From 20ae64706abb14947dec3e037de52c738f2fdbc9 Mon Sep 17 00:00:00 2001 From: Benjamin Dalsass Date: Thu, 24 Aug 2023 14:29:31 +0200 Subject: [PATCH] poc form SDK (extends to form) --- css/DI/app.css | 86 + js/DI/app.js | 48 + js/DI/collection.js | 158 + js/DI/form.js | 129 +- js/DI/toolkit.js | 69 + js/DI/widget.js | 56 + js/DI/{ => widget}/text_widget.js | 8 +- lib/.gitignore | 33 - lib/.htaccess | 24 - lib/apereo/phpcas/.codecov.yml | 17 - lib/apereo/phpcas/.gitattributes | 7 - lib/apereo/phpcas/.github/dependabot.yml | 7 - lib/apereo/phpcas/.github/workflows/test.yml | 43 - lib/apereo/phpcas/CAS.php | 32 - lib/apereo/phpcas/LICENSE | 201 - lib/apereo/phpcas/NOTICE | 81 - lib/apereo/phpcas/README.md | 35 - lib/apereo/phpcas/composer.json | 55 - lib/apereo/phpcas/phpunit.xml.dist | 13 - lib/apereo/phpcas/source/CAS.php | 2083 -- .../source/CAS/AuthenticationException.php | 115 - lib/apereo/phpcas/source/CAS/Autoload.php | 95 - lib/apereo/phpcas/source/CAS/Client.php | 4380 --- lib/apereo/phpcas/source/CAS/CookieJar.php | 385 - lib/apereo/phpcas/source/CAS/Exception.php | 59 - .../CAS/GracefullTerminationException.php | 86 - .../source/CAS/InvalidArgumentException.php | 46 - .../phpcas/source/CAS/Languages/Catalan.php | 114 - .../CAS/Languages/ChineseSimplified.php | 114 - .../phpcas/source/CAS/Languages/English.php | 114 - .../phpcas/source/CAS/Languages/French.php | 116 - .../phpcas/source/CAS/Languages/Galego.php | 117 - .../phpcas/source/CAS/Languages/German.php | 116 - .../phpcas/source/CAS/Languages/Greek.php | 115 - .../phpcas/source/CAS/Languages/Japanese.php | 113 - .../CAS/Languages/LanguageInterface.php | 96 - .../source/CAS/Languages/Portuguese.php | 114 - .../phpcas/source/CAS/Languages/Spanish.php | 117 - ...uenceBeforeAuthenticationCallException.php | 56 - .../OutOfSequenceBeforeClientException.php | 58 - .../CAS/OutOfSequenceBeforeProxyException.php | 59 - .../source/CAS/OutOfSequenceException.php | 49 - .../source/CAS/PGTStorage/AbstractStorage.php | 222 - .../phpcas/source/CAS/PGTStorage/Db.php | 440 - .../phpcas/source/CAS/PGTStorage/File.php | 261 - .../phpcas/source/CAS/ProxiedService.php | 72 - .../source/CAS/ProxiedService/Abstract.php | 149 - .../source/CAS/ProxiedService/Exception.php | 46 - .../phpcas/source/CAS/ProxiedService/Http.php | 91 - .../CAS/ProxiedService/Http/Abstract.php | 360 - .../source/CAS/ProxiedService/Http/Get.php | 85 - .../source/CAS/ProxiedService/Http/Post.php | 152 - .../phpcas/source/CAS/ProxiedService/Imap.php | 281 - .../source/CAS/ProxiedService/Testable.php | 75 - lib/apereo/phpcas/source/CAS/ProxyChain.php | 127 - .../source/CAS/ProxyChain/AllowedList.php | 119 - .../phpcas/source/CAS/ProxyChain/Any.php | 64 - .../source/CAS/ProxyChain/Interface.php | 53 - .../phpcas/source/CAS/ProxyChain/Trusted.php | 59 - .../source/CAS/ProxyTicketException.php | 71 - .../source/CAS/Request/AbstractRequest.php | 380 - .../source/CAS/Request/CurlMultiRequest.php | 147 - .../phpcas/source/CAS/Request/CurlRequest.php | 198 - .../phpcas/source/CAS/Request/Exception.php | 45 - .../CAS/Request/MultiRequestInterface.php | 83 - .../source/CAS/Request/RequestInterface.php | 179 - .../phpcas/source/CAS/Session/PhpSession.php | 45 - .../source/CAS/TypeMismatchException.php | 70 - lib/autoload.php | 7 - lib/bin/generate-deps-for-config-factory | 97 - lib/bin/generate-deps-for-config-factory.bat | 4 - lib/bin/generate-factory-for-class | 97 - lib/bin/generate-factory-for-class.bat | 4 - lib/bin/patch-type-declarations | 97 - lib/bin/patch-type-declarations.bat | 4 - lib/bin/php-parse | 120 - lib/bin/php-parse.bat | 5 - lib/bin/pscss | 97 - lib/bin/pscss.bat | 4 - lib/bin/var-dump-server | 97 - lib/bin/var-dump-server.bat | 4 - lib/bin/yaml-lint | 97 - lib/bin/yaml-lint.bat | 4 - lib/combodo/tcpdf/CHANGELOG.TXT | 3074 -- lib/combodo/tcpdf/LICENSE.TXT | 860 - lib/combodo/tcpdf/README.md | 84 - lib/combodo/tcpdf/VERSION | 1 - lib/combodo/tcpdf/composer.json | 54 - lib/combodo/tcpdf/config/tcpdf_config.php | 227 - lib/combodo/tcpdf/fonts/courier.php | 12 - lib/combodo/tcpdf/fonts/courierb.php | 12 - lib/combodo/tcpdf/fonts/courierbi.php | 12 - lib/combodo/tcpdf/fonts/courieri.php | 12 - lib/combodo/tcpdf/fonts/dejavusans.ctg.z | Bin 10454 -> 0 bytes lib/combodo/tcpdf/fonts/dejavusans.php | 16 - lib/combodo/tcpdf/fonts/dejavusans.z | Bin 375806 -> 0 bytes lib/combodo/tcpdf/fonts/dejavusansb.ctg.z | Bin 10200 -> 0 bytes lib/combodo/tcpdf/fonts/dejavusansb.php | 16 - lib/combodo/tcpdf/fonts/dejavusansb.z | Bin 347269 -> 0 bytes lib/combodo/tcpdf/fonts/dejavusansbi.ctg.z | Bin 9101 -> 0 bytes lib/combodo/tcpdf/fonts/dejavusansbi.php | 16 - lib/combodo/tcpdf/fonts/dejavusansbi.z | Bin 326692 -> 0 bytes .../tcpdf/fonts/dejavusanscondensed.ctg.z | Bin 10454 -> 0 bytes .../tcpdf/fonts/dejavusanscondensed.php | 16 - lib/combodo/tcpdf/fonts/dejavusanscondensed.z | Bin 330293 -> 0 bytes .../tcpdf/fonts/dejavusanscondensedb.ctg.z | Bin 10200 -> 0 bytes .../tcpdf/fonts/dejavusanscondensedb.php | 16 - .../tcpdf/fonts/dejavusanscondensedb.z | Bin 326753 -> 0 bytes .../tcpdf/fonts/dejavusanscondensedbi.ctg.z | Bin 9101 -> 0 bytes .../tcpdf/fonts/dejavusanscondensedbi.php | 16 - .../tcpdf/fonts/dejavusanscondensedbi.z | Bin 312796 -> 0 bytes .../tcpdf/fonts/dejavusanscondensedi.ctg.z | Bin 9343 -> 0 bytes .../tcpdf/fonts/dejavusanscondensedi.php | 16 - .../tcpdf/fonts/dejavusanscondensedi.z | Bin 308709 -> 0 bytes .../tcpdf/fonts/dejavusansextralight.ctg.z | Bin 3989 -> 0 bytes .../tcpdf/fonts/dejavusansextralight.php | 16 - .../tcpdf/fonts/dejavusansextralight.z | Bin 173046 -> 0 bytes lib/combodo/tcpdf/fonts/dejavusansi.ctg.z | Bin 9343 -> 0 bytes lib/combodo/tcpdf/fonts/dejavusansi.php | 16 - lib/combodo/tcpdf/fonts/dejavusansi.z | Bin 326859 -> 0 bytes lib/combodo/tcpdf/fonts/dejavusansmono.ctg.z | Bin 6361 -> 0 bytes lib/combodo/tcpdf/fonts/dejavusansmono.php | 16 - lib/combodo/tcpdf/fonts/dejavusansmono.z | Bin 198919 -> 0 bytes lib/combodo/tcpdf/fonts/dejavusansmonob.ctg.z | Bin 6120 -> 0 bytes lib/combodo/tcpdf/fonts/dejavusansmonob.php | 16 - lib/combodo/tcpdf/fonts/dejavusansmonob.z | Bin 193788 -> 0 bytes .../tcpdf/fonts/dejavusansmonobi.ctg.z | Bin 4983 -> 0 bytes lib/combodo/tcpdf/fonts/dejavusansmonobi.php | 16 - lib/combodo/tcpdf/fonts/dejavusansmonobi.z | Bin 145530 -> 0 bytes lib/combodo/tcpdf/fonts/dejavusansmonoi.ctg.z | Bin 5221 -> 0 bytes lib/combodo/tcpdf/fonts/dejavusansmonoi.php | 16 - lib/combodo/tcpdf/fonts/dejavusansmonoi.z | Bin 147290 -> 0 bytes .../tcpdf/fonts/droidsansfallback.ctg.z | Bin 58024 -> 0 bytes lib/combodo/tcpdf/fonts/droidsansfallback.php | 2975 -- lib/combodo/tcpdf/fonts/droidsansfallback.z | Bin 1500903 -> 0 bytes lib/combodo/tcpdf/fonts/helvetica.php | 13 - lib/combodo/tcpdf/fonts/helveticab.php | 12 - lib/combodo/tcpdf/fonts/helveticabi.php | 12 - lib/combodo/tcpdf/fonts/helveticai.php | 12 - lib/combodo/tcpdf/fonts/symbol.php | 12 - lib/combodo/tcpdf/fonts/times.php | 12 - lib/combodo/tcpdf/fonts/timesb.php | 12 - lib/combodo/tcpdf/fonts/timesbi.php | 12 - lib/combodo/tcpdf/fonts/timesi.php | 12 - lib/combodo/tcpdf/fonts/zapfdingbats.php | 12 - .../tcpdf/include/barcodes/datamatrix.php | 1176 - lib/combodo/tcpdf/include/barcodes/pdf417.php | 996 - lib/combodo/tcpdf/include/barcodes/qrcode.php | 2842 -- lib/combodo/tcpdf/include/sRGB.icc | Bin 6922 -> 0 bytes lib/combodo/tcpdf/include/tcpdf_colors.php | 462 - lib/combodo/tcpdf/include/tcpdf_filters.php | 481 - lib/combodo/tcpdf/include/tcpdf_font_data.php | 18447 ------------ lib/combodo/tcpdf/include/tcpdf_fonts.php | 2656 -- lib/combodo/tcpdf/include/tcpdf_images.php | 359 - lib/combodo/tcpdf/include/tcpdf_static.php | 2669 -- lib/combodo/tcpdf/tcpdf.php | 24729 ---------------- lib/combodo/tcpdf/tcpdf_autoconfig.php | 241 - lib/combodo/tcpdf/tcpdf_barcodes_1d.php | 2356 -- lib/combodo/tcpdf/tcpdf_barcodes_2d.php | 349 - lib/combodo/tcpdf/tcpdf_import.php | 104 - lib/combodo/tcpdf/tcpdf_parser.php | 815 - lib/composer/ClassLoader.php | 572 - lib/composer/InstalledVersions.php | 350 - lib/composer/LICENSE | 21 - lib/composer/autoload_classmap.php | 3378 --- lib/composer/autoload_files.php | 25 - lib/composer/autoload_namespaces.php | 12 - lib/composer/autoload_psr4.php | 77 - lib/composer/autoload_real.php | 70 - lib/composer/autoload_static.php | 3804 --- lib/composer/include_paths.php | 13 - lib/composer/installed.json | 6216 ---- lib/composer/installed.php | 819 - lib/composer/platform_check.php | 43 - lib/doctrine/annotations/LICENSE | 19 - lib/doctrine/annotations/README.md | 24 - lib/doctrine/annotations/UPGRADE.md | 18 - lib/doctrine/annotations/composer.json | 72 - .../annotations/docs/en/annotations.rst | 189 - lib/doctrine/annotations/docs/en/custom.rst | 443 - lib/doctrine/annotations/docs/en/index.rst | 102 - lib/doctrine/annotations/docs/en/sidebar.rst | 6 - .../Common/Annotations/Annotation.php | 54 - .../Annotations/Annotation/Attribute.php | 21 - .../Annotations/Annotation/Attributes.php | 15 - .../Common/Annotations/Annotation/Enum.php | 69 - .../Annotation/IgnoreAnnotation.php | 43 - .../Annotation/NamedArgumentConstructor.php | 13 - .../Annotations/Annotation/Required.php | 13 - .../Common/Annotations/Annotation/Target.php | 101 - .../Annotations/AnnotationException.php | 158 - .../Common/Annotations/AnnotationReader.php | 385 - .../Common/Annotations/AnnotationRegistry.php | 43 - .../Doctrine/Common/Annotations/DocLexer.php | 131 - .../Doctrine/Common/Annotations/DocParser.php | 1494 - .../ImplicitlyIgnoredAnnotationNames.php | 178 - .../Common/Annotations/IndexedReader.php | 99 - .../Doctrine/Common/Annotations/PhpParser.php | 78 - .../Common/Annotations/PsrCachedReader.php | 232 - .../Doctrine/Common/Annotations/Reader.php | 80 - .../Common/Annotations/TokenParser.php | 205 - lib/doctrine/annotations/psalm.xml | 15 - lib/doctrine/cache/LICENSE | 19 - lib/doctrine/cache/README.md | 13 - lib/doctrine/cache/UPGRADE-1.11.md | 27 - lib/doctrine/cache/UPGRADE-1.4.md | 16 - lib/doctrine/cache/composer.json | 50 - .../cache/lib/Doctrine/Common/Cache/Cache.php | 90 - .../Doctrine/Common/Cache/CacheProvider.php | 325 - .../Doctrine/Common/Cache/ClearableCache.php | 21 - .../Doctrine/Common/Cache/FlushableCache.php | 18 - .../Common/Cache/MultiDeleteCache.php | 22 - .../Doctrine/Common/Cache/MultiGetCache.php | 23 - .../Common/Cache/MultiOperationCache.php | 12 - .../Doctrine/Common/Cache/MultiPutCache.php | 24 - .../Common/Cache/Psr6/CacheAdapter.php | 340 - .../Doctrine/Common/Cache/Psr6/CacheItem.php | 118 - .../Common/Cache/Psr6/DoctrineProvider.php | 135 - .../Common/Cache/Psr6/InvalidArgument.php | 13 - .../Common/Cache/Psr6/TypedCacheItem.php | 99 - lib/doctrine/deprecations/LICENSE | 19 - lib/doctrine/deprecations/README.md | 157 - lib/doctrine/deprecations/composer.json | 38 - .../lib/Doctrine/Deprecations/Deprecation.php | 312 - .../PHPUnit/VerifyDeprecations.php | 66 - lib/doctrine/deprecations/phpcs.xml | 22 - lib/doctrine/deprecations/phpstan.neon | 9 - lib/doctrine/deprecations/psalm.xml | 30 - lib/doctrine/lexer/LICENSE | 19 - lib/doctrine/lexer/README.md | 9 - lib/doctrine/lexer/UPGRADE.md | 14 - lib/doctrine/lexer/composer.json | 56 - lib/doctrine/lexer/src/AbstractLexer.php | 346 - lib/doctrine/lexer/src/Token.php | 145 - lib/firebase/php-jwt/CHANGELOG.md | 105 - lib/firebase/php-jwt/LICENSE | 30 - lib/firebase/php-jwt/README.md | 332 - lib/firebase/php-jwt/composer.json | 42 - .../php-jwt/src/BeforeValidException.php | 7 - lib/firebase/php-jwt/src/CachedKeySet.php | 258 - lib/firebase/php-jwt/src/ExpiredException.php | 7 - lib/firebase/php-jwt/src/JWK.php | 323 - lib/firebase/php-jwt/src/JWT.php | 638 - lib/firebase/php-jwt/src/Key.php | 64 - .../php-jwt/src/SignatureInvalidException.php | 7 - lib/guzzlehttp/guzzle/CHANGELOG.md | 1609 - lib/guzzlehttp/guzzle/LICENSE | 27 - lib/guzzlehttp/guzzle/README.md | 94 - lib/guzzlehttp/guzzle/UPGRADING.md | 1253 - lib/guzzlehttp/guzzle/composer.json | 103 - lib/guzzlehttp/guzzle/src/BodySummarizer.php | 28 - .../guzzle/src/BodySummarizerInterface.php | 13 - lib/guzzlehttp/guzzle/src/Client.php | 483 - lib/guzzlehttp/guzzle/src/ClientInterface.php | 84 - lib/guzzlehttp/guzzle/src/ClientTrait.php | 241 - .../guzzle/src/Cookie/CookieJar.php | 319 - .../guzzle/src/Cookie/CookieJarInterface.php | 79 - .../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 | 630 - .../src/Handler/CurlFactoryInterface.php | 25 - .../guzzle/src/Handler/CurlHandler.php | 49 - .../guzzle/src/Handler/CurlMultiHandler.php | 263 - .../guzzle/src/Handler/EasyHandle.php | 112 - .../guzzle/src/Handler/HeaderProcessor.php | 42 - .../guzzle/src/Handler/MockHandler.php | 212 - lib/guzzlehttp/guzzle/src/Handler/Proxy.php | 51 - .../guzzle/src/Handler/StreamHandler.php | 615 - lib/guzzlehttp/guzzle/src/HandlerStack.php | 275 - .../guzzle/src/MessageFormatter.php | 199 - .../guzzle/src/MessageFormatterInterface.php | 18 - lib/guzzlehttp/guzzle/src/Middleware.php | 268 - lib/guzzlehttp/guzzle/src/Pool.php | 125 - .../guzzle/src/PrepareBodyMiddleware.php | 105 - .../guzzle/src/RedirectMiddleware.php | 228 - lib/guzzlehttp/guzzle/src/RequestOptions.php | 276 - lib/guzzlehttp/guzzle/src/RetryMiddleware.php | 119 - lib/guzzlehttp/guzzle/src/TransferStats.php | 133 - lib/guzzlehttp/guzzle/src/Utils.php | 385 - lib/guzzlehttp/guzzle/src/functions.php | 167 - .../guzzle/src/functions_include.php | 6 - lib/guzzlehttp/promises/CHANGELOG.md | 138 - lib/guzzlehttp/promises/LICENSE | 24 - lib/guzzlehttp/promises/README.md | 559 - lib/guzzlehttp/promises/composer.json | 58 - .../promises/src/AggregateException.php | 19 - .../promises/src/CancellationException.php | 12 - lib/guzzlehttp/promises/src/Coroutine.php | 162 - lib/guzzlehttp/promises/src/Create.php | 79 - lib/guzzlehttp/promises/src/Each.php | 86 - lib/guzzlehttp/promises/src/EachPromise.php | 250 - .../promises/src/FulfilledPromise.php | 89 - lib/guzzlehttp/promises/src/Is.php | 40 - lib/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 - lib/guzzlehttp/promises/src/TaskQueue.php | 71 - .../promises/src/TaskQueueInterface.php | 24 - lib/guzzlehttp/promises/src/Utils.php | 259 - .../vendor-bin/php-cs-fixer/composer.json | 9 - .../promises/vendor-bin/phpstan/composer.json | 10 - .../promises/vendor-bin/psalm/composer.json | 9 - lib/guzzlehttp/psr7/CHANGELOG.md | 416 - lib/guzzlehttp/psr7/LICENSE | 26 - lib/guzzlehttp/psr7/README.md | 880 - lib/guzzlehttp/psr7/composer.json | 93 - lib/guzzlehttp/psr7/src/AppendStream.php | 248 - lib/guzzlehttp/psr7/src/BufferStream.php | 149 - lib/guzzlehttp/psr7/src/CachingStream.php | 153 - lib/guzzlehttp/psr7/src/DroppingStream.php | 49 - .../src/Exception/MalformedUriException.php | 14 - lib/guzzlehttp/psr7/src/FnStream.php | 180 - lib/guzzlehttp/psr7/src/Header.php | 134 - lib/guzzlehttp/psr7/src/HttpFactory.php | 100 - lib/guzzlehttp/psr7/src/InflateStream.php | 37 - lib/guzzlehttp/psr7/src/LazyOpenStream.php | 49 - lib/guzzlehttp/psr7/src/LimitStream.php | 157 - lib/guzzlehttp/psr7/src/Message.php | 246 - lib/guzzlehttp/psr7/src/MessageTrait.php | 263 - lib/guzzlehttp/psr7/src/MimeType.php | 1237 - lib/guzzlehttp/psr7/src/MultipartStream.php | 159 - lib/guzzlehttp/psr7/src/NoSeekStream.php | 28 - lib/guzzlehttp/psr7/src/PumpStream.php | 179 - lib/guzzlehttp/psr7/src/Query.php | 113 - lib/guzzlehttp/psr7/src/Request.php | 157 - lib/guzzlehttp/psr7/src/Response.php | 160 - lib/guzzlehttp/psr7/src/Rfc7230.php | 23 - lib/guzzlehttp/psr7/src/ServerRequest.php | 344 - lib/guzzlehttp/psr7/src/Stream.php | 282 - .../psr7/src/StreamDecoratorTrait.php | 155 - lib/guzzlehttp/psr7/src/StreamWrapper.php | 175 - lib/guzzlehttp/psr7/src/UploadedFile.php | 211 - lib/guzzlehttp/psr7/src/Uri.php | 740 - lib/guzzlehttp/psr7/src/UriComparator.php | 52 - lib/guzzlehttp/psr7/src/UriNormalizer.php | 220 - lib/guzzlehttp/psr7/src/UriResolver.php | 211 - lib/guzzlehttp/psr7/src/Utils.php | 459 - lib/laminas/laminas-loader/.laminas-ci.json | 5 - lib/laminas/laminas-loader/COPYRIGHT.md | 1 - lib/laminas/laminas-loader/LICENSE.md | 26 - lib/laminas/laminas-loader/README.md | 13 - lib/laminas/laminas-loader/composer.json | 51 - lib/laminas/laminas-loader/composer.lock | 2460 -- lib/laminas/laminas-loader/phpcs.xml.dist | 32 - .../laminas-loader/src/AutoloaderFactory.php | 212 - .../laminas-loader/src/ClassMapAutoloader.php | 234 - .../src/Exception/BadMethodCallException.php | 10 - .../src/Exception/DomainException.php | 9 - .../src/Exception/ExceptionInterface.php | 7 - .../Exception/InvalidArgumentException.php | 9 - .../src/Exception/InvalidPathException.php | 11 - .../MissingResourceNamespaceException.php | 11 - .../src/Exception/PluginLoaderException.php | 12 - .../src/Exception/RuntimeException.php | 9 - .../src/Exception/SecurityException.php | 9 - .../laminas-loader/src/ModuleAutoloader.php | 445 - .../laminas-loader/src/PluginClassLoader.php | 223 - .../laminas-loader/src/PluginClassLocator.php | 36 - .../laminas-loader/src/ShortNameLocator.php | 33 - .../laminas-loader/src/SplAutoloader.php | 60 - .../laminas-loader/src/StandardAutoloader.php | 332 - lib/laminas/laminas-mail/.laminas-ci.json | 5 - .../laminas-mail/.laminas-ci/pre-run.sh | 14 - lib/laminas/laminas-mail/COPYRIGHT.md | 1 - lib/laminas/laminas-mail/LICENSE.md | 26 - lib/laminas/laminas-mail/README.md | 12 - lib/laminas/laminas-mail/composer.json | 83 - lib/laminas/laminas-mail/composer.lock | 4882 --- lib/laminas/laminas-mail/src/Address.php | 162 - .../src/Address/AddressInterface.php | 27 - lib/laminas/laminas-mail/src/AddressList.php | 238 - .../laminas-mail/src/ConfigProvider.php | 36 - .../src/Exception/BadMethodCallException.php | 11 - .../src/Exception/DomainException.php | 10 - .../src/Exception/ExceptionInterface.php | 7 - .../Exception/InvalidArgumentException.php | 11 - .../src/Exception/OutOfBoundsException.php | 10 - .../src/Exception/RuntimeException.php | 10 - .../src/Header/AbstractAddressList.php | 276 - lib/laminas/laminas-mail/src/Header/Bcc.php | 16 - lib/laminas/laminas-mail/src/Header/Cc.php | 9 - .../src/Header/ContentDisposition.php | 315 - .../src/Header/ContentTransferEncoding.php | 108 - .../laminas-mail/src/Header/ContentType.php | 197 - lib/laminas/laminas-mail/src/Header/Date.php | 63 - .../Exception/BadMethodCallException.php | 9 - .../Header/Exception/ExceptionInterface.php | 9 - .../Exception/InvalidArgumentException.php | 9 - .../src/Header/Exception/RuntimeException.php | 9 - lib/laminas/laminas-mail/src/Header/From.php | 9 - .../laminas-mail/src/Header/GenericHeader.php | 195 - .../src/Header/GenericMultiHeader.php | 49 - .../src/Header/HeaderInterface.php | 69 - .../laminas-mail/src/Header/HeaderLoader.php | 43 - .../laminas-mail/src/Header/HeaderLocator.php | 69 - .../src/Header/HeaderLocatorInterface.php | 19 - .../laminas-mail/src/Header/HeaderName.php | 67 - .../laminas-mail/src/Header/HeaderValue.php | 110 - .../laminas-mail/src/Header/HeaderWrap.php | 155 - .../src/Header/IdentificationField.php | 137 - .../laminas-mail/src/Header/InReplyTo.php | 9 - .../laminas-mail/src/Header/ListParser.php | 93 - .../laminas-mail/src/Header/MessageId.php | 113 - .../laminas-mail/src/Header/MimeVersion.php | 81 - .../src/Header/MultipleHeadersInterface.php | 8 - .../laminas-mail/src/Header/Received.php | 86 - .../laminas-mail/src/Header/References.php | 9 - .../laminas-mail/src/Header/ReplyTo.php | 9 - .../laminas-mail/src/Header/Sender.php | 147 - .../src/Header/StructuredInterface.php | 13 - .../laminas-mail/src/Header/Subject.php | 113 - lib/laminas/laminas-mail/src/Header/To.php | 9 - .../src/Header/UnstructuredInterface.php | 10 - lib/laminas/laminas-mail/src/Headers.php | 607 - lib/laminas/laminas-mail/src/Message.php | 576 - .../laminas-mail/src/MessageFactory.php | 58 - lib/laminas/laminas-mail/src/Module.php | 19 - .../src/Protocol/AbstractProtocol.php | 344 - .../Protocol/Exception/ExceptionInterface.php | 9 - .../Exception/InvalidArgumentException.php | 12 - .../Protocol/Exception/RuntimeException.php | 12 - .../laminas-mail/src/Protocol/Imap.php | 819 - .../laminas-mail/src/Protocol/Pop3.php | 389 - .../src/Protocol/ProtocolTrait.php | 112 - .../laminas-mail/src/Protocol/Smtp.php | 514 - .../src/Protocol/Smtp/Auth/Crammd5.php | 132 - .../src/Protocol/Smtp/Auth/Login.php | 120 - .../src/Protocol/Smtp/Auth/Plain.php | 118 - .../src/Protocol/SmtpPluginManager.php | 108 - .../src/Protocol/SmtpPluginManagerFactory.php | 48 - lib/laminas/laminas-mail/src/Storage.php | 17 - .../src/Storage/AbstractStorage.php | 325 - .../Storage/Exception/ExceptionInterface.php | 9 - .../Exception/InvalidArgumentException.php | 12 - .../Exception/OutOfBoundsException.php | 12 - .../Storage/Exception/RuntimeException.php | 12 - .../laminas-mail/src/Storage/Folder.php | 211 - .../src/Storage/Folder/FolderInterface.php | 32 - .../src/Storage/Folder/Maildir.php | 223 - .../laminas-mail/src/Storage/Folder/Mbox.php | 219 - lib/laminas/laminas-mail/src/Storage/Imap.php | 553 - .../laminas-mail/src/Storage/Maildir.php | 430 - lib/laminas/laminas-mail/src/Storage/Mbox.php | 410 - .../laminas-mail/src/Storage/Message.php | 80 - .../laminas-mail/src/Storage/Message/File.php | 64 - .../src/Storage/Message/MessageInterface.php | 28 - .../src/Storage/ParamsNormalizer.php | 37 - lib/laminas/laminas-mail/src/Storage/Part.php | 474 - .../Part/Exception/ExceptionInterface.php | 9 - .../Exception/InvalidArgumentException.php | 12 - .../Part/Exception/RuntimeException.php | 12 - .../laminas-mail/src/Storage/Part/File.php | 154 - .../src/Storage/Part/PartInterface.php | 117 - lib/laminas/laminas-mail/src/Storage/Pop3.php | 288 - .../src/Storage/Writable/Maildir.php | 957 - .../Storage/Writable/WritableInterface.php | 86 - .../laminas-mail/src/Transport/Envelope.php | 58 - .../Transport/Exception/DomainException.php | 12 - .../Exception/ExceptionInterface.php | 9 - .../Exception/InvalidArgumentException.php | 12 - .../Transport/Exception/RuntimeException.php | 12 - .../laminas-mail/src/Transport/Factory.php | 79 - .../laminas-mail/src/Transport/File.php | 90 - .../src/Transport/FileOptions.php | 89 - .../laminas-mail/src/Transport/InMemory.php | 40 - .../laminas-mail/src/Transport/Sendmail.php | 330 - .../laminas-mail/src/Transport/Smtp.php | 400 - .../src/Transport/SmtpOptions.php | 203 - .../src/Transport/TransportInterface.php | 19 - lib/laminas/laminas-mime/.laminas-ci.json | 5 - lib/laminas/laminas-mime/COPYRIGHT.md | 1 - lib/laminas/laminas-mime/LICENSE.md | 26 - lib/laminas/laminas-mime/README.md | 32 - lib/laminas/laminas-mime/composer.json | 59 - lib/laminas/laminas-mime/composer.lock | 3023 -- lib/laminas/laminas-mime/phpcs.xml.dist | 21 - lib/laminas/laminas-mime/src/Decode.php | 240 - .../src/Exception/ExceptionInterface.php | 7 - .../Exception/InvalidArgumentException.php | 8 - .../src/Exception/RuntimeException.php | 10 - lib/laminas/laminas-mime/src/Message.php | 321 - lib/laminas/laminas-mime/src/Mime.php | 709 - lib/laminas/laminas-mime/src/Part.php | 549 - .../laminas-servicemanager/COPYRIGHT.md | 1 - lib/laminas/laminas-servicemanager/LICENSE.md | 26 - lib/laminas/laminas-servicemanager/README.md | 40 - .../bin/generate-deps-for-config-factory | 22 - .../bin/generate-factory-for-class | 22 - .../laminas-servicemanager/composer.json | 98 - .../laminas-servicemanager/composer.lock | 5437 ---- .../AbstractFactory/ConfigAbstractFactory.php | 80 - .../ReflectionBasedAbstractFactory.php | 247 - .../src/AbstractFactoryInterface.php | 53 - .../src/AbstractPluginManager.php | 222 - .../laminas-servicemanager/src/Config.php | 102 - .../src/ConfigInterface.php | 90 - .../src/DelegatorFactoryInterface.php | 41 - ...tainerModificationsNotAllowedException.php | 25 - .../src/Exception/CyclicAliasException.php | 152 - .../src/Exception/ExceptionInterface.php | 14 - .../Exception/InvalidArgumentException.php | 46 - .../src/Exception/InvalidServiceException.php | 15 - .../Exception/ServiceNotCreatedException.php | 16 - .../Exception/ServiceNotFoundException.php | 18 - .../src/Factory/AbstractFactoryInterface.php | 28 - .../src/Factory/DelegatorFactoryInterface.php | 34 - .../src/Factory/FactoryInterface.php | 33 - .../src/Factory/InvokableFactory.php | 29 - .../src/FactoryInterface.php | 36 - .../src/Initializer/InitializerInterface.php | 24 - .../src/InitializerInterface.php | 36 - .../src/PluginManagerInterface.php | 30 - .../src/Proxy/LazyServiceFactory.php | 62 - .../src/ServiceLocatorInterface.php | 30 - .../src/ServiceManager.php | 983 - .../src/Tool/ConfigDumper.php | 263 - .../src/Tool/ConfigDumperCommand.php | 248 - .../src/Tool/FactoryCreator.php | 164 - .../src/Tool/FactoryCreatorCommand.php | 154 - .../laminas-servicemanager/src/autoload.php | 21 - lib/laminas/laminas-stdlib/COPYRIGHT.md | 1 - lib/laminas/laminas-stdlib/LICENSE.md | 26 - lib/laminas/laminas-stdlib/README.md | 45 - lib/laminas/laminas-stdlib/composer.json | 65 - lib/laminas/laminas-stdlib/composer.lock | 4852 --- .../laminas-stdlib/src/AbstractOptions.php | 194 - .../laminas-stdlib/src/ArrayObject.php | 505 - .../src/ArraySerializableInterface.php | 23 - lib/laminas/laminas-stdlib/src/ArrayStack.php | 32 - lib/laminas/laminas-stdlib/src/ArrayUtils.php | 338 - .../src/ArrayUtils/MergeRemoveKey.php | 9 - .../src/ArrayUtils/MergeReplaceKey.php | 27 - .../ArrayUtils/MergeReplaceKeyInterface.php | 16 - .../laminas-stdlib/src/ConsoleHelper.php | 162 - .../src/DispatchableInterface.php | 15 - .../laminas-stdlib/src/ErrorHandler.php | 119 - .../src/Exception/BadMethodCallException.php | 12 - .../src/Exception/DomainException.php | 12 - .../src/Exception/ExceptionInterface.php | 12 - .../Exception/ExtensionNotLoadedException.php | 12 - .../Exception/InvalidArgumentException.php | 12 - .../src/Exception/LogicException.php | 12 - .../src/Exception/RuntimeException.php | 12 - .../laminas-stdlib/src/FastPriorityQueue.php | 406 - lib/laminas/laminas-stdlib/src/Glob.php | 226 - .../src/Guard/AllGuardsTrait.php | 15 - .../Guard/ArrayOrTraversableGuardTrait.php | 45 - .../src/Guard/EmptyGuardTrait.php | 36 - .../src/Guard/NullGuardTrait.php | 36 - .../src/InitializableInterface.php | 18 - .../laminas-stdlib/src/JsonSerializable.php | 13 - lib/laminas/laminas-stdlib/src/Message.php | 117 - .../laminas-stdlib/src/MessageInterface.php | 41 - .../src/ParameterObjectInterface.php | 33 - lib/laminas/laminas-stdlib/src/Parameters.php | 116 - .../src/ParametersInterface.php | 81 - .../laminas-stdlib/src/PriorityList.php | 283 - .../laminas-stdlib/src/PriorityQueue.php | 385 - lib/laminas/laminas-stdlib/src/Request.php | 10 - .../laminas-stdlib/src/RequestInterface.php | 9 - lib/laminas/laminas-stdlib/src/Response.php | 10 - .../laminas-stdlib/src/ResponseInterface.php | 9 - .../laminas-stdlib/src/SplPriorityQueue.php | 156 - lib/laminas/laminas-stdlib/src/SplQueue.php | 94 - lib/laminas/laminas-stdlib/src/SplStack.php | 93 - .../laminas-stdlib/src/StringUtils.php | 213 - .../StringWrapper/AbstractStringWrapper.php | 278 - .../src/StringWrapper/Iconv.php | 302 - .../laminas-stdlib/src/StringWrapper/Intl.php | 89 - .../src/StringWrapper/MbString.php | 127 - .../src/StringWrapper/Native.php | 135 - .../StringWrapper/StringWrapperInterface.php | 108 - lib/laminas/laminas-validator/COPYRIGHT.md | 1 - lib/laminas/laminas-validator/LICENSE.md | 26 - lib/laminas/laminas-validator/README.md | 41 - .../bin/update_hostname_validator.php | 196 - lib/laminas/laminas-validator/composer.json | 91 - lib/laminas/laminas-validator/composer.lock | 5217 ---- lib/laminas/laminas-validator/renovate.json | 6 - .../src/AbstractValidator.php | 623 - lib/laminas/laminas-validator/src/Barcode.php | 199 - .../src/Barcode/AbstractAdapter.php | 312 - .../src/Barcode/AdapterInterface.php | 59 - .../laminas-validator/src/Barcode/Codabar.php | 66 - .../laminas-validator/src/Barcode/Code128.php | 739 - .../laminas-validator/src/Barcode/Code25.php | 17 - .../src/Barcode/Code25interleaved.php | 19 - .../laminas-validator/src/Barcode/Code39.php | 90 - .../src/Barcode/Code39ext.php | 16 - .../laminas-validator/src/Barcode/Code93.php | 119 - .../src/Barcode/Code93ext.php | 16 - .../laminas-validator/src/Barcode/Ean12.php | 16 - .../laminas-validator/src/Barcode/Ean13.php | 16 - .../laminas-validator/src/Barcode/Ean14.php | 16 - .../laminas-validator/src/Barcode/Ean18.php | 16 - .../laminas-validator/src/Barcode/Ean2.php | 16 - .../laminas-validator/src/Barcode/Ean5.php | 18 - .../laminas-validator/src/Barcode/Ean8.php | 35 - .../laminas-validator/src/Barcode/Gtin12.php | 16 - .../laminas-validator/src/Barcode/Gtin13.php | 16 - .../laminas-validator/src/Barcode/Gtin14.php | 16 - .../src/Barcode/Identcode.php | 37 - .../src/Barcode/Intelligentmail.php | 18 - .../laminas-validator/src/Barcode/Issn.php | 91 - .../laminas-validator/src/Barcode/Itf14.php | 16 - .../src/Barcode/Leitcode.php | 16 - .../laminas-validator/src/Barcode/Planet.php | 16 - .../laminas-validator/src/Barcode/Postnet.php | 16 - .../src/Barcode/Royalmail.php | 156 - .../laminas-validator/src/Barcode/Sscc.php | 16 - .../laminas-validator/src/Barcode/Upca.php | 16 - .../laminas-validator/src/Barcode/Upce.php | 35 - lib/laminas/laminas-validator/src/Between.php | 217 - lib/laminas/laminas-validator/src/Bitwise.php | 203 - .../src/BusinessIdentifierCode.php | 329 - .../laminas-validator/src/Callback.php | 150 - .../laminas-validator/src/ConfigProvider.php | 38 - .../laminas-validator/src/CreditCard.php | 436 - lib/laminas/laminas-validator/src/Csrf.php | 376 - lib/laminas/laminas-validator/src/Date.php | 232 - .../laminas-validator/src/DateStep.php | 525 - .../laminas-validator/src/Db/AbstractDb.php | 315 - .../src/Db/NoRecordExists.php | 36 - .../laminas-validator/src/Db/RecordExists.php | 36 - lib/laminas/laminas-validator/src/Digits.php | 66 - .../laminas-validator/src/EmailAddress.php | 617 - .../src/Exception/BadMethodCallException.php | 7 - .../src/Exception/ExceptionInterface.php | 7 - .../Exception/ExtensionNotLoadedException.php | 7 - .../Exception/InvalidArgumentException.php | 7 - .../InvalidMagicMimeFileException.php | 7 - .../src/Exception/RuntimeException.php | 7 - lib/laminas/laminas-validator/src/Explode.php | 204 - .../laminas-validator/src/File/Count.php | 257 - .../laminas-validator/src/File/Crc32.php | 110 - .../src/File/ExcludeExtension.php | 72 - .../src/File/ExcludeMimeType.php | 97 - .../laminas-validator/src/File/Exists.php | 183 - .../laminas-validator/src/File/Extension.php | 242 - .../src/File/FileInformationTrait.php | 164 - .../laminas-validator/src/File/FilesSize.php | 184 - .../laminas-validator/src/File/Hash.php | 177 - .../laminas-validator/src/File/ImageSize.php | 377 - .../src/File/IsCompressed.php | 84 - .../laminas-validator/src/File/IsImage.php | 110 - .../laminas-validator/src/File/Md5.php | 110 - .../laminas-validator/src/File/MimeType.php | 416 - .../laminas-validator/src/File/NotExists.php | 68 - .../laminas-validator/src/File/Sha1.php | 110 - .../laminas-validator/src/File/Size.php | 359 - .../laminas-validator/src/File/Upload.php | 270 - .../laminas-validator/src/File/UploadFile.php | 175 - .../laminas-validator/src/File/WordCount.php | 204 - .../laminas-validator/src/GpsPoint.php | 122 - .../laminas-validator/src/GreaterThan.php | 154 - lib/laminas/laminas-validator/src/Hex.php | 45 - .../laminas-validator/src/Hostname.php | 2293 -- .../laminas-validator/src/Hostname/Biz.php | 2897 -- .../laminas-validator/src/Hostname/Cn.php | 2179 -- .../laminas-validator/src/Hostname/Com.php | 176 - .../laminas-validator/src/Hostname/Jp.php | 719 - lib/laminas/laminas-validator/src/Iban.php | 364 - .../laminas-validator/src/Identical.php | 221 - lib/laminas/laminas-validator/src/InArray.php | 253 - lib/laminas/laminas-validator/src/Ip.php | 193 - .../laminas-validator/src/IsCountable.php | 203 - .../laminas-validator/src/IsInstanceOf.php | 103 - lib/laminas/laminas-validator/src/Isbn.php | 189 - .../laminas-validator/src/Isbn/Isbn10.php | 54 - .../laminas-validator/src/Isbn/Isbn13.php | 55 - .../laminas-validator/src/LessThan.php | 159 - lib/laminas/laminas-validator/src/Module.php | 43 - .../laminas-validator/src/NotEmpty.php | 306 - lib/laminas/laminas-validator/src/Regex.php | 137 - .../src/Sitemap/Changefreq.php | 72 - .../laminas-validator/src/Sitemap/Lastmod.php | 69 - .../laminas-validator/src/Sitemap/Loc.php | 58 - .../src/Sitemap/Priority.php | 56 - .../laminas-validator/src/StaticValidator.php | 71 - lib/laminas/laminas-validator/src/Step.php | 176 - .../laminas-validator/src/StringLength.php | 233 - .../laminas-validator/src/Timezone.php | 173 - .../Translator/TranslatorAwareInterface.php | 62 - .../src/Translator/TranslatorInterface.php | 14 - .../src/UndisclosedPassword.php | 135 - lib/laminas/laminas-validator/src/Uri.php | 185 - lib/laminas/laminas-validator/src/Uuid.php | 58 - .../laminas-validator/src/ValidatorChain.php | 334 - .../src/ValidatorInterface.php | 39 - .../src/ValidatorPluginManager.php | 657 - .../ValidatorPluginManagerAwareInterface.php | 18 - .../src/ValidatorPluginManagerFactory.php | 85 - .../src/ValidatorProviderInterface.php | 24 - lib/league/oauth2-client/LICENSE | 21 - lib/league/oauth2-client/README.md | 58 - lib/league/oauth2-client/composer.json | 58 - .../oauth2-client/src/Grant/AbstractGrant.php | 80 - .../src/Grant/AuthorizationCode.php | 41 - .../src/Grant/ClientCredentials.php | 39 - .../Grant/Exception/InvalidGrantException.php | 26 - .../oauth2-client/src/Grant/GrantFactory.php | 104 - .../oauth2-client/src/Grant/Password.php | 42 - .../oauth2-client/src/Grant/RefreshToken.php | 41 - .../HttpBasicAuthOptionProvider.php | 42 - .../OptionProviderInterface.php | 30 - .../OptionProvider/PostAuthOptionProvider.php | 51 - .../src/Provider/AbstractProvider.php | 843 - .../Exception/IdentityProviderException.php | 48 - .../src/Provider/GenericProvider.php | 233 - .../src/Provider/GenericResourceOwner.php | 61 - .../src/Provider/ResourceOwnerInterface.php | 36 - .../oauth2-client/src/Token/AccessToken.php | 243 - .../src/Token/AccessTokenInterface.php | 74 - .../ResourceOwnerAccessTokenInterface.php | 25 - .../src/Tool/ArrayAccessorTrait.php | 52 - .../src/Tool/BearerAuthorizationTrait.php | 36 - .../src/Tool/GuardedPropertyTrait.php | 70 - .../src/Tool/MacAuthorizationTrait.php | 83 - .../src/Tool/ProviderRedirectTrait.php | 122 - .../src/Tool/QueryBuilderTrait.php | 33 - .../oauth2-client/src/Tool/RequestFactory.php | 87 - .../src/Tool/RequiredParameterTrait.php | 56 - lib/league/oauth2-google/CHANGELOG.md | 72 - lib/league/oauth2-google/CONTRIBUTING.md | 42 - lib/league/oauth2-google/LICENSE | 21 - lib/league/oauth2-google/README.md | 242 - lib/league/oauth2-google/composer.json | 44 - lib/league/oauth2-google/examples/index.php | 35 - .../oauth2-google/examples/provider.php | 24 - lib/league/oauth2-google/examples/reset.php | 7 - lib/league/oauth2-google/examples/server.sh | 3 - lib/league/oauth2-google/examples/user.php | 39 - lib/league/oauth2-google/phpunit.xml.dist | 28 - .../src/Exception/HostedDomainException.php | 15 - .../oauth2-google/src/Provider/Google.php | 152 - .../oauth2-google/src/Provider/GoogleUser.php | 112 - lib/nikic/php-parser/LICENSE | 29 - lib/nikic/php-parser/README.md | 225 - lib/nikic/php-parser/bin/php-parse | 205 - lib/nikic/php-parser/composer.json | 41 - lib/nikic/php-parser/grammar/README.md | 30 - lib/nikic/php-parser/grammar/parser.template | 106 - lib/nikic/php-parser/grammar/php5.y | 1036 - lib/nikic/php-parser/grammar/php7.y | 1204 - lib/nikic/php-parser/grammar/phpyLang.php | 184 - .../php-parser/grammar/rebuildParsers.php | 81 - lib/nikic/php-parser/grammar/tokens.template | 17 - lib/nikic/php-parser/grammar/tokens.y | 115 - .../php-parser/lib/PhpParser/Builder.php | 13 - .../lib/PhpParser/Builder/ClassConst.php | 132 - .../lib/PhpParser/Builder/Class_.php | 146 - .../lib/PhpParser/Builder/Declaration.php | 43 - .../lib/PhpParser/Builder/EnumCase.php | 85 - .../lib/PhpParser/Builder/Enum_.php | 117 - .../lib/PhpParser/Builder/FunctionLike.php | 73 - .../lib/PhpParser/Builder/Function_.php | 67 - .../lib/PhpParser/Builder/Interface_.php | 93 - .../lib/PhpParser/Builder/Method.php | 146 - .../lib/PhpParser/Builder/Namespace_.php | 45 - .../lib/PhpParser/Builder/Param.php | 122 - .../lib/PhpParser/Builder/Property.php | 161 - .../lib/PhpParser/Builder/TraitUse.php | 64 - .../PhpParser/Builder/TraitUseAdaptation.php | 148 - .../lib/PhpParser/Builder/Trait_.php | 78 - .../php-parser/lib/PhpParser/Builder/Use_.php | 49 - .../lib/PhpParser/BuilderFactory.php | 399 - .../lib/PhpParser/BuilderHelpers.php | 322 - .../php-parser/lib/PhpParser/Comment.php | 239 - .../php-parser/lib/PhpParser/Comment/Doc.php | 7 - .../ConstExprEvaluationException.php | 6 - .../lib/PhpParser/ConstExprEvaluator.php | 229 - lib/nikic/php-parser/lib/PhpParser/Error.php | 180 - .../php-parser/lib/PhpParser/ErrorHandler.php | 13 - .../lib/PhpParser/ErrorHandler/Collecting.php | 46 - .../lib/PhpParser/ErrorHandler/Throwing.php | 18 - .../lib/PhpParser/Internal/DiffElem.php | 27 - .../lib/PhpParser/Internal/Differ.php | 164 - .../Internal/PrintableNewAnonClassNode.php | 61 - .../lib/PhpParser/Internal/TokenStream.php | 281 - .../php-parser/lib/PhpParser/JsonDecoder.php | 103 - lib/nikic/php-parser/lib/PhpParser/Lexer.php | 560 - .../lib/PhpParser/Lexer/Emulative.php | 248 - .../Lexer/TokenEmulator/AttributeEmulator.php | 56 - .../CoaleseEqualTokenEmulator.php | 47 - .../Lexer/TokenEmulator/EnumTokenEmulator.php | 31 - .../TokenEmulator/ExplicitOctalEmulator.php | 44 - .../FlexibleDocStringEmulator.php | 76 - .../Lexer/TokenEmulator/FnTokenEmulator.php | 23 - .../Lexer/TokenEmulator/KeywordEmulator.php | 62 - .../TokenEmulator/MatchTokenEmulator.php | 23 - .../TokenEmulator/NullsafeTokenEmulator.php | 67 - .../NumericLiteralSeparatorEmulator.php | 105 - .../TokenEmulator/ReadonlyTokenEmulator.php | 23 - .../Lexer/TokenEmulator/ReverseEmulator.php | 36 - .../Lexer/TokenEmulator/TokenEmulator.php | 25 - .../php-parser/lib/PhpParser/NameContext.php | 285 - lib/nikic/php-parser/lib/PhpParser/Node.php | 151 - .../php-parser/lib/PhpParser/Node/Arg.php | 46 - .../lib/PhpParser/Node/Attribute.php | 34 - .../lib/PhpParser/Node/AttributeGroup.php | 29 - .../lib/PhpParser/Node/ComplexType.php | 14 - .../php-parser/lib/PhpParser/Node/Const_.php | 37 - .../php-parser/lib/PhpParser/Node/Expr.php | 9 - .../lib/PhpParser/Node/Expr/ArrayDimFetch.php | 34 - .../lib/PhpParser/Node/Expr/ArrayItem.php | 41 - .../lib/PhpParser/Node/Expr/Array_.php | 34 - .../lib/PhpParser/Node/Expr/ArrowFunction.php | 79 - .../lib/PhpParser/Node/Expr/Assign.php | 34 - .../lib/PhpParser/Node/Expr/AssignOp.php | 30 - .../Node/Expr/AssignOp/BitwiseAnd.php | 12 - .../Node/Expr/AssignOp/BitwiseOr.php | 12 - .../Node/Expr/AssignOp/BitwiseXor.php | 12 - .../PhpParser/Node/Expr/AssignOp/Coalesce.php | 12 - .../PhpParser/Node/Expr/AssignOp/Concat.php | 12 - .../lib/PhpParser/Node/Expr/AssignOp/Div.php | 12 - .../PhpParser/Node/Expr/AssignOp/Minus.php | 12 - .../lib/PhpParser/Node/Expr/AssignOp/Mod.php | 12 - .../lib/PhpParser/Node/Expr/AssignOp/Mul.php | 12 - .../lib/PhpParser/Node/Expr/AssignOp/Plus.php | 12 - .../lib/PhpParser/Node/Expr/AssignOp/Pow.php | 12 - .../Node/Expr/AssignOp/ShiftLeft.php | 12 - .../Node/Expr/AssignOp/ShiftRight.php | 12 - .../lib/PhpParser/Node/Expr/AssignRef.php | 34 - .../lib/PhpParser/Node/Expr/BinaryOp.php | 40 - .../Node/Expr/BinaryOp/BitwiseAnd.php | 16 - .../Node/Expr/BinaryOp/BitwiseOr.php | 16 - .../Node/Expr/BinaryOp/BitwiseXor.php | 16 - .../Node/Expr/BinaryOp/BooleanAnd.php | 16 - .../Node/Expr/BinaryOp/BooleanOr.php | 16 - .../PhpParser/Node/Expr/BinaryOp/Coalesce.php | 16 - .../PhpParser/Node/Expr/BinaryOp/Concat.php | 16 - .../lib/PhpParser/Node/Expr/BinaryOp/Div.php | 16 - .../PhpParser/Node/Expr/BinaryOp/Equal.php | 16 - .../PhpParser/Node/Expr/BinaryOp/Greater.php | 16 - .../Node/Expr/BinaryOp/GreaterOrEqual.php | 16 - .../Node/Expr/BinaryOp/Identical.php | 16 - .../Node/Expr/BinaryOp/LogicalAnd.php | 16 - .../Node/Expr/BinaryOp/LogicalOr.php | 16 - .../Node/Expr/BinaryOp/LogicalXor.php | 16 - .../PhpParser/Node/Expr/BinaryOp/Minus.php | 16 - .../lib/PhpParser/Node/Expr/BinaryOp/Mod.php | 16 - .../lib/PhpParser/Node/Expr/BinaryOp/Mul.php | 16 - .../PhpParser/Node/Expr/BinaryOp/NotEqual.php | 16 - .../Node/Expr/BinaryOp/NotIdentical.php | 16 - .../lib/PhpParser/Node/Expr/BinaryOp/Plus.php | 16 - .../lib/PhpParser/Node/Expr/BinaryOp/Pow.php | 16 - .../Node/Expr/BinaryOp/ShiftLeft.php | 16 - .../Node/Expr/BinaryOp/ShiftRight.php | 16 - .../PhpParser/Node/Expr/BinaryOp/Smaller.php | 16 - .../Node/Expr/BinaryOp/SmallerOrEqual.php | 16 - .../Node/Expr/BinaryOp/Spaceship.php | 16 - .../lib/PhpParser/Node/Expr/BitwiseNot.php | 30 - .../lib/PhpParser/Node/Expr/BooleanNot.php | 30 - .../lib/PhpParser/Node/Expr/CallLike.php | 39 - .../lib/PhpParser/Node/Expr/Cast.php | 26 - .../lib/PhpParser/Node/Expr/Cast/Array_.php | 12 - .../lib/PhpParser/Node/Expr/Cast/Bool_.php | 12 - .../lib/PhpParser/Node/Expr/Cast/Double.php | 17 - .../lib/PhpParser/Node/Expr/Cast/Int_.php | 12 - .../lib/PhpParser/Node/Expr/Cast/Object_.php | 12 - .../lib/PhpParser/Node/Expr/Cast/String_.php | 12 - .../lib/PhpParser/Node/Expr/Cast/Unset_.php | 12 - .../PhpParser/Node/Expr/ClassConstFetch.php | 36 - .../lib/PhpParser/Node/Expr/Clone_.php | 30 - .../lib/PhpParser/Node/Expr/Closure.php | 79 - .../lib/PhpParser/Node/Expr/ClosureUse.php | 34 - .../lib/PhpParser/Node/Expr/ConstFetch.php | 31 - .../lib/PhpParser/Node/Expr/Empty_.php | 30 - .../lib/PhpParser/Node/Expr/Error.php | 31 - .../lib/PhpParser/Node/Expr/ErrorSuppress.php | 30 - .../lib/PhpParser/Node/Expr/Eval_.php | 30 - .../lib/PhpParser/Node/Expr/Exit_.php | 34 - .../lib/PhpParser/Node/Expr/FuncCall.php | 39 - .../lib/PhpParser/Node/Expr/Include_.php | 39 - .../lib/PhpParser/Node/Expr/Instanceof_.php | 35 - .../lib/PhpParser/Node/Expr/Isset_.php | 30 - .../lib/PhpParser/Node/Expr/List_.php | 30 - .../lib/PhpParser/Node/Expr/Match_.php | 31 - .../lib/PhpParser/Node/Expr/MethodCall.php | 45 - .../lib/PhpParser/Node/Expr/New_.php | 41 - .../Node/Expr/NullsafeMethodCall.php | 45 - .../Node/Expr/NullsafePropertyFetch.php | 35 - .../lib/PhpParser/Node/Expr/PostDec.php | 30 - .../lib/PhpParser/Node/Expr/PostInc.php | 30 - .../lib/PhpParser/Node/Expr/PreDec.php | 30 - .../lib/PhpParser/Node/Expr/PreInc.php | 30 - .../lib/PhpParser/Node/Expr/Print_.php | 30 - .../lib/PhpParser/Node/Expr/PropertyFetch.php | 35 - .../lib/PhpParser/Node/Expr/ShellExec.php | 30 - .../lib/PhpParser/Node/Expr/StaticCall.php | 46 - .../Node/Expr/StaticPropertyFetch.php | 36 - .../lib/PhpParser/Node/Expr/Ternary.php | 38 - .../lib/PhpParser/Node/Expr/Throw_.php | 30 - .../lib/PhpParser/Node/Expr/UnaryMinus.php | 30 - .../lib/PhpParser/Node/Expr/UnaryPlus.php | 30 - .../lib/PhpParser/Node/Expr/Variable.php | 30 - .../lib/PhpParser/Node/Expr/YieldFrom.php | 30 - .../lib/PhpParser/Node/Expr/Yield_.php | 34 - .../lib/PhpParser/Node/FunctionLike.php | 43 - .../lib/PhpParser/Node/Identifier.php | 75 - .../lib/PhpParser/Node/IntersectionType.php | 30 - .../lib/PhpParser/Node/MatchArm.php | 31 - .../php-parser/lib/PhpParser/Node/Name.php | 242 - .../PhpParser/Node/Name/FullyQualified.php | 50 - .../lib/PhpParser/Node/Name/Relative.php | 50 - .../lib/PhpParser/Node/NullableType.php | 28 - .../php-parser/lib/PhpParser/Node/Param.php | 60 - .../php-parser/lib/PhpParser/Node/Scalar.php | 7 - .../lib/PhpParser/Node/Scalar/DNumber.php | 81 - .../lib/PhpParser/Node/Scalar/Encapsed.php | 31 - .../Node/Scalar/EncapsedStringPart.php | 30 - .../lib/PhpParser/Node/Scalar/LNumber.php | 80 - .../lib/PhpParser/Node/Scalar/MagicConst.php | 28 - .../Node/Scalar/MagicConst/Class_.php | 16 - .../PhpParser/Node/Scalar/MagicConst/Dir.php | 16 - .../PhpParser/Node/Scalar/MagicConst/File.php | 16 - .../Node/Scalar/MagicConst/Function_.php | 16 - .../PhpParser/Node/Scalar/MagicConst/Line.php | 16 - .../Node/Scalar/MagicConst/Method.php | 16 - .../Node/Scalar/MagicConst/Namespace_.php | 16 - .../Node/Scalar/MagicConst/Trait_.php | 16 - .../lib/PhpParser/Node/Scalar/String_.php | 157 - .../php-parser/lib/PhpParser/Node/Stmt.php | 9 - .../lib/PhpParser/Node/Stmt/Break_.php | 30 - .../lib/PhpParser/Node/Stmt/Case_.php | 34 - .../lib/PhpParser/Node/Stmt/Catch_.php | 41 - .../lib/PhpParser/Node/Stmt/ClassConst.php | 80 - .../lib/PhpParser/Node/Stmt/ClassLike.php | 109 - .../lib/PhpParser/Node/Stmt/ClassMethod.php | 159 - .../lib/PhpParser/Node/Stmt/Class_.php | 137 - .../lib/PhpParser/Node/Stmt/Const_.php | 30 - .../lib/PhpParser/Node/Stmt/Continue_.php | 30 - .../PhpParser/Node/Stmt/DeclareDeclare.php | 34 - .../lib/PhpParser/Node/Stmt/Declare_.php | 34 - .../lib/PhpParser/Node/Stmt/Do_.php | 34 - .../lib/PhpParser/Node/Stmt/Echo_.php | 30 - .../lib/PhpParser/Node/Stmt/ElseIf_.php | 34 - .../lib/PhpParser/Node/Stmt/Else_.php | 30 - .../lib/PhpParser/Node/Stmt/EnumCase.php | 37 - .../lib/PhpParser/Node/Stmt/Enum_.php | 40 - .../lib/PhpParser/Node/Stmt/Expression.php | 33 - .../lib/PhpParser/Node/Stmt/Finally_.php | 30 - .../lib/PhpParser/Node/Stmt/For_.php | 43 - .../lib/PhpParser/Node/Stmt/Foreach_.php | 47 - .../lib/PhpParser/Node/Stmt/Function_.php | 77 - .../lib/PhpParser/Node/Stmt/Global_.php | 30 - .../lib/PhpParser/Node/Stmt/Goto_.php | 31 - .../lib/PhpParser/Node/Stmt/GroupUse.php | 39 - .../lib/PhpParser/Node/Stmt/HaltCompiler.php | 30 - .../lib/PhpParser/Node/Stmt/If_.php | 43 - .../lib/PhpParser/Node/Stmt/InlineHTML.php | 30 - .../lib/PhpParser/Node/Stmt/Interface_.php | 37 - .../lib/PhpParser/Node/Stmt/Label.php | 31 - .../lib/PhpParser/Node/Stmt/Namespace_.php | 38 - .../lib/PhpParser/Node/Stmt/Nop.php | 17 - .../lib/PhpParser/Node/Stmt/Property.php | 91 - .../PhpParser/Node/Stmt/PropertyProperty.php | 34 - .../lib/PhpParser/Node/Stmt/Return_.php | 30 - .../lib/PhpParser/Node/Stmt/StaticVar.php | 37 - .../lib/PhpParser/Node/Stmt/Static_.php | 30 - .../lib/PhpParser/Node/Stmt/Switch_.php | 34 - .../lib/PhpParser/Node/Stmt/Throw_.php | 30 - .../lib/PhpParser/Node/Stmt/TraitUse.php | 34 - .../Node/Stmt/TraitUseAdaptation.php | 13 - .../Node/Stmt/TraitUseAdaptation/Alias.php | 38 - .../Stmt/TraitUseAdaptation/Precedence.php | 34 - .../lib/PhpParser/Node/Stmt/Trait_.php | 32 - .../lib/PhpParser/Node/Stmt/TryCatch.php | 38 - .../lib/PhpParser/Node/Stmt/Unset_.php | 30 - .../lib/PhpParser/Node/Stmt/UseUse.php | 52 - .../lib/PhpParser/Node/Stmt/Use_.php | 47 - .../lib/PhpParser/Node/Stmt/While_.php | 34 - .../lib/PhpParser/Node/UnionType.php | 28 - .../lib/PhpParser/Node/VarLikeIdentifier.php | 17 - .../PhpParser/Node/VariadicPlaceholder.php | 27 - .../php-parser/lib/PhpParser/NodeAbstract.php | 178 - .../php-parser/lib/PhpParser/NodeDumper.php | 206 - .../php-parser/lib/PhpParser/NodeFinder.php | 81 - .../lib/PhpParser/NodeTraverser.php | 291 - .../lib/PhpParser/NodeTraverserInterface.php | 29 - .../php-parser/lib/PhpParser/NodeVisitor.php | 72 - .../PhpParser/NodeVisitor/CloningVisitor.php | 20 - .../PhpParser/NodeVisitor/FindingVisitor.php | 48 - .../NodeVisitor/FirstFindingVisitor.php | 50 - .../PhpParser/NodeVisitor/NameResolver.php | 257 - .../NodeVisitor/NodeConnectingVisitor.php | 52 - .../NodeVisitor/ParentConnectingVisitor.php | 41 - .../lib/PhpParser/NodeVisitorAbstract.php | 25 - lib/nikic/php-parser/lib/PhpParser/Parser.php | 18 - .../lib/PhpParser/Parser/Multiple.php | 55 - .../php-parser/lib/PhpParser/Parser/Php5.php | 2672 -- .../php-parser/lib/PhpParser/Parser/Php7.php | 2829 -- .../lib/PhpParser/Parser/Tokens.php | 148 - .../lib/PhpParser/ParserAbstract.php | 1038 - .../lib/PhpParser/ParserFactory.php | 44 - .../lib/PhpParser/PrettyPrinter/Standard.php | 1105 - .../lib/PhpParser/PrettyPrinterAbstract.php | 1506 - lib/paragonie/random_compat/LICENSE | 22 - lib/paragonie/random_compat/build-phar.sh | 5 - lib/paragonie/random_compat/composer.json | 34 - .../dist/random_compat.phar.pubkey | 5 - .../dist/random_compat.phar.pubkey.asc | 11 - lib/paragonie/random_compat/lib/random.php | 32 - .../random_compat/other/build_phar.php | 57 - .../random_compat/psalm-autoload.php | 9 - lib/paragonie/random_compat/psalm.xml | 19 - lib/pear/archive_tar/.github/FUNDING.yml | 2 - lib/pear/archive_tar/.github/dependabot.yml | 11 - .../archive_tar/.github/workflows/build.yml | 40 - lib/pear/archive_tar/.gitignore | 15 - lib/pear/archive_tar/.travis.yml | 29 - lib/pear/archive_tar/Archive/Tar.php | 2530 -- lib/pear/archive_tar/README.md | 34 - lib/pear/archive_tar/composer.json | 54 - lib/pear/archive_tar/package.xml | 712 - lib/pear/console_getopt/.gitignore | 6 - lib/pear/console_getopt/.travis.yml | 9 - lib/pear/console_getopt/Console/Getopt.php | 365 - lib/pear/console_getopt/LICENSE | 25 - lib/pear/console_getopt/README.rst | 26 - lib/pear/console_getopt/composer.json | 35 - lib/pear/console_getopt/package.xml | 302 - lib/pear/pear-core-minimal/README.rst | 26 - lib/pear/pear-core-minimal/composer.json | 32 - lib/pear/pear-core-minimal/src/OS/Guess.php | 395 - lib/pear/pear-core-minimal/src/PEAR.php | 1135 - lib/pear/pear-core-minimal/src/PEAR/Error.php | 14 - .../pear-core-minimal/src/PEAR/ErrorStack.php | 979 - lib/pear/pear-core-minimal/src/System.php | 630 - lib/pear/pear_exception/LICENSE | 27 - lib/pear/pear_exception/PEAR/Exception.php | 456 - lib/pear/pear_exception/composer.json | 41 - lib/pelago/emogrifier/CHANGELOG.md | 415 - lib/pelago/emogrifier/LICENSE | 21 - lib/pelago/emogrifier/README.md | 427 - lib/pelago/emogrifier/composer.json | 125 - lib/pelago/emogrifier/phpunit.xml | 23 - .../src/Caching/SimpleStringCache.php | 87 - lib/pelago/emogrifier/src/Css/CssDocument.php | 187 - lib/pelago/emogrifier/src/Css/StyleRule.php | 83 - lib/pelago/emogrifier/src/CssInliner.php | 1196 - .../HtmlProcessor/AbstractHtmlProcessor.php | 472 - .../HtmlProcessor/CssToAttributeConverter.php | 303 - .../src/HtmlProcessor/HtmlNormalizer.php | 16 - .../src/HtmlProcessor/HtmlPruner.php | 137 - .../src/Utilities/ArrayIntersector.php | 57 - .../src/Utilities/CssConcatenator.php | 181 - lib/psr/cache/CHANGELOG.md | 16 - lib/psr/cache/LICENSE.txt | 19 - lib/psr/cache/README.md | 9 - lib/psr/cache/composer.json | 25 - lib/psr/cache/src/CacheException.php | 10 - lib/psr/cache/src/CacheItemInterface.php | 105 - lib/psr/cache/src/CacheItemPoolInterface.php | 138 - .../cache/src/InvalidArgumentException.php | 13 - lib/psr/container/.gitignore | 3 - lib/psr/container/LICENSE | 21 - lib/psr/container/README.md | 13 - lib/psr/container/composer.json | 22 - .../src/ContainerExceptionInterface.php | 12 - lib/psr/container/src/ContainerInterface.php | 36 - .../src/NotFoundExceptionInterface.php | 10 - lib/psr/event-dispatcher/.editorconfig | 15 - lib/psr/event-dispatcher/.gitignore | 2 - lib/psr/event-dispatcher/LICENSE | 21 - lib/psr/event-dispatcher/README.md | 6 - lib/psr/event-dispatcher/composer.json | 26 - .../src/EventDispatcherInterface.php | 21 - .../src/ListenerProviderInterface.php | 19 - .../src/StoppableEventInterface.php | 26 - lib/psr/http-client/CHANGELOG.md | 23 - lib/psr/http-client/LICENSE | 19 - lib/psr/http-client/README.md | 12 - lib/psr/http-client/composer.json | 27 - .../src/ClientExceptionInterface.php | 10 - lib/psr/http-client/src/ClientInterface.php | 20 - .../src/NetworkExceptionInterface.php | 24 - .../src/RequestExceptionInterface.php | 24 - lib/psr/http-factory/LICENSE | 21 - lib/psr/http-factory/README.md | 12 - lib/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 - lib/psr/http-message/CHANGELOG.md | 36 - lib/psr/http-message/LICENSE | 19 - lib/psr/http-message/README.md | 16 - lib/psr/http-message/composer.json | 26 - lib/psr/http-message/docs/PSR7-Interfaces.md | 130 - lib/psr/http-message/docs/PSR7-Usage.md | 159 - lib/psr/http-message/src/MessageInterface.php | 187 - lib/psr/http-message/src/RequestInterface.php | 130 - .../http-message/src/ResponseInterface.php | 68 - .../src/ServerRequestInterface.php | 261 - lib/psr/http-message/src/StreamInterface.php | 158 - .../src/UploadedFileInterface.php | 123 - lib/psr/http-message/src/UriInterface.php | 324 - lib/psr/log/LICENSE | 19 - lib/psr/log/Psr/Log/AbstractLogger.php | 128 - .../log/Psr/Log/InvalidArgumentException.php | 7 - lib/psr/log/Psr/Log/LogLevel.php | 18 - lib/psr/log/Psr/Log/LoggerAwareInterface.php | 18 - lib/psr/log/Psr/Log/LoggerAwareTrait.php | 26 - lib/psr/log/Psr/Log/LoggerInterface.php | 125 - lib/psr/log/Psr/Log/LoggerTrait.php | 142 - lib/psr/log/Psr/Log/NullLogger.php | 30 - lib/psr/log/README.md | 58 - lib/psr/log/composer.json | 26 - lib/ralouphie/getallheaders/LICENSE | 21 - lib/ralouphie/getallheaders/README.md | 27 - lib/ralouphie/getallheaders/composer.json | 26 - .../getallheaders/src/getallheaders.php | 46 - lib/sabberworm/php-css-parser/CHANGELOG.md | 241 - lib/sabberworm/php-css-parser/LICENSE | 21 - lib/sabberworm/php-css-parser/README.md | 632 - lib/sabberworm/php-css-parser/composer.json | 69 - .../src/CSSList/AtRuleBlockList.php | 83 - .../src/CSSList/CSSBlockList.php | 143 - .../php-css-parser/src/CSSList/CSSList.php | 479 - .../php-css-parser/src/CSSList/Document.php | 172 - .../php-css-parser/src/CSSList/KeyFrame.php | 104 - .../php-css-parser/src/Comment/Comment.php | 71 - .../src/Comment/Commentable.php | 25 - .../php-css-parser/src/OutputFormat.php | 334 - .../php-css-parser/src/OutputFormatter.php | 231 - lib/sabberworm/php-css-parser/src/Parser.php | 60 - .../src/Parsing/OutputException.php | 18 - .../src/Parsing/ParserState.php | 516 - .../src/Parsing/SourceException.php | 32 - .../src/Parsing/UnexpectedEOFException.php | 12 - .../src/Parsing/UnexpectedTokenException.php | 51 - .../php-css-parser/src/Property/AtRule.php | 34 - .../src/Property/CSSNamespace.php | 154 - .../php-css-parser/src/Property/Charset.php | 129 - .../php-css-parser/src/Property/Import.php | 137 - .../src/Property/KeyframeSelector.php | 23 - .../php-css-parser/src/Property/Selector.php | 138 - .../php-css-parser/src/Renderable.php | 21 - .../php-css-parser/src/Rule/Rule.php | 392 - .../php-css-parser/src/RuleSet/AtRuleSet.php | 73 - .../src/RuleSet/DeclarationBlock.php | 831 - .../php-css-parser/src/RuleSet/RuleSet.php | 326 - .../php-css-parser/src/Settings.php | 89 - .../php-css-parser/src/Value/CSSFunction.php | 73 - .../php-css-parser/src/Value/CSSString.php | 105 - .../php-css-parser/src/Value/CalcFunction.php | 89 - .../src/Value/CalcRuleValueList.php | 24 - .../php-css-parser/src/Value/Color.php | 166 - .../php-css-parser/src/Value/LineName.php | 65 - .../src/Value/PrimitiveValue.php | 14 - .../src/Value/RuleValueList.php | 15 - .../php-css-parser/src/Value/Size.php | 209 - .../php-css-parser/src/Value/URL.php | 82 - .../php-css-parser/src/Value/Value.php | 198 - .../php-css-parser/src/Value/ValueList.php | 100 - lib/scssphp/scssphp/LICENSE.md | 20 - lib/scssphp/scssphp/README.md | 71 - lib/scssphp/scssphp/bin/pscss | 244 - lib/scssphp/scssphp/composer.json | 117 - lib/scssphp/scssphp/scss.inc.php | 21 - lib/scssphp/scssphp/src/Base/Range.php | 57 - lib/scssphp/scssphp/src/Block.php | 73 - lib/scssphp/scssphp/src/Block/AtRootBlock.php | 37 - .../scssphp/src/Block/CallableBlock.php | 45 - .../scssphp/src/Block/ContentBlock.php | 38 - .../scssphp/src/Block/DirectiveBlock.php | 37 - lib/scssphp/scssphp/src/Block/EachBlock.php | 37 - lib/scssphp/scssphp/src/Block/ElseBlock.php | 27 - lib/scssphp/scssphp/src/Block/ElseifBlock.php | 32 - lib/scssphp/scssphp/src/Block/ForBlock.php | 47 - lib/scssphp/scssphp/src/Block/IfBlock.php | 37 - lib/scssphp/scssphp/src/Block/MediaBlock.php | 37 - .../scssphp/src/Block/NestedPropertyBlock.php | 37 - lib/scssphp/scssphp/src/Block/WhileBlock.php | 32 - lib/scssphp/scssphp/src/Cache.php | 272 - lib/scssphp/scssphp/src/Colors.php | 247 - lib/scssphp/scssphp/src/CompilationResult.php | 69 - lib/scssphp/scssphp/src/Compiler.php | 10408 ------- .../scssphp/src/Compiler/CachedResult.php | 77 - .../scssphp/src/Compiler/Environment.php | 68 - .../src/Exception/CompilerException.php | 24 - .../scssphp/src/Exception/ParserException.php | 58 - .../scssphp/src/Exception/RangeException.php | 24 - .../scssphp/src/Exception/SassException.php | 7 - .../src/Exception/SassScriptException.php | 32 - .../scssphp/src/Exception/ServerException.php | 26 - lib/scssphp/scssphp/src/Formatter.php | 377 - lib/scssphp/scssphp/src/Formatter/Compact.php | 52 - .../scssphp/src/Formatter/Compressed.php | 83 - .../scssphp/src/Formatter/Crunched.php | 87 - lib/scssphp/scssphp/src/Formatter/Debug.php | 127 - .../scssphp/src/Formatter/Expanded.php | 72 - lib/scssphp/scssphp/src/Formatter/Nested.php | 238 - .../scssphp/src/Formatter/OutputBlock.php | 68 - .../scssphp/src/Logger/LoggerInterface.php | 48 - .../scssphp/src/Logger/QuietLogger.php | 29 - .../scssphp/src/Logger/StreamLogger.php | 62 - lib/scssphp/scssphp/src/Node.php | 43 - lib/scssphp/scssphp/src/Node/Number.php | 804 - lib/scssphp/scssphp/src/OutputStyle.php | 9 - lib/scssphp/scssphp/src/Parser.php | 4201 --- lib/scssphp/scssphp/src/SourceMap/Base64.php | 187 - .../scssphp/src/SourceMap/Base64VLQ.php | 151 - .../src/SourceMap/SourceMapGenerator.php | 390 - lib/scssphp/scssphp/src/Type.php | 208 - lib/scssphp/scssphp/src/Util.php | 184 - lib/scssphp/scssphp/src/Util/Path.php | 77 - lib/scssphp/scssphp/src/ValueConverter.php | 95 - lib/scssphp/scssphp/src/Version.php | 23 - lib/scssphp/scssphp/src/Warn.php | 84 - lib/symfony/cache-contracts/.gitignore | 3 - lib/symfony/cache-contracts/CHANGELOG.md | 5 - .../cache-contracts/CacheInterface.php | 57 - lib/symfony/cache-contracts/CacheTrait.php | 80 - .../cache-contracts/CallbackInterface.php | 30 - lib/symfony/cache-contracts/ItemInterface.php | 65 - lib/symfony/cache-contracts/LICENSE | 19 - lib/symfony/cache-contracts/README.md | 9 - .../TagAwareCacheInterface.php | 38 - lib/symfony/cache-contracts/composer.json | 38 - lib/symfony/cache/Adapter/AbstractAdapter.php | 208 - .../cache/Adapter/AbstractTagAwareAdapter.php | 330 - .../cache/Adapter/AdapterInterface.php | 47 - lib/symfony/cache/Adapter/ApcuAdapter.php | 138 - lib/symfony/cache/Adapter/ArrayAdapter.php | 407 - lib/symfony/cache/Adapter/ChainAdapter.php | 342 - .../cache/Adapter/CouchbaseBucketAdapter.php | 252 - .../Adapter/CouchbaseCollectionAdapter.php | 222 - lib/symfony/cache/Adapter/DoctrineAdapter.php | 110 - .../cache/Adapter/DoctrineDbalAdapter.php | 397 - .../cache/Adapter/FilesystemAdapter.php | 29 - .../Adapter/FilesystemTagAwareAdapter.php | 239 - .../cache/Adapter/MemcachedAdapter.php | 353 - lib/symfony/cache/Adapter/NullAdapter.php | 152 - .../cache/Adapter/ParameterNormalizer.php | 35 - lib/symfony/cache/Adapter/PdoAdapter.php | 583 - lib/symfony/cache/Adapter/PhpArrayAdapter.php | 435 - lib/symfony/cache/Adapter/PhpFilesAdapter.php | 330 - lib/symfony/cache/Adapter/ProxyAdapter.php | 268 - lib/symfony/cache/Adapter/Psr16Adapter.php | 86 - lib/symfony/cache/Adapter/RedisAdapter.php | 32 - .../cache/Adapter/RedisTagAwareAdapter.php | 325 - lib/symfony/cache/Adapter/TagAwareAdapter.php | 428 - .../Adapter/TagAwareAdapterInterface.php | 33 - .../cache/Adapter/TraceableAdapter.php | 295 - .../Adapter/TraceableTagAwareAdapter.php | 38 - lib/symfony/cache/CHANGELOG.md | 108 - lib/symfony/cache/CacheItem.php | 192 - .../DataCollector/CacheDataCollector.php | 185 - .../CacheCollectorPass.php | 94 - .../CachePoolClearerPass.php | 52 - .../DependencyInjection/CachePoolPass.php | 274 - .../CachePoolPrunerPass.php | 64 - lib/symfony/cache/DoctrineProvider.php | 124 - .../cache/Exception/CacheException.php | 25 - .../Exception/InvalidArgumentException.php | 25 - .../cache/Exception/LogicException.php | 25 - lib/symfony/cache/LICENSE | 19 - lib/symfony/cache/LockRegistry.php | 165 - .../cache/Marshaller/DefaultMarshaller.php | 104 - .../cache/Marshaller/DeflateMarshaller.php | 53 - .../cache/Marshaller/MarshallerInterface.php | 40 - .../cache/Marshaller/SodiumMarshaller.php | 80 - .../cache/Marshaller/TagAwareMarshaller.php | 89 - .../Messenger/EarlyExpirationDispatcher.php | 61 - .../Messenger/EarlyExpirationHandler.php | 80 - .../Messenger/EarlyExpirationMessage.php | 97 - lib/symfony/cache/PruneableInterface.php | 23 - lib/symfony/cache/Psr16Cache.php | 289 - lib/symfony/cache/README.md | 19 - lib/symfony/cache/ResettableInterface.php | 21 - .../cache/Traits/AbstractAdapterTrait.php | 424 - lib/symfony/cache/Traits/ContractsTrait.php | 109 - .../cache/Traits/FilesystemCommonTrait.php | 196 - lib/symfony/cache/Traits/FilesystemTrait.php | 124 - lib/symfony/cache/Traits/ProxyTrait.php | 43 - .../cache/Traits/RedisClusterNodeProxy.php | 53 - .../cache/Traits/RedisClusterProxy.php | 63 - lib/symfony/cache/Traits/RedisProxy.php | 65 - lib/symfony/cache/Traits/RedisTrait.php | 603 - lib/symfony/cache/composer.json | 60 - lib/symfony/config/Builder/ClassBuilder.php | 174 - .../config/Builder/ConfigBuilderGenerator.php | 561 - .../ConfigBuilderGeneratorInterface.php | 27 - .../config/Builder/ConfigBuilderInterface.php | 30 - lib/symfony/config/Builder/Method.php | 34 - lib/symfony/config/Builder/Property.php | 86 - lib/symfony/config/CHANGELOG.md | 129 - lib/symfony/config/ConfigCache.php | 62 - lib/symfony/config/ConfigCacheFactory.php | 47 - .../config/ConfigCacheFactoryInterface.php | 32 - lib/symfony/config/ConfigCacheInterface.php | 49 - lib/symfony/config/Definition/ArrayNode.php | 404 - lib/symfony/config/Definition/BaseNode.php | 589 - lib/symfony/config/Definition/BooleanNode.php | 55 - .../Builder/ArrayNodeDefinition.php | 549 - .../Builder/BooleanNodeDefinition.php | 53 - .../Builder/BuilderAwareInterface.php | 25 - .../Definition/Builder/EnumNodeDefinition.php | 56 - .../config/Definition/Builder/ExprBuilder.php | 246 - .../Builder/FloatNodeDefinition.php | 32 - .../Builder/IntegerNodeDefinition.php | 32 - .../Definition/Builder/MergeBuilder.php | 63 - .../config/Definition/Builder/NodeBuilder.php | 219 - .../Definition/Builder/NodeDefinition.php | 383 - .../Builder/NodeParentInterface.php | 21 - .../Builder/NormalizationBuilder.php | 60 - .../Builder/NumericNodeDefinition.php | 73 - .../Builder/ParentNodeDefinitionInterface.php | 51 - .../Builder/ScalarNodeDefinition.php | 32 - .../config/Definition/Builder/TreeBuilder.php | 63 - .../Definition/Builder/ValidationBuilder.php | 44 - .../Builder/VariableNodeDefinition.php | 68 - .../Definition/ConfigurationInterface.php | 29 - .../Definition/Dumper/XmlReferenceDumper.php | 306 - .../Definition/Dumper/YamlReferenceDumper.php | 251 - lib/symfony/config/Definition/EnumNode.php | 65 - .../Exception/DuplicateKeyException.php | 22 - .../config/Definition/Exception/Exception.php | 21 - .../Exception/ForbiddenOverwriteException.php | 22 - .../InvalidConfigurationException.php | 47 - .../Exception/InvalidDefinitionException.php | 21 - .../Exception/InvalidTypeException.php | 21 - .../Exception/UnsetKeyException.php | 22 - lib/symfony/config/Definition/FloatNode.php | 51 - lib/symfony/config/Definition/IntegerNode.php | 46 - .../config/Definition/NodeInterface.php | 100 - lib/symfony/config/Definition/NumericNode.php | 68 - lib/symfony/config/Definition/Processor.php | 91 - .../Definition/PrototypeNodeInterface.php | 25 - .../config/Definition/PrototypedArrayNode.php | 350 - lib/symfony/config/Definition/ScalarNode.php | 67 - .../config/Definition/VariableNode.php | 142 - ...LoaderImportCircularReferenceException.php | 33 - .../FileLocatorFileNotFoundException.php | 34 - .../config/Exception/LoaderLoadException.php | 115 - lib/symfony/config/FileLocator.php | 94 - lib/symfony/config/FileLocatorInterface.php | 34 - lib/symfony/config/LICENSE | 19 - .../config/Loader/DelegatingLoader.php | 50 - lib/symfony/config/Loader/FileLoader.php | 180 - lib/symfony/config/Loader/GlobFileLoader.php | 36 - lib/symfony/config/Loader/Loader.php | 84 - lib/symfony/config/Loader/LoaderInterface.php | 52 - lib/symfony/config/Loader/LoaderResolver.php | 68 - .../config/Loader/LoaderResolverInterface.php | 30 - .../config/Loader/ParamConfigurator.php | 32 - lib/symfony/config/README.md | 15 - .../Resource/ClassExistenceResource.php | 232 - .../config/Resource/ComposerResource.php | 67 - .../config/Resource/DirectoryResource.php | 97 - .../config/Resource/FileExistenceResource.php | 56 - lib/symfony/config/Resource/FileResource.php | 64 - lib/symfony/config/Resource/GlobResource.php | 246 - .../Resource/ReflectionClassResource.php | 267 - .../config/Resource/ResourceInterface.php | 31 - .../Resource/SelfCheckingResourceChecker.php | 46 - .../SelfCheckingResourceInterface.php | 30 - .../config/ResourceCheckerConfigCache.php | 187 - .../ResourceCheckerConfigCacheFactory.php | 44 - .../config/ResourceCheckerInterface.php | 45 - .../Util/Exception/InvalidXmlException.php | 22 - .../Util/Exception/XmlParsingException.php | 21 - lib/symfony/config/Util/XmlUtils.php | 289 - lib/symfony/config/composer.json | 46 - lib/symfony/console/Application.php | 1301 - lib/symfony/console/Attribute/AsCommand.php | 39 - lib/symfony/console/CHANGELOG.md | 217 - .../console/CI/GithubActionReporter.php | 99 - lib/symfony/console/Color.php | 180 - lib/symfony/console/Command/Command.php | 710 - .../console/Command/CompleteCommand.php | 205 - .../console/Command/DumpCompletionCommand.php | 139 - lib/symfony/console/Command/HelpCommand.php | 101 - lib/symfony/console/Command/LazyCommand.php | 218 - lib/symfony/console/Command/ListCommand.php | 95 - lib/symfony/console/Command/LockableTrait.php | 69 - .../Command/SignalableCommandInterface.php | 30 - .../CommandLoader/CommandLoaderInterface.php | 42 - .../CommandLoader/ContainerCommandLoader.php | 63 - .../CommandLoader/FactoryCommandLoader.php | 62 - .../console/Completion/CompletionInput.php | 249 - .../Completion/CompletionSuggestions.php | 99 - .../Output/BashCompletionOutput.php | 33 - .../Output/CompletionOutputInterface.php | 25 - lib/symfony/console/Completion/Suggestion.php | 37 - lib/symfony/console/ConsoleEvents.php | 72 - lib/symfony/console/Cursor.php | 207 - .../AddConsoleCommandPass.php | 148 - .../Descriptor/ApplicationDescription.php | 143 - lib/symfony/console/Descriptor/Descriptor.php | 94 - .../Descriptor/DescriptorInterface.php | 24 - .../console/Descriptor/JsonDescriptor.php | 181 - .../console/Descriptor/MarkdownDescriptor.php | 206 - .../console/Descriptor/TextDescriptor.php | 341 - .../console/Descriptor/XmlDescriptor.php | 247 - .../console/Event/ConsoleCommandEvent.php | 51 - .../console/Event/ConsoleErrorEvent.php | 58 - lib/symfony/console/Event/ConsoleEvent.php | 67 - .../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 | 285 - .../Formatter/OutputFormatterInterface.php | 60 - .../Formatter/OutputFormatterStyle.php | 108 - .../OutputFormatterStyleInterface.php | 52 - .../Formatter/OutputFormatterStyleStack.php | 110 - .../WrappableOutputFormatterInterface.php | 25 - .../console/Helper/DebugFormatterHelper.php | 107 - .../console/Helper/DescriptorHelper.php | 92 - lib/symfony/console/Helper/Dumper.php | 64 - .../console/Helper/FormatterHelper.php | 92 - lib/symfony/console/Helper/Helper.php | 180 - .../console/Helper/HelperInterface.php | 39 - lib/symfony/console/Helper/HelperSet.php | 108 - .../console/Helper/InputAwareHelper.php | 33 - lib/symfony/console/Helper/ProcessHelper.php | 144 - lib/symfony/console/Helper/ProgressBar.php | 609 - .../console/Helper/ProgressIndicator.php | 249 - lib/symfony/console/Helper/QuestionHelper.php | 616 - .../console/Helper/SymfonyQuestionHelper.php | 109 - lib/symfony/console/Helper/Table.php | 915 - lib/symfony/console/Helper/TableCell.php | 78 - lib/symfony/console/Helper/TableCellStyle.php | 89 - lib/symfony/console/Helper/TableRows.php | 30 - lib/symfony/console/Helper/TableSeparator.php | 25 - lib/symfony/console/Helper/TableStyle.php | 376 - lib/symfony/console/Input/ArgvInput.php | 378 - lib/symfony/console/Input/ArrayInput.php | 210 - lib/symfony/console/Input/Input.php | 213 - lib/symfony/console/Input/InputArgument.php | 129 - .../console/Input/InputAwareInterface.php | 26 - lib/symfony/console/Input/InputDefinition.php | 424 - lib/symfony/console/Input/InputInterface.php | 151 - lib/symfony/console/Input/InputOption.php | 231 - .../Input/StreamableInputInterface.php | 37 - lib/symfony/console/Input/StringInput.php | 84 - lib/symfony/console/LICENSE | 19 - lib/symfony/console/Logger/ConsoleLogger.php | 126 - lib/symfony/console/Output/BufferedOutput.php | 45 - lib/symfony/console/Output/ConsoleOutput.php | 172 - .../console/Output/ConsoleOutputInterface.php | 32 - .../console/Output/ConsoleSectionOutput.php | 143 - lib/symfony/console/Output/NullOutput.php | 128 - lib/symfony/console/Output/Output.php | 174 - .../console/Output/OutputInterface.php | 110 - lib/symfony/console/Output/StreamOutput.php | 115 - .../console/Output/TrimmedBufferOutput.php | 63 - .../console/Question/ChoiceQuestion.php | 183 - .../console/Question/ConfirmationQuestion.php | 57 - lib/symfony/console/Question/Question.php | 299 - lib/symfony/console/README.md | 36 - .../console/Resources/bin/hiddeninput.exe | Bin 9216 -> 0 bytes lib/symfony/console/Resources/completion.bash | 84 - .../console/SignalRegistry/SignalRegistry.php | 65 - .../console/SingleCommandApplication.php | 72 - lib/symfony/console/Style/OutputStyle.php | 153 - lib/symfony/console/Style/StyleInterface.php | 132 - lib/symfony/console/Style/SymfonyStyle.php | 518 - lib/symfony/console/Terminal.php | 172 - .../console/Tester/ApplicationTester.php | 85 - .../Tester/CommandCompletionTester.php | 56 - lib/symfony/console/Tester/CommandTester.php | 76 - .../Tester/Constraint/CommandIsSuccessful.php | 55 - lib/symfony/console/Tester/TesterTrait.php | 197 - lib/symfony/console/composer.json | 60 - lib/symfony/css-selector/CHANGELOG.md | 18 - .../css-selector/CssSelectorConverter.php | 69 - .../Exception/ExceptionInterface.php | 24 - .../Exception/ExpressionErrorException.php | 24 - .../Exception/InternalErrorException.php | 24 - .../css-selector/Exception/ParseException.php | 24 - .../Exception/SyntaxErrorException.php | 65 - lib/symfony/css-selector/LICENSE | 19 - .../css-selector/Node/AbstractNode.php | 39 - .../css-selector/Node/AttributeNode.php | 82 - lib/symfony/css-selector/Node/ClassNode.php | 57 - .../Node/CombinedSelectorNode.php | 66 - lib/symfony/css-selector/Node/ElementNode.php | 59 - .../css-selector/Node/FunctionNode.php | 76 - lib/symfony/css-selector/Node/HashNode.php | 57 - .../css-selector/Node/NegationNode.php | 57 - .../css-selector/Node/NodeInterface.php | 31 - lib/symfony/css-selector/Node/PseudoNode.php | 57 - .../css-selector/Node/SelectorNode.php | 57 - lib/symfony/css-selector/Node/Specificity.php | 73 - .../Parser/Handler/CommentHandler.php | 48 - .../Parser/Handler/HandlerInterface.php | 30 - .../Parser/Handler/HashHandler.php | 58 - .../Parser/Handler/IdentifierHandler.php | 58 - .../Parser/Handler/NumberHandler.php | 54 - .../Parser/Handler/StringHandler.php | 77 - .../Parser/Handler/WhitespaceHandler.php | 46 - lib/symfony/css-selector/Parser/Parser.php | 353 - .../css-selector/Parser/ParserInterface.php | 34 - lib/symfony/css-selector/Parser/Reader.php | 86 - .../Parser/Shortcut/ClassParser.php | 51 - .../Parser/Shortcut/ElementParser.php | 47 - .../Parser/Shortcut/EmptyStringParser.php | 46 - .../Parser/Shortcut/HashParser.php | 51 - lib/symfony/css-selector/Parser/Token.php | 111 - .../css-selector/Parser/TokenStream.php | 167 - .../Parser/Tokenizer/Tokenizer.php | 73 - .../Parser/Tokenizer/TokenizerEscaping.php | 65 - .../Parser/Tokenizer/TokenizerPatterns.php | 89 - lib/symfony/css-selector/README.md | 20 - .../XPath/Extension/AbstractExtension.php | 65 - .../Extension/AttributeMatchingExtension.php | 119 - .../XPath/Extension/CombinationExtension.php | 71 - .../XPath/Extension/ExtensionInterface.php | 67 - .../XPath/Extension/FunctionExtension.php | 171 - .../XPath/Extension/HtmlExtension.php | 187 - .../XPath/Extension/NodeExtension.php | 197 - .../XPath/Extension/PseudoClassExtension.php | 122 - lib/symfony/css-selector/XPath/Translator.php | 230 - .../XPath/TranslatorInterface.php | 37 - lib/symfony/css-selector/XPath/XPathExpr.php | 111 - lib/symfony/css-selector/composer.json | 33 - lib/symfony/dependency-injection/Alias.php | 161 - .../Argument/AbstractArgument.php | 41 - .../Argument/ArgumentInterface.php | 27 - .../Argument/BoundArgument.php | 62 - .../Argument/IteratorArgument.php | 22 - .../Argument/ReferenceSetArgumentTrait.php | 54 - .../Argument/RewindableGenerator.php | 46 - .../Argument/ServiceClosureArgument.php | 50 - .../Argument/ServiceLocator.php | 52 - .../Argument/ServiceLocatorArgument.php | 44 - .../Argument/TaggedIteratorArgument.php | 73 - .../Attribute/AsTaggedItem.php | 27 - .../Attribute/Autoconfigure.php | 34 - .../Attribute/AutoconfigureTag.php | 30 - .../Attribute/TaggedIterator.php | 24 - .../Attribute/TaggedLocator.php | 24 - .../dependency-injection/Attribute/Target.php | 54 - .../dependency-injection/Attribute/When.php | 26 - lib/symfony/dependency-injection/CHANGELOG.md | 302 - .../dependency-injection/ChildDefinition.php | 104 - .../Compiler/AbstractRecursivePass.php | 242 - .../AliasDeprecatedPublicServicesPass.php | 76 - .../Compiler/AnalyzeServiceReferencesPass.php | 191 - .../AttributeAutoconfigurationPass.php | 168 - .../Compiler/AutoAliasServicePass.php | 60 - .../Compiler/AutowirePass.php | 625 - .../Compiler/AutowireRequiredMethodsPass.php | 109 - .../AutowireRequiredPropertiesPass.php | 64 - .../Compiler/CheckArgumentsValidityPass.php | 119 - .../Compiler/CheckCircularReferencesPass.php | 78 - .../Compiler/CheckDefinitionValidityPass.php | 90 - ...xceptionOnInvalidReferenceBehaviorPass.php | 105 - .../Compiler/CheckReferenceValidityPass.php | 43 - .../Compiler/CheckTypeDeclarationsPass.php | 329 - .../Compiler/Compiler.php | 107 - .../Compiler/CompilerPassInterface.php | 27 - .../Compiler/DecoratorServicePass.php | 133 - .../Compiler/DefinitionErrorExceptionPass.php | 56 - .../Compiler/ExtensionCompilerPass.php | 37 - .../Compiler/InlineServiceDefinitionsPass.php | 223 - .../MergeExtensionConfigurationPass.php | 216 - .../Compiler/PassConfig.php | 269 - .../Compiler/PriorityTaggedServiceTrait.php | 171 - .../RegisterAutoconfigureAttributesPass.php | 92 - .../Compiler/RegisterEnvVarProcessorsPass.php | 75 - .../Compiler/RegisterReverseContainerPass.php | 70 - .../RegisterServiceSubscribersPass.php | 131 - .../RemoveAbstractDefinitionsPass.php | 33 - .../Compiler/RemovePrivateAliasesPass.php | 39 - .../Compiler/RemoveUnusedDefinitionsPass.php | 90 - .../ReplaceAliasByActualDefinitionPass.php | 120 - .../Compiler/ResolveBindingsPass.php | 246 - .../Compiler/ResolveChildDefinitionsPass.php | 204 - .../Compiler/ResolveClassPass.php | 40 - .../Compiler/ResolveDecoratorStackPass.php | 131 - .../Compiler/ResolveEnvPlaceholdersPass.php | 44 - .../Compiler/ResolveFactoryClassPass.php | 38 - .../Compiler/ResolveHotPathPass.php | 90 - .../ResolveInstanceofConditionalsPass.php | 177 - .../Compiler/ResolveInvalidReferencesPass.php | 136 - .../Compiler/ResolveNamedArgumentsPass.php | 127 - .../Compiler/ResolveNoPreloadPass.php | 104 - .../ResolveParameterPlaceHoldersPass.php | 103 - .../Compiler/ResolvePrivatesPass.php | 44 - .../ResolveReferencesToAliasesPass.php | 84 - .../ResolveServiceSubscribersPass.php | 52 - .../ResolveTaggedIteratorArgumentPass.php | 38 - .../Compiler/ServiceLocatorTagPass.php | 138 - .../Compiler/ServiceReferenceGraph.php | 99 - .../Compiler/ServiceReferenceGraphEdge.php | 99 - .../Compiler/ServiceReferenceGraphNode.php | 118 - .../Compiler/ValidateEnvPlaceholdersPass.php | 103 - .../Config/ContainerParametersResource.php | 44 - .../ContainerParametersResourceChecker.php | 52 - .../dependency-injection/Container.php | 434 - .../ContainerAwareInterface.php | 25 - .../ContainerAwareTrait.php | 30 - .../dependency-injection/ContainerBuilder.php | 1702 -- .../ContainerInterface.php | 84 - .../dependency-injection/Definition.php | 922 - .../dependency-injection/Dumper/Dumper.php | 29 - .../Dumper/DumperInterface.php | 27 - .../Dumper/GraphvizDumper.php | 251 - .../dependency-injection/Dumper/PhpDumper.php | 2261 -- .../dependency-injection/Dumper/Preloader.php | 131 - .../dependency-injection/Dumper/XmlDumper.php | 395 - .../Dumper/YamlDumper.php | 375 - .../EnvVarLoaderInterface.php | 25 - .../dependency-injection/EnvVarProcessor.php | 304 - .../EnvVarProcessorInterface.php | 40 - .../Exception/AutowiringFailedException.php | 74 - .../Exception/BadMethodCallException.php | 19 - .../Exception/EnvNotFoundException.php | 21 - .../Exception/EnvParameterException.php | 25 - .../Exception/ExceptionInterface.php | 24 - .../Exception/InvalidArgumentException.php | 21 - .../InvalidParameterTypeException.php | 35 - .../Exception/LogicException.php | 19 - .../Exception/OutOfBoundsException.php | 19 - .../ParameterCircularReferenceException.php | 34 - .../Exception/ParameterNotFoundException.php | 100 - .../Exception/RuntimeException.php | 21 - .../ServiceCircularReferenceException.php | 41 - .../Exception/ServiceNotFoundException.php | 67 - .../ExpressionLanguage.php | 40 - .../ExpressionLanguageProvider.php | 50 - .../ConfigurationExtensionInterface.php | 30 - .../Extension/Extension.php | 139 - .../Extension/ExtensionInterface.php | 52 - .../Extension/PrependExtensionInterface.php | 22 - lib/symfony/dependency-injection/LICENSE | 19 - .../Instantiator/InstantiatorInterface.php | 34 - .../Instantiator/RealServiceInstantiator.php | 33 - .../LazyProxy/PhpDumper/DumperInterface.php | 43 - .../LazyProxy/PhpDumper/NullDumper.php | 48 - .../LazyProxy/ProxyHelper.php | 93 - .../Loader/ClosureLoader.php | 49 - .../Configurator/AbstractConfigurator.php | 119 - .../AbstractServiceConfigurator.php | 115 - .../Loader/Configurator/AliasConfigurator.php | 31 - .../ClosureReferenceConfigurator.php | 16 - .../Configurator/ContainerConfigurator.php | 212 - .../Configurator/DefaultsConfigurator.php | 69 - .../Loader/Configurator/EnvConfigurator.php | 224 - .../InlineServiceConfigurator.php | 43 - .../Configurator/InstanceofConfigurator.php | 49 - .../Configurator/ParametersConfigurator.php | 57 - .../Configurator/PrototypeConfigurator.php | 87 - .../Configurator/ReferenceConfigurator.php | 69 - .../Configurator/ServiceConfigurator.php | 72 - .../Configurator/ServicesConfigurator.php | 192 - .../Configurator/Traits/AbstractTrait.php | 28 - .../Configurator/Traits/ArgumentTrait.php | 42 - .../Traits/AutoconfigureTrait.php | 31 - .../Configurator/Traits/AutowireTrait.php | 27 - .../Loader/Configurator/Traits/BindTrait.php | 42 - .../Loader/Configurator/Traits/CallTrait.php | 35 - .../Loader/Configurator/Traits/ClassTrait.php | 27 - .../Configurator/Traits/ConfiguratorTrait.php | 29 - .../Configurator/Traits/DecorateTrait.php | 34 - .../Configurator/Traits/DeprecateTrait.php | 48 - .../Configurator/Traits/FactoryTrait.php | 38 - .../Loader/Configurator/Traits/FileTrait.php | 27 - .../Loader/Configurator/Traits/LazyTrait.php | 32 - .../Configurator/Traits/ParentTrait.php | 46 - .../Configurator/Traits/PropertyTrait.php | 27 - .../Configurator/Traits/PublicTrait.php | 35 - .../Loader/Configurator/Traits/ShareTrait.php | 27 - .../Configurator/Traits/SyntheticTrait.php | 28 - .../Loader/Configurator/Traits/TagTrait.php | 39 - .../Loader/DirectoryLoader.php | 56 - .../Loader/FileLoader.php | 247 - .../Loader/GlobFileLoader.php | 42 - .../Loader/IniFileLoader.php | 105 - .../Loader/PhpFileLoader.php | 211 - .../Loader/XmlFileLoader.php | 782 - .../Loader/YamlFileLoader.php | 966 - .../schema/dic/services/services-1.0.xsd | 353 - .../dependency-injection/Parameter.php | 35 - .../ParameterBag/ContainerBag.php | 55 - .../ParameterBag/ContainerBagInterface.php | 57 - .../EnvPlaceholderParameterBag.php | 154 - .../ParameterBag/FrozenParameterBag.php | 68 - .../ParameterBag/ParameterBag.php | 276 - .../ParameterBag/ParameterBagInterface.php | 106 - lib/symfony/dependency-injection/README.md | 14 - .../dependency-injection/Reference.php | 47 - .../dependency-injection/ReverseContainer.php | 81 - .../dependency-injection/ServiceLocator.php | 150 - .../TaggedContainerInterface.php | 29 - .../dependency-injection/TypedReference.php | 46 - lib/symfony/dependency-injection/Variable.php | 43 - .../dependency-injection/composer.json | 56 - lib/symfony/deprecation-contracts/.gitignore | 3 - .../deprecation-contracts/CHANGELOG.md | 5 - lib/symfony/deprecation-contracts/LICENSE | 19 - lib/symfony/deprecation-contracts/README.md | 26 - .../deprecation-contracts/composer.json | 35 - .../deprecation-contracts/function.php | 27 - lib/symfony/dotenv/CHANGELOG.md | 40 - lib/symfony/dotenv/Command/DebugCommand.php | 143 - .../dotenv/Command/DotenvDumpCommand.php | 123 - lib/symfony/dotenv/Dotenv.php | 573 - .../dotenv/Exception/ExceptionInterface.php | 21 - .../dotenv/Exception/FormatException.php | 34 - .../Exception/FormatExceptionContext.php | 49 - .../dotenv/Exception/PathException.php | 25 - lib/symfony/dotenv/LICENSE | 19 - lib/symfony/dotenv/README.md | 36 - lib/symfony/dotenv/composer.json | 33 - lib/symfony/error-handler/BufferingLogger.php | 71 - lib/symfony/error-handler/CHANGELOG.md | 24 - lib/symfony/error-handler/Debug.php | 41 - .../error-handler/DebugClassLoader.php | 1211 - .../Error/ClassNotFoundError.php | 33 - .../error-handler/Error/FatalError.php | 89 - .../error-handler/Error/OutOfMemoryError.php | 16 - .../Error/UndefinedFunctionError.php | 33 - .../Error/UndefinedMethodError.php | 33 - .../ClassNotFoundErrorEnhancer.php | 177 - .../ErrorEnhancer/ErrorEnhancerInterface.php | 20 - .../UndefinedFunctionErrorEnhancer.php | 87 - .../UndefinedMethodErrorEnhancer.php | 69 - lib/symfony/error-handler/ErrorHandler.php | 798 - .../ErrorRenderer/CliErrorRenderer.php | 49 - .../ErrorRenderer/ErrorRendererInterface.php | 27 - .../ErrorRenderer/HtmlErrorRenderer.php | 367 - .../ErrorRenderer/SerializerErrorRenderer.php | 94 - .../Exception/FlattenException.php | 427 - .../Exception/SilencedErrorContext.php | 67 - .../error-handler/Internal/TentativeTypes.php | 1642 - lib/symfony/error-handler/LICENSE | 19 - lib/symfony/error-handler/README.md | 44 - .../Resources/assets/css/error.css | 4 - .../Resources/assets/css/exception.css | 252 - .../Resources/assets/css/exception_full.css | 128 - .../Resources/assets/images/chevron-right.svg | 1 - .../assets/images/favicon.png.base64 | 1 - .../Resources/assets/images/icon-book.svg | 1 - .../Resources/assets/images/icon-copy.svg | 1 - .../assets/images/icon-minus-square-o.svg | 1 - .../assets/images/icon-minus-square.svg | 1 - .../assets/images/icon-plus-square-o.svg | 1 - .../assets/images/icon-plus-square.svg | 1 - .../Resources/assets/images/icon-support.svg | 1 - .../assets/images/symfony-ghost.svg.php | 1 - .../Resources/assets/images/symfony-logo.svg | 1 - .../Resources/assets/js/exception.js | 297 - .../bin/extract-tentative-return-types.php | 80 - .../Resources/bin/patch-type-declarations | 94 - .../Resources/views/error.html.php | 20 - .../Resources/views/exception.html.php | 116 - .../Resources/views/exception_full.html.php | 42 - .../Resources/views/logs.html.php | 45 - .../Resources/views/trace.html.php | 43 - .../Resources/views/traces.html.php | 51 - .../Resources/views/traces_text.html.php | 43 - lib/symfony/error-handler/ThrowableUtils.php | 40 - lib/symfony/error-handler/composer.json | 38 - .../event-dispatcher-contracts/.gitignore | 3 - .../event-dispatcher-contracts/CHANGELOG.md | 5 - .../event-dispatcher-contracts/Event.php | 54 - .../EventDispatcherInterface.php | 31 - .../event-dispatcher-contracts/LICENSE | 19 - .../event-dispatcher-contracts/README.md | 9 - .../event-dispatcher-contracts/composer.json | 38 - .../Attribute/AsEventListener.php | 29 - lib/symfony/event-dispatcher/CHANGELOG.md | 91 - .../Debug/TraceableEventDispatcher.php | 366 - .../Debug/WrappedListener.php | 127 - .../AddEventAliasesPass.php | 46 - .../RegisterListenersPass.php | 238 - .../event-dispatcher/EventDispatcher.php | 280 - .../EventDispatcherInterface.php | 70 - .../EventSubscriberInterface.php | 49 - lib/symfony/event-dispatcher/GenericEvent.php | 182 - .../ImmutableEventDispatcher.php | 91 - lib/symfony/event-dispatcher/LICENSE | 19 - .../LegacyEventDispatcherProxy.php | 31 - lib/symfony/event-dispatcher/README.md | 15 - lib/symfony/event-dispatcher/composer.json | 52 - lib/symfony/filesystem/CHANGELOG.md | 82 - .../Exception/ExceptionInterface.php | 21 - .../Exception/FileNotFoundException.php | 34 - .../filesystem/Exception/IOException.php | 39 - .../Exception/IOExceptionInterface.php | 27 - .../Exception/InvalidArgumentException.php | 19 - .../filesystem/Exception/RuntimeException.php | 19 - lib/symfony/filesystem/Filesystem.php | 769 - lib/symfony/filesystem/LICENSE | 19 - lib/symfony/filesystem/Path.php | 819 - lib/symfony/filesystem/README.md | 13 - lib/symfony/filesystem/composer.json | 31 - lib/symfony/finder/CHANGELOG.md | 87 - lib/symfony/finder/Comparator/Comparator.php | 117 - .../finder/Comparator/DateComparator.php | 50 - .../finder/Comparator/NumberComparator.php | 78 - .../Exception/AccessDeniedException.php | 19 - .../Exception/DirectoryNotFoundException.php | 19 - lib/symfony/finder/Finder.php | 806 - lib/symfony/finder/Gitignore.php | 93 - lib/symfony/finder/Glob.php | 111 - .../finder/Iterator/CustomFilterIterator.php | 64 - .../Iterator/DateRangeFilterIterator.php | 61 - .../Iterator/DepthRangeFilterIterator.php | 51 - .../ExcludeDirectoryFilterIterator.php | 96 - .../Iterator/FileTypeFilterIterator.php | 56 - .../Iterator/FilecontentFilterIterator.php | 61 - .../Iterator/FilenameFilterIterator.php | 50 - lib/symfony/finder/Iterator/LazyIterator.php | 32 - .../Iterator/MultiplePcreFilterIterator.php | 117 - .../finder/Iterator/PathFilterIterator.php | 59 - .../Iterator/RecursiveDirectoryIterator.php | 168 - .../Iterator/SizeRangeFilterIterator.php | 60 - .../finder/Iterator/SortableIterator.php | 104 - .../Iterator/VcsIgnoredFilterIterator.php | 151 - lib/symfony/finder/LICENSE | 19 - lib/symfony/finder/README.md | 14 - lib/symfony/finder/SplFileInfo.php | 88 - lib/symfony/finder/composer.json | 30 - lib/symfony/form/AbstractExtension.php | 198 - lib/symfony/form/AbstractRendererEngine.php | 206 - lib/symfony/form/AbstractType.php | 66 - lib/symfony/form/AbstractTypeExtension.php | 48 - lib/symfony/form/Button.php | 455 - lib/symfony/form/ButtonBuilder.php | 744 - lib/symfony/form/ButtonTypeInterface.php | 21 - lib/symfony/form/CHANGELOG.md | 567 - lib/symfony/form/CallbackTransformer.php | 44 - .../form/ChoiceList/ArrayChoiceList.php | 238 - lib/symfony/form/ChoiceList/ChoiceList.php | 159 - .../form/ChoiceList/ChoiceListInterface.php | 140 - .../Factory/Cache/AbstractStaticOption.php | 64 - .../ChoiceList/Factory/Cache/ChoiceAttr.php | 27 - .../Factory/Cache/ChoiceFieldName.php | 27 - .../ChoiceList/Factory/Cache/ChoiceFilter.php | 27 - .../ChoiceList/Factory/Cache/ChoiceLabel.php | 27 - .../ChoiceList/Factory/Cache/ChoiceLoader.php | 52 - .../Cache/ChoiceTranslationParameters.php | 27 - .../ChoiceList/Factory/Cache/ChoiceValue.php | 27 - .../form/ChoiceList/Factory/Cache/GroupBy.php | 27 - .../Factory/Cache/PreferredChoice.php | 27 - .../Factory/CachingFactoryDecorator.php | 254 - .../Factory/ChoiceListFactoryInterface.php | 88 - .../Factory/DefaultChoiceListFactory.php | 322 - .../Factory/PropertyAccessDecorator.php | 239 - .../form/ChoiceList/LazyChoiceList.php | 103 - .../Loader/AbstractChoiceLoader.php | 79 - .../Loader/CallbackChoiceLoader.php | 35 - .../Loader/ChoiceLoaderInterface.php | 76 - .../Loader/FilterChoiceLoaderDecorator.php | 70 - .../Loader/IntlCallbackChoiceLoader.php | 44 - .../form/ChoiceList/View/ChoiceGroupView.php | 47 - .../form/ChoiceList/View/ChoiceListView.php | 59 - .../form/ChoiceList/View/ChoiceView.php | 54 - lib/symfony/form/ClearableErrorsInterface.php | 29 - lib/symfony/form/ClickableInterface.php | 27 - lib/symfony/form/Command/DebugCommand.php | 292 - .../form/Console/Descriptor/Descriptor.php | 207 - .../Console/Descriptor/JsonDescriptor.php | 118 - .../Console/Descriptor/TextDescriptor.php | 222 - .../form/Console/Helper/DescriptorHelper.php | 33 - lib/symfony/form/DataAccessorInterface.php | 65 - lib/symfony/form/DataMapperInterface.php | 62 - lib/symfony/form/DataTransformerInterface.php | 92 - .../form/DependencyInjection/FormPass.php | 146 - lib/symfony/form/Event/PostSetDataEvent.php | 23 - lib/symfony/form/Event/PostSubmitEvent.php | 24 - lib/symfony/form/Event/PreSetDataEvent.php | 25 - lib/symfony/form/Event/PreSubmitEvent.php | 25 - lib/symfony/form/Event/SubmitEvent.php | 24 - .../form/Exception/AccessException.php | 16 - .../Exception/AlreadySubmittedException.php | 22 - .../form/Exception/BadMethodCallException.php | 21 - .../form/Exception/ErrorMappingException.php | 16 - .../form/Exception/ExceptionInterface.php | 21 - .../Exception/InvalidArgumentException.php | 21 - .../InvalidConfigurationException.php | 16 - lib/symfony/form/Exception/LogicException.php | 21 - .../form/Exception/OutOfBoundsException.php | 21 - .../form/Exception/RuntimeException.php | 21 - .../form/Exception/StringCastException.php | 16 - .../TransformationFailedException.php | 52 - .../Exception/UnexpectedTypeException.php | 20 - .../form/Extension/Core/CoreExtension.php | 89 - .../Core/DataAccessor/CallbackAccessor.php | 64 - .../Core/DataAccessor/ChainAccessor.php | 90 - .../DataAccessor/PropertyPathAccessor.php | 108 - .../Core/DataMapper/CheckboxListMapper.php | 75 - .../Extension/Core/DataMapper/DataMapper.php | 91 - .../Core/DataMapper/PropertyPathMapper.php | 118 - .../Core/DataMapper/RadioListMapper.php | 74 - .../ArrayToPartsTransformer.php | 84 - .../BaseDateTimeTransformer.php | 55 - .../BooleanToStringTransformer.php | 85 - .../ChoiceToValueTransformer.php | 53 - .../ChoicesToValuesTransformer.php | 73 - .../DataTransformer/DataTransformerChain.php | 90 - .../DateIntervalToArrayTransformer.php | 171 - .../DateIntervalToStringTransformer.php | 101 - ...DateTimeImmutableToDateTimeTransformer.php | 67 - .../DateTimeToArrayTransformer.php | 184 - ...ateTimeToHtml5LocalDateTimeTransformer.php | 106 - .../DateTimeToLocalizedStringTransformer.php | 208 - .../DateTimeToRfc3339Transformer.php | 91 - .../DateTimeToStringTransformer.php | 140 - .../DateTimeToTimestampTransformer.php | 80 - .../DateTimeZoneToStringTransformer.php | 82 - .../IntegerToLocalizedStringTransformer.php | 59 - .../IntlTimeZoneToStringTransformer.php | 84 - .../MoneyToLocalizedStringTransformer.php | 74 - .../NumberToLocalizedStringTransformer.php | 265 - .../PercentToLocalizedStringTransformer.php | 249 - .../StringToFloatTransformer.php | 65 - .../UlidToStringTransformer.php | 75 - .../UuidToStringTransformer.php | 77 - .../ValueToDuplicatesTransformer.php | 85 - .../WeekToArrayTransformer.php | 105 - .../EventListener/FixUrlProtocolListener.php | 48 - .../EventListener/MergeCollectionListener.php | 113 - .../Core/EventListener/ResizeFormListener.php | 169 - .../TransformationFailureListener.php | 65 - .../Core/EventListener/TrimListener.php | 41 - .../form/Extension/Core/Type/BaseType.php | 161 - .../form/Extension/Core/Type/BirthdayType.php | 52 - .../form/Extension/Core/Type/ButtonType.php | 49 - .../form/Extension/Core/Type/CheckboxType.php | 84 - .../form/Extension/Core/Type/ChoiceType.php | 501 - .../Extension/Core/Type/CollectionType.php | 142 - .../form/Extension/Core/Type/ColorType.php | 98 - .../form/Extension/Core/Type/CountryType.php | 72 - .../form/Extension/Core/Type/CurrencyType.php | 69 - .../Extension/Core/Type/DateIntervalType.php | 291 - .../form/Extension/Core/Type/DateTimeType.php | 362 - .../form/Extension/Core/Type/DateType.php | 405 - .../form/Extension/Core/Type/EmailType.php | 49 - .../form/Extension/Core/Type/EnumType.php | 57 - .../form/Extension/Core/Type/FileType.php | 255 - .../form/Extension/Core/Type/FormType.php | 245 - .../form/Extension/Core/Type/HiddenType.php | 46 - .../form/Extension/Core/Type/IntegerType.php | 77 - .../form/Extension/Core/Type/LanguageType.php | 96 - .../form/Extension/Core/Type/LocaleType.php | 69 - .../form/Extension/Core/Type/MoneyType.php | 149 - .../form/Extension/Core/Type/NumberType.php | 102 - .../form/Extension/Core/Type/PasswordType.php | 63 - .../form/Extension/Core/Type/PercentType.php | 105 - .../form/Extension/Core/Type/RadioType.php | 49 - .../form/Extension/Core/Type/RangeType.php | 49 - .../form/Extension/Core/Type/RepeatedType.php | 80 - .../form/Extension/Core/Type/ResetType.php | 39 - .../form/Extension/Core/Type/SearchType.php | 49 - .../form/Extension/Core/Type/SubmitType.php | 60 - .../form/Extension/Core/Type/TelType.php | 49 - .../form/Extension/Core/Type/TextType.php | 67 - .../form/Extension/Core/Type/TextareaType.php | 44 - .../form/Extension/Core/Type/TimeType.php | 388 - .../form/Extension/Core/Type/TimezoneType.php | 143 - .../Type/TransformationFailureExtension.php | 45 - .../form/Extension/Core/Type/UlidType.php | 49 - .../form/Extension/Core/Type/UrlType.php | 77 - .../form/Extension/Core/Type/UuidType.php | 49 - .../form/Extension/Core/Type/WeekType.php | 195 - .../form/Extension/Csrf/CsrfExtension.php | 45 - .../EventListener/CsrfValidationListener.php | 81 - .../Csrf/Type/FormTypeCsrfExtension.php | 110 - .../DataCollector/DataCollectorExtension.php | 40 - .../EventListener/DataCollectorListener.php | 75 - .../DataCollector/FormDataCollector.php | 343 - .../FormDataCollectorInterface.php | 85 - .../DataCollector/FormDataExtractor.php | 168 - .../FormDataExtractorInterface.php | 51 - .../Proxy/ResolvedTypeDataCollectorProxy.php | 140 - .../ResolvedTypeFactoryDataCollectorProxy.php | 46 - .../Type/DataCollectorTypeExtension.php | 53 - .../DependencyInjectionExtension.php | 111 - .../HttpFoundationExtension.php | 29 - .../HttpFoundationRequestHandler.php | 131 - .../Type/FormTypeHttpFoundationExtension.php | 47 - .../Extension/Validator/Constraints/Form.php | 36 - .../Validator/Constraints/FormValidator.php | 279 - .../EventListener/ValidationListener.php | 59 - .../Validator/Type/BaseValidatorExtension.php | 59 - .../Type/FormTypeValidatorExtension.php | 90 - .../Type/RepeatedTypeValidatorExtension.php | 46 - .../Type/SubmitTypeValidatorExtension.php | 28 - .../Type/UploadValidatorExtension.php | 56 - .../Extension/Validator/Util/ServerParams.php | 25 - .../Validator/ValidatorExtension.php | 67 - .../Validator/ValidatorTypeGuesser.php | 283 - .../Validator/ViolationMapper/MappingRule.php | 87 - .../ViolationMapper/RelativePath.php | 38 - .../ViolationMapper/ViolationMapper.php | 343 - .../ViolationMapperInterface.php | 29 - .../ViolationMapper/ViolationPath.php | 256 - .../ViolationMapper/ViolationPathIterator.php | 30 - lib/symfony/form/FileUploadError.php | 19 - lib/symfony/form/Form.php | 1194 - lib/symfony/form/FormBuilder.php | 254 - lib/symfony/form/FormBuilderInterface.php | 82 - lib/symfony/form/FormConfigBuilder.php | 811 - .../form/FormConfigBuilderInterface.php | 254 - lib/symfony/form/FormConfigInterface.php | 249 - lib/symfony/form/FormError.php | 134 - lib/symfony/form/FormErrorIterator.php | 316 - lib/symfony/form/FormEvent.php | 62 - lib/symfony/form/FormEvents.php | 113 - lib/symfony/form/FormExtensionInterface.php | 63 - lib/symfony/form/FormFactory.php | 122 - lib/symfony/form/FormFactoryBuilder.php | 187 - .../form/FormFactoryBuilderInterface.php | 98 - lib/symfony/form/FormFactoryInterface.php | 102 - lib/symfony/form/FormInterface.php | 328 - lib/symfony/form/FormRegistry.php | 176 - lib/symfony/form/FormRegistryInterface.php | 52 - lib/symfony/form/FormRenderer.php | 303 - .../form/FormRendererEngineInterface.php | 136 - lib/symfony/form/FormRendererInterface.php | 95 - .../form/FormTypeExtensionInterface.php | 59 - lib/symfony/form/FormTypeGuesserChain.php | 103 - lib/symfony/form/FormTypeGuesserInterface.php | 53 - lib/symfony/form/FormTypeInterface.php | 87 - lib/symfony/form/FormView.php | 180 - lib/symfony/form/Forms.php | 87 - lib/symfony/form/Guess/Guess.php | 105 - lib/symfony/form/Guess/TypeGuess.php | 59 - lib/symfony/form/Guess/ValueGuess.php | 44 - lib/symfony/form/LICENSE | 19 - lib/symfony/form/NativeRequestHandler.php | 256 - lib/symfony/form/PreloadedExtension.php | 87 - lib/symfony/form/README.md | 13 - lib/symfony/form/RequestHandlerInterface.php | 36 - lib/symfony/form/ResolvedFormType.php | 224 - lib/symfony/form/ResolvedFormTypeFactory.php | 26 - .../form/ResolvedFormTypeFactoryInterface.php | 36 - .../form/ResolvedFormTypeInterface.php | 92 - .../form/Resources/config/validation.xml | 13 - .../Resources/translations/validators.af.xlf | 139 - .../Resources/translations/validators.ar.xlf | 139 - .../Resources/translations/validators.az.xlf | 139 - .../Resources/translations/validators.be.xlf | 139 - .../Resources/translations/validators.bg.xlf | 139 - .../Resources/translations/validators.bs.xlf | 139 - .../Resources/translations/validators.ca.xlf | 139 - .../Resources/translations/validators.cs.xlf | 139 - .../Resources/translations/validators.da.xlf | 139 - .../Resources/translations/validators.de.xlf | 139 - .../Resources/translations/validators.el.xlf | 139 - .../Resources/translations/validators.en.xlf | 139 - .../Resources/translations/validators.es.xlf | 139 - .../Resources/translations/validators.et.xlf | 139 - .../Resources/translations/validators.eu.xlf | 139 - .../Resources/translations/validators.fa.xlf | 139 - .../Resources/translations/validators.fi.xlf | 139 - .../Resources/translations/validators.fr.xlf | 139 - .../Resources/translations/validators.gl.xlf | 139 - .../Resources/translations/validators.he.xlf | 139 - .../Resources/translations/validators.hr.xlf | 139 - .../Resources/translations/validators.hu.xlf | 139 - .../Resources/translations/validators.hy.xlf | 139 - .../Resources/translations/validators.id.xlf | 139 - .../Resources/translations/validators.it.xlf | 139 - .../Resources/translations/validators.ja.xlf | 139 - .../Resources/translations/validators.lb.xlf | 139 - .../Resources/translations/validators.lt.xlf | 139 - .../Resources/translations/validators.lv.xlf | 139 - .../Resources/translations/validators.mn.xlf | 139 - .../Resources/translations/validators.my.xlf | 139 - .../Resources/translations/validators.nb.xlf | 139 - .../Resources/translations/validators.nl.xlf | 139 - .../Resources/translations/validators.nn.xlf | 139 - .../Resources/translations/validators.no.xlf | 139 - .../Resources/translations/validators.pl.xlf | 139 - .../Resources/translations/validators.pt.xlf | 139 - .../translations/validators.pt_BR.xlf | 139 - .../Resources/translations/validators.ro.xlf | 139 - .../Resources/translations/validators.ru.xlf | 139 - .../Resources/translations/validators.sk.xlf | 139 - .../Resources/translations/validators.sl.xlf | 139 - .../Resources/translations/validators.sq.xlf | 139 - .../translations/validators.sr_Cyrl.xlf | 139 - .../translations/validators.sr_Latn.xlf | 139 - .../Resources/translations/validators.sv.xlf | 139 - .../Resources/translations/validators.th.xlf | 139 - .../Resources/translations/validators.tl.xlf | 139 - .../Resources/translations/validators.tr.xlf | 139 - .../Resources/translations/validators.uk.xlf | 139 - .../Resources/translations/validators.ur.xlf | 139 - .../Resources/translations/validators.uz.xlf | 139 - .../Resources/translations/validators.vi.xlf | 139 - .../translations/validators.zh_CN.xlf | 139 - .../translations/validators.zh_TW.xlf | 139 - lib/symfony/form/ReversedTransformer.php | 46 - lib/symfony/form/SubmitButton.php | 55 - lib/symfony/form/SubmitButtonBuilder.php | 30 - .../form/SubmitButtonTypeInterface.php | 21 - .../form/Test/FormBuilderInterface.php | 18 - .../form/Test/FormIntegrationTestCase.php | 57 - lib/symfony/form/Test/FormInterface.php | 18 - .../form/Test/FormPerformanceTestCase.php | 66 - .../Test/Traits/ValidatorExtensionTrait.php | 44 - lib/symfony/form/Test/TypeTestCase.php | 65 - lib/symfony/form/Util/FormUtil.php | 44 - .../form/Util/InheritDataAwareIterator.php | 47 - .../form/Util/OptionsResolverWrapper.php | 110 - lib/symfony/form/Util/OrderedHashMap.php | 192 - .../form/Util/OrderedHashMapIterator.php | 172 - lib/symfony/form/Util/ServerParams.php | 101 - lib/symfony/form/Util/StringUtil.php | 57 - lib/symfony/form/composer.json | 70 - lib/symfony/framework-bundle/CHANGELOG.md | 492 - .../AbstractPhpFileCacheWarmer.php | 89 - .../CacheWarmer/AnnotationsCacheWarmer.php | 113 - .../CachePoolClearerCacheWarmer.php | 64 - .../CacheWarmer/ConfigBuilderCacheWarmer.php | 91 - .../CacheWarmer/RouterCacheWarmer.php | 68 - .../CacheWarmer/SerializerCacheWarmer.php | 87 - .../CacheWarmer/TranslationsCacheWarmer.php | 71 - .../CacheWarmer/ValidatorCacheWarmer.php | 101 - .../framework-bundle/Command/AboutCommand.php | 136 - .../Command/AbstractConfigCommand.php | 159 - .../Command/AssetsInstallCommand.php | 279 - .../Command/BuildDebugContainerTrait.php | 64 - .../Command/CacheClearCommand.php | 261 - .../Command/CachePoolClearCommand.php | 131 - .../Command/CachePoolDeleteCommand.php | 98 - .../Command/CachePoolListCommand.php | 68 - .../Command/CachePoolPruneCommand.php | 74 - .../Command/CacheWarmupCommand.php | 87 - .../Command/ConfigDebugCommand.php | 240 - .../Command/ConfigDumpReferenceCommand.php | 190 - .../Command/ContainerDebugCommand.php | 313 - .../Command/ContainerLintCommand.php | 134 - .../Command/DebugAutowiringCommand.php | 177 - .../Command/EventDispatcherDebugCommand.php | 164 - .../Command/RouterDebugCommand.php | 176 - .../Command/RouterMatchCommand.php | 129 - .../Command/SecretsDecryptToLocalCommand.php | 104 - .../SecretsEncryptFromLocalCommand.php | 79 - .../Command/SecretsGenerateKeysCommand.php | 126 - .../Command/SecretsListCommand.php | 109 - .../Command/SecretsRemoveCommand.php | 102 - .../Command/SecretsSetCommand.php | 149 - .../Command/TranslationDebugCommand.php | 418 - .../Command/TranslationUpdateCommand.php | 473 - .../Command/WorkflowDumpCommand.php | 148 - .../Command/XliffLintCommand.php | 63 - .../Command/YamlLintCommand.php | 62 - .../framework-bundle/Console/Application.php | 212 - .../Console/Descriptor/Descriptor.php | 380 - .../Console/Descriptor/JsonDescriptor.php | 420 - .../Console/Descriptor/MarkdownDescriptor.php | 414 - .../Console/Descriptor/TextDescriptor.php | 638 - .../Console/Descriptor/XmlDescriptor.php | 570 - .../Console/Helper/DescriptorHelper.php | 37 - .../Controller/AbstractController.php | 476 - .../Controller/ControllerResolver.php | 44 - .../Controller/RedirectController.php | 189 - .../Controller/TemplateController.php | 72 - .../DataCollector/AbstractDataCollector.php | 35 - .../DataCollector/RouterDataCollector.php | 37 - .../TemplateAwareDataCollectorInterface.php | 22 - .../AddAnnotationsCachedReaderPass.php | 46 - .../Compiler/AddDebugLogProcessorPass.php | 43 - .../AddExpressionLanguageProvidersPass.php | 38 - .../Compiler/AssetsContextPass.php | 44 - .../ContainerBuilderDebugDumpPass.php | 35 - .../Compiler/DataCollectorTranslatorPass.php | 35 - .../Compiler/LoggingTranslatorPass.php | 54 - .../Compiler/ProfilerPass.php | 62 - ...oveUnusedSessionMarshallingHandlerPass.php | 43 - .../Compiler/SessionPass.php | 72 - .../TestServiceContainerRealRefPass.php | 54 - .../TestServiceContainerWeakRefPass.php | 71 - .../Compiler/UnusedTagsPass.php | 129 - .../Compiler/WorkflowGuardListenerPass.php | 48 - .../DependencyInjection/Configuration.php | 2075 -- .../FrameworkExtension.php | 2717 -- .../SuggestMissingPackageSubscriber.php | 82 - .../framework-bundle/FrameworkBundle.php | 180 - .../framework-bundle/HttpCache/HttpCache.php | 101 - .../Kernel/MicroKernelTrait.php | 234 - .../framework-bundle/KernelBrowser.php | 262 - lib/symfony/framework-bundle/LICENSE | 19 - lib/symfony/framework-bundle/README.md | 13 - .../Resources/bin/check-unused-known-tags.php | 23 - .../Resources/config/annotations.php | 83 - .../Resources/config/assets.php | 94 - .../Resources/config/cache.php | 267 - .../Resources/config/cache_debug.php | 39 - .../Resources/config/collectors.php | 78 - .../Resources/config/console.php | 331 - .../Resources/config/debug.php | 50 - .../Resources/config/debug_prod.php | 39 - .../Resources/config/error_renderer.php | 38 - .../framework-bundle/Resources/config/esi.php | 25 - .../Resources/config/form.php | 152 - .../Resources/config/form_csrf.php | 29 - .../Resources/config/form_debug.php | 38 - .../Resources/config/fragment_listener.php | 22 - .../Resources/config/fragment_renderer.php | 71 - .../Resources/config/http_client.php | 64 - .../Resources/config/http_client_debug.php | 25 - .../Resources/config/identity_translator.php | 26 - .../Resources/config/lock.php | 30 - .../Resources/config/mailer.php | 81 - .../Resources/config/mailer_debug.php | 27 - .../Resources/config/mailer_transports.php | 91 - .../Resources/config/messenger.php | 215 - .../Resources/config/messenger_debug.php | 25 - .../Resources/config/mime_type.php | 26 - .../Resources/config/notifier.php | 119 - .../Resources/config/notifier_debug.php | 22 - .../Resources/config/notifier_transports.php | 277 - .../Resources/config/profiling.php | 39 - .../Resources/config/property_access.php | 30 - .../Resources/config/property_info.php | 52 - .../Resources/config/rate_limiter.php | 30 - .../Resources/config/request.php | 22 - .../Resources/config/routing.php | 182 - .../Resources/config/routing/errors.xml | 12 - .../Resources/config/schema/symfony-1.0.xsd | 829 - .../Resources/config/secrets.php | 33 - .../Resources/config/security_csrf.php | 52 - .../Resources/config/serializer.php | 222 - .../Resources/config/services.php | 218 - .../Resources/config/session.php | 174 - .../framework-bundle/Resources/config/ssi.php | 25 - .../Resources/config/test.php | 60 - .../Resources/config/translation.php | 162 - .../Resources/config/translation_debug.php | 30 - .../config/translation_providers.php | 66 - .../framework-bundle/Resources/config/uid.php | 41 - .../Resources/config/validator.php | 108 - .../Resources/config/validator_debug.php | 38 - .../framework-bundle/Resources/config/web.php | 113 - .../Resources/config/web_link.php | 21 - .../Resources/config/workflow.php | 50 - .../AnnotatedRouteControllerLoader.php | 52 - .../Routing/DelegatingLoader.php | 95 - .../RedirectableCompiledUrlMatcher.php | 39 - .../Routing/RouteLoaderInterface.php | 19 - .../framework-bundle/Routing/Router.php | 210 - .../Secrets/AbstractVault.php | 49 - .../framework-bundle/Secrets/DotenvVault.php | 107 - .../framework-bundle/Secrets/SodiumVault.php | 233 - .../Session/DeprecatedSessionFactory.php | 46 - .../Session/ServiceSessionFactory.php | 41 - .../Translation/Translator.php | 187 - lib/symfony/framework-bundle/composer.json | 118 - lib/symfony/http-foundation/AcceptHeader.php | 168 - .../http-foundation/AcceptHeaderItem.php | 177 - .../http-foundation/BinaryFileResponse.php | 407 - lib/symfony/http-foundation/CHANGELOG.md | 296 - lib/symfony/http-foundation/Cookie.php | 422 - .../Exception/BadRequestException.php | 19 - .../Exception/ConflictingHeadersException.php | 21 - .../Exception/JsonException.php | 21 - .../Exception/RequestExceptionInterface.php | 21 - .../Exception/SessionNotFoundException.php | 27 - .../SuspiciousOperationException.php | 20 - .../ExpressionRequestMatcher.php | 47 - .../File/Exception/AccessDeniedException.php | 25 - .../Exception/CannotWriteFileException.php | 21 - .../File/Exception/ExtensionFileException.php | 21 - .../File/Exception/FileException.php | 21 - .../File/Exception/FileNotFoundException.php | 25 - .../File/Exception/FormSizeFileException.php | 21 - .../File/Exception/IniSizeFileException.php | 21 - .../File/Exception/NoFileException.php | 21 - .../File/Exception/NoTmpDirFileException.php | 21 - .../File/Exception/PartialFileException.php | 21 - .../Exception/UnexpectedTypeException.php | 20 - .../File/Exception/UploadException.php | 21 - lib/symfony/http-foundation/File/File.php | 152 - lib/symfony/http-foundation/File/Stream.php | 31 - .../http-foundation/File/UploadedFile.php | 290 - lib/symfony/http-foundation/FileBag.php | 140 - lib/symfony/http-foundation/HeaderBag.php | 295 - lib/symfony/http-foundation/HeaderUtils.php | 293 - lib/symfony/http-foundation/InputBag.php | 113 - lib/symfony/http-foundation/IpUtils.php | 216 - lib/symfony/http-foundation/JsonResponse.php | 221 - lib/symfony/http-foundation/LICENSE | 19 - lib/symfony/http-foundation/ParameterBag.php | 228 - lib/symfony/http-foundation/README.md | 28 - .../AbstractRequestRateLimiter.php | 71 - .../RequestRateLimiterInterface.php | 30 - .../http-foundation/RedirectResponse.php | 109 - lib/symfony/http-foundation/Request.php | 2148 -- .../http-foundation/RequestMatcher.php | 196 - .../RequestMatcherInterface.php | 27 - lib/symfony/http-foundation/RequestStack.php | 128 - lib/symfony/http-foundation/Response.php | 1286 - .../http-foundation/ResponseHeaderBag.php | 291 - lib/symfony/http-foundation/ServerBag.php | 99 - .../Session/Attribute/AttributeBag.php | 152 - .../Attribute/AttributeBagInterface.php | 61 - .../Attribute/NamespacedAttributeBag.php | 161 - .../Session/Flash/AutoExpireFlashBag.php | 161 - .../Session/Flash/FlashBag.php | 152 - .../Session/Flash/FlashBagInterface.php | 88 - .../http-foundation/Session/Session.php | 285 - .../Session/SessionBagInterface.php | 46 - .../Session/SessionBagProxy.php | 95 - .../Session/SessionFactory.php | 40 - .../Session/SessionFactoryInterface.php | 20 - .../Session/SessionInterface.php | 166 - .../http-foundation/Session/SessionUtils.php | 59 - .../Handler/AbstractSessionHandler.php | 155 - .../Storage/Handler/IdentityMarshaller.php | 42 - .../Handler/MarshallingSessionHandler.php | 108 - .../Handler/MemcachedSessionHandler.php | 135 - .../Handler/MigratingSessionHandler.php | 139 - .../Storage/Handler/MongoDbSessionHandler.php | 193 - .../Handler/NativeFileSessionHandler.php | 55 - .../Storage/Handler/NullSessionHandler.php | 80 - .../Storage/Handler/PdoSessionHandler.php | 943 - .../Storage/Handler/RedisSessionHandler.php | 137 - .../Storage/Handler/SessionHandlerFactory.php | 91 - .../Storage/Handler/StrictSessionHandler.php | 118 - .../Session/Storage/MetadataBag.php | 167 - .../Storage/MockArraySessionStorage.php | 252 - .../Storage/MockFileSessionStorage.php | 160 - .../Storage/MockFileSessionStorageFactory.php | 42 - .../Session/Storage/NativeSessionStorage.php | 506 - .../Storage/NativeSessionStorageFactory.php | 49 - .../Storage/PhpBridgeSessionStorage.php | 64 - .../PhpBridgeSessionStorageFactory.php | 47 - .../Session/Storage/Proxy/AbstractProxy.php | 118 - .../Storage/Proxy/SessionHandlerProxy.php | 111 - .../Session/Storage/ServiceSessionFactory.php | 38 - .../SessionStorageFactoryInterface.php | 25 - .../Storage/SessionStorageInterface.php | 131 - .../http-foundation/StreamedResponse.php | 139 - lib/symfony/http-foundation/UrlHelper.php | 102 - lib/symfony/http-foundation/composer.json | 43 - .../Attribute/ArgumentInterface.php | 23 - .../http-kernel/Attribute/AsController.php | 23 - lib/symfony/http-kernel/Bundle/Bundle.php | 163 - .../http-kernel/Bundle/BundleInterface.php | 71 - lib/symfony/http-kernel/CHANGELOG.md | 317 - .../CacheClearer/CacheClearerInterface.php | 25 - .../CacheClearer/ChainCacheClearer.php | 42 - .../CacheClearer/Psr6CacheClearer.php | 76 - .../http-kernel/CacheWarmer/CacheWarmer.php | 32 - .../CacheWarmer/CacheWarmerAggregate.php | 126 - .../CacheWarmer/CacheWarmerInterface.php | 32 - .../CacheWarmer/WarmableInterface.php | 27 - .../http-kernel/Config/FileLocator.php | 46 - .../Controller/ArgumentResolver.php | 98 - .../ArgumentResolver/DefaultValueResolver.php | 40 - .../NotTaggedControllerValueResolver.php | 82 - .../RequestAttributeValueResolver.php | 40 - .../ArgumentResolver/RequestValueResolver.php | 40 - .../ArgumentResolver/ServiceValueResolver.php | 93 - .../ArgumentResolver/SessionValueResolver.php | 50 - .../TraceableValueResolver.php | 62 - .../VariadicValueResolver.php | 46 - .../Controller/ArgumentResolverInterface.php | 32 - .../ArgumentValueResolverInterface.php | 37 - .../ContainerControllerResolver.php | 76 - .../Controller/ControllerReference.php | 44 - .../Controller/ControllerResolver.php | 220 - .../ControllerResolverInterface.php | 41 - .../Controller/ErrorController.php | 62 - .../Controller/TraceableArgumentResolver.php | 44 - .../TraceableControllerResolver.php | 44 - .../ControllerMetadata/ArgumentMetadata.php | 163 - .../ArgumentMetadataFactory.php | 78 - .../ArgumentMetadataFactoryInterface.php | 27 - .../DataCollector/AjaxDataCollector.php | 38 - .../DataCollector/ConfigDataCollector.php | 275 - .../DataCollector/DataCollector.php | 112 - .../DataCollector/DataCollectorInterface.php | 36 - .../DataCollector/DumpDataCollector.php | 292 - .../DataCollector/EventDataCollector.php | 137 - .../DataCollector/ExceptionDataCollector.php | 85 - .../LateDataCollectorInterface.php | 25 - .../DataCollector/LoggerDataCollector.php | 358 - .../DataCollector/MemoryDataCollector.php | 113 - .../DataCollector/RequestDataCollector.php | 504 - .../DataCollector/RouterDataCollector.php | 108 - .../DataCollector/TimeDataCollector.php | 143 - .../http-kernel/Debug/FileLinkFormatter.php | 116 - .../Debug/TraceableEventDispatcher.php | 91 - .../AddAnnotatedClassesToCachePass.php | 146 - .../ConfigurableExtension.php | 42 - .../ControllerArgumentValueResolverPass.php | 68 - .../DependencyInjection/Extension.php | 44 - .../FragmentRendererPass.php | 67 - .../LazyLoadingFragmentHandler.php | 51 - .../DependencyInjection/LoggerPass.php | 41 - .../MergeExtensionConfigurationPass.php | 44 - ...RegisterControllerArgumentLocatorsPass.php | 224 - .../RegisterLocaleAwareServicesPass.php | 62 - ...oveEmptyControllerArgumentLocatorsPass.php | 79 - .../ResettableServicePass.php | 79 - .../DependencyInjection/ServicesResetter.php | 51 - .../Event/ControllerArgumentsEvent.php | 61 - .../http-kernel/Event/ControllerEvent.php | 48 - .../http-kernel/Event/ExceptionEvent.php | 76 - .../http-kernel/Event/FinishRequestEvent.php | 21 - lib/symfony/http-kernel/Event/KernelEvent.php | 92 - .../http-kernel/Event/RequestEvent.php | 58 - .../http-kernel/Event/ResponseEvent.php | 47 - .../http-kernel/Event/TerminateEvent.php | 41 - lib/symfony/http-kernel/Event/ViewEvent.php | 61 - .../EventListener/AbstractSessionListener.php | 315 - .../AbstractTestSessionListener.php | 120 - .../AddRequestFormatsListener.php | 52 - .../EventListener/DebugHandlersListener.php | 190 - .../DisallowRobotsIndexingListener.php | 43 - .../EventListener/DumpListener.php | 63 - .../EventListener/ErrorListener.php | 186 - .../EventListener/FragmentListener.php | 99 - .../EventListener/LocaleAwareListener.php | 77 - .../EventListener/LocaleListener.php | 95 - .../EventListener/ProfilerListener.php | 150 - .../EventListener/ResponseListener.php | 68 - .../EventListener/RouterListener.php | 174 - .../EventListener/SessionListener.php | 60 - .../StreamedResponseListener.php | 51 - .../EventListener/SurrogateListener.php | 67 - .../EventListener/TestSessionListener.php | 46 - .../EventListener/ValidateRequestListener.php | 55 - .../Exception/AccessDeniedHttpException.php | 35 - .../Exception/BadRequestHttpException.php | 34 - .../Exception/ConflictHttpException.php | 34 - ...ntrollerDoesNotReturnResponseException.php | 84 - .../Exception/GoneHttpException.php | 34 - .../http-kernel/Exception/HttpException.php | 62 - .../Exception/HttpExceptionInterface.php | 34 - .../Exception/InvalidMetadataException.php | 16 - .../Exception/LengthRequiredHttpException.php | 34 - .../MethodNotAllowedHttpException.php | 42 - .../Exception/NotAcceptableHttpException.php | 34 - .../Exception/NotFoundHttpException.php | 34 - .../PreconditionFailedHttpException.php | 34 - .../PreconditionRequiredHttpException.php | 36 - .../ServiceUnavailableHttpException.php | 44 - .../TooManyRequestsHttpException.php | 46 - .../Exception/UnauthorizedHttpException.php | 42 - .../UnexpectedSessionUsageException.php | 19 - .../UnprocessableEntityHttpException.php | 34 - .../UnsupportedMediaTypeHttpException.php | 34 - .../AbstractSurrogateFragmentRenderer.php | 103 - .../Fragment/EsiFragmentRenderer.php | 28 - .../http-kernel/Fragment/FragmentHandler.php | 113 - .../Fragment/FragmentRendererInterface.php | 40 - .../Fragment/FragmentUriGenerator.php | 93 - .../FragmentUriGeneratorInterface.php | 32 - .../Fragment/HIncludeFragmentRenderer.php | 104 - .../Fragment/InlineFragmentRenderer.php | 145 - .../Fragment/RoutableFragmentRenderer.php | 52 - .../Fragment/SsiFragmentRenderer.php | 28 - .../HttpCache/AbstractSurrogate.php | 136 - lib/symfony/http-kernel/HttpCache/Esi.php | 117 - .../http-kernel/HttpCache/HttpCache.php | 737 - .../HttpCache/ResponseCacheStrategy.php | 234 - .../ResponseCacheStrategyInterface.php | 37 - lib/symfony/http-kernel/HttpCache/Ssi.php | 100 - lib/symfony/http-kernel/HttpCache/Store.php | 489 - .../http-kernel/HttpCache/StoreInterface.php | 81 - .../HttpCache/SubRequestHandler.php | 92 - .../HttpCache/SurrogateInterface.php | 87 - lib/symfony/http-kernel/HttpClientKernel.php | 112 - lib/symfony/http-kernel/HttpKernel.php | 299 - lib/symfony/http-kernel/HttpKernelBrowser.php | 208 - .../http-kernel/HttpKernelInterface.php | 48 - lib/symfony/http-kernel/Kernel.php | 881 - lib/symfony/http-kernel/KernelEvents.php | 128 - lib/symfony/http-kernel/KernelInterface.php | 149 - lib/symfony/http-kernel/LICENSE | 19 - .../http-kernel/Log/DebugLoggerInterface.php | 45 - lib/symfony/http-kernel/Log/Logger.php | 124 - .../Profiler/FileProfilerStorage.php | 311 - lib/symfony/http-kernel/Profiler/Profile.php | 270 - lib/symfony/http-kernel/Profiler/Profiler.php | 253 - .../Profiler/ProfilerStorageInterface.php | 54 - lib/symfony/http-kernel/README.md | 31 - .../http-kernel/RebootableInterface.php | 30 - .../http-kernel/Resources/welcome.html.php | 123 - .../http-kernel/TerminableInterface.php | 32 - lib/symfony/http-kernel/UriSigner.php | 113 - lib/symfony/http-kernel/composer.json | 79 - lib/symfony/options-resolver/CHANGELOG.md | 81 - .../Debug/OptionsResolverIntrospector.php | 120 - .../Exception/AccessException.php | 22 - .../Exception/ExceptionInterface.php | 21 - .../Exception/InvalidArgumentException.php | 21 - .../Exception/InvalidOptionsException.php | 23 - .../Exception/MissingOptionsException.php | 23 - .../Exception/NoConfigurationException.php | 26 - .../Exception/NoSuchOptionException.php | 26 - .../Exception/OptionDefinitionException.php | 21 - .../Exception/UndefinedOptionsException.php | 24 - lib/symfony/options-resolver/LICENSE | 19 - .../options-resolver/OptionConfigurator.php | 139 - lib/symfony/options-resolver/Options.php | 22 - .../options-resolver/OptionsResolver.php | 1347 - lib/symfony/options-resolver/README.md | 15 - lib/symfony/options-resolver/composer.json | 31 - lib/symfony/polyfill-ctype/Ctype.php | 232 - lib/symfony/polyfill-ctype/LICENSE | 19 - lib/symfony/polyfill-ctype/README.md | 12 - lib/symfony/polyfill-ctype/bootstrap.php | 50 - lib/symfony/polyfill-ctype/bootstrap80.php | 46 - lib/symfony/polyfill-ctype/composer.json | 41 - .../polyfill-intl-grapheme/Grapheme.php | 247 - lib/symfony/polyfill-intl-grapheme/LICENSE | 19 - lib/symfony/polyfill-intl-grapheme/README.md | 31 - .../polyfill-intl-grapheme/bootstrap.php | 58 - .../polyfill-intl-grapheme/bootstrap80.php | 50 - .../polyfill-intl-grapheme/composer.json | 38 - lib/symfony/polyfill-intl-icu/Collator.php | 262 - lib/symfony/polyfill-intl-icu/Currencies.php | 43 - .../DateFormat/AmPmTransformer.php | 39 - .../DateFormat/DayOfWeekTransformer.php | 56 - .../DateFormat/DayOfYearTransformer.php | 39 - .../DateFormat/DayTransformer.php | 39 - .../DateFormat/FullTransformer.php | 312 - .../DateFormat/Hour1200Transformer.php | 52 - .../DateFormat/Hour1201Transformer.php | 52 - .../DateFormat/Hour2400Transformer.php | 51 - .../DateFormat/Hour2401Transformer.php | 54 - .../DateFormat/HourTransformer.php | 32 - .../DateFormat/MinuteTransformer.php | 41 - .../DateFormat/MonthTransformer.php | 127 - .../DateFormat/QuarterTransformer.php | 65 - .../DateFormat/SecondTransformer.php | 41 - .../DateFormat/TimezoneTransformer.php | 108 - .../DateFormat/Transformer.php | 65 - .../DateFormat/YearTransformer.php | 43 - .../Exception/ExceptionInterface.php | 21 - .../MethodArgumentNotImplementedException.php | 28 - ...odArgumentValueNotImplementedException.php | 37 - .../MethodNotImplementedException.php | 26 - .../Exception/NotImplementedException.php | 30 - .../Exception/RuntimeException.php | 21 - lib/symfony/polyfill-intl-icu/Icu.php | 117 - .../polyfill-intl-icu/IntlDateFormatter.php | 645 - lib/symfony/polyfill-intl-icu/LICENSE | 19 - lib/symfony/polyfill-intl-icu/Locale.php | 310 - .../polyfill-intl-icu/NumberFormatter.php | 835 - lib/symfony/polyfill-intl-icu/README.md | 23 - .../Resources/currencies.php | 1321 - .../Resources/stubs/Collator.php | 21 - .../Resources/stubs/IntlDateFormatter.php | 21 - .../Resources/stubs/Locale.php | 21 - .../Resources/stubs/NumberFormatter.php | 23 - lib/symfony/polyfill-intl-icu/bootstrap.php | 33 - lib/symfony/polyfill-intl-icu/bootstrap80.php | 25 - lib/symfony/polyfill-intl-icu/composer.json | 42 - lib/symfony/polyfill-intl-idn/Idn.php | 925 - lib/symfony/polyfill-intl-idn/Info.php | 23 - lib/symfony/polyfill-intl-idn/LICENSE | 19 - lib/symfony/polyfill-intl-idn/README.md | 12 - .../Resources/unidata/DisallowedRanges.php | 375 - .../Resources/unidata/Regex.php | 24 - .../Resources/unidata/deviation.php | 8 - .../Resources/unidata/disallowed.php | 2638 -- .../unidata/disallowed_STD3_mapped.php | 308 - .../unidata/disallowed_STD3_valid.php | 71 - .../Resources/unidata/ignored.php | 273 - .../Resources/unidata/mapped.php | 5778 ---- .../Resources/unidata/virama.php | 65 - lib/symfony/polyfill-intl-idn/bootstrap.php | 145 - lib/symfony/polyfill-intl-idn/bootstrap80.php | 125 - lib/symfony/polyfill-intl-idn/composer.json | 44 - lib/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 - lib/symfony/polyfill-mbstring/LICENSE | 19 - lib/symfony/polyfill-mbstring/Mbstring.php | 873 - lib/symfony/polyfill-mbstring/README.md | 13 - .../Resources/unidata/lowerCase.php | 1397 - .../Resources/unidata/titleCaseRegexp.php | 5 - .../Resources/unidata/upperCase.php | 1489 - lib/symfony/polyfill-mbstring/bootstrap.php | 147 - lib/symfony/polyfill-mbstring/bootstrap80.php | 143 - lib/symfony/polyfill-mbstring/composer.json | 41 - lib/symfony/polyfill-php72/LICENSE | 19 - lib/symfony/polyfill-php72/Php72.php | 217 - lib/symfony/polyfill-php72/README.md | 35 - lib/symfony/polyfill-php72/bootstrap.php | 57 - lib/symfony/polyfill-php72/composer.json | 35 - lib/symfony/polyfill-php73/LICENSE | 19 - lib/symfony/polyfill-php73/Php73.php | 43 - lib/symfony/polyfill-php73/README.md | 18 - .../Resources/stubs/JsonException.php | 16 - lib/symfony/polyfill-php73/bootstrap.php | 31 - lib/symfony/polyfill-php73/composer.json | 36 - lib/symfony/polyfill-php80/LICENSE | 19 - lib/symfony/polyfill-php80/Php80.php | 115 - lib/symfony/polyfill-php80/PhpToken.php | 103 - lib/symfony/polyfill-php80/README.md | 25 - .../Resources/stubs/Attribute.php | 22 - .../Resources/stubs/PhpToken.php | 7 - .../Resources/stubs/Stringable.php | 11 - .../Resources/stubs/UnhandledMatchError.php | 7 - .../Resources/stubs/ValueError.php | 7 - lib/symfony/polyfill-php80/bootstrap.php | 42 - lib/symfony/polyfill-php80/composer.json | 40 - lib/symfony/polyfill-php81/LICENSE | 19 - lib/symfony/polyfill-php81/Php81.php | 37 - lib/symfony/polyfill-php81/README.md | 17 - .../Resources/stubs/ReturnTypeWillChange.php | 11 - lib/symfony/polyfill-php81/bootstrap.php | 28 - lib/symfony/polyfill-php81/composer.json | 36 - lib/symfony/property-access/CHANGELOG.md | 70 - .../Exception/AccessException.php | 21 - .../Exception/ExceptionInterface.php | 21 - .../Exception/InvalidArgumentException.php | 21 - .../InvalidPropertyPathException.php | 21 - .../Exception/NoSuchIndexException.php | 21 - .../Exception/NoSuchPropertyException.php | 21 - .../Exception/OutOfBoundsException.php | 21 - .../Exception/RuntimeException.php | 21 - .../Exception/UnexpectedTypeException.php | 39 - .../UninitializedPropertyException.php | 21 - lib/symfony/property-access/LICENSE | 19 - .../property-access/PropertyAccess.php | 40 - .../property-access/PropertyAccessor.php | 748 - .../PropertyAccessorBuilder.php | 308 - .../PropertyAccessorInterface.php | 114 - lib/symfony/property-access/PropertyPath.php | 208 - .../property-access/PropertyPathBuilder.php | 281 - .../property-access/PropertyPathInterface.php | 88 - .../property-access/PropertyPathIterator.php | 48 - .../PropertyPathIteratorInterface.php | 36 - lib/symfony/property-access/README.md | 14 - lib/symfony/property-access/composer.json | 37 - lib/symfony/property-info/CHANGELOG.md | 39 - .../PropertyInfoConstructorPass.php | 54 - .../DependencyInjection/PropertyInfoPass.php | 75 - ...structorArgumentTypeExtractorInterface.php | 33 - .../Extractor/ConstructorExtractor.php | 47 - .../Extractor/PhpDocExtractor.php | 360 - .../Extractor/PhpStanExtractor.php | 289 - .../Extractor/ReflectionExtractor.php | 885 - .../Extractor/SerializerExtractor.php | 58 - lib/symfony/property-info/LICENSE | 19 - .../property-info/PhpStan/NameScope.php | 65 - .../PhpStan/NameScopeFactory.php | 70 - .../PropertyAccessExtractorInterface.php | 34 - .../PropertyDescriptionExtractorInterface.php | 34 - .../PropertyInfoCacheExtractor.php | 124 - .../property-info/PropertyInfoExtractor.php | 119 - .../PropertyInfoExtractorInterface.php | 23 - ...ropertyInitializableExtractorInterface.php | 25 - .../PropertyListExtractorInterface.php | 27 - .../property-info/PropertyReadInfo.php | 82 - .../PropertyReadInfoExtractorInterface.php | 25 - .../PropertyTypeExtractorInterface.php | 27 - .../property-info/PropertyWriteInfo.php | 123 - .../PropertyWriteInfoExtractorInterface.php | 25 - lib/symfony/property-info/README.md | 14 - lib/symfony/property-info/Type.php | 206 - .../property-info/Util/PhpDocTypeHelper.php | 191 - .../property-info/Util/PhpStanTypeHelper.php | 192 - lib/symfony/property-info/composer.json | 57 - lib/symfony/routing/Alias.php | 96 - lib/symfony/routing/Annotation/Route.php | 272 - lib/symfony/routing/CHANGELOG.md | 296 - lib/symfony/routing/CompiledRoute.php | 173 - .../RoutingResolverPass.php | 53 - .../routing/Exception/ExceptionInterface.php | 21 - .../Exception/InvalidArgumentException.php | 16 - .../Exception/InvalidParameterException.php | 21 - .../Exception/MethodNotAllowedException.php | 50 - .../MissingMandatoryParametersException.php | 22 - .../Exception/NoConfigurationException.php | 21 - .../Exception/ResourceNotFoundException.php | 23 - .../RouteCircularReferenceException.php | 20 - .../Exception/RouteNotFoundException.php | 21 - .../routing/Exception/RuntimeException.php | 16 - .../Generator/CompiledUrlGenerator.php | 69 - .../ConfigurableRequirementsInterface.php | 53 - .../Dumper/CompiledUrlGeneratorDumper.php | 124 - .../Generator/Dumper/GeneratorDumper.php | 37 - .../Dumper/GeneratorDumperInterface.php | 37 - .../routing/Generator/UrlGenerator.php | 378 - .../Generator/UrlGeneratorInterface.php | 82 - lib/symfony/routing/LICENSE | 19 - .../routing/Loader/AnnotationClassLoader.php | 394 - .../Loader/AnnotationDirectoryLoader.php | 93 - .../routing/Loader/AnnotationFileLoader.php | 146 - lib/symfony/routing/Loader/ClosureLoader.php | 46 - .../Loader/Configurator/AliasConfigurator.php | 43 - .../Configurator/CollectionConfigurator.php | 125 - .../Configurator/ImportConfigurator.php | 90 - .../Loader/Configurator/RouteConfigurator.php | 49 - .../Configurator/RoutingConfigurator.php | 81 - .../Loader/Configurator/Traits/AddTrait.php | 60 - .../Loader/Configurator/Traits/HostTrait.php | 49 - .../Traits/LocalizedRouteTrait.php | 76 - .../Configurator/Traits/PrefixTrait.php | 62 - .../Loader/Configurator/Traits/RouteTrait.php | 175 - .../routing/Loader/ContainerLoader.php | 46 - .../routing/Loader/DirectoryLoader.php | 58 - lib/symfony/routing/Loader/GlobFileLoader.php | 47 - lib/symfony/routing/Loader/ObjectLoader.php | 84 - lib/symfony/routing/Loader/PhpFileLoader.php | 85 - lib/symfony/routing/Loader/XmlFileLoader.php | 469 - lib/symfony/routing/Loader/YamlFileLoader.php | 314 - .../Loader/schema/routing/routing-1.0.xsd | 194 - .../routing/Matcher/CompiledUrlMatcher.php | 31 - .../Dumper/CompiledUrlMatcherDumper.php | 501 - .../Dumper/CompiledUrlMatcherTrait.php | 191 - .../routing/Matcher/Dumper/MatcherDumper.php | 37 - .../Matcher/Dumper/MatcherDumperInterface.php | 37 - .../Matcher/Dumper/StaticPrefixCollection.php | 205 - .../Matcher/ExpressionLanguageProvider.php | 58 - .../Matcher/RedirectableUrlMatcher.php | 64 - .../RedirectableUrlMatcherInterface.php | 31 - .../Matcher/RequestMatcherInterface.php | 39 - .../routing/Matcher/TraceableUrlMatcher.php | 164 - lib/symfony/routing/Matcher/UrlMatcher.php | 279 - .../routing/Matcher/UrlMatcherInterface.php | 41 - lib/symfony/routing/README.md | 51 - lib/symfony/routing/RequestContext.php | 327 - .../routing/RequestContextAwareInterface.php | 27 - lib/symfony/routing/Route.php | 507 - lib/symfony/routing/RouteCollection.php | 383 - .../routing/RouteCollectionBuilder.php | 364 - lib/symfony/routing/RouteCompiler.php | 346 - .../routing/RouteCompilerInterface.php | 30 - lib/symfony/routing/Router.php | 393 - lib/symfony/routing/RouterInterface.php | 35 - lib/symfony/routing/composer.json | 51 - lib/symfony/service-contracts/.gitignore | 3 - .../service-contracts/Attribute/Required.php | 25 - .../Attribute/SubscribedService.php | 33 - lib/symfony/service-contracts/CHANGELOG.md | 5 - lib/symfony/service-contracts/LICENSE | 19 - lib/symfony/service-contracts/README.md | 9 - .../service-contracts/ResetInterface.php | 30 - .../service-contracts/ServiceLocatorTrait.php | 128 - .../ServiceProviderInterface.php | 36 - .../ServiceSubscriberInterface.php | 53 - .../ServiceSubscriberTrait.php | 109 - lib/symfony/service-contracts/composer.json | 42 - lib/symfony/stopwatch/CHANGELOG.md | 24 - lib/symfony/stopwatch/LICENSE | 19 - lib/symfony/stopwatch/README.md | 42 - lib/symfony/stopwatch/Section.php | 185 - lib/symfony/stopwatch/Stopwatch.php | 166 - lib/symfony/stopwatch/StopwatchEvent.php | 258 - lib/symfony/stopwatch/StopwatchPeriod.php | 81 - lib/symfony/stopwatch/composer.json | 29 - lib/symfony/string/AbstractString.php | 795 - lib/symfony/string/AbstractUnicodeString.php | 623 - lib/symfony/string/ByteString.php | 506 - lib/symfony/string/CHANGELOG.md | 35 - lib/symfony/string/CodePointString.php | 270 - .../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 - lib/symfony/string/LICENSE | 19 - lib/symfony/string/LazyString.php | 164 - lib/symfony/string/README.md | 14 - .../Resources/data/wcswidth_table_wide.php | 1135 - .../Resources/data/wcswidth_table_zero.php | 1375 - lib/symfony/string/Resources/functions.php | 38 - lib/symfony/string/Slugger/AsciiSlugger.php | 183 - .../string/Slugger/SluggerInterface.php | 27 - lib/symfony/string/UnicodeString.php | 377 - lib/symfony/string/composer.json | 43 - lib/symfony/translation-contracts/.gitignore | 3 - .../translation-contracts/CHANGELOG.md | 5 - lib/symfony/translation-contracts/LICENSE | 19 - .../LocaleAwareInterface.php | 31 - lib/symfony/translation-contracts/README.md | 9 - .../TranslatableInterface.php | 20 - .../TranslatorInterface.php | 67 - .../translation-contracts/TranslatorTrait.php | 262 - .../translation-contracts/composer.json | 37 - lib/symfony/twig-bridge/AppVariable.php | 182 - lib/symfony/twig-bridge/CHANGELOG.md | 169 - .../twig-bridge/Command/DebugCommand.php | 600 - .../twig-bridge/Command/LintCommand.php | 296 - .../DataCollector/TwigDataCollector.php | 203 - .../ErrorRenderer/TwigErrorRenderer.php | 90 - .../twig-bridge/Extension/AssetExtension.php | 61 - .../twig-bridge/Extension/CodeExtension.php | 246 - .../twig-bridge/Extension/CsrfExtension.php | 32 - .../twig-bridge/Extension/CsrfRuntime.php | 33 - .../twig-bridge/Extension/DumpExtension.php | 86 - .../Extension/ExpressionExtension.php | 39 - .../twig-bridge/Extension/FormExtension.php | 219 - .../Extension/HttpFoundationExtension.php | 67 - .../Extension/HttpKernelExtension.php | 42 - .../Extension/HttpKernelRuntime.php | 69 - .../Extension/LogoutUrlExtension.php | 62 - .../Extension/ProfilerExtension.php | 57 - .../Extension/RoutingExtension.php | 93 - .../Extension/SecurityExtension.php | 87 - .../Extension/SerializerExtension.php | 28 - .../Extension/SerializerRuntime.php | 33 - .../Extension/StopwatchExtension.php | 54 - .../Extension/TranslationExtension.php | 145 - .../Extension/WebLinkExtension.php | 133 - .../Extension/WorkflowExtension.php | 121 - .../twig-bridge/Extension/YamlExtension.php | 63 - .../twig-bridge/Form/TwigRendererEngine.php | 182 - lib/symfony/twig-bridge/LICENSE | 19 - lib/symfony/twig-bridge/Mime/BodyRenderer.php | 105 - .../twig-bridge/Mime/NotificationEmail.php | 250 - .../twig-bridge/Mime/TemplatedEmail.php | 87 - .../Mime/WrappedTemplatedEmail.php | 194 - lib/symfony/twig-bridge/Node/DumpNode.php | 87 - .../twig-bridge/Node/FormThemeNode.php | 42 - .../twig-bridge/Node/RenderBlockNode.php | 45 - .../Node/SearchAndRenderBlockNode.php | 110 - .../twig-bridge/Node/StopwatchNode.php | 48 - .../Node/TransDefaultDomainNode.php | 32 - lib/symfony/twig-bridge/Node/TransNode.php | 130 - lib/symfony/twig-bridge/NodeVisitor/Scope.php | 103 - .../TranslationDefaultDomainNodeVisitor.php | 128 - .../NodeVisitor/TranslationNodeVisitor.php | 187 - lib/symfony/twig-bridge/README.md | 13 - .../Email/default/notification/body.html.twig | 1 - .../Email/default/notification/body.txt.twig | 1 - .../Resources/views/Email/zurb_2/main.css | 1667 -- .../Email/zurb_2/notification/body.html.twig | 67 - .../Email/zurb_2/notification/body.txt.twig | 20 - .../notification/content_markdown.html.twig | 1 - .../views/Email/zurb_2/notification/local.css | 19 - .../bootstrap_3_horizontal_layout.html.twig | 71 - .../views/Form/bootstrap_3_layout.html.twig | 216 - .../bootstrap_4_horizontal_layout.html.twig | 88 - .../views/Form/bootstrap_4_layout.html.twig | 371 - .../bootstrap_5_horizontal_layout.html.twig | 130 - .../views/Form/bootstrap_5_layout.html.twig | 374 - .../Form/bootstrap_base_layout.html.twig | 208 - .../views/Form/form_div_layout.html.twig | 476 - .../views/Form/form_table_layout.html.twig | 50 - .../views/Form/foundation_5_layout.html.twig | 340 - .../views/Form/foundation_6_layout.html.twig | 50 - .../views/Form/tailwind_2_layout.html.twig | 69 - .../TokenParser/DumpTokenParser.php | 53 - .../TokenParser/FormThemeTokenParser.php | 64 - .../TokenParser/StopwatchTokenParser.php | 64 - .../TransDefaultDomainTokenParser.php | 45 - .../TokenParser/TransTokenParser.php | 95 - .../twig-bridge/Translation/TwigExtractor.php | 104 - .../twig-bridge/UndefinedCallableHandler.php | 107 - lib/symfony/twig-bridge/composer.json | 88 - lib/symfony/twig-bundle/CHANGELOG.md | 94 - .../CacheWarmer/TemplateCacheWarmer.php | 90 - .../twig-bundle/Command/LintCommand.php | 58 - .../Compiler/ExtensionPass.php | 129 - .../Compiler/RuntimeLoaderPass.php | 39 - .../Compiler/TwigEnvironmentPass.php | 57 - .../Compiler/TwigLoaderPass.php | 60 - .../DependencyInjection/Configuration.php | 206 - .../Configurator/EnvironmentConfigurator.php | 58 - .../DependencyInjection/TwigExtension.php | 208 - lib/symfony/twig-bundle/LICENSE | 19 - lib/symfony/twig-bundle/README.md | 13 - .../twig-bundle/Resources/config/console.php | 33 - .../twig-bundle/Resources/config/form.php | 30 - .../twig-bundle/Resources/config/mailer.php | 26 - .../Resources/config/schema/twig-1.0.xsd | 58 - .../twig-bundle/Resources/config/twig.php | 171 - lib/symfony/twig-bundle/TemplateIterator.php | 91 - lib/symfony/twig-bundle/TwigBundle.php | 45 - lib/symfony/twig-bundle/composer.json | 56 - lib/symfony/var-dumper/CHANGELOG.md | 72 - lib/symfony/var-dumper/Caster/AmqpCaster.php | 212 - lib/symfony/var-dumper/Caster/ArgsStub.php | 80 - lib/symfony/var-dumper/Caster/Caster.php | 170 - lib/symfony/var-dumper/Caster/ClassStub.php | 106 - lib/symfony/var-dumper/Caster/ConstStub.php | 36 - .../var-dumper/Caster/CutArrayStub.php | 30 - lib/symfony/var-dumper/Caster/CutStub.php | 64 - lib/symfony/var-dumper/Caster/DOMCaster.php | 304 - lib/symfony/var-dumper/Caster/DateCaster.php | 127 - .../var-dumper/Caster/DoctrineCaster.php | 62 - lib/symfony/var-dumper/Caster/DsCaster.php | 70 - lib/symfony/var-dumper/Caster/DsPairStub.php | 28 - lib/symfony/var-dumper/Caster/EnumStub.php | 30 - .../var-dumper/Caster/ExceptionCaster.php | 388 - lib/symfony/var-dumper/Caster/FiberCaster.php | 43 - lib/symfony/var-dumper/Caster/FrameStub.php | 30 - lib/symfony/var-dumper/Caster/GmpCaster.php | 32 - .../var-dumper/Caster/ImagineCaster.php | 37 - lib/symfony/var-dumper/Caster/ImgStub.php | 26 - lib/symfony/var-dumper/Caster/IntlCaster.php | 172 - lib/symfony/var-dumper/Caster/LinkStub.php | 108 - .../var-dumper/Caster/MemcachedCaster.php | 81 - .../var-dumper/Caster/MysqliCaster.php | 33 - lib/symfony/var-dumper/Caster/PdoCaster.php | 122 - lib/symfony/var-dumper/Caster/PgSqlCaster.php | 156 - .../var-dumper/Caster/ProxyManagerCaster.php | 33 - .../var-dumper/Caster/RdKafkaCaster.php | 186 - lib/symfony/var-dumper/Caster/RedisCaster.php | 152 - .../var-dumper/Caster/ReflectionCaster.php | 442 - .../var-dumper/Caster/ResourceCaster.php | 103 - lib/symfony/var-dumper/Caster/SplCaster.php | 245 - lib/symfony/var-dumper/Caster/StubCaster.php | 84 - .../var-dumper/Caster/SymfonyCaster.php | 97 - lib/symfony/var-dumper/Caster/TraceStub.php | 36 - lib/symfony/var-dumper/Caster/UuidCaster.php | 30 - .../var-dumper/Caster/XmlReaderCaster.php | 91 - .../var-dumper/Caster/XmlResourceCaster.php | 63 - .../var-dumper/Cloner/AbstractCloner.php | 400 - .../var-dumper/Cloner/ClonerInterface.php | 27 - lib/symfony/var-dumper/Cloner/Cursor.php | 43 - lib/symfony/var-dumper/Cloner/Data.php | 468 - .../var-dumper/Cloner/DumperInterface.php | 56 - lib/symfony/var-dumper/Cloner/Stub.php | 67 - lib/symfony/var-dumper/Cloner/VarCloner.php | 311 - .../Command/Descriptor/CliDescriptor.php | 79 - .../Descriptor/DumpDescriptorInterface.php | 23 - .../Command/Descriptor/HtmlDescriptor.php | 119 - .../var-dumper/Command/ServerDumpCommand.php | 114 - .../var-dumper/Dumper/AbstractDumper.php | 202 - lib/symfony/var-dumper/Dumper/CliDumper.php | 652 - .../ContextProvider/CliContextProvider.php | 32 - .../ContextProviderInterface.php | 22 - .../RequestContextProvider.php | 51 - .../ContextProvider/SourceContextProvider.php | 126 - .../Dumper/ContextualizedDumper.php | 43 - .../var-dumper/Dumper/DataDumperInterface.php | 24 - lib/symfony/var-dumper/Dumper/HtmlDumper.php | 986 - .../var-dumper/Dumper/ServerDumper.php | 53 - .../Exception/ThrowingCasterException.php | 26 - lib/symfony/var-dumper/LICENSE | 19 - lib/symfony/var-dumper/README.md | 15 - .../var-dumper/Resources/bin/var-dump-server | 63 - .../Resources/css/htmlDescriptor.css | 130 - .../var-dumper/Resources/functions/dump.php | 50 - .../var-dumper/Resources/js/htmlDescriptor.js | 10 - lib/symfony/var-dumper/Server/Connection.php | 99 - lib/symfony/var-dumper/Server/DumpServer.php | 115 - lib/symfony/var-dumper/VarDumper.php | 115 - lib/symfony/var-dumper/composer.json | 50 - lib/symfony/var-exporter/CHANGELOG.md | 12 - .../Exception/ClassNotFoundException.php | 20 - .../Exception/ExceptionInterface.php | 16 - .../NotInstantiableTypeException.php | 20 - lib/symfony/var-exporter/Instantiator.php | 92 - .../var-exporter/Internal/Exporter.php | 406 - .../var-exporter/Internal/Hydrator.php | 152 - .../var-exporter/Internal/Reference.php | 30 - .../var-exporter/Internal/Registry.php | 146 - lib/symfony/var-exporter/Internal/Values.php | 27 - lib/symfony/var-exporter/LICENSE | 19 - lib/symfony/var-exporter/README.md | 38 - lib/symfony/var-exporter/VarExporter.php | 115 - lib/symfony/var-exporter/composer.json | 32 - lib/symfony/web-profiler-bundle/CHANGELOG.md | 95 - .../Controller/ExceptionPanelController.php | 61 - .../Controller/ProfilerController.php | 391 - .../Controller/RouterController.php | 104 - .../Csp/ContentSecurityPolicyHandler.php | 270 - .../Csp/NonceGenerator.php | 27 - .../DependencyInjection/Configuration.php | 46 - .../WebProfilerExtension.php | 72 - .../EventListener/WebDebugToolbarListener.php | 165 - lib/symfony/web-profiler-bundle/LICENSE | 19 - .../Profiler/TemplateManager.php | 90 - lib/symfony/web-profiler-bundle/README.md | 16 - .../Resources/ICONS_LICENSE.txt | 5 - .../Resources/config/profiler.php | 83 - .../Resources/config/routing/profiler.xml | 47 - .../Resources/config/routing/wdt.xml | 10 - .../config/schema/webprofiler-1.0.xsd | 14 - .../Resources/config/toolbar.php | 31 - .../Resources/views/Collector/ajax.html.twig | 35 - .../Resources/views/Collector/cache.html.twig | 153 - .../views/Collector/config.html.twig | 226 - .../views/Collector/events.html.twig | 119 - .../views/Collector/exception.css.twig | 32 - .../views/Collector/exception.html.twig | 37 - .../Resources/views/Collector/form.html.twig | 731 - .../views/Collector/http_client.html.twig | 131 - .../views/Collector/logger.html.twig | 270 - .../views/Collector/mailer.html.twig | 217 - .../views/Collector/memory.html.twig | 24 - .../views/Collector/messenger.html.twig | 201 - .../views/Collector/notifier.html.twig | 168 - .../views/Collector/request.html.twig | 392 - .../views/Collector/router.html.twig | 14 - .../Resources/views/Collector/time.css.twig | 64 - .../Resources/views/Collector/time.html.twig | 214 - .../Resources/views/Collector/time.js | 457 - .../views/Collector/translation.html.twig | 210 - .../Resources/views/Collector/twig.html.twig | 115 - .../views/Collector/validator.html.twig | 103 - .../Resources/views/Icon/ajax.svg | 1 - .../Resources/views/Icon/cache.svg | 1 - .../Resources/views/Icon/close.svg | 1 - .../Resources/views/Icon/config.svg | 1 - .../Resources/views/Icon/event.svg | 1 - .../Resources/views/Icon/exception.svg | 1 - .../Resources/views/Icon/filter.svg | 1 - .../Resources/views/Icon/form.svg | 1 - .../Resources/views/Icon/forward.svg | 1 - .../Resources/views/Icon/http-client.svg | 1 - .../Resources/views/Icon/logger.svg | 1 - .../Resources/views/Icon/mailer.svg | 1 - .../Resources/views/Icon/memory.svg | 1 - .../Resources/views/Icon/menu.svg | 1 - .../Resources/views/Icon/messenger.svg | 1 - .../Resources/views/Icon/no-gray.svg | 1 - .../Resources/views/Icon/no.svg | 1 - .../Resources/views/Icon/notifier.svg | 1 - .../Resources/views/Icon/redirect.svg | 1 - .../Resources/views/Icon/request.svg | 1 - .../Resources/views/Icon/router.svg | 1 - .../Resources/views/Icon/search.svg | 1 - .../Resources/views/Icon/symfony.svg | 1 - .../Resources/views/Icon/time.svg | 1 - .../Resources/views/Icon/translation.svg | 1 - .../Resources/views/Icon/twig.svg | 1 - .../Resources/views/Icon/validator.svg | 1 - .../Resources/views/Icon/yes.svg | 1 - .../views/Profiler/ajax_layout.html.twig | 1 - .../Resources/views/Profiler/bag.html.twig | 20 - .../Resources/views/Profiler/base.html.twig | 34 - .../views/Profiler/base_js.html.twig | 874 - .../Resources/views/Profiler/cancel.html.twig | 25 - .../Resources/views/Profiler/header.html.twig | 14 - .../Resources/views/Profiler/info.html.twig | 22 - .../Resources/views/Profiler/layout.html.twig | 153 - .../Resources/views/Profiler/open.css.twig | 79 - .../Resources/views/Profiler/open.html.twig | 22 - .../views/Profiler/profiler.css.twig | 1479 - .../views/Profiler/results.html.twig | 67 - .../Resources/views/Profiler/search.html.twig | 56 - .../views/Profiler/settings.html.twig | 193 - .../Resources/views/Profiler/table.html.twig | 16 - .../Resources/views/Profiler/toolbar.css.twig | 562 - .../views/Profiler/toolbar.html.twig | 46 - .../views/Profiler/toolbar_item.html.twig | 6 - .../views/Profiler/toolbar_js.html.twig | 21 - .../views/Profiler/toolbar_redirect.html.twig | 18 - .../Resources/views/Router/panel.html.twig | 71 - .../views/images/icon-minus-square.svg | 1 - .../views/images/icon-plus-square.svg | 1 - .../Twig/WebProfilerExtension.php | 119 - .../web-profiler-bundle/WebProfilerBundle.php | 27 - lib/symfony/web-profiler-bundle/composer.json | 47 - lib/symfony/yaml/CHANGELOG.md | 237 - lib/symfony/yaml/Command/LintCommand.php | 289 - lib/symfony/yaml/Dumper.php | 166 - lib/symfony/yaml/Escaper.php | 95 - lib/symfony/yaml/Exception/DumpException.php | 21 - .../yaml/Exception/ExceptionInterface.php | 21 - lib/symfony/yaml/Exception/ParseException.php | 132 - .../yaml/Exception/RuntimeException.php | 21 - lib/symfony/yaml/Inline.php | 811 - lib/symfony/yaml/LICENSE | 19 - lib/symfony/yaml/Parser.php | 1305 - lib/symfony/yaml/README.md | 13 - lib/symfony/yaml/Resources/bin/yaml-lint | 49 - lib/symfony/yaml/Tag/TaggedValue.php | 38 - lib/symfony/yaml/Unescaper.php | 132 - lib/symfony/yaml/Yaml.php | 100 - lib/symfony/yaml/composer.json | 42 - .../oauth2-azure/.devcontainer/Dockerfile | 15 - .../.devcontainer/devcontainer.json | 29 - lib/thenetworg/oauth2-azure/.gitignore | 9 - lib/thenetworg/oauth2-azure/.php_cs | 70 - .../oauth2-azure/.vscode/launch.json | 27 - lib/thenetworg/oauth2-azure/CHANGELOG.md | 5 - lib/thenetworg/oauth2-azure/LICENSE.md | 21 - lib/thenetworg/oauth2-azure/README.md | 283 - lib/thenetworg/oauth2-azure/composer.json | 36 - .../oauth2-azure/src/Grant/JwtBearer.php | 19 - .../oauth2-azure/src/Provider/Azure.php | 492 - .../src/Provider/AzureResourceOwner.php | 97 - .../oauth2-azure/src/Token/AccessToken.php | 73 - lib/twig/twig/.editorconfig | 18 - lib/twig/twig/.gitattributes | 4 - lib/twig/twig/.github/workflows/ci.yml | 149 - .../twig/.github/workflows/documentation.yml | 64 - lib/twig/twig/.gitignore | 6 - lib/twig/twig/.php-cs-fixer.dist.php | 20 - lib/twig/twig/CHANGELOG | 150 - lib/twig/twig/LICENSE | 27 - lib/twig/twig/README.rst | 23 - lib/twig/twig/composer.json | 50 - lib/twig/twig/src/Cache/CacheInterface.php | 46 - lib/twig/twig/src/Cache/FilesystemCache.php | 87 - lib/twig/twig/src/Cache/NullCache.php | 38 - lib/twig/twig/src/Compiler.php | 214 - lib/twig/twig/src/Environment.php | 832 - lib/twig/twig/src/Error/Error.php | 227 - lib/twig/twig/src/Error/LoaderError.php | 21 - lib/twig/twig/src/Error/RuntimeError.php | 22 - lib/twig/twig/src/Error/SyntaxError.php | 46 - lib/twig/twig/src/ExpressionParser.php | 825 - .../twig/src/Extension/AbstractExtension.php | 45 - lib/twig/twig/src/Extension/CoreExtension.php | 1695 -- .../twig/src/Extension/DebugExtension.php | 64 - .../twig/src/Extension/EscaperExtension.php | 416 - .../twig/src/Extension/ExtensionInterface.php | 68 - .../twig/src/Extension/GlobalsInterface.php | 25 - .../twig/src/Extension/OptimizerExtension.php | 29 - .../twig/src/Extension/ProfilerExtension.php | 52 - .../Extension/RuntimeExtensionInterface.php | 19 - .../twig/src/Extension/SandboxExtension.php | 123 - .../twig/src/Extension/StagingExtension.php | 100 - .../src/Extension/StringLoaderExtension.php | 42 - lib/twig/twig/src/ExtensionSet.php | 463 - .../src/FileExtensionEscapingStrategy.php | 60 - lib/twig/twig/src/Lexer.php | 501 - lib/twig/twig/src/Loader/ArrayLoader.php | 77 - lib/twig/twig/src/Loader/ChainLoader.php | 119 - lib/twig/twig/src/Loader/FilesystemLoader.php | 283 - lib/twig/twig/src/Loader/LoaderInterface.php | 49 - lib/twig/twig/src/Markup.php | 52 - lib/twig/twig/src/Node/AutoEscapeNode.php | 38 - lib/twig/twig/src/Node/BlockNode.php | 44 - lib/twig/twig/src/Node/BlockReferenceNode.php | 36 - lib/twig/twig/src/Node/BodyNode.php | 21 - .../twig/src/Node/CheckSecurityCallNode.php | 28 - lib/twig/twig/src/Node/CheckSecurityNode.php | 88 - lib/twig/twig/src/Node/CheckToStringNode.php | 45 - lib/twig/twig/src/Node/DeprecatedNode.php | 53 - lib/twig/twig/src/Node/DoNode.php | 38 - lib/twig/twig/src/Node/EmbedNode.php | 48 - .../Node/Expression/AbstractExpression.php | 24 - .../src/Node/Expression/ArrayExpression.php | 85 - .../Expression/ArrowFunctionExpression.php | 64 - .../Node/Expression/AssignNameExpression.php | 27 - .../Node/Expression/Binary/AbstractBinary.php | 42 - .../src/Node/Expression/Binary/AddBinary.php | 23 - .../src/Node/Expression/Binary/AndBinary.php | 23 - .../Expression/Binary/BitwiseAndBinary.php | 23 - .../Expression/Binary/BitwiseOrBinary.php | 23 - .../Expression/Binary/BitwiseXorBinary.php | 23 - .../Node/Expression/Binary/ConcatBinary.php | 23 - .../src/Node/Expression/Binary/DivBinary.php | 23 - .../Node/Expression/Binary/EndsWithBinary.php | 35 - .../Node/Expression/Binary/EqualBinary.php | 39 - .../Node/Expression/Binary/FloorDivBinary.php | 29 - .../Node/Expression/Binary/GreaterBinary.php | 39 - .../Expression/Binary/GreaterEqualBinary.php | 39 - .../src/Node/Expression/Binary/InBinary.php | 33 - .../src/Node/Expression/Binary/LessBinary.php | 39 - .../Expression/Binary/LessEqualBinary.php | 39 - .../Node/Expression/Binary/MatchesBinary.php | 33 - .../src/Node/Expression/Binary/ModBinary.php | 23 - .../src/Node/Expression/Binary/MulBinary.php | 23 - .../Node/Expression/Binary/NotEqualBinary.php | 39 - .../Node/Expression/Binary/NotInBinary.php | 33 - .../src/Node/Expression/Binary/OrBinary.php | 23 - .../Node/Expression/Binary/PowerBinary.php | 22 - .../Node/Expression/Binary/RangeBinary.php | 33 - .../Expression/Binary/SpaceshipBinary.php | 22 - .../Expression/Binary/StartsWithBinary.php | 35 - .../src/Node/Expression/Binary/SubBinary.php | 23 - .../Expression/BlockReferenceExpression.php | 86 - .../src/Node/Expression/CallExpression.php | 319 - .../Node/Expression/ConditionalExpression.php | 36 - .../Node/Expression/ConstantExpression.php | 28 - .../Node/Expression/Filter/DefaultFilter.php | 52 - .../src/Node/Expression/FilterExpression.php | 40 - .../Node/Expression/FunctionExpression.php | 43 - .../src/Node/Expression/GetAttrExpression.php | 87 - .../twig/src/Node/Expression/InlinePrint.php | 35 - .../Node/Expression/MethodCallExpression.php | 62 - .../src/Node/Expression/NameExpression.php | 97 - .../Expression/NullCoalesceExpression.php | 60 - .../src/Node/Expression/ParentExpression.php | 46 - .../Node/Expression/TempNameExpression.php | 31 - .../src/Node/Expression/Test/ConstantTest.php | 49 - .../src/Node/Expression/Test/DefinedTest.php | 74 - .../Node/Expression/Test/DivisiblebyTest.php | 36 - .../src/Node/Expression/Test/EvenTest.php | 35 - .../src/Node/Expression/Test/NullTest.php | 34 - .../twig/src/Node/Expression/Test/OddTest.php | 35 - .../src/Node/Expression/Test/SameasTest.php | 34 - .../src/Node/Expression/TestExpression.php | 42 - .../Node/Expression/Unary/AbstractUnary.php | 34 - .../src/Node/Expression/Unary/NegUnary.php | 23 - .../src/Node/Expression/Unary/NotUnary.php | 23 - .../src/Node/Expression/Unary/PosUnary.php | 23 - .../Node/Expression/VariadicExpression.php | 24 - lib/twig/twig/src/Node/FlushNode.php | 35 - lib/twig/twig/src/Node/ForLoopNode.php | 49 - lib/twig/twig/src/Node/ForNode.php | 107 - lib/twig/twig/src/Node/IfNode.php | 70 - lib/twig/twig/src/Node/ImportNode.php | 63 - lib/twig/twig/src/Node/IncludeNode.php | 106 - lib/twig/twig/src/Node/MacroNode.php | 113 - lib/twig/twig/src/Node/ModuleNode.php | 464 - lib/twig/twig/src/Node/Node.php | 179 - .../twig/src/Node/NodeCaptureInterface.php | 21 - .../twig/src/Node/NodeOutputInterface.php | 21 - lib/twig/twig/src/Node/PrintNode.php | 39 - lib/twig/twig/src/Node/SandboxNode.php | 52 - lib/twig/twig/src/Node/SetNode.php | 105 - lib/twig/twig/src/Node/TextNode.php | 38 - lib/twig/twig/src/Node/WithNode.php | 70 - lib/twig/twig/src/NodeTraverser.php | 76 - .../src/NodeVisitor/AbstractNodeVisitor.php | 49 - .../src/NodeVisitor/EscaperNodeVisitor.php | 208 - .../MacroAutoImportNodeVisitor.php | 74 - .../src/NodeVisitor/NodeVisitorInterface.php | 46 - .../src/NodeVisitor/OptimizerNodeVisitor.php | 217 - .../NodeVisitor/SafeAnalysisNodeVisitor.php | 160 - .../src/NodeVisitor/SandboxNodeVisitor.php | 136 - lib/twig/twig/src/Parser.php | 348 - .../twig/src/Profiler/Dumper/BaseDumper.php | 63 - .../src/Profiler/Dumper/BlackfireDumper.php | 72 - .../twig/src/Profiler/Dumper/HtmlDumper.php | 47 - .../twig/src/Profiler/Dumper/TextDumper.php | 35 - .../src/Profiler/Node/EnterProfileNode.php | 42 - .../src/Profiler/Node/LeaveProfileNode.php | 36 - .../NodeVisitor/ProfilerNodeVisitor.php | 70 - lib/twig/twig/src/Profiler/Profile.php | 181 - .../RuntimeLoader/ContainerRuntimeLoader.php | 37 - .../RuntimeLoader/FactoryRuntimeLoader.php | 41 - .../RuntimeLoader/RuntimeLoaderInterface.php | 27 - lib/twig/twig/src/Sandbox/SecurityError.php | 23 - .../Sandbox/SecurityNotAllowedFilterError.php | 33 - .../SecurityNotAllowedFunctionError.php | 33 - .../Sandbox/SecurityNotAllowedMethodError.php | 40 - .../SecurityNotAllowedPropertyError.php | 40 - .../Sandbox/SecurityNotAllowedTagError.php | 33 - lib/twig/twig/src/Sandbox/SecurityPolicy.php | 126 - .../src/Sandbox/SecurityPolicyInterface.php | 45 - lib/twig/twig/src/Source.php | 51 - lib/twig/twig/src/Template.php | 422 - lib/twig/twig/src/TemplateWrapper.php | 109 - lib/twig/twig/src/Token.php | 178 - .../src/TokenParser/AbstractTokenParser.php | 32 - .../twig/src/TokenParser/ApplyTokenParser.php | 60 - .../src/TokenParser/AutoEscapeTokenParser.php | 58 - .../twig/src/TokenParser/BlockTokenParser.php | 78 - .../src/TokenParser/DeprecatedTokenParser.php | 43 - .../twig/src/TokenParser/DoTokenParser.php | 38 - .../twig/src/TokenParser/EmbedTokenParser.php | 73 - .../src/TokenParser/ExtendsTokenParser.php | 52 - .../twig/src/TokenParser/FlushTokenParser.php | 38 - .../twig/src/TokenParser/ForTokenParser.php | 78 - .../twig/src/TokenParser/FromTokenParser.php | 66 - .../twig/src/TokenParser/IfTokenParser.php | 89 - .../src/TokenParser/ImportTokenParser.php | 44 - .../src/TokenParser/IncludeTokenParser.php | 69 - .../twig/src/TokenParser/MacroTokenParser.php | 66 - .../src/TokenParser/SandboxTokenParser.php | 66 - .../twig/src/TokenParser/SetTokenParser.php | 73 - .../src/TokenParser/TokenParserInterface.php | 46 - .../twig/src/TokenParser/UseTokenParser.php | 73 - .../twig/src/TokenParser/WithTokenParser.php | 56 - lib/twig/twig/src/TokenStream.php | 132 - lib/twig/twig/src/TwigFilter.php | 134 - lib/twig/twig/src/TwigFunction.php | 122 - lib/twig/twig/src/TwigTest.php | 100 - .../twig/src/Util/DeprecationCollector.php | 77 - .../twig/src/Util/TemplateDirIterator.php | 36 - lib/web.config | 30 - lib/webmozart/assert/CHANGELOG.md | 207 - lib/webmozart/assert/LICENSE | 20 - lib/webmozart/assert/README.md | 287 - lib/webmozart/assert/composer.json | 43 - lib/webmozart/assert/src/Assert.php | 2080 -- .../assert/src/InvalidArgumentException.php | 16 - lib/webmozart/assert/src/Mixin.php | 5089 ---- sources/DI/Controller/Controller.php | 122 +- sources/DI/Form/Builder/AttributeBuilder.php | 195 + sources/DI/Form/Builder/LayoutBuilder.php | 79 + .../Form/Listener/IFormTypeOptionModifier.php | 6 +- .../DI/Form/Listener/ObjectFormListener.php | 7 +- .../Form/Transformer/DocumentTransformer.php | 31 + .../Transformer/ExternalKeyTransformer.php | 42 + .../{Simple => Attribute}/DocumentType.php | 25 +- .../Form/Type/Attribute/ExternalFieldType.php | 38 + .../{Simple => Attribute}/ExternalKeyType.php | 9 +- .../{Simple => Attribute}/LinkSetType.php | 21 +- .../Type/{ => Compound}/ConfigurationType.php | 35 +- .../ObjectSingleAttributeType.php | 20 +- .../Form/Type/{ => Compound}/ObjectType.php | 31 +- sources/DI/ITopKernel.php | 2 + .../DI/Services/ObjectPresentationService.php | 329 +- sources/DI/Services/ObjectService.php | 63 +- sources/DI/Services/TwigHelper.php | 12 +- templates/DI/base.html.twig | 238 +- ...gle_attribute.html.twig => form.html.twig} | 0 templates/DI/form/classic_theme.html.twig | 165 + .../DI/form/external_key_widget.html.twig | 16 - templates/DI/form/form_layout.html.twig | 134 - templates/DI/home.html.twig | 2 +- templates/DI/object/edit.html.twig | 62 +- 3325 files changed, 1500 insertions(+), 547966 deletions(-) create mode 100644 css/DI/app.css create mode 100644 js/DI/app.js create mode 100644 js/DI/collection.js create mode 100644 js/DI/toolkit.js create mode 100644 js/DI/widget.js rename js/DI/{ => widget}/text_widget.js (54%) delete mode 100644 lib/.gitignore delete mode 100644 lib/.htaccess delete mode 100644 lib/apereo/phpcas/.codecov.yml delete mode 100644 lib/apereo/phpcas/.gitattributes delete mode 100644 lib/apereo/phpcas/.github/dependabot.yml delete mode 100644 lib/apereo/phpcas/.github/workflows/test.yml delete mode 100644 lib/apereo/phpcas/CAS.php delete mode 100644 lib/apereo/phpcas/LICENSE delete mode 100644 lib/apereo/phpcas/NOTICE delete mode 100644 lib/apereo/phpcas/README.md delete mode 100644 lib/apereo/phpcas/composer.json delete mode 100644 lib/apereo/phpcas/phpunit.xml.dist delete mode 100644 lib/apereo/phpcas/source/CAS.php delete mode 100644 lib/apereo/phpcas/source/CAS/AuthenticationException.php delete mode 100644 lib/apereo/phpcas/source/CAS/Autoload.php delete mode 100644 lib/apereo/phpcas/source/CAS/Client.php delete mode 100644 lib/apereo/phpcas/source/CAS/CookieJar.php delete mode 100644 lib/apereo/phpcas/source/CAS/Exception.php delete mode 100644 lib/apereo/phpcas/source/CAS/GracefullTerminationException.php delete mode 100644 lib/apereo/phpcas/source/CAS/InvalidArgumentException.php delete mode 100644 lib/apereo/phpcas/source/CAS/Languages/Catalan.php delete mode 100644 lib/apereo/phpcas/source/CAS/Languages/ChineseSimplified.php delete mode 100644 lib/apereo/phpcas/source/CAS/Languages/English.php delete mode 100644 lib/apereo/phpcas/source/CAS/Languages/French.php delete mode 100644 lib/apereo/phpcas/source/CAS/Languages/Galego.php delete mode 100644 lib/apereo/phpcas/source/CAS/Languages/German.php delete mode 100644 lib/apereo/phpcas/source/CAS/Languages/Greek.php delete mode 100644 lib/apereo/phpcas/source/CAS/Languages/Japanese.php delete mode 100644 lib/apereo/phpcas/source/CAS/Languages/LanguageInterface.php delete mode 100644 lib/apereo/phpcas/source/CAS/Languages/Portuguese.php delete mode 100644 lib/apereo/phpcas/source/CAS/Languages/Spanish.php delete mode 100644 lib/apereo/phpcas/source/CAS/OutOfSequenceBeforeAuthenticationCallException.php delete mode 100644 lib/apereo/phpcas/source/CAS/OutOfSequenceBeforeClientException.php delete mode 100644 lib/apereo/phpcas/source/CAS/OutOfSequenceBeforeProxyException.php delete mode 100644 lib/apereo/phpcas/source/CAS/OutOfSequenceException.php delete mode 100644 lib/apereo/phpcas/source/CAS/PGTStorage/AbstractStorage.php delete mode 100644 lib/apereo/phpcas/source/CAS/PGTStorage/Db.php delete mode 100644 lib/apereo/phpcas/source/CAS/PGTStorage/File.php delete mode 100644 lib/apereo/phpcas/source/CAS/ProxiedService.php delete mode 100644 lib/apereo/phpcas/source/CAS/ProxiedService/Abstract.php delete mode 100644 lib/apereo/phpcas/source/CAS/ProxiedService/Exception.php delete mode 100644 lib/apereo/phpcas/source/CAS/ProxiedService/Http.php delete mode 100644 lib/apereo/phpcas/source/CAS/ProxiedService/Http/Abstract.php delete mode 100644 lib/apereo/phpcas/source/CAS/ProxiedService/Http/Get.php delete mode 100644 lib/apereo/phpcas/source/CAS/ProxiedService/Http/Post.php delete mode 100644 lib/apereo/phpcas/source/CAS/ProxiedService/Imap.php delete mode 100644 lib/apereo/phpcas/source/CAS/ProxiedService/Testable.php delete mode 100644 lib/apereo/phpcas/source/CAS/ProxyChain.php delete mode 100644 lib/apereo/phpcas/source/CAS/ProxyChain/AllowedList.php delete mode 100644 lib/apereo/phpcas/source/CAS/ProxyChain/Any.php delete mode 100644 lib/apereo/phpcas/source/CAS/ProxyChain/Interface.php delete mode 100644 lib/apereo/phpcas/source/CAS/ProxyChain/Trusted.php delete mode 100644 lib/apereo/phpcas/source/CAS/ProxyTicketException.php delete mode 100644 lib/apereo/phpcas/source/CAS/Request/AbstractRequest.php delete mode 100644 lib/apereo/phpcas/source/CAS/Request/CurlMultiRequest.php delete mode 100644 lib/apereo/phpcas/source/CAS/Request/CurlRequest.php delete mode 100644 lib/apereo/phpcas/source/CAS/Request/Exception.php delete mode 100644 lib/apereo/phpcas/source/CAS/Request/MultiRequestInterface.php delete mode 100644 lib/apereo/phpcas/source/CAS/Request/RequestInterface.php delete mode 100644 lib/apereo/phpcas/source/CAS/Session/PhpSession.php delete mode 100644 lib/apereo/phpcas/source/CAS/TypeMismatchException.php delete mode 100644 lib/autoload.php delete mode 100644 lib/bin/generate-deps-for-config-factory delete mode 100644 lib/bin/generate-deps-for-config-factory.bat delete mode 100644 lib/bin/generate-factory-for-class delete mode 100644 lib/bin/generate-factory-for-class.bat delete mode 100644 lib/bin/patch-type-declarations delete mode 100644 lib/bin/patch-type-declarations.bat delete mode 100644 lib/bin/php-parse delete mode 100644 lib/bin/php-parse.bat delete mode 100644 lib/bin/pscss delete mode 100644 lib/bin/pscss.bat delete mode 100644 lib/bin/var-dump-server delete mode 100644 lib/bin/var-dump-server.bat delete mode 100644 lib/bin/yaml-lint delete mode 100644 lib/bin/yaml-lint.bat delete mode 100644 lib/combodo/tcpdf/CHANGELOG.TXT delete mode 100644 lib/combodo/tcpdf/LICENSE.TXT delete mode 100644 lib/combodo/tcpdf/README.md delete mode 100644 lib/combodo/tcpdf/VERSION delete mode 100644 lib/combodo/tcpdf/composer.json delete mode 100644 lib/combodo/tcpdf/config/tcpdf_config.php delete mode 100644 lib/combodo/tcpdf/fonts/courier.php delete mode 100644 lib/combodo/tcpdf/fonts/courierb.php delete mode 100644 lib/combodo/tcpdf/fonts/courierbi.php delete mode 100644 lib/combodo/tcpdf/fonts/courieri.php delete mode 100644 lib/combodo/tcpdf/fonts/dejavusans.ctg.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusans.php delete mode 100644 lib/combodo/tcpdf/fonts/dejavusans.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusansb.ctg.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusansb.php delete mode 100644 lib/combodo/tcpdf/fonts/dejavusansb.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusansbi.ctg.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusansbi.php delete mode 100644 lib/combodo/tcpdf/fonts/dejavusansbi.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusanscondensed.ctg.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusanscondensed.php delete mode 100644 lib/combodo/tcpdf/fonts/dejavusanscondensed.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusanscondensedb.ctg.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusanscondensedb.php delete mode 100644 lib/combodo/tcpdf/fonts/dejavusanscondensedb.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusanscondensedbi.ctg.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusanscondensedbi.php delete mode 100644 lib/combodo/tcpdf/fonts/dejavusanscondensedbi.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusanscondensedi.ctg.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusanscondensedi.php delete mode 100644 lib/combodo/tcpdf/fonts/dejavusanscondensedi.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusansextralight.ctg.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusansextralight.php delete mode 100644 lib/combodo/tcpdf/fonts/dejavusansextralight.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusansi.ctg.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusansi.php delete mode 100644 lib/combodo/tcpdf/fonts/dejavusansi.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusansmono.ctg.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusansmono.php delete mode 100644 lib/combodo/tcpdf/fonts/dejavusansmono.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusansmonob.ctg.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusansmonob.php delete mode 100644 lib/combodo/tcpdf/fonts/dejavusansmonob.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusansmonobi.ctg.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusansmonobi.php delete mode 100644 lib/combodo/tcpdf/fonts/dejavusansmonobi.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusansmonoi.ctg.z delete mode 100644 lib/combodo/tcpdf/fonts/dejavusansmonoi.php delete mode 100644 lib/combodo/tcpdf/fonts/dejavusansmonoi.z delete mode 100644 lib/combodo/tcpdf/fonts/droidsansfallback.ctg.z delete mode 100644 lib/combodo/tcpdf/fonts/droidsansfallback.php delete mode 100644 lib/combodo/tcpdf/fonts/droidsansfallback.z delete mode 100644 lib/combodo/tcpdf/fonts/helvetica.php delete mode 100644 lib/combodo/tcpdf/fonts/helveticab.php delete mode 100644 lib/combodo/tcpdf/fonts/helveticabi.php delete mode 100644 lib/combodo/tcpdf/fonts/helveticai.php delete mode 100644 lib/combodo/tcpdf/fonts/symbol.php delete mode 100644 lib/combodo/tcpdf/fonts/times.php delete mode 100644 lib/combodo/tcpdf/fonts/timesb.php delete mode 100644 lib/combodo/tcpdf/fonts/timesbi.php delete mode 100644 lib/combodo/tcpdf/fonts/timesi.php delete mode 100644 lib/combodo/tcpdf/fonts/zapfdingbats.php delete mode 100644 lib/combodo/tcpdf/include/barcodes/datamatrix.php delete mode 100644 lib/combodo/tcpdf/include/barcodes/pdf417.php delete mode 100644 lib/combodo/tcpdf/include/barcodes/qrcode.php delete mode 100644 lib/combodo/tcpdf/include/sRGB.icc delete mode 100644 lib/combodo/tcpdf/include/tcpdf_colors.php delete mode 100644 lib/combodo/tcpdf/include/tcpdf_filters.php delete mode 100644 lib/combodo/tcpdf/include/tcpdf_font_data.php delete mode 100644 lib/combodo/tcpdf/include/tcpdf_fonts.php delete mode 100644 lib/combodo/tcpdf/include/tcpdf_images.php delete mode 100644 lib/combodo/tcpdf/include/tcpdf_static.php delete mode 100644 lib/combodo/tcpdf/tcpdf.php delete mode 100644 lib/combodo/tcpdf/tcpdf_autoconfig.php delete mode 100644 lib/combodo/tcpdf/tcpdf_barcodes_1d.php delete mode 100644 lib/combodo/tcpdf/tcpdf_barcodes_2d.php delete mode 100644 lib/combodo/tcpdf/tcpdf_import.php delete mode 100644 lib/combodo/tcpdf/tcpdf_parser.php delete mode 100644 lib/composer/ClassLoader.php delete mode 100644 lib/composer/InstalledVersions.php delete mode 100644 lib/composer/LICENSE delete mode 100644 lib/composer/autoload_classmap.php delete mode 100644 lib/composer/autoload_files.php delete mode 100644 lib/composer/autoload_namespaces.php delete mode 100644 lib/composer/autoload_psr4.php delete mode 100644 lib/composer/autoload_real.php delete mode 100644 lib/composer/autoload_static.php delete mode 100644 lib/composer/include_paths.php delete mode 100644 lib/composer/installed.json delete mode 100644 lib/composer/installed.php delete mode 100644 lib/composer/platform_check.php delete mode 100644 lib/doctrine/annotations/LICENSE delete mode 100644 lib/doctrine/annotations/README.md delete mode 100644 lib/doctrine/annotations/UPGRADE.md delete mode 100644 lib/doctrine/annotations/composer.json delete mode 100644 lib/doctrine/annotations/docs/en/annotations.rst delete mode 100644 lib/doctrine/annotations/docs/en/custom.rst delete mode 100644 lib/doctrine/annotations/docs/en/index.rst delete mode 100644 lib/doctrine/annotations/docs/en/sidebar.rst delete mode 100644 lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php delete mode 100644 lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php delete mode 100644 lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attributes.php delete mode 100644 lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php delete mode 100644 lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php delete mode 100644 lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/NamedArgumentConstructor.php delete mode 100644 lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Required.php delete mode 100644 lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Target.php delete mode 100644 lib/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php delete mode 100644 lib/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php delete mode 100644 lib/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php delete mode 100644 lib/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php delete mode 100644 lib/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php delete mode 100644 lib/doctrine/annotations/lib/Doctrine/Common/Annotations/ImplicitlyIgnoredAnnotationNames.php delete mode 100644 lib/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php delete mode 100644 lib/doctrine/annotations/lib/Doctrine/Common/Annotations/PhpParser.php delete mode 100644 lib/doctrine/annotations/lib/Doctrine/Common/Annotations/PsrCachedReader.php delete mode 100644 lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php delete mode 100644 lib/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php delete mode 100644 lib/doctrine/annotations/psalm.xml delete mode 100644 lib/doctrine/cache/LICENSE delete mode 100644 lib/doctrine/cache/README.md delete mode 100644 lib/doctrine/cache/UPGRADE-1.11.md delete mode 100644 lib/doctrine/cache/UPGRADE-1.4.md delete mode 100644 lib/doctrine/cache/composer.json delete mode 100644 lib/doctrine/cache/lib/Doctrine/Common/Cache/Cache.php delete mode 100644 lib/doctrine/cache/lib/Doctrine/Common/Cache/CacheProvider.php delete mode 100644 lib/doctrine/cache/lib/Doctrine/Common/Cache/ClearableCache.php delete mode 100644 lib/doctrine/cache/lib/Doctrine/Common/Cache/FlushableCache.php delete mode 100644 lib/doctrine/cache/lib/Doctrine/Common/Cache/MultiDeleteCache.php delete mode 100644 lib/doctrine/cache/lib/Doctrine/Common/Cache/MultiGetCache.php delete mode 100644 lib/doctrine/cache/lib/Doctrine/Common/Cache/MultiOperationCache.php delete mode 100644 lib/doctrine/cache/lib/Doctrine/Common/Cache/MultiPutCache.php delete mode 100644 lib/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/CacheAdapter.php delete mode 100644 lib/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/CacheItem.php delete mode 100644 lib/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/DoctrineProvider.php delete mode 100644 lib/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/InvalidArgument.php delete mode 100644 lib/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/TypedCacheItem.php delete mode 100644 lib/doctrine/deprecations/LICENSE delete mode 100644 lib/doctrine/deprecations/README.md delete mode 100644 lib/doctrine/deprecations/composer.json delete mode 100644 lib/doctrine/deprecations/lib/Doctrine/Deprecations/Deprecation.php delete mode 100644 lib/doctrine/deprecations/lib/Doctrine/Deprecations/PHPUnit/VerifyDeprecations.php delete mode 100644 lib/doctrine/deprecations/phpcs.xml delete mode 100644 lib/doctrine/deprecations/phpstan.neon delete mode 100644 lib/doctrine/deprecations/psalm.xml delete mode 100644 lib/doctrine/lexer/LICENSE delete mode 100644 lib/doctrine/lexer/README.md delete mode 100644 lib/doctrine/lexer/UPGRADE.md delete mode 100644 lib/doctrine/lexer/composer.json delete mode 100644 lib/doctrine/lexer/src/AbstractLexer.php delete mode 100644 lib/doctrine/lexer/src/Token.php delete mode 100644 lib/firebase/php-jwt/CHANGELOG.md delete mode 100644 lib/firebase/php-jwt/LICENSE delete mode 100644 lib/firebase/php-jwt/README.md delete mode 100644 lib/firebase/php-jwt/composer.json delete mode 100644 lib/firebase/php-jwt/src/BeforeValidException.php delete mode 100644 lib/firebase/php-jwt/src/CachedKeySet.php delete mode 100644 lib/firebase/php-jwt/src/ExpiredException.php delete mode 100644 lib/firebase/php-jwt/src/JWK.php delete mode 100644 lib/firebase/php-jwt/src/JWT.php delete mode 100644 lib/firebase/php-jwt/src/Key.php delete mode 100644 lib/firebase/php-jwt/src/SignatureInvalidException.php delete mode 100644 lib/guzzlehttp/guzzle/CHANGELOG.md delete mode 100644 lib/guzzlehttp/guzzle/LICENSE delete mode 100644 lib/guzzlehttp/guzzle/README.md delete mode 100644 lib/guzzlehttp/guzzle/UPGRADING.md delete mode 100644 lib/guzzlehttp/guzzle/composer.json delete mode 100644 lib/guzzlehttp/guzzle/src/BodySummarizer.php delete mode 100644 lib/guzzlehttp/guzzle/src/BodySummarizerInterface.php delete mode 100644 lib/guzzlehttp/guzzle/src/Client.php delete mode 100644 lib/guzzlehttp/guzzle/src/ClientInterface.php delete mode 100644 lib/guzzlehttp/guzzle/src/ClientTrait.php delete mode 100644 lib/guzzlehttp/guzzle/src/Cookie/CookieJar.php delete mode 100644 lib/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php delete mode 100644 lib/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php delete mode 100644 lib/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php delete mode 100644 lib/guzzlehttp/guzzle/src/Cookie/SetCookie.php delete mode 100644 lib/guzzlehttp/guzzle/src/Exception/BadResponseException.php delete mode 100644 lib/guzzlehttp/guzzle/src/Exception/ClientException.php delete mode 100644 lib/guzzlehttp/guzzle/src/Exception/ConnectException.php delete mode 100644 lib/guzzlehttp/guzzle/src/Exception/GuzzleException.php delete mode 100644 lib/guzzlehttp/guzzle/src/Exception/InvalidArgumentException.php delete mode 100644 lib/guzzlehttp/guzzle/src/Exception/RequestException.php delete mode 100644 lib/guzzlehttp/guzzle/src/Exception/ServerException.php delete mode 100644 lib/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php delete mode 100644 lib/guzzlehttp/guzzle/src/Exception/TransferException.php delete mode 100644 lib/guzzlehttp/guzzle/src/Handler/CurlFactory.php delete mode 100644 lib/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php delete mode 100644 lib/guzzlehttp/guzzle/src/Handler/CurlHandler.php delete mode 100644 lib/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php delete mode 100644 lib/guzzlehttp/guzzle/src/Handler/EasyHandle.php delete mode 100644 lib/guzzlehttp/guzzle/src/Handler/HeaderProcessor.php delete mode 100644 lib/guzzlehttp/guzzle/src/Handler/MockHandler.php delete mode 100644 lib/guzzlehttp/guzzle/src/Handler/Proxy.php delete mode 100644 lib/guzzlehttp/guzzle/src/Handler/StreamHandler.php delete mode 100644 lib/guzzlehttp/guzzle/src/HandlerStack.php delete mode 100644 lib/guzzlehttp/guzzle/src/MessageFormatter.php delete mode 100644 lib/guzzlehttp/guzzle/src/MessageFormatterInterface.php delete mode 100644 lib/guzzlehttp/guzzle/src/Middleware.php delete mode 100644 lib/guzzlehttp/guzzle/src/Pool.php delete mode 100644 lib/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php delete mode 100644 lib/guzzlehttp/guzzle/src/RedirectMiddleware.php delete mode 100644 lib/guzzlehttp/guzzle/src/RequestOptions.php delete mode 100644 lib/guzzlehttp/guzzle/src/RetryMiddleware.php delete mode 100644 lib/guzzlehttp/guzzle/src/TransferStats.php delete mode 100644 lib/guzzlehttp/guzzle/src/Utils.php delete mode 100644 lib/guzzlehttp/guzzle/src/functions.php delete mode 100644 lib/guzzlehttp/guzzle/src/functions_include.php delete mode 100644 lib/guzzlehttp/promises/CHANGELOG.md delete mode 100644 lib/guzzlehttp/promises/LICENSE delete mode 100644 lib/guzzlehttp/promises/README.md delete mode 100644 lib/guzzlehttp/promises/composer.json delete mode 100644 lib/guzzlehttp/promises/src/AggregateException.php delete mode 100644 lib/guzzlehttp/promises/src/CancellationException.php delete mode 100644 lib/guzzlehttp/promises/src/Coroutine.php delete mode 100644 lib/guzzlehttp/promises/src/Create.php delete mode 100644 lib/guzzlehttp/promises/src/Each.php delete mode 100644 lib/guzzlehttp/promises/src/EachPromise.php delete mode 100644 lib/guzzlehttp/promises/src/FulfilledPromise.php delete mode 100644 lib/guzzlehttp/promises/src/Is.php delete mode 100644 lib/guzzlehttp/promises/src/Promise.php delete mode 100644 lib/guzzlehttp/promises/src/PromiseInterface.php delete mode 100644 lib/guzzlehttp/promises/src/PromisorInterface.php delete mode 100644 lib/guzzlehttp/promises/src/RejectedPromise.php delete mode 100644 lib/guzzlehttp/promises/src/RejectionException.php delete mode 100644 lib/guzzlehttp/promises/src/TaskQueue.php delete mode 100644 lib/guzzlehttp/promises/src/TaskQueueInterface.php delete mode 100644 lib/guzzlehttp/promises/src/Utils.php delete mode 100644 lib/guzzlehttp/promises/vendor-bin/php-cs-fixer/composer.json delete mode 100644 lib/guzzlehttp/promises/vendor-bin/phpstan/composer.json delete mode 100644 lib/guzzlehttp/promises/vendor-bin/psalm/composer.json delete mode 100644 lib/guzzlehttp/psr7/CHANGELOG.md delete mode 100644 lib/guzzlehttp/psr7/LICENSE delete mode 100644 lib/guzzlehttp/psr7/README.md delete mode 100644 lib/guzzlehttp/psr7/composer.json delete mode 100644 lib/guzzlehttp/psr7/src/AppendStream.php delete mode 100644 lib/guzzlehttp/psr7/src/BufferStream.php delete mode 100644 lib/guzzlehttp/psr7/src/CachingStream.php delete mode 100644 lib/guzzlehttp/psr7/src/DroppingStream.php delete mode 100644 lib/guzzlehttp/psr7/src/Exception/MalformedUriException.php delete mode 100644 lib/guzzlehttp/psr7/src/FnStream.php delete mode 100644 lib/guzzlehttp/psr7/src/Header.php delete mode 100644 lib/guzzlehttp/psr7/src/HttpFactory.php delete mode 100644 lib/guzzlehttp/psr7/src/InflateStream.php delete mode 100644 lib/guzzlehttp/psr7/src/LazyOpenStream.php delete mode 100644 lib/guzzlehttp/psr7/src/LimitStream.php delete mode 100644 lib/guzzlehttp/psr7/src/Message.php delete mode 100644 lib/guzzlehttp/psr7/src/MessageTrait.php delete mode 100644 lib/guzzlehttp/psr7/src/MimeType.php delete mode 100644 lib/guzzlehttp/psr7/src/MultipartStream.php delete mode 100644 lib/guzzlehttp/psr7/src/NoSeekStream.php delete mode 100644 lib/guzzlehttp/psr7/src/PumpStream.php delete mode 100644 lib/guzzlehttp/psr7/src/Query.php delete mode 100644 lib/guzzlehttp/psr7/src/Request.php delete mode 100644 lib/guzzlehttp/psr7/src/Response.php delete mode 100644 lib/guzzlehttp/psr7/src/Rfc7230.php delete mode 100644 lib/guzzlehttp/psr7/src/ServerRequest.php delete mode 100644 lib/guzzlehttp/psr7/src/Stream.php delete mode 100644 lib/guzzlehttp/psr7/src/StreamDecoratorTrait.php delete mode 100644 lib/guzzlehttp/psr7/src/StreamWrapper.php delete mode 100644 lib/guzzlehttp/psr7/src/UploadedFile.php delete mode 100644 lib/guzzlehttp/psr7/src/Uri.php delete mode 100644 lib/guzzlehttp/psr7/src/UriComparator.php delete mode 100644 lib/guzzlehttp/psr7/src/UriNormalizer.php delete mode 100644 lib/guzzlehttp/psr7/src/UriResolver.php delete mode 100644 lib/guzzlehttp/psr7/src/Utils.php delete mode 100644 lib/laminas/laminas-loader/.laminas-ci.json delete mode 100644 lib/laminas/laminas-loader/COPYRIGHT.md delete mode 100644 lib/laminas/laminas-loader/LICENSE.md delete mode 100644 lib/laminas/laminas-loader/README.md delete mode 100644 lib/laminas/laminas-loader/composer.json delete mode 100644 lib/laminas/laminas-loader/composer.lock delete mode 100644 lib/laminas/laminas-loader/phpcs.xml.dist delete mode 100644 lib/laminas/laminas-loader/src/AutoloaderFactory.php delete mode 100644 lib/laminas/laminas-loader/src/ClassMapAutoloader.php delete mode 100644 lib/laminas/laminas-loader/src/Exception/BadMethodCallException.php delete mode 100644 lib/laminas/laminas-loader/src/Exception/DomainException.php delete mode 100644 lib/laminas/laminas-loader/src/Exception/ExceptionInterface.php delete mode 100644 lib/laminas/laminas-loader/src/Exception/InvalidArgumentException.php delete mode 100644 lib/laminas/laminas-loader/src/Exception/InvalidPathException.php delete mode 100644 lib/laminas/laminas-loader/src/Exception/MissingResourceNamespaceException.php delete mode 100644 lib/laminas/laminas-loader/src/Exception/PluginLoaderException.php delete mode 100644 lib/laminas/laminas-loader/src/Exception/RuntimeException.php delete mode 100644 lib/laminas/laminas-loader/src/Exception/SecurityException.php delete mode 100644 lib/laminas/laminas-loader/src/ModuleAutoloader.php delete mode 100644 lib/laminas/laminas-loader/src/PluginClassLoader.php delete mode 100644 lib/laminas/laminas-loader/src/PluginClassLocator.php delete mode 100644 lib/laminas/laminas-loader/src/ShortNameLocator.php delete mode 100644 lib/laminas/laminas-loader/src/SplAutoloader.php delete mode 100644 lib/laminas/laminas-loader/src/StandardAutoloader.php delete mode 100644 lib/laminas/laminas-mail/.laminas-ci.json delete mode 100644 lib/laminas/laminas-mail/.laminas-ci/pre-run.sh delete mode 100644 lib/laminas/laminas-mail/COPYRIGHT.md delete mode 100644 lib/laminas/laminas-mail/LICENSE.md delete mode 100644 lib/laminas/laminas-mail/README.md delete mode 100644 lib/laminas/laminas-mail/composer.json delete mode 100644 lib/laminas/laminas-mail/composer.lock delete mode 100644 lib/laminas/laminas-mail/src/Address.php delete mode 100644 lib/laminas/laminas-mail/src/Address/AddressInterface.php delete mode 100644 lib/laminas/laminas-mail/src/AddressList.php delete mode 100644 lib/laminas/laminas-mail/src/ConfigProvider.php delete mode 100644 lib/laminas/laminas-mail/src/Exception/BadMethodCallException.php delete mode 100644 lib/laminas/laminas-mail/src/Exception/DomainException.php delete mode 100644 lib/laminas/laminas-mail/src/Exception/ExceptionInterface.php delete mode 100644 lib/laminas/laminas-mail/src/Exception/InvalidArgumentException.php delete mode 100644 lib/laminas/laminas-mail/src/Exception/OutOfBoundsException.php delete mode 100644 lib/laminas/laminas-mail/src/Exception/RuntimeException.php delete mode 100644 lib/laminas/laminas-mail/src/Header/AbstractAddressList.php delete mode 100644 lib/laminas/laminas-mail/src/Header/Bcc.php delete mode 100644 lib/laminas/laminas-mail/src/Header/Cc.php delete mode 100644 lib/laminas/laminas-mail/src/Header/ContentDisposition.php delete mode 100644 lib/laminas/laminas-mail/src/Header/ContentTransferEncoding.php delete mode 100644 lib/laminas/laminas-mail/src/Header/ContentType.php delete mode 100644 lib/laminas/laminas-mail/src/Header/Date.php delete mode 100644 lib/laminas/laminas-mail/src/Header/Exception/BadMethodCallException.php delete mode 100644 lib/laminas/laminas-mail/src/Header/Exception/ExceptionInterface.php delete mode 100644 lib/laminas/laminas-mail/src/Header/Exception/InvalidArgumentException.php delete mode 100644 lib/laminas/laminas-mail/src/Header/Exception/RuntimeException.php delete mode 100644 lib/laminas/laminas-mail/src/Header/From.php delete mode 100644 lib/laminas/laminas-mail/src/Header/GenericHeader.php delete mode 100644 lib/laminas/laminas-mail/src/Header/GenericMultiHeader.php delete mode 100644 lib/laminas/laminas-mail/src/Header/HeaderInterface.php delete mode 100644 lib/laminas/laminas-mail/src/Header/HeaderLoader.php delete mode 100644 lib/laminas/laminas-mail/src/Header/HeaderLocator.php delete mode 100644 lib/laminas/laminas-mail/src/Header/HeaderLocatorInterface.php delete mode 100644 lib/laminas/laminas-mail/src/Header/HeaderName.php delete mode 100644 lib/laminas/laminas-mail/src/Header/HeaderValue.php delete mode 100644 lib/laminas/laminas-mail/src/Header/HeaderWrap.php delete mode 100644 lib/laminas/laminas-mail/src/Header/IdentificationField.php delete mode 100644 lib/laminas/laminas-mail/src/Header/InReplyTo.php delete mode 100644 lib/laminas/laminas-mail/src/Header/ListParser.php delete mode 100644 lib/laminas/laminas-mail/src/Header/MessageId.php delete mode 100644 lib/laminas/laminas-mail/src/Header/MimeVersion.php delete mode 100644 lib/laminas/laminas-mail/src/Header/MultipleHeadersInterface.php delete mode 100644 lib/laminas/laminas-mail/src/Header/Received.php delete mode 100644 lib/laminas/laminas-mail/src/Header/References.php delete mode 100644 lib/laminas/laminas-mail/src/Header/ReplyTo.php delete mode 100644 lib/laminas/laminas-mail/src/Header/Sender.php delete mode 100644 lib/laminas/laminas-mail/src/Header/StructuredInterface.php delete mode 100644 lib/laminas/laminas-mail/src/Header/Subject.php delete mode 100644 lib/laminas/laminas-mail/src/Header/To.php delete mode 100644 lib/laminas/laminas-mail/src/Header/UnstructuredInterface.php delete mode 100644 lib/laminas/laminas-mail/src/Headers.php delete mode 100644 lib/laminas/laminas-mail/src/Message.php delete mode 100644 lib/laminas/laminas-mail/src/MessageFactory.php delete mode 100644 lib/laminas/laminas-mail/src/Module.php delete mode 100644 lib/laminas/laminas-mail/src/Protocol/AbstractProtocol.php delete mode 100644 lib/laminas/laminas-mail/src/Protocol/Exception/ExceptionInterface.php delete mode 100644 lib/laminas/laminas-mail/src/Protocol/Exception/InvalidArgumentException.php delete mode 100644 lib/laminas/laminas-mail/src/Protocol/Exception/RuntimeException.php delete mode 100644 lib/laminas/laminas-mail/src/Protocol/Imap.php delete mode 100644 lib/laminas/laminas-mail/src/Protocol/Pop3.php delete mode 100644 lib/laminas/laminas-mail/src/Protocol/ProtocolTrait.php delete mode 100644 lib/laminas/laminas-mail/src/Protocol/Smtp.php delete mode 100644 lib/laminas/laminas-mail/src/Protocol/Smtp/Auth/Crammd5.php delete mode 100644 lib/laminas/laminas-mail/src/Protocol/Smtp/Auth/Login.php delete mode 100644 lib/laminas/laminas-mail/src/Protocol/Smtp/Auth/Plain.php delete mode 100644 lib/laminas/laminas-mail/src/Protocol/SmtpPluginManager.php delete mode 100644 lib/laminas/laminas-mail/src/Protocol/SmtpPluginManagerFactory.php delete mode 100644 lib/laminas/laminas-mail/src/Storage.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/AbstractStorage.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/Exception/ExceptionInterface.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/Exception/InvalidArgumentException.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/Exception/OutOfBoundsException.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/Exception/RuntimeException.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/Folder.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/Folder/FolderInterface.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/Folder/Maildir.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/Folder/Mbox.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/Imap.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/Maildir.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/Mbox.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/Message.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/Message/File.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/Message/MessageInterface.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/ParamsNormalizer.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/Part.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/Part/Exception/ExceptionInterface.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/Part/Exception/InvalidArgumentException.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/Part/Exception/RuntimeException.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/Part/File.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/Part/PartInterface.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/Pop3.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/Writable/Maildir.php delete mode 100644 lib/laminas/laminas-mail/src/Storage/Writable/WritableInterface.php delete mode 100644 lib/laminas/laminas-mail/src/Transport/Envelope.php delete mode 100644 lib/laminas/laminas-mail/src/Transport/Exception/DomainException.php delete mode 100644 lib/laminas/laminas-mail/src/Transport/Exception/ExceptionInterface.php delete mode 100644 lib/laminas/laminas-mail/src/Transport/Exception/InvalidArgumentException.php delete mode 100644 lib/laminas/laminas-mail/src/Transport/Exception/RuntimeException.php delete mode 100644 lib/laminas/laminas-mail/src/Transport/Factory.php delete mode 100644 lib/laminas/laminas-mail/src/Transport/File.php delete mode 100644 lib/laminas/laminas-mail/src/Transport/FileOptions.php delete mode 100644 lib/laminas/laminas-mail/src/Transport/InMemory.php delete mode 100644 lib/laminas/laminas-mail/src/Transport/Sendmail.php delete mode 100644 lib/laminas/laminas-mail/src/Transport/Smtp.php delete mode 100644 lib/laminas/laminas-mail/src/Transport/SmtpOptions.php delete mode 100644 lib/laminas/laminas-mail/src/Transport/TransportInterface.php delete mode 100644 lib/laminas/laminas-mime/.laminas-ci.json delete mode 100644 lib/laminas/laminas-mime/COPYRIGHT.md delete mode 100644 lib/laminas/laminas-mime/LICENSE.md delete mode 100644 lib/laminas/laminas-mime/README.md delete mode 100644 lib/laminas/laminas-mime/composer.json delete mode 100644 lib/laminas/laminas-mime/composer.lock delete mode 100644 lib/laminas/laminas-mime/phpcs.xml.dist delete mode 100644 lib/laminas/laminas-mime/src/Decode.php delete mode 100644 lib/laminas/laminas-mime/src/Exception/ExceptionInterface.php delete mode 100644 lib/laminas/laminas-mime/src/Exception/InvalidArgumentException.php delete mode 100644 lib/laminas/laminas-mime/src/Exception/RuntimeException.php delete mode 100644 lib/laminas/laminas-mime/src/Message.php delete mode 100644 lib/laminas/laminas-mime/src/Mime.php delete mode 100644 lib/laminas/laminas-mime/src/Part.php delete mode 100644 lib/laminas/laminas-servicemanager/COPYRIGHT.md delete mode 100644 lib/laminas/laminas-servicemanager/LICENSE.md delete mode 100644 lib/laminas/laminas-servicemanager/README.md delete mode 100644 lib/laminas/laminas-servicemanager/bin/generate-deps-for-config-factory delete mode 100644 lib/laminas/laminas-servicemanager/bin/generate-factory-for-class delete mode 100644 lib/laminas/laminas-servicemanager/composer.json delete mode 100644 lib/laminas/laminas-servicemanager/composer.lock delete mode 100644 lib/laminas/laminas-servicemanager/src/AbstractFactory/ConfigAbstractFactory.php delete mode 100644 lib/laminas/laminas-servicemanager/src/AbstractFactory/ReflectionBasedAbstractFactory.php delete mode 100644 lib/laminas/laminas-servicemanager/src/AbstractFactoryInterface.php delete mode 100644 lib/laminas/laminas-servicemanager/src/AbstractPluginManager.php delete mode 100644 lib/laminas/laminas-servicemanager/src/Config.php delete mode 100644 lib/laminas/laminas-servicemanager/src/ConfigInterface.php delete mode 100644 lib/laminas/laminas-servicemanager/src/DelegatorFactoryInterface.php delete mode 100644 lib/laminas/laminas-servicemanager/src/Exception/ContainerModificationsNotAllowedException.php delete mode 100644 lib/laminas/laminas-servicemanager/src/Exception/CyclicAliasException.php delete mode 100644 lib/laminas/laminas-servicemanager/src/Exception/ExceptionInterface.php delete mode 100644 lib/laminas/laminas-servicemanager/src/Exception/InvalidArgumentException.php delete mode 100644 lib/laminas/laminas-servicemanager/src/Exception/InvalidServiceException.php delete mode 100644 lib/laminas/laminas-servicemanager/src/Exception/ServiceNotCreatedException.php delete mode 100644 lib/laminas/laminas-servicemanager/src/Exception/ServiceNotFoundException.php delete mode 100644 lib/laminas/laminas-servicemanager/src/Factory/AbstractFactoryInterface.php delete mode 100644 lib/laminas/laminas-servicemanager/src/Factory/DelegatorFactoryInterface.php delete mode 100644 lib/laminas/laminas-servicemanager/src/Factory/FactoryInterface.php delete mode 100644 lib/laminas/laminas-servicemanager/src/Factory/InvokableFactory.php delete mode 100644 lib/laminas/laminas-servicemanager/src/FactoryInterface.php delete mode 100644 lib/laminas/laminas-servicemanager/src/Initializer/InitializerInterface.php delete mode 100644 lib/laminas/laminas-servicemanager/src/InitializerInterface.php delete mode 100644 lib/laminas/laminas-servicemanager/src/PluginManagerInterface.php delete mode 100644 lib/laminas/laminas-servicemanager/src/Proxy/LazyServiceFactory.php delete mode 100644 lib/laminas/laminas-servicemanager/src/ServiceLocatorInterface.php delete mode 100644 lib/laminas/laminas-servicemanager/src/ServiceManager.php delete mode 100644 lib/laminas/laminas-servicemanager/src/Tool/ConfigDumper.php delete mode 100644 lib/laminas/laminas-servicemanager/src/Tool/ConfigDumperCommand.php delete mode 100644 lib/laminas/laminas-servicemanager/src/Tool/FactoryCreator.php delete mode 100644 lib/laminas/laminas-servicemanager/src/Tool/FactoryCreatorCommand.php delete mode 100644 lib/laminas/laminas-servicemanager/src/autoload.php delete mode 100644 lib/laminas/laminas-stdlib/COPYRIGHT.md delete mode 100644 lib/laminas/laminas-stdlib/LICENSE.md delete mode 100644 lib/laminas/laminas-stdlib/README.md delete mode 100644 lib/laminas/laminas-stdlib/composer.json delete mode 100644 lib/laminas/laminas-stdlib/composer.lock delete mode 100644 lib/laminas/laminas-stdlib/src/AbstractOptions.php delete mode 100644 lib/laminas/laminas-stdlib/src/ArrayObject.php delete mode 100644 lib/laminas/laminas-stdlib/src/ArraySerializableInterface.php delete mode 100644 lib/laminas/laminas-stdlib/src/ArrayStack.php delete mode 100644 lib/laminas/laminas-stdlib/src/ArrayUtils.php delete mode 100644 lib/laminas/laminas-stdlib/src/ArrayUtils/MergeRemoveKey.php delete mode 100644 lib/laminas/laminas-stdlib/src/ArrayUtils/MergeReplaceKey.php delete mode 100644 lib/laminas/laminas-stdlib/src/ArrayUtils/MergeReplaceKeyInterface.php delete mode 100644 lib/laminas/laminas-stdlib/src/ConsoleHelper.php delete mode 100644 lib/laminas/laminas-stdlib/src/DispatchableInterface.php delete mode 100644 lib/laminas/laminas-stdlib/src/ErrorHandler.php delete mode 100644 lib/laminas/laminas-stdlib/src/Exception/BadMethodCallException.php delete mode 100644 lib/laminas/laminas-stdlib/src/Exception/DomainException.php delete mode 100644 lib/laminas/laminas-stdlib/src/Exception/ExceptionInterface.php delete mode 100644 lib/laminas/laminas-stdlib/src/Exception/ExtensionNotLoadedException.php delete mode 100644 lib/laminas/laminas-stdlib/src/Exception/InvalidArgumentException.php delete mode 100644 lib/laminas/laminas-stdlib/src/Exception/LogicException.php delete mode 100644 lib/laminas/laminas-stdlib/src/Exception/RuntimeException.php delete mode 100644 lib/laminas/laminas-stdlib/src/FastPriorityQueue.php delete mode 100644 lib/laminas/laminas-stdlib/src/Glob.php delete mode 100644 lib/laminas/laminas-stdlib/src/Guard/AllGuardsTrait.php delete mode 100644 lib/laminas/laminas-stdlib/src/Guard/ArrayOrTraversableGuardTrait.php delete mode 100644 lib/laminas/laminas-stdlib/src/Guard/EmptyGuardTrait.php delete mode 100644 lib/laminas/laminas-stdlib/src/Guard/NullGuardTrait.php delete mode 100644 lib/laminas/laminas-stdlib/src/InitializableInterface.php delete mode 100644 lib/laminas/laminas-stdlib/src/JsonSerializable.php delete mode 100644 lib/laminas/laminas-stdlib/src/Message.php delete mode 100644 lib/laminas/laminas-stdlib/src/MessageInterface.php delete mode 100644 lib/laminas/laminas-stdlib/src/ParameterObjectInterface.php delete mode 100644 lib/laminas/laminas-stdlib/src/Parameters.php delete mode 100644 lib/laminas/laminas-stdlib/src/ParametersInterface.php delete mode 100644 lib/laminas/laminas-stdlib/src/PriorityList.php delete mode 100644 lib/laminas/laminas-stdlib/src/PriorityQueue.php delete mode 100644 lib/laminas/laminas-stdlib/src/Request.php delete mode 100644 lib/laminas/laminas-stdlib/src/RequestInterface.php delete mode 100644 lib/laminas/laminas-stdlib/src/Response.php delete mode 100644 lib/laminas/laminas-stdlib/src/ResponseInterface.php delete mode 100644 lib/laminas/laminas-stdlib/src/SplPriorityQueue.php delete mode 100644 lib/laminas/laminas-stdlib/src/SplQueue.php delete mode 100644 lib/laminas/laminas-stdlib/src/SplStack.php delete mode 100644 lib/laminas/laminas-stdlib/src/StringUtils.php delete mode 100644 lib/laminas/laminas-stdlib/src/StringWrapper/AbstractStringWrapper.php delete mode 100644 lib/laminas/laminas-stdlib/src/StringWrapper/Iconv.php delete mode 100644 lib/laminas/laminas-stdlib/src/StringWrapper/Intl.php delete mode 100644 lib/laminas/laminas-stdlib/src/StringWrapper/MbString.php delete mode 100644 lib/laminas/laminas-stdlib/src/StringWrapper/Native.php delete mode 100644 lib/laminas/laminas-stdlib/src/StringWrapper/StringWrapperInterface.php delete mode 100644 lib/laminas/laminas-validator/COPYRIGHT.md delete mode 100644 lib/laminas/laminas-validator/LICENSE.md delete mode 100644 lib/laminas/laminas-validator/README.md delete mode 100644 lib/laminas/laminas-validator/bin/update_hostname_validator.php delete mode 100644 lib/laminas/laminas-validator/composer.json delete mode 100644 lib/laminas/laminas-validator/composer.lock delete mode 100644 lib/laminas/laminas-validator/renovate.json delete mode 100644 lib/laminas/laminas-validator/src/AbstractValidator.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/AbstractAdapter.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/AdapterInterface.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Codabar.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Code128.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Code25.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Code25interleaved.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Code39.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Code39ext.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Code93.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Code93ext.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Ean12.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Ean13.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Ean14.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Ean18.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Ean2.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Ean5.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Ean8.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Gtin12.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Gtin13.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Gtin14.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Identcode.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Intelligentmail.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Issn.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Itf14.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Leitcode.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Planet.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Postnet.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Royalmail.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Sscc.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Upca.php delete mode 100644 lib/laminas/laminas-validator/src/Barcode/Upce.php delete mode 100644 lib/laminas/laminas-validator/src/Between.php delete mode 100644 lib/laminas/laminas-validator/src/Bitwise.php delete mode 100644 lib/laminas/laminas-validator/src/BusinessIdentifierCode.php delete mode 100644 lib/laminas/laminas-validator/src/Callback.php delete mode 100644 lib/laminas/laminas-validator/src/ConfigProvider.php delete mode 100644 lib/laminas/laminas-validator/src/CreditCard.php delete mode 100644 lib/laminas/laminas-validator/src/Csrf.php delete mode 100644 lib/laminas/laminas-validator/src/Date.php delete mode 100644 lib/laminas/laminas-validator/src/DateStep.php delete mode 100755 lib/laminas/laminas-validator/src/Db/AbstractDb.php delete mode 100644 lib/laminas/laminas-validator/src/Db/NoRecordExists.php delete mode 100644 lib/laminas/laminas-validator/src/Db/RecordExists.php delete mode 100644 lib/laminas/laminas-validator/src/Digits.php delete mode 100644 lib/laminas/laminas-validator/src/EmailAddress.php delete mode 100644 lib/laminas/laminas-validator/src/Exception/BadMethodCallException.php delete mode 100644 lib/laminas/laminas-validator/src/Exception/ExceptionInterface.php delete mode 100644 lib/laminas/laminas-validator/src/Exception/ExtensionNotLoadedException.php delete mode 100644 lib/laminas/laminas-validator/src/Exception/InvalidArgumentException.php delete mode 100644 lib/laminas/laminas-validator/src/Exception/InvalidMagicMimeFileException.php delete mode 100644 lib/laminas/laminas-validator/src/Exception/RuntimeException.php delete mode 100644 lib/laminas/laminas-validator/src/Explode.php delete mode 100644 lib/laminas/laminas-validator/src/File/Count.php delete mode 100644 lib/laminas/laminas-validator/src/File/Crc32.php delete mode 100644 lib/laminas/laminas-validator/src/File/ExcludeExtension.php delete mode 100644 lib/laminas/laminas-validator/src/File/ExcludeMimeType.php delete mode 100644 lib/laminas/laminas-validator/src/File/Exists.php delete mode 100644 lib/laminas/laminas-validator/src/File/Extension.php delete mode 100644 lib/laminas/laminas-validator/src/File/FileInformationTrait.php delete mode 100644 lib/laminas/laminas-validator/src/File/FilesSize.php delete mode 100644 lib/laminas/laminas-validator/src/File/Hash.php delete mode 100644 lib/laminas/laminas-validator/src/File/ImageSize.php delete mode 100644 lib/laminas/laminas-validator/src/File/IsCompressed.php delete mode 100644 lib/laminas/laminas-validator/src/File/IsImage.php delete mode 100644 lib/laminas/laminas-validator/src/File/Md5.php delete mode 100644 lib/laminas/laminas-validator/src/File/MimeType.php delete mode 100644 lib/laminas/laminas-validator/src/File/NotExists.php delete mode 100644 lib/laminas/laminas-validator/src/File/Sha1.php delete mode 100644 lib/laminas/laminas-validator/src/File/Size.php delete mode 100644 lib/laminas/laminas-validator/src/File/Upload.php delete mode 100644 lib/laminas/laminas-validator/src/File/UploadFile.php delete mode 100644 lib/laminas/laminas-validator/src/File/WordCount.php delete mode 100644 lib/laminas/laminas-validator/src/GpsPoint.php delete mode 100644 lib/laminas/laminas-validator/src/GreaterThan.php delete mode 100644 lib/laminas/laminas-validator/src/Hex.php delete mode 100644 lib/laminas/laminas-validator/src/Hostname.php delete mode 100644 lib/laminas/laminas-validator/src/Hostname/Biz.php delete mode 100644 lib/laminas/laminas-validator/src/Hostname/Cn.php delete mode 100644 lib/laminas/laminas-validator/src/Hostname/Com.php delete mode 100644 lib/laminas/laminas-validator/src/Hostname/Jp.php delete mode 100644 lib/laminas/laminas-validator/src/Iban.php delete mode 100644 lib/laminas/laminas-validator/src/Identical.php delete mode 100644 lib/laminas/laminas-validator/src/InArray.php delete mode 100644 lib/laminas/laminas-validator/src/Ip.php delete mode 100644 lib/laminas/laminas-validator/src/IsCountable.php delete mode 100644 lib/laminas/laminas-validator/src/IsInstanceOf.php delete mode 100644 lib/laminas/laminas-validator/src/Isbn.php delete mode 100755 lib/laminas/laminas-validator/src/Isbn/Isbn10.php delete mode 100755 lib/laminas/laminas-validator/src/Isbn/Isbn13.php delete mode 100644 lib/laminas/laminas-validator/src/LessThan.php delete mode 100644 lib/laminas/laminas-validator/src/Module.php delete mode 100644 lib/laminas/laminas-validator/src/NotEmpty.php delete mode 100644 lib/laminas/laminas-validator/src/Regex.php delete mode 100644 lib/laminas/laminas-validator/src/Sitemap/Changefreq.php delete mode 100644 lib/laminas/laminas-validator/src/Sitemap/Lastmod.php delete mode 100644 lib/laminas/laminas-validator/src/Sitemap/Loc.php delete mode 100644 lib/laminas/laminas-validator/src/Sitemap/Priority.php delete mode 100644 lib/laminas/laminas-validator/src/StaticValidator.php delete mode 100644 lib/laminas/laminas-validator/src/Step.php delete mode 100644 lib/laminas/laminas-validator/src/StringLength.php delete mode 100644 lib/laminas/laminas-validator/src/Timezone.php delete mode 100644 lib/laminas/laminas-validator/src/Translator/TranslatorAwareInterface.php delete mode 100644 lib/laminas/laminas-validator/src/Translator/TranslatorInterface.php delete mode 100644 lib/laminas/laminas-validator/src/UndisclosedPassword.php delete mode 100644 lib/laminas/laminas-validator/src/Uri.php delete mode 100644 lib/laminas/laminas-validator/src/Uuid.php delete mode 100644 lib/laminas/laminas-validator/src/ValidatorChain.php delete mode 100644 lib/laminas/laminas-validator/src/ValidatorInterface.php delete mode 100644 lib/laminas/laminas-validator/src/ValidatorPluginManager.php delete mode 100644 lib/laminas/laminas-validator/src/ValidatorPluginManagerAwareInterface.php delete mode 100644 lib/laminas/laminas-validator/src/ValidatorPluginManagerFactory.php delete mode 100644 lib/laminas/laminas-validator/src/ValidatorProviderInterface.php delete mode 100644 lib/league/oauth2-client/LICENSE delete mode 100644 lib/league/oauth2-client/README.md delete mode 100644 lib/league/oauth2-client/composer.json delete mode 100644 lib/league/oauth2-client/src/Grant/AbstractGrant.php delete mode 100644 lib/league/oauth2-client/src/Grant/AuthorizationCode.php delete mode 100644 lib/league/oauth2-client/src/Grant/ClientCredentials.php delete mode 100644 lib/league/oauth2-client/src/Grant/Exception/InvalidGrantException.php delete mode 100644 lib/league/oauth2-client/src/Grant/GrantFactory.php delete mode 100644 lib/league/oauth2-client/src/Grant/Password.php delete mode 100644 lib/league/oauth2-client/src/Grant/RefreshToken.php delete mode 100644 lib/league/oauth2-client/src/OptionProvider/HttpBasicAuthOptionProvider.php delete mode 100644 lib/league/oauth2-client/src/OptionProvider/OptionProviderInterface.php delete mode 100644 lib/league/oauth2-client/src/OptionProvider/PostAuthOptionProvider.php delete mode 100644 lib/league/oauth2-client/src/Provider/AbstractProvider.php delete mode 100644 lib/league/oauth2-client/src/Provider/Exception/IdentityProviderException.php delete mode 100644 lib/league/oauth2-client/src/Provider/GenericProvider.php delete mode 100644 lib/league/oauth2-client/src/Provider/GenericResourceOwner.php delete mode 100644 lib/league/oauth2-client/src/Provider/ResourceOwnerInterface.php delete mode 100644 lib/league/oauth2-client/src/Token/AccessToken.php delete mode 100644 lib/league/oauth2-client/src/Token/AccessTokenInterface.php delete mode 100644 lib/league/oauth2-client/src/Token/ResourceOwnerAccessTokenInterface.php delete mode 100644 lib/league/oauth2-client/src/Tool/ArrayAccessorTrait.php delete mode 100644 lib/league/oauth2-client/src/Tool/BearerAuthorizationTrait.php delete mode 100644 lib/league/oauth2-client/src/Tool/GuardedPropertyTrait.php delete mode 100644 lib/league/oauth2-client/src/Tool/MacAuthorizationTrait.php delete mode 100644 lib/league/oauth2-client/src/Tool/ProviderRedirectTrait.php delete mode 100644 lib/league/oauth2-client/src/Tool/QueryBuilderTrait.php delete mode 100644 lib/league/oauth2-client/src/Tool/RequestFactory.php delete mode 100644 lib/league/oauth2-client/src/Tool/RequiredParameterTrait.php delete mode 100644 lib/league/oauth2-google/CHANGELOG.md delete mode 100644 lib/league/oauth2-google/CONTRIBUTING.md delete mode 100644 lib/league/oauth2-google/LICENSE delete mode 100644 lib/league/oauth2-google/README.md delete mode 100644 lib/league/oauth2-google/composer.json delete mode 100644 lib/league/oauth2-google/examples/index.php delete mode 100644 lib/league/oauth2-google/examples/provider.php delete mode 100644 lib/league/oauth2-google/examples/reset.php delete mode 100644 lib/league/oauth2-google/examples/server.sh delete mode 100644 lib/league/oauth2-google/examples/user.php delete mode 100644 lib/league/oauth2-google/phpunit.xml.dist delete mode 100644 lib/league/oauth2-google/src/Exception/HostedDomainException.php delete mode 100644 lib/league/oauth2-google/src/Provider/Google.php delete mode 100644 lib/league/oauth2-google/src/Provider/GoogleUser.php delete mode 100644 lib/nikic/php-parser/LICENSE delete mode 100644 lib/nikic/php-parser/README.md delete mode 100755 lib/nikic/php-parser/bin/php-parse delete mode 100644 lib/nikic/php-parser/composer.json delete mode 100644 lib/nikic/php-parser/grammar/README.md delete mode 100644 lib/nikic/php-parser/grammar/parser.template delete mode 100644 lib/nikic/php-parser/grammar/php5.y delete mode 100644 lib/nikic/php-parser/grammar/php7.y delete mode 100644 lib/nikic/php-parser/grammar/phpyLang.php delete mode 100644 lib/nikic/php-parser/grammar/rebuildParsers.php delete mode 100644 lib/nikic/php-parser/grammar/tokens.template delete mode 100644 lib/nikic/php-parser/grammar/tokens.y delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Builder.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Builder/ClassConst.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Builder/Class_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Builder/Declaration.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Builder/EnumCase.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Builder/Enum_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Builder/Function_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Builder/Interface_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Builder/Method.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Builder/Param.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Builder/Property.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Builder/TraitUse.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Builder/Trait_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Builder/Use_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/BuilderFactory.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/BuilderHelpers.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Comment.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Comment/Doc.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/ConstExprEvaluationException.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Error.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/ErrorHandler.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/ErrorHandler/Collecting.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Internal/DiffElem.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Internal/Differ.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/JsonDecoder.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Lexer.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/CoaleseEqualTokenEmulator.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/EnumTokenEmulator.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ExplicitOctalEmulator.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyTokenEmulator.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/NameContext.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Arg.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Attribute.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/ComplexType.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Const_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Coalesce.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignRef.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/CallLike.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Double.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/String_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Identifier.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/IntersectionType.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/MatchArm.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Name.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/NullableType.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Param.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Scalar.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Scalar/DNumber.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Scalar/String_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Break_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/EnumCase.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Enum_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/UnionType.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Node/VariadicPlaceholder.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/NodeAbstract.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/NodeDumper.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/NodeFinder.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/NodeTraverser.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/NodeVisitor.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Parser.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Parser/Multiple.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Parser/Php5.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Parser/Php7.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/Parser/Tokens.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/ParserAbstract.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/ParserFactory.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php delete mode 100644 lib/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php delete mode 100644 lib/paragonie/random_compat/LICENSE delete mode 100644 lib/paragonie/random_compat/build-phar.sh delete mode 100644 lib/paragonie/random_compat/composer.json delete mode 100644 lib/paragonie/random_compat/dist/random_compat.phar.pubkey delete mode 100644 lib/paragonie/random_compat/dist/random_compat.phar.pubkey.asc delete mode 100644 lib/paragonie/random_compat/lib/random.php delete mode 100644 lib/paragonie/random_compat/other/build_phar.php delete mode 100644 lib/paragonie/random_compat/psalm-autoload.php delete mode 100644 lib/paragonie/random_compat/psalm.xml delete mode 100644 lib/pear/archive_tar/.github/FUNDING.yml delete mode 100644 lib/pear/archive_tar/.github/dependabot.yml delete mode 100644 lib/pear/archive_tar/.github/workflows/build.yml delete mode 100644 lib/pear/archive_tar/.gitignore delete mode 100644 lib/pear/archive_tar/.travis.yml delete mode 100644 lib/pear/archive_tar/Archive/Tar.php delete mode 100644 lib/pear/archive_tar/README.md delete mode 100644 lib/pear/archive_tar/composer.json delete mode 100644 lib/pear/archive_tar/package.xml delete mode 100644 lib/pear/console_getopt/.gitignore delete mode 100644 lib/pear/console_getopt/.travis.yml delete mode 100644 lib/pear/console_getopt/Console/Getopt.php delete mode 100644 lib/pear/console_getopt/LICENSE delete mode 100644 lib/pear/console_getopt/README.rst delete mode 100644 lib/pear/console_getopt/composer.json delete mode 100644 lib/pear/console_getopt/package.xml delete mode 100644 lib/pear/pear-core-minimal/README.rst delete mode 100644 lib/pear/pear-core-minimal/composer.json delete mode 100644 lib/pear/pear-core-minimal/src/OS/Guess.php delete mode 100644 lib/pear/pear-core-minimal/src/PEAR.php delete mode 100644 lib/pear/pear-core-minimal/src/PEAR/Error.php delete mode 100644 lib/pear/pear-core-minimal/src/PEAR/ErrorStack.php delete mode 100644 lib/pear/pear-core-minimal/src/System.php delete mode 100644 lib/pear/pear_exception/LICENSE delete mode 100644 lib/pear/pear_exception/PEAR/Exception.php delete mode 100644 lib/pear/pear_exception/composer.json delete mode 100644 lib/pelago/emogrifier/CHANGELOG.md delete mode 100644 lib/pelago/emogrifier/LICENSE delete mode 100644 lib/pelago/emogrifier/README.md delete mode 100644 lib/pelago/emogrifier/composer.json delete mode 100644 lib/pelago/emogrifier/phpunit.xml delete mode 100644 lib/pelago/emogrifier/src/Caching/SimpleStringCache.php delete mode 100644 lib/pelago/emogrifier/src/Css/CssDocument.php delete mode 100644 lib/pelago/emogrifier/src/Css/StyleRule.php delete mode 100644 lib/pelago/emogrifier/src/CssInliner.php delete mode 100644 lib/pelago/emogrifier/src/HtmlProcessor/AbstractHtmlProcessor.php delete mode 100644 lib/pelago/emogrifier/src/HtmlProcessor/CssToAttributeConverter.php delete mode 100644 lib/pelago/emogrifier/src/HtmlProcessor/HtmlNormalizer.php delete mode 100644 lib/pelago/emogrifier/src/HtmlProcessor/HtmlPruner.php delete mode 100644 lib/pelago/emogrifier/src/Utilities/ArrayIntersector.php delete mode 100644 lib/pelago/emogrifier/src/Utilities/CssConcatenator.php delete mode 100644 lib/psr/cache/CHANGELOG.md delete mode 100644 lib/psr/cache/LICENSE.txt delete mode 100644 lib/psr/cache/README.md delete mode 100644 lib/psr/cache/composer.json delete mode 100644 lib/psr/cache/src/CacheException.php delete mode 100644 lib/psr/cache/src/CacheItemInterface.php delete mode 100644 lib/psr/cache/src/CacheItemPoolInterface.php delete mode 100644 lib/psr/cache/src/InvalidArgumentException.php delete mode 100644 lib/psr/container/.gitignore delete mode 100644 lib/psr/container/LICENSE delete mode 100644 lib/psr/container/README.md delete mode 100644 lib/psr/container/composer.json delete mode 100644 lib/psr/container/src/ContainerExceptionInterface.php delete mode 100644 lib/psr/container/src/ContainerInterface.php delete mode 100644 lib/psr/container/src/NotFoundExceptionInterface.php delete mode 100644 lib/psr/event-dispatcher/.editorconfig delete mode 100644 lib/psr/event-dispatcher/.gitignore delete mode 100644 lib/psr/event-dispatcher/LICENSE delete mode 100644 lib/psr/event-dispatcher/README.md delete mode 100644 lib/psr/event-dispatcher/composer.json delete mode 100644 lib/psr/event-dispatcher/src/EventDispatcherInterface.php delete mode 100644 lib/psr/event-dispatcher/src/ListenerProviderInterface.php delete mode 100644 lib/psr/event-dispatcher/src/StoppableEventInterface.php delete mode 100644 lib/psr/http-client/CHANGELOG.md delete mode 100644 lib/psr/http-client/LICENSE delete mode 100644 lib/psr/http-client/README.md delete mode 100644 lib/psr/http-client/composer.json delete mode 100644 lib/psr/http-client/src/ClientExceptionInterface.php delete mode 100644 lib/psr/http-client/src/ClientInterface.php delete mode 100644 lib/psr/http-client/src/NetworkExceptionInterface.php delete mode 100644 lib/psr/http-client/src/RequestExceptionInterface.php delete mode 100644 lib/psr/http-factory/LICENSE delete mode 100644 lib/psr/http-factory/README.md delete mode 100644 lib/psr/http-factory/composer.json delete mode 100644 lib/psr/http-factory/src/RequestFactoryInterface.php delete mode 100644 lib/psr/http-factory/src/ResponseFactoryInterface.php delete mode 100644 lib/psr/http-factory/src/ServerRequestFactoryInterface.php delete mode 100644 lib/psr/http-factory/src/StreamFactoryInterface.php delete mode 100644 lib/psr/http-factory/src/UploadedFileFactoryInterface.php delete mode 100644 lib/psr/http-factory/src/UriFactoryInterface.php delete mode 100644 lib/psr/http-message/CHANGELOG.md delete mode 100644 lib/psr/http-message/LICENSE delete mode 100644 lib/psr/http-message/README.md delete mode 100644 lib/psr/http-message/composer.json delete mode 100644 lib/psr/http-message/docs/PSR7-Interfaces.md delete mode 100644 lib/psr/http-message/docs/PSR7-Usage.md delete mode 100644 lib/psr/http-message/src/MessageInterface.php delete mode 100644 lib/psr/http-message/src/RequestInterface.php delete mode 100644 lib/psr/http-message/src/ResponseInterface.php delete mode 100644 lib/psr/http-message/src/ServerRequestInterface.php delete mode 100644 lib/psr/http-message/src/StreamInterface.php delete mode 100644 lib/psr/http-message/src/UploadedFileInterface.php delete mode 100644 lib/psr/http-message/src/UriInterface.php delete mode 100644 lib/psr/log/LICENSE delete mode 100644 lib/psr/log/Psr/Log/AbstractLogger.php delete mode 100644 lib/psr/log/Psr/Log/InvalidArgumentException.php delete mode 100644 lib/psr/log/Psr/Log/LogLevel.php delete mode 100644 lib/psr/log/Psr/Log/LoggerAwareInterface.php delete mode 100644 lib/psr/log/Psr/Log/LoggerAwareTrait.php delete mode 100644 lib/psr/log/Psr/Log/LoggerInterface.php delete mode 100644 lib/psr/log/Psr/Log/LoggerTrait.php delete mode 100644 lib/psr/log/Psr/Log/NullLogger.php delete mode 100644 lib/psr/log/README.md delete mode 100644 lib/psr/log/composer.json delete mode 100644 lib/ralouphie/getallheaders/LICENSE delete mode 100644 lib/ralouphie/getallheaders/README.md delete mode 100644 lib/ralouphie/getallheaders/composer.json delete mode 100644 lib/ralouphie/getallheaders/src/getallheaders.php delete mode 100644 lib/sabberworm/php-css-parser/CHANGELOG.md delete mode 100644 lib/sabberworm/php-css-parser/LICENSE delete mode 100644 lib/sabberworm/php-css-parser/README.md delete mode 100644 lib/sabberworm/php-css-parser/composer.json delete mode 100644 lib/sabberworm/php-css-parser/src/CSSList/AtRuleBlockList.php delete mode 100644 lib/sabberworm/php-css-parser/src/CSSList/CSSBlockList.php delete mode 100644 lib/sabberworm/php-css-parser/src/CSSList/CSSList.php delete mode 100644 lib/sabberworm/php-css-parser/src/CSSList/Document.php delete mode 100644 lib/sabberworm/php-css-parser/src/CSSList/KeyFrame.php delete mode 100644 lib/sabberworm/php-css-parser/src/Comment/Comment.php delete mode 100644 lib/sabberworm/php-css-parser/src/Comment/Commentable.php delete mode 100644 lib/sabberworm/php-css-parser/src/OutputFormat.php delete mode 100644 lib/sabberworm/php-css-parser/src/OutputFormatter.php delete mode 100644 lib/sabberworm/php-css-parser/src/Parser.php delete mode 100644 lib/sabberworm/php-css-parser/src/Parsing/OutputException.php delete mode 100644 lib/sabberworm/php-css-parser/src/Parsing/ParserState.php delete mode 100644 lib/sabberworm/php-css-parser/src/Parsing/SourceException.php delete mode 100644 lib/sabberworm/php-css-parser/src/Parsing/UnexpectedEOFException.php delete mode 100644 lib/sabberworm/php-css-parser/src/Parsing/UnexpectedTokenException.php delete mode 100644 lib/sabberworm/php-css-parser/src/Property/AtRule.php delete mode 100644 lib/sabberworm/php-css-parser/src/Property/CSSNamespace.php delete mode 100644 lib/sabberworm/php-css-parser/src/Property/Charset.php delete mode 100644 lib/sabberworm/php-css-parser/src/Property/Import.php delete mode 100644 lib/sabberworm/php-css-parser/src/Property/KeyframeSelector.php delete mode 100644 lib/sabberworm/php-css-parser/src/Property/Selector.php delete mode 100644 lib/sabberworm/php-css-parser/src/Renderable.php delete mode 100644 lib/sabberworm/php-css-parser/src/Rule/Rule.php delete mode 100644 lib/sabberworm/php-css-parser/src/RuleSet/AtRuleSet.php delete mode 100644 lib/sabberworm/php-css-parser/src/RuleSet/DeclarationBlock.php delete mode 100644 lib/sabberworm/php-css-parser/src/RuleSet/RuleSet.php delete mode 100644 lib/sabberworm/php-css-parser/src/Settings.php delete mode 100644 lib/sabberworm/php-css-parser/src/Value/CSSFunction.php delete mode 100644 lib/sabberworm/php-css-parser/src/Value/CSSString.php delete mode 100644 lib/sabberworm/php-css-parser/src/Value/CalcFunction.php delete mode 100644 lib/sabberworm/php-css-parser/src/Value/CalcRuleValueList.php delete mode 100644 lib/sabberworm/php-css-parser/src/Value/Color.php delete mode 100644 lib/sabberworm/php-css-parser/src/Value/LineName.php delete mode 100644 lib/sabberworm/php-css-parser/src/Value/PrimitiveValue.php delete mode 100644 lib/sabberworm/php-css-parser/src/Value/RuleValueList.php delete mode 100644 lib/sabberworm/php-css-parser/src/Value/Size.php delete mode 100644 lib/sabberworm/php-css-parser/src/Value/URL.php delete mode 100644 lib/sabberworm/php-css-parser/src/Value/Value.php delete mode 100644 lib/sabberworm/php-css-parser/src/Value/ValueList.php delete mode 100644 lib/scssphp/scssphp/LICENSE.md delete mode 100644 lib/scssphp/scssphp/README.md delete mode 100644 lib/scssphp/scssphp/bin/pscss delete mode 100644 lib/scssphp/scssphp/composer.json delete mode 100644 lib/scssphp/scssphp/scss.inc.php delete mode 100644 lib/scssphp/scssphp/src/Base/Range.php delete mode 100644 lib/scssphp/scssphp/src/Block.php delete mode 100644 lib/scssphp/scssphp/src/Block/AtRootBlock.php delete mode 100644 lib/scssphp/scssphp/src/Block/CallableBlock.php delete mode 100644 lib/scssphp/scssphp/src/Block/ContentBlock.php delete mode 100644 lib/scssphp/scssphp/src/Block/DirectiveBlock.php delete mode 100644 lib/scssphp/scssphp/src/Block/EachBlock.php delete mode 100644 lib/scssphp/scssphp/src/Block/ElseBlock.php delete mode 100644 lib/scssphp/scssphp/src/Block/ElseifBlock.php delete mode 100644 lib/scssphp/scssphp/src/Block/ForBlock.php delete mode 100644 lib/scssphp/scssphp/src/Block/IfBlock.php delete mode 100644 lib/scssphp/scssphp/src/Block/MediaBlock.php delete mode 100644 lib/scssphp/scssphp/src/Block/NestedPropertyBlock.php delete mode 100644 lib/scssphp/scssphp/src/Block/WhileBlock.php delete mode 100644 lib/scssphp/scssphp/src/Cache.php delete mode 100644 lib/scssphp/scssphp/src/Colors.php delete mode 100644 lib/scssphp/scssphp/src/CompilationResult.php delete mode 100644 lib/scssphp/scssphp/src/Compiler.php delete mode 100644 lib/scssphp/scssphp/src/Compiler/CachedResult.php delete mode 100644 lib/scssphp/scssphp/src/Compiler/Environment.php delete mode 100644 lib/scssphp/scssphp/src/Exception/CompilerException.php delete mode 100644 lib/scssphp/scssphp/src/Exception/ParserException.php delete mode 100644 lib/scssphp/scssphp/src/Exception/RangeException.php delete mode 100644 lib/scssphp/scssphp/src/Exception/SassException.php delete mode 100644 lib/scssphp/scssphp/src/Exception/SassScriptException.php delete mode 100644 lib/scssphp/scssphp/src/Exception/ServerException.php delete mode 100644 lib/scssphp/scssphp/src/Formatter.php delete mode 100644 lib/scssphp/scssphp/src/Formatter/Compact.php delete mode 100644 lib/scssphp/scssphp/src/Formatter/Compressed.php delete mode 100644 lib/scssphp/scssphp/src/Formatter/Crunched.php delete mode 100644 lib/scssphp/scssphp/src/Formatter/Debug.php delete mode 100644 lib/scssphp/scssphp/src/Formatter/Expanded.php delete mode 100644 lib/scssphp/scssphp/src/Formatter/Nested.php delete mode 100644 lib/scssphp/scssphp/src/Formatter/OutputBlock.php delete mode 100644 lib/scssphp/scssphp/src/Logger/LoggerInterface.php delete mode 100644 lib/scssphp/scssphp/src/Logger/QuietLogger.php delete mode 100644 lib/scssphp/scssphp/src/Logger/StreamLogger.php delete mode 100644 lib/scssphp/scssphp/src/Node.php delete mode 100644 lib/scssphp/scssphp/src/Node/Number.php delete mode 100644 lib/scssphp/scssphp/src/OutputStyle.php delete mode 100644 lib/scssphp/scssphp/src/Parser.php delete mode 100644 lib/scssphp/scssphp/src/SourceMap/Base64.php delete mode 100644 lib/scssphp/scssphp/src/SourceMap/Base64VLQ.php delete mode 100644 lib/scssphp/scssphp/src/SourceMap/SourceMapGenerator.php delete mode 100644 lib/scssphp/scssphp/src/Type.php delete mode 100644 lib/scssphp/scssphp/src/Util.php delete mode 100644 lib/scssphp/scssphp/src/Util/Path.php delete mode 100644 lib/scssphp/scssphp/src/ValueConverter.php delete mode 100644 lib/scssphp/scssphp/src/Version.php delete mode 100644 lib/scssphp/scssphp/src/Warn.php delete mode 100644 lib/symfony/cache-contracts/.gitignore delete mode 100644 lib/symfony/cache-contracts/CHANGELOG.md delete mode 100644 lib/symfony/cache-contracts/CacheInterface.php delete mode 100644 lib/symfony/cache-contracts/CacheTrait.php delete mode 100644 lib/symfony/cache-contracts/CallbackInterface.php delete mode 100644 lib/symfony/cache-contracts/ItemInterface.php delete mode 100644 lib/symfony/cache-contracts/LICENSE delete mode 100644 lib/symfony/cache-contracts/README.md delete mode 100644 lib/symfony/cache-contracts/TagAwareCacheInterface.php delete mode 100644 lib/symfony/cache-contracts/composer.json delete mode 100644 lib/symfony/cache/Adapter/AbstractAdapter.php delete mode 100644 lib/symfony/cache/Adapter/AbstractTagAwareAdapter.php delete mode 100644 lib/symfony/cache/Adapter/AdapterInterface.php delete mode 100644 lib/symfony/cache/Adapter/ApcuAdapter.php delete mode 100644 lib/symfony/cache/Adapter/ArrayAdapter.php delete mode 100644 lib/symfony/cache/Adapter/ChainAdapter.php delete mode 100644 lib/symfony/cache/Adapter/CouchbaseBucketAdapter.php delete mode 100644 lib/symfony/cache/Adapter/CouchbaseCollectionAdapter.php delete mode 100644 lib/symfony/cache/Adapter/DoctrineAdapter.php delete mode 100644 lib/symfony/cache/Adapter/DoctrineDbalAdapter.php delete mode 100644 lib/symfony/cache/Adapter/FilesystemAdapter.php delete mode 100644 lib/symfony/cache/Adapter/FilesystemTagAwareAdapter.php delete mode 100644 lib/symfony/cache/Adapter/MemcachedAdapter.php delete mode 100644 lib/symfony/cache/Adapter/NullAdapter.php delete mode 100644 lib/symfony/cache/Adapter/ParameterNormalizer.php delete mode 100644 lib/symfony/cache/Adapter/PdoAdapter.php delete mode 100644 lib/symfony/cache/Adapter/PhpArrayAdapter.php delete mode 100644 lib/symfony/cache/Adapter/PhpFilesAdapter.php delete mode 100644 lib/symfony/cache/Adapter/ProxyAdapter.php delete mode 100644 lib/symfony/cache/Adapter/Psr16Adapter.php delete mode 100644 lib/symfony/cache/Adapter/RedisAdapter.php delete mode 100644 lib/symfony/cache/Adapter/RedisTagAwareAdapter.php delete mode 100644 lib/symfony/cache/Adapter/TagAwareAdapter.php delete mode 100644 lib/symfony/cache/Adapter/TagAwareAdapterInterface.php delete mode 100644 lib/symfony/cache/Adapter/TraceableAdapter.php delete mode 100644 lib/symfony/cache/Adapter/TraceableTagAwareAdapter.php delete mode 100644 lib/symfony/cache/CHANGELOG.md delete mode 100644 lib/symfony/cache/CacheItem.php delete mode 100644 lib/symfony/cache/DataCollector/CacheDataCollector.php delete mode 100644 lib/symfony/cache/DependencyInjection/CacheCollectorPass.php delete mode 100644 lib/symfony/cache/DependencyInjection/CachePoolClearerPass.php delete mode 100644 lib/symfony/cache/DependencyInjection/CachePoolPass.php delete mode 100644 lib/symfony/cache/DependencyInjection/CachePoolPrunerPass.php delete mode 100644 lib/symfony/cache/DoctrineProvider.php delete mode 100644 lib/symfony/cache/Exception/CacheException.php delete mode 100644 lib/symfony/cache/Exception/InvalidArgumentException.php delete mode 100644 lib/symfony/cache/Exception/LogicException.php delete mode 100644 lib/symfony/cache/LICENSE delete mode 100644 lib/symfony/cache/LockRegistry.php delete mode 100644 lib/symfony/cache/Marshaller/DefaultMarshaller.php delete mode 100644 lib/symfony/cache/Marshaller/DeflateMarshaller.php delete mode 100644 lib/symfony/cache/Marshaller/MarshallerInterface.php delete mode 100644 lib/symfony/cache/Marshaller/SodiumMarshaller.php delete mode 100644 lib/symfony/cache/Marshaller/TagAwareMarshaller.php delete mode 100644 lib/symfony/cache/Messenger/EarlyExpirationDispatcher.php delete mode 100644 lib/symfony/cache/Messenger/EarlyExpirationHandler.php delete mode 100644 lib/symfony/cache/Messenger/EarlyExpirationMessage.php delete mode 100644 lib/symfony/cache/PruneableInterface.php delete mode 100644 lib/symfony/cache/Psr16Cache.php delete mode 100644 lib/symfony/cache/README.md delete mode 100644 lib/symfony/cache/ResettableInterface.php delete mode 100644 lib/symfony/cache/Traits/AbstractAdapterTrait.php delete mode 100644 lib/symfony/cache/Traits/ContractsTrait.php delete mode 100644 lib/symfony/cache/Traits/FilesystemCommonTrait.php delete mode 100644 lib/symfony/cache/Traits/FilesystemTrait.php delete mode 100644 lib/symfony/cache/Traits/ProxyTrait.php delete mode 100644 lib/symfony/cache/Traits/RedisClusterNodeProxy.php delete mode 100644 lib/symfony/cache/Traits/RedisClusterProxy.php delete mode 100644 lib/symfony/cache/Traits/RedisProxy.php delete mode 100644 lib/symfony/cache/Traits/RedisTrait.php delete mode 100644 lib/symfony/cache/composer.json delete mode 100644 lib/symfony/config/Builder/ClassBuilder.php delete mode 100644 lib/symfony/config/Builder/ConfigBuilderGenerator.php delete mode 100644 lib/symfony/config/Builder/ConfigBuilderGeneratorInterface.php delete mode 100644 lib/symfony/config/Builder/ConfigBuilderInterface.php delete mode 100644 lib/symfony/config/Builder/Method.php delete mode 100644 lib/symfony/config/Builder/Property.php delete mode 100644 lib/symfony/config/CHANGELOG.md delete mode 100644 lib/symfony/config/ConfigCache.php delete mode 100644 lib/symfony/config/ConfigCacheFactory.php delete mode 100644 lib/symfony/config/ConfigCacheFactoryInterface.php delete mode 100644 lib/symfony/config/ConfigCacheInterface.php delete mode 100644 lib/symfony/config/Definition/ArrayNode.php delete mode 100644 lib/symfony/config/Definition/BaseNode.php delete mode 100644 lib/symfony/config/Definition/BooleanNode.php delete mode 100644 lib/symfony/config/Definition/Builder/ArrayNodeDefinition.php delete mode 100644 lib/symfony/config/Definition/Builder/BooleanNodeDefinition.php delete mode 100644 lib/symfony/config/Definition/Builder/BuilderAwareInterface.php delete mode 100644 lib/symfony/config/Definition/Builder/EnumNodeDefinition.php delete mode 100644 lib/symfony/config/Definition/Builder/ExprBuilder.php delete mode 100644 lib/symfony/config/Definition/Builder/FloatNodeDefinition.php delete mode 100644 lib/symfony/config/Definition/Builder/IntegerNodeDefinition.php delete mode 100644 lib/symfony/config/Definition/Builder/MergeBuilder.php delete mode 100644 lib/symfony/config/Definition/Builder/NodeBuilder.php delete mode 100644 lib/symfony/config/Definition/Builder/NodeDefinition.php delete mode 100644 lib/symfony/config/Definition/Builder/NodeParentInterface.php delete mode 100644 lib/symfony/config/Definition/Builder/NormalizationBuilder.php delete mode 100644 lib/symfony/config/Definition/Builder/NumericNodeDefinition.php delete mode 100644 lib/symfony/config/Definition/Builder/ParentNodeDefinitionInterface.php delete mode 100644 lib/symfony/config/Definition/Builder/ScalarNodeDefinition.php delete mode 100644 lib/symfony/config/Definition/Builder/TreeBuilder.php delete mode 100644 lib/symfony/config/Definition/Builder/ValidationBuilder.php delete mode 100644 lib/symfony/config/Definition/Builder/VariableNodeDefinition.php delete mode 100644 lib/symfony/config/Definition/ConfigurationInterface.php delete mode 100644 lib/symfony/config/Definition/Dumper/XmlReferenceDumper.php delete mode 100644 lib/symfony/config/Definition/Dumper/YamlReferenceDumper.php delete mode 100644 lib/symfony/config/Definition/EnumNode.php delete mode 100644 lib/symfony/config/Definition/Exception/DuplicateKeyException.php delete mode 100644 lib/symfony/config/Definition/Exception/Exception.php delete mode 100644 lib/symfony/config/Definition/Exception/ForbiddenOverwriteException.php delete mode 100644 lib/symfony/config/Definition/Exception/InvalidConfigurationException.php delete mode 100644 lib/symfony/config/Definition/Exception/InvalidDefinitionException.php delete mode 100644 lib/symfony/config/Definition/Exception/InvalidTypeException.php delete mode 100644 lib/symfony/config/Definition/Exception/UnsetKeyException.php delete mode 100644 lib/symfony/config/Definition/FloatNode.php delete mode 100644 lib/symfony/config/Definition/IntegerNode.php delete mode 100644 lib/symfony/config/Definition/NodeInterface.php delete mode 100644 lib/symfony/config/Definition/NumericNode.php delete mode 100644 lib/symfony/config/Definition/Processor.php delete mode 100644 lib/symfony/config/Definition/PrototypeNodeInterface.php delete mode 100644 lib/symfony/config/Definition/PrototypedArrayNode.php delete mode 100644 lib/symfony/config/Definition/ScalarNode.php delete mode 100644 lib/symfony/config/Definition/VariableNode.php delete mode 100644 lib/symfony/config/Exception/FileLoaderImportCircularReferenceException.php delete mode 100644 lib/symfony/config/Exception/FileLocatorFileNotFoundException.php delete mode 100644 lib/symfony/config/Exception/LoaderLoadException.php delete mode 100644 lib/symfony/config/FileLocator.php delete mode 100644 lib/symfony/config/FileLocatorInterface.php delete mode 100644 lib/symfony/config/LICENSE delete mode 100644 lib/symfony/config/Loader/DelegatingLoader.php delete mode 100644 lib/symfony/config/Loader/FileLoader.php delete mode 100644 lib/symfony/config/Loader/GlobFileLoader.php delete mode 100644 lib/symfony/config/Loader/Loader.php delete mode 100644 lib/symfony/config/Loader/LoaderInterface.php delete mode 100644 lib/symfony/config/Loader/LoaderResolver.php delete mode 100644 lib/symfony/config/Loader/LoaderResolverInterface.php delete mode 100644 lib/symfony/config/Loader/ParamConfigurator.php delete mode 100644 lib/symfony/config/README.md delete mode 100644 lib/symfony/config/Resource/ClassExistenceResource.php delete mode 100644 lib/symfony/config/Resource/ComposerResource.php delete mode 100644 lib/symfony/config/Resource/DirectoryResource.php delete mode 100644 lib/symfony/config/Resource/FileExistenceResource.php delete mode 100644 lib/symfony/config/Resource/FileResource.php delete mode 100644 lib/symfony/config/Resource/GlobResource.php delete mode 100644 lib/symfony/config/Resource/ReflectionClassResource.php delete mode 100644 lib/symfony/config/Resource/ResourceInterface.php delete mode 100644 lib/symfony/config/Resource/SelfCheckingResourceChecker.php delete mode 100644 lib/symfony/config/Resource/SelfCheckingResourceInterface.php delete mode 100644 lib/symfony/config/ResourceCheckerConfigCache.php delete mode 100644 lib/symfony/config/ResourceCheckerConfigCacheFactory.php delete mode 100644 lib/symfony/config/ResourceCheckerInterface.php delete mode 100644 lib/symfony/config/Util/Exception/InvalidXmlException.php delete mode 100644 lib/symfony/config/Util/Exception/XmlParsingException.php delete mode 100644 lib/symfony/config/Util/XmlUtils.php delete mode 100644 lib/symfony/config/composer.json delete mode 100644 lib/symfony/console/Application.php delete mode 100644 lib/symfony/console/Attribute/AsCommand.php delete mode 100644 lib/symfony/console/CHANGELOG.md delete mode 100644 lib/symfony/console/CI/GithubActionReporter.php delete mode 100644 lib/symfony/console/Color.php delete mode 100644 lib/symfony/console/Command/Command.php delete mode 100644 lib/symfony/console/Command/CompleteCommand.php delete mode 100644 lib/symfony/console/Command/DumpCompletionCommand.php delete mode 100644 lib/symfony/console/Command/HelpCommand.php delete mode 100644 lib/symfony/console/Command/LazyCommand.php delete mode 100644 lib/symfony/console/Command/ListCommand.php delete mode 100644 lib/symfony/console/Command/LockableTrait.php delete mode 100644 lib/symfony/console/Command/SignalableCommandInterface.php delete mode 100644 lib/symfony/console/CommandLoader/CommandLoaderInterface.php delete mode 100644 lib/symfony/console/CommandLoader/ContainerCommandLoader.php delete mode 100644 lib/symfony/console/CommandLoader/FactoryCommandLoader.php delete mode 100644 lib/symfony/console/Completion/CompletionInput.php delete mode 100644 lib/symfony/console/Completion/CompletionSuggestions.php delete mode 100644 lib/symfony/console/Completion/Output/BashCompletionOutput.php delete mode 100644 lib/symfony/console/Completion/Output/CompletionOutputInterface.php delete mode 100644 lib/symfony/console/Completion/Suggestion.php delete mode 100644 lib/symfony/console/ConsoleEvents.php delete mode 100644 lib/symfony/console/Cursor.php delete mode 100644 lib/symfony/console/DependencyInjection/AddConsoleCommandPass.php delete mode 100644 lib/symfony/console/Descriptor/ApplicationDescription.php delete mode 100644 lib/symfony/console/Descriptor/Descriptor.php delete mode 100644 lib/symfony/console/Descriptor/DescriptorInterface.php delete mode 100644 lib/symfony/console/Descriptor/JsonDescriptor.php delete mode 100644 lib/symfony/console/Descriptor/MarkdownDescriptor.php delete mode 100644 lib/symfony/console/Descriptor/TextDescriptor.php delete mode 100644 lib/symfony/console/Descriptor/XmlDescriptor.php delete mode 100644 lib/symfony/console/Event/ConsoleCommandEvent.php delete mode 100644 lib/symfony/console/Event/ConsoleErrorEvent.php delete mode 100644 lib/symfony/console/Event/ConsoleEvent.php delete mode 100644 lib/symfony/console/Event/ConsoleSignalEvent.php delete mode 100644 lib/symfony/console/Event/ConsoleTerminateEvent.php delete mode 100644 lib/symfony/console/EventListener/ErrorListener.php delete mode 100644 lib/symfony/console/Exception/CommandNotFoundException.php delete mode 100644 lib/symfony/console/Exception/ExceptionInterface.php delete mode 100644 lib/symfony/console/Exception/InvalidArgumentException.php delete mode 100644 lib/symfony/console/Exception/InvalidOptionException.php delete mode 100644 lib/symfony/console/Exception/LogicException.php delete mode 100644 lib/symfony/console/Exception/MissingInputException.php delete mode 100644 lib/symfony/console/Exception/NamespaceNotFoundException.php delete mode 100644 lib/symfony/console/Exception/RuntimeException.php delete mode 100644 lib/symfony/console/Formatter/NullOutputFormatter.php delete mode 100644 lib/symfony/console/Formatter/NullOutputFormatterStyle.php delete mode 100644 lib/symfony/console/Formatter/OutputFormatter.php delete mode 100644 lib/symfony/console/Formatter/OutputFormatterInterface.php delete mode 100644 lib/symfony/console/Formatter/OutputFormatterStyle.php delete mode 100644 lib/symfony/console/Formatter/OutputFormatterStyleInterface.php delete mode 100644 lib/symfony/console/Formatter/OutputFormatterStyleStack.php delete mode 100644 lib/symfony/console/Formatter/WrappableOutputFormatterInterface.php delete mode 100644 lib/symfony/console/Helper/DebugFormatterHelper.php delete mode 100644 lib/symfony/console/Helper/DescriptorHelper.php delete mode 100644 lib/symfony/console/Helper/Dumper.php delete mode 100644 lib/symfony/console/Helper/FormatterHelper.php delete mode 100644 lib/symfony/console/Helper/Helper.php delete mode 100644 lib/symfony/console/Helper/HelperInterface.php delete mode 100644 lib/symfony/console/Helper/HelperSet.php delete mode 100644 lib/symfony/console/Helper/InputAwareHelper.php delete mode 100644 lib/symfony/console/Helper/ProcessHelper.php delete mode 100644 lib/symfony/console/Helper/ProgressBar.php delete mode 100644 lib/symfony/console/Helper/ProgressIndicator.php delete mode 100644 lib/symfony/console/Helper/QuestionHelper.php delete mode 100644 lib/symfony/console/Helper/SymfonyQuestionHelper.php delete mode 100644 lib/symfony/console/Helper/Table.php delete mode 100644 lib/symfony/console/Helper/TableCell.php delete mode 100644 lib/symfony/console/Helper/TableCellStyle.php delete mode 100644 lib/symfony/console/Helper/TableRows.php delete mode 100644 lib/symfony/console/Helper/TableSeparator.php delete mode 100644 lib/symfony/console/Helper/TableStyle.php delete mode 100644 lib/symfony/console/Input/ArgvInput.php delete mode 100644 lib/symfony/console/Input/ArrayInput.php delete mode 100644 lib/symfony/console/Input/Input.php delete mode 100644 lib/symfony/console/Input/InputArgument.php delete mode 100644 lib/symfony/console/Input/InputAwareInterface.php delete mode 100644 lib/symfony/console/Input/InputDefinition.php delete mode 100644 lib/symfony/console/Input/InputInterface.php delete mode 100644 lib/symfony/console/Input/InputOption.php delete mode 100644 lib/symfony/console/Input/StreamableInputInterface.php delete mode 100644 lib/symfony/console/Input/StringInput.php delete mode 100644 lib/symfony/console/LICENSE delete mode 100644 lib/symfony/console/Logger/ConsoleLogger.php delete mode 100644 lib/symfony/console/Output/BufferedOutput.php delete mode 100644 lib/symfony/console/Output/ConsoleOutput.php delete mode 100644 lib/symfony/console/Output/ConsoleOutputInterface.php delete mode 100644 lib/symfony/console/Output/ConsoleSectionOutput.php delete mode 100644 lib/symfony/console/Output/NullOutput.php delete mode 100644 lib/symfony/console/Output/Output.php delete mode 100644 lib/symfony/console/Output/OutputInterface.php delete mode 100644 lib/symfony/console/Output/StreamOutput.php delete mode 100644 lib/symfony/console/Output/TrimmedBufferOutput.php delete mode 100644 lib/symfony/console/Question/ChoiceQuestion.php delete mode 100644 lib/symfony/console/Question/ConfirmationQuestion.php delete mode 100644 lib/symfony/console/Question/Question.php delete mode 100644 lib/symfony/console/README.md delete mode 100644 lib/symfony/console/Resources/bin/hiddeninput.exe delete mode 100644 lib/symfony/console/Resources/completion.bash delete mode 100644 lib/symfony/console/SignalRegistry/SignalRegistry.php delete mode 100644 lib/symfony/console/SingleCommandApplication.php delete mode 100644 lib/symfony/console/Style/OutputStyle.php delete mode 100644 lib/symfony/console/Style/StyleInterface.php delete mode 100644 lib/symfony/console/Style/SymfonyStyle.php delete mode 100644 lib/symfony/console/Terminal.php delete mode 100644 lib/symfony/console/Tester/ApplicationTester.php delete mode 100644 lib/symfony/console/Tester/CommandCompletionTester.php delete mode 100644 lib/symfony/console/Tester/CommandTester.php delete mode 100644 lib/symfony/console/Tester/Constraint/CommandIsSuccessful.php delete mode 100644 lib/symfony/console/Tester/TesterTrait.php delete mode 100644 lib/symfony/console/composer.json delete mode 100644 lib/symfony/css-selector/CHANGELOG.md delete mode 100644 lib/symfony/css-selector/CssSelectorConverter.php delete mode 100644 lib/symfony/css-selector/Exception/ExceptionInterface.php delete mode 100644 lib/symfony/css-selector/Exception/ExpressionErrorException.php delete mode 100644 lib/symfony/css-selector/Exception/InternalErrorException.php delete mode 100644 lib/symfony/css-selector/Exception/ParseException.php delete mode 100644 lib/symfony/css-selector/Exception/SyntaxErrorException.php delete mode 100644 lib/symfony/css-selector/LICENSE delete mode 100644 lib/symfony/css-selector/Node/AbstractNode.php delete mode 100644 lib/symfony/css-selector/Node/AttributeNode.php delete mode 100644 lib/symfony/css-selector/Node/ClassNode.php delete mode 100644 lib/symfony/css-selector/Node/CombinedSelectorNode.php delete mode 100644 lib/symfony/css-selector/Node/ElementNode.php delete mode 100644 lib/symfony/css-selector/Node/FunctionNode.php delete mode 100644 lib/symfony/css-selector/Node/HashNode.php delete mode 100644 lib/symfony/css-selector/Node/NegationNode.php delete mode 100644 lib/symfony/css-selector/Node/NodeInterface.php delete mode 100644 lib/symfony/css-selector/Node/PseudoNode.php delete mode 100644 lib/symfony/css-selector/Node/SelectorNode.php delete mode 100644 lib/symfony/css-selector/Node/Specificity.php delete mode 100644 lib/symfony/css-selector/Parser/Handler/CommentHandler.php delete mode 100644 lib/symfony/css-selector/Parser/Handler/HandlerInterface.php delete mode 100644 lib/symfony/css-selector/Parser/Handler/HashHandler.php delete mode 100644 lib/symfony/css-selector/Parser/Handler/IdentifierHandler.php delete mode 100644 lib/symfony/css-selector/Parser/Handler/NumberHandler.php delete mode 100644 lib/symfony/css-selector/Parser/Handler/StringHandler.php delete mode 100644 lib/symfony/css-selector/Parser/Handler/WhitespaceHandler.php delete mode 100644 lib/symfony/css-selector/Parser/Parser.php delete mode 100644 lib/symfony/css-selector/Parser/ParserInterface.php delete mode 100644 lib/symfony/css-selector/Parser/Reader.php delete mode 100644 lib/symfony/css-selector/Parser/Shortcut/ClassParser.php delete mode 100644 lib/symfony/css-selector/Parser/Shortcut/ElementParser.php delete mode 100644 lib/symfony/css-selector/Parser/Shortcut/EmptyStringParser.php delete mode 100644 lib/symfony/css-selector/Parser/Shortcut/HashParser.php delete mode 100644 lib/symfony/css-selector/Parser/Token.php delete mode 100644 lib/symfony/css-selector/Parser/TokenStream.php delete mode 100644 lib/symfony/css-selector/Parser/Tokenizer/Tokenizer.php delete mode 100644 lib/symfony/css-selector/Parser/Tokenizer/TokenizerEscaping.php delete mode 100644 lib/symfony/css-selector/Parser/Tokenizer/TokenizerPatterns.php delete mode 100644 lib/symfony/css-selector/README.md delete mode 100644 lib/symfony/css-selector/XPath/Extension/AbstractExtension.php delete mode 100644 lib/symfony/css-selector/XPath/Extension/AttributeMatchingExtension.php delete mode 100644 lib/symfony/css-selector/XPath/Extension/CombinationExtension.php delete mode 100644 lib/symfony/css-selector/XPath/Extension/ExtensionInterface.php delete mode 100644 lib/symfony/css-selector/XPath/Extension/FunctionExtension.php delete mode 100644 lib/symfony/css-selector/XPath/Extension/HtmlExtension.php delete mode 100644 lib/symfony/css-selector/XPath/Extension/NodeExtension.php delete mode 100644 lib/symfony/css-selector/XPath/Extension/PseudoClassExtension.php delete mode 100644 lib/symfony/css-selector/XPath/Translator.php delete mode 100644 lib/symfony/css-selector/XPath/TranslatorInterface.php delete mode 100644 lib/symfony/css-selector/XPath/XPathExpr.php delete mode 100644 lib/symfony/css-selector/composer.json delete mode 100644 lib/symfony/dependency-injection/Alias.php delete mode 100644 lib/symfony/dependency-injection/Argument/AbstractArgument.php delete mode 100644 lib/symfony/dependency-injection/Argument/ArgumentInterface.php delete mode 100644 lib/symfony/dependency-injection/Argument/BoundArgument.php delete mode 100644 lib/symfony/dependency-injection/Argument/IteratorArgument.php delete mode 100644 lib/symfony/dependency-injection/Argument/ReferenceSetArgumentTrait.php delete mode 100644 lib/symfony/dependency-injection/Argument/RewindableGenerator.php delete mode 100644 lib/symfony/dependency-injection/Argument/ServiceClosureArgument.php delete mode 100644 lib/symfony/dependency-injection/Argument/ServiceLocator.php delete mode 100644 lib/symfony/dependency-injection/Argument/ServiceLocatorArgument.php delete mode 100644 lib/symfony/dependency-injection/Argument/TaggedIteratorArgument.php delete mode 100644 lib/symfony/dependency-injection/Attribute/AsTaggedItem.php delete mode 100644 lib/symfony/dependency-injection/Attribute/Autoconfigure.php delete mode 100644 lib/symfony/dependency-injection/Attribute/AutoconfigureTag.php delete mode 100644 lib/symfony/dependency-injection/Attribute/TaggedIterator.php delete mode 100644 lib/symfony/dependency-injection/Attribute/TaggedLocator.php delete mode 100644 lib/symfony/dependency-injection/Attribute/Target.php delete mode 100644 lib/symfony/dependency-injection/Attribute/When.php delete mode 100644 lib/symfony/dependency-injection/CHANGELOG.md delete mode 100644 lib/symfony/dependency-injection/ChildDefinition.php delete mode 100644 lib/symfony/dependency-injection/Compiler/AbstractRecursivePass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/AliasDeprecatedPublicServicesPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/AttributeAutoconfigurationPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/AutoAliasServicePass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/AutowirePass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/AutowireRequiredPropertiesPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/Compiler.php delete mode 100644 lib/symfony/dependency-injection/Compiler/CompilerPassInterface.php delete mode 100644 lib/symfony/dependency-injection/Compiler/DecoratorServicePass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/ExtensionCompilerPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/PassConfig.php delete mode 100644 lib/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php delete mode 100644 lib/symfony/dependency-injection/Compiler/RegisterAutoconfigureAttributesPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/RegisterReverseContainerPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/ResolveBindingsPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/ResolveClassPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/ResolveDecoratorStackPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/ResolveHotPathPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/ResolveNoPreloadPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/ResolvePrivatesPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php delete mode 100644 lib/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php delete mode 100644 lib/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php delete mode 100644 lib/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php delete mode 100644 lib/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php delete mode 100644 lib/symfony/dependency-injection/Config/ContainerParametersResource.php delete mode 100644 lib/symfony/dependency-injection/Config/ContainerParametersResourceChecker.php delete mode 100644 lib/symfony/dependency-injection/Container.php delete mode 100644 lib/symfony/dependency-injection/ContainerAwareInterface.php delete mode 100644 lib/symfony/dependency-injection/ContainerAwareTrait.php delete mode 100644 lib/symfony/dependency-injection/ContainerBuilder.php delete mode 100644 lib/symfony/dependency-injection/ContainerInterface.php delete mode 100644 lib/symfony/dependency-injection/Definition.php delete mode 100644 lib/symfony/dependency-injection/Dumper/Dumper.php delete mode 100644 lib/symfony/dependency-injection/Dumper/DumperInterface.php delete mode 100644 lib/symfony/dependency-injection/Dumper/GraphvizDumper.php delete mode 100644 lib/symfony/dependency-injection/Dumper/PhpDumper.php delete mode 100644 lib/symfony/dependency-injection/Dumper/Preloader.php delete mode 100644 lib/symfony/dependency-injection/Dumper/XmlDumper.php delete mode 100644 lib/symfony/dependency-injection/Dumper/YamlDumper.php delete mode 100644 lib/symfony/dependency-injection/EnvVarLoaderInterface.php delete mode 100644 lib/symfony/dependency-injection/EnvVarProcessor.php delete mode 100644 lib/symfony/dependency-injection/EnvVarProcessorInterface.php delete mode 100644 lib/symfony/dependency-injection/Exception/AutowiringFailedException.php delete mode 100644 lib/symfony/dependency-injection/Exception/BadMethodCallException.php delete mode 100644 lib/symfony/dependency-injection/Exception/EnvNotFoundException.php delete mode 100644 lib/symfony/dependency-injection/Exception/EnvParameterException.php delete mode 100644 lib/symfony/dependency-injection/Exception/ExceptionInterface.php delete mode 100644 lib/symfony/dependency-injection/Exception/InvalidArgumentException.php delete mode 100644 lib/symfony/dependency-injection/Exception/InvalidParameterTypeException.php delete mode 100644 lib/symfony/dependency-injection/Exception/LogicException.php delete mode 100644 lib/symfony/dependency-injection/Exception/OutOfBoundsException.php delete mode 100644 lib/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php delete mode 100644 lib/symfony/dependency-injection/Exception/ParameterNotFoundException.php delete mode 100644 lib/symfony/dependency-injection/Exception/RuntimeException.php delete mode 100644 lib/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php delete mode 100644 lib/symfony/dependency-injection/Exception/ServiceNotFoundException.php delete mode 100644 lib/symfony/dependency-injection/ExpressionLanguage.php delete mode 100644 lib/symfony/dependency-injection/ExpressionLanguageProvider.php delete mode 100644 lib/symfony/dependency-injection/Extension/ConfigurationExtensionInterface.php delete mode 100644 lib/symfony/dependency-injection/Extension/Extension.php delete mode 100644 lib/symfony/dependency-injection/Extension/ExtensionInterface.php delete mode 100644 lib/symfony/dependency-injection/Extension/PrependExtensionInterface.php delete mode 100644 lib/symfony/dependency-injection/LICENSE delete mode 100644 lib/symfony/dependency-injection/LazyProxy/Instantiator/InstantiatorInterface.php delete mode 100644 lib/symfony/dependency-injection/LazyProxy/Instantiator/RealServiceInstantiator.php delete mode 100644 lib/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php delete mode 100644 lib/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php delete mode 100644 lib/symfony/dependency-injection/LazyProxy/ProxyHelper.php delete mode 100644 lib/symfony/dependency-injection/Loader/ClosureLoader.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/AliasConfigurator.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/ClosureReferenceConfigurator.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/EnvConfigurator.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/InlineServiceConfigurator.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/ParametersConfigurator.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/ReferenceConfigurator.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/Traits/AbstractTrait.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/Traits/ArgumentTrait.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/Traits/AutoconfigureTrait.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/Traits/AutowireTrait.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/Traits/BindTrait.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/Traits/CallTrait.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/Traits/ClassTrait.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/Traits/ConfiguratorTrait.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/Traits/DeprecateTrait.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/Traits/FactoryTrait.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/Traits/FileTrait.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/Traits/LazyTrait.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/Traits/ParentTrait.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/Traits/PropertyTrait.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/Traits/PublicTrait.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/Traits/ShareTrait.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/Traits/SyntheticTrait.php delete mode 100644 lib/symfony/dependency-injection/Loader/Configurator/Traits/TagTrait.php delete mode 100644 lib/symfony/dependency-injection/Loader/DirectoryLoader.php delete mode 100644 lib/symfony/dependency-injection/Loader/FileLoader.php delete mode 100644 lib/symfony/dependency-injection/Loader/GlobFileLoader.php delete mode 100644 lib/symfony/dependency-injection/Loader/IniFileLoader.php delete mode 100644 lib/symfony/dependency-injection/Loader/PhpFileLoader.php delete mode 100644 lib/symfony/dependency-injection/Loader/XmlFileLoader.php delete mode 100644 lib/symfony/dependency-injection/Loader/YamlFileLoader.php delete mode 100644 lib/symfony/dependency-injection/Loader/schema/dic/services/services-1.0.xsd delete mode 100644 lib/symfony/dependency-injection/Parameter.php delete mode 100644 lib/symfony/dependency-injection/ParameterBag/ContainerBag.php delete mode 100644 lib/symfony/dependency-injection/ParameterBag/ContainerBagInterface.php delete mode 100644 lib/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php delete mode 100644 lib/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php delete mode 100644 lib/symfony/dependency-injection/ParameterBag/ParameterBag.php delete mode 100644 lib/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php delete mode 100644 lib/symfony/dependency-injection/README.md delete mode 100644 lib/symfony/dependency-injection/Reference.php delete mode 100644 lib/symfony/dependency-injection/ReverseContainer.php delete mode 100644 lib/symfony/dependency-injection/ServiceLocator.php delete mode 100644 lib/symfony/dependency-injection/TaggedContainerInterface.php delete mode 100644 lib/symfony/dependency-injection/TypedReference.php delete mode 100644 lib/symfony/dependency-injection/Variable.php delete mode 100644 lib/symfony/dependency-injection/composer.json delete mode 100644 lib/symfony/deprecation-contracts/.gitignore delete mode 100644 lib/symfony/deprecation-contracts/CHANGELOG.md delete mode 100644 lib/symfony/deprecation-contracts/LICENSE delete mode 100644 lib/symfony/deprecation-contracts/README.md delete mode 100644 lib/symfony/deprecation-contracts/composer.json delete mode 100644 lib/symfony/deprecation-contracts/function.php delete mode 100644 lib/symfony/dotenv/CHANGELOG.md delete mode 100644 lib/symfony/dotenv/Command/DebugCommand.php delete mode 100644 lib/symfony/dotenv/Command/DotenvDumpCommand.php delete mode 100644 lib/symfony/dotenv/Dotenv.php delete mode 100644 lib/symfony/dotenv/Exception/ExceptionInterface.php delete mode 100644 lib/symfony/dotenv/Exception/FormatException.php delete mode 100644 lib/symfony/dotenv/Exception/FormatExceptionContext.php delete mode 100644 lib/symfony/dotenv/Exception/PathException.php delete mode 100644 lib/symfony/dotenv/LICENSE delete mode 100644 lib/symfony/dotenv/README.md delete mode 100644 lib/symfony/dotenv/composer.json delete mode 100644 lib/symfony/error-handler/BufferingLogger.php delete mode 100644 lib/symfony/error-handler/CHANGELOG.md delete mode 100644 lib/symfony/error-handler/Debug.php delete mode 100644 lib/symfony/error-handler/DebugClassLoader.php delete mode 100644 lib/symfony/error-handler/Error/ClassNotFoundError.php delete mode 100644 lib/symfony/error-handler/Error/FatalError.php delete mode 100644 lib/symfony/error-handler/Error/OutOfMemoryError.php delete mode 100644 lib/symfony/error-handler/Error/UndefinedFunctionError.php delete mode 100644 lib/symfony/error-handler/Error/UndefinedMethodError.php delete mode 100644 lib/symfony/error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php delete mode 100644 lib/symfony/error-handler/ErrorEnhancer/ErrorEnhancerInterface.php delete mode 100644 lib/symfony/error-handler/ErrorEnhancer/UndefinedFunctionErrorEnhancer.php delete mode 100644 lib/symfony/error-handler/ErrorEnhancer/UndefinedMethodErrorEnhancer.php delete mode 100644 lib/symfony/error-handler/ErrorHandler.php delete mode 100644 lib/symfony/error-handler/ErrorRenderer/CliErrorRenderer.php delete mode 100644 lib/symfony/error-handler/ErrorRenderer/ErrorRendererInterface.php delete mode 100644 lib/symfony/error-handler/ErrorRenderer/HtmlErrorRenderer.php delete mode 100644 lib/symfony/error-handler/ErrorRenderer/SerializerErrorRenderer.php delete mode 100644 lib/symfony/error-handler/Exception/FlattenException.php delete mode 100644 lib/symfony/error-handler/Exception/SilencedErrorContext.php delete mode 100644 lib/symfony/error-handler/Internal/TentativeTypes.php delete mode 100644 lib/symfony/error-handler/LICENSE delete mode 100644 lib/symfony/error-handler/README.md delete mode 100644 lib/symfony/error-handler/Resources/assets/css/error.css delete mode 100644 lib/symfony/error-handler/Resources/assets/css/exception.css delete mode 100644 lib/symfony/error-handler/Resources/assets/css/exception_full.css delete mode 100644 lib/symfony/error-handler/Resources/assets/images/chevron-right.svg delete mode 100644 lib/symfony/error-handler/Resources/assets/images/favicon.png.base64 delete mode 100644 lib/symfony/error-handler/Resources/assets/images/icon-book.svg delete mode 100644 lib/symfony/error-handler/Resources/assets/images/icon-copy.svg delete mode 100644 lib/symfony/error-handler/Resources/assets/images/icon-minus-square-o.svg delete mode 100644 lib/symfony/error-handler/Resources/assets/images/icon-minus-square.svg delete mode 100644 lib/symfony/error-handler/Resources/assets/images/icon-plus-square-o.svg delete mode 100644 lib/symfony/error-handler/Resources/assets/images/icon-plus-square.svg delete mode 100644 lib/symfony/error-handler/Resources/assets/images/icon-support.svg delete mode 100644 lib/symfony/error-handler/Resources/assets/images/symfony-ghost.svg.php delete mode 100644 lib/symfony/error-handler/Resources/assets/images/symfony-logo.svg delete mode 100644 lib/symfony/error-handler/Resources/assets/js/exception.js delete mode 100644 lib/symfony/error-handler/Resources/bin/extract-tentative-return-types.php delete mode 100644 lib/symfony/error-handler/Resources/bin/patch-type-declarations delete mode 100644 lib/symfony/error-handler/Resources/views/error.html.php delete mode 100644 lib/symfony/error-handler/Resources/views/exception.html.php delete mode 100644 lib/symfony/error-handler/Resources/views/exception_full.html.php delete mode 100644 lib/symfony/error-handler/Resources/views/logs.html.php delete mode 100644 lib/symfony/error-handler/Resources/views/trace.html.php delete mode 100644 lib/symfony/error-handler/Resources/views/traces.html.php delete mode 100644 lib/symfony/error-handler/Resources/views/traces_text.html.php delete mode 100644 lib/symfony/error-handler/ThrowableUtils.php delete mode 100644 lib/symfony/error-handler/composer.json delete mode 100644 lib/symfony/event-dispatcher-contracts/.gitignore delete mode 100644 lib/symfony/event-dispatcher-contracts/CHANGELOG.md delete mode 100644 lib/symfony/event-dispatcher-contracts/Event.php delete mode 100644 lib/symfony/event-dispatcher-contracts/EventDispatcherInterface.php delete mode 100644 lib/symfony/event-dispatcher-contracts/LICENSE delete mode 100644 lib/symfony/event-dispatcher-contracts/README.md delete mode 100644 lib/symfony/event-dispatcher-contracts/composer.json delete mode 100644 lib/symfony/event-dispatcher/Attribute/AsEventListener.php delete mode 100644 lib/symfony/event-dispatcher/CHANGELOG.md delete mode 100644 lib/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php delete mode 100644 lib/symfony/event-dispatcher/Debug/WrappedListener.php delete mode 100644 lib/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php delete mode 100644 lib/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php delete mode 100644 lib/symfony/event-dispatcher/EventDispatcher.php delete mode 100644 lib/symfony/event-dispatcher/EventDispatcherInterface.php delete mode 100644 lib/symfony/event-dispatcher/EventSubscriberInterface.php delete mode 100644 lib/symfony/event-dispatcher/GenericEvent.php delete mode 100644 lib/symfony/event-dispatcher/ImmutableEventDispatcher.php delete mode 100644 lib/symfony/event-dispatcher/LICENSE delete mode 100644 lib/symfony/event-dispatcher/LegacyEventDispatcherProxy.php delete mode 100644 lib/symfony/event-dispatcher/README.md delete mode 100644 lib/symfony/event-dispatcher/composer.json delete mode 100644 lib/symfony/filesystem/CHANGELOG.md delete mode 100644 lib/symfony/filesystem/Exception/ExceptionInterface.php delete mode 100644 lib/symfony/filesystem/Exception/FileNotFoundException.php delete mode 100644 lib/symfony/filesystem/Exception/IOException.php delete mode 100644 lib/symfony/filesystem/Exception/IOExceptionInterface.php delete mode 100644 lib/symfony/filesystem/Exception/InvalidArgumentException.php delete mode 100644 lib/symfony/filesystem/Exception/RuntimeException.php delete mode 100644 lib/symfony/filesystem/Filesystem.php delete mode 100644 lib/symfony/filesystem/LICENSE delete mode 100644 lib/symfony/filesystem/Path.php delete mode 100644 lib/symfony/filesystem/README.md delete mode 100644 lib/symfony/filesystem/composer.json delete mode 100644 lib/symfony/finder/CHANGELOG.md delete mode 100644 lib/symfony/finder/Comparator/Comparator.php delete mode 100644 lib/symfony/finder/Comparator/DateComparator.php delete mode 100644 lib/symfony/finder/Comparator/NumberComparator.php delete mode 100644 lib/symfony/finder/Exception/AccessDeniedException.php delete mode 100644 lib/symfony/finder/Exception/DirectoryNotFoundException.php delete mode 100644 lib/symfony/finder/Finder.php delete mode 100644 lib/symfony/finder/Gitignore.php delete mode 100644 lib/symfony/finder/Glob.php delete mode 100644 lib/symfony/finder/Iterator/CustomFilterIterator.php delete mode 100644 lib/symfony/finder/Iterator/DateRangeFilterIterator.php delete mode 100644 lib/symfony/finder/Iterator/DepthRangeFilterIterator.php delete mode 100644 lib/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php delete mode 100644 lib/symfony/finder/Iterator/FileTypeFilterIterator.php delete mode 100644 lib/symfony/finder/Iterator/FilecontentFilterIterator.php delete mode 100644 lib/symfony/finder/Iterator/FilenameFilterIterator.php delete mode 100644 lib/symfony/finder/Iterator/LazyIterator.php delete mode 100644 lib/symfony/finder/Iterator/MultiplePcreFilterIterator.php delete mode 100644 lib/symfony/finder/Iterator/PathFilterIterator.php delete mode 100644 lib/symfony/finder/Iterator/RecursiveDirectoryIterator.php delete mode 100644 lib/symfony/finder/Iterator/SizeRangeFilterIterator.php delete mode 100644 lib/symfony/finder/Iterator/SortableIterator.php delete mode 100644 lib/symfony/finder/Iterator/VcsIgnoredFilterIterator.php delete mode 100644 lib/symfony/finder/LICENSE delete mode 100644 lib/symfony/finder/README.md delete mode 100644 lib/symfony/finder/SplFileInfo.php delete mode 100644 lib/symfony/finder/composer.json delete mode 100644 lib/symfony/form/AbstractExtension.php delete mode 100644 lib/symfony/form/AbstractRendererEngine.php delete mode 100644 lib/symfony/form/AbstractType.php delete mode 100644 lib/symfony/form/AbstractTypeExtension.php delete mode 100644 lib/symfony/form/Button.php delete mode 100644 lib/symfony/form/ButtonBuilder.php delete mode 100644 lib/symfony/form/ButtonTypeInterface.php delete mode 100644 lib/symfony/form/CHANGELOG.md delete mode 100644 lib/symfony/form/CallbackTransformer.php delete mode 100644 lib/symfony/form/ChoiceList/ArrayChoiceList.php delete mode 100644 lib/symfony/form/ChoiceList/ChoiceList.php delete mode 100644 lib/symfony/form/ChoiceList/ChoiceListInterface.php delete mode 100644 lib/symfony/form/ChoiceList/Factory/Cache/AbstractStaticOption.php delete mode 100644 lib/symfony/form/ChoiceList/Factory/Cache/ChoiceAttr.php delete mode 100644 lib/symfony/form/ChoiceList/Factory/Cache/ChoiceFieldName.php delete mode 100644 lib/symfony/form/ChoiceList/Factory/Cache/ChoiceFilter.php delete mode 100644 lib/symfony/form/ChoiceList/Factory/Cache/ChoiceLabel.php delete mode 100644 lib/symfony/form/ChoiceList/Factory/Cache/ChoiceLoader.php delete mode 100644 lib/symfony/form/ChoiceList/Factory/Cache/ChoiceTranslationParameters.php delete mode 100644 lib/symfony/form/ChoiceList/Factory/Cache/ChoiceValue.php delete mode 100644 lib/symfony/form/ChoiceList/Factory/Cache/GroupBy.php delete mode 100644 lib/symfony/form/ChoiceList/Factory/Cache/PreferredChoice.php delete mode 100644 lib/symfony/form/ChoiceList/Factory/CachingFactoryDecorator.php delete mode 100644 lib/symfony/form/ChoiceList/Factory/ChoiceListFactoryInterface.php delete mode 100644 lib/symfony/form/ChoiceList/Factory/DefaultChoiceListFactory.php delete mode 100644 lib/symfony/form/ChoiceList/Factory/PropertyAccessDecorator.php delete mode 100644 lib/symfony/form/ChoiceList/LazyChoiceList.php delete mode 100644 lib/symfony/form/ChoiceList/Loader/AbstractChoiceLoader.php delete mode 100644 lib/symfony/form/ChoiceList/Loader/CallbackChoiceLoader.php delete mode 100644 lib/symfony/form/ChoiceList/Loader/ChoiceLoaderInterface.php delete mode 100644 lib/symfony/form/ChoiceList/Loader/FilterChoiceLoaderDecorator.php delete mode 100644 lib/symfony/form/ChoiceList/Loader/IntlCallbackChoiceLoader.php delete mode 100644 lib/symfony/form/ChoiceList/View/ChoiceGroupView.php delete mode 100644 lib/symfony/form/ChoiceList/View/ChoiceListView.php delete mode 100644 lib/symfony/form/ChoiceList/View/ChoiceView.php delete mode 100644 lib/symfony/form/ClearableErrorsInterface.php delete mode 100644 lib/symfony/form/ClickableInterface.php delete mode 100644 lib/symfony/form/Command/DebugCommand.php delete mode 100644 lib/symfony/form/Console/Descriptor/Descriptor.php delete mode 100644 lib/symfony/form/Console/Descriptor/JsonDescriptor.php delete mode 100644 lib/symfony/form/Console/Descriptor/TextDescriptor.php delete mode 100644 lib/symfony/form/Console/Helper/DescriptorHelper.php delete mode 100644 lib/symfony/form/DataAccessorInterface.php delete mode 100644 lib/symfony/form/DataMapperInterface.php delete mode 100644 lib/symfony/form/DataTransformerInterface.php delete mode 100644 lib/symfony/form/DependencyInjection/FormPass.php delete mode 100644 lib/symfony/form/Event/PostSetDataEvent.php delete mode 100644 lib/symfony/form/Event/PostSubmitEvent.php delete mode 100644 lib/symfony/form/Event/PreSetDataEvent.php delete mode 100644 lib/symfony/form/Event/PreSubmitEvent.php delete mode 100644 lib/symfony/form/Event/SubmitEvent.php delete mode 100644 lib/symfony/form/Exception/AccessException.php delete mode 100644 lib/symfony/form/Exception/AlreadySubmittedException.php delete mode 100644 lib/symfony/form/Exception/BadMethodCallException.php delete mode 100644 lib/symfony/form/Exception/ErrorMappingException.php delete mode 100644 lib/symfony/form/Exception/ExceptionInterface.php delete mode 100644 lib/symfony/form/Exception/InvalidArgumentException.php delete mode 100644 lib/symfony/form/Exception/InvalidConfigurationException.php delete mode 100644 lib/symfony/form/Exception/LogicException.php delete mode 100644 lib/symfony/form/Exception/OutOfBoundsException.php delete mode 100644 lib/symfony/form/Exception/RuntimeException.php delete mode 100644 lib/symfony/form/Exception/StringCastException.php delete mode 100644 lib/symfony/form/Exception/TransformationFailedException.php delete mode 100644 lib/symfony/form/Exception/UnexpectedTypeException.php delete mode 100644 lib/symfony/form/Extension/Core/CoreExtension.php delete mode 100644 lib/symfony/form/Extension/Core/DataAccessor/CallbackAccessor.php delete mode 100644 lib/symfony/form/Extension/Core/DataAccessor/ChainAccessor.php delete mode 100644 lib/symfony/form/Extension/Core/DataAccessor/PropertyPathAccessor.php delete mode 100644 lib/symfony/form/Extension/Core/DataMapper/CheckboxListMapper.php delete mode 100644 lib/symfony/form/Extension/Core/DataMapper/DataMapper.php delete mode 100644 lib/symfony/form/Extension/Core/DataMapper/PropertyPathMapper.php delete mode 100644 lib/symfony/form/Extension/Core/DataMapper/RadioListMapper.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/ArrayToPartsTransformer.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/BaseDateTimeTransformer.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/BooleanToStringTransformer.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/DataTransformerChain.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/DateIntervalToArrayTransformer.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/DateIntervalToStringTransformer.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/DateTimeImmutableToDateTimeTransformer.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/DateTimeToHtml5LocalDateTimeTransformer.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/DateTimeZoneToStringTransformer.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/IntlTimeZoneToStringTransformer.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/StringToFloatTransformer.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/UlidToStringTransformer.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/UuidToStringTransformer.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php delete mode 100644 lib/symfony/form/Extension/Core/DataTransformer/WeekToArrayTransformer.php delete mode 100644 lib/symfony/form/Extension/Core/EventListener/FixUrlProtocolListener.php delete mode 100644 lib/symfony/form/Extension/Core/EventListener/MergeCollectionListener.php delete mode 100644 lib/symfony/form/Extension/Core/EventListener/ResizeFormListener.php delete mode 100644 lib/symfony/form/Extension/Core/EventListener/TransformationFailureListener.php delete mode 100644 lib/symfony/form/Extension/Core/EventListener/TrimListener.php delete mode 100644 lib/symfony/form/Extension/Core/Type/BaseType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/BirthdayType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/ButtonType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/CheckboxType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/ChoiceType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/CollectionType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/ColorType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/CountryType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/CurrencyType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/DateIntervalType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/DateTimeType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/DateType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/EmailType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/EnumType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/FileType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/FormType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/HiddenType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/IntegerType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/LanguageType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/LocaleType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/MoneyType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/NumberType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/PasswordType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/PercentType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/RadioType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/RangeType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/RepeatedType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/ResetType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/SearchType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/SubmitType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/TelType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/TextType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/TextareaType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/TimeType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/TimezoneType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/TransformationFailureExtension.php delete mode 100644 lib/symfony/form/Extension/Core/Type/UlidType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/UrlType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/UuidType.php delete mode 100644 lib/symfony/form/Extension/Core/Type/WeekType.php delete mode 100644 lib/symfony/form/Extension/Csrf/CsrfExtension.php delete mode 100644 lib/symfony/form/Extension/Csrf/EventListener/CsrfValidationListener.php delete mode 100644 lib/symfony/form/Extension/Csrf/Type/FormTypeCsrfExtension.php delete mode 100644 lib/symfony/form/Extension/DataCollector/DataCollectorExtension.php delete mode 100644 lib/symfony/form/Extension/DataCollector/EventListener/DataCollectorListener.php delete mode 100644 lib/symfony/form/Extension/DataCollector/FormDataCollector.php delete mode 100644 lib/symfony/form/Extension/DataCollector/FormDataCollectorInterface.php delete mode 100644 lib/symfony/form/Extension/DataCollector/FormDataExtractor.php delete mode 100644 lib/symfony/form/Extension/DataCollector/FormDataExtractorInterface.php delete mode 100644 lib/symfony/form/Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.php delete mode 100644 lib/symfony/form/Extension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.php delete mode 100644 lib/symfony/form/Extension/DataCollector/Type/DataCollectorTypeExtension.php delete mode 100644 lib/symfony/form/Extension/DependencyInjection/DependencyInjectionExtension.php delete mode 100644 lib/symfony/form/Extension/HttpFoundation/HttpFoundationExtension.php delete mode 100644 lib/symfony/form/Extension/HttpFoundation/HttpFoundationRequestHandler.php delete mode 100644 lib/symfony/form/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php delete mode 100644 lib/symfony/form/Extension/Validator/Constraints/Form.php delete mode 100644 lib/symfony/form/Extension/Validator/Constraints/FormValidator.php delete mode 100644 lib/symfony/form/Extension/Validator/EventListener/ValidationListener.php delete mode 100644 lib/symfony/form/Extension/Validator/Type/BaseValidatorExtension.php delete mode 100644 lib/symfony/form/Extension/Validator/Type/FormTypeValidatorExtension.php delete mode 100644 lib/symfony/form/Extension/Validator/Type/RepeatedTypeValidatorExtension.php delete mode 100644 lib/symfony/form/Extension/Validator/Type/SubmitTypeValidatorExtension.php delete mode 100644 lib/symfony/form/Extension/Validator/Type/UploadValidatorExtension.php delete mode 100644 lib/symfony/form/Extension/Validator/Util/ServerParams.php delete mode 100644 lib/symfony/form/Extension/Validator/ValidatorExtension.php delete mode 100644 lib/symfony/form/Extension/Validator/ValidatorTypeGuesser.php delete mode 100644 lib/symfony/form/Extension/Validator/ViolationMapper/MappingRule.php delete mode 100644 lib/symfony/form/Extension/Validator/ViolationMapper/RelativePath.php delete mode 100644 lib/symfony/form/Extension/Validator/ViolationMapper/ViolationMapper.php delete mode 100644 lib/symfony/form/Extension/Validator/ViolationMapper/ViolationMapperInterface.php delete mode 100644 lib/symfony/form/Extension/Validator/ViolationMapper/ViolationPath.php delete mode 100644 lib/symfony/form/Extension/Validator/ViolationMapper/ViolationPathIterator.php delete mode 100644 lib/symfony/form/FileUploadError.php delete mode 100644 lib/symfony/form/Form.php delete mode 100644 lib/symfony/form/FormBuilder.php delete mode 100644 lib/symfony/form/FormBuilderInterface.php delete mode 100644 lib/symfony/form/FormConfigBuilder.php delete mode 100644 lib/symfony/form/FormConfigBuilderInterface.php delete mode 100644 lib/symfony/form/FormConfigInterface.php delete mode 100644 lib/symfony/form/FormError.php delete mode 100644 lib/symfony/form/FormErrorIterator.php delete mode 100644 lib/symfony/form/FormEvent.php delete mode 100644 lib/symfony/form/FormEvents.php delete mode 100644 lib/symfony/form/FormExtensionInterface.php delete mode 100644 lib/symfony/form/FormFactory.php delete mode 100644 lib/symfony/form/FormFactoryBuilder.php delete mode 100644 lib/symfony/form/FormFactoryBuilderInterface.php delete mode 100644 lib/symfony/form/FormFactoryInterface.php delete mode 100644 lib/symfony/form/FormInterface.php delete mode 100644 lib/symfony/form/FormRegistry.php delete mode 100644 lib/symfony/form/FormRegistryInterface.php delete mode 100644 lib/symfony/form/FormRenderer.php delete mode 100644 lib/symfony/form/FormRendererEngineInterface.php delete mode 100644 lib/symfony/form/FormRendererInterface.php delete mode 100644 lib/symfony/form/FormTypeExtensionInterface.php delete mode 100644 lib/symfony/form/FormTypeGuesserChain.php delete mode 100644 lib/symfony/form/FormTypeGuesserInterface.php delete mode 100644 lib/symfony/form/FormTypeInterface.php delete mode 100644 lib/symfony/form/FormView.php delete mode 100644 lib/symfony/form/Forms.php delete mode 100644 lib/symfony/form/Guess/Guess.php delete mode 100644 lib/symfony/form/Guess/TypeGuess.php delete mode 100644 lib/symfony/form/Guess/ValueGuess.php delete mode 100644 lib/symfony/form/LICENSE delete mode 100644 lib/symfony/form/NativeRequestHandler.php delete mode 100644 lib/symfony/form/PreloadedExtension.php delete mode 100644 lib/symfony/form/README.md delete mode 100644 lib/symfony/form/RequestHandlerInterface.php delete mode 100644 lib/symfony/form/ResolvedFormType.php delete mode 100644 lib/symfony/form/ResolvedFormTypeFactory.php delete mode 100644 lib/symfony/form/ResolvedFormTypeFactoryInterface.php delete mode 100644 lib/symfony/form/ResolvedFormTypeInterface.php delete mode 100644 lib/symfony/form/Resources/config/validation.xml delete mode 100644 lib/symfony/form/Resources/translations/validators.af.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.ar.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.az.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.be.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.bg.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.bs.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.ca.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.cs.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.da.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.de.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.el.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.en.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.es.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.et.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.eu.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.fa.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.fi.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.fr.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.gl.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.he.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.hr.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.hu.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.hy.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.id.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.it.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.ja.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.lb.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.lt.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.lv.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.mn.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.my.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.nb.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.nl.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.nn.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.no.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.pl.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.pt.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.pt_BR.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.ro.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.ru.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.sk.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.sl.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.sq.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.sr_Cyrl.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.sr_Latn.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.sv.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.th.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.tl.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.tr.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.uk.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.ur.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.uz.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.vi.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.zh_CN.xlf delete mode 100644 lib/symfony/form/Resources/translations/validators.zh_TW.xlf delete mode 100644 lib/symfony/form/ReversedTransformer.php delete mode 100644 lib/symfony/form/SubmitButton.php delete mode 100644 lib/symfony/form/SubmitButtonBuilder.php delete mode 100644 lib/symfony/form/SubmitButtonTypeInterface.php delete mode 100644 lib/symfony/form/Test/FormBuilderInterface.php delete mode 100644 lib/symfony/form/Test/FormIntegrationTestCase.php delete mode 100644 lib/symfony/form/Test/FormInterface.php delete mode 100644 lib/symfony/form/Test/FormPerformanceTestCase.php delete mode 100644 lib/symfony/form/Test/Traits/ValidatorExtensionTrait.php delete mode 100644 lib/symfony/form/Test/TypeTestCase.php delete mode 100644 lib/symfony/form/Util/FormUtil.php delete mode 100644 lib/symfony/form/Util/InheritDataAwareIterator.php delete mode 100644 lib/symfony/form/Util/OptionsResolverWrapper.php delete mode 100644 lib/symfony/form/Util/OrderedHashMap.php delete mode 100644 lib/symfony/form/Util/OrderedHashMapIterator.php delete mode 100644 lib/symfony/form/Util/ServerParams.php delete mode 100644 lib/symfony/form/Util/StringUtil.php delete mode 100644 lib/symfony/form/composer.json delete mode 100644 lib/symfony/framework-bundle/CHANGELOG.md delete mode 100644 lib/symfony/framework-bundle/CacheWarmer/AbstractPhpFileCacheWarmer.php delete mode 100644 lib/symfony/framework-bundle/CacheWarmer/AnnotationsCacheWarmer.php delete mode 100644 lib/symfony/framework-bundle/CacheWarmer/CachePoolClearerCacheWarmer.php delete mode 100644 lib/symfony/framework-bundle/CacheWarmer/ConfigBuilderCacheWarmer.php delete mode 100644 lib/symfony/framework-bundle/CacheWarmer/RouterCacheWarmer.php delete mode 100644 lib/symfony/framework-bundle/CacheWarmer/SerializerCacheWarmer.php delete mode 100644 lib/symfony/framework-bundle/CacheWarmer/TranslationsCacheWarmer.php delete mode 100644 lib/symfony/framework-bundle/CacheWarmer/ValidatorCacheWarmer.php delete mode 100644 lib/symfony/framework-bundle/Command/AboutCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/AbstractConfigCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/AssetsInstallCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/BuildDebugContainerTrait.php delete mode 100644 lib/symfony/framework-bundle/Command/CacheClearCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/CachePoolClearCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/CachePoolDeleteCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/CachePoolListCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/CachePoolPruneCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/CacheWarmupCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/ConfigDebugCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/ConfigDumpReferenceCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/ContainerDebugCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/ContainerLintCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/DebugAutowiringCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/EventDispatcherDebugCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/RouterDebugCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/RouterMatchCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/SecretsDecryptToLocalCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/SecretsEncryptFromLocalCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/SecretsGenerateKeysCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/SecretsListCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/SecretsRemoveCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/SecretsSetCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/TranslationDebugCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/TranslationUpdateCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/WorkflowDumpCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/XliffLintCommand.php delete mode 100644 lib/symfony/framework-bundle/Command/YamlLintCommand.php delete mode 100644 lib/symfony/framework-bundle/Console/Application.php delete mode 100644 lib/symfony/framework-bundle/Console/Descriptor/Descriptor.php delete mode 100644 lib/symfony/framework-bundle/Console/Descriptor/JsonDescriptor.php delete mode 100644 lib/symfony/framework-bundle/Console/Descriptor/MarkdownDescriptor.php delete mode 100644 lib/symfony/framework-bundle/Console/Descriptor/TextDescriptor.php delete mode 100644 lib/symfony/framework-bundle/Console/Descriptor/XmlDescriptor.php delete mode 100644 lib/symfony/framework-bundle/Console/Helper/DescriptorHelper.php delete mode 100644 lib/symfony/framework-bundle/Controller/AbstractController.php delete mode 100644 lib/symfony/framework-bundle/Controller/ControllerResolver.php delete mode 100644 lib/symfony/framework-bundle/Controller/RedirectController.php delete mode 100644 lib/symfony/framework-bundle/Controller/TemplateController.php delete mode 100644 lib/symfony/framework-bundle/DataCollector/AbstractDataCollector.php delete mode 100644 lib/symfony/framework-bundle/DataCollector/RouterDataCollector.php delete mode 100644 lib/symfony/framework-bundle/DataCollector/TemplateAwareDataCollectorInterface.php delete mode 100644 lib/symfony/framework-bundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php delete mode 100644 lib/symfony/framework-bundle/DependencyInjection/Compiler/AddDebugLogProcessorPass.php delete mode 100644 lib/symfony/framework-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php delete mode 100644 lib/symfony/framework-bundle/DependencyInjection/Compiler/AssetsContextPass.php delete mode 100644 lib/symfony/framework-bundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php delete mode 100644 lib/symfony/framework-bundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php delete mode 100644 lib/symfony/framework-bundle/DependencyInjection/Compiler/LoggingTranslatorPass.php delete mode 100644 lib/symfony/framework-bundle/DependencyInjection/Compiler/ProfilerPass.php delete mode 100644 lib/symfony/framework-bundle/DependencyInjection/Compiler/RemoveUnusedSessionMarshallingHandlerPass.php delete mode 100644 lib/symfony/framework-bundle/DependencyInjection/Compiler/SessionPass.php delete mode 100644 lib/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php delete mode 100644 lib/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php delete mode 100644 lib/symfony/framework-bundle/DependencyInjection/Compiler/UnusedTagsPass.php delete mode 100644 lib/symfony/framework-bundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php delete mode 100644 lib/symfony/framework-bundle/DependencyInjection/Configuration.php delete mode 100644 lib/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php delete mode 100644 lib/symfony/framework-bundle/EventListener/SuggestMissingPackageSubscriber.php delete mode 100644 lib/symfony/framework-bundle/FrameworkBundle.php delete mode 100644 lib/symfony/framework-bundle/HttpCache/HttpCache.php delete mode 100644 lib/symfony/framework-bundle/Kernel/MicroKernelTrait.php delete mode 100644 lib/symfony/framework-bundle/KernelBrowser.php delete mode 100644 lib/symfony/framework-bundle/LICENSE delete mode 100644 lib/symfony/framework-bundle/README.md delete mode 100644 lib/symfony/framework-bundle/Resources/bin/check-unused-known-tags.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/annotations.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/assets.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/cache.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/cache_debug.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/collectors.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/console.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/debug.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/debug_prod.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/error_renderer.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/esi.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/form.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/form_csrf.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/form_debug.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/fragment_listener.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/fragment_renderer.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/http_client.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/http_client_debug.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/identity_translator.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/lock.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/mailer.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/mailer_debug.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/mailer_transports.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/messenger.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/messenger_debug.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/mime_type.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/notifier.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/notifier_debug.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/notifier_transports.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/profiling.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/property_access.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/property_info.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/rate_limiter.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/request.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/routing.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/routing/errors.xml delete mode 100644 lib/symfony/framework-bundle/Resources/config/schema/symfony-1.0.xsd delete mode 100644 lib/symfony/framework-bundle/Resources/config/secrets.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/security_csrf.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/serializer.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/services.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/session.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/ssi.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/test.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/translation.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/translation_debug.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/translation_providers.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/uid.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/validator.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/validator_debug.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/web.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/web_link.php delete mode 100644 lib/symfony/framework-bundle/Resources/config/workflow.php delete mode 100644 lib/symfony/framework-bundle/Routing/AnnotatedRouteControllerLoader.php delete mode 100644 lib/symfony/framework-bundle/Routing/DelegatingLoader.php delete mode 100644 lib/symfony/framework-bundle/Routing/RedirectableCompiledUrlMatcher.php delete mode 100644 lib/symfony/framework-bundle/Routing/RouteLoaderInterface.php delete mode 100644 lib/symfony/framework-bundle/Routing/Router.php delete mode 100644 lib/symfony/framework-bundle/Secrets/AbstractVault.php delete mode 100644 lib/symfony/framework-bundle/Secrets/DotenvVault.php delete mode 100644 lib/symfony/framework-bundle/Secrets/SodiumVault.php delete mode 100644 lib/symfony/framework-bundle/Session/DeprecatedSessionFactory.php delete mode 100644 lib/symfony/framework-bundle/Session/ServiceSessionFactory.php delete mode 100644 lib/symfony/framework-bundle/Translation/Translator.php delete mode 100644 lib/symfony/framework-bundle/composer.json delete mode 100644 lib/symfony/http-foundation/AcceptHeader.php delete mode 100644 lib/symfony/http-foundation/AcceptHeaderItem.php delete mode 100644 lib/symfony/http-foundation/BinaryFileResponse.php delete mode 100644 lib/symfony/http-foundation/CHANGELOG.md delete mode 100644 lib/symfony/http-foundation/Cookie.php delete mode 100644 lib/symfony/http-foundation/Exception/BadRequestException.php delete mode 100644 lib/symfony/http-foundation/Exception/ConflictingHeadersException.php delete mode 100644 lib/symfony/http-foundation/Exception/JsonException.php delete mode 100644 lib/symfony/http-foundation/Exception/RequestExceptionInterface.php delete mode 100644 lib/symfony/http-foundation/Exception/SessionNotFoundException.php delete mode 100644 lib/symfony/http-foundation/Exception/SuspiciousOperationException.php delete mode 100644 lib/symfony/http-foundation/ExpressionRequestMatcher.php delete mode 100644 lib/symfony/http-foundation/File/Exception/AccessDeniedException.php delete mode 100644 lib/symfony/http-foundation/File/Exception/CannotWriteFileException.php delete mode 100644 lib/symfony/http-foundation/File/Exception/ExtensionFileException.php delete mode 100644 lib/symfony/http-foundation/File/Exception/FileException.php delete mode 100644 lib/symfony/http-foundation/File/Exception/FileNotFoundException.php delete mode 100644 lib/symfony/http-foundation/File/Exception/FormSizeFileException.php delete mode 100644 lib/symfony/http-foundation/File/Exception/IniSizeFileException.php delete mode 100644 lib/symfony/http-foundation/File/Exception/NoFileException.php delete mode 100644 lib/symfony/http-foundation/File/Exception/NoTmpDirFileException.php delete mode 100644 lib/symfony/http-foundation/File/Exception/PartialFileException.php delete mode 100644 lib/symfony/http-foundation/File/Exception/UnexpectedTypeException.php delete mode 100644 lib/symfony/http-foundation/File/Exception/UploadException.php delete mode 100644 lib/symfony/http-foundation/File/File.php delete mode 100644 lib/symfony/http-foundation/File/Stream.php delete mode 100644 lib/symfony/http-foundation/File/UploadedFile.php delete mode 100644 lib/symfony/http-foundation/FileBag.php delete mode 100644 lib/symfony/http-foundation/HeaderBag.php delete mode 100644 lib/symfony/http-foundation/HeaderUtils.php delete mode 100644 lib/symfony/http-foundation/InputBag.php delete mode 100644 lib/symfony/http-foundation/IpUtils.php delete mode 100644 lib/symfony/http-foundation/JsonResponse.php delete mode 100644 lib/symfony/http-foundation/LICENSE delete mode 100644 lib/symfony/http-foundation/ParameterBag.php delete mode 100644 lib/symfony/http-foundation/README.md delete mode 100644 lib/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php delete mode 100644 lib/symfony/http-foundation/RateLimiter/RequestRateLimiterInterface.php delete mode 100644 lib/symfony/http-foundation/RedirectResponse.php delete mode 100644 lib/symfony/http-foundation/Request.php delete mode 100644 lib/symfony/http-foundation/RequestMatcher.php delete mode 100644 lib/symfony/http-foundation/RequestMatcherInterface.php delete mode 100644 lib/symfony/http-foundation/RequestStack.php delete mode 100644 lib/symfony/http-foundation/Response.php delete mode 100644 lib/symfony/http-foundation/ResponseHeaderBag.php delete mode 100644 lib/symfony/http-foundation/ServerBag.php delete mode 100644 lib/symfony/http-foundation/Session/Attribute/AttributeBag.php delete mode 100644 lib/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php delete mode 100644 lib/symfony/http-foundation/Session/Attribute/NamespacedAttributeBag.php delete mode 100644 lib/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php delete mode 100644 lib/symfony/http-foundation/Session/Flash/FlashBag.php delete mode 100644 lib/symfony/http-foundation/Session/Flash/FlashBagInterface.php delete mode 100644 lib/symfony/http-foundation/Session/Session.php delete mode 100644 lib/symfony/http-foundation/Session/SessionBagInterface.php delete mode 100644 lib/symfony/http-foundation/Session/SessionBagProxy.php delete mode 100644 lib/symfony/http-foundation/Session/SessionFactory.php delete mode 100644 lib/symfony/http-foundation/Session/SessionFactoryInterface.php delete mode 100644 lib/symfony/http-foundation/Session/SessionInterface.php delete mode 100644 lib/symfony/http-foundation/Session/SessionUtils.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/Handler/IdentityMarshaller.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/MetadataBag.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/NativeSessionStorage.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/ServiceSessionFactory.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/SessionStorageFactoryInterface.php delete mode 100644 lib/symfony/http-foundation/Session/Storage/SessionStorageInterface.php delete mode 100644 lib/symfony/http-foundation/StreamedResponse.php delete mode 100644 lib/symfony/http-foundation/UrlHelper.php delete mode 100644 lib/symfony/http-foundation/composer.json delete mode 100644 lib/symfony/http-kernel/Attribute/ArgumentInterface.php delete mode 100644 lib/symfony/http-kernel/Attribute/AsController.php delete mode 100644 lib/symfony/http-kernel/Bundle/Bundle.php delete mode 100644 lib/symfony/http-kernel/Bundle/BundleInterface.php delete mode 100644 lib/symfony/http-kernel/CHANGELOG.md delete mode 100644 lib/symfony/http-kernel/CacheClearer/CacheClearerInterface.php delete mode 100644 lib/symfony/http-kernel/CacheClearer/ChainCacheClearer.php delete mode 100644 lib/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php delete mode 100644 lib/symfony/http-kernel/CacheWarmer/CacheWarmer.php delete mode 100644 lib/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php delete mode 100644 lib/symfony/http-kernel/CacheWarmer/CacheWarmerInterface.php delete mode 100644 lib/symfony/http-kernel/CacheWarmer/WarmableInterface.php delete mode 100644 lib/symfony/http-kernel/Config/FileLocator.php delete mode 100644 lib/symfony/http-kernel/Controller/ArgumentResolver.php delete mode 100644 lib/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php delete mode 100644 lib/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php delete mode 100644 lib/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php delete mode 100644 lib/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php delete mode 100644 lib/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php delete mode 100644 lib/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php delete mode 100644 lib/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php delete mode 100644 lib/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php delete mode 100644 lib/symfony/http-kernel/Controller/ArgumentResolverInterface.php delete mode 100644 lib/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php delete mode 100644 lib/symfony/http-kernel/Controller/ContainerControllerResolver.php delete mode 100644 lib/symfony/http-kernel/Controller/ControllerReference.php delete mode 100644 lib/symfony/http-kernel/Controller/ControllerResolver.php delete mode 100644 lib/symfony/http-kernel/Controller/ControllerResolverInterface.php delete mode 100644 lib/symfony/http-kernel/Controller/ErrorController.php delete mode 100644 lib/symfony/http-kernel/Controller/TraceableArgumentResolver.php delete mode 100644 lib/symfony/http-kernel/Controller/TraceableControllerResolver.php delete mode 100644 lib/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php delete mode 100644 lib/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php delete mode 100644 lib/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php delete mode 100644 lib/symfony/http-kernel/DataCollector/AjaxDataCollector.php delete mode 100644 lib/symfony/http-kernel/DataCollector/ConfigDataCollector.php delete mode 100644 lib/symfony/http-kernel/DataCollector/DataCollector.php delete mode 100644 lib/symfony/http-kernel/DataCollector/DataCollectorInterface.php delete mode 100644 lib/symfony/http-kernel/DataCollector/DumpDataCollector.php delete mode 100644 lib/symfony/http-kernel/DataCollector/EventDataCollector.php delete mode 100644 lib/symfony/http-kernel/DataCollector/ExceptionDataCollector.php delete mode 100644 lib/symfony/http-kernel/DataCollector/LateDataCollectorInterface.php delete mode 100644 lib/symfony/http-kernel/DataCollector/LoggerDataCollector.php delete mode 100644 lib/symfony/http-kernel/DataCollector/MemoryDataCollector.php delete mode 100644 lib/symfony/http-kernel/DataCollector/RequestDataCollector.php delete mode 100644 lib/symfony/http-kernel/DataCollector/RouterDataCollector.php delete mode 100644 lib/symfony/http-kernel/DataCollector/TimeDataCollector.php delete mode 100644 lib/symfony/http-kernel/Debug/FileLinkFormatter.php delete mode 100644 lib/symfony/http-kernel/Debug/TraceableEventDispatcher.php delete mode 100644 lib/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php delete mode 100644 lib/symfony/http-kernel/DependencyInjection/ConfigurableExtension.php delete mode 100644 lib/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php delete mode 100644 lib/symfony/http-kernel/DependencyInjection/Extension.php delete mode 100644 lib/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php delete mode 100644 lib/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php delete mode 100644 lib/symfony/http-kernel/DependencyInjection/LoggerPass.php delete mode 100644 lib/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php delete mode 100644 lib/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php delete mode 100644 lib/symfony/http-kernel/DependencyInjection/RegisterLocaleAwareServicesPass.php delete mode 100644 lib/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php delete mode 100644 lib/symfony/http-kernel/DependencyInjection/ResettableServicePass.php delete mode 100644 lib/symfony/http-kernel/DependencyInjection/ServicesResetter.php delete mode 100644 lib/symfony/http-kernel/Event/ControllerArgumentsEvent.php delete mode 100644 lib/symfony/http-kernel/Event/ControllerEvent.php delete mode 100644 lib/symfony/http-kernel/Event/ExceptionEvent.php delete mode 100644 lib/symfony/http-kernel/Event/FinishRequestEvent.php delete mode 100644 lib/symfony/http-kernel/Event/KernelEvent.php delete mode 100644 lib/symfony/http-kernel/Event/RequestEvent.php delete mode 100644 lib/symfony/http-kernel/Event/ResponseEvent.php delete mode 100644 lib/symfony/http-kernel/Event/TerminateEvent.php delete mode 100644 lib/symfony/http-kernel/Event/ViewEvent.php delete mode 100644 lib/symfony/http-kernel/EventListener/AbstractSessionListener.php delete mode 100644 lib/symfony/http-kernel/EventListener/AbstractTestSessionListener.php delete mode 100644 lib/symfony/http-kernel/EventListener/AddRequestFormatsListener.php delete mode 100644 lib/symfony/http-kernel/EventListener/DebugHandlersListener.php delete mode 100644 lib/symfony/http-kernel/EventListener/DisallowRobotsIndexingListener.php delete mode 100644 lib/symfony/http-kernel/EventListener/DumpListener.php delete mode 100644 lib/symfony/http-kernel/EventListener/ErrorListener.php delete mode 100644 lib/symfony/http-kernel/EventListener/FragmentListener.php delete mode 100644 lib/symfony/http-kernel/EventListener/LocaleAwareListener.php delete mode 100644 lib/symfony/http-kernel/EventListener/LocaleListener.php delete mode 100644 lib/symfony/http-kernel/EventListener/ProfilerListener.php delete mode 100644 lib/symfony/http-kernel/EventListener/ResponseListener.php delete mode 100644 lib/symfony/http-kernel/EventListener/RouterListener.php delete mode 100644 lib/symfony/http-kernel/EventListener/SessionListener.php delete mode 100644 lib/symfony/http-kernel/EventListener/StreamedResponseListener.php delete mode 100644 lib/symfony/http-kernel/EventListener/SurrogateListener.php delete mode 100644 lib/symfony/http-kernel/EventListener/TestSessionListener.php delete mode 100644 lib/symfony/http-kernel/EventListener/ValidateRequestListener.php delete mode 100644 lib/symfony/http-kernel/Exception/AccessDeniedHttpException.php delete mode 100644 lib/symfony/http-kernel/Exception/BadRequestHttpException.php delete mode 100644 lib/symfony/http-kernel/Exception/ConflictHttpException.php delete mode 100644 lib/symfony/http-kernel/Exception/ControllerDoesNotReturnResponseException.php delete mode 100644 lib/symfony/http-kernel/Exception/GoneHttpException.php delete mode 100644 lib/symfony/http-kernel/Exception/HttpException.php delete mode 100644 lib/symfony/http-kernel/Exception/HttpExceptionInterface.php delete mode 100644 lib/symfony/http-kernel/Exception/InvalidMetadataException.php delete mode 100644 lib/symfony/http-kernel/Exception/LengthRequiredHttpException.php delete mode 100644 lib/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php delete mode 100644 lib/symfony/http-kernel/Exception/NotAcceptableHttpException.php delete mode 100644 lib/symfony/http-kernel/Exception/NotFoundHttpException.php delete mode 100644 lib/symfony/http-kernel/Exception/PreconditionFailedHttpException.php delete mode 100644 lib/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php delete mode 100644 lib/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php delete mode 100644 lib/symfony/http-kernel/Exception/TooManyRequestsHttpException.php delete mode 100644 lib/symfony/http-kernel/Exception/UnauthorizedHttpException.php delete mode 100644 lib/symfony/http-kernel/Exception/UnexpectedSessionUsageException.php delete mode 100644 lib/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php delete mode 100644 lib/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php delete mode 100644 lib/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php delete mode 100644 lib/symfony/http-kernel/Fragment/EsiFragmentRenderer.php delete mode 100644 lib/symfony/http-kernel/Fragment/FragmentHandler.php delete mode 100644 lib/symfony/http-kernel/Fragment/FragmentRendererInterface.php delete mode 100644 lib/symfony/http-kernel/Fragment/FragmentUriGenerator.php delete mode 100644 lib/symfony/http-kernel/Fragment/FragmentUriGeneratorInterface.php delete mode 100644 lib/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php delete mode 100644 lib/symfony/http-kernel/Fragment/InlineFragmentRenderer.php delete mode 100644 lib/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php delete mode 100644 lib/symfony/http-kernel/Fragment/SsiFragmentRenderer.php delete mode 100644 lib/symfony/http-kernel/HttpCache/AbstractSurrogate.php delete mode 100644 lib/symfony/http-kernel/HttpCache/Esi.php delete mode 100644 lib/symfony/http-kernel/HttpCache/HttpCache.php delete mode 100644 lib/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php delete mode 100644 lib/symfony/http-kernel/HttpCache/ResponseCacheStrategyInterface.php delete mode 100644 lib/symfony/http-kernel/HttpCache/Ssi.php delete mode 100644 lib/symfony/http-kernel/HttpCache/Store.php delete mode 100644 lib/symfony/http-kernel/HttpCache/StoreInterface.php delete mode 100644 lib/symfony/http-kernel/HttpCache/SubRequestHandler.php delete mode 100644 lib/symfony/http-kernel/HttpCache/SurrogateInterface.php delete mode 100644 lib/symfony/http-kernel/HttpClientKernel.php delete mode 100644 lib/symfony/http-kernel/HttpKernel.php delete mode 100644 lib/symfony/http-kernel/HttpKernelBrowser.php delete mode 100644 lib/symfony/http-kernel/HttpKernelInterface.php delete mode 100644 lib/symfony/http-kernel/Kernel.php delete mode 100644 lib/symfony/http-kernel/KernelEvents.php delete mode 100644 lib/symfony/http-kernel/KernelInterface.php delete mode 100644 lib/symfony/http-kernel/LICENSE delete mode 100644 lib/symfony/http-kernel/Log/DebugLoggerInterface.php delete mode 100644 lib/symfony/http-kernel/Log/Logger.php delete mode 100644 lib/symfony/http-kernel/Profiler/FileProfilerStorage.php delete mode 100644 lib/symfony/http-kernel/Profiler/Profile.php delete mode 100644 lib/symfony/http-kernel/Profiler/Profiler.php delete mode 100644 lib/symfony/http-kernel/Profiler/ProfilerStorageInterface.php delete mode 100644 lib/symfony/http-kernel/README.md delete mode 100644 lib/symfony/http-kernel/RebootableInterface.php delete mode 100644 lib/symfony/http-kernel/Resources/welcome.html.php delete mode 100644 lib/symfony/http-kernel/TerminableInterface.php delete mode 100644 lib/symfony/http-kernel/UriSigner.php delete mode 100644 lib/symfony/http-kernel/composer.json delete mode 100644 lib/symfony/options-resolver/CHANGELOG.md delete mode 100644 lib/symfony/options-resolver/Debug/OptionsResolverIntrospector.php delete mode 100644 lib/symfony/options-resolver/Exception/AccessException.php delete mode 100644 lib/symfony/options-resolver/Exception/ExceptionInterface.php delete mode 100644 lib/symfony/options-resolver/Exception/InvalidArgumentException.php delete mode 100644 lib/symfony/options-resolver/Exception/InvalidOptionsException.php delete mode 100644 lib/symfony/options-resolver/Exception/MissingOptionsException.php delete mode 100644 lib/symfony/options-resolver/Exception/NoConfigurationException.php delete mode 100644 lib/symfony/options-resolver/Exception/NoSuchOptionException.php delete mode 100644 lib/symfony/options-resolver/Exception/OptionDefinitionException.php delete mode 100644 lib/symfony/options-resolver/Exception/UndefinedOptionsException.php delete mode 100644 lib/symfony/options-resolver/LICENSE delete mode 100644 lib/symfony/options-resolver/OptionConfigurator.php delete mode 100644 lib/symfony/options-resolver/Options.php delete mode 100644 lib/symfony/options-resolver/OptionsResolver.php delete mode 100644 lib/symfony/options-resolver/README.md delete mode 100644 lib/symfony/options-resolver/composer.json delete mode 100644 lib/symfony/polyfill-ctype/Ctype.php delete mode 100644 lib/symfony/polyfill-ctype/LICENSE delete mode 100644 lib/symfony/polyfill-ctype/README.md delete mode 100644 lib/symfony/polyfill-ctype/bootstrap.php delete mode 100644 lib/symfony/polyfill-ctype/bootstrap80.php delete mode 100644 lib/symfony/polyfill-ctype/composer.json delete mode 100644 lib/symfony/polyfill-intl-grapheme/Grapheme.php delete mode 100644 lib/symfony/polyfill-intl-grapheme/LICENSE delete mode 100644 lib/symfony/polyfill-intl-grapheme/README.md delete mode 100644 lib/symfony/polyfill-intl-grapheme/bootstrap.php delete mode 100644 lib/symfony/polyfill-intl-grapheme/bootstrap80.php delete mode 100644 lib/symfony/polyfill-intl-grapheme/composer.json delete mode 100644 lib/symfony/polyfill-intl-icu/Collator.php delete mode 100644 lib/symfony/polyfill-intl-icu/Currencies.php delete mode 100644 lib/symfony/polyfill-intl-icu/DateFormat/AmPmTransformer.php delete mode 100644 lib/symfony/polyfill-intl-icu/DateFormat/DayOfWeekTransformer.php delete mode 100644 lib/symfony/polyfill-intl-icu/DateFormat/DayOfYearTransformer.php delete mode 100644 lib/symfony/polyfill-intl-icu/DateFormat/DayTransformer.php delete mode 100644 lib/symfony/polyfill-intl-icu/DateFormat/FullTransformer.php delete mode 100644 lib/symfony/polyfill-intl-icu/DateFormat/Hour1200Transformer.php delete mode 100644 lib/symfony/polyfill-intl-icu/DateFormat/Hour1201Transformer.php delete mode 100644 lib/symfony/polyfill-intl-icu/DateFormat/Hour2400Transformer.php delete mode 100644 lib/symfony/polyfill-intl-icu/DateFormat/Hour2401Transformer.php delete mode 100644 lib/symfony/polyfill-intl-icu/DateFormat/HourTransformer.php delete mode 100644 lib/symfony/polyfill-intl-icu/DateFormat/MinuteTransformer.php delete mode 100644 lib/symfony/polyfill-intl-icu/DateFormat/MonthTransformer.php delete mode 100644 lib/symfony/polyfill-intl-icu/DateFormat/QuarterTransformer.php delete mode 100644 lib/symfony/polyfill-intl-icu/DateFormat/SecondTransformer.php delete mode 100644 lib/symfony/polyfill-intl-icu/DateFormat/TimezoneTransformer.php delete mode 100644 lib/symfony/polyfill-intl-icu/DateFormat/Transformer.php delete mode 100644 lib/symfony/polyfill-intl-icu/DateFormat/YearTransformer.php delete mode 100644 lib/symfony/polyfill-intl-icu/Exception/ExceptionInterface.php delete mode 100644 lib/symfony/polyfill-intl-icu/Exception/MethodArgumentNotImplementedException.php delete mode 100644 lib/symfony/polyfill-intl-icu/Exception/MethodArgumentValueNotImplementedException.php delete mode 100644 lib/symfony/polyfill-intl-icu/Exception/MethodNotImplementedException.php delete mode 100644 lib/symfony/polyfill-intl-icu/Exception/NotImplementedException.php delete mode 100644 lib/symfony/polyfill-intl-icu/Exception/RuntimeException.php delete mode 100644 lib/symfony/polyfill-intl-icu/Icu.php delete mode 100644 lib/symfony/polyfill-intl-icu/IntlDateFormatter.php delete mode 100644 lib/symfony/polyfill-intl-icu/LICENSE delete mode 100644 lib/symfony/polyfill-intl-icu/Locale.php delete mode 100644 lib/symfony/polyfill-intl-icu/NumberFormatter.php delete mode 100644 lib/symfony/polyfill-intl-icu/README.md delete mode 100644 lib/symfony/polyfill-intl-icu/Resources/currencies.php delete mode 100644 lib/symfony/polyfill-intl-icu/Resources/stubs/Collator.php delete mode 100644 lib/symfony/polyfill-intl-icu/Resources/stubs/IntlDateFormatter.php delete mode 100644 lib/symfony/polyfill-intl-icu/Resources/stubs/Locale.php delete mode 100644 lib/symfony/polyfill-intl-icu/Resources/stubs/NumberFormatter.php delete mode 100644 lib/symfony/polyfill-intl-icu/bootstrap.php delete mode 100644 lib/symfony/polyfill-intl-icu/bootstrap80.php delete mode 100644 lib/symfony/polyfill-intl-icu/composer.json delete mode 100644 lib/symfony/polyfill-intl-idn/Idn.php delete mode 100644 lib/symfony/polyfill-intl-idn/Info.php delete mode 100644 lib/symfony/polyfill-intl-idn/LICENSE delete mode 100644 lib/symfony/polyfill-intl-idn/README.md delete mode 100644 lib/symfony/polyfill-intl-idn/Resources/unidata/DisallowedRanges.php delete mode 100644 lib/symfony/polyfill-intl-idn/Resources/unidata/Regex.php delete mode 100644 lib/symfony/polyfill-intl-idn/Resources/unidata/deviation.php delete mode 100644 lib/symfony/polyfill-intl-idn/Resources/unidata/disallowed.php delete mode 100644 lib/symfony/polyfill-intl-idn/Resources/unidata/disallowed_STD3_mapped.php delete mode 100644 lib/symfony/polyfill-intl-idn/Resources/unidata/disallowed_STD3_valid.php delete mode 100644 lib/symfony/polyfill-intl-idn/Resources/unidata/ignored.php delete mode 100644 lib/symfony/polyfill-intl-idn/Resources/unidata/mapped.php delete mode 100644 lib/symfony/polyfill-intl-idn/Resources/unidata/virama.php delete mode 100644 lib/symfony/polyfill-intl-idn/bootstrap.php delete mode 100644 lib/symfony/polyfill-intl-idn/bootstrap80.php delete mode 100644 lib/symfony/polyfill-intl-idn/composer.json delete mode 100644 lib/symfony/polyfill-intl-normalizer/LICENSE delete mode 100644 lib/symfony/polyfill-intl-normalizer/Normalizer.php delete mode 100644 lib/symfony/polyfill-intl-normalizer/README.md delete mode 100644 lib/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php delete mode 100644 lib/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalComposition.php delete mode 100644 lib/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalDecomposition.php delete mode 100644 lib/symfony/polyfill-intl-normalizer/Resources/unidata/combiningClass.php delete mode 100644 lib/symfony/polyfill-intl-normalizer/Resources/unidata/compatibilityDecomposition.php delete mode 100644 lib/symfony/polyfill-intl-normalizer/bootstrap.php delete mode 100644 lib/symfony/polyfill-intl-normalizer/bootstrap80.php delete mode 100644 lib/symfony/polyfill-intl-normalizer/composer.json delete mode 100644 lib/symfony/polyfill-mbstring/LICENSE delete mode 100644 lib/symfony/polyfill-mbstring/Mbstring.php delete mode 100644 lib/symfony/polyfill-mbstring/README.md delete mode 100644 lib/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php delete mode 100644 lib/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php delete mode 100644 lib/symfony/polyfill-mbstring/Resources/unidata/upperCase.php delete mode 100644 lib/symfony/polyfill-mbstring/bootstrap.php delete mode 100644 lib/symfony/polyfill-mbstring/bootstrap80.php delete mode 100644 lib/symfony/polyfill-mbstring/composer.json delete mode 100644 lib/symfony/polyfill-php72/LICENSE delete mode 100644 lib/symfony/polyfill-php72/Php72.php delete mode 100644 lib/symfony/polyfill-php72/README.md delete mode 100644 lib/symfony/polyfill-php72/bootstrap.php delete mode 100644 lib/symfony/polyfill-php72/composer.json delete mode 100644 lib/symfony/polyfill-php73/LICENSE delete mode 100644 lib/symfony/polyfill-php73/Php73.php delete mode 100644 lib/symfony/polyfill-php73/README.md delete mode 100644 lib/symfony/polyfill-php73/Resources/stubs/JsonException.php delete mode 100644 lib/symfony/polyfill-php73/bootstrap.php delete mode 100644 lib/symfony/polyfill-php73/composer.json delete mode 100644 lib/symfony/polyfill-php80/LICENSE delete mode 100644 lib/symfony/polyfill-php80/Php80.php delete mode 100644 lib/symfony/polyfill-php80/PhpToken.php delete mode 100644 lib/symfony/polyfill-php80/README.md delete mode 100644 lib/symfony/polyfill-php80/Resources/stubs/Attribute.php delete mode 100644 lib/symfony/polyfill-php80/Resources/stubs/PhpToken.php delete mode 100644 lib/symfony/polyfill-php80/Resources/stubs/Stringable.php delete mode 100644 lib/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php delete mode 100644 lib/symfony/polyfill-php80/Resources/stubs/ValueError.php delete mode 100644 lib/symfony/polyfill-php80/bootstrap.php delete mode 100644 lib/symfony/polyfill-php80/composer.json delete mode 100644 lib/symfony/polyfill-php81/LICENSE delete mode 100644 lib/symfony/polyfill-php81/Php81.php delete mode 100644 lib/symfony/polyfill-php81/README.md delete mode 100644 lib/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php delete mode 100644 lib/symfony/polyfill-php81/bootstrap.php delete mode 100644 lib/symfony/polyfill-php81/composer.json delete mode 100644 lib/symfony/property-access/CHANGELOG.md delete mode 100644 lib/symfony/property-access/Exception/AccessException.php delete mode 100644 lib/symfony/property-access/Exception/ExceptionInterface.php delete mode 100644 lib/symfony/property-access/Exception/InvalidArgumentException.php delete mode 100644 lib/symfony/property-access/Exception/InvalidPropertyPathException.php delete mode 100644 lib/symfony/property-access/Exception/NoSuchIndexException.php delete mode 100644 lib/symfony/property-access/Exception/NoSuchPropertyException.php delete mode 100644 lib/symfony/property-access/Exception/OutOfBoundsException.php delete mode 100644 lib/symfony/property-access/Exception/RuntimeException.php delete mode 100644 lib/symfony/property-access/Exception/UnexpectedTypeException.php delete mode 100644 lib/symfony/property-access/Exception/UninitializedPropertyException.php delete mode 100644 lib/symfony/property-access/LICENSE delete mode 100644 lib/symfony/property-access/PropertyAccess.php delete mode 100644 lib/symfony/property-access/PropertyAccessor.php delete mode 100644 lib/symfony/property-access/PropertyAccessorBuilder.php delete mode 100644 lib/symfony/property-access/PropertyAccessorInterface.php delete mode 100644 lib/symfony/property-access/PropertyPath.php delete mode 100644 lib/symfony/property-access/PropertyPathBuilder.php delete mode 100644 lib/symfony/property-access/PropertyPathInterface.php delete mode 100644 lib/symfony/property-access/PropertyPathIterator.php delete mode 100644 lib/symfony/property-access/PropertyPathIteratorInterface.php delete mode 100644 lib/symfony/property-access/README.md delete mode 100644 lib/symfony/property-access/composer.json delete mode 100644 lib/symfony/property-info/CHANGELOG.md delete mode 100644 lib/symfony/property-info/DependencyInjection/PropertyInfoConstructorPass.php delete mode 100644 lib/symfony/property-info/DependencyInjection/PropertyInfoPass.php delete mode 100644 lib/symfony/property-info/Extractor/ConstructorArgumentTypeExtractorInterface.php delete mode 100644 lib/symfony/property-info/Extractor/ConstructorExtractor.php delete mode 100644 lib/symfony/property-info/Extractor/PhpDocExtractor.php delete mode 100644 lib/symfony/property-info/Extractor/PhpStanExtractor.php delete mode 100644 lib/symfony/property-info/Extractor/ReflectionExtractor.php delete mode 100644 lib/symfony/property-info/Extractor/SerializerExtractor.php delete mode 100644 lib/symfony/property-info/LICENSE delete mode 100644 lib/symfony/property-info/PhpStan/NameScope.php delete mode 100644 lib/symfony/property-info/PhpStan/NameScopeFactory.php delete mode 100644 lib/symfony/property-info/PropertyAccessExtractorInterface.php delete mode 100644 lib/symfony/property-info/PropertyDescriptionExtractorInterface.php delete mode 100644 lib/symfony/property-info/PropertyInfoCacheExtractor.php delete mode 100644 lib/symfony/property-info/PropertyInfoExtractor.php delete mode 100644 lib/symfony/property-info/PropertyInfoExtractorInterface.php delete mode 100644 lib/symfony/property-info/PropertyInitializableExtractorInterface.php delete mode 100644 lib/symfony/property-info/PropertyListExtractorInterface.php delete mode 100644 lib/symfony/property-info/PropertyReadInfo.php delete mode 100644 lib/symfony/property-info/PropertyReadInfoExtractorInterface.php delete mode 100644 lib/symfony/property-info/PropertyTypeExtractorInterface.php delete mode 100644 lib/symfony/property-info/PropertyWriteInfo.php delete mode 100644 lib/symfony/property-info/PropertyWriteInfoExtractorInterface.php delete mode 100644 lib/symfony/property-info/README.md delete mode 100644 lib/symfony/property-info/Type.php delete mode 100644 lib/symfony/property-info/Util/PhpDocTypeHelper.php delete mode 100644 lib/symfony/property-info/Util/PhpStanTypeHelper.php delete mode 100644 lib/symfony/property-info/composer.json delete mode 100644 lib/symfony/routing/Alias.php delete mode 100644 lib/symfony/routing/Annotation/Route.php delete mode 100644 lib/symfony/routing/CHANGELOG.md delete mode 100644 lib/symfony/routing/CompiledRoute.php delete mode 100644 lib/symfony/routing/DependencyInjection/RoutingResolverPass.php delete mode 100644 lib/symfony/routing/Exception/ExceptionInterface.php delete mode 100644 lib/symfony/routing/Exception/InvalidArgumentException.php delete mode 100644 lib/symfony/routing/Exception/InvalidParameterException.php delete mode 100644 lib/symfony/routing/Exception/MethodNotAllowedException.php delete mode 100644 lib/symfony/routing/Exception/MissingMandatoryParametersException.php delete mode 100644 lib/symfony/routing/Exception/NoConfigurationException.php delete mode 100644 lib/symfony/routing/Exception/ResourceNotFoundException.php delete mode 100644 lib/symfony/routing/Exception/RouteCircularReferenceException.php delete mode 100644 lib/symfony/routing/Exception/RouteNotFoundException.php delete mode 100644 lib/symfony/routing/Exception/RuntimeException.php delete mode 100644 lib/symfony/routing/Generator/CompiledUrlGenerator.php delete mode 100644 lib/symfony/routing/Generator/ConfigurableRequirementsInterface.php delete mode 100644 lib/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php delete mode 100644 lib/symfony/routing/Generator/Dumper/GeneratorDumper.php delete mode 100644 lib/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php delete mode 100644 lib/symfony/routing/Generator/UrlGenerator.php delete mode 100644 lib/symfony/routing/Generator/UrlGeneratorInterface.php delete mode 100644 lib/symfony/routing/LICENSE delete mode 100644 lib/symfony/routing/Loader/AnnotationClassLoader.php delete mode 100644 lib/symfony/routing/Loader/AnnotationDirectoryLoader.php delete mode 100644 lib/symfony/routing/Loader/AnnotationFileLoader.php delete mode 100644 lib/symfony/routing/Loader/ClosureLoader.php delete mode 100644 lib/symfony/routing/Loader/Configurator/AliasConfigurator.php delete mode 100644 lib/symfony/routing/Loader/Configurator/CollectionConfigurator.php delete mode 100644 lib/symfony/routing/Loader/Configurator/ImportConfigurator.php delete mode 100644 lib/symfony/routing/Loader/Configurator/RouteConfigurator.php delete mode 100644 lib/symfony/routing/Loader/Configurator/RoutingConfigurator.php delete mode 100644 lib/symfony/routing/Loader/Configurator/Traits/AddTrait.php delete mode 100644 lib/symfony/routing/Loader/Configurator/Traits/HostTrait.php delete mode 100644 lib/symfony/routing/Loader/Configurator/Traits/LocalizedRouteTrait.php delete mode 100644 lib/symfony/routing/Loader/Configurator/Traits/PrefixTrait.php delete mode 100644 lib/symfony/routing/Loader/Configurator/Traits/RouteTrait.php delete mode 100644 lib/symfony/routing/Loader/ContainerLoader.php delete mode 100644 lib/symfony/routing/Loader/DirectoryLoader.php delete mode 100644 lib/symfony/routing/Loader/GlobFileLoader.php delete mode 100644 lib/symfony/routing/Loader/ObjectLoader.php delete mode 100644 lib/symfony/routing/Loader/PhpFileLoader.php delete mode 100644 lib/symfony/routing/Loader/XmlFileLoader.php delete mode 100644 lib/symfony/routing/Loader/YamlFileLoader.php delete mode 100644 lib/symfony/routing/Loader/schema/routing/routing-1.0.xsd delete mode 100644 lib/symfony/routing/Matcher/CompiledUrlMatcher.php delete mode 100644 lib/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php delete mode 100644 lib/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php delete mode 100644 lib/symfony/routing/Matcher/Dumper/MatcherDumper.php delete mode 100644 lib/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php delete mode 100644 lib/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php delete mode 100644 lib/symfony/routing/Matcher/ExpressionLanguageProvider.php delete mode 100644 lib/symfony/routing/Matcher/RedirectableUrlMatcher.php delete mode 100644 lib/symfony/routing/Matcher/RedirectableUrlMatcherInterface.php delete mode 100644 lib/symfony/routing/Matcher/RequestMatcherInterface.php delete mode 100644 lib/symfony/routing/Matcher/TraceableUrlMatcher.php delete mode 100644 lib/symfony/routing/Matcher/UrlMatcher.php delete mode 100644 lib/symfony/routing/Matcher/UrlMatcherInterface.php delete mode 100644 lib/symfony/routing/README.md delete mode 100644 lib/symfony/routing/RequestContext.php delete mode 100644 lib/symfony/routing/RequestContextAwareInterface.php delete mode 100644 lib/symfony/routing/Route.php delete mode 100644 lib/symfony/routing/RouteCollection.php delete mode 100644 lib/symfony/routing/RouteCollectionBuilder.php delete mode 100644 lib/symfony/routing/RouteCompiler.php delete mode 100644 lib/symfony/routing/RouteCompilerInterface.php delete mode 100644 lib/symfony/routing/Router.php delete mode 100644 lib/symfony/routing/RouterInterface.php delete mode 100644 lib/symfony/routing/composer.json delete mode 100644 lib/symfony/service-contracts/.gitignore delete mode 100644 lib/symfony/service-contracts/Attribute/Required.php delete mode 100644 lib/symfony/service-contracts/Attribute/SubscribedService.php delete mode 100644 lib/symfony/service-contracts/CHANGELOG.md delete mode 100644 lib/symfony/service-contracts/LICENSE delete mode 100644 lib/symfony/service-contracts/README.md delete mode 100644 lib/symfony/service-contracts/ResetInterface.php delete mode 100644 lib/symfony/service-contracts/ServiceLocatorTrait.php delete mode 100644 lib/symfony/service-contracts/ServiceProviderInterface.php delete mode 100644 lib/symfony/service-contracts/ServiceSubscriberInterface.php delete mode 100644 lib/symfony/service-contracts/ServiceSubscriberTrait.php delete mode 100644 lib/symfony/service-contracts/composer.json delete mode 100644 lib/symfony/stopwatch/CHANGELOG.md delete mode 100644 lib/symfony/stopwatch/LICENSE delete mode 100644 lib/symfony/stopwatch/README.md delete mode 100644 lib/symfony/stopwatch/Section.php delete mode 100644 lib/symfony/stopwatch/Stopwatch.php delete mode 100644 lib/symfony/stopwatch/StopwatchEvent.php delete mode 100644 lib/symfony/stopwatch/StopwatchPeriod.php delete mode 100644 lib/symfony/stopwatch/composer.json delete mode 100644 lib/symfony/string/AbstractString.php delete mode 100644 lib/symfony/string/AbstractUnicodeString.php delete mode 100644 lib/symfony/string/ByteString.php delete mode 100644 lib/symfony/string/CHANGELOG.md delete mode 100644 lib/symfony/string/CodePointString.php delete mode 100644 lib/symfony/string/Exception/ExceptionInterface.php delete mode 100644 lib/symfony/string/Exception/InvalidArgumentException.php delete mode 100644 lib/symfony/string/Exception/RuntimeException.php delete mode 100644 lib/symfony/string/Inflector/EnglishInflector.php delete mode 100644 lib/symfony/string/Inflector/FrenchInflector.php delete mode 100644 lib/symfony/string/Inflector/InflectorInterface.php delete mode 100644 lib/symfony/string/LICENSE delete mode 100644 lib/symfony/string/LazyString.php delete mode 100644 lib/symfony/string/README.md delete mode 100644 lib/symfony/string/Resources/data/wcswidth_table_wide.php delete mode 100644 lib/symfony/string/Resources/data/wcswidth_table_zero.php delete mode 100644 lib/symfony/string/Resources/functions.php delete mode 100644 lib/symfony/string/Slugger/AsciiSlugger.php delete mode 100644 lib/symfony/string/Slugger/SluggerInterface.php delete mode 100644 lib/symfony/string/UnicodeString.php delete mode 100644 lib/symfony/string/composer.json delete mode 100644 lib/symfony/translation-contracts/.gitignore delete mode 100644 lib/symfony/translation-contracts/CHANGELOG.md delete mode 100644 lib/symfony/translation-contracts/LICENSE delete mode 100644 lib/symfony/translation-contracts/LocaleAwareInterface.php delete mode 100644 lib/symfony/translation-contracts/README.md delete mode 100644 lib/symfony/translation-contracts/TranslatableInterface.php delete mode 100644 lib/symfony/translation-contracts/TranslatorInterface.php delete mode 100644 lib/symfony/translation-contracts/TranslatorTrait.php delete mode 100644 lib/symfony/translation-contracts/composer.json delete mode 100644 lib/symfony/twig-bridge/AppVariable.php delete mode 100644 lib/symfony/twig-bridge/CHANGELOG.md delete mode 100644 lib/symfony/twig-bridge/Command/DebugCommand.php delete mode 100644 lib/symfony/twig-bridge/Command/LintCommand.php delete mode 100644 lib/symfony/twig-bridge/DataCollector/TwigDataCollector.php delete mode 100644 lib/symfony/twig-bridge/ErrorRenderer/TwigErrorRenderer.php delete mode 100644 lib/symfony/twig-bridge/Extension/AssetExtension.php delete mode 100644 lib/symfony/twig-bridge/Extension/CodeExtension.php delete mode 100644 lib/symfony/twig-bridge/Extension/CsrfExtension.php delete mode 100644 lib/symfony/twig-bridge/Extension/CsrfRuntime.php delete mode 100644 lib/symfony/twig-bridge/Extension/DumpExtension.php delete mode 100644 lib/symfony/twig-bridge/Extension/ExpressionExtension.php delete mode 100644 lib/symfony/twig-bridge/Extension/FormExtension.php delete mode 100644 lib/symfony/twig-bridge/Extension/HttpFoundationExtension.php delete mode 100644 lib/symfony/twig-bridge/Extension/HttpKernelExtension.php delete mode 100644 lib/symfony/twig-bridge/Extension/HttpKernelRuntime.php delete mode 100644 lib/symfony/twig-bridge/Extension/LogoutUrlExtension.php delete mode 100644 lib/symfony/twig-bridge/Extension/ProfilerExtension.php delete mode 100644 lib/symfony/twig-bridge/Extension/RoutingExtension.php delete mode 100644 lib/symfony/twig-bridge/Extension/SecurityExtension.php delete mode 100644 lib/symfony/twig-bridge/Extension/SerializerExtension.php delete mode 100644 lib/symfony/twig-bridge/Extension/SerializerRuntime.php delete mode 100644 lib/symfony/twig-bridge/Extension/StopwatchExtension.php delete mode 100644 lib/symfony/twig-bridge/Extension/TranslationExtension.php delete mode 100644 lib/symfony/twig-bridge/Extension/WebLinkExtension.php delete mode 100644 lib/symfony/twig-bridge/Extension/WorkflowExtension.php delete mode 100644 lib/symfony/twig-bridge/Extension/YamlExtension.php delete mode 100644 lib/symfony/twig-bridge/Form/TwigRendererEngine.php delete mode 100644 lib/symfony/twig-bridge/LICENSE delete mode 100644 lib/symfony/twig-bridge/Mime/BodyRenderer.php delete mode 100644 lib/symfony/twig-bridge/Mime/NotificationEmail.php delete mode 100644 lib/symfony/twig-bridge/Mime/TemplatedEmail.php delete mode 100644 lib/symfony/twig-bridge/Mime/WrappedTemplatedEmail.php delete mode 100644 lib/symfony/twig-bridge/Node/DumpNode.php delete mode 100644 lib/symfony/twig-bridge/Node/FormThemeNode.php delete mode 100644 lib/symfony/twig-bridge/Node/RenderBlockNode.php delete mode 100644 lib/symfony/twig-bridge/Node/SearchAndRenderBlockNode.php delete mode 100644 lib/symfony/twig-bridge/Node/StopwatchNode.php delete mode 100644 lib/symfony/twig-bridge/Node/TransDefaultDomainNode.php delete mode 100644 lib/symfony/twig-bridge/Node/TransNode.php delete mode 100644 lib/symfony/twig-bridge/NodeVisitor/Scope.php delete mode 100644 lib/symfony/twig-bridge/NodeVisitor/TranslationDefaultDomainNodeVisitor.php delete mode 100644 lib/symfony/twig-bridge/NodeVisitor/TranslationNodeVisitor.php delete mode 100644 lib/symfony/twig-bridge/README.md delete mode 100644 lib/symfony/twig-bridge/Resources/views/Email/default/notification/body.html.twig delete mode 100644 lib/symfony/twig-bridge/Resources/views/Email/default/notification/body.txt.twig delete mode 100644 lib/symfony/twig-bridge/Resources/views/Email/zurb_2/main.css delete mode 100644 lib/symfony/twig-bridge/Resources/views/Email/zurb_2/notification/body.html.twig delete mode 100644 lib/symfony/twig-bridge/Resources/views/Email/zurb_2/notification/body.txt.twig delete mode 100644 lib/symfony/twig-bridge/Resources/views/Email/zurb_2/notification/content_markdown.html.twig delete mode 100644 lib/symfony/twig-bridge/Resources/views/Email/zurb_2/notification/local.css delete mode 100644 lib/symfony/twig-bridge/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig delete mode 100644 lib/symfony/twig-bridge/Resources/views/Form/bootstrap_3_layout.html.twig delete mode 100644 lib/symfony/twig-bridge/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig delete mode 100644 lib/symfony/twig-bridge/Resources/views/Form/bootstrap_4_layout.html.twig delete mode 100644 lib/symfony/twig-bridge/Resources/views/Form/bootstrap_5_horizontal_layout.html.twig delete mode 100644 lib/symfony/twig-bridge/Resources/views/Form/bootstrap_5_layout.html.twig delete mode 100644 lib/symfony/twig-bridge/Resources/views/Form/bootstrap_base_layout.html.twig delete mode 100644 lib/symfony/twig-bridge/Resources/views/Form/form_div_layout.html.twig delete mode 100644 lib/symfony/twig-bridge/Resources/views/Form/form_table_layout.html.twig delete mode 100644 lib/symfony/twig-bridge/Resources/views/Form/foundation_5_layout.html.twig delete mode 100644 lib/symfony/twig-bridge/Resources/views/Form/foundation_6_layout.html.twig delete mode 100644 lib/symfony/twig-bridge/Resources/views/Form/tailwind_2_layout.html.twig delete mode 100644 lib/symfony/twig-bridge/TokenParser/DumpTokenParser.php delete mode 100644 lib/symfony/twig-bridge/TokenParser/FormThemeTokenParser.php delete mode 100644 lib/symfony/twig-bridge/TokenParser/StopwatchTokenParser.php delete mode 100644 lib/symfony/twig-bridge/TokenParser/TransDefaultDomainTokenParser.php delete mode 100644 lib/symfony/twig-bridge/TokenParser/TransTokenParser.php delete mode 100644 lib/symfony/twig-bridge/Translation/TwigExtractor.php delete mode 100644 lib/symfony/twig-bridge/UndefinedCallableHandler.php delete mode 100644 lib/symfony/twig-bridge/composer.json delete mode 100644 lib/symfony/twig-bundle/CHANGELOG.md delete mode 100644 lib/symfony/twig-bundle/CacheWarmer/TemplateCacheWarmer.php delete mode 100644 lib/symfony/twig-bundle/Command/LintCommand.php delete mode 100644 lib/symfony/twig-bundle/DependencyInjection/Compiler/ExtensionPass.php delete mode 100644 lib/symfony/twig-bundle/DependencyInjection/Compiler/RuntimeLoaderPass.php delete mode 100644 lib/symfony/twig-bundle/DependencyInjection/Compiler/TwigEnvironmentPass.php delete mode 100644 lib/symfony/twig-bundle/DependencyInjection/Compiler/TwigLoaderPass.php delete mode 100644 lib/symfony/twig-bundle/DependencyInjection/Configuration.php delete mode 100644 lib/symfony/twig-bundle/DependencyInjection/Configurator/EnvironmentConfigurator.php delete mode 100644 lib/symfony/twig-bundle/DependencyInjection/TwigExtension.php delete mode 100644 lib/symfony/twig-bundle/LICENSE delete mode 100644 lib/symfony/twig-bundle/README.md delete mode 100644 lib/symfony/twig-bundle/Resources/config/console.php delete mode 100644 lib/symfony/twig-bundle/Resources/config/form.php delete mode 100644 lib/symfony/twig-bundle/Resources/config/mailer.php delete mode 100644 lib/symfony/twig-bundle/Resources/config/schema/twig-1.0.xsd delete mode 100644 lib/symfony/twig-bundle/Resources/config/twig.php delete mode 100644 lib/symfony/twig-bundle/TemplateIterator.php delete mode 100644 lib/symfony/twig-bundle/TwigBundle.php delete mode 100644 lib/symfony/twig-bundle/composer.json delete mode 100644 lib/symfony/var-dumper/CHANGELOG.md delete mode 100644 lib/symfony/var-dumper/Caster/AmqpCaster.php delete mode 100644 lib/symfony/var-dumper/Caster/ArgsStub.php delete mode 100644 lib/symfony/var-dumper/Caster/Caster.php delete mode 100644 lib/symfony/var-dumper/Caster/ClassStub.php delete mode 100644 lib/symfony/var-dumper/Caster/ConstStub.php delete mode 100644 lib/symfony/var-dumper/Caster/CutArrayStub.php delete mode 100644 lib/symfony/var-dumper/Caster/CutStub.php delete mode 100644 lib/symfony/var-dumper/Caster/DOMCaster.php delete mode 100644 lib/symfony/var-dumper/Caster/DateCaster.php delete mode 100644 lib/symfony/var-dumper/Caster/DoctrineCaster.php delete mode 100644 lib/symfony/var-dumper/Caster/DsCaster.php delete mode 100644 lib/symfony/var-dumper/Caster/DsPairStub.php delete mode 100644 lib/symfony/var-dumper/Caster/EnumStub.php delete mode 100644 lib/symfony/var-dumper/Caster/ExceptionCaster.php delete mode 100644 lib/symfony/var-dumper/Caster/FiberCaster.php delete mode 100644 lib/symfony/var-dumper/Caster/FrameStub.php delete mode 100644 lib/symfony/var-dumper/Caster/GmpCaster.php delete mode 100644 lib/symfony/var-dumper/Caster/ImagineCaster.php delete mode 100644 lib/symfony/var-dumper/Caster/ImgStub.php delete mode 100644 lib/symfony/var-dumper/Caster/IntlCaster.php delete mode 100644 lib/symfony/var-dumper/Caster/LinkStub.php delete mode 100644 lib/symfony/var-dumper/Caster/MemcachedCaster.php delete mode 100644 lib/symfony/var-dumper/Caster/MysqliCaster.php delete mode 100644 lib/symfony/var-dumper/Caster/PdoCaster.php delete mode 100644 lib/symfony/var-dumper/Caster/PgSqlCaster.php delete mode 100644 lib/symfony/var-dumper/Caster/ProxyManagerCaster.php delete mode 100644 lib/symfony/var-dumper/Caster/RdKafkaCaster.php delete mode 100644 lib/symfony/var-dumper/Caster/RedisCaster.php delete mode 100644 lib/symfony/var-dumper/Caster/ReflectionCaster.php delete mode 100644 lib/symfony/var-dumper/Caster/ResourceCaster.php delete mode 100644 lib/symfony/var-dumper/Caster/SplCaster.php delete mode 100644 lib/symfony/var-dumper/Caster/StubCaster.php delete mode 100644 lib/symfony/var-dumper/Caster/SymfonyCaster.php delete mode 100644 lib/symfony/var-dumper/Caster/TraceStub.php delete mode 100644 lib/symfony/var-dumper/Caster/UuidCaster.php delete mode 100644 lib/symfony/var-dumper/Caster/XmlReaderCaster.php delete mode 100644 lib/symfony/var-dumper/Caster/XmlResourceCaster.php delete mode 100644 lib/symfony/var-dumper/Cloner/AbstractCloner.php delete mode 100644 lib/symfony/var-dumper/Cloner/ClonerInterface.php delete mode 100644 lib/symfony/var-dumper/Cloner/Cursor.php delete mode 100644 lib/symfony/var-dumper/Cloner/Data.php delete mode 100644 lib/symfony/var-dumper/Cloner/DumperInterface.php delete mode 100644 lib/symfony/var-dumper/Cloner/Stub.php delete mode 100644 lib/symfony/var-dumper/Cloner/VarCloner.php delete mode 100644 lib/symfony/var-dumper/Command/Descriptor/CliDescriptor.php delete mode 100644 lib/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php delete mode 100644 lib/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php delete mode 100644 lib/symfony/var-dumper/Command/ServerDumpCommand.php delete mode 100644 lib/symfony/var-dumper/Dumper/AbstractDumper.php delete mode 100644 lib/symfony/var-dumper/Dumper/CliDumper.php delete mode 100644 lib/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php delete mode 100644 lib/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php delete mode 100644 lib/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php delete mode 100644 lib/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php delete mode 100644 lib/symfony/var-dumper/Dumper/ContextualizedDumper.php delete mode 100644 lib/symfony/var-dumper/Dumper/DataDumperInterface.php delete mode 100644 lib/symfony/var-dumper/Dumper/HtmlDumper.php delete mode 100644 lib/symfony/var-dumper/Dumper/ServerDumper.php delete mode 100644 lib/symfony/var-dumper/Exception/ThrowingCasterException.php delete mode 100644 lib/symfony/var-dumper/LICENSE delete mode 100644 lib/symfony/var-dumper/README.md delete mode 100644 lib/symfony/var-dumper/Resources/bin/var-dump-server delete mode 100644 lib/symfony/var-dumper/Resources/css/htmlDescriptor.css delete mode 100644 lib/symfony/var-dumper/Resources/functions/dump.php delete mode 100644 lib/symfony/var-dumper/Resources/js/htmlDescriptor.js delete mode 100644 lib/symfony/var-dumper/Server/Connection.php delete mode 100644 lib/symfony/var-dumper/Server/DumpServer.php delete mode 100644 lib/symfony/var-dumper/VarDumper.php delete mode 100644 lib/symfony/var-dumper/composer.json delete mode 100644 lib/symfony/var-exporter/CHANGELOG.md delete mode 100644 lib/symfony/var-exporter/Exception/ClassNotFoundException.php delete mode 100644 lib/symfony/var-exporter/Exception/ExceptionInterface.php delete mode 100644 lib/symfony/var-exporter/Exception/NotInstantiableTypeException.php delete mode 100644 lib/symfony/var-exporter/Instantiator.php delete mode 100644 lib/symfony/var-exporter/Internal/Exporter.php delete mode 100644 lib/symfony/var-exporter/Internal/Hydrator.php delete mode 100644 lib/symfony/var-exporter/Internal/Reference.php delete mode 100644 lib/symfony/var-exporter/Internal/Registry.php delete mode 100644 lib/symfony/var-exporter/Internal/Values.php delete mode 100644 lib/symfony/var-exporter/LICENSE delete mode 100644 lib/symfony/var-exporter/README.md delete mode 100644 lib/symfony/var-exporter/VarExporter.php delete mode 100644 lib/symfony/var-exporter/composer.json delete mode 100644 lib/symfony/web-profiler-bundle/CHANGELOG.md delete mode 100644 lib/symfony/web-profiler-bundle/Controller/ExceptionPanelController.php delete mode 100644 lib/symfony/web-profiler-bundle/Controller/ProfilerController.php delete mode 100644 lib/symfony/web-profiler-bundle/Controller/RouterController.php delete mode 100644 lib/symfony/web-profiler-bundle/Csp/ContentSecurityPolicyHandler.php delete mode 100644 lib/symfony/web-profiler-bundle/Csp/NonceGenerator.php delete mode 100644 lib/symfony/web-profiler-bundle/DependencyInjection/Configuration.php delete mode 100644 lib/symfony/web-profiler-bundle/DependencyInjection/WebProfilerExtension.php delete mode 100644 lib/symfony/web-profiler-bundle/EventListener/WebDebugToolbarListener.php delete mode 100644 lib/symfony/web-profiler-bundle/LICENSE delete mode 100644 lib/symfony/web-profiler-bundle/Profiler/TemplateManager.php delete mode 100644 lib/symfony/web-profiler-bundle/README.md delete mode 100644 lib/symfony/web-profiler-bundle/Resources/ICONS_LICENSE.txt delete mode 100644 lib/symfony/web-profiler-bundle/Resources/config/profiler.php delete mode 100644 lib/symfony/web-profiler-bundle/Resources/config/routing/profiler.xml delete mode 100644 lib/symfony/web-profiler-bundle/Resources/config/routing/wdt.xml delete mode 100644 lib/symfony/web-profiler-bundle/Resources/config/schema/webprofiler-1.0.xsd delete mode 100644 lib/symfony/web-profiler-bundle/Resources/config/toolbar.php delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Collector/ajax.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Collector/cache.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Collector/config.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Collector/events.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Collector/exception.css.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Collector/exception.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Collector/form.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Collector/http_client.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Collector/logger.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Collector/mailer.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Collector/memory.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Collector/messenger.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Collector/notifier.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Collector/request.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Collector/router.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Collector/time.css.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Collector/time.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Collector/time.js delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Collector/translation.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Collector/twig.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Collector/validator.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/ajax.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/cache.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/close.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/config.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/event.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/exception.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/filter.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/form.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/forward.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/http-client.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/logger.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/mailer.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/memory.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/menu.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/messenger.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/no-gray.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/no.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/notifier.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/redirect.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/request.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/router.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/search.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/symfony.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/time.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/translation.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/twig.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/validator.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Icon/yes.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Profiler/ajax_layout.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Profiler/bag.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Profiler/base.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Profiler/base_js.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Profiler/cancel.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Profiler/header.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Profiler/info.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Profiler/layout.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Profiler/open.css.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Profiler/open.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Profiler/profiler.css.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Profiler/results.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Profiler/search.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Profiler/settings.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Profiler/table.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar.css.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar_item.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar_js.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar_redirect.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/Router/panel.html.twig delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/images/icon-minus-square.svg delete mode 100644 lib/symfony/web-profiler-bundle/Resources/views/images/icon-plus-square.svg delete mode 100644 lib/symfony/web-profiler-bundle/Twig/WebProfilerExtension.php delete mode 100644 lib/symfony/web-profiler-bundle/WebProfilerBundle.php delete mode 100644 lib/symfony/web-profiler-bundle/composer.json delete mode 100644 lib/symfony/yaml/CHANGELOG.md delete mode 100644 lib/symfony/yaml/Command/LintCommand.php delete mode 100644 lib/symfony/yaml/Dumper.php delete mode 100644 lib/symfony/yaml/Escaper.php delete mode 100644 lib/symfony/yaml/Exception/DumpException.php delete mode 100644 lib/symfony/yaml/Exception/ExceptionInterface.php delete mode 100644 lib/symfony/yaml/Exception/ParseException.php delete mode 100644 lib/symfony/yaml/Exception/RuntimeException.php delete mode 100644 lib/symfony/yaml/Inline.php delete mode 100644 lib/symfony/yaml/LICENSE delete mode 100644 lib/symfony/yaml/Parser.php delete mode 100644 lib/symfony/yaml/README.md delete mode 100644 lib/symfony/yaml/Resources/bin/yaml-lint delete mode 100644 lib/symfony/yaml/Tag/TaggedValue.php delete mode 100644 lib/symfony/yaml/Unescaper.php delete mode 100644 lib/symfony/yaml/Yaml.php delete mode 100644 lib/symfony/yaml/composer.json delete mode 100644 lib/thenetworg/oauth2-azure/.devcontainer/Dockerfile delete mode 100644 lib/thenetworg/oauth2-azure/.devcontainer/devcontainer.json delete mode 100644 lib/thenetworg/oauth2-azure/.gitignore delete mode 100644 lib/thenetworg/oauth2-azure/.php_cs delete mode 100644 lib/thenetworg/oauth2-azure/.vscode/launch.json delete mode 100644 lib/thenetworg/oauth2-azure/CHANGELOG.md delete mode 100644 lib/thenetworg/oauth2-azure/LICENSE.md delete mode 100644 lib/thenetworg/oauth2-azure/README.md delete mode 100644 lib/thenetworg/oauth2-azure/composer.json delete mode 100644 lib/thenetworg/oauth2-azure/src/Grant/JwtBearer.php delete mode 100644 lib/thenetworg/oauth2-azure/src/Provider/Azure.php delete mode 100644 lib/thenetworg/oauth2-azure/src/Provider/AzureResourceOwner.php delete mode 100644 lib/thenetworg/oauth2-azure/src/Token/AccessToken.php delete mode 100644 lib/twig/twig/.editorconfig delete mode 100644 lib/twig/twig/.gitattributes delete mode 100644 lib/twig/twig/.github/workflows/ci.yml delete mode 100644 lib/twig/twig/.github/workflows/documentation.yml delete mode 100644 lib/twig/twig/.gitignore delete mode 100644 lib/twig/twig/.php-cs-fixer.dist.php delete mode 100644 lib/twig/twig/CHANGELOG delete mode 100644 lib/twig/twig/LICENSE delete mode 100644 lib/twig/twig/README.rst delete mode 100644 lib/twig/twig/composer.json delete mode 100644 lib/twig/twig/src/Cache/CacheInterface.php delete mode 100644 lib/twig/twig/src/Cache/FilesystemCache.php delete mode 100644 lib/twig/twig/src/Cache/NullCache.php delete mode 100644 lib/twig/twig/src/Compiler.php delete mode 100644 lib/twig/twig/src/Environment.php delete mode 100644 lib/twig/twig/src/Error/Error.php delete mode 100644 lib/twig/twig/src/Error/LoaderError.php delete mode 100644 lib/twig/twig/src/Error/RuntimeError.php delete mode 100644 lib/twig/twig/src/Error/SyntaxError.php delete mode 100644 lib/twig/twig/src/ExpressionParser.php delete mode 100644 lib/twig/twig/src/Extension/AbstractExtension.php delete mode 100644 lib/twig/twig/src/Extension/CoreExtension.php delete mode 100644 lib/twig/twig/src/Extension/DebugExtension.php delete mode 100644 lib/twig/twig/src/Extension/EscaperExtension.php delete mode 100644 lib/twig/twig/src/Extension/ExtensionInterface.php delete mode 100644 lib/twig/twig/src/Extension/GlobalsInterface.php delete mode 100644 lib/twig/twig/src/Extension/OptimizerExtension.php delete mode 100644 lib/twig/twig/src/Extension/ProfilerExtension.php delete mode 100644 lib/twig/twig/src/Extension/RuntimeExtensionInterface.php delete mode 100644 lib/twig/twig/src/Extension/SandboxExtension.php delete mode 100644 lib/twig/twig/src/Extension/StagingExtension.php delete mode 100644 lib/twig/twig/src/Extension/StringLoaderExtension.php delete mode 100644 lib/twig/twig/src/ExtensionSet.php delete mode 100644 lib/twig/twig/src/FileExtensionEscapingStrategy.php delete mode 100644 lib/twig/twig/src/Lexer.php delete mode 100644 lib/twig/twig/src/Loader/ArrayLoader.php delete mode 100644 lib/twig/twig/src/Loader/ChainLoader.php delete mode 100644 lib/twig/twig/src/Loader/FilesystemLoader.php delete mode 100644 lib/twig/twig/src/Loader/LoaderInterface.php delete mode 100644 lib/twig/twig/src/Markup.php delete mode 100644 lib/twig/twig/src/Node/AutoEscapeNode.php delete mode 100644 lib/twig/twig/src/Node/BlockNode.php delete mode 100644 lib/twig/twig/src/Node/BlockReferenceNode.php delete mode 100644 lib/twig/twig/src/Node/BodyNode.php delete mode 100644 lib/twig/twig/src/Node/CheckSecurityCallNode.php delete mode 100644 lib/twig/twig/src/Node/CheckSecurityNode.php delete mode 100644 lib/twig/twig/src/Node/CheckToStringNode.php delete mode 100644 lib/twig/twig/src/Node/DeprecatedNode.php delete mode 100644 lib/twig/twig/src/Node/DoNode.php delete mode 100644 lib/twig/twig/src/Node/EmbedNode.php delete mode 100644 lib/twig/twig/src/Node/Expression/AbstractExpression.php delete mode 100644 lib/twig/twig/src/Node/Expression/ArrayExpression.php delete mode 100644 lib/twig/twig/src/Node/Expression/ArrowFunctionExpression.php delete mode 100644 lib/twig/twig/src/Node/Expression/AssignNameExpression.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/AbstractBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/AddBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/AndBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/BitwiseAndBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/BitwiseOrBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/BitwiseXorBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/ConcatBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/DivBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/EndsWithBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/EqualBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/FloorDivBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/GreaterBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/GreaterEqualBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/InBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/LessBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/LessEqualBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/MatchesBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/ModBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/MulBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/NotEqualBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/NotInBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/OrBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/PowerBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/RangeBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/SpaceshipBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/StartsWithBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Binary/SubBinary.php delete mode 100644 lib/twig/twig/src/Node/Expression/BlockReferenceExpression.php delete mode 100644 lib/twig/twig/src/Node/Expression/CallExpression.php delete mode 100644 lib/twig/twig/src/Node/Expression/ConditionalExpression.php delete mode 100644 lib/twig/twig/src/Node/Expression/ConstantExpression.php delete mode 100644 lib/twig/twig/src/Node/Expression/Filter/DefaultFilter.php delete mode 100644 lib/twig/twig/src/Node/Expression/FilterExpression.php delete mode 100644 lib/twig/twig/src/Node/Expression/FunctionExpression.php delete mode 100644 lib/twig/twig/src/Node/Expression/GetAttrExpression.php delete mode 100644 lib/twig/twig/src/Node/Expression/InlinePrint.php delete mode 100644 lib/twig/twig/src/Node/Expression/MethodCallExpression.php delete mode 100644 lib/twig/twig/src/Node/Expression/NameExpression.php delete mode 100644 lib/twig/twig/src/Node/Expression/NullCoalesceExpression.php delete mode 100644 lib/twig/twig/src/Node/Expression/ParentExpression.php delete mode 100644 lib/twig/twig/src/Node/Expression/TempNameExpression.php delete mode 100644 lib/twig/twig/src/Node/Expression/Test/ConstantTest.php delete mode 100644 lib/twig/twig/src/Node/Expression/Test/DefinedTest.php delete mode 100644 lib/twig/twig/src/Node/Expression/Test/DivisiblebyTest.php delete mode 100644 lib/twig/twig/src/Node/Expression/Test/EvenTest.php delete mode 100644 lib/twig/twig/src/Node/Expression/Test/NullTest.php delete mode 100644 lib/twig/twig/src/Node/Expression/Test/OddTest.php delete mode 100644 lib/twig/twig/src/Node/Expression/Test/SameasTest.php delete mode 100644 lib/twig/twig/src/Node/Expression/TestExpression.php delete mode 100644 lib/twig/twig/src/Node/Expression/Unary/AbstractUnary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Unary/NegUnary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Unary/NotUnary.php delete mode 100644 lib/twig/twig/src/Node/Expression/Unary/PosUnary.php delete mode 100644 lib/twig/twig/src/Node/Expression/VariadicExpression.php delete mode 100644 lib/twig/twig/src/Node/FlushNode.php delete mode 100644 lib/twig/twig/src/Node/ForLoopNode.php delete mode 100644 lib/twig/twig/src/Node/ForNode.php delete mode 100644 lib/twig/twig/src/Node/IfNode.php delete mode 100644 lib/twig/twig/src/Node/ImportNode.php delete mode 100644 lib/twig/twig/src/Node/IncludeNode.php delete mode 100644 lib/twig/twig/src/Node/MacroNode.php delete mode 100644 lib/twig/twig/src/Node/ModuleNode.php delete mode 100644 lib/twig/twig/src/Node/Node.php delete mode 100644 lib/twig/twig/src/Node/NodeCaptureInterface.php delete mode 100644 lib/twig/twig/src/Node/NodeOutputInterface.php delete mode 100644 lib/twig/twig/src/Node/PrintNode.php delete mode 100644 lib/twig/twig/src/Node/SandboxNode.php delete mode 100644 lib/twig/twig/src/Node/SetNode.php delete mode 100644 lib/twig/twig/src/Node/TextNode.php delete mode 100644 lib/twig/twig/src/Node/WithNode.php delete mode 100644 lib/twig/twig/src/NodeTraverser.php delete mode 100644 lib/twig/twig/src/NodeVisitor/AbstractNodeVisitor.php delete mode 100644 lib/twig/twig/src/NodeVisitor/EscaperNodeVisitor.php delete mode 100644 lib/twig/twig/src/NodeVisitor/MacroAutoImportNodeVisitor.php delete mode 100644 lib/twig/twig/src/NodeVisitor/NodeVisitorInterface.php delete mode 100644 lib/twig/twig/src/NodeVisitor/OptimizerNodeVisitor.php delete mode 100644 lib/twig/twig/src/NodeVisitor/SafeAnalysisNodeVisitor.php delete mode 100644 lib/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php delete mode 100644 lib/twig/twig/src/Parser.php delete mode 100644 lib/twig/twig/src/Profiler/Dumper/BaseDumper.php delete mode 100644 lib/twig/twig/src/Profiler/Dumper/BlackfireDumper.php delete mode 100644 lib/twig/twig/src/Profiler/Dumper/HtmlDumper.php delete mode 100644 lib/twig/twig/src/Profiler/Dumper/TextDumper.php delete mode 100644 lib/twig/twig/src/Profiler/Node/EnterProfileNode.php delete mode 100644 lib/twig/twig/src/Profiler/Node/LeaveProfileNode.php delete mode 100644 lib/twig/twig/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php delete mode 100644 lib/twig/twig/src/Profiler/Profile.php delete mode 100644 lib/twig/twig/src/RuntimeLoader/ContainerRuntimeLoader.php delete mode 100644 lib/twig/twig/src/RuntimeLoader/FactoryRuntimeLoader.php delete mode 100644 lib/twig/twig/src/RuntimeLoader/RuntimeLoaderInterface.php delete mode 100644 lib/twig/twig/src/Sandbox/SecurityError.php delete mode 100644 lib/twig/twig/src/Sandbox/SecurityNotAllowedFilterError.php delete mode 100644 lib/twig/twig/src/Sandbox/SecurityNotAllowedFunctionError.php delete mode 100644 lib/twig/twig/src/Sandbox/SecurityNotAllowedMethodError.php delete mode 100644 lib/twig/twig/src/Sandbox/SecurityNotAllowedPropertyError.php delete mode 100644 lib/twig/twig/src/Sandbox/SecurityNotAllowedTagError.php delete mode 100644 lib/twig/twig/src/Sandbox/SecurityPolicy.php delete mode 100644 lib/twig/twig/src/Sandbox/SecurityPolicyInterface.php delete mode 100644 lib/twig/twig/src/Source.php delete mode 100644 lib/twig/twig/src/Template.php delete mode 100644 lib/twig/twig/src/TemplateWrapper.php delete mode 100644 lib/twig/twig/src/Token.php delete mode 100644 lib/twig/twig/src/TokenParser/AbstractTokenParser.php delete mode 100644 lib/twig/twig/src/TokenParser/ApplyTokenParser.php delete mode 100644 lib/twig/twig/src/TokenParser/AutoEscapeTokenParser.php delete mode 100644 lib/twig/twig/src/TokenParser/BlockTokenParser.php delete mode 100644 lib/twig/twig/src/TokenParser/DeprecatedTokenParser.php delete mode 100644 lib/twig/twig/src/TokenParser/DoTokenParser.php delete mode 100644 lib/twig/twig/src/TokenParser/EmbedTokenParser.php delete mode 100644 lib/twig/twig/src/TokenParser/ExtendsTokenParser.php delete mode 100644 lib/twig/twig/src/TokenParser/FlushTokenParser.php delete mode 100644 lib/twig/twig/src/TokenParser/ForTokenParser.php delete mode 100644 lib/twig/twig/src/TokenParser/FromTokenParser.php delete mode 100644 lib/twig/twig/src/TokenParser/IfTokenParser.php delete mode 100644 lib/twig/twig/src/TokenParser/ImportTokenParser.php delete mode 100644 lib/twig/twig/src/TokenParser/IncludeTokenParser.php delete mode 100644 lib/twig/twig/src/TokenParser/MacroTokenParser.php delete mode 100644 lib/twig/twig/src/TokenParser/SandboxTokenParser.php delete mode 100644 lib/twig/twig/src/TokenParser/SetTokenParser.php delete mode 100644 lib/twig/twig/src/TokenParser/TokenParserInterface.php delete mode 100644 lib/twig/twig/src/TokenParser/UseTokenParser.php delete mode 100644 lib/twig/twig/src/TokenParser/WithTokenParser.php delete mode 100644 lib/twig/twig/src/TokenStream.php delete mode 100644 lib/twig/twig/src/TwigFilter.php delete mode 100644 lib/twig/twig/src/TwigFunction.php delete mode 100644 lib/twig/twig/src/TwigTest.php delete mode 100644 lib/twig/twig/src/Util/DeprecationCollector.php delete mode 100644 lib/twig/twig/src/Util/TemplateDirIterator.php delete mode 100644 lib/web.config delete mode 100644 lib/webmozart/assert/CHANGELOG.md delete mode 100644 lib/webmozart/assert/LICENSE delete mode 100644 lib/webmozart/assert/README.md delete mode 100644 lib/webmozart/assert/composer.json delete mode 100644 lib/webmozart/assert/src/Assert.php delete mode 100644 lib/webmozart/assert/src/InvalidArgumentException.php delete mode 100644 lib/webmozart/assert/src/Mixin.php create mode 100644 sources/DI/Form/Builder/AttributeBuilder.php create mode 100644 sources/DI/Form/Builder/LayoutBuilder.php create mode 100644 sources/DI/Form/Transformer/DocumentTransformer.php create mode 100644 sources/DI/Form/Transformer/ExternalKeyTransformer.php rename sources/DI/Form/Type/{Simple => Attribute}/DocumentType.php (60%) create mode 100644 sources/DI/Form/Type/Attribute/ExternalFieldType.php rename sources/DI/Form/Type/{Simple => Attribute}/ExternalKeyType.php (86%) rename sources/DI/Form/Type/{Simple => Attribute}/LinkSetType.php (66%) rename sources/DI/Form/Type/{ => Compound}/ConfigurationType.php (85%) rename sources/DI/Form/Type/{ => Compound}/ObjectSingleAttributeType.php (66%) rename sources/DI/Form/Type/{ => Compound}/ObjectType.php (63%) rename templates/DI/{object/object_single_attribute.html.twig => form.html.twig} (100%) create mode 100644 templates/DI/form/classic_theme.html.twig delete mode 100644 templates/DI/form/external_key_widget.html.twig delete mode 100644 templates/DI/form/form_layout.html.twig diff --git a/css/DI/app.css b/css/DI/app.css new file mode 100644 index 000000000..ab84f87f5 --- /dev/null +++ b/css/DI/app.css @@ -0,0 +1,86 @@ +body{ + font-family: 'Montserrat', serif; + padding-top: 64px; +} + +.combodo-row{ + display: flex; +} +.combodo-row fieldset{ + flex-grow: 1; +} +.combodo-column{ + padding: 10px; +} +.combodo-field-set{ + border: #b7b7b7 dashed 1px; + padding: 10px; + border-radius: 10px; +} +.combodo-field-set-label{ + font-weight: bold; + border-bottom: 2px solid #b7b7b7; + margin-bottom: 10px; +} +.loading{ + position: relative; +} +.loading:after{ + content: 'loading...'; + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + background-color: #0d6efd11; + display: flex; + align-items: center; + justify-content: center; + border-radius: 10px; +} +label.required:after{ + content: ' *'; + color: red; +} +label.locked:after{ + content: "\f023"; + font-family: "Font Awesome 5 Free", serif; + font-weight: 600; + margin-left: 8px; + color: #ffcc00; + font-size: .7rem; +} +form{ + /*background-color: #f8f8f8;*/ + border-radius: 10px; + padding: 5px; +} +form.actions button,a{ + margin: 0 3px; +} +[data-block="container"]:has(.test:empty) { + display: none; +} +.z_list_list{ + display: flex; +} +body[data-bs-theme="dark"] .app_icon{ + filter: invert(1); +} +.combodo-field-set-label.is_indirect_1:after{ + content: 'indirect'; + margin-left: 5px; + font-size: .8rem; + color: #0C63E4; +} +.combodo-field-set-label.is_abstract_1:after{ + content: 'abstract'; + margin-left: 5px; + font-size: .8rem; + color: #0C63E4; +} +.dropdown_scroll_300{ + max-height: 300px; + overflow-y: auto; + overflow-x: clip; +} diff --git a/js/DI/app.js b/js/DI/app.js new file mode 100644 index 000000000..dcba71d68 --- /dev/null +++ b/js/DI/app.js @@ -0,0 +1,48 @@ +/** + * Application handling. + * + * @returns {{init: init}} + * @constructor + */ +const App = function(){ + + // dom selectors + const aSelectors = { + darkModeButton: '#dark_mode' + }; + + /** + * init. + * + */ + function init(){ + + $(aSelectors.darkModeButton).on('click', function(){ + $('body').attr('data-bs-theme', this.ariaPressed === 'true' ? 'dark' : 'light'); + }); + + if (window.matchMedia('(prefers-color-scheme: dark)').matches) { + $('body').attr('data-bs-theme', 'dark'); + $(aSelectors.darkModeButton).attr('aria-pressed', 'true'); + $(aSelectors.darkModeButton).toggleClass('active', true); + } + + } + + return { + init + } +}; + + + + + + + + + + + + + diff --git a/js/DI/collection.js b/js/DI/collection.js new file mode 100644 index 000000000..4f9596619 --- /dev/null +++ b/js/DI/collection.js @@ -0,0 +1,158 @@ +/** + * Collections handling. + * + * @param oForm + * @param objectFormUrl + * @returns {{handleElement: handleElement}} + * @constructor + */ +const Collection = function(oForm, objectFormUrl){ + + /** + * Listen for add item buttons. + * + * @param oContainer + */ + function listenAddItem (oContainer) { + + oContainer.querySelectorAll('.add_item_link').forEach(btn => { + btn.addEventListener("click", addFormToCollection) + }); + + } + + /** + * Listen for create item buttons. + * + * @param oContainer + */ + function listenCreateItem (oContainer) { + + oContainer.querySelectorAll('.create_item_link').forEach(btn => { + btn.addEventListener("click", createObject) + }); + + } + + /** + * Listen for remove item buttons. + * + * @param oContainer + */ + function listenRemoveItem(oContainer){ + + oContainer.querySelectorAll('.btn-remove-link').forEach(btn => { + btn.addEventListener("click", (e) => { + + const oContainer = e.currentTarget.closest('.link_set_widget_container'); + + btn.closest('tr').remove() + + if(oContainer.querySelectorAll('tbody tr').length === 1) { + oContainer.querySelector('.no_data').style.display = 'table-row'; + } + }) + }); + + } + + /** + * Add form to the collection. + * + * @param e + */ + function addFormToCollection(e){ + + // retrieve link set container + const oContainer = e.currentTarget.closest('.link_set_widget_container'); + + // retrieve collection holder + const collectionHolder = oContainer.querySelector('.' + e.currentTarget.dataset.collectionHolderClass); + + // compute template + const text = collectionHolder + .dataset + .prototype + .replace( + /__name__/g, + collectionHolder.dataset.index + ); + + // create item element + const item = oToolkit.createElementFromHtml(text); + listenRemoveItem(item); + oForm.handleElement(item); + collectionHolder.appendChild(item); + + // store new index + collectionHolder.dataset.index++; + + // remove no data row + oContainer.querySelector('.no_data').style.display = 'none'; + } + + /** + * Create an iTop object. + * + * @param e + */ + function createObject(e){ + + // set modal loading state + $('#object_modal .modal-body').html('loading...'); + + // open modal + const myModalAlternative = new bootstrap.Modal('#object_modal', []); + myModalAlternative.show(); + + // compute object form url + const url = objectFormUrl + .replaceAll('object_class', e.currentTarget.dataset.objectClass) + .replaceAll('form_name', 'new'); + + // prepare request data + const aLockedAttributes = {}; + aLockedAttributes[e.currentTarget.dataset.extKeyToMe] = 0; + const aData = { + locked_attributes: aLockedAttributes + } + + // fetch url + fetch(url, { + method: 'post', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, + body: JSON.stringify(aData) + }) + .then((response) => response.json()) + .then((data) => { + const oModalBody = $('#object_modal .modal-body'); + oModalBody.html(data.template); + oForm.handleElement(oModalBody[0]); + }) + .catch(function (error) { + console.error(error); + }); + } + + /** + * Handle collection on the provided container element. + * + * @param oContainer + */ + const handleElement = function(oContainer) + { + listenAddItem(oContainer); + listenCreateItem(oContainer); + listenRemoveItem(oContainer); + } + + return { + handleElement + } +}; + + + diff --git a/js/DI/form.js b/js/DI/form.js index a730843ec..c7b21d0cc 100644 --- a/js/DI/form.js +++ b/js/DI/form.js @@ -1,7 +1,21 @@ +/** + * Forms handling. + * + * @param oWidget + * @returns {{handleElement: handleElement}} + * @constructor + */ +const Form = function(oWidget){ -const DIForm = function(reload_url){ + const DEPENDS_ON_SEPARATOR = ' '; - const SELECTOR = '[data-block="container"]'; + const aSelectors = { + dataDependsOn: '[data-depends-on]', + dataHideWhen: '[data-hide-when]', + dataDisableWhen: '[data-disable-when]', + dataBlockContainer: '[data-block="container"]', + dataAttCode: '[data-att-code="{0}"]' + }; /** * hideEmptyContainers. @@ -10,22 +24,11 @@ const DIForm = function(reload_url){ * Ex: FieldSetType with no children * */ - const hideEmptyContainers = function(oElement){ - $('.combodo-field-set', oElement).each(function(e){ + function hideEmptyContainers(oElement){ + $('.combodo-field-set', oElement).each(function(){ $(this).parent().toggle($(this).children().length !== 0); }); - }; - - /** - * parseTextToHtml. - * - * @param sText - * @returns {Document} - */ - const parseTextToHtml = (sText) => { - const oParser = new DOMParser(); - return oParser.parseFromString(sText, 'text/html'); - }; + } /** * updateForm. @@ -35,7 +38,7 @@ const DIForm = function(reload_url){ * @param sMethod * @returns {Promise} */ - const updateForm = async (aData, sUrl, sMethod) => { + async function updateForm(aData, sUrl, sMethod){ const req = await fetch(sUrl, { method: sMethod, body: aData, @@ -46,7 +49,7 @@ const DIForm = function(reload_url){ }); return await req.text(); - }; + } /** * changeOptions. @@ -55,7 +58,7 @@ const DIForm = function(reload_url){ * @param sId * @returns {Promise} */ - const changeOptions = async (oEvent, sId) => { + async function changeOptions(oEvent, sId){ // retrieve field that's need to be updated const oDependentField = document.getElementById(sId); @@ -66,21 +69,28 @@ const DIForm = function(reload_url){ const oForm = oDependentField.closest('form'); // retrieve field container - const oContainer = oDependentField.closest('[data-block="container"]'); + const oContainer = oDependentField.closest(aSelectors.dataBlockContainer); // set field container loading state oContainer.classList.add('loading'); - // prepare quest data - let sRequestBody = 'object_single_attribute['+oEvent.target.dataset.attCode + ']=' + oEvent.target.value; + // prepare request body + const oFormData = new FormData(oForm); + let sRequestBody = ''; + function encode(s){ return encodeURIComponent(s).replace(/%20/g,'+'); } + for(let pair of oFormData.entries()){ + if(typeof pair[1]=='string'){ + sRequestBody += (sRequestBody?'&':'') + encode(pair[0])+'='+encode(pair[1]); + } + } sRequestBody += '&att_code=' + oDependentField.dataset.attCode; sRequestBody += '&dependency_att_code=' + oEvent.target.dataset.attCode; // update fom - const sUpdateFormResponse = await updateForm(sRequestBody, reload_url, oForm.getAttribute('method')); - const oHtml = parseTextToHtml(sUpdateFormResponse); + const sUpdateFormResponse = await updateForm(sRequestBody, oForm.dataset.reloadUrl, oForm.getAttribute('method')); + const oHtml = oToolkit.parseTextToHtml(sUpdateFormResponse); let oSingle = oHtml.getElementById('object_single_attribute'); - oContainer.innerHTML = oSingle.innerHTML; + oContainer.replaceWith(oSingle.firstChild); // remove loading state oContainer.classList.remove('loading'); @@ -92,22 +102,23 @@ const DIForm = function(reload_url){ oNewDependentField.setAttribute('data-att-code', sAttCode); // init dynamics + initDependencies(oContainer); initDynamicsInvisible(oContainer); initDynamicsDisable(oContainer); // init widgets - initWidgets(oContainer); - }; + oWidget.handleElement(oContainer); + } /** * initDependencies. * * @param oElement */ - const initDependencies = function(oElement){ + function initDependencies(oElement){ // get all dependent fields - const aDependentsFields = oElement.querySelectorAll('[data-depends-on]'); + const aDependentsFields = oElement.querySelectorAll(aSelectors.dataDependsOn); // iterate throw dependent fields... aDependentsFields.forEach(function (oDependentField) { @@ -116,13 +127,13 @@ const DIForm = function(reload_url){ const sDependsOn = oDependentField.dataset.dependsOn; // may have multiple dependencies - let aDependsEls = sDependsOn.split(' '); + let aDependsEls = sDependsOn.split(DEPENDS_ON_SEPARATOR); // iterate throw dependencies... aDependsEls.forEach(function(sEl){ // retrieve dependency - const oDependsOnElement = document.querySelector(`[id$="${sEl}"]`); + const oDependsOnElement = oElement.querySelector(`[id$="${sEl}"]`); // listen for changes if(oDependsOnElement != null){ @@ -130,17 +141,17 @@ const DIForm = function(reload_url){ } }); }); - }; + } /** * initDynamicsInvisible. * * @param oElement */ - const initDynamicsInvisible = function(oElement){ + function initDynamicsInvisible(oElement){ // get all dynamic hide fields - const aInvisibleFields = oElement.querySelectorAll('[data-hide-when]'); + const aInvisibleFields = oElement.querySelectorAll(aSelectors.dataHideWhen); // iterate throw fields... aInvisibleFields.forEach(function (oInvisibleField) { @@ -149,29 +160,29 @@ const DIForm = function(reload_url){ const aHideWhenCondition = JSON.parse(oInvisibleField.dataset.hideWhen); // retrieve condition data - const oHideWhenElement = document.querySelector(`[data-att-code="${aHideWhenCondition.att_code}"]`); + const oHideWhenElement = oElement.querySelector(String.format(aSelectors.dataAttCode, aHideWhenCondition.att_code)); // initial hidden state - oInvisibleField.closest(SELECTOR).hidden = (oHideWhenElement.value === aHideWhenCondition.value); + oInvisibleField.closest(aSelectors.dataBlockContainer).hidden = (oHideWhenElement.value === aHideWhenCondition.value); // listen for changes oHideWhenElement.addEventListener('change', (e) => { - oInvisibleField.closest(SELECTOR).hidden = (e.target.value === aHideWhenCondition.value); - oInvisibleField.closest(SELECTOR).style.visibility = (e.target.value === aHideWhenCondition.value) ? 'hidden' : ''; + oInvisibleField.closest(aSelectors.dataBlockContainer).hidden = (e.target.value === aHideWhenCondition.value); + oInvisibleField.closest(aSelectors.dataBlockContainer).style.visibility = (e.target.value === aHideWhenCondition.value) ? 'hidden' : ''; }); }); - }; + } /** * initDynamicsDisable. * * @param oElement */ - const initDynamicsDisable = function(oElement){ + function initDynamicsDisable(oElement){ // get all dynamic hide fields - const aDisabledFields = oElement.querySelectorAll('[data-disable-when]'); + const aDisabledFields = oElement.querySelectorAll(aSelectors.dataDisableWhen); // iterate throw fields... aDisabledFields.forEach(function (oDisabledField) { @@ -180,55 +191,33 @@ const DIForm = function(reload_url){ const aDisableWhenCondition = JSON.parse(oDisabledField.dataset.disableWhen); // retrieve condition data - const oDisableWhenElement = document.querySelector(`[data-att-code="${aDisableWhenCondition.att_code}"]`); + const oDisableWhenElement = oElement.querySelector(`[data-att-code="${aDisableWhenCondition.att_code}"]`); // initial disabled state - oDisabledField.closest(SELECTOR).disabled = (oDisableWhenElement.value === aDisableWhenCondition.value); + oDisabledField.closest(aSelectors.dataBlockContainer).disabled = (oDisableWhenElement.value === aDisableWhenCondition.value); // listen for changes oDisableWhenElement.addEventListener('change', (e) => { - oDisabledField.closest(SELECTOR).disabled = (e.target.value === aDisableWhenCondition.value); + oDisabledField.closest(aSelectors.dataBlockContainer).disabled = (e.target.value === aDisableWhenCondition.value); }); }); - }; - - /** - * initWidgets. - * - * @param oElement - */ - const initWidgets = function(oElement){ - - // get all widgets - const aWidgetFields = oElement.querySelectorAll('[data-widget]'); - - // iterate throw widgets... - aWidgetFields.forEach(function (widgetField) { - - // initialize widget - const sWidgetName = widgetField.dataset.widget; - const oWidget = eval(`$(widgetField).${sWidgetName}()`); - console.log('Init widget: ' + sWidgetName); - console.log(oWidget); - }); - - }; + } /** * handleElement. * * @param element */ - const handleElement = function(element){ + function handleElement(element){ hideEmptyContainers(element); initDependencies(element); - initWidgets(element); initDynamicsInvisible(element); initDynamicsDisable(element); + oWidget.handleElement(element); } return { - handleElement + handleElement, } }; diff --git a/js/DI/toolkit.js b/js/DI/toolkit.js new file mode 100644 index 000000000..638f03510 --- /dev/null +++ b/js/DI/toolkit.js @@ -0,0 +1,69 @@ +/** + * Toolkit. + * + * @returns {{init: init, parseTextToHtml: (function(*): Document), createElementFromHtml: (function(*): DocumentFragment)}} + * @constructor + */ +const Toolkit = function(){ + + function init(){ + installStringFormatFunction(); + } + + /** + * installStringFormatFunction. + * + * String formatter utility. + */ + function installStringFormatFunction(){ + if (!String.format) { + String.format = function(format) { + const args = Array.prototype.slice.call(arguments, 1); + return format.replace(/{(\d+)}/g, function(match, number) { + return typeof args[number] != 'undefined' ? args[number] : match; + }); + }; + } + } + + /** + * parseTextToHtml. + * + * @param sText + * @returns {Document} + */ + function parseTextToHtml(sText){ + const oParser = new DOMParser(); + return oParser.parseFromString(sText, 'text/html'); + } + + /** + * + * @param html + * @returns {DocumentFragment} + */ + function createElementFromHtml(html) { + const t = document.createElement('template'); + t.innerHTML = html; + return t.content; + } + + return { + init, + parseTextToHtml, + createElementFromHtml + } +}; + + + + + + + + + + + + + diff --git a/js/DI/widget.js b/js/DI/widget.js new file mode 100644 index 000000000..d463daa00 --- /dev/null +++ b/js/DI/widget.js @@ -0,0 +1,56 @@ +/** + * Widgets handling. + * + * @returns {{handleElement: handleElement}} + * @constructor + */ +const Widget = function(){ + + /** + * initWidgets. + * + * @param oElement + */ + function initWidgets(oElement){ + + // get all widgets + const aWidgetFields = oElement.querySelectorAll('[data-widget]'); + + // iterate throw widgets... + aWidgetFields.forEach(function (widgetField) { + + // initialize widget + const sWidgetName = widgetField.dataset.widget; + const oWidget = eval(`$(widgetField).${sWidgetName}()`); + console.log('Init widget: ' + sWidgetName); + console.log(oWidget); + }); + + } + + /** + * handleElement. + * + * @param element + */ + function handleElement(element){ + initWidgets(element); + } + + return { + handleElement, + } +}; + + + + + + + + + + + + + diff --git a/js/DI/text_widget.js b/js/DI/widget/text_widget.js similarity index 54% rename from js/DI/text_widget.js rename to js/DI/widget/text_widget.js index 8fc09c8c7..198e9e215 100644 --- a/js/DI/text_widget.js +++ b/js/DI/widget/text_widget.js @@ -12,7 +12,13 @@ $.widget( "itop.text_widget", // the constructor _create: function() { - CKEDITOR.replace( this.element.attr('id')); + editor = CKEDITOR.replace(this.element.attr('id'), { + language: 'fr', + uiColor: '#9ec5fe88', + toolbarStartupExpanded: true + }); + + } }); diff --git a/lib/.gitignore b/lib/.gitignore deleted file mode 100644 index aeb628c79..000000000 --- a/lib/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -# Combodo's fork of TCPDF -/combodo/tcpdf/examples -/combodo/tcpdf/tools -/combodo/tcpdf/fonts/** -!/combodo/tcpdf/fonts/courier* -!/combodo/tcpdf/fonts/dejavusans* -!/combodo/tcpdf/fonts/droidsansfallback* -!/combodo/tcpdf/fonts/helvetica* -!/combodo/tcpdf/fonts/symbol.php -!/combodo/tcpdf/fonts/times* -!/combodo/tcpdf/fonts/zapfdingbats.php - -# ArchiveTar -/pear/archive_tar/docs -/pear/archive_tar/scripts -/pear/archive_tar/sync-php4 - -# Emogrifier -/pelago/emogrifier/.github -/pelago/emogrifier/tests - -# SCSSPHP -/scssphp/scssphp/example - -# SwiftMailer -/swiftmailer/swiftmailer/.github -/swiftmailer/swiftmailer/doc -/swiftmailer/swiftmailer/tests - -# TWIG -/twig/twig/doc -/twig/twig/test -/twig/twig/drupal_test.sh diff --git a/lib/.htaccess b/lib/.htaccess deleted file mode 100644 index 1e558f452..000000000 --- a/lib/.htaccess +++ /dev/null @@ -1,24 +0,0 @@ -# Allow only static resources files -# - HTML not allowed as there could be some test pages calling server scripts or executing JS scripts -# - PHP not allowed as they should not be publicly accessible - -# Apache 2.4 - -Require all denied - - Require all granted - - - -# Apache 2.2 - -deny from all -Satisfy All - - Order Allow,Deny - Allow from all - - - -# Apache 2.2 and 2.4 -IndexIgnore * diff --git a/lib/apereo/phpcas/.codecov.yml b/lib/apereo/phpcas/.codecov.yml deleted file mode 100644 index ddfdd0eff..000000000 --- a/lib/apereo/phpcas/.codecov.yml +++ /dev/null @@ -1,17 +0,0 @@ -codecov: - strict_yaml_branch: master - -coverage: - round: up - precision: 2 - status: - project: - default: - target: "70%" - informational: true - patch: # temporarily disabled - default: - target: "70%" - informational: true - -comment: false diff --git a/lib/apereo/phpcas/.gitattributes b/lib/apereo/phpcas/.gitattributes deleted file mode 100644 index 3e28f4e42..000000000 --- a/lib/apereo/phpcas/.gitattributes +++ /dev/null @@ -1,7 +0,0 @@ -/docs/ export-ignore -/test/ export-ignore -/utils/ export-ignore -/.buildpath export-ignore -/.gitignore export-ignore -/.project export-ignore -/.travis.yml export-ignore diff --git a/lib/apereo/phpcas/.github/dependabot.yml b/lib/apereo/phpcas/.github/dependabot.yml deleted file mode 100644 index c630ffa6b..000000000 --- a/lib/apereo/phpcas/.github/dependabot.yml +++ /dev/null @@ -1,7 +0,0 @@ -version: 2 -updates: -- package-ecosystem: composer - directory: "/" - schedule: - interval: daily - open-pull-requests-limit: 10 diff --git a/lib/apereo/phpcas/.github/workflows/test.yml b/lib/apereo/phpcas/.github/workflows/test.yml deleted file mode 100644 index 081e334d6..000000000 --- a/lib/apereo/phpcas/.github/workflows/test.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Test - -on: - - push - - pull_request - -jobs: - test: - runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - php-version: - - php: '7.2' - phpunit: '8' - - php: '7.3' - phpunit: latest - - php: '7.4' - phpunit: latest - - php: '8.0' - phpunit: latest - - php: '8.1' - phpunit: latest - steps: - - uses: actions/checkout@v2 - - uses: php-actions/composer@v6 - with: - php_version: "${{ matrix.php-version.php }}" - - name: Run PHPUnit - uses: php-actions/phpunit@v3 - with: - version: "${{ matrix.php-version.phpunit }}" - php_version: "${{ matrix.php-version.php }}" - php_extensions: xdebug - args: --verbose --coverage-clover=coverage.xml - bootstrap: vendor/autoload.php - env: - XDEBUG_MODE: coverage - - name: Report coverage - uses: codecov/codecov-action@v1 - with: - files: coverage.xml diff --git a/lib/apereo/phpcas/CAS.php b/lib/apereo/phpcas/CAS.php deleted file mode 100644 index 6ddcf07bc..000000000 --- a/lib/apereo/phpcas/CAS.php +++ /dev/null @@ -1,32 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -require_once __DIR__.'/source/CAS.php'; - -trigger_error('Including CAS.php is deprecated. Install phpCAS using composer instead.', E_USER_DEPRECATED); diff --git a/lib/apereo/phpcas/LICENSE b/lib/apereo/phpcas/LICENSE deleted file mode 100644 index 261eeb9e9..000000000 --- a/lib/apereo/phpcas/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/lib/apereo/phpcas/NOTICE b/lib/apereo/phpcas/NOTICE deleted file mode 100644 index 70d9ffcd4..000000000 --- a/lib/apereo/phpcas/NOTICE +++ /dev/null @@ -1,81 +0,0 @@ -Copyright 2007-2011, JA-SIG, Inc. -This project includes software developed by Jasig. -http://www.jasig.org/ - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this software except in compliance with the License. -You may obtain a copy of the License at: - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -=========================================================================== - -Copyright © 2003-2007, The ESUP-Portail consortium - -Requirements for sources originally licensed under the New BSD License: - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -- Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. - -- Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. - -- Neither the name of JA-SIG, Inc. nor the names of its contributors may be -used to endorse or promote products derived from this software without -specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -=========================================================================== - -Copyright (c) 2009, Regents of the University of Nebraska -All rights reserved. - -Requirements for CAS_Autloader originally licensed under the New BSD License: - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. - -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -Neither the name of the University of Nebraska nor the names of its contributors -may be used to endorse or promote products derived from this software without -specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. diff --git a/lib/apereo/phpcas/README.md b/lib/apereo/phpcas/README.md deleted file mode 100644 index d48128912..000000000 --- a/lib/apereo/phpcas/README.md +++ /dev/null @@ -1,35 +0,0 @@ -phpCAS -======= - -phpCAS is an authentication library that allows PHP applications to easily authenticate -users via a Central Authentication Service (CAS) server. - -Please see the wiki website for more information: - -https://apereo.github.io/phpCAS/ - -Api documentation can be found here: - -https://apereo.github.io/phpCAS/api/ - - -[![Test](https://github.com/apereo/phpCAS/actions/workflows/test.yml/badge.svg)](https://github.com/apereo/phpCAS/actions/workflows/test.yml) - -LICENSE -------- - -Copyright 2007-2020, Apereo Foundation. -This project includes software developed by Apereo Foundation. -http://www.apereo.org/ - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this software except in compliance with the License. -You may obtain a copy of the License at: - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/lib/apereo/phpcas/composer.json b/lib/apereo/phpcas/composer.json deleted file mode 100644 index 89ab7b9f6..000000000 --- a/lib/apereo/phpcas/composer.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "name" : "apereo/phpcas", - "description" : "Provides a simple API for authenticating users against a CAS server", - "keywords" : [ - "cas", - "jasig", - "apereo" - ], - "homepage" : "https://wiki.jasig.org/display/CASC/phpCAS", - "type" : "library", - "license" : "Apache-2.0", - "authors" : [{ - "name" : "Joachim Fritschi", - "homepage" : "https://github.com/jfritschi", - "email" : "jfritschi@freenet.de" - }, { - "name" : "Adam Franco", - "homepage" : "https://github.com/adamfranco" - }, { - "name" : "Henry Pan", - "homepage" : "https://github.com/phy25" - } - ], - "require" : { - "php" : ">=7.1.0", - "ext-curl" : "*", - "ext-dom" : "*", - "psr/log" : "^1.0 || ^2.0 || ^3.0" - }, - "require-dev" : { - "monolog/monolog" : "^1.0.0 || ^2.0.0", - "phpunit/phpunit" : ">=7.5", - "phpstan/phpstan" : "^1.5" - }, - "autoload" : { - "classmap" : [ - "source/" - ] - }, - "autoload-dev" : { - "files": ["source/CAS.php"], - "psr-4" : { - "PhpCas\\" : "test/CAS/" - } - }, - "scripts" : { - "test" : "phpunit", - "phpstan" : "phpstan" - }, - "extra" : { - "branch-alias" : { - "dev-master" : "1.3.x-dev" - } - } -} diff --git a/lib/apereo/phpcas/phpunit.xml.dist b/lib/apereo/phpcas/phpunit.xml.dist deleted file mode 100644 index f0431f153..000000000 --- a/lib/apereo/phpcas/phpunit.xml.dist +++ /dev/null @@ -1,13 +0,0 @@ - - - - - source/ - - - - - test/CAS/Tests/ - - - diff --git a/lib/apereo/phpcas/source/CAS.php b/lib/apereo/phpcas/source/CAS.php deleted file mode 100644 index 8243a83e3..000000000 --- a/lib/apereo/phpcas/source/CAS.php +++ /dev/null @@ -1,2083 +0,0 @@ - - * @author Olivier Berger - * @author Brett Bieber - * @author Joachim Fritschi - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - * @ingroup public - */ - -use Psr\Log\LoggerInterface; - -// -// hack by Vangelis Haniotakis to handle the absence of $_SERVER['REQUEST_URI'] -// in IIS -// -if (!isset($_SERVER['REQUEST_URI']) && isset($_SERVER['SCRIPT_NAME']) && isset($_SERVER['QUERY_STRING'])) { - $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] . '?' . $_SERVER['QUERY_STRING']; -} - - -// ######################################################################## -// CONSTANTS -// ######################################################################## - -// ------------------------------------------------------------------------ -// CAS VERSIONS -// ------------------------------------------------------------------------ - -/** - * phpCAS version. accessible for the user by phpCAS::getVersion(). - */ -define('PHPCAS_VERSION', '1.6.0'); - -/** - * @addtogroup public - * @{ - */ - -/** - * phpCAS supported protocols. accessible for the user by phpCAS::getSupportedProtocols(). - */ - -/** - * CAS version 1.0 - */ -define("CAS_VERSION_1_0", '1.0'); -/*! - * CAS version 2.0 -*/ -define("CAS_VERSION_2_0", '2.0'); -/** - * CAS version 3.0 - */ -define("CAS_VERSION_3_0", '3.0'); - -// ------------------------------------------------------------------------ -// SAML defines -// ------------------------------------------------------------------------ - -/** - * SAML protocol - */ -define("SAML_VERSION_1_1", 'S1'); - -/** - * XML header for SAML POST - */ -define("SAML_XML_HEADER", ''); - -/** - * SOAP envelope for SAML POST - */ -define("SAML_SOAP_ENV", ''); - -/** - * SOAP body for SAML POST - */ -define("SAML_SOAP_BODY", ''); - -/** - * SAMLP request - */ -define("SAMLP_REQUEST", ''); -define("SAMLP_REQUEST_CLOSE", ''); - -/** - * SAMLP artifact tag (for the ticket) - */ -define("SAML_ASSERTION_ARTIFACT", ''); - -/** - * SAMLP close - */ -define("SAML_ASSERTION_ARTIFACT_CLOSE", ''); - -/** - * SOAP body close - */ -define("SAML_SOAP_BODY_CLOSE", ''); - -/** - * SOAP envelope close - */ -define("SAML_SOAP_ENV_CLOSE", ''); - -/** - * SAML Attributes - */ -define("SAML_ATTRIBUTES", 'SAMLATTRIBS'); - -/** @} */ -/** - * @addtogroup publicPGTStorage - * @{ - */ -// ------------------------------------------------------------------------ -// FILE PGT STORAGE -// ------------------------------------------------------------------------ -/** - * Default path used when storing PGT's to file - */ -define("CAS_PGT_STORAGE_FILE_DEFAULT_PATH", session_save_path()); -/** @} */ -// ------------------------------------------------------------------------ -// SERVICE ACCESS ERRORS -// ------------------------------------------------------------------------ -/** - * @addtogroup publicServices - * @{ - */ - -/** - * phpCAS::service() error code on success - */ -define("PHPCAS_SERVICE_OK", 0); -/** - * phpCAS::service() error code when the PT could not retrieve because - * the CAS server did not respond. - */ -define("PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE", 1); -/** - * phpCAS::service() error code when the PT could not retrieve because - * the response of the CAS server was ill-formed. - */ -define("PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE", 2); -/** - * phpCAS::service() error code when the PT could not retrieve because - * the CAS server did not want to. - */ -define("PHPCAS_SERVICE_PT_FAILURE", 3); -/** - * phpCAS::service() error code when the service was not available. - */ -define("PHPCAS_SERVICE_NOT_AVAILABLE", 4); - -// ------------------------------------------------------------------------ -// SERVICE TYPES -// ------------------------------------------------------------------------ -/** - * phpCAS::getProxiedService() type for HTTP GET - */ -define("PHPCAS_PROXIED_SERVICE_HTTP_GET", 'CAS_ProxiedService_Http_Get'); -/** - * phpCAS::getProxiedService() type for HTTP POST - */ -define("PHPCAS_PROXIED_SERVICE_HTTP_POST", 'CAS_ProxiedService_Http_Post'); -/** - * phpCAS::getProxiedService() type for IMAP - */ -define("PHPCAS_PROXIED_SERVICE_IMAP", 'CAS_ProxiedService_Imap'); - - -/** @} */ -// ------------------------------------------------------------------------ -// LANGUAGES -// ------------------------------------------------------------------------ -/** - * @addtogroup publicLang - * @{ - */ - -define("PHPCAS_LANG_ENGLISH", 'CAS_Languages_English'); -define("PHPCAS_LANG_FRENCH", 'CAS_Languages_French'); -define("PHPCAS_LANG_GREEK", 'CAS_Languages_Greek'); -define("PHPCAS_LANG_GERMAN", 'CAS_Languages_German'); -define("PHPCAS_LANG_JAPANESE", 'CAS_Languages_Japanese'); -define("PHPCAS_LANG_SPANISH", 'CAS_Languages_Spanish'); -define("PHPCAS_LANG_CATALAN", 'CAS_Languages_Catalan'); -define("PHPCAS_LANG_CHINESE_SIMPLIFIED", 'CAS_Languages_ChineseSimplified'); -define("PHPCAS_LANG_GALEGO", 'CAS_Languages_Galego'); -define("PHPCAS_LANG_PORTUGUESE", 'CAS_Languages_Portuguese'); - -/** @} */ - -/** - * @addtogroup internalLang - * @{ - */ - -/** - * phpCAS default language (when phpCAS::setLang() is not used) - */ -define("PHPCAS_LANG_DEFAULT", PHPCAS_LANG_ENGLISH); - -/** @} */ -// ------------------------------------------------------------------------ -// DEBUG -// ------------------------------------------------------------------------ -/** - * @addtogroup publicDebug - * @{ - */ - -/** - * The default directory for the debug file under Unix. - * @return string directory for the debug file - */ -function gettmpdir() { -if (!empty($_ENV['TMP'])) { return realpath($_ENV['TMP']); } -if (!empty($_ENV['TMPDIR'])) { return realpath( $_ENV['TMPDIR']); } -if (!empty($_ENV['TEMP'])) { return realpath( $_ENV['TEMP']); } -return "/tmp"; -} -define('DEFAULT_DEBUG_DIR', gettmpdir()."/"); - -/** @} */ - -// include the class autoloader -require_once __DIR__ . '/CAS/Autoload.php'; - -/** - * The phpCAS class is a simple container for the phpCAS library. It provides CAS - * authentication for web applications written in PHP. - * - * @ingroup public - * @class phpCAS - * @category Authentication - * @package PhpCAS - * @author Pascal Aubry - * @author Olivier Berger - * @author Brett Bieber - * @author Joachim Fritschi - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -class phpCAS -{ - - /** - * This variable is used by the interface class phpCAS. - * - * @var CAS_Client - * @hideinitializer - */ - private static $_PHPCAS_CLIENT; - - /** - * @var array - * This variable is used to store where the initializer is called from - * (to print a comprehensive error in case of multiple calls). - * - * @hideinitializer - */ - private static $_PHPCAS_INIT_CALL; - - /** - * @var array - * This variable is used to store phpCAS debug mode. - * - * @hideinitializer - */ - private static $_PHPCAS_DEBUG; - - /** - * This variable is used to enable verbose mode - * This pevents debug info to be show to the user. Since it's a security - * feature the default is false - * - * @hideinitializer - */ - private static $_PHPCAS_VERBOSE = false; - - - // ######################################################################## - // INITIALIZATION - // ######################################################################## - - /** - * @addtogroup publicInit - * @{ - */ - - /** - * phpCAS client initializer. - * - * @param string $server_version the version of the CAS server - * @param string $server_hostname the hostname of the CAS server - * @param int $server_port the port the CAS server is running on - * @param string $server_uri the URI the CAS server is responding on - * @param string|string[]|CAS_ServiceBaseUrl_Interface - * $service_base_url the base URL (protocol, host and the - * optional port) of the CAS client; pass - * in an array to use auto discovery with - * an allowlist; pass in - * CAS_ServiceBaseUrl_Interface for custom - * behavior. Added in 1.6.0. Similar to - * serverName config in other CAS clients. - * @param bool $changeSessionID Allow phpCAS to change the session_id - * (Single Sign Out/handleLogoutRequests - * is based on that change) - * @param \SessionHandlerInterface $sessionHandler the session handler - * - * @return void a newly created CAS_Client object - * @note Only one of the phpCAS::client() and phpCAS::proxy functions should be - * called, only once, and before all other methods (except phpCAS::getVersion() - * and phpCAS::setDebug()). - */ - public static function client($server_version, $server_hostname, - $server_port, $server_uri, $service_base_url, - $changeSessionID = true, \SessionHandlerInterface $sessionHandler = null - ) { - phpCAS :: traceBegin(); - if (is_object(self::$_PHPCAS_CLIENT)) { - phpCAS :: error(self::$_PHPCAS_INIT_CALL['method'] . '() has already been called (at ' . self::$_PHPCAS_INIT_CALL['file'] . ':' . self::$_PHPCAS_INIT_CALL['line'] . ')'); - } - - // store where the initializer is called from - $dbg = debug_backtrace(); - self::$_PHPCAS_INIT_CALL = array ( - 'done' => true, - 'file' => $dbg[0]['file'], - 'line' => $dbg[0]['line'], - 'method' => __CLASS__ . '::' . __FUNCTION__ - ); - - // initialize the object $_PHPCAS_CLIENT - try { - self::$_PHPCAS_CLIENT = new CAS_Client( - $server_version, false, $server_hostname, $server_port, $server_uri, $service_base_url, - $changeSessionID, $sessionHandler - ); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - phpCAS :: traceEnd(); - } - - /** - * phpCAS proxy initializer. - * - * @param string $server_version the version of the CAS server - * @param string $server_hostname the hostname of the CAS server - * @param string $server_port the port the CAS server is running on - * @param string $server_uri the URI the CAS server is responding on - * @param string|string[]|CAS_ServiceBaseUrl_Interface - * $service_base_url the base URL (protocol, host and the - * optional port) of the CAS client; pass - * in an array to use auto discovery with - * an allowlist; pass in - * CAS_ServiceBaseUrl_Interface for custom - * behavior. Added in 1.6.0. Similar to - * serverName config in other CAS clients. - * @param bool $changeSessionID Allow phpCAS to change the session_id - * (Single Sign Out/handleLogoutRequests - * is based on that change) - * @param \SessionHandlerInterface $sessionHandler the session handler - * - * @return void a newly created CAS_Client object - * @note Only one of the phpCAS::client() and phpCAS::proxy functions should be - * called, only once, and before all other methods (except phpCAS::getVersion() - * and phpCAS::setDebug()). - */ - public static function proxy($server_version, $server_hostname, - $server_port, $server_uri, $service_base_url, - $changeSessionID = true, \SessionHandlerInterface $sessionHandler = null - ) { - phpCAS :: traceBegin(); - if (is_object(self::$_PHPCAS_CLIENT)) { - phpCAS :: error(self::$_PHPCAS_INIT_CALL['method'] . '() has already been called (at ' . self::$_PHPCAS_INIT_CALL['file'] . ':' . self::$_PHPCAS_INIT_CALL['line'] . ')'); - } - - // store where the initialzer is called from - $dbg = debug_backtrace(); - self::$_PHPCAS_INIT_CALL = array ( - 'done' => true, - 'file' => $dbg[0]['file'], - 'line' => $dbg[0]['line'], - 'method' => __CLASS__ . '::' . __FUNCTION__ - ); - - // initialize the object $_PHPCAS_CLIENT - try { - self::$_PHPCAS_CLIENT = new CAS_Client( - $server_version, true, $server_hostname, $server_port, $server_uri, $service_base_url, - $changeSessionID, $sessionHandler - ); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - phpCAS :: traceEnd(); - } - - /** - * Answer whether or not the client or proxy has been initialized - * - * @return bool - */ - public static function isInitialized () - { - return (is_object(self::$_PHPCAS_CLIENT)); - } - - /** @} */ - // ######################################################################## - // DEBUGGING - // ######################################################################## - - /** - * @addtogroup publicDebug - * @{ - */ - - /** - * Set/unset PSR-3 logger - * - * @param LoggerInterface $logger the PSR-3 logger used for logging, or - * null to stop logging. - * - * @return void - */ - public static function setLogger($logger = null) - { - if (empty(self::$_PHPCAS_DEBUG['unique_id'])) { - self::$_PHPCAS_DEBUG['unique_id'] = substr(strtoupper(md5(uniqid(''))), 0, 4); - } - self::$_PHPCAS_DEBUG['logger'] = $logger; - self::$_PHPCAS_DEBUG['indent'] = 0; - phpCAS :: trace('START ('.date("Y-m-d H:i:s").') phpCAS-' . PHPCAS_VERSION . ' ******************'); - } - - /** - * Set/unset debug mode - * - * @param string $filename the name of the file used for logging, or false - * to stop debugging. - * - * @return void - * - * @deprecated - */ - public static function setDebug($filename = '') - { - trigger_error('phpCAS::setDebug() is deprecated in favor of phpCAS::setLogger().', E_USER_DEPRECATED); - - if ($filename != false && gettype($filename) != 'string') { - phpCAS :: error('type mismatched for parameter $dbg (should be false or the name of the log file)'); - } - if ($filename === false) { - self::$_PHPCAS_DEBUG['filename'] = false; - - } else { - if (empty ($filename)) { - if (preg_match('/^Win.*/', getenv('OS'))) { - if (isset ($_ENV['TMP'])) { - $debugDir = $_ENV['TMP'] . '/'; - } else { - $debugDir = ''; - } - } else { - $debugDir = DEFAULT_DEBUG_DIR; - } - $filename = $debugDir . 'phpCAS.log'; - } - - if (empty (self::$_PHPCAS_DEBUG['unique_id'])) { - self::$_PHPCAS_DEBUG['unique_id'] = substr(strtoupper(md5(uniqid(''))), 0, 4); - } - - self::$_PHPCAS_DEBUG['filename'] = $filename; - self::$_PHPCAS_DEBUG['indent'] = 0; - - phpCAS :: trace('START ('.date("Y-m-d H:i:s").') phpCAS-' . PHPCAS_VERSION . ' ******************'); - } - } - - /** - * Enable verbose errors messages in the website output - * This is a security relevant since internal status info may leak an may - * help an attacker. Default is therefore false - * - * @param bool $verbose enable verbose output - * - * @return void - */ - public static function setVerbose($verbose) - { - if ($verbose === true) { - self::$_PHPCAS_VERBOSE = true; - } else { - self::$_PHPCAS_VERBOSE = false; - } - } - - - /** - * Show is verbose mode is on - * - * @return bool verbose - */ - public static function getVerbose() - { - return self::$_PHPCAS_VERBOSE; - } - - /** - * Logs a string in debug mode. - * - * @param string $str the string to write - * - * @return void - * @private - */ - public static function log($str) - { - $indent_str = "."; - - - if (isset(self::$_PHPCAS_DEBUG['logger']) || !empty(self::$_PHPCAS_DEBUG['filename'])) { - for ($i = 0; $i < self::$_PHPCAS_DEBUG['indent']; $i++) { - - $indent_str .= '| '; - } - // allow for multiline output with proper identing. Usefull for - // dumping cas answers etc. - $str2 = str_replace("\n", "\n" . self::$_PHPCAS_DEBUG['unique_id'] . ' ' . $indent_str, $str); - $str3 = self::$_PHPCAS_DEBUG['unique_id'] . ' ' . $indent_str . $str2; - if (isset(self::$_PHPCAS_DEBUG['logger'])) { - self::$_PHPCAS_DEBUG['logger']->info($str3); - } - if (!empty(self::$_PHPCAS_DEBUG['filename'])) { - // Check if file exists and modifiy file permissions to be only - // readable by the webserver - if (!file_exists(self::$_PHPCAS_DEBUG['filename'])) { - touch(self::$_PHPCAS_DEBUG['filename']); - // Chmod will fail on windows - @chmod(self::$_PHPCAS_DEBUG['filename'], 0600); - } - error_log($str3 . "\n", 3, self::$_PHPCAS_DEBUG['filename']); - } - } - - } - - /** - * This method is used by interface methods to print an error and where the - * function was originally called from. - * - * @param string $msg the message to print - * - * @return void - * @private - */ - public static function error($msg) - { - phpCAS :: traceBegin(); - $dbg = debug_backtrace(); - $function = '?'; - $file = '?'; - $line = '?'; - if (is_array($dbg)) { - for ($i = 1; $i < sizeof($dbg); $i++) { - if (is_array($dbg[$i]) && isset($dbg[$i]['class']) ) { - if ($dbg[$i]['class'] == __CLASS__) { - $function = $dbg[$i]['function']; - $file = $dbg[$i]['file']; - $line = $dbg[$i]['line']; - } - } - } - } - if (self::$_PHPCAS_VERBOSE) { - echo "
\nphpCAS error: " . __CLASS__ . "::" . $function . '(): ' . htmlentities($msg) . " in " . $file . " on line " . $line . "
\n"; - } - phpCAS :: trace($msg . ' in ' . $file . 'on line ' . $line ); - phpCAS :: traceEnd(); - - throw new CAS_GracefullTerminationException(__CLASS__ . "::" . $function . '(): ' . $msg); - } - - /** - * This method is used to log something in debug mode. - * - * @param string $str string to log - * - * @return void - */ - public static function trace($str) - { - $dbg = debug_backtrace(); - phpCAS :: log($str . ' [' . basename($dbg[0]['file']) . ':' . $dbg[0]['line'] . ']'); - } - - /** - * This method is used to indicate the start of the execution of a function - * in debug mode. - * - * @return void - */ - public static function traceBegin() - { - $dbg = debug_backtrace(); - $str = '=> '; - if (!empty ($dbg[1]['class'])) { - $str .= $dbg[1]['class'] . '::'; - } - $str .= $dbg[1]['function'] . '('; - if (is_array($dbg[1]['args'])) { - foreach ($dbg[1]['args'] as $index => $arg) { - if ($index != 0) { - $str .= ', '; - } - if (is_object($arg)) { - $str .= get_class($arg); - } else { - $str .= str_replace(array("\r\n", "\n", "\r"), "", var_export($arg, true)); - } - } - } - if (isset($dbg[1]['file'])) { - $file = basename($dbg[1]['file']); - } else { - $file = 'unknown_file'; - } - if (isset($dbg[1]['line'])) { - $line = $dbg[1]['line']; - } else { - $line = 'unknown_line'; - } - $str .= ') [' . $file . ':' . $line . ']'; - phpCAS :: log($str); - if (!isset(self::$_PHPCAS_DEBUG['indent'])) { - self::$_PHPCAS_DEBUG['indent'] = 0; - } else { - self::$_PHPCAS_DEBUG['indent']++; - } - } - - /** - * This method is used to indicate the end of the execution of a function in - * debug mode. - * - * @param mixed $res the result of the function - * - * @return void - */ - public static function traceEnd($res = '') - { - if (empty(self::$_PHPCAS_DEBUG['indent'])) { - self::$_PHPCAS_DEBUG['indent'] = 0; - } else { - self::$_PHPCAS_DEBUG['indent']--; - } - $str = ''; - if (is_object($res)) { - $str .= '<= ' . get_class($res); - } else { - $str .= '<= ' . str_replace(array("\r\n", "\n", "\r"), "", var_export($res, true)); - } - - phpCAS :: log($str); - } - - /** - * This method is used to indicate the end of the execution of the program - * - * @return void - */ - public static function traceExit() - { - phpCAS :: log('exit()'); - while (self::$_PHPCAS_DEBUG['indent'] > 0) { - phpCAS :: log('-'); - self::$_PHPCAS_DEBUG['indent']--; - } - } - - /** @} */ - // ######################################################################## - // INTERNATIONALIZATION - // ######################################################################## - /** - * @addtogroup publicLang - * @{ - */ - - /** - * This method is used to set the language used by phpCAS. - * - * @param string $lang string representing the language. - * - * @return void - * - * @sa PHPCAS_LANG_FRENCH, PHPCAS_LANG_ENGLISH - * @note Can be called only once. - */ - public static function setLang($lang) - { - phpCAS::_validateClientExists(); - - try { - self::$_PHPCAS_CLIENT->setLang($lang); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - } - - /** @} */ - // ######################################################################## - // VERSION - // ######################################################################## - /** - * @addtogroup public - * @{ - */ - - /** - * This method returns the phpCAS version. - * - * @return string the phpCAS version. - */ - public static function getVersion() - { - return PHPCAS_VERSION; - } - - /** - * This method returns supported protocols. - * - * @return array an array of all supported protocols. Use internal protocol name as array key. - */ - public static function getSupportedProtocols() - { - $supportedProtocols = array(); - $supportedProtocols[CAS_VERSION_1_0] = 'CAS 1.0'; - $supportedProtocols[CAS_VERSION_2_0] = 'CAS 2.0'; - $supportedProtocols[CAS_VERSION_3_0] = 'CAS 3.0'; - $supportedProtocols[SAML_VERSION_1_1] = 'SAML 1.1'; - - return $supportedProtocols; - } - - /** @} */ - // ######################################################################## - // HTML OUTPUT - // ######################################################################## - /** - * @addtogroup publicOutput - * @{ - */ - - /** - * This method sets the HTML header used for all outputs. - * - * @param string $header the HTML header. - * - * @return void - */ - public static function setHTMLHeader($header) - { - phpCAS::_validateClientExists(); - - try { - self::$_PHPCAS_CLIENT->setHTMLHeader($header); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - } - - /** - * This method sets the HTML footer used for all outputs. - * - * @param string $footer the HTML footer. - * - * @return void - */ - public static function setHTMLFooter($footer) - { - phpCAS::_validateClientExists(); - - try { - self::$_PHPCAS_CLIENT->setHTMLFooter($footer); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - } - - /** @} */ - // ######################################################################## - // PGT STORAGE - // ######################################################################## - /** - * @addtogroup publicPGTStorage - * @{ - */ - - /** - * This method can be used to set a custom PGT storage object. - * - * @param CAS_PGTStorage_AbstractStorage $storage a PGT storage object that inherits from the - * CAS_PGTStorage_AbstractStorage class - * - * @return void - */ - public static function setPGTStorage($storage) - { - phpCAS :: traceBegin(); - phpCAS::_validateProxyExists(); - - try { - self::$_PHPCAS_CLIENT->setPGTStorage($storage); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - phpCAS :: traceEnd(); - } - - /** - * This method is used to tell phpCAS to store the response of the - * CAS server to PGT requests in a database. - * - * @param string $dsn_or_pdo a dsn string to use for creating a PDO - * object or a PDO object - * @param string $username the username to use when connecting to the - * database - * @param string $password the password to use when connecting to the - * database - * @param string $table the table to use for storing and retrieving - * PGT's - * @param string $driver_options any driver options to use when connecting - * to the database - * - * @return void - */ - public static function setPGTStorageDb($dsn_or_pdo, $username='', - $password='', $table='', $driver_options=null - ) { - phpCAS :: traceBegin(); - phpCAS::_validateProxyExists(); - - try { - self::$_PHPCAS_CLIENT->setPGTStorageDb($dsn_or_pdo, $username, $password, $table, $driver_options); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - phpCAS :: traceEnd(); - } - - /** - * This method is used to tell phpCAS to store the response of the - * CAS server to PGT requests onto the filesystem. - * - * @param string $path the path where the PGT's should be stored - * - * @return void - */ - public static function setPGTStorageFile($path = '') - { - phpCAS :: traceBegin(); - phpCAS::_validateProxyExists(); - - try { - self::$_PHPCAS_CLIENT->setPGTStorageFile($path); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - phpCAS :: traceEnd(); - } - /** @} */ - // ######################################################################## - // ACCESS TO EXTERNAL SERVICES - // ######################################################################## - /** - * @addtogroup publicServices - * @{ - */ - - /** - * Answer a proxy-authenticated service handler. - * - * @param string $type The service type. One of - * PHPCAS_PROXIED_SERVICE_HTTP_GET; PHPCAS_PROXIED_SERVICE_HTTP_POST; - * PHPCAS_PROXIED_SERVICE_IMAP - * - * @return CAS_ProxiedService - * @throws InvalidArgumentException If the service type is unknown. - */ - public static function getProxiedService ($type) - { - phpCAS :: traceBegin(); - phpCAS::_validateProxyExists(); - - try { - $res = self::$_PHPCAS_CLIENT->getProxiedService($type); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - - phpCAS :: traceEnd(); - return $res; - } - - /** - * Initialize a proxied-service handler with the proxy-ticket it should use. - * - * @param CAS_ProxiedService $proxiedService Proxied Service Handler - * - * @return void - * @throws CAS_ProxyTicketException If there is a proxy-ticket failure. - * The code of the Exception will be one of: - * PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE - * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE - * PHPCAS_SERVICE_PT_FAILURE - */ - public static function initializeProxiedService (CAS_ProxiedService $proxiedService) - { - phpCAS::_validateProxyExists(); - - try { - self::$_PHPCAS_CLIENT->initializeProxiedService($proxiedService); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - } - - /** - * This method is used to access an HTTP[S] service. - * - * @param string $url the service to access. - * @param int &$err_code an error code Possible values are - * PHPCAS_SERVICE_OK (on success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, - * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE, PHPCAS_SERVICE_PT_FAILURE, - * PHPCAS_SERVICE_NOT_AVAILABLE. - * @param string &$output the output of the service (also used to give an - * error message on failure). - * - * @return bool true on success, false otherwise (in this later case, - * $err_code gives the reason why it failed and $output contains an error - * message). - */ - public static function serviceWeb($url, & $err_code, & $output) - { - phpCAS :: traceBegin(); - phpCAS::_validateProxyExists(); - - try { - $res = self::$_PHPCAS_CLIENT->serviceWeb($url, $err_code, $output); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - - phpCAS :: traceEnd($res); - return $res; - } - - /** - * This method is used to access an IMAP/POP3/NNTP service. - * - * @param string $url a string giving the URL of the service, - * including the mailing box for IMAP URLs, as accepted by imap_open(). - * @param string $service a string giving for CAS retrieve Proxy ticket - * @param string $flags options given to imap_open(). - * @param int &$err_code an error code Possible values are - * PHPCAS_SERVICE_OK (on success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, - * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE, PHPCAS_SERVICE_PT_FAILURE, - * PHPCAS_SERVICE_NOT_AVAILABLE. - * @param string &$err_msg an error message on failure - * @param string &$pt the Proxy Ticket (PT) retrieved from the CAS - * server to access the URL on success, false on error). - * - * @return object|false IMAP stream on success, false otherwise (in this later - * case, $err_code gives the reason why it failed and $err_msg contains an - * error message). - */ - public static function serviceMail($url, $service, $flags, & $err_code, & $err_msg, & $pt) - { - phpCAS :: traceBegin(); - phpCAS::_validateProxyExists(); - - try { - $res = self::$_PHPCAS_CLIENT->serviceMail($url, $service, $flags, $err_code, $err_msg, $pt); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - - phpCAS :: traceEnd($res); - return $res; - } - - /** @} */ - // ######################################################################## - // AUTHENTICATION - // ######################################################################## - /** - * @addtogroup publicAuth - * @{ - */ - - /** - * Set the times authentication will be cached before really accessing the - * CAS server in gateway mode: - * - -1: check only once, and then never again (until you pree login) - * - 0: always check - * - n: check every "n" time - * - * @param int $n an integer. - * - * @return void - */ - public static function setCacheTimesForAuthRecheck($n) - { - phpCAS::_validateClientExists(); - - try { - self::$_PHPCAS_CLIENT->setCacheTimesForAuthRecheck($n); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - } - - - /** - * Set a callback function to be run when receiving CAS attributes - * - * The callback function will be passed an $success_elements - * payload of the response (\DOMElement) as its first parameter. - * - * @param string $function Callback function - * @param array $additionalArgs optional array of arguments - * - * @return void - */ - public static function setCasAttributeParserCallback($function, array $additionalArgs = array()) - { - phpCAS::_validateClientExists(); - - self::$_PHPCAS_CLIENT->setCasAttributeParserCallback($function, $additionalArgs); - } - - /** - * Set a callback function to be run when a user authenticates. - * - * The callback function will be passed a $logoutTicket as its first - * parameter, followed by any $additionalArgs you pass. The $logoutTicket - * parameter is an opaque string that can be used to map the session-id to - * logout request in order to support single-signout in applications that - * manage their own sessions (rather than letting phpCAS start the session). - * - * phpCAS::forceAuthentication() will always exit and forward client unless - * they are already authenticated. To perform an action at the moment the user - * logs in (such as registering an account, performing logging, etc), register - * a callback function here. - * - * @param callable $function Callback function - * @param array $additionalArgs optional array of arguments - * - * @return void - */ - public static function setPostAuthenticateCallback ($function, array $additionalArgs = array()) - { - phpCAS::_validateClientExists(); - - self::$_PHPCAS_CLIENT->setPostAuthenticateCallback($function, $additionalArgs); - } - - /** - * Set a callback function to be run when a single-signout request is - * received. The callback function will be passed a $logoutTicket as its - * first parameter, followed by any $additionalArgs you pass. The - * $logoutTicket parameter is an opaque string that can be used to map a - * session-id to the logout request in order to support single-signout in - * applications that manage their own sessions (rather than letting phpCAS - * start and destroy the session). - * - * @param callable $function Callback function - * @param array $additionalArgs optional array of arguments - * - * @return void - */ - public static function setSingleSignoutCallback ($function, array $additionalArgs = array()) - { - phpCAS::_validateClientExists(); - - self::$_PHPCAS_CLIENT->setSingleSignoutCallback($function, $additionalArgs); - } - - /** - * This method is called to check if the user is already authenticated - * locally or has a global cas session. A already existing cas session is - * determined by a cas gateway call.(cas login call without any interactive - * prompt) - * - * @return bool true when the user is authenticated, false when a previous - * gateway login failed or the function will not return if the user is - * redirected to the cas server for a gateway login attempt - */ - public static function checkAuthentication() - { - phpCAS :: traceBegin(); - phpCAS::_validateClientExists(); - - $auth = self::$_PHPCAS_CLIENT->checkAuthentication(); - - // store where the authentication has been checked and the result - self::$_PHPCAS_CLIENT->markAuthenticationCall($auth); - - phpCAS :: traceEnd($auth); - return $auth; - } - - /** - * This method is called to force authentication if the user was not already - * authenticated. If the user is not authenticated, halt by redirecting to - * the CAS server. - * - * @return bool Authentication - */ - public static function forceAuthentication() - { - phpCAS :: traceBegin(); - phpCAS::_validateClientExists(); - $auth = self::$_PHPCAS_CLIENT->forceAuthentication(); - - // store where the authentication has been checked and the result - self::$_PHPCAS_CLIENT->markAuthenticationCall($auth); - - /* if (!$auth) { - phpCAS :: trace('user is not authenticated, redirecting to the CAS server'); - self::$_PHPCAS_CLIENT->forceAuthentication(); - } else { - phpCAS :: trace('no need to authenticate (user `' . phpCAS :: getUser() . '\' is already authenticated)'); - }*/ - - phpCAS :: traceEnd(); - return $auth; - } - - /** - * This method is called to renew the authentication. - * - * @return void - **/ - public static function renewAuthentication() - { - phpCAS :: traceBegin(); - phpCAS::_validateClientExists(); - - $auth = self::$_PHPCAS_CLIENT->renewAuthentication(); - - // store where the authentication has been checked and the result - self::$_PHPCAS_CLIENT->markAuthenticationCall($auth); - - //self::$_PHPCAS_CLIENT->renewAuthentication(); - phpCAS :: traceEnd(); - } - - /** - * This method is called to check if the user is authenticated (previously or by - * tickets given in the URL). - * - * @return bool true when the user is authenticated. - */ - public static function isAuthenticated() - { - phpCAS :: traceBegin(); - phpCAS::_validateClientExists(); - - // call the isAuthenticated method of the $_PHPCAS_CLIENT object - $auth = self::$_PHPCAS_CLIENT->isAuthenticated(); - - // store where the authentication has been checked and the result - self::$_PHPCAS_CLIENT->markAuthenticationCall($auth); - - phpCAS :: traceEnd($auth); - return $auth; - } - - /** - * Checks whether authenticated based on $_SESSION. Useful to avoid - * server calls. - * - * @return bool true if authenticated, false otherwise. - * @since 0.4.22 by Brendan Arnold - */ - public static function isSessionAuthenticated() - { - phpCAS::_validateClientExists(); - - return (self::$_PHPCAS_CLIENT->isSessionAuthenticated()); - } - - /** - * This method returns the CAS user's login name. - * - * @return string the login name of the authenticated user - * @warning should only be called after phpCAS::forceAuthentication() - * or phpCAS::checkAuthentication(). - * */ - public static function getUser() - { - phpCAS::_validateClientExists(); - - try { - return self::$_PHPCAS_CLIENT->getUser(); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - } - - /** - * Answer attributes about the authenticated user. - * - * @warning should only be called after phpCAS::forceAuthentication() - * or phpCAS::checkAuthentication(). - * - * @return array - */ - public static function getAttributes() - { - phpCAS::_validateClientExists(); - - try { - return self::$_PHPCAS_CLIENT->getAttributes(); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - } - - /** - * Answer true if there are attributes for the authenticated user. - * - * @warning should only be called after phpCAS::forceAuthentication() - * or phpCAS::checkAuthentication(). - * - * @return bool - */ - public static function hasAttributes() - { - phpCAS::_validateClientExists(); - - try { - return self::$_PHPCAS_CLIENT->hasAttributes(); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - } - - /** - * Answer true if an attribute exists for the authenticated user. - * - * @param string $key attribute name - * - * @return bool - * @warning should only be called after phpCAS::forceAuthentication() - * or phpCAS::checkAuthentication(). - */ - public static function hasAttribute($key) - { - phpCAS::_validateClientExists(); - - try { - return self::$_PHPCAS_CLIENT->hasAttribute($key); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - } - - /** - * Answer an attribute for the authenticated user. - * - * @param string $key attribute name - * - * @return mixed string for a single value or an array if multiple values exist. - * @warning should only be called after phpCAS::forceAuthentication() - * or phpCAS::checkAuthentication(). - */ - public static function getAttribute($key) - { - phpCAS::_validateClientExists(); - - try { - return self::$_PHPCAS_CLIENT->getAttribute($key); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - } - - /** - * Handle logout requests. - * - * @param bool $check_client additional safety check - * @param array $allowed_clients array of allowed clients - * - * @return void - */ - public static function handleLogoutRequests($check_client = true, $allowed_clients = array()) - { - phpCAS::_validateClientExists(); - - return (self::$_PHPCAS_CLIENT->handleLogoutRequests($check_client, $allowed_clients)); - } - - /** - * This method returns the URL to be used to login. - * - * @return string the login URL - */ - public static function getServerLoginURL() - { - phpCAS::_validateClientExists(); - - return self::$_PHPCAS_CLIENT->getServerLoginURL(); - } - - /** - * Set the login URL of the CAS server. - * - * @param string $url the login URL - * - * @return void - * @since 0.4.21 by Wyman Chan - */ - public static function setServerLoginURL($url = '') - { - phpCAS :: traceBegin(); - phpCAS::_validateClientExists(); - - try { - self::$_PHPCAS_CLIENT->setServerLoginURL($url); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - - phpCAS :: traceEnd(); - } - - /** - * Set the serviceValidate URL of the CAS server. - * Used for all CAS versions of URL validations. - * Examples: - * CAS 1.0 http://www.exemple.com/validate - * CAS 2.0 http://www.exemple.com/validateURL - * CAS 3.0 http://www.exemple.com/p3/serviceValidate - * - * @param string $url the serviceValidate URL - * - * @return void - */ - public static function setServerServiceValidateURL($url = '') - { - phpCAS :: traceBegin(); - phpCAS::_validateClientExists(); - - try { - self::$_PHPCAS_CLIENT->setServerServiceValidateURL($url); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - - phpCAS :: traceEnd(); - } - - /** - * Set the proxyValidate URL of the CAS server. - * Used for all CAS versions of proxy URL validations - * Examples: - * CAS 1.0 http://www.exemple.com/ - * CAS 2.0 http://www.exemple.com/proxyValidate - * CAS 3.0 http://www.exemple.com/p3/proxyValidate - * - * @param string $url the proxyValidate URL - * - * @return void - */ - public static function setServerProxyValidateURL($url = '') - { - phpCAS :: traceBegin(); - phpCAS::_validateClientExists(); - - try { - self::$_PHPCAS_CLIENT->setServerProxyValidateURL($url); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - - phpCAS :: traceEnd(); - } - - /** - * Set the samlValidate URL of the CAS server. - * - * @param string $url the samlValidate URL - * - * @return void - */ - public static function setServerSamlValidateURL($url = '') - { - phpCAS :: traceBegin(); - phpCAS::_validateClientExists(); - - try { - self::$_PHPCAS_CLIENT->setServerSamlValidateURL($url); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - - phpCAS :: traceEnd(); - } - - /** - * This method returns the URL to be used to logout. - * - * @return string the URL to use to log out - */ - public static function getServerLogoutURL() - { - phpCAS::_validateClientExists(); - - return self::$_PHPCAS_CLIENT->getServerLogoutURL(); - } - - /** - * Set the logout URL of the CAS server. - * - * @param string $url the logout URL - * - * @return void - * @since 0.4.21 by Wyman Chan - */ - public static function setServerLogoutURL($url = '') - { - phpCAS :: traceBegin(); - phpCAS::_validateClientExists(); - - try { - self::$_PHPCAS_CLIENT->setServerLogoutURL($url); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - - phpCAS :: traceEnd(); - } - - /** - * This method is used to logout from CAS. - * - * @param string $params an array that contains the optional url and - * service parameters that will be passed to the CAS server - * - * @return void - */ - public static function logout($params = "") - { - phpCAS :: traceBegin(); - phpCAS::_validateClientExists(); - - $parsedParams = array (); - if ($params != "") { - if (is_string($params)) { - phpCAS :: error('method `phpCAS::logout($url)\' is now deprecated, use `phpCAS::logoutWithUrl($url)\' instead'); - } - if (!is_array($params)) { - phpCAS :: error('type mismatched for parameter $params (should be `array\')'); - } - foreach ($params as $key => $value) { - if ($key != "service" && $key != "url") { - phpCAS :: error('only `url\' and `service\' parameters are allowed for method `phpCAS::logout($params)\''); - } - $parsedParams[$key] = $value; - } - } - self::$_PHPCAS_CLIENT->logout($parsedParams); - // never reached - phpCAS :: traceEnd(); - } - - /** - * This method is used to logout from CAS. Halts by redirecting to the CAS - * server. - * - * @param string $service a URL that will be transmitted to the CAS server - * - * @return void - */ - public static function logoutWithRedirectService($service) - { - phpCAS :: traceBegin(); - phpCAS::_validateClientExists(); - - if (!is_string($service)) { - phpCAS :: error('type mismatched for parameter $service (should be `string\')'); - } - self::$_PHPCAS_CLIENT->logout(array ( "service" => $service )); - // never reached - phpCAS :: traceEnd(); - } - - /** - * This method is used to logout from CAS. Halts by redirecting to the CAS - * server. - * - * @param string $url a URL that will be transmitted to the CAS server - * - * @return void - * @deprecated The url parameter has been removed from the CAS server as of - * version 3.3.5.1 - */ - public static function logoutWithUrl($url) - { - trigger_error('Function deprecated for cas servers >= 3.3.5.1', E_USER_DEPRECATED); - phpCAS :: traceBegin(); - if (!is_object(self::$_PHPCAS_CLIENT)) { - phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()'); - } - if (!is_string($url)) { - phpCAS :: error('type mismatched for parameter $url (should be `string\')'); - } - self::$_PHPCAS_CLIENT->logout(array ( "url" => $url )); - // never reached - phpCAS :: traceEnd(); - } - - /** - * This method is used to logout from CAS. Halts by redirecting to the CAS - * server. - * - * @param string $service a URL that will be transmitted to the CAS server - * @param string $url a URL that will be transmitted to the CAS server - * - * @return void - * - * @deprecated The url parameter has been removed from the CAS server as of - * version 3.3.5.1 - */ - public static function logoutWithRedirectServiceAndUrl($service, $url) - { - trigger_error('Function deprecated for cas servers >= 3.3.5.1', E_USER_DEPRECATED); - phpCAS :: traceBegin(); - phpCAS::_validateClientExists(); - - if (!is_string($service)) { - phpCAS :: error('type mismatched for parameter $service (should be `string\')'); - } - if (!is_string($url)) { - phpCAS :: error('type mismatched for parameter $url (should be `string\')'); - } - self::$_PHPCAS_CLIENT->logout( - array ( - "service" => $service, - "url" => $url - ) - ); - // never reached - phpCAS :: traceEnd(); - } - - /** - * Set the fixed URL that will be used by the CAS server to transmit the - * PGT. When this method is not called, a phpCAS script uses its own URL - * for the callback. - * - * @param string $url the URL - * - * @return void - */ - public static function setFixedCallbackURL($url = '') - { - phpCAS :: traceBegin(); - phpCAS::_validateProxyExists(); - - try { - self::$_PHPCAS_CLIENT->setCallbackURL($url); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - - phpCAS :: traceEnd(); - } - - /** - * Set the fixed URL that will be set as the CAS service parameter. When this - * method is not called, a phpCAS script uses its own URL. - * - * @param string $url the URL - * - * @return void - */ - public static function setFixedServiceURL($url) - { - phpCAS :: traceBegin(); - phpCAS::_validateProxyExists(); - - try { - self::$_PHPCAS_CLIENT->setURL($url); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - - phpCAS :: traceEnd(); - } - - /** - * Get the URL that is set as the CAS service parameter. - * - * @return string Service Url - */ - public static function getServiceURL() - { - phpCAS::_validateProxyExists(); - return (self::$_PHPCAS_CLIENT->getURL()); - } - - /** - * Retrieve a Proxy Ticket from the CAS server. - * - * @param string $target_service Url string of service to proxy - * @param int &$err_code error code - * @param string &$err_msg error message - * - * @return string Proxy Ticket - */ - public static function retrievePT($target_service, & $err_code, & $err_msg) - { - phpCAS::_validateProxyExists(); - - try { - return (self::$_PHPCAS_CLIENT->retrievePT($target_service, $err_code, $err_msg)); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - } - - /** - * Set the certificate of the CAS server CA and if the CN should be properly - * verified. - * - * @param string $cert CA certificate file name - * @param bool $validate_cn Validate CN in certificate (default true) - * - * @return void - */ - public static function setCasServerCACert($cert, $validate_cn = true) - { - phpCAS :: traceBegin(); - phpCAS::_validateClientExists(); - - try { - self::$_PHPCAS_CLIENT->setCasServerCACert($cert, $validate_cn); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - - phpCAS :: traceEnd(); - } - - /** - * Set no SSL validation for the CAS server. - * - * @return void - */ - public static function setNoCasServerValidation() - { - phpCAS :: traceBegin(); - phpCAS::_validateClientExists(); - - phpCAS :: trace('You have configured no validation of the legitimacy of the cas server. This is not recommended for production use.'); - self::$_PHPCAS_CLIENT->setNoCasServerValidation(); - phpCAS :: traceEnd(); - } - - - /** - * Disable the removal of a CAS-Ticket from the URL when authenticating - * DISABLING POSES A SECURITY RISK: - * We normally remove the ticket by an additional redirect as a security - * precaution to prevent a ticket in the HTTP_REFERRER or be carried over in - * the URL parameter - * - * @return void - */ - public static function setNoClearTicketsFromUrl() - { - phpCAS :: traceBegin(); - phpCAS::_validateClientExists(); - - self::$_PHPCAS_CLIENT->setNoClearTicketsFromUrl(); - phpCAS :: traceEnd(); - } - - /** @} */ - - /** - * Change CURL options. - * CURL is used to connect through HTTPS to CAS server - * - * @param string $key the option key - * @param string $value the value to set - * - * @return void - */ - public static function setExtraCurlOption($key, $value) - { - phpCAS :: traceBegin(); - phpCAS::_validateClientExists(); - - self::$_PHPCAS_CLIENT->setExtraCurlOption($key, $value); - phpCAS :: traceEnd(); - } - - /** - * Set a salt/seed for the session-id hash to make it harder to guess. - * - * When $changeSessionID = true phpCAS will create a session-id that is derived - * from the service ticket. Doing so allows phpCAS to look-up and destroy the - * proper session on single-log-out requests. While the service tickets - * provided by the CAS server may include enough data to generate a strong - * hash, clients may provide an additional salt to ensure that session ids - * are not guessable if the session tickets do not have enough entropy. - * - * @param string $salt The salt to combine with the session ticket. - * - * @return void - */ - public static function setSessionIdSalt($salt) { - phpCAS :: traceBegin(); - phpCAS::_validateClientExists(); - self::$_PHPCAS_CLIENT->setSessionIdSalt($salt); - phpCAS :: traceEnd(); - } - - /** - * If you want your service to be proxied you have to enable it (default - * disabled) and define an accepable list of proxies that are allowed to - * proxy your service. - * - * Add each allowed proxy definition object. For the normal CAS_ProxyChain - * class, the constructor takes an array of proxies to match. The list is in - * reverse just as seen from the service. Proxies have to be defined in reverse - * from the service to the user. If a user hits service A and gets proxied via - * B to service C the list of acceptable on C would be array(B,A). The definition - * of an individual proxy can be either a string or a regexp (preg_match is used) - * that will be matched against the proxy list supplied by the cas server - * when validating the proxy tickets. The strings are compared starting from - * the beginning and must fully match with the proxies in the list. - * Example: - * phpCAS::allowProxyChain(new CAS_ProxyChain(array( - * 'https://app.example.com/' - * ))); - * phpCAS::allowProxyChain(new CAS_ProxyChain(array( - * '/^https:\/\/app[0-9]\.example\.com\/rest\//', - * 'http://client.example.com/' - * ))); - * - * For quick testing or in certain production screnarios you might want to - * allow allow any other valid service to proxy your service. To do so, add - * the "Any" chain: - * phpCAS::allowProxyChain(new CAS_ProxyChain_Any); - * THIS SETTING IS HOWEVER NOT RECOMMENDED FOR PRODUCTION AND HAS SECURITY - * IMPLICATIONS: YOU ARE ALLOWING ANY SERVICE TO ACT ON BEHALF OF A USER - * ON THIS SERVICE. - * - * @param CAS_ProxyChain_Interface $proxy_chain A proxy-chain that will be - * matched against the proxies requesting access - * - * @return void - */ - public static function allowProxyChain(CAS_ProxyChain_Interface $proxy_chain) - { - phpCAS :: traceBegin(); - phpCAS::_validateClientExists(); - - if (self::$_PHPCAS_CLIENT->getServerVersion() !== CAS_VERSION_2_0 - && self::$_PHPCAS_CLIENT->getServerVersion() !== CAS_VERSION_3_0 - ) { - phpCAS :: error('this method can only be used with the cas 2.0/3.0 protocols'); - } - self::$_PHPCAS_CLIENT->getAllowedProxyChains()->allowProxyChain($proxy_chain); - phpCAS :: traceEnd(); - } - - /** - * Answer an array of proxies that are sitting in front of this application. - * This method will only return a non-empty array if we have received and - * validated a Proxy Ticket. - * - * @return array - * @access public - * @since 6/25/09 - */ - public static function getProxies () - { - phpCAS::_validateProxyExists(); - - return(self::$_PHPCAS_CLIENT->getProxies()); - } - - // ######################################################################## - // PGTIOU/PGTID and logoutRequest rebroadcasting - // ######################################################################## - - /** - * Add a pgtIou/pgtId and logoutRequest rebroadcast node. - * - * @param string $rebroadcastNodeUrl The rebroadcast node URL. Can be - * hostname or IP. - * - * @return void - */ - public static function addRebroadcastNode($rebroadcastNodeUrl) - { - phpCAS::traceBegin(); - phpCAS::log('rebroadcastNodeUrl:'.$rebroadcastNodeUrl); - phpCAS::_validateClientExists(); - - try { - self::$_PHPCAS_CLIENT->addRebroadcastNode($rebroadcastNodeUrl); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - - phpCAS::traceEnd(); - } - - /** - * This method is used to add header parameters when rebroadcasting - * pgtIou/pgtId or logoutRequest. - * - * @param String $header Header to send when rebroadcasting. - * - * @return void - */ - public static function addRebroadcastHeader($header) - { - phpCAS :: traceBegin(); - phpCAS::_validateClientExists(); - - try { - self::$_PHPCAS_CLIENT->addRebroadcastHeader($header); - } catch (Exception $e) { - phpCAS :: error(get_class($e) . ': ' . $e->getMessage()); - } - - phpCAS :: traceEnd(); - } - - /** - * Checks if a client already exists - * - * @throws CAS_OutOfSequenceBeforeClientException - * - * @return void - */ - private static function _validateClientExists() - { - if (!is_object(self::$_PHPCAS_CLIENT)) { - throw new CAS_OutOfSequenceBeforeClientException(); - } - } - - /** - * Checks of a proxy client aready exists - * - * @throws CAS_OutOfSequenceBeforeProxyException - * - * @return void - */ - private static function _validateProxyExists() - { - if (!is_object(self::$_PHPCAS_CLIENT)) { - throw new CAS_OutOfSequenceBeforeProxyException(); - } - } - - /** - * @return CAS_Client - */ - public static function getCasClient() - { - return self::$_PHPCAS_CLIENT; - } - - /** - * For testing purposes, use this method to set the client to a test double - * - * @return void - */ - public static function setCasClient(\CAS_Client $client) - { - self::$_PHPCAS_CLIENT = $client; - } -} -// ######################################################################## -// DOCUMENTATION -// ######################################################################## - -// ######################################################################## -// MAIN PAGE - -/** - * @mainpage - * - * The following pages only show the source documentation. - * - */ - -// ######################################################################## -// MODULES DEFINITION - -/** @defgroup public User interface */ - -/** @defgroup publicInit Initialization - * @ingroup public */ - -/** @defgroup publicAuth Authentication - * @ingroup public */ - -/** @defgroup publicServices Access to external services - * @ingroup public */ - -/** @defgroup publicConfig Configuration - * @ingroup public */ - -/** @defgroup publicLang Internationalization - * @ingroup publicConfig */ - -/** @defgroup publicOutput HTML output - * @ingroup publicConfig */ - -/** @defgroup publicPGTStorage PGT storage - * @ingroup publicConfig */ - -/** @defgroup publicDebug Debugging - * @ingroup public */ - -/** @defgroup internal Implementation */ - -/** @defgroup internalAuthentication Authentication - * @ingroup internal */ - -/** @defgroup internalBasic CAS Basic client features (CAS 1.0, Service Tickets) - * @ingroup internal */ - -/** @defgroup internalProxy CAS Proxy features (CAS 2.0, Proxy Granting Tickets) - * @ingroup internal */ - -/** @defgroup internalSAML CAS SAML features (SAML 1.1) - * @ingroup internal */ - -/** @defgroup internalPGTStorage PGT storage - * @ingroup internalProxy */ - -/** @defgroup internalPGTStorageDb PGT storage in a database - * @ingroup internalPGTStorage */ - -/** @defgroup internalPGTStorageFile PGT storage on the filesystem - * @ingroup internalPGTStorage */ - -/** @defgroup internalCallback Callback from the CAS server - * @ingroup internalProxy */ - -/** @defgroup internalProxyServices Proxy other services - * @ingroup internalProxy */ - -/** @defgroup internalService CAS client features (CAS 2.0, Proxied service) - * @ingroup internal */ - -/** @defgroup internalConfig Configuration - * @ingroup internal */ - -/** @defgroup internalBehave Internal behaviour of phpCAS - * @ingroup internalConfig */ - -/** @defgroup internalOutput HTML output - * @ingroup internalConfig */ - -/** @defgroup internalLang Internationalization - * @ingroup internalConfig - * - * To add a new language: - * - 1. define a new constant PHPCAS_LANG_XXXXXX in CAS/CAS.php - * - 2. copy any file from CAS/languages to CAS/languages/XXXXXX.php - * - 3. Make the translations - */ - -/** @defgroup internalDebug Debugging - * @ingroup internal */ - -/** @defgroup internalMisc Miscellaneous - * @ingroup internal */ - -// ######################################################################## -// EXAMPLES - -/** - * @example example_simple.php - */ -/** - * @example example_service.php - */ -/** - * @example example_service_that_proxies.php - */ -/** - * @example example_service_POST.php - */ -/** - * @example example_proxy_serviceWeb.php - */ -/** - * @example example_proxy_serviceWeb_chaining.php - */ -/** - * @example example_proxy_POST.php - */ -/** - * @example example_proxy_GET.php - */ -/** - * @example example_lang.php - */ -/** - * @example example_html.php - */ -/** - * @example example_pgt_storage_file.php - */ -/** - * @example example_pgt_storage_db.php - */ -/** - * @example example_gateway.php - */ -/** - * @example example_logout.php - */ -/** - * @example example_rebroadcast.php - */ -/** - * @example example_custom_urls.php - */ -/** - * @example example_advanced_saml11.php - */ diff --git a/lib/apereo/phpcas/source/CAS/AuthenticationException.php b/lib/apereo/phpcas/source/CAS/AuthenticationException.php deleted file mode 100644 index 803c88908..000000000 --- a/lib/apereo/phpcas/source/CAS/AuthenticationException.php +++ /dev/null @@ -1,115 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * This interface defines methods that allow proxy-authenticated service handlers - * to interact with phpCAS. - * - * Proxy service handlers must implement this interface as well as call - * phpCAS::initializeProxiedService($this) at some point in their implementation. - * - * While not required, proxy-authenticated service handlers are encouraged to - * implement the CAS_ProxiedService_Testable interface to facilitate unit testing. - * - * @class CAS_AuthenticationException - * @category Authentication - * @package PhpCAS - * @author Joachim Fritschi - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -class CAS_AuthenticationException -extends RuntimeException -implements CAS_Exception -{ - - /** - * This method is used to print the HTML output when the user was not - * authenticated. - * - * @param CAS_Client $client phpcas client - * @param string $failure the failure that occured - * @param string $cas_url the URL the CAS server was asked for - * @param bool $no_response the response from the CAS server (other - * parameters are ignored if TRUE) - * @param bool $bad_response bad response from the CAS server ($err_code - * and $err_msg ignored if TRUE) - * @param string $cas_response the response of the CAS server - * @param int $err_code the error code given by the CAS server - * @param string $err_msg the error message given by the CAS server - */ - public function __construct($client,$failure,$cas_url,$no_response, - $bad_response=false,$cas_response='',$err_code=-1,$err_msg='' - ) { - $messages = array(); - phpCAS::traceBegin(); - $lang = $client->getLangObj(); - $client->printHTMLHeader($lang->getAuthenticationFailed()); - - if (phpCAS::getVerbose()) { - printf( - $lang->getYouWereNotAuthenticated(), - htmlentities($client->getURL()), - $_SERVER['SERVER_ADMIN'] ?? '' - ); - } - - phpCAS::trace($messages[] = 'CAS URL: '.$cas_url); - phpCAS::trace($messages[] = 'Authentication failure: '.$failure); - if ( $no_response ) { - phpCAS::trace($messages[] = 'Reason: no response from the CAS server'); - } else { - if ( $bad_response ) { - phpCAS::trace($messages[] = 'Reason: bad response from the CAS server'); - } else { - switch ($client->getServerVersion()) { - case CAS_VERSION_1_0: - phpCAS::trace($messages[] = 'Reason: CAS error'); - break; - case CAS_VERSION_2_0: - case CAS_VERSION_3_0: - if ( $err_code === -1 ) { - phpCAS::trace($messages[] = 'Reason: no CAS error'); - } else { - phpCAS::trace($messages[] = 'Reason: ['.$err_code.'] CAS error: '.$err_msg); - } - break; - } - } - phpCAS::trace($messages[] = 'CAS response: '.$cas_response); - } - $client->printHTMLFooter(); - phpCAS::traceExit(); - - parent::__construct(implode("\n", $messages)); - } - -} -?> diff --git a/lib/apereo/phpcas/source/CAS/Autoload.php b/lib/apereo/phpcas/source/CAS/Autoload.php deleted file mode 100644 index 29395d592..000000000 --- a/lib/apereo/phpcas/source/CAS/Autoload.php +++ /dev/null @@ -1,95 +0,0 @@ - - * @copyright 2008 Regents of the University of Nebraska - * @license http://www1.unl.edu/wdn/wiki/Software_License BSD License - * @link http://code.google.com/p/simplecas/ - **/ - -/** - * Autoload a class - * - * @param string $class Classname to load - * - * @return bool - */ -function CAS_autoload($class) -{ - // Static to hold the Include Path to CAS - static $include_path; - // Check only for CAS classes - if (substr($class, 0, 4) !== 'CAS_' && substr($class, 0, 7) !== 'PhpCas\\') { - return false; - } - - // Setup the include path if it's not already set from a previous call - if (empty($include_path)) { - $include_path = array(dirname(__DIR__)); - } - - // Declare local variable to store the expected full path to the file - foreach ($include_path as $path) { - $class_path = str_replace('_', DIRECTORY_SEPARATOR, $class); - // PhpCas namespace mapping - if (substr($class_path, 0, 7) === 'PhpCas\\') { - $class_path = 'CAS' . DIRECTORY_SEPARATOR . substr($class_path, 7); - } - - $file_path = $path . DIRECTORY_SEPARATOR . $class_path . '.php'; - $fp = @fopen($file_path, 'r', true); - if ($fp) { - fclose($fp); - include $file_path; - if (!class_exists($class, false) && !interface_exists($class, false)) { - die( - new Exception( - 'Class ' . $class . ' was not present in ' . - $file_path . - ' [CAS_autoload]' - ) - ); - } - return true; - } - } - - $e = new Exception( - 'Class ' . $class . ' could not be loaded from ' . - $file_path . ', file does not exist (Path="' - . implode(':', $include_path) .'") [CAS_autoload]' - ); - $trace = $e->getTrace(); - if (isset($trace[2]) && isset($trace[2]['function']) - && in_array($trace[2]['function'], array('class_exists', 'interface_exists', 'trait_exists')) - ) { - return false; - } - if (isset($trace[1]) && isset($trace[1]['function']) - && in_array($trace[1]['function'], array('class_exists', 'interface_exists', 'trait_exists')) - ) { - return false; - } - die ((string) $e); -} - -// Set up autoload if not already configured by composer. -if (!class_exists('CAS_Client')) -{ - trigger_error('phpCAS autoloader is deprecated. Install phpCAS using composer instead.', E_USER_DEPRECATED); - spl_autoload_register('CAS_autoload'); - if (function_exists('__autoload') - && !in_array('__autoload', spl_autoload_functions()) - ) { - // __autoload() was being used, but now would be ignored, add - // it to the autoload stack - spl_autoload_register('__autoload'); - } -} diff --git a/lib/apereo/phpcas/source/CAS/Client.php b/lib/apereo/phpcas/source/CAS/Client.php deleted file mode 100644 index 91642ee52..000000000 --- a/lib/apereo/phpcas/source/CAS/Client.php +++ /dev/null @@ -1,4380 +0,0 @@ - - * @author Olivier Berger - * @author Brett Bieber - * @author Joachim Fritschi - * @author Adam Franco - * @author Tobias Schiebeck - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * The CAS_Client class is a client interface that provides CAS authentication - * to PHP applications. - * - * @class CAS_Client - * @category Authentication - * @package PhpCAS - * @author Pascal Aubry - * @author Olivier Berger - * @author Brett Bieber - * @author Joachim Fritschi - * @author Adam Franco - * @author Tobias Schiebeck - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - * - */ - -class CAS_Client -{ - - // ######################################################################## - // HTML OUTPUT - // ######################################################################## - /** - * @addtogroup internalOutput - * @{ - */ - - /** - * This method filters a string by replacing special tokens by appropriate values - * and prints it. The corresponding tokens are taken into account: - * - __CAS_VERSION__ - * - __PHPCAS_VERSION__ - * - __SERVER_BASE_URL__ - * - * Used by CAS_Client::PrintHTMLHeader() and CAS_Client::printHTMLFooter(). - * - * @param string $str the string to filter and output - * - * @return void - */ - private function _htmlFilterOutput($str) - { - $str = str_replace('__CAS_VERSION__', $this->getServerVersion(), $str); - $str = str_replace('__PHPCAS_VERSION__', phpCAS::getVersion(), $str); - $str = str_replace('__SERVER_BASE_URL__', $this->_getServerBaseURL(), $str); - echo $str; - } - - /** - * A string used to print the header of HTML pages. Written by - * CAS_Client::setHTMLHeader(), read by CAS_Client::printHTMLHeader(). - * - * @hideinitializer - * @see CAS_Client::setHTMLHeader, CAS_Client::printHTMLHeader() - */ - private $_output_header = ''; - - /** - * This method prints the header of the HTML output (after filtering). If - * CAS_Client::setHTMLHeader() was not used, a default header is output. - * - * @param string $title the title of the page - * - * @return void - * @see _htmlFilterOutput() - */ - public function printHTMLHeader($title) - { - if (!phpCAS::getVerbose()) { - return; - } - - $this->_htmlFilterOutput( - str_replace( - '__TITLE__', $title, - (empty($this->_output_header) - ? '__TITLE__

__TITLE__

' - : $this->_output_header) - ) - ); - } - - /** - * A string used to print the footer of HTML pages. Written by - * CAS_Client::setHTMLFooter(), read by printHTMLFooter(). - * - * @hideinitializer - * @see CAS_Client::setHTMLFooter, CAS_Client::printHTMLFooter() - */ - private $_output_footer = ''; - - /** - * This method prints the footer of the HTML output (after filtering). If - * CAS_Client::setHTMLFooter() was not used, a default footer is output. - * - * @return void - * @see _htmlFilterOutput() - */ - public function printHTMLFooter() - { - if (!phpCAS::getVerbose()) { - return; - } - - $lang = $this->getLangObj(); - $message = empty($this->_output_footer) - ? '
phpCAS __PHPCAS_VERSION__ ' . $lang->getUsingServer() . - ' __SERVER_BASE_URL__ (CAS __CAS_VERSION__)
' - : $this->_output_footer; - - $this->_htmlFilterOutput($message); - } - - /** - * This method set the HTML header used for all outputs. - * - * @param string $header the HTML header. - * - * @return void - */ - public function setHTMLHeader($header) - { - // Argument Validation - if (gettype($header) != 'string') - throw new CAS_TypeMismatchException($header, '$header', 'string'); - - $this->_output_header = $header; - } - - /** - * This method set the HTML footer used for all outputs. - * - * @param string $footer the HTML footer. - * - * @return void - */ - public function setHTMLFooter($footer) - { - // Argument Validation - if (gettype($footer) != 'string') - throw new CAS_TypeMismatchException($footer, '$footer', 'string'); - - $this->_output_footer = $footer; - } - - /** - * Simple wrapper for printf function, that respects - * phpCAS verbosity setting. - * - * @param string $format - * @param string|int|float ...$values - * - * @see printf() - */ - private function printf(string $format, ...$values): void - { - if (phpCAS::getVerbose()) { - printf($format, ...$values); - } - } - - /** @} */ - - - // ######################################################################## - // INTERNATIONALIZATION - // ######################################################################## - /** - * @addtogroup internalLang - * @{ - */ - /** - * A string corresponding to the language used by phpCAS. Written by - * CAS_Client::setLang(), read by CAS_Client::getLang(). - - * @note debugging information is always in english (debug purposes only). - */ - private $_lang = PHPCAS_LANG_DEFAULT; - - /** - * This method is used to set the language used by phpCAS. - * - * @param string $lang representing the language. - * - * @return void - */ - public function setLang($lang) - { - // Argument Validation - if (gettype($lang) != 'string') - throw new CAS_TypeMismatchException($lang, '$lang', 'string'); - - phpCAS::traceBegin(); - $obj = new $lang(); - if (!($obj instanceof CAS_Languages_LanguageInterface)) { - throw new CAS_InvalidArgumentException( - '$className must implement the CAS_Languages_LanguageInterface' - ); - } - $this->_lang = $lang; - phpCAS::traceEnd(); - } - /** - * Create the language - * - * @return CAS_Languages_LanguageInterface object implementing the class - */ - public function getLangObj() - { - $classname = $this->_lang; - return new $classname(); - } - - /** @} */ - // ######################################################################## - // CAS SERVER CONFIG - // ######################################################################## - /** - * @addtogroup internalConfig - * @{ - */ - - /** - * a record to store information about the CAS server. - * - $_server['version']: the version of the CAS server - * - $_server['hostname']: the hostname of the CAS server - * - $_server['port']: the port the CAS server is running on - * - $_server['uri']: the base URI the CAS server is responding on - * - $_server['base_url']: the base URL of the CAS server - * - $_server['login_url']: the login URL of the CAS server - * - $_server['service_validate_url']: the service validating URL of the - * CAS server - * - $_server['proxy_url']: the proxy URL of the CAS server - * - $_server['proxy_validate_url']: the proxy validating URL of the CAS server - * - $_server['logout_url']: the logout URL of the CAS server - * - * $_server['version'], $_server['hostname'], $_server['port'] and - * $_server['uri'] are written by CAS_Client::CAS_Client(), read by - * CAS_Client::getServerVersion(), CAS_Client::_getServerHostname(), - * CAS_Client::_getServerPort() and CAS_Client::_getServerURI(). - * - * The other fields are written and read by CAS_Client::_getServerBaseURL(), - * CAS_Client::getServerLoginURL(), CAS_Client::getServerServiceValidateURL(), - * CAS_Client::getServerProxyValidateURL() and CAS_Client::getServerLogoutURL(). - * - * @hideinitializer - */ - private $_server = array( - 'version' => '', - 'hostname' => 'none', - 'port' => -1, - 'uri' => 'none'); - - /** - * This method is used to retrieve the version of the CAS server. - * - * @return string the version of the CAS server. - */ - public function getServerVersion() - { - return $this->_server['version']; - } - - /** - * This method is used to retrieve the hostname of the CAS server. - * - * @return string the hostname of the CAS server. - */ - private function _getServerHostname() - { - return $this->_server['hostname']; - } - - /** - * This method is used to retrieve the port of the CAS server. - * - * @return int the port of the CAS server. - */ - private function _getServerPort() - { - return $this->_server['port']; - } - - /** - * This method is used to retrieve the URI of the CAS server. - * - * @return string a URI. - */ - private function _getServerURI() - { - return $this->_server['uri']; - } - - /** - * This method is used to retrieve the base URL of the CAS server. - * - * @return string a URL. - */ - private function _getServerBaseURL() - { - // the URL is build only when needed - if ( empty($this->_server['base_url']) ) { - $this->_server['base_url'] = 'https://' . $this->_getServerHostname(); - if ($this->_getServerPort()!=443) { - $this->_server['base_url'] .= ':' - .$this->_getServerPort(); - } - $this->_server['base_url'] .= $this->_getServerURI(); - } - return $this->_server['base_url']; - } - - /** - * This method is used to retrieve the login URL of the CAS server. - * - * @param bool $gateway true to check authentication, false to force it - * @param bool $renew true to force the authentication with the CAS server - * - * @return string a URL. - * @note It is recommended that CAS implementations ignore the "gateway" - * parameter if "renew" is set - */ - public function getServerLoginURL($gateway=false,$renew=false) - { - phpCAS::traceBegin(); - // the URL is build only when needed - if ( empty($this->_server['login_url']) ) { - $this->_server['login_url'] = $this->_buildQueryUrl($this->_getServerBaseURL().'login','service='.urlencode($this->getURL())); - } - $url = $this->_server['login_url']; - if ($renew) { - // It is recommended that when the "renew" parameter is set, its - // value be "true" - $url = $this->_buildQueryUrl($url, 'renew=true'); - } elseif ($gateway) { - // It is recommended that when the "gateway" parameter is set, its - // value be "true" - $url = $this->_buildQueryUrl($url, 'gateway=true'); - } - phpCAS::traceEnd($url); - return $url; - } - - /** - * This method sets the login URL of the CAS server. - * - * @param string $url the login URL - * - * @return string login url - */ - public function setServerLoginURL($url) - { - // Argument Validation - if (gettype($url) != 'string') - throw new CAS_TypeMismatchException($url, '$url', 'string'); - - return $this->_server['login_url'] = $url; - } - - - /** - * This method sets the serviceValidate URL of the CAS server. - * - * @param string $url the serviceValidate URL - * - * @return string serviceValidate URL - */ - public function setServerServiceValidateURL($url) - { - // Argument Validation - if (gettype($url) != 'string') - throw new CAS_TypeMismatchException($url, '$url', 'string'); - - return $this->_server['service_validate_url'] = $url; - } - - - /** - * This method sets the proxyValidate URL of the CAS server. - * - * @param string $url the proxyValidate URL - * - * @return string proxyValidate URL - */ - public function setServerProxyValidateURL($url) - { - // Argument Validation - if (gettype($url) != 'string') - throw new CAS_TypeMismatchException($url, '$url', 'string'); - - return $this->_server['proxy_validate_url'] = $url; - } - - - /** - * This method sets the samlValidate URL of the CAS server. - * - * @param string $url the samlValidate URL - * - * @return string samlValidate URL - */ - public function setServerSamlValidateURL($url) - { - // Argument Validation - if (gettype($url) != 'string') - throw new CAS_TypeMismatchException($url, '$url', 'string'); - - return $this->_server['saml_validate_url'] = $url; - } - - - /** - * This method is used to retrieve the service validating URL of the CAS server. - * - * @return string serviceValidate URL. - */ - public function getServerServiceValidateURL() - { - phpCAS::traceBegin(); - // the URL is build only when needed - if ( empty($this->_server['service_validate_url']) ) { - switch ($this->getServerVersion()) { - case CAS_VERSION_1_0: - $this->_server['service_validate_url'] = $this->_getServerBaseURL() - .'validate'; - break; - case CAS_VERSION_2_0: - $this->_server['service_validate_url'] = $this->_getServerBaseURL() - .'serviceValidate'; - break; - case CAS_VERSION_3_0: - $this->_server['service_validate_url'] = $this->_getServerBaseURL() - .'p3/serviceValidate'; - break; - } - } - $url = $this->_buildQueryUrl( - $this->_server['service_validate_url'], - 'service='.urlencode($this->getURL()) - ); - phpCAS::traceEnd($url); - return $url; - } - /** - * This method is used to retrieve the SAML validating URL of the CAS server. - * - * @return string samlValidate URL. - */ - public function getServerSamlValidateURL() - { - phpCAS::traceBegin(); - // the URL is build only when needed - if ( empty($this->_server['saml_validate_url']) ) { - switch ($this->getServerVersion()) { - case SAML_VERSION_1_1: - $this->_server['saml_validate_url'] = $this->_getServerBaseURL().'samlValidate'; - break; - } - } - - $url = $this->_buildQueryUrl( - $this->_server['saml_validate_url'], - 'TARGET='.urlencode($this->getURL()) - ); - phpCAS::traceEnd($url); - return $url; - } - - /** - * This method is used to retrieve the proxy validating URL of the CAS server. - * - * @return string proxyValidate URL. - */ - public function getServerProxyValidateURL() - { - phpCAS::traceBegin(); - // the URL is build only when needed - if ( empty($this->_server['proxy_validate_url']) ) { - switch ($this->getServerVersion()) { - case CAS_VERSION_1_0: - $this->_server['proxy_validate_url'] = ''; - break; - case CAS_VERSION_2_0: - $this->_server['proxy_validate_url'] = $this->_getServerBaseURL().'proxyValidate'; - break; - case CAS_VERSION_3_0: - $this->_server['proxy_validate_url'] = $this->_getServerBaseURL().'p3/proxyValidate'; - break; - } - } - $url = $this->_buildQueryUrl( - $this->_server['proxy_validate_url'], - 'service='.urlencode($this->getURL()) - ); - phpCAS::traceEnd($url); - return $url; - } - - - /** - * This method is used to retrieve the proxy URL of the CAS server. - * - * @return string proxy URL. - */ - public function getServerProxyURL() - { - // the URL is build only when needed - if ( empty($this->_server['proxy_url']) ) { - switch ($this->getServerVersion()) { - case CAS_VERSION_1_0: - $this->_server['proxy_url'] = ''; - break; - case CAS_VERSION_2_0: - case CAS_VERSION_3_0: - $this->_server['proxy_url'] = $this->_getServerBaseURL().'proxy'; - break; - } - } - return $this->_server['proxy_url']; - } - - /** - * This method is used to retrieve the logout URL of the CAS server. - * - * @return string logout URL. - */ - public function getServerLogoutURL() - { - // the URL is build only when needed - if ( empty($this->_server['logout_url']) ) { - $this->_server['logout_url'] = $this->_getServerBaseURL().'logout'; - } - return $this->_server['logout_url']; - } - - /** - * This method sets the logout URL of the CAS server. - * - * @param string $url the logout URL - * - * @return string logout url - */ - public function setServerLogoutURL($url) - { - // Argument Validation - if (gettype($url) != 'string') - throw new CAS_TypeMismatchException($url, '$url', 'string'); - - return $this->_server['logout_url'] = $url; - } - - /** - * An array to store extra curl options. - */ - private $_curl_options = array(); - - /** - * This method is used to set additional user curl options. - * - * @param string $key name of the curl option - * @param string $value value of the curl option - * - * @return void - */ - public function setExtraCurlOption($key, $value) - { - $this->_curl_options[$key] = $value; - } - - /** @} */ - - // ######################################################################## - // Change the internal behaviour of phpcas - // ######################################################################## - - /** - * @addtogroup internalBehave - * @{ - */ - - /** - * The class to instantiate for making web requests in readUrl(). - * The class specified must implement the CAS_Request_RequestInterface. - * By default CAS_Request_CurlRequest is used, but this may be overridden to - * supply alternate request mechanisms for testing. - */ - private $_requestImplementation = 'CAS_Request_CurlRequest'; - - /** - * Override the default implementation used to make web requests in readUrl(). - * This class must implement the CAS_Request_RequestInterface. - * - * @param string $className name of the RequestImplementation class - * - * @return void - */ - public function setRequestImplementation ($className) - { - $obj = new $className; - if (!($obj instanceof CAS_Request_RequestInterface)) { - throw new CAS_InvalidArgumentException( - '$className must implement the CAS_Request_RequestInterface' - ); - } - $this->_requestImplementation = $className; - } - - /** - * @var boolean $_clearTicketsFromUrl; If true, phpCAS will clear session - * tickets from the URL after a successful authentication. - */ - private $_clearTicketsFromUrl = true; - - /** - * Configure the client to not send redirect headers and call exit() on - * authentication success. The normal redirect is used to remove the service - * ticket from the client's URL, but for running unit tests we need to - * continue without exiting. - * - * Needed for testing authentication - * - * @return void - */ - public function setNoClearTicketsFromUrl () - { - $this->_clearTicketsFromUrl = false; - } - - /** - * @var callback $_attributeParserCallbackFunction; - */ - private $_casAttributeParserCallbackFunction = null; - - /** - * @var array $_attributeParserCallbackArgs; - */ - private $_casAttributeParserCallbackArgs = array(); - - /** - * Set a callback function to be run when parsing CAS attributes - * - * The callback function will be passed a XMLNode as its first parameter, - * followed by any $additionalArgs you pass. - * - * @param string $function callback function to call - * @param array $additionalArgs optional array of arguments - * - * @return void - */ - public function setCasAttributeParserCallback($function, array $additionalArgs = array()) - { - $this->_casAttributeParserCallbackFunction = $function; - $this->_casAttributeParserCallbackArgs = $additionalArgs; - } - - /** @var callable $_postAuthenticateCallbackFunction; - */ - private $_postAuthenticateCallbackFunction = null; - - /** - * @var array $_postAuthenticateCallbackArgs; - */ - private $_postAuthenticateCallbackArgs = array(); - - /** - * Set a callback function to be run when a user authenticates. - * - * The callback function will be passed a $logoutTicket as its first parameter, - * followed by any $additionalArgs you pass. The $logoutTicket parameter is an - * opaque string that can be used to map a session-id to the logout request - * in order to support single-signout in applications that manage their own - * sessions (rather than letting phpCAS start the session). - * - * phpCAS::forceAuthentication() will always exit and forward client unless - * they are already authenticated. To perform an action at the moment the user - * logs in (such as registering an account, performing logging, etc), register - * a callback function here. - * - * @param callable $function callback function to call - * @param array $additionalArgs optional array of arguments - * - * @return void - */ - public function setPostAuthenticateCallback ($function, array $additionalArgs = array()) - { - $this->_postAuthenticateCallbackFunction = $function; - $this->_postAuthenticateCallbackArgs = $additionalArgs; - } - - /** - * @var callable $_signoutCallbackFunction; - */ - private $_signoutCallbackFunction = null; - - /** - * @var array $_signoutCallbackArgs; - */ - private $_signoutCallbackArgs = array(); - - /** - * Set a callback function to be run when a single-signout request is received. - * - * The callback function will be passed a $logoutTicket as its first parameter, - * followed by any $additionalArgs you pass. The $logoutTicket parameter is an - * opaque string that can be used to map a session-id to the logout request in - * order to support single-signout in applications that manage their own sessions - * (rather than letting phpCAS start and destroy the session). - * - * @param callable $function callback function to call - * @param array $additionalArgs optional array of arguments - * - * @return void - */ - public function setSingleSignoutCallback ($function, array $additionalArgs = array()) - { - $this->_signoutCallbackFunction = $function; - $this->_signoutCallbackArgs = $additionalArgs; - } - - // ######################################################################## - // Methods for supplying code-flow feedback to integrators. - // ######################################################################## - - /** - * Ensure that this is actually a proxy object or fail with an exception - * - * @throws CAS_OutOfSequenceBeforeProxyException - * - * @return void - */ - public function ensureIsProxy() - { - if (!$this->isProxy()) { - throw new CAS_OutOfSequenceBeforeProxyException(); - } - } - - /** - * Mark the caller of authentication. This will help client integraters determine - * problems with their code flow if they call a function such as getUser() before - * authentication has occurred. - * - * @param bool $auth True if authentication was successful, false otherwise. - * - * @return null - */ - public function markAuthenticationCall ($auth) - { - // store where the authentication has been checked and the result - $dbg = debug_backtrace(); - $this->_authentication_caller = array ( - 'file' => $dbg[1]['file'], - 'line' => $dbg[1]['line'], - 'method' => $dbg[1]['class'] . '::' . $dbg[1]['function'], - 'result' => (boolean)$auth - ); - } - private $_authentication_caller; - - /** - * Answer true if authentication has been checked. - * - * @return bool - */ - public function wasAuthenticationCalled () - { - return !empty($this->_authentication_caller); - } - - /** - * Ensure that authentication was checked. Terminate with exception if no - * authentication was performed - * - * @throws CAS_OutOfSequenceBeforeAuthenticationCallException - * - * @return void - */ - private function _ensureAuthenticationCalled() - { - if (!$this->wasAuthenticationCalled()) { - throw new CAS_OutOfSequenceBeforeAuthenticationCallException(); - } - } - - /** - * Answer the result of the authentication call. - * - * Throws a CAS_OutOfSequenceException if wasAuthenticationCalled() is false - * and markAuthenticationCall() didn't happen. - * - * @return bool - */ - public function wasAuthenticationCallSuccessful () - { - $this->_ensureAuthenticationCalled(); - return $this->_authentication_caller['result']; - } - - - /** - * Ensure that authentication was checked. Terminate with exception if no - * authentication was performed - * - * @throws CAS_OutOfSequenceException - * - * @return void - */ - public function ensureAuthenticationCallSuccessful() - { - $this->_ensureAuthenticationCalled(); - if (!$this->_authentication_caller['result']) { - throw new CAS_OutOfSequenceException( - 'authentication was checked (by ' - . $this->getAuthenticationCallerMethod() - . '() at ' . $this->getAuthenticationCallerFile() - . ':' . $this->getAuthenticationCallerLine() - . ') but the method returned false' - ); - } - } - - /** - * Answer information about the authentication caller. - * - * Throws a CAS_OutOfSequenceException if wasAuthenticationCalled() is false - * and markAuthenticationCall() didn't happen. - * - * @return string the file that called authentication - */ - public function getAuthenticationCallerFile () - { - $this->_ensureAuthenticationCalled(); - return $this->_authentication_caller['file']; - } - - /** - * Answer information about the authentication caller. - * - * Throws a CAS_OutOfSequenceException if wasAuthenticationCalled() is false - * and markAuthenticationCall() didn't happen. - * - * @return int the line that called authentication - */ - public function getAuthenticationCallerLine () - { - $this->_ensureAuthenticationCalled(); - return $this->_authentication_caller['line']; - } - - /** - * Answer information about the authentication caller. - * - * Throws a CAS_OutOfSequenceException if wasAuthenticationCalled() is false - * and markAuthenticationCall() didn't happen. - * - * @return string the method that called authentication - */ - public function getAuthenticationCallerMethod () - { - $this->_ensureAuthenticationCalled(); - return $this->_authentication_caller['method']; - } - - /** @} */ - - // ######################################################################## - // CONSTRUCTOR - // ######################################################################## - /** - * @addtogroup internalConfig - * @{ - */ - - /** - * CAS_Client constructor. - * - * @param string $server_version the version of the CAS server - * @param bool $proxy true if the CAS client is a CAS proxy - * @param string $server_hostname the hostname of the CAS server - * @param int $server_port the port the CAS server is running on - * @param string $server_uri the URI the CAS server is responding on - * @param bool $changeSessionID Allow phpCAS to change the session_id - * (Single Sign Out/handleLogoutRequests - * is based on that change) - * @param string|string[]|CAS_ServiceBaseUrl_Interface - * $service_base_url the base URL (protocol, host and the - * optional port) of the CAS client; pass - * in an array to use auto discovery with - * an allowlist; pass in - * CAS_ServiceBaseUrl_Interface for custom - * behavior. Added in 1.6.0. Similar to - * serverName config in other CAS clients. - * @param \SessionHandlerInterface $sessionHandler the session handler - * - * @return self a newly created CAS_Client object - */ - public function __construct( - $server_version, - $proxy, - $server_hostname, - $server_port, - $server_uri, - $service_base_url, - $changeSessionID = true, - \SessionHandlerInterface $sessionHandler = null - ) { - // Argument validation - if (gettype($server_version) != 'string') - throw new CAS_TypeMismatchException($server_version, '$server_version', 'string'); - if (gettype($proxy) != 'boolean') - throw new CAS_TypeMismatchException($proxy, '$proxy', 'boolean'); - if (gettype($server_hostname) != 'string') - throw new CAS_TypeMismatchException($server_hostname, '$server_hostname', 'string'); - if (gettype($server_port) != 'integer') - throw new CAS_TypeMismatchException($server_port, '$server_port', 'integer'); - if (gettype($server_uri) != 'string') - throw new CAS_TypeMismatchException($server_uri, '$server_uri', 'string'); - if (gettype($changeSessionID) != 'boolean') - throw new CAS_TypeMismatchException($changeSessionID, '$changeSessionID', 'boolean'); - - $this->_setServiceBaseUrl($service_base_url); - - if (empty($sessionHandler)) { - $sessionHandler = new CAS_Session_PhpSession; - } - - phpCAS::traceBegin(); - // true : allow to change the session_id(), false session_id won't be - // changed and logout won't be handled because of that - $this->_setChangeSessionID($changeSessionID); - - $this->setSessionHandler($sessionHandler); - - if (!$this->_isLogoutRequest()) { - if (session_id() === "") { - // skip Session Handling for logout requests and if don't want it - session_start(); - phpCAS :: trace("Starting a new session " . session_id()); - } - // init phpCAS session array - if (!isset($_SESSION[static::PHPCAS_SESSION_PREFIX]) - || !is_array($_SESSION[static::PHPCAS_SESSION_PREFIX])) { - $_SESSION[static::PHPCAS_SESSION_PREFIX] = array(); - } - } - - // Only for debug purposes - if ($this->isSessionAuthenticated()){ - phpCAS :: trace("Session is authenticated as: " . $this->getSessionValue('user')); - } else { - phpCAS :: trace("Session is not authenticated"); - } - // are we in proxy mode ? - $this->_proxy = $proxy; - - // Make cookie handling available. - if ($this->isProxy()) { - if (!$this->hasSessionValue('service_cookies')) { - $this->setSessionValue('service_cookies', array()); - } - // TODO remove explicit call to $_SESSION - $this->_serviceCookieJar = new CAS_CookieJar( - $_SESSION[static::PHPCAS_SESSION_PREFIX]['service_cookies'] - ); - } - - // check version - $supportedProtocols = phpCAS::getSupportedProtocols(); - if (isset($supportedProtocols[$server_version]) === false) { - phpCAS::error( - 'this version of CAS (`'.$server_version - .'\') is not supported by phpCAS '.phpCAS::getVersion() - ); - } - - if ($server_version === CAS_VERSION_1_0 && $this->isProxy()) { - phpCAS::error( - 'CAS proxies are not supported in CAS '.$server_version - ); - } - - $this->_server['version'] = $server_version; - - // check hostname - if ( empty($server_hostname) - || !preg_match('/[\.\d\-a-z]*/', $server_hostname) - ) { - phpCAS::error('bad CAS server hostname (`'.$server_hostname.'\')'); - } - $this->_server['hostname'] = $server_hostname; - - // check port - if ( $server_port == 0 - || !is_int($server_port) - ) { - phpCAS::error('bad CAS server port (`'.$server_hostname.'\')'); - } - $this->_server['port'] = $server_port; - - // check URI - if ( !preg_match('/[\.\d\-_a-z\/]*/', $server_uri) ) { - phpCAS::error('bad CAS server URI (`'.$server_uri.'\')'); - } - // add leading and trailing `/' and remove doubles - if(strstr($server_uri, '?') === false) $server_uri .= '/'; - $server_uri = preg_replace('/\/\//', '/', '/'.$server_uri); - $this->_server['uri'] = $server_uri; - - // set to callback mode if PgtIou and PgtId CGI GET parameters are provided - if ( $this->isProxy() ) { - if(!empty($_GET['pgtIou'])&&!empty($_GET['pgtId'])) { - $this->_setCallbackMode(true); - $this->_setCallbackModeUsingPost(false); - } elseif (!empty($_POST['pgtIou'])&&!empty($_POST['pgtId'])) { - $this->_setCallbackMode(true); - $this->_setCallbackModeUsingPost(true); - } else { - $this->_setCallbackMode(false); - $this->_setCallbackModeUsingPost(false); - } - - - } - - if ( $this->_isCallbackMode() ) { - //callback mode: check that phpCAS is secured - if ( !$this->getServiceBaseUrl()->isHttps() ) { - phpCAS::error( - 'CAS proxies must be secured to use phpCAS; PGT\'s will not be received from the CAS server' - ); - } - } else { - //normal mode: get ticket and remove it from CGI parameters for - // developers - $ticket = (isset($_GET['ticket']) ? $_GET['ticket'] : ''); - if (preg_match('/^[SP]T-/', $ticket) ) { - phpCAS::trace('Ticket \''.$ticket.'\' found'); - $this->setTicket($ticket); - unset($_GET['ticket']); - } else if ( !empty($ticket) ) { - //ill-formed ticket, halt - phpCAS::error( - 'ill-formed ticket found in the URL (ticket=`' - .htmlentities($ticket).'\')' - ); - } - - } - phpCAS::traceEnd(); - } - - /** @} */ - - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - // XX XX - // XX Session Handling XX - // XX XX - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - - /** - * @addtogroup internalConfig - * @{ - */ - - /** The session prefix for phpCAS values */ - const PHPCAS_SESSION_PREFIX = 'phpCAS'; - - /** - * @var bool A variable to whether phpcas will use its own session handling. Default = true - * @hideinitializer - */ - private $_change_session_id = true; - - /** - * @var SessionHandlerInterface - */ - private $_sessionHandler; - - /** - * Set a parameter whether to allow phpCAS to change session_id - * - * @param bool $allowed allow phpCAS to change session_id - * - * @return void - */ - private function _setChangeSessionID($allowed) - { - $this->_change_session_id = $allowed; - } - - /** - * Get whether phpCAS is allowed to change session_id - * - * @return bool - */ - public function getChangeSessionID() - { - return $this->_change_session_id; - } - - /** - * Set the session handler. - * - * @param \SessionHandlerInterface $sessionHandler - * - * @return bool - */ - public function setSessionHandler(\SessionHandlerInterface $sessionHandler) - { - $this->_sessionHandler = $sessionHandler; - if (session_status() !== PHP_SESSION_ACTIVE) { - return session_set_save_handler($this->_sessionHandler, true); - } - return true; - } - - /** - * Get a session value using the given key. - * - * @param string $key - * @param mixed $default default value if the key is not set - * - * @return mixed - */ - protected function getSessionValue($key, $default = null) - { - $this->validateSession($key); - - if (isset($_SESSION[static::PHPCAS_SESSION_PREFIX][$key])) { - return $_SESSION[static::PHPCAS_SESSION_PREFIX][$key]; - } - - return $default; - } - - /** - * Determine whether a session value is set or not. - * - * To check if a session value is empty or not please use - * !!(getSessionValue($key)). - * - * @param string $key - * - * @return bool - */ - protected function hasSessionValue($key) - { - $this->validateSession($key); - - return isset($_SESSION[static::PHPCAS_SESSION_PREFIX][$key]); - } - - /** - * Set a session value using the given key and value. - * - * @param string $key - * @param mixed $value - * - * @return string - */ - protected function setSessionValue($key, $value) - { - $this->validateSession($key); - - $_SESSION[static::PHPCAS_SESSION_PREFIX][$key] = $value; - } - - /** - * Remove a session value with the given key. - * - * @param string $key - */ - protected function removeSessionValue($key) - { - $this->validateSession($key); - - if (isset($_SESSION[static::PHPCAS_SESSION_PREFIX][$key])) { - unset($_SESSION[static::PHPCAS_SESSION_PREFIX][$key]); - return true; - } - - return false; - } - - /** - * Remove all phpCAS session values. - */ - protected function clearSessionValues() - { - unset($_SESSION[static::PHPCAS_SESSION_PREFIX]); - } - - /** - * Ensure $key is a string for session utils input - * - * @param string $key - * - * @return bool - */ - protected function validateSession($key) - { - if (!is_string($key)) { - throw new InvalidArgumentException('Session key must be a string.'); - } - - return true; - } - - /** - * Renaming the session - * - * @param string $ticket name of the ticket - * - * @return void - */ - protected function _renameSession($ticket) - { - phpCAS::traceBegin(); - if ($this->getChangeSessionID()) { - if (!empty($this->_user)) { - $old_session = $_SESSION; - phpCAS :: trace("Killing session: ". session_id()); - session_destroy(); - // set up a new session, of name based on the ticket - $session_id = $this->_sessionIdForTicket($ticket); - phpCAS :: trace("Starting session: ". $session_id); - session_id($session_id); - session_start(); - phpCAS :: trace("Restoring old session vars"); - $_SESSION = $old_session; - } else { - phpCAS :: trace ( - 'Session should only be renamed after successfull authentication' - ); - } - } else { - phpCAS :: trace( - "Skipping session rename since phpCAS is not handling the session." - ); - } - phpCAS::traceEnd(); - } - - /** @} */ - - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - // XX XX - // XX AUTHENTICATION XX - // XX XX - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - - /** - * @addtogroup internalAuthentication - * @{ - */ - - /** - * The Authenticated user. Written by CAS_Client::_setUser(), read by - * CAS_Client::getUser(). - * - * @hideinitializer - */ - private $_user = ''; - - /** - * This method sets the CAS user's login name. - * - * @param string $user the login name of the authenticated user. - * - * @return void - */ - private function _setUser($user) - { - $this->_user = $user; - } - - /** - * This method returns the CAS user's login name. - * - * @return string the login name of the authenticated user - * - * @warning should be called only after CAS_Client::forceAuthentication() or - * CAS_Client::isAuthenticated(), otherwise halt with an error. - */ - public function getUser() - { - // Sequence validation - $this->ensureAuthenticationCallSuccessful(); - - return $this->_getUser(); - } - - /** - * This method returns the CAS user's login name. - * - * @return string the login name of the authenticated user - * - * @warning should be called only after CAS_Client::forceAuthentication() or - * CAS_Client::isAuthenticated(), otherwise halt with an error. - */ - private function _getUser() - { - // This is likely a duplicate check that could be removed.... - if ( empty($this->_user) ) { - phpCAS::error( - 'this method should be used only after '.__CLASS__ - .'::forceAuthentication() or '.__CLASS__.'::isAuthenticated()' - ); - } - return $this->_user; - } - - /** - * The Authenticated users attributes. Written by - * CAS_Client::setAttributes(), read by CAS_Client::getAttributes(). - * @attention client applications should use phpCAS::getAttributes(). - * - * @hideinitializer - */ - private $_attributes = array(); - - /** - * Set an array of attributes - * - * @param array $attributes a key value array of attributes - * - * @return void - */ - public function setAttributes($attributes) - { - $this->_attributes = $attributes; - } - - /** - * Get an key values arry of attributes - * - * @return array of attributes - */ - public function getAttributes() - { - // Sequence validation - $this->ensureAuthenticationCallSuccessful(); - // This is likely a duplicate check that could be removed.... - if ( empty($this->_user) ) { - // if no user is set, there shouldn't be any attributes also... - phpCAS::error( - 'this method should be used only after '.__CLASS__ - .'::forceAuthentication() or '.__CLASS__.'::isAuthenticated()' - ); - } - return $this->_attributes; - } - - /** - * Check whether attributes are available - * - * @return bool attributes available - */ - public function hasAttributes() - { - // Sequence validation - $this->ensureAuthenticationCallSuccessful(); - - return !empty($this->_attributes); - } - /** - * Check whether a specific attribute with a name is available - * - * @param string $key name of attribute - * - * @return bool is attribute available - */ - public function hasAttribute($key) - { - // Sequence validation - $this->ensureAuthenticationCallSuccessful(); - - return $this->_hasAttribute($key); - } - - /** - * Check whether a specific attribute with a name is available - * - * @param string $key name of attribute - * - * @return bool is attribute available - */ - private function _hasAttribute($key) - { - return (is_array($this->_attributes) - && array_key_exists($key, $this->_attributes)); - } - - /** - * Get a specific attribute by name - * - * @param string $key name of attribute - * - * @return string attribute values - */ - public function getAttribute($key) - { - // Sequence validation - $this->ensureAuthenticationCallSuccessful(); - - if ($this->_hasAttribute($key)) { - return $this->_attributes[$key]; - } - } - - /** - * This method is called to renew the authentication of the user - * If the user is authenticated, renew the connection - * If not, redirect to CAS - * - * @return bool true when the user is authenticated; otherwise halt. - */ - public function renewAuthentication() - { - phpCAS::traceBegin(); - // Either way, the user is authenticated by CAS - $this->removeSessionValue('auth_checked'); - if ( $this->isAuthenticated(true) ) { - phpCAS::trace('user already authenticated'); - $res = true; - } else { - $this->redirectToCas(false, true); - // never reached - $res = false; - } - phpCAS::traceEnd(); - return $res; - } - - /** - * This method is called to be sure that the user is authenticated. When not - * authenticated, halt by redirecting to the CAS server; otherwise return true. - * - * @return bool true when the user is authenticated; otherwise halt. - */ - public function forceAuthentication() - { - phpCAS::traceBegin(); - - if ( $this->isAuthenticated() ) { - // the user is authenticated, nothing to be done. - phpCAS::trace('no need to authenticate'); - $res = true; - } else { - // the user is not authenticated, redirect to the CAS server - $this->removeSessionValue('auth_checked'); - $this->redirectToCas(false/* no gateway */); - // never reached - $res = false; - } - phpCAS::traceEnd($res); - return $res; - } - - /** - * An integer that gives the number of times authentication will be cached - * before rechecked. - * - * @hideinitializer - */ - private $_cache_times_for_auth_recheck = 0; - - /** - * Set the number of times authentication will be cached before rechecked. - * - * @param int $n number of times to wait for a recheck - * - * @return void - */ - public function setCacheTimesForAuthRecheck($n) - { - if (gettype($n) != 'integer') - throw new CAS_TypeMismatchException($n, '$n', 'string'); - - $this->_cache_times_for_auth_recheck = $n; - } - - /** - * This method is called to check whether the user is authenticated or not. - * - * @return bool true when the user is authenticated, false when a previous - * gateway login failed or the function will not return if the user is - * redirected to the cas server for a gateway login attempt - */ - public function checkAuthentication() - { - phpCAS::traceBegin(); - $res = false; // default - if ( $this->isAuthenticated() ) { - phpCAS::trace('user is authenticated'); - /* The 'auth_checked' variable is removed just in case it's set. */ - $this->removeSessionValue('auth_checked'); - $res = true; - } else if ($this->getSessionValue('auth_checked')) { - // the previous request has redirected the client to the CAS server - // with gateway=true - $this->removeSessionValue('auth_checked'); - } else { - // avoid a check against CAS on every request - // we need to write this back to session later - $unauth_count = $this->getSessionValue('unauth_count', -2); - - if (($unauth_count != -2 - && $this->_cache_times_for_auth_recheck == -1) - || ($unauth_count >= 0 - && $unauth_count < $this->_cache_times_for_auth_recheck) - ) { - if ($this->_cache_times_for_auth_recheck != -1) { - $unauth_count++; - phpCAS::trace( - 'user is not authenticated (cached for ' - .$unauth_count.' times of ' - .$this->_cache_times_for_auth_recheck.')' - ); - } else { - phpCAS::trace( - 'user is not authenticated (cached for until login pressed)' - ); - } - $this->setSessionValue('unauth_count', $unauth_count); - } else { - $this->setSessionValue('unauth_count', 0); - $this->setSessionValue('auth_checked', true); - phpCAS::trace('user is not authenticated (cache reset)'); - $this->redirectToCas(true/* gateway */); - // never reached - } - } - phpCAS::traceEnd($res); - return $res; - } - - /** - * This method is called to check if the user is authenticated (previously or by - * tickets given in the URL). - * - * @param bool $renew true to force the authentication with the CAS server - * - * @return bool true when the user is authenticated. Also may redirect to the - * same URL without the ticket. - */ - public function isAuthenticated($renew=false) - { - phpCAS::traceBegin(); - $res = false; - - if ( $this->_wasPreviouslyAuthenticated() ) { - if ($this->hasTicket()) { - // User has a additional ticket but was already authenticated - phpCAS::trace( - 'ticket was present and will be discarded, use renewAuthenticate()' - ); - if ($this->_clearTicketsFromUrl) { - phpCAS::trace("Prepare redirect to : ".$this->getURL()); - session_write_close(); - header('Location: '.$this->getURL()); - flush(); - phpCAS::traceExit(); - throw new CAS_GracefullTerminationException(); - } else { - phpCAS::trace( - 'Already authenticated, but skipping ticket clearing since setNoClearTicketsFromUrl() was used.' - ); - $res = true; - } - } else { - // the user has already (previously during the session) been - // authenticated, nothing to be done. - phpCAS::trace( - 'user was already authenticated, no need to look for tickets' - ); - $res = true; - } - - // Mark the auth-check as complete to allow post-authentication - // callbacks to make use of phpCAS::getUser() and similar methods - $this->markAuthenticationCall($res); - } else { - if ($this->hasTicket()) { - $validate_url = ''; - $text_response = ''; - $tree_response = ''; - - switch ($this->getServerVersion()) { - case CAS_VERSION_1_0: - // if a Service Ticket was given, validate it - phpCAS::trace( - 'CAS 1.0 ticket `'.$this->getTicket().'\' is present' - ); - $this->validateCAS10( - $validate_url, $text_response, $tree_response, $renew - ); // if it fails, it halts - phpCAS::trace( - 'CAS 1.0 ticket `'.$this->getTicket().'\' was validated' - ); - $this->setSessionValue('user', $this->_getUser()); - $res = true; - $logoutTicket = $this->getTicket(); - break; - case CAS_VERSION_2_0: - case CAS_VERSION_3_0: - // if a Proxy Ticket was given, validate it - phpCAS::trace( - 'CAS '.$this->getServerVersion().' ticket `'.$this->getTicket().'\' is present' - ); - $this->validateCAS20( - $validate_url, $text_response, $tree_response, $renew - ); // note: if it fails, it halts - phpCAS::trace( - 'CAS '.$this->getServerVersion().' ticket `'.$this->getTicket().'\' was validated' - ); - if ( $this->isProxy() ) { - $this->_validatePGT( - $validate_url, $text_response, $tree_response - ); // idem - phpCAS::trace('PGT `'.$this->_getPGT().'\' was validated'); - $this->setSessionValue('pgt', $this->_getPGT()); - } - $this->setSessionValue('user', $this->_getUser()); - if (!empty($this->_attributes)) { - $this->setSessionValue('attributes', $this->_attributes); - } - $proxies = $this->getProxies(); - if (!empty($proxies)) { - $this->setSessionValue('proxies', $this->getProxies()); - } - $res = true; - $logoutTicket = $this->getTicket(); - break; - case SAML_VERSION_1_1: - // if we have a SAML ticket, validate it. - phpCAS::trace( - 'SAML 1.1 ticket `'.$this->getTicket().'\' is present' - ); - $this->validateSA( - $validate_url, $text_response, $tree_response, $renew - ); // if it fails, it halts - phpCAS::trace( - 'SAML 1.1 ticket `'.$this->getTicket().'\' was validated' - ); - $this->setSessionValue('user', $this->_getUser()); - $this->setSessionValue('attributes', $this->_attributes); - $res = true; - $logoutTicket = $this->getTicket(); - break; - default: - phpCAS::trace('Protocol error'); - break; - } - } else { - // no ticket given, not authenticated - phpCAS::trace('no ticket found'); - } - - // Mark the auth-check as complete to allow post-authentication - // callbacks to make use of phpCAS::getUser() and similar methods - $this->markAuthenticationCall($res); - - if ($res) { - // call the post-authenticate callback if registered. - if ($this->_postAuthenticateCallbackFunction) { - $args = $this->_postAuthenticateCallbackArgs; - array_unshift($args, $logoutTicket); - call_user_func_array( - $this->_postAuthenticateCallbackFunction, $args - ); - } - - // if called with a ticket parameter, we need to redirect to the - // app without the ticket so that CAS-ification is transparent - // to the browser (for later POSTS) most of the checks and - // errors should have been made now, so we're safe for redirect - // without masking error messages. remove the ticket as a - // security precaution to prevent a ticket in the HTTP_REFERRER - if ($this->_clearTicketsFromUrl) { - phpCAS::trace("Prepare redirect to : ".$this->getURL()); - session_write_close(); - header('Location: '.$this->getURL()); - flush(); - phpCAS::traceExit(); - throw new CAS_GracefullTerminationException(); - } - } - } - phpCAS::traceEnd($res); - return $res; - } - - /** - * This method tells if the current session is authenticated. - * - * @return bool true if authenticated based soley on $_SESSION variable - */ - public function isSessionAuthenticated () - { - return !!$this->getSessionValue('user'); - } - - /** - * This method tells if the user has already been (previously) authenticated - * by looking into the session variables. - * - * @note This function switches to callback mode when needed. - * - * @return bool true when the user has already been authenticated; false otherwise. - */ - private function _wasPreviouslyAuthenticated() - { - phpCAS::traceBegin(); - - if ( $this->_isCallbackMode() ) { - // Rebroadcast the pgtIou and pgtId to all nodes - if ($this->_rebroadcast&&!isset($_POST['rebroadcast'])) { - $this->_rebroadcast(self::PGTIOU); - } - $this->_callback(); - } - - $auth = false; - - if ( $this->isProxy() ) { - // CAS proxy: username and PGT must be present - if ( $this->isSessionAuthenticated() - && $this->getSessionValue('pgt') - ) { - // authentication already done - $this->_setUser($this->getSessionValue('user')); - if ($this->hasSessionValue('attributes')) { - $this->setAttributes($this->getSessionValue('attributes')); - } - $this->_setPGT($this->getSessionValue('pgt')); - phpCAS::trace( - 'user = `'.$this->getSessionValue('user').'\', PGT = `' - .$this->getSessionValue('pgt').'\'' - ); - - // Include the list of proxies - if ($this->hasSessionValue('proxies')) { - $this->_setProxies($this->getSessionValue('proxies')); - phpCAS::trace( - 'proxies = "' - .implode('", "', $this->getSessionValue('proxies')).'"' - ); - } - - $auth = true; - } elseif ( $this->isSessionAuthenticated() - && !$this->getSessionValue('pgt') - ) { - // these two variables should be empty or not empty at the same time - phpCAS::trace( - 'username found (`'.$this->getSessionValue('user') - .'\') but PGT is empty' - ); - // unset all tickets to enforce authentication - $this->clearSessionValues(); - $this->setTicket(''); - } elseif ( !$this->isSessionAuthenticated() - && $this->getSessionValue('pgt') - ) { - // these two variables should be empty or not empty at the same time - phpCAS::trace( - 'PGT found (`'.$this->getSessionValue('pgt') - .'\') but username is empty' - ); - // unset all tickets to enforce authentication - $this->clearSessionValues(); - $this->setTicket(''); - } else { - phpCAS::trace('neither user nor PGT found'); - } - } else { - // `simple' CAS client (not a proxy): username must be present - if ( $this->isSessionAuthenticated() ) { - // authentication already done - $this->_setUser($this->getSessionValue('user')); - if ($this->hasSessionValue('attributes')) { - $this->setAttributes($this->getSessionValue('attributes')); - } - phpCAS::trace('user = `'.$this->getSessionValue('user').'\''); - - // Include the list of proxies - if ($this->hasSessionValue('proxies')) { - $this->_setProxies($this->getSessionValue('proxies')); - phpCAS::trace( - 'proxies = "' - .implode('", "', $this->getSessionValue('proxies')).'"' - ); - } - - $auth = true; - } else { - phpCAS::trace('no user found'); - } - } - - phpCAS::traceEnd($auth); - return $auth; - } - - /** - * This method is used to redirect the client to the CAS server. - * It is used by CAS_Client::forceAuthentication() and - * CAS_Client::checkAuthentication(). - * - * @param bool $gateway true to check authentication, false to force it - * @param bool $renew true to force the authentication with the CAS server - * - * @return void - */ - public function redirectToCas($gateway=false,$renew=false) - { - phpCAS::traceBegin(); - $cas_url = $this->getServerLoginURL($gateway, $renew); - session_write_close(); - if (php_sapi_name() === 'cli') { - @header('Location: '.$cas_url); - } else { - header('Location: '.$cas_url); - } - phpCAS::trace("Redirect to : ".$cas_url); - $lang = $this->getLangObj(); - $this->printHTMLHeader($lang->getAuthenticationWanted()); - $this->printf('

'. $lang->getShouldHaveBeenRedirected(). '

', $cas_url); - $this->printHTMLFooter(); - phpCAS::traceExit(); - throw new CAS_GracefullTerminationException(); - } - - - /** - * This method is used to logout from CAS. - * - * @param array $params an array that contains the optional url and service - * parameters that will be passed to the CAS server - * - * @return void - */ - public function logout($params) - { - phpCAS::traceBegin(); - $cas_url = $this->getServerLogoutURL(); - $paramSeparator = '?'; - if (isset($params['url'])) { - $cas_url = $cas_url . $paramSeparator . "url=" - . urlencode($params['url']); - $paramSeparator = '&'; - } - if (isset($params['service'])) { - $cas_url = $cas_url . $paramSeparator . "service=" - . urlencode($params['service']); - } - header('Location: '.$cas_url); - phpCAS::trace("Prepare redirect to : ".$cas_url); - - phpCAS::trace("Destroying session : ".session_id()); - session_unset(); - session_destroy(); - if (session_status() === PHP_SESSION_NONE) { - phpCAS::trace("Session terminated"); - } else { - phpCAS::error("Session was not terminated"); - phpCAS::trace("Session was not terminated"); - } - $lang = $this->getLangObj(); - $this->printHTMLHeader($lang->getLogout()); - $this->printf('

'.$lang->getShouldHaveBeenRedirected(). '

', $cas_url); - $this->printHTMLFooter(); - phpCAS::traceExit(); - throw new CAS_GracefullTerminationException(); - } - - /** - * Check of the current request is a logout request - * - * @return bool is logout request. - */ - private function _isLogoutRequest() - { - return !empty($_POST['logoutRequest']); - } - - /** - * This method handles logout requests. - * - * @param bool $check_client true to check the client bofore handling - * the request, false not to perform any access control. True by default. - * @param array $allowed_clients an array of host names allowed to send - * logout requests. - * - * @return void - */ - public function handleLogoutRequests($check_client=true, $allowed_clients=array()) - { - phpCAS::traceBegin(); - if (!$this->_isLogoutRequest()) { - phpCAS::trace("Not a logout request"); - phpCAS::traceEnd(); - return; - } - if (!$this->getChangeSessionID() - && is_null($this->_signoutCallbackFunction) - ) { - phpCAS::trace( - "phpCAS can't handle logout requests if it is not allowed to change session_id." - ); - } - phpCAS::trace("Logout requested"); - $decoded_logout_rq = urldecode($_POST['logoutRequest']); - phpCAS::trace("SAML REQUEST: ".$decoded_logout_rq); - $allowed = false; - if ($check_client) { - if ($allowed_clients === array()) { - $allowed_clients = array( $this->_getServerHostname() ); - } - $client_ip = $_SERVER['REMOTE_ADDR']; - $client = gethostbyaddr($client_ip); - phpCAS::trace("Client: ".$client."/".$client_ip); - foreach ($allowed_clients as $allowed_client) { - if (($client == $allowed_client) - || ($client_ip == $allowed_client) - ) { - phpCAS::trace( - "Allowed client '".$allowed_client - ."' matches, logout request is allowed" - ); - $allowed = true; - break; - } else { - phpCAS::trace( - "Allowed client '".$allowed_client."' does not match" - ); - } - } - } else { - phpCAS::trace("No access control set"); - $allowed = true; - } - // If Logout command is permitted proceed with the logout - if ($allowed) { - phpCAS::trace("Logout command allowed"); - // Rebroadcast the logout request - if ($this->_rebroadcast && !isset($_POST['rebroadcast'])) { - $this->_rebroadcast(self::LOGOUT); - } - // Extract the ticket from the SAML Request - preg_match( - "|(.*)|", - $decoded_logout_rq, $tick, PREG_OFFSET_CAPTURE, 3 - ); - $wrappedSamlSessionIndex = preg_replace( - '||', '', $tick[0][0] - ); - $ticket2logout = preg_replace( - '||', '', $wrappedSamlSessionIndex - ); - phpCAS::trace("Ticket to logout: ".$ticket2logout); - - // call the post-authenticate callback if registered. - if ($this->_signoutCallbackFunction) { - $args = $this->_signoutCallbackArgs; - array_unshift($args, $ticket2logout); - call_user_func_array($this->_signoutCallbackFunction, $args); - } - - // If phpCAS is managing the session_id, destroy session thanks to - // session_id. - if ($this->getChangeSessionID()) { - $session_id = $this->_sessionIdForTicket($ticket2logout); - phpCAS::trace("Session id: ".$session_id); - - // destroy a possible application session created before phpcas - if (session_id() !== "") { - session_unset(); - session_destroy(); - } - // fix session ID - session_id($session_id); - $_COOKIE[session_name()]=$session_id; - $_GET[session_name()]=$session_id; - - // Overwrite session - session_start(); - session_unset(); - session_destroy(); - phpCAS::trace("Session ". $session_id . " destroyed"); - } - } else { - phpCAS::error("Unauthorized logout request from client '".$client."'"); - phpCAS::trace("Unauthorized logout request from client '".$client."'"); - } - flush(); - phpCAS::traceExit(); - throw new CAS_GracefullTerminationException(); - - } - - /** @} */ - - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - // XX XX - // XX BASIC CLIENT FEATURES (CAS 1.0) XX - // XX XX - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - - // ######################################################################## - // ST - // ######################################################################## - /** - * @addtogroup internalBasic - * @{ - */ - - /** - * The Ticket provided in the URL of the request if present - * (empty otherwise). Written by CAS_Client::CAS_Client(), read by - * CAS_Client::getTicket() and CAS_Client::_hasPGT(). - * - * @hideinitializer - */ - private $_ticket = ''; - - /** - * This method returns the Service Ticket provided in the URL of the request. - * - * @return string service ticket. - */ - public function getTicket() - { - return $this->_ticket; - } - - /** - * This method stores the Service Ticket. - * - * @param string $st The Service Ticket. - * - * @return void - */ - public function setTicket($st) - { - $this->_ticket = $st; - } - - /** - * This method tells if a Service Ticket was stored. - * - * @return bool if a Service Ticket has been stored. - */ - public function hasTicket() - { - return !empty($this->_ticket); - } - - /** @} */ - - // ######################################################################## - // ST VALIDATION - // ######################################################################## - /** - * @addtogroup internalBasic - * @{ - */ - - /** - * @var string the certificate of the CAS server CA. - * - * @hideinitializer - */ - private $_cas_server_ca_cert = null; - - - /** - - * validate CN of the CAS server certificate - - * - - * @hideinitializer - - */ - - private $_cas_server_cn_validate = true; - - /** - * Set to true not to validate the CAS server. - * - * @hideinitializer - */ - private $_no_cas_server_validation = false; - - - /** - * Set the CA certificate of the CAS server. - * - * @param string $cert the PEM certificate file name of the CA that emited - * the cert of the server - * @param bool $validate_cn valiate CN of the CAS server certificate - * - * @return void - */ - public function setCasServerCACert($cert, $validate_cn) - { - // Argument validation - if (gettype($cert) != 'string') { - throw new CAS_TypeMismatchException($cert, '$cert', 'string'); - } - if (gettype($validate_cn) != 'boolean') { - throw new CAS_TypeMismatchException($validate_cn, '$validate_cn', 'boolean'); - } - if (!file_exists($cert)) { - throw new CAS_InvalidArgumentException("Certificate file does not exist " . $this->_requestImplementation); - } - $this->_cas_server_ca_cert = $cert; - $this->_cas_server_cn_validate = $validate_cn; - } - - /** - * Set no SSL validation for the CAS server. - * - * @return void - */ - public function setNoCasServerValidation() - { - $this->_no_cas_server_validation = true; - } - - /** - * This method is used to validate a CAS 1,0 ticket; halt on failure, and - * sets $validate_url, $text_reponse and $tree_response on success. - * - * @param string &$validate_url reference to the the URL of the request to - * the CAS server. - * @param string &$text_response reference to the response of the CAS - * server, as is (XML text). - * @param string &$tree_response reference to the response of the CAS - * server, as a DOM XML tree. - * @param bool $renew true to force the authentication with the CAS server - * - * @return bool true when successfull and issue a CAS_AuthenticationException - * and false on an error - * @throws CAS_AuthenticationException - */ - public function validateCAS10(&$validate_url,&$text_response,&$tree_response,$renew=false) - { - phpCAS::traceBegin(); - // build the URL to validate the ticket - $validate_url = $this->getServerServiceValidateURL() - .'&ticket='.urlencode($this->getTicket()); - - if ( $renew ) { - // pass the renew - $validate_url .= '&renew=true'; - } - - $headers = ''; - $err_msg = ''; - // open and read the URL - if ( !$this->_readURL($validate_url, $headers, $text_response, $err_msg) ) { - phpCAS::trace( - 'could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')' - ); - throw new CAS_AuthenticationException( - $this, 'CAS 1.0 ticket not validated', $validate_url, - true/*$no_response*/ - ); - } - - if (preg_match('/^no\n/', $text_response)) { - phpCAS::trace('Ticket has not been validated'); - throw new CAS_AuthenticationException( - $this, 'ST not validated', $validate_url, false/*$no_response*/, - false/*$bad_response*/, $text_response - ); - } else if (!preg_match('/^yes\n/', $text_response)) { - phpCAS::trace('ill-formed response'); - throw new CAS_AuthenticationException( - $this, 'Ticket not validated', $validate_url, - false/*$no_response*/, true/*$bad_response*/, $text_response - ); - } - // ticket has been validated, extract the user name - $arr = preg_split('/\n/', $text_response); - $this->_setUser(trim($arr[1])); - - $this->_renameSession($this->getTicket()); - - // at this step, ticket has been validated and $this->_user has been set, - phpCAS::traceEnd(true); - return true; - } - - /** @} */ - - - // ######################################################################## - // SAML VALIDATION - // ######################################################################## - /** - * @addtogroup internalSAML - * @{ - */ - - /** - * This method is used to validate a SAML TICKET; halt on failure, and sets - * $validate_url, $text_reponse and $tree_response on success. These - * parameters are used later by CAS_Client::_validatePGT() for CAS proxies. - * - * @param string &$validate_url reference to the the URL of the request to - * the CAS server. - * @param string &$text_response reference to the response of the CAS - * server, as is (XML text). - * @param string &$tree_response reference to the response of the CAS - * server, as a DOM XML tree. - * @param bool $renew true to force the authentication with the CAS server - * - * @return bool true when successfull and issue a CAS_AuthenticationException - * and false on an error - * - * @throws CAS_AuthenticationException - */ - public function validateSA(&$validate_url,&$text_response,&$tree_response,$renew=false) - { - phpCAS::traceBegin(); - $result = false; - // build the URL to validate the ticket - $validate_url = $this->getServerSamlValidateURL(); - - if ( $renew ) { - // pass the renew - $validate_url .= '&renew=true'; - } - - $headers = ''; - $err_msg = ''; - // open and read the URL - if ( !$this->_readURL($validate_url, $headers, $text_response, $err_msg) ) { - phpCAS::trace( - 'could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')' - ); - throw new CAS_AuthenticationException( - $this, 'SA not validated', $validate_url, true/*$no_response*/ - ); - } - - phpCAS::trace('server version: '.$this->getServerVersion()); - - // analyze the result depending on the version - switch ($this->getServerVersion()) { - case SAML_VERSION_1_1: - // create new DOMDocument Object - $dom = new DOMDocument(); - // Fix possible whitspace problems - $dom->preserveWhiteSpace = false; - // read the response of the CAS server into a DOM object - if (!($dom->loadXML($text_response))) { - phpCAS::trace('dom->loadXML() failed'); - throw new CAS_AuthenticationException( - $this, 'SA not validated', $validate_url, - false/*$no_response*/, true/*$bad_response*/, - $text_response - ); - } - // read the root node of the XML tree - if (!($tree_response = $dom->documentElement)) { - phpCAS::trace('documentElement() failed'); - throw new CAS_AuthenticationException( - $this, 'SA not validated', $validate_url, - false/*$no_response*/, true/*$bad_response*/, - $text_response - ); - } else if ( $tree_response->localName != 'Envelope' ) { - // insure that tag name is 'Envelope' - phpCAS::trace( - 'bad XML root node (should be `Envelope\' instead of `' - .$tree_response->localName.'\'' - ); - throw new CAS_AuthenticationException( - $this, 'SA not validated', $validate_url, - false/*$no_response*/, true/*$bad_response*/, - $text_response - ); - } else if ($tree_response->getElementsByTagName("NameIdentifier")->length != 0) { - // check for the NameIdentifier tag in the SAML response - $success_elements = $tree_response->getElementsByTagName("NameIdentifier"); - phpCAS::trace('NameIdentifier found'); - $user = trim($success_elements->item(0)->nodeValue); - phpCAS::trace('user = `'.$user.'`'); - $this->_setUser($user); - $this->_setSessionAttributes($text_response); - $result = true; - } else { - phpCAS::trace('no tag found in SAML payload'); - throw new CAS_AuthenticationException( - $this, 'SA not validated', $validate_url, - false/*$no_response*/, true/*$bad_response*/, - $text_response - ); - } - } - if ($result) { - $this->_renameSession($this->getTicket()); - } - // at this step, ST has been validated and $this->_user has been set, - phpCAS::traceEnd($result); - return $result; - } - - /** - * This method will parse the DOM and pull out the attributes from the SAML - * payload and put them into an array, then put the array into the session. - * - * @param string $text_response the SAML payload. - * - * @return bool true when successfull and false if no attributes a found - */ - private function _setSessionAttributes($text_response) - { - phpCAS::traceBegin(); - - $result = false; - - $attr_array = array(); - - // create new DOMDocument Object - $dom = new DOMDocument(); - // Fix possible whitspace problems - $dom->preserveWhiteSpace = false; - if (($dom->loadXML($text_response))) { - $xPath = new DOMXPath($dom); - $xPath->registerNamespace('samlp', 'urn:oasis:names:tc:SAML:1.0:protocol'); - $xPath->registerNamespace('saml', 'urn:oasis:names:tc:SAML:1.0:assertion'); - $nodelist = $xPath->query("//saml:Attribute"); - - if ($nodelist) { - foreach ($nodelist as $node) { - $xres = $xPath->query("saml:AttributeValue", $node); - $name = $node->getAttribute("AttributeName"); - $value_array = array(); - foreach ($xres as $node2) { - $value_array[] = $node2->nodeValue; - } - $attr_array[$name] = $value_array; - } - // UGent addition... - foreach ($attr_array as $attr_key => $attr_value) { - if (count($attr_value) > 1) { - $this->_attributes[$attr_key] = $attr_value; - phpCAS::trace("* " . $attr_key . "=" . print_r($attr_value, true)); - } else { - $this->_attributes[$attr_key] = $attr_value[0]; - phpCAS::trace("* " . $attr_key . "=" . $attr_value[0]); - } - } - $result = true; - } else { - phpCAS::trace("SAML Attributes are empty"); - $result = false; - } - } - phpCAS::traceEnd($result); - return $result; - } - - /** @} */ - - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - // XX XX - // XX PROXY FEATURES (CAS 2.0) XX - // XX XX - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - - // ######################################################################## - // PROXYING - // ######################################################################## - /** - * @addtogroup internalProxy - * @{ - */ - - /** - * @var bool is the client a proxy - * A boolean telling if the client is a CAS proxy or not. Written by - * CAS_Client::CAS_Client(), read by CAS_Client::isProxy(). - */ - private $_proxy; - - /** - * @var CAS_CookieJar Handler for managing service cookies. - */ - private $_serviceCookieJar; - - /** - * Tells if a CAS client is a CAS proxy or not - * - * @return bool true when the CAS client is a CAS proxy, false otherwise - */ - public function isProxy() - { - return $this->_proxy; - } - - - /** @} */ - // ######################################################################## - // PGT - // ######################################################################## - /** - * @addtogroup internalProxy - * @{ - */ - - /** - * the Proxy Grnting Ticket given by the CAS server (empty otherwise). - * Written by CAS_Client::_setPGT(), read by CAS_Client::_getPGT() and - * CAS_Client::_hasPGT(). - * - * @hideinitializer - */ - private $_pgt = ''; - - /** - * This method returns the Proxy Granting Ticket given by the CAS server. - * - * @return string the Proxy Granting Ticket. - */ - private function _getPGT() - { - return $this->_pgt; - } - - /** - * This method stores the Proxy Granting Ticket. - * - * @param string $pgt The Proxy Granting Ticket. - * - * @return void - */ - private function _setPGT($pgt) - { - $this->_pgt = $pgt; - } - - /** - * This method tells if a Proxy Granting Ticket was stored. - * - * @return bool true if a Proxy Granting Ticket has been stored. - */ - private function _hasPGT() - { - return !empty($this->_pgt); - } - - /** @} */ - - // ######################################################################## - // CALLBACK MODE - // ######################################################################## - /** - * @addtogroup internalCallback - * @{ - */ - /** - * each PHP script using phpCAS in proxy mode is its own callback to get the - * PGT back from the CAS server. callback_mode is detected by the constructor - * thanks to the GET parameters. - */ - - /** - * @var bool a boolean to know if the CAS client is running in callback mode. Written by - * CAS_Client::setCallBackMode(), read by CAS_Client::_isCallbackMode(). - * - * @hideinitializer - */ - private $_callback_mode = false; - - /** - * This method sets/unsets callback mode. - * - * @param bool $callback_mode true to set callback mode, false otherwise. - * - * @return void - */ - private function _setCallbackMode($callback_mode) - { - $this->_callback_mode = $callback_mode; - } - - /** - * This method returns true when the CAS client is running in callback mode, - * false otherwise. - * - * @return bool A boolean. - */ - private function _isCallbackMode() - { - return $this->_callback_mode; - } - - /** - * @var bool a boolean to know if the CAS client is using POST parameters when in callback mode. - * Written by CAS_Client::_setCallbackModeUsingPost(), read by CAS_Client::_isCallbackModeUsingPost(). - * - * @hideinitializer - */ - private $_callback_mode_using_post = false; - - /** - * This method sets/unsets usage of POST parameters in callback mode (default/false is GET parameters) - * - * @param bool $callback_mode_using_post true to use POST, false to use GET (default). - * - * @return void - */ - private function _setCallbackModeUsingPost($callback_mode_using_post) - { - $this->_callback_mode_using_post = $callback_mode_using_post; - } - - /** - * This method returns true when the callback mode is using POST, false otherwise. - * - * @return bool A boolean. - */ - private function _isCallbackModeUsingPost() - { - return $this->_callback_mode_using_post; - } - - /** - * the URL that should be used for the PGT callback (in fact the URL of the - * current request without any CGI parameter). Written and read by - * CAS_Client::_getCallbackURL(). - * - * @hideinitializer - */ - private $_callback_url = ''; - - /** - * This method returns the URL that should be used for the PGT callback (in - * fact the URL of the current request without any CGI parameter, except if - * phpCAS::setFixedCallbackURL() was used). - * - * @return string The callback URL - */ - private function _getCallbackURL() - { - // the URL is built when needed only - if ( empty($this->_callback_url) ) { - // remove the ticket if present in the URL - $final_uri = $this->getServiceBaseUrl()->get(); - $request_uri = $_SERVER['REQUEST_URI']; - $request_uri = preg_replace('/\?.*$/', '', $request_uri); - $final_uri .= $request_uri; - $this->_callback_url = $final_uri; - } - return $this->_callback_url; - } - - /** - * This method sets the callback url. - * - * @param string $url url to set callback - * - * @return string the callback url - */ - public function setCallbackURL($url) - { - // Sequence validation - $this->ensureIsProxy(); - // Argument Validation - if (gettype($url) != 'string') - throw new CAS_TypeMismatchException($url, '$url', 'string'); - - return $this->_callback_url = $url; - } - - /** - * This method is called by CAS_Client::CAS_Client() when running in callback - * mode. It stores the PGT and its PGT Iou, prints its output and halts. - * - * @return void - */ - private function _callback() - { - phpCAS::traceBegin(); - if ($this->_isCallbackModeUsingPost()) { - $pgtId = $_POST['pgtId']; - $pgtIou = $_POST['pgtIou']; - } else { - $pgtId = $_GET['pgtId']; - $pgtIou = $_GET['pgtIou']; - } - if (preg_match('/^PGTIOU-[\.\-\w]+$/', $pgtIou)) { - if (preg_match('/^[PT]GT-[\.\-\w]+$/', $pgtId)) { - phpCAS::trace('Storing PGT `'.$pgtId.'\' (id=`'.$pgtIou.'\')'); - $this->_storePGT($pgtId, $pgtIou); - if ($this->isXmlResponse()) { - echo '' . "\r\n"; - echo ''; - phpCAS::traceExit("XML response sent"); - } else { - $this->printHTMLHeader('phpCAS callback'); - echo '

Storing PGT `'.$pgtId.'\' (id=`'.$pgtIou.'\').

'; - $this->printHTMLFooter(); - phpCAS::traceExit("HTML response sent"); - } - phpCAS::traceExit("Successfull Callback"); - } else { - phpCAS::error('PGT format invalid' . $pgtId); - phpCAS::traceExit('PGT format invalid' . $pgtId); - } - } else { - phpCAS::error('PGTiou format invalid' . $pgtIou); - phpCAS::traceExit('PGTiou format invalid' . $pgtIou); - } - - // Flush the buffer to prevent from sending anything other then a 200 - // Success Status back to the CAS Server. The Exception would normally - // report as a 500 error. - flush(); - throw new CAS_GracefullTerminationException(); - } - - /** - * Check if application/xml or text/xml is pressent in HTTP_ACCEPT header values - * when return value is complex and contains attached q parameters. - * Example: HTTP_ACCEPT = text/html,application/xhtml+xml,application/xml;q=0.9 - * @return bool - */ - private function isXmlResponse() - { - if (!array_key_exists('HTTP_ACCEPT', $_SERVER)) { - return false; - } - if (strpos($_SERVER['HTTP_ACCEPT'], 'application/xml') === false && strpos($_SERVER['HTTP_ACCEPT'], 'text/xml') === false) { - return false; - } - - return true; - } - - /** @} */ - - // ######################################################################## - // PGT STORAGE - // ######################################################################## - /** - * @addtogroup internalPGTStorage - * @{ - */ - - /** - * @var CAS_PGTStorage_AbstractStorage - * an instance of a class inheriting of PGTStorage, used to deal with PGT - * storage. Created by CAS_Client::setPGTStorageFile(), used - * by CAS_Client::setPGTStorageFile() and CAS_Client::_initPGTStorage(). - * - * @hideinitializer - */ - private $_pgt_storage = null; - - /** - * This method is used to initialize the storage of PGT's. - * Halts on error. - * - * @return void - */ - private function _initPGTStorage() - { - // if no SetPGTStorageXxx() has been used, default to file - if ( !is_object($this->_pgt_storage) ) { - $this->setPGTStorageFile(); - } - - // initializes the storage - $this->_pgt_storage->init(); - } - - /** - * This method stores a PGT. Halts on error. - * - * @param string $pgt the PGT to store - * @param string $pgt_iou its corresponding Iou - * - * @return void - */ - private function _storePGT($pgt,$pgt_iou) - { - // ensure that storage is initialized - $this->_initPGTStorage(); - // writes the PGT - $this->_pgt_storage->write($pgt, $pgt_iou); - } - - /** - * This method reads a PGT from its Iou and deletes the corresponding - * storage entry. - * - * @param string $pgt_iou the PGT Iou - * - * @return string mul The PGT corresponding to the Iou, false when not found. - */ - private function _loadPGT($pgt_iou) - { - // ensure that storage is initialized - $this->_initPGTStorage(); - // read the PGT - return $this->_pgt_storage->read($pgt_iou); - } - - /** - * This method can be used to set a custom PGT storage object. - * - * @param CAS_PGTStorage_AbstractStorage $storage a PGT storage object that - * inherits from the CAS_PGTStorage_AbstractStorage class - * - * @return void - */ - public function setPGTStorage($storage) - { - // Sequence validation - $this->ensureIsProxy(); - - // check that the storage has not already been set - if ( is_object($this->_pgt_storage) ) { - phpCAS::error('PGT storage already defined'); - } - - // check to make sure a valid storage object was specified - if ( !($storage instanceof CAS_PGTStorage_AbstractStorage) ) - throw new CAS_TypeMismatchException($storage, '$storage', 'CAS_PGTStorage_AbstractStorage object'); - - // store the PGTStorage object - $this->_pgt_storage = $storage; - } - - /** - * This method is used to tell phpCAS to store the response of the - * CAS server to PGT requests in a database. - * - * @param string|PDO $dsn_or_pdo a dsn string to use for creating a PDO - * object or a PDO object - * @param string $username the username to use when connecting to the - * database - * @param string $password the password to use when connecting to the - * database - * @param string $table the table to use for storing and retrieving - * PGTs - * @param string $driver_options any driver options to use when connecting - * to the database - * - * @return void - */ - public function setPGTStorageDb( - $dsn_or_pdo, $username='', $password='', $table='', $driver_options=null - ) { - // Sequence validation - $this->ensureIsProxy(); - - // Argument validation - if (!(is_object($dsn_or_pdo) && $dsn_or_pdo instanceof PDO) && !is_string($dsn_or_pdo)) - throw new CAS_TypeMismatchException($dsn_or_pdo, '$dsn_or_pdo', 'string or PDO object'); - if (gettype($username) != 'string') - throw new CAS_TypeMismatchException($username, '$username', 'string'); - if (gettype($password) != 'string') - throw new CAS_TypeMismatchException($password, '$password', 'string'); - if (gettype($table) != 'string') - throw new CAS_TypeMismatchException($table, '$password', 'string'); - - // create the storage object - $this->setPGTStorage( - new CAS_PGTStorage_Db( - $this, $dsn_or_pdo, $username, $password, $table, $driver_options - ) - ); - } - - /** - * This method is used to tell phpCAS to store the response of the - * CAS server to PGT requests onto the filesystem. - * - * @param string $path the path where the PGT's should be stored - * - * @return void - */ - public function setPGTStorageFile($path='') - { - // Sequence validation - $this->ensureIsProxy(); - - // Argument validation - if (gettype($path) != 'string') - throw new CAS_TypeMismatchException($path, '$path', 'string'); - - // create the storage object - $this->setPGTStorage(new CAS_PGTStorage_File($this, $path)); - } - - - // ######################################################################## - // PGT VALIDATION - // ######################################################################## - /** - * This method is used to validate a PGT; halt on failure. - * - * @param string &$validate_url the URL of the request to the CAS server. - * @param string $text_response the response of the CAS server, as is - * (XML text); result of - * CAS_Client::validateCAS10() or - * CAS_Client::validateCAS20(). - * @param DOMElement $tree_response the response of the CAS server, as a DOM XML - * tree; result of CAS_Client::validateCAS10() or CAS_Client::validateCAS20(). - * - * @return bool true when successfull and issue a CAS_AuthenticationException - * and false on an error - * - * @throws CAS_AuthenticationException - */ - private function _validatePGT(&$validate_url,$text_response,$tree_response) - { - phpCAS::traceBegin(); - if ( $tree_response->getElementsByTagName("proxyGrantingTicket")->length == 0) { - phpCAS::trace(' not found'); - // authentication succeded, but no PGT Iou was transmitted - throw new CAS_AuthenticationException( - $this, 'Ticket validated but no PGT Iou transmitted', - $validate_url, false/*$no_response*/, false/*$bad_response*/, - $text_response - ); - } else { - // PGT Iou transmitted, extract it - $pgt_iou = trim( - $tree_response->getElementsByTagName("proxyGrantingTicket")->item(0)->nodeValue - ); - if (preg_match('/^PGTIOU-[\.\-\w]+$/', $pgt_iou)) { - $pgt = $this->_loadPGT($pgt_iou); - if ( $pgt == false ) { - phpCAS::trace('could not load PGT'); - throw new CAS_AuthenticationException( - $this, - 'PGT Iou was transmitted but PGT could not be retrieved', - $validate_url, false/*$no_response*/, - false/*$bad_response*/, $text_response - ); - } - $this->_setPGT($pgt); - } else { - phpCAS::trace('PGTiou format error'); - throw new CAS_AuthenticationException( - $this, 'PGT Iou was transmitted but has wrong format', - $validate_url, false/*$no_response*/, false/*$bad_response*/, - $text_response - ); - } - } - phpCAS::traceEnd(true); - return true; - } - - // ######################################################################## - // PGT VALIDATION - // ######################################################################## - - /** - * This method is used to retrieve PT's from the CAS server thanks to a PGT. - * - * @param string $target_service the service to ask for with the PT. - * @param int &$err_code an error code (PHPCAS_SERVICE_OK on success). - * @param string &$err_msg an error message (empty on success). - * - * @return string|false a Proxy Ticket, or false on error. - */ - public function retrievePT($target_service,&$err_code,&$err_msg) - { - // Argument validation - if (gettype($target_service) != 'string') - throw new CAS_TypeMismatchException($target_service, '$target_service', 'string'); - - phpCAS::traceBegin(); - - // by default, $err_msg is set empty and $pt to true. On error, $pt is - // set to false and $err_msg to an error message. At the end, if $pt is false - // and $error_msg is still empty, it is set to 'invalid response' (the most - // commonly encountered error). - $err_msg = ''; - - // build the URL to retrieve the PT - $cas_url = $this->getServerProxyURL().'?targetService=' - .urlencode($target_service).'&pgt='.$this->_getPGT(); - - $headers = ''; - $cas_response = ''; - // open and read the URL - if ( !$this->_readURL($cas_url, $headers, $cas_response, $err_msg) ) { - phpCAS::trace( - 'could not open URL \''.$cas_url.'\' to validate ('.$err_msg.')' - ); - $err_code = PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE; - $err_msg = 'could not retrieve PT (no response from the CAS server)'; - phpCAS::traceEnd(false); - return false; - } - - $bad_response = false; - - // create new DOMDocument object - $dom = new DOMDocument(); - // Fix possible whitspace problems - $dom->preserveWhiteSpace = false; - // read the response of the CAS server into a DOM object - if ( !($dom->loadXML($cas_response))) { - phpCAS::trace('dom->loadXML() failed'); - // read failed - $bad_response = true; - } - - if ( !$bad_response ) { - // read the root node of the XML tree - if ( !($root = $dom->documentElement) ) { - phpCAS::trace('documentElement failed'); - // read failed - $bad_response = true; - } - } - - if ( !$bad_response ) { - // insure that tag name is 'serviceResponse' - if ( $root->localName != 'serviceResponse' ) { - phpCAS::trace('localName failed'); - // bad root node - $bad_response = true; - } - } - - if ( !$bad_response ) { - // look for a proxySuccess tag - if ( $root->getElementsByTagName("proxySuccess")->length != 0) { - $proxy_success_list = $root->getElementsByTagName("proxySuccess"); - - // authentication succeded, look for a proxyTicket tag - if ( $proxy_success_list->item(0)->getElementsByTagName("proxyTicket")->length != 0) { - $err_code = PHPCAS_SERVICE_OK; - $err_msg = ''; - $pt = trim( - $proxy_success_list->item(0)->getElementsByTagName("proxyTicket")->item(0)->nodeValue - ); - phpCAS::trace('original PT: '.trim($pt)); - phpCAS::traceEnd($pt); - return $pt; - } else { - phpCAS::trace(' was found, but not '); - } - } else if ($root->getElementsByTagName("proxyFailure")->length != 0) { - // look for a proxyFailure tag - $proxy_failure_list = $root->getElementsByTagName("proxyFailure"); - - // authentication failed, extract the error - $err_code = PHPCAS_SERVICE_PT_FAILURE; - $err_msg = 'PT retrieving failed (code=`' - .$proxy_failure_list->item(0)->getAttribute('code') - .'\', message=`' - .trim($proxy_failure_list->item(0)->nodeValue) - .'\')'; - phpCAS::traceEnd(false); - return false; - } else { - phpCAS::trace('neither nor found'); - } - } - - // at this step, we are sure that the response of the CAS server was - // illformed - $err_code = PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE; - $err_msg = 'Invalid response from the CAS server (response=`' - .$cas_response.'\')'; - - phpCAS::traceEnd(false); - return false; - } - - /** @} */ - - // ######################################################################## - // READ CAS SERVER ANSWERS - // ######################################################################## - - /** - * @addtogroup internalMisc - * @{ - */ - - /** - * This method is used to acces a remote URL. - * - * @param string $url the URL to access. - * @param string &$headers an array containing the HTTP header lines of the - * response (an empty array on failure). - * @param string &$body the body of the response, as a string (empty on - * failure). - * @param string &$err_msg an error message, filled on failure. - * - * @return bool true on success, false otherwise (in this later case, $err_msg - * contains an error message). - */ - private function _readURL($url, &$headers, &$body, &$err_msg) - { - phpCAS::traceBegin(); - $className = $this->_requestImplementation; - $request = new $className(); - - if (count($this->_curl_options)) { - $request->setCurlOptions($this->_curl_options); - } - - $request->setUrl($url); - - if (empty($this->_cas_server_ca_cert) && !$this->_no_cas_server_validation) { - phpCAS::error( - 'one of the methods phpCAS::setCasServerCACert() or phpCAS::setNoCasServerValidation() must be called.' - ); - } - if ($this->_cas_server_ca_cert != '') { - $request->setSslCaCert( - $this->_cas_server_ca_cert, $this->_cas_server_cn_validate - ); - } - - // add extra stuff if SAML - if ($this->getServerVersion() == SAML_VERSION_1_1) { - $request->addHeader("soapaction: http://www.oasis-open.org/committees/security"); - $request->addHeader("cache-control: no-cache"); - $request->addHeader("pragma: no-cache"); - $request->addHeader("accept: text/xml"); - $request->addHeader("connection: keep-alive"); - $request->addHeader("content-type: text/xml"); - $request->makePost(); - $request->setPostBody($this->_buildSAMLPayload()); - } - - if ($request->send()) { - $headers = $request->getResponseHeaders(); - $body = $request->getResponseBody(); - $err_msg = ''; - phpCAS::traceEnd(true); - return true; - } else { - $headers = ''; - $body = ''; - $err_msg = $request->getErrorMessage(); - phpCAS::traceEnd(false); - return false; - } - } - - /** - * This method is used to build the SAML POST body sent to /samlValidate URL. - * - * @return string the SOAP-encased SAMLP artifact (the ticket). - */ - private function _buildSAMLPayload() - { - phpCAS::traceBegin(); - - //get the ticket - $sa = urlencode($this->getTicket()); - - $body = SAML_SOAP_ENV.SAML_SOAP_BODY.SAMLP_REQUEST - .SAML_ASSERTION_ARTIFACT.$sa.SAML_ASSERTION_ARTIFACT_CLOSE - .SAMLP_REQUEST_CLOSE.SAML_SOAP_BODY_CLOSE.SAML_SOAP_ENV_CLOSE; - - phpCAS::traceEnd($body); - return ($body); - } - - /** @} **/ - - // ######################################################################## - // ACCESS TO EXTERNAL SERVICES - // ######################################################################## - - /** - * @addtogroup internalProxyServices - * @{ - */ - - - /** - * Answer a proxy-authenticated service handler. - * - * @param string $type The service type. One of: - * PHPCAS_PROXIED_SERVICE_HTTP_GET, PHPCAS_PROXIED_SERVICE_HTTP_POST, - * PHPCAS_PROXIED_SERVICE_IMAP - * - * @return CAS_ProxiedService - * @throws InvalidArgumentException If the service type is unknown. - */ - public function getProxiedService ($type) - { - // Sequence validation - $this->ensureIsProxy(); - $this->ensureAuthenticationCallSuccessful(); - - // Argument validation - if (gettype($type) != 'string') - throw new CAS_TypeMismatchException($type, '$type', 'string'); - - switch ($type) { - case PHPCAS_PROXIED_SERVICE_HTTP_GET: - case PHPCAS_PROXIED_SERVICE_HTTP_POST: - $requestClass = $this->_requestImplementation; - $request = new $requestClass(); - if (count($this->_curl_options)) { - $request->setCurlOptions($this->_curl_options); - } - $proxiedService = new $type($request, $this->_serviceCookieJar); - if ($proxiedService instanceof CAS_ProxiedService_Testable) { - $proxiedService->setCasClient($this); - } - return $proxiedService; - case PHPCAS_PROXIED_SERVICE_IMAP; - $proxiedService = new CAS_ProxiedService_Imap($this->_getUser()); - if ($proxiedService instanceof CAS_ProxiedService_Testable) { - $proxiedService->setCasClient($this); - } - return $proxiedService; - default: - throw new CAS_InvalidArgumentException( - "Unknown proxied-service type, $type." - ); - } - } - - /** - * Initialize a proxied-service handler with the proxy-ticket it should use. - * - * @param CAS_ProxiedService $proxiedService service handler - * - * @return void - * - * @throws CAS_ProxyTicketException If there is a proxy-ticket failure. - * The code of the Exception will be one of: - * PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE - * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE - * PHPCAS_SERVICE_PT_FAILURE - * @throws CAS_ProxiedService_Exception If there is a failure getting the - * url from the proxied service. - */ - public function initializeProxiedService (CAS_ProxiedService $proxiedService) - { - // Sequence validation - $this->ensureIsProxy(); - $this->ensureAuthenticationCallSuccessful(); - - $url = $proxiedService->getServiceUrl(); - if (!is_string($url)) { - throw new CAS_ProxiedService_Exception( - "Proxied Service ".get_class($proxiedService) - ."->getServiceUrl() should have returned a string, returned a " - .gettype($url)." instead." - ); - } - $pt = $this->retrievePT($url, $err_code, $err_msg); - if (!$pt) { - throw new CAS_ProxyTicketException($err_msg, $err_code); - } - $proxiedService->setProxyTicket($pt); - } - - /** - * This method is used to access an HTTP[S] service. - * - * @param string $url the service to access. - * @param int &$err_code an error code Possible values are - * PHPCAS_SERVICE_OK (on success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, - * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE, PHPCAS_SERVICE_PT_FAILURE, - * PHPCAS_SERVICE_NOT_AVAILABLE. - * @param string &$output the output of the service (also used to give an error - * message on failure). - * - * @return bool true on success, false otherwise (in this later case, $err_code - * gives the reason why it failed and $output contains an error message). - */ - public function serviceWeb($url,&$err_code,&$output) - { - // Sequence validation - $this->ensureIsProxy(); - $this->ensureAuthenticationCallSuccessful(); - - // Argument validation - if (gettype($url) != 'string') - throw new CAS_TypeMismatchException($url, '$url', 'string'); - - try { - $service = $this->getProxiedService(PHPCAS_PROXIED_SERVICE_HTTP_GET); - $service->setUrl($url); - $service->send(); - $output = $service->getResponseBody(); - $err_code = PHPCAS_SERVICE_OK; - return true; - } catch (CAS_ProxyTicketException $e) { - $err_code = $e->getCode(); - $output = $e->getMessage(); - return false; - } catch (CAS_ProxiedService_Exception $e) { - $lang = $this->getLangObj(); - $output = sprintf( - $lang->getServiceUnavailable(), $url, $e->getMessage() - ); - $err_code = PHPCAS_SERVICE_NOT_AVAILABLE; - return false; - } - } - - /** - * This method is used to access an IMAP/POP3/NNTP service. - * - * @param string $url a string giving the URL of the service, including - * the mailing box for IMAP URLs, as accepted by imap_open(). - * @param string $serviceUrl a string giving for CAS retrieve Proxy ticket - * @param string $flags options given to imap_open(). - * @param int &$err_code an error code Possible values are - * PHPCAS_SERVICE_OK (on success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, - * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE, PHPCAS_SERVICE_PT_FAILURE, - * PHPCAS_SERVICE_NOT_AVAILABLE. - * @param string &$err_msg an error message on failure - * @param string &$pt the Proxy Ticket (PT) retrieved from the CAS - * server to access the URL on success, false on error). - * - * @return object|false an IMAP stream on success, false otherwise (in this later - * case, $err_code gives the reason why it failed and $err_msg contains an - * error message). - */ - public function serviceMail($url,$serviceUrl,$flags,&$err_code,&$err_msg,&$pt) - { - // Sequence validation - $this->ensureIsProxy(); - $this->ensureAuthenticationCallSuccessful(); - - // Argument validation - if (gettype($url) != 'string') - throw new CAS_TypeMismatchException($url, '$url', 'string'); - if (gettype($serviceUrl) != 'string') - throw new CAS_TypeMismatchException($serviceUrl, '$serviceUrl', 'string'); - if (gettype($flags) != 'integer') - throw new CAS_TypeMismatchException($flags, '$flags', 'string'); - - try { - $service = $this->getProxiedService(PHPCAS_PROXIED_SERVICE_IMAP); - $service->setServiceUrl($serviceUrl); - $service->setMailbox($url); - $service->setOptions($flags); - - $stream = $service->open(); - $err_code = PHPCAS_SERVICE_OK; - $pt = $service->getImapProxyTicket(); - return $stream; - } catch (CAS_ProxyTicketException $e) { - $err_msg = $e->getMessage(); - $err_code = $e->getCode(); - $pt = false; - return false; - } catch (CAS_ProxiedService_Exception $e) { - $lang = $this->getLangObj(); - $err_msg = sprintf( - $lang->getServiceUnavailable(), - $url, - $e->getMessage() - ); - $err_code = PHPCAS_SERVICE_NOT_AVAILABLE; - $pt = false; - return false; - } - } - - /** @} **/ - - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - // XX XX - // XX PROXIED CLIENT FEATURES (CAS 2.0) XX - // XX XX - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - - // ######################################################################## - // PT - // ######################################################################## - /** - * @addtogroup internalService - * @{ - */ - - /** - * This array will store a list of proxies in front of this application. This - * property will only be populated if this script is being proxied rather than - * accessed directly. - * - * It is set in CAS_Client::validateCAS20() and can be read by - * CAS_Client::getProxies() - * - * @access private - */ - private $_proxies = array(); - - /** - * Answer an array of proxies that are sitting in front of this application. - * - * This method will only return a non-empty array if we have received and - * validated a Proxy Ticket. - * - * @return array - * @access public - */ - public function getProxies() - { - return $this->_proxies; - } - - /** - * Set the Proxy array, probably from persistant storage. - * - * @param array $proxies An array of proxies - * - * @return void - * @access private - */ - private function _setProxies($proxies) - { - $this->_proxies = $proxies; - if (!empty($proxies)) { - // For proxy-authenticated requests people are not viewing the URL - // directly since the client is another application making a - // web-service call. - // Because of this, stripping the ticket from the URL is unnecessary - // and causes another web-service request to be performed. Additionally, - // if session handling on either the client or the server malfunctions - // then the subsequent request will not complete successfully. - $this->setNoClearTicketsFromUrl(); - } - } - - /** - * A container of patterns to be allowed as proxies in front of the cas client. - * - * @var CAS_ProxyChain_AllowedList - */ - private $_allowed_proxy_chains; - - /** - * Answer the CAS_ProxyChain_AllowedList object for this client. - * - * @return CAS_ProxyChain_AllowedList - */ - public function getAllowedProxyChains () - { - if (empty($this->_allowed_proxy_chains)) { - $this->_allowed_proxy_chains = new CAS_ProxyChain_AllowedList(); - } - return $this->_allowed_proxy_chains; - } - - /** @} */ - // ######################################################################## - // PT VALIDATION - // ######################################################################## - /** - * @addtogroup internalProxied - * @{ - */ - - /** - * This method is used to validate a cas 2.0 ST or PT; halt on failure - * Used for all CAS 2.0 validations - * - * @param string &$validate_url the url of the reponse - * @param string &$text_response the text of the repsones - * @param DOMElement &$tree_response the domxml tree of the respones - * @param bool $renew true to force the authentication with the CAS server - * - * @return bool true when successfull and issue a CAS_AuthenticationException - * and false on an error - * - * @throws CAS_AuthenticationException - */ - public function validateCAS20(&$validate_url,&$text_response,&$tree_response, $renew=false) - { - phpCAS::traceBegin(); - phpCAS::trace($text_response); - // build the URL to validate the ticket - if ($this->getAllowedProxyChains()->isProxyingAllowed()) { - $validate_url = $this->getServerProxyValidateURL().'&ticket=' - .urlencode($this->getTicket()); - } else { - $validate_url = $this->getServerServiceValidateURL().'&ticket=' - .urlencode($this->getTicket()); - } - - if ( $this->isProxy() ) { - // pass the callback url for CAS proxies - $validate_url .= '&pgtUrl='.urlencode($this->_getCallbackURL()); - } - - if ( $renew ) { - // pass the renew - $validate_url .= '&renew=true'; - } - - // open and read the URL - if ( !$this->_readURL($validate_url, $headers, $text_response, $err_msg) ) { - phpCAS::trace( - 'could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')' - ); - throw new CAS_AuthenticationException( - $this, 'Ticket not validated', $validate_url, - true/*$no_response*/ - ); - } - - // create new DOMDocument object - $dom = new DOMDocument(); - // Fix possible whitspace problems - $dom->preserveWhiteSpace = false; - // CAS servers should only return data in utf-8 - $dom->encoding = "utf-8"; - // read the response of the CAS server into a DOMDocument object - if ( !($dom->loadXML($text_response))) { - // read failed - throw new CAS_AuthenticationException( - $this, 'Ticket not validated', $validate_url, - false/*$no_response*/, true/*$bad_response*/, $text_response - ); - } else if ( !($tree_response = $dom->documentElement) ) { - // read the root node of the XML tree - // read failed - throw new CAS_AuthenticationException( - $this, 'Ticket not validated', $validate_url, - false/*$no_response*/, true/*$bad_response*/, $text_response - ); - } else if ($tree_response->localName != 'serviceResponse') { - // insure that tag name is 'serviceResponse' - // bad root node - throw new CAS_AuthenticationException( - $this, 'Ticket not validated', $validate_url, - false/*$no_response*/, true/*$bad_response*/, $text_response - ); - } else if ( $tree_response->getElementsByTagName("authenticationFailure")->length != 0) { - // authentication failed, extract the error code and message and throw exception - $auth_fail_list = $tree_response - ->getElementsByTagName("authenticationFailure"); - throw new CAS_AuthenticationException( - $this, 'Ticket not validated', $validate_url, - false/*$no_response*/, false/*$bad_response*/, - $text_response, - $auth_fail_list->item(0)->getAttribute('code')/*$err_code*/, - trim($auth_fail_list->item(0)->nodeValue)/*$err_msg*/ - ); - } else if ($tree_response->getElementsByTagName("authenticationSuccess")->length != 0) { - // authentication succeded, extract the user name - $success_elements = $tree_response - ->getElementsByTagName("authenticationSuccess"); - if ( $success_elements->item(0)->getElementsByTagName("user")->length == 0) { - // no user specified => error - throw new CAS_AuthenticationException( - $this, 'Ticket not validated', $validate_url, - false/*$no_response*/, true/*$bad_response*/, $text_response - ); - } else { - $this->_setUser( - trim( - $success_elements->item(0)->getElementsByTagName("user")->item(0)->nodeValue - ) - ); - $this->_readExtraAttributesCas20($success_elements); - // Store the proxies we are sitting behind for authorization checking - $proxyList = array(); - if ( sizeof($arr = $success_elements->item(0)->getElementsByTagName("proxy")) > 0) { - foreach ($arr as $proxyElem) { - phpCAS::trace("Found Proxy: ".$proxyElem->nodeValue); - $proxyList[] = trim($proxyElem->nodeValue); - } - $this->_setProxies($proxyList); - phpCAS::trace("Storing Proxy List"); - } - // Check if the proxies in front of us are allowed - if (!$this->getAllowedProxyChains()->isProxyListAllowed($proxyList)) { - throw new CAS_AuthenticationException( - $this, 'Proxy not allowed', $validate_url, - false/*$no_response*/, true/*$bad_response*/, - $text_response - ); - } else { - $result = true; - } - } - } else { - throw new CAS_AuthenticationException( - $this, 'Ticket not validated', $validate_url, - false/*$no_response*/, true/*$bad_response*/, - $text_response - ); - } - - $this->_renameSession($this->getTicket()); - - // at this step, Ticket has been validated and $this->_user has been set, - - phpCAS::traceEnd($result); - return $result; - } - - /** - * This method recursively parses the attribute XML. - * It also collapses name-value pairs into a single - * array entry. It parses all common formats of - * attributes and well formed XML files. - * - * @param string $root the DOM root element to be parsed - * @param string $namespace namespace of the elements - * - * @return an array of the parsed XML elements - * - * Formats tested: - * - * "Jasig Style" Attributes: - * - * - * - * jsmith - * - * RubyCAS - * Smith - * John - * CN=Staff,OU=Groups,DC=example,DC=edu - * CN=Spanish Department,OU=Departments,OU=Groups,DC=example,DC=edu - * - * PGTIOU-84678-8a9d2sfa23casd - * - * - * - * "Jasig Style" Attributes (longer version): - * - * - * - * jsmith - * - * - * surname - * Smith - * - * - * givenName - * John - * - * - * memberOf - * ['CN=Staff,OU=Groups,DC=example,DC=edu', 'CN=Spanish Department,OU=Departments,OU=Groups,DC=example,DC=edu'] - * - * - * PGTIOU-84678-8a9d2sfa23casd - * - * - * - * "RubyCAS Style" attributes - * - * - * - * jsmith - * - * RubyCAS - * Smith - * John - * CN=Staff,OU=Groups,DC=example,DC=edu - * CN=Spanish Department,OU=Departments,OU=Groups,DC=example,DC=edu - * - * PGTIOU-84678-8a9d2sfa23casd - * - * - * - * "Name-Value" attributes. - * - * Attribute format from these mailing list thread: - * http://jasig.275507.n4.nabble.com/CAS-attributes-and-how-they-appear-in-the-CAS-response-td264272.html - * Note: This is a less widely used format, but in use by at least two institutions. - * - * - * - * jsmith - * - * - * - * - * - * - * - * PGTIOU-84678-8a9d2sfa23casd - * - * - * - * result: - * - * Array ( - * [surname] => Smith - * [givenName] => John - * [memberOf] => Array ( - * [0] => CN=Staff, OU=Groups, DC=example, DC=edu - * [1] => CN=Spanish Department, OU=Departments, OU=Groups, DC=example, DC=edu - * ) - * ) - */ - private function _xml_to_array($root, $namespace = "cas") - { - $result = array(); - if ($root->hasAttributes()) { - $attrs = $root->attributes; - $pair = array(); - foreach ($attrs as $attr) { - if ($attr->name === "name") { - $pair['name'] = $attr->value; - } elseif ($attr->name === "value") { - $pair['value'] = $attr->value; - } else { - $result[$attr->name] = $attr->value; - } - if (array_key_exists('name', $pair) && array_key_exists('value', $pair)) { - $result[$pair['name']] = $pair['value']; - } - } - } - if ($root->hasChildNodes()) { - $children = $root->childNodes; - if ($children->length == 1) { - $child = $children->item(0); - if ($child->nodeType == XML_TEXT_NODE) { - $result['_value'] = $child->nodeValue; - return (count($result) == 1) ? $result['_value'] : $result; - } - } - $groups = array(); - foreach ($children as $child) { - $child_nodeName = str_ireplace($namespace . ":", "", $child->nodeName); - if (in_array($child_nodeName, array("user", "proxies", "proxyGrantingTicket"))) { - continue; - } - if (!isset($result[$child_nodeName])) { - $res = $this->_xml_to_array($child, $namespace); - if (!empty($res)) { - $result[$child_nodeName] = $this->_xml_to_array($child, $namespace); - } - } else { - if (!isset($groups[$child_nodeName])) { - $result[$child_nodeName] = array($result[$child_nodeName]); - $groups[$child_nodeName] = 1; - } - $result[$child_nodeName][] = $this->_xml_to_array($child, $namespace); - } - } - } - return $result; - } - - /** - * This method parses a "JSON-like array" of strings - * into an array of strings - * - * @param string $json_value the json-like string: - * e.g.: - * ['CN=Staff,OU=Groups,DC=example,DC=edu', 'CN=Spanish Department,OU=Departments,OU=Groups,DC=example,DC=edu'] - * - * @return array of strings Description - * e.g.: - * Array ( - * [0] => CN=Staff,OU=Groups,DC=example,DC=edu - * [1] => CN=Spanish Department,OU=Departments,OU=Groups,DC=example,DC=edu - * ) - */ - private function _parse_json_like_array_value($json_value) - { - $parts = explode(",", trim($json_value, "[]")); - $out = array(); - $quote = ''; - foreach ($parts as $part) { - $part = trim($part); - if ($quote === '') { - $value = ""; - if ($this->_startsWith($part, '\'')) { - $quote = '\''; - } elseif ($this->_startsWith($part, '"')) { - $quote = '"'; - } else { - $out[] = $part; - } - $part = ltrim($part, $quote); - } - if ($quote !== '') { - $value .= $part; - if ($this->_endsWith($part, $quote)) { - $out[] = rtrim($value, $quote); - $quote = ''; - } else { - $value .= ", "; - }; - } - } - return $out; - } - - /** - * This method recursively removes unneccessary hirarchy levels in array-trees. - * into an array of strings - * - * @param array $arr the array to flatten - * e.g.: - * Array ( - * [attributes] => Array ( - * [attribute] => Array ( - * [0] => Array ( - * [name] => surname - * [value] => Smith - * ) - * [1] => Array ( - * [name] => givenName - * [value] => John - * ) - * [2] => Array ( - * [name] => memberOf - * [value] => ['CN=Staff,OU=Groups,DC=example,DC=edu', 'CN=Spanish Department,OU=Departments,OU=Groups,DC=example,DC=edu'] - * ) - * ) - * ) - * ) - * - * @return array the flattened array - * e.g.: - * Array ( - * [attribute] => Array ( - * [surname] => Smith - * [givenName] => John - * [memberOf] => Array ( - * [0] => CN=Staff, OU=Groups, DC=example, DC=edu - * [1] => CN=Spanish Department, OU=Departments, OU=Groups, DC=example, DC=edu - * ) - * ) - * ) - */ - private function _flatten_array($arr) - { - if (!is_array($arr)) { - if ($this->_startsWith($arr, '[') && $this->_endsWith($arr, ']')) { - return $this->_parse_json_like_array_value($arr); - } else { - return $arr; - } - } - $out = array(); - foreach ($arr as $key => $val) { - if (!is_array($val)) { - $out[$key] = $val; - } else { - switch (count($val)) { - case 1 : { - $key = key($val); - if (array_key_exists($key, $out)) { - $value = $out[$key]; - if (!is_array($value)) { - $out[$key] = array(); - $out[$key][] = $value; - } - $out[$key][] = $this->_flatten_array($val[$key]); - } else { - $out[$key] = $this->_flatten_array($val[$key]); - }; - break; - }; - case 2 : { - if (array_key_exists("name", $val) && array_key_exists("value", $val)) { - $key = $val['name']; - if (array_key_exists($key, $out)) { - $value = $out[$key]; - if (!is_array($value)) { - $out[$key] = array(); - $out[$key][] = $value; - } - $out[$key][] = $this->_flatten_array($val['value']); - } else { - $out[$key] = $this->_flatten_array($val['value']); - }; - } else { - $out[$key] = $this->_flatten_array($val); - } - break; - }; - default: { - $out[$key] = $this->_flatten_array($val); - } - } - } - } - return $out; - } - - /** - * This method will parse the DOM and pull out the attributes from the XML - * payload and put them into an array, then put the array into the session. - * - * @param DOMNodeList $success_elements payload of the response - * - * @return bool true when successfull, halt otherwise by calling - * CAS_Client::_authError(). - */ - private function _readExtraAttributesCas20($success_elements) - { - phpCAS::traceBegin(); - - $extra_attributes = array(); - if ($this->_casAttributeParserCallbackFunction !== null - && is_callable($this->_casAttributeParserCallbackFunction) - ) { - array_unshift($this->_casAttributeParserCallbackArgs, $success_elements->item(0)); - phpCAS :: trace("Calling attritubeParser callback"); - $extra_attributes = call_user_func_array( - $this->_casAttributeParserCallbackFunction, - $this->_casAttributeParserCallbackArgs - ); - } else { - phpCAS :: trace("Parse extra attributes: "); - $attributes = $this->_xml_to_array($success_elements->item(0)); - phpCAS :: trace(print_r($attributes,true). "\nFLATTEN Array: "); - $extra_attributes = $this->_flatten_array($attributes); - phpCAS :: trace(print_r($extra_attributes, true)."\nFILTER : "); - if (array_key_exists("attribute", $extra_attributes)) { - $extra_attributes = $extra_attributes["attribute"]; - } elseif (array_key_exists("attributes", $extra_attributes)) { - $extra_attributes = $extra_attributes["attributes"]; - }; - phpCAS :: trace(print_r($extra_attributes, true)."return"); - } - $this->setAttributes($extra_attributes); - phpCAS::traceEnd(); - return true; - } - - /** - * Add an attribute value to an array of attributes. - * - * @param array &$attributeArray reference to array - * @param string $name name of attribute - * @param string $value value of attribute - * - * @return void - */ - private function _addAttributeToArray(array &$attributeArray, $name, $value) - { - // If multiple attributes exist, add as an array value - if (isset($attributeArray[$name])) { - // Initialize the array with the existing value - if (!is_array($attributeArray[$name])) { - $existingValue = $attributeArray[$name]; - $attributeArray[$name] = array($existingValue); - } - - $attributeArray[$name][] = trim($value); - } else { - $attributeArray[$name] = trim($value); - } - } - - /** @} */ - - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - // XX XX - // XX MISC XX - // XX XX - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - - /** - * @addtogroup internalMisc - * @{ - */ - - // ######################################################################## - // URL - // ######################################################################## - /** - * the URL of the current request (without any ticket CGI parameter). Written - * and read by CAS_Client::getURL(). - * - * @hideinitializer - */ - private $_url = ''; - - - /** - * This method sets the URL of the current request - * - * @param string $url url to set for service - * - * @return void - */ - public function setURL($url) - { - // Argument Validation - if (gettype($url) != 'string') - throw new CAS_TypeMismatchException($url, '$url', 'string'); - - $this->_url = $url; - } - - /** - * This method returns the URL of the current request (without any ticket - * CGI parameter). - * - * @return string The URL - */ - public function getURL() - { - phpCAS::traceBegin(); - // the URL is built when needed only - if ( empty($this->_url) ) { - // remove the ticket if present in the URL - $final_uri = $this->getServiceBaseUrl()->get(); - $request_uri = explode('?', $_SERVER['REQUEST_URI'], 2); - $final_uri .= $request_uri[0]; - - if (isset($request_uri[1]) && $request_uri[1]) { - $query_string= $this->_removeParameterFromQueryString('ticket', $request_uri[1]); - - // If the query string still has anything left, - // append it to the final URI - if ($query_string !== '') { - $final_uri .= "?$query_string"; - } - } - - phpCAS::trace("Final URI: $final_uri"); - $this->setURL($final_uri); - } - phpCAS::traceEnd($this->_url); - return $this->_url; - } - - /** - * This method sets the base URL of the CAS server. - * - * @param string $url the base URL - * - * @return string base url - */ - public function setBaseURL($url) - { - // Argument Validation - if (gettype($url) != 'string') - throw new CAS_TypeMismatchException($url, '$url', 'string'); - - return $this->_server['base_url'] = $url; - } - - /** - * The ServiceBaseUrl object that provides base URL during service URL - * discovery process. - * - * @var CAS_ServiceBaseUrl_Interface - * - * @hideinitializer - */ - private $_serviceBaseUrl = null; - - /** - * Answer the CAS_ServiceBaseUrl_Interface object for this client. - * - * @return CAS_ServiceBaseUrl_Interface - */ - public function getServiceBaseUrl() - { - if (empty($this->_serviceBaseUrl)) { - phpCAS::error("ServiceBaseUrl object is not initialized"); - } - return $this->_serviceBaseUrl; - } - - /** - * This method sets the service base URL used during service URL discovery process. - * - * This is required since phpCAS 1.6.0 to protect the integrity of the authentication. - * - * @since phpCAS 1.6.0 - * - * @param $name can be any of the following: - * - A base URL string. The service URL discovery will always use this (protocol, - * hostname and optional port number) without using any external host names. - * - An array of base URL strings. The service URL discovery will check against - * this list before using the auto discovered base URL. If there is no match, - * the first base URL in the array will be used as the default. This option is - * helpful if your PHP website is accessible through multiple domains without a - * canonical name, or through both HTTP and HTTPS. - * - A class that implements CAS_ServiceBaseUrl_Interface. If you need to customize - * the base URL discovery behavior, you can pass in a class that implements the - * interface. - * - * @return void - */ - private function _setServiceBaseUrl($name) - { - if (is_array($name)) { - $this->_serviceBaseUrl = new CAS_ServiceBaseUrl_AllowedListDiscovery($name); - } else if (is_string($name)) { - $this->_serviceBaseUrl = new CAS_ServiceBaseUrl_Static($name); - } else if ($name instanceof CAS_ServiceBaseUrl_Interface) { - $this->_serviceBaseUrl = $name; - } else { - throw new CAS_TypeMismatchException($name, '$name', 'array, string, or CAS_ServiceBaseUrl_Interface object'); - } - } - - /** - * Removes a parameter from a query string - * - * @param string $parameterName name of parameter - * @param string $queryString query string - * - * @return string new query string - * - * @link http://stackoverflow.com/questions/1842681/regular-expression-to-remove-one-parameter-from-query-string - */ - private function _removeParameterFromQueryString($parameterName, $queryString) - { - $parameterName = preg_quote($parameterName); - return preg_replace( - "/&$parameterName(=[^&]*)?|^$parameterName(=[^&]*)?&?/", - '', $queryString - ); - } - - /** - * This method is used to append query parameters to an url. Since the url - * might already contain parameter it has to be detected and to build a proper - * URL - * - * @param string $url base url to add the query params to - * @param string $query params in query form with & separated - * - * @return string url with query params - */ - private function _buildQueryUrl($url, $query) - { - $url .= (strstr($url, '?') === false) ? '?' : '&'; - $url .= $query; - return $url; - } - - /** - * This method tests if a string starts with a given character. - * - * @param string $text text to test - * @param string $char character to test for - * - * @return bool true if the $text starts with $char - */ - private function _startsWith($text, $char) - { - return (strpos($text, $char) === 0); - } - - /** - * This method tests if a string ends with a given character - * - * @param string $text text to test - * @param string $char character to test for - * - * @return bool true if the $text ends with $char - */ - private function _endsWith($text, $char) - { - return (strpos(strrev($text), $char) === 0); - } - - /** - * Answer a valid session-id given a CAS ticket. - * - * The output must be deterministic to allow single-log-out when presented with - * the ticket to log-out. - * - * - * @param string $ticket name of the ticket - * - * @return string - */ - private function _sessionIdForTicket($ticket) - { - // Hash the ticket to ensure that the value meets the PHP 7.1 requirement - // that session-ids have a length between 22 and 256 characters. - return hash('sha256', $this->_sessionIdSalt . $ticket); - } - - /** - * Set a salt/seed for the session-id hash to make it harder to guess. - * - * @var string $_sessionIdSalt - */ - private $_sessionIdSalt = ''; - - /** - * Set a salt/seed for the session-id hash to make it harder to guess. - * - * @param string $salt - * - * @return void - */ - public function setSessionIdSalt($salt) { - $this->_sessionIdSalt = (string)$salt; - } - - // ######################################################################## - // AUTHENTICATION ERROR HANDLING - // ######################################################################## - /** - * This method is used to print the HTML output when the user was not - * authenticated. - * - * @param string $failure the failure that occured - * @param string $cas_url the URL the CAS server was asked for - * @param bool $no_response the response from the CAS server (other - * parameters are ignored if true) - * @param bool $bad_response bad response from the CAS server ($err_code - * and $err_msg ignored if true) - * @param string $cas_response the response of the CAS server - * @param int $err_code the error code given by the CAS server - * @param string $err_msg the error message given by the CAS server - * - * @return void - */ - private function _authError( - $failure, - $cas_url, - $no_response=false, - $bad_response=false, - $cas_response='', - $err_code=-1, - $err_msg='' - ) { - phpCAS::traceBegin(); - $lang = $this->getLangObj(); - $this->printHTMLHeader($lang->getAuthenticationFailed()); - $this->printf( - $lang->getYouWereNotAuthenticated(), htmlentities($this->getURL()), - isset($_SERVER['SERVER_ADMIN']) ? $_SERVER['SERVER_ADMIN']:'' - ); - phpCAS::trace('CAS URL: '.$cas_url); - phpCAS::trace('Authentication failure: '.$failure); - if ( $no_response ) { - phpCAS::trace('Reason: no response from the CAS server'); - } else { - if ( $bad_response ) { - phpCAS::trace('Reason: bad response from the CAS server'); - } else { - switch ($this->getServerVersion()) { - case CAS_VERSION_1_0: - phpCAS::trace('Reason: CAS error'); - break; - case CAS_VERSION_2_0: - case CAS_VERSION_3_0: - if ( $err_code === -1 ) { - phpCAS::trace('Reason: no CAS error'); - } else { - phpCAS::trace( - 'Reason: ['.$err_code.'] CAS error: '.$err_msg - ); - } - break; - } - } - phpCAS::trace('CAS response: '.$cas_response); - } - $this->printHTMLFooter(); - phpCAS::traceExit(); - throw new CAS_GracefullTerminationException(); - } - - // ######################################################################## - // PGTIOU/PGTID and logoutRequest rebroadcasting - // ######################################################################## - - /** - * Boolean of whether to rebroadcast pgtIou/pgtId and logoutRequest, and - * array of the nodes. - */ - private $_rebroadcast = false; - private $_rebroadcast_nodes = array(); - - /** - * Constants used for determining rebroadcast node type. - */ - const HOSTNAME = 0; - const IP = 1; - - /** - * Determine the node type from the URL. - * - * @param String $nodeURL The node URL. - * - * @return int hostname - * - */ - private function _getNodeType($nodeURL) - { - phpCAS::traceBegin(); - if (preg_match("/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/", $nodeURL)) { - phpCAS::traceEnd(self::IP); - return self::IP; - } else { - phpCAS::traceEnd(self::HOSTNAME); - return self::HOSTNAME; - } - } - - /** - * Store the rebroadcast node for pgtIou/pgtId and logout requests. - * - * @param string $rebroadcastNodeUrl The rebroadcast node URL. - * - * @return void - */ - public function addRebroadcastNode($rebroadcastNodeUrl) - { - // Argument validation - if ( !(bool)preg_match("/^(http|https):\/\/([A-Z0-9][A-Z0-9_-]*(?:\.[A-Z0-9][A-Z0-9_-]*)+):?(\d+)?\/?/i", $rebroadcastNodeUrl)) - throw new CAS_TypeMismatchException($rebroadcastNodeUrl, '$rebroadcastNodeUrl', 'url'); - - // Store the rebroadcast node and set flag - $this->_rebroadcast = true; - $this->_rebroadcast_nodes[] = $rebroadcastNodeUrl; - } - - /** - * An array to store extra rebroadcast curl options. - */ - private $_rebroadcast_headers = array(); - - /** - * This method is used to add header parameters when rebroadcasting - * pgtIou/pgtId or logoutRequest. - * - * @param string $header Header to send when rebroadcasting. - * - * @return void - */ - public function addRebroadcastHeader($header) - { - if (gettype($header) != 'string') - throw new CAS_TypeMismatchException($header, '$header', 'string'); - - $this->_rebroadcast_headers[] = $header; - } - - /** - * Constants used for determining rebroadcast type (logout or pgtIou/pgtId). - */ - const LOGOUT = 0; - const PGTIOU = 1; - - /** - * This method rebroadcasts logout/pgtIou requests. Can be LOGOUT,PGTIOU - * - * @param int $type type of rebroadcasting. - * - * @return void - */ - private function _rebroadcast($type) - { - phpCAS::traceBegin(); - - $rebroadcast_curl_options = array( - CURLOPT_FAILONERROR => 1, - CURLOPT_FOLLOWLOCATION => 1, - CURLOPT_RETURNTRANSFER => 1, - CURLOPT_CONNECTTIMEOUT => 1, - CURLOPT_TIMEOUT => 4); - - // Try to determine the IP address of the server - if (!empty($_SERVER['SERVER_ADDR'])) { - $ip = $_SERVER['SERVER_ADDR']; - } else if (!empty($_SERVER['LOCAL_ADDR'])) { - // IIS 7 - $ip = $_SERVER['LOCAL_ADDR']; - } - // Try to determine the DNS name of the server - if (!empty($ip)) { - $dns = gethostbyaddr($ip); - } - $multiClassName = 'CAS_Request_CurlMultiRequest'; - $multiRequest = new $multiClassName(); - - for ($i = 0; $i < sizeof($this->_rebroadcast_nodes); $i++) { - if ((($this->_getNodeType($this->_rebroadcast_nodes[$i]) == self::HOSTNAME) && !empty($dns) && (stripos($this->_rebroadcast_nodes[$i], $dns) === false)) - || (($this->_getNodeType($this->_rebroadcast_nodes[$i]) == self::IP) && !empty($ip) && (stripos($this->_rebroadcast_nodes[$i], $ip) === false)) - ) { - phpCAS::trace( - 'Rebroadcast target URL: '.$this->_rebroadcast_nodes[$i] - .$_SERVER['REQUEST_URI'] - ); - $className = $this->_requestImplementation; - $request = new $className(); - - $url = $this->_rebroadcast_nodes[$i].$_SERVER['REQUEST_URI']; - $request->setUrl($url); - - if (count($this->_rebroadcast_headers)) { - $request->addHeaders($this->_rebroadcast_headers); - } - - $request->makePost(); - if ($type == self::LOGOUT) { - // Logout request - $request->setPostBody( - 'rebroadcast=false&logoutRequest='.$_POST['logoutRequest'] - ); - } else if ($type == self::PGTIOU) { - // pgtIou/pgtId rebroadcast - $request->setPostBody('rebroadcast=false'); - } - - $request->setCurlOptions($rebroadcast_curl_options); - - $multiRequest->addRequest($request); - } else { - phpCAS::trace( - 'Rebroadcast not sent to self: ' - .$this->_rebroadcast_nodes[$i].' == '.(!empty($ip)?$ip:'') - .'/'.(!empty($dns)?$dns:'') - ); - } - } - // We need at least 1 request - if ($multiRequest->getNumRequests() > 0) { - $multiRequest->send(); - } - phpCAS::traceEnd(); - } - - /** @} */ -} diff --git a/lib/apereo/phpcas/source/CAS/CookieJar.php b/lib/apereo/phpcas/source/CAS/CookieJar.php deleted file mode 100644 index b2439373a..000000000 --- a/lib/apereo/phpcas/source/CAS/CookieJar.php +++ /dev/null @@ -1,385 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * This class provides access to service cookies and handles parsing of response - * headers to pull out cookie values. - * - * @class CAS_CookieJar - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -class CAS_CookieJar -{ - - private $_cookies; - - /** - * Create a new cookie jar by passing it a reference to an array in which it - * should store cookies. - * - * @param array &$storageArray Array to store cookies - * - * @return void - */ - public function __construct (array &$storageArray) - { - $this->_cookies =& $storageArray; - } - - /** - * Store cookies for a web service request. - * Cookie storage is based on RFC 2965: http://www.ietf.org/rfc/rfc2965.txt - * - * @param string $request_url The URL that generated the response headers. - * @param array $response_headers An array of the HTTP response header strings. - * - * @return void - * - * @access private - */ - public function storeCookies ($request_url, $response_headers) - { - $urlParts = parse_url($request_url); - $defaultDomain = $urlParts['host']; - - $cookies = $this->parseCookieHeaders($response_headers, $defaultDomain); - - foreach ($cookies as $cookie) { - // Enforce the same-origin policy by verifying that the cookie - // would match the url that is setting it - if (!$this->cookieMatchesTarget($cookie, $urlParts)) { - continue; - } - - // store the cookie - $this->storeCookie($cookie); - - phpCAS::trace($cookie['name'].' -> '.$cookie['value']); - } - } - - /** - * Retrieve cookies applicable for a web service request. - * Cookie applicability is based on RFC 2965: http://www.ietf.org/rfc/rfc2965.txt - * - * @param string $request_url The url that the cookies will be for. - * - * @return array An array containing cookies. E.g. array('name' => 'val'); - * - * @access private - */ - public function getCookies ($request_url) - { - if (!count($this->_cookies)) { - return array(); - } - - // If our request URL can't be parsed, no cookies apply. - $target = parse_url($request_url); - if ($target === false) { - return array(); - } - - $this->expireCookies(); - - $matching_cookies = array(); - foreach ($this->_cookies as $key => $cookie) { - if ($this->cookieMatchesTarget($cookie, $target)) { - $matching_cookies[$cookie['name']] = $cookie['value']; - } - } - return $matching_cookies; - } - - - /** - * Parse Cookies without PECL - * From the comments in http://php.net/manual/en/function.http-parse-cookie.php - * - * @param array $header array of header lines. - * @param string $defaultDomain The domain to use if none is specified in - * the cookie. - * - * @return array of cookies - */ - protected function parseCookieHeaders( $header, $defaultDomain ) - { - phpCAS::traceBegin(); - $cookies = array(); - foreach ( $header as $line ) { - if ( preg_match('/^Set-Cookie2?: /i', $line)) { - $cookies[] = $this->parseCookieHeader($line, $defaultDomain); - } - } - - phpCAS::traceEnd($cookies); - return $cookies; - } - - /** - * Parse a single cookie header line. - * - * Based on RFC2965 http://www.ietf.org/rfc/rfc2965.txt - * - * @param string $line The header line. - * @param string $defaultDomain The domain to use if none is specified in - * the cookie. - * - * @return array - */ - protected function parseCookieHeader ($line, $defaultDomain) - { - if (!$defaultDomain) { - throw new CAS_InvalidArgumentException( - '$defaultDomain was not provided.' - ); - } - - // Set our default values - $cookie = array( - 'domain' => $defaultDomain, - 'path' => '/', - 'secure' => false, - ); - - $line = preg_replace('/^Set-Cookie2?: /i', '', trim($line)); - - // trim any trailing semicolons. - $line = trim($line, ';'); - - phpCAS::trace("Cookie Line: $line"); - - // This implementation makes the assumption that semicolons will not - // be present in quoted attribute values. While attribute values that - // contain semicolons are allowed by RFC2965, they are hopefully rare - // enough to ignore for our purposes. Most browsers make the same - // assumption. - $attributeStrings = explode(';', $line); - - foreach ( $attributeStrings as $attributeString ) { - // split on the first equals sign and use the rest as value - $attributeParts = explode('=', $attributeString, 2); - - $attributeName = trim($attributeParts[0]); - $attributeNameLC = strtolower($attributeName); - - if (isset($attributeParts[1])) { - $attributeValue = trim($attributeParts[1]); - // Values may be quoted strings. - if (strpos($attributeValue, '"') === 0) { - $attributeValue = trim($attributeValue, '"'); - // unescape any escaped quotes: - $attributeValue = str_replace('\"', '"', $attributeValue); - } - } else { - $attributeValue = null; - } - - switch ($attributeNameLC) { - case 'expires': - $cookie['expires'] = strtotime($attributeValue); - break; - case 'max-age': - $cookie['max-age'] = (int)$attributeValue; - // Set an expiry time based on the max-age - if ($cookie['max-age']) { - $cookie['expires'] = time() + $cookie['max-age']; - } else { - // If max-age is zero, then the cookie should be removed - // imediately so set an expiry before now. - $cookie['expires'] = time() - 1; - } - break; - case 'secure': - $cookie['secure'] = true; - break; - case 'domain': - case 'path': - case 'port': - case 'version': - case 'comment': - case 'commenturl': - case 'discard': - case 'httponly': - case 'samesite': - $cookie[$attributeNameLC] = $attributeValue; - break; - default: - $cookie['name'] = $attributeName; - $cookie['value'] = $attributeValue; - } - } - - return $cookie; - } - - /** - * Add, update, or remove a cookie. - * - * @param array $cookie A cookie array as created by parseCookieHeaders() - * - * @return void - * - * @access protected - */ - protected function storeCookie ($cookie) - { - // Discard any old versions of this cookie. - $this->discardCookie($cookie); - $this->_cookies[] = $cookie; - - } - - /** - * Discard an existing cookie - * - * @param array $cookie An cookie - * - * @return void - * - * @access protected - */ - protected function discardCookie ($cookie) - { - if (!isset($cookie['domain']) - || !isset($cookie['path']) - || !isset($cookie['path']) - ) { - throw new CAS_InvalidArgumentException('Invalid Cookie array passed.'); - } - - foreach ($this->_cookies as $key => $old_cookie) { - if ( $cookie['domain'] == $old_cookie['domain'] - && $cookie['path'] == $old_cookie['path'] - && $cookie['name'] == $old_cookie['name'] - ) { - unset($this->_cookies[$key]); - } - } - } - - /** - * Go through our stored cookies and remove any that are expired. - * - * @return void - * - * @access protected - */ - protected function expireCookies () - { - foreach ($this->_cookies as $key => $cookie) { - if (isset($cookie['expires']) && $cookie['expires'] < time()) { - unset($this->_cookies[$key]); - } - } - } - - /** - * Answer true if cookie is applicable to a target. - * - * @param array $cookie An array of cookie attributes. - * @param array|false $target An array of URL attributes as generated by parse_url(). - * - * @return bool - * - * @access private - */ - protected function cookieMatchesTarget ($cookie, $target) - { - if (!is_array($target)) { - throw new CAS_InvalidArgumentException( - '$target must be an array of URL attributes as generated by parse_url().' - ); - } - if (!isset($target['host'])) { - throw new CAS_InvalidArgumentException( - '$target must be an array of URL attributes as generated by parse_url().' - ); - } - - // Verify that the scheme matches - if ($cookie['secure'] && $target['scheme'] != 'https') { - return false; - } - - // Verify that the host matches - // Match domain and mulit-host cookies - if (strpos($cookie['domain'], '.') === 0) { - // .host.domain.edu cookies are valid for host.domain.edu - if (substr($cookie['domain'], 1) == $target['host']) { - // continue with other checks - } else { - // non-exact host-name matches. - // check that the target host a.b.c.edu is within .b.c.edu - $pos = strripos($target['host'], $cookie['domain']); - if (!$pos) { - return false; - } - // verify that the cookie domain is the last part of the host. - if ($pos + strlen($cookie['domain']) != strlen($target['host'])) { - return false; - } - // verify that the host name does not contain interior dots as per - // RFC 2965 section 3.3.2 Rejecting Cookies - // http://www.ietf.org/rfc/rfc2965.txt - $hostname = substr($target['host'], 0, $pos); - if (strpos($hostname, '.') !== false) { - return false; - } - } - } else { - // If the cookie host doesn't begin with '.', - // the host must case-insensitive match exactly - if (strcasecmp($target['host'], $cookie['domain']) !== 0) { - return false; - } - } - - // Verify that the port matches - if (isset($cookie['ports']) - && !in_array($target['port'], $cookie['ports']) - ) { - return false; - } - - // Verify that the path matches - if (strpos($target['path'], $cookie['path']) !== 0) { - return false; - } - - return true; - } - -} - -?> diff --git a/lib/apereo/phpcas/source/CAS/Exception.php b/lib/apereo/phpcas/source/CAS/Exception.php deleted file mode 100644 index 2ff7cd658..000000000 --- a/lib/apereo/phpcas/source/CAS/Exception.php +++ /dev/null @@ -1,59 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * A root exception interface for all exceptions in phpCAS. - * - * All exceptions thrown in phpCAS should implement this interface to allow them - * to be caught as a category by clients. Each phpCAS exception should extend - * an appropriate SPL exception class that best fits its type. - * - * For example, an InvalidArgumentException in phpCAS should be defined as - * - * class CAS_InvalidArgumentException - * extends InvalidArgumentException - * implements CAS_Exception - * { } - * - * This definition allows the CAS_InvalidArgumentException to be caught as either - * an InvalidArgumentException or as a CAS_Exception. - * - * @class CAS_Exception - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - * - */ -interface CAS_Exception -{ - -} -?> diff --git a/lib/apereo/phpcas/source/CAS/GracefullTerminationException.php b/lib/apereo/phpcas/source/CAS/GracefullTerminationException.php deleted file mode 100644 index 29aa638cd..000000000 --- a/lib/apereo/phpcas/source/CAS/GracefullTerminationException.php +++ /dev/null @@ -1,86 +0,0 @@ - - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * An exception for terminatinating execution or to throw for unit testing - * - * @class CAS_GracefullTerminationException.php - * @category Authentication - * @package PhpCAS - * @author Joachim Fritschi - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -class CAS_GracefullTerminationException -extends RuntimeException -implements CAS_Exception -{ - - /** - * Test if exceptions should be thrown or if we should just exit. - * In production usage we want to just exit cleanly when prompting the user - * for a redirect without filling the error logs with uncaught exceptions. - * In unit testing scenarios we cannot exit or we won't be able to continue - * with our tests. - * - * @param string $message Message Text - * @param int $code Error code - * - * @return self - */ - public function __construct ($message = 'Terminate Gracefully', $code = 0) - { - // Exit cleanly to avoid filling up the logs with uncaught exceptions. - if (self::$_exitWhenThrown) { - exit; - } else { - // Throw exceptions to allow unit testing to continue; - parent::__construct($message, $code); - } - } - - private static $_exitWhenThrown = true; - /** - * Force phpcas to thow Exceptions instead of calling exit() - * Needed for unit testing. Generally shouldn't be used in production due to - * an increase in Apache error logging if CAS_GracefulTerminiationExceptions - * are not caught and handled. - * - * @return void - */ - public static function throwInsteadOfExiting() - { - self::$_exitWhenThrown = false; - } - -} -?> diff --git a/lib/apereo/phpcas/source/CAS/InvalidArgumentException.php b/lib/apereo/phpcas/source/CAS/InvalidArgumentException.php deleted file mode 100644 index 99be2ac32..000000000 --- a/lib/apereo/phpcas/source/CAS/InvalidArgumentException.php +++ /dev/null @@ -1,46 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * Exception that denotes invalid arguments were passed. - * - * @class CAS_InvalidArgumentException - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -class CAS_InvalidArgumentException -extends InvalidArgumentException -implements CAS_Exception -{ - -} -?> diff --git a/lib/apereo/phpcas/source/CAS/Languages/Catalan.php b/lib/apereo/phpcas/source/CAS/Languages/Catalan.php deleted file mode 100644 index 1ead905fc..000000000 --- a/lib/apereo/phpcas/source/CAS/Languages/Catalan.php +++ /dev/null @@ -1,114 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * Catalan language class - * - * @class CAS_Languages_Catalan - * @category Authentication - * @package PhpCAS - * @author Iván-Benjamín García Torà - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - * - * @sa @link internalLang Internationalization @endlink - * @ingroup internalLang - */ -class CAS_Languages_Catalan implements CAS_Languages_LanguageInterface -{ - /** - * Get the using server string - * - * @return string using server - */ - public function getUsingServer() - { - return 'usant servidor'; - } - - /** - * Get authentication wanted string - * - * @return string authentication wanted - */ - public function getAuthenticationWanted() - { - return 'Autentificació CAS necessària!'; - } - - /** - * Get logout string - * - * @return string logout - */ - public function getLogout() - { - return 'Sortida de CAS necessària!'; - } - - /** - * Get the should have been redirected string - * - * @return string should habe been redirected - */ - public function getShouldHaveBeenRedirected() - { - return 'Ja hauria d\ haver estat redireccionat al servidor CAS. Feu click aquí per a continuar.'; - } - - /** - * Get authentication failed string - * - * @return string authentication failed - */ - public function getAuthenticationFailed() - { - return 'Autentificació CAS fallida!'; - } - - /** - * Get the your were not authenticated string - * - * @return string not authenticated - */ - public function getYouWereNotAuthenticated() - { - return '

No estàs autentificat.

Pots tornar a intentar-ho fent click aquí.

Si el problema persisteix hauría de contactar amb l\'administrador d\'aquest llocc.

'; - } - - /** - * Get the service unavailable string - * - * @return string service unavailable - */ - public function getServiceUnavailable() - { - return 'El servei `%s\' no està disponible (%s).'; - } -} diff --git a/lib/apereo/phpcas/source/CAS/Languages/ChineseSimplified.php b/lib/apereo/phpcas/source/CAS/Languages/ChineseSimplified.php deleted file mode 100644 index 5e33cb650..000000000 --- a/lib/apereo/phpcas/source/CAS/Languages/ChineseSimplified.php +++ /dev/null @@ -1,114 +0,0 @@ -, Phy25 - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * Chinese Simplified language class - * - * @class CAS_Languages_ChineseSimplified - * @category Authentication - * @package PhpCAS - * @author Pascal Aubry , Phy25 - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - * - * @sa @link internalLang Internationalization @endlink - * @ingroup internalLang - */ -class CAS_Languages_ChineseSimplified implements CAS_Languages_LanguageInterface -{ - /** - * Get the using server string - * - * @return string using server - */ - public function getUsingServer() - { - return '连接的服务器'; - } - - /** - * Get authentication wanted string - * - * @return string authentication wanted - */ - public function getAuthenticationWanted() - { - return '请进行 CAS 认证!'; - } - - /** - * Get logout string - * - * @return string logout - */ - public function getLogout() - { - return '请进行 CAS 登出!'; - } - - /** - * Get the should have been redirected string - * - * @return string should habe been redirected - */ - public function getShouldHaveBeenRedirected() - { - return '你正被重定向到 CAS 服务器。点击这里继续。'; - } - - /** - * Get authentication failed string - * - * @return string authentication failed - */ - public function getAuthenticationFailed() - { - return 'CAS 认证失败!'; - } - - /** - * Get the your were not authenticated string - * - * @return string not authenticated - */ - public function getYouWereNotAuthenticated() - { - return '

你没有成功登录。

你可以点击这里重新登录

如果问题依然存在,请联系本站管理员

'; - } - - /** - * Get the service unavailable string - * - * @return string service unavailable - */ - public function getServiceUnavailable() - { - return '服务器 %s 不可用(%s)。'; - } -} diff --git a/lib/apereo/phpcas/source/CAS/Languages/English.php b/lib/apereo/phpcas/source/CAS/Languages/English.php deleted file mode 100644 index cb13bde93..000000000 --- a/lib/apereo/phpcas/source/CAS/Languages/English.php +++ /dev/null @@ -1,114 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * English language class - * - * @class CAS_Languages_English - * @category Authentication - * @package PhpCAS - * @author Pascal Aubry - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - * - * @sa @link internalLang Internationalization @endlink - * @ingroup internalLang - */ -class CAS_Languages_English implements CAS_Languages_LanguageInterface -{ - /** - * Get the using server string - * - * @return string using server - */ - public function getUsingServer() - { - return 'using server'; - } - - /** - * Get authentication wanted string - * - * @return string authentication wanted - */ - public function getAuthenticationWanted() - { - return 'CAS Authentication wanted!'; - } - - /** - * Get logout string - * - * @return string logout - */ - public function getLogout() - { - return 'CAS logout wanted!'; - } - - /** - * Get the should have been redirected string - * - * @return string should habe been redirected - */ - public function getShouldHaveBeenRedirected() - { - return 'You should already have been redirected to the CAS server. Click here to continue.'; - } - - /** - * Get authentication failed string - * - * @return string authentication failed - */ - public function getAuthenticationFailed() - { - return 'CAS Authentication failed!'; - } - - /** - * Get the your were not authenticated string - * - * @return string not authenticated - */ - public function getYouWereNotAuthenticated() - { - return '

You were not authenticated.

You may submit your request again by clicking here.

If the problem persists, you may contact the administrator of this site.

'; - } - - /** - * Get the service unavailable string - * - * @return string service unavailable - */ - public function getServiceUnavailable() - { - return 'The service `%s\' is not available (%s).'; - } -} diff --git a/lib/apereo/phpcas/source/CAS/Languages/French.php b/lib/apereo/phpcas/source/CAS/Languages/French.php deleted file mode 100644 index 14f65aba2..000000000 --- a/lib/apereo/phpcas/source/CAS/Languages/French.php +++ /dev/null @@ -1,116 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * French language class - * - * @class CAS_Languages_French - * @category Authentication - * @package PhpCAS - * @author Pascal Aubry - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - * - * @sa @link internalLang Internationalization @endlink - * @ingroup internalLang - */ -class CAS_Languages_French implements CAS_Languages_LanguageInterface -{ - /** - * Get the using server string - * - * @return string using server - */ - public function getUsingServer() - { - return 'utilisant le serveur'; - } - - /** - * Get authentication wanted string - * - * @return string authentication wanted - */ - public function getAuthenticationWanted() - { - return 'Authentication CAS nécessaire !'; - } - - /** - * Get logout string - * - * @return string logout - */ - public function getLogout() - { - return 'Déconnexion demandée !'; - } - - /** - * Get the should have been redirected string - * - * @return string should habe been redirected - */ - public function getShouldHaveBeenRedirected() - { - return 'Vous auriez du etre redirigé(e) vers le serveur CAS. Cliquez ici pour continuer.'; - } - - /** - * Get authentication failed string - * - * @return string authentication failed - */ - public function getAuthenticationFailed() - { - return 'Authentification CAS infructueuse !'; - } - - /** - * Get the your were not authenticated string - * - * @return string not authenticated - */ - public function getYouWereNotAuthenticated() - { - return '

Vous n\'avez pas été authentifié(e).

Vous pouvez soumettre votre requete à nouveau en cliquant ici.

Si le problème persiste, vous pouvez contacter l\'administrateur de ce site.

'; - } - - /** - * Get the service unavailable string - * - * @return string service unavailable - */ - public function getServiceUnavailable() - { - return 'Le service `%s\' est indisponible (%s)'; - } -} - -?> diff --git a/lib/apereo/phpcas/source/CAS/Languages/Galego.php b/lib/apereo/phpcas/source/CAS/Languages/Galego.php deleted file mode 100644 index d5bf40455..000000000 --- a/lib/apereo/phpcas/source/CAS/Languages/Galego.php +++ /dev/null @@ -1,117 +0,0 @@ -aquí para continuar'; - } - - /** - * Get authentication failed string - * - * @return string authentication failed - */ - public function getAuthenticationFailed() - { - return 'Autenticación CAS errada!'; - } - - /** - * Get the your were not authenticated string - * - * @return string not authenticated - */ - public function getYouWereNotAuthenticated() - { - return ' -

Non estás autenticado

Podes volver tentalo facendo click aquí.

Se o problema persiste debería contactar con el administrador deste sitio.

'; - } - - /** - * Get the service unavailable string - * - * @return string service unavailable - */ - public function getServiceUnavailable() - { - return 'O servizo `%s\' non está dispoñible (%s).'; - } -} -?> diff --git a/lib/apereo/phpcas/source/CAS/Languages/German.php b/lib/apereo/phpcas/source/CAS/Languages/German.php deleted file mode 100644 index b718b1452..000000000 --- a/lib/apereo/phpcas/source/CAS/Languages/German.php +++ /dev/null @@ -1,116 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * German language class - * - * @class CAS_Languages_German - * @category Authentication - * @package PhpCAS - * @author Henrik Genssen - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - * - * @sa @link internalLang Internationalization @endlink - * @ingroup internalLang - */ -class CAS_Languages_German implements CAS_Languages_LanguageInterface -{ - /** - * Get the using server string - * - * @return string using server - */ - public function getUsingServer() - { - return 'via Server'; - } - - /** - * Get authentication wanted string - * - * @return string authentication wanted - */ - public function getAuthenticationWanted() - { - return 'CAS Authentifizierung erforderlich!'; - } - - /** - * Get logout string - * - * @return string logout - */ - public function getLogout() - { - return 'CAS Abmeldung!'; - } - - /** - * Get the should have been redirected string - * - * @return string should habe been redirected - */ - public function getShouldHaveBeenRedirected() - { - return 'eigentlich häten Sie zum CAS Server weitergeleitet werden sollen. Drücken Sie hier um fortzufahren.'; - } - - /** - * Get authentication failed string - * - * @return string authentication failed - */ - public function getAuthenticationFailed() - { - return 'CAS Anmeldung fehlgeschlagen!'; - } - - /** - * Get the your were not authenticated string - * - * @return string not authenticated - */ - public function getYouWereNotAuthenticated() - { - return '

Sie wurden nicht angemeldet.

Um es erneut zu versuchen klicken Sie hier.

Wenn das Problem bestehen bleibt, kontaktieren Sie den Administrator dieser Seite.

'; - } - - /** - * Get the service unavailable string - * - * @return string service unavailable - */ - public function getServiceUnavailable() - { - return 'Der Dienst `%s\' ist nicht verfügbar (%s).'; - } -} - -?> diff --git a/lib/apereo/phpcas/source/CAS/Languages/Greek.php b/lib/apereo/phpcas/source/CAS/Languages/Greek.php deleted file mode 100644 index 1cfb107e4..000000000 --- a/lib/apereo/phpcas/source/CAS/Languages/Greek.php +++ /dev/null @@ -1,115 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * Greek language class - * - * @class CAS_Languages_Greek - * @category Authentication - * @package PhpCAS - * @author Vangelis Haniotakis - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - * - * @sa @link internalLang Internationalization @endlink - * @ingroup internalLang - */ -class CAS_Languages_Greek implements CAS_Languages_LanguageInterface -{ - /** - * Get the using server string - * - * @return string using server - */ - public function getUsingServer() - { - return 'χρησιμοποιείται ο εξυπηρετητής'; - } - - /** - * Get authentication wanted string - * - * @return string authentication wanted - */ - public function getAuthenticationWanted() - { - return 'Απαιτείται η ταυτοποίηση CAS!'; - } - - /** - * Get logout string - * - * @return string logout - */ - public function getLogout() - { - return 'Απαιτείται η αποσύνδεση από CAS!'; - } - - /** - * Get the should have been redirected string - * - * @return string should habe been redirected - */ - public function getShouldHaveBeenRedirected() - { - return 'Θα έπρεπε να είχατε ανακατευθυνθεί στον εξυπηρετητή CAS. Κάντε κλίκ εδώ για να συνεχίσετε.'; - } - - /** - * Get authentication failed string - * - * @return string authentication failed - */ - public function getAuthenticationFailed() - { - return 'Η ταυτοποίηση CAS απέτυχε!'; - } - - /** - * Get the your were not authenticated string - * - * @return string not authenticated - */ - public function getYouWereNotAuthenticated() - { - return '

Δεν ταυτοποιηθήκατε.

Μπορείτε να ξαναπροσπαθήσετε, κάνοντας κλίκ εδώ.

Εαν το πρόβλημα επιμείνει, ελάτε σε επαφή με τον διαχειριστή.

'; - } - - /** - * Get the service unavailable string - * - * @return string service unavailable - */ - public function getServiceUnavailable() - { - return 'Η υπηρεσία `%s\' δεν είναι διαθέσιμη (%s).'; - } -} -?> diff --git a/lib/apereo/phpcas/source/CAS/Languages/Japanese.php b/lib/apereo/phpcas/source/CAS/Languages/Japanese.php deleted file mode 100644 index 568148458..000000000 --- a/lib/apereo/phpcas/source/CAS/Languages/Japanese.php +++ /dev/null @@ -1,113 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * Japanese language class. Now Encoding is UTF-8. - * - * @class CAS_Languages_Japanese - * @category Authentication - * @package PhpCAS - * @author fnorif - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - * - **/ -class CAS_Languages_Japanese implements CAS_Languages_LanguageInterface -{ - /** - * Get the using server string - * - * @return string using server - */ - public function getUsingServer() - { - return 'サーバーを使っています。'; - } - - /** - * Get authentication wanted string - * - * @return string authentication wanted - */ - public function getAuthenticationWanted() - { - return 'CASによる認証を行います。'; - } - - /** - * Get logout string - * - * @return string logout - */ - public function getLogout() - { - return 'CASからログアウトします!'; - } - - /** - * Get the should have been redirected string - * - * @return string should habe been redirected - */ - public function getShouldHaveBeenRedirected() - { - return 'CASサーバに行く必要があります。自動的に転送されない場合は こちら をクリックして続行します。'; - } - - /** - * Get authentication failed string - * - * @return string authentication failed - */ - public function getAuthenticationFailed() - { - return 'CASによる認証に失敗しました。'; - } - - /** - * Get the your were not authenticated string - * - * @return string not authenticated - */ - public function getYouWereNotAuthenticated() - { - return '

認証できませんでした。

もう一度リクエストを送信する場合はこちらをクリック。

問題が解決しない場合は このサイトの管理者に問い合わせてください。

'; - } - - /** - * Get the service unavailable string - * - * @return string service unavailable - */ - public function getServiceUnavailable() - { - return 'サービス `%s\' は利用できません (%s)。'; - } -} -?> diff --git a/lib/apereo/phpcas/source/CAS/Languages/LanguageInterface.php b/lib/apereo/phpcas/source/CAS/Languages/LanguageInterface.php deleted file mode 100644 index dfb0ac514..000000000 --- a/lib/apereo/phpcas/source/CAS/Languages/LanguageInterface.php +++ /dev/null @@ -1,96 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * Language Interface class for all internationalization files - * - * @class CAS_Languages_LanguageInterface - * @category Authentication - * @package PhpCAS - * @author Joachim Fritschi - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - * - * @sa @link internalLang Internationalization @endlink - * @ingroup internalLang - */ - -interface CAS_Languages_LanguageInterface -{ - /** - * Get the using server string - * - * @return string using server - */ - public function getUsingServer(); - - /** - * Get authentication wanted string - * - * @return string authentication wanted - */ - public function getAuthenticationWanted(); - - /** - * Get logout string - * - * @return string logout - */ - public function getLogout(); - - /** - * Get the should have been redirected string - * - * @return string should habe been redirected - */ - public function getShouldHaveBeenRedirected(); - - /** - * Get authentication failed string - * - * @return string authentication failed - */ - public function getAuthenticationFailed(); - - /** - * Get the your were not authenticated string - * - * @return string not authenticated - */ - public function getYouWereNotAuthenticated(); - - /** - * Get the service unavailable string - * - * @return string service unavailable - */ - public function getServiceUnavailable(); - -} -?> diff --git a/lib/apereo/phpcas/source/CAS/Languages/Portuguese.php b/lib/apereo/phpcas/source/CAS/Languages/Portuguese.php deleted file mode 100644 index a927cad62..000000000 --- a/lib/apereo/phpcas/source/CAS/Languages/Portuguese.php +++ /dev/null @@ -1,114 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://apereo.atlassian.net/wiki/spaces/CASC/pages/103252517/phpCAS - */ - -/** - * Portuguese language class - * - * @class CAS_Languages_Portuguese - * @category Authentication - * @package PhpCAS - * @author Sherwin Harris - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://apereo.atlassian.net/wiki/spaces/CASC/pages/103252517/phpCAS - * - * @sa @link internalLang Internationalization @endlink - * @ingroup internalLang - */ -class CAS_Languages_Portuguese implements CAS_Languages_LanguageInterface -{ - /** - * Get the using server string - * - * @return string using server - */ - public function getUsingServer() - { - return 'Usando o servidor'; - } - - /** - * Get authentication wanted string - * - * @return string authentication wanted - */ - public function getAuthenticationWanted() - { - return 'A autenticação do servidor CAS desejado!'; - } - - /** - * Get logout string - * - * @return string logout - */ - public function getLogout() - { - return 'Saida do servidor CAS desejado!'; - } - - /** - * Get the should have been redirected string - * - * @return string should have been redirected - */ - public function getShouldHaveBeenRedirected() - { - return 'Você já deve ter sido redirecionado para o servidor CAS. Clique aqui para continuar'; - } - - /** - * Get authentication failed string - * - * @return string authentication failed - */ - public function getAuthenticationFailed() - { - return 'A autenticação do servidor CAS falheu!'; - } - - /** - * Get the your were not authenticated string - * - * @return string not authenticated - */ - public function getYouWereNotAuthenticated() - { - return '

Você não foi autenticado.

Você pode enviar sua solicitação novamente clicando aqui.

Se o problema persistir, você pode entrar em contato com o administrador deste site.

'; - } - - /** - * Get the service unavailable string - * - * @return string service unavailable - */ - public function getServiceUnavailable() - { - return 'O serviço `%s\' não está disponível (%s).'; - } -} diff --git a/lib/apereo/phpcas/source/CAS/Languages/Spanish.php b/lib/apereo/phpcas/source/CAS/Languages/Spanish.php deleted file mode 100644 index c6ea50e74..000000000 --- a/lib/apereo/phpcas/source/CAS/Languages/Spanish.php +++ /dev/null @@ -1,117 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * Spanish language class - * - * @class CAS_Languages_Spanish - * @category Authentication - * @package PhpCAS - * @author Iván-Benjamín García Torà - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - * - - * @sa @link internalLang Internationalization @endlink - * @ingroup internalLang - */ -class CAS_Languages_Spanish implements CAS_Languages_LanguageInterface -{ - - /** - * Get the using server string - * - * @return string using server - */ - public function getUsingServer() - { - return 'usando servidor'; - } - - /** - * Get authentication wanted string - * - * @return string authentication wanted - */ - public function getAuthenticationWanted() - { - return '¡Autentificación CAS necesaria!'; - } - - /** - * Get logout string - * - * @return string logout - */ - public function getLogout() - { - return '¡Salida CAS necesaria!'; - } - - /** - * Get the should have been redirected string - * - * @return string should habe been redirected - */ - public function getShouldHaveBeenRedirected() - { - return 'Ya debería haber sido redireccionado al servidor CAS. Haga click aquí para continuar.'; - } - - /** - * Get authentication failed string - * - * @return string authentication failed - */ - public function getAuthenticationFailed() - { - return '¡Autentificación CAS fallida!'; - } - - /** - * Get the your were not authenticated string - * - * @return string not authenticated - */ - public function getYouWereNotAuthenticated() - { - return '

No estás autentificado.

Puedes volver a intentarlo haciendo click aquí.

Si el problema persiste debería contactar con el administrador de este sitio.

'; - } - - /** - * Get the service unavailable string - * - * @return string service unavailable - */ - public function getServiceUnavailable() - { - return 'El servicio `%s\' no está disponible (%s).'; - } -} -?> diff --git a/lib/apereo/phpcas/source/CAS/OutOfSequenceBeforeAuthenticationCallException.php b/lib/apereo/phpcas/source/CAS/OutOfSequenceBeforeAuthenticationCallException.php deleted file mode 100644 index d4d7680de..000000000 --- a/lib/apereo/phpcas/source/CAS/OutOfSequenceBeforeAuthenticationCallException.php +++ /dev/null @@ -1,56 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * This class defines Exceptions that should be thrown when the sequence of - * operations is invalid. In this case it should be thrown when an - * authentication call has not yet happened. - * - * @class CAS_OutOfSequenceBeforeAuthenticationCallException - * @category Authentication - * @package PhpCAS - * @author Joachim Fritschi - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -class CAS_OutOfSequenceBeforeAuthenticationCallException -extends CAS_OutOfSequenceException -implements CAS_Exception -{ - /** - * Return standard error meessage - * - * @return void - */ - public function __construct () - { - parent::__construct('An authentication call hasn\'t happened yet.'); - } -} diff --git a/lib/apereo/phpcas/source/CAS/OutOfSequenceBeforeClientException.php b/lib/apereo/phpcas/source/CAS/OutOfSequenceBeforeClientException.php deleted file mode 100644 index 6c2c39c58..000000000 --- a/lib/apereo/phpcas/source/CAS/OutOfSequenceBeforeClientException.php +++ /dev/null @@ -1,58 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * This class defines Exceptions that should be thrown when the sequence of - * operations is invalid. In this case it should be thrown when the client() or - * proxy() call has not yet happened and no client or proxy object exists. - * - * @class CAS_OutOfSequenceBeforeClientException - * @category Authentication - * @package PhpCAS - * @author Joachim Fritschi - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -class CAS_OutOfSequenceBeforeClientException -extends CAS_OutOfSequenceException -implements CAS_Exception -{ - /** - * Return standard error message - * - * @return void - */ - public function __construct () - { - parent::__construct( - 'this method cannot be called before phpCAS::client() or phpCAS::proxy()' - ); - } -} diff --git a/lib/apereo/phpcas/source/CAS/OutOfSequenceBeforeProxyException.php b/lib/apereo/phpcas/source/CAS/OutOfSequenceBeforeProxyException.php deleted file mode 100644 index 799155521..000000000 --- a/lib/apereo/phpcas/source/CAS/OutOfSequenceBeforeProxyException.php +++ /dev/null @@ -1,59 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * This class defines Exceptions that should be thrown when the sequence of - * operations is invalid. In this case it should be thrown when the proxy() call - * has not yet happened and no proxy object exists. - * - * @class CAS_OutOfSequenceBeforeProxyException - * @category Authentication - * @package PhpCAS - * @author Joachim Fritschi - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -class CAS_OutOfSequenceBeforeProxyException -extends CAS_OutOfSequenceException -implements CAS_Exception -{ - - /** - * Return standard error message - * - * @return void - */ - public function __construct () - { - parent::__construct( - 'this method cannot be called before phpCAS::proxy()' - ); - } -} diff --git a/lib/apereo/phpcas/source/CAS/OutOfSequenceException.php b/lib/apereo/phpcas/source/CAS/OutOfSequenceException.php deleted file mode 100644 index d6f7d88fc..000000000 --- a/lib/apereo/phpcas/source/CAS/OutOfSequenceException.php +++ /dev/null @@ -1,49 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * This class defines Exceptions that should be thrown when the sequence of - * operations is invalid. Examples are: - * - Requesting the response before executing a request. - * - Changing the URL of a request after executing the request. - * - * @class CAS_OutOfSequenceException - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -class CAS_OutOfSequenceException -extends BadMethodCallException -implements CAS_Exception -{ - -} diff --git a/lib/apereo/phpcas/source/CAS/PGTStorage/AbstractStorage.php b/lib/apereo/phpcas/source/CAS/PGTStorage/AbstractStorage.php deleted file mode 100644 index a93568d60..000000000 --- a/lib/apereo/phpcas/source/CAS/PGTStorage/AbstractStorage.php +++ /dev/null @@ -1,222 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * Basic class for PGT storage - * The CAS_PGTStorage_AbstractStorage class is a generic class for PGT storage. - * This class should not be instanciated itself but inherited by specific PGT - * storage classes. - * - * @class CAS_PGTStorage_AbstractStorage - * @category Authentication - * @package PhpCAS - * @author Pascal Aubry - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - * - * @ingroup internalPGTStorage - */ - -abstract class CAS_PGTStorage_AbstractStorage -{ - /** - * @addtogroup internalPGTStorage - * @{ - */ - - // ######################################################################## - // CONSTRUCTOR - // ######################################################################## - - /** - * The constructor of the class, should be called only by inherited classes. - * - * @param CAS_Client $cas_parent the CAS _client instance that creates the - * current object. - * - * @return void - * - * @protected - */ - function __construct($cas_parent) - { - phpCAS::traceBegin(); - if ( !$cas_parent->isProxy() ) { - phpCAS::error( - 'defining PGT storage makes no sense when not using a CAS proxy' - ); - } - phpCAS::traceEnd(); - } - - // ######################################################################## - // DEBUGGING - // ######################################################################## - - /** - * This virtual method returns an informational string giving the type of storage - * used by the object (used for debugging purposes). - * - * @return string - * - * @public - */ - function getStorageType() - { - phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called'); - } - - /** - * This virtual method returns an informational string giving informations on the - * parameters of the storage.(used for debugging purposes). - * - * @return string - * - * @public - */ - function getStorageInfo() - { - phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called'); - } - - // ######################################################################## - // ERROR HANDLING - // ######################################################################## - - /** - * string used to store an error message. Written by - * PGTStorage::setErrorMessage(), read by PGTStorage::getErrorMessage(). - * - * @hideinitializer - * @deprecated not used. - */ - var $_error_message=false; - - /** - * This method sets en error message, which can be read later by - * PGTStorage::getErrorMessage(). - * - * @param string $error_message an error message - * - * @return void - * - * @deprecated not used. - */ - function setErrorMessage($error_message) - { - $this->_error_message = $error_message; - } - - /** - * This method returns an error message set by PGTStorage::setErrorMessage(). - * - * @return string an error message when set by PGTStorage::setErrorMessage(), FALSE - * otherwise. - * - * @deprecated not used. - */ - function getErrorMessage() - { - return $this->_error_message; - } - - // ######################################################################## - // INITIALIZATION - // ######################################################################## - - /** - * a boolean telling if the storage has already been initialized. Written by - * PGTStorage::init(), read by PGTStorage::isInitialized(). - * - * @hideinitializer - */ - var $_initialized = false; - - /** - * This method tells if the storage has already been intialized. - * - * @return bool - * - * @protected - */ - function isInitialized() - { - return $this->_initialized; - } - - /** - * This virtual method initializes the object. - * - * @return void - */ - function init() - { - $this->_initialized = true; - } - - // ######################################################################## - // PGT I/O - // ######################################################################## - - /** - * This virtual method stores a PGT and its corresponding PGT Iuo. - * - * @param string $pgt the PGT - * @param string $pgt_iou the PGT iou - * - * @return void - * - * @note Should never be called. - * - */ - function write($pgt,$pgt_iou) - { - phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called'); - } - - /** - * This virtual method reads a PGT corresponding to a PGT Iou and deletes - * the corresponding storage entry. - * - * @param string $pgt_iou the PGT iou - * - * @return string - * - * @note Should never be called. - */ - function read($pgt_iou) - { - phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called'); - } - - /** @} */ - -} - -?> diff --git a/lib/apereo/phpcas/source/CAS/PGTStorage/Db.php b/lib/apereo/phpcas/source/CAS/PGTStorage/Db.php deleted file mode 100644 index 2efe5a3e8..000000000 --- a/lib/apereo/phpcas/source/CAS/PGTStorage/Db.php +++ /dev/null @@ -1,440 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -define('CAS_PGT_STORAGE_DB_DEFAULT_TABLE', 'cas_pgts'); - -/** - * Basic class for PGT database storage - * The CAS_PGTStorage_Db class is a class for PGT database storage. - * - * @class CAS_PGTStorage_Db - * @category Authentication - * @package PhpCAS - * @author Daniel Frett - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - * - * @ingroup internalPGTStorageDb - */ - -class CAS_PGTStorage_Db extends CAS_PGTStorage_AbstractStorage -{ - /** - * @addtogroup internalCAS_PGTStorageDb - * @{ - */ - - /** - * the PDO object to use for database interactions - */ - private $_pdo; - - /** - * This method returns the PDO object to use for database interactions. - * - * @return PDO object - */ - private function _getPdo() - { - return $this->_pdo; - } - - /** - * database connection options to use when creating a new PDO object - */ - private $_dsn; - private $_username; - private $_password; - private $_driver_options; - - /** - * @var string the table to use for storing/retrieving pgt's - */ - private $_table; - - /** - * This method returns the table to use when storing/retrieving PGT's - * - * @return string the name of the pgt storage table. - */ - private function _getTable() - { - return $this->_table; - } - - // ######################################################################## - // DEBUGGING - // ######################################################################## - - /** - * This method returns an informational string giving the type of storage - * used by the object (used for debugging purposes). - * - * @return string an informational string. - */ - public function getStorageType() - { - return "db"; - } - - /** - * This method returns an informational string giving informations on the - * parameters of the storage.(used for debugging purposes). - * - * @return string an informational string. - * @public - */ - public function getStorageInfo() - { - return 'table=`'.$this->_getTable().'\''; - } - - // ######################################################################## - // CONSTRUCTOR - // ######################################################################## - - /** - * The class constructor. - * - * @param CAS_Client $cas_parent the CAS_Client instance that creates - * the object. - * @param string $dsn_or_pdo a dsn string to use for creating a PDO - * object or a PDO object - * @param string $username the username to use when connecting to - * the database - * @param string $password the password to use when connecting to - * the database - * @param string $table the table to use for storing and - * retrieving PGT's - * @param string $driver_options any driver options to use when - * connecting to the database - */ - public function __construct( - $cas_parent, $dsn_or_pdo, $username='', $password='', $table='', - $driver_options=null - ) { - phpCAS::traceBegin(); - // call the ancestor's constructor - parent::__construct($cas_parent); - - // set default values - if ( empty($table) ) { - $table = CAS_PGT_STORAGE_DB_DEFAULT_TABLE; - } - if ( !is_array($driver_options) ) { - $driver_options = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION); - } - - // store the specified parameters - if ($dsn_or_pdo instanceof PDO) { - $this->_pdo = $dsn_or_pdo; - } else { - $this->_dsn = $dsn_or_pdo; - $this->_username = $username; - $this->_password = $password; - $this->_driver_options = $driver_options; - } - - // store the table name - $this->_table = $table; - - phpCAS::traceEnd(); - } - - // ######################################################################## - // INITIALIZATION - // ######################################################################## - - /** - * This method is used to initialize the storage. Halts on error. - * - * @return void - */ - public function init() - { - phpCAS::traceBegin(); - // if the storage has already been initialized, return immediatly - if ($this->isInitialized()) { - return; - } - - // initialize the base object - parent::init(); - - // create the PDO object if it doesn't exist already - if (!($this->_pdo instanceof PDO)) { - try { - $this->_pdo = new PDO( - $this->_dsn, $this->_username, $this->_password, - $this->_driver_options - ); - } - catch(PDOException $e) { - phpCAS::error('Database connection error: ' . $e->getMessage()); - } - } - - phpCAS::traceEnd(); - } - - // ######################################################################## - // PDO database interaction - // ######################################################################## - - /** - * attribute that stores the previous error mode for the PDO handle while - * processing a transaction - */ - private $_errMode; - - /** - * This method will enable the Exception error mode on the PDO object - * - * @return void - */ - private function _setErrorMode() - { - // get PDO object and enable exception error mode - $pdo = $this->_getPdo(); - $this->_errMode = $pdo->getAttribute(PDO::ATTR_ERRMODE); - $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - } - - /** - * this method will reset the error mode on the PDO object - * - * @return void - */ - private function _resetErrorMode() - { - // get PDO object and reset the error mode to what it was originally - $pdo = $this->_getPdo(); - $pdo->setAttribute(PDO::ATTR_ERRMODE, $this->_errMode); - } - - // ######################################################################## - // database queries - // ######################################################################## - // these queries are potentially unsafe because the person using this library - // can set the table to use, but there is no reliable way to escape SQL - // fieldnames in PDO yet - - /** - * This method returns the query used to create a pgt storage table - * - * @return string the create table SQL, no bind params in query - */ - protected function createTableSql() - { - return 'CREATE TABLE ' . $this->_getTable() - . ' (pgt_iou VARCHAR(255) NOT NULL PRIMARY KEY, pgt VARCHAR(255) NOT NULL)'; - } - - /** - * This method returns the query used to store a pgt - * - * @return string the store PGT SQL, :pgt and :pgt_iou are the bind params contained - * in the query - */ - protected function storePgtSql() - { - return 'INSERT INTO ' . $this->_getTable() - . ' (pgt_iou, pgt) VALUES (:pgt_iou, :pgt)'; - } - - /** - * This method returns the query used to retrieve a pgt. the first column - * of the first row should contain the pgt - * - * @return string the retrieve PGT SQL, :pgt_iou is the only bind param contained - * in the query - */ - protected function retrievePgtSql() - { - return 'SELECT pgt FROM ' . $this->_getTable() . ' WHERE pgt_iou = :pgt_iou'; - } - - /** - * This method returns the query used to delete a pgt. - * - * @return string the delete PGT SQL, :pgt_iou is the only bind param contained in - * the query - */ - protected function deletePgtSql() - { - return 'DELETE FROM ' . $this->_getTable() . ' WHERE pgt_iou = :pgt_iou'; - } - - // ######################################################################## - // PGT I/O - // ######################################################################## - - /** - * This method creates the database table used to store pgt's and pgtiou's - * - * @return void - */ - public function createTable() - { - phpCAS::traceBegin(); - - // initialize this PGTStorage object if it hasn't been initialized yet - if ( !$this->isInitialized() ) { - $this->init(); - } - - // initialize the PDO object for this method - $pdo = $this->_getPdo(); - $this->_setErrorMode(); - - try { - $pdo->beginTransaction(); - - $query = $pdo->query($this->createTableSQL()); - $query->closeCursor(); - - $pdo->commit(); - } - catch(PDOException $e) { - // attempt rolling back the transaction before throwing a phpCAS error - try { - $pdo->rollBack(); - } - catch(PDOException $e) { - } - phpCAS::error('error creating PGT storage table: ' . $e->getMessage()); - } - - // reset the PDO object - $this->_resetErrorMode(); - - phpCAS::traceEnd(); - } - - /** - * This method stores a PGT and its corresponding PGT Iou in the database. - * Echoes a warning on error. - * - * @param string $pgt the PGT - * @param string $pgt_iou the PGT iou - * - * @return void - */ - public function write($pgt, $pgt_iou) - { - phpCAS::traceBegin(); - - // initialize the PDO object for this method - $pdo = $this->_getPdo(); - $this->_setErrorMode(); - - try { - $pdo->beginTransaction(); - - $query = $pdo->prepare($this->storePgtSql()); - $query->bindValue(':pgt', $pgt, PDO::PARAM_STR); - $query->bindValue(':pgt_iou', $pgt_iou, PDO::PARAM_STR); - $query->execute(); - $query->closeCursor(); - - $pdo->commit(); - } - catch(PDOException $e) { - // attempt rolling back the transaction before throwing a phpCAS error - try { - $pdo->rollBack(); - } - catch(PDOException $e) { - } - phpCAS::error('error writing PGT to database: ' . $e->getMessage()); - } - - // reset the PDO object - $this->_resetErrorMode(); - - phpCAS::traceEnd(); - } - - /** - * This method reads a PGT corresponding to a PGT Iou and deletes the - * corresponding db entry. - * - * @param string $pgt_iou the PGT iou - * - * @return string|false the corresponding PGT, or FALSE on error - */ - public function read($pgt_iou) - { - phpCAS::traceBegin(); - $pgt = false; - - // initialize the PDO object for this method - $pdo = $this->_getPdo(); - $this->_setErrorMode(); - - try { - $pdo->beginTransaction(); - - // fetch the pgt for the specified pgt_iou - $query = $pdo->prepare($this->retrievePgtSql()); - $query->bindValue(':pgt_iou', $pgt_iou, PDO::PARAM_STR); - $query->execute(); - $pgt = $query->fetchColumn(0); - $query->closeCursor(); - - // delete the specified pgt_iou from the database - $query = $pdo->prepare($this->deletePgtSql()); - $query->bindValue(':pgt_iou', $pgt_iou, PDO::PARAM_STR); - $query->execute(); - $query->closeCursor(); - - $pdo->commit(); - } - catch(PDOException $e) { - // attempt rolling back the transaction before throwing a phpCAS error - try { - $pdo->rollBack(); - } - catch(PDOException $e) { - } - phpCAS::trace('error reading PGT from database: ' . $e->getMessage()); - } - - // reset the PDO object - $this->_resetErrorMode(); - - phpCAS::traceEnd(); - return $pgt; - } - - /** @} */ - -} - -?> diff --git a/lib/apereo/phpcas/source/CAS/PGTStorage/File.php b/lib/apereo/phpcas/source/CAS/PGTStorage/File.php deleted file mode 100644 index fbacd3b7d..000000000 --- a/lib/apereo/phpcas/source/CAS/PGTStorage/File.php +++ /dev/null @@ -1,261 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * The CAS_PGTStorage_File class is a class for PGT file storage. An instance of - * this class is returned by CAS_Client::SetPGTStorageFile(). - * - * @class CAS_PGTStorage_File - * @category Authentication - * @package PhpCAS - * @author Pascal Aubry - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - * - * - * @ingroup internalPGTStorageFile - */ - -class CAS_PGTStorage_File extends CAS_PGTStorage_AbstractStorage -{ - /** - * @addtogroup internalPGTStorageFile - * @{ - */ - - /** - * a string telling where PGT's should be stored on the filesystem. Written by - * PGTStorageFile::PGTStorageFile(), read by getPath(). - * - * @private - */ - var $_path; - - /** - * This method returns the name of the directory where PGT's should be stored - * on the filesystem. - * - * @return string the name of a directory (with leading and trailing '/') - * - * @private - */ - function getPath() - { - return $this->_path; - } - - // ######################################################################## - // DEBUGGING - // ######################################################################## - - /** - * This method returns an informational string giving the type of storage - * used by the object (used for debugging purposes). - * - * @return string an informational string. - * @public - */ - function getStorageType() - { - return "file"; - } - - /** - * This method returns an informational string giving informations on the - * parameters of the storage.(used for debugging purposes). - * - * @return string an informational string. - * @public - */ - function getStorageInfo() - { - return 'path=`'.$this->getPath().'\''; - } - - // ######################################################################## - // CONSTRUCTOR - // ######################################################################## - - /** - * The class constructor, called by CAS_Client::SetPGTStorageFile(). - * - * @param CAS_Client $cas_parent the CAS_Client instance that creates the object. - * @param string $path the path where the PGT's should be stored - * - * @return void - * - * @public - */ - function __construct($cas_parent,$path) - { - phpCAS::traceBegin(); - // call the ancestor's constructor - parent::__construct($cas_parent); - - if (empty($path)) { - $path = CAS_PGT_STORAGE_FILE_DEFAULT_PATH; - } - // check that the path is an absolute path - if (getenv("OS")=="Windows_NT" || strtoupper(substr(PHP_OS,0,3)) == 'WIN') { - - if (!preg_match('`^[a-zA-Z]:`', $path)) { - phpCAS::error('an absolute path is needed for PGT storage to file'); - } - - } else { - - if ( $path[0] != '/' ) { - phpCAS::error('an absolute path is needed for PGT storage to file'); - } - - // store the path (with a leading and trailing '/') - $path = preg_replace('|[/]*$|', '/', $path); - $path = preg_replace('|^[/]*|', '/', $path); - } - - $this->_path = $path; - phpCAS::traceEnd(); - } - - // ######################################################################## - // INITIALIZATION - // ######################################################################## - - /** - * This method is used to initialize the storage. Halts on error. - * - * @return void - * @public - */ - function init() - { - phpCAS::traceBegin(); - // if the storage has already been initialized, return immediatly - if ($this->isInitialized()) { - return; - } - // call the ancestor's method (mark as initialized) - parent::init(); - phpCAS::traceEnd(); - } - - // ######################################################################## - // PGT I/O - // ######################################################################## - - /** - * This method returns the filename corresponding to a PGT Iou. - * - * @param string $pgt_iou the PGT iou. - * - * @return string a filename - * @private - */ - function getPGTIouFilename($pgt_iou) - { - phpCAS::traceBegin(); - $filename = $this->getPath()."phpcas-".hash("sha256", $pgt_iou); -// $filename = $this->getPath().$pgt_iou.'.plain'; - phpCAS::trace("Sha256 filename:" . $filename); - phpCAS::traceEnd(); - return $filename; - } - - /** - * This method stores a PGT and its corresponding PGT Iou into a file. Echoes a - * warning on error. - * - * @param string $pgt the PGT - * @param string $pgt_iou the PGT iou - * - * @return void - * - * @public - */ - function write($pgt,$pgt_iou) - { - phpCAS::traceBegin(); - $fname = $this->getPGTIouFilename($pgt_iou); - if (!file_exists($fname)) { - touch($fname); - // Chmod will fail on windows - @chmod($fname, 0600); - if ($f=fopen($fname, "w")) { - if (fputs($f, $pgt) === false) { - phpCAS::error('could not write PGT to `'.$fname.'\''); - } - phpCAS::trace('Successful write of PGT to `'.$fname.'\''); - fclose($f); - } else { - phpCAS::error('could not open `'.$fname.'\''); - } - } else { - phpCAS::error('File exists: `'.$fname.'\''); - } - phpCAS::traceEnd(); - } - - /** - * This method reads a PGT corresponding to a PGT Iou and deletes the - * corresponding file. - * - * @param string $pgt_iou the PGT iou - * - * @return string|false the corresponding PGT, or FALSE on error - * - * @public - */ - function read($pgt_iou) - { - phpCAS::traceBegin(); - $pgt = false; - $fname = $this->getPGTIouFilename($pgt_iou); - if (file_exists($fname)) { - if (!($f=fopen($fname, "r"))) { - phpCAS::error('could not open `'.$fname.'\''); - } else { - if (($pgt=fgets($f)) === false) { - phpCAS::error('could not read PGT from `'.$fname.'\''); - } - phpCAS::trace('Successful read of PGT to `'.$fname.'\''); - fclose($f); - } - // delete the PGT file - @unlink($fname); - } else { - phpCAS::error('No such file `'.$fname.'\''); - } - phpCAS::traceEnd($pgt); - return $pgt; - } - - /** @} */ - -} -?> diff --git a/lib/apereo/phpcas/source/CAS/ProxiedService.php b/lib/apereo/phpcas/source/CAS/ProxiedService.php deleted file mode 100644 index 2673ee955..000000000 --- a/lib/apereo/phpcas/source/CAS/ProxiedService.php +++ /dev/null @@ -1,72 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * This interface defines methods that allow proxy-authenticated service handlers - * to interact with phpCAS. - * - * Proxy service handlers must implement this interface as well as call - * phpCAS::initializeProxiedService($this) at some point in their implementation. - * - * While not required, proxy-authenticated service handlers are encouraged to - * implement the CAS_ProxiedService_Testable interface to facilitate unit testing. - * - * @class CAS_ProxiedService - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -interface CAS_ProxiedService -{ - - /** - * Answer a service identifier (URL) for whom we should fetch a proxy ticket. - * - * @return string - * @throws Exception If no service url is available. - */ - public function getServiceUrl (); - - /** - * Register a proxy ticket with the ProxiedService that it can use when - * making requests. - * - * @param string $proxyTicket Proxy ticket string - * - * @return void - * @throws InvalidArgumentException If the $proxyTicket is invalid. - * @throws CAS_OutOfSequenceException If called after a proxy ticket has - * already been initialized/set. - */ - public function setProxyTicket ($proxyTicket); - -} -?> diff --git a/lib/apereo/phpcas/source/CAS/ProxiedService/Abstract.php b/lib/apereo/phpcas/source/CAS/ProxiedService/Abstract.php deleted file mode 100644 index 0801c723b..000000000 --- a/lib/apereo/phpcas/source/CAS/ProxiedService/Abstract.php +++ /dev/null @@ -1,149 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * This class implements common methods for ProxiedService implementations included - * with phpCAS. - * - * @class CAS_ProxiedService_Abstract - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -abstract class CAS_ProxiedService_Abstract -implements CAS_ProxiedService, CAS_ProxiedService_Testable -{ - - /** - * The proxy ticket that can be used when making service requests. - * @var string $_proxyTicket; - */ - private $_proxyTicket; - - /** - * Register a proxy ticket with the Proxy that it can use when making requests. - * - * @param string $proxyTicket proxy ticket - * - * @return void - * @throws InvalidArgumentException If the $proxyTicket is invalid. - * @throws CAS_OutOfSequenceException If called after a proxy ticket has - * already been initialized/set. - */ - public function setProxyTicket ($proxyTicket) - { - if (empty($proxyTicket)) { - throw new CAS_InvalidArgumentException( - 'Trying to initialize with an empty proxy ticket.' - ); - } - if (!empty($this->_proxyTicket)) { - throw new CAS_OutOfSequenceException( - 'Already initialized, cannot change the proxy ticket.' - ); - } - $this->_proxyTicket = $proxyTicket; - } - - /** - * Answer the proxy ticket to be used when making requests. - * - * @return string - * @throws CAS_OutOfSequenceException If called before a proxy ticket has - * already been initialized/set. - */ - protected function getProxyTicket () - { - if (empty($this->_proxyTicket)) { - throw new CAS_OutOfSequenceException( - 'No proxy ticket yet. Call $this->initializeProxyTicket() to aquire the proxy ticket.' - ); - } - - return $this->_proxyTicket; - } - - /** - * @var CAS_Client $_casClient; - */ - private $_casClient; - - /** - * Use a particular CAS_Client->initializeProxiedService() rather than the - * static phpCAS::initializeProxiedService(). - * - * This method should not be called in standard operation, but is needed for unit - * testing. - * - * @param CAS_Client $casClient cas client - * - * @return void - * @throws CAS_OutOfSequenceException If called after a proxy ticket has - * already been initialized/set. - */ - public function setCasClient (CAS_Client $casClient) - { - if (!empty($this->_proxyTicket)) { - throw new CAS_OutOfSequenceException( - 'Already initialized, cannot change the CAS_Client.' - ); - } - - $this->_casClient = $casClient; - } - - /** - * Fetch our proxy ticket. - * - * Descendent classes should call this method once their service URL is available - * to initialize their proxy ticket. - * - * @return void - * @throws CAS_OutOfSequenceException If called after a proxy ticket has - * already been initialized. - */ - protected function initializeProxyTicket() - { - if (!empty($this->_proxyTicket)) { - throw new CAS_OutOfSequenceException( - 'Already initialized, cannot initialize again.' - ); - } - // Allow usage of a particular CAS_Client for unit testing. - if (empty($this->_casClient)) { - phpCAS::initializeProxiedService($this); - } else { - $this->_casClient->initializeProxiedService($this); - } - } - -} -?> diff --git a/lib/apereo/phpcas/source/CAS/ProxiedService/Exception.php b/lib/apereo/phpcas/source/CAS/ProxiedService/Exception.php deleted file mode 100644 index 0f87413dd..000000000 --- a/lib/apereo/phpcas/source/CAS/ProxiedService/Exception.php +++ /dev/null @@ -1,46 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * An Exception for problems communicating with a proxied service. - * - * @class CAS_ProxiedService_Exception - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -class CAS_ProxiedService_Exception -extends Exception -implements CAS_Exception -{ - -} -?> diff --git a/lib/apereo/phpcas/source/CAS/ProxiedService/Http.php b/lib/apereo/phpcas/source/CAS/ProxiedService/Http.php deleted file mode 100644 index 4240b061a..000000000 --- a/lib/apereo/phpcas/source/CAS/ProxiedService/Http.php +++ /dev/null @@ -1,91 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * This interface defines methods that clients should use for configuring, sending, - * and receiving proxied HTTP requests. - * - * @class CAS_ProxiedService_Http - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -interface CAS_ProxiedService_Http -{ - - /********************************************************* - * Configure the Request - *********************************************************/ - - /** - * Set the URL of the Request - * - * @param string $url Url to set - * - * @return void - * @throws CAS_OutOfSequenceException If called after the Request has been sent. - */ - public function setUrl ($url); - - /********************************************************* - * 2. Send the Request - *********************************************************/ - - /** - * Perform the request. - * - * @return bool TRUE on success, FALSE on failure. - * @throws CAS_OutOfSequenceException If called multiple times. - */ - public function send (); - - /********************************************************* - * 3. Access the response - *********************************************************/ - - /** - * Answer the headers of the response. - * - * @return array An array of header strings. - * @throws CAS_OutOfSequenceException If called before the Request has been sent. - */ - public function getResponseHeaders (); - - /** - * Answer the body of response. - * - * @return string - * @throws CAS_OutOfSequenceException If called before the Request has been sent. - */ - public function getResponseBody (); - -} -?> diff --git a/lib/apereo/phpcas/source/CAS/ProxiedService/Http/Abstract.php b/lib/apereo/phpcas/source/CAS/ProxiedService/Http/Abstract.php deleted file mode 100644 index 8d55edd50..000000000 --- a/lib/apereo/phpcas/source/CAS/ProxiedService/Http/Abstract.php +++ /dev/null @@ -1,360 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * This class implements common methods for ProxiedService implementations included - * with phpCAS. - * - * @class CAS_ProxiedService_Http_Abstract - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -abstract class CAS_ProxiedService_Http_Abstract extends -CAS_ProxiedService_Abstract implements CAS_ProxiedService_Http -{ - /** - * The HTTP request mechanism talking to the target service. - * - * @var CAS_Request_RequestInterface $requestHandler - */ - protected $requestHandler; - - /** - * The storage mechanism for cookies set by the target service. - * - * @var CAS_CookieJar $_cookieJar - */ - private $_cookieJar; - - /** - * Constructor. - * - * @param CAS_Request_RequestInterface $requestHandler request handler object - * @param CAS_CookieJar $cookieJar cookieJar object - * - * @return void - */ - public function __construct(CAS_Request_RequestInterface $requestHandler, - CAS_CookieJar $cookieJar - ) { - $this->requestHandler = $requestHandler; - $this->_cookieJar = $cookieJar; - } - - /** - * The target service url. - * @var string $_url; - */ - private $_url; - - /** - * Answer a service identifier (URL) for whom we should fetch a proxy ticket. - * - * @return string - * @throws Exception If no service url is available. - */ - public function getServiceUrl() - { - if (empty($this->_url)) { - throw new CAS_ProxiedService_Exception( - 'No URL set via ' . get_class($this) . '->setUrl($url).' - ); - } - - return $this->_url; - } - - /********************************************************* - * Configure the Request - *********************************************************/ - - /** - * Set the URL of the Request - * - * @param string $url url to set - * - * @return void - * @throws CAS_OutOfSequenceException If called after the Request has been sent. - */ - public function setUrl($url) - { - if ($this->hasBeenSent()) { - throw new CAS_OutOfSequenceException( - 'Cannot set the URL, request already sent.' - ); - } - if (!is_string($url)) { - throw new CAS_InvalidArgumentException('$url must be a string.'); - } - - $this->_url = $url; - } - - /********************************************************* - * 2. Send the Request - *********************************************************/ - - /** - * Perform the request. - * - * @return void - * @throws CAS_OutOfSequenceException If called multiple times. - * @throws CAS_ProxyTicketException If there is a proxy-ticket failure. - * The code of the Exception will be one of: - * PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE - * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE - * PHPCAS_SERVICE_PT_FAILURE - * @throws CAS_ProxiedService_Exception If there is a failure sending the - * request to the target service. - */ - public function send() - { - if ($this->hasBeenSent()) { - throw new CAS_OutOfSequenceException( - 'Cannot send, request already sent.' - ); - } - - phpCAS::traceBegin(); - - // Get our proxy ticket and append it to our URL. - $this->initializeProxyTicket(); - $url = $this->getServiceUrl(); - if (strstr($url, '?') === false) { - $url = $url . '?ticket=' . $this->getProxyTicket(); - } else { - $url = $url . '&ticket=' . $this->getProxyTicket(); - } - - try { - $this->makeRequest($url); - } catch (Exception $e) { - phpCAS::traceEnd(); - throw $e; - } - } - - /** - * Indicator of the number of requests (including redirects performed. - * - * @var int $_numRequests; - */ - private $_numRequests = 0; - - /** - * The response headers. - * - * @var array $_responseHeaders; - */ - private $_responseHeaders = array(); - - /** - * The response status code. - * - * @var int $_responseStatusCode; - */ - private $_responseStatusCode = ''; - - /** - * The response headers. - * - * @var string $_responseBody; - */ - private $_responseBody = ''; - - /** - * Build and perform a request, following redirects - * - * @param string $url url for the request - * - * @return void - * @throws CAS_ProxyTicketException If there is a proxy-ticket failure. - * The code of the Exception will be one of: - * PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE - * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE - * PHPCAS_SERVICE_PT_FAILURE - * @throws CAS_ProxiedService_Exception If there is a failure sending the - * request to the target service. - */ - protected function makeRequest($url) - { - // Verify that we are not in a redirect loop - $this->_numRequests++; - if ($this->_numRequests > 4) { - $message = 'Exceeded the maximum number of redirects (3) in proxied service request.'; - phpCAS::trace($message); - throw new CAS_ProxiedService_Exception($message); - } - - // Create a new request. - $request = clone $this->requestHandler; - $request->setUrl($url); - - // Add any cookies to the request. - $request->addCookies($this->_cookieJar->getCookies($url)); - - // Add any other parts of the request needed by concrete classes - $this->populateRequest($request); - - // Perform the request. - phpCAS::trace('Performing proxied service request to \'' . $url . '\''); - if (!$request->send()) { - $message = 'Could not perform proxied service request to URL`' - . $url . '\'. ' . $request->getErrorMessage(); - phpCAS::trace($message); - throw new CAS_ProxiedService_Exception($message); - } - - // Store any cookies from the response; - $this->_cookieJar->storeCookies($url, $request->getResponseHeaders()); - - // Follow any redirects - if ($redirectUrl = $this->getRedirectUrl($request->getResponseHeaders()) - ) { - phpCAS::trace('Found redirect:' . $redirectUrl); - $this->makeRequest($redirectUrl); - } else { - - $this->_responseHeaders = $request->getResponseHeaders(); - $this->_responseBody = $request->getResponseBody(); - $this->_responseStatusCode = $request->getResponseStatusCode(); - } - } - - /** - * Add any other parts of the request needed by concrete classes - * - * @param CAS_Request_RequestInterface $request request interface object - * - * @return void - */ - abstract protected function populateRequest( - CAS_Request_RequestInterface $request - ); - - /** - * Answer a redirect URL if a redirect header is found, otherwise null. - * - * @param array $responseHeaders response header to extract a redirect from - * - * @return string|null - */ - protected function getRedirectUrl(array $responseHeaders) - { - // Check for the redirect after authentication - foreach ($responseHeaders as $header) { - if ( preg_match('/^(Location:|URI:)\s*([^\s]+.*)$/', $header, $matches) - ) { - return trim(array_pop($matches)); - } - } - return null; - } - - /********************************************************* - * 3. Access the response - *********************************************************/ - - /** - * Answer true if our request has been sent yet. - * - * @return bool - */ - protected function hasBeenSent() - { - return ($this->_numRequests > 0); - } - - /** - * Answer the headers of the response. - * - * @return array An array of header strings. - * @throws CAS_OutOfSequenceException If called before the Request has been sent. - */ - public function getResponseHeaders() - { - if (!$this->hasBeenSent()) { - throw new CAS_OutOfSequenceException( - 'Cannot access response, request not sent yet.' - ); - } - - return $this->_responseHeaders; - } - - /** - * Answer HTTP status code of the response - * - * @return int - * @throws CAS_OutOfSequenceException If called before the Request has been sent. - */ - public function getResponseStatusCode() - { - if (!$this->hasBeenSent()) { - throw new CAS_OutOfSequenceException( - 'Cannot access response, request not sent yet.' - ); - } - - return $this->_responseStatusCode; - } - - /** - * Answer the body of response. - * - * @return string - * @throws CAS_OutOfSequenceException If called before the Request has been sent. - */ - public function getResponseBody() - { - if (!$this->hasBeenSent()) { - throw new CAS_OutOfSequenceException( - 'Cannot access response, request not sent yet.' - ); - } - - return $this->_responseBody; - } - - /** - * Answer the cookies from the response. This may include cookies set during - * redirect responses. - * - * @return array An array containing cookies. E.g. array('name' => 'val'); - */ - public function getCookies() - { - return $this->_cookieJar->getCookies($this->getServiceUrl()); - } - -} -?> diff --git a/lib/apereo/phpcas/source/CAS/ProxiedService/Http/Get.php b/lib/apereo/phpcas/source/CAS/ProxiedService/Http/Get.php deleted file mode 100644 index a459d55ae..000000000 --- a/lib/apereo/phpcas/source/CAS/ProxiedService/Http/Get.php +++ /dev/null @@ -1,85 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * This class is used to make proxied service requests via the HTTP GET method. - * - * Usage Example: - * - * try { - * $service = phpCAS::getProxiedService(PHPCAS_PROXIED_SERVICE_HTTP_GET); - * $service->setUrl('http://www.example.com/path/'); - * $service->send(); - * if ($service->getResponseStatusCode() == 200) - * return $service->getResponseBody(); - * else - * // The service responded with an error code 404, 500, etc. - * throw new Exception('The service responded with an error.'); - * - * } catch (CAS_ProxyTicketException $e) { - * if ($e->getCode() == PHPCAS_SERVICE_PT_FAILURE) - * return "Your login has timed out. You need to log in again."; - * else - * // Other proxy ticket errors are from bad request format - * // (shouldn't happen) or CAS server failure (unlikely) - * // so lets just stop if we hit those. - * throw $e; - * } catch (CAS_ProxiedService_Exception $e) { - * // Something prevented the service request from being sent or received. - * // We didn't even get a valid error response (404, 500, etc), so this - * // might be caused by a network error or a DNS resolution failure. - * // We could handle it in some way, but for now we will just stop. - * throw $e; - * } - * - * @class CAS_ProxiedService_Http_Get - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -class CAS_ProxiedService_Http_Get -extends CAS_ProxiedService_Http_Abstract -{ - - /** - * Add any other parts of the request needed by concrete classes - * - * @param CAS_Request_RequestInterface $request request interface - * - * @return void - */ - protected function populateRequest (CAS_Request_RequestInterface $request) - { - // do nothing, since the URL has already been sent and that is our - // only data. - } -} -?> diff --git a/lib/apereo/phpcas/source/CAS/ProxiedService/Http/Post.php b/lib/apereo/phpcas/source/CAS/ProxiedService/Http/Post.php deleted file mode 100644 index 344c43987..000000000 --- a/lib/apereo/phpcas/source/CAS/ProxiedService/Http/Post.php +++ /dev/null @@ -1,152 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * This class is used to make proxied service requests via the HTTP POST method. - * - * Usage Example: - * - * try { - * $service = phpCAS::getProxiedService(PHPCAS_PROXIED_SERVICE_HTTP_POST); - * $service->setUrl('http://www.example.com/path/'); - * $service->setContentType('text/xml'); - * $service->setBody('example.search'); - * $service->send(); - * if ($service->getResponseStatusCode() == 200) - * return $service->getResponseBody(); - * else - * // The service responded with an error code 404, 500, etc. - * throw new Exception('The service responded with an error.'); - * - * } catch (CAS_ProxyTicketException $e) { - * if ($e->getCode() == PHPCAS_SERVICE_PT_FAILURE) - * return "Your login has timed out. You need to log in again."; - * else - * // Other proxy ticket errors are from bad request format - * // (shouldn't happen) or CAS server failure (unlikely) so lets just - * // stop if we hit those. - * throw $e; - * } catch (CAS_ProxiedService_Exception $e) { - * // Something prevented the service request from being sent or received. - * // We didn't even get a valid error response (404, 500, etc), so this - * // might be caused by a network error or a DNS resolution failure. - * // We could handle it in some way, but for now we will just stop. - * throw $e; - * } - * - * @class CAS_ProxiedService_Http_Post - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -class CAS_ProxiedService_Http_Post -extends CAS_ProxiedService_Http_Abstract -{ - - /** - * The content-type of this request - * - * @var string $_contentType - */ - private $_contentType; - - /** - * The body of the this request - * - * @var string $_body - */ - private $_body; - - /** - * Set the content type of this POST request. - * - * @param string $contentType content type - * - * @return void - * @throws CAS_OutOfSequenceException If called after the Request has been sent. - */ - public function setContentType ($contentType) - { - if ($this->hasBeenSent()) { - throw new CAS_OutOfSequenceException( - 'Cannot set the content type, request already sent.' - ); - } - - $this->_contentType = $contentType; - } - - /** - * Set the body of this POST request. - * - * @param string $body body to set - * - * @return void - * @throws CAS_OutOfSequenceException If called after the Request has been sent. - */ - public function setBody ($body) - { - if ($this->hasBeenSent()) { - throw new CAS_OutOfSequenceException( - 'Cannot set the body, request already sent.' - ); - } - - $this->_body = $body; - } - - /** - * Add any other parts of the request needed by concrete classes - * - * @param CAS_Request_RequestInterface $request request interface class - * - * @return void - */ - protected function populateRequest (CAS_Request_RequestInterface $request) - { - if (empty($this->_contentType) && !empty($this->_body)) { - throw new CAS_ProxiedService_Exception( - "If you pass a POST body, you must specify a content type via " - .get_class($this).'->setContentType($contentType).' - ); - } - - $request->makePost(); - if (!empty($this->_body)) { - $request->addHeader('Content-Type: '.$this->_contentType); - $request->addHeader('Content-Length: '.strlen($this->_body)); - $request->setPostBody($this->_body); - } - } - - -} -?> diff --git a/lib/apereo/phpcas/source/CAS/ProxiedService/Imap.php b/lib/apereo/phpcas/source/CAS/ProxiedService/Imap.php deleted file mode 100644 index c4b47401d..000000000 --- a/lib/apereo/phpcas/source/CAS/ProxiedService/Imap.php +++ /dev/null @@ -1,281 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * Provides access to a proxy-authenticated IMAP stream - * - * @class CAS_ProxiedService_Imap - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -class CAS_ProxiedService_Imap -extends CAS_ProxiedService_Abstract -{ - - /** - * The username to send via imap_open. - * - * @var string $_username; - */ - private $_username; - - /** - * Constructor. - * - * @param string $username Username - * - * @return void - */ - public function __construct ($username) - { - if (!is_string($username) || !strlen($username)) { - throw new CAS_InvalidArgumentException('Invalid username.'); - } - - $this->_username = $username; - } - - /** - * The target service url. - * @var string $_url; - */ - private $_url; - - /** - * Answer a service identifier (URL) for whom we should fetch a proxy ticket. - * - * @return string - * @throws Exception If no service url is available. - */ - public function getServiceUrl () - { - if (empty($this->_url)) { - throw new CAS_ProxiedService_Exception( - 'No URL set via '.get_class($this).'->getServiceUrl($url).' - ); - } - - return $this->_url; - } - - /********************************************************* - * Configure the Stream - *********************************************************/ - - /** - * Set the URL of the service to pass to CAS for proxy-ticket retrieval. - * - * @param string $url Url to set - * - * @return void - * @throws CAS_OutOfSequenceException If called after the stream has been opened. - */ - public function setServiceUrl ($url) - { - if ($this->hasBeenOpened()) { - throw new CAS_OutOfSequenceException( - 'Cannot set the URL, stream already opened.' - ); - } - if (!is_string($url) || !strlen($url)) { - throw new CAS_InvalidArgumentException('Invalid url.'); - } - - $this->_url = $url; - } - - /** - * The mailbox to open. See the $mailbox parameter of imap_open(). - * - * @var string $_mailbox - */ - private $_mailbox; - - /** - * Set the mailbox to open. See the $mailbox parameter of imap_open(). - * - * @param string $mailbox Mailbox to set - * - * @return void - * @throws CAS_OutOfSequenceException If called after the stream has been opened. - */ - public function setMailbox ($mailbox) - { - if ($this->hasBeenOpened()) { - throw new CAS_OutOfSequenceException( - 'Cannot set the mailbox, stream already opened.' - ); - } - if (!is_string($mailbox) || !strlen($mailbox)) { - throw new CAS_InvalidArgumentException('Invalid mailbox.'); - } - - $this->_mailbox = $mailbox; - } - - /** - * A bit mask of options to pass to imap_open() as the $options parameter. - * - * @var int $_options - */ - private $_options = null; - - /** - * Set the options for opening the stream. See the $options parameter of - * imap_open(). - * - * @param int $options Options for the stream - * - * @return void - * @throws CAS_OutOfSequenceException If called after the stream has been opened. - */ - public function setOptions ($options) - { - if ($this->hasBeenOpened()) { - throw new CAS_OutOfSequenceException( - 'Cannot set options, stream already opened.' - ); - } - if (!is_int($options)) { - throw new CAS_InvalidArgumentException('Invalid options.'); - } - - $this->_options = $options; - } - - /********************************************************* - * 2. Open the stream - *********************************************************/ - - /** - * Open the IMAP stream (similar to imap_open()). - * - * @return resource Returns an IMAP stream on success - * @throws CAS_OutOfSequenceException If called multiple times. - * @throws CAS_ProxyTicketException If there is a proxy-ticket failure. - * The code of the Exception will be one of: - * PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE - * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE - * PHPCAS_SERVICE_PT_FAILURE - * @throws CAS_ProxiedService_Exception If there is a failure sending the - * request to the target service. - */ - public function open () - { - if ($this->hasBeenOpened()) { - throw new CAS_OutOfSequenceException('Stream already opened.'); - } - if (empty($this->_mailbox)) { - throw new CAS_ProxiedService_Exception( - 'You must specify a mailbox via '.get_class($this) - .'->setMailbox($mailbox)' - ); - } - - phpCAS::traceBegin(); - - // Get our proxy ticket and append it to our URL. - $this->initializeProxyTicket(); - phpCAS::trace('opening IMAP mailbox `'.$this->_mailbox.'\'...'); - $this->_stream = @imap_open( - $this->_mailbox, $this->_username, $this->getProxyTicket(), - $this->_options - ); - if ($this->_stream) { - phpCAS::trace('ok'); - } else { - phpCAS::trace('could not open mailbox'); - // @todo add localization integration. - $message = 'IMAP Error: '.$this->_url.' '. var_export(imap_errors(), true); - phpCAS::trace($message); - throw new CAS_ProxiedService_Exception($message); - } - - phpCAS::traceEnd(); - return $this->_stream; - } - - /** - * Answer true if our request has been sent yet. - * - * @return bool - */ - protected function hasBeenOpened () - { - return !empty($this->_stream); - } - - /********************************************************* - * 3. Access the result - *********************************************************/ - /** - * The IMAP stream - * - * @var resource $_stream - */ - private $_stream; - - /** - * Answer the IMAP stream - * - * @return resource - * @throws CAS_OutOfSequenceException if stream is not opened yet - */ - public function getStream () - { - if (!$this->hasBeenOpened()) { - throw new CAS_OutOfSequenceException( - 'Cannot access stream, not opened yet.' - ); - } - return $this->_stream; - } - - /** - * CAS_Client::serviceMail() needs to return the proxy ticket for some reason, - * so this method provides access to it. - * - * @return string - * @throws CAS_OutOfSequenceException If called before the stream has been - * opened. - */ - public function getImapProxyTicket () - { - if (!$this->hasBeenOpened()) { - throw new CAS_OutOfSequenceException( - 'Cannot access errors, stream not opened yet.' - ); - } - return $this->getProxyTicket(); - } -} -?> diff --git a/lib/apereo/phpcas/source/CAS/ProxiedService/Testable.php b/lib/apereo/phpcas/source/CAS/ProxiedService/Testable.php deleted file mode 100644 index 3ce44fd16..000000000 --- a/lib/apereo/phpcas/source/CAS/ProxiedService/Testable.php +++ /dev/null @@ -1,75 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * This interface defines methods that allow proxy-authenticated service handlers - * to be tested in unit tests. - * - * Classes implementing this interface SHOULD store the CAS_Client passed and - * initialize themselves with that client rather than via the static phpCAS - * method. For example: - * - * / ** - * * Fetch our proxy ticket. - * * / - * protected function initializeProxyTicket() { - * // Allow usage of a particular CAS_Client for unit testing. - * if (is_null($this->casClient)) - * phpCAS::initializeProxiedService($this); - * else - * $this->casClient->initializeProxiedService($this); - * } - * - * @class CAS_ProxiedService_Testabel - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -interface CAS_ProxiedService_Testable -{ - - /** - * Use a particular CAS_Client->initializeProxiedService() rather than the - * static phpCAS::initializeProxiedService(). - * - * This method should not be called in standard operation, but is needed for unit - * testing. - * - * @param CAS_Client $casClient Cas client object - * - * @return void - * @throws CAS_OutOfSequenceException If called after a proxy ticket has - * already been initialized/set. - */ - public function setCasClient (CAS_Client $casClient); - -} -?> diff --git a/lib/apereo/phpcas/source/CAS/ProxyChain.php b/lib/apereo/phpcas/source/CAS/ProxyChain.php deleted file mode 100644 index e200724ce..000000000 --- a/lib/apereo/phpcas/source/CAS/ProxyChain.php +++ /dev/null @@ -1,127 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * A normal proxy-chain definition that lists each level of the chain as either - * a string or regular expression. - * - * @class CAS_ProxyChain - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -class CAS_ProxyChain -implements CAS_ProxyChain_Interface -{ - - protected $chain = array(); - - /** - * A chain is an array of strings or regexp strings that will be matched - * against. Regexp will be matched with preg_match and strings will be - * matched from the beginning. A string must fully match the beginning of - * an proxy url. So you can define a full domain as acceptable or go further - * down. - * Proxies have to be defined in reverse from the service to the user. If a - * user hits service A get proxied via B to service C the list of acceptable - * proxies on C would be array(B,A); - * - * @param array $chain A chain of proxies - */ - public function __construct(array $chain) - { - // Ensure that we have an indexed array - $this->chain = array_values($chain); - } - - /** - * Match a list of proxies. - * - * @param array $list The list of proxies in front of this service. - * - * @return bool - */ - public function matches(array $list) - { - $list = array_values($list); // Ensure that we have an indexed array - if ($this->isSizeValid($list)) { - $mismatch = false; - foreach ($this->chain as $i => $search) { - $proxy_url = $list[$i]; - if (preg_match('/^\/.*\/[ixASUXu]*$/s', $search)) { - if (preg_match($search, $proxy_url)) { - phpCAS::trace( - "Found regexp " . $search . " matching " . $proxy_url - ); - } else { - phpCAS::trace( - "No regexp match " . $search . " != " . $proxy_url - ); - $mismatch = true; - break; - } - } else { - if (strncasecmp($search, $proxy_url, strlen($search)) == 0) { - phpCAS::trace( - "Found string " . $search . " matching " . $proxy_url - ); - } else { - phpCAS::trace( - "No match " . $search . " != " . $proxy_url - ); - $mismatch = true; - break; - } - } - } - if (!$mismatch) { - phpCAS::trace("Proxy chain matches"); - return true; - } - } else { - phpCAS::trace("Proxy chain skipped: size mismatch"); - } - return false; - } - - /** - * Validate the size of the the list as compared to our chain. - * - * @param array $list List of proxies - * - * @return bool - */ - protected function isSizeValid (array $list) - { - return (sizeof($this->chain) == sizeof($list)); - } -} diff --git a/lib/apereo/phpcas/source/CAS/ProxyChain/AllowedList.php b/lib/apereo/phpcas/source/CAS/ProxyChain/AllowedList.php deleted file mode 100644 index 988ddbb3c..000000000 --- a/lib/apereo/phpcas/source/CAS/ProxyChain/AllowedList.php +++ /dev/null @@ -1,119 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - - -/** - * ProxyChain is a container for storing chains of valid proxies that can - * be used to validate proxied requests to a service - * - * @class CAS_ProxyChain_AllowedList - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -class CAS_ProxyChain_AllowedList -{ - - private $_chains = array(); - - /** - * Check whether proxies are allowed by configuration - * - * @return bool - */ - public function isProxyingAllowed() - { - return (count($this->_chains) > 0); - } - - /** - * Add a chain of proxies to the list of possible chains - * - * @param CAS_ProxyChain_Interface $chain A chain of proxies - * - * @return void - */ - public function allowProxyChain(CAS_ProxyChain_Interface $chain) - { - $this->_chains[] = $chain; - } - - /** - * Check if the proxies found in the response match the allowed proxies - * - * @param array $proxies list of proxies to check - * - * @return bool whether the proxies match the allowed proxies - */ - public function isProxyListAllowed(array $proxies) - { - phpCAS::traceBegin(); - if (empty($proxies)) { - phpCAS::trace("No proxies were found in the response"); - phpCAS::traceEnd(true); - return true; - } elseif (!$this->isProxyingAllowed()) { - phpCAS::trace("Proxies are not allowed"); - phpCAS::traceEnd(false); - return false; - } else { - $res = $this->contains($proxies); - phpCAS::traceEnd($res); - return $res; - } - } - - /** - * Validate the proxies from the proxy ticket validation against the - * chains that were definded. - * - * @param array $list List of proxies from the proxy ticket validation. - * - * @return bool if any chain fully matches the supplied list - */ - public function contains(array $list) - { - phpCAS::traceBegin(); - $count = 0; - foreach ($this->_chains as $chain) { - phpCAS::trace("Checking chain ". $count++); - if ($chain->matches($list)) { - phpCAS::traceEnd(true); - return true; - } - } - phpCAS::trace("No proxy chain matches."); - phpCAS::traceEnd(false); - return false; - } -} -?> diff --git a/lib/apereo/phpcas/source/CAS/ProxyChain/Any.php b/lib/apereo/phpcas/source/CAS/ProxyChain/Any.php deleted file mode 100644 index fe18c5fbf..000000000 --- a/lib/apereo/phpcas/source/CAS/ProxyChain/Any.php +++ /dev/null @@ -1,64 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * A proxy-chain definition that will match any list of proxies. - * - * Use this class for quick testing or in certain production screnarios you - * might want to allow allow any other valid service to proxy your service. - * - * THIS CLASS IS HOWEVER NOT RECOMMENDED FOR PRODUCTION AND HAS SECURITY - * IMPLICATIONS: YOU ARE ALLOWING ANY SERVICE TO ACT ON BEHALF OF A USER - * ON THIS SERVICE. - * - * @class CAS_ProxyChain_Any - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -class CAS_ProxyChain_Any -implements CAS_ProxyChain_Interface -{ - - /** - * Match a list of proxies. - * - * @param array $list The list of proxies in front of this service. - * - * @return bool - */ - public function matches(array $list) - { - phpCAS::trace("Using CAS_ProxyChain_Any. No proxy validation is performed."); - return true; - } - -} diff --git a/lib/apereo/phpcas/source/CAS/ProxyChain/Interface.php b/lib/apereo/phpcas/source/CAS/ProxyChain/Interface.php deleted file mode 100644 index b1d688174..000000000 --- a/lib/apereo/phpcas/source/CAS/ProxyChain/Interface.php +++ /dev/null @@ -1,53 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * An interface for classes that define a list of allowed proxies in front of - * the current application. - * - * @class CAS_ProxyChain_Interface - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -interface CAS_ProxyChain_Interface -{ - - /** - * Match a list of proxies. - * - * @param array $list The list of proxies in front of this service. - * - * @return bool - */ - public function matches(array $list); - -} diff --git a/lib/apereo/phpcas/source/CAS/ProxyChain/Trusted.php b/lib/apereo/phpcas/source/CAS/ProxyChain/Trusted.php deleted file mode 100644 index e67d70852..000000000 --- a/lib/apereo/phpcas/source/CAS/ProxyChain/Trusted.php +++ /dev/null @@ -1,59 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * A proxy-chain definition that defines a chain up to a trusted proxy and - * delegates the resposibility of validating the rest of the chain to that - * trusted proxy. - * - * @class CAS_ProxyChain_Trusted - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -class CAS_ProxyChain_Trusted -extends CAS_ProxyChain -implements CAS_ProxyChain_Interface -{ - - /** - * Validate the size of the the list as compared to our chain. - * - * @param array $list list of proxies - * - * @return bool - */ - protected function isSizeValid (array $list) - { - return (sizeof($this->chain) <= sizeof($list)); - } - -} diff --git a/lib/apereo/phpcas/source/CAS/ProxyTicketException.php b/lib/apereo/phpcas/source/CAS/ProxyTicketException.php deleted file mode 100644 index 2f825b421..000000000 --- a/lib/apereo/phpcas/source/CAS/ProxyTicketException.php +++ /dev/null @@ -1,71 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - * - */ - -/** - * An Exception for errors related to fetching or validating proxy tickets. - * - * @class CAS_ProxyTicketException - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -class CAS_ProxyTicketException -extends BadMethodCallException -implements CAS_Exception -{ - - /** - * Constructor - * - * @param string $message Message text - * @param int $code Error code - * - * @return void - */ - public function __construct ($message, $code = PHPCAS_SERVICE_PT_FAILURE) - { - // Warn if the code is not in our allowed list - $ptCodes = array( - PHPCAS_SERVICE_PT_FAILURE, - PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, - PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE, - ); - if (!in_array($code, $ptCodes)) { - trigger_error( - 'Invalid code '.$code - .' passed. Must be one of PHPCAS_SERVICE_PT_FAILURE, PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, or PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE.' - ); - } - - parent::__construct($message, $code); - } -} diff --git a/lib/apereo/phpcas/source/CAS/Request/AbstractRequest.php b/lib/apereo/phpcas/source/CAS/Request/AbstractRequest.php deleted file mode 100644 index 4f9013ee2..000000000 --- a/lib/apereo/phpcas/source/CAS/Request/AbstractRequest.php +++ /dev/null @@ -1,380 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * Provides support for performing web-requests via curl - * - * @class CAS_Request_AbstractRequest - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -abstract class CAS_Request_AbstractRequest -implements CAS_Request_RequestInterface -{ - - protected $url = null; - protected $cookies = array(); - protected $headers = array(); - protected $isPost = false; - protected $postBody = null; - protected $caCertPath = null; - protected $validateCN = true; - private $_sent = false; - private $_responseHeaders = array(); - private $_responseBody = null; - private $_errorMessage = ''; - - /********************************************************* - * Configure the Request - *********************************************************/ - - /** - * Set the URL of the Request - * - * @param string $url Url to set - * - * @return void - * @throws CAS_OutOfSequenceException If called after the Request has been sent. - */ - public function setUrl ($url) - { - if ($this->_sent) { - throw new CAS_OutOfSequenceException( - 'Request has already been sent cannot '.__METHOD__ - ); - } - - $this->url = $url; - } - - /** - * Add a cookie to the request. - * - * @param string $name Name of entry - * @param string $value value of entry - * - * @return void - * @throws CAS_OutOfSequenceException If called after the Request has been sent. - */ - public function addCookie ($name, $value) - { - if ($this->_sent) { - throw new CAS_OutOfSequenceException( - 'Request has already been sent cannot '.__METHOD__ - ); - } - - $this->cookies[$name] = $value; - } - - /** - * Add an array of cookies to the request. - * The cookie array is of the form - * array('cookie_name' => 'cookie_value', 'cookie_name2' => cookie_value2') - * - * @param array $cookies cookies to add - * - * @return void - * @throws CAS_OutOfSequenceException If called after the Request has been sent. - */ - public function addCookies (array $cookies) - { - if ($this->_sent) { - throw new CAS_OutOfSequenceException( - 'Request has already been sent cannot '.__METHOD__ - ); - } - - $this->cookies = array_merge($this->cookies, $cookies); - } - - /** - * Add a header string to the request. - * - * @param string $header Header to add - * - * @return void - * @throws CAS_OutOfSequenceException If called after the Request has been sent. - */ - public function addHeader ($header) - { - if ($this->_sent) { - throw new CAS_OutOfSequenceException( - 'Request has already been sent cannot '.__METHOD__ - ); - } - - $this->headers[] = $header; - } - - /** - * Add an array of header strings to the request. - * - * @param array $headers headers to add - * - * @return void - * @throws CAS_OutOfSequenceException If called after the Request has been sent. - */ - public function addHeaders (array $headers) - { - if ($this->_sent) { - throw new CAS_OutOfSequenceException( - 'Request has already been sent cannot '.__METHOD__ - ); - } - - $this->headers = array_merge($this->headers, $headers); - } - - /** - * Make the request a POST request rather than the default GET request. - * - * @return void - * @throws CAS_OutOfSequenceException If called after the Request has been sent. - */ - public function makePost () - { - if ($this->_sent) { - throw new CAS_OutOfSequenceException( - 'Request has already been sent cannot '.__METHOD__ - ); - } - - $this->isPost = true; - } - - /** - * Add a POST body to the request - * - * @param string $body body to add - * - * @return void - * @throws CAS_OutOfSequenceException If called after the Request has been sent. - */ - public function setPostBody ($body) - { - if ($this->_sent) { - throw new CAS_OutOfSequenceException( - 'Request has already been sent cannot '.__METHOD__ - ); - } - if (!$this->isPost) { - throw new CAS_OutOfSequenceException( - 'Cannot add a POST body to a GET request, use makePost() first.' - ); - } - - $this->postBody = $body; - } - - /** - * Specify the path to an SSL CA certificate to validate the server with. - * - * @param string $caCertPath path to cert - * @param bool $validate_cn valdiate CN of certificate - * - * @return void - * @throws CAS_OutOfSequenceException If called after the Request has been sent. - */ - public function setSslCaCert ($caCertPath,$validate_cn=true) - { - if ($this->_sent) { - throw new CAS_OutOfSequenceException( - 'Request has already been sent cannot '.__METHOD__ - ); - } - $this->caCertPath = $caCertPath; - $this->validateCN = $validate_cn; - } - - /********************************************************* - * 2. Send the Request - *********************************************************/ - - /** - * Perform the request. - * - * @return bool TRUE on success, FALSE on failure. - * @throws CAS_OutOfSequenceException If called multiple times. - */ - public function send () - { - if ($this->_sent) { - throw new CAS_OutOfSequenceException( - 'Request has already been sent cannot send again.' - ); - } - if (is_null($this->url) || !$this->url) { - throw new CAS_OutOfSequenceException( - 'A url must be specified via setUrl() before the request can be sent.' - ); - } - $this->_sent = true; - return $this->sendRequest(); - } - - /** - * Send the request and store the results. - * - * @return bool TRUE on success, FALSE on failure. - */ - abstract protected function sendRequest (); - - /** - * Store the response headers. - * - * @param array $headers headers to store - * - * @return void - */ - protected function storeResponseHeaders (array $headers) - { - $this->_responseHeaders = array_merge($this->_responseHeaders, $headers); - } - - /** - * Store a single response header to our array. - * - * @param string $header header to store - * - * @return void - */ - protected function storeResponseHeader ($header) - { - $this->_responseHeaders[] = $header; - } - - /** - * Store the response body. - * - * @param string $body body to store - * - * @return void - */ - protected function storeResponseBody ($body) - { - $this->_responseBody = $body; - } - - /** - * Add a string to our error message. - * - * @param string $message message to add - * - * @return void - */ - protected function storeErrorMessage ($message) - { - $this->_errorMessage .= $message; - } - - /********************************************************* - * 3. Access the response - *********************************************************/ - - /** - * Answer the headers of the response. - * - * @return array An array of header strings. - * @throws CAS_OutOfSequenceException If called before the Request has been sent. - */ - public function getResponseHeaders () - { - if (!$this->_sent) { - throw new CAS_OutOfSequenceException( - 'Request has not been sent yet. Cannot '.__METHOD__ - ); - } - return $this->_responseHeaders; - } - - /** - * Answer HTTP status code of the response - * - * @return int - * @throws CAS_OutOfSequenceException If called before the Request has been sent. - * @throws CAS_Request_Exception if the response did not contain a status code - */ - public function getResponseStatusCode () - { - if (!$this->_sent) { - throw new CAS_OutOfSequenceException( - 'Request has not been sent yet. Cannot '.__METHOD__ - ); - } - - if (!preg_match( - '/HTTP\/[0-9.]+\s+([0-9]+)\s*(.*)/', - $this->_responseHeaders[0], $matches - ) - ) { - throw new CAS_Request_Exception( - 'Bad response, no status code was found in the first line.' - ); - } - - return intval($matches[1]); - } - - /** - * Answer the body of response. - * - * @return string - * @throws CAS_OutOfSequenceException If called before the Request has been sent. - */ - public function getResponseBody () - { - if (!$this->_sent) { - throw new CAS_OutOfSequenceException( - 'Request has not been sent yet. Cannot '.__METHOD__ - ); - } - - return $this->_responseBody; - } - - /** - * Answer a message describing any errors if the request failed. - * - * @return string - * @throws CAS_OutOfSequenceException If called before the Request has been sent. - */ - public function getErrorMessage () - { - if (!$this->_sent) { - throw new CAS_OutOfSequenceException( - 'Request has not been sent yet. Cannot '.__METHOD__ - ); - } - return $this->_errorMessage; - } -} diff --git a/lib/apereo/phpcas/source/CAS/Request/CurlMultiRequest.php b/lib/apereo/phpcas/source/CAS/Request/CurlMultiRequest.php deleted file mode 100644 index 850f6f0e4..000000000 --- a/lib/apereo/phpcas/source/CAS/Request/CurlMultiRequest.php +++ /dev/null @@ -1,147 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * This interface defines a class library for performing multiple web requests - * in batches. Implementations of this interface may perform requests serially - * or in parallel. - * - * @class CAS_Request_CurlMultiRequest - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -class CAS_Request_CurlMultiRequest -implements CAS_Request_MultiRequestInterface -{ - private $_requests = array(); - private $_sent = false; - - /********************************************************* - * Add Requests - *********************************************************/ - - /** - * Add a new Request to this batch. - * Note, implementations will likely restrict requests to their own concrete - * class hierarchy. - * - * @param CAS_Request_RequestInterface $request reqest to add - * - * @return void - * @throws CAS_OutOfSequenceException If called after the Request has been sent. - * @throws CAS_InvalidArgumentException If passed a Request of the wrong - * implmentation. - */ - public function addRequest (CAS_Request_RequestInterface $request) - { - if ($this->_sent) { - throw new CAS_OutOfSequenceException( - 'Request has already been sent cannot '.__METHOD__ - ); - } - if (!$request instanceof CAS_Request_CurlRequest) { - throw new CAS_InvalidArgumentException( - 'As a CAS_Request_CurlMultiRequest, I can only work with CAS_Request_CurlRequest objects.' - ); - } - - $this->_requests[] = $request; - } - - /** - * Retrieve the number of requests added to this batch. - * - * @return int number of request elements - * @throws CAS_OutOfSequenceException if the request has already been sent - */ - public function getNumRequests() - { - if ($this->_sent) { - throw new CAS_OutOfSequenceException( - 'Request has already been sent cannot '.__METHOD__ - ); - } - return count($this->_requests); - } - - /********************************************************* - * 2. Send the Request - *********************************************************/ - - /** - * Perform the request. After sending, all requests will have their - * responses poulated. - * - * @return bool TRUE on success, FALSE on failure. - * @throws CAS_OutOfSequenceException If called multiple times. - */ - public function send () - { - if ($this->_sent) { - throw new CAS_OutOfSequenceException( - 'Request has already been sent cannot send again.' - ); - } - if (!count($this->_requests)) { - throw new CAS_OutOfSequenceException( - 'At least one request must be added via addRequest() before the multi-request can be sent.' - ); - } - - $this->_sent = true; - - // Initialize our handles and configure all requests. - $handles = array(); - $multiHandle = curl_multi_init(); - foreach ($this->_requests as $i => $request) { - $handle = $request->initAndConfigure(); - curl_setopt($handle, CURLOPT_RETURNTRANSFER, true); - $handles[$i] = $handle; - curl_multi_add_handle($multiHandle, $handle); - } - - // Execute the requests in parallel. - do { - curl_multi_exec($multiHandle, $running); - } while ($running > 0); - - // Populate all of the responses or errors back into the request objects. - foreach ($this->_requests as $i => $request) { - $buf = curl_multi_getcontent($handles[$i]); - $request->_storeResponseBody($buf); - curl_multi_remove_handle($multiHandle, $handles[$i]); - curl_close($handles[$i]); - } - - curl_multi_close($multiHandle); - } -} diff --git a/lib/apereo/phpcas/source/CAS/Request/CurlRequest.php b/lib/apereo/phpcas/source/CAS/Request/CurlRequest.php deleted file mode 100644 index e30dd0d19..000000000 --- a/lib/apereo/phpcas/source/CAS/Request/CurlRequest.php +++ /dev/null @@ -1,198 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * Provides support for performing web-requests via curl - * - * @class CAS_Request_CurlRequest - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -class CAS_Request_CurlRequest -extends CAS_Request_AbstractRequest -implements CAS_Request_RequestInterface -{ - - /** - * Set additional curl options - * - * @param array $options option to set - * - * @return void - */ - public function setCurlOptions (array $options) - { - $this->_curlOptions = $options; - } - private $_curlOptions = array(); - - /** - * Send the request and store the results. - * - * @return bool true on success, false on failure. - */ - protected function sendRequest () - { - phpCAS::traceBegin(); - - /********************************************************* - * initialize the CURL session - *********************************************************/ - $ch = $this->initAndConfigure(); - - /********************************************************* - * Perform the query - *********************************************************/ - $buf = curl_exec($ch); - if ( $buf === false ) { - phpCAS::trace('curl_exec() failed'); - $this->storeErrorMessage( - 'CURL error #'.curl_errno($ch).': '.curl_error($ch) - ); - $res = false; - } else { - $this->storeResponseBody($buf); - phpCAS::trace("Response Body: \n".$buf."\n"); - $res = true; - - } - // close the CURL session - curl_close($ch); - - phpCAS::traceEnd($res); - return $res; - } - - /** - * Internal method to initialize our cURL handle and configure the request. - * This method should NOT be used outside of the CurlRequest or the - * CurlMultiRequest. - * - * @return resource|false The cURL handle on success, false on failure - */ - public function initAndConfigure() - { - /********************************************************* - * initialize the CURL session - *********************************************************/ - $ch = curl_init($this->url); - - curl_setopt_array($ch, $this->_curlOptions); - - /********************************************************* - * Set SSL configuration - *********************************************************/ - if ($this->caCertPath) { - if ($this->validateCN) { - curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); - } else { - curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); - } - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1); - curl_setopt($ch, CURLOPT_CAINFO, $this->caCertPath); - phpCAS::trace('CURL: Set CURLOPT_CAINFO ' . $this->caCertPath); - } else { - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); - curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); - } - - /********************************************************* - * Configure curl to capture our output. - *********************************************************/ - // return the CURL output into a variable - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - - // get the HTTP header with a callback - curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this, '_curlReadHeaders')); - - /********************************************************* - * Add cookie headers to our request. - *********************************************************/ - if (count($this->cookies)) { - $cookieStrings = array(); - foreach ($this->cookies as $name => $val) { - $cookieStrings[] = $name.'='.$val; - } - curl_setopt($ch, CURLOPT_COOKIE, implode(';', $cookieStrings)); - } - - /********************************************************* - * Add any additional headers - *********************************************************/ - if (count($this->headers)) { - curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers); - } - - /********************************************************* - * Flag and Body for POST requests - *********************************************************/ - if ($this->isPost) { - curl_setopt($ch, CURLOPT_POST, 1); - curl_setopt($ch, CURLOPT_POSTFIELDS, $this->postBody); - } - - /********************************************************* - * Set User Agent - *********************************************************/ - curl_setopt($ch, CURLOPT_USERAGENT, 'phpCAS/' . phpCAS::getVersion()); - - return $ch; - } - - /** - * Store the response body. - * This method should NOT be used outside of the CurlRequest or the - * CurlMultiRequest. - * - * @param string $body body to stor - * - * @return void - */ - public function _storeResponseBody ($body) - { - $this->storeResponseBody($body); - } - - /** - * Internal method for capturing the headers from a curl request. - * - * @param resource $ch handle of curl - * @param string $header header - * - * @return int - */ - public function _curlReadHeaders ($ch, $header) - { - $this->storeResponseHeader($header); - return strlen($header); - } -} diff --git a/lib/apereo/phpcas/source/CAS/Request/Exception.php b/lib/apereo/phpcas/source/CAS/Request/Exception.php deleted file mode 100644 index dd5a2a55a..000000000 --- a/lib/apereo/phpcas/source/CAS/Request/Exception.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * An Exception for problems performing requests - * - * @class CAS_Request_Exception - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -class CAS_Request_Exception -extends Exception -implements CAS_Exception -{ - -} diff --git a/lib/apereo/phpcas/source/CAS/Request/MultiRequestInterface.php b/lib/apereo/phpcas/source/CAS/Request/MultiRequestInterface.php deleted file mode 100644 index 41002c777..000000000 --- a/lib/apereo/phpcas/source/CAS/Request/MultiRequestInterface.php +++ /dev/null @@ -1,83 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * This interface defines a class library for performing multiple web requests - * in batches. Implementations of this interface may perform requests serially - * or in parallel. - * - * @class CAS_Request_MultiRequestInterface - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -interface CAS_Request_MultiRequestInterface -{ - - /********************************************************* - * Add Requests - *********************************************************/ - - /** - * Add a new Request to this batch. - * Note, implementations will likely restrict requests to their own concrete - * class hierarchy. - * - * @param CAS_Request_RequestInterface $request request interface - * - * @return void - * @throws CAS_OutOfSequenceException If called after the Request has been - * sent. - * @throws CAS_InvalidArgumentException If passed a Request of the wrong - * implmentation. - */ - public function addRequest (CAS_Request_RequestInterface $request); - - /** - * Retrieve the number of requests added to this batch. - * - * @return int number of request elements - */ - public function getNumRequests (); - - /********************************************************* - * 2. Send the Request - *********************************************************/ - - /** - * Perform the request. After sending, all requests will have their - * responses poulated. - * - * @return bool TRUE on success, FALSE on failure. - * @throws CAS_OutOfSequenceException If called multiple times. - */ - public function send (); -} diff --git a/lib/apereo/phpcas/source/CAS/Request/RequestInterface.php b/lib/apereo/phpcas/source/CAS/Request/RequestInterface.php deleted file mode 100644 index b8e8772e9..000000000 --- a/lib/apereo/phpcas/source/CAS/Request/RequestInterface.php +++ /dev/null @@ -1,179 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * This interface defines a class library for performing web requests. - * - * @class CAS_Request_RequestInterface - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -interface CAS_Request_RequestInterface -{ - - /********************************************************* - * Configure the Request - *********************************************************/ - - /** - * Set the URL of the Request - * - * @param string $url url to set - * - * @return void - * @throws CAS_OutOfSequenceException If called after the Request has been sent. - */ - public function setUrl ($url); - - /** - * Add a cookie to the request. - * - * @param string $name name of cookie - * @param string $value value of cookie - * - * @return void - * @throws CAS_OutOfSequenceException If called after the Request has been sent. - */ - public function addCookie ($name, $value); - - /** - * Add an array of cookies to the request. - * The cookie array is of the form - * array('cookie_name' => 'cookie_value', 'cookie_name2' => cookie_value2') - * - * @param array $cookies cookies to add - * - * @return void - * @throws CAS_OutOfSequenceException If called after the Request has been sent. - */ - public function addCookies (array $cookies); - - /** - * Add a header string to the request. - * - * @param string $header header to add - * - * @return void - * @throws CAS_OutOfSequenceException If called after the Request has been sent. - */ - public function addHeader ($header); - - /** - * Add an array of header strings to the request. - * - * @param array $headers headers to add - * - * @return void - * @throws CAS_OutOfSequenceException If called after the Request has been sent. - */ - public function addHeaders (array $headers); - - /** - * Make the request a POST request rather than the default GET request. - * - * @return void - * @throws CAS_OutOfSequenceException If called after the Request has been sent. - */ - public function makePost (); - - /** - * Add a POST body to the request - * - * @param string $body body to add - * - * @return void - * @throws CAS_OutOfSequenceException If called after the Request has been sent. - */ - public function setPostBody ($body); - - - /** - * Specify the path to an SSL CA certificate to validate the server with. - * - * @param string $caCertPath path to cert file - * @param boolean $validate_cn validate CN of SSL certificate - * - * @return void - * @throws CAS_OutOfSequenceException If called after the Request has been sent. - */ - public function setSslCaCert ($caCertPath, $validate_cn = true); - - - - /********************************************************* - * 2. Send the Request - *********************************************************/ - - /** - * Perform the request. - * - * @return bool TRUE on success, FALSE on failure. - * @throws CAS_OutOfSequenceException If called multiple times. - */ - public function send (); - - /********************************************************* - * 3. Access the response - *********************************************************/ - - /** - * Answer the headers of the response. - * - * @return array An array of header strings. - * @throws CAS_OutOfSequenceException If called before the Request has been sent. - */ - public function getResponseHeaders (); - - /** - * Answer HTTP status code of the response - * - * @return int - * @throws CAS_OutOfSequenceException If called before the Request has been sent. - */ - public function getResponseStatusCode (); - - /** - * Answer the body of response. - * - * @return string - * @throws CAS_OutOfSequenceException If called before the Request has been sent. - */ - public function getResponseBody (); - - /** - * Answer a message describing any errors if the request failed. - * - * @return string - * @throws CAS_OutOfSequenceException If called before the Request has been sent. - */ - public function getErrorMessage (); -} diff --git a/lib/apereo/phpcas/source/CAS/Session/PhpSession.php b/lib/apereo/phpcas/source/CAS/Session/PhpSession.php deleted file mode 100644 index 031cbbc70..000000000 --- a/lib/apereo/phpcas/source/CAS/Session/PhpSession.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * Empty class used as a default implementation for phpCAS. - * - * Implements the standard PHP session handler without no alterations. - * - * @class CAS_Session_PhpSession - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -class CAS_Session_PhpSession extends SessionHandler implements SessionHandlerInterface -{ -} diff --git a/lib/apereo/phpcas/source/CAS/TypeMismatchException.php b/lib/apereo/phpcas/source/CAS/TypeMismatchException.php deleted file mode 100644 index 72bdc87a1..000000000 --- a/lib/apereo/phpcas/source/CAS/TypeMismatchException.php +++ /dev/null @@ -1,70 +0,0 @@ - - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ - -/** - * Exception that denotes invalid arguments were passed. - * - * @class CAS_InvalidArgumentException - * @category Authentication - * @package PhpCAS - * @author Adam Franco - * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 - * @link https://wiki.jasig.org/display/CASC/phpCAS - */ -class CAS_TypeMismatchException -extends CAS_InvalidArgumentException -{ - /** - * Constructor, provides a nice message. - * - * @param mixed $argument Argument - * @param string $argumentName Argument Name - * @param string $type Type - * @param string $message Error Message - * @param integer $code Code - * - * @return void - */ - public function __construct ( - $argument, $argumentName, $type, $message = '', $code = 0 - ) { - if (is_object($argument)) { - $foundType = get_class($argument).' object'; - } else { - $foundType = gettype($argument); - } - - parent::__construct( - 'type mismatched for parameter ' - . $argumentName . ' (should be \'' . $type .' \'), ' - . $foundType . ' given. ' . $message, $code - ); - } -} -?> diff --git a/lib/autoload.php b/lib/autoload.php deleted file mode 100644 index 460e67535..000000000 --- a/lib/autoload.php +++ /dev/null @@ -1,7 +0,0 @@ -handle = fopen($opened_path, $mode); - $this->position = 0; - - // remove all traces of this stream wrapper once it has been used - stream_wrapper_unregister('composer-bin-proxy'); - - return (bool) $this->handle; - } - - public function stream_read($count) - { - $data = fread($this->handle, $count); - - if ($this->position === 0) { - $data = preg_replace('{^#!.*\r?\n}', '', $data); - } - - $this->position += strlen($data); - - return $data; - } - - public function stream_cast($castAs) - { - return $this->handle; - } - - public function stream_close() - { - fclose($this->handle); - } - - public function stream_lock($operation) - { - return $operation ? flock($this->handle, $operation) : true; - } - - public function stream_tell() - { - return $this->position; - } - - public function stream_eof() - { - return feof($this->handle); - } - - public function stream_stat() - { - return fstat($this->handle); - } - - public function stream_set_option($option, $arg1, $arg2) - { - return true; - } - } - } - - if (function_exists('stream_wrapper_register') && stream_wrapper_register('composer-bin-proxy', 'Composer\BinProxyWrapper')) { - include("composer-bin-proxy://" . $binPath); - exit(0); - } -} - -include $binPath; diff --git a/lib/bin/generate-deps-for-config-factory.bat b/lib/bin/generate-deps-for-config-factory.bat deleted file mode 100644 index 3eae0eb2c..000000000 --- a/lib/bin/generate-deps-for-config-factory.bat +++ /dev/null @@ -1,4 +0,0 @@ -@ECHO OFF -setlocal DISABLEDELAYEDEXPANSION -SET BIN_TARGET=%~dp0/../laminas/laminas-servicemanager/bin/generate-deps-for-config-factory -php "%BIN_TARGET%" %* diff --git a/lib/bin/generate-factory-for-class b/lib/bin/generate-factory-for-class deleted file mode 100644 index 9aec04dbc..000000000 --- a/lib/bin/generate-factory-for-class +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env php -handle = fopen($opened_path, $mode); - $this->position = 0; - - // remove all traces of this stream wrapper once it has been used - stream_wrapper_unregister('composer-bin-proxy'); - - return (bool) $this->handle; - } - - public function stream_read($count) - { - $data = fread($this->handle, $count); - - if ($this->position === 0) { - $data = preg_replace('{^#!.*\r?\n}', '', $data); - } - - $this->position += strlen($data); - - return $data; - } - - public function stream_cast($castAs) - { - return $this->handle; - } - - public function stream_close() - { - fclose($this->handle); - } - - public function stream_lock($operation) - { - return $operation ? flock($this->handle, $operation) : true; - } - - public function stream_tell() - { - return $this->position; - } - - public function stream_eof() - { - return feof($this->handle); - } - - public function stream_stat() - { - return fstat($this->handle); - } - - public function stream_set_option($option, $arg1, $arg2) - { - return true; - } - } - } - - if (function_exists('stream_wrapper_register') && stream_wrapper_register('composer-bin-proxy', 'Composer\BinProxyWrapper')) { - include("composer-bin-proxy://" . $binPath); - exit(0); - } -} - -include $binPath; diff --git a/lib/bin/generate-factory-for-class.bat b/lib/bin/generate-factory-for-class.bat deleted file mode 100644 index 97f2fa32a..000000000 --- a/lib/bin/generate-factory-for-class.bat +++ /dev/null @@ -1,4 +0,0 @@ -@ECHO OFF -setlocal DISABLEDELAYEDEXPANSION -SET BIN_TARGET=%~dp0/../laminas/laminas-servicemanager/bin/generate-factory-for-class -php "%BIN_TARGET%" %* diff --git a/lib/bin/patch-type-declarations b/lib/bin/patch-type-declarations deleted file mode 100644 index 1b0b28230..000000000 --- a/lib/bin/patch-type-declarations +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env php -handle = fopen($opened_path, $mode); - $this->position = 0; - - // remove all traces of this stream wrapper once it has been used - stream_wrapper_unregister('composer-bin-proxy'); - - return (bool) $this->handle; - } - - public function stream_read($count) - { - $data = fread($this->handle, $count); - - if ($this->position === 0) { - $data = preg_replace('{^#!.*\r?\n}', '', $data); - } - - $this->position += strlen($data); - - return $data; - } - - public function stream_cast($castAs) - { - return $this->handle; - } - - public function stream_close() - { - fclose($this->handle); - } - - public function stream_lock($operation) - { - return $operation ? flock($this->handle, $operation) : true; - } - - public function stream_tell() - { - return $this->position; - } - - public function stream_eof() - { - return feof($this->handle); - } - - public function stream_stat() - { - return fstat($this->handle); - } - - public function stream_set_option($option, $arg1, $arg2) - { - return true; - } - } - } - - if (function_exists('stream_wrapper_register') && stream_wrapper_register('composer-bin-proxy', 'Composer\BinProxyWrapper')) { - include("composer-bin-proxy://" . $binPath); - exit(0); - } -} - -include $binPath; diff --git a/lib/bin/patch-type-declarations.bat b/lib/bin/patch-type-declarations.bat deleted file mode 100644 index b92a2da31..000000000 --- a/lib/bin/patch-type-declarations.bat +++ /dev/null @@ -1,4 +0,0 @@ -@ECHO OFF -setlocal DISABLEDELAYEDEXPANSION -SET BIN_TARGET=%~dp0/../symfony/error-handler/Resources/bin/patch-type-declarations -php "%BIN_TARGET%" %* diff --git a/lib/bin/php-parse b/lib/bin/php-parse deleted file mode 100644 index 1bd2c838c..000000000 --- a/lib/bin/php-parse +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/env php -realpath = realpath($opened_path) ?: $opened_path; - $opened_path = $this->realpath; - $this->handle = fopen($this->realpath, $mode); - $this->position = 0; - - return (bool) $this->handle; - } - - public function stream_read($count) - { - $data = fread($this->handle, $count); - - if ($this->position === 0) { - $data = preg_replace('{^#!.*\r?\n}', '', $data); - } - - $this->position += strlen($data); - - return $data; - } - - public function stream_cast($castAs) - { - return $this->handle; - } - - public function stream_close() - { - fclose($this->handle); - } - - public function stream_lock($operation) - { - return $operation ? flock($this->handle, $operation) : true; - } - - public function stream_seek($offset, $whence) - { - if (0 === fseek($this->handle, $offset, $whence)) { - $this->position = ftell($this->handle); - return true; - } - - return false; - } - - public function stream_tell() - { - return $this->position; - } - - public function stream_eof() - { - return feof($this->handle); - } - - public function stream_stat() - { - return array(); - } - - public function stream_set_option($option, $arg1, $arg2) - { - return true; - } - - public function url_stat($path, $flags) - { - $path = substr($path, 17); - if (file_exists($path)) { - return stat($path); - } - - return false; - } - } - } - - if ( - (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true)) - || (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) - ) { - include("phpvfscomposer://" . __DIR__ . '/..'.'/nikic/php-parser/bin/php-parse'); - exit(0); - } -} - -include __DIR__ . '/..'.'/nikic/php-parser/bin/php-parse'; diff --git a/lib/bin/php-parse.bat b/lib/bin/php-parse.bat deleted file mode 100644 index 2c5096dc3..000000000 --- a/lib/bin/php-parse.bat +++ /dev/null @@ -1,5 +0,0 @@ -@ECHO OFF -setlocal DISABLEDELAYEDEXPANSION -SET BIN_TARGET=%~dp0/php-parse -SET COMPOSER_RUNTIME_BIN_DIR=%~dp0 -php "%BIN_TARGET%" %* diff --git a/lib/bin/pscss b/lib/bin/pscss deleted file mode 100644 index fa9a900db..000000000 --- a/lib/bin/pscss +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env php -handle = fopen($opened_path, $mode); - $this->position = 0; - - // remove all traces of this stream wrapper once it has been used - stream_wrapper_unregister('composer-bin-proxy'); - - return (bool) $this->handle; - } - - public function stream_read($count) - { - $data = fread($this->handle, $count); - - if ($this->position === 0) { - $data = preg_replace('{^#!.*\r?\n}', '', $data); - } - - $this->position += strlen($data); - - return $data; - } - - public function stream_cast($castAs) - { - return $this->handle; - } - - public function stream_close() - { - fclose($this->handle); - } - - public function stream_lock($operation) - { - return $operation ? flock($this->handle, $operation) : true; - } - - public function stream_tell() - { - return $this->position; - } - - public function stream_eof() - { - return feof($this->handle); - } - - public function stream_stat() - { - return fstat($this->handle); - } - - public function stream_set_option($option, $arg1, $arg2) - { - return true; - } - } - } - - if (function_exists('stream_wrapper_register') && stream_wrapper_register('composer-bin-proxy', 'Composer\BinProxyWrapper')) { - include("composer-bin-proxy://" . $binPath); - exit(0); - } -} - -include $binPath; diff --git a/lib/bin/pscss.bat b/lib/bin/pscss.bat deleted file mode 100644 index 1e368dc92..000000000 --- a/lib/bin/pscss.bat +++ /dev/null @@ -1,4 +0,0 @@ -@ECHO OFF -setlocal DISABLEDELAYEDEXPANSION -SET BIN_TARGET=%~dp0/../scssphp/scssphp/bin/pscss -php "%BIN_TARGET%" %* diff --git a/lib/bin/var-dump-server b/lib/bin/var-dump-server deleted file mode 100644 index 10567b2c7..000000000 --- a/lib/bin/var-dump-server +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env php -handle = fopen($opened_path, $mode); - $this->position = 0; - - // remove all traces of this stream wrapper once it has been used - stream_wrapper_unregister('composer-bin-proxy'); - - return (bool) $this->handle; - } - - public function stream_read($count) - { - $data = fread($this->handle, $count); - - if ($this->position === 0) { - $data = preg_replace('{^#!.*\r?\n}', '', $data); - } - - $this->position += strlen($data); - - return $data; - } - - public function stream_cast($castAs) - { - return $this->handle; - } - - public function stream_close() - { - fclose($this->handle); - } - - public function stream_lock($operation) - { - return $operation ? flock($this->handle, $operation) : true; - } - - public function stream_tell() - { - return $this->position; - } - - public function stream_eof() - { - return feof($this->handle); - } - - public function stream_stat() - { - return fstat($this->handle); - } - - public function stream_set_option($option, $arg1, $arg2) - { - return true; - } - } - } - - if (function_exists('stream_wrapper_register') && stream_wrapper_register('composer-bin-proxy', 'Composer\BinProxyWrapper')) { - include("composer-bin-proxy://" . $binPath); - exit(0); - } -} - -include $binPath; diff --git a/lib/bin/var-dump-server.bat b/lib/bin/var-dump-server.bat deleted file mode 100644 index 46836b50c..000000000 --- a/lib/bin/var-dump-server.bat +++ /dev/null @@ -1,4 +0,0 @@ -@ECHO OFF -setlocal DISABLEDELAYEDEXPANSION -SET BIN_TARGET=%~dp0/../symfony/var-dumper/Resources/bin/var-dump-server -php "%BIN_TARGET%" %* diff --git a/lib/bin/yaml-lint b/lib/bin/yaml-lint deleted file mode 100644 index 182c83f09..000000000 --- a/lib/bin/yaml-lint +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env php -handle = fopen($opened_path, $mode); - $this->position = 0; - - // remove all traces of this stream wrapper once it has been used - stream_wrapper_unregister('composer-bin-proxy'); - - return (bool) $this->handle; - } - - public function stream_read($count) - { - $data = fread($this->handle, $count); - - if ($this->position === 0) { - $data = preg_replace('{^#!.*\r?\n}', '', $data); - } - - $this->position += strlen($data); - - return $data; - } - - public function stream_cast($castAs) - { - return $this->handle; - } - - public function stream_close() - { - fclose($this->handle); - } - - public function stream_lock($operation) - { - return $operation ? flock($this->handle, $operation) : true; - } - - public function stream_tell() - { - return $this->position; - } - - public function stream_eof() - { - return feof($this->handle); - } - - public function stream_stat() - { - return fstat($this->handle); - } - - public function stream_set_option($option, $arg1, $arg2) - { - return true; - } - } - } - - if (function_exists('stream_wrapper_register') && stream_wrapper_register('composer-bin-proxy', 'Composer\BinProxyWrapper')) { - include("composer-bin-proxy://" . $binPath); - exit(0); - } -} - -include $binPath; diff --git a/lib/bin/yaml-lint.bat b/lib/bin/yaml-lint.bat deleted file mode 100644 index 0474134c6..000000000 --- a/lib/bin/yaml-lint.bat +++ /dev/null @@ -1,4 +0,0 @@ -@ECHO OFF -setlocal DISABLEDELAYEDEXPANSION -SET BIN_TARGET=%~dp0/../symfony/yaml/Resources/bin/yaml-lint -php "%BIN_TARGET%" %* diff --git a/lib/combodo/tcpdf/CHANGELOG.TXT b/lib/combodo/tcpdf/CHANGELOG.TXT deleted file mode 100644 index e90bd161a..000000000 --- a/lib/combodo/tcpdf/CHANGELOG.TXT +++ /dev/null @@ -1,3074 +0,0 @@ -6.4.4 (2021-12-31) - - PHP 8.1 fixes - -6.4.3 (2021-12-28) - - Fix MultiCell PHPDoc typehint (#407) - - Fix type hint for \TCPDF_STATIC::_freadint (#414) - - Footer and Header font phpdoc fixes + constructor $pdfa phpdoc fix + setHeaderData lw param fix (#402) - - Fix text-annotation state options (#412) - - Fix - Named links have been broken. This fixes. (#415) - - Fixed type in comment for $lw header image logo width in mm - - Change Set to set. Fixes #419 (#421) - - Fix failing tests and failing tests not marking exit code as 1 (#426) - - Fix phpdoc and prefer null as default value (#444) - - Run on PHP 8.1 normally and add nightly PHP as allowed to fail (#452) - - Fix AES128 encryption if the OpenSSL extension is installed (#453) - - Explicitly cast values to int for imagesetpixel (#460) - - Fix cell_height_ratio type (#405) - - Leave &NBSP; lowercase when using text-transform (#403) - -6.4.2 (2021-07-20) - - Fix PHP 8.1 type error with TCPDF_STATIC::pregSplit on preg_split - - Fix a PHP array offset error - - Fixed phpdoc blocks - - Drop a PHP 4 polyfill and add a .gitattributes file - - Added a test-suite - - Removed pointless assignments - - Fix docblock spelling error - - Update version info - - Fix color being filled to type 0 with PHP 8 - - Fix warnings for undefined tags for $lineStyle - - Normalized composer.json - - Allowed transparency in PDF/A-2 and PDF/A-3 - - Add a TCPDF composer example - - Fixed implicit conversion from float to int for PHP 8.1 - - Removed status.txt from font directories, because of filesize - - Fixed type hints - - Removed "U" modifier from regexes - -6.4.1 (2021-03-27) - - Update tcpdf version (no code changes) - -6.4.0 (2021-03-27) - - allow styles on
tags - - check if file exists before calling unlink - - Fix image file type for urls with query params - - Fix SVGPath should accept 1.19.30 (equiv 1.19,.30) compacted values list - - Fix Second parameter of TCPDF::cell() must be a number - - PHP 8.0 function signature fixes - - Fix vulnerability to roman numeral bombs - - Optimized a regular expression - - Cache file get contents calls - - Remove mb_internal encoding handling - -6.3.5 (2020-02-14) - - Fixed curly braces in pdf417 - - Fixed a syntax error issue when accessing an index of a casted variable - -6.3.4 (2020-02-12) - - Check if imagekeys exist - - Unlink only images in cache - -6.3.3 (2020-02-12) - - Fixed PHP 7.4 - cannot use array offset on integers - - Fixed PDF/A-3B validation issue caused by missing pdfaSchema:property. - - Removed backup changelog files from repo - - Prevents the deletion of non-existent files in /tmp - - Prevent crash in case of no list access in cache path - - Check existence of file before delete it - - Fixed erase users pictures - - Fixed problem with $imagekeys undefined or unlinked - - Fix SVGPath elliptical arc with rx/ry=0 + z should return to initial point - - Fixed PHP 7.4 errors - - handle integers for pages - - Fixed background image doesn't work in RTL - - Fixed PDF/A validity - - Fixed datamatrix.php for PHP 7.4 - - Fixed deprecated PHP features - -6.3.2 (2019-09-20) - - Update ICC profile - -6.3.1 (2019-09-20) - - Fix reported version - - Fix Undefined property: GLPIPDF::$imagekeys - -6.3.0 (2019-09-19) - - fix SpotColor handling in HTML - - Add an additional empty test to prevent error in PHP 7.2 - - Fix the documentation how to calculate the cell height - - Drop duplicated array indices - - Fix TCPDF_STATIC::fileGetContents() - - Introduce other version of pdfA (2 and 3) - - Add UF and AFRelationship missing - - Fix performance issue of cloned instances - - Change glob to readdir which performs better - - URI in PDF can result in E_NOTICE - - Fix a warning for PHP 7.4 - - Fixed gradient offsets for percentage-based stops. - - Fixed file_get_contents return value should also be checked for a non-empty string - - Fix Array and string offset access syntax with curly braces is deprecated - - Fix PHP Warning: chr() expects parameter 1 to be int - - Add a VERSION file - -6.2.26 (2018-10-16) - - Update sRGB.icc with the one from the Debian package icc-profiles-free - - Fix unsupported operand types error when codepoints arrays are merged - -6.2.25 (2018-09-23) - - Fix support for image URLs. - -6.2.24 - - Support remote urls when checking if file exists. - -6.2.23 (2018-09-22) - - Simplify file_exists function. - -6.2.22 (2018-09-14) - - Fixes on `include/tcpdf_images.php`, `include/tcpdf_static.php` and `tcpdf.php` about file handling - -6.2.21 (2018-09-14) - - _no code changes_ - -6.2.20 (2018-09-14) - - Fix for security vulnerability: Using the phar:// wrapper it was possible to trigger the unserialization of user provided data. - -6.2.19 (2018-09-14) - - Merge various fixes for PHP 7.3 compatibility and security. - -6.2.13 (2016-06-10) - - IMPORTANT: A new version of this library is under development at https://github.com/tecnickcom/tc-lib-pdf and as a consequence this version will not receive any additional development or support. This version should be considered obsolete, new projects should use the new version as soon it will become stable. - -6.2.12 (2015-09-12) - - fix composer package name to tecnickcom/tcpdf - -6.2.11 (2015-08-02) - - Bug #1070 "PNG regression in 6.2.9 (they appear as their alpha channel)" was fixed. - - Bug #1069 "Encoded SRC URLs in tags don't work anymore" was fixed. - -6.2.10 (2015-07-28) - - Minor mod to PNG parsing. - - Make dependency on mcrypt optional. - -6.2.8 (2015-04-29) - - Removed unwanted file. - -6.2.7 (2015-04-28) - - Merged PR 17: Avoid warning when iterating a non-array variable. - - Merged PR 16: Improve MuliCell param definition. - - Improved column check (PR 15). - - Merged PR 11: Use stream_is_local instead of limit to file://. - - Merged PR 10: ImageMagick link on README.txt. - -6.2.6 (2015-01-28) - - Bug #1008 "UTC offset sing breaks PDF/A-1b compliance" was fixed. - -6.2.5 (2015-01-24) - - Bug #1019 "$this in static context" was fixed. - - Bug #1015 "Infinite loop in getIndirectObject method of parser" was fixed. - -6.2.4 (2015-01-08) - - fix warning related to empty K_PATH_URL. - - fix error when a $table_colwidths key is not set. - -6.2.3 (2014-12-18) - - New comment. - - Moved the K_PATH_IMAGES definition in tcpdf_autoconfig. - -6.2.2 (2014-12-18) - - Fixed mispelled words. - - Fixed version number. - -6.2.1 (2014-12-18) - - The constant K_TCPDF_THROW_EXCEPTION_ERROR is now set to false in the default configuration file. - - An issue with the _destroy() method was fixed. - -6.2.0 (2014-12-10) - - Bug #1005 "Security Report, LFI posting internal files externally abusing default parameter" was fixed. - - Static methods serializeTCPDFtagParameters() and unserializeTCPDFtagParameters() were moved as non static to the main TCPDF class (see changes in example n. 49). - - Deprecated methods were removed, please use the equivalents defined in other classes (i.e. TCPDF_STATIC and TCPDF_FONTS). - - The constant K_TCPDF_CALLS_IN_HTML is now set by default to FALSE. - - DLE, DLX and DLP page format was added. - - Page format are now defined as a public property in TCPDF_STATIC. - -6.1.1 (2014-12-09) - - Fixed bug with the register_shutdown_function(). - -6.1.0 (2014-12-07) - - The method TCPDF_STATIC::getRandomSeed() was improved. - - The disk caching feature was removed. - - Bug #1003 "Backslashes become duplicated in table, using WriteHTML" was fixed. - - Bug #1002 "SVG radialGradient within non-square Rect" was fixed. - -6.0.099 (2014-11-15) - - Added basic support for nested SVG images (adapted PR from SamMousa). - - A bug related to setGDImageTransparency() was fixed (thanks to Maarten Boerema). - -6.0.098 (2014-11-08) - - Bug item #996 "getCharBBox($char) returns incorrect results for TTF glyphs without outlines" was fixed. - - Bug item #991 "Text problem with SVG" was fixed (only the font style part). - -6.0.097 (2014-10-20) - - Bug item #988 "hyphenateText - charmin parameter not work" was fixed. - - New 1D barcode method to print pre-formatted IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200. - -6.0.096 (2014-10-06) - - Bug item #982 "Display style is not inherited in SVG" was fixed. - - Bug item #984 "Double quote url in CSS" was fixed. - -6.0.095 (2014-10-02) - - Bug item #979 "New Timezone option overwriting current timezone" was fixed. - -6.0.094 (2014-09-30) - - Bug item #978 "Variable Undefined: $cborder" was fixed. - -6.0.093 (2014-09-02) - - Security fix: some serialize/unserialize methods were replaced with json_encode/json_decode to avoid a potential object injection with user supplied content. Thanks to ownCloud Inc. for reporting this issue. - - K_TIMEZONE constant was added to the default configuration to suppress date-time warnings. - -6.0.092 (2014-09-01) - - Bug item #956 "Monospaced fonts are not alignd at the baseline" was fixed. - - Bug item #964 "Problem when changing font size" was fixed. - - Bug item #969 "ImageSVG with radialGradient problem" was fixed. - - sRGB.icc file was replaced with the one from the Debian package icc-profiles-free (2.0.1+dfsg-1) - -6.0.091 (2014-08-13) - - Issue #325"Division by zero when css fontsize equals 0" was fixed. - -6.0.090 (2014-08-08) - - Starting from this version TCPDF is also available in GitHub at https://github.com/tecnickcom/TCPDF - - Function getmypid() was removed for better compatibility with shared hosting environments. - - Support for pulling SVG stroke opacity value from RGBa color was mergeg [adf006]. - - Bug item #951 "HTML Table within TCPDF columns doesnt flow correctly on page break ..." was fixed. - -6.0.089 (2014-07-16) - - Bug item #948 "bottom line of rowspan cell not work correctly" was fixed. - -6.0.088 (2014-07-09) - - Bug item #946 "Case sensitive type check causes broken match for SVG" was fixed. - - Bug item #945 "Imagick load doesn't account for passed data string " was fixed. - -6.0.087 (2014-06-25) - - A bug affecting fitcell option in Multicell was fixed. - -6.0.086 (2014-06-20) - - Bug item #938 "Hyphenation-dash extends outside of cell" was fixed (collateral effect). - -6.0.085 (2014-06-19) - - Some example images were replaced. - - A race condition bug was fixed. - - Bug item #938 "Hyphenation-dash extends outside of cell" was fixed. - -6.0.084 (2014-06-13) - - A bug related to MultiCell fitcell feature was fixed. - - Bug item #931 "Documentation error for setPageFormat()" was fixed. - -6.0.083 (2014-05-29) - - Bug item #928 "setHtmlVSpace with HR element" was fixed. - -6.0.082 (2014-05-23) - - Bug item #926 "test statement instead of assignment used in tcpdf_fonts.php" was fixed. - - Bug item #925 "924 transparent images bug" was fixed. - -6.0.081 (2014-05-22) - - Bug item #922 "writehtml tables thead repeating" was fixed. - - Patch #71 "External and internal links, local and remote" wa applied. - -6.0.080 (2014-05-20) - - Bug item #921 "Fatal error in hyphenateText() function" was fixed. - - Bug item #923 "Automatic Hyphenation error" was fixed. - - Patch #70 "Augument TCPDFBarcode classes with ability to return raw png image data" was applied. - -6.0.079 (2014-05-19) - - Patch item #69 "Named destinations, HTML internal and external links" was merged. - - Bug item #920 "hyphenateText() should not hyphenate the content of style-tags in HTML mode" was fixed. - - Image method now trigs an error in case the cache is now writeable. - - Fixed issue with layer default status. - -6.0.078 (2014-05-12) - - A warning issue in addTTFfont() method was fixed. - - Fonts were updated to include cbbox metrics. - -6.0.077 (2014-05-06) - - A Datamatrix barcode bug was fixed. - -6.0.076 (2014-05-06) - - A bug in Datamatrix Base256 encoding was fixed. - - Merged fix for SVG use/clip-gradient. - - Now it is possible to prefix a page number in Link methods with the * character to avoid been changed when adding/deleting/moving pages (see example_045.php). - -6.0.075 (2014-05-05) - - Bug #917 "Using realtive Units like ex or em for images distort output in HTML mode" was fixed. - -6.0.074 (2014-05-03) - - Part of Bug #917 "Using realtive Units like ex or em for images distort output in HTML mode" was fixed. - - Bug #915 "Problem with SVG Image using Radial Gradients" was fixed. - -6.0.073 (2014-04-29) - - Bug #913 "Possible bug with line-height" was fixed. - - Bug #914 "MultiCell and FitCell" was fixed. - - Bug #915 "Problem with SVG Image using Radial Gradients" was fixed. - -6.0.072 (2014-04-27) - - Deprecated curly braces substring syntax was replaced with square braces. - -6.0.071 (2014-04-25) - - Bug #911 "error with buffered png pics" was fixed. - -6.0.070 (2014-04-24) - - Bug #910 "An SVG image is being cut off (with clipping mask) when you use align options" was fixed. - -6.0.069 (2014-04-24) - - Datamatrix Base256 encoding was fixed. - -6.0.068 (2014-04-22) - - Some Datamatrix barcode bugs were fixed. - -6.0.067 (2014-04-21) - - startLayer() method signature was changed to include a new "lock" parameter. - -6.0.066 (2014-04-20) - - Bug #908 "Linebreak is not considered when getting length of the next string" was fixed. - -6.0.065 (2014-04-10) - - Bug #905 "RGB percentage color bug in convertHTMLColorToDec()" was fixed. - -6.0.064 (2014-04-07) - - Header and Footer fonts are now set by default. - - Bug #904 "PDF corrupted" was fixed. - -6.0.063 (2014-04-03) - - Method TCPDF_IMAGES::_parsepng() was fixed to support transparency in Indexed images. - -6.0.062 (2014-03-02) - - The method startLayer() now accepts the NULL value for the $print parameter to not set the print layer option. - -6.0.061 (2014-02-18) - - Bug #893 "Parsing error on streamed xref for secured pdf" was fixed. - -6.0.060 (2014-02-16) - - Bug #891 "Error on parsing hexa fields" was fixed. - - Bug #892 "Parsing pdf with trailing space at start" was fixed. - -6.0.059 (2014-02-03) - - SVG 'use' support was imporved. - -6.0.058 (2014-01-31) - - Bug #886 "Bugs with SVG using and " was fixed. - -6.0.057 (2014-01-26) - - Bug #883 "Parsing error" was fixed. - -6.0.056 (2014-01-25) - - The automatic cache folder selection now works also with some restricted hosting environments. - - CSS text-transform property is now supported (requires the multibyte string library for php) - see examle n. 061 (Thanks to Walter Ferraz). - - Bug #884 "Parsing error prev tag looking for" was fixed. - -6.0.055 (2014-01-15) - - Bug #880 "Error detecting hX tags (h1,h2..)" was fixed - - Bug #879 "Thead on the second page inherits style of previous tr" was fixed - -6.0.054 (2014-01-13) - - Bug #877 "Parenteses causing corrupt text" was fixed. - -6.0.053 (2014-01-03) - - Bug #876 "Cell padding should not be multiplied with number of lines in getStringHeight" was fixed. - - Patch #68 "Empty img src attribute leads to access of uninitialized string offset" was applied. - -6.0.052 (2013-12-12) - - Bug #871 "Datamatrix coding" was fixed. - -6.0.051 (2013-12-02) - - cbbox array values in addTTFfont() were converted to integers. - -6.0.050 (2013-12-01) - - The method getNumLines() was extended to support hyphenation. - - The CSS property line-height now supports non percentage values. - -6.0.050 (2013-11-27) - - A bug related to PNG images was fixed. - -6.0.048 (2013-11-24) - - SVG vars are now reset in ImageSVG() method. - -6.0.047 (2013-11-19) - - SVG support was extended to support some nested defs. - -6.0.046 (2013-11-17) - - preg_replace_callback functions were replaced to improve memory performances. - -6.0.045 (2013-11-17) - - Bug #862 "Parsing error on flate filter" was fixed. - -6.0.044 (2013-11-10) - - Bug #857 "Undefined offset error" was fixed. - - The uniord method now uses a static cache to improve performances (thanks to Mathieu Masseboeuf for the sugegstion). - - Two bugs in the TCPDF_FONTS class were fixed. - -6.0.043 (2013-10-29) - - Bug #854 "CSS instruction display" was fixed. - -6.0.042 (2013-10-25) - - Bug #852 "CMYK Colors Bug" was fixed. - -6.0.041 (2013-10-21) - - Bug #851 "Problem with images in PDF. PHP timing out" was fixed. - -6.0.040 (2013-10-20) - - Bug #849 "SVG import bug" was fixed. - -6.0.039 (2013-10-13) - - Bug #843 "Wrong call in parser" was fixed. - - Bug #844 "Wrong object type named" was fixed. - - Bug #845 "Parsing error on obj ref prefixed by '000000'" was fixed. - -6.0.038 (2013-10-06) - - Bug #841 "Division by zero warning at writeHTML a
  • tag" was fixed. - -6.0.037 (2013-09-30) - - Method getAllSpotColors() was added to return all spot colors. - - Method colorRegistrationBar() was extended to automatically print all spot colors and support individual spot colors. - - The method registrationMarkCMYK() was added to print a registration mark for CMYK colors. - - A bug related to page groups was fixed. - - Gradient() method now supports CMYK equivalents of spot colors. - - Example n. 56 was updated. - -6.0.036 (2013-09-29) - - Methods for registration bars and crop marks were extended to support registration color (see example n. 56). - - New default spot colors were added to tcpdf_colors.php, including the 'All' and 'None' special registration colors. - -6.0.035 (2013-09-25) - - TCPDF_PARSER class was improved. - -6.0.034 (2013-09-24) - - Bug #839 "Error in xref parsing in mixed newline chars" was fixed. - -6.0.033 (2013-09-23) - - Bug fix related to PNG image transparency using GD library. - -6.0.032 (2013-09-23) - - Bug #838 "Fatal error when imagick cannot handle the image, even though GD is available and can" was fixed. - -6.0.031 (2013-09-18) - - Bug #836 "Optional EOL marker before endstream" was fixed. - - Some additional controls were added to avoid "division by zero" error with badly formatted input. - -6.0.030 (2013-09-17) - - Bug #835 "PDF417 and Cyrilic simbols" was fixed. - -6.0.029 (2013-09-15) - - Constants K_TCPDF_PARSER_THROW_EXCEPTION_ERROR and K_TCPDF_PARSER_IGNORE_DECODING_ERRORS where removed in favor of a new configuration array in the TCPDF_PARSER class. - - The TCPDF_PARSER class can now be configured using the new $cfg parameter. - -6.0.028 (2013-09-15) - - A debug print_r was removed form tcpdf_parser.php. - - TCPDF_FILTERS class now throws an exception in case of error. - - TCPDF_PARSER class now throws an exception in case of error unless you define the constant K_TCPDF_PARSER_THROW_EXCEPTION_ERROR to false. - - The constant K_TCPDF_PARSER_IGNORE_DECODING_ERRORS can be set to tru eto ignore decoding errors on TCPDF_PARSER. - -6.0.027 (2013-09-14) - - A bug in tcpdf_parser wen parsing hexadecimal strings was fixed. - - A bug in tcpdf_parser wen looking for statxref was fixed. - - A bug on RC4 encryption was fixed. - -6.0.026 (2013-09-14) - - A bug in tcpdf_parser wen decoding streams was fixed. - -6.0.025 (2013-09-04) - - A pregSplit() bug was fixed. - - Improved content loading from URLs. - - Improved font path loading. - -6.0.024 (2013-09-02) - - Bug #826 "addEmptySignatureAppearance issue" was fixed. - -6.0.023 (2013-08-05) - - GNU Freefont fonts were updated. - - Licensing and copyright information about fonts were improved. - - PNG image support was improved. - -6.0.022 (2013-08-02) - - fixing initialization problem for signature_appearance property. - -6.0.021 (2013-07-18) - - The bug caused by the preg_split function on some PHP 5.2.x versions was fixed. - -6.0.020 (2013-06-04) - - The method addTTFfont() was fixed (Bug item #813 Undefined offset). - -6.0.019 (2013-06-04) - - The magic constant __DIR__ was replaced with dirname(__FILE__) for php 5.2 compatibility. - - The exceptions raised by file_exists() function were suppressed. - -6.0.018 (2013-05-19) - - The barcode examples were changed to automatically search for the barcode class path (in case the examples directory is not installed under the TCPDF root). - -6.0.017 (2013-05-16) - - The command line tool tcpdf_addfont.php was improved. - - The php logic was removed from configuration files that now contains only constant defines. - - The tcpdf_autoconfig.php file was added to automatically set missing configuration values. - -6.0.016 (2013-05-15) - - The tcpdf_addfont.php tool was improved (thanks to Remi Collet). - - Constant K_PATH_IMAGES is now automatically set in configuration file. - -6.0.015 (2013-05-14) - - Some unused vars were removed from AddFont() method. - - Some directories were moved inside the examples directory. - - All examples were updated to reflect the new default structure. - - Source code were clean-up up to be more compatible with system packaging. - - Files encodings and permissions were reset. - - The command line tool tcpdf_addfont.php was added on the tools directory. - -6.0.014 (2013-04-13) - - The signature of addTTFfont() method includes a new parameter to link existing fonts instead of copying and compressing them. - -6.0.013 (2013-04-10) - - Add support for SVG dx and dy text/tspan attributes. - - replace require() with require_once(). - - fix some minor typos on documentation. - - fix a problem when deleting all pages. - -6.0.012 (2013-04-24) - - An error condition in addHtmlLink() method was fixed (bug #799). - -6.0.011 (2013-04-22) - - Minor documentation changes. - -6.0.010 (2013-04-03) - - The method Rect() was fixed to print borders correctly. - -6.0.009 (2013-04-02) - - Adding back some files that were not properly committed on the latest release. - -6.0.008 (2013-04-01) - - Duplicated encoding maps was removed from tcpdf_font_data.php. - - Fixing bug on AddTTFFont(). - -6.0.007 (2013-03-29) - - HTML/CSS font size conversion were improved. - -6.0.006 (2013-03-27) - - Bug related to SVG and EPS files on xobjects were fixed. - -6.0.005 (2013-03-26) - - Default font path was fixed. - -6.0.004 (2013-03-21) - - Return value of addTTFfont() method was fixed. - -6.0.003 (2013-03-20) - - A bug related to non-unicode mode was fixed. - -6.0.002 (2013-03-18) - - _getFIXED call on tcpdf_fonts.php was fixed. - -6.0.001 (2013-03-18) - - Fixed $uni_type call on tcpdf.php. - -6.0.000 (2013-03-17) - - IMPORTANT: PHP4 support has been removed starting from this version. - - Several TCPDF methods and vars were moved to new class files: tcpdf_static.php, tcpdf_colors.php, tcpdf_images.php, tcpdf_font_data.php, tcpdf_fonts.php. - - Files htmlcolors.php, spotcolors.php, unicode_data.php and ecodings_maps.php were removed. - - Barcode classes were renamed and new barcode examples were added. - - Class TCPDF_PARSER was improved. - -******************************************************************************** - -5.9.209 (2013-03-15) - - Image method was improved. - -5.9.208 (2013-03-15) - - objclone function was patched to support old imagick extensions. - - tcpdf_parser was improved to support Cross-Reference Streams and large streams. - -5.9.207 (2013-03-04) - - Datamatrix class was fixed (a debug echo was removed). - -5.9.206 (2013-02-22) - - Bug item #754 "PNG with alpha channel becomes gray scale" was fixed. - - Minor documentation fixes. - -5.9.205 (2013-02-06) - - The constant K_TCPDF_THROW_EXCEPTION_ERROR was added on configuration file to change the behavior of Error() method. - - PDF417 barcode bug was fixed. - -5.9.204 (2013-01-23) - - The method Bookmark() was extended to include named destinations, URLs, internal links or embedded files (see example n. 15). - - automatic path calculation on configuration file was fixed. - - Error() method was extended to throw new Exception if PHP > 5. - -5.9.203 (2013-01-22) - - Horizontal position of radiobuttons and checkboxes was adjusted. - -5.9.202 (2012-12-16) - - Vertical space problem after table was fixed. - -5.9.201 (2012-12-10) - - First 256 chars are now always included on font subset to overcome a problem reported on the forum. - -5.9.200 (2012-12-05) - - Bug item #768 "Rowspan with Pagebreak error" was fixed. - - Page regions now works also with limited MultiCell() cells. - -5.9.199 (2012-11-29) - - Internal setImageBuffer() method was improved. - -5.9.198 (2012-11-19) - - Datamatrix EDIFACT mode was fixed. - -5.9.197 (2012-11-06) - - Bug item #756 "TCPDF 5.9.196 shows line on top of all PDFs" was fixed. - -5.9.196 (2012-11-02) - - Several methods were improved to avoid output when the context is out of page. - - Bug item #755 "remove cached files before unsetting" was fixed. - -5.9.195 (2012-10-24) - - Method _putfonts() was improved. - -5.9.194 (2012-10-23) - - Text alignment on TextField() method was fixed. - -5.9.193 (2012-09-25) - - Support for named destinations on HTML links was added (i.e.: link to named destination). - -5.9.192 (2012-09-24) - - A problem on the releasing process was fixed. - -5.9.191 (2012-09-24) - - SVG image naow support svg and eps images. - -5.9.190 (2012-09-23) - - "page" word translation is now set to empty if not defined. - - Tooltip feature was added on the radiobutton annotation. - -5.9.189 (2012-09-18) - - Bug item #3568969 "ini_get safe_mode error" was fixed. - -5.9.188 (2012-09-15) - - A datamatrix barcode bug was fixed. - -5.9.187 (2012-09-14) - - Subset feature was extended to include the first 256 characters. - -5.9.186 (2012-09-13) - - barcodes.php file was resynced. - - Methods SetAbsX, SetAbsY, SetAbsXY where added to set the absolute pointer coordinates. - - Method getCharBBox were added to get single character bounding box. - - Signature of addTTFfont method was changed ($addcbbox parameter was added). - -5.9.185 (2012-09-12) - - Method _putfontwidths() was fixed. - -5.9.184 (2012-09-11) - - A problem with EAN barcodes was fixed. - -5.9.183 (2012-09-07) - - A problem with font names normalization was fixed. - -5.9.182 (2012-09-05) - - Bug item #3564982 "Infinite loop in Write() method" was fixed. - -5.9.181 (2012-08-31) - - composer.json file was added. - - Bug item #3563369 "Cached images are not unlinked some time" was fixed. - -5.9.180 (2012-08-22) - - Bug item #3560493 "Problems with nested cells in HTML" was fixed. - -5.9.179 (2012-08-04) - - SVG 'use' tag was fixed for 'circle' and 'ellipse' shift problem. - - Alpha status is now correctly stored and restored by getGraphicVars() and SetGraphicVars() methods. - -5.9.178 (2012-08-02) - - SVG 'use' tag was fixed for 'circle' and 'ellipse'. - -5.9.177 (2012-08-02) - - An additional control on annotations was fixed. - -5.9.176 (2012-07-25) - - A bug related to stroke width was fixed. - - A problem related to font spacing in HTML was fixed. - -5.9.175 (2012-07-25) - - The problem of missing letter on hyphen break was fixed. - -5.9.174 (2012-07-25) - - The problem of wrong filename when downloading PDF from an Android device was fixed. - - The method setHeaderData() was extended to set text and line color for header (see example n. 1). - - The method setFooterData() was added to set text and line color for footer (see example n. 1). - - The methods setTextShadow() and getTextShadow() were added to set text shadows (see example n. 1). - - The GetCharWidth() method was fixed for negative character spacing. - - A 'none' border mode is now correctly recognized. - - Break on hyphen problem was fixed. - -5.9.173 (2012-07-23) - - Some additional control wher added on barcode methods. - - The option CURLOPT_FOLLOWLOCATION on Image method is now disabled if PHP safe_mode is on or open_basedir is set. - - Method Bookmark() was extended to include X parameter. - - Method setDestination() was extended to include X parameter. - - A problem with Thai language was fixed. - -5.9.172 (2012-07-02) - - A PNG color profile issue was fixed. - -5.9.171 (2012-07-01) - - Some SVG rendering problems were fixed. - -5.9.170 (2012-06-27) - - Bug #3538227 "Numerous errors inserting shared images" was fixed. - -5.9.169 (2012-06-25) - - Some SVG rendering problems were fixed. - -5.9.168 (2012-06-22) - - Thai language rendering was fixed. - -5.9.167 (2012-06-22) - - Thai language rendering was fixed and improved. - - Method isCharDefined() was improved. - - Protected method replaceChar() was added. - - Font "kerning" word was corrected to "tracking". - -5.9.166 (2012-06-21) - - Array to string conversion on file_id creation was fixed. - - Thai language rendering was fixed (thanks to Atsawin Chaowanakritsanakul). - -5.9.165 (2012-06-07) - - Some HTML form related bugs were fixed. - -5.9.164 (2012-06-06) - - A bug introduced on the latest release was fixed. - -5.9.163 (2012-06-05) - - Method getGDgamma() was changed. - - Rendering performances of PNG images with alpha channel were improved. - -5.9.162 (2012-05-11) - - A bug related to long text on TD cells was fixed. - -5.9.161 (2012-05-09) - - A bug on XREF table was fixed (Bug ID: 3525051). - - Deprecated Imagick:clone was replaced. - - Method objclone() was fixed for PHP4. - -5.9.160 (2012-05-03) - - A bug on tcpdf_parser.php was fixed. - -5.9.159 (2012-04-30) - - Barcode classes were updated to fix PNG export Bug (ID: 3522291). - -5.9.158 (2012-04-22) - - Some SVG-related bugs were fixed. - -5.9.157 (2012-04-16) - - Some SVG-related bugs were fixed. - -5.9.156 (2012-04-10) - - Bug item #3515885 "TOC and booklet: left and right page exchanged". - - SetAutoPageBreak(false) now works also in multicolumn mode. - -5.9.155 (2012-04-02) - - Bug item #3512596 "font import problems" was fixed. - - Method addTTFfont() was modified to extract only specified Platform ID and Encoding ID (check the source code documentation). - - All fonts were updated. - - Bug item #3513867 "booklet and setHeaderTemplateAutoreset: header shifted left" was fixed. - - Bug item #3513749 "TCPDF Superscript/Subscript" was fixed. - -5.9.154 (2012-03-29) - - A debug echo was removed. - -5.9.153 (2012-03-28) - - A bug on font conversion was fixed. - - All fonts were updated. - - Method isCharDefined() was added to find if a character is defined on the selected font. - - Method replaceMissingChars() was added to automatically replace missing chars on selected font. - - SetFont() method was fixed. - -5.9.152 (2012-03-23) - - The following overprint methods were added: setOverprint(), getOverprint(). - - Signature of setAlpha() method was changed and method getAlpha() was added. - - stroke-opacity support was added on SVG. - - The following date methods were added: setDocCreationTimestamp(), setDocModificationTimestamp(), getDocCreationTimestamp(), getDocModificationTimestamp(), getFormattedDate(), getTimestamp(). - - Signature of _datestring() method was changed. - - Method getFontBBox() was added. - - Method setPageBoxTypes() was aded. - -5.9.151 (2012-03-22) - - Bug item #3509889 "Transform() distorts PDF" was fixed. - - Precision of real number were extended. - - ComboBox and ListBox methods were fixed. - - Bulgarian language file was added. - - addTOC() method was improved to include bookmark color and font style. - -5.9.150 (2012-03-16) - - A bug related to form fields in PDF/A mode was fixed. - -5.9.149 (2012-02-21) - - Bug item #3489933 "SVG Parser treats tspan like text" was fixed. - -5.9.148 (2012-02-17) - - Bug item #3488600 "Multiple radiobutton sets get first set value" was fixed. - -5.9.147 (2012-02-14) - - A problem with SVG gradients has been fixed. - -5.9.146 (2012-02-12) - - Bug item #3486880 "$filehash undefine error" was fixed. - - The default font is now the one specified at PDF_FONT_NAME_MAIN constant. - -5.9.145 (2012-01-28) - - Japanese language file was added. - - TCPDF license and README.TXT files were updated. - -5.9.144 (2012-01-12) - - HTML output on barcode classes was improved. - -5.9.143 (2012-01-08) - - Bug item #3471057 "setCreator() has no effect" was fixed. - -5.9.142 (2011-12-23) - - Source code documentation was updated. - -5.9.141 (2011-12-14) - - Some minor bugs were fixed. - -5.9.140 (2011-12-13) - - SVG now supports embedded images encoded as base64. - -5.9.139 (2011-12-11) - - Spot color methods were fixed. - -5.9.138 (2011-12-10) - - cropMark() method was improved (check source code documentation). - - Example n. 56 was updated. - - Bug item #3452390 "Check Box still not ticked when set to true" was fixed. - -5.9.137 (2011-12-01) - - Bug item #3447005 "Background color and border of Form Elements is printed" was fixed. - - Color support for Form elements was improved. - -5.9.136 (2011-11-27) - - Bug item #3443387 "SetMargins with keep option does not work for top margin" was fixed. - -5.9.135 (2011-11-04) - - Bug item #3433406 "Double keywords in description" was fixed. - -5.9.134 (2011-10-29) - - The default value for $defcol parameter on convertHTMLColorToDec() method was fixed. - - Deafult HTTP headers were changed to avoid browser caching. - - Some deprecated syntax were replaced. - -5.9.133 (2011-10-26) - - Bug item #3428446 "copyPage method not working when diskcache enabled" was fixed. - -5.9.132 (2011-10-20) - - Bug item #3426167 "bug in function convertHTMLColorToDec()" was fixed. - -5.9.131 (2011-10-13) - - An error message was added to ImagePngAlpha() method. - -5.9.130 (2011-10-12) - - Now you can set image data strings on HTML img tag by encoding the image binary data in this way: $imgsrc = '@'.base64_encode($imgdata); - -5.9.129 (2011-10-07) - - Core fonts metrics was fixed (replace all helvetica and times php files on fonts folder). - - Form fields support was improved and some problems were fixed (check the example n. 14). - - Bug item #3420249 "Issue with booklet and MultiCell" was fixed. - -5.9.128 (2011-10-06) - - Method addTTFfont() was improved (check the source code documentation). - - Method setExtraXMP() to set custom XMP data was added. - -5.9.127 (2011-10-04) - - Readonly mode option was activated for radiobuttons. - -5.9.126 (2011-10-03) - - Bug item #3417989 "Graphics State operator in form XObject fails to render" was fixed. - - Xobjects problems with transparency, gradients and spot colors were fixed. - -5.9.125 (2011-10-03) - - Support for 8-digit CMYK hexadecimal color representation was added (to be used with XHTML and SVG). - - Spot colors support was improved (check example n. 37). - - Color methods were improved. - -5.9.124 (2011-10-02) - - Core fonts were updated. - -5.9.123 (2011-10-02) - - The method addTTFfont() wad added to automatically convert TTF fonts (check the new fonts guide at http://www.tcpdf.org). - - Old font utils were removed. - - All fonts were updated and new arabic fonts were added (almohanad were removed and replaced by aefurat and aealarabiya). - - The file unicode_data.php was updated. - - The file encodings_maps.php was added. - - PDF/A files are now compressed to save space. - - XHTML input form fields now support text-alignment attribute. - -5.9.122 (2011-09-29) - - PDF/A-1b compliance was improved to pass some online testing. - -5.9.121 (2011-09-28) - - This version includes support for PDF/A-1b format (the class constructor signature was changed - see example n. 65). - - Method setSRGBmode() was added to force sRGB_IEC61966-2.1 black scaled ICC color profile for the whole document (file sRGB.icc was added). - - 14 new fonts were added to allow embedding core fonts (for PDF/A compliance). - - Font utils were fixed. - -5.9.120 (2011-09-22) - - This version includes a fix for _getTrueTypeFontSubset() method. - -5.9.119 (2011-09-19) - - This version includes a fix for extra page numbering on TOC. - -5.9.118 (2011-09-17) - - This version includes some changes that allows you to add a bookmark for a page that do not exist. - -5.9.117 (2011-09-15) - - TCPDFBarcode and TCPDF2DBarcode classes were extended to include a method for exporting barcodes as PNG images. - -5.9.116 (2011-09-14) - - Datamatrix class was improved and documentation was fixed. - -5.9.115 (2011-09-13) - - Datamatrix ECC200 barcode support was added (a new datamatrix.php file was added) - check example n. 50. - - getBarcodeHTML() method was added on TCPDFBarcode and TCPDF2DBarcode classes to return an HTML representation of the barcode. - - cURL options on Image() method were improved. - - A bug on write2DBarcode() was fixed. - -5.9.114 (2011-09-04) - - A bug related to column position was fixed. - -5.9.113 (2011-08-24) - - This release include two new experimental files for parsing an existing PDF document (the integration with TCPDF is under development). - -5.9.112 (2011-08-18) - - A newline character was added after the 'trailer' keyword for compatibility with some parsers. - - Support for layers was improved. - -5.9.111 (2011-08-17) - - Barcode CODE 39 default gap was restored at 1. - -5.9.110 (2011-08-17) - - Barcode CODE 39 was fixed. - -5.9.109 (2011-08-12) - - Method getNumLines() was fixed. - - A bug related to page break in multi-column mode was fixed. - -5.9.108 (2011-08-09) - - A bug on PHP4 version was fixed. - -5.9.107 (2011-08-08) - - This version includes a minor bugfix. - -5.9.106 (2011-08-04) - - This version includes transparency groups: check the new parameter on startTemplate() method and example 62. - -5.9.105 (2011-08-04) - - Bug item #3386153 "Check Box not ticked when set to true" was fixed. - -5.9.104 (2011-08-01) - - Bug item #3383698 "imagemagick, resize and dpi" was fixed. - -5.9.103 (2011-07-16) - - Alignment of XHTML lines was improved. - - Spell of the "length" word was fixed. - -5.9.102 (2011-07-13) - - Methods startLayer() and endLayer() were added to support arbitrary PDF layers. - - Some improvements/fixes for images were added (thanks to Brendan Abbott). - -5.9.101 (2011-07-07) - - Support for JPEG and PNG ICC Color Profiles was added. - - Method addEmptySignatureAppearance() was added to add empty signature fields (see example n. 52). - - Bug item #3354332 "Strange line spacing with reduced font-size in writeHTML" was fixed. - -5.9.100 (2011-06-29) - - An SVG bug has been fixed. - -5.9.099 (2011-06-27) - - Bug item #3335045 "Font freesans seems somehow corrupted in footer" was fixed. - -5.9.098 (2011-06-23) - - The Named Destination feature was fixed. - -5.9.097 (2011-06-23) - - The method setHtmlVSpace() now can be used also for tags: div, li, br, dt and dd. - - The Named Destination feature was added (check the example n. 15) - thanks to Christian Deligant. - -5.9.096 (2011-06-19) - - Bug item #3322234 "Surrogate pairs codes in arrUTF8ToUTF16BE" was fixed. - -5.9.095 (2011-06-18) - - Numbers alignment for Table-Of-Content methods was improved and fixed. - - Font subsetting was fixed to include all parts of composite fonts. - -5.9.094 (2011-06-17) - - Bug item #3317898 "Page Group numbering broken in 5.9.093" was fixed. - -5.9.093 (2011-06-16) - - Method setStartingPageNumber() was added to set starting page number (for automatic page numbering). - -5.9.092 (2011-06-15) - - Method _putpages() was improved. - - Bug item #3316678 "Memory overflow when use Rotate and SetAutoPageBreak" was fixed. - - Right alignment of page numbers was improved. - -5.9.090 (2011-06-14) - - Methods AliasNbPages() and AliasNumPage() were re-added as deprecated for backward compatibility. - -5.9.089 (2011-06-13) - - Example n. 8 was updated. - - Method sendOutputData() was changed to remove default compression (it was incompatible with some server settings). - - Bugs related to page group numbers were fixed. - - Method copyPage() was fixed. - - Method Image() was improved to include support for alternative and external images. - -5.9.088 (2011-06-01) - - Method getAutoPageBreak() was added (see example n. 51). - - Example n. 51 (full page background) was updated. - -5.9.087 (2011-06-01) - - Method sendOutputData() was improved to include deflate encoding. - - Barcode classes on PHP 4 version were fixed. - -5.9.086 (2011-05-31) - - Font files were updated (the ones on the previous release were broken). - - The script fonts/utils/makeallttffonts.php was updated and fixed. - - Output() method was improved to use compression when available. - -5.9.085 (2011-05-31) - - TCPDFBarcode class (barcodes.php) now includes getBarcodeSVG() and getBarcodeSVGcode() methods to get SVG image representation of the barcode. - - TCPDF2DBarcode class (2dbarcodes.php) now includes getBarcodeSVG() and getBarcodeSVGcode() methods to get SVG image representation of the barcode. - -5.9.084 (2011-05-29) - - Font files were updated. - - The file fonts/utils/makeallttffonts.php was updated. - - Bug item# 3308774 "Problems with font subsetting" was fixed. - -5.9.083 (2011-05-24) - - Bug item #3308387 "line height & SetCellHeightRatio" was fixed. - -5.9.082 (2011-05-22) - - Bug item #3305592 "Setting fill color <> text color breaks text clipping" was fixed. - -5.9.081 (2011-05-18) - - Method resetHeaderTemplate() was added to reset the xobject template used by Header() method. - - Method setHeaderTemplateAutoreset() was added to automatically reset the xobject template used by Header() method at each page. - -5.9.080 (2011-05-17) - - A problem related to file path calculation for images was fixed. - - A problem related to unsuppressed getimagesize() error was fixed. - -5.9.079 (2011-05-16) - - Footer() method was changed to use C128 barcode as default (instead of the previous C128B). - -5.9.078 (2011-05-12) - - Bug item #3300878 "wrong rendering for html bullet list in some case" was fixed. - - Bug item #3301017 "Emphasized vs. font-weight" was fixed. - - Barcode Code 128 was improved to include AUTO mode (automatically switch between A, B and C modes). - - Examples n. 27 and 49 were updated. - -5.9.077 (2011-05-07) - - Bug item #3298591 "error code93" was fixed. - - SetLineStyle() function was improved. - -5.9.076 (2011-05-06) - - Bug item #3298264 "codebar 93 error" was fixed. - -5.9.075 (2011-05-02) - - Table header alignment when using WriteHTMLCell() or MultiCell() was fixed. - -5.9.074 (2011-04-28) - - Bug item #3294306 "CSS classes not work in table section" was fixed. - -5.9.073 (2011-04-27) - - A bug related to character entities on HTML cells was fixed. - -5.9.072 (2011-04-26) - - Method resetColumns() was added to remove multiple columns and reset page margins (example n. 10 was updated). - -5.9.071 (2011-04-19) - - Bug #3288574 "
    trouble" was fixed. - -5.9.069 (2011-04-19) - - Bug #3288763 "HTML-Table: non-breaking table rows: Bug" was fixed. - -5.9.068 (2011-04-15) - - Bookmark, addTOC and addHTMLTOC methods were improved to include font style and color (Examples 15, 49 and 59 were updated). - - Default $_SERVER['DOCUMENT_ROOT'] value on tcpdf_config.php file was changed. - -5.9.067 (2011-04-10) - - Performances were drastically improved (PDF documents are now created more quickly). - -5.9.066 (2011-04-09) - - A bug related to digital signature + encryption was fixed. - - A bug related to encryption + xobject templates was fixed. - -5.9.065 (2011-04-08) - - Bug item #3280512 "Text encoding iso-8859-2 crashes" was fixed. - -5.9.064 (2011-04-05) - - A bug related to character entities on HTML cells was fixed. - -5.9.063 (2011-04-01) - - Bug item #3267235 "WriteHTML() and image that doesn't fit on the page" was fixed. - -5.9.062 (2011-03-23) - - Bug item #3232650 "Using Write if there are pageRegions active creates error" was fixed. - - Bug item #3221891 "text input borders" was fixed. - - Bug item #3228958 "Adobe Reader 9.4.2 crash" was fixed. - -5.9.061 (2011-03-15) - - Bug item #3213488 "wrong function call in function Write" was fixed. - - Bug item #3203007 "list element with black background" was fixed. - -5.9.060 (2011-03-08) - - addTOC() method was fixed for text alignment problems. - -5.9.059 (2011-02-27) - - Default Header() method was improved to reduce document size. - -5.9.058 (2011-02-25) - - Image() method was improved to cache images with transparency layers (thanks to Korneliusz Jarzębski for reporting this problem). - -5.9.057 (2011-02-24) - - A problem with image caching system was fixed (thanks to Korneliusz Jarzębski for reporting this problem). - -5.9.056 (2011-02-22) - - A bug on fixHTMLCode() method was fixed. - - Automatic line break for HTML was fixed. - -5.9.055 (2011-02-17) - - Another bug related to HTML table page break was fixed. - -5.9.054 (2011-02-16) - - A bug related to HTML table page break was fixed. - -5.9.053 (2011-02-16) - - Support for HTML attribute display="none" was added. - -5.9.052 (2011-02-15) - - A bug related to HTML automatic newlines was fixed. - -5.9.051 (2011-02-12) - - "Commas at beginning of new lines" problem was fixed. - -5.9.050 (2011-02-11) - - Bug #3177606 "SVG Bar chart error" was fixed. - -5.9.049 (2011-02-03) - - Bug #3170777 "TCPDF creates a new page after a single line in writeHTML" was fixed. - -5.9.048 (2011-02-02) - - No changes. Just released to override previous release that was not uploaded correctly. - -5.9.047 (2011-01-28) - - Bug #3167115 "PDF error in (example 48)" was fixed (was introduced in 5.8.046). - -5.9.046 (2011-01-18) - - PDF view/print layers are now automatically turned off if not used (see setVisibility() method). - -5.9.045 (2011-01-17) - - HTML list support were improved. - -5.9.044 (2011-01-15) - - Bug #3158422 "writeHTMLCell Loop" was fixed. - - Some HTML image alignment problems were fixed. - -5.9.043 (2011-01-14) - - Bug #3158178 "PHP Notice" was fixed. - - Bug #3158193 "Endless loop in writeHTML" was fixed. - - Bug #3157764 "SVG Pie chart incorrectly rendered2". - -5.9.042 (2011-01-14) - - Some problems of the PHP4 version were fixed. - -5.9.041 (2011-01-13) - - A problem with SVG elliptical arc path was fixed (ref. bug #3156574). - - A problem related to font weight on HTML table headers was fixed. - -5.9.040 (2011-01-12) - - A bug related to empty pages after table was fixed. - -5.9.039 (2011-01-12) - - Bug item #3155759 "openssl_random_pseudo_bytes() slow under Windows" was fixed. - -5.9.038 (2011-01-11) - - Minor bugs were fixed. - -5.9.037 (2011-01-09) - - An alignment problem for HTML texts was fixed. - -5.9.036 (2011-01-07) - - A bug related to HTML tables on header was fixed. - -5.9.035 (2011-01-03) - - A problem related to HTML table border alignment was fixed. - - Bug #2996366 "FastCGI and Header Problems" was fixed. - -5.9.034 (2010-12-19) - - DejaVu and GNU Free fonts were updated. - -5.9.033 (2010-12-18) - - Source code documetnation was improved. - -5.9.032 (2010-12-18) - - Default font stretching and spacing values are now inherited by HTML methods. - -5.9.031 (2010-12-16) - - Source code documentation errors were fixed. - -5.9.030 (2010-12-16) - - Several source code documentation errors were fixed. - - Source code style was changed for Doxygen. - - Source code documentation was moved online to http://www.tcpdf.org - -5.9.029 (2010-12-04) - - The $fitbox parameter on Image() method was extended to specify image alignment inside the box (check the example n. 9). - -5.9.028 (2010-12-03) - - Font utils makefont.php and makeallttffonts.php were updated. - -5.9.027 (2010-12-01) - - Spot Colors are now better integrated with HTML mode. - - Method SetDocInfoUnicode() was added to turn on/off Unicode mode for document information dictionary (meta tags) - check the example n. 19. - -5.9.026 (2010-12-01) - - A problem with mixed text directions on HTML was fixed. - -5.9.025 (2010-12-01) - - The AddSpotColor() now automatically fills the spotcolor array (defined on spotcolors.php file). - -5.9.024 (2010-11-30) - - Bug item #3123612 "SVG not use gradientTransform in percentage mode" was fixed. - -5.9.023 (2010-11-25) - - A potential bug on SVG transcoder was fixed. - -5.9.022 (2010-11-21) - - Method ImageEPS includes support for EPS/AI Spot colors. - - Method ImageEPS includes a new parameter $fixoutvals to remove values outside the bounding box. - -5.9.021 (2010-11-20) - - Support for custom bullet points images was added (check the example n.6) - - Examples n. 6 and 61 were update (check the comments inside). - -5.9.020 (2010-11-19) - - A problem related to additional page when using multicolumn mode was fixed. - -5.9.019 (2010-11-19) - - An SVG bug was fixed. - - ImageSVG() and ImageEPS() methods now accepts image data streams (put the string on the $file parameter preceded by '@' character). - - Option 'E' was added to the $dest parameter of Output() method to return the document as base64 mime multi-part email attachment (RFC 2045). - -5.9.018 (2010-11-19) - - An SVG bug was fixed. - -5.9.017 (2010-11-16) - - Tagline color was set to transparent. - - The method fixHTMLCode() was added to automatically clean up HTML code (requires HTML Tidy). - -5.9.016 (2010-11-16) - - Bug item #3109705 "list item page break hanging bullet" was fixed. - -5.9.015 (2010-11-16) - - Bug item affecting QRCode was fixed. - - Some bugs affecting HTML lists were fixed. - - ImageSVG() and fitBlock() methods were improved to handle some SVG problems. - - Some problems with PHP4 compatibility were fixed. - -5.9.014 (2010-11-15) - - Bug item #3109464 "QRCode error" was fixed. - -5.9.013 (2010-11-15) - - Bug item #3109257 "Problem with interlaced GIFs and PNGs" was fixed. - - Image function now accepts image data streams (check example n. 9). - -5.9.012 (2010-11-12) - - Method getTCPDFVersion() was added. - - PDF_PRODUCER constant was removed. - - Method convertHTMLColorToDec() was improved. - - HTML colors now support spot color names defined on the new spotcolors.php file. - - The default method Header() was improved to support SVG and EPS/AI images. - - A bug on SVG importer was fixed. - -5.9.011 (2010-11-02) - - Bug item #3101486 "Bug Fix for image loading" was fixed. - -5.9.010 (2010-10-27) - - Support for CSS properties 'border-spacing' and 'padding' for tables were added. - - Several language files were added. - -5.9.009 (2010-10-21) - - HTML text alignment was improved to include the case of RTL text on LTR direction and LTR text on RTL direction. - -5.9.008 (2010-10-21) - - Bug item #3091502 "Bookmark oddity" was fixed. - - HTML internal links now accepts page number and Y position. - - The method write1DBarcode() was improved to accept separate horizontal and vertical padding (see example n. 27). - -5.9.007 (2010-10-20) - - Method adjustCellPadding() was fixed to handle bad input. - -5.9.006 (2010-10-19) - - Support for AES 256 bit encryption was added (see example n. 16). - - Method getNumLines() was fixed for the empty string case. - -5.9.005 (2010-10-18) - - Method addPageRegion() was changed to accept regions starting exactly from the top of the page. - -5.9.004 (2010-10-18) - - A bug related to annotations was fixed. - - The file unicode_data.php was canged to encapsulate all data in a class. - - The file htmlcolors.php was changed to remove the global variable. - -5.9.003 (2010-10-15) - - Support for no-write page regions was added. Check the example n. 64 and new methods setPageRegions(), addPageRegion(), getPageRegions(), removePageRegion(). - - A bug on Right-To-Left alignment was fixed. - -5.9.002 (2010-10-08) - - Cell method was improved to preserve the font stretching and spacing values when using the $stretch parameter (see example n. 4). - -5.9.001 (2010-10-07) - - The problem of blank page for nobr table higher than a single page was fixed. - -5.9.000 (2010-10-06) - - Support for text stretching and spacing (tracking) was added, see example n. 63 and methods setFontStretching(), getFontStretching(), setFontSpacing(), getFontSpacing(). - - Support for CSS properties 'font-stretch' and 'letter-spacing' was added (see example n. 63). - - The cMargin state was replaced by cell_padding array that can be set/get using setCellPadding() and getCellPadding() methods. - - Methods getCellPaddings() and setCellPaddings() were added to fine tune cell paddings (see example n. 5). - - Methods getCellMargins() and setCellMargins() were added to fine tune cell margins (see example n. 5). - - Method write1DBarcode() was improved to permit custom labels (see example n. 27). - - Method ImagePngAlpha() now includes support for ImageMagick to improve performances. - - XObject Template support was extended to support Multicell(), writeHTML() and writeHTMLCell() methods. - - The signature of getNumLines() and getStringHeight() methods is changed. - - Example n. 57 was updated. - -// ------------------------------------------------------------------- - -5.8.034 (2010-09-27) - - A bug related to SetFont on XObject templates was fixed. - -5.8.033 (2010-09-25) - - A problem with Footer() and multiple columns was fixed. - -5.8.032 (2010-09-22) - - Bug #3073165 "Issues with changes to addHTMLVertSpace()" was fixed. - -5.8.031 (2010-09-20) - - Bug #3071961 "Spaces in HTML" was fixed. - -5.8.030 (2010-09-17) - - SVG support was improved and some bugs were fixed. - -5.8.029 (2010-09-16) - - A problem with HTML borders was fixed. - -5.8.028 (2010-09-13) - - Bug #3065224 "mcrypt_create_iv error on TCPDF 5.8.027 on PHP 5.3.2" was fixed. - -5.8.027 (2010-09-13) - - Bug #3065118 "mcrypt_decrypt error on TCPDF 5.8.026 on PHP 5.3.2" was fixed. - -5.8.026 (2010-09-13) - - A bug on addHTMLTOC() method was fixed. Note: be sure that the #TOC_PAGE_NUMBER# template has enough width to be printed correctly. - -5.8.025 (2010-09-09) - - Bug #3062692 "Textarea inside a table" was fixed. - -5.8.024 (2010-09-08) - - Bug #3062005 "Undefined variable: ann_obj_id" was fixed. - -5.8.023 (2010-08-31) - - Forms bug added on version 5.8.019 was fixed. - -5.8.022 (2010-08-31) - - Bug #3056632 "SVG rendered vertically flipped" was fixed. - -5.8.021 (2010-08-30) - - A new CID-0 'chinese' font was added for traditional Chinese. - - Bug #3054287 'Inner tags are ignored due to "align" attribute' was fixed. - -5.8.020 (2010-08-26) - - CSS "catch-all" class selector is now supported. - -5.8.019 (2010-08-26) - - XObject Templates now includes support for links and annotations. - - A problem related to link alignment on cell was fixed. - - A problem related to SVG styles was fixed. - -5.8.018 (2010-08-25) - - Method getNumberOfColumns() was added. - - A problem related to table header was fixed. - - Method getSVGTransformMatrix() was fixed to apply SVG transformations in the correct order. - - SVG support was improved and several bugs were fixed. - -5.8.017 (2010-08-25) - - This version includes support for XObject Templates (see the new example n. 62). - - Methods starttemplate(), endTemplate() and printTemplate() were added (see the new example n. 62). - -5.8.016 (2010-08-24) - - Alignment problem on write2DBarcode was fixed. - -5.8.015 (2010-08-24) - - A problem arose with the latest bugfix was fixed. - -5.8.014 (2010-08-23) - - Method _getxobjectdict() was added for better compatibility with external extensions. - - A bug related to radiobuttons was fixed. - - Bug #3051509 "new line after punctuation marks" was fixed (partially). - -5.8.013 (2010-08-23) - - SVG support for 'direction' property was added. - - A problem on default width calculation for linear barcodes was fixed. - - New option was added to write1DBarcode() method to improve alignments (see example n. 27). - - Bug #3050896 "Nested HTML tables: styles are not applied" was fixed. - - Method _putresourcedict() was improved to include external XObject templates. - -5.8.012 (2010-08-22) - - Support for SVG 'text-anchor' property was added. - -5.8.011 (2010-08-21) - - Method write1DBarcode() was improved to be backward compatible (check the new example n. 27). - - Support for CSS width and height properties on images were added. - -5.8.010 (2010-08-20) - - Documentation of unhtmlentities() was fixed. - - The 'fitwidth' option was added and border color problem was fixed on write1DBarcode() method (check the example n. 27). - -5.8.009 (2010-08-20) - - Internal object numbering was improved. - - Some errors in object encryption were fixed. - -5.8.008 (2010-08-19) - - Method write1DBarcode() was changed, check the example n. 27. - - Method Footer() was changed to account for barcode changes. - - Automatic calculation of K_PATH_URL constant was fixed on configuration file. - - Method setEqualColumns() was fixed for $width=0 case. - - Method AddTOC() was fixed for multipage and multicolumn modes. - - Better support for SVG "font-family" property. - - A problem on default Page Zoom mode was fixed. - - Several Annotation bugs were fixed. - -5.8.007 (2010-08-18) - - A bug affecting HTML tables was fixed. - - Bug #3047500 "SVG not rendering paths properly" was fixed. - -5.8.006 (2010-08-17) - - A bug affecting HTML table nesting was fixed. - -5.8.005 (2010-08-17) - - A bug affecting the HTML 'select' tag in certain conditions was fixed. - -5.8.004 (2010-08-17) - - Better support for HTML "font-family" property. - - A bug related to HTML multicolumn was fixed. - -5.8.003 (2010-08-16) - - Better support for HTML "font-family" property. - -5.8.002 (2010-08-14) - - HTML alignments were improved - - IMPORTANT: Default regular expression to find spaces has been changed to exclude the non-breaking-space (160 DEC- A0 HEX). If you are using setSpacesRE() method, please read the new documentation. - - Example n. 1 was updated. - -5.8.001 (2010-08-12) - - Bug #3043650 "subsetchars incorrectly cached" was fixed. - -5.8.000 (2010-08-11) - - A control to avoid bookmarking page 0 was added. - - addTOC() method now includes support for multicolumn mode. - - Support for tables in multicolumn mode was improved. - - Example n.10 was updated. - - All trimming functions were replaced with stringLeftTrim(), stringRightTrim() and stringTrim(). - - HTML alignments were improved. - ------------------------------------------------------------- - -5.7.003 (2010-08-08) - - Bug #3041263 "php source ending is bad" was fixed (all PHP files were updated, including fonts). - -5.7.002 (2010-08-06) - - Methods copyPage(), movePage() and deletePage() were changed to account for internal markings. - -5.7.001 (2010-08-05) - - Bug #3040105 "Broken PDF when using TOC (example 45)" was fixed. - -5.7.000 (2010-08-03) - - CSS borders are now supported for HTML tables and other block tags (see example n. 61); - - Cell borders were improved (see example n. 57); - - Minor bugs were fixed. - ------------------------------------------------------------- - -5.6.000 (2010-07-31) - - A bug with object IDs was fixes. - - Performances were improved. - ------------------------------------------------------------- - -5.5.015 (2010-07-29) - - Automatic fix for unclosed self-closing tag. - - Support for deprecated 's' and 'strike' tags was added. - - Empty list items problem was fixed. - -5.5.014 (2010-07-15) - - Support for external images was improved. - -5.5.013 (2010-07-14) - - Bug #3029338 "FI and FO output destination filename bug" was fixed (previous fix was wrong). - -5.5.012 (2010-07-14) - - Bug #3029310 "Font baseline inconsistencies with line-height and font-size" was fixed. - - Bug #3029338 "FI and FO output destination filename bug" was fixed. - -5.5.011 (2010-07-09) - - Support for multiple CSS classes was added. - - The method getColumn() was added to return the current column number. - - Some regular Expressions were fixed to be more compatible with UTF-8. - -5.5.010 (2010-07-06) - - Bug item #3025772 "Borders in all image functions are still flawed" was fixed. - -5.5.009 (2010-07-05) - - A problem related to last page footer was fixed. - - Image alignments and fit-on-page features were improved. - -5.5.008 (2010-07-02) - - A problem on table header alignment in booklet mode was fixed. - - Default graphic vars are now applied for setHeader(); - -5.5.007 (2010-07-02) - - Attribute "readonly" was added to input and textarea form fields. - - Vertical alignment feature was added on MultiCell() method only for simple text mode (see example n. 5). - - Text-Fit feature was added on MultiCell() method only for simple text mode (see example n. 5). - -5.5.006 (2010-06-29) - - getStringHeight() and getNumLines() methods were fixed. - -5.5.005 (2010-06-28) - - Bug #3022170 "getFontDescent() does not return correct descent value" was fixed. - - Some problems with multicolumn mode were fixed. - -5.5.004 (2010-06-27) - - Bug #3021803 "SVG Border" was fixed. - -5.5.003 (2010-06-26) - - On Write() method, blank lines at the beginning of a page or column are now automatically removed. - -5.5.002 (2010-06-24) - - ToUnicode Identity-H name was replaced with a full CMap (to avoid preflight syntax error). - - Bug #3020638 "str_split() not available in php4" was fixed. - - Bug #3020665 "file_get_contents() too many parameters for php4" was fixed. - -5.5.001 (2010-06-23) - - A problem on image streams was fixed. - -5.5.000 (2010-06-22) - - Several PDF syntax errors (and related bugs) were fixed. - - Bug #3019090 "/Length values are wrong if AES encryption is used" was fixed. - ------------------------------------------------------------- - -5.4.003 (2010-06-19) - - A problem related to page boxes was fixed. - - Bug #3016920 "Font subsetting issues when editing pdf" was partially fixed (Note that flattening transparency layers is currently incompatible with TrueTypeUnicode fonts). - -5.4.002 (2010-06-18) - - A problem related with setProtection() method was fixed. - -5.4.001 (2010-06-18) - - A problem related with setProtection() method was fixed. - -5.4.000 (2010-06-18) - - The method setSignatureAppearance() was added, check the example n. 52. - - Several problems related to font subsetting were fixed. - ------------------------------------------------------------- - -5.3.010 (2010-06-15) - - Previous release was corrupted. - -5.3.009 (2010-06-15) - - Bug #3015934 "Bullets don't display correctly" was fixed. - -5.3.008 (2010-06-13) - - This version fixes some problems of SVG rasterization. - -5.3.007 (2010-06-13) - - This version improves SVG support. - -5.3.006 (2010-06-10) - - This version includes a change in uniqid calls for backward compatibility with PHP4. - -5.3.005 (2010-06-09) - - The method getPageSizeFromFormat() was changed to include all standard page formats (includes 281 page formats + variation). - -5.3.004 (2010-06-08) - - Bug #3013291 "HTML table cell width" was fixed. - - Bug #3013294 "HTML table cell alignment" was fixed. - - The columns widths of HTML tables are now inherited from the first row. - -5.3.003 (2010-06-08) - - Bug #3013102 "HTML table header misaligned after page break" was fixed. - -5.3.002 (2010-06-07) - - The methods setFontSubsetting() and setFontSubsetting() were added to control the default font subsetting mode (see example n. 1). - - Bug #3012596 "Whitespace should not appeared after use Thai top characters" was fixed. - - Examples n. 1, 14, and 54 were updated. - -5.3.001 (2010-06-06) - - Barcode PDF417 was improved to support Macro Code Blocks (see example n. 50). - -5.3.000 (2010-06-05) - - License was changed to GNU-LGPLv3 (see the updated LICENSE.TXT file). - - PDF417 barcode support was added (check the example n. 50). - - The method write2DBarcode() was improved (some parameters were added and other changed - check example n. 50). - ------------------------------------------------------------- - -5.2.000 (2010-06-02) - - IMPORTANT: Support for font subsetting was added by default to reduce the size of documents using large unicode font files. - If you embed the whole font in the PDF, the person on the other end can make changes to it even if he didn't have your font. - If you subset the font, file size of the PDF will be smaller but the person who receives your PDF would need to have your same font in order to make changes to your PDF. - - The signature of the SetFont() and AddFont() methods were changed to include the font subsetting option (subsetting is applied by default). - - Examples 14 and 54 were updated. - ------------------------------------------------------------- - -5.1.002 (2010-05-27) - - Bug #3007818 "SetAutoPageBreak fails with MultiCell" was fixed. - - A bug related to MultiCell() minimun height was fixed. - -5.1.001 (2010-05-26) - - The problem of blank page after table was fixed. - -5.1.000 (2010-05-25) - - This version includes support for CSS (Cascading Style Sheets) (see example n. 61). - - The convertHTMLColorToDec() method was improved. - ------------------------------------------------------------- - -5.0.014 (2010-05-21) - - A problem on color and style of HTML links was fixed. - - A bug relative to gradients was fixed. - - The getStringHeight() method was added and getNumLines() method was improved. - - All examples were updated. - -5.0.013 (2010-05-19) - - A bug related to page-breaks and table cells was fixed. - -5.0.012 (2010-05-19) - - Page orientation bug was fixed. - - The access to method setPageFormat() was changed to 'protected' because it is not intended to be directly called. - -5.0.011 (2010-05-19) - - Page orientation bug was fixed. - - Bug #3003966 "Multiple columns and nested lists" was fixed. - -5.0.010 (2010-05-17) - - The methods setPageFormat(), setPageOrientation() and related methods were extended to include page boxes, page rotations and page transitions. - - The method setPageBoxes() was added to set page boundaries (MediaBox, CropBox, BleedBox, TrimBox, ArtBox); - - A bug relative to underline, overline and linethrough was fixed. - -5.0.009 (2010-05-16) - - Bug #3002381 "Multiple columns and nested lists" was fixed. - -5.0.008 (2010-05-15) - - Bug "Columns WriteHTML and Justification" was fixed. - -5.0.007 (2010-05-14) - - Bug #3001347 "Bug when using WriteHTML with setEqualColumns()" was fixed. - - Bug #3001505 "problem with sup and sub tags at the beginning of a line" was fixed. - -5.0.006 (2010-05-13) - - Length of hr tag was fixed. - - An error on 2d barcode method was fixed. - -5.0.005 (2010-05-12) - - WARNING: The logic of permissions on the SetProtection() method has been inverted and extended (see example 16). Now you have to specify the features you want to block. - - SetProtection() method was extended to support RSA and AES 128 encryption and public-keys (see example 16). - - Bug #2999489 "setEqualColumns() and TOC uses wrong columns" was fixed (see the example 10). - -5.0.004 (2010-05-10) - - HTML line alignment when using sub and sup tags was fixed. - -5.0.003 (2010-05-07) - - Horizontal alignment was fixed for images and barcodes. Now the X coordinate is always relative to the left margin. Use GetAbsX() instead of GetX() to get the X relative to left margin. - - Header() method was changed to account for new image alignment rules. - -5.0.002 (2010-05-06) - - Bookmark() and related methods were fixed to accept HTML code. - - A problem on HTML links was fixed. - -5.0.001 (2010-05-06) - - Protected method _putstream was re-added for backward compatibility. - - The following method were added to display HTML Table Of Content (see example n. 59): - addTOCPage(), endTOCPage(), addHTMLTOC(). - -5.0.000 (2010-05-05) - - Method ImageSVG() was added to embedd SVG images (see example n. 58). Note that not all SVG images are supported. - - Method setRasterizeVectorImages() was added to enable/disable rasterization for vector images via ImageMagick library. - - Method RoundedRectXY() was added. - - Method PieSectorXY() was added. - - Gradient() method is now public and support new features. - - Shading to transparency is now supported. - - Image alignments were fixed. - - Support for dynamic images were improved. - - PDF_IMAGE_SCALE_RATIO has been changed to 1.25 for better compatibility with SVG. - - RAW and RAW2 modes were added to 2D Barcodes (see example n. 50). - - Automatic padding feature was added on barcodes (see examples n. 27 and 50). - - Bug #2995003 "Reproduced thead bug" was fixed. - - The Output() method now accepts FI and FD destinations to save the document on server before sending it to the client. - - Ellipse() method was improved and fixed (see page 2 of example n. 12). - ------------------------------------------------------------- - -4.9.018 (2010-04-21) - - Bug item #2990356 "Current font size not respected with more than two HTML

    " was fixed. - -4.9.017 (2010-04-21) - - Bug item #2990224 "Different behaviour for equivalent HTML strings" was fixed. - - Bug item #2990314 "Dash is not appearing with SHY character" was fixed. - -4.9.016 (2010-04-20) - - An error on htmlcolors.php was fixed. - - getImageFileType() method was improved. - - GIF images with transparency are now better supported. - - Automatic page orientation was improved. - -4.9.015 (2010-04-20) - - A new method copyPage() was added to clone pages (see example n. 44). - - Support for text overline was added. - - Underline and linethrough methods were fixed. - - Bug #2989058 "SHY character causes unnecessary word-wrapping" was fixed. - -4.9.014 (2010-04-18) - - Bug item #2988845 was fixed. - -4.9.013 (2010-04-15) - - Image() and ImageEPS() methods were fixed and improved; $fitonpage parameter was added. - -4.9.012 (2010-04-12) - - The hyphenateText() method was added to automatically hyphenate text (see example n. 46). - -4.9.011 (2010-04-07) - - Vertical alignments for Cell() method were improved (see example n. 57). - -4.9.010 (2010-04-06) - - Signature of Cell() method now includes new parameters for vertical alignment (see example n. 57). - - Text() method was extended to include all Cell() parameters. - - HTML line alignment procedure was changed to fix some bugs. - -4.9.009 (2010-04-05) - - Text() method was fixed for backward compatibility. - -4.9.008 (2010-04-03) - - Additional line space after table header was removed. - - Support for HTML lists in multicolumn mode was added. - - The method setTextRenderingMode() was added to set text rendering modes (see the example n. 26). - - The following HTML attributes were added to set text rendering modes (see the example n. 26): stroke, strokecolor, fill. - -4.9.007 (2010-04-03) - - Font Descent computation was fixed (patch #2981441). - -4.9.006 (2010-04-02) - - The constant K_TCPDF_CALLS_IN_HTML was added on configuration file to enable/disable the ability to call TCPDF methods in HTML. - - The usage of tcpdf tag in HTML mode was changed to remove the possible security flaw offered by the eval() function (thanks to Matthias Hecker for spotting this security problem). See the new example n. 49 for further information. - -4.9.005 (2010-04-01) - - Bug# 2980354 "Wrong File attachment description with security" was fixed. - - Several problems with HTML line alignment were fixed. - - The constant K_THAI_TOPCHAR was added on configuration file to enable/disable the special procedure used to avoid the overlappind of symbols on Thai language. - - A problem with font name directory was fixed. - - A bug on _destroy() method was fixed. - -4.9.004 (2010-03-31) - - Patch #979681 "GetCharWidth - default character width" was applied (bugfix). - -4.9.003 (2010-03-30) - - Problem of first
    on multiple columns was fixed. - - HTML line alignment was fixed. - - A QR-code bug was fixed. - -4.9.002 (2010-03-29) - - Patch #2978349 "$ignore_min_height is ignored in function Cell()" was applied. - - Bug #2978607 "2D Barcodes are wrong" was fixed. - - A problem with HTML block tags was fixed. - - Artificial italic for CID-0 fonts was added. - - Several multicolumn bugs were fixed. - - Support for HTML tables on multicolumn was added. - -4.9.001 (2010-03-28) - - QR Code minor bug was fixed. - - Multicolumn mode was added (see the new example n. 10). - - The following methods were added: setEqualColumns(), setColumnsArray(), selectColumn(). - - Thai diacritics support were changed (note that this is incompatible with html justification). - -4.9.000 (2010-03-27) - - QR Code (2D barcode) support was added (see example n. 50). - - The following methods were added to print crop and registration marks (see example n. 56): colorRegistrationBar(), cropMark(), registrationMark(). - - Limited support for CSS line-height property was added. - - Gradient method now supports Gray, RGB and CMYK space color. - - Example n. 51 was updated. - - Vertical alignment of font inside cell was fixed. - - Support for multiple Thai diacritics was added. - - Bug item #2974929 "Duplicate case values" was fixed. - - Bug item #2976729 "File attachment not working with security" was fixed. - ------------------------------------------------------------- - -4.8.039 (2010-03-20) - - Problems related to custom locale settings were fixed. - - Problems related to HTML on Header and Footer were fixed. - -4.8.038 (2010-03-13) - - Various bugs related to page-break in HTML mode were fixed. - - Bug item #2968974 "Another

    pagebreak problem" was fixed. - - Bug item #2969276 "justification problem" was fixed. - - Bug item #2969289 "bug when using justified text and custom headers" was fixed. - - Images are now automatically resized to be contained on the page. - - Some HTML line alignments were fixed. - - Signature of AddPage() and SetMargins() methods were changed to include an option to set default page margins. - -4.8.037 (2010-03-03) - - Bug item #2962068 was fixed. - - Bug item #2967017 "Problems with and pagebreaks" was fixed. - - Bug item #2967023 "table header lost with pagebreak" was fixed. - - Bug item #2967032 "Header lost with nested tables" was fixed. - -4.8.036 (2010-02-24) - - Automatic page break for HTML images was improved. - - Example 10 was updated. - - Japanese was removed from example 8 because the freeserif font doesn't contain japanese (you can display it using arialunicid0 font). - -4.8.035 (2010-02-23) - - Automatic page break for HTML images was added. - - Support for multicolumn HTML was added (example 10 was updated). - -4.8.034 (2010-02-17) - - Language files were updated. - -4.8.033 (2010-02-12) - - A bug related to protection mode with links was fixed. - -4.8.032 (2010-02-04) - - A bug related to $maxh parameter on Write() and MultiCell() was fixed. - - Support for body tag was added. - -4.8.031 (2010-01-30) - - Bug item #2941589 "paragraph justify not working on some non-C locales" was fixed. - -4.8.030 (2010-01-27) - - Some text alignment cases were fixed. - -4.8.029 (2010-01-27) - - Bug item #2941057 "TOC Error in PDF File Output" was fixed. - - Some text alignment cases were fixed. - -4.8.028 (2010-01-26) - - Text alignment for RTL mode was fixed. - -4.8.027 (2010-01-25) - - Bug item #2938412 "Table related problems - thead, nobr, table width" was fixed. - -4.8.026 (2010-01-19) - - The misspelled word "length" was replaced with "length" in some variables and comments. - -4.8.025 (2010-01-18) - - addExtGState() method was improved to reuse existing ExtGState objects. - -4.8.024 (2010-01-15) - - Justification mode for HTML was fixed (Bug item #2932470). - -4.8.023 (2010-01-15) - - Bug item #2932470 "Some HTML entities breaks justification" was fixed. - -4.8.022 (2010-01-14) - - Source code documentation was fixed. - -4.8.021 (2010-01-03) - - A Bug relative to Table Of Content index was fixed. - -4.8.020 (2009-12-21) - - Bug item #2918545 "Display problem of the first row of a table with larger font" was fixed. - - A Bug relative to table rowspan mode was fixed. - -4.8.019 (2009-12-16) - - Bug item #2915684 "Image size" was fixed. - - Bug item #2914995 "Image jpeg quality" was fixed. - - The signature of the Image() method was changed (check the documentation for the $resize parameter). - -4.8.018 (2009-12-15) - - Bug item #2914352 "write error" was fixed. - -4.8.017 (2009-11-27) - - THEAD problem when table is used on header/footer was fixed. - - A first line alignment on HTML justification was fixed. - - Method getImageFileType() was added. - - Images with unknown extension and type are now supported via ImageMagick PHP extension. - -4.8.016 (2009-11-21) - - Document Information Dictionary was fixed. - - CSS attributes 'page-break-before', 'page-break-after' and 'page-break-inside' are now supported. - - Problem of unclosed last page was fixed. - - Problem of 'thead' unnecessarily repeated on the next page was fixed. - -4.8.015 (2009-11-20) - - A problem with some PNG transparency images was fixed. - - Bug #2900762 "Sort issues in Bookmarks" was fixed. - - Text justification was fixed for various modes: underline, strikeout and background. - -4.8.014 (2009-11-04) - - Bug item #2891316 "writeHTML, underlining replacing spaces" was fixed. - - The handling of temporary RTL text direction mode was fixed. - -4.8.013 (2009-10-26) - - Bug item #2884729 "Problem with word-wrap and hyphen" was fixed. - -4.8.012 (2009-10-23) - - Table cell alignments for RTL booklet mode were fixed. - - Images and barcode alignments for booklet mode were fixed. - -4.8.011 (2009-10-22) - - DejaVu fonts were updated to latest version. - -4.8.010 (2009-10-21) - - Bookmark for TOC page was added. - - Signature of addTOC() method is changed. - - Bookmarks are now automatically sorted by page and Y position. - - Example n. 45 was updated. - - Example n. 55 was added to display all charactes available on core fonts. - -4.8.009 (2009-09-30) - - Compatibility with PHP 5.3 was improved. - - All examples were updated. - - Index file for examples was added. - -4.8.008 (2009-09-29) - - Example 49 was updated. - - Underline and linethrough now works with cell stretching mode. - -4.8.007 (2009-09-23) - - Infinite loop problem caused by nobr attribute was fixed. - -4.8.006 (2009-09-23) - - Bug item #2864522 "No images if DOCUMENT_ROOT=='/'" was fixed. - - Support for text-indent CSS attribute was added. - - Method rollbackTransaction() was changed to support self-reassignment of previous object (check source code documentation). - - Support for the HTML "nobr" attribute was added to avoid splitting a table or a table row on two pages (i.e.: ...). - -4.8.005 (2009-09-17) - - A bug relative to multiple transformations and annotations was fixed. - -4.8.004 (2009-09-16) - - A bug on _putannotsrefs() method was fixed. - -4.8.003 (2009-09-15) - - Bug item #2858754 "Division by zero" was fixed. - - A bug relative to HTML list items was fixed. - - A bug relative to form fields on multiple pages was fixed. - - PolyLine() method was added (see example n. 12). - - Signature of Polygon() method was changed. - -4.8.002 (2009-09-12) - - A problem related to CID-0 fonts offset was fixed: if the $cw[1] entry on the CID-0 font file is not defined, then a CID keys offset is introduced. - -4.8.001 (2009-09-09) - - The appearance streams (AP) for anotations form fields was fixed (see examples n. 14 and 54). - - Radiobuttons were fixed. - -4.8.000 (2009-09-07) - - This version includes some support for Forms fields (see example n. 14) and XHTML forms (see example n. 54). - - The following methods were changed to work without JavaScript: TextField(), RadioButton(), ListBox(), ComboBox(), CheckBox(), Button(). - - Support for Widget annotations was improved. - - Alignment of annotation objects was fixed (examples 36 and 41 were updated). - - addJavascriptObject() method was added. - - Signature of Image() method was changed. - - htmlcolors.php file was updated. - ------------------------------------------------------------- - -4.7.003 (2009-09-03) - - Support for TCPDF methods on HTML was improved (see example n. 49). - -4.7.002 (2009-09-02) - - Bug item #2848892 "writeHTML + table: Gaps between rows" was fixed. - - JavaScript support was fixed (see example n. 53). - -4.7.001 (2009-08-30) - - The Polygon() and Arrow() methods were fixed and improved (see example n. 12). - -4.7.000 (2009-08-29) - - This is a major release. - - Some procedures were internally optimized. - - The problem of mixed signature and annotations was fixed (example n. 52). - -4.6.030 (2009-08-29) - - IMPORTANT: percentages on table cell widths are now relative to the full table width (as in standard HTML). - - Various minor bugs were fixed. - - Example n. 52 (digital signature) was updated. - -4.6.029 (2009-08-26) - - PHP4 version was fixed. - -4.6.028 (2009-08-25) - - Signature algorithm was finally fixed (see example n. 52). - -4.6.027 (2009-08-24) - - TCPDF now supports unembedded TrueTypeUnicode Fonts (just comment the $file entry on the fonts' php file. - -4.6.026 (2009-08-21) - - Bug #2841693 "Problem with MultiCell and ishtml and justification" was fixed. - - Signature functions were improved but not yet fixed (tcpdf.crt and example n. 52 were updated). - -4.6.025 (2009-08-17) - - Carriage returns (\r) were removed from source code. - - Problem related to set_magic_quotes_runtime() depracated was fixed. - -4.6.024 (2009-08-07) - - Bug item #2833556 "justification using other units than mm" was fixed. - - Documentation was fixed/updated. - -4.6.023 (2009-08-02) - - Bug item #2830537 "MirrorH can show mask for transparent PNGs" was fixed. - -4.6.022 (2009-07-24) - - A bug relative to single line printing when using WriteHTMLCell() was fixed. - - Signature support were improved but is still experimental. - - Fonts Free and Dejavu were updated to latest versions. - -4.6.021 (2009-07-20) - - Bug item #2824015 "XHTML Ampersand & in hyperlink bug" was fixed. - - Bug item #2824036 "Image as hyperlink in table, text displaced at page break" was fixed. - - Links alignment on justified text was fixed. - - Unicode "\u" modifier was added to re_spaces variable by default. - -4.6.020 (2009-07-16) - - Bug item #2821921 "issue in example 18" was fixed. - - Signature of SetRTL() method was changed. - -4.6.019 (2009-07-13) - - Bug item #2820703 "xref table broken" was fixed. - -4.6.018 (2009-07-10) - - Bug item #2819319 "Text over text" was fixed. - - Method Arrow() was added to print graphic arrows (example 12 was updated). - -4.6.017 (2009-07-05) - - Bug item #2816079 "Example 48 not working" was fixed. - - The signature of the checkPageBreak() was changed. The parameter $addpage was added to turn off the automatic page creation. - -4.6.016 (2009-06-16) - - Method setSpacesRE() was added to set the regular expression used for detecting withespaces or word separators. If you are using chinese, try: setSpacesRE('/[\s\p{Z}\p{Lo}]/');, otherwise you can use setSpacesRE('/[\s\p{Z}]/'); - - The method _putinfo() now automatically fills the metadata with '?' in case of empty string. - -4.6.015 (2009-06-11) - - Bug #2804667 "word wrap bug" was fixed. - -4.6.014 (2009-06-04) - - Bug #2800931 "Table thead tag bug" was fixed. - - A bug related to
     tag was fixed.
    -
    -4.6.013 (2009-05-28)
    -	- List bullets position was fixed for RTL languages.
    -
    -4.6.012 (2009-05-23)
    -	- setUserRights() method doesn't work anymore unless you call the setSignature() method with the Adobe private key!
    -
    -4.6.011 (2009-05-18)
    -	- Signature of the Image() method was changed to include the new $fitbox parameter (see source code documentation).
    -
    -4.6.010 (2009-05-17)
    -	- Image() method was improved: now is possible to specify the maximum dimensions for a constraint box defined by $w and $h parameters, and setting the $resize parameter to null.
    -	-  tag indent problem was fixed.
    -	- $y parameter was added to checkPageBreak() method.
    -	- Bug n. 2791773 "writeHTML" was fixed.
    -
    -4.6.009 (2009-05-13)
    -	- xref table for embedded files was fixed.
    -
    -4.6.008 (2009-05-07)
    -	- setSignature() method was improved (but is still experimental).
    -	- Example n. 52 was added.
    -
    -4.6.007 (2009-05-05)
    -	- Bug #2786685 "writeHtmlCell and 
    in custom footer" was fixed. - - Table header repeating bug was fixed. - - Some newlines and tabs are now automatically removed from HTML strings. - -4.6.006 (2009-04-28) - - Support for "..." was added. - - By default TCPDF requires PCRE Unicode support turned on but now works also without it (with limited ability to detect some Unicode blank spaces). - -4.6.005 (2009-04-25) - - Points (pt) conversion in getHTMLUnitToUnits() was fixed. - - Default tcpdf.pem certificate file was added. - - Experimental support for signing document was added but it is not yet completed (some help is needed - I think that the calculation of the ByteRange is OK and the problem is on the signature calculation). - -4.6.004 (2009-04-23) - - Method deletePage() was added to delete pages (see example n. 44). - -4.6.003 (2009-04-21) - - The caching mechanism of the UTF8StringToArray() method was fixed. - -4.6.002 (2009-04-20) - - Documentation of rollbackTransaction() method was fixed. - - The setImageScale() and getImageScale() methods now set and get the adjusting parameter used by pixelsToUnits() method. - - HTML images now support other units of measure than pixels (getHTMLUnitToUnits() is now used instead of pixelsToUnits()). - - WARNING: PDF_IMAGE_SCALE_RATIO has been changed by default to 1. - -4.6.001 (2009-04-17) - - Spaces between HTML block tags are now automatically removed. - - The bug related to cMargin changes between tables was fixed. - -4.6.000 (2009-04-16) - - WARNING: THIS VERSION CHANGES THE BEHAVIOUR OF $x and $y parameters for several TCPDF methods: - zero coordinates for $x and $y are now valid coordinates; - set $x and $y as empty strings to get the current value. - - Some error caused by 'empty' function were fixed. - - Default color for convertHTMLColorToDec() method was changed to white and the return value for invalid color is false. - - HTML on footer bug was fixed. - - The following examples were fixed: 5,7,10,17,19,20,21,33,42,43. - -4.5.043 (2009-04-15) - - Barcode class (barcode.php) was extended to include new linear barcode types (see example n. 27): - C39 : CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9 - C39+ : CODE 39 with checksum - C39E : CODE 39 EXTENDED - C39E+ : CODE 39 EXTENDED + CHECKSUM - C93 : CODE 93 - USS-93 - S25 : Standard 2 of 5 - S25+ : Standard 2 of 5 + CHECKSUM - I25 : Interleaved 2 of 5 - I25+ : Interleaved 2 of 5 + CHECKSUM - C128A : CODE 128 A - C128B : CODE 128 B - C128C : CODE 128 C - EAN2 : 2-Digits UPC-Based Extension - EAN5 : 5-Digits UPC-Based Extension - EAN8 : EAN 8 - EAN13 : EAN 13 - UPCA : UPC-A - UPCE : UPC-E - MSI : MSI (Variation of Plessey code) - MSI+ : MSI + CHECKSUM (modulo 11) - POSTNET : POSTNET - PLANET : PLANET - RMS4CC : RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code) - KIX : KIX (Klant index - Customer index) - IMB: Intelligent Mail Barcode - Onecode - USPS-B-3200 (NOTE: requires BCMath PHP extension) - CODABAR : CODABAR - CODE11 : CODE 11 - PHARMA : PHARMACODE - PHARMA2T : PHARMACODE TWO-TRACKS - -4.5.042 (2009-04-15) - - Method Write() was fixed for the strings containing only zero value. - -4.5.041 (2009-04-14) - - Barcode methods were fixed. - -4.5.040 (2009-04-14) - - Method Write() was fixed to handle empty strings. - -4.5.039 (2009-04-11) - - Support for linear barcodes was extended (see example n. 27 and barcodes.php documentation). - -4.5.038 (2009-04-10) - - Write() method was improved to support separators for Japanese, Korean, Chinese Traditional and Chinese Simplified. - -4.5.037 (2009-04-09) - - General performances were improved. - - The signature of the method utf8Bidi() was changed. - - The method UniArrSubString() was added. - - Experimental support for 2D barcodes were added (see example n. 50 and 2dbarcodes.php class). - -4.5.036 (2009-04-03) - - TCPDF methods can be called inside the HTML code (see example n. 49). - - All tag attributes, such as

    must be enclosed within double quotes. - -4.5.035 (2009-03-28) - - Bug #2717436 "writeHTML rowspan problem (continued)" was fixed. - - Bug #2719090 "writeHTML fix follow up" was fixed. - - The method _putuserrights() was changed to avoid Adobe Reader 9.1 crash. This broken the 'trick' that was used to display forms in Acrobat Reader. - -4.5.034 (2009-03-27) - - Bug #2716914 "Bug writeHTML of a table in body and footer related with pb" was fixed. - - Bug #2717056 ] "writeHTML problem when setting tr style" was fixed. - - The signature of the Cell() method was changed. - -4.5.033 (2009-03-27) - - The support for rowspan/colspan on HTML tables was improved (see example n. 48). - -4.5.032 (2009-03-23) - - setPrintFooter(false) bug was fixed. - -4.5.031 (2009-03-20) - - Table header support was extended to multiple pages. - -4.5.030 (2009-03-20) - - thead tag is now supported on HTML tables (header rows are repeated after page breaks). - - The startTransaction() was improved to autocommit. - - List bullets now uses the foreground color (putHtmlListBullet()). - -4.5.029 (2009-03-19) - - The following methods were added to UNDO commands (see example 47): startTransaction(), commitTransaction(), rollbackTransaction(). - - All examples were updated. - -4.5.028 (2009-03-18) - - Bug #2690945 "List Bugs" was fixed. - - HTML text alignment on lists was fixed. - - The constant PDF_FONT_MONOSPACED was added to the configuration file to define the default monospaced font. - - The following methods were fixed: getPageWidth(), getPageHeight(), getBreakMargin(). - - All examples were updated. - -4.5.027 (2009-03-16) - - Method getPageDimensions() was added to get page dimensions. - - The signature of the following methos were changed: getPageWidth(), getPageHeight(), getBreakMargin(). - - _parsepng() method was fixed for PNG URL images (fread bug). - -4.5.026 (2009-03-11) - - Bug #2681793 affecting URL images with spaces was fixed. - -4.5.025 (2009-03-10) - - A small bug affecting hyphenation support was fixed. - - The method SetDefaultMonospacedFont() was added to define the default monospaced font. - -4.5.024 (2009-03-07) - - The bug #2666493 was fixed "Footer corrupts document". - -4.5.023 (2009-03-06) - - The bug #2666688 was fixed "Rowspan in tables". - -4.5.022 (2009-03-05) - - The bug #2659676 was fixed "refer to #2157099 test 4 < BR > problem still not fixed". - - addTOC() function bug was fixed. - -4.5.020 (2009-03-03) - - The following bug was fixed: "function removeSHY corrupts unicode". - -4.5.019 (2009-02-28) - - The problem of decimal separator using different locale was fixed. - - The text hyphenation is now supported (see example n. 46). - -4.5.018 (2009-02-26) - - The _destroy() method was added to unset all class variables and frees memory. - - Now it's possible to call Output() method multiple times. - -4.5.017 (2009-02-24) - - A minor bug that raises a PHP warning was fixed. - -4.5.016 (2009-02-24) - - Bug item #2631200 "getNumLines() counts wrong" was fixed. - - Multiple attachments bug was fixed. - - All class variables are now cleared on Output() for memory otpimization. - -4.5.015 (2009-02-18) - - Bug item #2612553 "function Write() must not break a line on   character" was fixed. - -4.5.014 (2009-02-13) - - Bug item #2595015 "POSTNET Barcode Checksum Error" was fixed (on barcode.php). - - Pagebreak bug for barcode was fixed. - -4.5.013 (2009-02-12) - - border attribute is now supported on HTML images (only accepts the same values accepted by Cell()). - -4.5.012 (2009-02-12) - - An error on image border feature was fixed. - -4.5.011 (2009-02-12) - - HTML links for images are now supported. - - height attribute is now supported on HTML cells. - - $border parameter was added to Image() and ImageEps() methods. - - The method getNumLines() was added to estimate the number of lines required for the specified text. - -4.5.010 (2009-01-29) - - Bug n. 2546108 "BarCode Y position" was fixed. - -4.5.009 (2009-01-26) - - Bug n. 2538094 "Empty pdf file created" was fixed. - -4.5.008 (2009-01-26) - - setPage() method was fixed to correctly restore graphic states. - - Source code was cleaned up for performances. - -4.5.007 (2009-01-24) - - checkPageBreak() and write1DBarcode() methods were fixed. - - Source code was cleaned up for performances. - - barcodes.php was updated. - -4.5.006 (2009-01-23) - - getHTMLUnitToPoints() method was replaced by getHTMLUnitToUnits() to fix HTML units bugs. - -4.5.005 (2009-01-23) - - Page closing bug was fixed. - -4.5.004 (2009-01-21) - - The access of convertHTMLColorToDec() method was changed to public - - Fixed bug on UL tag. - -4.5.003 (2009-01-19) - - Fonts on different folders are now supported. - -4.5.002 (2009-01-07) - - addTOC() function was improved (see example n. 45). - -4.5.001 (2009-01-04) - - The signature of startPageGroup() function was changed. - - Method Footer() was improved to automatically print page or page-group number (see example n. 23). - - Protected method formatTOCPageNumber() was added to customize the format of page numbers on the Table Of Content. - - The signature of addTOC() was changed to include the font used for page numbers. - -4.5.000 (2009-01-03) - - A new $diskcache parameter was added to class constructor to enable disk caching and reduce RAM memory usage (see example n. 43). - - The method movePageTo() was added to move pages to previous positions (see example n. 44). - - The methods getAliasNumPage() and getPageNumGroupAlias() were added to get the alias for page number (needed when using movepageTo()). - - The methods addTOC() was added to print a Table Of Content (see example n. 45). - - Imagick class constant was removed for better compatibility with PHP4. - - All existing examples were updated and new examples were added. - -4.4.009 (2008-12-29) - - Examples 1 and 35 were fixed. - -4.4.008 (2008-12-28) - - Bug #2472169 "Unordered bullet size not adjusted for unit type" was fixed. - -4.4.007 (2008-12-23) - - Bug #2459935 "no unit conversion for header line" was fixed. - - Example n. 42 for image alpha channel was added. - - All examples were updated. - -4.4.006 (2008-12-11) - - Method setLIsymbol() was changed to reflect latest changes in HTML list handling. - -4.4.005 (2008-12-10) - - Bug item #2413870 "ordered list override value" was fixed. - -4.4.004 (2008-12-10) - - The protected method getHTMLUnitToPoints() was added to accept various HTML units of measure (em, ex, px, in, cm, mm, pt, pc, %). - - The method intToRoman() was added to convert integer number to Roman representation. - - Support fot HTML lists was improved: the CSS property list-style-type is now supported. - -4.4.003 (2008-12-09) - - Bug item #2412147 "Warning on line 3367" was fixed. - - Method setHtmlLinksStyle() was added to set default HTML link colors and font style. - - Method addHtmlLink() was changed to use color and style defined on the inline CSS. - -4.4.002 (2008-12-09) - - Borders on Multicell() were fixed. - - Problem of Multicell() on Header function (Bug item #2407579) was fixed. - - Problem on graphics tranformations applied to Multicell() was fixed. - - Support for ImageMagick was added. - - Width calculation for nested tables was fixed. - -4.4.001 (2008-12-08) - - Some missing core fonts were added on fonts directory. - - CID0 fonts rendering was fixed. - - HTML support was improved (

     and  tags are now supported).
    -	- Bug item #2406022 "Left padding bug in MultiCell with maxh" was fixed.
    -
    -4.4.000 (2008-12-07)
    -	- File attachments are now supported (see example n. 41).
    -	- Font functions were optimized to reduce document size.
    -	- makefont.php was updated.
    -	- Linux binaries were added on /fonts/utils
    -	- All fonts were updated.
    -	- $autopadding parameter was added to Multicell() to disable automatic padding features.
    -	- $maxh parameter was added to Multicell() and Write() to set a maximum height.
    -
    -4.3.009 (2008-12-05)
    -	- Bug item #2392989 (Custom header + setlinewidth + cell border bug) was fixed.
    -
    -4.3.008 (2008-12-05)
    -	- Bug item #2390566 "rect bug" was fixed.
    -	- File path was fixed for font embedded files.
    -	- SetFont() method signature was changed to include the font filename.
    -	- Some font-related methods were improved.
    -	- Methods getFontFamily() and getFontStyle() were added.
    -
    -4.3.007 (2008-12-03)
    -	- PNG alpha channel is now supported (GD library is required).
    -	- AddFont() function now support custom font file path on $file parameter.
    -	- The default width variable ($dw) is now always defined for any font.
    -	- The 'Style' attribute on CID-0 fonts was removed because of protection bug.
    -
    -4.3.006 (2008-12-01)
    -	- A regular expression on getHtmlDomArray() to find HTML tags was fixed.
    -
    -4.3.005 (2008-11-25)
    -	- makefont.php was fixed.
    -	- Bug item #2339877 was fixed (false loop condition detected on WriteHTML()).
    -	- Bug item #2336733 was fixed (lasth value update on Multicell() when border and fill are disabled).
    -	- Bug item #2342303 was fixed (automatic page-break on Image() and ImageEPS()).
    -
    -4.3.004 (2008-11-19)
    -	- Function _textstring() was fixed (bug 2309051).
    -	- All examples were updated.
    -
    -4.3.003 (2008-11-18)
    -	- CID-0 font bug was fixed.
    -	- Some functions were optimized.
    -	- Function getGroupPageNoFormatted() was added.
    -	- Example n. 23 was updated.
    -
    -4.3.002 (2008-11-17)
    -	- Bug item #2305518 "CID-0 font don't work with encryption" was fixed.
    -
    -4.3.001 (2008-11-17)
    -	- Bug item #2300007 "download mimetype pdf" was fixed.
    -	- Double quotes were replaced by single quotes to improve PHP performances.
    -	- A bug relative to HTML cell borders was fixed.
    -
    -4.3.000 (2008-11-14)
    -	- The function setOpenCell() was added to set the top/bottom cell sides to be open or closed when the cell cross the page.
    -	- A bug relative to list items indentation was fixed.
    -	- A bug relative to borders on HTML tables and Multicell was fixed.
    -	- A bug relative to rowspanned cells was fixed.
    -	- A bug relative to html images across pages was fixed.
    -
    -4.2.009 (2008-11-13)
    -	- Spaces between li tags are now automatically removed.
    -
    -4.2.008 (2008-11-12)
    -	- A bug relative to fill color on next page was fixed.
    -
    -4.2.007 (2008-11-12)
    -	- The function setListIndentWidth() was added to set custom indentation widht for HTML lists.
    -
    -4.2.006 (2008-11-06)
    -	- A bug relative to HTML justification was fixed.
    -
    -4.2.005 (2008-11-06)
    -	- A bug relative to HTML justification was fixed.
    -	- The methods formatPageNumber() and PageNoFormatted() were added to format page numbers.
    -	- Default Footer() method was changed to use PageNoFormatted() instead of PageNo().
    -	- Example 6 was updated.
    -
    -4.2.004 (2008-11-04)
    -	- Bug item n. 2217039 "filename handling improvement" was fixed.
    -
    -4.2.003 (2008-10-31)
    -	- Font style bug was fixed.
    -
    -4.2.002 (2008-10-31)
    -	- Bug item #2210922 (htm element br not work) was fixed.
    -	- Write() function was improved to support margin changes.
    -
    -4.2.001 (2008-10-30)
    -	- setHtmlVSpace($tagvs) function was added to set custom vertical spaces for HTML tags.
    -	- writeHTML() function now support margin changes during execution.
    -	- Signature of addHTMLVertSpace() function is changed.
    -
    -4.2.000 (2008-10-29)
    -	- htmlcolors.php was changed to support class-loaders.
    -	- ImageEps() function was improved in performances.
    -	- Signature of Link() And Annotation() functions were changed.
    -	- (Bug item #2198926) Links and Annotations alignment were fixed (support for geometric tranformations was added).
    -	- rowspan mode for HTML table cells was improved and fixed.
    -	- Booklet mode for double-sided pages was added; see SetBooklet() function and example n. 40.
    -	- lastPage() signature is changed.
    -	- Signature of Write() function is changed.
    -	- Some HTML justification problems were fixed.
    -	- Some functions were fixed to better support RTL mode.
    -	- Example n. 10 was changed to support RTL mode.
    -	- All examples were updated.
    -
    -4.1.004 (2008-10-23)
    -	- unicode_data.php was changed to support class-loaders.
    -	- Bug item #2186040/2 (writeHTML margin problem) was fixed.
    -
    -4.1.003 (2008-10-22)
    -	- Bug item #2185399 was fixed (rowspan and page break).
    -	- Bugs item #2186040 was fixed (writeHTML margin problem).
    -	- Newline after table was removed.
    -
    -4.1.002 (2008-10-21)
    -	- Bug item #2184525 was fixed (rowspan on HTML cell).
    -
    -4.1.001 (2008-10-21)
    -	- Support for "start" attribute was added to HTML ordered list.
    -	- unicode_data.php file was changed to include UTF-8 to ASCII table.
    -	- Some functions were modified to better support UTF-8 extensions to core fonts.
    -	- Support for images on HTML lists was improved.
    -	- Examples n. 1 and 6 were updated.
    -
    -4.1.000 (2008-10-18)
    -	- Page-break bug using HTML content was fixed.
    -	- The "false" parameter was reintroduced to class_exists function on PHP5 version to avoid autoload.
    -	- addHtmlLink() function was improved to support internal links (i.e.: link to page 23).
    -	- Justification alignment is now supported on HTML (see example n. 39).
    -	- example_006.php was updated.
    -
    -4.0.033 (2008-10-13)
    -	- Bug n. 2157099 was fixed.
    -	- SetX() and SetY() functions were improved.
    -	- SetY() includes a new parameter to avoid the X reset.
    -
    -4.0.032 (2008-10-10)
    -	- Bug n. 2156926 was fixed (bold, italic, underlined, linethrough).
    -	- setStyle() method was removed.
    -	- Configuration file was changed to use helvetica (non-unicode) font by default.
    -	- The use of mixed font types was improved.
    -	- All examples were updated.
    -
    -4.0.031 (2008-10-09)
    -	- _putannots() and _putbookmarks() links alignments were fixed.
    -
    -4.0.030 (2008-10-07)
    -	- _putbookmarks() function was fixed.
    -	- _putannots() was fixed to include internal links.
    -
    -4.0.029 (2008-09-27)
    -	- Infinite loop bug was fixed [Bug item #130309].
    -	- Multicell() problem on Header() was fixed.
    -
    -4.0.028 (2008-09-26)
    -	- setLIsymbol() was added to set the LI symbol used on UL lists.
    -	- Missing $padding and $encryption_key variables declarations were added [Bug item #2129058].
    -
    -4.0.027 (2008-09-19)
    -	- Bug #2118588 "Undefined offset in tcpdf.php on line 9581" was fixed.
    -	- arailunicid0.php font was updated.
    -	- The problem of javascript form fields duplication after saving was fixed.
    -
    -4.0.026 (2008-09-17)
    -	- convertHTMLColorToDec() function was improved to support rgb(RR,GG,BB) notation.
    -	- The following inline CSS attributes are now supported: text-decoration, color, background-color and font-size names: xx-small, x-small, small, medium, large, x-large, xx-large
    -	- Example n. 6 was updated.
    -
    -4.0.025 (2008-09-15)
    -	- _putcidfont0 function was improved to include CJK fonts (Chinese, Japanese, Korean, CJK, Asian fonts) without embedding.
    -	- arialunicid0 font was added (see the new example n. 38).
    -	- The following Unicode to CID-0 tables were added on fonts folder: uni2cid_ak12.php, uni2cid_aj16.php, uni2cid_ag15.php, uni2cid_ac15.php.
    -
    -4.0.024 (2008-09-12)
    -	- "stripos" function was replaced with "strpos + strtolower" for backward compatibility with PHP4.
    -	- support for Spot Colors were added. Check the new example n. 37 and the following new functions:
    -		AddSpotColor()
    -		SetDrawSpotColor()
    -		SetFillSpotColor()
    -		SetTextSpotColor()
    -		_putspotcolors()
    -	- Bookmark() function was improved to fix wrong levels.
    -	- $lasth changes after header/footer calls were fixed.
    -
    -4.0.023 (2008-09-05)
    -	- Some HTML related problems were fixed.
    -	- Image alignment on HTML was changed, now it always defaults to the normal mode (see example_006.php).
    -
    -4.0.022 (2008-08-28)
    -	- Line height on HTML was fixed.
    -	- Image inside an HTML cell problem was fixed.
    -	- A new "zarbold" persian font was added.
    -
    -4.0.021 (2008-08-24)
    -	- HTTP headers were fixed on Output function().
    -	- getAliasNbPages() and getPageGroupAlias() functions were changed to support non-unicode fonts on unicode documents.
    -	- Function Write() was fixed.
    -	- The problem of additional vertical spaces on HTML was fixed.
    -	- The problem of frame around HTML links was fixed.
    -
    -4.0.020 (2008-08-15)
    -	- "[2052259] WriteHTML  & " bug was fixed.
    -
    -4.0.019 (2008-08-13)
    -	- "Rowspan on first cell" bug was fixed.
    -
    -4.0.018 (2008-08-08)
    -	- Default cellpadding for HTML tables was fixed.
    -	- Annotation() function was added to support some PDF annotations (see example_036.php and section 8.4 of PDF reference 1.7).
    -	- HTML links are now correclty shifted during line alignments.
    -	- function getAliasNbPages() was added and Footer() was updated.
    -	- RowSpan mode for HTML tables was fixed.
    -	- Bugs item #2043610 "Multiple sizes vertical align wrong" was fixed.
    -	- ImageEPS() function was improved and RTL alignment was fixed (see example_032.php).
    -
    -4.0.017 (2008-08-05)
    -	- Missing CNZ and CEO style modes were added to Rect() function.
    -	- Fonts utils were updated to include support for OpenType fonts.
    -	- getLastH() function was added.
    -
    -4.0.016 (2008-07-30)
    -	- setPageMark() function was added. This function must be called after calling Image() function for a background image.
    -
    -4.0.015 (2008-07-29)
    -	- Some functions were changed to support different page formats (see example_028.php).
    -	- The signature of setPage() function is changed.
    -
    -4.0.014 (2008-07-29)
    -	- K_PATH_MAIN calculation on tcpdf_config.php was fixed.
    -	- HTML support for EPS/AI images was added (see example_006.php).
    -	- Bugs item #2030807 "Truncated text on multipage html fields" was fixed.
    -	- PDF header bug was fixed.
    -	- helvetica was added as default font family.
    -	- Stroke mode was fixed on Text function.
    -	- several minor bugs were fixed.
    -
    -4.0.013 (2008-07-27)
    -	- Bugs item #2027799 " Big spaces between lines after page break" was fixed.
    -	- K_PATH_MAIN calculation on tcpdf_config.php was changed.
    -	- Function setVisibility() was fixed to avoid the "Incorrect PDEObject type" error message.
    -
    -4.0.012 (2008-07-24)
    -	- Addpage(), Header() and Footer() functions were changed to simplify the implementation of external header/footer functions.
    -	- The following functions were added:
    -			setHeader()
    -			setFooter()
    -			getImageRBX()
    -			getImageRBY()
    -			getCellHeightRatio()
    -			getHeaderFont()
    -			getFooterFont()
    -			getRTL()
    -			getBarcode()
    -			getHeaderData()
    -			getHeaderMargin()
    -			getFooterMargin()
    -
    -4.0.011 (2008-07-23)
    -	- Font support was improved.
    -	- The folder /fonts/utils contains new utilities and instructions for embedd font files.
    -	- Documentation was updated.
    -
    -4.0.010 (2008-07-22)
    -	- HTML tables were fixed to work across pages.
    -	- Header() and Footer() functions were updated to preserve previous settings.
    -	- example_035.php was added.
    -
    -4.0.009 (2008-07-21)
    -	- UTF8StringToArray() function was fixed for non-unicode mode.
    -
    -4.0.008 (2008-07-21)
    -	- Barcodes alignment was fixed (see example_027.php).
    -	- unicode_data.php was updated.
    -	- Arabic shaping for "Zero-Width Non-Joiner" character (U+200C) was fixed.
    -
    -4.0.007 (2008-07-18)
    -	- str_split was replaced by preg_split for compatibility with PHP4 version.
    -	- Clipping mode was added to all graphic functions by using parameter $style = "CNZ" or "CEO" (see example_034.php).
    -
    -4.0.006 (2008-07-16)
    -	- HTML rowspan bug was fixed.
    -	- Line style for MultiCell() was fixed.
    -	- WriteHTML() function was improved.
    -	- CODE128C barcode was fixed (barcodes.php).
    -
    -4.0.005 (2008-07-11)
    -	- Bug [2015715] "PHP Error/Warning" was fixed.
    -
    -4.0.004 (2008-07-09)
    -	- HTML cell internal padding was fixed.
    -
    -4.0.003 (2008-07-08)
    -	- Removed URL encoding when F option is selected on Output() function.
    -	- fixed some minor bugs in html tables.
    -
    -4.0.002 (2008-07-07)
    -	- Bug [2000861] was still unfixed and has been fixed.
    -
    -4.0.001 (2008-07-05)
    -	- Bug [2000861] was fixed.
    -
    -4.0.000 (2008-07-03)
    -	- THIS IS A MAIN RELEASE THAT INCLUDES SEVERAL NEW FEATURES AND BUGFIXES
    -	- Signature fo SetTextColor() and SetFillColor() functions was changed (parameter $storeprev was removed).
    -	- HTML support was completely rewritten and improved (see example 6).
    -	- Alignments parameters were fixed.
    -	- Functions GetArrStringWidth() and GetStringWidth() now include font parameters.
    -	- Fonts support was improved.
    -	- All core fonts were replaced and moved to fonts/ directory.
    -	- The following functions were added: getMargins(), getFontSize(), getFontSizePt().
    -	- File config/tcpdf_config_old.php was renamed tcpdf_config_alt.php and updated.
    -	- Multicell and WriteHTMLCell fill function was fixed.
    -	- Several minor bugs were fixed.
    -	- barcodes.php was updated.
    -	- All examples were updated.
    -
    -------------------------------------------------------------
    -
    -3.1.001 (2008-06-13)
    -	- Bug [1992515] "K_PATH_FONTS default value wrong" was fixed.
    -	- Vera font was removed, DejaVu font and Free fonts were updated.
    -	- Image handling was improved.
    -	- All examples were updated.
    -
    -3.1.000 (2008-06-11)
    -	- setPDFVersion() was added to change the default PDF version (currently 1.7).
    -	- setViewerPreferences() was added to control the way the document is to be presented on the screen or printed (see example 29).
    -	- SetDisplayMode() signature was changed (new options were added).
    -	- LinearGradient(), RadialGradient(), CoonsPatchMesh() functions were added to print various color gradients (see example 30).
    -	- PieSector() function was added to render render pie charts (see example 31).
    -	- ImageEps() was added to display EPS and AI images with limited support (see example 32).
    -	- writeBarcode() function is now depracated, a new write1DBarcode() function was added. The barcode directory was removed and a new barcodes.php file was added.
    -	- The new write1DBarcode() function support more barcodes and do not need the GD library (see example 027). All barcodes are directly written to PDF using graphic functions.
    -	- HTML lists were improved and could be nested (you may now represent trees).
    -	- AddFont() bug was fixed.
    -	- _putfonts() bug was fixed.
    -	- graphics functions were fixed.
    -	- unicode_data.php file was updated (fixed).
    -	- almohanad font was updated.
    -	- example 18 was updated (Farsi and Arabic languages).
    -	- source code cleanup.
    -	- All examples were updated and new examples were added.
    -
    -3.0.015 (2008-06-06)
    -	- AddPage() function signature is changed to include page format.
    -	- example 28 was added to show page format changes.
    -	- setPageUnit() function was added to change the page units of measure.
    -	- setPageFormat() function was added to change the page format and orientation between pages.
    -	- setPageOrientation() function was added to change the page orientation.
    -	- Arabic font shaping was fixed for laa letter and square boxes (see the example 18).
    -
    -3.0.014 (2008-06-04)
    -	- Arabic font shaping was fixed.
    -	- setDefaultTableColumns() function was added.
    -	- $cell_height_ratio variable was added.
    -	- setCellHeightRatio() function was added to define the default height of cell repect font height.
    -
    -3.0.013 (2008-06-03)
    -	- Multicell height parameter was fixed.
    -	- Arabic font shaping was improved.
    -	- unicode_data.php was updated.
    -
    -3.0.012 (2008-05-30)
    -	- K_PATH_MAIN and K_PATH_URL constants are now automatically set on config file.
    -	- DOCUMENT_ROOT constant was fixed for IIS Webserver (config file was updated).
    -	- Arabic font shaping was improved.
    -	- TranslateY() function was fixed (bug [1977962]).
    -	- setVisibility() function was fixed.
    -	- writeBarcode() function was fixed to scale using $xref parameter.
    -	- All examples were updated.
    -
    -3.0.011 (2008-05-23)
    -	- CMYK color support was added to all graphic functions.
    -	- HTML table support was improved:
    -	  -- now it's possible to include additional html tags inside a cell;
    -	  -- colspan attribute was added.
    -	- example 006 was updated.
    -
    -3.0.010 (2008-05-21)
    -	- fixed $laa_array inclusion on utf8Bidi() function.
    -
    -3.0.009 (2008-05-20)
    -	- unicode_data.php was updated.
    -	- Arabic laa letter problem was fixed.
    -
    -3.0.008 (2008-05-12)
    -	- Arabic support was fixed and improved (unicode_data.php was updated).
    -	- Polycurve() function was added to draw a poly-Bezier curve.
    -	- list items alignment was fixed.
    -	- example 6 was updated.
    -
    -3.0.007 (2008-05-06)
    -	- Arabic support was fixed and improved.
    -	- AlMohanad (arabic) font was added.
    -	- C128 barcode bugs were fixed.
    -
    -3.0.006 (2008-04-21)
    -	- Condition to check negative width values was added.
    -
    -3.0.005 (2008-04-18)
    -	- back-Slash character escape was fixed on writeHTML() function.
    -	- Exampe 6 was updated.
    -
    -3.0.004 (2008-04-11)
    -	- Bug [1939304] (Right to Left Issue) was fixed.
    -
    -3.0.003 (2008-04-07)
    -	- Bug [1934523](Words between HTML tags in cell not kept on one line) was fixed.
    -	- "face" attribute of "font" tag is now fully supported.
    -
    -3.0.002 (2008-04-01)
    -	- Write() functions now return the number of cells and not the number of lines.
    -	- TCPDF is released under LGPL 2.1, or any later version.
    -
    -3.0.001 (2008-05-28)
    -	- _legacyparsejpeg() and _legacyparsepng() were renamed _parsejpeg() and _parsepng().
    -	- function writeBarcode() was fixed.
    -	- all examples were updated.
    -	- example 27 was added to show various barcodes.
    -
    -3.0.000 (2008-03-27)
    -	- private function pixelsToMillimeters() was changed to public function pixelsToUnits() to fix html image size bug.
    -	- Image-related functions were rewritten.
    -	- resize parameter was added to Image() signature to reduce the image size and fit width and height (see example 9).
    -	- TCPDF now supports all images supported by GD library: GD, GD2, GD2PART, GIF, JPEG, PNG, BMP, XBM, XPM.
    -	- CMYK support was added to SetDrawColor(), SetFillColor(), SetTextColor() (see example 22).
    -	- Page Groups were added (see example 23).
    -	- setVisibility() function was added to restrict the rendering of some elements to screen or printout (see example 24).
    -	- All private variables and functions were changed to protected.
    -	- setAlpha() function was added to give transparency support for all objects (see example 25).
    -	- Clipping and stroke modes were added to Text() function (see example 26).
    -	- All examples were moved to "examples" directory.
    -	- function setJPEGQuality() was added to set the JPEG image comrpession (see example 9).
    -
    -2.9.000 (2008-03-26)
    -	- htmlcolors.php file was added to include html colors.
    -	- Support for HTML color names and three-digit hexadecimal color codes was added.
    -	- private function convertColorHexToDec() was renamed convertHTMLColorToDec().
    -	- color and bgcolor attributes are now supported on all HTML tags (color nesting is also supported).
    -	- Write() function were fixed.
    -	- example_006.php was updated.
    -	- private function setUserRights() was added to release user rights on Acrobat Reader (this allows to display forms, see example 14)
    -
    -2.8.000 (2008-03-20)
    -	- Private variables were changed to protected.
    -	- Function Write() was fixed and improved.
    -	- Support for dl, dt, dd, del HTML tags was introduced.
    -	- Line-trought mode was added for HTML and text.
    -	- Text vertical alignment on cells were fixed.
    -	- Examples were updated to reflect changes.
    -
    -2.7.002 (2008-03-13)
    -	- Bug "[1912142] Encrypted PDF created/modified date" was fixed.
    -
    -2.7.001 (2008-03-10)
    -	- Cell justification was fixed for non-unicode mode.
    -
    -2.7.000 (2008-03-09)
    -	- Cell() stretching mode 4 (forced character spacing) was fixed.
    -	- writeHTMLCell() now uses Multicell() to write.
    -	- Multicell() has a new parameter $ishtml to act as writeHTMLCell().
    -	- Write() speed was improved for non-arabic strings.
    -	- Example n. 20 was changed.
    -
    -2.6.000 (2008-03-07)
    -	- various alignments bugs were fixed.
    -
    -2.5.000 (2008-03-07)
    -	- Several bugs were fixed.
    -	- example_019.php was added to test non-unicode mode using old fonts.
    -
    -2.4.000 (2008-03-06)
    -	- RTL support was deeply improved.
    -	- GetStringWidth() was fixed to support RTL languages.
    -	- Text() RTL alignment was fixed.
    -	- Some functions were added: GetArrStringWidth(), GetCharWidth(), uniord(), utf8Bidi().
    -	- example_018.php was added and test_unicode.php was removed.
    -
    -2.3.000 (2008-03-05)
    -	- MultiCell() signature is changed. Now support multiple columns across pages (see example_017).
    -	- Write() signature is changed. Now support the cell mode to be used with MultiCell.
    -	- Header() and Footer() were changed.
    -	- The following functions were added: UTF8ArrSubString() and unichr().
    -	- Examples were updated to reflect last changes.
    -
    -2.2.004 (2008-03-04)
    -	- Several examples were added.
    -	- AddPage() Header() and Footer() were fixed.
    -	- Documentation is now available on http://www.tcpdf.org
    -
    -2.2.003 (2008-03-03)
    -	- [1894853] Performance of MultiCell() was improved.
    -	- RadioButton and ListBox functions were added.
    -	- javascript form functions were rewritten and properties names are changed. The properties function supported by form fields are listed on Possible values are listed on http://www.adobe.com/devnet/acrobat/pdfs/js_developer_guide.pdf.
    -
    -2.2.002 (2008-02-28)
    -	- [1900495] html images path was fixed.
    -	- Legacy image functions were reintroduced to allow PNG and JPEG support without GD library.
    -
    -2.2.001 (2008-02-16)
    -	- The bug "[1894700] bug with replace relative path" was fixed
    -	- Justification was fixed
    -
    -2.2.000 (2008-02-12)
    -	- fixed javascript bug introduced with latest release
    -
    -2.1.002 (2008-02-12)
    -	- Justify function was fixed on PHP4 version.
    -	- Bookmank function was added ([1578250] Table of contents).
    -	- Javascript and Form fields support was added ([1796359] Form fields).
    -
    -2.1.001 (2008-02-10)
    -	- The bug "[1885776] Race Condition in function justitfy" was fixed.
    -	- The bug "[1890217] xpdf complains that pdf is incorrect" was fixed.
    -
    -2.1.000 (2008-01-07)
    -	- FPDF_FONTPATH constant was changed to K_PATH_FONTS on config file
    -	- Bidirectional Algorithm to correctly reverse bidirectional languages was added.
    -	- SetLeftMargin, SetTopMargin, SetRightMargin functions were fixed.
    -	- SetCellPadding function was added.
    -	- writeHTML was updated with new parameters.
    -	- Text function was fixed.
    -	- MultiCell function was fixed, now works also across multiple pages.
    -	- Line width was fixed on Header and Footer functions and 
    tag. - - "GetImageSize" was renamed "getimagesize". - - Document version was changed from 1.3 to 1.5. - - _begindoc() function was fixed. - - ChangeDate was fixed and ModDate was added. - - The following functions were added: - setPage() : Move pointer to the specified document page. - getPage() : Get current document page number. - lastpage() : Reset pointer to the last document page. - getNumPages() : Get the total number of inserted pages. - GetNumChars() : count the number of (UTF-8) characters in a string. - - $stretch parameter was added to Cell() function to fit text on cell: - 0 = disabled - 1 = horizontal scaling only if necessary - 2 = forced horizontal scaling - 3 = character spacing only if necessary - 4 = forced character spacing - - Line function was fixed for RTL. - - Graphic transformation functions were added [1811158]: - StartTransform() - StopTransform() - ScaleX() - ScaleY() - ScaleXY() - Scale() - MirrorH() - MirrorV() - MirrorP() - MirrorL() - TranslateX() - TranslateY() - Translate() - Rotate() - SkewX() - SkewY() - Skew() - - Graphic function were added/updated [1688549]: - SetLineStyle() - _outPoint() - _outLine() - _outRect() - _outCurve() - Line() - Rect() - Curve - Ellipse - Circle - Polygon - RegularPolygon - -2.0.000 (2008-01-04) - - RTL (Right-To-Left) languages support was added. Language direction is set using the $l['a_meta_dir'] setting on /configure/language/xxx.php language files. - - setRTL($enable) method was added to manually enable/disable the RTL text direction. - - The attribute "dir" was added to support custom text direction on HTML tags. Possible values are: ltr - for Left-To-Right and RTL for Right-To-Left. - - RC4 40bit encryption was added. Check the SetProtection method. - - [1815213] Improved image support for GIF, JPEG, PNG formats. - - [1800094] Attribute "value" was added to ordered list items
  • . - - Image function now has a new "align" parameter that indicates the alignment of the pointer next to image insertion and relative to image height. The value can be: - T: top-right for LTR or top-left for RTL - M: middle-right for LTR or middle-left for RTL - B: bottom-right for LTR or bottom-left for RTL - N: next line - - Attribute "align" was added to html tag to set the above image "align" parameter. Possible values are: - top: top-right for LTR or top-left for RTL - middle: middle-right for LTR or middle-left for RTL - bottom: bottom-right for LTR or bottom-left for RTL - - [1798103] newline was added after , and

    tages. - - [1816393] Documentation was updated. - - 'ln' parameter was fixed on writeHTMLCell. Now it's possible to print two or more columns across several pages; - - The method lastPage() was added to move the pointer on the last page; - ------------------------------------------------------------- - -1.53.0.TC034 (2007-07-30) - - fixed htmlentities conversion. - - MultiCell() function returns the number of cells. - -1.53.0.TC033 (2007-07-30) - - fixed bug 1762550: case sensitive for font files - - NOTE: all fonts files names must be in lowercase! - -1.53.0.TC032 (2007-07-27) - - setLastH method was added to resolve bug 1689071. - - all fonts names were converted in lowercase (bug 1713005). - - bug 1740954 was fixed. - - justification was added as Cell option. - -1.53.0.TC031 (2007-03-20) - - ToUnicode CMap were added on _puttruetypeunicode function. Now you may search and copy unicode text. - -1.53.0.TC030 (2007-03-06) - - fixed bug on PHP4 version. - -1.53.0.TC029 (2007-03-06) - - DejaVu Fonts were added. - -1.53.0.TC028 (2007-03-03) - - MultiCell function signature were changed: the $ln parameter were added. Check documentation for further information. - - Greek language were added on example sentences. - - setPrintHeader() and setPrintFooter() functions were added to enable or disable page header and footer. - -1.53.0.TC027 (2006-12-14) - - $attr['face'] bug were fixed. - - K_TCPDF_EXTERNAL_CONFIG control where introduced on /config/tcpdf_config.php to use external configuration files. - -1.53.0.TC026 (2006-10-28) - - writeHTML function call were fixed on examples. - -1.53.0.TC025 (2006-10-27) - - Bugs item #1421290 were fixed (0D - 0A substitution in some characters) - - Bugs item #1573174 were fixed (MultiCell documentation) - -1.53.0.TC024 (2006-09-26) - - getPageHeight() function were fixed (bug 1543476). - - fixed missing breaks on closedHTMLTagHandler function (bug 1535263). - - fixed extra spaces on Write function (bug 1535262). - -1.53.0.TC023 (2006-08-04) - - paths to barcode directory were fixed. - - documentation were updated. - -1.53.0.TC022 (2006-07-16) - - fixed bug: [ 1516858 ] Probs with PHP autoloader and class_exists() - -1.53.0.TC021 (2006-07-01) - - HTML attributes with whitespaces are now supported (thanks to Nelson Benitez for his support) - -1.53.0.TC020 (2006-06-23) - - code cleanup - -1.53.0.TC019 (2006-05-21) - - fixed and closing tags - -1.53.0.TC018 (2006-05-18) - - fixed font names bug - -1.53.0.TC017 (2006-05-18) - - the TTF2UFM utility to convert True Type fonts for TCPDF were included on fonts folder. - - new free unicode fonts were included on /fonts/freefont. - - test_unicode.php example were exended. - - parameter $fill were added on Write, writeHTML and writeHTMLCell functions. - - documentation were updated. - -1.53.0.TC016 (2006-03-09) - - fixed closing tag on html parser. - -1.53.0.TC016 (2005-08-28) - - fpdf.php and tcpdf.php files were joined in one single class (you can still extend TCPDF with your own class). - - fixed problem when mb_internal_encoding is set. - -1.53.0.TC014 (2005-05-29) - - fixed WriteHTMLCell new page issue. - -1.53.0.TC013 (2005-05-29) - - fixed WriteHTMLCell across pages. - -1.53.0.TC012 (2005-05-29) - - font color attribute bug were fixed. - -1.53.0.TC011 (2005-03-31) - - SetFont function were fixed (thank Sjaak Lauwers for bug notice). - -1.53.0.TC010 (2005-03-22) - - the html functions were improved (thanks to Manfred Vervuert for bug reporting). - -1.53.0.TC009 (2005-03-19) - - a wrong reference to convertColorHexToDec were fixed. - -1.53.0.TC008 (2005-02-07) - - removed some extra bytes from PHP files. - -1.53.0.TC007 (2005-01-08) - - fill attribute were removed from writeHTMLCell method. - -1.53.0.TC006 (2005-01-08) - - the documentation were updated. - -1.53.0.TC005 (2005-01-05) - - Steven Wittens's unicode methods were removed. - - All unicode methods were rewritten from scratch. - - TCPDF is now licensed as LGPL. - -1.53.0.TC004 (2005-01-04) - - this changelog were added. - - removed commercial fonts for licensing issue. - - Bitstream Vera Fonts were added (http://www.bitstream.com/font_rendering/products/dev_fonts/vera.html). - - Now the AddFont and SetFont functions returns the basic font if the styled version do not exist. - -EOF -------------------------------------------------------- diff --git a/lib/combodo/tcpdf/LICENSE.TXT b/lib/combodo/tcpdf/LICENSE.TXT deleted file mode 100644 index 49147d01a..000000000 --- a/lib/combodo/tcpdf/LICENSE.TXT +++ /dev/null @@ -1,860 +0,0 @@ -********************************************************************** -* TCPDF LICENSE -********************************************************************** - - TCPDF is free software: you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - 2002-2019 Nicola Asuni - Tecnick.com LTD - -********************************************************************** -********************************************************************** - - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. - -********************************************************************** -********************************************************************** - - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. - -********************************************************************** -********************************************************************** diff --git a/lib/combodo/tcpdf/README.md b/lib/combodo/tcpdf/README.md deleted file mode 100644 index 0fb94009b..000000000 --- a/lib/combodo/tcpdf/README.md +++ /dev/null @@ -1,84 +0,0 @@ -# TCPDF -*PHP PDF Library* - -[![Donate via PayPal](https://img.shields.io/badge/donate-paypal-87ceeb.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations¤cy_code=GBP&business=paypal@tecnick.com&item_name=donation%20for%20TCPDF%20project) -*Please consider supporting this project by making a donation via [PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_donations¤cy_code=GBP&business=paypal@tecnick.com&item_name=donation%20for%20TCPDF%20project)* - -* **category** Library -* **author** Nicola Asuni -* **copyright** 2002-2021 Nicola Asuni - Tecnick.com LTD -* **license** http://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE.TXT) -* **link** http://www.tcpdf.org -* **source** https://github.com/tecnickcom/TCPDF - - -## IMPORTANT -A new version of this library is under development at https://github.com/tecnickcom/tc-lib-pdf and as a consequence this version will not receive any additional development or support. -This version should be considered obsolete, new projects should use the new version as soon it will become stable. - - - -## Description - -PHP library for generating PDF documents on-the-fly. - -### Main Features: -* no external libraries are required for the basic functions; -* all standard page formats, custom page formats, custom margins and units of measure; -* UTF-8 Unicode and Right-To-Left languages; -* TrueTypeUnicode, OpenTypeUnicode v1, TrueType, OpenType v1, Type1 and CID-0 fonts; -* font subsetting; -* methods to publish some XHTML + CSS code, Javascript and Forms; -* images, graphic (geometric figures) and transformation methods; -* supports JPEG, PNG and SVG images natively, all images supported by GD (GD, GD2, GD2PART, GIF, JPEG, PNG, BMP, XBM, XPM) and all images supported via ImagMagick (http://www.imagemagick.org/script/formats.php) -* 1D and 2D barcodes: CODE 39, ANSI MH10.8M-1983, USD-3, 3 of 9, CODE 93, USS-93, Standard 2 of 5, Interleaved 2 of 5, CODE 128 A/B/C, 2 and 5 Digits UPC-Based Extension, EAN 8, EAN 13, UPC-A, UPC-E, MSI, POSTNET, PLANET, RMS4CC (Royal Mail 4-state Customer Code), CBC (Customer Bar Code), KIX (Klant index - Customer index), Intelligent Mail Barcode, Onecode, USPS-B-3200, CODABAR, CODE 11, PHARMACODE, PHARMACODE TWO-TRACKS, Datamatrix, QR-Code, PDF417; -* JPEG and PNG ICC profiles, Grayscale, RGB, CMYK, Spot Colors and Transparencies; -* automatic page header and footer management; -* document encryption up to 256 bit and digital signature certifications; -* transactions to UNDO commands; -* PDF annotations, including links, text and file attachments; -* text rendering modes (fill, stroke and clipping); -* multiple columns mode; -* no-write page regions; -* bookmarks, named destinations and table of content; -* text hyphenation; -* text stretching and spacing (tracking); -* automatic page break, line break and text alignments including justification; -* automatic page numbering and page groups; -* move and delete pages; -* page compression (requires php-zlib extension); -* XOBject Templates; -* Layers and object visibility. -* PDF/A-1b support. - -### Third party fonts: - -This library may include third party font files released with different licenses. - -All the PHP files on the fonts directory are subject to the general TCPDF license (GNU-LGPLv3), -they do not contain any binary data but just a description of the general properties of a particular font. -These files can be also generated on the fly using the font utilities and TCPDF methods. - -All the original binary TTF font files have been renamed for compatibility with TCPDF and compressed using the gzcompress PHP function that uses the ZLIB data format (.z files). - -The binary files (.z) that begins with the prefix "free" have been extracted from the GNU FreeFont collection (GNU-GPLv3). -The binary files (.z) that begins with the prefix "pdfa" have been derived from the GNU FreeFont, so they are subject to the same license. -For the details of Copyright, License and other information, please check the files inside the directory fonts/freefont-20120503 -Link : http://www.gnu.org/software/freefont/ - -The binary files (.z) that begins with the prefix "dejavu" have been extracted from the DejaVu fonts 2.33 (Bitstream) collection. -For the details of Copyright, License and other information, please check the files inside the directory fonts/dejavu-fonts-ttf-2.33 -Link : http://dejavu-fonts.org - -The binary files (.z) that begins with the prefix "ae" have been extracted from the Arabeyes.org collection (GNU-GPLv2). -Link : http://projects.arabeyes.org/ - -### ICC profile: - -TCPDF includes the sRGB.icc profile from the icc-profiles-free Debian package: -https://packages.debian.org/source/stable/icc-profiles-free - - -## Developer(s) Contact - -* Nicola Asuni diff --git a/lib/combodo/tcpdf/VERSION b/lib/combodo/tcpdf/VERSION deleted file mode 100644 index 49df80bfe..000000000 --- a/lib/combodo/tcpdf/VERSION +++ /dev/null @@ -1 +0,0 @@ -6.4.4 diff --git a/lib/combodo/tcpdf/composer.json b/lib/combodo/tcpdf/composer.json deleted file mode 100644 index b53dd6e7f..000000000 --- a/lib/combodo/tcpdf/composer.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "name": "combodo/tcpdf", - "replace": { - "tecnickcom/tcpdf": "self.version" - }, - "type": "library", - "description": "TCPDF is a PHP class for generating PDF documents and barcodes.", - "keywords": [ - "PDF", - "tcpdf", - "PDFD32000-2008", - "qrcode", - "datamatrix", - "pdf417", - "barcodes" - ], - "homepage": "https://github.com/combodo-itop-libs/TCPDF", - "version": "6.4.4", - "license": "LGPL-3.0-only", - "authors": [ - { - "name": "Nicola Asuni", - "email": "info@tecnick.com", - "role": "lead" - }, - { - "name": "Combodo", - "email": "contact@combodo.com" - } - ], - "require": { - "php": ">=5.3.0" - }, - "autoload": { - "classmap": [ - "config", - "include", - "tcpdf.php", - "tcpdf_parser.php", - "tcpdf_import.php", - "tcpdf_barcodes_1d.php", - "tcpdf_barcodes_2d.php", - "include/tcpdf_colors.php", - "include/tcpdf_filters.php", - "include/tcpdf_font_data.php", - "include/tcpdf_fonts.php", - "include/tcpdf_images.php", - "include/tcpdf_static.php", - "include/barcodes/datamatrix.php", - "include/barcodes/pdf417.php", - "include/barcodes/qrcode.php" - ] - } -} diff --git a/lib/combodo/tcpdf/config/tcpdf_config.php b/lib/combodo/tcpdf/config/tcpdf_config.php deleted file mode 100644 index 92317b121..000000000 --- a/lib/combodo/tcpdf/config/tcpdf_config.php +++ /dev/null @@ -1,227 +0,0 @@ -. -// -// See LICENSE.TXT file for more information. -//============================================================+ - -/** - * Configuration file for TCPDF. - * @author Nicola Asuni - * @package com.tecnick.tcpdf - * @version 4.9.005 - * @since 2004-10-27 - */ - -// IMPORTANT: -// If you define the constant K_TCPDF_EXTERNAL_CONFIG, all the following settings will be ignored. -// If you use the tcpdf_autoconfig.php, then you can overwrite some values here. - - -/** - * Installation path (/var/www/tcpdf/). - * By default it is automatically calculated but you can also set it as a fixed string to improve performances. - */ -//define ('K_PATH_MAIN', ''); - -/** - * URL path to tcpdf installation folder (http://localhost/tcpdf/). - * By default it is automatically set but you can also set it as a fixed string to improve performances. - */ -//define ('K_PATH_URL', ''); - -/** - * Path for PDF fonts. - * By default it is automatically set but you can also set it as a fixed string to improve performances. - */ -//define ('K_PATH_FONTS', K_PATH_MAIN.'fonts/'); - -/** - * Default images directory. - * By default it is automatically set but you can also set it as a fixed string to improve performances. - */ -//define ('K_PATH_IMAGES', ''); - -/** - * Deafult image logo used be the default Header() method. - * Please set here your own logo or an empty string to disable it. - */ -//define ('PDF_HEADER_LOGO', ''); - -/** - * Header logo image width in user units. - */ -//define ('PDF_HEADER_LOGO_WIDTH', 0); - -/** - * Cache directory for temporary files (full path). - */ -//define ('K_PATH_CACHE', '/tmp/'); - -/** - * Generic name for a blank image. - */ -define ('K_BLANK_IMAGE', '_blank.png'); - -/** - * Page format. - */ -define ('PDF_PAGE_FORMAT', 'A4'); - -/** - * Page orientation (P=portrait, L=landscape). - */ -define ('PDF_PAGE_ORIENTATION', 'P'); - -/** - * Document creator. - */ -define ('PDF_CREATOR', 'TCPDF'); - -/** - * Document author. - */ -define ('PDF_AUTHOR', 'TCPDF'); - -/** - * Header title. - */ -define ('PDF_HEADER_TITLE', 'TCPDF Example'); - -/** - * Header description string. - */ -define ('PDF_HEADER_STRING', "by Nicola Asuni - Tecnick.com\nwww.tcpdf.org"); - -/** - * Document unit of measure [pt=point, mm=millimeter, cm=centimeter, in=inch]. - */ -define ('PDF_UNIT', 'mm'); - -/** - * Header margin. - */ -define ('PDF_MARGIN_HEADER', 5); - -/** - * Footer margin. - */ -define ('PDF_MARGIN_FOOTER', 10); - -/** - * Top margin. - */ -define ('PDF_MARGIN_TOP', 27); - -/** - * Bottom margin. - */ -define ('PDF_MARGIN_BOTTOM', 25); - -/** - * Left margin. - */ -define ('PDF_MARGIN_LEFT', 15); - -/** - * Right margin. - */ -define ('PDF_MARGIN_RIGHT', 15); - -/** - * Default main font name. - */ -define ('PDF_FONT_NAME_MAIN', 'helvetica'); - -/** - * Default main font size. - */ -define ('PDF_FONT_SIZE_MAIN', 10); - -/** - * Default data font name. - */ -define ('PDF_FONT_NAME_DATA', 'helvetica'); - -/** - * Default data font size. - */ -define ('PDF_FONT_SIZE_DATA', 8); - -/** - * Default monospaced font name. - */ -define ('PDF_FONT_MONOSPACED', 'courier'); - -/** - * Ratio used to adjust the conversion of pixels to user units. - */ -define ('PDF_IMAGE_SCALE_RATIO', 1.25); - -/** - * Magnification factor for titles. - */ -define('HEAD_MAGNIFICATION', 1.1); - -/** - * Height of cell respect font height. - */ -define('K_CELL_HEIGHT_RATIO', 1.25); - -/** - * Title magnification respect main font size. - */ -define('K_TITLE_MAGNIFICATION', 1.3); - -/** - * Reduction factor for small font. - */ -define('K_SMALL_RATIO', 2/3); - -/** - * Set to true to enable the special procedure used to avoid the overlappind of symbols on Thai language. - */ -define('K_THAI_TOPCHARS', true); - -/** - * If true allows to call TCPDF methods using HTML syntax - * IMPORTANT: For security reason, disable this feature if you are printing user HTML content. - */ -define('K_TCPDF_CALLS_IN_HTML', false); - -/** - * If true and PHP version is greater than 5, then the Error() method throw new exception instead of terminating the execution. - */ -define('K_TCPDF_THROW_EXCEPTION_ERROR', false); - -/** - * Default timezone for datetime functions - */ -define('K_TIMEZONE', 'UTC'); - -//============================================================+ -// END OF FILE -//============================================================+ diff --git a/lib/combodo/tcpdf/fonts/courier.php b/lib/combodo/tcpdf/fonts/courier.php deleted file mode 100644 index e935b6768..000000000 --- a/lib/combodo/tcpdf/fonts/courier.php +++ /dev/null @@ -1,12 +0,0 @@ -33,'FontBBox'=>'[-23 -250 715 805]','ItalicAngle'=>0,'Ascent'=>805,'Descent'=>-250,'Leading'=>0,'CapHeight'=>562,'XHeight'=>426,'StemV'=>51,'StemH'=>51,'AvgWidth'=>600,'MaxWidth'=>600,'MissingWidth'=>600); -$cw=array(0=>600,1=>600,2=>600,3=>600,4=>600,5=>600,6=>600,7=>600,8=>600,9=>600,10=>600,11=>600,12=>600,13=>600,14=>600,15=>600,16=>600,17=>600,18=>600,19=>600,20=>600,21=>600,22=>600,23=>600,24=>600,25=>600,26=>600,27=>600,28=>600,29=>600,30=>600,31=>600,32=>600,33=>600,34=>600,35=>600,36=>600,37=>600,38=>600,39=>600,40=>600,41=>600,42=>600,43=>600,44=>600,45=>600,46=>600,47=>600,48=>600,49=>600,50=>600,51=>600,52=>600,53=>600,54=>600,55=>600,56=>600,57=>600,58=>600,59=>600,60=>600,61=>600,62=>600,63=>600,64=>600,65=>600,66=>600,67=>600,68=>600,69=>600,70=>600,71=>600,72=>600,73=>600,74=>600,75=>600,76=>600,77=>600,78=>600,79=>600,80=>600,81=>600,82=>600,83=>600,84=>600,85=>600,86=>600,87=>600,88=>600,89=>600,90=>600,91=>600,92=>600,93=>600,94=>600,95=>600,96=>600,97=>600,98=>600,99=>600,100=>600,101=>600,102=>600,103=>600,104=>600,105=>600,106=>600,107=>600,108=>600,109=>600,110=>600,111=>600,112=>600,113=>600,114=>600,115=>600,116=>600,117=>600,118=>600,119=>600,120=>600,121=>600,122=>600,123=>600,124=>600,125=>600,126=>600,127=>600,128=>600,129=>600,130=>600,131=>600,132=>600,133=>600,134=>600,135=>600,136=>600,137=>600,138=>600,139=>600,140=>600,141=>600,142=>600,143=>600,144=>600,145=>600,146=>600,147=>600,148=>600,149=>600,150=>600,151=>600,152=>600,153=>600,154=>600,155=>600,156=>600,157=>600,158=>600,159=>600,160=>600,161=>600,162=>600,163=>600,164=>600,165=>600,166=>600,167=>600,168=>600,169=>600,170=>600,171=>600,172=>600,173=>600,174=>600,175=>600,176=>600,177=>600,178=>600,179=>600,180=>600,181=>600,182=>600,183=>600,184=>600,185=>600,186=>600,187=>600,188=>600,189=>600,190=>600,191=>600,192=>600,193=>600,194=>600,195=>600,196=>600,197=>600,198=>600,199=>600,200=>600,201=>600,202=>600,203=>600,204=>600,205=>600,206=>600,207=>600,208=>600,209=>600,210=>600,211=>600,212=>600,213=>600,214=>600,215=>600,216=>600,217=>600,218=>600,219=>600,220=>600,221=>600,222=>600,223=>600,224=>600,225=>600,226=>600,227=>600,228=>600,229=>600,230=>600,231=>600,232=>600,233=>600,234=>600,235=>600,236=>600,237=>600,238=>600,239=>600,240=>600,241=>600,242=>600,243=>600,244=>600,245=>600,246=>600,247=>600,248=>600,249=>600,250=>600,251=>600,252=>600,253=>600,254=>600,255=>600); -// --- EOF --- diff --git a/lib/combodo/tcpdf/fonts/courierb.php b/lib/combodo/tcpdf/fonts/courierb.php deleted file mode 100644 index acb01b0d6..000000000 --- a/lib/combodo/tcpdf/fonts/courierb.php +++ /dev/null @@ -1,12 +0,0 @@ -33,'FontBBox'=>'[-113 -250 749 801]','ItalicAngle'=>0,'Ascent'=>801,'Descent'=>-250,'Leading'=>0,'CapHeight'=>562,'XHeight'=>439,'StemV'=>106,'StemH'=>84,'AvgWidth'=>600,'MaxWidth'=>600,'MissingWidth'=>600); -$cw=array(0=>600,1=>600,2=>600,3=>600,4=>600,5=>600,6=>600,7=>600,8=>600,9=>600,10=>600,11=>600,12=>600,13=>600,14=>600,15=>600,16=>600,17=>600,18=>600,19=>600,20=>600,21=>600,22=>600,23=>600,24=>600,25=>600,26=>600,27=>600,28=>600,29=>600,30=>600,31=>600,32=>600,33=>600,34=>600,35=>600,36=>600,37=>600,38=>600,39=>600,40=>600,41=>600,42=>600,43=>600,44=>600,45=>600,46=>600,47=>600,48=>600,49=>600,50=>600,51=>600,52=>600,53=>600,54=>600,55=>600,56=>600,57=>600,58=>600,59=>600,60=>600,61=>600,62=>600,63=>600,64=>600,65=>600,66=>600,67=>600,68=>600,69=>600,70=>600,71=>600,72=>600,73=>600,74=>600,75=>600,76=>600,77=>600,78=>600,79=>600,80=>600,81=>600,82=>600,83=>600,84=>600,85=>600,86=>600,87=>600,88=>600,89=>600,90=>600,91=>600,92=>600,93=>600,94=>600,95=>600,96=>600,97=>600,98=>600,99=>600,100=>600,101=>600,102=>600,103=>600,104=>600,105=>600,106=>600,107=>600,108=>600,109=>600,110=>600,111=>600,112=>600,113=>600,114=>600,115=>600,116=>600,117=>600,118=>600,119=>600,120=>600,121=>600,122=>600,123=>600,124=>600,125=>600,126=>600,127=>600,128=>600,129=>600,130=>600,131=>600,132=>600,133=>600,134=>600,135=>600,136=>600,137=>600,138=>600,139=>600,140=>600,141=>600,142=>600,143=>600,144=>600,145=>600,146=>600,147=>600,148=>600,149=>600,150=>600,151=>600,152=>600,153=>600,154=>600,155=>600,156=>600,157=>600,158=>600,159=>600,160=>600,161=>600,162=>600,163=>600,164=>600,165=>600,166=>600,167=>600,168=>600,169=>600,170=>600,171=>600,172=>600,173=>600,174=>600,175=>600,176=>600,177=>600,178=>600,179=>600,180=>600,181=>600,182=>600,183=>600,184=>600,185=>600,186=>600,187=>600,188=>600,189=>600,190=>600,191=>600,192=>600,193=>600,194=>600,195=>600,196=>600,197=>600,198=>600,199=>600,200=>600,201=>600,202=>600,203=>600,204=>600,205=>600,206=>600,207=>600,208=>600,209=>600,210=>600,211=>600,212=>600,213=>600,214=>600,215=>600,216=>600,217=>600,218=>600,219=>600,220=>600,221=>600,222=>600,223=>600,224=>600,225=>600,226=>600,227=>600,228=>600,229=>600,230=>600,231=>600,232=>600,233=>600,234=>600,235=>600,236=>600,237=>600,238=>600,239=>600,240=>600,241=>600,242=>600,243=>600,244=>600,245=>600,246=>600,247=>600,248=>600,249=>600,250=>600,251=>600,252=>600,253=>600,254=>600,255=>600); -// --- EOF --- diff --git a/lib/combodo/tcpdf/fonts/courierbi.php b/lib/combodo/tcpdf/fonts/courierbi.php deleted file mode 100644 index 631c623e9..000000000 --- a/lib/combodo/tcpdf/fonts/courierbi.php +++ /dev/null @@ -1,12 +0,0 @@ -97,'FontBBox'=>'[-57 -250 869 801]','ItalicAngle'=>-12,'Ascent'=>801,'Descent'=>-250,'Leading'=>0,'CapHeight'=>562,'XHeight'=>439,'StemV'=>106,'StemH'=>84,'AvgWidth'=>600,'MaxWidth'=>600,'MissingWidth'=>600); -$cw=array(0=>600,1=>600,2=>600,3=>600,4=>600,5=>600,6=>600,7=>600,8=>600,9=>600,10=>600,11=>600,12=>600,13=>600,14=>600,15=>600,16=>600,17=>600,18=>600,19=>600,20=>600,21=>600,22=>600,23=>600,24=>600,25=>600,26=>600,27=>600,28=>600,29=>600,30=>600,31=>600,32=>600,33=>600,34=>600,35=>600,36=>600,37=>600,38=>600,39=>600,40=>600,41=>600,42=>600,43=>600,44=>600,45=>600,46=>600,47=>600,48=>600,49=>600,50=>600,51=>600,52=>600,53=>600,54=>600,55=>600,56=>600,57=>600,58=>600,59=>600,60=>600,61=>600,62=>600,63=>600,64=>600,65=>600,66=>600,67=>600,68=>600,69=>600,70=>600,71=>600,72=>600,73=>600,74=>600,75=>600,76=>600,77=>600,78=>600,79=>600,80=>600,81=>600,82=>600,83=>600,84=>600,85=>600,86=>600,87=>600,88=>600,89=>600,90=>600,91=>600,92=>600,93=>600,94=>600,95=>600,96=>600,97=>600,98=>600,99=>600,100=>600,101=>600,102=>600,103=>600,104=>600,105=>600,106=>600,107=>600,108=>600,109=>600,110=>600,111=>600,112=>600,113=>600,114=>600,115=>600,116=>600,117=>600,118=>600,119=>600,120=>600,121=>600,122=>600,123=>600,124=>600,125=>600,126=>600,127=>600,128=>600,129=>600,130=>600,131=>600,132=>600,133=>600,134=>600,135=>600,136=>600,137=>600,138=>600,139=>600,140=>600,141=>600,142=>600,143=>600,144=>600,145=>600,146=>600,147=>600,148=>600,149=>600,150=>600,151=>600,152=>600,153=>600,154=>600,155=>600,156=>600,157=>600,158=>600,159=>600,160=>600,161=>600,162=>600,163=>600,164=>600,165=>600,166=>600,167=>600,168=>600,169=>600,170=>600,171=>600,172=>600,173=>600,174=>600,175=>600,176=>600,177=>600,178=>600,179=>600,180=>600,181=>600,182=>600,183=>600,184=>600,185=>600,186=>600,187=>600,188=>600,189=>600,190=>600,191=>600,192=>600,193=>600,194=>600,195=>600,196=>600,197=>600,198=>600,199=>600,200=>600,201=>600,202=>600,203=>600,204=>600,205=>600,206=>600,207=>600,208=>600,209=>600,210=>600,211=>600,212=>600,213=>600,214=>600,215=>600,216=>600,217=>600,218=>600,219=>600,220=>600,221=>600,222=>600,223=>600,224=>600,225=>600,226=>600,227=>600,228=>600,229=>600,230=>600,231=>600,232=>600,233=>600,234=>600,235=>600,236=>600,237=>600,238=>600,239=>600,240=>600,241=>600,242=>600,243=>600,244=>600,245=>600,246=>600,247=>600,248=>600,249=>600,250=>600,251=>600,252=>600,253=>600,254=>600,255=>600); -// --- EOF --- diff --git a/lib/combodo/tcpdf/fonts/courieri.php b/lib/combodo/tcpdf/fonts/courieri.php deleted file mode 100644 index 5ae725d4a..000000000 --- a/lib/combodo/tcpdf/fonts/courieri.php +++ /dev/null @@ -1,12 +0,0 @@ -97,'FontBBox'=>'[-27 -250 849 805]','ItalicAngle'=>-12,'Ascent'=>805,'Descent'=>-250,'Leading'=>0,'CapHeight'=>562,'XHeight'=>426,'StemV'=>51,'StemH'=>51,'AvgWidth'=>600,'MaxWidth'=>600,'MissingWidth'=>600); -$cw=array(0=>600,1=>600,2=>600,3=>600,4=>600,5=>600,6=>600,7=>600,8=>600,9=>600,10=>600,11=>600,12=>600,13=>600,14=>600,15=>600,16=>600,17=>600,18=>600,19=>600,20=>600,21=>600,22=>600,23=>600,24=>600,25=>600,26=>600,27=>600,28=>600,29=>600,30=>600,31=>600,32=>600,33=>600,34=>600,35=>600,36=>600,37=>600,38=>600,39=>600,40=>600,41=>600,42=>600,43=>600,44=>600,45=>600,46=>600,47=>600,48=>600,49=>600,50=>600,51=>600,52=>600,53=>600,54=>600,55=>600,56=>600,57=>600,58=>600,59=>600,60=>600,61=>600,62=>600,63=>600,64=>600,65=>600,66=>600,67=>600,68=>600,69=>600,70=>600,71=>600,72=>600,73=>600,74=>600,75=>600,76=>600,77=>600,78=>600,79=>600,80=>600,81=>600,82=>600,83=>600,84=>600,85=>600,86=>600,87=>600,88=>600,89=>600,90=>600,91=>600,92=>600,93=>600,94=>600,95=>600,96=>600,97=>600,98=>600,99=>600,100=>600,101=>600,102=>600,103=>600,104=>600,105=>600,106=>600,107=>600,108=>600,109=>600,110=>600,111=>600,112=>600,113=>600,114=>600,115=>600,116=>600,117=>600,118=>600,119=>600,120=>600,121=>600,122=>600,123=>600,124=>600,125=>600,126=>600,127=>600,128=>600,129=>600,130=>600,131=>600,132=>600,133=>600,134=>600,135=>600,136=>600,137=>600,138=>600,139=>600,140=>600,141=>600,142=>600,143=>600,144=>600,145=>600,146=>600,147=>600,148=>600,149=>600,150=>600,151=>600,152=>600,153=>600,154=>600,155=>600,156=>600,157=>600,158=>600,159=>600,160=>600,161=>600,162=>600,163=>600,164=>600,165=>600,166=>600,167=>600,168=>600,169=>600,170=>600,171=>600,172=>600,173=>600,174=>600,175=>600,176=>600,177=>600,178=>600,179=>600,180=>600,181=>600,182=>600,183=>600,184=>600,185=>600,186=>600,187=>600,188=>600,189=>600,190=>600,191=>600,192=>600,193=>600,194=>600,195=>600,196=>600,197=>600,198=>600,199=>600,200=>600,201=>600,202=>600,203=>600,204=>600,205=>600,206=>600,207=>600,208=>600,209=>600,210=>600,211=>600,212=>600,213=>600,214=>600,215=>600,216=>600,217=>600,218=>600,219=>600,220=>600,221=>600,222=>600,223=>600,224=>600,225=>600,226=>600,227=>600,228=>600,229=>600,230=>600,231=>600,232=>600,233=>600,234=>600,235=>600,236=>600,237=>600,238=>600,239=>600,240=>600,241=>600,242=>600,243=>600,244=>600,245=>600,246=>600,247=>600,248=>600,249=>600,250=>600,251=>600,252=>600,253=>600,254=>600,255=>600); -// --- EOF --- diff --git a/lib/combodo/tcpdf/fonts/dejavusans.ctg.z b/lib/combodo/tcpdf/fonts/dejavusans.ctg.z deleted file mode 100644 index df25b6497f084274a55feb158bb478f237137568..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10454 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 diff --git a/lib/combodo/tcpdf/fonts/dejavusans.php b/lib/combodo/tcpdf/fonts/dejavusans.php deleted file mode 100644 index 72147beec..000000000 --- a/lib/combodo/tcpdf/fonts/dejavusans.php +++ /dev/null @@ -1,16 +0,0 @@ -32,'FontBBox'=>'[-1021 -415 1681 1167]','ItalicAngle'=>0,'Ascent'=>928,'Descent'=>-236,'Leading'=>0,'CapHeight'=>729,'XHeight'=>547,'StemV'=>34,'StemH'=>15,'AvgWidth'=>507,'MaxWidth'=>1735,'MissingWidth'=>600); -$cbbox=array(0=>array(50,-177,550,705),33=>array(151,0,250,729),34=>array(96,458,364,729),35=>array(77,0,761,718),36=>array(83,-147,553,760),37=>array(55,-14,895,742),38=>array(63,-14,749,742),39=>array(96,458,179,729),40=>array(86,-132,310,759),41=>array(80,-132,304,759),42=>array(30,286,470,742),43=>array(106,0,732,627),44=>array(77,-116,220,124),45=>array(49,234,312,314),46=>array(107,0,210,124),47=>array(0,-93,337,729),48=>array(66,-14,570,742),49=>array(110,0,544,729),50=>array(73,0,536,742),51=>array(76,-14,556,742),52=>array(49,0,580,729),53=>array(77,-14,549,729),54=>array(70,-14,573,742),55=>array(82,0,551,729),56=>array(68,-14,568,742),57=>array(63,-14,566,742),58=>array(117,0,220,517),59=>array(77,-116,220,517),60=>array(106,46,732,581),61=>array(106,172,732,454),62=>array(106,46,732,581),63=>array(72,0,461,742),64=>array(66,-174,930,704),65=>array(8,0,676,729),66=>array(98,0,615,729),67=>array(56,-14,644,742),68=>array(98,0,711,729),69=>array(98,0,568,729),70=>array(98,0,517,729),71=>array(56,-14,693,742),72=>array(98,0,654,729),73=>array(98,0,197,729),74=>array(-52,-200,197,729),75=>array(98,0,677,729),76=>array(98,0,552,729),77=>array(98,0,765,729),78=>array(98,0,650,729),79=>array(56,-14,731,742),80=>array(98,0,569,729),81=>array(56,-129,731,742),82=>array(98,0,666,729),83=>array(66,-14,579,742),84=>array(-3,0,614,729),85=>array(87,-14,645,729),86=>array(8,0,676,729),87=>array(33,0,956,729),88=>array(30,0,654,729),89=>array(-2,0,613,729),90=>array(45,0,640,729),91=>array(86,-132,293,760),92=>array(0,-93,337,729),93=>array(97,-132,304,760),94=>array(106,457,732,729),95=>array(-10,-236,510,-166),96=>array(83,617,317,800),97=>array(60,-14,522,560),98=>array(91,-14,580,760),99=>array(55,-14,488,560),100=>array(55,-14,544,760),101=>array(55,-14,562,560),102=>array(23,0,371,760),103=>array(55,-208,544,560),104=>array(91,0,549,760),105=>array(94,0,184,760),106=>array(-18,-208,184,760),107=>array(91,0,576,760),108=>array(94,0,184,760),109=>array(91,0,889,560),110=>array(91,0,549,560),111=>array(55,-14,557,560),112=>array(91,-208,580,560),113=>array(55,-208,544,560),114=>array(91,0,411,560),115=>array(54,-14,472,560),116=>array(27,0,368,702),117=>array(85,-14,543,560),118=>array(30,0,562,547),119=>array(42,0,776,547),120=>array(29,0,559,547),121=>array(30,-208,562,547),122=>array(43,0,482,547),123=>array(125,-163,511,760),124=>array(127,-236,210,764),125=>array(125,-163,511,760),126=>array(106,228,732,399),161=>array(151,0,250,729),162=>array(84,-153,517,699),163=>array(63,0,548,742),164=>array(46,40,592,587),165=>array(40,0,595,729),166=>array(127,-171,210,699),167=>array(45,-95,454,742),168=>array(105,659,395,758),169=>array(138,0,862,725),170=>array(56,229,404,742),171=>array(77,69,518,517),172=>array(106,140,732,421),173=>array(49,234,312,314),174=>array(138,0,862,725),175=>array(104,673,396,745),176=>array(95,432,405,742),177=>array(106,0,732,627),178=>array(46,326,338,742),179=>array(48,319,350,742),180=>array(181,616,415,800),181=>array(85,-208,612,547),182=>array(77,-96,528,729),183=>array(107,285,210,409),184=>array(142,-193,344,0),185=>array(67,326,346,734),186=>array(47,229,424,742),187=>array(94,69,535,517),188=>array(67,-14,937,742),189=>array(67,-14,906,742),190=>array(48,-14,937,742),191=>array(70,-14,459,729),192=>array(8,0,676,927),193=>array(8,0,676,927),194=>array(8,0,676,928),195=>array(8,0,676,921),196=>array(8,0,676,913),197=>array(8,0,676,928),198=>array(4,0,910,729),199=>array(56,-193,644,742),200=>array(98,0,568,927),201=>array(98,0,568,927),202=>array(98,0,568,928),203=>array(98,0,568,913),204=>array(29,0,216,927),205=>array(79,0,265,927),206=>array(-1,0,297,928),207=>array(3,0,293,913),208=>array(5,0,716,729),209=>array(98,0,650,921),210=>array(56,-14,731,927),211=>array(56,-14,731,927),212=>array(56,-14,731,928),213=>array(56,-14,731,921),214=>array(56,-14,731,913),215=>array(137,31,701,596),216=>array(50,-34,737,761),217=>array(87,-14,645,927),218=>array(87,-14,645,927),219=>array(87,-14,645,928),220=>array(87,-14,645,913),221=>array(-2,0,613,927),222=>array(98,0,569,729),223=>array(91,-14,584,760),224=>array(60,-14,522,800),225=>array(60,-14,522,800),226=>array(60,-14,522,800),227=>array(60,-14,522,777),228=>array(60,-14,522,758),229=>array(60,-14,522,878),230=>array(60,-14,929,560),231=>array(55,-193,488,560),232=>array(55,-14,562,800),233=>array(55,-14,562,800),234=>array(55,-14,562,800),235=>array(55,-14,562,758),236=>array(-28,0,206,800),237=>array(70,0,304,800),238=>array(-17,0,295,800),239=>array(-6,0,284,758),240=>array(55,-14,557,760),241=>array(91,0,549,777),242=>array(55,-14,557,800),243=>array(55,-14,557,800),244=>array(55,-14,557,800),245=>array(55,-14,557,777),246=>array(55,-14,557,758),247=>array(106,73,732,554),248=>array(35,-46,576,592),249=>array(85,-14,543,800),250=>array(85,-14,543,800),251=>array(85,-14,543,800),252=>array(85,-14,543,758),253=>array(30,-208,562,800),254=>array(91,-208,580,760),255=>array(30,-208,562,758),256=>array(8,0,676,899),257=>array(60,-14,522,745),258=>array(8,0,676,946),259=>array(60,-14,522,765),260=>array(8,-193,706,729),261=>array(60,-193,563,560),262=>array(56,-14,644,927),263=>array(55,-14,488,800),264=>array(56,-14,644,928),265=>array(55,-14,488,800),266=>array(56,-14,644,914),267=>array(55,-14,488,760),268=>array(56,-14,644,928),269=>array(55,-14,488,800),270=>array(98,0,711,928),271=>array(55,-14,732,760),272=>array(5,0,716,729),273=>array(55,-14,619,760),274=>array(98,0,568,900),275=>array(55,-14,562,745),276=>array(98,0,568,928),277=>array(55,-14,562,785),278=>array(98,0,568,914),279=>array(55,-14,562,760),280=>array(98,-193,569,729),281=>array(55,-193,562,560),282=>array(98,0,568,925),283=>array(55,-14,562,797),284=>array(56,-14,693,928),285=>array(55,-208,544,800),286=>array(56,-14,693,928),287=>array(55,-208,544,785),288=>array(56,-14,693,914),289=>array(55,-208,544,760),290=>array(56,-250,693,742),291=>array(55,-208,544,775),292=>array(98,0,654,928),293=>array(-13,0,549,928),294=>array(98,0,818,729),295=>array(59,0,578,760),296=>array(-14,0,309,921),297=>array(-22,0,300,777),298=>array(1,0,293,899),299=>array(-7,0,285,745),300=>array(-5,0,300,928),301=>array(-14,0,292,785),302=>array(86,-193,268,729),303=>array(73,-193,255,760),304=>array(98,0,198,914),305=>array(94,0,184,560),306=>array(98,-200,492,729),307=>array(94,-208,461,760),308=>array(-52,-200,296,928),309=>array(-18,-208,295,800),310=>array(98,-235,677,729),311=>array(91,-235,576,760),312=>array(91,0,576,547),313=>array(98,0,552,928),314=>array(94,0,286,928),315=>array(98,-235,552,729),316=>array(66,-235,209,760),317=>array(98,0,552,729),318=>array(94,0,375,760),319=>array(98,0,552,729),320=>array(94,0,314,760),321=>array(-7,0,557,729),322=>array(1,0,285,760),323=>array(98,0,650,928),324=>array(91,0,549,803),325=>array(98,-235,650,729),326=>array(91,-235,549,560),327=>array(98,0,650,921),328=>array(91,0,549,800),329=>array(100,0,715,729),330=>array(98,-208,637,742),331=>array(91,-208,549,560),332=>array(56,-14,731,899),333=>array(55,-14,557,745),334=>array(56,-14,731,928),335=>array(55,-14,557,785),336=>array(56,-14,731,927),337=>array(55,-14,557,800),338=>array(56,0,1006,729),339=>array(55,-14,970,560),340=>array(98,0,666,928),341=>array(91,0,447,803),342=>array(98,-235,666,729),343=>array(63,-235,411,560),344=>array(98,0,666,921),345=>array(91,0,419,800),346=>array(66,-14,579,928),347=>array(54,-14,472,803),348=>array(66,-14,579,928),349=>array(54,-14,472,800),350=>array(66,-193,579,742),351=>array(54,-193,472,560),352=>array(66,-14,579,928),353=>array(54,-14,472,800),354=>array(-3,-193,614,729),355=>array(27,-193,368,702),356=>array(-3,0,614,921),357=>array(27,0,374,813),358=>array(-3,0,614,729),359=>array(27,0,368,702),360=>array(87,-14,645,921),361=>array(85,-14,543,777),362=>array(87,-14,645,899),363=>array(85,-14,543,745),364=>array(87,-14,645,928),365=>array(85,-14,543,785),366=>array(87,-14,645,929),367=>array(85,-14,543,849),368=>array(87,-14,645,927),369=>array(85,-14,546,800),370=>array(87,-193,645,729),371=>array(85,-193,613,560),372=>array(33,0,956,932),373=>array(42,0,776,803),374=>array(-2,0,613,932),375=>array(30,-208,562,803),376=>array(-2,0,613,913),377=>array(45,0,640,928),378=>array(43,0,482,803),379=>array(45,0,640,914),380=>array(43,0,482,760),381=>array(45,0,640,928),382=>array(43,0,482,800),383=>array(23,0,371,760),384=>array(16,-14,580,760),385=>array(-51,0,664,729),386=>array(98,0,615,729),387=>array(91,-14,580,760),388=>array(0,0,615,729),389=>array(0,-14,580,760),390=>array(56,-14,644,742),391=>array(56,-14,794,924),392=>array(55,-14,600,760),393=>array(5,0,716,729),394=>array(-51,0,760,729),395=>array(98,0,615,729),396=>array(55,-14,544,760),397=>array(55,-208,557,548),398=>array(64,0,534,729),399=>array(57,-14,731,742),400=>array(80,-14,560,742),401=>array(-52,-200,517,729),402=>array(-63,-208,371,760),403=>array(56,-14,824,924),404=>array(4,-210,683,729),405=>array(91,0,910,760),406=>array(98,0,347,729),407=>array(5,0,290,729),408=>array(98,0,746,742),409=>array(90,0,576,760),410=>array(5,0,271,760),411=>array(30,0,562,760),412=>array(87,-14,894,729),413=>array(-52,-200,650,729),414=>array(91,-208,549,560),415=>array(56,-14,731,742),416=>array(50,-14,764,760),417=>array(58,-14,603,615),418=>array(56,-14,851,742),419=>array(55,-208,668,560),420=>array(-51,0,618,729),421=>array(90,-208,580,760),422=>array(98,-129,666,729),423=>array(56,-14,569,742),424=>array(49,-14,467,560),425=>array(98,0,568,729),426=>array(-132,-208,355,760),427=>array(27,-208,368,702),428=>array(12,0,614,729),429=>array(27,0,368,760),430=>array(-3,-200,614,729),431=>array(84,-4,796,760),432=>array(86,-14,676,615),433=>array(38,-14,726,724),434=>array(98,-15,683,729),435=>array(-2,0,742,742),436=>array(30,-208,730,560),437=>array(45,0,640,729),438=>array(43,0,482,547),439=>array(78,-31,621,729),440=>array(45,-31,588,729),441=>array(51,-213,531,547),442=>array(55,-208,488,547),443=>array(73,0,536,742),444=>array(45,-31,622,729),445=>array(51,-213,531,547),446=>array(43,-14,456,702),447=>array(91,-208,580,560),448=>array(98,-208,197,729),449=>array(98,-208,394,729),450=>array(10,-208,451,729),451=>array(98,0,197,729),452=>array(98,0,1352,928),453=>array(98,0,1211,800),454=>array(55,-14,1071,800),455=>array(98,-200,768,729),456=>array(98,-208,733,760),457=>array(94,-208,367,760),458=>array(98,-200,868,729),459=>array(98,-208,839,760),460=>array(91,-208,733,760),461=>array(8,0,676,928),462=>array(60,-14,522,800),463=>array(-1,0,297,928),464=>array(-16,0,296,800),465=>array(56,-14,731,928),466=>array(55,-14,557,800),467=>array(87,-14,645,928),468=>array(85,-14,543,800),469=>array(87,-14,645,1025),470=>array(85,-14,543,899),471=>array(87,-14,645,1044),472=>array(85,-14,543,892),473=>array(87,-14,645,1044),474=>array(85,-14,543,892),475=>array(87,-14,645,1047),476=>array(85,-14,543,892),477=>array(55,-14,562,560),478=>array(8,0,676,1025),479=>array(60,-14,522,899),480=>array(8,0,676,1025),481=>array(60,-14,522,869),482=>array(4,0,910,900),483=>array(60,-14,929,743),484=>array(56,-14,752,742),485=>array(55,-208,622,560),486=>array(56,-14,693,928),487=>array(55,-208,544,798),488=>array(98,0,677,928),489=>array(-11,0,576,928),490=>array(56,-193,731,742),491=>array(55,-193,557,560),492=>array(56,-193,731,899),493=>array(55,-193,557,745),494=>array(78,-31,621,928),495=>array(43,-213,523,800),496=>array(-18,-208,299,800),497=>array(98,0,1352,729),498=>array(98,0,1211,729),499=>array(55,-14,1071,760),500=>array(56,-14,693,928),501=>array(55,-208,544,798),502=>array(98,-14,1022,729),503=>array(98,-208,626,742),504=>array(98,0,650,927),505=>array(91,0,549,799),506=>array(8,0,676,931),507=>array(60,-14,607,931),508=>array(4,0,910,928),509=>array(60,-14,929,798),510=>array(50,-34,737,928),511=>array(35,-46,576,798),512=>array(8,0,676,930),513=>array(60,-14,522,799),514=>array(8,0,676,901),515=>array(60,-14,522,785),516=>array(98,0,568,930),517=>array(55,-14,562,798),518=>array(98,0,568,901),519=>array(55,-14,562,785),520=>array(-43,0,306,930),521=>array(-30,0,313,798),522=>array(2,0,308,901),523=>array(-14,0,292,785),524=>array(56,-14,731,930),525=>array(55,-14,557,799),526=>array(56,-14,731,901),527=>array(55,-14,557,785),528=>array(97,0,666,930),529=>array(63,0,411,798),530=>array(98,0,666,901),531=>array(91,0,421,785),532=>array(87,-14,645,930),533=>array(85,-14,543,799),534=>array(87,-14,645,901),535=>array(85,-14,543,785),536=>array(66,-240,579,742),537=>array(54,-240,472,560),538=>array(-3,-240,614,729),539=>array(27,-240,368,702),540=>array(76,-210,556,742),541=>array(35,-211,467,560),542=>array(98,0,654,928),543=>array(-8,0,549,928),544=>array(98,-208,637,742),545=>array(55,-70,783,760),546=>array(55,-14,643,742),547=>array(55,-14,555,632),548=>array(45,-208,640,729),549=>array(43,-208,482,547),550=>array(8,0,676,914),551=>array(60,-14,522,760),552=>array(98,-193,568,729),553=>array(55,-193,562,560),554=>array(56,-14,731,1025),555=>array(55,-14,557,899),556=>array(56,-14,731,1025),557=>array(55,-14,557,864),558=>array(56,-14,731,914),559=>array(55,-14,557,760),560=>array(56,-14,731,1025),561=>array(55,-14,557,899),562=>array(-2,0,613,899),563=>array(30,-208,562,745),564=>array(67,-70,420,757),565=>array(91,-70,788,560),566=>array(27,-70,422,702),567=>array(-18,-208,184,547),568=>array(55,-14,943,760),569=>array(55,-208,943,560),570=>array(-1,-34,686,761),571=>array(6,-34,692,761),572=>array(4,-46,545,592),573=>array(5,0,552,729),574=>array(-38,-34,649,761),575=>array(54,-242,512,560),576=>array(43,-242,525,547),577=>array(39,0,569,729),578=>array(39,0,445,560),579=>array(5,0,615,729),580=>array(6,-14,726,729),581=>array(8,0,676,729),582=>array(98,-93,568,822),583=>array(55,-93,562,640),584=>array(-52,-200,290,729),585=>array(-18,-208,264,760),586=>array(56,-200,836,743),587=>array(55,-208,656,560),588=>array(5,0,666,729),589=>array(7,0,411,560),590=>array(-5,0,615,729),591=>array(5,-208,588,547),592=>array(85,-14,547,560),593=>array(55,-14,544,560),594=>array(91,-14,580,560),595=>array(91,-14,580,760),596=>array(62,-14,495,560),597=>array(55,-69,488,560),598=>array(55,-208,656,760),599=>array(55,-14,715,760),600=>array(55,-14,562,560),601=>array(55,-14,562,560),602=>array(61,-14,814,560),603=>array(65,-14,473,561),604=>array(65,-14,473,561),605=>array(65,-14,771,561),606=>array(55,-14,596,561),607=>array(-18,-208,264,547),608=>array(55,-208,715,760),609=>array(55,-208,544,547),610=>array(55,-14,539,560),611=>array(47,-210,549,547),612=>array(47,-14,549,547),613=>array(85,-208,543,547),614=>array(91,0,549,760),615=>array(91,-208,549,760),616=>array(7,0,265,760),617=>array(81,0,304,547),618=>array(57,0,314,547),619=>array(37,0,359,760),620=>array(38,0,416,760),621=>array(94,-208,296,760),622=>array(94,-213,651,760),623=>array(91,-13,889,548),624=>array(91,-208,889,548),625=>array(91,-208,889,560),626=>array(-18,-208,552,560),627=>array(91,-208,661,560),628=>array(87,0,549,547),629=>array(55,-14,557,560),630=>array(55,0,768,547),631=>array(72,-18,655,561),632=>array(55,-208,602,760),633=>array(0,-13,320,547),634=>array(0,-13,320,755),635=>array(0,-208,433,547),636=>array(91,-207,411,560),637=>array(91,-208,411,560),638=>array(64,0,437,560),639=>array(57,0,437,560),640=>array(91,0,574,547),641=>array(91,0,574,547),642=>array(54,-208,472,560),643=>array(-19,-208,355,760),644=>array(-19,-208,355,760),645=>array(27,-208,401,549),646=>array(-132,-208,355,760),647=>array(27,-156,368,546),648=>array(27,-208,370,702),649=>array(0,-14,634,547),650=>array(55,-15,564,547),651=>array(94,0,545,548),652=>array(30,0,562,547),653=>array(42,0,776,547),654=>array(30,0,562,760),655=>array(50,0,552,547),656=>array(43,-208,593,547),657=>array(43,-54,482,547),658=>array(43,-213,523,547),659=>array(53,-213,553,547),660=>array(43,0,456,759),661=>array(43,0,456,759),662=>array(43,0,456,759),663=>array(43,-213,456,760),664=>array(56,-14,731,742),665=>array(91,0,530,547),666=>array(55,-14,596,561),667=>array(55,-14,724,760),668=>array(91,0,563,547),669=>array(-132,-208,272,760),670=>array(91,-213,576,547),671=>array(91,0,493,547),672=>array(55,-208,746,759),673=>array(43,0,456,759),674=>array(43,0,456,759),675=>array(55,-14,970,760),676=>array(55,-213,1014,760),677=>array(55,-54,970,760),678=>array(27,0,781,702),679=>array(27,-208,629,760),680=>array(27,-70,723,702),681=>array(23,-208,804,760),682=>array(94,0,657,760),683=>array(94,0,610,760),684=>array(26,-15,489,640),685=>array(26,84,489,640),686=>array(0,-214,570,760),687=>array(0,-208,683,760),688=>array(57,326,346,751),689=>array(57,326,346,751),690=>array(-11,209,116,751),691=>array(57,326,259,640),692=>array(35,319,236,632),693=>array(35,209,307,632),694=>array(16,326,320,632),695=>array(26,326,489,632),696=>array(19,209,354,632),697=>array(78,557,203,800),698=>array(78,557,384,800),699=>array(85,489,228,729),700=>array(87,499,230,729),701=>array(96,616,239,856),702=>array(57,492,191,760),703=>array(57,492,191,760),704=>array(57,326,317,751),705=>array(57,326,317,751),706=>array(130,524,370,836),707=>array(130,524,370,836),708=>array(94,561,406,800),709=>array(94,561,406,800),710=>array(94,616,406,800),711=>array(94,616,406,800),712=>array(104,488,171,759),713=>array(104,673,396,745),714=>array(181,616,415,800),715=>array(83,617,317,800),716=>array(104,-148,171,123),717=>array(104,-156,396,-84),718=>array(83,-236,317,-54),719=>array(181,-236,415,-53),720=>array(54,0,229,517),721=>array(54,356,229,517),722=>array(57,249,191,517),723=>array(57,249,191,517),724=>array(140,229,360,448),725=>array(140,229,360,448),726=>array(49,125,341,417),727=>array(49,234,269,307),728=>array(97,645,403,785),729=>array(200,658,300,758),730=>array(116,610,384,878),731=>array(162,-193,344,0),732=>array(89,639,411,777),733=>array(117,616,460,800),734=>array(-0,233,334,504),735=>array(117,616,383,800),736=>array(57,208,374,632),737=>array(60,326,116,751),738=>array(57,326,320,648),739=>array(57,326,391,632),740=>array(57,326,317,751),741=>array(104,0,389,668),742=>array(104,0,389,668),743=>array(104,0,389,668),744=>array(104,0,389,668),745=>array(104,0,389,668),748=>array(94,-260,406,-21),749=>array(104,610,396,808),750=>array(85,489,428,729),755=>array(116,-240,384,28),759=>array(89,-192,411,-55),768=>array(-418,560,-184,800),769=>array(-320,560,-86,800),770=>array(-406,560,-94,800),771=>array(-412,639,-90,777),772=>array(-394,673,-102,745),773=>array(-510,686,10,755),774=>array(-407,645,-101,785),775=>array(-296,560,-206,760),776=>array(-395,560,-105,758),777=>array(-348,618,-129,810),778=>array(-385,610,-117,878),779=>array(-381,616,-38,800),780=>array(-404,560,-92,800),781=>array(-283,615,-217,832),782=>array(-383,615,-117,832),783=>array(-455,616,-112,800),784=>array(-407,645,-101,917),785=>array(-407,645,-101,785),786=>array(-235,489,-92,645),787=>array(-305,595,-187,844),788=>array(-305,595,-187,844),789=>array(-66,575,66,759),790=>array(-418,-266,-184,-83),791=>array(-320,-267,-86,-83),792=>array(-357,-240,-221,-24),793=>array(-279,-240,-143,-24),794=>array(-208,690,31,930),795=>array(-133,427,60,609),796=>array(-313,-241,-208,-32),797=>array(-370,-240,-130,-87),798=>array(-370,-240,-130,-87),799=>array(-357,-240,-143,-24),800=>array(-370,-184,-130,-117),801=>array(-315,-208,-23,63),802=>array(-317,-208,-25,63),803=>array(-296,-183,-206,-69),804=>array(-396,-183,-106,-84),805=>array(-355,-241,-146,-32),806=>array(-323,-240,-180,-84),807=>array(-358,-193,-156,0),808=>array(-338,-193,-156,0),809=>array(-283,-240,-217,-47),810=>array(-383,-211,-114,-50),811=>array(-452,-222,-51,-82),812=>array(-404,-240,-92,-57),813=>array(-407,-240,-95,-57),814=>array(-407,-222,-101,-82),815=>array(-407,-224,-101,-83),816=>array(-412,-222,-90,-84),817=>array(-394,-156,-102,-84),818=>array(-510,-236,10,-166),819=>array(-510,-236,10,-9),820=>array(-557,240,-41,381),821=>array(-316,221,-59,301),822=>array(-634,221,-0,301),823=>array(-574,-46,-33,592),824=>array(-741,-34,-54,761),825=>array(-291,-241,-187,-32),826=>array(-382,-206,-113,-44),827=>array(-359,-240,-139,-21),828=>array(-452,-222,-51,-82),829=>array(-354,619,-138,834),830=>array(-247,595,-109,853),831=>array(-510,528,10,755),832=>array(-418,617,-184,800),833=>array(-320,616,-86,800),834=>array(-412,639,-90,777),835=>array(-305,595,-187,844),836=>array(-387,659,-77,978),837=>array(-278,-208,-171,-45),838=>array(-396,639,-104,786),839=>array(-360,-226,-140,-35),840=>array(-365,-240,-135,-47),841=>array(-360,-240,-140,-21),842=>array(-411,616,-89,800),843=>array(-411,567,-89,850),844=>array(-411,596,-89,820),845=>array(-452,-230,-48,-30),846=>array(-350,-240,-150,-45),849=>array(-316,610,-184,878),850=>array(-407,547,-101,855),851=>array(-354,-240,-138,-24),855=>array(-316,610,-184,878),856=>array(-103,658,-3,758),858=>array(-430,-241,-71,-32),860=>array(-445,-237,445,-60),861=>array(-445,802,445,979),862=>array(-445,855,445,927),863=>array(-445,-156,445,-84),864=>array(-354,756,354,894),865=>array(-445,752,445,929),866=>array(-442,-230,447,-30),880=>array(98,0,555,729),881=>array(94,0,477,547),882=>array(98,0,764,729),883=>array(98,0,549,729),884=>array(78,557,203,800),885=>array(78,-208,203,35),886=>array(98,0,650,729),887=>array(91,0,559,547),890=>array(214,-208,321,-45),891=>array(62,-14,495,560),892=>array(55,-14,488,560),893=>array(62,-14,495,560),894=>array(77,-116,220,517),900=>array(181,616,415,800),901=>array(105,659,415,978),902=>array(8,0,676,800),903=>array(107,285,210,409),904=>array(-12,0,682,800),905=>array(-6,0,765,800),906=>array(-9,0,311,800),908=>array(-7,-14,750,800),910=>array(-15,0,821,800),911=>array(-18,0,752,800),912=>array(2,0,313,978),913=>array(8,0,676,729),914=>array(98,0,615,729),915=>array(98,0,552,729),916=>array(8,0,676,729),917=>array(98,0,568,729),918=>array(45,0,640,729),919=>array(98,0,654,729),920=>array(56,-14,731,742),921=>array(98,0,197,729),922=>array(98,0,677,729),923=>array(8,0,676,729),924=>array(98,0,765,729),925=>array(98,0,650,729),926=>array(98,0,548,729),927=>array(56,-14,731,742),928=>array(98,0,654,729),929=>array(98,0,569,729),931=>array(98,0,568,729),932=>array(-3,0,614,729),933=>array(-2,0,613,729),934=>array(56,0,731,729),935=>array(30,0,654,729),936=>array(56,0,732,729),937=>array(38,0,726,738),938=>array(3,0,293,913),939=>array(-2,0,613,913),940=>array(55,-12,611,800),941=>array(65,-14,473,800),942=>array(91,-208,549,800),943=>array(81,0,324,800),944=>array(73,-14,521,978),945=>array(55,-12,611,559),946=>array(94,-208,566,766),947=>array(16,-208,562,547),948=>array(55,-14,557,742),949=>array(65,-14,473,561),950=>array(52,-210,496,760),951=>array(91,-208,549,560),952=>array(55,-11,557,768),953=>array(81,0,304,547),954=>array(93,0,565,547),955=>array(30,0,562,760),956=>array(85,-208,612,547),957=>array(36,0,512,547),958=>array(52,-210,500,760),959=>array(55,-14,557,560),960=>array(36,-19,574,547),961=>array(91,-208,580,560),962=>array(55,-210,488,560),963=>array(55,-14,604,547),964=>array(49,0,553,547),965=>array(73,-14,521,547),966=>array(55,-208,602,551),967=>array(29,-208,549,547),968=>array(55,-208,602,547),969=>array(66,-14,769,547),970=>array(2,0,311,758),971=>array(73,-14,521,758),972=>array(55,-14,557,800),973=>array(73,-14,521,800),974=>array(66,-14,769,800),975=>array(98,-208,677,729),976=>array(82,-11,538,768),977=>array(55,-11,557,768),978=>array(42,0,665,734),979=>array(-15,0,829,800),980=>array(42,0,665,913),981=>array(55,-208,602,760),982=>array(32,-14,803,547),983=>array(55,-206,600,550),984=>array(56,-207,731,742),985=>array(55,-208,557,560),986=>array(68,-210,583,729),987=>array(55,-210,540,547),988=>array(98,0,517,729),989=>array(-94,-208,409,760),990=>array(87,-2,604,729),991=>array(93,0,566,759),992=>array(56,-208,797,742),993=>array(58,-180,573,559),994=>array(56,-213,877,729),995=>array(66,-208,769,547),996=>array(56,-208,660,742),997=>array(55,-208,568,560),998=>array(98,-213,735,729),999=>array(22,-14,571,575),1000=>array(39,-208,630,745),1001=>array(49,-208,552,560),1002=>array(56,0,714,742),1003=>array(26,0,599,560),1004=>array(56,-14,643,758),1005=>array(55,-14,544,758),1006=>array(21,-208,589,729),1007=>array(27,-208,510,726),1008=>array(55,-7,600,550),1009=>array(91,-208,580,560),1010=>array(55,-14,488,560),1011=>array(-18,-208,184,760),1012=>array(56,-14,731,742),1013=>array(55,-14,480,560),1014=>array(96,-14,521,560),1015=>array(98,0,569,729),1016=>array(91,-208,580,760),1017=>array(56,-14,644,742),1018=>array(98,0,765,729),1019=>array(62,-208,587,547),1020=>array(42,-208,580,560),1021=>array(56,-14,644,742),1022=>array(56,-14,644,742),1023=>array(56,-14,644,742),1024=>array(98,0,568,927),1025=>array(98,0,568,913),1026=>array(-3,-200,709,729),1027=>array(98,0,552,927),1028=>array(56,-14,644,742),1029=>array(66,-14,579,742),1030=>array(98,0,197,729),1031=>array(3,0,293,913),1032=>array(-52,-200,197,729),1033=>array(41,0,1023,729),1034=>array(98,0,975,729),1035=>array(-3,0,709,729),1036=>array(98,0,690,927),1037=>array(98,0,650,927),1038=>array(17,0,592,928),1039=>array(98,-157,654,729),1040=>array(8,0,676,729),1041=>array(98,0,615,729),1042=>array(98,0,615,729),1043=>array(98,0,552,729),1044=>array(49,-157,732,729),1045=>array(98,0,568,729),1046=>array(20,0,1058,729),1047=>array(66,-14,575,742),1048=>array(98,0,650,729),1049=>array(98,0,650,928),1050=>array(98,0,690,729),1051=>array(41,0,653,729),1052=>array(98,0,765,729),1053=>array(98,0,654,729),1054=>array(56,-14,731,742),1055=>array(98,0,654,729),1056=>array(98,0,569,729),1057=>array(56,-14,644,742),1058=>array(-3,0,614,729),1059=>array(17,0,592,729),1060=>array(59,0,802,729),1061=>array(30,0,654,729),1062=>array(98,-157,737,729),1063=>array(85,0,587,729),1064=>array(98,0,971,729),1065=>array(98,-157,1054,729),1066=>array(29,0,762,729),1067=>array(98,0,784,729),1068=>array(98,0,615,729),1069=>array(54,-14,642,742),1070=>array(103,-14,1023,742),1071=>array(66,0,597,729),1072=>array(60,-14,522,560),1073=>array(55,-14,562,777),1074=>array(91,0,530,547),1075=>array(91,0,477,547),1076=>array(52,-138,639,547),1077=>array(55,-14,562,560),1078=>array(34,0,867,547),1079=>array(65,-14,473,561),1080=>array(91,0,559,547),1081=>array(91,0,559,760),1082=>array(91,0,571,547),1083=>array(37,0,556,547),1084=>array(91,0,664,547),1085=>array(91,0,563,547),1086=>array(55,-14,557,560),1087=>array(91,0,563,547),1088=>array(91,-208,580,560),1089=>array(55,-14,488,560),1090=>array(29,0,553,547),1091=>array(30,-208,562,547),1092=>array(55,-208,800,729),1093=>array(29,0,559,547),1094=>array(91,-138,635,547),1095=>array(73,0,500,547),1096=>array(91,0,824,547),1097=>array(91,-138,896,547),1098=>array(30,0,647,547),1099=>array(91,0,701,560),1100=>array(91,0,530,547),1101=>array(55,-14,488,560),1102=>array(94,-14,787,560),1103=>array(57,0,517,547),1104=>array(55,-14,562,802),1105=>array(55,-14,562,758),1106=>array(23,-208,570,760),1107=>array(91,0,480,803),1108=>array(55,-14,488,560),1109=>array(54,-14,472,560),1110=>array(94,0,184,760),1111=>array(-6,0,284,758),1112=>array(-18,-208,184,760),1113=>array(37,0,843,547),1114=>array(91,0,839,547),1115=>array(23,0,567,760),1116=>array(91,0,571,803),1117=>array(91,0,559,802),1118=>array(30,-208,562,760),1119=>array(91,-138,563,547),1120=>array(56,-14,877,729),1121=>array(66,-14,769,547),1122=>array(15,0,711,729),1123=>array(15,0,613,760),1124=>array(103,-14,888,742),1125=>array(94,-14,688,560),1126=>array(8,0,871,729),1127=>array(25,0,758,547),1128=>array(98,0,1135,729),1129=>array(94,0,977,547),1130=>array(56,0,731,729),1131=>array(52,0,560,547),1132=>array(98,0,971,729),1133=>array(94,0,772,547),1134=>array(56,-208,556,935),1135=>array(44,-193,473,753),1136=>array(8,0,844,729),1137=>array(24,-208,852,765),1138=>array(56,-14,731,742),1139=>array(55,-14,557,560),1140=>array(8,0,769,742),1141=>array(24,0,640,560),1142=>array(8,0,769,930),1143=>array(24,0,640,800),1144=>array(56,-208,962,742),1145=>array(55,-208,875,560),1146=>array(56,-14,897,742),1147=>array(55,-14,704,560),1148=>array(58,-14,1122,932),1149=>array(74,-14,954,758),1150=>array(56,-14,877,900),1151=>array(66,-14,769,734),1152=>array(56,-208,644,742),1153=>array(55,-208,488,560),1154=>array(29,-44,474,457),1155=>array(-519,608,-93,810),1156=>array(-372,645,4,788),1157=>array(-288,595,-169,797),1158=>array(-288,595,-169,797),1159=>array(-776,606,4,788),1160=>array(-1021,-180,409,922),1161=>array(-957,-280,345,1022),1162=>array(98,-208,748,928),1163=>array(94,-208,652,760),1164=>array(16,0,615,729),1165=>array(19,0,534,702),1166=>array(98,0,610,729),1167=>array(91,-208,580,560),1168=>array(98,0,552,878),1169=>array(91,0,477,700),1170=>array(35,0,617,729),1171=>array(27,0,542,547),1172=>array(98,-200,600,729),1173=>array(91,-208,505,547),1174=>array(20,-157,1071,729),1175=>array(34,-138,876,547),1176=>array(66,-193,575,742),1177=>array(65,-193,473,561),1178=>array(98,-157,713,729),1179=>array(91,-138,587,547),1180=>array(98,0,690,729),1181=>array(91,0,571,547),1182=>array(16,0,690,729),1183=>array(30,0,571,760),1184=>array(24,0,837,729),1185=>array(21,0,688,547),1186=>array(98,-157,752,729),1187=>array(94,-138,656,547),1188=>array(98,0,1009,729),1189=>array(94,0,862,547),1190=>array(98,-200,1057,729),1191=>array(94,-208,891,547),1192=>array(56,-14,871,743),1193=>array(55,-14,684,560),1194=>array(56,-193,644,742),1195=>array(55,-193,488,560),1196=>array(-3,-157,614,729),1197=>array(29,-138,553,547),1198=>array(-2,0,613,729),1199=>array(30,-208,562,547),1200=>array(-2,0,613,729),1201=>array(30,-208,562,547),1202=>array(30,-157,654,729),1203=>array(29,-138,559,547),1204=>array(-3,-157,910,729),1205=>array(2,-138,782,547),1206=>array(85,-157,686,729),1207=>array(73,-138,590,547),1208=>array(85,0,587,729),1209=>array(73,0,500,547),1210=>array(85,0,587,729),1211=>array(91,0,549,760),1212=>array(10,-14,885,742),1213=>array(7,-14,675,560),1214=>array(10,-184,885,742),1215=>array(7,-161,675,560),1216=>array(98,0,197,729),1217=>array(20,0,1058,928),1218=>array(34,0,867,785),1219=>array(98,-200,651,729),1220=>array(93,-208,566,547),1221=>array(26,-208,751,729),1222=>array(22,-208,646,547),1223=>array(98,-200,654,729),1224=>array(94,-208,566,547),1225=>array(98,-208,752,729),1226=>array(94,-208,656,547),1227=>array(85,-157,587,729),1228=>array(73,-138,500,547),1229=>array(98,-208,863,729),1230=>array(94,-208,750,547),1231=>array(94,0,184,760),1232=>array(8,0,676,946),1233=>array(60,-14,522,765),1234=>array(8,0,676,913),1235=>array(60,-14,522,758),1236=>array(4,0,910,729),1237=>array(60,-14,929,560),1238=>array(98,0,568,928),1239=>array(55,-14,562,785),1240=>array(57,-14,731,742),1241=>array(55,-14,562,560),1242=>array(57,-14,731,913),1243=>array(55,-14,562,758),1244=>array(20,0,1058,913),1245=>array(34,0,867,758),1246=>array(66,-14,575,913),1247=>array(65,-14,473,758),1248=>array(78,-31,621,729),1249=>array(43,-213,523,547),1250=>array(98,0,650,899),1251=>array(91,0,559,745),1252=>array(98,0,650,913),1253=>array(91,0,559,758),1254=>array(56,-14,731,913),1255=>array(55,-14,557,758),1256=>array(56,-14,731,742),1257=>array(55,-14,557,560),1258=>array(56,-14,731,913),1259=>array(55,-14,557,758),1260=>array(54,-14,642,913),1261=>array(55,-14,488,758),1262=>array(17,0,592,899),1263=>array(30,-208,562,745),1264=>array(17,0,592,913),1265=>array(30,-208,562,758),1266=>array(17,0,592,927),1267=>array(30,-208,562,800),1268=>array(85,0,587,913),1269=>array(73,0,500,758),1270=>array(98,-157,552,729),1271=>array(91,-138,477,547),1272=>array(98,0,784,913),1273=>array(91,0,701,758),1274=>array(35,-208,617,729),1275=>array(27,-208,542,547),1276=>array(30,-200,646,729),1277=>array(29,-208,549,547),1278=>array(30,0,654,729),1279=>array(29,0,559,547),1280=>array(71,0,588,729),1281=>array(55,0,495,547),1282=>array(71,-14,908,729),1283=>array(55,-14,806,547),1284=>array(98,-14,876,742),1285=>array(83,-14,784,561),1286=>array(98,-208,654,742),1287=>array(83,-208,564,561),1288=>array(26,-14,974,729),1289=>array(22,-14,866,547),1290=>array(98,-14,1022,729),1291=>array(94,-14,876,547),1292=>array(56,-14,692,742),1293=>array(55,-14,534,560),1294=>array(-3,-14,675,729),1295=>array(2,-14,620,547),1296=>array(80,-14,560,742),1297=>array(65,-14,473,561),1298=>array(41,-200,653,729),1299=>array(37,-208,556,547),1300=>array(41,0,1139,729),1301=>array(37,0,962,547),1302=>array(98,0,863,729),1303=>array(91,-208,832,560),1304=>array(66,0,967,729),1305=>array(57,-14,933,560),1306=>array(56,-129,731,742),1307=>array(55,-208,544,560),1308=>array(33,0,956,729),1309=>array(42,0,776,547),1310=>array(98,0,690,729),1311=>array(91,0,571,547),1312=>array(41,-200,1056,729),1313=>array(37,-208,881,547),1314=>array(98,-200,1057,729),1315=>array(91,-208,888,547),1316=>array(98,-157,752,729),1317=>array(91,-138,653,547),1329=>array(87,-29,680,729),1330=>array(87,0,650,743),1331=>array(45,0,729,743),1332=>array(44,0,724,743),1333=>array(87,-14,650,729),1334=>array(87,0,692,744),1335=>array(92,0,616,729),1336=>array(87,0,650,743),1337=>array(87,-14,835,743),1338=>array(45,-14,729,729),1339=>array(92,0,650,729),1340=>array(92,0,533,729),1341=>array(92,-14,849,729),1342=>array(129,-13,763,742),1343=>array(87,0,645,729),1344=>array(34,-26,638,729),1345=>array(82,-23,688,744),1346=>array(49,0,729,743),1347=>array(51,0,715,735),1348=>array(87,-14,767,729),1349=>array(71,-14,668,743),1350=>array(0,-14,680,729),1351=>array(78,-15,684,729),1352=>array(87,0,645,743),1353=>array(59,-28,664,744),1354=>array(44,0,713,743),1355=>array(82,0,686,744),1356=>array(87,0,767,743),1357=>array(87,-14,645,729),1358=>array(49,0,729,729),1359=>array(73,-14,632,741),1360=>array(87,0,645,743),1361=>array(78,-14,675,743),1362=>array(92,0,538,729),1363=>array(59,0,752,729),1364=>array(24,0,679,743),1365=>array(56,-14,731,742),1366=>array(54,-13,746,729),1369=>array(57,492,191,760),1370=>array(87,499,230,729),1371=>array(0,620,234,803),1372=>array(2,618,356,893),1373=>array(-0,617,233,800),1374=>array(4,613,401,866),1375=>array(44,618,462,760),1377=>array(85,-14,883,547),1378=>array(91,-208,549,560),1379=>array(55,-208,648,560),1380=>array(91,-208,653,560),1381=>array(85,-14,548,760),1382=>array(55,-208,648,560),1383=>array(91,0,490,760),1384=>array(91,-208,549,560),1385=>array(91,-208,738,560),1386=>array(55,-14,648,760),1387=>array(91,-208,549,760),1388=>array(91,-208,303,547),1389=>array(91,-208,889,760),1390=>array(55,-14,557,760),1391=>array(85,-208,543,760),1392=>array(91,0,549,760),1393=>array(52,-15,523,760),1394=>array(91,-208,653,560),1395=>array(68,-14,544,768),1396=>array(85,-14,647,760),1397=>array(-21,-208,181,547),1398=>array(-19,-14,543,760),1399=>array(0,-208,435,560),1400=>array(91,0,549,560),1401=>array(5,-208,370,547),1402=>array(85,-208,883,547),1403=>array(54,-208,494,561),1404=>array(91,0,609,560),1405=>array(85,-14,543,560),1406=>array(85,-208,647,760),1407=>array(85,-14,889,560),1408=>array(91,-208,549,560),1409=>array(54,-208,543,560),1410=>array(91,0,449,547),1411=>array(85,-208,889,760),1412=>array(20,-208,580,560),1413=>array(54,-14,556,560),1414=>array(34,-208,766,760),1415=>array(85,-14,812,760),1417=>array(117,0,220,415),1418=>array(49,212,312,314),1456=>array(283,-217,356,-22),1457=>array(83,-217,438,-22),1458=>array(125,-217,454,-22),1459=>array(125,-217,454,-22),1460=>array(283,-159,356,-85),1461=>array(222,-159,417,-85),1462=>array(222,-217,417,-22),1463=>array(173,-159,466,-85),1464=>array(173,-193,466,-46),1465=>array(0,625,73,698),1466=>array(0,625,73,698),1467=>array(148,-237,465,-17),1468=>array(288,237,361,310),1469=>array(283,-217,356,-22),1470=>array(49,472,312,552),1471=>array(173,625,466,698),1472=>array(102,-98,193,645),1473=>array(637,625,710,698),1474=>array(96,625,169,698),1475=>array(102,0,193,547),1478=>array(50,0,357,547),1479=>array(173,-217,466,-22),1488=>array(91,0,578,547),1489=>array(43,0,535,547),1490=>array(43,-5,383,547),1491=>array(43,0,511,547),1492=>array(91,0,563,547),1493=>array(91,0,182,547),1494=>array(43,0,303,547),1495=>array(91,0,563,547),1496=>array(90,-14,593,552),1497=>array(66,204,157,547),1498=>array(43,-208,446,547),1499=>array(43,0,474,547),1500=>array(43,0,492,729),1501=>array(91,0,573,547),1502=>array(43,0,588,555),1503=>array(91,-208,182,547),1504=>array(43,0,309,547),1505=>array(90,-14,593,547),1506=>array(43,-93,535,547),1507=>array(91,-208,549,547),1508=>array(91,0,569,547),1509=>array(43,-208,497,548),1510=>array(43,0,502,547),1511=>array(91,-208,633,546),1512=>array(43,0,474,547),1513=>array(43,0,666,547),1514=>array(10,-4,566,547),1520=>array(91,0,380,547),1521=>array(66,0,332,547),1522=>array(66,204,312,547),1523=>array(91,361,325,547),1524=>array(91,361,554,547),1542=>array(0,-20,607,892),1543=>array(0,-20,607,895),1545=>array(65,0,685,635),1546=>array(65,0,904,635),1548=>array(107,0,250,240),1557=>array(123,624,377,868),1563=>array(107,0,250,633),1567=>array(72,0,461,742),1569=>array(80,42,390,483),1570=>array(-37,0,315,939),1571=>array(53,0,220,999),1572=>array(-42,-244,406,588),1573=>array(53,-244,220,760),1574=>array(63,-131,719,588),1575=>array(94,0,184,760),1576=>array(63,-171,865,327),1577=>array(68,-28,453,513),1578=>array(63,-10,865,391),1579=>array(63,-10,865,513),1580=>array(77,-244,645,425),1581=>array(77,-244,645,425),1582=>array(77,-244,645,586),1583=>array(61,-19,388,415),1584=>array(61,-19,388,586),1585=>array(-42,-244,423,269),1586=>array(-42,-244,423,464),1587=>array(63,-244,1138,366),1588=>array(63,-244,1138,586),1589=>array(63,-244,1134,362),1590=>array(63,-244,1134,464),1591=>array(70,0,857,760),1592=>array(70,0,857,760),1593=>array(57,-244,587,521),1594=>array(57,-244,587,659),1600=>array(-10,0,303,90),1601=>array(63,-45,952,635),1602=>array(52,-215,701,635),1603=>array(70,-27,722,760),1604=>array(70,-152,637,760),1605=>array(68,-240,546,369),1606=>array(72,-162,660,464),1607=>array(68,-28,453,358),1608=>array(-42,-244,406,315),1609=>array(63,-131,719,411),1610=>array(63,-244,719,411),1611=>array(107,591,393,825),1612=>array(107,591,393,874),1613=>array(107,-239,393,-5),1614=>array(107,591,393,708),1615=>array(107,590,393,874),1616=>array(107,-137,393,-20),1617=>array(98,599,402,869),1618=>array(115,610,383,878),1619=>array(74,590,426,719),1620=>array(164,593,331,808),1621=>array(164,-244,331,-29),1623=>array(107,615,393,898),1626=>array(119,616,381,775),1632=>array(215,220,322,342),1633=>array(136,0,342,635),1634=>array(40,0,492,635),1635=>array(37,0,509,635),1636=>array(85,-10,457,641),1637=>array(66,-10,471,643),1638=>array(42,0,493,635),1639=>array(29,0,508,635),1640=>array(29,0,508,635),1641=>array(49,0,493,640),1642=>array(65,0,472,635),1643=>array(0,-110,300,318),1644=>array(87,499,230,729),1645=>array(42,101,502,537),1646=>array(63,-10,865,327),1647=>array(52,-215,701,481),1648=>array(223,602,277,887),1652=>array(60,649,227,864),1657=>array(63,-10,865,575),1658=>array(63,-10,865,513),1659=>array(63,-244,865,327),1660=>array(63,-180,865,391),1661=>array(63,-10,865,464),1662=>array(63,-244,865,327),1663=>array(63,-10,865,513),1664=>array(63,-244,865,327),1665=>array(77,-244,645,710),1666=>array(77,-244,645,708),1667=>array(77,-244,645,425),1668=>array(77,-244,645,425),1669=>array(77,-244,645,708),1670=>array(77,-244,645,425),1671=>array(77,-244,645,425),1672=>array(61,-19,388,746),1673=>array(61,-180,388,415),1674=>array(61,-171,388,415),1675=>array(61,-171,388,746),1676=>array(61,-19,388,586),1677=>array(61,-146,388,415),1678=>array(61,-19,388,708),1679=>array(61,-19,388,684),1680=>array(61,-19,388,708),1681=>array(-42,-244,469,648),1682=>array(-42,-244,473,556),1683=>array(-42,-244,507,269),1684=>array(-42,-244,474,269),1685=>array(-42,-244,634,269),1686=>array(-42,-244,474,269),1687=>array(-42,-244,439,464),1688=>array(-42,-244,439,586),1689=>array(-42,-244,439,586),1690=>array(63,-244,1138,464),1691=>array(63,-244,1138,366),1692=>array(63,-244,1138,586),1693=>array(63,-244,1134,362),1694=>array(63,-244,1134,586),1695=>array(70,0,857,760),1696=>array(57,-244,587,781),1697=>array(63,-45,952,481),1698=>array(63,-171,952,481),1699=>array(63,-171,952,635),1700=>array(63,-45,952,757),1701=>array(63,-293,952,481),1702=>array(63,-45,952,757),1703=>array(52,-215,701,635),1704=>array(52,-215,701,757),1705=>array(63,-43,895,760),1706=>array(63,-43,1000,760),1707=>array(63,-43,895,760),1708=>array(70,-27,722,760),1709=>array(70,-27,722,854),1710=>array(70,-293,722,760),1711=>array(63,-43,895,896),1712=>array(63,-43,895,896),1713=>array(63,-43,895,903),1714=>array(63,-171,895,896),1715=>array(63,-293,895,896),1716=>array(63,-43,895,1025),1717=>array(70,-152,723,971),1718=>array(70,-152,637,952),1719=>array(70,-152,684,1025),1720=>array(70,-391,637,760),1721=>array(72,-317,660,464),1722=>array(72,-162,660,366),1723=>array(72,-162,660,636),1724=>array(72,-330,660,464),1725=>array(72,-162,660,586),1726=>array(70,-33,638,487),1727=>array(77,-244,645,586),1734=>array(-42,-244,406,556),1740=>array(63,-131,719,411),1742=>array(63,-131,719,556),1749=>array(68,-28,453,358),1776=>array(215,220,322,342),1777=>array(136,0,342,635),1778=>array(40,0,492,635),1779=>array(37,0,509,635),1780=>array(40,0,471,643),1781=>array(52,-5,485,643),1782=>array(102,0,445,640),1783=>array(29,0,508,635),1784=>array(29,0,508,635),1785=>array(49,0,493,640),1984=>array(66,-14,570,742),1985=>array(110,0,544,729),1986=>array(110,0,530,729),1987=>array(110,0,530,729),1988=>array(110,0,530,729),1989=>array(110,0,530,729),1990=>array(110,0,530,729),1991=>array(104,0,532,729),1992=>array(104,0,532,729),1993=>array(77,0,560,741),1994=>array(94,0,184,729),1995=>array(55,-14,516,447),1996=>array(30,0,394,731),1997=>array(30,0,562,430),1998=>array(91,0,563,430),1999=>array(91,0,563,430),2000=>array(55,0,539,735),2001=>array(91,0,563,581),2002=>array(55,0,738,741),2003=>array(94,0,408,729),2004=>array(30,0,344,729),2005=>array(91,0,504,729),2006=>array(94,0,518,729),2007=>array(30,0,256,729),2008=>array(94,0,865,513),2009=>array(30,0,443,729),2010=>array(30,0,754,729),2011=>array(91,0,563,430),2012=>array(30,0,595,729),2013=>array(94,0,679,729),2014=>array(94,0,436,729),2015=>array(55,0,630,729),2016=>array(30,0,443,729),2017=>array(30,0,595,729),2018=>array(55,0,539,729),2019=>array(94,0,436,729),2020=>array(94,0,436,612),2021=>array(94,0,428,729),2022=>array(55,0,539,729),2023=>array(55,0,539,729),2027=>array(106,673,398,745),2028=>array(32,609,468,800),2029=>array(205,658,305,758),2030=>array(93,616,405,800),2031=>array(44,616,456,800),2032=>array(32,609,468,800),2033=>array(44,616,456,800),2034=>array(200,-184,300,-84),2035=>array(104,659,394,758),2036=>array(98,557,216,760),2037=>array(98,557,216,760),2040=>array(49,0,511,498),2041=>array(49,0,511,483),2042=>array(-10,0,371,72),3647=>array(86,-138,571,769),3713=>array(63,-10,607,560),3714=>array(68,-17,691,568),3716=>array(67,-10,619,568),3719=>array(53,-238,415,568),3720=>array(62,-0,574,575),3722=>array(68,-234,690,568),3725=>array(56,-8,619,573),3732=>array(91,-14,592,560),3733=>array(63,-15,564,579),3734=>array(0,-240,587,560),3735=>array(42,-8,599,571),3737=>array(46,-14,593,568),3738=>array(36,-8,556,561),3739=>array(36,-8,556,760),3740=>array(43,-8,725,614),3741=>array(91,-14,676,760),3742=>array(51,-8,636,561),3743=>array(51,-8,636,760),3745=>array(31,-14,636,547),3746=>array(56,-8,619,760),3747=>array(68,-8,634,568),3749=>array(39,-8,583,568),3751=>array(56,-13,558,560),3754=>array(39,-8,688,679),3755=>array(62,-12,762,575),3757=>array(56,-14,558,560),3758=>array(68,-8,684,605),3759=>array(99,-166,742,579),3760=>array(54,-13,589,563),3761=>array(-578,639,-43,880),3762=>array(60,0,473,560),3763=>array(-425,0,473,806),3764=>array(-594,615,-73,926),3765=>array(-594,615,0,926),3766=>array(-594,615,-73,926),3767=>array(-594,615,0,926),3768=>array(-376,-350,-161,-38),3769=>array(-418,-306,-152,-40),3771=>array(-578,639,-43,880),3772=>array(-611,-278,6,-39),3773=>array(63,-240,619,715),3776=>array(60,-14,324,560),3777=>array(60,-14,598,560),3778=>array(-22,-5,398,896),3779=>array(45,-14,490,892),3780=>array(92,-11,445,886),3782=>array(72,-232,574,557),3784=>array(-366,618,-278,792),3785=>array(-563,609,-45,891),3786=>array(-595,598,22,869),3787=>array(-462,609,-182,890),3788=>array(-611,636,6,875),3789=>array(-425,620,-220,806),3792=>array(66,-14,570,547),3793=>array(48,-75,582,576),3794=>array(48,-66,545,711),3795=>array(11,-9,692,830),3796=>array(48,-83,601,711),3797=>array(48,-83,601,711),3798=>array(43,-8,744,812),3799=>array(63,-240,607,560),3800=>array(73,-210,680,557),3801=>array(51,-4,621,571),3804=>array(62,-12,947,575),3805=>array(62,-12,973,575),4256=>array(59,-15,815,828),4257=>array(54,-0,704,828),4258=>array(54,-148,649,837),4259=>array(54,-15,781,828),4260=>array(49,0,552,837),4261=>array(39,0,714,837),4262=>array(29,-15,695,828),4263=>array(59,-15,885,837),4264=>array(29,0,390,874),4265=>array(59,0,561,828),4266=>array(29,-15,784,828),4267=>array(59,-15,824,828),4268=>array(63,0,566,828),4269=>array(49,-167,806,837),4270=>array(24,-15,717,837),4271=>array(39,0,566,828),4272=>array(54,-15,853,828),4273=>array(63,-15,567,828),4274=>array(63,-0,566,837),4275=>array(49,-182,806,837),4276=>array(49,0,817,834),4277=>array(44,0,680,828),4278=>array(64,-15,566,837),4279=>array(54,0,557,828),4280=>array(59,-15,562,828),4281=>array(63,0,566,828),4282=>array(59,-15,764,837),4283=>array(59,-15,810,828),4284=>array(63,-0,566,828),4285=>array(49,-15,574,837),4286=>array(63,-0,566,828),4287=>array(29,0,695,828),4288=>array(29,-15,785,828),4289=>array(63,0,566,828),4290=>array(54,-15,635,837),4291=>array(29,0,532,828),4292=>array(54,0,540,828),4293=>array(39,-15,699,837),4304=>array(49,-15,459,592),4305=>array(49,-14,469,837),4306=>array(44,-235,537,551),4307=>array(49,-230,759,547),4308=>array(49,-236,449,547),4309=>array(49,-236,459,547),4310=>array(20,-14,452,838),4311=>array(49,-14,752,547),4312=>array(49,0,469,547),4313=>array(44,-236,456,542),4314=>array(49,-230,1016,552),4315=>array(49,-15,459,837),4316=>array(63,-15,474,833),4317=>array(49,-0,737,547),4318=>array(49,-15,459,833),4319=>array(49,-236,458,551),4320=>array(49,0,747,833),4321=>array(63,-15,474,827),4322=>array(44,-236,610,680),4323=>array(5,-236,464,571),4324=>array(49,-236,766,547),4325=>array(49,-236,449,828),4326=>array(49,-230,737,546),4327=>array(49,-236,459,538),4328=>array(29,-15,454,837),4329=>array(63,0,474,837),4330=>array(44,-236,527,532),4331=>array(49,-14,458,828),4332=>array(64,-15,488,837),4333=>array(49,-236,471,827),4334=>array(63,-15,474,827),4335=>array(10,-235,444,572),4336=>array(49,-15,459,837),4337=>array(59,-15,469,837),4338=>array(49,-141,458,547),4339=>array(49,-236,459,546),4340=>array(49,-236,458,837),4341=>array(49,-15,515,837),4342=>array(49,-236,778,547),4343=>array(44,-236,508,547),4344=>array(49,-236,459,538),4345=>array(39,-236,532,551),4346=>array(49,-77,459,547),4347=>array(54,-10,394,484),4348=>array(49,420,270,837),5121=>array(8,1,676,730),5122=>array(8,0,676,1037),5123=>array(8,0,676,729),5124=>array(8,0,676,914),5125=>array(98,0,711,729),5126=>array(98,0,711,914),5127=>array(98,0,711,913),5129=>array(98,0,711,729),5130=>array(58,0,671,729),5131=>array(58,0,671,914),5132=>array(98,1,827,730),5133=>array(8,1,776,730),5134=>array(98,0,827,729),5135=>array(8,0,776,729),5136=>array(98,0,827,914),5137=>array(8,0,776,914),5138=>array(98,0,909,729),5139=>array(98,0,909,729),5140=>array(98,0,909,914),5141=>array(98,0,909,914),5142=>array(98,0,711,914),5143=>array(98,0,869,729),5144=>array(58,0,909,729),5145=>array(98,0,869,914),5146=>array(58,0,909,914),5147=>array(58,0,671,914),5149=>array(98,629,198,729),5150=>array(67,326,488,734),5151=>array(46,356,362,714),5152=>array(46,356,362,714),5153=>array(67,398,334,674),5154=>array(67,391,334,667),5155=>array(67,398,338,667),5156=>array(67,398,334,667),5157=>array(35,327,405,733),5158=>array(67,326,331,734),5159=>array(98,312,198,412),5160=>array(67,503,334,563),5161=>array(67,399,334,667),5162=>array(67,399,334,691),5163=>array(8,1,1028,730),5164=>array(8,0,847,729),5165=>array(98,0,892,729),5166=>array(58,0,1055,729),5167=>array(8,0,676,729),5168=>array(8,0,676,1037),5169=>array(8,0,676,729),5170=>array(8,0,676,914),5171=>array(58,0,671,729),5172=>array(58,0,671,914),5173=>array(58,0,671,913),5175=>array(58,0,671,729),5176=>array(58,0,671,729),5177=>array(58,0,671,914),5178=>array(98,0,827,729),5179=>array(8,0,776,729),5180=>array(98,0,827,729),5181=>array(8,0,776,729),5182=>array(98,0,827,914),5183=>array(8,0,776,914),5184=>array(98,0,869,729),5185=>array(58,0,909,729),5186=>array(98,0,869,914),5187=>array(58,0,909,914),5188=>array(98,0,869,729),5189=>array(58,0,909,729),5190=>array(98,0,869,914),5191=>array(58,0,909,914),5192=>array(58,0,671,913),5193=>array(67,326,453,734),5194=>array(67,326,137,734),5196=>array(87,-14,645,729),5197=>array(87,0,645,1037),5198=>array(87,0,645,743),5199=>array(87,0,645,914),5200=>array(58,0,671,729),5201=>array(58,0,671,914),5202=>array(58,0,671,913),5204=>array(58,0,671,729),5205=>array(59,0,672,729),5206=>array(59,0,672,914),5207=>array(98,-14,834,729),5208=>array(87,-14,831,729),5209=>array(98,0,834,743),5210=>array(87,0,831,743),5211=>array(98,0,834,914),5212=>array(87,0,831,914),5213=>array(98,0,869,729),5214=>array(58,0,842,729),5215=>array(98,0,869,914),5216=>array(58,0,842,914),5217=>array(98,0,889,729),5218=>array(59,0,842,729),5219=>array(98,0,889,914),5220=>array(59,0,842,914),5221=>array(117,0,889,729),5222=>array(67,326,379,734),5223=>array(87,-14,823,734),5224=>array(87,0,823,743),5225=>array(58,0,811,734),5226=>array(59,0,835,734),5227=>array(34,0,530,743),5228=>array(98,0,594,1037),5229=>array(98,0,594,743),5230=>array(98,0,594,914),5231=>array(34,-14,530,729),5232=>array(34,-14,530,914),5233=>array(34,-14,623,913),5234=>array(98,-14,594,729),5235=>array(98,-14,594,914),5236=>array(98,0,762,743),5237=>array(34,0,712,743),5238=>array(98,0,781,743),5239=>array(98,0,758,743),5240=>array(98,0,781,914),5241=>array(98,0,758,914),5242=>array(98,-14,762,729),5243=>array(34,-14,712,729),5244=>array(98,-14,762,914),5245=>array(34,-14,712,914),5246=>array(98,-14,781,729),5247=>array(98,-14,758,729),5248=>array(98,-14,781,914),5249=>array(98,-14,758,914),5250=>array(117,-14,781,729),5251=>array(67,318,379,734),5252=>array(27,318,340,734),5253=>array(34,0,696,743),5254=>array(98,0,720,743),5255=>array(34,-14,696,734),5256=>array(98,-14,720,734),5257=>array(34,0,530,743),5258=>array(98,0,594,1037),5259=>array(98,0,594,743),5260=>array(98,0,594,914),5261=>array(34,-14,530,729),5262=>array(34,-14,530,914),5263=>array(34,-14,623,913),5264=>array(98,-14,594,729),5265=>array(98,-14,594,914),5266=>array(98,0,762,743),5267=>array(34,0,712,743),5268=>array(98,0,781,743),5269=>array(98,0,758,743),5270=>array(98,0,781,914),5271=>array(98,0,758,914),5272=>array(98,-14,762,729),5273=>array(34,-14,712,729),5274=>array(98,-14,762,914),5275=>array(34,-14,712,914),5276=>array(98,-14,781,729),5277=>array(98,-14,758,729),5278=>array(98,-14,781,914),5279=>array(98,-14,758,914),5280=>array(117,-14,781,729),5281=>array(67,318,379,734),5282=>array(67,318,379,734),5283=>array(58,0,512,729),5284=>array(98,0,552,1037),5285=>array(98,0,552,729),5286=>array(98,0,552,914),5287=>array(58,0,512,729),5288=>array(58,0,512,914),5289=>array(58,0,607,913),5290=>array(98,0,552,729),5291=>array(98,0,552,914),5292=>array(98,0,651,729),5293=>array(58,0,710,729),5294=>array(98,0,741,729),5295=>array(98,0,706,729),5296=>array(98,0,741,914),5297=>array(98,0,706,914),5298=>array(98,0,651,729),5299=>array(58,0,710,729),5300=>array(98,0,651,914),5301=>array(58,0,710,914),5302=>array(98,0,741,729),5303=>array(98,0,706,729),5304=>array(98,0,741,914),5305=>array(98,0,706,914),5306=>array(117,0,741,729),5307=>array(67,326,331,734),5308=>array(67,326,453,734),5309=>array(67,326,331,734),5312=>array(58,-14,817,436),5313=>array(34,-14,793,755),5314=>array(34,-14,793,436),5315=>array(5,-14,765,636),5316=>array(58,0,817,450),5317=>array(58,0,817,636),5318=>array(58,0,817,635),5319=>array(34,0,793,450),5320=>array(34,0,793,636),5321=>array(98,-14,1035,436),5322=>array(58,-14,977,436),5323=>array(98,0,1025,450),5324=>array(34,0,793,450),5325=>array(98,0,1025,636),5326=>array(34,0,793,636),5327=>array(34,0,793,635),5328=>array(67,484,545,736),5329=>array(67,318,397,734),5330=>array(67,484,545,736),5331=>array(58,0,817,450),5332=>array(34,0,793,755),5333=>array(34,0,793,450),5334=>array(34,0,793,636),5335=>array(58,0,817,450),5336=>array(58,0,817,636),5337=>array(58,0,817,635),5338=>array(34,0,793,450),5339=>array(34,0,793,636),5340=>array(98,0,1035,450),5341=>array(58,0,977,450),5342=>array(98,0,1025,450),5343=>array(34,0,972,450),5344=>array(98,0,1025,636),5345=>array(34,0,972,636),5346=>array(98,0,1035,450),5347=>array(58,0,977,450),5348=>array(98,0,1035,636),5349=>array(58,0,977,636),5350=>array(98,0,1025,450),5351=>array(34,0,972,450),5352=>array(98,0,1025,636),5353=>array(34,0,972,636),5354=>array(67,484,545,736),5356=>array(58,0,671,729),5357=>array(34,0,505,729),5358=>array(98,0,649,1037),5359=>array(98,0,569,729),5360=>array(98,0,569,914),5361=>array(34,0,505,729),5362=>array(34,0,505,914),5363=>array(34,0,600,913),5364=>array(98,0,569,729),5365=>array(98,0,569,914),5366=>array(98,0,736,729),5367=>array(34,0,696,729),5368=>array(98,0,758,729),5369=>array(98,0,713,729),5370=>array(98,0,758,914),5371=>array(98,0,713,914),5372=>array(98,0,736,729),5373=>array(34,0,696,729),5374=>array(98,0,736,914),5375=>array(34,0,696,914),5376=>array(98,0,758,729),5377=>array(98,0,713,729),5378=>array(98,0,758,914),5379=>array(98,0,713,914),5380=>array(117,0,758,729),5381=>array(67,326,363,734),5382=>array(67,318,365,741),5383=>array(67,326,363,734),5392=>array(34,-14,678,743),5393=>array(34,-14,678,743),5394=>array(34,-14,678,914),5395=>array(34,-14,857,464),5396=>array(34,-14,857,636),5397=>array(34,-14,857,464),5398=>array(34,-14,857,636),5399=>array(98,-14,875,743),5400=>array(34,-14,814,743),5401=>array(98,-14,875,743),5402=>array(34,-14,814,743),5403=>array(98,-14,875,914),5404=>array(34,-14,814,914),5405=>array(98,-14,1106,464),5406=>array(34,-14,1042,464),5407=>array(98,-14,1106,636),5408=>array(34,-14,1042,636),5409=>array(98,-14,1106,464),5410=>array(34,-14,1042,464),5411=>array(98,-14,1106,636),5412=>array(34,-14,1042,636),5413=>array(67,476,585,737),5414=>array(58,0,529,729),5415=>array(98,0,569,1037),5416=>array(98,0,569,729),5417=>array(98,0,569,914),5418=>array(58,0,529,729),5419=>array(58,0,531,914),5420=>array(58,0,626,913),5421=>array(98,0,569,729),5422=>array(98,0,569,914),5423=>array(98,0,746,729),5424=>array(58,0,723,729),5425=>array(98,0,758,729),5426=>array(98,0,760,729),5427=>array(98,0,758,914),5428=>array(98,0,760,914),5429=>array(98,0,746,729),5430=>array(58,0,723,729),5431=>array(98,0,749,914),5432=>array(58,0,723,914),5433=>array(98,0,758,729),5434=>array(98,0,760,729),5435=>array(98,0,758,914),5436=>array(98,0,760,914),5437=>array(117,0,758,729),5438=>array(67,326,363,734),5440=>array(67,399,334,667),5441=>array(67,326,429,734),5442=>array(98,-14,857,436),5443=>array(58,-14,817,436),5444=>array(58,0,817,450),5445=>array(98,0,857,755),5446=>array(98,0,857,450),5447=>array(98,0,857,636),5448=>array(98,0,569,729),5449=>array(98,0,569,914),5450=>array(98,0,569,729),5451=>array(34,0,505,729),5452=>array(34,0,505,914),5453=>array(34,0,505,729),5454=>array(98,0,736,914),5455=>array(34,0,696,914),5456=>array(67,326,363,734),5458=>array(58,0,671,729),5459=>array(73,0,676,744),5460=>array(73,-15,676,1037),5461=>array(73,-15,676,729),5462=>array(73,-15,676,914),5463=>array(38,0,668,662),5464=>array(38,0,668,914),5465=>array(58,0,688,662),5466=>array(58,0,688,914),5467=>array(98,0,886,914),5468=>array(58,0,909,914),5469=>array(67,326,462,695),5470=>array(87,-14,645,743),5471=>array(87,-14,645,743),5472=>array(87,-14,645,743),5473=>array(87,-14,645,743),5474=>array(87,-14,645,914),5475=>array(87,-14,645,914),5476=>array(41,0,671,729),5477=>array(41,0,671,914),5478=>array(59,0,689,729),5479=>array(59,0,689,914),5480=>array(98,0,907,914),5481=>array(59,0,842,914),5482=>array(67,326,467,734),5492=>array(34,0,772,743),5493=>array(58,0,796,743),5494=>array(58,0,796,914),5495=>array(34,-14,772,729),5496=>array(34,-14,772,914),5497=>array(58,-14,796,729),5498=>array(58,-14,796,914),5499=>array(67,318,508,734),5500=>array(98,0,654,729),5501=>array(67,326,429,734),5502=>array(67,0,1013,1037),5503=>array(67,0,1013,743),5504=>array(67,0,1013,914),5505=>array(67,-14,949,734),5506=>array(67,-14,949,914),5507=>array(67,-14,1013,734),5508=>array(67,-14,1013,914),5509=>array(67,318,798,734),5514=>array(34,0,772,743),5515=>array(58,0,796,743),5516=>array(34,-14,772,729),5517=>array(58,-14,796,729),5518=>array(67,0,1225,1037),5519=>array(67,0,1225,743),5520=>array(67,0,1225,914),5521=>array(67,-14,904,736),5522=>array(67,-14,904,914),5523=>array(67,-14,1225,736),5524=>array(67,-14,1225,914),5525=>array(67,332,645,736),5526=>array(67,332,1018,736),5536=>array(34,0,793,692),5537=>array(34,0,793,692),5538=>array(58,-242,817,450),5539=>array(58,-242,817,636),5540=>array(34,-242,793,450),5541=>array(34,-242,793,636),5542=>array(67,338,545,736),5543=>array(58,0,627,729),5544=>array(16,0,585,729),5545=>array(16,0,585,914),5546=>array(58,0,627,729),5547=>array(58,0,627,914),5548=>array(16,0,585,729),5549=>array(16,0,585,914),5550=>array(5,326,363,734),5551=>array(98,-14,594,729),5598=>array(98,0,711,729),5601=>array(56,0,669,729),5702=>array(67,326,413,734),5703=>array(67,240,413,820),5742=>array(57,0,391,306),5743=>array(67,0,949,743),5744=>array(67,0,1211,743),5745=>array(67,0,1598,743),5746=>array(67,0,1598,914),5747=>array(67,-14,1277,736),5748=>array(67,-14,1277,914),5749=>array(67,-14,1598,736),5750=>array(67,-14,1598,914),5760=>array(-10,246,487,328),5761=>array(-10,-125,502,328),5762=>array(-10,-125,722,328),5763=>array(-10,-125,941,328),5764=>array(-10,-125,1160,328),5765=>array(-10,-125,1379,328),5766=>array(-10,246,502,697),5767=>array(-10,246,722,697),5768=>array(-10,246,941,697),5769=>array(-10,246,1160,697),5770=>array(-10,246,1379,697),5771=>array(-10,-125,508,697),5772=>array(-10,-125,728,697),5773=>array(-10,-125,948,697),5774=>array(-10,-125,1168,697),5775=>array(-10,-125,1389,697),5776=>array(-10,41,502,533),5777=>array(-10,41,722,533),5778=>array(-10,41,939,533),5779=>array(-10,41,1159,533),5780=>array(-10,41,1379,533),5781=>array(-10,-125,508,697),5782=>array(-10,-125,762,697),5783=>array(-10,-83,798,328),5784=>array(-10,-240,1214,328),5785=>array(-10,246,1160,902),5786=>array(-10,82,693,328),5787=>array(55,28,517,544),5788=>array(-10,28,452,544),7424=>array(30,0,562,547),7425=>array(5,0,669,547),7426=>array(60,-14,929,560),7427=>array(30,0,530,547),7428=>array(55,-14,488,560),7429=>array(91,0,550,547),7430=>array(18,0,550,547),7431=>array(91,0,443,547),7432=>array(63,-14,471,561),7433=>array(94,-213,184,547),7434=>array(0,-14,310,547),7435=>array(91,0,576,547),7436=>array(1,0,498,560),7437=>array(91,0,664,547),7438=>array(91,0,559,547),7439=>array(55,-14,557,560),7440=>array(62,-14,495,560),7441=>array(55,22,629,524),7442=>array(55,57,629,489),7443=>array(25,2,663,543),7444=>array(55,-14,970,560),7446=>array(55,273,557,560),7447=>array(55,-14,557,273),7448=>array(74,0,475,547),7449=>array(24,0,507,547),7450=>array(24,0,507,547),7451=>array(29,0,553,547),7452=>array(91,-16,510,547),7453=>array(85,37,646,495),7454=>array(85,38,857,496),7455=>array(23,-238,583,560),7456=>array(30,0,562,547),7457=>array(42,0,776,547),7458=>array(43,0,482,547),7459=>array(59,-14,466,547),7462=>array(87,0,498,560),7463=>array(30,0,562,547),7464=>array(74,0,490,547),7465=>array(74,0,475,547),7466=>array(44,0,546,547),7467=>array(37,0,556,547),7468=>array(5,326,426,734),7469=>array(2,326,573,734),7470=>array(62,326,388,734),7472=>array(62,326,448,734),7473=>array(62,326,358,734),7474=>array(41,326,336,734),7475=>array(35,318,437,742),7476=>array(62,326,412,734),7477=>array(62,326,124,734),7478=>array(-33,214,124,734),7479=>array(62,326,426,734),7480=>array(62,326,348,734),7481=>array(62,326,482,734),7482=>array(62,326,410,734),7483=>array(62,326,410,734),7484=>array(35,318,460,742),7485=>array(35,318,405,742),7486=>array(62,326,358,734),7487=>array(62,326,419,734),7488=>array(-2,326,387,734),7489=>array(55,318,406,734),7490=>array(21,326,603,734),7491=>array(38,318,329,640),7492=>array(38,318,329,640),7493=>array(35,318,343,640),7494=>array(38,318,585,640),7495=>array(57,318,365,751),7496=>array(35,318,343,751),7497=>array(35,318,354,640),7498=>array(35,318,354,640),7499=>array(41,318,298,640),7500=>array(40,318,297,640),7501=>array(35,209,343,640),7502=>array(60,207,116,632),7503=>array(57,326,363,751),7504=>array(57,326,560,640),7505=>array(57,209,346,640),7506=>array(35,318,351,640),7507=>array(35,318,307,640),7508=>array(35,479,351,640),7509=>array(35,318,351,479),7510=>array(57,209,365,640),7511=>array(17,326,232,719),7512=>array(54,318,342,632),7513=>array(54,347,407,604),7514=>array(57,319,560,633),7515=>array(19,326,354,632),7517=>array(59,209,357,755),7518=>array(10,209,354,632),7519=>array(35,318,351,742),7520=>array(35,209,379,635),7521=>array(18,209,346,633),7522=>array(60,0,116,425),7523=>array(57,0,259,313),7524=>array(54,-8,342,306),7525=>array(19,0,354,306),7526=>array(59,-117,357,429),7527=>array(10,-117,354,306),7528=>array(59,-117,367,313),7529=>array(35,-117,379,309),7530=>array(18,-117,346,307),7543=>array(91,-208,580,560),7544=>array(62,326,412,734),7547=>array(57,0,314,547),7549=>array(24,-208,643,560),7557=>array(71,-208,273,760),7579=>array(35,318,343,640),7580=>array(35,318,307,640),7581=>array(35,287,307,640),7582=>array(35,318,351,751),7583=>array(41,318,298,640),7584=>array(15,326,234,751),7585=>array(-11,209,170,632),7586=>array(35,209,343,632),7587=>array(54,209,342,632),7588=>array(36,326,198,751),7589=>array(60,326,187,632),7590=>array(36,326,198,632),7591=>array(36,326,198,632),7592=>array(-83,209,172,751),7593=>array(60,209,187,751),7594=>array(44,209,172,751),7595=>array(55,326,314,640),7596=>array(57,209,560,640),7597=>array(57,209,560,633),7598=>array(-11,209,348,640),7599=>array(57,209,417,640),7600=>array(55,326,346,640),7601=>array(35,318,351,640),7602=>array(35,210,351,751),7603=>array(34,209,297,640),7604=>array(-11,209,224,751),7605=>array(17,209,232,719),7606=>array(46,318,445,632),7607=>array(35,318,355,632),7608=>array(57,317,321,632),7609=>array(60,326,343,632),7610=>array(19,326,354,632),7611=>array(27,326,304,632),7612=>array(27,209,374,632),7613=>array(27,296,304,632),7614=>array(27,207,330,632),7615=>array(35,320,351,756),7620=>array(-456,616,-44,800),7621=>array(-456,616,-44,800),7622=>array(-456,616,-44,800),7623=>array(-456,616,-44,800),7624=>array(-468,616,-32,800),7625=>array(-468,616,-32,800),7680=>array(8,-241,676,729),7681=>array(60,-241,522,560),7682=>array(98,0,615,914),7683=>array(90,-14,580,915),7684=>array(98,-183,615,729),7685=>array(91,-183,580,760),7686=>array(98,-156,615,729),7687=>array(91,-156,580,760),7688=>array(56,-193,644,928),7689=>array(55,-193,488,800),7690=>array(98,0,711,914),7691=>array(55,-14,544,942),7692=>array(98,-183,711,729),7693=>array(55,-183,544,760),7694=>array(98,-156,711,729),7695=>array(55,-156,544,760),7696=>array(98,-192,711,729),7697=>array(55,-193,544,760),7698=>array(98,-240,711,729),7699=>array(55,-240,544,760),7700=>array(98,0,568,1044),7701=>array(55,-14,562,921),7702=>array(98,0,568,1044),7703=>array(55,-14,562,921),7704=>array(98,-213,568,729),7705=>array(55,-213,562,560),7706=>array(98,-192,568,729),7707=>array(55,-192,562,560),7708=>array(98,-193,568,928),7709=>array(55,-193,562,785),7710=>array(98,0,517,914),7711=>array(23,0,371,942),7712=>array(56,-14,693,887),7713=>array(55,-208,544,745),7714=>array(98,0,654,913),7715=>array(90,0,549,915),7716=>array(98,-183,654,729),7717=>array(91,-183,549,760),7718=>array(98,0,654,914),7719=>array(-9,0,549,913),7720=>array(8,-193,654,729),7721=>array(1,-193,549,760),7722=>array(98,-222,654,729),7723=>array(91,-222,549,760),7724=>array(0,-192,322,729),7725=>array(-22,-192,300,760),7726=>array(3,0,293,1044),7727=>array(-6,0,284,886),7728=>array(98,0,677,928),7729=>array(91,0,576,928),7730=>array(98,-183,677,729),7731=>array(91,-183,576,760),7732=>array(98,-156,677,729),7733=>array(91,-156,576,760),7734=>array(98,-183,552,729),7735=>array(98,-183,189,760),7736=>array(1,-183,552,927),7737=>array(-1,-183,291,899),7738=>array(98,-156,552,729),7739=>array(-6,-156,286,760),7740=>array(98,-240,552,729),7741=>array(-17,-240,295,760),7742=>array(98,0,765,928),7743=>array(91,0,889,800),7744=>array(98,0,765,914),7745=>array(91,0,889,760),7746=>array(98,-183,765,729),7747=>array(91,-183,889,560),7748=>array(98,0,650,914),7749=>array(91,0,549,760),7750=>array(98,-183,650,729),7751=>array(91,-183,549,560),7752=>array(98,-156,650,729),7753=>array(91,-156,549,560),7754=>array(98,-240,650,729),7755=>array(91,-240,549,560),7756=>array(56,-14,731,1044),7757=>array(55,-14,557,881),7758=>array(56,-14,731,1042),7759=>array(55,-14,557,882),7760=>array(56,-14,731,1044),7761=>array(55,-14,557,921),7762=>array(56,-14,731,1044),7763=>array(55,-14,557,921),7764=>array(98,0,569,928),7765=>array(91,-208,580,800),7766=>array(98,0,569,914),7767=>array(91,-208,580,760),7768=>array(98,0,666,913),7769=>array(91,0,411,760),7770=>array(98,-183,666,729),7771=>array(91,-183,411,560),7772=>array(98,-183,666,899),7773=>array(91,-183,411,745),7774=>array(98,-156,666,729),7775=>array(41,-156,411,560),7776=>array(66,-14,579,914),7777=>array(54,-14,472,760),7778=>array(66,-183,579,742),7779=>array(54,-183,472,560),7780=>array(66,-14,579,928),7781=>array(54,-14,485,800),7782=>array(66,-14,579,1042),7783=>array(54,-14,472,973),7784=>array(66,-183,579,914),7785=>array(54,-183,472,733),7786=>array(-3,0,614,914),7787=>array(27,0,368,942),7788=>array(-3,-183,614,729),7789=>array(27,-183,368,702),7790=>array(-3,-156,614,729),7791=>array(27,-156,390,702),7792=>array(-3,-240,614,729),7793=>array(27,-240,394,702),7794=>array(87,-183,645,729),7795=>array(85,-183,543,560),7796=>array(87,-192,645,729),7797=>array(85,-192,543,560),7798=>array(87,-213,645,729),7799=>array(85,-213,543,560),7800=>array(87,-14,645,1044),7801=>array(85,-14,543,990),7802=>array(87,-14,645,1025),7803=>array(85,-14,543,869),7804=>array(8,0,676,936),7805=>array(30,0,562,777),7806=>array(8,-183,676,729),7807=>array(30,-183,562,547),7808=>array(33,0,956,931),7809=>array(42,0,776,802),7810=>array(33,0,956,931),7811=>array(42,0,776,803),7812=>array(33,0,956,913),7813=>array(42,0,776,758),7814=>array(33,0,956,913),7815=>array(42,0,776,760),7816=>array(33,-183,956,729),7817=>array(42,-183,776,547),7818=>array(30,0,654,914),7819=>array(29,0,559,760),7820=>array(30,0,654,913),7821=>array(29,0,559,758),7822=>array(-2,0,613,914),7823=>array(30,-208,562,760),7824=>array(45,0,640,928),7825=>array(43,0,482,800),7826=>array(45,-183,640,729),7827=>array(43,-183,482,547),7828=>array(45,-156,640,729),7829=>array(43,-156,482,547),7830=>array(91,-156,549,760),7831=>array(2,0,368,913),7832=>array(42,0,776,878),7833=>array(30,-208,562,878),7834=>array(60,-14,672,760),7835=>array(23,0,371,942),7836=>array(1,0,371,760),7837=>array(23,0,371,760),7838=>array(87,-14,713,743),7839=>array(55,-14,557,742),7840=>array(8,-183,676,729),7841=>array(60,-183,522,560),7842=>array(8,0,676,992),7843=>array(60,-14,522,810),7844=>array(8,0,676,1028),7845=>array(60,-14,585,846),7846=>array(8,0,676,1028),7847=>array(60,-14,522,847),7848=>array(8,0,676,1044),7849=>array(60,-14,577,862),7850=>array(8,0,676,1057),7851=>array(60,-14,522,875),7852=>array(8,-183,676,928),7853=>array(60,-183,522,800),7854=>array(8,0,676,1044),7855=>array(60,-14,522,877),7856=>array(8,0,676,1044),7857=>array(60,-14,522,877),7858=>array(8,0,676,1068),7859=>array(60,-14,522,901),7860=>array(8,0,676,1043),7861=>array(60,-14,522,876),7862=>array(8,-183,676,946),7863=>array(60,-183,522,765),7864=>array(98,-183,568,729),7865=>array(55,-183,562,560),7866=>array(98,0,568,992),7867=>array(55,-14,562,810),7868=>array(98,0,568,921),7869=>array(55,-14,562,777),7870=>array(98,0,637,1028),7871=>array(55,-14,613,846),7872=>array(98,0,568,1028),7873=>array(55,-14,562,847),7874=>array(98,0,620,1044),7875=>array(55,-14,605,862),7876=>array(98,0,568,1057),7877=>array(55,-14,562,875),7878=>array(98,-183,568,928),7879=>array(55,-183,562,800),7880=>array(44,0,263,992),7881=>array(33,0,252,811),7882=>array(98,-183,197,729),7883=>array(93,-183,184,760),7884=>array(56,-183,731,742),7885=>array(55,-183,557,560),7886=>array(56,-14,731,992),7887=>array(55,-14,557,810),7888=>array(56,-14,731,1028),7889=>array(55,-14,601,846),7890=>array(56,-14,731,1028),7891=>array(55,-14,557,847),7892=>array(56,-14,731,1044),7893=>array(55,-14,592,862),7894=>array(56,-14,731,1057),7895=>array(55,-14,557,875),7896=>array(56,-183,731,928),7897=>array(55,-183,557,800),7898=>array(50,-14,764,927),7899=>array(58,-14,603,800),7900=>array(50,-14,764,927),7901=>array(58,-14,603,800),7902=>array(50,-14,764,992),7903=>array(58,-14,603,810),7904=>array(50,-14,764,921),7905=>array(58,-14,603,777),7906=>array(50,-183,764,760),7907=>array(58,-183,603,615),7908=>array(87,-183,645,729),7909=>array(85,-183,543,560),7910=>array(87,-14,645,992),7911=>array(85,-14,543,810),7912=>array(84,-4,796,927),7913=>array(86,-14,676,800),7914=>array(84,-4,796,927),7915=>array(86,-14,676,800),7916=>array(84,-4,796,992),7917=>array(86,-14,676,810),7918=>array(84,-4,796,921),7919=>array(86,-14,676,777),7920=>array(84,-183,796,760),7921=>array(86,-183,676,615),7922=>array(-2,0,613,931),7923=>array(30,-208,562,802),7924=>array(-2,-183,613,729),7925=>array(30,-208,562,547),7926=>array(-2,0,613,996),7927=>array(30,-208,562,813),7928=>array(-2,0,613,921),7929=>array(30,-208,562,777),7930=>array(98,0,764,729),7931=>array(16,0,462,760),7936=>array(55,-12,611,797),7937=>array(55,-12,611,797),7938=>array(55,-12,611,800),7939=>array(55,-12,611,800),7940=>array(55,-12,611,800),7941=>array(55,-12,611,800),7942=>array(55,-12,611,928),7943=>array(55,-12,611,928),7944=>array(8,0,676,797),7945=>array(8,0,676,797),7946=>array(2,0,869,800),7947=>array(3,0,869,800),7948=>array(3,0,761,800),7949=>array(2,0,793,800),7950=>array(3,0,700,928),7951=>array(2,0,734,928),7952=>array(65,-14,473,797),7953=>array(65,-14,473,797),7954=>array(65,-14,473,800),7955=>array(65,-14,473,800),7956=>array(65,-14,486,800),7957=>array(65,-14,501,800),7960=>array(3,0,647,797),7961=>array(3,0,647,797),7962=>array(2,0,902,800),7963=>array(3,0,911,800),7964=>array(3,0,834,800),7965=>array(2,0,864,800),7968=>array(91,-208,549,797),7969=>array(91,-208,549,797),7970=>array(91,-208,549,800),7971=>array(91,-208,549,800),7972=>array(91,-208,549,800),7973=>array(91,-208,549,800),7974=>array(91,-208,549,928),7975=>array(91,-208,549,928),7976=>array(3,0,739,797),7977=>array(3,0,737,797),7978=>array(2,0,988,800),7979=>array(3,0,991,800),7980=>array(3,0,929,800),7981=>array(2,0,953,800),7982=>array(3,0,835,928),7983=>array(2,0,849,928),7984=>array(76,0,304,797),7985=>array(71,0,304,797),7986=>array(-39,0,340,800),7987=>array(-34,0,347,800),7988=>array(2,0,362,800),7989=>array(-22,0,366,800),7990=>array(-26,0,304,928),7991=>array(-28,0,304,928),7992=>array(3,0,282,797),7993=>array(3,0,276,797),7994=>array(2,0,537,800),7995=>array(3,0,537,800),7996=>array(3,0,472,800),7997=>array(2,0,501,800),7998=>array(3,0,392,928),7999=>array(2,0,395,928),8000=>array(55,-14,557,797),8001=>array(55,-14,557,797),8002=>array(55,-14,557,800),8003=>array(55,-14,557,800),8004=>array(55,-14,557,800),8005=>array(55,-14,557,800),8008=>array(3,-14,748,797),8009=>array(3,-14,792,797),8010=>array(2,-14,1039,800),8011=>array(3,-14,1043,800),8012=>array(3,-14,882,800),8013=>array(2,-14,914,800),8016=>array(73,-14,521,797),8017=>array(73,-14,521,797),8018=>array(73,-14,521,800),8019=>array(73,-14,521,800),8020=>array(73,-14,521,800),8021=>array(73,-14,521,800),8022=>array(73,-14,521,928),8023=>array(73,-14,521,928),8025=>array(3,0,786,797),8027=>array(3,0,1000,800),8029=>array(2,0,1014,800),8031=>array(2,0,900,928),8032=>array(66,-14,769,797),8033=>array(66,-14,769,797),8034=>array(66,-14,769,800),8035=>array(66,-14,769,800),8036=>array(66,-14,769,800),8037=>array(66,-14,769,800),8038=>array(66,-14,769,928),8039=>array(66,-14,769,928),8040=>array(3,0,764,797),8041=>array(3,0,805,797),8042=>array(2,0,1051,800),8043=>array(3,0,1057,800),8044=>array(3,0,908,800),8045=>array(2,0,934,800),8046=>array(3,0,883,928),8047=>array(2,0,914,928),8048=>array(55,-12,611,800),8049=>array(55,-12,611,800),8050=>array(65,-14,473,800),8051=>array(65,-14,473,800),8052=>array(91,-208,549,800),8053=>array(91,-208,549,800),8054=>array(-56,0,304,800),8055=>array(81,0,324,800),8056=>array(55,-14,557,800),8057=>array(55,-14,557,800),8058=>array(73,-14,521,800),8059=>array(73,-14,521,800),8060=>array(66,-14,769,800),8061=>array(66,-14,769,800),8064=>array(55,-208,611,797),8065=>array(55,-208,611,797),8066=>array(55,-208,611,800),8067=>array(55,-208,611,800),8068=>array(55,-208,611,800),8069=>array(55,-208,611,800),8070=>array(55,-208,611,928),8071=>array(55,-208,611,928),8072=>array(8,-208,676,797),8073=>array(8,-208,676,797),8074=>array(2,-208,869,800),8075=>array(3,-208,869,800),8076=>array(3,-208,761,800),8077=>array(2,-208,793,800),8078=>array(3,-208,700,928),8079=>array(2,-208,734,928),8080=>array(91,-208,549,797),8081=>array(91,-208,549,797),8082=>array(91,-208,549,800),8083=>array(91,-208,549,800),8084=>array(91,-208,549,800),8085=>array(91,-208,549,800),8086=>array(91,-208,549,928),8087=>array(91,-208,549,928),8088=>array(3,-208,739,797),8089=>array(3,-208,737,797),8090=>array(2,-208,988,800),8091=>array(3,-208,991,800),8092=>array(3,-208,929,800),8093=>array(2,-208,953,800),8094=>array(3,-208,835,928),8095=>array(2,-208,849,928),8096=>array(66,-208,769,797),8097=>array(66,-208,769,797),8098=>array(66,-208,769,800),8099=>array(66,-208,769,800),8100=>array(66,-208,769,800),8101=>array(66,-208,769,800),8102=>array(66,-208,769,928),8103=>array(66,-208,769,928),8104=>array(3,-208,764,797),8105=>array(3,-208,805,797),8106=>array(2,-208,1051,800),8107=>array(3,-208,1057,800),8108=>array(3,-208,908,800),8109=>array(2,-208,934,800),8110=>array(3,-208,883,928),8111=>array(2,-208,914,928),8112=>array(55,-12,611,785),8113=>array(55,-12,611,745),8114=>array(55,-208,611,800),8115=>array(55,-208,611,559),8116=>array(55,-208,611,800),8118=>array(55,-12,611,777),8119=>array(55,-208,611,777),8120=>array(8,0,676,928),8121=>array(8,0,676,899),8122=>array(-2,0,708,800),8123=>array(8,0,676,800),8124=>array(8,-208,676,729),8125=>array(190,595,309,797),8126=>array(214,-208,321,-45),8127=>array(190,595,309,797),8128=>array(89,639,411,777),8129=>array(89,659,411,928),8130=>array(91,-208,549,800),8131=>array(91,-208,549,560),8132=>array(91,-208,549,800),8134=>array(91,-208,549,777),8135=>array(91,-208,549,777),8136=>array(-2,0,741,800),8137=>array(-12,0,682,800),8138=>array(-2,0,833,800),8139=>array(-6,0,765,800),8140=>array(98,-208,654,729),8141=>array(67,595,446,800),8142=>array(88,595,447,800),8143=>array(89,595,411,928),8144=>array(-10,0,304,785),8145=>array(-14,0,304,745),8146=>array(-20,0,304,978),8147=>array(2,0,313,978),8150=>array(-14,0,309,777),8151=>array(-13,0,310,928),8152=>array(-5,0,300,928),8153=>array(1,0,293,899),8154=>array(-2,0,377,800),8155=>array(-9,0,311,800),8157=>array(62,595,443,800),8158=>array(73,595,461,800),8159=>array(89,595,411,928),8160=>array(73,-14,521,785),8161=>array(73,-14,521,745),8162=>array(73,-14,521,978),8163=>array(73,-14,521,978),8164=>array(91,-208,580,797),8165=>array(91,-208,580,797),8166=>array(73,-14,521,777),8167=>array(73,-14,521,928),8168=>array(-2,0,613,928),8169=>array(-2,0,613,899),8170=>array(-2,0,847,800),8171=>array(-15,0,821,800),8172=>array(3,0,651,797),8173=>array(83,659,395,978),8174=>array(105,659,415,978),8175=>array(83,617,317,800),8178=>array(66,-208,769,800),8179=>array(66,-208,769,547),8180=>array(66,-208,769,800),8182=>array(66,-14,769,777),8183=>array(66,-208,769,777),8184=>array(-2,-14,885,800),8185=>array(-7,-14,750,800),8186=>array(-2,0,884,800),8187=>array(-18,0,752,800),8188=>array(38,-208,726,738),8189=>array(181,616,415,800),8190=>array(190,595,309,797),8208=>array(49,234,312,314),8209=>array(49,234,312,314),8210=>array(49,239,587,309),8211=>array(49,239,451,309),8212=>array(49,239,951,309),8213=>array(0,239,1000,309),8214=>array(127,-236,371,764),8215=>array(-10,-236,510,-9),8216=>array(85,489,228,729),8217=>array(87,499,230,729),8218=>array(85,-116,228,124),8219=>array(87,499,230,729),8220=>array(85,489,428,729),8221=>array(85,489,428,729),8222=>array(85,-116,428,124),8223=>array(85,489,428,729),8224=>array(28,-96,472,729),8225=>array(28,-96,472,729),8226=>array(150,227,440,516),8227=>array(150,188,479,555),8228=>array(115,0,219,124),8229=>array(115,0,552,124),8230=>array(115,0,885,124),8231=>array(107,302,210,426),8240=>array(55,-14,1287,742),8241=>array(55,-14,1681,742),8242=>array(20,547,203,729),8243=>array(20,547,350,729),8244=>array(20,547,496,729),8245=>array(20,547,203,729),8246=>array(20,547,350,729),8247=>array(20,547,496,729),8248=>array(5,-236,333,-30),8249=>array(77,69,306,517),8250=>array(94,69,323,517),8251=>array(95,2,740,725),8252=>array(72,0,414,729),8253=>array(72,0,461,742),8254=>array(-10,686,510,755),8255=>array(-43,-237,847,-60),8256=>array(-43,752,847,929),8257=>array(-42,-236,286,229),8258=>array(30,-29,970,814),8259=>array(108,313,400,421),8260=>array(-183,-14,350,742),8261=>array(86,-132,293,760),8262=>array(86,-132,293,760),8263=>array(36,0,886,742),8264=>array(72,0,661,742),8265=>array(72,0,661,742),8266=>array(49,-123,448,545),8267=>array(115,-96,566,729),8268=>array(105,220,395,509),8269=>array(105,220,395,509),8270=>array(30,-29,470,427),8271=>array(139,-116,282,517),8272=>array(-43,-237,847,929),8273=>array(30,-7,470,929),8274=>array(71,-93,408,729),8275=>array(49,228,951,399),8276=>array(-43,-240,847,-63),8277=>array(152,98,686,631),8278=>array(122,149,464,589),8279=>array(20,547,643,729),8280=>array(175,125,663,613),8281=>array(175,120,663,608),8282=>array(107,0,210,729),8283=>array(49,-138,749,867),8284=>array(55,0,783,729),8285=>array(107,39,210,655),8286=>array(107,8,210,683),8304=>array(42,319,366,742),8305=>array(60,326,116,751),8308=>array(31,326,369,734),8309=>array(50,319,353,734),8310=>array(45,319,369,742),8311=>array(53,326,354,734),8312=>array(43,319,365,742),8313=>array(41,319,364,742),8314=>array(67,326,461,677),8315=>array(67,479,461,525),8316=>array(67,422,461,581),8317=>array(54,252,195,751),8318=>array(50,252,191,751),8319=>array(57,326,346,640),8320=>array(42,-7,366,416),8321=>array(67,0,346,408),8322=>array(46,0,338,416),8323=>array(48,-7,350,416),8324=>array(31,0,369,408),8325=>array(50,-7,353,408),8326=>array(45,-7,369,416),8327=>array(53,0,354,408),8328=>array(43,-7,365,416),8329=>array(41,-7,364,416),8330=>array(67,0,461,351),8331=>array(67,152,461,199),8332=>array(67,96,461,254),8333=>array(54,-74,195,425),8334=>array(50,-74,191,425),8336=>array(38,-8,329,313),8337=>array(35,-8,354,313),8338=>array(35,-8,351,313),8339=>array(57,0,391,306),8340=>array(35,-8,354,313),8341=>array(57,0,346,425),8342=>array(57,0,363,425),8343=>array(60,0,116,425),8344=>array(57,0,560,313),8345=>array(57,0,346,313),8346=>array(57,-117,365,313),8347=>array(57,0,320,322),8348=>array(17,0,232,393),8352=>array(42,0,835,729),8353=>array(56,-44,593,778),8354=>array(47,-14,587,742),8355=>array(65,0,599,729),8356=>array(63,0,548,742),8357=>array(91,-93,889,640),8358=>array(57,0,691,729),8359=>array(98,-14,1226,729),8360=>array(98,-14,1025,729),8361=>array(29,0,960,729),8362=>array(46,-14,743,729),8363=>array(55,-156,619,760),8364=>array(0,-14,570,742),8365=>array(20,0,636,729),8366=>array(10,0,626,729),8367=>array(102,-222,1205,742),8368=>array(22,-14,569,742),8369=>array(33,0,579,729),8370=>array(45,-81,586,809),8371=>array(8,0,627,729),8372=>array(57,-14,717,742),8373=>array(81,-147,556,760),8376=>array(10,0,626,729),8377=>array(52,0,585,729),8378=>array(5,2,649,731),8400=>array(-491,635,-26,760),8401=>array(-470,635,-5,760),8406=>array(-470,560,-26,760),8407=>array(-470,560,-26,760),8411=>array(-491,560,-10,758),8412=>array(-586,560,86,758),8417=>array(-470,560,-26,760),8448=>array(33,-24,980,752),8449=>array(33,-24,999,752),8450=>array(56,-14,644,742),8451=>array(95,-14,1053,742),8452=>array(-21,0,637,729),8453=>array(29,-24,987,752),8454=>array(29,-24,1038,752),8455=>array(80,-14,560,742),8456=>array(54,-146,642,611),8457=>array(95,0,894,742),8459=>array(36,-14,943,748),8460=>array(1,-128,693,731),8461=>array(98,0,751,729),8462=>array(35,0,566,760),8463=>array(44,0,566,760),8464=>array(29,-15,432,742),8465=>array(52,-14,659,742),8466=>array(33,-14,679,743),8467=>array(-14,-14,353,742),8468=>array(16,-14,763,760),8469=>array(97,0,704,729),8470=>array(26,0,969,729),8471=>array(138,0,862,724),8472=>array(54,-221,658,495),8473=>array(98,0,666,729),8474=>array(56,-129,731,742),8475=>array(32,-9,764,774),8476=>array(41,-14,803,743),8477=>array(98,0,774,729),8478=>array(83,0,814,729),8479=>array(98,-107,666,847),8480=>array(126,443,770,730),8481=>array(-2,0,1023,547),8482=>array(144,447,784,729),8483=>array(8,-108,676,846),8484=>array(45,0,700,729),8485=>array(43,-213,523,760),8486=>array(38,0,726,738),8487=>array(38,-14,726,724),8488=>array(12,-149,573,783),8489=>array(33,0,255,547),8490=>array(98,0,677,729),8491=>array(8,0,676,928),8492=>array(45,0,734,772),8493=>array(63,-12,652,742),8494=>array(61,-12,793,647),8495=>array(42,-14,547,533),8496=>array(79,-14,565,742),8497=>array(41,-16,758,755),8498=>array(98,0,517,729),8499=>array(28,-28,1032,751),8500=>array(51,-12,411,395),8501=>array(50,-14,712,742),8502=>array(-2,-14,653,743),8503=>array(13,-35,407,742),8504=>array(42,-35,591,742),8505=>array(34,0,355,760),8506=>array(44,-21,915,654),8507=>array(74,0,1162,547),8508=>array(18,-8,685,547),8509=>array(0,-194,669,560),8510=>array(98,0,648,729),8511=>array(98,0,750,729),8512=>array(12,-192,791,719),8513=>array(80,-14,716,742),8514=>array(4,0,458,729),8515=>array(3,0,457,729),8516=>array(-2,0,613,729),8517=>array(42,0,786,729),8518=>array(44,-14,709,760),8519=>array(44,-14,572,560),8520=>array(39,0,313,760),8521=>array(-114,-208,313,760),8523=>array(29,-14,715,742),8526=>array(40,0,441,547),8528=>array(67,-14,922,742),8529=>array(67,-14,932,742),8530=>array(67,-14,1335,742),8531=>array(67,-14,918,742),8532=>array(46,-14,918,742),8533=>array(67,-14,921,742),8534=>array(46,-14,921,742),8535=>array(48,-14,921,742),8536=>array(31,-14,921,742),8537=>array(67,-14,937,742),8538=>array(50,-14,937,742),8539=>array(67,-14,933,742),8540=>array(48,-14,933,742),8541=>array(50,-14,933,742),8542=>array(53,-14,933,742),8543=>array(67,-14,751,742),8544=>array(98,0,197,729),8545=>array(98,0,394,729),8546=>array(98,0,591,729),8547=>array(98,0,915,729),8548=>array(8,0,676,729),8549=>array(8,0,824,729),8550=>array(8,0,1021,729),8551=>array(8,0,1219,729),8552=>array(98,0,886,729),8553=>array(30,0,654,729),8554=>array(30,0,835,729),8555=>array(30,0,1032,729),8556=>array(98,0,552,729),8557=>array(56,-14,644,742),8558=>array(98,0,711,729),8559=>array(98,0,765,729),8560=>array(94,0,184,760),8561=>array(94,0,364,760),8562=>array(94,0,543,760),8563=>array(94,0,782,760),8564=>array(30,0,562,547),8565=>array(30,0,717,760),8566=>array(30,0,897,760),8567=>array(30,0,1077,760),8568=>array(94,0,786,760),8569=>array(29,0,559,547),8570=>array(29,0,729,760),8571=>array(29,0,908,760),8572=>array(94,0,184,760),8573=>array(55,-14,488,560),8574=>array(55,-14,544,760),8575=>array(91,0,889,560),8576=>array(59,0,1186,729),8577=>array(98,0,711,729),8578=>array(59,0,1186,729),8579=>array(56,-14,644,742),8580=>array(62,-14,495,560),8581=>array(56,-208,644,742),8585=>array(42,-14,918,742),8592=>array(49,100,781,527),8593=>array(205,0,632,732),8594=>array(57,100,789,527),8595=>array(205,-3,632,729),8596=>array(49,100,789,527),8597=>array(205,-8,632,732),8598=>array(141,25,703,587),8599=>array(141,25,703,587),8600=>array(141,25,703,587),8601=>array(141,25,703,587),8602=>array(49,100,781,527),8603=>array(57,100,789,527),8604=>array(21,103,827,414),8605=>array(11,103,816,414),8606=>array(49,100,781,527),8607=>array(206,0,633,732),8608=>array(57,100,789,527),8609=>array(206,-3,633,729),8610=>array(49,100,781,527),8611=>array(57,100,789,527),8612=>array(49,100,781,527),8613=>array(206,0,632,732),8614=>array(57,100,789,527),8615=>array(206,-3,632,729),8616=>array(206,0,632,732),8617=>array(49,100,780,565),8618=>array(58,100,789,565),8619=>array(49,100,780,565),8620=>array(58,100,789,565),8621=>array(49,100,789,527),8622=>array(49,93,789,534),8623=>array(146,-2,702,730),8624=>array(169,0,629,743),8625=>array(209,0,669,743),8626=>array(169,-14,629,729),8627=>array(209,-14,669,729),8628=>array(233,-3,760,604),8629=>array(49,100,656,626),8630=>array(22,203,799,668),8631=>array(39,203,816,668),8632=>array(108,25,788,729),8633=>array(55,-46,783,673),8634=>array(103,62,762,680),8635=>array(77,62,736,680),8636=>array(49,272,781,527),8637=>array(49,100,781,355),8638=>array(377,0,632,732),8639=>array(205,0,460,732),8640=>array(57,272,789,527),8641=>array(57,100,789,355),8642=>array(377,0,632,732),8643=>array(205,0,460,732),8644=>array(49,-47,789,674),8645=>array(58,-3,779,732),8646=>array(49,-47,789,674),8647=>array(49,-47,781,674),8648=>array(59,0,779,732),8649=>array(58,-47,790,674),8650=>array(59,-3,779,729),8651=>array(49,7,789,620),8652=>array(49,7,789,620),8653=>array(49,100,781,527),8654=>array(49,94,789,533),8655=>array(57,100,789,527),8656=>array(49,100,781,527),8657=>array(206,0,633,732),8658=>array(57,100,789,527),8659=>array(206,-3,633,729),8660=>array(49,100,789,527),8661=>array(205,-8,633,732),8662=>array(141,-23,751,587),8663=>array(92,-23,703,587),8664=>array(92,25,703,636),8665=>array(141,25,751,636),8666=>array(49,100,781,527),8667=>array(57,100,789,527),8668=>array(49,100,781,527),8669=>array(57,100,789,527),8670=>array(205,0,632,732),8671=>array(205,-3,632,729),8672=>array(49,100,781,527),8673=>array(205,0,633,732),8674=>array(57,100,789,527),8675=>array(205,-3,633,729),8676=>array(52,99,781,528),8677=>array(57,99,786,528),8678=>array(27,65,781,562),8679=>array(171,0,667,754),8680=>array(35,65,789,562),8681=>array(171,-25,667,729),8682=>array(171,0,667,754),8683=>array(171,0,667,754),8684=>array(156,0,682,754),8685=>array(171,0,667,754),8686=>array(171,0,667,754),8687=>array(171,0,667,754),8688=>array(57,65,811,562),8689=>array(60,0,788,729),8690=>array(60,0,788,729),8691=>array(171,-25,667,754),8692=>array(57,100,789,527),8693=>array(58,-3,779,732),8694=>array(57,-193,789,820),8695=>array(49,94,781,533),8696=>array(57,94,789,533),8697=>array(49,94,789,533),8698=>array(49,94,781,533),8699=>array(57,94,789,533),8700=>array(49,94,789,533),8701=>array(27,96,781,531),8702=>array(57,96,811,531),8703=>array(27,96,811,531),8704=>array(8,0,676,729),8705=>array(66,-14,554,742),8706=>array(46,-14,471,662),8707=>array(98,0,568,729),8708=>array(98,-46,568,776),8709=>array(76,-10,795,710),8710=>array(-3,0,672,719),8711=>array(-3,0,672,719),8712=>array(85,-10,786,710),8713=>array(85,-138,786,835),8714=>array(106,76,612,550),8715=>array(85,-10,786,710),8716=>array(85,-138,786,835),8717=>array(106,76,612,550),8718=>array(146,0,490,485),8719=>array(76,-192,680,719),8720=>array(76,-192,680,719),8721=>array(12,-192,654,719),8722=>array(106,272,732,355),8723=>array(106,0,732,627),8724=>array(106,0,732,729),8725=>array(0,-93,337,729),8726=>array(192,-54,529,768),8727=>array(127,0,710,627),8728=>array(158,160,468,470),8729=>array(168,168,458,458),8730=>array(30,-20,637,811),8731=>array(30,-20,637,933),8732=>array(30,-20,637,924),8733=>array(107,112,607,487),8734=>array(107,112,726,487),8735=>array(138,99,700,661),8736=>array(85,0,786,729),8737=>array(85,-53,786,729),8738=>array(116,-3,732,727),8739=>array(211,-214,289,771),8740=>array(50,-214,451,771),8741=>array(133,-214,367,771),8742=>array(50,-214,451,771),8743=>array(129,0,603,579),8744=>array(129,0,603,579),8745=>array(129,0,603,579),8746=>array(129,0,603,579),8747=>array(57,-212,464,757),8748=>array(57,-212,732,757),8749=>array(57,-212,1000,757),8750=>array(57,-212,464,757),8751=>array(57,-212,732,757),8752=>array(57,-212,1000,757),8753=>array(57,-213,522,757),8754=>array(57,-212,514,757),8755=>array(57,-212,515,757),8756=>array(59,100,577,604),8757=>array(59,100,577,604),8758=>array(79,100,182,604),8759=>array(59,100,577,604),8760=>array(106,272,732,552),8761=>array(106,78,732,552),8762=>array(105,78,732,552),8763=>array(106,78,732,552),8764=>array(106,228,732,399),8765=>array(106,228,732,399),8766=>array(79,149,759,479),8767=>array(106,42,732,584),8768=>array(102,0,273,626),8769=>array(106,77,732,553),8770=>array(106,133,732,454),8771=>array(106,172,732,494),8772=>array(106,48,732,603),8773=>array(106,90,732,594),8774=>array(106,12,732,594),8775=>array(106,-5,732,657),8776=>array(106,133,732,494),8777=>array(106,2,732,625),8778=>array(106,90,732,598),8779=>array(106,59,732,602),8780=>array(106,90,732,594),8781=>array(105,105,732,521),8782=>array(106,26,732,601),8783=>array(106,172,732,601),8784=>array(106,172,732,625),8785=>array(106,1,732,625),8786=>array(106,2,733,625),8787=>array(106,2,733,625),8788=>array(101,151,899,476),8789=>array(100,151,900,475),8790=>array(106,172,732,454),8791=>array(106,172,732,760),8792=>array(106,172,732,662),8793=>array(106,172,732,812),8794=>array(106,172,732,812),8795=>array(106,172,732,849),8796=>array(106,172,732,854),8797=>array(106,172,732,764),8798=>array(106,172,732,760),8799=>array(106,172,732,856),8800=>array(106,19,732,608),8801=>array(106,90,732,537),8802=>array(106,-24,732,650),8803=>array(106,0,732,629),8804=>array(106,0,732,582),8805=>array(106,0,732,582),8806=>array(106,-83,732,638),8807=>array(106,-83,732,638),8808=>array(106,-164,732,638),8809=>array(106,-164,732,638),8810=>array(72,22,975,609),8811=>array(72,22,975,609),8812=>array(86,-132,378,759),8813=>array(105,13,732,613),8814=>array(106,2,732,674),8815=>array(106,-47,732,625),8816=>array(106,-102,732,667),8817=>array(106,-102,732,667),8818=>array(106,-55,732,582),8819=>array(106,-39,732,582),8820=>array(106,-105,732,664),8821=>array(106,-102,732,667),8822=>array(102,-87,732,686),8823=>array(102,-87,732,686),8824=>array(102,-197,732,797),8825=>array(102,-197,732,797),8826=>array(106,-38,732,664),8827=>array(106,-38,732,664),8828=>array(106,-105,732,667),8829=>array(106,-105,732,667),8830=>array(106,-85,732,667),8831=>array(106,-85,732,667),8832=>array(106,-61,732,764),8833=>array(106,-138,732,687),8834=>array(100,80,738,546),8835=>array(100,80,738,546),8836=>array(100,-96,738,726),8837=>array(100,-100,738,722),8838=>array(93,0,732,613),8839=>array(106,0,745,613),8840=>array(93,-116,732,730),8841=>array(106,-116,745,730),8842=>array(93,-73,732,614),8843=>array(93,-73,732,614),8844=>array(129,0,603,579),8845=>array(129,0,603,579),8846=>array(129,2,603,582),8847=>array(106,0,732,568),8848=>array(106,0,732,568),8849=>array(106,-83,732,630),8850=>array(106,-83,732,630),8851=>array(106,0,674,626),8852=>array(106,0,674,626),8853=>array(91,-14,747,643),8854=>array(91,-14,747,643),8855=>array(91,-14,747,643),8856=>array(91,-14,747,643),8857=>array(91,-14,747,643),8858=>array(91,-14,747,643),8859=>array(91,-14,747,643),8860=>array(91,-14,747,643),8861=>array(91,-14,747,643),8862=>array(91,-14,747,643),8863=>array(91,-14,747,643),8864=>array(91,-14,747,643),8865=>array(91,-14,747,643),8866=>array(85,0,786,700),8867=>array(85,0,786,700),8868=>array(85,0,786,700),8869=>array(85,0,786,700),8870=>array(85,0,436,700),8871=>array(85,0,436,700),8872=>array(85,0,786,700),8873=>array(85,0,786,700),8874=>array(85,0,786,700),8875=>array(85,0,786,700),8876=>array(85,-40,786,740),8877=>array(85,-40,786,740),8878=>array(85,-40,786,740),8879=>array(85,-40,786,740),8880=>array(106,-43,724,670),8881=>array(106,-43,724,670),8882=>array(106,15,732,612),8883=>array(106,15,732,612),8884=>array(106,-48,732,674),8885=>array(106,-48,732,674),8886=>array(59,175,941,454),8887=>array(59,175,941,454),8888=>array(48,175,790,454),8889=>array(59,-47,779,674),8890=>array(116,0,404,701),8891=>array(98,0,634,740),8892=>array(98,0,634,740),8893=>array(98,0,634,740),8894=>array(138,0,700,562),8895=>array(138,0,700,562),8896=>array(-3,-192,823,719),8897=>array(-3,-192,823,719),8898=>array(68,-192,752,719),8899=>array(68,-192,752,719),8900=>array(3,-233,491,807),8901=>array(107,285,210,409),8902=>array(122,149,504,512),8903=>array(106,15,732,613),8904=>array(106,-30,894,657),8905=>array(106,-30,894,657),8906=>array(106,-30,894,657),8907=>array(106,-30,894,657),8908=>array(106,-30,894,657),8909=>array(106,172,732,494),8910=>array(48,0,684,579),8911=>array(48,0,684,579),8912=>array(93,-3,732,630),8913=>array(106,-3,745,630),8914=>array(103,0,735,663),8915=>array(103,-14,735,649),8916=>array(186,0,652,729),8917=>array(106,-100,732,729),8918=>array(106,46,732,581),8919=>array(106,46,732,581),8920=>array(72,22,1350,609),8921=>array(72,22,1350,609),8922=>array(106,-228,732,854),8923=>array(106,-228,732,854),8924=>array(106,0,732,582),8925=>array(106,0,732,582),8926=>array(106,-105,732,667),8927=>array(106,-105,732,667),8928=>array(106,-178,732,764),8929=>array(106,-178,732,764),8930=>array(106,-141,732,767),8931=>array(106,-141,732,767),8932=>array(106,-94,732,619),8933=>array(106,-94,732,619),8934=>array(106,-138,732,582),8935=>array(106,-138,732,582),8936=>array(106,-169,732,667),8937=>array(110,-171,736,667),8938=>array(106,-130,732,756),8939=>array(106,-130,732,756),8940=>array(106,-189,732,815),8941=>array(104,-189,730,815),8942=>array(448,-93,551,715),8943=>array(115,249,884,373),8944=>array(115,-93,884,715),8945=>array(115,-93,884,715),8946=>array(43,-10,957,710),8947=>array(85,-10,786,710),8948=>array(106,76,612,550),8949=>array(85,-10,786,910),8950=>array(85,-10,786,853),8951=>array(106,76,612,686),8952=>array(85,-144,786,710),8953=>array(85,-10,786,710),8954=>array(43,-10,957,710),8955=>array(85,-10,786,710),8956=>array(106,76,612,550),8957=>array(85,-10,786,853),8958=>array(106,76,612,686),8959=>array(106,0,765,720),8960=>array(36,-18,567,514),8961=>array(56,162,540,443),8962=>array(71,0,563,596),8963=>array(205,481,632,732),8964=>array(205,0,632,251),8965=>array(205,0,632,406),8966=>array(205,0,632,513),8967=>array(154,-29,334,788),8968=>array(86,-132,293,760),8969=>array(97,-132,304,760),8970=>array(86,-132,293,760),8971=>array(97,-132,304,760),8972=>array(369,-77,759,313),8973=>array(49,-77,439,313),8974=>array(369,243,759,634),8975=>array(49,243,439,634),8976=>array(106,140,732,421),8977=>array(3,126,510,634),8984=>array(121,0,879,759),8985=>array(106,140,732,421),8988=>array(86,425,403,760),8989=>array(65,425,383,760),8990=>array(86,-70,403,264),8991=>array(65,-70,383,264),8992=>array(210,-250,497,928),8993=>array(21,-237,307,942),8996=>array(76,227,1076,575),8997=>array(76,0,1076,575),8998=>array(76,0,1414,760),8999=>array(76,0,1076,760),9000=>array(59,0,1385,729),9003=>array(0,0,1338,760),9004=>array(73,-91,800,748),9075=>array(81,0,304,547),9076=>array(91,-208,580,560),9077=>array(66,-14,769,547),9082=>array(55,-12,611,559),9085=>array(13,-228,745,102),9095=>array(76,0,1096,748),9108=>array(17,0,856,727),9115=>array(86,-252,414,946),9116=>array(86,-252,181,942),9117=>array(86,-240,414,942),9118=>array(86,-252,414,946),9119=>array(319,-252,414,942),9120=>array(86,-240,414,942),9121=>array(86,-252,414,928),9122=>array(86,-252,181,942),9123=>array(86,-240,414,942),9124=>array(86,-252,414,928),9125=>array(319,-252,414,935),9126=>array(86,-240,414,935),9127=>array(330,-261,668,928),9128=>array(82,-252,420,940),9129=>array(330,-240,668,940),9130=>array(330,-256,420,943),9131=>array(82,-261,420,928),9132=>array(330,-252,668,940),9133=>array(82,-240,420,940),9134=>array(210,-250,307,942),9166=>array(27,65,781,729),9167=>array(91,0,854,596),9187=>array(73,-91,800,748),9189=>array(3,75,766,444),9192=>array(43,-129,601,294),9250=>array(-62,-14,580,760),9251=>array(71,-228,563,102),9312=>array(74,-10,822,738),9313=>array(74,-10,822,738),9314=>array(74,-10,822,738),9315=>array(74,-10,822,738),9316=>array(74,-10,822,738),9317=>array(74,-10,822,738),9318=>array(74,-10,822,738),9319=>array(74,-10,822,738),9320=>array(74,-10,822,738),9321=>array(74,-10,822,738),9472=>array(-10,242,612,326),9473=>array(-10,200,612,368),9474=>array(262,-302,340,973),9475=>array(223,-302,379,973),9476=>array(-10,242,612,326),9477=>array(-10,200,612,368),9478=>array(262,-302,340,973),9479=>array(223,-302,379,973),9480=>array(-10,242,612,326),9481=>array(-10,200,612,368),9482=>array(262,-302,340,973),9483=>array(223,-302,379,973),9484=>array(262,-302,612,326),9485=>array(262,-302,612,368),9486=>array(223,-302,612,326),9487=>array(223,-302,612,368),9488=>array(-10,-302,340,326),9489=>array(-10,-302,340,368),9490=>array(-10,-302,379,326),9491=>array(-10,-302,379,368),9492=>array(262,242,612,973),9493=>array(262,200,612,973),9494=>array(223,242,612,973),9495=>array(223,200,612,973),9496=>array(-10,242,340,973),9497=>array(-10,200,340,973),9498=>array(-10,242,379,973),9499=>array(-10,200,379,973),9500=>array(262,-302,612,973),9501=>array(262,-302,612,973),9502=>array(223,-302,612,973),9503=>array(223,-302,612,973),9504=>array(223,-302,612,973),9505=>array(223,-302,612,973),9506=>array(223,-302,612,973),9507=>array(223,-302,612,973),9508=>array(-10,-302,340,973),9509=>array(-10,-302,340,973),9510=>array(-10,-302,379,973),9511=>array(-10,-302,379,973),9512=>array(-10,-302,379,973),9513=>array(-10,-302,379,973),9514=>array(-10,-302,379,973),9515=>array(-10,-302,379,973),9516=>array(-10,-302,612,326),9517=>array(-10,-302,612,368),9518=>array(-10,-302,612,368),9519=>array(-10,-302,612,368),9520=>array(-10,-302,612,326),9521=>array(-10,-302,612,368),9522=>array(-10,-302,612,368),9523=>array(-10,-302,612,368),9524=>array(-10,242,612,973),9525=>array(-10,200,612,973),9526=>array(-10,200,612,973),9527=>array(-10,200,612,973),9528=>array(-10,242,612,973),9529=>array(-10,200,612,973),9530=>array(-10,200,612,973),9531=>array(-10,200,612,973),9532=>array(-10,-302,612,973),9533=>array(-10,-302,612,973),9534=>array(-10,-302,612,973),9535=>array(-10,-302,612,973),9536=>array(-10,-302,612,973),9537=>array(-10,-302,612,973),9538=>array(-10,-302,612,973),9539=>array(-10,-302,612,973),9540=>array(-10,-302,612,973),9541=>array(-10,-302,612,973),9542=>array(-10,-302,612,973),9543=>array(-10,-302,612,973),9544=>array(-10,-302,612,973),9545=>array(-10,-302,612,973),9546=>array(-10,-302,612,973),9547=>array(-10,-302,612,973),9548=>array(-10,242,612,326),9549=>array(-10,200,612,368),9550=>array(262,-302,340,973),9551=>array(223,-302,379,973),9552=>array(-10,158,612,410),9553=>array(184,-302,418,973),9554=>array(262,-302,612,410),9555=>array(184,-302,612,326),9556=>array(184,-302,612,410),9557=>array(-10,-302,340,410),9558=>array(-10,-302,418,326),9559=>array(-10,-302,418,410),9560=>array(262,158,612,973),9561=>array(184,242,612,973),9562=>array(184,158,612,973),9563=>array(-10,158,340,973),9564=>array(-10,242,418,973),9565=>array(-10,158,418,973),9566=>array(262,-302,612,973),9567=>array(184,-302,612,973),9568=>array(184,-302,612,973),9569=>array(-10,-302,340,973),9570=>array(-10,-302,418,973),9571=>array(-10,-302,418,973),9572=>array(-10,-302,612,410),9573=>array(-10,-302,612,326),9574=>array(-10,-302,612,410),9575=>array(-10,158,612,973),9576=>array(-10,242,612,973),9577=>array(-10,158,612,973),9578=>array(-10,-302,612,973),9579=>array(-10,-302,612,973),9580=>array(-10,-302,612,973),9581=>array(262,-302,612,326),9582=>array(-10,-302,340,326),9583=>array(-10,242,340,973),9584=>array(262,242,612,973),9585=>array(-53,-302,655,973),9586=>array(-53,-302,655,973),9587=>array(-53,-302,655,973),9588=>array(-10,242,311,326),9589=>array(262,284,340,973),9590=>array(311,242,612,326),9591=>array(262,-302,340,284),9592=>array(-10,200,311,368),9593=>array(223,284,379,973),9594=>array(311,200,612,368),9595=>array(223,-302,379,284),9596=>array(-10,200,612,368),9597=>array(223,-302,379,973),9598=>array(-10,200,612,368),9599=>array(223,-302,379,973),9600=>array(-10,260,779,770),9601=>array(-10,-250,779,-123),9602=>array(-10,-250,779,-5),9603=>array(-10,-250,779,132),9604=>array(-10,-250,779,260),9605=>array(-10,-250,779,387),9606=>array(-10,-250,779,515),9607=>array(-10,-250,779,642),9608=>array(-10,-250,779,770),9609=>array(-10,-250,680,770),9610=>array(-10,-250,582,770),9611=>array(-10,-250,483,770),9612=>array(-10,-250,384,770),9613=>array(-10,-250,286,770),9614=>array(-10,-250,187,770),9615=>array(-10,-250,88,770),9616=>array(384,-250,778,770),9617=>array(-10,-250,680,770),9618=>array(-10,-250,775,770),9619=>array(-10,-250,779,770),9620=>array(-10,642,779,770),9621=>array(680,-250,778,770),9622=>array(-10,-250,385,260),9623=>array(384,-250,779,260),9624=>array(-10,260,385,770),9625=>array(-10,-250,779,770),9626=>array(-10,-250,779,770),9627=>array(-10,-250,779,770),9628=>array(-10,-250,779,770),9629=>array(384,260,779,770),9630=>array(-10,-250,779,770),9631=>array(-10,-250,779,770),9632=>array(91,-123,854,643),9633=>array(91,-123,854,643),9634=>array(91,-123,854,643),9635=>array(91,-123,854,643),9636=>array(91,-123,854,643),9637=>array(91,-123,854,643),9638=>array(91,-123,854,643),9639=>array(91,-123,854,643),9640=>array(91,-123,854,643),9641=>array(91,-123,854,643),9642=>array(91,11,587,509),9643=>array(91,11,587,509),9644=>array(91,75,854,444),9645=>array(91,75,854,444),9646=>array(91,-122,459,642),9647=>array(91,-122,459,642),9648=>array(3,75,766,444),9649=>array(3,75,766,444),9650=>array(3,-123,766,643),9651=>array(3,-123,766,643),9652=>array(3,11,499,509),9653=>array(3,11,499,509),9654=>array(3,-123,766,643),9655=>array(3,-123,766,643),9656=>array(3,11,499,509),9657=>array(3,11,499,509),9658=>array(3,11,766,509),9659=>array(3,11,766,509),9660=>array(3,-123,766,643),9661=>array(3,-123,766,643),9662=>array(3,11,499,509),9663=>array(3,11,499,509),9664=>array(3,-123,766,643),9665=>array(3,-123,766,643),9666=>array(3,11,499,509),9667=>array(3,11,499,509),9668=>array(3,11,766,509),9669=>array(3,11,766,509),9670=>array(3,-123,766,643),9671=>array(3,-123,766,643),9672=>array(3,-123,766,643),9673=>array(55,-125,818,645),9674=>array(3,-233,491,807),9675=>array(55,-125,818,645),9676=>array(56,-125,817,644),9677=>array(55,-125,818,645),9678=>array(55,-125,818,645),9679=>array(55,-123,818,641),9680=>array(55,-123,818,641),9681=>array(55,-123,818,641),9682=>array(55,-123,818,641),9683=>array(55,-123,818,641),9684=>array(55,-123,818,641),9685=>array(55,-123,818,641),9686=>array(55,-125,436,645),9687=>array(91,-125,472,645),9688=>array(91,-10,700,770),9689=>array(91,-250,879,770),9690=>array(91,260,879,770),9691=>array(91,-250,879,260),9692=>array(3,260,384,645),9693=>array(3,260,384,645),9694=>array(3,-125,384,260),9695=>array(3,-125,384,260),9696=>array(55,260,818,645),9697=>array(55,-125,818,260),9698=>array(3,-123,766,643),9699=>array(3,-123,766,643),9700=>array(3,-123,766,643),9701=>array(3,-123,766,643),9702=>array(150,227,440,516),9703=>array(91,-123,854,643),9704=>array(91,-123,854,643),9705=>array(91,-123,854,643),9706=>array(91,-123,854,643),9707=>array(91,-123,854,643),9708=>array(3,-123,766,643),9709=>array(3,-123,766,643),9710=>array(3,-123,766,643),9711=>array(55,-250,1064,770),9712=>array(91,-123,854,643),9713=>array(91,-123,854,643),9714=>array(91,-123,854,643),9715=>array(91,-123,854,643),9716=>array(55,-123,818,641),9717=>array(55,-123,818,641),9718=>array(55,-123,818,641),9719=>array(55,-123,818,641),9720=>array(3,-123,766,643),9721=>array(3,-123,766,643),9722=>array(3,-123,766,643),9723=>array(91,-66,739,585),9724=>array(91,-66,739,585),9725=>array(91,-17,642,537),9726=>array(91,-17,642,537),9727=>array(3,-123,766,643),9728=>array(83,0,813,729),9729=>array(51,-2,949,360),9730=>array(49,0,848,729),9731=>array(83,-0,813,927),9732=>array(64,0,833,880),9733=>array(65,-4,832,723),9734=>array(65,-4,832,723),9735=>array(83,2,490,729),9736=>array(83,0,813,731),9737=>array(83,0,813,730),9738=>array(61,0,828,727),9739=>array(61,0,828,723),9740=>array(61,-1,610,722),9741=>array(61,0,952,723),9742=>array(68,0,1177,729),9743=>array(71,0,1180,729),9744=>array(90,0,807,729),9745=>array(89,0,808,729),9746=>array(89,0,808,729),9747=>array(75,78,457,656),9748=>array(49,0,870,933),9749=>array(74,0,822,731),9750=>array(84,0,813,731),9751=>array(84,0,813,727),9752=>array(78,0,819,729),9753=>array(83,140,813,574),9754=>array(84,113,813,569),9755=>array(84,113,813,569),9756=>array(87,104,810,569),9757=>array(72,0,537,724),9758=>array(86,103,810,569),9759=>array(72,-3,537,720),9760=>array(61,0,835,730),9761=>array(84,0,813,730),9762=>array(83,0,813,730),9763=>array(49,0,848,730),9764=>array(49,-2,620,727),9765=>array(83,0,663,731),9766=>array(83,-1,566,731),9767=>array(83,0,701,911),9768=>array(83,0,462,730),9769=>array(83,-1,813,729),9770=>array(87,0,810,730),9771=>array(83,0,814,731),9772=>array(83,0,627,731),9773=>array(83,0,813,730),9774=>array(83,0,813,730),9775=>array(83,0,813,730),9776=>array(83,0,813,729),9777=>array(83,0,814,729),9778=>array(83,0,813,729),9779=>array(83,0,813,729),9780=>array(83,0,813,729),9781=>array(83,0,813,729),9782=>array(83,0,813,729),9783=>array(83,0,813,729),9784=>array(66,-11,831,735),9785=>array(83,-73,959,804),9786=>array(83,-73,959,804),9787=>array(83,-73,959,804),9788=>array(83,0,813,730),9789=>array(358,0,814,730),9790=>array(83,0,539,730),9791=>array(85,-102,528,732),9792=>array(85,-125,647,731),9793=>array(85,-14,647,843),9794=>array(79,-14,831,720),9795=>array(166,0,730,730),9796=>array(219,0,677,730),9797=>array(121,0,774,730),9798=>array(127,0,769,730),9799=>array(240,0,656,730),9800=>array(45,0,851,731),9801=>array(89,0,807,730),9802=>array(94,0,802,731),9803=>array(113,31,784,679),9804=>array(140,0,756,730),9805=>array(53,-180,843,730),9806=>array(83,52,813,653),9807=>array(34,-96,863,730),9808=>array(83,-0,813,730),9809=>array(94,0,802,730),9810=>array(86,153,810,579),9811=>array(157,0,739,730),9812=>array(98,0,798,730),9813=>array(110,0,786,730),9814=>array(167,-1,729,729),9815=>array(214,0,683,730),9816=>array(165,0,732,730),9817=>array(148,-0,748,730),9818=>array(98,0,798,730),9819=>array(110,0,786,730),9820=>array(167,-1,729,729),9821=>array(214,0,683,730),9822=>array(162,0,734,730),9823=>array(148,-0,748,730),9824=>array(158,0,738,729),9825=>array(90,0,806,727),9826=>array(168,0,728,729),9827=>array(111,0,785,729),9828=>array(157,0,739,729),9829=>array(89,0,808,729),9830=>array(168,0,728,729),9831=>array(111,0,785,732),9832=>array(105,-1,791,729),9833=>array(84,-5,339,729),9834=>array(84,-5,554,729),9835=>array(184,-102,712,729),9836=>array(92,-5,804,729),9837=>array(88,-3,392,731),9838=>array(84,0,273,731),9839=>array(84,0,400,731),9840=>array(84,0,664,731),9841=>array(64,0,701,731),9842=>array(84,0,813,709),9843=>array(76,16,820,731),9844=>array(76,16,820,731),9845=>array(76,16,820,731),9846=>array(76,16,820,731),9847=>array(76,16,820,731),9848=>array(76,16,820,731),9849=>array(76,16,820,731),9850=>array(76,16,820,731),9851=>array(84,0,812,704),9852=>array(83,0,814,731),9853=>array(83,0,814,731),9854=>array(83,0,814,731),9855=>array(149,1,747,731),9856=>array(73,0,797,725),9857=>array(73,0,797,725),9858=>array(73,0,797,725),9859=>array(73,0,797,725),9860=>array(73,0,797,725),9861=>array(73,0,797,725),9862=>array(83,0,813,731),9863=>array(83,0,813,731),9864=>array(83,0,813,731),9865=>array(83,0,813,731),9866=>array(83,0,813,98),9867=>array(83,0,813,98),9868=>array(83,0,813,413),9869=>array(83,0,813,413),9870=>array(83,0,813,413),9871=>array(83,0,813,413),9872=>array(168,3,728,731),9873=>array(168,3,728,731),9874=>array(52,0,844,731),9875=>array(97,-10,799,732),9876=>array(131,0,765,729),9877=>array(61,-10,479,732),9878=>array(59,-10,837,732),9879=>array(61,0,835,732),9880=>array(145,0,750,732),9881=>array(95,-17,802,727),9882=>array(128,-9,768,733),9883=>array(127,0,769,728),9884=>array(127,0,769,729),9888=>array(49,0,848,729),9889=>array(83,2,619,730),9890=>array(85,-125,919,731),9891=>array(79,-206,1023,720),9892=>array(85,-186,1109,856),9893=>array(85,-125,837,917),9894=>array(131,-14,727,869),9895=>array(101,-170,741,884),9896=>array(188,-14,650,869),9897=>array(4,133,829,596),9898=>array(187,133,651,596),9899=>array(187,133,651,596),9900=>array(247,194,591,537),9901=>array(174,194,664,537),9902=>array(41,169,797,560),9903=>array(5,194,833,536),9904=>array(103,237,757,540),9905=>array(211,42,626,698),9906=>array(85,-125,647,731),9907=>array(168,-125,646,731),9908=>array(86,-125,646,731),9909=>array(86,-125,646,731),9910=>array(59,-118,791,643),9911=>array(194,-104,595,710),9912=>array(158,-125,543,731),9920=>array(42,4,796,553),9921=>array(42,4,796,724),9922=>array(42,4,796,553),9923=>array(42,4,796,724),9954=>array(85,-14,647,843),9985=>array(11,190,803,635),9986=>array(42,141,784,588),9987=>array(11,94,803,539),9988=>array(36,119,824,613),9990=>array(42,-14,796,742),9991=>array(42,-14,796,742),9992=>array(59,21,782,708),9993=>array(64,107,773,622),9996=>array(212,0,561,742),9997=>array(21,83,802,678),9998=>array(89,75,724,710),9999=>array(26,198,819,530),10000=>array(89,75,724,710),10001=>array(43,185,757,544),10002=>array(67,209,757,520),10003=>array(150,97,667,630),10004=>array(116,87,721,631),10005=>array(126,72,711,657),10006=>array(85,31,752,698),10007=>array(118,-9,701,732),10008=>array(123,0,754,739),10009=>array(55,0,783,729),10010=>array(55,0,783,729),10011=>array(55,0,783,729),10012=>array(55,0,783,729),10013=>array(165,0,673,729),10014=>array(131,0,678,729),10015=>array(155,0,683,729),10016=>array(55,0,783,729),10017=>array(91,-13,747,744),10018=>array(41,-14,797,742),10019=>array(42,-12,796,742),10020=>array(41,-14,797,742),10021=>array(41,-13,797,743),10022=>array(42,-14,796,745),10023=>array(42,-14,796,745),10025=>array(23,-10,815,744),10026=>array(42,-14,796,742),10027=>array(23,-9,814,743),10028=>array(23,-10,815,744),10029=>array(23,-9,814,743),10030=>array(23,-9,814,743),10031=>array(23,-9,814,743),10032=>array(24,12,815,714),10033=>array(64,0,773,729),10034=>array(74,0,764,729),10035=>array(55,0,783,729),10036=>array(31,-14,787,742),10037=>array(41,-14,797,742),10038=>array(91,-14,747,742),10039=>array(41,-14,797,742),10040=>array(41,-14,797,742),10041=>array(41,-14,797,742),10042=>array(55,0,783,729),10043=>array(82,-14,756,742),10044=>array(82,-14,756,742),10045=>array(79,-14,759,742),10046=>array(79,-14,759,742),10047=>array(54,0,784,709),10048=>array(54,0,784,709),10049=>array(41,-14,797,742),10050=>array(42,-14,796,742),10051=>array(79,-14,759,742),10052=>array(89,0,749,729),10053=>array(76,0,762,729),10054=>array(63,2,773,729),10055=>array(79,-13,759,742),10056=>array(47,-13,791,730),10057=>array(47,-13,791,730),10058=>array(41,-13,797,743),10059=>array(41,-13,797,743),10061=>array(50,-10,847,738),10063=>array(60,-49,837,729),10064=>array(60,0,837,777),10065=>array(60,-49,837,729),10066=>array(60,0,837,777),10070=>array(83,-2,813,728),10072=>array(377,-240,460,760),10073=>array(336,-240,502,760),10074=>array(253,-240,585,760),10075=>array(85,395,264,729),10076=>array(59,395,237,729),10077=>array(85,395,479,729),10078=>array(59,395,453,729),10081=>array(155,-93,772,851),10082=>array(202,-17,636,742),10083=>array(163,-17,675,742),10084=>array(54,83,784,645),10085=>array(168,-1,729,729),10086=>array(62,21,724,702),10087=>array(78,169,759,564),10088=>array(196,-139,648,769),10089=>array(196,-139,648,769),10090=>array(264,-132,574,758),10091=>array(264,-132,574,758),10092=>array(215,-240,607,760),10093=>array(232,-240,623,760),10094=>array(142,-240,685,760),10095=>array(153,-240,696,760),10096=>array(167,-240,656,760),10097=>array(183,-240,672,760),10098=>array(346,-241,535,760),10099=>array(303,-241,492,760),10100=>array(175,-163,634,760),10101=>array(204,-163,663,760),10102=>array(74,-10,822,738),10103=>array(74,-10,822,738),10104=>array(74,-10,822,738),10105=>array(74,-10,822,738),10106=>array(74,-10,822,738),10107=>array(74,-10,822,738),10108=>array(74,-10,822,738),10109=>array(74,-10,822,738),10110=>array(74,-10,822,738),10111=>array(74,-10,822,738),10112=>array(4,-52,833,780),10113=>array(4,-52,833,780),10114=>array(4,-52,833,780),10115=>array(4,-52,833,780),10116=>array(4,-52,833,780),10117=>array(4,-52,833,780),10118=>array(4,-52,833,780),10119=>array(4,-52,833,780),10120=>array(4,-52,833,780),10121=>array(4,-52,833,780),10122=>array(4,-52,833,780),10123=>array(4,-52,833,780),10124=>array(4,-52,833,780),10125=>array(4,-52,833,780),10126=>array(4,-52,833,780),10127=>array(4,-52,833,780),10128=>array(4,-52,833,780),10129=>array(4,-52,833,780),10130=>array(4,-52,833,780),10131=>array(4,-52,833,780),10132=>array(57,75,789,552),10136=>array(123,55,682,614),10137=>array(57,100,789,527),10138=>array(123,13,682,572),10139=>array(57,129,789,498),10140=>array(57,57,764,570),10141=>array(57,100,789,527),10142=>array(57,100,789,527),10143=>array(57,100,789,527),10144=>array(57,100,789,527),10145=>array(57,65,811,562),10146=>array(111,94,789,533),10147=>array(111,94,789,533),10148=>array(111,-4,789,631),10149=>array(57,100,789,548),10150=>array(57,79,789,527),10151=>array(240,-7,606,634),10152=>array(57,100,789,527),10153=>array(57,75,765,552),10154=>array(57,75,765,552),10155=>array(21,12,794,586),10156=>array(21,12,794,586),10157=>array(135,0,774,574),10158=>array(135,0,774,574),10159=>array(62,49,799,574),10161=>array(62,49,799,574),10162=>array(154,-20,721,585),10163=>array(63,157,789,470),10164=>array(81,55,682,655),10165=>array(57,173,789,454),10166=>array(82,-29,682,572),10167=>array(82,55,682,655),10168=>array(57,172,789,455),10169=>array(82,-28,682,572),10170=>array(56,84,789,543),10171=>array(73,140,779,487),10172=>array(79,167,774,460),10173=>array(79,118,774,509),10174=>array(57,81,789,546),10181=>array(54,-163,352,769),10182=>array(39,-163,336,769),10208=>array(3,-233,491,807),10214=>array(86,-132,398,760),10215=>array(85,-132,398,760),10216=>array(89,-132,310,759),10217=>array(80,-132,301,759),10218=>array(89,-132,476,759),10219=>array(80,-132,467,759),10224=>array(44,0,794,732),10225=>array(43,-3,793,729),10226=>array(39,53,814,658),10227=>array(39,61,814,666),10228=>array(57,-14,1108,643),10229=>array(49,100,1376,527),10230=>array(57,100,1385,527),10231=>array(49,100,1385,527),10232=>array(49,100,1376,527),10233=>array(57,100,1385,527),10234=>array(49,100,1385,527),10235=>array(49,100,1376,527),10236=>array(57,100,1385,527),10237=>array(49,100,1376,527),10238=>array(57,100,1385,527),10239=>array(57,100,1385,527),10241=>array(146,635,293,781),10242=>array(146,358,293,504),10243=>array(146,358,293,781),10244=>array(146,82,293,228),10245=>array(146,82,293,781),10246=>array(146,82,293,504),10247=>array(146,82,293,781),10248=>array(439,635,586,781),10249=>array(146,635,586,781),10250=>array(146,358,586,781),10251=>array(146,358,586,781),10252=>array(146,82,586,781),10253=>array(146,82,586,781),10254=>array(146,82,586,781),10255=>array(146,82,586,781),10256=>array(439,358,586,504),10257=>array(146,358,586,781),10258=>array(146,358,586,504),10259=>array(146,358,586,781),10260=>array(146,82,586,504),10261=>array(146,82,586,781),10262=>array(146,82,586,504),10263=>array(146,82,586,781),10264=>array(439,358,586,781),10265=>array(146,358,586,781),10266=>array(146,358,586,781),10267=>array(146,358,586,781),10268=>array(146,82,586,781),10269=>array(146,82,586,781),10270=>array(146,82,586,781),10271=>array(146,82,586,781),10272=>array(439,82,586,228),10273=>array(146,82,586,781),10274=>array(146,82,586,504),10275=>array(146,82,586,781),10276=>array(146,82,586,228),10277=>array(146,82,586,781),10278=>array(146,82,586,504),10279=>array(146,82,586,781),10280=>array(439,82,586,781),10281=>array(146,82,586,781),10282=>array(146,82,586,781),10283=>array(146,82,586,781),10284=>array(146,82,586,781),10285=>array(146,82,586,781),10286=>array(146,82,586,781),10287=>array(146,82,586,781),10288=>array(439,82,586,504),10289=>array(146,82,586,781),10290=>array(146,82,586,504),10291=>array(146,82,586,781),10292=>array(146,82,586,504),10293=>array(146,82,586,781),10294=>array(146,82,586,504),10295=>array(146,82,586,781),10296=>array(439,82,586,781),10297=>array(146,82,586,781),10298=>array(146,82,586,781),10299=>array(146,82,586,781),10300=>array(146,82,586,781),10301=>array(146,82,586,781),10302=>array(146,82,586,781),10303=>array(146,82,586,781),10304=>array(146,-195,293,-49),10305=>array(146,-195,293,781),10306=>array(146,-195,293,504),10307=>array(146,-195,293,781),10308=>array(146,-195,293,228),10309=>array(146,-195,293,781),10310=>array(146,-195,293,504),10311=>array(146,-195,293,781),10312=>array(146,-195,586,781),10313=>array(146,-195,586,781),10314=>array(146,-195,586,781),10315=>array(146,-195,586,781),10316=>array(146,-195,586,781),10317=>array(146,-195,586,781),10318=>array(146,-195,586,781),10319=>array(146,-195,586,781),10320=>array(146,-195,586,504),10321=>array(146,-195,586,781),10322=>array(146,-195,586,504),10323=>array(146,-195,586,781),10324=>array(146,-195,586,504),10325=>array(146,-195,586,781),10326=>array(146,-195,586,504),10327=>array(146,-195,586,781),10328=>array(146,-195,586,781),10329=>array(146,-195,586,781),10330=>array(146,-195,586,781),10331=>array(146,-195,586,781),10332=>array(146,-195,586,781),10333=>array(146,-195,586,781),10334=>array(146,-195,586,781),10335=>array(146,-195,586,781),10336=>array(146,-195,586,228),10337=>array(146,-195,586,781),10338=>array(146,-195,586,504),10339=>array(146,-195,586,781),10340=>array(146,-195,586,228),10341=>array(146,-195,586,781),10342=>array(146,-195,586,504),10343=>array(146,-195,586,781),10344=>array(146,-195,586,781),10345=>array(146,-195,586,781),10346=>array(146,-195,586,781),10347=>array(146,-195,586,781),10348=>array(146,-195,586,781),10349=>array(146,-195,586,781),10350=>array(146,-195,586,781),10351=>array(146,-195,586,781),10352=>array(146,-195,586,504),10353=>array(146,-195,586,781),10354=>array(146,-195,586,504),10355=>array(146,-195,586,781),10356=>array(146,-195,586,504),10357=>array(146,-195,586,781),10358=>array(146,-195,586,504),10359=>array(146,-195,586,781),10360=>array(146,-195,586,781),10361=>array(146,-195,586,781),10362=>array(146,-195,586,781),10363=>array(146,-195,586,781),10364=>array(146,-195,586,781),10365=>array(146,-195,586,781),10366=>array(146,-195,586,781),10367=>array(146,-195,586,781),10368=>array(439,-195,586,-49),10369=>array(146,-195,586,781),10370=>array(146,-195,586,504),10371=>array(146,-195,586,781),10372=>array(146,-195,586,228),10373=>array(146,-195,586,781),10374=>array(146,-195,586,504),10375=>array(146,-195,586,781),10376=>array(439,-195,586,781),10377=>array(146,-195,586,781),10378=>array(146,-195,586,781),10379=>array(146,-195,586,781),10380=>array(146,-195,586,781),10381=>array(146,-195,586,781),10382=>array(146,-195,586,781),10383=>array(146,-195,586,781),10384=>array(439,-195,586,504),10385=>array(146,-195,586,781),10386=>array(146,-195,586,504),10387=>array(146,-195,586,781),10388=>array(146,-195,586,504),10389=>array(146,-195,586,781),10390=>array(146,-195,586,504),10391=>array(146,-195,586,781),10392=>array(439,-195,586,781),10393=>array(146,-195,586,781),10394=>array(146,-195,586,781),10395=>array(146,-195,586,781),10396=>array(146,-195,586,781),10397=>array(146,-195,586,781),10398=>array(146,-195,586,781),10399=>array(146,-195,586,781),10400=>array(439,-195,586,228),10401=>array(146,-195,586,781),10402=>array(146,-195,586,504),10403=>array(146,-195,586,781),10404=>array(146,-195,586,228),10405=>array(146,-195,586,781),10406=>array(146,-195,586,504),10407=>array(146,-195,586,781),10408=>array(439,-195,586,781),10409=>array(146,-195,586,781),10410=>array(146,-195,586,781),10411=>array(146,-195,586,781),10412=>array(146,-195,586,781),10413=>array(146,-195,586,781),10414=>array(146,-195,586,781),10415=>array(146,-195,586,781),10416=>array(439,-195,586,504),10417=>array(146,-195,586,781),10418=>array(146,-195,586,504),10419=>array(146,-195,586,781),10420=>array(146,-195,586,504),10421=>array(146,-195,586,781),10422=>array(146,-195,586,504),10423=>array(146,-195,586,781),10424=>array(439,-195,586,781),10425=>array(146,-195,586,781),10426=>array(146,-195,586,781),10427=>array(146,-195,586,781),10428=>array(146,-195,586,781),10429=>array(146,-195,586,781),10430=>array(146,-195,586,781),10431=>array(146,-195,586,781),10432=>array(146,-195,586,-49),10433=>array(146,-195,586,781),10434=>array(146,-195,586,504),10435=>array(146,-195,586,781),10436=>array(146,-195,586,228),10437=>array(146,-195,586,781),10438=>array(146,-195,586,504),10439=>array(146,-195,586,781),10440=>array(146,-195,586,781),10441=>array(146,-195,586,781),10442=>array(146,-195,586,781),10443=>array(146,-195,586,781),10444=>array(146,-195,586,781),10445=>array(146,-195,586,781),10446=>array(146,-195,586,781),10447=>array(146,-195,586,781),10448=>array(146,-195,586,504),10449=>array(146,-195,586,781),10450=>array(146,-195,586,504),10451=>array(146,-195,586,781),10452=>array(146,-195,586,504),10453=>array(146,-195,586,781),10454=>array(146,-195,586,504),10455=>array(146,-195,586,781),10456=>array(146,-195,586,781),10457=>array(146,-195,586,781),10458=>array(146,-195,586,781),10459=>array(146,-195,586,781),10460=>array(146,-195,586,781),10461=>array(146,-195,586,781),10462=>array(146,-195,586,781),10463=>array(146,-195,586,781),10464=>array(146,-195,586,228),10465=>array(146,-195,586,781),10466=>array(146,-195,586,504),10467=>array(146,-195,586,781),10468=>array(146,-195,586,228),10469=>array(146,-195,586,781),10470=>array(146,-195,586,504),10471=>array(146,-195,586,781),10472=>array(146,-195,586,781),10473=>array(146,-195,586,781),10474=>array(146,-195,586,781),10475=>array(146,-195,586,781),10476=>array(146,-195,586,781),10477=>array(146,-195,586,781),10478=>array(146,-195,586,781),10479=>array(146,-195,586,781),10480=>array(146,-195,586,504),10481=>array(146,-195,586,781),10482=>array(146,-195,586,504),10483=>array(146,-195,586,781),10484=>array(146,-195,586,504),10485=>array(146,-195,586,781),10486=>array(146,-195,586,504),10487=>array(146,-195,586,781),10488=>array(146,-195,586,781),10489=>array(146,-195,586,781),10490=>array(146,-195,586,781),10491=>array(146,-195,586,781),10492=>array(146,-195,586,781),10493=>array(146,-195,586,781),10494=>array(146,-195,586,781),10495=>array(146,-195,586,781),10502=>array(49,100,781,527),10503=>array(57,100,789,527),10506=>array(125,0,713,732),10507=>array(125,-3,713,729),10560=>array(39,63,644,838),10561=>array(39,63,644,838),10627=>array(125,-163,609,760),10628=>array(125,-163,609,760),10702=>array(106,-226,732,747),10703=>array(106,15,894,612),10704=>array(106,15,894,612),10705=>array(106,-30,894,657),10706=>array(106,-30,894,657),10707=>array(106,-30,894,657),10708=>array(106,-30,894,657),10709=>array(106,-30,894,657),10731=>array(3,-233,491,807),10746=>array(106,0,732,627),10747=>array(106,0,732,627),10752=>array(28,-198,972,748),10753=>array(28,-198,972,748),10754=>array(28,-198,972,748),10764=>array(57,-212,1268,757),10765=>array(57,-212,464,757),10766=>array(57,-212,464,757),10767=>array(57,-212,464,757),10768=>array(57,-212,464,757),10769=>array(57,-212,522,757),10770=>array(57,-212,464,757),10771=>array(57,-212,464,757),10772=>array(57,-212,555,757),10773=>array(57,-212,464,757),10774=>array(57,-212,464,757),10775=>array(-32,-212,553,757),10776=>array(57,-212,464,757),10777=>array(57,-212,464,757),10778=>array(57,-212,464,757),10779=>array(57,-212,469,872),10780=>array(52,-327,464,757),10799=>array(137,31,701,596),10858=>array(106,228,732,552),10859=>array(106,78,732,552),10877=>array(106,-123,732,581),10878=>array(106,-123,732,581),10879=>array(106,-123,733,581),10880=>array(106,-123,732,581),10881=>array(106,-123,732,644),10882=>array(106,-123,732,644),10883=>array(106,-123,733,759),10884=>array(106,-123,732,756),10885=>array(106,-132,732,663),10886=>array(106,-132,732,663),10887=>array(106,-121,732,582),10888=>array(106,-121,732,582),10889=>array(106,-204,732,663),10890=>array(106,-204,732,663),10891=>array(106,-311,732,791),10892=>array(106,-311,732,791),10893=>array(106,-124,732,663),10894=>array(106,-124,732,663),10895=>array(106,-241,732,756),10896=>array(106,-241,732,756),10897=>array(106,-229,732,730),10898=>array(106,-229,732,730),10899=>array(106,-224,732,741),10900=>array(106,-224,732,741),10901=>array(106,-61,732,644),10902=>array(106,-61,732,644),10903=>array(106,-61,733,644),10904=>array(106,-61,732,644),10905=>array(106,-36,732,685),10906=>array(106,-36,732,685),10907=>array(106,-31,732,725),10908=>array(106,-31,732,725),10909=>array(106,8,732,645),10910=>array(106,23,732,645),10911=>array(106,-176,732,729),10912=>array(106,-176,732,729),10926=>array(106,50,732,601),10927=>array(106,-24,732,667),10928=>array(106,-24,732,667),10929=>array(106,-145,732,667),10930=>array(106,-145,732,667),10931=>array(106,-121,732,662),10932=>array(106,-121,732,662),10933=>array(106,-195,732,662),10934=>array(106,-195,732,662),10935=>array(106,-191,732,693),10936=>array(106,-191,732,693),10937=>array(106,-259,732,693),10938=>array(106,-259,732,693),11001=>array(106,-171,732,585),11002=>array(106,-171,732,585),11008=>array(88,-27,703,587),11009=>array(141,-27,755,587),11010=>array(88,25,703,640),11011=>array(141,25,755,640),11012=>array(27,65,789,562),11013=>array(27,65,781,562),11014=>array(171,0,667,754),11015=>array(171,-25,667,729),11016=>array(88,-27,703,587),11017=>array(141,-27,755,587),11018=>array(88,25,703,640),11019=>array(141,25,755,640),11020=>array(27,65,789,562),11021=>array(171,-25,667,754),11022=>array(57,-3,790,355),11023=>array(57,272,790,630),11024=>array(35,-3,768,355),11025=>array(35,272,768,630),11026=>array(91,-123,854,643),11027=>array(91,-123,854,643),11028=>array(91,-123,854,643),11029=>array(91,-123,854,643),11030=>array(3,-123,766,643),11031=>array(3,-123,766,643),11032=>array(3,-123,766,643),11033=>array(3,-123,766,643),11034=>array(91,-123,854,643),11039=>array(18,-26,852,767),11040=>array(18,-26,852,767),11041=>array(73,-91,800,748),11042=>array(73,-91,800,748),11043=>array(17,-35,856,692),11044=>array(55,-250,1064,770),11091=>array(38,-47,832,788),11092=>array(38,-47,832,788),11360=>array(5,0,552,729),11361=>array(5,0,271,760),11362=>array(-20,0,552,729),11363=>array(5,0,569,729),11364=>array(98,-200,666,729),11365=>array(35,-46,576,592),11366=>array(-12,-93,384,822),11367=>array(98,-157,752,729),11368=>array(91,-138,639,760),11369=>array(98,-157,677,729),11370=>array(91,-138,576,760),11371=>array(45,-157,738,729),11372=>array(43,-138,572,547),11373=>array(56,-14,683,743),11374=>array(98,-200,765,729),11375=>array(8,0,676,729),11376=>array(56,-14,683,743),11377=>array(30,0,734,560),11378=>array(33,0,1128,742),11379=>array(42,0,961,560),11380=>array(51,0,562,587),11381=>array(98,0,555,729),11382=>array(94,0,477,547),11383=>array(55,-12,602,551),11385=>array(0,-13,320,760),11386=>array(55,-14,557,560),11387=>array(48,0,400,547),11388=>array(-11,-117,116,425),11389=>array(5,326,426,734),11390=>array(66,-242,598,742),11391=>array(45,-242,640,729),11520=>array(60,-63,544,547),11521=>array(24,-235,556,546),11522=>array(39,-235,535,546),11523=>array(62,-10,572,807),11524=>array(51,-235,537,546),11525=>array(39,-236,862,546),11526=>array(0,-8,575,816),11527=>array(53,0,900,546),11528=>array(69,0,542,546),11529=>array(51,-235,556,816),11530=>array(39,0,903,546),11531=>array(53,-8,595,816),11532=>array(39,0,544,816),11533=>array(51,0,887,546),11534=>array(51,0,556,546),11535=>array(69,-235,767,816),11536=>array(51,0,880,816),11537=>array(51,0,545,816),11538=>array(50,-235,536,546),11539=>array(51,-235,884,661),11540=>array(60,-235,892,546),11541=>array(49,-235,784,816),11542=>array(39,0,545,546),11543=>array(51,-235,556,547),11544=>array(51,-235,551,546),11545=>array(39,-235,541,816),11546=>array(42,-235,532,547),11547=>array(60,-9,596,816),11548=>array(39,-235,870,547),11549=>array(29,-235,545,546),11550=>array(47,-235,547,546),11551=>array(34,-235,547,567),11552=>array(39,0,875,546),11553=>array(49,-235,544,816),11554=>array(60,0,538,626),11555=>array(61,-235,553,816),11556=>array(51,-235,603,546),11557=>array(60,-8,841,816),11568=>array(55,-14,591,380),11569=>array(56,-14,832,742),11570=>array(56,-14,832,742),11571=>array(31,0,651,729),11572=>array(33,0,652,729),11573=>array(31,0,604,729),11574=>array(73,0,488,729),11575=>array(8,0,676,729),11576=>array(8,0,676,729),11577=>array(98,0,568,729),11578=>array(64,0,534,729),11579=>array(73,-14,609,742),11580=>array(107,0,811,729),11581=>array(45,0,665,729),11582=>array(73,0,437,729),11583=>array(45,0,665,729),11584=>array(56,-14,832,742),11585=>array(56,-52,832,781),11586=>array(73,0,197,729),11587=>array(20,0,610,729),11588=>array(98,0,654,729),11589=>array(30,0,654,729),11590=>array(73,0,454,729),11591=>array(45,0,629,729),11592=>array(73,301,571,426),11593=>array(98,0,568,729),11594=>array(54,0,448,729),11595=>array(54,-15,899,742),11596=>array(54,0,725,729),11597=>array(98,0,650,729),11598=>array(100,0,566,729),11599=>array(98,0,197,729),11600=>array(54,0,725,729),11601=>array(98,0,198,729),11602=>array(78,-14,705,729),11603=>array(48,-14,584,742),11604=>array(56,-14,832,742),11605=>array(56,-54,832,742),11606=>array(98,0,654,729),11607=>array(98,0,222,729),11608=>array(73,0,676,729),11609=>array(56,-14,832,742),11610=>array(56,-14,832,780),11611=>array(56,-14,681,742),11612=>array(49,0,719,729),11613=>array(30,0,654,729),11614=>array(56,-14,681,742),11615=>array(98,0,568,729),11616=>array(8,0,676,729),11617=>array(98,0,654,729),11618=>array(98,0,559,729),11619=>array(56,0,732,729),11620=>array(98,0,495,729),11621=>array(56,0,732,729),11631=>array(26,522,489,729),11800=>array(70,-14,459,728),11806=>array(106,78,732,399),11810=>array(86,403,293,760),11811=>array(97,403,304,760),11812=>array(86,-132,293,225),11813=>array(97,-132,304,225),11822=>array(72,0,461,742),19904=>array(83,-158,813,729),19905=>array(83,-158,813,729),19906=>array(83,-158,813,729),19907=>array(83,-158,813,729),19908=>array(83,-158,813,729),19909=>array(83,-158,813,729),19910=>array(83,-158,813,729),19911=>array(83,-158,813,729),19912=>array(83,-158,813,729),19913=>array(83,-158,814,729),19914=>array(83,-158,813,729),19915=>array(83,-158,813,729),19916=>array(83,-158,813,729),19917=>array(83,-158,813,729),19918=>array(83,-158,813,729),19919=>array(83,-158,813,729),19920=>array(83,-158,814,729),19921=>array(83,-158,813,729),19922=>array(83,-158,814,729),19923=>array(83,-158,813,729),19924=>array(83,-158,813,729),19925=>array(83,-158,813,729),19926=>array(83,-158,813,729),19927=>array(83,-158,813,729),19928=>array(83,-158,813,729),19929=>array(83,-158,813,729),19930=>array(83,-158,813,729),19931=>array(83,-158,814,729),19932=>array(83,-158,813,729),19933=>array(83,-158,813,729),19934=>array(83,-158,814,729),19935=>array(83,-158,813,729),19936=>array(83,-158,813,729),19937=>array(83,-158,813,729),19938=>array(83,-158,813,729),19939=>array(83,-158,813,729),19940=>array(83,-158,813,729),19941=>array(83,-158,814,729),19942=>array(83,-158,813,729),19943=>array(83,-158,813,729),19944=>array(83,-158,814,729),19945=>array(83,-158,813,729),19946=>array(83,-158,814,729),19947=>array(83,-158,813,729),19948=>array(83,-158,814,729),19949=>array(83,-158,813,729),19950=>array(83,-158,814,729),19951=>array(83,-158,813,729),19952=>array(83,-158,814,729),19953=>array(83,-158,813,729),19954=>array(83,-158,813,729),19955=>array(83,-158,813,729),19956=>array(83,-158,813,729),19957=>array(83,-158,814,729),19958=>array(83,-158,813,729),19959=>array(83,-158,813,729),19960=>array(83,-158,813,729),19961=>array(83,-158,814,729),19962=>array(83,-158,813,729),19963=>array(83,-158,814,729),19964=>array(83,-158,814,729),19965=>array(83,-158,813,729),19966=>array(83,-158,813,729),19967=>array(83,-158,813,729),42192=>array(98,0,615,729),42193=>array(98,0,569,729),42194=>array(34,0,505,729),42195=>array(98,0,711,729),42196=>array(-3,0,614,729),42197=>array(-3,0,614,729),42198=>array(56,-14,693,742),42199=>array(98,0,677,729),42200=>array(-21,0,558,729),42201=>array(0,-14,414,729),42202=>array(56,-14,644,742),42203=>array(56,-14,644,742),42204=>array(45,0,640,729),42205=>array(98,0,517,729),42206=>array(98,0,517,729),42207=>array(98,0,765,729),42208=>array(98,0,650,729),42209=>array(98,0,552,729),42210=>array(66,-14,579,742),42211=>array(98,0,666,729),42212=>array(29,0,597,729),42213=>array(8,0,676,729),42214=>array(8,0,676,729),42215=>array(98,0,654,729),42216=>array(80,-14,716,742),42217=>array(98,0,512,743),42218=>array(33,0,956,729),42219=>array(30,0,654,729),42220=>array(-2,0,613,729),42221=>array(71,0,588,729),42222=>array(8,0,676,729),42223=>array(8,0,676,729),42224=>array(98,0,568,729),42225=>array(64,0,534,729),42226=>array(98,0,197,729),42227=>array(56,-14,731,742),42228=>array(87,-14,645,729),42229=>array(87,0,645,743),42230=>array(4,0,458,729),42231=>array(56,0,669,729),42232=>array(85,0,214,155),42233=>array(71,-156,214,155),42234=>array(85,0,511,155),42235=>array(85,-156,511,155),42236=>array(71,-156,214,517),42237=>array(85,0,214,517),42238=>array(85,0,502,354),42239=>array(85,172,502,454),42564=>array(56,-14,569,742),42565=>array(49,-14,467,560),42566=>array(98,0,347,729),42567=>array(81,0,304,547),42572=>array(58,-14,1122,645),42573=>array(74,-14,954,471),42576=>array(29,0,931,729),42577=>array(30,0,817,560),42580=>array(56,-14,977,742),42581=>array(55,-14,748,560),42582=>array(103,0,968,729),42583=>array(94,-14,752,560),42594=>array(49,-157,1004,729),42595=>array(52,-138,863,547),42596=>array(41,0,1008,729),42597=>array(37,0,852,547),42598=>array(98,0,1120,729),42599=>array(91,0,959,547),42600=>array(56,-14,731,742),42601=>array(55,-14,557,560),42602=>array(56,-14,799,742),42603=>array(55,-14,658,560),42604=>array(56,-14,1302,742),42605=>array(55,-14,964,560),42606=>array(28,-208,851,743),42634=>array(-3,-200,758,729),42635=>array(29,-208,660,547),42636=>array(-3,0,614,729),42637=>array(29,0,553,547),42644=>array(85,0,587,729),42645=>array(91,0,549,760),42760=>array(104,0,389,668),42761=>array(104,0,389,668),42762=>array(104,0,389,668),42763=>array(104,0,389,668),42764=>array(104,0,389,668),42765=>array(104,0,389,668),42766=>array(104,0,389,668),42767=>array(104,0,389,668),42768=>array(104,0,389,668),42769=>array(104,0,389,668),42770=>array(104,0,389,668),42771=>array(104,0,389,668),42772=>array(104,0,389,668),42773=>array(104,0,389,668),42774=>array(104,0,389,668),42779=>array(50,326,319,736),42780=>array(50,324,319,734),42781=>array(95,326,158,734),42782=>array(95,326,158,734),42783=>array(95,0,158,408),42786=>array(67,0,350,729),42787=>array(67,0,321,547),42788=>array(56,224,411,742),42789=>array(56,42,411,560),42790=>array(98,-200,654,729),42791=>array(91,-208,549,760),42792=>array(-3,-213,819,729),42793=>array(27,-213,650,702),42794=>array(80,-14,560,742),42795=>array(65,-200,473,561),42800=>array(91,0,437,547),42801=>array(54,-14,472,560),42802=>array(8,0,1241,729),42803=>array(60,-14,894,560),42804=>array(8,-14,1147,742),42805=>array(60,-14,935,560),42806=>array(8,-14,1055,729),42807=>array(60,-14,890,560),42808=>array(8,0,963,729),42809=>array(60,-14,788,560),42810=>array(8,0,963,729),42811=>array(60,-14,788,560),42812=>array(8,-208,951,729),42813=>array(60,-208,788,560),42814=>array(56,-14,644,742),42815=>array(62,-14,495,560),42816=>array(5,0,677,729),42817=>array(7,0,580,760),42822=>array(98,0,675,729),42823=>array(94,0,298,760),42824=>array(41,0,576,729),42825=>array(59,0,368,760),42826=>array(5,-14,802,742),42827=>array(5,-14,694,560),42830=>array(56,-14,1302,742),42831=>array(55,-14,964,560),42832=>array(5,0,569,729),42833=>array(-2,-208,580,560),42834=>array(24,0,700,729),42835=>array(24,-208,720,560),42838=>array(56,-178,731,742),42839=>array(55,-208,637,560),42852=>array(5,0,569,729),42853=>array(-2,-208,580,760),42854=>array(5,0,569,729),42855=>array(-2,-208,580,760),42880=>array(5,0,459,729),42881=>array(94,-208,184,560),42882=>array(98,-208,637,742),42883=>array(91,-208,549,560),42889=>array(117,0,220,517),42890=>array(78,161,298,380),42891=>array(151,235,250,729),42892=>array(96,458,179,729),42893=>array(85,0,587,729),42894=>array(38,-208,416,760),42896=>array(98,-157,733,729),42897=>array(91,-138,621,560),42912=>array(2,-14,778,742),42913=>array(2,-208,633,560),42914=>array(2,0,677,729),42915=>array(2,0,577,760),42916=>array(2,0,746,729),42917=>array(2,0,633,560),42918=>array(2,0,693,729),42919=>array(2,0,411,560),42920=>array(2,-14,633,742),42921=>array(2,-14,519,560),42922=>array(-51,0,703,729),43002=>array(91,0,824,547),43003=>array(58,0,477,729),43004=>array(34,0,505,729),43005=>array(98,0,765,729),43006=>array(98,0,197,928),43007=>array(33,0,1167,729),61184=>array(95,602,323,668),61185=>array(69,451,342,668),61186=>array(54,301,361,668),61187=>array(47,150,368,668),61188=>array(44,0,372,668),61189=>array(69,451,342,668),61190=>array(95,451,323,518),61191=>array(69,301,342,518),61192=>array(54,150,361,518),61193=>array(47,0,368,518),61194=>array(54,301,361,668),61195=>array(69,301,342,518),61196=>array(95,301,323,367),61197=>array(69,150,342,367),61198=>array(54,0,361,367),61199=>array(47,150,368,668),61200=>array(54,150,361,518),61201=>array(69,150,342,367),61202=>array(95,150,323,217),61203=>array(69,0,342,217),61204=>array(44,0,372,668),61205=>array(47,0,368,518),61206=>array(54,0,361,367),61207=>array(69,0,342,217),61208=>array(95,0,323,66),61209=>array(104,0,171,668),61440=>array(73,0,903,732),61441=>array(73,0,903,732),61442=>array(73,0,903,732),61443=>array(73,0,903,732),62464=>array(54,-15,526,828),62465=>array(54,-15,526,828),62466=>array(54,-15,570,837),62467=>array(54,0,835,837),62468=>array(54,-15,526,837),62469=>array(54,-15,526,837),62470=>array(54,-15,599,837),62471=>array(54,-15,828,837),62472=>array(54,0,501,837),62473=>array(54,-15,526,828),62474=>array(54,0,1115,837),62475=>array(54,-15,525,837),62476=>array(63,-15,536,828),62477=>array(54,0,815,837),62478=>array(54,-15,526,828),62479=>array(54,-15,526,844),62480=>array(54,0,860,837),62481=>array(63,-15,536,828),62482=>array(54,-15,677,837),62483=>array(24,-15,519,837),62484=>array(54,-15,818,837),62485=>array(54,-15,526,828),62486=>array(54,-15,841,837),62487=>array(54,-15,525,829),62488=>array(54,-15,525,837),62489=>array(64,0,536,837),62490=>array(55,-15,595,828),62491=>array(54,-15,525,828),62492=>array(64,-15,536,837),62493=>array(54,-15,545,828),62494=>array(63,-15,536,828),62495=>array(24,-15,492,837),62496=>array(54,-15,526,837),62497=>array(59,-15,530,837),62498=>array(54,-79,526,837),62499=>array(54,-15,525,838),62500=>array(54,-15,532,838),62501=>array(54,-15,594,837),62502=>array(54,-15,901,838),62504=>array(60,-235,872,816),62505=>array(49,-230,759,853),62506=>array(49,-15,459,765),62507=>array(49,-15,459,777),62508=>array(49,-15,459,875),62509=>array(49,-15,459,818),62510=>array(49,-15,459,887),62511=>array(49,-15,459,809),62512=>array(49,-236,449,765),62513=>array(49,-236,449,799),62514=>array(49,-236,449,901),62515=>array(49,-236,449,809),62516=>array(49,0,469,765),62517=>array(49,0,469,799),62518=>array(49,0,469,809),62519=>array(49,-0,737,765),62520=>array(49,-0,737,777),62521=>array(49,-0,737,895),62522=>array(49,-0,737,799),62523=>array(49,-0,737,809),62524=>array(29,-236,488,765),62525=>array(29,-236,488,777),62526=>array(29,-236,488,904),62527=>array(29,-236,488,799),62528=>array(29,-236,488,809),62529=>array(29,-236,488,852),63173=>array(55,-14,557,760),64256=>array(23,0,708,760),64257=>array(23,0,536,760),64258=>array(23,0,536,760),64259=>array(23,0,873,760),64260=>array(23,0,873,760),64261=>array(23,0,662,760),64262=>array(54,-14,837,742),64275=>array(83,-14,1111,760),64276=>array(85,-14,1111,760),64277=>array(85,-208,1111,760),64278=>array(85,-208,1111,760),64279=>array(85,-208,1451,760),64285=>array(66,44,157,547),64286=>array(167,625,473,765),64287=>array(36,44,329,547),64288=>array(38,0,562,547),64289=>array(85,0,772,547),64290=>array(43,0,717,547),64291=>array(91,0,764,547),64292=>array(43,0,716,547),64293=>array(43,0,716,760),64294=>array(91,0,764,547),64295=>array(43,0,716,547),64296=>array(47,-4,716,547),64297=>array(106,272,732,627),64298=>array(43,0,666,698),64299=>array(38,0,666,698),64300=>array(43,0,666,698),64301=>array(43,0,666,698),64302=>array(91,-159,578,547),64303=>array(91,-193,578,547),64304=>array(91,-159,578,547),64305=>array(43,0,535,547),64306=>array(43,-5,383,547),64307=>array(43,0,511,547),64308=>array(91,0,563,547),64309=>array(43,0,265,547),64310=>array(43,0,363,547),64312=>array(90,-14,593,552),64313=>array(43,204,264,547),64314=>array(43,-208,446,547),64315=>array(43,0,474,547),64316=>array(43,0,492,729),64318=>array(43,0,588,555),64320=>array(43,0,309,547),64321=>array(90,-14,593,547),64323=>array(91,-208,549,547),64324=>array(91,0,569,547),64326=>array(43,0,502,547),64327=>array(91,-208,633,546),64328=>array(43,0,474,547),64329=>array(43,0,666,547),64330=>array(10,-4,566,547),64331=>array(91,0,182,698),64332=>array(43,0,535,698),64333=>array(43,0,474,698),64334=>array(91,0,569,698),64335=>array(43,0,571,760),64338=>array(63,-244,865,327),64339=>array(63,-244,992,327),64340=>array(-10,-244,191,293),64341=>array(-10,-244,312,293),64342=>array(63,-244,865,327),64343=>array(63,-244,992,327),64344=>array(-10,-244,244,293),64345=>array(-10,-244,312,293),64346=>array(63,-244,865,327),64347=>array(63,-244,992,327),64348=>array(-10,-244,244,293),64349=>array(-10,-244,312,293),64350=>array(63,-10,865,513),64351=>array(63,-10,992,513),64352=>array(-10,0,191,610),64353=>array(-10,0,312,610),64354=>array(63,-10,865,513),64355=>array(63,-10,992,513),64356=>array(-10,0,244,610),64357=>array(-10,0,312,610),64358=>array(63,-10,865,575),64359=>array(63,-10,992,575),64360=>array(-10,0,273,672),64361=>array(-10,0,312,672),64362=>array(63,-45,952,757),64363=>array(63,-44,1045,659),64364=>array(-10,0,406,757),64365=>array(-10,0,516,684),64366=>array(63,-45,952,757),64367=>array(63,-44,1045,659),64368=>array(-10,0,406,757),64369=>array(-10,0,516,684),64370=>array(77,-244,645,425),64371=>array(77,-244,655,425),64372=>array(-10,-220,545,398),64373=>array(-10,-220,655,398),64374=>array(77,-244,645,425),64375=>array(77,-244,655,425),64376=>array(-10,-98,545,398),64377=>array(-10,-98,655,398),64378=>array(77,-244,645,425),64379=>array(77,-244,655,425),64380=>array(-10,-220,545,398),64381=>array(-10,-220,655,398),64382=>array(77,-244,645,425),64383=>array(77,-244,655,425),64384=>array(-10,-220,545,398),64385=>array(-10,-220,655,398),64386=>array(61,-146,388,415),64387=>array(61,-146,535,415),64388=>array(61,-19,388,586),64389=>array(61,-19,535,586),64390=>array(61,-19,388,708),64391=>array(61,-19,535,708),64392=>array(61,-19,388,746),64393=>array(61,-19,535,746),64394=>array(-42,-244,439,586),64395=>array(-42,-244,562,586),64396=>array(-42,-244,469,648),64397=>array(-42,-244,562,648),64398=>array(63,-43,895,760),64399=>array(63,-43,981,760),64400=>array(-10,0,476,760),64401=>array(-10,0,562,760),64402=>array(63,-43,895,896),64403=>array(63,-43,981,896),64404=>array(-10,0,476,896),64405=>array(-10,0,562,896),64406=>array(63,-293,895,896),64407=>array(63,-293,981,896),64408=>array(-10,-269,476,896),64409=>array(-10,-269,562,896),64410=>array(63,-43,895,903),64411=>array(63,-43,981,903),64412=>array(-10,0,476,903),64413=>array(-10,0,562,903),64414=>array(72,-162,660,366),64415=>array(72,-244,771,284),64416=>array(72,-162,660,636),64417=>array(72,-244,771,514),64418=>array(-10,0,273,672),64419=>array(-10,0,312,672),64426=>array(70,-33,638,487),64427=>array(70,-244,642,333),64428=>array(-10,-33,467,487),64429=>array(-10,-244,471,333),64467=>array(70,-27,722,854),64468=>array(70,-27,853,854),64469=>array(-10,0,476,928),64470=>array(-10,0,562,928),64473=>array(-42,-244,406,556),64474=>array(-42,-244,526,556),64488=>array(-10,0,191,293),64489=>array(-10,0,312,293),64508=>array(63,-131,719,411),64509=>array(63,-133,843,251),64510=>array(-10,-146,244,293),64511=>array(-10,-146,312,293),65056=>array(-445,752,0,929),65057=>array(0,752,445,929),65058=>array(-354,756,0,894),65059=>array(0,756,354,894),65136=>array(4,591,289,825),65137=>array(-10,0,303,825),65138=>array(4,591,289,874),65139=>array(51,0,271,177),65140=>array(4,-239,289,-5),65142=>array(4,591,289,708),65143=>array(-10,0,303,708),65144=>array(4,590,289,874),65145=>array(-10,0,303,874),65146=>array(4,-137,289,-20),65147=>array(-10,-137,303,90),65148=>array(-6,599,299,869),65149=>array(-10,0,303,869),65150=>array(12,610,279,878),65151=>array(-10,0,303,878),65152=>array(80,42,390,483),65153=>array(-37,0,315,939),65154=>array(-37,0,315,939),65155=>array(53,0,220,1028),65156=>array(53,0,314,1028),65157=>array(-42,-244,406,588),65158=>array(-42,-244,526,588),65159=>array(53,-244,220,760),65160=>array(53,-244,314,760),65161=>array(63,-131,719,588),65162=>array(63,-133,843,466),65163=>array(-10,0,227,613),65164=>array(-10,0,312,613),65165=>array(94,0,184,760),65166=>array(94,0,314,760),65167=>array(63,-171,865,327),65168=>array(63,-171,992,327),65169=>array(-10,-146,191,293),65170=>array(-10,-146,312,293),65171=>array(68,-28,453,513),65172=>array(71,0,546,513),65173=>array(63,-10,865,391),65174=>array(63,-10,992,391),65175=>array(-10,0,244,488),65176=>array(-10,0,312,488),65177=>array(63,-10,865,513),65178=>array(63,-10,992,513),65179=>array(-10,0,244,610),65180=>array(-10,0,312,610),65181=>array(77,-244,645,425),65182=>array(77,-244,655,425),65183=>array(-10,-146,545,398),65184=>array(-10,-146,655,398),65185=>array(77,-244,645,425),65186=>array(77,-244,655,425),65187=>array(-10,0,545,398),65188=>array(-10,0,655,398),65189=>array(77,-244,645,586),65190=>array(77,-244,655,586),65191=>array(-10,0,545,537),65192=>array(-10,0,655,537),65193=>array(61,-19,388,415),65194=>array(61,-19,535,415),65195=>array(61,-19,388,586),65196=>array(61,-19,535,586),65197=>array(-42,-244,423,269),65198=>array(-42,-244,562,269),65199=>array(-42,-244,423,464),65200=>array(-42,-244,562,464),65201=>array(63,-244,1138,366),65202=>array(63,-244,1285,366),65203=>array(-10,-14,755,366),65204=>array(-10,-14,902,366),65205=>array(63,-244,1138,586),65206=>array(63,-244,1285,586),65207=>array(-10,-14,755,586),65208=>array(-10,-14,902,586),65209=>array(63,-244,1134,362),65210=>array(63,-244,1235,362),65211=>array(-10,0,774,362),65212=>array(-10,0,877,362),65213=>array(63,-244,1134,464),65214=>array(63,-244,1235,464),65215=>array(-10,0,774,464),65216=>array(-10,0,877,464),65217=>array(70,0,857,760),65218=>array(70,0,959,760),65219=>array(-10,0,729,760),65220=>array(-10,0,830,760),65221=>array(70,0,857,760),65222=>array(70,0,959,760),65223=>array(-10,0,729,760),65224=>array(-10,0,830,760),65225=>array(57,-244,587,521),65226=>array(57,-244,587,382),65227=>array(-10,0,496,521),65228=>array(-10,0,492,382),65229=>array(57,-244,587,659),65230=>array(57,-244,587,537),65231=>array(-10,0,496,659),65232=>array(-10,0,492,537),65233=>array(63,-45,952,635),65234=>array(63,-44,1045,537),65235=>array(-10,0,406,635),65236=>array(-10,0,516,562),65237=>array(52,-215,701,635),65238=>array(52,-244,844,500),65239=>array(-10,0,406,635),65240=>array(-10,0,516,562),65241=>array(70,-27,722,760),65242=>array(70,-27,853,760),65243=>array(-10,0,476,760),65244=>array(-10,0,562,760),65245=>array(70,-152,637,760),65246=>array(70,-152,767,760),65247=>array(-10,0,210,760),65248=>array(-10,0,341,760),65249=>array(68,-240,546,369),65250=>array(68,-240,675,307),65251=>array(-10,-25,456,303),65252=>array(-10,-24,588,303),65253=>array(72,-162,660,464),65254=>array(72,-244,771,342),65255=>array(-10,0,191,488),65256=>array(-10,0,312,488),65257=>array(68,-28,453,358),65258=>array(71,0,546,366),65259=>array(-10,-33,467,487),65260=>array(-10,-244,471,333),65261=>array(-42,-244,406,315),65262=>array(-42,-244,526,315),65263=>array(63,-131,719,411),65264=>array(63,-133,843,251),65265=>array(63,-244,719,411),65266=>array(63,-244,843,251),65267=>array(-10,-146,244,293),65268=>array(-10,-146,312,293),65269=>array(-103,-10,468,866),65270=>array(-103,-10,606,866),65271=>array(-13,-10,468,955),65272=>array(-13,-10,606,955),65273=>array(11,-244,468,760),65274=>array(11,-244,606,760),65275=>array(41,-10,468,760),65276=>array(41,-10,606,760),65533=>array(15,-84,1011,912),65535=>array(50,-177,550,705)); -$cw=array(0=>600,32=>318,33=>401,34=>460,35=>838,36=>636,37=>950,38=>780,39=>275,40=>390,41=>390,42=>500,43=>838,44=>318,45=>361,46=>318,47=>337,48=>636,49=>636,50=>636,51=>636,52=>636,53=>636,54=>636,55=>636,56=>636,57=>636,58=>337,59=>337,60=>838,61=>838,62=>838,63=>531,64=>1000,65=>684,66=>686,67=>698,68=>770,69=>632,70=>575,71=>775,72=>752,73=>295,74=>295,75=>656,76=>557,77=>863,78=>748,79=>787,80=>603,81=>787,82=>695,83=>635,84=>611,85=>732,86=>684,87=>989,88=>685,89=>611,90=>685,91=>390,92=>337,93=>390,94=>838,95=>500,96=>500,97=>613,98=>635,99=>550,100=>635,101=>615,102=>352,103=>635,104=>634,105=>278,106=>278,107=>579,108=>278,109=>974,110=>634,111=>612,112=>635,113=>635,114=>411,115=>521,116=>392,117=>634,118=>592,119=>818,120=>592,121=>592,122=>525,123=>636,124=>337,125=>636,126=>838,160=>318,161=>401,162=>636,163=>636,164=>636,165=>636,166=>337,167=>500,168=>500,169=>1000,170=>471,171=>612,172=>838,173=>361,174=>1000,175=>500,176=>500,177=>838,178=>401,179=>401,180=>500,181=>636,182=>636,183=>318,184=>500,185=>401,186=>471,187=>612,188=>969,189=>969,190=>969,191=>531,192=>684,193=>684,194=>684,195=>684,196=>684,197=>684,198=>974,199=>698,200=>632,201=>632,202=>632,203=>632,204=>295,205=>295,206=>295,207=>295,208=>775,209=>748,210=>787,211=>787,212=>787,213=>787,214=>787,215=>838,216=>787,217=>732,218=>732,219=>732,220=>732,221=>611,222=>605,223=>630,224=>613,225=>613,226=>613,227=>613,228=>613,229=>613,230=>982,231=>550,232=>615,233=>615,234=>615,235=>615,236=>278,237=>278,238=>278,239=>278,240=>612,241=>634,242=>612,243=>612,244=>612,245=>612,246=>612,247=>838,248=>612,249=>634,250=>634,251=>634,252=>634,253=>592,254=>635,255=>592,256=>684,257=>613,258=>684,259=>613,260=>684,261=>613,262=>698,263=>550,264=>698,265=>550,266=>698,267=>550,268=>698,269=>550,270=>770,271=>635,272=>775,273=>635,274=>632,275=>615,276=>632,277=>615,278=>632,279=>615,280=>632,281=>615,282=>632,283=>615,284=>775,285=>635,286=>775,287=>635,288=>775,289=>635,290=>775,291=>635,292=>752,293=>634,294=>916,295=>695,296=>295,297=>278,298=>295,299=>278,300=>295,301=>278,302=>295,303=>278,304=>295,305=>278,306=>590,307=>556,308=>295,309=>278,310=>656,311=>579,312=>579,313=>557,314=>278,315=>557,316=>278,317=>557,318=>375,319=>557,320=>342,321=>562,322=>284,323=>748,324=>634,325=>748,326=>634,327=>748,328=>634,329=>813,330=>748,331=>634,332=>787,333=>612,334=>787,335=>612,336=>787,337=>612,338=>1070,339=>1023,340=>695,341=>411,342=>695,343=>411,344=>695,345=>411,346=>635,347=>521,348=>635,349=>521,350=>635,351=>521,352=>635,353=>521,354=>611,355=>392,356=>611,357=>392,358=>611,359=>392,360=>732,361=>634,362=>732,363=>634,364=>732,365=>634,366=>732,367=>634,368=>732,369=>634,370=>732,371=>634,372=>989,373=>818,374=>611,375=>592,376=>611,377=>685,378=>525,379=>685,380=>525,381=>685,382=>525,383=>352,384=>635,385=>735,386=>686,387=>635,388=>686,389=>635,390=>703,391=>698,392=>550,393=>775,394=>819,395=>686,396=>635,397=>612,398=>632,399=>787,400=>614,401=>575,402=>352,403=>775,404=>687,405=>984,406=>354,407=>295,408=>746,409=>579,410=>278,411=>592,412=>974,413=>748,414=>634,415=>787,416=>913,417=>612,418=>949,419=>759,420=>652,421=>635,422=>695,423=>635,424=>521,425=>632,426=>336,427=>392,428=>611,429=>392,430=>611,431=>858,432=>634,433=>764,434=>721,435=>744,436=>730,437=>685,438=>525,439=>666,440=>666,441=>578,442=>525,443=>636,444=>666,445=>578,446=>510,447=>635,448=>295,449=>492,450=>459,451=>295,452=>1422,453=>1299,454=>1154,455=>835,456=>787,457=>457,458=>931,459=>924,460=>797,461=>684,462=>613,463=>295,464=>278,465=>787,466=>612,467=>732,468=>634,469=>732,470=>634,471=>732,472=>634,473=>732,474=>634,475=>732,476=>634,477=>615,478=>684,479=>613,480=>684,481=>613,482=>974,483=>982,484=>775,485=>635,486=>775,487=>635,488=>656,489=>579,490=>787,491=>612,492=>787,493=>612,494=>666,495=>578,496=>278,497=>1422,498=>1299,499=>1154,500=>775,501=>635,502=>1113,503=>682,504=>748,505=>634,506=>684,507=>613,508=>974,509=>982,510=>787,511=>612,512=>684,513=>613,514=>684,515=>613,516=>632,517=>615,518=>632,519=>615,520=>295,521=>278,522=>295,523=>278,524=>787,525=>612,526=>787,527=>612,528=>695,529=>411,530=>695,531=>411,532=>732,533=>634,534=>732,535=>634,536=>635,537=>521,538=>611,539=>392,540=>627,541=>521,542=>752,543=>634,544=>735,545=>838,546=>698,547=>610,548=>685,549=>525,550=>684,551=>613,552=>632,553=>615,554=>787,555=>612,556=>787,557=>612,558=>787,559=>612,560=>787,561=>612,562=>611,563=>592,564=>475,565=>843,566=>477,567=>278,568=>998,569=>998,570=>684,571=>698,572=>550,573=>557,574=>611,575=>521,576=>525,577=>603,578=>479,579=>686,580=>732,581=>684,582=>632,583=>615,584=>295,585=>278,586=>781,587=>635,588=>695,589=>411,590=>611,591=>592,592=>600,593=>635,594=>635,595=>635,596=>549,597=>550,598=>635,599=>696,600=>615,601=>615,602=>819,603=>541,604=>532,605=>775,606=>664,607=>278,608=>696,609=>635,610=>629,611=>596,612=>596,613=>634,614=>634,615=>634,616=>278,617=>338,618=>372,619=>396,620=>487,621=>278,622=>706,623=>974,624=>974,625=>974,626=>646,627=>642,628=>634,629=>612,630=>858,631=>728,632=>660,633=>414,634=>414,635=>414,636=>411,637=>411,638=>530,639=>530,640=>604,641=>604,642=>521,643=>336,644=>336,645=>461,646=>336,647=>392,648=>392,649=>634,650=>618,651=>598,652=>592,653=>818,654=>592,655=>611,656=>525,657=>525,658=>578,659=>578,660=>510,661=>510,662=>510,663=>510,664=>787,665=>580,666=>664,667=>708,668=>654,669=>292,670=>667,671=>507,672=>727,673=>510,674=>510,675=>1014,676=>1058,677=>1013,678=>830,679=>610,680=>778,681=>848,682=>706,683=>654,684=>515,685=>515,686=>661,687=>664,688=>404,689=>399,690=>175,691=>259,692=>295,693=>296,694=>379,695=>515,696=>373,697=>278,698=>460,699=>318,700=>318,701=>318,702=>307,703=>307,704=>370,705=>370,706=>500,707=>500,708=>500,709=>500,710=>500,711=>500,712=>275,713=>500,714=>500,715=>500,716=>275,717=>500,718=>500,719=>500,720=>337,721=>337,722=>307,723=>307,724=>500,725=>500,726=>390,727=>317,728=>500,729=>500,730=>500,731=>500,732=>500,733=>500,734=>315,735=>500,736=>426,737=>166,738=>373,739=>444,740=>370,741=>493,742=>493,743=>493,744=>493,745=>493,748=>500,749=>500,750=>518,755=>500,759=>500,768=>0,769=>0,770=>0,771=>0,772=>0,773=>0,774=>0,775=>0,776=>0,777=>0,778=>0,779=>0,780=>0,781=>0,782=>0,783=>0,784=>0,785=>0,786=>0,787=>0,788=>0,789=>0,790=>0,791=>0,792=>0,793=>0,794=>0,795=>0,796=>0,797=>0,798=>0,799=>0,800=>0,801=>0,802=>0,803=>0,804=>0,805=>0,806=>0,807=>0,808=>0,809=>0,810=>0,811=>0,812=>0,813=>0,814=>0,815=>0,816=>0,817=>0,818=>0,819=>0,820=>0,821=>0,822=>0,823=>0,824=>0,825=>0,826=>0,827=>0,828=>0,829=>0,830=>0,831=>0,832=>0,833=>0,834=>0,835=>0,836=>0,837=>0,838=>0,839=>0,840=>0,841=>0,842=>0,843=>0,844=>0,845=>0,846=>0,847=>0,849=>0,850=>0,851=>0,855=>0,856=>0,858=>0,860=>0,861=>0,862=>0,863=>0,864=>0,865=>0,866=>0,880=>654,881=>568,882=>862,883=>647,884=>278,885=>278,886=>748,887=>650,890=>500,891=>549,892=>550,893=>549,894=>337,900=>500,901=>500,902=>692,903=>318,904=>746,905=>871,906=>408,908=>813,910=>825,911=>826,912=>338,913=>684,914=>686,915=>557,916=>684,917=>632,918=>685,919=>752,920=>787,921=>295,922=>656,923=>684,924=>863,925=>748,926=>632,927=>787,928=>752,929=>603,931=>632,932=>611,933=>611,934=>787,935=>685,936=>787,937=>764,938=>295,939=>611,940=>659,941=>541,942=>634,943=>338,944=>579,945=>659,946=>638,947=>592,948=>612,949=>541,950=>544,951=>634,952=>612,953=>338,954=>589,955=>592,956=>636,957=>559,958=>558,959=>612,960=>602,961=>635,962=>587,963=>634,964=>602,965=>579,966=>660,967=>578,968=>660,969=>837,970=>338,971=>579,972=>612,973=>579,974=>837,975=>656,976=>614,977=>619,978=>699,979=>842,980=>699,981=>660,982=>837,983=>664,984=>787,985=>612,986=>648,987=>587,988=>575,989=>458,990=>660,991=>660,992=>865,993=>627,994=>934,995=>837,996=>758,997=>659,998=>792,999=>615,1000=>687,1001=>607,1002=>768,1003=>625,1004=>699,1005=>612,1006=>611,1007=>536,1008=>664,1009=>635,1010=>550,1011=>278,1012=>787,1013=>615,1014=>615,1015=>605,1016=>635,1017=>698,1018=>863,1019=>651,1020=>635,1021=>703,1022=>698,1023=>703,1024=>632,1025=>632,1026=>786,1027=>610,1028=>698,1029=>635,1030=>295,1031=>295,1032=>295,1033=>1094,1034=>1045,1035=>786,1036=>710,1037=>748,1038=>609,1039=>752,1040=>684,1041=>686,1042=>686,1043=>610,1044=>781,1045=>632,1046=>1077,1047=>641,1048=>748,1049=>748,1050=>710,1051=>752,1052=>863,1053=>752,1054=>787,1055=>752,1056=>603,1057=>698,1058=>611,1059=>609,1060=>861,1061=>685,1062=>776,1063=>686,1064=>1069,1065=>1094,1066=>833,1067=>882,1068=>686,1069=>698,1070=>1080,1071=>695,1072=>613,1073=>617,1074=>589,1075=>525,1076=>691,1077=>615,1078=>901,1079=>532,1080=>650,1081=>650,1082=>604,1083=>639,1084=>754,1085=>654,1086=>612,1087=>654,1088=>635,1089=>550,1090=>583,1091=>592,1092=>855,1093=>592,1094=>681,1095=>591,1096=>915,1097=>942,1098=>707,1099=>790,1100=>589,1101=>549,1102=>842,1103=>602,1104=>615,1105=>615,1106=>625,1107=>525,1108=>549,1109=>521,1110=>278,1111=>278,1112=>278,1113=>902,1114=>898,1115=>652,1116=>604,1117=>650,1118=>592,1119=>654,1120=>934,1121=>837,1122=>771,1123=>672,1124=>942,1125=>749,1126=>879,1127=>783,1128=>1160,1129=>1001,1130=>787,1131=>612,1132=>1027,1133=>824,1134=>636,1135=>541,1136=>856,1137=>876,1138=>787,1139=>612,1140=>781,1141=>665,1142=>781,1143=>665,1144=>992,1145=>904,1146=>953,1147=>758,1148=>1180,1149=>1028,1150=>934,1151=>837,1152=>698,1153=>550,1154=>502,1155=>0,1156=>0,1157=>0,1158=>0,1159=>0,1160=>418,1161=>418,1162=>772,1163=>677,1164=>686,1165=>589,1166=>603,1167=>635,1168=>610,1169=>525,1170=>675,1171=>590,1172=>624,1173=>530,1174=>1077,1175=>901,1176=>641,1177=>532,1178=>710,1179=>604,1180=>710,1181=>604,1182=>710,1183=>604,1184=>856,1185=>832,1186=>752,1187=>661,1188=>1014,1189=>877,1190=>1081,1191=>916,1192=>878,1193=>693,1194=>698,1195=>550,1196=>611,1197=>583,1198=>611,1199=>592,1200=>611,1201=>592,1202=>685,1203=>592,1204=>934,1205=>807,1206=>686,1207=>591,1208=>686,1209=>591,1210=>686,1211=>634,1212=>941,1213=>728,1214=>941,1215=>728,1216=>295,1217=>1077,1218=>901,1219=>656,1220=>604,1221=>776,1222=>670,1223=>752,1224=>661,1225=>776,1226=>681,1227=>686,1228=>591,1229=>888,1230=>774,1231=>278,1232=>684,1233=>613,1234=>684,1235=>613,1236=>974,1237=>982,1238=>632,1239=>615,1240=>787,1241=>615,1242=>787,1243=>615,1244=>1077,1245=>901,1246=>641,1247=>532,1248=>666,1249=>578,1250=>748,1251=>650,1252=>748,1253=>650,1254=>787,1255=>612,1256=>787,1257=>612,1258=>787,1259=>612,1260=>698,1261=>549,1262=>609,1263=>592,1264=>609,1265=>592,1266=>609,1267=>592,1268=>686,1269=>591,1270=>610,1271=>525,1272=>882,1273=>790,1274=>675,1275=>590,1276=>685,1277=>592,1278=>685,1279=>592,1280=>686,1281=>589,1282=>1006,1283=>897,1284=>975,1285=>869,1286=>679,1287=>588,1288=>1072,1289=>957,1290=>1113,1291=>967,1292=>775,1293=>660,1294=>773,1295=>711,1296=>614,1297=>541,1298=>752,1299=>639,1300=>1169,1301=>994,1302=>894,1303=>864,1304=>1032,1305=>986,1306=>787,1307=>635,1308=>989,1309=>818,1310=>710,1311=>604,1312=>1081,1313=>905,1314=>1081,1315=>912,1316=>793,1317=>683,1329=>766,1330=>732,1331=>753,1332=>753,1333=>732,1334=>772,1335=>640,1336=>732,1337=>859,1338=>753,1339=>691,1340=>533,1341=>922,1342=>863,1343=>732,1344=>716,1345=>766,1346=>753,1347=>767,1348=>792,1349=>728,1350=>729,1351=>757,1352=>732,1353=>713,1354=>800,1355=>768,1356=>792,1357=>732,1358=>753,1359=>705,1360=>694,1361=>744,1362=>538,1363=>811,1364=>757,1365=>787,1366=>790,1369=>307,1370=>318,1371=>234,1372=>361,1373=>238,1374=>405,1375=>500,1377=>974,1378=>634,1379=>658,1380=>663,1381=>634,1382=>635,1383=>515,1384=>634,1385=>738,1386=>658,1387=>634,1388=>271,1389=>980,1390=>623,1391=>634,1392=>634,1393=>608,1394=>634,1395=>629,1396=>634,1397=>271,1398=>634,1399=>499,1400=>634,1401=>404,1402=>974,1403=>560,1404=>648,1405=>634,1406=>634,1407=>974,1408=>634,1409=>633,1410=>435,1411=>974,1412=>636,1413=>609,1414=>805,1415=>812,1417=>337,1418=>361,1456=>0,1457=>0,1458=>0,1459=>0,1460=>0,1461=>0,1462=>0,1463=>0,1464=>0,1465=>0,1466=>0,1467=>0,1468=>0,1469=>0,1470=>361,1471=>0,1472=>295,1473=>0,1474=>0,1475=>295,1478=>441,1479=>0,1488=>668,1489=>578,1490=>412,1491=>546,1492=>653,1493=>272,1494=>346,1495=>653,1496=>648,1497=>224,1498=>537,1499=>529,1500=>568,1501=>664,1502=>679,1503=>272,1504=>400,1505=>649,1506=>626,1507=>640,1508=>625,1509=>540,1510=>593,1511=>709,1512=>564,1513=>708,1514=>657,1520=>471,1521=>423,1522=>331,1523=>416,1524=>645,1542=>637,1543=>637,1545=>757,1546=>977,1548=>323,1557=>0,1563=>318,1567=>531,1569=>470,1570=>278,1571=>278,1572=>483,1573=>278,1574=>783,1575=>278,1576=>941,1577=>524,1578=>941,1579=>941,1580=>646,1581=>646,1582=>646,1583=>445,1584=>445,1585=>483,1586=>483,1587=>1221,1588=>1221,1589=>1209,1590=>1209,1591=>925,1592=>925,1593=>597,1594=>597,1600=>293,1601=>1037,1602=>776,1603=>824,1604=>727,1605=>619,1606=>734,1607=>524,1608=>483,1609=>783,1610=>783,1611=>0,1612=>0,1613=>0,1614=>0,1615=>0,1616=>0,1617=>0,1618=>0,1619=>0,1620=>0,1621=>0,1623=>0,1626=>500,1632=>537,1633=>537,1634=>537,1635=>537,1636=>537,1637=>537,1638=>537,1639=>537,1640=>537,1641=>537,1642=>537,1643=>325,1644=>318,1645=>545,1646=>941,1647=>776,1648=>0,1652=>292,1657=>941,1658=>941,1659=>941,1660=>941,1661=>941,1662=>941,1663=>941,1664=>941,1665=>646,1666=>646,1667=>646,1668=>646,1669=>646,1670=>646,1671=>646,1672=>445,1673=>445,1674=>445,1675=>445,1676=>445,1677=>445,1678=>445,1679=>445,1680=>445,1681=>483,1682=>483,1683=>498,1684=>530,1685=>610,1686=>530,1687=>483,1688=>483,1689=>483,1690=>1221,1691=>1221,1692=>1221,1693=>1209,1694=>1209,1695=>925,1696=>597,1697=>1037,1698=>1037,1699=>1037,1700=>1037,1701=>1037,1702=>1037,1703=>776,1704=>776,1705=>895,1706=>1054,1707=>895,1708=>824,1709=>824,1710=>824,1711=>895,1712=>895,1713=>895,1714=>895,1715=>895,1716=>895,1717=>727,1718=>727,1719=>727,1720=>727,1721=>734,1722=>734,1723=>734,1724=>734,1725=>734,1726=>698,1727=>646,1734=>483,1740=>783,1742=>783,1749=>524,1776=>537,1777=>537,1778=>537,1779=>537,1780=>537,1781=>537,1782=>537,1783=>537,1784=>537,1785=>537,1984=>636,1985=>636,1986=>636,1987=>636,1988=>636,1989=>636,1990=>636,1991=>636,1992=>636,1993=>636,1994=>278,1995=>571,1996=>424,1997=>592,1998=>654,1999=>654,2000=>594,2001=>654,2002=>829,2003=>438,2004=>438,2005=>559,2006=>612,2007=>350,2008=>959,2009=>473,2010=>783,2011=>654,2012=>625,2013=>734,2014=>530,2015=>724,2016=>473,2017=>625,2018=>594,2019=>530,2020=>530,2021=>522,2022=>594,2023=>594,2027=>0,2028=>0,2029=>0,2030=>0,2031=>0,2032=>0,2033=>0,2034=>0,2035=>0,2036=>313,2037=>313,2040=>560,2041=>560,2042=>361,3647=>636,3713=>670,3714=>684,3716=>688,3719=>482,3720=>628,3722=>684,3725=>688,3732=>669,3733=>642,3734=>645,3735=>655,3737=>659,3738=>625,3739=>625,3740=>745,3741=>767,3742=>687,3743=>687,3745=>702,3746=>688,3747=>684,3749=>649,3751=>632,3754=>703,3755=>819,3757=>633,3758=>684,3759=>788,3760=>632,3761=>0,3762=>539,3763=>539,3764=>0,3765=>0,3766=>0,3767=>0,3768=>0,3769=>0,3771=>0,3772=>0,3773=>663,3776=>375,3777=>657,3778=>460,3779=>547,3780=>491,3782=>674,3784=>0,3785=>0,3786=>0,3787=>0,3788=>0,3789=>0,3792=>636,3793=>641,3794=>641,3795=>670,3796=>625,3797=>625,3798=>703,3799=>670,3800=>674,3801=>677,3804=>1028,3805=>1028,4256=>874,4257=>733,4258=>679,4259=>834,4260=>615,4261=>768,4262=>753,4263=>914,4264=>453,4265=>620,4266=>843,4267=>882,4268=>625,4269=>854,4270=>781,4271=>629,4272=>912,4273=>621,4274=>620,4275=>854,4276=>866,4277=>724,4278=>630,4279=>621,4280=>625,4281=>620,4282=>818,4283=>874,4284=>615,4285=>623,4286=>625,4287=>725,4288=>844,4289=>596,4290=>688,4291=>596,4292=>594,4293=>738,4304=>508,4305=>518,4306=>581,4307=>818,4308=>508,4309=>513,4310=>500,4311=>801,4312=>518,4313=>510,4314=>1064,4315=>522,4316=>522,4317=>786,4318=>508,4319=>518,4320=>796,4321=>522,4322=>654,4323=>522,4324=>825,4325=>513,4326=>786,4327=>518,4328=>518,4329=>522,4330=>571,4331=>522,4332=>518,4333=>520,4334=>522,4335=>454,4336=>508,4337=>518,4338=>508,4339=>508,4340=>518,4341=>554,4342=>828,4343=>552,4344=>508,4345=>571,4346=>508,4347=>448,4348=>324,5121=>684,5122=>684,5123=>684,5124=>684,5125=>769,5126=>769,5127=>769,5129=>769,5130=>769,5131=>769,5132=>835,5133=>834,5134=>835,5135=>834,5136=>835,5137=>834,5138=>967,5139=>1007,5140=>967,5141=>1007,5142=>769,5143=>967,5144=>1007,5145=>967,5146=>1007,5147=>769,5149=>256,5150=>543,5151=>423,5152=>423,5153=>389,5154=>389,5155=>393,5156=>389,5157=>466,5158=>385,5159=>256,5160=>389,5161=>389,5162=>389,5163=>1090,5164=>909,5165=>953,5166=>1117,5167=>684,5168=>684,5169=>684,5170=>684,5171=>729,5172=>729,5173=>729,5175=>729,5176=>729,5177=>729,5178=>835,5179=>684,5180=>835,5181=>834,5182=>835,5183=>834,5184=>967,5185=>1007,5186=>967,5187=>1007,5188=>967,5189=>1007,5190=>967,5191=>1007,5192=>729,5193=>508,5194=>192,5196=>732,5197=>732,5198=>732,5199=>732,5200=>730,5201=>730,5202=>730,5204=>730,5205=>730,5206=>730,5207=>921,5208=>889,5209=>921,5210=>889,5211=>921,5212=>889,5213=>928,5214=>900,5215=>928,5216=>900,5217=>947,5218=>900,5219=>947,5220=>900,5221=>947,5222=>434,5223=>877,5224=>877,5225=>866,5226=>890,5227=>628,5228=>628,5229=>628,5230=>628,5231=>628,5232=>628,5233=>628,5234=>628,5235=>628,5236=>860,5237=>771,5238=>815,5239=>816,5240=>815,5241=>816,5242=>860,5243=>771,5244=>860,5245=>771,5246=>815,5247=>816,5248=>815,5249=>816,5250=>815,5251=>407,5252=>407,5253=>750,5254=>775,5255=>750,5256=>775,5257=>628,5258=>628,5259=>628,5260=>628,5261=>628,5262=>628,5263=>628,5264=>628,5265=>628,5266=>860,5267=>771,5268=>815,5269=>816,5270=>815,5271=>816,5272=>860,5273=>771,5274=>860,5275=>771,5276=>815,5277=>816,5278=>815,5279=>816,5280=>815,5281=>435,5282=>435,5283=>610,5284=>557,5285=>557,5286=>557,5287=>610,5288=>610,5289=>610,5290=>557,5291=>557,5292=>749,5293=>769,5294=>746,5295=>764,5296=>746,5297=>764,5298=>749,5299=>769,5300=>749,5301=>769,5302=>746,5303=>764,5304=>746,5305=>764,5306=>746,5307=>386,5308=>508,5309=>386,5312=>852,5313=>852,5314=>852,5315=>852,5316=>852,5317=>852,5318=>852,5319=>852,5320=>852,5321=>1069,5322=>1035,5323=>1059,5324=>852,5325=>1059,5326=>852,5327=>852,5328=>600,5329=>453,5330=>600,5331=>852,5332=>852,5333=>852,5334=>852,5335=>852,5336=>852,5337=>852,5338=>852,5339=>852,5340=>1069,5341=>1035,5342=>1059,5343=>1030,5344=>1059,5345=>1030,5346=>1069,5347=>1035,5348=>1069,5349=>1035,5350=>1083,5351=>1030,5352=>1083,5353=>1030,5354=>600,5356=>729,5357=>603,5358=>603,5359=>603,5360=>603,5361=>603,5362=>603,5363=>603,5364=>603,5365=>603,5366=>834,5367=>754,5368=>792,5369=>771,5370=>792,5371=>771,5372=>834,5373=>754,5374=>834,5375=>754,5376=>792,5377=>771,5378=>792,5379=>771,5380=>792,5381=>418,5382=>420,5383=>418,5392=>712,5393=>712,5394=>712,5395=>892,5396=>892,5397=>892,5398=>892,5399=>910,5400=>872,5401=>910,5402=>872,5403=>910,5404=>872,5405=>1140,5406=>1100,5407=>1140,5408=>1100,5409=>1140,5410=>1100,5411=>1140,5412=>1100,5413=>641,5414=>627,5415=>627,5416=>627,5417=>627,5418=>627,5419=>627,5420=>627,5421=>627,5422=>627,5423=>844,5424=>781,5425=>816,5426=>818,5427=>816,5428=>818,5429=>844,5430=>781,5431=>844,5432=>781,5433=>816,5434=>818,5435=>816,5436=>818,5437=>816,5438=>418,5440=>389,5441=>484,5442=>916,5443=>916,5444=>916,5445=>916,5446=>916,5447=>916,5448=>603,5449=>603,5450=>603,5451=>603,5452=>603,5453=>603,5454=>834,5455=>754,5456=>418,5458=>729,5459=>684,5460=>684,5461=>684,5462=>684,5463=>726,5464=>726,5465=>726,5466=>726,5467=>924,5468=>1007,5469=>508,5470=>732,5471=>732,5472=>732,5473=>732,5474=>732,5475=>732,5476=>730,5477=>730,5478=>730,5479=>730,5480=>947,5481=>900,5482=>508,5492=>831,5493=>831,5494=>831,5495=>831,5496=>831,5497=>831,5498=>831,5499=>563,5500=>752,5501=>484,5502=>1047,5503=>1047,5504=>1047,5505=>1047,5506=>1047,5507=>1047,5508=>1047,5509=>825,5514=>831,5515=>831,5516=>831,5517=>831,5518=>1259,5519=>1259,5520=>1259,5521=>1002,5522=>1002,5523=>1259,5524=>1259,5525=>700,5526=>1073,5536=>852,5537=>852,5538=>852,5539=>852,5540=>852,5541=>852,5542=>600,5543=>643,5544=>643,5545=>643,5546=>643,5547=>643,5548=>643,5549=>643,5550=>418,5551=>628,5598=>770,5601=>767,5702=>468,5703=>468,5742=>444,5743=>1047,5744=>1310,5745=>1632,5746=>1632,5747=>1375,5748=>1375,5749=>1632,5750=>1632,5760=>477,5761=>493,5762=>712,5763=>931,5764=>1150,5765=>1370,5766=>493,5767=>712,5768=>931,5769=>1150,5770=>1370,5771=>498,5772=>718,5773=>938,5774=>1159,5775=>1379,5776=>493,5777=>712,5778=>930,5779=>1149,5780=>1370,5781=>498,5782=>752,5783=>789,5784=>1205,5785=>1150,5786=>683,5787=>507,5788=>507,7424=>592,7425=>717,7426=>982,7427=>586,7428=>550,7429=>605,7430=>605,7431=>491,7432=>541,7433=>278,7434=>395,7435=>579,7436=>583,7437=>754,7438=>650,7439=>612,7440=>550,7441=>684,7442=>684,7443=>684,7444=>1023,7446=>612,7447=>612,7448=>524,7449=>602,7450=>602,7451=>583,7452=>574,7453=>737,7454=>948,7455=>638,7456=>592,7457=>818,7458=>525,7459=>526,7462=>583,7463=>592,7464=>564,7465=>524,7466=>590,7467=>639,7468=>431,7469=>613,7470=>432,7472=>485,7473=>398,7474=>398,7475=>488,7476=>474,7477=>186,7478=>186,7479=>413,7480=>351,7481=>543,7482=>471,7483=>471,7484=>496,7485=>439,7486=>380,7487=>438,7488=>385,7489=>461,7490=>623,7491=>392,7492=>392,7493=>405,7494=>648,7495=>428,7496=>405,7497=>417,7498=>417,7499=>360,7500=>359,7501=>405,7502=>179,7503=>426,7504=>623,7505=>409,7506=>414,7507=>370,7508=>414,7509=>414,7510=>428,7511=>295,7512=>405,7513=>470,7514=>623,7515=>417,7517=>402,7518=>373,7519=>385,7520=>416,7521=>364,7522=>179,7523=>259,7524=>405,7525=>417,7526=>402,7527=>373,7528=>412,7529=>416,7530=>364,7543=>635,7544=>474,7547=>372,7549=>667,7557=>278,7579=>405,7580=>370,7581=>370,7582=>414,7583=>360,7584=>296,7585=>233,7586=>405,7587=>405,7588=>261,7589=>250,7590=>261,7591=>261,7592=>234,7593=>250,7594=>235,7595=>376,7596=>623,7597=>623,7598=>411,7599=>479,7600=>409,7601=>414,7602=>414,7603=>360,7604=>287,7605=>295,7606=>508,7607=>418,7608=>361,7609=>406,7610=>417,7611=>366,7612=>437,7613=>366,7614=>392,7615=>414,7620=>0,7621=>0,7622=>0,7623=>0,7624=>0,7625=>0,7680=>684,7681=>613,7682=>686,7683=>635,7684=>686,7685=>635,7686=>686,7687=>635,7688=>698,7689=>550,7690=>770,7691=>635,7692=>770,7693=>635,7694=>770,7695=>635,7696=>770,7697=>635,7698=>770,7699=>635,7700=>632,7701=>615,7702=>632,7703=>615,7704=>632,7705=>615,7706=>632,7707=>615,7708=>632,7709=>615,7710=>575,7711=>352,7712=>775,7713=>635,7714=>752,7715=>634,7716=>752,7717=>634,7718=>752,7719=>634,7720=>752,7721=>634,7722=>752,7723=>634,7724=>295,7725=>278,7726=>295,7727=>278,7728=>656,7729=>579,7730=>656,7731=>579,7732=>656,7733=>579,7734=>557,7735=>288,7736=>557,7737=>288,7738=>557,7739=>278,7740=>557,7741=>278,7742=>863,7743=>974,7744=>863,7745=>974,7746=>863,7747=>974,7748=>748,7749=>634,7750=>748,7751=>634,7752=>748,7753=>634,7754=>748,7755=>634,7756=>787,7757=>612,7758=>787,7759=>612,7760=>787,7761=>612,7762=>787,7763=>612,7764=>603,7765=>635,7766=>603,7767=>635,7768=>695,7769=>411,7770=>695,7771=>411,7772=>695,7773=>411,7774=>695,7775=>411,7776=>635,7777=>521,7778=>635,7779=>521,7780=>635,7781=>521,7782=>635,7783=>521,7784=>635,7785=>521,7786=>611,7787=>392,7788=>611,7789=>392,7790=>611,7791=>392,7792=>611,7793=>392,7794=>732,7795=>634,7796=>732,7797=>634,7798=>732,7799=>634,7800=>732,7801=>634,7802=>732,7803=>634,7804=>684,7805=>592,7806=>684,7807=>592,7808=>989,7809=>818,7810=>989,7811=>818,7812=>989,7813=>818,7814=>989,7815=>818,7816=>989,7817=>818,7818=>685,7819=>592,7820=>685,7821=>592,7822=>611,7823=>592,7824=>685,7825=>525,7826=>685,7827=>525,7828=>685,7829=>525,7830=>634,7831=>392,7832=>818,7833=>592,7834=>613,7835=>352,7836=>352,7837=>352,7838=>769,7839=>612,7840=>684,7841=>613,7842=>684,7843=>613,7844=>684,7845=>613,7846=>684,7847=>613,7848=>684,7849=>613,7850=>684,7851=>613,7852=>684,7853=>613,7854=>684,7855=>613,7856=>684,7857=>613,7858=>684,7859=>613,7860=>684,7861=>613,7862=>684,7863=>613,7864=>632,7865=>615,7866=>632,7867=>615,7868=>632,7869=>615,7870=>632,7871=>615,7872=>632,7873=>615,7874=>632,7875=>615,7876=>632,7877=>615,7878=>632,7879=>615,7880=>295,7881=>278,7882=>295,7883=>278,7884=>787,7885=>612,7886=>787,7887=>612,7888=>787,7889=>612,7890=>787,7891=>612,7892=>787,7893=>612,7894=>787,7895=>612,7896=>787,7897=>612,7898=>913,7899=>612,7900=>913,7901=>612,7902=>913,7903=>612,7904=>913,7905=>612,7906=>913,7907=>612,7908=>732,7909=>634,7910=>732,7911=>634,7912=>858,7913=>634,7914=>858,7915=>634,7916=>858,7917=>634,7918=>858,7919=>634,7920=>858,7921=>634,7922=>611,7923=>592,7924=>611,7925=>592,7926=>611,7927=>592,7928=>611,7929=>592,7930=>769,7931=>477,7936=>659,7937=>659,7938=>659,7939=>659,7940=>659,7941=>659,7942=>659,7943=>659,7944=>684,7945=>684,7946=>877,7947=>877,7948=>769,7949=>801,7950=>708,7951=>743,7952=>541,7953=>541,7954=>541,7955=>541,7956=>541,7957=>541,7960=>711,7961=>711,7962=>966,7963=>975,7964=>898,7965=>928,7968=>634,7969=>634,7970=>634,7971=>634,7972=>634,7973=>634,7974=>634,7975=>634,7976=>837,7977=>835,7978=>1086,7979=>1089,7980=>1027,7981=>1051,7982=>934,7983=>947,7984=>338,7985=>338,7986=>338,7987=>338,7988=>338,7989=>338,7990=>338,7991=>338,7992=>380,7993=>374,7994=>635,7995=>635,7996=>570,7997=>600,7998=>489,7999=>493,8000=>612,8001=>612,8002=>612,8003=>612,8004=>612,8005=>612,8008=>804,8009=>848,8010=>1095,8011=>1100,8012=>938,8013=>970,8016=>579,8017=>579,8018=>579,8019=>579,8020=>579,8021=>579,8022=>579,8023=>579,8025=>784,8027=>998,8029=>1012,8031=>897,8032=>837,8033=>837,8034=>837,8035=>837,8036=>837,8037=>837,8038=>837,8039=>837,8040=>802,8041=>843,8042=>1089,8043=>1095,8044=>946,8045=>972,8046=>921,8047=>952,8048=>659,8049=>659,8050=>541,8051=>548,8052=>634,8053=>654,8054=>338,8055=>338,8056=>612,8057=>612,8058=>579,8059=>579,8060=>837,8061=>837,8064=>659,8065=>659,8066=>659,8067=>659,8068=>659,8069=>659,8070=>659,8071=>659,8072=>684,8073=>684,8074=>877,8075=>877,8076=>769,8077=>801,8078=>708,8079=>743,8080=>634,8081=>634,8082=>634,8083=>634,8084=>634,8085=>634,8086=>634,8087=>634,8088=>837,8089=>835,8090=>1086,8091=>1089,8092=>1027,8093=>1051,8094=>934,8095=>947,8096=>837,8097=>837,8098=>837,8099=>837,8100=>837,8101=>837,8102=>837,8103=>837,8104=>802,8105=>843,8106=>1089,8107=>1095,8108=>946,8109=>972,8110=>921,8111=>952,8112=>659,8113=>659,8114=>659,8115=>659,8116=>659,8118=>659,8119=>659,8120=>684,8121=>684,8122=>716,8123=>692,8124=>684,8125=>500,8126=>500,8127=>500,8128=>500,8129=>500,8130=>634,8131=>634,8132=>654,8134=>634,8135=>634,8136=>805,8137=>746,8138=>931,8139=>871,8140=>752,8141=>500,8142=>500,8143=>500,8144=>338,8145=>338,8146=>338,8147=>338,8150=>338,8151=>338,8152=>295,8153=>295,8154=>475,8155=>408,8157=>500,8158=>500,8159=>500,8160=>579,8161=>579,8162=>579,8163=>579,8164=>635,8165=>635,8166=>579,8167=>579,8168=>611,8169=>611,8170=>845,8171=>825,8172=>685,8173=>500,8174=>500,8175=>500,8178=>837,8179=>837,8180=>837,8182=>837,8183=>837,8184=>941,8185=>813,8186=>922,8187=>826,8188=>764,8189=>500,8190=>500,8192=>500,8193=>1000,8194=>500,8195=>1000,8196=>330,8197=>250,8198=>167,8199=>636,8200=>318,8201=>200,8202=>100,8203=>0,8204=>0,8205=>0,8206=>0,8207=>0,8208=>361,8209=>361,8210=>636,8211=>500,8212=>1000,8213=>1000,8214=>500,8215=>500,8216=>318,8217=>318,8218=>318,8219=>318,8220=>518,8221=>518,8222=>518,8223=>518,8224=>500,8225=>500,8226=>590,8227=>590,8228=>334,8229=>667,8230=>1000,8231=>318,8232=>0,8233=>0,8234=>0,8235=>0,8236=>0,8237=>0,8238=>0,8239=>200,8240=>1342,8241=>1735,8242=>227,8243=>374,8244=>520,8245=>227,8246=>374,8247=>520,8248=>339,8249=>400,8250=>400,8251=>838,8252=>485,8253=>531,8254=>500,8255=>804,8256=>804,8257=>250,8258=>1000,8259=>500,8260=>167,8261=>390,8262=>390,8263=>922,8264=>733,8265=>733,8266=>497,8267=>636,8268=>500,8269=>500,8270=>500,8271=>337,8272=>804,8273=>500,8274=>450,8275=>1000,8276=>804,8277=>838,8278=>586,8279=>663,8280=>838,8281=>838,8282=>318,8283=>797,8284=>838,8285=>318,8286=>318,8287=>222,8288=>0,8289=>0,8290=>0,8291=>0,8292=>0,8298=>0,8299=>0,8300=>0,8301=>0,8302=>0,8303=>0,8304=>401,8305=>179,8308=>401,8309=>401,8310=>401,8311=>401,8312=>401,8313=>401,8314=>528,8315=>528,8316=>528,8317=>246,8318=>246,8319=>398,8320=>401,8321=>401,8322=>401,8323=>401,8324=>401,8325=>401,8326=>401,8327=>401,8328=>401,8329=>401,8330=>528,8331=>528,8332=>528,8333=>246,8334=>246,8336=>392,8337=>417,8338=>414,8339=>444,8340=>417,8341=>404,8342=>426,8343=>166,8344=>623,8345=>398,8346=>428,8347=>373,8348=>295,8352=>877,8353=>636,8354=>636,8355=>636,8356=>636,8357=>974,8358=>748,8359=>1272,8360=>1074,8361=>989,8362=>784,8363=>636,8364=>636,8365=>636,8366=>636,8367=>1272,8368=>636,8369=>636,8370=>636,8371=>636,8372=>774,8373=>636,8376=>636,8377=>636,8378=>679,8400=>0,8401=>0,8406=>0,8407=>0,8411=>0,8412=>0,8417=>0,8448=>1019,8449=>1019,8450=>698,8451=>1123,8452=>642,8453=>1019,8454=>1067,8455=>614,8456=>698,8457=>952,8459=>988,8460=>754,8461=>850,8462=>634,8463=>634,8464=>470,8465=>697,8466=>720,8467=>413,8468=>818,8469=>801,8470=>1040,8471=>1000,8472=>697,8473=>701,8474=>787,8475=>798,8476=>814,8477=>792,8478=>896,8479=>684,8480=>1020,8481=>1074,8482=>1000,8483=>684,8484=>745,8485=>578,8486=>764,8487=>764,8488=>616,8489=>338,8490=>656,8491=>684,8492=>786,8493=>703,8494=>854,8495=>592,8496=>605,8497=>786,8498=>575,8499=>1069,8500=>462,8501=>745,8502=>674,8503=>466,8504=>645,8505=>380,8506=>926,8507=>1194,8508=>702,8509=>728,8510=>654,8511=>849,8512=>811,8513=>775,8514=>557,8515=>557,8516=>611,8517=>819,8518=>708,8519=>615,8520=>351,8521=>351,8523=>780,8526=>526,8528=>969,8529=>969,8530=>1370,8531=>969,8532=>969,8533=>969,8534=>969,8535=>969,8536=>969,8537=>969,8538=>969,8539=>969,8540=>969,8541=>969,8542=>969,8543=>568,8544=>295,8545=>492,8546=>689,8547=>923,8548=>684,8549=>922,8550=>1120,8551=>1317,8552=>917,8553=>685,8554=>933,8555=>1131,8556=>557,8557=>698,8558=>770,8559=>863,8560=>278,8561=>458,8562=>637,8563=>812,8564=>592,8565=>811,8566=>991,8567=>1170,8568=>819,8569=>592,8570=>822,8571=>1002,8572=>278,8573=>550,8574=>635,8575=>974,8576=>1245,8577=>770,8578=>1245,8579=>703,8580=>549,8581=>698,8585=>969,8592=>838,8593=>838,8594=>838,8595=>838,8596=>838,8597=>838,8598=>838,8599=>838,8600=>838,8601=>838,8602=>838,8603=>838,8604=>838,8605=>838,8606=>838,8607=>838,8608=>838,8609=>838,8610=>838,8611=>838,8612=>838,8613=>838,8614=>838,8615=>838,8616=>838,8617=>838,8618=>838,8619=>838,8620=>838,8621=>838,8622=>838,8623=>838,8624=>838,8625=>838,8626=>838,8627=>838,8628=>838,8629=>838,8630=>838,8631=>838,8632=>838,8633=>838,8634=>838,8635=>838,8636=>838,8637=>838,8638=>838,8639=>838,8640=>838,8641=>838,8642=>838,8643=>838,8644=>838,8645=>838,8646=>838,8647=>838,8648=>838,8649=>838,8650=>838,8651=>838,8652=>838,8653=>838,8654=>838,8655=>838,8656=>838,8657=>838,8658=>838,8659=>838,8660=>838,8661=>838,8662=>838,8663=>838,8664=>838,8665=>838,8666=>838,8667=>838,8668=>838,8669=>838,8670=>838,8671=>838,8672=>838,8673=>838,8674=>838,8675=>838,8676=>838,8677=>838,8678=>838,8679=>838,8680=>838,8681=>838,8682=>838,8683=>838,8684=>838,8685=>838,8686=>838,8687=>838,8688=>838,8689=>838,8690=>838,8691=>838,8692=>838,8693=>838,8694=>838,8695=>838,8696=>838,8697=>838,8698=>838,8699=>838,8700=>838,8701=>838,8702=>838,8703=>838,8704=>684,8705=>636,8706=>517,8707=>632,8708=>632,8709=>871,8710=>669,8711=>669,8712=>871,8713=>871,8714=>718,8715=>871,8716=>871,8717=>718,8718=>636,8719=>757,8720=>757,8721=>674,8722=>838,8723=>838,8724=>838,8725=>337,8726=>637,8727=>838,8728=>626,8729=>626,8730=>637,8731=>637,8732=>637,8733=>714,8734=>833,8735=>838,8736=>896,8737=>896,8738=>838,8739=>500,8740=>500,8741=>500,8742=>500,8743=>732,8744=>732,8745=>732,8746=>732,8747=>521,8748=>789,8749=>1057,8750=>521,8751=>789,8752=>1057,8753=>521,8754=>521,8755=>521,8756=>636,8757=>636,8758=>260,8759=>636,8760=>838,8761=>838,8762=>838,8763=>838,8764=>838,8765=>838,8766=>838,8767=>838,8768=>375,8769=>838,8770=>838,8771=>838,8772=>838,8773=>838,8774=>838,8775=>838,8776=>838,8777=>838,8778=>838,8779=>838,8780=>838,8781=>838,8782=>838,8783=>838,8784=>838,8785=>838,8786=>839,8787=>839,8788=>1000,8789=>1000,8790=>838,8791=>838,8792=>838,8793=>838,8794=>838,8795=>838,8796=>838,8797=>838,8798=>838,8799=>838,8800=>838,8801=>838,8802=>838,8803=>838,8804=>838,8805=>838,8806=>838,8807=>838,8808=>838,8809=>838,8810=>1047,8811=>1047,8812=>464,8813=>838,8814=>838,8815=>838,8816=>838,8817=>838,8818=>838,8819=>838,8820=>838,8821=>838,8822=>838,8823=>838,8824=>838,8825=>838,8826=>838,8827=>838,8828=>838,8829=>838,8830=>838,8831=>838,8832=>838,8833=>838,8834=>838,8835=>838,8836=>838,8837=>838,8838=>838,8839=>838,8840=>838,8841=>838,8842=>838,8843=>838,8844=>732,8845=>732,8846=>732,8847=>838,8848=>838,8849=>838,8850=>838,8851=>780,8852=>780,8853=>838,8854=>838,8855=>838,8856=>838,8857=>838,8858=>838,8859=>838,8860=>838,8861=>838,8862=>838,8863=>838,8864=>838,8865=>838,8866=>871,8867=>871,8868=>871,8869=>871,8870=>521,8871=>521,8872=>871,8873=>871,8874=>871,8875=>871,8876=>871,8877=>871,8878=>871,8879=>871,8880=>838,8881=>838,8882=>838,8883=>838,8884=>838,8885=>838,8886=>1000,8887=>1000,8888=>838,8889=>838,8890=>521,8891=>732,8892=>732,8893=>732,8894=>838,8895=>838,8896=>820,8897=>820,8898=>820,8899=>820,8900=>494,8901=>318,8902=>626,8903=>838,8904=>1000,8905=>1000,8906=>1000,8907=>1000,8908=>1000,8909=>838,8910=>732,8911=>732,8912=>838,8913=>838,8914=>838,8915=>838,8916=>838,8917=>838,8918=>838,8919=>838,8920=>1422,8921=>1422,8922=>838,8923=>838,8924=>838,8925=>838,8926=>838,8927=>838,8928=>838,8929=>838,8930=>838,8931=>838,8932=>838,8933=>838,8934=>838,8935=>838,8936=>838,8937=>838,8938=>838,8939=>838,8940=>838,8941=>838,8942=>1000,8943=>1000,8944=>1000,8945=>1000,8946=>1000,8947=>871,8948=>718,8949=>871,8950=>871,8951=>718,8952=>871,8953=>871,8954=>1000,8955=>871,8956=>718,8957=>871,8958=>718,8959=>871,8960=>602,8961=>602,8962=>635,8963=>838,8964=>838,8965=>838,8966=>838,8967=>488,8968=>390,8969=>390,8970=>390,8971=>390,8972=>809,8973=>809,8974=>809,8975=>809,8976=>838,8977=>513,8984=>1000,8985=>838,8988=>469,8989=>469,8990=>469,8991=>469,8992=>521,8993=>521,8996=>1152,8997=>1152,8998=>1414,8999=>1152,9000=>1443,9003=>1414,9004=>873,9075=>338,9076=>635,9077=>837,9082=>659,9085=>757,9095=>1152,9108=>873,9115=>500,9116=>500,9117=>500,9118=>500,9119=>500,9120=>500,9121=>500,9122=>500,9123=>500,9124=>500,9125=>500,9126=>500,9127=>750,9128=>750,9129=>750,9130=>750,9131=>750,9132=>750,9133=>750,9134=>521,9166=>838,9167=>945,9187=>873,9189=>769,9192=>636,9250=>635,9251=>635,9312=>896,9313=>896,9314=>896,9315=>896,9316=>896,9317=>896,9318=>896,9319=>896,9320=>896,9321=>896,9472=>602,9473=>602,9474=>602,9475=>602,9476=>602,9477=>602,9478=>602,9479=>602,9480=>602,9481=>602,9482=>602,9483=>602,9484=>602,9485=>602,9486=>602,9487=>602,9488=>602,9489=>602,9490=>602,9491=>602,9492=>602,9493=>602,9494=>602,9495=>602,9496=>602,9497=>602,9498=>602,9499=>602,9500=>602,9501=>602,9502=>602,9503=>602,9504=>602,9505=>602,9506=>602,9507=>602,9508=>602,9509=>602,9510=>602,9511=>602,9512=>602,9513=>602,9514=>602,9515=>602,9516=>602,9517=>602,9518=>602,9519=>602,9520=>602,9521=>602,9522=>602,9523=>602,9524=>602,9525=>602,9526=>602,9527=>602,9528=>602,9529=>602,9530=>602,9531=>602,9532=>602,9533=>602,9534=>602,9535=>602,9536=>602,9537=>602,9538=>602,9539=>602,9540=>602,9541=>602,9542=>602,9543=>602,9544=>602,9545=>602,9546=>602,9547=>602,9548=>602,9549=>602,9550=>602,9551=>602,9552=>602,9553=>602,9554=>602,9555=>602,9556=>602,9557=>602,9558=>602,9559=>602,9560=>602,9561=>602,9562=>602,9563=>602,9564=>602,9565=>602,9566=>602,9567=>602,9568=>602,9569=>602,9570=>602,9571=>602,9572=>602,9573=>602,9574=>602,9575=>602,9576=>602,9577=>602,9578=>602,9579=>602,9580=>602,9581=>602,9582=>602,9583=>602,9584=>602,9585=>602,9586=>602,9587=>602,9588=>602,9589=>602,9590=>602,9591=>602,9592=>602,9593=>602,9594=>602,9595=>602,9596=>602,9597=>602,9598=>602,9599=>602,9600=>769,9601=>769,9602=>769,9603=>769,9604=>769,9605=>769,9606=>769,9607=>769,9608=>769,9609=>769,9610=>769,9611=>769,9612=>769,9613=>769,9614=>769,9615=>769,9616=>769,9617=>769,9618=>769,9619=>769,9620=>769,9621=>769,9622=>769,9623=>769,9624=>769,9625=>769,9626=>769,9627=>769,9628=>769,9629=>769,9630=>769,9631=>769,9632=>945,9633=>945,9634=>945,9635=>945,9636=>945,9637=>945,9638=>945,9639=>945,9640=>945,9641=>945,9642=>678,9643=>678,9644=>945,9645=>945,9646=>550,9647=>550,9648=>769,9649=>769,9650=>769,9651=>769,9652=>502,9653=>502,9654=>769,9655=>769,9656=>502,9657=>502,9658=>769,9659=>769,9660=>769,9661=>769,9662=>502,9663=>502,9664=>769,9665=>769,9666=>502,9667=>502,9668=>769,9669=>769,9670=>769,9671=>769,9672=>769,9673=>873,9674=>494,9675=>873,9676=>873,9677=>873,9678=>873,9679=>873,9680=>873,9681=>873,9682=>873,9683=>873,9684=>873,9685=>873,9686=>527,9687=>527,9688=>791,9689=>970,9690=>970,9691=>970,9692=>387,9693=>387,9694=>387,9695=>387,9696=>873,9697=>873,9698=>769,9699=>769,9700=>769,9701=>769,9702=>590,9703=>945,9704=>945,9705=>945,9706=>945,9707=>945,9708=>769,9709=>769,9710=>769,9711=>1119,9712=>945,9713=>945,9714=>945,9715=>945,9716=>873,9717=>873,9718=>873,9719=>873,9720=>769,9721=>769,9722=>769,9723=>830,9724=>830,9725=>732,9726=>732,9727=>769,9728=>896,9729=>1000,9730=>896,9731=>896,9732=>896,9733=>896,9734=>896,9735=>573,9736=>896,9737=>896,9738=>888,9739=>888,9740=>671,9741=>1013,9742=>1246,9743=>1250,9744=>896,9745=>896,9746=>896,9747=>532,9748=>896,9749=>896,9750=>896,9751=>896,9752=>896,9753=>896,9754=>896,9755=>896,9756=>896,9757=>609,9758=>896,9759=>609,9760=>896,9761=>896,9762=>896,9763=>896,9764=>669,9765=>746,9766=>649,9767=>784,9768=>545,9769=>896,9770=>896,9771=>896,9772=>710,9773=>896,9774=>896,9775=>896,9776=>896,9777=>896,9778=>896,9779=>896,9780=>896,9781=>896,9782=>896,9783=>896,9784=>896,9785=>1042,9786=>1042,9787=>1042,9788=>896,9789=>896,9790=>896,9791=>614,9792=>732,9793=>732,9794=>896,9795=>896,9796=>896,9797=>896,9798=>896,9799=>896,9800=>896,9801=>896,9802=>896,9803=>896,9804=>896,9805=>896,9806=>896,9807=>896,9808=>896,9809=>896,9810=>896,9811=>896,9812=>896,9813=>896,9814=>896,9815=>896,9816=>896,9817=>896,9818=>896,9819=>896,9820=>896,9821=>896,9822=>896,9823=>896,9824=>896,9825=>896,9826=>896,9827=>896,9828=>896,9829=>896,9830=>896,9831=>896,9832=>896,9833=>472,9834=>638,9835=>896,9836=>896,9837=>472,9838=>357,9839=>484,9840=>748,9841=>766,9842=>896,9843=>896,9844=>896,9845=>896,9846=>896,9847=>896,9848=>896,9849=>896,9850=>896,9851=>896,9852=>896,9853=>896,9854=>896,9855=>896,9856=>869,9857=>869,9858=>869,9859=>869,9860=>869,9861=>869,9862=>896,9863=>896,9864=>896,9865=>896,9866=>896,9867=>896,9868=>896,9869=>896,9870=>896,9871=>896,9872=>896,9873=>896,9874=>896,9875=>896,9876=>896,9877=>541,9878=>896,9879=>896,9880=>896,9881=>896,9882=>896,9883=>896,9884=>896,9888=>896,9889=>702,9890=>1004,9891=>1089,9892=>1175,9893=>903,9894=>838,9895=>838,9896=>838,9897=>838,9898=>838,9899=>838,9900=>838,9901=>838,9902=>838,9903=>838,9904=>844,9905=>838,9906=>732,9907=>732,9908=>732,9909=>732,9910=>850,9911=>732,9912=>732,9920=>838,9921=>838,9922=>838,9923=>838,9954=>732,9985=>838,9986=>838,9987=>838,9988=>838,9990=>838,9991=>838,9992=>838,9993=>838,9996=>838,9997=>838,9998=>838,9999=>838,10000=>838,10001=>838,10002=>838,10003=>838,10004=>838,10005=>838,10006=>838,10007=>838,10008=>838,10009=>838,10010=>838,10011=>838,10012=>838,10013=>838,10014=>838,10015=>838,10016=>838,10017=>838,10018=>838,10019=>838,10020=>838,10021=>838,10022=>838,10023=>838,10025=>838,10026=>838,10027=>838,10028=>838,10029=>838,10030=>838,10031=>838,10032=>838,10033=>838,10034=>838,10035=>838,10036=>838,10037=>838,10038=>838,10039=>838,10040=>838,10041=>838,10042=>838,10043=>838,10044=>838,10045=>838,10046=>838,10047=>838,10048=>838,10049=>838,10050=>838,10051=>838,10052=>838,10053=>838,10054=>838,10055=>838,10056=>838,10057=>838,10058=>838,10059=>838,10061=>896,10063=>896,10064=>896,10065=>896,10066=>896,10070=>896,10072=>838,10073=>838,10074=>838,10075=>322,10076=>322,10077=>538,10078=>538,10081=>838,10082=>838,10083=>838,10084=>838,10085=>838,10086=>838,10087=>838,10088=>838,10089=>838,10090=>838,10091=>838,10092=>838,10093=>838,10094=>838,10095=>838,10096=>838,10097=>838,10098=>838,10099=>838,10100=>838,10101=>838,10102=>896,10103=>896,10104=>896,10105=>896,10106=>896,10107=>896,10108=>896,10109=>896,10110=>896,10111=>896,10112=>838,10113=>838,10114=>838,10115=>838,10116=>838,10117=>838,10118=>838,10119=>838,10120=>838,10121=>838,10122=>838,10123=>838,10124=>838,10125=>838,10126=>838,10127=>838,10128=>838,10129=>838,10130=>838,10131=>838,10132=>838,10136=>838,10137=>838,10138=>838,10139=>838,10140=>838,10141=>838,10142=>838,10143=>838,10144=>838,10145=>838,10146=>838,10147=>838,10148=>838,10149=>838,10150=>838,10151=>838,10152=>838,10153=>838,10154=>838,10155=>838,10156=>838,10157=>838,10158=>838,10159=>838,10161=>838,10162=>838,10163=>838,10164=>838,10165=>838,10166=>838,10167=>838,10168=>838,10169=>838,10170=>838,10171=>838,10172=>838,10173=>838,10174=>838,10181=>390,10182=>390,10208=>494,10214=>495,10215=>495,10216=>390,10217=>390,10218=>556,10219=>556,10224=>838,10225=>838,10226=>838,10227=>838,10228=>1157,10229=>1434,10230=>1434,10231=>1434,10232=>1434,10233=>1434,10234=>1434,10235=>1434,10236=>1434,10237=>1434,10238=>1434,10239=>1434,10240=>732,10241=>732,10242=>732,10243=>732,10244=>732,10245=>732,10246=>732,10247=>732,10248=>732,10249=>732,10250=>732,10251=>732,10252=>732,10253=>732,10254=>732,10255=>732,10256=>732,10257=>732,10258=>732,10259=>732,10260=>732,10261=>732,10262=>732,10263=>732,10264=>732,10265=>732,10266=>732,10267=>732,10268=>732,10269=>732,10270=>732,10271=>732,10272=>732,10273=>732,10274=>732,10275=>732,10276=>732,10277=>732,10278=>732,10279=>732,10280=>732,10281=>732,10282=>732,10283=>732,10284=>732,10285=>732,10286=>732,10287=>732,10288=>732,10289=>732,10290=>732,10291=>732,10292=>732,10293=>732,10294=>732,10295=>732,10296=>732,10297=>732,10298=>732,10299=>732,10300=>732,10301=>732,10302=>732,10303=>732,10304=>732,10305=>732,10306=>732,10307=>732,10308=>732,10309=>732,10310=>732,10311=>732,10312=>732,10313=>732,10314=>732,10315=>732,10316=>732,10317=>732,10318=>732,10319=>732,10320=>732,10321=>732,10322=>732,10323=>732,10324=>732,10325=>732,10326=>732,10327=>732,10328=>732,10329=>732,10330=>732,10331=>732,10332=>732,10333=>732,10334=>732,10335=>732,10336=>732,10337=>732,10338=>732,10339=>732,10340=>732,10341=>732,10342=>732,10343=>732,10344=>732,10345=>732,10346=>732,10347=>732,10348=>732,10349=>732,10350=>732,10351=>732,10352=>732,10353=>732,10354=>732,10355=>732,10356=>732,10357=>732,10358=>732,10359=>732,10360=>732,10361=>732,10362=>732,10363=>732,10364=>732,10365=>732,10366=>732,10367=>732,10368=>732,10369=>732,10370=>732,10371=>732,10372=>732,10373=>732,10374=>732,10375=>732,10376=>732,10377=>732,10378=>732,10379=>732,10380=>732,10381=>732,10382=>732,10383=>732,10384=>732,10385=>732,10386=>732,10387=>732,10388=>732,10389=>732,10390=>732,10391=>732,10392=>732,10393=>732,10394=>732,10395=>732,10396=>732,10397=>732,10398=>732,10399=>732,10400=>732,10401=>732,10402=>732,10403=>732,10404=>732,10405=>732,10406=>732,10407=>732,10408=>732,10409=>732,10410=>732,10411=>732,10412=>732,10413=>732,10414=>732,10415=>732,10416=>732,10417=>732,10418=>732,10419=>732,10420=>732,10421=>732,10422=>732,10423=>732,10424=>732,10425=>732,10426=>732,10427=>732,10428=>732,10429=>732,10430=>732,10431=>732,10432=>732,10433=>732,10434=>732,10435=>732,10436=>732,10437=>732,10438=>732,10439=>732,10440=>732,10441=>732,10442=>732,10443=>732,10444=>732,10445=>732,10446=>732,10447=>732,10448=>732,10449=>732,10450=>732,10451=>732,10452=>732,10453=>732,10454=>732,10455=>732,10456=>732,10457=>732,10458=>732,10459=>732,10460=>732,10461=>732,10462=>732,10463=>732,10464=>732,10465=>732,10466=>732,10467=>732,10468=>732,10469=>732,10470=>732,10471=>732,10472=>732,10473=>732,10474=>732,10475=>732,10476=>732,10477=>732,10478=>732,10479=>732,10480=>732,10481=>732,10482=>732,10483=>732,10484=>732,10485=>732,10486=>732,10487=>732,10488=>732,10489=>732,10490=>732,10491=>732,10492=>732,10493=>732,10494=>732,10495=>732,10502=>838,10503=>838,10506=>838,10507=>838,10560=>683,10561=>683,10627=>734,10628=>734,10702=>838,10703=>1000,10704=>1000,10705=>1000,10706=>1000,10707=>1000,10708=>1000,10709=>1000,10731=>494,10746=>838,10747=>838,10752=>1000,10753=>1000,10754=>1000,10764=>1325,10765=>521,10766=>521,10767=>521,10768=>521,10769=>521,10770=>521,10771=>521,10772=>521,10773=>521,10774=>521,10775=>521,10776=>521,10777=>521,10778=>521,10779=>521,10780=>521,10799=>838,10858=>838,10859=>838,10877=>838,10878=>838,10879=>838,10880=>838,10881=>838,10882=>838,10883=>838,10884=>838,10885=>838,10886=>838,10887=>838,10888=>838,10889=>838,10890=>838,10891=>838,10892=>838,10893=>838,10894=>838,10895=>838,10896=>838,10897=>838,10898=>838,10899=>838,10900=>838,10901=>838,10902=>838,10903=>838,10904=>838,10905=>838,10906=>838,10907=>838,10908=>838,10909=>838,10910=>838,10911=>838,10912=>838,10926=>838,10927=>838,10928=>838,10929=>838,10930=>838,10931=>838,10932=>838,10933=>838,10934=>838,10935=>838,10936=>838,10937=>838,10938=>838,11001=>838,11002=>838,11008=>838,11009=>838,11010=>838,11011=>838,11012=>838,11013=>838,11014=>838,11015=>838,11016=>838,11017=>838,11018=>838,11019=>838,11020=>838,11021=>838,11022=>836,11023=>836,11024=>836,11025=>836,11026=>945,11027=>945,11028=>945,11029=>945,11030=>769,11031=>769,11032=>769,11033=>769,11034=>945,11039=>869,11040=>869,11041=>873,11042=>873,11043=>873,11044=>1119,11091=>869,11092=>869,11360=>557,11361=>278,11362=>557,11363=>603,11364=>695,11365=>613,11366=>392,11367=>752,11368=>634,11369=>656,11370=>579,11371=>685,11372=>525,11373=>781,11374=>863,11375=>684,11376=>781,11377=>734,11378=>1128,11379=>961,11380=>592,11381=>654,11382=>568,11383=>660,11385=>414,11386=>612,11387=>491,11388=>175,11389=>431,11390=>635,11391=>685,11520=>591,11521=>595,11522=>564,11523=>602,11524=>587,11525=>911,11526=>626,11527=>952,11528=>595,11529=>607,11530=>954,11531=>620,11532=>595,11533=>926,11534=>595,11535=>806,11536=>931,11537=>584,11538=>592,11539=>923,11540=>953,11541=>828,11542=>596,11543=>595,11544=>590,11545=>592,11546=>592,11547=>621,11548=>920,11549=>589,11550=>586,11551=>581,11552=>914,11553=>596,11554=>595,11555=>592,11556=>642,11557=>901,11568=>646,11569=>888,11570=>888,11571=>682,11572=>684,11573=>635,11574=>562,11575=>684,11576=>684,11577=>632,11578=>632,11579=>683,11580=>875,11581=>685,11582=>491,11583=>685,11584=>888,11585=>888,11586=>300,11587=>627,11588=>752,11589=>656,11590=>527,11591=>685,11592=>645,11593=>632,11594=>502,11595=>953,11596=>778,11597=>748,11598=>621,11599=>295,11600=>778,11601=>295,11602=>752,11603=>633,11604=>888,11605=>888,11606=>752,11607=>320,11608=>749,11609=>888,11610=>888,11611=>698,11612=>768,11613=>685,11614=>698,11615=>622,11616=>684,11617=>752,11618=>632,11619=>788,11620=>567,11621=>788,11631=>515,11800=>531,11806=>838,11810=>390,11811=>390,11812=>390,11813=>390,11822=>531,19904=>896,19905=>896,19906=>896,19907=>896,19908=>896,19909=>896,19910=>896,19911=>896,19912=>896,19913=>896,19914=>896,19915=>896,19916=>896,19917=>896,19918=>896,19919=>896,19920=>896,19921=>896,19922=>896,19923=>896,19924=>896,19925=>896,19926=>896,19927=>896,19928=>896,19929=>896,19930=>896,19931=>896,19932=>896,19933=>896,19934=>896,19935=>896,19936=>896,19937=>896,19938=>896,19939=>896,19940=>896,19941=>896,19942=>896,19943=>896,19944=>896,19945=>896,19946=>896,19947=>896,19948=>896,19949=>896,19950=>896,19951=>896,19952=>896,19953=>896,19954=>896,19955=>896,19956=>896,19957=>896,19958=>896,19959=>896,19960=>896,19961=>896,19962=>896,19963=>896,19964=>896,19965=>896,19966=>896,19967=>896,42192=>686,42193=>603,42194=>603,42195=>770,42196=>611,42197=>611,42198=>775,42199=>656,42200=>656,42201=>512,42202=>698,42203=>703,42204=>685,42205=>575,42206=>575,42207=>863,42208=>748,42209=>557,42210=>635,42211=>695,42212=>695,42213=>684,42214=>684,42215=>752,42216=>775,42217=>512,42218=>989,42219=>685,42220=>611,42221=>686,42222=>684,42223=>684,42224=>632,42225=>632,42226=>295,42227=>787,42228=>732,42229=>732,42230=>557,42231=>767,42232=>300,42233=>300,42234=>596,42235=>596,42236=>300,42237=>300,42238=>588,42239=>588,42564=>635,42565=>521,42566=>354,42567=>338,42572=>1180,42573=>1028,42576=>1029,42577=>906,42580=>1080,42581=>842,42582=>977,42583=>843,42594=>1062,42595=>912,42596=>1066,42597=>901,42598=>1178,42599=>1008,42600=>787,42601=>612,42602=>855,42603=>712,42604=>1358,42605=>1019,42606=>879,42634=>782,42635=>685,42636=>611,42637=>583,42644=>686,42645=>634,42760=>493,42761=>493,42762=>493,42763=>493,42764=>493,42765=>493,42766=>493,42767=>493,42768=>493,42769=>493,42770=>493,42771=>493,42772=>493,42773=>493,42774=>493,42779=>369,42780=>369,42781=>252,42782=>252,42783=>252,42786=>385,42787=>356,42788=>472,42789=>472,42790=>752,42791=>634,42792=>878,42793=>709,42794=>614,42795=>541,42800=>491,42801=>521,42802=>1250,42803=>985,42804=>1203,42805=>990,42806=>1142,42807=>981,42808=>971,42809=>818,42810=>971,42811=>818,42812=>959,42813=>818,42814=>703,42815=>549,42816=>656,42817=>583,42822=>680,42823=>392,42824=>582,42825=>427,42826=>807,42827=>704,42830=>1358,42831=>1019,42832=>603,42833=>635,42834=>734,42835=>774,42838=>787,42839=>635,42852=>605,42853=>635,42854=>605,42855=>635,42880=>557,42881=>278,42882=>735,42883=>634,42889=>337,42890=>376,42891=>401,42892=>275,42893=>686,42894=>487,42896=>772,42897=>667,42912=>775,42913=>635,42914=>656,42915=>579,42916=>748,42917=>634,42918=>695,42919=>411,42920=>635,42921=>521,42922=>801,43002=>915,43003=>575,43004=>603,43005=>863,43006=>295,43007=>1199,61184=>213,61185=>238,61186=>257,61187=>264,61188=>267,61189=>238,61190=>213,61191=>238,61192=>257,61193=>264,61194=>257,61195=>238,61196=>213,61197=>238,61198=>257,61199=>264,61200=>257,61201=>238,61202=>213,61203=>238,61204=>267,61205=>264,61206=>257,61207=>238,61208=>213,61209=>275,61440=>977,61441=>977,61442=>977,61443=>977,62464=>580,62465=>580,62466=>624,62467=>889,62468=>585,62469=>580,62470=>653,62471=>882,62472=>555,62473=>580,62474=>1168,62475=>589,62476=>590,62477=>869,62478=>580,62479=>589,62480=>914,62481=>590,62482=>731,62483=>583,62484=>872,62485=>589,62486=>895,62487=>589,62488=>589,62489=>590,62490=>649,62491=>589,62492=>589,62493=>599,62494=>590,62495=>516,62496=>580,62497=>584,62498=>580,62499=>580,62500=>581,62501=>638,62502=>955,62504=>931,62505=>808,62506=>508,62507=>508,62508=>508,62509=>508,62510=>508,62511=>508,62512=>508,62513=>508,62514=>508,62515=>508,62516=>518,62517=>518,62518=>518,62519=>787,62520=>787,62521=>787,62522=>787,62523=>787,62524=>546,62525=>546,62526=>546,62527=>546,62528=>546,62529=>546,63173=>612,64256=>689,64257=>630,64258=>630,64259=>967,64260=>967,64261=>686,64262=>861,64275=>1202,64276=>1202,64277=>1196,64278=>1186,64279=>1529,64285=>224,64286=>0,64287=>331,64288=>636,64289=>856,64290=>774,64291=>906,64292=>771,64293=>843,64294=>855,64295=>807,64296=>875,64297=>838,64298=>708,64299=>708,64300=>708,64301=>708,64302=>668,64303=>668,64304=>668,64305=>578,64306=>412,64307=>546,64308=>653,64309=>355,64310=>406,64312=>648,64313=>330,64314=>537,64315=>529,64316=>568,64318=>679,64320=>399,64321=>649,64323=>640,64324=>625,64326=>593,64327=>709,64328=>564,64329=>708,64330=>657,64331=>272,64332=>578,64333=>529,64334=>625,64335=>629,64338=>941,64339=>982,64340=>278,64341=>302,64342=>941,64343=>982,64344=>278,64345=>302,64346=>941,64347=>982,64348=>278,64349=>302,64350=>941,64351=>982,64352=>278,64353=>302,64354=>941,64355=>982,64356=>278,64357=>302,64358=>941,64359=>982,64360=>278,64361=>302,64362=>1037,64363=>1035,64364=>478,64365=>506,64366=>1037,64367=>1035,64368=>478,64369=>506,64370=>646,64371=>646,64372=>618,64373=>646,64374=>646,64375=>646,64376=>618,64377=>646,64378=>646,64379=>646,64380=>618,64381=>646,64382=>646,64383=>646,64384=>618,64385=>646,64386=>445,64387=>525,64388=>445,64389=>525,64390=>445,64391=>525,64392=>445,64393=>525,64394=>483,64395=>552,64396=>483,64397=>552,64398=>895,64399=>895,64400=>476,64401=>552,64402=>895,64403=>895,64404=>476,64405=>552,64406=>895,64407=>895,64408=>476,64409=>552,64410=>895,64411=>895,64412=>476,64413=>552,64414=>734,64415=>761,64416=>734,64417=>761,64418=>278,64419=>302,64426=>698,64427=>632,64428=>527,64429=>461,64467=>824,64468=>843,64469=>476,64470=>552,64473=>483,64474=>517,64488=>278,64489=>302,64508=>783,64509=>833,64510=>278,64511=>302,65024=>0,65025=>0,65026=>0,65027=>0,65028=>0,65029=>0,65030=>0,65031=>0,65032=>0,65033=>0,65034=>0,65035=>0,65036=>0,65037=>0,65038=>0,65039=>0,65056=>0,65057=>0,65058=>0,65059=>0,65136=>293,65137=>293,65138=>293,65139=>262,65140=>293,65142=>293,65143=>293,65144=>293,65145=>293,65146=>293,65147=>293,65148=>293,65149=>293,65150=>293,65151=>293,65152=>470,65153=>278,65154=>305,65155=>278,65156=>305,65157=>483,65158=>517,65159=>278,65160=>305,65161=>783,65162=>833,65163=>278,65164=>302,65165=>278,65166=>305,65167=>941,65168=>982,65169=>278,65170=>302,65171=>524,65172=>536,65173=>941,65174=>982,65175=>278,65176=>302,65177=>941,65178=>982,65179=>278,65180=>302,65181=>646,65182=>646,65183=>618,65184=>646,65185=>646,65186=>646,65187=>618,65188=>646,65189=>646,65190=>646,65191=>618,65192=>646,65193=>445,65194=>525,65195=>445,65196=>525,65197=>483,65198=>552,65199=>483,65200=>552,65201=>1221,65202=>1275,65203=>838,65204=>892,65205=>1221,65206=>1275,65207=>838,65208=>892,65209=>1209,65210=>1225,65211=>849,65212=>867,65213=>1209,65214=>1225,65215=>849,65216=>867,65217=>925,65218=>949,65219=>796,65220=>820,65221=>925,65222=>949,65223=>796,65224=>820,65225=>597,65226=>532,65227=>597,65228=>482,65229=>597,65230=>532,65231=>523,65232=>482,65233=>1037,65234=>1035,65235=>478,65236=>506,65237=>776,65238=>834,65239=>478,65240=>506,65241=>824,65242=>843,65243=>476,65244=>552,65245=>727,65246=>757,65247=>305,65248=>331,65249=>619,65250=>666,65251=>536,65252=>578,65253=>734,65254=>761,65255=>278,65256=>302,65257=>524,65258=>536,65259=>527,65260=>461,65261=>483,65262=>517,65263=>783,65264=>833,65265=>783,65266=>833,65267=>278,65268=>302,65269=>570,65270=>597,65271=>570,65272=>597,65273=>570,65274=>597,65275=>570,65276=>597,65279=>0,65529=>0,65530=>0,65531=>0,65532=>0,65533=>1025,65535=>600); -// --- EOF --- diff --git a/lib/combodo/tcpdf/fonts/dejavusans.z b/lib/combodo/tcpdf/fonts/dejavusans.z deleted file mode 100644 index d0c4d3de7a82cc63c15cbcc1d29dab60dfc4173a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 375806 zcmYhCRZv_(*RBJ>8Qk67gS!QHf@=mF2sXI8Ly(}sbqIvu?iLu_-QC@tKi_}8bLw=} z)4MNLSJ&=~?p3Sb*E8$n710+@W?mp}eB{pAN2!y)eM0I$rb$*p=m$D%IKKCfwN{=V z=+xAoKW9WniXcS>MwZ~pz_93H;$i)3REsZTBWtw$xDD>Ec|5}#I zUKV#PcPkQ2sL=<{qbJ(YO9^nN=$MH!^TUbks*z_jm zb&#-0Vcn)(j|4Lvz}+T!D7 zNhxR!kWlfvgCoD<*#$0#A^k=EA%(j!DaE?sBt^R6-;LoZArC8}FOMK1V~yg;olmqe z8kQQ^h`l5sXdea)#2}!Te!>O9Y@mjP1#)1QBgODdMhI|8{Xz32t47~&>wErC$-oEK z_G5wc0^iKGYk5EyD>Wd+ky7U250=A%J$Wl^5jg$|{Mat4}pyRv=jBfVRQxTVo5AymV zMQZnw0s#vH-Mts7SY9E|8^$zG?&lF0wRZ&t)H(zlTN(AXWD;w9Y$PA-<};++Q_XR) zhIigrn#g|OkLKa}WX>&qP#W5jC|fzr5ElkH@0#dd%FAm1SSeD8`S5$`d-ooo!FrbT zt5SHQgA6d!%AV1JDgXGg6Fk4{f^0d)sI{D*0hlA1@mu&X6WQGWa0gb+=fQ*^UTET~#1CaHvRU{H z9$B^^=4=i2p^q(qk3(v(LnAV%lg@R~CM>hX>PEWJs31irg$~hn9tOU@KnQ3T79~X* z(qzQT8n!uwoSKMQ?-qhj!Tudn7P&C2x<>%m#wq!eRv8~ZxIg+v=CQz!t3%I})Vi`W zDNXYiFWd!*IzQ4^HLL|M9^4*ABpgcR5KfXFUnC`}KcNX2K+#Y(%m(QX>mN@;x{k&i zp95et00*?+69aR#)|@uGdMZm^f<}8HBNw+mD*x6h_5*LqGJm9pi<|$rfK`E;9x9Xn zLEhL)KwP>_RVh(+9pSpDyASjOiLWL{&lC`SAA`0*UTpvQPv>Wi0C*{s&@0Ru%9$d_ zMKeGZC8XKXX@w|cXB(nk_BVh!#dcCQVVBGrLnsiv(ELF92Ki?B`hdD6xS|kNx$1j4 zp?6#mN+)Aj_%B?1e|H~6q_JkQaOaw-?^wWzk#kTLdI%QqkoP?BxmU4J7pu1q94mR8 zE2Vp2aKJc%PP3PGx$z@g8l|=!Yh#Ugo8c9s+?OVaA7+y0X#H!0zc*g6qm+6*T6ko@2`g^@N= z3d=AZBse8LNOG7ZC;{9tLyY^lFtI6%BukL;nYGg}gE5IGQ@@nHas=;~Hb+~SCrEvw z*lFcE$Ux2mS%t*uqdd`3xDMk_u(V42B9)SxK)%5e3K`2sJ^0iT?l7eq>vr-NO8}i= z6Oa{Ew%sB?!r#y4WO%^eEP#RWxA%fj1bMv6Bmw;N)_#&P~kIqUO$B~1jufL^kuCXDb??Qv(U!b zX}@^kHI{KQ^`=XLjs3=7kxo<`L{A?)yV8Cn83j%Lh>4By9l?nEN)D#I_A~!EPXd*d z^yhnv0?|Z&=2MkNJon`vy6M>SL({(NK+o~UzaF;L$lX6*3rRT!?b35sc8ai+Askr1 zU4=>XU=9$%GD#m;4S2zd#B4J@}QPN5d1STNow+Ny`7cq&Yt&#KDLdP(jsdgj- zotVfGU|s}7kb3|~E>x_cRir)4NVZggqCJLGCxKOnJupZSRHPvnRH15=zA&32p)r^h z5>4p&A4)#7Cv9UI_mVNjU?|d132W3em%ghaT(0iP3ofDtQl}57Tc8 zNOX>O9>Lc$if&9|oTp|C&0D|UR=do-G`(EEOnWGML0iN0lnitC z3L~VFl*eI4(GFXZQn#k%AuvEC3v-a-$nWID71=`W;Q=;qn(8tC!MzH*?ZF4ORw*qo zkYdLnF@(m4a`y;s27~pR=vQ#N>v7yBnPelK%o2Z6Sw+wGwQMNx;TuNV_l=oV{A57K zjfgV;tFQ%ds%TO-Vz0oSk0$9W-$Hka_mmJ}CC3rR702qt9FHOBW7%@6mY_~#)u(I3 zrGqcREp1Dtn@v7aKr1TNjGHkzqP|UdQVfA$O$pdU^L)u*U`y4JFN3&ES=nUPeOY25 zOJ4i2mZYkXt6-|Iu8>w#Hib5r;H95(TB95H180Y)xxh%ff(>z3*4d@GensPq{yy<} zSbA6E3eGD-#4v}0BSm-U@ygpPrp zOED|4$bvCl(G60OSk9wkz-*r~rdW~q3!oLwWS*=r1hA~AQP;2dqdCV+l2Sf|ZW-?^ zA^3;%i$ntcrubXjlF4boo%-|d zkXfuF0k>$OFWJA?b#zP0X5Egg+%j9ftd@~$t!u1*Q7g?YH7#8)O`9n@LYtlNRGB@= z(2beIuHz{$(9td{hp(44a4D~!(>N}^oqDpBuGd(Cv(Ml&%&cUa)%o_g~VzUot0ArI!O0+Yp=*D=btk?vcDbkuE_a? zF%xlUexvXN@T=%hH?63gnm;1BEq_Ayi}#lh|3fh?J|jNaIWc}raLe-K*4`z>TGRK< z$*_PGMkyN7MmMZEtvNo`H8qoHZsT}pb_hJQC9)#|5`ogq(rwZ~`gZz2eS3Y-qTQm^ zqRpbMptTqDDrYx&mwQ+@^_(@0RhNyQH9V#9w@&Md7SKXyjbvY~|$S_~kg{0-)+p zMkpMV2WkiPg=#_-$_rItaE?}8J#>{7 z*v?WI1AvNaTWTw~mlqcnrxxcH7t@bNT+m(7UE-WnoyWjqZtSk?9u>|NZVs*vZfD># zCvq^kJGqPh!OP#ruMwew_0Low5LjwbMW8it*DG=t zD5$_35Ec}(Vo{P#ec5HYVAb@^12E=5%&pmZT2pUSs3 z2GuMrEc_;K(?dIVBD_lIOApvf-C8kAoo@T~AtXhw1#>Q5mHUOY7pHe9y+?DT1E=rn z`Bc`P{uI**YY1%%kEkmjt?nP=UB+ychx=(I2tk_pYhBhN%e$2~p_`Ql(GzE+# zm#N8Q36$Ytf~dZW%3Tf>jN3S$+aH}Pwmp{EH?qiW9xY7OxLaY$wrp+2J-yci!}g_P zT$jt%N|p9x6*xWK1q#bmpN8wG|73kiG>y~f4^^fJm%d4js>MDNFa#U|e7M@=a%>ro z`B=ceWEdMzNn(JD-l=oqF9y@!Lha-{4W)>m-EFVZESmnXma~O74(|Lm^Q^q-WHGno zIW?lkqkmyJWMZY;Rh#ZTp>+6ya-J^MIHMD8;F?~4Mt*pIv`we;bvySU^r8c^csZZG zEIQxjhqSw3oALbt$L1%@HPfL95#|1#a_uJ8Ri)w8x&B{6#mOl=R;|NCh%uY(MQ5tb zPqs`z;!3+?hr&%`Z$C!yGPOU4Ims+p?_%p1OFev5xuQ-wnL|!7Q4N`8M3PT(~Ggzb$#b12Jo*&FbClk zbV1F8G{TSW<*hc-MzGTjP!}O#P}0_6hvy3bJE}fdqQ-=AmjqqJSj(UqnYM%+$ao0f zGc4?hZi$Aad5T~8$Ll@|=h<50Aj7O2&G`)_42xT~oFN12Rc)};J zr3{g>snqR%AOa~vftUv^5ek@A5)oo!+vzy97g6)d*fkzPU zP6?_!F*x}PrJ{@9+-KT(nzkJTx@)5+D$WfH_zR%Q?9v}#DOz?1^k=g;ud3 z92U`aW|%@9_ZlySAKPCf-^kwD-!qloJDYF*@8{m-Ft5^p`xSriD@g-7vyOoZl`&QX z#??NfDz8`veN&8+1A<3Tw*A<}9Ij^82;{IY!MHVH*GS%}Ce5fgA^UUy{tSh}%Jz;h z^ol`)@q4~M@pOgHq45Q;du6*_`?`?gi%L&Ga?w-<#fRF+T`z5{cx<>m1>MQ}as|}jWtH_JScNxhR z7bZM_LfVf0gXa07gNEF3DQ>tD0lO~ByT7-5IMc78YLmf@ z+@f5T@PwLX!qi={6iw?pqF4LFU41m^gbJ{%qsA%lNWmy)k{NE%-~baa-g~4DP`c(UN7vc-%#^H~+y(CV z=}t8wlo02OTPRV8O_;iGa%H#nqbSr6XAU}?4$<)BSbTe~ffn_Jl9l>#0f`n3t&fht znRpdJ=T)XI%|vvZtYj7&MqI2(;&gyil}>fo-qWv{n*UD4gz`500){@02s^Z-O-?26 z^!gTMieFjO)Jf51`u4_rq89c1w&!fR2p?DvZ`Au> zDh_JWHI1?C3x_vQQ{&^W4$JDZXy)+yDQAyKM~_K6s&sJ=-EzE|DnKXcRgmLxxyMn7 z&;0>d)T%hyn}h0EtQdFgkm{!iyE|9e&_*`#xru*|u?Ql;t*447=$!8r*rl|wT6b{j zeZ|h?<2bDfw-~BLg-4ZNqfP|OZ%`+};#(f6Ufk2-Th1D@%9N{G-0O2~ATlsUS7}u{YI|VE{r1s-(Bt2oG)ccC6LElRTwr(;+0i=k(wE;_ZuYvquzZ=D zLu65w_>SC61m>Njf`r1$XecY$BXi15$6xLEbB%=x(VFt=dWr# zp%FyNUpccO^X8t?2pWWKs`=J?S-1#`)2-?@dt|kQ7A!}hzV5R)fX1}FAGT={!I6Xv zbD!l;nBApa&vFW%2M-*qwXD*p%x;k)1Yj7$oka7}DBv|{W=QL0$u#(9P;cd=-{(3A z@`%I(=i(@oY-FiC!Z)cqYiRvY#N(#Ej~DW6%YDhX^kW)bSPTbH4|%~L3np8=^d?(L z(L(V1^7p^z@tAv!OpPSgmdqgWrRI!tKzO!6|EAFB=Y-Xb`c9iM&KHA-;3knLE1MTc zWnwU5FbWA}l{N&Xdhf@h*#4%Pv2e-x%G;swu&i<2>*^Lw`(#!@Mf1G)(z+FZocDYp zT@Q=Rp8Qm37VVQ6r%|h}pnXu$Pz!FJN!Xxc$1eisj@GaC< zn8~BEgv<1wg5J}<9{LS-Y6f%0BcifS_$3X4y|Th=x4fHR9HL#oJ}dC|U4EBeMPTE5 zzg#GbU~u%aTzqRockExjP;Dci_P5k-Ye8>>aD ztzeH$8!PWJMeO_LP(*O37M`eK0h=ysmGo%Aq_1!_=v@jv>mM96>@1dBIi#a>5tu{4}yxP84j@R z>p0mq$FAr&AT~w_caiPIIZ-(0f=$8u%`q!@XF|GNI3|1LZJF^~AAM0wbH=x9uWla@ ze7}fAIF5U4`ds)ucE2F`lZuDs4vudVT(cbDP%+ETe0dgs2)KCPco(AmN{~3=H`4D0 zKU|9)_j`l)RC2b<(VIjYQTPI8q1$w`Bz77s^gHAndSCbqHlH}Sy^wC={T(m7se0hQ zLgpd2=*dbRPfn@2^*L6;(Q7h+X&hTx_f}1SISrId+%4%Y`ico$haOP_m+Z@F8Y!b*Zu}7d}%>U zF-k;$F;aCp0WtLwWf2Nxel$s-8Vz!`xS>}+{Qf-=6yD1uJg12voDhh`8(Fr6L)z3c=`eeG0@Xj1>r`#S9sk3 zh0y_)KQ?o8bU)RZrP~!nSDWZvH1^JBT4B!#h+GV^~;l%Gn=z1Y^zC-gM zAQm;g!TosTYb=)OIMTSYe3kuZBozw-rF^=kTWLiy8*i$CqCI3xvm%)REje7l zyhvdRU{g`2ZopoiIHyPgDW5{OiFcI{VkJuwOBValkuau20AZPOE0v(HVKuaDB&9># z!EJ8KqMJ`X9z@$Ic8*&yIitQ$cpeJb#kvykiWd2j!@!ZMJ5aXkc4g(2+4g0Pg(7+V z$9j_5VD6yl;QCM#uyVp^6(JvZgI4h#;o=);{5(n zg>T^*r8>IDzZbum*F%A3F1ue z5!bEsEzT|KZJW17dx42ADo?>+hPI2XhJl3Apkl3|5XP;OS(%QOLV8d-KDu*O?2H_&t}bU z;6zm_OLS*#k0slGtQk3$d(5;Rw%@!xsrx01N#+)h&+Q*8-KKbVbeOCcIL><b#i6A0t zA}b>Ebc=kKl6Y>itIFJ+M$7a|$!^`{Af)F4>lK>Es*1PjNfRIP&xEuUMias2|O~idF zoJyG0LwU?$R}-$8xYs$dbQ{7{Mn5*SAKI&le)UIYCxTPKid>${;yxC5xJo3J4T=9c zvGX7eD6Xkp<9twJQvCzy?7xV*KOoo}OEjV9=<)u71fsJuXR=dmAjH@<_dpIYzGvArZaI-eTMz(uVagWz^#+4(^v*;XM8KFyI7h^Eg@CMaoc$SDHGS z3NrFMbK1dkmppk$+QD+$hxPFbEC59}7^7D-U<-rWFOGvVYY|;6bF-XCZp5cr^kCs6 z$}UX=de`luO{8olSPrS%wc>0FmP|V5CnD7~DE4A|%Z5-`F@4__Df_t3rULDxZW%fu zqJ?pAjy3K}Zz%}ev;(QhBZ}c6=%#5d&uA0_LLUg}NvOyUP;L9bIvu6ZHC7?hp3-%P zbK(3?xv0mT#i?R_7j(sOXwzLqS`6Sq6&AaphRF`SwGj|=zLUOXc)-X-qvEt+?P+0; z)6#kLCFgTT3WU|X-i(I8IeF8{d%;ugt0VD-@#YQic4fqw9Od}d%Jgj|nJ(3Vih zSyGtnt7B$zkSlDV3_*0zx@&`?Wv#XXr@v9?QMF*1T^&{&;#bmUva!j>GJ4KLUmRY` z!a*xL{4)6O%xZ-?2Z)3kdlOuAM}ZDKlgNfu@NVH)#b}}C?tQ^K6%UZ0NRqU`eEM$tmscv+MWu=U05DHlH>FSLHYRJ@ zRpLVTl-N4(8rcy%2?-s$MD~Rh8rR({%X0+!>XZ3F)ixLk&UbU1Ic`F-7%(Kndpxai zpWtObCrzmQd#gajn_T2$o%qKT*QbVQjZf~(oy_x9hK9v#y(XtbY!uIR^-Dse<@OVN z8v=yVZK1E6(F;*Y^`cAUSp}!lciUR0Xs0S!744Aruwh$ATRA6qLZEM8Eo%f@gp(VT z3Cd*Dd--GA+-Ul;bep>3v}vd5d*-yD=*p1(v_6jbXV4wkmSBI&$tUf=c_WU!kp=6% zfZNA2w5+BKhJ5?*j3{p3i~L?BZr(HJLL}%~6j4;}vUV+Ijp7njY>VbWCiiUmQYUwQ zzmMb5>d7iN`?Zt7^1WVdsEyb76=qCA=&(0;LwsxeV*dg4#qy0f;EO~s<3aG3NX)HJ zS}N%Q+~25fVRre|6Png6uK3PjBEUROWkMQdY%3&}u&^FyU`mzF!oZ&30ePNzPeczx z4?&ODW&v2Hi5)kxXoMBI>iz)@UoLW6aZljQ^!z<4Dd}JC{-uI_KBe{@LKOFYx+-2j zo3|uyU(ui={CjoA@kP5r9Gq$qx=O@fZDZ~C54{OUVY*Z(+9dmQ=PhCB&B`8+Yba=)^? z3cn`$Yj@_8;I9=JoZwf|^(TH+sMV^|s-J0qV~b@SWh-YRV_RiyXMJUpW-DaHVV!2J zWxHlmVq;-@OubEIOFd0BPW4NbPNhl3NsVU(vF@`Hu%@xiv+|b@FdMj)O%nrSYw7j5 z|D?|y&9%(g*_zub*&5n{Y%6%jg(ieXg!+XBg?feNTP9joT83KYS|(d&TY6id-d)}c z-Xl->w>ZZHbJue*b1ZYmbFd`UrF^ZUwlURo3sZJ@_S*LK_L7E$?^EsKs&b(;V?TBV zz!pNkg^z@4$YROZ$n43o$(rLtpb}6{C?S*<3V<3x&7dgIZ%`qq6_gLE3N?XBLWSe* zyS84$ePU9}N?9U0=n_O!b2(pQz>Z8i8Qd?}A!SNb^I?(=)Hu3kRc43!S>0pkAf`?( z5#AF6oZNv8Y=qIQwBEDf3Th}3Y5#`UQ&s}cE;PiFXTBJ_2HpShpeg0m0KGG-#IxQu z;ORR{UE(Z<4s#ID*07mkL9t5k12PeM!r6i8_*6LOfjMVN3U1#S7Z&(wr<}wm_>NL| zJ*0bOie&`fdA$m^wk_)9n|FN4R%>l)YF%VKOq;JxYs3K&DJtk85!;%L>)cA9kbqCO zNY$eL`FEXm{#0x7)i`UWE1>W#pVMKMX_s-4qF)2&sb?t5U06;9nG%su8LiM$i^;V2 zaze-~sgSa&Nj_(is5V(j%w;LI@y+ zJIBy-{H$byQl08NWT%f5eoyRD?^9Xj?~eF)Subbl&kLu>UzOVM*xse9ECokJ!KFPKdqag-tUN?y?-AeCJjDQ5qbJMbaPz2A7L|Ln|YiiJy`(X(vox;HSl(zFtQ47BMn z9(2RG(eMk9S#mSGr*Ihm0X+GI8`AV{YwTa%QYIZJY4-2rQJ>LBs6qmOuGsnIvKp z(c@XIM>VyIY@`vrJ)LrDb(EsvhfCJJhyhD(3~W4q@_Bs`(C;CcCh+F`ZdhC-Mo`>ZmV8Iy8x3JaZXG_U zYR&Y%!$WY(_%dLzOJSues=cHu-6BxHBie=m{-{4Tu7_-AN^p*nRMh~v1$bc=Djj`& zDs-;SLbZbs-@~+m{$Ku-^s#VgBR*9Hqn?BPyLb$dg$cvjknGtXM`F zBV8DGZaX4*sRHxGi198rpVm2S_Y)gWE&hW?>Xo65_rUWhg^up|sn?KaJUwDMKKfv7 zX}3y@cDa@nn9hbTn*@Vpv@XC+=HgT^YLos1TQ*Gwa-~qgrTDof88`J)O7}EGG$jk< z)sNIEt;mKl$b{fgW#9(n^!?5+1bAn;;7nEWX0 zdGoD=pFA?6K+F@4JRV_-%@dV4sB&9;LY~i5EOj(Z&GLHpdBOJ)WY_V+I-hVH-Lc{A z)IND`Bwj)B6hhL4Cc)n`Q$%47%6_2Xs)Il40zG z_+rNI7+$blFm}+aW5w^aUanpcb|9{QjE7ubdXl~iybI)XaqOjSM7<#Rf6N(i+&2w! z>ibt|3-owrerL{MzfVToAiDbM#p545Hn+{NTYAOXrs!|YQ|pW!oj(71eN$QE^<-?9<4=+KYkhq05TnZLDdb-S8=qRh&(UcL%j=tSVO2r) zZ5%tDH#txiH~Ra|h_lt^uwD2YXy0ic*|*PY>XE5q?`7o?zGL@g>5-S+*?;>boKh%2 zjWfHG0rnr*|6tdxVM(WL(KOzbPh^>%4J?}0_tlIa+e(T!U=_1b0bMGPoMWs}DCi2s zs5u|9iXEQSKA#jtjPJT6<+#e`-V}2`(Q@3ZrZg^i==#f$-}R+f|AX)!djI(Fyrl^H z9BxVde5OeJ51G5wly4`kERqRcE~;zMBdbmxnemko2fFc?4(R#3X6pj498VP})cTm; zqyoLMOBihak2otY=f*}b$b0IR4(>=HFXw-|8+{S|I3&aPk#&5f`1Urw$s2TUjBKgg{K^TB1MCHe z+5-3T#}k|1&F(biH%wgmegAHMkqDo#Y_b988o#)`Xp)@vQJhta@qIra-FKwn#of58 zb3I+W4u2wkMz(GvOPU!r6;Rpbw7OSv*tdcfyIb(~#91Hv*G`?_@+Ukyz@2WZ}E2GGu# zIex{;w%Q%Dwi_{4^c2&(-vzq)Yp6D5?^Ax~|CDZ5ud`YA?BW2mW}i6W%9r7r)MERDz5k*aYru zJD@4D7MvSa^Sj)J-*pUsUTS^s9i}_45pRUOFxoFnFA-;Wo~@!(A25<1bBid-*QFw- zM-zJ?JhXJHOnx!Tm`6;&EcSk-Ef^V`(X#v;7Mmy2l$h4J^VkCZXj_B;OJ1tN(o3?H zZZ*hklcw_?dqy6ugZkY{r<_Wm&!z{U6n^O`hpzfr`Q`X&*R*n+%u=IO*5_7X8_gg> zd>j=>)@#D{=ofw%^69Q1H1Sxu^r7)6GguSg-DvPGOY|NR@ZDd6cZ2{ha_U zFC3^yb^O>bv|R)Bk*KP^a}Fzm|?i9_ef?eqpOq*rhpe z@%f(|>1RC`oAJP#G4k$Rve7=jTjC{|C?dprqVq-0tNY;I^w2o0ZT`Ke{e|Ki!-P{; zCkvGBZKxCEH2k(o!7dokOb%pYI&5@Iezl*Qx#4_&{r1-Q2BS;xi7nxZ;_CFhx2`}F z`jQy+mG^y#F~wViL5VKz4PE%zfe1bKGo1?uoeO8|yA|H@mtl0B(r44#`1i&200WxP zI{T3Ku_wIv)wieBVa3H<1yWJnsmk|qp^tdu$p&iy=jY-o;xu-5RSP-EYax#r#n3mk zBU7uao1NVGOVg}P?|RRFaz1Ik7TZBtytht`&i5+F^Ln~C8|tL-o|>bh;pNL=0O(b5 z-{ZaYNLTaDcrW+8^(}Ai_-*={`5pL*O`P=Z^S1szLy?3aL~~~<Z?ErNFQ!f=+s54M>wk1FUwil7-+tw&t?!;YiskaX=QXx< z@8zpJd`owFIJxji`#yBo*4wjHH^rdQ|2HA+;%K#fDPU3uQuQmgvPM|Dpk+C$`jZub zlT2l}xE$-`hsxB3f`KnujYVm{Lai1}+I>{stX`46#h#pGM=5|YlL3fwxuTThkRGZ$ zSAoyTFcG0c-Bg7rV8#+^QfBKCMR{p`@IeU*DZUmSI?Hc_2sG`8-negFn-aX6;NYDZ zDRwOqbpGETBM@i9dSlK)dJ$=M`Waz)gJ`hpLupV%;pBK`s(GU&Pd6fEvNs~7vo|ja zBQ}xp*uj4bCBd|LQDE8v8!&DDp*2F?9+!aTgt9>5q@94~B&opEgqZ+b9d3DGhIp)w z^y*yKrpzO_s1UR{Adxv4qfXJ{P($hsA7@?n@iaK&B!Y Y#(>2uaS%6)EoOfRhw& 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�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[ARRMhj-nWN965j zrI_4HIKXqV33bzKwM(MJseNs}axlkSIhe_nL(NH9Dv_uOI1#l_cT#qg;4^KN4HbwD z6=Jo$q9q#$2M8}>*pS8AoVHY3Z(CmrYqVNjZhO47jWx-Yi#ng->Sgb19fi6+$u-?R z6Lou)>jjtXFFQ{EJ<{=T4$fAsX0C4T_#ry@=%L2HH|sTOd~h|9qbV`=t{NZQFIKNX z_P~Z_{5!B5XPaoc8UKz0%U8slWe|HhOSQkJfM&c9Vt-d^_V*%Uf8SjG-?L)Mb3bS} zwL0g&n@%aGqk4ymOLr?CiAw*XSUcyY`mfBsi5~b%EInFGwtDWdkequIG{|R8J|F3r^Q9bF!*A5@Xww&uHEti#5VTX-d znxy`{33gRp+l24zk(~(dLF>>6I?4_sr31P$_6(>t@g|lV3{@}dhRe}BNa`huvDv?x zC8w*=Fqu~?pFCBRIcoq@a$_U$vx{K9Y(#slo@7YwCfhQ51toiLHr~v)aa(#r$=@r3 zfMgal7N`-cvXI7C8QL>d&V-Gkq0+qFgEsuEYgr9h0?xdO1$VB1c3@i;+LA@Y6@dK! zLykaBWV;4rhgL;AOviihp+jf~uKI0Z)xvAUFYp@r>o>AfvlE8n-FZ0Ksj2ID6aEfv z`)(05zfMgIA9!7<4qsKOUq5u{b#=3D{DJJyi^*<{`==D^Hj?w0AnIRF+&?I#^ll?2 zNIFYm?~vrWrGJv4b(M{2U*(UhG}$&<&m>f52$$7NaatFf$)}S;B5@~;=pi|1#*r>J zGlF|3rVCZgUAq|V@AU&wCctSi^eg{K5BsE~ya^rj z`1IX-luw>l>Cz+nb^=q4=xT%MLW}TLy0W8mB_q1Du=!afXGU({2Dy<#+qWAt>28lZ z{GpDUdSb|+!Gi`48$RLcqj~U3@7^b-PMtXDpAXkUY0n$m+Ff|a_P`t*#r`Xl#IFiq77Nu&&tmZ81U7*(@zcj9w=3ww|GDKSM5C*L`J>eR_=(8LS%PfH70Q~LE^v-i2g z#3N~Gty_Fr;F!vNNh3kaax0siRnTQxYhK4!Su0(LhHF=F5=a#TJ#tg5ZjN>i!yu$jdwAD? zk!$-F7Z2L;?2UULsC(@Ke0odS!`=Eg9Bob)&0YNWOW!JufY@jTEp8m=qDceeU@kUOwb z00AAcwvMMw-3kVN5f3qszzG2@*eY1lEFiEyL zXs=Gsc0{9W6G6Ac=3qM#wOWgF&eoF14`+f)FaVvME*JGqCx|OIZ)CvgL=1vPZXvPr zAqnlzfTw-FO}>3TdV+RVif<}ZheUiW!TL2Yv*Q=3e_VX(DdkHN4e{mEPt(tZeMio} zb_6Z{ZPe`Wwu9T0dgUY78m4SJc<|nqQ??{;tVoYZ#Q*kHgJy;JYNh#n2m1? zu$LzO)&=sAaDg@?E^L00t~}gr^w#arpj1~;?ZZ2|9qx9NI-(R*eF|;cm16GEvl@cj z*|Y4W>zAm6@Hf<(@Fk@PO$Ve)bVqt%B49x(Xot^0i5Q?+)KIerbx0SmMIzi?dD+;m zV{OElIvxg`^qbUhi!cxFQrbM$Z}RLnr%Zi+&Wfo+4&UYX?t!fuJ7)GiJU&1D{&01f z-MOpEGIrj3M(VNcV+FJFYwlQOyO+SX`Co&2SHf;+fHv4e|J+x}SzBL+{iq{*m8sD3 z9Fc7V`*j$(PaY%tkZxsyrgF(@N7mX=VYMBIW|rsjq3AUUO!Fa!fUO)fikI{AYXpLk z(Wp9^5!DOFK{{l|5M=dia_n<(6VP%OVq=u?I8(#Usj<{JERtFp{zZ*9qO4C-mEk^Q zA0zhzUZj)Z@ft3txX#*-xviWL7|Zl$+?1_?6+pGyu-&;u}hJ<2H)XZJmYv4EU3~YEx`Bixij)0b@8XCX+vG$#R z{p+3DADN%Nzy7G|R9yPND)=lMkG`H=6<(%%qr41z!36ZxOL;jGM47i@wcHKaWw`Z9uXhCZUgFd8|hUn1O+P>oq93` zf}(Q3tjrrfM_?$F;#WSZjzyt3d}HIz$#j=yAPP0tAdY`=fh6#<>}EOIp$AEE5^G5C zFpfgE!D|ssj9-kdZ1CjsH;36^X0?d3Id=}erA69oEid0nRYxOj!t1G} zXxV6?Hdo5-zyCq9Ph0T0IT_;5$k-{@$cqCH3Po{u0DH1G1Nn%YqBg zhLDfu?QVmaHx;EuF4|NO3E2TETqX-wC03>;t@XX+tqN>3Ri_ebl*FRc2z8fFdwfQh z-U1}eVOq{COf2*jCKdVzCl2-vP8#f=lsL&ZDQS{_UgA98yrg-4HP=h2e^cTn-=?HZ ze)j}9SeOv`RAKVqgvcicCr?UT&B8js8eU)mX<-Qs~l^&ix`PBo>d9fO`JARB?gLs7VrF4`%I9G~Y6(10pW;jzy zZxM-(1Wk0rWR^fOgXBsffHm3wEt^E;U*wTEd}IG@Q%FQG#-1d$E}@IAGFkOiZpTJz zWqh>2F?4zS6^YvkX^DQHN}U>VSffT9MzMYfiBWO;Ur3AwvJ+BCU}5-?SU|56 zPboi)9rqXX9%Al0|KaX??^W%e(xz|d-w;2WvAnA2N)^ki3S)WovPoQ@zsB;)ipBDZ zjI6E{BT2#5%7@DJkp~7e157d5DJjZpXm`7!yb%aI7lD>i=i4Hje+`5{Iv6Zl(~P>d zZ6%vdvVlIy`1Im(mIgV5eTE4}mbI#V>nayh6|9VRZOjlZ*W%ch`UVXKD^ti^mAN@{ ze`YKUmI~mdS_8y7<{W_zd8(#{w_|e56-d@Fv8L*{P}jb*pX^sSY53zq`f@u>`RU~t z9c$zP<)Kakw?1$OlcV-wA{K0ZkYxE6~`y0H$y}M8a3f|LZKOm;lBunCr_O_JZr#TNQk$H#&%=PUx*1! zewC7WoeUPr=6H9UTjKl2@q!1#r$r!`WEY6@Sl0^c>~R$ydzH!avagD%G;ItJ@qSrA zb52z;Gvro1^xJ zjABTZN90(>pT}zPi3{$3;OoZ6%J=M6uFZLW>Xd0yXTLaohNG;;qH3z3iJh-} z-1xQfXC?L2I%J?wAc85ayoI**pOiB&P=hlt;&E8n^bPj_*=sw1rLvIQK8+7`pd@pD zR`NMiZ?VRP`hv##n$xLHBg0T;6}`urUeP|399NZGnWL`~H|7BK?o6nwZ#d~&o45|U zUCTz+VKh@rs*_I^Rlo~F2P4CZsZK}8p|c3&z>_Hm=7w^$gE8oIL~tds;ils>Px2&u zfR-JD_?trynodDOcza^fuyu!EiLd;z#>;EQdnv^hKj3e7PM)T+Vs}dX#mdywS#9JO zMh*Muq4&CWRCf0YjHNc0+^zg{;E63WcEguLfoTwW;xL1D2U;z8Y-eW1?vk-@srL{M zBKi9kvr^*dzBj$TNaQnm&9!D$g05heEXcVTd_j7m)ZQl1o{+Ing)ysB`Ijj>Q`d&p zC0DhsEOb|R3XN+G>#SAW#zM?GY{NB>->18@2d#nIqozE_KbcpNo6#DxHRD7xegTXwT>@n_ZGGQ!+`ZjMSE#ch@yw?qImgs`$zbu|mq=t6FW$ zATxi2PM!Hdi=NG_S+KC6U_R-(@`m!! z_U&~2+=cJFKW}l1&g>sF_~8k1H#h063aGeeuX+zcd66bzL%V}7VhGzcL)dPzBSV-% zhOiA8!uG#5gs~N@ndkEze_;j3TEI8izuG=kN%WWuFj8*iF(v4wwKiv!m99z+R3@~m zXuVxuWjzy@(7IilRFCTRDJAvFjJkc2*yEbZL`!IP?nLrGYgN|%teYJ>1*%zjxXGEb zS<7j5>QtisoF|(dIiEarwqn+RW^YdAYvl*x%X#Kp3qMYE)6o1^$CBJM0j#UJjb2_{ zD>;xPs|r-}RhBazuN&`XtR(t+rD#2i_Nuu@!BxTiK{a{Wf9+5QDcesUP!5-E`-@Ic zKB@~`_s+|=r~XgaTGiF?d>@QtX#z&q1#CR5pyR7}X|1>p(O$`KOr!uWc3|8{dB9GL z^_Lr)F-}$Q;fx@f0e-O=2s8%24-rgPJPy0v@$m``1$5@?6DGYf73*$;SMG)4#_-i< z4A8v1!(F>#_06i<3nj`hW*V8l0dS9O2vTlImn4~`6b+oM<`nSSX?K!_&1SDMoI&=R zRGkvVW;5%&2Ey2rHc^tiI6mrxC{bQsC^!j4iXu-=0Z3C4eum`K2^uwr#rz2oaR>jQ zk6^BG1jc|MuHB5wMood;Ur{E_PVKx6{p*}MTbc9>|l;-vN;P=$B#`X1gPX!XP8qPQ>zdW8*K}PrU<&1I^r1fc<*cHjEZML2 z8G<8d?TjXU&X?nHzA_8s$}HkW1FSZkv77b0aS+858Ko{70beTCL^7y2-gDq=K14;; zV44DCHl`lI8Oolotn6`Y$*XU{m#C-1llSdAdyrc3=kHYU^r=@PIi;o%yn!B(Txldt zn%CrzDy&+rG^->y5EU4Jpdo5v6*OX0mk1rlOA-j&Y)rzmmar~PW}2EXjUc%Uyft5% ziV{|f^QA@d${@P@pr0JXbR|G@S%R-J+2-|BIJZl>GDhMIh&HFk`}WUx&RWoqL?Yj$S>*2P;pW zjGU_ClOp=LACOM-G-`7$QzCHmKr)9G<6KhY&Oam@XpU!ipyv%Hf#7Z9O9nk-tbo<5 zzJgCDkFah^(*62TON%Mt(4p|vqjdGbgN@%GJV?87o&8arU!r~mK!I!y8jB4Q?z}a@=s)iU+ij?SsFAt?mG>}PjA-iF>IEw5pQf;5 zp9iee!!DH+6wRrUMBPheXOFYnDmgahwa3ZX8-IdOA50lm*0&!MevqaZT6@KzF+g0P zM<7~7WKHGB#yAGYbpf5z>=Ekg>k6_Eu}GVEvN?afsMr-mKK)lxjT6_E6h9(me0*s<38U2+Ia8b|&dN-PL`E}e zWTP5v5)GXufJuG_-DB43sUwFf?vnWyT6JoCdcoyrm&gS*>Q>f}tod1+ky5-r>s;2CSxs5`2~ahu9I+|J=;lpI zOM#&I8*nK(7vWe+F)V~HYCP`tmX+QB+m@eA@#_B7lVcdS%Bdn z|K9+DG`0YO44i-h{JciFssw77lE!=JvK#y9I~yNU{o!y-7~p^zctBg(%~Tk5Rd#@k z2>Zr310#t;jkM(I)eQKkX1T9N^ER2&`P)Mpjhx@^v}I|>MCd2A;L&o4S}c`sEk6`q zduZELC@EJ|h(Y?xS4&G@ZQTF;V~>4LH!5!_4LD(Z1YS_PZvcQxLA;aDi1wAuJ_hJH zinqBX3$bPD2 @34=u0)N2_7vW=x`LxQftfQA-HjK%_)rz<$lVzFVJT6jObp+y$C zkm|zaium+&hMY58M>)d(qB=GHLwWg`Lx-M$y;=vaE<^vW2APsw%IA+OkL`YB6QWXj zWYd~E=X~<%op&KxA8V>-yD}@04x9qAWOHgSo#e6cz$Dqp;b&cA9r3X<14EgMww5IZ zHo7Wh#rXH(#@>IsSJ(Kd8-&$x_JPu9EzN5JvQL1opQ$8+aD zx#XUGKjAZ_`Dji5jk8M}J&UXz(DW^}8S&Zz($UUGF$N27X4DiTszCnlw$gB)E_74DVxN>X55rBwkhE<_FQqAjXX27f;lv7W( zpd-AObQ{TKjTi_XK)UUHh!!gd$~wvfcvdF}^|cK+bGB>%I#Zdk8f_X3QS6CAscQ96 zjJK~2D&U}M*ihew&mBBSbyKsA5W69!Zk%V5)J+mf;kpfF=G)h;p6EHL3n#-@532o$ z)Qvkp?iG>j-cIaVFE}c9xQ#D?gJv8RdV7Vr+Q_gRE$V^SX<-c>i4pAvwDXWF$NCtL z1mbSc@R!a8iK?@K?SFGNNW96}!1mY92CCCov!j7MV^P+T^9TB^7+O&UANcH}`QhK* zSX#PdHDxv|o}j!7eXBYtA*N*SQ?oY0J<1Ekg9esp*c&lC=_Nb#I?hU)yiSRwa7rR* zM;qBKotCW}Z?fx=B(^&$kWpz%znn!}2Jsh;n#I=%wrtu0$&o4-@Y^DUzEo8)bVa`d z=Z|D9%9uU>qtBF;Rd1|bQo0nGlc7$lpig;s!eT@G##vA8g$>FJB?AW)6aUR(9Dj%O zvsH2rvx%}8ho^;jJ*6`Y52b~=dn)42WEza2G{y(k!u5=Ay&tF5X1kqE#(Y6|LrwZJO&EVVNbY{TVY&$-v_6>=VNMelCE>OGO zN+-E9umMkRz;2@Jr#x0z^VEMnnKs&?PR-g^*KEAwS^3!=*prkgJd&0+Vuak+Z)v@A z{qEBuV~?%mqj^xdnlF~4`q^0(Ws#_5{q4+aB*nyyR$Bg_m^PEZU|BLJd7;y9vkztk z1Mf+MMgEwhYM~YjAK8^y0jm8bZ-q79QD#5m*XZy^>4*S%*<$VqUAOvj1#&dn-~shG zyZ_0PFEAy82!-K8bj-0foV5vPxSn(la|hy2@@eZ}BM&*dP*;ypTV#W!OgLj_%D8H~ zhN8?y#YVGCgxgg_(f&mG+vzj{A=>y85h5)yO|xWEoZd`{w3Bz4Z^AS+d3ChA4A{!V z?M5Oc1f<>6X82W%0|I559dpSaNY+xGEq(Evlr!v<@;7MF`hNbzQkq^l*DpRkPcHf7 z1Lg?n{q-layJfh6*5_BKUzv%h&)Kq`H(Df~g?cKzppK}Wm>3HS_zGjSm9CH|tc+f3 zAh4krj&p*V2d9}4co^Vuoc}U{!l}FhyKbUN2mohz|0d-%4L|jFb}wqPi|kbqKY<9V z?R=T>jNQnq7@?AdOiO|hO5Dz{GYv73nz2B|Td+Vi%+vw1E_`+BNewNvF`ldl`db2% zs^(E+C87@`;`4no^p*)g$5a^XF0-(ah1EuviQ&0HZhTVd)0A9t(v@|sramhRyTUb! z60%#8-b>QXD>VmJ?Z%oU1dVvG9;u`{Rlf9+dUSb&-WPsz<;qRRshRK(g~#6qm4fG{ zPrdq`;owu$zI`u6&ho!z@EMp7442IbagraPZA7vd7!}~NuBKMS_Y@P%up&{YPI6V< zgzqVPz7oF@eopu~@qO`q;md?C6J=2ru-}kr0t{dQgf(**JKW1L$uJvzk+cT~ufv1ql>^EFrUcnm&oz!fO_AK8 zh#nLCS+??egV6*j8tDs0pfgACJH-*>`X80>4;%hrBu(ouEfB{Y_CIRIj|KHHrl^+O z9~fAQHu2|lGyufU8Xt~iP$MB_G#KfT1|u`lpf|81IaaSXKoOV#l0KBl1ds;9@;aUq zb-LRknMQxBe`2h}CIjnXJybhGCqofiL}BdA5$p(RtYMO2GCP@?Ww@K2&)!YVr`ECC z*zMHgh7;@w>Q(kF<`pV|W%Ue48!3ayXk>6oB-Xox%VovZ<%Br=h1_w#b%ZT`^b84xxuq z!{9J5#5CME!Z1=lRX2^hgPqOXLC>aU!`Wc2ak72}KhLs6w}iWgy_Z==-%BlrrEobY z1@nsH{W4W)JZGt4&oj031?nE8g!uzTi2uXvc$m%QRQ~hZPyhLC zB@BN0%del(vm3YJZ)AwirnklB`w&6VNgHPYl2C^X+{{zD3U0dvkX<3;MZs(m$u$p4 z&f`zx`NZf9(Br+aj${`&!GLOf0G*W~n`n%Y zONnTL@qiq@HsGJOYm|Nx?(I*ef$&yIX z6fKI9*j-;?IAfKNT0mD=4TBkphJb;By=5e>5EF?jXyBjNv}@3CP#ar7f3^ht6j`HW zb-3wxsg0E6$ffh842O&XKQZL2wTCo{9wSY15Wr8mgehUCNTrTdju#y9QS{ShEe;3W zE>Ht(2h2)GYCt$I5>fN_XUIl`!)?hvG`eXEi7}1?esD|{os1;LCrTy{>YoWhS2F5g zw0o|Y?zv*SSFh%nF?$eyY%abkiH@&ur8gGTHwd-F?cJj?((Q3~zli~zq6~1eMvpas z7~pB+NeUnacrpSi1A2H+=RK1GYUihTN&~9`F9cj#$Fn2ua!xG1iMJf?Kg51=I*zd6 zh2#<4N*?Hx3cC)wZx+3iR<>bwz^0B56^$lLInXQYZlDR~m#V^!HZwP$q4S`d=AxQKmR3t`j2okIPK=|+114(hd|BLH^ zBzwF)DHxxUl#`Sf-z%voenis$_4NSSXsH5%n|jmL0ESgPf&;T*JpoR=ZUM}l&-5$BsiAE!oq2uz@o1d&a_?>c$qG0Ra_nO8}JgBv&+%aqQ zv=Ku?({`rWx9jhH{eHOj>{MmInHwzAxpn4){nWOVl#XrgoUviS$U6=W>nPrHy>l0bY8OH;2f>2-Ih?Atq7V}z*NzzwI+vDRZKs-pVyNq>|{zFFB z$JdP^fmnz=snJL*G@X((j~X!mM-;wN+zIASJuzhPpg{wM4jl1BN!5xn~n&5*awI@bb)|YLK_CH95grzT1h81eobwRL9A@!&=4zI(v*kzgy^Ap zAT;wyh>)}~0g(i^CjjBv%~aXQ-Q#URH4&>IChM+;R4mOwg9b;)qOQ@1F}Ej6U1NwY zd@tJWbTE#WB#ls-7a4y=Sw3BXPyvCtdJ>o^Gy^+Wq)^sjw-cfX(7s#Gf9 zD*sd}VILR=<6(m`PT5PcV;-bx;8P%qW7U=1QNMAEZ&?@FlIfCs`XD2$ousxl*(ggrz7$t)X%HKBSf?N!vX$KuByTi<8U zh>_brm^pQ7iSj#~ynVa!k@ChBMR{oD{DOjo3+Vdx?d76&ZFgjM96h#U$HnvBe`n#` z{d@N)SCA$8+Ue)--0F6BlP5epc#!Hl#9l=6AOw2LAt_$;x+@&p(*PTU6?CwQ7rpCz z#D^%20(^W2CRs9)gs)K_qQ-{&NEXP*G3hO?L@@^YUpp1$&B|1r75>t-$ZGWy%U$_4 z;$ftX&uTJ0f5Y*9#MW+)`a=T=iJg2|)Z19bDOs5W9b|dHkOUO?A|1_k^}@jDHlJat z!7;rJEz|UZ+N{f{Zy7cml}JpxsOhak1~-VO+Sx7Y%rEG3EQpuQ;2d4Su{s*#9&pH@s>SXh7*W z;{rga#ktPyWP?eGuka`O@HXQ^+l((F(TQWq|FYLOqK+zmx#xWM-Gy&2-+tezJE$~3 z`@x%NA1Iqrh2#W2Kz1L@UqXG&iKJu@(1<5epGvGq@dxmB6rd{-0=FmLmXn?HS9?-t zsCj$*=eyf)O71_PD(*(58N+cB$wU8iZ6IYN9d#X@HL&iouy0*!U-{)9(C~0X&WY z?SNBm!e&2&X0$7@S>L&>!o|d*VU4Z43Hu6bKYyu=UGEgrC;FYn>_aWVun^@)E4r<& z_F*hc7KsVoqI-?-)dI3Xr<*wogIJT6aF_f6RfoP!SBXv?;99c!6KZF820asL*#&?9 z25oc4TM-R=&rKbLVf&Gy(JgpCsqs3^VbC9#^!pj2dAID|_0rsNl$yhbli9uaw|3ly zwkJPfam-1z>!zb^9oI@d%xON73#Klj^hEIx9Q_m1usBB7Ehv>#M4LUWhcxPG~KHFBkB$>?_Ze4Dj%)dpzPGBUtTUsXw5qv z3l=KV7wVt={q9zYQq}-^aJOhL{&ee%q5j1N{hmLd?s2s{X#CTaVs0MdZ4T~BjMquC zTZCT~oH0C4fPVCsW*TzyBEBcYS3>!)>gdr?qwwi;C>6G&Ues`hh+AUB|3r14p#RpG zPXBGwpqEDy&QDeGhtxAhwj0q^0N(iim&y1lS_A)W@(t$f*Vq2n8HeT>KHK~nwQE2c z=_9h)%+f}V)*JC|Y*8K8va|>^Lw9opRn1m_?K*?n4Oxdfj-a3#7D>lE{J_66%X>zCFz zY>YRHXPbz6+bn@Asa?dS42fAJ#iFt`x9My82i6Bn7%j(!kEGCl8lO+mu`hBLZ`r(l z%jU&Z>vrs1R~7q$8mYM85BNL$FhzwGwoA*`xDD_;X+sCBAX_$xCWhBTGd?>K$nJ*k z7?6f+GFr?Pyg+k^Ujh*78f&x2j|`h%n_k*?E`4HCc+MvECu)B*WR)AtLiIPf=kLdC zM&skbt;GW;?;2#~*&;(6stzkRBpHHK2B?j3`ZD8oXSMrGoIv0&%OQg_f!oz%n5f_&YwL<-ScNd)YpK$oA~;6lFeu{cSMLtju1f- z!x1Wy4Ty?lZ&~6QXLYimMhpLUQaJ6HDReVQ%#fK`MW^?&x1sFDBacnrUG+JlZ3(rT zs^PGMc!sQV0NP?O;tQ^V^xE3~N6kY=A9KhZ$7CKab-)Qg<~Y$r;r9!0ICu+ZXf3@r zRkL`|pow=bS<-4jzkBXwT*`xR>6kHd#w&a28OpOAJFW#WZN`I6{f}DED&P|UEjSHE zFK)Ru+H`{2bOLT#$9Y66g-aCF)uP77{5MzZ2o*CH?%&!y;}%k=2bRqlm0P@!kOQcu zAK>%g3ZlmhL=cd5HY?=u;VL4f9wQLRI*SN+9XW2T73yoTW*sZ_ke;=Cafj@MZGGL{ z?!}8)Yk1AF+}zRe@x}DQHIe>GY$B@NC$pka$D_Jy0jU{?I@+S=)3I*_X6Y@y9F$~h z@0~Jh$&!>MBTNYr^MXOYV2*N{S~NL7kD}H2)rWc*US_SR{`iwTXA~u@6r<`-0g<-o z^y#&PV>UI~Hk#TvHPnYxy?C)&HPwi#hW)}1t5u_V;q%lIRBt>8oldamIS26Kn(OPa zG&5W6Af9&fdONaj5L);dd2_m{#D&8ooKWA0uaAlQsKXYZbKv%2s}FLYJ*T_^<>&C+q<@BGNH$qO=1HJqOje=( zWT9!WiJDMbe;VinU6PKTP>=~uLk8&h?N%g<>Twdk3HfNWb5zR@L$0FXSt5@fEiW1} zc<>PV=M|&n!qF>+4F2bkA?h4$(GG89tZ2H|BkPp`Mu8EGNlcQFBkfp>XswZU>LTr6 zwGp55IMm|-SVkIIgqx#(9x~*ggNLjbT_}$Rk+rs-qktE*k@eV3#u;Y;2|`^>eSNK# zRxl1oW{Y0(CgAm~&fD9VfmzK*j`q+!c_}bZxB!{LnHkyHIY&nI>{&Et6*Eq5o!37_ zHksTdcD-SA(acG54^ervB^~W#gBQ51z^wyx0&1+jR;bY^p;70pb|V!_N%J{l_ATd( z@W;|Qy?gc=^?Xitc1C7aX4ZnPDKMCO4>L~b2JaGk$dhIkjW+1*C2o^RPU)Z5TE;wq zMkb5;jXMfB^djgmLq`xA;g8BrI74x=FaNgTNhk`XP}ZlvY}`> z@G7&CF65@8a$Qa`)Dli7)Z;7MQw&Ri6FM|>L*(13xsje@%40-hcJy#?8n13GazR40bX z#zA)zAkk!Kcv|fZvogX5waqJ9n|ZPcb><}MO-%oA*3bW;Mvy=#7?2xu)hl&_Mk=Mz6jAa08T)$zYNhvV+<@9pf11BuHVjdO)3!2S!1o5K) z?KosQqnT_WGueW^)R~N)TSpLQ1>)C$OOOP*7F?2)uw|X=DQ7h zw`|$V_37Wg-+)bq6^9=vvrt8+*#x>DmxuJasd5UCbQU86C7spCNasB|=DfrBlh+C@K<6lS zE=A*dx0iqbh-waYd_+zn-}0mXBXY|`80jUW?L}Xj+zP1>5djSw!Xv49`*Vof2g|QRV1&D5SgR{-DQ!ZPBP#G&**3*K4@0QBP*h= zR!bI%1#4DI!O9Z?dGr+#+B7n7=>XMu{ExELhre8pMIXKy!oG@4@C)jBhDX*apo1+z z3m|khqY?azo^~(-HE;k`|1+XdKs4gDhIWL!5EkA#7d3wTgp;REot!ZK(9NoUa4NcZZ%#1 z=g9{iIQJ_||LQB{p(8s64qQ*x?{aE4v1yQ1bBva6qWy>$n13`Rn<{1mZEu36_3ym19!fXXzx*;%%HLDY{{B1c1KWK0C6S-1-X(C< z{iJ^%p>a!KN2A@rf%L%&B+ht-;_y8jT0=-i`H8n8RjzcSdNc2@yM8Fhj3O+kgD#Pg66| z|La=3Ukh61GxK2vlL3*&3^}F({x7t^4v3tVw5YrQ6&R6=iSPpF*T#qEIaK+&aMe2I z{p*L;;k zeR}qMoFy6U>9-d?x0O3BV{p|e9TTQYq>m^x2jLO{)bfFHBF}En!f>$|ivEq(YvUni zg;GZ35Cd{$6GZwVQ^_)PPsnOo9ZvYsLiR9(NCxjVgh)NU^$Xuc6dpKQRjU*Spu!87 z6-`5$>!xDsuKVBW#=4wKS&x;aO<1HY!Zg2%>Q(hn9Vn2knwDG16GfNDWNUT*kE$*k z)^uH1sA{{5h@RJYl1*sp!{wo|-+My=>a$PTDNX4}??k#^BcndM(ZH?*cFrj1j9!8w zhs&K~TQy~Jeb8rj-S~q%q{0Ufug8+RTLuIXKhA<-Y_QGVd<9?Cj~>A>`4=m~fO zcZCmBR!-#XKO99`X97w;VJGTp?F|7|nRxM{a?iz!5VdmQ!i9?fhVz(T zmH%)AQ%cs`i)D6|sn}yquWg8{kHb#noaN{m*!oV{9~3yd{>#Y550^F1LtQb>4}rSTJ!U?_$Q%VG z;6A15zUf5sJ!!bg09|?k66WS@Y}s`MzCq=O<1x@b~n*-nWAk`vVvw#1xWy+~#PhjX{RHg=%saMOen#mEa zS%wN_J+bTw)c29>T2QE)k8_XFc;5>2RrbOk*KyykBR08mm7W7uFkc~EI8)|y#TG^c z=`jw^7S#nCJ3rQE)#C-l8kkpsm|oL}SQrHu3}tJ(!NPtD^csUQz@l*?8=p6({ggs6zSfvV^%K938m$z z<6%TR_^oLm;S-52L&MhdnBqLPPT9R~-LYHBVBdSpr|M(yM^xtZNSPFkm&ORcBm6|{ zME^0@F;lhr)}i_YV!xs4!uY^v-MV$;z2&HP?}JsSe<0+Dy$a2UT+6L`OuKi(zP{n5 zsQf!>`IahhcqvwZe^5>h9kxnUeoH<=KcabcNm<_%Y8sB_ z(Ciz^pFN0NN8D2C5U;Ual_>K!nNu?7c$G$WmdfwHu&R`CxgpH=Q0_e|$KpX4yHfcv zH5cgw6FzlBVLNYBn-Rhd?zEQTAAoVcnCX>v8~!sDtF$-s&~tXKZEe!6n{ zwb$@D04g(8$#2@xG#Vq}Lewp~Lryl)qD+ z#ma_ZFpi?PZ7YY{l&>LKx34SqrXEcjan|5Q=Fe0Rii*FeQ}j3@zKN-;BXI)69>=l{ zeYOkv>^d|y|F@sbZ^~>Mt;)wg1yw#Ox#-zQe5U?i-WrHJ=2RubL<$k-RIDHS@RdN3A}37y~>fb z!m9AT+5vs|xrl7)-YlA6<1fm%CU?_QMCNE=uZ_Q~hmQ5iIN0yC*Ob#}efrTn|EB39 zvgZO;^ouYj;84C%y25@Rw8m#b%IOb2XgP;jv?y(MM*!;U?~tL?Tq@pcFj*~a zTE4_{i|Isk)R3y9s=BIjR^2O^tJnrm_exD(EI@k75c2HqsQz^ueK@jDBU`nGl=+S= zYMP?^K+w_NMnNm{hEl8?XgY|VIn`%~*OyRTZMeR8L}*o{_%Cf!KH5eVvkCY>5X)7c zlBN8ksZt#`sO5B5{y|0ze`hV*whWhZpz-||kz-_s76TCP;to`eylop1V#;DXE1177!^FAA#HiiR277b-!zl(HU!R zB_;a1&z)now|vGn&8W~@3@O23W&QeE%n36N8O_mGNUuN5tVeCvqVe~GAUmR=Rcr$9w>d`h0+J$cMsh6!V5~;lZ_zw!gWCVL>0LBGuOM694`SQG znR7Dm5fHu)%fPo|cr}HWsqK(9xeY7eAk@fU)L5G~-Q>2do0^*1vpt)xa{{XK@$h40 z?$V8$6{%@n(>XNT9C*C~XI593n#|?pW;wA7H;2bJ%aL#|a zo?5x`beFED(N85ecW_RQay}<#U|!B$g)2|o+fBar#7gDe+=02MIO^kkC7#~g^dMTN z35{=S>u)|chu*Baq(0+^kaaYl`xrf&qn>d){EhQB$oAVfXPk9B^F@nh9=zGsS zM)=a2GgBYwLLh)T6uNm<-+amtN@X^C2e(bRBd3Txz$}>m*0{p_vE<3*{N7CD3D+;r zC>c^RdXqVwOkT9@uTF4{eg@Gx7tx=n_6gCrR7s;BMRSel`DBs>@*0 z%xk|=4EKRPYI%xg0M%SRNC#|iANoKa#R7i?&3UFtUYF;he);zhzwcUdM{rsxrnaKB zh1Vn=5F`pzEtcB)SX`XF++eZ1nz-@n;sB2 zP}HIvdJZ1J&$aS*<0tX-1eu-0TX||hMssdzoLilaS3bj84e3S zK9kq#MSpRii)`u+%9+)$oaQ-NC*a^q5=cl~`6M8+3{8m~#{!XoB26=_4x@qNP)ng< zj2`+~G?G-cGM&!3QAKt7mda->H+CIjFI{iboZp+!oJL-cM{WDa>n_dtjLB3_PsS+1YYr61#_n7>wVH)I z10#$sh%lNHX$lgI6;7mp2qD#i(b)mKVBoix2#Y^ZQZa*BOH@{HDo-ETFjQTA#y2WfOn=@Zd8@Gzk#J34PS5LsI!i`@-exo$OJ%4suVjE;~| zN0Q_bI0BVBMv-M11D=NHFMvHuTW}|c=*!V#yTlLSG3v9%uJB96Pah3;gkK&$e3+U~ ziH8q||4s6dqqct_w2(aHYMxW_x-d7+Ct;`<36bHP)1d;JL1sn`i zNAT2f)Ds3K0ObjB@vB36zC0*}((4K^1{eOB5!Gd~HSHoqr>ZkBFDKjKR6+4|jsW%A zwkd1YOxbo}+muzS(64KI&z#xw+l6a;s;l>0yTCl+7`5n)*B6a)px>{*fqpj%&b9lY z6P&cz`}23yp9Iieb_wS4c*O6CBr%$`(F6av8huZc;J&yl>bbfc07Ct7Vhoa=aq9X6Q;lVO7GrJ96x@1 z^3zXWxVmMF^7+pfo_>1r@#7oH%PV2m*I$3VM!ERfV~;(ot}hM=&C$9+LdaP~r{mn} zG+x{MNj=T+IJbIq9;s!R1*A+qDPy8^kuqq%{f@cJO_x&XUPSuG&jrm`_ryOgeh5$z z@YOw^;OUb60=z-?h5qC@#*y7Y>KRCOnD{1j-!5un>%FkzIdx8i=3o0ZER`eT)3Ft4KP|(oOz>{B@8BjJpfFZfzdh;rQogmx#+WJa; zz5NmfnFoMDu&<@RsGlHcMx?^nq4MqvuW>(MoJTvF)aREnHIi@Eb6X(tr2U+=our&zf@yeg}i$C;pz;=Lo>q~da8mF(f({v1#p)eZ zPO-|okvfxrLDuRT^XnRj7m?skLR@3e?_}DUjs9kHlEe;yBoW?I1rNjH&q246ST|o7^lfOCFSZuC+_j)re3rOK6QW0l{ORM_u%v~|Tf4@3Fy%3Ek{CE@(c1k+BIbpoy9 zvHN3PoeE~FqfFg615>epCBoq4ihK?sJdsv zS--)F=atTt%4cmSWfr}T#OnZh+6}DO9;SQVw>L7^zG0T2{o4!Lff2HuW7C-QUfwjx zFjQhBw_lQawb!C+kCz(YgoYXtm53O{u|diUsH(VNm1Sdl9DLhIFyZoL&Y3WrN`n|zH)uY;KI;#(tRBPnc&AIt_4@>(5(dnJ1! zBDAiquBNfJ|50J+=qljER}y$q^Hl~=C2dTMbCtQbCt@E$^j(i8b;Q4-Lyl9E&`GpF z!u4_5rV9@Y9?@^elf7CeCHXpq4?wDOxPhJ?Zd(fb4_>xt$f*7U*tUUSPTSU0Hf(@n zs;ZR7l#rrgH4<6KtUwlartIX(EK;SZnmS{2712CU5l@{efKfEnRff#&cdc?!HzAxy zvxG;m&8wo3IX8|oeOe{~C-yy>(?2jvxD=uj_`zT~-drVZPln}UGFydJ(q2F>Ifp_~ zO6)}t&C%3$qN$yw>7{kDu2A%eR*|02pk`?Fa870^vp=vZfU`3BC3T!_lsW}ym=!a* zkp!cUh3~iaDlXqPyszGyTm0zGp|TBjxw;%2gn@Kzm5e=-lnl0lI=Pd0$y?<`_Lxk+ZSa40ene>5;4z8d-}_r?$-Dh!ct>>b2~qMF==X#4zihzw|jJOTK3Bxc)d@&{)G{ zy>Z`OiY7knXkLDc?Q*b`%+r2|CO6`V19X>lXp=?lI5AZ?M4mC?8({(;+B@Fq#_pkxmTBs&9USz~RcENQDc zPr%MMd{+w>{31M$`c($N|+K#8Yq zJaD>&`Wlkt26e)uE3<5L&^A{YsCHljI7`LQ!w1SOTng22zJ5&R!;)spSYiIAWz4Pg4);hXPB%2+*WBS-YbH=*x z5&FIFK96Mgf?xrX+c;NT3ihT+Kw>0S-$#&WHO9TR4r$G@7+;lOs{$K?`n862<|?i- zh{u!=g>O`nZj=4w=0T3!*vfUbufqbc7Qka0Sssb^}@tZ?j(T5s^KKh=0Z; zt3k32Wu*9C78qCBKX%2UUE!B6!)15BjwLnb zKfyj`Wfg|rr-O)s5fwNZScGc6#+^=eJ5+FHEWvDPX8UzIVjvNatlvpF|9&a}p0 z^mvme4n)ZgF(xY%*{INr)`o&8D@1b<1-eVONs~qv7v*j&UB7h1jz!w(NyLE2pGJd8G^u||Hc|U?3`?UOg(f=+%LRTWlt_+G{bEdBDc_Gv4SJ7G&Vmdl~?tX4#WhBr=HV_1&ENUmDqO<%{?C z82Qruch|q@2~J-6Z)$z`z842{x6qdw+giGhc!63SUe-8wY5*T{Vw%dDzTrXy?Q6%(BJwCIfzQ*F_gxrk+dt)K=;Be8=mn{o)*SzzZX9ru02=Fljq5? z839X>&|!{He9d`l_DXMk$#oe2GU3aJ%h;Oz_4UdV*w={RNUS}26g7uZWUt#P#x(mOGdX%-&mT&!V2B2ki%Y|qPeB|-_?7XlGF zU12JmHRNK?dtmMI3Aymf@15^cEF0!g%hrBy@H1+{jWJ(#8ggXQC^vkbp3ii-^U*I} zx>I@cnIG0nx^(Ff-S+Gy2)|aoJ-yAY{J84q?sk9MtI2*MOgwwH~7_xEz>c&j6h z_w-6a-KoV>qY)=-wlHPV_9RedOek}1j7!4MZuRO8K#qHeWMT0+F1`kp2riP#AxKFQ zeI&Dc`S4};^n*5~_Wlpwf8n#=l*>v$`K|gWOn-`=|NDK1*N;6sHt%q^Sul717s|B8 zM&%B88h(JZsedbHV0ScbqX1xsvR|S~kv^LY;_Zyrs`Cr=wT=1pH75&!98XQa3ro~7 zcGgmE^?`D8x!o;pVbiY_)HXEK))8Y?*3a{m`ZoFA^Dz@LAV+ICE0A`dtjo#Gaxpe3 zm>bQ#$`tJ%*7{=WVfzOzP4mqg348RJ1AVEJS`QaJ{U2n-KFYrzeky!7_0UrfLvx>i z{;dWiX@?JJsKz%RT)+OoH_2wO_RSX;3>*Pr@xTQyE*LNh!jS_wyE1j>ZsjMmRqs^h zY5Rd~_fELy`qCMTF1)p5Mq?%2XU3AZ(AI$GRyVW;@g6Rqe)N)^j3@~VXG!WsCrF%| z_t+(9!74@#kvwW<4jdit7DT!XR{P?eWxQ#lPf$f8(iUsg97{;O2&T}KABm*AR*=Io ziOxo=MeNXxYy0RxB!GTNZiTe6$pe{Ajaz$v@g8%SdG8DQP-W$N2gA=p2wN+cs9^`+ z``a@_IDJFY@W?Z&>>kIw!^{BrXk5q@w+t*g9p9G|rQ-(&(_m$VmVy znHO-YoeVF=A(SZq*`W`eSUG2L% z=T7B6E0YKBg8GM+cgmf4=T{j_NI5@l;GIy9A1nV+ABVr1o|3sg6Y+MDGMe1Qh-lsR zlr4TC!DBH1FYWZ`1iWnPPXk(@GiZ7OS|F!^MX+R8XrlMZCR@2-OHy1ppy8P$0b^OK zSkfdAG;&OfW($>sZ)ylijELs%1C@>Y&zz}-onfcy>gs(fls-819IRZuYL#1=4>!l1 z_<*YU@PiLNBsVc9*uLr|&B24(C5@(QqPdOpdYBR21+w7pWstnUqq9gNBRPn`sXv|} zLPT|be!Z5WqRLa5q^q)sNTE+6J7q-e6r!g|v`Rgh*;(X9iCXknv3iPBT%3RS>>Ol@ z|8f;d>u1wnE?TV2UA*Y~x87X5q*0F)o2~Kp;+bsUy<5%uv3rHOZ*D;L*|TV`NCE9- zgXEM_O##N67(^R+ZJi2zY!=ETzC3PY5R@mc4hj+79crArRbdZk_gt-@gDz73U9w`_ zU2iQP(`=F{uRKy-^$=VJ?_k?3-J!groGRThqNUD$@gsN#9Q4z%!-Pg;XD~wvK4k}F zcO^*4Hk}EX85pXZ5P95+%pFXrtIA_V#)e;y3=MyjQkDRtA!_`8Wns*yRSgXIyfW^@ z8?Vo6HZPJQ=7n$foA2IYT4;Am0dn7gk(^+YtQ6Bl1T!V~MZMi=lafFhmf!^hkHYRO zvl+_tHcJ`1JuRusmr@pgCM|;Yhs3vlFHCO^Q+B9$KrOK&v&i}(}*K%K~NBEDi%^x9Dc@Co9ZrRw%CG79jhm@A=z-x0q%RAV zVy*!8{ zeup~!^83oc47O8vBh|P6tT*0M-c=gHuPLLIt#AOm0RMJx`oIqFhu`p1_Wx{p7&0mk zmnxf?ZOk%&ovY~pObtQ&BQ=nNgbZpvfCS6jpR3?BOO{epMfs+*ul^9W`}M2m79T2s z9h6%5N?>64ed=hb|AB*_yrm3LzEsx3iCRvTMM{69>|X+1z$n>UV1@z@@}*9NLJrc# z#5Ufx$zD&Ql;9D%M)ceKx_qqR3iXJkNA(3`@WQa_`L1p96IORMr)HKrHg+XZ*J#hF z6>5=QhHn8mmeYmsQBP{jwkG>i ztxmo=6-eeXW@BoECpDNSer@l?<^bh#YFjTh2b?5TwaP3s6@N+$D8DL`%Rbu#zkHuP zOuzfZrq9Y?{;bz`eK2SKxS<=~gwU+~M0L^(h3#l(u2b4j6r8CV3x9jy+TIm?gTkH0 zHig=F7qflP9LD#h2CG*z0mkc5)5z8rkQ*IPp0LrfI*~^MX+4ujPIwyeUV*5JSnl|q zR874`M6oS5NHv@+d2sHO^EFeZe)?(8nKKVJf!zmQ+78p$e$oR~%9TH#-LYdQG*S(J ztfn?UAQxWx9QKB}kiP_p{4HiSqW#Q^X|f>pdKuoW;=D#^D)VkMS10K9+c#R&Tc#*Y zc*Z21yM`>BI2;ZbF`^P9#%=!W!S#Df!*tj(_2Ku=tX{lm@kJ{0&)=zG z7%=V79}RCEP;Hz3?AK^L1VO%R5zHosH`I$s@OzV(RLw4_uR()+%xn_KFdIGPpfb^H zI+L_IG5vC5E!kEhceIg#%!}UVYFXW|NlFiZp<`zYdK^CgOI6>=Yw!JZ$GWz;_bqzo z;-Uo?E)1GAi&=5vH6>j8#PL;+_R29m=*$|m{H~d$uk6{jcJ+NdFl;9Zk~&y+m=4; z%S#9*2o{so9T!MS^z`oBHw7B+ES;zP=i#aSbGi*3Q8sDKu)=YB2KUd5_Z2Of-n&(w zEIFf9VuG)I*CBUI{9tp(*6Z@Fxp-n0U4Z7sGJ{`Ju?%XB4FuBdX;+aFXqOlo_=B||j(zjHEUsrzK3GabpUYm38yy5+q zw9Q&QZ1?xC9o+r8^3_Y5iGGKD8cwr6qrY+h2>SIj*{H2Bf^p)~!^mF_jSM|hFNggk zDg=H;%|&{T9j;R9ZE?wk9%nCqlFz%af7^6OL4Ai%|Ah&ON&cQLcR{KxPWb>X=5z_Y zdS5@^yHA|yFub75q`JVD6XKE?!^=jN?U7cbtcIoi13g&Q__BdX7E_g8;q!XlfB3Lp z%L|>0_Tr0(M;gtv9^OKA{4G?|EveoGYcHc6KmTWkn2_tRb@Il?x$l>QX|KPY7L@OI z$HjX)*&MkEqT_ei4o#p=eQ(U^+sVW3g&mbE@F48swRmXV!#u-eC*~;EA(xYw%`p7K zI@)9LDwWC%p7reA>tR(MH+{nfIRVMRHfU5+5HaczHU=QpGRQ@)CM6;ECZ2Asd^D<~ zbLhwwYkq@SX#f6GdH3Lx8&<-ji^})+pSbx?BAIB#`G#l-SQ)R5 zmy9Nyl?&t3V=Py!9#eWoS8g>`n^&`E1PsWAjLzCD95I+f+*7gBJCc3Oix-uD;s5X} zoIK#yY1j9&CDV`=yhPbR+RIZ$GIsVof;MNSdDI@S!}*GDYR`n*E5q%P=4xY_BfhPX z=IqaZTlMYpaBCGasR_)#zLs4+AMHBxmCeLnZTgkitJ&zq|8A)|@Oa>hAu8?vY^36c z$~Osc=Pl-GP3Q5>lNfJ{Ca4AR3)0f8P?(KYRPg;Lr%Vi}^CmN6nlkz@^;ri3M7o%OlE(VoN}9hd&NT|}!FdVs z{uJv^2Pdoc7b^b=>L=E#Bd*!VBq3W@A#|u}hM)oF(w_u_Q)j<8eUd~y6&@!|n*QRd zf&B*0oTFSLcORxZ=B9<{BW6R~)bSOYE5=Wa^E@LtckiascJFrbCemIFT4!z4_G}UO zVC+AcoQ|(W$#$taTwzLTLTPjFfF@kIa&6Ac!TkoV!i|T=QBUEYeM}bgJa(Eia9*aX!3!9(noX3P z@R+(AbQI0g;04~urjvY1E|SOwUkB^3*9)Y0;`~DC4SFaV4EkGA+#H{8!MW)~hC=eh zkW2N|^)-yqjWO`DgMwz-$$RvvuoayHJJG%PetH8*7NIA}k&y)=2Hr+C?Y*!RwtHPE zy{MGdu$L4+{PKDm)~9&jch~=c`%{YgdjjXl0fS||rAWs!1|FC(G`)H-LAs%*LABm= zhD&dV>4!v#yg{#ZM(qKs6Mhm9?LYCtPh)I;TQe!8FkV56I=)J2*s1)h3W=2!@WC7V z>ElWX+<#p=HyNp|Cw%G*T;eUu0^7j^T?e#S807MjEQ}SS$8>_!jeFD^>>e>VC3kd7VSmHqZaWf%o%fR6(F^^j{*T#fvcL? z`KV1iO634lvklcO4;hW#k~^wT@u%>a#dT#m`y86n@%Vg&HF)Fg7N^%HdWAZCZc$It zI$GIs=BQvPcL`3h+_qZ4SKF#1QASXRCWPyd8X!9fxu3-O583BxFAwOtcHYXB%DRin zFlIye3VhygUOT+)HJH3_Z#bWAbNH}Q^uv`X4`&k|K0|o;5_1Ic3PyO2WbGhX zA14`sX!md)oT|P~Jz8faGhc~+OWE>iIlb)18&FWL-cSa>!%*Jy}q#8V2HaP0e|p|TIO~FI!OqFgeo+97;|{-g$va33mRE47m@VU6Z^2+H!`Mn zQ_~PZUwr-D{#)`qfadZU z-CaV+`3kd;+mhbuYN*X< z1vR!InyKd%?*;0M3ySwJdkMz`U2mhDyE$G%9WNZO0eIj*mb=NN2Ogn4WAr*0%~!34 zWI;5RJ678nG?&c5 zcW2HybLO-;=M3_okskPPz&=chVk>tT|b6royRA7RK5kxiJrMEz@$!_q}@}ObN?CR?0pI2A2W%r;HJli=uV>XDVgMjC= z`%sU=tKi2M>q!t!=x^yv!h_q*3Mq$>kpY8}(g}^1uL$=mt23RHDy>w;(NYbv2wdbm zxi~IX)TFKwH7`};>)JSym&QqDG8X-js8UnepRiSc^eLypU97cEK07!j%}z54Y&*KWtyno$o>|gts7s+PidT z+ZTV(h^K5m^w+jC*4Yez-{YpLz|Gpste|_?eC%iK>`o+$L#Pb1(#zL_33K(3AuSN9 zvc}$PYPd%fhO1|Vmr}Lg<+!#&8Mr^_xPJw;QMo1*x52?yFG)j1Tam@J#JHlEHTeew zJDN*~3WX#o;ZkF|>z^Qb-O`P(!aYys!iNz%s^-_@1!EP-=LE!+-dI(B$CaPy!q{9oF8l7Yus`oV+OYHB}F8RgDn-Am?c@nk(eQy z{*T#FNG<^OfiN6 zFZv8G*8HG(iC#b-R#WLUS~c&a5z|J`WvZOYkSdREvezBCs3{~l)M_>5qEyFxXNJbl*Ua$A-^}I*MtSEyf5*iqv)ZVVdw4oidV{xtMGRAjV9NoJSC+%fb>gr zi^ClOf`XXBfXn301qDPSq;5s~ChxKT+U5z3^kH zaL1Zm)J_!?8d@ZYN*rAvikz3zWiCpQESN5-tqlx99LZH-5xLS>OCw{OS zuIQsHm@-OJ!5!09P%0-6nFi@~#$DBb?Q>GrCE682BR!+t^a~cOjHE>H2kb&G6-)|j z`t|Bb42}JHy^!_gu=_f9vVGRMlcVM^o4c6 zsfSiVIeXw<_xFU$5Zw3*$uSS7{m#b~6)NnTxF4r0TwnA}B#N%5Xde3}5?=64w5~=! z4T*KoMn7_zDL5*@lkOt-L;A$k`ZeR@`UL*nOx?W$T#%cx9L_~9%OCeZ_61--{s{2C zaDN>f26w>iaM%V!pS#W9NMjJJE=V>dn|-MY-Ns;Pg<(ywu_EYLK$$5->EX_L_^FJ6 zh5$C0&?>b_tjuevarL*K{R;)IK+}>@fy1+mVC8cQ8<&)oEop3ATvoQ&I?cJJMog?A zg|0O<&hXByTU_@Sawrbkeh2RFG>ADCci(vjxZB1dbuyN$?+UcO*N9E)N}0_HcUH$4 z)Rc$J$qflnaetbXnS6z+Os213j%j7&VsD|$wN|f|yQ*a*P=U{s0ok!ef213O0utf_ zLW!IQU{}Q^&>mjfQ~`ei+eb80fJMrNy#;@RGuhy!<+SFN=lS$n&#I5!{qk8jJ;YMq6gSM>8DK8fSPAW!mkNKW>QK@lj;efHcs}ycStkB@lQY?KKUUH?OZ^jo4+G7If!2H3(&wPzx)dS zl<-{pL5SSaxruS@BA+eneqAeBa(Bz?I7|6;cAk&~0y*6wd_;=JYS-(y`N-pNPmPyDE8vy-#N)t}QCD4A4)ua+nKiIkfus4BUitV&Z4 zs{EquHXe2(uq8*lJp4_dk#y3L2>rv1U@G7jE?c$`KKpI-vSp)TJ~(&v-uSVL)_nUR zOrcr0erRFg5O5RT>f5bbugx1?88yenef!j{!aZQ;g}w{er#Oea2`L~Kw&8Z!HEb2A zZ{<^*XIyQsvc;RNad>UU!AG1oxv$!l_!LqnO_jTgDIiatM$&5 zYnAo|pF)CMibUdO+g*w`XjiykCj59%ND2MN=FQgWn>RD<*T4~ti6Q;(f~tGgIM@ex z!AIb@BjfA=Tq|3C64aEXjMSo9|{YQgs(!ik{aDlC7a z_6=Bm6*Rz!AA;}MV%u-DGwf~aMJL{bo56&ewp;WmaKiQ*!Pj2P7J_7_!b1}jrqVEa zKY6IC5np01aFwgya^Dq(I+G<-SEUaXD+!P*@zi=!ncKU->h*M>P}J7y=NKS56+!>m zsUVFZdHT})RS-VOt19eLU9_!g>&h*=rkAgt)n)&%lIrePzL`xAcHcDq*g1pYXkg&v z!h&(z2WFcGdwL&sci*$Ns7&NR+#3V=6&Yqd@h0kNPLYlM2`MF!^4W4?kf60A_T)p+ zpD@c?d=Lq->Bt2v0EmsCM9lbbs9r6ttux~)`q;@tp zAm2bD*D%O8a7MlXb_-7G|ATLUKfjUGO||$2QY!o9zCr!}d*8s$B4Y0_GlHi(f@d0nN3gfDt(#s9`DY^k^4r$+W$X_aJLG! zp9fAL9b^CiPe8E0MIF3tfw$@qni~2Eg5;zvn0{c*6X{+?=pJm=$*O34o43L#Tgpng zmIY`eDhzW;qj2A(U9_C9qx;v@*^c7ic@nt!ypm>Z)|R~SR&`4Dc?7?vN>Werj8v9Q zu~JF)%l#U*Oc)pw&Kie4+Hw{`#_jv>b0aiQs#w1wp$z9_fRXZ)RMmKo2;Z}eq>8HN zaFiGqKasUcW!u5bvoMp$VCEfRjx?cO7>zmDo)^rIBKBJd@}@G)>V&LNjZw*aNQ0w1 z@dcXkFZd;z2x*;<-r}(>z8zB+;Ic+>AzrLBcqo*MVC9&kCU?CRa?`M>lp72g3Lg84-)H3A8|Uu8zI=2 zsp663V5BtR31op`v%Qw5>yax{^)gq6EwiRz{@A=3UrUM?5emGp6<>@{?W&;7`84MHv8qoMg0V1R$j=+FWD`MlDx@A&NmCmiR@rlpKrs=)HFb(|BqI`x#a z>ZPs@2R^BL=3fUM)NN+od0r`?M%n2l2`4gx_&QZ+7b|!vA(`mw2t*^kPCfQ@s{XUD z!*3U6LDRJm&`v~}N=Nb|ipUQ=6=7DmWob2xvqCDByQ;1b2ZtC5(key0#JNi8QYDEN z5;{qw8Cy8S>EVo`A;e7i@LOcsB*O|i07&3JK(cV@QhM8~M~)n1-q{S3HVYOHWta8b zF47C>ch;YDRrr$FmMu1!mI^d0^jVa~g;Stit`pOs5NX*eg{+>#HVaO%bcA$?n%25g+F%Zj)|y zb6)PWLgBugT0z&jN~-ub6m=>Kc5!gL?}-YcuRor=#KlP>MUjX;xBw8J=nF26fAEyO zdp3WdwcVg&mHV#m+`s1#;6Wt(6gFSjd_Vu_C!5E7k^g!&+FrlnOO|s8O)fTn!*@q8 zDkvXhZ@c(q$ut^9<0HgvO5+F^M&1PhL_$%+re&RNBwR43rX#c2*&AX-TcYA zxl*ZSnU0gHDNT#_LNqU5rK*?ds~GIN-1{%SO9v#rvF{>W$VduG0hqgZ*57~6T8vgT zfBMdk9)NRokKj4RyYCP%Y_N4b_|bFa`UCr)SAqvH*kOP2`0U~)<}RvJA=hG;lG>%4 z*v6p7VoCDSGfNk8W@$R)^71oFAIF)c4?ciwb!O?J!b6B>mL~N{CV@Js zIcXBlEKT^#l03zq!u%MG^aj3z&==WUE;=`@LNn@J`Y&oX1(^u)MD$dC(q^}LDfC;H%_J^OcF->0NwZ8x+ZY~HhX^99%pKLyBL z&3--qi!qx&IhtRcLvr0+KpKL55`ytM(e?TE{&r%HNOuy`e2O+4a%*JlytD+GoNH5V4oQWkWTu<3$Cy&ffa*mm7R(WT+ zYB;$@>PabFq)yq6lT6}!IBBb7o{B1<(m2=4oQPS5`39R#Entafn!pYj+f#(f_IX_$ z?GFYMxUk)ZLBf`SV8dDCM6dwPC}US5e)htWOX{IT4DBKEvq9u%L>5w3De$r@;bn~{ zqL-bU|HaDsR*fedYS^S4*EVc{Qsf_FgJzP%UsBjy!-jE#hM-z9Qk<|Iig z-(#HMdtiA{#I@LQ#3%U(Kc{yNX|U^Q(dH#K08-J4Dw)Huah!ElA=~EVXPy0EDK>0i zsi>HrSHed^J^;y!kH__%0h+)>m7gKh)!^o2U}YL9t4jD+y{Bt{v`lTNh!pER8)CTs zZH~LW)Ej5w((V6yYWuu-?{6AOa^SuHcj@fkz6ncDpBh3E;O#Y?q|agz;Z+}`|4)%K zcW)d+^3{59PHGPq%Ak-r`C#>n4B-ZqP;l!a*HkD~&Sf(93UJJ$LM8-V?-46lZ;xzZ zTO=V)Z`8L6e9{Fi0ZzC9OuhxC0BuVElAC{CecK( zU50OftU6Ey2MCtRZ#8J^Aj5DoX5!88)~oQO5EHtKc*BePg=CJBtr@3jeVe?-LtM$!{4{;iH;t6Hzy$Ay=y?|KaK4Yt_;b06Z%1r(5({a zh>S+OB^VdDRU4a*h4tgX{z}jQBb@g3pN+(IJsNqQe6z)}-EHnRBD8Bd4p{$mNE{N| z$2L495+&}|;=N*jMgDJc#^6j*MicQ-jmSxj)5-w<_gC--`28*TE&SmthJJJkHo`{Q z%k~I=ardpi(@D0QXpA^ChMMeKG6q93HW@sI0`Tg~P2X4^HC?9HUEcWn@1O#X!(Yhb ztpoevP0h4Th-?~K)1*vUeYDxcaz=m{@FlI4xM-azi9soK za;FT87rwxwp|QqA+Dl3or67Uac#hJVoy}SX{UlyW?VPD}QB#aZg}YOkPD)3oranz+ zB3zDx3OaYSi>JGX+S$d~U9I$R_f$J6og^HID2V?IJZ&}rp=}T@>M-H92Ed4Ov2iU? zP%tnut8Z-{vE=@R+10Q&r-69~r`O+KT>Ljkw=Jay+78nL4GRy#N1)_`Xz*3up?r^`g}t6b;m#9-c2?STotM-hf*p8MQJ2G2G5UKv*vz z%w)l$_h~77V_fda%lYl|Eq#;oFRko09=^exgIj5xtsy9XH*C5-y_Y8(3=VkaPQM9s zyZZ;z@%CJ$D`+i!a2BboHT7CkRXnFa1pOKAYa!$gfx7)C+Rom(#Vo^QWv0+0S`pH( zHIawL3oJU34iWqiw0E$-*mmw05ftV|1YnZjx2);~JiUD3Cge~o!ZetLxb&sS`nro; zoB_8AwL|PQ$y^+*0i;}zv?{}@jEFvD2RMpvjA923Q$nm*W@5zNR}vGab<~&Wh57*8 z|3iiQow3uVZNJv}ys5ac2?_f<`(CyWPj2U3)=y)oqHto*)T!KQh0#wB5{Bdq-e_4^iV=<0hxhh0#Ud;Rftc?mb;$#L z_72IHmJRcg1q845cMI&Z4JeBTc25qMZU>dU!;DFXeH8@5;cl_=0g_3#qJO&*>uT;Q z_H5-ZBHlINzUzXv07S-tIDqZDIIRFRf3dxXU!ZqpDt!3t)-yQxG8nSp)`IVPj?OHL zOXhSE#v^&ZO%88?MBJQ-`O&JSr{2qpQ{g#cVLpF{_xYdaxYII6tvE-meGcYx`yBb8 z8qdLveYQoMx*=(_FrQGj0sy4m)u?(6zJVC4Ix6%_%5$B zlbxr+sN8lIJs=VTt->wtcny@YdrSs962 zqP-_MLu%E1aF(a6)#cSmT6}pmP)TS%CPNA2#l_R#ZJ0LV(=We#8AwNA&f%Lk4uSeZH*Q+rVT!GlVqK3U z645CX$EpKcE*mFBZvLdkt)&eikwn;TbCuXj4B}dzxy9L!oJ}pCW{Z4&oVs}N)E|8m zF0Njl>7HJ$DtXk8Q^)C2lXRTUWeHUJX*FQL_ zRf|vTwL{!~MEf8r?*+V_f&YtGr-K%xvAF&h)}&Oh71qqu$o)C_`5D!b61gTKK0+gx zM84W3zkklF!UIQ^njepNoG+!3vhJ=&Ese;{>Qo})C z373@sR}~RaU>Mq0&TCE4JI|SDP}ok@N$ZA_25*vX4ZPICfX~*izaPql+OE| zj%zAp8x5WnRCH4V>490};_K^+3=yNrQC8NFg9xO};-Z?Iy;_Furb zo7e7uzF_ow4mV&A{21O{vc+~%=v|OcVm$;lZ;huiN3UT?J?~QzUr;KSJFQUHNi7DC zDgu=Ck0&u^g^RDscd_pV-%4K&!R9CS7H-oOfba^E*z|Vzd~L}yLb1Vy?W-I z8IJxt^T*At`Gg0|{gkQi)J>gYyNuhx1FA#wYs@X?Fp-y%V2K<05^jbO zZiiuRjre%X$0I&oaD2hX!gphikD=Aa7n~KIED*jsJK`(_o`1rA-kizLB~@`ov98wt zg>qG+_>I8BLL))+2iCzjxk9V+a8Gvk&}kKN;RgeFr{$?mE%_~-So3#K0aG|@RbKRB)hjl`q zIm2Fpukpjk{SW?X;ifnE+Hb$UvYfpH6kGQ0VF=H)dCzfg+-turf8|&19r(v6W)JB{ z3;wyqKCr_8G|0bY1N8yH0l`6%e{Pk76H`GJhy{Ld=+E#$>1W$H0J_hc4wkzOo+44= z!%OL3AHoexwgjI&c;J53l$q*56;h+{tqZMgfNJvt_kZ;_@OqourI_S4KmK#P&5wNP zfBUVZw#|=!Dck(Wu53G0NAVgf*jxN&z4-4l@WKN+^o0k{x3^pcNJ;-LuwAAvNh2u^ zd9!Nd-FYKVJQQ;);&m;)<}jE+`Y$*s(2WCb5-vCp=|oN+3G}AG1P+)Iv~da$r)Nys zaa-q18eH{!7Ws$s-8vWK4~E}7>s~PjRt*9MzW8-q)c^OT*Wug1%nrSKu&mEr{8!;t z^ul1^&7Ivk2Mjn?s$-E9de}&wlwv(!CZa{j*DCWQY--{R7Z^dh!D7U#KUUcNhts|iEe-SLAaW*WQ z#qFi!$VN)R=QET>?droT4F-2tPu~|}MNY0hRqh5)u1e|2SLvghuGm9Gt>I7`#qux$ zCN^93Oj&xT#rROIEHmBqH*mQ#XZrMMAHtMfyDWP^_aR|Xa9dP3{RO<$zYjdwrw@*S zro&6??YV|6`s z)Gi;5WlS>`&g*MC!rh-T_0vs}5h=?z+1`t;SxB|+;i)AGC1Fy}KDh7 z{Z}rkE9U6qX5No4YJ(OTni}yjOK~KEOxKM;P z**>GURMXq4p|;vKo{XQ2#_v!1eTJLmWK?OZQ5(t0Fi=*ZX{)&U|1?7enZea|093+a z@U$9S+5NoZ(o}_n<|~*o zI@;cQTgba0Ax^|vYL(pzCk1q1^DT@N*nfV?1X4VgoHT#F5CyA-*|VlTf$!q#x!hb* zK4KUSdF{Bh;YOR7)+l?@+B7}ATk%^WYyNh_UeG5)8lwC`Yd;Pql= z8n!jz3|!-)3Zmww;0n*9l;9V>0%zcSHT?Wt{QS0PgW_ED8X`Nyo{KFw+e;(BPnB1* z+7w6FOfC3{XC-GyP6MTV0VjJ3)vR@v-!Jr%) z0WLb~G)5dFpqv8zo`Bn8twtc2aSE4fw8|3`$3j{_Na;edmVi_|5@g!*x<(cgn1+2e z6J!gyUGVC?VHhev`hhGbv0yX~zF)PaYy^w#o41Y}X@n9IJkPU)=M&AI$_n}zOO^2zGH1D@Laty8T(T1`Il}2UvFQI) zl62O9OF^4rPUoosDAGDIaKziua5cuwn?j8Z4*3hEcUbt5a}@Z9Gn4(%&g|(#^5^&} znZiY#tz@N=Dmmwbv*=Xf`K_2ohbL^wq;pJl(LxWfp#N-D7JPC7-m#{TokVi#gncB{ z5Z;J1yYm&STtH7LQ|1*7U`_XTt?K8XJw zi#p1cuVNJhC7BZ^N9ZUpF3w^`;1zpD;J;?TcwhnDf=IQs8^MC;DCu-^_f9gh1YHbT zPsTt=adnfAkX6>$Ak=nySICdiOogP3*H-9w8sD^S&xLVZUH39oC6q(4Q(vO1NO_cP z_rKK@S;u^d5#jBN^p&&GMXK{+qzEplB-^hITnb+qgR>X4dK&R{BktYQ*w6~3muf5t zy8_dKx&AVh#ay$t#{u)UTI*m?6eq@}_`kScsgBe@WS>Pb3GwM{T&xeWgPmy!Ng@`y zw@1;z_@96vIw4+@4$wnJuk)et@6*wTqF9r^GmD?F;VI+$#A?Gj4=d~2bHT9eNWEvq z*xo^-JEV_{i<+Gl)Vu$H@XX6|s^Qc6;e%fPYtOW!lao{Dy;;_0@u`fyF*=1?Kumg2 zyPPMKx}Nk$@3Pq?^|=ax|^q7>v_aYBh{I_g5syY2fU9| z0@dvW&WBw~cfK=!!RLodJSMbXzHVbybm{PcokGI93@RQPRC09PL`Pg|HanNfz;P*U zd^+748$tr~oewRf>&L|kzsLEK`0ps1BM8$7Vf4zB-1YA-FIqJyGPZbCL2$kyAS2o< zByW0;%*lC?gNK?r`*=l$hPkT)Ba;J@mUQyT?%Kt-{NBdyOum1lr^3}3qVbF{YUz-r zAMY+;cJbL$w-=ODPEA*+14qqXVlLV@tz*jQO#^rRIz%gH#3@jk9)#m!Kt(DVCD`i zr5^4~yUWOem zgCStZWew~M>e-&8>JZprCHJg~rS}Qs6Uf_SzJPz<#^$!|mj_@k*!95n3y^|oa4nct zUClV#cG9KR->RuLII3_ATQ4*Pv5&H-lIGKNrt z?}DSTf~AIyMhpyld-7Es91I73LhE6)P(lg)$a2#2Y_Blhw8eIx4!6aTI2u~lIfBjh zuW_VPkllG6o__$&z^M;FC|&!1JeAho2dN3&J^m)U01g-Dqq9V)OWb6rrU z0-KVWN<{DZq^CucSqWTOUTa`=P6nl(w2Vi(nxsBTD%8ic$}&pWT%@|vz6n^veBGw*}P85>Yb!Y*Vc2&B~==o z(!TFV8Z>uOV(NNQb5cjrpd}hd8gwgI?0G^M7z&}@IvbiSF)bUKZ~5UaPKbW9RZXco zCES-P;L-sQIts&@=p`Klj5HfQynXw_4XqFYDeyWnhr;RW@Vz#9-FQ44o)N~t-Emrg z1OHSav2mhON+g-h5t3%dT7zVT+;uUGFM2@Jhz=n^1~l|@F`pdpTc*GhkleD5b(|=&>xH%_eJ;g%8n`YTk{VdoKJ9b zLHe|moks;yQPdc-Ix0x-9VFG}QoM%KYZO#8!mX*%tf08bF^jm9G4I82 z&S$yz3J+cpRHgH%^QUxggw?rN{MSTdY#*MUqyt5APZQ(O_qq?Nj)AcDrrHpsP#vZ`|~(@XZm!Jw4-(N9bI4Zvkc73JV7e5c=%vU^!V= z3GQP9L|RK;vMkuk2xzl1^lAsSe|_oNOqg{V+A8gf!%QF)f9qfC;={pL!EnDrmq9ImxsYstDu@tvf0Lb&|Tbdv~8x7p)%a$Nf_r0dn~(4~1>=q&H7g-%jgR?@R@|7Lv8AjxAvW4|;yB#s_O577ZGr^VWiSPiXpb#&m5^sKg~ z_Mw1KlCt6rz7h07BFyI*q8BKm*ye#tu(xT^0~6Q&7W7(H0yp04G=rIa6K-10h2Mkj zu-cYWgM9$DbLnL}X1nGPlN zA3JuC>jSSZhnt}FJ?|Y}i{1l=?}>EnK;UX;cE){Ut1Ua>=Uhw*?sYE+Et5~{1 zdQ8TbvC+f@L>@|Dt1d^5)nKO}R|)&K?|wtpU^G3{p4j$mvp|2*HzG9G<2qXvvcKH2 zJmQ-p`nM$H+3AkYBFut4_OH(h-WYMV5$(m)XX0+}AfH8c z0nt4=jIYk12F{4m_*PhA7&KX9NkO-Qu23Gs_r_Le)eghp1)G5AP||zBZWY|VSxtMl zvI%gTB=Doaci1+d2%Wo_o%B)-a6y#DHBqju=aq{UQ&l>R-8j(vry8li7wrN8pf+_< z7RwGWxy3HPxy+!3veW-N(i24BT_Bbfs&S1W?~4f!!o@y*_O^c2)tGrXUn?>No_)pL zw@R76MIPdXnlHybXc>#kA)DYdsZu-*cv7^;iu*vURTOF$U&#CK)pF;#WD}M{)VrXY zmS=Fzt)|AEl4|iivu17*HAzYr#n|iNd0$l!y|dRx=*=tmG_J;uf88e0N z6=+otL*y^Ez0f;1g?A>myfed*@6@|(Z8z=J@_XSf6wVLJc6NO0S{r;HP(PeeG(n6t z3%Y>3&-eb9E>I!=bu8Fx*9BtVxt-!&E9K<EtN_XT*VO$6SC zmVP{B{Z9+)&jpk9XM8T@3y*yREzMl5=7w$*G>;HkU{?n)z-j4Cjz;FLgxo55C zX6KW0RWf($IoJiHz5&lc3H30XNyKdw!R=y8O{_rMuQ6s{iL@1ZzX`OPN@!QxQYV3E z7eq}Nf+_b=oA-tB9lhclbrod%A=JO#ABWz*^pf{W(VpAa=6z!0i{m$t_unATi67Bw z{7+lXGf1yC8D%od6*ONV!=2jX_(Z7*pUIuW{o8mc72VL_=&*n#9_ie6^Cow{`uQU4 zl!-MUq(_5&EPUz)vW2m5=;Ivj)bNtA&Xd3<^5Cki-(Z)@(f5V$%v<8R)sl51b&`ZP zz96+$V}VpSXGHYC=ZqdyirLA-*-JQI)UyEBCWt4DB>dv6(>qfw2a)25psE3B*0!gD zM!j9TCML8!g9Kx`^mz+@Kc;)jVPw;m8^sfM4?8BDNg`PAnWP8R!Hgi0c{r0}NfDSU z!oj4fH8d^flTD5Is-yn_nzrYa6SMog4Zk0o+j4NZ#tsdRf0S}z!Wms4xzoU&2-p(8 z;KBgy(zg_ujO9ro3OMA2fQTpU{$>d>#uKK|v)e{Rgt!R4FPEIp$!J#*NPNFnf_(yZ z1RMv(d3EZ2<>D2OUJ39*>p%(8Kwm(&ppnRVc+yM1tL5#22KYzi~qv^dl(k)$>)*8P>nrvlr9T_T6*%3s5}=JwffN zPMv8}r_RjgXW_U}CtXV7xfI3xf$)%1uDCAPJ)6@@6_iGu`ydrLV9KyE>B+EDV=^BrhGVU`t&)t$x!#g@F*}QDvUn&ys}Rpkk_X_xGK~F zZA5yt6X^*RgKuYuWrGZ%PF_lbH|OEjPQW`wEWh=aR%k(m=dnobnvi<$vUaK_V$`W{ zeuvS1>k;xYv?NPRNLvpeMwM8cC0-baf5ZGhh|_CmSxs)fQRy5vcF4phWh)4kZf3+! z9@8P?*2K{tJt%EQ-|W;G{*X6x!h(J9GjBt2V!N`Hw=m_NH?1Gkty`~M^gdhRmy2f4 zPO-m%uX|3V8PRz0}rwd3b1diCnvXM5i_r%oF&a^U0T%e!=0y0K61*6S2wFoM&| zy5%0~kUDuk?IsLMIs!J>7Ec3YR)JOCndrCkEHWu8By**Zlpvfy|3&O2noy{}oL}+cO7u zkm=MpI}7=~d8CQVl&PtylgrFm>1kuc^}9Z~1SFRx$8C>@%r-|wIXU5eGCg~(Ei!j> z_sHp$Q_wl9WeI1DwCm)2E|ug?w>LXUojkmQ4dJv$ppFkCE7&A7-qaW+6;evKUw>R( z;juBeBIE)U-P9yr{GJkH#CHMykLyQzN=&=?Ul#1pX!|FlNKHo<>vuVa{xB0aDa ztxG8G6{^-4fhL^SgepD5gjH!GNw8|q0?MQKh7+=nE`@_{H@QgRlRKRbg(t zVX^$DWmwoLYlrOus0P^uFDJiy*W9sUYy$0>TS%T6@x2NrR$-9q4V0_FXz&+W)7-O? zt?yc4Ec53oRBH?sUUGj`L#n-p?n^dzLYoi=*S>}AKO8gB5$NFVzbKFve9cUGG3-HL zj6!_>M7$f#$v;~zmFc9EUh3y%Yy+dd%CFwYR=KS4s`8W>+rao=KulC8u+!#_YT;Q& zDi{fZzxoRPVEdE~{Ak`SaQ@3hDMp_U8t6Oke6a4Lw`}`tm0J#iUnsHH z2AfU#;A42Qc#THqq@l75MB@nXsOsFck~&^i$6DN5!=n|_#DyADqC{~HvyMPGWz$xm zxO4u^D;G)%3rjA1ZMpdfS}WGk(ZG4n{)yG|=TC+6r_KlIZ(eQs_RwB@CWT|!#CDE0 zBdb~A!}L2GSwQnr>f!MQ?WSyrL3P|)YBhj#7}Brd3-v> zgZxk&T0N)C$t z8yK_O$YOkK#hkMp&(F?k%hL-97>JJ#A~@y|f3i=DPtDFp9#dBWXFp_5w}8?#EuOzSuKgqDL1g}HtyH3uzBqpso?qy*@RIp;ZRVHo-QS4o zO#kuf+3a@1qJl_wE$;<~z@6IXYd(B?cTDJh=Brjcw)!Ev*&z56_O`t;vFkMYzomWe z9MOBAsR#BW)=HbDrJ=9jLsrKh~nD%o3J>RUOJK%)|TffbIv zm+W^o1AW!jf&SB)4xhrANfnzwGQ6=#?0;Dev#V|2RO2R?Y&CpVPHQMq4>ujj`B?}@ zUn+>yg$NBvgajH=?vBVO_N~F!I!T0zgFt&z8_6u|Y2`b$W3QJCzcUU#-Lsv21kYU) zTH4Sf^GAIRBo_L$6+7#kZMj0j8+u6Lo7dyxkB3F<-hK%Ni;Zr);AdC1)g0fuiuAuB zIU#@JxR8pc;>BE$e72CChkh1fUY!w*4srL<&+W<2`G^-1a6bmBuuXoY4xfp*B^iO6 zDOe&V_Qk0|Fg><>+h>4*uijXSgAK>#2JMFj(a);(yBF8YVRuENKy}d)faeEbVHMvYN%>SoBYqj6&n-& zo3bsf3SUZBM~!BnW&HUl=;Fj#+IT{Afd5@ZR{GsAv!h0-1x>8MBX0h|}mI zi{k}db(-8Y@EfvQs5sKInNsUbj#N1!ZBGM#;0`=M!0qtD)x{;N3&WUm)^5x}5C}ry z1Nb1tZ_d#Pv9S}5&Vk>afN4UEr3j6CAC0Re7~x!MoR1Pk<2*ey2cs6Jz&Np=K6`c> zZe0EGmL5H}e7pv@0sq@!g{z9ktj`aO7_@pQJrxZLF6XVg^4-<-z2S$j5xxsN@TBcW ztk}D3Xad3mNj>hifQQjOwl^>(5R^O!04yI?xMo=K>ca5bAOPXx4*Z`zV^-UN_e(*F zHyC~dKZWmNH1L{yL+)Ylz-vhEHpUB(PUEvPaa^zf(;}>JbqN_4LG~^D4t~zvhpSJ( z9W6s+IteQv(tH*7JFcz)I%ifw;>db5GK&c>0*(mf=Rv|-=eJr7)fAiRZP>U=D8nY)iLp zTRz(ye*%6q?$wDY?Wdji;mG(n_qoR=Sid?lIn&_PaajboHQ!!2I=N-abwb*!2B@0Y!V>|L)G- z!T3VL6PXh??A#yGg`A{$3@!?Kt7O*kpBP=^%07RVn+ZpvUSKZr`i|PCJ>OtYR z(c;K@bj{iP+1A`xLf!GN&$0b3u4`v% zNk?bVQfn{FFNAhL+WeUJB)yE%$$pPZXD~```X~mQNv|{on2AyJz)`e$m5^|Fm-Pws;GK0N-SE!b?C0*?t!m z;pp7$xX!2f7UwC*iav+Gwtfed0Ji5M`b8Fte&+CBp-b531Ft& zzW7G*sG&~D(c9kzW^GFM;u)**Mjz?|qT$N$f?*TPS%cGqTo7L#X}-fPM)D$o>Llbo zFuLUS8oA?AO(AtN1+3CSxGCnZn(XJMCRrD-a}3RS=XsOLyGfar_EoUJ?i*^ z>=xlt@anf4@?YD%E+cYi+`9OYF#|^gJ+C$R z2mRFcLzglx)MOr%Vx4->FKhgc8w)4gECAc!lgx45LaYm4sVX+n&$}HG^a5`Z>&Db} z1!GqZ*eT^gkw^C!K7?Nqr95oSz%X!?3$iKTXYf8o#IA_rCLEp3Ac+g8O-S|(SXJ$5{X?>^ez{dRcqt|^mu4GFt-({_^1 z>piPS;68Y(@^-fsZ~gH0%I<;Yeo>ug42T8wqmC`?(rw9!ksYTFh>gvkoW6L`iQrCy z6J}1CI&WyjsKkWQ%|#tX_f2(CXAGK&_X&kyn_|cJ-#XBg0Ir4>t{F}i4pE5lzTc7{r*)4498_T+WaA)+c zQjEekAmIB~2js52@O}SxLDs!d3a9)n*QR{&a|`r+E5F}5{qu7RDADFQi(tn&bx3|Y zGvX9+u~^!w2^!3(+xe?Y;%}Fp`+M^qs`>2j+sUQtxGp%oT-kMUML}4~k_Wp74A}i( z2|}l$SH;X;f-XFQ#$JGM@y92Qz(0yj2(njLIMWV`1^F~Vfg-Woe2B!Cq%*W8e|BD! zn}q4L`_bmgrrkZdzfwCMJU|vq&)%1Zh8zI*V@B?sG;Z(6D4x-T=XRKLYC^C&JSV}M z-epSZ(#5PFcWFz(ki(Bw%=xT-OFL}UWTc(G{CGt5ysVTFTICD?%IkC27!$;A=2snTK?7#m)G{Z%>?(Ho8N18uK<<}%AJz8;{KMN zeYW0*)(D ziipK&)8_^C?-oNjZ0H{3E-um5GGS}$nyvk9Vmo7#h{TmRl> z@X|6-j0#D!ggCtqqe7VJP4q_>-+%w&?V^g&$;qQDif)&GSy@m}`DHo!W`AMfe)J8y zPVxZG{8++v7`Oe(j`1BBtBUWp^*&I3xV;~@Zy(oh`-kx9ef0evVgKU(PZQBvd6Djt zxD?EBD=k?&L{&so(a0u-1Yp9_Cl1N=WVTyJ-+uE=w3u$I9}x2v@&Wm4KUmj4FlfNK zJ8Sa6NBY2cANcsh&YdUdk!U;l^;~`FyNj!O(1p9p2FJz@D%<U5g>d&GJ84?GW_)t1~& z9k*q`tP|6cfBO0DSH3)8i|SRH>gJYOO23{wrebhm#Ta@SytyW~$GRKygM;(Si{e@O zaai8uE;}~C-nnZ(1`3riE<4uG#kQ(?WpSL%n~fie*LMcRd;*J{J{q67~$PnJ4*gwD* z`~*Y=^bRlq_v`Td4t@e$fzJ=vU+D*uK)kn*$w+iOF4Bubiv%XMFHG~D8#iQm-^@WN zo^zuLS8$iPfRvmN^SqJ_o()9bb(uG$1F5rWW`6;n^Q9^Y)v39^m?I@+zhe^kpRm8F zHMJ7sq(U$bi)~Tn1Ub_)CV(yrkC$f5El%}I8r_E%u4noHn1-uzI4dv}H*ec8tPj6w?Vf=i7c?ahNQ zxDw{`^5dn$pM3wdu-B%*d@h>w%fNjVMQtGLDPZ?2RD#u>KpaUB9o~ETrWw7%BhWw7 zdoz@!{mBKTN9J_uH0Ma^f|Knn_wUnNZtb6(nmT#^$PxRepnsnm={_Td_22aX@DFzN zA2y=eYOWOV;Mxm#VCV%*99ZblH|)qdgouE|wfhL|9E^sooGm6e*sPVpT71KnptbTO zYb8WG9G!+m@&^YUx6oD_o1V5{d%t{(rPIlo7e|Z$=h;Hoy%K_bdA){~?Eldg^ZKZg z*|S>FMNjH1u;u>(Er77rtf)g+w(vfj_5vxa_l;d=4@fP_j`49a=FURjWufojpOr7r z!}ea!-Sc_`cI-c_G^XdS`8|Tn`NgFI|KmO&O$av`(c5CvUS^xkWI@caoDSr52!89A zZTJG``Kw#_!a+}wE3EkfQ_y=cF|7+KMUJoy7S2t$@6Z?#xYiLETUjJ%7=~2pA|?jKty<*q$i`?Q&*r>(yt?s19{?VZ$fPOzXU2;e_5%o3?6-%eG|aEGkY;Dx3yN z;fJ2FA?|MB=1`B`y*tyu|a-VrSp|oPyNX)fUDo28iFlFlH4ZZVseY|wa?VW>g@8e24ebJm6 z!De;vtI!CX9bs|s>Q%Ih2MhFl{+Z-W+g?Op%DzVQcygDPz*TWz>ND8Wf_Q?L+vCdK zXpS&^p7Wv%!9qsmSPwN`4_7v)l@v)U8`t@-+=)2>b#>Z~14ehae1$&vbsGs1I$^#@Y3D_Xu(~R{G05#SnPB(w>#l^ZJdNdN|(ew?Bq;hTAO(o62M=&cMxQPqy?SQ zIxl_u&$pL!PM@@M&{rY7XXW*pofo1B?-F0$b9V1gP7dT>e^A-;qh)j7-PXVVws+^w zzP4qE%Jz2Oib)+iPO9kJW7hEeh^!eq1v(u^v@Q^PP~Z{|`w6oklh9`VyCQ!8*~XWy z<6Zpx7`!xe$ZPbxfBvNNN0t2ivYNQD&0n)IXv|0|6I0h2NL)2~Oj^RtNM(^?>t@3irKVz`J?DnHE#_^8g-{CZ@!MDNVm)nkePaX^m0YmdE} zE06EeH?(s?N``j_x5x~CTCMT7R%T7>8<|uzuXBFFtQn(&VrP`^wDS*_BJ6Q|s`xLN z$)&()Eo_L`>IIQ$?IXzjHE691`2ZyK(-DOeNXScQV2g}8qGTO}2@cXEX$4J7$PkW{ z{F*CCYY$%>=Mm`|AKPWo)RHh}*895)E$-Qar)QOJD@|ay#N>QFvg@$q>}h?Y!b%QvJEZd3W5#17fJ5JqIxD z25ZU07Gc`^ybiM>o|T^Wyb@3PJ#${PpzFyrt@sm!#c-!rj{&Nx}YRAvd^?GgLd`|>eg#u!Zb@+R%*$@B@0VZA4t_MvP!S$ zjDU7yr_7wcXz44Ra>jHv28A7Wc5{&?j6X0Tw_-#2{7FN)Q7yHiq&A~BflH2L63+iX zaA_Sdv0`U}q&T5h0S-?|gm10jneD@X>?ETpwQup*gy@MwGZcOuV!rLrBSIaN(I?U) z(*#PZ=47%8HDW;5sO;$Wy_Wu9cwo?D!u&t2HC?LiaO-)2=^pu^C^j~M<+Y$5GP88gG0y($#h7Cf568El< z2oX)@DO!=GXhnSWc;$jRwe#+i<6+XVyfiGaLp#5&vv=lAJUK5D28QQ%4)cvlit>$3 zT{1o^BzG+RLC+lP1SC7u!dj&-I$<67}FSgh6;>7k7_f~tx z_lPrQcFyVEH==j1_6wJ-%E=m&6JWO$*e?-(iIK$?xzG~%NDu&}FZPeno;M|>a#{R@Iji!zmJLfr zJcMno0>VQD_BDIS{=~Z1sBXPKEyzlG$^QKN>q;!PpV;@h#DMS!Cg+dD>>#z!cGYL! zd*U?AdW*5wfI$(LuUP(09hVnn>2zwuJ7VSZ|SBhi=erzik)vy>M;? zrqV$+e@kU0z5!0)bpxWCfUEjnxT^m%t|?=Cw`+?l8*SU$8rkT=W&NLjMhM#)Tg>O7 zVxK%OToW7E%D=XAj0*c$K|qMp3w{BZ#^|j-)@|Ha*Z$=E(j#*_b((vmbpA;?Ih?ox z;lwe>3qJyn>>4_B7pJNoF$|ed@Y%<^@`r&Rv5|*-f?I--CD!|}(+I8lKU;NZsD`7t$lOREY?c2DZi zVbbmr%evoB+w=>j&tv3S3r>z5dvXDN9sd2{wm!HbFSzTd#T9*v@&|06n#p*E_nO!# zXL65V*gbpYdmyM+PG%3=;Edj}`RN!oq`*AOep?cZQwlPnz$Nu?#gV!vPuY#TVO-I>*x#OXI5p z8ymZ}kKxc9*o>z;Z$BEMpaNjsgm~lj>eWBZjQqX-bMe)lrFF zkRxYKN}18b611co#Wuf9v2Mw3$paC^7=@HlNTh5F#c&LmL0?HCXbUh#Tj7JPU;{!9 z@dp@=;C!PMK6ER5@G1Fly1;hi1io7gzdHlHyC2^rQ^U~|FH;F5tpOCnVgA6E_K4)8 zKiT>fUGT?NG7Yw0kPzF-Z6)&nw5kk?@Dt|2T)P$hZY$;^@jVsKd0@T*(a?*jYyJ%J zm5%zNxfs*)(VvLBbnr)N4V8A9lCy-O_yW~|XDC+AsSwGi)09j}p3Cs_(-bQsKe6Il zG8VlRgW#fjA}Rlno@a-PLF;LU3lop-xpgZ&Z!6imt@g;jX@$%QOyEd3S=i?zm}~SR zb}Wv0VY_GqzAA+sdr+VwM=@`-(4x(p4w`dheW>@Flfh~(1ifoOG?!AW&>QwNpjlNz zLrjgC%j0O$sm=8M`SV=JGZmSi^WZ4%#LMZ8@!~uLiW69`B8D6E@^`i9-K)Z@H1$4u zc{Nf!m{(2bWHgV!k*e;+l1tQU7*Nkiq8pxKpk#S60+b+<5Mbxev&FY;@j_1oTnN=j z>UO-(xo}FE)X5oPbq}{EJ;znC^>SSL^b{vcCw2gOdn}^#oo_a6Sw0ce+g8y-fb-M! zTQ5P^^#WgZLVS7m|9~$qKYJ$fCANF^ksP;4wV~O*QXe3tYh9&!xm1xILaxAStX+g8 z=p=e5eL92Yikj}_p7h4N=@w-A3gw;UZ!M!@+8U}0d~QWbb+%zq2t6X__VI~s^Z?U5qc-E%XY*`pNJj; zWnG_@!+N)iz@b%aX|Xw^o<6bGO^X{x>0MQg_ZqE@jWyHdlO%LeI}vs_3_DdTt&-KN ztMpYTbAH|UKSRV$5*Nh4DcZ#5_IRoH1&~4tS=~-Tftg7|kz1-oY?E}|G z^S4I`u6q zSa6b$c1Pr^^{O(|`>CoFCz4i^)E5p;Bwr z*+RF#)8fsi_pH{M$xdVCw4GVh0<+XAs+9FK#n1@*=zCXGRx4?x$BB)65{!PXU_~8s zs;=xji~@In{ww-*TR*xu$aak`{&>gwXLf!D)5+Y%b6hrJ=4=*?WEH34gsD#B2D1;z z@L>9Re629a#Y1$UCy;%abvyv)#y_81#s_FD}3KUTU6MJr^pDVlg{1OZNwhj?V z_ccAlc7UF9ZId;cE&fH2cXh~ie2X22_;FCJ(L*X%1F6p`+}jYLT031gS+__YEk9i; z=ZdTj7BC9C!lg>*TkpqJoit#EywY@bynLd^M4z*R`SR=KiUI;sgVPxS56-osf{V@lvy-&KkEZHb)x&7C3TlZO zWTI8Jt?N#|N%$T4shdbYkmPfkY)Z<=)p(t)HN%ucWe&E~2*f@ouTs>53u+Y-0_TP@ zy_gJ!DG~^7mj^Vn>AXI+U{Mi#4#1HQmnVQH*3r!Nsk>%m`mRsg_MN!Lm|LVyB;lNw zM5=Z6@D#*PZ7-Kz?inr_?k8D?2=XF0ob#xn>Yb~cqOthVV!5MpX2gsTOjBb4D46la z>^y(}yxDKefJZ>Vh_yZa{d=w*0gtf7=5d?$yuN4CIP<#n85`?2&Pb>1d!6}()D9%p z$|X`Dl~UYkDJ{b!wB9?t2!K|LE*IdC&{Zrh^0qc0rZ(cnH)>7-KpEI#>+}Zw83P9} z@6#+?4JKM$?EAlh^!Rh3;?e%6qzbtdoWk25b9B4b`<^-{tD=#{16bqLOj0gX(na`! zMNC#b`UkT$TVV|Z->iLmR=o8Kdeo9Swzz%Sg;ijh^-b`@wM`DZ*t6_pDv%mc8=S3_ zs-3;0H3lH1f^cE)>B$C+S0h$eruL>VlfhIw+Ei%j#*Sudrm;$s)V}J$qA=1`$*Fpm zD(914Nc39oS!)Z}@#?|qne6FBYOV;`1wOznosIMJ!1dhZ5=(Mn1Y^?TV-33C0h{S+ z=+V8TdmPwgdl$@}JFF%@CXD7v&gU^MoP;T2ixqo%W{*hpk=mZv4y*%rF27MZ=v`+w zr~wC5UA^LhUClt^hN&XgE_vHSo`NsAuf*P+H4|U+9COZjARZAHpG0^ zwsHj-AAG$NHa@IPH7YrUL^M`=LOmn$tc?la%@Jc4E_~+=+n4LhO}EUgUzQf3BN6RbC93qIR_dCH?p@k`X-Oc@YG?AYbH& z<#oh(w zXC3Y>i0E=I-O1a@#ffq3ND(}wi>s8N-uYC$9#Q&U)598_ibJ|Pre>5=7bm(1kkm?6 z!X*S^g9d1r6>n?X6|A_l1TF>v@ZKe$Tecya=?o0;;mp$~RxBDDy}D{N>tu~h*@_!N z*kdWUFTs#n4=kIUq|(#cY<}MZXnQM!0ZLf-iZ*Za7vRBhGKEvUTYe+Nn>c<-5Q+pn6CT zdHy#mzq9|Bu31joRa;Ji5q~&r$91Gua%`;+gZmarC8sG|CwT<{TQgLdfi^P&D$O}f zp6i?|ZzbV;1o%CwbSkvsvQv1)t=0vNr-$mm6!&wJb$PmO1_t5a;lM#haKOutFDL*B zM)5XV3EzUic~A{#5CT7f&1laIX?p+Thpz#UBO=2V!$#Y8uyNhnPd+{WxrmIY5B_0? zQ?68(T6d{b!Z=ISXONNRhJ@lh>lMVm63oA~iA-mvAHy-N@NgHDzJ#h*U2sE7aOHFo zgA4oIT;0-vn8qd{x&j0hCoKHz>cb6UhaMO;c%iESMn{<9*UyXG+ z6O?y!Y*&!dBGWiTUr%a$ts&dZNvfo!r#*oeVNzUqd{UK5NTWogIi;kcRRa;_Yg1i2 zFd0-1Q#+m-NDZaBxt<&2I-g3TWDcke0@R3;J*zwr;jh&8b4^C5O~6G%r1F4h#H++|n<>j7AE9^3_6tYz!~H~{UU{O-^H1l7#@>xfor zt%KE+`J5KZQMm@|{ib#&opbx0bjj^EsNkeB+F{UX1xo_!e;S!uF~|VSD>%ha(a|vj z+vtCWxpiJ2m$$GFJPCR&d~0qGU%EXqO51mxIVL-FeL~UN{f_y$zG(gs>OgInpVZey z>dc&z(ymfKha!1wRaqNrRL+z$*)%zP2R@uv`PNdtc~mhqnL@J9+L(J%kyr2r<=Xr< z1rT`2?M|`!=mp4IsP&^_r~&!`cyG6>E!B=NT)HIu0Gpy$olZrl>^c|5nXi6e~W$my4L!kbz$UEw=+_AwJ#JoK~E?R$ad;~F-i@OaU**?(r&WCqY>z${*O2@75w5rB&_QS~8VpT8~ z4z}X%OI$d4z5*%0BjWRT@;q924i3ZRy2lFrCeyGQPiR*}B9_@fN|I*dPl z!9E6VncpdfL!_+hrYvCUnRup+{m}+8&Zpm);&-LI7u*W_m)7P za*^w%y7`vO^YL)YD^Mz&9#UaDa^cuf3E~T(A8A7;uUVN(F zBOy9Je`WW5my%QJJ7rHC*ltL|!2Bg6cOu%nO7&-an9nJHib}%em`RR{-^kUfSiZUG z$R5Dl^=fqA&hhKw67)W!hL=n%9FZN@t{B`%X`j=+@SSh_pX5DsM)&T$`gP2mnUUsN z=Su_6n90*(on5r1y41WvoQroBA^D1ADcbk*n!Uj#wC{!5UEJ9Fvc!g-&qvRf+n+Zd zg-XWEo+ZyO!F2R|vhY4sg3G)PJzvo5P2`6#&Jy@L_qO={Q}X^4B3Hy-h$QA3hp%3+ z@VbA*v$ZAg0RJPsM-{}aBYnxPFe&f=dcL~(8dJ%7qUV#y^Q+V|W*L6JxrzUg@pHU? zm9D2(*`Jg5h3D7A=X;=%3t>vp^FncaeB(N>KgT^z9E3 zVr0D5B~rkT%)_2+nV-&Jv2Iz={0Za5^da>*i2~CTfrnY0vug%W{<=w;ntAM-DVcrz z^5CG7R1#zfLvxWa$y|elxj+`4i>zY_9Yp$C z;+f*`EHuX&6a11A=~v|mmRM;N{0u&XZ-SWHpX_a)vv9@CWqs1&fnD1yi&r^#p@cby z#vUT#F@^C%cr1ZRnJ4{(%0OcaJ*R?#1JvDfPWJ?cE+FU6ns*z|1i1&s>>a;uLD~7uaV1DHxxW+i&yEO1L4Ntqrh1nGHu?%vR=Ix3_EYRg;t;`C_a+j-+kecjc@!^ z_6DF=2L86IM_bf7uNuE-^D395kl0P*Cnov>Ir{SJI^jfFk3Q;I-}`&&xV^U+~DWVAY-^OIO|6Q5aEAuE(F5}asR!CxE@e5ppre! zhLO8^T5Y=c7AY8~Z`A-SNzdXRK;K!QFWG^E4wVd;(jzXqpkcoC^7NvZ$f%Iey%7G~ z^!};6Xdl*3x_N5kQV-TAdC8qcJ*qm!kIwaQ*JOEHJS&#g;l77tel8oqRVwb4SuFCo znvqzd$5R$8tMIXej$UlB5I$)>DA~(lJkAU6bAPZ4(erUIhucM-uNUMI(}!J%Y2191 zyN+mV#FZ2+HUlB4xVyz&AB4FFB;pOB!rK5n3P`|=rWYBFxzjBu&so{Iw4hJV%;e6I zsVS*FyJ`FYo!cLjcDGEd_-w_@_eR1`RTgKua?YYP1Glr2`moMEMuSErcPW?{7OW_c zdwTi=sa1yPsNO;0*5h3PU`|%wo?vCp@{%NtH*`nwJW z>Q#fMOzqMaGP~e32o7^iY45HpP%FJUcMiE|=;_%D>Oj-6 z(xkAEEz2?j`W}u<-qbOVM(ej3p5=1L9=U6m&t#7f{X>6_tRG*Tc_VRbdjcum8?6jJ z@J6Q56M&?YltD$gne(<^JGT~Wer;KC@56!p=&%7<^ZGf%K2Mvtcv9GJ7jLk+H^7z5&>BP<;};8WO8SrC?Q={|Ie+~{Aja_xXoafRzk ziEbu3o9RX+V)-pBvO~%VH_r-7gZ{(|x6qo%Pj-HGbLH|&Vb!VGWjXNE3`-`U4-QLP zSazykhlQC_JGD21H;3LSUh8FX$_&ZsnV!1f@01=iP*!&h@*EAg8B>-H-yG@5E8LBF z$qC)OU820=Ql@R~78sUxEX}B+>EIy$q_Do`{sTLUvKqsR)@q8d*T7S#L~GT^o@WC1 zokG5aHX%?C&{rd!W3$jXT=m2y6X81am%w|%yEa5^Y|FO@8$sH+#efL z^^V(vX+@yk=r%sfkkK_HNvU<#=%RJ;p1J*pOigwvRGMOv_c4sjU+1RKMC!N^0bvrS zlpzD+^}&g~(5ixoG?&&he`n~FVV=29Boe*5zd`0?2-HYL_@FBj(EMi$E`cq$Kv#su zM2rd$@ZhS6O(nd+o)?hBIMxvyeMru4TMT`W1uSY@Q$nnLg*u04oG?QOI2*C-zL->5$3QqW)04Jbsu(z3H z{wc0f04=*o5HNz{hairNwOcGiHqt5=V@g)9P=D1hg@-majirm3fnA(NDZL{5cJcM% zmUR!w%7~vZp=3dFKYtIMdv%|I0g0E7PfO`K{guRla+%RbpmP)Z6@zvd+IP5n3?=|C zq-Fyh?;jMO7)x(0Fn1goQc zwYf9`Q&_USa#W|V#P*@%3JME5CHQym(fKtlab91&lPa|P0<*WPTAjU^T-O$5f~ki5l7v{n79omLLNty;Vu6qT z7wgJL{qNWHclHV6#K+_OCBWe3I}A8?dG(Sdt1q)pK=$R!P{@x37I2B)Le~p5M#%TF zG&a)p&xGH(BBbg$QU_r)se)-HPNQ|D>uUnr?Y=Uns~@Op1V%6s8KzrykvaR2Ga?L!WyD(sV@FE%;uC@#%3&at3muxrsT<`3bcF|EtIXHW(Pw z+|m_D;SDUG9MhrO@PdW;UFVM+SuuIUxQ+!m5lMjldNSvCL>=GBY)Xk?4|X?C?UULK zxEaH*1RC5HOnz;nrMa&wp&9?&p_{zEB$>9bn&{=hihK@fYZT7 zxDWmamxInA7ldsz#MZjq4KTp9e5Dz1``L2 zPaT$&*d-;=U56-&cGxTEuj`Ju4b?hU!?0~*G>-TT)$B``(yQ^B=E^Q@MlgCAS zx^DI8-s`n77qYo26V~VTDlYChsk-velpLP=-_{uppx$LUwmaVETB8>*a@s&nI{=KD zJQ<9FpHD)|+&GE;3-pIa@4=&Y?}Gl=F2Vjhy@&J%5u9SyVVejBXkY*VmTz?Fz8GGH z-_*TT2G3T;fqnsh40>drAMFI{tQqi&>rDEI>dPZ5EdGj7vy2%r~LqO zaytzui;vin6%boEtF*FV&HW4e0C;QS@tTk8cBRHYLh|w^`#zl{@gTAkH#oaF5j{Yb z0jBX>E*8Ac|3Lb;v@&Y+4lYa5b8~w}s8q@A2dBr!nlshjLyWUw6}MHR3kZxX4v#dB zFlzifdw9vcOM8g184^?3VUMYBxnP;?$V*}^H<%P5HUpJyVmat}Gf$pxXce;w7GgH& z_xI^4xWN(AIp_G?b-JGMd&zj{xiH=f^WQ}8zij@S;`<~9!=13lV7U3zs^(0S~ux=OF2JYMqr1|vc8``_bS1D9COm%M+S-b!tK$@81&`3ZachWpDNzu|J5 zFA?|`zzsN7XSAc09jkf1f;`?Rb72J^%V8@86`JVY(7u=OP!a3g&XDdJ-QT;)pHXWT&F%i(Y)r zI@3XpnA3f_04l}zZ?$@Ug^7nb!gEfGo}+PS{vV$<(g*RJ1N7Yav;_sKWiftjk z0`s5noX}~AxUMgMeiJ+;^dPY$GEOn!^DEp?#PuXrK-NW!l{sQf*SXo^{%9S83Kn8e zFZ^ChKXSxzu5z;-<7vs~O2pXJLb7jOjJaGx*!8i;Jb1Gs=5Y-~uqSb>3&%Ey9Blt@ zIjBXF*XY;E^*8zvui;;!QNr_QTT8+-6OmN@8GZ#HEP=HoI&ixXxPy-Ge>B3RYY~uz znZ;4=fPO(F!cS_l(?Ul88J619yZfhf7$4NLMMCD3Ca(P29zVvgx5Q^Hsf8VpS<+_o7`-)I{%LUTw&g8i3^eU*Nba_<3d=k z9hQWWdPOSG9z+BJ9f6(`3_#El1#VGz3~jlzCqR`5Z^g<@Bk1pK$GYfwU!W~bPk?`Y zv;XbIqVg-q>zL#jm6ZwRr}Z`&XN7^p^Ur)j6drzo@Z7w4Q%2_Z?;2DB6qv3HGyR1a zK=WZKgsYCDtaf7( zp*f)yqTwZB|8v9P5`je&=|8oer{nf@58_nXO`7!9uKy z(68P$6Y&9wh0#xl&1H|xx3;((<{_6eV&Xr;@|I12mS{`6n?*(4yIkzFf z+Sw~`EEw@)?+vg26z{G}_`Iap^7(Gc9&6)V?Xfnb1#ZAV0$0&X;ku9DF0y})$ho^M zau``b8=5b0Ud$s(E=1`;JaXc7B*TSi9ZVqY##&6GAmnbiQ9@g5OgG_t&2jEF)gBiU-nO5i(VwIDCXtwe=!>JD zg}8(0f1{tv$T*^ZjecH2eir>=^z%}O|9zDUBz0{q2Bt*xT8XQQ$lk_-1~=G(!Q=ZC z4DOul0$zrYdAI#Ut zPt}o#kt4QYYB?ux6V_doq(O?yRaj$sab&Df>ouToKtW-?mrG!5WMRn0%BX~)XR7zT zIW!@5_eM~-zuUO{k3RnL%ln_CzS3>~or=AdIUwi?meTKgNqMi(0So|51*1dR^)u8D^=;VQM1NXxcW5)_|s|?B9TU|q67RWA!|`Zuim|9 z5Bh%(91Z>iGWZvi!@syZguXjKk`V$Z0D&aJ^9G1grU@e#f<|4X$gl(^KO(eW036vmON9Zh?_- zM|E{I7oKCudA^p=8;_et`h)t`0t3xT4HCHuUvz-5I>%JXXlWTAjqi(zAzd_tmXR}V z*v8+u!F&sz*hX6~bN8X<#j(yY5`&BbXejj2SbVQfB`YgqDsieW8jBo(5$G^v^cLHA zddrP!P*+XgXfuvqEoT4{nSsGD-6IzSv6WIu8Nm`?5JYN2Nmo-)MQ_1FA<(L;87KON zbzN(iB$U@#iUS5lim}6&gemz-iY=p~$vs2jB@JvEMhtD>4{c%GecMrrdSQ%nz#!p- zK`@2R@|84OMv*a$LVsX12Br=gV>mO_hMivOL-hHMk-O zAZu!419g_JP=^wY+s8VX3HQY5Py+0=G1fxyV%HYmUZ_5ld#n>XnLXz-JaH!X#g zXm}xJy9bRuk9&f6-G_=bJNsox44$q&24`T6V}!DsL&TAbxT4}XMn>2&z44nK#${s@YFM$?cC z3FaP9QYzf6pm>G`j6ovBf*GPIAsdTf8DGPWT)OrK&W?&Ur z{-{R6H&UEkq@@b`9Ze+im7mB~t+@`_bLH0dpuA5v z%v?bEc54QSAL}@BT`&v zb_03o&b`*ZH&b?6aNnZ+rKY^_{_te1VBKj z$R#%>@lpmb$3icK3E(#Uh0Vy_-wdNS*?FIS+c74~Xn;g32(BnB5Z+Ms7~c6=(i=&Tl0DqN9{(UA+9uuM0$ zK1;@i3Kr1xZg>Yo^ofs%Nb?x8sGy)=yzSjO`g7aaqF!?sbRD|6eCP+q%3r~)>_z&p z0p#xC4raNARq+O;#EDg_o;IEyDgi|))_Y9|AE4x&s7hy~DxWr`s8dqR5}=_pN++d6 z#UaqpzD9PMMq-Mmal9XAEMM5OB0f_AEM5scR$gX?a~36{do)f1-$+zNFnl(!MNcVACivlXlF*^d!(EVDp!MtuK|!d1MF8c$+eYoLnZ5O ztVCiq7GK&D6Q_>Xke0;a&EAY~yodBK`NkU_*1I1JS#kbgVc8-8Z8--E z$8P};JUK))=SD_;P_THkEr_1KWbxGsI1vnAy6Er+zqQEE)ui`+kXhj*^_3&FN%_)B ztme=kTrMjEG*Wd6r0P-|Q)5Uij=)7GumYY1xfYNM&svzpTfjw_vBkRBJ}!^>NK2)d zReGhb9APZwH3o|HrFFvKjp77mB~Uw6G7_{a%Cs)gsZVjeyfrmdyya57CPCbg!jyI3 zvITU9H5Qo0lx@cI;;+rtMNFA>k%N!1OvUF1Ml6{HgQ7(;pJS0&+-yy)Y1sLV~im9m4^_%L5q243B7x zrIDF%q$tqW*L%!C=ma`|lgrFmp!480_iX);Cpx8fR$A(aA-3HZb^5PYHq75RXg&Zo ze?&<^hAkkx5@J?5Aw4ChrL2Kxl~^=15|LBOF~~qxlp!J3*kEmlX?+(sv%mt+A~l|C zValMD-UY4TB3Ucs3376RvlkU*cJgLDecctvgpg>xkf?6BXBTI3FXu|igRXQd6V0Gl zB78(|g(J5hIIdMhd%qFHzHQWf|m}~elBWC6Ex!}&@&Fqrr3pWeB=j}Ql_szvQHwk#d zxVnkzS}hueIMzY8R^2Q-OEU#oQ;|K`t*-@Z@J?Biy1nL5-E6PlH^X^OKCy?c9YSgw z&I8L8zU>ZO>zg0#3qQw}<4{3|xA25$|1bu?86?6kYa;d!+Gfc3e~Nekh#FPk18hBV zneZxjmvW55J|_1AD->wAGBP|6QIL(ql9E!$;-;hTHMANkP8_U``P%Bk^b)v=&;^e- zf!MGLWEmoEl^b{lAeR7hYid)Y$Wc@!hjb)b69rzAdx9hg6tC9>b3q5F#EChi3i@-r zDK>-mHxsemiuMXBfJ!sF1R)z4W2&9*OFaSmSd2V4mg&EfnY)oGeyNu!I?ppwBZ2Acca%>(MJw3Oan!)sRmv1K|J>lCP+&6mP@ zf4{)!6Mul&U&;*uUsC`afymYa@&9PZUSB`r(Mmwp{!kbjB5JrNz~=TE%=bEh*j z2kbBdie_8E%vJ)Xk_NO0v#viF31)y-02{<4GTBTaJ(eaAYZC(FB!T)tfIHVj&qLro zd`y#d20LLnUE18Y&H6A>S>_~1 zbF@LPG+uG+ z&|vgY9iy=Rv3WCYsB;oNW;gP|1P&i6nB4b<#j`rj0|=2Ll5xOGaKBCoAFMWM)nY;> zBYYDCCcg8|J8%YAJ>vbTGiFa;y=!sVuOmjxPVd|~efIXQT{p2S;Y_f~_ANAmFKin) zPv8W9r~CBVIeVSPaO#y4#lvX$n0pn@Vk2Tk3~v`{`w_j^zQf#k)3IH(r1?koQ+6JS zQG`+5%`O4bK$X@DWl9fec}Tgp1$_oNKv!Y{{e{dvM*LT+Gx;aP8*#!#LOinC6LAH*NgZ$Umw?e3 z867*KFUvoVL2$V1s1#eR8QSRefZd?6;GO*Cffno$$rw_o)H|R{b z13p21uFJ~%NA|5+KBoW7+ecx0@F8&i2#%ZBJ%gEqk$_DPS6+cfVN=fzSz}Ar-5<7b z(LX=0mXRbtXSBCXsWC=?XNtqesINVWF>V21&rUdXi;GpSPf`phH-Dz&=aS z8C>0tB1WG<7wa@?09Db!{_L?uixYd@E1hy?J^ah|7TvM_mFZKuch$mkih#i>QEP9U z!?I=qbZ2@aI6aW}mS}e3rD`XslJavkP&lfBXsW^$w)jd`A9qh(Ib-p6aw(Txz@A+L z`a-)VMjKDKKt=9&OhSm_M!Bvy2~->8#wWQ3Cr&u<85p_qoe!rwUGSfMVhIDdkMDfg ziJ>z)F@QNVWrppkZ9V+wmpg0a@BdDJ0Y>YM?*Ra0pd)@Klh`ARnw!~e>`o*HLaA7@ zlS-rYmgyM}lO`xD3>#z(_Zo<7GAn$`m6k9n(2IA|AcN}Ol?GB1DW;9$y~q%vOSJL9 zI&4uRo>1WfU2+KqGA2(382tPKz5M!v!1?nmVC0PlpFB;3JHF|zw)l*ti}COLeFDAc z_H$;#2eyR(gs$sz2+*}}j|N+LcDc{;+}!H)Mhx?6=*KNbv{g`vRD#*rSEC7tl*KV_ z8f8dU61LP3(AWXMcbD=BRCKw@lH^eyv?fVKZZ1W?Z4I^r+x~uPofF_OFXQtJy-F*g z)wHoSH{+ueP%Pr`$G02K6P7;q9Ju^E$25D}mJM%qgJTd!SAbrGqr0j+-}-==WJfDz z<(ypjJ)AtY=ZMmuJAVYNa7%A69L$1${PXdmF`YKfPfnP20pT{S`Deu66$rO5s)N}% zNE*oKWZv$6NH!CJgOmea61*ZR|MJi^;ojv2%9Ynxg6hLnO;0iA!UfF)x8NX*Co<21 zk~G3uHa?z8(qr$3V@b(HU;ua=U@-b3tl+WN4k7*+-}qTsB3;;V!`jVYHJER)HQ3HD z6@GpJUH};V0t~k8>+>i403rdXy+(r-7rMkN_q(}IKEm_hO*+GN(N+V1;7>Py!`2h| zX`tGf6*8%TSJBQ=9l5a?ixrFouPAr7NWE3axHj{YGpkwSt$K>t-!39Kb-d9}ulCbp z5vfLUCzjQ#!D~ob(7vz^dG;QUe+0e{KLnvaViEEq<9qEI%)4^q2EDFf=FA4`bplIS z^VjTBc0ZzP6qRarR%tYm9)2=^#!nNR6^+5U*MPgz5xP=-e88G$kMc-weYta}MH7u{ zcpDK}(Mt%d7S;iYNwIb@O-|m>zl;c|3ddgJV!?QkWk7eo9lu$U!qP()&kgHgN<@VA zxc~gOZ9&QY0l(V0go&FEV3qY86Z7ebDPt~th4A>~19~eMFykoBdV@Olw5X55sSLAo zWPmi7*U)ZK=Ww}KgbK@YE0O0|oU4(}2`%?FS|TVFr&|+rAp-FSA}nU2*7UUtbuHSy z7;xT1Dsr$2B3(N%_tP>goOhtVjsrKEe)zM|_W=NR4yykt6O;c=jn5`08r14g(N>-)1+Wb%?-Go+xjPUx3C#rebs&WoTBU zefL^%=ODCwUCV>lMDpR3f4Q@lF&#?q(lfNGGwpx|s56t2c zz<(Y$ZCDM?o&&)k#4=+n+z2<_zsvk>r@r~Y{S#|f9BDX77eD}>TcXXWeIGlKVJ>3y#&C8WAFnE96S2?b`dy+8rb|Z*T8;{_|uKb!r99$jAm@T^Miu< zVBDD{(JfZOb85nSaf}YHU_eqlE<{McO4|*&$U2_&6*TS`aO9NG=6_YjQV zzjn|9Ufl)11$RI4@|I|h_;TRNY32hvW7_|7u*+giN2CXS@N&0qAdQ~?#g7ee@WF$?4Bt9*n0;z%z$=4!V>F__E4u*EKN3ke zmAh20mO4ksLYN3?fL~UWC?AmVbdQK?-k%DxxYkFxXqDxjK5L=~+*ec&iKuS9c-mHQ ziaX3tO{_(X2!m@YM~G|FkpOH*VaLkHP2Xj!5I=>tW-1~RqO89G! z4Tl{#Ae#Rl;Q)6)h`+Gy{|g-0@1DE2#$h%5z5B+)*iSVhzHue}jsnaQUMfX?rn{<< zw6rkGC7|A&Emyd#amTQ#h}Vn&B1O$AqhGM-#Ykckz-9~Z{Ko=&!84(8=dSJEK;x^_ zBj8U!OW(6zg>NP&@7_93xU*8QeF)wDPi>!V|Nmh7FrQe19JbGD!~+^)qef6kW~H}A zDGT<{Fe($#aShn8#xhP7Uhcalil+jd%e~ynH5Rn^R>T*LFVS*FKTKQfXCVti_#s$a zdWmbC9~h389(~al;9}c7IuVpSp7Hl1xCU&ZJ#EOTD(`>yOV`|5;0g-Jd+1B`9Y_WN zjq~1Evk$I^yC!DMyZu2=T_A?P7g~#I0)Gs?4LUYL*Tyd)S|9e81Mfk7Z1 z3q1rRP(&QG4T0eu`C0q#?~4cARd{Rau!m9~4&@B(38d&JHpwv>@-ZHdUE$pfKh5XF#cn@|5#ZyicZlmR|=aJ_gAp8TcohIsX39oex3_xaRIKWS0 z-4aDtUTAlu0!J2uju`-aN&bQVK*Os@mp^(!gBh!o5?}z7&YOOWjnjmw+iaFT1&Kic zK+ycyZVCWs^UCi=@AwFSd#h)xf zPeV4Jz$<=K2=*R~8fU35?@kA5TB$54#c-`pVhGTdwStz3)VT_+_ztMW|#0Ecr?|=4FT1PWT=-VH@0WBa0WPvUi zq1zxHB)~hijsGmE{_sJUP}2$En*b7b?W&|4a%eXDG2)+iD&6el8LV-ZwKHiLO=MPr zLl9w487ZI8HHkbGttt=nE_XMU>nw=~3$(+LIJ)wpI08uVpjC=D5+_INMho5#maJ_B z6Bupxe*(ZZIM4PO*nfN2*s-I{TYCI{cuMY`cfcGv)OHkJFQ4$$M?-gm)pi{P{{hs6 zc3F?D1IGh425y<1H>4!F54;4Y%@{iW^G}Mh4Ftd2@EG?C^6MC!l}Y*QVwqq-1qZnR zJ~%+DF(M_zljA*qtT!_NX{H01j*A!nT1NK;u^m!YUD{L$M*|v+eg~Oicki(WKk3>3 zqlLTwfTvie#n1hg)8W9UL(15#Q_zms05-gf*!zyo2;t+*L&F&EP!+r(^!WKC8 z%w&*}%6r4+BjX-`kMjap&_61B)%qS8AU(})f6qf3@+P?-%^krbW2CHJp?1mgApQ$c zuL`Xbn?}Iz%@TnAu8$UO*P0eE^V<5D2~LAex0pFwpQk+|CES zu@E4f5x-nq_{LSo92AA-&>@>fh9_}WBb652AWm~mD^b!ej5D66?L;~W?knwwWo^q` z>Gy0^h;0C@YdzhpZVScv=vFxCsW2oBG`x=1C<$VXSYVKJ8j5H|^b z36kK8CokaHv$0W_SH#nuiZUzEyzaEC16MTjJt1)f&Ft2K@e6ae!ny7At?_OHfq;6y zMjWHFLR%a>*L<2{@ePWszb-D3A=Qdvd>h+iwkJzEb{xEc3+a5OdSuT*4fSOJzBg%* zS{1POe9u9vXMBjqIc!@8Z#17EzG9$R>gB;}XlK1Vx`Et6fPEGTtE5!Ohm3A$z*LRl z?C}gVlifDv^>#u3BZGXLyO^YM6xt8hrxE8a%w(>@bjchW{y|W?oQDSxDct^eojXMh=ji^`}j)!Y(w%YDnt$^TwE%aQfyauUiIRv4HNMe_mX4X!%>P zXH0ZdyD=cnZ|YlzK___U+SFfgJPhjCryTA;if<;36?z~LgPE*89u?pf~7ZEBI#ykPVr?c>0@N;qU!&>2n!&bCW(} zD~4vEUIZd;ygzN+R**$cT>#=fe&2SbAAJ7LakxW}Pjj2Up|_KJ3XN#r$UG=tg-R;P z#s-&28HIDX%;Im*xw6R_Oeb+EH zJ8wmfqF3+JXOUr#?SEiAFgZ8`WYZHLcAFX5%Vvx#`q>UP$va0du{YRxNN#n(H3oba zItIhqe7E^eCPos0^IO_R3qTOEWN`LX9JXxJF2-gFTuYdj-A3uF-X)HJofF-_iep4~X zgC`F@IAi-u{;2V@48g0%FxEH!z-*AXB0BlMKqnF>@dZXV9?dAOV3LVGZl}-)ditSd zEDNGKdXl_!s2!9L%TBvicM0f2u zI4x$$xy%7@E8O3&*9AR@139)T5pJen`ryu;2Tw1O|N0(U+=M>?ojSOGCkU<8@UPMp zvnJ1!-;&C}C_2ZE3)WFK4g0I@8lR8s8D}#`Q}{R=`H9i^b_})2rm3mn^WiQeHx{v9 zHoq$I!+GyiFp`T>7h2D&mC;x%3UU#P4y~7yyE3{lRgjFpH8>H;D?U(1hk}H}1Re*f zyn#;QmzZGn2&X|}^*cWSgoo3i5epu{&t8d|EZMUHfTgvA zL)Mbs0ngLf8&nkkJF+g(s^S=ct56Y%Z9kzY1#dK=xd`=z9!Gjz2eJ`}9JNOM0s>yL)D*qA`K#ZktA?M-`8z>GU}E2G9YwB>-9eA1zE{ zom8Wj3=Vi@TuE~K4#=#}-msq@S_sCK#)cAoZ|%u`3D-z`5YHLS5(y`*qG+sTt*MPf zZO~kmOd%B>#DIjjggAV>jdY#0=f~?l{&*c{!GC}JG2Z{r4V)Y0B*83_g>-8k<}d3` z_D`73PbKkqH#4hb(P9a-XPs#|kH3!*0%a!uB+*o|?!0&B-koLL`{m_vZ`Rb@xRH~S zC70{srW_T~2gUWbpWhQa3uA{@(dZT^W{#UI4^1%YUr#|H-pHb|VH z&qT+?l^htfie2F#8>9aE96a~){aP|SPeX%X0I{-7+AAW%f69%TbU%m72 zj4c`QwErOh(mLU5I=ZB(AJn+d{^*Ur_Z-srh$w=2JkhjqTcbaL9K83R*^qhFImlW9g zz>+9kqzjSyYpn~D+$8!$d%urhUJH0q;RsgR&AvwyC&HSUlb6#VJhB3K`p0&DK|wBy z5f$XRZXX9~Dx%^tjwQ^V36}-CxL23;2D|Olvh7WYi>n(A#zjZR&H9QyC8$mKg{U{d zdAs7Y-I&_%*ik8vZpn^}1x!g7&;j1@)%!0gi4b^ZO!HstU+hN8fGZRMvg{BC6QiGF z6ND2%``N4pZ@jBu0ssrwTHxF8>bci|`(4}Xix;ySkz-@48p$wYnYGqw&k?uK1t$-} z!3{rtLC*&%R>@*YjAuzUi}9?kFUGStwQHPklo#k9%m*gmb4ek5r3rjlsLK>%a>TmY z#<%E=ihjc_@cWW5GyL#VA(#bV&VLVjIig(?Y?Bh%N~W9j9J~M`q8UpA_^Ktc1^%Z{ z81AKv@w_SG*`3^r`7cacjw7&BgqY}mk1W$VQvU+to~5%b@ZKu{$@?B~+?9avJ|z*_ zr2iTDr(!_A6%p=k*-L2f=J1g;bM2xOe6v}t3sA-VuZZychnDC+(j~K-zv7qk`*7b{ zprVYpZuI|Q>^lIWI-ZB$?tAZ!&K>Qj0v<&Lr5wkBRI!T%Q4x@4!;TGXSg^zrHCF73 zyl`N?Ci|!%)WiIw9LIXIs3vl zoRO178p%u)g$|>As0+A*^7#(h0_|Q92IOBrw{EM)ureGlMuATt6^GQ^_8rerL-ZD9 zVooLkt8Y#x{z&GmJe`i;h}*&0GfzAPqn2sBIiaE%eYJr-dt%um^zan0MgLwIx$amw z?gu>E0d%|%q#r+iI(avh4fz5$5?aI2uY9QF0HYxL>%8URLZ(L|eZO$w01-Ji8O;YH zhEJc|Zy`2-!zb^9(dbvujA!T195;GEzry_s_B?o9Ry7ZWkn?19k0f!JH%n443rhiW zhdZwdWi(g>9RBVr>;!h?_-Sb4PrstAp#8JILG($Kgsz}#C>}1?{=!SNzrrQ(9u6d8 z&^a8yXfaxj79BzDApqr|J&aisw_`{27Gd8c*|Rtp_rac?18?YoJdCvK0@y=8Pg}b0 z+wngG+1n?;i%SFC;hl@FeKY?w@F>Gx`#QQ-wUy9GVgP>#({T}GL62wBOM{lU_5j{; z9-{3B7iSNdn>u5$_TaHs&u+6Ary zt1lZ+Pjnyc0T8I!=j*iy-NS8+*FBUvV7|@BDEi8k^sQxY`gR7#*pq`d$S9^2p^fMm zXalm~w`do-iTa~v09*u{K@-SN<(Hxf*x5ZroxoryuX+l>L+~A#4jyS=YP--nV1R8P z(UQuGzGVBQqqiIm(f)b>1_AykXu0|GcEQh%!(%atjz6hcE*!E$&MywPC!0qY@@Nf9 zl5v!?73FJ+kCm0=-}!#gd-SpV-q82J4obkmN%tdB*4ifkwF1L?KpZ}?Y&5#u86AE_ zU&Rq*DrqBGuh%i!gp9n>1SCYFbT2=iI2jqk&wes({>nq&jlGJ_{*C@YTMxi9o96=_ zIH2!g1Ta4ygNo3XgAi^e8#zKiFne12H$1346OB%5*Py?|K4G0+PRGzwm^;ZHaqPp1 zSY^;x&~R~&zZ~wI_7)zWb#N6_pmp!is|)BnP$S@}?Z^&-&TRErbo;^mJK%J+3;P_k zK$YkS@iI+-KZpUTrCL-qPN+M=0B)AxOMFEsk~7K3(ae4lg`-}ECs*y8SN`;0a2h$z z$cNiXs{se#*hd?CSLgEPS1y%;)GfP{&~He)i0ltWJ0zp9p5UCv*fzZwdlgRWS*f5m z^rsY$7+;QdSG`6%LH08|*>@jSKe*5Z0aw zlmaek5278QtqpVo{c$k#964j3_74i{{)QFoHB|SAKPlKNa3Wl&sqC0DtY(s;Km+qk6^D@M(gRhw1OWD(~!c%5|#`Q zafR&ljl18XH(UMyf4l%-|B^+R7OY4CO`n(iv3|)I^z7)~6gKR0AAv98yRKn+E`p9z z0b$pwFbp_(?MUK{+M{Q89;3S_MvsCQiuNomhl8fG<52__^BoX$4Y)5DS@7eki}$Z_ zL$y^^F9h1tbdR_>m^SG%HhnLKP@~R3O=bmd4n)74M(@yv1K`~Hsr!~^e}GNUd)({6 ze{+MXmj3t(+`awlcMH!lv?h^`n@#PV9FrJM&XDtt1sVrx=#GLvserfFpa;Nf?X8pO zS5%E2z;o4e!8O1D6*u?PWi0@QPXCF1Kmi*h<>;)S=l#&!`t&0d`w(w6*-9(%u2B)z z3F}AMr!S}s^nU&x^f-lvJ%e!4AGoaps5PFw+GB-2f9Vq28!N|pl!*iWYuLFQ(QZdO z)}0s=u@5!`IUpOnL3U^jx`_S|VyAu#kj#3AL(fyc^LKMxpQ8kBS8X!Zf^uP4E% z127Ecg09sa*n{8}`USSoo<+Pc*3)$l>G;U;{7fbhsc@p89}%U3n_Yf-?zfls1JLN< zQ=kBz+^$`B!0laC-MQ^AK?`)`4?!2PZWmx4{GeRuFO~&^VkL3V)KOcIq5sCR@fS#OaCEVn9=&xVVjgyCF zeRuiLjt{6DY}>kd_W|(p5%d#;Zyxw~FWkIkTU9p@c@#!yFD^fx%7z;ID9U5F=%c8A z=kTn19jv@MtE~LMo;9~X5P&XuwHuz^qvBs6y$+f;0D}Mb_6X# z`?0>KLa+{etbSSJzYDP}EQIwFDCRzb|7OJLQborXUbs+kVfF0w&;sp5@2{dN^a!*C zW}gp230sZct^4!Ch2O!QY6bfe`Jg}13y=i7us%gWPFr0y)?k|@SbtrF+PR`_N|f}C zQ#DnmP$#xxL?(&^7m_BQ{Ou@;gl-4WigH+Z^f%sa>M-O0rxcZb)S<%XsF7s-BO2pi z|FHtgiexVi)PJZXb~J;-fi!ug*UnK%gExf(!>vGnKf%7_*VEvqU7J^7+si@MAH6yT zO2-#{3)xoS*K6nr=wE#hz1y+sVrePxTo3Hg!(Y$OT{h-tv{Cd|LO<+9PvB2Ii;9Hw zq#Qdp8{K=eWi`A~T~t2*)Qqd;+;2F1`$K^m?2@dnp6|3CNWfz{S7TdRi0MF_BjEVQ z94J{*`~V9Aa1*rauy5G&``>8D9q5V*b$oa2YyN}wQ}xf_gSHEs4VUexUL)94G#I`jpIbcryehO+zR?n^GB_-PGliT{Nr!h00zev1Q z<0bvbBq3;(9V5hwj!I$>P7LpWR=oQUm4d@_ras$#?Er7B z2%$MpKKp+9oRTNMKfi*rmX05$mXv(=-J~PvMK$Ufull z6c}TjUh*%V-0}h7%NF3r+Ual-cnXxzMf>!^4zT$$bfZ2x3CFZV7cDSF74gvxB~qdD!b{`| zM^aVF1_aRQ$k7H!=@~ImwAh52Ja}<}YtFU)22N?0G#18;OYPem92hw6G`M%>07yq$ z;mxIGf8IEF4ow4-;gJoe9>K`W$&<1N=5W^i(q^R}9N(|x8hXC`^_t5NUf93nA#f=^ zczQ8 zfpPS8Fy#7Xv`m}}b&uIIxQ}*>t4K-aORE0TlE=1yV`cslvZT$PL1`!v%(V|%vgGj8 zX~Fg&w)_JE;6LcCJqM$qS&Nq21`YnM#q4j&+ZUoxaM;lSXQ_0Jm`O(sxQ^T)#+ja} z;~<0^zTuiMWkXLO^(QfzgOp=&5-bsY7S|E!{(FJ`0>AA92i8EzdRx#Mbb~vbbG`BW zKq^*2Z@O7f*-$RyIfc^Cm+rXoAstkNV>V<;^58dAVh>Oj>g?XL-~;Fn1NaM;XyCH^ z2}9PPb>N!=!*dxO*i`-+y$6=BVUqSSZ1i2iX0#hwo~^jPt}nZB=*S=~cnm6c?bCh+ z6VNOq#$El82fKpqCuI1VF>?VjWkW}WlE^{Mu0Z)H)q9uAyGIW%YIcQSk3TmKWq_>@ zA7dx%#M%S+?$I4E6Ac&X?ZWgL8qxE1lH)*2saDa)4SKQ;QYS~O6vI(_-#uP{yIZ<- z>czh=I+ZEFcu;cf&lr>r)<1oUDj{&4`G@O@j9XVvZ&?kxqm93PGZ0Z*XpHq_t)!f+ z^3%DNYKq3sUgpcmC3x^;I1k00VZ)UT6;Kh*u0KQr4sB}ATRM?}2^;5#(K047;dgwT* zyyTEoGIBfOcO3DM5&@FN`+?2x2TooL7Qm+ufIWQCf4IUOjYc_e>DyP8@1P~@apJJH z5@&zUfFp`3QaCkAYT6APS zn*m$lIp-3d50zjc8ipRA`#4Fkg)VfA)A5*W;ZjJ(#@iW>2|3HkM_*W(le1eOzPC+i zX(M3%=Zo?Ipz)!X<6i@uANK+)UOz*BL*TX+Ep2n=z^?6wulDYR{?qGFBQq~Jb3 zrLC5sH$eIroIrjs4tiULfX>%01_fb7T#uRtTA;zGGe{HKnWlTlR!DZ>*w{sA2b)o2 z;OO1ZQ68=#hAfd%eXKyqC>L}F8&U9>xr@Qn@~Xo8f3(=sUj+ZMg&H_I%6pYXC(2iZyHY z!=AnGfNx+5PLuusPFT+-qiw(a2GYJbNw!E-`j4f-q-A; zK9}kttM@fLd7`EE@(=e_`?5O$>Wg|phjNFvA5p)@I8bYhE%0}?Nj%B~8<#G{4%mhL z*k#rzbO&x;R?v3Le*HQW{{{0+Dx1rUK|gVufjJ?MkR;w1bdo>{%Xe4Jsmi{GX| zT^o1OYQ-EAkNr9!W)oj}!1@#p)wq`qc6iKlQF1BZo`H*!LvDY9$66hfaX9lp6G6ca zAe&OUITKxB#JS0Xd&G}mtcV_AZ^o)vPDuUip->&q*IsGQr9)n^UjcOJM;t1DLTAds zog=%Sp}mTIPG~P^4liZ{Tl7zcHWZyjjlpjq5s&^_?EAuD@M7&$IC&xA+X9ctA#O2= zZEO5B9ux8ef>pBEMfhtJf~m^cLnsfmb-``&FW{^~iv<>Il7~6;Oj^*T<$4fI#%I&x z$LJ+cumcXw!`WZ2ag8>F9zTvQ&^gaT;*Iq;l+^OICmW_QMLfmgm`}oad*Ku*ESx;^ z7P2JjnL@*f>mV-~%Z&Z$2Eb;HI|1f^s`~)_fyeC;deOJv%A0?$Kb+*&?I?S_q_>3y zj=R&~viJY|^B(pGRp-y5PSedp$b-_SkFSop25CisZmi2Z8=y4S|kzdA_#VnDc3s@Cg}yczJPBgt+= zq!8A|SraxFwe1Wh&z+f`n!FiAl!i}e_ZC%x9XK`fhH(~wVCB4JDQbUzb!t&q#gQZE zRn-$HkvsCJ6B;6}*D=`k4$xIk4Sk+OS`ubUAu+~0IZ9!=)B4Rz^TD#+*Dk-FF{TuI z;1+V;cSZhHw6ZMko!rU$jhg4wai`x*t>H56vj9iG6p{^-khR?5HfmiMq-C1Op%rvKKM6jFKHYW{i9Fx(a;M zR>CmMNn5z7su|dpfO;cxggG-EkIM@>E;!D#heX?=fTMpyg(Dr68cE?+6f*Kf=_j2I zK;-7+)bww@oeVm+Eh?EZ3C~jjXnyG@b)C0DD*zJ@Z=DISUyh=4 zu;7O+j6E@NHB=LX*|!f$DV;L~EGvJVvl_>jjkL#L5I0{tJq}O6yP{A>G)IVQ98d%H zJ8lV`Q>4Bur;u<;HO{pBf`GlRhSvz^X{&{8leU2Ut}A-60GQ+H>cFe@&%l|{H__~_ zAUDN6u4C&~i@GE$Gr*0aGW6THgC~AjHhRR0(AHr6v3ciKHS}#7Hmh0Fc|BUJsmY`8 zxcQsT!8C*pRfpG}ipA-;H|p7_ywU4_M{e5G9}d{GF&(05+rZRKhxeTXQxVSc@Z5O| zSl)rt))alScv$h4ly48Ok7+%7QM-|J&FT@&x%`dhFVZG$%+MxD!JHKOHqQ`6EdB4} z*u#g1!;yy%^@G*NUURz-?>j*oe9axHYKLbW%g5uEFDN`ctn1m?X&Vp3wq87|-AHlG z^8s5*&zHuYRuM`ALoc}<@1$}h$DG*96yd~x=Pz%AzJRS@Jw*Q`FM7CW-Tk?5D__0o zK6*dMhQZoj(8dF!ueAU5Y9iYWt(`C);3eKr?JbhyGm105S8HaaN%6+l3 zB~f1*%Jw|&58l4MdvG{VqJ%xHC;Aikkt}5Mqr2!a@Z1a^M3zP-6-+P4a0`Fh7-^#(k#t_T`V`jXq24(0eD(XJAny%IA9&w)Z*`bg{Itpnr zS%9WeBwMEBDo5U1*d+)YRNf@{Vt3=7W??I}Kp*fBZ3UY~jT(hsqN=|?d_l6m0srL# z41a}Ifm|>a0DJsn5L*6vHu~pV@a)k)?5lrX-_@^Idq^Vj*twDX8T+Y*{*Gj!nv_By z+sz#HK|VD+>?<{)l1PZsX6K-+PoLfb4z&YYpJ%511GXLf`1r+J=&wCK`vRIU?-N`C zHlS{(|F zn0-RrbaC|o9Y?!iFsLBAsO0hmuY zcIU3>U;5&H^`^0aSg2Y^%Y40X2%-@}5GMtE85Na1z2)?lv(e9BFIZ{$z3U?c66Q}_ z3)oJH3%d*pJ_}}m(-3vPd;$2N6KKcsz_mm-^K_N0Kl?y`-j6+2MPB^m{qz%fd*K4I zsi59LRwq7|m{~I>0^W&Q*5?e`=lh z8`@b+#%>r>aa=m zm7Nn9C^2Rk%T>aeNZ5pBb7&9LfGe-gWH*&oxe%sNBjktPz;RFDc=}$7(4N3IA42&) zCi2Hh*7AQ~{`LbkePiXOC~H;{PT@DX4HUj#-ye*BL*_^DWKu~vxl0%ujDN!jzq|&Y zv@1DSi$2E3a6idGN{8Mh;7eOmI)^~95q=H)CSOM3hic%I{^7d#l>T9XKDoVGbJ%ck}(|dNVm4k?tuIw$`at zaCgbGk_q&jM6TuN_3K9iZ*;#!&(!#U55m3P_}(7$Ub!+%e9eMB=MQy)yC;xC7RdpN zTmriPAs{}rXA5*6cw;(Zy9e>TGV)YK?Jc~dLB2RSNWdoa47kRprpA-sqf1KI;KJ1S zxYWXuXX}am2t4=rALl!&OwV`ZTGl$>5i;%IS~iv!>Vz@oSaQDjgWXhvS?DqH2Ojtr z{F#-7RKE$KKN(?M;1)bCV-%_IfND(_U1!tN~h5%7!5$h*OzV%2(;96B!4 zK3Rwd6b~02GBWOPGAL#fjmDi#{E5hflfd2FR616qp7U<)9q7YJ3I$n*;6A62xd2D| zYNfcP8~ich#*GO#ILVD0h4_DlsllB^dPW`#k%uh=5Bl&{$QRr$EEH_qtU0yut5}jX zHco8w0=0#!>?2cKmNpdNT#S(oV%;_yDZu%86n@Oqf0H+2>-F;wYWex#ulV@~v`>1U zDPfu)#O{(MHTI&3!#t3{?v(@?rX!XkPEx|-i3yUjvnI|`L&_36g0WmD;@+!V4&jt9 z_&9d%+S#@2RP^tUjO^FgzZ<~?zr-A({{2xMUU^d2nmBh-z574{DQ7M6Dv@(6WaI$g zM4aX29LJjQN=~}Pyz*JZsaG91bcj0i`!@U4%&;#(hm#kW5Gif?^f7oXC9_7(cizC!=`SLi>l$9L1Q z$8s(Z+``=~LhjDAu#;6MmdU!O9>uqwiAbxY zHD;}gxkctoQ1m-ec$==C(%syGpWhF>fg8>Pyf5!L_x&DrGw=aT&`orwI)k12=GwJ4 z)dhMUM4Ng}^|Z>wM&yk9A}q6t-u*H1A#!X6)i_aXfj$>+omtj_O*3v`T`wS?N@ACOZmm2 z6rV%+^*GF!huXOCGCOh#OEhNKve;~@yjZB5?dzy#RQ%%2=b+x0zky&G=CuSRV7?y$ zPoUnq6$}Q`KoJbm&UE~@L`3wEciZAX%mB0r5NTwBZT zP+fdVABprE8Ri=gLPrX~NhAF6wdw2SL+}ZGDXfc6=u4pq{WrDgD;!0;Uc;JUo0Bu1 z2hACq$-JHDyW`E}cfm)?yJm~*uMv3L+*#xK zUFxFG&$zQSJej*VTC?u99N{Tccu5@d$9+uCmH^udYX8!!~)37zfFmQV^FDOc2=uyDHF|%3J6zkpI1Zx}Gce z6a1#?FOe%cezbkj#;;Mn+zjw)ajv;Wd=h~Z8DjX^8h-JZy5ONTlA)zIuJfGh=a&uF z2qMHB%T@44qoDkr;9HsAB7oXDiG{Ju( z()T022=|w^Li3KftU2~cWc+;&vy6_xSAAVyBuYQ_ zWHXloDYQz;m|aRu%Ic8Oy?5`f*-LjFo>RPYA^e=urhB^{ZM!CdNsVXDm^XRm4A_CT z8v*CSBeY$zhsap}gNXr9l4P$K7}uqD_lyo%Nx*F3&f+~^~88b!QSS0v5Zk(xZ@ZXE@QX?H8W3fo^bt1l-UWOR|z7c){>c90q(3WvK zWZ^Dl+<{Ci?RAhL(To}PGFO6uQt#)4U$imV z^nS~hX>bTPhMUy)4d?g8R`aBbWU?pkUXe-{PU3!V!RCRCwkSHMQ=~;sA^4>F{ZZss z{86OPZ_yvwl6ofY0E^ks@54mM^UMs4sPs-pSX5v?R*3F~$QhgxyiC4*29IfU zEkC2K*U$J#)uwi8@H3iv{fr-xr?H)ie#T!KQ5T=uX~b9jOypPmOypPmO!Ke!ndV>d zGtpo1Gtpo1GcjNBGco_u&(KzA>?8OYqF+oVu*j6k#8pW=tarJOWLV$PlPgqueeP{`MVB$sOiBT`bkFG0n|cklxNFBwN#sW2EW{jvbEfCd zD-J?;ra3E-(Lz+^Y%xbpR1wa;Q+spH723w^20oy)#(oBi_PT@GYgdE44yN>+;^4Pq)NZssG%p?;|^*cU76baaqhsFKXS&$6aDdI zoO5+H{GA-|QOXAhaUJI(+S>t2ubV#Jk&0cYR)|L9oE(ZL6jPSdPIR$}>IR!^^3esOaKGm~ilN^EKQ$0%-^-N~MkH54V z;lw!Rr~LSl{!x5a1AaKA-@PtArQf{{{y&s{N?m>^{ggWV2>kc_3jaM#@Zad=BiadV zMaU88Iv~%ulmjM{3_B@{dx*IUaqcg{HbPDTBiqe^3z(;UvJmG1Y)i(FU#$N><`=Z$ zo)6vqCgd0E(HDJ!0VL>o?G(e5H+tTHx0)_MvKH`0^~pT)>;c>Ux9p^vSW@9=?qchL zqlxR4IBcZh1P**%6-=>}tL%DZsO+6-NbYZlB*Qe`YHt3TxfipuFRobd1+eIKB~BGO zYFEK)Tl2OrUAlexqSA+VE8o1SEFD}b_&Z6O#Dd!8ARUMGcBnocm!ye2HIBEy{K#1s zYXu3&f2d)~VVsA8O!2-iPHU z@TrWq5XRKm)<}MsQ9H)DUPcW$pM%uf5w=`C_hMGg#gz-bAT5wr;`E>s98g+!H1+eZ zBu$iCcgoL5{k&t=j-7<FDEJ!aA|OC zcKgS*8pYNDj{J7NOCs6W6JI%hWcB z-4Z(F(hOh&YqoTnlwHfM@$>3J%?HIHAYadY$g{J3HP z4uG8mtKPDBi#Yf-@)YfOGqvL>`q-Q5A&I>iYZo&d6%q|3jad{+nPMO`<|wF~x9HYj zOKP28a2)v8f|cjDY$0}lO=HXA+B&wGj@^{H{jzr9%nkj*?cmmgb7Is&fAkNSxcSuX zzL1_RSn(r#Z`xK}yPNtIyPI0KzpRUyRZV}fWU+h&CIml4x=Z^FTlP7>aslbBU}NyT zLAv$!cZNad+ff^tWNK3kgKcURp1URqI!`Ri#HOaywh`%hia$lf52g|T zsD&@^GxaO{Os&IDJ4%0AU3^M^+E@6W@fH4Oe1-pSzQX@EHTd)ynP6)qCaoDDn$Lne z$%B&8;9_mwx=p*b@nc%0w`-X*tjxHYMG;I%K=ZqN8)kErxwNY?!hNGkfGlW14drg>m3 z7|y~}Ekq~vW5-#Daq=eG)+z)1iWnzvqH*%7x_xHcEpVUtnm%I*^HVJaF6cYBDmll< z9hL0&Xcs!!w*pAOyNae@0B8x3b~}p}p}u)_`pl{*A8QS9;}aTxE~}H5E)wErwwlg! z%MAIXjN-4T6MvSA@wO+$Ur~ck^JYw@$HUVi+DoCrSQN{>(Juda(v z>94MhFY>>(UjF@vTuk{9`Cs=H{@0n{zY*!{~Tphd&TA{so>a;zp{pt5O1+bJz$cWjQC+oA28gcig6 zn+3I<5*M{`LCj?S`&ph1+BJ^1cek~1j*reAKiSQ7hQEKuh!|xfb8AIZc=qrjCzC$e z;6H+~QG|tS$f6oqi*i|5`FLTwt4HAZCMmm~I)b*S!y5hi4?mQDOZR9Ck%fvLpyVR1 zFezn(O*tEzl97{KaqL{_Z-y`6)U|=>57F~;hk-9lCEtO|xx?so9lCOXhEiO!qV(k| zAhtB~Q{9V7kF;ukQ|LA(oetmnA zJM3Y)=Ta23pHl5*=O}^R4Pg)vhr~(c*bu72?7Tzm6zmu88KWjlOxy|Bi(nJFwd?n= zP_G%Ir;P2f;qz~sf&cECVW2Ga^0tXNPq(1&cNe3Jz-96X5db=@Ujzuq(o#U5*9kfLKJxTT#Gg*rvi6BK^vVR^U%KDqIa>|>{<`?oMi11*r#5<^Hon;{ z_AtgT2U=5nvmOMFXV^2;hn3gh(|P$|U3@w(i+jMxT_*Go)l1)x$fY(urGNM<^bgnI z(|P|Yx0ioL$2k^iLY)-Y;*Ew`I0h2iyJ47NuO|MZho9;LW~^-=(;+%BRMEn6(dc8j zVDhF;5sA$cT60(0#4H2bJ7pfs8{5=vXba^S$76fC_ue;Te6x`Loy2vbC_FEjG0hG_ zcQXkNR_|P)RhbjailJmGLnq?IZmEYQa$YJPdi#&;pESC>1ysPBi>lB{U`&Pfd-w&W z?uNf;o9gE!VeZ#GqI3TxlX=jL2|C2_Qg?DGfO&h#hyS?sQ_=wJhmkeuR`aVkC0V}ELBgC=)RE|!(^)v}^lS)8V z$)XHhq-3r zwus+6$SzDH?-S#YlGpnI{g>c-hMXBX`krac){fPGvV=~IJc{)U0kR&mtLwp zH%c5u{342fsn%RtQ5T=uX@zK~MYZ_3TrWRKnUh$6o=R_?0PmXdADKnwLO4JN zcoHw2ga=qE<4p#5&O&e%ZCM0{Aus+uIy@dt2J=a~;yyb&iR2H%dfjmP42-c?xdD|q zP+H>q%NG53ei8Zy_%3?*co7J~B<_KRXgq2KlF=S;g3&)G!E?$a#-5x*YVK|Y+$|W+ zfiB9>H7&kaHqXHdr{NB=>(P~DP0QY}WI&b=h4rjU6+idSx(=Ucp9u?D>?D-1dBxK0 z;8ZE9B+D^^{fX;(_KfdgOLsGScgDhju2a#LY>T;h4rav`H7x;=y1sG|X;bp8u!5(3 z2A^EZ?*B7si8KHlN>Rf0r7Jd*%*`nGwkNwF-K~LfTZeF`tZ+j?(IofvHf$Cm%?RsE zl5cT`vae~~p{uYE22PRgpoCK3Aa+O8i#y^P!x=9cbK zdv|jqnI6I&H8ZrX(x0eDgemfINm$i_u3Go&S^a+or%02ivJ{*m9YhI+w#6L$49&rx znfMiZvdSiN;o~ga8B5Z5G|ey$TNj%##Q^6R^gvO2aW#dO<`6fyUIG_M)kR$ussI<~ zuUa*q58C?p_T5J$!&*FR=Hfa&mUE&$=0)B1ITu^fzPVBR(qc=d*nFye&=bV&p&`@!j+;UI`FGv+vE49nSlBh~ zTa$$=i>W~9rmwiJLW_xrypZ;Vc2R}E$yO?6l3Nlno8&%~_2xb`xm%@)-*I4k4qIlL zG2CRCBXK!gGZC=s-48#l3V3S+W2&Wd3)O>5Q|z*w@dKt9~_>SgTUDwjjAULL7@c^v)xG5R2@kUFrvE@$w2`Q&T=;^ zcNe*WhQDyQ5rgV`VLq+uGX5<<@q%FV=PXVzNJm z@NW*tQOpvh1a}N<4Q-wf7#baY0L*;~BY#7F=-%X#ZG&^lX2moNOlTG#90U?Lt1kh( zP4y$QHMye~fi;818~S4M>|W?gCp<2xd?M{j_jn7|%G}P~-Ng>~ha6cUyF#Lq!wHO) zt;F5YHRw(x>7&pe8*5uDce#tJvz1)otia#gz|O65;X1K*^&N`pJ!M1R@22{q@F&{YhhUiCizwe>fA-M+d|>qN zuuK#ClZ>s@idEQJyURR?O1Kd$~?kF6`V6E!yrWPtRM)-qmYb6#7kjh3uII6~0ry8@7Cw7|TpE z-ZL%zr1!T{1@#4=>)#VB{mdBl1k?REtJ(ehLfm&R({*}(o^a|LE*=7cdBxna5^q00 zPxmIiv(W~)zWOE9G;18_-!3$`Er9WTxN~l9J}$n__DYv^=vT7)7df~Db%_cLXiwV` z_Vm7GENI3;+oDZLYo0BL`*MYK+JLo280({{9!CMyQXZJ|?A8jindY48DtcuO+BNz5f zAZ>eDaP;I3?Y9m7b~kSSDdyll-6m|*xI;>h?EHmW25UR(8)r9H7Z8T(v`w28p7e>r z74{$0+L8?ZuHClD7G=<*PTO#Q?On_Nqiv1cu#-n@Slk0eDg(1`jAf47b;T`v>t$}# zG}t3-j;`4-t?ewzTqo|~Hr_8S)lprn12+?%8Fdrq3N!K!q#a?D)a&D^TPB_?JPMfX zp!WCsFM42flv)i!9OiyAdhMoR2WqxZ3tOuf%;Z5%P*6?~0D&Qcm$U5h5q&r4_f(6! ztmjR|JawzRx7v)QJdr)jGxR($SZ00_%$P4Hm6&Xd7VO!d)YjsjV2+}q2clol-`^}G zyQ9IWnqAWehHY9q`kT4jhMZ;qvvtCJ>O5h;v|$JJhQ1>RpM!;G0knPNJ=A8r!OmL{ zxS6E>J;G*^nmxkedsruF?C-~z)Et-6L6=DN&kekMWIkedSVvDkKW{fbzXomkTAyv- z>C|@MQuEY)RC0D7ex!?!n;WtEt0~dm?rfV5>yH-ZT?Tt9(vqWk>YwK}qkCrEP207X z8}HEt3Q+GZU68U04XoLz`(+ROM!%!8dONhr)vghrZD-fl2G(2+FxqtM&-FFzx<&WU zz*QinX76oL&E{L&Out<1J2q9^>Du1#o{A(}d|r@6$HLO^%)gm9w=*VtYrTOK811fA z7;Ue`0mX_{sI+F2ZINM@EuXAilMAh?x9gi1*RYxy?`t!&7UnJt&#td+R&Kme7Wf0M zZ#`ROQRynM!mwQyH(aO}FPo};mkaxe&${*f=7hFw^?NxvIo2r|mAjnvx2FXsMUQ53 zSka>M2_HA;w`qcSapNXi49*}F1G=E)!fs7x{q{{m9v?;b3I))=#rzff5n*q^9ELG- zC9#&&nN6ed?VB1nT_1cy^KBP$RS&0gpa6H(!*!3P%lZ2TxSKKD2;aR1j_KFnH!y}9 z;d|=gaIT~e+21J*s^L?7=1OeCj%glm&O+YZ&eGk=o^FG@5=nzXOS59eb`ju$uDpw^ zq*2FVobNGmmW4FTu=yvAyz8gW2*sVCTr4#kbdPLI6gPvOqQ*jZfi5P)tIvJ2_3fLv zOKsg{j2yRrCsH^+);vLKS}-wNx0B1U$CJwp?ThxMUuDN82L}jNRY7)YQad{( zn3AwP6x$YKSf?g-W5>kAo6F=j?f^4kuRp!kD#6Ycx6jSP60ny&iG26!imZMX^d_d# zuQvcG7b_SRWr3O+uMq4>*f5F>j4`Y=WK$mENPcL=yR!^5l7UqM;H=DwZRcS*m~v5j zAk49i>6ahGt)g%MwJ*?+4uoKFyn@;l-6txJgs7Y5KT%x{=dFm2nEBVhh5es(;le&o zQ#jVyDEBO>4 zD!~)P0C1^Ko4owIq|~Lmb}cR58FaL3V9VAEcMj{li%aj`Jh4-!#5V2nzL_{;)~pe! zQQL+mv>m){+l*PWr;|OpENRoshqkF=Voh50{$GuH8?oeFbB~@E7#C2Bm#PYpJ@B`H zQo~$SYF*y+{OWOP_EGS2us%h{TgdEyIqw3jWcG9~g^XDB;RHKaY-=WLs1Onf3%Oiw zXD5^6n|Q<9``-G;M#3@#&`8qgo{~Po4ioI2-wtHoB1ATP(5)Y!$11~~i#auWF3cJW zdXD6Doy(4iIE;C+lG!o#m>*%E$>9Xd4=A>ik#h$tzs8e7zw)Esi2|f!IVZ{z-HC!H zWa|N`02(+#JB4T5v~6)ON(SXAK#&!Nr%|4W{{wb5E*4TEDstEs7HG0Tn5?~1Da{CkR27m?h1C-$AlMTS4AG#Utw7H;ILnj;aQoy z;4D1*kkf;!*pZhm8J-VZx>WIC^L6?d1WnugfZXfNFx(#TUg7;{@lghONxHn^Qq2R6 zOAj7A*bFAqryAEclRnXV#krcLb9G2X*miVj!lV?X(7&FAZ$3)RI`q1L~W--^~ zjGtMUshC=P0@5*IHCj&J=LY4*Y+kD1-s4V^Cl6rq<_D&HvMH3Nn$olo*QR9jeexQr zL<(~jPMKm@>7Fu$zh97-OBcJZ=hb?*$c+gkdk5uCZszVToI82BNO-%*N>c13yk6wG z$R&urUi8)Xi~JoMD(id0=x|||!n&^*wF}^H=nQo-aLgk3%hCAnbeccN8Be;CBb0No z5#F~Xi@ao!Q(A0E-?s$%^4IoqF|FVhzSF;A`L3cSiQt3uZ&~s|Ujp=rgJF%oGnSt@ zmLHZJ4(QdudpX>p{R|zoQP2!Y`1>i^sd*`Iir`y8CEHoDfU#$s=uSPXZ}<*c99Ts} zPaZKiYFM=t`V2xpgHUt__zVK>=m|;phTWV7*OZl|fN?;Yhkv7u=zbo&F>|JN<@)u) z{91q;@rI-6yZ$Ut`b(97RVg&AgAQ2D`RS)Qz^-b}@#Anbx{6MH_yF30fcy8w`3=Wp z^nI+_v7Pxo65Ema2*+4zezYELb&0|oQMks;tOic=ApstthwC0&Xz;wJhez_CYv4xs z&1>M8ehq$f4ILBuF$B&4T_yO)K7}Qu{sD^z!GZl;Erli9g=;#%@%WllxJH)L9XJ=1 zR)JD6iq-;tVDxzWc}ULh(Bmm7F8?RS{aAx7+(GfBvoOA`3BGWTbTz%F)?FrTnYV+q z#(1rJh5OAj#QW=^VAQ^)Ii{hgmxe&c(!)UKE0m0Q0v|b^UnZv`w?S*@e{DcJ1D+%7RI+V!Z*2x-1Vt{&0VH#nYYFF+Sj_b z*8P~m)(=}uDHykJX^v?q>Y-7G4&mk9C%tvwf z7aApsjEYy#t!w&z;Cobt`;;~JzN)$Zl@SdCof=xwWtf(m5iL`CwP@C&Tbs5C{hBt+ z({LNgT5Z&Ar=GUzX|KLE>$F?bwxv66JD{Gn>u>)nJbZ1a+K9m}@qHgEz;=|1f9dZv++RaOIs?;it7|tVHcn}M zsv!5_U#9d-Xx7j*Z-eP7>$j;oK18IC`Q3`r#jmy7sMAhOTbAayt$?rFUcG+H(B>yW zzMuX_yY;rMZ(p=kIcc9IPvMFB*pmnGL}TXvbz{{kswAWSy0LPlUN4XhcuREwyhd_7 z{w$#*alv#TV?+1oy8&MkBVt-4S^{{^4gKZUY8Q|NTD=6VKo;7Bj=x05(I(dEDkuRT zkt=w%-JoD_K62ChlAe;j*oRw-KAZ#sru{Vm;o*&!zE<y~qWV8;k zpQ_C&_>wQZL6_~|({>zxjbxg0O0E}J}n-~<^-@&{Nq z3bhh+fN9RI6YgQXfx;X}@j!tY;KV4@8c8ehQa^xv^jv zZza}kB~eF~oAP}wlI4C6Hh)3igQ7E}rYo1DZ3}r}%^&+Oz89@$k3AFBU%BDKVl|dq zf?Moh?FaB5vW5z65IU6)R=ofmm$MXITZ(2cAq3fu;uMYPf!ilI7)=WHp%8$a=xaU8#1F?`SEpw!TKpyb^hGyU^`0hyG0|hkjmym1eljP=Zc3Zh&6<_^JJ<&Y zgIUYd(|h(@my=uAr+MVCq2(ln$9;<>?}KAmSzwFD_T}rP4r>gkev$&&a?G-WRCw;| zEhLShPH-H62%#@`?tpuhZ{JoPy*Xvx^P4CV+sC0Fudh5$o^e;Jq0FmcWJ|Z2Vmbw0Rk~4af0;Qos4PChjon_0wgtL_X zd@e^%3%uXF8I=(7=nB?z%pW@!)3p?=L9ax|;14yrW6&8|pZziWBR7%3*|D%!S}JUo z7Kfe;yHMlSpaD`fJun;Rh7x#sM0E71kw0`S?bAD{YumA{+q7z#zk2DMcAdNTSf1IV zN89x7J(6Al_$_3eTf}G1@6y@Xd7Fo|b+cyiZJGwIP(`GsM?~1!`|fnNu{pGR=wd9F zv#28&kNFqunY=QAUC`MhM~-kgRqIj5moFJoZ{sm6#5g!Nj-i{4HNrDf!g;I3od+}v zSibI9+XXR4qhmU?`5lhe&O*=r3KZ5C$@s0|a`1T4^T2V73|o!u#G1CIQAnx8r2d*? zN9T0B0q0bo%Ik21D@6Tz4_=Ojl!6nT2TvF2@LdQU_7?-)@$~O2^lz*;TmjXaWcv3M zEa&&+Z|FqzXe85=H|IjI4m;6$cV6Pt8jS;a3aJhwKe=JgQQq?x7caadhmlpHf6xUG z3G9Ibh=4&$ckL`*vTN6pH|Q0xd-E^O$X_$m&*k&x>|f;VH(w<=$W5TEP?AS-^prFQ z3HSZ3fPlv+_i;c#sgDnc1vbDAG*{+#UYm5_{P_b(Ydd$^lBvas?KSkJ$40^CR1D8| z;?i(FZBJqbb9|4;Fl~e!x8sj}i5Ej2QYxhWHYABBJK+5_?0#)olSVHtb}3lZxbffD z+T}G{-s#7&q!+5N?OhIZIzNu|EKIe%GjIma8xLr)WS2umlL4{Ici1~j3J*uG|II9E zIX8Q;IvjU2XG7dvq8(Vi((m!O`QiBt`&@gqH$AIebZkxvs-p@gxlC|n{(}G0=sg<1 zKV<&mQJPL8u`kQbJv{hgAMDH4zwO#~;GlW`&Ym-8_P_H64NmC%VgYt{M`5zy#h}^J zl$0JRSokR^kV!w)uWwiw_F;L$^1?N1*Wj*Hu34jr7&>IcqQyU~NKeE53zd(~2aEGZ zoXEP z1ff~s;owq}Cf&OQ1k`O0kF7sWF`N`m;+8PFRRPHL4XVIF4Q^o1_Z#D)qI&N*iYDH| z0{|_>_Fy-8cz6~FMGr^%_<~zi>yx@}95fI01ziIIx^-{T1lwmcZf_X1-<#Ag9Me7E z9E9^_e7wZhJ-vkYKfyBqM<2a~Qg0od^xZ~yKpS=Y!GqiIM{TE#!dlNBrXwG~ejqcs zuW=nrMBmYIz?Y^XhAArk4zjhq41G51FqY!2DdQ_uG`qDb58aq?JO>5&wxI$vB0YJnQ42o zvyYA{Sg`eIWaQZS-MSq;8do-cLP`(f|HQZm`$OSbU<$)X)b#Ik`gbbs^lkdLP{VW_ z_Ls+m^OrP4)oDd};7iJ0hSFYp`G33NTG5QcyeYs!d!1#_hc?THKS7f&olNL=yx&6X z)s`$l=Q@-OTYpG{=^YULJPx;nH zNO6eFL+s(|_V^mPPqZzW#B2h+5BG-4qV>N?egANAX2K@os8nMurh95|*aev*Jt9-i z%^tSz$lhV!{*V&c4F`iEuAN3-0)gl{b|I5oUcGXev<90${`*2fCs*87M@)M()zPbT z4zYl1*n#{5@{O!2;xq~<{k^41aCA3Ff4>k6n2~}~Q)cobQ4X}NK5_FV#^m7|ZW+FZ z#+hU(T?`P^s54p&YERGjI4{r4aCN_q&6--;jp{LCf)Fp0wu{BKja$Z% zn9y8ffL5LBm7d<~9C{9TU^k_xXexSxs`%;JF`c{Y*xtEwX8-=b|B>5Yun9~L-o^C9 zxJfUTDKHr|1!qt^xUb!)7XrcWhVl0a_(DMtnjos-KJ7+u52K$!P5B4aC$d2hz6ayC zgY($Q{A*ejUQLc%6k}{*qY>5!M?WFF5`%D-`2}?Dke1s2?!-xxCf?2HmfWUIQkR~) zd#0rH+}(08YyU74tqf8)j~adDr_rMv9Q?M2uN#4iYG z)V&Qx{jj`M>zwXG^|E9K(Xk=;bbmddO>fuKKB^WX+ZcUUEhsh)iE_T8yd!y zZHw?=;wwQh_r5|6HJ}WW(+h47>wVF_#D451iR5WmI zbjwz)T8_?d)v{&6s^oBWv~SVi=$PQv$qTbm!__%MqhtE^K63bnn3$nMn}jE~-^eu% z2t^M zdVBAMX({ObOegYcrxJJAPuz(wbk~rN!I;K={{B;Ek8c(j*zwybz;i=Vm&Q%d==B*{ zSs9#-MD%;d_8mG9eXquCIpemBo=b47JKA4__G1^I zb%Rd@T^WJLCLZJ23wGh8PegsXuR%jC+IF_KcFl3Lv~1JXr2VF3CxRwiY{vsg z| ze@E0@S+;h5R)m{ddN0tZSGt?qh9@oJ<6Dp)WUj;g<@VxsR5(&3N@7?~(Wf0^mxaW` z&~tG?h3?(<6_bxRV3bXJ;OsbPX1DLUb%&19_!gsEOpc3dk&rOBbLZe@ty=XOJ0qz} z$;L2scFZVs+_=cJnaBx*g{9;~H8+1eKRmo~qc**pH;4bJ!n!8U3mp;>(ZHj(vz1jt z@0KkadJoK^0`vEG#R78*|Fe6jDkLN|oCwy-i%6EpuK>%hQo`bS!h`JVBvO)4i2-3{ zNG7ZYkTnUIPlOdlexOpH5uK(c;eS&*jqoWbVEaCaZ_y&2`~dSK!qa=9KYFEyM`W=B z3}b}b5XMOUe;lKvu3eMrj1lNoz0!1$^zDl6+`wbxN>3(o^wuYPjiD6I!&|(Wh@#X32Nmy5$ogW67GcuR{k%MA+I;vG(j)ysB4v*W_W{RiPol zsRsQcZ8~88-zl-os#|Kj6uQ}(J2LLF>sNlbekC-q%&}WynRD0l#4>sJUa2P;s5`^h z;*Xo|OhiOP8rfjRnma^3 zz2%M{kC%M6H6IL2>0MyP9uFNd+yis#yr+28!A--u_wSQReN}hNXCK~^^+xq#oYg-r`u8xh#4NMFS3~186PiD`iA!>DYRJginq*|?7wlN@( zeP!e06V@d#P%5>~lH0hr`uMxJ^ziTuQF(eCC{AV)eDF^cuQj>>} zR9#qms(jPWfemX#TX z|7B){ZBI(t5`!UqYry#A;bZgLbx0q?BD4;S?bUNg23iM4_m0%GPH3GlXEOQ*j7?7+LU_aD z@B`+p0p?9AWvmqT4xR#IR}#ytyQc2*ipOTNe~K63&&<}*%@Yq3#<+fkyhub|gEWMw z#!QMH8vYQb8nu2&LU8BKSwjm78b?HS7#|nQDbR#*;o+&_DPUS!n#fv&yL&<_#$e}H zF;A8_0tt`j&23pnXBjcnTIPM6nzlJHZDQFxVOIt62oD9A2OI&}8_lpLda1XRw!tb@ z_?E2f%&hgz)!6TchNwnhFBdmLg}-ti9W2aKQ&%oeOS7&z`Fp1CLi(x);h`@ak$> zSQ5LO;B$ssQ+k@-3h9_v;x^@E9yrv77{#QfN#GR zLn9&t`=5_(Sw?rFiay(vy?Qu>T?3+HlJmwD`1rI>SBK^M_#~!J##7+u396@33)M32Zi5`RfPd=~$ascwm06xNtAw!vWJLeAqCI8&r|)TdXj9JYJ2t zd7OXLJ=!yHBDWh&1kbedU%v*|+osmo^=mwPlQ^23?n;(t^jVvbJgLKQfiM|35ip(Z>Wn{#ALQX_s;ql7S5$GF5bOM9lK z_FOe8)5jsO%L;$=N!}>_NnDF*gGYo%N;qNeVa<65?86(Ac-~R2PwDhVj(a4AFmz(3 zv$Q-6S~QM{3fDCCPVJhK(skJU9WQZBqf4`8#NiTA@#E(jcePF=VOc6+6IAYKbFeZ9lqR zR)B?W2dCLdVSxdbr+WiW!qIk8v%?0MAI7^uVaE)x@j5xY%?`(~;|7=mh6#8l1Q^jZ z40{cy3GZVFp3;dv9P%e~6JK+(>``9`2hD(4dT7g9rD@7zEkKP=|x) zk3*UWbO1J-S~zmrw2`BxlJ}$9>g23B9EaOGW#GXVxAz0g$FS1|9*&_DZWC9CIcP-A z^|kX36=N+N@e{{pCznAXu(sFF3HaJE1SGw8;Vd}$V0q;Ji9c6Y|2%PjK4PRFZ<;ZwIl$DjSCpK?JyEdZ-n>Pcm&7eD7j}ApCybtb= z3yv7DrTEe_h*SnIt-$02#{%?Wx0o8?NNx1d*|U!}-&c6KDA)0ush0Ugmkaknjdr0~ zhwh6PckiHG3v+E_$=BHJ+CA)^h2TnQzup_CeZTOp;*Gt*nLWAr`MDr=MoNCZQ0r+C zN`XNV2Vq~ZgG3Ax{WWB*1_o^|ZxcM&uL%c_99gyJ=9x9Y;Y%GP4qs;0%;Sc9(caN0 zE)bs-8P7DwaVip_(WfGs2#~7|6H<{d_$3>T7BUes*O;b@MsqbeSzW)hX9%o~UgdRy z1$c4}9T^)J7dtXEG$bT=U{uM8Q(M$3756a*&&=_0&*I|o%$)7uuz&f=GII-kKN2Z@ zDfL^#feNdK(lCv_xRueOBJpVyqHGA#eSYCJhLC>Ch7R=iN0oy-1LN%&uY`DfG$1!=9?O)Hs?0OOk z2{_p~Ah2ulGJG+jsXDxQcDOpESxRQ__9;yR5}T?*V`7E|O>En)Bm2s_apUOTDwUa3 zmg8t)>E)>k@$~2s>hI&~B9+RstZf1VyM(nP{4~Jv#(gXwN4lSwCi}$dsO1RDarcME zx;URcU67Zj(TtU_JrqvOBa*atp)x6OP*5;gi+TxmgA6>ckrgyYeOyb@4{Ci_dtc#b zHqbM{*?H8c{5-hEk_54C?maA%pi+A`iK)qJY#A#ikgh)0sG`06t9cD&5Oz4PPiVsO zzn0OkcmEbrnHaE9dmE=SX6B~p%%W+jsWj%ne0(K-lGll!A~bd4r|NZ}ix5CTrahMJ zGP-VIOP`KWS&&JR{Axccf4~5oBe5$pfGc{Iq1D2{(}Z|s0={oDl?CQOpY-B*>6OB{ zWrM&`xx6hJ(Zk)X=g_fWA;G8ZV0_COze#*%d(dg{V02(OcOWAJwa&-@$Bl6HK33c| zp}ez;O20 z|8(hu{88gA8>$>eB|_La!P!#6POA=_I2w-D&hHtgRIl*xakD1<#dIfQx;BE$9c#Kg zAz$n=e8PHGKkSy`=9W5i9O-i}kr(o`*huFD2McmkVN~JVSeTy=-}a^o*PxpvJD~ct zAmfoZCY+9alVL4?&Nm}8ojQhxbIV(Md$(>i8RvCFaatGrBBp72 zsyaM_CZB-;^czV(-Q5~0#Xb6zum58lE&o5p(G9)7os5;3M9*rqA&yq}!s@&hbZssK z($vo3B`gy%D;cG)`uWvZ6r#lk=QkPAVM1(NzJDWZGU0HMkiNpny(1zLT1_SCG&UUE zO?}_k9zyO2>XWIXQ8EORs1=4AlH=e6&%jZtFwR~eSd$x1MH5nRqv7KW<4*E+lV>d> zcY>ycJJB^f;7AHSYbS#*NFqGr*5}l=;;Oz;K1;lh6LHWuh)@_Jin+_lMk>w}QqfYy#W9V7KD;FlS>!_G54tP|8<&r0lakVA#B!9iJg;TXo-On8!*Q(b zTN`mSwfQC^V4?NT(@b`;!%76dG8C4 zd2ihR=8RagQfgeZk_aM*ES`(Q5(8`2#e(!ZFhZSRRLJ0no=pNhJu@2>hJ|(NJUcSh zIyhm;dOTq9aj`MUsh(a#8xP58+h$t)C{Ei4&%(|@K8_A{X3hakI`vek%vq^0h7AXM z*xH6RZGsy&bLieaH8@zt=yelRV7cM^z#g)=S^Y|3jiycjK%<(FH$2wa1&Znk7lBOB zslO_i%xc;WR6E5y9MdCtxTi@TZlDzdYNzBPMb;!U?=9%Nr9MH2OctESF641iIM;wb(JHFy(ekj4LwOq_ioq$PX>kl&Epc&aN?** zOOA+D7G^}m#de&YoZL0JC^n1oP3P^dxcqgQqc#24sJNll~En!P6O@P2iMoz~y$zhH2^F;VB|t z;o8D0Jwnqsw0SW1gUB11BFSXw4zL$b>l)G0)49%?fKXXY1#cAIxmyU#*WoKR+P82t z#na%w@-UvsJ6dg_Kk5j|wU7_-wXKIUbJHTK=G9|(^(8Kx*3Qw8;Y$V zVkyjTmXsL8ZD-N89q4mgvcRQLs>w=>BTx~C=%Dl`ixNr+m>d>TdCU8#9()-W_*r!=B zW;h!nxrX7PhaXL2r1pj-G?^wGc0H$HD{6E{HC5S4s-kq^MKR)K2$? zwM|QHGaO7GGZtly9s3Gw96N^gtGXBWO1DLlOV6RetZP)LOuG{*w$J5WEqzk!I;&E6 zJ8F~O&)p6c+$%8d$+;orLVz!05n0{nx>KXMf5->XI6QKWy*ls+D>xn}8@4n1ko>Fq1V(BCQ2EG&n&x?AM@ z1EyWQ`2SX#;A40@B7diUb-(L4%1FbXL~aUKsK>|fG77(h#+cxj zk)3K3e~bx!8M9jKZvi(~It=r9hTDM0MZAxhz??G3X^Nzsc%MI9#mo}qm1r1mPAR?@ zJ%+q*Ox7DQ98YcVlQ7=w13KRA1%1*z=I2VCF})^~kGUWeG^FjMaOwO94DUeb!@2Ei z^eKwgZ#~O9fYFAUB}Z_({Y>m3QEv~Vwh7T29+LAwM0{co{X~6QK;cHUP^3w?-2mF} z!N3f}>vXz*D1F>6JZeH;j`C^k6g~a~^a^9^7>M!-eGE?&;rA*05{fj&hxd64k)KFo ze0ZM|YBn=y3|va_1BG$Ybs%uvH4Gm>`7hIXQ2skod?}W58r3I?@AMkwQ~Y-r-bU(# z;s1&7-sptb-@$@CbC0M!H>=slF2LDz3h!)?=U~cDGtrOSG01Zb<-fBCU!?ahCin}0 zwZXsC;7j0wF?xHOL(Z+DK1S1UaEIumf#pfzFf4RXq0!If#7CW|n{U zGtj?>9AE~;pRMztaKkxS5>L@jj;8Vp*2`7uLH%SB)r&D;sS&>L?*CY7H^%r5)K9*o z{3Pk+A@LOTI-klTSU(O@4?2%r=buq{l0mOkq91-w?JvYI&Vn5r;pR~KT@B-`62}2i zIw3W7BhV*yBdftbL-29GLPU9fG>mgU>Swx&@OgT9iu7kQh{{b*-$A55n<=L7t_DAG zi|TbK^^+fSYy4z^)C$AtIbu#9b^FnN1AdAD|NT&7d|MIUpBc;yXLR_!65uAX+@ z4mQ3oOQvt-C~L)eE&a{!b~qJ32$?V|Wh%uA4&Pv#{JY ziv2x8`x{Q-!*!3@3nKsilz-v;x>;BsH}Y>N|KCzRMSS!vdqLDwU+NE1jOY*3`#V|} zV>4K6(#|6~4&)p-Ke&2c3b9gVq1YdKzgbV2pVNmYjBr;Cf6_~ozoy`zodhUr_!IlH zn)JuKR}FvsJ)u9k3JlMn{^ScD@0TL}DB6Dw#m7J4TXFt$rS{uXz{m7oisLtu_Fu%u ze(x>6j*j083fJSGA^5m|8o}@OVMP2htS83zgA3j<0(BAJL8L#M8Aa_;Pv3#{r}Ss* zUQjrt&+Nzg(U{`j;NH-263&(1gZWIQ<8gy4r0`S`e+)f;-j9h86K(fj%C`RB5Hm4+!)27-kumX}}M| z`2U2~!I!+lUq))@N+;oVBWb(qn14VU{eFLm2E%Dp4Y+QYKK`FW<9|K= zb({sz_XDte$ol~TK7nUZIL-p3Tcx9LyC?YfU?Og}dCmI`53G$`$Me*C>R*iUg?Xy2F+QG;w$kxxF7%5R z&M8m9^Ou^-!SHku-a(K9jlTr_ub}jWvz?;I`){KC_o4KA8R2)vbfScKji~^!27DQY z_oCWASeP$#)foOK}+4dJ1yTHKlT(<06$9kNcgxE5oZM5^&(H5>BDxP91`b{e8Z791eCNtW zjR&Co6@#u)dO;#R1*IpxF&=JM5|pYOm6%*vS=j;Wwmm7m1`@4~ZM|ULf;nwcRyOi# zwSdwgc3jTCCEkkcy0BsC3U@543gr|HIY);Eyij{ce`-%NDQ22uhwX{a&5rlG9NBN- z*1oquu;wb#wH!Qk>fn~>(s%l-TZ-lx@Ov5Xbw>DWCC@N@oo-nj`UM93FUItx zI3jcUVv0}XBOQkEXNY#Qw?;nH{x*y7hDP+$4fLx`=yRBUwQdnAt;J6bzP1j&R=2ng z{#*k-GQn44e1s)a8$Zo}UuA;N8su3;S~2u@F~GS*R++0IEIhX2BBT-M*QT?Io4U(GmfMeWzBYYCa9w(Ss4;vZcTRgvE z{ai;@jEvVacxS3VjZE~7;J*;{?H4+}#_Jz7_@9l}OR&EAV@>-7%`?G&PxVc}*BRme zj`dByUZNwd80Z%m@W1?JyuKpn+pos_5P4F4n^#w!l3Z$!b4g@qPR~TbQIQ~5>|LQN zm8+1aA7hnNu6T4ICz+_vyD{9F0YW=q2^}{9|2iw=-KQ~}%yWJupQmu)Jm%3@FK%JK zA>$(gO}<3=5%7=k{)TZbpyQk@j`Jj={HnPjkNISjFa0cz+aW5a zn_N$bSv~ ziLc3`JI$Ne&< zKg|%ok$0J;27IBvb>myAKVwDeG)^MxPVW2-;hDO=GSj7s7ZvdLFT430UvBULUv88N zxL!Es-H&54d!c5eSl&|nPpvw8qIr5oA?e;nMMABR4$CBp> z5{oS(^!98DzuV3jo-4wo7WMW^GEyM7mRHmK89?>~dcMQWX7{O2LqV+O>PmSOQ1pCtchT*S_;AeDn zZ9sRKv`fdJlh_N&kM4Xe_*tDy-*4E0%D-8CV*}OVwR-fQOQf=F29MMo8hhT12&Hlps>unnpFn~Cx_85_2-cx_p&u@T}yG6vlQUo)K6Jdcv%dB2*r8>Tc!T7XMZ1o$L_l!=UWkIlMJnS{YHwPlR2rHR*y zjAg8QEVUKjAiTDW@wFuJ+Spn$F2+1Jp**AsvWlr6e%H+yo@;>b_pcv*+Pi-Eft>o` zXL=gJslE#E@`(E3XPs;8w>{O>NFf?E(pBOsbhO`*th14Ch2I6;jo`Tk_Rs5zh9a2CU6N$ z*E4nVsjsi`#lIrqyg)1qxPs!ftk;kHT4?G=By3K-Ht}n)sjW!Z-u3Fkub`6&T*3jXG#Bj~9fPTn&yf=e;niNb*Z2LlCN!|+rJha$XGk1xc$ z7OdFr-+Fu@=C$BN{7}<4%|cG#tdlOH7Tm5LIBD1ZD{zOez#YE=cd84gd@8;IcQ%2O z{=TGqx`_Q+XMjJWa90t&S}%VZxA|GP32=6eUj8&@^RsXl;T!dIXw2qk;UU76dU?`# z&CjBN2=8tfuf3E{PjMXk8OE!E!o5Ve_*@smsb98eFZ4_Ae+}>s^}tEHiC=+t{0h9& zSKyuN!YQ9!z5-7&fs_7He{IoKlyimwK9a(dMR=KB{?u3dS#%TSwp}lO>ZkoIx{L5~ zgZx`kcn?u-(+u(-PvI#d{D=WxPWkL9!jla6Nfe$c!WS6%-*$Sx3|CDs^2_`OJ)9Xi zzLwvxNUQ4~xbb@Yx_*ZEcVjqhS7VqDw&oe*W4Of{Q$ItWZw%At(@tl&V|0B-fQRVe z%t+=0h!WO2_)^-gUjp^Ny5t%<)c<Bn^?aeViW3tYYg-2RR54xH5X%za(r#6c&!=Lt~>NB=0g~6Bs2Zk>i(uNLOXqo09Wbg zvo_sh0;e|6Nzg5w4Tb+f^R?d$F~wC~GkqKei!fZm(!IF4C;0DiRE7fHRsm1<48tcF z<$K$7!4!@o062icn+ZCO^CqI>EZMt9b-bC#M>D;Svz(BZ39FJua{LG1Gl|O4oANdp z_kAvv$zAkGlo!yf;hN4?kXLs7^15pj>$KCyKya0DenI7xCin~=ll=)tDn`#3vDz)T9P4&6s*|$%4HZ^9f&Eh-J(n5BN#qA@gIhsg7p@VZU%C^57hF zuP~hYfASOOb%5E!z696!8`!5g$6GS%*r^hhV_bklcBh&g$SkABC8_OIESP$2^VDSa z3oMncYW*59jgWR>=SBlq$*R-m&WPPliE&JJ8-km26x z`g^Yn_hNbZ3imSPUbG9H0r4hnGQiPZ$*RFO$x}Crq*oByko1WiMsX|||9E=|v(B8I zYGrOAagnl|lpzPj-KoBE{fZ1-|Cz8ET^TBNk~iuqSY_1V-9oqP&^Bk+Nf<&~>LLNO z2UfKAvOBMgXw!}ucSoSj-=MwPCG-svnXtpCOloLPx1v;~v;|Yz)r7XM5p77RqTCvR ziKJ`sElSQ?kl$1+KRApEaW@g-Zs8}Eb)+tey+F_T@{e~g{ak};xd&&0-i*-4Hv zGP9#NU4u3jR#V|Q2U{jhZjD>u(=4T|11Sns8Cp$#&~|G5bl>S_7T5m$N zd-BAcyCzNA1;0$(xpU&AUAq{1|5Ww{Ha3h!s-=Nu~f25f9Sv-!|*BroO z$5Fcbndva7GFXHCQ{{~t2;n<19yf&INg3BeSTA`O&P;Z_nxL0+*d$<(IK)cwVVB*w zp-mz8BC_j*CHG4m#QQB7WxU)B-((?yoC}YMnY)--QDTH#5RqREDS_Pe>u|@78((${ zBneT#+<`;DUUraBr`1t;=h`)P5MoFy^4Ovy|AyA5QZoLGiiu+qnLY8Xd~ALFeEn?w zef$&RnZ;Jk7B`sRXt8q}$>K1p`OW?8=J_};>ge0PrGH33OY0bOYg-%E+A+l1Eykw3 zwWB7$+Ret>vZJi}N#*q)Dxb(+$zFZHAGuv5{+|qY=)36XC!v+00z8x)PAHY}|Bz2w zLy%bJ&^@utynC<2GE4Hqiu|x9KWu0vyp9ZU86BC9x-$`S4W1poRw2viySEA`?Tybi zHoB%Tf}6eT*{@&E9)0`vSadW=_V!dK4WCC#E6Ol%BTInn@zhbZhlcCNj>~4`#eb-@NcwU)*au!>Q$< z2F19`R<5O9)HF1r zOI|Vs>wBX6mkD7Lnsj~0(!Lf=0q$>U4^wNdW15zDe%`73p3YzNls>p~>G2cAAQ^dl z{tUKKoOR56IGR&35~gjuFZ+VyIrsuVp8R5=gpq(3j3fba&zY@K$TGwEJSjPNF_O-> zk<>&uY$0aiha;BaXbv2K8jeQSKvNXJDNmz!=-p|sF`2Y?7Pq&Iw%0!1kAETIAq%+| zEN<%sIRF$h005J~v!p>D3}=}UQZo4%Hz>9we9Ul*_M|;?a2DJ^0l3L)oDyXvqpZ`w z3Rn?2ea~?G-~1IEE3ae{W&Vs@_X3h#$a3g}9VY(G#o)iC(Xg@{U;O~y~R4Y^4!=)PgB8Q%k(t%Z&3hwDEakTSM5*r`Q^#7iw% z3mk^n;Hl=$ooG_*Fw{rmC?O{q`>UNeHvBpG@#){F`Gfl?y7Cz~hYk)LIC;#Ng0Yha z4G`!{ILQTR-dE{caF%#VFs9Eb9Q}Nh4LPYg+=mT+0M7sY6h%FMj$)rxf*+)LW5!G# zIB>wA$zuyB{Zg!>?ZFLNo1PSVB(GRM?}HwJ27Uhdr!O8+ALIkRMPtY~#^`>OelMAh z$Hkgqw1wn1M}A8gYdkdywW039sjQ04rgI9Oqwm5LZ7G|5k6c4@bdTXrcUGVAN0(e*OA^0w- zg6_X-c$jEkLsEKH&`Z9902j29?O+10(btAx6(hvH{d7FLjLXDrYYy`gsTs$SsPVdj zoJDStU}?4ka?A-F>|J>m{X-?4^A4NId8r&HSyEnBDXUDgC+}cO@vum|{QIr?tLlIm zdaweR6`=1ga+xw&QB@;ukF70@MRZZzEbPO`nI7~^9jUls2k!bEaDV^)-KqKfjTfhm z+?7}Fmw0}DC|M=M(0_n)Y$MK&VW~t_aw&a@AIC*-{NBA|;G|u20I0s-C5f1tCE7%^jGie_7wPej&V%b2PW`Tz89WC+20>q-)p^p|+M#h}qxx^cV8VJuQ_XU9;}l;-!@`GYiGb zc{A=T#ebFkW@BdM_;TK~-`SA;U0OwP5K3Y@b=%*ibu!K;&w!Ihv7jk z^8w#~&v3uJKtX>FiJl7lKyJNQ9eDB1ML4sDNcB7X+lmr{%x!${9y(7;g{YO3}ug!(4*27gFOxZ>=1o&!g|MkKgcAH7UeTX%TmC8^; zPv{BmODxjbAozjA{v5`aWBjqE{gKzb>)JIq2eFl?dKqHhAi=hK!ujwO_PN&NY%oTw z3Pa0A1Q|!W(5xaN|0#GD5lV?)&6>F$@5Hc{(z`q`|Hv+~0ag}Fro@c1vcZm$cttslKB`I9X%`s`NW`C5W=leU z8TlbMBac&mcRo9fk@CEv|-cOLF`<1CwrW= z1bBk7g|@t{#8zr+W@~9{WovEEcmhx8$$LsXrJiP(p`jti%p> zb|c+vtaJC|Iyhn}XW%ye!+Ky#-nyxM_Jh5?wx86rX?Pn|JR7t_D*k?O^*`_lwUso?cO~ZAifKaLDr0I+ zCkXTR6{-_@)jp>}ERDz_fUt0so)iK~L#TvyDP+NtyK;euGfsDT-R@H4_l zIW&51c^N-MJXc1)RwIX9K{nbj2yFn_{19|8n;hv9@H*qA@Wu9P(hH1k#z<2FRQgN<2_xM8LxC$;sXOX9WcX zHOrR3snyu?7ELdj@@2~88Th^d_`ccrKI-9|=(!$JWjH-tZ9xC*pk~d2vio;$+@wik z37jz*-$ZVm0^sDyV%_o|Xf4j*c&Q^TK<;2t=i5=J^X*9Ld`l#9D@d+K|8V_Ez4gc8 z5BXwA?~xtGPvR7`0-B+ecf?FOfA-Y<3tzF_?WC6N4fR{+U_t%Jw#2bcp#g?tLRe1l zNaa)!)(7AF6NS~(u8qTZ@5sHDi3V6M#=Ayg9SyJy4Ev9^+sObMN^0Cvyv_z#8pf-n zcwG#zZW#8G!jg=6X3OAJ4C`700}*T)SdL-IMtDDBJaY`|W`GUX4FU_Rby=EH?u(lX>gTl6(z^+o*KI1yS|j$K}yJX$#g7Hb6<+wl}h~&;|4dy0xaD0h_rtBaP!rWwwWQ(lPr6 z>&0ap56bmElzjA+SHVa&T{{9MY0JKRsi*{#xt^t{T`4-)njEg#n%+MZ-`@xKM=9Pf z)JUc^JZ0f3qe9MtJB4c4wA!=s^yv#1ZoY_F-lgO0n5Fq(78(y0fJ$_#v=k&PSg;@) z@c(&w9BSNn_4Ri6Pllc`m>~7Q{x1Lr+)6|JT;r;Y3VW3_-1txh@&#Tg1;h9-@rb?H zwAAqvdW8FaQ<|DFZtp4K{Jm4`xcO~6W%u4l&*#ex4T<%O1+8zYK0K^B!Vlo|i6?fz zll&9nS-m0SN2`zfJKFmz9mx^zV)Z;CJ8xEBxfXwTg-XpT)G)Ejp@_*p0NJ&tKYWk> zp*P|eXcsZLOBZ(U&p)HLOO~)<> z7K-5vCsKmbaJrL1e6i-{Xt3iW3jT&|D z9^c;Erpd}VYYr)upyW50L+4@KM>7>q)@)jfeU#xYDwJ$9Aas&0^-3E6PoOXJ_`kd7 z?+2Ek#l^*o;c4#H=?-(p-KhW<0aHDFQj5aaUVU=<_MSGc|IYZGD<1ruTi&tr_VhV( z`Yet6Vavxq(t8KuPQ981B;S1bLkgxW>!Y2+-?;h5{9`^&3n!PWT-^RgpX|&?%t7D! zmy(>$Q`DNKq&^H*8@0+`rSR6!4|y4!d|2^6HSY!hz5v{yRORoDza46j**xS*FtiVT zOn&?n5}D~SVckRY=l6HegA(q{mMy5j11$2W^4hZHsmCODZAbDKXIrq~9R0VTU_o^e zTSPt!7H9{+m4GWKK-Kzh1qD?0*}BL4zjTd-RMz$NVq5?4?oyNM&kd;^A`pE5=qjm zA3~qJt9(}}K7+X%{VJ3sT;|=4AGpxeOF@1()0`@l=2W5hKQX78fb%P02`xjqI}EZK zYLjO>TsB-j+-|u2AcrBI!@Y)k4{tbJnddXqcaZ;}rX|u6vl8tDQ1h>j|%FL*PT9zNG`E!(uvg&4|=`^d{979Px*)Ao;4L{@5G7 z;$CZCJxxNFpCzG+%g;N3uos=!`CwgXDf)NA@IPj69DYlC1RUFtcWd@WvN?}uenFAu zo3TzgVXN!IjAf=1pKVW0VkWLaNUVf{3TS5J(0i*Rz8nU`ENq;J2> z-YwTut#4>!W9w{dLwrj!Y~SDEv1m-{C)xYcSsQ1M#%ZIFI;w@VmdaDv(AOx5JUVyD z@QLxM4TCk0lhS7A_wGLA;N-#8GkdikJ7?I)4xwrl3~uG73=Q*kfn3g;&O;LRp-nr@YxtSw3c8Fe*I%@L3Hn)cEO$mvM3+_oCQ!yNQx1HOF_0NOx!7&E$&t&cv z=Tk=|&eep<;sJtY^WKhza~lEx{>wW&YgO2}5GsX@%!Yc3gh`g!WD#&CRj>KPirZL}r<~ zUfe#(ILuX368Wgb5LTmBkz&mB&;ox_eOV(H4@#B#lb=eTx}<3Pi{;|3PY`=-nA;a#>Y@Z5F<3fUiZxjZ@O*Rv>rA*%|D3EOhl>X&iYwThBN-cSi7oLw`jg>lSnZ>xg=#Z6rw&C( z%`UdGjykX<`^xB1e-3&N6fS#_cEBGk;WyRYLQd=+Rasc{dN6v9?%HjK8>CJh0t?N| z1BQ$#3fKJT=lA4%kA%XECf0>fS(9hCY5hx3@Pk{4afNt%wxDa=D2W4}+nb1$spX-< zsWar^1RfoGbgF06?R#=5^3-$QCNYw%=3W)!09WW`B=2h`7S zxSYmYLr*Fhtl?}lXk8aapw@igV_HmV5fjzor(35JTeTT?2QBWdUgr7lw;y6Tk5V#|B!Ha+ z$$jGM??BiIyU2b%fzB4*Q~oQKs4MI{<_3ni!5ROvr^NP2oe_WRE1hXIZJ|oOyv7}h zs|-LtKk)u(FP3i_KYr8l7iok4nSpkr31BAZHuE2?rP6clT2H>um=@__RZYXv6AEzf zS0b(_RM~UA+`M<8W9axUVW0N*IA0q^pBvM95{w^9&S`+Uo1}gY%~b=Kl}DJspd(CE z{BgWp7+k{-oefF8++cpPBfx41c!b&msId zk3To@$2zkG&pgFn-s2CNVkM1*(k*txSNB0|%-bEo962>5$-_J$$F%Lj1> zJerUC>8FuV9_;lAd7P!4a#w(pEmysnlQ{;I`q)`=O-k>1jVb{)z;11x5PL*peSC`b z(FI2zjYy4{ubT-qBK;MapO0bF6Dz65I^bQRR@{)@W5)E(89Nr;2h;xi6HUIwFE=s^ zk7{BTiP%`Ub&D63tOs7}*M7Qj{nMxGWER1^nRUXv*$Y`KkPC-5i|6A}&i*&Ie8!2c zNqq}WoRBQcS+_x3`c*bTM<~<2A2n!d0eDlru$6hzSx#3Uo5Hi*%{Z1UB(=wY@Q%!I zbdy(dk7ZK!EW?O(E565hx1W(-HfC8m-?Y~~md@j=nBn*jTbyms7~S}}1$|T`tPtuS za47U?0*O|=4OxT!uqHiPxC=0(5uU)o=pNx{HTE- zZsh9Z+Q`*A&`IN=iuCl=c;pOi8>R7Zw?_7%>df6o2PT9C`m1g2ES=2#6MA)RK7P`UUgcNUZOYga9~P?&w6*gNwDj-VrgR&lgM%?Q9ol+^$$WeQ zWlcQn8V5zr7@w&0l~DOX^qHT_-y$neyhiM|KFJ~O5DP;JrL?F%4f4fHR0#MQUG;=i zFoLAQHAMD!fRqi{CW9KK`g$teTsHn}$kN*Ra+hXmb(;dGlSw^r?|TIY zj~aSy@*1~>{G!D6lf0waw;3Jf>6y3TpSNqHveC=#SwGF|>glP8oHTa-vaF%a+Rhn2 zDx+5z`qCxRS2;*|FRN2(RMD34W8(YHpRr_;6u83v&DyuhaCOqOkBSXVdA@B59 z@tU|dmDH7C#b@UBf(?+TkvM4AWDQ%t$R}Bd<Gcb;019Hr0w^~n zp>Ib*KT7wI&Bt?0q+mNT)6=4B>_9Eo+ku1WQ%heMK;)7;{N-jn#pflk#3%{(_PTGJ}h)=eqZG;_1>6f<+i zDOT?4(JUm+&54UQ_xH4OYSd{;YWqh1*23O^!FWDwgL(BPJ~a;L^G&Lb>aaLKt+dAG z?ez%sStj-YgXaw|h@7#|dwjpPu}Micl9JRF$KHld{U#zSZ`l08DHDn&O}aRD_=1}Y zCKRP_@lQ&b(>rnUh{ePDt)Dk{{E(%6PGr5k*CmM$j|d5BUfR4*b2>h)Fi&~>TY4@! zUvt))rsmuWAElaz&Ob~rEBiX$NiZ{U`2qi@P=$iq0OqB4iyn}YU>@k4H-3CrZt4P5 zmE20BwpO=y4e<@uSn^8m_`bi6YMWrw*fY?>+EUtB6`9yf>BDgjPJWsM);1Po=LI{v zq$I3LZeTOR=1JaorDwZ2W(jdKoX@6u`#47?fGIm>6m=RKs~PGlYvyJdrST1nYIJSe z$%65Lt%6xP=ReUshQDE%yOV5!oVBM>39gbn=_DFpM>>NiRtW6u!^xo`tONu%?%6!? zo9H$j+pLL8Tr)Ju!n0styTVDpt{pmZJhFkyu-f-2Jb>!Tk!{%WR^{toKPUNE%&c z8(C&cxRI4vms#L0u*&uWqslC!$=?n)aYJ5r%K{_I0x8E{Wqvoy{K{Mjm~dSdR2Ep~ zfbVE7BmeM)5X^gRev?uU`nfuIVM&P)i6SDg%py6JG*K5nJ}K4k)zJBJiPYN0RuAVD z5ou{@H8OK3a}{OgfMuqrUuKFLnJHxZJ(P`2WEN7!l}RxXCOOq=pUhTTW-Hq#k^fVM zN0FCnEv%sRK3-y0#>vX~XiEz#R`^pYE0f?q(^TqEHBl@aemFLCB;On)#&3FPj1EdA zZ^wi$0W!F3?Xe~3jdt)_?(xC_0~V6cyvWedNb;EnUX>2v&Qy7_SBi>Dhg8LL539q9 ziecWjr%!)NKAi^)=!`$wR)vLR&m7LxB~SSZoUyvlef!wfNqXVMu;ix%f05gfKjkui zUjLNJ*IV32DOXA?|3n?oujndDmVj~)0zw<3kLU}U$%6tQ0a7sjxc1uqzC(ueB`@%l zm6w<8pU?e!8~u!ap@$X)!rQ@bXm_M0>Pn^{PFe<}|} z@h#a8Ofab(2ZU(D*qerHj5g5#JHu2Zqt1#IG6RYL)w4Z&?Yuo>dYkrZ#_#Fh(ayZ_ z$O)OP{k%GyL?yFYr%fN(Jnnw87fYvl1~+Tr?!}&;cB<2m{!34GOxpS9@7tmSJQ~d# z`2ECoF=#xxH*sy=cQFYwfo1i&DX%tHzdm1B(5wvz3d`( zs76kO$T>Q2ScrJg#jpzmR`dhSoD~XZZ9H7`1puV0LMV?-jc%Hm5h%nV+QASmhW&0| zyYZ)XHlMCt>C`x-WL-*Q+}>#PiPYm{{2xwUV}>_Ycq z;kj-o|1Z;?)UD+G1Rb^o1|4=%h*Z)tG`*6p2Ek08Wl_eL#=z;$gB= zqb^M{#tj%SZ+`B8rp@Bx7skcM$7OVF5g#AlEqrT>_Wi=tCXV0F?;OgSko;_14 zQhH_-j9Ig`prAnM)u*RT$iAM16SG2m1{O{)8q=~D*DWyv6}N3UFn9cNFN+|CCpIDp zrL`U#&=U$t)=bwa$vyyb@Uy+Q@VMApcw8)%0MURHqUw^>MXsu2tJdS1cIv<20{WyL z8T%7zM;;G5pggz@Fx3Si+G5a}*wu;_0qJQ?s`ppW)ytqu=qc>tGGj7X&D1{<{-sZ2 zxJ9rs1+^{^+oN$)VtQn(c3^&|)3p#!X4?_QE9eO0jXz$pBaF>2_=CS&lXa0_$fCp% z#vXs?@3i2Vzi?l_;1A4f;fBqV$L7i7;G4&T&NFHFGYEgiW_y9Sxqz&- zD>VA|D8Ohmf7Pn_z-#nwQ~@ql0nmBRsTb%c(DLQg>n}ii{dNFtb~xD#@c8zwA-DfR zGtm&hp=wY}(G6m@r6XjE>1>@PBHB=YB!?}|76nKJu1wqIiCS)OZ@c+pB5BR8xt^pXoXKvZ_>}Hc} z8c8;r%>qdv$tGC>X|&KGbO^nJ(wjjk0TihMf`EV!Q2|#31VljP!SX0#R}@jOVn;*E^hQsjxsi)_q05Kt+= z%+}BZgCh{{=dkr-&jTFZqH$3#*@ki(t_>Bg_Z|aL;Ds{kl>e%g-DT?)YV0`JMzwE8CMm5w-IhdSajQP5F#b0qt9Q41Gho zPwBu;qX9odt~CnSALA`vPJaCdaP7SFD5J>8(}!^k4xgjsYfrsVaLSXFPG^TLLos&tYoZ4}z2Y;dGW{o0}F~*kFF{ay~-i19(!Lf;@ zTjq34bC@En6An%uM)s}@oOjEb7Pc0_!M0fIyM;EZtVGAO>GaUzJKKq2TW+hO-_x4Y zF?T0q7-I@ki!yAs=-c|oCeH3QZ{C&xC8gF|TJU}~7Ge&PWOXUG;0zQEQW`Nm(6-9uA+;rh1I;E%cO%J z!>s`4#+{;Tmkeu>HT;yEXPZ1T;kKlv;nCI>9l}zd4oyiYXx9m~u$z5N+0-OkbQjxf z=keKnhAsP$9zXb5+Mb_P6%b7wP_h*s*WRyJ{ibzf+ zdASj(&KxNs%9;|D7wNQOSIS!=u&({EP0)4AEj^}Fsb{Uh zN*#m*b|xkGRwZbpXi^fK$?R}iCP~&?ONI<7rOl4n1>ix2~CKzr;i_1I;y;7#fbTj-Emv%DWfW$Up%Kc6uL}oYucA$FCFpd{*{wsqEd^> zH?A6Ud*7S^Ju`En!>kFZ=}Gp~^wM#g7xc`s#N{V8DVTcy?omVL6!SCC`_+A-n3Q0l z2jfF$!(=tsw8=Zx8~Xl5V0BqdIxoJFc-{d(Pa;Z7C;w<01GGC8&&+=)J}#->;|OSl5X1rxvA~8KD{<8I?F2m zVt%MwWKpbop~ILhcUE;fGa|QL)1 zBe(4daCK`D%?|Jb?VL$%-|}YQ-2pOoR|#tp~Z#UyrYZGXmfcXS-Nv%nRh807u)?r@EYY%|`~rnt=6VtDzu9vzxDiLtq`*OGCIHKFsw&V@yh zEy82s?IY%`on&}q`gCV-zXes>w;XEcXcCc_ks1(f2$o{wn#47io2Ypgsus75&d4aW zw&^gcz_p_vLFa0H(qZ}{eT5F_5e{ELn@6YKRz|~rc>3`0UL`Fv?ADkz#kb6xy_38@ zsIbifaePTf$B3zq&>DJ`J`oI^uL9Y;#nGgR!)ObP4s9aEM7Lmda$?=rVpp*l-~T}X zHbz4D$EygDjZYB%`6_}uIAW2Kx62uo_)tGfTp4x52 z?e>i=8qo3A7h8_bTfOyXd`Tul>}t|yIKOp;AAal3;ssT%jK&> z6A7BfXz66HjKsT5ktwxTqhn%H?lMKDig!jv+Dp|%ZSp!diI$9!u^}PNlM=}LgNH~* zJvJ#dGXCxeg+xXeQb=kF{M*vW{9PQ zQC{n^HE-H7C~k?GN^4X4CMJy<7uM8hy&H*oea6Cev59RI!q+a;9g|KVEo{`9qpD{= z5w(L;W{L1FSxd{4f>dEjCm-WtP+q4vg;OLI1X)_dm_kCN-7^+8O^QrPOqP+fjmGZm?I2KAGP7%=F%Du2%2quyl($ZS!XML+;mm z+BAGQwRXBz-UzOnc_IwnW`YdF@WdU5RcW?aEOQX-8Q4HcSoNqkoOAo z)qUDREOeilPwqe~4XhIs$VS6$u$e5Sk?;)duvuLCB-~ObY=+xbR?rR=tHt-%{(5a4 zeF6HcLx1nvbube9BJ}7Y^;s;|BhtLS0qLHp1auz)UwkC~5_T6aah9cc*H zzE9ipv^Ea=6p^SYIU+NUQToB}*dH>nZkr9o%$C$gvVMphy&@wnFl?D6vf#790h60{ zo_(jP7S4ekYU!SeIM#E}y8qp-+F5EPuQt8dMAYP#i2a_q^}fqkKJ<-NuX&`-)MEupT~yHtK1thfTceQSwur zn(DG0C9sRFKPc!kc2$3z198PZ6 zqi57+;)8O!etrnsLw>KGPf7s)e8OVV^3vrjK8@KV?)8iy=j8Wl(%o`8+F-tKA0G!2 zth`FFQK+xa)6sO?d18E(j90gcVdQ1C0P7bTNu?{_v&xJuRSKfjmVy#=6F?SGv(4Dc z6rE;SANG#T%7&1Q<%bSIhwQAe zWcb*ceR4lK){`$TS+a9S*Vz*%X=~4ipwGJj>t2vHlg5u)vqlqlhcwUI=j((sXVL5X zei+g-I`P3YTlL;fBjzot7;3q7@|0WY)ddydc~2hpTpC|yj8NA`5(p~j`DoYnB&*Q1 zW@3|Qv2|3!618hoQgqWf&7-5YPutz02bgy~xPHurvhs?tt#an}nPo!y*ud>#l&8Kn z9-Ian7NE^+HCy48V=a!IU3O?$Dn0Ze^i(3htt}9@cqFuLVqG*Hpyvz0K8=>oY!ms4 zX4&TAteLHBeklht{>-wsYJhuUkWvyb_|=(r0$B)2_YEFM ze>hk5*_e_Ag}eTpntHTl_OwCH32*d%aL~Qamz1*l)*B0VId5xHO9SP=fZ#GgAwk9$ zUp#x6ZKhTlV7OZm?-rh6Rqw2~^6?6|-17=qL=EtVG_tmO15Dchud=nCbzc}pvOP_L zQ$%)}ZyH`Zpiy!TapL4_b5^p?PlY4`BhJWD=@b}Q;$9v=1`rRAE zv;4Q+Ab&4E`fj@ceZBnP-*yA|-uTJB_?|b6NBj!$;WudU+Sm_2vrZ8*yw9Se{tP=I zqy8*&>1p44hxVSui%q@phTeYp3gFxNu_O+^!27IhsXr@M$dG04`+yAJdx!R(#VhxF z;{#7!7w^#GS-OBs9~~AyI@*ACmOVdHmebM3`>gEe>DuUY#CzWdwDY}pXzw{42YhnS z#>%ua?De^(_?+e&OFPKp9o}btrn~nn_vcXF>?}Zqodu{plW*(K1{Au(bnkm6eU{JibVGDHeD4h%eD59FdrrrzjpU{6dpo1<3-N2| z4ty^2K1&rmzLU1!Fv4rXY|y zUkEKigJwZ!7B4glLbD(=3qrFXGz&trAT$d?vmi7JLbD(=3qrFXGz*8u=(ArC*jKU? z{VUlCApw0k7EZvhS^tt|#&D1j!NWo9OInmy;uzo^Jkj@U&8im-Y^WD^XArLZT-Ukh z&J7!O(r>T>pcf7u1%nTJrG4o6H{W`J>`=d1yn5wg_}E)4d`}`@`7_x!#hy`n_SH(m zo$jMX)M!Wtv(;Zez@$&-HRtK-;mp%Fl$1y6q}9{PiR}4az21=78o8b)v?!nITb309!z$zgY71_*X(g=K4*A zmq+_n&(oKOk5G+pT#{0KbKwPjpA4-H_qIL`t@So4Y~KvF2bb`gQX;iN^d` zDGX4Ig{2`PAs|Ykv>gceULQ1e>pMs|ERujgW1+F|NWk_$p6T)taXaDZE)O>6fxZRT zSXfc{t@J`|(YKYPe+7GRe_P4-?|KLoC|th4==G<|M;7*S{MqP5dIgq{5@e$>z0!^8 zmHg?2#`H=)dNDK@oM3S9C7@zv1uU=p#{FHTe1Xob{I0f8dhxqTzD5k?Tkeyup!gFu zf{f7Q8>kReJ!QN6zbjve0)4wPrJUYY`E6~H^a2X_Km~i?0!I1P{ekj*Pm^ywT@B@1 z&jwSIa#H@kBVXAD`o?VH-4#r%?r$m$u(I+y>BZW@?<#%z%j6p_e0bCl6iC7aqY)`% z#DyYZ;Uj`Z7`jluyCFV4#Hjt2@7WobEd<#hle*Rq$9!G z5ik!a+YKCsw_-S4S^?_SLwx4jN?5^)&eOqHO}?$9xAEfS)rFVmPrSZ_3m@N%{cNGJ z^h~Io;pIW)2GrE>(x6g9z_7+L`imlNBqQm@GHR$0ek zzp12^Tz9-x)6@RDN;;Qmk@&2pL)ft7$~&dQe00jiCLP2k{RanF^W>4fB+}s$^(=JdPmeZCZ#S?VyIo*%$~*lM%_@16BVwD# zH%#wf178;Qk$!|PO|Bnh{x+QLlOj6Is35=<#%vL-QBu3p8#k+UOfi^(kg@m(TS+E; zq(3N3gSg(nkp8sB?PsqTESBG^bPR4DnTeSRc=b-*j*oOaImdJRRF6Yuurh>ql^tTa zzV{6q;wT1}Z^}6SH>A~nZZ`NP%e7?ld9WO0_`%k)S*yH^tg@(-!Ztm-4jR&_kE<}{ zfhe0bhrMr^YKuxL$r;#b$e^x0+f+Zw#R6BYQD$>gSyr#Y)+x!!c2{Aqwpli-#cYmD zwPkf_m*+@MPHA0DkCKd%M}garXryzwPN&PBXJuvTTY8`7@F&vYPd@wj%mz24mvwN} z8j%BYN|K^%sVy_|S~bf-x9WkELRTM+$ift)jJ|SsGQAMzD{pz2{ydAO}GN1u!z4lo)M#Xb?InYG$af8xgJKR|W^=%tCf&fut!lq^yQNs&w4iy~ zBMzl|yf#H^%O25v6D~V_8xC&nMVao!r%(ru_VHv-L)&v5HDEKgsuix)Th+=xkS zvs*hdqoSiN=`C||i^U5JW1J;E&XN$08GHslI<9Gp-2B3#{DNkfS{s}7$|6Q6W+T82 z*4?qib{cgC9~t_D2yL1K`wY#t>ePiMtzY7$F(?9Q%*O{~NYJA?T@9&R@~FDe*SMY2 zD2|J_#F@10;R%-bB};TtHNuMuwWkXge4^EO@XAx;p)u`V$u(_tSR28DzKg@k6>?52o_$dt6^p&{&zBRs+<3q=V^iS$J(_%A5X*gQ>phtHZ!PNGc8 z*o+E$BlpPX-WaQ=)9t?cxNBMUbQtR;oDM(P8uIGR@wC?TRUZLpTbkE-2s@2N&$3`SlLAV5%$&|JGqLUGQ#Q6^k-(H zD$qs+%D-rPhT2SCLghd=HT#-|^|jN)ul*GlU?1iiqUZB*gdXfZ;;Y-#?3UL1X!gYN zeC+#KApeHfpe>RE)k!`{{NRQTK5XLG8a~W7M9)`m!d4L^7hLI-KRC$?TnEZ@bt zKa@!6td`H~sax};!@gwdS?R2&$ctQzb$fMME|JCS=qzcF)K7DWb_PTyR4e1;L44kX zj?P<8ll5w9%WY7{NrA7w&?0ka#nj0lOrBaXG_!@fUAw{oT~GGxQ(9`Xl4IVMC1=s} zTSpAYZqXupz=&I?FB-P1T^onhYAY%2+k2SSM)X1&?$&AWwR6 z*TeZ(o>ud&Uspn&Ic5y4@8=Lztw19eF^E1Z1ojWyLQ%;b~bk@W6xI6vPFxm!Tn}WxT|XN^g)BOTA)y+^me^_ z53BH&Si4;n!+Q5_XJd|hsoPdDefpyL(`O9sn~OOI4xTZ6K9exg`GBxU{z9kI^(Um1 zFz>|MiMWmv=}09OB+@fz`sAv+Cd}@~=xJHu#oR6hneY|AHCalpWJSt|8HfpU`)b5Y zuR!Kl@4=?C;Z+632CFk9llz&9(Csi$1Os#Bj+DyfG8vZrBmsH5VnFxKQ@~uin+zx& z<(+Pk7z_PJ==9+^lDUKr&H4OVa*pGZNh5r+0^140cbVgpWLZIU;&$zzg$DSf?JQFE z;?w#!W95%(c~vLp+`I<^qOALK%)o2IaH70~kHL9I-~{h@p?E+~r*&||18%0Q@`ajI zHb@8B{(f^%Ugf&HWQ7>m_|}nL@(7)NvK{K>_4nxqtskV6*Vx%m8+Hsb-SvF|?vv{> zBZATpCjn)!FK2c@;xjX>28-3sq-x;f zh+0d^&%F?TQ}3TN34VmMc_dQZGiON``qnV5aUDi-@e%ry?scdoFjM596mSta%H=pzAx6@E_;X+rQQMbUCatD=nAbxG6vDgFH(nAmj-8 z;XL&+8O#{V^5RurV{AW0V(a7`kTXRPfG_UHXe%rWHQgkU7nmeX;N)( z$>rsy_7%oRrH_Y7Umu!{udw_Um#&9gEy>TfOhn9@e}RV57%6Y;ZiG~J~8|< zn-j|AY><6Y&}e~m;>JmnJd-Dhcd0{tI`ptk7b9xYXFjnE^Y!ovJY080Hll1a*d`>; zA^Iew(Mf*3VQ%RlqML+hJ$LvJ4f7%AW2$v;E24B*8^bZ6^TnJA8?du|UJ=Xtt1=rs zTuN&Ddk)?w&h;GZPipUELwc&*Uo1ztKU4QMACqNr%d;VqHr~YNfkV1>A5Xs2n|$s@ z{>%pV?!;$JZ=PXex^lFJ-vxP2lfjzj#E?_E=1abmW4jM#aEk6!&z3yODbmJ-6;aC% zQBJV1DYy=H@R9{yxsNAbswamT8+{DjiO&u7HeAzhQuhL(TOg-T9@%3l_IuXOXR1K8NYjJEED#M(qJbl?J zZwF=_!=+6zlH^zGX48Ls)^Z5VzZw=6tFM9mIO+SP*c6q-!(0knI8}EaD zc!QbWRr-Bri{*QU^L~&9&FRD7vWR!_)9$LUCHuyP*~vg62E|P7sjxP43Fgv;#6&~qin)}+UJ&ZE`f#i8D$1#Vk0nO= zcV?6l|LzMqoP5l0p*WOQ>0^n=)2m7sEw9GTR z042Z+gUybX1NrP|Y3y|wr0Ebuuhm|aLdN0?i3J!Poso`mFCD(>j`=IgJWss*at~#hUIM%N8;$)r`7Y{%>Er=R*W56 zyC2cqOXAe8)TyF-Ho~u$i;3AY2H(^Ww231mFCK>`AIv6QJX?>WVl(>bak>ba97ovF zr4MS?)iWSou1!D|cpdVG&&IvEZ$LDBD1N*Ed#*SOXngNq9xlOOTVEM%|W=JNZM869qLNP8v+f1Azr!fvbE?1m%2?0f)yEZIAh%nV_wHjc)&;dPj;zHyIy z-Nrwt1jXlMmlkbk-M&Rme2{YTWTO`_g0%sj5q)gUV&cMKvMHuX>O{IFEVfCit&c6W zNvzf`#Ke^5WXH$FCAP>Zjfru`#nwN@#<4czf$)g9ghZPq!AP$(iAykshZ_^(ghu_- zXuW?LqxDajU8l2^a%CNF>kW-MeY&S@kd^Yf#+|?VE?^yNP3!8rf!>}VBIZ8ODYX3^ z>f2?L?-+0ICrPIpzM^q%_4WGCkyGdfH{AeJzSZXwox-x|;A>0k&%>+#9QnGN#=%!^ z;`I9zi2&RTl>VKS)573b8jj&w{l=X|*$pdv1IV|z>23AjS-hYsyuj;6r0e;N_2bj& zK)x@a<^S zP$o7%xsdIv$F7ECpJYD8NBU_)*<2@|hB9J)z>6p&b{aij6J?M!(*%#yKv&uhPD)*2 zIb5x2OP9h)I7yc-;r8rBv}fKtE(hBL8nemaH8th6M={4q%(=X#hW>jAETHXZJFLqt zUmne3xf~3cW(f7Xo=r7Uq?*sLk~2OSA^zBPa0o@8JC30sHlkrQgVSs^JApg{X7!_L z^`-ZglLwc-qrUty`P$P5E#G2TRFkgNueOU`*8sf6 z<24trWq57EYd2m;@p=ib_wmwq*9{kb#fuCRP6!eD6y6Bq3BDGEg+*glw%MpH0J8CU z9K>Xd@GWz;z6(4cN+U~B}TKXIL7H)?%FO6B(#dSY@ zoxX&(Nr5p zXQyIC8;QgR(Y3R%jBFbOOEg=H%+6Eh8@C2(vxrie^c-n&z~Eb|CUqQpnpPiw`e3W9 zg_GPREyuhBBcDEgFv9Z+xf-_q{;l+4pWXnyQ^g6Y?8scd^?pd{+XtXeYq`zT2m0QA zh*r@DPL4=)Y=5U+zbBvy#+)1xRQs*?NI=gAHmu*aZGEZO!P6%xrkD0Kfw#SNHCWOk z<>&ZWORY-7(bExSNn}$cv3X!4-zIj%aLX58GZkc&Mvj3gWI9xmMP!~lS20W#7NNHC zGb))MME23)Vh8o7Pf7cltX@rB-GnSm}gI%6yz^Ohfk5`|4S1PReS$+;v zv+_QGGVOvgP0;3Au?9KHnxgL~!44nLTIMJiXejBrdc{U^Tt@SzRkv_3REixgcTW>7CG{*UHLa)mUx^=$A?tHaKp+4gAteO%uXs*(lX^B0=XzG!%VvH8C$?R? za^>1R0KHn@b5H=@0UQnrzih zwl-LFcx6kgpFU2jZzfyraqx=AHtVtGSj-j?>E}4p0kkiPqCwQxGLqy?UFZcEeq8;Q z^hVh-wDqz@I=&NaW&M`;$(DYJvIS2ye1Wos2p9bwWvkOAw$WruJ6BWbhO&iZw$WcR z$g}5YtRp$-!jcUr)#mhllyDiGV6yeB6zAH@W?!Ub(u8Y2|AfLVN7=&q>^|%`Xkb2= z_`Uc!-%s$E04*pKD{9bB@^il*RTliQ^g0;g`-XEe90-sn7!XW7j6#nm z%dD?B-u@H0c7@(%==#S}Wx?-98H`wj(FS1z3&TnyvA0fS0}%`%L1+L#P?UfWQHwbm~6QO1{wKbDm_%ACYq? zN7GSZJCQ(;kdkcn{V0pUIxmwNO3t}in{^&-%SW=Loo8&VKTz4q#)!oId)0SI=3bJi zzN@Co1eUsCDP7>kyl!9K_julcC(x--crz;-wf*4~ya(y`khiq=p=@V+x#bD$>4)*e zp?ohlQD3FP+UR3~;Vms3_!isS%{Ran%Z8i8{fromti5OrWH*(e)(y3g$F{^}-#o}6 zzMd* z!w%BWXJ@JV+tKG1#6mo3)`F3LoDgSamXB8TwQ>x;VQxfP$WCodrZ5YZ`QDH7z7Ouk z-lMcH2wzGciC<#5v7PdBT*SMRjvS?by1ss^NsS z=jSG6w{O#B_T7Vr5AVCSOMXdu)28gXTj|Exi&ns`S3v39WBl}vW#rDp_>$Cqm3gJ( zZaJ`b=D0*_fwLn%Exkf(m@j~I$!{QCHne(exP84L9sc{i*!`#nMx4HpmG}swsp~98 zQ@?w>G}S-n(|nBym#Y=|{=QiYSMneXy8(InQ+y8}BXAWd)`Co*;)Pe``(?J=OR)3W zBi~=U#4VnERa)rDU~LBW@w@OozF=qD+kw)hX1sX(7tgC_&Y*krE31bG>Ne_W;<2BN zbpWkjL`$~(EL>lH#wyhbK|;MYpebS1O$#x%`Ir!eanbsltZX~qkC1IQr?>uWc8kM` z5_LsOBOP7a4y12<0V98*-DmU}mJWmHE7EG&)0~7RCY3iivufF_;WUwaL7J+4W^LGW z@Jyb|l_%y$Mb0sEKlg{a8u^0!HhP9lggjQ26ZEPquM zWPn`ga|#Ap6T4eee|+cU;g}_m}|wkVAhK0=WqnPrME+dmM8d1c;I{l>LI@Kq{(~q z8-lJar%zU^J;(s@Jyo5vqN5>TWX|T zo_^xK+Tnibn9XK=wg~;aM}B-N1pNB*m0$O5d}Q~=eWcv$cBlu5>*~AjUR7Udl;8hs z5VqAifq;D*cR#Xm->+AG{+0A0+ce5j39om+;7(?{^m~Qj$ z-9D|qnV$5$gzT6u)3$A&HNdQHGq&tJ;g(LR5i}RxH?`+Kz_Td2xMeQX}`|oC$3`;lwjuhr*6gu+WvXM>(UPCJ)w7pyI3a zJ~xB)ftCl`wau(uLo6yC$nO*(<6X+cXT&bGfK-MX(|^R%Kc}T9W-Xpk!uq)IuKbah z!}s6fM|pXd=IN*0dH2}Nmp__xc+}K;gA7Xew&8>Jjb=|9f@StJ;88K>aLvr21`S!`|H#K~2BK^q z=e`iSKO%9Yh&J@8%n_Cxv;5H=wO@@LKYsQgw>Ln}sa5bkTmWh#RkS%x1-QuU+gs?^ zX32!f$ZBJhdl&koIh^{&yV|5@l69nKht`rrl)~=)SP(^`6n33>WF!_$fD*Qy70fM% zMo+yrL{f}fhYxV;V@wYqos;?avtP-w(J$W#ZVu5wz8cd(E7)Q4_HElcuH%45C*Z@# zd5>))eUo{)ro+NAx;nXAe+*~PyUMh0!so$=WxNZ!FUejlY6&+~A~yJ}( z52;LJDr9J+Ot5?}$2AghT@~WkNwhb@l|*iaC_K6zjd=A?FC9(aLx@HREb2yYb?ZC{ zqfut>3Um-JjC zjtwP@<5zt=$LKg)+!Uh?IoIcbq9nL9{v5lf``2*a+v-*^cJ(wf0PXe`xy$p)?rAro z#nT;WSvkvsztyw!F}S*G@<(zzPSJIRpcRCd9DhR5JCH^P1$G9kyOxJ$V@SVF+L=*`S$FB?J3gs_>k@9!bBl6ywG^I@WmWHV0iZO1<%>br%c)j z_58}ZxxqF6_vU!Q4dQ}i1CP@x*L9{EK4itAz2*!{L}V6RvmY|*MV+?hyxw9M>ccJB z8hJk|eHDY%3yWkbNY{ue?cQ}mg%(`8z`W++6$R-UeWg7*->X%T=c^;uJS>h1?baU& zihQ~iw>517>6TI$9?B`kml}x%7++dnS6)HA&Ex0P{i)`f|4Vzp=$)~)QN&A5pCRdf zy(+^yH&E{%-Fmw}59xiI(_8-E(fj8yH|OG?u?Oe=9%DCpcfAec?SBdJZ~Vi7xBbA* zUBFB80iwhGJpdDT0O~DR|86A)1>62ZeVH3zXw$J5J?(bWReVAtLI3C+;!M})@Fd&w zBstk0g+Fpss$G)vQpF+kGrAonKmw$}V7iNb3U;WV57Ce5r}P1sNZ#Fj=swf#Lz@rd z6;2*Lv{|=}C|T(ZY~xVF?E2R!{S#n{_xlyEoM!#Ap#BXj$NS-sS7dQW`^;8}@e*vK z*TNE90|vh_cwl~F2)zc|rTD~FE!wwl!J_F{2ntEeABfQdTnS+iM8~n{%=1!WM*EIK z_7-Lh$#FV!hByoM4(-q(JyGl_C8l@iFm!K$Q;Wzd+&iRW`;0{0W{uQoPu5m~{V92@ z8X$=`r9o}O3nKkbFsfg0KUKq7$34y{IBrxJZtjl~-+Qxq!kEV1>;C9*9xuxuYw_sO z910n^;s5A1l`|d`QLT!R^!XUOw7r%29{x_&DYx(i?)*I1JpSb~l6;k$`-?Mo4ct~kVPR}M zt&#~{5eK9ut4pV>tWKSBuDIPLt%}?1-5WQe6(6hNu$3t8^P9YTD6{|CDZe@S==A02 ztKPLexXycZpWM}X?AY~V$8~OVtD|}Iy|>@-@E&p3-YagY!|1Y(BS)?pJtMto)3L2* zJ-B1;+=sZGVYuXOI<9(5$(E=z)Z9Ej&`Uu0>{D7tzxtMg6u;kmXfwI*kls(>G%wdW9PhZWR-8qq2` z!RjZL-O%%s>0niRYLHIRo@Bh5g!wcW2^>bekR`Z;PHg8sAEYQW%S~91PCI#$oev~N zS+74b*`STRI`VwSEA!WirV1%OQly7VQsbvgXp@nH%=cp zX7;2``Rz&yCVi;BRg`L*eR7U%!iK(mH}v(%Tids`xgTHJakZxUG2{AxGm1ynOK+!j zSV{k(6|RDgz5(l(y(^n&_sHk=2H2NfT?$u*hZ+ZqgmvpNp8#j7HLS|+{T)TWnMOMp^ zxkIO=W@cC-B~jGW9TuJLnbS5sBfe!!rpsm>o{%uAS6avPbW40_P-2|s1EG&AUBp(U zxHKg+BuFH0O2T#}G$cS`dvD3%LZtBmI)2)B$imlhJcXBywD2aTnqr!+nAM%kpj0?)_%%lgv3cNph>F++JV%4YU`z z-0C&-@9TR!Y-{ZM)DB`y)&0F8g)W{6KdVnpCC5GAF227Hy$Fk^Q6uRt?s9+AZzKB8 zue!hMw@K?@Ncwl~K%MSzp;>7pqdX)mAjlXNq=g}H zo^I?{@O_V$_6iEt@P4H&$aYZ@VY>hlyAhBT8B0%YCrfOKk@&W<$FMyR0*H`mkZi$5 zEU=s$Hs9#-)ytNGtZsb=8KfT!#sK}2ei)n*h|OAFpyoGvO2t!twERxLr#~Ko>28?j zA-=v_t6j>yKEWHg#P=I0}sezKf2||h*5~Ne2 zT>(gu8GR^55_6Bh%2p`fXcz!cmUnpCz?^SZDfH>%3_;959 z5;?tMWiu$JDI-Xcn!j?T__3Etw|kcR;aS=E`^ap$te#X&_J4^7IMsiSh+fbbX^6(h z4#TlgXkmCw`oz0_gn^R-IaI@Io|nYdwP&P!5A}v56P-?H{+k5sBtdV~2OGoDN|deL zWw(t|e(f2tbt~;Anch&Z?NopNH{1j3d_m6dLHdiRC=o&|+nW~@gZC>1`gweoA0J>! zbC|Vr5gpnIpX82aw!yhwyXFqIHKV8M!`0EIwrx$({8x$SRQAx0&p-L}iygZ<;lEuw zzWDT$&v!gj)~P0^O`Ff*jnCQ?7Pk3}=6ueEkI@&8lP^f$XkL^dFSP_x(I2;)Ee31@ zrErkYCznMB8F=Is2>fImy+)sgLm<4k@$RQi)7nd8!3ZU^XC1zPVaYFzIKo>@=L9FN$`A3GGYinIpTgSFyeU%$7*! z01UBa1?ghb(d>D4jZl#h&Q(&pm#%=8SLsrCwo-jn6z4wN88YdLneeUp(Ri{-&FlWK z*lTisb*3BI?{Z&+(xR6K9GpzwUVUf>{lWcqk#HR@yMr5bM!J_3S;w^=0^g@i=J zARP_g3{jsYi|%}Q5qzjlnIa0F=XyR&Hg_-feB!=*+o4sz?m74rj4Pshm%E>(A8=G0 z*E%fgy+RWqmCeq$>A;3oFXRh+q%ufhBbC_iWTTiH@hNQk@Bw=#cx(2R8;*F2!>_C3 zbq6{A`1;W@M+@*ruk9?Cuh(@i_7H#MAslz@c-?x29qL(DC`n3j_kO;RSnOBrIp59D zwv-FmY;?r#Kf2nmP<`CHe6nc?Xn8_`+?p7wQQ%0wReebenDa&RoD)g0`=2ka=Y{Wt0r$L^2<;9Ygj@T~mnsq55c;===4N(}h0~VgByiNDYJ+-^+rc8{vy&%9$r43SYq|GAe!N0If)}78BrZL^WA=&nS3&A;U(hAr zFM(S(Ke%8H9PHn0cgZ7UTsJy<&V4@}o{voiI`>*&)7w%5ec^c7B+m_%P)JPU|Tu#LGvW|=IH_r}d4F;Qc z#f#Y~vV&y|icO60!$t3f?Pt`jWFx}`(TEEQI4;kJbRA6JMAmJBiF6D7t{&G(-lt+G z55%B!Sby4gHl&}Jf04eewMgH3o_l5Gs#Th-SDYNdWW8wwhpCi)R4S7@R~(62Cfe$rpHiqTkSMx8r{@?gHWPE;Gxuv6_loKx?Vh;P#~oJ7ZV zvOw)vM1J?YGHO|O`YrS;KE8x80kg&|>ke7;Ua1eKeAA{)Kjaw zndNIf+}ZaQ7Lw~VTn}~;sui$7TZm6-KhK;;i8Tkl%}w62S~*)s6Ca!Sf*q9fg)fLsRps+e_;>wyBz+?F-4)ER1t|PP_SF zE6?MTiJs1>uV6Xv7F)T!)G#0H>AElEKjc*GZ#&ssQbFH~u;C_ktdUJkuHT?F43hnJ zIhE^|XPCr)zdvkf_a5ExZ|Jc4Al(m$wfS%Ofd|Ezo_k2@KjVarM~?c39Q@D7AN^*wrH#wsvbg@K{K*fhr_$q@ z$AABE3DA=s%%{%dzc(y{K(N4n#nV@0dZoG!Cj3KnTE?@9RsXagZm2(Kk|O>K+R2r( zXW#p0bc;aAs{ev!$wzY_w)r{ie5XJA7FP`a1uJ4j`P8Y^Q>XPRotxgG#qni#A31jA zA9B`qT6wQ2Q+7;WoZTXGX1hC|I&$~26R-XE^~5Bk^E1MIYqc^#TfIg83-+Wd^jT=1 zOWz((-_C{h^x0f!IUZX6_77RiK5%f*Q}l7@`_!O=2L?X{ed*&*f%H##l>GG1fc@b% zngxscFRd7fBUNe@yWp{Z$j>dyPc0``|KHg%*MDcrSgZL@ZCESD$0SV83RlA-rI%1Vt}Q-maAUfMJ6% zR0q<~{;=;$W;V)W2;@f#1cF@$As5m6;MRF`6WufqZl(9lgInMh&l)dC@iL34gj@8O zc`SA64RQF*+x7Cy>=qs6gM}t(nK!Gpeyyv#6?4Uw1`$aS0wje9%*iT5C&^gIyd&?P z9tRf52{o7Gt?Hab>huPAeXC2Au8S~5!XmP65m_bp*2nQQpi5rqqRy&PXUSU^)qE+( zFVg%xzjRK0nd$+uri!dtB*)i$xyYMFoUf4_iD!P@Ss+#O^aHAO5Ek9#`N2QZ^X4yF=)=|$fvTqpSD;&gRd zL^ik`TIN?fb^*E=EH9^l~G3@xO7SIhs|q+A8{Nm<5OOO6v8^1 zuTh8sf*qbZ6w~*9R5G$XKXY+0dHc~D?=91YbTi0oFDJ4d;avqX>pN&oSKk63t6y{4 zFEd2s&@HqRqn2bgV!-npC!dcI?vY=Whw-@xd8u}7dbBOY;LuJ`XX}40+DYnsJ%YA8 zEA>2VgVNLEih2~6yJl5XFF&~P3%UYs`(oq4<<%9lT;;_*ipHI$r$~#vO$WPrWff+% zE?#&`^}L-!Ru>ko9UE9* z`(JJ^j?vhg6#UWLFrS8r_uF)2JfA;4BFuvchP%aGs6lL(p!}TZNIsp8O{`;6Vc2M- zHD5~6=EKN4`+o1<^Gk21S?wL^?DxyA-QN$)HIoC8p0P7~^_ta7?A3SgPY?HYwr}U` zv+I{V{d3!Q2rI{!8JZj#;_`#<^23|T=iMlgWRw>d!uR1qyyA9_3r^e=*Jzla^g&#q zY^9^w<&PsZO=D*?h^NfiL%x4x*Drl@&9JrCtnyy7d!a6NXgPS#FT46U+uc*%dq%Hb z+((^PSFN<+^3~=}@U^cpAG$L+?QGme*}E5-l2G+OReSf+57hsVP)ImimxkwrU+20kkvn{nA1q#JB&T zc4m}?xf^NxlOJC-UNPX2AIt0!5b4Pv9mC^`-dI~AEu`N^*vo!=ct8c|pgz;KWbGS8 z@q!;r-pdaJtDJ|zm45QPFE;mNh-cm6Sq@B}>WDS5+I|2V;eDo3;}Vq#CRvQQAr3hwl@Ba&98OcDgg7AgaoU~|+Wv9K{_+ct^m1)7 zJ;^pvg?7@XwFNa_*3}6LwTV9}b0UJ1(9 z0m&!V@LwO=9gfgdm2d{mRMJ%#?hbP*vC+$~1oN-bE7xeDo4?@EZk`h3bX;}M8ys>w zK^E9vm4bzB_=SxqyPX#uqQi538%-2r;PYa+N}-Ef_B9-p*MQkQ9E>`fo}r1mKIQ%s2Xv7pFfiBUH|O#Ec`Uz9f#*C~4f*i7H2PEK zfguUy>cNX}2?=;cYe%*G24ovrlroG<Ns&_$X^lYH}xy=!xBKHK}|Grh&D{ks(fUO&qlX&QsH%#(I;i{TW^5#SU= z8yRyB=9F}SThGx}<4=s2cF}dz4j;k{y4Z73vL%#GKG@MrX zBlXtSO`DdtCikhgR82v!^X#)HAe?MgZ_$RC$$er-(`E&&%iR@&mQ)?_ zba?h8cFRNl^{m@B;LOUrM!x2y!JKE+93DQNt!;?r9piTJLGENrw8>~ttmnz5#fJu0 zRH?U+`&ySbZQ5GBmE5NdspG575Pss>XP==ziy`hKRZ9j{xXW7?G;8Yl(XEZGyPy3R zy-NRc@>#82cn9V8x!hAQvH2ZV6Kf**d03zH&8rsdagIYqd2wT~#sYP?g$>yaYz5eC7nbg5lGrSK_}jYHJNI_O(8j zvo*Y6V(ligOMKgsv^)*3BaNFVOLQ^{!9?Ej;T4~ucdFlTys&QNYB^hN%`lUf)K(lb zIjy#)SLpI*PJj`^tu)M7Qvv29zpdo=_y|99CADLOb(USc*D7}hFpBQ9e4SH_W>MFz%XU@QTQ<9F+qP}n zt}ff?vTfV8ZQJ(WUruuJU7Y{i?94oC-|XyUB@<%~Y0}OKdxjai z1(B+mz0n2{3GbDm;MyP^>yshU^}vlUtTFkS1h|*vuEDbI>FO@E&1)((=Nvos^`R}z zjq%ES)_w?J&Mk*3|w>HK=1cMCJN7&tvYXO?Y*{``IHWe zi2{0XC0jI2FprZ;5!Upt;++8R#9ie*JGsz@987ZU*pj`=R&3b>E1!loNBEK{h7Vb- zTaUfTKoh4)myD7ts4@Q>K+Z$bq8!)LG-e*Yk@X;9`?SnTo!z+Ez7_6B{Ac1Kq@I+QMLdiJNH{$h~19bAfuWb(KbsX@rh?rKZA5V6Thf@xH zy`Q{$oQ!1qz&3R6W3k^*&&odAegC@MnTHMwzU!4BtR4IrCIl*31y{>AJyK2e;b2I9 zF|<8SFW#C(eg`|fCur(x?J}(7VA!Y3V%f$HcW>aPHogMv;{SRz9ReV!hGC-TKSCJ` zbSb$K-g2cMwTCdAEOLSwR#I+!9fyx6iMeAq~`VY)@b45*-bmd|Vw<-`8BFoACAI)SN9=*IuyMoG<5v8)Q|Hi1ZX# zGC2e?tUhXzJJo@o)qb$U-JNTe37*P`0gUatM3`kU76Q6YpS(q$NIqC8jk!npe|%jO zzLe{lzL%M^6s2( zi5wEcZG|PtJVziU+}&-C)1Q>q!~r<6AB zVzT$EE#W4ve=M{=>dhJS53UjY{iu!oV=d@0OtKME z(b2`6$a_rfQs4V_a|(PD;h(Q1&a;H@C+r+9zpGPxN|YRmq_^kY-vKROEAl@=?m0XG zvFB~l>(<=PTkzKDxsOjVMJG!K_*bpDzO=5PaVmCK>T-ceafa~1a!^C^_&Cn6TEBiLc7|OUv45c6**@Mw(k;WW`{Hw zcbutnUSSV7`^;ACI%KotnpUl=@3yrWmjvrO#IfET2U@SGnzhQ8=V>vevi|gNaE)-d zqp~f%QCIU8?=%)F<=x)iY+qs7`+ql6NB7B>`p;J3AFRtNP}!E663NC!UatJI&)^W7MG1#S2dT@mC|aFn=g)Z6N{Hh|77 zZT{vpUX&+ek2*9xP`3NHn=w{+9;^p;cgc5Y72RE$+tD{qavH3hGEt8H8*A%GTW!if4@2Q{}?Q17rU z|1E!sTP5VNemoP^8u4|pnjt&P@VZto>dYAFFIl-h+d7{1VYbEJ;XywdKVx%dEe@`n zTZw5-fWki*ei`R_=UmCSTAiSN)4N*NdI;k_lykfO^`mn2R1zoV@ds&&`9;ok#AMaB zS*V&^_p|RBVN9tH@s~ig$fWW{EBLHTpfYU zaW}l;inr;3jX!V&YNM2%MRngo^~T0pADVB=-QH0Vb*2q$>)WYkJy=dNJcroDSl)qp z=~2IOpL9NUsVaevH1&$=s&}j*O-xn4EdeGTPzzCfTT&Wu)!niyKgKPFtY|(BxRFD2 zY0Y{)c6Z}T-5lnU37?(MTP?n0ISI;Ks_VK=g0x0%^+BvI6EhtaBzAo5%Q|tY;?S$U zgRs`MVpfN1kLt_49rO2&EQkcZ8KEETgpBvYo1BIxvn2I8-L0oK8Jvm*2s5#?nl3hE zjfSbcPd8!`OospAmCROgz06_I9R5A8tRA02%gIyO9bRRY^aW1Tb}661rF9&}(L@;} z5!W)iK7j-g+majpl@qI6aGrPW#I3FX0-AVTG!oYKGh?9;*X4>%fN$sykJ#9NGvAh6 zxkS0A0Pb1Hi#}dg#-4xZAmW>bhPQD#{sx30*;gHkYW+do>8~>`PZ6%!7)+fnYnpzs z`m0NEChXSLGDXoZsBJy;C+e5K6FFaxR+h_e@1d1hKXZX zU4F=7sd(CSwUWf8oC^g$TnnUN3JCYe(=DJSWfTy4|lYLq`kafSo|gA$9o-c*%Di;-%I_#VGXYxNCw zK5Wr&PWMZguc5g6k))=TBQu-0MCpRSYMg?eN)=Xp%=ikIf?rG;iajk9TpOv{IxW}C zm{8=4UB+AOE}xy#lu!wyxx)+8QtZ zLW&?G{hiRsGDZfeXQ(hFQZ9y)>X4yY_aT_}Fj`FkKVH`;4DsGNqw||u$03-~08%Qo z`QTUQWD@Q>FnEO??|>ySkyjZYpc#``yRqAl|G@p8QS)P#?8pjR*E*HeS zgSn^o*nCNLxnoB~wx{J;!a?J}X$-Dt>~*V`+sGWX@c4@}29M>@=^T|<^fmu6kw3!U z`_=h!)Y-?uebSM}%#jpoUI9LKg{CAPqm-Be`bbZEXGpO5Kc69KVlK*{FV4FJE?S4= zb~b$bv6iR0WgrRS&|NB0PV$)q&Clm(*dwS~N+!4(lsjd<0(dL))C0_-I&=@}`6k9k zoNv=EmU{C+1Em?X&BM8qE3@@XE1DHfb%*$BJ+t>loeGg|j+`k1Q=Bfe7WvOdtouN} z2C)W=b@64|s@ZR0w)=R)>Y~T;>!t1a;W#{sy{*frcnHa~p_yfw!Q}-I#C4>F-HY`$ zK2aJNXgV7_@qJPkt@qqB7T6g_Y6SzaEuikNH1+42RhYyMP0~g)FZQrh7eCY6)m1DY z@wFYPj8WcHZEIQvw178?s?;U)1^`v$_s6Ho*HJVXGj1HjSDNZd@l_!=qFu7QtLXH~#>~HG4+c-ocnAYjp4G zs*_FPg%bQynEb5;3eELYh6xtH5{J9qv~^pGaoG0!@nSWq?Nan8bftC)T7g#b9jdLY zmeBT6yCPY5l75n|t%5Cay#L^*Oa)DvQ%c3qXRTPa2eUf;qNuND)4vJ_$C`-o>5$e8 z3Dslw$;2#qh@WZ~#NSR0b$02!y(`}B*D12|(2+Q+hC#Ubdy|a%*D}mT5Kq6so?d@N zKgS;I9(f*muuTYwI3%DkRCkpn1E`@^uLFj4K*$~_J0x{arxi@CR|w>G+F9eVJ`g_PZ$@0j2!a;)=2l;W4n6hnL}tI|@0*|_zP=~9z0a)L0XpkfJt(g4 z)UzL^Hca(+OF7o(1LhwMGCZp(3y^r$Q~cYvp~xOm-OX8+-3MA7Un$|AmF=Y%zns;M zqGHzuA+@Xc6pNS0b@&)I_s%`|>$;WoyPKD1wur9V6(B`B6t{-U9~)k}t?*|R*Jra9 zJ*#ZX7CUQ#I6l0(4bm~&)SV9XkE5YT#ZQq=x2xYnZcil6bsHUp7G*j6JwJ~(ImhoM zXR)7Z$`*e3YiA>_A3kHxw60AJJ6<~6ldco1{ZIm8SnK+>2=J_|Dgn7()b&VUxNknW zC+Qf*?#>5TrU)yG)Iy+P=!#!6S}&)j>ToE5td?Z)GCl%IW7MZ6E^Y1UlOoy~=i^Ct z^^ijAlk%`1vP1N@v9I~CaAdGnp{r!4o8v^KX@}VN(O8M9K==T(S+vg#4%GWqZ~1%R z436_RNgSBih3@Q73%#~03{MX@+;Lxt=yzc3lGSMVMP-XZ1!S+=yIfRf|HoQqNZyx| z8MhUmJa+d_`fu)nYpb&aX2cw>`)9V8<~YA!+xJhwuZ+Jg5AlhYZhLF+4p>$N`22Ua zn1TErn{Rg}UBtLvDaEVXw5KcCNiky< z`?{hGs+Y3vFp{l*` z638u1jC>4(z!dSP5g9BEvH{)3z3IKmWhvy>jt5>Is09fwB<`MA0@<#vv$4Y~wNi^ZNGW}UZe zZznzk$25i$J_@)N>UUZ*0FaYYi_hH$J9K0CCgekU{U6ws<$GpMy%w(-C;oIj`b}S( zaQv7J4_|Un|GIPW)-dR1BA-LTCoT`9{uSA>C)xuh3Wfbz)P>_LAf_+Rf2q?G*FdJ+ z@(nw?@9r0r6Wuh*+>^$SA&6qbswJI;AU-)Cxhhjo6*lYYS`W3(XkKc6Ch$W<=*ztSX8u?Yz6oJO_>?76Q4vq#& zhjox)A|j2=*!QcM+-5YJ0m+=AU6Ni=XRplSHe$21=PD?mGqx0lkNO^P3m%Kbyy{KR z_=kC@3)k$Te*Wr7Y>aJR4NVj`z*)Rm`q}(mciE5m zyyPle3@RQsv2;W7441KV$?mMp3R+M-4Q)~1&Fs)$YJO7G!tb)|M<)(-cZP=4A&0{B z^(F`_8fKg5_SnN)S>FE=VYf1KCg=zDZ5vfhKSJ8A>07hgKnOIW>I6l41DJf z{LLfR1>hX-rhs05;14`}{~x>^w%y*5o9wUGgN7U5%QdlWTh@&|15{h_t%P>E!q7UK z#pCjNIyDfj!?fctLs-{Kk72G&xG^_jfDLi52aen}IaFX2(I={`iA$Y6Jc?-ELrk*2;Y_-B znG#e6gMIcqQ}8^$9z3op{Pp{0>(&lq!iug{ z3nxEyXo{hh-kG0&Nam&c=a^cRTbS3GMWKxD`kj-^R&e!q_K>Di(=p5fieUv+_x-cqOQF#?m8rzmBR!w&&DQ))#7`8=y#TiHRmIn~W1tWm;VSz!beUQRDs|3fu`4jR*V4sJJcVp?QhGmhgk| z&2J^KY*#}8TTRYGi$4$%uWpU<+<2TXfdI)=M6CMUflQ5-7>%xO!`WHFwg+3>y3W(S z6SD83-?k_KM6HG`lpZ#!Jhc~D9yLHSEp@o$HV$f=q3TT8(t=nwPasPPwd z!{JW@)|k1FP^>B?@QsDtR$-D-t%A`W+E&!s?e%Nqavy?fd=tF25QNqC4kPYQ{?DJ; zzii8u9FiM9Cdg0uQsQP$tLbh#T_>C$@<3ZyDWVCwSQ4VeJFPDI?~|DVTpXIG6K0IM0mniOz6`03(>Ty*%s>%6F@t7`U>qE#D=HfLcdG2h3w z!=>T5l8fBp@|WH1dN9)=@JA7x;5mDQ;B?nV>se&@(h8HW{KsD*{(0DCfiS86eRzF# zxCGv#eIW7QU&dyqkr0!P8U#?^Rqu6aW-%}en} zT#Gv5|M35U+DsbRof$3Al%8C10egnl>guh3TcDvmGj0Jie{Me1|GCoDWb(_DtJQUG zLN)U}?l4dwKI3pUlIxm%L|b}n5OLI&n>~e}RK(`IUpsHp_?78!i6NF@@U$C_n!D?F z(0Ceo*w3M2ui&fpd?N)+MPJH9-14X;A2`isnEphkZ%;kMjk4C*D7Q!j*^)FmT+!Yy zU0b8E!kYd32wl+%X^wX`CK1w@h)ZG4D~9}Up+i>f0Z+z9(sRm>5;`&N1abI)w4I0G zXw``S`elE6Ld?rNEL#(KmCth_c)sZ#I)-h{M&h$51gn7g&kApGj!9jEQ?YY};VqX< z?~#nZ>4_a?8t9j3)M+TdN22|x3=)r>QvxQ(>;7&;ZW?#BL#&0@r~T>lEA{+K#UqvW zsEf;u@&?4|V_LV{+jXanfEKsi@!>dGD3w=jv06vLp~E$Ly=n7eqsg#~fzCGfihTBK z8P0Ly$17bgsu7KtW=LF$VP5h79bOg{VOUU#K29>Tphk3cD^eAfC#ROHVl2RvSq3XN z36^UTs#L|5tBR}qJNc!!^ndZzrkdn1`sBsD*(t3sgd5?!Ghm<2y5JbQ?f%!!9;8CN zwfMy45}WdLj|s=h6aEs&Mni77E|-SabIm`iy)Dn~lQ_c4s*elX=klvE1#Hh?biCEp z@38l&(8qMlm?%6(W9E*=8%6k$7RMmN)#no&!v&SYl>G{K zhn!*Qyf`;gZ%6;(k8DN8Adp?=5?D!|axB`{t%cW0ZKCy~lsAYY51#;2rz0lvCH{rh z``q4^!OTmK0G@2-3yLrw)|0nvVyT`u-A8Cphj=`wjLjV7l-;%JE%CVFri8`*1eitP95xk97J#jTcXY*N3wB#jlV}50tiPAE{8Z zGlcDMIriY((gSr&VdqsxzvrIXl{bb{ii;F-k9nV`6Zs{Yq_>(6e8eSaqW`5TZZK|T z$!$rdzP`q_<#|d{>LD_F_%PL!VoU1++1bYu3Q{&wrgREFCVLn$hAtXWcFTl}7$4_Z zhf$PAN_Qah*N3GgSPwJ&>D+=ied)1*9Tr0`K0;=3nW3N&``=<<9#1TM9FzfPa1$D< zB9rKTMxr!(k?-8&OJ2O5CV@_g$er@WQk&_>th+13K%YXhBTzsW|0A;&b|J%=#W}D8 zSMQV9v8(?X_E@PXZZeZ)`gwCN!0vvifL8M6=Po8C=OQ{AzY1KNpM(=Adk0`w9{U1P zx&kh3bUQ9|^0!P#9-)5V-_``@Vu&*gsmflLtX}6o0o^0T5OtXhGxL(aw8f#C6f|#Q zl$r{v&y zRLUyJl(dkKxoExQqAdFwfPYP4CwZS>RAv>jO@&2ghY^gYZc{O$RIB+9YVmkn*yAkLMg^tJ+tS$8H z;e%X-!}2jux~N$8uY3rGictEZ_1K8TU8pQ~aY(Q6Wd3(~H_&R{!ETAUV4L@SVYIMN zqc)P4sAiz*4(CWp!sa_jSFA*(KuPN2tv_e>;_awQj^>VS4q;yq7*Uha9%{H!-r=+*@tQ&gL&Yh5oYTHvYV)QguTz4(x z?6mG|bL{T?t7_){#J$r+uLhKD81?)lRw`r4zU>dEqbJ4XZ9KXNL9;6a}ZMBV}Y6R zE&Tiq<9=|@xK-O}8*}o`{XG~D;qz;o%kU%qjT-e~QzEciqKk!Bl+g;Fq+nak%*hh# z^_2G~^W*3cP=%a8Qnf_{|9R_)ul>@6O=8CE9M_G;wXy)MDObHr@FmcEvmy3UFAMQU zGKgaopU)1K%7ZV=W#;ia<5-WdlYeU`ru=2ADdIQ2;4zQS-x<#A{bR$VW~)alPNb5)^-iJ>oXSS}nb zs~$*;#xM^oQdXrxc1+B{dqaLq8traPO+HO#8pGPyvbKHWbZIkU2vI*7IpMx_-p3KH z*AKIFW9J!EmHa?QGn?e)9HF+;D-r#!!aD80l?KtrnO@lNNs$O@&(DesMJtvASTiA( z_nd1n`-dAqe6j%18#ZuffB_dMrSk}@rB)ZX9q$*39B1H*&`WWY5clv&9uilP1db&lF(bbUJh=E^4 zMl5Id2Aa8N1uNST-Q0|h$k%kFU0w5}LoVU~RT+5De5-_>SnSIhscBCe!){tN@-i5z zfNJ8-sV6I$Mou9!r@J?8rKf8osSefli= zyDpa|k)id~KlsYawzC@TR~!|A$DGG!15!Y+n>jK)3@J!|YPue>%>&?`@#<5n_Hntv zFtOiu^G!a`r(cxWFd*A}eI2ADC;OZ^l&^8;GmbRXmFw*^j&!r9?4k&QCh~oW8^ud; zxC_(wIs(KCGuPRkRcRlvck~-A67%2U302ReJlPCO@fb0V`+f=c)=%nl$J`1$f>eY2?!K2wRgp#d(rT z+DKo4I#%LnefTpMA6w!3J$wxdj&bg&Q#AXUL=SUGq;(dW5=Lg|@r8_AoqID%%#_9^ zCe%Y56wddpJ8qSXG(H_vgw1eu!<0y9955*35)PbTr^G z5n&HX#5bk-I2c+7vU8+RhTxHtvW6+4{Jd@g$TzSCF|B*_9)~Dpum{1Jzpg-eWV81G zrlJ_{Jws?9*(s+5;^x-^uYN?1Y3Ev zEHklRl}8&q;O({!X@4ZOuVp^`ipd-mN3eZX(XQ=|@#3Y&Gvzt+E+~t`X&Ci8;&mcA zAYJ#?DuRyr>88twnf$?VTqJ$1-Gy~$>yLAL5Q=a9JHJ5?y})0xe>H2AYxHH9jNq(( zygmQhq+7Z@lRcTe%-itWrrX5Z40&=W)4-|t6GzQMzP5p%*bzR;AE{x!)|X+o*tg?5 zmdKx;EIr%b6HRRI1Dtn1MNk6tuhweRIbMUs*~Tzy>F~8@smnbr7AZU_bUK}VzusUz z#6oiVdYH~>D;o?Kn9NR%ukM4vRVnv;t_+hOS`a&vm3hm97g^l5l<=3=5!Q-ZaDC#f zvAxJ=Zr6$w?sWooZR7^U`8McSpVoYBM;=}OG^ORQ0iY{wP>8>5ER|5!a;JLPZEnCn zYZ~7UpzF#^T{Td8n7yno*|sduwCJ28Ri%M%E>E_E_0h3ioQmLJ<_X*Rg{Ygg$0DY0dSP2+H2 zF9D3S;S01n_mw@&s1RWb`amvT%SvuTMN<3L-d&oRQ+id!wl-N65DTYJ8Hi*8^uG

    #I+P8(;>5(xZe`@S|F6U`h->RKDkE~iovThmHpCBEb=FWHl>6DJH9=`cL zWAYp6oW1_%XLa5e80UBzXLjMc!za#L_+wPJ&X+R$aqY0vqbU)tH~kO>cwRscH6Ip8 zcL-}XzZH-9a=~brjcp47e;tdtV#g*EhG7r{(OMWDhs@73M0-Zc_oq>DJu;B*q4wzf z zpvn4a6CIN#aV-Yt!TVy&eRBKU@TDIGvn`PXJ6$W{Lk|H4xMmP&>2R30(``KL%vtc#ruX z*^X*KNwl?`ELO_zlbSt$YCoamPnjAY&T~$ldeC_71z3xU(yFk4#GygJ)6UH37AiOx z1ApUW-4yMQdP~={yZN%d85m4|t@$d`pP$8VZU)D-(qkLNIf{zV3hE_QT`;Zd5NdLg z)ODqU0UA2?Z|3qxh%K5I0VA$E_iH)~^G+VcuOE&K!%S*&6T8+b+o(4N_Ue+&%BtZz zlGT>>oeuA-ObvVE7|edL^~y+sQRm5N)HGI*Xm<`ALn{bzKZ_L5e%kXk9cSk@ zIc5nz)MB7){Bp3{P54;ku37wg6}Qw{wI9YbCPG$Q<3eRzX&x8DU|x%DpXfd zjCFPg>10jKo`~S;Bk}YjQ~Me+FQ2^!P+1EHz+mit^Qbv@W6k!d5(*VP-mJ5(%0Ckx zjJ>8OZ#TkQ2(WjaQr?Y^|^)O9h~opS6G=5 z^Q;V%olICCd4Ca=oL_l@c2EBC4}J&3lo?*EG#V=uYI>VbOXIcy?Z&{lbNelU+%C(u zD-{abmDh4YFGZ$W@yqx{TBqde3>bAjush=}B~WQLT{FHA!QA63 zU^wFhrX1oflC2hP9Dy;EMqwo>tw=dFQBtvtcEzdoN%PwyAU;5!BIIS4C%wAbG821x z&a@FT(+W%kt$2acBzZGxM#+W@s!SBHlQA(mEou)XnuaTzY-yaqhYePcH6$ULHdOZj zimpNObMLqMhTd9627rRrN zR2wUcCzeBw=xK7<&&rwkd)H>h`|X%!Y1U((ttcrIgl`YX6(2q=W(B&< z{D|qxZ;Fq+kL7C%V%cc44yMw;_A z&Wf_bTfa0N_02jR)rItixjChSgRwB$B^?~0X*lGLd$T8jue7(rr+X9Lsw}StL0{0Z z^fe6tI_l2Dk~uIc6$mQ2|IpwoYaTVdapt!Cc3;YB^DCX}kWp-3an$2vRMh07m5tN^ zbxP|z-KNjyVeIm=v3u(lkxs+vKnZuAuDc+X;zLRwff=TvRp4!w!f%$44L6TtJ^@9r z=I*Mz?FJ>rXmnBK?zz6lfX^#W{_7kK`Pp{;W9d)I*S+1`KYb+a2cwMgOaAE$|lw>ybqJI}%DJdgXkX0aj| zP2qFaUK>fu8mWViEqlvux1Jw1o;w>ivmfGlsT$_69rOr0b9;~7ZrhkeclQ8$!XW|% z0X;-Ou-jkg1_tf3{ZS=pW%ylDJxDbw*0Dv5+Q)2N#!zffvZ30rWFQ^tO`PUZt6`Vg zP*2z&&sk>%Q20nNztukL5dZ{NTA=K+L?Cbr9sW09q(d_LZsc)EsMo*_ALx^Qmkcx7MYpj4 z4KDWpm=OL+?DDLT#PwWX*2<1fw)vyuUx_jDo?9aq* z*%n*c#lBI6Ar`F|zIgEe`Vg5+uAxwQzkHhOdNo#PgEDfbS>7S&+su=2J6hxgJ9 z&Aw-IM>`hrj=#kJ1HTRKN@+pwa&(qVH5{e2bbJ^5fIskCz;d`+o5OW7;+Ih^=cHcm zF(V63%fj%Gv^5S~R`1ohx=ow_Em}4H!Gn|*Q=GNZ$d`uZP^v1v?t_$jfwMdx+=&z= zD;DB|0c11?OIDNuzC6>Yxl1UU(o`fC&695paM7;_JI5v?hP7u$6vkuWD;y`ElRJnnt_sRHeYVr~q{$gHkZWPD-Vp)fD5R`Ql&H9r zC_Kw?J}~ z(F5_F@TbWY4dU@b>ox5#Etm9Y_Z5e$9^q@$%b;r!iv(oo zr`N@09$ea`(+Fp5zDrugR^F`%_o2(j`Aq&w`D{Cl4M*x8pGhP9*4s#y{QP)qM*3iInqO93l8TML@$Fh|x^`#508L!%8G#1~>*S3u@)T64`4?Lu3q) zXywBpbPVZBIUSC1NFbFx;jES|>JPD35YJTah?p@;WtzEp+TjGSSA^z2%7;}v-H6~V zDUoDPlW5q%Bk-)14gHyGE?KYG%B{(t9r5@YWa^N~)$td5e401;1)K;QaPu9Z>%+P~aSIsrCHY7K-4~XRuWSBjjyC@b&=C%YwuUg<=9#RT74c7fe$qu{-=s;fwfdC zbwTEszq@>d#o4JgvFfElI?(`O5os;rrNW#IK?#^NC55h7HtfQhVt-#sXcntgc58W) z;4a2sVWN3M6@k&hBhbb1Q40w|9V)2~0xg20$nP5j`d~~r#Sgz0{6rMWX5J^%M!__i zTnA7=(0;AKD5sD_R}sq{2L@wf!OZ-iC@OPVJlfy#f|*5kBFM&Dp*hsE-NdaI=Sid? zS{{0p(9atiu*AVj{Yw1+B#0^l>dL^9Jt`F0_1vc{!Q(jaLxp=<1(DEI0EY?7W*Npj zjx4&Q(_u$GO+@96$k+8P&EFwf^BAU)Bdy}-E}NmuoBn(QF+L1;GZjO#9sL`Y=q#W= z!HLI{(2&ci(Smn%V5~`br0XdOCx-25p}`}M3uy!M-&2M6d_Y#;ANoH@>!Uq#Hiyw+ zLpu}$J9+${W{j^H5{bDA^P<{sDDCWJeu$+PGq-wrAkmNG`8z-4Ne3bO-x}+rO{;cMaKOHvB=hMI8_&rAECaQny8eJt|n2ed(f=2UY0&3+sRFVWi(^(Lq5(n?f z7@?UAu@n$k3fW+x6vWHn_6QSXPzFHKOCW2iNKNQ zQ3C}hg_TL9qQVqXD3FQxBgjbPBO>ELq5c`#8=?^cD_UowiF31* znWGc-_Ud93o|;e6Gb@4+hkXWg)JG|VEjF+$ z5G^&f5H@cVQ6AjM7ZxH2n@;K<*RIM=G1t zShFK9OoNAgqf~8m1(HjD1`%DCcihV@WVB$jLr3}@S%xB@u`b^Ve1;i9KenKUinb4% zWQ6I?Q2r;^+%7T*`W2fY23a^i&T0&VL_XYrvak}nm_K_Eh?GoK)WEH=!4P2bW0(qs z?p1zD+8S-S;)#N+y`aL#1jXDyG z&E{)(k}1s2$734f@yga^6a{V4fah^qQG@4ctlH9gd%C^jtVpg2+dlwXnLw!?6@f0) zAHHP5++G=`5fy_HD0AzoXlrh6n_$j78gI%#A4PH;6na9EP|H7uLx~-=mEbtg@7{@F zlH%^IjuD$WsqQEm_Tq(12@w)0Q$NsOpAokA$B<;EcIj^}1+-|dA|f0aMP{vfAR#N< zkW>I@xM8l|-*hl=7KU&E#vq9B)2nn8_z+=KQ=~va0fcocX?hHlC}B{4a5Ovs5)vTh zJP+6(10GZmEifR=+W&Ud-+$Gfew2hlJPE|G{{TM3Jq0)*pw0+%_|@OvT@)D%a_=Ef zlN*Bs3OWF3_Fv9L0Y(x?MKq=_9>E_>Mo1WjM}*P#G;?xs5O~KS&P)adL52~Ji-Hn$ zxa3_9*f|-zCLlt5;G(we7akD_&WD9b+}8>TZHY?l4-i&G-!m2zHst3w1Ot(FNf16}_B>it@Cq0#qabP*!H+e);5pYv}!U2W{fZ5mJ3pxYs z)S>Sgy*LD#eIloP(QV|cjOF@TjnUSl1a)aEPw;UAgK*5YtSq0x!$WGdmYwt=*Mrs0zO;l~uBqkRZEiV-fq^$%Dv|0iY9HxPxqA^gTEF3f& zNjj)z&}jJU-wZSqQ}HO~(^!%1!8{Z)RSBPMV<(^|eM3@?{eoRINyQIA0 zK2-6szpRu*{w460@D~2hTf%&mAvG?wSSd`rB$weYeAne4GHb*={UZidclzK?1b=Uc zK;^h)AZCM5nNx;w0W0w!PbTgEc9#)buviSe$2`4Fesky$v0CWELs$`G;HnPbl&*tV zS!}+0nM)hRDKwG?&DQLCg#9To2iV{&(unWBtg;!FNC;~Y)ipV%UD4`yNsa;#(c}1C zfIry@qT6{@=+ZY5;QQ{qNcdQUyQI3_f7u*i$U4%byrR@okHX5yqfeZyc_^AvaVoxj*eNfAeT2F{TM)God=} zCSu7!`aj>tf$(;Z+Ed5#?Rqtq5Y7*0fLeHgl1d3LvjP2vupUbyZKU!E?w0K620@kM zhDDWIneAMVIz~{I{a7;Xx3zPKR{m*0#z1AgvC$bR2cvoKOs{hIeEBOQXjl zbh>oT-xhuSp*d0&Irwn;9fXox8t2{}JBF1YXlgMv8Z$qo$63Jub6LyfwStJoZEw=U(-@rNi}W<)tTNMY+;xDB*dt1{DIcS zfxDv5G)gxloS%B4R1BHl(Wu-!og@;hnh}OS0Gh5X9EQWPa#ArW2-?4pUAs!BEOweV z5e1Q{IJhXdTvD1fOgqU9Oa>tEZ_&J91HN4KWZZ^OaRp+OxQybNZExZ>SMfAVAYO<| z+wjq>RfaC+0$IO(XnRP&9uoP#A_9EY*rA*S&N--U>MkVSNrh zIo=@}KkbeApf-NTuybKV6rh8P7ooLZ`T}Ez^ zCI7N`_gj#bM1L0p>hfrRSO1=nY?x26@8-P7*NB0pH&G5)Iowzz^&4Xrh#CRG;2o2! z5+@f3-9ri;5zpAi1ShJ@!p3 zP221DA;(&VdgWwkmB?-s%2zY$<1)MIBSKH@7@c&!f}A|xtD1e-F@A5;h`D$Wy?w0> ztj-WY9Stn}=UQ@3dhAir(ZKKInk8a*IJ7`gWVp{tyOiXdLj5_Wi<`n7kTE16D7h?u z*}cO4I0VY34JFPXv^fa~lTO?Z%z#y&tr@)^hT9CP3;d4H(e0aVALki2k13w{#eim4!|FePTmqc)whYb zBY9e+8RWr4!I-BY7hxz0f`S$l=t4!3fo96U=|@5{kq3~FG=ks1%_@HYGhmJREFC?c=kcN4-!MT&kpO(HPwB`*;~V@hQX&Fo?ggB@pb*o3 zeI`ln1#8xzVAFCuA!lW0CS^J)XQp}RChBqxj1L8TBXEEPJ@bJ3yq*Q#5dLi{dIpow z04UL9+Fl-TEfRjeyq5wf9B7Kqb02<<_w5?vySa8t5UaDvY-e*`&yVc-i1ARIYtIkf zdNX5KwRz$!4eN4zP7;{O-kwfmAnih`g{3NQ(_Cr~;_quLJOmR7i8qV=hoYAx)0VHa zm_Qr8mZ{;;X+6HjTQxnN&)Jn&I$l*37dRpgr}M;5QO*z|zf7q_fvSVg;84?DI%BUl zCXD=@$o`$usAAxdQIN=C`9{Kj9e9N~tddu$lOQHvb~Vgf6^aAp13&_ojawVUzwhGB z{ImOqcI8=C?>F)o?)?6I0KUi5kwb+vP_fE^uJ2R4zV{L#hoD55xP@kriG^;pwXgpB zzPkVF&;tHyB{iFvs0e^X#-IT%)}VtUGPnBz#D^qe=N=*=KfM zadQ4>3HdUFc#l>0fYM*P>TJ3q16j~zPyuD@i0DEgyl48%&(RaJqk#y;1)(%DA5XUz z(?|C@!%S4pYnO@YDIGMku~VCZ!masj zLfy+L4G`cjee6}7Kf9qd&ups@8Dg{HwI)!wVG9!`HuJ=f* zFdMCYttzGHFQY|*BwQ~rwPJ^k%fujrH)fdW;6j;&;$LT6vxWpbQm0(|{G-Ko<3-Hu zK)eVya-^0>AN_XB?m(ZwJy@%oysX1N6$Z3+fd{q8Mq*-Uu-0d_iBFi31S^1AFVK{W z{KJd<%O5&EjNT8!efc65O#XB@7PL6w@5hY69nuJy5XvgTXcD;p0aHM%zcUmJ;W6rC z|JC;e1>Ov@kybGF%>bL|`r^%iR5AZJ{^F}PZx~WV*Q7Vu@Aq#8+DO4xc{(lc9%2Y> z7G2RIl(flLcUDA^0WlUu394|~$>4ma9NeN+tjkEMo_}dN)6qa-3(9u``t@vnQi9+V zI-upACoB@!q0EtJ-mLkqT$@!fM`Nf26a#l|^U`b%#lXf@`C0N#e&iF2uz?d>@5pEi z6RIPZ9jC-6_qnXmGV4d9^J~CbZN(CB<)xyS^PSO_G*hnA8Xe^YmkthK*j&J1+xT%V zc}{Hh!4@tp4i*z@s}o9Oqj)tmuuEX;fmux;xqv`^n~oX1lXDEM)6A3eo5WPAS%ITr zxfEcYVhx%`KRWj8{wGp~dW!90M>;-2q4zH&M)hZtM91ZbQbhmvU&)sySo7Bouuacv zZ!me%l_05outc{g=8|AVEH99QO34w$;Od+^C|aVg$3;X(zdU6b^lsK5_53%yL;7S6TC)&|u@{o&#fof`W`isX^fZ2BShq z|A3^_8Ud32;vU1wx3v&s|+HW)z`a8|LLT@DW9je)gBQQsXHvAd7csCgV0Uu%kATR zxwlxq6`@!d7{MiOBdZ6B3`PZ67%9Jnng1nX?ha6;V4j_rXN`PTU|*m_-Uy<{m&2z! zVzG(#`iYNW=%D#efE1&nj0Rgiw)moNP9!P@+sak%En!x%@`J8}>}iAAX0&TPv{mSk zm!V^i&INfkTbUtZvOOf&T2N}W-O~Nd!099IHN4Sdk}ajARZ2*(eR71M%x24L)w!n_ z0J#&V-C7#mr_aph_C>Sl_u~>wA@S|nMMV`jnwVV8lTz*R%|cSfL-e4&^y1gQKwif# z^tpA%2RO#`h)nC(EHyQ>kUkO+cxM;! zNxkg9MxNFPIqd7VwrhC4%gKxz?@zY@m+!4r3!>L;Wrbu#S53)R%hQVzVk6A?((;zE zNlkL%j$n_ZLvfSX$Y|(8R5866--#Ik#-wzZ+r0Se;`I2O&>%5{#3g3L=OhFbWyIx# z1rxl-JL95FNyQmLW4g?_3>j*ZHAmar+-k8#Tf9Lhf5|L^#p!#yuedqPO;0ohh#7I& ziN)!vNT5%2WNboF2kbx{M#PD+S$9kM=7^XkMd@m}WXmW{GDXKZ<1>naNN`wA9NrUh z;xiKCNQf8|niHR1tm(iZ;jD58(v^aiQLvk_Gh|IMShH*?kxr|@ni9osHoUa~esdbw zhcYftcC#}75#@+aOo&W`q7u+0%Sw0VTRi8bUVTYjDBaPwFSHK4*thR~b8+9k3Bv$} zb(J1tw@ZY+#O^RrQl+5)L&c2bc1*6_eiozb&VqZpck9xtTW9=j0uv{obBsS`yuvZi zk(6Y54l^D$2!hmIJ|kEe4=$N)K9cJ&-&XAoLQdgjK?Q!o$L0;e_y<@V;b_LP%G4d2nImE57MAHw16D+ z3|j+MElAdeztJNwIP>%J(bJ0JlSI(3h_dj`6+6eeC9noVi9)9!C6Bch7FV7fZ7*v# zFiR5TIb3OZ`SyH>v^X&VzO*1r1M9yvVQV2-XU*ZlKYTP;uy>csoV{d&BJ(B+!8&re zVx%x{#q3OVTJjN2nvHc+?dYE~Vl2Ejm&WGlFdA4+M;9T^8o<;CoDqWXMtI zHl`S4tV8xFS01}Nqg)OHzqGxqk;yy@zdQ3}e2YCB?kA4XQT#{l*N?{{=N9SvJu_eD$b54yYD;D`E6%LSgY=XyI-Pj zP3~wYlN{Ep!nND2-OHHRjf@9#Kn@S+#3an{hJ*d(RXr&ZI_=;M9vI)mSnv%$asa$EMlz z*Ub0Nr$a(&Lbuti{uN@#j5bEbDuHl!xELE6LpMc0Y8-t(_O*D@$s*25j*NXIc2;bU zWc81khK@>@xolgC`GgoA@kLHlNU@SMLVZYV5*s@m(}%}K#>pQ%H@RQOnd65mc`b^I z3g+jf#AF&KH;Wh>8j+D!Ja_J}F=NKW4xHXTGd(nPY{Y$rR-y6jrcWf08rFMIIdqjFF9^1EVYN%mnPDsI|%)F^t0Xe(q zvX{gD6%^8TQriA5(SwJV59?swW?w$Eq-1EXf$c*x_Yj*{uxO*>}jYxge|6#GXy;iKB;hn3xgXY+^}-{93l+>XM^mTeA&0F*!<(lp{NX zatzsie%uFqtX%WM0G$szbF*zS`dO&$E`g6$ut!u?r_^rkjNJL^Uz26XmhtPjbolVyZ_In9=gt`D1+m~6)CN9<{A=+4Z#RxYyw zN)xc=8SVKPwxgwH)yN#JGs9~qXChx*0gE7DCVk=gv&r;MS~CXv94Cpp_t3N7F9ge> zPoV#IgMmIS)3XVC*Sww8Dj=uD*){aj5p*CVMVQ|)kYyu8IslSV(%)G?yYy)l+u{FV z?mYmbDz<>(JNNFrTe7|PY~S>@+1>Pn5R#BU2nmD`0s#^r(xrypks?)klP1yyM5I^| z6&s?WqNvYjdx{O)(+An%pSgE83C&l(@B5RzyEAjAo^xjAoS8FcVw3olnd(w6eHku$ z>^*oS^bnYL_?Q_~19JYs{_umNXW_ZemVml-dt{*Rr@R}beZiP$3tU}G#dK|;<-m4D zB8IDZD^?xJPD(R?kv-s>mF}dHKy;PcLwC(EV;FJzX_pBZd(lS)F_KtD;QL?^Lhx*= z#)Ek}#cG>l1|bdW*QoKl#4eO-0mm$d8EGwh{|3AAgcW%(JBjb)036eerZcSqUpR$N zw4q30u9MxK!8&&yuhNYfbG)gFlk&01iwfpt6qN#(i=5J1B+c)}@0VxS^qIh4P-cKJ z{fa4h^B6LYdVbWNq_o}jAa`>8!0EGlR|ZdJC7Zf9Y|)kiV=#YvmrA&2XMcGY-hC}E zNZua%6A{8K>8Ii#reM zJ1&>r-uZ*{^ig9(o#(=vqOB)H55@5L#fI|eEq(eLm$w${4QqEyA_p%9(y`6Qy}gSz zc&jWqLXm6HLzsqjMAOYy-rwoBkUV7}oJ2g4Pt*{jhphmRe zNe?=tfX3Sr-VR@U^o1mQKAzPWG$;DgX6B-eG&zV^5crmBBfZHw3xqqw00~j6wlFj(nTpAI={G z_@o$4QreX=nZlt2rza$s2Cg6PiEEfysYuP6;|ICkVcOihwDg?#kjj)ezF$I|XMB@7 zRZ-bXp64qo$klqAbJEkmmt~2i&N%p6-(H|W*Ovqosn+RYvyfzZ=iXgxCa=-E+deSUD(2f0 zV!HS0qLD>eDN9)Pt_}HQS)N+|QJ(?VnbdevfmfUS3cMDl(E6w;uS^|FqQFK90j&JDDoweYx(AP`1EPy|NrxtFW z3+_KsyR-F8aHgcOv7`+SoB3sEys@#i+|mMa54Qip?t#PuMbIY%PD$YLK7nt14+~)o zVBmG2gWrI^f+x6rd+HedK6?{6Uh+gdENU0lCTBIr?OuNnwG>+*^Mm&fFptpmBf!Nl z@FV5`13#f@;MhgeyXg1n&CD9+er5yRI+v!Yne+zaS;KH^zX-mF7kC%n2G1(2W7FwD zPBk4H=;Tz_gV;zXE)uV-+7;*(c?O(dnC*xa8qT0k=*8`*+%ksQA3Dd3XV8bt*^jl- zCo`e9cA!^X8D?APJQtbF*v2s6Nru@$CNq;+Ih|mpp}E$?Vi*mJPH%+qaBEl=-9~vZ zr-9%3G>FIc@}2%5q62D+=Hs`SAK|{Y27sDHTL9R;q-VekSN$*_EIdfgqL{q5_I5hD zk19O)E`51*0KU5I6kPpYNg6Z47zOg4`v&a)p)d5kLd`s*m_D6)WhTX*bH@D9JVbL^ zBqa@I?Z4n@8$W*3e!R%+WrYqbh^A>Mp9_iPel&&SeRaI>%!)jGFP=Pb8g|i4o{xf2 zll+uFn8vmWkIU@R4L+)ujt6E|r-+}9H?rhz@~WvI$?i@l)X-!XYl73B*i(LtOmhfO z7j=#P2!Jj@Z)Y37uy|K|u z$5932%8nid;Hzl*xzFIEzmb$jyDyIE()jw1-@HebeKTSh5Wi8(BduefyqtXLL{Ela z_1Lo{81-vJCxoUE9QzSNiP0>dD+{wcI;SR$V~BiOg`8q1K>R|3cU3Usq`~XgSYaB$ zf)gRVc-ax3GFKp8n4M;kZ0BSJ%VZFskPI1MCq;(c0Yq-{a$%K9Hp`ds256bG{DB!7 z`s&)29vLlGNt{@iz+?}oY#vj&iJ!^DO4lV-P1y7Wt(oy&{*=kD|Dc!mx$pq5*wWV* z1I9W!twb=BO;4)q+56?eJbRxr|^}-iROnqaU_*ZI(|r9NAZg9&(4|9 zeRcn5o!JGu9r1^N9d!R@k7~-{8@rN~E#>vEKQnB)vNUvab=iGOt7jU@@^_AJTs$;) z?*_In9$;mH_whPfn2pw{i6lo#_MDjw)p{%y~$|6n9@M)(ad&HTzzcw_No_u!WO^!rb5e*cvvYv%1A zT}#2#WqbqJVCmib()bBtKuYO{ACr=G(_L^#m*5I~H(Nwzh$57zUl<8HK4Z%2_^{t9 zwGL1Wq0;J1AP^K{y+6XM*bh#C00@F7U^#pRz6#4WOac4Jb8y$8BhQfyZ|sMQ!I}Hv zj(5nbDAJR#D;udBI1U0|wt(NjSsvUK8hn%?n?vgayTJ*#e(Z1m0R4HekZ9|txK2vK zie{&DJUejL0JBx1*qggMDnHQao`}v&hpJQSL@%yf{R$imzkr{>X=?q^wJTl%ujYE< za&qEgvO`_6tFp4HvZ*g4jfgag{KL5X`8PKKE!Y63!B-9*dv057R#q%dhM(B19B-sK zT=TGvHm=U^Dm}7#f{=UhH@Q&G$G@~B{C*yNsl$6fEYiG z++(Ps_kHHEC|G@eZ^h6aOHO#b6;CYbIY`m7*#vIbUE<|~!R%PelT8o8#{}Bfy6MQ@ z^$bv|dWJ@*Mev%ooIEbjzFwt(6YOsBvPL+|;yu~4jPlG+P988nB_-trZ-w{C>6H!g z%Ar<*}$GtPNCo<^D673dJePTVBM&mQT3HmPJ;xM2uQTu_ls07RcK(I$9Q1i z+@RGVnl%`fTjLZD*8J*m92_=nu`&u?vvz+(s6N}>iu>-(;rv6)X!e}6ok%2dvHlqD z5NzLY?IoRntm+u70JCWudZ}BdNBbUdRsZe&$o|CF@dX!;x z^#>@uEc6qb{#Q~ACZJ@U!P9Iu&%uI_JHz+H6TXbn1n=@?F^FUNpR^4to!P<`W^7*1 zf7rJ1=9uMR&2q10ygThgsP%;J-)-Cel6dd(<=%u+wvF8Qc1zn**)#6AdvHo!VFfP- z13I+E9d3-5YmB#JYuIW`sJgQ?VEkP$lT}?ciK{to0X%kV_4~DBV!1aS)i5#^-+5ND z_J4X>k~;;5nFl;bP~$5Yrh*|eGylkKy%Ea8hbL3tua}%FO?hI7`|0BL!;_Oi9iI>P zL=I0Lr?P*~B~5H<*IYxF>9*8`!u-`<`Z5C%zX}?*W_*yc zl8Joa-{wxC@^d7@SsK49 z7*OD&)_8SX!&As}Coti@t)WJdfS4<#wSpK@H*+y-vT+8`*L8;AKTt>x2x4eu=soI=I3-G^9)z6yTeVs5xrKdw%p-z3vFAuWN;rm^5b{#5Goh`1Y~UCPppd+ zOQ}$?@HprOK0(C-!E~&)IvxJ5;MN0n-uxWR-!BkC#B<^HaxnL(7*=Z+AqCijNIX^G zYLI^o7kOjvuiwIhpzl{-j0N|>We zL-h(U5$<07{MYRMGN?ua{rjwZNC1C${IdXOSY4OzW9>5A{ghhtyMTUDeA9QgUbfhpuEz=N%)_D-W-ydDFlugCd5hw>ec^2PEsA~9}RL4hU@C7LpD z0THMwoMhba;Tw(}8?)iqj}NY2wt39xO&fU2)*nB<9?lpA;hDNGr;zi1D4n)%|5RAa z!s!px=hIN$B0O$)&^-4d(q`wQbQV7fd@+^N-*#yfD&L2%$e`XB+oMNDut!#IO1BN8 zMr`bsoQLF%3!68CG+srQ79=8!vZDRe%R!`Fir5 z4VY8K&xTOqdc2+hc&JWjgd=hg#b}&<++@6H@8^55T<^uLXDyC}{R*yob$E@J3egYs z+4>_#9+|ohtOTnztXxTwpt)k$DzJL}s#Qa}4-ba|ux{!jkDWPlX8ls_)OGLoTK?e1 zjSnvGMXqn|p(bBlwsg~`rOQG=b;a;?pfC5XFYldoQ*=w$WB7sZ5N`5W-rj;&CJ^_5 z#cL-54Ld(zg*ZG=Vpb9S3O0hICfkkd0NhVb6$n~Gf>oe+ZmC?b)7_K4e6f22{CmA3 zbVx8)AfR8K2VHZGmAiA~tjvY@Qsx5czb-TiV%2jzzc^WW!G?sHKv2o9@bH}+DG&;( z27b10j-%JY{<~I#3G)OrPcR>he`sg_g}ohf_rlM}T8e(rF?;s>9rMq$-bjs!Nu}sB z$TNG6;~biy_F~$2lGRDPObCdia38XvE`%7}JkqCekdc$!oOU`l*(CV zue$bEn1N1qvXU`G1FC>7E?BBa#!o+XThu5l2UsG4NK3RX` zGhOnAe*M(}ypY2L87CdZ1uxVz&R zXin2qUe}2P&1#kd757%rAfsxsB1@qo`XzhjOu73|57_eZ$QwtXW z3&;c`H-_N4tOb#mzmX^BKeJ%LGf+&%#82;~HI97rp*In{hIQ{oo|um^eP%w{LdM2V z>!mS{+_UD*H`lBl*1bETOEl^+5`;Sy(LJ&slmyWH$ZpVJ=~ERpK13jK1@HB+RVCVn zXI)qWhSRTa)1gX35y&;=X;RDmUYD~xRcamMb*B8~_`wh1C%lCvO`T?qX9B@ikw^Z`lj#oZDat4ZyPp4{2Cr=sk zGWhG+g^z5Wld~#s@N7k&qVb8^@|HkGPR_U_O{~Otk{jPg!4=FisC`*j-vpqBuu`;z z)!)}D5CeeK0~x*_v6zZKV%+ioP`Fg-cwK@a_vTNId8s_F zDrH_#P7|C5R_{$Jd-Snqrwfy^7UZvwb^;LlxN7Z&<&#{xC&_bw)F+yG))n;Smu63X z^U*7>&Y1i){1G<8X9qkVyJHA{g1OHJR3D`R7y$U-eCr@;6X-Pjv-evk@H##7Y>y-T zpK4tlx_BK_J-_qPMro+5ttu(3@8;f`+wcvTdo4s2C!m7^So1lf}vCMnm25aD0)wsx_|%FDZLfg zED+JBvFp&pqC>0{r%?ANF!QxTTSXJY`u63$_8PD6YefkH&0Rp%B@9*o zWMgK4NrxWeO=>BdL}~v7G+~H_=A%09!*(oC9kCI9g%I$CAej_`eDq+Rfxa5b2e~7W zY*Pz{1F#pqfPZqy=OK?G$jhKLln-AR339`)(d0cGz!%8pH-y^9k;_CZE3>32gJE-A z2m+|-PJb|B0hpf9&><9+fUotm!jaXUfP#QD<;bQ5>TwJJ_oxBWTc%M(m{@Yz4BIlI0~OB`$c* zcgo+byrOeSY4N**!3RL%EiNuCEiQJ#7t>A!x_7H6Dk&{}cM!`rbwYFKRfGpK^6*K( zNA&NvlR!tPd`b``C_CS-1YUyTNq@4ztB(Mm30?*%H)vI$&or2dig_wFI$d9Ues4F%-{x+?9`!4N3%dPM^`=#-C~M5Nbg)QQPLFg55Dq zi)14OR3#vtzOpS3^{OgEIrdowYV_K&p4AWa=w6oYAOXxLe``Gz=jk$X^h?c^-CQ<_ zeB{XcMvjzAqTStkG`}=@WRW*E^qwJ6r%%+Qk1o+by-ZQ@=GdNVD|@bvkqQLTnAJTi z*Y=Dx$5T}3Bzy}b!#QAo9aV&sd%qe)l3lFthi_vup{;PI9DE;4%fiz7#z3uq;9 z4sV7b-he*(M4c`X>&btH;8cd-R7zA3RYWr}omfdcLY!geU=|3dr3_z1IXd`Ex4bg} zPT7<5Q5}6w)<}{c@k|!d?gu)m9pD%X7;?dIXgDw&7F205P$PjDUBE}B-IAIO3`e{z zw0nct60n#9W?trx>D5Y$KicfKkV#L+cP6cVlf`ePI(tqfSpp_&z!Ftc4?w)dZ?^g^ zlE&?=yC~NaaP5=i`>i*-|BcUAs?|=l(y39qlxUm^EIPx`3YE&GR5{fumx?a{hsF=2 zX_Z^0ajKLqwOT3Q!%a;oD!D?Vb*PkXl}aU*f!O9fQBf#~#-UO>RVpQqqHd54W}g{- z3bc?RpXqN-Gow$UBc!I%ttsYoqcPna(6_!yevuq!!Vyiq<)Jc?a>OGi3K#%WLvNAE z@GpNY&wVFl_ioTDj+9b7krS1G>x@bRp+9WoKS)aC^te!+Jvc;VBHse)NPvhYLn5kB zBx2*MaaxgpZ2d3}T%|M)+(PtGJEBMu^(oN%CZyk^-(zp5@e+ybUIBMOt5d^Q=ui(q z5(VC{bD|jsU)_ptW&=U=h4^~(&g)ko`HT_(%>f`CUtd4|#;oyJH*h=X)Vxi0kN+7-KYt=K?zS-*1U=Ib|tLF($fhK6~eNfTzzo{&!3 z$5y1t%do4icTw=sEz?Z-jqkm0CDw8)=437@>bwu!zX~z%B%+2}nM{d%PM| z023BVS31g0AmWS=B}2XzZ4*T0xMI<~7++zw8Wq~ain!Q{M2*~NwscR310c?w6(xwa zArZycS^#7~eDL6;g9mr!BzEuBJu&|iatSQA__G2QYrt$t2W$M9IevxIlV4iNtL$1H zClx6z-q`r^xVZB8Sg%DTl*W~JMXyTpJTiqpCo4el;6$(nR7@W^9ev=j#IErbv9T5L z1p#=FHe~tDW`CC7WJ0h(vkiTPofGjHm@#-H#AhQojYKpsW0oYBJvHGCD~beyoGKCO zo7q@xg;zt!Vb~z&1D5-$ zqTpOHHNp#(fEO+49<3Dcz7|Aj;-#qrnui%p@afhu8ClywOaU{VTCUVulPdr5oYg#P zs!c_kMw?pTxA{rVRI3b*b*9U#x>WMffu20K$*z>k1~n!my!c!Q()js)9jQOO=8VmW$@3i8>kA;HWc8JRvWEM|(RrPvAc`A#ySNFKM?!CMgHKM!q)m7yl zi(Fj+uWZlCoIm6KDf8w{xgQ%P6WnEA=Oa3p-wiv`%OTH}+tnlQ+^xGko{r|w6 z40eacUw~gL6}g2)lMC{4V=d%Qq$M^tx6|aJ!d#^ie)E59)^0s<{`>{L*gmCm;k3?n zor@w#%B8b+o>tg-ie1b{(nkB7-VM>||86Fy!`EE@xASW#mV7@H`@fn2U#qBq@Ac?` z`e$T*!ZsT5?P=`Ip!iY!(^-o5UT8M?YU_8c_nMn{^9KxQO&&9bcHU!JLh^ZJ4oW8q z@J`UbIr{)R@N}Gf$b+zBcxIq`yjfJr&jYWdgUL+yMBZ0A zuOU;LWbN5kk}L-BAUF7%?icVMUEN%1uKw~FlW|nDNN6@X-G!#9H|5q;M@j*V)mvnK z2U*Y;{u1I*RY*pOjOR(Hz5m`g4YL20@%P^xSXsHLGpfti^d)vhU#n8K8T;`%HFBNP zA5eImZMJ`id_Zj&aQS=2yVGB=sUfcV{oa%(x%aFy-GpaAc3+CV^eFreUd`-X8T05s z?Z;yHJKM=^mNR7BhZD?Xb90!`_Li4>et8jGp~$@Er%STnA2lMT zbjZ_(N4V*?;P;jKV&H$LqEZ6k-$EZ0lHVUY@%HpYxI%vAi_lZ#nH}pr2gjOWCy%k> ztxt~@vui`37Qy9h1Q!9eJ}d+pf{%AOggj~;nG^avS_XB+WEP}IfQIt{^reuIAIe62 z>+Bi{xh^y;)I@F}@umUs1sWSmP(DFU&qb$}0Ux{f#IZ9D3d33B^ad1uCmGow#P8Yl zYEG$q{d+?sR7(z3)=TxnK;2t0B|i_LsxC6Usixna9cuV{p-)&-LG`laypIa{JUwIL z_8jx8g*k6Diy5F4!hNF{W;W?Cdzrw)Mh16RW z@((5O>&=LEoI@raF3guu=P!X_U0;S{<}Ntn7k*g0=Fu2y^pQ6~^o_B)x+->U8;ym` zWCUkj7|y=%9T&Lsgb9j_d2K=*Njd9BKJeB|+r`k2Oz6VimwVBdzU`m7bHvC`tGizR zJhXs3`o@RvOi#ppqn!p21!y&BxJ(aH>%i|_Lg&Px3u6%0$M=?mOak&_=@P61hH+g= ze}t%dAikB4L$VC~OXz0zMFW&N8ffrRq71NGzp6kGYs~vN2q$A!hSQj5I|9NJK1@Vy zey!OsP8*#Y`$xU}ZAaIihEi2;Ve0t%bHfb3clLR5qZ`eaORnt`kC-IK6;Lii|4MLl@% z>({zueOo1F#vb*&cApA9zWH@ACA`#mO@9yYnmV;CT<}a%Jo8BkC8QRQ?w)X>kNo_N z3+91Tqn6WSx_lEd2;_vE-Q~yY${kN)r=Y>m%>}61j%L#xV<5kZWwdxU7dv$N(2S*(0EnWHtE)BeCpEmF)q2Igfc4@+9ni<`g^%*TAEvp59B% zE3bJJB!M!Jyr-tyJUTOfbK~48uk4xNtCNmf^!>o^*S~lMUbu0rVyQrQ^sRn9&du1d zDRgmF;W+84L(rOfbkM*fg9jfOIOu3?vH0A}&A*dRhHYE!afDrT*^O};=E+$y<=~z5@)U(yZiOTWwa2J(xStR84f?NwY7XT0&= z#>BnzbOpTk5N)^IOr{@4dE-Hf)+snii>;c%&DAvGB}3%n)N_G%k9uo*hCW)?*?4(> zeBVm?-B)?nzuz3Un>SNSW$~i+-MF$iL$H}Y)xqn`dxu+Jf9mGn8C-uoyDEnYp%E{L zZAjp&Px(%pAA1moWcM>8c<{zI%5O&Xpjsah{LF*!yQbP&svrF>?}qYS&F&@AY;tX= z?oHRx8S(<&U*Fua1?T_7&Fhqd{vdo827<6J;M1x|+N)40TnY>($C*T$+P~^^wI%d8 zl>v5wwUg-&nAZI7DR>k1sio-mZd`&}8$qf>yhac{yH1cPC{GD%^9<$b4y$uG@om*^ zh4W}E11d;f3=JP6(@9_<=?`d_yo0>aNYmiU?Yt$Sjc~?FFbm~%2n`D9D6be!*H@^C2Q0S&SKAl5iWzz66dA4sAnQ`F?CU<#c?!%yirdd?hj)*SQ;Z17WH z!-ZbVA(!!U;L_j&yw31_9uFuUgnQ6Wr<~ZulgQ4~^v!R~jC8G>io=kFhSS!ix_Ovik2De0apc>b3;@aWFO8SqH10sLr&J;hYJEn2+ke1=XKH7*Z1^A{*bI1u&z;9$>_b6sx(f z^HEN$z8|D~_*4oX-)V^tonTPo?MHm|Bv$K}0nGd=eE5n}KgiamBs?H)NPsg2E^H6@B3frwj^9ti;6C!dXWdQ3eQ69GY zV}*O2Mu*i-(C~x0gWrosB0IL4qG2eM3ra)g0x!1Q!ZC?70=++-wMc@^XV45^gC;e* zf{Fo4vn<^Q3+O{|H?6EXBTu?tH#TTJBB$UxylsjEpnO&PYJ>THxjJOMwmq-AxmNpUmaJ`Ppap-^Cf^4~2tp@wnK~Jp)=uYc1;Xz0*S_GzIk43HcfkI2`P9<25H@B7qInUbg$!=aM56|hD3NH1 z1&Ms%4XV8Sh`N|vV@HgI8+B2QH>mM(`~nq3Y_=L`5zSEEAje1ZDKFM`B;P%7`qfzn zpegiAf~QyBxBA>hzRuZSCI{=FxjZw8UfTPyN8f(?r7QzK_0>hcxLd#4H?UW};c8B! zBc0FB_rJdACvQeFxC%BI2U#JgKiR!UY58i`2zb+VP_1&>62QZD)1Ze$UDvNIjtVMN z>7`&`57@u3Q-HS(tX}1UH%B-R#sJ|6xT6B>?qoN0Y_pm06Jc*a)qD09kc>2EvQag-dh)zTeF#^GeGc(~p!!oBFj<==#ZN~B1LH0j@7q2d= z;m}s!$l}r={sHwhJ;sbLEh+07JFupFRO*~f)vd$-3#gILkkvW$L!`=)R%MzmF|8ls zcVeaL!7@qT^7JyO|F2<3x517?^N0t{B6!`3@=>@?IW+u%7vPIz zs($ItN7tn_7kBILuj=2w%3E0sCI1a@E;ft>{0WUsQ`qWeW{uvV=ST=FNgZox{ zy0<>^-}J1fI!!7lnA8bKhiat*{rs5mgBm70vTns;ack&*Kv?Z`#Sqa%I(vJJT?3pd z`~QM~c9JB#_7H@-py$6KnA2&YQ=~C8?SIf-s;#|xA`!2j1poVHp8qe}_TK-XO$^I> z&Z2i98Qn;DiA*FbRJHM&h`F>Qc9Zfr`N&VXyok*NN{ueeQU-#wQpYlpPKsTf_4<9l z$1;p+mR&@_VO}vkNX3DLS@yCUyzqcu*7bqUeQOtPVXH+)9{lC$#gGzN3R({5`M3t{X#I< zNY~fE6Pr|kXHJGS@T$%`G)o`@S-P<%_^Bixo{+~{K)o$`c5GB81s@r26vExQ@xXnA zf&1v$DJgRag5P#NQbo9lG$IG_BK7PzfK?_ffU_ZinPs^W4q=`Vxe zm|ag&u=49_kn_x9k8g@83+P4jsp=j|jWM+7XCZHGq0W-l;IEL7b2d&IY#b6Rz41n6 zdDK!1Wm+!mwiNv10cH-x9CYOlr?d`ujtO1uG~C!qe*jk>ev^SczU>AU?%m}F4L{9$ zh#GN$(neE)YYB_BV)&P(G5}^Or_6}{go3{=N#5E$Cw*F~_Ur74WeY#{K3-ygEG|LRfX985L?G0z-oU5EhVy8_N@Z%fN zY!t&08iJ$UA4GzS6O$QhrYeA!CK0?Tw;i7qbdr3Hhw`Qey&QpQD87@gaeCd@j3i!Y z2~Zor`tOIq`MckO1OC@Sr6B3KMAM(rJn2uvi$n2o}*0gTKCmP zQ}=$>#7)%a%E{&ga@S(b$fhl=mw|c}MO9FH81WXerh*JHphT@dq}#_Z55OfLo?(9L z>16-{=lWxpVC^@3!GxVxz`k#Lg_LmYNTB>#W(^9@q?~J}5mlnGEIJ3FBYiAYVJn zqe#yk5c-&R_BHa2XW=jAr)8%q`2rq2VI$bTA8edJ^920LQ?jQA-3CK~1gQi`UuVZ$ ztW%tZNCn%@VohhMg7_{V%I=`j@kUV+cQFF)Z&r|o9pt8sV74Bp#Bv_|UJRZVFI$*G z!yn{pp;O!&{Bi%Z>7UIguqVeD$m$Jy*2i^8qCZ%^i~MReZwLd&#Vix_)q_KnYr*yA z{270pF@0Q4(g!)6t2b0vciWf7&Ijudeg@KSu;)gt;a#~~E?Z{p3WD%Oh~$qdb+joy z&TQ4FkjvZ)J3^1ruU@~xn|)(8`Ay_admK}!kbdL3?-AZScD`*dFOf(^vQoIjJ8pOW zClvvw+KO*4jU0KG+O^&vsU0|cm)enA?h@E4Zm%+;;f{4KVt0-I-CF+#jRAqXH0G{> z|D=Ur=-mPb{b{qA+uGa@NwkgsZmZq@hcO#k^Y7CDFZym2dipMbcXRzyV&UHbw{gTI zV(R~4$o=03D17x#$ASL?P=>$#lc5F8;St#D&dna(008o#BfA z3v|wN-L3thwfBI^|FIr%*D?EUF7VLZFi`U^rlyFy1m5_t1OBj03c$=|_eV^uc1l|K zN_SGObOE&zxs?8N(&cpUNM1zw0N+^Pq1HVGhP?J7+zh9~%`d(JhQOG^AP3ZfoWqa9 zbC2$YFC3*Fa^%=;ISyw|v^|^t;CZ+KPK8@vdI>awg`oNQkopjO@$g}gedr*_KX3p( z|3+bs-JVmJYqLe{8FZ{$;NPj8E84AT@s-e7s9B0`7Z&mvvTW;7LK2sX0zw!3E zr*+gWzN3C*Ry3}F&5kN?7r?cyYb(cgD-N+N_Gcxz+LZ$x%%2zA`bgN7Q}9o!@NhfY zxVv@c66f(fvskL#PhY+sbN+mr?WFKKKKIs*V~_(w+o=}(eIEU_*@U3Fhix|SIhzZ2 z3GaVPctzO80vCVbUBYqvg{oP&bwXAnoS&ojtH`M@9MYp$Fg#vnz`Sk`F6(iOIpD zhM7XLzu#{ZwA5=t67wc&=p|NXfGb~*_t)-G7TA6Foax=SWrtus9O3_Y`a^tfQwaFp zpf{)s>i9yy{c2T0paXp1MIS%~;Nz!WI-Rs6{?v;nL3hyo1N5sl*3#ISn<$} zY7C#eG{+~9I;Jn0QB*Wz(R7DYm^LSrEOMmQQdGfo_(UhUqBa$)Ljeh*v1s}|H2Wdg zvzi8|RZ@Vr)3D9EU=(1@L}0xRB%fjfbUv*Pp#~v}`V45xP5li0x8#vbPJ9V(>#%;_ zp@qNxTsXv2-@FCn$CUFx{+9m6dQ&;jhCa8Ei^wH*@@aT6J7;3o6I4N*1Mqt6%@7nS zQh@`0lBy^aWb7@CvbefYC%R6|$p$Ip{I#Jh@};#LPd(%2chtKGM|?C+B(e9{v6h@} zvF(>0jF|SLT>f;ohO^a2vkCkmEci8HqvAsW(z)MB+UO81)(90}|qFw(G zo1D}WyFn+=nUtAdgr5QF0WyI?@)bDoV)yRd;Uu2qT^`lRKej<{%q$Y{6UiSLK3oTs zB!HiHr!{(goK_d7*J*gW#X?3Dbz@DTr69#oP-RTk>yz^)cLGm(#xy1ud3;HI2lY($ zJ5s$4cw9vRI7bd9s+O#zyI2j3i43GAPh29;wdDfRK8g<#qmuN7B)vY#pihdzW9bw` z$Hx$ic!Ut^W4VPuYh%Aqi!4AL4*Wb*t0-QrX(L~7;sY`%S$SXNYNixhOBcq-1KLfC{v}07O8$zshu;R#K9mS43qh%(CRon?Yyz zG-p#9+cG|k>TYDMsNTk7aa!D{BYBlT<)rKi^iWO}`S!_efwWi3or?IG<;5vmtL&NH zT z-!`pZ^xNJ|>iH``D)|lA%y-6bIk>HN?`;RS#Itke*_$6T!|97eK2d^t0zu$Aq{HTP z*l%^%oDTaf1B@dXM2zaN-|1mPJnVNqAZ!G_(@oA(GY(IBAdMPc8*l7fFtb}huVnip zZuuG>Z;jmjh&{PiLARL&osIE-{u)T&8VCUiMgkIk-fwolezWO|^cjhDeqzCvw4CT( z^$vjb~_6DyH$R7`1DEmMj+D2(T72W!C-?}pSUqLosq!UldB z9cS#fYP8#1*V0X%k~1w0WP1i{vU8HtvSM1t8{tpuc;!I*L?jG+vF`qeZ+t1weW%MOA7+MP+XoQ)K3)$E1TOok0LdUrag` z9qWjJy(>Y5riw3&p|?Atm9|2MVp3j;Cqq3b&)z$3W*60{ZmY@#GX^T;bMi&vX@eF8 zjg9>zJv=FS^5OQpL9q)}U1oM(Bq(3iXQ?Q6np)E|jWPxoNhST_yZgCHCDviXlyP2E zuQ=8$WnWe>oWeS;Q&>Bid&kxQg|M+uO4f(ovA=8``C)y@Ad+HKF0~qoh4}lgJxXTz z+yY&VK-joJ3O-|`8ykg!8lAwMKC7e~NoJ;}k4jEWOG`~jOD4%AUy3g^H7$uU$e13* zGXfrzP#85NbR0M)=jTmw>>f+;CfLNzj74Bc&@PUi#Ejkz99h`~opQ1qJ4Z7u(NXrm zl0^Y$lx;kZ8cVuONy(|cjn&{%j9{bN^e%LVVRG5W4vBZOl()H*=#hL&DM;p%nYm9Vl-NiJ2MN2>l*x-LwaX> zRnizh3(3cyd+u>Ei_B1)lJbU31d|%`5>4tLm33rrW8>f>*}S0In3&%TxApDUukSWH!DngMgLthdLe1K?Y9SU9YcRLT;uk**o$k?K&Eo)P^)Q$O z@Mz;sXYI7IR0BBr;S9D0xV<>M%FVX|9c!GJ&yf+fOTtnLdXwi&5;Hqg=yKv4F;R7wlF`fvjq4Y zHeE)hI{m(y}q(NO223r{yUKYiiZ zVZ(a%-hOy%ZSB^>+k3O}JZD4v65>B4ga*ws1n>ck-RmTD_{qu~$?|?>?NzY)vOw+QX>`ErC;aJ7S2EzeCDnwM_XG3ztv#jW1C!xH zaz1@o!w-E{QY|eB_15soK9Z6$MG5AoAA>jfbx7{AA~`aZ$i=r{01tarXW%wNM-gL3 zVFN)yk38s6;nxaJkTV#BDNarYaE~o(5<-mRy#=%TS?TaFW{-minZYIR%Pp& zL=pT02t|*`FN2aVlv`nC#z;^yZX7(t$qPGSKS2up0_txr#1mw&mZ&^7MvezkBIp5X z!p4sKsLedi&Jkznhyv`1XFJ6ZxEtB94JyR-`5g@P`$Tx=ZxfP&au9soOfG;=K>PlQ zu7xA_gTCOkF=1m!U@10-v=(kEFx_8-!oL4q3NL>b`Jf&KUx)8U<))6j3`)l( z!dEWu{uI&WV{o3}FU$w1#fd~Fz8{Gob*RpOz4`Q3YgOJbemfd=a(6%~=zvXXH5fl} zBGm^z{>!GBeVW>BT0MaAyMFrYO<#@y!{LLd#miB9Z#=|dcJb0IFexK{=hdq_J7q1S z&ZAahtiW&o2A}GZAnIWFY9@>7qB7e zsErtt2sbp>q7G)NZZpuun{pN5>~9G6t$)E4e{L;kZnIf+i>)qR=Pz*Cm%nD~H5&A5 ztJB#Z?=abgZ z14RRtJ`2+_{|cYJZ)s~QN?xCvGdm|UEiu(#sLjuspOcvy$E|n033t&y@Rev}z&8H^ zX>BbC-}S_gEOxNUWOmm06dv-}g%7-r!}qFaz85dzVEg?1$hlQ)n}gGF#4sX%NFN(` z{Ig8dt_S-+o)puiq@+thU1APU!SB~0`C65cT2s`eq`26d8jT>(tN(+~feV?R^@3S& zNr^u%J}EUdDLE^1NxPHxfLIK+)h|KK%=!!tvcz;bFu37Bmx36z=;XR<*VdgBYTTW> z9B3H4uO!A=df$@auYHD~`s|YW*O2=iy*WN*Nk}kf-JJ?qH;41t22^{g8=54jP(g+R{i;GGM%&51e?=4M&G*3)LMkK=#wKdVvh4GMwRt!6>M z-ii^SYVO1}L(lzaUGIBWt@pZ*A~k#EUNs{h#vr&CcrfS=j)2?XwtInx#oH_(r~SMa z(OjS-q6=giB_&e|^#-Mq5i1G3{G;zKeRnREkY7T-DWLu0Xd>9*;$@VH?%X+S(EZ#w z_|3+r7c6)hKjgRPfEHdo_aeLsv}bYH!l$3cYisRgstWj&P%L2xvHYV;uj6vg-BQY} zIp2~Ys{3`YjCYz>&elC1)qMmd8-eRSf)S74>Rx_C-mCT$!Q6Z)Kg$pZL|D;Ly%xV)@MpvS8Rft=SMKafr@*`1IwFS`> zU!t(Y8IlC11ewP{^I}}05x#^GF|H9N^#~$^Egb(Vl)6m(q!I-hk3$ztQ_(V=B04aF zPo?NaNE9e$&Ub0}Q7ALHPi9JAw${3K6GLsa_l2eAHjCh_t%bBmvq00EtE!5Ms&LD= zU(`B=&d;Oi>WN@LT3T9NUOvs>_R+YxHXClR-Hw}Fd;i!zU{YE}_ih;(-MUZfGxq*k z3A}ol5s3JzOn(0pBUgKFZdor(WIJjjr;Qc3wDA~Goq@~IktG8IA z%@&ul%IUILtTvOy)vY|Mb5fe$pO#vX`%t?x6#ehS=1pz=l&q5}jnT!iF=ZyRTqcv7 zttBzBc5^sYZn-&H!p{>1{ypyBYW*3=&oklWucdKQ8lhGL1e9g4-#*nM~CqA~hy@D(HFRUyiZ z!e{Z_e8l~`X$9@3TUuZL=p(osjH6y{4Z!8(`%8v&KiwS+nA-y9x6H+3;8CK6rs#D@ zcELNP;Uy4%(C^gfxC;!TNjrC+Xwd7oYr<#fsqqbys$3OW=d&tYRg)Ta!S8lY8`LYI zmMo}E=rw2>P#phD`r!K5)Sd3!T=&k@*!scge>r{zWL+KjOnteb==${{LwWr(1Fv#C zMZ~@;AD?II$ivw+K zz!ni^sIE_7PA?{X$JbxOGczadMVVJVy7+M*<2buxd@M-}pRfnzZrjANeAvcVIByj` zd8-nViZq|b;Z(36f0|Db6p}~CJTed3A6T^Lfqr$1&|eK(!{gM$WOnGq&^PecFz+bd z3&wylcmm6Ek$kbe(x48_ra>LnPzQW(2mY1s#TMLvWm@R*)@kqyuo%t+nyH~St~E3j zXi(5%-ak-a6WrQ56@D=temgA`I?NSGR)wYk&2-fNT5igiUbLGKBKZ}cA=cPg>u^GV z?>PZ>T@W#HLf~Y2!FOOj`hN%P1l>TlpAN#wfcM^efVUhsX*npH4m*Kor^6GVjJguq zL)L{Ry!$Te<#?p!Hxqbg>BkU`%>?0M?~V63NDphl)~9gmB!KT$AmWlUq-Wxui4*ta zz1dva{~&PJz>Q#74ZPB~xcSYG@ry~J4=w=buo5kG0bV$?=B>Ba9ENXey9|RLUqCo7 zf;V}!to%xJ5OCNl%<$qGqrs9M<3%hQRm#F@%g_oC+y8KB_G^PDT<_DnY&3!*ixpqD z4HI{Oq*GaPzAk&g)^qTUof$H>>gIG-$DoD~Favm_*t^4ghyw5eoeiH>=8SR^Hg3(% z#@&E{hB5^n%j`BhbSd!IWw)I^aDlA2a3Cq;T4?0=`PA0Xu?q*dpaTix$BrHQ6+8=H z{+e~6VKI}mJT$PTxw&TGYKOU{#YRRo*EDhgjWvBU7xjcYD;8yrAD_9X0u1PhT%5iE zTTl8m)|O5pD+k_EGjLnIsoVVcWQ_r|SKR=(y7T6AsO^mrx3nbg79Vf@UD`qq>ri<( z{g#Ho=Wp>+b!^)@wywQ>bQ>O`*mKqSL~r&~B(AN;tF_w*8@mw8P9v;f&vM|mxAI@X z7Tpq^aT5Lne>{^?3-X)vVwv7-f$#p?NawfVoU@jnO_US;@C`S2hebzd={mT{{|TLt<#z`X z_2q5Q{Qfq-=)a>c>Ta+!haue>{^bq%Ur-^{!A>`Ke^ul}3}RnYZB~BqNJrs4at)w5 znDQonC>S)Lb8)``x+flJx7iKgKLBV1jqvxnuz77TqhC>8ZSPKn{mCjQz-&W+|Gk0H(h-OW5VmBL{3_83`>#&T0 zZz$w$f7ZDpDI(Hcc+tWN*ahjx3I@9w8j0qi-gs~PVRIZs3MDBnbG*ytGHP^6u_V=L ziE|3;2GzNxS~rEn39+`KS8AHUEK`Xk={9F+sWDoj6br2s?T8&!1(tr@V~8R&_}x~C zMy;1?EHo_^$rK3+wOV83GZK*%q$qV}vBt{7FJ$p*okC-#(F<7=SnviTkO*RRwj@cE zOlr`$EM->grrchNHuD8ZDwV3pp;qfnR!^bDmMV&}>aAv1XRFS_muQWns%)|4Z%z@? ze7#%|ty4ssBuTGX}^>C$96~Z$aKUIdsyov?QhzcW|T4-uvfmj+A?PKz{9L>D9IyN z$kE3WaZrF9l`yL36}W2nx=MxFtc|f(*d1o0m30aS)eJRx^m>nJaGl?8kI|aVR-@U0 zqF|?@a@}w+=1R{|3D>{6BV%yCR3eR5DWlO3b}3cJ1xB{!_gS5gCzT3324{{@BbP{| zI!!01gLONE#u#~wQRtA!HO3r=vy(AJZR3SEK%@w67=El~Wj+Y7LIE4%bja9iJ-N5xg*t4M8xb-Fy_>~{nhk1O z+Tap`TYR^~Lp1*`xlJ*o$JcOTRa2V9E)**z(Z!LAF;<;D&tpae9VPNv9hq?^tDfg_6d{sN67aQAlvk~e zk|x@0MRr@7R2C&kvgs0NsgUU17hm{?d$J*}e~%B~sx?YP=;r3y&hBWB+Js`t^d=ih$9kA3xfnbI zqCe=-KQ8p~2Q(uTYK20EjyT8<1QIEq5!uifV~+I<^fdq1Bb;;g1i%p6~Gqc0(cO=HRoF5#O40maUyKsiP6Oil7oPtFVC2a5BZP&zLAKN8J6(!cF)cP^NGY4_ zSvVcLyC;koH+tg8We;xIw0zmUAG=q*xWR#>xWpdh76lDV2^0ab|#40k2vJ@682r^caIZdgG^7&F5o4#MP z?CbjmrgQFP4?LB(VHA=hw*vX((K*@K8RN#l?{;i}*Cvn6%Fb36)}$nNkCw~c_z|oW zs57#P3gV)tj~`^ynykXa;uv#K?1;f*@LI8F-)GC$Q0p#2TGH+UnP7#8Ir<8janghQrl@pBe`Z?TEsr+t7u4KpjCPUXN)Z5|~c( zek4Z`Du2-H(*@il<Q7N#Xs2wE*NGVsV{>zz#ahMS$Jxq)}iSqCH*|h&moVFGBqtoV-yB zPVxopB4xZ*kPHsPDhfUfi+OutF~bipUh-36H8@0tex?sn%^(3@5(@CDqsk!M4?iK7 z!H*S6)d=_wNEGn7)kyw+;0TQec9lvQ`U}r;<8!=M@HqOKPXCDHkBh|T#4p_W8J6Ah z>DuN>Zlu7Pih)}vy*5=(N{ub)uvcYj`Rs-C>0DwoI&cgd`)QL|BKlI%q&70rv`I8! zJuB{?y?sjEHi@%|QS~@QEiR{U-SBlZ?47ONaP|DEbSxD|vT9Qv^Rz2sVSh3JkGpk> zbZH_<@{F-owL@oe$(1RJvT~11s^rrmT1*2FZHf(ABtQg&C>o%EmJ0oa7P?bRO7a29 z>*Ucu3KWC21Y_ic}4wFsWs6TJ?f#-#Pi5b1@cW%!_o$5(k^KXrU!YL-N-kPC$x zoshm?sZQ>cAykS)N<|bij644oPwZoc(<9NSn@Myd#uC$rS;S&u85#k!++s-hLI}*f z@@W;TZWU9kmrTaeasW7z0Us+GMrK2H=PDREHo@L>%f8dF zx8Bl$pbUid0R8DSKj^t^Qp@Dj*yNEZ7SFmedt3x%plJo;<83xOh2Q1ck$KPB#(*2Elj70_}Sf$_i$8^f|_H_xtAoyLypv z60K711>TbQL`jsGaW{+@K9g@5w`|7nZUZkaoc?3|uoudW1<6)5m6YLM*BIl%>su#? zP4sK@V}yz@5H>U$rXegK*4Y~+t2avKp`JS9WN27uz5+Z=O2~XN zbQbImFrgdwle9t>8ZC*IOAseUGb*XnqL2!uavrTtoJHnEi828w5ST@@;0Il4AZXTS zlTqY9HmsIxSPiBsL-Rt-C&}qRs1E&-Arg~$ttSF@nSx~Q4_#--s}c>(Q=p9H(Gn@@ z_)>Y4L~i|68ahiBBDna$I%YX9k5CXg!b-Ri9p~d+dxG0eRAU8jtp-ym?f3FEIx2|Q z`n|x8;bAAxqp`cvF$a)_nE}?o6yD_5@!1&kEga+_36z*WS z3*x?rZ|UEHYArf$7OtBQegmf4^a)ftv_dM9 z$fK2{7-Wi~LT72AFpA99n}dN;-46m&Afg&2waO(?aw(!DDWWfwqk>0k5Pgda5&01$Q46LqQeHoV`4WOa-73vza|4YV zH<07*2D5Wy=7jcp=n(e3>13$&p zv|AK1sQ~>UBGjmz5jSf?+DE)Z_n}3sl}~QaCRE|!gaBa{g1z_jMXx$WA&~;Zk9iN+ zw01ZXp3s$)N*qb)#qs3wf)+J63$&$Tp)?kzgj!vUY{^D%oEIOZBfck&(J#_s)}}(Z zj5Y(m1iwQez7C}f892)rr3=lN7PlcSsLL!Z9+*NIaWPvTD-%#!r72|nq?=K^?AXFo zTLO3gB1NpBkJ6p+4l;XFlvfCXLZGAm23}bXGhlEzc!m8!Uh*moF2mks*t-m7pf46L zj}iGuc3j8i5ye{tCcszVgXsSi*nJ5qG;3WUrdb=DphisPAE~DZK6Q!^4InBM{>E*XHsZPy3gQGFa4+%>kL}4+A3EX zH(mS`E(ye$b1S2zacKGw0moLSNNO}%6k@q`?}n4F>p2>2MM9f^zRI2)WGfU|DWcj} zj95*UaD&LOt!ZzhU2O*isN36y4P5rJnA8HJ$R?G_fBJUK8iiHuCZ&3t%PNq%OgdxV zDPPqpG^A1?Bh^ZS#bp%=mHN5orZ#GIa;-51MClaqlHu$A_75?A)vC<`v{)+9#K^C} zmtWth)TbI1B;o}1$|#e$;aPa&0i!EgBDOjerbJ4j*K4AWTzVQr<(iGDHm}r>W;}Nq z2tE{ZXRpVib{Em_vU*8QRvWJE-`(!CQ|+7CK3)Kp!Wyt2oCN#f9`Fn-4DE%5;2E;^ zJocQ&?(@`3-~j9$iC7tl0iF#_;Ua)%S-7{CPk;{P@f@Th^a&gr`h;|VmDI6_i*%xK zGm?fPWO&8c?+kXR9r^hWKm16J3oXAET279;MvnghL|nujX;DcXTS-0ymcwyiMaQy9 zCs+vFC20M+{%SV@ooftntP;>*}O9DO=m zlvm;O;$IzBm%y3$P$s;Bb?e|IxP0BZbszzZTX+5=cnKtY1QK}r*1_eWhIM4rIxr3- zthrP&FQ6G)-mWY<2KdA6> z3a9ar!QZE|2g9o%lx$kl<6R3ATxkY_E3T-^7fm&W(eP95;_RY50J_bGVx(@$Y1?g7tc?b!pm?b)+uWre zqRos!&IOTs^1|}FkBaG*5XflB2qbi~ot|1esVN2hHBBm> zdfIlc7nJ$lG0#lFFH%$Siz#Q?UvP9&bMtTP8reMdE|y#MRBuyLW%Y17>Lv$nSs~+V z+G4dOQg_Ub%l%e0-`li&JrpSyT_Qzli>)dtvC0;$R4A0uwyMOWDw{(lq%NW9Nh4Rs zS?vyo-4+v59}{E4PN!QZ(I`+-N+@&Onbe{dk!(_l&h5M{sWnb5*N_kWX}0g)yGHN+ zS+@VIMhO1Zh;{~r;U8W@ya#v@Z^rf5dx016=iyb&dw>`9XGbKjyQ0_%sF(zoRIV4r z#Kd`QSxMtk0xnNnoJV97sAIiFL+lcWl7(pay^AeVS!^BcWVl+?o}wIeQ)u)i1ptLTycBo){@d+o+IQSo z|J^p=!WIthorvFIS&~b1mt8y#g9`hddE6yY$9=P$*? zlt>h%j#3-UR=rWh`eF zaEqjB16z+6QB;&jtukQ`YIwLT9sP5ZSc%$++G6A~VSUj$LrgdicqN=in!2rqRB@-bt@#eEQD;M*=NAHQ$t(e9;QkH=fu{pis99xp9(d;Up%lW%^< zEI@pWki9p;Ed(@BxoH)k?0^yi3fPlL39teyDS><3Py|J8@Yb`Twcyuh!EfNVXTh(b zwbUc?z-!Py4-N`__3Epnk@_z5I9wAt4o1Q?WH&I9)e(;De+ls|?(Ml#_uizU>JEn9 z0cQ__7r+Y#!P(F|2k)`HL|+a408fT~1f}pKsQ{&<{!cfBNFwFt_so3yXT-62@!jV4 z+`7j)<|;c-34sdLbnC**%#;+JUaw0@$;|BNnf@#}0*ar7Q84ORC?-cxU+9gAX&Kpt zow7615{-J!*Qt>8k)AMgM!>Z!bf^wE@Z#H;+p$30HW1%B(5n6fN6Y`DvVV>}@X5bZ zc~)kOz!TGuh2?(}0LQw4z<<5rI{E=#U4aT_FgUEv2O z;D;wp0M7|<1D3!aVF^&cAHgZ0AeY}kW_PKJ&d1kz`9ZJG1R^yEQg)hhqYtW!XL^&T z34Nw}ZY%lO@o))9o(PiJFSvy2Itl%w4;6iDu{Yq>E9i3tG+x2`ypi%rf<{t86d}bH zmE6GZ20=i1-FAKy&?(x00sabFLfb*h*I??(ugQT30AR)KFxUtbzq|~8EDzlPr^;V` ziJT2fUZSe+Y&%J$5qf4J{UoOej`H`qffp5`(xLKjn*sXRnT0U#;7)i94&QkY=8=g9 zcWwq-Lf(b22Nm03c$MUa5(z~pM%4m1)Z?B@~TNnr4 z`xa=vy^3#)z-`!o@-(A7X;zz^uk!`HGy)wGhk;HA_yB9Qd&$pRT7GD0fg52`3wZk) zc)JBAv0v9v0CnoZ#fuj%0Lex8GieHa38WX{FYxD!Koa_jG{Rpl-Xf#2kP2tZD&>dE zLV`SX37jf{#Z9od1e^}7AjiQj$k7B&m%uLMIPxS8KNDI`-p@v80%uTU^8U~YHbN6B zqX3P0-O!kaR~8VyB|r$G(36NBs<;QZ1hG4IWU>fefqw;?rlGINli?8HoE&-zxIr`=It|H}lP5n6=I;g%z$v@o z^oJjY(|5xu;DOy>K5xM^B!VLN-pCkGC z8oOqK2RvLeH0)7zW65NE5+U@~*s-Cvz_YLunT+7^)bm&dem-=D?D9O8f}igw>)s8% zb@zi~Xq@;JiqUvcasU0W0{x1S|3`3)z6PU!5>|}Ep-SZb4gLU*-9HYc_~DLxZ-pCG zw;xPdjJw@p_`v@C@PWl}4H&r?OhI|#paUI(_8&k|JLae3^5b&k@(kyS@|^%=C7|&~ zPy_e>2)CBNpC(LzKb63(Kf?W>=10(20%WL+ecZe8k$3w*AMV|R@m%_jw4IFmrB9*K zQHY-1I@+$W(|k9gb`>9=4x!NC-~}`ql>Byg5ce`FNLgF;su7Z}_2?_k3-8t)ZT-tx%W zg*;j>y1$dRb56QeQ({%q(mr|J#8IMoO=2D`9y&KlB<_~iM@p-$B^qsdPG@iD(NdE^ z9$EV6E)-aF($SsoNI$_u&%7cf zY=YMYD=D#&IErro2Vub?tl*^L6h-c|JDl7`<<2%Tzmvo{MU(unR?6*fBAB?P6^+vQ$`U-8iHKZoOP4;pV>)XYPFLzj>7r*VdBEZD>NR$q zOT#n7Wc4m9>zx&2;AvbsyGHMIH~hti~jdK||{tNsZaL!@TiojmF?ft#Et#gxyJvS$QLz4h>IZa$$EkPJ*_W;!n_kRToWEwlw-DV&J&paw_o%}W}hakl+vY6hk%PnJXQ={r=OA5l%lr#=y_7qb;7VZhLDTz6$Sw43j-^5~a zI)@JaKSOZ$mAL}GRAMk0Y}Qh%4gFGjzM!+yR+wxx4bz+3Ug&x6QOR*F0=_fag}v+> z4Uf!lI`wU7&H7;`YjUCOx5`Ql=SQzx(N4agB`*07cSR~fyap3NZgyjmLq~^^J_jq(tq?GwG!giBxaObE(C1c~q#8ky?|i34?WoE@$MW zUI6%UVY+)->F}y>#<%TIaSgaFGPaO(*Ph(A_YxTl_+%DCexVSG zj3NQU<1qq}UMy66K{6LyYIC|)jTgk#+H|wpMHxwE@?@p8JM`bvqPtn>{8rF}}B}!{(l+IzBNr#%@+CY~EmZhf^k(D{bbQG`CG5?}TC}RdtLV z(<3nJv|6dGElHFBkejqxGbuuU zC`2q0h)APWogq?dwMKo8(TILUO?tK6uGOlI#vHv7{gQb)jZ})Fip63nMxFpT+`Vh! zVr_Q0-0t$VZ?XD3(I~{6h(^^qkImt9$0Vh>Vr*6q!d*gaY^U3!d#!SLr`XuqUM>fY zJP^fo*q}K|a$JH)3ByDw7E2_0AtT}ds`f=&Oa?U0sik(Zg@vbv4MKFS(I9Y&r40jV z)JzOcAxbOP3TYBrREp&yMqrRg#A0O_>yqPA(J8wWWfgBQS)zSv7U@w4=^A|R5*vm% ztBERQc^Mt0!%2lK&JpIRzud#}33TD^Ac!)cNa#-}(n$okJG|jmS$v4{qoNSy`z$JV zq&u_+wsi-YHk??jL)`(}MF{UF7ziIxK@9j)`SUJ^XSg1#y7%sbj^dUxO@Lj^q^b2& zeg1g%&+lt@j_p&_J&=heqs+3>{q4@`du&x~*$QXvf-}IpU0}}EtzgbBFb~ey1!wV8 zT767Xb53@1QjA{9y0dezdttOAkg={;#k%aw=xElxlXZeof40XVU^Cs;v9N8ZFsyqW zkx2x^L&O&1QQ{c!JaG}P6aD{ACXoR}_!Nf99pQ%+d(t|m%+?iBo%P#|B;aL8!X{U2G4&SmQvsw5f|`%+$O2q zXm=8TI6)9Jq~9evVfzH!Jr91LMyKF@gF3z<$o=a0UcQd|)j0iL1^0_mDEQnjNjnAklCjO*$2E`J{OMAl9n;+X^Uu3CkAdGV`E)Z1 z?A|@M`2e&@PRK;Dg&SM8q4?-W;Z)EH+M7rP z(GOpv!&aK`o#8<@dQd<ehh!l0YVhuf`3O2;5={u zKcU|bBFCov$o2OF2U-r$@50yj!6TcRH|^cKv3V1GY#)3B`1XOGo0>Q7-HU=jnx`;`6mR{g4ASDe79&gMD-A&%=Kp2Yv~EKi@B>7RQQ$zoW4FoWAFQ1Ucw; zn|mHw3NLI1nw{y*{+@@HY}~x`P*3FC0W=%nMdWTCf?@#wM)>Uxf3vUW;ia24qEO`A z0l(c00?5tn6YRM8C8I*)6+XY(aXjMd?lNewBa2tTo_>%5M|hZ5@NbV2X4Zn7_HNQ` zH#F%Kkr|@R_`4$5VHBhPFquqA$^Jl+O7YWA3RP0TpPYn(%!$cjNl`<|m%fl#HX}NGRd(WSmZ}PW1)q18hzmQ{jx;(iu~5=04u2KoVC*lx*pPvM8?n z^yFmZFeWDjw3-LuH~c6QTO#^0Me%{|L5&t=X5?Z-Qa`v9rAATOUZA8v$0aqH!fD|* zY}!P#$z;X*O@j~)s_FMpPl+OAti`M(q6?Cuu}zxr-2zzKoJ1cl`T&*ZRyc>jPj%SK z?tlrZ!z9uH5p;)Xp#%1)YqisBYo~)p;f&s3UPuCG^#*guZJh5()^{pXrsDyUlIh0j zWE2T_I$7qOK@aEX-9?tFF4j)A)Kpt1YnLiZky{VGyK69&fD5e+C4u?9;dHVL%;^nh zf`zF<{!r!Yk3gmICXG(=YE<`jgbZU-gU*;3 zXD~J5;B~(vh$_cr%@1X8*>_`qz)bjlZx9)wv_Y zgr2=EH=igc`VbAQJwx_>V7K4RcKq}}HlQ^$cdi{DXaHXJ02+5mG``UYa~`ZQ9(=hG zKDCQ4=>S3YR1yZa1yD{3pP~=r4V$FM1uCBkcZ-2$bBqWM1lvU(tN9%4$h# zO0#^-_8CpsM}8M)H6w@B8WWR)e$7_0yCu$RLCK0yGV_hitPhaIC`U8O5oP#fF)G@G zihd9IK-XeaH1g3B3$F1X@UX~h3H4_CNNXbw0}sPNDC`!UMq(tV5rvNggFxFU7=|CV z6B0HM60sP-_IIG_u-T&mOgr}(+Bujk#JTYtNwrBXraSyn3;d~_ zt(H|YJ&1QBFz4_ddL;cj(ZrX?@f+US!=9@s%j@Vt9upF?7{nOi1GNm%6+L~?b02!9 zpl309Hlk-AdQPF|74+bX)Fu5-67G+P(*#Ax*~(G!(`f7xv2LCGBq2wS^dfqaIllq9 z4Pm$GBKO{LF(p+cC+s#t5x!IpFiz}Ix;TrnJf#M`cANq$fEoR-H~~){Is{LiAU`q~ z;5nFo0o?zL0sTD>?tcU3!?OnRD*OVU$pGfZLCMjh@KkG05*VxarXn8n7?aUn7SmQ%RJg3D_Oj@M%z+XTwPz4W%G@KuWu)pLtZ9eoC9w4uR-tYi&Ik<3k z45MhMrXFL|_zpp=EJQuFpHct8f(wvGpqj^vyt6BKJa{nt5|9jfceum5!=c*9JK``E zLtJCE zk&L}#kS0OXEO|uM3h|xeJyUg>Go)>6>Wk5Un#WMQZ>0VfKpTS zkOQGv)^V+TfWo^YI(ovu+ckFSSo)I7#kZaN7mF}AZBO3bePPw8=srj2d@=Jxw~fjE zZ0SjeAeEw|S)(#e8Yd_77cVtJEf}%89D`e-muj9Dyy$ZS>RMCesPE>$qiy9J?}PjW zC;ZRM3O%wU2!XrIpUuQ9Ru<;vm|t!m!;=qL+NjN?1Hs3{zcUH`F@fPAlPW^ z^chpvov3&;KKR4XJWYhZ>#yXjaYosk=8FcQe<#0)KwbR<0NOo3x)%ez~|FLx971QBuI@H0dNHJ2v;| zD3n@^LTA?s@%E!BgSp+g!F`mlo}G=4n2X&)*<|_$aqzHWa%eAM{zDPNE|avH7&qdE zVd_Ah=60!5Sryq%hL&HRi>E0HmGi2H-qo=B!sl~gEo>1lrd zaKwvRKjWFni1b<={ru+4hy_x@xSOprVYZLgZY()$baWI9K^EYwXR$B?@+MNqe;Hi_ zXSAPDikngI?(F85{Ox9kk)flc(w*pY~P7u=_?=izXw%8!9l3B+f}eWnL9%Uv;AXAA!Vx#gpA(lQNlqe zZOe`K$JC8DCf$wBz)Wxv_|MR0AJyNg5GILy=+owFU$- z!Rz{duzDX)jC)(|ttH8O9UJYg?%smbl#;MzI=yDs+#V+VUG0Akc+wtI?!~kt`B^8N4WCC zgoky`QHMH;53Rby#=vj~p{QezGzu>EwtPqEA-}J(>bn+m!GuOos7h4>dt50*YQi8P zo;`Of4NHWH;;M*c+z)G@7T||eUBU2eygPQ>-cBoa^*LHxV9NF_7FS-W`7$-ZMhIy0 z8;H8MuJ!$zi`p>tx6!p@qThWOZO~E~K~NDBZTsUeBIF})*+xb`)7D+&kpy(C&0*%! zn_((i)`U#!g_4Nqo=BxPi-p2I0&$w$j+!TyeiNTzb2_EEM|_>NlOvR)X8qg44m4wQb?y6w z*TLLYSpT@VtBuxuIq&|lk@jC4@vA#8^mbggOvkI(4PRv+{gpq@^EIHFIZ|8Rw zh*C5m2TjsTNo_%TSjR`H?OD?15`BLqSFEuo)pavoTV6x6m7tw%tXiGwmptj2Cp3@K zHUjmltw9uIM$4ys7tV_xPS<2AMjNV?!^b0!6DHfAw1l17o))|1;Fy261zpB`t(#&$ zY$~Os$FzH&oPb}wR_{*9`0V(EXI(*&Hlp){UZUM(!;f>BXEAbo=^xW+rnmgu`)jp#j2v2aSJe{`Neyml0X`c+I{X5Ss9jUbapfPVf+TlMJ zghKrNf0DFkZ#eeOLfoT?ly?J};2J8W8xczWg|D$46?%m3%XxwIvhue;l*E-d@rv>vCtkj?%@RnE;7nb& zw_OELY4EoiYtjOc|9dhHf%y{w^Cy0p1GgfYUJ3J`gkK&GyD$=Qt|kMt4)$O`vf2EaZZfWtl0mCrC zN8tMp7K(4wb9(raGCIYnYuJv*jID`9gQJd zmIGGixu;{OXJ=?=r?*dU90l2YnEApSDrg)Lge!sul@bL-hYke=111d~R1DIu6lhQ` zSf@gyL4))UPWd0We*h&;L623~Q*kD8OCupdO6IppQbZXQvZ5kMLBa3eqLC3%D9GsK zBs5b0Q(zSGU&zULygKV|2RzRR)B52Jl6XJAq6aK?8I7#D?i+wWAnm!*Bn;&!*%9>F&>N2~_z40`GG zU2}_HaARzyxln)m7)C02(@YtEPT|-9IO@puCNjlhdJ*J`(QQ|k{U}8l4>?H zM%%~#*Wr#zLa;}B6OD)l&?Or|iip(DZnwQVQY{Vqe%p#Nl5kF}$Tt>KJ@$`p<{>^X z_ysffhjUH!`{x``Hr|LyZv~W{V5QxFtM&DxyOXw<**R0Y=sQsPt_-yW18NifA#Wg9 zPaDzJ`AN!)M@hPafO4=KJ{ki3==a{VIoKWD^16O^m+>yG-aM7X)9fJPyBwIXcpDqs z4uDn=R)*82z~i!Rwz(f^`h&~wDI}u%Z4m8RJo9z-P$HUiCr>Fu&cN%S1n#<_h)+;sp%RS*cUWyrOUgy4ijj4ohR4q7gpIieGqrdqXUHb<(z3q&x zH;Tt*uw5$MJY`*f4vkM*$M!z&quT2MC(JsP4gv#^hZ%Kw++R9e8&7M%R|y+582#6Z z|3x^Z6ae-lLe>yO0q7%D0I`?x8uy;+u9j?q;|8ZW<%^-NN^Db9#Pc;IB3itI#W^)0{LGO1~k0Gl< ziJcVXFD9k#{vWH15J~QC2?3>)zOacb?DwNRah-s78~q8bLWfU zBle&pA15atKhx8D2Lgerqd$LN}E9`oxBF6UJx zYXBb8HLHn`j5fr4Iu=@>%x6dUH3luSkKJilF}gj9pn<{|GSD0oG8jMjF5%E(NH#9R z2Iiq{s}1~b!K2x+yH-%@tHvj(h}v^qWmG}{sl=tG<~pk0njW<8;z< zudggOiBMm>suTLH2EY9-sDBxq-q7c6cH4{F-tX^!2aEH@Rd_40Ligj{;8k0EU7;&h z^T7At(wJPW&Y!dXXKPX*?arS)#g*{YLXta_`WD|i5(+(aSK1p{L=#p|u%CKRKZt_T zZP3xa1`Fib^k)UL%kQS^S*8`e9&GC_gUmg5ZC&!ai;He?8>dy++saM|0e;;s|G7Tj zZ85sB>WEOrr9^+kZtq%{4ZWY=>Kwh7CyUHGx_5z*z^B@xjT1!n| ziouS>%Peg@HHQ61`-fUaUD|Xjjp7tG`A&eY+@@JvvV^g&DnC%Y(;YF}fpjOHK8C2oN^SYrF0n`L~#fy9j6m*PNVB?62dAOnINTmHUk2@dMvY=aN(5#cm0ro^1EI z%YEZJ={E%4&++lnnk4u4yM|>DgfB~xjs2Or&TJgF?VFu4$lG|&I!{JUj1Edng}Sqm z(XM>mAGB@!69!_G*~9zpGCZ()rQ%dRa1(2NsfPW2t~JBr1NoDO9@G=YH>;noBj`uQ zKuE^v%m_2Pw&Q2$NPx`p>N!`3gYkxF zlVD4Aw}WzB>mhlvzwq44%r7Sa&;vw90>EAMsI?lI;}H;dXuHDOJzs{iMlB>?ATn97 z&TlxvBy?R*Lgc|Ze^-QK*F1apQB}7h2h1FtWcDH9y>*hV0Z03yJ9Y$1E8$!U!9nwv zYtYb7`zjD~_bJb>w+?T3g4>^w8S7pEd*(3^l5FFmmQ%z?W7H|}t3ak|-OR*qBUI&a z+}PyiJ2{3H1XFXGd;)&R5fT#Df#ke^EZAp*D>kN-W^DeHoW4&8#ts-Eq_lv{55C{G zq`7S>cojg>Lzj<&8$oqDg7)n z812x#!H&@%d~HuR98u57>WKxt+~u$BZwTLWgN;?YQRX@KAVKAm1s~Gn!UI*%1Jm%$@kk7 zNt%U|4VWmXbhUV7>E)ql7plG8iR|n1WWa<3@VZ{(_|z01`^X_Y!)N?a+n4FHv}y1B zeh(Z3nzCHyw3cnpgtXjnsCQ6fInff6%P z2PFe7V+rE5zik=HHtPo_EI+r~nG;&Zg)95s(WnAp5Xmik`|u!J4zpspl)8J{E%|{Q zZX`8{rnA$%&HviOF!B+0Qwz#`6#uwO-Ov3fW#C-T$NiCV2eK(DI2L3PoDGNp^01G! z4QT0avw?(#j0GGr15c3nAEAtJ=CQ+SF!}z1ydST(ScbYj&64PVggaKVhGp z$KUD1W#nZfu*8wgJ}VF;x7zJ!Tv!*|>hCh~vrdWzN7lCv=!??^_??bx-gYzGrCf1( z{(AV+Citk^F<547pCyedj4ENI-|LEmj_rRCY;8%F*Ym4QNN3_&1E;NU+fR7EaH3j6 zE5kOpqb-aw6#R@@5S4X?v-FlM(06B65G_^|zZGjNsaBg-+!y@_#K{kMwRef*0$5bU zRdkHqP^mg+mLF^0A+9Cf4rw-tcUfup>9d?KYY^VuKuu-WV{B$N?ZzFCqT3$scYxkeJ9ZM&S=I*Ox5{zLu*GWyv!rSe= z9c?W2TT{pk+V<3K4OH*1++2HPauy=a5SeK?SJsAx+$TPOvdN3Nh2`eq_k$?}y5u;3 z1rM0LTypgo>$RI*_v;#5bP8k51xCd4+7A_Rm`I<)G!dD3$x1^&)O4r+QjfI91==V* znem0Oh_B?ro4J>a+iOpmvBnJz)?gi_NfNS0l3%d{SGaTIABofM>8yKWP6MVlAT+Z3 z4A?PXOmi!0d#pis{32yS{S(-1V2{Dn&wodobo-kLtJ&Aw!$;g0)GlN9ru5pUbHaM{ zey=2vlA|9!UwnMyF~9qCwvf;XKq$|~#`i34y6kDd>z`A-Tgahra(X54-K9~BygEPm z3N!B!YhZf1{i@-(e{<~kHEL(pr)t1hH65g1aFJei8h3Z7c5|iUb7V$Q@usJ8uchN? zL&&&w!&xOBoe^E6yFvt>(ZMxIETq<&(tU|KyX;A4at2LHKz*get=(%Lx2UXW7uHgTWZ!Pc z)d+i<`^}8t^#g>K=2qJ8B#-{_1D4s^emrniD6Kq@>wq%A-Ebj?(OKOb6xRuVeN;G+ z2IaU25gF&Gl(33{Qu>+4%s`DQuMuS}jl~#W3bH1O7$$>(>8j=(68mP1-T<5`)wc#L zkzP?&nrjl5OJ2MV6Ti>7da@1B@fv>_yJXB}me-%r@s7m&K(w|XhzT6&$gB1IV~Q?!!5(w;8Ov&WmH3Mlrn5- z9s@SUxhWx+;wx&um>5Vopx?BuHlAQIB=ei)EH6HGhs6@kIfn9R^4%xQkP3B}sY$Re zTpwBiXu7hHTC5LBSQ|`h+&V$k3M6*w^ff|fbUgmo)ma}*?su`Q^< z4sxm4O_1;DZw44PJ~6m9Pk>Z_(!*fh!9HC(mkCKdX zwycVdj)LgS^}P3R&wQbqHz@G!&C+-0>JvhDW@lcL<$K~%)EZ?fM>4~h={-9R0VyL3 z!9W17W8Y-~FPJw8&?fUj88nzIJ<2H~OlELh5|{y69M0e5wz1b6$~!21xG7cLr8^B3 zwlZ#+@0G^UgQZEJuAai?&8Rpjwt%7cSHX9};|KNkYNE3TFDQR*VUk=vcfmVJR+480 z_i_+3WlWrKGPY~H*v z26>4ef$3ueI;bQRL1xLh0ARmhMFkMQK-{s`eQqY+q#>Cu$Kw&6uHQ6lWEQ$|`}HSK zC{jvmzmycShP7IC4~J+^1bqqgNX+#+F*0Nc-$w~bYRbr)?j$8ggxzwoyI_Suj2RZcX>T1i)lCHMF-{ek- zZp9t8J~_yj5Z)ur+*kjshhd9a<4)0%tTvey%l|6lz%Je*W$ZIAJOa zUb~ay#5>+Zys!H{i@ST5A>Q*wmjnOY!_8eAg)JLC+N6J`w{L|b+zG-z+I$kv4@vp> zn}PE%6Z6}Dx`?)G?w?iqx?%)5t9P+Isq;u=x6#l!@qkEd?` zt0qljE`1WnRDvOwr7*oKpDi=Ny%`=cmwho0J4-D{5#g?R(6G3yZiBTDJzr%7MPKVt zF&~D0jxrM0y5eK&o*BI~W#tzcQB|S9MLjIX;H8eCqM|1&m2S;Nh3AhVhn|hVT?g5= zjNJ7`rcLWso=4aU@0aV|UswHyi_^2%M(b@8VR2(ez__a@ zog8OTd12kcf1)AQynC9iDZu7?_fR?8k8#`hCUQ17-yq+%5rc7+uNCD5=$#A%6pVXC zz!ca30xvr}3>BnSSUu)9-JLFO>&4I{lM84_MU`b5g+blh;^qV zsYT-`2gOJw{ypm>1#7z0fQ6zP_hyy6R%-j^ZKz)+vp{jOUD;?5o^^h2jyU$-(ZmG3 zF}V{{Y2lcf_Aul5taY4aQ3z*vB0kj&^W^W>v(HaePCvH|)mnEG-!}EKRfXbIY*zac zkglzwGNHmXuPuGPU*+6f4>4$W!s>7Eq3)j9x(2o4(LS28WDPNpYBaW9+Gy|8b$6xh zRI^gmf@hf5i~-{@N3gL07dNaf3`4oqYa~)qMv@$JcXB()!pp{6MKQP~5t#4anVDJH z>E8*Qvo%ka*#=6MxJZC0AZyfL+bmz=b#f|!`&E*?!p)Ov#J%cA4?N{pzEXh==R6EP zJPx8*F>7|w2$v=;djF~-&6Y62nGzYUTAKXB<#;70;Lb)Rl@~_0spubVSp-C#W~ThM zIsiQOi!`RM=gk)$Y!Pu z*PqQd8HlH;lg=zWv=*far$QR8ld|dm0ObMoCAcIX)7@l#PYJTe| z441@+4s=3WVnV>}d25FFL?XFsgsDy`1Kq<)m>WDZN(EZ0KxzVTx5-v7dMO^KbzX6_ zNbr4?S#m|O$Qu=NfrUl+q!h`mmTm<7CoRu-l1SDjEYCU*SQ8i}X4D_>U$Ou7;Dqz4 z>8N%7wQ>vfMT9+~J((OIo=bcY%EvPO)S8Z%VisEahW}CXmJL^V3)2#ulByc+YK+b z?rHjS+@(TsdvJQ~X@Z9ysO-0+^l?AKtLEfou1AZlf_1YwdH2f#yS;m1*L1-1P}lOC zx>Tp#6RHQr^}Xf6^q5-Se@93h`(HoOm-6opJ2|CIa$T7@t*7+5=C^;9!Oy(~+Uyxg zC*^ApE0k|j^ff)DR?J2By7+37eJhx{T94^Pc6SnI9wxf-{n1m5MIW@z*Ssg2NldF; z4!VzZ96tcKIZ-LYgNjn~TI;2KgVBpppR_Bt|HN?;Er-11=j+RVu4412J2BSjA*IFN zw42rzFfpUNQ1Z{d;fItaF8grx_%74UhN!vs7Z&pC-OXclwVZ}){o$imb`Nq}xqsU3 zV+YZ0crwYZ@OEj?{e*rqMOA}wSF^-sQ^}C8n&=w&xFg{&i((I zQ1xFEK->*j`D^c2A6LyBSCuJ#Xl zpuH*Te{?CJci$7xKyEYT-5MN~L_Nq3ICWEuZ!le(0c^?9%#iM}Rywe!o|LDJmn|JD1|D8waIKb{TASJu>DXr(=$9~;YI&||7Lp<7offc@Gb4>rp!K0_7nlo(2YhN(c9AjetvFwo*(~b@RO5| z^%nrXom;!MaWwyJ`QlGYu?n*>`C8Q2#bSDCFM6c$Z-74=ZcBUZX_Z^--~B#5?fyG) z$-aX>Y8pTGlb>#Y)&aNo?7PVqdRm*(UG3f7+&K4S`c=PPcb+nd^w!V1Tiey$PT#Lo zFE9U}A9D`?EZhMAVx0fJb3Zk?w5dlGZ06tKH386rUt79NTf<)qAGb}X8fu`nqK@gy z8*fGIhbNMj;$Pz*Kj#3ucU|)92`{}y5B}Oa4cCCr@m`WU>5Y}wME~J)fW5~~uZ^Yl zBmZ@tk?BOsKA>1vrOIZV{i(Mp@pb>!KkT))ukHart7DJe+IkDx`mYieVV8S%m%snL z{+mZ`1G&%EtDOKkwerZ?oc$`($2=D&w>afOE3ZzE10U?=qwX6Re&All+2Cz3`S--MTNNJh3F=z1;eq!2W7 zMCII$hxqRChvw;NFUW&mKnHL&r$ifSKl%ESysT6p6P>}Lh#hvbEOnz zNw9#JL&Ov7UIqn0l@*8j>!SA1vg)B;$%sfks1B&p+Eri`ePli6Q^tcNq4MImg@let zaV-?Y$93Hy-&nm%6y{{d#3{vgP?@L9%~KCTy54FOdOhRdd&d@KZY(NK&2B@&+rKD7 z%t%}6yaX1OFApkp!r{Yh?d9ussGENterrl0%SysmGN^nrgJxi5B>ApH8oR1YNef%* z868T*B=3px4;8ZPqM}+3Lxbf9qlRH7%FUwmZ^iS`S6$Jc$|xS9Wu+QUOIcy@^s}~j zy`oelIj59I0uxT`Avt*D-UUm|TDD#2SQSV=PxN$1X)$snlVTp-;vpU2*0guVJ%%kF5bYe zcF{!e%JOHNvXQRY-UKploN-c?!QnLHc2W(gPS(INC-u~k!Bop`pkmjTuFqtb8BPTu z;A0H!`2)Uf?g~0wG2wr%^c~(^kCC1s31L$?*cA}9-cfqXHY5C(I~NNEB0{OVt819@ zT~&idWmU;du5 zGmZ)ZQ1#dii`N&2z^%^XbvOnRIv6a!!xk_Lu;A&IYEmA?Ikwsx*K;Dq_#_t;6)=B= z0g}_fF&(T_Fm?25@QUo}>X{A>5tl^NqIxyAlNWeQ^Bp`DDRD+mFk;beBLEF+Of65W z;bqOD%tRX?wczUYVbtP#ddA4;cE>y!PENm70=y1ui$L0X!EY*wQAlJfLx0*PFk(;b z9QiMZ_Mv$`EyY+vLp)I+N>=#LOJJl4uao^7OUCr z@@hC$H-fc#bE33j`!eU&ohHE0Q~UW>O!G3AB61L^848mW8nlm(s~(ZZfNRJI;Yac* z-eu@|pY}_<%Zi)i8J_T87<9!j2PcNo`ZMkF!G&kN7x_N4v2FRkr(qviwc8$3{C{gg-w z5HjRqv4z27#Ev~CjP|g3#{|`GB_IOy{Am3s!_|OE{L&D1rRSCKRih*8J+knHsLuZy zEBxsZzK>VxU){YpIQu~gWEA1$uQ#|ELljQ{oH7Lbp0vM$iq1PM5G7=_eCRI_<%EnI z;yR&xBGsG7t<|+YqWbzue13Z`i*L4Cq@1e-fIS_ZtF8=)@;EVMt;aW77-GC82(XpK|8G#;*2>}=iY&~FhJI}y&hrjc>`B@XwvL;s_<*4$ghuqY}=!Rc?X6AVNvcfM>Q2$kZS**^;5OdN*@DW0ue3_|6yU>t(!uxd@7ib4bw z_F3%SwIwV&t4faB)!y=6I!xj}b2yeINmOq5M#F~%TgyT+=hBO~qPncvcsTMDtYpkx z##)Po_2L;N2-i%%tsD1A#jHrRWmh|lKU-p9;K?PYjdZEwOW1kEkjvXIfEh)3;s95Mj99=AlMVD(ud-@kMGGu% z+I(2B5Eq)EYEza)a&T|hXtPA}`v&k{GO-|DvSN>v$+Vhho^^3gu7g!zMW- zdp3$uyw|D*7r|dS6O8IsU#77$TOwTJe70h8u^3gH86Ii_A4SOQ&YA;CjEBZ!ErB%2y0Jr}&L7L*#35A{nf;kO${${> z*}rc}=^8i)&(&qNABu4!sE{R0PcC;WwAJ6%T`W)6v9`cW;irVbS6$_C8&4j_Rm54w zlG+vB{^j!=3+zA8l+~IL&!;X@G7*C$0{Z9COm$v^wG*zrf5v*1fg#uZm-T%KN0XM_ zzS;adS`%d4Y)6B~_^KwSjG|>kW0?yz@C1B(tJNcfmGi+)0f(brA8Ku&hZAjnOG(>L zRzGO2Tf=&bN7UDq$A~c`f1~d@PDp;brZzCgpBm+#SW2kg-YrrDS?m*>g$R%0-R}=;r2?&=+=@5tiU`@ zck9YB0Oz2|#M-5%j^xedsIl@0zk9Ul5H(>OsppGC?Ns$gKSV|yVUOw+sm8i^F=3ur z94F+weHpAYe8Uagz{RInoc6Do@-(nf23MZgOf0h-@HhI5u@&okPm7mlWcrXa?_f%T z81JnieZeon_>z-92}ayObS<-}1x+~hO~a)8c|9R`74-Pw{>vDNd6Lzuj$21a(MU3| zphB{E&5UWhI307x=wLo#OWkgA(3VV_CbQ3Y}pfSlEYpBi)BnvN+VEcZN{* zwD8=foF4ylBG#=V>!veKJ5zFNQvluH^!f6IGc+rgvsQK%U!AQBaQL1%@j#X~Z*$vS z>#xxEhjm|?OC8B8%s21sHaOY_idS%tU!Th>DlAI|v3+WBRFFeSB>&xV)0cigg{}xW z@!|OTSJRc7U8v7p@LyJDR)G+`-x#{Nv2 z8IhSTNKw>NVL)(#PJ?!$Q!|g-=%lZT^wuCxk^a~7$^&Mb_5$2O$!4P_K7F*I@VNuJ zCfYUA$70G)(sjBezkpVY%$LQYPh&C)vVI%nfHRTNt|~QKY29W_<>%coo=<3QmNGj6 zKB&x8cE4(69;twRGMH6HoVengnZ=u*T5u&AMGZDaHy zG8tCY`e}E_n_Fg=@{x{VuJ-zumDKz&6e-2Yu%@~qH{Iph{Pzxx>=sUWrEuCN3_!W6E~>hl#xZGpzG zX||x)YwP8U`7$WqQa3MaDZrVs=W!2#pnYH) zkdFSK!+^lQ3DQd%a@((7M2}I!kf`q6)^L9o6=+RQwGYoV4)tyWJH>-mf@UI=G4z*) zAF&?XDDUb~!GgtL*ib2}WPfS7U8yWJyBO31`_)VnADzBH)PB51XLZY$+8801V*zF*r!Ze=gPZJuPL3fQP>AwZvWgtm|P6p)ic{YSH)t8eN zl5yV=p^=diDkfDU%bYUZxlTp0zE$FUzZJEyN#07bSC&xILTSTPl2hj6cj#Nf10zM` zt{kknA>@nrg@R0~5@A-#9i|Mgi@*SWH@xUI*u_Eg*}(-!%#OGip%nh^b#JqAYqK1J z+hlmj>C0_9Y4N62Oz`$XKHn=mSm@8!%lN;~h`)11$NZCw%Es1WR67w-`^nFTwif!* zUy{mvBR1)2-l<3FE%C`X8D9zku?ALbxnZHXQ4HCanG*@as%&%z+a!u?Z4b^oYjiDw$C4w zD({n~l6icQ5KIBZPaK0&Y*&rF%*H}P(_sC3V5KGoH|!%V=Qz!FWcBwc4>C@~$fzO= zry`I#1JTIt6wl1ij{|1Op3EYdAGZv4D(Tg5+~UIBp*@lDNJ=DAGZ>y1ArSVel`$vt zfNB61LtidCLE3;khwMN)6Znl0z_F-S!9TcEZi@wU_8p>YVIeK|4L;aVo-`okE<4)N zYmk^x7XOa|uceS~l*BM5JtAbjI`Jz!VK>>e8kUq3(I%2Mh(P2y&OOl~n(QJ9!cc-z zH<@oVoC2)B(Zz&6jHP1Kzx6S0aO3M6-Y2c0nDmb)uFS9DAK)JhTu95W(vq4t)Ur^x zg;tET-91nI)}lS|-LGwmDY|fExRO}01I%RTPfkq&843j%W|*PReYXx5jO<*VTAHR2 zzimZ)YPTKUpU(xIucTiz=8t7KN1uy`!^6dzHGP@Rx3zP>$DPH2bY&?qBS&eq` zy$d9;49p(Y=Xn*3B)>;%E6ZUidky%r0z6bj!biRy6O6uhk7lLb0Li@r{N$G>-|Muh z{=dzO^dr7=KFoNX@Ef&QVRgYr@H)>t!+d(<(YirW; zQMdGOiVjn0=`PNmAszfjy|uD?X>JBwgxWR2rtT$;da^2@b>;{~vmYrhL;Zvq7s3tk z-gn@YK{t}a*=UA{%h2y3^-^U1?Q?-@hA|9q>^Ei0gnP~phUQtx@d)R6_tLpl;YpR0 z6bS5vDCGp?gn4($^&jlr0$3UzSiE3%gaaEPYlTe`vVE@dv(7`XF_ouh>L>h}|o+NRd6kCgUDb6~v2!qLo)u z4j@4RUyBbz>W&;l=hGyWCLoJ?S*7+L5ZAne>O(?kq1s9Lu`E^L7Zbr|!Xr2IVZBv5nc_y`^qvNF4fpD8m3 zuw?dth@-y~m#&n|H_zaS6R*48r14I*^SGY-F^xA6*^ez!8buDx-ra(%-j#M0)qTvkNPjteo;z0w1f}U9rq4H5)XtwO?#z2 z`NLz#0`a{bk7MGj@jmT*?+#>mR8#?5Up|R|@FM}o(Zu+t+wj`i*sr_DcYK{6ha=Q= zgm=v2N`}fmCSVd|fp9-Q;ytANDjsnH0bvr8GF}t@js)6nfV66hF<^WF0vDwa>QN=5 z9!thu7_L2SLlmbrYhV_q5z)9pp2`@4vMwfl?i{*M{9gb=$5X zov_D6PP{o!Y|P4ns8#K7?q1Qk;Guee2jii5QO3lRVCu=z>yoH!Lak`k_A*1M-%g^? zi)^9`;45ZT=*y;TJgXI=cUmkKDidV6O7JX5-jsTxALnpcBIKg9`p28%>?OgDXfcsy z4=_tK-?%ztT6Hs`QQnH8kswgC<;-W--1tA_cYcd4h50ZXiKu^3f9KiDY{w-6hHy2q zlaoU!PxBNWQhyB!EvtC7a44*gQKqJHy!5wqdq4IN0gkV?qhn1ZS2Y#U7_(C+F?|c? z3{6~^R@30x3ey-z#td(myCp*34KN>&E$~5gb>_&HS}XO$EtMmOsdMZO;HlC2*!y~~ ztByesW{DF{jw#WTv5&op`%CkAl3kv(a5|tV!Au6Wb&q+RL?i&0UcfV$a??{;S`m+N zgtMct>a}_i`IR2VLt{L<|6%~y9{0{nbTqiUR28Q-n(%c6d`4YE+c3`L@}z1=ULMJO zx$G>aJia=jUc==Cne*B6*moo4G4sW-W|uJEHviizT|%pi=?-jRx7v{_E_R=?01vd! zYi)I&Sh+z~0Z~uKq%q(8Fz+;j*{{vf_rFm}{8{WOUT?XC|ElEZ*`CR@)3x~x5 z*#WJ6sQF+62H_s(bu3cvBcUsph7BZjqoUv6_T~{$k!p+E-1V-4>)YfZ$ICn{=5AKK zPx;No0~ME7_?!MoetEvR#=1FXbhkatC;Mq{+iw!vdX)%L<^-=%7ZD{A>0G|vWHMG< zjfWwHl(9UVtTlRklvEZ+KWdobp-b-foFTs|b|mE<(I(pHSPWBtol03QXF?| z7%Lf~O0`RM(4pg*@$HusLl*|ta44PRZ2rBTvR<6ck(Dgg}zB<5|>*nwS;86#U!eR7blct}o3dQJ4`uA|=c9i*GTDCSx{F*+M2npU647-JisMSZwn3IBD`Xf3mmhb)8I~bO|^tG3fP@ z72%c80q!pXWr6#VivdG4fR!OMb)v8X1L}fwDt13&Qo?(`XNe@0`UPo`J=-?%$(l7S zq2R`0SwZ-L#y!WvN_TtR?>MRTtVDk8Ce6JjFt^08K2Or>((V!#%b3+%aj})Xfm{JE z*N^s-r)VexbpX=y<8c$t4AMEo(~AwJn>`E4OD_NR!F%bOdl%?N@M7t#tiYFw!})10 zBl;KF*TdoE-_lkbbf>5W`f077JEusvIX|c`o`Lru92OmtL5^e{$nN(p_jIYsTtp`u6J z(JF1Aaxv21=WrcVE?_!EJWP-EE;ko=O^!1$&S&N2^vs9peJ|bV$A?p%bI1hUB$2H2 z`XIA=m}AU(Yz#d}qif)l7IE%-y8^y5xLBQaAJpZ)|33g^K%2k9EbbsR#T}-Sj^Qy^=iT1!u`T3qUQBW@kXJG@Pd2-KS)eX?K*V&xY*Xg-ZJeS zIZnNo&`x*t$P>{PvemrNp5pf+QWl%I*X%k&Cf!5z_||W~-@@N;?&nyw$@1a^jiqq&9{Ka8vH-2(h_kvzoT#iitKP&@7;Q6bo7P*s$&HH z2%-~eHdbR7YX~DGKhmE zF4!G4UOa{duj;Wjz3279X>6WkMA1WGG^txP(R^yo*{;gSSR0_K?`s3>f_HcGjZU#K zyj!=~X=!uPq^`s-ybmt;1+IdB)|K+nlMoOk+c98+IQhdzN#V$y-fSlQC8QT_SOyu(A#6EY z6D)dGq~%`l{an=OLynVr%YGMH%l8-W$#;0urT{PkubK(fAY=w!MP4?N64410yVr6y z)(GcG+o89nyV9i=RzK|0Lbe0h-3M5=RUNU#?;vFfhIZ}Y?BYv*qW(hDQ3c&U-JcM< zef*PtgO`rFFni*%CLZmFC zcxz2?HYGTX3@34cjDG$>F;TAON{rLR(hZ45oy;GmIOb;ekCzFRtIwxpmiZnbT+dmtB35sIk{N znD2Ya$ zUy2{JIriZRJ!CA*cZb2tZn&>IIoEU868wA+u8jIo_@?VZ_dN_l8$OhvOJTC)ihdPV zt7a3M;7?`AbTf_)gWOdjRTwYo29x?E&ShK_&oE!`9FT=?wQ}u#eZnC9@gRH&|1;;B z$H4vv_Gr)A4(#N-XFN>Ey5`A;5F}sCg7^lL`M(>~-;HiUqbJX#L9w_q(N>CkFzM%_ z36HjHjaq3JZUJD;pHWd;$~3>tyU${LxNW783yIMPf&q)Jd#pJ&+oOLLem*VF2T$03 z+du2L7pz)*lW@2X+fg;0WMe+W3&g*`B&Ph+mT6EqWR_rlDX@mT=`AXulmN74~!a@;RscFd7LTxx-i^ zg})Ov9ee#*yUq}_S*pDuF;S%|L}^8D=MS7%=0Vi*_Ne2l{9psjL`Tq0?5l;zi|+W!wJ*e9gNYj_^r-&{KKS7t znOC5`klK^Tnbc%}#Xv>|6#roY=R@(*wO2j199ve2*hTg16Z2eCKZZ&JPAog=iKosx zwtF|xEYr1JyZA8qyKv*~-DddACOf|Y->3jxePS*JsvUJ=?I|lbg&So(#Xc${;opbZ z0lD&v;lwG>h{o|MbT!!-AI-}5Zh)Up+2)q|RZE`_BX1sSXsH6ATz zoPtO~G=FaIUceVA z&Dck+6Pr`{u=*@RXMzYTI-~eKQH=9$jPA`RO6pC2|BL#JA(waWF0D7A&+${!0BMH2 zH)I0A<;QG*j-4@yRR_ve09f-^xhwV{NUfu)VX$}+)K>BzI}KZhpMFqj_-?S{T|Fmt z#=Dz(EX)Qz`-@8W=86w(JA9Q`2}}65>!H-OXm|aD2ekg?%P@Y(Py~Chdgm^9y&HC8 z)h_b&_3qtawQ(pEoY_tMjq1eT*o!aGI_ypKvoWbd;u{lUc%7&wR*9E2GJvS3Q77_4 z`hC?V7I&$9dcwI@u%$tVQ;nlwgZIS=1+8)FFljex3o|DC!Vi=FnFWVYJ81&mo^iso z9(hkz+JCCteoFQWx+quy6Bga@SaV^vM>o zm_Sv@}2%Q>u zHEB5iGU#(0d2=87LQ2I?!XO0>fmcIRRl3EQ{YVuVeb5$ckjbS&dDGuPuSR)wUxM$Y zr`~Qfhxj|Avo5&7fE8EV)|{H_H6jcD{2{CTKP3qs2zMh1!Szd zuT~SFqQ_-?wSfjdHS1U1V|l^vL{-;*S@>?+Pana4DfijWKHoit4Ql-D{xfGjK3f?= zf4E!?8Np`PUg@JzfEVI!2-+MQ5BeX53c-8#0W}!}XF9>zgW#n58wJuvd0(nRNJIv7 zUW!j&er!Gx4ed{K^OtJI!Bgx5s3Biu3V4ZrHeJI-mGOK6qX~hLF3e^9fSbEN=>vSj zA&QK2edD4KNm2U;sdPq{fWRPV>pvED64bxrA2q6PZB!ef$C8b%(w{f?)W$^zFZ!KA zpkEV;rf>iDE?n*XOWPrBmP;e?v0Vvs$L~3YSHL&NFaBfhd(|AFoAtfa(s@BiM@eo4 zs*F<}c*Xks&}Qy~rsI2kzg%?O4SXM6_Uz)(ZvZsxc6|44h=hMh72FiMk@}Ek(6%7k z4%WB3o2@n&LFZziLoYS4;BKVSiNPK)5uZ&%=r3Gje>E7s>!&4Nk&v7AJMfii z#*2ZK&Op3ZD>rE(Tt>5I&ic(CBJo#*Y8(9b&Vwj&^{J=VH;<{EU}AEaNa!9Sx7`4p z+$qcO-DJD>aOmAu2xqOi6guzN0{7Ydq1vdH*J{s@R-=Hy%zT=z?nJwJ1B#I@neEF} zB4-NE7)On{%G$~ZjgQ(~A9AtznZ)BBS*K>{7f*qa!@g|Ny|Hu*xkgdrlDl{n-$3pQ z#~1yoI;@&QDlVY7or*-$)uinh*yu=$3)PC;T0AHTZmT;v89^2sqZ{GdrDDOUa zec!6mL431XGjDVn!9wT+`LOK-f^HC1jlUIg6i4jaw;vtNw{?}8Q!ydWlQp3&Aatxn zy{@nV9}2?v2rYE3<1kOxaosupL_5#Mwl2=Ri)&*KHtYGk2A62V9du9~bXnk`p(_g! zKxYTs0!gWl6_iLa|CrwOHtAFrNAQq)ea*}gj~WjhCEi%XmrglZnW zdail?>Uo4N+9j4Kx8UaDsz)kHKp+Y*6o=pmFa!p%Eu+L49yR$o1a8^{f!8NbzK(Bi z+JtXkpDcDR%=DVq^5)pFgT77kDO?~-u4H*aKYa{7SH_ROf**Xm4nLs3z^7UMl6L74 zJsvgx_rlV)|2k|xhxFD`sqH86;Y!82bA7fRGk0;^Ds3$xHn|ac@)C^B} z9!Xepsie>LGw$?q&vrHhF!q8edyyKFk>n_o#W*+4U0W5jv79cD3!=YNT$$|MsRZ_) zqs=(*bFi;e3IF-IlnS>$$A6a1+6DZ?fCQ<~0F~gw3sA`*nUG+>PnfPIa-0|=-r(#w zN3K_*BhNWxL#E1>7dcxe&E3=2PuJkW6J9;9Su-Nh)lti-IF(j(6dkm@4R52hwXrbNI-qyiUw6k^KRBBFT!wbBPqv%Zj>+DB2s4Ek=abOrDWaD6jUg9x$^h<=s zL3^o_7?QJ^Sd=EnU3!KNeF9%GIvWx?<4e-17Bdm2=0yvgk0Sr~=nP;RaM;9}8VsUS z;UFlG@JpBv^Il3g18+y$RMIuk(2Ahi)iN7>3QS0Cg*^ZfZ zYChXm>#VkO&}i-^Tu&&Vs|_`4DuU&-&b%{d9RvqKs|Gc%wd3r{CK!R*j#Gi!nHPCy z!NJ}^u;XNc*$xzlvuqsVZ%LgX1?Qq|cGO!-Z@y1b32xVcQDnWX=YZjOyiV zV05n_Uvy1|?#Hm_jEP!a&DjV`?7^F}^|lec1qaPt6ZuD)ZTPE%go4Njc2J&uv_{^$ zpgk#@!S)0(P_z14VGgp&6(|PLo>^Yb{Pbbff=`)a?kH~NZ zv0wK{8>IHj$c1xJT+>8NOye57my2sygss8FIjC{8#zdOb>Fe~1niaRGgAozc9Avw; zB--a-HIIY-3!<5QV_&qH5=$p9UNU><&TL#1vv+(s>2%vSI=t%O!BzCb?BBn#Ei5BV zisLt!(uGkqqod>FqoZqXUNn8$qD9lDFEZu5k;JFU@p0~OoN5xO107c@(NVN@;Jww3 z$eYu+=rwl>BA-XzeI8jrZHq?jlFd10qn(_vL~E06?@VpZqeyBziD6+ovy`=bWqSDz zvWNM|9v_GL(w}&=^e5EE$LSIP>YY#5Q(=>)YxaEOf_eR z1QloRjffHu6L$Tywx(zA*Z8Lvy_{^(%dkY9eYVYR z(wMlNLbe(>ThWGUCeg>c1-bPc>j6rmEz9(rSY(Ta(v1jcD#qB2d@$eU5^i=$ym6^4 zemPa9eYR+?5=cAqR+ZrQ`KtuNFVd=c8;rY%ec;V3;P5bT)dW|9tgaR$-zG z4wVeq&R)L79cZMcyxv6){iao^oq+T)adm;M-vpM~!`!Hz_HCWS&of)5q8$27AIt1r z)=e7msE3z>u-`DJ-F^73u!Ui6+xwFy4u9OkOW`M5^_i+3850@F_<3lek6U$DcdnA1 zjiYzvpg^@=RmtBrT;uQQxTF$cuDZx|8s@X182;VLXs>_Z;_-UHor6wy&f11U>_6nFK!S)kSVbG8SPDqRnqAN*tkt~LX zr#DRdc<59nh)1V4WUd`L<;D{9)8fy@-dvk1%v&P4X0e}&EXJH3aB3j_UKYpLGlNbJ z1jD)~yZDve(m%aF@$qg`Kl+27eIa@b%Po5B%vDcxS7!@Ek4gJ=$mVuCJKBoiU?Xs} zf1vi2El59lewQ$Imv}@(gR3-6#Ku{isS1-DhilwGwUByFs*7gJ`3< zd-pW$ZW10vBKJ5j7Zwkpmj>3-cD<4W9y)GbaGT_)i!F-5?G>I z^W5@(qO%RyI;ia(NOwvyadxB+O|%oWHa2Rcb>f`VoaPt$>8y*Qp~`3@W@4Fk8+7?# z|1I`K+_yLtr`$$v;tkvz*5XmHP>M4BgCqpSx*2^1(=`L>jYxahE!Ysx4|s24gu@FWO$BV@2KBxpbV|2JyS!n1 zAif6GO}8NoUlniAZcgsvD9oY<>KeqxhI65bZq9~mz4sE^pzKg#K|~FoYW|)ME~*F( zsgdV*BMAc<;#JC(LD#knenBy0yw7%p_^D%JqkQQKaa^n+(%m)CyjvvBRb})I3gj;b zM4!Strj8skj?*rwJ8Ja;F+MtC9f%6jCZv)7$c;71 z;z^i;{V|V%?bltB4@>jG75_{>`FLnP{vQ13hoqAxkpXjXMh;$-gU7*a`pJQjIpi5e zn(JANV)eX()ky)V_c_dVc_%sv*|1y8=2S@ZCVEBsgwv67uO4A0sDM8rIicU>idEpj zGUi8yn)QasMn_tM0~sXPg13v4gND;k&aV2XOls|Zu{^@cM0>FyR5oP zFfTKXj_0F>(oy=!r%@N_hw^IXlk%wS1tdgdD{Y@rzzMsN2;KtYCuxs{M*8GvAk)a_ zjJJY<2uO5{uuZgWZJTbp*mk|GDlLwN#v%>oLO}t_&!_FZa0}&aebGa4GlA{R)lKwp zb{1n`-Q($qL}Kr4Y;DXV3o;msc8QZ0 z)}6pS=nsmbE64_4|MkZXBaLaZutUoD;>?{34{lsMejgvk2k}?Qik}{#_~{YF ze)@a6=xB~*lET_Oe=|*})Vf)-*7URa)0H1>+49lKPbIA-i9XU~d5@Ihj|FkTiS~5V zFZ*G^va3RSI?rrpWAPAQQ}+BtoZbgfKO-i(I--t8*=|?r+M8pke_{Sxj?Z=f({$oj zOqwYFmG^QjVRX6?{coM<;p}8r#n<5Ds8P8aovLe$glKm{bXZCMijI|>U3{w;d^C=# zU~gydY?ol>QH9BjoRIUC$5DpWI7DYD&}n+ z_*@=8{xW{BZXLci;M}16vEwfj_9i~qoZbzN4aCiMJ*L0YH$ULY@Hsmi{_8 zQExrgaI^)HG+sK`NFe_g6c00WO6N>J7i6!@dW<1bKY;DeGy4HLu3n;-4ziJEw=+Sp z(?OLjI`e9zvbAy4I%xFDc!qu-sHd*S*R$mnr+^}4w#mpgC`MV2aK!%1H}Eizb3~g< zuR|`O8D>iO61p5hYzI*XyQ;y#dY=+Q3vJEt0?qS%;Z-4x8px2Zf_GXJym*QZDx%{e zA**6~4rej0kgmI4lI`oLqDN$0QP-^RL~;TC#y~r@%H3d7U1K2QiE{MaMzm8K1N{St zzT1@6_tPcyy~Mbo1bg(nS75Qelaa#obwj6=!Cw|$J`IMO#|%v0>6l>3B4W!-)Ct7gtvMU}0PjO3BWsu?p^>3zH7A$TVq z&#wyg_70_=Eb|Za4En+PQ9-S0XD(Ti*)$d(!w<;6W3f%?bM00^qhS5`gc>yxYDY%$ zv)PaEaJoK0+Rh2q=8cJ3(S{BvIMOCX$EQk@Xiukr5F5|fS`k%f z14(A{yo$t0J0U(5u>*-!+`aW4**=x(WCu6Pwy)ICJ~&P^YK+-6Xa&?*kX*6?Xge-A z{bn`zsa3A@%mf|b8MQ{bgVItbG&DlRE9J#UQw|qAdsc9G%11Bcim6|FCjPa8HM42n z4@5{gMO@Jj^ER2Qr%^wiPV{!N&lXTNm#N9N5q7$WPTBT0wxD$;zPg~N zqPu?jw5+SdVJGcU^CB{0Ullz-n(Vn-m}g$s1%8iI3A6=2{ZxQ|MgN%U5@!!LQAm>> z=5QtF6Zxto`Uo{wB~hb7nL;*aD^NGm8<;1_);!o;PE{qAwOG4w5$zPj8)SqNqQDTw zu{ohSi4F}&2Owk;9Tx;!VtlXD`A?#0#D_|BvC$#~YAw$r@{7#|(Lp8~VA^P&cQzQ= zOsoN5?~m{UHV}s5;RkdA4a&)pR?B0NQ7k4lJ^#`w(Jerua`sd^A%Bg*!_(JOXNSD? zl_8ut80#?k#R_5kGp4idiMA>vurM1o z8sY&^FQeczAx?H*qWEW~7K>5#Vj&E+Qo}3zEsKjD@;k(9ECwarLC6k<$Yf=zp@FHLjia&Q zk(%+R)+f*H*fBiD(={O)obc;ouroBKTaC_fRpj=^;!g6BR`DoxxD(-N4_^zVsPy!l zoQ~caV%!5;U*@Uwi>1#Q&*#YdVe)(8%n*|e2Y!XE2gR9-r9k?A5B?pcKmj{v7scjJ z`@h5~c~cgn+j4pGewh3o=nW@PXc$iU^&tLzF-oFzEhB>2BfiwA#1@Rs9DGDIjo67G z_X!+liY0#Wgi`6#l=Nw((kCnFQ%j{!RnjxdfnPFzAWhe( zCzd0hDdos#ayfKnmdTeny?i+3=|gF`WtJ&tbNb{`atNe+k@P8V-|l6PAP}ZN#*G0)H3NWZWohF>3L>3aHhOf&TrPsgg4}4 zoxij`nE5T8znIR6Wwzh);J+!iN#*Fn)@xUf&=v=y+tl_>z>VW`Q}7!C+^hif#}XW7u8@ zdLC3>_}4}WWAde**n}RNo`4;?l#j+rb5R~&S*n4)mTBXNpU{fJaYyW#;t67S0!uza zQ}#^P6sj=1bu2P7vgfKLpY2bZpH*`H2-wz33NO`o#6>WN914oJN=lr@_Cy!*%wVN{0pe`Q>cu)5yz>wFxa&?t8u9d z8eK(^Olh3T&AO1ws%r%khRqEgQzPNOPqXW%fSDHk9_j+$DcqWd}H~N zCClMY$@KK~)QQ=jf~F98@D9j0d;Wr%(rP$0Y~+aHTTbkqyGieRapn2jrDQ|BO6zCs zL+iB~7q)kU$U@n>LC>}^-Bu>eg~q1V=n0){lWh1?IdCWkRkoh9cVTn(ivHbV`Vh&U z_mStS?0r0gzmMRrN@T6&swLXmdE3Nmy}9}>#iI;*an^Ga86JJ^m@O=^mA5EF(a8;8 z&J!#rr}vTO;suq!aB4=`PUqaR^d=cM=DiHH3ANRnm zaer6=`^0ek3}44r@sDEo>kt?S(_kvFJM*~R2_^kRaXR6T!4!=0 ztyv0Gt&EsKR?t)Ef{~Iz$}k#985YAu-gjcARLQPnmGcTBx+&+StBh?ZHJaM!njCoW$DozZ z9}wPF7ClsN8XNn@es6H*zD-@(Wt(8Tz~Ja-#hHs% zL;65J!RV{i=%SFTM&5xbGZU$e=GE@=@W}S~#!Gy?Egm`V?9$71n`OB6HuctzYgX^_ zQvM8nh=0bdA3T7)pohx%;A>nM-_;>5&Y^2OsQ-ZvWLrZloO&ef&-r7tKj%WlA6R-_ z(x=QLbsETj&(i-8waWbOL-l3xC1*=_t8=WC(Jyz}qtfjKoYL}qIRS7}+F?T;@K+%s zKObLq!YlC^d=}4v45&pql>TBe&cl!K6PyQ4iDmFQgI2r_LD~36+!sED9?%m$#r-(> z9P~r6P?$hk2|edxo`BN?LKH)6RB=W>MvMy@xopRdW!c+zK>r(gd6#YRzrVf2FUY9> z-oN}0&(59y@hL2Qici7u!VSpwAAA*Rf{sWi9zUXZNbjOPPV9{{i(gL4?Z-~B zD6uuDmMS1)qYU!Aq8whs&B9t8Pzf}m#*T~O_@BHyxH>Q!&}T|WjXz%EB|q%Q9JcD9 z5=P_Xrcte>zlC&M-_K>rd=^NMOaqER4J$|;;egG1os@UxJ49XsOB z8-=j@IPhcDQz4ze_hj&6Y4Ge)@SVZ1r)zLev90vUvSkOQuw{H-JZVg2vz!E&Ccae=(hq<3`AZtwTl#f>ia4h-VZBjG!dAm>iW@5x^ZHdbNYl;8YC5D1$fz zj!+ls@%^Pw4&sY>IRBuKF1er=l!QG}5V~b*UED`&g1B+;fc76sU#*;}*93BHSvwsE z)r)3u0$X$HL)s~|77Nz?HAR!b`3UPyY`!ueEI9IFQZ)Y zjnCss_#XJe6Y%Am&^4|#SFfVe*REc@CM8@IJ}TLC2~I+b*ie|D#A)>@#>q2pQQq2a zHV@<*ju52%uU%{Y<-_}DPCa~hir{L7zrgqK4-_iOCpeMrDIWUt$Mff&ttIq4$G@=i z{j9;7eHXidL@t3kZ+iaKDk;4PCeAEYse8?MNSkVk7KO!NGN=Nq!IdipeC)HQt zZ&quB?pzfzh6pF)hI-rw^sZNK294Jua{{IQa&icRXcy(Le>u-wsb?Kq@d*L?O)4aa zbXdM@F+!d?tPS*A+2cZE{-`NJq4}&?(yy~-A+7uu|1)cr;5TcQX+rLR0lED*uy5GL z{%mC5(k%7|XIa1cVBz-d3x(+I_+bY(XJ^+A_`$X)1dF$CUyLHRflmilXJ@w#P6PaVakavTD-=s`CS(c4vp&?AwfE}qjtoT%VB7 zbjJK%&E7{TIp)v>6)^=D%z0-XY2~}~n0lAULud(LZ4bJ^ap|B;DtX@*twoE(M=YKv zy`GU?PaXu_YW|(PbkMS7@zHk;r%N5s_UR2--jyWpJ(kxP#BL*xbBB*={*%0H(9&eI zlH^6(r4A%7;=V*{p&`l3v)G1gyM|V64El2F)Txer9rOIU4efG-{WBEOBAx5+Ikv>vXIh72}Hx@<->UcGJ0h z4bAoV05tc(n^0vZ+g*7oyH8NiCvavHUhufr5L}46SYRxX&+C?g;qG!6LiKbTl@Iy4 z?_@J$vC3{0Ok4$(R^lJmwdi~V=PB!&aFK7${BsU8?rIdHF}V6d*yzpk(KpgV{u0Jl zt3!?J$oGzU9ke6gob=gc=SL}){72>dG}c~iHaEoL7ZQmU2hk#Cgl+S=^sq&}Swkhi zeEFz@Id&H6F4dHMA>5JL4d%&PMO9<|FR{rMlg#f>BCG8mee&!lpEs#NOmT_eYQ2B` zQEE!eQAGSwW`A+AipChMCfi@~kKH)Pg6$aSFfm4nb4WMfv)DG44u$WA`wYnJ)uGKw zBF|Bo)20oaGI{QaUcFP(KHUYG(mJ_=xwsm;#fJ>;Kkx4NaXOv+ladzCYSw%u z{A6lQx*Fi(aIzRJuA?(?X5@m5TRucrjN05g#AxNHjRse~J|h8N#y@uJ)q7z3^Fxji z3c7x_3wB8ZSsc4fvu7XV`@mgB#CN~D=mNg15lKjxk<@$({2^_g+j8~#t0;Xj9n^1S zHhMGh4=1p(dRr#@nYbT+UYN-4wp4CurI$UpD&Zbo&3%s&ODa+cEXB?u#=`vJ2?--d zoKDW^*`sxv4>D^vY1Ht;HOuEVZP~uVM?Knf_@GPs4y|8cJP&sGcI+_WQ2+jw0uO}g zUF$X-GNei4l`T5VoYSF$w|D%p0G-Rr$BR$Oelb6p=)A4c_c6!#5IQaW1vhZWAt8M^ zzP4QYlkqaF=plcO&NI*`VWg#!c4GTN8LQEg+3eI99k7J}9ksDAp$63aF(%~ENX(tf>F^G*jW4J`Fh1J-z4g{D(CAwOM zb)|-L?h)>94C{b6bxJO^3LTS&ar{0y)*ISJ9`Q+qRztlEml6X$X-*7`JICI4t&gIV zAzm^Y1qRu%q2SRI<}u)8eIx6EAoL%)C4szi*U0iKdT1NQ_NBS8dCe#t-BGPL=t1-z zPbx#JK|=G#d11qkkb!$G$iQ>RK>o~;*43qc7IDrYBYp{ZGU5mE2KL!C=_>Au*WvZJ z>(!KzvS9guQo{xs>w(C4f-**qr|pIzBm_92GKA{u9&0Vl;-Q5&?xh?fY)+iPC4IrZ zy#>~CglZ$^;a19^Sy;Yfd-k#&JA?`5LB+>)+cutELUu=wN_l3v?Jy5QSYJWpW;25A z`FEpHzzjs|+ziwJ%5$DP6&yN3C4whBh9k`ZPVKr##xzgxs4)Rl`rE4peU3k@@C6;$wKp4 z+JJPal=c&za14#nC))~z2WBg5p(=7ET*#cTe@1ti88jLC;m%7RTX^dC40>Ia<`0OW zY;9F+#0^thQiD1375!y=QT>geaq`MB25#==fTdQ<6R(LMT}G?#=X`ecmuuEsxrX&J z|M0=$(ye>QCHNTk%91WwWWaPtgFC9%FkU@m{Zv_oIrYF&cQUsyIH^VRiQjHdt`-uh zv#|U%T)fIEam3krb#nXzW=1NNnJAo)edGzaBjY)U&O?;Pv0Q;pAUg>4z*dM!<(;+L`KDWuQ%llB?BC+q+0 zgANo;0XhaSs5T0279 zS_0G2!lM#jx-ft1Rtk9QR`JHY&8E&dLYvJbe+Gg3JAun$&TB2vq@i=({rlv9l^#FX zT)0bUyP4ipMs$53=`&o(NS#JmAj4?tStGhnGANKI#a!ZI1z&oHQ(%zJKpY_7xLBU_ z7)Lg`XHK@?bAbdp|6DmA78#SZE?1*USr8y}(ECFCWI6&F zAyog-rI&Muxt=~@H+k;M-{wrVJ9XA|*qq;%cdVyHqqOxpZkMLpBzMeS*0F^!VeRBg zS+BA_{+N7Sn!I-Hs1DOJJB-Ew+xw0BupejMze?wxxJsNqi^gX@lT_S;%6ob>oM7og zi@*3FB9w5WvHDT#4)thte`9qfBs?3&Q308IR6fh9cYS#^rcRxh;_fxNPD1oG*o;oY zr<+T5u+X$rhs&Gi#7J9kWqx3B7izGYsEd@jiDJDm6DkufeG+q({?iny{8;vKuB(fS z>)hX17yR-!`RV0v^y&uw2XpUfnaW%1;pOFFnb7-~K7Cv~t!EuC+=k6vngd=36bBA> zE!NXza*XhJOWg2ZexVIFT>6@A6OiMEpU%Q25V8pDqCztM*v#UP(#>?5KwrYNFAY7+ z;_ybY2)uzoTDB)PhJXASzWdo{;BPv5{9vuU6AFk`DVVUg7RCpmH>`O26c2og`(+8w zb9(o{N2HhdNRQsQAZyVgnGa$e#Z`n4SxXJ7tZ&l=p*CRYRj|c_~D+?-vtimP7uD ztp_2}K4;YMuP;7*dJ#YL^zf=59juTut8;C4w8bKpP0|&*euS6Pd2C|ujMnQ%5EK_g zBUoA{hmo3|0&q7534F2IBHdoFz{-)`Xp0AuruO+?Cn$+_{9xUrf zw5gczqLieGlLilRrZO5qWaLR?L}z?uUkhnCIvQfCz%FZuF>pjTVu_CMn`-Tyc(I5p zx;Sxft-RyM^XP8qg+wp5ZpC-E_U-|VkOms{=$%ujCzYSY&mwy9l<0?*F00vo3N2f= zqBF?sOmU>35zJxmnI^AVgyZvn`30L*;P`PNNV>8V9G1YYu&ku}xakADOZ3QM`X%c! z>l3VWIY7A%KsNrxI&INq9CPsa@q-u_>$63dL!@1*HCfA+W#Kaxg)W~5twO)6SzcB= zm^omrv6u(^4`rcSR`1?f<SEX#d9VAUr5@Vlf7ON4`{*-zbLU zur_lNcZ6|7ALzJ`12sK1TRAl^Pnh8K?_cuV2hkUzyZRFI7Ou=lx_E+7XuW#X{%`X0 z+w|?T?%}fw{FHBQ6n$T4qn`5H?1l~SNnBu>UOfLn@aWizpjBXb)&$*(Bg)fx542fI zl_xz4zf;-m>eKsI=GVL=Wxo`RE-Gpt3GEx88S2T~o7eec*gw=0*M(E`1I<>fphw{$ z2JRz{$)Fb9GoGmuc;GosMR#-97w_hvXLdA?3KDI7`R@E4{#RZ|i+}^1+E?9L&8Lxi zC$2NZT-0xJ6>mr*@EYht_&USqz%X{+DlX9uW^kDTCn7LYn;EsHIqAw~IQJ9)CeN>!$ z=SA_1N(688rIi9p-Q!w7YU{k$uj^#gXmWfNO29t?{29Z$%t)&F8rhie25I=j57!pt zqgh9lIzBFbr}$2EcbB}Z%~tv}XvOKA9Q;xmcv>0O+@MRLG^#nL)azs6Z)Q(u3!!bW zjJjR6tW@p(O4mHi(^^70t6|^-;%C()x)w}##nBBtD#7Sa`e1e|13m04xYKP<#L?ox zoko-<15n{hd;qzO#!oijO=lMdw+|T(Fdw=t1@*Auruq2Sd9!)pY)GM-=fHWO9klfZ zEZHJWY1aV?mOk*F65vw>hQg|*O}^=#zUm`<3$mx+?q82x6(IXM0?~a9;VqDiaB2~n zG{|7SGL(4p%9VODaW0ApjdOPfQNDCfj(8ylz!th-{JO`EHf`3m{XDnkzKLH=Zdj$i z;X}3QtBLz+=4BfW9F*4UtG8XA{i&lavh9lHpQ8Er0e)85XMbq5qsP1U>iKcI;l^G; z@pVCfT0MK^;JuN(>eRW|DPic{bFPzn)*pKJd}VK@D}v(d)AFJ-urd(yLNz4=@h?Zso!Sv}XvoF||eyZZJLMNV$VqK3sh zD2@T|R)xYg&kdJ|`Yr|qFrUmS^845=?U7#yUezgfF#Zld9r&v`-g^(}K?w9|5z(ha z)b~DBw4YBI8x%kIz^!``mO$^i+$m%Is;9GH@0>!HK<72fq|04jd?9d2y69vvKfmSH zE_3JhTpk984ESbJXj}OE+b&-Y?t8Y!v;}>(`{PyyFxCxBzV}t%T%q2s;NbS{6Pp?A zmi6l88=O3M?E$0lSWHakHc71mY_fXw@Cs}`eccYaS)hoF?8No*{T#%iuzMe3YlBwV zT10x|uo+|4p14Vu7-$3&F#@^`sL|x}PuLMUEseobKE~7jhsk=Z*cyidbrcjyde?yt}d=8RrxKhV4fd!zprkzb z?#@Hbyg!xQHR8Z=Q7n)N$Qy_*oQBMcka-4Q!Ecl17v4)PjvfHL82jvT|kg1Yq5jhdJ6Ty_)3Lo$p!cL~PgGopsx zxbZrK-o8O^-jL(ToDwdhY_^W5JpkJf@dO0T>FcCxrV#+B`;d*p;F@rG4#~TaUyF{C zy!0-yAmY2;Y=&%t`L&~~OM!%QH z^ShJu`xq3HCR{f4Zp7asdAg8F__su!f9<6oC!*TDh0BEzaiXCVEu_PToA5MP`iCuB zLNikTr^x$k!C#}+HRd>6z;t3Eq2(w`Yhp`*q-CR*G9A)NnGS;UC`)T%NgGOVK4NJf$Z4fyCFA@( zO}aP+Il+-R{Jln|-X-X7Rm`Uaesc@_QzR`Lj>vSFddv9;&Z8`?iJVqa_5m`^e|t-3 zCL)hHb3{X2VMIy!v@e#Uh5lB>d|Kc)x8OWQ(z3ZZT1E!}r`}7dP?Hd$tPw*uri)IW zBj9X!K|@1moIXuk&rS2ooQ@CFnu~iCWNUlt-RC>NH*+%A-KY^762^adxm25J?W6v*b__G(5+C zstHXxjl15)!i}4!y)fZ}k=j?4LjY{4c+!unQhi`OMhv0Bo z`U#(ldQU?{jPk&_YP@TN$`4=I27ryWvVWNTcsGF^uH~scHQxbFe!D7v-}X**vv=>_ z(ijvd-6o$gz1bHYUPdAxKyN&k8qsgjxp(i^b9yUj14!nb^ancf&MXzy)qDR7y2>R1 z(^m5L|5|+|wEaJg{Xe9!UMNM{O4N~ji=K))vb63b^C$EN(b#uo`Txrsyc__@v}ZQAY|yzY<23ZBKP{REGJ?h+&@%y;WATmU{$1>!iKapBopppItcfs8d804>}gz>IO^w)u7uPJy6 z9Nf0P48g)6iWu8{!D{?PFC2#VdbGRQHZd_*NQ1?A-D*6xvNsHt$K%6T9qeawz8d+i1&u-Q zglL1G*4@Zc36Yw0!+y}^@=!9Kt%V=`(e7Ad*au(0d0YveK{&pGzW`{(kGg`3{sKps zi|5O*hbpkC)KzM?%0TK>7sbm;!bKt{#v$#jMk+4U7gqS)!f{c>v-K{yMG3=*Mf7 z#8~&(C|@1l4F7?DA(iOJcd{$Me}j$t@89Tfb({cS-OC>JH%v#uQkaG(OUrO7Y+i$# z;Mb4g4qSzC_!lXR#*{=ukO4ipEj?p0=Qx2U_-Q-U@J1Jc$w<-Zj7X+L;Mbhp{3pJ% z>-=VT2>VbWo`)wuL&$^GFd0w7eQ`Uy55~bXSWP4M7T4nj)=H5mJGWHJnidEs&ySurf^Wf3@^=mkbz2Oh=$9M5AfJPaRur+gc_Q7LA@ZY_A z;dKh#Ha`=(V_0kP=jGPoOJ$^W)e}bQfQ!+Wosl-O1&KhSpsp@rth)e)zyN=Mv{6fN zoe22i$KkzU-H>j7z^)%InLsMyc09bZ6Jh*M80;ILg`B_zUk=8r@EUw!OGd*#;N=AP zdEeo~`*4+hhj4G$d%hlg@Dz7}Ex?gdC! zQAP2i2cOv=b4nzu3)L)q?jCf*zd!y0|NS%6{RZELW8Y^?I|vuhDWW{z!cgb{U&D0# zwKNUQhG5cYYv9lD3J8WZ@HH~Ld@224)t~s7`;)jRb+KWfGnFw>dcjq%7Kr(Yz&84G zmFceIJ-0^zkJIkLgrB)0_$B~Hzz_TPqbKDVH3AH0L zZsJL3ANp!f_s^y&^14st7075O;-NL}%TwKCc1B6@H@N!qaZH6(_wlA*VKy$rf5Hj; z1e;*_&v+H+!4>73e%~_*?BJ_uGvThXj%bpOWmF0+nh)DIE(44A5F5Sas;=|522OFdg!#1d`FsN_{ z9s|vi_Cw&RTTdq9LPcicK-O>3Ic&Aojox1!qb1OcI-`!R$O|qcm2Pq%sV;HIZbk}% zE5H4E>E==w{bBtw7pVRkfRMfoAHnBN+!a3yf4LtYU5V$w*j12t02(3FFTD0?qf|V4 zFFtSu2g1!8&}~(Irx&pH8)xkk zfQmEFiSj5qYaSWPOk5oKL)x61n&^$7bmIg+v3PtF{3|ipZXocHfRE#6y}!nvU%Wl7 z`Pm<*Osst!|2=b9Adj2j5cpCWvfwb}JpWc$2V?N!`84RSbmBVx{#It~sh8#ge1zuy z05MaCFCR%15m43nNOSHa?t&jLoxm0A@_M$uQ`}rU0R^elI?{oPkveS@QD--7j4NnN z6uRE!+|$rte*z5I@!dAar)~bbyQHITiTsJxhpo8iU+9K#4s0^RR~;tusK!pe%HE33 zg>+D^DrS5cGNRxlfnHf9`z)dM2Pv$y7EJb|--c0ayJFQwZqJty7t{xR*~Q{t`g z5)sl5dwcqUH}Xw_zwy7I#=bp%#>*l7_x8{pkEFo?U?JW*1h>FD1()IX+xBXFOyN0N zwUONr8qp>G8_?+^ie1DpSW3uk=2Y&OKt#AfchQq}F z`~yFOM(|HBdjtoAw_UitJeb%myAM%KYg=x^Zo<_vzYHm++{NJLu8lVOvDF+yjNBpd z3r3y8cL1etCAQ5L;NhHoyY_F!Pr*C3!*xg^PVU)eIBO)H2Wgl`4q5Oossrg0b8FSg zU4P;P-mk>GXijia-r@*+tt;uti2o}KTMVQtyri$ysnKH1r>A$VfdV*j_eXp?^Wc6U z26hVQMW>~s@ss=g1;BN>5wU*;qxbA0js)~HO%z_jm-v^Z1kZ57+n1#8pq#l8xzX)P zL~H1gd~GFgCv7`W>Baryh`|+>pnr(Ld5jT0i$;Dk3ktUH-oc-^+J(sQA@LFXMfI)) z6YyX70o$fD96p9n;y2BIg?o|2-vOL=7Jky_ROXTe?dNdCvZX%0t3|d%uu4BkoFHu! zzhHbmegxjoXe;(1j>4lY%eNvme9{^Z?~F&lVCfaA+nflnEovr@8>SPO&4}#izC}(a zyVb6~tcHjiuZ@i(N=k7=DMNWRn&GeKZV|^p zt)oZRZ)ntL!y3G<17Ph~=??P3GhxJhXq&F^k;;4^DoG>VGpe)dws;!nzz`J_rYvL17xx9vivj#Rf)boN*hZCM=S8fO>>|o1m@Bq*ykJPlKy@nOyN7=6k_0~ z4(%>oK>@-_=}1f9WE=Z{|5fqJ)d9TVt`dl5$HoK(1nC0e#JJe#K%<&nj;?nG{?``x zvn9|P=m=~TxL*MLdek#Kt~F#1)HP3>wsuDIB%k4Y!MyGG=b?AcKG`s3{E6VkkbP{y znN!~F;&p41n(vD{ZDqscev>l6>L;3Qu9mxf@`v8Z$oz6QS2wj=asM2)`suaRtDiod zj)#mHgW7zAw!!ojunIRr0$xkTl>29lgU?sxt;0EMdbFIq{DYx%UogQ}SGAAg6D=L1 zj3|z2eJpFzTH>a;xsw5ks|KZF@6X8qHfZ{`ZG%N|`j#!j@Hg-j)}sReJ5Tt)6QM=n zetZaA?xDTYCw&3And|V?PuumIJTBK@=9GP$MonyD^A^a0OfJgXo^rx$K(N4$V; zum#nYPU3EO6aJ^wu_sTVc)S&@`keXcO!cFb5iV=tTG7?04bX^!mY7R-9B>o@Ao%x3 z6QHZ~`APmPVX6tNz{zm^+IRRS=+{7{%{w8({W&alm5#3)fv;L{G*IQrzG5*B4XrnS zUS$-tQF=pUTof6|3UcioC%PYoe>yP~`k~LJv)cTA(rSBr1FEtSKP2s(s4rmn`}pvSl8uYv&5FM-EJ5ax~{L-?RW{O7=bxf*s&n|5jK_$vJTGLAd z`6wN`Rd%&x@@n8dd?Zxgjs&NsUW>cnhp4x&)F|!iG<(zKu z%dI$c*REYn`ors8&7_U@f{7ts!mfjST?++E1BYTIrgm=}tkS8jaS`++IJj}tYu6&t zpO22CyRM0-1b1U#fJz-iMs}pK0%PLb)$$3TK#o+Ud?6nl%<+Q&I{LscSK<`()F(6< z*x@_qgF?hR_IToo562H$i`PLd|G*6%AN3eE74Q!9>91A1VpAI00X$Y++l-%V@7q|9 zL$R-34?p)^WM`WihY#W%J5PMSwKKnRaKG?p#8o^V-(vLM_;HJ}=FT4vUe^nqpsg5P zDQzRpwzHG@A@*^H%7;kVO+M9U@wlQQwSmMrbaQvRg*r+(=o;>d(}MOGfBzNm_`~Sf zah1<ZMLh1}MfCIy;PLtS z`KE+7!E=HPU(InYgyu@jdwvr#joM)eX|ba;bjgvj1aoEVkW(5BIQ-r!>a{>Kzp1{-EMsXdD2#2eLR*8mDS_-NG%Rt-Ot#-R4V|BPF1 z`m8J*X4=OQe~*r*kuM)bx0mbQM8OB^q+Hz?&zv3Zuis!|9F5DhVntz%GLXpo>8kn4itP{*>ms8VKKl*H8en@3;B z6|(A0Z0cBAC9gM>i_gpxtry?2>!k!bzO|)tj+McjQa%4REe|20G2;0Xq>i+f*)lpo zr=@dcv^Sx(#-CWVbLn4r$*zxJALK}JjJrno6+RC%26Yx5LZiJvEpSAhaBMke1-Ey( zaOol65^(Vs_c8v2!M#BGic)Zihx3mW+;IeMrLy4iW{H&qKHMUvauImSvXa|Ik@$qj z#GBQD3!Tb9baY~jp{NjjRtCUSJmM3;zg&TExcYR<(`x|nSMU>Q;z{;txFc zxr6v4nmxg8vEACXL-d_mFK*Rv14K}Z8cUaL9zMj+z@6`RU;+LVx@H7#j68f8pQCyx z1l{$Vq0kj8y-S%xH5M5+6s1ua6;ZTMDic<1(36*;*IpTI%;r?y; z7K+Su(Oa$y+6%l}8lAuS=M&WKt)ig4PwxugrTsxwtN!4f$oVD~odb`zl3?y5K6qP& znCZB}vDmzzGX|-Rx_65p<(XL|q`KwiRt03?7a?Hd+UR zMxPv@F(sUir1z+3637?5rXf*l>!{u4f-24CJU&uYaXCWon0*o%i4$H#YF^OW;au6) z^x~W0=rJ$4OPYo3ATKB{V$PmkE$F)9L99NwXV0#qyY}=73WR@m9aZU9weH_*u_>It zLO+XJ9^SqxIJkc=@|VacoXx4}Nw4e4wN2D|HR0TC+?@4-jScT+r%J9=OfODgmtolO z+c?c^Cy!%pd!0VA<&KCzseOT8XkO4eMiT9dyf%1cc}?}wc!|Ic_mm=;P%H;FlPTS~ z{~)FO--8E*^ui5h8o$_0iH3d86qzbC#w9wtHvt>L&cVh;Be*yvyHWaN@+ftV&i31E zh1uLkTH7Ozh!TbwRdUpqVkyexpyr4>h`&(eMueu)|NC5=V3rn@6w@PuUu7crt8!sn zmqd^7Chj3N)ihqNHkGQ`a#d6|{yw&Tfyvd2MRhuoew&!U+`Xz8xA|*fHWzlR+FlL! zk(=88h-YO(ctXOXNb^m?n&(PAEA>f(DVl|4xew4ncND$r3H>8ia3}AemeWaPw?O-- zK$Y6(i9AWg%k|vBTNgydX%?@UIrPk;vy8t$u4STIa1%!xjhlzwMq|r)t85HjwpEPD zK~}sm)|e`Ic>8WMXwhtkz>i$jh9l0Ed}OBRtv#hVBCV}t6-tbQv2d~7 zx^ArMM{aY;gnk-rQ;xMm54)P-Q%Od;yUBR1!>k!&cn|-8K7Ir@!PKeKQJb*Ae{ zRzY>D0KIZZIh}4DhbX)_43E1Uy|x?zqiAk51IM@N*sOh%(e-NAsIk1>ms=)G{5Czc z$Kbxbdi9vrq)BAh-o)+6$$f`^-n507+I7={p500?GCLx+QRCQXq28_#t-e}Nr^En% zgHy=Lxof+2)w&pu#Z>YN3vH7WY^>(&-#lsBmX;muD_5D_Jq^-R=OmY4w`Kj1NT?B! zScmexz38FMLn8MiI)mYAiF2xr(kh`!qJs=dcwWYnt3Jw5;;{-C_>xggXmO#HEe%_8 z@;p5>w^PLJR(5UOW$eh#ou^NS!S1oPaaW#ypYBu}z5`2$lauH90|5q8){eftUOt7s zcq0vK0!#e8yR};~y+Nnl6XwNFPpaZNes@S!-z8Fy4eKmHPe^tX|`-*bWV#_JqyN6Lsh?7%XH4spe;c+k)^*T}Mnz*VXyL>qL-DKN3m{9_q-Am~pD>83WHjQBla%-{IthX?j#4r?5= zm)}k0PWqcL0?U_1sxg8S&-Ak{iX+3ax;&AqtKNwh_QUvJq@=K(U2Eqx8#}%pp8X5T z4eOa&J1??j|8y9DKSCd=;=6s6f?t7M@10{?y1_tc080UfzdEiS+J!Dsb19^6I7)EQ z6VgWcAeeYG|B$JQ*hlF_ohod02BsPp1V_0pE?Yb>=#>1Mo#2|O=45{dNT2}cZET|T-x z`IUmcS@GlIRHHF<@zWJjF#2}H*1mPz-0Jk*IzkE-((4b%UbSac_JI0}sx=)tdiCg` zO{pkl`EhPD77&4u&`Cy%wItbaqr{2-tod*@O9jbNLE_;II>@nUi6Q6h?Mm)mnDpA=`llkuQP2xMj6tfLw5d& z!&_tj2`gh-)(`xk`cA&#;**0zQ8#H5N^jn)Pptsy(#^}7#ZDtXK~akv&dZhI-$G&H z9Z@i!ey0Kv@4Ut+Y%2;wVL2#Fy2j2RQ6AcfD>Q+kVI$|F66E`@F zq9;l*In#0Nca|Eclskk+E9oAk(#`qxCDI8Vp(#lZ z620+#_9jS9FZzquD(ME69&E|)uB2zO^s1Jaty39%Z{C?50Wv}abb`JR&{fJ*o3?-`8N<);oNOAAGjmGRC%|Tm5MOa%jcI!uVG1l zN$-^*>1|kgq=moFh2a!;1Wk=DmJ`Y-mIt9#zT-ruwV3ZXi@a$p29`d8rq?v56Znhd z^ocaRmQ_873VfNK1T!2_D|Dy%uh7&w#raF|Rkv7gSh^>wX>zpai@xX|VU87@iN*B5 zhfL25g}LlaNU>h9^eROoto4H8RnqHQ$&>NL^t=jZ;Y)7Y!V+RnLKQnK(B3b)t{BJD z(40|fs4K|ESmZ}SJzR|nh7OK%ey>gouNr~yvqrR|QcvE&Un9BezcN1GacAl?U zq#|{P6#=4#7?iH!zbTpZy2gxZUe}Nf}0{9lM2mXb(!oN@s{0nCIMbA|~3zcL!@H2|x7d==1 zYMpL|Pbzk{@W5I=Lb9BWCbRSc>vSvlgw8VH2U56{9{N^+|A!TPLT8!qm2?IEDx#A~ zFhkl}3jQiHeEF>cCqnFDhA$=+h2Y_4_$2>)ZOTfP%W{~&g!6$EpJ!QbZ z0HI<=8SpQV#`S=}`4~Hh!F*p;kjjT^0`;@y zdPI&z@p3xJPt)gEr(3~4gXVFbWxzj!0*js&!!L?20sjnS$?%KfOTbsst>B+SE4US9 zz(0pPxyW+qKWBztivDwNz`sD?mnEMIZ-sxM9QaB)HwjVWZMW4xACI3m0$bsgg?T9;q>zeb^bUD8{o#^>z z>Z&x}yLd|3JNudX7U?rcUm73>-t*VeZH1P|!E}NH&I29-naowtkcG57+Vcu554vYw)gZ6km^-((&TxBRLw|KY$5+O zrCopAY#W6s?D>S!h6!)#5F)!D`F!R#oU)|fBI$v8ZzenT)(nrOSEjk$ejLsf!)56{ z*6G|dX{!SNJi3855%}jV=`ws@rLB^;6pnOTfp3u0p)tNLrz`ONtkV_xYf+u!XQ(z8 z!)Nr@vcP9=E%ev2z(2z!nbQgUS{C?9I=2jeE;dCk2weI8wPmEQ3qg(9UNjmpM5$Ai zx?DvN?uB}}MaCo~P5Z!)@0{^#kJJxG;Jom>8W*}Gr?fhiWaxt$_egJ@keC-SWZAg} zUIBxk*Y1UL_dk#E&__J%Gd%AiXQo4Rqq@(X#{n`uES=CJcoVuq6`egVh5Uy;B&+DC z=*2%KaKB;es#(}k^h4V@TP}p&mKRVL=q5>`$pJEhZc!0YG4g#Xt}42^@1|#0c@Xs$ z8TT}lq6+P;ce#C1^FZkbO`g+4eU*71g3zeCE8UyE^^@wvKl;7ah?B?=*t&81X8=R|y=a9!kfWT0cP@ z6YC%K6xVt39M1fpy54WV+h z6T6|-MSl@Eqs=&F*rZ=ni(^XCLHkNMjnrv>CGSCnjQCG+AR39fHR-i+eB zByBL4NAhM^=Pi0ATtvN9uSni;rQp6IdB>H2>ml4n32GI|JHBLIl4h3MctviXa2R2fc@^!6pv1NH1)Bl#^UKbXk&OPiV`|3vHjG#$+#>E`?s z<@`z;{hZ}L^+p^0oaDc%1M!{<_@M#|XXityCj=13_kyUfxPtkY@iV;IMLkM>N*Xe?wx2aD53r)Mo{ zb~2CY*y`4uV3e@2a1b>DseKe$HYww?(|k?V2b;%do7niwJicLX6}w- z+1){N5(3W;sZu$rX_vgb6}{Iw@AGK=g=ucL&13RwZ8tVe+Oz}E-Q<)l&6gy7_sP`W z4>S9J*bP;7ch_musysCqqkFFQi0;`S)2nq}(^>;Nn(v7H3ca!|d*7Z%(2VxMH;?1kTX}xTwi5Hr)8%m)cCh;Zy`Zt|0^A4zQOpsg2RKTJkExDXfsBEQ*Y0li z9AfDZEsC|Cyp|CGdAh`*i}IL&myBsNB*3>>#5`?{?uqepgFM>LJlQ&9>Ja?PfV{x~ z%euGe*?nBML;y`Pa{88yA&7ig`bSEiFwdN>j$`R7tBehkr%Kc2{b`uUNo|7_^^nTt2F3FR(E;;;5=3zi{ z1AHoJ4ozLtqNIW~nm2gLvU$#N!I4V`cWdGYDBy!`n2nW1_u^P-WrdN-N|lEkqXtc20vOliT?z9GaW=3EU@uXYuro)6n)(M-u&|M zgkLK>{{w!l>VW!wU$Z{Dw>h2G1*x+wiZA`O*@vX^A?cqfeb+g2I^~6=Z?#V6Mw7m7 zpHPj!?aS(zJ@Zan0E-yRE*p`zZn8VEsZiBEK>79!GW&xN8|~++7xt~hMY!w7JrCDu zG^xjn?o+zf?AGW&hYeZyuYXoo9R%G^UYBaj`3eu~b!0p&T@d+UwV{a-5sAaQHVpAi zY?1dUbI{;A>&BoJ@##_ivLD9(BUEFzC`VFPi~5^Uu6`=n&xHCsr)hNgBsKh?$OA{QPaQki_ZNujy^3?sx+!IJbg_5)@Yyb ze*MA^9?T2&59-h*D6C4=xahF3=(ws?!h(9Xs1h2ShdQVod@FbFUfI`y)gzO)*o65- zV~PD|^bvby+T=FNTFO6k4Me|NNgr!j19{2v?@`h}VZI()OA(p=h<}z|tD*Uo zwG{HUc&&!yH?O4-yv1uZq`Y}8|Qaa83n=(IX@)a~+T zhwxo39b-xFfWO>4u(gvzqrNF^TQ-Pq6qZmkp=EOyUqDG6<_%f$bsv03ljnpsjGMBc z^U9vd@~C&!h;_oSwt|z7!P`Y+=bSRMT9AE;U8PDsfm)4sc=a}cA%(++kPxo|+#MQam+}4@{UaqR$%3_-P8;Py1F})@ugkV=b{#;HoW`fa0}*>RxLUdxp=8 z9;`kGGas5ftBh>#HW$FQcUim6%;WRt1FfdG1(%j`6%23b;x!Hz&g#&sF}@3sm{)&G zaI@A!b~T&)P#7qSIjVZ_-UfbdUBP8u>ZnnZ8)*DuEc2qf$y>Da-m&|m2yc&oiaBnWXqJuyf46dp&R;x@IHj;GI^L*&^M#Q~ zp64^_cR`z4q&97z6YLxuI3Q`-?yc3_YS!}5r)V9#8Z`>u=48{lrFY9pt?)7!va@eo zwczD5>iK`LzhNk&m)gprOZ*lzgmY!JLupa2AT9QMim9fTk*WCJJ(hhnG_n7N52HJY z`q|yu?CIJ=dRcdUxGp-lT1xe<&g$sCJtOiysPTF0`1YOi7PoBd64N*-uxdh&0EX`? zA(!B*EZb%azBmg)3*V)s#Zb?`DWeVzp}5nUHaMvjqx=UYP1}R@j0VxIR!~q()kuX5 ze*iZbcq?gKh`P;NC5VN|yGqRq~Zjt&`Z zhat%QP~h{x-!;C<@T6&7nuP_sF0~D?uS!clBvSnnsn{ z&731v@0`+zda(1g# zpA>ZcH@an*vrAY+i_kVdd<$HnQ*iU$(^qFKor|`sdOB#MYfRFr4VA&sE3s*v>H*PV zAx58oF>~w(G;W#LzFimFAg6C%LX{RE&TCx#6G&leMf1p` z?QZB7*gUEI$n0J7njzr*{2Ljc2+!<|Wr`?NhZ<<@lu7U?C6IX0{9On3vpr zIj{Bz={&ni%{57$fNG>JY*%`nhRtKJbsD<9EXKw#GGu3nicirw%UxD(Wv)C5$z375 zvQKDq>-Ij?Mt7R(Yc!4=KDd&+N^6Yp@|n=HV|o>bs{KH7|nEVz$@%vHSg`f z)|f2m|7ER-q*pI`&L3C(LehVb=l}5v2$j=?+bsQFiS)-bzxoqP{)xru!flp*&pMrR zCwg(5`QLK>NmyPtCg}ve-jbiClR9b7=+VnD!PHi>a1h1Xr#6Z|K0mI-rF8?7(mRZp zgWdK+PGx;S9^U|8zun=3T;Dw3l|mC!{gAl1d1x1BhDmX;Gty;2w3^-LqiZ+I-&hK^ zUt;S4nY;UHA)#yiQV2|qcC}xZ_eWK>mg`g0-o{Ox%+3W?<2YNvH7X`3CYo9Cda`w4 z-GzMHhpS%Y%&wsjD)AojXqJvzn97i9Qr_*nL`dWF$dY zRr3ZO418}C@dQO|Jt-|X2`c#MPouc+b<0Hf3)`U_G?8O`oG3U4Kd}I9hM~jAU)``*Bb!wgX{)^;#A~f?qiGR@h0YqDHw*`KX>0e$wMan>PD)TnH z%@k>@G?w+z9MKj*C0-@tVOMqo2EEb6jVO#@h^tFlMRf=|-vwr@TkmNX6ps($Q(e9~ zSKrR%2o|qqjQ_U}?l~oI=Lwr$*I|6>jwN;kH-X2m6@O>G5xt>C9iV(*VlKMwEt!z7 z{6&1jeDU|u``Y0zQ{*p3yScorb$P3@d^OWeOEHq49_FTZOWU*4qwIhJy%T-~O1XMf z+Isb>cq6xPS#GXCZ|R`C#}{ zzl`tUv-sZS@#8OpFVq6x%j2bXr@+MrJLO_09~!0+em{j@pgHin5BbxQpCd@(&IZHhh5|}Ew&(s}AQJ4rtQ>7MDb0G?G zZ`A)1cjQ8=nTRcb3;m99wp2}ROlR8zWw!lz2@P<81l zyeLeT%d5tc@;0nIrOsTQmNl0nWmtZZ$-PeC;uUy!W&in4b9iqQU}6Q zVn4Lxfd($40Wpo**eH7MqR0n>J-&t?#Kh%pnhZVRW1NXP_q~4LU)Af=;&nYfj-TT_ zOU-ap)#NrpTDUFHYkG*B&*y>!Qf@BhF;B$233YoNA{>=AqV9zanQb6#OQ=NJqCLC2 zF1kASIf32>BI{D?uVzsSt3z~Mi1Y!zZ_`OjCpD#Crty6fo92E{zkkNKuU~yVj(@sr zV$-G*mywsrS84}1(W|3+AWksF z7cb1)kzKe@*tu#)aUJCn95k;xwOCPFA$qEbw!xpKnl4C}h-6b4Ee}auQdyGr6vq@@ zZ3{uD4Q{*wmcp_XxG@}FfrsFsE6^|Klb*C1dP-?hN>9{VTH90BPlD?KyKBsg_9q4- z^|k0SYD|=?Y_-*%w0qPLFIub2Z18TmIhh+bPTj8jNlzLwBndxfe+nv1-3aG4O|5kC zBKd`Dl3)C6DZ)K@FhmYclA5B+?#V+}t{9pu%S7cS(@*RO#Iexb?!bSPD`ifFqFibl zGSMqEc`D}MA+AhK#5C5Xe&aWZ2Z?;xJ;Ypepr1WAb8DxR-bJkja(+120)@hm)){{UaS4gZn5u)Y)o@p5z#TICX6(v%#b6TbIH=8W8kYMXMOkXr9|_wvyvIy4)*sMhux zGewpmI>LMjP8TEJmem_J6HB}#7iGN;K}+P=C&b_Qo!DI`d51sI70zsHa-_>oq{~~O z5DM`U*`!dnL)@46`nDJ-eQUNI#4l9(1Q(V5rP(K7evC@-Vr)V2V6ccq*?AEIU*BeB z6#^a{*|9#s)C`ceC8ZMat@7(;wj z@~dT!D7fV{ELoMenFQ1hh-zsk_8Ogd; znipBlW+|m9@-B^A=D8SiT6y(i!CfZAlDJDq(4136pUcQsl7cdMDHEPj)1_$y-*?Kp zG|!6G%B9QVxfI;8crLBC3huID5?Ez${ieLZ_l-8Dvpg4~#uQ%mgUcR()@|9`{ zZ_1mNv}&WpdYk&DY?w^aO0@mdvf6$b@XBh_#d*_8*{F))F4OK%c%|BQner}0XSwn& zC*K?LHq%%v@3QsV!b?f}o%V+PeuL+?<|}Qd-YIXs*s_!-@6vXnO#591ytm=DvS}0| zmDXEf%KX12pS4XhLwvWq-)z&?@T}}a`8+H3Tgm@cd0Xs-Y|F~kTSa~{&u^j8TrUdm zO3t^)Th_|A=S!GDO((+C#&qkHt`5pdA3EXM##;w@f z^8AyM`IMGbVR+^ECuSN;*om^`UCMr!+g?ihDN4`!R(*V{e_}BxVw1coat|ZR7LMb7F)7=mGvyPV*s7W*BK(&thbg7pABp} zTpMWQwNbHAyBQkq{Nd?u*v2 z8C*gOokruT0_bEq2!0-7wVI$G5fA%d1@4bqOA;)FUVm=b@E0DQ59sUgoFePy-5`iq(!6`0R;h(G(b?0t|EzujiQK@ zhzJs51Vlvz{i>+g%NPCfRcz#L@BilQ?&a=sA(v3(`}+sx&F<{%%$ql#nfGRPW{#D+ zv#_Ew<~3zKT|j4TR_3!#;8_z)j(7q`iZPCzJfu3>=A`_-Fwfka{SG$wSIs>rKd*uU z^EUGM9~%>`Gb+ng@b|POAqI;bl`I6|9Ffrw6et!fmQ5wEE?xTSBa81GDi7p*=gQxe z%Uk8SbOpU*4b{ys4GeAm{PWF)Z^m}dtLc~*ACX4CFEB42G=x4%r_t&3(H`Au#tS_I zo4+U@lwWDCUhKQ)26+NE9P5ky%DB;A zho6|@qKpP9CW@^gNTY3ruFmZ*pP{SY{#yPyw{$ur^3tyb?!E5#Npvf?yjK48Qo)8w zRi083&fj?BtUrTw3^hiv4Jjw+YMw7MJ;kqi)Kn?YEC7+R8A@}W>EGPD=JpC>YMmxS z8X}ub^uroaUSGp~RI`!2c6n8SI0Iv|ZmfzB-3-J(!yAE2V<;cRepx&UfAWr@UHnWQ z-CZ6>p)UVL7tzJ^Bl-Q4m%~nqvua)t23}qzo;B(Dzb>~{m{5}j4(^6J{sijShXmnF zH9NmEGAPh!(BXPJqah>RFEA1?9jW749YYmUqdG6h$J4AshhKY5u9n|8^xA8Ox=*Es zsZ-^PQzyknKK^(l_jydj@(DK;ee-}10uCM;aP z##|cNyxqHWoh4=(a=nMTUz3!3%|9+5s!2mneihQoqL~UUkeAB~*$>mp57a`hfc-Lk?XT0bx}FN{O48c5 zo5mw%5<_VVeq^<2n|wd5p!d+?adIC}96jU*<%I=wzsj=t9WL2iYxJKO?X?_h#* z@5FZRt)z(`cd)&t@Y7j|FG3|AkE#-kp1B=+3vyHK*rp9J7D$yY`!?9Guus~=zyW^=pexvV4e$vD_y|$DU7V_#jto-*Nzvk>qXIuc2n4&iVgVf^^6}1v){m}4z-={~J z0l#giG-PX^uG6~r8rI{M0Rwvsm4g#w7u*-SsvtI&cB0#EarQB0yCLZ z?%-RLnwNk~Mve9k?A!b4=KOx{j=wKFS1^|5a|W6}RvxjX_w4>Tk$h=nP9gV%A`??O zUszbSrPrK^lK|y208@)VCVnIs*FZ%1vAmgVP^Uu01yIT88{`+&7TDDZi_9x%@6jJ0 zn|5r9d`W(jwlsZ91#?U_ePa?w`BTsL%HsriT)?QgZCcU})Sdd#TjWpvq_ggmKb3!b zn0|2hdm~ZLGUeGBeeSr!ipd)ao(i(pj_Sl-Og%U=g)`pOHgjp9Fa7Te>#{OwF*N0u zcJIDz*dg%+_ck3Kso5{|8lB%^ML}l9nt}pTbN;)6f zZeV&dO4INpx*S?t4MAzFzl(~F=l#{%fcmK2IKluTNR!2Xo2CxfGH~DC+8W7%3i?of z`|gwTHMG)pwov6Sn{rOB6rZ5J{EW*RA4qKV+L2k-N-B8H)JFbF{xOWdmm!$d6(HDL zX^UN+ot-51KzVuNuT!$+y-Z^4vsj8T!Fs@Aly<;kltA3{-B%7uGgU7AH|^iEddZnj z<(*TeJg{DVN$~RUoOsy0j>|iGdlub)d9T=~z|HdR!_IWbo&;)umQi!BXya zrAE206<-+h!kq;>dp&TEwcd8r)}K->Mw^QEv$-Z#Oabq8F%^fH3TQH>IF@(83l50F z_Q=k{hCDs+i!b~2n`G9{C_S-XARDzr*Rk-p*%zs={L97v%KxFp!jyR_@V_86Vdl&P z`bkQQnKN4m3*_VS1^H*_kTRjm@uwYXKJxJ34|;f*rtmYv+B_h~KG23AXj&86W(ocD zfi{HL_6^p4Iga(q0k!H1b(Ny6@B^XIX31YlGCd;iu~k>xgId3A`d2Bp*rs28&isO; zf6l6`=rc;U%#>B3d4|~Ias^oICu_T9r@YzsQ&H5Wk77d)`+kbwYTrBUF=uOC6DW;R zS!dflJ!jJw{rwle&ZZkOC5t^wJ#4!or49050B^kVyKq*hM9=`HBp6U=czeo#|}G9 zv8~y8%}j4A8TzYd981i`ppz0pd&eitN_{$~OI%#okk)OBQ&wko|6ovg|H-rZJd(QV zp7ZZa*xRSq$k8)q-a0Sk$>Kl%HR9M*{%@b4oO>oDr9>N2I_51Hm}>~?GJ9%DMuJbP zj9X?5Hpv+s?ikXqf1)9Ah-<@nB}QI+1m+L7M$nd&F%N{ab0P{4GoWE$_s( zN(ZyHN(T>OO_iH!ew{T{ev@gU(p0%^<|NisxgE;52ehT|66EP3-afjpiZpRQQv`RN4R5H4E3S9X6mfZ>st9QGR8CX(KH3T|P?R^qva<1jrhjmH3H z*rY+xN1E?h$vtRV&i~hZFSoqr4{o`6waQrm)JFloNtx$jW2TAXS%bt@$H2Whj{^6~ zdVDrFk|17$`*`g+8xI=r_YTzfEAYOB^*#pgTUy^=f$z7nzTXj_D`z}zgo6CR?t=nx z4ehx6dnxGyKLz-_H{M&%CSffC`2AEKs^0gt#@~$h{j~U8Cc6*v)Sm0Y zF#TI=)5rS(R{rMV{Xpe8@Uso?2RZOJSbLxEh4(}7UhUuEekk5Ut#H4JTj2gSyng}G zABN9|Y4QhojDh>%c+dKgG`t^y_fRXse7wJ1i4XZJ@s)XVcJ}C}cs~kt{4z*?wRjPF zAx~wF6vi8DPQ$>aMM1H!F<){9WpjqmS^PoWv*|E@4^b9?_D#^#^^2a_t!k??R2C=kxt+#Q}s2J(3WGO`%KLr$B*b*_@4Yd<@fzYBa#M;k}q>DYJQ*`-I6nZ>9kEp z3+UVH^H$N!k(t55%;yRYzAJwwWKO(vYTV8ZkI0jN7q0WTBedCb>yzW}yOnoSp+aNa&n?G!)!V{oCs6ZJ@xP~;wPnpj*vR{v6qiX)yxA^1o8F>JGk*8~S z?UHAjzhL4Pj+(ya-!`Ryx}w__V_GmS7gj=A0*nOIv!T-|h@3||5B0VuH3(74o&ah& zeiz*juxLMd?>l^Nxhpl&V94mTS5CinZVCSgJ#RLLn7$iH&y6wn%JFZ% zU68e-O^Y45m!5qt`ce7AJGxB#or?0sKjbguU+Aqf$5T%lJd&P#S$;&0S)Xjs^U;zY zw=#ROXL=iXLZJK~xt;tI;P+GdG{ahFVCX|_F3zf(K$7cauMg>OH6IG=&ELy|xaQ^{ zhsi@7Spnr(f#vW7Y_x=)Jd>pt$F_SDgJPEYr7;^VHj-^+&;=kgB4fd5^J6BfsFt>w zT5M6Z^Z8-#>2$};2S-OGCPwyoU^TJO*W}d?JhD~(Q}&hrd}{SEosOoppV=P%C*7Tt zbT^d}Bgc%6D(LmoH~qK-`LDhqzSQI!Vm`-3zVyJ$r%%89z)O)d=8aV!|M0`dtKKkA z&xUJ^XK$CP)vfvxim+Je5K#3+p*`BhkBc*Gw?JRg~2ay>@ur{H3 zQdk|)O(##%PweZ6wqkW8*HFVBAX#5|w>W;hd`bRcq@4aTok2fim1O!{@-xrDN}`X! zc!$161EH&llW$jb+bYy;e%QBt33WCCb&tQYrjh*~4L%RRd$qm7J?d&)^Sce>2jTq| zcwT__!Faz4?l)lkW_bS`#8-4Kf;6?onb#wDAZILfFoO zwhuj2^O)OkI+{CXiWPpZ@xZob8y7;LXEY{&V*}0OZo?n?^CHhxkuTaVxoF z<{a$5wfB@?#$=<^)Y^@YxXVt$vzVw&g1RJwv3XE@Y;bd<0j`331~>CH{JlxbhC3D; z)ZEu#FoXuh#<52%j`=yq%tf2L6QTc0WflY;dJ$iTg*w4Xs0~m0mz-t#2JqLB0@If3Fh%*|Dp+P;=*umX{oBJ6|e>gBN+3?;P+Gba< zCi=Rqg|by73HutNfE>C$0YNUTR@M&_S$88;#AmA-w|OIb4QdOzafu2AS`7 z^6uqOYyAw=a?;-SGnoJ5oDZd&U?H)r?@{1jtuE|#7;J3f^{6MB>FX=#C-%E_VI<0~ zozw$o?j$Q$FDoFMK^|tgk=n^tKLyz6C#Si`HQdIyQ?`(0t;A>$3L39R<6Poivg5rA zjE#G-@o7D>YpTw5CTQ{d#_M6H1(ly{s&XdwIx4Xq9n~laG)8Z`ES4tda@R%GWCdSW zM@=KM$XqhNUg_Ncz3)t>{HW_^3pkZCZF{{91UDzLFDA>#N_O_vjg`I&cEgRSlm={x z8&Oj(85r(1b;sQ$3N_EEm9cpcaE4F)~ z5d~~uu0THETA5w4+9F((hOK>2JNM9!&F3`P7HW)4nle}6s-T)Yr{S{j^iJnK#-n|3 zP3@?w7HJdgtE&=oQ%x?{acetM)_uv(^Uac?A=or?uQY>#@q@13iPUP&?L#HuDSCF!PU&@7g|frv9xD9St@6`l^p@ z*2lWnJKwXKJoAsv`81|+-SGJ#S6ksfFpuPVTlKiYeAAQUz|A%1)F_qykIzrJjE|dQ z9?Nye*v;G6d{=O8QN}sfpiQzf<^9g|=lhK{KL1um5VozFy18hNI(}CeMn;k`%qF|~ z(!0_hUX4(MvsdiSu0~R;T$=B5oU<8L`(5E0V5iA8@zuyw8rp;pdRHN6^Uqf?-{?4R zGmK1Ad-_#3rUn{iS6}mLY05{*Yh6`Mp6{${qp`YEW^JCn7PS|51LjAss!sV+*KZ>A zYU=sE>;65~qn^6oP4S;tTWIicbxSFwNoRG zu?(i)ovZ}89y2wLYi^V^1nHzVj4bBb&vn;R?&~1e2BySK(zO(|&BS@n`uZ|%+BK~N zJA2rEe*HfDj@i`l#PymkYs!4QLoHd=qg@(K>Pb_Nb>bPCJacbTeb++!+0R=#&hf8e zHu1F`kKE8|ZNgCH232)a2Qb&V`s>=n%Gw#F?q9tz>pZVl9@lgI=(WembzYHr?K=)f zo7nz)$073mKl;t%e+N_z43%zrq`5MJy4L9PYT$dz+vMw;>zm8=*qg&^g`rjJ!I>Xuj);PGHj?1gTvGEW8Cr8IO z3Y0f|%zOio`VWkwoub#oL*)501H=;`{&NIJ}`TqB1s*CRyZGGJz~4 zYaB-Bj##XVdt1OcM?Q6id?gJV=qo8W2fuaLZZ39l-!Pyt$OfwnQ6QisjA@0Q^|51^ zdA*aj9R~CCR~z9oFfoxcyeJs9g{o6f)_rRJ#W~FD#IzeHDr5XiGJxDg7Lm2&dDlky zH%G-bF#P`~tJ|eXfqxPN4&y~_zM#Jq2S=`E#^C0_M^mN}{z=d@d4l1e1(K)Jd4~ej z2hWki^NM#P=J}VA?xG6-E*t_1jkVjA_pC$jM^q-v#`M(P82Bt~=4Z0ocNn?~U{9&&N6<&?JI)o!k(ryUs4TB#dkUgYH6+PM~+M$)rx8?gof z2UpWX);W3GVg99O&_6Q&;@E0%>91p}=~<`I)VEXKp~=*DT!3;Ws_ZYmrkkdoiHc{v z8>8r#+F7W)?xBZ-34c7RoQY}^*F*UQwhVCW*YS?q7f3hlk7pm!=b928!ZYX8_iE2X zbyO<~B&kh;d{bP?e1r_Jipf)%*TpbHm4D}5AxM-($qIO|*EP8Ls zYRfgWYOQ({l+!Xb`7Bds zHFCL`lN?;o&pNyEJJ(T-l0akhw(DYPsxo(3R87(Fb#+wjnW)aCcLVgkQ<+}pGfJIF z+4R(PH4xmK$iDVW)Eg>&7wm=`Q7Nt%6E~)!8Zt24ZR*b1nW)Y+$IWDSIIGT^;`C8x z6?DS6OK5!q;wVnUC zYLQ;=GfJ<~oQmtBcVZvZuIauZ^Dm95lj}TJ<7zEk&pDk&RGpoD;OumJNH`Dx6qtyFNF<0d(LjLhNt;X~hl0$!?osa6YcKn=c(J$9OE zA7713n|xg9RSEjJZn+-F@I&HjAUtFAr2 z8(^bfO`TrfV@R*6l1-`C_uH&TJ#}AuKI%SJoV7}wU|T#s{1r8#!c>Z!I~ z$J0J-8?PD-+HRdQL3xk**55dukJ_+ay$*7o(ch)VcXEd?uxdthn=2{dX3jR-pDGwNltFLMxPL_ zL)AO6haJyGy%A%X>y*d!UPpRuQF1*$VO$UB*x19GZ8Aw+Mf4ykgYndf>tm(x|A-F1 z#`e%RH{2p{fLG62bk(c!)o2Q~>{WgPgQaV3UwAd}Z3WLly_vqRT(>WMH^sM@Yuxqy zZ}X6X~(Hfp;Ko*-r3ow|HGqK=a~B68q+#M+5gr!*E#fT#v@lc z`}80D68OIi%A4en&>Ozg@CKpR+l8_8-~XSCrk$JQ{};#D&Jg~8aNJ!_f9>Wl7PmY5 z)NVBHh{d|Nw*{PYHpxVKDEPl&Y6AaY>iIXqA7i${Uyp_@{B;;pAJh-T9|Y|K5Ca;G@Zt2>&2v zn(!(6pT?1=)42z`^G~nw?88kAum8cbL$A?v#Xkzey5mS^XP@4PS&W+lo7Z`I;~zxp z^_=$jXM0lbde;H4@#KE;7CBFT|Hsw>I32LMHjGtzOD6-?I*_(Obp3$7LF)$onX?RU z=<)*2$+rwA$5ql)CkIZtj`pce-d4{zz2f|d^^DV-Y6j&WZU+u?D*s=d^XcL=ORAG2 zTFpCLI^LBla`JBNG|NBRUhv#f-CfXLJV+1;VQ2pa82wYClGBW-F>z7Ja1#?14L9se zURp74o^WK|yqeC!k&72=I$xxTLU-x+d4DaPH%~Wz-n@%{ExmYAH~-?FAL!^`7UgUf zOgosw!dNhcbcFN+34u0?Z6e+yOesq{}_!d&X@P+7xTgM<@@8~`hD~GsVP%VJ^oF+`IruU@`-ltoel3jo5DFX?X>g^l9n1D6D{e|I?9N(bXM&EnJcO9dh7i5RYPE9Di8wE@n zQvzZFV$!10TrJ|m@>?`5@R_AcSIgsE2IWS16c=j#X4=7n^NEwX8_)#qMZjf%s#=&5 zz*+=_0JW!7o~!r_rm{RgG%PgqNvN$cyR+}_lG&+K*BOO{Gg2p}yIR7FqffaBLf<|` zOMCb7^_>;s?KRMD^4Ssv`wA)9drlqBhxIHbE zj=Rg>-J^G(N82}V-luQz;{N?UKT|#T9=)403}iGxDnU^JG=@gGSlEl)BzfC1+Cxrp zxmJ@*KXc!xXDHb4nge6#$xYywU@c-LrY6MU&^bL)wP6CaI#dVLHkA!;xmuqa52mF} z9yKyOEls{KxNW;_G<@KIw(SOu=#VyK=$5h}L(|gRv}-$LK>MVmcF!cWbGce?Pi)=0 z&(Ory8(NR@ZJ*quU`|$6L9e9tzP?!*x6bbjfAjlgcBsyckBf`#jI=K9Z^b=jjmEvw zq(L5%9lkYD`6Z)-V$|m0YMXBhm`+-fe~Wuec4pVr&)qick!NokHU*)6YS;v55JS>Z zQ(cBh%@=q1d${-R{aCw@=9`L_^zAoehJtf?_r#G(YZ#fDO6uaM6Y15YzK^KIMSQfQ zsG?9f>C~u8%SbW0CE~07P}izjcC~)@Ebg4Qs(p*W-CSklMNXt2ee&r?AAS1ti58PP&z zb>(q|tL1IPxI)8W$Htc2VNl^(@odKwE(5XNF@?f=zs7Rj@PNWKOkQz3;cDqz8BZwX z%ps#1jn2jnCS0pU7snDVqqQkx2}LHUjg^QtkZ`G>wc`kvYqQQcLg6!u3?p|nme;Eo zM7UOujT=L_T%A`nhEU|ymyB#Q)*Cs1aIKBIHhyqbG))*kDDvn?x;MU`Yk2VBk__q_ zJGk6`yF7N#+Dc>lbGw0qYxQa!H@Mugos1h4e!Djssr3&UT&obLV+NNo=zPrZF_dYZ zI%a4Ox~Auq#|(`taeV`Z<<5%h=h}EdPI9fhb?U3p7PswS!8N^MJ63QRVD*m`B;rfL zf%lfcd6FAVf`2Xy4o=cd@eg`bRuxvAIauaCES z?EEY6Sg&bchu`iE^XsxPU$1PhY`~!Xa@YYD9w%+#RnjL$E zBD-w5)~WAA(6|lv4GkNs^_8tY`}9ivSOX?$oi@|D;l9nz2(7mstaj&>T8`D!tiwl# zh7nW0aapebo!XOE!h$ms(hlFjBpUkDEGxJCl}yQcN}}ZD;b;u5EEcOO;T+DC*}%{b*FZA_{((z9%nVB`=pj zb1$c-8HtsehF@n&8n1Z@Ku(oUW2wVWvs`@ZG2f>v3-?t z7hGkzT{esxRo7QGmK!gR#@Nsr&U;>+WE>3aMit-I=xzego!jC{xkg@HsTwxa8-@2P z8t;uSxl1;^B8T2&%2gu2u?Bym5a8k+Tf<~qHD^SN0C=g zGURIe;D!f8jge7(gQO&E{%PD26AFIB={T`&eP88B$acWkD7|Pqh-?CY z?Z%dZ&Dhe9MBsb|A0_f}@IQ+86RBUE=ttw~A7>WGhp2QX)lqRg73EjQ?V@|+iZN{5 zIZi%6UzYnia4$@k-#IM5efTgFN_Hxf7q^7o_VXz#s)G zuM@?=iZ_g8f^@7VK~=NbOMrK^Rv5%~7zOx;^Faw2e&M`ta*#T(VKKcqov4e0+6L-P z!6FvHENDl8w&huJYLn)^>oT%SmyvUfZM=+a>5F(1WK8rjwvlH9Mg|5(UO@Wf)P8M4 z+&Dw2XUAEyho;|>k<_{8xN-dl72e`o7(`n=*NO%e`rcAFsQ$yeOjMfwPM$(&Ap2@4X0&-`2ytxS`#RHMLvJ|`AFF-kk$wsHD3^D+3-z8 zy*H2AwPMxD)_jN6cipx6uELyP-%i2Cxp;Fd3@^eC+|;bo*zRaB3{VbIqks*r|rypAtHjtb z|4Def^X>;%9ynZzXEOA*Om=G{JqTF!$C;!SB#}H!9wlYOOm*zLWIT%6UrJyVui6YS z2CIEQGlFyp859O(aZso1F&nqCy=2VFNXQ5b>Lg@9*8`N{BB8AS$l!daq>GP@6m(Fn zZFvac(F6<%7vbG-At*hrHb1Jv98xnNxtQp-QbJourxVR!fC=Y<0wdTrMz9xy*seC7 z0VAAa9iO+ZHI;m*wl$9dE}Fp;|4}J2K^bQ8^OHN}0Dn2*zHPjXL4j%0r*l11ayli0 zs~ME?MrLj+e%*BQ`(1L4VrJ?~D<*Y)pi8D`%56ge%4A1rRGsHw1eOtEd7rLOLb!cxJ~%l{e1eVd2)}vx-R(OCpG_Rm3ZrCJ>B#n zUWq=LZdp?XrjAaFP9Ef&5Zo*wU|?8CzkVTM0|OG81t<6pN{&t&ojPzzmRqJzqF0FC zt>otc&9SU;uAG zFY~>5crPwU3{*&9B)~K-Lqr0JL)V#}OQF#OrL#UTmu<@o7a(x}JyYHZoKA|0Oo->9 z4a6tF?K300-kvphaMtZzM^0VcE5B>c)wH71eU#If;7vEDwq)Hq|%|Y z=yXrBC!fu#3J9pmdiKeXyF1_6c1~gIE{R?9=6Aa9`+JLv@BRM1PV+PSBzDPJxGHn< zy`9$v&s~}27Px$@m)F?kfo@qV=LWCseDCDURSSK(cn`R(ZKt;KpAT=@vXXkh<$&9~ zyRiOnJK$u4&I9#g7>Oh8aXrvPvWaY0erL>4JMz&AJ{TH^st;+Zf)9ocYK@6VO9z-m zMaTO_B4RpmDr|I2Ewa82V8CGJ8z}$`6blYJF6haC>Y&qVOR*b_SBxZP7_lAo3~Z=x z0bm`WKa7uKLuaiY#)%ZZ*}ypi2hMpUFvAeo!4RAn7Y>f|!a&&)91)ku91X|krmrU# zzB6WT$H~vhzdZ2MgY@;M7Y+^&ix@hhu=}it(3#x}M+}V!3m?4jG@VQ{#!fOc3!A)J z?-d$dI$YAhO9R?% zObO2#=%Z79KN9ev+a*m0qy*x3msFBTI*~58N?WtIp>pCFPLxa0K%ydv5h-tTO`{AX z63pEUV+?PMF$Tt^XT*qUF@ap+fR0%M2WE8~z;zioXV4(HFioRJXg1BEugSN_$K)!x z^HR>6&Y^QTPxB>tg}l=IEArTx=J9JId)GkV0qAw&kPh$))ibO3c&*)Hm&zhJY3w70ISXbE&d}U*fZ& zs#`*#KGiJ-Y24&uScu*l{jH^N>F2AvG^vqk;>G4|Irb z-8>{cF(xhYDrHbx#}e@ZD>V+s5Re|4&U6t{23+&dfL~AF?kvy)gak409(C*TYVw#Sp}WwQ6<2eENI&J*#Zm zea|Hk(b_hANC-)Q@mr>fp?XT{V1H-=YD2LxAvzi=R$UY8Uz%{}WvzW-_19mXI=04A zMHU50yQ)*J6kNUKP%gfa{hpK3B{reIb1d3#jqKl)Z^X9!dIs2u1Fo#Kl3|D|#Xw0? z{GmTfOM#{yM$_xosfZs2ad-m*C}D!5IVi7V#aVXGot;~^flg`NQW{3r(a@y}GTy7V zenmt7krDB+AqKA~N;xMwjg_xu(o_*F8t$b0Ee$lR<_imE6WwHuoRL!pq|ts_okH1)=`#&c0)? zNf{DiO)1|mQ9nNRauzL|YH=hc}Lwz@BkE#Zm^@Jm*?j;gPAg-vvO%^A9V>PeM9 zSvK9@V5RXZm%^WUr^*nQ*_i%F(Wz{H2l=$o5iSfAxIX;rrhA$)JfO3dF6CA#NuSes)C2Y6-vFK@x2HVZ?jafM0n16LG)Js^)Qk*5P!5#)7iQl797LpBJBOshP{WkNzwRMF*Ov~f`3y*3`NyWfhTr)>TL1L){%LYoD9zIs zXZ&~i^#9I~U$h6(BMkz{7Dt*ELLB)uR_{OyNNofVg zGEJpTse+vg=!OOK)y6elM|npex)|T}v=cX)LHTIy^hGw9Nze{uROWKor7oU3F`9ah zHjikq(Fotlze3cKUEZA#%Q{OA^$qaEzNKy^G{-)syI!&)&w7lZ@cdhu3w zGUlCIS9hj-cD8Kpy!uwt-iF(d<1CCE+o|6@4-ISEcGyGr^y@@p8mLRjMsG($Z^wFy ze)U^8bw?d86;ztsym>YUhRv2voO^s;3ovXr&uG)oxS$B>lp6xsK%Abwp^a-$v3QAcKkQ8!{q<4Ee6-8DShXU zw#DF%Hr_;cGEdq;okwiUmy0-17%^Dps2Eo0CVsI1ef}$yo(_2j%HPpFe-;BY7~pd_O~Wwt+9WRsz#G*m|{i2@(@T zr;@=LQCFoSma>^mxpf^W$lf>^D#tZJ7~);i&(8SVzU1`6nHguz|7~pfYw=9<$zQ~3YZH;HWW zw1ZxqdBzx$O8Q@+x3pE)btKA`ThxAZ%B5_Tg&Nm|ezb?C*Z0&BDZi&%R^LeN6I5j1 ztZqwP=vjGRO}(3{?B&N7tsFPNJ2xXn{r;5eHE`TY7ST=~2Gk#HTN_@#N@WWx*aTrDwC*N-#}_8}qFw`2z-hUg zY7NvWzqd{O`hjliM@EndWGb0QiphgyHQ7KmldT{N+@zpv_@rvtL@cRwrZ^zR7@uH_ zNdt%{#H0br@zyBmjDh~TfEeh!SQNO8Nwb?qwu4f720Wygjj}HyLEHBNacDqbP#Rlh z7LcA12Q)A!PSUY!pn*ZchB>{4Oq$WZ&)srHEk1HJ;njF)f=$a0kIN6A_Hc*%)~%zW z^P{6$x6beI@bs|!xbXb+y7LvYqJx5?BAN%rn72g6#6(iJyZiK?F=WsdrR#>tIv=n8;?WsCRT!Y=qE!;MBQ2`_GtR`VnRR9m=0(Xw~v~ z$wAt&ZA*Fj@bvDndD)wRLxGwna~r52AA{Sx*lroa>DpFpik<9wClA#O!29U4co5&`qbv;@}VZ;+|Q;LlZV;d8BbgdQ!2jDt~)(o@-uNw4u*H))$z7;}Z= z$ko*L+OKVU3(L*Tu^Z+7aBUZ{)!J-2kfds}Y3q#}X#wzw8_sOla7KQ;N#CeOuy;4` z9UG_Y32`>okHZu08qn_6Qr0&q+JIh{f9O5Ackjujmm6*c^=We1pQX^7KGR?!ZND2C zaMw%>p1;z~=DU%#Kv(tc$Q*{X$PKxM-;dfVbvv-hpOBzlV=USFG{mVgqY*)-kah4R zUMY2?>c>IB#kdU7DvY$YG=VdwvakLmk_HBa(*OhSO~G7Iej3q_O%t;g?nAw47zN8E zGJ!pVUVzylZP`+KU)F(y(YV0K4CN*KB`frlzEQ_^|FB5d(})2Bn3T*t2Mm}yaG?A* z6Crm$%F}clrE7k&$I##hC+2i~f$F#)sq{j}oQV$x5ACrueo5GUTtZfy>-*S<>6sU)Z)l5{X}`@%jLQqn&aLSa9@(!ZH#;;hE^*dx(_&hL z%D-I9oE{PT{ipG9QNuglIW*cYf1Xcihx89+(W~aH8a;kR@#K+f zk~HJ8L^B8FXX_Y(Myx;64-Gf^<`b5!y?y+O72}z^eeJRds+HJZwdk5Tm~!S8SSwt7 zL#@HxD!*Q2D7gc)-vnq2Gszq>A6JBHy3EL|^?)E|jkD8BRA)?qe+e02Wk>1)GT37$GE}cETbrKRjNN@>BDb zzuWt6cvc?w?1sL#s{yI`k`xz_?_^xdVbAK9PYwC`%ToFFsm)A(=jVqsOKs2BPF-wY zC700O5?kCQxXEpn;UCvQ{)ifKXG~f!X3T;~GjipNw59pD@{E4qCQNLRD0|XHt9RIo zxS7%m7jPZS$EnXt?aq%EqG`0;1CVV&a@!S^K0$TA%KJ&;@_}B`^5v7dfczm1!ADi|gG4BUCqaqI_xO zMCv)x!N0s1Wy0q-;d_tcyjW{oqrvR5pbTc0CDb=JB53lliOa1YJ!{tJS$8vfx7@nn z3Bp2bpfud(HNJ&*1wk)fc{(IiX@mtfZxFlnQ|{_1v!s!$0Gc!*qJ7M9dDV`)jqDXY z$-e)`sx!Lw)_q!3KngfbW3pd>q)~xUk#XsMI%-VtrJP~{^FdMD>wI&XO1J-uZm+S} z>b6Wi-1HSc*mO@7rIe%oZv}o?bLOi+@uQH#igkN9^t_PB{p3)HgKYWFcbaZmN`vLG zYd=0gja%d@n!QE-4}F<(N6w!=B3qt-7MBIKf4q*3Y{SSvvWh%Gc94DKRdN(+N!?DF zf$J76$YtMjDXsafs6y0^Iap07KkP0qcm zQ=foa0tTi!*z5MMgV?5fxnsGSC_9FdRuH>H2bK%l5M2q^U@>pqWh20R8!#?J}rtsO;}sVI|ZqXDKn z$T4&@Z}sbAbL8W5HeG5JDh9Z_bHTSROEjh=CWYz^8n(9Wqd)H7IsveC3b19+hbASa z8rnWM&~%((ble0Lqf&Uf{0qZqb~Lx4e4c4xTt=tV5&8*2fu#5Kj1+?7y#aA|O!{*2 zDD%VFhWJ20oWCSY6edf;h}7)#*u+#{@8HBaum8*Z`X{f?Y1P~i%Y74=)Fs(}83Wu& z>!kv?#Ml-9xKsdKH~&s~srJMOkVj+o0I(;_=%Sz@ynokF#9 zdR$_vF^un}%a>e$U~024V`^etdUi^yiQ_aNj+)tK2CZ@#g!X+|D>9mFCfmtga*UjA zs4v4u;WQaxcOyGCG|Sa3>KV0r)74Gs3F*qFb=$q^SMJ(o-hFRwZrbZVy_Vb~Yp!Y0 zKhn?9ug2ffX_PLhPgILrI_S;H{`COPqVI4^Tx{QV`s6kpZyCSMvw7QA$_Dm&I=hJx zZe9EI?ds0;yP=(4S+~)*b?h4K5f#+4b)=V<)Go@WO;}KrXR}+nw2B{nAMYQ~%+rHU z!}Th*=MnTGMPw7%b)~Zi;;#F#0#rSIMO})o9JmvgtSn|@Pt-MTsp(fbfPg!ABTp3I zzIM-Q)3y^^=--~pYsVJ{L|q&9!QSuY zK9Pc27x=6D$#}{Z0L=bhIFy3_&&h{dgwBpm+b5fG+uHQ$XJ^PcH{kMTx4-a;b_FVuuVVK(d0vs;e|r1;iFpezwaf zIZe0nQ?CU`IGvjcro#DhMwy?8?6j9MqqKXyX&mJ7QP~C&KY534<8c44q#AnQsR(8;;$;#<> z??c1ewi*7=z5R0NC#Ws)+$Tr;+)1{OXUL1t>l`AlUt<(q!=47B>Efexap{pkn1|Ii zW8Gw&sEfNcIJ#b)P4{k9-Nu9u4wqN&EAQ!a zd-3flI-khC57Z8m-z}7Y^( zE9^(#*IO;{wd-71mqU2A4kCdD>013GJ$D*4LG2;od0 ziQbl$;>T!fKAq@x**2p6i zsNV8=2V+Ku;Z%9(HTd@4yMvS%me-XSBu|TBgc!}7z7A;z4|eiWo^cEv!;KNgNHgh7 zZl*X>($i5iB_JjaoP5VyZ^`rDdQ1HHt+(D{&l(+ycj>d86 zTsLkgH<{kWx%m(u8bKmxJJOCyqZp5TjGXbxH;;;c$bT{3O#4C3y~H0$7@3E-ZGZ)TWFlNFZ<2V~`l6`|Rjo^|re#4R9 zaQJ7>Z#eQB&YolVUV}$Ob8Zw(z(Y2}Xbesgu+B3jIX#D_;BmNSQ)aUW&)61=?iw1K zlav`0?GxEz5qH<%=#FA$l($E68|lt_3?boOo+&M*f_n`hYfq5%3Y7KoJR{|Jj_^F! zh0tp&>sAtxXdv;Wu_TtJ(Oc*cGK7|qGWsHUk$QvFd5}5}Qs+_XelfiH&8kPgV^XJj zl>58FFP8S=U(lP~o98YNk-MxDI7w$XQ>BQus#c;p~Y|&G|!zED7mcTMQY`(Dp}>N z_ii`Vu-qB(zy@^ntU}A+iDV$Yyg`a2(R`%DSmjfKGE#W+R^;>p;TP(@XOH{`S^?h3r8oSuFO@fz%9}m6?QMKe6pk;^6hwB00&J55dw*Hk0}MYV zddm~UPXWW-50G~_0lGcGfNY()VBg<40#oa-9D&UGCi7#bPKlqs4Snl(P``Vyjp&G9 z9teQf=^=+x*rh_bSueq}p5kxlDORYx1^dnq@AiXto2%~<2J9#XZe7)*-*9>$T1-GW zWy+dtfPXw8X~4h+_=6CR1=H0S4rye-lLT;=H*C1PVS^fnSK>e{W&I)XgBU?-%taeE zEW*fi^@aj#e2ZjF6XLVDeva`A*c%!T7D?p|cnC;gAGj3`F_QA_&OS{aB~=zrr~1h7 zW$RnYtCSR4F6jQlJwf7`UCE9(48U1VNhg3G%g1M=D8C&Ms~$X?5-9zrTW)UlggM=B z4SxJb+5AD(Liqrtc@>@Cnz)e)hu>V#F|5Lm{&l)zT1C%6U5e7O;_syT2S?tqY|$;z zTt?Qk)O$N+^ag${mJ5*QQf`<*^6#kKbNAzYHkP~4^0a;=Zv@L1jHx(aDJs^6rKse% z4D~!~o28F|DNzAY(Fw{Kxyr9xU~FmL#Od-6@qZUz#*yqUfC(-6A+J$4_e6KDKpmHchyTN~{>O`$nV-A&Cp;N5nqfJ1BY3 zhPd$6lWD~lo$vDx>7LNcy;-)OZ-*}Z2*=99=kgyzZ6ql+Ujpu{(&0}nsAu`I-x8=( z2sTKJ;)b^D5|NnNq6N)p(W-~}h5ruT*greMCwFXNzj6AY4gLCz=rX2lP`_Rar#&Jc z;hMGX+cBjXrL9_~+#26ZJ`m(NDk(XG5UbQSSf#C&t6C!y% ziNbZVTDEHaD@WDaN>^tUWRP|MaXdHSK(Ia_EH+{7;*XcT^2)N07q3kSiw)2Ry%OFz zH`m9vL$G^rM1F2;GmoH5Kko9a82>ZK(iVCR5*MG~P}4zJ&oQ{FDM9&WprIlo-7np~?t=n_ ziY{&EXRei6tZjMQ%nsv|{iWsttLLOPIS*`k@oo9xJGyqN=oFGorIj1bP89{HOrUG$1+J?)j8=1+I^OCI(})`zs>zHX278%nvu4=#FU%#_FbWEJL*qa*IS zt#?c__mHgcX4#1y{n>AQE0|^&Fi3&#X!lI+aQ|*?8{mI1#0P@?WzYpyk@NgOtu0{q zsoHS0KiW?Z;JO16$9}9s`Gti}Y=aH7+*Gy$iDrj}4(!0(eYtrRxp{fH6?x}cgobr! z*(x-oLrFy*{8i-T=2|SIP+qP34!ednD~0Ax(y6Aa`Tb7PQNxvVgxzX734v8yuF#y7n|@E4p?o_DBZWR{ zdLTu*+R}mHf%8(*l{>-vebjW>^Ubx-nO+l9_|dx7OzXIT^~aAkJ;{%j*2`Nq&~Z=& zpn9I#LRaZ-G|IlMwVTT>(~ zx*YW3m@%7^+V2t;)f6#)Kyz^s!Wh7JGK@bwo)`7xkR)nz zk6&b3Y7|=>25&)M!N)`^^KMb{d(``A#l9oHX#*qo-OCFLCdK>8LqB_47*kXJ_{`if z)R59SDF|>(*GS{}AM`1P1Tu@f#^r$IUl9(0iLE>v3(r!OXT+jB<8D`<-J!e}cogE_ zYS1a~vw4g>Gw?DA9I8w$@@xfa1QeBb81+m!d{TzCfMs`rbjQ1(&Zq6Q<#_L*iFlK0L!XYMSGLm$^3YL7Lo3_1RE(HXNS4uE-jn&BSL# z(op_)SP}sp4;2FlTmO-b#ojsEb^t>&frpJT@mRqIihInod z>j$_BuvAAV_9soGiL9L(*(#+(`3!R`7~cDu?+b)cx00^h3BuQ)Y>xsTnUX*BH<|k+ zPLF-eg(?`g4C=kxFkr;6SBM1TmErBlUb0bIs%v-Qo1{Fi+D_-9mxSGpzaql;w4)V$ zCV52edrI=JDSUM7=GQ-jGCcx1;STN>$P;YR7}t#xKe*>dn$UrLpp!PiVgaev?Un$7tULLO;ji z>PaBz02ue+uf2&e8EAI;MZvv9(@vJ2j!Em0+*>|(&cFSnq;_FH(te+}EVwgJ@U1z$ zZ?I2Nk4ptf?H?6()~tknn#u74`5x{r;4OjMZ3zSJB*r7~d_-PO=iBgnh7UuYFOq-J zV?vF>v!6N^x%dJ6(GO)IMrL)e5hDHp`1T;J^8($u^>m4wupT=7P=OD1*L#GzxqBMU zBwt82n1DdveK6whw2S-gF_umsYjySVkD8=uSC z6oq)An`s-LyL~(Idt7*n@1Xw`@Gu*4hcSmZzc$=$2!zjZ2tNq%e}HhfrcuK32CyNe9zkSR1bYuab@yuHv>I$V?>7^Sp$?+>1oe z3A~;PlEGv$RWT`DNK#bW(TcO;*~^F5;(X=>^*tR4&-0~wQJXkU6l9fd@WyYu<#<$!P|nsN$l+lO1>?r@}@i+UWC^G2MpuS z@M|I80Ma4PDkrcW5(rmgx7KPLa12GCL(F!5)ulYIFV z_Q>oOri97=KKA_LwaWO%%1<-WInNjz0{nP;=!1j+8fxh3)!a~pOa&wbln3ymf>frw zbme}Yj4AJ+@@AgQ1af37Isv2x!x3l9?dd1?`gx)=_QKXKe*Rb;{-SE-#l+>O_o1Qg zT>}DD-h7gL%6(8^7ZiDU`SIn(mHKi&M|trILk1GV*t4>v@dDWn2i9sC+N^RT-zWb& z3~|Hu8u9bQkBK`;&GQoVoV%w^(ueW_=V3Tkm29d?K38S*%>+I?MNZH2RN|MoFQp7g zIOE!q8fi)h1-mecpJ)DD{=V|%mn-G(>14hY_o6(CK4l(Yo}}Uv^YJ9}mK_m2sxNami&%@0_(1nUZC?~js<~xHOz2t-ZRT}c)|zaLXwN;E#TG=(KKQ!qs} zL5DJfP7$O~jtZ>E*(!rVx%8BdD_68jQVP^7!%<4WLEhW+EB_|&)_W}o+qS$mX$b;l zY&lIU#+sHtf6hr-SVkR*%yWZ|I8>0J8^@$r0i|;Clu*vG2AxDPm8djUI!tJmX%$Ne z_3SK2=ZyFj{xVutp0{sQ*N{+8LnsXhmAXbk#h%-f2Lm$`c%F2W+QSB~r-tzLZjTrl zr_iNjUr35Fvi)GGooHk@`^+rqj8Or^Kb$6a!Uee!Ck*U$cS*@N)bqQdqS?I%a>1s| z+c#G{F=E6M6`Of)kI44Vz483GanHZ;T>D55bIDp^*UT{;I*ehYcHW8c$#xiY0u2s*(!l_Z?)U)||DIjva_aj7PvPf2Vjl*L)9T~Rc_7E3b6U+tM z^DGara?E;!1@=tSG8>K+e*4$Tm5J5cH#&c5ol1fMY(O-d8m1sZ&iHFFSMp!JQ_U1%J-?Z{Pk3yL>94g~eOc3vKEOlLp57kN z6`!eUM7o!s5XaX|S6HH^8=L3Gc=i-9<#Voc%*}M*7~6rgPy7XUEoJ2S_(mAPCi2&F z-XVIouHmeQ1Eqb&bPlySFVgZbpWt$LnH?WgW!YFIH6n_|3@()ZA z+se0W{_D{0m*|8$R&e*cV~QNrp?ccgcW|Gx%^V-nA>U5ewEqM&Z+_N^qEQ_-RTrt{ zMZN+6M;-GFzEO;?K;SD3_zFNI*>L8~IE(OU4xAAqLs7EETbvW#K&98q-QOA9j|zX# zRX8vRy`z;wt**bXm7SgF{K9KlJY_FCQf{o3U0wdJz};oB9_CobX3HDeyZm|_BP8Z| zxO?e%KhZ6e3NTtTWt*~5XdYs@jzDMmqPtR=hI7mUhE76tN4X+7jlLzPaiQYbwQ{>P z=Dk*%7}NG5NqL^0K5n9)&I3#v>dj1AEp<;_xf_wng%>$bwPR=L$E4Zj;D5F@3$S|~ z^T^lu2SbBpp{huh1rw=t!1DlZ?(;AWFzQ(iQvaco`!Rf zvPtRdK`zjF>TG2brRoy~Ax^LIU38ZFVhw$7t<8ABRyKmWuf+KYdM2CN)IG&=o&fhR zdUAHMvCYAs3$sG`Z>}6xkfP3AXSet>GK2iEc zVI`#PPJ&3QJkP*pA-YgMZ!XkR2xibZqbL|RTJGbugbytDFn}EimNUbxx&RNYA7yDC z$Z4~DnkEiRO-#%&fBXs^GHLO!{vUvmv2RrW`xf;aZH^Ytnl~>U{rMj}?yqaU(s~or+$|Ye5=j(+6L>^)kb4JVBh9&=Zw5(-=l^;NamUS&d zRvz>ygJw(yAs~VP0~hKocxo(MP-I~AS>nZ)d$g-716x+47+WcLsJsjtHq}-R8aKO^ zmT2u)_#5Y$^YT1=0|Yl?s7NHi-*D;Np3#Jk$^?U_3hEgwe#yODw?yrbGmV*r~uJV*^eF-z-%06IKi>T46U$P&NF1e`9;KrrE(Aj!}33mPj~4 zKeZ=x(;2s&8)kp>(*D|{ip`3KF!hOe~yFAUlSTkwOzUu?Vb*~G}iIFrXF{FK-w;?XnJJdHgG$aaCRV*_; z)Zq|RZ@GJTxnO7>qqKLnlmnDisxRAoq%H+!a#Obc8>5s9P^U*PRWF*C7PsMp_wQJC zR-UzO#FE8SHuu;zV(L07(_fw;mfmgJyg%%LiDnr5EG&HBjrH<$I=*P}v+w`P)*di9 zAdh||l*ExVu#gf2L#TiA(6AWRC&immy98?Xv!w5e6o(IVNU(eUWwJU z^mbQxmHurj&p2RJ5ht)3tFd}Pk*8;Pxx_^`W5!6meDYW3^5B(tjIYb0s(a6&er$ub zLxcy6rfCH4Z8*pDx?;|`L*L5lq$OxMn3z&im9M7T=`wjA?Oj28gSVMqvX&l|bJv=E zYx@Pv!v|#G(vej^RX&p%!tb~@3hItnhokiCNpUmpXniKt=nN3pm<8haUpb+|+6LS_>%% za?UF(_gCn#3ff2BizS6Js-m?PS+UE9VV@gBy5#x#HuH{vVY9!xJ}{J%A_Nkwmb;c4 zAD;jwXD^+{5@Qfm+J%)L8*y8?VLYm0ujR+QQ_j)EqOpTKsys1$ZB*nF{ z^AF{9Q0sxVEV1hFHu$mn@b=U%2~ZUk(q%6$4fvD@^8Llisgo|*&?(_xZbs6N}TiXVD^aQ zB?zJJZmdn)%oydl>C1(uI5$!0ATO!5wwkp6J8IhM6quSgXPr+``SlP)#;)D0(E&F| znAd6iDkiqb#KNYH_%}_zVzO&Bei>dxf2a@k+ZMO%)wzoTD8i~LY}sAtdNAA8>&p3d z7uY0C??J=zd^w{;IbsA|!WnsL6hM3G3>OR+fanbuhSMmj0~Zy*SDWY1ZnNbip;Vqo ze-yja-2b{ZRj}vFVWq_d0lD#$dzZfQhwHet~uEScbGRb9GIi| zSzJNM>V=QozK~M$zO|};vho>4vh$3QF~DcD2omZKeEJH8Xl2Z7<C^xW{D^J*u`X#nv8xIyE`Z+uJArh2wzep>OkKk#|%3I5diQ8SvskS`!`PAlO zn@MX$r_O}B{Q~PYjHKjwheim&5rNG^J*dtY5^gY^I#WAXZw3+z;sAspy4G#9A zmF03!soD-TZDNC-qe=1^9PrWU@{TEsaJZMuGzS;O{mJ!Khkb5bfimWUdX?L$`c>sC zg3T#GOKu(!92)9Hb$%h93~)A_d4+(Gn{nkqOTxU$Bdn8NcDyl(T!A}z2;b~V{H>+$ z*)eGCXWeUM7h%g{xRpg#N1j#=z3P!&UH-1jT|K;+H`~~j+INNsDU?KjB0Fa?p(%2J zO6B|#9h)L$AH-47Tg^$nA2aa8E^F7;3~;a`JxEJ7Pb5X?L%9f4x>|~$bop}V*WJps zuk5NpQ)@da>8=%C)Do_>8Iey9T?DA|2$3mVmh35}aKSuT!YiZIWUEb5YbLTZF-1~G z-{!rncjr;vGVVa@h)X06Ri37Fs8Qr7Vaf(HE$CZbuv0p5(0Ab1Grn3rC?7P_)8Ele z%hw8pHTSQrN7r_F+0Bz_S{qHL7nDqGa@Db1^?DuXIgY7%$6Q7AtDTasyk|MxRGYJ^ zW$krr-plTKredvSm6iyOWpyoAyF5?VX4%^2ThUoO1)r$jC2%b=`|&U%J3kOVPy{&p z^m9ws8NCL|`#64B*Sm|0@9s6o?h6nt^@wQyO!c6l?IJvWTPrW{3QvBf`kD5T9>1>T zqi2rp&|$RgcNNA1JCBn9$kJToLj6#3Wj5CS<{BH;?>nk2uEdA4&oyERN9}n^Z zdmd`_9a^l=&S@xWJG8JbC?6ELa&ZY-te326E=p5z+@UjK7x@kPj?H{3ria$GyBD+A zg-}VeuGJY&5wwl9q1))1D62k$bfHmN6Ry=`s%6cGDq2jjteMGhK*B^dK5LWI64cUb zU0ZJ9JL`92w@^jRmhZ2p-#>Q+c}%%!0Mf zxhuF=^73Ii&xct+ZjhG_Moi2Cs?E)lfLT)R3Ei$YW@nS1V)$8eM5EL$OEB*2^W>-1 zme0o~OK&a93rhLa939GM&Cf13hs^BzI1dsJ<9b6}i>|uRh~_b&L0&Y}w`+p(Mcj*y zV&mvNc@f%|W-noVjF32T@Vm zN7=M|)BU!cB`vk7S?Hjs%acl}>HmNRb8|x4A~PG{?1*+qqJyP(16K;4>1$R%$?>KWWf0U-YuZDRPKI z`4bRllwBPAbl@4r8RFQC&gAP*IW2@7EK83}DA4L7v1)$__(%WN4v7Zn|!kcP|ZDPMleOLLDNuUNQn z{jLgGzC3p4fB{Y}$Q29TshHq8FtLXFcR{L=APeX#(+fr$f>OQx80?+5MT|MNo@RdXO zb_hQ~E{pzJxU$Bbi^n}&!(>lojk{fV6`v~ia28JXk`~UNhV{|(AsCUG>pr33$Wc`L5b-zvGYy<+|wmFK(;_li~VPiW6|8TfpY zv*$|s+%IbSy1+NZc@_!Z^OW2%e4`T1M{41^3=H378?K~-d#)5dtA($SPrLN+xx!~P z_n`9JHeGza$=P$3zT21FxA1%m=KF>?&szRu3@=l{p_a6A3m9H*8?K~-`6%gBLv2JV zdncr13@@|pB~!z70*05{hLhD0zEkpt@Mn~8zF6C1D4xOaXO(bnp%yM}!|>;9!^vEz z_dU3W?FBXcL~U;y|Cf{p;V)|8+TJ<-BF5is8z0KGmF?>_#0S2u>}}+ysB$=idnM!9 zUP%^CpHueo$!BoSWIWq5SsSjT!}h*mIt*{W1Nt1&gZ81MhpkJv-!WYXQPO44Uj_8p zq;G!Cj?Xu_UzBvspV;yFCfli_gxm3{hAVqn1q$J(75)XvPto>Xz5hbPW%tJ=lfZGq2$j_OO8v9P0yjJ330JG zsI+MmJE1BlFh~pxv+f6vPmqL|sOW@PqqfU7MfjtFPH8{iG+chd!>^p%O~;rfj`ndA zq!;*;f3@=oY&&9PrpF+8>XWkP>kr8Lb8&b0unkj1w<*4lWE|E>oyL!$kDGtUh;ffe z3)v9=SJyj?VnuRNW?}p|>cO^I-`^!#9cxL&5H<(Jm5a9GC6G7U4GXN%Gp z(ZOTPvlSD=f)^WE?n16Z?p;S4#ENz;Zd3YE%d@(VvHgW&y`2@i@x^LAzl-5VlyK;k z)o@`khQDqbPF7n^Nbh6#VFgFrFJd=qI(J*ssUpY4bJle3wx*+olhx+u?9zEt>$jjC z*z)rxIc{wSw*08!O1X5cAw05fxiCDcZn-c#+OAyC?(Nd4?MKhprSpcy543aJbl$M# zN1tj<2ilXgP2&f{m2|2}Z!KI{jN#F?;p*PEEf8L*w(rS0y}HNwMGQZtwqvS=a|bcJ z$~Ig{2h*=q`T0T1m-E5!V`{#Ot>FhTyvjD5tTvsOVo?5-YJJ6TnSKPavpzKb!-NUZQ9ruRUK0jsq z9MXTmY5Hfmc+(3ud(R!yciemKn7+36d@b~st;{0 zx!c@7`{d`#qkXb}ClTyW975j7{b-No|M{Wm1+Tl^h7fjwBvDTj0jirOhY{lS)t?_; z9^iGi8gBgyIw!nMCg9L=JGd2qx-^=`zd+uQ_L41P5ZSJKjLed9$PzAvyunA1-Qczf zgyg{Uk0JgR?rTy2{-Cb3k^^BT@JF(;FrLAG6Z0pQ3sA1@!uMnWyn9fXKxTnI zOSnL0aqp3K>{|3C2f0jgl*_byDr{A*b#IY_EL`{&;~!-4_+D_|n#|y1NCrH6K{y2R zT0w?_-;rGlDP))!L|`IFS7+l)DoL<Uu?jSFayECWz6#NNFJ=i*^ zgEv9`tHJ*q+$EI1S`Us6>-SsIgVlwtV|9Ub&3q^;*1e+-Wk)R3<0D3)&awOqBMh$> z8ul5U)%TqHfOXN=@~v(#_^Ze~kn=ZC&JRG=JovxD{qNv^1NXZ@4jZst03L-3NdIoY zD6|oVQ*0-IRdjRJIEufF`8-kY4}rfJ((Oh#R*y`Uj=oe#-nL%%K^)F<^!2OAY<)W@ zC$vG<4phI;de7P=w2k_F)@E6|ar6;0tlnJoS$oGe$1rxNw%udfbMV#n9Vvck*@%4) zYsZV&*En$HP#;=dLmf*GS>qtKpgxPB>~n>mpkI6pWd5FIG1lSzM6de-`iL{wR@}uu zu^wIlxw|udpk3_|P0)|2vefk>cR_mh=r%%o@q=_TARmA7irSam4YDb~cDGypRgnt` z*5o67Ms`6uyQMJFPppFYzd>351(?>#Ihd4#8!42LiEuv)`{%)A6y68Gb0{yv4}THd zPU6pvA}2h?kQ43&0?!*S+D{v(RtMCMR?dE{z2lsci)NfK1DI4Fj&$5w-`1 z_Qv`f*5)1CgMwqrkB)d_WrK1IV_3K2S$$8>^ut_5M8`f(i{e)x)4kZQ%o4r=U#mL@e(Gy?ny=xV zKSdst4wHlYdnAL&MrR_km=ot)%#epC;Mon@y*tF;gM2|=pg(Wr!Eyn7y93{zr~_)t zkNt_1r`E?R;tu8XhWGz~{5-&pcmcx|9e7Zx?+JW%BE{h52xs8>jH0)>-IkA;<6i>VsqIbG zqd@~`4h$kQ9b--C43 zxcV@_?LFX{1OMBgjekipq%3eJpr3jg%A5`PN04;p#9nMABa|nb%;npYxpac%N6web zg*M!SyMy%L^(2zT<7!Ae$g3P|yK=AxUI4cTTopGL;xhNU;=oSuP#ol81!enL#o5n`SN{!wsy!F^0f4cO8q7!{hgg8vct z8Q`<9OW@vs`$OPg1UE{F$DAAi;j0yAnO~c(ITjp@Ok}XHWq8N@05}iT#j5^&;Ow1sTf5UxX*gdKM;zkk_GYM`EAK`l}ISie_J8yaVJ2+Kpgi3-d@X z;T|#ta2ffV>2f6G_n}(hiEnu z`s(;V>IHKDQW?iF-KUJ(h{W`W{&g}~KT?S!zM#~daGu1VF4V?Uu z3o#00WK!!I-h=pq86O%Zto6?9HCFE|&9BLPtoL*XUr1imKMZNT4)LES**YI3ABaCg z{}lNEblNf;cl-zH>Hx?f70S8{>J`ebOC#Nw&SKa`e4hnBjP#M*!0)Jz|2nF=k6|9t zM;-AIqy^(X@ooq|NH*vOf}UCq@t!4}qyZ4d@+pA&VfOcF&_k-8gt}?R@@LObCn@93 zOQ_2`kUqL3NFxK{oK^W@ScLqo_1=nvi(^Q*?m;M*3_8*c+DSf1aqAA{=b_yyIGUo* z09kAToe~81gUIdDCotyYNwU?h$bz93;TwirVoT z;)Ks{6-gNW9zMcd95nzYapRLdO1Km>M5B7zR<};jIdCf)Mj!0?H&PI{8 z8c&Et7^7)v>6$|wB(wU3uzKua8~bmrtzSnjsy(dr!HGvZ=uDRBz9w_9KL>kJ8|P^_&_50F zJCQzE-+iFm!=U{4fFGsIIY>G(3fu_1ZUbQvRb?JD_z&SP=*l6lfyWP}t4@rGFQDiF5;Rvv=;-=JRl zLYfO9p10Dzq=95Q+Dl-I(es3G-w=_0Z?W*5h#vIh2&j9-{=Eh2sUO<3Xk!cEicKv3 zpgv=|D-r7EBWOQ0c#rQ1pOML;AH>mc!FY({tvHlsVsLs&qji%Dww zZ0vke&DTg~@b^KwCvhIBC17HPGz(;LKcvOx@V+Jmz;!+t5IflCXT`C5`ljl}D^B~P z?bz8*EROOn9S`m0J>aGpJbZ&)^UK(LBpojf2mZ^+Fuo7i#CHImv!IM^!M&ke1HZ4( zlh9wY=N-YVgz)|lJ_E*r5RXrV`}Qz?=D-Je2^MezAl?zU-v!sj;O_v}h4}MT5Puw5 z#yw4z@q-|Z7T}sGTtQux=uVRoZaw)Fcr@W$S}s}3A0tmeU%U_6>{R|U%MRvCw~#`d z6I@0Lh4y3x^O+M{kta0AuO^Go!8^>kRgpq;I~Av!Kvpv+R73j)#|^Vw(Dx>V(1%Qc zetNZd8lGK(`aDn8vOHKCEMMk;zjO6Cwgdv~M6wBF+h1|y9ANA>p%1M97YK432(Ayf z7r`wBHw0X^>I%S>aF5~~@g89$xs8>J@dRm|;D(a>w6fOcY-Ql+tTMThQ{}~*EIWi8 za9=6DHQZK~4)SDjWHNN-P_E!~E#ZDT#0Q_rS##{(nPc@}=b%37xD61_%4btYtj?Us zocWW%owk*^&3w8u_o3>Zz&Sk_WAg>r2csQ;Hp%OXO(H!B&z6v*;BvrLWwy#u?roBz z+X-REL1*Tx?-206fV6Tz54{EBWq8KISUM~WU0ZPM{<%jlh_NbO8*oqfKG_KyFv= znNJ@B|14KXjxz^+OaXJ;*Om*w^KQ_Gh2lK2LR>Py~&@EKr_ zj1g`H`|ef~@K%#&?@ThdXIUI@q0rwh;R(49`iJ}Y7c3tLW64PV7tj?2WG&b-FdnN} z46YNr(~rdm|1qquNHQMXC=v+#jz?EchGTgPKo?9Vlk{0+F>{hk=82y}-#Z=p)m>yd z=yPV5-wJvoTX!p&&zA!Zeg}PV7;V*g(1#UDA3~fwk}SHBTXntRoj(Cnf2iR<17=Qw zZgVF^5I!C9o(Jz2f_|JYnc?~Z#5F-20=%3e+0s!+AKHpo2sS_!T)z(Q{6KCM3{Y3G z;GO|}wgP;1-y9qzEv1R-vj8$eUkrX*bcIqcH6A>Z?oh&Dj5q>(cj+;k$*z>;-#wFFH1E z*agoWeBB|i+rY-seD;odeXr)T_c>3nGll_X$CEqIg~2s*ajJii^xy-?au(0}44l3K z^5_b#9Mbv^xwp=@ma`D%#4-M`JkI&Ow?3b}D;UXgx|}R`{O%%t1kdf=eCBj_K$%0y zo;vj8FKc6hui4YeY;P75u1f;10yHp4K*Sc;t4#Oli#%l#OMG5#z z!D+r0Uf=T)$g?xZwlnDe#*J)G!!(osi-|#(#ky z3iq0?h1d7|FUThl@_;&IzH}O}a2ohgoQHaUuWdMvZM&0u_46SOcCY%(32#F>Wsu(6 zb<*nAP+IyNB`x%|aLwPYhO0hHAF=lVTz{a9$5q$O#$g!X_=Kc~{Dy+x8l2{9;q^Tq z3bGjve|qXAq80?^WFi&DAGEO*UBmv)G?(uygN{zN)*IIrhzl z^$QG7b^3$aeqoU6l>R_%-|QXfX~^?wD2L*@+1?9<@El~p%Ap@qzXLsBn-2Q!eq_1k zV9_Oni9on#$ zkK#Ot;kna1DesH-S}q7aU{862&uq8XhzEZ2-c35;`~(}*eMDmUpTQrbj4${Wgy8qw z?S#Ymrxf+O_XMzc=HoXt=2F;qSnGH2WU^5>O_I^E`HoHS-nTH;TMuKq=A@nVdj|W4 zkp{YVJ9!!B0gB)~_U;&g;uMqaygOV!0M6fH;&+poFlKGdN0YwjI+5;TJMgEGx$K%BsyOZ| zGMGD02C^_Z9c;3RFg{}63c7;p56}OAc>Pre@4{FzhR-3>`AV>nSiGSmp3fljxf&Sn z1wfoZ@Xn7Uj-|!Emtb7mIK9FCQsc0BDONW2?MWO;lA#VBVSKPWwS1Ak(IlLHX895M zhV-}~(vw;s{Xo(aug_bCvU~a^xt-^sPE2YUdcr#&Vp(QsWq|a$alI`+vT}f(a|d9# zJNFI5$%C>3pWH7bgTJ3-pwGTf!8>4s-tOSKFlU`pQodVP*nH!*&ga^#WoW>6b&Ug? zn`YnE?bkGr3e`WTe*63xd?Va*S~$n{FDPprbZpL3Tf^Y!RVgW!qyt7b7T$q zj&pf7bD>VxP2e0-3=yo~LD^aWsBdr_)_XkJgL91at*yCMzKeLQ&j*~1fHs}4uAw>7 zQ2p2ETi0+j;5*irb^S&IzT+IVqtC`H{Cgx4zh7O+X=}SgB7&3PJ)Ja(2;z346aPyD z{NClniM!!BINd>b?-Y@ANpL+C-c!HP*XN`?kp7EAr{7IP{eB|pGvIn65p?t5{k25k z_L0ZIJ;Lp?yaeu5_H7LO55T^Pn3gmMH@;Lzc9D{rwf%o5p zcSnQ21>~d39pyM)`PK+yXB;8VyJa7U%R&B2?;%8(nbNpp2BU_vMFV*F6duSMYpI!5hl1EtCG0nZS1K7=%#eSp(Tu)$*&DTp~ z;rU)N6W1w&V_zm3^T(%=+tB7rBe~!vfEx*JD!Ad`1__yfJ=M`a$qaCJ@kwB-!F#yo zR$Y_ZsP~yIJXE!3A42=JJFf9j*U6yW$ns#eu1T?X0gyx4cU*8|z?HCd#HzhB*S#%_ z|2BgC^CRgfbt9wU8CwU)u+{>cKRiDTep_();6{NnNbSj7@SkSS!A%yYv)=+R`GL!^ zad2OAE4$XmlUtZ$_N3lKj)^gr58*yrzZ}LJKap+hTchp?a!mIF=?UW&PCAA58PZ2twZZ50)%%us)rQs|1!{a1ELZZ>E{w7q zLQ^~r4D-%zfLEbLI3rbN>0E``daE-$~92R)6|X zTKc&0y)JWKSFfj?oTtRGzom!Q2Yyx-+aEIPRdevJaxXTGl!2*&i68E5a>OLuWU?EDY{p7_UyefX(Ngu{5FL!J=za-lB0+amrH~C5ZsrhNH;5!9_hk_;uNVH_S676kI&;mJC!X{lB1PbtFe(S zZ{W0Hv!qq{<^-Ny0Znd6*0bIKI||R`m$jOUd3>+0(kr~mRw?|9F!wP$RcMd1-;?f` z`FyQPT(kCU*SLtNz(I3PT9(Gt1rhd8z;D=Rd+lm1wjVVRaZFw>$*(5}E}xN#4^cNh z4P~6ElIBdjO1$h!DUu!LA>D7>zPrWd4(dL$gcHF9I?nEY3%b2O;}hY9z8_FEmPj@% z+>3F@?^MLx=WSxaa#d`?gul&;Lg;sG@sr;WUUYY$ajym72Ouyvdb#|Eu5i?kxZ%hv zRrmH3Sq-0K%Tx;?^#vZaw>HmWav9y<=RMPy)y`7#mGY<>%sP70s*7t(0t0qgRou3@ z=EpMO#t~%CONy6^k{gwRo5BSYl^U8KV_Z6jT*U^2>ju(Z<8}CAht_NhMA{<#g`|A9 zyz3tW4Yrd>@j@j%g#-%m5M+^qv3{y9%n7_aw%|y zVx~H@VF#K%h$Sd#5`r z49n#{{f%WAX|9+sy&oweCi7%fOjWGsHCGIsna5tRv2XR|` zGouPJHWKqMs@c5mXuN>x&8U{h((@Fu?~_by7VtMo3jfZ{eP8$i5_>73e=Nf z?QzwF^wFXhLvGM5S7mExJw-HnR_mLmf0XnQaEx`H)*Ti7dMdW=68qZZ>>s49mE6}n3JtniK#0w z7DijJ*KAIkhc6e;Twrz~Mf%PsR_Mt*`B@2A$$cAeA6hw;*zhU7+%c=zc|PGy<*X;a zUuL(+IemjXx!3oY{jxdB-JFM}L-)FNg$z z2j_7RSdMRA4{_#4kq&s);9NNK$7;U7fQpv#iC`l#ZnSi34({!;1czt5!4&~&lR+s> zlbk#xpI_Q8YT9&G0hM06TTIx01K#mwX=RP#Hx6#VQ_QNcq4Ub4v|W^86mCE&Zn=|z znqA)o^BN#*EFouByRzn0YZc_g=WiQ)v#l?L&sw>?^&~?YZ7zV(8*s1sssq|XozG=( z6s3=YEI)gSlnvod!5;0zF!OuuQ)l`6cq^RlPEnHm2}3nbG+ev4SG;|~f~DFNxspBa zN#A=j&2nQ}Xez5U@|-WSj}=l$(@T)OtGX6$B5Li#5KPC?lv%OYDsI&#dgp@hC3}%U zl&FXqE18RmUTvvB=HPO06PgO~;nmfn-^(z5T@gql*nId}$Fqrh$+ngW(pr}@j%3fj zb9ul{|Eo>g+~L>zA@@4+$bIeFj!LHM&`4J7n?AeneUelZA!BISvROOky2@f>zF$IJ zKY>CF6LkS+goDm_jn#|c>BX<8syF-S@&100b1u~sQd&T-F|@ArB1_D;!s@wMPi z#2u3LbOu{dIC3}h>iTMWj8x5PSz-$mvdMOU;pg~GYO6R<=VPo{yaA(OcfE9=4ciuX zunsWwSGskxd50?dCX55F5V7-}T>S^#l;z3-l)1EUo6Pp=vAD6r;#PaVyFwPRL!j<= z7rUnUf^m9sNt1b}uY022wS5_TTJ~GZfi!dJvcw4WkVk~y`37-ZYuCEIwe`s-%WDGA z;cF3a69jNJl;?V&iZK*=ZXbcF{R~9kcEMWL)=H*d{#wwwvFHyaJe=(hY$!7zG&naB zvE=36uRG-`k0$LHcOAr;Yw^#nm|Ez*F5#E0zi6WM)Tqp3Xk_T0VU?wfM%A3?<1fWf z$j>$=gb3x7&do;6TxM!-2Me84Ud1~+2u%2%GjL_A&xB@>WIGIn({on@#S*;%mT&mf$O}8)5JI(3)Xt^}wI>KMr5je=^Ofucjc{t48RDjoT z9-JyMJ=!Hte!!yB61FxtX0MRYcOG^#-mr?c=e{9s*zU6`QFs_au6RfGMeFMY9#(Cx z!_iEVxA@l5R@$FZA5^DL`(D~F`&5@Sre*c4+&1qMSG9f9zbt!Nq0e#6oMla7oxWv< zh7Z9lF;PE;nXYKOW?EKd_bmoBY~H`#qe;37%Q$gr;7vxW$hV(TzXjYp1Y!}dZw91( zSbjK$=VeSfP1MaGQ})hMO9GhSY3erTU%@ucCW2%BA;4!3-+gDo`)&Twu4$;q%%rI6 zeCWMCw4l_NRdmdFV@tR|N>GsMiKkb0e~IgfrW?xTULQZ`JeNO_QGGU~``P>hZfkV5 zXP0fF&z^sS?loVWV$5Yl#V`{f(|Fz5it!;c4p)x)O6){KlWP*Wv@))yZra@{M!z z{5jm_+)tVY{KQzfQ7bH;Q#_6EajmsknUyh{ZEJIq4P2a>YW%k2;vCT8;Uo|9kpTY` zm+jMtIPcEeyBM8XZv^`=dCIgjI8mNi%qCK7w{ZDA2;H}gYF5mB7#9oG>rt}dXT?aW zW5W0qe~SAnW{yNG#}4apZz{32!idhGNRdgVg_5i(3-)`LBP^NJ9&Bb;X-u!uHKq|2 zojQC+;jz1=A2ngt13PK1O3f5oT&4Ee>p&e()-jYO8C#`Nz#UKN`1-r!6)L7lr*bPf z5YYlhno=5VVsaMkL~_Nd&#X!t0nDVe@thn=Mm22d-<8U&hg60d|4K#HO3O}al}0n>mU?M!Y9@di zx^m`IDx13hu$gEJSbCMZuMvRZh%?5~57jSym+eM9_Nuf`c$lD+JFPAHlxnOotu6A@ zqVxcO!q_q?Wd)$%8XH>rUtQZMRzZ zJ9eV|!1$npzMasz3s>6bL5RU)OC={hxhIs48q4Gs9&uGt4~?0$G~PQ(6N(WXlH)a* zl6W!1@O709rd6pnvuxp(GN!qzn8vs<_wA%>>H&iBwl*}O94Nvq$;9INl_$d<_m`v? z;>DO8?~T1I-Aa^9eXy!hm%86`NShiGk@16{wDgX!vO=PO3et^c5hXIlP|B71OfKV; zX~a>J7Qk;y_1apDXp2)FfK#+DPR@ZDQ0A#5nkHhxX+=not%7wbnn(lSS2vBQr*fo+ zfO>Wwlujnve7{?5PLRs+WK|l|?*`)~$*Cq@ux_ECdk~(7rcw2Djs#-{rDkag(O!&WWoZhLrzWMd!rz!R zec9)uy#&{r$hJaC@luW0f~i-SRFDi~-I^&@?={kl*yUsD3AY$E%hTH4obt7uQH-Ue zg~XqVmZE!)Z-(#J+xOF&3YUavMhdmkkCB%Wd-GHLuiUoVXeUi{)k}wq; z&_N)Flh+~MHc43B`I&%xjNzM>6TTuwJ?<~J-?n)?EaTlrl20?Z;CL6z6Gt;4j+%&E{A$MfbA%@mH<12$Bmyjt*RCYLZN zrZnFjPTVmC!VIkzW^0tS?1<(b+)_l&MMGruAj~K1Vy|f94aR$%en*YkwFIR=tLt#h zSOD`IJtE;~_R?NW?bJ+mi&!4eUzJoL+22JSd1s7Yb5N*nFMII6N>2ZteyI+2L&;G^ zD;sA&MQM*p?en&xQ3zJ0a422_+w)MRq>*&)5}bF5{W_2WY5IyzH6;^tUShVMdMPKz z*joz6A93||4^2hRhki_BbK4F+ifImW-}N>eG1U%lL);&Et|^UU@B(m|>7o=E)?-lA zZV$kQS5n<>Q3SJxsiu*t%8)n$K0W!XblPVR8|hr~l+LCqB%RWiLfPk&zwatFQ*H^A z3fc+;9tHe$5kx+KNJpKDm&T@rKne_eeMnIEN&uQAsSvi?GL~?(6+-W2L--0pwb@A; z<~_X4No}7UFQS7(FTn1|)@`9=qL_z!=1ujIFQ!M8zf74`1m`7Jzaq)rrC6#^ATR5f z7B+z!whZ}}P$`G-x>#w2q&D`K+Q#@)8V-JC(|9lGb%Pj3*Iu#0fBxnF7g@cbU)qUX?-&d%Q2TJA4p;CYg#-!0xX*AGIAgu#2KK6aI*TPz?KC9@zx`N&<1J`<*8* zzPt#F%EGj#QNjI@<%_w;<%azW+mZEi0q`ZNP;NIxWm*7 zT+Q5%=6~hupm1L$4aZ2CP_&C5N^Hy_RUzTjf5^8bh-H(sb>R)HC3XLuAm)7R($x_X zV~nsAG_Z&*9~IOV1B*>#QFcvXmru^i>!4cb-0?j^imE%3^9qtEGxT1R3Tx&-phbHo z1D~x$F=j*4Nbliw$&Q#82?<0^hnhMJ9l zV1_MG%|f+i=B@vrXs@1=kHJz|)C2BZD&AhAXedXBme@WXXwo#C@^x5aj0mL~&}hC8 z9|^jzP17G0EtF#yt}}f`t`tI}xsLHf!W7!&lOMe&Lv*jZ>d&7d-i!CsCDoXVW}!Ng zc+4Tqwa?s#ZT^iH?HE`S0hmuY{ab#qEB;l*`zQ5F3v04R^svw)dLq9Hdc)6&^e9A` zl^Ien?Oj?qtZXTsOx=~WDV(Cv{zdVND6pBd@b7n6*S?ECZ>}Ce2<*yL0_o?d@t!q%X;We&G$gC6UK&VZr^D zLo%n1VR6Ub-j*yiNnT0f9Ajo0+wQj~(@etDb>`)F`;xWHKRtH5>u3LRj&r{M!8tbm zd5$aD2eO)qw!$CU*qHiaW`>hO@^8Od)kKfl9;;|E~4wP^b zS9``_iH8H}NY`v8@L#f$u9=c#nD}#w#HbD>*xkttz5}5T_fWUWqhKq{T=mK8 zY++t?r`l91h1&M}v@V2uagSMOBG~6+y%fi=HF;ADI(!$^kn~ZB5AUT!89`stO$=+U zTHiYsx+`@Zro-VZ;KVRY`j~@2(+uDeDTXao7}GE#_BI+YlR7LW!UWP_V}9dBKZEZj z4a~C6cteN=76%k_cj~iq?v7tf)Oe2j&14(LNl&L1w z(t`hp0@H|rQIN`}<^IDV+T~qWK;~z1d$Txuo}QU`6(;4sBnMw23dZPZ1454skN<5vqx?Pee>Y6hG|M`+faR~`4h%#d$u;B-UPK zlV&;bHue87LAJL|pAsoav$&I*XerkJ*hES3sN_)rbmPgn)#B3Gd$cH)OYuDn{s+ra zftFD(c~t7D0H*Qe{AzKT><_gmia+9y8YI5tQLm@sFpa0+?~Ti}d8jR1{E_bePWkRb zZGz&DcSa2&Uh*i{XRw(*BIoCf%lw}ydl*DW@hInIu<1S`=jMz{zuTiluv~iQZ?alm z2D|Pf3hs|_=>|PoJjl5yMeI4J-)Ltmim$M`;CEAYbunvRgT{9%MN^g=oZA;NiFy8pOjg3U_P$_Zyfw@AU$JsEhAt%c9Zv-d5{wtZKkAA+-L)}*t z=my#0K133aeE!YI zR(89ku7rja66^k;!owknb*wA9eNtDysVBw?Q->6u&@kqol$x##Yvrj`9$}(kxW@yb zVT!yQ=?GC#4fhx8_{*30=kdSUeTa0tN3u;`3Ejru=mY&oV;kVRY2a^Cj0<{50(`^J zdRN?!^VQ*_3HZCuoxJ~h0sB=C=Plkex7_vi<=ozXG%^3~a|^G&uW|AJn}Bb;`cB5h zQ&kTuE#4rT@4^zF{pm4nx%l=9tQtyt21xT?VU#xu>b7< zEQnN*j-@d`;ww4hv$&)OJ?hjpC4@El(bJz*oS*(*Bu~aAz3NdHw<%$$(NCKGtnU1j zL*gq1<9}0r`jq3rR|@LMxcFBO)x?X78T9p&K7UsK@5*UUk~BZ7-+Rh&_bUa#WL(s% zhbrRi9~l07a`>wrC2^Y~2H_`3bf49UpK{=SrNEwie)XTbgURQ=UEipUVsgN$)OOm+ z%NkaV1eBEN?txXFuh6h8-3D{w2`R)MZzWH?d{@lWzHF35Ht9&u_Imu~yZpbT2eL^< zGmiBGx+Tv-87h(EFDDDt%WuR?oytbPDkd4B9P8))2#P}pBmP$|3n9Grhl7r6OQrB0 z4X-?EJ;^@y*SVCd>XH4s(B*H=?apGnJXthV)k$qG-V{-eYwSJ=C#+&H?|c@?+w{sE z$C#wyJ%h8Lc$2~B{~)Xi{`EiK@t*=`wMiPXejjEU_^KK_VHNnL^V}eE?<4MQKo!H+ z&S$FPO|NbvAo+Xb7ofime7m6NKT^bZpOfg(j|hX>qKyClsLrDd4ix|QiF}h3rOss> zLK;C5yK=rT27bJ-7?WhIq~27&L0ctJwh*?f7kFYs-F5s4Ve4iJ7{9O$>EgWT#?t6K z84Nn4M^u8!|K8VcD{wo|V5D>MA9lY5rtSar;A^QCfWPIWNyZ@`5yYYvz$ERDx8<C~tcJC(Gj zEb=G-e{7bYJ1jyS8!4wSpX`MxBrrPZXM@_AF;fcP! zKE=&qohLwQWk?h;=eYwQa*UA-G5JONKjH}%tsHPqr+sQ(Z5WQ>;-=dn<)oqoPwrlBS+|6pKC zUtc#R{&m39|1W~RugXLrEl>*d|2~F^RZB7hy@?&I0C^Ko+2+~P?SX*8f8)OXXcsCy zw|s4A-1PL#`$;12N$v43q8*j*uZdK**J)t}jT1W!J=T+}mUITb;0qaVNw6MS)3e7n z(Ex8y!Vd*i@5>77&)nN@xwp>jzy-xH!?S>x202+2LvlQ1Zsj(HgyVMSM3#x?Zu1jxfSW5 z)|wW&AduFv*6%ncODo@oTEG1K-dy^LWs~2+6TwTf^bf$}MlRLkgUz{#n*`|zYJmcA zv5Crgp-VGL@Ap6li|dT$j|;ytHJ!4rD}SV3J2h7WE`7b;5&vi}VRU}^dA9C@D>SBA zo^ku!`PO57d$8^30I(+LV0@=H0Q?YSe7hLVX+R}Vu@ts*8UO~mjg3m~oY8<6zQSbB z00xJ}+v{k?kxB_oq?;&yz-Igr*WAQyP(sG90^-&ck zu_R}xeeum>&}H$Y+gr2%;LJPg{0Z#IuO~30_|M}RxD&#t$B>VF+qhYu3`KbjB%A9q znvXaoy}3U=IOESMDBJ%ynD==wuN0Pk77!2Ao7{_*{kL}nm>=Eji3gy*nu8XNVLJ@S-1o>} z7jRVx%==8{vD;(Vfh{uFyxlEozn#lArTN{>&APVd7g-Aio%v_&?P{TmhM>T$vxoUV z?tu#`V1}mwUx9k z*iKbI@Zd)wZ>V9U}EQ=bF$CkV~N~nSjzSpDR|)vtmQPI z5qL1V1HLV-S?<3}>)BvHu#TI2C9Hkx?4w=MTDtc`P)R_3F>LL$`PG<6Mc`5-3UNo^ zULCQxNz8jb)t{}jnn)X&KRk~!Ke&E@+0k$7BIQkDnsXOo`Bdi(+qnmykWH?o+yDED zg?w8WkR)JT8G=p)g2s2w0>Jux^Ik_{XD?782_fybl?y1R0oD#}H)~%kfd!r+j}i*? z4`BWZ9~KqA+?Ioe*i&TO@T$K>*B}zbi$t~jkjb(CJh*ixu2t}ZPt`))vD_|`z+CeM z{i_#)R`)O6UhCIIe&Xu-GJYzvVnFJR(uNvJw${fs*8m;1sRrccv3tPVM-nSN>Rh^?8Sro(uh0;MKg% zkI?jl_c`2jQ+qVJH}-=grHHu-nAvGSIq+a& z$07i1210C}0l^{W8Z&>t6uHTl-d5k8Rm*eSTs*gSFOlg8WSW)sws@z}#9(CQ8N%hP zIe+07&~2}1(RX6ecWh@EnJWUq@ypLvBGV-Yw zK86{SUapONkehoj(pa1?Vxj-QTR-Ee9dJDNwT}LSlOTSP@{TJR$Wyi9v%|I!sp?bdz*uB>v(<8Ef$d>B8bE4<1!Mi#K2ddJ8>fhD=Bo-}fH<&a!t#NUgT=^@BD; z^QZ7M1!HTIlKUQqD`ixio#M8&#bO;*Nw0Vwt(?Ta#%_{iN2p)S*IVkp7fb8%{-Tu5hnz=zPZ> zZlA0BZj5C!N1beKi*4b4|L#(8ks(>NTW5&;_wy)AJ@>$_HKS@*HIP}2wqQXZ;7Y=7 zQGIc?qn$){4tJfoXO6iajQ!o0tx@u3D~Sc1HqU5z4ncs^X7H{Mod?12(OBW&xH5(5 z4}wQ9+5!~aEZOYFah_R9gyriahftv_$}H3y=#AAmUYVi~V;C9Uh(uT$_Dj~VM9d2h zj9}cN0}N*gj9e0(o5kG`2eu&GtKhJYjB_K}1`I_%Ib`^ZpAJXJgHF6+5!-knU=Iip7@{!SNmU zRg7*8-1ttr4J5-V>+Z!nwvszHoSVj2?RQTZlZQD*9PZSJV+~PQCHJUvyg{XH%H5Ss z?n&lYlDq55u@pm}p?}B_O{URlO(mi}st|uZnn<6NDD2LFT_$`;AL(kFs)(y#TMc`@ z{E|*DtkCE?yKt8`pBi_Qmski(l7O#}Y=Xnj zNj4k8rKZCQ7~>*I+-LC7Nt^W)SI#}gjH4bL=QEm%NvHFF!sGt=M6krl%FoSeoJ+H~ zKK|(-qQzdC-G=CM{>@e#i^gLMXSK%4o_-^w%g03{q&)FL_i12u2-&zBW5Z%haKi_L z#IiLbQ$y#!LbtE%O5-gAHQFBR^-TE$wKEqw_vy{Pd9!!1PI1VJiT)?>Q^306fGc9% zl)x1UZ%U?J@m~9~`Qjb5QdZ$S!kbd4 zJ`ewva&yc3E`qJ(W7=6%3;VXNq&&W{w##EKP__oX_0SvJz_^hMTfnR7R)(7`1rTv8dV2W90wRP>yi@WBQ zF;L#=Jvt8$;@mdeLKq#I;XE|ow{OdrX_vC!4_m=a=;pD_)x9RSqiY&EH{008H{HH* zqrPyj_#K`pwz9Y+MBGnA+&H3U)NwTk14QO`L+;NCxZ+sev^_;s z*O)VkU2EK4R|EozCy&vI0vq&bqJvP(6)%G;5DE{NcY+95Kwql&}poq%(9~p87i_?VS~@cyII1pjZYqdMdrYrNa^F6N1!CBfypRDFWPiB}mR8PBLLJ{1Q(cn#`gfmzi# zZ5wWelGIiyw>!a2X4Jxc?N33inO!YTM?b#xx6xRdYcDz-jena)o32_Uv_9xB$7*~q zT~8SB)OyZ4(VE1$$(0D_=9z^-wZ${3XT3DfYMh?AgZfBewxFF(FbgX%Wxm{6Z)z~+ zRgadqSCzWlQ|-1smdR>g?^R<5bMIf}qMu}%CYOwv<;%N4xE{vXIpXlA*s~LCFJ5(& zCLv)3cKwX4&K&fdR(|^~)Z5>Z47GCvp1{`o{pDB?yRHIolURNnS7c74LmZjJ z1Hyp>5c?uy+~$c`vtYl8GCk~7iHGW{Qj$HiNiUtE+|5ZNjMV}k~=fOXD4UCbR6 zcwEJeJnu=CPxI!@ZY=f`tOCPliT1%S4{*@H>4dZPC5hc2MwtcDsl82qyyJro%Zf7+ z@MZGrm(UNPq$p3n#n|cH$O;Ac877GA7%4(_#(9p6m?X16QjnqO(zS!uZ3@kUV1>e{ znmr6>G4dPi&S6!Dsht?*MAnDb#45B?%Q1jcW)(T&P6gFb`}=JJu^I~JgMFbm(;qPM z39GF!QABjcacIIzb;383*8MEFt`x@!)!r0{-X1mKyhm^erd-kuMuy=lic{urQVxF> zt->^SmLHOmZ{1w)U6iCszi$|wb`U$zpyVx~m&6?s?q^B(3F&fVYM|>o(?u@)n3i1% zrB!GlqW87!JDPTqyP%|#rC8Ka+0e488y44L58gPonneb~y6pK~$b`3nhYx%{=057wYJrgs=sqRAWZ`Sg1l3|VEbki8axW6PjJh6`&F)bu-=X4!Qj`(sQ z-5!=D!CiZj8MoRg3K-KGDf}60c$}QNx!fg}vL5%(MHS@6B|N_HqBNIS%6+`qL=fm) zeDGrT8~uK6T6e%)b&lV(4xd|ix6!Jz{jL#GF%d}Si56OE2ybB~ou!91!w&CH%O0Y2 z7xsDtT5jJMv*3DaQ|UC_eI*aykA?z++Gx@H_HznVS9Di&i~F|INMV};4_8d9ym~{9A_MG@O9T=s%HgDx!B54I z@;@)S-K7&BlXh>=FYnV=L2Y0TIjRNS4N!{PzjYqqOKEJPVNzW~Py9GvV2JD)17 zJojZ>(14D^3)S}>y=0RFSUV8d&S#j{3LTcL%OEm;1mHlS6dDT;?rBLmL}*Oka4dx0 z(i}#`PmA0aH?7X6izre{wMev7quD5sW z7zZ8kUWfJq+W}XSQszaAI7kbtA)MWS@R0WL1K;Iy-zM`OG%dYnns8P}vzLzWgO&S4 zJb2V4A0+K%>?>`=rb_BRGU+FB(S9VdXN$ghAsg)@y0^Z1;?etZOLOU!i%yQt(t=TR zZ5~$gyv7^-RBOerbj*piZq{~|zunV8!@jc*WfRcHble zm~nT2k1#JkmZ$8t;ZQ;}EO2OX=m8jy)}a-#==TDQ<0#TjyH?LzwQOyCDrEF`UHzW6 zv7q;%&_Tc+8^^5LO*mkfS6vY4SFZp5$>xe`8`-78>Q(ANWF6VCg4EU0ZfqUvaER1Z z=V9a$UN>0`>oDdaHXQFI(FjdXgR&iN8hwvqCqESuH;u70lzd;=F1Fe>&WUcZWhW~k~)yAN=b$kpg$ z`cuQ7QM4HK#J;OGB|_s$<@LF>q=RwXR5b7=U?eMXk9+@^e|X7sH8JBvI>gZrEi^6IoQhUpv+vc36)8SLb2oG9*ZNi=8b zUYV4%T@-2ofvGJ9Y#LLIKieidQ(e~%zkGz;(B%;)5vj#R*C8F{KqBH#lHP1}eDQ$B3U zQH5Nd{^$eYTvTB&6IJ^IY>6({3H=3nAkm4;xKl!hu}e_v>6dh^v4FC;Hnn={QKN@u z6fSCq{3>YnRhrH(_`&gqPQnTTkcHkuo)|Y_ruZ5);bW6J#)KLz0-pz+0-QZB368pv z^HNMX-D%QH0^Mnnc?gbbH2$u5gcMV_yt);d!kr}?r9R?z&xcVfuXai@xhIpO2Bo>| zaL+^NZk~S6^nIHUsv~hi#zZVnDq9Uqh;c(30xCm%9=SSBa3SU4q1t%Qkh} z7U4w3?j~V(R_wAGcLt)entu9(ynld4KYeVTN6(bhMRMeUl(QVEWpelaN~$QSv@d%s zIQmF8$eTOc*Cs)>6HHX)8}3hg;Ts+*>GPejWiF|*uVly1i#erggB0bH@yY@5X*Hl{RKZyoSh{YbAKwANpA|_NqfdcOZRj!*;td-2;uGCQga(?ff}K# z=h@nPL!310cZodTM1Q}PSBGzX6eTBc;gq8jI>o|`%bw04sh_dqK~nq}PMFV$;H_b8 zzu_FGUQn~4+aEKJ)}}6c+8H2W7Wb3pmTp#)=koW^Cd93&OTG5x;+%V5py>)i&X7XCihzo>kN?+L~pSqBQ!xe2Si zqR0iug?BWVvl-L_yxIdzyM%zcAb zaekVzVLi`>#HOOjB~1EIGVW6x>EKTu@~ty&3^TS2lJInr&BkyKM!MUXMU0)(`0HF= z^HEi~7c>&q=$}Kjxo<{)!rdU~+);l~88^&8qG>aDEsnr0b&^@fYy{A(X4a^Rtb5Jc z`BLaPS>&0}^VyDHkSmv-b&1{E{x??*&|bZ~$}C5}UsO#B`-;9Z`hLyfeV@RLbLRSk zFevH8ZU<2ILcj-pke|3nfX+XiiQcuCJ79Q--*0dE zYAy-bl2(J)va1{`FL%&M8d!4$yx98)1r{KLLs)%gVl7xAyKOg5q=H!bfGL!ryM{?u zZ}L&Cp;&p`hb!rDg&!xFRd^$77zd=}Xgs(-xfx3rZYaxo`WC`{s=w^e^N#{yx5JA4e5ducsWO+ zeAhGwoONmb#66%O1UjCAsyy;PJ2nLOKr+&U@H3Y4P*%oP z=oMlqn1NZh`vluA7^9J_<}9{nE4DuPq2hU?`gtQHrQ@2;EQlDIQUmR~Sf@O_j6xK$ z=LT0D8G2n4?-zQYm}EnA3!!N!9FJ3+xweN3S&68(=Ysw>gp5JGC&unCpiXj;iK3gH zxGj0%8!&iq(q4OvWT5p5%>Cy5IjHlRp~|xR$Z2_v@vyy9U=e=cHgd&iv(4BR?pD1h z*)u13vBN0T)=9e9wPbdE%^wh)0B!4CU$mKZJ6dU+J~X@CF3mqP#9_<#-@{R#ulqHr zd|Tv(@8LCR!D8o$tX~Ko^Z~7+Q zSko>!{viTRxb1GDh6+JU5iVFF(2tB>Z2~iwBa6qCG z=R+a;infT8=@YqgxfFS*E%Z;izcGrE6M=T0(E8nAK`r5zL~^0w8-j<|I0fw;e~KMw z>TAo+{{$90&?MLY5fH&Gm8Nj)u1RATx6rbv&@%MFDLVhAeH`tJMC+mxPTTPp6HdXm zaQJWG&Z71q_!g|pBMvw(fLJ?sg9JMfw~%kF6Q5#`G!``$X`q>-Yoa!zEv!f#9ijQbQan*?r{7VZQc@JlEWdkN#{mtO!#iej_w4wotcW-F zH{y{U(MG!ZrQdL?ETa6cFS{O&@yEjS5MB3txJ=r{9T-6sr8ze$58gaPwY%FjEU>$) zQa~izvbj-QcxyVm0nj8l$tG9#dDQ)WPr*{>4;|3p_}99^{^nH9o1HNQK&sQjqF6ln z+qWJ^rpRARC!~O_0z1zm_Lx;Vr-06T^S7;gT7QM>9o2%A5C!DrNN=nTYjE)CS?4&O z9xE!i|IAifvEft{LWZXpa=N0Sh(etrZcWH(NoZIbCK7jqH*6lepOj4&V-X_=`;df9 zGHi}5DDse`ivvG}t%1;{{1&2>vzs1>jH>ek(+>;wln{ z&|M2%SRZ!7V>|y8?p)(vP#ki=H9AtlSTPk<7V(2Q`ja{Uj{>Po^zGErs6Wd8LEm+1 z*bf+{KEs_8IpvR39E3wfF6xMH_-?5cy0%Bt1ewV>HMo3Ld(p<%WS?f1*=E1>H^_~c z%XmPA{4^pN-Nw`ZSlN{@*l;r!tDQ9J!C-afJ1ufzE zSHjq@?&Xgbciv>}bT${%z`ENRpp(_s;>#5bN6$zUCQ~i)5tDDqx7{mrho1E%i^ml* z^nVQ}6^EN(=f5Iv6i+ow4-tP8`F@B)e94lM<=dti(U9pa$WDF&OB_87+z16vV78Dp zd0*0O7dy%C?|g{F^(7%?I39=R-8KQ$`95`WFw2&X7m%iSA&^Da}z zXADOsu;U%0a>v}Q1?5;fA_qC!ZrQI7$8Bk5V`66=~oOVMaNSN;NgmB@b#> z1^ZVIF8+Lm%w0R14ikg?jF4~J7PK$E;n)AKhTueTo%|=D(Z(brU;k&4DAqa8lwHX& z&w!nv$!=N0nH0O7aXVOS2u*tdkS=CZs?RqN*%+rM)a4s+pCLc_0|M$ap~{Q(1r@5( z$~$7db5`01Yo94f1pwz0-w&`m0X~kcs}Y;j&>7WCem6-` zpE36X?%3_$KV$!c;-I9y=N)L8Z{{8#UB6KK$ie-ET6O*S?TP;rC|~7yF1$@O@T7bN<2$pPb+FQaAAW zg4xBncvh_bv&hol+4RSybFVweMu@g2i?72+d>USL>5uGgGTN{6h4{00Io-M~;|lNg zm%NSde@-#qfq#lI@AxCS*k|9@VmqVvYC5`nvSZk-+DXPkPMX?;p#Rx2kHTQ*HSaH9 z(JF(VMpOa@7vS)&W2qd^{lM(O{gCWCcY&7?s4xY~&ljJ5+kC#zTy44z7ya0N-(gm} zZ@Ozgv|~K>G9?E)4~p_*CXjpp(X_jpubK`Did=#vN#8^L2!B( z-}9=-YP`m8Gi{7-$CT36L;)el9;B*Nr9BYjR-X+Cpt+E{>rAsPFA04RX^|Tdg)QC^pR_xLcbLD}31Pyg}=RZGp<8dtiP-4{%P6d8Mmu zDt<8gC)D8Qu}*_pcLPnw-sJ$^yIL%g59IsN;LT5`hL$eJY>_2JDiP(3w-+ywU{!@)VmqOP}xuhKW^PHva z{2x`dhaPGU`lp|d;yL!EJkO=%E;zPw!p?7ms@>C4zr1a9u`d*=wnUbhQlmMR@gXzX zgff>5wvl;w)wP#ba0?6#(6;?MRP$-3^~F&d?nLhlrgLtJyAbgqN3B%Ny}uSZ_z%ox zp{oi(kl!IkD4bqXhce8f=0c+@27Zx55do>EJEC5#1r-0C6J`=-g>;PDqI(bfiCy`e z*JKzMjfJFF3ig=!hx^A3j2+HetURNP(Qu0xmwbKn2*LpGF|R z&ts1WE|{n1w2RfI@}xL^XqWaK#Db>%*8Nb4Un{o=qXO9KZ8@u7%p3Ku(-QpG%I%$U z+)dVvf{codkVbJrP8w{TZm)_Q-d;0wk@3jodE2)U+h6=Pxt(g$OulMLKaSg_Mj6dD zQ!QT3n`h~nYd$NkRrw@$^ucLGpFY%Tt|8-1LRahH#@`m=Lt6BfG;0Go^36}L{egC6 z18sUs6{^#btrjKrX;&@abp36rh?9EIDQB-*56@Kow}MzU@AQHwMcT=7R6koA`kGbQ z-T3+nv@lQER>_d{VWxd+D;I6$MEjTeN_0l_75(~8$s&<0xm1BW6p%S$E zvaIx$AloJ`TrpOZo(B|WLz4ymRUtSHx{ncbm*q6Qon9Yc!{AYW_Le%tQDyFpDJlAG zFmQ0{psN2|sktgVQ|WhUIBb20T3MSoB~<@d_3^67osGuTH!RkN0X9_(pNb5;7KYW&7y+FDgHz)? zT~(eJto+(-1D+d+VWw9|w{QmeO{@xajn=7W(;P-`Po>8V|7@aan;W z=C>id)|BD8GSS4FIwmb zbPeT%Yvl~h*sY|(pAt^XnjLd?sSIj)1_g7RCW=EsroF-0hYAa2FjJi$zTFbEH+{Pq;EG9E0id@#>+ek98)miK zW+GlsYJ7uqO`t}${oI0;y+=3Sx6sT47Z^dR_g0muY@7yudP?32@G-gnk%##RoZ(B! zb1ZW^w6ml8x|{r!EUo+g4@0zn`97KM+To2AnC+5=@{qQ#?&}}4GAQ~lR5iKsvuxkM z`P1W!=A_vaN515wcWjHE_5I>6H}60GD8o%MFUeTB3*(c^(8hjoN$S#ays0^FD+fuBt7{e^1=nwl6v)QexOI8L}dv z&>Ul6a}OFXwJduO$g7NrW9|y{=TYX>M%~^~{J?9lvvm~_d+UR0P|0wd?Vd95QfeO%%+v<*eB|B$~&4Yi=8U7yX{hb$4 z2%*JP1;DQ1L)%XvoabVm!KoaI(WJqAy#FeRce^!`aD1{AJWC3b7`%6^T}?e@4<3+c zRbfS>D^mVz)%H?8??e}Uqf4XhrQmGQz8HJNv7u<(t1gX0H}hRhIGjf8^P^sXz~VKvwE_>jqE26?c+o!%Tn zQMQQ3sZlW%FA2JJ##5zchGlP7bAl`omPwlCm1e^2rF#}Vw4Gk=0D1-ERil*Fv7X1N z>jz~wOez+lio`b&#!&*y)+7*he=fT0#jS5D8fz8xDR9>7!FI-wg!dPF*9dYyz0gkg zbA74>eg1f-N9%Y4%357JD4e?NN8czLsU7_(sz@NHPUX9qgu7;@*HJNKR^{Z5D z(0#>ls6x!ojm}Tm$1PHPb8aZ^cr#!y1nkP^ZcB3s$^J=?V=P165f?(J2m>!>xv8I;wjmMaDQC^Z)Y@tmuYH0J}CAlJ5?|AEQO1+ySLSz4Rv)ThJMj_+>s%?>V-Ud;}6 zbjh@(>rm2vr)!G#JtvFqIPXH)NzNbC87_j`Fn2D3UH^kNG!;1Ixi2Q?2Cu>7ww)h9 zT(*=45sHYu!2ddw>K+p9RQ7jkxXkdJMEB9c0UdvS2UU>jh+xri; zSN==sxU(}O_H%$?6>~{h{I32Td%~xX2Mk}RT~mDSQ6tYN%{eiymv$HT?N`+{Lix|8 zwK3->YTMxx_KRZIU{Yri5fk<&iI2ph|G;jXN#s#(O{ImQt}5!yA+GWrw{JsFW>_%i zfiU&6>GEd)F}Fyj`4hSaHa957s~GxbDn#v;4N;yQ z!2Sv4DBxnT$uq)=`j2L&(czChtWXBfAfHqe}>@UIvu^DhDO$&-2#pu$%S+bQ6*67`E{ zx2VEMiA)FbEeCQ3c@%_lL#MErHM}vK?*so;i%&HbRUQJ;W%@~{ZM{g#vfW(7&vdG^ zGLX!w%>1OZYn%`p*Qmv9H~Fxe_n=4jb7Z3(`S*_REl7Fw1N-RW+a1*xj%BuPv{D|e z9zWdOdkAEf?Be}7K=)_=u0rI{%0Ecef3qX2Pw%~F{zGP6$azjF`9{h9NHmHGjtU6Q zIB#DK;lS_;VzcLGYH@q!0qT+BgS#PDv$a3BQK@e#(m7rF5Ja4TJrn&O?RM!nWG|9*HV)W>Fr5vk z>OsKoK!!<3__>^405=~b{8TOo6DvmefLG=fI+I z7e_)_nvdu9`J@d-C{LQzo^G=wkS+)Ah8ILFY3!(9rD!xjJ4o8UFRr(!J)iArrf}%z z{9L)M0Q;Du{-L*|nUcJlBSjYyQ9d|#z=^!zQHI5l)E}i{o(|lZ3;n{6dDx1%AJJ-0 zZL9rB=0Lr@scQaQmQ0C2LO3W)$An+ofU{7&kgU!~=WaOR9#MI!RbzX*jm!rn6pXOo z_UQi3@iY&92xeBMybK}zKH;CI+*VMx;~$Ss%|UDrS`LPvGi+k+ub2jqway_YTUV$B zIj!#u&0mp*K1zkIz?*)PG|z1Ql8W}D#&X}By^Rw#0gCk~c7oPl&re#$8sT>gLT@yi_bRb9WbVW-SY?viIGw?$0kTvV2oM&>b~4_7>3yj2a8)VewMwWh*-_ zv_Cw|Wh``iTTYfvHj0vcV}Q8UYZUZ$_4W(s^}c_$HGbdtz{zD`{(Mqj@wwvbXYrDx zUpq|ld3Tjx5q5lfgz2Y$bv@1z8NYs}^)vde%y8nBmEVthEPJl?Jfp|mtS<1QKhv7$ zqgAITJU)55Q!uC97XOi-7Q=Yr_)~%g%DK}UW^?UAdM@qq|Ed_E<~zL~ZP+hr=F(^} zq9=}R6922pxdNp>5t=Ir`(NSUKM&xZ;ZJdGjMqt}C6J!{IC7>}tZ**UOIavVs7r|7 zXa^D~Bk-d1d7J#wpAr?^(!4oeR!_Liha>tr)7+LTY87Fb^uJ602VMqiPKgX#e?5xA z72KZ|$ukvDc=w#5yJ~YIJB1@DYPR(KD}gw}FR0O5^eRU4flQ$y1J|gs&fB7_(&(l0IZIP7#6UXLDm+rc85$e_&5KV6hEyzdT}x@}xYy zXw2lP#l1JYAME-)koI`K4d3Z}eX=HaGW%}~{Bx1u+>Rls)YX|= z08}ANX1ib3gmkG*q0dz;JuL-jU{cTl>xC)k|Z5k(=i}5>@qfQ%A!U&7<;>Yx8 zeUdAYW%<$pM;Mgml>OSR!9bie3v=Kcqy5I+6XxPU+XK#5ubA47G!kT3DNLUR-zcoK zKj62yvt#+QJ^_4BjyEFY$ZPz5W#^8Vme!3E0i3gfANPmZ2R}J=C~tpr^!rP4DaW>@ z0_UYtk)AQ!bjP0WIkl&!Z){~904Yu_x3ji?nfTw-@Xy<}dXI*mpy3FAV005=f2N~z zX4PBXua%pGBbskVECigzmJk9$r1`S21(bjdX+BD9SH!|sRlbWGa|S<;ZhyNY_%rZ| z%H#u!M|ZuiNdI5BFa7Ag_kAgauW0-GjjuYGljc;um}ULTmox;twcDpQtn@{tgNipO z)$w)uzf6*LXB^y~a9StL%TnP>S@(&Hv{XBEScy~p)w6A(4kD|Y6fLRb9~z@-iE~{d z>rP3SI_-tfoB?ePsmNFO#HcNYp4ud;B4o+ zfF>uj#FwgV%V8$_?39G7XSK>yvjyuD8QrLs)!<$I$zTiTIXLHu$2G(g8p7aDgX4c- z$3w?__H%r#I!F2A!7fda$n?7YLU%!TnXfXpJvKBdYJXD~|K`-QGL5`^tIBayRt}nm7TICU>%#wkL5A<`eHB z7<2QAB$OGMtKE$GGL$K+(3PJy;weo7TF& zLs0R_h}7RtP-IE}Z*n2eLg{aZ?N|R%*;xr!=cgbfkON(h_U9F;qB?RQk{EI(9!9z1 zAkh)QfS7;oWBHls&MkR{wc6|Y(Q|cFpgKuoG-Ci)vG*_D^8@cJRCRV-+_Hz>I1_(H z5NHN`WZnp@I0hya*-Fp`3*q#>HYMZia==zvIgZm3B^0l}K*e1|=82hpNHwZn?a~$v z4n)gi@*eY%yx~|OQr%0xQS(tvhJ-GQB$BfcW*uCz# zcij)h8lydb^f*XGm!cg=c?_LuJLip={J`{IT12Mb-C#PUZQE&mx8~a(%ABYqPvtL> zS$$$n)p&7x_d6#|JA>kGH4K4Gb9LN-O@AQrQq|ms} zDIOd-S#v$(xkizsdV=?|FRz$SF64!mU9}d{uVQ6Nq+V2Zi`M zfS0cdI5F{+q67`%ZJwC_#W!=NbYY`SChjQ4!Q!ZWV9;HE&J`BoWyt>zOpXBl-^u?- z29o5f3;#cWV0*zG0}J1UNRpYbn6?vn4$8HK|CFoeg6PH92dX-FosC`gqfiEA%%|70 zT3gB;y~?-~-jGA)R%j%Z8UVm(5d5qAm19Eb)LX*i4d$to#>~GnO&z_#ArjjU7HA~Z z{+-bNeZoNqd48I_y)APB{ZL*t=XEW!YPVB9=9HaG$eUoXy?B|ElK|tJ#O%b9v@$Q4 zu|>O4{qOY==|6fn4X9rRU8;E z%jE2~bJ%QkdGFEyD?Vym2$q7eePHJbXXTmqq-@}b< z5Hk$NlQ>Ui;EG9}`XFx~O`4CV_I&FvoZ4lEeaojOuj-;Eb z`=yyTNImD#P8j31o*g_u;l_uM*ZS&Dmh(KL+^ufYhm5y7(r|G52_s{F{)XQ~CHhrwb*qv!#jUUpf_#w7z!Eroa<^E_D!;a%9>DV+w8^kReoTUJX4h zc7x1q%Ol2gd_tm;sI~yQ76ZF7f1z!=remR!K+0t$*yk#>kNaIzo^y}$TxeXTL<96g zX4RbUHSVlugH=L={9f}}SbU}WKlqiQb8WZ12O$Fm$5psf|B&EPguQ(7W4{soP7hfT zKfGP%*0)!axj5rlFW${HJBAnccuWf(mi z|I3VE-nnJ^n2s$t_YRdo%<}QJivH=hU*3;j3fC z?$g>GYyA)YCy!|rZ=SqZz0;k4SL7G&F{$8p^haJz>w{){2^y31pk!q72Udp^Dwo6H z1B{cJCA3|$`UWXLYwp-(^i!lM?aFqIGixw?P;o9ym!*fDKGW#uOS=$7g*0G@qGXR$ z>-0_fn%+?T4;q1sY1%n^3_>wtgSfpq1FqTxx4WGb`JSiSSREf5Qn)+3l}CnX@>tZ2I?O%a0)wTJ%I7Yz&mV z$VQ&%dK^<_@*P)JpzZ7SE^CGBp!8V|*G~DDSnw}2`%$STz+Dowu%fi^_@r4}!51ZR z6tpw?b8P4VQ*cq9DVN{NNT8D6=X(-ZZ=OB{snlG^6~H5x-k*;Sl?@vpVR1~=cGS$A ztEiiqTq7u{&DcK`QlTDq#XX)%Dn3K~#EPwrBzlSk8*xm~&sf+cnXFFJXIK0L z#rBOKfM1u_WA!W6@LV$%;e-rm#n&+|KKIX`um9yBZcB02@kFjm3mePx}`I@E34#;o~NBf z9BesW7<*GzZyd)w$b?m(^F6R8jhrJ8@dPdZSifD{3-Ycn!e(){P=V7t2(sLoHw|D- zL!hPsY-0*KTbogYlkd~YDfEJxTQeW%ejFwT$KL{vYHx)`)&7w~AB!w&4TiZ$Dsz|^ zXdBFOCx4#TM9WJvz(kG(XKj*$Yi~)Jqy|SDVsVyR6}rC_-feB_Ixe`O{e_ugBbR1F ztu%}@(Z`QzxUs#rnt4h{c zsbo<#OesDPdK)FAsau&?z-SEGMW!SgP?V+}g*8qd8Lu5gmfMqr(!k*>fg&{$N#)z++`msdis`;xU`h>FB3}weV?` zvm)u%O9wnHuZ@$PXg?K1?_FaQ)u|Xq1%WJDg4RkywMyjrMTEqKdipsnMCy&91f|k+ zjfg@&-6LWB&166(;K_ZI4e#N0gkYjZ(_##V()YWtr=XF{4-{KlldarLk9MPT=Du$J z1VCnnQ8GLuEyqHkc`%{5wUk63vAnoc)z5bPj?-k? z({JCeMvF938D$n4MdFl$+nf&)-bNy5Eu(iFD#fc_9tZL+E=y~1ni(46sy$|)*LkIy z^*!5m@>|g)hNx?c)zrY#Xft7j8UG{=q~xby&0L!&h6CAFX9p*`?)2ONM7;?cz4Zm5 z^5r9sl~!qy@mKTw+7o=hdfBla)~@uR_f}$y9y$%{RY`73!&)zu(0?rZckI%_JFbK}HT(@PTgew;KRHjon?n}Z zlVzopZZAQWqB<+HX)5{Beh@PYWK0jyr-KL+Q0%Z};=aL!d9HKYyIs;7QjjD0#5Ck> zzH`2VQ~%A_^^0ypiksW8V1WQCIscLStj!9};J)i;z7kDXvyfv(ohzm+1nN6#HISGQ^`AqzgQj#uBDVPAK0;98-U|ychW8 z<-<=RGLmEVQAZ~t9`zjrjRVg>imjX}Wk>(3+Til)eh(WujlfE|`85rbhUw=+OAjus zTUcswm4e3%_-#%l_Ux9_56JkN!tQCc?$os}KY+WQ%bym-lUwdscKSAi(4{RnT&)O% z*&!?)lRZ{KP7@hUOP&NTt;&G5_#adr1q-e8LPjwchS%0*LViHS*yGSa4@m_IXq5@l z*z}CS;MLPcLKSkt#@x82$IJA5hd?rkJ~ZF=s%+h>w<0GdibURnm8(WMbmR!IuisSt z78Djx{)At!K$iqGA?0M2k`X4Mi`+tALvR!pz4~`GzM0Ir!P$ulyaDU^KF++8IuLMY z)4OrcESEK`5j&*T2jj3V)_v4-Hi64JFYI8}HMKG+jnN;~nMCaf3Mm`I^wsL~V8IRo zT}~pZJ~3{Ez7ghhTS+zeU8LBA+gcjWpBQbBR7acK7+wui8E$Ib`Q3ST&_!7Pppu6eE34Bz{yhiW7fu>E7n#%A`ibdz8th@bIgUBY++5lm(o8^oH_f zdKfJNZyq-#tR!DZK`4seHZ7p$8m^Y08FS(f^wE0C(>2lQ=iAB$kTa`5KqEl7-`w;_ z$+T*Q42ld5^tWtG#Wb(C)SNxeYSKG?VOkY*zDC?1mbKmGFH5`<%4@dM)#Fe&8zfM2 zrw8(g7B;ma@YVZZ+J?wd-iuz1Dj)WBjBB-cna@V~Bunv(Fr;`mn|)t7H%$I|7W$?9 zRpJ>_T5I<)knAKMa(bMDIexZob2e8a4y*TSm?CR7Vi+7HQc3^{=4uXdWmCfXp|Kz>n+)>IBA$%0JcATqTwRmpbxz+>WO$#Q2F}dV13DI>*Jt4)A zvgI#uNTD=~HmS0Z-087N`9w&e{%@_;qO>T=7?D!S;_*jH z79r)`66UOFIK`-hvbe2l+KN)AR360FY^#%fOMPJ0jfp3)%?SbH)BP$v7>S6b3{>f@ zt0O$tjoB|?=caTB$6Rys)8Tps7tarPthSsT=XQL zsUL|X{lMpP8v=-KdKFnZ=agB9HuWi9P{yevf#jEb2HQkEIOHe$`7FujQcekRqm*9| zZOW@H$_7L`&3PP_`Ibz+!+%IP>0DX2aU~~VPQFtrY(mJ;!J}=`-vaBy=t1@KnR)eH zhS%MMZb-i6Y0{S&Z1l0SdWar^TYVlEGiV_ZSKG8%Q?MJY)v!*N_>22D)lYAmu``G{Ai<>w{MiR?fL>l?t%$VelAleqH4WbVc zs#hm-8B~xAC{~g!~(g*3h)yGWdDQborF`Q80ZBeJj&MP-b@m&?zQ{8A}h;xfGs_ZI>M&fW|+~;zkffr1}e@`jjA(d{tUQH zqEX`Fh&trD{*Tn;?<_AjEr&1;50|Sft(*;$0cP)pAOQqRt5+Bm)?T7a^F#UWXQYuZ ziw5*|!aOPQmDX|!qbP^+$R@$Wt7e>(BR2lZ5%8pQzzxH#{T&DqZu*{YrDA9K)U9qd}S1JiWBMPIJyy$bM&3 zSB!7g`Hcr5aS>h!B{4+&HXX~vHAepfrNXY97_b(lM`Jpa-s7xHP5%nN_Dx9k0r+R#W=0L;nnGK zm5K_<(@IaApV%<8pD!H_>Rq!KNVxSpp8MbB17Zo-8q~N*mtl0ZYF@)DYV_e7%=F*p z%cn}Qmx~C(;fXghM(*6}?7o?H%1RM4G%TbK^Qg|e2NQdWwOsbp?X7&(>sw-93)f<2JrvQexajgXQ~VN&epZor;U+>9Y?pCg z3SLX<3?CY9cAt}lED)ar;3fw%PmSLRh9gDwx-QD zhlJ{lo8sI7j{B9y=T7cTPW2$d{d%E=DgV{PDWq|eiPb+-Md51iUexz&WwMToHyPEY zsyNBHk0FiI0HD%->c_;t`t7UR|7!EwWT{@6lNH{{Pj?enZ`8${Rr~epC)`oRl>GKp zUB4!`{LcD!%UMn7hYm_@&S&6p8W zZ1C>wL%JKmk?X@~y^@VSzwTBYVx0>i&k8x!tTAz9o^EB~>yk6|gxgpej_em-iV*If zazcVkMPx;4t(>9@mC~Li&ghPz?U`j2b2a_WH}uop!9{*s-)72<_pT`;*OO<;qi1j9 zfnShHGfuoy{sXOO5s6iQ&ivG=7DpuWhb!q9sPutXrWnZS29$kLkpsB|1v8GH)t?NiDa?To_+|>Q0U%X&Z zWK^XV`p=9*{%|RZ@Y&Mo=ikM5hHnblA3jR@8rXT3rccjf@g`&6Fxorf688I|Y2mSb zWgq9S>c8qPL>YM0-T+q;>i^2k`mLQi&1K4_~iw6+zCJ zGQjd>Y7h5UWd|SLGj;**^nr&G7}&EvZ{AwT+Yk~X($eS!N@;xNN%Xp-AM-E!8X6nh zc#=?Q`jmCd-cF7=U1psJuAgHm2Z=iU5-&**iS$v*YNAexfYCYz<6ubf z>rOt~7EK?;SV|X>O;cZi()v6$E&N{&54fE|D&j^(GARBg+UrYWZ`WbYzJ=B;O1dNz zRbf*ZXGl>lD{!bLuW6hD=L^W~pA6Pvc2r@XDqyO2-X4A$%$Z=OtkAyhULwCf&X&G!td?THFrc1Mdf9YC2ojd(~y70*#*osFng>S}Eecz?1&Sc6K;dk~$TYJf= zD2Y5#YxTCdX;=eIYvo}aB!m(|iTFQmk!ojmjFmP|&sWKtE(xi8W$Yv(lR}pq+hY;_ z7Ofo!NG}w9(`pKRvt`UKGLlk~a-6)K%+@2gq`j26msDdh`9q~jr9`FtpiSF*cP5(S z?DO8oy(q7DfjWWar&r=Jl{`k)#>n}@+8&i9rlkh2D+Fj!NJZaIAsqsXal~AL@i*8v za+y1VOx(DBe?iaQE=Jmdvuv7LI_XH5Mc7}&UuYraMi1u__mWh2x2>ERqe*zbttr%0 zoQvn$*xZwbWW8&hb8-QU*5Pe)GAB%zHHQ9?{+H>d#^@XDoACtu$0eDjP^o13cara( zypt~Es+4*sX9@mp-!SlI?0rjKMqXoHL|*Y;*17bh3Dhvc+NL-$Zef~yP2#p$=S19t|u1&0Nfg%CbPo3Vn)ozb0X zlW~)YmywrAo?D4iNdzNwCpkXFfYFN4ifM*%hDntX#Sz5iA$uS_?bI;yJ~9t=uWP7l zXkutE0lW&~u;p<1ZNw+fD9tFxD8*>3W~?T&$W71qDZ(z|z6K(%LvmX3m*lWykK~jj zR&rc&;C;!wc>7GmZjVy?)%F+d58EBuS=-;WKWX=AXKYuENRKd&2xh8f@@DjA+GpHn zVqj!oie^0KWam!h*pe5O6_pW{SFts-Gjla_3>d1Os>W82?RKUW@=(=VhUyqW;$n#=j4;$kXNw_7=Hir{m}d0JIV8|?RM=l z5zb75oN*l4^3ApZf8LMoB+fgwi$nk;Oqr@Ut>t;-GbNkt0!H2s@1)MVw<|{&Mffvq zbI!_V%7xgT4DEcK2ev-Q!g9yTbHX`fVqeGh$CzW?fZjj`pdL^J z2nKQk0YGJ7Fpv(Yz0i-<#|~h{v6a-==N6U^3y4vTMR5glLS$w=n%i;sZ@>-U26)4{ zPxeTjS(5q5GAA7;9d{&0B-ef{E%y0>B=9Q&XJ*gi!DGkc%Hzo6&I9BD^Efw;1f=bH zECeiEU3jtZaKT}Lb>ZE@lLemz#syVuI@TN;99tXf9pfFlAG06J5W^4~9dpcihdYg9 zTV7mNTt-}8&DPS+($&&2WT;`P0oyQslHi%;+2R@QS>T!ES?d|?S+;ApAh+PR@BphF ztDKzFLx;`6T486fs@N86D7Gsmp8J?PM^epI#a6{d#UZ5Uq;4} zn+oKj^Q3H7et~vj8yk()6YO-5K`R4{=Dl>1~p>eP5M-nMy)9s8IK$mgNoOSxr#H2EsCd# zm5LjSg9Q7Nopj|pUwIn+O1Ap}0oj6FKn@_c#x|dVH9@1>M#ZJ2rRhSw$?hNzkR8Ys zpSgm<>WPncxb(xYAr6wepm?2#UMIr4bKWrSnI zY(!xstGMZvKO74e{3e(om@Wt}{zm=c>BVrTZ(CCRPx_^2z!~ltzzlGPa|Xo1*22ZY zp>ePdSJ&Z#aV>RCcSWyV9-$x69T6T0FCHtFEv_$)d_{ake9ire`!)O({59Ye;57>z znT~|>NvVRS?513&9H-o;fK%Wp=b*lW23O45jgh2cn&R+cjpCA525@G0wv;M3XuzlA zpm~jUB)YhuIPH}L+**oPrUew#f6%zru=ej7(+IpcsTlPN0-u%2l5PP94IZ?v)veKt zL>9-t;)knAg@Vrd4$x~1BWcA|ubf}mz+0t4!Ajt>frFMcx)H^Z_~M*b>hJ+LREh*T z>-T9pXj;o(OEj0_?$fI6c9R42nbh{X$t(B$m~{0^pK*$x1Rtf7mctZXnA6*rKP!U7 zf#P6&sWh21c~eQ#C#KRR8C6oIayH;f`_=)=v5*#Y2D%X)fi6a;qLJu0bR|05T&5&_ zq+iN=I#bg58xhX^jru-F=Y~Th2`;VO(;bP;q)*0G&(GZ9^y|JIPOtT!mtg&3uX8>n`=SZo8p#vcu7tN=%`_an<%V~WQa2qLp z84L*8f6;i_aQg2l(>{DTX&KcAffJ;1q%mOV;6>|c-6_p}72R!* zG!r$6?zcxNi2mqw^)#PmkM9KUnqQ=b3Ao%a|CRb#03-wy0_z}>Ym-s$s^8VUt0}ao zM7%>EkzkcjYSbf#YL$_$fCHS%A#z|+CuYTF)6+2#A*k#bpV$cmj#zO z7r>)>+6CP`+>z+&3UYPou5q9)y@i>Dg@w5VV9IRDV#<69pk$_G;eqt2@j?0^eCmB_ zeNYG0)Annw=&|8mFZhyQFK_B>Dvut&o{gTmUS$!+G0ZVnU{LzEG)}rhdNdItRLyD; zVIC#gnR=`Deed<&m%WdBU3xis&3YAjvr?Nx{Q+2jpqZeBpt&HR*o?YunHK|`%(f7H zb$vC{;B@zNU^+P6IUQndYwlw1fF7*D)pU4a97`S39nnjdd+B?1dxd+$Q^!(eQ|nVB zMTw$BF>X+V*wz|kpMn~3TV=9(sj~t(tQ#*37&Kg?AvQ_#4O$DO-iLn z4NuibEfF;UFaxp?D&W8Yua3RuCEDKT)PmGBQ3-%Gf~U3_6xhGlxYV%p?-EllJT)m5 zB?vr+iP0NUrIDaaFuJ7b%T%=N;stsrO^zCST(yvqIQ0N!CCHEz$|cODCv7vB%wpS(bZiMcRL{z85h1Bn1dz^(!Wd}W0QR%E}fEt(v5mjX@mx5rDXvK_JhgC}OH=oFN2)6r1a|7Jainhf7C4J3i%ARo6mDv2YH|usUB@X8 zq;HKc(ih=d?_2AOI;@_tC%QI`jraP&H~sLu$XO&0fFEE3PzO|2VBEvpbHxVbe#_zH zI^;%EAtKdmQxTIjp)wp#_bMwgS!LV0PZY!k4ZXU1nERKdXmejP{6o3!|7WC1eGO#*L?;H_-|1@|8{ZZ>TGyUB!y zBa@IQHwb zjV%!^#Vx5V$d?0$d9I04@htlHOq-5bPTUFkOM^6mK%$CT5e@ zU%=nWU)>*G-vD_Gd8vw4>rfk3Yf<~01(JTpISL(#S!&&6BfF9hk#)(Z$#&EYF7J^Q z$eEk9OW?8gF|lE>QLz!RvHaou(fpD8G2k$v6#X7uhIPz#&bG;R%m!wItgNlDna+@DEp-YQPi_3r|z;gOh`m))Q*)r=`BROf4b~AMI%4YtO0d=4D>{4~dAXH$>ULA#w z9J86XnY<)DW>qRs-rx|_vsXi@qJ&Y7kkdDlHY=AvW7yK{vIfT>^d5rpol?h&o1u9J{Fogq}UW2DYS5U>hz+n z+cS@6;JdDOJ@2}|Qi8kP^)_ED_)>+sHQ-jCmzGzP7m@cS??qlkUThvbFYAiOE5%QI z=XJ&tTx}H=lz9|*lz0?*lwDlM=c+pUS`y~%7VKs_+-;T9luZ>(l}r^)l}8mul|~gu zm6a5flw7<$-95cM-8{WKJv_nduH#?k=Boz!y4=#IyxaL=F|oWl0yN@be2Ajt= zFNM(OJI)WEZ#n-tfpFUOxKe~-G;eDxTf1xfp?2N&)9rTcT>yaLK}ys0P0`6E!5ZgDTa2%_PE$=UUg-Za-iGp!d8zP@@wr>?o?t? z0sTNh+TC)8TW^c5e}J(V8fF&hdBOMxU^{mkcy5L|=pKO`lPh|0tE=dYgW`ue)5~uQ zjBei%l_$(`D@wCuQF6U9f#sIy; zl@AG{_v$a#->SdrocpNg`oJTH7in)V8k-eJ4j4H&et0@+1NLzhQiQ+QwulctR!zT z58QW1FfD#j&^&N#LD%b>uD>P+idX zdf`{1WR{tSGQ=0I4bUxUcqRB{*W9zn#gs@HCKq-MFns1%xaReI=VgtlMIPKx;Pz1A z;=qvwZLg#nlZjjxLjj}8!m$CJ&pHEq3pc!yYs@C{Rt!mnafNX(@_^W9u>snJ%Ny}K z&vxGX-GgXDj375ubJa=^FA)X&hE}(&jI3_O6_ym06qdl+2iO+?3+W42HzYTlH~2Q5 z?Z9`kb`XB1luOjdICLrZD4LYJ6n%<0MT2sia!oZa@NHmTAS}zU;ZB2b&`orqdXaje zIt)Kx_1S6w`cj_++nT=7ita`6W>hfD6^vu10g_K z;1!?{&<1}51;~_FOjnS}yq?*UVS;i3dH|V$dO!)FBM<;I11bakfeb($d=Kgd3WbtF z!BH-#6%;?pEJHQ3QpsNt&5yJC$Ge+FNRB4rSi4V2Yg1Lt--woBL8@%bopMz(T;YvBCuN8h&X4{HE? zC8``n$iONGxn_Cn&Fyw>m#@{WapFr**bL5$24!g_>FVRj$cLV(=8uwFA9{_LdnY%) zuE~%}?pj{0s*}p@A~02jz~d#BqN{S@7vN>^$Q zh89D$Mb$;M4pj~{4%H5|3snm>3)Qm5X%Z709<3IP#t|?CEEtvpOMsOw(hog_r<-3l zPldmszO&-2aRsaz77lw2dk*^mdkT9C%Y@a#LScD}kBr5PfySK1#>Vo-U}M%HNq83A z%%a}Bvf2eaF}bk((QU(R!)wE1re>#>zKXtP)jZTZ)Z&Wy6^m^+jd6}+3arC$N!;xS z_^Int&!_HBy`Q>0^?K?tF<;Z=Rq0sg7~+`gnCMvM80}c(nC4jH7_rDdq(5|as2)B7 zSAC}0&j(jz{$^#z+b~3!e`(N<`U)-7BF*GaXkyzbMkYLg`>Hn z1#9(S^R)fcNT)>fQevoNz@t*xl8sO5K4T^OAlogbYUT^^kpg`EX2d#KL( zjeo#yge_hjIxuv3=+w|1c)kVH0$r8mrHWVj;)mG?S=1W3HKYemwkWBJt+w>4pY@yY zGB+V8P5L!&yjgs;C^<9+2b<@c6KXIX^#rBmoyLuvMWLZ~xPf_gjhY8!Wv6N5^`gYX z*u^J{jzjVvH6A7`nhlu@f#C!T^(s_#peJQ|XT%G$5wmDK1cEceu@;;b$>Y&uxQjK{ zUCPJ4RMa@T)Q(LWP28yLTK4uIx2!}jgBivzgFE=Vb;fUjxxpsjXzF*ot~R7Lw>D9E z0P?i9jBE<#AbG76tt?Iqj1Nr6jmu4Z82>QgHSRUBF`lN}lerRGJ+%_1+-!lJXq@Ps z=$IIWgp##M*H=VW^uc$iQ$8=0$0o)nnkGI?e4H4aXqyl&X zZLey##k7=nauu{zr%IOok5JLVpNf;eX5c1FAi$6RORS zIR7{PFUXc8ClW8ooTNeuAkmOCNP;BDO6!Wq3VA|rqHDZsg0;%H%DBe3TEMf!yTq-; zOMTiBZ%M%5Fmsq`%o64cW+8C6zNdbI5=p*AVj{5L-KR;6U7ERp5~X~O$|8EURgz1i>d=E z1FCW=a;hIxKB#)Bc&Tovq>1$;twi~L$qEx|zJu*=?CjfWB+J>TmN7`svpyj?Cw=WF};qJ>r0GfG_ZtXeTr;b-l6* zIsi?B)<6rQAz7_iB3WcrJ=HFiE>%_^BOfDivIiaRX~0>{4lF^%f9U%AJ^b` zRWv!PKZ{jGz)x*8U}?K$tq?DR#%D>ZSotAVGrk5aZ?~N7JDRSut69maUFNo_f)e5y!8l^%qMf7Kufc`9m{a{;HNGL--AUTFguN z=_CF^n1aeDmBsR{)VU>$8PcrJtTTO~zRhgJ|7~S7NeN^~*uXeo7BD=RG>j=`6r+Tx z!T4GBq|aU_wbi+Sn$joV5}a|)bI#MwOZ7aH!O*l%p2|`phn$7XeO0J&p*Q;x;7pfDg&#TL;x2dzKpQ;1<5mqtF ze1uF~=3M4<=2GUD%!SO^%$3Z^`gY}hVPyB3?&dz((eC}3@51)$e4Z%Yn_0f`fA`3rG;Ebk|E$R z(sfpT4XasS1D7dn5pB9ss{2tT!+51p@E^E zp^2epa7;-)!N^J)>x>wKfVcd}?g5Yh2!s+)jo3pRKm;RHuqUzB*rV8+R)~^D<2k^r z#3~2*T0k>IC_o637mx?B39x}o1%P)}RwtGLgmhf`T>3P1H2)=iA$>M|C4I8CUA|ww z3tR%K0L6mfpezsq6b#A%B@ooG53p=l3gR{5Az}u>5FimC0f7au?ii5=w+46kSKqF^ zB{>tF*PU0LH=VyaZ>TPf&5o`3w~z`zP*6T78B__11C@ZX3Fom>2ns?hz+i`Ei)Dvp zJ8M;SS$WC7jZ{of#2&-0Avgo1cVc%eSL>JjTfyC=B7z)t5ix~eN5}_&cBrpmS*>68 zZwG%Q!3nBZGNK>B8X&NvwhCDyw~z`6GFUu9I>2fNv6}f6vP^Cxy(JVAl(8g)Kma~K zeJ600vZPEPw~}B4c`O~4fQUip1-62S0E%eC2WreXqTJ>3VW-m0fS&am}ZHV4i3NqZ^*mKxh*yGtt+cVu8 z-Ba4D+4BqR$(}VJwePwGHDynh5I{K49B3M})PM}i+ZPRD4|>y3*pRB;mAwpF0ZoGD zK{KFb&=hD9ga;7_IKo`R2(}YDf^EePV0*9=*yf;^hWve_AnASQy)g=S%b)DA3)zKG zD7)2rdwU1=g7;MRPwrdqAKkwhglK5AniH6nUgad~?KV?{c7-T;yLl9wT^q{OE_jEq zid_~UWaF~uvZu3`vcF_6WY1==WKTA_a5%e>@n<0>`G8zyR19LlW({>vs04`m*{`P}_d-zT*C|{k1*LUFn^; z9jn!brJ&ZJ?){>Dx&6hxsXg{R`CZVC!47t{VL7Nh=;J@;+%#U>Couz7w>%zobssZ{3IO%kR_e6ZT^E z^bUwvAL62Y^H|ZE@g8l(V^!Rtf&;)t4p#=11E5AuA_GmZ^~vLh7zBguUh2PeIw^8f z>ZaPwQ#a4wJQL4TC3;iQ)%oQ$T+O9{#*JWy;DunG;Iv@V;L%{E;F@5+1CsG4bXi+y zzFrcHKUN@Mchru{?zkOq)hSmS+?z{Dmma;ee`#`3BA(BV-|md>S zVD9J~SCwM#nO?VZK-}P^l1As?Fmy2Z!c{jWG_D16(n!iB%bT*ZklxcWwNaDOl>jR3tGQvmOlFwq`Y z-iQyDrm><&Fl8_X@NJ0_opDaM+C~y}k7GQII(;D1F0X>XmI%=iSJ@ceNC=Jz*1IfX zcZetS%}Yf)M$^!Wm#TAziY^0tIXoFuFN1nH*BNM$*5{5NW)MQ!z0-f^bWY@+)IGI( zr|zAGCxq#$BrXfv{qevxW4btzjWXcJB*0zwZ)`BU= ziUpjGI&nE2cjB!(XKn5f0a4&H< zTs*GVI`G}edtAIH&N7`~&~cArc`H zp|B8EdSiy6gG2NJOw{odtIJImacBr2G(99e)GWj-l$D{9u9883QH^K(*f{q%$2i|O z`#4~nGvMr&k82Py3YUbWMTR1;AoD{E7+4vy8Pxy*Qa-|40mN`z3^EUy93stN#mLW$ z;0ci2@+0~XHHlAg>BuBxWeA7?%b3N400c;H1rj}pq10Wfsawu4s51ug?4I57CC1>A zktHF(5G#fT#z24yU{`7jLWJU~adF7(5OoGLLlEO0&#t7;sV#rv1LAF6MsAI^_%pUF zCK`kBlD4dh8V()Y?&0I73_1X-;k!APPIEDZH|6M_<`HKX2V7%(&itI!@Q~qQL#Ede za7IHG3qTQDjnrK^Pe_4jfnR}k!J`7B0`Gzw1ug}ay3DV`KV2!ksq*a5!>|P?PZ&=G zPdE?M<>dI(K}nueK1n1-7|N5e)VM#D#;N?}S7E-YS5UMyaW zUPru`y;wI6O|UI+*T{XA@HCs-?B&bB?ZZ22d7g7NaV_Ps&qxJzy@pHzp@9Cs{)pYRSmQT+ibtx$ZaT zGp9NCv^PB`DW_5c1jR6BGSvh8q}K!IJm*4tp*e9H0#G$Z2+z*hb>F#|-sGGT4WNb< z6u}4qC;@h))**Ay-s;}CoNNtsC<+?LNa5L$^gOlhKlfnn_B}>GQ`@^UPAq0kgYP7r zSe2U`hPl1NC+-^z12)4cla~~@Si+kpbrpD|*rfnB7?YWkS&a`FA2w#nk0@a@X0Zam z*$`6ZasiMk(<;9z?W#vrMpfQbH>zB!EblSrhxa#^x~gOx0){O@0bzg$KsW#jI)vpy zoEaC+;CA70Ie}sVLersUVP+9#;bzdWu(61-@G+=zm~sS&1fywxI}>2)+Ui}5;K|Mn(c~pZE$s|3i7$+W33>qa#}?}MOZ~PLqO^fX9P4nrm1x@ zkw_#)5<7?m#5rOLahO;|%$%%k0z=!OVqsztV&P)Y{IL9p{P27zFpR*6K8$9<00>Q8?Y5ljG4@vOm32fS}_VRH}C{X?)q){Y-w&iC8kd%O;$F6pjgIi zrUpQu^lspm=T<27HAHbu0#J3vAfCOmyS`g7#N^46CSa2lw1F`Qpa$5J+J$UEiPglo z$?PU|C>k2XxX-gE8E|UXf9t{4ZOtey!M4aV4`S~L4n|5oh*J=BXyJC#8b4;x0{E)6 zn{Y{(i&3j7L06dP4Eq_t)u?AN&*JVz-hFa6`js|3>Taw#ppdOv>b9IaS+pZO%5$ZgMKf1)$m zRwqrzRMS-3RLfLnRC82&RBKd6NmEJNCDt?AGuAW8^QmWyXWV+^INLmTwcIBOceClu z4!#6TLWXX(E>^ce*X31^?Il}lVd)E}FDP6Pz95?@a3=D&c7#^6U~58R2eBivqobps zW3D5mW4NQLBQv2^5UkUtBdRH?EvhA|^G5TH_8YA?I*&A0qPm}SM~?$i`BK?a0jZp+ z0wzaIxJ-^$OP48>3A+c`+S{7g`c4OTM0b4bDC!7J7)X#y_>ce?jc|`}jPQ-Hj{rtEeb27?*al5UbtEOwCWIzjNyry8&|%TZ zic$giO1TTK226){#3bY;BnwLGSVr;2)baRAuKG>;OlwX*?MP2ZN~jbB>0qKVqU!*@ z(yM{fp3|Wn(1bWa0Ufod0G{o$tG?4Q9mxqLf!5T3qjq_=CEZW0`cFTYzI``}C%3KOj6h$h+nLAtL{Ic1opc>D zO*3sXEi;`l%`xpUtuY;CO=WFRtar3`tap_6Q|}n>xXnlm+cI~(+^B?~+4|-jUmvC~ z!!FwnYu8}s@;=D(lBcz-w9;wnzZHd*WYYvBBTr~UwPJEx`x57fbCGi$a|LsAb18Gf zb5(PheYLq@opv2DO)+gTEis*Z&3x^At$ZDzCLs#-1Qm?|Wb$RQX96-gGX*S;T5wq$ zua~Y-s1f!H^0fCf@$_8}o{OIQI9D_m+BeWA*Y}|hn!A|0mt;F#c>V4na?a6-=R_;?1bN6jVm(e{P*UFpluHPB(z$&OM3K&1SH zcLLVK=VJQu`jT^{b*!TJV-P$L$sNCSpLNakr*r9jNqv>MARTN}miuv%G`B*HtF;S4 z(!=fsHa8@|?8f{++DQIsuqIqir(yU4GyU;tJWIvQGt11Lomq|zKDGDz@#D8p2;-H3 zN7SVc?mL@3J<_+xdv1a)0=PLoP3{W1RJmPNRp?Ir!w3& zF?&9JWIoxkr(e3lDEDfX-KV0vNp-jTKd_;EUmM%N2HWZ`qXv!dAFgpHIC#jxkU@T2 zH=m`as|$-YSXo**j%6U4_1xcHS&xA&4^Se^H>{n_9A2K*0> z2F%50Op2_8z_N=ouPGjX?mp)!2hD{kdWz57yz4h_u2gidK|$H-VcQp2_wbB^y@;{i z;%)IauRaS}BuYtMt$FWQs0U51c@MLbGk?EeS~TEFc`$GKELpwrf{ICP?cUYqNn`bq zn&?GnmvKKuyh5m?reUUt+-JPqxx_Y_nsGyYo8oxk)V@XM-Em7<1QW@rwSf&|02j z=}pMQ-FN9s-gl5L;=|YJYJVk0W3IPidRj0&2OCmx^6a~hLa_S8bjCm#BuI4Yk0P3F z_bl??$xiG#A<;i&OI07V=8e@aHFTI=MxR)B`fWBFf-&z+XZG{B43e7b(IU_0LOl8q z)i`<3%SWQX#7}W5_&77ON8a;tVwIlo#hWU^`99Y35ae@zi)+-aB-{t4(?o|ntJ|h| zk{vbR-0p9shv?mVo;lvBzL@0r!n}OO)ZwY@b)p<{=%5vQz)z&h)eGSVmqILD_B+IW zJ;km`lU+3JTwmDLv~yS4MeUn}ucy3XOp?8yD60Rdh0Xp!lx(SH8ZMtP@RzIxm(Lvd zOXk;va#9nntn!JkJ4!RJanj<@E9PL&Q}I#cE2sk5h2%2h~Nl z&LiU(1NDhEAp-2XRk(IKb*U{kWE^v#IdLjPfb-9!Fr3&y^;27nNP|Ox8btPx?4!GX zA{|DekM92KEWm{RRp*71*Iyj4FFUN8^zc&JS=vvw-0`Aak7fU*>uoTu%bi-5*1n8a zH))1imf@4FBDHL=tO?7j&R@GsX_4sTyZXpvk;`dk89&)xjThAmku_m^)tN}G;Glh( zux`??UGMe3#lH!W?xIGWc-2`(jiR$JJ4xWpiFYRgS0sPFx@{&c-Z8>_v6kV)@xz1r?T_F*&(93Kad#FSI$Qmy z>%(XI`NSLjBAIXWl&&Xxrb*4qT70svdDZWE{hr;%%;+U}i1bxii$uE`;Xco+)ThBU z`$eMO=&@Zl(DO)mwZ7liC2{Sl==Eg%G^tcsiwpKOwx2vZU(F|8?H5UUqxa7pSyEf` zA<|K@7Hsx4!k;{^Qj6*KizK|!6TF_RnI`r39gNhfs15D)y!vcD@pQk)dpDYm!D+H zBt_`9=~`C;eW{C_Td9i+lhPDlxmw2tE_QTEpYG&KOi!NrD0LQPqX%oK04D4D!)U5K zytvYm$K#XLJnM_fNAKIMJpOcJPo-v`u`AamHGTHQ^gYw*ca3L7v_;ueJPgwGaV9l~ zr%@RP-@orXbGEy*qKA7l-zv6r!qtX6*~agC@xJv^3UER8UE?Q3P-8Feo#c$ki}!67 z6waYPKlxOufF4*77qy&s-8SjjZvFv24jVw#7kgtKez?-Suk!xx8Ax5V!R^8WS6`o{ zxI>>!4{N^g)xZ7P)+P#m`*zC1ckoX~EneRS$T~mj7I5Kx4wN`O&~=x3GSiH^*UINO z?=aRdA_|Yz@7(rze_Z&;O3mmXrXgouylT{}xn$D_DS#1weX3JfmHK>1K5V4blr1Sy z|5N#cM+$aEklmS!QCCI`-gE_Cu-HtRFU!_Xrr6djiS>(oeWmy1YH~}GRFs$nn?a3m zmgiNK`9z;jzj1g!n=i}LPu6@U6?NKz?N-gw>Hdd0sZz=xJx6Z6(aXJ-%=hrOnmp(3 zYzWqzn9dyNfdoly_2_-IDT6-gnL-3aupNvBRbp8ivrqHoTx2h{f2Ko%O~H|?LWhhq12#X%Ke2gJ(=>Spq}abIbyF` z{)B&7)sIE~{}4v#Jio1~C<^FIaT2yEOL)?$ec>15>Pp-%b|U##{^|Xc|4XQv-v3|6 zeAV<%@Y$IOY`U}RY5xB$+|5`22siW9|9!ZcuTr7+Pf$1iusSzxI=Sl4kyJHJMd%;l zGdT0L$$0g$`G0`f?W*oIw^aPp1$6tvEb5y$)8e<~POUj;%npQg=QF0VvR^=p*sAGu zsJw{xJ$q{Hp2loxSho%1NV~ADKvFzJUt{z9Um3IQVcl_zsRHa5)J1Ir^*eS`;sk$w6YfKoGIT=ylX3$NNg3TC>!ctq<$=XH5O>c#u33ZTZgvzLi7>pIWof*yLnP zMYCPV{@&1l7xCNFhMH*1mWOo%zd541+`}7wq`$=YN}O7|tugyLtXq#UHJR;#w1}=)w1Z2!`cb)&;i?bPB{Sa&mHDwgd+gNSXQUdQf>DwPJghHd7Kg)%ZDfQ& zwz`;(__~BszCu?vMYzkPJC6o(C+b|VwMy(;Dy!44zWCfxrutE*oEiM}&Lds^kMSzc zPWhg`vU)ROI_Geo`cI_u3U?y(f-vjD-$(qVVj(Cbr#Fpfh-4~|< zyN)(IjKp4O0darHf6^70NYSn+zEl1%u;az{DYMydr&NZrhx{Ec2wkS3xh<(TRH|$z*2i*~xT~fbuZV3t|r&!la2*7F71#`1RQNmr?W|*td=q zT?2KX{QKV4PvR%+Wm!dh?{vnMBoCJBD8*kJ^0JE9-sylVNoz;0qyDbpK`kREt2op< zZBDKFzhTJ8Dx!O*RjAE5d>!?l80Tdb+k2;Zsm-BQ@UyYTd>th%tJu&xy{nP*|BV0M zH7MzwuA|n*bR8ujtN4G}I3uf=PyLc>BzaJq^KTiF-iqqqZyGDV8#$ed;iCBCX&HCy z-2Y&NisBEaWysjMqh59@{-=gHoz*|<;*@4s*|`VibZ%3d!I}0ijcRJxiL?weJ9n3y z&c9)Bq-7Y}xm)IR`cf<4FsCzKE&KCxok*@bi|0zqu(5NGrCyu}(LXcxUUqI%uLo;d zhPs{m-!l%IYayn)s{RG4tEPVgpV=9=2b`TAZhr>%8!tPnAB#4~IIb#}i#F6ctk%M) z2lwZDWm4BVYIFnRW_Xfe9qi;TLUGzIs;HAtyl>?NV7T&`L01=0G`W;cv^_YG|Tw1X?B_YjW*yHgHR&89%a_iB~wv?j{U(yHI-c zZ5Fp`$J}LY)(d{|eW6cSY&}or(Q@;3%w5uExS$l@7yLV^E_;%4m;m%qZzgkN(8Rz9 zk_=TMAI1W=)S5}$2s9BAL68afo#ZlD^_l&b@NYFB3{nYqek}d_3fD>x?*q5goA0b z3NXaMXskH4ikynq^jZ?CgdaUPW$MfPv)pJL{?#$KlKS#5+*=wDhYzgLj1D7CH2SSX zjk&*TiYujwWpw7Xi7MI-ZnbYSyJC<^K0oH>h3+Dc(Dve+nw;Qckinh zavA)V(qYaLAKf=M=i=n_d4EnyifB(YLez+;q@)L|DmIguvuI-XRRuC?qZC?>E-qQ} zc+xdYT3zz*ITq0NFx<`LzIj{VFfS5lZp4+$@egG$6}aDB9yB|mo-VXSEugcul;^wI zr$V;Ng2)wx^shI|5!? zs`cHRP$9cy{UTq~A@(tEVpYf>kAnjB*6OHo0sKhZ+ETmk=G5#VHNV@v?3?%ilSRhG z8%t>4O}q-(!{cDKm)Pc_3fU`*qJ$321U8_`t?(lyYfD4E-{l_z2)lm!@N?KR#mXFm znM`ZhO*MD!PZYjexqA;R{-d^dBit+hn;cZ|Ztw2BAn{^#j=^lEMFTAgEul>MOSxEZ z{>$>6yZ0dC#cCWz*-S8l@PYiMg{0h-=o*OyctP#&31D$Ixkdl1CM@%}9tU_qb?$6* zn#6a4iT0CNcw11J`zJ))QDp)8*Y3YAIT&p!;qbQLL+&@SP+U-+i;7nIg%lMRlzJ}) zoKatZ6_n&6qIbmqb5h2XTO4v4cJiZmB$ami9sgkX+31#;mNUnX=fUzd}%-E=!LLEYVe|vPLmBddFa4tEEVPUDP)V<>U z$$S)RW^&Ahu({U(iw1 zbw61CARWSqjQK2dJMK{6LG=&;WE@V1D71BK_q(b7Sotqf`b8;AEcF59TGb#@>_yhB znZk^b3B}=Q`pD1fu0XQujaJD+jA74EPRoP|l{>Mlo4y*EY+l#i&+ATTFI>D`nNaie zv-3fpgZ2mQUrD6~T-df9J=ss6TJvbZLE|LN0Bq zlPKior@Z>B(;DoDuAh8%>2&Z-nw*2ZaHzNH`^6j!)@47tAw9KPh|hZu z|FuJDq@yLEOD>mO>_Q{hWS1X!fXOJyl}6}e)q_g_;*TlEhLz8MZum+&ztU!JDKr+M zN6C4}D(P=Ga;1yk^qUm;y=rV{C`@|rZD#1(^74#Kb0W=sOV%~Nl%eK2{@D!+C1qe~ zy~o;M-&WF1P6Bxl(A9s{Ydb2iQAVS*z>M^7BZVzu$-8fzZrZ`(Xq!HQ!b-gjjU_2(LI#_`jW&Q(E?s)tv8mQpI1-nMU-CH3-J$kbe`m~lH8mDv(%xHc+KxtTpu4s%@7Q`IYzL_CZ?zXuE1 zFTyp5Z*RaeA(l#C-BWDgy2k}?9lAHxJjy?~ z`R?MQ;t+0_b(>QA=BEvAXW-hbN@Kc7WChomE?u)rvp!`^S;Zk@FkGkj-=-dS9lLy6 zDi^r%gYxZQDY&%3PP=`PA*W)!$p%}O*d3`BrV=A0%#i57QD;i`d%9~n&9r>mE?J}Y zIFWgaZkHzTK*M9JMrj=9H#30F3TaH__~QY1Le>C^LQz+O55LdZQpr$NQYeHfA99Fy_bY&@bE}U!p zIr8U1_~8uI8o8iJP&d0u)=ipMX7MiO#?<%qAiWHY;4r9iCD>b@wJQIht~?wTvRH(x z5wC(X!C@XwXcT*OIzxLt;n>$Uup!ZmW7mkT!4L`h`xIY*uf+P-t*xu@kJjE;%*FV; zWx^DNR2Jdhiu=I+hg3-?Xw^A|yzsTyTqk)@9=7i+keS&~w#jfC%sDGnRZCI3T>?5Q zXMdVo=KMcCxT^)n@92PH1>Oj?x;E@Z+KShqi1>SweMokA)JnO^8{xwYL@SP6W4e7q zWRT(SDSp^8Ln099zj1}WJs&GUPgnJhNvb%68HQ^T|8LNbAH%&I_vh3I7mgmKr>QDq zf)|HKz;GYM{}olzAs!33Or%3{9<(|dU~W#wX^d<&bamtSQ<^EXbw~{k4}rmO3qO}^ z-|&jX32lYom_wuwAx{39#88AbOyVy_2D&-!r}Q~D^YU|=AhnEK6FAIm@mx`~=a1=p zNlb|fFW_XY$ksLho+!(&cz(L7i3$ELgt-_;BT?0ex`lol=EEPg#6O`}U#IP2r&v)E zvJA5(iw`51E|!G!z^ui@hohLhb3-5n)|^Vr=eOTQd~Q@eQrG{-tUo@&UYB-C_S}s> zW?f#dc-LK>1nJClCxNk<{Ci-7Q0Ayg;VAMdPz!$ZQ~uAFqzY>~Jxg?(@fj)P`-p zyVh&Oc$$`3H&gx0m14G=^h%QX5@G!uP4i5Xo~^tF(dWj|kN3L1GEMq~yVhwaSf1i7 zNtwFJxFb$`t!ZUlZ=YF9hzwt2thgQWo$@XojrBUzt`ug&*Hp?fc@OGZd_`gK)Ia3u>3i*& zj@t6&45|ZW!)NBdfkgt*FJtcC+UM|WD}-GUsFh!62t_G)dCg7XI`$C$o<5Eq zj{a_|`L9xmGEC1%)LblE{Ra?#a@Kfx2b3|{x=AF(l~L53 zT8K&|*x^ZN>UwGZfVS5u?mfqLXNZrl^H;r|i$UR?1Bg>HI$<{wn zkHbLlW){L*rEJ%h>LDP+1y@(o?7qqFUaTA(=zGwH|A>F6c|X znllORy!8ilN)&G&q<_s9`YHCZef!JfcxmLep6ec4M#DjTiQ=cjhp#FB;(c#(bM*Y_ zWv*x5-(}U$pUXddgUqEl?vv|>kGh^@=k1vN)m?i?P2#p{b7()%K)WFJX~ zatv7;<%OAJ$q^Xz6}I>)a-%5;TB!q$RB&;VwWZkEU?@JKdzzu z%=dET2QP*K<$qHeIq;F?ruXAA+Gl((mwtH2a9a7&AEk52%-u6I`@$!Q1~fDQe7MEN zyHe+#GwaXL+^PNn$e^IyIC22R;_CgloHm0Gw?vhylp6aE#Im@0KF*^x=f&ZEU|>*C zXha@hVR3bR97XyJa zasY9J==>N&8vwwK{eY$auSj(~xPc!^=zZiGVZo_}){i*uL74x|lQ=yF(y9P(BR`<& zeJ(bZAILgVyv8uNO}n@o?6ubzAbu{p$?5jF^yB(GbZc730Jqp_^s`gv9yUI^bYZJwIkzXuKcn3sJZK!AVH51s(C>ya_;6gUtT1?*81sOonxxebGJ0( z1o!vOmN5zRGl~vPIBG>HLMD(1IW~E>a zN8j5>7p;F!nq@pjiJmjoY!KYx=qrf~)LNIwwfdbjNGr4!)3Gafp&_zcT5#W5G8cTT zKBkyKo9ZBcPJk?QsCn7mKUa2+YeX_;>4laNy^us`!gFNDM{C=M=gKZ{nQ%W@x}&pM z_$}HH*->O|Yk00qoXdpcNimbQr!tkM8fY2O3Bf`VCh8&)I_s*rgkzAnIe$&8kX}fF z2(ly5+V<+X-2G#exVa$BeW4wJzWvBOoptp;NbVPnb#+qmf-O+lm4UX&6Soa;qy{gpXjkoMYZ?{p3l;KBKGglut2db zH6)2K>pIaX1jw$EjvG0M79Ex8%le(mzL zy(=M5@sqU9&dfhVTVCZ0v3%U^u}^Gt+De6{h7;TdI;tExw}3xmq@>^L=bovsR8;D{ zNTU^zsqDW%mdMmUfNdA~1|9wOgZ<}`p8Dtb*#91-{u!klSUZml&_5@@-rauiFKDS^ z2)d4e{X9}r|J*Tl{g#9OtCZTvwd36_2W8G9_4UuOv;RWV^B^qcV#t=O=N#F((+-x4 zB8#t{Gjk|^%8Z|j(r}8DEEU>px%8wZI3-fZ?P_<69Ne@U2PDdDaqk`uq*o8kMxuXf z{xp~HyQzhLn14FG@Lj~Vg)@3gg;l#XjVs)D$v7u}BLyJV{gi#S?LU;i+B{)QnhNW5 zYnoQL@1Ai^@kR=-n0_p~XggI_3@O1$Y%w8zIrQ%>wTf;&VD~SLsvmB#bbL@ES6Z1i zY<7L=wdm$;cK^bt`p+$K1|oq0;$NrkL{&l(kS@h04<}z+((C!hNYHM%P0jE@ws@(*^Wpq!OLs&z3)#qbqaXz> zYIh$9h?lZHABJ9AQWn|FWFy~*g5Rpqif(Ut1Co*^FZ&>qJrV6cerV0@ts6H$7gdtv6p%x7`;j z-A@|czq+(9ylKEj7K@@Jwd`GeU?p5CojA;Sbty)8Q;Ur(7)6P13DkXn6)XiM3|Hzd znF()7vXM_jL1J1ET0hIh&0>R-?2E)GudNoPU0ws0NN3%7xVQO6zVYO`c$VdneB+6M z&2{$Wd9l%cgZKH_b_VKw8G*Tq6ittvsM&S)o_Vq9b$0h1Mny_kMxe$G^+|(Y0nN+r zjJ1>tU5yjvs65&#sp-aiD=^)1yXVA=yxDtIiof1cr0V&jLT)ETzv!B?$&?-)$YsEW z5|AXEKT&myKY$hSJM*zLj(Lj)@#6vhSOUjXMf2m~NY!uBhD#&pw+Sil_X!h`{?XGi z6(P|Nez*hI$3CC`aG~Dl&Cthn(^O0Jd3NSLVycluzr#b*xB9T>_8YvN$=(9t0rvX| zn*#qb^A@ltCHx~JBzW`N<4Z;MU+kK#Iu{!2?MZG|PGb{;sAR)oNZ~UqkDpJ0nl|Pd z7yp|;V!<%m0cg^WJl97tD46&4jS2=W`%V%Xzm@;RE zV>I3!l{|bRF}$zo6V0L4kgS6s9}KZ>(zkgn0)GSz__p2EZw0RSZ>jiknW2)|>+=6n z=Eo92UH?r@IuotLmOo8A&5nml&eydO{|PZ|c05udS2sxfCq$`v@o~1<7mH^azAi8FG=id{$4uOmC0u~5%cd8U&wM);XJkGv zFL(DgLdCj!BSSbU%fEQjf9Adkyp(ys>l*=Gs^>t+*I|f$&Htyh>kVq^%A?)wSlVSV zc5R7;5vOZQxZo91 z0~A6?GN33Cfkhw@cu7o1NKM=q0>T4cUb3Ov&eXN*%+BoGbI&{X%=>WXcklglXYO$Z z$(|6^w)!o@S;gT4+fo~~b9-u!$`i!jTXSu3Z#3_a`{_mw?}E8PL!}+ew?t+I_Vs?yc#fGe8+`MmE%p0t zaG2LO`4^gP}(M1z?l(!WMO%6o=TnHNO* zPm*?;KW;`8TqKd8`r_&=qIb=EM6R$p*R0uVmtW8ub}s)L%)Hs0+aNVjO&+sxP++X2RQ3QPI6 zwcn&j@6o@+5u0;wk2@u&r^=6K?-j=QFQe%iwTgSfJb0T=AYeW(aIwNRH4G!S^+g>N z;fpqKre~(T!ReZqWGoXK)9(16sZi%0B-A-1Fq3|Dz4~ZjLmP1!y!wiOAvNBgm`YGh zOiabbsT3+zdnQ3k)y_ze?|R9#!qGUwwd#s1D+8siD+9%MimtbEN4@K64}3g7h*sVu zz}o^9-f;Wi zDQuleLM3o3!wy}nN~AY1#-K&>IRmCx0C>L&80^|cd0D}t!fB@+%Wqf6q=c)F)m?N_ zL87yDz_A?Xv;E>iiFzn0(OGh#i`5B{oRd_2==egiphzJ2t&PO}=i&LAwVA#gx9&h@ z>Z!GhyTanXStAomnw1EjfT@hZ=ql)%c7KXMCaSAl;2uc@aI2r|Qu%!qdQXKi*z_X@BnI+k=inlutI+J{0n=vB;7fPT?dkBPy?k z*&?ps$g>-m{>%oQmff&L@28eA?T4$>M!v+6J7}SEyK0zfMH5qfrFuE8UMBX_YK_A= z@=IjhnD$IuDh-$C%*tgzSw2{=p$U7BWodf^Z1U6{h00hP~pDI;abz7_^%qQSRTBLBKT+u#f%`4b?%As+;=x74faqJvwCl&!!B1Bz#T@X_>gH2#L)Dh%_Hc577aYES-OJ5YIu6VCuF}e;5{BE zR^^*9ZrCXgfnNw30`Fph6YiX@4V)0LgT>{$dER%!@}CW+Vw7D7jXnZ4yrf+6&- z1f=-J27*aMMN>&Vq7)p*s^|D zN$K|8y$w9RW0`gdEu+vhDiW^R~DvfXB`5<@yZLz8tD)Pn?Ibi9v1 zfh5u{%;2~unQdAMvSUq4ml4rC@wjn*QDt?>*lJeQI4gv7R`^GRT+X4Ybq>4wqpKq2Yu* zQKBTQyD<>8?c|Lu7?yVe6C8Uw@}WNMgk>0?#rAej@zCYITRY*EdC1`$ijvZcWbsa6 zMWl{|Hh3;aEBEoKvHG;A;psciC^@-Hp z9CloDWB{GxLp6o3(iJxP@ex%itEY|vWy2so)G$3iI4wrNNI14|w_wN`CLuk(KMh?J z^G~qx_2A~hlS$$5Y?}Ub5_dTk{zt7cT2YP-qoth%%VHPGZiCC(2IZq6GSm}0aZ1d0 zUx5A;$^Ftn_G;=35R_R%ZwdhkGgNW6tMIbG>@6Z`Ks(WndrpR!k9I KOwPKpd;bC>3tJ=r diff --git a/lib/combodo/tcpdf/fonts/dejavusansb.ctg.z b/lib/combodo/tcpdf/fonts/dejavusansb.ctg.z deleted file mode 100644 index 71cef637e83311b26f0d4325c39b137930335918..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10200 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,'FontBBox'=>'[-1069 -415 1975 1174]','ItalicAngle'=>0,'Ascent'=>928,'Descent'=>-236,'Leading'=>0,'CapHeight'=>729,'XHeight'=>547,'StemV'=>60,'StemH'=>26,'AvgWidth'=>573,'MaxWidth'=>2016,'MissingWidth'=>600); -$cbbox=array(0=>array(50,-177,550,705),33=>array(140,0,316,729),34=>array(95,458,426,729),35=>array(68,0,770,718),36=>array(78,-147,628,760),37=>array(32,-14,970,742),38=>array(60,-14,830,742),39=>array(95,458,211,729),40=>array(86,-132,377,759),41=>array(80,-132,371,759),42=>array(20,278,503,742),43=>array(106,0,732,627),44=>array(53,-142,278,189),45=>array(54,217,361,359),46=>array(102,0,278,189),47=>array(0,-93,365,729),48=>array(48,-14,648,742),49=>array(113,0,627,729),50=>array(79,0,609,742),51=>array(67,-14,616,742),52=>array(45,0,650,729),53=>array(77,-14,626,729),54=>array(62,-14,642,741),55=>array(67,0,616,729),56=>array(61,-14,634,742),57=>array(52,-14,632,741),58=>array(112,0,288,547),59=>array(63,-142,288,547),60=>array(106,30,732,597),61=>array(106,144,732,482),62=>array(106,30,732,597),63=>array(69,0,515,742),64=>array(66,-174,929,703),65=>array(5,0,769,729),66=>array(92,0,692,729),67=>array(50,-14,670,742),68=>array(92,0,778,729),69=>array(92,0,610,729),70=>array(92,0,599,729),71=>array(50,-14,747,742),72=>array(92,0,745,729),73=>array(92,0,280,729),74=>array(-56,-200,280,729),75=>array(92,0,805,729),76=>array(92,0,610,729),77=>array(92,0,903,729),78=>array(92,0,745,729),79=>array(50,-14,800,742),80=>array(92,0,692,729),81=>array(50,-146,800,742),82=>array(92,0,750,729),83=>array(72,-14,647,742),84=>array(5,0,677,729),85=>array(92,-14,720,729),86=>array(5,0,769,729),87=>array(30,0,1072,729),88=>array(19,0,751,729),89=>array(-10,0,734,729),90=>array(45,0,680,729),91=>array(86,-132,389,760),92=>array(0,-93,365,729),93=>array(68,-132,371,760),94=>array(101,457,737,729),95=>array(0,-236,500,-143),96=>array(46,616,322,800),97=>array(43,-14,596,560),98=>array(84,-14,671,760),99=>array(43,-14,526,560),100=>array(45,-14,632,760),101=>array(43,-14,630,560),102=>array(19,0,444,760),103=>array(45,-216,632,559),104=>array(84,0,634,760),105=>array(84,0,259,760),106=>array(-33,-216,259,760),107=>array(84,0,684,760),108=>array(84,0,259,760),109=>array(83,0,963,560),110=>array(84,0,634,560),111=>array(43,-14,644,560),112=>array(84,-208,671,560),113=>array(45,-208,632,559),114=>array(84,0,490,560),115=>array(52,-14,548,560),116=>array(13,0,455,702),117=>array(78,-14,628,547),118=>array(15,0,637,547),119=>array(35,0,889,547),120=>array(15,0,630,547),121=>array(12,-216,634,547),122=>array(45,0,534,547),123=>array(125,-163,587,760),124=>array(127,-236,238,764),125=>array(125,-163,587,760),126=>array(106,212,732,415),161=>array(140,0,316,729),162=>array(85,-153,567,699),163=>array(61,0,613,742),164=>array(36,30,601,596),165=>array(12,0,684,729),166=>array(127,-171,238,699),167=>array(7,-95,496,742),168=>array(96,654,404,774),169=>array(138,0,862,725),170=>array(77,182,489,742),171=>array(77,67,552,519),172=>array(106,140,732,444),173=>array(54,217,361,359),174=>array(138,0,862,725),175=>array(96,668,404,760),176=>array(87,424,412,749),177=>array(106,0,732,627),178=>array(53,326,382,742),179=>array(44,319,384,742),180=>array(178,616,454,800),181=>array(85,-209,704,547),182=>array(63,-96,549,729),183=>array(102,253,278,442),184=>array(128,-196,349,0),185=>array(60,326,382,734),186=>array(57,182,507,742),187=>array(94,67,569,519),188=>array(49,-14,957,742),189=>array(49,-14,987,742),190=>array(51,-14,957,742),191=>array(69,-14,515,729),192=>array(5,0,769,927),193=>array(5,0,769,927),194=>array(5,0,769,927),195=>array(5,0,769,931),196=>array(5,0,769,927),197=>array(5,0,769,928),198=>array(0,0,1012,729),199=>array(50,-196,670,742),200=>array(92,0,610,927),201=>array(92,0,610,927),202=>array(92,0,610,927),203=>array(92,0,610,927),204=>array(11,0,280,927),205=>array(92,0,337,927),206=>array(1,0,370,927),207=>array(32,0,339,927),208=>array(16,0,787,729),209=>array(92,0,745,928),210=>array(50,-14,800,927),211=>array(50,-14,800,927),212=>array(50,-14,800,927),213=>array(50,-14,800,928),214=>array(50,-14,800,927),215=>array(125,20,713,607),216=>array(22,-36,823,765),217=>array(92,-14,720,927),218=>array(92,-14,720,927),219=>array(92,-14,720,927),220=>array(92,-14,720,927),221=>array(-10,0,734,927),222=>array(92,0,692,729),223=>array(84,-14,676,760),224=>array(43,-14,596,800),225=>array(43,-14,596,800),226=>array(43,-14,596,800),227=>array(43,-14,596,778),228=>array(43,-14,596,774),229=>array(43,-14,596,888),230=>array(43,-14,1000,560),231=>array(43,-196,526,560),232=>array(43,-14,630,800),233=>array(43,-14,630,800),234=>array(43,-14,630,800),235=>array(43,-14,630,774),236=>array(-21,0,259,800),237=>array(84,0,387,800),238=>array(-13,0,355,800),239=>array(17,0,325,774),240=>array(43,-14,644,760),241=>array(84,0,634,778),242=>array(43,-14,644,800),243=>array(43,-14,644,800),244=>array(43,-14,644,800),245=>array(43,-14,644,778),246=>array(43,-14,644,774),247=>array(106,42,732,585),248=>array(38,-46,645,594),249=>array(78,-14,628,800),250=>array(78,-14,628,800),251=>array(78,-14,628,800),252=>array(78,-14,628,774),253=>array(12,-216,634,800),254=>array(84,-208,671,760),255=>array(12,-216,634,774),256=>array(5,0,769,914),257=>array(43,-14,596,763),258=>array(5,0,769,935),259=>array(43,-14,596,780),260=>array(5,-196,769,729),261=>array(43,-196,596,560),262=>array(50,-14,670,927),263=>array(43,-14,557,800),264=>array(50,-14,670,927),265=>array(43,-14,542,800),266=>array(50,-14,670,927),267=>array(43,-14,526,760),268=>array(50,-14,670,927),269=>array(43,-14,537,800),270=>array(92,0,778,927),271=>array(45,-14,871,760),272=>array(16,0,787,729),273=>array(45,-14,707,760),274=>array(92,0,610,914),275=>array(43,-14,630,763),276=>array(92,0,610,927),277=>array(43,-14,630,784),278=>array(92,0,610,927),279=>array(43,-14,630,760),280=>array(92,-196,610,729),281=>array(43,-196,630,560),282=>array(92,0,610,927),283=>array(43,-14,630,800),284=>array(50,-14,747,927),285=>array(45,-216,632,800),286=>array(50,-14,747,927),287=>array(45,-216,632,784),288=>array(50,-14,747,927),289=>array(45,-216,632,760),290=>array(50,-224,747,742),291=>array(45,-216,632,765),292=>array(92,0,745,927),293=>array(-9,0,634,927),294=>array(92,0,882,729),295=>array(81,0,709,760),296=>array(16,0,355,928),297=>array(1,0,341,778),298=>array(32,0,339,914),299=>array(18,0,325,763),300=>array(21,0,350,927),301=>array(7,0,335,784),302=>array(92,-196,366,729),303=>array(84,-196,345,760),304=>array(92,0,280,927),305=>array(84,0,259,547),306=>array(92,-200,651,729),307=>array(84,-216,602,760),308=>array(-56,-200,370,927),309=>array(-33,-216,355,800),310=>array(92,-209,805,729),311=>array(84,-209,684,760),312=>array(84,0,684,547),313=>array(92,0,610,928),314=>array(84,0,357,928),315=>array(92,-209,610,729),316=>array(71,-209,273,760),317=>array(92,0,610,729),318=>array(84,0,479,760),319=>array(92,0,610,729),320=>array(84,0,484,760),321=>array(-45,0,615,729),322=>array(-18,0,390,760),323=>array(92,0,745,928),324=>array(84,0,634,803),325=>array(92,-209,745,729),326=>array(84,-209,634,560),327=>array(92,0,745,927),328=>array(84,0,634,800),329=>array(51,0,891,729),330=>array(84,-200,730,742),331=>array(84,-216,634,560),332=>array(50,-14,800,914),333=>array(43,-14,644,763),334=>array(50,-14,800,927),335=>array(43,-14,644,787),336=>array(50,-14,800,927),337=>array(43,-14,644,800),338=>array(50,-1,1094,730),339=>array(43,-14,1046,560),340=>array(92,0,750,928),341=>array(84,0,515,803),342=>array(92,-209,750,729),343=>array(71,-209,490,560),344=>array(92,0,750,927),345=>array(84,0,490,800),346=>array(72,-14,647,928),347=>array(52,-14,548,803),348=>array(72,-14,647,927),349=>array(52,-14,548,800),350=>array(72,-196,647,742),351=>array(52,-196,548,560),352=>array(72,-14,647,927),353=>array(52,-14,548,800),354=>array(5,-196,677,729),355=>array(13,-196,455,702),356=>array(5,0,677,930),357=>array(13,0,507,814),358=>array(5,0,677,729),359=>array(13,0,455,702),360=>array(92,-14,720,928),361=>array(78,-14,628,778),362=>array(92,-14,720,914),363=>array(78,-14,628,763),364=>array(92,-14,720,927),365=>array(78,-14,628,784),366=>array(92,-14,720,929),367=>array(78,-14,628,881),368=>array(92,-14,720,927),369=>array(78,-14,628,800),370=>array(92,-196,720,729),371=>array(78,-196,716,547),372=>array(30,0,1072,931),373=>array(35,0,889,800),374=>array(-10,0,734,931),375=>array(12,-216,634,800),376=>array(-10,0,734,927),377=>array(45,0,680,928),378=>array(45,0,534,803),379=>array(45,0,680,929),380=>array(45,0,534,760),381=>array(45,0,680,927),382=>array(45,0,534,800),383=>array(19,0,444,760),384=>array(9,-14,671,760),385=>array(-68,0,741,729),386=>array(92,0,692,729),387=>array(84,-14,671,760),388=>array(40,0,731,729),389=>array(25,-14,696,760),390=>array(50,-14,670,742),391=>array(50,-14,818,924),392=>array(43,-14,643,724),393=>array(16,0,787,729),394=>array(-68,0,827,729),395=>array(70,0,669,729),396=>array(45,-14,632,760),397=>array(43,-222,645,560),398=>array(92,0,610,729),399=>array(51,-14,800,742),400=>array(67,-14,616,742),401=>array(-56,-200,599,729),402=>array(-57,-208,444,760),403=>array(50,-14,868,924),404=>array(2,-211,793,730),405=>array(84,0,1000,760),406=>array(92,0,428,729),407=>array(5,0,384,729),408=>array(92,0,805,742),409=>array(84,0,684,760),410=>array(5,0,355,760),411=>array(-11,0,562,760),412=>array(83,-13,963,729),413=>array(-56,-200,745,729),414=>array(84,-208,634,560),415=>array(50,-14,800,742),416=>array(53,-14,854,761),417=>array(46,-14,708,609),418=>array(50,-14,1007,742),419=>array(43,-216,826,560),420=>array(-68,0,741,729),421=>array(84,-208,671,760),422=>array(92,-146,760,729),423=>array(26,-14,601,742),424=>array(15,-14,511,560),425=>array(92,0,610,729),426=>array(-31,-217,561,760),427=>array(13,-216,455,702),428=>array(15,0,701,729),429=>array(13,0,455,760),430=>array(5,-200,677,729),431=>array(91,-14,833,761),432=>array(75,-14,733,609),433=>array(27,-14,823,728),434=>array(92,0,772,729),435=>array(-10,0,796,742),436=>array(12,-216,778,560),437=>array(45,0,680,729),438=>array(45,0,534,547),439=>array(72,-33,728,729),440=>array(41,-33,696,729),441=>array(37,-215,586,547),442=>array(57,-208,534,547),443=>array(79,0,609,742),444=>array(41,-33,728,729),445=>array(37,-215,586,547),446=>array(36,-15,525,702),447=>array(84,-208,671,560),448=>array(92,-208,280,729),449=>array(92,-208,566,729),450=>array(5,-208,536,729),451=>array(99,0,274,729),452=>array(92,0,1510,927),453=>array(92,0,1364,800),454=>array(45,-14,1250,800),455=>array(92,-200,917,729),456=>array(92,-216,896,760),457=>array(84,-216,602,760),458=>array(92,-200,1117,729),459=>array(92,-216,1096,760),460=>array(84,-216,971,760),461=>array(5,0,769,927),462=>array(43,-14,596,800),463=>array(3,0,371,927),464=>array(2,0,370,800),465=>array(50,-14,800,927),466=>array(43,-14,644,800),467=>array(92,-14,720,927),468=>array(78,-14,628,800),469=>array(92,-14,720,1040),470=>array(78,-14,628,914),471=>array(92,-14,720,1114),472=>array(78,-14,628,917),473=>array(92,-14,720,1114),474=>array(78,-14,628,917),475=>array(92,-14,720,1114),476=>array(78,-14,628,917),477=>array(43,-14,630,560),478=>array(5,0,769,1040),479=>array(43,-14,596,914),480=>array(5,0,769,1042),481=>array(43,-14,596,914),482=>array(0,0,1012,914),483=>array(43,-14,1000,758),484=>array(50,-14,792,742),485=>array(45,-216,674,559),486=>array(50,-14,747,927),487=>array(45,-216,632,800),488=>array(92,0,805,927),489=>array(-5,0,684,927),490=>array(50,-196,800,742),491=>array(43,-196,644,560),492=>array(50,-196,800,914),493=>array(43,-196,644,763),494=>array(72,-33,728,927),495=>array(43,-215,593,793),496=>array(-33,-216,359,800),497=>array(92,0,1510,729),498=>array(92,0,1364,729),499=>array(45,-14,1250,760),500=>array(50,-14,747,928),501=>array(45,-216,632,800),502=>array(92,-14,1186,729),503=>array(92,-208,737,742),504=>array(92,0,745,927),505=>array(84,0,634,800),506=>array(5,0,769,931),507=>array(43,-14,708,931),508=>array(0,0,1012,927),509=>array(43,-14,1000,800),510=>array(22,-36,823,927),511=>array(38,-46,645,800),512=>array(5,0,769,928),513=>array(43,-14,596,800),514=>array(5,0,769,923),515=>array(43,-14,596,784),516=>array(92,0,610,928),517=>array(43,-14,630,800),518=>array(92,0,610,923),519=>array(43,-14,630,784),520=>array(-41,0,377,928),521=>array(-3,0,381,800),522=>array(23,0,351,923),523=>array(7,0,335,784),524=>array(50,-14,800,928),525=>array(43,-14,644,800),526=>array(50,-14,800,923),527=>array(43,-14,644,784),528=>array(92,0,750,928),529=>array(58,0,490,800),530=>array(92,0,750,923),531=>array(84,0,490,784),532=>array(92,-14,720,928),533=>array(78,-14,628,800),534=>array(92,-14,720,923),535=>array(78,-14,628,784),536=>array(72,-239,647,742),537=>array(52,-239,548,560),538=>array(5,-239,677,729),539=>array(13,-239,455,702),540=>array(67,-210,616,742),541=>array(49,-211,544,560),542=>array(92,0,745,927),543=>array(-12,0,634,927),544=>array(84,-208,730,742),545=>array(45,-75,822,760),546=>array(61,-14,748,742),547=>array(43,-14,616,646),548=>array(45,-216,680,729),549=>array(45,-216,534,547),550=>array(5,0,769,927),551=>array(43,-14,596,760),552=>array(92,-192,610,729),553=>array(43,-196,630,560),554=>array(50,-14,800,1040),555=>array(43,-14,644,914),556=>array(50,-14,800,1040),557=>array(43,-14,644,898),558=>array(50,-14,800,927),559=>array(43,-14,644,760),560=>array(50,-14,800,1042),561=>array(43,-14,644,914),562=>array(-10,0,734,914),563=>array(12,-216,634,763),564=>array(84,-75,449,760),565=>array(84,-75,824,560),566=>array(13,-76,469,702),567=>array(-33,-216,259,547),568=>array(45,-14,1043,760),569=>array(45,-208,1043,560),570=>array(-14,-36,788,765),571=>array(-34,-36,768,765),572=>array(-7,-46,600,594),573=>array(-1,0,610,729),574=>array(-60,-36,742,765),575=>array(52,-240,595,560),576=>array(45,-240,595,547),577=>array(40,0,741,729),578=>array(42,0,573,560),579=>array(6,0,692,729),580=>array(23,-14,789,729),581=>array(5,0,769,729),582=>array(92,-93,610,822),583=>array(43,-93,630,640),584=>array(-56,-200,360,729),585=>array(-33,-216,360,760),586=>array(48,-200,927,741),587=>array(45,-216,800,560),588=>array(6,0,750,729),589=>array(-21,0,490,560),590=>array(-10,0,734,729),591=>array(-4,-216,656,547),592=>array(78,-14,631,560),593=>array(45,-14,632,560),594=>array(84,-14,671,560),595=>array(84,-14,671,760),596=>array(43,-14,526,560),597=>array(43,-69,526,560),598=>array(45,-216,750,760),599=>array(45,-14,801,760),600=>array(43,-14,630,560),601=>array(43,-14,630,560),602=>array(59,-14,885,560),603=>array(54,-14,493,560),604=>array(54,-14,493,560),605=>array(54,-14,769,560),606=>array(54,-14,665,560),607=>array(-33,-216,360,547),608=>array(45,-216,801,760),609=>array(45,-216,632,547),610=>array(43,-14,545,546),611=>array(25,-211,619,547),612=>array(25,-21,619,547),613=>array(78,-214,628,547),614=>array(84,0,634,760),615=>array(84,-216,634,760),616=>array(84,0,461,760),617=>array(83,0,356,547),618=>array(84,0,461,547),619=>array(84,0,475,760),620=>array(84,0,609,760),621=>array(85,-216,429,760),622=>array(84,-215,793,760),623=>array(79,-14,959,546),624=>array(79,-209,959,546),625=>array(83,-216,964,560),626=>array(-33,-216,634,560),627=>array(84,-216,802,560),628=>array(84,0,623,547),629=>array(43,-14,644,560),630=>array(43,-1,826,547),631=>array(51,0,630,574),632=>array(60,-208,729,760),633=>array(84,-13,490,547),634=>array(84,-13,490,760),635=>array(84,-216,659,547),636=>array(84,-208,490,560),637=>array(83,-216,490,560),638=>array(84,0,530,547),639=>array(84,0,530,547),640=>array(52,0,590,547),641=>array(52,0,590,547),642=>array(52,-216,548,560),643=>array(-33,-216,431,760),644=>array(-11,-216,444,760),645=>array(84,-216,539,560),646=>array(-31,-217,561,760),647=>array(13,-155,455,547),648=>array(13,-216,455,702),649=>array(84,-14,836,547),650=>array(79,-14,693,547),651=>array(83,0,625,547),652=>array(15,0,637,547),653=>array(35,0,889,547),654=>array(12,0,634,763),655=>array(64,0,660,547),656=>array(45,-216,703,547),657=>array(45,-69,617,547),658=>array(43,-215,593,547),659=>array(57,-215,593,547),660=>array(36,0,525,759),661=>array(36,0,525,759),662=>array(36,0,525,759),663=>array(36,-208,525,759),664=>array(50,-14,800,742),665=>array(84,0,589,547),666=>array(54,-14,665,560),667=>array(43,0,693,760),668=>array(84,0,607,547),669=>array(-170,-216,341,760),670=>array(84,-213,684,547),671=>array(84,0,499,547),672=>array(45,-208,801,760),673=>array(36,0,525,759),674=>array(36,0,525,759),675=>array(45,-14,1108,760),676=>array(45,-215,1167,760),677=>array(45,-55,1107,760),678=>array(13,0,928,702),679=>array(13,-216,777,760),680=>array(13,-69,881,702),681=>array(19,-216,979,760),682=>array(84,0,815,760),683=>array(84,0,732,760),684=>array(22,0,569,641),685=>array(22,86,345,641),686=>array(-89,-214,629,760),687=>array(-89,-216,797,760),688=>array(54,326,406,751),689=>array(54,326,406,751),690=>array(-21,205,166,751),691=>array(54,326,314,640),692=>array(54,319,314,632),693=>array(54,205,421,632),694=>array(14,326,358,632),695=>array(22,326,569,632),696=>array(8,205,406,632),697=>array(78,557,218,800),698=>array(78,557,437,800),699=>array(103,418,318,729),700=>array(63,418,278,729),701=>array(124,616,296,856),702=>array(116,481,255,760),703=>array(116,481,255,760),704=>array(23,326,336,751),705=>array(23,326,336,751),706=>array(130,517,370,843),707=>array(130,517,370,843),708=>array(87,561,413,800),709=>array(87,561,413,800),710=>array(66,616,434,800),711=>array(66,616,434,800),712=>array(107,488,199,759),713=>array(96,668,404,760),714=>array(178,616,454,800),715=>array(46,616,322,800),716=>array(107,-81,199,190),717=>array(96,-184,404,-92),718=>array(46,-236,322,-52),719=>array(178,-236,454,-52),720=>array(45,0,246,547),721=>array(45,361,246,547),722=>array(116,269,255,547),723=>array(116,269,255,547),724=>array(138,238,357,458),725=>array(141,238,360,458),726=>array(54,119,362,427),727=>array(54,229,274,317),728=>array(86,639,414,784),729=>array(183,654,317,774),730=>array(111,610,389,888),731=>array(167,-196,376,0),732=>array(80,638,420,778),733=>array(94,616,479,800),734=>array(0,213,360,524),735=>array(111,616,387,800),736=>array(16,208,390,633),737=>array(54,326,166,751),738=>array(33,318,351,640),739=>array(10,326,403,632),740=>array(23,326,336,751),741=>array(96,0,404,693),742=>array(96,0,404,693),743=>array(96,0,404,693),744=>array(96,0,404,693),745=>array(96,0,404,693),748=>array(88,-260,414,-21),749=>array(96,605,404,822),750=>array(92,418,554,729),755=>array(111,-240,389,38),759=>array(80,-196,420,-84),768=>array(-455,616,-179,800),769=>array(-326,616,-50,800),770=>array(-435,616,-67,800),771=>array(-424,638,-84,778),772=>array(-405,668,-97,760),773=>array(-500,663,0,755),774=>array(-409,639,-81,784),775=>array(-338,617,-164,760),776=>array(-402,654,-94,774),777=>array(-370,616,-122,843),778=>array(-390,610,-112,888),779=>array(-404,616,-19,800),780=>array(-435,616,-67,800),781=>array(-297,615,-205,832),782=>array(-390,615,-113,832),783=>array(-484,616,-100,800),784=>array(-409,639,-81,882),785=>array(-409,639,-81,784),786=>array(-271,418,-69,563),787=>array(-266,595,-132,844),788=>array(-266,595,-132,844),789=>array(-89,616,89,800),790=>array(-455,-276,-179,-93),791=>array(-326,-276,-50,-93),792=>array(-380,-240,-211,-6),793=>array(-295,-240,-126,-6),794=>array(-224,658,47,929),795=>array(-175,400,21,609),796=>array(-331,-240,-216,-11),797=>array(-386,-240,-115,-59),798=>array(-389,-240,-118,-59),799=>array(-370,-240,-136,-6),800=>array(-389,-202,-118,-110),801=>array(-423,-216,-79,117),802=>array(-419,-216,-75,117),803=>array(-338,-212,-164,-70),804=>array(-402,-212,-94,-92),805=>array(-365,-240,-135,-11),806=>array(-327,-239,-125,-93),807=>array(-372,-196,-151,0),808=>array(-333,-196,-124,0),809=>array(-297,-240,-205,-47),810=>array(-405,-237,-97,-54),811=>array(-450,-239,-51,-94),812=>array(-435,-240,-67,-57),813=>array(-435,-240,-67,-57),814=>array(-409,-239,-81,-94),815=>array(-409,-240,-81,-95),816=>array(-424,-234,-84,-94),817=>array(-405,-184,-97,-92),818=>array(-500,-236,0,-143),819=>array(-500,-236,0,-9),820=>array(-625,212,1,415),821=>array(-471,214,-94,309),822=>array(-837,214,-86,309),823=>array(-655,-46,-48,594),824=>array(-825,-36,-24,765),825=>array(-285,-240,-170,-11),826=>array(-405,-238,-97,-55),827=>array(-332,-241,-98,-6),828=>array(-450,-239,-51,-94),829=>array(-379,585,-123,842),830=>array(-267,595,-127,867),831=>array(-500,528,0,755),832=>array(-455,616,-179,800),833=>array(-323,616,-47,800),834=>array(-421,638,-81,778),835=>array(-266,595,-132,844),836=>array(-404,654,-55,978),837=>array(-286,-208,-179,-45),838=>array(-403,639,-97,786),839=>array(-360,-226,-140,-35),840=>array(-379,-240,-121,-47),841=>array(-367,-240,-133,-21),842=>array(-420,616,-80,800),843=>array(-420,567,-80,850),844=>array(-420,573,-80,835),845=>array(-459,-230,-41,-30),846=>array(-357,-240,-143,-45),849=>array(-320,610,-179,888),850=>array(-409,640,-81,882),851=>array(-367,-240,-135,-9),855=>array(-320,610,-179,888),856=>array(-120,654,14,774),858=>array(-445,-240,-58,-11),860=>array(-433,-237,458,-79),861=>array(-433,802,458,960),862=>array(-445,797,445,889),863=>array(-445,-185,445,-93),864=>array(-362,756,362,894),865=>array(-445,769,445,927),866=>array(-449,-230,454,-30),880=>array(92,0,606,729),881=>array(84,0,481,547),882=>array(92,0,930,729),883=>array(92,0,744,729),884=>array(78,557,218,800),885=>array(78,-208,218,35),886=>array(92,0,745,729),887=>array(84,0,617,547),890=>array(202,-208,333,-45),891=>array(43,-14,526,560),892=>array(43,-14,526,560),893=>array(43,-14,526,560),894=>array(63,-142,288,547),900=>array(169,616,445,800),901=>array(96,654,445,978),902=>array(26,0,792,800),903=>array(102,253,278,442),904=>array(-24,0,771,800),905=>array(-18,0,915,800),906=>array(-21,0,450,800),908=>array(-19,-14,836,800),910=>array(-27,0,992,800),911=>array(-30,0,867,800),912=>array(23,-19,372,978),913=>array(5,0,769,729),914=>array(92,0,692,729),915=>array(92,0,610,729),916=>array(5,0,769,729),917=>array(92,0,610,729),918=>array(45,0,680,729),919=>array(92,0,745,729),920=>array(50,-14,800,742),921=>array(92,0,280,729),922=>array(92,0,805,729),923=>array(5,0,769,729),924=>array(92,0,903,729),925=>array(92,0,745,729),926=>array(98,0,548,729),927=>array(50,-14,800,742),928=>array(92,0,745,729),929=>array(92,0,692,729),931=>array(92,0,610,729),932=>array(5,0,677,729),933=>array(-10,0,734,729),934=>array(50,0,800,729),935=>array(19,0,751,729),936=>array(56,0,795,729),937=>array(27,0,823,742),938=>array(34,0,342,927),939=>array(-10,0,734,927),940=>array(48,-13,645,800),941=>array(54,-14,493,800),942=>array(84,-208,634,800),943=>array(77,-19,353,800),944=>array(78,-10,629,978),945=>array(48,-13,645,559),946=>array(84,-208,671,773),947=>array(15,-208,667,547),948=>array(43,-14,645,768),949=>array(54,-14,493,560),950=>array(43,-208,542,760),951=>array(84,-208,634,560),952=>array(43,-11,645,768),953=>array(78,-19,348,547),954=>array(84,0,655,547),955=>array(30,0,603,760),956=>array(85,-209,704,547),957=>array(15,0,635,547),958=>array(43,-208,542,760),959=>array(43,-14,644,560),960=>array(42,-19,732,547),961=>array(84,-208,671,562),962=>array(43,-208,526,560),963=>array(43,-14,727,547),964=>array(21,-19,612,547),965=>array(78,-10,629,547),966=>array(64,-208,725,552),967=>array(25,-208,620,547),968=>array(65,-208,724,547),969=>array(43,-13,826,547),970=>array(19,-19,355,774),971=>array(78,-10,629,774),972=>array(43,-14,644,800),973=>array(78,-10,629,800),974=>array(43,-13,826,800),975=>array(92,-208,805,729),976=>array(55,-11,575,768),977=>array(51,-11,612,768),978=>array(21,0,717,729),979=>array(-24,0,954,800),980=>array(21,0,717,927),981=>array(60,-208,729,760),982=>array(22,-13,843,547),983=>array(54,-205,688,548),984=>array(50,-208,800,742),985=>array(43,-208,644,560),986=>array(50,-208,678,729),987=>array(43,-208,541,547),988=>array(92,0,599,729),989=>array(-56,-208,437,760),990=>array(61,2,646,729),991=>array(82,0,571,759),992=>array(56,-208,843,742),993=>array(22,-180,537,559),994=>array(50,-213,1043,729),995=>array(59,-208,775,547),996=>array(50,-208,740,742),997=>array(45,-208,632,560),998=>array(92,-213,878,729),999=>array(21,-14,689,575),1000=>array(42,-208,692,745),1001=>array(46,-208,608,560),1002=>array(53,0,736,742),1003=>array(49,0,622,560),1004=>array(50,-14,715,758),1005=>array(83,-14,670,758),1006=>array(28,-208,654,729),1007=>array(27,-208,563,729),1008=>array(54,-7,688,548),1009=>array(84,-216,671,562),1010=>array(43,-14,526,560),1011=>array(-33,-216,259,760),1012=>array(50,-14,800,742),1013=>array(67,-14,550,560),1014=>array(81,-14,563,560),1015=>array(92,0,692,729),1016=>array(84,-208,671,760),1017=>array(50,-14,670,742),1018=>array(92,0,903,729),1019=>array(73,-208,649,547),1020=>array(33,-208,671,562),1021=>array(33,-14,653,742),1022=>array(50,-14,670,742),1023=>array(33,-14,653,742),1024=>array(92,0,610,927),1025=>array(92,0,610,927),1026=>array(5,-200,798,729),1027=>array(92,0,610,928),1028=>array(50,-14,670,742),1029=>array(72,-14,647,742),1030=>array(92,0,280,729),1031=>array(32,0,339,927),1032=>array(-56,-200,280,729),1033=>array(46,0,1102,729),1034=>array(92,0,1060,729),1035=>array(5,0,798,729),1036=>array(92,0,803,928),1037=>array(92,0,745,927),1038=>array(29,0,741,927),1039=>array(92,-157,745,729),1040=>array(5,0,769,729),1041=>array(92,0,692,729),1042=>array(92,0,692,729),1043=>array(92,0,610,729),1044=>array(60,-157,831,729),1045=>array(92,0,610,729),1046=>array(15,0,1209,729),1047=>array(66,-14,645,742),1048=>array(92,0,745,729),1049=>array(92,0,745,927),1050=>array(92,0,803,729),1051=>array(46,0,739,729),1052=>array(92,0,903,729),1053=>array(92,0,745,729),1054=>array(50,-14,800,742),1055=>array(92,0,745,729),1056=>array(92,0,692,729),1057=>array(50,-14,670,742),1058=>array(5,0,677,729),1059=>array(29,0,741,729),1060=>array(50,0,941,729),1061=>array(19,0,751,729),1062=>array(92,-157,868,729),1063=>array(81,0,716,729),1064=>array(92,0,1143,729),1065=>array(92,-157,1266,729),1066=>array(49,0,890,729),1067=>array(92,0,944,729),1068=>array(92,0,692,729),1069=>array(64,-14,684,742),1070=>array(92,-14,1119,742),1071=>array(64,0,678,729),1072=>array(43,-14,596,560),1073=>array(43,-14,655,792),1074=>array(84,0,589,547),1075=>array(84,0,499,547),1076=>array(56,-138,751,547),1077=>array(43,-14,630,560),1078=>array(15,0,980,547),1079=>array(49,-14,518,560),1080=>array(84,0,617,547),1081=>array(84,0,617,765),1082=>array(84,0,664,547),1083=>array(55,0,648,547),1084=>array(84,0,733,547),1085=>array(84,0,607,547),1086=>array(43,-14,644,560),1087=>array(84,0,607,547),1088=>array(84,-208,671,560),1089=>array(43,-14,526,560),1090=>array(4,0,575,547),1091=>array(12,-216,634,547),1092=>array(55,-208,937,760),1093=>array(15,0,630,547),1094=>array(84,-138,698,547),1095=>array(64,0,573,547),1096=>array(84,0,972,547),1097=>array(84,-138,1063,547),1098=>array(20,0,711,547),1099=>array(84,0,823,547),1100=>array(84,0,588,547),1101=>array(67,-14,550,560),1102=>array(84,-14,928,560),1103=>array(31,0,560,547),1104=>array(43,-14,630,803),1105=>array(43,-14,630,774),1106=>array(20,-216,669,760),1107=>array(84,0,520,803),1108=>array(43,-14,526,560),1109=>array(52,-14,548,560),1110=>array(84,0,259,760),1111=>array(17,0,325,774),1112=>array(-33,-216,259,760),1113=>array(44,0,942,547),1114=>array(84,0,912,547),1115=>array(20,0,656,760),1116=>array(84,0,664,803),1117=>array(84,0,617,803),1118=>array(12,-216,634,765),1119=>array(84,-138,607,547),1120=>array(50,-14,1043,729),1121=>array(43,-13,826,547),1122=>array(49,0,791,729),1123=>array(20,0,692,731),1124=>array(92,-14,948,742),1125=>array(84,-14,760,560),1126=>array(8,0,984,729),1127=>array(25,0,807,547),1128=>array(92,0,1351,729),1129=>array(84,0,1097,547),1130=>array(50,0,800,729),1131=>array(43,0,644,547),1132=>array(92,0,1137,729),1133=>array(84,0,964,547),1134=>array(54,-208,616,938),1135=>array(40,-193,493,756),1136=>array(9,0,1060,729),1137=>array(9,-208,1046,759),1138=>array(50,-14,800,742),1139=>array(43,-14,644,560),1140=>array(5,0,826,742),1141=>array(9,0,681,560),1142=>array(5,0,826,928),1143=>array(9,0,681,800),1144=>array(47,-216,1130,742),1145=>array(43,-216,1025,560),1146=>array(50,-14,1024,742),1147=>array(43,-14,820,560),1148=>array(57,-14,1348,928),1149=>array(47,-13,1126,828),1150=>array(50,-14,1043,910),1151=>array(43,-13,826,746),1152=>array(50,-208,670,742),1153=>array(43,-208,526,560),1154=>array(27,-33,521,488),1155=>array(-601,606,-85,822),1156=>array(-413,638,0,784),1157=>array(-365,595,-231,785),1158=>array(-365,595,-231,785),1159=>array(-796,592,4,788),1160=>array(-1069,-179,383,928),1161=>array(-996,-280,306,1022),1162=>array(92,-208,933,927),1163=>array(84,-208,782,765),1164=>array(23,0,692,729),1165=>array(0,0,567,702),1166=>array(92,0,702,729),1167=>array(84,-208,671,560),1168=>array(92,0,610,878),1169=>array(84,0,499,700),1170=>array(28,0,638,729),1171=>array(21,0,519,547),1172=>array(92,-200,728,729),1173=>array(84,-216,591,547),1174=>array(15,-157,1209,729),1175=>array(15,-138,980,547),1176=>array(66,-196,645,742),1177=>array(49,-196,518,560),1178=>array(92,-157,803,729),1179=>array(84,-138,664,547),1180=>array(92,0,803,729),1181=>array(84,0,664,547),1182=>array(23,0,803,729),1183=>array(7,0,664,760),1184=>array(24,0,1000,729),1185=>array(20,0,812,547),1186=>array(92,-157,932,729),1187=>array(84,-138,783,547),1188=>array(92,0,1075,729),1189=>array(84,0,847,547),1190=>array(92,-200,1193,729),1191=>array(84,-216,939,547),1192=>array(56,-14,924,743),1193=>array(55,-14,836,560),1194=>array(50,-196,670,742),1195=>array(43,-196,526,560),1196=>array(5,-157,677,729),1197=>array(4,-138,575,547),1198=>array(-10,0,734,729),1199=>array(12,-216,634,547),1200=>array(-10,0,734,729),1201=>array(12,-216,634,547),1202=>array(19,-157,751,729),1203=>array(15,-138,630,547),1204=>array(5,-157,1088,729),1205=>array(4,-138,976,547),1206=>array(81,-157,904,729),1207=>array(64,-138,749,547),1208=>array(81,0,716,729),1209=>array(64,0,573,547),1210=>array(81,0,716,729),1211=>array(84,0,634,760),1212=>array(7,-14,976,742),1213=>array(5,-14,761,560),1214=>array(7,-184,976,742),1215=>array(5,-161,761,560),1216=>array(92,0,280,729),1217=>array(15,0,1209,927),1218=>array(15,0,980,784),1219=>array(92,-200,769,729),1220=>array(84,-216,626,547),1221=>array(26,-208,926,729),1222=>array(21,-208,781,547),1223=>array(92,-200,745,729),1224=>array(84,-216,608,547),1225=>array(92,-208,933,729),1226=>array(84,-208,782,547),1227=>array(81,-157,716,729),1228=>array(64,-138,573,547),1229=>array(92,-208,1090,729),1230=>array(84,-208,908,547),1231=>array(84,0,259,760),1232=>array(5,0,769,935),1233=>array(43,-14,596,780),1234=>array(5,0,769,927),1235=>array(43,-14,596,774),1236=>array(0,0,1012,729),1237=>array(43,-14,1000,560),1238=>array(92,0,610,927),1239=>array(43,-14,630,784),1240=>array(51,-14,800,742),1241=>array(43,-14,630,560),1242=>array(51,-14,800,927),1243=>array(43,-14,630,774),1244=>array(15,0,1209,927),1245=>array(15,0,980,774),1246=>array(66,-14,645,927),1247=>array(49,-14,518,773),1248=>array(72,-33,728,729),1249=>array(43,-215,593,547),1250=>array(92,0,745,914),1251=>array(84,0,617,763),1252=>array(92,0,745,927),1253=>array(84,0,617,774),1254=>array(50,-14,800,927),1255=>array(43,-14,644,774),1256=>array(50,-14,800,742),1257=>array(43,-14,644,560),1258=>array(50,-14,800,927),1259=>array(43,-14,644,774),1260=>array(64,-14,684,927),1261=>array(67,-14,550,774),1262=>array(29,0,741,914),1263=>array(12,-216,634,763),1264=>array(29,0,741,927),1265=>array(12,-216,634,774),1266=>array(29,0,741,927),1267=>array(12,-216,634,800),1268=>array(81,0,716,927),1269=>array(64,0,573,774),1270=>array(92,-157,610,729),1271=>array(84,-138,499,547),1272=>array(92,0,944,927),1273=>array(84,0,823,774),1274=>array(28,-216,638,729),1275=>array(21,-217,519,547),1276=>array(19,-200,750,729),1277=>array(15,-216,620,547),1278=>array(19,0,751,729),1279=>array(15,0,630,547),1280=>array(70,0,670,729),1281=>array(44,0,524,547),1282=>array(70,-14,1081,729),1283=>array(44,-14,850,547),1284=>array(98,-14,1027,742),1285=>array(79,-14,836,560),1286=>array(98,-208,804,742),1287=>array(79,-208,668,560),1288=>array(26,-14,1150,729),1289=>array(21,-14,933,547),1290=>array(92,-14,1186,729),1291=>array(84,-14,939,547),1292=>array(50,-14,748,742),1293=>array(43,-14,544,546),1294=>array(5,-14,846,729),1295=>array(4,-14,709,547),1296=>array(67,-14,616,742),1297=>array(54,-14,493,560),1298=>array(46,-200,739,729),1299=>array(55,-216,648,547),1300=>array(46,0,1266,729),1301=>array(55,0,1053,547),1302=>array(92,0,1045,729),1303=>array(84,-208,964,560),1304=>array(64,0,1008,729),1305=>array(31,-14,965,560),1306=>array(50,-146,800,742),1307=>array(45,-208,632,559),1308=>array(30,0,1072,729),1309=>array(35,0,889,547),1310=>array(92,0,803,729),1311=>array(84,0,664,547),1312=>array(46,-200,1187,729),1313=>array(55,-216,980,547),1314=>array(92,-200,1193,729),1315=>array(84,-216,939,547),1316=>array(92,-157,933,729),1317=>array(84,-138,782,547),1329=>array(83,-38,731,729),1330=>array(83,0,655,743),1331=>array(26,0,728,743),1332=>array(22,0,731,743),1333=>array(83,-14,655,729),1334=>array(66,0,664,743),1335=>array(83,0,625,729),1336=>array(83,0,655,743),1337=>array(83,-13,903,742),1338=>array(26,-14,728,729),1339=>array(83,0,648,729),1340=>array(83,0,549,729),1341=>array(83,-14,888,729),1342=>array(62,-12,722,741),1343=>array(74,0,639,729),1344=>array(4,-46,598,729),1345=>array(66,-48,664,743),1346=>array(18,0,715,743),1347=>array(22,0,660,735),1348=>array(83,-14,780,729),1349=>array(57,-14,645,743),1350=>array(0,-14,697,729),1351=>array(57,-14,655,729),1352=>array(83,0,648,743),1353=>array(40,-48,638,743),1354=>array(18,0,789,743),1355=>array(57,0,654,743),1356=>array(83,0,780,743),1357=>array(92,-14,720,729),1358=>array(18,0,715,729),1359=>array(53,-14,641,743),1360=>array(83,0,648,743),1361=>array(57,-14,645,743),1362=>array(83,0,567,729),1363=>array(22,0,811,729),1364=>array(9,0,645,743),1365=>array(49,-14,799,742),1366=>array(44,-14,833,729),1369=>array(104,481,230,760),1370=>array(57,418,250,729),1371=>array(0,616,310,800),1372=>array(0,595,375,893),1373=>array(-7,614,290,847),1374=>array(0,586,460,878),1375=>array(40,618,434,893),1377=>array(71,-13,863,547),1378=>array(76,-208,571,560),1379=>array(40,-208,700,559),1380=>array(76,-208,703,560),1381=>array(71,-14,567,760),1382=>array(40,-208,700,559),1383=>array(76,0,532,760),1384=>array(76,-208,579,560),1385=>array(76,-208,756,560),1386=>array(40,-14,700,760),1387=>array(76,-208,571,760),1388=>array(76,-208,410,547),1389=>array(76,-208,909,760),1390=>array(40,-14,600,760),1391=>array(71,-208,567,760),1392=>array(76,0,571,760),1393=>array(26,-13,536,760),1394=>array(76,-208,703,560),1395=>array(62,-13,570,768),1396=>array(71,-13,699,760),1397=>array(-30,-216,233,547),1398=>array(-61,-13,567,760),1399=>array(13,-208,456,560),1400=>array(76,0,571,560),1401=>array(5,-208,375,547),1402=>array(71,-208,863,546),1403=>array(44,-208,533,560),1404=>array(76,0,622,560),1405=>array(71,-13,567,547),1406=>array(71,-208,699,760),1407=>array(71,-13,863,560),1408=>array(76,-208,571,560),1409=>array(44,-216,631,559),1410=>array(76,0,475,547),1411=>array(71,-208,863,760),1412=>array(-56,-208,604,560),1413=>array(44,-14,645,560),1414=>array(31,-190,774,760),1415=>array(71,-14,808,760),1417=>array(101,0,259,547),1418=>array(49,180,325,359),1456=>array(296,-229,394,-10),1457=>array(147,-229,501,-10),1458=>array(138,-229,492,-10),1459=>array(125,-229,492,-10),1460=>array(296,-171,394,-73),1461=>array(223,-171,467,-73),1462=>array(235,-229,455,-10),1463=>array(174,-171,516,0),1464=>array(187,-217,504,0),1465=>array(-24,547,73,723),1466=>array(-24,547,73,723),1467=>array(187,-239,528,-5),1468=>array(301,225,399,322),1469=>array(296,-217,394,-22),1470=>array(54,413,361,555),1471=>array(187,547,504,710),1472=>array(98,-98,273,645),1473=>array(753,613,851,710),1474=>array(137,613,235,710),1475=>array(98,0,273,547),1478=>array(78,0,462,547),1479=>array(187,-229,504,-10),1488=>array(84,0,644,547),1489=>array(43,0,567,547),1490=>array(43,-9,418,547),1491=>array(43,0,545,547),1492=>array(91,0,596,547),1493=>array(91,0,252,547),1494=>array(43,0,357,547),1495=>array(91,0,596,547),1496=>array(90,-13,624,553),1497=>array(66,164,228,547),1498=>array(43,-240,487,547),1499=>array(43,0,511,547),1500=>array(43,0,527,711),1501=>array(91,0,605,547),1502=>array(43,0,633,554),1503=>array(91,-240,252,547),1504=>array(43,0,362,547),1505=>array(90,-13,624,547),1506=>array(43,-101,575,547),1507=>array(91,-240,584,547),1508=>array(91,0,603,547),1509=>array(11,-240,543,548),1510=>array(33,0,564,547),1511=>array(91,-240,660,546),1512=>array(43,0,511,547),1513=>array(20,0,750,547),1514=>array(10,-4,592,547),1520=>array(91,0,574,547),1521=>array(66,0,524,547),1522=>array(66,164,500,547),1523=>array(84,361,360,547),1524=>array(84,361,626,547),1542=>array(-2,-20,630,892),1543=>array(-2,-20,630,897),1545=>array(65,0,811,635),1546=>array(65,0,1084,635),1548=>array(98,0,322,331),1557=>array(121,612,379,868),1563=>array(98,0,323,689),1567=>array(69,0,515,742),1569=>array(73,20,437,493),1570=>array(-20,0,362,955),1571=>array(75,0,259,993),1572=>array(-42,-244,547,603),1573=>array(76,-245,259,760),1574=>array(63,-107,863,603),1575=>array(84,0,259,760),1576=>array(63,-149,921,327),1577=>array(48,-30,540,513),1578=>array(63,-5,921,415),1579=>array(63,-5,921,537),1580=>array(77,-244,720,425),1581=>array(77,-244,720,425),1582=>array(77,-244,720,579),1583=>array(61,-15,442,415),1584=>array(61,-15,442,579),1585=>array(-42,-244,508,269),1586=>array(-42,-244,508,457),1587=>array(63,-244,1297,366),1588=>array(63,-244,1297,586),1589=>array(63,-244,1265,362),1590=>array(63,-244,1265,457),1591=>array(70,0,971,760),1592=>array(70,0,971,760),1593=>array(87,-244,720,521),1594=>array(87,-244,720,652),1600=>array(-10,0,352,125),1601=>array(63,-24,1082,627),1602=>array(52,-215,825,635),1603=>array(70,-27,814,760),1604=>array(70,-142,778,760),1605=>array(68,-244,660,369),1606=>array(62,-165,779,457),1607=>array(48,-30,540,358),1608=>array(-42,-244,547,322),1609=>array(63,-107,863,462),1610=>array(63,-244,863,462),1611=>array(107,591,393,825),1612=>array(107,591,393,881),1613=>array(107,-239,393,-5),1614=>array(107,591,393,723),1615=>array(107,590,393,881),1616=>array(107,-137,393,-5),1617=>array(88,599,412,869),1618=>array(115,610,383,878),1619=>array(59,584,441,735),1620=>array(154,601,335,822),1621=>array(155,-245,336,-23),1623=>array(107,615,393,906),1626=>array(99,616,401,775),1632=>array(218,195,392,366),1633=>array(140,0,431,635),1634=>array(12,0,598,635),1635=>array(12,0,597,635),1636=>array(74,-10,530,646),1637=>array(63,-10,547,643),1638=>array(37,0,574,635),1639=>array(15,0,596,635),1640=>array(15,0,596,635),1641=>array(32,0,590,640),1642=>array(65,0,545,635),1643=>array(0,-118,349,318),1644=>array(63,418,278,729),1645=>array(42,101,502,537),1646=>array(63,-5,921,327),1647=>array(52,-215,825,484),1648=>array(216,600,284,885),1652=>array(51,641,232,863),1657=>array(63,-5,921,599),1658=>array(63,-5,921,566),1659=>array(63,-244,921,327),1660=>array(63,-171,921,415),1661=>array(63,-5,921,566),1662=>array(63,-244,921,327),1663=>array(63,-5,921,566),1664=>array(63,-244,921,327),1665=>array(77,-244,720,725),1666=>array(77,-244,720,737),1667=>array(77,-244,720,425),1668=>array(77,-244,720,425),1669=>array(77,-244,720,737),1670=>array(77,-244,720,425),1671=>array(77,-244,720,425),1672=>array(61,-15,442,746),1673=>array(61,-180,442,415),1674=>array(61,-171,442,415),1675=>array(61,-171,442,746),1676=>array(61,-15,442,586),1677=>array(61,-146,442,415),1678=>array(61,-15,442,708),1679=>array(61,-15,442,684),1680=>array(61,-15,442,708),1681=>array(-42,-244,520,648),1682=>array(-42,-244,542,556),1683=>array(-42,-244,587,269),1684=>array(-42,-244,522,269),1685=>array(-42,-244,753,269),1686=>array(-42,-244,522,269),1687=>array(-42,-244,508,464),1688=>array(-42,-244,508,586),1689=>array(-42,-244,508,586),1690=>array(63,-244,1297,464),1691=>array(63,-244,1297,366),1692=>array(63,-244,1297,586),1693=>array(63,-244,1265,362),1694=>array(63,-244,1265,586),1695=>array(70,0,971,760),1696=>array(87,-244,720,781),1697=>array(63,-24,1082,484),1698=>array(63,-171,1082,484),1699=>array(63,-171,1082,635),1700=>array(63,-24,1082,786),1701=>array(63,-293,1082,484),1702=>array(63,-24,1082,786),1703=>array(52,-215,825,635),1704=>array(52,-215,825,757),1705=>array(63,-39,1024,760),1706=>array(63,-39,1194,760),1707=>array(63,-39,1024,760),1708=>array(70,-27,814,760),1709=>array(70,-27,814,854),1710=>array(70,-293,814,760),1711=>array(63,-39,1024,910),1712=>array(63,-39,1024,910),1713=>array(63,-39,1024,910),1714=>array(63,-171,1024,910),1715=>array(63,-293,1024,910),1716=>array(63,-39,1024,1025),1717=>array(70,-142,841,971),1718=>array(70,-142,778,952),1719=>array(70,-142,781,1025),1720=>array(70,-391,778,760),1721=>array(62,-317,779,464),1722=>array(62,-165,779,366),1723=>array(62,-165,779,636),1724=>array(62,-330,779,464),1725=>array(62,-165,779,586),1726=>array(70,-33,877,506),1727=>array(77,-244,720,579),1734=>array(-42,-244,547,556),1740=>array(63,-107,863,462),1742=>array(63,-107,863,556),1749=>array(48,-30,540,358),1776=>array(218,195,392,366),1777=>array(140,0,431,635),1778=>array(12,0,598,635),1779=>array(12,0,597,635),1780=>array(12,0,573,650),1781=>array(30,-8,580,643),1782=>array(85,0,514,645),1783=>array(15,0,596,635),1784=>array(15,0,596,635),1785=>array(32,0,590,640),1984=>array(48,-14,648,742),1985=>array(69,0,583,729),1986=>array(80,0,616,729),1987=>array(80,0,616,729),1988=>array(80,0,616,729),1989=>array(80,0,616,729),1990=>array(80,0,616,729),1991=>array(98,0,599,729),1992=>array(98,0,599,729),1993=>array(70,0,625,742),1994=>array(84,0,259,729),1995=>array(43,-14,504,465),1996=>array(15,0,529,729),1997=>array(15,0,637,451),1998=>array(84,0,607,451),1999=>array(84,0,607,451),2000=>array(46,0,548,742),2001=>array(84,0,607,667),2002=>array(43,0,820,742),2003=>array(84,0,467,729),2004=>array(84,0,467,729),2005=>array(84,0,584,729),2006=>array(84,0,604,729),2007=>array(15,0,360,729),2008=>array(84,0,938,532),2009=>array(15,0,491,729),2010=>array(15,0,811,729),2011=>array(84,0,607,451),2012=>array(15,0,637,729),2013=>array(84,0,869,729),2014=>array(84,0,543,729),2015=>array(43,0,692,729),2016=>array(15,0,491,729),2017=>array(15,0,637,729),2018=>array(43,0,531,729),2019=>array(84,0,543,729),2020=>array(84,0,543,581),2021=>array(84,0,543,729),2022=>array(43,0,531,729),2023=>array(43,0,531,729),2027=>array(95,668,403,760),2028=>array(63,638,438,777),2029=>array(185,654,319,774),2030=>array(65,616,433,800),2031=>array(33,616,438,803),2032=>array(63,638,438,777),2033=>array(33,616,438,803),2034=>array(183,-212,317,-92),2035=>array(96,654,404,774),2036=>array(63,418,278,729),2037=>array(103,418,318,729),2040=>array(84,0,607,562),2041=>array(84,0,607,564),2042=>array(-10,0,425,125),3647=>array(62,-147,638,760),3713=>array(43,-14,706,560),3714=>array(43,-14,723,560),3716=>array(43,-14,704,560),3719=>array(21,-241,521,561),3720=>array(42,0,705,560),3722=>array(40,-269,768,560),3725=>array(40,-24,713,610),3732=>array(42,-14,647,560),3733=>array(42,-19,647,561),3734=>array(-22,-240,684,560),3735=>array(20,-14,768,560),3737=>array(37,-15,681,560),3738=>array(38,-15,664,561),3739=>array(38,-15,664,760),3740=>array(60,-12,910,626),3741=>array(64,-14,762,760),3742=>array(76,-14,773,560),3743=>array(76,-14,773,760),3745=>array(24,-14,771,547),3746=>array(40,-23,713,760),3747=>array(48,-10,733,615),3749=>array(41,-33,693,560),3751=>array(33,-33,640,561),3754=>array(51,-21,819,724),3755=>array(44,-21,935,620),3757=>array(53,-20,662,606),3758=>array(48,-14,825,698),3759=>array(43,-259,897,648),3760=>array(36,-16,658,567),3761=>array(-653,610,-31,896),3762=>array(39,0,563,593),3763=>array(-479,0,563,875),3764=>array(-654,622,-62,950),3765=>array(-654,633,13,962),3766=>array(-654,622,-62,950),3767=>array(-654,633,13,962),3768=>array(-426,-385,-165,-55),3769=>array(-473,-316,-174,-28),3771=>array(-653,610,-31,896),3772=>array(-682,-311,15,-48),3773=>array(39,-220,691,776),3776=>array(83,-13,444,561),3777=>array(83,-13,818,561),3778=>array(-37,-14,458,936),3779=>array(23,-14,595,879),3780=>array(-15,-35,585,809),3782=>array(70,-240,688,582),3784=>array(-413,659,-297,844),3785=>array(-627,622,-22,918),3786=>array(-667,621,39,965),3787=>array(-521,612,-187,917),3788=>array(-682,603,15,866),3789=>array(-479,668,-229,875),3792=>array(66,-29,723,563),3793=>array(25,-139,721,586),3794=>array(31,-80,603,711),3795=>array(24,-14,882,981),3796=>array(48,-156,696,711),3797=>array(48,-156,696,711),3798=>array(64,-14,894,950),3799=>array(43,-240,706,560),3800=>array(72,-269,774,582),3801=>array(58,-14,858,564),3804=>array(44,-21,1301,620),3805=>array(44,-21,1305,620),4256=>array(47,-14,827,819),4257=>array(39,-0,719,819),4258=>array(37,-138,667,828),4259=>array(41,-15,793,819),4260=>array(29,0,572,828),4261=>array(24,0,729,828),4262=>array(15,-14,709,819),4263=>array(49,-14,890,828),4264=>array(4,0,415,862),4265=>array(39,0,581,819),4266=>array(18,-14,796,820),4267=>array(48,-14,837,819),4268=>array(43,0,586,819),4269=>array(37,-157,817,829),4270=>array(11,-14,731,822),4271=>array(20,0,585,823),4272=>array(43,-15,863,820),4273=>array(43,-15,587,820),4274=>array(43,-0,586,828),4275=>array(37,-170,817,828),4276=>array(37,0,828,825),4277=>array(28,0,695,820),4278=>array(44,0,586,828),4279=>array(34,0,577,820),4280=>array(39,-14,582,820),4281=>array(43,0,586,819),4282=>array(45,-14,778,827),4283=>array(46,-15,822,820),4284=>array(43,-0,586,819),4285=>array(29,-15,594,828),4286=>array(43,-0,586,819),4287=>array(15,0,726,819),4288=>array(18,-14,796,820),4289=>array(43,0,586,820),4290=>array(37,-15,652,828),4291=>array(9,0,552,820),4292=>array(33,0,561,820),4293=>array(24,-14,714,828),4304=>array(49,-14,505,599),4305=>array(49,-14,515,823),4306=>array(44,-232,578,561),4307=>array(49,-225,786,557),4308=>array(49,-232,496,557),4309=>array(49,-232,505,557),4310=>array(25,-14,502,828),4311=>array(49,-14,779,557),4312=>array(49,0,515,557),4313=>array(49,-232,506,542),4314=>array(49,-225,1025,562),4315=>array(49,-14,505,828),4316=>array(63,-14,520,819),4317=>array(49,-0,765,557),4318=>array(49,-14,505,818),4319=>array(49,-232,504,560),4320=>array(49,0,774,830),4321=>array(63,-14,520,818),4322=>array(49,-232,651,670),4323=>array(29,-232,533,604),4324=>array(49,-232,792,558),4325=>array(49,-232,496,818),4326=>array(49,-225,766,557),4327=>array(49,-232,505,549),4328=>array(20,-14,489,828),4329=>array(63,0,520,828),4330=>array(49,-232,573,548),4331=>array(49,-14,504,818),4332=>array(64,-15,534,828),4333=>array(49,-232,517,818),4334=>array(63,-14,520,818),4335=>array(24,-232,516,580),4336=>array(49,-15,505,823),4337=>array(49,-14,505,823),4338=>array(49,-146,504,557),4339=>array(49,-232,505,558),4340=>array(49,-232,504,828),4341=>array(49,-14,558,828),4342=>array(49,-232,803,557),4343=>array(49,-232,556,557),4344=>array(49,-232,505,549),4345=>array(44,-232,578,561),4346=>array(49,-111,505,557),4347=>array(49,0,399,500),4348=>array(24,400,294,828),5121=>array(5,0,769,729),5122=>array(5,0,769,1056),5123=>array(5,0,769,729),5124=>array(5,0,769,928),5125=>array(92,0,821,729),5126=>array(92,0,821,928),5127=>array(92,0,821,927),5129=>array(92,0,821,729),5130=>array(84,0,813,729),5131=>array(84,0,813,928),5132=>array(92,0,1013,729),5133=>array(5,0,925,729),5134=>array(92,0,1013,729),5135=>array(5,0,925,729),5136=>array(92,0,1013,928),5137=>array(5,0,925,928),5138=>array(92,0,1065,729),5139=>array(92,0,1056,729),5140=>array(92,0,1065,928),5141=>array(92,0,1056,928),5142=>array(92,0,821,928),5143=>array(92,0,1057,729),5144=>array(84,0,1058,729),5145=>array(92,0,1057,928),5146=>array(84,0,1058,928),5147=>array(84,0,813,928),5149=>array(92,607,226,728),5150=>array(60,326,473,734),5151=>array(31,338,379,722),5152=>array(31,338,379,722),5153=>array(60,392,338,711),5154=>array(60,352,338,670),5155=>array(60,392,338,670),5156=>array(60,392,338,670),5157=>array(31,327,518,749),5158=>array(60,326,414,734),5159=>array(92,304,226,424),5160=>array(60,494,338,569),5161=>array(60,392,338,670),5162=>array(60,392,338,693),5163=>array(5,0,1167,729),5164=>array(5,0,940,729),5165=>array(92,0,1170,729),5166=>array(84,0,1251,729),5167=>array(5,0,769,729),5168=>array(5,0,769,1056),5169=>array(5,0,769,729),5170=>array(5,0,769,928),5171=>array(73,0,802,729),5172=>array(73,0,802,928),5173=>array(73,0,802,927),5175=>array(73,0,802,729),5176=>array(73,0,802,729),5177=>array(73,0,802,928),5178=>array(92,0,1013,729),5179=>array(5,0,925,729),5180=>array(92,0,1013,729),5181=>array(5,0,925,729),5182=>array(92,0,1013,928),5183=>array(5,0,925,928),5184=>array(92,0,1046,729),5185=>array(73,0,1056,729),5186=>array(92,0,1046,928),5187=>array(73,0,1056,928),5188=>array(92,0,1046,729),5189=>array(73,0,1058,729),5190=>array(92,0,1046,928),5191=>array(73,0,1058,928),5192=>array(73,0,802,927),5193=>array(60,326,520,727),5194=>array(60,326,172,734),5196=>array(92,-14,720,729),5197=>array(92,0,720,1056),5198=>array(92,0,720,743),5199=>array(92,0,720,928),5200=>array(73,0,759,729),5201=>array(73,0,759,928),5202=>array(73,0,759,927),5204=>array(73,0,759,729),5205=>array(56,0,742,729),5206=>array(56,0,742,928),5207=>array(92,-14,964,729),5208=>array(92,-14,964,729),5209=>array(92,0,964,743),5210=>array(92,0,964,743),5211=>array(92,0,964,928),5212=>array(92,0,964,928),5213=>array(92,0,1003,729),5214=>array(73,0,970,729),5215=>array(92,0,1003,928),5216=>array(73,0,970,928),5217=>array(92,0,986,729),5218=>array(56,0,968,729),5219=>array(92,0,986,928),5220=>array(56,0,968,928),5221=>array(92,0,986,729),5222=>array(60,326,427,733),5223=>array(92,-14,949,734),5224=>array(92,0,949,743),5225=>array(73,0,967,734),5226=>array(56,0,960,734),5227=>array(41,0,651,743),5228=>array(92,0,702,1056),5229=>array(92,0,702,743),5230=>array(92,0,702,928),5231=>array(41,-14,651,729),5232=>array(41,-14,651,928),5233=>array(41,-14,708,927),5234=>array(92,-14,702,729),5235=>array(92,-14,702,928),5236=>array(92,0,937,743),5237=>array(41,0,891,743),5238=>array(92,0,939,743),5239=>array(92,0,891,743),5240=>array(92,0,939,928),5241=>array(92,0,891,928),5242=>array(92,-14,937,729),5243=>array(41,-14,891,729),5244=>array(92,-14,937,928),5245=>array(41,-14,891,928),5246=>array(92,-14,939,729),5247=>array(92,-14,891,729),5248=>array(92,-14,939,928),5249=>array(92,-14,891,928),5250=>array(92,-14,939,729),5251=>array(60,319,445,734),5252=>array(60,319,445,734),5253=>array(41,0,881,743),5254=>array(92,0,881,743),5255=>array(41,-14,881,734),5256=>array(92,-14,881,734),5257=>array(41,0,651,743),5258=>array(92,0,702,1056),5259=>array(92,0,702,743),5260=>array(92,0,702,928),5261=>array(41,-14,651,729),5262=>array(41,-14,651,928),5263=>array(41,-14,714,927),5264=>array(92,-14,702,729),5265=>array(92,-14,702,928),5266=>array(92,0,937,743),5267=>array(41,0,891,743),5268=>array(92,0,988,743),5269=>array(92,0,891,743),5270=>array(92,0,988,928),5271=>array(92,0,891,928),5272=>array(92,-14,937,729),5273=>array(41,-14,891,729),5274=>array(92,-14,937,928),5275=>array(41,-14,891,928),5276=>array(92,-14,988,729),5277=>array(92,-14,891,729),5278=>array(92,-14,988,928),5279=>array(92,-14,891,928),5280=>array(92,-14,988,729),5281=>array(60,319,445,734),5282=>array(60,319,445,734),5283=>array(27,0,535,729),5284=>array(92,0,599,1056),5285=>array(92,0,599,729),5286=>array(92,0,599,928),5287=>array(27,0,535,729),5288=>array(27,0,535,928),5289=>array(27,0,598,927),5290=>array(92,0,599,729),5291=>array(92,0,599,928),5292=>array(92,0,790,729),5293=>array(27,0,771,729),5294=>array(92,0,836,729),5295=>array(92,0,790,729),5296=>array(92,0,836,928),5297=>array(92,0,790,928),5298=>array(92,0,790,729),5299=>array(27,0,790,729),5300=>array(92,0,790,928),5301=>array(27,0,790,928),5302=>array(92,0,836,729),5303=>array(92,0,790,729),5304=>array(92,0,836,928),5305=>array(92,0,790,928),5306=>array(92,0,836,729),5307=>array(60,326,380,734),5308=>array(60,326,492,733),5309=>array(60,326,380,734),5312=>array(84,-14,947,468),5313=>array(41,-14,904,786),5314=>array(41,-14,904,468),5315=>array(41,-14,904,667),5316=>array(27,0,890,482),5317=>array(27,0,890,667),5318=>array(27,0,890,667),5319=>array(41,0,904,482),5320=>array(41,0,904,667),5321=>array(92,-14,1197,468),5322=>array(84,-14,1163,468),5323=>array(92,0,1172,482),5324=>array(41,0,1144,482),5325=>array(92,0,1172,667),5326=>array(41,0,1144,667),5327=>array(41,0,904,667),5328=>array(60,477,604,742),5329=>array(60,319,440,734),5330=>array(60,477,604,742),5331=>array(84,0,947,468),5332=>array(41,0,904,786),5333=>array(41,0,904,468),5334=>array(41,0,904,667),5335=>array(27,0,890,468),5336=>array(27,0,890,667),5337=>array(27,0,890,667),5338=>array(41,0,904,468),5339=>array(41,0,904,667),5340=>array(92,0,1190,468),5341=>array(84,0,1163,468),5342=>array(92,0,1199,468),5343=>array(41,0,1144,468),5344=>array(92,0,1199,667),5345=>array(41,0,1144,667),5346=>array(92,0,1187,468),5347=>array(27,0,1130,468),5348=>array(92,0,1187,667),5349=>array(27,0,1130,667),5350=>array(92,0,1199,468),5351=>array(41,0,1144,468),5352=>array(92,0,1199,667),5353=>array(41,0,1144,667),5354=>array(60,477,604,734),5356=>array(73,0,802,729),5357=>array(41,0,638,729),5358=>array(92,0,736,1056),5359=>array(92,0,689,729),5360=>array(92,0,689,928),5361=>array(41,0,638,729),5362=>array(41,0,638,928),5363=>array(41,0,694,927),5364=>array(92,0,689,729),5365=>array(92,0,689,928),5366=>array(92,0,906,729),5367=>array(41,0,875,729),5368=>array(92,0,926,729),5369=>array(92,0,905,729),5370=>array(92,0,926,928),5371=>array(92,0,905,928),5372=>array(92,0,906,729),5373=>array(41,0,875,729),5374=>array(92,0,906,928),5375=>array(41,0,875,928),5376=>array(92,0,926,729),5377=>array(92,0,905,729),5378=>array(92,0,926,928),5379=>array(92,0,905,928),5380=>array(92,0,926,729),5381=>array(60,326,437,734),5382=>array(60,319,404,742),5383=>array(60,326,437,734),5392=>array(41,-14,882,743),5393=>array(41,-14,882,743),5394=>array(41,-14,882,928),5395=>array(41,-14,1095,482),5396=>array(41,-14,1095,667),5397=>array(41,-14,1095,482),5398=>array(41,-14,1095,667),5399=>array(92,-14,1168,743),5400=>array(41,-14,1118,743),5401=>array(92,-14,1168,743),5402=>array(41,-14,1118,743),5403=>array(92,-14,1168,928),5404=>array(41,-14,1118,928),5405=>array(92,-14,1390,482),5406=>array(41,-14,1336,482),5407=>array(92,-14,1390,667),5408=>array(41,-14,1336,667),5409=>array(92,-14,1390,482),5410=>array(41,-14,1336,482),5411=>array(92,-14,1390,667),5412=>array(41,-14,1336,667),5413=>array(60,469,690,747),5414=>array(84,0,684,729),5415=>array(92,0,692,1056),5416=>array(92,0,692,729),5417=>array(92,0,692,928),5418=>array(84,0,684,729),5419=>array(84,0,684,928),5420=>array(84,0,750,927),5421=>array(92,0,692,729),5422=>array(92,0,692,928),5423=>array(92,0,911,729),5424=>array(84,0,919,729),5425=>array(92,0,929,729),5426=>array(92,0,912,729),5427=>array(92,0,929,928),5428=>array(92,0,912,928),5429=>array(92,0,911,729),5430=>array(84,0,919,729),5431=>array(92,0,911,928),5432=>array(84,0,919,928),5433=>array(92,0,929,729),5434=>array(92,0,912,729),5435=>array(92,0,929,928),5436=>array(92,0,912,928),5437=>array(92,0,929,928),5438=>array(60,326,438,734),5440=>array(60,392,338,670),5441=>array(60,326,454,734),5442=>array(92,-14,949,468),5443=>array(84,-14,941,468),5444=>array(27,0,884,482),5445=>array(92,0,949,786),5446=>array(92,0,949,482),5447=>array(92,0,949,667),5448=>array(92,0,692,729),5449=>array(92,0,692,928),5450=>array(92,0,692,729),5451=>array(41,0,641,729),5452=>array(41,0,641,928),5453=>array(41,0,641,729),5454=>array(92,0,911,928),5455=>array(41,0,875,928),5456=>array(60,326,438,727),5458=>array(73,0,802,729),5459=>array(51,0,769,743),5460=>array(51,-14,769,1056),5461=>array(51,-14,769,729),5462=>array(51,-14,769,928),5463=>array(73,0,844,663),5464=>array(73,0,844,928),5465=>array(84,0,855,663),5466=>array(84,0,855,928),5467=>array(92,0,1099,928),5468=>array(84,0,1058,928),5469=>array(60,311,546,675),5470=>array(92,-14,720,743),5471=>array(92,-14,720,743),5472=>array(92,-14,720,743),5473=>array(92,-14,720,743),5474=>array(92,-14,720,928),5475=>array(92,-14,720,928),5476=>array(54,0,759,729),5477=>array(54,0,759,928),5478=>array(56,0,762,729),5479=>array(56,0,762,928),5480=>array(92,0,1006,928),5481=>array(56,0,968,928),5482=>array(60,326,512,733),5492=>array(41,0,893,743),5493=>array(84,0,936,743),5494=>array(84,0,936,928),5495=>array(41,-14,893,729),5496=>array(41,-14,893,928),5497=>array(84,-14,936,729),5498=>array(84,-14,936,928),5499=>array(60,319,562,734),5500=>array(92,0,745,729),5501=>array(60,326,454,734),5502=>array(60,0,1197,1056),5503=>array(60,0,1197,743),5504=>array(60,0,1197,928),5505=>array(60,-14,1146,729),5506=>array(60,-14,1146,928),5507=>array(60,-14,1197,729),5508=>array(60,-14,1197,928),5509=>array(60,319,939,734),5514=>array(41,0,893,743),5515=>array(84,0,936,743),5516=>array(41,-14,893,729),5517=>array(84,-14,936,729),5518=>array(60,0,1550,1056),5519=>array(60,0,1550,743),5520=>array(60,0,1550,928),5521=>array(60,-14,1203,741),5522=>array(60,-14,1203,928),5523=>array(60,-14,1550,741),5524=>array(60,-14,1550,928),5525=>array(60,335,792,741),5526=>array(60,335,1217,741),5536=>array(41,0,904,709),5537=>array(41,0,904,709),5538=>array(27,-242,890,468),5539=>array(27,-242,890,667),5540=>array(41,-242,904,468),5541=>array(41,-242,904,667),5542=>array(60,344,604,734),5543=>array(84,0,771,729),5544=>array(5,0,692,729),5545=>array(5,0,692,928),5546=>array(84,0,771,729),5547=>array(84,0,771,928),5548=>array(5,0,692,729),5549=>array(5,0,692,928),5550=>array(15,326,438,734),5551=>array(92,-14,702,729),5598=>array(92,0,778,729),5601=>array(52,0,738,729),5702=>array(60,326,439,734),5703=>array(60,240,439,820),5742=>array(10,0,403,306),5743=>array(60,0,1146,743),5744=>array(60,0,1499,743),5745=>array(60,0,1975,743),5746=>array(60,0,1975,928),5747=>array(60,-14,1628,741),5748=>array(60,-14,1586,928),5749=>array(60,-14,1975,741),5750=>array(60,-14,1975,928),5760=>array(-10,219,553,354),5761=>array(-10,-125,646,354),5762=>array(-10,-125,955,354),5763=>array(-10,-125,1264,354),5764=>array(-10,-125,1572,354),5765=>array(-10,-125,1881,354),5766=>array(-10,219,637,697),5767=>array(-10,219,945,697),5768=>array(-10,219,1264,697),5769=>array(-10,219,1569,697),5770=>array(-10,219,1881,697),5771=>array(-10,-125,579,697),5772=>array(-10,-125,888,697),5773=>array(-10,-125,1198,697),5774=>array(-10,-125,1507,697),5775=>array(-10,-125,1817,697),5776=>array(-10,41,646,532),5777=>array(-10,41,955,532),5778=>array(-10,41,1264,532),5779=>array(-10,41,1572,532),5780=>array(-10,41,1881,532),5781=>array(-10,-125,579,697),5782=>array(-10,-125,948,697),5783=>array(-10,-109,798,354),5784=>array(-10,-254,1244,354),5785=>array(-10,219,1569,928),5786=>array(-10,14,750,354),5787=>array(55,-49,648,622),5788=>array(-10,-49,583,622),7424=>array(15,0,637,547),7425=>array(0,0,755,547),7426=>array(43,-14,1000,560),7427=>array(20,0,564,547),7428=>array(43,-14,526,560),7429=>array(84,-1,611,547),7430=>array(20,-1,611,547),7431=>array(92,0,480,547),7432=>array(54,-14,493,560),7433=>array(84,-213,259,547),7434=>array(44,-14,416,547),7435=>array(84,0,684,547),7436=>array(-18,0,499,547),7437=>array(84,0,733,547),7438=>array(84,0,617,547),7439=>array(43,-14,644,560),7440=>array(43,-14,526,560),7441=>array(43,-27,617,573),7442=>array(43,31,617,515),7443=>array(13,-28,653,579),7444=>array(43,-14,1046,560),7446=>array(43,273,644,560),7447=>array(44,-14,646,273),7448=>array(51,0,515,547),7449=>array(21,0,560,547),7450=>array(21,0,560,547),7451=>array(4,0,575,547),7452=>array(84,-14,607,547),7453=>array(85,10,646,560),7454=>array(69,10,857,561),7455=>array(19,-238,651,560),7456=>array(15,0,637,547),7457=>array(35,0,889,547),7458=>array(45,0,534,547),7459=>array(57,-14,581,547),7462=>array(84,0,499,547),7463=>array(15,0,637,547),7464=>array(84,0,607,547),7465=>array(51,0,515,547),7466=>array(84,0,698,547),7467=>array(55,0,648,547),7468=>array(3,326,484,734),7469=>array(0,326,638,734),7470=>array(58,326,436,734),7472=>array(58,326,490,734),7473=>array(58,326,384,734),7474=>array(58,326,384,734),7475=>array(31,318,471,742),7476=>array(58,326,469,734),7477=>array(58,326,176,734),7478=>array(-35,214,176,734),7479=>array(58,326,507,734),7480=>array(58,326,384,734),7481=>array(58,326,569,734),7482=>array(58,326,469,734),7483=>array(58,326,469,734),7484=>array(31,318,504,742),7485=>array(39,318,471,742),7486=>array(58,326,436,734),7487=>array(58,326,473,734),7488=>array(3,326,426,734),7489=>array(58,318,454,734),7490=>array(19,326,675,734),7491=>array(53,318,402,640),7492=>array(53,318,402,640),7493=>array(53,318,423,640),7494=>array(53,318,656,640),7495=>array(53,318,423,751),7496=>array(53,318,423,751),7497=>array(53,318,423,640),7498=>array(53,318,423,640),7499=>array(53,318,330,640),7500=>array(53,318,330,640),7501=>array(53,205,423,639),7502=>array(53,207,164,632),7503=>array(53,326,431,751),7504=>array(53,326,607,640),7505=>array(53,205,399,640),7506=>array(53,318,432,640),7507=>array(53,318,357,640),7508=>array(53,479,432,640),7509=>array(53,318,432,479),7510=>array(53,209,423,640),7511=>array(53,326,332,719),7512=>array(53,318,399,632),7513=>array(53,332,407,640),7514=>array(53,318,607,632),7515=>array(53,326,445,632),7517=>array(53,209,423,759),7518=>array(10,209,420,632),7519=>array(27,318,406,756),7520=>array(41,209,457,635),7521=>array(16,209,391,632),7522=>array(53,0,164,425),7523=>array(54,0,314,313),7524=>array(53,-8,399,306),7525=>array(53,0,445,306),7526=>array(53,-117,423,433),7527=>array(10,-117,420,306),7528=>array(53,-117,423,314),7529=>array(41,-117,457,309),7530=>array(16,-117,391,306),7543=>array(84,-216,671,559),7544=>array(58,326,469,734),7547=>array(84,0,461,547),7549=>array(5,-208,742,560),7557=>array(84,-216,434,760),7579=>array(53,318,423,640),7580=>array(53,318,357,640),7581=>array(53,288,357,640),7582=>array(53,318,432,751),7583=>array(53,318,330,640),7584=>array(53,326,321,751),7585=>array(53,205,292,632),7586=>array(53,205,423,632),7587=>array(53,207,399,632),7588=>array(53,326,291,751),7589=>array(53,326,226,632),7590=>array(53,326,291,632),7591=>array(53,326,291,632),7592=>array(53,205,375,751),7593=>array(53,205,270,751),7594=>array(53,205,274,751),7595=>array(53,326,314,632),7596=>array(53,205,608,640),7597=>array(53,209,607,632),7598=>array(53,205,506,640),7599=>array(53,205,505,640),7600=>array(53,326,393,632),7601=>array(53,318,432,640),7602=>array(53,209,486,751),7603=>array(53,205,366,640),7604=>array(53,205,340,751),7605=>array(53,205,332,719),7606=>array(53,318,527,632),7607=>array(53,298,438,632),7608=>array(53,318,383,632),7609=>array(53,326,395,632),7610=>array(53,326,445,632),7611=>array(53,326,361,632),7612=>array(53,205,468,632),7613=>array(53,288,414,632),7614=>array(53,206,399,632),7615=>array(53,320,370,756),7620=>array(-467,616,-35,800),7621=>array(-467,616,-35,800),7622=>array(-467,616,-35,800),7623=>array(-467,616,-35,800),7624=>array(-513,616,11,800),7625=>array(-513,616,11,800),7680=>array(5,-240,769,729),7681=>array(43,-240,596,560),7682=>array(92,0,692,928),7683=>array(84,-14,671,913),7684=>array(92,-212,692,729),7685=>array(84,-212,671,760),7686=>array(92,-184,692,729),7687=>array(84,-184,671,760),7688=>array(50,-196,670,927),7689=>array(43,-196,526,800),7690=>array(92,0,778,927),7691=>array(45,-14,632,942),7692=>array(92,-212,778,729),7693=>array(45,-212,632,760),7694=>array(92,-184,778,729),7695=>array(45,-184,632,760),7696=>array(92,-192,778,729),7697=>array(45,-196,632,760),7698=>array(92,-240,778,729),7699=>array(45,-240,632,760),7700=>array(92,0,610,1057),7701=>array(43,-14,630,927),7702=>array(92,0,610,1057),7703=>array(43,-14,630,927),7704=>array(92,-203,610,729),7705=>array(43,-203,630,560),7706=>array(92,-195,610,729),7707=>array(43,-195,630,560),7708=>array(92,-196,610,927),7709=>array(43,-196,630,784),7710=>array(92,0,599,928),7711=>array(19,0,444,942),7712=>array(50,-14,747,901),7713=>array(45,-216,632,760),7714=>array(92,0,745,928),7715=>array(84,0,634,913),7716=>array(92,-212,745,729),7717=>array(84,-212,634,760),7718=>array(92,0,745,927),7719=>array(23,0,634,927),7720=>array(45,-196,745,729),7721=>array(38,-196,634,760),7722=>array(92,-236,745,729),7723=>array(84,-236,634,760),7724=>array(16,-195,355,729),7725=>array(1,-195,341,760),7726=>array(40,0,378,1057),7727=>array(16,0,354,917),7728=>array(92,0,805,927),7729=>array(84,0,684,982),7730=>array(92,-212,805,729),7731=>array(84,-212,684,760),7732=>array(92,-184,805,729),7733=>array(84,-184,684,760),7734=>array(92,-212,610,729),7735=>array(83,-212,259,760),7736=>array(32,-212,610,942),7737=>array(18,-212,325,914),7738=>array(92,-184,610,729),7739=>array(20,-184,328,760),7740=>array(92,-240,610,729),7741=>array(-13,-240,355,760),7742=>array(92,0,903,927),7743=>array(83,0,963,800),7744=>array(92,0,903,928),7745=>array(83,0,963,760),7746=>array(92,-212,903,729),7747=>array(83,-212,963,560),7748=>array(92,0,745,928),7749=>array(84,0,634,760),7750=>array(92,-212,745,729),7751=>array(84,-212,634,560),7752=>array(92,-184,745,729),7753=>array(84,-184,634,560),7754=>array(92,-240,745,729),7755=>array(84,-240,634,560),7756=>array(50,-14,800,1057),7757=>array(43,-14,644,916),7758=>array(50,-14,800,1043),7759=>array(43,-14,644,900),7760=>array(50,-14,800,1057),7761=>array(43,-14,644,927),7762=>array(50,-14,800,1057),7763=>array(43,-14,644,927),7764=>array(92,0,692,927),7765=>array(84,-208,671,800),7766=>array(92,0,692,928),7767=>array(84,-208,671,760),7768=>array(92,0,750,928),7769=>array(84,0,490,760),7770=>array(92,-212,750,729),7771=>array(83,-212,490,560),7772=>array(92,-212,750,914),7773=>array(83,-212,490,759),7774=>array(92,-184,750,729),7775=>array(33,-184,490,560),7776=>array(72,-14,647,928),7777=>array(52,-14,548,760),7778=>array(72,-212,647,742),7779=>array(52,-212,548,560),7780=>array(72,-14,647,928),7781=>array(52,-14,548,816),7782=>array(72,-14,647,1053),7783=>array(52,-14,548,1002),7784=>array(72,-212,647,928),7785=>array(52,-212,548,762),7786=>array(5,0,677,927),7787=>array(13,0,455,942),7788=>array(5,-212,677,729),7789=>array(13,-212,455,702),7790=>array(5,-184,677,729),7791=>array(13,-184,455,702),7792=>array(5,-240,677,729),7793=>array(13,-240,455,702),7794=>array(92,-212,720,729),7795=>array(78,-212,628,547),7796=>array(92,-196,720,729),7797=>array(78,-195,628,547),7798=>array(92,-203,720,729),7799=>array(78,-203,628,547),7800=>array(92,-14,720,1057),7801=>array(78,-14,628,916),7802=>array(92,-14,720,1043),7803=>array(78,-14,628,887),7804=>array(5,0,769,928),7805=>array(15,0,637,778),7806=>array(5,-212,769,729),7807=>array(15,-212,637,547),7808=>array(30,0,1072,931),7809=>array(35,0,889,803),7810=>array(30,0,1072,931),7811=>array(35,0,889,803),7812=>array(30,0,1072,927),7813=>array(35,0,889,774),7814=>array(30,0,1072,927),7815=>array(35,0,889,760),7816=>array(30,-212,1072,729),7817=>array(35,-212,889,547),7818=>array(19,0,751,928),7819=>array(15,0,630,760),7820=>array(19,0,751,927),7821=>array(15,0,630,774),7822=>array(-10,0,734,928),7823=>array(12,-216,634,760),7824=>array(45,0,680,927),7825=>array(45,0,534,798),7826=>array(45,-212,680,729),7827=>array(45,-212,534,547),7828=>array(45,-184,680,729),7829=>array(45,-184,534,547),7830=>array(84,-184,634,760),7831=>array(13,0,455,927),7832=>array(35,0,889,888),7833=>array(12,-216,634,888),7834=>array(43,-14,758,760),7835=>array(19,0,444,942),7836=>array(-18,0,444,760),7837=>array(19,0,444,760),7838=>array(92,-14,823,743),7839=>array(43,-14,645,768),7840=>array(5,-212,769,729),7841=>array(43,-212,596,560),7842=>array(5,0,769,1025),7843=>array(43,-14,596,843),7844=>array(5,0,769,1054),7845=>array(43,-14,652,873),7846=>array(5,0,769,1054),7847=>array(43,-14,597,874),7848=>array(5,0,769,1093),7849=>array(43,-14,672,912),7850=>array(5,0,769,1068),7851=>array(43,-14,596,887),7852=>array(5,-212,769,927),7853=>array(43,-212,596,800),7854=>array(5,0,769,1057),7855=>array(43,-14,596,891),7856=>array(5,0,769,1057),7857=>array(43,-14,596,894),7858=>array(5,0,769,1123),7859=>array(43,-14,596,959),7860=>array(5,0,769,1068),7861=>array(43,-14,596,905),7862=>array(5,-212,769,935),7863=>array(43,-212,596,780),7864=>array(92,-212,610,729),7865=>array(43,-212,630,560),7866=>array(92,0,610,1025),7867=>array(43,-14,630,843),7868=>array(92,0,610,928),7869=>array(43,-14,630,778),7870=>array(92,0,684,1054),7871=>array(43,-14,688,873),7872=>array(92,0,621,1054),7873=>array(43,-14,630,874),7874=>array(92,0,686,1093),7875=>array(43,-14,681,912),7876=>array(92,0,610,1068),7877=>array(43,-14,630,887),7878=>array(92,-212,610,927),7879=>array(43,-212,630,800),7880=>array(66,0,313,1025),7881=>array(52,0,300,842),7882=>array(92,-212,280,729),7883=>array(83,-212,259,760),7884=>array(50,-212,800,742),7885=>array(43,-212,644,560),7886=>array(50,-14,800,1025),7887=>array(43,-14,644,843),7888=>array(50,-14,800,1054),7889=>array(43,-14,679,873),7890=>array(50,-14,800,1054),7891=>array(43,-14,644,874),7892=>array(50,-14,800,1093),7893=>array(43,-14,685,912),7894=>array(50,-14,800,1068),7895=>array(43,-14,644,887),7896=>array(50,-212,800,927),7897=>array(43,-212,644,800),7898=>array(53,-14,854,927),7899=>array(46,-14,708,800),7900=>array(53,-14,854,927),7901=>array(46,-14,708,800),7902=>array(53,-14,854,1025),7903=>array(46,-14,708,843),7904=>array(53,-14,854,928),7905=>array(46,-14,708,778),7906=>array(53,-212,854,761),7907=>array(46,-212,708,609),7908=>array(92,-212,720,729),7909=>array(78,-212,628,547),7910=>array(92,-14,720,1025),7911=>array(78,-14,628,843),7912=>array(91,-14,833,927),7913=>array(75,-14,733,800),7914=>array(91,-14,833,927),7915=>array(75,-14,733,800),7916=>array(91,-14,833,1025),7917=>array(75,-14,733,843),7918=>array(91,-14,833,928),7919=>array(75,-14,733,778),7920=>array(91,-212,833,761),7921=>array(75,-212,733,609),7922=>array(-10,0,734,931),7923=>array(12,-216,634,803),7924=>array(-10,-212,734,729),7925=>array(12,-216,634,547),7926=>array(-10,0,734,1029),7927=>array(12,-216,634,843),7928=>array(-10,0,734,928),7929=>array(12,-216,634,778),7930=>array(92,0,925,729),7931=>array(9,0,635,760),7936=>array(48,-13,645,785),7937=>array(48,-13,645,785),7938=>array(48,-13,645,800),7939=>array(48,-13,645,800),7940=>array(48,-13,645,800),7941=>array(48,-13,645,800),7942=>array(48,-13,645,928),7943=>array(48,-13,645,928),7944=>array(5,0,769,785),7945=>array(5,0,769,785),7946=>array(2,0,1036,800),7947=>array(3,0,1039,800),7948=>array(1,0,930,800),7949=>array(2,0,958,800),7950=>array(4,0,831,928),7951=>array(3,0,854,928),7952=>array(54,-14,493,785),7953=>array(54,-14,493,785),7954=>array(54,-14,498,800),7955=>array(54,-14,493,800),7956=>array(54,-14,531,800),7957=>array(54,-14,516,800),7960=>array(3,0,718,785),7961=>array(4,0,721,785),7962=>array(2,0,1026,800),7963=>array(3,0,1023,800),7964=>array(1,0,950,800),7965=>array(2,0,979,800),7968=>array(84,-208,634,785),7969=>array(84,-208,634,785),7970=>array(84,-208,634,800),7971=>array(84,-208,634,800),7972=>array(84,-208,634,800),7973=>array(84,-208,634,800),7974=>array(84,-208,634,928),7975=>array(84,-208,634,928),7976=>array(3,0,854,785),7977=>array(4,0,859,785),7978=>array(2,0,1159,800),7979=>array(3,0,1158,800),7980=>array(1,0,1088,800),7981=>array(2,0,1114,800),7982=>array(4,0,962,928),7983=>array(3,0,971,928),7984=>array(78,-19,348,785),7985=>array(78,-19,348,785),7986=>array(-27,-19,407,800),7987=>array(-58,-19,376,800),7988=>array(31,-19,446,800),7989=>array(-6,-19,438,800),7990=>array(-2,-19,348,928),7991=>array(-5,-19,348,928),7992=>array(3,0,391,785),7993=>array(4,0,397,785),7994=>array(2,0,685,800),7995=>array(3,0,693,800),7996=>array(1,0,620,800),7997=>array(2,0,646,800),7998=>array(4,0,512,928),7999=>array(3,0,512,928),8000=>array(43,-14,644,785),8001=>array(43,-14,644,785),8002=>array(43,-14,644,800),8003=>array(43,-14,644,800),8004=>array(43,-14,644,800),8005=>array(43,-14,644,800),8008=>array(3,-14,841,785),8009=>array(4,-14,883,785),8010=>array(2,-14,1171,800),8011=>array(3,-14,1173,800),8012=>array(1,-14,1002,800),8013=>array(2,-14,1032,800),8016=>array(78,-10,629,785),8017=>array(78,-10,629,785),8018=>array(78,-10,629,800),8019=>array(78,-10,629,800),8020=>array(78,-10,629,800),8021=>array(78,-10,629,800),8022=>array(78,-10,629,928),8023=>array(78,-10,629,928),8025=>array(4,0,940,785),8027=>array(3,0,1194,800),8029=>array(2,0,1208,800),8031=>array(3,0,1059,928),8032=>array(43,-13,826,785),8033=>array(43,-13,826,785),8034=>array(43,-13,826,800),8035=>array(43,-13,826,800),8036=>array(43,-13,826,800),8037=>array(43,-13,826,800),8038=>array(43,-13,826,928),8039=>array(43,-13,826,928),8040=>array(3,0,881,785),8041=>array(4,0,931,785),8042=>array(2,0,1219,800),8043=>array(3,-3,1224,800),8044=>array(1,0,1048,800),8045=>array(2,0,1078,800),8046=>array(4,0,1000,928),8047=>array(3,0,1048,928),8048=>array(48,-13,645,800),8049=>array(48,-13,645,800),8050=>array(54,-14,493,800),8051=>array(54,-14,493,800),8052=>array(84,-208,634,800),8053=>array(84,-208,634,800),8054=>array(-26,-19,348,800),8055=>array(77,-19,353,800),8056=>array(43,-14,644,800),8057=>array(43,-14,644,800),8058=>array(78,-10,629,800),8059=>array(78,-10,629,800),8060=>array(43,-13,826,800),8061=>array(43,-13,826,800),8064=>array(48,-208,645,785),8065=>array(48,-208,645,785),8066=>array(48,-208,645,800),8067=>array(48,-208,645,800),8068=>array(48,-208,645,800),8069=>array(48,-208,645,800),8070=>array(48,-208,645,928),8071=>array(48,-208,645,928),8072=>array(5,-208,769,785),8073=>array(5,-208,769,785),8074=>array(2,-208,1036,800),8075=>array(3,-208,1039,800),8076=>array(1,-208,930,800),8077=>array(2,-208,958,800),8078=>array(4,-208,831,928),8079=>array(3,-208,854,928),8080=>array(84,-208,634,785),8081=>array(84,-208,634,785),8082=>array(84,-208,634,800),8083=>array(84,-208,634,800),8084=>array(84,-208,634,800),8085=>array(84,-208,634,800),8086=>array(84,-208,634,928),8087=>array(84,-208,634,928),8088=>array(3,-208,854,785),8089=>array(4,-208,859,785),8090=>array(2,-208,1159,800),8091=>array(3,-208,1158,800),8092=>array(1,-208,1088,800),8093=>array(2,-208,1114,800),8094=>array(4,-208,962,928),8095=>array(3,-208,971,928),8096=>array(43,-208,826,785),8097=>array(43,-208,826,785),8098=>array(43,-208,826,800),8099=>array(43,-208,826,800),8100=>array(43,-208,826,800),8101=>array(43,-208,826,800),8102=>array(43,-208,826,928),8103=>array(43,-208,826,928),8104=>array(3,-208,881,785),8105=>array(4,-208,931,785),8106=>array(2,-208,1219,800),8107=>array(3,-208,1224,800),8108=>array(1,-208,1048,800),8109=>array(2,-208,1078,800),8110=>array(4,-208,1000,928),8111=>array(3,-208,1048,928),8112=>array(48,-13,645,784),8113=>array(48,-13,645,760),8114=>array(48,-208,645,800),8115=>array(48,-208,645,559),8116=>array(48,-208,645,800),8118=>array(48,-13,645,778),8119=>array(48,-208,645,778),8120=>array(5,0,769,927),8121=>array(5,0,769,914),8122=>array(-1,0,872,800),8123=>array(26,0,792,800),8124=>array(5,-208,769,729),8125=>array(183,595,317,785),8126=>array(202,-208,333,-45),8127=>array(183,595,317,785),8128=>array(80,638,420,778),8129=>array(80,654,420,928),8130=>array(84,-208,634,800),8131=>array(84,-208,634,560),8132=>array(84,-208,634,800),8134=>array(84,-208,634,778),8135=>array(84,-208,634,778),8136=>array(-1,0,856,800),8137=>array(-24,0,771,800),8138=>array(-1,0,988,800),8139=>array(-18,0,915,800),8140=>array(92,-208,745,729),8141=>array(34,595,468,800),8142=>array(63,595,478,800),8143=>array(80,595,420,928),8144=>array(3,-19,348,784),8145=>array(20,-19,348,760),8146=>array(-36,-19,348,978),8147=>array(23,-19,372,978),8150=>array(4,-19,348,778),8151=>array(-6,-19,348,928),8152=>array(21,0,350,927),8153=>array(32,0,339,914),8154=>array(-1,0,529,800),8155=>array(-21,0,450,800),8157=>array(40,595,474,800),8158=>array(45,595,489,800),8159=>array(80,595,420,928),8160=>array(78,-10,629,784),8161=>array(78,-10,629,760),8162=>array(78,-10,629,978),8163=>array(78,-10,629,978),8164=>array(84,-208,671,785),8165=>array(84,-208,671,785),8166=>array(78,-10,629,778),8167=>array(78,-10,629,928),8168=>array(-10,0,734,927),8169=>array(-10,0,734,914),8170=>array(-1,0,1030,800),8171=>array(-27,0,992,800),8172=>array(4,0,797,785),8173=>array(46,654,404,978),8174=>array(96,654,445,978),8175=>array(46,616,322,800),8178=>array(43,-208,826,800),8179=>array(43,-208,826,547),8180=>array(43,-208,826,800),8182=>array(43,-13,826,778),8183=>array(43,-208,826,778),8184=>array(-1,-14,1015,800),8185=>array(-19,-14,836,800),8186=>array(-1,0,1057,800),8187=>array(-30,0,867,800),8188=>array(27,-208,823,742),8189=>array(178,616,454,800),8190=>array(183,595,317,785),8208=>array(54,217,361,359),8209=>array(54,217,361,359),8210=>array(54,211,642,337),8211=>array(54,211,446,337),8212=>array(54,211,946,337),8213=>array(0,211,1000,337),8214=>array(127,-236,399,764),8215=>array(0,-236,500,-9),8216=>array(103,418,318,729),8217=>array(63,418,278,729),8218=>array(72,-122,287,189),8219=>array(63,418,278,729),8220=>array(103,418,565,729),8221=>array(92,418,554,729),8222=>array(72,-122,534,189),8223=>array(92,418,554,729),8224=>array(26,-96,470,729),8225=>array(25,-96,470,729),8226=>array(144,196,495,547),8227=>array(144,157,534,586),8228=>array(79,0,255,189),8229=>array(79,0,588,189),8230=>array(79,0,921,189),8231=>array(86,253,262,442),8240=>array(32,-14,1417,742),8241=>array(32,-14,1864,742),8242=>array(20,547,240,729),8243=>array(20,547,423,729),8244=>array(20,547,606,729),8245=>array(20,547,240,729),8246=>array(20,547,425,729),8247=>array(20,547,606,729),8248=>array(101,-238,632,29),8249=>array(77,67,318,519),8250=>array(94,67,335,519),8251=>array(72,0,900,829),8252=>array(69,0,558,729),8253=>array(69,0,515,742),8254=>array(0,663,500,755),8255=>array(-31,-237,859,-79),8256=>array(-31,769,859,927),8257=>array(-52,-235,296,231),8258=>array(20,-37,1003,832),8259=>array(96,220,404,358),8260=>array(-199,-14,366,742),8261=>array(86,-132,389,760),8262=>array(68,-132,371,760),8263=>array(34,0,996,742),8264=>array(69,0,760,742),8265=>array(69,0,760,742),8266=>array(49,-125,464,546),8267=>array(93,-96,579,729),8268=>array(75,189,425,541),8269=>array(75,189,425,541),8270=>array(20,0,503,464),8271=>array(104,-142,329,547),8272=>array(-31,-237,859,927),8273=>array(53,-14,439,797),8274=>array(30,-93,529,729),8275=>array(49,212,951,415),8276=>array(-31,-240,859,-82),8277=>array(152,98,686,631),8278=>array(110,93,574,645),8279=>array(20,547,789,729),8280=>array(76,21,762,708),8281=>array(126,71,712,657),8282=>array(102,0,280,729),8283=>array(49,-170,822,898),8284=>array(55,0,783,729),8285=>array(102,0,278,683),8286=>array(102,0,278,683),8304=>array(29,319,398,742),8305=>array(53,326,164,751),8308=>array(27,326,397,734),8309=>array(47,319,384,734),8310=>array(38,319,394,742),8311=>array(41,326,378,734),8312=>array(38,319,389,742),8313=>array(32,319,388,742),8314=>array(67,326,461,677),8315=>array(67,469,461,534),8316=>array(67,407,461,596),8317=>array(54,252,237,751),8318=>array(50,252,234,751),8319=>array(54,326,406,640),8320=>array(29,-7,398,416),8321=>array(60,0,382,408),8322=>array(53,0,382,416),8323=>array(44,-7,384,416),8324=>array(27,0,397,408),8325=>array(47,-7,384,408),8326=>array(38,-7,394,416),8327=>array(41,0,378,408),8328=>array(38,-7,389,416),8329=>array(32,-7,388,416),8330=>array(67,0,461,351),8331=>array(67,143,461,208),8332=>array(67,81,461,270),8333=>array(54,-74,237,425),8334=>array(50,-74,234,425),8336=>array(53,-8,402,313),8337=>array(53,-8,423,313),8338=>array(53,-8,432,313),8339=>array(10,0,403,306),8340=>array(53,-8,423,313),8341=>array(54,0,406,425),8342=>array(53,0,431,425),8343=>array(54,0,166,425),8344=>array(53,0,607,313),8345=>array(54,0,406,313),8346=>array(53,-117,423,313),8347=>array(33,-8,351,313),8348=>array(53,0,332,393),8352=>array(38,0,892,729),8353=>array(50,-44,634,778),8354=>array(29,-14,667,742),8355=>array(75,0,663,729),8356=>array(61,0,613,742),8357=>array(83,-93,963,640),8358=>array(43,0,794,729),8359=>array(92,-14,1470,729),8360=>array(92,-14,1157,729),8361=>array(13,0,1088,729),8362=>array(39,-14,859,729),8363=>array(30,-182,692,760),8364=>array(-19,-14,629,742),8365=>array(29,0,695,729),8366=>array(12,0,684,729),8367=>array(92,-223,1247,742),8368=>array(14,-14,648,742),8369=>array(34,0,696,729),8370=>array(50,-81,643,809),8371=>array(5,0,691,729),8372=>array(43,-14,816,742),8373=>array(72,-147,629,760),8376=>array(12,0,684,729),8377=>array(50,0,647,729),8378=>array(5,0,745,729),8400=>array(-498,628,-26,760),8401=>array(-470,628,1,760),8406=>array(-470,560,-26,760),8407=>array(-470,560,-26,760),8411=>array(-501,654,-1,774),8412=>array(-595,654,99,774),8417=>array(-470,560,-26,760),8448=>array(20,-24,1083,752),8449=>array(20,-24,1137,752),8450=>array(50,-14,670,742),8451=>array(87,-14,1147,749),8452=>array(64,0,832,729),8453=>array(20,-24,1064,752),8454=>array(20,-24,1117,752),8455=>array(67,-14,616,742),8456=>array(64,-146,684,611),8457=>array(87,0,1002,749),8459=>array(36,-14,1063,746),8460=>array(6,-125,809,747),8461=>array(100,0,788,729),8462=>array(31,0,654,760),8463=>array(10,0,625,760),8464=>array(36,-14,533,742),8465=>array(52,-14,659,743),8466=>array(37,-14,787,742),8467=>array(-14,-14,401,742),8468=>array(9,-14,936,760),8469=>array(92,0,745,729),8470=>array(34,0,1154,729),8471=>array(138,0,862,725),8472=>array(54,-221,658,495),8473=>array(92,0,709,729),8474=>array(50,-146,800,742),8475=>array(31,-14,904,768),8476=>array(41,-14,803,743),8477=>array(98,0,793,729),8478=>array(37,0,859,729),8479=>array(81,-112,694,887),8480=>array(127,444,792,731),8481=>array(3,0,1249,547),8482=>array(144,447,790,729),8483=>array(11,-113,729,885),8484=>array(45,0,709,729),8485=>array(26,-230,540,777),8486=>array(27,0,823,742),8487=>array(27,-14,823,728),8488=>array(-5,-159,670,729),8489=>array(1,0,271,566),8490=>array(92,0,805,729),8491=>array(5,0,769,928),8492=>array(41,-1,853,772),8493=>array(63,-19,767,742),8494=>array(61,-12,793,647),8495=>array(41,-14,591,533),8496=>array(72,-14,668,742),8497=>array(37,-14,860,773),8498=>array(92,0,599,729),8499=>array(38,-18,1156,751),8500=>array(29,-12,436,420),8501=>array(50,-14,761,742),8502=>array(19,-14,687,742),8503=>array(31,-35,439,742),8504=>array(63,-41,633,742),8505=>array(34,0,355,760),8506=>array(44,-27,932,723),8507=>array(69,0,1352,547),8508=>array(34,-14,765,547),8509=>array(-40,-208,700,561),8510=>array(92,0,627,729),8511=>array(92,0,771,729),8512=>array(12,-192,820,719),8513=>array(25,-14,723,742),8514=>array(9,0,527,729),8515=>array(43,0,561,729),8516=>array(0,0,744,729),8517=>array(21,0,786,729),8518=>array(34,-14,752,760),8519=>array(33,-14,635,560),8520=>array(15,0,353,760),8521=>array(-143,-216,354,760),8523=>array(41,-14,811,742),8526=>array(55,0,470,547),8528=>array(49,-14,983,742),8529=>array(49,-14,993,742),8530=>array(49,-14,1441,742),8531=>array(49,-14,989,742),8532=>array(53,-14,989,742),8533=>array(49,-14,989,742),8534=>array(53,-14,989,742),8535=>array(44,-14,989,742),8536=>array(27,-14,989,742),8537=>array(49,-14,999,742),8538=>array(47,-14,999,742),8539=>array(49,-14,994,742),8540=>array(44,-14,994,742),8541=>array(47,-14,994,742),8542=>array(41,-14,994,742),8543=>array(49,-14,814,742),8544=>array(92,0,280,729),8545=>array(92,0,566,729),8546=>array(92,0,853,729),8547=>array(92,0,1094,729),8548=>array(5,0,769,729),8549=>array(5,0,1007,729),8550=>array(5,0,1293,729),8551=>array(5,0,1580,729),8552=>array(92,0,1101,729),8553=>array(19,0,751,729),8554=>array(19,0,1028,729),8555=>array(19,0,1314,729),8556=>array(92,0,610,729),8557=>array(50,-14,670,742),8558=>array(92,0,778,729),8559=>array(92,0,903,729),8560=>array(84,0,259,760),8561=>array(84,0,523,760),8562=>array(84,0,788,760),8563=>array(84,0,946,760),8564=>array(15,0,637,547),8565=>array(15,0,878,760),8566=>array(15,0,1143,760),8567=>array(15,0,1407,760),8568=>array(84,0,954,760),8569=>array(15,0,630,547),8570=>array(15,0,885,760),8571=>array(15,0,1149,760),8572=>array(84,0,259,760),8573=>array(43,-14,526,560),8574=>array(45,-14,632,760),8575=>array(83,0,963,560),8576=>array(52,0,1236,729),8577=>array(92,0,778,729),8578=>array(52,0,1236,729),8579=>array(50,-14,670,742),8580=>array(43,-14,526,560),8581=>array(50,-208,670,742),8585=>array(29,-14,989,742),8592=>array(49,87,781,540),8593=>array(193,0,646,732),8594=>array(57,87,789,540),8595=>array(193,-3,646,729),8596=>array(49,87,789,540),8597=>array(193,-3,646,732),8598=>array(136,66,720,650),8599=>array(136,66,720,650),8600=>array(136,66,720,650),8601=>array(136,66,720,650),8602=>array(49,87,781,540),8603=>array(57,87,789,540),8604=>array(13,84,833,431),8605=>array(5,84,825,431),8606=>array(49,87,781,540),8607=>array(189,0,641,732),8608=>array(57,87,789,540),8609=>array(194,-3,646,729),8610=>array(49,87,793,540),8611=>array(45,87,789,540),8612=>array(49,87,781,540),8613=>array(193,0,646,732),8614=>array(57,87,789,540),8615=>array(193,0,646,732),8616=>array(193,0,646,732),8617=>array(49,87,781,565),8618=>array(57,87,789,565),8619=>array(49,87,781,565),8620=>array(57,87,789,565),8621=>array(49,87,789,540),8622=>array(49,86,789,541),8623=>array(123,-4,714,733),8624=>array(169,0,646,755),8625=>array(192,0,669,755),8626=>array(169,-26,646,729),8627=>array(192,-26,669,729),8628=>array(233,-3,772,621),8629=>array(49,87,673,626),8630=>array(11,198,816,685),8631=>array(22,198,828,685),8632=>array(118,13,788,729),8633=>array(49,-108,789,735),8634=>array(86,45,767,691),8635=>array(71,45,751,691),8636=>array(49,255,781,540),8637=>array(49,87,781,372),8638=>array(361,0,646,732),8639=>array(193,0,478,732),8640=>array(57,255,789,540),8641=>array(57,87,789,372),8642=>array(361,0,646,732),8643=>array(193,0,478,732),8644=>array(49,-59,789,686),8645=>array(47,-3,792,732),8646=>array(49,-59,789,686),8647=>array(49,-59,781,686),8648=>array(46,0,792,732),8649=>array(57,-59,789,686),8650=>array(46,-3,792,729),8651=>array(49,-5,789,632),8652=>array(49,-5,789,632),8653=>array(49,87,781,540),8654=>array(49,87,789,540),8655=>array(57,87,789,540),8656=>array(49,87,781,540),8657=>array(193,0,645,732),8658=>array(57,87,789,540),8659=>array(193,-3,645,729),8660=>array(49,87,789,540),8661=>array(193,-8,645,732),8662=>array(132,-26,755,596),8663=>array(88,-26,711,597),8664=>array(88,16,711,639),8665=>array(132,16,755,639),8666=>array(49,87,781,540),8667=>array(57,87,789,540),8668=>array(44,87,776,540),8669=>array(57,87,789,540),8670=>array(193,0,646,732),8671=>array(193,-3,646,729),8672=>array(49,87,781,540),8673=>array(193,0,646,732),8674=>array(57,87,789,540),8675=>array(193,-3,646,729),8676=>array(49,87,781,540),8677=>array(57,87,789,540),8678=>array(27,46,781,581),8679=>array(151,0,687,754),8680=>array(35,46,789,581),8681=>array(151,-25,687,729),8682=>array(151,0,687,754),8683=>array(151,0,687,754),8684=>array(151,0,687,754),8685=>array(151,0,687,754),8686=>array(151,0,687,754),8687=>array(151,0,687,754),8688=>array(35,46,789,581),8689=>array(60,0,788,729),8690=>array(60,0,788,729),8691=>array(151,-25,687,754),8692=>array(57,87,789,540),8693=>array(47,-3,792,732),8694=>array(57,-223,789,850),8695=>array(49,87,781,540),8696=>array(57,87,789,540),8697=>array(49,87,789,540),8698=>array(49,87,781,540),8699=>array(57,87,789,540),8700=>array(49,87,789,540),8701=>array(27,96,781,531),8702=>array(57,96,811,531),8703=>array(27,96,811,531),8704=>array(5,0,769,729),8705=>array(48,-14,629,742),8706=>array(29,-14,515,674),8707=>array(92,0,610,729),8708=>array(92,-46,610,775),8709=>array(47,-15,810,715),8710=>array(0,0,697,719),8711=>array(0,0,697,719),8712=>array(73,-2,824,730),8713=>array(73,-46,824,775),8714=>array(106,58,644,568),8715=>array(73,-2,824,730),8716=>array(73,-46,824,775),8717=>array(106,58,644,568),8718=>array(98,0,539,553),8719=>array(73,-192,712,719),8720=>array(73,-193,712,718),8721=>array(20,-192,697,719),8722=>array(106,256,732,371),8723=>array(106,0,732,627),8724=>array(49,0,647,729),8725=>array(0,-93,365,729),8726=>array(165,-49,530,772),8727=>array(118,0,720,626),8728=>array(150,151,475,477),8729=>array(102,253,278,442),8730=>array(37,-20,669,837),8731=>array(37,-20,669,933),8732=>array(36,-20,669,924),8733=>array(92,89,617,505),8734=>array(92,89,741,505),8735=>array(106,67,732,693),8736=>array(77,0,820,729),8737=>array(77,-44,820,729),8738=>array(116,-0,732,726),8739=>array(207,-207,322,773),8740=>array(48,-207,482,773),8741=>array(112,-207,417,773),8742=>array(48,-207,482,773),8743=>array(151,0,661,579),8744=>array(151,0,661,579),8745=>array(151,0,661,579),8746=>array(151,0,661,579),8747=>array(15,-227,548,754),8748=>array(15,-227,914,754),8749=>array(15,-227,1280,754),8750=>array(14,-227,548,754),8751=>array(38,-227,938,754),8752=>array(23,-227,1290,754),8753=>array(15,-227,616,754),8754=>array(14,-227,600,754),8755=>array(14,-227,588,754),8756=>array(60,78,637,647),8757=>array(60,78,637,647),8758=>array(59,79,235,647),8759=>array(60,78,637,647),8760=>array(106,256,732,631),8761=>array(106,45,800,584),8762=>array(106,-4,732,631),8763=>array(106,-34,732,660),8764=>array(106,212,732,415),8765=>array(106,212,732,415),8766=>array(65,131,772,497),8767=>array(106,42,732,584),8768=>array(85,0,289,626),8769=>array(106,76,732,551),8770=>array(106,110,732,482),8771=>array(106,144,732,517),8772=>array(106,0,732,637),8773=>array(106,37,732,628),8774=>array(106,-31,732,628),8775=>array(106,-86,732,726),8776=>array(106,110,732,517),8777=>array(106,8,732,614),8778=>array(106,37,732,628),8779=>array(106,-13,732,628),8780=>array(106,37,732,628),8781=>array(105,105,732,585),8782=>array(106,26,732,656),8783=>array(106,172,732,656),8784=>array(106,144,732,744),8785=>array(106,-117,732,743),8786=>array(105,-92,732,719),8787=>array(104,-92,731,719),8788=>array(98,102,965,520),8789=>array(96,102,966,520),8790=>array(106,144,732,482),8791=>array(106,144,732,839),8792=>array(106,144,732,704),8793=>array(106,144,732,840),8794=>array(106,144,732,840),8795=>array(106,144,732,959),8796=>array(106,144,732,952),8797=>array(106,144,732,762),8798=>array(106,144,732,786),8799=>array(106,144,732,903),8800=>array(106,-5,732,631),8801=>array(106,38,732,588),8802=>array(106,-69,732,695),8803=>array(106,-74,732,700),8804=>array(106,0,732,582),8805=>array(106,0,732,582),8806=>array(106,-106,732,617),8807=>array(106,-106,732,617),8808=>array(106,-185,732,617),8809=>array(106,-185,732,617),8810=>array(72,-34,974,660),8811=>array(72,-34,974,660),8812=>array(86,-132,414,759),8813=>array(105,-10,732,700),8814=>array(106,-4,732,690),8815=>array(106,-63,732,631),8816=>array(106,-112,732,645),8817=>array(106,-112,732,645),8818=>array(106,-84,732,582),8819=>array(106,-84,732,582),8820=>array(106,-112,732,645),8821=>array(106,-112,732,645),8822=>array(102,-119,732,678),8823=>array(102,-119,732,678),8824=>array(102,-221,732,779),8825=>array(102,-221,732,779),8826=>array(106,-55,732,681),8827=>array(106,-55,732,681),8828=>array(106,-177,732,684),8829=>array(106,-177,732,684),8830=>array(106,-132,732,684),8831=>array(106,-132,732,684),8832=>array(106,-89,732,781),8833=>array(106,-89,732,781),8834=>array(99,67,739,559),8835=>array(99,65,739,559),8836=>array(99,-96,739,726),8837=>array(99,-100,739,722),8838=>array(99,0,739,636),8839=>array(99,0,739,635),8840=>array(99,-124,739,759),8841=>array(99,-124,739,759),8842=>array(99,-97,739,636),8843=>array(99,-97,739,635),8844=>array(151,0,661,579),8845=>array(151,0,661,579),8846=>array(151,0,661,579),8847=>array(106,0,732,584),8848=>array(106,0,732,584),8849=>array(106,-115,732,667),8850=>array(106,-115,732,667),8851=>array(106,0,690,626),8852=>array(106,0,690,626),8853=>array(91,-14,747,643),8854=>array(91,-14,747,643),8855=>array(91,-14,747,643),8856=>array(91,-13,747,642),8857=>array(91,-14,747,643),8858=>array(91,-14,747,643),8859=>array(91,-14,747,643),8860=>array(91,-14,747,643),8861=>array(91,-14,747,643),8862=>array(77,-29,761,657),8863=>array(77,-29,761,657),8864=>array(77,-29,761,657),8865=>array(77,-29,761,657),8866=>array(85,0,829,705),8867=>array(85,0,829,705),8868=>array(85,0,829,705),8869=>array(85,0,829,705),8870=>array(85,0,457,705),8871=>array(85,0,457,705),8872=>array(85,0,829,705),8873=>array(85,0,829,705),8874=>array(85,0,829,705),8875=>array(85,0,829,705),8876=>array(85,-100,829,805),8877=>array(85,-100,829,805),8878=>array(85,-100,829,805),8879=>array(85,-100,829,805),8880=>array(106,-54,724,681),8881=>array(114,-54,732,681),8882=>array(106,-1,732,628),8883=>array(106,-1,732,628),8884=>array(106,-80,732,706),8885=>array(106,-80,732,706),8886=>array(60,151,940,477),8887=>array(60,151,940,477),8888=>array(60,151,778,477),8889=>array(43,-63,794,689),8890=>array(63,0,480,705),8891=>array(103,0,709,759),8892=>array(103,0,709,759),8893=>array(103,0,709,759),8894=>array(106,0,732,626),8895=>array(106,0,732,626),8896=>array(0,-192,843,719),8897=>array(0,-192,843,719),8898=>array(48,-192,794,719),8899=>array(48,-192,794,719),8900=>array(3,-233,491,807),8901=>array(102,253,278,442),8902=>array(83,112,543,549),8903=>array(106,-56,732,683),8904=>array(106,-48,894,674),8905=>array(106,-48,894,675),8906=>array(106,-48,894,675),8907=>array(106,-48,894,675),8908=>array(106,-48,894,675),8909=>array(106,144,732,517),8910=>array(49,0,763,579),8911=>array(49,0,763,579),8912=>array(93,-22,732,649),8913=>array(106,-22,745,649),8914=>array(83,0,755,639),8915=>array(83,-14,755,625),8916=>array(186,0,652,729),8917=>array(106,-100,732,729),8918=>array(106,30,732,597),8919=>array(106,30,732,597),8920=>array(72,-34,1350,660),8921=>array(72,-34,1350,660),8922=>array(106,-211,732,837),8923=>array(106,-211,732,837),8924=>array(106,0,732,582),8925=>array(106,0,732,582),8926=>array(106,-177,732,684),8927=>array(106,-177,732,684),8928=>array(106,-197,732,808),8929=>array(106,-263,732,742),8930=>array(106,-191,732,817),8931=>array(106,-191,732,817),8932=>array(106,-146,732,636),8933=>array(106,-146,732,636),8934=>array(106,-168,732,582),8935=>array(106,-168,732,582),8936=>array(106,-216,732,684),8937=>array(106,-216,732,684),8938=>array(106,-138,732,808),8939=>array(106,-138,732,808),8940=>array(106,-224,732,894),8941=>array(106,-224,732,894),8942=>array(412,-40,588,735),8943=>array(79,253,921,442),8944=>array(79,-40,921,735),8945=>array(79,-40,921,735),8946=>array(72,-2,1085,730),8947=>array(73,-2,824,730),8948=>array(106,58,644,568),8949=>array(73,-2,824,984),8950=>array(73,-2,824,919),8951=>array(106,58,644,741),8952=>array(73,-207,824,730),8953=>array(73,-2,824,730),8954=>array(72,-2,1085,730),8955=>array(73,-2,824,730),8956=>array(106,58,644,568),8957=>array(72,-2,824,919),8958=>array(106,58,644,741),8959=>array(106,0,791,732),8960=>array(31,-22,572,519),8961=>array(56,152,540,453),8962=>array(64,0,651,596),8963=>array(193,470,646,732),8964=>array(193,0,646,263),8965=>array(193,-12,646,423),8966=>array(193,-12,646,552),8967=>array(139,-39,349,798),8968=>array(86,-132,389,760),8969=>array(68,-132,371,760),8970=>array(86,-132,389,760),8971=>array(68,-132,371,760),8972=>array(352,-77,759,331),8973=>array(49,-77,457,331),8974=>array(352,226,759,634),8975=>array(49,226,457,634),8976=>array(106,140,732,444),8977=>array(3,113,536,646),8984=>array(84,0,843,759),8985=>array(106,140,732,444),8988=>array(86,425,403,760),8989=>array(65,425,383,760),8990=>array(86,-126,403,208),8991=>array(65,-126,383,208),8992=>array(235,-250,586,926),8993=>array(22,-240,373,940),8996=>array(76,215,1076,575),8997=>array(76,0,1076,575),8998=>array(76,0,1414,760),8999=>array(76,0,1076,760),9000=>array(59,0,1385,729),9003=>array(0,0,1338,760),9004=>array(73,-91,800,748),9075=>array(78,-19,348,547),9076=>array(84,-208,671,562),9077=>array(43,-13,826,547),9082=>array(48,-13,645,559),9085=>array(13,-228,850,99),9095=>array(76,0,1100,743),9108=>array(17,0,856,727),9115=>array(63,-252,438,928),9116=>array(63,-252,205,940),9117=>array(63,-240,438,940),9118=>array(63,-252,438,928),9119=>array(295,-252,438,940),9120=>array(63,-240,438,940),9121=>array(63,-252,438,928),9122=>array(63,-252,205,940),9123=>array(63,-240,438,940),9124=>array(63,-252,438,928),9125=>array(295,-252,438,940),9126=>array(63,-240,438,940),9127=>array(306,-261,668,928),9128=>array(82,-247,444,934),9129=>array(306,-240,668,934),9130=>array(306,-256,444,934),9131=>array(82,-261,444,928),9132=>array(306,-247,668,934),9133=>array(82,-240,444,934),9134=>array(235,-250,373,940),9166=>array(27,46,781,729),9167=>array(91,0,854,596),9187=>array(73,-91,800,748),9189=>array(3,75,766,444),9192=>array(39,-129,665,294),9250=>array(-81,-14,671,760),9251=>array(64,-228,651,99),9312=>array(59,-15,788,715),9313=>array(59,-15,788,715),9314=>array(59,-15,788,715),9315=>array(59,-15,788,715),9316=>array(59,-15,788,715),9317=>array(59,-15,788,715),9318=>array(59,-15,788,715),9319=>array(59,-15,788,715),9320=>array(59,-15,788,715),9321=>array(59,-15,788,715),9600=>array(-10,260,779,770),9601=>array(-10,-250,779,-123),9602=>array(-10,-250,779,-5),9603=>array(-10,-250,779,132),9604=>array(-10,-250,779,260),9605=>array(-10,-250,779,387),9606=>array(-10,-250,779,515),9607=>array(-10,-250,779,642),9608=>array(-10,-250,779,770),9609=>array(-10,-250,680,770),9610=>array(-10,-250,582,770),9611=>array(-10,-250,483,770),9612=>array(-10,-250,384,770),9613=>array(-10,-250,286,770),9614=>array(-10,-250,187,770),9615=>array(-10,-250,88,770),9616=>array(384,-250,778,770),9617=>array(-10,-250,680,770),9618=>array(-10,-250,779,770),9619=>array(-10,-250,779,770),9620=>array(-10,642,779,770),9621=>array(680,-250,778,770),9622=>array(-10,-250,385,260),9623=>array(384,-250,779,260),9624=>array(-10,260,385,770),9625=>array(-10,-250,779,770),9626=>array(-10,-250,779,770),9627=>array(-10,-250,779,770),9628=>array(-10,-250,779,770),9629=>array(384,260,779,770),9630=>array(-10,-250,779,770),9631=>array(-10,-250,779,770),9632=>array(91,-124,854,643),9633=>array(91,-124,854,643),9634=>array(91,-124,854,643),9635=>array(91,-124,854,643),9636=>array(91,-124,854,643),9637=>array(91,-124,854,643),9638=>array(91,-124,854,643),9639=>array(91,-124,854,643),9640=>array(91,-124,854,643),9641=>array(91,-124,854,643),9642=>array(91,11,587,509),9643=>array(91,11,587,509),9644=>array(91,75,854,444),9645=>array(91,75,854,444),9646=>array(91,-122,459,642),9647=>array(91,-122,459,642),9648=>array(3,75,766,444),9649=>array(3,75,766,444),9650=>array(3,-124,766,643),9651=>array(3,-124,766,643),9652=>array(3,11,499,509),9653=>array(3,11,499,509),9654=>array(3,-124,766,643),9655=>array(3,-124,766,643),9656=>array(3,11,499,509),9657=>array(3,11,499,509),9658=>array(3,11,766,509),9659=>array(3,11,766,509),9660=>array(3,-124,766,643),9661=>array(3,-124,766,643),9662=>array(3,11,499,509),9663=>array(3,11,499,509),9664=>array(3,-124,766,643),9665=>array(3,-124,766,643),9666=>array(3,11,499,509),9667=>array(3,11,499,509),9668=>array(3,11,766,509),9669=>array(3,11,766,509),9670=>array(3,-124,766,643),9671=>array(3,-124,766,643),9672=>array(3,-124,766,643),9673=>array(55,-125,818,645),9674=>array(3,-233,491,807),9675=>array(55,-125,818,645),9676=>array(56,-125,817,644),9677=>array(55,-125,818,645),9678=>array(55,-125,818,645),9679=>array(55,-123,818,641),9680=>array(55,-123,818,641),9681=>array(55,-123,818,641),9682=>array(55,-123,818,641),9683=>array(55,-123,818,641),9684=>array(55,-123,818,641),9685=>array(55,-123,818,641),9686=>array(55,-125,436,645),9687=>array(91,-125,472,645),9688=>array(91,-10,750,770),9689=>array(91,-250,879,770),9690=>array(91,260,879,770),9691=>array(91,-250,879,260),9692=>array(3,260,385,645),9693=>array(3,260,384,645),9694=>array(3,-125,384,260),9695=>array(3,-125,385,260),9696=>array(3,260,766,645),9697=>array(3,-125,766,260),9698=>array(3,-124,766,643),9699=>array(3,-124,766,643),9700=>array(3,-124,766,643),9701=>array(3,-124,766,643),9702=>array(144,196,495,547),9703=>array(91,-124,854,643),9704=>array(91,-124,854,643),9705=>array(91,-124,854,643),9706=>array(91,-124,854,643),9707=>array(91,-124,854,643),9708=>array(3,-124,766,643),9709=>array(3,-124,766,643),9710=>array(3,-124,766,643),9711=>array(55,-250,1064,770),9712=>array(91,-124,854,643),9713=>array(91,-124,854,643),9714=>array(91,-124,854,643),9715=>array(91,-124,854,643),9716=>array(55,-123,818,641),9717=>array(55,-123,818,641),9718=>array(55,-123,818,641),9719=>array(55,-123,818,641),9720=>array(3,-124,766,643),9721=>array(3,-124,766,643),9722=>array(3,-124,766,643),9723=>array(91,-66,739,585),9724=>array(91,-66,739,585),9725=>array(91,-17,642,537),9726=>array(91,-17,642,537),9727=>array(3,-124,766,643),9728=>array(83,0,813,729),9729=>array(51,-2,949,360),9730=>array(49,0,848,729),9731=>array(83,-0,813,927),9732=>array(64,0,833,880),9733=>array(65,-4,832,723),9734=>array(65,-4,832,723),9735=>array(83,2,490,729),9736=>array(83,0,813,731),9737=>array(83,0,813,730),9738=>array(61,0,828,727),9739=>array(61,0,828,723),9740=>array(61,-1,610,722),9741=>array(61,0,952,723),9742=>array(68,0,1177,729),9743=>array(71,0,1180,729),9744=>array(90,0,807,729),9745=>array(89,0,808,729),9746=>array(89,0,808,729),9747=>array(75,78,457,656),9748=>array(49,0,870,933),9749=>array(74,0,822,731),9750=>array(84,0,813,731),9751=>array(84,0,813,727),9752=>array(78,0,819,729),9753=>array(83,140,813,574),9754=>array(84,113,813,569),9755=>array(84,113,813,569),9756=>array(87,104,810,569),9757=>array(72,0,537,724),9758=>array(86,103,810,569),9759=>array(72,-3,537,720),9760=>array(61,0,835,730),9761=>array(84,0,813,730),9762=>array(83,0,813,730),9763=>array(49,0,848,730),9764=>array(49,-2,620,727),9765=>array(83,0,663,731),9766=>array(83,-1,566,731),9767=>array(83,0,701,911),9768=>array(83,0,462,730),9769=>array(83,-1,813,729),9770=>array(87,0,810,730),9771=>array(83,0,814,731),9772=>array(83,0,627,731),9773=>array(83,0,813,730),9774=>array(83,0,813,730),9775=>array(83,0,813,730),9776=>array(83,0,813,729),9777=>array(83,0,814,729),9778=>array(83,0,813,729),9779=>array(83,0,813,729),9780=>array(83,0,813,729),9781=>array(83,0,813,729),9782=>array(83,0,813,729),9783=>array(83,0,813,729),9784=>array(80,3,817,721),9785=>array(83,-73,959,804),9786=>array(83,-73,959,804),9787=>array(83,-73,959,804),9788=>array(83,0,813,730),9789=>array(358,0,814,730),9790=>array(83,0,539,730),9791=>array(85,-102,528,732),9792=>array(85,-125,647,731),9793=>array(85,-14,647,843),9794=>array(79,-14,831,720),9795=>array(166,0,730,730),9796=>array(219,0,677,730),9797=>array(121,0,774,730),9798=>array(127,0,769,730),9799=>array(240,0,656,730),9800=>array(45,0,851,731),9801=>array(89,0,807,730),9802=>array(94,0,802,731),9803=>array(113,31,784,679),9804=>array(140,0,756,730),9805=>array(53,-180,843,730),9806=>array(83,52,813,653),9807=>array(34,-96,863,730),9808=>array(83,-0,813,730),9809=>array(94,0,802,730),9810=>array(86,153,810,579),9811=>array(157,0,739,730),9812=>array(98,0,798,730),9813=>array(110,0,786,730),9814=>array(167,-1,729,729),9815=>array(214,0,683,730),9816=>array(165,0,732,730),9817=>array(148,-0,748,730),9818=>array(98,0,798,730),9819=>array(110,0,786,730),9820=>array(167,-1,729,729),9821=>array(214,0,683,730),9822=>array(162,0,734,730),9823=>array(148,-0,748,730),9824=>array(158,0,738,729),9825=>array(90,0,806,727),9826=>array(168,0,728,729),9827=>array(111,0,785,729),9828=>array(157,0,739,729),9829=>array(89,0,808,729),9830=>array(168,0,728,729),9831=>array(111,0,785,732),9832=>array(105,-1,791,729),9833=>array(84,-5,339,729),9834=>array(84,-5,554,729),9835=>array(184,-102,712,729),9836=>array(92,-5,804,729),9837=>array(88,-3,392,731),9838=>array(84,0,273,731),9839=>array(84,0,400,731),9840=>array(84,0,664,731),9841=>array(64,0,701,731),9842=>array(84,0,813,709),9843=>array(76,16,820,731),9844=>array(76,16,820,731),9845=>array(76,16,820,731),9846=>array(76,16,820,731),9847=>array(76,16,820,731),9848=>array(76,16,820,731),9849=>array(76,16,820,731),9850=>array(76,16,820,731),9851=>array(84,0,812,704),9852=>array(83,0,814,731),9853=>array(83,0,814,731),9854=>array(83,0,814,731),9855=>array(149,1,747,731),9856=>array(73,0,797,725),9857=>array(73,0,797,725),9858=>array(73,0,797,725),9859=>array(73,0,797,725),9860=>array(73,0,797,725),9861=>array(73,0,797,725),9862=>array(83,0,813,731),9863=>array(83,0,813,731),9864=>array(83,0,813,731),9865=>array(83,0,813,731),9866=>array(83,0,813,98),9867=>array(83,0,813,98),9868=>array(83,0,813,413),9869=>array(83,0,813,413),9870=>array(83,0,813,413),9871=>array(83,0,813,413),9872=>array(168,3,728,731),9873=>array(168,3,728,731),9874=>array(52,0,844,731),9875=>array(97,-10,799,732),9876=>array(131,0,765,729),9877=>array(61,-10,479,732),9878=>array(59,-10,837,732),9879=>array(61,0,835,732),9880=>array(145,0,750,732),9881=>array(95,-17,802,727),9882=>array(128,-9,768,733),9883=>array(127,0,769,728),9884=>array(127,0,769,729),9888=>array(49,0,848,729),9889=>array(83,2,619,730),9890=>array(85,-125,919,731),9891=>array(79,-206,1023,720),9892=>array(85,-186,1109,856),9893=>array(85,-125,837,917),9894=>array(131,-14,727,869),9895=>array(101,-170,741,884),9896=>array(188,-14,650,869),9897=>array(4,133,829,596),9898=>array(188,133,650,597),9899=>array(188,133,650,597),9900=>array(249,194,589,536),9901=>array(175,194,663,536),9902=>array(41,169,797,560),9903=>array(5,194,833,536),9904=>array(103,237,757,540),9905=>array(211,42,626,698),9906=>array(85,-125,647,731),9907=>array(168,-125,646,731),9908=>array(86,-125,646,731),9909=>array(86,-125,646,731),9910=>array(59,-118,791,643),9911=>array(194,-104,595,710),9912=>array(158,-125,543,731),9920=>array(42,4,796,553),9921=>array(42,4,796,724),9922=>array(42,4,796,553),9923=>array(42,4,796,724),9954=>array(85,-14,647,843),9985=>array(11,190,803,635),9986=>array(42,141,784,588),9987=>array(11,94,803,539),9988=>array(36,119,824,613),9990=>array(42,-14,796,742),9991=>array(42,-14,796,742),9992=>array(59,21,782,708),9993=>array(64,107,773,622),9996=>array(212,0,561,742),9997=>array(21,83,802,678),9998=>array(89,75,724,710),9999=>array(26,198,819,530),10000=>array(89,75,724,710),10001=>array(43,185,757,544),10002=>array(67,209,757,520),10003=>array(150,97,667,630),10004=>array(116,87,721,631),10005=>array(126,72,711,657),10006=>array(85,31,752,698),10007=>array(118,-9,701,732),10008=>array(123,0,754,739),10009=>array(55,0,783,729),10010=>array(55,0,783,729),10011=>array(55,0,783,729),10012=>array(55,0,783,729),10013=>array(165,0,673,729),10014=>array(131,0,678,729),10015=>array(155,0,683,729),10016=>array(55,0,783,729),10017=>array(91,-13,747,744),10018=>array(41,-14,797,742),10019=>array(42,-12,796,742),10020=>array(41,-14,797,742),10021=>array(41,-13,797,743),10022=>array(42,-14,796,745),10023=>array(42,-14,796,745),10025=>array(23,-9,814,743),10026=>array(42,-14,796,742),10027=>array(23,-9,814,743),10028=>array(23,-9,814,743),10029=>array(23,-9,814,743),10030=>array(23,-9,814,743),10031=>array(23,-9,814,743),10032=>array(24,12,815,714),10033=>array(64,0,773,729),10034=>array(74,0,764,729),10035=>array(55,0,783,729),10036=>array(31,-14,787,742),10037=>array(41,-14,797,742),10038=>array(91,-14,747,742),10039=>array(41,-14,797,742),10040=>array(41,-14,797,742),10041=>array(41,-14,797,742),10042=>array(55,0,783,729),10043=>array(82,-14,756,742),10044=>array(82,-14,756,742),10045=>array(84,-14,753,742),10046=>array(79,-14,759,742),10047=>array(54,0,784,709),10048=>array(54,0,784,709),10049=>array(41,-14,797,742),10050=>array(42,-14,796,742),10051=>array(79,-14,759,742),10052=>array(89,0,749,729),10053=>array(76,0,762,729),10054=>array(63,2,773,729),10055=>array(79,-13,759,742),10056=>array(47,-13,791,730),10057=>array(47,-13,791,730),10058=>array(41,-13,797,743),10059=>array(41,-13,797,743),10061=>array(50,-10,847,738),10063=>array(60,-49,837,729),10064=>array(60,0,837,777),10065=>array(60,-49,837,729),10066=>array(60,0,837,777),10070=>array(83,-2,813,728),10072=>array(377,-240,460,760),10073=>array(336,-240,502,760),10074=>array(253,-240,585,760),10075=>array(85,395,288,729),10076=>array(59,395,262,729),10077=>array(85,395,528,729),10078=>array(59,395,502,729),10081=>array(155,-93,772,851),10082=>array(202,-17,636,742),10083=>array(163,-17,675,742),10084=>array(54,83,784,645),10085=>array(168,-1,729,729),10086=>array(62,21,724,702),10087=>array(78,169,759,564),10088=>array(196,-139,648,769),10089=>array(196,-139,648,769),10090=>array(264,-132,574,758),10091=>array(264,-132,574,758),10092=>array(215,-240,607,760),10093=>array(232,-240,623,760),10094=>array(142,-240,685,760),10095=>array(153,-240,696,760),10096=>array(167,-240,656,760),10097=>array(183,-240,672,760),10098=>array(346,-241,535,760),10099=>array(303,-241,492,760),10100=>array(175,-163,634,760),10101=>array(204,-163,663,760),10102=>array(59,-15,788,715),10103=>array(59,-15,788,715),10104=>array(59,-15,788,715),10105=>array(59,-15,788,715),10106=>array(59,-15,788,715),10107=>array(59,-15,788,715),10108=>array(59,-15,788,715),10109=>array(59,-15,788,715),10110=>array(59,-15,788,715),10111=>array(59,-15,788,715),10112=>array(4,-52,833,780),10113=>array(4,-52,833,780),10114=>array(4,-52,833,780),10115=>array(4,-52,833,780),10116=>array(4,-52,833,780),10117=>array(4,-52,833,780),10118=>array(4,-52,833,780),10119=>array(4,-52,833,780),10120=>array(4,-52,833,780),10121=>array(4,-52,833,780),10122=>array(4,-52,833,780),10123=>array(4,-52,833,780),10124=>array(4,-52,833,780),10125=>array(4,-52,833,780),10126=>array(4,-52,833,780),10127=>array(4,-52,833,780),10128=>array(4,-52,833,780),10129=>array(4,-52,833,780),10130=>array(4,-52,833,780),10131=>array(4,-52,833,780),10132=>array(57,75,789,552),10136=>array(123,55,682,614),10137=>array(57,100,789,527),10138=>array(123,13,682,572),10139=>array(57,129,789,498),10140=>array(57,57,764,570),10141=>array(57,100,789,527),10142=>array(57,100,789,527),10143=>array(57,100,789,527),10144=>array(57,100,789,527),10145=>array(57,46,811,581),10146=>array(111,94,789,533),10147=>array(111,94,789,533),10148=>array(111,-4,789,631),10149=>array(57,100,789,548),10150=>array(57,79,789,527),10151=>array(240,-7,606,634),10152=>array(57,100,789,527),10153=>array(57,75,765,552),10154=>array(57,75,765,552),10155=>array(21,12,794,586),10156=>array(21,12,794,586),10157=>array(135,0,774,574),10158=>array(135,0,774,574),10159=>array(62,49,799,574),10161=>array(62,49,799,574),10162=>array(154,-20,721,585),10163=>array(63,157,789,470),10164=>array(81,55,682,655),10165=>array(57,173,789,454),10166=>array(82,-29,682,572),10167=>array(82,55,682,655),10168=>array(57,172,789,455),10169=>array(82,-28,682,572),10170=>array(56,84,789,543),10171=>array(73,140,779,487),10172=>array(79,167,774,460),10173=>array(79,118,774,509),10174=>array(57,81,789,546),10181=>array(54,-163,405,769),10182=>array(52,-163,403,769),10208=>array(3,-233,491,807),10214=>array(86,-132,419,760),10215=>array(86,-132,419,760),10216=>array(104,-132,377,759),10217=>array(80,-132,353,759),10218=>array(104,-132,641,759),10219=>array(80,-132,616,759),10224=>array(41,0,797,732),10225=>array(42,-3,798,729),10226=>array(9,45,816,685),10227=>array(22,45,830,685),10228=>array(57,-14,1108,643),10229=>array(49,87,1376,540),10230=>array(57,87,1385,540),10231=>array(49,87,1385,540),10232=>array(49,87,1376,540),10233=>array(57,87,1385,540),10234=>array(49,87,1385,540),10235=>array(49,87,1376,540),10236=>array(57,87,1385,540),10237=>array(49,87,1376,540),10238=>array(57,87,1385,540),10239=>array(57,87,1385,540),10241=>array(146,586,342,781),10242=>array(146,325,342,521),10243=>array(146,325,342,781),10244=>array(146,65,342,261),10245=>array(146,65,342,781),10246=>array(146,65,342,521),10247=>array(146,65,342,781),10248=>array(439,586,635,781),10249=>array(146,586,635,781),10250=>array(146,325,635,781),10251=>array(146,325,635,781),10252=>array(146,65,635,781),10253=>array(146,65,635,781),10254=>array(146,65,635,781),10255=>array(146,65,635,781),10256=>array(439,325,635,521),10257=>array(146,325,635,781),10258=>array(146,325,635,521),10259=>array(146,325,635,781),10260=>array(146,65,635,521),10261=>array(146,65,635,781),10262=>array(146,65,635,521),10263=>array(146,65,635,781),10264=>array(439,325,635,781),10265=>array(146,325,635,781),10266=>array(146,325,635,781),10267=>array(146,325,635,781),10268=>array(146,65,635,781),10269=>array(146,65,635,781),10270=>array(146,65,635,781),10271=>array(146,65,635,781),10272=>array(439,65,635,261),10273=>array(146,65,635,781),10274=>array(146,65,635,521),10275=>array(146,65,635,781),10276=>array(146,65,635,261),10277=>array(146,65,635,781),10278=>array(146,65,635,521),10279=>array(146,65,635,781),10280=>array(439,65,635,781),10281=>array(146,65,635,781),10282=>array(146,65,635,781),10283=>array(146,65,635,781),10284=>array(146,65,635,781),10285=>array(146,65,635,781),10286=>array(146,65,635,781),10287=>array(146,65,635,781),10288=>array(439,65,635,521),10289=>array(146,65,635,781),10290=>array(146,65,635,521),10291=>array(146,65,635,781),10292=>array(146,65,635,521),10293=>array(146,65,635,781),10294=>array(146,65,635,521),10295=>array(146,65,635,781),10296=>array(439,65,635,781),10297=>array(146,65,635,781),10298=>array(146,65,635,781),10299=>array(146,65,635,781),10300=>array(146,65,635,781),10301=>array(146,65,635,781),10302=>array(146,65,635,781),10303=>array(146,65,635,781),10304=>array(146,-195,342,0),10305=>array(146,-195,342,781),10306=>array(146,-195,342,521),10307=>array(146,-195,342,781),10308=>array(146,-195,342,261),10309=>array(146,-195,342,781),10310=>array(146,-195,342,521),10311=>array(146,-195,342,781),10312=>array(146,-195,635,781),10313=>array(146,-195,635,781),10314=>array(146,-195,635,781),10315=>array(146,-195,635,781),10316=>array(146,-195,635,781),10317=>array(146,-195,635,781),10318=>array(146,-195,635,781),10319=>array(146,-195,635,781),10320=>array(146,-195,635,521),10321=>array(146,-195,635,781),10322=>array(146,-195,635,521),10323=>array(146,-195,635,781),10324=>array(146,-195,635,521),10325=>array(146,-195,635,781),10326=>array(146,-195,635,521),10327=>array(146,-195,635,781),10328=>array(146,-195,635,781),10329=>array(146,-195,635,781),10330=>array(146,-195,635,781),10331=>array(146,-195,635,781),10332=>array(146,-195,635,781),10333=>array(146,-195,635,781),10334=>array(146,-195,635,781),10335=>array(146,-195,635,781),10336=>array(146,-195,635,261),10337=>array(146,-195,635,781),10338=>array(146,-195,635,521),10339=>array(146,-195,635,781),10340=>array(146,-195,635,261),10341=>array(146,-195,635,781),10342=>array(146,-195,635,521),10343=>array(146,-195,635,781),10344=>array(146,-195,635,781),10345=>array(146,-195,635,781),10346=>array(146,-195,635,781),10347=>array(146,-195,635,781),10348=>array(146,-195,635,781),10349=>array(146,-195,635,781),10350=>array(146,-195,635,781),10351=>array(146,-195,635,781),10352=>array(146,-195,635,521),10353=>array(146,-195,635,781),10354=>array(146,-195,635,521),10355=>array(146,-195,635,781),10356=>array(146,-195,635,521),10357=>array(146,-195,635,781),10358=>array(146,-195,635,521),10359=>array(146,-195,635,781),10360=>array(146,-195,635,781),10361=>array(146,-195,635,781),10362=>array(146,-195,635,781),10363=>array(146,-195,635,781),10364=>array(146,-195,635,781),10365=>array(146,-195,635,781),10366=>array(146,-195,635,781),10367=>array(146,-195,635,781),10368=>array(439,-195,635,0),10369=>array(146,-195,635,781),10370=>array(146,-195,635,521),10371=>array(146,-195,635,781),10372=>array(146,-195,635,261),10373=>array(146,-195,635,781),10374=>array(146,-195,635,521),10375=>array(146,-195,635,781),10376=>array(439,-195,635,781),10377=>array(146,-195,635,781),10378=>array(146,-195,635,781),10379=>array(146,-195,635,781),10380=>array(146,-195,635,781),10381=>array(146,-195,635,781),10382=>array(146,-195,635,781),10383=>array(146,-195,635,781),10384=>array(439,-195,635,521),10385=>array(146,-195,635,781),10386=>array(146,-195,635,521),10387=>array(146,-195,635,781),10388=>array(146,-195,635,521),10389=>array(146,-195,635,781),10390=>array(146,-195,635,521),10391=>array(146,-195,635,781),10392=>array(439,-195,635,781),10393=>array(146,-195,635,781),10394=>array(146,-195,635,781),10395=>array(146,-195,635,781),10396=>array(146,-195,635,781),10397=>array(146,-195,635,781),10398=>array(146,-195,635,781),10399=>array(146,-195,635,781),10400=>array(439,-195,635,261),10401=>array(146,-195,635,781),10402=>array(146,-195,635,521),10403=>array(146,-195,635,781),10404=>array(146,-195,635,261),10405=>array(146,-195,635,781),10406=>array(146,-195,635,521),10407=>array(146,-195,635,781),10408=>array(439,-195,635,781),10409=>array(146,-195,635,781),10410=>array(146,-195,635,781),10411=>array(146,-195,635,781),10412=>array(146,-195,635,781),10413=>array(146,-195,635,781),10414=>array(146,-195,635,781),10415=>array(146,-195,635,781),10416=>array(439,-195,635,521),10417=>array(146,-195,635,781),10418=>array(146,-195,635,521),10419=>array(146,-195,635,781),10420=>array(146,-195,635,521),10421=>array(146,-195,635,781),10422=>array(146,-195,635,521),10423=>array(146,-195,635,781),10424=>array(439,-195,635,781),10425=>array(146,-195,635,781),10426=>array(146,-195,635,781),10427=>array(146,-195,635,781),10428=>array(146,-195,635,781),10429=>array(146,-195,635,781),10430=>array(146,-195,635,781),10431=>array(146,-195,635,781),10432=>array(146,-195,635,0),10433=>array(146,-195,635,781),10434=>array(146,-195,635,521),10435=>array(146,-195,635,781),10436=>array(146,-195,635,261),10437=>array(146,-195,635,781),10438=>array(146,-195,635,521),10439=>array(146,-195,635,781),10440=>array(146,-195,635,781),10441=>array(146,-195,635,781),10442=>array(146,-195,635,781),10443=>array(146,-195,635,781),10444=>array(146,-195,635,781),10445=>array(146,-195,635,781),10446=>array(146,-195,635,781),10447=>array(146,-195,635,781),10448=>array(146,-195,635,521),10449=>array(146,-195,635,781),10450=>array(146,-195,635,521),10451=>array(146,-195,635,781),10452=>array(146,-195,635,521),10453=>array(146,-195,635,781),10454=>array(146,-195,635,521),10455=>array(146,-195,635,781),10456=>array(146,-195,635,781),10457=>array(146,-195,635,781),10458=>array(146,-195,635,781),10459=>array(146,-195,635,781),10460=>array(146,-195,635,781),10461=>array(146,-195,635,781),10462=>array(146,-195,635,781),10463=>array(146,-195,635,781),10464=>array(146,-195,635,261),10465=>array(146,-195,635,781),10466=>array(146,-195,635,521),10467=>array(146,-195,635,781),10468=>array(146,-195,635,261),10469=>array(146,-195,635,781),10470=>array(146,-195,635,521),10471=>array(146,-195,635,781),10472=>array(146,-195,635,781),10473=>array(146,-195,635,781),10474=>array(146,-195,635,781),10475=>array(146,-195,635,781),10476=>array(146,-195,635,781),10477=>array(146,-195,635,781),10478=>array(146,-195,635,781),10479=>array(146,-195,635,781),10480=>array(146,-195,635,521),10481=>array(146,-195,635,781),10482=>array(146,-195,635,521),10483=>array(146,-195,635,781),10484=>array(146,-195,635,521),10485=>array(146,-195,635,781),10486=>array(146,-195,635,521),10487=>array(146,-195,635,781),10488=>array(146,-195,635,781),10489=>array(146,-195,635,781),10490=>array(146,-195,635,781),10491=>array(146,-195,635,781),10492=>array(146,-195,635,781),10493=>array(146,-195,635,781),10494=>array(146,-195,635,781),10495=>array(146,-195,635,781),10502=>array(49,87,781,540),10503=>array(57,87,789,540),10506=>array(132,0,707,732),10507=>array(132,0,707,732),10560=>array(86,45,726,853),10561=>array(86,45,726,853),10627=>array(125,-163,628,760),10628=>array(125,-163,628,760),10702=>array(106,-258,732,800),10703=>array(106,-1,940,628),10704=>array(106,-1,940,628),10705=>array(106,-48,894,674),10706=>array(106,-48,894,674),10707=>array(106,-48,894,674),10708=>array(106,-48,894,675),10709=>array(106,-48,894,675),10731=>array(3,-233,491,807),10746=>array(106,0,732,627),10747=>array(106,0,732,627),10752=>array(28,-211,972,734),10753=>array(28,-211,972,734),10754=>array(28,-211,972,734),10764=>array(15,-227,1646,754),10765=>array(14,-227,548,754),10766=>array(14,-227,548,754),10767=>array(14,-227,548,754),10768=>array(14,-227,548,754),10769=>array(14,-227,576,754),10770=>array(14,-227,548,754),10771=>array(14,-227,548,754),10772=>array(14,-228,651,754),10773=>array(14,-227,548,754),10774=>array(14,-227,548,754),10775=>array(-30,-227,556,754),10776=>array(14,-227,548,754),10777=>array(14,-227,548,754),10778=>array(14,-227,548,754),10779=>array(15,-227,548,898),10780=>array(15,-372,548,754),10799=>array(125,20,713,607),10858=>array(106,212,732,660),10859=>array(106,-34,732,660),10877=>array(106,-150,732,632),10878=>array(106,-150,732,632),10879=>array(106,-150,732,632),10880=>array(106,-150,732,632),10881=>array(106,-150,732,688),10882=>array(106,-150,732,688),10883=>array(106,-150,732,827),10884=>array(106,-150,732,827),10885=>array(106,-217,732,630),10886=>array(106,-217,732,630),10887=>array(106,-124,732,582),10888=>array(106,-124,732,582),10889=>array(106,-281,732,630),10890=>array(106,-281,732,630),10891=>array(106,-303,732,814),10892=>array(106,-303,732,814),10893=>array(106,-183,732,653),10894=>array(106,-183,732,653),10895=>array(106,-245,732,765),10896=>array(106,-245,732,765),10897=>array(106,-278,732,782),10898=>array(106,-278,732,782),10899=>array(106,-263,732,771),10900=>array(106,-263,732,771),10901=>array(106,-50,732,733),10902=>array(106,-50,732,733),10903=>array(106,-50,732,733),10904=>array(106,-50,732,733),10905=>array(106,-45,732,678),10906=>array(106,-45,732,678),10907=>array(106,-81,732,724),10908=>array(106,-81,732,724),10909=>array(106,13,732,680),10910=>array(106,13,732,680),10911=>array(106,-239,732,746),10912=>array(106,-239,732,746),10926=>array(106,22,732,656),10927=>array(106,-83,732,684),10928=>array(106,-83,732,684),10929=>array(106,-246,732,684),10930=>array(106,-246,732,684),10931=>array(106,-205,732,672),10932=>array(106,-205,732,672),10933=>array(106,-304,732,672),10934=>array(106,-304,732,672),10935=>array(106,-252,732,713),10936=>array(106,-252,732,713),10937=>array(106,-316,732,713),10938=>array(106,-316,732,713),11001=>array(106,-195,732,609),11002=>array(106,-195,732,609),11008=>array(123,-23,744,598),11009=>array(94,-23,715,598),11010=>array(123,-23,744,598),11011=>array(94,-23,715,598),11012=>array(27,46,789,581),11013=>array(27,46,781,581),11014=>array(151,0,687,754),11015=>array(151,-25,687,729),11016=>array(123,-23,744,598),11017=>array(94,-23,715,598),11018=>array(123,-23,744,598),11019=>array(94,-23,715,598),11020=>array(27,46,789,581),11021=>array(151,-25,687,754),11022=>array(57,-25,800,372),11023=>array(57,255,800,652),11024=>array(38,-25,781,372),11025=>array(38,255,781,652),11026=>array(91,-124,854,643),11027=>array(91,-124,854,643),11028=>array(91,-124,854,643),11029=>array(91,-124,854,643),11030=>array(3,-124,766,643),11031=>array(3,-124,766,643),11032=>array(3,-124,766,643),11033=>array(3,-124,766,643),11034=>array(91,-124,854,643),11039=>array(18,-26,852,767),11040=>array(18,-26,852,767),11041=>array(73,-91,800,748),11042=>array(73,-91,800,748),11043=>array(17,-35,856,692),11044=>array(55,-250,1064,770),11091=>array(38,-47,832,788),11092=>array(38,-47,832,788),11360=>array(5,0,610,729),11361=>array(5,0,355,760),11362=>array(-17,0,610,729),11363=>array(6,0,692,729),11364=>array(92,-200,750,729),11365=>array(32,-46,639,594),11366=>array(13,-93,455,822),11367=>array(92,-157,932,729),11368=>array(84,-138,809,760),11369=>array(92,-157,805,729),11370=>array(84,-138,684,760),11371=>array(45,-157,768,729),11372=>array(45,-138,622,547),11373=>array(48,-14,769,741),11374=>array(92,-200,903,729),11375=>array(5,0,769,729),11376=>array(48,-14,769,741),11377=>array(15,0,778,560),11378=>array(30,0,1221,742),11379=>array(35,0,1056,560),11380=>array(38,0,637,586),11381=>array(92,0,606,729),11382=>array(84,0,481,547),11383=>array(64,0,725,552),11385=>array(84,-13,490,760),11386=>array(43,-14,644,560),11387=>array(78,0,467,547),11388=>array(-21,-121,166,425),11389=>array(3,326,484,734),11390=>array(72,-240,670,742),11391=>array(45,-240,680,729),11520=>array(45,-64,609,547),11521=>array(16,-232,625,546),11522=>array(41,-232,629,547),11523=>array(42,-10,585,807),11524=>array(40,-228,613,546),11525=>array(41,-228,988,546),11526=>array(20,-8,668,816),11527=>array(42,-9,974,547),11528=>array(39,0,589,547),11529=>array(41,-227,614,816),11530=>array(39,-9,985,546),11531=>array(42,-8,649,816),11532=>array(39,0,627,816),11533=>array(41,-8,988,546),11534=>array(41,-8,629,546),11535=>array(41,-228,846,816),11536=>array(42,-9,976,816),11537=>array(41,-9,630,816),11538=>array(46,-232,610,546),11539=>array(41,-228,984,661),11540=>array(45,-228,958,546),11541=>array(39,-228,978,816),11542=>array(44,0,628,546),11543=>array(41,-228,630,547),11544=>array(41,-232,627,546),11545=>array(44,-228,628,816),11546=>array(42,-232,610,547),11547=>array(43,-9,658,816),11548=>array(44,-228,989,547),11549=>array(44,-232,619,546),11550=>array(46,-232,639,546),11551=>array(44,-228,615,567),11552=>array(44,-9,1004,546),11553=>array(44,-228,619,816),11554=>array(42,-9,601,626),11555=>array(44,-228,622,816),11556=>array(42,-228,684,546),11557=>array(45,-8,959,816),11568=>array(55,-14,636,380),11569=>array(50,-14,892,742),11570=>array(50,-14,892,742),11571=>array(51,0,674,729),11572=>array(51,0,674,729),11573=>array(56,0,669,729),11574=>array(48,0,627,729),11575=>array(5,0,769,729),11576=>array(5,0,769,729),11577=>array(92,0,610,729),11578=>array(92,0,610,729),11579=>array(73,-14,729,742),11580=>array(73,0,916,729),11581=>array(92,0,754,729),11582=>array(92,0,549,729),11583=>array(92,0,754,729),11584=>array(50,-14,892,742),11585=>array(50,-84,892,815),11586=>array(92,0,281,729),11587=>array(21,0,720,729),11588=>array(92,0,745,729),11589=>array(-30,0,944,729),11590=>array(92,0,598,729),11591=>array(92,0,709,729),11592=>array(73,256,607,445),11593=>array(92,0,610,729),11594=>array(73,0,529,729),11595=>array(64,-14,892,742),11596=>array(82,0,695,729),11597=>array(92,0,745,729),11598=>array(92,0,610,729),11599=>array(92,0,280,729),11600=>array(82,0,695,729),11601=>array(92,0,281,729),11602=>array(42,-14,684,729),11603=>array(55,-14,636,742),11604=>array(50,-14,892,742),11605=>array(50,-95,892,742),11606=>array(92,0,745,729),11607=>array(92,0,281,729),11608=>array(92,0,744,729),11609=>array(50,-14,892,742),11610=>array(50,-14,892,823),11611=>array(50,-14,718,742),11612=>array(79,0,797,729),11613=>array(19,0,751,729),11614=>array(50,-14,718,742),11615=>array(92,0,610,729),11616=>array(5,0,769,729),11617=>array(92,0,745,729),11618=>array(92,0,599,729),11619=>array(50,0,800,729),11620=>array(92,0,654,729),11621=>array(50,0,800,729),11631=>array(64,490,651,729),11800=>array(69,-14,515,728),11807=>array(106,-34,732,415),11810=>array(86,403,389,760),11811=>array(68,403,371,760),11812=>array(86,-132,389,225),11813=>array(68,-132,371,225),11822=>array(69,0,515,742),19904=>array(83,-158,813,729),19905=>array(83,-158,813,729),19906=>array(83,-158,813,729),19907=>array(83,-158,813,729),19908=>array(83,-158,813,729),19909=>array(83,-158,813,729),19910=>array(83,-158,813,729),19911=>array(83,-158,813,729),19912=>array(83,-158,813,729),19913=>array(83,-158,814,729),19914=>array(83,-158,813,729),19915=>array(83,-158,813,729),19916=>array(83,-158,813,729),19917=>array(83,-158,813,729),19918=>array(83,-158,813,729),19919=>array(83,-158,813,729),19920=>array(83,-158,814,729),19921=>array(83,-158,813,729),19922=>array(83,-158,814,729),19923=>array(83,-158,813,729),19924=>array(83,-158,813,729),19925=>array(83,-158,813,729),19926=>array(83,-158,813,729),19927=>array(83,-158,813,729),19928=>array(83,-158,813,729),19929=>array(83,-158,813,729),19930=>array(83,-158,813,729),19931=>array(83,-158,814,729),19932=>array(83,-158,813,729),19933=>array(83,-158,813,729),19934=>array(83,-158,814,729),19935=>array(83,-158,813,729),19936=>array(83,-158,813,729),19937=>array(83,-158,813,729),19938=>array(83,-158,813,729),19939=>array(83,-158,813,729),19940=>array(83,-158,813,729),19941=>array(83,-158,814,729),19942=>array(83,-158,813,729),19943=>array(83,-158,813,729),19944=>array(83,-158,814,729),19945=>array(83,-158,813,729),19946=>array(83,-158,814,729),19947=>array(83,-158,813,729),19948=>array(83,-158,814,729),19949=>array(83,-158,813,729),19950=>array(83,-158,814,729),19951=>array(83,-158,813,729),19952=>array(83,-158,814,729),19953=>array(83,-158,813,729),19954=>array(83,-158,813,729),19955=>array(83,-158,813,729),19956=>array(83,-158,813,729),19957=>array(83,-158,814,729),19958=>array(83,-158,813,729),19959=>array(83,-158,813,729),19960=>array(83,-158,813,729),19961=>array(83,-158,814,729),19962=>array(83,-158,813,729),19963=>array(83,-158,814,729),19964=>array(83,-158,814,729),19965=>array(83,-158,813,729),19966=>array(83,-158,813,729),19967=>array(83,-158,813,729),42192=>array(92,0,692,729),42193=>array(92,0,692,729),42194=>array(41,0,641,729),42195=>array(92,0,778,729),42196=>array(5,0,677,729),42197=>array(5,0,677,729),42198=>array(50,-14,747,742),42199=>array(92,0,805,729),42200=>array(-30,0,683,729),42201=>array(0,-14,439,729),42202=>array(50,-14,670,742),42203=>array(50,-14,670,742),42204=>array(45,0,680,729),42205=>array(92,0,599,729),42206=>array(92,0,599,729),42207=>array(92,0,903,729),42208=>array(92,0,745,729),42209=>array(92,0,610,729),42210=>array(72,-14,647,742),42211=>array(92,0,750,729),42212=>array(20,0,678,729),42213=>array(5,0,769,729),42214=>array(5,0,769,729),42215=>array(92,0,745,729),42216=>array(25,-14,723,742),42217=>array(91,0,530,743),42218=>array(30,0,1072,729),42219=>array(19,0,751,729),42220=>array(-10,0,734,729),42221=>array(70,0,670,729),42222=>array(5,0,769,729),42223=>array(5,0,769,729),42224=>array(92,0,610,729),42225=>array(73,0,591,729),42226=>array(92,0,280,729),42227=>array(50,-14,800,742),42228=>array(92,-14,720,729),42229=>array(92,0,720,743),42230=>array(9,0,527,729),42231=>array(52,0,738,729),42232=>array(73,0,249,189),42233=>array(24,-142,249,189),42234=>array(73,0,601,189),42235=>array(73,-142,601,189),42236=>array(24,-142,249,547),42237=>array(73,0,249,547),42238=>array(73,0,515,405),42239=>array(73,134,515,492),42564=>array(26,-14,601,742),42565=>array(15,-14,511,560),42566=>array(92,0,428,729),42567=>array(83,0,356,547),42572=>array(57,-14,1348,654),42573=>array(47,-13,1126,547),42576=>array(49,0,1142,729),42577=>array(20,0,946,547),42580=>array(55,-14,1082,742),42581=>array(44,-14,888,560),42582=>array(92,0,1088,729),42583=>array(84,-14,880,560),42594=>array(60,-157,1058,729),42595=>array(56,-138,900,547),42596=>array(46,0,1069,729),42597=>array(55,0,888,547),42598=>array(92,0,1233,729),42599=>array(84,0,973,547),42600=>array(50,-14,800,742),42601=>array(43,-14,644,560),42602=>array(50,-14,987,742),42603=>array(43,-14,825,560),42604=>array(50,-14,1356,742),42605=>array(43,-14,1063,560),42606=>array(28,-208,933,743),42634=>array(5,-200,883,729),42635=>array(4,-216,709,547),42636=>array(5,0,677,729),42637=>array(4,0,575,547),42644=>array(81,0,716,729),42645=>array(84,0,634,760),42760=>array(96,0,404,693),42761=>array(96,0,404,693),42762=>array(96,0,404,693),42763=>array(96,0,404,693),42764=>array(96,0,404,693),42765=>array(96,0,404,693),42766=>array(96,0,404,693),42767=>array(96,0,404,693),42768=>array(96,0,404,693),42769=>array(96,0,404,693),42770=>array(96,0,404,693),42771=>array(96,0,404,693),42772=>array(96,0,404,693),42773=>array(96,0,404,693),42774=>array(96,0,404,693),42779=>array(58,326,342,736),42780=>array(58,324,342,734),42781=>array(88,326,199,734),42782=>array(88,326,199,734),42783=>array(88,0,199,408),42786=>array(67,0,409,729),42787=>array(67,0,355,547),42788=>array(56,224,479,742),42789=>array(56,42,479,560),42790=>array(92,-200,745,729),42791=>array(84,-216,634,760),42792=>array(5,-216,986,729),42793=>array(13,-215,810,702),42794=>array(67,-14,616,742),42795=>array(54,-202,493,560),42800=>array(92,0,473,547),42801=>array(52,-14,548,560),42802=>array(5,0,1344,729),42803=>array(43,-14,973,560),42804=>array(5,-14,1234,742),42805=>array(43,-14,1021,560),42806=>array(5,-14,1124,729),42807=>array(43,-14,970,560),42808=>array(5,0,1074,729),42809=>array(43,-14,907,560),42810=>array(5,0,1074,729),42811=>array(43,-14,907,560),42812=>array(5,-216,1030,729),42813=>array(43,-216,907,560),42814=>array(33,-14,653,742),42815=>array(43,-14,526,560),42816=>array(5,0,812,729),42817=>array(6,0,708,760),42822=>array(92,0,822,729),42823=>array(84,0,458,760),42824=>array(41,0,655,729),42825=>array(59,0,473,760),42826=>array(16,-14,902,742),42827=>array(5,-14,809,560),42830=>array(50,-14,1356,742),42831=>array(43,-14,1063,560),42832=>array(16,0,692,729),42833=>array(5,-208,671,560),42834=>array(34,0,907,729),42835=>array(34,-208,892,560),42838=>array(50,-188,800,742),42839=>array(45,-208,711,559),42852=>array(16,0,692,729),42853=>array(5,-208,671,760),42854=>array(16,0,692,729),42855=>array(5,-208,671,760),42880=>array(27,0,545,729),42881=>array(84,-208,259,547),42882=>array(84,-208,730,742),42883=>array(84,-208,634,560),42889=>array(112,0,288,547),42890=>array(83,141,303,405),42891=>array(140,245,316,729),42892=>array(95,458,211,729),42893=>array(81,0,716,729),42894=>array(84,-216,680,760),42896=>array(92,-157,868,729),42897=>array(84,-138,725,560),42912=>array(-11,-14,832,742),42913=>array(-11,-216,727,559),42914=>array(-11,0,805,729),42915=>array(-11,0,684,760),42916=>array(-11,0,848,729),42917=>array(-11,0,723,560),42918=>array(-11,0,781,729),42919=>array(-11,0,504,560),42920=>array(-11,-14,731,742),42921=>array(-11,-14,606,560),42922=>array(-68,0,794,729),43002=>array(84,0,972,547),43003=>array(84,0,591,729),43004=>array(41,0,641,729),43005=>array(92,0,903,729),43006=>array(92,0,280,928),43007=>array(31,0,1294,729),61184=>array(91,602,317,693),61185=>array(48,451,338,693),61186=>array(26,301,363,693),61187=>array(17,150,373,693),61188=>array(13,0,378,693),61189=>array(48,451,338,693),61190=>array(91,451,317,543),61191=>array(48,301,338,543),61192=>array(26,150,363,543),61193=>array(17,0,373,543),61194=>array(26,301,363,693),61195=>array(48,301,338,543),61196=>array(91,301,317,393),61197=>array(48,150,338,393),61198=>array(26,0,363,393),61199=>array(17,150,373,693),61200=>array(26,149,363,542),61201=>array(48,150,338,393),61202=>array(91,150,317,242),61203=>array(48,0,338,242),61204=>array(13,0,378,693),61205=>array(17,0,373,543),61206=>array(26,0,363,393),61207=>array(48,0,338,242),61208=>array(91,0,317,92),61209=>array(96,0,188,693),62464=>array(49,-14,563,819),62465=>array(49,-15,563,823),62466=>array(49,-14,604,828),62467=>array(49,0,853,828),62468=>array(49,-15,563,828),62469=>array(49,-15,563,828),62470=>array(29,-15,612,828),62471=>array(49,-14,846,828),62472=>array(49,0,541,828),62473=>array(49,-14,563,820),62474=>array(49,-6,1114,828),62475=>array(49,-14,563,828),62476=>array(63,-15,578,820),62477=>array(54,0,839,828),62478=>array(49,-15,563,819),62479=>array(49,-15,563,840),62480=>array(49,0,875,828),62481=>array(63,-14,578,819),62482=>array(44,-14,699,828),62483=>array(34,-14,570,828),62484=>array(49,-14,837,828),62485=>array(49,-14,563,819),62486=>array(49,0,858,828),62487=>array(49,-14,563,820),62488=>array(44,-14,558,828),62489=>array(64,0,579,828),62490=>array(50,-15,628,820),62491=>array(49,-14,563,819),62492=>array(63,-14,577,828),62493=>array(49,-14,581,820),62494=>array(63,-14,578,819),62495=>array(24,-14,546,828),62496=>array(49,-15,563,828),62497=>array(63,-15,577,828),62498=>array(49,-73,563,828),62499=>array(49,-15,563,830),62500=>array(49,-15,569,828),62501=>array(49,-14,627,828),62502=>array(49,-14,914,828),62504=>array(45,-228,960,816),62505=>array(54,-223,791,843),62506=>array(54,-14,510,761),62507=>array(54,-14,510,773),62508=>array(54,-14,510,866),62509=>array(54,-14,510,812),62510=>array(54,-14,510,877),62511=>array(54,-14,510,803),62512=>array(54,-232,501,761),62513=>array(54,-232,501,793),62514=>array(54,-232,501,891),62515=>array(54,-232,501,803),62516=>array(54,0,520,761),62517=>array(54,0,520,793),62518=>array(54,0,520,803),62519=>array(54,-0,770,761),62520=>array(54,-0,770,773),62521=>array(54,-0,770,884),62522=>array(54,-0,770,793),62523=>array(54,-0,770,803),62524=>array(54,-232,557,761),62525=>array(54,-232,557,773),62526=>array(54,-232,557,894),62527=>array(54,-232,557,793),62528=>array(54,-232,557,803),62529=>array(54,-232,557,844),63173=>array(43,-14,644,760),64256=>array(19,0,819,760),64257=>array(21,0,657,760),64258=>array(19,0,657,760),64259=>array(19,0,1031,760),64260=>array(19,0,1032,760),64261=>array(19,0,785,760),64262=>array(52,-14,997,742),64275=>array(74,-14,1300,760),64276=>array(78,-14,1301,760),64277=>array(78,-208,1300,760),64278=>array(78,-208,1300,760),64279=>array(78,-208,1629,760),64285=>array(66,32,228,547),64286=>array(182,635,510,780),64287=>array(66,32,500,547),64288=>array(38,0,590,547),64289=>array(85,0,855,547),64290=>array(43,0,731,547),64291=>array(91,0,778,547),64292=>array(43,0,730,547),64293=>array(43,0,730,739),64294=>array(91,0,778,547),64295=>array(43,0,730,547),64296=>array(47,-4,730,547),64297=>array(106,256,732,627),64298=>array(20,0,750,710),64299=>array(20,0,750,723),64300=>array(20,0,750,710),64301=>array(20,0,750,710),64302=>array(84,-171,644,547),64303=>array(84,-217,644,547),64304=>array(84,-171,644,547),64305=>array(43,0,567,547),64306=>array(43,-9,418,547),64307=>array(43,0,545,547),64308=>array(91,0,596,547),64309=>array(43,0,346,547),64310=>array(43,0,442,547),64312=>array(90,-13,624,553),64313=>array(43,164,369,547),64314=>array(43,-240,487,547),64315=>array(43,0,511,547),64316=>array(43,0,527,711),64318=>array(43,0,633,554),64320=>array(43,0,362,547),64321=>array(90,-13,624,547),64323=>array(91,-240,584,547),64324=>array(91,0,603,547),64326=>array(33,0,564,547),64327=>array(91,-240,660,546),64328=>array(43,0,511,547),64329=>array(20,0,750,547),64330=>array(10,-4,592,547),64331=>array(91,0,252,710),64332=>array(43,0,567,710),64333=>array(43,0,511,710),64334=>array(91,0,603,710),64335=>array(43,0,652,729),64338=>array(63,-244,921,327),64339=>array(63,-244,1068,327),64340=>array(-10,-244,292,293),64341=>array(-10,-244,418,293),64342=>array(63,-244,921,327),64343=>array(63,-244,1068,327),64344=>array(-10,-244,302,293),64345=>array(-10,-244,418,293),64346=>array(63,-244,921,327),64347=>array(63,-244,1068,327),64348=>array(-10,-244,302,293),64349=>array(-10,-244,418,293),64350=>array(63,-5,921,566),64351=>array(63,-5,1068,566),64352=>array(-10,0,292,640),64353=>array(-10,0,418,640),64354=>array(63,-5,921,566),64355=>array(63,-5,1068,566),64356=>array(-10,0,302,640),64357=>array(-10,0,418,640),64358=>array(63,-5,921,599),64359=>array(63,-5,1068,599),64360=>array(-10,0,333,672),64361=>array(-10,0,418,672),64362=>array(63,-24,1082,786),64363=>array(63,-29,1201,786),64364=>array(-10,0,575,786),64365=>array(-10,0,729,786),64366=>array(63,-24,1082,786),64367=>array(63,-29,1201,786),64368=>array(-10,0,575,786),64369=>array(-10,0,729,786),64370=>array(77,-244,720,425),64371=>array(77,-244,730,425),64372=>array(-10,-244,628,405),64373=>array(-10,-244,730,405),64374=>array(77,-244,720,425),64375=>array(77,-244,730,425),64376=>array(-10,-117,628,405),64377=>array(-10,-117,730,405),64378=>array(77,-244,720,425),64379=>array(77,-244,730,425),64380=>array(-10,-244,628,405),64381=>array(-10,-244,730,405),64382=>array(77,-244,720,425),64383=>array(77,-244,730,425),64384=>array(-10,-244,628,405),64385=>array(-10,-244,730,405),64386=>array(61,-146,442,415),64387=>array(61,-146,587,415),64388=>array(61,-15,442,586),64389=>array(61,-15,587,586),64390=>array(61,-15,442,708),64391=>array(61,-15,587,708),64392=>array(61,-15,442,746),64393=>array(61,-15,587,746),64394=>array(-42,-244,508,615),64395=>array(-42,-244,632,615),64396=>array(-42,-244,520,648),64397=>array(-42,-244,632,648),64398=>array(63,-39,1024,760),64399=>array(63,-39,1034,760),64400=>array(-10,0,582,760),64401=>array(-10,0,591,760),64402=>array(63,-39,1024,910),64403=>array(63,-39,1034,910),64404=>array(-10,0,582,910),64405=>array(-10,0,591,910),64406=>array(63,-293,1024,910),64407=>array(63,-293,1034,910),64408=>array(-10,-269,582,910),64409=>array(-10,-269,591,910),64410=>array(63,-39,1024,910),64411=>array(63,-39,1034,910),64412=>array(-10,0,582,910),64413=>array(-10,0,591,910),64414=>array(62,-165,779,366),64415=>array(62,-244,910,287),64416=>array(62,-165,779,636),64417=>array(62,-244,910,514),64418=>array(-10,0,333,672),64419=>array(-10,0,418,672),64426=>array(70,-33,877,506),64427=>array(70,-244,890,369),64428=>array(-10,-33,633,506),64429=>array(-10,-244,670,369),64467=>array(70,-27,814,854),64468=>array(70,-27,941,854),64469=>array(-10,0,582,928),64470=>array(-10,0,591,928),64473=>array(-42,-244,547,556),64474=>array(-42,-244,637,556),64488=>array(-10,0,292,293),64489=>array(-10,0,418,293),64508=>array(63,-107,863,462),64509=>array(63,-126,1021,291),64510=>array(-10,-166,302,293),64511=>array(-10,-166,418,293),65056=>array(-419,735,0,880),65057=>array(0,735,419,880),65058=>array(-362,756,0,894),65059=>array(0,756,362,894),65136=>array(28,591,313,825),65137=>array(-10,0,352,825),65138=>array(28,591,313,881),65139=>array(51,0,356,177),65140=>array(28,-239,313,-5),65142=>array(28,591,313,723),65143=>array(-10,0,352,723),65144=>array(28,590,313,881),65145=>array(-10,0,352,881),65146=>array(28,-137,313,-5),65147=>array(-10,-137,352,125),65148=>array(9,599,333,869),65149=>array(-10,0,352,869),65150=>array(36,610,304,878),65151=>array(-10,0,352,878),65152=>array(73,20,437,493),65153=>array(-20,0,362,955),65154=>array(-20,0,385,955),65155=>array(75,0,259,993),65156=>array(75,0,385,993),65157=>array(-42,-244,547,603),65158=>array(-42,-244,637,603),65159=>array(76,-245,259,760),65160=>array(76,-245,385,760),65161=>array(63,-107,863,603),65162=>array(63,-126,1021,480),65163=>array(-10,0,292,627),65164=>array(-10,0,418,627),65165=>array(84,0,259,760),65166=>array(84,0,385,760),65167=>array(63,-149,921,327),65168=>array(63,-149,1068,327),65169=>array(-10,-173,292,293),65170=>array(-10,-173,418,293),65171=>array(48,-30,540,513),65172=>array(65,0,616,513),65173=>array(63,-5,921,415),65174=>array(63,-5,1068,415),65175=>array(-10,0,302,488),65176=>array(-10,0,418,488),65177=>array(63,-5,921,537),65178=>array(63,-5,1068,537),65179=>array(-10,0,302,610),65180=>array(-10,0,418,610),65181=>array(77,-244,720,425),65182=>array(77,-244,730,425),65183=>array(-10,-173,628,405),65184=>array(-10,-173,730,405),65185=>array(77,-244,720,425),65186=>array(77,-244,730,425),65187=>array(-10,0,628,405),65188=>array(-10,0,730,405),65189=>array(77,-244,720,579),65190=>array(77,-244,730,579),65191=>array(-10,0,628,530),65192=>array(-10,0,730,530),65193=>array(61,-15,442,415),65194=>array(61,-15,587,415),65195=>array(61,-15,442,579),65196=>array(61,-15,587,579),65197=>array(-42,-244,508,269),65198=>array(-42,-244,632,269),65199=>array(-42,-244,508,457),65200=>array(-42,-244,632,457),65201=>array(63,-244,1297,366),65202=>array(63,-244,1423,366),65203=>array(-10,-14,901,366),65204=>array(-10,-14,1027,366),65205=>array(63,-244,1297,586),65206=>array(63,-244,1423,586),65207=>array(-10,-14,901,586),65208=>array(-10,-14,1027,586),65209=>array(63,-244,1265,362),65210=>array(63,-244,1374,362),65211=>array(-10,0,886,362),65212=>array(-10,0,995,362),65213=>array(63,-244,1265,457),65214=>array(63,-244,1374,457),65215=>array(-10,0,886,481),65216=>array(-10,0,995,481),65217=>array(70,0,971,760),65218=>array(70,0,1081,760),65219=>array(-10,0,875,760),65220=>array(-10,0,984,760),65221=>array(70,0,971,760),65222=>array(70,0,1081,760),65223=>array(-10,0,875,760),65224=>array(-10,0,984,760),65225=>array(87,-244,720,521),65226=>array(57,-244,693,382),65227=>array(-10,0,583,521),65228=>array(-10,0,574,382),65229=>array(87,-244,720,652),65230=>array(57,-244,693,530),65231=>array(-10,0,583,652),65232=>array(-10,0,574,530),65233=>array(63,-24,1082,627),65234=>array(63,-29,1201,627),65235=>array(-10,0,575,627),65236=>array(-10,0,729,627),65237=>array(52,-215,825,635),65238=>array(52,-244,911,476),65239=>array(-10,0,575,635),65240=>array(-10,0,729,635),65241=>array(70,-27,814,760),65242=>array(70,-27,941,760),65243=>array(-10,0,582,760),65244=>array(-10,0,591,760),65245=>array(70,-142,778,760),65246=>array(70,-142,902,760),65247=>array(-10,0,292,760),65248=>array(-10,0,418,760),65249=>array(68,-244,660,369),65250=>array(68,-244,794,311),65251=>array(-10,-23,546,311),65252=>array(-10,-23,680,311),65253=>array(62,-165,779,457),65254=>array(62,-244,910,383),65255=>array(-10,0,292,481),65256=>array(-10,0,418,481),65257=>array(48,-30,540,358),65258=>array(65,0,616,366),65259=>array(-10,-33,633,506),65260=>array(-10,-244,670,369),65261=>array(-42,-244,547,322),65262=>array(-42,-244,637,322),65263=>array(63,-107,863,462),65264=>array(63,-126,1021,291),65265=>array(63,-244,863,462),65266=>array(63,-244,1021,291),65267=>array(-10,-166,302,293),65268=>array(-10,-166,418,293),65269=>array(-62,-15,643,882),65270=>array(-62,-15,769,882),65271=>array(33,-15,643,944),65272=>array(33,-15,769,944),65273=>array(41,-245,643,760),65274=>array(41,-245,769,760),65275=>array(41,-15,643,760),65276=>array(41,-15,769,760),65533=>array(24,-139,1089,926),65535=>array(50,-177,550,705)); -$cw=array(0=>600,32=>348,33=>456,34=>521,35=>838,36=>696,37=>1002,38=>872,39=>306,40=>457,41=>457,42=>523,43=>838,44=>380,45=>415,46=>380,47=>365,48=>696,49=>696,50=>696,51=>696,52=>696,53=>696,54=>696,55=>696,56=>696,57=>696,58=>400,59=>400,60=>838,61=>838,62=>838,63=>580,64=>1000,65=>774,66=>762,67=>734,68=>830,69=>683,70=>683,71=>821,72=>837,73=>372,74=>372,75=>775,76=>637,77=>995,78=>837,79=>850,80=>733,81=>850,82=>770,83=>720,84=>682,85=>812,86=>774,87=>1103,88=>771,89=>724,90=>725,91=>457,92=>365,93=>457,94=>838,95=>500,96=>500,97=>675,98=>716,99=>593,100=>716,101=>678,102=>435,103=>716,104=>712,105=>343,106=>343,107=>665,108=>343,109=>1042,110=>712,111=>687,112=>716,113=>716,114=>493,115=>595,116=>478,117=>712,118=>652,119=>924,120=>645,121=>652,122=>582,123=>712,124=>365,125=>712,126=>838,160=>348,161=>456,162=>696,163=>696,164=>636,165=>696,166=>365,167=>500,168=>500,169=>1000,170=>564,171=>646,172=>838,173=>415,174=>1000,175=>500,176=>500,177=>838,178=>438,179=>438,180=>500,181=>736,182=>636,183=>380,184=>500,185=>438,186=>564,187=>646,188=>1035,189=>1035,190=>1035,191=>580,192=>774,193=>774,194=>774,195=>774,196=>774,197=>774,198=>1085,199=>734,200=>683,201=>683,202=>683,203=>683,204=>372,205=>372,206=>372,207=>372,208=>838,209=>837,210=>850,211=>850,212=>850,213=>850,214=>850,215=>838,216=>850,217=>812,218=>812,219=>812,220=>812,221=>724,222=>738,223=>719,224=>675,225=>675,226=>675,227=>675,228=>675,229=>675,230=>1048,231=>593,232=>678,233=>678,234=>678,235=>678,236=>343,237=>343,238=>343,239=>343,240=>687,241=>712,242=>687,243=>687,244=>687,245=>687,246=>687,247=>838,248=>687,249=>712,250=>712,251=>712,252=>712,253=>652,254=>716,255=>652,256=>774,257=>675,258=>774,259=>675,260=>774,261=>675,262=>734,263=>593,264=>734,265=>593,266=>734,267=>593,268=>734,269=>593,270=>830,271=>716,272=>838,273=>716,274=>683,275=>678,276=>683,277=>678,278=>683,279=>678,280=>683,281=>678,282=>683,283=>678,284=>821,285=>716,286=>821,287=>716,288=>821,289=>716,290=>821,291=>716,292=>837,293=>712,294=>974,295=>790,296=>372,297=>343,298=>372,299=>343,300=>372,301=>343,302=>372,303=>343,304=>372,305=>343,306=>744,307=>686,308=>372,309=>343,310=>775,311=>665,312=>665,313=>637,314=>343,315=>637,316=>343,317=>637,318=>479,319=>637,320=>557,321=>642,322=>371,323=>837,324=>712,325=>837,326=>712,327=>837,328=>712,329=>983,330=>837,331=>712,332=>850,333=>687,334=>850,335=>687,336=>850,337=>687,338=>1167,339=>1094,340=>770,341=>493,342=>770,343=>493,344=>770,345=>493,346=>720,347=>595,348=>720,349=>595,350=>720,351=>595,352=>720,353=>595,354=>682,355=>478,356=>682,357=>478,358=>682,359=>478,360=>812,361=>712,362=>812,363=>712,364=>812,365=>712,366=>812,367=>712,368=>812,369=>712,370=>812,371=>712,372=>1103,373=>924,374=>724,375=>652,376=>724,377=>725,378=>582,379=>725,380=>582,381=>725,382=>582,383=>435,384=>716,385=>811,386=>762,387=>716,388=>762,389=>716,390=>734,391=>734,392=>593,393=>838,394=>879,395=>757,396=>716,397=>688,398=>683,399=>849,400=>696,401=>683,402=>435,403=>821,404=>793,405=>1045,406=>436,407=>389,408=>775,409=>665,410=>360,411=>592,412=>1042,413=>837,414=>712,415=>850,416=>874,417=>687,418=>1083,419=>912,420=>782,421=>716,422=>770,423=>720,424=>595,425=>683,426=>552,427=>478,428=>707,429=>478,430=>682,431=>835,432=>712,433=>850,434=>813,435=>797,436=>778,437=>725,438=>582,439=>772,440=>772,441=>641,442=>582,443=>696,444=>772,445=>641,446=>573,447=>716,448=>372,449=>659,450=>544,451=>372,452=>1555,453=>1412,454=>1298,455=>1009,456=>980,457=>686,458=>1209,459=>1180,460=>1055,461=>774,462=>675,463=>372,464=>343,465=>850,466=>687,467=>812,468=>712,469=>812,470=>712,471=>812,472=>712,473=>812,474=>712,475=>812,476=>712,477=>678,478=>774,479=>675,480=>774,481=>675,482=>1085,483=>1048,484=>821,485=>716,486=>821,487=>716,488=>775,489=>665,490=>850,491=>687,492=>850,493=>687,494=>772,495=>582,496=>343,497=>1555,498=>1412,499=>1298,500=>821,501=>716,502=>1289,503=>787,504=>837,505=>712,506=>774,507=>675,508=>1085,509=>1048,510=>850,511=>687,512=>774,513=>675,514=>774,515=>675,516=>683,517=>678,518=>683,519=>678,520=>372,521=>343,522=>372,523=>343,524=>850,525=>687,526=>850,527=>687,528=>770,529=>493,530=>770,531=>493,532=>812,533=>712,534=>812,535=>712,536=>720,537=>595,538=>682,539=>478,540=>690,541=>607,542=>837,543=>712,544=>837,545=>865,546=>809,547=>659,548=>725,549=>582,550=>774,551=>675,552=>683,553=>678,554=>850,555=>687,556=>850,557=>687,558=>850,559=>687,560=>850,561=>687,562=>724,563=>652,564=>492,565=>867,566=>512,567=>343,568=>1088,569=>1088,570=>774,571=>734,572=>593,573=>637,574=>682,575=>595,576=>582,577=>782,578=>614,579=>762,580=>812,581=>774,582=>683,583=>678,584=>372,585=>343,586=>860,587=>791,588=>770,589=>493,590=>724,591=>652,592=>675,593=>716,594=>716,595=>716,596=>593,597=>593,598=>717,599=>792,600=>678,601=>678,602=>876,603=>557,604=>545,605=>815,606=>731,607=>343,608=>792,609=>716,610=>627,611=>644,612=>635,613=>712,614=>712,615=>712,616=>545,617=>440,618=>545,619=>559,620=>693,621=>343,622=>841,623=>1042,624=>1042,625=>1042,626=>712,627=>793,628=>707,629=>687,630=>909,631=>681,632=>796,633=>538,634=>538,635=>650,636=>493,637=>493,638=>596,639=>596,640=>642,641=>642,642=>595,643=>415,644=>435,645=>605,646=>552,647=>478,648=>478,649=>920,650=>772,651=>670,652=>652,653=>924,654=>652,655=>724,656=>694,657=>684,658=>641,659=>641,660=>573,661=>573,662=>573,663=>573,664=>850,665=>633,666=>731,667=>685,668=>691,669=>343,670=>732,671=>539,672=>792,673=>573,674=>573,675=>1156,676=>1214,677=>1155,678=>975,679=>769,680=>929,681=>1026,682=>862,683=>780,684=>591,685=>415,686=>677,687=>789,688=>456,689=>456,690=>219,691=>315,692=>315,693=>315,694=>411,695=>591,696=>417,697=>302,698=>521,699=>380,700=>380,701=>380,702=>366,703=>366,704=>326,705=>326,706=>500,707=>500,708=>500,709=>500,710=>500,711=>500,712=>306,713=>500,714=>500,715=>500,716=>306,717=>500,718=>500,719=>500,720=>337,721=>337,722=>366,723=>366,724=>500,725=>500,726=>416,727=>328,728=>500,729=>500,730=>500,731=>500,732=>500,733=>500,734=>351,735=>500,736=>412,737=>219,738=>381,739=>413,740=>326,741=>500,742=>500,743=>500,744=>500,745=>500,748=>500,749=>500,750=>657,755=>500,759=>500,768=>0,769=>0,770=>0,771=>0,772=>0,773=>0,774=>0,775=>0,776=>0,777=>0,778=>0,779=>0,780=>0,781=>0,782=>0,783=>0,784=>0,785=>0,786=>0,787=>0,788=>0,789=>0,790=>0,791=>0,792=>0,793=>0,794=>0,795=>0,796=>0,797=>0,798=>0,799=>0,800=>0,801=>0,802=>0,803=>0,804=>0,805=>0,806=>0,807=>0,808=>0,809=>0,810=>0,811=>0,812=>0,813=>0,814=>0,815=>0,816=>0,817=>0,818=>0,819=>0,820=>0,821=>0,822=>0,823=>0,824=>0,825=>0,826=>0,827=>0,828=>0,829=>0,830=>0,831=>0,832=>0,833=>0,834=>0,835=>0,836=>0,837=>0,838=>0,839=>0,840=>0,841=>0,842=>0,843=>0,844=>0,845=>0,846=>0,847=>0,849=>0,850=>0,851=>0,855=>0,856=>0,858=>0,860=>0,861=>0,862=>0,863=>0,864=>0,865=>0,866=>0,880=>698,881=>565,882=>1022,883=>836,884=>302,885=>302,886=>837,887=>701,890=>500,891=>593,892=>550,893=>549,894=>400,900=>441,901=>500,902=>797,903=>380,904=>846,905=>1009,906=>563,908=>891,910=>980,911=>894,912=>390,913=>774,914=>762,915=>637,916=>774,917=>683,918=>725,919=>837,920=>850,921=>372,922=>775,923=>774,924=>995,925=>837,926=>632,927=>850,928=>837,929=>733,931=>683,932=>682,933=>724,934=>850,935=>771,936=>850,937=>850,938=>372,939=>724,940=>687,941=>557,942=>712,943=>390,944=>675,945=>687,946=>716,947=>681,948=>687,949=>557,950=>591,951=>712,952=>687,953=>390,954=>710,955=>633,956=>736,957=>681,958=>591,959=>687,960=>791,961=>716,962=>593,963=>779,964=>638,965=>675,966=>782,967=>645,968=>794,969=>869,970=>390,971=>675,972=>687,973=>675,974=>869,975=>775,976=>651,977=>661,978=>746,979=>981,980=>746,981=>796,982=>869,983=>744,984=>850,985=>687,986=>734,987=>593,988=>683,989=>494,990=>702,991=>660,992=>919,993=>627,994=>1093,995=>837,996=>832,997=>716,998=>928,999=>744,1000=>733,1001=>650,1002=>789,1003=>671,1004=>752,1005=>716,1006=>682,1007=>590,1008=>744,1009=>716,1010=>593,1011=>343,1012=>850,1013=>645,1014=>644,1015=>738,1016=>716,1017=>734,1018=>995,1019=>732,1020=>716,1021=>698,1022=>734,1023=>698,1024=>683,1025=>683,1026=>878,1027=>637,1028=>734,1029=>720,1030=>372,1031=>372,1032=>372,1033=>1154,1034=>1130,1035=>878,1036=>817,1037=>837,1038=>771,1039=>837,1040=>774,1041=>762,1042=>762,1043=>637,1044=>891,1045=>683,1046=>1224,1047=>710,1048=>837,1049=>837,1050=>817,1051=>831,1052=>995,1053=>837,1054=>850,1055=>837,1056=>733,1057=>734,1058=>682,1059=>771,1060=>992,1061=>771,1062=>928,1063=>808,1064=>1235,1065=>1326,1066=>939,1067=>1036,1068=>762,1069=>734,1070=>1174,1071=>770,1072=>675,1073=>698,1074=>633,1075=>522,1076=>808,1077=>678,1078=>995,1079=>581,1080=>701,1081=>701,1082=>679,1083=>732,1084=>817,1085=>691,1086=>687,1087=>691,1088=>716,1089=>593,1090=>580,1091=>652,1092=>992,1093=>645,1094=>741,1095=>687,1096=>1062,1097=>1105,1098=>751,1099=>904,1100=>632,1101=>593,1102=>972,1103=>642,1104=>678,1105=>678,1106=>714,1107=>522,1108=>593,1109=>595,1110=>343,1111=>343,1112=>343,1113=>991,1114=>956,1115=>734,1116=>679,1117=>701,1118=>652,1119=>691,1120=>1093,1121=>869,1122=>840,1123=>736,1124=>1012,1125=>839,1126=>992,1127=>832,1128=>1358,1129=>1121,1130=>850,1131=>687,1132=>1236,1133=>1007,1134=>696,1135=>557,1136=>1075,1137=>1061,1138=>850,1139=>687,1140=>850,1141=>695,1142=>850,1143=>695,1144=>1148,1145=>1043,1146=>1074,1147=>863,1148=>1405,1149=>1173,1150=>1093,1151=>869,1152=>734,1153=>593,1154=>652,1155=>0,1156=>0,1157=>0,1158=>0,1159=>0,1160=>418,1161=>418,1162=>957,1163=>807,1164=>762,1165=>611,1166=>733,1167=>716,1168=>637,1169=>522,1170=>666,1171=>543,1172=>808,1173=>669,1174=>1224,1175=>995,1176=>710,1177=>581,1178=>775,1179=>679,1180=>817,1181=>679,1182=>817,1183=>679,1184=>1015,1185=>826,1186=>956,1187=>808,1188=>1103,1189=>874,1190=>1273,1191=>1017,1192=>952,1193=>858,1194=>734,1195=>593,1196=>682,1197=>580,1198=>724,1199=>652,1200=>724,1201=>652,1202=>771,1203=>645,1204=>1112,1205=>1000,1206=>808,1207=>687,1208=>808,1209=>687,1210=>808,1211=>712,1212=>1026,1213=>810,1214=>1026,1215=>810,1216=>372,1217=>1224,1218=>995,1219=>775,1220=>630,1221=>951,1222=>805,1223=>837,1224=>691,1225=>957,1226=>807,1227=>808,1228=>687,1229=>1115,1230=>933,1231=>343,1232=>774,1233=>675,1234=>774,1235=>675,1236=>1085,1237=>1048,1238=>683,1239=>678,1240=>849,1241=>678,1242=>849,1243=>678,1244=>1224,1245=>995,1246=>710,1247=>581,1248=>772,1249=>641,1250=>837,1251=>701,1252=>837,1253=>701,1254=>850,1255=>687,1256=>850,1257=>687,1258=>850,1259=>687,1260=>734,1261=>593,1262=>771,1263=>652,1264=>771,1265=>652,1266=>771,1267=>652,1268=>808,1269=>687,1270=>637,1271=>522,1272=>1036,1273=>904,1274=>666,1275=>543,1276=>771,1277=>645,1278=>771,1279=>645,1280=>762,1281=>608,1282=>1159,1283=>893,1284=>1119,1285=>920,1286=>828,1287=>693,1288=>1242,1289=>1017,1290=>1289,1291=>1013,1292=>839,1293=>638,1294=>938,1295=>803,1296=>696,1297=>557,1298=>831,1299=>732,1300=>1286,1301=>1068,1302=>1065,1303=>979,1304=>1082,1305=>1013,1306=>850,1307=>716,1308=>1103,1309=>924,1310=>817,1311=>679,1312=>1267,1313=>1059,1314=>1273,1315=>1017,1316=>957,1317=>807,1329=>813,1330=>729,1331=>728,1332=>731,1333=>729,1334=>733,1335=>652,1336=>720,1337=>903,1338=>728,1339=>666,1340=>558,1341=>961,1342=>788,1343=>713,1344=>651,1345=>730,1346=>715,1347=>704,1348=>780,1349=>689,1350=>715,1351=>708,1352=>731,1353=>677,1354=>867,1355=>711,1356=>780,1357=>731,1358=>715,1359=>693,1360=>666,1361=>698,1362=>576,1363=>833,1364=>698,1365=>763,1366=>855,1369=>330,1370=>342,1371=>308,1372=>374,1373=>313,1374=>461,1375=>468,1377=>938,1378=>642,1379=>704,1380=>708,1381=>642,1382=>644,1383=>565,1384=>642,1385=>756,1386=>704,1387=>643,1388=>310,1389=>984,1390=>638,1391=>643,1392=>643,1393=>603,1394=>643,1395=>642,1396=>643,1397=>309,1398=>643,1399=>486,1400=>643,1401=>366,1402=>938,1403=>573,1404=>666,1405=>643,1406=>643,1407=>934,1408=>643,1409=>643,1410=>479,1411=>934,1412=>648,1413=>620,1414=>813,1415=>812,1417=>360,1418=>374,1456=>0,1457=>0,1458=>0,1459=>0,1460=>0,1461=>0,1462=>0,1463=>0,1464=>0,1465=>0,1466=>0,1467=>0,1468=>0,1469=>0,1470=>415,1471=>0,1472=>372,1473=>0,1474=>0,1475=>372,1478=>497,1479=>0,1488=>728,1489=>610,1490=>447,1491=>588,1492=>687,1493=>343,1494=>400,1495=>687,1496=>679,1497=>294,1498=>578,1499=>566,1500=>605,1501=>696,1502=>724,1503=>343,1504=>453,1505=>680,1506=>666,1507=>675,1508=>658,1509=>661,1510=>653,1511=>736,1512=>602,1513=>758,1514=>683,1520=>664,1521=>567,1522=>519,1523=>444,1524=>710,1542=>667,1543=>667,1545=>884,1546=>1157,1548=>380,1557=>0,1563=>400,1567=>580,1569=>511,1570=>343,1571=>343,1572=>622,1573=>343,1574=>917,1575=>343,1576=>1005,1577=>590,1578=>1005,1579=>1005,1580=>721,1581=>721,1582=>721,1583=>513,1584=>513,1585=>576,1586=>576,1587=>1380,1588=>1380,1589=>1345,1590=>1345,1591=>1039,1592=>1039,1593=>683,1594=>683,1600=>342,1601=>1162,1602=>894,1603=>917,1604=>868,1605=>733,1606=>854,1607=>590,1608=>622,1609=>917,1610=>917,1611=>0,1612=>0,1613=>0,1614=>0,1615=>0,1616=>0,1617=>0,1618=>0,1619=>0,1620=>0,1621=>0,1623=>0,1626=>500,1632=>610,1633=>610,1634=>610,1635=>610,1636=>610,1637=>610,1638=>610,1639=>610,1640=>610,1641=>610,1642=>610,1643=>374,1644=>380,1645=>545,1646=>1005,1647=>894,1648=>0,1652=>292,1657=>1005,1658=>1005,1659=>1005,1660=>1005,1661=>1005,1662=>1005,1663=>1005,1664=>1005,1665=>721,1666=>721,1667=>721,1668=>721,1669=>721,1670=>721,1671=>721,1672=>445,1673=>445,1674=>445,1675=>445,1676=>445,1677=>445,1678=>445,1679=>445,1680=>445,1681=>576,1682=>576,1683=>576,1684=>576,1685=>681,1686=>576,1687=>576,1688=>576,1689=>576,1690=>1380,1691=>1380,1692=>1380,1693=>1345,1694=>1345,1695=>1039,1696=>683,1697=>1162,1698=>1162,1699=>1162,1700=>1162,1701=>1162,1702=>1162,1703=>894,1704=>894,1705=>1024,1706=>1271,1707=>1024,1708=>917,1709=>917,1710=>917,1711=>1024,1712=>1024,1713=>1024,1714=>1024,1715=>1024,1716=>1024,1717=>868,1718=>868,1719=>868,1720=>868,1721=>854,1722=>854,1723=>854,1724=>854,1725=>854,1726=>938,1727=>721,1734=>622,1740=>917,1742=>917,1749=>590,1776=>610,1777=>610,1778=>610,1779=>610,1780=>610,1781=>610,1782=>610,1783=>610,1784=>610,1785=>610,1984=>696,1985=>696,1986=>696,1987=>696,1988=>696,1989=>696,1990=>696,1991=>696,1992=>696,1993=>696,1994=>343,1995=>547,1996=>543,1997=>652,1998=>691,1999=>691,2000=>594,2001=>691,2002=>904,2003=>551,2004=>551,2005=>627,2006=>688,2007=>444,2008=>1022,2009=>506,2010=>826,2011=>691,2012=>652,2013=>912,2014=>627,2015=>707,2016=>506,2017=>652,2018=>574,2019=>627,2020=>627,2021=>627,2022=>574,2023=>574,2027=>0,2028=>0,2029=>0,2030=>0,2031=>0,2032=>0,2033=>0,2034=>0,2035=>0,2036=>380,2037=>380,2040=>691,2041=>691,2042=>415,3647=>696,3713=>790,3714=>748,3716=>749,3719=>569,3720=>742,3722=>744,3725=>761,3732=>706,3733=>704,3734=>747,3735=>819,3737=>730,3738=>727,3739=>727,3740=>922,3741=>827,3742=>866,3743=>866,3745=>836,3746=>761,3747=>770,3749=>769,3751=>713,3754=>827,3755=>1031,3757=>724,3758=>784,3759=>934,3760=>688,3761=>0,3762=>610,3763=>610,3764=>0,3765=>0,3766=>0,3767=>0,3768=>0,3769=>0,3771=>0,3772=>0,3773=>670,3776=>516,3777=>860,3778=>516,3779=>650,3780=>632,3782=>759,3784=>0,3785=>0,3786=>0,3787=>0,3788=>0,3789=>0,3792=>771,3793=>771,3794=>693,3795=>836,3796=>729,3797=>729,3798=>849,3799=>790,3800=>759,3801=>910,3804=>1363,3805=>1363,4256=>874,4257=>733,4258=>679,4259=>834,4260=>615,4261=>768,4262=>753,4263=>914,4264=>453,4265=>620,4266=>843,4267=>882,4268=>625,4269=>854,4270=>781,4271=>629,4272=>912,4273=>621,4274=>620,4275=>854,4276=>866,4277=>724,4278=>630,4279=>621,4280=>625,4281=>620,4282=>818,4283=>874,4284=>615,4285=>623,4286=>625,4287=>725,4288=>844,4289=>596,4290=>688,4291=>596,4292=>594,4293=>738,4304=>554,4305=>563,4306=>622,4307=>834,4308=>555,4309=>564,4310=>551,4311=>828,4312=>563,4313=>556,4314=>1074,4315=>568,4316=>568,4317=>814,4318=>554,4319=>563,4320=>823,4321=>568,4322=>700,4323=>591,4324=>852,4325=>560,4326=>814,4327=>563,4328=>553,4329=>568,4330=>622,4331=>568,4332=>553,4333=>566,4334=>568,4335=>540,4336=>554,4337=>559,4338=>553,4339=>554,4340=>553,4341=>587,4342=>853,4343=>604,4344=>563,4345=>622,4346=>554,4347=>448,4348=>324,5121=>774,5122=>774,5123=>774,5124=>774,5125=>905,5126=>905,5127=>905,5129=>905,5130=>905,5131=>905,5132=>1018,5133=>1009,5134=>1018,5135=>1009,5136=>1018,5137=>1009,5138=>1149,5139=>1140,5140=>1149,5141=>1140,5142=>905,5143=>1149,5144=>1142,5145=>1149,5146=>1142,5147=>905,5149=>310,5150=>529,5151=>425,5152=>425,5153=>395,5154=>395,5155=>395,5156=>395,5157=>564,5158=>470,5159=>310,5160=>395,5161=>395,5162=>395,5163=>1213,5164=>986,5165=>1216,5166=>1297,5167=>774,5168=>774,5169=>774,5170=>774,5171=>886,5172=>886,5173=>886,5175=>886,5176=>886,5177=>886,5178=>1018,5179=>1009,5180=>1018,5181=>1009,5182=>1018,5183=>1009,5184=>1149,5185=>1140,5186=>1149,5187=>1140,5188=>1149,5189=>1142,5190=>1149,5191=>1142,5192=>886,5193=>576,5194=>229,5196=>812,5197=>812,5198=>812,5199=>812,5200=>815,5201=>815,5202=>815,5204=>815,5205=>815,5206=>815,5207=>1056,5208=>1048,5209=>1056,5210=>1048,5211=>1056,5212=>1048,5213=>1060,5214=>1054,5215=>1060,5216=>1054,5217=>1060,5218=>1052,5219=>1060,5220=>1052,5221=>1060,5222=>483,5223=>1005,5224=>1005,5225=>1023,5226=>1017,5227=>743,5228=>743,5229=>743,5230=>743,5231=>743,5232=>743,5233=>743,5234=>743,5235=>743,5236=>1029,5237=>975,5238=>980,5239=>975,5240=>980,5241=>975,5242=>1029,5243=>975,5244=>1029,5245=>975,5246=>980,5247=>975,5248=>980,5249=>975,5250=>980,5251=>501,5252=>501,5253=>938,5254=>938,5255=>938,5256=>938,5257=>743,5258=>743,5259=>743,5260=>743,5261=>743,5262=>743,5263=>743,5264=>743,5265=>743,5266=>1029,5267=>975,5268=>1029,5269=>975,5270=>1029,5271=>975,5272=>1029,5273=>975,5274=>1029,5275=>975,5276=>1029,5277=>975,5278=>1029,5279=>975,5280=>1029,5281=>501,5282=>501,5283=>626,5284=>626,5285=>626,5286=>626,5287=>626,5288=>626,5289=>626,5290=>626,5291=>626,5292=>881,5293=>854,5294=>863,5295=>874,5296=>863,5297=>874,5298=>881,5299=>874,5300=>881,5301=>874,5302=>863,5303=>874,5304=>863,5305=>874,5306=>863,5307=>436,5308=>548,5309=>436,5312=>988,5313=>988,5314=>988,5315=>988,5316=>931,5317=>931,5318=>931,5319=>931,5320=>931,5321=>1238,5322=>1247,5323=>1200,5324=>1228,5325=>1200,5326=>1228,5327=>931,5328=>660,5329=>497,5330=>660,5331=>988,5332=>988,5333=>988,5334=>988,5335=>931,5336=>931,5337=>931,5338=>931,5339=>931,5340=>1231,5341=>1247,5342=>1283,5343=>1228,5344=>1283,5345=>1228,5346=>1228,5347=>1214,5348=>1228,5349=>1214,5350=>1283,5351=>1228,5352=>1283,5353=>1228,5354=>660,5356=>886,5357=>730,5358=>730,5359=>730,5360=>730,5361=>730,5362=>730,5363=>730,5364=>730,5365=>730,5366=>998,5367=>958,5368=>967,5369=>989,5370=>967,5371=>989,5372=>998,5373=>958,5374=>998,5375=>958,5376=>967,5377=>989,5378=>967,5379=>989,5380=>967,5381=>493,5382=>460,5383=>493,5392=>923,5393=>923,5394=>923,5395=>1136,5396=>1136,5397=>1136,5398=>1136,5399=>1209,5400=>1202,5401=>1209,5402=>1202,5403=>1209,5404=>1202,5405=>1431,5406=>1420,5407=>1431,5408=>1420,5409=>1431,5410=>1420,5411=>1431,5412=>1420,5413=>746,5414=>776,5415=>776,5416=>776,5417=>776,5418=>776,5419=>776,5420=>776,5421=>776,5422=>776,5423=>1003,5424=>1003,5425=>1013,5426=>996,5427=>1013,5428=>996,5429=>1003,5430=>1003,5431=>1003,5432=>1003,5433=>1013,5434=>996,5435=>1013,5436=>996,5437=>1013,5438=>495,5440=>395,5441=>510,5442=>1033,5443=>1033,5444=>976,5445=>976,5446=>976,5447=>976,5448=>733,5449=>733,5450=>733,5451=>733,5452=>733,5453=>733,5454=>1003,5455=>959,5456=>495,5458=>886,5459=>774,5460=>774,5461=>774,5462=>774,5463=>928,5464=>928,5465=>928,5466=>928,5467=>1172,5468=>1142,5469=>602,5470=>812,5471=>812,5472=>812,5473=>812,5474=>812,5475=>812,5476=>815,5477=>815,5478=>815,5479=>815,5480=>1060,5481=>1052,5482=>548,5492=>977,5493=>977,5494=>977,5495=>977,5496=>977,5497=>977,5498=>977,5499=>618,5500=>837,5501=>510,5502=>1238,5503=>1238,5504=>1238,5505=>1238,5506=>1238,5507=>1238,5508=>1238,5509=>989,5514=>977,5515=>977,5516=>977,5517=>977,5518=>1591,5519=>1591,5520=>1591,5521=>1295,5522=>1295,5523=>1591,5524=>1591,5525=>848,5526=>1273,5536=>988,5537=>988,5538=>931,5539=>931,5540=>931,5541=>931,5542=>660,5543=>776,5544=>776,5545=>776,5546=>776,5547=>776,5548=>776,5549=>776,5550=>495,5551=>743,5598=>830,5601=>830,5702=>496,5703=>496,5742=>413,5743=>1238,5744=>1591,5745=>2016,5746=>2016,5747=>1720,5748=>1678,5749=>2016,5750=>2016,5760=>543,5761=>637,5762=>945,5763=>1254,5764=>1563,5765=>1871,5766=>627,5767=>936,5768=>1254,5769=>1559,5770=>1871,5771=>569,5772=>877,5773=>1187,5774=>1497,5775=>1807,5776=>637,5777=>945,5778=>1240,5779=>1555,5780=>1871,5781=>569,5782=>569,5783=>789,5784=>1234,5785=>1559,5786=>740,5787=>638,5788=>638,7424=>652,7425=>833,7426=>1048,7427=>608,7428=>593,7429=>676,7430=>676,7431=>559,7432=>557,7433=>343,7434=>494,7435=>665,7436=>539,7437=>817,7438=>701,7439=>687,7440=>593,7441=>660,7442=>660,7443=>660,7444=>1094,7446=>687,7447=>687,7448=>556,7449=>642,7450=>642,7451=>580,7452=>634,7453=>737,7454=>948,7455=>695,7456=>652,7457=>924,7458=>582,7459=>646,7462=>539,7463=>652,7464=>691,7465=>556,7466=>781,7467=>732,7468=>487,7469=>683,7470=>480,7472=>523,7473=>430,7474=>430,7475=>517,7476=>527,7477=>234,7478=>234,7479=>488,7480=>401,7481=>626,7482=>527,7483=>527,7484=>535,7485=>509,7486=>461,7487=>485,7488=>430,7489=>511,7490=>695,7491=>458,7492=>458,7493=>479,7494=>712,7495=>479,7496=>479,7497=>479,7498=>479,7499=>386,7500=>386,7501=>479,7502=>219,7503=>487,7504=>664,7505=>456,7506=>488,7507=>414,7508=>488,7509=>488,7510=>479,7511=>388,7512=>456,7513=>462,7514=>664,7515=>501,7517=>451,7518=>429,7519=>433,7520=>493,7521=>406,7522=>219,7523=>315,7524=>456,7525=>501,7526=>451,7527=>429,7528=>451,7529=>493,7530=>406,7543=>716,7544=>527,7547=>545,7549=>747,7557=>514,7579=>479,7580=>414,7581=>414,7582=>488,7583=>386,7584=>377,7585=>348,7586=>479,7587=>456,7588=>347,7589=>281,7590=>347,7591=>347,7592=>431,7593=>326,7594=>330,7595=>370,7596=>664,7597=>664,7598=>562,7599=>562,7600=>448,7601=>488,7602=>542,7603=>422,7604=>396,7605=>388,7606=>583,7607=>494,7608=>399,7609=>451,7610=>501,7611=>417,7612=>523,7613=>470,7614=>455,7615=>425,7620=>0,7621=>0,7622=>0,7623=>0,7624=>0,7625=>0,7680=>774,7681=>675,7682=>762,7683=>716,7684=>762,7685=>716,7686=>762,7687=>716,7688=>734,7689=>593,7690=>830,7691=>716,7692=>830,7693=>716,7694=>830,7695=>716,7696=>830,7697=>716,7698=>830,7699=>716,7700=>683,7701=>678,7702=>683,7703=>678,7704=>683,7705=>678,7706=>683,7707=>678,7708=>683,7709=>678,7710=>683,7711=>435,7712=>821,7713=>716,7714=>837,7715=>712,7716=>837,7717=>712,7718=>837,7719=>712,7720=>837,7721=>712,7722=>837,7723=>712,7724=>372,7725=>343,7726=>372,7727=>343,7728=>775,7729=>665,7730=>775,7731=>665,7732=>775,7733=>665,7734=>637,7735=>343,7736=>637,7737=>343,7738=>637,7739=>343,7740=>637,7741=>343,7742=>995,7743=>1042,7744=>995,7745=>1042,7746=>995,7747=>1042,7748=>837,7749=>712,7750=>837,7751=>712,7752=>837,7753=>712,7754=>837,7755=>712,7756=>850,7757=>687,7758=>850,7759=>687,7760=>850,7761=>687,7762=>850,7763=>687,7764=>733,7765=>716,7766=>733,7767=>716,7768=>770,7769=>493,7770=>770,7771=>493,7772=>770,7773=>493,7774=>770,7775=>493,7776=>720,7777=>595,7778=>720,7779=>595,7780=>720,7781=>595,7782=>720,7783=>595,7784=>720,7785=>595,7786=>682,7787=>478,7788=>682,7789=>478,7790=>682,7791=>478,7792=>682,7793=>478,7794=>812,7795=>712,7796=>812,7797=>712,7798=>812,7799=>712,7800=>812,7801=>712,7802=>812,7803=>712,7804=>774,7805=>652,7806=>774,7807=>652,7808=>1103,7809=>924,7810=>1103,7811=>924,7812=>1103,7813=>924,7814=>1103,7815=>924,7816=>1103,7817=>924,7818=>771,7819=>645,7820=>771,7821=>645,7822=>724,7823=>652,7824=>725,7825=>582,7826=>725,7827=>582,7828=>725,7829=>582,7830=>712,7831=>478,7832=>924,7833=>652,7834=>675,7835=>435,7836=>435,7837=>435,7838=>896,7839=>687,7840=>774,7841=>675,7842=>774,7843=>675,7844=>774,7845=>675,7846=>774,7847=>675,7848=>774,7849=>675,7850=>774,7851=>675,7852=>774,7853=>675,7854=>774,7855=>675,7856=>774,7857=>675,7858=>774,7859=>675,7860=>774,7861=>675,7862=>774,7863=>675,7864=>683,7865=>678,7866=>683,7867=>678,7868=>683,7869=>678,7870=>683,7871=>678,7872=>683,7873=>678,7874=>683,7875=>678,7876=>683,7877=>678,7878=>683,7879=>678,7880=>372,7881=>343,7882=>372,7883=>343,7884=>850,7885=>687,7886=>850,7887=>687,7888=>850,7889=>687,7890=>850,7891=>687,7892=>850,7893=>687,7894=>850,7895=>687,7896=>850,7897=>687,7898=>874,7899=>687,7900=>874,7901=>687,7902=>874,7903=>687,7904=>874,7905=>687,7906=>874,7907=>687,7908=>812,7909=>712,7910=>812,7911=>712,7912=>835,7913=>712,7914=>835,7915=>712,7916=>835,7917=>712,7918=>835,7919=>712,7920=>835,7921=>712,7922=>724,7923=>652,7924=>724,7925=>652,7926=>724,7927=>652,7928=>724,7929=>652,7930=>953,7931=>644,7936=>687,7937=>687,7938=>687,7939=>687,7940=>687,7941=>687,7942=>687,7943=>687,7944=>774,7945=>774,7946=>1041,7947=>1043,7948=>935,7949=>963,7950=>835,7951=>859,7952=>557,7953=>557,7954=>557,7955=>557,7956=>557,7957=>557,7960=>792,7961=>794,7962=>1100,7963=>1096,7964=>1023,7965=>1052,7968=>712,7969=>712,7970=>712,7971=>712,7972=>712,7973=>712,7974=>712,7975=>712,7976=>945,7977=>951,7978=>1250,7979=>1250,7980=>1180,7981=>1206,7982=>1054,7983=>1063,7984=>390,7985=>390,7986=>390,7987=>390,7988=>390,7989=>390,7990=>390,7991=>390,7992=>483,7993=>489,7994=>777,7995=>785,7996=>712,7997=>738,7998=>604,7999=>604,8000=>687,8001=>687,8002=>687,8003=>687,8004=>687,8005=>687,8008=>892,8009=>933,8010=>1221,8011=>1224,8012=>1053,8013=>1082,8016=>675,8017=>675,8018=>675,8019=>675,8020=>675,8021=>675,8022=>675,8023=>675,8025=>930,8027=>1184,8029=>1199,8031=>1049,8032=>869,8033=>869,8034=>869,8035=>869,8036=>869,8037=>869,8038=>869,8039=>869,8040=>909,8041=>958,8042=>1246,8043=>1251,8044=>1076,8045=>1105,8046=>1028,8047=>1076,8048=>687,8049=>687,8050=>557,8051=>557,8052=>712,8053=>712,8054=>390,8055=>390,8056=>687,8057=>687,8058=>675,8059=>675,8060=>869,8061=>869,8064=>687,8065=>687,8066=>687,8067=>687,8068=>687,8069=>687,8070=>687,8071=>687,8072=>774,8073=>774,8074=>1041,8075=>1043,8076=>935,8077=>963,8078=>835,8079=>859,8080=>712,8081=>712,8082=>712,8083=>712,8084=>712,8085=>712,8086=>712,8087=>712,8088=>945,8089=>951,8090=>1250,8091=>1250,8092=>1180,8093=>1206,8094=>1054,8095=>1063,8096=>869,8097=>869,8098=>869,8099=>869,8100=>869,8101=>869,8102=>869,8103=>869,8104=>909,8105=>958,8106=>1246,8107=>1251,8108=>1076,8109=>1105,8110=>1028,8111=>1076,8112=>687,8113=>687,8114=>687,8115=>687,8116=>687,8118=>687,8119=>687,8120=>774,8121=>774,8122=>876,8123=>797,8124=>774,8125=>500,8126=>500,8127=>500,8128=>500,8129=>500,8130=>712,8131=>712,8132=>712,8134=>712,8135=>712,8136=>929,8137=>846,8138=>1080,8139=>1009,8140=>837,8141=>500,8142=>500,8143=>500,8144=>390,8145=>390,8146=>390,8147=>390,8150=>390,8151=>390,8152=>372,8153=>372,8154=>621,8155=>563,8157=>500,8158=>500,8159=>500,8160=>675,8161=>675,8162=>675,8163=>675,8164=>716,8165=>716,8166=>675,8167=>675,8168=>724,8169=>724,8170=>1020,8171=>980,8172=>838,8173=>500,8174=>500,8175=>500,8178=>869,8179=>869,8180=>869,8182=>869,8183=>869,8184=>1065,8185=>891,8186=>1084,8187=>894,8188=>850,8189=>500,8190=>500,8192=>500,8193=>1000,8194=>500,8195=>1000,8196=>330,8197=>250,8198=>167,8199=>696,8200=>380,8201=>200,8202=>100,8203=>0,8204=>0,8205=>0,8206=>0,8207=>0,8208=>415,8209=>415,8210=>696,8211=>500,8212=>1000,8213=>1000,8214=>500,8215=>500,8216=>380,8217=>380,8218=>380,8219=>380,8220=>657,8221=>657,8222=>657,8223=>657,8224=>500,8225=>500,8226=>639,8227=>639,8228=>333,8229=>667,8230=>1000,8231=>348,8232=>0,8233=>0,8234=>0,8235=>0,8236=>0,8237=>0,8238=>0,8239=>200,8240=>1440,8241=>1887,8242=>264,8243=>447,8244=>630,8245=>264,8246=>447,8247=>630,8248=>733,8249=>412,8250=>412,8251=>972,8252=>627,8253=>580,8254=>500,8255=>828,8256=>828,8257=>329,8258=>1023,8259=>500,8260=>167,8261=>457,8262=>457,8263=>1030,8264=>829,8265=>829,8266=>513,8267=>636,8268=>500,8269=>500,8270=>523,8271=>400,8272=>828,8273=>523,8274=>556,8275=>1000,8276=>828,8277=>838,8278=>684,8279=>813,8280=>838,8281=>838,8282=>380,8283=>872,8284=>838,8285=>380,8286=>380,8287=>222,8288=>0,8289=>0,8290=>0,8291=>0,8292=>0,8298=>0,8299=>0,8300=>0,8301=>0,8302=>0,8303=>0,8304=>438,8305=>219,8308=>438,8309=>438,8310=>438,8311=>438,8312=>438,8313=>438,8314=>528,8315=>528,8316=>528,8317=>288,8318=>288,8319=>456,8320=>438,8321=>438,8322=>438,8323=>438,8324=>438,8325=>438,8326=>438,8327=>438,8328=>438,8329=>438,8330=>528,8331=>528,8332=>528,8333=>288,8334=>288,8336=>458,8337=>479,8338=>488,8339=>413,8340=>479,8341=>456,8342=>487,8343=>219,8344=>664,8345=>456,8346=>479,8347=>381,8348=>388,8352=>929,8353=>696,8354=>696,8355=>696,8356=>696,8357=>1042,8358=>837,8359=>1518,8360=>1205,8361=>1103,8362=>904,8363=>696,8364=>696,8365=>696,8366=>696,8367=>1392,8368=>696,8369=>696,8370=>696,8371=>696,8372=>859,8373=>696,8376=>696,8377=>696,8378=>769,8400=>0,8401=>0,8406=>0,8407=>0,8411=>0,8412=>0,8417=>0,8448=>1120,8449=>1170,8450=>734,8451=>1211,8452=>896,8453=>1091,8454=>1144,8455=>614,8456=>698,8457=>1086,8459=>1073,8460=>913,8461=>888,8462=>712,8463=>712,8464=>597,8465=>697,8466=>856,8467=>472,8468=>974,8469=>837,8470=>1203,8471=>1000,8472=>697,8473=>750,8474=>850,8475=>938,8476=>814,8477=>801,8478=>896,8479=>710,8480=>1020,8481=>1281,8482=>1000,8483=>755,8484=>754,8485=>578,8486=>850,8487=>850,8488=>763,8489=>338,8490=>775,8491=>774,8492=>928,8493=>818,8494=>854,8495=>636,8496=>729,8497=>808,8498=>683,8499=>1184,8500=>465,8501=>794,8502=>731,8503=>494,8504=>684,8505=>380,8506=>945,8507=>1348,8508=>790,8509=>737,8510=>654,8511=>863,8512=>840,8513=>775,8514=>557,8515=>637,8516=>760,8517=>830,8518=>716,8519=>678,8520=>343,8521=>343,8523=>872,8526=>547,8528=>1035,8529=>1035,8530=>1483,8531=>1035,8532=>1035,8533=>1035,8534=>1035,8535=>1035,8536=>1035,8537=>1035,8538=>1035,8539=>1035,8540=>1035,8541=>1035,8542=>1035,8543=>615,8544=>372,8545=>659,8546=>945,8547=>1099,8548=>774,8549=>1099,8550=>1386,8551=>1672,8552=>1121,8553=>771,8554=>1120,8555=>1407,8556=>637,8557=>734,8558=>830,8559=>995,8560=>343,8561=>607,8562=>872,8563=>984,8564=>652,8565=>962,8566=>1227,8567=>1491,8568=>969,8569=>645,8570=>969,8571=>1233,8572=>343,8573=>593,8574=>716,8575=>1042,8576=>1289,8577=>830,8578=>1289,8579=>734,8580=>593,8581=>734,8585=>1035,8592=>838,8593=>838,8594=>838,8595=>838,8596=>838,8597=>838,8598=>838,8599=>838,8600=>838,8601=>838,8602=>838,8603=>838,8604=>838,8605=>838,8606=>838,8607=>838,8608=>838,8609=>838,8610=>838,8611=>838,8612=>838,8613=>838,8614=>838,8615=>838,8616=>838,8617=>838,8618=>838,8619=>838,8620=>838,8621=>838,8622=>838,8623=>838,8624=>838,8625=>838,8626=>838,8627=>838,8628=>838,8629=>838,8630=>838,8631=>838,8632=>838,8633=>838,8634=>838,8635=>838,8636=>838,8637=>838,8638=>838,8639=>838,8640=>838,8641=>838,8642=>838,8643=>838,8644=>838,8645=>838,8646=>838,8647=>838,8648=>838,8649=>838,8650=>838,8651=>838,8652=>838,8653=>838,8654=>838,8655=>838,8656=>838,8657=>838,8658=>838,8659=>838,8660=>838,8661=>838,8662=>838,8663=>838,8664=>838,8665=>838,8666=>838,8667=>838,8668=>838,8669=>838,8670=>838,8671=>838,8672=>838,8673=>838,8674=>838,8675=>838,8676=>838,8677=>838,8678=>838,8679=>838,8680=>838,8681=>838,8682=>838,8683=>838,8684=>838,8685=>838,8686=>838,8687=>838,8688=>838,8689=>838,8690=>838,8691=>838,8692=>838,8693=>838,8694=>838,8695=>838,8696=>838,8697=>838,8698=>838,8699=>838,8700=>838,8701=>838,8702=>838,8703=>838,8704=>774,8705=>696,8706=>544,8707=>683,8708=>683,8709=>856,8710=>697,8711=>697,8712=>896,8713=>896,8714=>750,8715=>896,8716=>896,8717=>750,8718=>636,8719=>787,8720=>787,8721=>718,8722=>838,8723=>838,8724=>696,8725=>365,8726=>696,8727=>838,8728=>626,8729=>380,8730=>667,8731=>667,8732=>667,8733=>712,8734=>833,8735=>838,8736=>896,8737=>896,8738=>838,8739=>500,8740=>500,8741=>500,8742=>500,8743=>812,8744=>812,8745=>812,8746=>812,8747=>610,8748=>929,8749=>1295,8750=>563,8751=>977,8752=>1313,8753=>563,8754=>563,8755=>563,8756=>696,8757=>696,8758=>294,8759=>696,8760=>838,8761=>838,8762=>838,8763=>838,8764=>838,8765=>838,8766=>838,8767=>838,8768=>375,8769=>838,8770=>838,8771=>838,8772=>838,8773=>838,8774=>838,8775=>838,8776=>838,8777=>838,8778=>838,8779=>838,8780=>838,8781=>838,8782=>838,8783=>838,8784=>838,8785=>838,8786=>838,8787=>838,8788=>1063,8789=>1063,8790=>838,8791=>838,8792=>838,8793=>838,8794=>838,8795=>838,8796=>838,8797=>838,8798=>838,8799=>838,8800=>838,8801=>838,8802=>838,8803=>838,8804=>838,8805=>838,8806=>838,8807=>838,8808=>841,8809=>841,8810=>1047,8811=>1047,8812=>500,8813=>838,8814=>838,8815=>838,8816=>838,8817=>838,8818=>838,8819=>838,8820=>838,8821=>838,8822=>838,8823=>838,8824=>838,8825=>838,8826=>838,8827=>838,8828=>838,8829=>838,8830=>838,8831=>838,8832=>838,8833=>838,8834=>838,8835=>838,8836=>838,8837=>838,8838=>838,8839=>838,8840=>838,8841=>838,8842=>838,8843=>838,8844=>812,8845=>812,8846=>812,8847=>838,8848=>838,8849=>838,8850=>838,8851=>796,8852=>796,8853=>838,8854=>838,8855=>838,8856=>838,8857=>838,8858=>838,8859=>838,8860=>838,8861=>838,8862=>838,8863=>838,8864=>838,8865=>838,8866=>914,8867=>914,8868=>914,8869=>914,8870=>542,8871=>542,8872=>914,8873=>914,8874=>914,8875=>914,8876=>914,8877=>914,8878=>914,8879=>914,8880=>838,8881=>838,8882=>838,8883=>838,8884=>838,8885=>838,8886=>1000,8887=>1000,8888=>838,8889=>838,8890=>542,8891=>812,8892=>812,8893=>812,8894=>838,8895=>838,8896=>843,8897=>843,8898=>843,8899=>843,8900=>494,8901=>380,8902=>626,8903=>838,8904=>1000,8905=>1000,8906=>1000,8907=>1000,8908=>1000,8909=>838,8910=>812,8911=>812,8912=>838,8913=>838,8914=>838,8915=>838,8916=>838,8917=>838,8918=>838,8919=>838,8920=>1422,8921=>1422,8922=>838,8923=>838,8924=>838,8925=>838,8926=>838,8927=>838,8928=>838,8929=>838,8930=>838,8931=>838,8932=>838,8933=>838,8934=>838,8935=>838,8936=>838,8937=>838,8938=>838,8939=>838,8940=>838,8941=>838,8942=>1000,8943=>1000,8944=>1000,8945=>1000,8946=>1158,8947=>896,8948=>750,8949=>896,8950=>896,8951=>750,8952=>896,8953=>896,8954=>1158,8955=>896,8956=>750,8957=>896,8958=>750,8959=>896,8960=>602,8961=>602,8962=>716,8963=>838,8964=>838,8965=>838,8966=>838,8967=>488,8968=>457,8969=>457,8970=>457,8971=>457,8972=>809,8973=>809,8974=>809,8975=>809,8976=>838,8977=>539,8984=>928,8985=>838,8988=>469,8989=>469,8990=>469,8991=>469,8992=>610,8993=>610,8996=>1152,8997=>1152,8998=>1414,8999=>1152,9000=>1443,9003=>1414,9004=>873,9075=>390,9076=>716,9077=>869,9082=>687,9085=>863,9095=>1152,9108=>873,9115=>500,9116=>500,9117=>500,9118=>500,9119=>500,9120=>500,9121=>500,9122=>500,9123=>500,9124=>500,9125=>500,9126=>500,9127=>750,9128=>750,9129=>750,9130=>750,9131=>750,9132=>750,9133=>750,9134=>610,9166=>838,9167=>945,9187=>873,9189=>769,9192=>696,9250=>716,9251=>716,9312=>847,9313=>847,9314=>847,9315=>847,9316=>847,9317=>847,9318=>847,9319=>847,9320=>847,9321=>847,9600=>769,9601=>769,9602=>769,9603=>769,9604=>769,9605=>769,9606=>769,9607=>769,9608=>769,9609=>769,9610=>769,9611=>769,9612=>769,9613=>769,9614=>769,9615=>769,9616=>769,9617=>769,9618=>769,9619=>769,9620=>769,9621=>769,9622=>769,9623=>769,9624=>769,9625=>769,9626=>769,9627=>769,9628=>769,9629=>769,9630=>769,9631=>769,9632=>945,9633=>945,9634=>945,9635=>945,9636=>945,9637=>945,9638=>945,9639=>945,9640=>945,9641=>945,9642=>678,9643=>678,9644=>945,9645=>945,9646=>550,9647=>550,9648=>769,9649=>769,9650=>769,9651=>769,9652=>502,9653=>502,9654=>769,9655=>769,9656=>502,9657=>502,9658=>769,9659=>769,9660=>769,9661=>769,9662=>502,9663=>502,9664=>769,9665=>769,9666=>502,9667=>502,9668=>769,9669=>769,9670=>769,9671=>769,9672=>769,9673=>873,9674=>494,9675=>873,9676=>873,9677=>873,9678=>873,9679=>873,9680=>873,9681=>873,9682=>873,9683=>873,9684=>873,9685=>873,9686=>527,9687=>527,9688=>840,9689=>970,9690=>970,9691=>970,9692=>387,9693=>387,9694=>387,9695=>387,9696=>769,9697=>769,9698=>769,9699=>769,9700=>769,9701=>769,9702=>639,9703=>945,9704=>945,9705=>945,9706=>945,9707=>945,9708=>769,9709=>769,9710=>769,9711=>1119,9712=>945,9713=>945,9714=>945,9715=>945,9716=>873,9717=>873,9718=>873,9719=>873,9720=>769,9721=>769,9722=>769,9723=>830,9724=>830,9725=>732,9726=>732,9727=>769,9728=>896,9729=>1000,9730=>896,9731=>896,9732=>896,9733=>896,9734=>896,9735=>573,9736=>896,9737=>896,9738=>888,9739=>888,9740=>671,9741=>1013,9742=>1246,9743=>1250,9744=>896,9745=>896,9746=>896,9747=>532,9748=>896,9749=>896,9750=>896,9751=>896,9752=>896,9753=>896,9754=>896,9755=>896,9756=>896,9757=>609,9758=>896,9759=>609,9760=>896,9761=>896,9762=>896,9763=>896,9764=>669,9765=>746,9766=>649,9767=>784,9768=>545,9769=>896,9770=>896,9771=>896,9772=>710,9773=>896,9774=>896,9775=>896,9776=>896,9777=>896,9778=>896,9779=>896,9780=>896,9781=>896,9782=>896,9783=>896,9784=>896,9785=>1042,9786=>1042,9787=>1042,9788=>896,9789=>896,9790=>896,9791=>614,9792=>732,9793=>732,9794=>896,9795=>896,9796=>896,9797=>896,9798=>896,9799=>896,9800=>896,9801=>896,9802=>896,9803=>896,9804=>896,9805=>896,9806=>896,9807=>896,9808=>896,9809=>896,9810=>896,9811=>896,9812=>896,9813=>896,9814=>896,9815=>896,9816=>896,9817=>896,9818=>896,9819=>896,9820=>896,9821=>896,9822=>896,9823=>896,9824=>896,9825=>896,9826=>896,9827=>896,9828=>896,9829=>896,9830=>896,9831=>896,9832=>896,9833=>472,9834=>638,9835=>896,9836=>896,9837=>472,9838=>357,9839=>484,9840=>748,9841=>766,9842=>896,9843=>896,9844=>896,9845=>896,9846=>896,9847=>896,9848=>896,9849=>896,9850=>896,9851=>896,9852=>896,9853=>896,9854=>896,9855=>896,9856=>869,9857=>869,9858=>869,9859=>869,9860=>869,9861=>869,9862=>896,9863=>896,9864=>896,9865=>896,9866=>896,9867=>896,9868=>896,9869=>896,9870=>896,9871=>896,9872=>896,9873=>896,9874=>896,9875=>896,9876=>896,9877=>541,9878=>896,9879=>896,9880=>896,9881=>896,9882=>896,9883=>896,9884=>896,9888=>896,9889=>702,9890=>1004,9891=>1089,9892=>1175,9893=>903,9894=>838,9895=>838,9896=>838,9897=>838,9898=>838,9899=>838,9900=>838,9901=>838,9902=>838,9903=>838,9904=>844,9905=>838,9906=>732,9907=>732,9908=>732,9909=>732,9910=>850,9911=>732,9912=>732,9920=>838,9921=>838,9922=>838,9923=>838,9954=>732,9985=>838,9986=>838,9987=>838,9988=>838,9990=>838,9991=>838,9992=>838,9993=>838,9996=>838,9997=>838,9998=>838,9999=>838,10000=>838,10001=>838,10002=>838,10003=>838,10004=>838,10005=>838,10006=>838,10007=>838,10008=>838,10009=>838,10010=>838,10011=>838,10012=>838,10013=>838,10014=>838,10015=>838,10016=>838,10017=>838,10018=>838,10019=>838,10020=>838,10021=>838,10022=>838,10023=>838,10025=>838,10026=>838,10027=>838,10028=>838,10029=>838,10030=>838,10031=>838,10032=>838,10033=>838,10034=>838,10035=>838,10036=>838,10037=>838,10038=>838,10039=>838,10040=>838,10041=>838,10042=>838,10043=>838,10044=>838,10045=>838,10046=>838,10047=>838,10048=>838,10049=>838,10050=>838,10051=>838,10052=>838,10053=>838,10054=>838,10055=>838,10056=>838,10057=>838,10058=>838,10059=>838,10061=>896,10063=>896,10064=>896,10065=>896,10066=>896,10070=>896,10072=>838,10073=>838,10074=>838,10075=>347,10076=>347,10077=>587,10078=>587,10081=>838,10082=>838,10083=>838,10084=>838,10085=>838,10086=>838,10087=>838,10088=>838,10089=>838,10090=>838,10091=>838,10092=>838,10093=>838,10094=>838,10095=>838,10096=>838,10097=>838,10098=>838,10099=>838,10100=>838,10101=>838,10102=>847,10103=>847,10104=>847,10105=>847,10106=>847,10107=>847,10108=>847,10109=>847,10110=>847,10111=>847,10112=>838,10113=>838,10114=>838,10115=>838,10116=>838,10117=>838,10118=>838,10119=>838,10120=>838,10121=>838,10122=>838,10123=>838,10124=>838,10125=>838,10126=>838,10127=>838,10128=>838,10129=>838,10130=>838,10131=>838,10132=>838,10136=>838,10137=>838,10138=>838,10139=>838,10140=>838,10141=>838,10142=>838,10143=>838,10144=>838,10145=>838,10146=>838,10147=>838,10148=>838,10149=>838,10150=>838,10151=>838,10152=>838,10153=>838,10154=>838,10155=>838,10156=>838,10157=>838,10158=>838,10159=>838,10161=>838,10162=>838,10163=>838,10164=>838,10165=>838,10166=>838,10167=>838,10168=>838,10169=>838,10170=>838,10171=>838,10172=>838,10173=>838,10174=>838,10181=>457,10182=>457,10208=>494,10214=>487,10215=>487,10216=>457,10217=>457,10218=>721,10219=>721,10224=>838,10225=>838,10226=>838,10227=>838,10228=>1157,10229=>1434,10230=>1434,10231=>1434,10232=>1434,10233=>1434,10234=>1434,10235=>1434,10236=>1434,10237=>1434,10238=>1434,10239=>1434,10240=>781,10241=>781,10242=>781,10243=>781,10244=>781,10245=>781,10246=>781,10247=>781,10248=>781,10249=>781,10250=>781,10251=>781,10252=>781,10253=>781,10254=>781,10255=>781,10256=>781,10257=>781,10258=>781,10259=>781,10260=>781,10261=>781,10262=>781,10263=>781,10264=>781,10265=>781,10266=>781,10267=>781,10268=>781,10269=>781,10270=>781,10271=>781,10272=>781,10273=>781,10274=>781,10275=>781,10276=>781,10277=>781,10278=>781,10279=>781,10280=>781,10281=>781,10282=>781,10283=>781,10284=>781,10285=>781,10286=>781,10287=>781,10288=>781,10289=>781,10290=>781,10291=>781,10292=>781,10293=>781,10294=>781,10295=>781,10296=>781,10297=>781,10298=>781,10299=>781,10300=>781,10301=>781,10302=>781,10303=>781,10304=>781,10305=>781,10306=>781,10307=>781,10308=>781,10309=>781,10310=>781,10311=>781,10312=>781,10313=>781,10314=>781,10315=>781,10316=>781,10317=>781,10318=>781,10319=>781,10320=>781,10321=>781,10322=>781,10323=>781,10324=>781,10325=>781,10326=>781,10327=>781,10328=>781,10329=>781,10330=>781,10331=>781,10332=>781,10333=>781,10334=>781,10335=>781,10336=>781,10337=>781,10338=>781,10339=>781,10340=>781,10341=>781,10342=>781,10343=>781,10344=>781,10345=>781,10346=>781,10347=>781,10348=>781,10349=>781,10350=>781,10351=>781,10352=>781,10353=>781,10354=>781,10355=>781,10356=>781,10357=>781,10358=>781,10359=>781,10360=>781,10361=>781,10362=>781,10363=>781,10364=>781,10365=>781,10366=>781,10367=>781,10368=>781,10369=>781,10370=>781,10371=>781,10372=>781,10373=>781,10374=>781,10375=>781,10376=>781,10377=>781,10378=>781,10379=>781,10380=>781,10381=>781,10382=>781,10383=>781,10384=>781,10385=>781,10386=>781,10387=>781,10388=>781,10389=>781,10390=>781,10391=>781,10392=>781,10393=>781,10394=>781,10395=>781,10396=>781,10397=>781,10398=>781,10399=>781,10400=>781,10401=>781,10402=>781,10403=>781,10404=>781,10405=>781,10406=>781,10407=>781,10408=>781,10409=>781,10410=>781,10411=>781,10412=>781,10413=>781,10414=>781,10415=>781,10416=>781,10417=>781,10418=>781,10419=>781,10420=>781,10421=>781,10422=>781,10423=>781,10424=>781,10425=>781,10426=>781,10427=>781,10428=>781,10429=>781,10430=>781,10431=>781,10432=>781,10433=>781,10434=>781,10435=>781,10436=>781,10437=>781,10438=>781,10439=>781,10440=>781,10441=>781,10442=>781,10443=>781,10444=>781,10445=>781,10446=>781,10447=>781,10448=>781,10449=>781,10450=>781,10451=>781,10452=>781,10453=>781,10454=>781,10455=>781,10456=>781,10457=>781,10458=>781,10459=>781,10460=>781,10461=>781,10462=>781,10463=>781,10464=>781,10465=>781,10466=>781,10467=>781,10468=>781,10469=>781,10470=>781,10471=>781,10472=>781,10473=>781,10474=>781,10475=>781,10476=>781,10477=>781,10478=>781,10479=>781,10480=>781,10481=>781,10482=>781,10483=>781,10484=>781,10485=>781,10486=>781,10487=>781,10488=>781,10489=>781,10490=>781,10491=>781,10492=>781,10493=>781,10494=>781,10495=>781,10502=>838,10503=>838,10506=>838,10507=>838,10560=>838,10561=>838,10627=>753,10628=>753,10702=>838,10703=>1046,10704=>1046,10705=>1000,10706=>1000,10707=>1000,10708=>1000,10709=>1000,10731=>494,10746=>838,10747=>838,10752=>1000,10753=>1000,10754=>1000,10764=>1661,10765=>563,10766=>563,10767=>563,10768=>563,10769=>563,10770=>563,10771=>563,10772=>563,10773=>563,10774=>563,10775=>563,10776=>563,10777=>563,10778=>563,10779=>563,10780=>563,10799=>838,10858=>838,10859=>838,10877=>838,10878=>838,10879=>838,10880=>838,10881=>838,10882=>838,10883=>838,10884=>838,10885=>838,10886=>838,10887=>838,10888=>838,10889=>838,10890=>838,10891=>838,10892=>838,10893=>838,10894=>838,10895=>838,10896=>838,10897=>838,10898=>838,10899=>838,10900=>838,10901=>838,10902=>838,10903=>838,10904=>838,10905=>838,10906=>838,10907=>838,10908=>838,10909=>838,10910=>838,10911=>838,10912=>838,10926=>838,10927=>838,10928=>838,10929=>838,10930=>838,10931=>838,10932=>838,10933=>838,10934=>838,10935=>838,10936=>838,10937=>838,10938=>838,11001=>838,11002=>838,11008=>838,11009=>838,11010=>838,11011=>838,11012=>838,11013=>838,11014=>838,11015=>838,11016=>838,11017=>838,11018=>838,11019=>838,11020=>838,11021=>838,11022=>838,11023=>838,11024=>838,11025=>838,11026=>945,11027=>945,11028=>945,11029=>945,11030=>769,11031=>769,11032=>769,11033=>769,11034=>945,11039=>869,11040=>869,11041=>873,11042=>873,11043=>873,11044=>1119,11091=>869,11092=>869,11360=>637,11361=>360,11362=>637,11363=>733,11364=>770,11365=>675,11366=>478,11367=>956,11368=>712,11369=>775,11370=>665,11371=>725,11372=>582,11373=>860,11374=>995,11375=>774,11376=>860,11377=>778,11378=>1221,11379=>1056,11380=>652,11381=>698,11382=>565,11383=>782,11385=>538,11386=>687,11387=>559,11388=>219,11389=>487,11390=>720,11391=>725,11520=>663,11521=>676,11522=>661,11523=>629,11524=>661,11525=>1032,11526=>718,11527=>1032,11528=>648,11529=>667,11530=>1032,11531=>673,11532=>677,11533=>1036,11534=>680,11535=>886,11536=>1032,11537=>683,11538=>674,11539=>1035,11540=>1033,11541=>1027,11542=>676,11543=>673,11544=>667,11545=>667,11546=>660,11547=>671,11548=>1039,11549=>673,11550=>692,11551=>659,11552=>1048,11553=>660,11554=>654,11555=>670,11556=>733,11557=>1017,11568=>691,11569=>941,11570=>941,11571=>725,11572=>725,11573=>725,11574=>676,11575=>774,11576=>774,11577=>683,11578=>683,11579=>802,11580=>989,11581=>761,11582=>623,11583=>761,11584=>941,11585=>941,11586=>373,11587=>740,11588=>837,11589=>914,11590=>672,11591=>737,11592=>680,11593=>683,11594=>602,11595=>1039,11596=>778,11597=>837,11598=>683,11599=>372,11600=>778,11601=>373,11602=>725,11603=>691,11604=>941,11605=>941,11606=>837,11607=>373,11608=>836,11609=>941,11610=>941,11611=>734,11612=>876,11613=>771,11614=>734,11615=>683,11616=>774,11617=>837,11618=>683,11619=>850,11620=>697,11621=>850,11631=>716,11800=>580,11807=>838,11810=>457,11811=>457,11812=>457,11813=>457,11822=>580,19904=>896,19905=>896,19906=>896,19907=>896,19908=>896,19909=>896,19910=>896,19911=>896,19912=>896,19913=>896,19914=>896,19915=>896,19916=>896,19917=>896,19918=>896,19919=>896,19920=>896,19921=>896,19922=>896,19923=>896,19924=>896,19925=>896,19926=>896,19927=>896,19928=>896,19929=>896,19930=>896,19931=>896,19932=>896,19933=>896,19934=>896,19935=>896,19936=>896,19937=>896,19938=>896,19939=>896,19940=>896,19941=>896,19942=>896,19943=>896,19944=>896,19945=>896,19946=>896,19947=>896,19948=>896,19949=>896,19950=>896,19951=>896,19952=>896,19953=>896,19954=>896,19955=>896,19956=>896,19957=>896,19958=>896,19959=>896,19960=>896,19961=>896,19962=>896,19963=>896,19964=>896,19965=>896,19966=>896,19967=>896,42192=>762,42193=>733,42194=>733,42195=>830,42196=>682,42197=>682,42198=>821,42199=>775,42200=>775,42201=>530,42202=>734,42203=>734,42204=>725,42205=>683,42206=>683,42207=>995,42208=>837,42209=>637,42210=>720,42211=>770,42212=>770,42213=>774,42214=>774,42215=>837,42216=>775,42217=>530,42218=>1103,42219=>771,42220=>724,42221=>762,42222=>774,42223=>774,42224=>683,42225=>683,42226=>372,42227=>850,42228=>812,42229=>812,42230=>557,42231=>830,42232=>322,42233=>322,42234=>674,42235=>674,42236=>322,42237=>322,42238=>588,42239=>588,42564=>720,42565=>595,42566=>436,42567=>440,42572=>1405,42573=>1173,42576=>1234,42577=>1027,42580=>1174,42581=>972,42582=>1093,42583=>958,42594=>1085,42595=>924,42596=>1096,42597=>912,42598=>1260,42599=>997,42600=>850,42601=>687,42602=>1037,42603=>868,42604=>1406,42605=>1106,42606=>961,42634=>963,42635=>787,42636=>682,42637=>580,42644=>808,42645=>712,42760=>500,42761=>500,42762=>500,42763=>500,42764=>500,42765=>500,42766=>500,42767=>500,42768=>500,42769=>500,42770=>500,42771=>500,42772=>500,42773=>500,42774=>500,42779=>400,42780=>400,42781=>287,42782=>287,42783=>287,42786=>444,42787=>390,42788=>540,42789=>540,42790=>837,42791=>712,42792=>1031,42793=>857,42794=>696,42795=>557,42800=>559,42801=>595,42802=>1349,42803=>1052,42804=>1284,42805=>1064,42806=>1216,42807=>1054,42808=>1079,42809=>922,42810=>1079,42811=>922,42812=>1035,42813=>922,42814=>698,42815=>549,42816=>656,42817=>688,42822=>850,42823=>542,42824=>683,42825=>531,42826=>918,42827=>814,42830=>1406,42831=>1106,42832=>733,42833=>716,42834=>948,42835=>937,42838=>850,42839=>716,42852=>738,42853=>716,42854=>738,42855=>716,42880=>637,42881=>343,42882=>837,42883=>712,42889=>400,42890=>386,42891=>456,42892=>306,42893=>808,42894=>693,42896=>928,42897=>768,42912=>821,42913=>716,42914=>775,42915=>665,42916=>837,42917=>712,42918=>770,42919=>493,42920=>720,42921=>595,42922=>886,43002=>1062,43003=>683,43004=>733,43005=>995,43006=>372,43007=>1325,61184=>216,61185=>242,61186=>267,61187=>277,61188=>282,61189=>242,61190=>216,61191=>242,61192=>267,61193=>277,61194=>267,61195=>242,61196=>216,61197=>242,61198=>267,61199=>277,61200=>267,61201=>242,61202=>216,61203=>242,61204=>282,61205=>277,61206=>267,61207=>242,61208=>216,61209=>282,62464=>612,62465=>612,62466=>653,62467=>902,62468=>622,62469=>622,62470=>661,62471=>895,62472=>589,62473=>622,62474=>1163,62475=>626,62476=>627,62477=>893,62478=>612,62479=>626,62480=>924,62481=>627,62482=>744,62483=>634,62484=>886,62485=>626,62486=>907,62487=>626,62488=>621,62489=>628,62490=>677,62491=>626,62492=>621,62493=>630,62494=>627,62495=>571,62496=>622,62497=>631,62498=>612,62499=>611,62500=>618,62501=>671,62502=>963,62504=>1023,62505=>844,62506=>563,62507=>563,62508=>563,62509=>563,62510=>563,62511=>563,62512=>555,62513=>555,62514=>555,62515=>555,62516=>573,62517=>573,62518=>573,62519=>824,62520=>824,62521=>824,62522=>824,62523=>824,62524=>611,62525=>611,62526=>611,62527=>611,62528=>611,62529=>611,63173=>687,64256=>810,64257=>741,64258=>741,64259=>1115,64260=>1116,64261=>808,64262=>1020,64275=>1388,64276=>1384,64277=>1378,64278=>1384,64279=>1713,64285=>294,64286=>0,64287=>519,64288=>665,64289=>939,64290=>788,64291=>920,64292=>786,64293=>857,64294=>869,64295=>821,64296=>890,64297=>838,64298=>758,64299=>758,64300=>758,64301=>758,64302=>728,64303=>728,64304=>728,64305=>610,64306=>447,64307=>588,64308=>687,64309=>437,64310=>485,64312=>679,64313=>435,64314=>578,64315=>566,64316=>605,64318=>724,64320=>453,64321=>680,64323=>675,64324=>658,64326=>653,64327=>736,64328=>602,64329=>758,64330=>683,64331=>343,64332=>610,64333=>566,64334=>658,64335=>710,64338=>1005,64339=>1059,64340=>375,64341=>408,64342=>1005,64343=>1059,64344=>375,64345=>408,64346=>1005,64347=>1059,64348=>375,64349=>408,64350=>1005,64351=>1059,64352=>375,64353=>408,64354=>1005,64355=>1059,64356=>375,64357=>408,64358=>1005,64359=>1059,64360=>375,64361=>408,64362=>1162,64363=>1191,64364=>655,64365=>720,64366=>1162,64367=>1191,64368=>655,64369=>720,64370=>721,64371=>721,64372=>721,64373=>721,64374=>721,64375=>721,64376=>721,64377=>721,64378=>721,64379=>721,64380=>721,64381=>721,64382=>721,64383=>721,64384=>721,64385=>721,64386=>513,64387=>578,64388=>513,64389=>578,64390=>513,64391=>578,64392=>513,64393=>578,64394=>576,64395=>622,64396=>576,64397=>622,64398=>1024,64399=>1024,64400=>582,64401=>582,64402=>1024,64403=>1024,64404=>582,64405=>582,64406=>1024,64407=>1024,64408=>582,64409=>582,64410=>1024,64411=>1024,64412=>582,64413=>582,64414=>854,64415=>900,64416=>854,64417=>900,64418=>375,64419=>408,64426=>938,64427=>880,64428=>693,64429=>660,64467=>824,64468=>843,64469=>476,64470=>552,64473=>622,64474=>627,64488=>375,64489=>408,64508=>917,64509=>1012,64510=>375,64511=>408,65024=>0,65025=>0,65026=>0,65027=>0,65028=>0,65029=>0,65030=>0,65031=>0,65032=>0,65033=>0,65034=>0,65035=>0,65036=>0,65037=>0,65038=>0,65039=>0,65056=>0,65057=>0,65058=>0,65059=>0,65136=>342,65137=>342,65138=>342,65139=>346,65140=>342,65142=>342,65143=>342,65144=>342,65145=>342,65146=>342,65147=>342,65148=>342,65149=>342,65150=>342,65151=>342,65152=>511,65153=>343,65154=>375,65155=>343,65156=>375,65157=>622,65158=>627,65159=>343,65160=>375,65161=>917,65162=>917,65163=>375,65164=>408,65165=>343,65166=>375,65167=>1005,65168=>1059,65169=>375,65170=>408,65171=>590,65172=>606,65173=>1005,65174=>1059,65175=>375,65176=>408,65177=>1005,65178=>1059,65179=>375,65180=>408,65181=>721,65182=>721,65183=>721,65184=>721,65185=>721,65186=>721,65187=>721,65188=>721,65189=>721,65190=>721,65191=>721,65192=>721,65193=>513,65194=>578,65195=>513,65196=>578,65197=>576,65198=>622,65199=>576,65200=>622,65201=>1380,65202=>1414,65203=>983,65204=>1018,65205=>1380,65206=>1414,65207=>983,65208=>1018,65209=>1345,65210=>1364,65211=>966,65212=>985,65213=>1345,65214=>1364,65215=>966,65216=>985,65217=>1039,65218=>1071,65219=>942,65220=>974,65221=>1039,65222=>1071,65223=>942,65224=>974,65225=>683,65226=>683,65227=>683,65228=>564,65229=>683,65230=>683,65231=>683,65232=>564,65233=>1162,65234=>1191,65235=>655,65236=>720,65237=>894,65238=>901,65239=>655,65240=>720,65241=>917,65242=>931,65243=>582,65244=>582,65245=>868,65246=>893,65247=>375,65248=>408,65249=>733,65250=>784,65251=>619,65252=>670,65253=>854,65254=>900,65255=>375,65256=>408,65257=>590,65258=>606,65259=>693,65260=>660,65261=>622,65262=>627,65263=>917,65264=>1012,65265=>917,65266=>1012,65267=>375,65268=>408,65269=>745,65270=>759,65271=>745,65272=>759,65273=>745,65274=>759,65275=>745,65276=>759,65279=>0,65529=>0,65530=>0,65531=>0,65532=>0,65533=>1113,65535=>600); -// --- EOF --- diff --git a/lib/combodo/tcpdf/fonts/dejavusansb.z b/lib/combodo/tcpdf/fonts/dejavusansb.z deleted file mode 100644 index 07031ce34da2e7d17ce67aa85fea28fe941c4444..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 347269 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

  • Fuxq%KVOq`rn8%vyfGZgckX3z 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 z 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

    Em|_`oNolqBVruS4V_`Vm~j22-JQ#~DMWWy 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 P diff --git a/lib/combodo/tcpdf/fonts/dejavusansbi.ctg.z b/lib/combodo/tcpdf/fonts/dejavusansbi.ctg.z deleted file mode 100644 index 23445ef2f4ba7cbb6b067515a98d6500f62a23f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9101 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 diff --git a/lib/combodo/tcpdf/fonts/dejavusansbi.php b/lib/combodo/tcpdf/fonts/dejavusansbi.php deleted file mode 100644 index e4a66708b..000000000 --- a/lib/combodo/tcpdf/fonts/dejavusansbi.php +++ /dev/null @@ -1,16 +0,0 @@ -96,'FontBBox'=>'[-1067 -385 1999 1121]','ItalicAngle'=>-11,'Ascent'=>928,'Descent'=>-236,'Leading'=>0,'CapHeight'=>729,'XHeight'=>547,'StemV'=>60,'StemH'=>26,'AvgWidth'=>573,'MaxWidth'=>2016,'MissingWidth'=>600); -$cbbox=array(0=>array(50,-177,550,705),33=>array(69,0,387,729),34=>array(95,458,426,729),35=>array(65,0,780,718),36=>array(27,-147,630,760),37=>array(55,-14,947,742),38=>array(28,-14,813,742),39=>array(95,458,211,729),40=>array(77,-132,468,759),41=>array(-27,-132,364,759),42=>array(20,278,503,742),43=>array(106,0,732,627),44=>array(-34,-142,256,189),45=>array(25,217,360,359),46=>array(46,0,259,189),47=>array(-96,-93,434,729),48=>array(36,-14,660,742),49=>array(43,0,578,729),50=>array(8,0,640,742),51=>array(0,-14,637,742),52=>array(-1,0,635,729),53=>array(13,-14,644,729),54=>array(50,-15,660,741),55=>array(78,0,694,729),56=>array(22,-14,659,742),57=>array(41,-15,652,741),58=>array(41,0,323,547),59=>array(-35,-142,323,547),60=>array(106,30,732,597),61=>array(106,144,732,482),62=>array(106,30,732,597),63=>array(104,0,554,742),64=>array(45,-172,927,703),65=>array(-65,0,691,729),66=>array(21,0,699,729),67=>array(36,-14,724,742),68=>array(21,0,786,729),69=>array(21,0,670,729),70=>array(21,0,670,729),71=>array(36,-14,778,742),72=>array(21,0,816,729),73=>array(21,0,351,729),74=>array(-166,-200,351,729),75=>array(21,0,837,729),76=>array(21,0,566,729),77=>array(21,0,974,729),78=>array(21,0,816,729),79=>array(36,-14,814,742),80=>array(21,0,719,729),81=>array(36,-146,814,742),82=>array(21,0,685,729),83=>array(15,-14,665,742),84=>array(48,0,748,729),85=>array(68,-14,791,729),86=>array(76,0,840,729),87=>array(107,0,1143,729),88=>array(-51,0,812,729),89=>array(63,0,809,729),90=>array(-26,0,740,729),91=>array(-10,-132,466,760),92=>array(71,-93,276,729),93=>array(-28,-132,448,760),94=>array(101,457,737,729),95=>array(-10,-236,510,-143),96=>array(131,616,371,800),97=>array(17,-14,611,560),98=>array(31,-14,677,760),99=>array(37,-14,581,560),100=>array(36,-14,724,760),101=>array(36,-14,640,560),102=>array(50,0,540,760),103=>array(20,-216,682,559),104=>array(31,0,654,760),105=>array(31,0,354,760),106=>array(-128,-216,354,760),107=>array(31,0,716,760),108=>array(31,0,354,760),109=>array(31,0,984,560),110=>array(31,0,654,560),111=>array(36,-14,651,560),112=>array(-10,-208,677,560),113=>array(36,-208,682,560),114=>array(31,0,545,560),115=>array(10,-14,560,560),116=>array(43,0,509,702),117=>array(60,-14,681,547),118=>array(63,0,678,547),119=>array(87,0,927,547),120=>array(-41,0,671,547),121=>array(0,-216,687,547),122=>array(-9,0,586,547),123=>array(106,-163,669,760),124=>array(127,-236,238,764),125=>array(44,-163,606,760),126=>array(106,212,732,415),161=>array(69,0,387,729),162=>array(67,-153,610,699),163=>array(7,0,691,742),164=>array(36,30,601,596),165=>array(6,0,755,729),166=>array(127,-171,238,699),167=>array(-33,-95,494,742),168=>array(152,654,484,774),169=>array(138,0,862,725),170=>array(43,182,527,742),171=>array(61,67,594,519),172=>array(106,140,732,444),173=>array(25,217,360,359),174=>array(138,0,862,725),175=>array(155,668,481,760),176=>array(87,424,412,749),177=>array(106,0,732,627),178=>array(45,326,431,742),179=>array(40,319,427,742),180=>array(227,616,539,800),181=>array(-27,-209,670,547),182=>array(74,-96,603,729),183=>array(84,253,297,442),184=>array(22,-196,259,0),185=>array(67,326,395,734),186=>array(46,182,545,742),187=>array(57,66,589,519),188=>array(56,-14,948,742),189=>array(56,-14,1036,742),190=>array(47,-14,948,742),191=>array(37,-13,488,729),192=>array(-65,0,691,927),193=>array(-65,0,691,927),194=>array(-65,0,691,927),195=>array(-65,0,691,928),196=>array(-65,0,691,927),197=>array(-65,0,691,928),198=>array(-78,0,1072,729),199=>array(36,-196,724,742),200=>array(21,0,670,927),201=>array(21,0,670,927),202=>array(21,0,670,927),203=>array(21,0,670,927),204=>array(21,0,351,927),205=>array(21,0,448,927),206=>array(21,0,440,927),207=>array(21,0,442,927),208=>array(-2,0,803,729),209=>array(21,0,816,928),210=>array(36,-14,814,927),211=>array(36,-14,814,927),212=>array(36,-14,814,927),213=>array(36,-14,814,928),214=>array(36,-14,814,927),215=>array(125,20,713,607),216=>array(-47,-38,896,771),217=>array(68,-14,791,927),218=>array(68,-14,791,927),219=>array(68,-14,791,927),220=>array(68,-14,791,927),221=>array(63,0,809,927),222=>array(21,0,695,729),223=>array(31,-14,666,760),224=>array(17,-14,611,800),225=>array(17,-14,627,800),226=>array(17,-14,611,800),227=>array(17,-14,611,778),228=>array(17,-14,611,774),229=>array(17,-14,611,883),230=>array(17,-14,1008,560),231=>array(37,-196,581,560),232=>array(36,-14,640,800),233=>array(36,-14,650,800),234=>array(36,-14,640,800),235=>array(36,-14,640,774),236=>array(31,0,313,800),237=>array(31,0,470,800),238=>array(31,0,414,800),239=>array(31,0,415,774),240=>array(36,-14,678,760),241=>array(31,0,654,778),242=>array(36,-14,651,800),243=>array(36,-14,651,800),244=>array(36,-14,651,800),245=>array(36,-14,651,778),246=>array(36,-14,651,774),247=>array(106,42,732,585),248=>array(-17,-50,700,597),249=>array(60,-14,681,800),250=>array(60,-14,681,800),251=>array(60,-14,681,800),252=>array(60,-14,681,774),253=>array(0,-216,687,800),254=>array(-10,-208,677,760),255=>array(0,-216,687,774),256=>array(-65,0,691,914),257=>array(17,-14,611,763),258=>array(-65,0,691,936),259=>array(17,-14,611,772),260=>array(-65,-196,691,729),261=>array(17,-196,611,560),262=>array(36,-14,724,927),263=>array(37,-14,645,800),264=>array(36,-14,724,927),265=>array(37,-14,589,800),266=>array(36,-14,724,927),267=>array(37,-14,581,759),268=>array(36,-14,732,927),269=>array(37,-14,634,800),270=>array(21,0,786,927),271=>array(36,-14,947,760),272=>array(-2,0,803,729),273=>array(36,-14,817,760),274=>array(21,0,670,914),275=>array(36,-14,640,763),276=>array(21,0,670,927),277=>array(36,-14,640,784),278=>array(21,0,670,927),279=>array(36,-14,640,759),280=>array(21,-196,670,729),281=>array(36,-196,640,560),282=>array(21,0,670,927),283=>array(36,-14,640,800),284=>array(36,-14,778,927),285=>array(20,-216,682,800),286=>array(36,-14,778,927),287=>array(20,-216,682,784),288=>array(36,-14,778,927),289=>array(20,-216,682,759),290=>array(36,-224,778,742),291=>array(20,-216,682,765),292=>array(21,0,816,927),293=>array(31,0,654,927),294=>array(89,0,935,729),295=>array(85,0,708,760),296=>array(21,0,456,928),297=>array(31,0,431,778),298=>array(21,0,417,914),299=>array(31,0,402,763),300=>array(21,0,453,927),301=>array(31,0,427,784),302=>array(21,-196,351,729),303=>array(31,-196,354,760),304=>array(21,0,355,927),305=>array(31,0,313,547),306=>array(21,-200,723,729),307=>array(31,-216,697,760),308=>array(-166,-200,453,927),309=>array(-128,-216,428,800),310=>array(21,-209,837,729),311=>array(31,-209,716,760),312=>array(31,0,716,547),313=>array(21,0,566,928),314=>array(31,0,478,928),315=>array(21,-209,566,729),316=>array(-23,-209,354,760),317=>array(21,0,623,729),318=>array(31,0,582,760),319=>array(21,0,624,729),320=>array(31,0,555,760),321=>array(-23,0,603,729),322=>array(-7,0,456,760),323=>array(21,0,816,928),324=>array(31,0,654,803),325=>array(21,-209,816,729),326=>array(31,-209,654,560),327=>array(21,0,816,927),328=>array(31,0,654,800),329=>array(61,0,911,729),330=>array(31,-200,775,742),331=>array(50,-216,673,560),332=>array(36,-14,814,914),333=>array(36,-14,651,763),334=>array(36,-14,814,927),335=>array(36,-14,651,784),336=>array(36,-14,814,927),337=>array(36,-14,657,800),338=>array(42,0,1154,729),339=>array(36,-14,1054,560),340=>array(21,0,685,928),341=>array(31,0,618,803),342=>array(21,-209,685,729),343=>array(-23,-209,545,560),344=>array(21,0,685,927),345=>array(31,0,602,800),346=>array(15,-14,665,928),347=>array(10,-14,618,803),348=>array(15,-14,665,927),349=>array(10,-14,560,800),350=>array(15,-196,665,742),351=>array(10,-196,560,560),352=>array(15,-14,665,927),353=>array(10,-14,576,800),354=>array(48,-196,748,729),355=>array(43,-196,509,702),356=>array(48,0,748,927),357=>array(43,0,615,800),358=>array(48,0,748,729),359=>array(-11,0,493,702),360=>array(68,-14,791,928),361=>array(60,-14,681,778),362=>array(68,-14,791,914),363=>array(60,-14,681,763),364=>array(68,-14,791,927),365=>array(60,-14,681,784),366=>array(68,-14,791,923),367=>array(60,-14,681,873),368=>array(68,-14,791,927),369=>array(60,-14,681,800),370=>array(68,-196,791,729),371=>array(60,-196,681,547),372=>array(107,0,1143,931),373=>array(87,0,927,800),374=>array(63,0,809,931),375=>array(0,-216,687,800),376=>array(63,0,809,927),377=>array(-26,0,740,928),378=>array(-9,0,618,803),379=>array(-26,0,740,918),380=>array(-9,0,586,759),381=>array(-26,0,740,927),382=>array(-9,0,586,800),383=>array(50,0,540,760),384=>array(12,-14,651,760),385=>array(-37,0,744,729),386=>array(21,0,714,729),387=>array(12,-14,662,760),388=>array(61,0,704,729),389=>array(37,-14,677,760),390=>array(-13,-14,675,742),391=>array(32,-14,909,924),392=>array(27,-14,715,724),393=>array(-2,0,803,729),394=>array(-37,0,830,729),395=>array(65,0,763,729),396=>array(25,-14,707,760),397=>array(57,-208,662,548),398=>array(21,0,681,729),399=>array(36,-14,819,742),400=>array(37,-14,652,742),401=>array(-146,-200,689,729),402=>array(-151,-208,538,760),403=>array(32,-14,959,924),404=>array(94,-210,882,729),405=>array(10,-1,980,760),406=>array(74,0,384,729),407=>array(-7,0,397,729),408=>array(20,0,827,742),409=>array(10,0,695,760),410=>array(-10,0,365,760),411=>array(-44,0,536,760),412=>array(55,-13,1035,729),413=>array(-146,-200,835,729),414=>array(50,-208,664,560),415=>array(36,-14,814,742),416=>array(39,-14,907,760),417=>array(40,-14,771,570),418=>array(50,-14,1056,742),419=>array(63,-216,891,560),420=>array(-37,0,765,729),421=>array(-10,-208,670,760),422=>array(35,-146,684,729),423=>array(-1,-14,631,742),424=>array(-7,-14,534,560),425=>array(21,0,670,729),426=>array(34,-217,539,759),427=>array(48,-216,514,702),428=>array(36,0,772,729),429=>array(21,0,512,760),430=>array(67,-200,767,729),431=>array(67,-14,938,761),432=>array(57,-14,795,570),433=>array(42,-14,813,723),434=>array(74,0,764,729),435=>array(60,0,841,742),436=>array(24,-216,822,560),437=>array(-26,0,740,729),438=>array(-8,0,587,547),439=>array(21,-33,743,729),440=>array(10,-33,771,729),441=>array(6,-215,647,547),442=>array(-11,-208,585,547),443=>array(7,0,634,742),444=>array(11,-33,696,729),445=>array(-30,-215,573,547),446=>array(-27,-15,508,702),447=>array(-12,-208,693,560),448=>array(0,-208,371,729),449=>array(0,-208,658,729),450=>array(-23,-208,574,729),451=>array(27,0,346,729),452=>array(21,0,1570,927),453=>array(21,0,1416,800),454=>array(36,-14,1302,800),455=>array(21,-200,988,729),456=>array(21,-216,991,760),457=>array(31,-216,697,760),458=>array(21,-200,1188,729),459=>array(21,-216,1191,760),460=>array(31,-216,1066,760),461=>array(-65,0,691,927),462=>array(17,-14,615,800),463=>array(21,0,473,927),464=>array(31,0,457,800),465=>array(36,-14,814,927),466=>array(36,-14,651,800),467=>array(68,-14,791,927),468=>array(60,-14,681,800),469=>array(68,-14,791,1040),470=>array(60,-14,681,914),471=>array(68,-14,791,1057),472=>array(60,-14,681,917),473=>array(68,-14,791,1058),474=>array(60,-14,681,917),475=>array(68,-14,791,1057),476=>array(60,-14,681,917),477=>array(42,-14,630,560),478=>array(-65,0,691,1040),479=>array(17,-14,611,914),480=>array(-65,0,691,1040),481=>array(17,-14,620,881),482=>array(-78,0,1072,914),483=>array(17,-14,1008,758),484=>array(36,-14,778,742),485=>array(20,-216,682,559),486=>array(36,-14,778,927),487=>array(20,-216,682,799),488=>array(21,0,837,926),489=>array(31,0,716,926),490=>array(36,-196,814,742),491=>array(36,-196,651,560),492=>array(36,-196,814,914),493=>array(36,-196,651,763),494=>array(21,-33,743,927),495=>array(-44,-215,588,793),496=>array(-128,-216,466,800),497=>array(21,0,1570,729),498=>array(21,0,1416,729),499=>array(36,-14,1302,760),500=>array(36,-14,778,928),501=>array(20,-216,682,798),502=>array(22,-14,1222,729),503=>array(-20,-208,775,742),504=>array(21,0,816,927),505=>array(31,0,654,798),506=>array(-65,0,867,986),507=>array(17,-14,814,931),508=>array(-78,0,1072,928),509=>array(17,-14,1008,799),510=>array(-47,-38,896,928),511=>array(-17,-50,700,800),512=>array(-65,0,691,930),513=>array(17,-14,611,800),514=>array(-65,0,691,947),515=>array(17,-14,611,784),516=>array(21,0,670,930),517=>array(36,-14,640,800),518=>array(21,0,670,947),519=>array(36,-14,640,784),520=>array(21,0,437,930),521=>array(31,0,409,799),522=>array(21,0,447,947),523=>array(31,0,417,784),524=>array(36,-14,814,930),525=>array(36,-14,651,800),526=>array(36,-14,814,947),527=>array(36,-14,651,784),528=>array(21,0,685,930),529=>array(31,0,545,800),530=>array(21,0,685,947),531=>array(31,0,545,784),532=>array(68,-14,791,930),533=>array(60,-14,681,800),534=>array(68,-14,791,947),535=>array(60,-14,681,784),536=>array(15,-236,665,742),537=>array(10,-236,560,560),538=>array(48,-236,748,729),539=>array(43,-236,509,702),540=>array(-45,-210,649,742),541=>array(-47,-211,564,560),542=>array(21,0,816,926),543=>array(31,0,654,926),544=>array(32,-208,764,742),545=>array(31,-75,786,760),546=>array(25,-14,769,742),547=>array(22,-14,656,646),548=>array(-5,-216,761,729),549=>array(13,-216,608,547),550=>array(-65,0,691,927),551=>array(17,-14,611,759),552=>array(21,-192,670,729),553=>array(36,-196,640,560),554=>array(36,-14,814,1040),555=>array(36,-14,651,914),556=>array(36,-14,814,1040),557=>array(36,-14,651,914),558=>array(36,-14,814,928),559=>array(36,-14,651,759),560=>array(36,-14,814,1040),561=>array(36,-14,651,914),562=>array(63,0,809,914),563=>array(0,-216,687,763),564=>array(32,-75,413,760),565=>array(37,-75,808,560),566=>array(34,-76,500,702),567=>array(-128,-216,313,547),568=>array(25,-14,1023,760),569=>array(64,-208,1062,560),570=>array(-81,-36,854,765),571=>array(-101,-36,834,765),572=>array(-61,-46,652,594),573=>array(-13,0,566,729),574=>array(-127,-36,809,765),575=>array(33,-240,583,560),576=>array(15,-240,611,547),577=>array(69,0,765,729),578=>array(56,0,582,560),579=>array(-35,0,695,729),580=>array(20,-14,804,729),581=>array(-66,0,698,729),582=>array(21,-93,681,822),583=>array(36,-93,638,640),584=>array(-166,-200,368,729),585=>array(-128,-216,368,760),586=>array(66,-200,863,741),587=>array(64,-216,747,560),588=>array(-12,0,685,729),589=>array(-33,0,543,560),590=>array(30,0,805,729),591=>array(10,-216,708,547),592=>array(66,-14,660,560),593=>array(45,-14,685,560),594=>array(-8,-14,632,560),595=>array(12,-14,651,760),596=>array(-7,-14,537,560),597=>array(48,-69,581,560),598=>array(45,-216,727,760),599=>array(25,-14,876,760),600=>array(22,-14,630,560),601=>array(42,-14,630,560),602=>array(38,-14,890,560),603=>array(27,-14,520,560),604=>array(-50,-11,509,560),605=>array(-50,-11,788,560),606=>array(54,-14,679,560),607=>array(-107,-216,388,547),608=>array(23,-216,896,760),609=>array(44,-216,706,547),610=>array(43,-14,573,546),611=>array(87,-211,692,547),612=>array(80,-21,674,547),613=>array(88,-214,703,546),614=>array(10,0,625,760),615=>array(31,-216,646,760),616=>array(52,0,448,760),617=>array(74,-1,326,547),618=>array(31,0,515,547),619=>array(70,0,488,760),620=>array(93,0,613,760),621=>array(32,-216,356,760),622=>array(31,-215,788,760),623=>array(69,-14,1013,546),624=>array(88,-209,1032,546),625=>array(49,-216,994,560),626=>array(-160,-216,665,560),627=>array(50,-216,749,560),628=>array(-32,0,613,547),629=>array(36,-14,651,560),630=>array(43,-1,871,547),631=>array(-9,0,580,574),632=>array(60,-208,729,760),633=>array(31,-13,544,547),634=>array(10,-13,565,760),635=>array(50,-216,607,547),636=>array(9,-208,563,560),637=>array(51,-216,564,560),638=>array(31,0,583,547),639=>array(99,0,499,547),640=>array(-32,0,509,547),641=>array(-32,0,613,547),642=>array(28,-216,581,560),643=>array(-126,-216,519,760),644=>array(-106,-216,539,760),645=>array(137,-216,486,560),646=>array(-97,-217,655,760),647=>array(-25,-155,441,547),648=>array(48,-216,514,702),649=>array(74,-14,845,547),650=>array(22,-51,690,547),651=>array(74,-1,626,547),652=>array(-38,0,584,547),653=>array(-18,0,836,547),654=>array(-62,0,620,763),655=>array(53,0,648,547),656=>array(13,-216,651,547),657=>array(-1,-69,599,547),658=>array(-23,-215,608,547),659=>array(25,-215,608,547),660=>array(59,0,546,759),661=>array(57,0,592,759),662=>array(-31,0,504,759),663=>array(-5,-208,612,759),664=>array(50,-14,800,742),665=>array(31,0,593,547),666=>array(31,-14,665,560),667=>array(22,0,768,760),668=>array(28,0,658,547),669=>array(-235,-217,354,760),670=>array(73,-213,758,547),671=>array(31,0,473,547),672=>array(44,-208,895,760),673=>array(-3,0,546,759),674=>array(57,0,592,759),675=>array(25,-14,1142,760),676=>array(45,-215,1161,760),677=>array(29,-55,1145,760),678=>array(27,0,926,702),679=>array(42,-216,872,760),680=>array(34,-69,923,702),681=>array(48,-216,990,760),682=>array(10,0,808,760),683=>array(10,0,764,760),684=>array(20,0,631,641),685=>array(-31,86,399,641),686=>array(-18,-214,682,760),687=>array(-16,-216,724,760),688=>array(12,326,401,751),689=>array(12,326,400,751),690=>array(-75,205,219,751),691=>array(23,326,344,640),692=>array(24,319,344,632),693=>array(35,205,392,632),694=>array(-16,326,388,632),695=>array(52,326,599,632),696=>array(22,205,447,632),697=>array(78,557,218,800),698=>array(78,557,437,800),699=>array(113,418,389,729),700=>array(73,418,348,729),701=>array(198,616,347,856),702=>array(168,481,334,760),703=>array(159,481,325,760),704=>array(43,326,348,751),705=>array(35,326,374,751),706=>array(184,517,463,843),707=>array(161,517,440,843),708=>array(125,561,452,800),709=>array(172,561,499,800),710=>array(106,616,483,800),711=>array(151,616,528,800),712=>array(81,488,226,759),713=>array(155,668,481,760),714=>array(227,616,539,800),715=>array(131,616,371,800),716=>array(81,-81,226,190),717=>array(-11,-185,315,-93),718=>array(131,-238,371,-54),719=>array(227,-238,539,-54),720=>array(-8,0,299,547),721=>array(63,361,264,547),722=>array(126,269,292,547),723=>array(118,269,284,547),724=>array(116,238,353,458),725=>array(145,238,382,458),726=>array(46,119,370,427),727=>array(46,229,282,317),728=>array(166,639,496,784),729=>array(239,654,397,774),730=>array(184,605,462,883),731=>array(73,-196,284,0),732=>array(133,638,500,778),733=>array(143,616,563,800),734=>array(-12,213,347,524),735=>array(163,616,474,800),736=>array(36,213,458,637),737=>array(12,326,207,751),738=>array(11,318,355,640),739=>array(-20,326,427,632),740=>array(35,326,374,751),741=>array(146,0,471,693),742=>array(117,0,471,693),743=>array(87,0,471,693),744=>array(58,0,471,693),745=>array(29,0,471,693),748=>array(14,-260,340,-21),749=>array(143,605,492,822),750=>array(73,418,612,729),755=>array(91,-240,369,38),759=>array(88,-221,455,-109),768=>array(-259,616,-19,800),769=>array(-160,616,152,800),770=>array(-287,616,90,800),771=>array(-257,638,110,778),772=>array(-235,668,91,760),773=>array(-346,663,174,755),774=>array(-221,639,109,784),775=>array(-184,617,18,760),776=>array(-238,654,94,774),777=>array(-363,616,-117,843),778=>array(-200,605,78,883),779=>array(-244,616,176,800),780=>array(-236,616,141,800),781=>array(-130,615,4,832),782=>array(-223,615,97,832),783=>array(-279,616,70,800),784=>array(-221,642,109,882),785=>array(-250,639,80,784),786=>array(-264,418,-34,563),787=>array(-313,595,-130,844),788=>array(-288,595,-130,844),789=>array(-102,616,102,800),790=>array(-474,-276,-233,-93),791=>array(-406,-276,-94,-93),792=>array(-388,-240,-188,-6),793=>array(-318,-240,-118,-6),794=>array(-216,658,73,929),795=>array(-132,361,83,570),796=>array(-331,-240,-193,-11),797=>array(-403,-240,-114,-59),798=>array(-389,-240,-100,-59),799=>array(-378,-240,-128,-6),800=>array(-296,-202,-7,-110),801=>array(-514,-216,-105,117),802=>array(-310,-216,13,117),803=>array(-412,-212,-253,-92),804=>array(-442,-212,-110,-92),805=>array(-366,-240,-136,-11),806=>array(-392,-236,-162,-91),807=>array(-478,-196,-241,0),808=>array(-427,-196,-216,0),809=>array(-363,-310,-228,-93),810=>array(-422,-237,-80,-54),811=>array(-477,-239,-75,-94),812=>array(-414,-240,-37,-57),813=>array(-458,-240,-82,-57),814=>array(-424,-239,-94,-94),815=>array(-491,-240,-161,-95),816=>array(-480,-234,-113,-94),817=>array(-440,-185,-114,-93),818=>array(-565,-236,-28,-143),819=>array(-568,-236,-4,-9),820=>array(-625,212,1,415),821=>array(-480,214,-84,309),822=>array(-847,214,-77,309),823=>array(-709,-46,4,594),824=>array(-893,-36,43,765),825=>array(-308,-240,-170,-11),826=>array(-422,-238,-80,-55),827=>array(-355,-241,-75,-6),828=>array(-501,-239,-100,-94),829=>array(-392,562,-110,819),830=>array(-292,595,-101,867),831=>array(-510,528,10,755),832=>array(-259,616,-19,800),833=>array(-160,616,152,800),834=>array(-257,638,110,778),835=>array(-313,595,-130,844),836=>array(-344,654,94,978),837=>array(-365,-208,-244,-45),838=>array(-418,639,-82,786),839=>array(-378,-226,-122,-35),840=>array(-398,-240,-102,-47),841=>array(-363,-240,-111,-21),842=>array(-434,616,-68,800),843=>array(-434,567,-66,850),844=>array(-438,573,-31,835),845=>array(-459,-230,-41,-30),846=>array(-371,-240,-141,-45),849=>array(-321,610,-152,888),850=>array(-250,604,80,882),851=>array(-378,-240,-124,-9),855=>array(-348,610,-179,888),856=>array(0,654,159,774),858=>array(-445,-240,-58,-11),860=>array(-471,-237,419,-79),861=>array(-278,802,613,960),862=>array(-291,797,618,889),863=>array(-481,-185,427,-93),864=>array(-291,756,459,894),865=>array(-278,769,613,927),866=>array(-533,-230,376,-30),880=>array(21,0,623,729),881=>array(31,0,494,547),882=>array(88,0,1001,729),883=>array(88,0,815,729),884=>array(78,557,218,800),885=>array(54,-208,242,35),886=>array(21,0,816,729),887=>array(31,0,670,547),890=>array(132,-208,253,-45),891=>array(-7,-14,537,560),892=>array(37,-14,581,560),893=>array(-7,-14,537,560),894=>array(-35,-142,323,547),900=>array(216,616,528,800),901=>array(152,654,589,978),902=>array(-42,0,714,800),903=>array(84,253,297,442),904=>array(22,0,831,800),905=>array(28,0,986,800),906=>array(25,0,521,800),908=>array(28,-14,851,800),910=>array(20,0,1067,800),911=>array(-1,0,855,800),912=>array(50,-19,516,978),913=>array(-65,0,691,729),914=>array(21,0,699,729),915=>array(21,0,681,729),916=>array(-66,0,698,729),917=>array(21,0,670,729),918=>array(-26,0,740,729),919=>array(21,0,816,729),920=>array(40,-14,810,742),921=>array(21,0,351,729),922=>array(21,0,837,729),923=>array(-66,0,698,729),924=>array(21,0,974,729),925=>array(21,0,816,729),926=>array(27,0,619,729),927=>array(36,-14,814,742),928=>array(21,0,816,729),929=>array(21,0,719,729),931=>array(21,0,670,729),932=>array(48,0,748,729),933=>array(63,0,809,729),934=>array(43,0,806,729),935=>array(-51,0,812,729),936=>array(78,0,866,729),937=>array(-45,0,812,742),938=>array(21,0,450,927),939=>array(63,0,809,927),940=>array(38,-12,692,800),941=>array(27,-14,567,800),942=>array(50,-208,664,800),943=>array(42,-19,436,800),944=>array(54,-10,660,978),945=>array(38,-12,692,559),946=>array(-11,-208,660,773),947=>array(66,-208,740,547),948=>array(16,-14,634,768),949=>array(27,-14,520,560),950=>array(32,-208,627,760),951=>array(50,-208,664,560),952=>array(28,-11,659,768),953=>array(42,-19,313,547),954=>array(31,0,679,547),955=>array(-44,0,529,760),956=>array(-27,-209,670,547),957=>array(68,0,653,547),958=>array(26,-208,627,760),959=>array(36,-14,651,560),960=>array(73,-19,787,547),961=>array(9,-208,699,562),962=>array(55,-208,595,560),963=>array(37,-14,781,547),964=>array(52,-19,667,547),965=>array(54,-10,645,547),966=>array(76,-208,752,552),967=>array(-48,-208,693,547),968=>array(79,-208,797,547),969=>array(33,-13,834,547),970=>array(50,-19,407,774),971=>array(54,-10,645,774),972=>array(36,-14,651,800),973=>array(54,-10,645,800),974=>array(33,-13,834,800),975=>array(41,-208,860,729),976=>array(55,-11,601,768),977=>array(46,-11,612,768),978=>array(63,0,751,729),979=>array(22,0,989,800),980=>array(63,0,751,927),981=>array(60,-208,729,760),982=>array(33,-13,897,547),983=>array(38,-188,743,547),984=>array(68,-208,818,742),985=>array(62,-208,663,560),986=>array(70,-208,769,729),987=>array(63,-208,614,547),988=>array(21,0,670,729),989=>array(-146,-208,525,760),990=>array(21,2,682,729),991=>array(68,0,585,759),992=>array(102,-208,825,742),993=>array(-15,-180,500,559),994=>array(33,-213,1048,729),995=>array(81,-208,797,547),996=>array(37,-208,811,742),997=>array(34,-208,683,560),998=>array(21,-213,861,729),999=>array(-17,-14,736,575),1000=>array(-29,-208,721,745),1001=>array(-16,-208,626,560),1002=>array(-14,0,807,742),1003=>array(-7,0,674,560),1004=>array(26,-14,791,758),1005=>array(75,-14,739,758),1006=>array(23,-208,689,729),1007=>array(42,-208,614,726),1008=>array(19,-6,723,547),1009=>array(50,-216,690,560),1010=>array(37,-14,581,560),1011=>array(-128,-216,354,760),1012=>array(36,-14,814,742),1013=>array(67,-14,602,560),1014=>array(-26,-14,509,560),1015=>array(21,0,695,729),1016=>array(-10,-208,677,760),1017=>array(36,-14,724,742),1018=>array(21,0,974,729),1019=>array(0,-208,723,547),1020=>array(-31,-208,689,560),1021=>array(-13,-14,670,742),1022=>array(36,-14,724,742),1023=>array(-13,-14,670,742),1024=>array(21,0,670,927),1025=>array(21,0,670,927),1026=>array(67,-200,798,729),1027=>array(21,0,681,927),1028=>array(41,-14,733,742),1029=>array(15,-14,665,742),1030=>array(21,0,351,729),1031=>array(21,0,468,927),1032=>array(-166,-200,351,729),1033=>array(-25,0,1081,729),1034=>array(21,0,1039,729),1035=>array(48,0,778,729),1036=>array(21,0,857,927),1037=>array(21,0,816,927),1038=>array(77,0,812,927),1039=>array(36,-157,831,729),1040=>array(-65,0,691,729),1041=>array(21,0,714,729),1042=>array(21,0,699,729),1043=>array(21,0,681,729),1044=>array(-26,-157,813,729),1045=>array(21,0,670,729),1046=>array(-56,0,1249,729),1047=>array(-0,-14,668,742),1048=>array(21,0,816,729),1049=>array(21,0,816,927),1050=>array(21,0,857,729),1051=>array(-25,0,810,729),1052=>array(21,0,974,729),1053=>array(21,0,816,729),1054=>array(36,-14,814,742),1055=>array(21,0,816,729),1056=>array(21,0,719,729),1057=>array(36,-14,724,742),1058=>array(48,0,748,729),1059=>array(77,0,812,729),1060=>array(44,0,950,729),1061=>array(-51,0,812,729),1062=>array(36,-157,840,729),1063=>array(100,0,787,729),1064=>array(21,0,1214,729),1065=>array(36,-157,1238,729),1066=>array(92,0,869,729),1067=>array(21,0,1016,729),1068=>array(21,0,671,729),1069=>array(1,-14,693,742),1070=>array(21,-14,1129,742),1071=>array(-7,0,749,729),1072=>array(17,-14,611,560),1073=>array(24,-14,640,792),1074=>array(31,0,593,547),1075=>array(28,0,549,547),1076=>array(-10,-138,736,547),1077=>array(36,-14,640,560),1078=>array(-39,0,1015,547),1079=>array(-1,-14,535,560),1080=>array(31,0,670,547),1081=>array(31,0,670,765),1082=>array(31,0,698,547),1083=>array(2,0,702,547),1084=>array(28,0,784,547),1085=>array(28,0,658,547),1086=>array(36,-14,651,560),1087=>array(28,0,658,547),1088=>array(-10,-208,677,560),1089=>array(37,-14,581,560),1090=>array(34,0,626,547),1091=>array(0,-216,687,547),1092=>array(46,-208,945,760),1093=>array(-41,0,671,547),1094=>array(44,-138,682,547),1095=>array(80,0,626,547),1096=>array(31,0,1025,547),1097=>array(44,-138,1047,547),1098=>array(52,0,695,547),1099=>array(31,0,877,547),1100=>array(31,0,572,547),1101=>array(17,-14,557,560),1102=>array(31,-14,936,560),1103=>array(-22,0,613,547),1104=>array(36,-14,640,803),1105=>array(36,-14,640,774),1106=>array(52,-216,648,760),1107=>array(28,0,604,803),1108=>array(36,-14,576,560),1109=>array(10,-14,560,560),1110=>array(31,0,354,760),1111=>array(31,0,405,774),1112=>array(-128,-216,354,760),1113=>array(-9,0,926,547),1114=>array(31,0,896,547),1115=>array(31,0,622,760),1116=>array(31,0,698,803),1117=>array(31,0,670,803),1118=>array(0,-216,687,765),1119=>array(44,-138,673,547),1120=>array(33,-14,1048,729),1121=>array(33,-13,834,547),1122=>array(77,0,770,729),1123=>array(36,0,658,731),1124=>array(21,-14,1011,742),1125=>array(31,-14,810,560),1126=>array(-63,0,914,729),1127=>array(-28,0,754,547),1128=>array(21,0,1280,729),1129=>array(31,0,1044,547),1130=>array(-21,0,851,729),1131=>array(-13,0,683,547),1132=>array(21,0,1188,729),1133=>array(28,0,1003,547),1134=>array(-25,-208,640,938),1135=>array(-24,-193,525,756),1136=>array(74,0,1126,729),1137=>array(62,-208,1100,759),1138=>array(36,-14,814,742),1139=>array(36,-14,651,560),1140=>array(75,0,896,742),1141=>array(60,0,732,560),1142=>array(75,0,896,930),1143=>array(60,0,732,800),1144=>array(57,-216,1186,742),1145=>array(63,-216,1098,565),1146=>array(40,-14,1033,742),1147=>array(35,-14,823,560),1148=>array(37,-14,1348,928),1149=>array(31,-13,1129,828),1150=>array(33,-14,1048,910),1151=>array(33,-13,834,746),1152=>array(40,-208,732,742),1153=>array(33,-208,573,560),1154=>array(19,-33,530,488),1155=>array(-608,606,-79,822),1156=>array(-427,638,-12,784),1157=>array(-356,595,-213,785),1158=>array(-384,595,-213,785),1159=>array(-811,592,1,788),1160=>array(-1067,-179,388,928),1161=>array(-973,-280,323,1022),1162=>array(21,-208,890,927),1163=>array(28,-208,748,765),1164=>array(21,0,671,729),1165=>array(27,0,549,702),1166=>array(21,0,717,729),1167=>array(-10,-208,670,560),1168=>array(21,0,710,878),1169=>array(28,0,579,700),1170=>array(17,0,709,729),1171=>array(10,0,572,547),1172=>array(21,-200,708,729),1173=>array(28,-216,554,547),1174=>array(-41,-157,1264,729),1175=>array(-25,-138,1028,547),1176=>array(-0,-196,668,742),1177=>array(-1,-196,535,560),1178=>array(36,-157,873,729),1179=>array(44,-138,711,547),1180=>array(21,0,857,729),1181=>array(31,0,698,547),1182=>array(21,0,857,729),1183=>array(10,0,677,760),1184=>array(68,0,1055,729),1185=>array(52,0,846,547),1186=>array(36,-157,904,729),1187=>array(44,-138,765,547),1188=>array(21,0,1146,729),1189=>array(28,0,897,547),1190=>array(21,-200,1174,729),1191=>array(28,-216,902,547),1192=>array(40,-14,875,743),1193=>array(40,-14,798,560),1194=>array(36,-196,724,742),1195=>array(37,-196,581,560),1196=>array(63,-157,763,729),1197=>array(49,-138,642,547),1198=>array(63,0,809,729),1199=>array(66,-216,688,547),1200=>array(61,0,805,729),1201=>array(63,-216,708,547),1202=>array(-37,-157,827,729),1203=>array(-25,-138,687,547),1204=>array(63,-157,1060,729),1205=>array(49,-138,957,547),1206=>array(129,-157,876,729),1207=>array(103,-138,730,547),1208=>array(114,0,787,729),1209=>array(87,0,624,547),1210=>array(106,0,793,729),1211=>array(31,0,654,760),1212=>array(42,-14,984,742),1213=>array(30,-14,769,560),1214=>array(42,-184,984,742),1215=>array(30,-161,769,560),1216=>array(21,0,351,729),1217=>array(-56,0,1249,927),1218=>array(-39,0,1015,784),1219=>array(21,-200,840,729),1220=>array(31,-216,679,547),1221=>array(-46,-208,885,729),1222=>array(-38,-208,746,547),1223=>array(21,-200,816,729),1224=>array(28,-216,658,547),1225=>array(21,-208,889,729),1226=>array(28,-208,748,547),1227=>array(129,-157,803,729),1228=>array(103,-138,640,547),1229=>array(21,-208,1047,729),1230=>array(28,-208,874,547),1231=>array(31,0,354,760),1232=>array(-65,0,691,936),1233=>array(17,-14,611,772),1234=>array(-65,0,691,927),1235=>array(17,-14,611,774),1236=>array(-78,0,1072,729),1237=>array(17,-14,1008,560),1238=>array(21,0,670,927),1239=>array(36,-14,640,784),1240=>array(36,-14,819,742),1241=>array(42,-14,630,560),1242=>array(36,-14,819,927),1243=>array(42,-14,630,774),1244=>array(-56,0,1249,927),1245=>array(-39,0,1015,774),1246=>array(-0,-14,668,927),1247=>array(-1,-14,540,774),1248=>array(21,-33,743,729),1249=>array(-23,-215,608,547),1250=>array(21,0,816,914),1251=>array(31,0,670,763),1252=>array(21,0,816,927),1253=>array(31,0,670,774),1254=>array(36,-14,814,927),1255=>array(36,-14,651,774),1256=>array(36,-14,814,742),1257=>array(36,-14,651,560),1258=>array(36,-14,814,927),1259=>array(36,-14,651,774),1260=>array(1,-14,693,927),1261=>array(17,-14,557,774),1262=>array(77,0,812,914),1263=>array(0,-216,687,763),1264=>array(77,0,812,927),1265=>array(0,-216,687,774),1266=>array(77,0,812,927),1267=>array(0,-216,687,800),1268=>array(100,0,787,927),1269=>array(80,0,626,774),1270=>array(36,-157,696,729),1271=>array(44,-138,565,547),1272=>array(21,0,1016,927),1273=>array(31,0,877,774),1274=>array(38,-216,730,729),1275=>array(31,-217,593,547),1276=>array(-32,-200,832,729),1277=>array(-17,-216,694,547),1278=>array(-52,0,812,729),1279=>array(-38,0,673,547),1280=>array(37,0,741,729),1281=>array(17,0,575,547),1282=>array(35,-14,1116,729),1283=>array(16,-14,868,547),1284=>array(138,-14,1063,742),1285=>array(104,-14,854,560),1286=>array(138,-208,760,742),1287=>array(104,-208,634,560),1288=>array(-48,-14,1185,729),1289=>array(-38,-14,950,547),1290=>array(22,-14,1222,729),1291=>array(28,-14,957,547),1292=>array(41,-14,783,742),1293=>array(35,-14,573,546),1294=>array(47,-14,881,729),1295=>array(34,-14,727,547),1296=>array(37,-14,652,742),1297=>array(27,-14,520,560),1298=>array(-5,-200,829,729),1299=>array(23,-216,723,547),1300=>array(-25,0,1327,729),1301=>array(2,0,1096,547),1302=>array(21,0,1106,729),1303=>array(-10,-208,1008,560),1304=>array(-7,0,1068,729),1305=>array(-22,-14,965,560),1306=>array(36,-146,814,742),1307=>array(36,-208,682,560),1308=>array(107,0,1143,729),1309=>array(87,0,927,547),1310=>array(21,0,857,729),1311=>array(31,0,698,547),1312=>array(-25,-200,1167,729),1313=>array(2,-216,946,547),1314=>array(21,-200,1173,729),1315=>array(28,-216,902,547),1316=>array(36,-157,905,729),1317=>array(44,-138,764,547),1329=>array(75,-38,849,729),1330=>array(21,0,741,743),1331=>array(50,0,805,743),1332=>array(37,0,809,743),1333=>array(78,-14,763,729),1334=>array(18,0,753,743),1335=>array(21,0,730,729),1336=>array(21,0,741,743),1337=>array(21,-13,1020,742),1338=>array(11,-14,844,729),1339=>array(21,0,705,729),1340=>array(21,0,566,729),1341=>array(21,-14,1021,729),1342=>array(93,-12,864,741),1343=>array(97,0,746,729),1344=>array(-16,-46,694,729),1345=>array(33,-48,753,743),1346=>array(32,0,748,743),1347=>array(-22,0,733,735),1348=>array(78,-14,938,729),1349=>array(42,-14,709,743),1350=>array(46,-14,763,729),1351=>array(49,-14,762,729),1352=>array(21,0,734,743),1353=>array(51,-48,724,743),1354=>array(32,0,890,743),1355=>array(7,0,742,743),1356=>array(21,0,863,743),1357=>array(68,-14,791,729),1358=>array(35,0,748,729),1359=>array(37,-14,703,743),1360=>array(21,0,741,743),1361=>array(42,-14,709,743),1362=>array(21,0,666,729),1363=>array(24,0,901,729),1364=>array(-49,0,741,743),1365=>array(36,-14,813,742),1366=>array(30,-14,909,729),1369=>array(159,481,325,760),1370=>array(73,418,349,729),1371=>array(120,616,500,800),1372=>array(115,595,590,893),1373=>array(-1,616,315,849),1374=>array(117,586,652,878),1375=>array(164,618,622,893),1377=>array(74,-13,1018,547),1378=>array(-10,-208,654,560),1379=>array(43,-208,748,559),1380=>array(31,-208,752,560),1381=>array(59,-14,683,760),1382=>array(38,-208,708,559),1383=>array(31,0,644,760),1384=>array(-10,-208,653,560),1385=>array(-10,-208,843,560),1386=>array(43,-14,830,760),1387=>array(-10,-208,646,760),1388=>array(-10,-208,385,547),1389=>array(-10,-208,1063,760),1390=>array(40,-14,719,760),1391=>array(67,-208,683,760),1392=>array(31,0,646,760),1393=>array(10,-13,593,760),1394=>array(31,-208,711,560),1395=>array(52,-13,729,768),1396=>array(67,-13,871,760),1397=>array(-128,-216,313,547),1398=>array(2,-13,683,760),1399=>array(-60,-208,520,560),1400=>array(31,0,646,560),1401=>array(-67,-208,366,547),1402=>array(59,-208,1012,547),1403=>array(-26,-208,605,560),1404=>array(31,0,665,560),1405=>array(67,-13,683,547),1406=>array(67,-208,724,760),1407=>array(63,-13,975,560),1408=>array(-10,-208,646,560),1409=>array(19,-216,681,559),1410=>array(31,0,498,547),1411=>array(63,-208,975,760),1412=>array(-151,-208,671,560),1413=>array(37,-14,652,560),1414=>array(31,-190,865,760),1415=>array(67,-14,868,760),1417=>array(41,0,323,547),1418=>array(96,179,430,359),1456=>array(275,-229,416,-10),1457=>array(149,-229,523,-10),1458=>array(140,-229,513,-10),1459=>array(127,-229,513,-10),1460=>array(287,-171,404,-73),1461=>array(213,-171,477,-73),1462=>array(237,-229,477,-10),1463=>array(89,-171,451,0),1464=>array(109,-217,446,0),1465=>array(-34,625,83,723),1466=>array(-34,625,83,723),1467=>array(190,-239,525,-5),1468=>array(293,225,411,322),1469=>array(277,-217,413,-22),1470=>array(40,413,375,555),1471=>array(132,547,469,710),1472=>array(26,-98,345,645),1473=>array(816,613,934,710),1474=>array(204,613,321,710),1475=>array(45,0,326,547),1478=>array(25,0,490,547),1479=>array(188,-229,525,-10),1488=>array(104,0,730,547),1489=>array(43,0,590,547),1490=>array(44,-9,428,547),1491=>array(126,0,651,547),1492=>array(100,0,661,547),1493=>array(91,0,359,547),1494=>array(94,0,464,547),1495=>array(91,0,654,547),1496=>array(142,-13,676,553),1497=>array(98,164,334,547),1498=>array(126,-240,549,547),1499=>array(43,0,570,547),1500=>array(126,0,633,711),1501=>array(91,0,663,547),1502=>array(84,0,690,554),1503=>array(44,-240,359,547),1504=>array(43,0,430,547),1505=>array(144,-13,678,547),1506=>array(35,-101,682,547),1507=>array(158,-240,642,547),1508=>array(91,0,656,547),1509=>array(118,-240,649,548),1510=>array(54,0,670,547),1511=>array(51,-240,767,546),1512=>array(126,0,575,547),1513=>array(89,0,856,547),1514=>array(11,-4,650,547),1520=>array(91,0,680,547),1521=>array(98,0,680,547),1522=>array(98,164,655,547),1523=>array(66,361,378,547),1524=>array(66,361,644,547),3647=>array(2,-147,642,760),3713=>array(14,-14,752,560),3714=>array(12,-14,727,560),3716=>array(13,-14,699,558),3719=>array(2,-241,548,593),3720=>array(44,0,711,561),3722=>array(45,-269,747,584),3725=>array(14,-24,767,610),3732=>array(18,-14,671,593),3733=>array(17,-19,670,603),3734=>array(35,-240,729,593),3735=>array(-1,-14,784,560),3737=>array(-9,-33,735,593),3738=>array(13,-15,716,613),3739=>array(-1,-15,739,760),3740=>array(29,-12,952,665),3741=>array(24,-14,837,760),3742=>array(50,-14,825,604),3743=>array(35,-14,848,760),3745=>array(-7,-14,826,547),3746=>array(-0,-23,789,760),3747=>array(18,-10,768,615),3749=>array(9,-33,717,593),3751=>array(5,-33,668,593),3754=>array(8,-21,860,724),3755=>array(32,-21,961,620),3757=>array(27,-20,689,606),3758=>array(15,-14,880,698),3759=>array(79,-259,932,648),3760=>array(5,27,682,606),3761=>array(-649,610,-29,896),3762=>array(51,0,578,593),3763=>array(-479,0,578,875),3764=>array(-656,622,-63,950),3765=>array(-656,633,-1,962),3766=>array(-656,622,-63,950),3767=>array(-656,633,-1,962),3768=>array(-413,-385,-165,-55),3769=>array(-479,-316,-150,-28),3771=>array(-657,610,-33,896),3772=>array(-689,-311,17,-48),3773=>array(-25,-220,758,776),3776=>array(53,-13,469,561),3777=>array(53,-13,843,561),3778=>array(25,-14,486,936),3779=>array(67,-14,640,879),3780=>array(47,-35,552,809),3782=>array(33,-240,731,582),3784=>array(-431,659,-279,844),3785=>array(-636,622,-19,918),3786=>array(-672,621,37,965),3787=>array(-530,612,-178,917),3788=>array(-511,603,194,866),3789=>array(-479,668,-229,875),3792=>array(66,-29,723,563),3793=>array(55,-139,731,586),3794=>array(1,-80,612,711),3795=>array(-49,-14,953,981),3796=>array(31,-156,647,711),3797=>array(31,-156,647,711),3798=>array(5,-14,962,950),3799=>array(36,-240,748,560),3800=>array(86,-269,766,582),3801=>array(38,-14,875,564),3804=>array(32,-21,1356,620),3805=>array(32,-21,1361,620),4256=>array(111,-14,929,819),4257=>array(139,-0,736,819),4258=>array(150,-138,672,828),4259=>array(97,-15,902,819),4260=>array(133,0,665,828),4261=>array(136,0,832,828),4262=>array(144,-14,752,819),4263=>array(117,-14,993,828),4264=>array(127,0,562,862),4265=>array(108,0,653,819),4266=>array(95,-14,834,820),4267=>array(89,-14,942,819),4268=>array(24,0,689,819),4269=>array(106,-157,886,829),4270=>array(141,-14,886,822),4271=>array(141,0,741,823),4272=>array(76,-15,969,820),4273=>array(83,-15,626,820),4274=>array(23,-0,685,828),4275=>array(106,-170,886,828),4276=>array(127,0,918,825),4277=>array(101,0,794,820),4278=>array(24,0,685,828),4279=>array(127,0,731,820),4280=>array(66,-14,736,820),4281=>array(24,0,632,819),4282=>array(113,-14,880,827),4283=>array(89,-15,926,820),4284=>array(23,-0,698,819),4285=>array(75,-15,648,828),4286=>array(23,-0,741,819),4287=>array(27,0,880,819),4288=>array(110,-14,901,820),4289=>array(24,0,647,820),4290=>array(78,-15,692,828),4291=>array(95,0,707,820),4292=>array(131,0,715,820),4293=>array(43,-14,833,828),4304=>array(76,-14,531,599),4305=>array(86,-14,552,823),4306=>array(31,-232,565,561),4307=>array(41,-225,826,557),4308=>array(26,-232,551,557),4309=>array(25,-232,562,557),4310=>array(75,-14,537,828),4311=>array(84,-14,821,557),4312=>array(75,0,556,557),4313=>array(24,-232,554,542),4314=>array(96,-225,1077,562),4315=>array(87,-14,622,828),4316=>array(89,-14,629,819),4317=>array(92,-0,808,557),4318=>array(78,-14,589,818),4319=>array(25,-232,604,560),4320=>array(91,0,816,830),4321=>array(92,-14,560,818),4322=>array(62,-232,664,670),4323=>array(47,-232,591,604),4324=>array(94,-232,844,558),4325=>array(25,-232,650,818),4326=>array(88,-225,815,557),4327=>array(25,-232,602,549),4328=>array(63,-14,609,828),4329=>array(39,0,561,828),4330=>array(65,-232,612,548),4331=>array(86,-14,659,818),4332=>array(91,-15,685,828),4333=>array(35,-232,616,818),4334=>array(95,-14,553,818),4335=>array(-7,-232,542,580),4336=>array(73,-15,602,823),4337=>array(79,-14,609,823),4338=>array(17,-146,543,557),4339=>array(25,-232,604,558),4340=>array(26,-232,618,828),4341=>array(65,-14,656,828),4342=>array(87,-232,842,557),4343=>array(29,-232,551,557),4344=>array(25,-232,548,549),4345=>array(93,-232,627,561),4346=>array(68,-111,558,557),4347=>array(29,0,446,500),4348=>array(124,400,424,828),5121=>array(76,0,840,729),5122=>array(-66,0,698,1050),5123=>array(-66,0,698,729),5124=>array(-66,0,698,928),5125=>array(21,0,843,729),5126=>array(21,0,843,928),5127=>array(21,0,843,927),5129=>array(21,0,843,729),5130=>array(62,0,884,729),5131=>array(62,0,884,928),5132=>array(80,0,1084,729),5133=>array(76,0,937,729),5134=>array(80,0,942,729),5135=>array(-66,0,937,729),5136=>array(80,0,942,928),5137=>array(-66,0,937,928),5138=>array(80,0,1087,729),5139=>array(21,0,1067,729),5140=>array(80,0,1087,928),5141=>array(21,0,1067,928),5142=>array(21,0,843,928),5143=>array(80,0,1128,729),5144=>array(62,0,1070,729),5145=>array(80,0,1128,928),5146=>array(62,0,1070,928),5147=>array(62,0,884,928),5149=>array(80,607,237,728),5150=>array(20,326,434,734),5151=>array(8,338,402,722),5152=>array(54,338,356,722),5153=>array(53,392,370,711),5154=>array(29,352,345,670),5155=>array(33,392,341,670),5156=>array(57,392,341,670),5157=>array(-2,327,552,749),5158=>array(21,326,454,734),5159=>array(80,304,237,424),5160=>array(53,494,346,569),5161=>array(53,392,346,670),5162=>array(75,392,368,693),5163=>array(76,0,1145,729),5164=>array(-66,0,917,729),5165=>array(21,0,1147,729),5166=>array(62,0,1229,729),5167=>array(76,0,840,729),5168=>array(-66,0,698,1050),5169=>array(-66,0,698,729),5170=>array(-66,0,698,928),5171=>array(2,0,824,729),5172=>array(2,0,824,928),5173=>array(2,0,824,927),5175=>array(2,0,824,729),5176=>array(51,0,873,729),5177=>array(51,0,873,928),5178=>array(80,0,1084,729),5179=>array(76,0,937,729),5180=>array(80,0,942,729),5181=>array(-66,0,937,729),5182=>array(80,0,942,928),5183=>array(-66,0,937,928),5184=>array(80,0,1068,729),5185=>array(2,0,1067,729),5186=>array(80,0,1068,928),5187=>array(2,0,1067,928),5188=>array(80,0,1117,729),5189=>array(51,0,1070,729),5190=>array(80,0,1117,928),5191=>array(51,0,1070,928),5192=>array(51,0,873,927),5193=>array(48,326,559,727),5194=>array(20,326,212,734),5196=>array(79,-14,792,729),5197=>array(20,0,733,1050),5198=>array(20,0,733,743),5199=>array(20,0,733,928),5200=>array(2,0,763,729),5201=>array(2,0,763,928),5202=>array(2,0,763,927),5204=>array(2,0,763,729),5205=>array(52,0,813,729),5206=>array(52,0,813,928),5207=>array(80,-14,1037,729),5208=>array(79,-14,976,729),5209=>array(80,0,977,743),5210=>array(20,0,976,743),5211=>array(80,0,977,928),5212=>array(20,0,976,928),5213=>array(80,0,1007,729),5214=>array(2,0,982,729),5215=>array(80,0,1007,928),5216=>array(2,0,982,928),5217=>array(80,0,1057,729),5218=>array(52,0,979,729),5219=>array(80,0,1057,928),5220=>array(52,0,979,928),5221=>array(52,0,1057,729),5222=>array(59,326,466,733),5223=>array(79,-14,989,734),5224=>array(20,0,989,743),5225=>array(2,0,1007,734),5226=>array(52,0,1000,734),5227=>array(64,0,675,743),5228=>array(20,0,726,1050),5229=>array(20,0,726,743),5230=>array(20,0,726,928),5231=>array(18,-14,724,729),5232=>array(18,-14,731,928),5233=>array(18,-14,818,927),5234=>array(68,-14,679,729),5235=>array(68,-14,679,928),5236=>array(80,0,960,743),5237=>array(64,0,902,743),5238=>array(80,0,962,743),5239=>array(20,0,902,743),5240=>array(80,0,962,928),5241=>array(20,0,902,928),5242=>array(80,-14,1009,729),5243=>array(18,-14,902,729),5244=>array(80,-14,1017,928),5245=>array(18,-14,902,928),5246=>array(80,-14,916,729),5247=>array(68,-14,902,729),5248=>array(80,-14,916,928),5249=>array(68,-14,902,928),5250=>array(52,-14,916,729),5251=>array(47,319,432,734),5252=>array(43,319,485,734),5253=>array(64,0,921,743),5254=>array(20,0,921,743),5255=>array(18,-14,921,734),5256=>array(68,-14,921,734),5257=>array(64,0,675,743),5258=>array(20,0,726,1050),5259=>array(20,0,726,743),5260=>array(20,0,726,928),5261=>array(18,-14,724,729),5262=>array(18,-14,737,928),5263=>array(18,-14,824,927),5264=>array(68,-14,679,729),5265=>array(68,-14,679,928),5266=>array(80,0,960,743),5267=>array(64,0,902,743),5268=>array(80,0,1011,743),5269=>array(20,0,902,743),5270=>array(80,0,1011,928),5271=>array(20,0,902,928),5272=>array(80,-14,1009,729),5273=>array(18,-14,902,729),5274=>array(80,-14,1023,928),5275=>array(18,-14,902,928),5276=>array(80,-14,964,729),5277=>array(68,-14,902,729),5278=>array(80,-14,964,928),5279=>array(68,-14,902,928),5280=>array(52,-14,964,729),5281=>array(47,319,432,734),5282=>array(46,319,485,734),5283=>array(71,0,605,729),5284=>array(21,0,670,1050),5285=>array(21,0,670,729),5286=>array(21,0,670,928),5287=>array(-43,0,605,729),5288=>array(-43,0,621,928),5289=>array(-43,0,708,927),5290=>array(21,0,556,729),5291=>array(21,0,556,928),5292=>array(80,0,860,729),5293=>array(71,0,782,729),5294=>array(80,0,907,729),5295=>array(21,0,801,729),5296=>array(80,0,907,928),5297=>array(21,0,801,928),5298=>array(80,0,860,729),5299=>array(-43,0,801,729),5300=>array(80,0,875,928),5301=>array(-43,0,801,928),5302=>array(80,0,792,729),5303=>array(21,0,801,729),5304=>array(80,0,792,928),5305=>array(21,0,801,928),5306=>array(52,0,792,729),5307=>array(21,326,355,734),5308=>array(55,326,532,733),5309=>array(20,326,420,734),5312=>array(103,-14,946,468),5313=>array(41,-14,951,781),5314=>array(41,-14,951,468),5315=>array(41,-14,951,667),5316=>array(-20,0,891,482),5317=>array(-20,0,891,667),5318=>array(-20,0,891,667),5319=>array(42,0,885,482),5320=>array(42,0,885,667),5321=>array(80,-14,1196,468),5322=>array(103,-14,1175,468),5323=>array(80,0,1153,482),5324=>array(42,0,1156,482),5325=>array(80,0,1153,667),5326=>array(42,0,1156,667),5327=>array(42,0,885,667),5328=>array(61,477,593,742),5329=>array(43,319,481,734),5330=>array(34,477,607,742),5331=>array(102,0,945,468),5332=>array(39,0,949,781),5333=>array(39,0,949,468),5334=>array(39,0,949,667),5335=>array(-18,0,892,468),5336=>array(-18,0,892,667),5337=>array(-18,0,892,667),5338=>array(43,0,886,468),5339=>array(43,0,886,667),5340=>array(80,0,1188,468),5341=>array(102,0,1175,468),5342=>array(80,0,1245,468),5343=>array(39,0,1156,468),5344=>array(80,0,1245,667),5345=>array(39,0,1156,667),5346=>array(80,0,1189,468),5347=>array(-18,0,1142,468),5348=>array(80,0,1189,667),5349=>array(-18,0,1142,667),5350=>array(80,0,1181,468),5351=>array(43,0,1156,468),5352=>array(80,0,1181,667),5353=>array(43,0,1156,667),5354=>array(61,477,593,734),5356=>array(26,0,874,729),5357=>array(92,0,643,729),5358=>array(21,0,841,1050),5359=>array(21,0,760,729),5360=>array(21,0,773,928),5361=>array(-30,0,709,729),5362=>array(-30,0,717,928),5363=>array(-30,0,804,927),5364=>array(87,0,638,729),5365=>array(87,0,638,928),5366=>array(80,0,911,729),5367=>array(92,0,886,729),5368=>array(80,0,997,729),5369=>array(21,0,917,729),5370=>array(80,0,1010,928),5371=>array(21,0,917,928),5372=>array(80,0,977,729),5373=>array(-30,0,886,729),5374=>array(80,0,985,928),5375=>array(-30,0,886,928),5376=>array(80,0,875,729),5377=>array(87,0,917,729),5378=>array(80,0,875,928),5379=>array(87,0,917,928),5380=>array(52,0,875,729),5381=>array(57,326,406,734),5382=>array(28,319,413,742),5383=>array(20,326,477,734),5392=>array(65,-14,858,743),5393=>array(7,-14,917,743),5394=>array(7,-14,917,928),5395=>array(33,-14,1103,482),5396=>array(33,-14,1103,667),5397=>array(36,-14,1100,482),5398=>array(36,-14,1100,667),5399=>array(80,-14,1144,743),5400=>array(65,-14,1129,743),5401=>array(80,-14,1202,743),5402=>array(7,-14,1129,743),5403=>array(80,-14,1202,928),5404=>array(7,-14,1129,928),5405=>array(80,-14,1398,482),5406=>array(33,-14,1348,482),5407=>array(80,-14,1398,667),5408=>array(33,-14,1348,667),5409=>array(80,-14,1395,482),5410=>array(36,-14,1348,482),5411=>array(80,-14,1395,667),5412=>array(36,-14,1348,667),5413=>array(58,469,693,747),5414=>array(63,0,689,729),5415=>array(21,0,697,1050),5416=>array(21,0,697,729),5417=>array(21,0,697,928),5418=>array(79,0,755,729),5419=>array(79,0,772,928),5420=>array(79,0,859,927),5421=>array(87,0,713,729),5422=>array(87,0,713,928),5423=>array(80,0,916,729),5424=>array(63,0,931,729),5425=>array(80,0,934,729),5426=>array(21,0,923,729),5427=>array(80,0,934,928),5428=>array(21,0,923,928),5429=>array(80,0,982,729),5430=>array(79,0,931,729),5431=>array(80,0,1000,928),5432=>array(79,0,931,928),5433=>array(80,0,950,729),5434=>array(87,0,923,729),5435=>array(80,0,950,928),5436=>array(87,0,923,928),5437=>array(52,0,950,928),5438=>array(57,326,450,734),5440=>array(53,392,346,670),5441=>array(20,326,487,734),5442=>array(91,-14,996,468),5443=>array(103,-14,988,468),5444=>array(-20,0,885,482),5445=>array(45,0,930,781),5446=>array(45,0,930,482),5447=>array(45,0,930,667),5448=>array(21,0,716,729),5449=>array(21,0,716,928),5450=>array(21,0,667,729),5451=>array(65,0,712,729),5452=>array(65,0,712,928),5453=>array(17,0,712,729),5454=>array(80,0,982,928),5455=>array(65,0,887,928),5456=>array(74,326,478,727),5458=>array(2,0,849,729),5459=>array(99,0,838,743),5460=>array(2,-14,700,1050),5461=>array(2,-14,700,729),5462=>array(2,-14,700,928),5463=>array(51,0,873,663),5464=>array(51,0,873,928),5465=>array(69,0,896,663),5466=>array(69,0,896,928),5467=>array(80,0,1140,928),5468=>array(69,0,1070,928),5469=>array(52,311,568,675),5470=>array(68,-14,791,743),5471=>array(68,-14,772,743),5472=>array(40,-14,744,743),5473=>array(21,-14,744,743),5474=>array(40,-14,744,928),5475=>array(21,-14,744,928),5476=>array(2,0,769,729),5477=>array(2,0,769,928),5478=>array(47,0,811,729),5479=>array(47,0,811,928),5480=>array(80,0,1055,928),5481=>array(47,0,979,928),5482=>array(55,326,540,733),5492=>array(58,0,871,743),5493=>array(62,0,966,743),5494=>array(62,0,966,928),5495=>array(11,-14,915,729),5496=>array(11,-14,915,928),5497=>array(106,-14,919,729),5498=>array(106,-14,919,928),5499=>array(69,319,551,734),5500=>array(21,0,816,729),5501=>array(20,326,487,734),5502=>array(74,0,1220,1050),5503=>array(74,0,1220,743),5504=>array(74,0,1220,928),5505=>array(74,-14,1218,729),5506=>array(74,-14,1226,928),5507=>array(74,-14,1173,729),5508=>array(74,-14,1173,928),5509=>array(74,319,926,734),5514=>array(64,0,871,743),5515=>array(62,0,966,743),5516=>array(11,-14,916,729),5517=>array(106,-14,913,729),5518=>array(77,0,1573,1050),5519=>array(77,0,1573,743),5520=>array(77,0,1573,928),5521=>array(77,-14,1275,741),5522=>array(77,-14,1289,928),5523=>array(77,-14,1526,741),5524=>array(77,-14,1526,928),5525=>array(77,335,795,741),5526=>array(77,335,1220,741),5536=>array(16,0,939,709),5537=>array(16,0,939,709),5538=>array(-8,-242,916,468),5539=>array(-8,-242,916,667),5540=>array(66,-242,910,468),5541=>array(66,-242,910,667),5542=>array(74,344,606,734),5543=>array(62,0,739,729),5544=>array(-49,0,697,729),5545=>array(-49,0,697,928),5546=>array(79,0,825,729),5547=>array(79,0,825,928),5548=>array(37,0,714,729),5549=>array(37,0,714,928),5550=>array(36,326,450,734),5551=>array(22,-14,686,729),5598=>array(21,0,782,729),5601=>array(48,0,809,729),5702=>array(20,326,473,734),5703=>array(20,240,473,820),5742=>array(-20,0,427,306),5743=>array(74,0,1169,743),5744=>array(77,0,1522,743),5745=>array(77,0,1999,743),5746=>array(77,0,1999,928),5747=>array(77,-14,1701,741),5748=>array(77,-14,1672,928),5749=>array(77,-14,1952,741),5750=>array(77,-14,1952,928),7424=>array(-38,0,584,547),7425=>array(-53,0,800,547),7426=>array(42,-14,1021,560),7427=>array(-9,0,565,547),7428=>array(37,-14,581,560),7429=>array(31,-1,614,547),7430=>array(11,-1,611,547),7431=>array(39,0,526,547),7432=>array(27,-14,516,560),7433=>array(10,-213,333,547),7434=>array(-4,-14,471,547),7435=>array(31,0,716,547),7436=>array(-26,0,473,547),7437=>array(28,0,784,547),7438=>array(31,0,670,547),7439=>array(36,-14,651,560),7440=>array(-7,-14,537,560),7441=>array(42,-27,617,573),7442=>array(20,31,603,515),7443=>array(44,-28,619,579),7444=>array(42,-14,1046,560),7446=>array(15,273,616,560),7447=>array(72,-14,673,273),7448=>array(-2,0,533,547),7449=>array(-32,0,613,547),7450=>array(71,0,613,547),7451=>array(34,0,626,547),7452=>array(75,-14,662,547),7453=>array(32,10,685,560),7454=>array(39,11,896,561),7455=>array(-59,-238,715,560),7456=>array(63,0,678,547),7457=>array(87,0,927,547),7458=>array(-9,0,586,547),7459=>array(19,-14,588,547),7462=>array(31,0,552,547),7463=>array(-38,0,584,547),7464=>array(31,0,660,547),7465=>array(-2,0,533,547),7466=>array(98,0,751,547),7467=>array(2,0,702,547),7468=>array(-37,326,445,734),7469=>array(-40,326,670,734),7470=>array(18,326,436,734),7472=>array(18,326,490,734),7473=>array(18,326,417,734),7474=>array(18,326,424,734),7475=>array(31,318,489,742),7476=>array(18,326,509,734),7477=>array(18,326,216,734),7478=>array(-86,214,227,734),7479=>array(18,326,524,734),7480=>array(18,326,360,734),7481=>array(18,326,608,734),7482=>array(18,326,509,734),7483=>array(18,326,509,734),7484=>array(31,318,504,742),7485=>array(21,318,480,742),7486=>array(18,326,450,734),7487=>array(18,326,433,734),7488=>array(27,326,466,734),7489=>array(50,318,494,734),7490=>array(58,326,715,734),7491=>array(37,318,411,640),7492=>array(48,318,415,640),7493=>array(53,318,457,640),7494=>array(53,318,669,640),7495=>array(20,318,427,751),7496=>array(48,318,481,751),7497=>array(49,318,429,640),7498=>array(53,318,423,640),7499=>array(39,318,347,640),7500=>array(37,318,345,640),7501=>array(38,205,455,639),7502=>array(7,207,210,632),7503=>array(20,326,451,751),7504=>array(21,326,621,640),7505=>array(32,205,424,640),7506=>array(49,318,436,640),7507=>array(22,318,357,640),7508=>array(108,479,487,640),7509=>array(108,318,487,479),7510=>array(-6,209,427,640),7511=>array(72,326,365,719),7512=>array(42,318,433,632),7513=>array(55,332,466,640),7514=>array(47,318,642,632),7515=>array(83,326,471,632),7517=>array(-0,209,414,759),7518=>array(39,209,461,632),7519=>array(16,318,395,756),7520=>array(52,209,468,635),7521=>array(-25,209,432,632),7522=>array(12,0,205,425),7523=>array(23,0,344,313),7524=>array(42,-8,433,306),7525=>array(83,0,471,306),7526=>array(-0,-117,414,433),7527=>array(39,-117,461,306),7528=>array(-0,-117,427,314),7529=>array(52,-117,468,309),7530=>array(-25,-117,432,306),7543=>array(11,-216,673,559),7544=>array(18,326,509,734),7547=>array(31,0,515,547),7549=>array(-10,-208,753,560),7557=>array(84,-216,458,760),7579=>array(23,318,423,640),7580=>array(53,318,385,640),7581=>array(56,288,388,640),7582=>array(42,318,432,751),7583=>array(25,318,337,640),7584=>array(58,326,362,751),7585=>array(12,205,288,632),7586=>array(57,205,464,632),7587=>array(58,207,441,632),7588=>array(35,326,283,751),7589=>array(48,326,208,632),7590=>array(23,326,321,632),7591=>array(23,326,321,632),7592=>array(17,205,376,751),7593=>array(23,205,229,751),7594=>array(23,205,258,751),7595=>array(23,326,300,632),7596=>array(35,205,625,640),7597=>array(58,209,648,632),7598=>array(11,205,523,640),7599=>array(35,205,476,640),7600=>array(23,326,422,632),7601=>array(53,318,432,640),7602=>array(53,209,485,751),7603=>array(41,205,382,640),7604=>array(0,205,393,751),7605=>array(73,205,365,719),7606=>array(47,318,532,632),7607=>array(54,298,471,632),7608=>array(47,318,413,632),7609=>array(48,326,395,632),7610=>array(23,326,416,632),7611=>array(23,326,391,632),7612=>array(35,205,439,632),7613=>array(27,288,403,632),7614=>array(16,206,404,632),7615=>array(53,320,370,756),7620=>array(-483,616,-19,800),7621=>array(-451,616,-35,800),7622=>array(-467,616,-51,800),7623=>array(-483,616,-19,800),7624=>array(-495,616,-7,800),7625=>array(-531,616,29,800),7680=>array(-65,-240,691,729),7681=>array(17,-240,611,560),7682=>array(21,0,699,927),7683=>array(31,-14,677,941),7684=>array(21,-212,699,729),7685=>array(31,-212,677,760),7686=>array(21,-185,699,729),7687=>array(31,-185,677,760),7688=>array(36,-196,724,927),7689=>array(37,-196,581,800),7690=>array(21,0,786,927),7691=>array(36,-14,757,941),7692=>array(21,-212,786,729),7693=>array(36,-212,724,760),7694=>array(21,-185,786,729),7695=>array(36,-185,724,760),7696=>array(21,-194,786,729),7697=>array(34,-196,724,760),7698=>array(21,-240,786,729),7699=>array(36,-240,724,760),7700=>array(21,0,670,1057),7701=>array(36,-14,640,898),7702=>array(21,0,670,1057),7703=>array(36,-14,640,900),7704=>array(44,-203,693,729),7705=>array(36,-203,640,560),7706=>array(21,-221,670,729),7707=>array(36,-221,640,560),7708=>array(21,-196,670,927),7709=>array(36,-196,640,783),7710=>array(21,0,670,928),7711=>array(50,0,540,941),7712=>array(36,-14,778,899),7713=>array(20,-216,682,760),7714=>array(21,0,816,928),7715=>array(31,0,654,941),7716=>array(21,-212,816,729),7717=>array(31,-212,654,760),7718=>array(21,0,816,927),7719=>array(31,0,654,927),7720=>array(-61,-196,816,729),7721=>array(-43,-196,654,760),7722=>array(21,-239,816,729),7723=>array(31,-239,654,760),7724=>array(-108,-221,351,729),7725=>array(-108,-221,354,760),7726=>array(21,0,511,1057),7727=>array(31,0,477,903),7728=>array(21,0,837,927),7729=>array(31,0,716,982),7730=>array(21,-212,837,729),7731=>array(31,-212,716,760),7732=>array(21,-185,837,729),7733=>array(31,-185,716,760),7734=>array(21,-212,566,729),7735=>array(10,-212,354,760),7736=>array(21,-212,566,942),7737=>array(10,-212,450,914),7738=>array(21,-185,566,729),7739=>array(-68,-185,354,760),7740=>array(21,-240,566,729),7741=>array(-113,-240,354,760),7742=>array(21,0,974,927),7743=>array(31,0,984,800),7744=>array(21,0,974,928),7745=>array(31,0,984,759),7746=>array(21,-212,974,729),7747=>array(31,-212,984,560),7748=>array(21,0,816,927),7749=>array(31,0,654,759),7750=>array(21,-212,816,729),7751=>array(31,-212,654,560),7752=>array(21,-185,816,729),7753=>array(31,-185,654,560),7754=>array(21,-240,816,729),7755=>array(31,-240,654,560),7756=>array(36,-14,814,1057),7757=>array(36,-14,651,917),7758=>array(36,-14,814,1061),7759=>array(36,-14,651,900),7760=>array(36,-14,814,1057),7761=>array(36,-14,651,898),7762=>array(36,-14,814,1057),7763=>array(36,-14,651,900),7764=>array(21,0,719,927),7765=>array(-10,-208,677,800),7766=>array(21,0,719,928),7767=>array(-10,-208,677,759),7768=>array(21,0,685,928),7769=>array(31,0,545,759),7770=>array(21,-212,685,729),7771=>array(10,-212,545,560),7772=>array(21,-212,685,914),7773=>array(10,-212,545,759),7774=>array(21,-185,685,729),7775=>array(-69,-185,545,560),7776=>array(15,-14,665,928),7777=>array(10,-14,560,759),7778=>array(15,-212,665,742),7779=>array(10,-212,560,560),7780=>array(15,-14,719,928),7781=>array(10,-14,682,816),7782=>array(15,-14,690,1053),7783=>array(10,-14,605,875),7784=>array(15,-212,665,928),7785=>array(10,-212,560,762),7786=>array(48,0,748,928),7787=>array(43,0,509,941),7788=>array(48,-212,748,729),7789=>array(43,-212,509,702),7790=>array(48,-185,748,729),7791=>array(27,-185,509,702),7792=>array(38,-240,748,729),7793=>array(-20,-240,509,702),7794=>array(68,-212,791,729),7795=>array(60,-212,681,547),7796=>array(68,-221,791,729),7797=>array(60,-221,681,547),7798=>array(68,-203,791,729),7799=>array(60,-203,681,547),7800=>array(68,-14,791,1057),7801=>array(60,-14,681,917),7802=>array(68,-14,791,1043),7803=>array(60,-14,681,885),7804=>array(76,0,840,928),7805=>array(63,0,678,778),7806=>array(76,-212,840,729),7807=>array(63,-212,678,547),7808=>array(107,0,1143,931),7809=>array(87,0,927,803),7810=>array(107,0,1143,931),7811=>array(87,0,927,803),7812=>array(107,0,1143,927),7813=>array(87,0,927,774),7814=>array(107,0,1143,927),7815=>array(87,0,927,759),7816=>array(107,-212,1143,729),7817=>array(87,-212,927,547),7818=>array(-51,0,812,927),7819=>array(-41,0,671,759),7820=>array(-51,0,812,927),7821=>array(-41,0,671,774),7822=>array(63,0,809,928),7823=>array(0,-216,687,759),7824=>array(-26,0,740,927),7825=>array(-9,0,586,800),7826=>array(-26,-212,740,729),7827=>array(-9,-212,586,547),7828=>array(-26,-185,740,729),7829=>array(-9,-185,586,547),7830=>array(31,-185,654,760),7831=>array(43,0,509,927),7832=>array(87,0,927,883),7833=>array(0,-216,687,883),7834=>array(17,-14,825,760),7835=>array(50,0,540,941),7836=>array(-39,0,518,760),7837=>array(17,0,518,760),7838=>array(38,-14,808,743),7839=>array(16,-14,634,768),7840=>array(-65,-212,691,729),7841=>array(17,-212,611,560),7842=>array(-65,0,691,1025),7843=>array(17,-14,611,844),7844=>array(-65,0,853,1057),7845=>array(17,-14,795,876),7846=>array(-65,0,759,1057),7847=>array(17,-14,704,876),7848=>array(-65,0,840,1093),7849=>array(17,-14,773,913),7850=>array(-65,0,691,1068),7851=>array(17,-14,631,888),7852=>array(-65,-212,691,927),7853=>array(17,-212,611,800),7854=>array(-65,0,702,1057),7855=>array(17,-14,646,889),7856=>array(-65,0,691,1057),7857=>array(17,-14,611,889),7858=>array(-65,0,691,1121),7859=>array(17,-14,611,953),7860=>array(-65,0,693,1068),7861=>array(17,-14,630,900),7862=>array(-65,-212,691,936),7863=>array(17,-212,611,772),7864=>array(21,-212,670,729),7865=>array(36,-212,640,560),7866=>array(21,0,670,1025),7867=>array(36,-14,640,844),7868=>array(21,0,670,928),7869=>array(36,-14,640,778),7870=>array(21,0,805,1057),7871=>array(36,-14,814,876),7872=>array(21,0,772,1057),7873=>array(36,-14,721,876),7874=>array(21,0,799,1093),7875=>array(36,-14,797,913),7876=>array(21,0,670,1068),7877=>array(36,-14,648,888),7878=>array(21,-212,670,927),7879=>array(36,-212,640,800),7880=>array(21,0,417,1025),7881=>array(31,0,395,844),7882=>array(6,-212,351,729),7883=>array(10,-212,354,760),7884=>array(36,-212,814,742),7885=>array(36,-212,651,560),7886=>array(36,-14,814,1025),7887=>array(36,-14,651,844),7888=>array(36,-14,884,1057),7889=>array(36,-14,815,876),7890=>array(36,-14,814,1057),7891=>array(36,-14,724,876),7892=>array(36,-14,890,1093),7893=>array(36,-14,802,913),7894=>array(36,-14,814,1068),7895=>array(36,-14,655,888),7896=>array(36,-212,814,927),7897=>array(36,-212,651,800),7898=>array(39,-14,907,927),7899=>array(40,-14,771,800),7900=>array(39,-14,907,927),7901=>array(40,-14,771,798),7902=>array(39,-14,907,1025),7903=>array(40,-14,771,844),7904=>array(39,-14,907,928),7905=>array(40,-14,771,778),7906=>array(39,-212,907,760),7907=>array(40,-212,771,570),7908=>array(68,-212,791,729),7909=>array(60,-212,681,547),7910=>array(68,-14,791,1025),7911=>array(60,-14,681,844),7912=>array(67,-14,938,927),7913=>array(57,-14,795,799),7914=>array(67,-14,938,927),7915=>array(57,-14,795,800),7916=>array(67,-14,938,1025),7917=>array(57,-14,795,844),7918=>array(67,-14,938,928),7919=>array(57,-14,795,778),7920=>array(67,-212,938,761),7921=>array(57,-212,795,570),7922=>array(63,0,809,931),7923=>array(0,-216,687,803),7924=>array(63,-212,809,729),7925=>array(0,-216,687,547),7926=>array(63,0,809,1025),7927=>array(0,-216,687,844),7928=>array(63,0,809,928),7929=>array(0,-216,687,778),7930=>array(21,0,882,729),7931=>array(10,0,698,760),7936=>array(38,-12,692,785),7937=>array(38,-12,692,785),7938=>array(38,-12,692,800),7939=>array(38,-12,692,800),7940=>array(38,-12,692,800),7941=>array(38,-12,692,800),7942=>array(38,-12,692,928),7943=>array(38,-12,692,928),7944=>array(-65,0,691,785),7945=>array(-65,0,691,785),7946=>array(29,0,958,800),7947=>array(69,0,960,800),7948=>array(29,0,852,800),7949=>array(67,0,880,800),7950=>array(-3,0,752,928),7951=>array(20,0,776,928),7952=>array(27,-14,520,785),7953=>array(27,-14,520,785),7954=>array(27,-14,547,800),7955=>array(27,-14,541,800),7956=>array(27,-14,616,800),7957=>array(27,-14,601,800),7960=>array(31,0,778,785),7961=>array(69,0,781,785),7962=>array(29,0,1086,800),7963=>array(69,0,1083,800),7964=>array(29,0,1010,800),7965=>array(67,0,1039,800),7968=>array(50,-208,664,785),7969=>array(50,-208,664,785),7970=>array(50,-208,664,800),7971=>array(50,-208,664,800),7972=>array(50,-208,664,800),7973=>array(50,-208,684,800),7974=>array(50,-208,664,928),7975=>array(50,-208,664,928),7976=>array(31,0,924,785),7977=>array(69,0,930,785),7978=>array(29,0,1229,800),7979=>array(69,0,1229,800),7980=>array(29,0,1159,800),7981=>array(67,0,1185,800),7982=>array(98,0,1033,928),7983=>array(97,0,1042,928),7984=>array(42,-19,313,785),7985=>array(42,-19,313,785),7986=>array(0,-19,457,800),7987=>array(7,-19,426,800),7988=>array(42,-19,531,800),7989=>array(42,-19,523,800),7990=>array(42,-19,458,928),7991=>array(42,-19,455,928),7992=>array(31,0,462,785),7993=>array(69,0,468,785),7994=>array(29,0,756,800),7995=>array(69,0,764,800),7996=>array(29,0,691,800),7997=>array(67,0,717,800),7998=>array(98,0,583,928),7999=>array(97,0,583,928),8000=>array(36,-14,651,785),8001=>array(36,-14,651,785),8002=>array(36,-14,651,800),8003=>array(36,-14,651,800),8004=>array(36,-14,667,800),8005=>array(36,-14,680,800),8008=>array(31,-14,855,785),8009=>array(69,-14,897,785),8010=>array(29,-14,1185,800),8011=>array(69,-14,1188,800),8012=>array(29,-14,1017,800),8013=>array(67,-14,1046,800),8016=>array(54,-10,645,785),8017=>array(54,-10,645,785),8018=>array(54,-10,645,800),8019=>array(54,-10,645,800),8020=>array(54,-10,677,800),8021=>array(54,-10,683,800),8022=>array(54,-10,645,928),8023=>array(54,-10,645,928),8025=>array(69,0,1015,785),8027=>array(69,0,1269,800),8029=>array(67,0,1284,800),8031=>array(97,0,1134,928),8032=>array(33,-13,834,785),8033=>array(33,-13,834,785),8034=>array(33,-13,834,800),8035=>array(33,-13,834,800),8036=>array(33,-13,834,800),8037=>array(33,-13,834,800),8038=>array(33,-13,834,928),8039=>array(33,-13,834,928),8040=>array(13,0,870,785),8041=>array(63,0,920,785),8042=>array(29,0,1208,800),8043=>array(69,-3,1213,800),8044=>array(29,0,1037,800),8045=>array(67,0,1066,800),8046=>array(98,0,989,928),8047=>array(97,0,1037,928),8048=>array(38,-12,692,800),8049=>array(38,-12,692,800),8050=>array(27,-14,520,800),8051=>array(27,-14,567,800),8052=>array(50,-208,664,800),8053=>array(50,-208,664,800),8054=>array(42,-19,313,800),8055=>array(42,-19,436,800),8056=>array(36,-14,651,800),8057=>array(36,-14,651,800),8058=>array(54,-10,645,800),8059=>array(54,-10,645,800),8060=>array(33,-13,834,800),8061=>array(33,-13,834,800),8064=>array(38,-208,692,785),8065=>array(38,-208,692,785),8066=>array(38,-208,692,800),8067=>array(38,-208,692,800),8068=>array(38,-208,692,800),8069=>array(38,-208,692,800),8070=>array(38,-208,692,928),8071=>array(38,-208,692,928),8072=>array(-65,-208,691,785),8073=>array(-65,-208,691,785),8074=>array(29,-208,958,800),8075=>array(69,-208,960,800),8076=>array(29,-208,852,800),8077=>array(67,-208,880,800),8078=>array(-3,-208,752,928),8079=>array(20,-208,776,928),8080=>array(50,-208,664,785),8081=>array(50,-208,664,785),8082=>array(50,-208,664,800),8083=>array(50,-208,664,800),8084=>array(50,-208,664,800),8085=>array(50,-208,684,800),8086=>array(50,-208,664,928),8087=>array(50,-208,664,928),8088=>array(31,-208,924,785),8089=>array(69,-208,930,785),8090=>array(29,-208,1229,800),8091=>array(69,-208,1229,800),8092=>array(29,-208,1159,800),8093=>array(67,-208,1185,800),8094=>array(98,-208,1033,928),8095=>array(97,-208,1042,928),8096=>array(33,-208,834,785),8097=>array(33,-208,834,785),8098=>array(33,-208,834,800),8099=>array(33,-208,834,800),8100=>array(33,-208,834,800),8101=>array(33,-208,834,800),8102=>array(33,-208,834,928),8103=>array(33,-208,834,928),8104=>array(13,-208,870,785),8105=>array(63,-208,920,785),8106=>array(29,-208,1208,800),8107=>array(69,-208,1213,800),8108=>array(29,-208,1037,800),8109=>array(67,-208,1066,800),8110=>array(98,-208,989,928),8111=>array(97,-208,1037,928),8112=>array(38,-12,692,784),8113=>array(38,-12,692,760),8114=>array(38,-208,692,800),8115=>array(38,-208,692,559),8116=>array(38,-208,692,800),8118=>array(38,-12,692,778),8119=>array(38,-208,692,778),8120=>array(-65,0,691,927),8121=>array(-65,0,691,914),8122=>array(38,0,793,800),8123=>array(-42,0,714,800),8124=>array(-65,-208,691,729),8125=>array(210,595,381,785),8126=>array(132,-208,253,-45),8127=>array(210,595,381,785),8128=>array(133,638,500,778),8129=>array(152,654,540,928),8130=>array(50,-208,664,800),8131=>array(50,-208,664,560),8132=>array(50,-208,664,800),8134=>array(50,-208,664,778),8135=>array(50,-208,664,778),8136=>array(84,0,916,800),8137=>array(22,0,831,800),8138=>array(84,0,1059,800),8139=>array(28,0,986,800),8140=>array(21,-208,816,729),8141=>array(61,595,518,800),8142=>array(90,595,563,800),8143=>array(174,595,540,928),8144=>array(42,-19,413,784),8145=>array(42,-19,405,760),8146=>array(42,-19,402,978),8147=>array(50,-19,516,978),8150=>array(42,-19,424,778),8151=>array(42,-19,454,928),8152=>array(21,0,424,927),8153=>array(21,0,417,914),8154=>array(84,0,600,800),8155=>array(25,0,521,800),8157=>array(105,595,523,800),8158=>array(111,595,574,800),8159=>array(174,595,540,928),8160=>array(54,-10,645,784),8161=>array(54,-10,645,760),8162=>array(54,-10,645,978),8163=>array(54,-10,660,978),8164=>array(9,-208,699,785),8165=>array(9,-208,699,785),8166=>array(54,-10,645,778),8167=>array(54,-10,645,928),8168=>array(63,0,809,927),8169=>array(63,0,809,914),8170=>array(84,0,1105,800),8171=>array(20,0,1067,800),8172=>array(69,0,825,785),8173=>array(152,654,484,978),8174=>array(152,654,589,978),8175=>array(131,616,371,800),8178=>array(33,-208,834,800),8179=>array(33,-208,834,547),8180=>array(33,-208,834,800),8182=>array(33,-13,834,778),8183=>array(33,-208,834,778),8184=>array(84,-14,1029,800),8185=>array(28,-14,851,800),8186=>array(84,0,1046,800),8187=>array(-1,0,855,800),8188=>array(-45,-208,812,742),8189=>array(227,616,539,800),8190=>array(249,595,392,785),8208=>array(25,217,360,359),8209=>array(25,217,360,359),8210=>array(24,211,637,337),8211=>array(24,211,441,337),8212=>array(24,211,941,337),8213=>array(-30,211,995,337),8214=>array(127,-236,399,764),8215=>array(-10,-236,510,-9),8216=>array(113,418,389,729),8217=>array(73,418,349,729),8218=>array(-34,-122,242,189),8219=>array(107,418,302,729),8220=>array(113,418,652,729),8221=>array(73,418,612,729),8222=>array(-34,-122,505,189),8223=>array(95,418,535,729),8224=>array(38,-96,504,729),8225=>array(-28,-96,504,729),8226=>array(144,196,495,547),8227=>array(144,157,534,586),8228=>array(46,0,259,189),8229=>array(46,0,569,189),8230=>array(46,0,879,189),8231=>array(124,304,282,424),8240=>array(55,-14,1401,742),8241=>array(55,-14,1855,742),8242=>array(2,547,257,729),8243=>array(2,547,440,729),8244=>array(2,547,624,729),8245=>array(161,547,346,729),8246=>array(161,547,532,729),8247=>array(161,547,712,729),8248=>array(101,-238,632,29),8249=>array(61,67,355,519),8250=>array(38,66,331,519),8251=>array(72,0,900,829),8252=>array(-2,0,629,729),8253=>array(98,0,550,742),8254=>array(-10,663,510,755),8255=>array(-31,-237,859,-79),8256=>array(-31,769,859,927),8257=>array(-52,-235,296,231),8258=>array(20,-37,1003,832),8259=>array(102,188,428,325),8260=>array(-278,-14,445,742),8261=>array(-10,-132,466,760),8262=>array(-28,-132,448,760),8263=>array(69,0,1035,742),8264=>array(104,0,831,742),8265=>array(-2,0,799,742),8266=>array(87,-125,530,546),8267=>array(57,-96,666,729),8268=>array(75,189,425,541),8269=>array(75,189,425,541),8270=>array(20,-37,503,427),8271=>array(56,-142,327,547),8272=>array(-31,-237,859,927),8273=>array(68,-3,455,830),8274=>array(3,-93,548,729),8275=>array(49,212,951,415),8276=>array(-31,-351,859,-192),8277=>array(142,98,694,631),8278=>array(95,93,628,645),8279=>array(2,547,807,729),8280=>array(61,21,776,708),8281=>array(80,71,768,657),8282=>array(31,0,350,729),8283=>array(30,-170,839,898),8284=>array(43,0,794,729),8285=>array(31,0,339,683),8286=>array(31,0,339,683),8304=>array(29,319,398,742),8305=>array(12,326,205,751),8308=>array(3,326,388,734),8309=>array(12,319,393,734),8310=>array(37,319,403,742),8311=>array(51,326,418,734),8312=>array(20,319,400,742),8313=>array(23,319,389,742),8314=>array(67,326,461,677),8315=>array(67,469,461,534),8316=>array(67,407,461,596),8317=>array(48,252,282,751),8318=>array(-1,252,232,751),8319=>array(23,326,412,640),8320=>array(29,-7,398,416),8321=>array(67,0,395,408),8322=>array(45,0,431,416),8323=>array(40,-7,427,416),8324=>array(3,0,388,408),8325=>array(12,-7,393,408),8326=>array(37,-7,403,416),8327=>array(51,0,418,408),8328=>array(20,-7,400,416),8329=>array(23,-7,389,416),8330=>array(67,0,461,351),8331=>array(67,143,461,208),8332=>array(67,81,461,270),8333=>array(48,-74,282,425),8334=>array(-1,-74,232,425),8336=>array(37,-8,411,313),8337=>array(49,-8,429,313),8338=>array(49,-8,436,313),8339=>array(-20,0,427,306),8340=>array(53,-8,423,313),8341=>array(12,0,401,425),8342=>array(20,0,451,425),8343=>array(12,0,207,425),8344=>array(21,0,621,313),8345=>array(23,0,412,313),8346=>array(-6,-117,427,313),8347=>array(11,-8,355,313),8348=>array(72,0,365,393),8352=>array(53,0,919,729),8353=>array(36,-44,693,778),8354=>array(36,-14,697,742),8355=>array(3,0,690,729),8356=>array(7,0,691,742),8357=>array(30,-93,975,640),8358=>array(14,0,823,729),8359=>array(21,-14,1453,729),8360=>array(22,-14,1154,729),8361=>array(23,0,1143,729),8362=>array(-32,-14,870,729),8363=>array(36,-185,817,760),8364=>array(-41,-14,687,742),8365=>array(12,0,735,729),8366=>array(55,0,754,729),8367=>array(37,-223,1220,742),8368=>array(1,-14,660,742),8369=>array(21,0,697,729),8370=>array(38,-81,682,809),8371=>array(-66,0,685,729),8372=>array(16,-14,844,742),8373=>array(76,-147,688,760),8376=>array(18,0,754,729),8377=>array(61,0,718,729),8378=>array(-10,0,745,729),8400=>array(-510,628,-26,760),8401=>array(-483,628,-11,760),8406=>array(-470,560,-20,760),8407=>array(-477,560,-26,760),8411=>array(-335,654,190,774),8412=>array(-432,654,287,774),8417=>array(-470,560,-26,760),8448=>array(15,-23,1106,752),8449=>array(15,-23,1106,752),8450=>array(50,-14,670,742),8451=>array(87,-14,1201,749),8452=>array(64,0,832,729),8453=>array(25,-24,1097,752),8454=>array(25,-24,1169,752),8455=>array(37,-14,652,742),8456=>array(1,-146,693,611),8457=>array(87,0,999,749),8459=>array(36,-14,1063,746),8460=>array(6,-125,809,747),8461=>array(100,0,788,729),8462=>array(31,0,654,760),8463=>array(10,0,625,760),8464=>array(36,-14,533,742),8465=>array(52,-14,659,743),8466=>array(37,-14,787,742),8467=>array(-14,-14,401,742),8468=>array(12,-14,935,760),8469=>array(92,0,745,729),8470=>array(-37,0,1156,729),8471=>array(138,0,862,725),8472=>array(54,-221,658,495),8473=>array(92,0,709,729),8474=>array(50,-146,800,742),8475=>array(31,-14,904,768),8476=>array(41,-14,803,743),8477=>array(98,0,793,729),8478=>array(53,0,844,729),8479=>array(53,-112,666,887),8480=>array(126,443,770,730),8481=>array(40,0,1223,547),8482=>array(144,447,790,729),8483=>array(22,-113,877,885),8484=>array(45,0,709,729),8485=>array(-11,-230,648,777),8486=>array(-45,0,812,742),8487=>array(42,-14,813,723),8488=>array(-5,-159,670,729),8489=>array(36,0,306,566),8490=>array(21,0,837,729),8491=>array(-65,0,691,928),8492=>array(41,-1,853,772),8493=>array(63,-19,767,742),8494=>array(61,-12,793,647),8495=>array(41,-14,591,533),8496=>array(72,-14,668,742),8497=>array(37,-14,860,773),8498=>array(21,0,670,729),8499=>array(38,-18,1156,751),8500=>array(29,-12,436,420),8501=>array(50,-14,761,742),8502=>array(19,-14,687,742),8503=>array(31,-35,439,742),8504=>array(63,-41,633,742),8505=>array(34,0,355,760),8506=>array(44,-27,994,723),8507=>array(0,0,1384,547),8508=>array(34,-14,765,547),8509=>array(-40,-208,700,561),8510=>array(92,0,627,729),8511=>array(92,0,771,729),8512=>array(12,-192,820,719),8513=>array(5,-14,747,742),8514=>array(9,0,554,729),8515=>array(11,0,671,729),8516=>array(2,0,749,729),8517=>array(21,0,786,729),8518=>array(34,-14,752,760),8519=>array(33,-14,635,560),8520=>array(15,0,353,760),8521=>array(-143,-216,354,760),8523=>array(60,-14,838,742),8526=>array(1,0,523,547),8528=>array(56,-14,1023,742),8529=>array(56,-14,994,742),8530=>array(56,-14,1441,742),8531=>array(56,-14,1032,742),8532=>array(45,-14,1032,742),8533=>array(56,-14,998,742),8534=>array(45,-14,998,742),8535=>array(40,-14,998,742),8536=>array(3,-14,998,742),8537=>array(56,-14,1008,742),8538=>array(12,-14,1008,742),8539=>array(56,-14,1005,742),8540=>array(40,-14,1005,742),8541=>array(12,-14,1005,742),8542=>array(51,-14,1005,742),8543=>array(56,-14,893,742),8544=>array(21,0,351,729),8545=>array(21,0,638,729),8546=>array(21,0,924,729),8547=>array(21,0,1165,729),8548=>array(76,0,840,729),8549=>array(76,0,1078,729),8550=>array(76,0,1365,729),8551=>array(76,0,1651,729),8552=>array(21,0,1162,729),8553=>array(-51,0,812,729),8554=>array(-51,0,1099,729),8555=>array(-51,0,1386,729),8556=>array(21,0,566,729),8557=>array(36,-14,724,742),8558=>array(21,0,786,729),8559=>array(21,0,974,729),8560=>array(31,0,354,760),8561=>array(31,0,619,760),8562=>array(31,0,883,760),8563=>array(31,0,987,760),8564=>array(63,0,678,547),8565=>array(63,0,973,760),8566=>array(63,0,1238,760),8567=>array(63,0,1502,760),8568=>array(31,0,995,760),8569=>array(-41,0,671,547),8570=>array(-41,0,980,760),8571=>array(-41,0,1245,760),8572=>array(31,0,354,760),8573=>array(37,-14,581,560),8574=>array(36,-14,724,760),8575=>array(31,0,984,560),8576=>array(48,0,1240,729),8577=>array(21,0,782,729),8578=>array(48,0,1240,729),8579=>array(-13,-14,675,742),8580=>array(-7,-14,537,560),8581=>array(68,-208,752,742),8585=>array(29,-14,1032,742),8592=>array(49,87,781,540),8593=>array(193,0,646,732),8594=>array(57,87,789,540),8595=>array(193,-3,646,729),8596=>array(49,87,789,540),8597=>array(193,-3,646,732),8598=>array(136,66,720,650),8599=>array(136,66,720,650),8600=>array(136,66,720,650),8601=>array(136,66,720,650),8602=>array(49,87,781,540),8603=>array(57,87,789,540),8604=>array(13,84,833,431),8605=>array(5,84,825,431),8606=>array(49,87,781,540),8607=>array(189,0,641,732),8608=>array(57,87,789,540),8609=>array(194,-3,646,729),8610=>array(49,87,793,540),8611=>array(45,87,789,540),8612=>array(49,87,781,540),8613=>array(193,0,646,732),8614=>array(57,87,789,540),8615=>array(193,0,646,732),8616=>array(193,0,646,732),8617=>array(49,87,781,565),8618=>array(57,87,789,565),8619=>array(49,87,781,565),8620=>array(57,87,789,565),8621=>array(49,87,789,540),8622=>array(49,86,789,541),8623=>array(123,-4,714,733),8624=>array(169,0,646,755),8625=>array(192,0,669,755),8626=>array(169,-26,646,729),8627=>array(192,-26,669,729),8628=>array(233,-3,772,621),8629=>array(49,87,673,626),8630=>array(11,198,816,685),8631=>array(22,198,828,685),8632=>array(118,13,788,729),8633=>array(49,-108,789,735),8634=>array(86,45,767,691),8635=>array(71,45,751,691),8636=>array(49,255,781,540),8637=>array(49,87,781,372),8638=>array(361,0,646,732),8639=>array(193,0,478,732),8640=>array(57,255,789,540),8641=>array(57,87,789,372),8642=>array(361,0,646,732),8643=>array(193,0,478,732),8644=>array(49,-59,789,686),8645=>array(47,-3,792,732),8646=>array(49,-59,789,686),8647=>array(49,-59,781,686),8648=>array(46,0,792,732),8649=>array(57,-59,789,686),8650=>array(46,-3,792,729),8651=>array(49,-5,789,632),8652=>array(49,-5,789,632),8653=>array(49,87,781,540),8654=>array(49,87,789,540),8655=>array(57,87,789,540),8656=>array(49,87,781,540),8657=>array(193,0,645,732),8658=>array(57,87,789,540),8659=>array(193,-3,645,729),8660=>array(49,87,789,540),8661=>array(193,-8,645,732),8662=>array(132,-26,755,596),8663=>array(88,-26,711,597),8664=>array(88,16,711,639),8665=>array(132,16,755,639),8666=>array(49,87,781,540),8667=>array(57,87,789,540),8668=>array(44,87,776,540),8669=>array(57,87,789,540),8670=>array(193,0,646,732),8671=>array(193,-3,646,729),8672=>array(49,87,781,540),8673=>array(193,0,646,732),8674=>array(57,87,789,540),8675=>array(193,-3,646,729),8676=>array(49,87,781,540),8677=>array(57,87,789,540),8678=>array(27,46,781,581),8679=>array(151,0,687,754),8680=>array(35,46,789,581),8681=>array(151,-25,687,729),8682=>array(151,0,687,754),8683=>array(151,0,687,754),8684=>array(151,0,687,754),8685=>array(151,0,687,754),8686=>array(151,0,687,754),8687=>array(151,0,687,754),8688=>array(35,46,789,581),8689=>array(60,0,788,729),8690=>array(60,0,788,729),8691=>array(151,-25,687,754),8692=>array(57,87,789,540),8693=>array(47,-3,792,732),8694=>array(57,-223,789,850),8695=>array(49,87,781,540),8696=>array(57,87,789,540),8697=>array(49,87,789,540),8698=>array(49,87,781,540),8699=>array(57,87,789,540),8700=>array(49,87,789,540),8701=>array(27,96,781,531),8702=>array(57,96,811,531),8703=>array(27,96,811,531),8704=>array(5,0,769,729),8705=>array(48,-14,629,742),8706=>array(29,-14,515,674),8707=>array(92,0,610,729),8708=>array(92,-46,610,775),8709=>array(47,-15,810,715),8710=>array(0,0,697,719),8711=>array(0,0,697,719),8712=>array(73,-2,824,730),8713=>array(73,-46,824,775),8714=>array(106,58,644,568),8715=>array(73,-2,824,730),8716=>array(73,-46,824,775),8717=>array(106,58,644,568),8718=>array(98,0,539,553),8719=>array(73,-192,712,719),8720=>array(73,-193,712,718),8721=>array(20,-192,697,719),8722=>array(106,256,732,371),8723=>array(106,0,732,627),8724=>array(49,0,647,729),8725=>array(-96,-93,434,729),8726=>array(165,-49,530,772),8727=>array(118,0,720,626),8728=>array(150,151,475,477),8729=>array(102,253,278,442),8730=>array(37,-20,669,837),8731=>array(37,-20,669,933),8732=>array(36,-20,669,924),8733=>array(92,89,617,505),8734=>array(92,89,741,505),8735=>array(106,67,732,693),8736=>array(77,0,820,729),8737=>array(77,-44,820,729),8738=>array(116,-0,732,726),8739=>array(207,-207,322,773),8740=>array(48,-207,482,773),8741=>array(112,-207,417,773),8742=>array(48,-207,482,773),8743=>array(151,0,661,579),8744=>array(151,0,661,579),8745=>array(151,0,661,579),8746=>array(151,0,661,579),8747=>array(15,-227,548,754),8748=>array(15,-227,914,754),8749=>array(15,-227,1280,754),8750=>array(14,-227,548,754),8751=>array(38,-227,938,754),8752=>array(23,-227,1290,754),8753=>array(15,-227,616,754),8754=>array(14,-227,600,754),8755=>array(14,-227,588,754),8756=>array(60,78,637,647),8757=>array(60,78,637,647),8758=>array(59,79,235,647),8759=>array(60,78,637,647),8760=>array(106,256,732,631),8761=>array(106,45,800,584),8762=>array(106,-4,732,631),8763=>array(106,-34,732,660),8764=>array(106,212,732,415),8765=>array(106,212,732,415),8766=>array(65,131,772,497),8767=>array(106,42,732,584),8768=>array(85,0,289,626),8769=>array(106,76,732,551),8770=>array(106,110,732,482),8771=>array(106,144,732,517),8772=>array(106,0,732,637),8773=>array(106,37,732,628),8774=>array(106,-31,732,628),8775=>array(106,-86,732,726),8776=>array(106,110,732,517),8777=>array(106,8,732,614),8778=>array(106,37,732,628),8779=>array(106,-13,732,628),8780=>array(106,37,732,628),8781=>array(105,105,732,585),8782=>array(106,26,732,656),8783=>array(106,172,732,656),8784=>array(106,144,732,744),8785=>array(106,-117,732,743),8786=>array(105,-92,732,719),8787=>array(104,-92,731,719),8788=>array(98,102,965,520),8789=>array(96,102,966,520),8790=>array(106,144,732,482),8791=>array(106,144,732,839),8792=>array(106,144,732,704),8793=>array(106,144,732,840),8794=>array(106,144,732,840),8795=>array(106,144,732,959),8796=>array(106,144,732,952),8797=>array(106,144,732,762),8798=>array(106,144,732,786),8799=>array(106,144,732,903),8800=>array(106,-5,732,631),8801=>array(106,38,732,588),8802=>array(106,-69,732,695),8803=>array(106,-74,732,700),8804=>array(106,0,732,582),8805=>array(106,0,732,582),8806=>array(106,-106,732,617),8807=>array(106,-106,732,617),8808=>array(106,-185,732,617),8809=>array(106,-185,732,617),8810=>array(72,-34,974,660),8811=>array(72,-34,974,660),8812=>array(86,-132,414,759),8813=>array(105,-10,732,700),8814=>array(106,-4,732,690),8815=>array(106,-63,732,631),8816=>array(106,-112,732,645),8817=>array(106,-112,732,645),8818=>array(106,-84,732,582),8819=>array(106,-84,732,582),8820=>array(106,-112,732,645),8821=>array(106,-112,732,645),8822=>array(102,-119,732,678),8823=>array(102,-119,732,678),8824=>array(102,-221,732,779),8825=>array(102,-221,732,779),8826=>array(106,-55,732,681),8827=>array(106,-55,732,681),8828=>array(106,-177,732,684),8829=>array(106,-177,732,684),8830=>array(106,-132,732,684),8831=>array(106,-132,732,684),8832=>array(106,-89,732,781),8833=>array(106,-89,732,781),8834=>array(99,67,739,559),8835=>array(99,65,739,559),8836=>array(99,-96,739,726),8837=>array(99,-100,739,722),8838=>array(99,0,739,636),8839=>array(99,0,739,635),8840=>array(99,-124,739,759),8841=>array(99,-124,739,759),8842=>array(99,-97,739,636),8843=>array(99,-97,739,635),8844=>array(151,0,661,579),8845=>array(151,0,661,579),8846=>array(151,0,661,579),8847=>array(106,0,732,584),8848=>array(106,0,732,584),8849=>array(106,-115,732,667),8850=>array(106,-115,732,667),8851=>array(106,0,690,626),8852=>array(106,0,690,626),8853=>array(91,-14,747,643),8854=>array(91,-14,747,643),8855=>array(91,-14,747,643),8856=>array(91,-13,747,642),8857=>array(91,-14,747,643),8858=>array(91,-14,747,643),8859=>array(91,-14,747,643),8860=>array(91,-14,747,643),8861=>array(91,-14,747,643),8862=>array(77,-29,761,657),8863=>array(77,-29,761,657),8864=>array(77,-29,761,657),8865=>array(77,-29,761,657),8866=>array(85,0,829,705),8867=>array(85,0,829,705),8868=>array(85,0,829,705),8869=>array(85,0,829,705),8870=>array(85,0,457,705),8871=>array(85,0,457,705),8872=>array(85,0,829,705),8873=>array(85,0,829,705),8874=>array(85,0,829,705),8875=>array(85,0,829,705),8876=>array(85,-100,829,805),8877=>array(85,-100,829,805),8878=>array(85,-100,829,805),8879=>array(85,-100,829,805),8880=>array(106,-54,724,681),8881=>array(114,-54,732,681),8882=>array(106,-1,732,628),8883=>array(106,-1,732,628),8884=>array(106,-80,732,706),8885=>array(106,-80,732,706),8886=>array(60,151,940,477),8887=>array(60,151,940,477),8888=>array(60,151,778,477),8889=>array(43,-63,794,689),8890=>array(63,0,480,705),8891=>array(103,0,709,759),8892=>array(103,0,709,759),8893=>array(103,0,709,759),8894=>array(106,0,732,626),8895=>array(106,0,732,626),8896=>array(0,-192,843,719),8897=>array(0,-192,843,719),8898=>array(48,-192,794,719),8899=>array(48,-192,794,719),8900=>array(3,-233,491,807),8901=>array(102,253,278,442),8902=>array(83,112,543,549),8903=>array(106,-56,732,683),8904=>array(106,-48,894,674),8905=>array(106,-48,894,675),8906=>array(106,-48,894,675),8907=>array(106,-48,894,675),8908=>array(106,-48,894,675),8909=>array(106,144,732,517),8910=>array(49,0,763,579),8911=>array(49,0,763,579),8912=>array(93,-22,732,649),8913=>array(106,-22,745,649),8914=>array(83,0,755,639),8915=>array(83,-14,755,625),8916=>array(186,0,652,729),8917=>array(106,-100,732,729),8918=>array(106,30,732,597),8919=>array(106,30,732,597),8920=>array(72,-34,1350,660),8921=>array(72,-34,1350,660),8922=>array(106,-211,732,837),8923=>array(106,-211,732,837),8924=>array(106,0,732,582),8925=>array(106,0,732,582),8926=>array(106,-177,732,684),8927=>array(106,-177,732,684),8928=>array(106,-197,732,808),8929=>array(106,-263,732,742),8930=>array(106,-191,732,817),8931=>array(106,-191,732,817),8932=>array(106,-146,732,636),8933=>array(106,-146,732,636),8934=>array(106,-168,732,582),8935=>array(106,-168,732,582),8936=>array(106,-216,732,684),8937=>array(106,-216,732,684),8938=>array(106,-138,732,808),8939=>array(106,-138,732,808),8940=>array(106,-224,732,894),8941=>array(106,-224,732,894),8942=>array(412,-40,588,735),8943=>array(79,253,921,442),8944=>array(79,-40,921,735),8945=>array(79,-40,921,735),8946=>array(72,-2,1085,730),8947=>array(73,-2,824,730),8948=>array(106,58,644,568),8949=>array(73,-2,824,984),8950=>array(73,-2,824,919),8951=>array(106,58,644,741),8952=>array(73,-207,824,730),8953=>array(73,-2,824,730),8954=>array(72,-2,1085,730),8955=>array(73,-2,824,730),8956=>array(106,58,644,568),8957=>array(72,-2,824,919),8958=>array(106,58,644,741),8959=>array(106,0,791,732),8960=>array(31,-22,572,519),8961=>array(56,152,540,453),8962=>array(64,0,651,596),8963=>array(193,470,646,732),8964=>array(193,0,646,263),8965=>array(193,-12,646,423),8966=>array(193,-12,646,552),8967=>array(194,-42,443,802),8968=>array(-1,-132,476,760),8969=>array(118,-132,458,760),8970=>array(-1,-132,339,760),8971=>array(-19,-132,458,760),8972=>array(352,-77,759,331),8973=>array(49,-77,457,331),8974=>array(352,226,759,634),8975=>array(49,226,457,634),8976=>array(106,140,732,444),8977=>array(3,113,536,646),8984=>array(84,0,843,759),8985=>array(106,140,732,444),8988=>array(86,425,469,760),8989=>array(127,425,469,760),8990=>array(62,-126,403,208),8991=>array(41,-126,423,208),8992=>array(235,-250,586,926),8993=>array(22,-240,373,940),8996=>array(76,215,1076,575),8997=>array(76,0,1076,575),8998=>array(76,0,1414,760),8999=>array(76,0,1076,760),9000=>array(59,0,1385,729),9003=>array(0,0,1338,760),9004=>array(73,-91,800,748),9075=>array(78,-19,348,547),9076=>array(84,-208,671,562),9077=>array(43,-13,826,547),9082=>array(48,-13,645,559),9085=>array(1,-228,862,99),9095=>array(76,0,1100,743),9108=>array(17,0,856,727),9115=>array(63,-252,438,928),9116=>array(63,-252,205,940),9117=>array(63,-240,438,940),9118=>array(63,-252,438,928),9119=>array(295,-252,438,940),9120=>array(63,-240,438,940),9121=>array(63,-252,438,928),9122=>array(63,-252,205,940),9123=>array(63,-240,438,940),9124=>array(63,-252,438,928),9125=>array(295,-252,438,940),9126=>array(63,-240,438,940),9127=>array(306,-261,668,928),9128=>array(82,-247,444,934),9129=>array(306,-240,668,934),9130=>array(306,-256,444,934),9131=>array(82,-261,444,928),9132=>array(306,-247,668,934),9133=>array(82,-240,444,934),9134=>array(235,-250,373,940),9166=>array(27,46,781,729),9167=>array(91,0,854,596),9187=>array(73,-91,800,748),9189=>array(3,75,766,444),9192=>array(-5,-129,623,294),9250=>array(-34,-14,652,760),9251=>array(21,-228,672,99),9312=>array(59,-15,788,715),9313=>array(59,-15,788,715),9314=>array(59,-15,788,715),9315=>array(59,-15,788,715),9316=>array(59,-15,788,715),9317=>array(59,-15,788,715),9318=>array(59,-15,788,715),9319=>array(59,-15,788,715),9320=>array(59,-15,788,715),9321=>array(59,-15,788,715),9600=>array(-10,260,779,770),9601=>array(-10,-250,779,-123),9602=>array(-10,-250,779,-5),9603=>array(-10,-250,779,132),9604=>array(-10,-250,779,260),9605=>array(-10,-250,779,387),9606=>array(-10,-250,779,515),9607=>array(-10,-250,779,642),9608=>array(-10,-250,779,770),9609=>array(-10,-250,680,770),9610=>array(-10,-250,582,770),9611=>array(-10,-250,483,770),9612=>array(-10,-250,384,770),9613=>array(-10,-250,286,770),9614=>array(-10,-250,187,770),9615=>array(-10,-250,88,770),9616=>array(384,-250,778,770),9617=>array(-10,-250,680,770),9618=>array(-10,-250,779,770),9619=>array(-10,-250,779,770),9620=>array(-10,642,779,770),9621=>array(680,-250,778,770),9622=>array(-10,-250,385,260),9623=>array(384,-250,779,260),9624=>array(-10,260,385,770),9625=>array(-10,-250,779,770),9626=>array(-10,-250,779,770),9627=>array(-10,-250,779,770),9628=>array(-10,-250,779,770),9629=>array(384,260,779,770),9630=>array(-10,-250,779,770),9631=>array(-10,-250,779,770),9632=>array(91,-124,854,643),9633=>array(91,-124,854,643),9634=>array(91,-124,854,643),9635=>array(91,-124,854,643),9636=>array(91,-124,854,643),9637=>array(91,-124,854,643),9638=>array(91,-124,854,643),9639=>array(91,-124,854,643),9640=>array(91,-124,854,643),9641=>array(91,-124,854,643),9642=>array(91,11,587,509),9643=>array(91,11,587,509),9644=>array(91,75,854,444),9645=>array(91,75,854,444),9646=>array(91,-122,459,642),9647=>array(91,-122,459,642),9648=>array(3,75,766,444),9649=>array(3,75,766,444),9650=>array(3,-124,766,643),9651=>array(3,-124,766,643),9652=>array(3,11,499,509),9653=>array(3,11,499,509),9654=>array(3,-124,766,643),9655=>array(3,-124,766,643),9656=>array(3,11,499,509),9657=>array(3,11,499,509),9658=>array(3,11,766,509),9659=>array(3,11,766,509),9660=>array(3,-124,766,643),9661=>array(3,-124,766,643),9662=>array(3,11,499,509),9663=>array(3,11,499,509),9664=>array(3,-124,766,643),9665=>array(3,-124,766,643),9666=>array(3,11,499,509),9667=>array(3,11,499,509),9668=>array(3,11,766,509),9669=>array(3,11,766,509),9670=>array(3,-124,766,643),9671=>array(3,-124,766,643),9672=>array(3,-124,766,643),9673=>array(55,-125,818,645),9674=>array(3,-233,491,807),9675=>array(55,-125,818,645),9676=>array(56,-125,817,644),9677=>array(55,-125,818,645),9678=>array(55,-125,818,645),9679=>array(55,-123,818,641),9680=>array(55,-123,818,641),9681=>array(55,-123,818,641),9682=>array(55,-123,818,641),9683=>array(55,-123,818,641),9684=>array(55,-123,818,641),9685=>array(55,-123,818,641),9686=>array(55,-125,436,645),9687=>array(91,-125,472,645),9688=>array(91,-10,750,770),9689=>array(91,-250,879,770),9690=>array(91,260,879,770),9691=>array(91,-250,879,260),9692=>array(3,260,385,645),9693=>array(3,260,384,645),9694=>array(3,-125,384,260),9695=>array(3,-125,385,260),9696=>array(3,260,766,645),9697=>array(3,-125,766,260),9698=>array(3,-124,766,643),9699=>array(3,-124,766,643),9700=>array(3,-124,766,643),9701=>array(3,-124,766,643),9702=>array(144,196,495,547),9703=>array(91,-124,854,643),9704=>array(91,-124,854,643),9705=>array(91,-124,854,643),9706=>array(91,-124,854,643),9707=>array(91,-124,854,643),9708=>array(3,-124,766,643),9709=>array(3,-124,766,643),9710=>array(3,-124,766,643),9711=>array(55,-250,1064,770),9712=>array(91,-124,854,643),9713=>array(91,-124,854,643),9714=>array(91,-124,854,643),9715=>array(91,-124,854,643),9716=>array(55,-123,818,641),9717=>array(55,-123,818,641),9718=>array(55,-123,818,641),9719=>array(55,-123,818,641),9720=>array(3,-124,766,643),9721=>array(3,-124,766,643),9722=>array(3,-124,766,643),9723=>array(91,-66,739,585),9724=>array(91,-66,739,585),9725=>array(91,-17,642,537),9726=>array(91,-17,642,537),9727=>array(3,-124,766,643),9728=>array(83,0,813,729),9729=>array(51,-2,949,360),9730=>array(49,0,848,729),9731=>array(83,-0,813,927),9732=>array(64,0,833,880),9733=>array(65,-4,832,723),9734=>array(65,-4,832,723),9735=>array(83,2,490,729),9736=>array(83,0,813,731),9737=>array(83,0,813,730),9738=>array(61,0,828,727),9739=>array(61,0,828,723),9740=>array(61,-1,610,722),9741=>array(61,0,952,723),9742=>array(68,0,1177,729),9743=>array(71,0,1180,729),9744=>array(90,0,807,729),9745=>array(89,0,808,729),9746=>array(89,0,808,729),9747=>array(75,78,457,656),9748=>array(49,0,870,933),9749=>array(74,0,822,731),9750=>array(84,0,813,731),9751=>array(84,0,813,727),9752=>array(78,0,819,729),9753=>array(83,140,813,574),9754=>array(84,113,813,569),9755=>array(84,113,813,569),9756=>array(87,104,810,569),9757=>array(72,0,537,724),9758=>array(86,103,810,569),9759=>array(72,-3,537,720),9760=>array(61,0,835,730),9761=>array(84,0,813,730),9762=>array(83,0,813,730),9763=>array(49,0,848,730),9764=>array(49,-2,620,727),9765=>array(83,0,663,731),9766=>array(83,-1,566,731),9767=>array(83,0,701,911),9768=>array(83,0,462,730),9769=>array(83,-1,813,729),9770=>array(87,0,810,730),9771=>array(83,0,814,731),9772=>array(83,0,627,731),9773=>array(83,0,813,730),9774=>array(83,0,813,730),9775=>array(83,0,813,730),9776=>array(83,0,813,729),9777=>array(83,0,814,729),9778=>array(83,0,813,729),9779=>array(83,0,813,729),9780=>array(83,0,813,729),9781=>array(83,0,813,729),9782=>array(83,0,813,729),9783=>array(83,0,813,729),9784=>array(80,3,817,721),9785=>array(83,-73,959,804),9786=>array(83,-73,959,804),9787=>array(83,-73,959,804),9788=>array(83,0,813,730),9789=>array(358,0,814,730),9790=>array(83,0,539,730),9791=>array(85,-102,528,732),9792=>array(85,-125,647,731),9793=>array(85,-14,647,843),9794=>array(79,-14,831,720),9795=>array(166,0,730,730),9796=>array(219,0,677,730),9797=>array(121,0,774,730),9798=>array(127,0,769,730),9799=>array(240,0,656,730),9800=>array(45,0,851,731),9801=>array(89,0,807,730),9802=>array(94,0,802,731),9803=>array(113,31,784,679),9804=>array(140,0,756,730),9805=>array(53,-180,843,730),9806=>array(83,52,813,653),9807=>array(34,-96,863,730),9808=>array(83,-0,813,730),9809=>array(94,0,802,730),9810=>array(86,153,810,579),9811=>array(157,0,739,730),9812=>array(98,0,798,730),9813=>array(110,0,786,730),9814=>array(167,-1,729,729),9815=>array(214,0,683,730),9816=>array(165,0,732,730),9817=>array(148,-0,748,730),9818=>array(98,0,798,730),9819=>array(110,0,786,730),9820=>array(167,-1,729,729),9821=>array(214,0,683,730),9822=>array(162,0,734,730),9823=>array(148,-0,748,730),9824=>array(158,0,738,729),9825=>array(90,0,806,727),9826=>array(168,0,728,729),9827=>array(111,0,785,729),9828=>array(157,0,739,729),9829=>array(89,0,808,729),9830=>array(168,0,728,729),9831=>array(111,0,785,732),9832=>array(105,-1,791,729),9833=>array(84,-5,339,729),9834=>array(84,-5,554,729),9835=>array(184,-102,712,729),9836=>array(92,-5,804,729),9837=>array(88,-3,392,731),9838=>array(84,0,273,731),9839=>array(84,0,400,731),9840=>array(84,0,664,731),9841=>array(64,0,701,731),9842=>array(84,0,813,709),9843=>array(76,16,820,731),9844=>array(76,16,820,731),9845=>array(76,16,820,731),9846=>array(76,16,820,731),9847=>array(76,16,820,731),9848=>array(76,16,820,731),9849=>array(76,16,820,731),9850=>array(76,16,820,731),9851=>array(84,0,812,704),9852=>array(83,0,814,731),9853=>array(83,0,814,731),9854=>array(83,0,814,731),9855=>array(149,1,747,731),9856=>array(73,0,797,725),9857=>array(73,0,797,725),9858=>array(73,0,797,725),9859=>array(73,0,797,725),9860=>array(73,0,797,725),9861=>array(73,0,797,725),9862=>array(83,0,813,731),9863=>array(83,0,813,731),9864=>array(83,0,813,731),9865=>array(83,0,813,731),9866=>array(83,0,813,98),9867=>array(83,0,813,98),9868=>array(83,0,813,413),9869=>array(83,0,813,413),9870=>array(83,0,813,413),9871=>array(83,0,813,413),9872=>array(168,3,728,731),9873=>array(168,3,728,731),9874=>array(52,0,844,731),9875=>array(97,-10,799,732),9876=>array(131,0,765,729),9877=>array(61,-10,479,732),9878=>array(59,-10,837,732),9879=>array(61,0,835,732),9880=>array(145,0,750,732),9881=>array(95,-17,802,727),9882=>array(128,-9,768,733),9883=>array(127,0,769,728),9884=>array(127,0,769,729),9888=>array(49,0,848,729),9889=>array(83,2,619,730),9890=>array(85,-125,919,731),9891=>array(79,-206,1023,720),9892=>array(85,-186,1109,856),9893=>array(85,-125,837,917),9894=>array(131,-14,727,869),9895=>array(101,-170,741,884),9896=>array(188,-14,650,869),9897=>array(4,133,829,596),9898=>array(188,133,650,597),9899=>array(188,133,650,597),9900=>array(249,194,589,536),9901=>array(175,194,663,536),9902=>array(41,169,797,560),9903=>array(5,194,833,536),9904=>array(103,237,757,540),9905=>array(211,42,626,698),9906=>array(85,-125,647,731),9907=>array(168,-125,646,731),9908=>array(86,-125,646,731),9909=>array(86,-125,646,731),9910=>array(59,-118,791,643),9911=>array(194,-104,595,710),9912=>array(158,-125,543,731),9920=>array(42,4,796,553),9921=>array(42,4,796,724),9922=>array(42,4,796,553),9923=>array(42,4,796,724),9954=>array(85,-14,647,843),9985=>array(11,190,803,635),9986=>array(42,141,784,588),9987=>array(11,94,803,539),9988=>array(36,119,824,613),9990=>array(42,-14,796,742),9991=>array(42,-14,796,742),9992=>array(59,21,782,708),9993=>array(64,107,773,622),9996=>array(212,0,561,742),9997=>array(21,83,802,678),9998=>array(89,75,724,710),9999=>array(26,198,819,530),10000=>array(89,75,724,710),10001=>array(43,185,757,544),10002=>array(67,209,757,520),10003=>array(150,97,667,630),10004=>array(116,87,721,631),10005=>array(126,72,711,657),10006=>array(85,31,752,698),10007=>array(118,-9,701,732),10008=>array(123,0,754,739),10009=>array(55,0,783,729),10010=>array(55,0,783,729),10011=>array(55,0,783,729),10012=>array(55,0,783,729),10013=>array(165,0,673,729),10014=>array(131,0,678,729),10015=>array(155,0,683,729),10016=>array(55,0,783,729),10017=>array(91,-13,747,744),10018=>array(41,-14,797,742),10019=>array(42,-12,796,742),10020=>array(41,-14,797,742),10021=>array(41,-13,797,743),10022=>array(42,-14,796,745),10023=>array(42,-14,796,745),10025=>array(23,-9,814,743),10026=>array(42,-14,796,742),10027=>array(23,-9,814,743),10028=>array(23,-9,814,743),10029=>array(23,-9,814,743),10030=>array(23,-9,814,743),10031=>array(23,-9,814,743),10032=>array(24,12,815,714),10033=>array(64,0,773,729),10034=>array(74,0,764,729),10035=>array(55,0,783,729),10036=>array(31,-14,787,742),10037=>array(41,-14,797,742),10038=>array(91,-14,747,742),10039=>array(41,-14,797,742),10040=>array(41,-14,797,742),10041=>array(41,-14,797,742),10042=>array(55,0,783,729),10043=>array(82,-14,756,742),10044=>array(82,-14,756,742),10045=>array(84,-14,753,742),10046=>array(79,-14,759,742),10047=>array(54,0,784,709),10048=>array(54,0,784,709),10049=>array(41,-14,797,742),10050=>array(42,-14,796,742),10051=>array(79,-14,759,742),10052=>array(89,0,749,729),10053=>array(76,0,762,729),10054=>array(63,2,773,729),10055=>array(79,-13,759,742),10056=>array(47,-13,791,730),10057=>array(47,-13,791,730),10058=>array(41,-13,797,743),10059=>array(41,-13,797,743),10061=>array(50,-10,847,738),10063=>array(60,-49,837,729),10064=>array(60,0,837,777),10065=>array(60,-49,837,729),10066=>array(60,0,837,777),10070=>array(83,-2,813,728),10072=>array(377,-240,460,760),10073=>array(336,-240,502,760),10074=>array(253,-240,585,760),10075=>array(85,395,264,729),10076=>array(59,395,237,729),10077=>array(85,395,479,729),10078=>array(59,395,453,729),10081=>array(155,-93,772,851),10082=>array(202,-17,636,742),10083=>array(163,-17,675,742),10084=>array(54,83,784,645),10085=>array(168,-1,729,729),10086=>array(62,21,724,702),10087=>array(78,169,759,564),10088=>array(196,-139,648,769),10089=>array(196,-139,648,769),10090=>array(264,-132,574,758),10091=>array(264,-132,574,758),10092=>array(215,-240,607,760),10093=>array(232,-240,623,760),10094=>array(142,-240,685,760),10095=>array(153,-240,696,760),10096=>array(167,-240,656,760),10097=>array(183,-240,672,760),10098=>array(346,-241,535,760),10099=>array(303,-241,492,760),10100=>array(175,-163,634,760),10101=>array(204,-163,663,760),10102=>array(59,-15,788,715),10103=>array(59,-15,788,715),10104=>array(59,-15,788,715),10105=>array(59,-15,788,715),10106=>array(59,-15,788,715),10107=>array(59,-15,788,715),10108=>array(59,-15,788,715),10109=>array(59,-15,788,715),10110=>array(59,-15,788,715),10111=>array(59,-15,788,715),10112=>array(4,-52,833,780),10113=>array(4,-52,833,780),10114=>array(4,-52,833,780),10115=>array(4,-52,833,780),10116=>array(4,-52,833,780),10117=>array(4,-52,833,780),10118=>array(4,-52,833,780),10119=>array(4,-52,833,780),10120=>array(4,-52,833,780),10121=>array(4,-52,833,780),10122=>array(4,-52,833,780),10123=>array(4,-52,833,780),10124=>array(4,-52,833,780),10125=>array(4,-52,833,780),10126=>array(4,-52,833,780),10127=>array(4,-52,833,780),10128=>array(4,-52,833,780),10129=>array(4,-52,833,780),10130=>array(4,-52,833,780),10131=>array(4,-52,833,780),10132=>array(57,75,789,552),10136=>array(123,55,682,614),10137=>array(57,100,789,527),10138=>array(123,13,682,572),10139=>array(57,129,789,498),10140=>array(57,57,764,570),10141=>array(57,100,789,527),10142=>array(57,100,789,527),10143=>array(57,100,789,527),10144=>array(57,100,789,527),10145=>array(57,46,811,581),10146=>array(111,94,789,533),10147=>array(111,94,789,533),10148=>array(111,-4,789,631),10149=>array(57,100,789,548),10150=>array(57,79,789,527),10151=>array(240,-7,606,634),10152=>array(57,100,789,527),10153=>array(57,75,765,552),10154=>array(57,75,765,552),10155=>array(21,12,794,586),10156=>array(21,12,794,586),10157=>array(135,0,774,574),10158=>array(135,0,774,574),10159=>array(62,49,799,574),10161=>array(62,49,799,574),10162=>array(154,-20,721,585),10163=>array(63,157,789,470),10164=>array(81,55,682,655),10165=>array(57,173,789,454),10166=>array(82,-29,682,572),10167=>array(82,55,682,655),10168=>array(57,172,789,455),10169=>array(82,-28,682,572),10170=>array(56,84,789,543),10171=>array(73,140,779,487),10172=>array(79,167,774,460),10173=>array(79,118,774,509),10174=>array(57,81,789,546),10181=>array(0,-163,438,769),10182=>array(-39,-163,474,769),10208=>array(3,-233,491,807),10214=>array(7,-132,498,760),10215=>array(7,-132,498,760),10216=>array(104,-132,464,759),10217=>array(-7,-132,353,759),10218=>array(104,-132,728,759),10219=>array(-7,-132,616,759),10224=>array(41,0,797,732),10225=>array(42,-3,798,729),10226=>array(9,45,816,685),10227=>array(22,45,830,685),10228=>array(57,-14,1108,643),10229=>array(49,87,1376,540),10230=>array(57,87,1385,540),10231=>array(49,87,1385,540),10232=>array(49,87,1376,540),10233=>array(57,87,1385,540),10234=>array(49,87,1385,540),10235=>array(49,87,1376,540),10236=>array(57,87,1385,540),10237=>array(49,87,1376,540),10238=>array(57,87,1385,540),10239=>array(57,87,1385,540),10241=>array(146,586,342,781),10242=>array(146,325,342,521),10243=>array(146,325,342,781),10244=>array(146,65,342,261),10245=>array(146,65,342,781),10246=>array(146,65,342,521),10247=>array(146,65,342,781),10248=>array(439,586,635,781),10249=>array(146,586,635,781),10250=>array(146,325,635,781),10251=>array(146,325,635,781),10252=>array(146,65,635,781),10253=>array(146,65,635,781),10254=>array(146,65,635,781),10255=>array(146,65,635,781),10256=>array(439,325,635,521),10257=>array(146,325,635,781),10258=>array(146,325,635,521),10259=>array(146,325,635,781),10260=>array(146,65,635,521),10261=>array(146,65,635,781),10262=>array(146,65,635,521),10263=>array(146,65,635,781),10264=>array(439,325,635,781),10265=>array(146,325,635,781),10266=>array(146,325,635,781),10267=>array(146,325,635,781),10268=>array(146,65,635,781),10269=>array(146,65,635,781),10270=>array(146,65,635,781),10271=>array(146,65,635,781),10272=>array(439,65,635,261),10273=>array(146,65,635,781),10274=>array(146,65,635,521),10275=>array(146,65,635,781),10276=>array(146,65,635,261),10277=>array(146,65,635,781),10278=>array(146,65,635,521),10279=>array(146,65,635,781),10280=>array(439,65,635,781),10281=>array(146,65,635,781),10282=>array(146,65,635,781),10283=>array(146,65,635,781),10284=>array(146,65,635,781),10285=>array(146,65,635,781),10286=>array(146,65,635,781),10287=>array(146,65,635,781),10288=>array(439,65,635,521),10289=>array(146,65,635,781),10290=>array(146,65,635,521),10291=>array(146,65,635,781),10292=>array(146,65,635,521),10293=>array(146,65,635,781),10294=>array(146,65,635,521),10295=>array(146,65,635,781),10296=>array(439,65,635,781),10297=>array(146,65,635,781),10298=>array(146,65,635,781),10299=>array(146,65,635,781),10300=>array(146,65,635,781),10301=>array(146,65,635,781),10302=>array(146,65,635,781),10303=>array(146,65,635,781),10304=>array(146,-195,342,0),10305=>array(146,-195,342,781),10306=>array(146,-195,342,521),10307=>array(146,-195,342,781),10308=>array(146,-195,342,261),10309=>array(146,-195,342,781),10310=>array(146,-195,342,521),10311=>array(146,-195,342,781),10312=>array(146,-195,635,781),10313=>array(146,-195,635,781),10314=>array(146,-195,635,781),10315=>array(146,-195,635,781),10316=>array(146,-195,635,781),10317=>array(146,-195,635,781),10318=>array(146,-195,635,781),10319=>array(146,-195,635,781),10320=>array(146,-195,635,521),10321=>array(146,-195,635,781),10322=>array(146,-195,635,521),10323=>array(146,-195,635,781),10324=>array(146,-195,635,521),10325=>array(146,-195,635,781),10326=>array(146,-195,635,521),10327=>array(146,-195,635,781),10328=>array(146,-195,635,781),10329=>array(146,-195,635,781),10330=>array(146,-195,635,781),10331=>array(146,-195,635,781),10332=>array(146,-195,635,781),10333=>array(146,-195,635,781),10334=>array(146,-195,635,781),10335=>array(146,-195,635,781),10336=>array(146,-195,635,261),10337=>array(146,-195,635,781),10338=>array(146,-195,635,521),10339=>array(146,-195,635,781),10340=>array(146,-195,635,261),10341=>array(146,-195,635,781),10342=>array(146,-195,635,521),10343=>array(146,-195,635,781),10344=>array(146,-195,635,781),10345=>array(146,-195,635,781),10346=>array(146,-195,635,781),10347=>array(146,-195,635,781),10348=>array(146,-195,635,781),10349=>array(146,-195,635,781),10350=>array(146,-195,635,781),10351=>array(146,-195,635,781),10352=>array(146,-195,635,521),10353=>array(146,-195,635,781),10354=>array(146,-195,635,521),10355=>array(146,-195,635,781),10356=>array(146,-195,635,521),10357=>array(146,-195,635,781),10358=>array(146,-195,635,521),10359=>array(146,-195,635,781),10360=>array(146,-195,635,781),10361=>array(146,-195,635,781),10362=>array(146,-195,635,781),10363=>array(146,-195,635,781),10364=>array(146,-195,635,781),10365=>array(146,-195,635,781),10366=>array(146,-195,635,781),10367=>array(146,-195,635,781),10368=>array(439,-195,635,0),10369=>array(146,-195,635,781),10370=>array(146,-195,635,521),10371=>array(146,-195,635,781),10372=>array(146,-195,635,261),10373=>array(146,-195,635,781),10374=>array(146,-195,635,521),10375=>array(146,-195,635,781),10376=>array(439,-195,635,781),10377=>array(146,-195,635,781),10378=>array(146,-195,635,781),10379=>array(146,-195,635,781),10380=>array(146,-195,635,781),10381=>array(146,-195,635,781),10382=>array(146,-195,635,781),10383=>array(146,-195,635,781),10384=>array(439,-195,635,521),10385=>array(146,-195,635,781),10386=>array(146,-195,635,521),10387=>array(146,-195,635,781),10388=>array(146,-195,635,521),10389=>array(146,-195,635,781),10390=>array(146,-195,635,521),10391=>array(146,-195,635,781),10392=>array(439,-195,635,781),10393=>array(146,-195,635,781),10394=>array(146,-195,635,781),10395=>array(146,-195,635,781),10396=>array(146,-195,635,781),10397=>array(146,-195,635,781),10398=>array(146,-195,635,781),10399=>array(146,-195,635,781),10400=>array(439,-195,635,261),10401=>array(146,-195,635,781),10402=>array(146,-195,635,521),10403=>array(146,-195,635,781),10404=>array(146,-195,635,261),10405=>array(146,-195,635,781),10406=>array(146,-195,635,521),10407=>array(146,-195,635,781),10408=>array(439,-195,635,781),10409=>array(146,-195,635,781),10410=>array(146,-195,635,781),10411=>array(146,-195,635,781),10412=>array(146,-195,635,781),10413=>array(146,-195,635,781),10414=>array(146,-195,635,781),10415=>array(146,-195,635,781),10416=>array(439,-195,635,521),10417=>array(146,-195,635,781),10418=>array(146,-195,635,521),10419=>array(146,-195,635,781),10420=>array(146,-195,635,521),10421=>array(146,-195,635,781),10422=>array(146,-195,635,521),10423=>array(146,-195,635,781),10424=>array(439,-195,635,781),10425=>array(146,-195,635,781),10426=>array(146,-195,635,781),10427=>array(146,-195,635,781),10428=>array(146,-195,635,781),10429=>array(146,-195,635,781),10430=>array(146,-195,635,781),10431=>array(146,-195,635,781),10432=>array(146,-195,635,0),10433=>array(146,-195,635,781),10434=>array(146,-195,635,521),10435=>array(146,-195,635,781),10436=>array(146,-195,635,261),10437=>array(146,-195,635,781),10438=>array(146,-195,635,521),10439=>array(146,-195,635,781),10440=>array(146,-195,635,781),10441=>array(146,-195,635,781),10442=>array(146,-195,635,781),10443=>array(146,-195,635,781),10444=>array(146,-195,635,781),10445=>array(146,-195,635,781),10446=>array(146,-195,635,781),10447=>array(146,-195,635,781),10448=>array(146,-195,635,521),10449=>array(146,-195,635,781),10450=>array(146,-195,635,521),10451=>array(146,-195,635,781),10452=>array(146,-195,635,521),10453=>array(146,-195,635,781),10454=>array(146,-195,635,521),10455=>array(146,-195,635,781),10456=>array(146,-195,635,781),10457=>array(146,-195,635,781),10458=>array(146,-195,635,781),10459=>array(146,-195,635,781),10460=>array(146,-195,635,781),10461=>array(146,-195,635,781),10462=>array(146,-195,635,781),10463=>array(146,-195,635,781),10464=>array(146,-195,635,261),10465=>array(146,-195,635,781),10466=>array(146,-195,635,521),10467=>array(146,-195,635,781),10468=>array(146,-195,635,261),10469=>array(146,-195,635,781),10470=>array(146,-195,635,521),10471=>array(146,-195,635,781),10472=>array(146,-195,635,781),10473=>array(146,-195,635,781),10474=>array(146,-195,635,781),10475=>array(146,-195,635,781),10476=>array(146,-195,635,781),10477=>array(146,-195,635,781),10478=>array(146,-195,635,781),10479=>array(146,-195,635,781),10480=>array(146,-195,635,521),10481=>array(146,-195,635,781),10482=>array(146,-195,635,521),10483=>array(146,-195,635,781),10484=>array(146,-195,635,521),10485=>array(146,-195,635,781),10486=>array(146,-195,635,521),10487=>array(146,-195,635,781),10488=>array(146,-195,635,781),10489=>array(146,-195,635,781),10490=>array(146,-195,635,781),10491=>array(146,-195,635,781),10492=>array(146,-195,635,781),10493=>array(146,-195,635,781),10494=>array(146,-195,635,781),10495=>array(146,-195,635,781),10502=>array(49,87,781,540),10503=>array(57,87,789,540),10506=>array(132,0,707,732),10507=>array(132,0,707,732),10560=>array(86,45,726,853),10561=>array(86,45,726,853),10627=>array(117,-163,718,760),10628=>array(35,-163,636,760),10702=>array(106,-258,732,800),10703=>array(106,-1,940,628),10704=>array(106,-1,940,628),10705=>array(106,-48,894,674),10706=>array(106,-48,894,674),10707=>array(106,-48,894,674),10708=>array(106,-48,894,675),10709=>array(106,-48,894,675),10731=>array(3,-233,491,807),10746=>array(106,0,732,627),10747=>array(106,0,732,627),10752=>array(28,-211,972,734),10753=>array(28,-211,972,734),10754=>array(28,-211,972,734),10764=>array(15,-227,1646,754),10765=>array(14,-227,548,754),10766=>array(14,-227,548,754),10767=>array(14,-227,548,754),10768=>array(14,-227,548,754),10769=>array(14,-227,576,754),10770=>array(14,-227,548,754),10771=>array(14,-227,548,754),10772=>array(14,-228,651,754),10773=>array(14,-227,548,754),10774=>array(14,-227,548,754),10775=>array(-30,-227,556,754),10776=>array(14,-227,548,754),10777=>array(14,-227,548,754),10778=>array(14,-227,548,754),10779=>array(15,-227,548,898),10780=>array(15,-372,548,754),10799=>array(125,20,713,607),10858=>array(106,212,732,660),10859=>array(106,-34,732,660),10877=>array(106,-150,732,632),10878=>array(106,-150,732,632),10879=>array(106,-150,732,632),10880=>array(106,-150,732,632),10881=>array(106,-150,732,688),10882=>array(106,-150,732,688),10883=>array(106,-150,732,827),10884=>array(106,-150,732,827),10885=>array(106,-217,732,630),10886=>array(106,-217,732,630),10887=>array(106,-124,732,582),10888=>array(106,-124,732,582),10889=>array(106,-281,732,630),10890=>array(106,-281,732,630),10891=>array(106,-303,732,814),10892=>array(106,-303,732,814),10893=>array(106,-183,732,653),10894=>array(106,-183,732,653),10895=>array(106,-245,732,765),10896=>array(106,-245,732,765),10897=>array(106,-278,732,782),10898=>array(106,-278,732,782),10899=>array(106,-263,732,771),10900=>array(106,-263,732,771),10901=>array(106,-50,732,733),10902=>array(106,-50,732,733),10903=>array(106,-50,732,733),10904=>array(106,-50,732,733),10905=>array(106,-45,732,678),10906=>array(106,-45,732,678),10907=>array(106,-81,732,724),10908=>array(106,-81,732,724),10909=>array(106,13,732,680),10910=>array(106,13,732,680),10911=>array(106,-239,732,746),10912=>array(106,-239,732,746),10926=>array(106,22,732,656),10927=>array(106,-83,732,684),10928=>array(106,-83,732,684),10929=>array(106,-246,732,684),10930=>array(106,-246,732,684),10931=>array(106,-205,732,672),10932=>array(106,-205,732,672),10933=>array(106,-304,732,672),10934=>array(106,-304,732,672),10935=>array(106,-252,732,713),10936=>array(106,-252,732,713),10937=>array(106,-316,732,713),10938=>array(106,-316,732,713),11001=>array(106,-195,732,609),11002=>array(106,-195,732,609),11008=>array(123,-23,744,598),11009=>array(94,-23,715,598),11010=>array(123,-23,744,598),11011=>array(94,-23,715,598),11012=>array(27,46,789,581),11013=>array(27,46,781,581),11014=>array(151,0,687,754),11015=>array(151,-25,687,729),11016=>array(123,-23,744,598),11017=>array(94,-23,715,598),11018=>array(123,-23,744,598),11019=>array(94,-23,715,598),11020=>array(27,46,789,581),11021=>array(151,-25,687,754),11022=>array(57,-25,800,372),11023=>array(57,255,800,652),11024=>array(38,-25,781,372),11025=>array(38,255,781,652),11026=>array(91,-124,854,643),11027=>array(91,-124,854,643),11028=>array(91,-124,854,643),11029=>array(91,-124,854,643),11030=>array(3,-124,766,643),11031=>array(3,-124,766,643),11032=>array(3,-124,766,643),11033=>array(3,-124,766,643),11034=>array(91,-124,854,643),11039=>array(18,-26,852,767),11040=>array(18,-26,852,767),11041=>array(73,-91,800,748),11042=>array(73,-91,800,748),11043=>array(17,-35,856,692),11044=>array(55,-250,1064,770),11091=>array(38,-47,832,788),11092=>array(38,-47,832,788),11360=>array(-24,0,566,729),11361=>array(-35,0,390,760),11362=>array(-28,0,566,729),11363=>array(18,0,716,729),11364=>array(54,-200,708,729),11365=>array(-21,-46,692,594),11366=>array(-6,-93,531,822),11367=>array(36,-157,904,729),11368=>array(23,-138,770,760),11369=>array(36,-157,855,729),11370=>array(23,-138,709,760),11371=>array(-11,-157,755,729),11372=>array(5,-138,606,547),11373=>array(48,-14,840,741),11374=>array(41,-200,993,729),11375=>array(76,0,840,729),11376=>array(-23,-14,780,741),11377=>array(67,0,797,560),11378=>array(99,0,1263,742),11379=>array(87,0,1075,560),11380=>array(44,0,687,586),11381=>array(21,0,623,729),11382=>array(31,0,494,547),11383=>array(64,0,724,552),11385=>array(10,-13,529,760),11386=>array(43,-14,644,560),11387=>array(25,0,520,547),11388=>array(-75,-121,219,425),11389=>array(42,326,524,734),11390=>array(37,-240,688,742),11391=>array(-2,-240,763,729),11520=>array(41,-64,638,547),11521=>array(-12,-232,663,546),11522=>array(28,-232,635,547),11523=>array(42,-10,646,807),11524=>array(29,-228,642,546),11525=>array(21,-228,1017,546),11526=>array(74,-8,697,816),11527=>array(31,-9,1003,547),11528=>array(42,0,617,547),11529=>array(29,-227,643,816),11530=>array(20,-9,1014,546),11531=>array(35,-8,687,816),11532=>array(20,0,656,816),11533=>array(30,-8,1025,546),11534=>array(29,-8,667,546),11535=>array(55,-228,875,816),11536=>array(30,-9,1005,816),11537=>array(29,-9,668,816),11538=>array(26,-232,632,546),11539=>array(29,-228,1024,661),11540=>array(40,-228,980,546),11541=>array(26,-228,1009,816),11542=>array(24,0,657,546),11543=>array(29,-228,668,547),11544=>array(29,-232,665,546),11545=>array(27,-228,657,816),11546=>array(26,-232,632,547),11547=>array(41,-9,695,816),11548=>array(24,-228,1018,547),11549=>array(23,-232,641,546),11550=>array(31,-232,677,546),11551=>array(16,-228,653,567),11552=>array(24,-9,1042,546),11553=>array(31,-228,648,816),11554=>array(38,-9,625,626),11555=>array(40,-228,659,816),11556=>array(30,-228,721,546),11557=>array(40,-8,982,816),11800=>array(37,-13,494,729),11807=>array(106,-34,732,415),11810=>array(77,314,466,760),11811=>array(124,314,448,760),11812=>array(-10,-132,314,314),11813=>array(-28,-132,362,314),11822=>array(104,0,580,742),19904=>array(83,-158,813,729),19905=>array(83,-158,813,729),19906=>array(83,-158,813,729),19907=>array(83,-158,813,729),19908=>array(83,-158,813,729),19909=>array(83,-158,813,729),19910=>array(83,-158,813,729),19911=>array(83,-158,813,729),19912=>array(83,-158,813,729),19913=>array(83,-158,814,729),19914=>array(83,-158,813,729),19915=>array(83,-158,813,729),19916=>array(83,-158,813,729),19917=>array(83,-158,813,729),19918=>array(83,-158,813,729),19919=>array(83,-158,813,729),19920=>array(83,-158,814,729),19921=>array(83,-158,813,729),19922=>array(83,-158,814,729),19923=>array(83,-158,813,729),19924=>array(83,-158,813,729),19925=>array(83,-158,813,729),19926=>array(83,-158,813,729),19927=>array(83,-158,813,729),19928=>array(83,-158,813,729),19929=>array(83,-158,813,729),19930=>array(83,-158,813,729),19931=>array(83,-158,814,729),19932=>array(83,-158,813,729),19933=>array(83,-158,813,729),19934=>array(83,-158,814,729),19935=>array(83,-158,813,729),19936=>array(83,-158,813,729),19937=>array(83,-158,813,729),19938=>array(83,-158,813,729),19939=>array(83,-158,813,729),19940=>array(83,-158,813,729),19941=>array(83,-158,814,729),19942=>array(83,-158,813,729),19943=>array(83,-158,813,729),19944=>array(83,-158,814,729),19945=>array(83,-158,813,729),19946=>array(83,-158,814,729),19947=>array(83,-158,813,729),19948=>array(83,-158,814,729),19949=>array(83,-158,813,729),19950=>array(83,-158,814,729),19951=>array(83,-158,813,729),19952=>array(83,-158,814,729),19953=>array(83,-158,813,729),19954=>array(83,-158,813,729),19955=>array(83,-158,813,729),19956=>array(83,-158,813,729),19957=>array(83,-158,814,729),19958=>array(83,-158,813,729),19959=>array(83,-158,813,729),19960=>array(83,-158,813,729),19961=>array(83,-158,814,729),19962=>array(83,-158,813,729),19963=>array(83,-158,814,729),19964=>array(83,-158,814,729),19965=>array(83,-158,813,729),19966=>array(83,-158,813,729),19967=>array(83,-158,813,729),42192=>array(21,0,699,729),42193=>array(21,0,719,729),42194=>array(17,0,712,729),42195=>array(21,0,786,729),42196=>array(48,0,748,729),42197=>array(-65,0,634,729),42198=>array(36,-14,778,742),42199=>array(21,0,837,729),42200=>array(-65,0,754,729),42201=>array(7,-14,581,729),42202=>array(36,-14,724,742),42203=>array(-13,-14,675,742),42204=>array(-26,0,740,729),42205=>array(21,0,670,729),42206=>array(21,0,670,729),42207=>array(21,0,974,729),42208=>array(21,0,816,729),42209=>array(21,0,566,729),42210=>array(15,-14,665,742),42211=>array(21,0,685,729),42212=>array(81,0,749,729),42213=>array(-66,0,698,729),42214=>array(76,0,840,729),42215=>array(21,0,816,729),42216=>array(5,-14,747,742),42217=>array(19,0,592,743),42218=>array(107,0,1143,729),42219=>array(-51,0,812,729),42220=>array(63,0,809,729),42221=>array(67,0,741,729),42222=>array(-65,0,691,729),42223=>array(76,0,840,729),42224=>array(21,0,670,729),42225=>array(13,0,662,729),42226=>array(21,0,351,729),42227=>array(36,-14,814,742),42228=>array(68,-14,791,729),42229=>array(20,0,733,743),42230=>array(9,0,554,729),42231=>array(48,0,809,729),42232=>array(17,0,230,189),42233=>array(-63,-142,227,189),42234=>array(17,0,582,189),42235=>array(17,-142,579,189),42236=>array(-74,-142,284,547),42237=>array(2,0,284,547),42238=>array(88,0,554,405),42239=>array(39,134,549,492),42564=>array(-1,-14,631,742),42565=>array(-7,-14,534,560),42566=>array(74,0,384,729),42567=>array(74,-1,326,547),42572=>array(37,-14,1348,654),42573=>array(31,-13,1129,547),42576=>array(92,0,1213,729),42577=>array(52,0,1000,547),42580=>array(45,-14,1153,742),42581=>array(37,-14,941,560),42582=>array(21,0,1017,729),42583=>array(31,-14,905,560),42594=>array(-26,-157,1144,729),42595=>array(-10,-138,967,547),42596=>array(-25,0,1140,729),42597=>array(2,0,941,547),42598=>array(21,0,1304,729),42599=>array(28,0,1023,547),42600=>array(36,-14,814,742),42601=>array(36,-14,651,560),42602=>array(50,-14,987,742),42603=>array(43,-14,825,560),42604=>array(50,-14,1356,742),42605=>array(43,-14,1063,560),42606=>array(28,-208,933,743),42634=>array(48,-200,863,729),42635=>array(34,-216,672,547),42636=>array(48,0,748,729),42637=>array(34,0,626,547),42644=>array(106,0,793,729),42645=>array(10,0,625,760),42760=>array(146,0,471,693),42761=>array(117,0,471,693),42762=>array(87,0,471,693),42763=>array(58,0,471,693),42764=>array(29,0,471,693),42765=>array(29,0,471,693),42766=>array(29,0,442,693),42767=>array(29,0,413,693),42768=>array(29,0,383,693),42769=>array(29,0,354,693),42770=>array(29,0,471,693),42771=>array(29,0,442,693),42772=>array(29,0,413,693),42773=>array(29,0,383,693),42774=>array(29,0,354,693),42779=>array(180,326,464,736),42780=>array(142,324,426,734),42781=>array(152,326,342,734),42782=>array(152,326,342,734),42783=>array(88,0,278,408),42786=>array(30,0,432,729),42787=>array(38,0,369,547),42788=>array(55,224,530,742),42789=>array(55,42,530,560),42790=>array(41,-200,835,729),42791=>array(31,-216,646,760),42792=>array(69,-216,984,729),42793=>array(48,-215,810,702),42794=>array(37,-14,652,742),42795=>array(-2,-202,517,560),42800=>array(39,0,526,547),42801=>array(10,-14,560,560),42802=>array(-66,0,1273,729),42803=>array(22,-14,981,560),42804=>array(-65,-14,1249,742),42805=>array(17,-14,1029,560),42806=>array(-65,-14,1224,729),42807=>array(17,-14,1021,560),42808=>array(-66,0,1145,729),42809=>array(22,-14,960,560),42810=>array(-66,0,1145,729),42811=>array(22,-14,960,560),42812=>array(-45,-216,1122,729),42813=>array(42,-216,979,560),42814=>array(-13,-14,670,742),42815=>array(-7,-14,537,560),42816=>array(21,0,837,729),42817=>array(31,0,716,760),42822=>array(81,0,779,729),42823=>array(68,0,472,760),42824=>array(65,0,612,729),42825=>array(81,0,520,760),42826=>array(4,-14,915,742),42827=>array(-4,-14,821,560),42830=>array(50,-14,1356,742),42831=>array(43,-14,1063,560),42832=>array(-42,0,723,729),42833=>array(-81,-208,679,560),42834=>array(-1,0,938,729),42835=>array(0,-208,900,560),42838=>array(40,-188,811,742),42839=>array(34,-208,682,559),42852=>array(21,0,698,729),42853=>array(-11,-208,678,760),42854=>array(-50,0,698,729),42855=>array(-82,-208,678,760),42880=>array(71,0,616,729),42881=>array(11,-208,332,547),42882=>array(-8,-208,776,742),42883=>array(-10,-208,654,560),42889=>array(41,0,323,547),42890=>array(63,141,333,405),42891=>array(142,245,387,729),42892=>array(69,458,237,729),42893=>array(100,0,787,729),42894=>array(93,-216,613,760),42896=>array(21,-157,824,729),42897=>array(31,-138,695,560),42912=>array(-17,-14,837,742),42913=>array(-19,-216,735,559),42914=>array(-16,0,837,729),42915=>array(-18,0,716,760),42916=>array(-17,0,854,729),42917=>array(-19,0,731,560),42918=>array(-15,0,785,729),42919=>array(-15,0,545,560),42920=>array(-14,-14,734,742),42921=>array(-17,-14,612,560),42922=>array(-37,0,865,729),43002=>array(31,0,1025,547),43003=>array(92,0,662,729),43004=>array(65,0,712,729),43005=>array(21,0,974,729),43006=>array(1,0,370,928),43007=>array(-40,0,1365,729),61184=>array(141,602,384,693),61185=>array(83,451,406,693),61186=>array(29,301,430,693),61187=>array(-12,150,440,693),61188=>array(-47,0,446,693),61189=>array(100,451,376,693),61190=>array(112,451,355,543),61191=>array(54,301,376,543),61192=>array(0,150,401,543),61193=>array(-41,0,411,543),61194=>array(82,301,372,693),61195=>array(71,301,347,543),61196=>array(83,301,326,393),61197=>array(25,150,347,393),61198=>array(-29,0,372,393),61199=>array(75,150,353,693),61200=>array(53,149,342,542),61201=>array(42,150,318,393),61202=>array(53,150,296,242),61203=>array(-4,0,318,242),61204=>array(73,0,329,693),61205=>array(46,0,323,543),61206=>array(23,0,313,393),61207=>array(12,0,289,242),61208=>array(24,0,268,92),61209=>array(29,0,255,693),62464=>array(84,-14,614,819),62465=>array(90,-15,610,823),62466=>array(86,-14,652,828),62467=>array(124,0,954,828),62468=>array(80,-15,679,828),62469=>array(81,-15,657,828),62470=>array(129,-15,677,828),62471=>array(92,-14,949,828),62472=>array(98,0,644,828),62473=>array(80,-14,684,820),62474=>array(139,-6,1218,828),62475=>array(81,-14,674,828),62476=>array(88,-15,675,820),62477=>array(107,0,938,828),62478=>array(78,-15,654,819),62479=>array(87,-15,722,840),62480=>array(99,0,938,828),62481=>array(99,-14,618,819),62482=>array(97,-14,785,828),62483=>array(80,-14,680,828),62484=>array(136,-14,947,828),62485=>array(79,-14,717,819),62486=>array(113,0,963,828),62487=>array(74,-14,717,820),62488=>array(72,-14,672,828),62489=>array(40,0,626,828),62490=>array(100,-15,715,820),62491=>array(86,-14,717,819),62492=>array(90,-14,729,828),62493=>array(79,-14,719,820),62494=>array(94,-14,619,819),62495=>array(29,-14,623,828),62496=>array(81,-15,658,828),62497=>array(88,-15,677,828),62498=>array(14,-73,658,828),62499=>array(77,-15,719,830),62500=>array(78,-15,726,828),62501=>array(76,-14,732,828),62502=>array(126,-14,1016,828),62504=>array(40,-228,982,816),62505=>array(48,-223,821,843),62506=>array(81,-14,565,761),62507=>array(81,-14,567,773),62508=>array(81,-14,586,866),62509=>array(81,-14,623,812),62510=>array(81,-14,604,877),62511=>array(81,-14,577,803),62512=>array(31,-232,574,761),62513=>array(31,-232,631,793),62514=>array(31,-232,649,891),62515=>array(31,-232,601,803),62516=>array(80,0,589,761),62517=>array(80,0,637,793),62518=>array(80,0,601,803),62519=>array(97,-0,813,761),62520=>array(97,-0,813,773),62521=>array(97,-0,813,884),62522=>array(97,-0,813,793),62523=>array(97,-0,813,803),62524=>array(76,-232,621,761),62525=>array(76,-232,621,773),62526=>array(76,-232,630,894),62527=>array(76,-232,636,793),62528=>array(76,-232,621,803),62529=>array(76,-232,621,844),62917=>array(16,-14,648,760),64256=>array(50,0,916,760),64257=>array(50,0,798,760),64258=>array(50,0,798,760),64259=>array(50,0,1128,760),64260=>array(50,0,1129,760),64261=>array(45,0,836,760),64262=>array(8,-14,1047,742),64275=>array(47,-14,1334,760),64276=>array(47,-14,1335,760),64277=>array(65,-208,1311,760),64278=>array(65,-208,1353,760),64279=>array(65,-208,1682,760),64285=>array(98,38,334,547),64286=>array(194,635,524,780),64287=>array(98,36,655,547),64288=>array(38,0,697,547),64289=>array(120,0,926,547),64290=>array(126,0,838,547),64291=>array(100,0,840,547),64292=>array(43,0,791,547),64293=>array(126,0,837,739),64294=>array(91,0,842,547),64295=>array(126,0,794,547),64296=>array(48,-4,798,547),64297=>array(155,256,804,627),64298=>array(89,0,857,710),64299=>array(89,0,856,723),64300=>array(89,0,856,710),64301=>array(89,0,856,710),64302=>array(104,-171,730,547),64303=>array(104,-217,730,547),64304=>array(104,-171,730,547),64305=>array(43,0,590,547),64306=>array(44,-9,428,547),64307=>array(126,0,651,547),64308=>array(100,0,661,547),64309=>array(73,0,452,547),64310=>array(73,0,548,547),64312=>array(142,-13,676,553),64313=>array(101,164,476,547),64314=>array(126,-240,549,547),64315=>array(43,0,570,547),64316=>array(126,0,633,711),64318=>array(84,0,690,554),64320=>array(43,0,430,547),64321=>array(144,-13,678,547),64323=>array(158,-240,642,547),64324=>array(91,0,656,547),64326=>array(54,0,670,547),64327=>array(51,-240,767,546),64328=>array(126,0,575,547),64329=>array(89,0,856,547),64330=>array(11,-4,650,547),64331=>array(91,0,359,710),64332=>array(43,0,590,710),64333=>array(43,0,570,710),64334=>array(91,0,656,710),64335=>array(47,0,732,729),65056=>array(-276,735,171,880),65057=>array(157,735,564,880),65058=>array(-215,756,169,894),65059=>array(152,756,536,894),65533=>array(100,-139,1164,926),65535=>array(50,-177,550,705)); -$cw=array(0=>600,32=>348,33=>456,34=>521,35=>696,36=>696,37=>1002,38=>872,39=>306,40=>457,41=>457,42=>523,43=>838,44=>380,45=>415,46=>380,47=>365,48=>696,49=>696,50=>696,51=>696,52=>696,53=>696,54=>696,55=>696,56=>696,57=>696,58=>400,59=>400,60=>838,61=>838,62=>838,63=>580,64=>1000,65=>774,66=>762,67=>734,68=>830,69=>683,70=>683,71=>821,72=>837,73=>372,74=>372,75=>775,76=>637,77=>995,78=>837,79=>850,80=>733,81=>850,82=>770,83=>720,84=>682,85=>812,86=>774,87=>1103,88=>771,89=>724,90=>725,91=>457,92=>365,93=>457,94=>838,95=>500,96=>500,97=>675,98=>716,99=>593,100=>716,101=>678,102=>435,103=>716,104=>712,105=>343,106=>343,107=>665,108=>343,109=>1042,110=>712,111=>687,112=>716,113=>716,114=>493,115=>595,116=>478,117=>712,118=>652,119=>924,120=>645,121=>652,122=>582,123=>712,124=>365,125=>712,126=>838,160=>348,161=>456,162=>696,163=>696,164=>636,165=>696,166=>365,167=>500,168=>500,169=>1000,170=>564,171=>650,172=>838,173=>415,174=>1000,175=>500,176=>500,177=>838,178=>438,179=>438,180=>500,181=>736,182=>636,183=>380,184=>500,185=>438,186=>564,187=>650,188=>1035,189=>1035,190=>1035,191=>580,192=>774,193=>774,194=>774,195=>774,196=>774,197=>774,198=>1085,199=>734,200=>683,201=>683,202=>683,203=>683,204=>372,205=>372,206=>372,207=>372,208=>845,209=>837,210=>850,211=>850,212=>850,213=>850,214=>850,215=>838,216=>850,217=>812,218=>812,219=>812,220=>812,221=>724,222=>742,223=>719,224=>675,225=>675,226=>675,227=>675,228=>675,229=>675,230=>1048,231=>593,232=>678,233=>678,234=>678,235=>678,236=>343,237=>343,238=>343,239=>343,240=>687,241=>712,242=>687,243=>687,244=>687,245=>687,246=>687,247=>838,248=>687,249=>712,250=>712,251=>712,252=>712,253=>652,254=>716,255=>652,256=>774,257=>675,258=>774,259=>675,260=>774,261=>675,262=>734,263=>593,264=>734,265=>593,266=>734,267=>593,268=>734,269=>593,270=>830,271=>716,272=>845,273=>716,274=>683,275=>678,276=>683,277=>678,278=>683,279=>678,280=>683,281=>678,282=>683,283=>678,284=>821,285=>716,286=>821,287=>716,288=>821,289=>716,290=>821,291=>716,292=>837,293=>712,294=>974,295=>790,296=>372,297=>343,298=>372,299=>343,300=>372,301=>343,302=>372,303=>343,304=>372,305=>343,306=>744,307=>686,308=>372,309=>343,310=>775,311=>665,312=>665,313=>637,314=>343,315=>637,316=>343,317=>637,318=>343,319=>637,320=>343,321=>660,322=>375,323=>837,324=>712,325=>837,326=>712,327=>837,328=>712,329=>983,330=>837,331=>712,332=>850,333=>687,334=>850,335=>687,336=>850,337=>687,338=>1167,339=>1094,340=>770,341=>493,342=>770,343=>493,344=>770,345=>493,346=>720,347=>595,348=>720,349=>595,350=>720,351=>595,352=>720,353=>595,354=>682,355=>478,356=>682,357=>478,358=>682,359=>478,360=>812,361=>712,362=>812,363=>712,364=>812,365=>712,366=>812,367=>712,368=>812,369=>712,370=>812,371=>712,372=>1103,373=>924,374=>724,375=>652,376=>724,377=>725,378=>582,379=>725,380=>582,381=>725,382=>582,383=>435,384=>716,385=>811,386=>762,387=>716,388=>762,389=>716,390=>734,391=>734,392=>593,393=>845,394=>879,395=>762,396=>716,397=>687,398=>683,399=>850,400=>696,401=>683,402=>435,403=>821,404=>793,405=>1045,406=>436,407=>389,408=>775,409=>665,410=>360,411=>592,412=>1042,413=>837,414=>712,415=>850,416=>850,417=>687,418=>1114,419=>962,420=>782,421=>716,422=>770,423=>720,424=>595,425=>683,426=>552,427=>478,428=>707,429=>478,430=>682,431=>812,432=>712,433=>769,434=>813,435=>797,436=>778,437=>725,438=>582,439=>772,440=>772,441=>641,442=>582,443=>696,444=>772,445=>641,446=>573,447=>716,448=>372,449=>659,450=>544,451=>372,452=>1548,453=>1450,454=>1307,455=>977,456=>979,457=>670,458=>1193,459=>1213,460=>1063,461=>774,462=>675,463=>372,464=>343,465=>850,466=>687,467=>812,468=>712,469=>812,470=>712,471=>812,472=>712,473=>812,474=>712,475=>812,476=>712,477=>678,478=>774,479=>675,480=>774,481=>675,482=>1085,483=>1048,484=>821,485=>716,486=>821,487=>716,488=>775,489=>665,490=>850,491=>687,492=>850,493=>687,494=>772,495=>582,496=>343,497=>1548,498=>1450,499=>1307,500=>821,501=>716,502=>1289,503=>787,504=>837,505=>712,506=>774,507=>675,508=>1085,509=>1048,510=>850,511=>687,512=>774,513=>675,514=>774,515=>675,516=>683,517=>678,518=>683,519=>678,520=>372,521=>343,522=>372,523=>343,524=>850,525=>687,526=>850,527=>687,528=>770,529=>493,530=>770,531=>493,532=>812,533=>712,534=>812,535=>712,536=>720,537=>595,538=>682,539=>478,540=>690,541=>607,542=>837,543=>712,544=>837,545=>865,546=>809,547=>659,548=>725,549=>582,550=>774,551=>675,552=>683,553=>678,554=>850,555=>687,556=>850,557=>687,558=>850,559=>687,560=>850,561=>687,562=>724,563=>652,564=>492,565=>867,566=>512,567=>343,568=>1088,569=>1088,570=>774,571=>734,572=>593,573=>637,574=>682,575=>595,576=>582,577=>782,578=>614,579=>762,580=>812,581=>774,582=>683,583=>678,584=>372,585=>343,586=>860,587=>791,588=>770,589=>493,590=>724,591=>652,592=>675,593=>716,594=>716,595=>716,596=>593,597=>593,598=>791,599=>792,600=>678,601=>678,602=>876,603=>557,604=>545,605=>774,606=>731,607=>343,608=>792,609=>716,610=>627,611=>735,612=>635,613=>712,614=>712,615=>712,616=>545,617=>440,618=>545,619=>559,620=>693,621=>343,622=>841,623=>1042,624=>1042,625=>1042,626=>712,627=>793,628=>642,629=>687,630=>909,631=>682,632=>796,633=>538,634=>538,635=>650,636=>493,637=>493,638=>596,639=>596,640=>642,641=>642,642=>595,643=>415,644=>435,645=>605,646=>552,647=>478,648=>478,649=>920,650=>769,651=>670,652=>652,653=>924,654=>652,655=>724,656=>694,657=>684,658=>641,659=>641,660=>573,661=>573,662=>573,663=>573,664=>850,665=>633,666=>731,667=>685,668=>691,669=>343,670=>732,671=>539,672=>792,673=>573,674=>573,675=>1156,676=>1214,677=>1155,678=>975,679=>769,680=>929,681=>1026,682=>862,683=>780,684=>591,685=>415,686=>677,687=>789,688=>456,689=>456,690=>219,691=>315,692=>315,693=>315,694=>411,695=>591,696=>417,697=>302,698=>521,699=>380,700=>380,701=>380,702=>366,703=>366,704=>326,705=>326,706=>500,707=>500,708=>500,709=>500,710=>500,711=>500,712=>306,713=>500,714=>500,715=>500,716=>306,717=>500,718=>500,719=>500,720=>337,721=>337,722=>366,723=>366,724=>500,725=>500,726=>416,727=>328,728=>500,729=>500,730=>500,731=>500,732=>500,733=>500,734=>351,735=>500,736=>412,737=>219,738=>381,739=>413,740=>326,741=>500,742=>500,743=>500,744=>500,745=>500,748=>500,749=>500,750=>644,755=>500,759=>500,768=>0,769=>0,770=>0,771=>0,772=>0,773=>0,774=>0,775=>0,776=>0,777=>0,778=>0,779=>0,780=>0,781=>0,782=>0,783=>0,784=>0,785=>0,786=>0,787=>0,788=>0,789=>0,790=>0,791=>0,792=>0,793=>0,794=>0,795=>0,796=>0,797=>0,798=>0,799=>0,800=>0,801=>0,802=>0,803=>0,804=>0,805=>0,806=>0,807=>0,808=>0,809=>0,810=>0,811=>0,812=>0,813=>0,814=>0,815=>0,816=>0,817=>0,818=>0,819=>0,820=>0,821=>0,822=>0,823=>0,824=>0,825=>0,826=>0,827=>0,828=>0,829=>0,830=>0,831=>0,832=>0,833=>0,834=>0,835=>0,836=>0,837=>0,838=>0,839=>0,840=>0,841=>0,842=>0,843=>0,844=>0,845=>0,846=>0,847=>0,849=>0,850=>0,851=>0,855=>0,856=>0,858=>0,860=>0,861=>0,862=>0,863=>0,864=>0,865=>0,866=>0,880=>698,881=>565,882=>1022,883=>836,884=>302,885=>302,886=>837,887=>701,890=>500,891=>593,892=>550,893=>549,894=>400,900=>441,901=>500,902=>797,903=>380,904=>846,905=>1009,906=>563,908=>891,910=>980,911=>894,912=>390,913=>774,914=>762,915=>637,916=>774,917=>683,918=>725,919=>837,920=>850,921=>372,922=>775,923=>774,924=>995,925=>837,926=>632,927=>850,928=>837,929=>733,931=>683,932=>682,933=>724,934=>850,935=>771,936=>850,937=>850,938=>372,939=>724,940=>687,941=>557,942=>712,943=>390,944=>675,945=>687,946=>716,947=>681,948=>687,949=>557,950=>591,951=>712,952=>687,953=>390,954=>710,955=>633,956=>736,957=>681,958=>591,959=>687,960=>791,961=>716,962=>593,963=>779,964=>638,965=>675,966=>782,967=>645,968=>794,969=>869,970=>390,971=>675,972=>687,973=>675,974=>869,975=>775,976=>651,977=>661,978=>746,979=>981,980=>746,981=>796,982=>869,983=>744,984=>850,985=>687,986=>734,987=>593,988=>683,989=>494,990=>702,991=>660,992=>919,993=>627,994=>1093,995=>837,996=>832,997=>716,998=>928,999=>744,1000=>733,1001=>650,1002=>789,1003=>671,1004=>752,1005=>716,1006=>682,1007=>590,1008=>744,1009=>716,1010=>593,1011=>343,1012=>850,1013=>645,1014=>645,1015=>742,1016=>716,1017=>734,1018=>995,1019=>732,1020=>716,1021=>734,1022=>734,1023=>698,1024=>683,1025=>683,1026=>878,1027=>637,1028=>734,1029=>720,1030=>372,1031=>372,1032=>372,1033=>1154,1034=>1130,1035=>878,1036=>817,1037=>837,1038=>771,1039=>837,1040=>774,1041=>762,1042=>762,1043=>637,1044=>891,1045=>683,1046=>1224,1047=>710,1048=>837,1049=>837,1050=>817,1051=>831,1052=>995,1053=>837,1054=>850,1055=>837,1056=>733,1057=>734,1058=>682,1059=>771,1060=>992,1061=>771,1062=>928,1063=>808,1064=>1235,1065=>1326,1066=>939,1067=>1036,1068=>762,1069=>734,1070=>1174,1071=>770,1072=>675,1073=>698,1074=>633,1075=>522,1076=>808,1077=>678,1078=>995,1079=>581,1080=>701,1081=>701,1082=>679,1083=>732,1084=>817,1085=>691,1086=>687,1087=>691,1088=>716,1089=>593,1090=>580,1091=>652,1092=>992,1093=>645,1094=>741,1095=>687,1096=>1062,1097=>1105,1098=>751,1099=>904,1100=>632,1101=>593,1102=>972,1103=>642,1104=>678,1105=>678,1106=>714,1107=>522,1108=>593,1109=>595,1110=>343,1111=>343,1112=>343,1113=>991,1114=>956,1115=>734,1116=>679,1117=>701,1118=>652,1119=>691,1120=>1093,1121=>869,1122=>840,1123=>736,1124=>1012,1125=>839,1126=>992,1127=>832,1128=>1358,1129=>1121,1130=>850,1131=>687,1132=>1236,1133=>1007,1134=>696,1135=>557,1136=>1075,1137=>1061,1138=>850,1139=>687,1140=>850,1141=>695,1142=>850,1143=>695,1144=>1148,1145=>1043,1146=>1074,1147=>863,1148=>1405,1149=>1173,1150=>1093,1151=>869,1152=>734,1153=>593,1154=>652,1155=>0,1156=>0,1157=>0,1158=>0,1159=>0,1160=>418,1161=>418,1162=>938,1163=>806,1164=>762,1165=>611,1166=>736,1167=>718,1168=>637,1169=>522,1170=>666,1171=>543,1172=>789,1173=>522,1174=>1224,1175=>995,1176=>710,1177=>581,1178=>775,1179=>679,1180=>817,1181=>679,1182=>817,1183=>679,1184=>1015,1185=>826,1186=>837,1187=>691,1188=>1103,1189=>871,1190=>1254,1191=>979,1192=>946,1193=>859,1194=>734,1195=>593,1196=>682,1197=>580,1198=>724,1199=>652,1200=>724,1201=>652,1202=>771,1203=>645,1204=>1104,1205=>1001,1206=>808,1207=>687,1208=>808,1209=>687,1210=>808,1211=>712,1212=>1026,1213=>810,1214=>1026,1215=>810,1216=>372,1217=>1224,1218=>995,1219=>778,1220=>629,1221=>933,1222=>804,1223=>837,1224=>691,1225=>938,1226=>806,1227=>808,1228=>687,1229=>1096,1230=>932,1231=>343,1232=>774,1233=>675,1234=>774,1235=>675,1236=>1085,1237=>1048,1238=>683,1239=>678,1240=>850,1241=>678,1242=>850,1243=>678,1244=>1224,1245=>995,1246=>710,1247=>581,1248=>772,1249=>641,1250=>837,1251=>701,1252=>837,1253=>701,1254=>850,1255=>687,1256=>850,1257=>687,1258=>850,1259=>687,1260=>734,1261=>593,1262=>771,1263=>652,1264=>771,1265=>652,1266=>771,1267=>652,1268=>808,1269=>687,1270=>637,1271=>522,1272=>1036,1273=>904,1274=>666,1275=>543,1276=>771,1277=>645,1278=>771,1279=>645,1280=>762,1281=>608,1282=>1159,1283=>893,1284=>1119,1285=>920,1286=>828,1287=>693,1288=>1242,1289=>1017,1290=>1289,1291=>1013,1292=>839,1293=>638,1294=>938,1295=>803,1296=>696,1297=>557,1298=>831,1299=>732,1300=>1286,1301=>1070,1302=>1065,1303=>982,1304=>1082,1305=>960,1306=>850,1307=>716,1308=>1103,1309=>924,1310=>817,1311=>679,1312=>1248,1313=>1022,1314=>1254,1315=>979,1316=>957,1317=>807,1329=>904,1330=>810,1331=>809,1332=>813,1333=>810,1334=>815,1335=>724,1336=>800,1337=>1004,1338=>809,1339=>740,1340=>620,1341=>1068,1342=>875,1343=>792,1344=>723,1345=>811,1346=>794,1347=>782,1348=>867,1349=>766,1350=>794,1351=>787,1352=>812,1353=>752,1354=>963,1355=>790,1356=>867,1357=>812,1358=>794,1359=>771,1360=>740,1361=>775,1362=>640,1363=>926,1364=>775,1365=>848,1366=>951,1369=>366,1370=>380,1371=>342,1372=>415,1373=>348,1374=>513,1375=>521,1377=>1043,1378=>713,1379=>782,1380=>786,1381=>713,1382=>715,1383=>628,1384=>713,1385=>840,1386=>782,1387=>714,1388=>344,1389=>1094,1390=>708,1391=>714,1392=>714,1393=>670,1394=>714,1395=>713,1396=>714,1397=>343,1398=>714,1399=>541,1400=>714,1401=>407,1402=>1043,1403=>636,1404=>740,1405=>714,1406=>714,1407=>1038,1408=>714,1409=>714,1410=>532,1411=>1038,1412=>720,1413=>689,1414=>904,1415=>902,1417=>400,1418=>415,1456=>0,1457=>0,1458=>0,1459=>0,1460=>0,1461=>0,1462=>0,1463=>0,1464=>0,1465=>0,1466=>0,1467=>0,1468=>0,1469=>0,1470=>415,1471=>0,1472=>372,1473=>0,1474=>0,1475=>372,1478=>497,1479=>0,1488=>728,1489=>610,1490=>447,1491=>588,1492=>687,1493=>343,1494=>400,1495=>687,1496=>679,1497=>294,1498=>578,1499=>566,1500=>605,1501=>696,1502=>724,1503=>343,1504=>453,1505=>680,1506=>666,1507=>675,1508=>658,1509=>661,1510=>653,1511=>736,1512=>602,1513=>749,1514=>683,1520=>664,1521=>664,1522=>663,1523=>444,1524=>710,3647=>696,3713=>815,3714=>748,3716=>749,3719=>569,3720=>742,3722=>744,3725=>761,3732=>706,3733=>704,3734=>747,3735=>819,3737=>730,3738=>727,3739=>727,3740=>922,3741=>827,3742=>866,3743=>866,3745=>836,3746=>761,3747=>770,3749=>769,3751=>713,3754=>827,3755=>1031,3757=>724,3758=>784,3759=>934,3760=>688,3761=>0,3762=>610,3763=>610,3764=>0,3765=>0,3766=>0,3767=>0,3768=>0,3769=>0,3771=>0,3772=>0,3773=>670,3776=>516,3777=>860,3778=>516,3779=>650,3780=>632,3782=>759,3784=>0,3785=>0,3786=>0,3787=>0,3788=>0,3789=>0,3792=>771,3793=>771,3794=>693,3795=>836,3796=>729,3797=>729,3798=>849,3799=>790,3800=>759,3801=>910,3804=>1363,3805=>1363,4256=>874,4257=>733,4258=>679,4259=>834,4260=>615,4261=>768,4262=>753,4263=>914,4264=>453,4265=>620,4266=>843,4267=>882,4268=>625,4269=>854,4270=>781,4271=>629,4272=>912,4273=>621,4274=>620,4275=>854,4276=>866,4277=>724,4278=>630,4279=>621,4280=>625,4281=>620,4282=>818,4283=>874,4284=>615,4285=>623,4286=>625,4287=>725,4288=>844,4289=>596,4290=>688,4291=>596,4292=>594,4293=>738,4304=>554,4305=>563,4306=>622,4307=>834,4308=>550,4309=>559,4310=>546,4311=>828,4312=>563,4313=>556,4314=>1074,4315=>563,4316=>563,4317=>814,4318=>554,4319=>559,4320=>823,4321=>563,4322=>700,4323=>582,4324=>847,4325=>555,4326=>814,4327=>559,4328=>543,4329=>563,4330=>622,4331=>563,4332=>543,4333=>566,4334=>563,4335=>530,4336=>554,4337=>554,4338=>553,4339=>554,4340=>553,4341=>583,4342=>853,4343=>604,4344=>559,4345=>632,4346=>554,4347=>448,4348=>324,5121=>774,5122=>774,5123=>774,5124=>774,5125=>905,5126=>905,5127=>905,5129=>905,5130=>905,5131=>905,5132=>1018,5133=>1009,5134=>1018,5135=>1009,5136=>1018,5137=>1009,5138=>1149,5139=>1140,5140=>1149,5141=>1140,5142=>905,5143=>1149,5144=>1142,5145=>1149,5146=>1142,5147=>905,5149=>310,5150=>529,5151=>425,5152=>425,5153=>395,5154=>395,5155=>395,5156=>395,5157=>564,5158=>470,5159=>310,5160=>395,5161=>395,5162=>395,5163=>1213,5164=>986,5165=>1216,5166=>1297,5167=>774,5168=>774,5169=>774,5170=>774,5171=>886,5172=>886,5173=>886,5175=>886,5176=>886,5177=>886,5178=>1018,5179=>1009,5180=>1018,5181=>1009,5182=>1018,5183=>1009,5184=>1149,5185=>1140,5186=>1149,5187=>1140,5188=>1149,5189=>1142,5190=>1149,5191=>1142,5192=>886,5193=>576,5194=>229,5196=>812,5197=>812,5198=>812,5199=>812,5200=>815,5201=>815,5202=>815,5204=>815,5205=>815,5206=>815,5207=>1056,5208=>1048,5209=>1056,5210=>1048,5211=>1056,5212=>1048,5213=>1060,5214=>1054,5215=>1060,5216=>1054,5217=>1060,5218=>1052,5219=>1060,5220=>1052,5221=>1060,5222=>483,5223=>1005,5224=>1005,5225=>1023,5226=>1017,5227=>743,5228=>743,5229=>743,5230=>743,5231=>743,5232=>743,5233=>743,5234=>743,5235=>743,5236=>1029,5237=>975,5238=>980,5239=>975,5240=>980,5241=>975,5242=>1029,5243=>975,5244=>1029,5245=>975,5246=>980,5247=>975,5248=>980,5249=>975,5250=>980,5251=>501,5252=>501,5253=>938,5254=>938,5255=>938,5256=>938,5257=>743,5258=>743,5259=>743,5260=>743,5261=>743,5262=>743,5263=>743,5264=>743,5265=>743,5266=>1029,5267=>975,5268=>1029,5269=>975,5270=>1029,5271=>975,5272=>1029,5273=>975,5274=>1029,5275=>975,5276=>1029,5277=>975,5278=>1029,5279=>975,5280=>1029,5281=>501,5282=>501,5283=>626,5284=>626,5285=>626,5286=>626,5287=>626,5288=>626,5289=>626,5290=>626,5291=>626,5292=>881,5293=>854,5294=>863,5295=>874,5296=>863,5297=>874,5298=>881,5299=>874,5300=>881,5301=>874,5302=>863,5303=>874,5304=>863,5305=>874,5306=>863,5307=>436,5308=>548,5309=>436,5312=>988,5313=>988,5314=>988,5315=>988,5316=>931,5317=>931,5318=>931,5319=>931,5320=>931,5321=>1238,5322=>1247,5323=>1200,5324=>1228,5325=>1200,5326=>1228,5327=>931,5328=>660,5329=>497,5330=>660,5331=>988,5332=>988,5333=>988,5334=>988,5335=>931,5336=>931,5337=>931,5338=>931,5339=>931,5340=>1231,5341=>1247,5342=>1283,5343=>1228,5344=>1283,5345=>1228,5346=>1228,5347=>1214,5348=>1228,5349=>1214,5350=>1283,5351=>1228,5352=>1283,5353=>1228,5354=>660,5356=>886,5357=>730,5358=>730,5359=>730,5360=>730,5361=>730,5362=>730,5363=>730,5364=>730,5365=>730,5366=>998,5367=>958,5368=>967,5369=>989,5370=>967,5371=>989,5372=>998,5373=>958,5374=>998,5375=>958,5376=>967,5377=>989,5378=>967,5379=>989,5380=>967,5381=>493,5382=>460,5383=>493,5392=>923,5393=>923,5394=>923,5395=>1136,5396=>1136,5397=>1136,5398=>1136,5399=>1209,5400=>1202,5401=>1209,5402=>1202,5403=>1209,5404=>1202,5405=>1431,5406=>1420,5407=>1431,5408=>1420,5409=>1431,5410=>1420,5411=>1431,5412=>1420,5413=>746,5414=>776,5415=>776,5416=>776,5417=>776,5418=>776,5419=>776,5420=>776,5421=>776,5422=>776,5423=>1003,5424=>1003,5425=>1013,5426=>996,5427=>1013,5428=>996,5429=>1003,5430=>1003,5431=>1003,5432=>1003,5433=>1013,5434=>996,5435=>1013,5436=>996,5437=>1013,5438=>495,5440=>395,5441=>510,5442=>1033,5443=>1033,5444=>976,5445=>976,5446=>976,5447=>976,5448=>733,5449=>733,5450=>733,5451=>733,5452=>733,5453=>733,5454=>1003,5455=>959,5456=>495,5458=>886,5459=>774,5460=>774,5461=>774,5462=>774,5463=>928,5464=>928,5465=>928,5466=>928,5467=>1172,5468=>1142,5469=>602,5470=>812,5471=>812,5472=>812,5473=>812,5474=>812,5475=>812,5476=>815,5477=>815,5478=>815,5479=>815,5480=>1060,5481=>1052,5482=>548,5492=>977,5493=>977,5494=>977,5495=>977,5496=>977,5497=>977,5498=>977,5499=>618,5500=>837,5501=>510,5502=>1238,5503=>1238,5504=>1238,5505=>1238,5506=>1238,5507=>1238,5508=>1238,5509=>989,5514=>977,5515=>977,5516=>977,5517=>977,5518=>1591,5519=>1591,5520=>1591,5521=>1295,5522=>1295,5523=>1591,5524=>1591,5525=>848,5526=>1273,5536=>988,5537=>988,5538=>931,5539=>931,5540=>931,5541=>931,5542=>660,5543=>776,5544=>776,5545=>776,5546=>776,5547=>776,5548=>776,5549=>776,5550=>495,5551=>743,5598=>830,5601=>830,5702=>496,5703=>496,5742=>413,5743=>1238,5744=>1591,5745=>2016,5746=>2016,5747=>1720,5748=>1678,5749=>2016,5750=>2016,7424=>652,7425=>833,7426=>1048,7427=>608,7428=>593,7429=>676,7430=>676,7431=>559,7432=>557,7433=>343,7434=>494,7435=>665,7436=>539,7437=>817,7438=>701,7439=>687,7440=>593,7441=>660,7442=>660,7443=>660,7444=>1094,7446=>687,7447=>687,7448=>556,7449=>642,7450=>642,7451=>580,7452=>634,7453=>737,7454=>948,7455=>695,7456=>652,7457=>924,7458=>582,7459=>646,7462=>539,7463=>652,7464=>691,7465=>556,7466=>781,7467=>732,7468=>487,7469=>683,7470=>480,7472=>523,7473=>430,7474=>430,7475=>517,7476=>527,7477=>234,7478=>234,7479=>488,7480=>401,7481=>626,7482=>527,7483=>527,7484=>535,7485=>509,7486=>461,7487=>485,7488=>430,7489=>511,7490=>695,7491=>458,7492=>458,7493=>479,7494=>712,7495=>479,7496=>479,7497=>479,7498=>479,7499=>386,7500=>386,7501=>479,7502=>219,7503=>487,7504=>664,7505=>456,7506=>488,7507=>414,7508=>488,7509=>488,7510=>479,7511=>388,7512=>456,7513=>462,7514=>664,7515=>501,7517=>451,7518=>429,7519=>433,7520=>493,7521=>406,7522=>219,7523=>315,7524=>456,7525=>501,7526=>451,7527=>429,7528=>451,7529=>493,7530=>406,7543=>716,7544=>527,7547=>545,7549=>747,7557=>514,7579=>479,7580=>414,7581=>414,7582=>488,7583=>386,7584=>377,7585=>348,7586=>479,7587=>456,7588=>347,7589=>281,7590=>347,7591=>347,7592=>431,7593=>326,7594=>330,7595=>370,7596=>664,7597=>664,7598=>562,7599=>562,7600=>448,7601=>488,7602=>542,7603=>422,7604=>396,7605=>388,7606=>583,7607=>494,7608=>399,7609=>451,7610=>501,7611=>417,7612=>523,7613=>470,7614=>455,7615=>425,7620=>0,7621=>0,7622=>0,7623=>0,7624=>0,7625=>0,7680=>774,7681=>675,7682=>762,7683=>716,7684=>762,7685=>716,7686=>762,7687=>716,7688=>734,7689=>593,7690=>830,7691=>716,7692=>830,7693=>716,7694=>830,7695=>716,7696=>830,7697=>716,7698=>830,7699=>716,7700=>683,7701=>678,7702=>683,7703=>678,7704=>683,7705=>678,7706=>683,7707=>678,7708=>683,7709=>678,7710=>683,7711=>435,7712=>821,7713=>716,7714=>837,7715=>712,7716=>837,7717=>712,7718=>837,7719=>712,7720=>837,7721=>712,7722=>837,7723=>712,7724=>372,7725=>343,7726=>372,7727=>343,7728=>775,7729=>665,7730=>775,7731=>665,7732=>775,7733=>665,7734=>637,7735=>343,7736=>637,7737=>343,7738=>637,7739=>343,7740=>637,7741=>343,7742=>995,7743=>1042,7744=>995,7745=>1042,7746=>995,7747=>1042,7748=>837,7749=>712,7750=>837,7751=>712,7752=>837,7753=>712,7754=>837,7755=>712,7756=>850,7757=>687,7758=>850,7759=>687,7760=>850,7761=>687,7762=>850,7763=>687,7764=>733,7765=>716,7766=>733,7767=>716,7768=>770,7769=>493,7770=>770,7771=>493,7772=>770,7773=>493,7774=>770,7775=>493,7776=>720,7777=>595,7778=>720,7779=>595,7780=>720,7781=>595,7782=>720,7783=>595,7784=>720,7785=>595,7786=>682,7787=>478,7788=>682,7789=>478,7790=>682,7791=>478,7792=>682,7793=>478,7794=>812,7795=>712,7796=>812,7797=>712,7798=>812,7799=>712,7800=>812,7801=>712,7802=>812,7803=>712,7804=>774,7805=>652,7806=>774,7807=>652,7808=>1103,7809=>924,7810=>1103,7811=>924,7812=>1103,7813=>924,7814=>1103,7815=>924,7816=>1103,7817=>924,7818=>771,7819=>645,7820=>771,7821=>645,7822=>724,7823=>652,7824=>725,7825=>582,7826=>725,7827=>582,7828=>725,7829=>582,7830=>712,7831=>478,7832=>924,7833=>652,7834=>675,7835=>435,7836=>435,7837=>435,7838=>896,7839=>687,7840=>774,7841=>675,7842=>774,7843=>675,7844=>774,7845=>675,7846=>774,7847=>675,7848=>774,7849=>675,7850=>774,7851=>675,7852=>774,7853=>675,7854=>774,7855=>675,7856=>774,7857=>675,7858=>774,7859=>675,7860=>774,7861=>675,7862=>774,7863=>675,7864=>683,7865=>678,7866=>683,7867=>678,7868=>683,7869=>678,7870=>683,7871=>678,7872=>683,7873=>678,7874=>683,7875=>678,7876=>683,7877=>678,7878=>683,7879=>678,7880=>372,7881=>343,7882=>372,7883=>343,7884=>850,7885=>687,7886=>850,7887=>687,7888=>850,7889=>687,7890=>850,7891=>687,7892=>850,7893=>687,7894=>850,7895=>687,7896=>850,7897=>687,7898=>850,7899=>687,7900=>850,7901=>687,7902=>850,7903=>687,7904=>850,7905=>687,7906=>850,7907=>687,7908=>812,7909=>712,7910=>812,7911=>712,7912=>812,7913=>712,7914=>812,7915=>712,7916=>812,7917=>712,7918=>812,7919=>712,7920=>812,7921=>712,7922=>724,7923=>652,7924=>724,7925=>652,7926=>724,7927=>652,7928=>724,7929=>652,7930=>953,7931=>644,7936=>687,7937=>687,7938=>687,7939=>687,7940=>687,7941=>687,7942=>687,7943=>687,7944=>774,7945=>774,7946=>1041,7947=>1043,7948=>935,7949=>963,7950=>835,7951=>859,7952=>557,7953=>557,7954=>557,7955=>557,7956=>557,7957=>557,7960=>792,7961=>794,7962=>1100,7963=>1096,7964=>1023,7965=>1052,7968=>712,7969=>712,7970=>712,7971=>712,7972=>712,7973=>712,7974=>712,7975=>712,7976=>945,7977=>951,7978=>1250,7979=>1250,7980=>1180,7981=>1206,7982=>1054,7983=>1063,7984=>390,7985=>390,7986=>390,7987=>390,7988=>390,7989=>390,7990=>390,7991=>390,7992=>483,7993=>489,7994=>777,7995=>785,7996=>712,7997=>738,7998=>604,7999=>604,8000=>687,8001=>687,8002=>687,8003=>687,8004=>687,8005=>687,8008=>892,8009=>933,8010=>1221,8011=>1224,8012=>1053,8013=>1082,8016=>675,8017=>675,8018=>675,8019=>675,8020=>675,8021=>675,8022=>675,8023=>675,8025=>930,8027=>1184,8029=>1199,8031=>1049,8032=>869,8033=>869,8034=>869,8035=>869,8036=>869,8037=>869,8038=>869,8039=>869,8040=>909,8041=>958,8042=>1246,8043=>1251,8044=>1076,8045=>1105,8046=>1028,8047=>1076,8048=>687,8049=>687,8050=>557,8051=>557,8052=>712,8053=>712,8054=>390,8055=>390,8056=>687,8057=>687,8058=>675,8059=>675,8060=>869,8061=>869,8064=>687,8065=>687,8066=>687,8067=>687,8068=>687,8069=>687,8070=>687,8071=>687,8072=>774,8073=>774,8074=>1041,8075=>1043,8076=>935,8077=>963,8078=>835,8079=>859,8080=>712,8081=>712,8082=>712,8083=>712,8084=>712,8085=>712,8086=>712,8087=>712,8088=>945,8089=>951,8090=>1250,8091=>1250,8092=>1180,8093=>1206,8094=>1054,8095=>1063,8096=>869,8097=>869,8098=>869,8099=>869,8100=>869,8101=>869,8102=>869,8103=>869,8104=>909,8105=>958,8106=>1246,8107=>1251,8108=>1076,8109=>1105,8110=>1028,8111=>1076,8112=>687,8113=>687,8114=>687,8115=>687,8116=>687,8118=>687,8119=>687,8120=>774,8121=>774,8122=>876,8123=>797,8124=>774,8125=>500,8126=>500,8127=>500,8128=>500,8129=>500,8130=>712,8131=>712,8132=>712,8134=>712,8135=>712,8136=>929,8137=>846,8138=>1080,8139=>1009,8140=>837,8141=>500,8142=>500,8143=>500,8144=>390,8145=>390,8146=>390,8147=>390,8150=>390,8151=>390,8152=>372,8153=>372,8154=>621,8155=>563,8157=>500,8158=>500,8159=>500,8160=>675,8161=>675,8162=>675,8163=>675,8164=>716,8165=>716,8166=>675,8167=>675,8168=>724,8169=>724,8170=>1020,8171=>980,8172=>838,8173=>500,8174=>500,8175=>500,8178=>869,8179=>869,8180=>869,8182=>869,8183=>869,8184=>1065,8185=>891,8186=>1084,8187=>894,8188=>850,8189=>500,8190=>500,8192=>500,8193=>1000,8194=>500,8195=>1000,8196=>330,8197=>250,8198=>167,8199=>696,8200=>380,8201=>200,8202=>100,8203=>0,8204=>0,8205=>0,8206=>0,8207=>0,8208=>415,8209=>415,8210=>696,8211=>500,8212=>1000,8213=>1000,8214=>500,8215=>500,8216=>380,8217=>380,8218=>380,8219=>380,8220=>644,8221=>644,8222=>644,8223=>657,8224=>500,8225=>500,8226=>639,8227=>639,8228=>380,8229=>685,8230=>1000,8231=>348,8232=>0,8233=>0,8234=>0,8235=>0,8236=>0,8237=>0,8238=>0,8239=>200,8240=>1454,8241=>1908,8242=>264,8243=>447,8244=>630,8245=>264,8246=>447,8247=>630,8248=>733,8249=>412,8250=>412,8251=>972,8252=>627,8253=>580,8254=>500,8255=>828,8256=>828,8257=>329,8258=>1023,8259=>500,8260=>167,8261=>457,8262=>457,8263=>1030,8264=>829,8265=>829,8266=>513,8267=>687,8268=>500,8269=>500,8270=>523,8271=>400,8272=>828,8273=>523,8274=>556,8275=>838,8276=>828,8277=>838,8278=>684,8279=>813,8280=>838,8281=>838,8282=>380,8283=>872,8284=>838,8285=>380,8286=>380,8287=>222,8288=>0,8289=>0,8290=>0,8291=>0,8292=>0,8298=>0,8299=>0,8300=>0,8301=>0,8302=>0,8303=>0,8304=>438,8305=>219,8308=>438,8309=>438,8310=>438,8311=>438,8312=>438,8313=>438,8314=>528,8315=>528,8316=>528,8317=>288,8318=>288,8319=>456,8320=>438,8321=>438,8322=>438,8323=>438,8324=>438,8325=>438,8326=>438,8327=>438,8328=>438,8329=>438,8330=>528,8331=>528,8332=>528,8333=>288,8334=>288,8336=>458,8337=>479,8338=>488,8339=>413,8340=>479,8341=>456,8342=>487,8343=>219,8344=>664,8345=>456,8346=>479,8347=>381,8348=>388,8352=>929,8353=>696,8354=>696,8355=>696,8356=>696,8357=>1042,8358=>837,8359=>1488,8360=>1205,8361=>1103,8362=>854,8363=>696,8364=>696,8365=>696,8366=>696,8367=>1392,8368=>696,8369=>696,8370=>696,8371=>696,8372=>859,8373=>696,8376=>696,8377=>696,8378=>769,8400=>0,8401=>0,8406=>0,8407=>0,8411=>0,8412=>0,8417=>0,8448=>1106,8449=>1106,8450=>734,8451=>1211,8452=>896,8453=>1114,8454=>1148,8455=>696,8456=>698,8457=>952,8459=>1073,8460=>913,8461=>888,8462=>712,8463=>712,8464=>597,8465=>697,8466=>856,8467=>472,8468=>974,8469=>837,8470=>1203,8471=>1000,8472=>697,8473=>750,8474=>850,8475=>938,8476=>814,8477=>801,8478=>896,8479=>710,8480=>1020,8481=>1239,8482=>1000,8483=>834,8484=>754,8485=>622,8486=>850,8487=>769,8488=>763,8489=>303,8490=>775,8491=>774,8492=>928,8493=>818,8494=>854,8495=>636,8496=>729,8497=>808,8498=>683,8499=>1184,8500=>465,8501=>794,8502=>731,8503=>494,8504=>684,8505=>380,8506=>945,8507=>1370,8508=>790,8509=>737,8510=>654,8511=>863,8512=>840,8513=>786,8514=>576,8515=>637,8516=>760,8517=>830,8518=>716,8519=>678,8520=>343,8521=>343,8523=>872,8526=>547,8528=>1035,8529=>1035,8530=>1483,8531=>1035,8532=>1035,8533=>1035,8534=>1035,8535=>1035,8536=>1035,8537=>1035,8538=>1035,8539=>1035,8540=>1035,8541=>1035,8542=>1035,8543=>615,8544=>372,8545=>659,8546=>945,8547=>1099,8548=>774,8549=>1099,8550=>1386,8551=>1672,8552=>1121,8553=>771,8554=>1120,8555=>1407,8556=>637,8557=>734,8558=>830,8559=>995,8560=>343,8561=>607,8562=>872,8563=>984,8564=>652,8565=>962,8566=>1227,8567=>1491,8568=>969,8569=>645,8570=>969,8571=>1233,8572=>343,8573=>593,8574=>716,8575=>1042,8576=>1289,8577=>830,8578=>1289,8579=>734,8580=>593,8581=>734,8585=>1035,8592=>838,8593=>838,8594=>838,8595=>838,8596=>838,8597=>838,8598=>838,8599=>838,8600=>838,8601=>838,8602=>838,8603=>838,8604=>838,8605=>838,8606=>838,8607=>838,8608=>838,8609=>838,8610=>838,8611=>838,8612=>838,8613=>838,8614=>838,8615=>838,8616=>838,8617=>838,8618=>838,8619=>838,8620=>838,8621=>838,8622=>838,8623=>838,8624=>838,8625=>838,8626=>838,8627=>838,8628=>838,8629=>838,8630=>838,8631=>838,8632=>838,8633=>838,8634=>838,8635=>838,8636=>838,8637=>838,8638=>838,8639=>838,8640=>838,8641=>838,8642=>838,8643=>838,8644=>838,8645=>838,8646=>838,8647=>838,8648=>838,8649=>838,8650=>838,8651=>838,8652=>838,8653=>838,8654=>838,8655=>838,8656=>838,8657=>838,8658=>838,8659=>838,8660=>838,8661=>838,8662=>838,8663=>838,8664=>838,8665=>838,8666=>838,8667=>838,8668=>838,8669=>838,8670=>838,8671=>838,8672=>838,8673=>838,8674=>838,8675=>838,8676=>838,8677=>838,8678=>838,8679=>838,8680=>838,8681=>838,8682=>838,8683=>838,8684=>838,8685=>838,8686=>838,8687=>838,8688=>838,8689=>838,8690=>838,8691=>838,8692=>838,8693=>838,8694=>838,8695=>838,8696=>838,8697=>838,8698=>838,8699=>838,8700=>838,8701=>838,8702=>838,8703=>838,8704=>774,8705=>696,8706=>544,8707=>683,8708=>683,8709=>856,8710=>697,8711=>697,8712=>896,8713=>896,8714=>750,8715=>896,8716=>896,8717=>750,8718=>636,8719=>787,8720=>787,8721=>718,8722=>838,8723=>838,8724=>696,8725=>365,8726=>696,8727=>838,8728=>626,8729=>380,8730=>667,8731=>667,8732=>667,8733=>712,8734=>833,8735=>838,8736=>896,8737=>896,8738=>838,8739=>500,8740=>500,8741=>500,8742=>500,8743=>812,8744=>812,8745=>812,8746=>812,8747=>610,8748=>929,8749=>1295,8750=>563,8751=>977,8752=>1313,8753=>563,8754=>563,8755=>563,8756=>696,8757=>696,8758=>294,8759=>696,8760=>838,8761=>838,8762=>838,8763=>838,8764=>838,8765=>838,8766=>838,8767=>838,8768=>375,8769=>838,8770=>838,8771=>838,8772=>838,8773=>838,8774=>838,8775=>838,8776=>838,8777=>838,8778=>838,8779=>838,8780=>838,8781=>838,8782=>838,8783=>838,8784=>838,8785=>838,8786=>838,8787=>838,8788=>1063,8789=>1063,8790=>838,8791=>838,8792=>838,8793=>838,8794=>838,8795=>838,8796=>838,8797=>838,8798=>838,8799=>838,8800=>838,8801=>838,8802=>838,8803=>838,8804=>838,8805=>838,8806=>838,8807=>838,8808=>841,8809=>841,8810=>1047,8811=>1047,8812=>500,8813=>838,8814=>838,8815=>838,8816=>838,8817=>838,8818=>838,8819=>838,8820=>838,8821=>838,8822=>838,8823=>838,8824=>838,8825=>838,8826=>838,8827=>838,8828=>838,8829=>838,8830=>838,8831=>838,8832=>838,8833=>838,8834=>838,8835=>838,8836=>838,8837=>838,8838=>838,8839=>838,8840=>838,8841=>838,8842=>838,8843=>838,8844=>812,8845=>812,8846=>812,8847=>838,8848=>838,8849=>838,8850=>838,8851=>796,8852=>796,8853=>838,8854=>838,8855=>838,8856=>838,8857=>838,8858=>838,8859=>838,8860=>838,8861=>838,8862=>838,8863=>838,8864=>838,8865=>838,8866=>914,8867=>914,8868=>914,8869=>914,8870=>542,8871=>542,8872=>914,8873=>914,8874=>914,8875=>914,8876=>914,8877=>914,8878=>914,8879=>914,8880=>838,8881=>838,8882=>838,8883=>838,8884=>838,8885=>838,8886=>1000,8887=>1000,8888=>838,8889=>838,8890=>542,8891=>812,8892=>812,8893=>812,8894=>838,8895=>838,8896=>843,8897=>843,8898=>843,8899=>843,8900=>494,8901=>380,8902=>626,8903=>838,8904=>1000,8905=>1000,8906=>1000,8907=>1000,8908=>1000,8909=>838,8910=>812,8911=>812,8912=>838,8913=>838,8914=>838,8915=>838,8916=>838,8917=>838,8918=>838,8919=>838,8920=>1422,8921=>1422,8922=>838,8923=>838,8924=>838,8925=>838,8926=>838,8927=>838,8928=>838,8929=>838,8930=>838,8931=>838,8932=>838,8933=>838,8934=>838,8935=>838,8936=>838,8937=>838,8938=>838,8939=>838,8940=>838,8941=>838,8942=>1000,8943=>1000,8944=>1000,8945=>1000,8946=>1158,8947=>896,8948=>750,8949=>896,8950=>896,8951=>750,8952=>896,8953=>896,8954=>1158,8955=>896,8956=>750,8957=>896,8958=>750,8959=>896,8960=>602,8961=>602,8962=>716,8963=>838,8964=>838,8965=>838,8966=>838,8967=>488,8968=>457,8969=>457,8970=>457,8971=>457,8972=>809,8973=>809,8974=>809,8975=>809,8976=>838,8977=>539,8984=>928,8985=>838,8988=>469,8989=>469,8990=>469,8991=>469,8992=>610,8993=>610,8996=>1152,8997=>1152,8998=>1414,8999=>1152,9000=>1443,9003=>1414,9004=>873,9075=>390,9076=>716,9077=>869,9082=>687,9085=>863,9095=>1152,9108=>873,9115=>500,9116=>500,9117=>500,9118=>500,9119=>500,9120=>500,9121=>500,9122=>500,9123=>500,9124=>500,9125=>500,9126=>500,9127=>750,9128=>750,9129=>750,9130=>750,9131=>750,9132=>750,9133=>750,9134=>610,9166=>838,9167=>945,9187=>873,9189=>769,9192=>696,9250=>716,9251=>716,9312=>847,9313=>847,9314=>847,9315=>847,9316=>847,9317=>847,9318=>847,9319=>847,9320=>847,9321=>847,9600=>769,9601=>769,9602=>769,9603=>769,9604=>769,9605=>769,9606=>769,9607=>769,9608=>769,9609=>769,9610=>769,9611=>769,9612=>769,9613=>769,9614=>769,9615=>769,9616=>769,9617=>769,9618=>769,9619=>769,9620=>769,9621=>769,9622=>769,9623=>769,9624=>769,9625=>769,9626=>769,9627=>769,9628=>769,9629=>769,9630=>769,9631=>769,9632=>945,9633=>945,9634=>945,9635=>945,9636=>945,9637=>945,9638=>945,9639=>945,9640=>945,9641=>945,9642=>678,9643=>678,9644=>945,9645=>945,9646=>550,9647=>550,9648=>769,9649=>769,9650=>769,9651=>769,9652=>502,9653=>502,9654=>769,9655=>769,9656=>502,9657=>502,9658=>769,9659=>769,9660=>769,9661=>769,9662=>502,9663=>502,9664=>769,9665=>769,9666=>502,9667=>502,9668=>769,9669=>769,9670=>769,9671=>769,9672=>769,9673=>873,9674=>494,9675=>873,9676=>873,9677=>873,9678=>873,9679=>873,9680=>873,9681=>873,9682=>873,9683=>873,9684=>873,9685=>873,9686=>527,9687=>527,9688=>840,9689=>970,9690=>970,9691=>970,9692=>387,9693=>387,9694=>387,9695=>387,9696=>769,9697=>769,9698=>769,9699=>769,9700=>769,9701=>769,9702=>639,9703=>945,9704=>945,9705=>945,9706=>945,9707=>945,9708=>769,9709=>769,9710=>769,9711=>1119,9712=>945,9713=>945,9714=>945,9715=>945,9716=>873,9717=>873,9718=>873,9719=>873,9720=>769,9721=>769,9722=>769,9723=>830,9724=>830,9725=>732,9726=>732,9727=>769,9728=>896,9729=>1000,9730=>896,9731=>896,9732=>896,9733=>896,9734=>896,9735=>573,9736=>896,9737=>896,9738=>888,9739=>888,9740=>671,9741=>1013,9742=>1246,9743=>1250,9744=>896,9745=>896,9746=>896,9747=>532,9748=>896,9749=>896,9750=>896,9751=>896,9752=>896,9753=>896,9754=>896,9755=>896,9756=>896,9757=>609,9758=>896,9759=>609,9760=>896,9761=>896,9762=>896,9763=>896,9764=>669,9765=>746,9766=>649,9767=>784,9768=>545,9769=>896,9770=>896,9771=>896,9772=>710,9773=>896,9774=>896,9775=>896,9776=>896,9777=>896,9778=>896,9779=>896,9780=>896,9781=>896,9782=>896,9783=>896,9784=>896,9785=>1042,9786=>1042,9787=>1042,9788=>896,9789=>896,9790=>896,9791=>614,9792=>732,9793=>732,9794=>896,9795=>896,9796=>896,9797=>896,9798=>896,9799=>896,9800=>896,9801=>896,9802=>896,9803=>896,9804=>896,9805=>896,9806=>896,9807=>896,9808=>896,9809=>896,9810=>896,9811=>896,9812=>896,9813=>896,9814=>896,9815=>896,9816=>896,9817=>896,9818=>896,9819=>896,9820=>896,9821=>896,9822=>896,9823=>896,9824=>896,9825=>896,9826=>896,9827=>896,9828=>896,9829=>896,9830=>896,9831=>896,9832=>896,9833=>472,9834=>638,9835=>896,9836=>896,9837=>472,9838=>357,9839=>484,9840=>748,9841=>766,9842=>896,9843=>896,9844=>896,9845=>896,9846=>896,9847=>896,9848=>896,9849=>896,9850=>896,9851=>896,9852=>896,9853=>896,9854=>896,9855=>896,9856=>869,9857=>869,9858=>869,9859=>869,9860=>869,9861=>869,9862=>896,9863=>896,9864=>896,9865=>896,9866=>896,9867=>896,9868=>896,9869=>896,9870=>896,9871=>896,9872=>896,9873=>896,9874=>896,9875=>896,9876=>896,9877=>541,9878=>896,9879=>896,9880=>896,9881=>896,9882=>896,9883=>896,9884=>896,9888=>896,9889=>702,9890=>1004,9891=>1089,9892=>1175,9893=>903,9894=>838,9895=>838,9896=>838,9897=>838,9898=>838,9899=>838,9900=>838,9901=>838,9902=>838,9903=>838,9904=>844,9905=>838,9906=>732,9907=>732,9908=>732,9909=>732,9910=>850,9911=>732,9912=>732,9920=>838,9921=>838,9922=>838,9923=>838,9954=>732,9985=>838,9986=>838,9987=>838,9988=>838,9990=>838,9991=>838,9992=>838,9993=>838,9996=>838,9997=>838,9998=>838,9999=>838,10000=>838,10001=>838,10002=>838,10003=>838,10004=>838,10005=>838,10006=>838,10007=>838,10008=>838,10009=>838,10010=>838,10011=>838,10012=>838,10013=>838,10014=>838,10015=>838,10016=>838,10017=>838,10018=>838,10019=>838,10020=>838,10021=>838,10022=>838,10023=>838,10025=>838,10026=>838,10027=>838,10028=>838,10029=>838,10030=>838,10031=>838,10032=>838,10033=>838,10034=>838,10035=>838,10036=>838,10037=>838,10038=>838,10039=>838,10040=>838,10041=>838,10042=>838,10043=>838,10044=>838,10045=>838,10046=>838,10047=>838,10048=>838,10049=>838,10050=>838,10051=>838,10052=>838,10053=>838,10054=>838,10055=>838,10056=>838,10057=>838,10058=>838,10059=>838,10061=>896,10063=>896,10064=>896,10065=>896,10066=>896,10070=>896,10072=>838,10073=>838,10074=>838,10075=>322,10076=>322,10077=>538,10078=>538,10081=>838,10082=>838,10083=>838,10084=>838,10085=>838,10086=>838,10087=>838,10088=>838,10089=>838,10090=>838,10091=>838,10092=>838,10093=>838,10094=>838,10095=>838,10096=>838,10097=>838,10098=>838,10099=>838,10100=>838,10101=>838,10102=>847,10103=>847,10104=>847,10105=>847,10106=>847,10107=>847,10108=>847,10109=>847,10110=>847,10111=>847,10112=>838,10113=>838,10114=>838,10115=>838,10116=>838,10117=>838,10118=>838,10119=>838,10120=>838,10121=>838,10122=>838,10123=>838,10124=>838,10125=>838,10126=>838,10127=>838,10128=>838,10129=>838,10130=>838,10131=>838,10132=>838,10136=>838,10137=>838,10138=>838,10139=>838,10140=>838,10141=>838,10142=>838,10143=>838,10144=>838,10145=>838,10146=>838,10147=>838,10148=>838,10149=>838,10150=>838,10151=>838,10152=>838,10153=>838,10154=>838,10155=>838,10156=>838,10157=>838,10158=>838,10159=>838,10161=>838,10162=>838,10163=>838,10164=>838,10165=>838,10166=>838,10167=>838,10168=>838,10169=>838,10170=>838,10171=>838,10172=>838,10173=>838,10174=>838,10181=>457,10182=>457,10208=>494,10214=>487,10215=>487,10216=>457,10217=>457,10218=>721,10219=>721,10224=>838,10225=>838,10226=>838,10227=>838,10228=>1157,10229=>1434,10230=>1434,10231=>1434,10232=>1434,10233=>1434,10234=>1434,10235=>1434,10236=>1434,10237=>1434,10238=>1434,10239=>1434,10240=>781,10241=>781,10242=>781,10243=>781,10244=>781,10245=>781,10246=>781,10247=>781,10248=>781,10249=>781,10250=>781,10251=>781,10252=>781,10253=>781,10254=>781,10255=>781,10256=>781,10257=>781,10258=>781,10259=>781,10260=>781,10261=>781,10262=>781,10263=>781,10264=>781,10265=>781,10266=>781,10267=>781,10268=>781,10269=>781,10270=>781,10271=>781,10272=>781,10273=>781,10274=>781,10275=>781,10276=>781,10277=>781,10278=>781,10279=>781,10280=>781,10281=>781,10282=>781,10283=>781,10284=>781,10285=>781,10286=>781,10287=>781,10288=>781,10289=>781,10290=>781,10291=>781,10292=>781,10293=>781,10294=>781,10295=>781,10296=>781,10297=>781,10298=>781,10299=>781,10300=>781,10301=>781,10302=>781,10303=>781,10304=>781,10305=>781,10306=>781,10307=>781,10308=>781,10309=>781,10310=>781,10311=>781,10312=>781,10313=>781,10314=>781,10315=>781,10316=>781,10317=>781,10318=>781,10319=>781,10320=>781,10321=>781,10322=>781,10323=>781,10324=>781,10325=>781,10326=>781,10327=>781,10328=>781,10329=>781,10330=>781,10331=>781,10332=>781,10333=>781,10334=>781,10335=>781,10336=>781,10337=>781,10338=>781,10339=>781,10340=>781,10341=>781,10342=>781,10343=>781,10344=>781,10345=>781,10346=>781,10347=>781,10348=>781,10349=>781,10350=>781,10351=>781,10352=>781,10353=>781,10354=>781,10355=>781,10356=>781,10357=>781,10358=>781,10359=>781,10360=>781,10361=>781,10362=>781,10363=>781,10364=>781,10365=>781,10366=>781,10367=>781,10368=>781,10369=>781,10370=>781,10371=>781,10372=>781,10373=>781,10374=>781,10375=>781,10376=>781,10377=>781,10378=>781,10379=>781,10380=>781,10381=>781,10382=>781,10383=>781,10384=>781,10385=>781,10386=>781,10387=>781,10388=>781,10389=>781,10390=>781,10391=>781,10392=>781,10393=>781,10394=>781,10395=>781,10396=>781,10397=>781,10398=>781,10399=>781,10400=>781,10401=>781,10402=>781,10403=>781,10404=>781,10405=>781,10406=>781,10407=>781,10408=>781,10409=>781,10410=>781,10411=>781,10412=>781,10413=>781,10414=>781,10415=>781,10416=>781,10417=>781,10418=>781,10419=>781,10420=>781,10421=>781,10422=>781,10423=>781,10424=>781,10425=>781,10426=>781,10427=>781,10428=>781,10429=>781,10430=>781,10431=>781,10432=>781,10433=>781,10434=>781,10435=>781,10436=>781,10437=>781,10438=>781,10439=>781,10440=>781,10441=>781,10442=>781,10443=>781,10444=>781,10445=>781,10446=>781,10447=>781,10448=>781,10449=>781,10450=>781,10451=>781,10452=>781,10453=>781,10454=>781,10455=>781,10456=>781,10457=>781,10458=>781,10459=>781,10460=>781,10461=>781,10462=>781,10463=>781,10464=>781,10465=>781,10466=>781,10467=>781,10468=>781,10469=>781,10470=>781,10471=>781,10472=>781,10473=>781,10474=>781,10475=>781,10476=>781,10477=>781,10478=>781,10479=>781,10480=>781,10481=>781,10482=>781,10483=>781,10484=>781,10485=>781,10486=>781,10487=>781,10488=>781,10489=>781,10490=>781,10491=>781,10492=>781,10493=>781,10494=>781,10495=>781,10502=>838,10503=>838,10506=>838,10507=>838,10560=>838,10561=>838,10627=>753,10628=>753,10702=>838,10703=>1046,10704=>1046,10705=>1000,10706=>1000,10707=>1000,10708=>1000,10709=>1000,10731=>494,10746=>838,10747=>838,10752=>1000,10753=>1000,10754=>1000,10764=>1661,10765=>563,10766=>563,10767=>563,10768=>563,10769=>563,10770=>563,10771=>563,10772=>563,10773=>563,10774=>563,10775=>563,10776=>563,10777=>563,10778=>563,10779=>563,10780=>563,10799=>838,10858=>838,10859=>838,10877=>838,10878=>838,10879=>838,10880=>838,10881=>838,10882=>838,10883=>838,10884=>838,10885=>838,10886=>838,10887=>838,10888=>838,10889=>838,10890=>838,10891=>838,10892=>838,10893=>838,10894=>838,10895=>838,10896=>838,10897=>838,10898=>838,10899=>838,10900=>838,10901=>838,10902=>838,10903=>838,10904=>838,10905=>838,10906=>838,10907=>838,10908=>838,10909=>838,10910=>838,10911=>838,10912=>838,10926=>838,10927=>838,10928=>838,10929=>838,10930=>838,10931=>838,10932=>838,10933=>838,10934=>838,10935=>838,10936=>838,10937=>838,10938=>838,11001=>838,11002=>838,11008=>838,11009=>838,11010=>838,11011=>838,11012=>838,11013=>838,11014=>838,11015=>838,11016=>838,11017=>838,11018=>838,11019=>838,11020=>838,11021=>838,11022=>838,11023=>838,11024=>838,11025=>838,11026=>945,11027=>945,11028=>945,11029=>945,11030=>769,11031=>769,11032=>769,11033=>769,11034=>945,11039=>869,11040=>869,11041=>873,11042=>873,11043=>873,11044=>1119,11091=>869,11092=>869,11360=>637,11361=>360,11362=>637,11363=>733,11364=>770,11365=>675,11366=>478,11367=>956,11368=>712,11369=>775,11370=>665,11371=>725,11372=>582,11373=>860,11374=>995,11375=>774,11376=>860,11377=>778,11378=>1221,11379=>1056,11380=>652,11381=>698,11382=>565,11383=>782,11385=>538,11386=>687,11387=>559,11388=>219,11389=>487,11390=>720,11391=>725,11520=>663,11521=>676,11522=>661,11523=>629,11524=>661,11525=>1032,11526=>718,11527=>1032,11528=>648,11529=>667,11530=>1032,11531=>673,11532=>677,11533=>1036,11534=>680,11535=>886,11536=>1032,11537=>683,11538=>674,11539=>1035,11540=>1033,11541=>1027,11542=>676,11543=>673,11544=>667,11545=>667,11546=>660,11547=>671,11548=>1039,11549=>673,11550=>692,11551=>659,11552=>1048,11553=>660,11554=>654,11555=>670,11556=>733,11557=>1017,11800=>586,11807=>838,11810=>457,11811=>457,11812=>457,11813=>457,11822=>580,19904=>896,19905=>896,19906=>896,19907=>896,19908=>896,19909=>896,19910=>896,19911=>896,19912=>896,19913=>896,19914=>896,19915=>896,19916=>896,19917=>896,19918=>896,19919=>896,19920=>896,19921=>896,19922=>896,19923=>896,19924=>896,19925=>896,19926=>896,19927=>896,19928=>896,19929=>896,19930=>896,19931=>896,19932=>896,19933=>896,19934=>896,19935=>896,19936=>896,19937=>896,19938=>896,19939=>896,19940=>896,19941=>896,19942=>896,19943=>896,19944=>896,19945=>896,19946=>896,19947=>896,19948=>896,19949=>896,19950=>896,19951=>896,19952=>896,19953=>896,19954=>896,19955=>896,19956=>896,19957=>896,19958=>896,19959=>896,19960=>896,19961=>896,19962=>896,19963=>896,19964=>896,19965=>896,19966=>896,19967=>896,42192=>762,42193=>733,42194=>733,42195=>830,42196=>682,42197=>682,42198=>821,42199=>775,42200=>775,42201=>530,42202=>734,42203=>734,42204=>725,42205=>683,42206=>683,42207=>995,42208=>837,42209=>637,42210=>720,42211=>770,42212=>770,42213=>774,42214=>774,42215=>837,42216=>786,42217=>530,42218=>1103,42219=>771,42220=>724,42221=>762,42222=>774,42223=>774,42224=>683,42225=>683,42226=>372,42227=>850,42228=>812,42229=>812,42230=>576,42231=>830,42232=>322,42233=>322,42234=>674,42235=>674,42236=>322,42237=>322,42238=>588,42239=>588,42564=>720,42565=>595,42566=>436,42567=>440,42572=>1405,42573=>1173,42576=>1234,42577=>1027,42580=>1174,42581=>972,42582=>1100,42583=>969,42594=>1100,42595=>940,42596=>1096,42597=>915,42598=>1260,42599=>997,42600=>850,42601=>687,42602=>1037,42603=>868,42604=>1406,42605=>1106,42606=>961,42634=>944,42635=>749,42636=>682,42637=>580,42644=>808,42645=>712,42760=>500,42761=>500,42762=>500,42763=>500,42764=>500,42765=>500,42766=>500,42767=>500,42768=>500,42769=>500,42770=>500,42771=>500,42772=>500,42773=>500,42774=>500,42779=>400,42780=>400,42781=>287,42782=>287,42783=>287,42786=>444,42787=>390,42788=>540,42789=>540,42790=>837,42791=>712,42792=>1031,42793=>857,42794=>696,42795=>557,42800=>559,42801=>595,42802=>1349,42803=>1052,42804=>1285,42805=>1065,42806=>1245,42807=>1052,42808=>1079,42809=>922,42810=>1079,42811=>922,42812=>1035,42813=>922,42814=>698,42815=>549,42816=>656,42817=>579,42822=>850,42823=>542,42824=>683,42825=>531,42826=>918,42827=>814,42830=>1406,42831=>1106,42832=>733,42833=>716,42834=>948,42835=>937,42838=>850,42839=>716,42852=>738,42853=>716,42854=>738,42855=>716,42880=>637,42881=>343,42882=>837,42883=>712,42889=>400,42890=>396,42891=>456,42892=>306,42893=>808,42894=>693,42896=>928,42897=>768,42912=>821,42913=>716,42914=>775,42915=>665,42916=>837,42917=>712,42918=>770,42919=>493,42920=>720,42921=>595,42922=>886,43002=>1062,43003=>683,43004=>733,43005=>995,43006=>372,43007=>1325,61184=>216,61185=>242,61186=>267,61187=>277,61188=>282,61189=>242,61190=>216,61191=>242,61192=>267,61193=>277,61194=>267,61195=>242,61196=>216,61197=>242,61198=>267,61199=>277,61200=>267,61201=>242,61202=>216,61203=>242,61204=>282,61205=>277,61206=>267,61207=>242,61208=>216,61209=>282,62464=>612,62465=>612,62466=>653,62467=>902,62468=>617,62469=>617,62470=>680,62471=>904,62472=>599,62473=>617,62474=>1163,62475=>621,62476=>622,62477=>893,62478=>612,62479=>622,62480=>924,62481=>622,62482=>754,62483=>624,62484=>886,62485=>622,62486=>907,62487=>621,62488=>611,62489=>624,62490=>677,62491=>621,62492=>611,62493=>630,62494=>622,62495=>561,62496=>612,62497=>626,62498=>612,62499=>611,62500=>618,62501=>667,62502=>963,62504=>1023,62505=>844,62506=>563,62507=>563,62508=>563,62509=>563,62510=>563,62511=>563,62512=>555,62513=>555,62514=>555,62515=>555,62516=>573,62517=>573,62518=>573,62519=>824,62520=>824,62521=>824,62522=>824,62523=>824,62524=>611,62525=>611,62526=>611,62527=>611,62528=>611,62529=>611,62917=>687,64256=>833,64257=>787,64258=>787,64259=>1138,64260=>1139,64261=>808,64262=>1020,64275=>1388,64276=>1384,64277=>1378,64278=>1384,64279=>1713,64285=>294,64286=>0,64287=>663,64288=>665,64289=>939,64290=>788,64291=>920,64292=>786,64293=>857,64294=>869,64295=>821,64296=>890,64297=>838,64298=>749,64299=>749,64300=>749,64301=>749,64302=>728,64303=>728,64304=>728,64305=>610,64306=>447,64307=>588,64308=>687,64309=>343,64310=>400,64311=>1000,64312=>679,64313=>436,64314=>578,64315=>566,64316=>605,64317=>1000,64318=>724,64319=>1000,64320=>453,64321=>680,64322=>1000,64323=>675,64324=>658,64325=>1000,64326=>653,64327=>736,64328=>602,64329=>749,64330=>683,64331=>343,64332=>610,64333=>566,64334=>658,64335=>710,65024=>0,65025=>0,65026=>0,65027=>0,65028=>0,65029=>0,65030=>0,65031=>0,65032=>0,65033=>0,65034=>0,65035=>0,65036=>0,65037=>0,65038=>0,65039=>0,65056=>0,65057=>0,65058=>0,65059=>0,65529=>0,65530=>0,65531=>0,65532=>0,65533=>1113,65535=>600); -// --- EOF --- diff --git a/lib/combodo/tcpdf/fonts/dejavusansbi.z b/lib/combodo/tcpdf/fonts/dejavusansbi.z deleted file mode 100644 index ff50412f166db8dc30dd0a2aa0af3a70b0baabca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 326692 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

    O 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

    n4X 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 z

    }7$^GWYo!od% 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 z
    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⪯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
    dGEx5;)9urPs$IO5)ORfX}HPA<$1vQ#O4qYM~ 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 diff --git a/lib/combodo/tcpdf/fonts/dejavusansextralight.ctg.z b/lib/combodo/tcpdf/fonts/dejavusansextralight.ctg.z deleted file mode 100644 index d5fff04b70447a9468fac81266618fbb3b08d4c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3989 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 diff --git a/lib/combodo/tcpdf/fonts/dejavusansextralight.php b/lib/combodo/tcpdf/fonts/dejavusansextralight.php deleted file mode 100644 index f916c3355..000000000 --- a/lib/combodo/tcpdf/fonts/dejavusansextralight.php +++ /dev/null @@ -1,16 +0,0 @@ -32,'FontBBox'=>'[-733 -269 1659 1104]','ItalicAngle'=>0,'Ascent'=>928,'Descent'=>-236,'Leading'=>0,'CapHeight'=>729,'XHeight'=>547,'StemV'=>17,'StemH'=>7,'AvgWidth'=>506,'MaxWidth'=>1735,'MissingWidth'=>600); -$cbbox=array(0=>array(50,-177,550,705),33=>array(177,0,224,729),34=>array(113,458,345,729),35=>array(77,0,761,718),36=>array(83,-147,556,760),37=>array(74,-14,875,742),38=>array(86,-14,718,742),39=>array(113,458,160,729),40=>array(109,-132,287,760),41=>array(109,-132,287,760),42=>array(37,286,461,742),43=>array(106,0,732,627),44=>array(114,-116,183,62),45=>array(49,254,312,294),46=>array(134,0,184,62),47=>array(16,-93,321,729),48=>array(89,-15,543,742),49=>array(110,0,520,729),50=>array(69,0,536,742),51=>array(76,-14,531,742),52=>array(49,0,556,729),53=>array(99,-14,525,729),54=>array(97,-14,549,742),55=>array(82,0,525,729),56=>array(94,-14,542,742),57=>array(97,-14,549,742),58=>array(144,0,193,480),59=>array(125,-116,193,480),60=>array(106,64,732,560),61=>array(106,215,732,412),62=>array(106,64,732,560),63=>array(76,0,439,742),64=>array(108,-186,917,708),65=>array(30,0,651,729),66=>array(123,0,587,729),67=>array(83,-14,644,742),68=>array(122,0,687,729),69=>array(122,0,542,729),70=>array(122,0,492,729),71=>array(83,-14,668,742),72=>array(122,0,628,729),73=>array(121,0,172,729),74=>array(5,-178,171,729),75=>array(173,0,644,729),76=>array(122,0,526,729),77=>array(161,0,702,729),78=>array(121,0,596,729),79=>array(82,-14,706,742),80=>array(122,0,542,729),81=>array(82,-129,706,742),82=>array(123,0,641,729),83=>array(89,-14,553,742),84=>array(22,0,589,729),85=>array(112,-14,620,729),86=>array(30,0,651,729),87=>array(69,0,895,729),88=>array(59,0,629,729),89=>array(22,0,587,729),90=>array(45,0,640,729),91=>array(113,-132,280,760),92=>array(16,-93,321,729),93=>array(113,-132,280,760),94=>array(125,457,713,729),95=>array(-10,-236,510,-198),96=>array(100,617,299,800),97=>array(82,-14,500,560),98=>array(114,-14,555,760),99=>array(68,-14,488,560),100=>array(114,-14,555,760),101=>array(79,-14,540,560),102=>array(45,0,349,760),103=>array(81,-208,521,560),104=>array(113,0,526,760),105=>array(112,0,157,760),106=>array(-18,-208,162,760),107=>array(159,0,547,760),108=>array(113,0,158,760),109=>array(113,0,868,560),110=>array(113,0,526,560),111=>array(79,-17,532,560),112=>array(114,-208,555,560),113=>array(114,-208,555,560),114=>array(114,0,410,560),115=>array(75,-14,449,560),116=>array(50,0,346,702),117=>array(113,-13,526,547),118=>array(63,0,528,547),119=>array(63,0,726,547),120=>array(56,0,536,547),121=>array(54,-189,538,547),122=>array(43,0,482,547),123=>array(169,-163,431,760),124=>array(146,-236,193,764),125=>array(169,-163,431,760),126=>array(106,250,732,382),161=>array(177,0,224,729),162=>array(109,-153,527,699),163=>array(63,0,548,742),164=>array(60,54,577,573),165=>array(62,0,574,729),166=>array(142,-171,190,699),167=>array(46,-85,446,742),168=>array(159,699,342,758),169=>array(138,0,862,725),170=>array(68,249,404,742),171=>array(94,86,535,500),172=>array(105,141,716,399),173=>array(49,254,312,294),174=>array(138,0,862,725),175=>array(104,702,396,745),176=>array(116,451,384,720),177=>array(105,0,732,627),178=>array(46,358,338,742),179=>array(48,345,340,742),180=>array(181,616,380,800),181=>array(107,-208,618,547),182=>array(84,-96,516,729),183=>array(133,306,184,367),184=>array(142,-188,333,0),185=>array(67,359,346,729),186=>array(63,249,408,742),187=>array(94,86,535,500),188=>array(67,-14,923,742),189=>array(67,-14,906,742),190=>array(48,-14,923,742),191=>array(76,-14,439,728),192=>array(30,0,651,927),193=>array(30,0,651,927),194=>array(30,0,651,928),195=>array(30,0,651,914),196=>array(30,0,651,913),197=>array(30,0,651,920),198=>array(27,0,910,729),199=>array(83,-188,644,742),200=>array(122,0,542,927),201=>array(122,0,542,927),202=>array(122,0,542,928),203=>array(122,0,542,913),204=>array(47,0,199,927),205=>array(95,0,246,927),206=>array(7,0,288,928),207=>array(56,0,239,913),208=>array(5,0,687,729),209=>array(121,0,596,914),210=>array(82,-14,706,927),211=>array(82,-14,706,927),212=>array(82,-14,706,928),213=>array(82,-14,706,914),214=>array(82,-14,706,913),215=>array(161,54,677,573),216=>array(59,-29,730,754),217=>array(112,-14,620,927),218=>array(112,-14,620,927),219=>array(112,-14,620,928),220=>array(112,-14,620,913),221=>array(22,0,587,927),222=>array(122,0,543,729),223=>array(133,-14,576,760),224=>array(82,-14,500,800),225=>array(82,-14,500,800),226=>array(82,-14,500,800),227=>array(82,-14,500,767),228=>array(82,-14,500,758),229=>array(82,-14,500,864),230=>array(82,-14,914,561),231=>array(68,-188,488,560),232=>array(79,-14,540,800),233=>array(79,-14,540,800),234=>array(79,-14,540,800),235=>array(79,-14,540,758),236=>array(-11,0,188,800),237=>array(70,0,270,800),238=>array(-0,0,280,800),239=>array(48,0,231,758),240=>array(79,-14,531,760),241=>array(113,0,526,767),242=>array(79,-17,532,800),243=>array(79,-17,532,800),244=>array(79,-17,532,800),245=>array(79,-17,532,767),246=>array(79,-17,532,758),247=>array(105,73,732,554),248=>array(39,-42,569,589),249=>array(113,-13,526,800),250=>array(113,-13,526,800),251=>array(113,-13,526,800),252=>array(113,-13,526,758),253=>array(54,-189,538,800),254=>array(114,-208,555,760),255=>array(54,-189,538,758),256=>array(30,0,651,899),257=>array(82,-14,500,745),258=>array(30,0,651,946),259=>array(82,-14,500,765),260=>array(30,-188,726,729),261=>array(82,-188,604,560),262=>array(83,-14,644,927),263=>array(68,-14,488,800),264=>array(83,-14,644,928),265=>array(68,-14,488,800),266=>array(83,-14,644,876),267=>array(68,-14,488,722),268=>array(83,-14,644,928),269=>array(68,-14,488,800),270=>array(122,0,687,938),271=>array(114,-14,707,760),272=>array(5,0,687,729),273=>array(79,-14,596,760),274=>array(122,0,542,900),275=>array(79,-14,540,745),276=>array(122,0,542,928),277=>array(79,-14,540,785),278=>array(122,0,542,876),279=>array(79,-14,540,722),280=>array(122,-188,589,729),281=>array(79,-188,548,560),282=>array(122,0,542,925),283=>array(79,-14,540,797),284=>array(83,-14,668,928),285=>array(81,-208,521,800),286=>array(83,-14,668,928),287=>array(81,-208,521,785),288=>array(83,-14,668,876),289=>array(81,-208,521,722),290=>array(83,-250,668,742),291=>array(81,-208,521,775),292=>array(122,0,628,928),293=>array(-5,0,526,928),294=>array(121,0,791,729),295=>array(70,0,556,760),296=>array(2,0,291,914),297=>array(-7,0,284,767),298=>array(1,0,293,899),299=>array(-7,0,285,745),300=>array(-5,0,300,928),301=>array(-14,0,292,785),302=>array(97,-188,288,729),303=>array(84,-188,275,760),304=>array(121,0,172,876),305=>array(112,0,157,547),306=>array(121,-178,466,729),307=>array(112,-208,439,760),308=>array(5,-178,287,928),309=>array(-18,-208,280,800),310=>array(173,-235,644,729),311=>array(159,-235,547,760),312=>array(111,0,576,547),313=>array(122,0,526,928),314=>array(113,0,267,928),315=>array(122,-235,526,729),316=>array(82,-235,181,760),317=>array(122,0,526,730),318=>array(113,0,350,761),319=>array(122,0,526,729),320=>array(113,0,288,760),321=>array(-2,0,526,729),322=>array(6,0,279,760),323=>array(121,0,596,928),324=>array(113,0,526,803),325=>array(121,-235,596,729),326=>array(113,-235,526,560),327=>array(121,0,596,921),328=>array(113,0,526,800),329=>array(127,0,693,729),330=>array(131,-178,606,729),331=>array(113,-198,526,560),332=>array(82,-14,706,899),333=>array(79,-17,532,745),334=>array(82,-14,706,928),335=>array(79,-17,532,785),336=>array(82,-14,706,927),337=>array(79,-17,532,800),338=>array(82,0,977,729),339=>array(79,-17,948,561),340=>array(123,0,641,928),341=>array(114,0,413,803),342=>array(123,-235,641,729),343=>array(79,-235,410,560),344=>array(123,0,641,921),345=>array(114,0,410,800),346=>array(89,-14,553,928),347=>array(75,-14,449,803),348=>array(89,-14,553,928),349=>array(75,-14,449,800),350=>array(89,-188,553,742),351=>array(75,-188,449,560),352=>array(89,-14,553,928),353=>array(75,-14,449,800),354=>array(22,-188,589,729),355=>array(50,-188,346,702),356=>array(22,0,589,921),357=>array(50,0,349,814),358=>array(22,0,589,729),359=>array(50,0,346,702),360=>array(112,-14,620,914),361=>array(113,-13,526,767),362=>array(112,-14,620,899),363=>array(113,-13,526,745),364=>array(112,-14,620,928),365=>array(113,-13,526,785),366=>array(112,-14,620,920),367=>array(113,-13,526,835),368=>array(112,-14,620,927),369=>array(113,-13,527,800),370=>array(112,-196,620,729),371=>array(113,-188,633,547),372=>array(69,0,895,932),373=>array(63,0,726,803),374=>array(22,0,587,932),375=>array(54,-189,538,803),376=>array(22,0,587,913),377=>array(45,0,640,928),378=>array(43,0,482,803),379=>array(45,0,640,867),380=>array(43,0,482,722),381=>array(45,0,640,928),382=>array(43,0,482,800),383=>array(45,0,349,760),384=>array(70,-14,555,760),385=>array(-48,0,587,729),386=>array(123,0,587,729),387=>array(114,-14,555,760),390=>array(83,-14,644,742),391=>array(83,-14,779,882),392=>array(68,-14,623,719),393=>array(5,0,687,729),394=>array(-49,0,687,729),395=>array(123,0,587,729),396=>array(114,-14,555,760),397=>array(76,-209,534,547),398=>array(122,0,542,729),399=>array(82,-14,706,742),400=>array(76,-14,531,742),401=>array(5,-178,492,729),402=>array(-3,-208,349,760),403=>array(83,-14,786,882),404=>array(91,-210,612,661),405=>array(113,0,863,760),406=>array(121,0,347,729),407=>array(24,0,271,729),408=>array(173,0,736,729),409=>array(112,0,500,760),410=>array(4,0,271,760),412=>array(113,-13,868,729),413=>array(5,-178,596,729),414=>array(113,-208,526,560),415=>array(82,-14,706,742),416=>array(76,-14,772,758),417=>array(82,-17,677,573),418=>array(82,-14,827,742),419=>array(79,-208,668,560),420=>array(-49,0,542,729),421=>array(114,-208,555,760),422=>array(123,-129,641,729),423=>array(89,-14,553,742),424=>array(75,-14,449,560),425=>array(98,0,568,729),427=>array(50,-208,346,702),428=>array(24,0,589,729),429=>array(50,0,346,760),430=>array(22,-178,589,729),431=>array(109,-4,797,760),432=>array(114,-13,699,573),433=>array(57,-15,707,729),434=>array(121,0,657,729),435=>array(22,0,716,729),436=>array(54,-189,674,560),437=>array(45,0,640,729),438=>array(43,0,482,547),448=>array(123,-208,172,729),449=>array(123,-208,370,729),450=>array(27,-208,434,729),451=>array(124,0,171,729),452=>array(122,0,1352,928),453=>array(122,0,1211,800),454=>array(114,-14,1071,800),455=>array(122,-178,742,729),456=>array(122,-208,711,760),457=>array(113,-208,344,760),458=>array(121,-178,842,729),459=>array(121,-208,817,760),460=>array(113,-208,711,760),461=>array(30,0,651,928),462=>array(82,-14,500,800),463=>array(7,0,288,928),464=>array(0,0,281,800),465=>array(82,-14,706,928),466=>array(79,-17,532,800),467=>array(112,-14,620,928),468=>array(113,-13,526,800),469=>array(112,-14,620,1025),470=>array(113,-13,526,899),471=>array(112,-14,620,1044),472=>array(113,-13,526,892),473=>array(112,-14,620,1044),474=>array(113,-13,526,892),475=>array(112,-14,620,1047),476=>array(113,-13,526,892),477=>array(79,-14,540,560),478=>array(30,0,651,1025),479=>array(82,-14,500,899),480=>array(30,0,651,1025),481=>array(82,-14,500,869),482=>array(27,0,910,900),483=>array(82,-14,914,743),484=>array(83,-14,752,742),485=>array(81,-208,598,560),486=>array(83,-14,668,928),487=>array(81,-208,521,798),488=>array(63,0,644,928),489=>array(42,0,547,928),490=>array(82,-196,706,742),491=>array(79,-196,532,560),492=>array(82,-196,706,899),493=>array(79,-196,532,745),496=>array(-18,-208,281,800),497=>array(122,0,1352,729),498=>array(122,0,1211,729),499=>array(114,-14,1071,760),500=>array(83,-14,668,928),501=>array(81,-208,521,798),504=>array(121,0,596,927),505=>array(113,0,526,799),506=>array(30,0,651,1000),507=>array(82,-14,611,1026),508=>array(27,0,910,928),509=>array(82,-14,914,798),510=>array(59,-29,730,928),511=>array(39,-42,569,798),512=>array(30,0,651,930),513=>array(82,-14,500,799),514=>array(30,0,651,901),515=>array(82,-14,500,785),516=>array(122,0,542,930),517=>array(79,-14,540,798),518=>array(122,0,542,901),519=>array(79,-14,540,785),520=>array(-29,0,287,930),521=>array(-13,0,299,798),522=>array(2,0,308,901),523=>array(-14,0,292,785),524=>array(82,-14,706,930),525=>array(79,-17,532,799),526=>array(82,-14,706,901),527=>array(79,-17,532,785),528=>array(112,0,641,930),529=>array(81,0,410,798),530=>array(123,0,641,901),531=>array(114,0,421,785),532=>array(112,-14,620,930),533=>array(113,-13,526,799),534=>array(112,-14,620,901),535=>array(113,-13,526,785),536=>array(89,-240,553,742),537=>array(75,-240,449,560),538=>array(22,-240,589,729),539=>array(50,-240,346,702),542=>array(122,0,628,928),543=>array(0,0,526,928),548=>array(45,-206,640,729),549=>array(43,-208,482,547),550=>array(30,0,651,878),551=>array(82,-14,500,723),552=>array(122,-188,542,729),553=>array(79,-188,540,560),554=>array(82,-14,706,1025),555=>array(79,-17,532,899),556=>array(82,-14,706,1025),557=>array(79,-17,532,864),558=>array(82,-14,706,876),559=>array(79,-17,532,722),560=>array(82,-14,706,1025),561=>array(79,-17,532,899),562=>array(22,0,587,899),563=>array(54,-189,538,745),567=>array(-18,-208,162,547),568=>array(114,-14,952,760),569=>array(114,-208,952,560),581=>array(30,0,651,729),584=>array(5,-178,290,729),585=>array(-18,-208,264,760),587=>array(114,-208,690,560),588=>array(5,0,641,729),589=>array(8,0,410,560),592=>array(87,-14,505,560),593=>array(114,-14,555,560),594=>array(114,-14,555,560),595=>array(114,-14,555,760),596=>array(68,-14,488,560),598=>array(114,-208,690,760),599=>array(114,-14,690,760),600=>array(79,-14,540,560),601=>array(79,-14,540,560),603=>array(89,-14,473,561),604=>array(89,-14,473,561),607=>array(-18,-208,264,547),608=>array(81,-208,656,719),609=>array(81,-208,521,547),611=>array(126,-210,576,547),613=>array(113,-208,526,547),614=>array(113,0,526,760),615=>array(113,-208,526,760),616=>array(10,0,268,760),617=>array(114,0,271,547),618=>array(57,0,314,547),621=>array(114,-208,271,760),623=>array(113,-13,868,547),624=>array(113,-208,868,547),625=>array(113,-208,868,560),626=>array(-21,-208,526,560),627=>array(113,-208,661,560),628=>array(114,0,523,547),629=>array(79,-17,532,560),632=>array(81,-208,579,754),633=>array(0,-13,296,547),634=>array(0,-13,296,755),635=>array(0,-208,432,547),636=>array(114,-207,410,560),637=>array(114,-208,410,560),638=>array(64,0,437,560),639=>array(94,0,466,560),640=>array(48,0,482,547),641=>array(48,0,482,547),642=>array(75,-208,449,560),643=>array(-3,-208,349,760),645=>array(38,-208,390,547),647=>array(50,-155,346,547),648=>array(50,-208,346,702),649=>array(57,-13,586,547),650=>array(55,-15,564,547),651=>array(114,0,496,547),652=>array(63,0,528,547),653=>array(63,0,726,547),654=>array(54,0,538,736),656=>array(43,-208,593,547),665=>array(113,0,506,547),668=>array(113,0,541,547),670=>array(132,-212,520,548),671=>array(125,0,481,560),672=>array(114,-208,718,760),675=>array(78,-14,946,760),678=>array(69,0,752,702),679=>array(50,-208,623,760),681=>array(45,-198,782,760),682=>array(113,0,634,760),683=>array(113,0,585,760),686=>array(0,-208,548,760),687=>array(0,-208,683,760),699=>array(114,499,183,729),700=>array(114,499,183,729),702=>array(57,492,191,760),710=>array(110,616,391,800),711=>array(110,616,391,800),713=>array(104,702,396,745),714=>array(181,616,380,800),715=>array(100,617,299,800),717=>array(104,-127,396,-84),718=>array(100,-235,299,-53),719=>array(181,-236,380,-53),728=>array(97,645,403,785),729=>array(228,658,272,722),730=>array(130,624,370,864),731=>array(173,-188,364,0),732=>array(104,650,395,767),733=>array(130,615,441,800),741=>array(104,0,372,668),742=>array(104,0,372,668),743=>array(104,0,372,668),744=>array(104,0,372,668),745=>array(104,0,372,668),755=>array(130,-238,370,3),759=>array(104,-170,395,-54),768=>array(-401,617,-202,800),769=>array(-320,616,-121,800),770=>array(-391,616,-110,800),771=>array(-397,650,-106,767),772=>array(-394,702,-102,745),773=>array(-510,686,10,724),774=>array(-407,645,-101,785),775=>array(-268,658,-223,722),776=>array(-342,699,-159,758),777=>array(-340,618,-161,847),778=>array(-371,624,-131,864),779=>array(-368,615,-57,800),780=>array(-388,616,-107,800),781=>array(-271,615,-229,832),782=>array(-383,615,-117,832),783=>array(-438,615,-126,800),784=>array(-407,645,-101,819),785=>array(-407,645,-101,785),786=>array(-210,489,-110,645),787=>array(-278,635,-187,844),788=>array(-305,635,-213,844),789=>array(-48,575,42,760),790=>array(-401,-266,-202,-83),791=>array(-320,-267,-121,-83),795=>array(-123,382,65,573),803=>array(-272,-184,-228,-120),804=>array(-342,-143,-159,-84),805=>array(-355,-241,-146,-32),806=>array(-308,-240,-209,-84),807=>array(-358,-188,-167,0),808=>array(-327,-188,-136,0),812=>array(-388,-269,-107,-85),813=>array(-391,-267,-110,-83),814=>array(-407,-222,-101,-82),815=>array(-407,-224,-101,-83),816=>array(-397,-211,-106,-95),817=>array(-394,-127,-102,-84),818=>array(-510,-236,10,-198),819=>array(-510,-236,10,-41),820=>array(-557,240,-41,343),821=>array(-317,266,-60,306),822=>array(-635,266,0,306),823=>array(-568,-42,-38,589),824=>array(-733,-29,-63,754),831=>array(-510,528,10,724),856=>array(-272,658,-228,722),860=>array(-446,-237,445,-59),861=>array(-446,802,445,980),865=>array(-446,751,446,929),880=>array(122,0,579,729),881=>array(114,0,497,547),882=>array(123,0,739,729),883=>array(121,0,527,729),884=>array(78,557,203,800),885=>array(78,-208,203,35),886=>array(123,0,632,729),887=>array(113,0,545,547),890=>array(210,-208,300,-45),891=>array(68,-14,488,560),892=>array(68,-14,488,560),893=>array(68,-14,488,560),894=>array(125,-116,193,480),900=>array(181,616,380,800),901=>array(159,699,380,978),902=>array(30,0,651,800),903=>array(133,306,184,367),904=>array(-12,0,657,800),905=>array(-6,0,739,800),906=>array(-9,0,286,800),908=>array(-7,-14,725,800),910=>array(-15,0,795,800),911=>array(-18,0,733,800),912=>array(57,0,279,978),913=>array(30,0,651,729),914=>array(123,0,587,729),915=>array(122,0,552,729),916=>array(30,0,651,729),917=>array(122,0,542,729),918=>array(45,0,640,729),919=>array(122,0,628,729),920=>array(82,-14,706,742),921=>array(121,0,172,729),922=>array(173,0,644,729),923=>array(30,0,651,729),924=>array(161,0,702,729),925=>array(121,0,596,729),926=>array(98,0,548,729),927=>array(82,-14,706,742),928=>array(123,0,629,729),929=>array(122,0,542,729),931=>array(98,0,568,729),932=>array(22,0,589,729),933=>array(22,0,587,729),934=>array(83,0,711,729),935=>array(59,0,629,729),936=>array(82,0,706,729),937=>array(57,0,707,744),938=>array(56,0,239,913),939=>array(22,0,587,913),940=>array(80,-12,596,800),941=>array(89,-14,473,800),942=>array(113,-208,526,800),943=>array(90,0,290,800),944=>array(96,0,498,978),945=>array(80,-12,596,559),946=>array(116,-208,542,760),947=>array(16,-208,539,547),948=>array(76,-14,534,742),949=>array(89,-14,473,561),950=>array(67,-210,496,760),951=>array(113,-208,526,560),952=>array(79,-11,534,768),953=>array(114,0,271,547),954=>array(113,0,530,547),955=>array(54,0,538,736),956=>array(107,-208,618,547),957=>array(67,0,491,547),958=>array(68,-210,479,760),959=>array(79,-17,532,560),960=>array(36,-14,574,547),961=>array(113,-208,555,560),962=>array(68,-210,488,560),963=>array(81,-14,581,547),964=>array(59,0,542,547),965=>array(96,0,498,547),966=>array(81,-208,579,556),967=>array(29,-208,549,547),968=>array(74,-208,583,547),969=>array(90,-14,735,547),970=>array(57,0,279,758),971=>array(96,0,498,758),972=>array(79,-17,532,800),973=>array(96,0,498,800),974=>array(90,-14,735,800),975=>array(173,-208,644,729),981=>array(81,-208,579,754),982=>array(56,-14,769,547),984=>array(82,-207,706,742),985=>array(79,-207,532,560),988=>array(122,0,492,729),1009=>array(113,-208,555,560),1010=>array(68,-14,488,560),1011=>array(-18,-208,162,760),1012=>array(82,-14,706,742),1013=>array(68,-14,480,560),1014=>array(95,-14,507,560),1015=>array(122,0,543,729),1016=>array(114,-208,555,760),1017=>array(83,-14,644,742),1020=>array(42,-208,555,560),1021=>array(83,-14,644,742),1022=>array(83,-14,644,742),1023=>array(83,-14,644,742),1024=>array(122,0,542,927),1025=>array(122,0,542,898),1026=>array(21,-178,684,729),1027=>array(122,0,552,927),1028=>array(83,-14,644,742),1029=>array(89,-14,553,742),1030=>array(121,0,172,729),1031=>array(56,0,239,913),1032=>array(5,-178,171,729),1033=>array(51,-14,996,729),1034=>array(122,0,947,729),1035=>array(21,0,684,729),1036=>array(123,0,616,927),1037=>array(123,0,632,927),1038=>array(44,-14,565,928),1039=>array(123,-157,629,729),1040=>array(30,0,651,729),1041=>array(123,0,587,729),1042=>array(123,0,587,729),1043=>array(122,0,552,729),1044=>array(80,-157,696,729),1045=>array(122,0,542,729),1046=>array(58,0,982,729),1047=>array(76,-14,565,742),1048=>array(123,0,632,729),1049=>array(123,0,632,928),1050=>array(123,0,616,729),1051=>array(51,-14,628,729),1052=>array(161,0,702,729),1053=>array(122,0,628,729),1054=>array(82,-14,706,742),1055=>array(123,0,629,729),1056=>array(122,0,542,729),1057=>array(83,-14,644,742),1058=>array(22,0,589,729),1059=>array(44,-14,565,729),1060=>array(93,0,767,729),1061=>array(59,0,629,729),1062=>array(122,-157,696,729),1063=>array(116,0,568,729),1064=>array(122,0,946,729),1065=>array(122,-157,1014,729),1066=>array(25,0,737,729),1067=>array(123,0,759,729),1068=>array(123,0,587,729),1069=>array(83,-14,644,742),1070=>array(121,-14,949,742),1071=>array(84,0,571,729),1072=>array(82,-14,500,560),1073=>array(79,-17,532,777),1074=>array(113,0,506,547),1075=>array(120,0,452,547),1076=>array(73,-138,607,547),1077=>array(79,-14,540,560),1078=>array(63,0,845,547),1079=>array(89,-14,473,561),1080=>array(113,0,545,547),1081=>array(113,0,545,760),1082=>array(113,0,530,547),1083=>array(47,-14,538,547),1084=>array(137,0,617,547),1085=>array(113,0,541,547),1086=>array(79,-17,532,560),1087=>array(113,0,541,547),1088=>array(114,-208,555,560),1089=>array(68,-14,488,560),1090=>array(34,0,515,547),1091=>array(54,-189,538,547),1092=>array(74,-208,781,760),1093=>array(56,0,536,547),1094=>array(112,-138,610,547),1095=>array(97,0,477,547),1096=>array(112,0,800,547),1097=>array(112,-138,868,547),1098=>array(41,0,643,547),1099=>array(113,0,649,547),1100=>array(113,0,506,547),1101=>array(68,-14,479,560),1102=>array(112,-14,734,563),1103=>array(66,0,479,547),1104=>array(79,-14,540,802),1105=>array(79,-14,540,722),1106=>array(41,-208,536,760),1107=>array(120,0,452,803),1108=>array(68,-14,479,560),1109=>array(75,-14,449,560),1110=>array(112,0,157,760),1111=>array(48,0,231,758),1112=>array(-18,-208,162,760),1113=>array(47,-14,818,547),1114=>array(114,0,818,547),1115=>array(41,0,544,760),1116=>array(113,0,530,803),1117=>array(113,0,545,802),1118=>array(54,-189,538,760),1119=>array(116,-138,546,547),1121=>array(90,-14,735,547),1122=>array(20,0,669,729),1123=>array(15,0,583,760),1124=>array(121,-14,890,742),1125=>array(112,-14,688,560),1136=>array(82,0,706,729),1137=>array(74,-208,583,547),1138=>array(82,-14,706,742),1168=>array(122,0,526,879),1169=>array(120,0,452,701),1176=>array(76,-188,565,742),1177=>array(89,-188,473,561),1184=>array(11,0,763,729),1185=>array(22,0,648,547),1188=>array(122,0,1008,729),1189=>array(114,0,829,547),1194=>array(83,-188,644,742),1195=>array(68,-188,488,560),1198=>array(22,0,587,729),1199=>array(54,-211,538,547),1204=>array(22,-157,885,729),1205=>array(22,-138,761,547),1210=>array(116,0,568,729),1211=>array(113,0,526,760),1216=>array(113,0,158,760),1217=>array(58,0,982,928),1218=>array(63,0,845,785),1223=>array(122,-208,628,729),1224=>array(113,-208,541,547),1232=>array(30,0,651,946),1233=>array(82,-14,500,765),1234=>array(30,0,651,913),1235=>array(82,-14,500,758),1236=>array(27,0,910,729),1237=>array(82,-14,914,561),1238=>array(122,0,542,928),1239=>array(79,-14,540,785),1240=>array(82,-14,706,742),1241=>array(79,-14,540,560),1242=>array(82,-14,706,913),1243=>array(79,-14,540,758),1244=>array(58,0,982,913),1245=>array(63,0,845,758),1246=>array(76,-14,565,913),1247=>array(89,-14,473,758),1250=>array(123,0,632,899),1251=>array(113,0,545,745),1252=>array(123,0,632,913),1253=>array(113,0,545,758),1254=>array(82,-14,706,913),1255=>array(79,-17,532,758),1256=>array(82,-14,706,742),1257=>array(79,-17,532,560),1258=>array(82,-14,706,913),1259=>array(79,-17,532,758),1260=>array(83,-14,644,913),1261=>array(68,-14,479,758),1262=>array(44,-14,565,899),1263=>array(54,-189,538,745),1264=>array(44,-14,565,913),1265=>array(54,-189,538,758),1266=>array(44,-14,565,927),1267=>array(54,-189,538,800),1268=>array(116,0,568,913),1269=>array(97,0,477,758),1272=>array(123,0,759,913),1273=>array(113,0,649,758),1278=>array(59,0,629,729),1279=>array(56,0,536,547),1280=>array(99,0,563,729),1281=>array(83,0,477,547),1296=>array(76,-14,531,742),1297=>array(89,-14,473,561),1298=>array(51,-208,628,729),1299=>array(47,-208,538,547),1300=>array(51,-14,1113,729),1301=>array(47,-14,938,547),1306=>array(82,-129,706,742),1307=>array(114,-208,555,560),1308=>array(69,0,895,729),1309=>array(63,0,726,547),1329=>array(112,-29,719,729),1330=>array(112,0,634,743),1331=>array(73,0,716,743),1332=>array(78,0,731,743),1333=>array(112,-14,634,729),1334=>array(103,0,676,743),1335=>array(112,0,596,729),1336=>array(112,0,634,743),1337=>array(112,-15,853,743),1338=>array(78,-14,721,729),1339=>array(112,0,620,729),1340=>array(122,0,526,729),1341=>array(112,-14,929,729),1342=>array(119,-14,781,743),1343=>array(111,0,620,729),1344=>array(44,-12,591,729),1345=>array(93,-21,666,743),1346=>array(78,0,731,743),1347=>array(59,0,746,740),1348=>array(112,-14,765,729),1349=>array(79,-15,649,744),1350=>array(24,-14,677,729),1351=>array(103,-15,677,729),1352=>array(112,0,620,743),1353=>array(88,-15,660,743),1354=>array(73,0,777,743),1355=>array(107,0,685,743),1356=>array(112,0,783,743),1357=>array(112,-14,620,729),1358=>array(78,0,731,729),1359=>array(87,-15,649,744),1360=>array(112,0,620,743),1361=>array(79,-15,649,744),1362=>array(112,0,563,729),1363=>array(78,0,706,729),1364=>array(73,0,669,743),1365=>array(82,-14,706,742),1366=>array(83,-11,711,729),1370=>array(114,499,183,729),1371=>array(17,670,216,853),1372=>array(2,669,346,925),1373=>array(5,670,205,853),1374=>array(16,666,358,872),1375=>array(0,702,366,745),1377=>array(113,-13,868,547),1378=>array(113,-208,526,560),1379=>array(78,-208,678,560),1380=>array(113,-208,718,560),1381=>array(113,-13,526,760),1382=>array(78,-208,677,560),1383=>array(113,0,526,760),1384=>array(113,-208,526,560),1385=>array(113,-208,796,560),1386=>array(78,-13,678,760),1387=>array(113,-208,526,760),1388=>array(113,-208,355,547),1389=>array(113,-208,799,760),1390=>array(79,-17,532,774),1391=>array(113,-208,526,760),1392=>array(113,0,526,760),1393=>array(74,-13,509,760),1394=>array(113,-208,687,560),1395=>array(68,-13,537,789),1396=>array(113,-13,695,760),1397=>array(-18,-208,162,547),1398=>array(0,-13,556,760),1399=>array(62,-208,483,562),1400=>array(113,0,526,560),1401=>array(30,-208,359,563),1402=>array(113,-208,868,547),1403=>array(56,-208,502,562),1404=>array(113,0,602,560),1405=>array(113,-13,526,547),1406=>array(113,-208,676,760),1407=>array(113,-13,895,560),1408=>array(113,-208,526,560),1409=>array(81,-208,521,560),1410=>array(113,0,453,547),1411=>array(113,-208,895,760),1412=>array(59,-208,571,560),1413=>array(79,-17,532,560),1414=>array(69,-208,826,760),1415=>array(113,-13,812,760),1417=>array(144,0,193,480),1418=>array(49,208,312,294),1652=>array(67,810,234,1048),4304=>array(49,0,420,550),4305=>array(49,0,420,770),4306=>array(49,-222,469,511),4307=>array(49,-222,677,511),4308=>array(49,-222,420,511),4309=>array(49,-222,419,511),4310=>array(39,0,419,770),4311=>array(49,0,661,511),4312=>array(49,5,419,511),4313=>array(49,-222,420,510),4314=>array(49,-222,921,513),4315=>array(49,0,420,770),4316=>array(59,0,430,764),4317=>array(49,5,694,511),4318=>array(49,0,420,770),4319=>array(49,-222,420,524),4320=>array(49,5,705,771),4321=>array(59,0,430,770),4322=>array(49,-222,529,604),4323=>array(17,-222,418,511),4324=>array(68,-222,671,511),4325=>array(49,-222,419,770),4326=>array(49,-222,694,511),4327=>array(49,-222,420,506),4328=>array(49,0,420,770),4329=>array(59,5,430,770),4330=>array(49,-222,464,511),4331=>array(49,0,420,770),4332=>array(59,0,430,770),4333=>array(49,-222,419,770),4334=>array(59,0,430,770),4335=>array(49,-222,420,551),4336=>array(49,0,419,770),4337=>array(49,0,419,770),4338=>array(49,-78,420,511),4339=>array(49,-222,420,510),4340=>array(49,-222,420,769),4341=>array(49,0,476,770),4342=>array(49,-222,706,511),4343=>array(49,-222,468,511),4344=>array(49,-222,420,506),4345=>array(49,-222,470,511),4346=>array(49,-37,403,511),4347=>array(49,24,367,486),4348=>array(49,370,255,760),5760=>array(-10,267,487,307),5761=>array(-10,-125,502,307),5762=>array(-10,-125,722,307),5763=>array(-10,-125,941,307),5764=>array(-10,-125,1160,307),5765=>array(-10,-125,1379,307),5766=>array(-10,267,502,697),5767=>array(-10,267,722,697),5768=>array(-10,267,941,697),5769=>array(-10,267,1160,697),5770=>array(-10,267,1379,697),5771=>array(-10,-125,508,697),5772=>array(-10,-125,728,697),5773=>array(-10,-125,948,697),5774=>array(-10,-125,1168,697),5775=>array(-10,-125,1389,697),5776=>array(-10,41,502,533),5777=>array(-10,41,722,533),5778=>array(-10,41,939,533),5779=>array(-10,41,1159,533),5780=>array(-10,41,1379,533),5781=>array(-10,-125,508,697),5782=>array(-10,-125,762,697),5783=>array(-10,-83,798,307),5784=>array(-10,-240,1214,307),5785=>array(-10,267,1160,902),5786=>array(-10,103,693,307),5787=>array(55,49,517,523),5788=>array(-10,49,452,523),7426=>array(82,-14,914,561),7428=>array(68,-14,488,560),7433=>array(112,-213,157,547),7435=>array(111,0,576,547),7437=>array(137,0,617,547),7438=>array(113,0,545,547),7439=>array(79,-18,532,559),7440=>array(68,-14,488,560),7441=>array(55,47,632,500),7442=>array(55,57,629,476),7443=>array(31,9,662,540),7444=>array(79,-17,948,561),7446=>array(79,273,532,559),7447=>array(79,-18,533,269),7449=>array(66,0,479,547),7450=>array(66,0,479,547),7456=>array(63,0,528,547),7457=>array(63,0,726,547),7458=>array(43,0,482,547),7462=>array(120,0,452,547),7463=>array(63,0,528,547),7464=>array(113,0,541,547),7467=>array(47,-14,538,547),7543=>array(81,-208,521,560),7680=>array(30,-241,651,729),7681=>array(82,-241,500,560),7682=>array(123,0,587,875),7683=>array(114,-14,555,877),7684=>array(123,-184,587,729),7685=>array(114,-184,555,760),7686=>array(123,-127,587,729),7687=>array(114,-127,555,760),7688=>array(83,-188,644,928),7689=>array(68,-188,488,800),7690=>array(122,0,687,876),7691=>array(114,-14,555,877),7692=>array(122,-184,687,729),7693=>array(114,-184,555,760),7694=>array(122,-127,687,729),7695=>array(114,-127,555,760),7696=>array(122,-188,687,729),7697=>array(114,-188,555,760),7698=>array(122,-240,687,729),7699=>array(114,-240,555,760),7700=>array(122,0,542,1044),7701=>array(79,-14,540,921),7702=>array(122,0,542,1044),7703=>array(79,-14,540,921),7704=>array(122,-240,542,729),7705=>array(79,-240,540,560),7706=>array(122,-170,542,729),7707=>array(79,-170,540,560),7708=>array(122,-188,542,928),7709=>array(79,-188,540,785),7710=>array(122,0,492,876),7711=>array(45,0,349,878),7712=>array(83,-14,668,887),7713=>array(81,-208,521,745),7714=>array(122,0,628,875),7715=>array(113,0,526,877),7716=>array(122,-184,628,729),7717=>array(113,-184,526,760),7718=>array(122,0,628,914),7719=>array(44,0,526,913),7720=>array(8,-189,628,729),7721=>array(0,-189,526,760),7722=>array(122,-222,628,729),7723=>array(113,-222,526,760),7724=>array(15,-170,306,729),7725=>array(-7,-170,284,760),7726=>array(57,0,272,1044),7727=>array(47,0,263,886),7728=>array(173,0,644,928),7729=>array(116,0,547,928),7730=>array(173,-184,644,729),7731=>array(159,-184,547,760),7732=>array(173,-127,644,729),7733=>array(159,-127,547,760),7734=>array(122,-184,526,729),7735=>array(119,-184,167,760),7736=>array(1,-184,526,927),7737=>array(-1,-184,291,899),7738=>array(122,-127,526,729),7739=>array(-6,-127,286,760),7740=>array(122,-240,526,729),7741=>array(-0,-240,280,760),7742=>array(161,0,702,928),7743=>array(113,0,868,800),7744=>array(161,0,702,876),7745=>array(113,0,868,722),7746=>array(161,-184,702,729),7747=>array(113,-184,868,560),7748=>array(121,0,596,875),7749=>array(113,0,526,722),7750=>array(121,-184,596,729),7751=>array(113,-184,526,560),7752=>array(121,-127,596,729),7753=>array(113,-127,526,560),7754=>array(121,-240,596,729),7755=>array(113,-240,526,560),7756=>array(82,-14,706,1044),7757=>array(79,-17,532,881),7758=>array(82,-14,706,1042),7759=>array(79,-17,532,882),7760=>array(82,-14,706,1044),7761=>array(79,-17,532,921),7762=>array(82,-14,706,1044),7763=>array(79,-17,532,921),7764=>array(122,0,542,928),7765=>array(114,-208,555,800),7766=>array(122,0,542,876),7767=>array(114,-208,555,722),7768=>array(123,0,641,875),7769=>array(114,0,410,722),7770=>array(123,-184,641,729),7771=>array(114,-184,410,560),7772=>array(123,-184,641,899),7773=>array(114,-184,410,745),7774=>array(123,-127,641,729),7775=>array(41,-127,410,560),7776=>array(89,-14,553,876),7777=>array(75,-14,449,722),7778=>array(89,-184,553,742),7779=>array(75,-184,449,560),7780=>array(89,-14,553,928),7781=>array(75,-14,451,800),7782=>array(89,-14,553,1005),7783=>array(75,-14,449,925),7784=>array(89,-184,553,876),7785=>array(75,-184,449,723),7786=>array(22,0,589,876),7787=>array(50,0,346,877),7788=>array(22,-184,589,729),7789=>array(50,-184,346,702),7790=>array(22,-127,589,729),7791=>array(50,-127,390,702),7792=>array(22,-240,589,729),7793=>array(50,-240,379,702),7794=>array(112,-143,620,729),7795=>array(113,-143,526,547),7796=>array(112,-170,620,729),7797=>array(113,-170,526,547),7798=>array(112,-240,620,729),7799=>array(113,-240,526,547),7800=>array(112,-14,620,1044),7801=>array(113,-13,526,990),7802=>array(112,-14,620,1025),7803=>array(113,-13,526,869),7804=>array(30,0,651,926),7805=>array(63,0,528,767),7806=>array(30,-184,651,729),7807=>array(63,-184,528,547),7808=>array(69,0,895,931),7809=>array(63,0,726,802),7810=>array(69,0,895,931),7811=>array(63,0,726,803),7812=>array(69,0,895,913),7813=>array(63,0,726,758),7814=>array(69,0,895,875),7815=>array(63,0,726,722),7816=>array(69,-184,895,729),7817=>array(63,-184,726,547),7818=>array(59,0,629,876),7819=>array(56,0,536,722),7820=>array(59,0,629,913),7821=>array(56,0,536,758),7822=>array(22,0,587,876),7823=>array(54,-189,538,722),7824=>array(45,0,640,928),7825=>array(43,0,482,800),7826=>array(45,-184,640,729),7827=>array(43,-184,482,547),7828=>array(45,-127,640,729),7829=>array(43,-127,482,547),7830=>array(113,-127,526,760),7831=>array(50,0,346,913),7832=>array(63,0,726,864),7833=>array(54,-189,538,864),7834=>array(82,-14,672,760),7835=>array(45,0,349,878),7836=>array(1,0,349,760),7837=>array(45,0,349,760),7838=>array(135,-14,713,743),7839=>array(76,-14,534,742),7840=>array(30,-184,651,729),7841=>array(82,-184,500,560),7842=>array(30,0,651,1029),7843=>array(82,-14,500,847),7844=>array(30,0,651,1028),7845=>array(82,-14,566,846),7846=>array(30,0,651,1028),7847=>array(82,-14,500,847),7848=>array(30,0,651,1081),7849=>array(82,-14,545,899),7850=>array(30,0,651,1050),7851=>array(82,-14,500,868),7852=>array(30,-184,651,928),7853=>array(82,-184,500,800),7854=>array(30,0,651,1044),7855=>array(82,-14,500,877),7856=>array(30,0,651,1044),7857=>array(82,-14,500,877),7858=>array(30,0,651,1104),7859=>array(82,-14,500,938),7860=>array(30,0,651,1037),7861=>array(82,-14,500,870),7862=>array(30,-184,651,946),7863=>array(82,-184,500,765),7864=>array(122,-184,542,729),7865=>array(79,-184,540,560),7866=>array(122,0,542,1029),7867=>array(79,-14,540,847),7868=>array(122,0,542,914),7869=>array(79,-14,540,767),7870=>array(122,0,618,1028),7871=>array(79,-14,594,846),7872=>array(122,0,542,1028),7873=>array(79,-14,540,847),7874=>array(122,0,588,1081),7875=>array(79,-14,574,899),7876=>array(122,0,542,1050),7877=>array(79,-14,540,868),7878=>array(122,-184,542,928),7879=>array(79,-184,540,800),7880=>array(52,0,231,1029),7881=>array(41,0,221,847),7882=>array(121,-184,172,729),7883=>array(112,-184,162,760),7884=>array(82,-184,706,742),7885=>array(79,-184,532,560),7886=>array(82,-14,706,1029),7887=>array(79,-17,532,847),7888=>array(82,-14,706,1028),7889=>array(79,-17,582,846),7890=>array(82,-14,706,1028),7891=>array(79,-17,532,847),7892=>array(82,-14,706,1081),7893=>array(79,-17,561,899),7894=>array(82,-14,706,1050),7895=>array(79,-17,532,868),7896=>array(82,-184,706,928),7897=>array(79,-184,532,800),7898=>array(76,-14,772,927),7899=>array(82,-17,677,800),7900=>array(76,-14,772,927),7901=>array(82,-17,677,800),7902=>array(76,-14,772,1029),7903=>array(82,-17,677,847),7904=>array(76,-14,772,914),7905=>array(82,-17,677,767),7906=>array(76,-184,772,758),7907=>array(82,-184,677,573),7908=>array(112,-184,620,729),7909=>array(113,-184,526,547),7910=>array(112,-14,620,1029),7911=>array(113,-13,526,847),7912=>array(109,-4,797,927),7913=>array(114,-13,699,800),7914=>array(109,-4,797,927),7915=>array(114,-13,699,800),7916=>array(109,-4,797,1029),7917=>array(114,-13,699,847),7918=>array(109,-4,797,914),7919=>array(114,-13,699,767),7920=>array(109,-184,797,760),7921=>array(114,-184,699,573),7922=>array(22,0,587,931),7923=>array(54,-189,538,802),7924=>array(22,-184,587,729),7925=>array(54,-189,538,547),7926=>array(22,0,587,1032),7927=>array(54,-189,538,850),7928=>array(22,0,587,914),7929=>array(54,-189,538,767),7930=>array(122,0,738,729),7931=>array(16,0,462,760),7936=>array(80,-12,596,806),7937=>array(80,-12,596,806),7938=>array(80,-12,596,806),7939=>array(80,-12,596,806),7940=>array(80,-12,596,806),7941=>array(80,-12,596,806),7942=>array(80,-12,596,966),7943=>array(80,-12,596,966),7944=>array(30,0,651,806),7945=>array(30,0,651,806),7946=>array(12,0,844,806),7947=>array(18,0,844,806),7948=>array(13,0,736,806),7949=>array(17,0,768,806),7950=>array(18,0,675,966),7951=>array(17,0,709,966),7952=>array(89,-14,473,806),7953=>array(89,-14,473,806),7954=>array(89,-14,473,806),7955=>array(89,-14,473,806),7956=>array(89,-14,473,806),7957=>array(89,-14,473,806),7960=>array(13,0,622,806),7961=>array(18,0,622,806),7962=>array(12,0,876,806),7963=>array(18,0,885,806),7964=>array(13,0,809,806),7965=>array(17,0,838,806),7968=>array(113,-208,526,806),7969=>array(113,-208,526,806),7970=>array(113,-208,526,806),7971=>array(113,-208,526,806),7972=>array(113,-208,526,806),7973=>array(113,-208,526,806),7974=>array(113,-208,526,966),7975=>array(113,-208,526,966),7976=>array(13,0,713,806),7977=>array(18,0,711,806),7978=>array(12,0,962,806),7979=>array(18,0,965,806),7980=>array(13,0,903,806),7981=>array(17,0,927,806),7982=>array(18,0,810,966),7983=>array(17,0,823,966),7984=>array(85,0,271,806),7985=>array(85,0,271,806),7986=>array(-30,0,322,806),7987=>array(-20,0,329,806),7988=>array(12,0,327,806),7989=>array(-8,0,332,806),7990=>array(-11,0,280,966),7991=>array(-14,0,278,966),7992=>array(13,0,257,806),7993=>array(18,0,251,806),7994=>array(12,0,512,806),7995=>array(18,0,512,806),7996=>array(13,0,447,806),7997=>array(17,0,477,806),7998=>array(18,0,367,966),7999=>array(17,0,370,966),8000=>array(79,-17,532,806),8001=>array(79,-17,532,806),8002=>array(79,-17,532,806),8003=>array(79,-17,532,806),8004=>array(79,-17,532,806),8005=>array(79,-17,532,806),8008=>array(13,-14,723,806),8009=>array(18,-14,767,806),8010=>array(12,-14,1013,806),8011=>array(18,-14,1018,806),8012=>array(13,-14,857,806),8013=>array(17,-14,889,806),8016=>array(96,0,498,806),8017=>array(96,0,498,806),8018=>array(95,0,498,806),8019=>array(92,0,498,806),8020=>array(96,0,498,806),8021=>array(96,0,498,806),8022=>array(96,0,498,966),8023=>array(96,0,498,966),8025=>array(18,0,760,806),8027=>array(18,0,974,806),8029=>array(17,0,989,806),8031=>array(17,0,875,966),8032=>array(90,-14,735,806),8033=>array(90,-14,735,806),8034=>array(90,-14,735,806),8035=>array(90,-14,735,806),8036=>array(90,-14,735,806),8037=>array(90,-14,735,806),8038=>array(90,-14,735,966),8039=>array(90,-14,735,966),8040=>array(13,0,745,806),8041=>array(18,0,786,806),8042=>array(12,0,1032,806),8043=>array(18,0,1038,806),8044=>array(13,0,889,806),8045=>array(17,0,915,806),8046=>array(18,0,864,966),8047=>array(17,0,895,966),8048=>array(80,-12,596,800),8049=>array(80,-12,596,800),8050=>array(89,-14,473,800),8051=>array(89,-14,473,800),8052=>array(113,-208,526,800),8053=>array(113,-208,526,800),8054=>array(-40,0,271,800),8055=>array(90,0,290,800),8056=>array(79,-17,532,800),8057=>array(79,-17,532,800),8058=>array(96,0,498,800),8059=>array(96,0,498,800),8060=>array(90,-14,735,800),8061=>array(90,-14,735,800),8064=>array(80,-208,596,806),8065=>array(80,-208,596,806),8066=>array(80,-208,596,806),8067=>array(80,-208,596,806),8068=>array(80,-208,596,806),8069=>array(80,-208,596,806),8070=>array(80,-208,596,966),8071=>array(80,-208,596,966),8072=>array(30,-208,651,806),8073=>array(30,-208,651,806),8074=>array(12,-208,844,806),8075=>array(18,-208,844,806),8076=>array(13,-208,736,806),8077=>array(17,-208,768,806),8078=>array(18,-208,675,966),8079=>array(17,-208,709,966),8080=>array(113,-208,526,806),8081=>array(113,-208,526,806),8082=>array(113,-208,526,806),8083=>array(113,-208,526,806),8084=>array(113,-208,526,806),8085=>array(113,-208,526,806),8086=>array(113,-208,526,966),8087=>array(113,-208,526,966),8088=>array(13,-208,713,806),8089=>array(18,-208,711,806),8090=>array(12,-208,962,806),8091=>array(18,-208,965,806),8092=>array(13,-208,903,806),8093=>array(17,-208,927,806),8094=>array(18,-208,810,966),8095=>array(17,-208,823,966),8096=>array(90,-208,735,806),8097=>array(90,-208,735,806),8098=>array(90,-208,735,806),8099=>array(90,-208,735,806),8100=>array(90,-208,735,806),8101=>array(90,-208,735,806),8102=>array(90,-208,735,966),8103=>array(90,-208,735,966),8104=>array(13,-208,745,806),8105=>array(18,-208,786,806),8106=>array(12,-208,1032,806),8107=>array(18,-208,1038,806),8108=>array(13,-208,889,806),8109=>array(17,-208,915,806),8110=>array(18,-208,864,966),8111=>array(17,-208,895,966),8112=>array(80,-12,596,785),8113=>array(80,-12,596,745),8114=>array(80,-208,596,800),8115=>array(80,-208,596,559),8116=>array(80,-208,596,800),8118=>array(80,-12,596,767),8119=>array(80,-208,596,767),8120=>array(30,0,651,928),8121=>array(30,0,651,899),8122=>array(15,0,683,800),8123=>array(30,0,651,800),8124=>array(30,-208,651,729),8125=>array(200,597,291,806),8126=>array(210,-208,300,-45),8127=>array(200,597,291,806),8128=>array(104,650,395,767),8129=>array(104,699,395,938),8130=>array(113,-208,526,800),8131=>array(113,-208,526,560),8132=>array(113,-208,526,800),8134=>array(113,-208,526,767),8135=>array(113,-208,526,767),8136=>array(15,0,715,800),8137=>array(-12,0,657,800),8138=>array(15,0,807,800),8139=>array(-6,0,739,800),8140=>array(122,-208,628,729),8141=>array(76,597,428,806),8142=>array(97,597,413,806),8143=>array(104,597,395,966),8144=>array(-10,0,295,785),8145=>array(-14,0,278,745),8146=>array(-3,0,271,978),8147=>array(57,0,279,978),8150=>array(1,0,292,767),8151=>array(2,0,293,938),8152=>array(-5,0,300,928),8153=>array(2,0,294,899),8154=>array(15,0,352,800),8155=>array(-9,0,286,800),8157=>array(76,597,425,806),8158=>array(87,597,427,806),8159=>array(104,597,395,966),8160=>array(96,0,498,785),8161=>array(96,0,498,745),8162=>array(96,0,498,978),8163=>array(96,0,498,978),8164=>array(113,-208,555,806),8165=>array(113,-208,555,806),8166=>array(96,0,498,767),8167=>array(96,0,498,938),8168=>array(22,0,587,928),8169=>array(22,0,587,899),8170=>array(15,0,822,800),8171=>array(-15,0,795,800),8172=>array(18,0,624,806),8173=>array(100,699,342,978),8174=>array(159,699,380,978),8175=>array(100,617,299,800),8178=>array(90,-208,735,800),8179=>array(90,-208,735,547),8180=>array(90,-208,735,800),8182=>array(90,-14,735,767),8183=>array(90,-208,735,767),8184=>array(15,-14,859,800),8185=>array(-7,-14,725,800),8186=>array(15,0,865,800),8187=>array(-18,0,733,800),8188=>array(57,-208,707,744),8189=>array(181,616,380,800),8190=>array(205,597,296,806),8208=>array(49,254,312,294),8209=>array(49,254,312,294),8210=>array(49,254,587,294),8211=>array(49,254,451,294),8212=>array(49,254,951,294),8213=>array(0,254,1000,294),8214=>array(146,-236,354,764),8215=>array(-10,-236,510,-41),8216=>array(114,499,183,729),8217=>array(114,499,183,729),8218=>array(114,-117,183,116),8219=>array(-183,499,-114,729),8220=>array(114,499,385,729),8221=>array(114,499,382,729),8222=>array(114,-118,384,116),8223=>array(-382,499,-114,729),8224=>array(28,-96,472,729),8225=>array(28,-96,472,729),8228=>array(142,0,191,62),8229=>array(142,0,524,63),8230=>array(142,0,857,63),8240=>array(74,-14,1267,742),8241=>array(74,-14,1659,742),8249=>array(77,86,306,500),8250=>array(77,86,306,500),8251=>array(122,2,713,662),8252=>array(98,0,388,729),8253=>array(76,0,439,742),8254=>array(-10,686,510,724),8255=>array(-44,-237,847,-59),8256=>array(-44,751,847,929),8258=>array(37,-29,961,814),8259=>array(108,340,400,395),8260=>array(-169,-14,336,742),8261=>array(113,-132,280,760),8262=>array(113,-132,280,760),8263=>array(40,0,864,742),8264=>array(76,0,635,742),8265=>array(98,0,639,742),8267=>array(121,-96,552,729),8268=>array(105,220,352,509),8269=>array(148,220,395,509),8270=>array(37,-29,461,427),8271=>array(125,-116,193,517),8272=>array(-44,-237,847,929),8273=>array(37,-7,461,929),8274=>array(86,-93,392,729),8275=>array(49,250,951,382),8276=>array(-44,-241,847,-63),8304=>array(53,345,351,742),8305=>array(60,326,116,751),8308=>array(48,359,358,734),8320=>array(53,-14,351,383),8321=>array(67,0,346,370),8322=>array(46,-1,338,383),8323=>array(48,-14,340,383),8324=>array(48,0,358,375),8363=>array(79,-127,596,760),8364=>array(27,-14,573,742),8369=>array(81,0,576,729),8376=>array(35,0,602,729),8377=>array(51,0,583,729),8451=>array(116,-14,1053,742),8457=>array(116,0,868,729),8462=>array(39,0,525,760),8463=>array(40,0,525,760),8470=>array(121,0,1102,742),8471=>array(138,0,862,725),8486=>array(57,0,707,744),8487=>array(57,-15,707,729),8490=>array(173,0,644,729),8491=>array(30,0,651,920),8494=>array(61,-12,793,647),8498=>array(122,0,492,729),8500=>array(52,-13,413,395),8513=>array(106,-14,691,742),8514=>array(31,0,435,729),8515=>array(31,0,435,729),8516=>array(23,0,588,729),8523=>array(86,-14,718,742),8530=>array(67,-14,1319,742),8531=>array(67,-14,908,742),8532=>array(46,-14,908,742),8543=>array(67,-14,737,742),8544=>array(121,0,172,729),8545=>array(121,0,369,729),8546=>array(121,0,566,729),8547=>array(121,0,890,729),8548=>array(30,0,651,729),8549=>array(30,0,799,729),8550=>array(30,0,997,729),8551=>array(30,0,1194,729),8552=>array(121,0,861,729),8553=>array(59,0,629,729),8554=>array(59,0,810,729),8555=>array(59,0,1007,729),8556=>array(122,0,526,729),8557=>array(83,-14,644,742),8558=>array(122,0,687,729),8559=>array(161,0,702,729),8560=>array(112,0,157,760),8561=>array(112,0,337,760),8562=>array(112,0,517,760),8563=>array(112,0,748,760),8564=>array(63,0,528,547),8565=>array(63,0,690,760),8566=>array(63,0,870,760),8567=>array(63,0,1050,760),8568=>array(112,0,763,760),8569=>array(56,0,536,547),8570=>array(56,0,702,760),8571=>array(56,0,881,760),8572=>array(113,0,158,760),8573=>array(68,-14,488,560),8574=>array(114,-14,555,760),8575=>array(113,0,868,560),8576=>array(122,0,1202,729),8577=>array(122,0,687,729),8578=>array(122,0,1202,729),8579=>array(83,-14,644,742),8580=>array(68,-14,488,560),8581=>array(83,-208,644,742),8585=>array(53,-14,908,742),8592=>array(49,112,781,515),8593=>array(217,0,621,732),8594=>array(57,112,789,515),8595=>array(217,-3,621,729),8596=>array(49,112,789,515),8597=>array(217,-8,621,732),8598=>array(149,37,691,580),8599=>array(149,37,691,580),8600=>array(149,37,691,580),8601=>array(149,37,691,580),8644=>array(49,-35,789,662),8645=>array(71,-57,767,684),8646=>array(49,-35,789,662),8647=>array(49,-35,781,661),8648=>array(71,0,767,732),8649=>array(58,-35,790,661),8650=>array(71,0,767,732),8704=>array(30,0,651,729),8707=>array(122,0,542,729),8710=>array(30,0,651,729),8711=>array(30,0,651,729),8722=>array(106,293,732,334),8725=>array(16,-93,321,729),8726=>array(208,-54,514,768),8727=>array(100,85,524,542),8728=>array(179,178,447,447),8756=>array(13,121,440,562),8757=>array(13,121,440,562),8758=>array(13,121,64,563),8759=>array(13,121,441,562),8764=>array(80,283,556,415),9134=>array(234,-236,281,764),9167=>array(91,0,854,596),10731=>array(3,-233,491,807),10799=>array(161,54,677,573),11374=>array(161,-178,702,729),11375=>array(30,0,651,729),11381=>array(122,0,579,729),11382=>array(114,0,497,547),11383=>array(81,-12,579,556),11386=>array(79,-17,532,560),11800=>array(76,-14,439,728),11810=>array(113,403,280,760),11811=>array(113,403,280,760),11812=>array(113,-132,280,225),11813=>array(113,-132,280,225),11822=>array(76,0,439,742),42192=>array(123,0,587,729),42193=>array(122,0,542,729),42194=>array(62,0,481,729),42195=>array(122,0,687,729),42196=>array(22,0,589,729),42197=>array(22,0,589,729),42198=>array(83,-14,668,742),42199=>array(173,0,644,729),42200=>array(12,0,483,729),42201=>array(0,-14,389,729),42202=>array(83,-14,644,742),42203=>array(83,-14,644,742),42204=>array(45,0,640,729),42205=>array(122,0,492,729),42206=>array(122,0,492,729),42207=>array(161,0,702,729),42208=>array(121,0,596,729),42209=>array(122,0,526,729),42210=>array(89,-14,553,742),42211=>array(123,0,641,729),42212=>array(54,0,572,729),42213=>array(30,0,651,729),42214=>array(30,0,651,729),42215=>array(122,0,628,729),42216=>array(106,-14,691,742),42217=>array(123,0,512,743),42218=>array(69,0,895,729),42219=>array(59,0,629,729),42220=>array(22,0,587,729),42221=>array(68,0,532,729),42222=>array(30,0,651,729),42223=>array(30,0,651,729),42224=>array(122,0,542,729),42225=>array(89,0,510,729),42226=>array(121,0,172,729),42227=>array(82,-14,706,742),42228=>array(112,-14,620,729),42229=>array(112,0,620,743),42230=>array(31,0,435,729),42231=>array(83,0,648,729),42232=>array(98,0,202,124),42233=>array(71,-156,202,124),42234=>array(98,0,499,124),42235=>array(98,-156,499,124),42236=>array(71,-156,202,501),42237=>array(98,0,202,501),42238=>array(85,0,502,340),42239=>array(85,187,502,439),42564=>array(89,-14,553,742),42565=>array(75,-14,449,560),42566=>array(121,0,347,729),42567=>array(114,0,271,547),42576=>array(25,0,906,729),42577=>array(41,0,791,547),42580=>array(82,-14,910,742),42581=>array(79,-14,700,563),42582=>array(121,0,894,729),42583=>array(112,-14,701,560),42594=>array(80,-157,1009,729),42595=>array(73,-138,827,547),42596=>array(51,-14,1009,729),42597=>array(47,-14,825,547),42598=>array(161,0,1083,729),42599=>array(137,0,905,547),42600=>array(82,-14,706,742),42601=>array(79,-17,532,560),42602=>array(56,-14,799,742),42603=>array(55,-14,658,560),42604=>array(82,-14,1278,742),42605=>array(79,-17,940,560),42606=>array(28,-208,851,743),42636=>array(22,0,589,729),42637=>array(34,0,515,547),42644=>array(116,0,568,729),42645=>array(113,0,526,760),42760=>array(104,0,372,668),42761=>array(104,0,372,668),42762=>array(104,0,372,668),42763=>array(104,0,372,668),42764=>array(104,0,372,668),42765=>array(104,0,372,668),42766=>array(104,0,372,668),42767=>array(104,0,372,668),42768=>array(104,0,372,668),42769=>array(104,0,372,668),42770=>array(104,0,372,668),42771=>array(104,0,372,668),42772=>array(104,0,372,668),42773=>array(104,0,372,668),42774=>array(104,0,372,668),42779=>array(58,326,312,736),42780=>array(58,324,312,734),42781=>array(111,326,141,734),42782=>array(111,326,141,734),42783=>array(111,0,141,408),42786=>array(77,0,340,729),42787=>array(77,0,311,547),42788=>array(56,224,411,742),42789=>array(56,42,411,560),42790=>array(122,-178,628,729),42791=>array(113,-198,526,760),42800=>array(137,0,437,547),42801=>array(75,-14,449,560),42802=>array(30,0,1220,729),42803=>array(82,-14,873,560),42814=>array(83,-14,644,742),42815=>array(68,-14,488,560),42822=>array(148,0,625,729),42823=>array(139,0,253,760),42830=>array(82,-14,1278,742),42831=>array(79,-17,940,560),42880=>array(31,0,435,729),42881=>array(113,-208,158,560),42891=>array(177,235,224,729),42892=>array(113,458,160,729),42893=>array(116,0,568,729),43002=>array(112,0,800,547),43003=>array(83,0,453,729),43004=>array(62,0,481,729),43005=>array(161,0,702,729),43006=>array(121,0,172,928),43007=>array(80,0,1096,729),62464=>array(49,-7,477,770),62465=>array(49,-7,477,770),62466=>array(49,-7,516,770),62467=>array(49,-2,759,770),62468=>array(49,-7,477,770),62469=>array(49,-7,476,770),62470=>array(49,-7,487,770),62471=>array(49,-7,772,769),62472=>array(49,-7,476,769),62473=>array(49,-7,477,770),62474=>array(49,-2,988,770),62475=>array(49,-8,477,770),62476=>array(59,-7,486,764),62477=>array(49,-2,788,769),62478=>array(49,-7,477,770),62479=>array(49,-7,477,770),62480=>array(49,0,781,770),62481=>array(59,-7,486,770),62482=>array(49,-8,623,780),62483=>array(49,-7,506,770),62484=>array(49,-7,774,770),62485=>array(49,-7,477,770),62486=>array(49,-2,741,770),62487=>array(49,-7,477,770),62488=>array(49,-7,477,770),62489=>array(59,0,486,770),62490=>array(49,-7,554,770),62491=>array(49,-7,476,770),62492=>array(59,-7,486,770),62493=>array(49,-8,476,769),62494=>array(60,-7,486,770),62495=>array(49,-7,477,770),62496=>array(49,-7,476,770),62497=>array(49,-7,476,770),62498=>array(49,-69,477,770),62499=>array(49,-7,477,770),62500=>array(49,-7,476,769),62501=>array(49,-7,538,770),63173=>array(76,-14,534,742),64256=>array(45,0,685,760),64257=>array(45,0,513,760),64258=>array(45,0,513,760),64259=>array(45,0,849,760),64260=>array(45,0,849,760),64297=>array(106,293,732,627),65533=>array(15,-84,1011,912),65535=>array(50,-177,550,705)); -$cw=array(0=>600,32=>318,33=>401,34=>460,35=>838,36=>636,37=>950,38=>780,39=>275,40=>390,41=>390,42=>500,43=>838,44=>318,45=>361,46=>318,47=>337,48=>636,49=>636,50=>636,51=>636,52=>636,53=>636,54=>636,55=>636,56=>636,57=>636,58=>337,59=>337,60=>838,61=>838,62=>838,63=>531,64=>1000,65=>684,66=>655,67=>698,68=>770,69=>632,70=>575,71=>775,72=>752,73=>295,74=>295,75=>656,76=>557,77=>863,78=>748,79=>787,80=>603,81=>787,82=>695,83=>635,84=>611,85=>732,86=>684,87=>989,88=>685,89=>611,90=>685,91=>390,92=>337,93=>390,94=>838,95=>500,96=>500,97=>613,98=>635,99=>550,100=>635,101=>615,102=>352,103=>600,104=>634,105=>278,106=>278,107=>579,108=>278,109=>974,110=>634,111=>612,112=>635,113=>635,114=>411,115=>521,116=>392,117=>634,118=>592,119=>818,120=>592,121=>592,122=>525,123=>636,124=>337,125=>636,126=>838,160=>318,161=>401,162=>636,163=>636,164=>636,165=>636,166=>337,167=>500,168=>500,169=>1000,170=>471,171=>612,172=>838,173=>361,174=>1000,175=>500,176=>500,177=>838,178=>401,179=>401,180=>483,181=>636,182=>636,183=>318,184=>500,185=>401,186=>471,187=>612,188=>969,189=>969,190=>969,191=>536,192=>684,193=>684,194=>684,195=>684,196=>684,197=>684,198=>974,199=>698,200=>632,201=>632,202=>632,203=>632,204=>295,205=>295,206=>295,207=>295,208=>775,209=>748,210=>787,211=>787,212=>787,213=>787,214=>787,215=>838,216=>787,217=>732,218=>732,219=>732,220=>732,221=>611,222=>605,223=>676,224=>613,225=>613,226=>613,227=>613,228=>613,229=>613,230=>982,231=>550,232=>615,233=>615,234=>615,235=>615,236=>278,237=>278,238=>278,239=>278,240=>612,241=>634,242=>612,243=>612,244=>612,245=>612,246=>612,247=>838,248=>612,249=>634,250=>634,251=>634,252=>634,253=>592,254=>635,255=>592,256=>684,257=>613,258=>684,259=>613,260=>684,261=>613,262=>698,263=>550,264=>698,265=>550,266=>698,267=>550,268=>698,269=>550,270=>770,271=>635,272=>775,273=>635,274=>632,275=>615,276=>632,277=>615,278=>632,279=>615,280=>632,281=>615,282=>632,283=>615,284=>775,285=>600,286=>775,287=>600,288=>775,289=>600,290=>775,291=>600,292=>752,293=>634,294=>916,295=>695,296=>295,297=>278,298=>295,299=>278,300=>295,301=>278,302=>295,303=>278,304=>295,305=>278,306=>590,307=>556,308=>295,309=>278,310=>656,311=>579,312=>579,313=>557,314=>278,315=>557,316=>278,317=>557,318=>375,319=>557,320=>342,321=>562,322=>284,323=>748,324=>634,325=>748,326=>634,327=>748,328=>634,329=>813,330=>757,331=>634,332=>787,333=>612,334=>787,335=>612,336=>787,337=>612,338=>1070,339=>1023,340=>695,341=>411,342=>695,343=>411,344=>695,345=>411,346=>635,347=>521,348=>635,349=>521,350=>635,351=>521,352=>635,353=>521,354=>611,355=>392,356=>611,357=>392,358=>611,359=>392,360=>732,361=>634,362=>732,363=>634,364=>732,365=>634,366=>732,367=>634,368=>732,369=>634,370=>732,371=>634,372=>989,373=>818,374=>611,375=>592,376=>611,377=>685,378=>525,379=>685,380=>525,381=>685,382=>525,383=>352,384=>635,385=>735,386=>686,387=>635,390=>698,391=>698,392=>550,393=>775,394=>824,395=>686,396=>635,397=>612,398=>632,399=>787,400=>585,401=>575,402=>352,403=>775,404=>685,405=>965,406=>354,407=>295,408=>690,409=>526,410=>278,412=>974,413=>748,414=>634,415=>787,416=>934,417=>757,418=>949,419=>759,420=>652,421=>635,422=>695,423=>635,424=>521,425=>632,427=>392,428=>611,429=>392,430=>611,431=>879,432=>779,433=>764,434=>721,435=>696,436=>805,437=>685,438=>525,448=>295,449=>492,450=>459,451=>295,452=>1422,453=>1299,454=>1154,455=>835,456=>787,457=>457,458=>931,459=>924,460=>797,461=>684,462=>613,463=>295,464=>278,465=>787,466=>612,467=>732,468=>634,469=>732,470=>634,471=>732,472=>634,473=>732,474=>634,475=>732,476=>634,477=>615,478=>684,479=>613,480=>684,481=>613,482=>974,483=>982,484=>775,485=>600,486=>775,487=>600,488=>656,489=>579,490=>787,491=>612,492=>787,493=>612,496=>278,497=>1422,498=>1299,499=>1154,500=>775,501=>600,504=>748,505=>634,506=>684,507=>613,508=>974,509=>982,510=>787,511=>612,512=>684,513=>613,514=>684,515=>613,516=>632,517=>615,518=>632,519=>615,520=>295,521=>278,522=>295,523=>278,524=>787,525=>612,526=>787,527=>612,528=>695,529=>411,530=>695,531=>411,532=>732,533=>634,534=>732,535=>634,536=>635,537=>521,538=>611,539=>392,542=>752,543=>634,548=>685,549=>525,550=>684,551=>613,552=>632,553=>615,554=>787,555=>612,556=>787,557=>612,558=>787,559=>612,560=>787,561=>612,562=>611,563=>592,567=>278,568=>1032,569=>1032,581=>684,584=>295,585=>278,587=>635,588=>695,589=>411,592=>614,593=>635,594=>635,595=>635,596=>550,598=>635,599=>727,600=>615,601=>615,603=>541,604=>541,607=>326,608=>637,609=>635,611=>685,613=>634,614=>634,615=>634,616=>278,617=>387,618=>372,621=>387,623=>974,624=>974,625=>974,626=>634,627=>634,628=>634,629=>612,632=>660,633=>411,634=>411,635=>411,636=>411,637=>411,638=>530,639=>530,640=>602,641=>602,642=>521,643=>336,645=>461,647=>392,648=>392,649=>634,650=>618,651=>598,652=>592,653=>818,654=>592,656=>525,665=>580,668=>654,670=>667,671=>583,672=>712,675=>1014,678=>824,679=>610,681=>848,682=>706,683=>654,686=>661,687=>664,699=>318,700=>318,702=>307,710=>500,711=>500,713=>500,714=>483,715=>500,717=>500,718=>500,719=>483,728=>500,729=>500,730=>500,731=>500,732=>500,733=>500,741=>493,742=>493,743=>493,744=>493,745=>493,755=>500,759=>500,768=>0,769=>0,770=>0,771=>0,772=>0,773=>0,774=>0,775=>0,776=>0,777=>0,778=>0,779=>0,780=>0,781=>0,782=>0,783=>0,784=>0,785=>0,786=>0,787=>0,788=>0,789=>0,790=>0,791=>0,795=>0,803=>0,804=>0,805=>0,806=>0,807=>0,808=>0,812=>0,813=>0,814=>0,815=>0,816=>0,817=>0,818=>0,819=>0,820=>0,821=>0,822=>0,823=>0,824=>0,831=>0,847=>0,856=>0,860=>0,861=>0,865=>0,880=>654,881=>568,882=>862,883=>647,884=>278,885=>278,886=>748,887=>650,890=>361,891=>549,892=>550,893=>549,894=>337,900=>483,901=>500,902=>692,903=>318,904=>746,905=>871,906=>408,908=>813,910=>825,911=>826,912=>387,913=>684,914=>655,915=>557,916=>684,917=>632,918=>685,919=>752,920=>787,921=>295,922=>656,923=>684,924=>863,925=>748,926=>632,927=>787,928=>752,929=>603,931=>632,932=>611,933=>611,934=>860,935=>685,936=>787,937=>764,938=>295,939=>611,940=>659,941=>541,942=>634,943=>387,944=>579,945=>659,946=>638,947=>592,948=>612,949=>541,950=>544,951=>634,952=>612,953=>387,954=>594,955=>592,956=>636,957=>559,958=>558,959=>612,960=>602,961=>635,962=>587,963=>634,964=>602,965=>579,966=>660,967=>592,968=>660,969=>837,970=>387,971=>579,972=>612,973=>579,974=>837,975=>656,981=>660,982=>837,984=>787,985=>612,988=>575,1009=>635,1010=>550,1011=>278,1012=>787,1013=>615,1014=>615,1015=>605,1016=>635,1017=>698,1020=>635,1021=>698,1022=>698,1023=>698,1024=>632,1025=>632,1026=>786,1027=>557,1028=>698,1029=>635,1030=>295,1031=>295,1032=>295,1033=>1094,1034=>1045,1035=>786,1036=>674,1037=>755,1038=>609,1039=>752,1040=>684,1041=>686,1042=>655,1043=>557,1044=>776,1045=>632,1046=>1040,1047=>636,1048=>755,1049=>755,1050=>674,1051=>752,1052=>863,1053=>752,1054=>787,1055=>752,1056=>603,1057=>698,1058=>611,1059=>609,1060=>860,1061=>685,1062=>776,1063=>686,1064=>1068,1065=>1094,1066=>833,1067=>882,1068=>686,1069=>698,1070=>1031,1071=>695,1072=>613,1073=>612,1074=>586,1075=>491,1076=>677,1077=>615,1078=>908,1079=>541,1080=>659,1081=>659,1082=>594,1083=>639,1084=>754,1085=>654,1086=>612,1087=>654,1088=>635,1089=>550,1090=>549,1091=>592,1092=>854,1093=>592,1094=>681,1095=>591,1096=>917,1097=>938,1098=>727,1099=>765,1100=>589,1101=>549,1102=>813,1103=>592,1104=>615,1105=>615,1106=>625,1107=>491,1108=>549,1109=>521,1110=>278,1111=>278,1112=>278,1113=>898,1114=>892,1115=>652,1116=>594,1117=>659,1118=>592,1119=>662,1121=>837,1122=>769,1123=>667,1124=>942,1125=>749,1136=>787,1137=>660,1138=>787,1168=>557,1169=>491,1176=>636,1177=>541,1184=>856,1185=>832,1188=>1014,1189=>868,1194=>698,1195=>550,1198=>611,1199=>592,1204=>934,1205=>809,1210=>686,1211=>634,1216=>278,1217=>1040,1218=>908,1223=>752,1224=>654,1232=>684,1233=>613,1234=>684,1235=>613,1236=>974,1237=>982,1238=>632,1239=>615,1240=>787,1241=>615,1242=>787,1243=>615,1244=>1040,1245=>908,1246=>636,1247=>541,1250=>755,1251=>659,1252=>755,1253=>659,1254=>787,1255=>612,1256=>787,1257=>612,1258=>787,1259=>612,1260=>698,1261=>549,1262=>609,1263=>592,1264=>609,1265=>592,1266=>609,1267=>592,1268=>686,1269=>591,1272=>882,1273=>765,1278=>685,1279=>592,1280=>686,1281=>589,1296=>585,1297=>541,1298=>752,1299=>639,1300=>1169,1301=>994,1306=>787,1307=>635,1308=>989,1309=>818,1329=>792,1330=>746,1331=>790,1332=>800,1333=>746,1334=>779,1335=>665,1336=>746,1337=>877,1338=>780,1339=>689,1340=>540,1341=>1040,1342=>858,1343=>744,1344=>684,1345=>774,1346=>800,1347=>794,1348=>789,1349=>728,1350=>755,1351=>755,1352=>732,1353=>739,1354=>889,1355=>792,1356=>833,1357=>732,1358=>790,1359=>737,1360=>732,1361=>728,1362=>557,1363=>784,1364=>767,1365=>787,1366=>833,1370=>318,1371=>224,1372=>359,1373=>213,1374=>370,1375=>366,1377=>974,1378=>634,1379=>702,1380=>742,1381=>634,1382=>702,1383=>567,1384=>634,1385=>832,1386=>702,1387=>634,1388=>280,1389=>894,1390=>645,1391=>634,1392=>634,1393=>606,1394=>702,1395=>649,1396=>709,1397=>278,1398=>669,1399=>581,1400=>634,1401=>419,1402=>974,1403=>581,1404=>671,1405=>634,1406=>701,1407=>1002,1408=>634,1409=>600,1410=>477,1411=>1002,1412=>645,1413=>612,1414=>899,1415=>836,1417=>337,1418=>313,1652=>292,4304=>469,4305=>469,4306=>519,4307=>726,4308=>479,4309=>478,4310=>468,4311=>709,4312=>468,4313=>479,4314=>970,4315=>479,4316=>479,4317=>744,4318=>469,4319=>479,4320=>754,4321=>479,4322=>578,4323=>468,4324=>729,4325=>468,4326=>743,4327=>479,4328=>479,4329=>479,4330=>513,4331=>479,4332=>479,4333=>468,4334=>479,4335=>469,4336=>468,4337=>468,4338=>469,4339=>469,4340=>469,4341=>524,4342=>755,4343=>517,4344=>479,4345=>519,4346=>524,4347=>416,4348=>304,5760=>477,5761=>493,5762=>712,5763=>931,5764=>1150,5765=>1370,5766=>493,5767=>712,5768=>931,5769=>1150,5770=>1370,5771=>498,5772=>718,5773=>938,5774=>1159,5775=>1379,5776=>493,5777=>712,5778=>930,5779=>1149,5780=>1370,5781=>498,5782=>752,5783=>789,5784=>1205,5785=>1150,5786=>683,5787=>507,5788=>507,7426=>982,7428=>550,7433=>278,7435=>604,7437=>754,7438=>650,7439=>612,7440=>550,7441=>684,7442=>684,7443=>684,7444=>1023,7446=>612,7447=>612,7449=>592,7450=>592,7456=>592,7457=>818,7458=>525,7462=>525,7463=>592,7464=>654,7467=>639,7543=>635,7680=>684,7681=>613,7682=>655,7683=>635,7684=>655,7685=>635,7686=>655,7687=>635,7688=>698,7689=>550,7690=>770,7691=>635,7692=>770,7693=>635,7694=>770,7695=>635,7696=>770,7697=>635,7698=>770,7699=>635,7700=>632,7701=>615,7702=>632,7703=>615,7704=>632,7705=>615,7706=>632,7707=>615,7708=>632,7709=>615,7710=>575,7711=>352,7712=>775,7713=>600,7714=>752,7715=>634,7716=>752,7717=>634,7718=>752,7719=>634,7720=>752,7721=>634,7722=>752,7723=>634,7724=>295,7725=>278,7726=>295,7727=>278,7728=>656,7729=>579,7730=>656,7731=>579,7732=>656,7733=>579,7734=>557,7735=>288,7736=>557,7737=>288,7738=>557,7739=>278,7740=>557,7741=>278,7742=>863,7743=>974,7744=>863,7745=>974,7746=>863,7747=>974,7748=>748,7749=>634,7750=>748,7751=>634,7752=>748,7753=>634,7754=>748,7755=>634,7756=>787,7757=>612,7758=>787,7759=>612,7760=>787,7761=>612,7762=>787,7763=>612,7764=>603,7765=>635,7766=>603,7767=>635,7768=>695,7769=>411,7770=>695,7771=>411,7772=>695,7773=>411,7774=>695,7775=>411,7776=>635,7777=>521,7778=>635,7779=>521,7780=>635,7781=>521,7782=>635,7783=>521,7784=>635,7785=>521,7786=>611,7787=>392,7788=>611,7789=>392,7790=>611,7791=>392,7792=>611,7793=>392,7794=>732,7795=>634,7796=>732,7797=>634,7798=>732,7799=>634,7800=>732,7801=>634,7802=>732,7803=>634,7804=>684,7805=>592,7806=>684,7807=>592,7808=>989,7809=>818,7810=>989,7811=>818,7812=>989,7813=>818,7814=>989,7815=>818,7816=>989,7817=>818,7818=>685,7819=>592,7820=>685,7821=>592,7822=>611,7823=>592,7824=>685,7825=>525,7826=>685,7827=>525,7828=>685,7829=>525,7830=>634,7831=>392,7832=>818,7833=>592,7834=>613,7835=>352,7836=>352,7837=>352,7838=>769,7839=>612,7840=>684,7841=>613,7842=>684,7843=>613,7844=>684,7845=>613,7846=>684,7847=>613,7848=>684,7849=>613,7850=>684,7851=>613,7852=>684,7853=>613,7854=>684,7855=>613,7856=>684,7857=>613,7858=>684,7859=>613,7860=>684,7861=>613,7862=>684,7863=>613,7864=>632,7865=>615,7866=>632,7867=>615,7868=>632,7869=>615,7870=>632,7871=>615,7872=>632,7873=>615,7874=>632,7875=>615,7876=>632,7877=>615,7878=>632,7879=>615,7880=>295,7881=>278,7882=>295,7883=>278,7884=>787,7885=>612,7886=>787,7887=>612,7888=>787,7889=>612,7890=>787,7891=>612,7892=>787,7893=>612,7894=>787,7895=>612,7896=>787,7897=>612,7898=>934,7899=>757,7900=>934,7901=>757,7902=>934,7903=>757,7904=>934,7905=>757,7906=>934,7907=>757,7908=>732,7909=>634,7910=>732,7911=>634,7912=>879,7913=>779,7914=>879,7915=>779,7916=>879,7917=>779,7918=>879,7919=>779,7920=>879,7921=>779,7922=>611,7923=>592,7924=>611,7925=>592,7926=>611,7927=>592,7928=>611,7929=>592,7930=>769,7931=>477,7936=>659,7937=>659,7938=>659,7939=>659,7940=>659,7941=>659,7942=>659,7943=>659,7944=>684,7945=>684,7946=>877,7947=>877,7948=>769,7949=>801,7950=>708,7951=>743,7952=>541,7953=>541,7954=>541,7955=>541,7956=>541,7957=>541,7960=>711,7961=>711,7962=>966,7963=>975,7964=>898,7965=>928,7968=>634,7969=>634,7970=>634,7971=>634,7972=>634,7973=>634,7974=>634,7975=>634,7976=>837,7977=>835,7978=>1086,7979=>1089,7980=>1027,7981=>1051,7982=>934,7983=>947,7984=>338,7985=>338,7986=>338,7987=>338,7988=>338,7989=>338,7990=>338,7991=>338,7992=>380,7993=>374,7994=>635,7995=>635,7996=>570,7997=>600,7998=>489,7999=>493,8000=>612,8001=>612,8002=>612,8003=>612,8004=>612,8005=>612,8008=>804,8009=>848,8010=>1095,8011=>1100,8012=>938,8013=>970,8016=>579,8017=>579,8018=>579,8019=>579,8020=>579,8021=>579,8022=>579,8023=>579,8025=>784,8027=>998,8029=>1012,8031=>897,8032=>837,8033=>837,8034=>837,8035=>837,8036=>837,8037=>837,8038=>837,8039=>837,8040=>802,8041=>843,8042=>1089,8043=>1095,8044=>946,8045=>972,8046=>921,8047=>952,8048=>659,8049=>659,8050=>541,8051=>548,8052=>634,8053=>654,8054=>338,8055=>338,8056=>612,8057=>612,8058=>579,8059=>579,8060=>837,8061=>837,8064=>659,8065=>659,8066=>659,8067=>659,8068=>659,8069=>659,8070=>659,8071=>659,8072=>684,8073=>684,8074=>877,8075=>877,8076=>769,8077=>801,8078=>708,8079=>743,8080=>634,8081=>634,8082=>634,8083=>634,8084=>634,8085=>634,8086=>634,8087=>634,8088=>837,8089=>835,8090=>1086,8091=>1089,8092=>1027,8093=>1051,8094=>934,8095=>947,8096=>837,8097=>837,8098=>837,8099=>837,8100=>837,8101=>837,8102=>837,8103=>837,8104=>802,8105=>843,8106=>1089,8107=>1095,8108=>946,8109=>972,8110=>921,8111=>952,8112=>659,8113=>659,8114=>659,8115=>659,8116=>659,8118=>659,8119=>659,8120=>684,8121=>684,8122=>716,8123=>692,8124=>684,8125=>500,8126=>500,8127=>500,8128=>500,8129=>500,8130=>634,8131=>634,8132=>654,8134=>634,8135=>634,8136=>805,8137=>746,8138=>931,8139=>871,8140=>752,8141=>500,8142=>500,8143=>500,8144=>338,8145=>338,8146=>338,8147=>338,8150=>338,8151=>338,8152=>295,8153=>295,8154=>475,8155=>408,8157=>500,8158=>500,8159=>500,8160=>579,8161=>579,8162=>579,8163=>579,8164=>635,8165=>635,8166=>579,8167=>579,8168=>611,8169=>611,8170=>845,8171=>825,8172=>685,8173=>500,8174=>500,8175=>500,8178=>837,8179=>837,8180=>837,8182=>837,8183=>837,8184=>941,8185=>813,8186=>922,8187=>826,8188=>764,8189=>500,8190=>500,8192=>500,8193=>1000,8194=>500,8195=>1000,8196=>330,8197=>250,8198=>167,8199=>636,8200=>318,8201=>200,8202=>100,8203=>0,8204=>0,8205=>0,8206=>0,8207=>0,8208=>361,8209=>361,8210=>636,8211=>500,8212=>1000,8213=>1000,8214=>500,8215=>500,8216=>318,8217=>318,8218=>318,8219=>318,8220=>518,8221=>518,8222=>518,8223=>518,8224=>500,8225=>500,8228=>334,8229=>667,8230=>1000,8232=>0,8233=>0,8234=>0,8235=>0,8236=>0,8237=>0,8238=>0,8239=>200,8240=>1342,8241=>1735,8249=>400,8250=>400,8251=>838,8252=>485,8253=>531,8254=>500,8255=>804,8256=>804,8258=>1000,8259=>500,8260=>167,8261=>390,8262=>390,8263=>922,8264=>733,8265=>733,8267=>636,8268=>500,8269=>500,8270=>500,8271=>337,8272=>804,8273=>500,8274=>450,8275=>1000,8276=>804,8287=>222,8288=>0,8289=>0,8290=>0,8291=>0,8292=>0,8298=>0,8299=>0,8300=>0,8301=>0,8302=>0,8303=>0,8304=>401,8305=>179,8308=>401,8320=>401,8321=>401,8322=>401,8323=>401,8324=>401,8363=>636,8364=>636,8369=>636,8376=>636,8377=>636,8451=>1123,8457=>952,8462=>634,8463=>634,8470=>1165,8471=>1000,8486=>764,8487=>764,8490=>656,8491=>684,8494=>854,8498=>575,8500=>462,8513=>775,8514=>557,8515=>557,8516=>611,8523=>780,8530=>1370,8531=>969,8532=>969,8543=>568,8544=>295,8545=>492,8546=>689,8547=>923,8548=>684,8549=>922,8550=>1120,8551=>1317,8552=>917,8553=>685,8554=>933,8555=>1131,8556=>557,8557=>698,8558=>770,8559=>863,8560=>278,8561=>458,8562=>637,8563=>812,8564=>592,8565=>811,8566=>991,8567=>1170,8568=>819,8569=>592,8570=>822,8571=>1002,8572=>278,8573=>550,8574=>635,8575=>974,8576=>1285,8577=>770,8578=>1285,8579=>698,8580=>549,8581=>698,8585=>969,8592=>838,8593=>838,8594=>838,8595=>838,8596=>838,8597=>838,8598=>838,8599=>838,8600=>838,8601=>838,8644=>838,8645=>838,8646=>838,8647=>838,8648=>838,8649=>838,8650=>838,8704=>684,8707=>632,8710=>684,8711=>684,8722=>838,8725=>337,8726=>637,8727=>626,8728=>626,8756=>636,8757=>636,8758=>260,8759=>636,8764=>636,9134=>521,9167=>945,10731=>494,10799=>838,11374=>863,11375=>684,11381=>654,11382=>568,11383=>660,11386=>612,11800=>536,11810=>390,11811=>390,11812=>390,11813=>390,11822=>531,42192=>655,42193=>603,42194=>603,42195=>770,42196=>611,42197=>611,42198=>775,42199=>656,42200=>656,42201=>512,42202=>698,42203=>698,42204=>685,42205=>575,42206=>575,42207=>863,42208=>748,42209=>557,42210=>635,42211=>695,42212=>695,42213=>684,42214=>684,42215=>752,42216=>775,42217=>512,42218=>989,42219=>685,42220=>611,42221=>655,42222=>684,42223=>684,42224=>632,42225=>632,42226=>295,42227=>787,42228=>732,42229=>732,42230=>557,42231=>770,42232=>300,42233=>300,42234=>596,42235=>596,42236=>300,42237=>300,42238=>588,42239=>588,42564=>635,42565=>521,42566=>354,42567=>387,42576=>1029,42577=>906,42580=>1031,42581=>813,42582=>927,42583=>814,42594=>1014,42595=>866,42596=>1015,42597=>864,42598=>1088,42599=>944,42600=>787,42601=>612,42602=>855,42603=>712,42604=>1358,42605=>1019,42606=>879,42636=>611,42637=>549,42644=>686,42645=>634,42760=>493,42761=>493,42762=>493,42763=>493,42764=>493,42765=>493,42766=>493,42767=>493,42768=>493,42769=>493,42770=>493,42771=>493,42772=>493,42773=>493,42774=>493,42779=>369,42780=>369,42781=>252,42782=>252,42783=>252,42786=>385,42787=>356,42788=>472,42789=>472,42790=>752,42791=>634,42800=>491,42801=>521,42802=>1250,42803=>985,42814=>703,42815=>549,42822=>680,42823=>392,42830=>1358,42831=>1019,42880=>557,42881=>278,42891=>401,42892=>275,42893=>686,43002=>917,43003=>575,43004=>603,43005=>863,43006=>295,43007=>1199,62464=>525,62465=>525,62466=>565,62467=>808,62468=>535,62469=>525,62470=>536,62471=>821,62472=>525,62473=>525,62474=>1037,62475=>535,62476=>535,62477=>837,62478=>525,62479=>536,62480=>830,62481=>535,62482=>672,62483=>565,62484=>823,62485=>535,62486=>790,62487=>535,62488=>535,62489=>535,62490=>603,62491=>535,62492=>535,62493=>525,62494=>535,62495=>525,62496=>525,62497=>525,62498=>525,62499=>525,62500=>524,62501=>567,63173=>612,64256=>689,64257=>630,64258=>630,64259=>967,64260=>967,64297=>838,65024=>0,65025=>0,65026=>0,65027=>0,65028=>0,65029=>0,65030=>0,65031=>0,65032=>0,65033=>0,65034=>0,65035=>0,65036=>0,65037=>0,65038=>0,65039=>0,65533=>1025,65535=>600); -// --- EOF --- diff --git a/lib/combodo/tcpdf/fonts/dejavusansextralight.z b/lib/combodo/tcpdf/fonts/dejavusansextralight.z deleted file mode 100644 index a966f6de5c41357b3cae9cf88610eb77711f28db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 173046 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

    !p5-TzKPgO%JLJCC`aZ=8=8II{xN7=oE#Lj~UY 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 Co_X#7 diff --git a/lib/combodo/tcpdf/fonts/dejavusansi.ctg.z b/lib/combodo/tcpdf/fonts/dejavusansi.ctg.z deleted file mode 100644 index 1b98d135f6843177fd449faf94308ad8f33326d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9343 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,'FontBBox'=>'[-1016 -350 1659 1068]','ItalicAngle'=>-11,'Ascent'=>928,'Descent'=>-236,'Leading'=>0,'CapHeight'=>729,'XHeight'=>547,'StemV'=>34,'StemH'=>15,'AvgWidth'=>507,'MaxWidth'=>1690,'MissingWidth'=>600); -$cbbox=array(0=>array(50,-177,550,705),33=>array(79,0,320,729),34=>array(96,458,364,729),35=>array(70,0,773,718),36=>array(33,-147,570,760),37=>array(91,-14,859,742),38=>array(47,-14,736,742),39=>array(96,458,179,729),40=>array(77,-132,427,759),41=>array(-62,-132,288,759),42=>array(30,286,470,742),43=>array(106,0,732,627),44=>array(3,-116,193,124),45=>array(45,234,324,314),46=>array(58,0,185,124),47=>array(-73,-93,427,729),48=>array(50,-14,586,742),49=>array(49,0,485,729),50=>array(4,0,574,742),51=>array(2,-14,572,742),52=>array(18,0,565,729),53=>array(20,-14,581,729),54=>array(63,-14,592,742),55=>array(93,0,627,729),56=>array(33,-14,593,742),57=>array(44,-14,574,742),58=>array(52,0,256,517),59=>array(1,-116,267,517),60=>array(106,46,732,581),61=>array(106,172,732,454),62=>array(106,46,732,581),63=>array(123,0,511,742),64=>array(58,-173,950,703),65=>array(-53,0,615,729),66=>array(27,0,625,729),67=>array(42,-14,695,742),68=>array(27,0,722,729),69=>array(27,0,630,729),70=>array(27,0,587,729),71=>array(45,-14,725,742),72=>array(27,0,725,729),73=>array(27,0,268,729),74=>array(-164,-200,266,729),75=>array(27,0,722,729),76=>array(27,0,497,729),77=>array(27,0,836,729),78=>array(27,0,721,729),79=>array(40,-14,747,742),80=>array(27,0,601,729),81=>array(41,-129,747,742),82=>array(27,0,600,729),83=>array(6,-14,603,742),84=>array(43,0,676,729),85=>array(58,-14,713,729),86=>array(78,0,742,729),87=>array(96,0,1020,729),88=>array(-43,0,703,729),89=>array(63,0,676,729),90=>array(-22,0,703,729),91=>array(40,-132,420,760),92=>array(85,-93,262,729),93=>array(-38,-132,342,760),94=>array(106,457,732,729),95=>array(-10,-236,510,-166),96=>array(190,617,388,800),97=>array(41,-14,547,560),98=>array(36,-14,587,760),99=>array(46,-14,536,560),100=>array(46,-14,639,760),101=>array(46,-14,571,560),102=>array(68,0,478,760),103=>array(32,-208,596,560),104=>array(35,0,566,760),105=>array(35,0,273,760),106=>array(-113,-208,277,760),107=>array(35,0,612,760),108=>array(35,0,273,760),109=>array(35,0,906,560),110=>array(35,0,566,560),111=>array(46,-14,566,560),112=>array(-3,-208,589,560),113=>array(46,-206,597,560),114=>array(35,0,463,560),115=>array(11,-14,500,560),116=>array(64,0,423,702),117=>array(57,-14,589,547),118=>array(72,0,604,547),119=>array(85,0,819,547),120=>array(-26,0,600,547),121=>array(-25,-208,603,547),122=>array(-3,0,543,547),123=>array(121,-163,605,760),124=>array(127,-236,210,764),125=>array(7,-163,491,760),126=>array(106,228,732,399),161=>array(85,0,326,729),162=>array(74,-153,563,698),163=>array(24,0,637,742),164=>array(46,40,592,587),165=>array(45,0,673,729),166=>array(127,-171,210,699),167=>array(12,-95,485,742),168=>array(184,659,493,758),169=>array(138,0,862,725),170=>array(40,229,446,742),171=>array(62,69,555,517),172=>array(106,140,732,421),173=>array(45,234,324,314),174=>array(138,0,862,725),175=>array(186,673,492,745),176=>array(95,432,405,742),177=>array(106,0,732,627),178=>array(36,326,385,742),179=>array(16,319,368,742),180=>array(252,616,522,800),181=>array(-13,-208,592,547),182=>array(78,-96,573,729),183=>array(114,285,241,409),184=>array(49,-193,267,0),185=>array(66,326,347,734),186=>array(40,229,462,742),187=>array(62,69,554,517),188=>array(66,-14,958,742),189=>array(66,-14,953,742),190=>array(16,-14,958,742),191=>array(37,-13,425,729),192=>array(-53,0,615,927),193=>array(-53,0,615,927),194=>array(-53,0,615,928),195=>array(-53,0,617,921),196=>array(-53,0,615,913),197=>array(-53,0,615,928),198=>array(-45,0,994,729),199=>array(42,-193,695,742),200=>array(27,0,630,927),201=>array(27,0,630,927),202=>array(27,0,630,928),203=>array(27,0,630,913),204=>array(27,0,292,927),205=>array(27,0,383,927),206=>array(27,0,379,928),207=>array(27,0,392,913),208=>array(0,0,727,729),209=>array(27,0,721,921),210=>array(40,-14,747,927),211=>array(40,-14,747,927),212=>array(40,-14,747,928),213=>array(40,-14,747,921),214=>array(40,-14,747,913),215=>array(137,31,701,596),216=>array(-34,-32,809,761),217=>array(58,-14,713,927),218=>array(58,-14,713,927),219=>array(58,-14,713,928),220=>array(58,-14,713,913),221=>array(63,0,676,927),222=>array(27,0,577,729),223=>array(47,-14,590,760),224=>array(41,-14,547,800),225=>array(41,-14,571,800),226=>array(41,-14,547,800),227=>array(41,-14,562,777),228=>array(41,-14,547,758),229=>array(41,-14,547,878),230=>array(41,-14,951,560),231=>array(46,-193,536,560),232=>array(46,-14,571,800),233=>array(46,-14,576,800),234=>array(46,-14,571,800),235=>array(46,-14,571,758),236=>array(35,0,262,800),237=>array(35,0,396,800),238=>array(35,0,351,800),239=>array(35,0,367,758),240=>array(45,-14,587,760),241=>array(35,0,580,777),242=>array(46,-14,566,800),243=>array(46,-14,578,800),244=>array(46,-14,566,800),245=>array(46,-14,569,777),246=>array(46,-14,566,758),247=>array(106,73,732,554),248=>array(-14,-46,622,590),249=>array(57,-14,589,800),250=>array(57,-14,589,800),251=>array(57,-14,589,800),252=>array(57,-14,589,758),253=>array(-25,-208,603,800),254=>array(-3,-208,589,760),255=>array(-25,-208,603,758),256=>array(-53,0,615,899),257=>array(41,-14,547,745),258=>array(-53,0,624,926),259=>array(41,-14,562,761),260=>array(-53,-194,618,729),261=>array(41,-194,547,560),262=>array(42,-14,695,927),263=>array(46,-14,580,800),264=>array(42,-14,695,928),265=>array(46,-14,551,800),266=>array(42,-14,695,914),267=>array(46,-14,536,760),268=>array(42,-14,695,928),269=>array(46,-14,570,800),270=>array(27,0,722,928),271=>array(46,-14,819,760),272=>array(0,0,727,729),273=>array(46,-14,701,760),274=>array(27,0,630,900),275=>array(46,-14,571,745),276=>array(27,0,630,928),277=>array(46,-14,571,785),278=>array(27,0,630,914),279=>array(46,-14,571,760),280=>array(27,-194,630,729),281=>array(46,-194,571,560),282=>array(27,0,630,928),283=>array(46,-14,571,800),284=>array(45,-14,725,928),285=>array(32,-208,596,800),286=>array(45,-14,725,928),287=>array(32,-208,596,785),288=>array(45,-14,725,914),289=>array(32,-208,596,760),290=>array(45,-250,725,742),291=>array(32,-208,596,775),292=>array(27,0,725,928),293=>array(35,0,566,928),294=>array(109,0,868,729),295=>array(46,0,576,760),296=>array(27,0,415,921),297=>array(35,0,387,777),298=>array(27,0,390,899),299=>array(35,0,381,745),300=>array(27,0,400,928),301=>array(35,0,381,785),302=>array(-7,-194,268,729),303=>array(-8,-194,273,760),304=>array(27,0,304,914),305=>array(35,0,232,547),306=>array(27,-200,561,729),307=>array(35,-208,554,760),308=>array(-164,-200,386,928),309=>array(-113,-208,360,800),310=>array(27,-235,722,729),311=>array(35,-235,612,760),312=>array(38,0,617,547),313=>array(27,0,497,928),314=>array(35,0,422,928),315=>array(27,-235,497,729),316=>array(20,-235,273,760),317=>array(27,0,497,729),318=>array(35,0,474,760),319=>array(27,0,497,729),320=>array(35,0,443,760),321=>array(-20,0,502,729),322=>array(17,0,318,760),323=>array(27,0,721,928),324=>array(35,0,566,803),325=>array(27,-235,721,729),326=>array(35,-235,566,560),327=>array(27,0,721,928),328=>array(35,0,570,800),329=>array(75,0,732,729),330=>array(46,-208,682,742),331=>array(35,-208,566,560),332=>array(40,-14,747,899),333=>array(46,-14,566,745),334=>array(40,-14,747,928),335=>array(46,-14,566,785),336=>array(40,-14,773,927),337=>array(46,-14,623,800),338=>array(46,0,1067,729),339=>array(46,-14,984,560),340=>array(27,0,600,928),341=>array(35,0,549,803),342=>array(27,-235,600,729),343=>array(20,-235,463,560),344=>array(27,0,600,925),345=>array(35,0,492,800),346=>array(6,-14,603,928),347=>array(11,-14,549,803),348=>array(6,-14,603,928),349=>array(11,-14,500,800),350=>array(6,-193,603,742),351=>array(11,-193,500,560),352=>array(6,-14,603,928),353=>array(11,-14,523,800),354=>array(43,-193,676,729),355=>array(62,-193,423,702),356=>array(43,0,676,928),357=>array(64,0,477,803),358=>array(52,0,685,729),359=>array(16,0,406,702),360=>array(58,-14,713,921),361=>array(57,-14,589,777),362=>array(58,-14,713,899),363=>array(57,-14,589,745),364=>array(58,-14,713,928),365=>array(57,-14,589,785),366=>array(58,-14,713,929),367=>array(57,-14,589,861),368=>array(58,-14,729,927),369=>array(57,-14,619,800),370=>array(58,-194,713,729),371=>array(57,-194,589,547),372=>array(96,0,1020,932),373=>array(85,0,819,800),374=>array(63,0,676,932),375=>array(-25,-208,603,800),376=>array(63,0,676,913),377=>array(-22,0,703,928),378=>array(-3,0,549,803),379=>array(-22,0,703,912),380=>array(-3,0,543,760),381=>array(-22,0,703,928),382=>array(-3,0,543,800),383=>array(68,0,478,760),384=>array(19,-14,561,760),385=>array(51,0,740,729),386=>array(27,0,635,729),387=>array(19,-14,579,760),388=>array(42,0,601,729),389=>array(35,-14,578,760),390=>array(63,-14,715,742),391=>array(39,-14,885,924),392=>array(39,-14,672,724),393=>array(0,0,727,729),394=>array(51,0,831,729),395=>array(69,0,686,729),396=>array(36,-14,619,760),397=>array(55,-208,575,548),398=>array(64,0,675,729),399=>array(51,-14,750,742),400=>array(121,-14,676,742),401=>array(-142,-200,607,729),402=>array(-157,-208,465,760),403=>array(39,-14,915,924),404=>array(95,-210,774,729),405=>array(17,0,897,760),406=>array(76,0,292,729),407=>array(0,0,299,729),408=>array(26,0,792,742),409=>array(17,0,596,760),410=>array(-2,0,277,760),411=>array(-44,0,535,760),412=>array(60,-14,966,729),413=>array(-142,-200,740,729),414=>array(57,-208,579,560),415=>array(40,-14,747,742),416=>array(34,-14,823,761),417=>array(48,-14,657,609),418=>array(56,-14,873,742),419=>array(74,-208,702,560),420=>array(51,0,717,729),421=>array(-3,-208,580,760),422=>array(40,-129,592,729),423=>array(2,-14,580,742),424=>array(11,-14,473,560),425=>array(27,0,630,729),426=>array(-58,-208,341,760),427=>array(72,-208,426,702),428=>array(43,0,685,729),429=>array(46,0,429,760),430=>array(71,-200,704,729),431=>array(56,-4,854,761),432=>array(58,-14,720,615),433=>array(42,-14,798,724),434=>array(76,-1,678,729),435=>array(67,0,789,742),436=>array(4,-208,777,560),437=>array(-26,0,700,729),438=>array(-10,0,535,547),439=>array(23,-31,652,729),440=>array(15,-31,662,729),441=>array(21,-213,594,547),442=>array(-9,-208,533,547),443=>array(1,0,564,742),444=>array(16,-31,625,729),445=>array(-16,-213,550,547),446=>array(-20,-14,430,702),447=>array(-5,-208,603,560),448=>array(7,-208,288,729),449=>array(7,-208,485,729),450=>array(-13,-208,484,729),451=>array(26,0,267,729),452=>array(27,0,1473,928),453=>array(27,0,1313,800),454=>array(46,-14,1178,800),455=>array(27,-200,823,729),456=>array(27,-208,834,760),457=>array(35,-208,555,760),458=>array(27,-200,1014,729),459=>array(27,-208,1025,760),460=>array(35,-208,911,760),461=>array(-53,0,615,928),462=>array(41,-14,556,800),463=>array(27,0,414,928),464=>array(35,0,400,800),465=>array(40,-14,747,928),466=>array(46,-14,598,800),467=>array(58,-14,713,928),468=>array(57,-14,589,800),469=>array(58,-14,713,1025),470=>array(57,-14,589,899),471=>array(58,-14,713,1047),472=>array(57,-14,589,903),473=>array(58,-14,713,1044),474=>array(57,-14,589,906),475=>array(58,-14,713,1044),476=>array(57,-14,589,903),477=>array(51,-14,563,560),478=>array(-53,0,626,1025),479=>array(41,-14,548,899),480=>array(-53,0,627,1025),481=>array(41,-14,573,868),482=>array(-45,0,994,900),483=>array(41,-14,951,743),484=>array(45,-14,743,742),485=>array(32,-208,596,560),486=>array(45,-14,725,928),487=>array(32,-208,596,800),488=>array(27,0,722,928),489=>array(35,0,612,928),490=>array(40,-194,747,742),491=>array(46,-194,566,560),492=>array(40,-194,747,899),493=>array(46,-194,566,745),494=>array(23,-31,652,928),495=>array(-47,-213,530,793),496=>array(-113,-208,392,793),497=>array(27,0,1473,729),498=>array(27,0,1313,729),499=>array(46,-14,1178,760),500=>array(45,-14,725,928),501=>array(32,-208,596,800),502=>array(29,-14,1059,729),503=>array(-14,-208,666,742),504=>array(27,0,721,927),505=>array(35,0,566,800),506=>array(-53,0,786,928),507=>array(41,-14,772,928),508=>array(-45,0,994,928),509=>array(41,-14,951,800),510=>array(-34,-32,809,928),511=>array(-14,-46,622,800),512=>array(-53,0,615,930),513=>array(41,-14,547,800),514=>array(-53,0,615,917),515=>array(41,-14,549,785),516=>array(27,0,630,930),517=>array(46,-14,571,800),518=>array(27,0,630,917),519=>array(46,-14,571,785),520=>array(27,0,363,930),521=>array(22,0,365,800),522=>array(27,0,393,917),523=>array(35,0,370,785),524=>array(40,-14,747,930),525=>array(46,-14,566,800),526=>array(40,-14,747,917),527=>array(46,-14,566,785),528=>array(27,0,600,930),529=>array(35,0,463,800),530=>array(27,0,600,917),531=>array(35,0,486,785),532=>array(58,-14,713,930),533=>array(57,-14,589,800),534=>array(58,-14,713,917),535=>array(57,-14,589,785),536=>array(6,-240,603,742),537=>array(11,-240,500,560),538=>array(43,-240,676,729),539=>array(64,-240,423,702),540=>array(-36,-210,593,742),541=>array(-62,-211,489,560),542=>array(27,0,725,928),543=>array(35,0,566,928),544=>array(27,-208,663,742),545=>array(41,-70,744,760),546=>array(19,-14,663,742),547=>array(34,-14,584,648),548=>array(-6,-208,720,729),549=>array(10,-208,555,547),550=>array(-53,0,615,914),551=>array(41,-14,547,760),552=>array(27,-189,630,729),553=>array(46,-193,571,560),554=>array(40,-14,747,1025),555=>array(46,-14,582,899),556=>array(40,-14,747,1025),557=>array(46,-14,579,861),558=>array(40,-14,747,914),559=>array(46,-14,566,760),560=>array(40,-14,747,1029),561=>array(46,-14,566,899),562=>array(63,0,676,899),563=>array(-25,-208,603,745),564=>array(-13,-70,381,757),565=>array(43,-70,768,560),566=>array(-5,-70,413,702),567=>array(-113,-208,235,547),568=>array(36,-14,924,760),569=>array(74,-208,962,560),570=>array(-70,-34,754,761),571=>array(-63,-34,762,761),572=>array(-50,-46,600,592),573=>array(0,0,497,729),574=>array(-107,-34,718,761),575=>array(27,-242,515,560),576=>array(13,-242,559,547),577=>array(157,0,668,729),578=>array(69,0,457,560),579=>array(-31,0,621,729),580=>array(4,-14,739,729),581=>array(-63,0,605,729),582=>array(27,-93,636,822),583=>array(36,-93,573,640),584=>array(-163,-200,293,729),585=>array(-114,-208,276,760),586=>array(74,-200,772,743),587=>array(74,-208,616,560),588=>array(-6,0,600,729),589=>array(-5,0,464,560),590=>array(29,0,684,729),591=>array(6,-208,635,547),592=>array(69,-14,575,560),593=>array(55,-14,597,560),594=>array(2,-14,544,560),595=>array(19,-14,561,760),596=>array(2,-14,493,560),597=>array(61,-70,542,560),598=>array(55,-208,638,760),599=>array(36,-14,821,760),600=>array(28,-14,561,560),601=>array(51,-14,563,560),602=>array(41,-14,819,560),603=>array(39,-14,506,561),604=>array(5,-11,504,560),605=>array(14,-14,777,561),606=>array(55,-14,609,561),607=>array(-91,-208,289,547),608=>array(33,-208,809,760),609=>array(53,-208,617,547),610=>array(55,0,569,574),611=>array(103,-210,623,547),612=>array(102,-14,604,547),613=>array(94,-208,616,547),614=>array(17,0,539,760),615=>array(37,-208,560,760),616=>array(26,0,309,760),617=>array(80,0,258,547),618=>array(4,0,368,547),619=>array(22,0,372,760),620=>array(41,0,417,760),621=>array(39,-208,278,760),622=>array(41,-213,662,760),623=>array(81,-13,944,548),624=>array(100,-208,962,547),625=>array(57,-208,919,560),626=>array(-93,-208,582,560),627=>array(57,-208,601,560),628=>array(34,0,602,547),629=>array(55,-14,557,560),630=>array(55,0,814,547),631=>array(66,-15,658,560),632=>array(54,-208,602,760),633=>array(2,-13,430,547),634=>array(-18,-13,450,755),635=>array(21,-208,449,547),636=>array(-20,-208,449,560),637=>array(19,-208,449,560),638=>array(2,0,491,560),639=>array(96,0,397,560),640=>array(-29,0,454,547),641=>array(-29,0,561,547),642=>array(18,-208,512,560),643=>array(-112,-208,449,760),644=>array(-113,-208,449,760),645=>array(86,-208,341,549),646=>array(-206,-208,449,760),647=>array(-11,-155,344,547),648=>array(40,-208,426,702),649=>array(-9,-14,641,547),650=>array(56,-15,619,547),651=>array(80,0,551,548),652=>array(-23,0,509,547),653=>array(-11,0,723,547),654=>array(-43,0,586,755),655=>array(103,0,605,547),656=>array(10,-208,555,547),657=>array(-5,-54,541,547),658=>array(-24,-213,554,547),659=>array(20,-213,554,547),660=>array(93,0,485,759),661=>array(72,0,522,759),662=>array(-24,0,426,759),663=>array(-7,-213,543,760),664=>array(56,-14,731,742),665=>array(38,0,534,547),666=>array(33,-14,596,561),667=>array(37,0,801,759),668=>array(38,0,616,547),669=>array(-205,-208,278,760),670=>array(71,-213,650,547),671=>array(38,0,454,547),672=>array(55,-208,840,759),673=>array(7,0,485,759),674=>array(72,0,522,759),675=>array(36,-14,1004,760),676=>array(55,-213,1024,760),677=>array(40,-54,1007,760),678=>array(51,0,787,702),679=>array(66,-208,723,760),680=>array(58,-70,764,702),681=>array(55,-208,815,760),682=>array(21,0,657,760),683=>array(21,0,643,760),684=>array(22,-15,552,640),685=>array(-28,84,543,640),686=>array(80,-214,624,760),687=>array(79,-208,623,760),688=>array(16,326,340,751),689=>array(16,326,340,751),690=>array(-64,209,168,751),691=>array(27,326,289,640),692=>array(5,319,267,632),693=>array(16,209,277,632),694=>array(-14,326,350,632),695=>array(56,326,519,632),696=>array(9,209,395,632),697=>array(164,557,336,800),698=>array(164,557,518,800),699=>array(131,489,321,729),700=>array(62,489,251,729),701=>array(179,616,298,856),702=>array(136,492,296,760),703=>array(138,492,297,760),704=>array(85,326,333,751),705=>array(74,326,354,751),706=>array(255,524,532,836),707=>array(232,524,509,836),708=>array(203,561,515,800),709=>array(250,561,561,800),710=>array(165,616,477,800),711=>array(200,616,512,800),712=>array(104,488,171,759),713=>array(186,673,492,745),714=>array(252,616,522,800),715=>array(190,617,388,800),716=>array(104,-148,171,123),717=>array(24,-156,331,-84),718=>array(190,-236,388,-54),719=>array(252,-237,522,-54),720=>array(4,0,279,517),721=>array(70,356,244,517),722=>array(89,249,249,517),723=>array(90,249,250,517),724=>array(119,229,353,448),725=>array(147,229,381,448),726=>array(47,125,353,417),727=>array(47,234,281,307),728=>array(200,645,507,785),729=>array(279,658,398,758),730=>array(209,610,477,878),731=>array(98,-194,279,0),732=>array(164,639,513,777),733=>array(188,616,567,800),734=>array(-5,233,323,504),735=>array(104,616,406,800),736=>array(63,208,415,632),737=>array(16,326,155,751),738=>array(30,326,330,648),739=>array(27,326,415,632),740=>array(74,326,354,751),741=>array(157,0,454,668),742=>array(127,0,454,668),743=>array(98,0,454,668),744=>array(69,0,454,668),745=>array(40,0,454,668),748=>array(96,-260,408,-21),749=>array(174,610,504,808),750=>array(135,489,525,729),755=>array(95,-240,363,28),759=>array(83,-193,432,-83),768=>array(-259,617,-61,800),769=>array(-203,616,67,800),770=>array(-284,616,28,800),771=>array(-288,639,61,777),772=>array(-266,673,40,745),773=>array(-510,686,10,755),774=>array(-249,645,58,785),775=>array(-169,646,-58,760),776=>array(-265,659,44,758),777=>array(-204,618,14,810),778=>array(-240,610,28,878),779=>array(-264,616,115,800),780=>array(-255,616,57,800),781=>array(-305,615,-195,832),782=>array(-404,615,-96,832),783=>array(-331,616,12,800),784=>array(-304,645,3,854),785=>array(-247,645,60,785),786=>array(-189,489,-16,645),787=>array(-329,595,-162,844),788=>array(-305,595,-163,844),789=>array(-80,616,80,800),790=>array(-311,-266,-113,-83),791=>array(-249,-267,21,-83),792=>array(-363,-240,-200,-24),793=>array(-300,-240,-137,-24),794=>array(-198,690,54,930),795=>array(-141,427,69,609),796=>array(-315,-241,-188,-32),797=>array(-384,-240,-132,-87),798=>array(-368,-240,-116,-87),799=>array(-363,-240,-137,-24),800=>array(-265,-184,-12,-117),801=>array(-339,-208,6,63),802=>array(-339,-208,-70,63),803=>array(-332,-184,-220,-70),804=>array(-435,-183,-126,-84),805=>array(-355,-241,-146,-32),806=>array(-339,-240,-165,-84),807=>array(-451,-193,-233,0),808=>array(-402,-194,-221,0),809=>array(-302,-240,-198,-47),810=>array(-398,-211,-98,-50),811=>array(-468,-222,-67,-82),812=>array(-386,-240,-74,-57),813=>array(-429,-240,-117,-57),814=>array(-433,-222,-126,-82),815=>array(-459,-224,-153,-83),816=>array(-466,-222,-117,-84),817=>array(-441,-156,-135,-84),818=>array(-566,-236,-33,-166),819=>array(-556,-236,8,-9),820=>array(-570,240,-27,381),821=>array(-325,221,-51,301),822=>array(-642,221,7,301),823=>array(-629,-46,21,592),824=>array(-811,-34,15,761),825=>array(-312,-241,-184,-32),826=>array(-398,-206,-98,-44),827=>array(-380,-240,-118,-21),828=>array(-495,-222,-94,-82),829=>array(-370,608,-130,825),830=>array(-272,595,-84,853),831=>array(-510,528,10,755),832=>array(-259,617,-61,800),833=>array(-203,616,67,800),834=>array(-288,639,61,777),835=>array(-329,595,-162,844),836=>array(-308,659,61,978),837=>array(-356,-208,-252,-45),838=>array(-411,639,-89,786),839=>array(-378,-226,-122,-35),840=>array(-383,-240,-117,-47),841=>array(-353,-240,-119,-21),842=>array(-425,616,-75,800),843=>array(-425,567,-75,850),844=>array(-424,596,-75,820),845=>array(-452,-230,-48,-30),846=>array(-360,-240,-147,-45),849=>array(-316,610,-157,878),850=>array(-415,633,-108,855),851=>array(-370,-241,-130,-24),855=>array(-343,610,-183,878),856=>array(23,658,142,758),858=>array(-430,-241,-71,-32),860=>array(-483,-237,407,-60),861=>array(-290,802,601,979),862=>array(-297,855,600,927),863=>array(-491,-156,415,-84),864=>array(-208,756,528,894),865=>array(-290,752,601,929),866=>array(-528,-230,366,-30),880=>array(27,0,568,729),881=>array(41,0,486,547),882=>array(95,0,834,729),883=>array(95,0,620,729),884=>array(164,557,336,800),885=>array(27,-208,199,35),886=>array(27,0,721,729),887=>array(38,0,612,547),890=>array(136,-208,240,-45),891=>array(2,-14,493,560),892=>array(46,-14,536,560),893=>array(2,-14,493,560),894=>array(1,-116,267,517),900=>array(252,616,522,800),901=>array(184,659,553,978),902=>array(-53,0,615,800),903=>array(114,285,241,409),904=>array(59,0,765,800),905=>array(64,0,869,800),906=>array(62,0,409,800),908=>array(64,-14,793,800),910=>array(56,0,919,800),911=>array(53,0,828,800),912=>array(74,0,450,978),913=>array(-53,0,615,729),914=>array(27,0,625,729),915=>array(27,0,623,729),916=>array(-63,0,605,729),917=>array(27,0,630,729),918=>array(-22,0,703,729),919=>array(27,0,725,729),920=>array(56,-14,731,742),921=>array(27,0,268,729),922=>array(27,0,722,729),923=>array(-63,0,605,729),924=>array(27,0,836,729),925=>array(27,0,721,729),926=>array(27,0,619,729),927=>array(40,-14,747,742),928=>array(27,0,725,729),929=>array(27,0,601,729),931=>array(27,0,630,729),932=>array(43,0,676,729),933=>array(63,0,676,729),934=>array(50,0,737,729),935=>array(-43,0,703,729),936=>array(88,0,803,729),937=>array(-34,0,723,738),938=>array(27,0,399,913),939=>array(63,0,676,913),940=>array(55,-12,645,800),941=>array(39,-14,561,800),942=>array(57,-208,619,800),943=>array(67,0,431,800),944=>array(59,0,566,978),945=>array(55,-12,645,559),946=>array(-1,-208,572,766),947=>array(74,-208,635,547),948=>array(38,-14,557,742),949=>array(39,-14,506,561),950=>array(49,-210,590,760),951=>array(57,-208,579,560),952=>array(55,-11,557,768),953=>array(67,0,265,547),954=>array(40,0,584,547),955=>array(-44,0,488,760),956=>array(-13,-208,592,547),957=>array(89,0,526,547),958=>array(38,-210,563,760),959=>array(46,-14,566,560),960=>array(55,-19,615,547),961=>array(16,-208,599,560),962=>array(74,-210,556,560),963=>array(57,-14,659,547),964=>array(84,0,606,547),965=>array(59,0,533,547),966=>array(74,-208,622,551),967=>array(-44,-208,622,547),968=>array(66,-208,675,547),969=>array(68,-14,771,547),970=>array(74,0,391,758),971=>array(59,0,533,758),972=>array(46,-14,583,800),973=>array(59,0,539,800),974=>array(68,-14,771,800),975=>array(47,-208,742,729),976=>array(81,-11,534,768),977=>array(65,-11,557,768),978=>array(97,0,701,729),979=>array(56,0,865,800),980=>array(97,0,701,913),981=>array(54,-208,602,760),982=>array(68,-14,858,547),983=>array(28,-188,665,547),984=>array(75,-207,750,742),985=>array(74,-208,576,560),986=>array(88,-210,675,729),987=>array(76,-210,613,547),988=>array(27,0,587,729),989=>array(-184,-208,500,760),990=>array(64,-2,639,729),991=>array(87,0,576,759),992=>array(109,-208,779,742),993=>array(21,-180,508,559),994=>array(36,-213,884,729),995=>array(86,-208,790,547),996=>array(43,-208,730,742),997=>array(44,-208,619,560),998=>array(27,-213,719,729),999=>array(-21,-14,620,575),1000=>array(-34,-208,660,745),1001=>array(-11,-208,569,560),1002=>array(-15,0,785,742),1003=>array(-29,0,649,560),1004=>array(33,-14,715,758),1005=>array(46,-14,584,758),1006=>array(31,-208,625,729),1007=>array(53,-208,561,726),1008=>array(9,-3,646,547),1009=>array(84,-208,599,560),1010=>array(46,-14,536,560),1011=>array(-113,-208,277,760),1012=>array(40,-14,747,742),1013=>array(55,-14,532,560),1014=>array(43,-14,521,560),1015=>array(27,0,577,729),1016=>array(-3,-208,589,760),1017=>array(42,-14,695,742),1018=>array(27,0,836,729),1019=>array(-11,-208,661,547),1020=>array(-22,-208,599,560),1021=>array(63,-14,715,742),1022=>array(42,-14,695,742),1023=>array(63,-14,715,742),1024=>array(27,0,630,927),1025=>array(27,0,630,913),1026=>array(71,-200,704,729),1027=>array(27,0,623,927),1028=>array(45,-14,704,742),1029=>array(6,-14,603,742),1030=>array(27,0,268,729),1031=>array(27,0,386,913),1032=>array(-164,-200,266,729),1033=>array(-30,0,1000,729),1034=>array(27,0,951,729),1035=>array(52,0,685,729),1036=>array(27,0,747,927),1037=>array(27,0,721,927),1038=>array(24,0,663,928),1039=>array(42,-157,740,729),1040=>array(-53,0,615,729),1041=>array(27,0,635,729),1042=>array(27,0,625,729),1043=>array(27,0,623,729),1044=>array(-37,-157,735,729),1045=>array(27,0,630,729),1046=>array(-51,0,1111,729),1047=>array(1,-14,595,742),1048=>array(27,0,721,729),1049=>array(27,0,721,928),1050=>array(27,0,747,729),1051=>array(-30,0,724,729),1052=>array(27,0,836,729),1053=>array(27,0,725,729),1054=>array(40,-14,747,742),1055=>array(27,0,725,729),1056=>array(27,0,601,729),1057=>array(42,-14,695,742),1058=>array(43,0,676,729),1059=>array(24,0,663,729),1060=>array(54,0,811,729),1061=>array(-43,0,703,729),1062=>array(42,-157,740,729),1063=>array(109,0,658,729),1064=>array(27,0,1042,729),1065=>array(42,-157,1057,729),1066=>array(84,0,738,729),1067=>array(27,0,855,729),1068=>array(27,0,592,729),1069=>array(-6,-14,642,742),1070=>array(32,-14,1034,742),1071=>array(-4,0,667,729),1072=>array(41,-14,547,560),1073=>array(31,-14,584,777),1074=>array(38,0,534,547),1075=>array(38,0,530,547),1076=>array(-14,-138,634,547),1077=>array(46,-14,571,560),1078=>array(-19,0,892,547),1079=>array(14,-14,488,561),1080=>array(38,0,612,547),1081=>array(38,0,612,760),1082=>array(38,0,597,547),1083=>array(-16,0,609,547),1084=>array(38,0,717,547),1085=>array(38,0,616,547),1086=>array(46,-14,566,560),1087=>array(38,0,616,547),1088=>array(-3,-208,589,560),1089=>array(46,-14,536,560),1090=>array(68,0,606,547),1091=>array(-25,-208,603,547),1092=>array(46,-208,813,729),1093=>array(-26,0,600,547),1094=>array(51,-138,629,547),1095=>array(94,0,553,547),1096=>array(38,0,877,547),1097=>array(51,-138,891,547),1098=>array(69,0,630,547),1099=>array(38,0,749,547),1100=>array(38,0,513,547),1101=>array(6,-14,496,560),1102=>array(41,-14,796,560),1103=>array(3,0,570,547),1104=>array(46,-14,571,802),1105=>array(46,-14,571,758),1106=>array(55,-208,552,760),1107=>array(38,0,587,803),1108=>array(47,-14,537,560),1109=>array(11,-14,500,560),1110=>array(35,0,273,760),1111=>array(35,0,382,758),1112=>array(-113,-208,277,760),1113=>array(-16,0,826,547),1114=>array(38,0,821,547),1115=>array(35,0,530,760),1116=>array(38,0,597,803),1117=>array(38,0,612,802),1118=>array(-25,-208,603,760),1119=>array(51,-138,629,547),1120=>array(36,-14,884,729),1121=>array(68,-14,771,547),1122=>array(49,0,688,729),1123=>array(36,0,578,729),1124=>array(32,-14,948,742),1125=>array(41,-14,737,560),1126=>array(-63,0,800,729),1127=>array(-28,0,705,547),1128=>array(27,0,1064,729),1129=>array(41,0,923,547),1130=>array(-15,0,784,729),1131=>array(-0,0,611,547),1132=>array(27,0,1023,729),1133=>array(39,0,823,547),1134=>array(-29,-208,582,935),1135=>array(-23,-193,518,753),1136=>array(73,0,910,729),1137=>array(77,-208,905,765),1138=>array(40,-14,747,742),1139=>array(55,-14,557,560),1140=>array(78,0,840,742),1141=>array(75,0,692,560),1142=>array(78,0,840,930),1143=>array(75,0,692,800),1144=>array(62,-208,1017,742),1145=>array(66,-208,946,560),1146=>array(47,-14,905,742),1147=>array(46,-14,708,560),1148=>array(35,-14,1121,932),1149=>array(61,-14,958,758),1150=>array(36,-14,884,900),1151=>array(68,-14,771,734),1152=>array(46,-208,704,742),1153=>array(46,-208,534,560),1154=>array(22,-44,484,457),1155=>array(-525,608,-86,810),1156=>array(-385,645,-8,788),1157=>array(-315,595,-179,797),1158=>array(-328,595,-170,797),1159=>array(-790,606,-0,788),1160=>array(-1016,-180,415,922),1161=>array(-936,-280,354,1022),1162=>array(27,-208,721,928),1163=>array(39,-208,613,760),1164=>array(27,0,592,729),1165=>array(39,0,514,702),1166=>array(27,0,604,729),1167=>array(-3,-208,580,560),1168=>array(13,0,637,878),1169=>array(23,0,544,700),1170=>array(26,0,688,729),1171=>array(21,0,595,547),1172=>array(27,-200,623,729),1173=>array(35,-208,527,547),1174=>array(-36,-157,1126,729),1175=>array(-5,-138,905,547),1176=>array(1,-193,595,742),1177=>array(14,-193,488,561),1178=>array(42,-157,762,729),1179=>array(51,-138,610,547),1180=>array(27,0,747,729),1181=>array(38,0,597,547),1182=>array(27,0,747,729),1183=>array(17,0,576,760),1184=>array(79,0,893,729),1185=>array(59,0,715,547),1186=>array(42,-157,740,729),1187=>array(54,-138,633,547),1188=>array(27,0,1080,729),1189=>array(39,0,913,547),1190=>array(27,-200,1031,729),1191=>array(39,-208,860,547),1192=>array(45,-14,815,743),1193=>array(44,-14,644,560),1194=>array(42,-193,695,742),1195=>array(46,-193,536,560),1196=>array(67,-157,700,729),1197=>array(53,-138,593,547),1198=>array(63,0,676,729),1199=>array(72,-208,603,547),1200=>array(69,0,684,729),1201=>array(62,-208,635,547),1202=>array(-26,-157,725,729),1203=>array(-11,-138,616,547),1204=>array(67,-157,898,729),1205=>array(53,-138,759,547),1206=>array(142,-157,674,729),1207=>array(117,-138,567,547),1208=>array(127,0,659,729),1209=>array(102,0,551,547),1210=>array(119,0,667,729),1211=>array(35,0,566,760),1212=>array(41,-14,894,742),1213=>array(31,-14,687,560),1214=>array(41,-184,894,742),1215=>array(31,-161,687,560),1216=>array(27,0,268,729),1217=>array(-51,0,1111,928),1218=>array(-19,0,892,785),1219=>array(27,-200,721,729),1220=>array(38,-208,617,547),1221=>array(-46,-208,726,729),1222=>array(-36,-208,607,547),1223=>array(27,-200,725,729),1224=>array(39,-208,617,547),1225=>array(27,-208,725,729),1226=>array(39,-208,617,547),1227=>array(142,-157,674,729),1228=>array(117,-138,567,547),1229=>array(27,-208,836,729),1230=>array(39,-208,711,547),1231=>array(35,0,273,760),1232=>array(-53,0,624,926),1233=>array(41,-14,562,761),1234=>array(-53,0,615,913),1235=>array(41,-14,547,758),1236=>array(-45,0,994,729),1237=>array(41,-14,951,560),1238=>array(27,0,630,928),1239=>array(46,-14,571,785),1240=>array(51,-14,750,742),1241=>array(51,-14,563,560),1242=>array(51,-14,750,913),1243=>array(51,-14,563,758),1244=>array(-51,0,1111,913),1245=>array(-19,0,892,758),1246=>array(1,-14,595,913),1247=>array(14,-14,488,758),1248=>array(23,-31,652,729),1249=>array(-24,-213,554,547),1250=>array(27,0,721,899),1251=>array(38,0,612,745),1252=>array(27,0,721,913),1253=>array(38,0,612,758),1254=>array(40,-14,747,913),1255=>array(46,-14,566,758),1256=>array(40,-14,747,742),1257=>array(55,-14,557,560),1258=>array(40,-14,747,913),1259=>array(55,-14,557,758),1260=>array(-6,-14,642,913),1261=>array(6,-14,496,758),1262=>array(24,0,663,899),1263=>array(-25,-208,603,745),1264=>array(24,0,663,913),1265=>array(-25,-208,603,758),1266=>array(24,0,701,927),1267=>array(-25,-208,603,800),1268=>array(109,0,658,913),1269=>array(94,0,553,758),1270=>array(42,-157,638,729),1271=>array(51,-138,543,547),1272=>array(27,0,855,913),1273=>array(38,0,749,758),1274=>array(47,-208,708,729),1275=>array(42,-208,615,547),1276=>array(-21,-200,729,729),1277=>array(-4,-208,622,547),1278=>array(-41,0,709,729),1279=>array(-24,0,602,547),1280=>array(35,0,658,729),1281=>array(27,0,545,547),1282=>array(36,-14,943,729),1283=>array(26,-14,824,547),1284=>array(148,-14,912,742),1285=>array(116,-14,802,561),1286=>array(148,-208,599,742),1287=>array(116,-208,523,561),1288=>array(-48,-14,1009,729),1289=>array(-36,-14,884,547),1290=>array(29,-14,1059,729),1291=>array(39,-14,894,547),1292=>array(45,-14,734,742),1293=>array(47,-14,568,560),1294=>array(51,-14,710,729),1295=>array(37,-14,638,547),1296=>array(121,-14,676,742),1297=>array(39,-14,506,561),1298=>array(-10,-200,744,729),1299=>array(4,-208,629,547),1300=>array(-10,0,1213,729),1301=>array(-16,0,1005,547),1302=>array(27,0,918,729),1303=>array(-3,-208,875,560),1304=>array(-4,0,1029,729),1305=>array(3,-14,945,560),1306=>array(41,-129,747,742),1307=>array(46,-206,597,560),1308=>array(96,0,1020,729),1309=>array(85,0,819,547),1310=>array(27,0,747,729),1311=>array(38,0,597,547),1312=>array(-30,-200,1031,729),1313=>array(-16,-208,852,547),1314=>array(27,-200,1031,729),1315=>array(38,-208,859,547),1316=>array(42,-157,740,729),1317=>array(51,-138,629,547),1329=>array(69,-29,715,729),1330=>array(16,0,662,743),1331=>array(66,0,717,743),1332=>array(56,0,712,743),1333=>array(69,-14,685,729),1334=>array(32,0,710,744),1335=>array(21,0,650,729),1336=>array(16,0,662,743),1337=>array(16,-14,847,743),1338=>array(23,-14,764,729),1339=>array(21,0,637,729),1340=>array(21,0,479,729),1341=>array(21,-14,884,729),1342=>array(111,-13,827,742),1343=>array(99,0,680,729),1344=>array(7,-26,671,729),1345=>array(43,-23,706,744),1346=>array(61,0,674,743),1347=>array(-2,0,715,735),1348=>array(69,-14,837,729),1349=>array(42,-14,659,743),1350=>array(53,-14,667,729),1351=>array(61,-15,709,729),1352=>array(16,0,662,743),1353=>array(70,-28,682,744),1354=>array(56,0,730,743),1355=>array(25,0,705,744),1356=>array(16,0,755,743),1357=>array(58,-14,713,729),1358=>array(61,0,677,729),1359=>array(44,-14,645,741),1360=>array(16,0,662,743),1361=>array(49,-14,666,743),1362=>array(21,0,572,729),1363=>array(56,0,752,729),1364=>array(-33,0,703,743),1365=>array(40,-14,747,742),1366=>array(31,-13,724,729),1369=>array(138,492,297,760),1370=>array(112,499,300,729),1371=>array(71,620,341,803),1372=>array(51,618,458,893),1373=>array(106,617,305,800),1374=>array(52,613,470,866),1375=>array(92,618,522,760),1377=>array(64,-14,934,547),1378=>array(-5,-208,557,560),1379=>array(52,-208,607,560),1380=>array(35,-208,613,560),1381=>array(71,-14,598,760),1382=>array(45,-208,594,560),1383=>array(35,0,541,760),1384=>array(-5,-208,557,560),1385=>array(-5,-208,735,560),1386=>array(46,-14,698,760),1387=>array(-5,-208,557,760),1388=>array(-5,-208,231,547),1389=>array(-5,-208,939,760),1390=>array(45,-14,605,760),1391=>array(71,-208,593,760),1392=>array(35,0,566,760),1393=>array(31,-15,516,760),1394=>array(35,-208,572,560),1395=>array(52,-14,625,768),1396=>array(71,-14,739,760),1397=>array(-116,-208,232,547),1398=>array(58,-14,593,760),1399=>array(-80,-208,448,560),1400=>array(35,0,566,560),1401=>array(-73,-208,339,547),1402=>array(64,-208,934,547),1403=>array(-22,-208,508,561),1404=>array(35,0,589,560),1405=>array(57,-14,589,547),1406=>array(71,-208,635,760),1407=>array(71,-14,897,560),1408=>array(-5,-208,557,560),1409=>array(31,-208,595,560),1410=>array(35,0,409,547),1411=>array(71,-208,897,760),1412=>array(-67,-208,583,560),1413=>array(45,-14,565,560),1414=>array(33,-208,765,760),1415=>array(71,-14,771,760),1417=>array(46,0,229,415),1418=>array(23,212,301,314),1456=>array(264,-217,375,-22),1457=>array(88,-217,458,-22),1458=>array(129,-217,473,-22),1459=>array(129,-217,473,-22),1460=>array(276,-159,364,-85),1461=>array(215,-159,425,-85),1462=>array(227,-217,437,-22),1463=>array(166,-159,474,-85),1464=>array(173,-193,481,-46),1465=>array(-7,625,81,698),1466=>array(-7,625,81,698),1467=>array(154,-237,458,-17),1468=>array(281,237,369,310),1469=>array(264,-217,375,-22),1470=>array(41,472,320,552),1471=>array(166,625,474,698),1472=>array(30,-98,265,645),1473=>array(697,625,785,698),1474=>array(162,625,250,698),1475=>array(49,0,246,547),1478=>array(-3,0,385,547),1479=>array(178,-217,485,-22),1488=>array(91,0,684,547),1489=>array(43,0,549,547),1490=>array(43,-5,383,547),1491=>array(135,0,618,547),1492=>array(101,0,617,547),1493=>array(91,0,288,547),1494=>array(99,0,410,547),1495=>array(91,0,620,547),1496=>array(141,-14,659,552),1497=>array(106,204,264,547),1498=>array(135,-208,509,547),1499=>array(43,0,534,547),1500=>array(135,0,599,729),1501=>array(91,0,640,547),1502=>array(75,0,646,555),1503=>array(50,-208,288,547),1504=>array(43,0,377,547),1505=>array(144,-14,647,547),1506=>array(29,-93,642,547),1507=>array(163,-208,606,547),1508=>array(91,0,623,547),1509=>array(149,-208,603,548),1510=>array(43,0,607,547),1511=>array(62,-208,740,546),1512=>array(135,0,538,547),1513=>array(118,0,772,547),1514=>array(10,-4,634,547),1520=>array(91,0,486,547),1521=>array(106,0,486,547),1522=>array(106,204,462,547),1523=>array(73,361,343,547),1524=>array(73,361,572,547),3647=>array(24,-138,575,769),3713=>array(27,-10,632,560),3714=>array(39,-17,648,568),3716=>array(46,-10,620,568),3719=>array(26,-238,443,568),3720=>array(68,-0,579,575),3722=>array(61,-234,676,568),3725=>array(30,-8,673,573),3732=>array(34,0,589,568),3733=>array(25,-15,589,579),3734=>array(85,-240,660,560),3735=>array(20,-8,631,571),3737=>array(-28,-8,629,568),3738=>array(11,-8,610,571),3739=>array(-7,-8,631,760),3740=>array(13,-8,768,614),3741=>array(46,-14,751,760),3742=>array(25,-8,688,561),3743=>array(6,-8,710,760),3745=>array(-8,-14,690,547),3746=>array(12,-8,694,760),3747=>array(41,-8,669,568),3749=>array(5,-8,604,568),3751=>array(26,-8,585,569),3754=>array(-6,-8,729,679),3755=>array(48,-12,789,575),3757=>array(27,-8,585,568),3758=>array(40,-8,739,605),3759=>array(133,-166,768,579),3760=>array(28,53,618,587),3761=>array(-576,639,-42,880),3762=>array(74,0,489,560),3763=>array(-357,0,489,820),3764=>array(-594,615,-73,926),3765=>array(-593,612,-18,926),3766=>array(-594,615,-73,926),3767=>array(-593,612,-18,926),3768=>array(-363,-350,-160,-38),3769=>array(-425,-306,-129,-40),3771=>array(-581,639,-44,880),3772=>array(-618,-284,9,-39),3773=>array(-4,-240,699,715),3776=>array(35,-14,373,560),3777=>array(35,-14,646,560),3778=>array(50,-5,417,896),3779=>array(101,-14,546,892),3780=>array(161,-11,438,886),3782=>array(28,-232,626,557),3784=>array(-380,632,-264,807),3785=>array(-572,609,-23,891),3786=>array(-595,598,23,869),3787=>array(-469,624,-175,904),3788=>array(-630,630,-2,875),3789=>array(-424,635,-219,820),3792=>array(66,-14,570,547),3793=>array(73,-75,601,576),3794=>array(17,-66,558,711),3795=>array(-56,-9,766,830),3796=>array(19,-83,560,711),3797=>array(19,-83,560,711),3798=>array(-6,-8,811,812),3799=>array(49,-240,654,560),3800=>array(82,-210,679,557),3801=>array(17,-4,675,571),3804=>array(48,-12,1001,575),3805=>array(48,-12,1027,575),4256=>array(128,-15,920,828),4257=>array(162,-0,718,828),4258=>array(176,-148,651,837),4259=>array(115,-15,893,828),4260=>array(162,0,652,837),4261=>array(159,0,821,837),4262=>array(174,-15,742,828),4263=>array(132,-15,992,837),4264=>array(167,0,543,874),4265=>array(134,0,639,828),4266=>array(119,-15,827,828),4267=>array(103,-15,932,828),4268=>array(49,0,672,828),4269=>array(124,-167,880,837),4270=>array(171,-15,880,837),4271=>array(169,0,727,828),4272=>array(89,-15,960,828),4273=>array(107,-15,609,828),4274=>array(48,-0,672,837),4275=>array(124,-182,880,837),4276=>array(146,0,914,834),4277=>array(127,0,781,828),4278=>array(46,-15,673,837),4279=>array(155,0,718,828),4280=>array(89,-15,723,828),4281=>array(49,0,616,828),4282=>array(133,-15,869,837),4283=>array(105,-15,917,828),4284=>array(48,-0,687,828),4285=>array(94,-15,639,837),4286=>array(48,-0,728,828),4287=>array(66,0,856,828),4288=>array(135,-15,892,828),4289=>array(49,0,627,828),4290=>array(99,-15,679,837),4291=>array(127,0,693,828),4292=>array(159,0,701,828),4293=>array(60,-15,827,837),4304=>array(79,-15,488,592),4305=>array(90,-14,510,837),4306=>array(33,-235,526,551),4307=>array(50,-230,806,547),4308=>array(28,-236,509,547),4309=>array(27,-236,521,547),4310=>array(80,-14,491,836),4311=>array(88,-14,797,547),4312=>array(94,0,514,547),4313=>array(21,-236,510,542),4314=>array(100,-230,1071,552),4315=>array(90,-15,585,837),4316=>array(97,-15,593,833),4317=>array(96,-0,784,547),4318=>array(80,-15,550,833),4319=>array(27,-236,561,551),4320=>array(95,0,793,833),4321=>array(100,-15,509,827),4322=>array(62,-236,627,680),4323=>array(31,-236,533,571),4324=>array(98,-236,822,547),4325=>array(27,-236,610,828),4326=>array(99,-230,791,546),4327=>array(27,-236,559,538),4328=>array(83,-15,589,837),4329=>array(49,0,524,837),4330=>array(62,-236,569,532),4331=>array(89,-14,620,828),4332=>array(98,-15,651,837),4333=>array(37,-236,569,827),4334=>array(104,-15,516,827),4335=>array(-16,-235,478,572),4336=>array(76,-15,564,837),4337=>array(92,-15,582,837),4338=>array(24,-141,501,547),4339=>array(27,-236,560,546),4340=>array(28,-236,575,837),4341=>array(68,-15,616,837),4342=>array(91,-236,820,547),4343=>array(26,-236,504,547),4344=>array(28,-236,500,538),4345=>array(85,-236,578,551),4346=>array(77,-77,516,547),4347=>array(37,-10,441,484),4348=>array(155,420,431,837),5121=>array(79,1,747,730),5122=>array(-63,0,605,1037),5123=>array(-63,0,605,729),5124=>array(-63,0,605,914),5125=>array(27,0,722,729),5126=>array(27,0,722,914),5127=>array(27,0,722,913),5129=>array(27,0,722,729),5130=>array(47,0,742,729),5131=>array(47,0,742,914),5132=>array(88,1,898,730),5133=>array(79,1,786,730),5134=>array(88,0,756,729),5135=>array(-63,0,786,729),5136=>array(88,0,756,914),5137=>array(-63,0,786,914),5138=>array(88,0,920,729),5139=>array(27,0,918,729),5140=>array(88,0,920,914),5141=>array(27,0,918,914),5142=>array(27,0,746,914),5143=>array(88,0,940,729),5144=>array(47,0,918,729),5145=>array(88,0,940,914),5146=>array(47,0,918,914),5147=>array(47,0,742,914),5149=>array(88,629,208,729),5150=>array(27,326,448,734),5151=>array(20,356,388,714),5152=>array(72,356,336,714),5153=>array(66,398,361,674),5154=>array(40,391,335,667),5155=>array(41,398,339,667),5156=>array(67,398,335,667),5157=>array(0,327,440,733),5158=>array(27,326,370,734),5159=>array(88,312,208,412),5160=>array(61,503,340,563),5161=>array(61,399,340,667),5162=>array(83,399,363,691),5163=>array(79,1,1002,730),5164=>array(-63,0,821,729),5165=>array(27,0,866,729),5166=>array(47,0,1029,729),5167=>array(78,0,742,729),5168=>array(-63,0,605,1037),5169=>array(-63,0,605,729),5170=>array(-63,0,605,914),5171=>array(-13,0,682,729),5172=>array(-13,0,682,914),5173=>array(-13,0,682,913),5175=>array(-13,0,682,729),5176=>array(47,0,742,729),5177=>array(47,0,742,914),5178=>array(88,0,893,729),5179=>array(78,0,786,729),5180=>array(88,0,756,729),5181=>array(-63,0,786,729),5182=>array(88,0,756,914),5183=>array(-63,0,786,914),5184=>array(88,0,880,729),5185=>array(-13,0,918,729),5186=>array(88,0,880,914),5187=>array(-13,0,918,914),5188=>array(88,0,940,729),5189=>array(47,0,918,729),5190=>array(88,0,940,914),5191=>array(47,0,918,914),5192=>array(47,0,742,913),5193=>array(61,326,493,734),5194=>array(27,326,177,734),5196=>array(71,-14,717,729),5197=>array(15,0,661,1037),5198=>array(15,0,661,743),5199=>array(15,0,661,914),5200=>array(-13,0,671,729),5201=>array(-13,0,671,914),5202=>array(-13,0,671,913),5204=>array(-13,0,671,729),5205=>array(59,0,743,729),5206=>array(59,0,743,914),5207=>array(88,-14,906,729),5208=>array(71,-14,840,729),5209=>array(88,0,850,743),5210=>array(15,0,840,743),5211=>array(88,0,850,914),5212=>array(15,0,840,914),5213=>array(88,0,869,729),5214=>array(-13,0,852,729),5215=>array(88,0,869,914),5216=>array(-13,0,852,914),5217=>array(88,0,960,729),5218=>array(59,0,852,729),5219=>array(88,0,960,914),5220=>array(59,0,852,914),5221=>array(57,0,960,729),5222=>array(67,326,419,734),5223=>array(71,-14,863,734),5224=>array(15,0,863,743),5225=>array(-13,0,851,734),5226=>array(59,0,875,734),5227=>array(62,0,557,743),5228=>array(26,0,622,1037),5229=>array(26,0,622,743),5230=>array(26,0,622,914),5231=>array(7,-14,603,729),5232=>array(7,-14,656,914),5233=>array(7,-14,751,913),5234=>array(71,-14,567,729),5235=>array(71,-14,567,914),5236=>array(88,0,789,743),5237=>array(62,0,722,743),5238=>array(88,0,808,743),5239=>array(26,0,768,743),5240=>array(88,0,808,914),5241=>array(26,0,768,914),5242=>array(88,-14,834,729),5243=>array(7,-14,722,729),5244=>array(88,-14,888,914),5245=>array(7,-14,722,914),5246=>array(88,-14,753,729),5247=>array(71,-14,768,729),5248=>array(88,-14,753,914),5249=>array(71,-14,768,914),5250=>array(57,-14,753,729),5251=>array(52,318,364,734),5252=>array(8,318,380,734),5253=>array(62,0,736,743),5254=>array(26,0,760,743),5255=>array(7,-14,736,734),5256=>array(71,-14,760,734),5257=>array(62,0,557,743),5258=>array(26,0,622,1037),5259=>array(26,0,622,743),5260=>array(26,0,622,914),5261=>array(7,-14,603,729),5262=>array(7,-14,656,914),5263=>array(7,-14,751,913),5264=>array(71,-14,567,729),5265=>array(71,-14,567,914),5266=>array(88,0,789,743),5267=>array(62,0,722,743),5268=>array(88,0,808,743),5269=>array(26,0,768,743),5270=>array(88,0,808,914),5271=>array(26,0,768,914),5272=>array(88,-14,834,729),5273=>array(7,-14,722,729),5274=>array(88,-14,888,914),5275=>array(7,-14,722,914),5276=>array(88,-14,753,729),5277=>array(71,-14,768,729),5278=>array(88,-14,753,914),5279=>array(71,-14,768,914),5280=>array(57,-14,753,729),5281=>array(52,318,364,734),5282=>array(48,318,420,734),5283=>array(113,0,583,729),5284=>array(27,0,623,1037),5285=>array(27,0,623,729),5286=>array(27,0,623,914),5287=>array(-13,0,583,729),5288=>array(-13,0,641,914),5289=>array(-13,0,736,913),5290=>array(27,0,497,729),5291=>array(27,0,497,914),5292=>array(88,0,722,729),5293=>array(113,0,720,729),5294=>array(88,0,812,729),5295=>array(27,0,715,729),5296=>array(88,0,812,914),5297=>array(27,0,715,914),5298=>array(88,0,722,729),5299=>array(-13,0,720,729),5300=>array(88,0,780,914),5301=>array(-13,0,720,914),5302=>array(88,0,686,729),5303=>array(27,0,715,729),5304=>array(88,0,686,914),5305=>array(27,0,715,914),5306=>array(57,0,686,729),5307=>array(27,326,301,734),5308=>array(61,326,493,734),5309=>array(27,326,371,734),5312=>array(85,-14,825,436),5313=>array(29,-14,837,755),5314=>array(29,-14,837,436),5315=>array(0,-14,809,636),5316=>array(14,0,823,450),5317=>array(14,0,823,636),5318=>array(14,0,823,635),5319=>array(26,0,766,450),5320=>array(26,0,766,636),5321=>array(88,-14,1043,436),5322=>array(85,-14,986,436),5323=>array(88,0,998,450),5324=>array(26,0,767,450),5325=>array(88,0,998,636),5326=>array(26,0,767,636),5327=>array(26,0,766,635),5328=>array(66,484,531,736),5329=>array(48,318,438,734),5330=>array(42,484,548,736),5331=>array(85,0,825,450),5332=>array(29,0,837,755),5333=>array(29,0,837,450),5334=>array(29,0,837,636),5335=>array(14,0,823,450),5336=>array(14,0,823,636),5337=>array(14,0,823,635),5338=>array(26,0,766,450),5339=>array(26,0,766,636),5340=>array(88,0,1043,450),5341=>array(85,0,986,450),5342=>array(88,0,1069,450),5343=>array(29,0,981,450),5344=>array(88,0,1069,636),5345=>array(29,0,981,636),5346=>array(88,0,1041,450),5347=>array(14,0,986,450),5348=>array(88,0,1041,636),5349=>array(14,0,986,636),5350=>array(88,0,998,450),5351=>array(26,0,981,450),5352=>array(88,0,998,636),5353=>array(26,0,981,636),5354=>array(67,484,531,736),5356=>array(16,0,742,729),5357=>array(95,0,507,729),5358=>array(27,0,774,1037),5359=>array(27,0,640,729),5360=>array(27,0,694,914),5361=>array(-37,0,576,729),5362=>array(-37,0,633,914),5363=>array(-37,0,728,913),5364=>array(96,0,508,729),5365=>array(96,0,508,914),5366=>array(88,0,738,729),5367=>array(95,0,706,729),5368=>array(88,0,829,729),5369=>array(27,0,723,729),5370=>array(88,0,883,914),5371=>array(27,0,723,914),5372=>array(88,0,807,729),5373=>array(-37,0,706,729),5374=>array(88,0,864,914),5375=>array(-37,0,706,914),5376=>array(88,0,697,729),5377=>array(96,0,723,729),5378=>array(88,0,697,914),5379=>array(96,0,723,914),5380=>array(57,0,697,729),5381=>array(65,326,332,734),5382=>array(33,318,377,741),5383=>array(27,326,403,734),5392=>array(63,-14,649,743),5393=>array(-6,-14,718,743),5394=>array(-6,-14,718,914),5395=>array(32,-14,860,464),5396=>array(32,-14,860,636),5397=>array(26,-14,865,464),5398=>array(26,-14,865,636),5399=>array(88,-14,847,743),5400=>array(63,-14,824,743),5401=>array(88,-14,916,743),5402=>array(-6,-14,824,743),5403=>array(88,-14,916,914),5404=>array(-6,-14,824,914),5405=>array(88,-14,1109,464),5406=>array(32,-14,1051,464),5407=>array(88,-14,1109,636),5408=>array(32,-14,1051,636),5409=>array(88,-14,1114,464),5410=>array(26,-14,1051,464),5411=>array(88,-14,1114,636),5412=>array(26,-14,1051,636),5413=>array(63,476,590,737),5414=>array(44,0,531,729),5415=>array(27,0,571,1037),5416=>array(27,0,571,729),5417=>array(27,0,571,914),5418=>array(56,0,600,729),5419=>array(56,0,660,914),5420=>array(56,0,755,913),5421=>array(96,0,583,729),5422=>array(96,0,583,914),5423=>array(88,0,749,729),5424=>array(44,0,732,729),5425=>array(88,0,760,729),5426=>array(27,0,770,729),5427=>array(88,0,760,914),5428=>array(27,0,770,914),5429=>array(88,0,817,729),5430=>array(56,0,732,729),5431=>array(88,0,877,914),5432=>array(56,0,732,914),5433=>array(88,0,771,729),5434=>array(96,0,770,729),5435=>array(88,0,771,914),5436=>array(96,0,770,914),5437=>array(57,0,771,729),5438=>array(65,326,372,734),5440=>array(61,399,340,667),5441=>array(27,326,460,734),5442=>array(100,-14,901,436),5443=>array(86,-14,861,436),5444=>array(-39,0,763,450),5445=>array(54,0,830,755),5446=>array(54,0,830,450),5447=>array(54,0,830,636),5448=>array(27,0,597,729),5449=>array(27,0,597,914),5450=>array(27,0,541,729),5451=>array(63,0,576,729),5452=>array(63,0,576,914),5453=>array(6,0,576,729),5454=>array(88,0,807,914),5455=>array(63,0,706,914),5456=>array(83,326,403,734),5458=>array(-13,0,713,729),5459=>array(114,0,746,744),5460=>array(23,-15,606,1037),5461=>array(23,-15,606,729),5462=>array(23,-15,606,914),5463=>array(-9,0,686,662),5464=>array(-9,0,686,914),5465=>array(54,0,731,662),5466=>array(54,0,731,914),5467=>array(88,0,929,914),5468=>array(54,0,918,914),5469=>array(64,326,483,685),5470=>array(60,-14,716,743),5471=>array(60,-14,695,743),5472=>array(37,-14,672,743),5473=>array(16,-14,672,743),5474=>array(37,-14,672,914),5475=>array(16,-14,672,914),5476=>array(-13,0,682,729),5477=>array(-13,0,682,914),5478=>array(48,0,738,729),5479=>array(48,0,738,914),5480=>array(88,0,955,914),5481=>array(48,0,852,914),5482=>array(61,326,493,734),5492=>array(55,0,758,743),5493=>array(44,0,830,743),5494=>array(44,0,830,914),5495=>array(0,-14,787,729),5496=>array(0,-14,787,914),5497=>array(72,-14,776,729),5498=>array(72,-14,776,914),5499=>array(76,318,497,734),5500=>array(27,0,725,729),5501=>array(27,326,460,734),5502=>array(83,0,1040,1037),5503=>array(83,0,1040,743),5504=>array(83,0,1040,914),5505=>array(83,-14,1021,734),5506=>array(83,-14,1075,914),5507=>array(83,-14,985,734),5508=>array(83,-14,985,914),5509=>array(83,318,783,734),5514=>array(61,0,759,743),5515=>array(44,0,831,743),5516=>array(0,-14,787,729),5517=>array(72,-14,770,729),5518=>array(83,0,1252,1037),5519=>array(83,0,1252,743),5520=>array(83,0,1252,914),5521=>array(83,-14,976,736),5522=>array(83,-14,1030,914),5523=>array(83,-14,1198,736),5524=>array(83,-14,1198,914),5525=>array(83,332,646,736),5526=>array(83,332,1020,736),5536=>array(12,0,822,692),5537=>array(12,0,822,692),5538=>array(-23,-242,787,450),5539=>array(-23,-242,787,636),5540=>array(56,-242,790,450),5541=>array(56,-242,790,636),5542=>array(81,338,545,736),5543=>array(44,0,593,729),5544=>array(-34,0,588,729),5545=>array(-34,0,588,914),5546=>array(55,0,677,729),5547=>array(55,0,677,914),5548=>array(50,0,599,729),5549=>array(50,0,599,914),5550=>array(23,326,372,734),5551=>array(29,-14,574,729),5598=>array(27,0,711,729),5601=>array(98,0,782,729),5702=>array(27,326,446,734),5703=>array(27,240,446,820),5742=>array(27,0,415,306),5743=>array(83,0,976,743),5744=>array(83,0,1238,743),5745=>array(83,0,1625,743),5746=>array(83,0,1625,914),5747=>array(83,-14,1349,736),5748=>array(83,-14,1403,914),5749=>array(83,-14,1571,736),5750=>array(83,-14,1571,914),7424=>array(-23,0,509,547),7425=>array(-48,0,716,547),7426=>array(56,-14,951,560),7427=>array(0,0,531,547),7428=>array(46,-14,536,560),7429=>array(38,0,550,547),7430=>array(12,0,550,547),7431=>array(38,0,490,547),7432=>array(31,-14,493,561),7433=>array(21,-213,258,547),7434=>array(-46,-14,365,547),7435=>array(38,0,617,547),7436=>array(-9,0,460,560),7437=>array(38,0,717,547),7438=>array(38,0,612,547),7439=>array(46,-14,566,560),7440=>array(2,-14,493,560),7441=>array(55,22,629,524),7442=>array(37,57,618,489),7443=>array(57,2,631,543),7444=>array(51,-14,970,560),7446=>array(27,273,529,560),7447=>array(83,-14,585,273),7448=>array(21,0,496,547),7449=>array(-29,0,561,547),7450=>array(78,0,561,547),7451=>array(68,0,606,547),7452=>array(78,-16,564,547),7453=>array(41,37,676,495),7454=>array(56,38,887,496),7455=>array(-55,-238,647,560),7456=>array(72,0,604,547),7457=>array(85,0,819,547),7458=>array(-3,0,543,547),7459=>array(18,-14,488,547),7462=>array(33,0,552,560),7463=>array(-23,0,509,547),7464=>array(21,0,543,547),7465=>array(21,0,496,547),7466=>array(69,0,599,547),7467=>array(-16,0,609,547),7468=>array(-35,326,386,734),7469=>array(-37,326,607,734),7470=>array(22,326,389,734),7472=>array(22,326,448,734),7473=>array(22,326,392,734),7474=>array(1,326,376,734),7475=>array(35,318,458,742),7476=>array(22,326,452,734),7477=>array(22,326,164,734),7478=>array(-83,214,175,734),7479=>array(22,326,450,734),7480=>array(22,326,317,734),7481=>array(22,326,521,734),7482=>array(22,326,449,734),7483=>array(22,326,449,734),7484=>array(35,318,460,742),7485=>array(18,318,413,742),7486=>array(22,326,375,734),7487=>array(22,326,380,734),7488=>array(29,326,426,734),7489=>array(45,318,447,734),7490=>array(61,326,642,734),7491=>array(25,318,333,640),7492=>array(33,318,341,640),7493=>array(35,318,373,640),7494=>array(35,318,598,640),7495=>array(17,318,354,751),7496=>array(24,318,385,751),7497=>array(34,318,356,640),7498=>array(32,318,354,640),7499=>array(29,318,315,640),7500=>array(23,318,309,640),7501=>array(38,209,383,640),7502=>array(18,207,158,632),7503=>array(16,326,374,751),7504=>array(27,326,565,640),7505=>array(38,209,363,640),7506=>array(35,318,351,640),7507=>array(7,318,307,640),7508=>array(19,479,335,640),7509=>array(50,318,367,479),7510=>array(15,209,376,640),7511=>array(31,326,253,719),7512=>array(48,318,373,632),7513=>array(29,347,423,604),7514=>array(52,319,590,633),7515=>array(48,326,384,632),7517=>array(6,209,356,755),7518=>array(42,209,395,632),7519=>array(25,318,347,742),7520=>array(46,209,391,635),7521=>array(-23,209,387,633),7522=>array(18,0,158,425),7523=>array(27,0,289,313),7524=>array(48,-8,373,306),7525=>array(48,0,384,306),7526=>array(6,-117,356,429),7527=>array(42,-117,395,306),7528=>array(6,-117,371,313),7529=>array(46,-117,391,309),7530=>array(-23,-117,387,307),7543=>array(19,-208,583,560),7544=>array(22,326,452,734),7547=>array(3,0,368,547),7549=>array(-3,-208,652,560),7557=>array(30,-208,332,760),7579=>array(5,318,343,640),7580=>array(35,318,334,640),7581=>array(38,287,338,640),7582=>array(22,318,353,751),7583=>array(13,318,304,640),7584=>array(25,326,275,751),7585=>array(-52,209,159,632),7586=>array(38,209,384,632),7587=>array(59,209,383,632),7588=>array(19,326,189,751),7589=>array(51,326,165,632),7590=>array(6,326,228,632),7591=>array(6,326,228,632),7592=>array(-124,209,169,751),7593=>array(28,209,169,751),7594=>array(-8,209,169,751),7595=>array(25,326,292,640),7596=>array(38,209,577,640),7597=>array(63,209,601,633),7598=>array(-53,209,365,640),7599=>array(38,209,383,640),7600=>array(25,326,376,640),7601=>array(35,318,351,640),7602=>array(34,210,351,751),7603=>array(14,209,317,640),7604=>array(-64,209,276,751),7605=>array(42,209,265,719),7606=>array(41,318,449,632),7607=>array(36,318,386,632),7608=>array(50,317,352,632),7609=>array(51,326,341,632),7610=>array(-11,326,324,632),7611=>array(-3,326,333,632),7612=>array(8,209,345,632),7613=>array(0,296,336,632),7614=>array(-11,207,344,632),7615=>array(35,320,351,756),7620=>array(-452,616,-61,800),7621=>array(-472,616,-28,800),7622=>array(-472,616,-28,800),7623=>array(-439,616,-48,800),7624=>array(-313,616,87,800),7625=>array(-348,616,123,800),7680=>array(-53,-241,615,729),7681=>array(41,-241,547,560),7682=>array(27,0,625,913),7683=>array(36,-14,587,915),7684=>array(27,-184,625,729),7685=>array(36,-184,587,760),7686=>array(27,-157,625,729),7687=>array(36,-157,587,760),7688=>array(42,-193,695,928),7689=>array(46,-193,536,800),7690=>array(27,0,722,914),7691=>array(46,-14,674,942),7692=>array(27,-184,722,729),7693=>array(46,-184,639,760),7694=>array(27,-156,722,729),7695=>array(46,-157,639,760),7696=>array(27,-193,722,729),7697=>array(44,-193,639,760),7698=>array(27,-240,722,729),7699=>array(34,-240,639,760),7700=>array(27,0,630,1044),7701=>array(46,-14,571,887),7702=>array(27,0,630,1044),7703=>array(46,-14,608,887),7704=>array(27,-213,630,729),7705=>array(46,-213,571,560),7706=>array(27,-193,630,729),7707=>array(46,-193,571,560),7708=>array(27,-193,630,928),7709=>array(46,-193,586,780),7710=>array(27,0,587,914),7711=>array(68,0,478,942),7712=>array(45,-14,725,899),7713=>array(32,-208,596,745),7714=>array(27,0,725,914),7715=>array(35,0,566,942),7716=>array(27,-184,725,729),7717=>array(35,-184,566,760),7718=>array(27,0,725,913),7719=>array(35,0,587,913),7720=>array(-79,-193,725,729),7721=>array(-77,-193,566,760),7722=>array(27,-222,725,729),7723=>array(35,-222,566,760),7724=>array(-110,-193,268,729),7725=>array(-127,-193,273,760),7726=>array(27,0,447,1044),7727=>array(35,0,437,883),7728=>array(27,0,722,928),7729=>array(35,0,612,928),7730=>array(27,-184,722,729),7731=>array(35,-184,612,760),7732=>array(27,-157,722,729),7733=>array(35,-157,612,760),7734=>array(27,-184,497,729),7735=>array(-2,-184,273,760),7736=>array(27,-184,497,927),7737=>array(-2,-184,411,899),7738=>array(27,-157,497,729),7739=>array(-92,-157,273,760),7740=>array(27,-240,497,729),7741=>array(-123,-240,273,760),7742=>array(27,0,836,928),7743=>array(35,0,906,800),7744=>array(27,0,836,914),7745=>array(35,0,906,760),7746=>array(27,-184,836,729),7747=>array(35,-184,906,560),7748=>array(27,0,721,913),7749=>array(35,0,566,760),7750=>array(27,-184,721,729),7751=>array(35,-184,566,560),7752=>array(27,-157,721,729),7753=>array(35,-157,566,560),7754=>array(27,-240,721,729),7755=>array(35,-240,566,560),7756=>array(40,-14,747,1044),7757=>array(46,-14,629,883),7758=>array(40,-14,747,1043),7759=>array(46,-14,583,885),7760=>array(40,-14,747,1044),7761=>array(46,-14,566,887),7762=>array(40,-14,747,1045),7763=>array(46,-14,600,886),7764=>array(27,0,601,928),7765=>array(-3,-208,589,800),7766=>array(27,0,601,914),7767=>array(-3,-208,589,760),7768=>array(27,0,600,914),7769=>array(35,0,463,760),7770=>array(27,-184,600,729),7771=>array(-2,-184,463,560),7772=>array(27,-184,600,899),7773=>array(-2,-184,504,745),7774=>array(27,-157,600,729),7775=>array(-93,-157,463,560),7776=>array(6,-14,603,914),7777=>array(11,-14,500,760),7778=>array(6,-184,603,742),7779=>array(11,-184,500,560),7780=>array(6,-14,648,928),7781=>array(11,-14,642,800),7782=>array(6,-14,659,1042),7783=>array(11,-14,571,858),7784=>array(6,-184,603,914),7785=>array(11,-184,500,760),7786=>array(43,0,676,914),7787=>array(64,0,423,942),7788=>array(43,-184,676,729),7789=>array(64,-184,423,702),7790=>array(43,-157,676,729),7791=>array(19,-156,423,702),7792=>array(23,-241,676,729),7793=>array(-10,-240,423,702),7794=>array(58,-183,713,729),7795=>array(57,-183,589,547),7796=>array(58,-193,713,729),7797=>array(28,-193,589,547),7798=>array(58,-213,713,729),7799=>array(57,-213,589,547),7800=>array(58,-14,713,1044),7801=>array(57,-14,619,883),7802=>array(58,-14,713,1025),7803=>array(57,-14,589,867),7804=>array(78,0,742,936),7805=>array(72,0,604,777),7806=>array(78,-182,742,729),7807=>array(72,-184,604,547),7808=>array(96,0,1020,931),7809=>array(85,0,819,802),7810=>array(96,0,1020,931),7811=>array(85,0,819,803),7812=>array(96,0,1020,913),7813=>array(85,0,819,758),7814=>array(96,0,1020,913),7815=>array(85,0,819,760),7816=>array(96,-184,1020,729),7817=>array(85,-184,819,547),7818=>array(-43,0,703,914),7819=>array(-26,0,600,760),7820=>array(-43,0,703,913),7821=>array(-26,0,600,758),7822=>array(63,0,676,914),7823=>array(-25,-208,603,760),7824=>array(-22,0,703,928),7825=>array(-3,0,543,800),7826=>array(-22,-184,703,729),7827=>array(-3,-184,543,547),7828=>array(-22,-157,703,729),7829=>array(-3,-157,543,547),7830=>array(35,-157,566,760),7831=>array(64,0,423,913),7832=>array(85,0,819,878),7833=>array(-25,-208,603,878),7834=>array(41,-14,777,760),7835=>array(68,0,478,942),7836=>array(-22,0,445,760),7837=>array(28,0,445,760),7838=>array(16,-14,682,743),7839=>array(38,-14,557,742),7840=>array(-53,-184,615,729),7841=>array(41,-184,547,560),7842=>array(-53,0,615,992),7843=>array(41,-14,555,810),7844=>array(-53,0,770,1028),7845=>array(41,-14,712,847),7846=>array(-53,0,615,1028),7847=>array(41,-14,547,847),7848=>array(-53,0,773,1044),7849=>array(41,-14,711,863),7850=>array(-53,0,641,1043),7851=>array(41,-14,580,862),7852=>array(-53,-184,615,928),7853=>array(41,-184,547,800),7854=>array(-53,0,649,1044),7855=>array(41,-14,594,868),7856=>array(-53,0,615,1044),7857=>array(41,-14,558,868),7858=>array(-53,0,615,1068),7859=>array(41,-14,552,895),7860=>array(-53,0,651,1043),7861=>array(41,-14,596,870),7862=>array(-53,-184,624,926),7863=>array(41,-184,562,761),7864=>array(27,-184,630,729),7865=>array(46,-184,571,560),7866=>array(27,0,630,992),7867=>array(46,-14,583,810),7868=>array(27,0,630,921),7869=>array(46,-14,571,777),7870=>array(27,0,760,1028),7871=>array(46,-14,741,847),7872=>array(27,0,630,1028),7873=>array(46,-14,571,847),7874=>array(27,0,764,1044),7875=>array(46,-14,746,863),7876=>array(27,0,631,1043),7877=>array(46,-14,614,862),7878=>array(27,-184,630,928),7879=>array(46,-184,571,800),7880=>array(27,0,368,992),7881=>array(35,0,336,810),7882=>array(-6,-184,268,729),7883=>array(-2,-184,273,760),7884=>array(40,-184,747,742),7885=>array(46,-184,566,560),7886=>array(40,-14,747,992),7887=>array(46,-14,575,810),7888=>array(40,-14,821,1028),7889=>array(46,-14,736,847),7890=>array(40,-14,747,1028),7891=>array(46,-14,566,847),7892=>array(40,-14,824,1044),7893=>array(46,-14,736,863),7894=>array(40,-14,747,1043),7895=>array(46,-14,604,862),7896=>array(40,-184,747,928),7897=>array(46,-184,566,800),7898=>array(34,-14,823,927),7899=>array(48,-14,657,800),7900=>array(34,-14,823,927),7901=>array(48,-14,657,800),7902=>array(34,-14,823,991),7903=>array(48,-14,657,810),7904=>array(34,-14,823,921),7905=>array(48,-14,657,777),7906=>array(34,-184,823,761),7907=>array(48,-184,657,609),7908=>array(58,-184,713,729),7909=>array(57,-184,589,547),7910=>array(58,-14,713,992),7911=>array(57,-14,589,810),7912=>array(56,-4,854,927),7913=>array(58,-14,720,800),7914=>array(56,-4,854,927),7915=>array(58,-14,720,800),7916=>array(56,-4,854,992),7917=>array(58,-14,720,810),7918=>array(56,-4,854,921),7919=>array(58,-14,720,777),7920=>array(56,-184,854,761),7921=>array(58,-184,720,615),7922=>array(63,0,676,931),7923=>array(-25,-208,603,802),7924=>array(63,-184,676,729),7925=>array(-25,-208,603,547),7926=>array(63,0,676,996),7927=>array(-25,-208,603,813),7928=>array(63,0,676,921),7929=>array(-25,-208,603,777),7930=>array(27,0,709,729),7931=>array(21,0,522,760),7936=>array(55,-12,645,797),7937=>array(55,-12,645,797),7938=>array(55,-12,645,800),7939=>array(55,-12,645,800),7940=>array(55,-12,645,800),7941=>array(55,-12,646,800),7942=>array(55,-12,645,928),7943=>array(55,-12,645,928),7944=>array(-53,0,615,797),7945=>array(-53,0,615,797),7946=>array(51,0,809,800),7947=>array(79,0,809,800),7948=>array(32,0,700,800),7949=>array(64,0,732,800),7950=>array(-29,0,639,928),7951=>array(5,0,674,928),7952=>array(39,-14,506,797),7953=>array(39,-14,506,797),7954=>array(39,-14,533,800),7955=>array(39,-14,532,800),7956=>array(39,-14,593,800),7957=>array(39,-14,608,800),7960=>array(52,0,709,797),7961=>array(79,0,709,797),7962=>array(51,0,964,800),7963=>array(79,0,973,800),7964=>array(52,0,896,800),7965=>array(78,0,926,800),7968=>array(57,-208,579,797),7969=>array(57,-208,579,797),7970=>array(57,-208,580,800),7971=>array(57,-208,579,800),7972=>array(57,-208,619,800),7973=>array(57,-208,653,800),7974=>array(57,-208,622,928),7975=>array(57,-208,611,928),7976=>array(52,0,810,797),7977=>array(79,0,809,797),7978=>array(51,0,1059,800),7979=>array(79,0,1062,800),7980=>array(52,0,1000,800),7981=>array(78,0,1024,800),7982=>array(111,0,907,928),7983=>array(109,0,920,928),7984=>array(67,0,282,797),7985=>array(67,0,279,797),7986=>array(10,0,412,800),7987=>array(42,0,418,800),7988=>array(51,0,469,800),7989=>array(53,0,473,800),7990=>array(67,0,431,928),7991=>array(67,0,428,928),7992=>array(52,0,353,797),7993=>array(79,0,347,797),7994=>array(51,0,608,800),7995=>array(79,0,608,800),7996=>array(52,0,543,800),7997=>array(78,0,573,800),7998=>array(111,0,463,928),7999=>array(109,0,466,928),8000=>array(46,-14,566,797),8001=>array(46,-14,566,797),8002=>array(46,-14,567,800),8003=>array(46,-14,566,800),8004=>array(46,-14,621,800),8005=>array(46,-14,639,800),8008=>array(52,-14,764,797),8009=>array(79,-14,808,797),8010=>array(51,-14,1055,800),8011=>array(79,-14,1060,800),8012=>array(52,-14,898,800),8013=>array(78,-14,930,800),8016=>array(59,0,533,797),8017=>array(59,0,533,797),8018=>array(59,0,537,800),8019=>array(59,0,533,800),8020=>array(59,0,601,800),8021=>array(59,0,611,800),8022=>array(59,0,573,928),8023=>array(59,0,557,928),8025=>array(79,0,849,797),8027=>array(79,0,1063,800),8029=>array(78,0,1077,800),8031=>array(109,0,963,928),8032=>array(68,-14,771,797),8033=>array(68,-14,771,797),8034=>array(68,-14,771,800),8035=>array(68,-14,771,800),8036=>array(68,-14,771,800),8037=>array(68,-14,771,800),8038=>array(68,-14,771,928),8039=>array(68,-14,771,928),8040=>array(4,0,761,797),8041=>array(45,0,802,797),8042=>array(51,0,1048,800),8043=>array(79,0,1054,800),8044=>array(52,0,904,800),8045=>array(78,0,931,800),8046=>array(111,0,880,928),8047=>array(109,0,911,928),8048=>array(55,-12,645,800),8049=>array(55,-12,645,800),8050=>array(39,-14,506,800),8051=>array(39,-14,561,800),8052=>array(57,-208,579,800),8053=>array(57,-208,619,800),8054=>array(51,0,265,800),8055=>array(67,0,431,800),8056=>array(46,-14,566,800),8057=>array(46,-14,583,800),8058=>array(59,0,533,800),8059=>array(59,0,539,800),8060=>array(68,-14,771,800),8061=>array(68,-14,771,800),8064=>array(55,-208,645,797),8065=>array(55,-208,645,797),8066=>array(55,-208,645,800),8067=>array(55,-208,645,800),8068=>array(55,-208,645,800),8069=>array(55,-208,646,800),8070=>array(55,-208,645,928),8071=>array(55,-208,645,928),8072=>array(-53,-208,615,797),8073=>array(-53,-208,615,797),8074=>array(51,-208,809,800),8075=>array(79,-208,809,800),8076=>array(32,-208,700,800),8077=>array(64,-208,732,800),8078=>array(-29,-208,639,928),8079=>array(5,-208,674,928),8080=>array(39,-208,579,797),8081=>array(39,-208,579,797),8082=>array(39,-208,580,800),8083=>array(39,-208,579,800),8084=>array(39,-208,619,800),8085=>array(39,-208,653,800),8086=>array(39,-208,622,928),8087=>array(39,-208,611,928),8088=>array(52,-208,810,797),8089=>array(79,-208,809,797),8090=>array(51,-208,1059,800),8091=>array(79,-208,1062,800),8092=>array(52,-208,1000,800),8093=>array(78,-208,1024,800),8094=>array(111,-208,907,928),8095=>array(109,-208,920,928),8096=>array(68,-208,771,797),8097=>array(68,-208,771,797),8098=>array(68,-208,771,800),8099=>array(68,-208,771,800),8100=>array(68,-208,771,800),8101=>array(68,-208,771,800),8102=>array(68,-208,771,928),8103=>array(68,-208,771,928),8104=>array(4,-208,761,797),8105=>array(45,-208,802,797),8106=>array(51,-208,1048,800),8107=>array(79,-208,1054,800),8108=>array(52,-208,904,800),8109=>array(78,-208,931,800),8110=>array(111,-208,880,928),8111=>array(109,-208,911,928),8112=>array(55,-12,645,785),8113=>array(55,-12,645,745),8114=>array(55,-208,645,800),8115=>array(55,-208,645,559),8116=>array(55,-208,645,800),8118=>array(55,-12,645,777),8119=>array(55,-208,645,777),8120=>array(-53,0,615,928),8121=>array(-53,0,615,899),8122=>array(-21,0,647,800),8123=>array(-53,0,615,800),8124=>array(-53,-208,615,729),8125=>array(239,595,397,797),8126=>array(136,-208,240,-45),8127=>array(239,595,397,797),8128=>array(164,639,513,777),8129=>array(184,659,545,928),8130=>array(39,-208,579,800),8131=>array(39,-208,579,560),8132=>array(39,-208,619,800),8134=>array(57,-208,583,777),8135=>array(39,-208,583,777),8136=>array(105,0,803,800),8137=>array(59,0,765,800),8138=>array(105,0,904,800),8139=>array(64,0,869,800),8140=>array(27,-208,725,729),8141=>array(116,595,518,800),8142=>array(137,595,554,800),8143=>array(196,595,545,928),8144=>array(67,0,399,785),8145=>array(67,0,374,745),8146=>array(67,0,391,978),8147=>array(74,0,450,978),8150=>array(62,0,411,777),8151=>array(67,0,444,928),8152=>array(27,0,394,928),8153=>array(27,0,391,899),8154=>array(105,0,448,800),8155=>array(62,0,409,800),8157=>array(137,595,514,800),8158=>array(148,595,568,800),8159=>array(196,595,545,928),8160=>array(59,0,533,785),8161=>array(59,0,533,745),8162=>array(59,0,533,978),8163=>array(59,0,566,978),8164=>array(16,-208,599,797),8165=>array(16,-208,599,797),8166=>array(59,0,533,777),8167=>array(59,0,558,928),8168=>array(63,0,676,928),8169=>array(63,0,676,899),8170=>array(105,0,910,800),8171=>array(56,0,919,800),8172=>array(79,0,683,797),8173=>array(184,659,493,978),8174=>array(184,659,553,978),8175=>array(190,617,388,800),8178=>array(68,-208,771,800),8179=>array(68,-208,771,547),8180=>array(68,-208,771,800),8182=>array(68,-14,771,777),8183=>array(68,-208,771,777),8184=>array(105,-14,901,800),8185=>array(64,-14,793,800),8186=>array(105,0,881,800),8187=>array(53,0,828,800),8188=>array(-34,-208,723,738),8189=>array(252,616,522,800),8190=>array(266,595,398,797),8208=>array(45,234,324,314),8209=>array(45,234,324,314),8210=>array(42,239,594,309),8211=>array(42,239,458,309),8212=>array(42,239,958,309),8213=>array(-7,239,1007,309),8214=>array(127,-236,371,764),8215=>array(-10,-236,510,-9),8216=>array(131,489,321,729),8217=>array(135,489,325,729),8218=>array(3,-116,193,124),8219=>array(165,489,287,729),8220=>array(131,489,521,729),8221=>array(135,489,525,729),8222=>array(3,-116,393,124),8223=>array(92,489,412,729),8224=>array(42,-96,501,729),8225=>array(-17,-96,508,729),8226=>array(150,227,440,516),8227=>array(150,188,479,555),8228=>array(65,0,192,124),8229=>array(65,0,525,124),8230=>array(65,0,859,124),8231=>array(99,302,226,426),8240=>array(91,-14,1259,742),8241=>array(91,-14,1659,742),8242=>array(2,547,221,729),8243=>array(2,547,367,729),8244=>array(2,547,514,729),8245=>array(90,547,238,729),8246=>array(90,547,385,729),8247=>array(90,547,531,729),8248=>array(5,-236,333,-30),8249=>array(62,69,338,517),8250=>array(62,69,338,517),8251=>array(114,0,717,596),8252=>array(0,0,483,729),8253=>array(115,0,500,742),8254=>array(-10,686,510,755),8255=>array(-43,-237,847,-60),8256=>array(-43,752,847,929),8257=>array(-42,-236,286,229),8258=>array(30,-29,970,814),8259=>array(97,313,411,421),8260=>array(-262,-14,428,742),8261=>array(40,-132,420,760),8262=>array(-39,-132,342,760),8263=>array(87,0,937,742),8264=>array(123,0,731,742),8265=>array(0,0,711,742),8266=>array(98,-123,513,545),8267=>array(54,-96,633,729),8268=>array(112,227,387,516),8269=>array(112,227,387,516),8270=>array(30,-29,470,427),8271=>array(96,-116,287,517),8272=>array(-43,-237,847,929),8273=>array(30,-7,470,876),8274=>array(-9,-93,491,729),8275=>array(49,228,951,399),8276=>array(-43,-237,847,-60),8277=>array(160,98,708,631),8278=>array(129,149,523,589),8279=>array(2,547,660,729),8280=>array(182,125,688,613),8281=>array(154,120,726,608),8282=>array(51,0,296,729),8283=>array(52,-138,776,867),8284=>array(63,0,806,729),8285=>array(59,39,282,655),8286=>array(53,8,287,683),8304=>array(42,319,367,742),8305=>array(18,326,158,751),8308=>array(41,326,390,734),8309=>array(13,319,359,734),8310=>array(45,319,376,742),8311=>array(78,326,394,734),8312=>array(26,319,375,742),8313=>array(33,319,364,742),8314=>array(67,326,461,677),8315=>array(67,479,461,525),8316=>array(67,422,461,581),8317=>array(55,252,246,751),8318=>array(7,252,198,751),8319=>array(26,326,352,640),8320=>array(42,-7,367,416),8321=>array(66,0,347,408),8322=>array(36,0,385,416),8323=>array(16,-7,368,416),8324=>array(41,0,390,408),8325=>array(13,-7,359,408),8326=>array(45,-7,376,416),8327=>array(78,0,394,408),8328=>array(26,-7,375,416),8329=>array(33,-7,364,416),8330=>array(67,0,461,351),8331=>array(67,152,461,199),8332=>array(67,96,461,254),8333=>array(55,-74,246,425),8334=>array(7,-74,198,425),8336=>array(25,-8,333,313),8337=>array(34,-8,356,313),8338=>array(35,-8,351,313),8339=>array(27,0,415,306),8340=>array(32,-8,354,313),8341=>array(16,0,340,425),8342=>array(16,0,374,425),8343=>array(16,0,155,425),8344=>array(27,0,565,313),8345=>array(26,0,352,314),8346=>array(15,-117,376,313),8347=>array(30,0,330,322),8348=>array(31,0,253,393),8352=>array(58,0,864,729),8353=>array(42,-44,636,778),8354=>array(42,-14,636,742),8355=>array(32,0,657,729),8356=>array(24,0,637,742),8357=>array(38,-93,900,640),8358=>array(38,0,710,729),8359=>array(27,-14,1250,729),8360=>array(28,-14,1029,729),8361=>array(43,0,1027,729),8362=>array(-24,-14,826,729),8363=>array(46,-157,701,760),8364=>array(-19,-14,607,742),8365=>array(19,0,682,729),8366=>array(64,0,698,729),8367=>array(47,-222,1178,742),8368=>array(9,-14,578,742),8369=>array(27,0,655,729),8370=>array(32,-81,630,809),8371=>array(-63,0,632,729),8372=>array(38,-14,736,742),8373=>array(84,-147,611,760),8376=>array(37,0,697,729),8377=>array(56,0,656,729),8378=>array(-20,2,649,731),8400=>array(-503,635,-28,760),8401=>array(-482,635,-17,760),8406=>array(-470,560,-21,760),8407=>array(-475,560,-26,760),8411=>array(-360,659,140,758),8412=>array(-456,659,235,758),8417=>array(-470,560,-26,760),8448=>array(17,-24,939,752),8449=>array(17,-24,939,752),8450=>array(56,-14,644,742),8451=>array(95,-14,1104,742),8452=>array(114,0,771,729),8453=>array(22,-24,924,752),8454=>array(22,-24,989,752),8455=>array(121,-14,676,742),8456=>array(-6,-146,642,611),8457=>array(95,0,916,742),8459=>array(36,-14,943,748),8460=>array(1,-128,693,731),8461=>array(98,0,751,729),8462=>array(35,0,566,760),8463=>array(44,0,566,760),8464=>array(29,-15,432,742),8465=>array(52,-14,659,742),8466=>array(33,-14,679,743),8467=>array(-14,-14,353,742),8468=>array(22,-14,762,760),8469=>array(97,0,704,729),8470=>array(-44,0,962,729),8471=>array(138,0,862,724),8472=>array(54,-221,658,495),8473=>array(98,0,666,729),8474=>array(56,-129,731,742),8475=>array(32,-9,764,774),8476=>array(41,-14,803,743),8477=>array(98,0,774,729),8478=>array(83,0,814,729),8479=>array(93,-107,670,847),8480=>array(126,443,770,730),8481=>array(32,0,987,547),8482=>array(144,447,784,729),8483=>array(14,-108,817,846),8484=>array(45,0,700,729),8485=>array(9,-213,627,760),8486=>array(-34,0,723,738),8487=>array(42,-14,798,724),8488=>array(12,-149,573,783),8489=>array(71,0,270,547),8490=>array(27,0,722,729),8491=>array(-53,0,615,928),8492=>array(45,0,734,772),8493=>array(63,-12,652,742),8494=>array(61,-12,793,647),8495=>array(42,-15,547,533),8496=>array(79,-14,565,742),8497=>array(41,-16,758,755),8498=>array(27,0,587,729),8499=>array(28,-28,1032,751),8500=>array(51,-12,411,395),8501=>array(50,-14,712,742),8502=>array(-2,-14,653,743),8503=>array(13,-35,407,742),8504=>array(42,-35,591,742),8505=>array(34,0,355,760),8506=>array(44,-21,967,654),8507=>array(20,0,1198,547),8508=>array(18,-8,685,547),8509=>array(0,-194,669,560),8510=>array(98,0,648,729),8511=>array(98,0,750,729),8512=>array(12,-192,791,719),8513=>array(47,-14,728,742),8514=>array(59,0,529,729),8515=>array(3,0,599,729),8516=>array(-65,0,548,729),8517=>array(42,0,786,729),8518=>array(44,-14,709,760),8519=>array(44,-14,572,560),8520=>array(39,0,313,760),8521=>array(-114,-208,313,760),8523=>array(58,-14,742,742),8526=>array(-14,0,495,547),8528=>array(66,-14,962,742),8529=>array(66,-14,932,742),8530=>array(66,-14,1335,742),8531=>array(66,-14,936,742),8532=>array(36,-14,936,742),8533=>array(66,-14,927,742),8534=>array(36,-14,927,742),8535=>array(16,-14,927,742),8536=>array(41,-14,927,742),8537=>array(66,-14,944,742),8538=>array(13,-14,944,742),8539=>array(66,-14,943,742),8540=>array(16,-14,943,742),8541=>array(13,-14,943,742),8542=>array(78,-14,943,742),8543=>array(66,-14,829,742),8544=>array(27,0,268,729),8545=>array(27,0,465,729),8546=>array(27,0,663,729),8547=>array(27,0,981,729),8548=>array(78,0,742,729),8549=>array(78,0,896,729),8550=>array(78,0,1093,729),8551=>array(78,0,1290,729),8552=>array(27,0,936,729),8553=>array(-43,0,703,729),8554=>array(-43,0,906,729),8555=>array(-43,0,1104,729),8556=>array(27,0,497,729),8557=>array(42,-14,695,742),8558=>array(27,0,722,729),8559=>array(27,0,836,729),8560=>array(35,0,273,760),8561=>array(35,0,453,760),8562=>array(35,0,632,760),8563=>array(35,0,824,760),8564=>array(72,0,604,547),8565=>array(72,0,806,760),8566=>array(72,0,986,760),8567=>array(72,0,1166,760),8568=>array(35,0,827,760),8569=>array(-26,0,600,547),8570=>array(-26,0,817,760),8571=>array(-26,0,997,760),8572=>array(35,0,273,760),8573=>array(46,-14,536,560),8574=>array(46,-14,639,760),8575=>array(35,0,906,560),8576=>array(59,0,1187,729),8577=>array(27,0,711,729),8578=>array(59,0,1187,729),8579=>array(63,-14,715,742),8580=>array(2,-14,493,560),8581=>array(75,-208,723,742),8585=>array(42,-14,936,742),8592=>array(49,100,781,527),8593=>array(205,0,632,732),8594=>array(57,100,789,527),8595=>array(205,-3,632,729),8596=>array(49,100,789,527),8597=>array(205,-8,632,732),8598=>array(141,25,703,587),8599=>array(141,25,703,587),8600=>array(141,25,703,587),8601=>array(141,25,703,587),8602=>array(49,100,781,527),8603=>array(57,100,789,527),8604=>array(21,103,827,414),8605=>array(11,103,816,414),8606=>array(49,100,781,527),8607=>array(206,0,633,732),8608=>array(57,100,789,527),8609=>array(206,-3,633,729),8610=>array(49,100,781,527),8611=>array(57,100,789,527),8612=>array(49,100,781,527),8613=>array(206,0,632,732),8614=>array(57,100,789,527),8615=>array(206,-3,632,729),8616=>array(206,0,632,732),8617=>array(49,100,780,565),8618=>array(58,100,789,565),8619=>array(49,100,780,565),8620=>array(58,100,789,565),8621=>array(49,100,789,527),8622=>array(49,93,789,534),8623=>array(146,-2,702,730),8624=>array(169,0,629,743),8625=>array(209,0,669,743),8626=>array(169,-14,629,729),8627=>array(209,-14,669,729),8628=>array(233,-3,760,604),8629=>array(49,100,656,626),8630=>array(22,203,799,668),8631=>array(39,203,816,668),8632=>array(108,25,788,729),8633=>array(55,-46,783,673),8634=>array(103,62,762,680),8635=>array(77,62,736,680),8636=>array(49,272,781,527),8637=>array(49,100,781,355),8638=>array(377,0,632,732),8639=>array(205,0,460,732),8640=>array(57,272,789,527),8641=>array(57,100,789,355),8642=>array(377,0,632,732),8643=>array(205,0,460,732),8644=>array(49,-47,789,674),8645=>array(58,-3,779,732),8646=>array(49,-47,789,674),8647=>array(49,-47,781,674),8648=>array(59,0,779,732),8649=>array(58,-47,790,674),8650=>array(59,-3,779,729),8651=>array(49,7,789,620),8652=>array(49,7,789,620),8653=>array(49,100,781,527),8654=>array(49,94,789,533),8655=>array(57,100,789,527),8656=>array(49,100,781,527),8657=>array(206,0,633,732),8658=>array(57,100,789,527),8659=>array(206,-3,633,729),8660=>array(49,100,789,527),8661=>array(205,-8,633,732),8662=>array(141,-23,751,587),8663=>array(92,-23,703,587),8664=>array(92,25,703,636),8665=>array(141,25,751,636),8666=>array(49,100,781,527),8667=>array(57,100,789,527),8668=>array(49,100,781,527),8669=>array(57,100,789,527),8670=>array(205,0,632,732),8671=>array(205,-3,632,729),8672=>array(49,100,781,527),8673=>array(205,0,633,732),8674=>array(57,100,789,527),8675=>array(205,-3,633,729),8676=>array(52,99,781,528),8677=>array(57,99,786,528),8678=>array(27,65,781,562),8679=>array(171,0,667,754),8680=>array(35,65,789,562),8681=>array(171,-25,667,729),8682=>array(171,0,667,754),8683=>array(171,0,667,754),8684=>array(156,0,682,754),8685=>array(171,0,667,754),8686=>array(171,0,667,754),8687=>array(171,0,667,754),8688=>array(57,65,811,562),8689=>array(60,0,788,729),8690=>array(60,0,788,729),8691=>array(171,-25,667,754),8692=>array(57,100,789,527),8693=>array(58,-3,779,732),8694=>array(57,-193,789,820),8695=>array(49,94,781,533),8696=>array(57,94,789,533),8697=>array(49,94,789,533),8698=>array(49,94,781,533),8699=>array(57,94,789,533),8700=>array(49,94,789,533),8701=>array(27,96,781,531),8702=>array(57,96,811,531),8703=>array(27,96,811,531),8704=>array(8,0,676,729),8705=>array(66,-14,554,742),8706=>array(46,-14,471,662),8707=>array(98,0,568,729),8708=>array(98,-46,568,776),8709=>array(76,-10,795,710),8710=>array(-3,0,672,719),8711=>array(-3,0,672,719),8712=>array(85,-10,786,710),8713=>array(85,-139,786,836),8714=>array(106,76,612,550),8715=>array(85,-10,786,710),8716=>array(85,-139,786,836),8717=>array(106,76,612,550),8718=>array(146,0,490,485),8719=>array(76,-192,680,719),8720=>array(76,-192,680,719),8721=>array(12,-192,654,719),8722=>array(106,272,732,355),8723=>array(106,0,732,627),8724=>array(106,0,732,729),8725=>array(-73,-93,427,729),8726=>array(192,-54,529,768),8727=>array(127,0,710,627),8728=>array(158,160,468,470),8729=>array(168,168,458,458),8730=>array(30,-20,637,811),8731=>array(30,-20,637,933),8732=>array(30,-20,637,924),8733=>array(107,112,607,487),8734=>array(107,112,726,487),8735=>array(138,99,700,661),8736=>array(85,0,786,729),8737=>array(85,-53,786,729),8738=>array(116,-3,732,727),8739=>array(211,-214,289,771),8740=>array(50,-214,451,771),8741=>array(133,-214,367,771),8742=>array(50,-214,451,771),8743=>array(128,0,604,579),8744=>array(128,0,604,579),8745=>array(128,0,604,579),8746=>array(128,0,604,579),8747=>array(57,-212,464,757),8748=>array(57,-212,732,757),8749=>array(57,-212,1000,757),8750=>array(57,-212,464,757),8751=>array(57,-212,732,757),8752=>array(57,-212,1000,757),8753=>array(57,-212,522,757),8754=>array(57,-212,514,757),8755=>array(57,-212,515,757),8756=>array(59,100,577,604),8757=>array(59,100,577,604),8758=>array(79,100,182,604),8759=>array(59,100,577,604),8760=>array(106,272,732,552),8761=>array(106,78,732,552),8762=>array(105,78,732,552),8763=>array(106,78,732,552),8764=>array(106,228,732,399),8765=>array(106,228,732,399),8766=>array(79,149,759,479),8767=>array(106,42,732,584),8768=>array(102,0,273,627),8769=>array(106,77,732,553),8770=>array(106,133,732,454),8771=>array(106,172,732,494),8772=>array(106,47,732,603),8773=>array(106,90,732,594),8774=>array(106,11,732,594),8775=>array(106,-5,732,658),8776=>array(106,133,732,494),8777=>array(106,2,732,625),8778=>array(106,90,732,598),8779=>array(106,59,732,602),8780=>array(106,90,732,594),8781=>array(105,105,732,521),8782=>array(106,26,732,601),8783=>array(106,172,732,601),8784=>array(106,172,732,625),8785=>array(106,1,732,625),8786=>array(104,2,732,625),8787=>array(104,2,731,625),8788=>array(101,151,899,476),8789=>array(100,151,900,475),8790=>array(106,172,732,454),8791=>array(106,172,732,760),8792=>array(106,172,732,662),8793=>array(106,172,732,812),8794=>array(106,172,732,812),8795=>array(106,172,732,849),8796=>array(106,172,732,854),8797=>array(106,172,732,764),8798=>array(106,172,732,760),8799=>array(106,172,732,856),8800=>array(106,19,732,608),8801=>array(106,90,732,537),8802=>array(106,-24,732,650),8803=>array(106,0,732,629),8804=>array(106,0,732,582),8805=>array(106,0,732,582),8806=>array(106,-83,732,638),8807=>array(106,-83,732,638),8808=>array(106,-164,732,638),8809=>array(106,-164,732,638),8810=>array(72,22,975,609),8811=>array(72,22,975,609),8812=>array(86,-132,378,759),8813=>array(105,13,732,613),8814=>array(106,2,732,674),8815=>array(106,-47,732,625),8816=>array(106,-102,732,667),8817=>array(106,-102,732,667),8818=>array(106,-55,732,582),8819=>array(106,-40,732,582),8820=>array(106,-105,732,664),8821=>array(106,-102,732,667),8822=>array(102,-87,732,686),8823=>array(102,-87,732,686),8824=>array(102,-197,732,797),8825=>array(102,-197,732,797),8826=>array(106,-38,732,664),8827=>array(106,-38,732,664),8828=>array(106,-105,732,667),8829=>array(106,-105,732,667),8830=>array(106,-85,732,667),8831=>array(106,-85,732,667),8832=>array(106,-61,732,764),8833=>array(106,-138,732,687),8834=>array(99,80,739,546),8835=>array(99,80,739,546),8836=>array(99,-96,739,726),8837=>array(99,-100,739,722),8838=>array(93,0,732,613),8839=>array(106,0,745,613),8840=>array(93,-116,732,730),8841=>array(106,-116,745,730),8842=>array(93,-73,732,613),8843=>array(93,-73,732,613),8844=>array(128,0,604,579),8845=>array(128,0,604,579),8846=>array(128,2,604,582),8847=>array(106,0,732,568),8848=>array(106,0,732,568),8849=>array(106,-83,732,630),8850=>array(106,-83,732,630),8851=>array(106,0,674,626),8852=>array(106,0,674,626),8853=>array(91,-14,747,643),8854=>array(91,-14,747,643),8855=>array(91,-14,747,643),8856=>array(91,-14,747,643),8857=>array(91,-14,747,643),8858=>array(91,-14,747,643),8859=>array(91,-14,747,643),8860=>array(91,-14,747,643),8861=>array(91,-14,747,643),8862=>array(91,-14,747,643),8863=>array(91,-14,747,643),8864=>array(91,-14,747,643),8865=>array(91,-14,747,643),8866=>array(85,0,786,700),8867=>array(85,0,786,700),8868=>array(85,0,786,700),8869=>array(85,0,786,700),8870=>array(85,0,436,700),8871=>array(85,0,436,700),8872=>array(85,0,786,700),8873=>array(85,0,786,700),8874=>array(85,0,786,700),8875=>array(85,0,786,700),8876=>array(85,-40,786,740),8877=>array(85,-40,786,740),8878=>array(85,-40,786,740),8879=>array(85,-40,786,740),8880=>array(106,-43,724,670),8881=>array(106,-43,724,670),8882=>array(106,15,732,612),8883=>array(106,15,732,612),8884=>array(106,-48,732,674),8885=>array(106,-48,732,674),8886=>array(59,175,941,455),8887=>array(59,175,941,455),8888=>array(47,175,791,455),8889=>array(59,-47,779,674),8890=>array(116,0,404,701),8891=>array(98,0,634,740),8892=>array(98,0,634,740),8893=>array(98,0,634,740),8894=>array(138,0,700,562),8895=>array(138,0,700,562),8896=>array(-3,-192,823,719),8897=>array(-3,-192,823,719),8898=>array(68,-192,752,719),8899=>array(68,-192,752,719),8900=>array(3,-233,491,807),8901=>array(107,285,210,409),8902=>array(122,149,504,512),8903=>array(106,15,732,613),8904=>array(106,-30,894,657),8905=>array(106,-30,894,657),8906=>array(106,-30,894,657),8907=>array(106,-30,894,657),8908=>array(106,-30,894,657),8909=>array(106,172,732,494),8910=>array(48,0,684,579),8911=>array(48,0,684,579),8912=>array(93,-3,732,630),8913=>array(106,-3,745,630),8914=>array(103,0,735,663),8915=>array(103,-14,735,649),8916=>array(186,0,652,729),8917=>array(106,-100,732,729),8918=>array(106,46,732,581),8919=>array(106,46,732,581),8920=>array(72,22,1350,609),8921=>array(72,22,1350,609),8922=>array(106,-228,732,854),8923=>array(106,-228,732,854),8924=>array(106,0,732,582),8925=>array(106,0,732,582),8926=>array(106,-105,732,667),8927=>array(106,-105,732,667),8928=>array(106,-178,732,764),8929=>array(106,-178,732,764),8930=>array(106,-141,732,767),8931=>array(106,-141,732,767),8932=>array(106,-94,732,619),8933=>array(106,-94,732,619),8934=>array(106,-138,732,582),8935=>array(106,-138,732,582),8936=>array(106,-169,732,667),8937=>array(106,-171,736,667),8938=>array(106,-130,732,756),8939=>array(106,-130,732,756),8940=>array(106,-189,732,815),8941=>array(104,-189,730,815),8942=>array(448,-93,551,715),8943=>array(115,249,884,373),8944=>array(115,-93,884,715),8945=>array(115,-93,884,715),8946=>array(42,-10,958,710),8947=>array(85,-10,786,710),8948=>array(106,76,612,550),8949=>array(85,-10,786,910),8950=>array(85,-10,786,853),8951=>array(106,76,612,686),8952=>array(85,-144,786,710),8953=>array(85,-10,786,710),8954=>array(42,-10,958,710),8955=>array(85,-10,786,710),8956=>array(106,76,612,550),8957=>array(85,-10,786,853),8958=>array(106,76,612,686),8959=>array(106,0,765,720),8960=>array(62,-18,593,514),8961=>array(56,162,540,443),8962=>array(71,0,563,596),8963=>array(205,481,632,732),8964=>array(205,0,632,251),8965=>array(205,0,632,406),8966=>array(205,0,632,513),8967=>array(208,-31,428,791),8968=>array(-1,-132,380,760),8969=>array(127,-132,391,760),8970=>array(-1,-132,263,760),8971=>array(10,-132,391,760),8972=>array(369,-77,759,313),8973=>array(49,-77,439,313),8974=>array(369,243,759,634),8975=>array(49,243,439,634),8976=>array(106,140,732,421),8977=>array(3,126,510,634),8984=>array(121,0,879,759),8985=>array(106,140,732,421),8988=>array(86,425,469,760),8989=>array(138,425,469,760),8990=>array(72,-70,403,264),8991=>array(52,-70,434,264),8992=>array(210,-250,497,928),8993=>array(21,-237,307,942),8996=>array(76,227,1076,575),8997=>array(76,0,1076,575),8998=>array(76,0,1414,760),8999=>array(76,0,1076,760),9000=>array(59,0,1385,729),9003=>array(0,0,1338,760),9004=>array(73,-91,800,748),9075=>array(81,0,304,547),9076=>array(91,-208,580,560),9077=>array(66,-14,769,547),9082=>array(55,-12,611,559),9085=>array(4,-228,753,102),9095=>array(76,0,1096,748),9108=>array(17,0,856,727),9115=>array(86,-252,414,946),9116=>array(86,-252,181,942),9117=>array(86,-240,414,942),9118=>array(86,-252,414,946),9119=>array(319,-252,414,942),9120=>array(86,-240,414,942),9121=>array(86,-252,414,928),9122=>array(86,-252,181,942),9123=>array(86,-240,414,942),9124=>array(86,-252,414,928),9125=>array(319,-252,414,935),9126=>array(86,-240,414,935),9127=>array(330,-261,668,928),9128=>array(82,-252,420,940),9129=>array(330,-240,668,940),9130=>array(330,-256,420,943),9131=>array(82,-261,420,928),9132=>array(330,-252,668,940),9133=>array(82,-240,420,940),9134=>array(210,-250,307,942),9166=>array(27,65,781,729),9167=>array(91,0,854,596),9187=>array(73,-91,800,748),9189=>array(3,75,766,444),9192=>array(16,-129,553,294),9250=>array(-15,-14,561,760),9251=>array(26,-228,583,102),9312=>array(74,-10,822,738),9313=>array(74,-10,822,738),9314=>array(74,-10,822,738),9315=>array(74,-10,822,738),9316=>array(74,-10,822,738),9317=>array(74,-10,822,738),9318=>array(74,-10,822,738),9319=>array(74,-10,822,738),9320=>array(74,-10,822,738),9321=>array(74,-10,822,738),9472=>array(-10,242,612,326),9473=>array(-10,200,612,368),9474=>array(262,-302,340,973),9475=>array(223,-302,379,973),9476=>array(-10,242,612,326),9477=>array(-10,200,612,368),9478=>array(262,-302,340,973),9479=>array(223,-302,379,973),9480=>array(-10,242,612,326),9481=>array(-10,200,612,368),9482=>array(262,-302,340,973),9483=>array(223,-302,379,973),9484=>array(262,-302,612,326),9485=>array(262,-302,612,368),9486=>array(223,-302,612,326),9487=>array(223,-302,612,368),9488=>array(-10,-302,340,326),9489=>array(-10,-302,340,368),9490=>array(-10,-302,379,326),9491=>array(-10,-302,379,368),9492=>array(262,242,612,973),9493=>array(262,200,612,973),9494=>array(223,242,612,973),9495=>array(223,200,612,973),9496=>array(-10,242,340,973),9497=>array(-10,200,340,973),9498=>array(-10,242,379,973),9499=>array(-10,200,379,973),9500=>array(262,-302,612,973),9501=>array(262,-302,612,973),9502=>array(223,-302,612,973),9503=>array(223,-302,612,973),9504=>array(223,-302,612,973),9505=>array(223,-302,612,973),9506=>array(223,-302,612,973),9507=>array(223,-302,612,973),9508=>array(-10,-302,340,973),9509=>array(-10,-302,340,973),9510=>array(-10,-302,379,973),9511=>array(-10,-302,379,973),9512=>array(-10,-302,379,973),9513=>array(-10,-302,379,973),9514=>array(-10,-302,379,973),9515=>array(-10,-302,379,973),9516=>array(-10,-302,612,326),9517=>array(-10,-302,612,368),9518=>array(-10,-302,612,368),9519=>array(-10,-302,612,368),9520=>array(-10,-302,612,326),9521=>array(-10,-302,612,368),9522=>array(-10,-302,612,368),9523=>array(-10,-302,612,368),9524=>array(-10,242,612,973),9525=>array(-10,200,612,973),9526=>array(-10,200,612,973),9527=>array(-10,200,612,973),9528=>array(-10,242,612,973),9529=>array(-10,200,612,973),9530=>array(-10,200,612,973),9531=>array(-10,200,612,973),9532=>array(-10,-302,612,973),9533=>array(-10,-302,612,973),9534=>array(-10,-302,612,973),9535=>array(-10,-302,612,973),9536=>array(-10,-302,612,973),9537=>array(-10,-302,612,973),9538=>array(-10,-302,612,973),9539=>array(-10,-302,612,973),9540=>array(-10,-302,612,973),9541=>array(-10,-302,612,973),9542=>array(-10,-302,612,973),9543=>array(-10,-302,612,973),9544=>array(-10,-302,612,973),9545=>array(-10,-302,612,973),9546=>array(-10,-302,612,973),9547=>array(-10,-302,612,973),9548=>array(-10,242,612,326),9549=>array(-10,200,612,368),9550=>array(262,-302,340,973),9551=>array(223,-302,379,973),9552=>array(-10,158,612,410),9553=>array(184,-302,418,973),9554=>array(262,-302,612,410),9555=>array(184,-302,612,326),9556=>array(184,-302,612,410),9557=>array(-10,-302,340,410),9558=>array(-10,-302,418,326),9559=>array(-10,-302,418,410),9560=>array(262,158,612,973),9561=>array(184,242,612,973),9562=>array(184,158,612,973),9563=>array(-10,158,340,973),9564=>array(-10,242,418,973),9565=>array(-10,158,418,973),9566=>array(262,-302,612,973),9567=>array(184,-302,612,973),9568=>array(184,-302,612,973),9569=>array(-10,-302,340,973),9570=>array(-10,-302,418,973),9571=>array(-10,-302,418,973),9572=>array(-10,-302,612,410),9573=>array(-10,-302,612,326),9574=>array(-10,-302,612,410),9575=>array(-10,158,612,973),9576=>array(-10,242,612,973),9577=>array(-10,158,612,973),9578=>array(-10,-302,612,973),9579=>array(-10,-302,612,973),9580=>array(-10,-302,612,973),9581=>array(262,-302,612,326),9582=>array(-10,-302,340,326),9583=>array(-10,242,340,973),9584=>array(262,242,612,973),9585=>array(-53,-302,655,973),9586=>array(-53,-302,655,973),9587=>array(-53,-302,655,973),9588=>array(-10,242,311,326),9589=>array(262,284,340,973),9590=>array(311,242,612,326),9591=>array(262,-302,340,284),9592=>array(-10,200,311,368),9593=>array(223,284,379,973),9594=>array(311,200,612,368),9595=>array(223,-302,379,284),9596=>array(-10,200,612,368),9597=>array(223,-302,379,973),9598=>array(-10,200,612,368),9599=>array(223,-302,379,973),9600=>array(-10,260,779,770),9601=>array(-10,-250,779,-123),9602=>array(-10,-250,779,-5),9603=>array(-10,-250,779,132),9604=>array(-10,-250,779,260),9605=>array(-10,-250,779,387),9606=>array(-10,-250,779,515),9607=>array(-10,-250,779,642),9608=>array(-10,-250,779,770),9609=>array(-10,-250,680,770),9610=>array(-10,-250,582,770),9611=>array(-10,-250,483,770),9612=>array(-10,-250,384,770),9613=>array(-10,-250,286,770),9614=>array(-10,-250,187,770),9615=>array(-10,-250,88,770),9616=>array(384,-250,778,770),9617=>array(-10,-250,680,770),9618=>array(-10,-250,779,770),9619=>array(-10,-250,779,770),9620=>array(-10,642,779,770),9621=>array(680,-250,778,770),9622=>array(-10,-250,385,260),9623=>array(384,-250,779,260),9624=>array(-10,260,385,770),9625=>array(-10,-250,779,770),9626=>array(-10,-250,779,770),9627=>array(-10,-250,779,770),9628=>array(-10,-250,779,770),9629=>array(384,260,779,770),9630=>array(-10,-250,779,770),9631=>array(-10,-250,779,770),9632=>array(91,-124,854,643),9633=>array(91,-124,854,643),9634=>array(91,-124,854,643),9635=>array(91,-124,854,643),9636=>array(91,-124,854,643),9637=>array(91,-124,854,643),9638=>array(91,-124,854,643),9639=>array(91,-124,854,643),9640=>array(91,-124,854,643),9641=>array(91,-124,854,643),9642=>array(91,11,587,509),9643=>array(91,11,587,509),9644=>array(91,75,854,444),9645=>array(91,75,854,444),9646=>array(91,-122,459,642),9647=>array(91,-122,459,642),9648=>array(3,75,766,444),9649=>array(3,75,766,444),9650=>array(3,-124,766,643),9651=>array(3,-124,766,643),9652=>array(3,11,499,509),9653=>array(3,11,499,509),9654=>array(3,-124,766,643),9655=>array(3,-124,766,643),9656=>array(3,11,499,509),9657=>array(3,11,499,509),9658=>array(3,11,766,509),9659=>array(3,11,766,509),9660=>array(3,-124,766,643),9661=>array(3,-124,766,643),9662=>array(3,11,499,509),9663=>array(3,11,499,509),9664=>array(3,-124,766,643),9665=>array(3,-124,766,643),9666=>array(3,11,499,509),9667=>array(3,11,499,509),9668=>array(3,11,766,509),9669=>array(3,11,766,509),9670=>array(3,-124,766,643),9671=>array(3,-124,766,643),9672=>array(3,-124,766,643),9673=>array(55,-125,818,645),9674=>array(3,-233,491,807),9675=>array(55,-125,818,645),9676=>array(56,-125,817,644),9677=>array(55,-125,818,645),9678=>array(55,-125,818,645),9679=>array(55,-123,818,641),9680=>array(55,-123,818,641),9681=>array(55,-123,818,641),9682=>array(55,-123,818,641),9683=>array(55,-123,818,641),9684=>array(55,-123,818,641),9685=>array(55,-123,818,641),9686=>array(55,-125,436,645),9687=>array(91,-125,472,645),9688=>array(91,-10,700,770),9689=>array(91,-250,879,770),9690=>array(91,260,879,770),9691=>array(91,-250,879,260),9692=>array(3,260,385,645),9693=>array(3,260,384,645),9694=>array(3,-125,384,260),9695=>array(3,-125,385,260),9696=>array(3,260,766,645),9697=>array(3,-125,766,260),9698=>array(3,-124,766,643),9699=>array(3,-124,766,643),9700=>array(3,-124,766,643),9701=>array(3,-124,766,643),9702=>array(150,227,440,516),9703=>array(91,-124,854,643),9704=>array(91,-124,854,643),9705=>array(91,-124,854,643),9706=>array(91,-124,854,643),9707=>array(91,-124,854,643),9708=>array(3,-124,766,643),9709=>array(3,-124,766,643),9710=>array(3,-124,766,643),9711=>array(55,-250,1064,770),9712=>array(91,-124,854,643),9713=>array(91,-124,854,643),9714=>array(91,-124,854,643),9715=>array(91,-124,854,643),9716=>array(55,-123,818,641),9717=>array(55,-123,818,641),9718=>array(55,-123,818,641),9719=>array(55,-123,818,641),9720=>array(3,-124,766,643),9721=>array(3,-124,766,643),9722=>array(3,-124,766,643),9723=>array(91,-66,739,585),9724=>array(91,-66,739,585),9725=>array(91,-17,642,537),9726=>array(91,-17,642,537),9727=>array(3,-124,766,643),9728=>array(83,0,813,729),9729=>array(51,-2,949,360),9730=>array(49,0,848,729),9731=>array(83,-0,813,927),9732=>array(64,0,833,880),9733=>array(65,-4,832,723),9734=>array(65,-4,832,723),9735=>array(83,2,490,729),9736=>array(83,0,813,731),9737=>array(83,0,813,730),9738=>array(61,0,828,727),9739=>array(61,0,828,723),9740=>array(61,-1,610,722),9741=>array(61,0,952,723),9742=>array(68,0,1177,729),9743=>array(71,0,1180,729),9744=>array(90,0,807,729),9745=>array(89,0,808,729),9746=>array(89,0,808,729),9747=>array(75,78,457,656),9748=>array(49,0,870,933),9749=>array(74,0,822,731),9750=>array(84,0,813,731),9751=>array(84,0,813,727),9752=>array(78,0,819,729),9753=>array(83,140,813,574),9754=>array(84,113,813,569),9755=>array(84,113,813,569),9756=>array(87,104,810,569),9757=>array(72,0,537,724),9758=>array(86,103,810,569),9759=>array(72,-3,537,720),9760=>array(61,0,835,730),9761=>array(84,0,813,730),9762=>array(83,0,813,730),9763=>array(49,0,848,730),9764=>array(49,-2,620,727),9765=>array(83,0,663,731),9766=>array(83,-1,566,731),9767=>array(83,0,701,911),9768=>array(83,0,462,730),9769=>array(83,-1,813,729),9770=>array(87,0,810,730),9771=>array(83,0,814,731),9772=>array(83,0,627,731),9773=>array(83,0,813,730),9774=>array(83,0,813,730),9775=>array(83,0,813,730),9776=>array(83,0,807,729),9777=>array(83,0,807,729),9778=>array(83,0,807,729),9779=>array(83,0,807,729),9780=>array(83,0,807,729),9781=>array(83,0,807,729),9782=>array(83,0,807,729),9783=>array(83,0,807,729),9784=>array(80,3,817,721),9785=>array(83,-73,959,804),9786=>array(83,-73,959,804),9787=>array(83,-73,959,804),9788=>array(83,0,813,730),9789=>array(358,0,814,730),9790=>array(83,0,539,730),9791=>array(85,-102,528,732),9792=>array(85,-125,647,731),9793=>array(85,-14,647,843),9794=>array(79,-14,831,720),9795=>array(166,0,730,730),9796=>array(219,0,677,730),9797=>array(121,0,774,730),9798=>array(127,0,769,730),9799=>array(240,0,656,730),9800=>array(45,0,851,731),9801=>array(89,0,807,730),9802=>array(94,0,802,731),9803=>array(113,31,784,679),9804=>array(140,0,756,730),9805=>array(53,-180,843,730),9806=>array(83,52,813,653),9807=>array(34,-96,863,730),9808=>array(83,-0,813,730),9809=>array(94,0,802,730),9810=>array(86,153,810,579),9811=>array(157,0,739,730),9812=>array(98,0,798,730),9813=>array(110,0,786,730),9814=>array(167,-1,729,729),9815=>array(214,0,683,730),9816=>array(165,0,732,730),9817=>array(148,-0,748,730),9818=>array(98,0,798,730),9819=>array(110,0,786,730),9820=>array(167,-1,729,729),9821=>array(214,0,683,730),9822=>array(162,0,734,730),9823=>array(148,-0,748,730),9824=>array(158,0,738,729),9825=>array(90,0,806,727),9826=>array(168,0,728,729),9827=>array(111,0,785,729),9828=>array(157,0,739,729),9829=>array(89,0,808,729),9830=>array(168,0,728,729),9831=>array(111,0,785,732),9832=>array(105,-1,791,729),9833=>array(84,-5,339,729),9834=>array(84,-5,554,729),9835=>array(184,-102,712,729),9836=>array(92,-5,804,729),9837=>array(88,-3,392,731),9838=>array(84,0,273,731),9839=>array(84,0,400,731),9840=>array(84,0,664,731),9841=>array(64,0,701,731),9842=>array(84,0,813,709),9843=>array(76,16,820,731),9844=>array(76,16,820,731),9845=>array(76,16,820,731),9846=>array(76,16,820,731),9847=>array(76,16,820,731),9848=>array(76,16,820,731),9849=>array(76,16,820,731),9850=>array(76,16,820,731),9851=>array(84,0,812,704),9852=>array(83,0,814,731),9853=>array(83,0,814,731),9854=>array(83,0,814,731),9855=>array(149,1,747,731),9856=>array(73,0,797,725),9857=>array(73,0,797,725),9858=>array(73,0,797,725),9859=>array(73,0,797,725),9860=>array(73,0,797,725),9861=>array(73,0,797,725),9862=>array(83,0,807,724),9863=>array(84,0,808,724),9864=>array(84,0,808,724),9865=>array(84,0,808,724),9866=>array(83,0,807,98),9867=>array(83,0,807,98),9868=>array(83,0,807,411),9869=>array(83,0,807,411),9870=>array(83,0,807,411),9871=>array(83,0,807,411),9872=>array(80,3,634,724),9873=>array(80,3,634,724),9874=>array(52,0,837,724),9875=>array(61,-10,756,725),9876=>array(44,0,672,722),9877=>array(62,-10,476,725),9878=>array(41,-10,811,725),9879=>array(49,0,815,725),9880=>array(42,0,642,725),9881=>array(95,-17,802,727),9882=>array(37,-9,671,726),9883=>array(127,0,763,721),9884=>array(127,0,762,722),9888=>array(49,0,840,721),9889=>array(83,2,619,730),9890=>array(85,-125,919,731),9891=>array(79,-206,1023,720),9892=>array(85,-186,1109,856),9893=>array(85,-125,837,917),9894=>array(131,-14,727,869),9895=>array(101,-170,741,884),9896=>array(188,-14,650,869),9897=>array(4,133,829,596),9898=>array(188,133,650,597),9899=>array(188,133,650,597),9900=>array(249,194,589,536),9901=>array(175,194,663,536),9902=>array(41,169,797,560),9903=>array(5,194,833,536),9904=>array(103,237,757,540),9905=>array(211,42,626,698),9906=>array(85,-125,647,731),9907=>array(168,-125,646,731),9908=>array(86,-125,646,731),9909=>array(86,-125,646,731),9910=>array(59,-118,791,643),9911=>array(194,-104,595,710),9912=>array(158,-125,543,731),9920=>array(42,4,796,553),9921=>array(42,4,796,724),9922=>array(42,4,796,553),9923=>array(42,4,796,724),9954=>array(85,-14,647,843),9985=>array(11,190,803,635),9986=>array(42,141,784,588),9987=>array(11,94,803,539),9988=>array(36,119,824,613),9990=>array(42,-14,796,742),9991=>array(42,-14,796,742),9992=>array(59,21,782,708),9993=>array(64,107,773,622),9996=>array(212,0,561,742),9997=>array(21,83,802,678),9998=>array(89,75,724,710),9999=>array(26,198,819,530),10000=>array(89,75,724,710),10001=>array(43,185,757,544),10002=>array(67,209,757,520),10003=>array(150,97,667,630),10004=>array(116,87,721,631),10005=>array(126,72,711,657),10006=>array(85,31,752,698),10007=>array(118,-9,701,732),10008=>array(123,0,754,739),10009=>array(55,0,783,729),10010=>array(55,0,783,729),10011=>array(55,0,783,729),10012=>array(55,0,783,729),10013=>array(165,0,673,729),10014=>array(131,0,678,729),10015=>array(155,0,683,729),10016=>array(55,0,783,729),10017=>array(91,-13,747,744),10018=>array(41,-14,797,742),10019=>array(42,-12,796,742),10020=>array(41,-14,797,742),10021=>array(41,-13,797,743),10022=>array(42,-14,796,745),10023=>array(42,-14,796,745),10025=>array(23,-9,814,743),10026=>array(42,-14,796,742),10027=>array(23,-9,814,743),10028=>array(23,-9,814,743),10029=>array(23,-9,814,743),10030=>array(23,-9,814,743),10031=>array(23,-9,814,743),10032=>array(24,12,815,714),10033=>array(64,0,773,729),10034=>array(74,0,764,729),10035=>array(55,0,783,729),10036=>array(31,-14,787,742),10037=>array(41,-14,797,742),10038=>array(91,-14,747,742),10039=>array(41,-14,797,742),10040=>array(41,-14,797,742),10041=>array(41,-14,797,742),10042=>array(55,0,783,729),10043=>array(82,-14,756,742),10044=>array(82,-14,756,742),10045=>array(84,-14,753,742),10046=>array(79,-14,759,742),10047=>array(54,0,784,709),10048=>array(54,0,784,709),10049=>array(41,-14,797,742),10050=>array(42,-14,796,742),10051=>array(79,-14,759,742),10052=>array(89,0,749,729),10053=>array(76,0,762,729),10054=>array(63,2,773,729),10055=>array(79,-13,759,742),10056=>array(47,-13,791,730),10057=>array(47,-13,791,730),10058=>array(41,-13,797,743),10059=>array(41,-13,797,743),10061=>array(50,-10,847,738),10063=>array(60,-49,837,729),10064=>array(60,0,837,777),10065=>array(60,-49,837,729),10066=>array(60,0,837,777),10070=>array(83,-2,813,728),10072=>array(377,-240,460,760),10073=>array(336,-240,502,760),10074=>array(253,-240,585,760),10075=>array(85,395,264,729),10076=>array(59,395,237,729),10077=>array(85,395,479,729),10078=>array(59,395,453,729),10081=>array(155,-93,772,851),10082=>array(202,-17,636,742),10083=>array(163,-17,675,742),10084=>array(54,83,784,645),10085=>array(168,-1,729,729),10086=>array(62,21,724,702),10087=>array(78,169,759,564),10088=>array(196,-139,648,769),10089=>array(196,-139,648,769),10090=>array(264,-132,574,758),10091=>array(264,-132,574,758),10092=>array(215,-240,607,760),10093=>array(232,-240,623,760),10094=>array(142,-240,685,760),10095=>array(153,-240,696,760),10096=>array(167,-240,656,760),10097=>array(183,-240,672,760),10098=>array(346,-241,535,760),10099=>array(303,-241,492,760),10100=>array(175,-163,634,760),10101=>array(204,-163,663,760),10102=>array(74,-10,822,738),10103=>array(74,-10,822,738),10104=>array(74,-10,822,738),10105=>array(74,-10,822,738),10106=>array(74,-10,822,738),10107=>array(74,-10,822,738),10108=>array(74,-10,822,738),10109=>array(74,-10,822,738),10110=>array(74,-10,822,738),10111=>array(74,-10,822,738),10112=>array(4,-52,833,780),10113=>array(4,-52,833,780),10114=>array(4,-52,833,780),10115=>array(4,-52,833,780),10116=>array(4,-52,833,780),10117=>array(4,-52,833,780),10118=>array(4,-52,833,780),10119=>array(4,-52,833,780),10120=>array(4,-52,833,780),10121=>array(4,-52,833,780),10122=>array(4,-52,833,780),10123=>array(4,-52,833,780),10124=>array(4,-52,833,780),10125=>array(4,-52,833,780),10126=>array(4,-52,833,780),10127=>array(4,-52,833,780),10128=>array(4,-52,833,780),10129=>array(4,-52,833,780),10130=>array(4,-52,833,780),10131=>array(4,-52,833,780),10132=>array(57,75,789,552),10136=>array(123,55,682,614),10137=>array(57,100,789,527),10138=>array(123,13,682,572),10139=>array(57,129,789,498),10140=>array(57,57,764,570),10141=>array(57,100,789,527),10142=>array(57,100,789,527),10143=>array(57,100,789,527),10144=>array(57,100,789,527),10145=>array(57,65,811,562),10146=>array(111,94,789,533),10147=>array(111,94,789,533),10148=>array(111,-4,789,631),10149=>array(57,100,789,548),10150=>array(57,79,789,527),10151=>array(240,-7,606,634),10152=>array(57,100,789,527),10153=>array(57,75,765,552),10154=>array(57,75,765,552),10155=>array(21,12,794,586),10156=>array(21,12,794,586),10157=>array(135,0,774,574),10158=>array(135,0,774,574),10159=>array(62,49,799,574),10161=>array(62,49,799,574),10162=>array(154,-20,721,585),10163=>array(63,157,789,470),10164=>array(81,55,682,655),10165=>array(57,173,789,454),10166=>array(82,-29,682,572),10167=>array(82,55,682,655),10168=>array(57,172,789,455),10169=>array(82,-28,682,572),10170=>array(56,84,789,543),10171=>array(73,140,779,487),10172=>array(79,167,774,460),10173=>array(79,118,774,509),10174=>array(57,81,789,546),10181=>array(0,-163,377,769),10182=>array(-52,-163,395,769),10208=>array(3,-233,491,807),10214=>array(-0,-132,485,760),10215=>array(-1,-132,484,760),10216=>array(89,-132,397,759),10217=>array(-7,-132,301,759),10218=>array(89,-132,563,759),10219=>array(-7,-132,467,759),10224=>array(44,0,794,732),10225=>array(43,-3,793,729),10226=>array(-17,53,759,659),10227=>array(39,61,814,666),10228=>array(57,-14,1108,643),10229=>array(49,100,1376,527),10230=>array(57,100,1385,527),10231=>array(49,100,1385,527),10232=>array(49,100,1376,527),10233=>array(57,100,1385,527),10234=>array(49,100,1385,527),10235=>array(49,100,1376,527),10236=>array(57,100,1385,527),10237=>array(49,100,1376,527),10238=>array(57,100,1385,527),10239=>array(57,100,1385,527),10241=>array(146,635,293,781),10242=>array(146,358,293,505),10243=>array(146,358,293,781),10244=>array(146,81,293,228),10245=>array(146,81,293,781),10246=>array(146,81,293,505),10247=>array(146,81,293,781),10248=>array(439,635,586,781),10249=>array(146,635,586,781),10250=>array(146,358,586,781),10251=>array(146,358,586,781),10252=>array(146,81,586,781),10253=>array(146,81,586,781),10254=>array(146,81,586,781),10255=>array(146,81,586,781),10256=>array(439,358,586,505),10257=>array(146,358,586,781),10258=>array(146,358,586,505),10259=>array(146,358,586,781),10260=>array(146,81,586,505),10261=>array(146,81,586,781),10262=>array(146,81,586,505),10263=>array(146,81,586,781),10264=>array(439,358,586,781),10265=>array(146,358,586,781),10266=>array(146,358,586,781),10267=>array(146,358,586,781),10268=>array(146,81,586,781),10269=>array(146,81,586,781),10270=>array(146,81,586,781),10271=>array(146,81,586,781),10272=>array(439,81,586,228),10273=>array(146,81,586,781),10274=>array(146,81,586,505),10275=>array(146,81,586,781),10276=>array(146,81,586,228),10277=>array(146,81,586,781),10278=>array(146,81,586,505),10279=>array(146,81,586,781),10280=>array(439,81,586,781),10281=>array(146,81,586,781),10282=>array(146,81,586,781),10283=>array(146,81,586,781),10284=>array(146,81,586,781),10285=>array(146,81,586,781),10286=>array(146,81,586,781),10287=>array(146,81,586,781),10288=>array(439,81,586,505),10289=>array(146,81,586,781),10290=>array(146,81,586,505),10291=>array(146,81,586,781),10292=>array(146,81,586,505),10293=>array(146,81,586,781),10294=>array(146,81,586,505),10295=>array(146,81,586,781),10296=>array(439,81,586,781),10297=>array(146,81,586,781),10298=>array(146,81,586,781),10299=>array(146,81,586,781),10300=>array(146,81,586,781),10301=>array(146,81,586,781),10302=>array(146,81,586,781),10303=>array(146,81,586,781),10304=>array(146,-195,293,-49),10305=>array(146,-195,293,781),10306=>array(146,-195,293,505),10307=>array(146,-195,293,781),10308=>array(146,-195,293,228),10309=>array(146,-195,293,781),10310=>array(146,-195,293,505),10311=>array(146,-195,293,781),10312=>array(146,-195,586,781),10313=>array(146,-195,586,781),10314=>array(146,-195,586,781),10315=>array(146,-195,586,781),10316=>array(146,-195,586,781),10317=>array(146,-195,586,781),10318=>array(146,-195,586,781),10319=>array(146,-195,586,781),10320=>array(146,-195,586,505),10321=>array(146,-195,586,781),10322=>array(146,-195,586,505),10323=>array(146,-195,586,781),10324=>array(146,-195,586,505),10325=>array(146,-195,586,781),10326=>array(146,-195,586,505),10327=>array(146,-195,586,781),10328=>array(146,-195,586,781),10329=>array(146,-195,586,781),10330=>array(146,-195,586,781),10331=>array(146,-195,586,781),10332=>array(146,-195,586,781),10333=>array(146,-195,586,781),10334=>array(146,-195,586,781),10335=>array(146,-195,586,781),10336=>array(146,-195,586,228),10337=>array(146,-195,586,781),10338=>array(146,-195,586,505),10339=>array(146,-195,586,781),10340=>array(146,-195,586,228),10341=>array(146,-195,586,781),10342=>array(146,-195,586,505),10343=>array(146,-195,586,781),10344=>array(146,-195,586,781),10345=>array(146,-195,586,781),10346=>array(146,-195,586,781),10347=>array(146,-195,586,781),10348=>array(146,-195,586,781),10349=>array(146,-195,586,781),10350=>array(146,-195,586,781),10351=>array(146,-195,586,781),10352=>array(146,-195,586,505),10353=>array(146,-195,586,781),10354=>array(146,-195,586,505),10355=>array(146,-195,586,781),10356=>array(146,-195,586,505),10357=>array(146,-195,586,781),10358=>array(146,-195,586,505),10359=>array(146,-195,586,781),10360=>array(146,-195,586,781),10361=>array(146,-195,586,781),10362=>array(146,-195,586,781),10363=>array(146,-195,586,781),10364=>array(146,-195,586,781),10365=>array(146,-195,586,781),10366=>array(146,-195,586,781),10367=>array(146,-195,586,781),10368=>array(439,-195,586,-49),10369=>array(146,-195,586,781),10370=>array(146,-195,586,505),10371=>array(146,-195,586,781),10372=>array(146,-195,586,228),10373=>array(146,-195,586,781),10374=>array(146,-195,586,505),10375=>array(146,-195,586,781),10376=>array(439,-195,586,781),10377=>array(146,-195,586,781),10378=>array(146,-195,586,781),10379=>array(146,-195,586,781),10380=>array(146,-195,586,781),10381=>array(146,-195,586,781),10382=>array(146,-195,586,781),10383=>array(146,-195,586,781),10384=>array(439,-195,586,505),10385=>array(146,-195,586,781),10386=>array(146,-195,586,505),10387=>array(146,-195,586,781),10388=>array(146,-195,586,505),10389=>array(146,-195,586,781),10390=>array(146,-195,586,505),10391=>array(146,-195,586,781),10392=>array(439,-195,586,781),10393=>array(146,-195,586,781),10394=>array(146,-195,586,781),10395=>array(146,-195,586,781),10396=>array(146,-195,586,781),10397=>array(146,-195,586,781),10398=>array(146,-195,586,781),10399=>array(146,-195,586,781),10400=>array(439,-195,586,228),10401=>array(146,-195,586,781),10402=>array(146,-195,586,505),10403=>array(146,-195,586,781),10404=>array(146,-195,586,228),10405=>array(146,-195,586,781),10406=>array(146,-195,586,505),10407=>array(146,-195,586,781),10408=>array(439,-195,586,781),10409=>array(146,-195,586,781),10410=>array(146,-195,586,781),10411=>array(146,-195,586,781),10412=>array(146,-195,586,781),10413=>array(146,-195,586,781),10414=>array(146,-195,586,781),10415=>array(146,-195,586,781),10416=>array(439,-195,586,505),10417=>array(146,-195,586,781),10418=>array(146,-195,586,505),10419=>array(146,-195,586,781),10420=>array(146,-195,586,505),10421=>array(146,-195,586,781),10422=>array(146,-195,586,505),10423=>array(146,-195,586,781),10424=>array(439,-195,586,781),10425=>array(146,-195,586,781),10426=>array(146,-195,586,781),10427=>array(146,-195,586,781),10428=>array(146,-195,586,781),10429=>array(146,-195,586,781),10430=>array(146,-195,586,781),10431=>array(146,-195,586,781),10432=>array(146,-195,586,-49),10433=>array(146,-195,586,781),10434=>array(146,-195,586,505),10435=>array(146,-195,586,781),10436=>array(146,-195,586,228),10437=>array(146,-195,586,781),10438=>array(146,-195,586,505),10439=>array(146,-195,586,781),10440=>array(146,-195,586,781),10441=>array(146,-195,586,781),10442=>array(146,-195,586,781),10443=>array(146,-195,586,781),10444=>array(146,-195,586,781),10445=>array(146,-195,586,781),10446=>array(146,-195,586,781),10447=>array(146,-195,586,781),10448=>array(146,-195,586,505),10449=>array(146,-195,586,781),10450=>array(146,-195,586,505),10451=>array(146,-195,586,781),10452=>array(146,-195,586,505),10453=>array(146,-195,586,781),10454=>array(146,-195,586,505),10455=>array(146,-195,586,781),10456=>array(146,-195,586,781),10457=>array(146,-195,586,781),10458=>array(146,-195,586,781),10459=>array(146,-195,586,781),10460=>array(146,-195,586,781),10461=>array(146,-195,586,781),10462=>array(146,-195,586,781),10463=>array(146,-195,586,781),10464=>array(146,-195,586,228),10465=>array(146,-195,586,781),10466=>array(146,-195,586,505),10467=>array(146,-195,586,781),10468=>array(146,-195,586,228),10469=>array(146,-195,586,781),10470=>array(146,-195,586,505),10471=>array(146,-195,586,781),10472=>array(146,-195,586,781),10473=>array(146,-195,586,781),10474=>array(146,-195,586,781),10475=>array(146,-195,586,781),10476=>array(146,-195,586,781),10477=>array(146,-195,586,781),10478=>array(146,-195,586,781),10479=>array(146,-195,586,781),10480=>array(146,-195,586,505),10481=>array(146,-195,586,781),10482=>array(146,-195,586,505),10483=>array(146,-195,586,781),10484=>array(146,-195,586,505),10485=>array(146,-195,586,781),10486=>array(146,-195,586,505),10487=>array(146,-195,586,781),10488=>array(146,-195,586,781),10489=>array(146,-195,586,781),10490=>array(146,-195,586,781),10491=>array(146,-195,586,781),10492=>array(146,-195,586,781),10493=>array(146,-195,586,781),10494=>array(146,-195,586,781),10495=>array(146,-195,586,781),10502=>array(49,100,781,527),10503=>array(57,100,789,527),10506=>array(125,0,713,732),10507=>array(125,-3,713,729),10560=>array(39,63,644,838),10561=>array(39,63,644,838),10627=>array(118,-163,699,760),10628=>array(35,-163,616,760),10702=>array(106,-226,732,747),10703=>array(106,15,894,612),10704=>array(106,15,894,612),10705=>array(106,-30,894,657),10706=>array(106,-30,894,657),10707=>array(106,-30,894,657),10708=>array(106,-30,894,657),10709=>array(106,-30,894,657),10731=>array(3,-233,491,807),10746=>array(106,0,732,627),10747=>array(106,0,732,627),10752=>array(28,-198,972,748),10753=>array(28,-198,972,748),10754=>array(28,-198,972,748),10764=>array(57,-212,1268,757),10765=>array(57,-212,464,757),10766=>array(57,-212,464,757),10767=>array(57,-212,464,757),10768=>array(57,-212,464,757),10769=>array(57,-212,522,757),10770=>array(57,-212,464,757),10771=>array(57,-212,464,757),10772=>array(57,-212,555,757),10773=>array(57,-212,464,757),10774=>array(57,-212,464,757),10775=>array(-33,-212,553,757),10776=>array(57,-212,464,757),10777=>array(57,-212,464,757),10778=>array(57,-212,464,757),10779=>array(57,-212,469,872),10780=>array(52,-327,464,757),10799=>array(137,31,701,596),10858=>array(106,228,732,552),10859=>array(106,78,732,552),10877=>array(106,-123,732,581),10878=>array(106,-123,732,581),10879=>array(106,-123,733,581),10880=>array(106,-123,732,581),10881=>array(106,-123,732,644),10882=>array(106,-123,732,644),10883=>array(106,-123,733,759),10884=>array(106,-123,732,756),10885=>array(106,-132,732,663),10886=>array(106,-132,732,663),10887=>array(106,-121,732,582),10888=>array(106,-121,732,582),10889=>array(106,-204,732,663),10890=>array(106,-204,732,663),10891=>array(106,-311,732,791),10892=>array(106,-311,732,791),10893=>array(106,-125,732,663),10894=>array(106,-125,732,663),10895=>array(106,-241,732,756),10896=>array(106,-241,732,756),10897=>array(106,-229,732,730),10898=>array(106,-229,732,730),10899=>array(106,-224,732,741),10900=>array(106,-224,732,741),10901=>array(106,-61,732,644),10902=>array(106,-61,732,644),10903=>array(106,-61,733,644),10904=>array(106,-61,732,644),10905=>array(106,-36,732,685),10906=>array(106,-36,732,685),10907=>array(106,-31,732,725),10908=>array(106,-31,732,725),10909=>array(106,8,732,645),10910=>array(106,23,732,645),10911=>array(106,-176,732,729),10912=>array(106,-176,732,729),10926=>array(106,50,732,601),10927=>array(106,-24,732,667),10928=>array(106,-24,732,667),10929=>array(106,-145,732,667),10930=>array(106,-145,732,667),10931=>array(106,-121,732,662),10932=>array(106,-121,732,662),10933=>array(106,-195,732,662),10934=>array(106,-195,732,662),10935=>array(106,-191,732,693),10936=>array(106,-191,732,693),10937=>array(106,-259,732,693),10938=>array(106,-259,732,693),11001=>array(106,-171,732,585),11002=>array(106,-171,732,585),11008=>array(88,-27,703,587),11009=>array(141,-27,755,587),11010=>array(88,25,703,640),11011=>array(141,25,755,640),11012=>array(27,65,789,562),11013=>array(27,65,781,562),11014=>array(171,0,667,754),11015=>array(171,-25,667,729),11016=>array(88,-27,703,587),11017=>array(141,-27,755,587),11018=>array(88,25,703,640),11019=>array(141,25,755,640),11020=>array(27,65,789,562),11021=>array(171,-25,667,754),11022=>array(57,-3,790,355),11023=>array(57,272,790,630),11024=>array(35,-3,768,355),11025=>array(35,272,768,630),11026=>array(91,-124,854,643),11027=>array(91,-124,854,643),11028=>array(91,-124,854,643),11029=>array(91,-124,854,643),11030=>array(3,-124,766,643),11031=>array(3,-124,766,643),11032=>array(3,-124,766,643),11033=>array(3,-124,766,643),11034=>array(91,-124,854,643),11039=>array(18,-26,852,767),11040=>array(18,-26,852,767),11041=>array(73,-91,800,748),11042=>array(73,-91,800,748),11043=>array(17,-35,856,692),11044=>array(55,-250,1064,770),11091=>array(38,-47,832,788),11092=>array(38,-47,832,788),11360=>array(-13,0,497,729),11361=>array(-16,0,291,760),11362=>array(-31,0,497,729),11363=>array(26,0,597,729),11364=>array(57,-200,618,729),11365=>array(-20,-46,631,592),11366=>array(-101,-93,473,822),11367=>array(42,-157,740,729),11368=>array(30,-138,593,760),11369=>array(42,-157,737,729),11370=>array(30,-138,610,760),11371=>array(-11,-157,715,729),11372=>array(3,-138,548,547),11373=>array(56,-14,754,743),11374=>array(47,-200,855,729),11375=>array(149,0,817,729),11376=>array(-15,-14,694,743),11377=>array(136,0,813,560),11378=>array(175,0,1245,742),11379=>array(148,0,1040,560),11380=>array(39,0,611,586),11381=>array(27,0,568,729),11382=>array(41,0,486,547),11383=>array(55,-12,603,551),11385=>array(-74,-13,357,760),11386=>array(55,-14,558,560),11387=>array(48,0,506,547),11388=>array(-64,-117,168,425),11389=>array(44,326,465,734),11390=>array(26,-242,624,742),11391=>array(-2,-242,723,729),11520=>array(61,-63,578,547),11521=>array(1,-235,598,546),11522=>array(17,-235,547,546),11523=>array(66,-10,637,807),11524=>array(45,-235,570,546),11525=>array(24,-236,896,546),11526=>array(59,-8,609,816),11527=>array(47,0,934,546),11528=>array(77,0,575,546),11529=>array(44,-235,590,816),11530=>array(24,0,937,546),11531=>array(51,-8,638,816),11532=>array(24,0,578,816),11533=>array(45,0,930,546),11534=>array(45,0,598,546),11535=>array(88,-235,801,816),11536=>array(45,0,914,816),11537=>array(45,0,588,816),11538=>array(34,-235,563,546),11539=>array(45,-235,929,661),11540=>array(61,-235,918,546),11541=>array(41,-235,820,816),11542=>array(24,0,579,546),11543=>array(45,-235,598,547),11544=>array(15,-235,593,546),11545=>array(27,-235,575,816),11546=>array(31,-235,559,547),11547=>array(62,-9,638,816),11548=>array(24,-235,904,547),11549=>array(-6,-235,562,546),11550=>array(37,-235,590,546),11551=>array(10,-235,589,567),11552=>array(24,0,917,546),11553=>array(41,-235,578,816),11554=>array(61,0,568,626),11555=>array(62,-235,595,816),11556=>array(45,-235,645,546),11557=>array(60,-8,876,816),11800=>array(37,-13,425,729),11807=>array(106,78,732,399),11810=>array(126,314,420,760),11811=>array(122,314,342,760),11812=>array(40,-132,260,314),11813=>array(-38,-132,255,314),11822=>array(110,0,522,742),19904=>array(83,-158,807,729),19905=>array(83,-158,807,729),19906=>array(83,-158,807,729),19907=>array(83,-158,807,729),19908=>array(83,-158,807,729),19909=>array(83,-158,807,729),19910=>array(83,-158,807,729),19911=>array(83,-158,807,729),19912=>array(83,-158,807,729),19913=>array(83,-158,807,729),19914=>array(83,-158,807,729),19915=>array(83,-158,807,729),19916=>array(83,-158,807,729),19917=>array(83,-158,807,729),19918=>array(83,-158,807,729),19919=>array(83,-158,807,729),19920=>array(83,-158,807,729),19921=>array(83,-158,807,729),19922=>array(83,-158,807,729),19923=>array(83,-158,807,729),19924=>array(83,-158,807,729),19925=>array(83,-158,807,729),19926=>array(83,-158,807,729),19927=>array(83,-158,807,729),19928=>array(83,-158,807,729),19929=>array(83,-158,807,729),19930=>array(83,-158,807,729),19931=>array(83,-158,807,729),19932=>array(83,-158,807,729),19933=>array(83,-158,807,729),19934=>array(83,-158,807,729),19935=>array(83,-158,807,729),19936=>array(83,-158,807,729),19937=>array(83,-158,807,729),19938=>array(83,-158,807,729),19939=>array(83,-158,807,729),19940=>array(83,-158,807,729),19941=>array(83,-158,807,729),19942=>array(83,-158,807,729),19943=>array(83,-158,807,729),19944=>array(83,-158,807,729),19945=>array(83,-158,807,729),19946=>array(83,-158,807,729),19947=>array(83,-158,807,729),19948=>array(83,-158,807,729),19949=>array(83,-158,807,729),19950=>array(83,-158,807,729),19951=>array(83,-158,807,729),19952=>array(83,-158,807,729),19953=>array(83,-158,807,729),19954=>array(83,-158,807,729),19955=>array(83,-158,807,729),19956=>array(83,-158,807,729),19957=>array(83,-158,807,729),19958=>array(83,-158,807,729),19959=>array(83,-158,807,729),19960=>array(83,-158,807,729),19961=>array(83,-158,807,729),19962=>array(83,-158,807,729),19963=>array(83,-158,807,729),19964=>array(83,-158,807,729),19965=>array(83,-158,807,729),19966=>array(83,-158,807,729),19967=>array(83,-158,807,729),42192=>array(27,0,625,729),42193=>array(27,0,601,729),42194=>array(6,0,576,729),42195=>array(27,0,722,729),42196=>array(43,0,676,729),42197=>array(-74,0,559,729),42198=>array(45,-14,725,742),42199=>array(27,0,722,729),42200=>array(-66,0,628,729),42201=>array(5,-14,556,729),42202=>array(42,-14,695,742),42203=>array(63,-14,715,742),42204=>array(-22,0,703,729),42205=>array(27,0,587,729),42206=>array(27,0,587,729),42207=>array(27,0,836,729),42208=>array(27,0,721,729),42209=>array(27,0,497,729),42210=>array(6,-14,603,742),42211=>array(27,0,600,729),42212=>array(96,0,667,729),42213=>array(-63,0,605,729),42214=>array(78,0,742,729),42215=>array(27,0,725,729),42216=>array(47,-14,728,742),42217=>array(26,0,575,743),42218=>array(96,0,1020,729),42219=>array(-43,0,703,729),42220=>array(63,0,676,729),42221=>array(65,0,659,729),42222=>array(-53,0,615,729),42223=>array(149,0,817,729),42224=>array(27,0,630,729),42225=>array(2,0,604,729),42226=>array(27,0,268,729),42227=>array(40,-14,747,742),42228=>array(58,-14,713,729),42229=>array(15,0,661,743),42230=>array(59,0,529,729),42231=>array(56,0,740,729),42232=>array(70,0,229,155),42233=>array(41,-156,245,155),42234=>array(70,0,526,155),42235=>array(70,-156,541,155),42236=>array(6,-156,280,517),42237=>array(35,0,265,517),42238=>array(104,0,537,354),42239=>array(58,172,530,454),42564=>array(2,-14,580,742),42565=>array(11,-14,473,560),42566=>array(76,0,292,729),42567=>array(80,0,258,547),42572=>array(35,-14,1121,645),42573=>array(61,-14,958,471),42576=>array(84,0,1002,729),42577=>array(69,0,865,547),42580=>array(45,-14,1047,742),42581=>array(46,-14,801,560),42582=>array(32,0,916,729),42583=>array(41,-14,781,560),42594=>array(-37,-157,1090,729),42595=>array(-14,-138,930,547),42596=>array(-30,0,1079,729),42597=>array(-16,0,905,547),42598=>array(27,0,1190,729),42599=>array(38,0,1012,547),42600=>array(40,-14,747,742),42601=>array(46,-14,566,560),42602=>array(56,-14,799,742),42603=>array(55,-14,658,560),42604=>array(56,-14,1302,742),42605=>array(55,-14,964,560),42606=>array(28,-208,851,743),42634=>array(43,-200,723,729),42635=>array(68,-208,631,547),42636=>array(43,0,676,729),42637=>array(68,0,606,547),42644=>array(119,0,667,729),42645=>array(17,0,539,760),42760=>array(157,0,454,668),42761=>array(127,0,454,668),42762=>array(98,0,454,668),42763=>array(69,0,454,668),42764=>array(40,0,454,668),42765=>array(40,0,454,668),42766=>array(40,0,425,668),42767=>array(40,0,396,668),42768=>array(40,0,366,668),42769=>array(40,0,337,668),42770=>array(40,0,454,668),42771=>array(40,0,425,668),42772=>array(40,0,396,668),42773=>array(40,0,366,668),42774=>array(40,0,337,668),42779=>array(69,326,338,736),42780=>array(31,324,300,734),42781=>array(56,326,197,734),42782=>array(56,326,197,734),42783=>array(56,0,197,408),42786=>array(30,0,374,729),42787=>array(38,0,335,547),42788=>array(55,224,461,742),42789=>array(55,42,461,560),42790=>array(47,-200,744,729),42791=>array(37,-208,560,760),42792=>array(72,-213,832,729),42793=>array(72,-213,666,702),42794=>array(121,-14,676,742),42795=>array(9,-199,502,561),42800=>array(38,0,490,547),42801=>array(11,-14,500,560),42802=>array(-63,0,1170,729),42803=>array(38,-14,902,560),42804=>array(-53,-14,1179,742),42805=>array(41,-14,954,560),42806=>array(-53,-14,1136,729),42807=>array(41,-14,951,560),42808=>array(-63,0,1034,729),42809=>array(38,-14,841,560),42810=>array(-63,0,1034,729),42811=>array(38,-14,841,560),42812=>array(-43,-208,1042,729),42813=>array(57,-208,860,560),42814=>array(63,-14,715,742),42815=>array(2,-14,493,560),42816=>array(27,0,722,729),42817=>array(35,0,612,760),42822=>array(92,0,620,729),42823=>array(84,0,307,760),42824=>array(52,0,521,729),42825=>array(90,0,415,760),42826=>array(0,-14,811,742),42827=>array(1,-14,704,560),42830=>array(56,-14,1302,742),42831=>array(55,-14,964,560),42832=>array(-42,0,603,729),42833=>array(-83,-208,589,560),42834=>array(-5,0,733,729),42835=>array(-15,-208,729,560),42838=>array(44,-178,740,742),42839=>array(46,-208,597,560),42852=>array(27,0,579,729),42853=>array(-5,-208,586,760),42854=>array(-57,0,579,729),42855=>array(-85,-208,586,760),42880=>array(60,0,530,729),42881=>array(21,-208,257,560),42882=>array(-14,-208,663,742),42883=>array(-5,-208,566,560),42889=>array(52,0,256,517),42890=>array(62,161,325,380),42891=>array(135,235,320,729),42892=>array(70,458,206,729),42893=>array(109,0,658,729),42894=>array(41,-208,417,760),42896=>array(27,-157,721,729),42897=>array(35,-138,579,560),42912=>array(-9,-14,789,742),42913=>array(-7,-208,642,560),42914=>array(-6,0,722,729),42915=>array(-6,0,612,760),42916=>array(-8,0,756,729),42917=>array(-7,0,642,560),42918=>array(-7,0,702,729),42919=>array(-2,0,463,560),42920=>array(-6,-14,641,742),42921=>array(-4,-14,525,560),42922=>array(51,0,845,729),43002=>array(38,0,877,547),43003=>array(86,0,548,729),43004=>array(63,0,576,729),43005=>array(27,0,836,729),43006=>array(8,0,287,928),43007=>array(-38,0,1237,729),61184=>array(147,602,388,668),61185=>array(103,451,407,668),61186=>array(56,301,426,668),61187=>array(18,150,433,668),61188=>array(-21,0,432,668),61189=>array(123,451,378,668),61190=>array(118,451,358,518),61191=>array(73,301,378,518),61192=>array(26,150,397,518),61193=>array(-12,0,404,518),61194=>array(110,301,368,668),61195=>array(94,301,349,518),61196=>array(88,301,329,367),61197=>array(44,150,349,367),61198=>array(-3,0,368,367),61199=>array(105,150,345,668),61200=>array(81,150,338,518),61201=>array(64,150,319,367),61202=>array(59,150,300,217),61203=>array(15,0,319,217),61204=>array(104,0,319,668),61205=>array(76,0,316,518),61206=>array(52,0,309,367),61207=>array(35,0,290,217),61208=>array(30,0,271,66),61209=>array(40,0,236,668),62464=>array(93,-15,582,828),62465=>array(99,-15,577,828),62466=>array(95,-15,622,837),62467=>array(137,0,944,837),62468=>array(87,-15,651,837),62469=>array(89,-15,627,837),62470=>array(141,-15,649,837),62471=>array(96,-15,935,837),62472=>array(118,0,608,837),62473=>array(87,-15,656,828),62474=>array(152,0,1227,837),62475=>array(89,-15,646,837),62476=>array(96,-15,641,828),62477=>array(112,0,922,837),62478=>array(85,-15,625,828),62479=>array(97,-15,690,844),62480=>array(109,0,928,837),62481=>array(107,-15,575,828),62482=>array(106,-15,764,837),62483=>array(80,-15,643,837),62484=>array(147,-15,937,837),62485=>array(86,-15,687,828),62486=>array(126,-15,955,837),62487=>array(82,-15,687,829),62488=>array(90,-15,654,837),62489=>array(49,0,594,837),62490=>array(96,-15,689,828),62491=>array(95,-15,687,828),62492=>array(103,-15,699,837),62493=>array(86,-15,688,828),62494=>array(103,-15,586,828),62495=>array(34,-15,578,837),62496=>array(89,-15,634,837),62497=>array(91,-15,643,837),62498=>array(22,-79,629,836),62499=>array(85,-15,688,838),62500=>array(86,-15,695,837),62501=>array(83,-15,702,837),62502=>array(138,-15,1012,837),62504=>array(61,-235,898,816),62505=>array(51,-230,793,853),62506=>array(77,-15,545,765),62507=>array(77,-15,537,777),62508=>array(77,-15,552,875),62509=>array(77,-15,543,818),62510=>array(77,-15,533,887),62511=>array(77,-15,552,809),62512=>array(28,-236,570,765),62513=>array(28,-236,573,799),62514=>array(28,-236,575,901),62515=>array(28,-236,571,809),62516=>array(94,0,560,765),62517=>array(94,0,573,799),62518=>array(94,0,571,809),62519=>array(96,-0,785,765),62520=>array(96,-0,785,777),62521=>array(96,-0,785,895),62522=>array(96,-0,785,799),62523=>array(96,-0,785,809),62524=>array(55,-236,557,765),62525=>array(55,-236,557,777),62526=>array(55,-236,583,904),62527=>array(55,-236,557,799),62528=>array(55,-236,566,809),62529=>array(55,-236,557,852),63173=>array(27,-14,575,760),64256=>array(68,0,814,760),64257=>array(68,0,641,760),64258=>array(68,0,641,760),64259=>array(68,0,979,760),64260=>array(68,0,979,760),64261=>array(53,0,713,760),64262=>array(2,-14,888,742),64275=>array(54,-14,1145,760),64276=>array(54,-14,1145,760),64277=>array(73,-208,1122,760),64278=>array(73,-208,1164,760),64279=>array(73,-208,1503,760),64285=>array(84,44,264,547),64286=>array(179,625,486,765),64287=>array(80,44,462,547),64288=>array(38,0,668,547),64289=>array(85,0,878,547),64290=>array(135,0,824,547),64291=>array(101,0,825,547),64292=>array(43,0,777,547),64293=>array(135,0,823,760),64294=>array(91,0,828,547),64295=>array(135,0,780,547),64296=>array(47,-4,784,547),64297=>array(159,272,801,627),64298=>array(118,0,793,698),64299=>array(118,0,772,698),64300=>array(118,0,797,698),64301=>array(118,0,772,698),64302=>array(91,-159,684,547),64303=>array(91,-193,684,547),64304=>array(91,-159,684,547),64305=>array(43,0,549,547),64306=>array(43,-5,383,547),64307=>array(135,0,618,547),64308=>array(101,0,617,547),64309=>array(98,0,371,547),64310=>array(83,0,469,547),64312=>array(141,-14,659,552),64313=>array(91,204,370,547),64314=>array(135,-208,509,547),64315=>array(43,0,534,547),64316=>array(135,0,599,729),64318=>array(75,0,646,555),64320=>array(43,0,377,547),64321=>array(144,-14,647,547),64323=>array(108,-208,551,547),64324=>array(91,0,623,547),64326=>array(43,0,607,547),64327=>array(62,-208,740,546),64328=>array(135,0,538,547),64329=>array(118,0,772,547),64330=>array(10,-4,634,547),64331=>array(91,0,308,698),64332=>array(43,0,549,698),64333=>array(43,0,534,698),64334=>array(91,0,623,698),64335=>array(84,0,677,760),65056=>array(-299,752,181,929),65057=>array(166,752,604,929),65058=>array(-208,756,168,894),65059=>array(153,756,528,894),65533=>array(96,-84,1092,912),65535=>array(50,-177,550,705)); -$cw=array(0=>600,32=>318,33=>401,34=>460,35=>838,36=>636,37=>950,38=>780,39=>275,40=>390,41=>390,42=>500,43=>838,44=>318,45=>361,46=>318,47=>337,48=>636,49=>636,50=>636,51=>636,52=>636,53=>636,54=>636,55=>636,56=>636,57=>636,58=>337,59=>337,60=>838,61=>838,62=>838,63=>531,64=>1000,65=>684,66=>686,67=>698,68=>770,69=>632,70=>575,71=>775,72=>752,73=>295,74=>295,75=>656,76=>557,77=>863,78=>748,79=>787,80=>603,81=>787,82=>695,83=>635,84=>611,85=>732,86=>684,87=>989,88=>685,89=>611,90=>685,91=>390,92=>337,93=>390,94=>838,95=>500,96=>500,97=>613,98=>635,99=>550,100=>635,101=>615,102=>352,103=>635,104=>634,105=>278,106=>278,107=>579,108=>278,109=>974,110=>634,111=>612,112=>635,113=>635,114=>411,115=>521,116=>392,117=>634,118=>592,119=>818,120=>592,121=>592,122=>525,123=>636,124=>337,125=>636,126=>838,160=>318,161=>401,162=>636,163=>636,164=>636,165=>636,166=>337,167=>500,168=>500,169=>1000,170=>471,171=>617,172=>838,173=>361,174=>1000,175=>500,176=>500,177=>838,178=>401,179=>401,180=>500,181=>636,182=>636,183=>318,184=>500,185=>401,186=>471,187=>617,188=>969,189=>969,190=>969,191=>531,192=>684,193=>684,194=>684,195=>684,196=>684,197=>684,198=>974,199=>698,200=>632,201=>632,202=>632,203=>632,204=>295,205=>295,206=>295,207=>295,208=>775,209=>748,210=>787,211=>787,212=>787,213=>787,214=>787,215=>838,216=>787,217=>732,218=>732,219=>732,220=>732,221=>611,222=>608,223=>630,224=>613,225=>613,226=>613,227=>613,228=>613,229=>613,230=>995,231=>550,232=>615,233=>615,234=>615,235=>615,236=>278,237=>278,238=>278,239=>278,240=>612,241=>634,242=>612,243=>612,244=>612,245=>612,246=>612,247=>838,248=>612,249=>634,250=>634,251=>634,252=>634,253=>592,254=>635,255=>592,256=>684,257=>613,258=>684,259=>613,260=>684,261=>613,262=>698,263=>550,264=>698,265=>550,266=>698,267=>550,268=>698,269=>550,270=>770,271=>635,272=>775,273=>635,274=>632,275=>615,276=>632,277=>615,278=>632,279=>615,280=>632,281=>615,282=>632,283=>615,284=>775,285=>635,286=>775,287=>635,288=>775,289=>635,290=>775,291=>635,292=>752,293=>634,294=>916,295=>695,296=>295,297=>278,298=>295,299=>278,300=>295,301=>278,302=>295,303=>278,304=>295,305=>278,306=>590,307=>556,308=>295,309=>278,310=>656,311=>579,312=>579,313=>557,314=>278,315=>557,316=>278,317=>557,318=>278,319=>557,320=>278,321=>562,322=>287,323=>748,324=>634,325=>748,326=>634,327=>748,328=>634,329=>813,330=>748,331=>634,332=>787,333=>612,334=>787,335=>612,336=>787,337=>612,338=>1070,339=>1028,340=>695,341=>411,342=>695,343=>411,344=>695,345=>411,346=>635,347=>521,348=>635,349=>521,350=>635,351=>521,352=>635,353=>521,354=>611,355=>392,356=>611,357=>392,358=>611,359=>392,360=>732,361=>634,362=>732,363=>634,364=>732,365=>634,366=>732,367=>634,368=>732,369=>634,370=>732,371=>634,372=>989,373=>818,374=>611,375=>592,376=>611,377=>685,378=>525,379=>685,380=>525,381=>685,382=>525,383=>352,384=>635,385=>735,386=>686,387=>635,388=>686,389=>635,390=>703,391=>698,392=>550,393=>775,394=>819,395=>686,396=>635,397=>612,398=>632,399=>787,400=>614,401=>575,402=>352,403=>775,404=>687,405=>984,406=>354,407=>295,408=>746,409=>579,410=>278,411=>592,412=>974,413=>748,414=>634,415=>787,416=>913,417=>612,418=>938,419=>737,420=>652,421=>635,422=>695,423=>635,424=>521,425=>632,426=>336,427=>392,428=>611,429=>392,430=>611,431=>838,432=>634,433=>764,434=>721,435=>744,436=>730,437=>685,438=>525,439=>666,440=>666,441=>578,442=>525,443=>636,444=>666,445=>578,446=>510,447=>635,448=>295,449=>492,450=>459,451=>295,452=>1455,453=>1295,454=>1160,455=>852,456=>835,457=>556,458=>1043,459=>1026,460=>912,461=>684,462=>613,463=>295,464=>278,465=>787,466=>612,467=>732,468=>634,469=>732,470=>634,471=>732,472=>634,473=>732,474=>634,475=>732,476=>634,477=>615,478=>684,479=>613,480=>684,481=>613,482=>974,483=>995,484=>775,485=>635,486=>775,487=>635,488=>656,489=>579,490=>787,491=>612,492=>787,493=>612,494=>666,495=>525,496=>278,497=>1455,498=>1295,499=>1160,500=>775,501=>635,502=>1113,503=>682,504=>748,505=>634,506=>684,507=>613,508=>974,509=>995,510=>787,511=>612,512=>684,513=>613,514=>684,515=>613,516=>632,517=>615,518=>632,519=>615,520=>295,521=>278,522=>295,523=>278,524=>787,525=>612,526=>787,527=>612,528=>695,529=>411,530=>695,531=>411,532=>732,533=>634,534=>732,535=>634,536=>635,537=>521,538=>611,539=>392,540=>627,541=>521,542=>752,543=>634,544=>735,545=>838,546=>698,547=>610,548=>685,549=>525,550=>684,551=>613,552=>632,553=>615,554=>787,555=>612,556=>787,557=>612,558=>787,559=>612,560=>787,561=>612,562=>611,563=>592,564=>475,565=>843,566=>477,567=>278,568=>998,569=>998,570=>684,571=>698,572=>550,573=>557,574=>611,575=>521,576=>525,577=>603,578=>479,579=>686,580=>732,581=>684,582=>632,583=>615,584=>295,585=>278,586=>781,587=>635,588=>695,589=>411,590=>611,591=>592,592=>613,593=>635,594=>635,595=>635,596=>550,597=>550,598=>635,599=>727,600=>615,601=>615,602=>844,603=>545,604=>545,605=>775,606=>664,607=>326,608=>696,609=>635,610=>629,611=>596,612=>596,613=>634,614=>634,615=>634,616=>372,617=>387,618=>372,619=>396,620=>487,621=>278,622=>706,623=>974,624=>974,625=>974,626=>646,627=>642,628=>634,629=>612,630=>858,631=>728,632=>660,633=>469,634=>469,635=>469,636=>469,637=>469,638=>530,639=>530,640=>602,641=>602,642=>521,643=>336,644=>336,645=>461,646=>336,647=>392,648=>392,649=>634,650=>618,651=>598,652=>592,653=>818,654=>592,655=>611,656=>525,657=>525,658=>578,659=>578,660=>510,661=>510,662=>510,663=>510,664=>787,665=>580,666=>664,667=>708,668=>654,669=>292,670=>667,671=>507,672=>727,673=>510,674=>510,675=>1014,676=>1058,677=>1013,678=>830,679=>610,680=>778,681=>848,682=>706,683=>654,684=>515,685=>515,686=>570,687=>664,688=>399,689=>399,690=>175,691=>259,692=>295,693=>296,694=>379,695=>515,696=>373,697=>278,698=>460,699=>318,700=>318,701=>318,702=>307,703=>307,704=>370,705=>370,706=>500,707=>500,708=>500,709=>500,710=>500,711=>500,712=>275,713=>500,714=>500,715=>500,716=>275,717=>500,718=>500,719=>500,720=>337,721=>337,722=>307,723=>307,724=>500,725=>500,726=>390,727=>317,728=>500,729=>500,730=>500,731=>500,732=>500,733=>500,734=>315,735=>500,736=>426,737=>166,738=>373,739=>444,740=>370,741=>493,742=>493,743=>493,744=>493,745=>493,748=>500,749=>500,750=>518,755=>500,759=>500,768=>0,769=>0,770=>0,771=>0,772=>0,773=>0,774=>0,775=>0,776=>0,777=>0,778=>0,779=>0,780=>0,781=>0,782=>0,783=>0,784=>0,785=>0,786=>0,787=>0,788=>0,789=>0,790=>0,791=>0,792=>0,793=>0,794=>0,795=>0,796=>0,797=>0,798=>0,799=>0,800=>0,801=>0,802=>0,803=>0,804=>0,805=>0,806=>0,807=>0,808=>0,809=>0,810=>0,811=>0,812=>0,813=>0,814=>0,815=>0,816=>0,817=>0,818=>0,819=>0,820=>0,821=>0,822=>0,823=>0,824=>0,825=>0,826=>0,827=>0,828=>0,829=>0,830=>0,831=>0,832=>0,833=>0,834=>0,835=>0,836=>0,837=>0,838=>0,839=>0,840=>0,841=>0,842=>0,843=>0,844=>0,845=>0,846=>0,847=>0,849=>0,850=>0,851=>0,855=>0,856=>0,858=>0,860=>0,861=>0,862=>0,863=>0,864=>0,865=>0,866=>0,880=>654,881=>568,882=>862,883=>647,884=>278,885=>278,886=>748,887=>650,890=>500,891=>549,892=>550,893=>549,894=>337,900=>500,901=>500,902=>684,903=>318,904=>767,905=>903,906=>435,908=>839,910=>860,911=>905,912=>338,913=>684,914=>686,915=>557,916=>684,917=>632,918=>685,919=>752,920=>787,921=>295,922=>656,923=>684,924=>863,925=>748,926=>632,927=>787,928=>752,929=>603,931=>632,932=>611,933=>611,934=>787,935=>685,936=>787,937=>764,938=>295,939=>611,940=>659,941=>541,942=>634,943=>338,944=>579,945=>659,946=>638,947=>592,948=>612,949=>541,950=>544,951=>634,952=>612,953=>338,954=>589,955=>592,956=>636,957=>559,958=>558,959=>612,960=>602,961=>635,962=>587,963=>634,964=>602,965=>579,966=>660,967=>592,968=>660,969=>837,970=>338,971=>579,972=>612,973=>579,974=>837,975=>656,976=>614,977=>619,978=>699,979=>842,980=>699,981=>660,982=>837,983=>664,984=>787,985=>612,986=>648,987=>587,988=>575,989=>458,990=>660,991=>660,992=>865,993=>627,994=>934,995=>837,996=>758,997=>659,998=>792,999=>615,1000=>687,1001=>607,1002=>768,1003=>625,1004=>699,1005=>612,1006=>611,1007=>536,1008=>664,1009=>635,1010=>550,1011=>278,1012=>787,1013=>615,1014=>615,1015=>608,1016=>635,1017=>698,1018=>863,1019=>651,1020=>635,1021=>703,1022=>698,1023=>703,1024=>632,1025=>632,1026=>786,1027=>557,1028=>698,1029=>635,1030=>295,1031=>295,1032=>295,1033=>1094,1034=>1045,1035=>786,1036=>710,1037=>748,1038=>609,1039=>752,1040=>684,1041=>686,1042=>686,1043=>557,1044=>781,1045=>632,1046=>1077,1047=>641,1048=>748,1049=>748,1050=>710,1051=>752,1052=>863,1053=>752,1054=>787,1055=>752,1056=>603,1057=>698,1058=>611,1059=>609,1060=>861,1061=>685,1062=>776,1063=>686,1064=>1069,1065=>1094,1066=>833,1067=>818,1068=>686,1069=>698,1070=>1080,1071=>695,1072=>613,1073=>617,1074=>589,1075=>525,1076=>691,1077=>615,1078=>901,1079=>532,1080=>650,1081=>650,1082=>604,1083=>639,1084=>754,1085=>654,1086=>612,1087=>654,1088=>635,1089=>550,1090=>583,1091=>592,1092=>855,1093=>592,1094=>681,1095=>591,1096=>915,1097=>942,1098=>707,1099=>790,1100=>589,1101=>549,1102=>842,1103=>602,1104=>615,1105=>615,1106=>625,1107=>525,1108=>549,1109=>521,1110=>278,1111=>278,1112=>278,1113=>902,1114=>898,1115=>652,1116=>604,1117=>650,1118=>592,1119=>654,1120=>934,1121=>837,1122=>771,1123=>672,1124=>942,1125=>749,1126=>879,1127=>783,1128=>1160,1129=>1001,1130=>787,1131=>612,1132=>1027,1133=>824,1134=>636,1135=>541,1136=>856,1137=>876,1138=>787,1139=>612,1140=>781,1141=>665,1142=>781,1143=>665,1144=>992,1145=>904,1146=>953,1147=>758,1148=>1180,1149=>1028,1150=>934,1151=>837,1152=>698,1153=>550,1154=>502,1155=>0,1156=>0,1157=>0,1158=>0,1159=>0,1160=>418,1161=>418,1162=>748,1163=>657,1164=>686,1165=>589,1166=>603,1167=>635,1168=>610,1169=>525,1170=>675,1171=>556,1172=>557,1173=>491,1174=>1077,1175=>901,1176=>641,1177=>532,1178=>710,1179=>604,1180=>710,1181=>604,1182=>710,1183=>604,1184=>856,1185=>832,1186=>752,1187=>661,1188=>1014,1189=>877,1190=>1113,1191=>950,1192=>890,1193=>707,1194=>698,1195=>550,1196=>611,1197=>529,1198=>611,1199=>592,1200=>611,1201=>592,1202=>685,1203=>592,1204=>934,1205=>807,1206=>686,1207=>591,1208=>686,1209=>591,1210=>686,1211=>634,1212=>929,1213=>731,1214=>929,1215=>731,1216=>295,1217=>1077,1218=>901,1219=>655,1220=>604,1221=>752,1222=>639,1223=>752,1224=>661,1225=>752,1226=>661,1227=>686,1228=>591,1229=>863,1230=>754,1231=>278,1232=>684,1233=>613,1234=>684,1235=>613,1236=>974,1237=>995,1238=>632,1239=>615,1240=>787,1241=>615,1242=>787,1243=>615,1244=>1077,1245=>901,1246=>641,1247=>532,1248=>666,1249=>578,1250=>748,1251=>650,1252=>748,1253=>650,1254=>787,1255=>612,1256=>787,1257=>612,1258=>787,1259=>612,1260=>698,1261=>549,1262=>609,1263=>592,1264=>609,1265=>592,1266=>609,1267=>592,1268=>686,1269=>591,1270=>557,1271=>491,1272=>818,1273=>790,1274=>675,1275=>556,1276=>685,1277=>592,1278=>685,1279=>592,1280=>686,1281=>589,1282=>1006,1283=>897,1284=>975,1285=>869,1286=>679,1287=>588,1288=>1072,1289=>957,1290=>1113,1291=>967,1292=>775,1293=>660,1294=>773,1295=>711,1296=>614,1297=>541,1298=>752,1299=>639,1300=>1195,1301=>997,1302=>900,1303=>867,1304=>1031,1305=>989,1306=>787,1307=>635,1308=>989,1309=>818,1310=>710,1311=>604,1312=>1113,1313=>942,1314=>1113,1315=>949,1316=>793,1317=>683,1329=>766,1330=>732,1331=>753,1332=>753,1333=>732,1334=>772,1335=>640,1336=>732,1337=>859,1338=>753,1339=>691,1340=>533,1341=>922,1342=>863,1343=>732,1344=>716,1345=>766,1346=>753,1347=>767,1348=>792,1349=>728,1350=>729,1351=>757,1352=>732,1353=>713,1354=>800,1355=>768,1356=>792,1357=>732,1358=>753,1359=>705,1360=>694,1361=>744,1362=>538,1363=>811,1364=>757,1365=>787,1366=>790,1369=>307,1370=>318,1371=>234,1372=>361,1373=>238,1374=>405,1375=>500,1377=>974,1378=>634,1379=>658,1380=>663,1381=>634,1382=>635,1383=>515,1384=>634,1385=>738,1386=>658,1387=>634,1388=>271,1389=>980,1390=>623,1391=>634,1392=>634,1393=>608,1394=>634,1395=>629,1396=>634,1397=>278,1398=>634,1399=>499,1400=>634,1401=>404,1402=>974,1403=>560,1404=>648,1405=>634,1406=>634,1407=>974,1408=>634,1409=>635,1410=>435,1411=>974,1412=>636,1413=>612,1414=>805,1415=>812,1417=>337,1418=>361,1456=>0,1457=>0,1458=>0,1459=>0,1460=>0,1461=>0,1462=>0,1463=>0,1464=>0,1465=>0,1466=>0,1467=>0,1468=>0,1469=>0,1470=>361,1471=>0,1472=>295,1473=>0,1474=>0,1475=>295,1478=>456,1479=>0,1488=>668,1489=>578,1490=>412,1491=>546,1492=>653,1493=>272,1494=>346,1495=>653,1496=>648,1497=>224,1498=>537,1499=>529,1500=>568,1501=>664,1502=>679,1503=>272,1504=>400,1505=>649,1506=>626,1507=>640,1508=>625,1509=>540,1510=>593,1511=>709,1512=>564,1513=>708,1514=>657,1520=>471,1521=>454,1522=>471,1523=>416,1524=>645,3647=>636,3713=>670,3714=>684,3716=>688,3719=>482,3720=>628,3722=>684,3725=>688,3732=>642,3733=>642,3734=>672,3735=>655,3737=>641,3738=>592,3739=>592,3740=>745,3741=>767,3742=>687,3743=>687,3745=>702,3746=>688,3747=>684,3749=>649,3751=>632,3754=>703,3755=>819,3757=>633,3758=>684,3759=>788,3760=>632,3761=>0,3762=>539,3763=>539,3764=>0,3765=>0,3766=>0,3767=>0,3768=>0,3769=>0,3771=>0,3772=>0,3773=>663,3776=>360,3777=>679,3778=>460,3779=>547,3780=>491,3782=>674,3784=>0,3785=>0,3786=>0,3787=>0,3788=>0,3789=>0,3792=>636,3793=>641,3794=>641,3795=>670,3796=>625,3797=>625,3798=>703,3799=>670,3800=>674,3801=>677,3804=>1028,3805=>1028,4256=>874,4257=>733,4258=>679,4259=>834,4260=>615,4261=>768,4262=>753,4263=>914,4264=>453,4265=>620,4266=>843,4267=>882,4268=>625,4269=>854,4270=>781,4271=>629,4272=>912,4273=>621,4274=>620,4275=>854,4276=>866,4277=>724,4278=>630,4279=>621,4280=>625,4281=>620,4282=>818,4283=>874,4284=>615,4285=>623,4286=>625,4287=>725,4288=>844,4289=>596,4290=>688,4291=>596,4292=>594,4293=>738,4304=>508,4305=>518,4306=>581,4307=>818,4308=>508,4309=>513,4310=>500,4311=>801,4312=>518,4313=>510,4314=>1064,4315=>522,4316=>522,4317=>786,4318=>508,4319=>518,4320=>796,4321=>522,4322=>654,4323=>522,4324=>825,4325=>513,4326=>786,4327=>518,4328=>518,4329=>522,4330=>571,4331=>522,4332=>518,4333=>520,4334=>522,4335=>454,4336=>508,4337=>518,4338=>508,4339=>508,4340=>518,4341=>554,4342=>828,4343=>552,4344=>508,4345=>571,4346=>508,4347=>448,4348=>324,5121=>684,5122=>684,5123=>684,5124=>684,5125=>769,5126=>769,5127=>769,5129=>769,5130=>769,5131=>769,5132=>835,5133=>834,5134=>835,5135=>834,5136=>835,5137=>834,5138=>967,5139=>1007,5140=>967,5141=>1007,5142=>769,5143=>967,5144=>1007,5145=>967,5146=>1007,5147=>769,5149=>256,5150=>543,5151=>423,5152=>423,5153=>389,5154=>389,5155=>393,5156=>389,5157=>466,5158=>385,5159=>256,5160=>389,5161=>389,5162=>389,5163=>1090,5164=>909,5165=>953,5166=>1117,5167=>684,5168=>684,5169=>684,5170=>684,5171=>729,5172=>729,5173=>729,5175=>729,5176=>729,5177=>729,5178=>835,5179=>684,5180=>835,5181=>834,5182=>835,5183=>834,5184=>967,5185=>1007,5186=>967,5187=>1007,5188=>967,5189=>1007,5190=>967,5191=>1007,5192=>729,5193=>508,5194=>192,5196=>732,5197=>732,5198=>732,5199=>732,5200=>730,5201=>730,5202=>730,5204=>730,5205=>730,5206=>730,5207=>921,5208=>889,5209=>921,5210=>889,5211=>921,5212=>889,5213=>928,5214=>900,5215=>928,5216=>900,5217=>947,5218=>900,5219=>947,5220=>900,5221=>947,5222=>434,5223=>877,5224=>877,5225=>866,5226=>890,5227=>628,5228=>628,5229=>628,5230=>628,5231=>628,5232=>628,5233=>628,5234=>628,5235=>628,5236=>860,5237=>771,5238=>815,5239=>816,5240=>815,5241=>816,5242=>860,5243=>771,5244=>860,5245=>771,5246=>815,5247=>816,5248=>815,5249=>816,5250=>815,5251=>407,5252=>407,5253=>750,5254=>775,5255=>750,5256=>775,5257=>628,5258=>628,5259=>628,5260=>628,5261=>628,5262=>628,5263=>628,5264=>628,5265=>628,5266=>860,5267=>771,5268=>815,5269=>816,5270=>815,5271=>816,5272=>860,5273=>771,5274=>860,5275=>771,5276=>815,5277=>816,5278=>815,5279=>816,5280=>815,5281=>435,5282=>435,5283=>610,5284=>557,5285=>557,5286=>557,5287=>610,5288=>610,5289=>610,5290=>557,5291=>557,5292=>749,5293=>769,5294=>746,5295=>764,5296=>746,5297=>764,5298=>749,5299=>769,5300=>749,5301=>769,5302=>746,5303=>764,5304=>746,5305=>764,5306=>746,5307=>386,5308=>508,5309=>386,5312=>852,5313=>852,5314=>852,5315=>852,5316=>852,5317=>852,5318=>852,5319=>852,5320=>852,5321=>1069,5322=>1035,5323=>1059,5324=>852,5325=>1059,5326=>852,5327=>852,5328=>600,5329=>453,5330=>600,5331=>852,5332=>852,5333=>852,5334=>852,5335=>852,5336=>852,5337=>852,5338=>852,5339=>852,5340=>1069,5341=>1035,5342=>1059,5343=>1030,5344=>1059,5345=>1030,5346=>1069,5347=>1035,5348=>1069,5349=>1035,5350=>1083,5351=>1030,5352=>1083,5353=>1030,5354=>600,5356=>729,5357=>603,5358=>603,5359=>603,5360=>603,5361=>603,5362=>603,5363=>603,5364=>603,5365=>603,5366=>834,5367=>754,5368=>792,5369=>771,5370=>792,5371=>771,5372=>834,5373=>754,5374=>834,5375=>754,5376=>792,5377=>771,5378=>792,5379=>771,5380=>792,5381=>418,5382=>420,5383=>418,5392=>712,5393=>712,5394=>712,5395=>892,5396=>892,5397=>892,5398=>892,5399=>910,5400=>872,5401=>910,5402=>872,5403=>910,5404=>872,5405=>1140,5406=>1100,5407=>1140,5408=>1100,5409=>1140,5410=>1100,5411=>1140,5412=>1100,5413=>641,5414=>627,5415=>627,5416=>627,5417=>627,5418=>627,5419=>627,5420=>627,5421=>627,5422=>627,5423=>844,5424=>781,5425=>816,5426=>818,5427=>816,5428=>818,5429=>844,5430=>781,5431=>844,5432=>781,5433=>816,5434=>818,5435=>816,5436=>818,5437=>816,5438=>418,5440=>389,5441=>484,5442=>916,5443=>916,5444=>863,5445=>916,5446=>863,5447=>863,5448=>603,5449=>603,5450=>603,5451=>603,5452=>603,5453=>603,5454=>834,5455=>754,5456=>418,5458=>729,5459=>684,5460=>684,5461=>684,5462=>684,5463=>726,5464=>726,5465=>726,5466=>726,5467=>924,5468=>1007,5469=>508,5470=>732,5471=>732,5472=>732,5473=>732,5474=>732,5475=>732,5476=>730,5477=>730,5478=>730,5479=>730,5480=>947,5481=>900,5482=>508,5492=>831,5493=>831,5494=>831,5495=>831,5496=>831,5497=>831,5498=>831,5499=>563,5500=>752,5501=>484,5502=>1047,5503=>1047,5504=>1047,5505=>1047,5506=>1047,5507=>1047,5508=>1047,5509=>825,5514=>831,5515=>831,5516=>831,5517=>831,5518=>1259,5519=>1259,5520=>1259,5521=>1002,5522=>1002,5523=>1259,5524=>1259,5525=>700,5526=>1073,5536=>852,5537=>852,5538=>799,5539=>799,5540=>799,5541=>799,5542=>600,5543=>643,5544=>643,5545=>643,5546=>643,5547=>643,5548=>643,5549=>643,5550=>418,5551=>628,5598=>770,5601=>770,5702=>468,5703=>468,5742=>444,5743=>1047,5744=>1310,5745=>1632,5746=>1632,5747=>1375,5748=>1375,5749=>1632,5750=>1632,7424=>592,7425=>717,7426=>982,7427=>586,7428=>550,7429=>605,7430=>605,7431=>491,7432=>541,7433=>278,7434=>395,7435=>579,7436=>583,7437=>754,7438=>650,7439=>612,7440=>550,7441=>684,7442=>684,7443=>684,7444=>1023,7446=>612,7447=>612,7448=>524,7449=>602,7450=>602,7451=>583,7452=>574,7453=>737,7454=>948,7455=>638,7456=>592,7457=>818,7458=>525,7459=>526,7462=>583,7463=>592,7464=>564,7465=>524,7466=>590,7467=>639,7468=>431,7469=>613,7470=>432,7472=>485,7473=>398,7474=>398,7475=>488,7476=>474,7477=>186,7478=>186,7479=>413,7480=>351,7481=>543,7482=>471,7483=>471,7484=>496,7485=>439,7486=>380,7487=>438,7488=>385,7489=>461,7490=>623,7491=>392,7492=>392,7493=>405,7494=>648,7495=>428,7496=>405,7497=>417,7498=>417,7499=>360,7500=>359,7501=>405,7502=>179,7503=>426,7504=>623,7505=>409,7506=>414,7507=>370,7508=>414,7509=>414,7510=>428,7511=>295,7512=>405,7513=>470,7514=>623,7515=>417,7517=>402,7518=>373,7519=>385,7520=>416,7521=>364,7522=>179,7523=>259,7524=>405,7525=>417,7526=>402,7527=>373,7528=>412,7529=>416,7530=>364,7543=>635,7544=>474,7547=>372,7549=>667,7557=>278,7579=>405,7580=>370,7581=>370,7582=>414,7583=>360,7584=>296,7585=>233,7586=>405,7587=>405,7588=>261,7589=>250,7590=>261,7591=>261,7592=>234,7593=>250,7594=>235,7595=>376,7596=>623,7597=>623,7598=>411,7599=>479,7600=>409,7601=>414,7602=>414,7603=>360,7604=>287,7605=>295,7606=>508,7607=>418,7608=>361,7609=>406,7610=>417,7611=>366,7612=>437,7613=>366,7614=>392,7615=>414,7620=>0,7621=>0,7622=>0,7623=>0,7624=>0,7625=>0,7680=>684,7681=>613,7682=>686,7683=>635,7684=>686,7685=>635,7686=>686,7687=>635,7688=>698,7689=>550,7690=>770,7691=>635,7692=>770,7693=>635,7694=>770,7695=>635,7696=>770,7697=>635,7698=>770,7699=>635,7700=>632,7701=>615,7702=>632,7703=>615,7704=>632,7705=>615,7706=>632,7707=>615,7708=>632,7709=>615,7710=>575,7711=>352,7712=>775,7713=>635,7714=>752,7715=>634,7716=>752,7717=>634,7718=>752,7719=>634,7720=>752,7721=>634,7722=>752,7723=>634,7724=>295,7725=>278,7726=>295,7727=>278,7728=>656,7729=>579,7730=>656,7731=>579,7732=>656,7733=>579,7734=>557,7735=>278,7736=>557,7737=>278,7738=>557,7739=>278,7740=>557,7741=>278,7742=>863,7743=>974,7744=>863,7745=>974,7746=>863,7747=>974,7748=>748,7749=>634,7750=>748,7751=>634,7752=>748,7753=>634,7754=>748,7755=>634,7756=>787,7757=>612,7758=>787,7759=>612,7760=>787,7761=>612,7762=>787,7763=>612,7764=>603,7765=>635,7766=>603,7767=>635,7768=>695,7769=>411,7770=>695,7771=>411,7772=>695,7773=>411,7774=>695,7775=>411,7776=>635,7777=>521,7778=>635,7779=>521,7780=>635,7781=>521,7782=>635,7783=>521,7784=>635,7785=>521,7786=>611,7787=>392,7788=>611,7789=>392,7790=>611,7791=>392,7792=>611,7793=>392,7794=>732,7795=>634,7796=>732,7797=>634,7798=>732,7799=>634,7800=>732,7801=>634,7802=>732,7803=>634,7804=>684,7805=>592,7806=>684,7807=>592,7808=>989,7809=>818,7810=>989,7811=>818,7812=>989,7813=>818,7814=>989,7815=>818,7816=>989,7817=>818,7818=>685,7819=>592,7820=>685,7821=>592,7822=>611,7823=>592,7824=>685,7825=>525,7826=>685,7827=>525,7828=>685,7829=>525,7830=>634,7831=>392,7832=>818,7833=>592,7834=>613,7835=>352,7836=>352,7837=>352,7838=>769,7839=>612,7840=>684,7841=>613,7842=>684,7843=>613,7844=>684,7845=>613,7846=>684,7847=>613,7848=>684,7849=>613,7850=>684,7851=>613,7852=>684,7853=>613,7854=>684,7855=>613,7856=>684,7857=>613,7858=>684,7859=>613,7860=>684,7861=>613,7862=>684,7863=>613,7864=>632,7865=>615,7866=>632,7867=>615,7868=>632,7869=>615,7870=>632,7871=>615,7872=>632,7873=>615,7874=>632,7875=>615,7876=>632,7877=>615,7878=>632,7879=>615,7880=>295,7881=>278,7882=>295,7883=>278,7884=>787,7885=>612,7886=>787,7887=>612,7888=>787,7889=>612,7890=>787,7891=>612,7892=>787,7893=>612,7894=>787,7895=>612,7896=>787,7897=>612,7898=>913,7899=>612,7900=>913,7901=>612,7902=>913,7903=>612,7904=>913,7905=>612,7906=>913,7907=>612,7908=>732,7909=>634,7910=>732,7911=>634,7912=>838,7913=>634,7914=>838,7915=>634,7916=>838,7917=>634,7918=>838,7919=>634,7920=>838,7921=>634,7922=>611,7923=>592,7924=>611,7925=>592,7926=>611,7927=>592,7928=>611,7929=>592,7930=>769,7931=>477,7936=>659,7937=>659,7938=>659,7939=>659,7940=>659,7941=>659,7942=>659,7943=>659,7944=>684,7945=>684,7946=>877,7947=>877,7948=>769,7949=>801,7950=>708,7951=>743,7952=>541,7953=>541,7954=>541,7955=>541,7956=>541,7957=>541,7960=>711,7961=>711,7962=>966,7963=>975,7964=>898,7965=>928,7968=>634,7969=>634,7970=>634,7971=>634,7972=>634,7973=>634,7974=>634,7975=>634,7976=>837,7977=>835,7978=>1086,7979=>1089,7980=>1027,7981=>1051,7982=>934,7983=>947,7984=>338,7985=>338,7986=>338,7987=>338,7988=>338,7989=>338,7990=>338,7991=>338,7992=>380,7993=>374,7994=>635,7995=>635,7996=>570,7997=>600,7998=>489,7999=>493,8000=>612,8001=>612,8002=>612,8003=>612,8004=>612,8005=>612,8008=>804,8009=>848,8010=>1095,8011=>1100,8012=>938,8013=>970,8016=>579,8017=>579,8018=>579,8019=>579,8020=>579,8021=>579,8022=>579,8023=>579,8025=>784,8027=>998,8029=>1012,8031=>897,8032=>837,8033=>837,8034=>837,8035=>837,8036=>837,8037=>837,8038=>837,8039=>837,8040=>802,8041=>843,8042=>1089,8043=>1095,8044=>946,8045=>972,8046=>921,8047=>952,8048=>659,8049=>659,8050=>541,8051=>548,8052=>634,8053=>654,8054=>338,8055=>338,8056=>612,8057=>612,8058=>579,8059=>579,8060=>837,8061=>837,8064=>659,8065=>659,8066=>659,8067=>659,8068=>659,8069=>659,8070=>659,8071=>659,8072=>684,8073=>684,8074=>877,8075=>877,8076=>769,8077=>801,8078=>708,8079=>743,8080=>634,8081=>634,8082=>634,8083=>634,8084=>634,8085=>634,8086=>634,8087=>634,8088=>837,8089=>835,8090=>1086,8091=>1089,8092=>1027,8093=>1051,8094=>934,8095=>947,8096=>837,8097=>837,8098=>837,8099=>837,8100=>837,8101=>837,8102=>837,8103=>837,8104=>802,8105=>843,8106=>1089,8107=>1095,8108=>946,8109=>972,8110=>921,8111=>952,8112=>659,8113=>659,8114=>659,8115=>659,8116=>659,8118=>659,8119=>659,8120=>684,8121=>684,8122=>716,8123=>692,8124=>684,8125=>500,8126=>500,8127=>500,8128=>500,8129=>500,8130=>634,8131=>634,8132=>654,8134=>634,8135=>634,8136=>805,8137=>746,8138=>931,8139=>871,8140=>752,8141=>500,8142=>500,8143=>500,8144=>338,8145=>338,8146=>338,8147=>338,8150=>338,8151=>338,8152=>295,8153=>295,8154=>475,8155=>408,8157=>500,8158=>500,8159=>500,8160=>579,8161=>579,8162=>579,8163=>579,8164=>635,8165=>635,8166=>579,8167=>579,8168=>611,8169=>611,8170=>845,8171=>825,8172=>685,8173=>500,8174=>500,8175=>500,8178=>837,8179=>837,8180=>837,8182=>837,8183=>837,8184=>941,8185=>813,8186=>922,8187=>826,8188=>764,8189=>500,8190=>500,8192=>500,8193=>1000,8194=>500,8195=>1000,8196=>330,8197=>250,8198=>167,8199=>636,8200=>318,8201=>200,8202=>100,8203=>0,8204=>0,8205=>0,8206=>0,8207=>0,8208=>361,8209=>361,8210=>636,8211=>500,8212=>1000,8213=>1000,8214=>500,8215=>500,8216=>318,8217=>318,8218=>318,8219=>318,8220=>518,8221=>518,8222=>518,8223=>518,8224=>500,8225=>500,8226=>590,8227=>590,8228=>333,8229=>667,8230=>1000,8231=>318,8232=>0,8233=>0,8234=>0,8235=>0,8236=>0,8237=>0,8238=>0,8239=>200,8240=>1350,8241=>1690,8242=>227,8243=>374,8244=>520,8245=>227,8246=>374,8247=>520,8248=>339,8249=>400,8250=>400,8251=>838,8252=>485,8253=>531,8254=>500,8255=>804,8256=>804,8257=>250,8258=>1000,8259=>500,8260=>167,8261=>390,8262=>390,8263=>922,8264=>733,8265=>733,8266=>497,8267=>636,8268=>500,8269=>500,8270=>500,8271=>337,8272=>804,8273=>500,8274=>450,8275=>1000,8276=>804,8277=>838,8278=>586,8279=>663,8280=>838,8281=>838,8282=>318,8283=>797,8284=>838,8285=>318,8286=>318,8287=>222,8288=>0,8289=>0,8290=>0,8291=>0,8292=>0,8298=>0,8299=>0,8300=>0,8301=>0,8302=>0,8303=>0,8304=>401,8305=>179,8308=>401,8309=>401,8310=>401,8311=>401,8312=>401,8313=>401,8314=>528,8315=>528,8316=>528,8317=>246,8318=>246,8319=>399,8320=>401,8321=>401,8322=>401,8323=>401,8324=>401,8325=>401,8326=>401,8327=>401,8328=>401,8329=>401,8330=>528,8331=>528,8332=>528,8333=>246,8334=>246,8336=>392,8337=>417,8338=>414,8339=>444,8340=>417,8341=>399,8342=>426,8343=>166,8344=>623,8345=>399,8346=>428,8347=>373,8348=>295,8352=>877,8353=>636,8354=>636,8355=>636,8356=>636,8357=>974,8358=>748,8359=>1271,8360=>1074,8361=>989,8362=>838,8363=>636,8364=>636,8365=>636,8366=>636,8367=>1272,8368=>636,8369=>636,8370=>636,8371=>636,8372=>774,8373=>636,8376=>636,8377=>636,8378=>679,8400=>0,8401=>0,8406=>0,8407=>0,8411=>0,8412=>0,8417=>0,8448=>970,8449=>970,8450=>698,8451=>1123,8452=>896,8453=>969,8454=>1032,8455=>614,8456=>698,8457=>952,8459=>988,8460=>754,8461=>850,8462=>634,8463=>634,8464=>470,8465=>697,8466=>720,8467=>413,8468=>818,8469=>801,8470=>1040,8471=>1000,8472=>697,8473=>701,8474=>787,8475=>798,8476=>814,8477=>792,8478=>896,8479=>684,8480=>1020,8481=>1014,8482=>1000,8483=>684,8484=>745,8485=>578,8486=>764,8487=>764,8488=>616,8489=>338,8490=>656,8491=>684,8492=>786,8493=>703,8494=>854,8495=>592,8496=>605,8497=>786,8498=>575,8499=>1069,8500=>462,8501=>745,8502=>674,8503=>466,8504=>645,8505=>380,8506=>926,8507=>1157,8508=>702,8509=>728,8510=>654,8511=>849,8512=>811,8513=>775,8514=>557,8515=>557,8516=>611,8517=>819,8518=>708,8519=>615,8520=>351,8521=>351,8523=>780,8526=>526,8528=>969,8529=>969,8530=>1370,8531=>969,8532=>969,8533=>969,8534=>969,8535=>969,8536=>969,8537=>969,8538=>969,8539=>969,8540=>969,8541=>969,8542=>969,8543=>568,8544=>295,8545=>492,8546=>689,8547=>923,8548=>684,8549=>922,8550=>1120,8551=>1317,8552=>917,8553=>685,8554=>933,8555=>1131,8556=>557,8557=>698,8558=>770,8559=>863,8560=>278,8561=>458,8562=>637,8563=>812,8564=>592,8565=>811,8566=>991,8567=>1170,8568=>819,8569=>592,8570=>822,8571=>1002,8572=>278,8573=>550,8574=>635,8575=>974,8576=>1245,8577=>770,8578=>1245,8579=>703,8580=>549,8581=>698,8585=>969,8592=>838,8593=>838,8594=>838,8595=>838,8596=>838,8597=>838,8598=>838,8599=>838,8600=>838,8601=>838,8602=>838,8603=>838,8604=>838,8605=>838,8606=>838,8607=>838,8608=>838,8609=>838,8610=>838,8611=>838,8612=>838,8613=>838,8614=>838,8615=>838,8616=>838,8617=>838,8618=>838,8619=>838,8620=>838,8621=>838,8622=>838,8623=>838,8624=>838,8625=>838,8626=>838,8627=>838,8628=>838,8629=>838,8630=>838,8631=>838,8632=>838,8633=>838,8634=>838,8635=>838,8636=>838,8637=>838,8638=>838,8639=>838,8640=>838,8641=>838,8642=>838,8643=>838,8644=>838,8645=>838,8646=>838,8647=>838,8648=>838,8649=>838,8650=>838,8651=>838,8652=>838,8653=>838,8654=>838,8655=>838,8656=>838,8657=>838,8658=>838,8659=>838,8660=>838,8661=>838,8662=>838,8663=>838,8664=>838,8665=>838,8666=>838,8667=>838,8668=>838,8669=>838,8670=>838,8671=>838,8672=>838,8673=>838,8674=>838,8675=>838,8676=>838,8677=>838,8678=>838,8679=>838,8680=>838,8681=>838,8682=>838,8683=>838,8684=>838,8685=>838,8686=>838,8687=>838,8688=>838,8689=>838,8690=>838,8691=>838,8692=>838,8693=>838,8694=>838,8695=>838,8696=>838,8697=>838,8698=>838,8699=>838,8700=>838,8701=>838,8702=>838,8703=>838,8704=>684,8705=>636,8706=>517,8707=>632,8708=>632,8709=>871,8710=>669,8711=>669,8712=>871,8713=>871,8714=>718,8715=>871,8716=>871,8717=>718,8718=>636,8719=>757,8720=>757,8721=>674,8722=>838,8723=>838,8724=>838,8725=>337,8726=>637,8727=>838,8728=>626,8729=>626,8730=>637,8731=>637,8732=>637,8733=>714,8734=>833,8735=>838,8736=>896,8737=>896,8738=>838,8739=>500,8740=>500,8741=>500,8742=>500,8743=>732,8744=>732,8745=>732,8746=>732,8747=>521,8748=>789,8749=>1057,8750=>521,8751=>789,8752=>1057,8753=>521,8754=>521,8755=>521,8756=>636,8757=>636,8758=>260,8759=>636,8760=>838,8761=>838,8762=>838,8763=>838,8764=>838,8765=>838,8766=>838,8767=>838,8768=>375,8769=>838,8770=>838,8771=>838,8772=>838,8773=>838,8774=>838,8775=>838,8776=>838,8777=>838,8778=>838,8779=>838,8780=>838,8781=>838,8782=>838,8783=>838,8784=>838,8785=>838,8786=>838,8787=>838,8788=>1000,8789=>1000,8790=>838,8791=>838,8792=>838,8793=>838,8794=>838,8795=>838,8796=>838,8797=>838,8798=>838,8799=>838,8800=>838,8801=>838,8802=>838,8803=>838,8804=>838,8805=>838,8806=>838,8807=>838,8808=>838,8809=>838,8810=>1047,8811=>1047,8812=>464,8813=>838,8814=>838,8815=>838,8816=>838,8817=>838,8818=>838,8819=>838,8820=>838,8821=>838,8822=>838,8823=>838,8824=>838,8825=>838,8826=>838,8827=>838,8828=>838,8829=>838,8830=>838,8831=>838,8832=>838,8833=>838,8834=>838,8835=>838,8836=>838,8837=>838,8838=>838,8839=>838,8840=>838,8841=>838,8842=>838,8843=>838,8844=>732,8845=>732,8846=>732,8847=>838,8848=>838,8849=>838,8850=>838,8851=>780,8852=>780,8853=>838,8854=>838,8855=>838,8856=>838,8857=>838,8858=>838,8859=>838,8860=>838,8861=>838,8862=>838,8863=>838,8864=>838,8865=>838,8866=>871,8867=>871,8868=>871,8869=>871,8870=>521,8871=>521,8872=>871,8873=>871,8874=>871,8875=>871,8876=>871,8877=>871,8878=>871,8879=>871,8880=>838,8881=>838,8882=>838,8883=>838,8884=>838,8885=>838,8886=>1000,8887=>1000,8888=>838,8889=>838,8890=>521,8891=>732,8892=>732,8893=>732,8894=>838,8895=>838,8896=>820,8897=>820,8898=>820,8899=>820,8900=>494,8901=>318,8902=>626,8903=>838,8904=>1000,8905=>1000,8906=>1000,8907=>1000,8908=>1000,8909=>838,8910=>732,8911=>732,8912=>838,8913=>838,8914=>838,8915=>838,8916=>838,8917=>838,8918=>838,8919=>838,8920=>1422,8921=>1422,8922=>838,8923=>838,8924=>838,8925=>838,8926=>838,8927=>838,8928=>838,8929=>838,8930=>838,8931=>838,8932=>838,8933=>838,8934=>838,8935=>838,8936=>838,8937=>838,8938=>838,8939=>838,8940=>838,8941=>838,8942=>1000,8943=>1000,8944=>1000,8945=>1000,8946=>1000,8947=>871,8948=>718,8949=>871,8950=>871,8951=>718,8952=>871,8953=>871,8954=>1000,8955=>871,8956=>718,8957=>871,8958=>718,8959=>871,8960=>602,8961=>602,8962=>635,8963=>838,8964=>838,8965=>838,8966=>838,8967=>488,8968=>390,8969=>390,8970=>390,8971=>390,8972=>809,8973=>809,8974=>809,8975=>809,8976=>838,8977=>513,8984=>1000,8985=>838,8988=>469,8989=>469,8990=>469,8991=>469,8992=>521,8993=>521,8996=>1152,8997=>1152,8998=>1414,8999=>1152,9000=>1443,9003=>1414,9004=>873,9075=>338,9076=>635,9077=>837,9082=>659,9085=>757,9095=>1152,9108=>873,9115=>500,9116=>500,9117=>500,9118=>500,9119=>500,9120=>500,9121=>500,9122=>500,9123=>500,9124=>500,9125=>500,9126=>500,9127=>750,9128=>750,9129=>750,9130=>750,9131=>750,9132=>750,9133=>750,9134=>521,9166=>838,9167=>945,9187=>873,9189=>769,9192=>636,9250=>635,9251=>635,9312=>896,9313=>896,9314=>896,9315=>896,9316=>896,9317=>896,9318=>896,9319=>896,9320=>896,9321=>896,9472=>602,9473=>602,9474=>602,9475=>602,9476=>602,9477=>602,9478=>602,9479=>602,9480=>602,9481=>602,9482=>602,9483=>602,9484=>602,9485=>602,9486=>602,9487=>602,9488=>602,9489=>602,9490=>602,9491=>602,9492=>602,9493=>602,9494=>602,9495=>602,9496=>602,9497=>602,9498=>602,9499=>602,9500=>602,9501=>602,9502=>602,9503=>602,9504=>602,9505=>602,9506=>602,9507=>602,9508=>602,9509=>602,9510=>602,9511=>602,9512=>602,9513=>602,9514=>602,9515=>602,9516=>602,9517=>602,9518=>602,9519=>602,9520=>602,9521=>602,9522=>602,9523=>602,9524=>602,9525=>602,9526=>602,9527=>602,9528=>602,9529=>602,9530=>602,9531=>602,9532=>602,9533=>602,9534=>602,9535=>602,9536=>602,9537=>602,9538=>602,9539=>602,9540=>602,9541=>602,9542=>602,9543=>602,9544=>602,9545=>602,9546=>602,9547=>602,9548=>602,9549=>602,9550=>602,9551=>602,9552=>602,9553=>602,9554=>602,9555=>602,9556=>602,9557=>602,9558=>602,9559=>602,9560=>602,9561=>602,9562=>602,9563=>602,9564=>602,9565=>602,9566=>602,9567=>602,9568=>602,9569=>602,9570=>602,9571=>602,9572=>602,9573=>602,9574=>602,9575=>602,9576=>602,9577=>602,9578=>602,9579=>602,9580=>602,9581=>602,9582=>602,9583=>602,9584=>602,9585=>602,9586=>602,9587=>602,9588=>602,9589=>602,9590=>602,9591=>602,9592=>602,9593=>602,9594=>602,9595=>602,9596=>602,9597=>602,9598=>602,9599=>602,9600=>769,9601=>769,9602=>769,9603=>769,9604=>769,9605=>769,9606=>769,9607=>769,9608=>769,9609=>769,9610=>769,9611=>769,9612=>769,9613=>769,9614=>769,9615=>769,9616=>769,9617=>769,9618=>769,9619=>769,9620=>769,9621=>769,9622=>769,9623=>769,9624=>769,9625=>769,9626=>769,9627=>769,9628=>769,9629=>769,9630=>769,9631=>769,9632=>945,9633=>945,9634=>945,9635=>945,9636=>945,9637=>945,9638=>945,9639=>945,9640=>945,9641=>945,9642=>678,9643=>678,9644=>945,9645=>945,9646=>550,9647=>550,9648=>769,9649=>769,9650=>769,9651=>769,9652=>502,9653=>502,9654=>769,9655=>769,9656=>502,9657=>502,9658=>769,9659=>769,9660=>769,9661=>769,9662=>502,9663=>502,9664=>769,9665=>769,9666=>502,9667=>502,9668=>769,9669=>769,9670=>769,9671=>769,9672=>769,9673=>873,9674=>494,9675=>873,9676=>873,9677=>873,9678=>873,9679=>873,9680=>873,9681=>873,9682=>873,9683=>873,9684=>873,9685=>873,9686=>527,9687=>527,9688=>791,9689=>970,9690=>970,9691=>970,9692=>387,9693=>387,9694=>387,9695=>387,9696=>769,9697=>769,9698=>769,9699=>769,9700=>769,9701=>769,9702=>590,9703=>945,9704=>945,9705=>945,9706=>945,9707=>945,9708=>769,9709=>769,9710=>769,9711=>1119,9712=>945,9713=>945,9714=>945,9715=>945,9716=>873,9717=>873,9718=>873,9719=>873,9720=>769,9721=>769,9722=>769,9723=>830,9724=>830,9725=>732,9726=>732,9727=>769,9728=>896,9729=>1000,9730=>896,9731=>896,9732=>896,9733=>896,9734=>896,9735=>573,9736=>896,9737=>896,9738=>888,9739=>888,9740=>671,9741=>1013,9742=>1246,9743=>1250,9744=>896,9745=>896,9746=>896,9747=>532,9748=>896,9749=>896,9750=>896,9751=>896,9752=>896,9753=>896,9754=>896,9755=>896,9756=>896,9757=>609,9758=>896,9759=>609,9760=>896,9761=>896,9762=>896,9763=>896,9764=>669,9765=>746,9766=>649,9767=>784,9768=>545,9769=>896,9770=>896,9771=>896,9772=>710,9773=>896,9774=>896,9775=>896,9776=>890,9777=>890,9778=>890,9779=>890,9780=>890,9781=>890,9782=>890,9783=>890,9784=>896,9785=>1042,9786=>1042,9787=>1042,9788=>896,9789=>896,9790=>896,9791=>614,9792=>732,9793=>732,9794=>896,9795=>896,9796=>896,9797=>896,9798=>896,9799=>896,9800=>896,9801=>896,9802=>896,9803=>896,9804=>896,9805=>896,9806=>896,9807=>896,9808=>896,9809=>896,9810=>896,9811=>896,9812=>896,9813=>896,9814=>896,9815=>896,9816=>896,9817=>896,9818=>896,9819=>896,9820=>896,9821=>896,9822=>896,9823=>896,9824=>896,9825=>896,9826=>896,9827=>896,9828=>896,9829=>896,9830=>896,9831=>896,9832=>896,9833=>472,9834=>638,9835=>896,9836=>896,9837=>472,9838=>357,9839=>484,9840=>748,9841=>766,9842=>896,9843=>896,9844=>896,9845=>896,9846=>896,9847=>896,9848=>896,9849=>896,9850=>896,9851=>896,9852=>896,9853=>896,9854=>896,9855=>896,9856=>869,9857=>869,9858=>869,9859=>869,9860=>869,9861=>869,9862=>890,9863=>890,9864=>890,9865=>890,9866=>890,9867=>890,9868=>890,9869=>890,9870=>890,9871=>890,9872=>750,9873=>750,9874=>890,9875=>816,9876=>716,9877=>537,9878=>852,9879=>890,9880=>684,9881=>896,9882=>708,9883=>890,9884=>890,9888=>890,9889=>702,9890=>1004,9891=>1089,9892=>1175,9893=>903,9894=>838,9895=>838,9896=>838,9897=>838,9898=>838,9899=>838,9900=>838,9901=>838,9902=>838,9903=>838,9904=>844,9905=>838,9906=>732,9907=>732,9908=>732,9909=>732,9910=>850,9911=>732,9912=>732,9920=>838,9921=>838,9922=>838,9923=>838,9954=>732,9985=>838,9986=>838,9987=>838,9988=>838,9990=>838,9991=>838,9992=>838,9993=>838,9996=>838,9997=>838,9998=>838,9999=>838,10000=>838,10001=>838,10002=>838,10003=>838,10004=>838,10005=>838,10006=>838,10007=>838,10008=>838,10009=>838,10010=>838,10011=>838,10012=>838,10013=>838,10014=>838,10015=>838,10016=>838,10017=>838,10018=>838,10019=>838,10020=>838,10021=>838,10022=>838,10023=>838,10025=>838,10026=>838,10027=>838,10028=>838,10029=>838,10030=>838,10031=>838,10032=>838,10033=>838,10034=>838,10035=>838,10036=>838,10037=>838,10038=>838,10039=>838,10040=>838,10041=>838,10042=>838,10043=>838,10044=>838,10045=>838,10046=>838,10047=>838,10048=>838,10049=>838,10050=>838,10051=>838,10052=>838,10053=>838,10054=>838,10055=>838,10056=>838,10057=>838,10058=>838,10059=>838,10061=>896,10063=>896,10064=>896,10065=>896,10066=>896,10070=>896,10072=>838,10073=>838,10074=>838,10075=>322,10076=>322,10077=>538,10078=>538,10081=>838,10082=>838,10083=>838,10084=>838,10085=>838,10086=>838,10087=>838,10088=>838,10089=>838,10090=>838,10091=>838,10092=>838,10093=>838,10094=>838,10095=>838,10096=>838,10097=>838,10098=>838,10099=>838,10100=>838,10101=>838,10102=>896,10103=>896,10104=>896,10105=>896,10106=>896,10107=>896,10108=>896,10109=>896,10110=>896,10111=>896,10112=>838,10113=>838,10114=>838,10115=>838,10116=>838,10117=>838,10118=>838,10119=>838,10120=>838,10121=>838,10122=>838,10123=>838,10124=>838,10125=>838,10126=>838,10127=>838,10128=>838,10129=>838,10130=>838,10131=>838,10132=>838,10136=>838,10137=>838,10138=>838,10139=>838,10140=>838,10141=>838,10142=>838,10143=>838,10144=>838,10145=>838,10146=>838,10147=>838,10148=>838,10149=>838,10150=>838,10151=>838,10152=>838,10153=>838,10154=>838,10155=>838,10156=>838,10157=>838,10158=>838,10159=>838,10161=>838,10162=>838,10163=>838,10164=>838,10165=>838,10166=>838,10167=>838,10168=>838,10169=>838,10170=>838,10171=>838,10172=>838,10173=>838,10174=>838,10181=>390,10182=>390,10208=>494,10214=>495,10215=>495,10216=>390,10217=>390,10218=>556,10219=>556,10224=>838,10225=>838,10226=>838,10227=>838,10228=>1157,10229=>1434,10230=>1434,10231=>1434,10232=>1434,10233=>1434,10234=>1434,10235=>1434,10236=>1434,10237=>1434,10238=>1434,10239=>1434,10240=>732,10241=>732,10242=>732,10243=>732,10244=>732,10245=>732,10246=>732,10247=>732,10248=>732,10249=>732,10250=>732,10251=>732,10252=>732,10253=>732,10254=>732,10255=>732,10256=>732,10257=>732,10258=>732,10259=>732,10260=>732,10261=>732,10262=>732,10263=>732,10264=>732,10265=>732,10266=>732,10267=>732,10268=>732,10269=>732,10270=>732,10271=>732,10272=>732,10273=>732,10274=>732,10275=>732,10276=>732,10277=>732,10278=>732,10279=>732,10280=>732,10281=>732,10282=>732,10283=>732,10284=>732,10285=>732,10286=>732,10287=>732,10288=>732,10289=>732,10290=>732,10291=>732,10292=>732,10293=>732,10294=>732,10295=>732,10296=>732,10297=>732,10298=>732,10299=>732,10300=>732,10301=>732,10302=>732,10303=>732,10304=>732,10305=>732,10306=>732,10307=>732,10308=>732,10309=>732,10310=>732,10311=>732,10312=>732,10313=>732,10314=>732,10315=>732,10316=>732,10317=>732,10318=>732,10319=>732,10320=>732,10321=>732,10322=>732,10323=>732,10324=>732,10325=>732,10326=>732,10327=>732,10328=>732,10329=>732,10330=>732,10331=>732,10332=>732,10333=>732,10334=>732,10335=>732,10336=>732,10337=>732,10338=>732,10339=>732,10340=>732,10341=>732,10342=>732,10343=>732,10344=>732,10345=>732,10346=>732,10347=>732,10348=>732,10349=>732,10350=>732,10351=>732,10352=>732,10353=>732,10354=>732,10355=>732,10356=>732,10357=>732,10358=>732,10359=>732,10360=>732,10361=>732,10362=>732,10363=>732,10364=>732,10365=>732,10366=>732,10367=>732,10368=>732,10369=>732,10370=>732,10371=>732,10372=>732,10373=>732,10374=>732,10375=>732,10376=>732,10377=>732,10378=>732,10379=>732,10380=>732,10381=>732,10382=>732,10383=>732,10384=>732,10385=>732,10386=>732,10387=>732,10388=>732,10389=>732,10390=>732,10391=>732,10392=>732,10393=>732,10394=>732,10395=>732,10396=>732,10397=>732,10398=>732,10399=>732,10400=>732,10401=>732,10402=>732,10403=>732,10404=>732,10405=>732,10406=>732,10407=>732,10408=>732,10409=>732,10410=>732,10411=>732,10412=>732,10413=>732,10414=>732,10415=>732,10416=>732,10417=>732,10418=>732,10419=>732,10420=>732,10421=>732,10422=>732,10423=>732,10424=>732,10425=>732,10426=>732,10427=>732,10428=>732,10429=>732,10430=>732,10431=>732,10432=>732,10433=>732,10434=>732,10435=>732,10436=>732,10437=>732,10438=>732,10439=>732,10440=>732,10441=>732,10442=>732,10443=>732,10444=>732,10445=>732,10446=>732,10447=>732,10448=>732,10449=>732,10450=>732,10451=>732,10452=>732,10453=>732,10454=>732,10455=>732,10456=>732,10457=>732,10458=>732,10459=>732,10460=>732,10461=>732,10462=>732,10463=>732,10464=>732,10465=>732,10466=>732,10467=>732,10468=>732,10469=>732,10470=>732,10471=>732,10472=>732,10473=>732,10474=>732,10475=>732,10476=>732,10477=>732,10478=>732,10479=>732,10480=>732,10481=>732,10482=>732,10483=>732,10484=>732,10485=>732,10486=>732,10487=>732,10488=>732,10489=>732,10490=>732,10491=>732,10492=>732,10493=>732,10494=>732,10495=>732,10502=>838,10503=>838,10506=>838,10507=>838,10560=>683,10561=>683,10627=>734,10628=>734,10702=>838,10703=>1000,10704=>1000,10705=>1000,10706=>1000,10707=>1000,10708=>1000,10709=>1000,10731=>494,10746=>838,10747=>838,10752=>1000,10753=>1000,10754=>1000,10764=>1325,10765=>521,10766=>521,10767=>521,10768=>521,10769=>521,10770=>521,10771=>521,10772=>521,10773=>521,10774=>521,10775=>521,10776=>521,10777=>521,10778=>521,10779=>521,10780=>521,10799=>838,10858=>838,10859=>838,10877=>838,10878=>838,10879=>838,10880=>838,10881=>838,10882=>838,10883=>838,10884=>838,10885=>838,10886=>838,10887=>838,10888=>838,10889=>838,10890=>838,10891=>838,10892=>838,10893=>838,10894=>838,10895=>838,10896=>838,10897=>838,10898=>838,10899=>838,10900=>838,10901=>838,10902=>838,10903=>838,10904=>838,10905=>838,10906=>838,10907=>838,10908=>838,10909=>838,10910=>838,10911=>838,10912=>838,10926=>838,10927=>838,10928=>838,10929=>838,10930=>838,10931=>838,10932=>838,10933=>838,10934=>838,10935=>838,10936=>838,10937=>838,10938=>838,11001=>838,11002=>838,11008=>838,11009=>838,11010=>838,11011=>838,11012=>838,11013=>838,11014=>838,11015=>838,11016=>838,11017=>838,11018=>838,11019=>838,11020=>838,11021=>838,11022=>836,11023=>836,11024=>836,11025=>836,11026=>945,11027=>945,11028=>945,11029=>945,11030=>769,11031=>769,11032=>769,11033=>769,11034=>945,11039=>869,11040=>869,11041=>873,11042=>873,11043=>873,11044=>1119,11091=>869,11092=>869,11360=>557,11361=>278,11362=>557,11363=>603,11364=>695,11365=>613,11366=>392,11367=>752,11368=>634,11369=>656,11370=>579,11371=>685,11372=>525,11373=>781,11374=>863,11375=>684,11376=>781,11377=>734,11378=>1128,11379=>961,11380=>592,11381=>654,11382=>568,11383=>660,11385=>414,11386=>612,11387=>491,11388=>175,11389=>431,11390=>635,11391=>685,11520=>591,11521=>595,11522=>564,11523=>602,11524=>587,11525=>911,11526=>626,11527=>952,11528=>595,11529=>607,11530=>954,11531=>620,11532=>595,11533=>926,11534=>595,11535=>806,11536=>931,11537=>584,11538=>592,11539=>923,11540=>953,11541=>828,11542=>596,11543=>595,11544=>590,11545=>592,11546=>592,11547=>621,11548=>920,11549=>589,11550=>586,11551=>581,11552=>914,11553=>596,11554=>595,11555=>592,11556=>642,11557=>901,11800=>531,11807=>838,11810=>390,11811=>390,11812=>390,11813=>390,11822=>531,19904=>896,19905=>896,19906=>896,19907=>896,19908=>896,19909=>896,19910=>896,19911=>896,19912=>896,19913=>896,19914=>896,19915=>896,19916=>896,19917=>896,19918=>896,19919=>896,19920=>896,19921=>896,19922=>896,19923=>896,19924=>896,19925=>896,19926=>896,19927=>896,19928=>896,19929=>896,19930=>896,19931=>896,19932=>896,19933=>896,19934=>896,19935=>896,19936=>896,19937=>896,19938=>896,19939=>896,19940=>896,19941=>896,19942=>896,19943=>896,19944=>896,19945=>896,19946=>896,19947=>896,19948=>896,19949=>896,19950=>896,19951=>896,19952=>896,19953=>896,19954=>896,19955=>896,19956=>896,19957=>896,19958=>896,19959=>896,19960=>896,19961=>896,19962=>896,19963=>896,19964=>896,19965=>896,19966=>896,19967=>896,42192=>686,42193=>603,42194=>603,42195=>770,42196=>611,42197=>611,42198=>775,42199=>656,42200=>656,42201=>512,42202=>698,42203=>703,42204=>685,42205=>575,42206=>575,42207=>863,42208=>748,42209=>557,42210=>635,42211=>695,42212=>695,42213=>684,42214=>684,42215=>752,42216=>775,42217=>512,42218=>989,42219=>685,42220=>611,42221=>686,42222=>684,42223=>684,42224=>632,42225=>632,42226=>295,42227=>787,42228=>732,42229=>732,42230=>557,42231=>767,42232=>300,42233=>300,42234=>596,42235=>596,42236=>300,42237=>300,42238=>588,42239=>588,42564=>635,42565=>521,42566=>354,42567=>338,42572=>1180,42573=>1028,42576=>1029,42577=>906,42580=>1080,42581=>842,42582=>985,42583=>847,42594=>1024,42595=>925,42596=>1014,42597=>900,42598=>863,42599=>1008,42600=>787,42601=>612,42602=>855,42603=>712,42604=>1358,42605=>1019,42606=>879,42634=>805,42635=>722,42636=>611,42637=>583,42644=>686,42645=>634,42760=>493,42761=>493,42762=>493,42763=>493,42764=>493,42765=>493,42766=>493,42767=>493,42768=>493,42769=>493,42770=>493,42771=>493,42772=>493,42773=>493,42774=>493,42779=>369,42780=>369,42781=>252,42782=>252,42783=>252,42786=>385,42787=>356,42788=>472,42789=>472,42790=>752,42791=>634,42792=>878,42793=>709,42794=>614,42795=>541,42800=>491,42801=>521,42802=>1250,42803=>985,42804=>1219,42805=>1000,42806=>1155,42807=>996,42808=>971,42809=>818,42810=>971,42811=>818,42812=>959,42813=>818,42814=>698,42815=>549,42816=>656,42817=>579,42822=>680,42823=>392,42824=>582,42825=>427,42826=>807,42827=>704,42830=>1358,42831=>1019,42832=>603,42833=>635,42834=>734,42835=>774,42838=>787,42839=>635,42852=>605,42853=>635,42854=>605,42855=>635,42880=>557,42881=>278,42882=>735,42883=>634,42889=>337,42890=>376,42891=>401,42892=>275,42893=>686,42894=>487,42896=>772,42897=>667,42912=>775,42913=>635,42914=>656,42915=>579,42916=>748,42917=>634,42918=>695,42919=>411,42920=>635,42921=>521,42922=>872,43002=>915,43003=>575,43004=>603,43005=>863,43006=>295,43007=>1199,61184=>213,61185=>238,61186=>257,61187=>264,61188=>267,61189=>238,61190=>213,61191=>238,61192=>257,61193=>264,61194=>257,61195=>238,61196=>213,61197=>238,61198=>257,61199=>264,61200=>257,61201=>238,61202=>213,61203=>238,61204=>267,61205=>264,61206=>257,61207=>238,61208=>213,61209=>275,62464=>580,62465=>580,62466=>624,62467=>889,62468=>585,62469=>580,62470=>653,62471=>882,62472=>555,62473=>580,62474=>1168,62475=>589,62476=>590,62477=>869,62478=>580,62479=>589,62480=>914,62481=>590,62482=>731,62483=>583,62484=>872,62485=>589,62486=>895,62487=>589,62488=>589,62489=>590,62490=>649,62491=>589,62492=>589,62493=>599,62494=>590,62495=>516,62496=>580,62497=>584,62498=>580,62499=>580,62500=>581,62501=>638,62502=>955,62504=>931,62505=>808,62506=>508,62507=>508,62508=>508,62509=>508,62510=>508,62511=>508,62512=>508,62513=>508,62514=>508,62515=>508,62516=>518,62517=>518,62518=>518,62519=>787,62520=>787,62521=>787,62522=>787,62523=>787,62524=>546,62525=>546,62526=>546,62527=>546,62528=>546,62529=>546,63173=>612,64256=>722,64257=>646,64258=>646,64259=>1000,64260=>1000,64261=>686,64262=>861,64275=>1202,64276=>1202,64277=>1196,64278=>1186,64279=>1529,64285=>224,64286=>0,64287=>471,64288=>636,64289=>856,64290=>774,64291=>906,64292=>771,64293=>843,64294=>855,64295=>807,64296=>875,64297=>838,64298=>708,64299=>708,64300=>708,64301=>708,64302=>668,64303=>668,64304=>668,64305=>578,64306=>412,64307=>546,64308=>653,64309=>272,64310=>346,64311=>1000,64312=>648,64313=>307,64314=>537,64315=>529,64316=>568,64317=>1000,64318=>679,64319=>1000,64320=>400,64321=>649,64322=>1000,64323=>640,64324=>625,64325=>1000,64326=>593,64327=>709,64328=>564,64329=>708,64330=>657,64331=>272,64332=>578,64333=>529,64334=>625,64335=>629,65024=>0,65025=>0,65026=>0,65027=>0,65028=>0,65029=>0,65030=>0,65031=>0,65032=>0,65033=>0,65034=>0,65035=>0,65036=>0,65037=>0,65038=>0,65039=>0,65056=>0,65057=>0,65058=>0,65059=>0,65529=>0,65530=>0,65531=>0,65532=>0,65533=>1025,65535=>600); -// --- EOF --- diff --git a/lib/combodo/tcpdf/fonts/dejavusansi.z b/lib/combodo/tcpdf/fonts/dejavusansi.z deleted file mode 100644 index 6a1b2b825c21e6e8e96b841be9ba6335d2b39580..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 326859 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 emy&$P`>w%0H_dzD*kpZyD#xN|oE diff --git a/lib/combodo/tcpdf/fonts/dejavusansmono.ctg.z b/lib/combodo/tcpdf/fonts/dejavusansmono.ctg.z deleted file mode 100644 index 209e2d50b7425f6576effe463780bc5d4a5e44ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6361 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 UQ9jh;vgW-fabR~j{3X+W03-m54*&oF diff --git a/lib/combodo/tcpdf/fonts/dejavusansmono.php b/lib/combodo/tcpdf/fonts/dejavusansmono.php deleted file mode 100644 index 5e0c537d2..000000000 --- a/lib/combodo/tcpdf/fonts/dejavusansmono.php +++ /dev/null @@ -1,16 +0,0 @@ -33,'FontBBox'=>'[-558 -375 718 1042]','ItalicAngle'=>0,'Ascent'=>928,'Descent'=>-236,'Leading'=>0,'CapHeight'=>729,'XHeight'=>547,'StemV'=>34,'StemH'=>15,'AvgWidth'=>602,'MaxWidth'=>602,'MissingWidth'=>602); -$cbbox=array(0=>array(51,-177,551,705),33=>array(252,0,351,729),34=>array(165,458,437,729),35=>array(1,0,600,718),36=>array(93,-147,544,760),37=>array(16,0,586,699),38=>array(28,-14,596,742),39=>array(258,458,343,729),40=>array(208,-132,432,759),41=>array(170,-132,394,759),42=>array(81,286,521,742),43=>array(43,55,559,572),44=>array(197,-140,368,148),45=>array(174,234,428,314),46=>array(239,0,362,149),47=>array(50,-93,527,729),48=>array(65,-14,537,742),49=>array(120,0,534,729),50=>array(74,0,517,742),51=>array(67,-14,527,742),52=>array(50,0,554,729),53=>array(70,-14,522,729),54=>array(65,-14,537,742),55=>array(68,0,527,729),56=>array(64,-14,538,742),57=>array(62,-14,534,742),58=>array(239,0,362,519),59=>array(197,-140,368,519),60=>array(43,69,559,558),61=>array(43,172,559,454),62=>array(43,69,559,558),63=>array(119,0,508,742),64=>array(13,-156,575,681),65=>array(18,0,584,729),66=>array(81,0,555,729),67=>array(68,-14,524,742),68=>array(67,0,540,729),69=>array(96,0,538,729),70=>array(114,0,543,729),71=>array(50,-14,539,742),72=>array(67,0,535,729),73=>array(98,0,503,729),74=>array(53,-14,467,729),75=>array(67,0,598,729),76=>array(105,0,556,729),77=>array(42,0,559,729),78=>array(68,0,534,729),79=>array(57,-14,545,742),80=>array(96,0,557,729),81=>array(57,-132,545,742),82=>array(70,0,602,729),83=>array(68,-14,536,742),84=>array(23,0,579,729),85=>array(72,-14,530,729),86=>array(28,0,574,729),87=>array(0,0,602,729),88=>array(9,0,593,729),89=>array(18,0,584,729),90=>array(76,0,571,729),91=>array(226,-132,433,760),92=>array(50,-93,527,729),93=>array(169,-132,376,760),94=>array(35,457,567,729),95=>array(0,-236,602,-197),96=>array(136,616,370,800),97=>array(65,-14,517,560),98=>array(94,-14,543,760),99=>array(95,-14,518,560),100=>array(60,-14,509,760),101=>array(60,-14,543,560),102=>array(95,0,519,760),103=>array(60,-215,509,560),104=>array(95,0,513,760),105=>array(87,0,533,760),106=>array(91,-208,383,760),107=>array(115,0,587,760),108=>array(78,0,505,765),109=>array(53,0,554,560),110=>array(95,0,513,560),111=>array(67,-14,535,560),112=>array(93,-208,541,560),113=>array(67,-210,515,558),114=>array(177,0,564,560),115=>array(104,-14,503,560),116=>array(64,0,504,702),117=>array(95,-14,513,546),118=>array(49,0,553,547),119=>array(0,0,602,547),120=>array(37,0,565,547),121=>array(51,-208,563,547),122=>array(99,0,508,548),123=>array(108,-163,494,760),124=>array(259,-236,343,764),125=>array(108,-163,494,760),126=>array(43,240,559,381),161=>array(252,0,351,729),162=>array(104,-153,518,699),163=>array(68,0,543,742),164=>array(100,95,537,532),165=>array(18,0,584,729),166=>array(259,-171,343,699),167=>array(97,-95,506,742),168=>array(156,659,446,758),169=>array(0,61,602,663),170=>array(132,229,469,742),171=>array(58,69,509,517),172=>array(43,181,559,421),173=>array(174,234,428,314),174=>array(0,61,602,663),175=>array(155,673,447,745),176=>array(146,432,456,742),177=>array(43,0,559,572),178=>array(157,326,436,742),179=>array(159,319,451,742),180=>array(232,616,466,800),181=>array(95,-209,577,547),182=>array(52,-96,503,729),183=>array(239,273,362,422),184=>array(193,-193,395,0),185=>array(168,326,447,734),186=>array(119,229,483,742),187=>array(94,69,545,517),188=>array(13,-132,544,810),189=>array(13,-132,544,810),190=>array(13,-132,544,818),191=>array(94,-13,483,729),192=>array(18,0,584,927),193=>array(18,0,584,927),194=>array(18,0,584,928),195=>array(18,0,584,921),196=>array(18,0,584,913),197=>array(18,0,584,928),198=>array(0,0,576,729),199=>array(68,-193,524,742),200=>array(96,0,538,927),201=>array(96,0,538,927),202=>array(96,0,538,928),203=>array(96,0,538,913),204=>array(98,0,503,927),205=>array(98,0,503,927),206=>array(98,0,503,928),207=>array(98,0,503,913),208=>array(4,0,538,729),209=>array(68,0,534,923),210=>array(57,-14,545,927),211=>array(57,-14,545,927),212=>array(57,-14,545,928),213=>array(57,-14,545,921),214=>array(57,-14,545,913),215=>array(73,85,529,541),216=>array(4,-34,586,761),217=>array(72,-14,530,927),218=>array(72,-14,530,927),219=>array(72,-14,530,928),220=>array(72,-14,530,913),221=>array(18,0,584,927),222=>array(98,0,569,729),223=>array(92,-14,561,760),224=>array(65,-14,517,800),225=>array(65,-14,517,800),226=>array(65,-14,517,800),227=>array(65,-14,517,777),228=>array(65,-14,517,758),229=>array(65,-14,517,878),230=>array(20,-14,586,560),231=>array(95,-193,518,560),232=>array(60,-14,543,800),233=>array(60,-14,543,800),234=>array(60,-14,543,800),235=>array(60,-14,543,758),236=>array(87,0,533,800),237=>array(87,0,533,800),238=>array(87,0,533,800),239=>array(87,0,533,758),240=>array(67,-14,535,760),241=>array(95,0,513,777),242=>array(67,-14,535,800),243=>array(67,-14,535,800),244=>array(67,-14,535,800),245=>array(67,-14,535,777),246=>array(67,-14,535,758),247=>array(43,73,559,554),248=>array(23,-47,573,592),249=>array(95,-14,513,800),250=>array(95,-14,513,800),251=>array(95,-14,513,800),252=>array(95,-14,513,758),253=>array(51,-208,563,800),254=>array(93,-208,541,765),255=>array(51,-208,563,758),256=>array(18,0,584,898),257=>array(65,-14,517,745),258=>array(18,0,584,928),259=>array(65,-14,517,785),260=>array(18,-193,609,729),261=>array(65,-193,556,560),262=>array(68,-14,524,927),263=>array(95,-14,518,800),264=>array(68,-14,524,932),265=>array(95,-14,518,800),266=>array(68,-14,524,914),267=>array(95,-14,518,758),268=>array(68,-14,524,928),269=>array(95,-14,518,800),270=>array(67,0,540,925),271=>array(60,-14,641,760),272=>array(4,0,538,729),273=>array(60,-14,602,760),274=>array(96,0,538,898),275=>array(60,-14,543,745),276=>array(96,0,538,928),277=>array(60,-14,543,785),278=>array(96,0,538,914),279=>array(60,-14,543,758),280=>array(96,-193,538,729),281=>array(60,-193,543,560),282=>array(96,0,538,925),283=>array(60,-14,543,797),284=>array(50,-14,539,928),285=>array(60,-215,509,800),286=>array(50,-14,539,928),287=>array(60,-215,509,785),288=>array(50,-14,539,914),289=>array(60,-215,509,758),290=>array(50,-280,539,742),291=>array(60,-215,509,788),292=>array(67,0,535,928),293=>array(95,0,513,928),294=>array(1,0,601,729),295=>array(34,0,513,760),296=>array(98,0,503,921),297=>array(87,0,533,777),298=>array(98,0,503,898),299=>array(87,0,533,745),300=>array(98,0,503,928),301=>array(87,0,533,785),302=>array(98,-193,503,729),303=>array(87,-193,533,760),304=>array(98,0,503,914),305=>array(87,0,533,547),306=>array(-0,-13,600,730),307=>array(-2,-213,567,760),308=>array(53,-14,474,928),309=>array(91,-208,457,800),310=>array(67,-266,598,729),311=>array(115,-266,587,760),312=>array(115,0,587,547),313=>array(98,0,556,928),314=>array(78,0,505,928),315=>array(105,-266,556,729),316=>array(78,-266,505,765),317=>array(105,0,556,729),318=>array(78,0,565,765),319=>array(105,0,556,729),320=>array(78,0,592,765),321=>array(-5,0,556,729),322=>array(37,0,505,765),323=>array(68,0,534,927),324=>array(95,0,513,803),325=>array(68,-266,534,729),326=>array(95,-266,513,560),327=>array(68,0,534,928),328=>array(95,0,513,800),329=>array(12,0,573,760),330=>array(72,-208,530,743),331=>array(95,-208,513,560),332=>array(57,-14,545,898),333=>array(67,-14,535,745),334=>array(57,-14,545,928),335=>array(67,-14,535,785),336=>array(57,-14,545,927),337=>array(67,-14,535,800),338=>array(35,0,594,729),339=>array(7,-14,591,560),340=>array(70,0,602,927),341=>array(177,0,566,803),342=>array(70,-266,602,729),343=>array(141,-266,564,560),344=>array(70,0,602,925),345=>array(177,0,564,800),346=>array(68,-14,536,927),347=>array(104,-14,503,803),348=>array(68,-14,536,928),349=>array(104,-14,503,800),350=>array(68,-193,536,742),351=>array(104,-193,503,560),352=>array(68,-14,536,928),353=>array(104,-14,503,800),354=>array(23,-193,579,729),355=>array(64,-193,504,702),356=>array(23,0,579,928),357=>array(64,0,504,812),358=>array(23,0,579,729),359=>array(64,0,504,702),360=>array(72,-14,530,921),361=>array(95,-14,513,777),362=>array(72,-14,530,898),363=>array(95,-14,513,745),364=>array(72,-14,530,928),365=>array(95,-14,513,785),366=>array(72,-14,530,1042),367=>array(95,-14,513,856),368=>array(72,-14,530,927),369=>array(95,-14,513,800),370=>array(72,-201,530,729),371=>array(95,-193,586,546),372=>array(0,0,602,932),373=>array(0,0,602,803),374=>array(18,0,584,932),375=>array(51,-208,563,803),376=>array(18,0,584,913),377=>array(76,0,571,927),378=>array(99,0,508,803),379=>array(76,0,571,914),380=>array(99,0,508,758),381=>array(76,0,571,928),382=>array(99,0,508,800),383=>array(95,0,519,760),384=>array(34,-14,543,760),385=>array(10,0,581,729),386=>array(81,0,555,729),387=>array(94,-14,543,760),388=>array(23,0,579,729),389=>array(29,-14,572,760),390=>array(68,-14,524,742),391=>array(29,-14,573,800),392=>array(46,-14,556,694),393=>array(4,0,538,729),394=>array(4,0,598,729),395=>array(64,0,538,729),396=>array(77,-14,525,760),397=>array(66,-220,535,560),398=>array(96,0,538,729),399=>array(57,-14,545,742),400=>array(67,-14,527,742),401=>array(31,-208,571,729),402=>array(95,-208,519,760),403=>array(25,-14,577,800),404=>array(14,-210,589,661),405=>array(32,0,570,760),406=>array(98,0,528,729),407=>array(98,0,503,729),408=>array(54,0,595,729),409=>array(115,0,587,760),410=>array(78,0,505,765),411=>array(24,0,553,729),412=>array(53,-13,554,729),413=>array(14,-208,512,729),414=>array(95,-210,513,560),415=>array(57,-14,545,742),416=>array(3,-14,582,760),417=>array(16,-14,587,560),418=>array(22,-14,580,742),419=>array(42,-210,583,560),420=>array(27,0,575,729),421=>array(93,-208,541,699),422=>array(70,-129,602,729),423=>array(68,-14,536,742),424=>array(104,-14,503,560),425=>array(59,0,553,729),426=>array(58,-208,544,760),427=>array(64,-208,504,702),428=>array(23,0,579,729),429=>array(64,0,504,760),430=>array(23,-208,579,729),431=>array(4,-14,598,762),432=>array(19,-14,583,555),433=>array(36,0,566,713),434=>array(75,0,521,729),435=>array(8,0,594,730),436=>array(12,-208,598,553),437=>array(76,0,571,729),438=>array(76,0,526,548),439=>array(13,-14,589,729),440=>array(13,-14,589,729),441=>array(61,-213,541,547),442=>array(84,-208,518,547),443=>array(74,0,517,742),444=>array(13,-14,589,729),445=>array(61,-213,541,547),446=>array(95,-14,507,702),447=>array(61,-208,550,560),448=>array(251,0,351,729),449=>array(153,0,449,729),450=>array(80,0,522,729),451=>array(251,0,351,729),461=>array(18,0,584,928),462=>array(65,-14,517,800),463=>array(98,0,503,928),464=>array(87,0,533,800),465=>array(57,-14,545,928),466=>array(67,-14,535,800),467=>array(72,-14,530,928),468=>array(95,-14,513,800),469=>array(72,-14,530,953),470=>array(95,-14,513,899),471=>array(72,-14,530,997),472=>array(95,-14,513,954),473=>array(72,-14,530,998),474=>array(95,-14,513,954),475=>array(72,-14,530,997),476=>array(95,-14,513,954),477=>array(60,-14,542,560),478=>array(18,0,584,953),479=>array(65,-14,517,899),480=>array(18,0,584,953),481=>array(65,-14,517,899),482=>array(0,0,576,898),483=>array(20,-14,586,745),486=>array(50,-14,539,928),487=>array(60,-215,509,800),488=>array(67,0,598,928),489=>array(115,0,587,928),490=>array(57,-201,545,742),491=>array(67,-201,535,560),492=>array(57,-201,545,898),493=>array(67,-201,535,745),494=>array(13,-14,589,928),495=>array(61,-213,541,800),496=>array(91,-208,474,797),500=>array(50,-14,539,927),501=>array(60,-215,509,800),502=>array(30,-14,572,729),504=>array(68,0,534,927),505=>array(95,0,513,800),508=>array(0,0,576,927),509=>array(20,-14,586,800),510=>array(4,-34,586,927),511=>array(23,-47,573,800),512=>array(18,0,584,927),513=>array(65,-14,517,800),514=>array(18,0,584,928),515=>array(65,-14,517,785),516=>array(91,0,538,927),517=>array(60,-14,543,800),518=>array(96,0,538,928),519=>array(60,-14,543,785),520=>array(91,0,503,927),521=>array(87,0,533,800),522=>array(98,0,503,928),523=>array(87,0,533,785),524=>array(57,-14,545,927),525=>array(67,-14,535,800),526=>array(57,-14,545,928),527=>array(67,-14,535,785),528=>array(67,0,602,927),529=>array(176,0,564,800),530=>array(70,0,602,928),531=>array(177,0,564,785),532=>array(72,-14,530,927),533=>array(95,-14,513,800),534=>array(72,-14,530,928),535=>array(95,-14,513,785),536=>array(68,-265,536,742),537=>array(104,-265,503,560),538=>array(23,-265,579,729),539=>array(64,-265,504,702),540=>array(61,-210,541,742),541=>array(85,-211,517,560),542=>array(67,0,535,928),543=>array(95,0,513,928),544=>array(72,-210,530,743),545=>array(9,-72,578,760),548=>array(76,-208,571,729),549=>array(99,-208,508,548),550=>array(18,0,584,914),551=>array(65,-14,517,758),552=>array(96,-193,538,729),553=>array(60,-193,543,560),554=>array(57,-14,545,953),555=>array(67,-14,535,899),556=>array(57,-14,545,953),557=>array(67,-14,535,899),558=>array(57,-14,545,914),559=>array(67,-14,535,758),560=>array(57,-14,545,953),561=>array(67,-14,535,899),562=>array(18,0,584,898),563=>array(51,-208,563,745),564=>array(78,-72,505,765),565=>array(52,-72,550,560),566=>array(64,-72,504,702),567=>array(91,-208,383,547),568=>array(59,-14,543,760),569=>array(59,-214,543,560),570=>array(4,-34,586,761),571=>array(4,-34,586,761),572=>array(23,-47,573,592),573=>array(10,0,592,729),574=>array(16,-34,598,761),575=>array(104,-242,512,560),576=>array(99,-242,508,548),577=>array(27,0,575,729),579=>array(4,0,555,729),580=>array(10,-14,592,729),581=>array(28,0,574,729),588=>array(10,0,602,729),589=>array(69,0,564,560),592=>array(75,-14,527,560),593=>array(60,-14,509,560),594=>array(94,-15,542,559),595=>array(94,-14,543,760),596=>array(90,-14,513,560),597=>array(95,-69,528,560),598=>array(60,-208,527,760),599=>array(60,-14,527,760),600=>array(60,-14,542,560),601=>array(60,-14,542,560),602=>array(15,-14,587,560),603=>array(83,-11,520,560),604=>array(83,-11,520,560),605=>array(27,-11,575,560),606=>array(86,-21,517,559),607=>array(91,-208,555,546),608=>array(60,-215,525,760),609=>array(77,-215,525,546),610=>array(60,0,543,574),611=>array(50,-210,552,546),612=>array(50,0,552,546),613=>array(92,-210,510,546),614=>array(95,0,513,760),615=>array(95,-208,513,760),616=>array(69,0,524,760),617=>array(97,0,505,546),618=>array(78,0,524,546),619=>array(43,0,559,765),620=>array(77,0,525,765),621=>array(78,-208,505,765),622=>array(20,-213,582,765),623=>array(51,0,552,560),624=>array(51,-210,552,560),625=>array(50,-208,551,560),626=>array(87,-208,538,560),627=>array(66,-208,515,560),628=>array(70,0,532,560),629=>array(67,-14,535,560),630=>array(34,0,568,547),631=>array(83,-15,519,560),632=>array(67,-208,535,759),633=>array(74,-13,461,546),634=>array(74,-13,461,765),635=>array(50,-208,563,546),636=>array(177,-208,564,560),637=>array(177,-208,564,560),638=>array(78,0,524,560),639=>array(78,0,524,560),640=>array(60,0,542,546),641=>array(60,0,542,546),642=>array(92,-208,510,560),643=>array(61,-208,541,760),644=>array(61,-208,541,760),645=>array(61,-208,541,546),646=>array(58,-208,544,760),647=>array(81,-155,521,547),648=>array(64,-208,504,702),649=>array(0,-14,602,547),650=>array(46,-15,556,547),651=>array(32,0,558,547),652=>array(35,0,567,547),653=>array(7,0,595,547),654=>array(35,0,567,755),655=>array(50,0,552,561),656=>array(95,-208,507,547),657=>array(82,-54,521,547),658=>array(61,-213,541,547),659=>array(51,-213,551,547),660=>array(95,0,507,759),661=>array(95,0,507,759),662=>array(95,0,507,759),663=>array(95,-214,507,759),664=>array(46,22,556,532),665=>array(102,0,500,561),666=>array(86,-21,517,559),667=>array(26,0,553,759),668=>array(70,0,532,560),669=>array(99,-208,503,760),670=>array(58,-213,544,547),671=>array(120,0,482,560),672=>array(17,-208,561,759),673=>array(95,0,507,759),674=>array(95,0,507,759),675=>array(14,-14,575,760),676=>array(13,-213,588,760),677=>array(26,-54,575,760),678=>array(75,-14,527,702),679=>array(75,-208,525,760),680=>array(88,-70,509,702),681=>array(66,-208,535,760),682=>array(112,-14,490,760),683=>array(107,0,494,760),684=>array(70,-15,532,641),685=>array(70,84,532,640),686=>array(87,-214,515,760),687=>array(96,-208,506,760),688=>array(157,326,445,752),689=>array(157,325,445,751),690=>array(237,209,365,752),691=>array(200,326,402,640),692=>array(200,318,402,633),693=>array(165,209,438,633),694=>array(148,326,454,633),695=>array(70,326,532,633),696=>array(133,209,469,633),697=>array(240,557,365,800),699=>array(226,472,397,760),700=>array(226,472,397,760),701=>array(242,595,360,844),702=>array(234,492,368,760),703=>array(234,492,368,760),704=>array(171,444,431,870),705=>array(171,444,431,870),710=>array(145,616,457,800),711=>array(145,616,457,800),712=>array(268,488,334,759),713=>array(155,673,447,745),716=>array(268,-148,334,123),717=>array(155,-174,447,-102),718=>array(184,-285,418,-102),719=>array(184,-285,418,-102),720=>array(214,0,388,517),721=>array(214,355,388,517),722=>array(234,249,368,517),723=>array(234,249,368,517),726=>array(155,125,447,417),727=>array(191,234,411,307),728=>array(148,645,454,785),729=>array(250,658,351,758),730=>array(167,610,435,878),731=>array(205,-193,387,0),732=>array(140,639,462,777),733=>array(168,616,511,800),734=>array(-171,233,431,504),736=>array(143,208,459,632),737=>array(167,326,436,755),738=>array(169,326,433,648),739=>array(134,326,468,632),740=>array(171,326,431,751),741=>array(146,0,456,668),742=>array(146,0,456,668),743=>array(146,0,456,668),744=>array(146,0,456,668),745=>array(146,0,456,668),750=>array(103,472,498,760),755=>array(194,-245,408,-31),768=>array(136,616,370,800),769=>array(232,616,466,800),770=>array(145,616,457,800),771=>array(140,639,462,777),772=>array(155,673,447,745),773=>array(0,716,602,755),774=>array(148,645,454,785),775=>array(250,658,351,758),776=>array(156,659,446,758),777=>array(200,618,402,847),778=>array(167,610,435,878),779=>array(168,616,511,800),780=>array(145,616,457,800),781=>array(267,616,333,833),782=>array(167,616,433,833),783=>array(103,616,445,800),784=>array(148,645,454,857),785=>array(148,645,454,785),786=>array(229,472,392,641),787=>array(242,595,360,844),788=>array(242,595,360,844),789=>array(232,616,362,800),790=>array(184,-285,418,-102),791=>array(184,-285,418,-102),792=>array(201,-375,354,-135),793=>array(225,-375,377,-135),794=>array(181,690,421,930),795=>array(205,373,397,555),796=>array(247,-245,354,-31),797=>array(173,-288,412,-135),798=>array(171,-288,410,-135),799=>array(171,-375,411,-135),800=>array(181,-202,421,-135),801=>array(245,-208,513,63),802=>array(89,-208,357,63),803=>array(250,-202,351,-102),804=>array(156,-201,446,-103),805=>array(194,-245,408,-31),806=>array(199,-265,362,-96),807=>array(193,-193,395,0),808=>array(210,-193,392,0),809=>array(268,-319,334,-102),810=>array(167,-263,436,-102),811=>array(101,-222,501,-82),812=>array(145,-237,457,-53),813=>array(145,-237,457,-53),814=>array(148,-238,454,-98),815=>array(148,-237,454,-97),816=>array(140,-237,462,-99),817=>array(155,-174,447,-102),818=>array(0,-236,602,-197),819=>array(0,-236,602,-80),820=>array(43,240,559,381),821=>array(69,221,519,301),822=>array(0,221,602,301),823=>array(23,-47,573,592),824=>array(4,-34,586,761),825=>array(247,-245,354,-31),826=>array(167,-188,436,-26),827=>array(167,-371,436,-102),828=>array(101,-222,501,-82),829=>array(193,599,409,816),830=>array(232,595,370,853),831=>array(0,599,602,755),835=>array(242,595,360,844),856=>array(501,658,601,758),865=>array(-116,742,718,902),884=>array(240,557,365,800),885=>array(237,-208,362,35),890=>array(265,-208,372,-45),894=>array(197,-140,368,519),900=>array(232,616,466,800),901=>array(156,659,466,980),902=>array(12,0,584,800),903=>array(239,273,362,422),904=>array(-110,0,538,800),905=>array(-134,0,535,800),906=>array(-110,0,503,800),908=>array(-37,-14,545,800),910=>array(-195,0,584,800),911=>array(-24,0,566,800),912=>array(151,0,476,980),913=>array(18,0,584,729),914=>array(81,0,555,729),915=>array(105,0,556,729),916=>array(18,0,584,729),917=>array(96,0,538,729),918=>array(76,0,571,729),919=>array(67,0,535,729),920=>array(57,-14,545,742),921=>array(98,0,503,729),922=>array(67,0,598,729),923=>array(18,0,584,729),924=>array(42,0,559,729),925=>array(68,0,534,729),926=>array(67,0,535,729),927=>array(57,-14,545,742),928=>array(67,0,535,729),929=>array(96,0,557,729),931=>array(59,0,553,729),932=>array(23,0,579,729),933=>array(18,0,584,729),934=>array(57,0,544,729),935=>array(9,0,593,729),936=>array(57,0,544,729),937=>array(36,0,566,713),938=>array(98,0,503,913),939=>array(18,0,584,913),940=>array(34,-12,573,800),941=>array(83,-11,520,800),942=>array(95,-208,513,800),943=>array(151,0,476,800),944=>array(25,0,551,980),945=>array(34,-12,573,559),946=>array(74,-208,547,766),947=>array(16,-208,553,547),948=>array(67,-14,535,767),949=>array(83,-11,520,560),950=>array(75,-210,519,760),951=>array(95,-208,513,560),952=>array(67,-14,535,732),953=>array(151,0,476,547),954=>array(115,0,587,547),955=>array(33,0,565,760),956=>array(95,-209,577,547),957=>array(57,0,532,547),958=>array(79,-210,527,760),959=>array(67,-14,535,560),960=>array(39,-19,577,547),961=>array(93,-208,541,560),962=>array(95,-210,518,560),963=>array(67,-14,552,547),964=>array(78,0,524,546),965=>array(25,0,551,547),966=>array(37,-208,565,551),967=>array(43,-208,559,547),968=>array(64,-208,538,547),969=>array(34,-14,568,547),970=>array(151,0,476,758),971=>array(25,0,551,758),972=>array(67,-14,535,800),973=>array(25,0,551,800),974=>array(34,-14,568,800),976=>array(73,-11,501,768),977=>array(57,-11,540,768),978=>array(17,0,582,729),979=>array(-195,0,582,800),980=>array(17,0,582,913),981=>array(53,-208,549,729),982=>array(28,0,574,547),983=>array(25,-188,571,547),984=>array(57,-208,545,742),985=>array(67,-208,535,560),986=>array(68,-210,537,729),987=>array(76,-210,520,547),988=>array(114,0,543,729),989=>array(0,-208,503,760),990=>array(47,-2,563,729),991=>array(64,0,538,759),992=>array(16,-208,575,742),993=>array(43,-180,559,559),1008=>array(25,-7,571,550),1009=>array(93,-208,541,560),1010=>array(95,-14,518,560),1011=>array(91,-208,383,760),1012=>array(57,-14,545,742),1013=>array(79,-14,504,560),1014=>array(79,-14,504,560),1015=>array(98,0,569,729),1016=>array(93,-208,541,765),1017=>array(68,-14,524,742),1018=>array(42,0,559,729),1019=>array(62,-208,539,547),1020=>array(42,-208,541,560),1021=>array(68,-14,524,742),1022=>array(68,-14,524,742),1023=>array(68,-14,524,742),1024=>array(96,0,538,927),1025=>array(96,0,538,913),1026=>array(-32,-229,554,730),1027=>array(105,0,556,927),1028=>array(68,-14,524,742),1029=>array(68,-14,536,742),1030=>array(98,0,503,729),1031=>array(98,0,503,913),1032=>array(53,-14,467,729),1033=>array(-9,0,597,729),1034=>array(17,0,597,729),1035=>array(-32,0,554,730),1036=>array(67,0,598,927),1037=>array(68,0,534,927),1038=>array(51,0,563,928),1039=>array(67,-157,535,729),1040=>array(18,0,584,729),1041=>array(81,0,555,729),1042=>array(81,0,555,729),1043=>array(105,0,556,729),1044=>array(16,-157,586,729),1045=>array(96,0,538,729),1046=>array(7,0,595,729),1047=>array(67,-14,527,742),1048=>array(68,0,534,729),1049=>array(68,0,534,928),1050=>array(67,0,598,729),1051=>array(2,0,534,729),1052=>array(42,0,559,729),1053=>array(67,0,535,729),1054=>array(57,-14,545,742),1055=>array(67,0,535,729),1056=>array(96,0,557,729),1057=>array(68,-14,524,742),1058=>array(23,0,579,729),1059=>array(51,0,563,729),1060=>array(32,0,570,729),1061=>array(9,0,593,729),1062=>array(39,-157,573,729),1063=>array(67,0,533,729),1064=>array(56,0,547,729),1065=>array(29,-157,586,729),1066=>array(16,0,557,729),1067=>array(32,0,554,729),1068=>array(96,0,557,729),1069=>array(68,-14,524,742),1070=>array(29,-14,573,742),1071=>array(37,0,553,729),1072=>array(65,-14,517,560),1073=>array(61,-14,535,777),1074=>array(102,0,500,547),1075=>array(125,0,493,547),1076=>array(51,-140,551,547),1077=>array(60,-14,543,560),1078=>array(29,0,574,547),1079=>array(83,-11,520,560),1080=>array(95,0,513,547),1081=>array(95,0,513,785),1082=>array(115,0,587,547),1083=>array(15,0,513,547),1084=>array(30,0,576,547),1085=>array(95,0,513,547),1086=>array(67,-14,535,560),1087=>array(95,0,513,547),1088=>array(93,-208,541,560),1089=>array(95,-14,518,560),1090=>array(110,0,503,547),1091=>array(51,-208,563,547),1092=>array(48,-208,549,760),1093=>array(37,0,565,547),1094=>array(61,-140,546,547),1095=>array(95,0,513,548),1096=>array(61,0,542,547),1097=>array(39,-140,590,547),1098=>array(15,0,568,547),1099=>array(51,0,551,547),1100=>array(95,0,527,547),1101=>array(95,-14,518,560),1102=>array(38,-14,570,560),1103=>array(82,0,480,547),1104=>array(60,-14,543,803),1105=>array(60,-14,543,718),1106=>array(17,-208,541,760),1107=>array(125,0,505,803),1108=>array(95,-14,518,560),1109=>array(104,-14,503,560),1110=>array(87,0,533,760),1111=>array(87,0,533,758),1112=>array(91,-208,383,760),1113=>array(5,0,599,547),1114=>array(32,0,577,547),1115=>array(17,0,528,760),1116=>array(115,0,587,803),1117=>array(95,0,513,803),1118=>array(51,-208,563,785),1119=>array(95,-140,513,547),1122=>array(16,0,557,729),1123=>array(15,0,568,760),1138=>array(57,-14,545,742),1139=>array(67,-14,535,560),1168=>array(105,0,556,878),1169=>array(125,0,493,700),1170=>array(42,0,556,729),1171=>array(62,0,493,547),1172=>array(105,-200,556,729),1173=>array(125,-208,540,547),1174=>array(7,-157,595,729),1175=>array(29,-140,585,547),1176=>array(67,-193,527,742),1177=>array(83,-193,520,560),1178=>array(67,-157,598,729),1179=>array(115,-140,587,547),1186=>array(15,-157,587,729),1187=>array(48,-140,561,547),1188=>array(55,0,590,729),1189=>array(61,0,585,547),1194=>array(68,-193,524,742),1195=>array(95,-193,518,560),1196=>array(23,-157,579,729),1197=>array(110,-140,503,547),1198=>array(18,0,584,729),1199=>array(45,-208,557,547),1200=>array(18,0,584,729),1201=>array(45,-208,557,547),1202=>array(9,-157,593,729),1203=>array(37,-140,565,547),1210=>array(68,0,535,730),1211=>array(95,0,513,760),1216=>array(98,0,503,729),1217=>array(7,0,595,928),1218=>array(29,0,574,785),1219=>array(67,-200,590,729),1220=>array(115,-208,553,547),1223=>array(67,-200,535,729),1224=>array(95,-208,513,547),1227=>array(68,-157,535,730),1228=>array(95,-140,513,548),1231=>array(222,0,312,765),1232=>array(18,0,584,928),1233=>array(65,-14,517,785),1234=>array(18,0,584,913),1235=>array(65,-14,517,758),1236=>array(0,0,576,729),1237=>array(20,-14,586,560),1238=>array(96,0,538,928),1239=>array(60,-14,543,785),1240=>array(57,-14,545,742),1241=>array(60,-14,542,560),1242=>array(57,-14,545,913),1243=>array(60,-14,542,758),1244=>array(7,0,595,913),1245=>array(29,0,574,758),1246=>array(67,-14,527,913),1247=>array(83,-11,520,758),1248=>array(13,-14,589,729),1249=>array(61,-213,541,547),1250=>array(68,0,534,898),1251=>array(95,0,513,745),1252=>array(68,0,534,913),1253=>array(95,0,513,758),1254=>array(57,-14,545,913),1255=>array(67,-14,535,758),1256=>array(57,-14,545,742),1257=>array(67,-14,535,560),1258=>array(57,-14,545,913),1259=>array(67,-14,535,758),1260=>array(68,-14,524,913),1261=>array(95,-14,518,758),1262=>array(51,0,563,898),1263=>array(51,-208,563,745),1264=>array(51,0,563,913),1265=>array(51,-208,563,758),1266=>array(51,0,563,927),1267=>array(51,-208,563,800),1268=>array(67,0,533,913),1269=>array(95,0,513,758),1270=>array(105,-157,556,729),1271=>array(125,-140,493,547),1272=>array(32,0,554,913),1273=>array(51,0,551,758),1296=>array(67,-14,527,742),1297=>array(83,-11,520,560),1306=>array(57,-132,545,742),1307=>array(67,-210,515,558),1308=>array(0,0,602,729),1309=>array(0,0,602,547),1329=>array(58,-29,544,729),1330=>array(63,0,539,742),1331=>array(42,0,561,742),1332=>array(26,0,576,742),1333=>array(63,-14,539,729),1334=>array(47,0,555,742),1335=>array(59,0,543,729),1336=>array(63,0,539,743),1337=>array(21,-14,581,742),1338=>array(42,-14,561,729),1339=>array(72,0,530,729),1340=>array(75,0,526,729),1341=>array(45,-14,557,729),1342=>array(26,-14,575,742),1343=>array(72,0,530,729),1344=>array(44,-26,558,729),1345=>array(46,-23,556,742),1346=>array(26,0,576,742),1347=>array(42,0,560,742),1348=>array(26,-14,576,729),1349=>array(31,-14,571,742),1350=>array(26,-14,576,729),1351=>array(47,-14,555,729),1352=>array(72,0,530,743),1353=>array(47,-28,555,742),1354=>array(32,0,570,742),1355=>array(47,0,555,742),1356=>array(26,0,576,742),1357=>array(72,-14,530,729),1358=>array(16,0,585,729),1359=>array(51,-14,550,742),1360=>array(72,0,530,743),1361=>array(31,-14,571,742),1362=>array(66,0,536,729),1363=>array(34,0,567,729),1364=>array(25,0,577,742),1365=>array(57,-14,545,742),1366=>array(35,-14,567,729),1369=>array(234,492,368,760),1370=>array(229,499,373,729),1371=>array(185,620,418,803),1372=>array(110,618,492,893),1373=>array(184,616,418,800),1374=>array(87,613,515,885),1375=>array(92,618,510,760),1377=>array(50,-13,551,547),1378=>array(89,-208,512,560),1379=>array(36,-208,566,558),1380=>array(56,-208,546,560),1381=>array(80,-14,522,760),1382=>array(36,-208,566,558),1383=>array(101,0,500,760),1384=>array(89,-208,512,560),1385=>array(32,-208,569,560),1386=>array(36,-14,566,760),1387=>array(92,-208,510,760),1388=>array(160,-208,442,547),1389=>array(51,-208,551,760),1390=>array(67,-14,535,771),1391=>array(92,-208,510,760),1392=>array(92,0,510,760),1393=>array(83,-15,518,760),1394=>array(56,-208,546,560),1395=>array(78,-14,524,760),1396=>array(51,-14,551,760),1397=>array(155,-208,447,547),1398=>array(51,-14,551,760),1399=>array(84,-208,517,561),1400=>array(92,0,510,560),1401=>array(118,-208,483,571),1402=>array(50,-208,551,547),1403=>array(82,-208,520,561),1404=>array(64,0,538,560),1405=>array(92,-14,510,546),1406=>array(50,-208,552,760),1407=>array(51,-13,551,560),1408=>array(92,-208,510,560),1409=>array(77,-215,525,560),1410=>array(122,0,480,547),1411=>array(51,-208,551,760),1412=>array(42,-208,560,560),1413=>array(67,-14,535,560),1414=>array(20,-208,582,760),1415=>array(35,-14,566,760),1417=>array(250,0,353,415),1418=>array(174,205,428,314),1542=>array(24,-19,573,892),1543=>array(24,-19,573,895),1545=>array(44,0,558,635),1546=>array(0,0,602,635),1548=>array(229,0,373,240),1557=>array(174,624,428,868),1563=>array(229,0,373,633),1567=>array(106,0,496,742),1569=>array(212,42,522,483),1570=>array(125,0,477,939),1571=>array(217,0,385,999),1572=>array(37,-244,525,588),1573=>array(217,-244,385,760),1574=>array(12,-131,602,544),1575=>array(256,0,346,760),1576=>array(34,-152,586,263),1577=>array(108,-28,494,513),1578=>array(34,-10,586,391),1579=>array(34,-10,586,513),1580=>array(43,-244,584,425),1581=>array(43,-244,584,425),1582=>array(43,-244,584,586),1583=>array(113,-19,488,427),1584=>array(113,-19,488,598),1585=>array(-25,-246,533,267),1586=>array(-25,-246,533,464),1587=>array(-107,-240,574,366),1588=>array(-107,-240,574,586),1589=>array(-117,-240,594,320),1590=>array(-117,-240,594,413),1591=>array(5,0,580,760),1592=>array(5,0,580,760),1593=>array(60,-244,589,521),1594=>array(60,-244,589,659),1600=>array(-10,0,612,90),1601=>array(-36,-45,568,600),1602=>array(15,-189,557,635),1603=>array(4,-27,578,760),1604=>array(33,-152,537,760),1605=>array(63,-240,541,369),1606=>array(26,-162,569,422),1607=>array(108,-28,494,358),1608=>array(37,-244,525,315),1609=>array(12,-131,602,389),1610=>array(12,-244,602,389),1611=>array(158,591,443,825),1612=>array(158,591,443,874),1613=>array(158,-239,443,-5),1614=>array(158,591,443,708),1615=>array(158,590,443,874),1616=>array(158,-137,443,-20),1617=>array(148,599,453,869),1618=>array(167,610,435,878),1619=>array(125,590,477,719),1620=>array(217,593,385,808),1621=>array(217,-244,385,-29),1626=>array(170,616,433,775),1632=>array(247,220,354,342),1633=>array(198,0,404,635),1634=>array(75,0,527,635),1635=>array(65,0,537,635),1636=>array(115,-10,486,641),1637=>array(99,-10,504,643),1638=>array(75,0,527,635),1639=>array(62,0,540,635),1640=>array(62,0,540,635),1641=>array(79,0,523,640),1642=>array(98,0,505,635),1643=>array(151,-110,451,318),1644=>array(229,499,373,729),1645=>array(71,101,531,537),1652=>array(217,649,385,864),1657=>array(34,-10,586,575),1658=>array(34,-10,586,513),1659=>array(34,-244,586,263),1662=>array(34,-244,586,263),1663=>array(34,-10,586,513),1664=>array(34,-244,586,263),1667=>array(43,-244,584,425),1668=>array(43,-244,584,425),1670=>array(43,-244,584,425),1671=>array(43,-244,584,425),1681=>array(-25,-246,602,582),1688=>array(-25,-246,549,555),1700=>array(-36,-45,568,700),1705=>array(5,-43,670,760),1711=>array(5,-43,672,902),1726=>array(0,-33,572,487),1740=>array(12,-131,602,389),1776=>array(247,220,354,342),1777=>array(198,0,404,635),1778=>array(75,0,527,635),1779=>array(65,0,537,635),1780=>array(85,0,517,643),1781=>array(84,-5,518,643),1782=>array(129,0,473,640),1783=>array(62,0,540,635),1784=>array(62,0,540,635),1785=>array(79,0,523,640),3713=>array(30,-10,549,560),3714=>array(53,-17,585,568),3716=>array(59,-10,539,568),3719=>array(120,-238,482,568),3720=>array(61,-0,542,575),3722=>array(47,-238,598,563),3725=>array(56,-8,545,573),3732=>array(60,-14,542,560),3733=>array(73,-15,554,579),3734=>array(13,-240,530,560),3735=>array(52,-14,551,560),3737=>array(37,-14,541,568),3738=>array(61,-8,541,561),3739=>array(61,-8,541,760),3740=>array(48,-8,620,638),3741=>array(48,-8,548,760),3742=>array(49,-8,553,561),3743=>array(49,-8,553,760),3745=>array(8,-14,547,547),3746=>array(56,-8,545,760),3747=>array(49,-8,553,568),3749=>array(47,-8,555,568),3751=>array(54,-13,548,560),3754=>array(48,-8,642,701),3755=>array(10,-12,592,575),3757=>array(58,-8,552,568),3758=>array(42,-8,606,605),3759=>array(23,-106,583,579),3760=>array(44,-13,549,563),3761=>array(-558,639,-53,880),3762=>array(77,0,516,560),3763=>array(-404,0,516,806),3764=>array(41,615,562,926),3765=>array(41,612,634,926),3766=>array(41,615,562,926),3767=>array(41,612,634,926),3768=>array(226,-350,441,-38),3769=>array(184,-306,450,-40),3771=>array(34,639,568,880),3772=>array(-8,-278,610,-39),3784=>array(257,618,345,792),3785=>array(42,609,560,891),3786=>array(46,598,664,869),3787=>array(161,609,441,890),3788=>array(-8,636,610,875),3789=>array(198,620,404,806),4304=>array(78,0,525,560),4305=>array(77,0,525,761),4306=>array(54,-208,547,510),4307=>array(27,-208,575,505),4308=>array(78,-208,525,510),4309=>array(77,-208,524,510),4310=>array(77,0,524,760),4311=>array(27,0,575,505),4312=>array(78,0,524,510),4313=>array(77,-207,525,501),4314=>array(78,-208,524,510),4315=>array(77,0,525,760),4316=>array(78,0,524,748),4317=>array(27,0,575,505),4318=>array(78,0,525,757),4319=>array(78,-207,525,524),4320=>array(27,0,575,760),4321=>array(78,0,525,743),4322=>array(22,-207,580,614),4323=>array(27,-207,536,506),4324=>array(27,-208,577,505),4325=>array(78,-208,524,743),4326=>array(27,-208,575,506),4327=>array(77,-207,524,496),4328=>array(27,0,525,760),4329=>array(77,0,525,760),4330=>array(42,-207,560,518),4331=>array(77,0,525,743),4332=>array(79,0,576,760),4333=>array(78,-207,525,743),4334=>array(78,0,525,743),4335=>array(78,-207,525,605),4336=>array(77,0,525,760),4337=>array(58,-207,525,760),4338=>array(78,-131,525,511),4339=>array(78,-208,525,510),4340=>array(78,-208,525,760),4341=>array(68,0,561,760),4342=>array(27,-207,575,511),4343=>array(52,-207,550,511),4344=>array(79,-207,525,520),4345=>array(54,-208,548,518),4346=>array(78,-66,455,511),4347=>array(142,24,460,486),4348=>array(198,370,404,760),7426=>array(20,-14,586,560),7432=>array(83,-11,520,560),7433=>array(87,-211,533,549),7444=>array(7,-14,591,560),7446=>array(67,273,535,560),7447=>array(66,-14,535,273),7453=>array(21,1,581,419),7454=>array(31,-1,571,417),7455=>array(21,0,581,501),7468=>array(123,326,479,734),7469=>array(120,326,482,734),7470=>array(152,326,450,734),7472=>array(152,326,450,734),7473=>array(162,326,440,734),7474=>array(162,326,440,734),7475=>array(146,318,455,742),7476=>array(153,326,448,734),7477=>array(174,326,429,734),7478=>array(171,318,431,734),7479=>array(134,326,469,734),7480=>array(159,326,443,734),7481=>array(138,326,464,734),7482=>array(154,326,448,734),7483=>array(154,326,448,734),7484=>array(147,318,455,742),7486=>array(156,326,446,734),7487=>array(133,326,469,734),7488=>array(126,326,476,734),7489=>array(157,318,445,734),7490=>array(111,326,491,734),7491=>array(159,318,443,640),7492=>array(159,318,443,640),7493=>array(160,318,442,640),7494=>array(123,318,479,640),7495=>array(160,318,442,751),7496=>array(160,318,442,751),7497=>array(149,318,453,640),7498=>array(149,318,453,640),7499=>array(164,320,438,640),7500=>array(164,320,438,640),7501=>array(160,206,442,640),7502=>array(161,208,441,633),7503=>array(152,326,450,751),7504=>array(143,326,459,640),7505=>array(169,209,433,640),7506=>array(153,318,449,640),7507=>array(168,318,434,640),7508=>array(153,479,449,640),7509=>array(153,318,449,479),7510=>array(160,209,442,640),7511=>array(163,326,439,719),7512=>array(169,318,433,632),7513=>array(125,327,478,561),7514=>array(143,326,459,640),7515=>array(142,326,460,632),7522=>array(160,0,441,425),7523=>array(200,0,402,314),7524=>array(169,-8,433,306),7525=>array(142,0,460,306),7543=>array(60,-215,509,560),7544=>array(153,326,448,734),7547=>array(76,0,526,547),7557=>array(78,-208,505,765),7579=>array(160,318,442,640),7580=>array(168,318,434,640),7581=>array(165,286,438,639),7582=>array(153,318,449,751),7583=>array(164,320,438,640),7584=>array(167,326,435,751),7585=>array(173,209,429,632),7586=>array(160,206,442,631),7587=>array(169,208,433,632),7588=>array(158,326,444,751),7589=>array(172,326,430,632),7590=>array(161,326,441,632),7591=>array(160,326,442,632),7592=>array(174,209,428,751),7593=>array(167,209,436,755),7594=>array(167,209,436,755),7595=>array(187,326,416,640),7596=>array(143,209,458,640),7597=>array(143,208,459,640),7598=>array(167,209,436,640),7599=>array(167,209,436,640),7600=>array(156,326,446,640),7601=>array(153,318,449,640),7602=>array(153,210,449,751),7603=>array(169,209,433,640),7604=>array(184,209,418,751),7605=>array(163,209,439,719),7606=>array(102,318,500,632),7607=>array(141,318,461,632),7609=>array(159,326,443,632),7610=>array(133,326,469,632),7611=>array(172,326,430,633),7612=>array(171,209,431,632),7613=>array(163,296,439,632),7614=>array(150,207,452,632),7615=>array(153,318,449,736),7680=>array(18,-245,584,729),7681=>array(65,-245,517,560),7682=>array(81,0,555,914),7683=>array(94,-14,543,760),7684=>array(81,-202,555,729),7685=>array(94,-202,543,760),7686=>array(81,-174,555,729),7687=>array(94,-174,543,760),7688=>array(68,-193,524,927),7689=>array(95,-193,518,800),7690=>array(67,0,540,914),7691=>array(60,-14,509,760),7692=>array(67,-202,540,729),7693=>array(60,-202,509,760),7694=>array(67,-174,540,729),7695=>array(60,-174,509,760),7696=>array(61,-193,540,729),7697=>array(60,-193,509,760),7698=>array(67,-237,540,729),7699=>array(60,-237,509,760),7704=>array(96,-237,538,729),7705=>array(60,-237,543,560),7706=>array(96,-237,538,729),7707=>array(60,-237,543,560),7708=>array(96,-193,538,928),7709=>array(60,-193,543,785),7710=>array(114,0,543,914),7711=>array(95,0,519,914),7712=>array(50,-14,539,898),7713=>array(60,-215,509,745),7714=>array(67,0,535,914),7715=>array(95,0,513,914),7716=>array(67,-202,535,729),7717=>array(95,-202,513,760),7718=>array(67,0,535,901),7719=>array(95,0,513,918),7720=>array(10,-193,535,729),7721=>array(27,-193,513,760),7722=>array(67,-238,535,729),7723=>array(95,-238,513,760),7724=>array(98,-237,503,729),7725=>array(87,-237,533,760),7728=>array(67,0,598,927),7729=>array(115,0,587,927),7730=>array(67,-202,598,729),7731=>array(115,-202,587,760),7732=>array(67,-174,598,729),7733=>array(115,-174,587,760),7734=>array(105,-202,556,729),7735=>array(78,-202,505,765),7736=>array(105,-202,556,898),7737=>array(78,-202,505,898),7738=>array(105,-174,556,729),7739=>array(78,-174,505,765),7740=>array(105,-237,556,729),7741=>array(78,-237,505,765),7742=>array(42,0,559,927),7743=>array(53,0,554,800),7744=>array(42,0,559,914),7745=>array(53,0,554,758),7746=>array(42,-202,559,729),7747=>array(53,-202,554,560),7748=>array(68,0,534,914),7749=>array(95,0,513,758),7750=>array(68,-202,534,729),7751=>array(95,-202,513,560),7752=>array(68,-174,534,729),7753=>array(95,-174,513,560),7754=>array(68,-237,534,729),7755=>array(95,-237,513,560),7756=>array(57,-14,545,997),7757=>array(67,-14,535,997),7764=>array(96,0,557,931),7765=>array(93,-208,541,800),7766=>array(96,0,557,914),7767=>array(93,-208,541,758),7768=>array(70,0,602,914),7769=>array(177,0,564,758),7770=>array(70,-202,602,729),7771=>array(177,-202,564,560),7772=>array(70,-202,602,898),7773=>array(155,-202,564,745),7774=>array(70,-174,602,729),7775=>array(155,-174,564,560),7776=>array(68,-14,536,914),7777=>array(104,-14,503,758),7778=>array(68,-202,536,742),7779=>array(104,-202,503,560),7784=>array(68,-202,536,914),7785=>array(104,-202,503,758),7786=>array(23,0,579,914),7787=>array(64,0,504,914),7788=>array(23,-202,579,729),7789=>array(64,-202,504,702),7790=>array(23,-174,579,729),7791=>array(64,-174,504,702),7792=>array(23,-237,579,729),7793=>array(64,-237,504,702),7794=>array(72,-201,530,729),7795=>array(95,-201,513,546),7796=>array(72,-237,530,729),7797=>array(95,-237,513,546),7798=>array(72,-237,530,729),7799=>array(95,-237,513,546),7800=>array(72,-14,530,997),7801=>array(95,-14,513,997),7804=>array(28,0,574,909),7805=>array(49,0,553,757),7806=>array(28,-202,574,729),7807=>array(49,-202,553,547),7808=>array(0,0,602,931),7809=>array(0,0,602,803),7810=>array(0,0,602,931),7811=>array(0,0,602,803),7812=>array(0,0,602,900),7813=>array(0,0,602,718),7814=>array(0,0,602,914),7815=>array(0,0,602,758),7816=>array(0,-202,602,729),7817=>array(0,-202,602,547),7818=>array(9,0,593,914),7819=>array(37,0,565,758),7820=>array(9,0,593,901),7821=>array(37,0,565,718),7822=>array(18,0,584,914),7823=>array(51,-208,563,758),7824=>array(76,0,571,932),7825=>array(99,0,508,803),7826=>array(76,-202,571,729),7827=>array(99,-202,508,548),7828=>array(76,-174,571,729),7829=>array(99,-174,508,548),7830=>array(95,-174,513,760),7831=>array(64,0,504,860),7832=>array(0,0,602,888),7833=>array(51,-208,563,888),7835=>array(95,0,519,914),7839=>array(67,-14,535,767),7840=>array(18,-202,584,729),7841=>array(65,-202,517,560),7852=>array(18,-202,584,932),7853=>array(65,-202,517,803),7856=>array(18,0,584,997),7857=>array(65,-14,517,954),7862=>array(18,-202,584,928),7863=>array(65,-202,517,760),7864=>array(96,-202,538,729),7865=>array(60,-202,543,560),7868=>array(96,0,538,921),7869=>array(60,-14,543,777),7878=>array(96,-202,538,932),7879=>array(60,-202,543,803),7882=>array(98,-202,503,729),7883=>array(87,-202,533,760),7884=>array(57,-202,545,742),7885=>array(67,-202,535,560),7896=>array(57,-202,545,932),7897=>array(67,-202,535,803),7898=>array(3,-14,582,927),7899=>array(16,-14,587,800),7900=>array(3,-14,582,927),7901=>array(16,-14,587,800),7904=>array(3,-14,582,921),7905=>array(16,-14,587,777),7906=>array(3,-202,582,760),7907=>array(16,-202,587,560),7908=>array(72,-202,530,729),7909=>array(95,-202,513,546),7912=>array(4,-14,598,927),7913=>array(19,-14,583,800),7914=>array(4,-14,598,927),7915=>array(19,-14,583,800),7918=>array(4,-14,598,921),7919=>array(19,-14,583,777),7920=>array(4,-202,598,762),7921=>array(19,-202,583,555),7922=>array(18,0,584,931),7923=>array(51,-208,563,803),7924=>array(18,-202,584,729),7925=>array(51,-208,563,547),7928=>array(18,0,584,921),7929=>array(51,-208,563,777),7936=>array(34,-12,573,806),7937=>array(34,-12,573,806),7938=>array(34,-12,573,806),7939=>array(34,-12,573,806),7940=>array(34,-12,573,806),7941=>array(34,-12,573,806),7942=>array(34,-12,573,977),7943=>array(34,-12,573,977),7944=>array(18,0,584,806),7945=>array(18,0,584,806),7946=>array(-198,0,584,806),7947=>array(-198,0,584,806),7948=>array(-112,0,584,806),7949=>array(-122,0,584,806),7950=>array(-31,0,584,977),7951=>array(-55,0,584,977),7952=>array(83,-11,520,806),7953=>array(83,-11,520,806),7954=>array(83,-11,520,806),7955=>array(83,-11,520,806),7956=>array(83,-11,520,806),7957=>array(83,-11,520,806),7960=>array(-63,0,538,806),7961=>array(-63,0,538,806),7962=>array(-308,0,538,806),7963=>array(-308,0,538,806),7964=>array(-247,0,538,806),7965=>array(-256,0,538,806),7968=>array(95,-208,513,806),7969=>array(95,-208,513,806),7970=>array(95,-208,513,806),7971=>array(95,-208,513,806),7972=>array(95,-208,515,806),7973=>array(95,-208,515,806),7974=>array(95,-208,513,977),7975=>array(95,-208,513,977),7976=>array(-88,0,535,806),7977=>array(-88,0,535,806),7978=>array(-344,0,535,806),7979=>array(-344,0,535,806),7980=>array(-295,0,535,806),7981=>array(-305,0,535,806),7982=>array(-202,0,535,977),7983=>array(-202,0,535,977),7984=>array(151,0,476,806),7985=>array(151,0,476,806),7986=>array(120,0,492,806),7987=>array(120,0,492,806),7988=>array(144,0,515,806),7989=>array(134,0,515,806),7990=>array(140,0,476,977),7991=>array(140,0,476,977),7992=>array(-63,0,503,806),7993=>array(-63,0,503,806),7994=>array(-295,0,503,806),7995=>array(-295,0,503,806),7996=>array(-247,0,503,806),7997=>array(-256,0,503,806),7998=>array(-165,0,503,977),7999=>array(-165,0,503,977),8000=>array(67,-14,535,806),8001=>array(67,-14,535,806),8002=>array(67,-14,535,806),8003=>array(67,-14,535,806),8004=>array(67,-14,535,806),8005=>array(67,-14,535,806),8008=>array(-27,-14,545,806),8009=>array(-63,-14,545,806),8010=>array(-308,-14,545,806),8011=>array(-308,-14,545,806),8012=>array(-173,-14,545,806),8013=>array(-183,-14,545,806),8016=>array(25,0,551,806),8017=>array(25,0,551,806),8018=>array(25,0,551,806),8019=>array(25,0,551,806),8020=>array(25,0,551,806),8021=>array(25,0,551,806),8022=>array(25,0,551,977),8023=>array(25,0,551,977),8025=>array(-137,0,584,806),8027=>array(-344,0,584,806),8029=>array(-342,0,584,806),8031=>array(-238,0,584,977),8032=>array(34,-14,568,806),8033=>array(34,-14,568,806),8034=>array(34,-14,568,806),8035=>array(34,-14,568,806),8036=>array(34,-14,568,806),8037=>array(34,-14,568,806),8038=>array(34,-14,568,977),8039=>array(34,-14,568,977),8040=>array(-27,0,566,806),8041=>array(-76,0,566,806),8042=>array(-308,0,566,806),8043=>array(-308,0,566,806),8044=>array(-161,0,566,806),8045=>array(-171,0,566,806),8046=>array(-128,0,566,977),8047=>array(-165,0,566,977),8048=>array(34,-12,573,800),8049=>array(34,-12,573,800),8050=>array(83,-11,520,800),8051=>array(83,-11,520,800),8052=>array(95,-208,513,800),8053=>array(95,-208,513,800),8054=>array(136,0,476,800),8055=>array(151,0,476,800),8056=>array(67,-14,535,800),8057=>array(67,-14,535,800),8058=>array(25,0,551,800),8059=>array(25,0,551,800),8060=>array(34,-14,568,800),8061=>array(34,-14,568,800),8064=>array(34,-208,573,806),8065=>array(34,-208,573,806),8066=>array(34,-208,573,806),8067=>array(34,-208,573,806),8068=>array(34,-208,573,806),8069=>array(34,-208,573,806),8070=>array(34,-208,573,977),8071=>array(34,-208,573,977),8072=>array(18,-208,584,806),8073=>array(18,-208,584,806),8074=>array(-198,-208,584,806),8075=>array(-198,-208,584,806),8076=>array(-112,-208,584,806),8077=>array(-122,-208,584,806),8078=>array(-31,-208,584,977),8079=>array(-55,-208,584,977),8080=>array(95,-208,513,806),8081=>array(95,-208,513,806),8082=>array(95,-208,513,806),8083=>array(95,-208,513,806),8084=>array(95,-208,515,806),8085=>array(95,-208,515,806),8086=>array(95,-208,513,977),8087=>array(95,-208,513,977),8088=>array(-88,-208,535,806),8089=>array(-88,-208,535,806),8090=>array(-344,-208,535,806),8091=>array(-344,-208,535,806),8092=>array(-295,-208,535,806),8093=>array(-305,-208,535,806),8094=>array(-202,-208,535,977),8095=>array(-202,-208,535,977),8096=>array(34,-208,568,806),8097=>array(34,-208,568,806),8098=>array(34,-208,568,806),8099=>array(34,-208,568,806),8100=>array(34,-208,568,806),8101=>array(34,-208,568,806),8102=>array(34,-208,568,977),8103=>array(34,-208,568,977),8104=>array(-27,-208,566,806),8105=>array(-76,-208,566,806),8106=>array(-308,-208,566,806),8107=>array(-308,-208,566,806),8108=>array(-161,-208,566,806),8109=>array(-171,-208,566,806),8110=>array(-128,-208,566,977),8111=>array(-165,-208,566,977),8112=>array(34,-12,573,785),8113=>array(34,-12,573,745),8114=>array(34,-208,573,800),8115=>array(34,-208,573,559),8116=>array(34,-208,573,800),8118=>array(34,-12,573,777),8119=>array(34,-208,573,777),8120=>array(18,0,584,928),8121=>array(18,0,584,898),8122=>array(-59,0,584,800),8123=>array(12,0,584,800),8124=>array(18,-208,584,729),8125=>array(242,595,360,806),8126=>array(265,-208,372,-45),8127=>array(242,595,360,806),8128=>array(140,639,462,777),8129=>array(140,659,462,943),8130=>array(95,-208,513,800),8131=>array(95,-208,513,560),8132=>array(95,-208,513,800),8134=>array(95,-208,513,777),8135=>array(95,-208,513,777),8136=>array(-181,0,538,800),8137=>array(-110,0,538,800),8138=>array(-206,0,535,800),8139=>array(-134,0,535,800),8140=>array(67,-208,535,729),8141=>array(120,595,492,806),8142=>array(144,595,515,806),8143=>array(140,595,462,977),8144=>array(148,0,476,785),8145=>array(151,0,476,745),8146=>array(136,0,476,980),8147=>array(151,0,476,980),8150=>array(140,0,476,777),8151=>array(140,0,476,943),8152=>array(98,0,503,928),8153=>array(98,0,503,898),8154=>array(-157,0,503,800),8155=>array(-110,0,503,800),8157=>array(120,595,492,806),8158=>array(134,595,515,806),8159=>array(140,595,462,977),8160=>array(25,0,551,785),8161=>array(25,0,551,745),8162=>array(25,0,551,980),8163=>array(25,0,551,980),8164=>array(93,-208,541,806),8165=>array(93,-208,541,806),8166=>array(25,0,551,777),8167=>array(25,0,551,943),8168=>array(18,0,584,928),8169=>array(18,0,584,898),8170=>array(-206,0,584,800),8171=>array(-195,0,584,800),8172=>array(-63,0,557,806),8173=>array(136,659,446,980),8174=>array(156,659,466,980),8175=>array(136,616,370,800),8178=>array(34,-208,568,800),8179=>array(34,-208,568,547),8180=>array(34,-208,568,800),8182=>array(34,-14,568,777),8183=>array(34,-208,568,777),8184=>array(-169,-14,545,800),8185=>array(-37,-14,545,800),8186=>array(-169,0,566,800),8187=>array(-24,0,566,800),8188=>array(36,-208,566,713),8189=>array(232,616,466,800),8190=>array(242,595,360,806),8208=>array(174,234,428,314),8209=>array(174,234,428,314),8210=>array(0,240,602,309),8211=>array(0,240,602,309),8212=>array(0,240,602,309),8213=>array(0,240,602,309),8214=>array(139,-236,462,764),8215=>array(0,-236,602,-80),8216=>array(226,472,397,760),8217=>array(226,472,397,760),8218=>array(197,-140,368,148),8219=>array(226,472,397,760),8220=>array(103,472,499,760),8221=>array(103,472,498,760),8222=>array(103,-140,498,148),8223=>array(103,472,498,760),8224=>array(79,-96,523,729),8225=>array(79,-96,523,729),8226=>array(156,227,446,516),8227=>array(156,188,485,555),8230=>array(39,0,562,149),8240=>array(0,0,602,699),8241=>array(0,0,602,699),8242=>array(209,547,393,729),8243=>array(136,547,466,729),8244=>array(63,547,539,729),8245=>array(209,547,393,729),8246=>array(136,547,466,729),8247=>array(63,547,539,729),8249=>array(169,69,398,517),8250=>array(205,69,434,517),8252=>array(102,0,501,729),8253=>array(119,0,508,742),8254=>array(0,716,602,755),8261=>array(226,-132,433,760),8262=>array(169,-132,376,760),8263=>array(16,0,586,742),8264=>array(16,0,501,742),8265=>array(102,0,586,742),8267=>array(99,-96,550,729),8304=>array(155,319,448,742),8305=>array(160,326,441,751),8308=>array(131,326,444,734),8309=>array(156,319,436,734),8310=>array(161,319,454,742),8311=>array(155,326,440,734),8312=>array(154,318,448,741),8313=>array(148,319,441,742),8314=>array(139,357,464,646),8315=>array(139,479,464,525),8316=>array(139,422,464,581),8317=>array(230,252,372,751),8318=>array(230,252,372,751),8319=>array(157,326,445,640),8320=>array(155,-7,448,416),8321=>array(168,0,447,408),8322=>array(157,0,436,416),8323=>array(159,-7,451,416),8324=>array(131,0,444,408),8325=>array(156,-7,436,408),8326=>array(161,-7,454,416),8327=>array(155,0,440,408),8328=>array(154,-8,448,415),8329=>array(148,-7,441,416),8330=>array(139,31,464,320),8331=>array(139,152,464,199),8332=>array(139,96,464,254),8333=>array(230,-74,372,425),8334=>array(230,-74,372,425),8336=>array(159,-8,443,313),8337=>array(149,-8,453,313),8338=>array(153,-8,449,313),8339=>array(134,0,468,306),8340=>array(149,-8,453,313),8341=>array(157,0,445,426),8342=>array(152,0,450,425),8343=>array(167,0,436,429),8344=>array(143,0,459,313),8345=>array(157,0,445,314),8346=>array(160,-117,442,313),8347=>array(169,0,433,322),8348=>array(163,0,439,393),8352=>array(5,-11,600,737),8353=>array(60,-44,548,778),8354=>array(46,-14,543,742),8355=>array(0,0,533,729),8356=>array(68,0,553,742),8357=>array(53,-93,554,640),8358=>array(0,0,602,729),8359=>array(5,-14,600,729),8360=>array(5,-14,598,729),8361=>array(0,0,602,729),8362=>array(21,-14,582,729),8363=>array(60,-174,602,760),8364=>array(18,-14,518,742),8365=>array(21,0,582,729),8366=>array(23,0,579,729),8367=>array(15,-222,597,742),8368=>array(22,-14,569,742),8369=>array(52,0,602,729),8370=>array(26,-81,567,809),8371=>array(19,0,583,729),8372=>array(0,-14,602,742),8373=>array(63,-147,539,760),8376=>array(23,0,579,729),8377=>array(51,0,555,729),8450=>array(68,-14,524,742),8453=>array(3,-24,602,752),8461=>array(28,0,577,729),8462=>array(41,0,535,760),8463=>array(41,0,535,760),8469=>array(36,0,565,729),8470=>array(5,0,597,729),8471=>array(0,61,602,663),8473=>array(32,0,575,729),8474=>array(8,-129,592,742),8477=>array(18,0,592,729),8482=>array(0,447,550,729),8484=>array(23,0,575,729),8486=>array(36,0,566,713),8490=>array(67,0,598,729),8491=>array(18,0,584,928),8494=>array(5,-12,597,647),8520=>array(13,0,469,760),8531=>array(13,-139,549,810),8532=>array(13,-139,549,818),8533=>array(13,-139,544,810),8534=>array(13,-139,544,818),8535=>array(13,-139,544,818),8536=>array(5,-139,544,810),8537=>array(13,-139,552,810),8538=>array(13,-139,552,810),8539=>array(13,-140,546,810),8540=>array(13,-140,546,818),8541=>array(13,-140,546,810),8542=>array(13,-140,546,810),8543=>array(13,246,544,810),8592=>array(32,112,570,436),8593=>array(139,0,463,538),8594=>array(32,112,570,436),8595=>array(139,0,463,538),8596=>array(32,112,570,436),8597=>array(139,0,463,538),8598=>array(90,0,512,422),8599=>array(90,0,512,422),8600=>array(90,0,512,422),8601=>array(90,0,512,422),8602=>array(32,112,570,436),8603=>array(32,112,570,436),8604=>array(43,193,559,422),8605=>array(43,193,559,422),8606=>array(32,112,570,436),8607=>array(139,0,463,538),8608=>array(32,112,570,436),8609=>array(139,0,463,538),8610=>array(32,112,570,436),8611=>array(32,112,570,436),8612=>array(32,112,570,436),8613=>array(139,0,463,538),8614=>array(32,112,570,436),8615=>array(139,0,463,538),8616=>array(139,0,463,538),8617=>array(32,112,570,517),8618=>array(32,112,570,517),8619=>array(32,112,570,517),8620=>array(32,112,570,517),8621=>array(32,112,570,436),8622=>array(32,102,570,446),8623=>array(55,0,547,698),8624=>array(89,0,513,674),8625=>array(89,0,513,674),8626=>array(89,0,513,674),8627=>array(89,0,513,674),8628=>array(91,0,511,540),8629=>array(31,0,571,420),8630=>array(40,168,563,487),8631=>array(40,168,563,487),8632=>array(24,0,578,513),8633=>array(32,0,570,604),8634=>array(43,0,559,497),8635=>array(43,0,559,497),8636=>array(32,234,570,436),8637=>array(32,112,570,314),8638=>array(261,0,463,538),8639=>array(139,0,341,538),8640=>array(32,234,570,436),8641=>array(32,112,570,314),8642=>array(261,0,463,538),8643=>array(160,0,362,538),8644=>array(32,0,570,561),8645=>array(21,0,582,538),8646=>array(32,0,570,561),8647=>array(32,0,570,561),8648=>array(21,0,582,538),8649=>array(32,0,570,561),8650=>array(21,0,582,538),8651=>array(32,32,570,516),8652=>array(32,32,570,516),8653=>array(32,112,570,436),8654=>array(32,112,570,460),8655=>array(32,112,570,436),8656=>array(32,112,570,436),8657=>array(139,0,463,538),8658=>array(32,112,570,436),8659=>array(139,0,463,538),8660=>array(32,112,570,436),8661=>array(139,0,463,538),8662=>array(76,-28,526,422),8663=>array(76,-28,526,422),8664=>array(76,0,526,451),8665=>array(76,0,526,451),8666=>array(32,112,570,436),8667=>array(32,112,570,436),8668=>array(32,112,570,436),8669=>array(32,112,570,436),8670=>array(139,0,463,538),8671=>array(139,0,463,538),8672=>array(32,112,570,436),8673=>array(139,0,463,538),8674=>array(32,112,570,436),8675=>array(139,0,463,538),8676=>array(32,112,570,436),8677=>array(32,112,570,436),8678=>array(12,92,570,456),8679=>array(119,0,483,558),8680=>array(32,92,590,456),8681=>array(119,0,483,558),8682=>array(119,0,483,558),8683=>array(119,0,483,558),8684=>array(119,0,483,558),8685=>array(119,0,483,558),8686=>array(119,0,483,558),8687=>array(119,0,483,558),8688=>array(32,92,590,456),8689=>array(34,0,568,534),8690=>array(34,0,568,534),8691=>array(119,0,483,558),8692=>array(32,112,570,436),8693=>array(21,0,582,538),8694=>array(32,-125,570,672),8695=>array(32,112,570,436),8696=>array(32,112,570,436),8697=>array(32,112,570,436),8698=>array(32,112,570,436),8699=>array(32,112,570,436),8700=>array(32,112,570,436),8701=>array(12,92,570,456),8702=>array(32,92,590,456),8703=>array(12,92,590,456),8704=>array(18,0,584,729),8705=>array(57,-14,545,742),8706=>array(89,-14,513,662),8707=>array(87,0,514,729),8708=>array(87,-46,514,776),8709=>array(36,48,567,580),8710=>array(-3,0,606,695),8711=>array(-3,0,606,695),8712=>array(63,0,539,715),8713=>array(63,-86,539,801),8714=>array(63,81,539,545),8715=>array(63,0,539,715),8716=>array(63,-86,539,801),8717=>array(63,81,539,545),8719=>array(74,-213,528,741),8721=>array(70,-213,530,741),8722=>array(43,272,559,355),8723=>array(43,0,559,572),8725=>array(50,-93,527,729),8727=>array(81,85,521,542),8728=>array(146,160,456,470),8729=>array(156,200,446,489),8730=>array(29,-19,578,828),8731=>array(29,-19,578,933),8732=>array(29,-19,578,924),8733=>array(91,122,511,492),8734=>array(20,122,582,492),8735=>array(61,140,541,620),8736=>array(61,140,541,620),8743=>array(80,0,521,579),8744=>array(80,0,521,579),8745=>array(80,0,521,579),8746=>array(80,0,521,579),8747=>array(63,-183,539,871),8748=>array(31,-189,571,877),8749=>array(26,-176,577,864),8756=>array(91,65,512,564),8757=>array(92,65,510,564),8758=>array(238,65,363,564),8759=>array(91,65,512,564),8760=>array(43,272,559,564),8761=>array(36,65,566,564),8762=>array(42,65,561,564),8763=>array(43,65,559,564),8764=>array(43,243,559,384),8765=>array(43,243,559,384),8769=>array(43,85,559,535),8770=>array(43,149,559,454),8771=>array(43,172,559,470),8772=>array(43,48,560,604),8773=>array(43,94,559,570),8774=>array(43,24,559,570),8775=>array(43,0,559,647),8776=>array(43,149,559,470),8777=>array(43,23,559,595),8778=>array(43,94,559,572),8779=>array(43,73,559,572),8780=>array(43,94,559,570),8781=>array(42,108,559,519),8782=>array(43,33,560,593),8783=>array(43,172,560,593),8784=>array(43,172,559,637),8785=>array(43,-11,559,637),8786=>array(43,-10,559,637),8787=>array(42,-10,560,637),8788=>array(36,147,566,479),8789=>array(36,147,566,479),8790=>array(43,172,559,454),8791=>array(43,172,559,760),8792=>array(43,172,559,662),8793=>array(43,172,559,783),8794=>array(43,172,559,783),8795=>array(43,172,559,831),8796=>array(43,172,559,836),8797=>array(34,172,568,764),8798=>array(43,172,559,760),8799=>array(43,172,559,856),8800=>array(43,18,559,608),8801=>array(43,94,559,532),8802=>array(43,5,559,622),8803=>array(43,0,559,616),8804=>array(43,0,559,531),8805=>array(43,0,559,531),8806=>array(42,-84,558,578),8807=>array(42,-84,558,578),8808=>array(42,-162,558,578),8809=>array(42,-162,558,578),8813=>array(42,0,559,627),8814=>array(43,-14,559,641),8815=>array(43,-14,559,641),8816=>array(43,-119,559,629),8817=>array(43,-119,559,629),8818=>array(42,-21,558,531),8819=>array(42,-21,558,531),8820=>array(42,-119,558,629),8821=>array(42,-119,558,629),8822=>array(42,-89,558,603),8823=>array(42,-89,558,603),8824=>array(42,-195,558,711),8825=>array(42,-195,558,711),8826=>array(42,-22,558,648),8827=>array(43,-22,559,648),8828=>array(42,-123,558,711),8829=>array(42,-123,558,711),8830=>array(42,-56,558,711),8831=>array(42,-56,558,711),8832=>array(42,-81,558,707),8833=>array(42,-81,558,707),8834=>array(43,80,559,546),8835=>array(43,80,559,546),8836=>array(43,-29,559,655),8837=>array(43,-29,559,655),8838=>array(43,0,559,625),8839=>array(43,0,559,625),8840=>array(43,-104,559,729),8841=>array(43,-104,559,729),8842=>array(43,-102,559,625),8843=>array(43,-102,559,625),8847=>array(43,58,559,568),8848=>array(43,58,559,568),8849=>array(43,7,559,619),8850=>array(43,7,559,619),8853=>array(39,51,563,577),8854=>array(39,51,563,577),8855=>array(39,51,563,577),8856=>array(39,51,563,577),8857=>array(39,51,563,577),8858=>array(39,51,563,577),8859=>array(39,51,563,577),8860=>array(39,51,563,577),8861=>array(39,51,563,577),8862=>array(39,51,564,576),8863=>array(39,51,564,576),8864=>array(39,51,564,576),8865=>array(39,51,564,576),8866=>array(43,0,559,627),8867=>array(43,0,559,627),8868=>array(43,0,559,627),8869=>array(43,0,559,627),8901=>array(239,273,362,422),8902=>array(129,201,473,527),8909=>array(43,172,559,470),8922=>array(43,-218,559,760),8923=>array(43,-218,559,760),8924=>array(42,0,558,531),8925=>array(43,0,559,531),8926=>array(42,-123,558,711),8927=>array(42,-123,558,711),8928=>array(42,-182,558,770),8929=>array(42,-182,558,770),8930=>array(43,-81,559,707),8931=>array(43,-81,559,707),8932=>array(43,-95,559,619),8933=>array(43,-95,559,619),8934=>array(42,-134,558,531),8935=>array(42,-134,558,531),8936=>array(42,-213,558,711),8937=>array(42,-213,558,711),8943=>array(39,239,562,388),8960=>array(36,48,567,580),8961=>array(56,162,540,443),8962=>array(71,0,531,596),8963=>array(71,406,530,746),8964=>array(71,-132,530,209),8965=>array(71,0,530,444),8966=>array(71,0,530,566),8968=>array(226,-132,433,760),8969=>array(169,-132,376,760),8970=>array(226,-132,433,760),8971=>array(169,-132,376,760),8972=>array(268,73,585,408),8973=>array(6,73,324,408),8974=>array(268,352,585,687),8975=>array(6,352,324,687),8976=>array(43,181,559,421),8977=>array(47,126,555,634),8978=>array(3,211,599,512),8979=>array(3,211,599,512),8980=>array(90,168,512,512),8981=>array(81,112,510,539),8984=>array(35,114,567,646),8985=>array(43,181,559,421),8988=>array(146,352,463,687),8989=>array(139,352,456,687),8990=>array(146,-56,463,279),8991=>array(139,-56,456,279),8992=>array(250,-250,537,928),8993=>array(61,-237,347,942),8997=>array(51,114,551,598),8998=>array(3,145,599,536),8999=>array(61,145,541,536),9000=>array(24,212,578,517),9003=>array(3,145,599,536),9013=>array(35,-22,566,286),9015=>array(125,-100,477,829),9016=>array(3,-100,599,829),9017=>array(3,-100,599,829),9018=>array(3,-100,599,829),9019=>array(3,-100,599,829),9020=>array(3,-100,599,829),9021=>array(3,-171,599,900),9022=>array(3,57,599,658),9025=>array(3,-100,599,829),9026=>array(3,-100,599,829),9027=>array(3,-100,599,829),9028=>array(3,-100,599,829),9031=>array(3,-100,599,829),9032=>array(3,-100,599,829),9033=>array(3,-29,599,729),9035=>array(18,-171,584,900),9036=>array(3,-100,599,829),9037=>array(3,-100,599,829),9040=>array(3,-100,599,829),9042=>array(18,-171,584,900),9043=>array(3,-100,599,829),9044=>array(3,-100,599,829),9047=>array(3,-100,599,829),9048=>array(125,-100,477,729),9049=>array(3,-100,599,729),9050=>array(3,-100,599,656),9051=>array(125,-100,477,489),9052=>array(3,-100,599,658),9054=>array(3,-100,599,829),9055=>array(-10,44,612,671),9056=>array(3,-100,599,829),9059=>array(129,201,473,636),9060=>array(156,229,446,660),9061=>array(3,57,599,831),9064=>array(43,240,559,660),9065=>array(43,69,559,660),9067=>array(18,0,584,729),9068=>array(43,-14,559,742),9069=>array(43,-171,559,900),9070=>array(125,-140,477,519),9071=>array(3,-100,599,829),9072=>array(3,-100,599,829),9075=>array(151,0,476,547),9076=>array(93,-208,541,560),9077=>array(34,-14,568,547),9078=>array(3,-100,599,559),9079=>array(76,-100,526,560),9080=>array(125,-100,477,547),9081=>array(3,-100,599,547),9082=>array(34,-12,573,559),9085=>array(13,-228,589,88),9088=>array(35,-22,566,528),9089=>array(3,106,599,528),9090=>array(3,106,599,528),9091=>array(3,177,599,567),9096=>array(40,27,562,601),9097=>array(34,46,567,579),9098=>array(34,46,567,579),9099=>array(34,46,567,579),9109=>array(3,-100,599,829),9115=>array(137,-258,465,940),9116=>array(137,-252,232,942),9117=>array(137,-240,465,942),9118=>array(137,-258,465,940),9119=>array(370,-252,465,942),9120=>array(137,-240,465,942),9121=>array(137,-252,465,928),9122=>array(137,-252,232,942),9123=>array(137,-240,465,942),9124=>array(137,-252,465,928),9125=>array(370,-252,465,935),9126=>array(137,-240,465,935),9127=>array(256,-261,594,928),9128=>array(8,-252,347,940),9129=>array(256,-240,594,940),9130=>array(256,-256,347,943),9131=>array(8,-261,346,928),9132=>array(255,-252,594,940),9133=>array(8,-240,346,940),9134=>array(250,-250,347,942),9166=>array(12,92,570,558),9167=>array(3,0,599,596),9251=>array(73,-228,528,88),9472=>array(-10,242,612,326),9473=>array(-10,200,612,368),9474=>array(262,-302,340,973),9475=>array(223,-302,379,973),9476=>array(-10,242,612,326),9477=>array(-10,200,612,368),9478=>array(262,-302,340,973),9479=>array(223,-302,379,973),9480=>array(-10,242,612,326),9481=>array(-10,200,612,368),9482=>array(262,-302,340,973),9483=>array(223,-302,379,973),9484=>array(262,-302,612,326),9485=>array(262,-302,612,368),9486=>array(223,-302,612,326),9487=>array(223,-302,612,368),9488=>array(-10,-302,340,326),9489=>array(-10,-302,340,368),9490=>array(-10,-302,379,326),9491=>array(-10,-302,379,368),9492=>array(262,242,612,973),9493=>array(262,200,612,973),9494=>array(223,242,612,973),9495=>array(223,200,612,973),9496=>array(-10,242,340,973),9497=>array(-10,200,340,973),9498=>array(-10,242,379,973),9499=>array(-10,200,379,973),9500=>array(262,-302,612,973),9501=>array(262,-302,612,973),9502=>array(223,-302,612,973),9503=>array(223,-302,612,973),9504=>array(223,-302,612,973),9505=>array(223,-302,612,973),9506=>array(223,-302,612,973),9507=>array(223,-302,612,973),9508=>array(-10,-302,340,973),9509=>array(-10,-302,340,973),9510=>array(-10,-302,379,973),9511=>array(-10,-302,379,973),9512=>array(-10,-302,379,973),9513=>array(-10,-302,379,973),9514=>array(-10,-302,379,973),9515=>array(-10,-302,379,973),9516=>array(-10,-302,612,326),9517=>array(-10,-302,612,368),9518=>array(-10,-302,612,368),9519=>array(-10,-302,612,368),9520=>array(-10,-302,612,326),9521=>array(-10,-302,612,368),9522=>array(-10,-302,612,368),9523=>array(-10,-302,612,368),9524=>array(-10,242,612,973),9525=>array(-10,200,612,973),9526=>array(-10,200,612,973),9527=>array(-10,200,612,973),9528=>array(-10,242,612,973),9529=>array(-10,200,612,973),9530=>array(-10,200,612,973),9531=>array(-10,200,612,973),9532=>array(-10,-302,612,973),9533=>array(-10,-302,612,973),9534=>array(-10,-302,612,973),9535=>array(-10,-302,612,973),9536=>array(-10,-302,612,973),9537=>array(-10,-302,612,973),9538=>array(-10,-302,612,973),9539=>array(-10,-302,612,973),9540=>array(-10,-302,612,973),9541=>array(-10,-302,612,973),9542=>array(-10,-302,612,973),9543=>array(-10,-302,612,973),9544=>array(-10,-302,612,973),9545=>array(-10,-302,612,973),9546=>array(-10,-302,612,973),9547=>array(-10,-302,612,973),9548=>array(-10,242,612,326),9549=>array(-10,200,612,368),9550=>array(262,-302,340,973),9551=>array(223,-302,379,973),9552=>array(-10,158,612,410),9553=>array(184,-302,418,973),9554=>array(262,-302,612,410),9555=>array(184,-302,612,326),9556=>array(184,-302,612,410),9557=>array(-10,-302,340,410),9558=>array(-10,-302,418,326),9559=>array(-10,-302,418,410),9560=>array(262,158,612,973),9561=>array(184,242,612,973),9562=>array(184,158,612,973),9563=>array(-10,158,340,973),9564=>array(-10,242,418,973),9565=>array(-10,158,418,973),9566=>array(262,-302,612,973),9567=>array(184,-302,612,973),9568=>array(184,-302,612,973),9569=>array(-10,-302,340,973),9570=>array(-10,-302,418,973),9571=>array(-10,-302,418,973),9572=>array(-10,-302,612,410),9573=>array(-10,-302,612,326),9574=>array(-10,-302,612,410),9575=>array(-10,158,612,973),9576=>array(-10,242,612,973),9577=>array(-10,158,612,973),9578=>array(-10,-302,612,973),9579=>array(-10,-302,612,973),9580=>array(-10,-302,612,973),9581=>array(262,-302,612,326),9582=>array(-10,-302,340,326),9583=>array(-10,242,340,973),9584=>array(262,242,612,973),9585=>array(-53,-302,655,973),9586=>array(-53,-302,655,973),9587=>array(-53,-302,655,973),9588=>array(-10,242,311,326),9589=>array(262,284,340,973),9590=>array(311,242,612,326),9591=>array(262,-302,340,284),9592=>array(-10,200,311,368),9593=>array(223,284,379,973),9594=>array(311,200,612,368),9595=>array(223,-302,379,284),9596=>array(-10,200,612,368),9597=>array(223,-302,379,973),9598=>array(-10,200,612,368),9599=>array(223,-302,379,973),9600=>array(-10,260,612,770),9601=>array(-10,-250,612,-123),9602=>array(-10,-250,612,5),9603=>array(-10,-250,612,132),9604=>array(-10,-250,612,260),9605=>array(-10,-250,612,387),9606=>array(-10,-250,612,515),9607=>array(-10,-250,612,642),9608=>array(-10,-250,612,770),9609=>array(-10,-250,534,770),9610=>array(-10,-250,457,770),9611=>array(-10,-250,379,770),9612=>array(-10,-250,301,770),9613=>array(-10,-250,223,770),9614=>array(-10,-250,146,770),9615=>array(-10,-250,68,770),9616=>array(301,-250,612,770),9617=>array(-10,-250,534,770),9618=>array(-10,-250,612,770),9619=>array(-10,-250,612,770),9620=>array(-10,642,612,770),9621=>array(534,-250,611,770),9622=>array(-10,-250,301,260),9623=>array(301,-250,612,260),9624=>array(-10,260,301,770),9625=>array(-10,-250,612,770),9626=>array(-10,-250,612,770),9627=>array(-10,-250,612,770),9628=>array(-10,-250,612,770),9629=>array(301,260,612,770),9630=>array(-10,-250,612,770),9631=>array(-10,-250,612,770),9632=>array(3,-39,599,558),9633=>array(3,-39,599,558),9634=>array(3,-39,599,558),9635=>array(3,-39,599,558),9636=>array(3,-39,599,558),9637=>array(3,-39,599,558),9638=>array(3,-39,599,558),9639=>array(3,-39,599,558),9640=>array(3,-39,599,558),9641=>array(3,-39,599,558),9642=>array(107,66,495,454),9643=>array(107,66,495,454),9644=>array(3,117,599,402),9645=>array(3,117,599,402),9646=>array(158,-39,444,558),9647=>array(158,-39,444,558),9648=>array(3,117,599,402),9649=>array(3,117,599,402),9650=>array(3,-39,599,558),9651=>array(3,-39,599,558),9652=>array(107,66,495,454),9653=>array(107,66,495,454),9654=>array(3,-39,599,558),9655=>array(3,-39,599,558),9656=>array(107,66,495,454),9657=>array(107,66,495,454),9658=>array(3,66,599,454),9659=>array(3,66,599,454),9660=>array(3,-39,599,558),9661=>array(3,-39,599,558),9662=>array(107,66,495,454),9663=>array(107,66,495,454),9664=>array(3,-39,599,558),9665=>array(3,-39,599,558),9666=>array(107,66,495,454),9667=>array(107,66,495,454),9668=>array(3,66,599,454),9669=>array(3,66,599,454),9670=>array(3,-39,599,558),9671=>array(3,-39,599,558),9672=>array(3,-39,599,558),9673=>array(3,-41,599,561),9674=>array(57,-233,545,807),9675=>array(3,-41,599,561),9676=>array(3,-41,599,561),9677=>array(3,-41,599,561),9678=>array(3,-41,599,561),9679=>array(3,-41,599,561),9680=>array(3,-41,599,561),9681=>array(3,-41,599,561),9682=>array(3,-41,599,561),9683=>array(3,-41,599,561),9684=>array(3,-41,599,561),9685=>array(3,-41,599,561),9686=>array(152,-41,450,561),9687=>array(152,-41,450,561),9688=>array(-10,-10,612,770),9689=>array(-10,-250,612,770),9690=>array(-10,260,612,770),9691=>array(-10,-250,612,260),9692=>array(152,260,450,561),9693=>array(152,260,450,561),9694=>array(152,-41,450,260),9695=>array(152,-41,450,260),9696=>array(3,260,599,561),9697=>array(3,-41,599,260),9698=>array(3,-39,599,558),9699=>array(3,-39,599,558),9700=>array(3,-39,599,558),9701=>array(3,-39,599,558),9702=>array(156,227,446,516),9703=>array(3,-39,599,558),9704=>array(3,-39,599,558),9705=>array(3,-39,599,558),9706=>array(3,-39,599,558),9707=>array(3,-39,599,558),9708=>array(3,-39,599,558),9709=>array(3,-39,599,558),9710=>array(3,-39,599,558),9711=>array(-10,-54,612,573),9712=>array(3,-39,599,558),9713=>array(3,-39,599,558),9714=>array(3,-39,599,558),9715=>array(3,-39,599,558),9716=>array(3,-41,599,561),9717=>array(3,-41,599,561),9718=>array(3,-41,599,561),9719=>array(3,-41,599,561),9720=>array(3,-39,599,558),9721=>array(3,-39,599,558),9722=>array(3,-39,599,558),9723=>array(47,6,554,513),9724=>array(47,6,554,513),9725=>array(85,44,516,475),9726=>array(85,44,516,475),9727=>array(3,-39,599,558),9728=>array(17,80,585,649),9729=>array(24,4,578,227),9730=>array(17,3,585,522),9731=>array(43,-3,559,708),9732=>array(14,23,588,681),9733=>array(28,7,574,525),9734=>array(28,10,574,528),9735=>array(98,2,504,729),9736=>array(29,0,573,731),9737=>array(21,3,581,563),9738=>array(7,2,595,639),9739=>array(9,-1,593,677),9740=>array(26,0,576,724),9741=>array(22,1,580,724),9742=>array(10,-0,592,598),9743=>array(4,5,598,598),9744=>array(54,2,548,504),9745=>array(48,-1,554,512),9746=>array(65,2,537,481),9747=>array(98,43,504,658),9748=>array(14,-2,588,651),9749=>array(38,3,564,688),9750=>array(27,3,575,734),9751=>array(23,1,579,728),9752=>array(19,3,583,596),9753=>array(23,203,579,557),9754=>array(23,132,579,560),9755=>array(23,132,579,560),9756=>array(7,138,595,516),9757=>array(68,0,534,724),9758=>array(7,138,595,516),9759=>array(68,-3,534,720),9760=>array(6,-1,596,593),9761=>array(4,-2,598,728),9762=>array(4,1,598,595),9763=>array(17,3,585,523),9764=>array(38,-0,564,671),9765=>array(47,-0,555,730),9766=>array(59,-1,543,731),9767=>array(47,3,555,751),9768=>array(100,-2,502,725),9769=>array(27,0,575,549),9770=>array(15,1,587,644),9771=>array(4,0,598,594),9772=>array(50,-3,552,669),9773=>array(7,2,595,642),9774=>array(13,2,589,578),9775=>array(7,2,595,591),9784=>array(13,82,589,642),9785=>array(16,80,586,650),9786=>array(16,80,586,650),9787=>array(16,80,586,650),9788=>array(16,80,586,650),9789=>array(76,2,526,722),9790=>array(73,3,529,734),9791=>array(92,-78,510,708),9792=>array(71,-49,531,655),9793=>array(71,-49,531,655),9794=>array(10,75,592,648),9795=>array(35,21,567,710),9796=>array(85,21,517,710),9797=>array(33,65,569,666),9798=>array(37,65,565,666),9799=>array(105,21,497,710),9800=>array(12,0,590,641),9801=>array(26,-4,576,596),9802=>array(13,6,589,601),9803=>array(25,24,577,632),9804=>array(30,-1,572,641),9805=>array(23,-136,579,562),9806=>array(42,88,561,614),9807=>array(24,-75,578,597),9808=>array(27,3,575,597),9809=>array(10,1,592,601),9810=>array(43,156,559,460),9811=>array(46,2,556,642),9812=>array(33,2,569,563),9813=>array(42,0,560,560),9814=>array(55,0,547,639),9815=>array(108,-4,494,596),9816=>array(70,3,532,597),9817=>array(76,3,526,551),9818=>array(52,-2,550,518),9819=>array(26,2,576,596),9820=>array(72,2,530,596),9821=>array(110,3,492,597),9822=>array(50,1,552,641),9823=>array(58,2,544,597),9824=>array(63,65,540,664),9825=>array(7,65,595,663),9826=>array(71,65,531,664),9827=>array(24,65,578,664),9828=>array(62,65,540,664),9829=>array(5,65,597,664),9830=>array(71,65,531,664),9831=>array(24,65,578,667),9832=>array(22,3,580,597),9833=>array(181,16,421,708),9834=>array(79,16,523,708),9835=>array(52,-79,550,706),9836=>array(8,61,594,664),9837=>array(158,18,444,710),9838=>array(211,21,391,710),9839=>array(152,21,450,710),9840=>array(47,-1,555,639),9841=>array(22,-8,580,632),9842=>array(23,-2,579,538),9843=>array(29,5,573,527),9844=>array(37,4,565,514),9845=>array(33,5,569,521),9846=>array(18,3,584,549),9847=>array(30,4,572,525),9848=>array(37,0,565,509),9849=>array(22,6,580,543),9850=>array(22,0,580,537),9851=>array(28,-0,574,528),9852=>array(22,3,580,561),9853=>array(27,2,575,550),9854=>array(22,3,580,561),9855=>array(39,4,563,643),9856=>array(29,2,573,546),9857=>array(29,2,573,546),9858=>array(29,2,573,546),9859=>array(29,0,573,544),9860=>array(29,2,573,546),9861=>array(29,-2,573,542),9862=>array(22,0,580,557),9863=>array(22,2,580,559),9864=>array(22,0,580,557),9865=>array(22,-5,580,552),9866=>array(40,3,562,73),9867=>array(40,3,562,73),9872=>array(73,-1,529,591),9873=>array(56,2,546,640),9874=>array(19,-0,583,520),9875=>array(15,0,587,603),9876=>array(63,6,539,553),9877=>array(92,-1,510,740),9878=>array(9,1,593,558),9879=>array(11,3,591,552),9880=>array(36,-1,566,640),9881=>array(15,0,587,603),9882=>array(21,6,582,656),9883=>array(40,5,562,597),9884=>array(21,-1,582,638),9888=>array(17,1,585,520),9889=>array(66,4,536,642),9904=>array(119,0,484,730),9905=>array(108,0,494,594),9985=>array(22,181,580,494),9986=>array(22,170,580,505),9987=>array(28,156,574,462),9988=>array(30,161,572,501),9990=>array(25,35,577,588),9991=>array(18,31,584,598),9992=>array(30,29,572,544),9993=>array(31,56,571,448),9996=>array(158,5,444,614),9997=>array(22,73,580,498),9998=>array(42,64,560,581),9999=>array(19,109,583,346),10000=>array(42,91,560,608),10001=>array(29,146,573,420),10002=>array(18,133,584,388),10003=>array(74,94,528,561),10004=>array(36,56,566,532),10005=>array(63,55,539,531),10006=>array(31,92,540,601),10007=>array(64,-10,538,593),10008=>array(25,-1,577,646),10009=>array(31,2,571,542),10010=>array(42,3,560,503),10011=>array(28,3,574,550),10012=>array(23,0,579,556),10013=>array(76,1,520,640),10014=>array(62,0,541,639),10015=>array(70,2,532,595),10016=>array(23,1,579,558),10017=>array(35,1,567,616),10018=>array(15,-10,587,562),10019=>array(14,-8,588,567),10020=>array(13,-9,589,567),10021=>array(11,-13,591,566),10022=>array(21,-12,581,552),10023=>array(18,-13,584,557),10025=>array(20,-8,583,527),10026=>array(33,-13,569,526),10027=>array(20,-13,583,522),10028=>array(17,-11,585,529),10029=>array(20,-8,583,527),10030=>array(30,-2,572,514),10031=>array(20,-5,583,531),10032=>array(22,8,580,502),10033=>array(26,-1,576,563),10034=>array(42,-0,560,547),10035=>array(23,-1,579,554),10036=>array(18,-8,584,560),10037=>array(13,-11,589,565),10038=>array(24,-14,578,625),10039=>array(15,-16,587,556),10040=>array(13,-11,589,565),10041=>array(18,-17,584,551),10042=>array(23,1,579,557),10043=>array(24,-8,578,613),10044=>array(27,-9,575,606),10045=>array(25,-10,573,609),10046=>array(16,-13,586,592),10047=>array(18,0,584,551),10048=>array(11,1,591,565),10049=>array(11,-9,591,572),10050=>array(18,-16,584,552),10051=>array(24,-9,578,653),10052=>array(16,1,586,667),10053=>array(23,-3,579,587),10054=>array(12,2,590,594),10055=>array(24,-9,578,605),10056=>array(20,-10,582,552),10057=>array(16,-14,586,556),10058=>array(11,-11,591,569),10059=>array(17,-11,585,513),10061=>array(18,-5,584,527),10063=>array(34,-31,568,504),10064=>array(30,0,572,542),10065=>array(27,-35,575,512),10066=>array(23,0,579,555),10070=>array(21,-3,581,557),10072=>array(263,-119,339,701),10073=>array(225,-120,377,700),10074=>array(165,-151,438,677),10075=>array(233,476,369,731),10076=>array(228,471,374,722),10077=>array(125,476,477,731),10078=>array(120,471,482,722),10081=>array(50,-80,552,688),10082=>array(125,-19,478,598),10083=>array(93,-14,509,603),10084=>array(22,51,580,507),10085=>array(56,-2,546,637),10086=>array(32,12,570,567),10087=>array(24,150,578,472),10088=>array(117,-49,485,688),10089=>array(117,-49,485,688),10090=>array(175,-59,427,665),10091=>array(179,-59,423,643),10092=>array(158,-64,444,667),10093=>array(158,-64,444,667),10094=>array(103,-83,500,647),10095=>array(103,-83,500,647),10096=>array(100,-93,502,727),10097=>array(101,-93,501,728),10098=>array(223,-138,379,683),10099=>array(223,-135,379,686),10100=>array(137,-160,465,671),10101=>array(122,-164,480,676),10132=>array(41,148,562,487),10136=>array(57,71,545,561),10137=>array(41,204,562,509),10138=>array(57,94,545,583),10139=>array(22,204,580,485),10140=>array(36,145,566,530),10141=>array(41,214,562,519),10142=>array(22,184,580,510),10143=>array(26,182,576,503),10144=>array(41,201,562,505),10145=>array(41,189,562,494),10146=>array(47,182,555,512),10147=>array(60,205,542,518),10148=>array(60,140,542,592),10149=>array(26,193,576,530),10150=>array(26,193,576,529),10151=>array(164,128,438,609),10152=>array(26,179,576,500),10153=>array(49,177,553,516),10154=>array(49,148,553,487),10155=>array(26,89,576,498),10156=>array(47,104,555,458),10157=>array(61,107,541,538),10158=>array(41,63,561,530),10159=>array(24,163,578,557),10161=>array(20,124,582,524),10162=>array(71,92,531,584),10163=>array(43,163,559,386),10164=>array(57,90,545,579),10165=>array(41,227,562,427),10166=>array(57,63,545,552),10167=>array(38,90,564,616),10168=>array(21,192,582,409),10169=>array(57,85,545,574),10170=>array(26,146,576,490),10171=>array(14,179,588,461),10172=>array(19,218,583,456),10173=>array(18,174,583,493),10174=>array(24,131,578,462),10178=>array(43,0,559,627),10181=>array(152,-163,450,769),10182=>array(152,-163,450,769),10208=>array(57,-233,545,807),10214=>array(145,-132,458,760),10215=>array(145,-132,457,760),10216=>array(190,-132,412,759),10217=>array(190,-132,412,759),10731=>array(57,-233,545,807),10746=>array(43,55,559,572),10747=>array(43,55,559,572),10799=>array(73,85,529,541),10858=>array(43,243,559,564),10859=>array(43,65,559,564),11013=>array(41,190,561,494),11014=>array(149,82,453,602),11015=>array(149,82,453,602),11016=>array(68,109,485,526),11017=>array(117,109,534,526),11018=>array(117,109,534,526),11019=>array(68,109,485,526),11020=>array(41,190,561,494),11021=>array(149,82,453,602),11026=>array(3,-39,599,558),11027=>array(3,-39,599,558),11028=>array(3,-39,599,558),11029=>array(3,-39,599,558),11030=>array(3,-39,599,558),11031=>array(3,-39,599,558),11032=>array(3,-39,599,558),11033=>array(3,-39,599,558),11034=>array(3,-39,599,558),11364=>array(70,-213,602,729),11373=>array(52,-14,540,742),11374=>array(42,-208,559,729),11375=>array(18,0,584,729),11376=>array(52,-14,540,742),11381=>array(67,0,535,729),11382=>array(95,0,513,547),11383=>array(37,-12,565,551),11385=>array(74,-13,461,760),11386=>array(67,-14,535,560),11388=>array(237,-117,365,426),11389=>array(129,326,473,734),11390=>array(68,-242,570,742),11391=>array(76,-242,571,729),11800=>array(94,-13,483,729),11807=>array(43,65,559,384),11810=>array(226,403,433,760),11811=>array(169,403,376,760),11812=>array(226,-132,433,225),11813=>array(169,-132,376,225),11822=>array(106,0,496,742),42760=>array(146,0,456,668),42761=>array(146,0,456,668),42762=>array(146,0,456,668),42763=>array(146,0,456,668),42764=>array(146,0,456,668),42765=>array(146,0,456,668),42766=>array(146,0,456,668),42767=>array(146,0,456,668),42768=>array(146,0,456,668),42769=>array(146,0,456,668),42770=>array(146,0,456,668),42771=>array(146,0,456,668),42772=>array(146,0,456,668),42773=>array(146,0,456,668),42774=>array(146,0,456,668),42779=>array(166,326,436,736),42780=>array(166,324,436,734),42781=>array(270,326,332,734),42782=>array(270,326,332,734),42783=>array(270,0,332,408),42786=>array(157,0,464,729),42787=>array(179,0,452,547),42788=>array(115,224,494,742),42789=>array(115,42,494,560),42790=>array(67,-208,535,729),42791=>array(95,-208,513,760),42889=>array(239,0,362,519),42890=>array(191,161,411,380),42891=>array(252,235,351,729),42892=>array(258,458,343,729),42893=>array(67,0,533,729),42894=>array(77,-208,525,765),42896=>array(41,-157,573,729),42897=>array(60,-140,546,560),42922=>array(10,0,585,729),63173=>array(67,-14,535,760),64257=>array(17,0,527,760),64258=>array(17,0,527,760),64338=>array(34,-244,586,263),64339=>array(34,-244,612,264),64340=>array(-10,-244,342,293),64341=>array(-10,-244,612,293),64342=>array(34,-244,586,263),64343=>array(34,-244,612,264),64344=>array(-10,-244,389,293),64345=>array(-10,-244,612,293),64346=>array(34,-244,586,263),64347=>array(34,-244,612,264),64348=>array(-10,-244,380,293),64349=>array(-10,-244,612,293),64350=>array(34,-10,586,467),64351=>array(34,-10,612,470),64352=>array(-10,0,342,559),64353=>array(-10,0,612,553),64354=>array(34,-10,586,513),64355=>array(34,-10,612,513),64356=>array(-10,0,390,559),64357=>array(-10,0,612,561),64358=>array(34,-10,586,542),64359=>array(34,-10,612,535),64360=>array(-10,0,465,620),64361=>array(-10,0,612,627),64362=>array(-36,-45,568,681),64363=>array(-73,-44,612,628),64364=>array(-10,0,406,757),64365=>array(-10,0,612,633),64366=>array(-36,-45,568,687),64367=>array(-73,-44,612,630),64368=>array(-10,0,406,757),64369=>array(-10,0,612,641),64370=>array(43,-244,584,425),64371=>array(43,-244,622,425),64372=>array(-10,-220,545,398),64373=>array(-10,-220,623,398),64374=>array(43,-244,584,425),64375=>array(43,-244,622,425),64376=>array(-10,-98,545,398),64377=>array(-10,-98,623,398),64378=>array(43,-244,584,425),64379=>array(43,-244,622,425),64380=>array(-10,-239,545,398),64381=>array(-10,-220,623,398),64382=>array(43,-244,584,425),64383=>array(43,-244,622,425),64384=>array(-10,-239,545,398),64385=>array(-10,-220,623,398),64394=>array(-25,-246,547,527),64395=>array(-78,-244,612,533),64396=>array(-25,-246,595,576),64397=>array(-78,-244,612,564),64398=>array(5,-43,670,760),64399=>array(-61,-43,638,760),64400=>array(-10,0,521,760),64401=>array(-10,0,612,760),64402=>array(5,-43,673,910),64403=>array(-61,-43,638,911),64404=>array(-10,0,521,903),64405=>array(-10,0,612,903),64414=>array(26,-162,569,336),64415=>array(-21,-244,612,256),64426=>array(0,-33,572,487),64427=>array(0,0,618,487),64428=>array(-10,-33,486,487),64429=>array(-10,0,618,487),64488=>array(-10,0,342,293),64489=>array(-10,0,612,293),64508=>array(12,-131,602,389),64509=>array(-64,-133,612,251),64510=>array(-10,-146,386,293),64511=>array(-10,-146,612,293),65136=>array(158,591,443,825),65137=>array(-10,0,612,825),65138=>array(158,591,443,874),65139=>array(392,0,612,177),65140=>array(158,-239,443,-5),65142=>array(158,591,443,708),65143=>array(-10,0,612,708),65144=>array(158,590,443,874),65145=>array(-10,0,612,874),65146=>array(158,-137,443,-20),65147=>array(-10,-137,612,90),65148=>array(148,599,453,869),65149=>array(-10,0,612,869),65150=>array(167,610,435,878),65151=>array(-10,0,612,878),65152=>array(212,42,522,483),65153=>array(125,0,477,939),65154=>array(125,0,612,939),65155=>array(212,0,380,1028),65156=>array(236,0,612,1028),65157=>array(37,-244,525,588),65158=>array(44,-244,612,588),65159=>array(214,-244,381,760),65160=>array(259,-244,612,760),65161=>array(12,-131,602,542),65162=>array(-64,-133,612,421),65163=>array(-10,0,374,613),65164=>array(-10,0,612,613),65165=>array(256,0,346,760),65166=>array(287,0,612,760),65167=>array(34,-171,586,263),65168=>array(34,-171,612,264),65169=>array(-10,-146,342,293),65170=>array(-10,-146,612,293),65171=>array(108,-28,494,513),65172=>array(118,0,612,513),65173=>array(34,-10,586,391),65174=>array(34,-10,612,391),65175=>array(-10,0,392,488),65176=>array(-10,0,612,488),65177=>array(34,-10,586,513),65178=>array(34,-10,612,513),65179=>array(-10,0,396,610),65180=>array(-10,0,612,592),65181=>array(43,-244,584,425),65182=>array(43,-244,622,425),65183=>array(-10,-146,545,398),65184=>array(-10,-146,623,398),65185=>array(43,-244,584,425),65186=>array(43,-244,622,425),65187=>array(-10,0,545,398),65188=>array(-10,0,623,398),65189=>array(43,-244,584,586),65190=>array(43,-244,622,586),65191=>array(-10,0,545,537),65192=>array(-10,0,623,537),65193=>array(113,-19,488,427),65194=>array(113,-19,612,427),65195=>array(113,-19,488,586),65196=>array(113,-19,612,586),65197=>array(-25,-246,533,267),65198=>array(-78,-244,612,269),65199=>array(-25,-246,533,464),65200=>array(-78,-244,612,464),65201=>array(-107,-240,574,366),65202=>array(-145,-240,612,366),65203=>array(-10,-17,572,363),65204=>array(-10,-17,612,363),65205=>array(-107,-240,574,586),65206=>array(-145,-240,612,586),65207=>array(-10,-17,572,586),65208=>array(-10,-17,612,586),65209=>array(-117,-240,594,320),65210=>array(-154,-240,612,320),65211=>array(-10,0,594,320),65212=>array(-10,0,612,320),65213=>array(-117,-240,594,400),65214=>array(-154,-240,612,400),65215=>array(-10,0,594,433),65216=>array(-10,0,612,426),65217=>array(5,0,580,760),65218=>array(10,0,612,760),65219=>array(-10,0,580,760),65220=>array(-10,0,612,760),65221=>array(5,0,580,760),65222=>array(10,0,612,760),65223=>array(-10,0,580,760),65224=>array(-10,0,612,760),65225=>array(60,-244,589,521),65226=>array(72,-244,619,382),65227=>array(-10,0,497,521),65228=>array(-10,0,612,382),65229=>array(60,-244,589,659),65230=>array(72,-244,619,537),65231=>array(-10,0,497,659),65232=>array(-10,0,612,537),65233=>array(-36,-45,568,594),65234=>array(-73,-44,612,537),65235=>array(-10,0,406,635),65236=>array(-10,0,612,562),65237=>array(15,-189,557,635),65238=>array(-9,-240,612,500),65239=>array(-10,0,406,635),65240=>array(-10,0,612,562),65241=>array(4,-27,578,760),65242=>array(-46,-27,612,760),65243=>array(-10,0,521,760),65244=>array(-10,0,612,760),65245=>array(33,-152,537,760),65246=>array(5,-152,612,760),65247=>array(-10,0,489,760),65248=>array(-10,0,612,760),65249=>array(63,-240,541,369),65250=>array(35,-240,612,307),65251=>array(-10,-24,456,303),65252=>array(-10,-24,612,303),65253=>array(26,-162,569,439),65254=>array(-21,-244,612,335),65255=>array(-10,0,342,488),65256=>array(-10,0,612,488),65257=>array(108,-28,494,358),65258=>array(118,0,612,366),65259=>array(-10,-33,486,487),65260=>array(-10,-244,612,333),65261=>array(37,-244,525,315),65262=>array(44,-244,612,315),65263=>array(12,-131,602,389),65264=>array(-64,-133,612,251),65265=>array(12,-244,602,389),65266=>array(-64,-244,612,251),65267=>array(-10,-146,384,293),65268=>array(-10,-146,612,293),65269=>array(-52,-10,515,866),65270=>array(-94,-10,612,866),65271=>array(41,-10,515,955),65272=>array(-16,-10,612,955),65273=>array(65,-244,515,760),65274=>array(46,-244,612,760),65275=>array(87,-10,515,760),65276=>array(46,-10,612,760),65533=>array(40,-84,562,887),65535=>array(51,-177,551,705)); -$cw=array(0=>602,32=>602,33=>602,34=>602,35=>602,36=>602,37=>602,38=>602,39=>602,40=>602,41=>602,42=>602,43=>602,44=>602,45=>602,46=>602,47=>602,48=>602,49=>602,50=>602,51=>602,52=>602,53=>602,54=>602,55=>602,56=>602,57=>602,58=>602,59=>602,60=>602,61=>602,62=>602,63=>602,64=>602,65=>602,66=>602,67=>602,68=>602,69=>602,70=>602,71=>602,72=>602,73=>602,74=>602,75=>602,76=>602,77=>602,78=>602,79=>602,80=>602,81=>602,82=>602,83=>602,84=>602,85=>602,86=>602,87=>602,88=>602,89=>602,90=>602,91=>602,92=>602,93=>602,94=>602,95=>602,96=>602,97=>602,98=>602,99=>602,100=>602,101=>602,102=>602,103=>602,104=>602,105=>602,106=>602,107=>602,108=>602,109=>602,110=>602,111=>602,112=>602,113=>602,114=>602,115=>602,116=>602,117=>602,118=>602,119=>602,120=>602,121=>602,122=>602,123=>602,124=>602,125=>602,126=>602,160=>602,161=>602,162=>602,163=>602,164=>602,165=>602,166=>602,167=>602,168=>602,169=>602,170=>602,171=>602,172=>602,173=>602,174=>602,175=>602,176=>602,177=>602,178=>602,179=>602,180=>602,181=>602,182=>602,183=>602,184=>602,185=>602,186=>602,187=>602,188=>602,189=>602,190=>602,191=>602,192=>602,193=>602,194=>602,195=>602,196=>602,197=>602,198=>602,199=>602,200=>602,201=>602,202=>602,203=>602,204=>602,205=>602,206=>602,207=>602,208=>602,209=>602,210=>602,211=>602,212=>602,213=>602,214=>602,215=>602,216=>602,217=>602,218=>602,219=>602,220=>602,221=>602,222=>602,223=>602,224=>602,225=>602,226=>602,227=>602,228=>602,229=>602,230=>602,231=>602,232=>602,233=>602,234=>602,235=>602,236=>602,237=>602,238=>602,239=>602,240=>602,241=>602,242=>602,243=>602,244=>602,245=>602,246=>602,247=>602,248=>602,249=>602,250=>602,251=>602,252=>602,253=>602,254=>602,255=>602,256=>602,257=>602,258=>602,259=>602,260=>602,261=>602,262=>602,263=>602,264=>602,265=>602,266=>602,267=>602,268=>602,269=>602,270=>602,271=>602,272=>602,273=>602,274=>602,275=>602,276=>602,277=>602,278=>602,279=>602,280=>602,281=>602,282=>602,283=>602,284=>602,285=>602,286=>602,287=>602,288=>602,289=>602,290=>602,291=>602,292=>602,293=>602,294=>602,295=>602,296=>602,297=>602,298=>602,299=>602,300=>602,301=>602,302=>602,303=>602,304=>602,305=>602,306=>602,307=>602,308=>602,309=>602,310=>602,311=>602,312=>602,313=>602,314=>602,315=>602,316=>602,317=>602,318=>602,319=>602,320=>602,321=>602,322=>602,323=>602,324=>602,325=>602,326=>602,327=>602,328=>602,329=>602,330=>602,331=>602,332=>602,333=>602,334=>602,335=>602,336=>602,337=>602,338=>602,339=>602,340=>602,341=>602,342=>602,343=>602,344=>602,345=>602,346=>602,347=>602,348=>602,349=>602,350=>602,351=>602,352=>602,353=>602,354=>602,355=>602,356=>602,357=>602,358=>602,359=>602,360=>602,361=>602,362=>602,363=>602,364=>602,365=>602,366=>602,367=>602,368=>602,369=>602,370=>602,371=>602,372=>602,373=>602,374=>602,375=>602,376=>602,377=>602,378=>602,379=>602,380=>602,381=>602,382=>602,383=>602,384=>602,385=>602,386=>602,387=>602,388=>602,389=>602,390=>602,391=>602,392=>602,393=>602,394=>602,395=>602,396=>602,397=>602,398=>602,399=>602,400=>602,401=>602,402=>602,403=>602,404=>602,405=>602,406=>602,407=>602,408=>602,409=>602,410=>602,411=>602,412=>602,413=>602,414=>602,415=>602,416=>602,417=>602,418=>602,419=>602,420=>602,421=>602,422=>602,423=>602,424=>602,425=>602,426=>602,427=>602,428=>602,429=>602,430=>602,431=>602,432=>602,433=>602,434=>602,435=>602,436=>602,437=>602,438=>602,439=>602,440=>602,441=>602,442=>602,443=>602,444=>602,445=>602,446=>602,447=>602,448=>602,449=>602,450=>602,451=>602,461=>602,462=>602,463=>602,464=>602,465=>602,466=>602,467=>602,468=>602,469=>602,470=>602,471=>602,472=>602,473=>602,474=>602,475=>602,476=>602,477=>602,478=>602,479=>602,480=>602,481=>602,482=>602,483=>602,486=>602,487=>602,488=>602,489=>602,490=>602,491=>602,492=>602,493=>602,494=>602,495=>602,496=>602,500=>602,501=>602,502=>602,504=>602,505=>602,508=>602,509=>602,510=>602,511=>602,512=>602,513=>602,514=>602,515=>602,516=>602,517=>602,518=>602,519=>602,520=>602,521=>602,522=>602,523=>602,524=>602,525=>602,526=>602,527=>602,528=>602,529=>602,530=>602,531=>602,532=>602,533=>602,534=>602,535=>602,536=>602,537=>602,538=>602,539=>602,540=>602,541=>602,542=>602,543=>602,544=>602,545=>602,548=>602,549=>602,550=>602,551=>602,552=>602,553=>602,554=>602,555=>602,556=>602,557=>602,558=>602,559=>602,560=>602,561=>602,562=>602,563=>602,564=>602,565=>602,566=>602,567=>602,568=>602,569=>602,570=>602,571=>602,572=>602,573=>602,574=>602,575=>602,576=>602,577=>602,579=>602,580=>602,581=>602,588=>602,589=>602,592=>602,593=>602,594=>602,595=>602,596=>602,597=>602,598=>602,599=>602,600=>602,601=>602,602=>602,603=>602,604=>602,605=>602,606=>602,607=>602,608=>602,609=>602,610=>602,611=>602,612=>602,613=>602,614=>602,615=>602,616=>602,617=>602,618=>602,619=>602,620=>602,621=>602,622=>602,623=>602,624=>602,625=>602,626=>602,627=>602,628=>602,629=>602,630=>602,631=>602,632=>602,633=>602,634=>602,635=>602,636=>602,637=>602,638=>602,639=>602,640=>602,641=>602,642=>602,643=>602,644=>602,645=>602,646=>602,647=>602,648=>602,649=>602,650=>602,651=>602,652=>602,653=>602,654=>602,655=>602,656=>602,657=>602,658=>602,659=>602,660=>602,661=>602,662=>602,663=>602,664=>602,665=>602,666=>602,667=>602,668=>602,669=>602,670=>602,671=>602,672=>602,673=>602,674=>602,675=>602,676=>602,677=>602,678=>602,679=>602,680=>602,681=>602,682=>602,683=>602,684=>602,685=>602,686=>602,687=>602,688=>602,689=>602,690=>602,691=>602,692=>602,693=>602,694=>602,695=>602,696=>602,697=>602,699=>602,700=>602,701=>602,702=>602,703=>602,704=>602,705=>602,710=>602,711=>602,712=>602,713=>602,716=>602,717=>602,718=>602,719=>602,720=>602,721=>602,722=>602,723=>602,726=>602,727=>602,728=>602,729=>602,730=>602,731=>602,732=>602,733=>602,734=>602,736=>602,737=>602,738=>602,739=>602,740=>602,741=>602,742=>602,743=>602,744=>602,745=>602,750=>602,755=>602,768=>602,769=>602,770=>602,771=>602,772=>602,773=>602,774=>602,775=>602,776=>602,777=>602,778=>602,779=>602,780=>602,781=>602,782=>602,783=>602,784=>602,785=>602,786=>602,787=>602,788=>602,789=>602,790=>602,791=>602,792=>602,793=>602,794=>602,795=>602,796=>602,797=>602,798=>602,799=>602,800=>602,801=>602,802=>602,803=>602,804=>602,805=>602,806=>602,807=>602,808=>602,809=>602,810=>602,811=>602,812=>602,813=>602,814=>602,815=>602,816=>602,817=>602,818=>602,819=>602,820=>602,821=>602,822=>602,823=>602,824=>602,825=>602,826=>602,827=>602,828=>602,829=>602,830=>602,831=>602,835=>602,856=>602,865=>602,884=>602,885=>602,890=>602,894=>602,900=>602,901=>602,902=>602,903=>602,904=>602,905=>602,906=>602,908=>602,910=>602,911=>602,912=>602,913=>602,914=>602,915=>602,916=>602,917=>602,918=>602,919=>602,920=>602,921=>602,922=>602,923=>602,924=>602,925=>602,926=>602,927=>602,928=>602,929=>602,931=>602,932=>602,933=>602,934=>602,935=>602,936=>602,937=>602,938=>602,939=>602,940=>602,941=>602,942=>602,943=>602,944=>602,945=>602,946=>602,947=>602,948=>602,949=>602,950=>602,951=>602,952=>602,953=>602,954=>602,955=>602,956=>602,957=>602,958=>602,959=>602,960=>602,961=>602,962=>602,963=>602,964=>602,965=>602,966=>602,967=>602,968=>602,969=>602,970=>602,971=>602,972=>602,973=>602,974=>602,976=>602,977=>602,978=>602,979=>602,980=>602,981=>602,982=>602,983=>602,984=>602,985=>602,986=>602,987=>602,988=>602,989=>602,990=>602,991=>602,992=>602,993=>602,1008=>602,1009=>602,1010=>602,1011=>602,1012=>602,1013=>602,1014=>602,1015=>602,1016=>602,1017=>602,1018=>602,1019=>602,1020=>602,1021=>602,1022=>602,1023=>602,1024=>602,1025=>602,1026=>602,1027=>602,1028=>602,1029=>602,1030=>602,1031=>602,1032=>602,1033=>602,1034=>602,1035=>602,1036=>602,1037=>602,1038=>602,1039=>602,1040=>602,1041=>602,1042=>602,1043=>602,1044=>602,1045=>602,1046=>602,1047=>602,1048=>602,1049=>602,1050=>602,1051=>602,1052=>602,1053=>602,1054=>602,1055=>602,1056=>602,1057=>602,1058=>602,1059=>602,1060=>602,1061=>602,1062=>602,1063=>602,1064=>602,1065=>602,1066=>602,1067=>602,1068=>602,1069=>602,1070=>602,1071=>602,1072=>602,1073=>602,1074=>602,1075=>602,1076=>602,1077=>602,1078=>602,1079=>602,1080=>602,1081=>602,1082=>602,1083=>602,1084=>602,1085=>602,1086=>602,1087=>602,1088=>602,1089=>602,1090=>602,1091=>602,1092=>602,1093=>602,1094=>602,1095=>602,1096=>602,1097=>602,1098=>602,1099=>602,1100=>602,1101=>602,1102=>602,1103=>602,1104=>602,1105=>602,1106=>602,1107=>602,1108=>602,1109=>602,1110=>602,1111=>602,1112=>602,1113=>602,1114=>602,1115=>602,1116=>602,1117=>602,1118=>602,1119=>602,1122=>602,1123=>602,1138=>602,1139=>602,1168=>602,1169=>602,1170=>602,1171=>602,1172=>602,1173=>602,1174=>602,1175=>602,1176=>602,1177=>602,1178=>602,1179=>602,1186=>602,1187=>602,1188=>602,1189=>602,1194=>602,1195=>602,1196=>602,1197=>602,1198=>602,1199=>602,1200=>602,1201=>602,1202=>602,1203=>602,1210=>602,1211=>602,1216=>602,1217=>602,1218=>602,1219=>602,1220=>602,1223=>602,1224=>602,1227=>602,1228=>602,1231=>602,1232=>602,1233=>602,1234=>602,1235=>602,1236=>602,1237=>602,1238=>602,1239=>602,1240=>602,1241=>602,1242=>602,1243=>602,1244=>602,1245=>602,1246=>602,1247=>602,1248=>602,1249=>602,1250=>602,1251=>602,1252=>602,1253=>602,1254=>602,1255=>602,1256=>602,1257=>602,1258=>602,1259=>602,1260=>602,1261=>602,1262=>602,1263=>602,1264=>602,1265=>602,1266=>602,1267=>602,1268=>602,1269=>602,1270=>602,1271=>602,1272=>602,1273=>602,1296=>602,1297=>602,1306=>602,1307=>602,1308=>602,1309=>602,1329=>602,1330=>602,1331=>602,1332=>602,1333=>602,1334=>602,1335=>602,1336=>602,1337=>602,1338=>602,1339=>602,1340=>602,1341=>602,1342=>602,1343=>602,1344=>602,1345=>602,1346=>602,1347=>602,1348=>602,1349=>602,1350=>602,1351=>602,1352=>602,1353=>602,1354=>602,1355=>602,1356=>602,1357=>602,1358=>602,1359=>602,1360=>602,1361=>602,1362=>602,1363=>602,1364=>602,1365=>602,1366=>602,1369=>602,1370=>602,1371=>602,1372=>602,1373=>602,1374=>602,1375=>602,1377=>602,1378=>602,1379=>602,1380=>602,1381=>602,1382=>602,1383=>602,1384=>602,1385=>602,1386=>602,1387=>602,1388=>602,1389=>602,1390=>602,1391=>602,1392=>602,1393=>602,1394=>602,1395=>602,1396=>602,1397=>602,1398=>602,1399=>602,1400=>602,1401=>602,1402=>602,1403=>602,1404=>602,1405=>602,1406=>602,1407=>602,1408=>602,1409=>602,1410=>602,1411=>602,1412=>602,1413=>602,1414=>602,1415=>602,1417=>602,1418=>602,1542=>602,1543=>602,1545=>602,1546=>602,1548=>602,1557=>602,1563=>602,1567=>602,1569=>602,1570=>602,1571=>602,1572=>602,1573=>602,1574=>602,1575=>602,1576=>602,1577=>602,1578=>602,1579=>602,1580=>602,1581=>602,1582=>602,1583=>602,1584=>602,1585=>602,1586=>602,1587=>602,1588=>602,1589=>602,1590=>602,1591=>602,1592=>602,1593=>602,1594=>602,1600=>602,1601=>602,1602=>602,1603=>602,1604=>602,1605=>602,1606=>602,1607=>602,1608=>602,1609=>602,1610=>602,1611=>602,1612=>602,1613=>602,1614=>602,1615=>602,1616=>602,1617=>602,1618=>602,1619=>602,1620=>602,1621=>602,1626=>602,1632=>602,1633=>602,1634=>602,1635=>602,1636=>602,1637=>602,1638=>602,1639=>602,1640=>602,1641=>602,1642=>602,1643=>602,1644=>602,1645=>602,1652=>602,1657=>602,1658=>602,1659=>602,1662=>602,1663=>602,1664=>602,1667=>602,1668=>602,1670=>602,1671=>602,1681=>602,1688=>602,1700=>602,1705=>602,1711=>602,1726=>602,1740=>602,1776=>602,1777=>602,1778=>602,1779=>602,1780=>602,1781=>602,1782=>602,1783=>602,1784=>602,1785=>602,3713=>602,3714=>602,3716=>602,3719=>602,3720=>602,3722=>602,3725=>602,3732=>602,3733=>602,3734=>602,3735=>602,3737=>602,3738=>602,3739=>602,3740=>602,3741=>602,3742=>602,3743=>602,3745=>602,3746=>602,3747=>602,3749=>602,3751=>602,3754=>602,3755=>602,3757=>602,3758=>602,3759=>602,3760=>602,3761=>602,3762=>602,3763=>602,3764=>602,3765=>602,3766=>602,3767=>602,3768=>602,3769=>602,3771=>602,3772=>602,3784=>602,3785=>602,3786=>602,3787=>602,3788=>602,3789=>602,4304=>602,4305=>602,4306=>602,4307=>602,4308=>602,4309=>602,4310=>602,4311=>602,4312=>602,4313=>602,4314=>602,4315=>602,4316=>602,4317=>602,4318=>602,4319=>602,4320=>602,4321=>602,4322=>602,4323=>602,4324=>602,4325=>602,4326=>602,4327=>602,4328=>602,4329=>602,4330=>602,4331=>602,4332=>602,4333=>602,4334=>602,4335=>602,4336=>602,4337=>602,4338=>602,4339=>602,4340=>602,4341=>602,4342=>602,4343=>602,4344=>602,4345=>602,4346=>602,4347=>602,4348=>602,7426=>602,7432=>602,7433=>602,7444=>602,7446=>602,7447=>602,7453=>602,7454=>602,7455=>602,7468=>602,7469=>602,7470=>602,7472=>602,7473=>602,7474=>602,7475=>602,7476=>602,7477=>602,7478=>602,7479=>602,7480=>602,7481=>602,7482=>602,7483=>602,7484=>602,7486=>602,7487=>602,7488=>602,7489=>602,7490=>602,7491=>602,7492=>602,7493=>602,7494=>602,7495=>602,7496=>602,7497=>602,7498=>602,7499=>602,7500=>602,7501=>602,7502=>602,7503=>602,7504=>602,7505=>602,7506=>602,7507=>602,7508=>602,7509=>602,7510=>602,7511=>602,7512=>602,7513=>602,7514=>602,7515=>602,7522=>602,7523=>602,7524=>602,7525=>602,7543=>602,7544=>602,7547=>602,7557=>602,7579=>602,7580=>602,7581=>602,7582=>602,7583=>602,7584=>602,7585=>602,7586=>602,7587=>602,7588=>602,7589=>602,7590=>602,7591=>602,7592=>602,7593=>602,7594=>602,7595=>602,7596=>602,7597=>602,7598=>602,7599=>602,7600=>602,7601=>602,7602=>602,7603=>602,7604=>602,7605=>602,7606=>602,7607=>602,7609=>602,7610=>602,7611=>602,7612=>602,7613=>602,7614=>602,7615=>602,7680=>602,7681=>602,7682=>602,7683=>602,7684=>602,7685=>602,7686=>602,7687=>602,7688=>602,7689=>602,7690=>602,7691=>602,7692=>602,7693=>602,7694=>602,7695=>602,7696=>602,7697=>602,7698=>602,7699=>602,7704=>602,7705=>602,7706=>602,7707=>602,7708=>602,7709=>602,7710=>602,7711=>602,7712=>602,7713=>602,7714=>602,7715=>602,7716=>602,7717=>602,7718=>602,7719=>602,7720=>602,7721=>602,7722=>602,7723=>602,7724=>602,7725=>602,7728=>602,7729=>602,7730=>602,7731=>602,7732=>602,7733=>602,7734=>602,7735=>602,7736=>602,7737=>602,7738=>602,7739=>602,7740=>602,7741=>602,7742=>602,7743=>602,7744=>602,7745=>602,7746=>602,7747=>602,7748=>602,7749=>602,7750=>602,7751=>602,7752=>602,7753=>602,7754=>602,7755=>602,7756=>602,7757=>602,7764=>602,7765=>602,7766=>602,7767=>602,7768=>602,7769=>602,7770=>602,7771=>602,7772=>602,7773=>602,7774=>602,7775=>602,7776=>602,7777=>602,7778=>602,7779=>602,7784=>602,7785=>602,7786=>602,7787=>602,7788=>602,7789=>602,7790=>602,7791=>602,7792=>602,7793=>602,7794=>602,7795=>602,7796=>602,7797=>602,7798=>602,7799=>602,7800=>602,7801=>602,7804=>602,7805=>602,7806=>602,7807=>602,7808=>602,7809=>602,7810=>602,7811=>602,7812=>602,7813=>602,7814=>602,7815=>602,7816=>602,7817=>602,7818=>602,7819=>602,7820=>602,7821=>602,7822=>602,7823=>602,7824=>602,7825=>602,7826=>602,7827=>602,7828=>602,7829=>602,7830=>602,7831=>602,7832=>602,7833=>602,7835=>602,7839=>602,7840=>602,7841=>602,7852=>602,7853=>602,7856=>602,7857=>602,7862=>602,7863=>602,7864=>602,7865=>602,7868=>602,7869=>602,7878=>602,7879=>602,7882=>602,7883=>602,7884=>602,7885=>602,7896=>602,7897=>602,7898=>602,7899=>602,7900=>602,7901=>602,7904=>602,7905=>602,7906=>602,7907=>602,7908=>602,7909=>602,7912=>602,7913=>602,7914=>602,7915=>602,7918=>602,7919=>602,7920=>602,7921=>602,7922=>602,7923=>602,7924=>602,7925=>602,7928=>602,7929=>602,7936=>602,7937=>602,7938=>602,7939=>602,7940=>602,7941=>602,7942=>602,7943=>602,7944=>602,7945=>602,7946=>602,7947=>602,7948=>602,7949=>602,7950=>602,7951=>602,7952=>602,7953=>602,7954=>602,7955=>602,7956=>602,7957=>602,7960=>602,7961=>602,7962=>602,7963=>602,7964=>602,7965=>602,7968=>602,7969=>602,7970=>602,7971=>602,7972=>602,7973=>602,7974=>602,7975=>602,7976=>602,7977=>602,7978=>602,7979=>602,7980=>602,7981=>602,7982=>602,7983=>602,7984=>602,7985=>602,7986=>602,7987=>602,7988=>602,7989=>602,7990=>602,7991=>602,7992=>602,7993=>602,7994=>602,7995=>602,7996=>602,7997=>602,7998=>602,7999=>602,8000=>602,8001=>602,8002=>602,8003=>602,8004=>602,8005=>602,8008=>602,8009=>602,8010=>602,8011=>602,8012=>602,8013=>602,8016=>602,8017=>602,8018=>602,8019=>602,8020=>602,8021=>602,8022=>602,8023=>602,8025=>602,8027=>602,8029=>602,8031=>602,8032=>602,8033=>602,8034=>602,8035=>602,8036=>602,8037=>602,8038=>602,8039=>602,8040=>602,8041=>602,8042=>602,8043=>602,8044=>602,8045=>602,8046=>602,8047=>602,8048=>602,8049=>602,8050=>602,8051=>602,8052=>602,8053=>602,8054=>602,8055=>602,8056=>602,8057=>602,8058=>602,8059=>602,8060=>602,8061=>602,8064=>602,8065=>602,8066=>602,8067=>602,8068=>602,8069=>602,8070=>602,8071=>602,8072=>602,8073=>602,8074=>602,8075=>602,8076=>602,8077=>602,8078=>602,8079=>602,8080=>602,8081=>602,8082=>602,8083=>602,8084=>602,8085=>602,8086=>602,8087=>602,8088=>602,8089=>602,8090=>602,8091=>602,8092=>602,8093=>602,8094=>602,8095=>602,8096=>602,8097=>602,8098=>602,8099=>602,8100=>602,8101=>602,8102=>602,8103=>602,8104=>602,8105=>602,8106=>602,8107=>602,8108=>602,8109=>602,8110=>602,8111=>602,8112=>602,8113=>602,8114=>602,8115=>602,8116=>602,8118=>602,8119=>602,8120=>602,8121=>602,8122=>602,8123=>602,8124=>602,8125=>602,8126=>602,8127=>602,8128=>602,8129=>602,8130=>602,8131=>602,8132=>602,8134=>602,8135=>602,8136=>602,8137=>602,8138=>602,8139=>602,8140=>602,8141=>602,8142=>602,8143=>602,8144=>602,8145=>602,8146=>602,8147=>602,8150=>602,8151=>602,8152=>602,8153=>602,8154=>602,8155=>602,8157=>602,8158=>602,8159=>602,8160=>602,8161=>602,8162=>602,8163=>602,8164=>602,8165=>602,8166=>602,8167=>602,8168=>602,8169=>602,8170=>602,8171=>602,8172=>602,8173=>602,8174=>602,8175=>602,8178=>602,8179=>602,8180=>602,8182=>602,8183=>602,8184=>602,8185=>602,8186=>602,8187=>602,8188=>602,8189=>602,8190=>602,8192=>602,8193=>602,8194=>602,8195=>602,8196=>602,8197=>602,8198=>602,8199=>602,8200=>602,8201=>602,8202=>602,8208=>602,8209=>602,8210=>602,8211=>602,8212=>602,8213=>602,8214=>602,8215=>602,8216=>602,8217=>602,8218=>602,8219=>602,8220=>602,8221=>602,8222=>602,8223=>602,8224=>602,8225=>602,8226=>602,8227=>602,8230=>602,8239=>602,8240=>602,8241=>602,8242=>602,8243=>602,8244=>602,8245=>602,8246=>602,8247=>602,8249=>602,8250=>602,8252=>602,8253=>602,8254=>602,8261=>602,8262=>602,8263=>602,8264=>602,8265=>602,8267=>602,8287=>602,8304=>602,8305=>602,8308=>602,8309=>602,8310=>602,8311=>602,8312=>602,8313=>602,8314=>602,8315=>602,8316=>602,8317=>602,8318=>602,8319=>602,8320=>602,8321=>602,8322=>602,8323=>602,8324=>602,8325=>602,8326=>602,8327=>602,8328=>602,8329=>602,8330=>602,8331=>602,8332=>602,8333=>602,8334=>602,8336=>602,8337=>602,8338=>602,8339=>602,8340=>602,8341=>602,8342=>602,8343=>602,8344=>602,8345=>602,8346=>602,8347=>602,8348=>602,8352=>602,8353=>602,8354=>602,8355=>602,8356=>602,8357=>602,8358=>602,8359=>602,8360=>602,8361=>602,8362=>602,8363=>602,8364=>602,8365=>602,8366=>602,8367=>602,8368=>602,8369=>602,8370=>602,8371=>602,8372=>602,8373=>602,8376=>602,8377=>602,8450=>602,8453=>602,8461=>602,8462=>602,8463=>602,8469=>602,8470=>602,8471=>602,8473=>602,8474=>602,8477=>602,8482=>602,8484=>602,8486=>602,8490=>602,8491=>602,8494=>602,8520=>602,8531=>602,8532=>602,8533=>602,8534=>602,8535=>602,8536=>602,8537=>602,8538=>602,8539=>602,8540=>602,8541=>602,8542=>602,8543=>602,8592=>602,8593=>602,8594=>602,8595=>602,8596=>602,8597=>602,8598=>602,8599=>602,8600=>602,8601=>602,8602=>602,8603=>602,8604=>602,8605=>602,8606=>602,8607=>602,8608=>602,8609=>602,8610=>602,8611=>602,8612=>602,8613=>602,8614=>602,8615=>602,8616=>602,8617=>602,8618=>602,8619=>602,8620=>602,8621=>602,8622=>602,8623=>602,8624=>602,8625=>602,8626=>602,8627=>602,8628=>602,8629=>602,8630=>602,8631=>602,8632=>602,8633=>602,8634=>602,8635=>602,8636=>602,8637=>602,8638=>602,8639=>602,8640=>602,8641=>602,8642=>602,8643=>602,8644=>602,8645=>602,8646=>602,8647=>602,8648=>602,8649=>602,8650=>602,8651=>602,8652=>602,8653=>602,8654=>602,8655=>602,8656=>602,8657=>602,8658=>602,8659=>602,8660=>602,8661=>602,8662=>602,8663=>602,8664=>602,8665=>602,8666=>602,8667=>602,8668=>602,8669=>602,8670=>602,8671=>602,8672=>602,8673=>602,8674=>602,8675=>602,8676=>602,8677=>602,8678=>602,8679=>602,8680=>602,8681=>602,8682=>602,8683=>602,8684=>602,8685=>602,8686=>602,8687=>602,8688=>602,8689=>602,8690=>602,8691=>602,8692=>602,8693=>602,8694=>602,8695=>602,8696=>602,8697=>602,8698=>602,8699=>602,8700=>602,8701=>602,8702=>602,8703=>602,8704=>602,8705=>602,8706=>602,8707=>602,8708=>602,8709=>602,8710=>602,8711=>602,8712=>602,8713=>602,8714=>602,8715=>602,8716=>602,8717=>602,8719=>602,8721=>602,8722=>602,8723=>602,8725=>602,8727=>602,8728=>602,8729=>602,8730=>602,8731=>602,8732=>602,8733=>602,8734=>602,8735=>602,8736=>602,8743=>602,8744=>602,8745=>602,8746=>602,8747=>602,8748=>602,8749=>602,8756=>602,8757=>602,8758=>602,8759=>602,8760=>602,8761=>602,8762=>602,8763=>602,8764=>602,8765=>602,8769=>602,8770=>602,8771=>602,8772=>602,8773=>602,8774=>602,8775=>602,8776=>602,8777=>602,8778=>602,8779=>602,8780=>602,8781=>602,8782=>602,8783=>602,8784=>602,8785=>602,8786=>602,8787=>602,8788=>602,8789=>602,8790=>602,8791=>602,8792=>602,8793=>602,8794=>602,8795=>602,8796=>602,8797=>602,8798=>602,8799=>602,8800=>602,8801=>602,8802=>602,8803=>602,8804=>602,8805=>602,8806=>602,8807=>602,8808=>602,8809=>602,8813=>602,8814=>602,8815=>602,8816=>602,8817=>602,8818=>602,8819=>602,8820=>602,8821=>602,8822=>602,8823=>602,8824=>602,8825=>602,8826=>602,8827=>602,8828=>602,8829=>602,8830=>602,8831=>602,8832=>602,8833=>602,8834=>602,8835=>602,8836=>602,8837=>602,8838=>602,8839=>602,8840=>602,8841=>602,8842=>602,8843=>602,8847=>602,8848=>602,8849=>602,8850=>602,8853=>602,8854=>602,8855=>602,8856=>602,8857=>602,8858=>602,8859=>602,8860=>602,8861=>602,8862=>602,8863=>602,8864=>602,8865=>602,8866=>602,8867=>602,8868=>602,8869=>602,8901=>602,8902=>602,8909=>602,8922=>602,8923=>602,8924=>602,8925=>602,8926=>602,8927=>602,8928=>602,8929=>602,8930=>602,8931=>602,8932=>602,8933=>602,8934=>602,8935=>602,8936=>602,8937=>602,8943=>602,8960=>602,8961=>602,8962=>602,8963=>602,8964=>602,8965=>602,8966=>602,8968=>602,8969=>602,8970=>602,8971=>602,8972=>602,8973=>602,8974=>602,8975=>602,8976=>602,8977=>602,8978=>602,8979=>602,8980=>602,8981=>602,8984=>602,8985=>602,8988=>602,8989=>602,8990=>602,8991=>602,8992=>602,8993=>602,8997=>602,8998=>602,8999=>602,9000=>602,9003=>602,9013=>602,9015=>602,9016=>602,9017=>602,9018=>602,9019=>602,9020=>602,9021=>602,9022=>602,9025=>602,9026=>602,9027=>602,9028=>602,9031=>602,9032=>602,9033=>602,9035=>602,9036=>602,9037=>602,9040=>602,9042=>602,9043=>602,9044=>602,9047=>602,9048=>602,9049=>602,9050=>602,9051=>602,9052=>602,9054=>602,9055=>602,9056=>602,9059=>602,9060=>602,9061=>602,9064=>602,9065=>602,9067=>602,9068=>602,9069=>602,9070=>602,9071=>602,9072=>602,9075=>602,9076=>602,9077=>602,9078=>602,9079=>602,9080=>602,9081=>602,9082=>602,9085=>602,9088=>602,9089=>602,9090=>602,9091=>602,9096=>602,9097=>602,9098=>602,9099=>602,9109=>602,9115=>602,9116=>602,9117=>602,9118=>602,9119=>602,9120=>602,9121=>602,9122=>602,9123=>602,9124=>602,9125=>602,9126=>602,9127=>602,9128=>602,9129=>602,9130=>602,9131=>602,9132=>602,9133=>602,9134=>602,9166=>602,9167=>602,9251=>602,9472=>602,9473=>602,9474=>602,9475=>602,9476=>602,9477=>602,9478=>602,9479=>602,9480=>602,9481=>602,9482=>602,9483=>602,9484=>602,9485=>602,9486=>602,9487=>602,9488=>602,9489=>602,9490=>602,9491=>602,9492=>602,9493=>602,9494=>602,9495=>602,9496=>602,9497=>602,9498=>602,9499=>602,9500=>602,9501=>602,9502=>602,9503=>602,9504=>602,9505=>602,9506=>602,9507=>602,9508=>602,9509=>602,9510=>602,9511=>602,9512=>602,9513=>602,9514=>602,9515=>602,9516=>602,9517=>602,9518=>602,9519=>602,9520=>602,9521=>602,9522=>602,9523=>602,9524=>602,9525=>602,9526=>602,9527=>602,9528=>602,9529=>602,9530=>602,9531=>602,9532=>602,9533=>602,9534=>602,9535=>602,9536=>602,9537=>602,9538=>602,9539=>602,9540=>602,9541=>602,9542=>602,9543=>602,9544=>602,9545=>602,9546=>602,9547=>602,9548=>602,9549=>602,9550=>602,9551=>602,9552=>602,9553=>602,9554=>602,9555=>602,9556=>602,9557=>602,9558=>602,9559=>602,9560=>602,9561=>602,9562=>602,9563=>602,9564=>602,9565=>602,9566=>602,9567=>602,9568=>602,9569=>602,9570=>602,9571=>602,9572=>602,9573=>602,9574=>602,9575=>602,9576=>602,9577=>602,9578=>602,9579=>602,9580=>602,9581=>602,9582=>602,9583=>602,9584=>602,9585=>602,9586=>602,9587=>602,9588=>602,9589=>602,9590=>602,9591=>602,9592=>602,9593=>602,9594=>602,9595=>602,9596=>602,9597=>602,9598=>602,9599=>602,9600=>602,9601=>602,9602=>602,9603=>602,9604=>602,9605=>602,9606=>602,9607=>602,9608=>602,9609=>602,9610=>602,9611=>602,9612=>602,9613=>602,9614=>602,9615=>602,9616=>602,9617=>602,9618=>602,9619=>602,9620=>602,9621=>602,9622=>602,9623=>602,9624=>602,9625=>602,9626=>602,9627=>602,9628=>602,9629=>602,9630=>602,9631=>602,9632=>602,9633=>602,9634=>602,9635=>602,9636=>602,9637=>602,9638=>602,9639=>602,9640=>602,9641=>602,9642=>602,9643=>602,9644=>602,9645=>602,9646=>602,9647=>602,9648=>602,9649=>602,9650=>602,9651=>602,9652=>602,9653=>602,9654=>602,9655=>602,9656=>602,9657=>602,9658=>602,9659=>602,9660=>602,9661=>602,9662=>602,9663=>602,9664=>602,9665=>602,9666=>602,9667=>602,9668=>602,9669=>602,9670=>602,9671=>602,9672=>602,9673=>602,9674=>602,9675=>602,9676=>602,9677=>602,9678=>602,9679=>602,9680=>602,9681=>602,9682=>602,9683=>602,9684=>602,9685=>602,9686=>602,9687=>602,9688=>602,9689=>602,9690=>602,9691=>602,9692=>602,9693=>602,9694=>602,9695=>602,9696=>602,9697=>602,9698=>602,9699=>602,9700=>602,9701=>602,9702=>602,9703=>602,9704=>602,9705=>602,9706=>602,9707=>602,9708=>602,9709=>602,9710=>602,9711=>602,9712=>602,9713=>602,9714=>602,9715=>602,9716=>602,9717=>602,9718=>602,9719=>602,9720=>602,9721=>602,9722=>602,9723=>602,9724=>602,9725=>602,9726=>602,9727=>602,9728=>602,9729=>602,9730=>602,9731=>602,9732=>602,9733=>602,9734=>602,9735=>602,9736=>602,9737=>602,9738=>602,9739=>602,9740=>602,9741=>602,9742=>602,9743=>602,9744=>602,9745=>602,9746=>602,9747=>602,9748=>602,9749=>602,9750=>602,9751=>602,9752=>602,9753=>602,9754=>602,9755=>602,9756=>602,9757=>602,9758=>602,9759=>602,9760=>602,9761=>602,9762=>602,9763=>602,9764=>602,9765=>602,9766=>602,9767=>602,9768=>602,9769=>602,9770=>602,9771=>602,9772=>602,9773=>602,9774=>602,9775=>602,9784=>602,9785=>602,9786=>602,9787=>602,9788=>602,9789=>602,9790=>602,9791=>602,9792=>602,9793=>602,9794=>602,9795=>602,9796=>602,9797=>602,9798=>602,9799=>602,9800=>602,9801=>602,9802=>602,9803=>602,9804=>602,9805=>602,9806=>602,9807=>602,9808=>602,9809=>602,9810=>602,9811=>602,9812=>602,9813=>602,9814=>602,9815=>602,9816=>602,9817=>602,9818=>602,9819=>602,9820=>602,9821=>602,9822=>602,9823=>602,9824=>602,9825=>602,9826=>602,9827=>602,9828=>602,9829=>602,9830=>602,9831=>602,9832=>602,9833=>602,9834=>602,9835=>602,9836=>602,9837=>602,9838=>602,9839=>602,9840=>602,9841=>602,9842=>602,9843=>602,9844=>602,9845=>602,9846=>602,9847=>602,9848=>602,9849=>602,9850=>602,9851=>602,9852=>602,9853=>602,9854=>602,9855=>602,9856=>602,9857=>602,9858=>602,9859=>602,9860=>602,9861=>602,9862=>602,9863=>602,9864=>602,9865=>602,9866=>602,9867=>602,9872=>602,9873=>602,9874=>602,9875=>602,9876=>602,9877=>602,9878=>602,9879=>602,9880=>602,9881=>602,9882=>602,9883=>602,9884=>602,9888=>602,9889=>602,9904=>602,9905=>602,9985=>602,9986=>602,9987=>602,9988=>602,9990=>602,9991=>602,9992=>602,9993=>602,9996=>602,9997=>602,9998=>602,9999=>602,10000=>602,10001=>602,10002=>602,10003=>602,10004=>602,10005=>602,10006=>602,10007=>602,10008=>602,10009=>602,10010=>602,10011=>602,10012=>602,10013=>602,10014=>602,10015=>602,10016=>602,10017=>602,10018=>602,10019=>602,10020=>602,10021=>602,10022=>602,10023=>602,10025=>602,10026=>602,10027=>602,10028=>602,10029=>602,10030=>602,10031=>602,10032=>602,10033=>602,10034=>602,10035=>602,10036=>602,10037=>602,10038=>602,10039=>602,10040=>602,10041=>602,10042=>602,10043=>602,10044=>602,10045=>602,10046=>602,10047=>602,10048=>602,10049=>602,10050=>602,10051=>602,10052=>602,10053=>602,10054=>602,10055=>602,10056=>602,10057=>602,10058=>602,10059=>602,10061=>602,10063=>602,10064=>602,10065=>602,10066=>602,10070=>602,10072=>602,10073=>602,10074=>602,10075=>602,10076=>602,10077=>602,10078=>602,10081=>602,10082=>602,10083=>602,10084=>602,10085=>602,10086=>602,10087=>602,10088=>602,10089=>602,10090=>602,10091=>602,10092=>602,10093=>602,10094=>602,10095=>602,10096=>602,10097=>602,10098=>602,10099=>602,10100=>602,10101=>602,10132=>602,10136=>602,10137=>602,10138=>602,10139=>602,10140=>602,10141=>602,10142=>602,10143=>602,10144=>602,10145=>602,10146=>602,10147=>602,10148=>602,10149=>602,10150=>602,10151=>602,10152=>602,10153=>602,10154=>602,10155=>602,10156=>602,10157=>602,10158=>602,10159=>602,10161=>602,10162=>602,10163=>602,10164=>602,10165=>602,10166=>602,10167=>602,10168=>602,10169=>602,10170=>602,10171=>602,10172=>602,10173=>602,10174=>602,10178=>602,10181=>602,10182=>602,10208=>602,10214=>602,10215=>602,10216=>602,10217=>602,10731=>602,10746=>602,10747=>602,10799=>602,10858=>602,10859=>602,11013=>602,11014=>602,11015=>602,11016=>602,11017=>602,11018=>602,11019=>602,11020=>602,11021=>602,11026=>602,11027=>602,11028=>602,11029=>602,11030=>602,11031=>602,11032=>602,11033=>602,11034=>602,11364=>602,11373=>602,11374=>602,11375=>602,11376=>602,11381=>602,11382=>602,11383=>602,11385=>602,11386=>602,11388=>602,11389=>602,11390=>602,11391=>602,11800=>602,11807=>602,11810=>602,11811=>602,11812=>602,11813=>602,11822=>602,42760=>602,42761=>602,42762=>602,42763=>602,42764=>602,42765=>602,42766=>602,42767=>602,42768=>602,42769=>602,42770=>602,42771=>602,42772=>602,42773=>602,42774=>602,42779=>602,42780=>602,42781=>602,42782=>602,42783=>602,42786=>602,42787=>602,42788=>602,42789=>602,42790=>602,42791=>602,42889=>602,42890=>602,42891=>602,42892=>602,42893=>602,42894=>602,42896=>602,42897=>602,42922=>602,63173=>602,64257=>602,64258=>602,64338=>602,64339=>602,64340=>602,64341=>602,64342=>602,64343=>602,64344=>602,64345=>602,64346=>602,64347=>602,64348=>602,64349=>602,64350=>602,64351=>602,64352=>602,64353=>602,64354=>602,64355=>602,64356=>602,64357=>602,64358=>602,64359=>602,64360=>602,64361=>602,64362=>602,64363=>602,64364=>602,64365=>602,64366=>602,64367=>602,64368=>602,64369=>602,64370=>602,64371=>602,64372=>602,64373=>602,64374=>602,64375=>602,64376=>602,64377=>602,64378=>602,64379=>602,64380=>602,64381=>602,64382=>602,64383=>602,64384=>602,64385=>602,64394=>602,64395=>602,64396=>602,64397=>602,64398=>602,64399=>602,64400=>602,64401=>602,64402=>602,64403=>602,64404=>602,64405=>602,64414=>602,64415=>602,64426=>602,64427=>602,64428=>602,64429=>602,64488=>602,64489=>602,64508=>602,64509=>602,64510=>602,64511=>602,65136=>602,65137=>602,65138=>602,65139=>602,65140=>602,65142=>602,65143=>602,65144=>602,65145=>602,65146=>602,65147=>602,65148=>602,65149=>602,65150=>602,65151=>602,65152=>602,65153=>602,65154=>602,65155=>602,65156=>602,65157=>602,65158=>602,65159=>602,65160=>602,65161=>602,65162=>602,65163=>602,65164=>602,65165=>602,65166=>602,65167=>602,65168=>602,65169=>602,65170=>602,65171=>602,65172=>602,65173=>602,65174=>602,65175=>602,65176=>602,65177=>602,65178=>602,65179=>602,65180=>602,65181=>602,65182=>602,65183=>602,65184=>602,65185=>602,65186=>602,65187=>602,65188=>602,65189=>602,65190=>602,65191=>602,65192=>602,65193=>602,65194=>602,65195=>602,65196=>602,65197=>602,65198=>602,65199=>602,65200=>602,65201=>602,65202=>602,65203=>602,65204=>602,65205=>602,65206=>602,65207=>602,65208=>602,65209=>602,65210=>602,65211=>602,65212=>602,65213=>602,65214=>602,65215=>602,65216=>602,65217=>602,65218=>602,65219=>602,65220=>602,65221=>602,65222=>602,65223=>602,65224=>602,65225=>602,65226=>602,65227=>602,65228=>602,65229=>602,65230=>602,65231=>602,65232=>602,65233=>602,65234=>602,65235=>602,65236=>602,65237=>602,65238=>602,65239=>602,65240=>602,65241=>602,65242=>602,65243=>602,65244=>602,65245=>602,65246=>602,65247=>602,65248=>602,65249=>602,65250=>602,65251=>602,65252=>602,65253=>602,65254=>602,65255=>602,65256=>602,65257=>602,65258=>602,65259=>602,65260=>602,65261=>602,65262=>602,65263=>602,65264=>602,65265=>602,65266=>602,65267=>602,65268=>602,65269=>602,65270=>602,65271=>602,65272=>602,65273=>602,65274=>602,65275=>602,65276=>602,65279=>602,65529=>602,65530=>602,65531=>602,65532=>602,65533=>602,65535=>602); -// --- EOF --- diff --git a/lib/combodo/tcpdf/fonts/dejavusansmono.z b/lib/combodo/tcpdf/fonts/dejavusansmono.z deleted file mode 100644 index 126cc9228fe34a68006c69b7b997e79256ae46e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 198919 zcmV)nK%KvMob3GvcvMB(IE>Gnx-Hu`o4VP}CRsv4Dj^AkWa*)YB81Q(K;HY%_lYxSGCODH zo_p>#Gxy9v7$IbYh(q?~%{#Xps0`nO5RQl3uog|5HJ>?jOfLKl0qt#(*S=Gapml5E z?}rFwmbU2hLgTyLxh@Db*bWuUYTqd_rMP17K7`y+P`*q5;eAK-$~*rh{5=h!z$N`B zjI;k(B5Dxosz8WI8aQgu@b1jeZxQO20p)iO>N|E665$`}b_4#_3>r3h;KX-^{{(;E zL+tt8MFaX4Ry@i(jJUW>@O!-?$WW9qBK&;;{*EddK5kOxp!zf5Z-6iO#;}q7`&tis z<{_@x6@*d`5AQo^lyME`LfqtaP~JYG@9+VAZv3PddlLfA!e5QBmd%Pd5gS;VY| z)COh)q&G5KA-#=x71G<8U66jADTVYK%v+G&%j|{p+sr{oA7YL{`UB<^q(5Xng!F0V zG^9V`#v{y4;ASJ1o5P)k^hexBkUqnmh4eY@-;lnn-iok#oBCD6sJClIBCHvunTQz8 zB+V}XB}bu?d!j;n(L*FOZQiCcis?J1Z$FgOfAW}ND0|SD0Yg#Vu)ZVhsK>Cr<3^w% z^gUEriBMIF)WSj?xKqc*c6gFJ>}}!6Gz0%QR2L~)c4})!bz9T84UOBjZv$~Vn(o-1 z#GP7qA~DUWs)--ocg#>^r*S-u>kc0}d?>0vW?a8Q)R@A>06ZMxX%7WLNARA)ufG^6 z0nR{VLop};)kE2+Im$!%s1KATZFKZLCqW(Lc?@cUC*C0ct(+$Rt=cSO(Ks)3yIgNt zDb2xYpVJm`MtyjOK}#4#A`Qg@W=45#khi&6G@eS|g!Y&s3Rw(5g;5feCa}XhOn)(w z#KJYmXSiwHOn9=~WNr#K9r`I#n;Aj~l^0~;W~ad~zMP~=XpPxjdF5})WK}MLGI^Ers&aOrc)*g~Q~g%w%07^z@%&9a zjHVK>$Lf(Ca%37sw1<2@8I9?Lo6{Iqhj<- zAQQ$!GPRflrY=*TaWl=CHcUq*pXtREGDDbA%mii{GY9x{IkN`%a|^SB+0E=@%9tZe zIdg{jjJd>IVZLX6VD2*anMW*Q1y;iv*&x=&MzOWoB(@%##WrSh*>-Gawt(%!4rGV1 zW7tXT40ay7gk8z5WjC?g*j?-%c0YTFJ;t75&#|AgU$Nh?H`t%pd+Y9p;X6 zr@2qK3*2Sy8h4Ak!~MoR;w;a55GyLD(YTnD_gtg#9a=*h zh_^`dfC_6#S0J`aAa!x)%25yxtDFSCuB5dsqP6v*Ia!rWA+9AgC2ds}LfR}%tAe48 zL}1RStVK8ks2?+KX+Mc+yMAyobv-|jI{oqsDO4KIZTc&DH=oA2v`hk#9*n_ro#27O zkXA{!y)%vbRQ85AKmy2_!Jb_ZH>Yt|&*iFkKFx8{xHHY^K;wLxQ=i6-X-*#+&!IK9 zp>g-hjSv@9ZlY0CJuV&qv_ z6)Pz3Xry5^^D(VQrvDoG(@1T&X{Ait&y4Y558<6+&%dhDn>>dp9tei>B|XI(w1_E| za1RNvft6BFRlXcglFXzn$?!ye8(M?iuRKR$bdSbg`K3Q2@K>das?t~JTT?t=R>jvU zR|EXLDwjQxzpC;TnlHz7=;-Jme{&^RU(Aro+2ma*n8cog5ND7YpIl3+xtFerfQz;ys4>ji3ozQ}Dwk?QU0Z&9lHd-Y8;QvHMaXEav* zSp67H)G!(rP0|ROA!v$b7+9d+YQERpM%OhzYJNmNYJS$-K|lRBn%-;6eDb%p%qD@1 z^lCBfiJb0Y@Dn*3#Rt`Pia;nMPJHx4nQ!^4|5Z*8n)3?HskUX5V5v`}7TYv#IyZxx z33j^@eu;rVW>_f@$jpb#BAP;I1tE{joKQ`R?&-MSQ#nN(%pSyPB3O~)DuC&GdB014ikK11IA#hn zi&?-FGpm?&%x0LYl)~)f0CSi*4)c&tmkIUj3bGckQt}|D__2C9`!?-a(Lo>K} z+!Agjx0c()ZR2)vd$|4FA?_G=3g$zfb6;`aa5uQ0xO?0Ku7YQH1+V4Jd7upCNg?yoxP$&!$MhO#yX~G;~ zk+57?BWw`12s?z`!aku)I3kn_XN1p$OTrc5d*KJ+u5e#?1k+$aBwA@5N91{-g2?dC zcsp?GIj)S1w?MTUQ$Zv!w*}&9>;;IUNE+Ygh~(!uVjXdOF64a15iNX-Czb<8-oooR zJJGZ3JxE{Sp?>UUp=Ml{gYxJH0n+G>aDhm2z828}{Cy&wxXut)@C2$&{6omU$AgW; zt`y2Cw4~%ij!4>jq-JIuOXSaPE{pz}1o2@GtP32(gTBLiNX+ymaN<{3(%-=>v5T71 zxT{}0pT=$)clL|B)3`p38`HQCjpva5GHqzwoi{;Tz?(^$dl}-E+*_n(n$wxaZMg4= z45V>up3KU7k{GY#NnbL!`vj|kn`i`@Z>M9S;BHjq_oMlrlh*Me8tZ(~UY*a3&m(CC?uXII<6@{kWiOE%I68Bh9Z{GfSw^~4SSl>-X=<=G)-!N98yCPM@A%`E2nAF zmYcgrYbH9u&KJ_S52Z8$^94ffcpRnhK7_{b6%P7{PZODllem=>!g-X=i52=4Pb?NY zsTl`xM8|2k-4qhiM+LzoVGdvB11{&=P<=r9J5NZW{UsLZEP>_|c$kMI zhk3{m{@u-!UJv7=h&DEymfdFTt1B`AosBLM#KpZu?oqY}(?WC?yw3wpvq zLLrq)gx`xFe&U5NWVp;!CjVE z%X3*m?G4yi$f+Q2;T;T-U_1-@7LQ`ctS6RjNou2Y$}(^y2h_{{q^Jw&3xtaBLXKDp zIB9Phhw zI*gXNQC$Ytu1?oz<*Arm{Ztvb#Z!JcpZTRH_}3r-eX~dW+C3-yDs>VJ;CSbaMF+gALs z`hN%~#j1bok3%nP@A$=^{cXD5llb(er}*{gpQJZbQ`d9TGVOg|jR*hqe~pa|Pg1X! z3nu;3v`jf(Nc_@V=94i06L`Edf9lEfKkt!0H$BZ+|7|Qw37H@LDaRjs|3mtp$ExSh zRlTRnQy9AV<;YSrlG5{2G{Zgz&o$(gg2sLll|543Q~Vc=EB$K7r)_;+jT3H&^zgqQ zUuL^MZOD-O(+sV-B_exeHWY;#B4VTTL?LJnT8QeRC1@S0k2av4s3j^zWvDAUgpQ+u zs2rU{BhhL2HyWKm|3+ib6?7fmxru&-cYZ^^qnFSF^d~Aok5C0#k1DZ%Hen?;q3t*j zThUuM1V^B^aU^!4_izkOMF(*`JQRJ1|AT)+9(*7FfhyI5)q^os4^U zMO{UGg2Djggy`k zLKvnTqnxCi0li1cc@UOBSP5Y*giR2(LD&Uhk8;2A5Im1T04h!J?ngwA2gklJ*AgqJ18Nzl5r4aV24yX>p^Eial5I%u$0m5a~HPtP6-huEN zgoh9$HHVOza5GZtAp}AIzEVd*s0ASb0_aI~eF$!Kb9EbaM|D1=dqF6KFa*LV2%rP57!W1LLTHany9yz$j|^(6TU&nqitTnn{`& znt7Tfnw6Th8W=kbjGbneW)H;sX*n1_4UC`Wl;)h~bIn(pZy*g4MFV4}fw9xT*lA$w z0+;|rfHuG!5CUl!yMUMg7`Xs48$kgX0oef{9|B-55|9T0MlYa80E}Ef5&a#;E?`^$ zj9kDh`ZtVSKykpTfOP?z17OSoV9WycLO1{c#w`HGEda(X0LCo<#x3A7glhpXashYf z`!IF^Fm?eFLRuI-EsUNP#!d@kr-iZ8!q{nH?6e8my4w0$x3;;qjkcpUU)xJts2!pm zrJbOirk$f*q+PCEqurq0qTQk0t=*?B(;m^5YtLvu(_YeE(SEP}L3>wwU;9Xhbb?N! zGwOnLHeHmiwk}CmPnV@@tjpE4({W1mY=qBlA=;rB`=vM01>Ne@N>2~S% z==SRl>5l16>CWjs*L|h?Mt4K^lkT4Gfv!T&=oNac-mDMN+x0Q}czudKL!Yg0s&A#w z(|6JL(D&09=|||t>8I#t=@;mW^{e#j^qckD^`-i~`UCpI`s4c3`cL#1^q2M5^tbeP z^uOsJ>LmkbP#N@wKtq@z(ooBgV5n=TZ*Uu$8`>B;8uAUj426avhEawIhG~X5hDCU26V>@GKV}Y@caiDRSag1@2afWf8afxxIajkKaahq|MagTAo@sRPD@s#nL z@pI!>#&3)_j6WIg86OxcOpHlk(wfYs5R=^$V~RJWm@-V+rlzJ=raV&@Qx8)=Q;}(e zX`E?_X_je$so1p2w9d5IwB1x{+G{#sI&3;_I&J#Ibis7lbj@_jbjS3Y>7hw7b7qxU zZw@qvnIp}$%n4@TTr+U4*$tsNgf<6*4mN`YV7>(53Iwq5%)rTJ;AAs!viXq( zSp{UXUf%d?d!1%zF zz>L7`z@~w%0`mg91ojB*7g!WHB5+*bl)zbm3j&J+R|T#M+#I+)urzRQ;DNxyfyV<+ z2YwQGA@FkGwZL0}cLIM4d?;&o{$jPJ_e;M+)3V)DkEUgdX9`Wr_VH$#-Yi>JG`-<( z>wI3BfAa1>N&Cb3zp3XR!B1Dqy=Ca?mKSd{|DC7uC(!%}Pvv{-k?kt~e1F@E=F9D- z&~(bvF#LU5uK(%u-}dFdsQ-Cw{hi%eBlf4Ocl^@-#hlrH^#4ihKg$2O=Ks1CKRmqS zM+5)m?E1fM>$$N%rTzUpP{xlRJ^z!q#;n^PSAKN$k7nTXU72hC+u69xr_bn@|A;@$ zYyX^D{P0|36+o5`GPlw)8~nD&BYl~$_nq{7n8_&?%PiwJ%qE(-#-TuCwr|G%64E~Fxed{B1hp6&- z^i1EqL-X%EmG8ypll9l6ndkNK*|0s|V)-w%Z8619F-^zP{Me^xqZ=*L?J0cvTO)pH zOr;jy@Kl)snl7Ma#?Ufjo+|S;O}|b1n@!uwerk+fqUo1t`4Kcd;(68x%^ykY8AHbgEk7yb_mG*ykENyG-Q|U>x%%rFCx6}OXPumIqXV&2J*DW`nD%HoId{NJ_e!m6BxcAie@B|`NYl+|x*1LPqUl~V zJ%*;o(DX{0Ude2Fq8|VBVVXWn(>XMqL(_d}x-U%+rs=_dTaSOb1x>f0=}?*u{m1Xt z^OMp&ypY@@G0iFDiAPN#O{dZPG@2gdhrI!`%mAA1L(_fyWxgc)SCF*KYlCTe@Za)_ zzwYzuUw{4b6weN(>A^IeOv@zGdLn3@5mdh;s^3vn{S1nJVoiS?s*5(DGSr%`;}1dQ z=rkIO&Y*i}5?!@_1wFt+(N=sO{#o%Y_!mT0*&jjF5M#q?N8e?IyaD675X^i_Z zO_^Lgh#kz1#>3dL>>@m#UB)iQOWBR=CcKQ-^Lo63H}X+;AjdL)F9Zo9fZ(G59UI?*BGj_kTzIvU&@C zSM#mrTYM0DDAJQwh@P=B($iJJ%p1%eWTPjlBI#MGIC_dInR;TJf$$lGOAxL=AiH}% zK)4IxK7>a|KH5WEUNjJl5P~4sAb_MGJK#780%&@i1)(wM72@yH4g&GQDImT`5J1!5 zVN|=4-FJ*<5U(5vONeh7@%$qGbr7}@{~h8HNBoV52N{H8bPosPb94s?W8!1=4YYLw z!cP$H{V(Ou{{^wXwfuj#_(^Dy0&$NMiO=pcY2_f$3ZarZluA;GUlTrp7{Iy)g`yE? z9GZe=p#`WItpfhpjJBgvv=<#fhk=7mqfgKUbQxVkx6mEnpod7p99CgH4#Z(N64$~B zxGt`b-MBe!gFE7U+zS`tA$Sy?fT!U(coANX*We9!3*LcuBg~yAJ>bq0U(V;JiKqO3 zlmFk=^S9~GiO<*n1^MTnm;b*^Gw|HaksVM5G4zxqqUR$q(m^2SHHoKQD+qZI$b6{> zgnp1F)H4E}#1C%@gjo<4Kp-A`s}QdIlX&Ps8xx-$%Mf_s80VMnL*p5Kai5y$D*CJm zFY=z%JcBcyaaOY_J*(M=p4A*i&uUJ1##v3?dp1&pHhd>Gjo!1BsOmH)?{{_+`PJe( zx0y}PZD!MRo7sNnHnaWCZD!MRo7q)$Vwz%UNMbVAO96DM|U+iwOmd<@$IU%jZ0OXFQSj)G2B0$+MpA zV4Qn->&b)P$+NTf?<@3lD3(3>fcFc%&l^yil3E7xbB*d`a5#sm+Qz40YVzajYq-s%!pI-ljbL& zCkF8D(ukS>jY(tGglZx*PEDdFRgl2fFOw52UN{7@Ppb*kglKG~xUz4qAtZA-krD><>sOh39 z(Dc&u(+pJK(u`0aQtwmmP?xF?sQ0MPs86XsQGc#JqQ0#DMtwv5)Bh1180eG%dNmX3 z)l5K)MoCi>y(tFT?@r|wDHTQOL5s|qaqtVP8G{%Y)lm?8s(u+ye;G@E8BKqwt|f%> z5k0#?PKl%T>TQ%p32n8cEimYJe5;yrx$|JF0Jrg}Jm^hqlb`IDXdnYpgi#AhR>3h0 zcMHW-evbZn49r-Ikbd64W`)R&?3I;*Su*1d;&6N&1l_maev9P)2nQ2hj+f<)qK(YM zW^yVB(|mHmoaA!~JG8_>%?ip}Gw=y~ot|p>i*YcGV7}6pIS8Ed5%UG}4f7*&m-(H| zVVkh|Y+rUfJB6LWE@6w=t?Vc4cU*56jj`ND?ltZm?tQMDI}MWdFW$h1^IiDf{6c<- zAPOo$BUpq`AwsAxydV?^!-a9eRAH7dPgp3tD6A8<3$F`r2}gu;!e81s+IiYV+9ld$ z+7j(6+E=x&X?JSh&>qwt)_$z72xr2T;pT8_ctm(Ycvg7#@B!hI!l#DM4}UNGsLf=n zV{2>cZ<}meZ`)|wYJ1c6w(X$pU$zfzAKR|lZrXmf{bBnn!V(c4(JZ2EMAwLJ5#1wt zMof>`A5k9hMa0(;zee1TknAeE(;j0_x7W94+gsXO+k4wb+n3un+26GvbTAIyp>tRr zA&ziIq$A1^1uWW&h8kxL_2MZOk!D)QsVA0vNt3QmhN z*y(WAa>hB+oY~H%&X&%$&OB#lXAfr|=K$wm=P2hC=XB>>=ThfO&OOdgqnt5`F-v1M z#cYjv+r_z*E|;sdtF5b}tBb3bYrJcX>n+z2*KyY=*EQFVu|LN?uANwWXk0*CNPJ=Z zsQ8KTQ{rbP1SLcyL?&K1ZR&v|8QtDg$A$OMh6lN+Rd@|pS@5?V11VLFv1rEVYPdSehCJQr!xx#`csNkM< zHc-JrN(F1Q>$O`c6_je<)V{Aht^W+DKmk+`7#&Gv)suI*t2iU^9ZN90E2d8wdx#H@$|5vL+9 zMO=;eE#iS4+4VpLiS|r;mc1FJf>HKy_LcT6_A*KZ0S=2JxQYsDQ!41>SP4{M04lIX zx+3dFHi{e`xgzqV$df1t6{I^GIa@ee0~K_1c6Ii0_IDOJhdRds z70hxj0xH<({3Oa5jbbulR>o|J+3UhC!KHD<0u{6eD#&;B1u9tQdK;+VBv8REpn^w0 z1w-QaI3rNO@c8lZljEmRDu@IsQ0xrd8M$-u&Xtr3@Z*k;mptD5xb*Q4k1M26(gdJ_ zzX%mnUave}d9d=m%Keq^RK8vLR^^_`U6ng3U#r|&`AX%>m76NpRj#RAR5`zLbmid6 zu9clC^D0|cwyJDdnOoVSGP5$hGPW|HQmkYpkMx)Hr}T&PyL45$C>@uMNk^q4QWL4M z)JV#d>PpE{k`yPoq(~`D3X%dPvt*J~66g8L^M~i2=X=jZ&%Ot74{ATC^}zKY`a#44 z+k@~2VGlwd1V0FRV11yuulj-i0o{IZ`;XiAZr`|l{r2~_uiQR+`=i^(ZohH6^!AY3 z18*1J?sdE1cK+?Iw>#f%bvyTV)7y=2*T0={JK=Wx?b^3%-Hy3!ziqo6c01&D&~5AO zz}uGF=G(^GhTHnv+S>uQ)wfl*mAARu%&kYa{<`(>)^E4|bL*R1pWHfk>+G%5w@%%f zackPG@wZ0Z8hLB@t--g7ZVkFsc&p#7mbY?l>27In1>DlyQs3flR^F_*`Pa<{H}BuP zc=OYnCvG0Ox##AaH{ZDV`pq3Tx8K}&bHmMbH`m^L>E`O2t8T8mx#H%sn@evlxw+`( zf}8Vh&bm4A=9rtEZlW7eH^OcN-LTvcua{ka@A|vf_g{bK`o8OLUEgzk_x0u1mtJ3T zec|=_*N0sn^xeSk^1q9|_Vcxl*V=u{f8+V)uWufH^XJvxSG!&9dbNGwgu*d}qY8C} z+WrsBSM*!;9rdmBjrAEiNp~k;TENtR$(mVStMC8&@BiKZX=qee{(~-l*&z^5NRr+H zc_$E=-y!@lgzFF%K)8j-Dhk3cL%0v&0fb$M-fu+qn(!MCD!}e=!1GObMnPx<=`Y~f z1VS@N{|BCJAheb1Ao~-{LAfrl<`MG&ggy{pF3P~Hju`~u90XFwPzaYGd;?)DgliCf zgfI=lU2gz5ncux(q1+ud2hxk+*+dR7Q$TFK97r2%UpX*m;5iP$cu1dx=M*_GfCF}h z9GFkwIS;}TNPh~?VmT1F*yRwmLi$U1z6t@#GC#xfGYH>7utEU*alPRg3s1l=*B{bg z9fGBcIOr3*5uPg{z>@_$bK4-i2I<$~SqkADNCR%ULl6L8?0fJ$2B93%fJg2_2&8{U z;CYtJiXlyY2Us~6Blb9$k$MOQNdE%Q5D4Lr{uQ3d5Wo^=0e5^i2mmJ+3{Suf54hxj zM)<`LpzmA@ganuq3NW7}p3nl!rv$J)xz_O1$bo|~7A$h$+QBna4qSV9M#zDK@fUzz zg!+)~08clB7a$E|EfmOsn+;E(31K*-=fHEE90;C-$q=SO`bBuc_z1Hgy#}6hA;36s zCGZ5A5D5H$XW>OT5c~@3IdGfd`Ia2GSKxU>4jk}@a83>|A3*|) zsqmLPR$72n3ovrK;Wl?cNw8@Mh-lTWw-(Yj3rN=W;yUMuHk_YfPQ&3Jb_-qVeI$-c*0yHJVBg3ore#AG|8I?VG^Vp!*i+}_@?ljF9#lEL^zC1IP{xu4o~Pu z_)$m$pV)wxZBRE4vt(NkggTIhF}FdxHlQ^g@Mr4`0m|}#Pg@ZLpbsAKV*?ps1Dx{E zciToe@V~(maBKto@<8)87&9B-jt5y}+Y154hX>haI{*RT;2*&gaB2G&q$PNQjIw=* z=+cM{WQPrKD*zsCUqQGk^M?&&l54Im5fIJXj7H9)mW%~otfL9x71L#M94w5a2 z2*NXfw+QHC1mIez2T$@h;6?!aM&v>uyajlT0RD;S3TfzTL^nAIqu|+H4#H@7_LPGF zGA06eI$}DcLDob7uSD#J^eT8lA0t492+*Gh=vM^DTLENR1PNb5`UX6qPZ1y|grDFE zxQhV!EqLGw_=*60h+Z{f2YL~KhU`ESb|<8PhU_tN5MickPlS*TX^?^TObEdHVhTK= zZ+4&&5%iKB`f3NcB0@QPYdMJI_ug_48^RO%X@~xa@QxkifgR+p2=c=Ya={KfEkgh8 zz^nFmAr1JkmqCDW6oF*5vpaA*ggt2$R*ecG$6X17(oKXB5o}hc2KpP66M<>vQ6L>)ZeCEuPg97Xo zXGaJi3lu=NPT&t`4@lpJXDz=q4ru0@R}dxMP3@VgTPNu&-i(hGRfRsQ{lbAeUl5E~!91y1>-yE*$j~_8M>ULPe4!lFFn;ks+wr61^D6NGdpzhH^$2)^9*Bo=RD-;T2VD?96VfoY z2|;pDL%Djyr+B)nH5PER_Q}C-dN>9Mmwbk6{eRBA^=VhsV(W#~_E)V2eBk z`SKWONew#dF}(j65v{7kP(@X8Cg&uvZ5dqj6zT-3Pa(b z{v$xWI8Y=AnCWb>XdBv&cA(eLPV_o@1C^rP=uPw%+Jp9@x6wQ3U9=w^ zKxODXbQryl{)LW+QD_V*L<7)ZF$PUSThS;q6!gagG(^z@EkYXaXO^P39)?60l6!nP4ean_BI;N9!6iFkI>hUx{Whgco$}o z4*V_Dwz#?#nB^=+Cm^269%1uw1RjpIW01ILDzrHg&1B%obcC8eru&K?!?-PkQQMA2 zLYhD}7vR4Nj*yJd6B;dzkm@dlnG|h3B4eA+kp?`WTqYZ0^XmB zI7qF_cVL?>Dy48)VUKJ?#I(m!S**9VuPAEC~E z>_hn50g!E?Jw|9h(~)n-w}UP(Q^6PGuURP0T>N6rgi{mAxklJjXH^#oP6Jndp{cl_sr(G}F_oBSL0h8@z zm6dto^oAqf5nVs?>N&bRt$Zyt^ z{zh8e%SXfiE&J@X_b;+9(JyhEhqQ)3@bGhL+MSP`=VQt2;b-AT#JOh$<}D()oVR0Hc|4XG9eNni=-C7^>$CwHl~N%OWQbt4 z>o1(M5^%FFWMx%kk+?kNP6{;0rkYaOREvWKr^yMyk>;QQJK0obchMh%w+y~7-R}HI z`nG7x;0J?WDUu`{+gW;m6N|9okIoPHBT`@diqv<5v~RuC4{s)6J#M!FzvB5&+6TQp zB7MOX0F?=#ITBH!J5y0B3T6~RT(mh+Z#CiQrBTZxYOS!DmztL263mTHARERboiK>YJkR!!H!#fgklN zJlp^DnJ~NQ zY(hfHp@oYMNV!hV7+YZ-+`jFwVQt$EU0AlzJ-$wz4UfRx!Ha&{4jJ#JNThao$-wp94wRVjm*mH+)0qJwL$v4|G|=ieOOyeSSixA>>R+$Am6?g_HK=Zfy$w!!RATfW+( zElXemNB@%n`3Zp|%|^m40K#3r65bkZ!^z zv{4%%BGxFNAe9#0OSxkpG^QugO<*i$qtzM1q}4U1v*YK_ojZR^$(l7Kg7Jpb;MPs4 z{;j+C#IjTt?(p$Qlehs6Pnf|xZhhw;CpCcC7j_%OFxYFbJX zrI_3>yIT5=`3)z61POAhS+HFNmc!vlAR6qP4~Z6#*!V%k$qoH+;-}JVJX0RuLi{Z| zoS6&sU^sxbFdRle4&_w)C1GeB7cxrEpUhlxn;cn}zloEfto{Jn#y}G?=_FFs=EOf% zRN!RkQ`*;om5sS{N@oBQ1B8Zch_SI8)v8`THgPDCiT^qX*Hhzi}U)7w#sxFD0TxoX8}y ziCiL|C?txBibQ3iDp8$-a&Qil!{%@~e2$PK<|uNMIjS6Wd(V z)m!}vdIi72yu!Z1y~4jDydu7$ct!b&>J{}{=q>yf^A`IS_ZI(_@RsZ~3TSV}MPnz;!Pnc?%gAe=nbCUwvZYIxEnm8H`LBQc@$0Ym?=yGP^YYR& z+O=UeNuNm{NoSy&9$hSz z=ZR!p-U;IyhB~-oQCKuD@Ik>LtTi-R5ctM=!_I&b^I8s-Fi5Xru*znQ)U#3H`U+_4 z*fEg2-UjcVljSe(6TH@xZjsT@b{b3%sX8ZmD=izRrf@_8YcU?r?5P<4J`PGNY`%I{ z_tT>Wec1PFtnOBraj~?t^dwHmo>J0&`trt2&LyY(_^&?4#x)|_VrVhYV>-ZF3$*}v zO(ho9Qss_-5+P!#eMeY{bFHx6@_KBb39;s2Ta4buMn;&G5wQR-0DR$&feMj3K%Rs^ ziSYqKgy>NYMv)j9vW|_zY1PWM3TRfbdXx0?AA>Fp8hEPTj(z*qZP>7M(~Aqb9Vwdp zua=iFznG11efZKRKgUFUlva1`vN`K_Oc_3QYOPv_?DntUow{AtqcDf#MpEzh0MytW zfdkk8#Iga65vvwUc+4(RVvP#f6r7;bL}~RE6-3}sm3M=rj9xv*eFRAUh^RHN{)qKT z1rqbE6pO!f{Pf|6A9)t?;T1o#A6KMqmp0+TqXc&=0C#nu?Qqo49m$E|Atj<=seZY+ zB!DSFivre*r8d@vz^+h5B7KC7405@bpKo~aC6xmNCL#a{R*=PvY9Nl_>r>{wr#!A} z{0~?!UH^09$#y*s_1*dI`#U>q0QxPJUexQPyFcBL?%C}hrzG#)wq;**G+@IgXM)I? z0Jl?&2rf}Yl;~A&a4_{*&XokN)vu3^w4s=QNKpvGrif@FZYplvk);iQcT-PIg(OTB zIYR*?O3G;mRz!}JKuoo}3@H0;&hoa$P9>F&`0AJYSEY*IuoIhGt&y(IUbANQf<=q? z{fDAm(znv>!lBZizyAgX^LYFso`RP}c!nL?zWvbKZ|>Pk`DZDNCy}WFN^=ME(G1J5 z(Hze;<^iKD&teWoq6iUSEvL#e@%|kjqma-o5^xDkJC?G$JwJWHC_HKW#V(I#^KoSL zW-j2Q9hJRKu)UkOqk}Z4#3hv2>XaBk`nq0E3erT?wppTVI;G7L8p+ypj))`}wmWp( z2sV7=PX5XS-1wm&+GqI?e)RG{6y%uvEKR0p;p&&>FIxSQbY}L8zkPQ8w-;xxeMORP z+>k0?X*+B3lvy*UPM*b_ELpN-eM#}+b)6miXYMq{bqlCZUr>!VEqiz6bHHcd=08Ri>c zJm2vt6`;XC=qUR@g#NIU{)`4<(-A`_)ovss4wiA}*{fH>a4!6gjP}VyGTOg?gSp?N ztJ2Rc*Dz~+L+M!z!;Kv{xNs;|-Tx0(N=u}X(n4u$1i&ooSk6V~fT8XHW*gegZ4-DL z&LIUgQHT({FDqPwSLs$%a4zY*lu1=D)Ise5sDsQ&qunM2*aO5U*sWqY6plrhGk}E! z|A=jHgG?5@<^fCUqb5QCXmZ&~U_X@3%eKohuw5ns?K#{=o`dNk&+ZZ46fuKpaV|o1 zDb!}V1E!LavEVe!O|IC(c6|IT=U_jOj!7rp!`pV?ZDd^XaUX6nyUp824Yx&Lwjc$M zlVEu$_%?65V)#m?mVZV3a3ZWD@p3x_?*y zF>r}*`oPKRi<9RJ*a_^AgKMfU!Y(?{sNpdEwm6yHM;dl6$WEL)yxqQjy^aT>W22&)M zAxT-~zK#KM%P)|u@{8q^;j8+aa90IU6@hKa9+2`rF~dzcp`|v*`%fHwUHnq$y_0!r&nMIWEQv z@F&uPYxGPQ;&xO0s6y-9jZicgzd+j2JSRdBqIsTEMzbmf1RSkmRVbPP{iy=|DVE^9 zpgwsZ7J;svDEUN{8gL{po&Zz%l&6BqUQzzvFQou^yia5??&%IuAst!)|2P(_8IIL( zN>NZOz>670Pt+5$4r(YnSSM3-5$0oW|A9X`Kf?3Ju=Bjr!?AlF#o_tVR3gK7Kz~L< ze-tqLu@lV}j7n6>65}FVqIx^Rpbm~ODHtAUZGn7BSh5n?j7bi{xL#|8>Wn+oS|JM~ zUct=z644Gn@g0lt=wJ7)-Ms79pI6PDy+&$<58Zq?ckb$)(gW!)sX6nJ=jzmDs}?f@ zrR-7DM;Gom_3q-$=D<(4oc)yOF_6p2z;nSU!5tF(4%!!3!Unvf*{3g2u4UJUm{K$- zSx5>YpjE3}kj6>T)%4+=L(8^sy>u?Q?Y8dHchU)*gTuRTYul={%gOTclliZ=OpA@h zYw;*N04JltN2Ap;D;;fe2B9tf>p%R^dbV`v;(IksDeUcFX zsUY)Q89^X?qwVz!`WT1PV4~2(VguffD$jgWiTV`cF1V?5SSppy?|6)JaqGvAC-RBX z8fg}o*)Nf$Q;bd$-x)}%QLH;qAoev{q$uIuR$*S5EP`2-s-eSDUS2gIRkDzTlk5af zXJ)x)40E(%BC&ItmwK*yZR{V3*FDs&L{V;&w{Grj5U#Z1x+=M1xgY-3I)7wGdU`Me zJR8rF8golM>E3zVbuJIaDja3G9l;?ekPRsbt1(`-&|sSe)ib3CX*PnXa#Fo_(4-6U za@*gGoWYsq;PN`0ogm$i%CQ@V_u8G;p|tnOlSfZA84&w#ykTnVwzve3Bmq(ala(;-Op>ulRcF=>NFaT#S5v4yS3o)|r zL1kE#xKeOLT(uGTK;Ei|;bRo_nC8q2Ojkv|vXGg=PgYD-Y8fy?MIH%^ND8_5cp*-V zQPgK!vMq!bVt2MHpD*N#T@^#wDeNTC3IYxW1E(s%Fcs-wO#H?3KGWsC6ug0qND;Hn zv$SMn zhW9jRzB^t4rnAVhj0!VY$uPLFN@Q510CcE9q=P)?Rf51Jssxl2ATz%YCFNDCfBZ-C z%*Z!8+NV=t)YBcsD^yA=4q~l}AY}}WWn&bv%6d4Ht*6LPYIP#~Q?W3mH#uNB1r!MV zHaNS0j%UDp*S#-2STFr?2s*A{9zKfWT@}Burbqww+WyTcUk`VOfz^c>K@=Jju=m4| zVv#X$$)W)zseHmphBwo14#yEFt(c5qjFkxzW0@E+L+naE1}BbZriiK_0RR@7 zx&<1%OuB`GaZ726Gz-tbi||4`OPWPxIFYC0sSG!vICl^((IXJ!M!ibGaEMO{$S@$A zGSw_g0eL9tvIX{2Z7}KP;-Hs!#ZSdAZ(1g`!TTR!Myh=L(-}U|^XZ!T^H=Y<{`J-G zJ-g(&#dzsA+Ghiu;o6Z+Z_tI7uofy34K_oNUZX=nMnFK2PcV{EG0-JteK|!$CS8o@ zBL%15nvQ4{{c*yq5JMD?{v^0qy!3R5-iM)32G0UZh9W_lEM1n?=N>6!|E!5EvhxbK zIS;rop)fSWodE_5s}iDFj^(2{j%_S($ii{}HB8JGsX5*ds1#TgYd~RIRu!DW8IsK^ znyksTwfqCQ(sR&Qr+S9X`zxd7PYu;zNdG5|xFnh7rZfFHKccFRi zh5;HztB$rs*c3`eR7FQb*cz+Uwg?Ve-ZAeCDly=9&`z!-daYr7Et^Um5h|jX&`fQz zSm*__=Zyjz zm%ZQPV6PQBhQBoA^JCJ(ioq9#j{Uf3ed+iYhkbS!2YlP*2*2&)23hk*_b+k=C4c_z z#cOryeA%+;;;Ex1*n<;~Y&rcO7xX=m_@cr%iYUyj6=cCzA2fP>p6m?L#keXJ1PD*$ z#!7Y0N^zih9$n<+wS2T1@Yj&8$;7&?I@X9dtSkvyug8mQI-4Px0S#cQ;#AOR1Q{ma zelywsk@qOl$e(0Mjr27EuRg2M*(Z1DI?18aoXKq7xOB+i(k9L7GY#2w6`J8agBxUJ zH3;r8jD1j1bn}Cp2KDPV$UZ5<0xFhUN7pjixMML{%RtcrSl5i#3a8e0W5nbAELhku z+hh{?Br?sk%FBR$B&YbrXJ&Vcj3%}+PGyR4@AFdYKcv>@OZhkuq!+z@DwG#A=sR~) z(1S{ql2a*Jm0AVjRILWS5MlBc&G8C_$V9V@25E3K(ll0qs#LH7Xa|LcOc3RbZ?%XL zy_=;KSyg(WCP46{>OmyhLP6wjkdhEmuLw4Ri%^l(;W!mpn9fiYFa^BYs*Yi5v(a2_ zzLp|R8Lf`dq%rl`G_F41Kv7>=S6xrj8Fj`5Og`I{>%w;zx{DnZU6uLjo|-|5BF$uW z0ykMXLG1+MG^B=N@;~cTW9P{grC;n`aq`=vXU`l3+1-?lthmA*c@)P^tRQ@4B!0-$ zMmXhet&9eIC;$^`^6=RUFvE_fb0f^~Ojn#k=m^lkx@gioYsW zJiXt8saeLLn)^LuG;lO)JW}xs+3*ooleP<>ZN}F&djP-3leSSqfgvsr<#Yllw+&`5 znCxjRBjw+_Czv08vqIqHwsYBC++r$Ag4`;WgVv$vyr{o$jxGV6gYobZ1M>ksy-#{k zTD1?K2GoCnmrCQAI#f1D;oNzN>_X|@MP-;nOyW83E*M~sJO4OQ8lIOY@0nS-yUYV& zAe4=EEAb(8ki%K5Zx^-oUS;Rjd$par=O2W^?u>4C-OM-2OGRI>y2}dfBzFNSl#Pb_kr){FFn~X#?GXU z9yMUp7l&focxLY??ES&E_m77!m|U-JnakC&W6EmTR{8+?3bX=!4MR!pkRXkcE!HWE zE$ekhLN^8@qp?MhMi4@pheO{|Qsj*#Y9NtWkN?^crt9o<%PYo3NReH;X#RpFOBT#u zx&nzTxKS9%!kS1uhP%b$*!H25f>(mP5?a7fcs#S z=nl~=4LGJpOM{OE7PIQ(()sfjvFDj4f8ANusVi=PE!cq5yGrUym#nB{*GW?-(gVy6%~o>`4#QT_Q-TRRm$azUY^Z$ zyMi^gP?wT5E;R)zi*13$Iug;M;*yMvTk7O^nC zh9jDdFdr6Bs{qjC&CP@tDJy2(p_X7K^$wANrCSeFNN}MChm4-Rw5%+7*Vs2+XAXE; zF$YSPzxRe`pr;`qVg=inX+pM5&>^V{tA}<1 zU{;pl4(Ab86)W%oR$s2&$R1amFsc=dlF@O37Rl}&<>g+orH#pa#na^#vmo!wQfIw< z=>-1co!6wF3V^N5?9COAi%)#9X}a**k1{^*kh5M?zMXW}S6F46$qF`;(h9bNRaCGH zZxz6ZWH>8Wxbo7=akSC9_M*gs&=fV(0LJg6_{^mnPnb*aKUZZe5e+XAJF=s|C=`KA z5FeySW9stt6wR4|#IctL5vx!HgA57cgM|<=NKuP*@wLPTYy;5JnPR%4728tmCUg^r zvV*z7!eDVSJBgnxOcukQSdqDN1Yf@G-n#mmU5u)TcGbM zAp&q712ccbst#yQvIlrD+L54cqa;2;73X9tg-(Ep?^y%FfiZL)i<#NI+m}DS_OA4A z{4HKPZN{bx$JxJDk~K22cMZH2iC%TPf{Z#PC!+9BL9}R!?d*}z*l(zl+8 z%}F~ zj;`kj#YR-DA-0IpsB6j^E!ja-=vS}j`0e!iyQDBh#Vc19FI%~C*^hrd`02+757=)n zU%L49*B38c-Xwi4eGfGC1+Ih1>^Xt7dqnEOb%u6{K1_9oRq4Yc+V%JZdpsO;VGF7i z{VWCG-71wBUDZ#ojZnjOn0W9YQHi&II5TiPzPC`e8x}6}d?ct=bm}Udl70d+;iInj z53lJU%lySsM=pY!NNpE@smgXaqFWz&BKUYXwOm?&4U=81rTt;@*UGr2KsPvXn}ze| zFJ3%<{z4|C&iVl#{rJNfFkcQHWa0=6pp`vKI(5V8ps53K{jQx>{Plp^pX5fNxqv4F zY7e6$s##=UOSDIn$3>MOAO*;_a=I!FKwLOS$UVs&tw(ySH`tLK+YL!538(6l3~uDc zP4sR<9?HXc`aFZNCzef`YI?D9a~n))x%&X%?&#d66Y8;(6Ka2T&hrJ==j(|xBco*b zcM<4C0C-$zyxUFJWvt$18LKVA);Qc2L|0}kXemC%nU`9Q1r-~(;^-rW^|iv~rJ44j zg0`h7m?N9jlGSC6r5U~S2eH1qF1voqGrq;9Cl+D^|Am-D#^-y$e%yXbr|DCByw_^+ zvOAx5Ixu9=;m%VQ{Gn*}%Bss}3U+Xr`x6p6bZXtosSVjQeaHJw=aICu{@rFJGunvN zGq=9wpnaVSxL5F-fftkAL0Vn`a~5R4#}x-u3bm2};?x_pH7$=j_p{2WJEPZ|uZH|H zFaz;6saLP@pMLjgDKS0x&C>A|o-Nb*t=@5#>9Yc7d+pUwuGbU%zg~rpYY6YR0wF;8 zU*3!GuH5*RZs?AI&s2;#Q8skcoFxYjCci#<_b$AP2mr$V%;d-0cJ(d%P9D!f=;Ls% z56q_qxMM+wz$Dlz&xJvs2}r;&V;0C<_&85?-Z9U$M9oCH*G}7i&h&Smi%#sdWD!ll zDmad3q8Y|FUB}MCqqrGvepDLs3+VOE?C!@~d}}rUiv}Cq&D5YmRZ10ExmT+IEG57s zSjnP|RbI5Q%8NEuzeStl&s(&)|NKQ8d9}v3cvH2uU#wPg>If8p!rf8{bu5P92qR3ZvRd>@2WCpVXxxxGp zf<+<!MOXAC-)g&fS4TxL(po zTy{|^lMY_QWzxuVI2OCOKAs;uW%vUrhskAvq@nmFxvxc_OJ+k~jcALzS%6g=KuAZ; zC^f_aGgysa0a|r>L>>lxfHpv9)oKG8>rDYjt1K2z7_`St2E8tTtoRxg#+KS33`0vpOJlbH6y}mHk!h5Rochi2Rk?l4Rogk>nv&^ zS{b6ZgsXYGgGK5CN^}69QhsPTV0t%Nqg3%xfx#$T#hVy2vIjR*>G}5k<|I6LH_=WBx zMi#tKd}QUCtG||vTQO$sy{oHNbY1@N<>kSl%Qrn-A%8i*D1|degmAB){JVaB@)hU2 ze)7A8@Q3s^#+rQ};!cl<4h_`k6rpNMu#V&HEDAmliViqWg?^|zV0bq=EI7oXBi>FS z7N?OzArY2_dZgxP?^DQHvhn%-m#2*~4w9_iPNyf}Dl7zs`z&mVg*be*>9Q^bBS&=a zvaD(LU%Q4bbGw%f-St=Yk^E&3H!TkhUjFjKW%(;sU%j_>%!+X(zg}G<_a`6U;U=@> z-q#qn5vw^J(sEmZft%D}Nb3sI)6MA%6lN(_ zMhB|f4oYpmtYy1Zoze2044O>IFvds`Q3_=c-tsYMWat zpapmlCkhIN<@}FT-6x}wmTF-Qrc{%G;m(qCRos`7^f;DTfd@z%J)>ni?xOS|7tOCj zA;^K+xod~Q%qtA+k!4}ZrHW3 zNnQgXY)$NgRM|@6nr6>zvS212D=lM!D^l-#_~F;zHd@RdD2tDO=h(kjNQtGT`232y z(xY&S*N@Q&t_{~1bV?$c?GCXAhFZ0?>I4MYLY1{ObzBaMj$@UT5!TQ$jNC4^GB%)2 zQbcT&J-}+zI$TkL&SI=>3({}`niQxtP8KHBvPUJ+h2IJYbgQw75xmUc_oK1qk2Mxk z*mSEXAKJ2tE_uUBbje3>(p~9RN}p`uwC)Adrx$de7PO;ahb`O|v8&gPgzhOxeUi5K z*bxyPA^)A4(2JQ{Fm-A{kLfe;xE(!rB=<~8>0W0?ubt#H-KzyVQhO$(^sKX^_b&Kb z<{#gFLJ*qiZpub;O1ht*RMPzfGcuF?1ao6XpUvvK?Nc)rJD~c8*&<;+mcm?`|`!s2-HODC$vK+PRsiQJeInnWgS$v_6IqL-!qpcGXQ||>=4m5Y8 z{KAbp<#Y+hnpx#^sW122*3GQqRZ1aN@0m97=?MdtX~Z{ez?6lp)H9Ra)oDd$-=QCe zXfMp^-m_u-b8oiX*tP4L%z>k?23?xfvwK#9(>rt5OUtqwF8eb(YXyH`yUUf=qF}5} zF>%9yg5tEg!`;hwg@;3K=QabUYA3B9*nLHE{HSJgUJ3VHtW%H(^Fb0XlKpsd_~z`3 zg5Gx?RA9d0&{YNBm&1MO#>|E4^Ps5~XEa$L%Q<@%FFJEZ(4RST2FX`tP3O+@?NBgE zMlDfOw=3YXR(08MCFVjlzKpob)_;dw$o?Ybd@HesIRN#F7cv5$ zy5z&ug6#F{CC}YUcdKz&wXo~+=5$30@`1MM{o=YrA-H@e2&*=Z34*gR+o%4>`r{WC z&&e2+Qg=+l{hxmJPQx+fL*8xOx^3ImZQdO`gN>S5I?c?;_voLhvZ}7v_}h_6%h|(B&Zty`bdk$fXk~&Vy52g)St&!r`jq;Oo9+mD(_mARj9r3oRq-;Bk z1>2#Qd>)P4!XSYS!^kD*Ws1E}PF%Z*Aj;<)yDAp4y(A0H`LE8RaaD9p{95Y5%x1p3 zrA`~b>NP!;Dy6!oN~LV9Q3-)cRp6I8^Owk=y42`GEV`I>A@+;#^KGqWorcWSl_9J} z-@_QvL&bJ)Av%ru4MbyFDE+67Va;b-+tuq_Iaa6@%NGw>WpbT@4fvC7aW>BGB0n~h<5Eq$uyo% zeEYc7WbYOwxPz3})#4WJdH@eJB;XJQ7p6fWT9uw^rwZ>83hx2SbkYUCLzeW608?0X z(z3LaTP?j;D(%N@N?{I#abso^JDr{#>gzV4t{l$=S{X}FSK_V02We3wB~}7RT8MRk z5*1QorCV!U8w|{#Rm=n{nFUo2RvC3DrpUN)!Mj%Ie=LA#ZaU*ifBHy(h_B-fo|Cr+ zbSUhYJUXY*(L1nKJExsEA0^sGWu589M!v>vZTC` zLiQBs0th)ZTyxFMUqN~;P{WC`Nh4>@K4^C+!^2{lMrOCxB+T#DV`jY6S^1&fOkk`1L}($fShgv%uN;vj24MqdA2J~R%`WFDnPbU zlPBeV`MD(OT1x&=A2g;pKDO-WvM=vop1=6lKq2C<@7Q*Rt7S)ikm=(`CXu+i%}L ze66C7SGRruy0u5OZq@KAmg-hsfi)tYz#_#2c~_GhtTfittyHBdakTtk7UGLi9B9=q zr24)T=ahPNlzJV-8mu{5ovf@xq0(<$fiP9?65Xh*qKn>zrb-gpq!%>h^ji~EzkBmz zNWNY~aTGV@O%+w%F$?!yT!B5L^ zQHx>(XK-!&5hk@rEjY{<%gL=~9 zl#ffL)k`zM?3Iar#_6agF--ZHGhEYW9*=T&&cU43gtZdjgwEH*q52pUg^)qid;nBD z9*J(Yy&Cr5D@LqIW*B)jZWuitO?aAZ6yKhX^V1Yz(@A5 z@US4eBO<^k*t9_!Ar$2W>4ZFEQ0uTnV{1pG{>lxoknW}sv#Dy{p6T6uy>*M2!em$H z9~_LD6+u>q&GQ46XqVXLM{p}ND>SnLW@%^H_?|V7lZmVY`yVcqPfD?zs@n);2lj2W}l-2m^FPfiI1Io-N8%E`~K@F>_k$K;k{wr(BMazfOj#qwDydgmFp z33xyU7Um##dO);JtASvM*6OtSXq`^mm@i?~B?dh%L5su^!(R6703}&5*6>;t;uHeY z->A|ik`m5?5{X%N@7}#n@T0%$zxXP5o$O;(9q}f!y6`@!D&^8e(+3bHv9pynUm=cWHUKirH^6WDg+5lznDVu>6s%+yS0cc0QxrK z@z2OVS|fjWRsQiB`R%Imk9hOxSs7YSytjVz%>1J@@`ua$ReYk}ueW0;*Rp?oFF(oU z+Eta4XCUT#a^nRh9S2AWf3PNMTHJJ8Ht%uBxn0 z25D@eMk<3sXWEiNb8Pm|L>mg#*<=}n(OR^JYru5|8I<4-Q;}nn3`PpIl4mute&N7g z5Ew-6K%pCSu5B z%~o1M2zMG{g*YL_TF;Q;OpB-1#4%&lwLsomg5*th{oP}FI`{YeNK9ekgaAf{63d6( z%z-%2Xpub^MOS(ZlP0?Xq+9V=+uY6@7OGU9tN3B?*e);6<(c58-fpZb`+(v`)Eoo->#~>k4_9x z4ovC9F*7R3krQQiBt{{JE=o~D#}QbvYQkby%CG>x6Pd7#`f6KH-FI<`5tXRRu)=Lp zE;1_^qXzLQx(t(w9Qp|)2Uk+6PjB9@sB!QItj<(B(Hp?$PQ3c3%`d;aS!#1e!ra4$ zQiXJeb9jEAH+Sw_ykGk5^UGhKmx#YKIt+cAE|^gw>f%nW<8o*?A;6Bf+JQ^0A;qTJ z#q37Y`UH(KAl&YN@sDx|Lbwp653D2To1*4PWD0Rkf9mc9+2PE4KKzDsS1(;8J3NHu z<+IV$;(3NkLrnD&rR=S7`17yMea>v$mENR&$;fNv%@#IpGrz&GS&b$&>Ct`LCT8;J z$z$HQ~xng~@GeNB7)5Zo|IdpzRU1z8zZhZsp3D-+tB`&Y@%GE`7XO9&hTO zEDVHkXi6-7)C4^{f5Nl#$sPZG`RP^plWXMbtLhozpDzkk;8b>U(Eell?N2V{WcT|_4K48Wlr0R;@^^eqwT;G&|*>`k9 zHqn^CTa0ZJ(RiD>t+@%`wqD%Wrn18cxqgK1WLc|bcEnOA0c=yfly$#)8Bg{@aVwM3 zlIkU;CuMLwaay&Xkv!WC$GqbSi`Dg<)joME!oWl%zdos3ryi~FFKxSaZG(T7EEo?M z)qZwL`n(n+Ub4I9_ucgB>7(QO_sW=;-F9A9_i53NdENHBh!5o!jPBNVK3-9`Wd5R; z<5uXLky}@$rtXf7>)0+YZ};{$-pQXdE6%mc>Bw<6Z2XJ#3BmITuoI%Wsl-kwBKU9a z#Xt1{rsJ3^kGuBS`4gU<&kU-Oub1-;Fuq!HkvHoOCtM7_%RZsxz29rl*OU1Zo|SKq z=}YP6-Kr!N?FAt)9tb+Q)vVKeLWM%B* zlLsE(yz%()wMeJVksBlZX#3^B*E6xhvB%l5&Z_lm7A;;=pHI9X%{wjKm%hTaV8*D# zwHT&OxA-3Y@=m|ltDj^I2>ATN@(UNrN1P>eKz)G;e|D(BpE9lpzB|?!pC|JtJS*Qj zKKlK-5SxWq5IV3oV3?}PrB{_B?FH@ECD=*1fFyfPg592&ptnaP2!7@DzVcK~1npPa zLRnINrfpPcZ(Ckydz(8H%7dK9M{Bvs+(^1-Lhe~JF%se=L9qp?G)f*%RB+V9AUmUU zDZ1i<_x=;&^5*2pa^T%R;6G^ySqa2T|6u?9U|XpygAyyZaBI24UVCD!J3B5uCL%n< zq{4^`h>fwE12`}#Lb&3XfZ~uNG3(>w;=!KK+igx-M2xlS!^H^E=xnMtTC?LR!8~D8 z$j3wFOLU$vDu~QcVxJ0d`3S=*f-dmc5@a{aXJfF#rR1mqjh3y{p=R+z)RQr&In2Qx5#oG0XBlrY+^4UJ5cb@PeHT>5; zq~b@Oeb06xt%6lw1*=cj$+k|CK1Oqv_L;a-n)fRiR!b}@Fuxc(o5*mqzf>>s4?tcQ z(>j{gr~~XW&8ez7g7%vfD2U*#w;~UW-$ zB}&%EkUs|W1j+B_dxOkt$Q>TkPK)u*>k8<+j-IWd-`c!`A-uSh+mll3CIE>GH#?;5qSZc$gwDJoMfVagd(eI8Mt~?!zNx zy~W!F3&8m=rhesHfYBE4LV&!M>}F>oum1ARIRS!I$ai+;Jm?m3r&z9A8Gs_gME154 zmtl=NEV4K-tXRK3@Cd(A%|vK876}TK&?4Aq%8e#c0K}0stGw!Xk0*=nJ5h(xG)G#h zh2FXL{IfpNr#QLn=+S4N_`zwDUwUcsqess<^;5kzK$Yi{y?%`Hiaj2UV>}oIp{&v4r~j zR@o*+&d0Poz0(BXcgeFDsHe8K{#?!|(;}_Cl@}ggdFXEnl1uxQujZwiokvYY&=L`P~!nw1fN&$bb{%H@vi)TMa+ZXdIOs8b%Q5Tuex0kf39Hb1|yp zYm{$Iqy%cc*Vw_gOX3zsp+2ZRVtXc0dS>CBPw2e?R+Qs*2#m2rX*Os|EaY+(txD8b zIh&GCHU^lnO^=d-=$cB(IXU)Sv~q>IO(mI9Emc%(pgR+3saD8Ze1@rgX5qp!o=ayI zEPynB@!GX(+aJG0ZeZa$Y~OzEn!H!j+Ecz-~EDBMuo7O|Gnt^em^>cl|K8kc3iSwy^z)L>gC93onZrrK5HPruP zm*1%_--#|lgO!z)x43isSIA6nvx=bCacJfkEMx2#5Z{ zxs)sCQs7bUb$KJir>FOYM$@Tty6^5BQ6Qd*zSGRa`;94XIIl%tSB&Jr%W`vfHEQJc z)M0wwxZ!#A#trwK4jo#x_Fb$qetcjcf5PuRAFlGT)S6r3J$FX#U2o}*Q57ps*qP7+ zMngooHf$qnJZ=s;U{$eNEa*6gCEOHb3=6RnL-gF0taJJ+Kk;6nyjJ&lAb<{ z#{1Cb1g>(jpZgz8s~C*u;CPP_$Nl_sNlAqNLA7I52jyV=$o)fSyz(H4%D*~vT*>*l zUDfiBd>c@fH=b+c4k5_jGem;Y3EuoWkiQS;gUGFwmE@OpsOmf%^)oMbXa3XkaOn8o z9fy0;vHbrY$Kkj>QlkHHIKatiazBwc3~+l?`UOt_ZcIdU=4(e)YiV1^nK`*kygr3&-GHK!H^M~W%<&^d)Cl`vfU1|$q3B~O2ldp=*f{owI)z!Vg)m20Nod$3?vK4 z6FXrK?^gv>RJZZf5R3eT#KN2gL#Fd^SUyqP} zk!?=8wm+1NBXUqa^3%5hu|+4CMab>ovr%EJn#*HYTaru5pEyrwc){k?Rp}WvkXThj4=2KmjH_Ok@abYG z+YynqCKJO3i*d>RdoW&|oI-VShyvM(PA2m)|Md{BPWINL-yg0(PC7q^X@*>`YTrk5 zn(Ew?C)Zt=)il4OcOINez9$L%si%8l5!w=sK~C1PJQ`(*FcgR?euq(qAd<`r?D~Cw>gO;1%n>g$H0Byc~$!NANO%BrlYh0=SpRg z^!C!FZ#OJ0#clB>ycM^WHz~Qw^S)>Jc57BkpK$L+7yE9V~sn?}7#;(q= zBKy*aWomT58m2CGT0bxd#c7F0Vx8+V5t|Ydq-?7lAHlY@HZix2ADbz=;*fi1y^AJP z;miBa`uo+_ugVt?;=1*G3$x@pUp+}eKd|HJC0gGyoV+Z{S(&^pUE4}K26oIV8kCpE z?v^b5N9D~;Y%sl5ztu@~XLbHpY3aYZ%}R`()Ag;D%!}$6<%#5 z3r#?uARfiPUcARSyC!XUZ^oY zrgv?5Wm_?mL}8 zg1pZhpp^HS$-Ct2r!WJ`bfqx-3zPYN_1#=LRL5=QG$o>%)e%jI>+>RO)1dk)Epd1Rh7jZ@OyL^+XAo#QB?mz02@r_<52DIXxw;JDS>QntN)-5) zs9HnxuOo|=Q2W&(uVKpTX%gReVG5wDQW5P%0Z5(tLVuQI;iL zNS!^sb;{+d*H0RH^X2l@>nAnKlX@D~kPUKqA{%;E%Lc#uV{|Cq9f(8?cYxOvt2gq; znE;g<2|O$6=@vn`@5^0u2Zt^m$k)Zl$Lp9K-pgXHp6}n5JMp-od{@l+4n+Sp_uhFF zLNN5?y+!iMLn<(!6X~m#m+@r3D~zU2En~?%+`mGbNo=KO%s;ujZak^4DD|A*Apr0;`xBj}fb?f%+ zcm4V^o;o0H{(N%D^$t9mbS%5!vQWLNd~TRhM-i^o`r-y{y@L)%IHD`VhZM zwM_tze5aMq#X!cgATDjYtve3KInoK~yYAcCwtPLG+^OBAv=zTOHdY!Wt&&zsL+GX2 zI0>iVRGdUE)yA~%FA0NCBtm`{W?8{L2gU(Bgv&lL7Wo2b_Itmpy9?S|YZts`?wlI` z^bOv%@p^M=3K;Nd3!9UBynn5_#v9t~1#OPymlJHuZ9c0>-UrJyFh9VB>Et20G|3Y^U>l}%cgRRcRY&w^z7EcqdI(Co+G>rII9aZsv`V_ z^i^95ELmRi-)^uPaBnX=y~^B^_ZfaTGjL-(%S)Z6j=zAJG>q3R+Tywg-Gd&0z%15-*GH*eii zsj|1sa)kyMVuJ?%Jb4M_Bgjn!NIgxEwJP+cJe`=6ksHcP@+(gt5-`DZ!^A|+2!>E zIdJVNCNf7oW0>Wh&iutkaivUnDLz!{cSkb0Tdkp6!!lth`g+R16qH8xA>*%=PX-WH|?XSn4dp+=|g}y2W*m6bdLi0PBQy14&Z5Qpyypi0KT;d7d^L+uq6&to_(SomMZ;pB1;&~b)M<#iXk_}b?EqR^W?!XF^u#juGKX< zt9f4~E11{E)*|=Dg#G`< zot7v7C=oz1m>u>sJ-uEd6*C5quW5SbGKi=?QZ9~>lD@*@@VLvKZKu9E$1IU@r15v| zKr1(xGV+DMiXFf|hnFnD&1C**1pKoSa2Z21sS}hP!I^wxFwu1Wt49X9SQE(njw55z zP4yCYuG=uPRm|0gKy+5xD8on}lDqih>l7Ts|1Ry(jgKoWt(Y>iVfGtC2A-;V zpPa1$jL<0=HOzdw6IGY_Gh}AQc(3&T3ybtxf0&<1gG)}@|zID+X zH^`!>^6FKkcTKc>IkR(R#Yf9YJ;~(GAUX#|INIvHZq>zuWs}M@!9DV%W%xfwrK8e; zqxkhmX>A^!z2_+Ruir*U(&G=9V;(pAVynj^v5ML$`7ByV5Wb))COBymiGF!T7H_s)g z+fp&%7@ooQTIRc>ei><_3*hh#ibFeTgD&G*e2ow$PS?}k8;ETpba|9F;Pa6)Zts0} z#1}t}?6UVulVxV3Ml(ODrDPKE{;|;|aU)1mFMA%A99|_!<0IMO%!1+4_jFH@%&NKd zFy>ZbDPlb@&@;L|Qw^GS*iC_$&H`fKCvLrTy32^3XNa}dr_T)R!X+I|68D8WaMQA$ zoK@Q1Hqf)nXR>wdAYExDt$I15>HO6m`CDAFKN7zVX~~{Grv0dwrgue>o`4Wcsh-mS z82W0S#uLwnN6ugPSgE*_py_^G6lJHQ_=9J2+I@WRbtPsJrNt@YV1`H0_*6WRxFx~kQYZvaRS>AmNHC<0(0m$Fn}&7W#Wed==l^m?6qxAUL9=yy9m zK4?x)-zi_uFTDsR>%$rs^i%m)eMdhs`95a&sdMe(yPqcqIg9#_ zo}bmA#vOF>Op$&%i+Spj0>5UlHg8A4naitQX{PvN!IaL22MsyU>GM0w7Poq@$JFVa zwzTIm9gerQ&RiX#Ws+xg>z|f(#OZv0$Mj7hT4$@)ojN2W(6xt2vfR@P%+GYZC%|}j z2N|uP^c5qsZz|7HjbxG4pwpgKm+Jjg3zH!l9V4c(>_j|?aYYyI-E*Qt*CWzzIPu+% zX~v^GSI3&vD0Rc*hJ#{jt?$xfKey-eull$EXF!<0M{cCJo(pY}^*}q3J-(~u!g00f z(hxs=&zw&|)Ozy1IkQ(qn0*(|(KdW*n|jh4--ISrUbMs~=QdB?bnFsyRjPBAPgJDK z6Bq9n2fXW*fQxXieOBYv$ zuPpSg9kqf!E#&tj8?hIi#Bmpq@0Zmzrh~C&p`SpulkXI}(zu0xOdTOzyZ4*)?Z~MQ z@u!m(?8kNASuly;zk7jn?J!tnFM_$2aTq)1@7~=;dheTCWYzc9H@Ib+-EvzSpsm{U z4jGu6la8et=n4X@pL`V=rbhTtX^(<)@$m&4_Ai)pdCG{DtHG+_avpyM{q@!+w^nwT z)(QCHj`3g8StLuwFcq6>+9~YN2k%LpKESyj_8*>5C$DvI3sq#Tu!vM{oK%}!Q_rS* zhT|7c*EVLF7Qj3qNQN~C#^WPyIMH9c;3YudHe#66sGb?op+&1{tB1Aeoa&GooWQ-X zHKjvbYI1r~T3A?MoWAI6{e~NI7j!1~n=$Xthz&FwR;$#p$p3D9BOP;crHxa*lnhW$ z@3)u6{~-ODC*32r++)*z9Em5;tL{B}iIuhi@08ckNj+&?KVLn>+9L;m)5zECvEv)I z4)9-ww7J`F2VP)|tZ4emXF2c)VA2F5Ng9YNQr z6^aRmgBaq-1pP)~e>}CYut%@$d+->KjXfhRDw@-;OP=(Z^n-Lo`V7CbqBZ=tVnNGR zJMh8MT~dpTxM4+0uKxDhRT;m2ZQ)e8PC6w?#l+zC@{tS#d-pU{dj%@~tm6y)XAhPZ zv8O$DJZ8_19zA3*@H?d9B}K#HGVsA&rBaI>ty(Ui0MNFkOKrH$^lUs*K2bdtrZB!v zU;E4`X#hLKGXU?|^IA`+{>bptore_m??qbg(52rjd<9?GwOR_;(W>=4Xdxx}M6}6B z+8$mzgS7P~&`p%w7SX!i$_;g+p?+tQL&l`t0*cyVX5R1Iwta`Ld0qNScDxpc{VaWh zZ+f74X)_)vC4Dd5wOHccu?J{z@ZGfNe$$wY)w`s^o6?=+puS7}zCTQ?jCxcx!Hg@_ z;uO7C+od_`c~}1;#qFOR{Ti$5L^jU5l_9-PJ|B!{NH_7m!M4D)nN8pQhF{kI$A9(d z)9QuN9BCJw0L=wiUKtG{8?ecZb(Vrz^Su^nr+m0r)+ zR-`K}kP&ctj;=?~*Q5(%iFDVXx&2@0K$>~~LaFrNM4dF!Mtqr+igBh)eXUOPhx(6$ zJk)vh3?*=SK$3n6*y3Hqq4g7$!?tbJ?al0)H_zO@{o1hcBbG>a-&nWlm3R7Q;`he1 z?~Qfav01vaeR}waiF*&uc)9uRE@K)|y*VA|U=ZkUEt!e%{`>hBJx1O^!SxOvth=zo z=Vfi%ReZ{f$;_B^<;^M5XM(DVA8n)|Rsf2N5>AhW*mA%ez--H2j+7_x@i`zE95mF>KZQ+iJegEPmqs$4|X~;&0zy^FOx#!4vPh zm__6r7|$d0y(y62m78i5aHZcqST!D8G6t&s=;^t(6unFCJLK=E`JT5t@u{3AzxAy5 zpuI~~dwQG1Bxvs}Dy8$aMKqtDlk@Wt-Q}&P+UNPib9|nQYWO76?*`T=FWb9x4WdSV zJDL8Z0b~vf^-K!8=kK2a`MGpIU(WC7qgPVix5uj&@K*ow)$rqO-h8V6{M*HoX+D*G z)$lXE{Z-=2c$WBn6R&SSUq%@Z@?K=Yv+zJplKAidvY;W^$D!ZMLeU`J$V!BFEeL{IPSfU)`jf{!raFt9g~(8x9zkZ_gm}9l)p1s zF<$z0sS7>fNA`gir~ZCq1g0hwCZAuJJoa)Q?$PpoWAE1o-`LZ0(BATL{TpPT2Xdat zul%7Jd%9%L`Xk>-kZM|_xGs6l8I+UHC{Om(*VicjzVFTfZ~ZmT1JL@Paekn>{-@6y ztgli2eczn}-umOc`Bk#h3;)yp(&T7Ql5vTsi=lwV(?e6>%)N6+y|D5>d_P~}5$ z@)_l;;rEqa>iOR5+q0*pZx7_lzCC+t`1T}1zU-^Br>3tCQH;9Bi9-1 zIFLw~GnlnlgT=IZQQn!o4yUDOvuSk`Sg;toZt4V~$&b7RVW|Mio(XQx@~k6^Ynk-i@F$(BWZBDbU$uYbAyfO)C8Zwv`( z)PHHm^e(B9nzAF?yBwI6HE{GefMt)=o_@!vF2G`Ap&?#O%jT*9;bcGrF)d1lL}0be zM`b%24_o*0J1@1`_Q&S_wI=jzkn`2Ik&U|M)QL!L(#Y9t*J`Xm|ebHgD+C%}MCfyGroE4P*sD14f9*9>N{e6HT~q)kkN5Z zoCERY%l7_iz$ft!efAork!yIihI8kmq5LaPcy+SKSUHS)1?KvMJ3)Fy2d0CxjC7gF z-iAdF@=_3;=`o2I%=@any+ErW73l-%x>F=OT+?_e%guT{U`)~WM=g?U=7~-1G5WBK zwuP_u==uKEys6GI&-!5(MvlC&(ug-^XODB<$INBvLqq$_;{n~G3(|5ivvITcgi|M` zNyUG>dz13q(Yse<_09QGE&l5yejiA~zSW0{6IEYItLhs=|t?Hg{Omjb_c;3Adw%a#_ot@JtL{(7C*ga-4yy59D0!r!CBm4tX6qcI=S%dq~fQQ_Yyc94D8r%rhk zxXHyefNR(zWF&P7BET^V07?Q}#h#A&^jk3&+&~6SIthTv8v_6GzYj-;jCA)m)kN;q zak35_c8aca>|kALjPL%@2P+Gu4{(F?BcvvCGP)!Ws*7*o&<=6kK80!Shj?l$DdX{D zJpa(y=FMB-tJtv-yFKJv!@l|zD3+`ox#;GQnSAxeo`^-4DaN%*Vg~epaf(DG~}@t)%g1r3Hi7&v19oJZ4&H z<5n3%JRf@$_>$*FbFxn&>A7H_&or`rUGuX!q98`#z*M@3o`~W9w0iP(Roz5}$cU#t zqBEgr@4D5s+qgQ9Y0>SM)B!0|r!>u`AJo~}qUAHbsMD*XYTb;e4Gm+u|DNX5AL0Ax zETD02nWmTIc9gMN++u+NQ{7o$4cR|P+h*@5=qf3=FK4#Uut%kuK&%rBK{61`a{Ro2ksq=YBJlejC*LEwm@U4SM{4{5ELX|H-#Omp$J0yh{QY zbgc3_t}8eBncr|d{=fT%>q|ZmJlCt>iZ3f;>Ui5{Ci$zfrChI?-;|9)neGU-SOd@m z5paSX#Wwk?vNlJA3{*6|1*|+XleohsR*`h?YeFg{qijR25qr2u$VpK_09EtaQ12ET;FZV zWvw=K#2k*1E=v`88`|Zr>9Oa~VNghJE;=qwIxXFSf2aLFILp9%eJocW;BXLn=If@@ zd0354*%Dv0RJ+CO0L#!~0<5Ifbw=X-0hviJ`G428zbL$L0@soDb!;KTWwly0Z@{vm z4$joAFcGi*%I%f@qPX|LzYLj8afB(eHT`~S7cPU^ZDe-iv)XuhThlA#83`F)z18bi;;uX^sJG@Q!W1#xL9ssN&rA2P9ft97_Y;GMAIsl!wBmXh(@Vd5{-T$dUXO94 zbWFN0{UUuB7x!Lf#_9Kj6`S^!KGjAJ^(i&#TaqvH=KA}T23CE?w>aQPc;Es09bf8I zdY^ce-uLq=t-6$qk{lo;T^4Oq*l^#6dNB_qca40g_a*wBUR3p+Ug<*s^1gHoN1obN zx_1-6X9M`&0r-@J-lECA6tS;TSmHrcb?PWh47BJOy9=kUGX> z!&6BJBU1h&k>e@=&T74D}u!x1abx?Nkxwd+}v*_++BrS74tDyUv{kwN>+qa;57isB|HB9f|M($ne{fGbtDE1|yze8+oXVQ)q{2lwkRVrAEct-1tCDm>nVwxy0eE*D$qN1bjMY)+xo3@_Qq?tQs z^n_^x>(ztoj7E*xwQt%iYjgM3+SiwahqbpS&27~13qBd(Y}IP`jvn0!qy}T%w0<4Z z(^tmFHEb0ZrwIUfHJbK~2F_ixJ~?SqpMuldupsYA?ybDYMS{*V6AKU94SGjSi0j5g z`>q}K-qGla0{yXBdJ}h=kkz1pW9gzrOC1d+OK-ohb<0OX`}G@ocFQX-NWZXONxh^- z4H~p*Q_uFYEq%k-u?cUk8MHh!Z26!ydm0|c`FM$M9?gvgbw}oEmg<>tT9v~&H(Gi{ zo*_%K@k}ybW{S2;wW#L7Uv0;OR!A!EcdP4CzuY9KsfOV54M&YHPJ^^E8GsU~v}AtC z&0UZjQa?PbsOXdI1x?z|sW)kab87yc&pzAp=cVCe$Bq~@g6n1XiNZ6F=gxWJ+tWYd zEYH_?=T}m{f6KPS%LE?imy&v28yw!2p854_>XOG!lO8_%)7RripT<8jncmu;_2ujD zUVDY$athdo`P@3XA5Z+M4U|)>Jg_ZZPc7=8$L`yN8|UV?J5wQD!tq$hE-IQeX;hco zeTDt{74F-!4~GU15!W{wTJLTf8aQUOG;s77=-)u812+`|1p=rZjJiNv+#P~vtKh=QfKL%j4q8LBO7(e zz@71KCR7@Omp@wDrWuaJ;V=RIPcw?kfzYoZ(3Xar{=$KJhaJXOcIO7ML=-r4X`ggm zI$uUwsD*2P<#{lE>S!kCKhnOPZ~w-arLlOKr(kn~q9W=Kd|2wpS?IS$QO)m%8mM`D zxNO*{IZMjQQg)50`Tfwp?lWEF4~SNOU!3?ziLx;9UskRnK*55iGqk3%A!BA0gEh7N zlS2jh>~U3}{@>lGzIn&%zC3M)@9qFW=15=N&%B_ZW-H0Bk9p(u{O(|~b*~futj7GW z2B_I4L+2JL&?YOdn)ohZ@%IpCG-YMd_xKX-CvCq__3tgE}dPm z0;g@qgDHMa5uaB8|-D*CBDfmyt=VrN>z>^%+A>&Sc! zZPtZ0gQ=&8pEo(sq_0819^o_~O{TPaw@W{~_HMTH$)wiTFooQ`JOw~A1#*} z?UJIrURy>}^oit@wJYYeZnXpdPT(k_d^**4KJ6)=_L?s3DUn637LC|dw|QRHu8cJq zyLQ`-#kCS7-R>2k0~uaS-1=1a%O z2_0_C?g1$&6DR%P>A`G%WpnS|+iCrapne;@qXh8=uVv!j5sTlPh4~>NvF9jvqj%p; zS&$F)hll5Ibr)r2o0)yDv~LeJdKPlMb`K~djpR}zqYrHZNR(?t?PK6+a{d4!=Sr-{ zSIeb)lCzwfS}~bj_;^0MuwpV|*{eRa9!=LfK!=$eUc(B{#GliTuH$cu zb8{3-x*{iciRTM#-Q413xpldzHNU^UYIyIxdwUP}T$|T^`0)0GmqEL5#q|5R;j;DN z6*|Q6fq3X!eI9`zv}Q|7aiO#c&+_d0eFpsZyWLtsoC!;;T%S_umyOc)-OE?N%+R=e z#p2&+Jg9i>AjBAe- zZ!Fq8C1t>Xlqnmgy@x8_#P(nIBD!|J7{)wTFhP%Fh~G1DE0sOmh|7m)p;v{a#mERq zw;H_8f-Es52(XO#9<%P=*51>m_TF~SQ*>{4;nb;xyUUuz=jO(H+9&7cCi5e=Z?6a$ zUqVp7c6`Xa*IxU@I(01>fRd@!T@}Ye8jrYmX?Wv`FWKCnmcuVy93kJ|v##ja z148Mtkg66Hu5~rO&wiVHo}Gz%yiH!j^1ci5@1MTQ-udf0-@5|=AG4s{U_W`=5X-No z`6^>)b}MMt@3nX2I{tse{Rco4SNA^-@3}L(OJ{f4rAS?tBA~QoDbf~1q$(mHf+AwW zh9Y(>*s=FsqQ*+>1<}|w#;7S8jmDTn6Vr_`iSbF4y}b9{nWY$?@2|Z7|NDxRnVq@i z+*3a1mUDyx)l;W#`t;Iow3yREgJ?fs7%5N4TQB+FOf=sZAhY;fOf=u}zAJ5yQ?oKR zm!J{m{WM6|p+oV{c<0fREo~|;R!>b#AdTY3d@eR?#E2Wsc2#IoYhcXmE3(MVJ$CE# zFh3s{O-yV#`tEjF>88-|b*8$dO9ee-eqSN(!6$}Abf*YIT!mrewTiS6r#?BBn~T1q zuc3ksrJG92nEy`R?M3M8$j%Cg6Qh2@21~Y0R6Lg<`bOw>lp(@!;L`TQ*x3GiPr~fa zM+_fr`s>PsM58fr0bpAVIl{=$;+3J>!$uDu@j0Gya&Q0G*u?FZ4v^|`d$GPNsHf|qq1$`p@Fh6F*Qb(# z(vrwX92FRt*E1+cz>)>Ln$RZNyw)JdiD!!==-&#OwDJf;pk=+`Ubo%FwJE9Lp{tCS zb8{z8xmP~S&%5GBd~C;H0>@{jriMq<8TVynJ^X0!aX#@t`}U-Mqpy$FE-*W5{^p`$ z&0A5So6djs%FxcWV}~A@?c4j>`($L!+_KL@+)F~^1*<9Em9{cqX6T4M75pn9$b*`B zR{TX8eYT;Cb6D}Foh{{yKA^G{)0@3eNA#(` z-+-H69^KoqV-aO~bhYv8A?*X!A86ogrWgs!3%a(=xfCe_V06$49Ag`<4G~(svh|6K z=%Zt&S7=q&PMlL2a*yMiV0X4xk4py*4fOTjpic^QdVk|6W9hwH{DEVA3f8v|7(&~+ z3t!}eh|OU8NLopPBNHbjO2Z|vT{z_dLHG{72nkD3DLda`+PV~96wb8tV(Zlot<26Et(@-t@`bVQN9@-aQjd0f=OW>Md(uv|xL?Pq zmFA(Fb?%_urhkwNXf&~|5w(*|KOs4`;Y;^4ezBV(w)3B<_i(<1w{|xz=L1x7BX2F)T18~-vS5iJUFl3vK z%b{l$Iu)GfJQ}}2i##S&)t#EUS*6tN3(`1_Nt#oZHRfM!CpxC(I7G`FXB6!YoV`xU zAGrYk%F6H7-CRC;&XJb>_wsQDE1&9^e>Gg`*m~ZX>Y0nL_W)uB9L*sYlwA1N`4xOZ zn`&M?Y(q8y2ltb7KT9x&j_;st}rzxl!5 z<|vR2F5aFftg!sJ^?YVBxrc9GOud0E!0E<(MRoyt+Fa+6rfRH<6Jv?ok+hp-g) zPySbtiwNX_jbHZdS5)%oR(@Vy0UiX4kDM==c-_#%J_F$*{xLr>xM1(9 z+M!eJT{ex|ut%H|{*28DYnbOtNMP0@;`t~arNW5vN2#;Z-rlIIjis z=P&SzGe(VryovNEOu@?i0|yQ(D;qX&;Qlq-y~y|tQ68H;BD-Z6BLU9B_NujbBHnW` z0re_aHDrmK>yja>dKD19h$QqGLHHuH&3vZloKYreHO=b|x;FEh=%cX&{k`33-Rz2s6V8Vc&DTErC)x?-CX)g zM$w7TrU^vP6%jpWMSVFXwJr3NKVNjp^xz4~HLZDuqEF#0ZY_34HYm^ZCDIA+{Y4u1 zfb>Nw^hKlni}b?eLfr9?I?4k&()KAb>KW5@Es^kVpgVDIB!u9k0}6jXZ#jCmLvrW7 z2P#I6tT@oOb8?6H_}a76ySuxc!~uzkUnC~dAA1IdhHc-D6x+9lg$}$T1`+w^KEDGG z8(UR17S@oTZS;=M|EM#?nCm)&{=ezYAAY#@-Qzdw&)Ylj6HxDv{Hs30o3yAf7oap( zh|*qDr-uf2>eTBTI~fKIx8J1i@P_6JIf*;La2p7J$cgmp#65lrVX;^^vPo=}uu`mG zX4gpxdj=jHH0U6xE08tr4{w?NQj}<8qr25?+g8&py3;aPieBPjKl}h|eh5M(IExtH zm3#W@!ypAIASEm`yYUq#Wiswc_~sak=iQmsEbyR$b<@{DM35~5PF!HEhWqzaVk>*S zI6SWbjj=?CM!H_XID?2-Da)!a68wJSbMPhcWKCFIEOl+J{KQU=cY+O|I zfO0^%k~X?|==(M5+i(c$2QjQ~wDl6ILL&)YSPE~V zGsw}$^>ige)L$TXf70}q(?#5~p6;_Dm_MQIp0rj3HP70Lrw*A@&@x{e(wqU5SBDIW z%*~DM?K>efeAUdzPSFXKHT`?^81?P99lH!q7$4g$&(n37-;m;Y)$t>kx0sh_OxN0V z$jq9*sa~nn`n`3F9e!tr;^%kEHW+#npV244-e<(>D z-}{Tr2Bc&NT@UlYB`I#@%-I=k9*AfFgKsx?_r=>{;|C3boq&IEbI+$fO}F|Y=2pE5 zxZ97-IH+^7Z?l%YYy>CdW!k#H&!5W4@utzdiqI~YSOg=(Aez>T)J)?$(K~9o+gBr} zyFOZ|3E~zHIh|LdWYxpC$3>g{S*ap|?5L?6g9nc>Z~NfN^Sr}rM1sD2?hunXbo1XJ-$)6|bjmz7 z-=?Nq`Cp<;i^{9niFSur)EwuzYgpKb^@|dnoH8?dmybGDF>F|Q<r+mNxHuX!#^!ui7xnJ0rMo}(oS>bOz zTOn*%Qi=@#vjuEq*&Gt9#0V1s0ik8?#b6n|{gcl9Aru z5aH`RC$uIeoG@U3gE}uS(a%R2l^SXBMmFn>e;7^%a&~w~}jW0PFeRnDGS(Bw+ zELW<8d1~Z8N8L8A^~KV$%a_exzHIEt+I8z|Pqw~5`Pd15qTi;)2$`@nzU?)wL$aUL z;YoCkJ@vN4q#xqy*0(0#!#PELvLfg{V{yio9~C94K+>NDhreIKwo znRm$MCzH@7Zkddyacqn-31??ztybKA5EpVIGfZNX$&@yT-iW(=`$pSDBtpI^M{e2J zZrw^oj2jnFnK5Z9?}X>Tgx=($228%P~Uhy(CHtgX^@kK@2f5=xEG zkJ-91+1Z)j7ZW{qCZ0>mE*wV6MqxcCL`L>8?=oiulYv!5jTTN&Yy^AJ{ z9WthaXL9J+u~K`}%!wlkBMZ1OGikfllfFkwJ>NXH%SAZ^yOj+aJJxqxo{hVTKWJrH zIULucs{S!i^rSR z=;g1?o$l-0H6>;K^KrxCeSO;xuCCB(wfOFo%=YA8<`nKH`);wt9Xp~b{2z@vaoalv z5055^lXFNgadSYj6m25%qo8vt4*yjsrS`AM9e|S1;5>Pcj+`B|gy10WqXl7oyZ1>6 zHF#<8H`NcmtVU&{yYy%J9c+32Osr{r#AD@IueOP!{s9qnrzgL%(uEVEGvyFjKnLb7v8|PBBrBz{Sc|T)k zC0_Y@*)8)2`qz=K9(_7}c-NHFg8h+teJCkjUzylb&lpVl7rTJDQGD(!thL@sKl9O^CS5F#3bnDdcE?M1t*KyEjm{N6JW$G;yoAeCq##kn2jLGY~h( zW6i^dYaXI;^ykAh0>9Q0ZqGpDSX>H%!MO~a02krwHMHyyX#lrfmPY!zgw};Xnu0!( zDaiFw)~5pg5mzmjk$RjYy^h#lwQK<1XrsBxIosq&s#Q5MXEMNan=|`m9$_0c!p>}j zoynIt!t_IWpCCtezv;YipQRfX5VgG34r#9Xt+7>ay;U{#t?ELfu~#pnu~7QFYU|c2 zdNZ-GmoceVA?@D|JdPvig4jXtqt6t(ed;C@Rt`!P76rV{(-tzR)u`*xr7Ql~u34p==KgcuL*5BeE!otK?myR-%&I zS@WQh+gtOh8!mGGhQ`{>9_%D?O^%~H$HGlPXNbfc(8K~a-i~|HIzL2PGPyA_xsfk{ zOyom*N+vf(CO7&yyKhXil-O9=SlifG+gmH_mG&xo2Ya=>#@^B1$2P|G0Pr^WimT!+gt(06{gf=4 zloW46!yEkkhQ7qVAMBNDTEh+8(Yytc@tQBZ!|jvWi?Kqf7Uli@qL^9$8HK)vNOb(j zANU0kp_jGi8fx+Bg&fSQ0q(&+$7XQcyz{?9$is(t!GU$z*^30;FCcbwii{!Gw)=6= z?C9v)73E`2K`=MHOV?f#MxahTgm;R`JL9Dx>=ecu{KM8;cUoLQE+=eQbgzPhzU`-m zM{JxQU7cc_8lPL}zs~cCW!|hv6O`;T;2=)J_(f zp6P}Cm85PJsrwwE0hMbGsIp~xkvrT3w(~#wa6YJB)}DTs7~_xe*%vP$4T8S@n%NEV zUKPP<|Ce@yFa96wMhBwTc1jDWRui_Laqie2P2xYPeYr={>T|jIb3J5Ek~eung2{-(^D;Fw7EuBdYfPkNn{ zSOZ6lv0QS}jwlYuVMkRTuuar)v?zUR5rvQm)}_7jOYJ6DZ&|)go({I@&PG_M(n#m>K^ynIEs7HoOFVEg%Im4%a(7ko?us+ z->cMG8bHQqDIF_;ckdA1^d>$rZL`ink1qfA?h5XGn(h|hH-d4$kzJtcjG)jN9EnZW zqes7w9{s!Y5^k#I=3}7@5eu{Di2c{8^%`$@CO(JfR?}w)PowWyA0>>SURNqN(2o7@ zV;X=>CP26GFN{j;lo!DmS+%u?aHqrA@o+7B=7tG4UVMh7IMi!U9(l%eqj*K;!L4)Utr+(Pw?9Pw%Vm+7*u|t7({C)-_z;l|El)I>Kd%?G`p$>Cr~k zE!?TL_OO8U$unu7j&<&q=xd7Z=2{2Eh)xo%x8dB5ol143(yzB^KFkV)Sslm zC_mg;)VpStcu?HbfxyLRi^wQJ;kQQtD$=ziQrqLNUgc;kkG=*Z*t zmKsY=ybS%X=r3h@-#*i)_vuRpOs`K()$6;ej*j;v1xSM4P-I0`?x>O`lyzuwnqiiqS_cWmdMQKqira)MzQOR5(Z!Q#gtj zZ{JYRBycbAdjzY2(Ka1=!%&z6^I<*6`fANg*>ax6ADxaiOdQ{_R|oIRkWTR(IwTAY z?OkkRGfQb78tl<4UeLJ*NZmRi%Z?TEOH5U0KN}AgfsQyKH<{|9?aViQ$4w!h$=PR= z@s!+@`S_RlH*x*Ni_}>F$wxSb=b8%HPJGfHF2bOv^MiUvC-MWyy-|7W*!#-ywnGLh z##;{^Y(L)q!C1U77uq3i&6?G)27d#B?}lBuJxwc#@8)8(X1-e+*X=fS-Cpy~u&d~u z{p)?^SGI90Z&SBY+SYR%DL9Tqhhi6QdsFoPjxCh_Pqy%?*%Y!eT}hdpm|oVk2E5$% zHt%59X8Q@ASB{y%{4|NjZqapAwAI+%Uhf8&)0gs>E^Bv8C^a}|sCh28m^ znC9?ImNZ{C^(FYlm0cIY6MhnBLq6}%<~tX|WuC@EqdJYKQQohy9F^}7_BBh$XE%k< zl!S}jyMNsh{=mQE%Ar_rC%bb8T$+O+=U zg4y$n1hd{^>(|WfpdPHSX24VuJ!rvpVMr-Y%%^B^_t}I>V`cau%VI{%leZy(MB2qPI5E@#m2=h5wjfM>!ggSa&4Q zr{h0m2V9(%Jd1O6 zjeE9)rUEd}1u`CT&~xx4>1+i*7XH9?0=>Q`w(dJg8vWdt(>b8;$meO;4*no|)PsEX zvS|n1*G{B^ZRL&y^m2CLYP}j4oLIY~T+qKO@gwvH?@##F>Xv5DCIAI1CkSvjMd+wrS#zi~Bt{v#SAn%)0heEv_?J~DpX$Fx5j zFst*4MA8z&h{XyOVnsIR!IB8Eq0G5?Wn31+%Hs3nFPS9l7#G5a$`#Kahe?h}kD;}E z$dkvRQlkQVr92rL8HaqqmnR&cc=CjNTRic#1gVzb&pLb-pXKJhngk#GRmV?yHLs2o z*%EJ$)!)7)zZ$!aZ;3C)u7f14^A~W0+gv4)#Afl~ib!M??r3mRupFJ2kJNB9{jt$r zzSd=p8>~f#-E7x7tal^6knlg0qEILCI0H?6;Lz%CE)-Y7(%$nnte-b;{f2p;(!@42 z1p<1%t`^dvojIETxIlW_6bLQx{aAZDw8XY#*TGCDn&~N%gdXEVK&0kTbW92%ag3NU zU*gdDay%#VmG~0i)=W%23x5GGZW1EG2RHFz8u~)26X;k#&tS27LR;cIvg8HH{5+1P+_6DxxmqjfTG?UiwN`9@6Qz_Gtk{9-_O!+%^xSk8 z1zc}TlHRGSYy6|m6jN8%5>re1tR=>mdEB_d=5Zd!+M{Q55M$Ysw!|GrmSIv0+LFgK z@sXvqe62+-NGW&G#ITem5?`6rn(lrf6!E1QzRfhTWZ{&B$kCh%$FOMJS8ylpug0&? zFQ#*KbtnlL#WsrZ<%Ot!ZDb)%;4N}p#Nuz#Ga1=N2k&sHwVS1%#KX?jr9-${(cUGL zX1aXvL~%KsCc6x$0L7^GYrhtpCGFO_*4ldbueDTI*{!t=X^eY7bE`iWeiK4Ew(OG; z&vvk#x&{jHIPrXkf6D=n4-fU9Qr-XXN^HOKaR2J+vO_E3_mx>eojV6*UC#ch=-x z_lvGji;+rOb&cJj8&=SV>A{)TY4b@(4wY43&+3>iz0+9i-D^3dKrg%(PdvBQ>$AGL z&%D;2Ba%e#oL=6`o7*X@&zfW4drFK(C*xX?RJz)a(TuVlEg9oFN;<-eFzRFS zUqQZv$poW~^WPT#@le@u@Q*?g68F?8{KeBy;+***gF-^XBdC#_wlz}4(p%9;`c9gR zzp5+1>)9Wm9aa4|4x2dl*oF;9=T6)=7rahG6pX?v@YU1!YZ^fx(!ctirs(OQAXHn_>rq=fb zJx}k8dfxmzkurWL)BmBB=z!>2tKAcLg?;obFlR&6!T{YuffjSU~8eyuiYdy#oQQ*#v3`n75V_+OwAQtG`Suv7@t>bU8*L<&{XzJE){G z&e4f(Z#3}A2!9_X^f(D0!cuq#91)M(&3vcFx8Q|CVffGZRTr$3aqxquE8c*glttp3 zINnJHm5Vhl;1BH_>tqmm#?~G`6nM&u)H#wbrDtLt#Pc)auI>jNOTtnwCP|tg^&Bof z%cV@)a>&$^>-%aeE&#S4Plze#P4pIx!fEzb2^RG=A0zQ(J38z^W)DJ?6ZU03Jr@<( zoL~<3c4(jQtB_wVKlcsU<+!igrkC5nvdbyaYw6`$AFf;LXXYWknv6R0@g(bUF7GGg z#_%<7Fo`fYii?+C9Adk(Bn~R{_w4R@898rv3H0*v>|{EwR-!D^6K-%L4(>1=GP_T# z%ITGvCGDW|HFO9>dUyzfPM*a5aS6ZqBp*zmd&oD_`0sn~``%QTl-G+jS>8%-T|-(xg~fs9Y1o^zz|h zMmx)TiQOV+3BO3S(RsZGjRE-Nvf@eoZ<2EoqlD|L5aMmHHC$=)iN^5evzgwvQ7B8BOFK>y-Oc=Y3FAK>51 zC5-vyIm6C3&1=;=~T@D|%I4sJ(gIt&4TiFNa z9b3wmHkfkK5~VQ5)@Ifrw5hR>+hfkVB*xDooUc^zU7f6CHbQ(V%K3Iy>UN9d>P3>X z^7Yo2+zAhg;i^I*QdAA*oJ_5wM4{O~jvXsxVyc)0kLL-Iq2}?`uw`>g`X%lP#LeAo zIwr=367z)llJ@w#na+~e<1nEot;OD)tJEBTsc*@@iOlkqim{h&R*Vw$;&2v+(_Ip7 zv~ssnDN=Zq6B9%ta7XQ2ofJwMgwtp(U!<1U)w^C)i_#cQMUbsgIf^T5QI2$rp1+_k z_4EMBywo(RGxx=P`O(@jcZqVW`WNZzk)^K4uZ#n!}e%tRw-F?nYa=%HDyKc{uv(RP6#4hpaMt z6h3gh-TTSyW1;>v{-|#pL2Tr2`x<-HmoT1!^IzoXDOuzIJ3z$0VSU!YalPhJphWTH zaX4LSQBdsWtx=i}ahbCO(*$Lr$=8Tblpr}yn$)KtJG*P(f(g^7&$w{n{VCI?m2XH2 z%gX9Dh`YYrlw02S>n{fsZ=Ssve~!Ojvkq6l^7R{uq3+mOSSMTPKRPD(wxoS2Yza^|F^ zCzei{c``2{@x&rWW3OFkhH2ux8=R&0r zqS>%;7Jdo`JyObqB$P@$1-|4@e+9=|&I->wl|NIXt|>f~89wXmG*AT?3%p(GT)Yd6 z0V{LXu*35Gu~q> zc+Gf^-M4LXzd24kC;vA-WcO{`+-H4c_mwU8iLG7J^b?O{J`zib3*946PjXS{D3?j8 zqw3@D$02$az`;=}^H&LkfWBbUZDl*peM`~}@GDF?KdwoFe;qs6%CcteEyxac#Y;Lr zlSSt4JQ&%F8=X`=f16CYbF%3rp8v?k{>l+p3)8RN#xp-`^030Dq1$+V-CqJ`9821g z%i2Ou2t*1Xme8E;7!VHZBVh}zgOf_I=iEZxkTGPRXSJ5l zeCAE)x10D*H0q9w69Q29BhnB&)ojX?t#|>2lg2|F>5W@XH{lu>j z?+e}q8K;qi{|B=Cq8=D0C2&gprnE{$in&W`CLKRdY~ zg^dx5+sW(!jm)E!$&o&s(-R)yh<0~U`4WE7c{xNfYtOAP9rEY+yu;Eu?qCmq&7m?o z{P?MV`(N=7)_iCZ-;dj~%!J>8PjL_e$TKZl{vXrV0HDV=kk@bP8yW=JkHFLU<)lvH z=SxYiqvVJVfuNY#IyRL{d6YOfa<;7`iaulDxic@c8s{^mR~K^-Us_un)NV;kaqhGi zT8F^bZu)(=Za+j>c|F@SUmn2$pDy0i09u5Eo3PARg3%ByXz>#&ABrPVLs)_IZTT7Mi;xAS%02>&@UCtkIn*bMtGG0eE#Avmzoxx=6CmP2~dWYa^A@`Mp&{an8 ztB&qZni5y+tkO8{@YH7ZBXyNFHS#lr90I@rM{SFSW+!z32da4KPFMK0 zg0uPA-!*yG_dWVKY%t08iGTC+a4}3XbtnxSp*xeBTMzf~ay8g-NMVm9FnWjZ3-75RaV5uD6!M~f%;3#|) zvfvv0S=>GK7tma(+7r1MR|b z>Ph5T7JQm`zkfX3H+D}cMBp26UYBk91Ra{LoxS7URh)yr#`B@%g{UK%{vbMH2s;PD ztb`!~%$s;=0uLvij3QML`f!aJ%u^#8A>Lj@6g(-t8s!}YJ_&YI85oP(xq`d<8Fmvt zXt{~Mb%*stJ$QHD0G10TcZwwXA(Z#U7mBl~f*`l?e_C!sVsUmWKSI--o3_O}P!S>0 zdMSNc!p@(qm~q$aA4tIs_TX~ti0+790&=5XK`TcASJk2W0b+1@NpnsWUz%4+lG>cd zNI~~aNwV9_wNw9^?k#I^lSQ-Y&?=6CxS*ea;y-~0rHlG=8Z^6nYgHMDk9G1^IMA2z_3JMgxR z1*yYykJO>s?b2Mem85xHU@_ArTiG=mYndmxJ}=DIllFv3pOI@n);@7QpY6-nS^`Uf zN<*+0fE^&y>TUkf=FT3k$-8lS7AA%(`P{ zLwFP`vLC)OdUPGy2MM#=@Zh&~Xr-A2!Q5xM#umkNrZDN!DlDwl+izj|-op1TUw*Hk zE+cz;F}On_zJwnYZ#R4#Z-h`{KlBi4jQ= zPE2~Fh@sL56yMF(W@+WH%3-~N9lKnA!A--ReM7zNjH}x@ZY{L4&L2MXKRuQBkrJ)G z4qMkQ3Dmgtc?XY@cC4#2{Tb-2wDh$?dA5qtk8vvgal$x+n%C{byjy9komqmN7HRA( z$uepsYaI`}NRP^naBD4;M-@jL*4nMHSnuK_aST_=!mLAG=mGb}@Ea^s23-Mq`r@gg z@#$elhxEgoBt56_sH4P)oT7V&f}=`Mi(X<_OASrHz-cv5!k<5Ldd-GI_z}KD^C}$L zuHx1CTGTKyP*Hud9NSOcTT*ZSO#r{d?hsZP>7E*Wh7DDsW#Xy*BKKQ58w5ESsP z#W7IXOXNX94zrO>-*TtfJ1j~&t!{fpgTdK)IX-ip7Z9baP{XZWZMUrAclDn%Z0WjxgL%{k+^ z9zxz5a(@QP)pdnQl92ZX2>v|F)*7uP5_3EpN{;#0QNVRP{vGKZnzZ?45IzgZ|6Y?O zG!@sR2~C|O;YK&fS{uu?jbKfmx%MSJT;PS5HWH(pq5V%=~)sReR`-I>t3E0A|I(+vbk;X@E z7LIRNb2rD;VL3=A8m%p;LvINlHWIbsL0n_pc_+4@mTVzKoRX6qv$v9k#Kn=eImLu# z_AE47TKHO8NaemVsa*Q2!s6H7V05sRSlCJA_7a&wB2`Lwm4pLDdZ(5z$q5@vTMLEM z0V(2yFVHJ#AXyzpXKMU87Cr%4zYA_3<3|ws-dDZf?funz5Q-mt3~oeB_M@JrU5#_l zf>SsYJ~?F?&sC!$(|&QjBZ}z}M?wDy>);YgNu1Hmg6DY7(!w&?0&&t~a)~9+SrEm? zDIwH~jASF-)VPOc#GK)!o>Q$7}q@WM;*H=Sa&kluNv=RbTI#DDloFKHzw zE%IQ_q4@e90A6g9y~M|8VeerB9#%4i;`Rd;S;S~5TPu~UwXU_3hQtZ{+)7WeCVcC3 z-9(fV7kr(nq<1lDR!Ia01ig7bK%0FOudmlrnHBd3$R!>|OTwXHQV&U}1tUtB;B&DfMyGl0>6zvc+2YdIv?V zMs1mp+8*6kHT{V+&g)=ZUyuK~{__0>u)I$1Kpa=y?!o(4AMn#BTj4s~gd6cbt99$F2qOSN zh&`=dJ!<#h>iZAcN#3ybpF?!gYNn%oj4BzbwX)#XT3dTq@E$VGLt?`=IX+;4Zo+Sn z4mHO$BZHqq_4wR6QH|fB>PFJcLn%y;co`MSwKA}(wY9VKuqFkDs#&mmmO3Q-0pTKZ zyyvKv2(k08SBxAtx%m3^@oT1?ILO^bfL-3saqogAz6?SuIyqgYb&Mf(l(KgF8Lg~6 ztSo4I!G@_(rbI1d)~J?r21rF@q(TGO!CB#pFKtwvdPu&^ZI`mxfpN|HImBp7(PIw~K;u4yEJM9RWd zb`lRuYey>j;UTmR8@sg@haIizZEGcKEzNsyTB8bjz(&X=1ivjAiD*b=VpV5Ea#8Lm9IXb zh-P0)dKdRNoGwSw@%9zYxU$Oi=Bl~3uQzTk9^5T%(uCq`*NQLFx-U>guqz{a4Qs$1 zv3_LM39QdSMrVt)Hj=egwU!!Nkn<8gTp2B~@vzc63U*vDAb z(?4Ik_VcTn88c=y_n1^zS^4D`G(u1d=5>{18!fFZZNgo`9FRM)X3w95)16LEmTPSe zyK_g;5$Rfq>ZrpJ#ahi8$$Gc8pw~u`epqTrL9eBa0D7h7#N*U6MCK_2!Eb~+hc>J^ zeWtXZ)KrVAJQB-Jzq@Y3A#mUN)>~WL3DjM=>W4Z|_g_Z<@Qn{m-q)`a+QgA|t|slY zmUu|gj6Tjz_IA9&kz1=+L-5Xew|1nJ9<^=~4+k%)hl_1H8xJ>61>uz2;ZGEqhwOS3 z-gbS^n~Lb;#;1zMPoFZ4~S24L)x&7kp-AK`ECrv&r3bX4x1kZZp> z{bYWU4N@$zl{#Amjol#FCm~K*>HkY{%I5#pZ&3d5KOdXpl+|7BH(<_47N?BED@W&a zFM;>*$N8N*7p&PZdejU%ms%lC88J4baleyxNhOX(D@i?f5opRN8R6B-ECmwV-$5Ld zlMUz@cdap!FI~gNW+?uK#Rjw^nu+3K8M2qzDP=ZNnT1OmT&$?Ky$JRe_5TGIs|-pl z^|;h>J5cMn-zKdwbzIXq$_qU?iD#=V?7Y|DEbzeJz%jTo5Vkf(auN8Cf&W>iZ6|5T z?aX*4joC3`A^Ei|wrDFnEPFE^zW8rE>_qXf)Bgi_m}|kqz!5yG*&}Is|2N={o-5x| ze(or6zr8PM;!AN3;iM6!2&6cSw?V(drf28|tim}h`^nf|AQroVCS}(b1 zQ*TWh#P;qoW>O5b$!v zuS9Q&zk0KXpyt`R_y(8&6B-)ucl1ABYRX1OUu{L-VNZBua&1k2hP$9%X31Z)LJ|wY zVNw~FYSTOp)Ck`edn?AcYauk^OeQk!G4TGYt#8=dVy=Up-m-&w{-O*?WKtmITQC$x zOK+y6ST5JAK@iPXt>!0LnLS(26)V_WF{$GbsY5Q-VJqS4r58aCL{h*)@t~2N^a^Qg zj1wfEh7kRv0e`^x(JHuWYt~3w^5(MrMtzum8$hlHvAoU{e-AJ!-Bk{@R*o(TnJuTX zl1pq`A@KBA${PfFFH+c^Z6{mgC|~b<$!?>U;>i=bz2SLV6#ieaH-p|z8V0!83Mtj^ zMCKfn416PtiNl6XeDJ~hUp0L7{s#{l8ptL0naldW{@U)c$q}p}hXzk6uyk;EUnSf&QfMg%1dnq-Sx_PnH5~L{qNxW zQp50y!ZBSM8VrjTF1m{Tgi(0;z`kmK`0LdcxTOhto5qYKb>y4dO}H^yCVi@ft2+wXZszRXSLu1Q2cB(_Zl2jlryfWoufhXpF>JG&h)-Uw~rJ0D`+!1b55Y;BIS+dOHfcFG}hyMU&YY zfwB}H%v$Q;qra!joj>XChQHwuNN)c6<7b-+i;9X&n6NdD-Mwee4#8HJi+h7OqH&xE z@}=WpsnRHTnXPjx+-+r3uOLLUyJ#!G?%U08jts+mG`W#FQzq9VcpQX zxVYHVNVI{ua>RHcn)TO#_!&+X^)>`2T(oo$FtSnHq&TfWo@ByAs!&hI>_L*qr*bgd3(u1IL|L~ zx2m_WU*ve!eZ3b$SWm^|gNLo`(+~3&6m45s2xvP>Tt;nPhG|(BpvyFVmy*_%?knkO zY5E4asJfKw>$@_&+lC&*@%3G~0ypMvjyabQTRHI1viZ5AJ0)G{5Gdp++_Wi((Wo0~ z^D?$Z?jcDu>de@Ck>af7B8t81Z9FczNn{RgQW=HbvKHvg^ylLTts%F0&t6n`WE;rs zFF@`OM`vYK4$IFUWQtj$ytR4r*WYhg|EXdL(c_6%K7W4U!q4!Mf+*rfJ;0w5F!%$g zf5mPz=rxiMgvH%sW9cYKHrg<(ZK0H?DAayHFjBRzdjAHo$po4BIp1 zQ2onaC+#0ry#;0%uI7N2+rzv6B-HBk)8TeCKe zV0Dl0A%BfGvy5K03+>J;B`ld8=UDHoTx4~YTkqv4(KxGYCGu1+#q-PIjp2&R!um%G zb2=*154$I3H`@~If>=yp7UYZp@B4eGo|Gn(ry{Ew*~C_2%TG@@vx{hX}(q{{3L%$BuYYSXNkn( z7^kq6$%DdL)^ZiXS}vk-Y5D66qkGWZii#jmIuUXc93^iCQq;nPI})H4^~oo;nlsYF2^IKPz^n9rrNGxlc?(Wyg=43P>l~Me?GmtDn{|#$ z6rYAbO(Jlf3v$Z2+H^Lmt0BhIP_DID|~;wXtzJL0Sk-iKd-^cqy|S_xLG zVDfD`wZiw<@$jKYcV^!Ros=xjVl$<*l=7rl2T~JN>mGkMz+T)-uv$2+K`><8hbt+q zR^pE+{kabtKQ260BxyZItdc?hmc4{@zW{P=Sr3uR1)RxA*FvqF&94E>oQa;9uEJJa3eW4{Vgr6rhizDY@nBYu7-vVIvAD3?I-V$OzfS9gs8f}r z$_GErN|+lRHD!vh!dHh=CyaTDKf=$aOs>n!ya?WJZDDjEJeDi$B{rAMA}hCzRZ4@q zQ!m*p6X7kOSA@YP*@0iNb zIujiS$rI9-BMguJ`~41cFT3Ni`Df3+(25``54H*pbt-;>mTv~~Th z6yH~O?$9L@I(;rw-n`~3w7rbfJ*9Qst=>I(=~9E){i7AbKbW{*xHFs)-X$7~KPkw7 zpo;_%&?+lW!3gAy*PX(vgu3cp-k}wXc>bUu18v`#x(7DEGu*I;Fg#PnYZ@b|W~OU8 zgzjO&cnqX;FA~S&61ndyj7K@WKUo})5JHdb!dkGoPjqVp`k2rH2k}+7BO`@0h%G`B zzmm{EF6h)Y&woPuPdrHc0qZ_@;K-3ToZ$pXA0kI%8D471)zRk?q(k~8oOhn6-cZ5AQT*lRyKZ+Q-}M&j=CI4n>t&{ zFo)#R8=C9BdiDI(tLFL*YkvQIje)+aBJ?@enqSz-9aaioIQX^{ufXH(!*iVTIix|i z&vBB#IkQYtIVW`1^dZulXu4ZT7NOhR*1XeF4)=1=Wfg9~C+|Q59(4l(!2e@BO5mak zI1!~GXFMEMn|`F_EF$#iD!psgajiEQ=#`O)K>o8G2z=M(4F=bB;i1OWp={RyX{im| zH}5SNAiZnK_jhe4?mIBsSXYKiGT*q*gRMokT0`wF@)w(vYh{B+HOu>8o(M48WvqXL zG7f5%UsUCMVr(mYymkUp1YG66^zn4FN?`gxI4j6v;J!&Ax2j-Rr`MG7m;Ovwpb7s{ z%6?|8VeUg3+p{h4ZQc52>F3kRhkVPLEvk=l{KsV0T-2{wg$U>GC?3(!{8Dc$r=7WR zqAF2~Z9=v!+Jx``;YrE^Ui3t!jGbhpC(?xD6T$+B7#f)drqSs`gweOj6Ieo%dj0yH zI^@$b@Q;ahOc$8~Ccg}zyAwqGMCUBpv3lf@Z1=3W5}KAzs9}I>92b_?4DK2TzM7`@ z0k`l+kHH%MMWNkCueQ*PsKk!GPXN($nP+oMu;~pl&wn0~8_j2NMcz`%IGXX!`Iv)+ z#91C>wC!h+Bk68ol!RD#No0M)%xej)cy6f3i{>-Eezb(VaoASs%eiM^{T6P^ko;$>_|DINR&{(@w5^)Dwv%e*@ z&yL=&ki3rDgnc?_f-tR#7US`zk_7|F5^%SHbYQ^abhvqBir( z!t<@$+oKh}Z)tC3YkINq?A2yGZ9H66Y&>13dxW|sdU&~pct~9BJ2J}>OmYN25t^L^^uw4&jZHqWiN4wCsnb1Jk7X3qlN7RMNp_MV2C?)qECUpVc5RyvlKy5 zz!Jz+1zju>*s`~%Pb}XJ-g!pP6@#DAzh_&k_Ur7(U8H2-SR+05tBP;vs+Jt zt>rbHw`ZbPYKOuOqxV!Cm}I=>(5bv2D)>hh;xk@7@3SICd4{Yq;5iMK1ceD*?yfNA{gns?T|)9g%JrT+yiO&KvMG1{DSgM z4xFs< zy4KQg+@JO%!`!W}1wO1Hb(VGu@%256$XBiUvt3+iUoY#hq2#@p9$>YDj@R9SEVl2B9N-rN1$+u+RsFG_{3~{dGCjE$3#3v&BB2dRQazwK z4U^K`FL#-BX5xg?v%1Wh72dl#J#BLD@bKP~(-yd<9#VLR>%1d$$^|}ptu!la*gKON ztGHb&AFN2vT>aI`h=cgs;X5m1^&|HDynjrzbM^j;#`}9lCOW$%4bK7hc1E@@p0sfa zp^?D9VpbTTRg8zVQjvFAt2o28sZ*0C9jq9&e_~?t*!|VK)O+>j@H+g^l>bUeM9r3cp%mlz0%C$ zY$98UYHfYuOFMa5pK6yr^VXbf_Y?YDPxs9Mm4X!1jC)*g@oph>)teYjWfI z_UP7e_{r}5S4D4owZGUgqUYot!`}LELU2gO1tz5QO{?5hl^Lk!t^G2lpPpkAh!O>Ea-aHUMzOEu6DsIgUFls`glH12`9#VFs z0AlfceP!jy(ro8;9bJU^zkW@h@M8#lgXyVDP$Rh`vlT+4nJhUHL!x+1jexgISOg3P zesoEXL0Ox0X+DJ?j!v7H9}<#3F>T2C!thS7=@nCQe0tZ!tfdJl3%Tig@rP3?W(|() z-?3+jUq;2U%I*Q#$^Cx<{#ZpA)ijQdRMRA_{LM5xeP&vAm$)vi^m4m4dRhA>t&FSR zpp_f9)V-#Y5!>rJnb{XDJMSo`QO5;tqFX^7B7OA2La$y+e)E$@{x%anZ+sCqI6bg? zQU7B6#p8>M!Fjz&pBz81H*Ci%-D9LlCk`}T-O(<(cS6oLtKXgt7#}!zwsCUR7JZ5y zP3l-e$CUE*Mqx}rE9ivRxP)_rIq#Z{ftgDPPHEiIVhRKkOgV*?X(VMXCw++#?28vE zPcMoiC6U&kWqx}}y?lB@Ead4_%U0~Ou(D9=y ztBY3+jgB6&yePK3XPmvVYiZT%eQs6`hBnr3qj>;f&KqnWS60{3lm69^)e*X}P zpIKj796zCS(#a_QU?IbZqmxwQAIwp`4|>0D6Sj}b_A#?&=D3APMbQ<$9jo=z(%{u| z+x8tpG-=~{qFapzE5bu74%Rq2?ti)}xyzbg_wM{-b2rr9MOD|%6R{@H?|F{-l(b3a+R`O_IuXH_vnrCsTylui2R)rEmEGw*FGDA;swW@8_2b@$cd zyHok1*km-*-zlVIMweispA-0I?lYs6$fyJm9+@eT_%?%lynJkwXyb1OUN3X;VbK$3+KXfV>~^= zlDejOMOTj>(Ia%wzHg>Y`tHJV-#W*Y<(^ ze;0K5{}Kxl;`|?B!B_QyjUaqWZG75qdr+B;t3DNSjbUs#y zDbTh&svt!Zq-`nlG0qhY5MPS-n2SXp5{quOLqfSjNjry-{>RgD&BaCp%bIyZXQqSN z!$Kn>o1wQt^T(znjqKJTdHDQg^M@xJM(r6}wXZVzmRnrkBxB!rkD&CjimHmT^q{0^ zCnr>2u1$k;nd7<#_@xi)l2)1=9NMY(jD9_qR~U^I%X>uhO7Pak_6#>GE)sYv6$3#YsIb7|Pk&*0#Zksw>JBJ=` z8j|4RZXCL9V63xq9K4NI_uDo;Ic5CzlG5!HI@`Jiy5my^pFcmy?QNenc*>B>K>xJz zq=dm4t>?YinHEmcm0VN$1dtXc2=+>D$I)Y~!5p(Nge{ab{5W+jlpY)ygcdRlrX=m; z7brt=50EQ=knC$4jD2m6cmhJpF-9qUlCa!CEueZxacQ$jiis?~v=;a6qkz}(z{ zkxJx}w|VYRtwLkNJG*-gowqs9!J*%pA<>+E_QEcMJA2`UvgG-nL)}feV_<54MrJxW za?`+&#!n1`*U)@FLT)ORj4cWQe8yq)O2F-;#WebD`%ibw$d%q%hc7@Po0EXa{9jye z*+|mw@o&lL8VdhA_nX|8<#V7QAu553(hHr3N$UbKhQx~f=b=Q3kpkFEyWow7&|H$NvUkBF`T;h|{eRQ~s>qq7Pe z?R~Px=jwYW`)NWmBfZ>}ZocZk#6XQLcwHiOpXPt()iO2nU#LFRoL+=(@V|p@?_?%3 zLz=#0`>lw*^=*aL9mTV`Ebfmm8*WbZhQhteGgAmO+GAtqlGZ(LkDGf&x|{p%-P!?( zYsRE?39dZ963sVFpFrT?@EqZzNZmc}KLI#1vN-i5DbF&YSmiyIOI zfi*|5vp+eka^?b5XDVQk?Dp+J_0ONLT~fafJ1)fqGOIoP%N|l0N+)H_<0lXu=+)8# z5xW}%ms2NEIC@1Y{Jc27j_U>w+BP~aZuGW61J?(i+_UGT>HE20Q(KFlFU%|KvG!i= zf-lzR7UZpL3?a4f`*7~(_hBE64K{{cmWXXO8^PBi?{U{wtzxZiZn5ceT1qKxHVePU z+6zvJB20ob&)f?M@OCtyo2HQAqi4-Oc`|IznEkt94?hBDEj8Vxh5cd* z-P34WpdjE3X^45L-nCK}W?X{Fh*!DrTfY0qS=^D^v(_G|B zGgvNdyu|p)Jhqyabue*kUmw}VEzM-gK=rg+jU$$d1B)cdq?{$BoFF<|4h*{@k=B9} zOvZrfB(b+t>qLpB7;)24hy1Cz*;QHo4GrGu`2*tz@1D>_I;h;b>)^==X;rx$481Dj ze3SG(^2_bQ+q)>d4Jc&rw#vA`qNRg~&bF%Sl+{tybN&6fOJ}_^IKV$+Xi~STOkW)5 zl|H^eO>mNjA;5{!o{Zx>LKl0wvH@DLb}Gsa$`%x^XXn2(oFD!*wlvkxD|yfYqRmc5 zRvvt|e^f+x#r|s0oZQ3R>@;Fy|3On8l2Pe4{TAr(@1{Dbo5n@G%pPzc@ZVCVuFm9Q^yotA;@m zR(o_FnbUn_io49!5WK$I$P`b$v@U#9#o)lnAFa*LU;EMIdDj=`+8+gN+1gvC6Fpat zN=h2Fx~G2B$iachm22D5+d*7lGqmjfHJol}C8IL+t5uZXsQRB5D3=K6cf#EF86rO# z79S+@CGF!oP2ccDXh;vKU!buAimE7yMSfOAv3U-bu~P5`sC&@tDbjA+aa@WfKvOiK zt6PIQF~2;v_rg;B<@%VsXji35|9*^@+9%x8+sic?cXo~G6`wt#v!^<;UuMjJ^gwBc z!?vz=hG{Ey6q}m%b;yYHNFKjy&;=;nDDRlqt-V*GTlf6XFxOBYjkU_Bv98Pbg0QH* z)hPw~NfSo+8>;88W_(EXVL!8+vx$g*X~Wg{NE==xI`ws3h$L^3@eU`n2&5<*nrF8J zq}hfhIs-vyZK)tb+IzTgS2uBg3L)YQ*tqt)*39c14O+_qiv=nD*`IkQU)?tlUtv0)iGTE!jFQ z>D60><5Jz@`cH~qm^GuclYBgWO67yJm&%7m(A^?K&{+&obC)xYfc|^TdK)#E(rB;w zkfkrH1+~p`OB8S`#k}{;8C(tMi-se+@XyEi(pQTv-`ez2@IzYF3Bsg7GaCwZf?^Mp zwlNmmmrKpO_-dFKTQU%*dlF=3=Rxi-O0?Qe1~cSpuXf1QG&V3L zv|ZeQX|tydi1W`J*;SX`CEl^N%SSVY9jNZyso$h&llpb~*rJ`YYN=~TqEGn9s>#!4 z&6$@HTiV&j!8g)-P|@(Hq3Z`^u3k2OT4iaLSsqyYoE|S}yZ#`w_=;b_B)+*#e3UR1 zl?YC9ItfL`Ju=G4j-!7fd-&LNRu>=Q>K&I`Iy|!D$kL>+sD9O+9peL%d-&@ToDxT$ zS&(hxCvGy#6Q|sX>D0qbob8LB#pm^O29*e zM*rJ*NcsOA9wJ)8DlSp*1@@471IX9}Q}2WzZb9(1%@cA79G%!Td!D|6t>Nh$0sR2+ z0pdV7v~#znW9HX6%sn^F-AlpwL>Z%e(kE`n8N7dLDh>=PND1`p7}?P?JaN|Wlz_~k z=$Gyrmd~F$x?eYUM|YKcsY_6dSMsuS_t14Qw^H4=iV-U0QW^i(d1N96<@k<;DFSr2Zr=qHgkN;(%BIsCoRZHpV2>>@(+;*4PQd| zr;zc_U_!fL|B}fT_up@@pr!ZWjsKF#zdv2hRJ9;y6bo0=9W~UpGDAmLui5yu9e#7~ z_@Tmx+bZaYcP)-kn>j$dL^J4syVnddl@Q|>Ic)O~bhm{G#9Pg_oyCD}jh$LB@oTo- z44YnkX@CDs^6(SCG5@iv{yOU)!SqJmJ9S z_i^6+HhXf}*)LAgp0r^Pp@R=WK9PdY%VN3`D--3x>6Ib^A^t910#LGJ3oZWcp6JP! z7B*zoRFrkB)^^S58(p@sqEn|)Zw)@U;9_-*DQ)W5YBb3`vt~fa^lUBaJoD~`d|V7W zJ)&~LYdT~Y+_~V6IiowLjn4MRUDM`Yh4m2BJuNxc^j*=S((uMx$>X-su}ULtu6;9~ z3w9t);PW4GzhSfqyIIgJE?3CiL-UYPhX$HHCI2wyaxt|}17Qa@63t?B zDULo-8X4~o17`u6JqtI^M6(iQF*~AV3Bve=HGR&nk$V%`Q4LPR?C2uIkiKlolb*#K zq`z4pCz^$u9?c{p3=UGX*4|1p#@VxfwTFw1N3fI|V`=N|r>b=6P}Wo9rFDmMTV71Z zvXE8q=@+1rIfjJ~YkFF}{X=6H9WVEB>pR6x0}xvIjyBHQO)hQxz|i=~Rm%L4d}5bqVRQnfmRgPucs>HNt) zFyix+hX(Q{ZlvsYAtt9eqc@EWN`VaB@<@Y)(%1vY5S8s@@UV~3I~^R|W3W$oVrr5x zQd(xK)p#m+NA=!8uoRz5Z|~gBCAT;{ke1ErmMTfzEISdY-J0d%WGx^}%K5Tpm^xyC z|Lzk3{twG-LnC(+-4R9Oe*{BIqFJX_DQP{x9XRf~OeVAN4=F54`?_Jsg_8b9yN{Tq zk0~mO#u%@xj)>E^7(xmP=4ZWiF*@dS=hTYcVI_v%1v3Y2AhbCm$>%$AU(xtdzBB}0 zlsP8}jWVTS(S4oNjQ1&L!I6-jDG^Kb293v%0c90M15@>3rEoQ-Q(C8@4}Zu%By&+~ zowK^TOgen)weS)Jn zwcONve>%B8m!6x%HoTrcPVQHU_Xpqv`aHJbh%X~PFXL;(y*V!UPyQxfOzw{ro^Kjs zdMp8CLx_7>rWSHxDs{-Fp+Tnp=LvhK3%<%9Laqvbo13TuzN(Pf2=?czrYqc^d^>Xg z7F2SxNiAc9=bN7Jhd3{GzX2_1exBWD&wmO#THP-seb~TUdHpzl zBY7qWho|Lw<=~gWC2NON&B zd%0f&%`wBu+y7A$pu70$xrW@FTPeI-iC9R9pq^GqYDK9m6Mfq@ZtPBm|76JG; z{tav3^aDxLhE8eIYRAvcO~A+ZFSTr_S<%!al)=^0vblUR1~Q)IplkBMYJMGhDj^Wm zmjwc%N{~=bPlG~>`&IoTLO?HsjHQ~K#r~y9YSiZE{n?wa$kN>}uIre7gT|>G;&&9v zQjo5Sj5nnVk9^rQz%vW&HW$(tY@4Q)jXs$zH?g5;`Cwd zeT-d)WL?e-Te4waQDMXM>GypN9YTZk1F~lpPZ_wcJT5#w**D2jYg=b$)exML+R;}# zvYV_X?r?6mNoPl9dbCph7Z%=L>-ZH*n!0AyR93C{wh4+Y_`N{O` zy-5+}nJ&(%F76HOR?j*)j_#|a^-EJ3O{S7@mhmjFd=ou~_MN1G>LnV$PtE_+&_HQe z-?W2Y#NS~3XyhY_F8Pt^5>GspA1kH(yM=o4)5!ftjJ6g{AMkGx+G^R{Lo+rILgtub z)-YCJ!LXq@Uz1EHGc$}RD5yHaFUQU%WpH6`x8&%Qj&U(@-7-{OfHL#pors2lnVmN_ z?0@@nMS~q$H>ub3gb93BE^p_dbyF#<>ZCwJWxmKIn5+=4z;Rnw9c-T{OzGYK!|p+AYv38r|i zg$hDObh)1}{YS^YC1bikH5n?LoYg^NkZEGu2gkamRD@@`T%DLygtlk*$?jh7W>Ge= z@Cf(^I>vNzRu?L5TvJloUvTTzt~*x4ll_CE0^6^eo#@kZcgN@zNjXHuC6V|zznCj! zJn%ERM#k=EHg?R;psxtZp(hNy<;^O~oRy(9s6%$i+I9d@F)_t`Gn1>=U8!FTD|gN= z?XlZ84+Zw>Qk~nOLridfcGAS7Tc@nLnwhW5`0aSNlR_Q|VoT9n8aGR*hp`B$0~o=z zL=B6Wv4s-oQDO&YeaQI&UkKjU@zhy7463$03>)8Zp?>VAF$ulXW;rY2a*Wm|DyTi* z5bJ`U%!*>mEE;YqQs-m}X9O0r9rMujUI99;d?&bq0^QJw%c zmqPv8m4kF#<*WfKJF0cMZe6{D1NEIc%vuv4o}N5E-o=|oYLA$J4qih#m1HygU_;x; zZ2K5&L*#TU^D|QTQ`{oi1~Ff_!B@k+Q&5_z0i{XnDrQ#TCFDn|XHA646sNZ+7(ufD zl0a?0IqDsWstEz}nCjIny%)KXW()Cg)H;nwaZgP5kG6HNb8rY&N3_ezE2)Z76xsNM zMsMMfmABg2O4UIv9q1D%w~Z<36`}Eu>`q1#Dv&h3Tfv5a%Kq&#pUUMLXKy!4TQ^^o zg+yo{cH|Z{y=du+Z>zpwN79W7p(_L*vc5=#{OaOU{3-S+?dM6>PfzA6y{VUiN!1yI zhmfa&h}3MloUQ{WZBf{Ja0Frc6)Mr z`$WEnV1HFi`q(*zv_($Aixs0vVOMva)Qagqx2nnz$w&x^;HHGB=z zY~4C$tn_(eVJ~A+ufn6>Z{7O+TeKe%Li10g7icU$h;nS>^!fSAL9%s7=fKELfx~+h z6(vV{uS?k_jjZmeu~h_QO*OhZdZ*S5K}*UTwE}7=Az5|Q%JpZ37-=9<0V`~pP|zNt|orj%Lfn8X<@Dx)(}h| zCuM7GTAjilae9@5BNunfFKpxGN$Fm&_W@|30)L5DZDe+U?oW*-&pQjAw^DeAcG8g{ zIXTjK!>?{mUbKWOow?j&lOw$>j#&hjJs-vOA2wzqb`;CpC|!qE=jTisiC>a(=aO=> zNV&eRm)pvtr++A#UHZq)3RcPGkoFFtX%@0$cAAhlJG*1;Q#Z}l>LY?VL$BUvag12o zm?;SsHpcK>U%B`q)FJR1{y26-g5HKshfAI`J>ecpz1VvBzdUxQ|K_oCrIUu#_UYEG z_q@@eaT#TW(+bk23>vg%^uQ6u!n6)i0FNrAUVD@gosGJfP<}_2aZGMp1~_ShF8jJU zO&z^+ZcUc6S7@iiH8qJu?_VQ+iG|chVoP^FNxX%$7c6;;KjCUe4e2+HV-OLgLhsBe z=*~&I5|^QU8qaszaBf~vK{<{enpZTBFTZ{M!24Cn$yM(kI1kGJZ~NsazCLc*vT8N?-S~%lV#esC3DZ-N$y`lB)3o{1*NN&xI7o zguvx);m3qnq{J`eb4fXb&$WJ}2+BH6kx?oKJt=b2Nr(NDq6pB!2(T2-ACKh1k_6=lHIY`mLJhMb2Zr*e3Ri)M{;X7`=LPNzyMM=s6jURv61RNdBHm1(m7oqZ^T&MPDz@kTz2$~=oZ zFLm&hI;?;pqbgwt{&F<_0)IIQ{Ri^#JGb#WpMDDYq}(&oaH5ZXW^x}T+J7n~&9)*+ zBZV{FIw+KYBBM*<4f@1nrF)5XBHk-qqf-0$cI?+77{F_wR^`<$+ttc_aCR$ye7(Y- z?YVT^F^EITjl|7p+HFw z!3S@1|311dIrxVApQB-tHE+281uAQKp83X~@Ou<~)F&p|yc?96PKfsh@s-rKM0e05 z!Dlx67}E9Z{%GD(@G;03S~cyK_GRms65nvfCLtiGC(zJz7@i<9O*4XH2HkJ_{m6)Z zClXY_1;`$kclBDeq&#=WfR9Iy!1aj@N!Pm<4vUM)j~RL`rE8vN_asP(?4sAz&c{FL?160RmdA6|mZAsG^ekJ!E!B>%Vg{eKX z@_30o6oH77AJI8Ze6tJmIsow%I?)WY;Y<9W^LXObcyw$Z+qI*;s$*z&haO)%0BNjU z`;3FLHfVgj{p}q)B{@0DHPBU7W}}P(V@DMKCABn#3N9HkDk@ zWY?k{CD*eUT|_%cu4l7r(Y}%EIc)q6l520NFFQYG#$=jiAk9n;p+_4_h;?Zk4*8Wd3~eYgX$K(uM-V#jcAm20n}1H}cd_P+WKMeUbw z4L0;UTDSe(5&(mK(=sU9mNC5G?!AW(@7#}@ld_Gq_cU9_1cT#Cpq|0Ul8`(;&uF@N3K0sIuar6F?~ocqrk zfGqZN`<3sXYc$ucE$@(Z2G%ruGr!k!l$->Rn7~QJKN>H6_`x+9jJEjXT#p|3Y~%Y} zOx+SPwj-LpJX={N70c=3md?vR!j}%clt`JA8fMni zq})3F?ppW`5MEc0zvZMqWPFyhWx?E`iTWGEabJLAM?S+>GqV$c8&$LF@%;W}?5> z*D!tW;f-8iCy>I+7_}#d)K2f*xPix^QngA6SOKB_-oS-Cm|hdv{nO6@@I(BW=^P@2 zJi&1dnJU=1)7rNv0`3(ds1W4NE10(*L3&?cwW+I!&60KQ|H360jt97oZd8%VD*Y zpX)I!(cJ8u6!FUIr4haC?;cvzyB!CY$%G^x+L~#?r zoT)~_R;NFk);nhOpc5(g{=~<7zyL`7^zUy*^y*fzmxGQ`1*b`ytD1h}`|ztto9VF} z)>?l*+Hy{<^G+8ZaykC?`%B%@hs!S}z|r)1m{=fD%m?OvlJW@d%dp82K{-AH{DY^r1+h)tEYX6HiUfd1CilON{pZ zM03k!Hps$9W*^cRN42wDE%S1gwF^*)G3aH=Mc(VlW!&>8MoZpL;=ahy>TG~nbAu?? z(g@1xGBz~I2q&JklUOGX5!O;fc|#T~M_De>F#GVKd!O+t`Wcb( z%)|SyJ-mJIG|IpLuNr4?(}!`~AkzuFpHR0PLN_qp$t3O1BRWS)t)e8H(t|Uwb$1^s z>l&q_urWfRC8|*eT#YdSHB9cCkAM8;Y2S(K8t}0Ld1F53s%nglp-TsCf*}?+z6AKf zG;S}zVJ@WcCO%SC#o}%MM(UYD#>GXj5x{gXO}Ho_3fU|=u$PR*?fMf$Qhy~qdII1J zaShl8yK_%#Ot{^*z~3n!cPC#!?4=e?;8?f*p`*TJ7Jf3=QP z!AS;?^8b>$65e)_WVF>-(pG;%5b^y4_gzVcQs%D^#!|0TQ)2o>MNk`KplY48&4K6$ zZnnt%rWN!Lzjj{m5TOA>2F;n4lXdGJ{62U=!HkSp71Q8+~a5y_7BEORz*4t&n_&Ry4r4@&^2H=#W86@mK2>AoTcGqTN43 z+%0oejYoIW795aDcQPhD&yf~F{IgxYTmB*JyA;V*=sEo<)E|LeAlyWi;dzqDloNt;FzePqpcXt$OyKdqO8O6x^%B*m0co~lDX zaTf+rQV=ha8}$Nw#`Gru(m-Ux*u$UVy_^(A!Xu(E!}0E~0d75X%vkaT6tc(3x8g^L z2A>DjrvWY4LNvlMyaC`yHBm4(yQ%%C_du`;Y1e4huHd$I4R{w&`})xozbvya%`~i{ zT%n-pNag-?VJ($Viq-`dh$!tJdo4_{`4*v%X>`|aKb8&7!B@WXZ--9ElwJSUda^dT za;pK)H{GU>e2E|rPJ9ON3(UtJ2pxbu;5;T{fO=HiKa6Ihn!e-9hz*hoYehs2f!J4j=i7Z2k_nJJfylz2M>G$|KtpLH8t=N z^u~8h4ft~eo0fhGcjMD7?!o07!uhhYrr)IA(oKXG;WRo!YijrsbVlF<874ZD$n=}? z4b%aG;Isq^KpIgHY|t`N@z2-_A@~E9jB!KO1Gdy4bc7JAa6yXAHwb<73Xn*w9WWLz z!u8Fhiih=f(D>7aFjd~{@dvi9SZliUCbFTMT}EaPr0rKX{m7r;*Gps)Te=rc;;oSp zfaxRr;;4-kq}UFWYCRcA8ByrWVJ2f~_MIFQ(5?oO5&@R8Ur%xA%tZiK&H|kJ`jOfl zodnpm-C!*EPebR#5a8Pp)RaZO8xcSkNZ1>)p1}SiQ*Yq6>ft!Du#}zHJD?1Be5!FT z*K2c;X#+mWXgz`O-7v;?zBGGXYl(;=EtLw~=ie*{beLrh1kTY6+|WlfE6=eU{(+a+ z>RR1gfCsY{^t2^PeH;o9ZUugwQ5GelNkOY(Evn37kJj{Qc}f z=I_HHA|rGmh(Y5-U=0NnSW|Ot1_}b_c$bMgXWqr%$St83>;XQ#ts7KTwCG^@L;Q%h zt$DS6F6ssW@h1ya`SJsW zoc=bAqiuV&Kf@%O)bv@5nVLDP7c$rW7(mx2rLzYhoS{E7-XkI_iuk7;FN6n^|Q zHn;fss}N?Rdh$>BY4V|LzF)1?cqwV36a`&MCPEJ?@FC*phj^R-L>->O>tw#~PJ={9 zz!&j_Y45%#mhrvRfs~aN9({=4&NQ$e1k?%0jK$qj^({ zXlAW9va$GRKILfLpl-!CPR{`R@u*^@!e`5=Zp917(XE9r(X@nH-*k}J zgLXnW;RXjfBSXCE7RQ2MIVA1iq#5&PLdMS{XKtB&q=N?cT2Yl?RXk~2Vs)3~LP*7@ zF46vWk-G7V2v4%z7~n{3njzBHTka^Vh*E7YAx!C{*7J*C&w>KLJCn4*R+`Vh1E`(| z?NChPqqszfmRa>%x*#<;ANZ7BhX6j$>sN{o5K6?;Jx$L{@AHqE4hu1m3AQ3SR-={@ zpV3j^OfB^nqnu=iLPLYl2lw|i^ts#sSzmos+IQF7bGTb*NO0It(0h$Jw;MX+Pp*u4 zCIMu}|Bf!n3Yz!#*&RD3E5IAs7#8pk`D(crsgItjCternfXr8o0>BVykWqy0PLQxy zq~Z5KfWQt2amPQyvvK~i6R>%CS2+BqY$OB)p@0rkzr$b72_7xqTnjMkM4$GHg|(%A z{8ed=>`xl)3%m(?ggXj57zD6F7cOO59jS`i5}B|nq*2GxsaavI8FHS1Px!Pzzl^lB z2U}(*=kOa)d3*fLc&?2>vRl!D%KCLv(jqJa4NgpV`M} z&hWD6PO$(TQ_+V(+ zfL{0nbpI@4FsQfbX9_xe3n?=~<|t9Ih$EyhPUUNe6t_;e1J9|nJe5j50>|MnVp3+o z+l!A++Xll=1O5&F4vt`nyi5;~7T(EQFwxEROmEkilgq~A2~fr1)p$6mqXPHh`|}!M zKF*gmSmhfT6+!0^2?{mPO4V`=&nbMp$T!dT$Cj7}MB)6>6!N4Sx2`nEVY3|qeYwIiMl>-vtIn2TS0UH0c9c=qSD!il-lpb%Hz z?4u6CY+p6Ucqp93M`x$28E-1041Q7c4;dR-Der*1xCno0awGY0zy=(B^(wLKdC&{` zK zU9$0Q$95oS6mngp(x4E=kd7|V7;LaX8L5-|k#W|C^BaEKetWjIC%%s7!PFI9?J~wf zlBo`*_Byt6A4=gx$>YGK{sC4axd(hdV1Q{73|&rO)o*9;BZ*lSDZSZRyj-W^ zm?d=3`8kkI^Wo1{d;qu+e}84wQ-Z~B!6l@_JFfx{o-hD!#oy!SA43s55!Q9L;NE-$ zkEqwthA-klAsqLMAQo2XDAn)|d<5Xmxc%t;W#A6zX;RW-T!e~%(5@ZwAPlm5;o!;| z{C#6MDAry1egm%gBupKK?+Nv66?ueOAJSNfMn^c_KQa-JV0UGN1tSd#Gy?yM`knQ` zM@zC3M%(@aH{i;6^;_ybTrH8T-Z*UHq3-4Vif!#c3Nzt44j6QN6Kviy4!Sn$6AjT( zZh}5hvJoII6Pxy?H#mit5;2X^1^dGF%PDI7_{VqQZMc5g^bLRq;R>R#kS(&D3g}l@ zmyiH{c&;fA*5dhiCOr#EX)k>x#N!t{G-7WwT5pY#3^gwd1<@mf&BAdffNb~(do0!& z8{or}G*vnQ6pqNp^ZD=XxK%1V97cT$*4&7xYl@f$vQ@80af zq^$rMQ-*wh>lTrX-7a{|edmImY4+(`p%cnm^88lA7Z)IKH@*b%yYUx08yjwc^N?4l zTlK13{8oHfnb0?CBc;DH8>tXyU#LjYSy(3m*@%tA@i?R&T#3o}{i9w>Ae=^CM;!OG zQH7Vln1kDfteQF{I=1s^W~C&+(Ld9RwzG&^hoO;idg9d-w~P zu9+^JhUqXDU$Eb4hcALR8b{}oUv)FhF~y?~OqWnR{4mP&9cov>Xhq7-;B6?aUb6=g zI+;?g^H;DKb8OX$y3P7XCm#ns1L17!x%}t?@CR<@Y^ynz6$uFmX+6Ueg7k4&L%OKb z=F_xUgq3%^Ra89<|M(33d=Bs*7cS6{A#?j3FB{O%Kw5RQ**E@-51gF`@=U%c&1n@|$r)G|oNoPY5{1={dJ^%9t{ptG`c zA?UVjGwm$N-hOCvJYEHJ{`1wKU1%+=s=rZv4SNBsuYnB%2H=se^3=sk&^x>F%Zd0d zNSk$57#U9w5jn6?qz2AGA@yU-L|WzOq<7HsVK@)F&OJ000)RRRU%!`oG!-hBOi{xA z&R7k5XAgu)mH0;}f%eFQ<95{d9<>$1;0#*N#-f18yA7Q!6HtOsY-AKqSk@jyI+*33 z;RS!9J%5c!!k<9DSs9Ad)sVG!(Zsm}J8ezMT8q|nx$c55&-|b#awKZfKL?(|kRgQX ziK)*I!|nrLJUfW5gW({4xd1Q5NAJOs(UY5PK{)pxh7o9g^$Mv^Jm~18sKS?k2gV*m zcyTKBJ56+@TwQpO=s2f)_y$;m>(LNg3(KexfA+i#z5{;uM_=NDzaUGqt&CuKg8W6S zr|@;8x>@JVmL!RO(<$`A5L;6#PHb5?(Ko%Z3gF6xRP~a@o44j~d~hmJ-Dw{LqXw#Y z{zHfz{Udydbwp!Z0L%dGom*PnC*Qz`3m5QtQwYqVdbI^>(ijOe3Z|n2lInbjNcj-w znTnIJu1s~fG?L5yo)GJ&BZOt~OZ?>#1fyZP2kh|p{E|l^_(pU0%kc`_aQb~nf??o* z-!mQO&q4uyzcl;YXZUfA$6P|o0z%8lysxOk3CALa2ppVboJK`460@%Uk>VK+zRx=! zAk%+LKipitgLJA76aw+z50SsOErk;^ccVG$3)R)1VpXMH$|#lIhf_(twjl`J*GZjt>i+ut zt(zAwQKw#j3xI=gms8LP-h{gU;Gg*0U?iio>YGn=+FN(<*E7KM)MNr=??=!UftGU^ z#@b5p3F!};Ig<(&it17+MRb1ta@r>+n%s{DTOq>Y=;R1$J@Ex~euR4>a3t!n)Q^m$ z5)M^zy$RnZWp6HlhBHJr?pth1e)}DO?fcYtB&;4al-M9cE28d{;F%mR=i}k1Q0&oo0zY~yg5U#$9|G-a)Z)bySO@AU= z?y+gxY%u)|)p!=3+iVjf_`B@%OpBf&^rYNj@HI#cdZkq3OSiU=J_Y0W;meF*L9qYD zI>0BP>k7!hhwh#Yz@hN*)J46AcEx7_lJ{?ZXWrI{$7+7We@;I;&grD3#0Ba^!t(%?irTt`LyLM+6g{ULvPwS-aN9!L??LVnMUbH(3he%GZ z;$+0v3l~}uX^0S!r<}FPPZSX+g63QOpeP~F^eif}{A8YQ7)A51(A?VExw986m`#7f z$>p%?%qD;%N7y$yd}Io~1NVr1vi%kk2?u`n2=B#5w_ZU@VD63un`XoECAnJfBWaOg z>vnpp+rRa$huZJNicobYfe-&AW8^5{KBw>~AL2)n)=M3uG(P?^Ik5QaLrgoSzSIFkR$@ zUZfrk)lyO>QciLe(;QMl3@-nR2^E{>jumWQ7$BZE=8DX#e+z9*x z)P$!ItRAH<#{Yoai}ZRc49f7h0e#(Z=*dd_ySXlcmwcM_J@ZK^@bgj1bj0_TYKU{F z4UbZ)hy$Qu0u^XT>d9tn*y78cF0O(Q!Z$*65 zXt)eY;{3-E&*12oF=Oy!a`BP~xTWbQkdcr6ga1I%dVCnV!(g-xU^wyN4&Ga}?TE)m zAAHIU`0U;#5qlI8o9ig}=0F$UbVLvg;r_%T$^A4+wO-@X3_5rvCqi#Eb>Z-b)7sfv z^eMU$q$?*;k`5X!sn|vnD`79Eng0J z96kWs4(`UYK4s%QoXEpq(hef~TEwiP51UVNlKWFq$fN?|W3$GC!Sok3hg~6M-Eola zw1QH|2YiqW07MeRZQM|Xd&6$18Z%`2>9?XaNze)JxjiczKgACqpgOY82mvQ=WBR7O z7>m-8Y8>Avo>)U2qXOY;Jr&Ju`vG(y$N#)TR1Ho*C-c<^{6PLL;8?8Zu<6D*2sIr} z{09GpqoDV<_!R-{cr+}Mi1RK3cpo9=7qJ_ZnRueXXaF&d066K^G9T)dRREH}3%my3 z-*V{);6=FZH$3nhKqAEA_wac%98LmG!@ukux8*p%qO2_ZJw*SI*9$V5`~n&wkYTl^ zN!$)XM~Yp9^EUnjO8HS=4E!a&UYrLI6@q>n+izy)nVrWzfyZb!p0u1WOerA_S5kRo z$~=%x8k;fL*<(MU<#C8MN#ju;Yy8FA*UAD{621kUB%C|IeQVyEP4{I>#c$A^KMyxg zox&k!&T!uzI&r2!z$0C=H9mzyQ9V5}gX$JF$1qJ{i~{`#=`fz%KxUMt7eP9yPmb z#cD7AIsG@ief8Y90VUD16S8N=6;JWi&hC9+Iogp{RN1@#99$W(c24c)pr!UY?`_NU z`h5XGx!rPd_U(A*XyL?~Apbo&ZK5$g`BxD3|BE>l*e(TjAWt};YY>Ciu%tT%@h^57 z*3f)*RK_VLBpILI>`~ljXnC)KtOcvm(&p`YYt5db;{5}Pi?jO|6&K)z3sxbSOOml< z?iL#x=iRQhHU$~+K^>M=^e8h#sFdFO-R$g&`|KLIity+WoWrN^10|L;OO~%z$VR2q z(vS+=3mkw~ax3sk@WhWA8hGyJ(xr`OO=o^0V_-+d;1nAJ4P7;JP>ZW(@jw^QXzY(j zg&%1DJqRkAIn+$|!zibqS2h$4&dn(wl9SVz2fqv$oii&Wc4|i1%Fu|KyfbxmXL{F! z_|EKga2b4P?Ps}s-ux{=$Z^ka_{#&kQ9HuFd2cT>==TK$bWTo5!cR=g@RNk3gd{Vq z=c5oBKZMTkIw(|LDuUWrxR&`Z;MRXGEnB>3844jR7L0Gums|Fam6f_0}W!$7?KiG$MVmkM?w^s6YrSj z@g;lu4}63gMvSIGV#4=~*|$gF>%=C^ui$zy*&=$0#x~{1H@u;|#3f6XpjzAxz8^ZU zW+Lvw*^f_2-7@*c4XC|#&D8jM*|dGY@8UTc3jtUO#GbU2`g-xaOInwk_-oSyG~?H* z>hDa`(Tr!K>2JQYG%hg}Zg>yPm^W&VAvGsV(#N>&r<uT2ziA(-vKS+c1V9?Gk{Fa6m4T`Q1xff8MNGvh-q0zu3kG9HzGV@SlpB; z6Q=|k+tmU>j{<`p!-ntNJ;w$G)a^U4Td8`~S6FlDMB1`OY>Sw;o#x+yPBl<6Z5rNQ zBYlYXLa)Ztumq2x@oC8O70rDWhLyZS?ps~CVtR4;GU=yja=(6Pu26mnX?qoUo>G=2 zNRAZauhad*P!cmaxv1+i7&T{O`~-A%cE^rA$H47=rVqEwau(iKk^0Uzw~r=>V;K%X zRRc>_;T14>1HMs88@UL^;yQvP-tL1>lJ~lh_ZE@&q(Z;QXmqK8_f03I4^6I=rmp1k zdh$8d33^wSx{K3sq+r*&w|CTy+f%xC94WK_>Kad@Z*f;RX>w=ni6if=ChyS*DJ*lO z4#@wwZ4h6*4PTs0iqAoZ$UBEjIsbZ|#zkhS*SOWy_|mq?kU)o-KFX!g*Qjj`CiHrn zjI|Y&9U<@%8)2f5y~wzGIdUHP{Y&%nOZ(s7gfDK~2nn0GIWT(5mWC5sApic|&!GP9 zT~baWsdokAX;mx9p#sBrS_fxW6%HutO}AfdetY|tRnw)j@Rgn!nYn$ZznG2>F*~mm zY45-|&jUP(=+nsdltq|uG?$CkgmsCinLj!#J7IDS$TsdAgx^}&r+2?%-rqX0@8eI4 zBJf*W%9Qav%ZXceH$5{go6-i6@;@f!%LTci#gcm;;`=rDbIL}p=sQNkBtnyA zg9U|Sj1<+JY)CNu!Q{#57FO!4$f!(>mAuBML*Vev$-@IX_;6n$&h$Zigq@cBvx|sB z(I!*P2p_GNmsTg79hN*MZTVH;2M5Xz(a?X@-Idh6fYhyE>zoFCtKPDZX^t$3 zug;ru96Q#%G_hvo%9_Of`2B*so`r=y^Z0Y!OiR0mgdWzgyOgM1^5V;eOq-OR z5Ub1c59{d{)6H3(7d^5M?-Za<43Ers=$@aERp^{!>EKY*!_B?a$vHTvV~5f{r31q{ zr#U;8s8u>2Z{OMbn&}~&yBN4}!xEtlxMjG^9Hx#Ajz?CgAS!b%Tmb3K?|q7a%x?9JZd#sP6XUL=J&`i zDk{kNV9oN-p%DoKgZdV@_3JWa<;p23B_3nBAwN!>_~Yb&#mnvO2fMfwmq}9%`h%-h z9tsWb!FVDa>bP2|Qt%sqrkG~douht3FMRKNl=%Je<5g8?3)1D};Ewq8EWtiU6TP{f z@Tl27OR0S(zGL)62wjYShU6vqRl!6Vhb@4Af+s;r`YZOHFL`et=_AFj|4xzqdI(0e zP?H>zpE}IDL%8oSpO9ePuwm*%|4<|Uae&{r?RYf|nPcoygV)25xry{Qs*3d1(PbH^OH@zF8mGseZZxpnTE+aYM|SWiPl`iNn?7LOho8&|0F z?h4EDa`X|Ucnhj3iF9+FM(Eaw@cUY(gB{!KH4FwXk=+dusJyVaxUhF|@e}adv~ktS zjr{wQCr+rYo-lE8uf1Eh?b)+!E2BvvDQglb%gIa=MXLc9cnk`I2Sn^>XxO3e9~Rsv zcI3G6BjWo7@K2qc58!JDoLq=eoA%>0txmvp+#S|7wi|{(2aV_}L8pzRA=Smb3yZls zTlenWI&t#ki3|&pzHoQg^Av6vL_djJyAj|2*YlK5_lq{bSwJ@}R)@6PM^u7vdfYgw zomQ-~zOFfxMg}Y`jSy#!KylSf2WSN9-*gO9r+q+PXEbHw&e{nZMC5?fu7Xhv9hr>?DF;hv4;;zhQ`Jv6;Vhq@Dv(dlvgb04<=K z_~AzrU#*tfoBlv{rp0W(6r>S{s+Jp~lFJh%5);cA3G2zdXf#VDN4=Zx6*oQO#-lMR zxwKRBJ;F`g0aQiq#S8c7*)E*MtJr)2(Tu)oVSa!x7Z;&w(aP?K%@8PsDFS-xf8LCF zOP1D7pV#p8hpb&a%eHo2UE5*Z$jd+fe0jv0kcI^x-@OZ4KEDsTM&R9C>w`ONKV&hr zqz}G=|G|IbD+NW%X?sMUMIn5)!7VZ(rp8S=P#iH{&GDzhy*J?(l9a8xAp|4M)Fp zLzSZI0rqk(=QeIVCp;QCwmc$Acu?2OdwL&MATl?e$6Ja3qC8g50PC)Qqp z8@&8brx3M!(VF#zg_hP1rOwXA#P5wfSGHgnqZ89T#E!IMSk`Q5Me`O6{&N2)f4x(b z6W6MfL@d#sDOGPRTl&^pi#3i`nqcRH4y&scs>A3WhA8}0ZZUpT#e@kJ@nimP?flKWz6Z7$s^UVb5=V|1)^9+0esM{! zkdeuqtHS53&*h%k_Kfd4*j~}!K^+^_F`-AOcVMWUeP27N&P|@35ccPvV^5zRUMb`9gJYs|OkWc7+hK?hzXZyN{v9P1W?>lur^z04 zn$}DUAFaO%ajRCvM3-+}8RO=THuZt`b4)+=v1TSsmulUNH*AS4(+dibezpauq^gE6ft(}aR~VO>+enHzyJOB<1%jM82o*o{W&@N`&^^#=ugTR zO=xG!yf!~!QbIf2zC-2mfcV3_SNGIUvd((yQ zzn9t*Xq1x!p93ZPc9SKpNcAy?foPX>4L2#w$&jl%|bol+qI? zYF2JkMD(~Bm=3$Nw8se1ee#<-3Fe9PmSEY`;`ZhlpINdD^g}6pwCg$>o! zL|=%UWbc({=0A9gYxP~z`p229wxP2p*uul4UNwIFcwJGV;5Fvu??=~bCB{1TAI(@_ z|C4@P^FQ_D&JBQOB+3`(L;D_uXm8w|g}ab2v{yf)Av3-%rf<%m!Ts~|yZ3=x=1r>0 z?hls?&&gSN54sP`9XN1e10$nJTD4sxKR`q$y@1d}Ng99+Jv<#1o!28VX~2M(pRhqA?!Urn#EnRxZ3o!DV@yF+Rl%4YXvmI9#Z^_s zlV){_NK1=ov__|;Me~m~G;9d!LU`yBw6dY$zJLN!Vdos6)0ob3)F5012_gLOJH-~eL!2Ne=7y%I9^c}dK1GHZx`&H1*T7|QK$Z7&%`?*4F;HAAf-4zkmQvc$r5>@l2A6dmc% z1qyE~$!b-1tPo2&Ob3Vs`jVQdC#Mc52HFS8N{^$jpYB@0J>9U-GQVQr) zZOcX-8Je{NBbWvmG84k}8+ZUM;MGG=QQx89H9E$R>vSfjtC#RiGOYzP@dWS?nbia0 ztp;QN1Pgi!^gyrkK|@esjc7#thG1e4$A3exegt7XBfTCuG}d9VlPF9F$RsVD-ek!j z^Jq*8xD^g(zX8vn253Q*Qxev00`CR{OzxBeAB-{@qcFJ|On(2`2{kb`K+9zVhuOWD zHlb`awCm;3oZzT#)kWi9K9;|@n|(>iyd|^8O#wk98}`vy!@ORLR_Q_}M@06mF0UO7 zLTiS|?Ah0J?Pe$)pCYazZ=|#t&sYE(&h;Bu*N+1u(L-$ix`F-COVXggq$T_JFB!Y! zzyUb;(|4|X^2wEVT3Q%0^5u^3*VGB{39_pcT^UIB>bVcYP255^yhMZ_BImLztJMkq z=P2AP!e4FqimM}gki$(@0xy;D(MWQZErvhtjgR31z5w^&?-B7&x5D2e;-B`yUx#LM znaYW3i~q|^J(!K3KQ)RxPY|EKhM$`iW7G-EoO*^l9Y>yar_a`q{fUIKyiK4MF%8*Q zBv>d5h4&EQYcS6>LRq}=F+5mS77zX&5&v{6{5>N6X)pZ6m{)>tflr~|877#fp!l;z z{HJabsE2-pNdH7D`Vk`j2`~DuV|bN-A57qhGW;WQfq$+I%qvmbCh)Cu*FP3R>_b%)^=nXdH|;bU<9R4X$u z{36x0WH(=BTrmF^&SO2rFPG$m>6FRnq{!$;$lw*SdM=actQ#N0BV_el;YHt$b?_zJ zG8=+v3OD^awS}3$C_z~;O@ZMdSQcesJ+F~+z;FkK6Z!;xM9P8k6DIO=vK2pJB0nd+ z__=`VMqp%97`{R#UoU(?j|o11O2jWD_#S)5pLXN# z5$OwZx4ZH8i1bf;(O-wf5HoY8yZE2^bFtiaDoe%mq@T;B@KG2(SrJ6>Kg7_1 z5vTU&*|J2 zKa2Lq42bu}=U>M76UYv-t?)g1mM4eH+O-?s)2_Yo30ziQ2|pOqc}Ye;Uxed+nY&L$ ze~=fx;AaF=`R9A^CH{jw_}F*mj>za2h;VW?+&wb-4I-Sp=h&j0h3TJR(x{y*q;TAO za%v(^I98*?(7_TuF4q>RpBAtMd<<7}BZTsL;qMXgg?`tAzemIu+M9$=`wy9)EcrLI z{VTpC_1LnXc{iB0ICp)8WBj=cIhD0uUS0w2PvBB{TltruiwGCas*S^T$SKGXm*DKfUVd4)L3rWw;jO$*v-#4M0{%hxsun z_v3cC8q+JlC3szy5B0Z+oJlUSe2Cm;e}74q&+8a2`16mq^5;j2{`}+K{ygTZN;!nK z_hjnFBntR6)^oV+Lz$euSng0-Zl{O7Q0_QVZkLFEf!KbTTs?m3NYPJy+{;g$jo}Tl ze#a`+7xC9+^-v?nm)C=W^WY2oFqj_&FXAh3xgHh$-7R2tumX&r@K_8#F8FObu$;lj zHu$f0fZwehd@9d&@Tok#@iCu|Ds-e=TNnXbz$bpTP+l+mZ5UoClc%RY7%BD#k9*m3 z70&m(Sl&65pXn5C!SE)`zlE98GKy#xn9&OV)ei8xwSzB|w=KQ{>+^hXe9Y&0MHq%Z z-ZF>6MSKizB71gYxEx<-H}d|XKxW@)e{o4Evu~~2v6nr>_8HS>?n)NXO@D~k-_34C z-=qH${q8N_aSxDvf#4kiSG?0cT z?poUl|GM*mcHut?aHMPnzv29x;{U4^{3ij9?LdFrpAvYBmwZ~m-STOTf4u|vk1}|) z41S{n_)l^=v>sc$^s_Zw)Xx^;=af-8pNsMw+#Vdulfqrat?;iq%iD$jD8di4g5Pj1 zqVP?v;6Dj)G?I?{TyeucbCt9UzbU{0j(gb4gboYj@^1}y%OCgK>@6Ao^$y^o{DB4M z8!dy2@(0>ha8dpshU8256ycwB0GH%X^j1OT@MRl)mciZne4rKnb?1}q!haOtRG;N= zxjxI`qCTT137pFLOHuxt+J)Z~;G$ngD@|5k9f{9EH+?*RT|2k;vmz$N=|fsAX= za(yq#^J77t-f)k7Xoc^#53S&meR!x9{Dx?s*R+EFB*4iy2REMb8Q>+KR&cj`TH{~u z0RCeK@EaY#f0Dzg9tL>Xht_aWKgp&|Vn6b;AUEe7cYBw?-R-@k75pb>CZ!YV?q3A> zO@R*XH^1W6Q$97V`gbq5tbg~$zup1-#}42(I)MKqhf_IdTJ`VVaH;)Xz~x#+%ln&` zzK!;VV|||4D@3A#f_^-^BL&vAg}s;Zpk*{G2h8 z-@_I&kKK3@Tmk=-^c?Y7Y(6K97;?p@b*eZG!i= zteuaM+PRya1Xr*jGJPK->8~44f-6{^tlq~+^(ZT^09UYj;U4o#{Xa!4!Gmu-$h3kR zJAlV^05`P{ClIVpQvBN*ZkEGI{V5XK(xGsR7u<~Dv>htw8zaSKrZqfC4o4H+@Z=8Q zDROvAxEp?%!o@hVMbQeLD#BkSaLQ+z7oAORc)Ay#ZhuHoK=c*9h0eEv7j^(I>HuEc z22T2KivYnnckTe*#oK>UbZtwY!n?`gEtMEf`zJ+-S9v|~QaRjJ?1p#m0N%q3e!vYE z|Co`(-R}t{c*`p4AB=IwnNBgz3=`oBc*SF<=(xhi za=CzCxijz!EMMv=w6wrz)F0k$IVjdVke)N-z)rQvZY6U!;TOMc-1r;+8fqE!&{M=0 z=c8CMHbmcM(fjV~apgKX)=PN89Du&^zD%*YZJVcKMJ?^v8dA2u+JQUVv6m!MH(c?) z93O3D@z7m4K87pcM?&3Dx(+vDSp~>_6`8EO;8a!ta#^|I3V55| z3-3~iPpk6srCY&U#TpJb-78*n*SX=6Y+JYWpF3#lBAn`{(AIzU($8t`w*CQ?HHmd+ zQ=9)IBa6*|0k_L7q}*b=bYl69RZK~1^z|o5pT}jhmdx=xouxT-WdtL zU#q@|_=I|IIQ0n~ZlC{(7e0n#msEz24$&BJj5`K&in06&5w3vm3wYFbALI7LCA_yq zxB`Ai^C>5N1OJSO=dppGaKEt6(eln|WAp4}qPa~M2X5Wk05)Nx_taAljUsyhfX~>; za0SCMnv+Z;h~FB81_Y(9V9$0rrG~<(Md-P+xUky(I7r zOm?k}g%_P?caLDtT?R`K-8Z^bTJ``#(t;=kr@iS;E1YAR>3n_H2t~--=pMSg7EZej zeF1;RR+DGKkK?4L065uEYVeoy_1z;u`eh-tJYNRrv?kULFOJytx=8+QLLV~kVH`wp z{1|iRU#DVN24~c6*G?+H}f^|~4_%X@P zP|{d7odfHC{+4_$oxes)8{)%V^o7i7 z#hd}~7b4;+}BBS=X80hQIG4M_Q)geJljV1tRz}NUG*$|usChR0%G@G+l4Ee>X{>7SM z7BiwBA!8$#F6Kx+$Aq8HPy;x)8^-Jc2Qe2ex`#6;23OcEoDr8T_*vCEtiPf^DGn*h z)vq%EUCJd)g9XJ$7B70@$;FEvhj$k}eq`aICmt8l-@|^vO~;aDfQBq7*bnZ3x6o>` zmrgadXG=k*xKEX-v&M&G_WLRz7sdNTsc>ETlU8<<gz z8X0fd;w*Vn97{@^l}#2GiVISNU-uST;&J1`Z-PTsSiXa6saW%euO;Q&O61VIf9?5F zUzN(Y`{+@nem?Yf-MUeuyZfqq{7UIBhK(G(W_0hooSK@Pyxw45pS-+keANdmkgmA- zVzFOdOU2*{6{Ix(ky`)2K>ylW|9}AhS|W$OeAd=iD$b8?B>#vmQTxj?6<Cer1hEfV#tq}Dg=e4>eujV1 zRqBy-qHR%5n@seN?~iU=BDB5eri*mb+t5u=rcrkBwl=#Q7d{u)Z-Af_>2qQSF- z1`p=omQ8G*M1xXLVPtR(rC=)WaV9jR1`T-`_yd1|SM0HIEGY-Wp-Z$U=0FxH2QKv= zWKIl!i!tCXbO+kh;=@ z*DoqkiwvP%&0q`rgpa?esTWX8{o9G213;#DkB;$F;%AZMc5@kr!Nivku z;XdUe?o-BM9U|)ltsL2COGB5ZYT&vL0Dtp?4KHutuYLd0sp}f&aYf9XFBEiQFAECc z2KE6gdw+87Cx&EsgdV5$oM%i$Zn1hT{K|&fRJ$^t+r%ovY>d1H91C{vi zf$ilL6_s3UXM}|LJB$B0}&pb1079ZrgP8Mx~65$LF;E&U7;6G!?3Q7CZevCgn1ysj< zIK^{-Y=Wli>=)>-@>33Ad7uhZU%gsz_NG-s^_KS7nq1On3#*NcScQ#n?*3V`)}qB= z1^NX9^PjoCo%-B!^Re4DQmE@BPi@02*!Z-(L>?ck(>MW ztsA(jd_hK5ac;r5X|u-K(la{opAEgF^66E%;@-;2;NThIL4hL%4IJg`7ee>=!1+9k z>m^FqOL5YaZVI%;RZkY0p$Q zG*s6n<3IlLxDb7xK6~>cqsz*IVC;VYU?pFKQAwTWDlD)SeuhGaC&j);?C3Rb8_D3W{QtDbt@^0j~DbN z1Iu?cmTwT5K@Y6nN4T?enGuEs0*OO+=ofk^lX zdy?-Yc&0?DOmvSqxEF+??{a$8XQTZE3E?8)Zr2#jHk6br zk{ynpJwkmiVW%!P2KlhB4g)1*&F+Vghj$f_?jJ%I!x>CzxO;cNyJT7Bm?8L20hgkC zmZ5v@bKP~_%ZO?2;54L#+USxjrHStK2|gS>bnxJzqx;s@D&W1Y#YS~4rFZOvIp``*Hq-`EG(zQIamk$WGEI;@=A*lxi}W}zE~Ej+uJ;4!n@uBbUEHvq81^vDx2qe5+W>nX#p~vV<+t2ox3e`ER^o`AZ#!+OZ@UdMPU3@dZPK5Q8e@3Lbstfv?34uzGw zVWpUt^>BHxk~h0ynHbhcVJU7{9)|6puq-z$7?}kShx?%V!yNI2F@fN#bm@D=OrDye~NA^BZR=8n3S~TohikIWr4+Z1Rf!i>> zC2m+R47-;#W4v5(KNP_Dw*0_d;=iGLba3 z<>y3hNQsZL=b;FUvj$ZX`uGMKV;PN_F-nqx8a0jqq=p(JtfJJxe+}$2qTj&tQ_)xG6et5x z)6Wm+_u7;XzM0W~!}?AeM+cg8Ak<-;vuv%>l8*W50rp}(#({l3dR!Yi1f4@4qK_V& z9nB7Ys9_+-H>rb8J}!(IVc(}4_HQ%{qjgt~v<1fxY`tq5tacs!`|me@086+5O{lC1 zohU`;KyInvACYxClW=)V)JM~aUK-uuLB1nPl(;Dm%N0xv0wHzO-;UxGip!DeR-c5tHiv$;#o0`+^} zp52fC&@J%-2Ins6-J5;t?YGhI+qSV;u8(1Y>*Iyn7777hg=st+$TM=-l1fFScLB)Unoq36|Q_l9J5wnBg@GC#DX|uAk6{Pj_A3 zx@zTCbm{zr>8`{4wdpmh$q|a1T#ak0Om_RgJ{8sGp!f%t?>!P7{bXWd-@cuD8UvGe zt$FaI$prSj3x^3~Y@~b_aQT#E7`CCe~}iO(ofc)9nxbW6>-L>kbSaHf%6B z1J^A`AJ}WdJs|$z!+oohs}l2yi;9bC>$^-&nlgOTy;#W z4K@cbMF6A028<4y0e_Ta>lU)HiTKZMBWER8Y!R%|b~EscVDQoDX=9Nq_-hvrGNac= zgIL4sQBhV+w}C5PemU^`%PR+#1Y4t`Uhm#>${}q$ckk@k$m!a_PM!_8Gx%@Q>`l&P z>|Ey>b{W1r<9gh+3yuXGJlgofkmC7Xa|6aOxY-bbIJEujCc_wF7C$sis~MNPNfEM&~TEQ>Y3~eyuQ5B_8X%u`kd?DK)lwnN{o3syx$?;wW2>z_^w(_p~s@xsYb7J!4!jg9`O$td( z3ra9dxp<{p(dFbs5DOxw_=lth1*dEMCSiFbV_kVvvcY5nLF#>y%|oyqdFBW#xbAum z+>4gL8DF^`JhGPU3-58Qfpc9;XS!nGWmhKrg6>%$tVP3g3_`q2EV;wL>+lCtQd-P* zr3G>*g`0^|zo|wSzpX}ZUVNt)h`Q2?-2nDBHKE@gp8DbH{Zl`3odVB2JmsU+`=?Ob z7maecH*kIFu@;YD=90B7z@jC4&k|V*0f;b0MIu`%w#}AC6f6mRwu4wHa^!Xqpo3d< z=K&?zwN^}<2FQ*c3MquaIDl0s4f0Q!>(`jG^k~ zY2gYVg}=tAjrI5QRRt;i{hUXY{LoNMaDbnxA<%9rZkV{w+No1eph;^r#wS`6W5dF; zG;uyYD!-)6qQu0~oCLrO3GmZ(iinQP?GtSX3Q%jJx}z<+un-?*fWO9oa+BaYJI2>c z&a>5RojYo*qd3-J1-B=JJ4}W4#O(Okh-_X`4;MZD%8{izKpQQfr~{6Ar25v6K)`*@f7P%F`5Qmc?PG*KM1+sB>Lh zhU2U1fvaZ??>q6tk_pb0gL=+gGkJQs)oz0sB@rfTmN5)+!){eg?0O6xsT($|_SjdC zA9(r9%IW*d3%1qGSTe5rN0XlFpIKa-G2jq2cjT=iwRz!83=>a!NUbrJ3^eGK!fs6| zz|%82bVl5D8FeHav>0`-gJ;0^ZMD zP@gctLUy%r2pe4ybtK=!--1`xf41iE;WeMFA3to`kf9StOspy{%bf?}M$Q{Id;NXA zr%vtt$flS_FM-Km%3FtGHm%`e;=6w^G@}#OTnshA7O>@zYiVt=nLo}w8arthx`N)_ zHHrAAWWMubv`t3P6Ep1CTfoIOkzGo71SW)!V%fr~3h0w=!d*S7UuG{1S`YgPB`SLB647%yRS|*IN-Hp3Oq4!=$kiADC1HRt-{Lc3NQ$QengZ;D5vh zaJ>ih?KgUKzrKS8HVhmz>h#R3SLYueJ$PUPS_=ksn-dfm7&fUJcktTy)YRtRQd7sj zR~8=!(Ji1e%zhu_YCzYEvkc$DFJYXi`2c&z&~U z+|1?;#8h5HDg3pjc}>lKb1Fg3<8YekI1L$7RT@d}LA0BU!5FlHvqE?AaTpzB`=%7& z;HEp!qx}uQB@(>~}2#8v3fMDpNQ4jT1 zoxc~|#$iJ#&@bLxIB3cDQ^))Gty$^syTZ}A(+a*490r5I4Ddi!^z!7qj4GeN4`cGP>+o~1ZVTQn=1PEuP}Ab zOYM`keaum;&&X+ihl6^Z4bp{9gB-{Ub%WF zqTkpuNALhS!V0PG2btW#=05C_6;GZj%5QGqo^mcH zmx8`A%wlZEs+bV$8QGX3GWr<^b>f!yMbMs=1}&ls5eQ9jX^`wMRRr7-k$5Bq>2Bb- z2`9Gq>QzyBV*G>?J1Z);pP0DxnLkFBpC^eIh%6E0rz>7e?0bPD~@vs>4mwbLh0orc~g ze0RlPyG2_a!PZH#$LASXVuq{y2Gm^<3v|5t|cm32DkS}P~ zlf2`UbPqRd5NOV7O9I>Q?Rzg{4+z~t&w=hR7L=ZFZ5VuWF#bO%CUWJ$+h06qj0QapyL|Nis3h0#AVjCt>h5uvD=Xq%)+1o)j*QIo3+NlzJM7*i*mSzX zws%G(!AAs98mI_CQNN^AB443jV%Tlm7#eqmFylIB2dR8jfxf;fjgQJlty1}P)dZ?o z5ESgs^56qsA7-^q9ptO>;WYun{4~R~%uqOt8>&cmqMO%#dH)w2fRMK!A zjpCodQQ2?8oJM?4_P>$#)sg0=DVSAMMt&{d;TRxQ*qhdYySi8hISyQ@h>ge1FE}2% z7{TPUWP6CsXtiq+#8aMr$gY?V{1)~rs;`{28NH4^Z`=>!cJBmn2b?yw8h)9ug# zJqvp|zV2n~+qYoYydL#WgDy`U1*K0uiJm{I?Wxs*Y1OuxK3Tm5dygYk_7!YHiB%%! zsTf%tyE%+n6LzccM`;3Gq45o1(mJPTf${10?p^ux%HF3^PjSPX+^A9PPUkpwCk*|8 zmN5c-#f?@hR9l$Y%mrtEb%Os{`etw;Ld=8i=j+=%pCx-5f8vXN&s803{N zrenrAnn>Qbgf?7O_#DZ&hOj_NT0_cwy$#_;q0Fann+{`#Q@J{D3<8wc2%X9U4}Jxw z%yMmA%3AW4y0*@OQ@(10kGoPku#g=?xiAq2JjhzmsITbF($@G%*aZd-vLiG5nHy;- z&E_jK${W|AvFU&T*mTBIZVV4oGC7j=jl-w0P6 zyjyeFEzY|&Oe;FLBo23NI5171ejB7?I$(t)G!%9JM(~+HN2m>v&Ooq^n}>O~)AtSH z=B&~`Itr^dDCs*|Yy*W64q;p)ofv&Ac@VE06C4|6j0q17*9B-&jJDM5oD^$Zr_c#J z?h`|ek&$6G-@vr!?35gPT1NcjrC1*DOaHmL;GiJ?D7_`akrZJtL?&kEcMDF@YXbxQ z^I|*YS)xKi!%~)g4j#-~+L}+S;09cW?va`VI^sfYw1OO|=;2&eBK8UNCm}XDJ|oSZ zlad{s7U*jWi;Tn^YK;7Z&`xpIl$`8Tn=wTbpu=T}F^0tkkAYt<%|oL;UzQRU8X9HE z>lB;k9~h|Brv!J)&rXaq7$TA!85Vt%e^5}cZf@&(p>5q_66@FIFu?I-B)qZy?slnu zx8JSD)r%pX>h*3Xgbr2`yVyo_24WMSUPvLdk-NCb!UTb;P}`VlBU#(miXV%^U=x+Z zL=?{s$F)rbS5VrLl3?0x_`%Ai6WgxcLTm?Vxp&=-m-1t2Rmw(~;KffMzQJXYEB`~k z*WY!0?QZaqSTvcxdrQVUJHCjWstOj)9329b)PC=GEF-504=*v?xBDM07ZFQdenL1Zin*jfpZo#Z8*9S70d?tZ|k(rQBX>vBP)Ngy9TaZ`^P$1 z9IlTD!ea1lV|Ao&C2U0lYwNzu11tuTEld!~A{LSS6H6z9Dn&C6VtkCaXHu%Q*!ko9 z^oH;V+*3qr^?s~UsR`C7qj8CXq>?NA6)I(fE}|$RLLcUXF;qTUA0MTX^$FKSh8IO( zLMnxyQmkdTf>mqcRDOOcfB$5oNv+Z7qT?<8{sfY&^5_K=hv255nvge$++(a*)z0=t=VlxHzgD(%d7KoXGz3jQ>2Rx!|l}>6O zB)~5avuboLItccezyB_l5vk$1_ma*SZ8`-7_n8da!>9|4c&OrqL@zDjjqyVA#N&Dg!66Cp z*2EqLsTdw!lBw??_zl@oQxok-hN(4^>`J#3p(Z5WoR*a9NX#&qwc4E^IyTQySu&t+ zkMi7t=y(9_lHMA6BwFJWLV^L-zj#YVx}$IRo_X2EsHo`N{Ic3A!QNT1O!sl&!aPz> z^gvd7$Rdc9+$2vB0gJ1vMO(>WTlv2Do>>a$=#&L|N`giTz`hl_VWCStc#!1}9u)d` z(%-XBi$Nc0UvQ^$A27Mb2_}O^f`HgCZa#a5zW?y*SmlP;KrJv87wJlhfN++8;Fz-y zM3tM(W=mPg(Ar7k>IRjOJ9GKmtk5v4HML95=KP|}Olw$ls*!l)?1HHB`axsI)isoL zOTnpnR16$6dhDP9y=Gbqi@KLAw04RP3yVm%E-dL@RA!0%O7hF)e40Fdc^j@Qj*bce z3MesSYIK+tcMbWQbGoEjtzn^Aa|MRW2Gxz5R6De!%#x6h(34$29P+OsEoGFe^oX#q z=uVWYLhH<40|t#9J!oJ>4~yBH(ygqaZrs>GgL(>m1Ne;g4GMQ0E(YP?vxT%Sr2Yf0 zpg2OccIA2rAux5)#dsU)MW2eE(FFvDd=ZV%rRd!4x54K{JTZ`eP7LCkpLPfEUc3P* zc$W}x&?W}$Ui=A$$1Vl=aK%EZJ8k$gih;eJ2K7>D$XPa+w{Juo>QCC>Hv$boEFN87 zgxiT$HnN}s?r{w7F^1-+J%a|U(mmebdebw)0fqSiblgEJ8+lNPa>O!Xt?n@hl2RP^ zkc~#jM?e^+4WFW9Fr#L7>y-29d|yrs%&rj`ebwC}MOh0pY24&4ut3fZ{4ThOxJkjH z3t~Y9GIVW(ySy}Rau-t21{)kFl~5SmsbTNE;O105$m7kA!Cgc_TXgIj?Ia`o2xSxM zp$$J~rAd;%pd}_a?tG0PeW3zsF0@llN#Q#e z(H{qK=55MHGP4^=T|3!xSBesj0zr{iVb@8%=nwar0T@6;}qjZJVInS_{+@TpCbT)qq-}Hf*#c z6z7-hv^M#RS}Z8FgFW6R0cOB0vYIyen^~JXDz<41@OeP6X;_T0uX~rpxw(ds>kv=R z93$G|NCzSlQs{czH5pgfwwi+yGe{#5q9QryX38xbx^6(?O`vU2Y77po#(S_6K3`i? zQ`^VQrzA04*czH^7f)W`S22Ggw>>RyaM|o|DmRmk`YjsKgV~53l|0ua(wk3#wmkSH z_G0p&eH!UqU6=9%e^QoSB@BWZgyB#-+l`>xrikcp3jC4)vPgeB&2v3pWO-7;V<6rQy7)HJ0yfK&EpV4fuP1DaGM@Jq!uv0`5#kAT{2?~g9g!}5e&O??8z%I#^ZDo7;mK{8$V3>PY#4L2orJP_piH&H zlhpnl7MqT>*yLk(031934&o@=Q&@-zgKW%E>#;+xh@(}E0qeb@iq>hp;}bI8=?O?k zQm+Vv*vK&E1)TPf*vBgkWW|wIMUP|!#b?g2zRtgTqjg|53!E+RkJnxsdx*raj!Mm4S@;r~W=d0I(i!b$4W&o86KI}?Lr}ax z@lBWhUAW}T8P{@55&S@@8OTyEtfvw^Kg=a*k0y~GCY279tc>dCx5^38H-{`L>oM9* znB84Y$igKHd-QPi@*+;(P0M9S&c71KYc(_nAS2(svEe-M?+*Om9D+7`$p5+zlV=}u z4!~Ks&i@mAe>yHj1!7~#k3&hQ8>pg)a`qW>_ROduM?~^OY2a!smzS^_oEh>2p?%(U z4(7_}`Z8+ajBrsX7NwceW=#%}I#mb=sc6og0kL8h=cP<=DR3^ReEoWG^30j@I3t`3 z%?f=cmBXW_zCvG*$=b1|T6EIE#UxtN0U~J3?|G6A{0L^D^>D`p*ZvEGaic-MT!24b zz^aQ?SfE*o6>&Y+9or7lOS#7<0G-SSl4UPBhda5RvO$XHdpcR1t_=;dQF?=^rDIR* zBsA)4nr6wj&CjvUZ`|)H*@Wijd$LZ(OJ{|+3O6DL6{JC^d>peu*l_0T5G*~tC^WPd zH!Zf>_5PVNF!{`x-n7oVXGX%;wOKWD z=2c||Pn@W=_MV$N))E`3;C^6A#`-+4@Rh$b^r6LL_iNzYKXiA~+Xk=Fel9yE&KQT-YB3wc@0o9y*!9^2j)9C`A? zY5Vkw*OUhGU$De%aI3iO0{)W-fnrbicHsi~FNFEt@AbUiGGLEN$3`DSkGT7iK?iXl z^x0k6i?q83+q@eji%E$y<{t6~$I0p12SI~dx(5%EH^{R0X>uB*4ZA}k(tS&gjLro0 zvYub&Rmi3YcvF?r4HL>o)?Ry&r~U`~Zfm#VMN&|&qSC^8(Ib*ZM&mH!1i0O^TX7FdS|sVM(Sp}-w#4WF(?Q%e!`x|j!M8Tx zggi}1zDRzs_KYi!l7JUg$Ap);Qol!yZSO~Q+iovTbaF+e&FtV^WvlWjeho}`*-$CDeKd)s_KbOhhzSl^~CfQ=+uJ?K<%jP z+|;7cwF5tRa+09y$FZ!U=pI6h!+p@b#&{e)m0Ps8`Us}mzrBcr2p z^Vio_cTbFmiQ$@!t`Ec1(G*r)+ug#z7Tlb;kN8b=4O{Qd$=rCJgDg~xXIaRP$92Gs zS8xC~YYy;tKr^Gjj{&cwdzf6J(;(BozNrzXKl=QvRP*A;=jVZOCSX%RqXH_fKp)p8 zv>ATEZ@N33d#(8g+J?RIW>_OIIe<~YedfA-WgM99iXq6CID?=I_h8&={uCYgp_7Dh zdyh-N+Mi9Y==eDfbu)b8I_<0nAELz7->+Qx{c3X6P+pZB=fg(BRbz%O-`;c<^Z^?| zpR-LBy_O9f(}Z)sr=>Sntr*Wl;?|i$XWSE#Vm0C%@&O%6Gm%NrT5&oJRxQ#g!%Cfj z)HolImUY)BE3=+yqjhG@vd5lDN1k=g<1W zk@rzqeYR>82AAZp8{)eQ$t>cW% zpTQ5BNFPGqcX8Y3{$kW?0Ut*dLmjCxf0%pb|aPgr037 zXQ_7O9CU7SFrBx1h3#$$pa*-1J%eF07{>Lku(t%*&2C|TR4bGT z%mvJIe#=K(qoNV_uIZh_eQ_Mj@P0h!qww=p`6xLSDtX3_2Y$F5bR8)v%-L672{w>z z$;`Mj#txo|9hC%3pMdx7Pe+QSf5GdEN4U)V%Pa1@zzXNg(L9uM$eiJp(O_k;!pAIw zk5*fhojq_Yo9CFjoPoVXb`@mA6O)C-GaxR(B3oEvz^zjkM;1TZU{g**L0NrGNy!AT zyLwqw*L(XeIkflQA**xJ?yt`omzL9z2N$j!dEbP|_sl`AQ7aZreE*Rr-ky2S?4|2x zFIqiHh$WM7zK3bP1}2?xbdHP{((#n3mZ~KWTjQs=GM2J{N-+t}pi|-M5jd z6W7<7+{AVQG3@)!tAd_-;gFTJ1cwc6a!rE=<#^cPs?CXuECE*k(hV&}=;1m8_fUdTne`Sw~D5bCe zkRMh z%z3BC$yA{vXbKuY^2hi>{`mqv$)EB8urzSr2!7+{v%xgZ(231W*l@ruE}5sR+PV1^ zn|jwz*ZcJvYwNwCXVunP`=|bY;bWwwjUR(cN9F? zIX^Ux^R+qh1=`G$xLiGGd@k&#A}~zWwHjE@T2BjWfuT``ERpN%%+#o=)wOj!yRRw7 zCF(P(b~UWVJ_u#q&(9wWh(TN83W{-&lFcabUKg;%3z~% zqOJsIq{1@Rj?ApuP~LlM&9LRbIBRgpT6TZa!K3*(wxD=JL6;|s9F8DIA*DYI(|--q zj}hqqQ%%ToXsRyKrMUj z(J=%2mD(rv>|<`20+U_ycFq|11L(80*VLZf8wv)M_U&G?JRs@~ZaVs08z0y8xHU06 z`uO8$)b7W>GxJO@UcvRYiRyj4XBBgMB{sAwa=XR0TKbFS z{_w~vN7&0=CHGUs3Cc+Px=fm{mW&OUW$)XinFasI0qAoF%wC5WxNzL`PIu6{b&zr0 zJ9awTw_|=@!R&0RDWu<=fBS4n^Q-tYa%Q(#d|&Bk#X}4U+hiK8G`e{nhi-vhrDzIx zr$VKWF<~pu>%XUupTD5xF~%J5Ffx|Hc-Ow}4-&?%a8TmKFE;F#oG$=XdBubH*((l@ z&cBA+u7j!QoDgM+&CEz)?UBHb3kvgV3}(U_1G(hbM!TgkEixxFBa%rD%psn-l{#Km z3$Pbv{j|V|FN9rmv1^KdGX6=mwe3}b?cW-pa`B10x%ug7dwZ>&hJfB7P0*K@+92=i zC=}xaCIjopYvi0yAhRfrf3z>Mnn?$&1zgX_5V*+ek?pW#xvM0jYVg|OxtRjH#pPKu z29>O>z?Y-O#*A1C4){@KLXPWIk}Wa zZEPMOD_`+P6YX9h(6&<)Le1vS#J;h=#oDHG#1`)ey8p-#)E=&Ss)%=p?8=bsF?{C4$YMCwlbMY4jNU=)vO;Di0h- zCxu_34`fPk-|-Ue0rSbok}!5bcS>-3Q$V0%+jd+Eu91TA?#DQ>*St-|S@Pm$CT1)v5y z$TxBvfnA#zx9o}Uq@o@sSx;iiwkKG~v>v;Wj4ji>pK$mM%~`fBSs-fz$Z7rz6oo~g zS2!cO5DxEV^z4z5(W8g;R#Q`PPEr2h!{I~8Nz9x;TcM*oYDoFD(q5-Dwzpg1cCi6b_`s1BJ`h0!RSf)#=)#ChDvtj?y$$&=`(O(Ouzj68nJR7Da@NU6`cTOy?YJrgWd#X)s;i4(VNiR&zeyv zYcC&*ZMu_;3oKjg{%2(u1G<;5r@O^1hwQsfUi!HC0I!W1GjdpDYHCzim+ZuWnd!rA z4b$RNJB4aFmKB%*M$9HL`Dwpolu&RVu%RvjSi>2mKpa=*Xj8e zu>t@+*OLf-8(8t zL&9#s)6imhli(xz;xu=OHFHN1-jRghnfLe=6xN}M;F~(vYj9n^4UV7C`GH^yimiuv zuDP`vh!_4!)2S|Vo5O%EO@I)OX0Y zNwVeM^vNqUhF5&UV)`oJ!zC&qL+KaXl+o9w(it+O2z9K(q0H9^*lb-bcWuedwKzwSblt* ziRePhS2&+otfj#?C$rs*+o4&1gXH@U9EZ+VwU1=m&8B zo$OwUv=xD&W)tm4Uz|F-nP9gjLm_6~icXf)}a7yAyu;8E^>*L}+ zQ~)|%DX!lxq<+KDqt)OsWa=6kC654OBZuw>S;%#*Hx&tdf5qVwV5t3O-KmkkJ3a?Ed_ANtJBK2}l0h;kD6qbm@B11m3P$@5-ACOFy*1<4fyw|c-8f4pe}J6vz& zhgOO*D(_J#$gsL#?EZc+QACLLyg2kB7+ZxZ!1uErh68)#?_7HL*eO1SO04*)oM6=(=QVerZEKQ1}73yiP}yq4oSeNUJ}Yoj%$63ttGxsfC~B2@t^SBus( zjG}FnDql$2!brrVq+poLU}2k$reT>K!_=Z_bjHU3Qi($2R|<_^tY8O*VIy!ade?aX zEJsyg;G%2K@vI);qmU)j2QMmC1OB5P2}Lq~b(^k41@2qXuvU6r!T6Ptg1#BighJnK&jh5!0KmhTMcn3WAIob-Q-2grpj~zqT z(Igymnw~{p|BW64!+!>m&+gfseLiQ!gP%GtbHAc@dJjf7e!Z|`dG4XY#oI43ZS&!< z>YKC8giAe-J0?zvA(&s7gl-(W2z+jUX=tmf*Rvqf!&571`~y$UB#&&qdrpu|`z%RPy8n_WCBn}j%+I6Z`ZK{lP_ksxS)%O;7Az3f zp-}4CtOMirOl~~U?}t~9qxT#4AA02n(BrR>u|r4qjupRlnB{SpZoy!ONTNcWDH%J_D7}%37an)x%sXaFRWd+ZtZzk;(B4tOGAgP zh9w8qtvmn5hIQLtS-p11Fs3yf2b~^6LLoYZN7$yg4wkGQHuR-6t`}g*c|z~Pf$hVF ztX=)e_H`THIKOV4;BTD8?XZaPA>$FkBm;4WCBhY*fki?U!kr0w9ZSnGJ1Mq|z9odc zB^3|n0xf#(IyAXn^!2US&t4$xrG#!al~Qg$vo~#bP22vNooSmFo!lT>h)ri3i8BVR zWOJgLHhH0+LHFyf>#!Ti3*@%V3vPDjMg2-*u}S+S3me*(G@T&RR@zNXO}kqOye-W_ z*pAQ%$u@E)FHaSC zxFA*Go)HGzrz5c|a;>CDC0Ve)YkK#6_Afz%4IKyfeB$p<3Y=i-xfi_P6S)~qM z&{xc95Aam&x%ES$OK4uqT--L-;mA0XIjTrMsn!lUpgr@nEN6($h^?q_h6 zq0d=-i*YhCwVv?VxrQa4$+{+2=O(eu%jkmiqtKo1D1Vg2bQJmqThxca2bIZBCOc*_#lVN1L zCIynIV(xv0IB7ny*Jcs~K`A>#72Li4Qt#dtaVD|*5-brW6zAsWm5LLI@n!cL>p=** zxgMJ~Ew{J2ckiLntm5h_d@alYwOql-^iUO%TaM-C6k8#JHAoZk!N2U`P!M0XYl|3x&%+i68~SxJ_Z2G ze^-W1BT?wc|C;v-l1k1qnJ3~9=JW*r4}60koKDSu!#1l%m*LC*CD#n+<~I=czgDJ_ zq5GT3-j?WvLj|!ZhyOz{;5f$!bAsi;>C<=YesoGzWlm1-KmMyyZA!A3hviJ!y<__H z2Uqo)R@uwp0AK&Nr6lhcJi26LEMx{LQ%Kg&b*xjo#!T-5ATB#AoWp>DLM)#Oaqp?+ z>6r|Qj`V8`(-IV%*F6;|&`qF??29r}yXR@pUKFIsD@{Yq*vq>aQOmSsrj_Oecc^h) z(B<7)ZEm#om+jlTSNB0L>_YDzf_@Tj*e3lb5p&OT;^>K#qDTP4&Udal z%yX{ynq2SkoNPW6#gh&-XRkO{vGWhZ)FzmE*VzsZrUrGW8)rl%Tzykh^PyJxvGirL z7QP6;i_M>b7XZ&SAHq&cJp;fGFdcrw4#VZqon{~aCm3?jJSQH5elvrfNRA7}4nvp8 z9tl2R4|{=g(3N*at-+`?Sd?0z0{(q#f&WK+KmNFu&0$(v_O|TZ%e1tf+b5s((cVl* z;#GA#84~&*IRc(-cS0n~)S)i)UARKnkHA3&;p}Fu=M@U|7g-bXyhC~OBzopBI&tbd z_DI`zDXr+41BBz9Juh>(`OfRCN%R6`1BP$@_}wW`aTruWf7uHjVH^b4$z1XM5d$bi zK=vHq<_Zi6B;Xo}LjQK&JCWVJNXf|B53xw(of2Fl6$bnzyvvb~H-UJEPQfd9d%SGK zN5}9SJP6{BT|~EUpv_WhrDC4 z#9QoomNCc6Msr}&=U@ujd;{ISc8LV2e%L`uSPX*g3BY zah9=rr#BKqbNES!||$$VT8=F0UiTkN5f z+7HKPoX_4Jgcuvpj~nmYIsflfM}ECHVd>~^aK#uxJ`MC?MSW=*gxmh3Ob}hyPGf!` zz8}^YRRCM7>b(QMMjxVYVOQ6J8TcBmMEgNF8pl6ce4T`b=Ax1BvF7`*qrtLyk9zW&1?X_2H7mVmSL;2qtMlrkGF&$W`-0|KJ+rKfR@`lV)1qijn7?fMr4r4c}@ex3(2W(yIzoTv{a0tXpfAq?gSb)aYkVp1|T^>guDS zjY1W)J;#uDO#Hu@Sq@r_lI#C@qWS6e29mWM&pubwbuga%U-8&#g#Dj+L_6D#EB_;h zZHAXyT9|6^Be#@|P%D+hCj3ZY;#y<1!Y734*$hz0)v)UYe*oBd4bZ{;u6Mvum;o1{ zcR~4?yC4mnJVVO672E$}?kx6faj$D5%hk@%pF;~RjChMtGbXylV4!nN=y@lR7z~6TD0Oydfck5R4J68mb2zYegi*YFV z0I&hu0rWe34&{LJjKoI~yOEwVB&-9VR39XJQGrVmX?Ej`krHuMNW-nB{!)Nvj)^R# zcWQ3+jMbj>09;1DvvU<8!kREL0}5OQhi{!yglxJqnLMw@&!PC7PLE>YsauMW+cy;3 zHnmPqk6Q(oPu)VlE934=-qbohIS|*zLR5F_6#9LWVjC_qG&9?|r`T?uv&6|pG4OY? z`0=e7GuUo32BBCYn*e4z+#%sn*5a8L0|JoMOB^xzX15z~WL;0_6o zu8C+xkK&OvCNr^rHH7j{y-JSwlXhp?Si5EoSO%7_U5l3ByFXy$v17>J_02Jc>aqeH zq*k@V+GIxT^UBKG>3j2KWD+~Tu@CrBzh8?Y| zJBk`-ygs!@k10fcr@%li6w~k_T0-|lP=Ra*4scWeybC(*DYv6)RBbN@Pu#u_K)`UJ zb;%CbU8ry*n<~+Hkb`L)V!q*YTs7t+4AY1c=Do32DWs@CFh6i>d9pJ>Dvrmx zFy-WQFkrKrG~$72+4;auXWLozQGm?Pv+Bv|Q97G=q*@^mXO)HMZNkVq=FCpsSY#!T zxo*Ne#(?1R<>k-bbI-te^9J5?&$G)fFF&T8=K1W~P^xX3UK`e)67W^>fMHNqke^K<+@JkO~beP0z$c zpbp=ZX1IPLU`&>2rAxvZP3(^!X6J*M;3xDdeMf|&;VbM3td{}~IYRk_>-!mSE${Do z9X=u8L}HvnB95I#I+1Yg4Bmf+s}|-H8Z8^y6Znb@(d%f0bHX)e2G(fT>q2_`{E+ZG zNjMBG5-YuH4$OCvDf18@hO1OgqI;)kvK-;=^{e7rMHcEZG!U@*h_2?3Ww*EYXrI>N?-TPN`r8mnKsyt z>7Hv#SGnfypYiv&T&ToN7fuAJke^8H<~XcB5*zo@OXMt91xUp0swX|+Er1CoJ1`ON4ZCnAR%-(WhtZ_5MF5MEyNLQY ze`NK5NAFqApSPg06)Vux+}!gQR;<9i?o{lJOasyA3-l!{eExaYYxw$0y7wB-EXH~C zrFr;Z?$qK=NGy)*G)CT&1N-Hq^XG3klh_YjTL|rm6A5jw8x|6(Gg#vcFS;p=6+F%D zOfygdErk|IB|!*Gg*?5bwyx)=^#Z^r?|xo3J5iXmD0E z6vnV8qNAM^F_VH~g7E*r!q3{E7_~Yk=#-k=sT5jp=4|M&VY@hko( zuB4io9~4v+7!<9>fxqX8D4h=MtX8nIHZ5yP0tPcSw;EuyD8N&!-uWYH2C2l%f>Y@3 z3J`eyd@jlc3T$b?X6I*M3;F^?gP7-^7woO;wdYCSQr7Yww;Gm{K8*)tFcOY)eO?AW z1Rs{A!qjqdbYMBzTbF6cVy`G37W_VPz!a-7YQPNeGt$n0SLzjO?(oXVx3@9ES+7~# zMG=?Imo{KrGYxy~H1t()uQxxze&LLfK9@+^8Q{4iH=E!FYX4i)AoicEG$0#jxT)bD z_?JKN9}1NdYZaLpnPIlsFNDaTBey2cNo#20&oKdgxC+>zU zPqLF^Bw5`XtQMvms_6_(mYyF?y#rFKK$@ZjJ|U4lS*#D;?r`T{+oxcxVZ}9tysr~jPnZSzPo;hRZ%o)%A(HH-L z&VBp-`Db6S2)=T(s|Ngm{54&Vx;o=)lmtG|bY+t;PnkjNrJ&5t&a9wJ!d#}{pEI+# zi+qVFC#C9F%-MOuo4allB!Z*b0&plM>d8Roqqti4vLmRLyrHmnxpPV=lXp5%E0x$k zyhsE!!};iHn&{3zDNSqL40P)zu+u|TL2K1~TU58 z(J2optMhG-mc!4{JT}6$2V{aD&^-79)2b}KL_4Jx<35tbO^qA@^Aph3H?qNQikBPf zfo=)~>f6#1MH{_0Ho_bvOtEy^r2~GKvIZ=&7UV2kv+0 z1M2|~!Z!4v{Ft#WAHljz>Q5ua&w|qrv>MikL*>Yw>EHtL*@;x(LfT(o<6nRA*T4|8 z|85G}4~Fp9?p`B%yRj3!WlwxfvRaCaWH_*-$Zko%G>;g88O`}KuxS{1NRf_yZho4p z0J<5sw_!7I(;3Eo?a0k&5~3+#r``yl(Za|yje_;Y%UQg-E)NYef%|Sx85f9ouS8GNp_#Y-y(2$-3wkU!j-C@ zh@F$@us=w2h!vFKm$>nN74SX%3dvFGS6W(HZZh@UH~bK_#h1KSKCf2z>|wn6A+jHa z2VZzM#_QD<|99}cLc#~d;3~U?FB9Q80!NaaRvZ%G%yze>7S_*_^{=ut%y0qDY-j~H z3T;)~kJ6WkrEf@#TIqa9x?n-cnpknhJ!@pi+x!S19#F(KxfU%*PPCT$=}Qa1_=+-9 z!gGIqWYG8MSzdaETlJxzU#V;Vjzy_fgKsaJFQ0;XLzQ0)?`sU0@nn8PpwhJuzM=4q zDtG;0f-*d~jpoxS-HbgF!WIA&OftKFC0?!T1fO_JD{;`>1lVa9yoo zyLLzQY`4-48@p!(=neJLaRJ8K4E(LLkD_-pAx{Pep`*{7J$o2rYIOJpR6iZRbLQKu z9+%AlfqCmr*K+j9)}0szZMZC2ePDZ6!t-^k!B=n8UNer`r>?TqKV+9g>}N^FMUMYgk6a2{#iGjMbN z8}hG@TCpGfxee@fHJ=-`q7nFPL!;deCpX1=^`LhN%7KK7In3!6#3k1T1Ch+jDu?o7T{sSE+w*c5kp&2prOSTw$m% z%S&6LfhQC|p{7BDON;uC96#PTrfm4EjceCe_O(yW%9~*AontragWa*hzlw`7)#^m^ATYD__)zMhtI?apt4qm@$n4&2gClc zjEnz`1blD|IuVzDE%yA9nKZ`AWHWh85jhnJ{Il*TWugH(b0MATWY+O!otbWP!0UKB zJG}#Kx+0bxyos)YPQu5v&2!C0x367NanNt`*Ux`p1}IsNfAN2`f5wa#@Gq{z8YYKZ z!d+&vm;$DRsbu;x^~^B3W?1NUgt2%BIbT;e7!RwX&|i`Hmt?XNISN?Vt3ue0$zjpx z9719NY|z++8EF=W1k^)WNwW>9$c>X{EWr1PCG{ zpRyjs(9*Q5m?&$qN_qIOQk86tS`ib8?|cp)_Q7|NFFf{`8YVyXm?r0==KJ<|ATSl zh-%)%lKC@^Y`~g`4jA;^`)_;m#+%#v3qO&!UU~IbWoX=-#^a51;zHT_gO_t`)pO#) zQ0Uu_D8u6BRNJ7&gN}c|6tokJE6AyyQ&KXgI%hvx?xV+Ox#(4}q&OER)swLTiATr; z<2XBk?s2a*GIBgIfm1!1 zv$b0z=c3^L;FlfX&F*OEKmmndPW2RvjQPv^V0RBJ^|tb190q_;*DdyxawVNlX0ofb z!CD)`LJj!jwZ`WTH6myIQrE2?*&X0Zm;qSVztBq8FV3H7Iw$x0mewO@LruFKP*2l&9?)efa|Vd$~Aviy{4Ki$=ySr4s*djkqI`soIX#! z_SYtg1OKEr3#2^YpE!>Ne=V2gv4Ezx5d!$BYZ$nW5q4w#pug)!?o~`*IHg5ed!kh6 z;2Y0Po&OxrqVGnRVEKm%t7yV-LLB6qEp}V1BRdRd zqgE<_D=&HUb5kl%b73K1drf(6bRv8;ws0Hj=K3D`gJ*|!;lT5yBf-;{gYQw<&H};< z3cb2+(J z#4=)YPD^Fb8?lqiDHXKDj%;|fAQ6|b7hnquQF8?@V={czSg;eEf}yTIP_L1t&jYT@ zP}CFi7Ybh7R!I0kA()?);%Pi&@szj}2l_oXb>S)WGYG@-#)W+Fi%nSG{dWuR66rfX zRv6!a;0?s6*8DZseKr9%N7z5gEF27^Arqd+Q9)SWHqyfa9s_mG7VxX<3^_6A(hKx} zAh6371cJ%wCvdbdXGMXH{6+4pa0TcrEIND!N5GN9oq~-pzPSM0CUV`5{nI?`pDLNi zXE}vJ#VUZ0`qP_g;-5aloa7WRy@0x=^oSSD_QSC6VUz|}5s%b0pUSx9Cb-3Y1Iav9 zhMfBv!rcM4jvSGm?Z(f3r_V42@@zLb=ZDlysB1esr9AJJM`)vKyRY@nw~4-=cWq~V zq-VHAod=!8hpa3=VP350xl!-!7|3$|3Xe!czdJwo2bTrCB7E9O%(eXFRlXo1Rq-?o z@uPd;nWvvQ{>+O~327NQTE=hPWhCh|Hm`pnQaZ0v3e~}It;!nYU0PX*8yorU(CT{o zHbcJoncyR2anWz;U$iQFP^;3nk^uR1NRH|Vm4(~3!ch2@>pjw6%H;$W5%S|F9HyvWfLtR(lC7iPUh;Yt`gyY4J zh{J(8;k+1v!}`eSfb%GxjciQ^<9P8S;<)KxdxUib%UYasWYpn0f~nvZ|KZ)MN9gn2 zUe7hc^WBQH=44v!q}*~EB>W`x1FlO%M4a7TI2sYhLx|b|sy{rn14Q3or$(%!e5bpK zqAhSg*SMc!UF6=s^RAGd>W!ElTMO_h&O{_Y)4QK*JkKQp9$mmVN=Y7KiHSP+T5)k` zWw*uCc;S&EkqQ@e0^_L!U&AO;tR{sgxLiFI5}60@jcXHg2j{CXSwYiqIRpkgxJpUp zl0*rno6+|2*Ldg82^B!qvt1rEUOY5#?~CYddC++CAmIu6?8c)tOEtPvBUM+v6EWFs z@HF0d9H}L0+XcOrc%-lVaLEWJsm^MV=G{ah)3&&zOr#xPs&3S)q{Vn}l^(hTlTej0 z+M1@OZT_5~QKC%S;8^To;sztGCpPbbEHp@;d${%%ER3uI`Z%M6zr9t zPydcjK}v$X{bxR9`OEkeZJ1KBJ=hPy)k91n)sQ2SFCx^VV1Edg0+#DN!Hi(U{vN+Y z#1-gaPDNZBrAeBHH?Go6S0m=VThI)TeU$S^q$F6d>ux673tM5^BHO=3{j8CKTPB(LeJhYBSA8R8dcoj`NY)zSsuZ&nH0U zkLt+auZKHis+P&Fzjv8vI+NIb#C}1_PLM@^nE>0#kIYe)m8{y+Qi%xrx6h}YPF_iR-m?G4I@WX`d$|I(UtgMb>+7HMX`4pQ9Q2A+Xmmu* zv~*i0;<-bw*u-OvPr=k?CG6z!)k$pU<)gd(bLyAF--S+y?BMFzhy2dow$!I1aOFeY1p41x@a4}t8tOcFBbz*#%jcCYBO8o9! zTzizh;Fq|05hpAORzvX1*(WhCcdMknzE0qUwF{h>G$HIHTtHl3gec*K%2&XZ@gisu zp?%7g#ZE%8Xco?a@PD@oXF>Wt?2nho{WC!_qUVWKqC|0T^D-fx!*UV(3zbLGxL$~? z!3M!OmpTnB7m+S6MX4B5vf5ySb6X>P3qFXIc^R%r#l3eEh5oRF>XJ}ayHWDlsW}BD zmL0q-G2EpL1{!ipnB*hmyS^*%7<^p?$8bHxb$lnnlIuc1?w*L&hq^G`tl3(|POe zv{dRuwHhTk-n~oJOCSIRJB9VqlP8gjo#>h9;bq}(%BHghYp1&p$9gZ+n9i;F*wLCP z)UntIsq(Y#JXk@N)MCi`N}SHQjq)f66E`n`M?sXLy^-oqv^Rp+Mr@8?AF&34I$S_p z4_^M0pIirtXS7~y5|SQXmBxIeJUl$g(~+E{v{GIqy*ocqU$owJ?a@tloqKdttb0jO zTho#A?Uu2~gCuBoAv^--+%$MP3&|kaKEd9|OGWw(G*h%aS4GlP$DB2^25^PTizypp z@n`572Wi_PT);kq4ukn<)xbfxV8b3>y7I`9Mb1XAages-v7u?H1JP~LB-N6_ z;v*~P9j3`-V+8(G7FOx>DN_iTH*ioR$?q1{@Xgnqd5K*S%P3Bby)M!}ze~hq#eLNH^Oel_%!tP$By-@fjEG^-K|c=S%l9 z-sJU6X}W#g{Y;VQ^~@*n?+>MC-Q~~fy`Hg;%AT>$c|Y@!Ka22s2FJ;s!9`xrzy;Ye z?C^R$OO`(?@_NRslb+$`yH|SD(gMc|<-_%M6fP!e!T8I{CCw8jXYj&9krvPBGnOe*iO- z8Ouy%<}yne#$eN!$onTP?c3Y_f_xw#bnyHC`h0C;aRUWn>T!h`OGyC?DkNcV-iU8ghK7@_GKa>=MKPgr-cwhY>(q*_69C?+Z)<;z7?KP8$RCs5Da*%>}}{Q};8aaDupeE=4^1dGnJZstnhUp8D%q7^q`4>Ld^w2FUlkuVL8N zU%S5hdIsnZ!$5!3ze(sF* z{$QTN+odhH<2HJpRx#5JTgM7)A8WCN9E5G;NNgn;Em`y2>hpgMBfBZho8bQYbdvk; zh72mZoZ|j-MslySyC;ab_yQADW>0$UU*TMbZIrPr{jn0^@w6b8vI`kI& zbGxe%u%DMZCseZcy8?H>L8$vWkiK!F^Y~Wg-|}H5*&2lGP54LrII!WglX>{>tOZ#v zzX#wjXG}S}qnC3M{MQcGLGavK^v=eOY;S>)8Njv$PcFgT|%oyX%pMF}GJ9 z-sp@aY{+zo>_-tuH7L?;*R5XqQ_b{c>X-&*I5UQsfP2}Q3}ZIf>=s~fSWFuHrKDF% z{Kb0RNgviGKo=|dj00%Cl#2a50L?p!~`mz$hj<0_54A}hPcfuPdLh<-1YR(5~M zR9X=QyHu7M`#oDxS@|9LR8~};Dvz%)v9l`TdY!B&t@yICqT+k}6( z?#qfw0a#vH`FVU*bOnqrHAQ__T2cC4bX9z*3v#cQ#aEhGOI&3vS{hYZ8V3SPE5mW7 zrLMDar4^Ah*Jm-w@9~FZ>Uxc4S{YYWc>DOgh(RU_qE{%vJt`RDP` z6+f58)kF%J#+QB~=qq48VOFt!vSjWVLzdTk!iKM6!=2w!`{;S5BzpvlGsAnqY}cDJ z*zh~}w@$>xHkrA_U1W0z9fB#WX1WE-g!wGeGjSY~tbXDKI%9;zC}0E_g&v$iZ~-W3 zImT`fY&)q9Py)+D;|^udFhQHvdeF1(Y z;L7=O>oLSFNCgyRDvrdL>={q`92I+vor=m_dkIoJJH;7G5k0cTG#o1M3D^KOh{A@l zXFTDURY9;4oc$8bBv^OAS=XDQs9W(uSI1#aTzkFyG=UctV9CJhROc4l`!#@5;8gRs z60SEt8X#0Xn#nM2_yMVe4(J8WBHUSo1M8Pxy0%ETMAoaYEG0Ua9~m9bGoJ2LMES{f zzKQvfk?|@M4~%deSyzOM)wWD#Iw1;<0}nVq0QVELx7fty7b&WDnal(Y&7{R@r%YO- zmLPnI3ce&rU?LVW)@N^Cw1Bu5*cTho%D)iG1IV(pAK9tRPY@(j#!f?JBC0np7!%7E zhJX#N+Lpizui=3Pyex14L%zf{Pcgk@EAir{;U!yRh?L2- z7pp=mpGm7yhzoB81tyrnQd?9nrV!S1$@>?a%J(h~uBM=^C>y*9E+V@pHHB`)-{i@g zC|jgLXdJ;b7BKvCebiSk35RN3(&Pr`W~h`{wU&}Caq#ya$R7pp_c$**&#}3jx%rdk z_qbFlS5Ns`tuyv6&$53g0-M$$*Frxp7$(Hz}X6lVH*TMp zG4>gm_}K%_k9}48Aa;9@UNwCIdT;@&bEa`DdzCdh#|0UDRBW=!$FR=z;36=I5!O`7 z^_}e28Y1XK7S##(AL~E(vRj-n&R9}{zv7N9D8zpY7m{zZ^&d0|4&QAF39*nb)B?i0 zn@ru&xA+_U+@Xd68PBbx+e&WFcqyhw_myOa1hZHU?^3{V0;jIM-lQx7E6%6Ab-fi$ z5JzfNZ;Nk3^N&B;(&Rvo^`w*=I-=>r=rK(}*a{8wBFgol^88~#D|v>H)z3ZFqi<28 zH`&&7#nsu_ns%Fg^NH4U(YK^NK-fRf^{3~Nh%z9gjctYdhd>`0I+Dh}$%ChFPKZ3( zBM!cAk8E3E0N`jj!tSQ^#_(|#T4C(&-8<1cAYf zl26u?@r0I}bc{%tn<{R*P1ZWm(eC2M7cGABiA9T#peMLH@a~ewpIEf;$m7mAih?`T zM_}D!OaU~S#d_`C?sy_l%q39;Lh+xhGdjWDxeK$1DCw>btb!Js7OC#er@}BP9gh*l zw{gAcgz*@YkO8Mj0%HCl+?{Zd>SeCNnJ#22jG{=Jpizz6Adab!acq&EP2`#ko*IRM zB!q-ZyoNXLVXp`}OomZVBOwNck#QHY%D=}3MyMwkLgi21SCdLIkgCVgDy9M!&i@1J zJLX~`spGczWTycWX+A=YE&OBQJW^u<$5P#5e#xE?cA~GCV+F{WhY@k@_FX8bBCg(6 zxMVW}8_{ug7m>@tKjts&OL!+ug!-OXK15eF!ftXlHy?y|w~bmL6kaHSTaH3OL>q_m z3&u1uY*K@=3A!GySRhoy0;z7~?UPVzf$db`hz3eoBH_Ce_o7dHndfuI;% zVYhHbVa!Ud`$~F#tFRwESg>Z~sP*ecj#`_4WbvXWo?N`>ad>z1nsp;btX(s5(c?!J zE_&ke)_$K^9GAnM^(~|(ezh#1>S$bzpmsd2M%OQhJ6z18DDBe}@IVJcb!~i2%Bjc! zd>A~7db&O!-$E)fdgW%ulUCZ7LM|m7sev!6a&oGA=j8N4mpwrnn2^(}SB|5q7y8{D zzO{)%aB3{8Q*8sicH%Iy6T>m^Y#U5s%eHdgaN8vxQM5hn^!XE+mLr2DO zgNMj7wFG1fz8cLrI{-ZO@A4FO5i$ygPy%`!eXBg5{bTSD7^DA`6Q#+S0%cKMC-CXOKs~X2G%w z4H(V@a8tPmZ#(!No9ujl1{b&#|Bm7Un|~K7oZlrWPxRlOQ?2JL;volFrYFw8X3!{277cIEDJ^D$(v)Da^VS#;BDfLc_z2#JpBXK7v-qpD=?SvkY?FQ{ z1z1(UaRoehF6~T)>(R66@F5d8aiG-qen>HVE1BZU)d7z;(v*P%DAGktxn*cUkm~0zaC$5hIWTBsx9B^jIDh3AfWi@28 zOu))A|IoNvU9n$g^A%G~RBVWHL})m>I4L@^99-FC*K4{(#|Cy%7b_-)Mt6&bP&vrK zM-*-0UF+d#{niMm!w<2`n@Csd*aLC1Q%2cH#klSA9@5}RS`iAr# zp@A@IP1AL*6E_eYDpV=_jGD4|Kaie+!pbzDBqW&Ueae!ez!xb=oGLy|+sPk{*|TpT zgZ<`#EqA$j{Nq?NH1w>OLZ+U%k2%JC3VeVXgo0R53FhJQ=p8nNGQncgI}$9}4!uFa zi@&V+YZ12;pa-<+9ilfv&rDNjvmIFUdU6;EJ(Prtji-l^V9{hbu<#SCL4f$aIxHRX z+=NAB(3|3l0Z~0Wt{b9$HYcF8ceaCvPtry{u34%mpkMibCin;Pcmw3U@`hFJk3fx^sjfyz$FN`D13aUd`d@bQoj z@JUMc31p|l^B_PC2~L1ACCLZlU`S8^;7pJY^hr+f3F2IlIu@t^K|sF0RDjb%sN%vy zc^?+&IRasIfc4?R!Z}s3mIFQ*MGILUUa#krkkzul#|J}LsO0o|lIV^lB>_E?2$B+- z6H^kV8AKWo`mo_)97fPVLWI?0s*2DsUIm@Mn=yZwV>f>s7mv$;`HSbEz#nAq<&#T! zWw+#dnB0kFlTtaDl*+Qnolr0|CqVq!J7(LKci!2uZA`ydXfGQ#X7uPW^}361K)mo;E|aX;X(R7-}gZG#AF2oWW}&*6&s>uRe>3 z5Y9&pGGej<0||nX)oD435Ew`hRGe1FDbyfW6Xok0rD1(J7~l&7fhJn1jMf0968Z)} z&bL_|sZ>U)p;7@=evtQpLE%0=;X%-chkh!kP`WCiInk1Q1DcZ(lOg@)W@(~*e4;hb zM+yA=A&+f;q)HX30VyP@Oe#zZGOK$uXcD4KsWGa`32A4m z!Z}~Rj8O>{n$WEAr*(dc5Fg(N70~)F*8A~V@p`O|UWfZ>ePVzSIC!IMg*{c--p@p{;vC6e|(E_EJI+H!4OdlSNaNmWIn@i+xd^k zUgKmhYj1)^4emqinydxv`vu{yZ@`6G6RP?UsRJ{?IhTJ)H~ypAxCqzlDB>C_jGF}Y zL1_^-@Y!8wX$e0lPw?SW7$tXzy9fL5VdOj!5W<+^7<*Q5yv@o5^C8%;w`Zk+SZsI2 z)9#7@wwBx@=-4kmqhq^)cGG4Mva9)JkP4mvX=`sI=k2xd{=Nly{Vb(DN-ePD7jzs{ z{qg_^x&MCj^Y-`Adm#1w)qmZ0-(RZ>YHJG;O5@{82_HdNZfE!?#+T7!D@1nXms|_8 z=Q6=eT?v5^ve%D2D?XN^=hNyblsXvpEXHPKu*cyyy?5{2oZilZIn~uUIlX(caav9H z^&>~FD=F$XxP?KRTbPDn-AdMt9I>H$VBlad;IG?Y0613PrE`6K=Pvd5chDgGTM-me zJ!5)fJ5=m3F0OxL?_822kN=HYDaEW)%4!3w5nW3@80-^wV=oU{u4bu zI54nu-Edr-ZbKWG7BGcrY3Nr}vTnr4wWS(u9oM~N#E6p8;biCk;iVn~WbBn*g#ZAg_?r zgnKoXvH=)i@umwGHf_9c?j>#TPArBG(AyyW<6(V4;BI#0`OOzbo~M`vaAiYN9K`xax3MC1i?4zylx)-6 zxnjbE?Gwhs-aE#RudEpF`aAUD8PgwboH45!fVIKf1(J^gik z-FMUp)B?bXX8~Bo!Zkhn;S1FAEC$}==g%;KOh`)$_ab+mF)&Gt9oJ+pW*{?)nZ_(+ zRx(?dhj8zBf_VHK)<*^I{~XyCBkm7z7il5=h22J!QilUJd{+o;I#xDXC$%I}#TMDM zMs^MLSRb$+U>(*^MQo~4Ageyoy0xbuNaSFO9xXQsaMD1~BFXZ=i{ z`_`>mj9x5ST$o<xVQ*)Uh~Q;YgWJd>Z)FoCiSYCIPqj~WMr^5GSc-! zNJK;kz5qYPB>4F&f;47-Kh#rg4)EnQL1r9F;ULWzAIvLE!NI|e{&B&<8im5B4d(qd z!CEpv9~^vMfgc%_^c%e&#QXXu1ZsHS05dqIR`~gwH9-o0KWsU1d+=fWxC`6`tj$r3 znMw81n?=lO=6>c7^9u7ZStVd1n{874z-o-|lvcg>aiYSJAM_VWCzJ$|I>c2^>Qi=Y zR^U3v+JWm_!ISGEKrf}|xYo_GYgWQlD)d^}wWE#FT11V;IA*=ofpy&=>be7af7tgU z<|`fOOk^mHID(c02e=yUGif{v#!up+*AHBd&g(3`n3a|P!oBxB|NMRTzOZ53_HpC3e;#fQ z4>uzd{Q)2P#j69ASQ~-@6=JYKr+S99 z3xBT-*6<2ruqIf+$Dx<8lB(nV{CIUxJXq(a48%7W6lDG}Z)s|$9v`9gVAe-HI;Aen zdoG}^GH9jGk^ME(0|5w}UbFv*&&r_6x&VW5P<+gk=xxgejSm4JWc;9I+oGq$#1Ar3 zyFQiSxDlL>bjFB5qcmDHWMp*~`vb>04O|6V&nbDQlH=GrJv@6dk8E*qQ|Q?}eq>xl zo>D37&}vec5>kL2JI^+{58pTr@O*O%U&T%tYLEK16X#c}>akfpV}gx0rIt=E;X=9Q zUwNL>lslKROQv#ZiRi*t$;OjhR>Q2CB`f*~`QC^9f=c#dns2ywzC1muQ>O$bV6v#d zTJ}X;fNoq**5;}Q0l>cq{Q>+7(C-la$rb>A^auM9=d|-Yd$Gj%BHOJF{R#XE(7({{ zpaA%xzw@za4WK^P1!f@U!>Xg_zM7B7&6TF@Fcj1hQ>4Ysr5kr;`*+^uC z;}>(A3q!{c*`xorfhQ0Hb)C5+Z~%mK;S#|@e8(p~A;1>0x-MMO+d$iePwWiwbs`#) z!~u|XHX5h{!Ync4d-H|~L(6rY!*Q3yDLW|>0=aDk!Z6jE^zMd0n7H!r$6Ur1Wf-vB z+02K*gne5S_L8=GFcQ#G7v*Ih@`{R)SEN`TZlp#qBof629nvV-kj|)>Uk0p(ovfbr4dWq zVUNdR&9>c`8en%$|icsuH6=mogRNS*$3*JH?_DOz;nI|ngt6{)5Uez1v(hcDefRmv23Ye*PPfRYZe6=| z>XGbQy7Tt9!4cuvih$AidY`aP8DSB9@*awrQnot!q5SHIu#A*&l`emDfFe6QqG3E- za<^~&fUMxUx`w!zu|vM7Ns9H=+p{&AG|SM^XuZ)lqV`Ml(r>?ku3y$h_!{-mr9&-g z8nwf&_l-@Wa!dz}+-Z$ zY){`}aIczM6I)%ZjwvxF^+MmyDT3R?Is}2Z3=0@5T?Rk=yw8KF9LR9$qj3U(JCATXEYea zgWgks!A60kSsQH9@$chv(_=xD(GZ}36G9U7=|EVfaLi`m7!nxNtBV#1d zFwo+_!H8Ye1YL;Ds5HjW9~1t`2lU6LBqQ=voaDzCXA#6`$tE%+5@fm2`IZRuMT*un zty?!Z)fauk(phAj-a1!mT@tsH=Icz<{{$cVER z0xP^HIw=hn78Dj1bS}&*D$EZBeft7G(61H*_3I1#`}NHMws=<`Qik;m!O2l+mS@I-5!rgyQd{eS0bpcJ4LYm( zthV;a;Nsfa$OZr!D!3!$=W7<^lV7x*gRa2<40c{Mc0p^Ciz?urR&`NAM`7$)*v{L8 zA980h(jQzsCbIS#WEiO?5j`@9N<@CJ)`-fZm;__Gb+f8BcI)@ivgtx1T@g+b;;z_QO@vw=b!SmOHpE&ItOX4YA?6bm)X14gRrf=nt+PTt^8e z-eSf&qfsa|Ay~6CN_>@Ir;Z+uR)n9Xo)wj46}`(UD|?p1ysUWVPtj~uY7s0MI}TUF z*zv&tUj&jb_;hV;VaSuUwbxbXjoMl;BESV|YgvmS8w@vQlqXdbC8M=nW1Uw?B|s;K zc9Kc}dGKrU`#4ulei$56`L`hMb?#-RH?s^!Q=6H6%#%0@e}Q?6c@IZbH<&M(ZO@R*^Lf!*^~~@6uK8&9Yo&N$xFnY$xtqD~!nk&kH-^2Mh zUWghHqQ`~o@Ix;6Vph0;(b7xY7B)Mk%dUDP>twX9FqaNQcNMPP5WCUumWB$e3h(@E zP#znj>?UvKM6I~R{A?pUA7yxvM52(Glne42s>bdy>C6&d%hR!=;|ALxY*qqOx+Gj% zWC3HYrLA?j5%NCz4Napl$}082M-p|3dHtHsvfc3r;#o@1@p3)j#qYDASwS5(7UQ)yOIY|j%7>QFs4+^!eV%CXXV zeZQzp%B)V4WDfSF5BGCvYvGGG%dU-2bZjry)YVsvZLrT87>NuluZc;$w3iNw{IVb& z2(W%8hs>fg&|hvE9h3$$m|$=MO{+2k8Es`oyRm6tew$b3YKti8+k#9+agYg`18kZu zjY*?|bebrQ#Wo)aarXuK8Rj)%U07h8IDps+A7+I;48mQ!;X+`xIe?uAO(W!w^GAdx zCO#K8k4g#akG?pZF@u0mT`$2OWVz_jHTMo9gpT4w@fGF z7K@?T`9ib3T$VgDDMCEov-A^4Qt}enL^07H-);|(kfT>I2>qQDDqZD^F@iFU9_yMo zwK44Fr?7Gl7I)%WmSWNP7kD@=>qGPyj~cCkNj3%#?qnlk{ zxdxoxxberwCVzD0eL(+cE&Pi9(Xe^$kw7M!=DTy=mksdtFBGby3@L9Q;cdWV@f@85 zukDwii@SVmMW(vQNuPzU?KlpqODnR<+%Bo=430aPU^~p5`?pbC}%K#o3mw zSEwN^n~?x2dvduiP`e4lL>X<%N38;0+qAfZZoS5A0UIrhL#4~*0{pr7B;I0lT~|TF z5k-t?F(}J%MYAib=dZK7UDhSjT8e08_JKJIxa<-4bF&(K_Fi7#&E2ql-dm z`Di9~k_zLrD%eev3$vQ9qZn`%Lr=>XAOi!d;N2wMSu^%IxtOd1^p-Ju$$$RBfXS6r zd%>3!eWN{g8$;evRaFIV0J4WmA`{xGhK9uyc`eJ{SUCB6Bo6OU+tpU9%Ap3=OieSj zZ<*o=44q%6$|zWr1Mf1X3V>@;X5ezf>z5?DR^grXr6Y;Jen#t=oL;$ zBWwXHB$YeIPUG`dj6V7(d$QKEuZ_*M00RILuTJaL>AYHx1dDJ@Ig_uZ>pHmwm z^R7+_dEx{`FWPzizP&f@9ExvuxMA*@DSkmQLSbB52Ic=`vD{NZfJc=$^kK-qoA zkKYG=1aTl9FRTMDM!erJ=5OfDNrX}9h>;0k)<*BqM;N_JjZl~JP=P2f7<=+WwUOit zwoC)Mo;!7P#R>`74ae=;MBYtq*Z`-4y$f&ck5>iz<7GmoqPRFRY0}NZz+H*Yw;o&% zzX1<#xONSgbN8^DyIuwl)r=pXT+~3~8yN~JGz%bMjW*>6wW)BEu#0fwjpeGRN zST@H6Akf8=YJJ!^RZ{IQjtx}dBJpaXOO1lSlc0{KuK;&2O$_?Lwkv2F-cQr3;2>rQ zO%GwfovUbi0@IGD^2?HHJ3-O+Fag3M^ll^< z4HhSbCU(XU!8d>XX-JUYM}Gk&5GVJQ%a2Z+AsVR0^3Peo!#w2daUMmW6K zDu@nT08arpO(3Z^gS-*15~ZT?+<>qHq~rCT)G|{f&u2*Kop8bij4A-$HRSot4o^%? zlldmE)#9y`?;_JIoCtg~{JvAA{)!Fy(M40#`S}YnX620QUo*+pa+;ep@NXG#Kre8x#<8z_&b)iNVbOn3e50g!(EVe+mIZSUS2 z)zB{5(%j6`ZYpm?$jO5L!Ob5{>*v-NGqY@;S+|Y>46`00&1Tk}zAFp3vZ6Xhg z=Qx(fDh;UhNch5X5?-rybEFzEm%N}^$fLoH;gtnq6cWC0MhK8T9EPv;nNl)Ptyqv1 zd3ffmwaez|=r=ddtc%RFld?b&8yiYDj+s=qoh$Uow^Qi@r)__Q(aw9SaMp~6-!Ukg zA6Z71n_IJdV34zTJ=0OGm>U`}u<`!k)iW1fdFtjV>V03sU*JD(Ofzrvg<>NAI~iO0 zO^?N=)@&Sdx0{R=U2FH<03;yyjs5D`H-5G^T{W|M@I!Zvo~y2e!41`8SJltws|xo_ z?N~9Y;J`Lv+$D7$+`^hzk|pKQ0K;gdr|?P+R$N8M6TqAU5&;pljrK^AZZ1Y1d-TW^ z6AsQH_pHBb^SoEcLzEsEv~0)91B;IjWv<~K{%GO@eC)YdV{A=hH#4q7n;yP<@#=Yd z#xziH+EUg4CYlF!9G^Hz@(&rab-xTW&2YTmUYxz0V9*$3=u`BKgp|-A{5Rv91GOog z3cT?j*YSX239W&*fLL4%5ZH-;+5*~t{0X$f+kg5I-hRbs&`chHUvJua4LR_p4e)I+ zq8)y98`<&`7!GekF^+(tKi)eUYz5;e_;upDZ8Z1ENw&Toq2ZrK|6TI)k@Ollm4Z9SdA>a*F8s`3rA?_k8>%d|IX5 zdBwaNz?>Y1J3HI$%uc+RRhfl8ln37U+i!@=82j6AU<^4$Klj?(mi-;n!l!@Rvg_KF zuBhJ}5ntv*ky$Ru*a6|)mwZPN zgyXy@A4d502|nOUzqixp_4y)sUO&u9PamcqR3U9FAG5EdWXH79W_iC>!!YElZ0{#; zE}gccq-6W_vU+)0iymw>Tg9{LLAsOQ**Fva%BgQC(vZzs<_%?8qDv+EtGbA^vYH#q zP1pAVPk^ZR}CN=kN)DH|XwZRUrD!$Z|W%cKL#M(-*q**vMN zR#cYs)eJ5Z)s~IA@=K-YRdw-tk@DIS6}-u&Uq5hSy3s5eUk{HNo$?v|9<^CEG>@64 z5WQ|JUd<`5DaO|;A{=!Qx6*erdBQzdK_nsOV;qgA7Wk7Z`0>;UTLD!#79i$C&vLcRw6Edi2;2-yJ))aPy`!k8j=#zj^%3rp@5BTT5a}AOo~A+87u@(H(=( z9G5wmW;$9KhWzq}V|UzvQ=zoqJ+^tvmd%en0aTkd!S^LE0F^=me|qjNdRPa;4e6j$ zzyHg+8<1?xc&Ug1{P%T#=g}};ZGa81JzSzM^?ONmL0+i_6oD#D`M{@7k}NxZCd*8o2FsWUGa0&b+9fso z8a`rBgF5nGQVDotnuwh}h2v&UN&XUO{Poo7_h%f2{l9t2fl6w(Fy zHa6DepTgzLbuf7h{04DGnkCuf(>V{E!v`RC+&%E>M(x_%+HEcRH<(hU=kv~_QDp8p z%AJJ|K#WYK1Fz+e$#J*K^Csmk#{B9*L_edBP>nCnOkW{Nszu?tPJ-#ZM z((4TCDKcP1iC{!R<$% zfGZMX6l~-1r-2A;dACVLNfag2S!jjxKQ_{>d(U@_5QBUGCM5SZ_8=a*nE4=CC!Z4_ zz7F7JRa6a*MHMmd!g43R$vPet4ok5%R3}4(Isg~KZ#u!YlP9w?o8eb04uHl@qxJ@2 zK4=cJLvH-M)e45+dOZgg-+2yf0${w7YdY~f{0Ywfut`Nr6s6Qt;A?Q@=SFJK-k(N{ z62r5wYf`dKk93crb<8m&`&SBkYyvKG`naCsJ&5Co1bQ|D{dmbp(3BDM9E5kgDU{^q zQiC?&r<(lk<;x~*eBm!($zzX^TPH7H?)D?E4TD=|dS|o@-mu*Ln|Ef*;2}enUNL0I z;1;^r8`gh;Yva1+Zm4PGJf6}nlVRE7ol=cvAr}jTDX;eUH6m{pA(d#yj9{uRX zb)&~5W^LWF<*BoX63n^!gOACLvz6{?;E}Tv8Jy$1OMjPRfgr+xKq!GAE z2Y%aj@>?||^vlh@M&5y6(BD+)fJ*Npmb{@j-49Y5ZAV)2s6 zZ|vOJRZluVOUuW&bLW!Be_p!u_zm-^oxd#ulXu|!kE8rOD1Usm3Bfff0;^M53&o_4 z;b8SL5711Qu=DWYDZ6f;GiTk-ew9~EnOs-5lU}g%=+T|<>d8wMpBVhsTypvB*;Vsz zY;KtcM+<$~k62IdUG zROJRsOUs52T~Qi{e0^c%$_rmF`}()#%YXYCJnwR5WR*LeSs6~(C}p5*SbJI7iuPe; zK?Ud!_bn$|m*e{;@v}T}d^zY$!nhvQZ#}9XHe#h0MyGIDXp{?J*))J5BAl&Exz)*G z+8dmc90d_QdHb?myEaZ-3KoJz%NH#oNievgZ4tO)*%em|Djy2a+wz4AmrdBT3pfrO zST#U-ydLHctyge!uqnjN8pB?h((XZHNx5i z=ZWDEHCgoHk`ZYQV=EVQ0_kXmrkK${I%R(4*oNT9#V?YioV*o&ykq{h`L`xI(mkGZ z^3biwu>)8WBN9KL_C&k?MIWS}MDlTFAC27rzPU4^cauG*y?PM@b&PO-CO{*ubI$eG ze|W=nb0-v54p_E*)T#+8jmI_nA2;3jk2y}SMm2uz$n87h6-DHON54CAD<`v z9mBebcBS0tUUJ7B-+zC{9ZTFMnX(-a!*=YBA-*2*-7+MrydF12JCB20-Sft-wr91^mv98+XDl5_{pNTQ@Cx1pUz_P3Vfcx+MW^*I})H*?<98 zgwEuJaLd`V@awU)HRKi{WEt5)27>dN>?mmK*|S?WkEs*vu9b8r=-mh> zBzTk%J-VN~L7O@RPa;~3jsFO>)AStN6K)Dlst>0$Ut)exwXVQqUQ=0_Z#KX982Kz4K18KZs>}xUGrzJOEWkX?u<#3o=wvkGbYcUt#1M4k+l^Sg=X{WihktO?I+G& zdkEHCKZ9y4n=*CWUEsE33$NTXH@Y%5^i0jfU~uS^?3`%cgtUw@@I-RVWWg`#o9UHA zOgL4EYAZ;2HX!^U{zZq?vxMt@(bx_s0Eehh9^Rc0UIK`7D+NFu(;`1N3m(rHWZN1I z7q~}cr}u|HPG0EBTd-{7P?mJ3jS5dQm~1QMQ>INAWLB*P-=9*u^!kbP%6;QHZdi5r z!03(>ufV5&s@?5a*2uK$``t$F_#S}U_9qI-vp=^2aQxOpEme8dRV5p0b|uEZL5~4y z_e}bF+=ju#ee^Q=OM)Uic--spb&!!1s-V$`Z#?t}Drf%Wfk}Qa9k}o|*aqi!W#7MU z-RW$AEpN$XC5!J|Tq2c&!u4R}hT-#W{^+Bd=MCSmL8=@ub=sai)20qkN|R?^yC=~% z(C4s(?9<_G;RugdC}HD=(xhOdx(r5Fpv7j2ud_5?K+P#{lEZi4fUl79i$Fiofaaj16S(ylib-Mm_f>eUX) z=_{z?hz3`n{ubur_{DDyu_SKHm*5UzksOf<>KpFq8=?KPR;Sprv?Lf%`<6Ov!y5Zl zFDY%(_?MIhf@;qXwEweKhXjQ;sr*arwss*n5Y+mF6gV7gI%AzUF*kSOMAP5B&rXlU zrcKC=On9~$G@r3fm=K9fn1KABn;u90k-Uk|RpUMyg=B?!jEAry2S-vI!rQ2e1iVHY z(P-lY<>Fi#5Fjb?)z_>)TnXexm;jUs{&?jN*1uYQ+y#F$;(JmPW+1!rM+;d`!MEUN zB!~djH9!gSDEK*i3j~3Yf-k`Du7T&_izG0CU{ap%hsxeTuR=1V6Vcf=0*MMhm_6JI zfa#KfcVSf~tWk+CXcy)gd~Z2W_v}(3FedfKqP={P9@8@$h(&sLu++jvS#D1@3P45x zumtk2m|am;pjHEJI$$;Gg3|Ii#YF`HGXU@~S(RAsv_)Inu4yhQv>GMyL4%qH4U$QW z)}rF(YuZ}#>`pjL>rrdnTJ%wSwB(l*>C!t(=a!bvwo6%7YM)(-98SH9q+rG8pTl>6 zPohrS+dAl)79(lNk+W1D+iG_?f2L(SGXb?BpUYczNZ2F*f4 zkO01vUP9CojYKQaNh~9F5r>F}5YG7n0uWG3Sx!s2`?xH?f2k{a(M4(dxIEYp0TV@h ziH$^{<*ADR$Gw0d7ttntQ=Umb5Z4+oPW8MrhtgPgntez}bdC+;me z!7vJy%A!=5)hdgEWxwg%Nz-zr(xOmW(6^FdLEW%AnpW5pC|qGtspKpRzp3{sWO9|t ztW;Q)N`+MRQS(ZXSYc7B%nIbGlv5NXBWn!-y*^;bQNd-Txkis2dXG8rBsq`w8L(wF zLz*_Rm5h6x$*>Ap;w!Ml;!Gy1h1bJ2aL0Rh6lC7yTd@MrPH;6zi7co9RImya2It}n zCPM#JG=N^M3We2X5m98~VRD5?B*a$Ylp>Z)T;l|bNSp(Xh5bl?#?owr zBV!qxU`0J3*xJSSY2z{B(Q|4ZjSMsw;SC*60FM=Y1m9W#;^+(U%qT1nRb$INUw^;% ztBK9c6T6fXTL5U8`1u~Ps%tj+VQr$cwwyd!0TM4UwoRLMtXK<)HOqJIT)rN3ty{5U z(}jcC+0=}=ZEbTCPfwgZdtwH7kAyD7OTFLyFX{*SDI`_&BU%u(AwVyWD5xDIUwhFp zWjX-;>)9T@5*spfSpcd&;`{O5pI#fo$RywrPq_$$kUfaVg0m(wE6%aG0dRZDd81yT z@s)dA7Ev}?0iXu*#B0VQNOi}P* zFc4@awNISbJ_&x~EB2JT-Q}LV4EP0|m7UJ>>G&(TrnU>sj}>Tsv=bpBf=4-sAz=%X zU<43vKrq>u-0F{GoerLh6#>LJ2rD@hkJx*62|!a{fW`XE1_Z1)R&EA`~) zvc2j$U0b7dCO@Py3=ffF@@WU02`Hz!%;!z1np&QGtW;ZAELuQqU;NwTPzaC*K@>=) z6%Q-5V3-_4Fp1KgNDj3T%>-V2OcC#7_r@@GaUc3@s0(kPk z2DDfXJd<9ZmR=u9Z%7N)*UI!#nO-I{NF@dtc(UuGQt`5xR=YvvEHBgSR&_%C1X}IsEi1 z-Yrzg^tSxc(m4((r_|fa3Y^Y@GP_>MNgZ=aOY?1dnX2&JE7H@)j~YCD+_>R`M`7AO zwY!U+O#AxGk)6b1VhdjHxn!m+BL6Q;lsFHpU)-Aq)=r7!;lp7UQ+dcZY4S#Abru&! zRjMB+{Ge9l6&6j&k41e(G?zY3niI!tmYjyh?E?y8CSELSXc*AYAQKzRvHSts8ym8% zHn>pZRB4=QwNs;VYCt;7zUpbYEIliGa7H+6)020QdRuxpvn?kpER&x@PRg#c6-+HC z?6gW)R$}ceL=KzIPLXizn{UGNKqXfBx79an8)yLL3^_vva!X2b10*BQFayKDZ4LF? z{3|S*B;$^~K0a(Pr5nZl z2fpGlrt`*hqqKQVqKe#}I7v1pPEr-1fe#rBAwEwHCy+%0c|6PVUTfk;@>*kn59#$G zKCDelAlv#?*a- z+W$DiP%{$$Ld?{v7eCzk&Zq$cMs*Dxg;knIy}6Y%cb%k8*4KA^I(#@CUcP+of+f(m zc)_}L3zmYnmM&Pk{K7voGLo|4KM0ok7SYK(qFliH|Jm%Jb!q+aK9dJHYUa=c;R3+r zDN9ZeWgb@=eB)uo_)=40qqW5?r;02|ETr^#xAx&Yu|5!BO20X2ekl8&F}qbBe}Wuc+sQddXLZi>^C_?R~5M3cCbje%X6pqA+upzGaR12wDU0KVDv zVNUKgKy>b7*U=sQO|_q#9@F9V&ElthpfIP~Liuol-XzbogMT&tGclh09Loy}5iWEf znKP3h;{P+cyHdPik;7?JyQ@nLM!j6)DR&{LYY@~;CDksC(cxIMQNm_st@);0Ei>9n z`c*A)%S1|}qZ&`Q)efVIlew2v^((O(<*M>;)@0$uC}I_{o^D~9u*407uJ5r7;z7KD zCyF5E>9y%WlmT*D!-*#t=lXEo%0_q9iTR;*F+@v`r z`C=)v>`SU{#vR4}y|;ssO=R+104nbZrhzc_?%?MpWjono4t0^WrE%rZE$5WEgY2^PN(Gfj!>nZyHDF{!ALkj}*WiFZgJcqD00 zYdw7f$|s&|C9hM0h_GLiWXLdlRlMF4h^eEV-nD%kF09KY6>O*8JxD^0&ml{yRZlc& z?{F49J&5dgjOkCdK6hQ4?zvb<)W4jnHs;)2#56sao;hY+4u4xL_wW!2^A8dHw4Gt5 z01f%^ZTVSesw6yFl;2S)J2XU@)HPX2Y@l12W;C9Ple;${+4Gn=>gjqS7GxvwNdkPnCc9~399{sATTsxpjSRauh7@tEh=2I|^#CmsZKnjsS(e0x>BxxJi zKI@K7^D)@Kz}zjjRx?eH*Qc!?)_%IG_@xIEKa;T|_aMx`d0y;))cXcK@S~nUeSduc zOq0Oe5va#MtCl8iV95^YTnxt?1jiehA*jE{q;z(K!*c&sR}1@yF-qqEdaRzJ1gX8S zcqCS-10j|$u+FKYQUN;{Uv`1Gh>HMHS70hxb{`O#pm+OkRt_I zGd5|N6Pej}wo2HKIQa2!nw|=@)Tg%>WS#9NVMbi(ynToge!J>+2_?EKzPQ2hgCRO@ z){KLG4|9Kj5>c}|%Dj7P6oz|*E(C{IDZf4-qqhJ?x`@1;k@D+;GHMGjN*96K7zqlK zQ(L^7uH6g2g>S=e_a4|pO)KfY=_ernd1L?5sdPTUGR$F&Zfql&CNR-n|20W`DL4yRaY())y(N zT)Vl$p4C*@FJS7@>q^=VHFG)f_OQ6rX624m8?C=pGW)+{Rs8O8RePw3Mx^`Jx%@fY-?>Dd6sFSF8pw} zdgB~f4kDtj9kX3IS)NCeM^~*9@&{FfkJ`>07qk=v2uJWSVv-4{wQ8?AhUWCTbeg(p z)0-Mg;;&>L*ecsMn>o&OE%-b2J)AX&WY%=4;E7Sdaf?XE?*tK|oXlNtH7H6}~wH2DOKa#szIqpBkVJAb$=svngu!JTR9D)9^eKV3sT)uULY9 zfeQ2CxZDp5$n{)4yfJSTT?Rj=X+W-n51^l{f(>i|m>6AK3X~M}ua%%M@c=xy7L3L? zHKrTVa~Lau7b!h{4(n86e2QY?QUrS5axtmVvo^$ZB;T-dB|a%7=p^g0V!m6@{D?)# z(C!;*a`fUMLx456?)t0eQKm>>X&_>v=Iy+`F2_m^86q}h*W9?XPXKu*Xm&)>b4mo) z{u^p@Y~;|Pq%EiRhW$dclAQF2qZz61&&QIgTr9^&C=XVWiBl2bhycF&2BRV=}K66SuZJHRlIyy#- zm^o(Bq^yY(smx%|9~4rc-ykT**$nD>W{@rv(vkaSju_d|F$=CcC7C)^atbV)g;I`~ z`Oy8?dH=+%L3lT44sJ!*oYj4SzL{=B?eicy86)};4M;j&L~J9jA#Nk?!mIwd4uD3! zpk0GxPk}Swgei_qc1t|Q>$RLdg81GnG`{14nj>RyfaF;n6vcu1whYfBh)UpuSX)vF z1brUAF!Zq^G_U8eN(Lf5+6W&FFj!p~TX0Bf5u-FHY5)(CBqPWmut)O*>j?O0Kf`i* zG>Ju`qz+_+4MhW4dL8_QR+R3Ld4_5RhxiRL>Jw_Q%>Bv%^?_Rb5VfoJRLX!dTEw;8^`!hTtF75@_57@M5Vd_vQ5C;cy_ znxZA+e4=mVYgzJ5)}sONJ1MzVyjMbfI`#FLjnB*f;#3w!6r%4b>0g_4>CvU*T5c_t z(BXfYRd!nci4FdZKEY5yH})p9Ee$J?I-jw6Ae_|hLO~}5^56zf1xJX#DP)b zwQE?zfXzUOzO7t^i+&ByiN%D3-b3dT62gJ_20TI|h&sfvB7ln#RGtHIK7efn#_`R> z0lyFRwmuNoV+JQc#kFXD0H}}STp*73KR7C&#pf#DUB2n+k;~!raJAD~l5tFvQLD7r zhJqlxAs%wk($ZCn4;+I5FL%*gV>eL% za>Ju$tU;4`CbA3W2>{k?^>+{LaWL0 z@8RamtJEHIG~});i#54BW?0;k@rh3ymg4a3>hv0g**X|F;o)eSlR96#Y|)-Q+tW1a ztX*U8G$)>4TmV%-s=rknR^OgpV+n`-SB^bq4Z1*SWwB?D(iYHKeQHaiMp08>$#IGs zK9A=|qMhdY`^`%OUN1ApsIBf4MW#*76$R33e#?h%WM%rPS}?iOe1E-Zsgq&rf6E7< zEM6PlVtMxJ(pZycwskl7mi@}@X z1$nV4=7tB%%Yt4XJI|=Ao+8SdF%2V64J?4KW@iSdL14-h^8*d$r7nhTNaTa8EM7-2 zgctFPchVCOS0P8TNmSq%xd=>%SM)!E8v+mJk z4pdp~9UuyK7NmRVf{OL4Zn)u^uudB}F!=#n;+9nd%CoiiWDc}tX9utCJZ($&l8c@M zVffeD88hnO`$fg^f?3vqrX?Y3}z;mGXQ`(`P zxNz}IZ+&jOU!b^OzhY}qF5Kg^BuRzBj7UWQ-WX4F(_%y__V3>n(r7WMFee_vq(XaC zAQk>SggD8YAXJ-ef z5n$>R^FxiMB-JPYIavbHU=Yn95Y5mC*0~$A)d&B_=O4qUnq~( z^?xuVz)7(Bg_)1R-{3))tt{(=CUbz&Vs8i8a8G`^n+}$*U4H%byTe*d?lqH6Srd1x ztS!sZ-jy-HmYE&cKj~h3$U~m-!+~Hov=$b{@@HC_AGfRy`2y@Bldf*2C_Z;~RFsxE z0Emj=x!jx}wGhmhVR^j8yxPrh&G6SEP?%%VVL3VjHSkt?AmW7rL}7Am?0?y$#{XqQ zHWe1f@@H6@&!7hQ{kQ?OGr9Pj*-^33fFgJdl+ zEfE8zqcHpB$pR_fD=$tOfj4Z54`3F`V0Rt0+bn5la(Z_?tDCLzk?WR`byE8%=~~S- ziH=pEZ5Kt-^ffG1tQ&ZYbOR7H8OXgF<9=#I4Nbp2)Qd#8{IZd0BD zp7N~01JC?LZLbfrvVW@EbZ<$r|0Q$i0c|vnv5V75*fmtg!3*jk@2sO?H$BGd9gFdk zOUe4nkW}SE6s;JI;1R?`Jo5{7w)&hw$6PCdgdS@Y#^RV!_j?$@P=hCV(F5Y}kwk)+ zRyTvVdCXfPY>4my2A}vqoDyO@qaJKID#{??CCPh^(u0f#2Edn=ZKdG-cb9*6Wv4AL zLYMIdH<2taR;aYl{s2qO&D9wEwP{5X@cDw_19S}zY1fM-1)`}2Qa_z5oC;P=X2wzU zT5DztsWyK{!zsBfx-;}L_{I9`7k5&8AD9HcxK9MA|9tr%M-V+cs^f5xk$f+RbWCQ$Y>2>hw<2As)3N8VXg)6;4 zaYr>gf5jH~-r;KS)IWoo^paNH3xzYay22{nHIF|Ol;zxWU+ySps$BK+&km4I4y zH3%Ipgo%lt$eyaDSS|$As z$CRC%LcdHmxO`~t=)paX;1O3H7x)IOt%v62-$4^ekr>w)y@$oNK>gTKSuA1)9JT@) z@c4cQZ5nKwF`#nUdN2{h?rnnaFTVkvy}J&iuLiT0RSuZBl_cS{F7$&1F0 zT|D^;k{&yC=O{Aq2~aFr;|1E|{oz-Ox5KxN_9tr&lGpC0NN_X!dgIOTkrP$Gy7YF? z@7^*vhT45CdGM+i4SQMH)s-U`fi-KuqLGzX%hPB$i**U+XgUO|D9ApeE~wTTSFcLS-1Ymb-v;t<6X8BJhzG(#==`YOSwipSVW$g zf58%;@zl)e6Y|m?jTY9eudA!PI*e&~F~K1DW_0TI>*S7;urQli5lz_&13h=!bSqT6 z&gs+}R0@TX*E=10UZsGg^w2IZHKyxEGEeZhG*aR_diaIgmQmvbd8((p<_vIi2iNUS=4TT+TD?Ack2H0|7oB3{y*qrnDxKG2g=wBA7?Mj z;J`nC)a7|7Qi$`r)Cti=#NjT(o6*D~Vkxom|2_n{{~tm2i+@iZDC-}<6W0F$wmSdY zar(@^B{;&|UEJM;`d~<(KG;cIO>&~x3pS3@%S@Xle+)R@xGdIgJ z+t#_pIo57l^VQdDx36`Kb>Sa^^6Lv$Asq0 z8fz5tD3DLgV`_p#8CoT;Z<@}*9lhX%O{P0$=6kD`!C1>bcQoVEoiK= z)#u)SD!1NN-M9c`+4HIF1^u;E`utbmR3rEld}e}!jo=X)=D{ch9{aY^r*C61|Q8zd`0SJK?+z%l{E1^sgNdqgg>PB2L%&yWY#nwv!4%IWH}QGK))P; zhkm#_LF<{X&=@liA>l42B==onNlee`1w&$#7fqh}q;)VxFb<{;Xw?BVwj5z0lD)p12K`Be^&I@1C4uTF8767?4f!xjo^5PwgbQiK zU;F3J9#uasS3;BDvn<>TG^7l^)kqtR#*o1nG8%RCefD(eh2535@@#iSt0~K9$Szw{ z0q*zBnvhlHk7TxwZOMvyB3?JVS4#o7S_Kwpx9no*I=e{|ke5fY7HmV;Igla6 zG|Xtk)Lbf9WTWUuQ+I$y5Ee;+0Y9iMHlRxfTD;?eXNb7gr8OvkFod*ti!ZMT#Q6yR z(5qg4`DIvzzR0_73^}fRne=+r)bw9nOTLi!?M1S7_4YMB4|r+6G5w~X|BSWF6vNtD# zH_FG<(&19pzO1k$Jv=oWF5VDp%F2B^0wT}`i?PiS;dxS^F9Q(XY(z9sj&D)9R7YB? zj~HTc9nA@L>HJ>G4&sp>qLQL1;N@_0D7`tH*_fWzd@Hm5+%<55I}7-N2oV|@j=!~n zEr?dtH*CIgYhy!IE}b^CF&u6j+8heO$(z7o*K-@!EqdeN&Uq_<1iUHR$U6L+uGunR zz?N$^`K?L5#E$6SJ&695A?^~NR>$`Orc9m)-@25|6X9D4SX6kA=@a2QFJ&u5_$~t) zC#y0zV=7k1y8U^vT(Y{xV=jn|D9y_aT4&qkqiK4y+&1b#PrU;}=5YDpRKJI1!DLyF4& z@;neO$;&fPp7uyMjZI`%R%U1Qt8Ai3l~(K4Xk1#28c+aacqyvC7I^y)_@I9do$1K{ z5}kn~Gdvk&Zo>xy`U9`Fh81}jvE8D|FIG;Dhg`Yp!7#A=zc3JxtVPnOT}~B z7iIGk#O_dBG13+r>|LNPnOU@mt6W*XL|nRY#6&)O(eOyW%$&-~oXmc~MnH<)K769e z=N6+Gu0iCXsM(oJ^G<_7t*OZLa*3iAt!XIv0O!rDP%5qbj%FrfsaWJDgc)2)ucV(w zZ)VhonM8l&vjy=**Aur9Cy57%v&3`68<>y7q&7*KFzMy6eg|v7im^UH899!LHXFbl zkW^vzC+G6yWmbIZK7x4a9g}k=F6^T6`dBY%iS!t;$BUy$8L9W^ZtoFZ#-F-z80Ew# zb)s<{QcAiw=VTc|43tK2A%Edls1uh`;fo_dL1k0*eC{tV=u8WzwKgx4flZ8bS#zsi zpAni|SW1#vp-{U&m=+8M(){>>g8+I>^HDk(Q(iDBJyWl5YlUuL9TSO+v1}PJ+AOwa z&IGf=7P0yMZNQS9otKxBW!-w(BsPa<&kS3|=8+@8S%V*C>G$iatE&fON31rBg@$i) zjKylT<_=xl(xx+Hh9?x1GhAjUlnF8!E+^M&wH=RSi)gdeR##Q6_xVF1pI_gfyiI9W ztE_6ZRi(Bo?@rGgRNcRtqB83m8tO7B%I)c2Jt%XN)8%kFobDnc&+GL(Z_LQf%rGV2 zO&OWlZ`U=XXSP=N_j+ksL|%FD;FV+!ATw14U+$pMV_I^322}=~v$LtCrDsLD5s0t3( z@px2cRH#*1MqM?2s@5zvCdJ5EW1Lb2p-l^)}j9dl|)!=`?W14#vL){{h4k3e6r zPH5^<*BE>0@ti*5TPYw9xU&NpA}Z`m3w0Bo0GF)=x3Ib>Mfrfcn+W-QVM>-34!b|E zF4Kf3+z6p@+jaE$)ug=ZUTkT;WD+uS63^G`)4TbS=p$uf$ zt-73CbwH+L!JbVUmx#r{7ReHDGc@ z<@nk0`cah)pgw!|IH_gCo&_Ua@~c64t8XAlPVXeyPJ^;3ebMUxyuK*CNy<~5Nbs6Y zk^{ZX7W?os!vc=-DoJ)>n%2H(ksWA4McI<-3cG*Unc?{VmMO$C ziWYMcxg5PKlwvW1T>3ZUDxFA~3X&?73bj-zmQsv_lZe3FD`{53sAVc%trUwS5{<&F zvzT?fN`+h+3rUHk45L=b74mGOTB_FS&3Y87R&ye~TCX$lM!i}jW5h~reWAe?y=pK^ zGn`l^lZn+bv5e_)NmMc&_>4m?sYE7|DrFKe$5IR`PbQZr zN|SpLYwmUplnVdy`a+&qwD_IU+b+r~Bf?qeyDHbtOiC%3t7MVQ#1=EmGc~ zvx?E5RX3nt#AdRq^itGpo!(?BGTPO8iIfo)&uIeML&dGGu8cn{2JAz*Nl}-|q*Af) zNxn;f=FzN*nXW8}gjLJ5X5OGxp@JnErI|OUTqaJZP|1`^EoYL*R9XWLFssxkmQ1Nb zF0D+(N~M{u8I{?idvnIcp(j-$?wdkTMqfjnL=yWI!U}MNbKzm-y4Wc~Hz+Oza~X*B z9b))yslG$86!fg-;^dh5DFVLB#?ECUO?#R9ve@LaS6>ZYlvT%XfZr8VyLAdNE0T%z zn%o?tL969Na*@YCa1^RjODQTEfI;8DuaPH@&>mg=}^hEl!T)TSuv|p zNEH&92vKr0d}K;F8cHILp`no#Gite1DUpgrG$j+GF(pF-Tr8$&Ok>4F2^c`{rYS@l zuRt8>y~L{o1Q{R?)b`j?=rcTe>0|Hkz}hE0M^5A*W#uUgORk1LqprfS8TK+Nc_~%Y z{QJ;9AFSw~{I{XZ#lSz#+#sA=LH~%i%>YTHOh&+p#h1kFQ%RhkPax(#zpj_u;jJZrVdJEURQ$hU$4C_pu@gLvseHnAh6Om1f?eK{Q6H zH}Ou3PR^#8Mwb?dWqQ%h9U`+xR8TtFl*Xx4PK!-vK-5X9HJW_9!)i2Yl+k zDv8RV)2QV#kqAv;2Ax50p=O~O4^iU>*B^BjO~};iq+-q}lFHRuM0>Rcxl$rRE{#UZ ztHf$-8>+0i*mc0JWI39mXndO*OQSy)(cCF&4{;_!*>XvB}+K1K* z@OV7#fz|E9CXVe$y7bP*P+D4GaMR?;bLMo8Yimizu9k_D=gymG&o#>>Ido^kj4G)r2=u8%+4rFDZc}!y9^jt`$H-K`QQS0<-tz04U z`MkAtLxzr@JakY)f4|@wI&|{5VL6$zn#WC?GjH;kq0Qm+^t3@OlO`;jHF@;V)=+x7 zJi83rXW(Vhy~lxQ4*#C;gq|jM?xT ziPUSfC>5_|Y4w=%6NyzSy*3NYQECzTQ>%5M2_xGF4D|YZz5%tTCQTZF9bT`ezGlSm z&iPX(4rxR14GwFaGG)QMX%mnu6bcS&nKBj3j2BB~j~L88x5r{saR3yV@TRm0QCbde zdW2OM$H&pM%4qSpeWqb(%F}4|s3}@?vKENpMEI=LD8*ox-#1`jd;8Q09qj|^8vMS2 z1KQgsO>H0CR2%RQ42Omc>YTiI?$mMZZRr^qp~1+tU?Fl1$_NW`MhQ`j=D-fDgQ<@z~-$TDeQE-Gkod0MVNw@!ngK`Y>h0 zJo+kXuW;hWjbw6EAK-H_edaMn&7iK71DCH4D)`hs)Sq~toBRMYbu9o*3~R8O%gin{ z>jgFN0TTWI@20lGyBS9Cw;C8fd=T^};VgO(IpLE}5cQpz>XXQUS+Mp04)@f(BKDl-f>zNem>;5pNS;B=`I=JC|E@QBFz{7rbg4 zyNHrK-e^{J2UY!1I?~_w@GEy8tigK zP*Gg!Kyv^RsAvfd7`wrhVUz+f$pI7(P-+Uma+-4l0cli{TFPmqX&|!Eny^mfQTR#? zn0ez^qg2^AyRm^%(X>WMQ~uE*)?-wm`Hr%e za;+jLqDT=-iSYeyqk%*U0Ld{x3`jU!Vav`?P(UFPQ>27u+Na3KDu+xg=O_s)9#78B zNMp?PcCml*KwFL-@%*$z-*KSPu2w|6X8Fu4Ml5!_jM;kS(z>5{x5id$_e?U*P|nXS z-J`UGR4}xh3k{Qtw3<>G;uG`~Es0asiZsn#BJrBN*@28`JUhLv zD8mONiV(bA?ePV(B@%_46REWvJyNL(L^C;sSfo^l>A_e(C4<;Q-%531&19lpxPyHq zqP*MD2sa3wiSMGqn1h*HB}gt{#d@d36jRFyeIF5yqefYQBx{q&lmhm~e3;qAtFb*3 zCH_qv=ucq{D}?EVO9#+UR)Qp{MowJp5v@`xBj>vsJUYwtC|^@#E`N9gBgxfiDu-oc zn@qlp8P1SJFWz{i(;A>}Dhr=zOdK=nS?XJ}%useXU{tsqR`LeF`p(v(j8dt&ctnQU zsA!F5#H`gWw|AVwtBHACbKK#?%|(*=<;`w`Lv_K^j{z%5tHEH9eITKvY^eXBGjhaN zAF47AD|czdz9rtEMt^XOUO#g6?x_vt+sw^6DUj$TxA~j0(yiqtwo5j9^nzm2j+h&% z6<8y7r&uJW%~cHphco)t3GMZO97irFLSnNv#mq`~blTLe+WcMUKPFzrcDd1R?gqdJ)n1Lfk zfLj%^#Ft2PlS>izi`ObdGQ{Y~Wt>!mcs!BFHyOMt7G(k;WhHVE%{{Iu3TGH}*#NPV zQ2IUyEeFiD0I?NNHY$~_{AA-g{9*RS8QW#mY36b?z; zvg}LnmBy6#2RXz8E#Q;H0u-H*E94AIqLi%g%8)w>NV`b`o>LB;8ike$6YC)3X`}+=sZRwM8U#0D-t?Z zt^`L==Zj$`Jp}oJY@Hz^T&R7VqeXH_;uh(mrP4)r-uM>D>`8o*`0Y$5cuj)PY8Jx6 zjuGGx!otrH4kFnBfg0nTOrj8QlEW_XyWnUHA#GA;qzI(bd#RCx2jADJ$qN{KjNXSA zxKcb~ui#n=;yyj&U~Q7}S&GS*Q3$`JC`DOKcm1(Wqp zwegPxd4UloKL<}j8kRqwmi9b21G-=_BbO=_ZiP}RM>u)W0e;~v{}@R&o^GN>{=;Ha z$Ydoz3Uy$29;>5X)yU=N{B83M8r zT;D=Cx5kYM`T3Rhwpj*=F7e_t-}-R2F1M^?2)P3nGG%`SN9vTu#L_4F@zSLS7o=MQ zLK&-xIdn5!Mo6)p4^E7gX0W~t`3{&j4{nFs=Ye^`7nnbf90s?|#m>24z7PuL%@y(} zCmyC-=$9|ggNg#{*YIQb$=ARNKmHn6kdu50J1xQ&uzU?aL4HCWYrDUq8|g;{8!Q;@ zE)sJ?(vrx<5z0~*DZ3_qaV+;pvgnt3RwP#_Q1|KOnj<$<&X<_Xl-eNHtH*Y3yVqQ5 zqtnE+;kF0HyEvs%F4J;S1#cFGYvu3OZVKS6WS5!PSDpg=|oFUJ9>xW=`fX>iEW~&o(GEYL%Q+s|+Tm zMI=(`=iV`Gs8*-Y@*yD6Dg3e#>z@0YgbA6o5x^iatMMq#z;Ex_p)`beC8@MW^eVB@ z*mnCT3k{^pB9odONG|CBvzLFk-`kxo< zCm{)>=ihhn)kR_TGi&fLJK;BQD_8(D zU?HNB1q4g)qbH#>O5yzA#hOK;9`Y=B1BUK}>EQKy?>Tvr+;uMufj902ZzL9-L}{~; z@N*MA7qwiOEU|AZ!7CsOz5=qrjc^Qn8IA!rf*f!Y$O65N8*!blB`7+Lu_x<%v2^lz zFbdxMD!dttdX+l!YQjK%`6?KN%3MJJdJtnpC0dfUHBeCjHNM47?c%X5WSj}Uw~ne` zyB7WiA6~n59b%2D*536v{0*>=1CG|Og%2n0Sqq+93#tIO?r(sFzdfF~hirHpwPY7T z(-rjD-ad@FurYo$&NCofIe?x>)I|yQ`PG8)KZ=D<{qz$k`suEpeu4$)?dfel;rF|! z>puDjKA(7x^nhputP@`D{}>*)2fy9(vCwDPsQow53x#pgyD)`{=v{v8UA00raSLpU z?c%Bis!=L99rP}D>0S8J1bncb%o>tY&@^t0qZ>}F{ zvBzTli`%;P4lb_CjoWOaE{lNWj~arcx6t1pxT=vf&l6@u&7A^-wJu8Qk_sE2Jjc7@ zNP>tsK%C+tjE6@KZQMh4o&wWPor1g3v**+)FfDuIMj+p~apTatwhu#pcf%*{8v3#D zMt_4w$~pLyFjk5{Vapd^e)+{0`&#zxgXi|Q?E7N>eo(Xz!QFxA>`8j1a5H?*l68vG zCgGb}<-p`9y?5&@MQ%%kuEIen?kPg{D|DrWIznl#LgV%k(e`>T`m1k`j@WMevjDQ= zPh*<4ci;e@4+nH?H}wW2=R<4vxAcAVW@4?t_hGdaL4mKAV@c|`;D3BFRxlGHn4Ik8 zWqM3a;%oMLV)Z7{_02AsyAZ24k-KkpD0k8)<8B5brNLC{ahDm53b|ZiG?uwNr6#kK zBX345ph~86@+Py{WU||9>~<4=wOBP`6_OurCON73_el*(5fGA!HCD@INqMJIrUJjB zY*kJJ3Nah)j{bIs5r>&=Y6;3#gt8TCJGb7Z8L^F;dEb`#imvw z7pG&DPK7e!3Y#Qig~;yrhcY|?n^mJyX{@$@CnMzd+eHeo#Nqd5D|KeET+7*2IHe`c zJJg%ZMrG%;axwDG_6F=Y8(V#P*z32Mb!s)r#qSMgx&1bgf>xqj$Z-*OnprAVaJGg} z*ypzy4Jwt^V)OgLneKp%Q_w2A&zG&#n^2WSHWm7_Sy5S@G;6Xfkya)_W#uKS%%Liy z!U8r6uCm1z@P^Y-mAPboHv+@Zu17QuIaLO)1v0@*1Z zr3dPlcA^6Gc9K4l0`~7a`j58{u=1fHHEb^HDtrs@zfJV}?*BvG44gXZ`SV5XKJLCa z^5@$gk!bJc2e>R!pG0IQuhA=%c*R>OQfdvnMyC{94!n1x(JG~)e;{cB2|h}tPHQk| zaj;m-a>%7OskJHv7G)G_jn1G)VH}Gh$_-ldpNuF%Ldb`lRBq7lhMugI3cZ@w>6PMS z1chFcA=Cjo#7Yg%t9xps)M*U*pi;_xD3_=?c`8nKxy^;6dr3^uW;ODV_7@cTQ;@8bHoLgC|TO)52+kTRSISv7mF@u+}j8Yi%Dp zW&WZ`lLrk>3nO08*ZnDd2R$E^Q-(`QVQ~+__6&m5pm6<%nw+n%uE>wsELL-2UR6~? zLseB?q1kG&#qukv;g|EL3L7=)!C@^^I~OkOoZ2!hm>vqZ4Vf^N%&=PHv8sMe4b|m^ zF`Lz9ixrmjuW#ztFBZ4jlG`hbh3%DaMmVE&__(PH7f zXnhvIP+A|O1(XX=Vn6{`8kqn53t;|FW_T?;Xa)l|!dftX6PN%dZUWaM=CokYKd5p1gjq9sT@4c^(AjX~7jV-TUw|vV0Lw$cmZovz=1!kD zvaLBSlyuFSg><#Kffl&PeWTNYZnql!x!u9E zzK-@y;558$69&>IcpW%Ro>pre-e4#zGZgeVwQ9B2=?R81vqC|yLkl)u1|*8`bbmn~ zr;8Dc0{8^L#hxJk{dQw-KY73vFTMn>_?H>(gZs_EHa0EjNmkAiOzZ1t-wdn31vnfq@B+9E zFoN9K7l-f~2_ND302dELv={sOA`CmL-#O9m`h?*p>QK#IR)@V-fx!H|-? zy84yX=mVy}b7$eXC!PR>XTdAKgI!5?7rmRd{=R$*a4{H$K3AMW%zc~>#8LT{wkmUV zmAR_TycQgWN7ur`@W@(t6dYdD*iF3L{PJI#U+yNzx|ZDLoSf!d(gSDwiax)BtAD-Y zhrK`SMIVAiZT=axxeQ?vgQN>7p&*O|kpZGUCJv~8&&8=JL^yjI4MqYfYzDGhQA-bj z6R4>ZCtlXrxo7X(b~XmD1O>5e+rT+^ZW}ogj=FRx31=GB^er?)$OS92j5Z4}0n|P% zuXXv507J#`Vl#a+d~)&Jf5LyvT@0TDn-s!O9S@23%p0F zu(K6!vU4H(?bTs(=Vfpmb?sV>A8Kp)`O+U zYcP&V2=dUE0u28!zcs+o3H0!vo$$jotKo;8@Si~62^{o>q}Q5@UTbhvLg?%FP+xZn z*s6_FK28pJpEe)`oR*1afB-}BWaqHwqd;;m0I(bNbM*OPLtco%pYG{K$?pNu*bDSz z*nJNU7%~(E{Cp4W2H+kbiM=p%2u^rUa_xmgcspOX1q&gn7LQ)e$1^Uyi$T9!K+91G znJM%eh%<<&L|tgu1n>|ii#pb{t^T&+JSgPmul=t48~BU|#8DoD;L|A0x8>ii9=y6^Ezadz z6dBhw2jTyX^ykD4f3#j9=;vKz<$Dy5@PBf_SXeaA{k<`OEUZ=VyTuJW!S!VcqA61X z_$Ku-!HzcGY{LJ2Lz8+0m~SX6^@cOYXNJ9{a+6LpGU|-yq-)fLCKWBMjg&HsNIb1o zLeY{z)5Ic%DUH-hX_cu^tx3;`JLAJ;2A#YogEEfewX)&y-{&yBRYFse)<4LhV3^pz zbL77yQ^pmPw+7PE0r*Scx@pa zV|5l!&g1kPBkvrKk_XWrN&8oC26_agCD?;h5=|cKx z*^Ew1A&L_3{)Rq4zm4X^2mS+(ll5QrX*#&1OH<03|Jxo#$@_L_O0V_z{kg;=zqmgn z@9U^7K^--=r>93m9r0|`PX(x-Wc?#060vAni-e}dgQki_l9EV&8S141)JxfMN4&kK zpKi|Gr7iuFd8ykFRqQmEC6i(6DZu2Mk_+p2R)nW|L7N*&X0q+ULM`qF9a-Cz;lUP%QZcZwK`GIDN2oMe`PIQ_sj@bf zQQdz)MMkt%S(Kkv70=YFM|kvNRejMwh0<;r99F49gRMAa(LlAt;2ELTX2$ymaLQ;# z)%NO)Sgo=+9_p8$rBRLW>LtpCLX^;H8JrGZD~y?pB2h+e4ogebd18s#Td22#oyB&2 zk=HB{<;!LI(C2J}QR>XB4k1k#jEP}s?%}C%06?z<*o+2Y{_qWb)iB$c@ z4`>*iR#p~nZ5S}VpGxGIHOS{+%mtoIho>kFiAiR$$V38XT9L<*;Vm>V_CU)_l&)%g zUBlo|Sy^asL*4i)mB@+G*%@PzC)4gN3^@U5nxvqB)#A{pEE=1N(mJ!Mii)bToLWj{ z(^ynGhsBzdbG-;@?xd$6db|BU$&`Px^!A7HaDe?o`S=gk;{JSHjl6MIc6K05tJ7)I z0@>Mp9V4@C>1m;KpU0_DsgxdDx-Z+H_nAG2jAnYRw7Z= zEtU4TPzCK?Z!j~40ZBZL+I>k1@$3cJbdSjtlCizeBC8k_om#DOJJJK$S!sT+MN6x6cAqaTGdGa#@G3MKc}OA+F}Fj{Nz`qQ$qQ93u8q;>Xy$3pJVQB=K8Wi=c1S}8u`pf{SWDqlTCCB9;$ zMj!8K&{|A3tEnekYX%S3-sL0V^7NOFh)Z_!E+2)L>&5r*k6h1Y zmEc|0>z~>pOf?1cFt4e-$K=RS_Ik&AHmQ<%Qi3I$i|$k@crf)qDw!-fnm}?m_JWhs z_3)~F>(*Ne{cmRiEiU7Ci+jn2{XPZtrv&7Ws1w*qlXuBEPAV29kM)SeVlgMbi=?l& zsPsX#Qo?Z(rCO)ct1RR=lD^iW;B~ql?;x+RTuYO8$Qe1;lYv+y6*Ka#7p-!+TxK#k z93Gb&VYA6(chorW=BVA~c6l5QlR+t$OYI@M&1{jPxF)^Z8L&xv5_z1LByw0?Znx86 zGRaU>OTdW|$q*xLGTZE+T`8Y|WGsnTigzS9ngW2PI9j?zD%x(As5vnZacWi2VASeV zQUzEnS88xPQub6U@o&*cmvkjH}DoqUk9mH>2YL{ zNTQX9M7TnFwJKeN@{kp~Yk$ z;Ik5r7Qw3(7;jh!&a)5RNVZBvJ4{lgm{SS|RuF!mlE7lAc&kaG>f@`DC{tJ??wbXT zvbaSi!&Kkluv&OMLR6Waw_q2V6J+pe2B0A)Lb7A>kXUNS0p@zE(xB6-l~|ursn+TY zN-H@IFb8aC%=Pi+6}AHmxI@lLMJNl3MwOPJiIkNmZSncKKcMfRry?G+m>5A!|BrJ0 zpX{-uNQL%4Y{Br9Pb&wMuo;m7v<$hoBM@*o@kX}O6$o_rgHFtnsa(!rTVeLw+t*@6c1Wd1}r}g!b0wcL{aGCJu4w@Vpn-%GUOm?Nbu3(@-tn;+1)S0n<{=8yE zel6yRc~D5HOl!3`6pFh10V=WH-LBSTM63Lf zVkJ(w3Ca2W6@{^2MJ!XTYWL{Gih%`nawIUehE}3(qh#}&fogEf&Mq`v316KR^qMC38d|zUvfH$)&;EMRmEsQJF zeuY=8shiQ!yGgtU?-GQ=94@&n2T;Vqq*M!T#=Et2H+Te){fIpx& zN{`-v{Bf;aZE)M|fPVLJolT?1uXz2%Ns#mjW~gv8Lds5IG@|FD$=^87>Ep>?o(ph% z@>lPP2K32alp@L{e^Ck&ynHxs{*k;Ro%nb1{Jg_2cOn=5{j&h_&J~kJ_wO7tWygyv z;iSP0Qr&mW50SM=dG{5dNbz$ zPe8E0jj!ck3wt)K0=xz9xEn~OP_x!pEo?qU!eAA|-gO|f^ zH~;Hjn}K@y;H8^3Ay1&%wMC;oPGZO(u>El<4l_7g30>v9I({092P0dL(rAg31nzWwGCt#b$F)ZP3J z3ZNfrtK2^4*A@R*7ivqd+&+8RiaFaW(%aJ4ez@$HIom7SS}V8Bxv=cRwdrl4iXC&7 zFGGImZE0&iT+uaqdu7i)%Qy55^jpNnl&zH>T7vC`{Q(8SOQ^yH&^iSWY^@?H5alk9 zl41_y0l_o#G84Ug($rWic^P!lQf0gkg`zhb3YRas$g1pU|7hhZz>;(*_%!uz?r8} z*M)t_GQ_eub7W%lf-(&G{pdyS_k}g;xgW72!@yxEA^I|i*pKF_H7F~6GCW;~nM#Xd z^akLBj2I`>8`5z~F_TQ` zq*49)jjBw10DR@}9q=IVl*9Kvg71_AU#bcpqjY)tzUlONRt?V#lOOJ0>PR_^3k2`Xk^)Ux_a4T=%;Sy6*d32H=JN zqAp3hB7FCk^n>(vLWZcLpNJ6UL<7-Ij3s7Z8)JB5#}^gu<70%oU>QAwF%MH7B^fBg zwlIZDeMnv~3Pa%q1(M6ce%PHw#)ad<7`iq>~I$ zC==Ou{e{uk1ybBx~U?0UKP-EK5E9R}uHtc%rABYB5YpL~abGTz{C z@EeZw8{MzpXjRHZ7CU)Epx$rb9S-DEA29IX34_Znh!tLx?7 zcPI5euXk|pEGXsdhQv=e_o_s(0r`Pacoz8y^x5701$`H7!5nz%W?f1f>vQyx@%7Q* z_A!RY#d9;1w$J96mSTIk#@x7%>7&)n^enev6M?)oxe!Qpx;z%T=nd2@{v4wrAkv_r z*{Ky5m^~g#K4XQ~fiyh`7>qftut@%D5pD5Q-~_MAMacv}57OXuRwm!#@t6z5TF?pK z(TH#YOD?H=11F%(PGcUUhxY-M4)_fEOuvhjosChvv&3nlV^6Al?o7SG$EkrF-lu0G zCa2RB5$iz>{6Wp(_)(4O$rx=y(RnI%R>lhP6+FTEo;I;#>9bVY^4|q1I`&HfjIK7P)6BO2B z@TpyD9v|C?s9m(8YqqSKCaW*NGHO@X>;nASEu<+y!q;wk$i*~1e9j~4Qq#Jw@zk3a z&R5f_Lh4}G1X+Jt)&IhIoF>2fG`*iTp)}%T8cyxvQ7Oi*jzZeh|3X(Gb!*p%BHGk( zp^NA}&obv?e8#1YqY~_0jnvl{-W*Bmim8)bjYV`?&4sU#ESQe?v)kzTf?ZwV{ESwt z2m=bxunWurG}aqRJc)jh8~F&oWC8XSTqK0>0$GGLxscCQ$ygY-NlUkkJjEQuHpHe4g3=>s)pR3TuJSQ>&P1y2q+SO64?p0%U!$HRA@g)94(Ew`z+XYy`YHWZ zFz4Vm-+oJUcLRcYnR$m5Ns!R zkEEwEtBEEwj}X6?in+_yMUyhLIyo>AL5#-rE_?^=AB)LYg9$uf(qmgZA`!N*qu28) zrCh;sB9UAr*P8Qki+mY6!*BP_9P`)Xzs&{uxwqIoxv`4!!XfcOZ<I%@ZafZblRNetc;uGg^Aoym9#YkkSKzSg z^uACyJFhI5mf_)bzkyGo8MnK;`)%q~`dKuGMlWl3pZaV5t&Sntxn{iE>rkp@UO9F8 zj+rW@!yc@kG%=L!^rD?~hY#x)`n>7%vo5K}5eSARv`#&IcpI6F5SLN1|?9!2xMmVOP%8vT+diZ5T${QdR|`5$UN{;gzv zeTesS*i|aE%I@&{hx&qc+@81g{%I@7@C|FLrY5VdQmO3rpg$b;2kj^imD+}zH?7~= zZUQyJ9}4H>phkGK8jaTDOS=3*lh8boNlc+{p_SN5q|fjB&n=?K&QAEmZoNJf%*$Pn zo0k?eAf7dtCOCp2y?!@*V#?X4M(ipnh=)Tao;Rk43S#Buv4Rj@ZZU++Ju7@B}Lg8W|PU7m040)RaID$nPoJY%o*85 zB^B3?dyU+31>Akq$me918&TZsqWtR0!lJBfqvZP(oN*FlwK^45p)i>o3okHMxg>tv(qM-L8` zxIAU0!8CbJ{}Q)P?N*yI^W5tBjbo$KHorH|Wl_ouS=P+C#pSWe-1?KFvrAh%)9O|( zTmKSp&s`GtZ%r#p3)>yMR>k{tC8GwG*faZ?%(=1tLnKL) zazKQ>kvfN{cVp6G6y8h(&gAJ+4r^WD7NS<6=6j;TDXCP4MUp@iwk4B|*P^INP+&lE zEQm&YQA2rd3><*3j0uFDPO_x2RUh-X*o8w?HixOTG*51`<`y=I=SS%rw>#66;~#c+ zrmnR~EUt(?vy*&8YENr3X63*`FXhL=yc+bc7$ht77=tBS3+Gp4lS+kBswfy_v^uJs zI+ZF=;fXqo@Xh5pMy0}#Q@OpV0OR2K?rW(JnKfu`Cz#9eP45;CxAYzyq&~c6%i7s9 z^7Hfa=1kwX<(l@k#*Hqg)77uMwRz;k!r1KT8#nCRzj@XC83l!bSnlg9R_@uga>dk1 z@py8q^_1l%2tGS{aUm3+Bk>@QOG(A~k0 zlcug%xogkL6|d*U{e=ZH=C9ncf8Y8|(`Uu;Avgdgb#J7mF|CN7MmU8++;>A}iVOk!7SHsP4=Yx-dIj8OevmX=c31*_S;~B4@ubAyJXoMQMP+e6d zmQSl|M?(<-cou#_iI|1>))E(9azb(+ zS@q=5&p#jffG?w)9Y3@t^8p7D&Dwi+XpL~P}_cmcT;aMQ-~mHTPkBbczcV&f|3rO zuT2$(MX=wZGyC-)GT7_sH#2(ZY-MFAZFW}HthUO^vxi=2UiFV1t4)TAik%;>ZeCMW z`RqFz^P+2}Y+Y*nYb&H)U5(y@D>chUsff)BES9q%$PA}z8C6T2h!+G zbP17**8$Lw!6eh&OH#^!%Z*2RUc8iyxOxdqslfCA1HFk8%iv#S8g;-WS8yCBl5b6n z(Yh=mmK9lCTJpxNauM=Y$Xx-oMh3zP@|<6#k)tFcYq@M--9@OmV7lISOh@fwqHTtO6z*!MNzyVU2joA z&;ait=N|qIo`fgyeoqW6psy7y3}PN%gHLIzBUI|aXWmgt@Ws9No*zDZZ$<|BEqo2Z zybj(^2JyAf7oU^xG`t_>HwYX=^^+o)%Lo;LhjkQB#;B%LpNy&gYwx{xE&Qn9*s+fX z58e?9QAfu8ZRDuGjRVKv;ERvY-gOA?eoXP~LOU+DHxpQo2<;__F<=Km_h`UboNb75}kOas`4U|B*S30|x2nRIZKqpsA{ z6jR78W~b9jc48PN_IaI7vqi2TUk9D&)nZc0_rUw%{d?p}lf~&w=D8K+SuEt)Gq0tx zOzq44S)M=qL5^O5jx`}}Z4LeR9+)B=A}3-Ub!@(a)PS=<2DMPz)25lIe0;(k_asB( zo+SS<9i!3oL>skv(Wm3bf4T_VieWktOrxjME)-WOSQbFtg(ii7UJUduJvkb(;J1^Y z10Gt8x8RU#+7U3}2s{K2{o@F51NV{dg*>w8=>nbk_jxFVJUEc`2YEz^`{{#JR}!Bs zz!i^Z^}rL2yL=p=I2RXtksLg}W`E+>smerxJT(qHw`5%6=r-^z&g$x&@bnJL(>=N2 zc8w+8pl4IZlKE+)E_`3Hp7I1-z{R`xxNj_YS2-Shu%n_Q@fLV8@z!cGID8HqPF}Z^ zUkX273ZJ|RP_JHf;R4QUIq?qNMmG==eDcK?K(qig5Z_xQv`|f6T?FS01kbgCnFHZf zV?i!_3C7-8v=@A{2wt@pNzrwSKrYB#1h=5P+K4sua=J8`7n-Iy)JQDR^9X7vJ96)E zu&o8o9}ZP5;O=aw0_Q=^N+;Xw;%Hs|_S8 zj#0EK6q8DKXIe)zQLqWy~GU^_Y0~Vs_uYr{VxwC>nFf1jY!ak z>71TC8HefJ6O;B^|6ATFK5Cz2u@Guyb^(nmllccSeLEsfc zcc-Q3crO)?GN@H?)JAIi%r$Ffb`yw9AKd|m?AU>R$OlhssHxd-BEN9QGdp)C^I1Tw zrbh^O*Cp#0z#<2(V}J{w9s-mHM5whp3ZkeY%nnq)H$XeQJ?m4@{wej?PS(9(U9#F& zfMK7aD(bQShlE1@; zk_7#BxXos9yF4zt8UCVkHkY38R*-# zEwsv{@U+8XHRxqB7?mr{Mz7Q7b9#+tr5rpjlj#jsiv!e3W!8n{E8-uhT! zVVzU+v&H0aIGi>f-fr>u1D=4}W|QNzV3ujCLWqukh339=!Cq9) zRWp~a!gzbvI1q=|Ya{g%NwCLggqNaD|NUqOHaDj2W8F4UE0yaE7ITROh{)}Uu|Hc% z%npq~N}j#U0Ipm%{22U}r0YtCoi!-2^=64uY0w!BI)hR*r_^lMqHdB-2!_T>qzbLk z^tf25(qp5wdSx;nneptf0RnBbp?URQ>Tbe}sfae#R}llX;-cY;UX{qy9V__V7B!kx zPN&D89?D5uhmS|E%V2A($c)1B+mN5qx3QAHhh;op<@M$=sh-3%6c?C1T*nT zrN<=MMa(gYgY&Y0KV?6{)oT*gAQ)Qj5txO2ot}kVbia z!m=zwQ*|^&a|{a=tW?5~BPnVmiQ};>_?~4r6j(>m$c3VFEX|M_7wrnxV!bp%(!r z@fnBUMJ*u76)AX;W=??D6bgY?h|US{s_B6jOM_~LB2Ow%bK$!f3aIH)RO6E@>Hv=J zf!Pxxst0CYBAETw7iO>Zzzo%h;nh2`%A3BRjb=<%y@3 zpRxenjshO+M1o7t7B_mufTVAjTsAe{Dk@oQi^Xhuf2Bpg- z5_$R{B$G~X@)`v>I=^J%V)fPqmVn>7V2gVG)MB_G9Lme9nK;o#ZnW7ZPOOPUL+Qf$ zKAKwS#SE=tMf(LlIUk;+4zPa0gd8Cd@KSz4ST)4@w|X6c+GmKxsRQE9IIJZBm_bvc z3NtoEUVk6n&B=hZwOR*HN(X_~jrUMbt|ySIC%H_uSYgz6po^3FawaVHr@$O?j(V}_T8P-y*Ir8 zz*{++n_9Z0NX8i?73N;(p+~R_&>M?)e8j?H2@(^2gfb`xKfrzDEASdHC6UE0xbV(} z*XRr?Cn4(EfzO(NH26Jrgw-YYql6RMf}t?I3v7P|{*_#H{(NE;bN8>evBM`!`1Q64 zn5KasN^`h34T`PB%&poJrK+BJWo*a%EV z;b-WJT!Z(>x@P}A9$u892Efmb0u%Zo*L2OMc2TK$t+&mDnCfY3Py0~#Fk%k9n7&%L zV+ge>W#%kt>I}KbcMt#c)8Wq#|M=r!@=fqCtU3y-@DF(SDE>)~`JOy1Sk8-F{J)r& zkl%BMZ$|&~<_SM@liBq=M=!pjtP$?*C63cYbeoFBHx^-B1mB@D)~WoWBD~WiI)LEo z6>xMzAO8UI{~ma8c()o3MRjWf>*?jx4?VIS;)20e^817WJ`3UqWFH^FtTcjW4sknm zBmIgH4;y_$;=(WRBOIDf?H2^>eE7`o{4i4Uj`>1fZo zOaRIIQxji4OB${Kr^z1^|9qCzUjb`U>!`#BbpM{X9N^S0GMh9!oA`1OI88m0j0+z4 zgSe>bY8S=yig{T) zUouO&{jzAkizjB#(0Lw46W5dD$nlBm27u?lb1+7ZOI)A0{`ci;fm%#m51#9ZPU>Kc z+Wl|h>M~c|Kq{DBV+ z4R3$`y(@QIv&+u>@cyg2AJXgM@!Mf1SbWpS#IzNqr3a@@VO5E5)@)e48N+jG_eXRq za~{z>eD|zCl~c^UT18;KlTal$rqwE8j-w8oJ{=i6Wafvf*8uwOvxl@LUT>)1v%9gO zp>g+~dZuFcZ|RRuFDQ8V6)+u41_v_2a8=^awFeIF2bmyq|FsA37#jkIp!xK5ymo~N zJGL%~I$kZTMMs6bHR@6L^M3f#gFpdDKm%p_@Ix=&KRhGM1iHSaw7F&y^jA)jU0tor>u@Pp zPyDX^K4B_LG2E#A7z{+R-K;tZ2jK2)KkUNoC)4}1|Ek^0>&fQB-Ecpglo1B2$PV0m z_!@jgXg+E`0z6%d>WW8mL@?ax+59{rhO*~TyAB>r6reaypg3lFjIgJm7A$ePb%M$~eCNIVr_O)GCUp7%`-w zp(eCt(aM#pAHV_2`wxh}97^+zqe6tx?#rx1jj)fsYQ zd4yA=BAuiPsGMqDuPSPcymP~-5gW(AdEnJweuf!8lU<3YS%YiD`i&iSJqyl^+SD;} zJ!OWkCZ50x)MN?#2e=zHm&XI{k)!S2sGz?AKJ8YM|D-xK9Emu+!~}t_5RnI|XPM+$ zs5XMJiR^rD9sK%Q`1LyS0{KbT!&H?pw?GxW6X6dc>Oe2tT`AlYhmA&Z_=J@(Y%{4W zfVT*GAd{E8u_Bu1MbM#s9Pz-Yowv={GxgOo>!#kn=E1#2#PpADo|N&vuG%(f*1Q)x z_a9ww<@8rZjso%zhCIsL{9;k@`Z?n}J;t0@?|XgraLwjhk5U?URrXhgIIGKgv#x6M z(%B20rtDFpZ+zyvKyqF?i0XM2!Z|ZRM51`*Uk`9Ksbu{~R3Fbl@|T2zdbaDwNn`(- zQQ6WIY?U2GfH`5rH`)a8YGf= zsva(|TE~pJslK9e#E{Ci60!)w-yQ|WGm66Doc6e*hv%U*eRv^&c^&XFRY)yDI4RsK ziJ33(GB|wxG^^X0xDWU3a1>6a!tu(eha7Mo96rsg-ch{Hvu<>qi`}A4lpAdp-4FF{Au|8PI4gT(NHYv7v{W*rJDu*H;mkem|@BJ z8=#3rFb@Wb|At;UO0LbKCr2$A^$O6sv-X|UaBGgFHH9^leW#Cxk~*F*bqka1{8$rvDfxvF|^}>6&m!98?#dV7?jL3%*Ni zOjZ?zw;>v|jQLpLDZUC(^{Uca@8!Q`>E{e-ytP~5)@aXokw zI--vA6#U+m=2BWwn86*#qhf!QAnX_Q%nezn5;Hp)tWRnzBXa`jV zuYBei;&*YeFyv9kBRqLH8JB6@(e*Hxh2nO1lR=c=Fjb}Eq`P|QXa#EH{mftSTCpqY zBvX&pz!|g}B+@O@!F6Dn9nL136yoEjS;;MA;1=-I&2ZZ%<7Z%lZ-U+e%Hw)87ydpE zUIT6fZ8~@dXtTpRNU=h+ZYL|*50>o*=6&$<>l@l1hNlJk_fPOV^&_Iw{||Bh0bfP& z^?}3N_ckE(PC{=XBzs#f{U*5!fzU#zf)J8G0%@kuL7H?$q=PQGrwT2eYta>RbQ#WzEjR+9QLirXs~Z8u6dW6 zG#Ox@1cBeu92*?YEo_y@^vv=kzHSTO3mGsXN|xou3808gBK+JQ{fHBCo>x_HWdZwLd~aZg6)Tb zYxxZJ{$`lCOE`%#B3JD&&n=KRNsz*>-i+bGetR*Rz0rAc4=P*}+M4f88h%iMe65-y zj$*#dddTfk!r8BzaB>ZE?rh<%+BCv=yQsGL4e2$T8va<#8ct!?14G}wvF(K}!EbK4 z+XUa^KmPmglG@$-46iY5#=5I#g?T4#)#c|re*4!=o96an?*yd;Pf9DnUnOJZz*hOj zdK`?U@Erf=xp})j2wKj`*Zy%zm;SyMtii`gm;Q00-jv{H(u3#=wavW&V-;WCEHzoP zh;J=fwYNfJ2#4-`5=`P7g&IQ|wF7MdS~Vc^UhrUi=3%^m(UiUB$-ZZueaSkX+$DY8 z&XpJVmoHoh`Yy=r2j|D=8;=;B}V^H*>5H4%?M^R-{h(E?=JUmH?K^#S zGx$RoE)CDVXu}G%G+#++Oy4$dEXyE(_;5+d#Di(Qh2OVH) zpUvXs+wH~6OZ$}UVdEymUrjEqThlPLnpoL($RaM`)>_Uwc&VmU6%@{DR~4>jl|a=> zfm)0$##I?p!E%laHW)uOD{v!uOM=(Zdh^YL*G*n({B={F3T7S+ae{sw2s)&FLjAB7 zj!z7~#PPn+s8pf!FNFq3ziOuQw~h4Dn?Z+gTo@A8!u}PNcZAYW-bnwtV*0=6zsH}r zFa7uUNg+C7g9`ND-=hyPU%f)pLn8z ze!OB!O8-(kSFRs{7uy+h(D{x_lPc&ZO#IADm%fy8D(I(*_)dtvRIeic;@l8@q_;%M zEOBm_V&Ir`#BgbH1^$p7FH0f%NFNcbj`TyNTcss(0qEagxL1TCChxe?Z78pR|0}{=aRTVSTSmXD zQrSr7Bc&NgzZObI`7oBgN}P%Gw^_PLe?}So>%s!*Mj3sZp&wz1RCFKu*ZD|!(mnJe zSo#`iQHVY_1nvHuI3}!xG=kb?Dz}%?|1#1Y4Jo}nH=Xs9F4AzZJ?Om8r;k`tNZ+m4@Ai|M&hY{p*5uU;SJM{Ri)&f1SI1U;5W8(l5Ojv`DFv7xYu9 z|GX(|NBSsZJW2_y{|pxnqI~PJ@@J*BM!)3;-r0q9ODan@%g<%~`I|e-L*+SJ=`->O zr3T6wn{0gP96Z;9-PJv#Kty`L;0o4in=mMCdd3n(T9BKD43LQvAJcbpM%Y zZ{%kO4|Of^U+9~(`F)S8^`S1+q6P_-gPD3YKD|||7Hv8=?NZ~A)+(`c`-suJebMj- z7fkBWU|c6(lbAR@a!m7-@VZ5H9ULAwV`s`Qid2pF5 zX=-=qY6H{N2f}WyGRiTT)Sl4Q2SN&0Eljb$S608R>O=a6+)~s~?C+P;rSx?y{W_!X z3BDjbD(nN^w@g>ppwq7e2m9@+&_-Lirs&0CCwHgS~S-Yox>n`y=?VFX- zb$y4%86{PlHVJP!$o1gh%1ZE$qD~#VPU5TWd2G*P2jlD1a6a?k#F7infhn=wN}``L zeJ!r^gtT1z5^c7Lt=sWW`bGQ_e0aD7wpwb;ew2u<*~{3W50-1UXz6AwHK%WQ2)$0< zJoK`-$M`T)dVF+n!O5O;wk}JU5LQyTQM*>rV>{HY)-JktWdEz5|JA+DolDJ{w5(FA zgTHnywI<)aQmwk~1}$e*l4Yfav!ul3_wG3HpqpKPu)g@>$B z9piNoh$uXm^iJ@3zRu>z=n^e*3*RQV@$C?aaWRo4M&GC#{8hRvHbCDfVtsj9@F&m| zpv&=OXReC1F^?N|a(?hC`u10$bT+>m>C0LA*KCcEARQH#C~H7(Lis#_=N85@Qpa;# zg>rY0V!Ri|i%pDj{CGotzI?|U(unWJM5gtc{n+rqC47<>Tn``oXj`HYtR*ffy#*SR z%4y1m4VzqHj@kw6@eF%%8TJvvo>GCwJ7wjjgvtePfd0EknMyL>kiO(f%F0cpa?#QS zag*{JQl?d)_gh)HX;f~I^r<*SRgf~hyd0ie7|#`Sv!5F%wG%%=N`Lljbm}+NIVd-n z`3hLg@n_9+*qu4B(JTdRW@Y6MpuElED=YtS=`B|N3!^;JTS^aeEz8SuNw7;!=>?Q8 zG|O|Nf?be4jLiWru<}~43(99P`iJ22Re~Kg=_}IAzZl;_b;G`~^qGS=lR8({$D~0> zFCu=1-uXDx*Tj(q{ooh3ZZ7{#Q&oQ5jrE?rhXMGM9l@nfMbJAe8 z7ELnkJnKtXTbbR-c->Y=!ZrKkTHZw!Os8O*=ke3##QS*Rb}OzDQ- z+tP8FzZ~3L?$-sc-sQJn=Kl;{tuQV^e&c1KhLO&FRQi(mtKpYQ1*U((k7Iu6FHEL- zY#hDB{L&1jGt*CwDC6fX{*hCM0sbFPw~6H33^k5UZ!#^>)QUE|FuWB0E~=u0dOV<>CJrnF?7^D^Eifq{27 zt1Z>8X@1k1bh%Z`tf|SJmBfP4pY)u?S3h%g)!)GtJLg;-wJ>Aj{E>W(b9}QGbHW=s zdkiZnS(U!7%Kke24&PohVhcZ^WHc|lxcVbr_&CEQ)~epRq#Mt>*NC%5w5|Y|QO1wx0A!8UeVR-x+2KizY92yvTE(U#aIqf_B*%@=$p_(d>+KXIKaZDJEzPZ*3FVq)E4oj-C#+di3?SaWvAM?)c^{>eSFXBt_=yzYvuL4fi;!TNR@*>8{0hs?gg`t}v>ChJ4(Xx$9`n(6#1 zmL64>{uQMsv-I{XJq&bC3ro@GjD2Duc%JpSrJRH7Zdhuq-1}}`qs(Tt=h<(v)9)D3 zhl%FGqRcDdT4ino#qLRpd=>>i2^fNh_d@`q3 zhzC=rp8rQYR8V)*iYhd@N$6KEyiL1uZYrwvUbdpNnHAV7Q)8(8MHl*42F(e5g$?Lm ztREoVm=h#n1Nw`*%=VuVC$RLv!Y4@gRPbXmS-MMj3+Y~S4UhD#%=a71K1Zm*eD502 zMa%p2uQG8Po3HkfE(A-({?n#&^L8CZ3~Vrc<(+@_?=SgRFLCSfC4K8YsZ2e= zY=f-~H~b#l>UU$YZxDzq$6IjcpI{ImkF8-XUO}_v0IZ>@o&VpH?fv)vH?mdGaSKDo zZ2pTEjdapAn`e-MHtAf}R$K2%?^0o1R586PYr`p+uMSIX(1uy84Oig#H?cBC6x!HX z{=3K(zT=9zZbVCF6dH#dJkDIj8?)7lW1U+xsuY$v^oOAt)hh)icoPPXT=B`9!NY&9 zX+54F$(+38^`rTnu14+kc>*7Ob&1x)S3kV9*VV3_Gqy#OF0rGkcWd6NnzDr9*ZJw!dbx&Noc_=I zN4pHrV-xv^;PBw){XnryOK&`@GQ096bkNK=CDOdid;8C- zXd;m8=o3Qb+1Gx0e|%iWR;dZ3gE7@AHR?SiJfU;`^`Bqc0hz~+ZGYrQNvmcp2M%l5 zE+lp9@OCXn_YRM2RU!<8pbbZkY-k7?Y9m=kAIPF{JW<+*bkK?df_jW zZ)ui9x?W)oXZm*aS^4he`_j_svVG~x!cS70(7rU4zs1T|*q4@BU*dP(yYG!>qkI$b zM%lh}cyPK@gz_yMpVI#D2x$h&f6wMQ-dGd^$#ts`FdjG2I3p?Fq-y>oEh6R6@PjK&6917Isg&I9u z^sDSh7&9cfPh4z5yH37NeR@`l;DufTh1oHY^?J?j_s|1<$G-gBmiNL+DzBM5xOjB` zo-QdVS*qNqaf51Mwkkt%+qAR~vDK^Bs72MV2JNHzw`j{>G}pjW`?PZlf-kAW*nu0- zu4#*=Bjb5he7;H~b zwzy$mKF_ZU_T$$rZ*QVD$`ro6vsdV^>dFSz%ug_1L~(>(I*xWg8(8LS|C% zr{E{wzR&gr-~T4~aqu^DUr<_UvSsREHpWJZ@GEqX&+Kw{=DQVfRXG*8M=Y z2gzQRzAkPTa__$WBys)iq{x88ZW( ziRse5mO_{3+qW68zr;>gQlU z=DCLxjQxId|DUVEwKKjmjlXA0U%ltE45`ct8_h%CbXwLP{LuS zUhY`ARnNV1)=YY0uW(rz?WpRCnGvQoZpc@D9AEiFH=?tVMySE&PpOoh?y;MR>FZPxF7a=-Df!U{sruq+zc7M|%|Wwi)Bo z;tTS!OS1C{;?u^@Fpsmd^$qK*C-4=PC-xk6Oyv>iG>+_$zDX26)?j}Ex^ zGYi-|`pkm8(O=<=r=dLRaZPFdt@z!vhQTh|+z@%eTBlBA>)wMKM$V4v)}(3EhvU07 zY7$nXjk{0g3rmtFFaN@!G}~W~e>CvW><%+)baF;In$?Z!+^78mRh31jOLlML!>UDy zfx(>y49Kfjqgm`r!x!}{8dtAU)#g>A%sp@iXaHS_V&KCVO+0K10PxttaX6j)v!kM5-~1#_5Fd}4@Q(ktd{iK{S)^|K1kUKPH zNXMZmae>immIs68d-2AXvLrxm^AwADhRb*#j=ifZ8t=q%LSw$^?OeX`72Z2r>}EWagt zK9A=)x93+OZ=icnu@B{X<=RWLt6P|5KIG+2O?TP0+ zM!#P>1T+19EhJIN2+GhVlemnMD=N|fX z%lfyM<<~RiMSdTaU!OfcjAxxaH(>8uUzdImzEZ}(VpQ#>aH7PEQrOjtF&zFx^G>m; z5b@GOYm_m;1)RWll`D(Ojo2S!9w?RY*laUP~J%IwXagj14d@)X)}}SW@f@DvBLyiFI?aky!M*>-h~Sn zLOhDY{DLL5kp1Ifr|>D^jX;i~X(BE)bmoDUbm z#r9l#zP-?1bQl>%qLHAC;72g&Hy!;T2*RSsbjBOkE_Qwv^R7#tkkG- zc$M(5@T%d}!mEeZ2(KAlE4+4ioyJx8Dnb>pid02535BYf0*6cCa=1O*5nd@&p^hOf z`}HZ~1!EVSAa){&eI1;W9nlifeRabfOj7+>+NSes?N!14cIwHg1P+OiUw%xFiW4Mhw%zIszph&jLJ zbECz03u`kk`pz2pPY&7LtP&>+sw5~X*f1OBMPC^^Dq}~*bvHXIgH?@u6Slh1Qyh}f zR~kr0Z;6zw=q=Towp5!6wi8#DY~Qv-{xf)M|Ngu1v$|O^yf{^q`7-<$HDC09!ud~p zbqhDz*T&k{XwiDCMU76}Mr<#&m#d86MQ3fVQxt4hmTcR;GRHDB_7;ZLY6dYiz*R*Ng;pWrFAVrO4M zhuK0aAUCaZj1>iQ0BahKn6T$;^%~v|tsAvz-X*rBuUnk2{{u7PyVtDM*%#$-ybNQw zY|ZFET*}anLt+x!G?#>0O%vYhQX9G-N~hfdE!%Vso(r;e>a462m#fi+JwGHI;?Utj z_8jUl4i$A42Hn}EMz1i=_?5aOcj@m2vQ|M6dkY?gWQ%HG7%DVRA?{_7n31@-Ei|kY5-i`97LGv1CKRY~c z=H@=UQI8y!oyY!`7pWo8S$_KnrHRE3G<{x#i>9(c|h5O8kL#Y( zTus2d1gq}pr0TX!ezO$+rN83|CS)Z^WOn;e-E>=ib<`rao*~<8%CW9_{R^0HL^-|~Po7Qbq1C|@3S~ju{ z@8s>JC1ZqVwkPur1TN{L_$9gm+iKri#JfpZL~?8NVm!XbVbV%9C;u^T;(oJW#63R4 z{V45|bM>?s!bU;A;S2iG!qbP@`FG1dB3cf2W-YqQUtKHDXQ;J(n&v<6{bR1!tlCW{ z?VpFpSk*l~rBa2bz?tJcZd9Og9`Xm__`X3t-`Gi>0|M~mYVV{7G)TeZH2BJW#UzrTL_ zd0cg>edV*xbD!Zx2ERiQV4%gx-vL@t4r8>|Gs42xi6-^q%^_2+rD{(*8=ymZNAWfF zxqA7_Mx>lRwFF`Uq4M5FnT2%O;ge`lIT1Q9jWB;A`B&o?s`(p)63x-^`s>agEm6|< z8}zyFt%uaxUR}sAQ7kY69Ez47VK%pY4jPrm7zfTkx<52ZJ)oHC}S5XHY{ z+JV*~qad${*|`T6%6^LOybcEq+LeZvyHeW=e?tDT|KwvU5M=vW+|?PfI&zv?_J#@z zQL3!_r&GM3S6q=%HK^u|xMGr=g;(QY;>K+gl_Y_n{yl`%x6{woP4Di?mE%LLq?*M4 z#y`5wYvKG8--h$GzZEHJeye7z^Kc*HqH6h5_M`q&wYJ}+v)DSuZUge^KI*?op=j+?!nK#)9~oO!XnGK zx(b{5+CH1qV_nfR?iy#^*1^YerPNN32Y&xUb1k&Kp-G5wEt8uL@E5QW6-0rX6 zbArr$VDWPcdULx}v|T>pvuPEwMav z{!nytzpHMw(xsPhXSL&ba?cNUw=w%~D?|2(Y742w;qJvJlT^1?B%dElddGQOP_E-Ju({Si-a)>g-~IcL!8(Bqc^8r8+qvbI-4rhW!r zGysDvaDEB4K6dmD|4EZdYOhQfrY_ zG~jhc6ky7k<$?3@MNI74Wvko3SE>6smtlTs!~EM#B|m$8?)Ce{p=v6ARyYOmo2c^d z_?g!}QRc#lI^Ri=@_y(wEulf6c#mUUx`SZgkla z?wp9v&QN&N)JAZm4}x_3y>xQU3b633RxeFhdEC2s2p))G1TFs4ZBHN$ix)?4evukO zgmrJLN9gTqr|sen?u_bWMukef;61J0py1(-0FordKM9pq938~G3N9Q~426u5St|WJ z-Jz>VR zOTYHWLGjt=wzSpfM73vGKy=!R_)P`OLfb@a{y`eB_%OKpZhqo-#tw@HhtG<28^f9m zE2DLD*AoMFD!qhqg@Wl}>=To(slUrZ*K-={IX|)u=%N|~-}Rbu2ARtG>zja0FZSp; zM_Uo2g$Ljc13HZ76un}uocIfM1Icgdy}AhXH@JmZrn1Eok?Yc<4m`M zEK$k*pjK}?@r$azEwFo&E^^oeKARemz0*1NYc7cP3DRo#xxr12`PjpzlVMj);UopE ze8sj$nAH|N)3ik8e0kp+0W2e@4S`baB}?43;uY4()%>+vOF>wqVdR@4>6EUl#h0oR zs9uB&a6g)0decjUVaNL!!L2Zf?wOI*GxraA<>{2C2(_WA*-Z25gg;Vi3WbJxVnRM9 zne{R%pDFkFtqG{WPVBDCHUwhAN zolgTW(Ja#OD*-qkTNYGV5IjD|qlv%3FCzAj)h^eXi;!|%&XOx8TxU-yeGc9JL9#_? zup&8vW}bE_a#vzkZ6WxkKk_iz)?wfD*B_*jp8MmoA_7la^l$CKW5L?FNG}8zdkz)B z#WvZW>xJDZWn=_w6TEM8<{y0<=h>sWD}bp+n7Ckn*W$7cTF$oN%o9AN9o$MC03Swe zir^w#d|T`3Nn7o{HsDZA@5zwE8ts`B0Zs5gai?C`ED2fcnMW&0j`QQ>vm=%<>9ekR z`+ih-G2-V<$tuVDfBNtEi@iSCws4YNwwtfae$Yc8?{ z?7nOpzrB+z=klaDL#*&Cy#ddknmJvIAhx?o)Ehy@vL}(8IiQ87zMuBnsa0MUrD>_K zegq|!4=<)~Kh}@}`9Xq!Oft%!yteM({FZpiRV$AoYN;R4-7UQTYUh5>pqN$Sd+xwH zaHdxi1xE7iw{Fivkd*bDOjy^=!kyb+#0n?uHeMVxeY7>wduFRLiBwl;pOD+tGPqRC zD^9xDf=^K)4coPr7?kDT9t?(B*g4N#h`9rgKfnVrU%%AxjL!-+a}!*X|1GW~ulVdo zyuYs^p0SEs8LpZAHfX@A3e+WXJL2_Sw9ArUV$7Lz=hMvno019GIpOfMy@ruAF4OgV z=p<$cxf|LjKiHePbRYMpA8n51QD|`Eq3Uc*;(;}0N`U z)xZj*(Y89YPTg>Nk-)n9Fj_u1h?o7BY<`OJkC(lE7%hhVfFAV$?TKPciNT7YG)uP@ zi!z=9Py6hzj;ShnM0P6kc6%=)#Bj^P7ShA25JD%tn)YBNX>VT{uhm<+dCFqTtZUa# z-g(HR8>^AUvy?HF*7o)njRd{ky`OXvkHVXd7#I4#d<$w4`euZRv`a5fps`dmRKot| z&SYw%=_p8Me?h-bXIs>683sX>l0AceaV=wTDoEz!26rINBifg{690t$YHa_Gd;1~a zqpgs2u*iZx?|jbC!DL03KOzxK$VIsj#;Teh{5e0O|hwee|xk&JO+3v}CC8?hVxP)3vMH=hCgI zej|1IdyA=QQxus}vS6^zT|XjuEvu*T8GrpJ$W^NRVNwl!j&*M#J+Rsq<;$Z>>c6F`0Ji-gx(SqrTSam#-jkpIMsIb6ieY5R3=q zx=w1}*rGoAncY~^OVp+Ja2MifxbWVLKTNJBYDY>-WTgbkBo%RFCC1FC6AWGVb z*2;ruejAEJ$B+~x)0pT?F}}!=0+>RfB3sm0wkQ(~TQ}1{{y&^_-UIRfaNZY~pgY&( zh{QUE$aXeIf3yz&5Pb7c8Y>>vcJxap|crZ?A!Kv<%LE8`~3mz zVW046vEO&gp?6#pe|)=}W~)Y{S1OiD?XPO^CYKp)DR`dGvk^dwz>11}#yAYiDDF8yz z3l2^4{qoB^j4s;h=Gce+hwpz4!zM<8{h9Nbcx<)FAitgR_Fl4Cay|7|*GSuWUl*kL z%a0I-<{xyTcyp||@mN2Q zA3rKhTjj}1WbXLwPyg-l8+Y4{C~RtNvaG|~dGj9TnWZUwr)L~A$CuggrWPD%@T z%ikVXjDE517zq?#BRTAVy$_r@f`p>}U^LWa-h51Gkhk@9tyT6|h7vM>2qH4TEWpWblO%uop6wpd+Rj5D=^we2 z+J4gAo4rX(hexG#J*1BFNdu8nKiSb_|0F`18@65GFs+2j&Je8urtoSr4@{*d$`N_D5I(^_A}rj*>fiq80dQ1FFr z|7c=BSAZw)+^B}*p8t4k+4gPz{e{|>Jt~IUe=vP$+5XJF@_ex+@i1GJL^Xnh>wc)4 zGVlyNPW)V&tYrw>J9%Py z@@1iotLw}jSGCv=OanNWb1oK(+nNW9tXfl+_K3{!H`RasI58V{{ETApZ90lV>$nc{ zRqQ8uWQXiE^&q>+&pVFo)`G$MBhO|E5|8J2Pqq)@V>#)Iw15O7y#;@49ls?{hfn75 z0}b7W2@_Q2**>x(ih4asfye$F<2@`(l*LLw(H1kKcq5Jsrt1E?Dxl&U!_@F-$p?!x z$7lC&z1nMaed0@TZ|*vYlsOI%;D;=D7VRWtqESg-cj7iPUX3JP+wr8A9`o{v2RKcI zEJo9NNB-rf3e9)PduhFc;X@fA#hHb3Iu0N&ml<)xwAOwHm2eZG zONWqpB~INI4ZSx9M*u1Rse3o)<)gvTk z=Wf*zs&}7)8SX*8l}vdh^|EmzZI`D!y=_G~q25n_WTIGf6~72lI2(`egHL7PrA`DP zM0gdyWW)omtLmkeXc-bI70I)~_PeRs3THQHF2+DxQpY)v`%i$SMxu?mob>d)ur0jg z=RB?P-(k0Xzc#h+3Z3b7HF6$sHYTjyw0pde!DDt#?Tx&>OLj=7M|$;ZmLQv|3S!ExyssOUyZQ*MD+#!6Za&8i zi`B4^NZ{dhH&uzwBSR#tiqGokSg${)D)qNz%*?Hn3Zpzo(;PAB9oU36IxStrZIMO}V9! zzIv@sj{?WD+7m$Yg_&YTA=?{|=jVo~W+00J z>bR3(>Bx%7ry2Ve$#A8BpP*||f>Yo)Vjmk7YFX#1K}8XRt_=k63Ch8Qng{C%#3SbW zv8M5e-2QAQ*&}&QA4Sds`kt3$FOp(gg)lx;BlP4uh-^QxbFA60BCC%)YjbkkiCH=V zf!Z>|dWr?h(S-{n^(aYllkdpU?WoeNy8T$C^4NAljmlz4hz+aK1ZL_w@KRbm6!H>x zF{U&W_sB9ln-tUL4l9SLa4Q#lJ=9yTM8^_lZZAl$3a zAdTQ#{60=yf^X?n8-*Mg&ixqH#wqLCZ;u+NZ$ddDh4lpguH zp-|Y($i&r`W_47N?9imA%|>#vH)4~iQI`~sCi+BuoH~=neL%(?j2CmT2KBmV{Gdzo zfQyFd;2|rj6u|YNZ1)kyRPU!}TPf(>mY9kr3;B65OzRfVISdpm2kb)XEGNVEWpSuS zOZS^M@8dLRUEL6$+z{xoB=4sFMc$(_)POCjFik!vM};HxOeQI5kL=6aV>_ z$h@Mg9$5hmq*41BTuER@^eP^*fd&{1ueWN@hVD> z>tc*@6 zO%Wy8;p9yx1h?bRQ%OT~e)AxG^O*kD=Rile0^lq^c9$6y#TqP-NSCEsJ0ysAMr}H0 z1gIM<@+w(bcHJQ%KLJ$|Fxdr!{rP1(|e;SSbD>BO3QLffl-;k@CtNnu?6B{~t> zu znrVb(EJr7zd|9lChoA)}o(TFtrcQJ!Bl?i`jys8eBM_u0kJ6|ryarY)OCDJc(S(d` zn)_;>&qW`_13i#Hk4|8pT8cavx=DFd$N?|a6APkRhm>D3lKg^w~<2*8M$ z@FnvKK7&hVco6T4Aw(7nX8-!a@%7*s=A8hV4%Nh-V44nfdVW(qQ+Ifi0z3-j69w7{ zWIviH8?!n>2ch~^hoc#y@VslclGQfNc6rZ#rC}vx;)rReofnv5ql@C?9;BZ8CM=Y{ zc_My3ABDHq{h4pJA%f{jke7j~$Uq14V@dL1;aq`TaVKGvgkG91%SpUFW%0b(p3+hL z{8iNCYQo3h31x*HSuw5004-{W5*I{%;Gm=KaOLPr#4Z_N?Ddz^hI>;8Y49i}wKj@N zd)?CRgp;m>u6yt(>c*bTgSz;WZTO|yfxXenHrBl^erO(c393iy@bth=qJcgqpeeM@ zd6CD3O8;RIYP<+FRD@YIZr*Vne$ExLE|pGdg%7pD=UdG-q_8JaGo65L2iQbyY-@G) zs`y$rjeV_dt7T3MTbI4wqMe?052&OLDmrh5=T3;=+43vbTmi-Sl}{{I9V##U;=|z? z&X3glqQPBVKrJ-1Fw|^=Z}^m90my`xK7GLvjHb*8H9xT%zK}j2?}U@2Ps2FY(RwlA z5Z4vG&Teq$G5>k`zO%%hp6Q+*c&~ioqAyH95j}LPjX||8e)susB;QU1-_8a3u6EyL zGJIcXglm^zBzDMzji&gU6?@5qjl9w@yj(C*&gG24=Yl%;fO_HY!{%9c)TO&&`aX#Z z8x2~HVd#!wARvWSH?uEkXU+he4!WieWinBeV|9qiI>c%nqKPN_7wEJHMhpc$_tlx; zsh2^+yL({|dJN9|CbiIIgx2g$b;o6jL1R>RDq*jG58rpm-yGc+c1qqwB-6Z13Atn< zkP>#wT`|`;!!)}X^YVdjfvM@&37RxAE3}gSQja_E=Gr>eBdX1gRK;;(PnbwNc$Sx8s2A~dOyVE8`NbBL~wlp zWLkbOUZ7M7L}d+_FdLK<(@a~{9qG@R(rqS+9L_u^S*Xs{j` zB(sRuf%>^PB2vWBBGUj1lcjKC2FOa3-+ygFCBYaX+?9eOA9D5?N`~dvuTu5V=vhC; zJT|a??D)vQy2XMDZcg7e3$x-2uGZWAbHNz>`;;5g4yyO6(Fl}F~Z#`mAYE7g8dp`7fn71Dp^?c&Jzw{=&- zG41>#GeJVv1?h}p?f*cHjs+bwhb=tqtZ!#_(vR3jnU$PY*crmxmXOPMm1jSwEt%qA?j8viclq5FI=*nGo zf54Ox&ao<3+Q& z7R9+K;O6LdCV89R^2nX~kcUg@l#8rAqwbKJRI!G-f6^&eIzn-~F2L;;Fg;Qu&6HU= z+1kvFMrC{p2=7i$UI9uq^K2EG;BvDYG-{au?HwV@h~|e8s8mqtBz9=BEvr9@?uZ@O zlU}+$2iF!2hAAoRCD@waegR0*D1Ss3&p|sv0doEd9KK&B)pe6<_^`}$u*^gp9oPvuSXMlz zbhAuv_l3{WM@>QQYX@VDNO<5Pff|~xEzoz!tf%XiUZv98*veq zz7vKOC0AtD5hmXvuK??a#x|-g+yU>Y;hyKsntxVbXi`5~1g?i;dceW2QX*=G&h(qj zuX!9Lm^AQjMm+tCk4x{?k)U>cr6WxJ;tocJ+F6jg<8GXNgdVY>>U%BbsC@-57ervgs@K*w2df!ZrLTCg4zR|!Qa%waX=)(DKvlZ-ee z){g##w*sKTB=QULqg-$w+8?LNt7sUz$&|ehJ-S(wdX|F;Vy!nq_==Z2>>u@*;iK1l z4=vq7LDi0upG%gKkI9KCfaIS_jXFz>W>NM&={#^Y=ih#$#nR=XyJ^L#Zsn0LIb4t! zeT(6Eh}?^JBm+oV6+(v{t$WWP4bOP7qF{}+GSjuVXld*wLVF#W{{riEmMtvc34xLz zLZ8TvuJ$Bd zN8lmKzv6BjmF0e+EezUh<~#To2YRyU?EP(az^4s~b} zT=d2%@*KODuXy7$!0Vf29A0;$8L*C;-;oAI6O^Q&$s0j(Ab#kA@a+hS@Nf#xCs*BT z;m8+N3XofelN=j*Zzw&IDN#amAp~8N165&t$SQ}^k|b#NDb`nRLuq%gMm&0g)xZaeNN+wFbDeKO^GP*r^8}xK|v>0lJCY7`FOtZ>Ys9fi{Kpt~wvtkcQqwYG zF2-GH?McSbY+p1@^BjDM8)X%*Y)`8-Uq-M#s(X$J;yY?%h^!kp44<)qTz*RKnb*ra zuF6v4=_TK(C+}E_CD3C+frDcptS9hvAvR<=_VWT6mrC4O<2I z{)M+T=DrdmJ_hZd#9GKATuDl4)dI_|hPplQV9s*xt$XkR3s+;+O z>qE&R{taEDCp?Ghi1OlWchTTx7PSTHxBq%VO`2dmt{k*#3zS-+Fr*zOh~sqWzfG}D zTGvp-U+KIkcGpr$VpCrX`zaDYvchQ765L@VNn9zV*4#3|7qbT<{tuv*=-+ligH$}U zz;BV{Bvp(yn6Md3;>DE$i9y*U)nO9v8X9)>(HS znwIdt5m|HiKRi)=XfWYFVG~Buz?FiDhkY^pr$`{_1x6b}__s3}vj-;rX9$oH$ua*C z6htUS;6H=5FNXY7hKxjs=_Mm@#F79w2QuQnos2jLIq5$^76$>6{xj~yIsgdFn0&Hc z3fFsPpDBXx>9kU461q zp#U<`7pfM2woSJ&u24Wi#_n2;0o|c^No>hC4S)8aF{?byv_^OH6UmMArUHeDrxUl5 z&vtoF|BGQ-;1VQkGYE6W8>W?fu&HywJ5s9mLNfl0qv%qb4)e=k%u7bMS4I~s6Nfy+ z>}woM=#?B6K#+PXhj0?}!nz2im*S^`;YC+^xJ>zkgczRYh)ClSwl1pB1&Wr@ap%y% z12(?UVh#Zd9QOi=*VcNe`0Vs~?DWq?nh!;WL#PAo0NwXIn(o2()sD`?0hEsab>4{j zMUTBSK1x%W$Pc)@sE!iqfSO*}=0V>cA z=&6Nk+d(@W$o(vJR>fuO;(DvG4=sPi*iueBMs?EERA=vrhxNQv?x5kXE330L=)3jWG)A`&G zd|$3a8yZ8T*ssK#Jw%<;X+$LvkmkEVj*$#YGTC^_urucHGiLdy#104OhdRVX9io>9 z)lWbC92j-PlXnJ+j0AF{$w)TXjjM}Ce*HtO*m$%q9$mKEidt_SCNZ3$g-GgaG0B8I z9g_M{>z>ZujYve%?Otl_%^T+{c(Du3`d*`==&a_woD<;bC3$mnLZr5CW+`e{8!=%z zOrky~as?9TxMD!NNY2V$K@x`s3D8ZX=_Y`ph@f^q*q#kMg0^c}7fk^Eh=C)Cu<#h2 z6K#}ROqmZc&O1ivQpWKzajD^bT> zGOTq1qvJ6WRNbISUnuUu%dV;TcYU)^&bWH+Uv?&#{V@)quJ6>koVwZxLrgfy-&S9n z+Sq<6i{8FNwawUrp-|;^V*Zl$4(?A?%=kelPmnN3Eq*XdN!3^X^%@!SfJO9)kx(pT zyY!u-9^WFfNxjiEcrBkRA3dYlAi3IWNh(aslqUtMW{HNp;59x#mkkU!{U`7>%NLzW z@ezySwAij^!_^?I>iFb8a0j5Gmy0l2tD6GF@FN!atIfV+MRy$8Uu*b72}*KTFX-Tc zI-~S8vQ7q%nL9dU4$q;j(tqaSZI2P<=h757D}nHutfO^AU{L5WePZh+ndOU2D6c1Po{Cbq-N(F$skX>MW6lP7|QKbHG+3in>z zr@)-(yrX)XijiXK_(NS1QI>U-;N8uL2XtS@EFt(=p!LeBjKaP#1uDX_+gfxW}pv4Ox=TJ!=(#~%3SIkfc>QA)%#Y0F;iqfe5( zukwrOM=n_TGoT44*;^pINT`n&pp~REA%xmAtAHf>CYMDe!S%2BwfESr%HkO$OtwkR*|LKZeFEA zL&(y#Ne4KTqcY0{7sZY`A7NG4Jj;cKJaDB+;hyl%OtY%5ijUAbj~xhk?r)jvKHLewR^T z=~=d>z~waopLY;GO^R>`6byk?CYx;tRj}#oQQnr(iD1(q0)}nLY5>>|WL<1!%d{{n zDlMAHd7A!Eq2Q|~Mh3$Yy4}}MlDgqcVbWhXWemduAQTlGz)sF{F~f5TtT$l9ROg(c z!j!C-8m_=}UX*gclB31cX!`Z^U5b_*b)zxhQG`Sqi-@3%|o)N=cgE;uzV z&xbnBG{Lfz2d2>Wn|(zuqZQaLJ;c|FX=*&NL(}kTPtJSODBo#RZzY2MgC2MqQN4A$ zH1lYSQ*?SV+0D^=LI+()e$_kJK|v5rhh1~RZaX#i4`A;>fL=HLASsp$F+n#LTyJB+xVm@I!NTf5;jHU=Ej za2!kK-_Ub7>_tI$Yx5h#u6%`*-m+^|C*AXWXy|A*i6VHP z;xr0C&?1l0Brhx>TNc#`RmDmhElL`#1fr}myVgBQ*N1J$RV{QlB;Z4A9_4HvS!`H{ z1j7w*B^s{J zx)Yz^Eo?t*CIwod$%}|mcleNd|7Z}_A;P~G9DD*_vai@ll)S(ZG#1FVUpQ$$t*J{K z$lj4XRZR~RK?PBtlb9R@fZ9Wj!kGv(zfmOMT#Z^ybaLKAXisrX4R~1!d$)-gI=mf2 z-4RY1X-`(l0iRCeoaTVynWv=5NzWa7$cbnQqN}5w;ff8`3wN1VoxR1q@Q2%bY7zBa zJuI4|Bbo!bhZu{%Y(?QnTC%m}yU(%fK(}(zrcS z^GyZRDX;T(5N@Bcq&IG&C#gmSN1#64-~qJwR>yc>SgE!@2^@?UJs)xCBY}M=N-f)fs_`hN zEisd|1J%h>LwTVhmT$LB^2$`r4Lcf(SZ0miQIQ@t|HbH^mX!HWi7r?MJ$(;)_vDP$ zq((lKWxz~}&hv4RP_W*xepn()wH4!sfTzzu9 zMLSLc%6J09o(aavK(OJ$j8m#|?15+gd+{1Q)$e`?(FswKAFIVi8!d(YN$}5MQIEH` z#I5WYo7^Xh26%w71;|L@%m8dia+hYG9t2k)CZrRJi~3q}dz-pF98k{Tfsf<8bNgPL z$t#^Ym4kC#hfAhcLPj*FTog-)J|1eda(L-vwlMvRtv-|9@2So@5t3^Yy6pjdJP@^? zD4q>ZIUd(0?O$JchjW4Hyp9{OZVbV>@kh3(vBahJsx(#WF+FP{)FhJX6oT+2_h9?Y zby)R;V!;5@%Gt##+{@V^WoW}%zLRFoa9DYZeEkMl1mGOBaX;YNksMP;Ny1tVF+)_`>{M zND)gVUXQGs>vk!*mVlwa3r?S_w3Yj{66&{2D6J+$xhf_?+9i@Aya24V0Tn%j552&6 zY5f@oPY|wA9KAo2xdvb6&>5nI4^d`Ek^8d?MqMSDC>&@JO^NUp#x7}%jMyWC>=-70 z4ya5){#OH!O#@7j+&Ra_^#D1nWKzvNROUUDDL*ACD{i;EErt%CMNX2#$RzT=iQ9bd zk@X%my&4wH`(u<*Mh|TbI?IRcxoQXeX31WqZXRO6kf?Eo6l+m{s2%DVJBGr1VMtJJ z8?T0xk&RUHZhrhcTU9II{0Xe6a z4$x~_wx^LA_^-f6Ulj9B6L+{>hOz@ae+l5^VV@0*1HGCbqOM=E|}@0nyvBoeT%Hz!NoGGlO#=-}$lH za5sZ|jUL(xVn0{zPy;50W9t4JS{nudnz(sjj3(}?76bVIfI!fPHYQhRN^Px9DT`SZ2HjbxK_$WZ&im z@|M9ho3KL-{}S-TA!_=to&y=5by?Lb(8w3d3-*s83*;qR24=64t=%G1Wr&?1Z$2i+ z`IBkzQb52^yx>R=S%(bSA!UUCAVaU7Ho1=^gguwNntb7s9CPgreEBZQSA^5q$ZV4; zOf~LE7;`Ch6v5h|0qPcrU%r*pyo$OAs1N}A4I%KWS9!W{ZH8_Eqn|8&YUI(TvB@mi zdtd$V5Yb79iEh3qVl=l;i@L`IR`;+^o09Mln_mgfdgzh=uwJUNk8~5Io)~f~kr+Y~ zS*m;auquY;*c3tZoYBrWuQV4R=7n(|o0k9knWXrq)bMh;D(3%px|@;c{**#56{=!D z$4EGlYeqZ%{69O*Ns@m`4KACiV%U$7WkjnP?X+|Ee>+k0s?D3KUpEo>!{G?(V+UR0 zJ&&w>#8AFD-u0+3A9g6eu+N4HqdbqMbUtQlK9lH+WQ#g{jEZ49k7RpM7q{Zo7e&9i z4w%9yyv#>M=gYcD_s=;1CPXj}fbseM?d_^VHEb8GSta`fG`PwW7R|D{Z#=wz1KXQ= z(m}T(4cwIXum@%3hw`9*Y@9;<{e9Z^-+iIB<;3Uh)B7Db_K1t}pl^Mj{VkCnRkwJ1 zH~430Z{mJHu#7*mcHFK(1@e6aH9mREeuJ0b9$e@DI`M9>->-jYma!`nO04|l7kB5@ zmFlLVTqoFw>|%$n_A}t3TrUHVK}?Yp%e3zj1$6M&ri`Y$6E0o{%LF|?wZz*0;>KxD zbtigVQ-nvT&qHs2xVSrOL)E#}BcIPz^8H)T3!JfN5Tz}<%A3)(mu*zFZ25yNhBX0` zZSUH6GMJfcc}G|S5~(O{LHQ%={yDde*8CLRQN=E zu4=CbVP6DmIYp+-l-V8)HojtNQ^6X=-jyb9l#h9!#&z4NW{^N%@zJIL+emxjT3k&- zp#jsUDQhE-$;pY7$z0*zjW21^XyhLRT@z*wnl8IW`1zCRyWz(#DQoFp(&MPPw#+{# zqz8PAe7z)C)H(Ckf+xYG;CJ`a`RP)B>i6`GgroGf1#sSL(LzcNR!o8DUd5GtK0gzp@+H2 z{BoXN@E+nBW48d0^Aouyb5lq&ffa>qxnJC_fHDvv>AtddH z{_TvCaP;A)?BJ>zaAjv(5A{H6@#%}Q8nJD#aa6dbf0y7aVtQQ!^X>+K5n9ZDs!6*= zhW0}0nqEg}x+A!T@3j$b&0|tAk>gvB$ZGVkn^(o}+G|J>zn5}|@;ND-3riw#_TuM5 z+Q+OazEQm?9XZ!wnEn%1v5r_LiQ3bBKbH$vO}Bp0tL*9C*hTlsOH%K`$K*8vr&FLRStO{DA?RVUnSsQwkx!VmSRTB0~nXY+C zzK1nEHT*X7U4ITNUuZ0LZG5f1`6Y8AmSbsF!q_*hkU?0YIWwSiU_oJKZhf_tu|=2^ z&zs{K_}M+=W}Lb5Q2ZVBwC3>8ZBpn*y|)VO<1*Wm2Kb|nz|PC=w%M4b&lkbn$2j%z$ey?DXaWe7=p3(4E{q(^6Lp|M17rlp8dvX`PRIB!v zti&w&$ISs-p~v-)<_z(xnBJg3m6h)Bc7d#%ncbf?_H!`}e<)pG@|-cMp_BCQS>GIw zq1xI**}n@$+|jSSeHTpsgP#nrl_E zzpTuJ+kBOyKxImO+t_jEx4WugG>bAfcy$H-BcEs3qfqhH{ybch^(JVC>cm^)Socf| z?mDB?^SxX^kGHStmdLIDglul)QrWg4fS~;yZ50S?h82Ozd9d?SEvcjQ$`T-w0LU=M`xX6@D)G zJ6cR7c552xqTIeS;DXBW8)0_jEs$~wWJUHQ`-n+Q@<1zh= zz2xj#jZ8~pfP;z1%V5s~Cv1!v*8$m$80K248!ThLwvwNOisG7IWXFaWL1{_^n&7%7y*|%AG+4u8cQ3kQuV$o7&UM%MS{KzhZiA zX__brM=CvW6C*agkQU!aD;vCP_g}O%*Vy3G*w+V5pZU!`P!?yPSH7P0(P&D}WCB0N zoJg(y^}S3QG_P7B4Tcmn>;4FBbp&ji-ue0~R^Eqz3^rb5>+5$(@>=l=MjcHL^1=}H-VwBAaxXXki} zxxt=F@!8e~nI}&+UKbo1*%!LY=d8a$Zf!i1O@3X~wj$xu_QB=bqg8wB4>5%!U6jC2 zIIRVOpTbPH#Mek=bkWto>L{icH zMZL(KOV5osab^jL`bQ{Ef9cfS7ea@ArAb!}8*Yc5RL z<~@CnM26Wp%DRM1T=Y#qxo=zioZMU}({BTtqU@piPM`(y_f37`sWFh|e%|2?o|n?s zX64|ig)dY|wT_Ad1;68L$=vE+ZoObie38SH_^o`%wStZ7=7-FtNfCP3)Is2M6P+rJ z`Va4$!*}_LRfOX2IG$V^)UgsB9+%KnV14`1uzD>YPo^MKCab`vn=v8y2}U1$Fw?m< zHfqo-mNNWZVz{mD2a`eWp~7GVKy1Y2&+gK@neU*>cU?y{a#n^$_r|4l=LhIhK76QD z_-;JQwJOm<7Rlyb$u0{&O8-*R(4L;r@bl`|v>A5|A;!kQ9Nluml+rH|Ib;0!zT%Qf zod8%widi?K%sOlTQ{R)dl$y>CHGT2nVdHVRQErvQB>9Zb)bu%YN1b#JV^d#HZY44q zj|@I#0jlRQO@8IJ*oY z>nD@BFlH=YETbSRx)qID`?{<7;F|eO%G4aDo8O5EI({*Mb+_XOdKgtzC<=yw*eee7J>s#x$_RQ?PXU?3na&jhnPG-KI9D5VqVZX&687I2B z^?=iZ@Eb16c>)vj&2RW!04kAD3v+h{U|3S8{?q zdKH7F9}%@co;+{7nVHz$&tX+|2Sh{k`ps7WfZ&0_Xu|mm(|jq-&R92wZ+1dpdgQb% zGxP3J8xHi%9Lq0{K4f2ifph2Kr7n3J*8>h7=J$OY2%$!`!@eiQcGAp-mBP_inq5y! z?wANhFXTyESXRI7t#e&{IhY#H+>fDJ!)c?gjl-^j3$XlvM^06EeT8}C0UJpz-mFru zP-=qWA^55N!w(vzWu!Y+_76+QlB<1BLh#gHpWZNhCs55$db@{(sh+YJ`@*#?CvQ&i z78v(VqW>vhAN!}?CrQGL%>M4A1LTy4_g7fByq|z&2_l9kQ}iYoE#;z^dIXT0M3R-i zIO>G%eot4IM+oxyNIvpk6DzE}Xk>?pq{Y;=oSa^s+q~NaSVxc8XWw`x%E2iu_+Dz( z(r^9w1y|Vqw~1_%>nh?bc~bSStkd!|+#1+@~71Ozu{& z=|`0gO)YP^A2ptt;8ZY9zs3*uo=bJ;5ME7l8)_mqQLP}GPIKt24_ik-0&VK{%Ll2> zC+CKIMfoTOPjf0ECV&dT>9FkqPmAq-AK2c+Ebn8c>4fbYcfVOn+`g!K0kW33i?b=Q z8~!NyR^#&g?LAp%77;wEr6H%~HTM`-K%?&bU1z!z%7#?qkzEw*;9A3L|LlvPKECQZ4O# zYQKAecf#iV77?X~i7@VI8!}z3$SrSQd9##7**hn2%OTXnnPl#a5mv}y>5zhJyXi6p z)2<475aeJ*rQabnB=u?Nv$cC|WBNSdye1gM3SJ`vuky^(^7a|~QoF3vnsAKlC!q%d z$g(*xlkw_+{0?mwxH_`J3~MFMZxfi9=I#MS#fS zNbmh6r=eRunO}xaK9e*B&L0M-w^L+yovfXI4Ll7B2nN2T|8UW{u-5*$9i@$aj$sIT zARS6SK)6ExIsA}$hA$)nIDG2%f|@1HOAxgfLGL=KJ7<(P*-65sE< zf4S8E1)06-eK@l3k8Z;NFMWfggF~eI-v5Gm#ckF>zZ`SWi(bLtUa|y7N)Kf(j~uL{ zDNYYDs+d6x7p4^BfVpwW6dVzp8T>Lh;r*xg-Db;`2h-?=Q*X5Q=?VJebQ^OE6OK{D z^kM**B8&}Y9YcXh!RTYAF?TPiFO4rHF4?|IeaAV!QJ;NkhBiB0LNA>fW9Tv27&Gi& zv!yXkmjv`E)f=GCH)J0KT?3Po%93%v(5=Gt`pBqrj}u=v^g(WkhT1#cNg{i^`p~&Y zw7C@;>hJi3h^X+QLtPmk*>VdJr{N8Su06ufg^sG&^3)N};l(|YU{tZ?dyLQjf=%>B z%4c%P7y7Ts0v_GU%^y|X;PxPH##^}lo(Rx|kNZewG;Hq?A*1F7$G3a&p^J~`b1O&H zH~3iaaY9L-<~&fMNtR_Joa?Pb}g1rJn|$Q1DH9yP}@z9H_xd;2K)0f>^% z5?}05MJxb?Pl$WtQLY9HDLzSPLamZG&l3YqNnUP}tj~+9K(b_fuF#|o&SmAN^hN7=UA9^#Th?6`UVh=K*~rq$+sfF= zVM4x$9pvkWIdmX8Bsy9;{5#G&JeP5n<(8S3EtW}^wU-5#pDp7rt1fdbJ1oEY8vV8W zYo@C<8jO}jYoe9WhG==TE?Nz3+Q^Dw#Bg9(F+3RNdGfv6vbj2_$6(UOnu(7Mbsp>1 zz1ACJo0AVWP%h)vBkt@fF&D0GHh76(hm$%))OU-Un^tETm^m^$B&Cj6HV>UKaAbN& zmL4(GO>VAQoitSCr;8$_vQ;6cvV-uH8*&vt7(|FE>gD~Q6(B~0^;z<&aPWs z%gEdNvTg;UDo@B1qwLI^QyC$|y^(LtlSM%^eAZE7<`t=cwJ5@f8|JwNEaXunT@gqY zw;ECT3{DV9QIud;c=uZ*w;N1UF@p=pG)%G{h2Is1WOA!+d>o(?@Wg}@$jeKTO_UPF z)s=+g+*fw1M<+Ham~d5)Oh-|7MI+hv?c8b`<>xt_NgAR?UQ2XkB6;@>-5Sstjf(SJ zdnDNuCsDV$ULx_4jQdpvOmxICk-c3jNZkDb9~DWSEaH*K^)8C;L!>Hl5XprsMLHmF z?C1F?2bc!P1!%W&x3hwYDs$pHFJovxKP< zYgrUWOzPOP38xq-@j&&o9EzhS^&%7Jlr^>dIgBFXg!(y}SQ=1qty*QM1aT!=C`iku zIBHUNi|rID$^ll1y%x{wnc}Aup`~7&lE`wDe5Mo#4blqcFr;FDD&at7$A7VVEu=%m zCdF_!ML~&Bg&C@;RU%}hk}wXvWA{c#Zy>Rzz-`=z!+0Rh9V*FT=BLCNiw9*YHb`So zOJq|{fO3rM*rf@XrZGx!4<%YF*Fwd{O*V<`vV_cx7T?PH6EuQ&mK1$UmBMlciM!ICaPG0 z)~sa7t(23kpY5tKjM?<{vpc4w_UN8@W#3KgB+~1V-gJxMxs}I_sY7fLtuo+KhRQ$;HHBsxc9mV$54i z6DAA;#Ux?s1LQ6hF7+-!?Hs{;-x=qA~#ctT%kX%|B$^|shOll)Wy zq0h%P>Ut{0&*$Dyg>&uSE*Db!uuNZNqZY*i^k zYKybeCV^CJpi$$xn}z5kQC6_B#S)_1?)IU zvID8?}NLhP4>5kPK0lj{mnnbq&A6DajP4^^8Rx@8E z4h_5{CaA&NoF_VL90^Gr13Fe|0;X?sCCfhPSaZ}Si4B;n5?f^nm>K49>yUFqC9w|V z4_FLnt-4vgJqWEaG0ZK~(c@6(EKMp(6do|L%B%s;<~Zs+{j2n>xmV$ zzRS=DYk~E^nqXb9HZMCxlIpZi9S#Rr~}jj z>H#%@xF`9r0m4(B(p@bq@~2AB;x`4f$RaZ zfu#ZI0jE{SJslNY(5kL1nXYn@uDq^pl)bJ~iK*wiq{#t$GT|rXC3@PWrNWbG_B{14 zBgOJkxb}AG-N{$>%)%zo8q}p~lZEzz^-Xh+oQh#u#-&b^F#CczP_!1Jbj& z+N>M1rEAf2F@JTc$V)@QJ-o4VKFS`j$8d7Z8@&5zXl>a2aEf=n)?R;)wLX1Ie`V4~ zSoZEaaqLYF_0so$7h$hnpORK^tatt{a4N_?SlEy@r|=!llf#Z+&QnFG=R6emn^ zZ0UHWiD#b6W#$6QhIMR;Yp2AvOpb^>v&79zb9i+qile4jxAM0vwzQ7iJl~#$Hk+8{ zR_N##tCy5c6-^3n8F|t+JT|R#)(|O4pDdah+9LNXZB|>T0Os#$c$c(H+Dt8MJ=>!5 ztZY^f1TR$5X%Lq1y$hf0w2$z6ELB3M9a9RJOxWT$s`FEjD$UY1(-|q{E9NV$d{3tF986Iz2>2(4bNX{`~h zrST8rqvL(|oFl4)*7S_i4AP9!+$6Y%czC#Zc*?oUd7QYNnuO=I=VOwUR3%gsp>3>b z25Ai*GLkaw^)c_De7 z+n?K?=bU@Q_}G}hfWQb`MN>lqOEiEOK#U-U5Mz)5$OvQzG9ESeFfgXmS`LGR@Bk%Q}qJ zDdHez6}AdtwdJUH*IVQ?kT11NDv#8yH!9OB9kOo_FH0&*D%UN03NL}%!?)m6@HDs) zd=4%SZ-)E9&)_%Vuiy%BSBKF0>iUTK;`+DsP4!{*(E6nM`ugbla^dm0VJa&pmuOgz zfpF=>R!ws`UFkHH!;ztcfrOESp@eaZL5op~;RRgOp;h=JRn-=J4^9Vv?4a(z=MZ1t zP#;rYS)X11UU*jgLz+3QEv+T3Bds~DJ*{=%2l09Fj4@h_RJ>uG)hEu~` z%9f1Y*Dlrtxm&9Jy>u!x3-^cuxIf&#X`S zFClGoTQxE9F<{^#= z#X40vy>@!%l)8Hr;flD8cnOPxX~J|6w#I2Z3&~HZEvOv^>#SybW_u7dPGT?<<1C(~ z>h#`p^4x}xFK*6$_Ngu z_kDyRLJScFJA|b;@*%+0ZT9{{ULU>2y!wxuckd$7VS}&+M}0?qr)ftQ#A0=uga62J z`)>0t4k8>D<4BJHRtMUje>!g3#Yd#TDjm%b&NJ=Rfez=xUK7V{ySETAuxv+ZL{RmG z{rS*w%Pw~A43Q0c?--1@tX_aERNruddJPXFZnW5@?9`Z6mwH7l*f-4XdWE;ex7D;o zN__%Pfrr2g;7;%aco2*L_kyRvBjBaQ4~wIVeRR$-RU$BvYLR-8T9Jl^s)o9Tng&=y zbwj=49AY+qXLon(n6ky%d(PCWVZq{L&SDqnf6HIdAK-7}PvNicFVeC^XA{!^n8EQ{ zSX@}_%(DGr_r*%R<^*<9eNul?d(r?v+?vte!P$Me^Kw^iM{c)shj1nwp*TZd7gHBg zQ#7ZDnAq7ozH?4_Zs1=iH3%FAE@nB6RIkq+?wlTn@7y?kIZim%KAt!hJgz-{c1*FmzRNdj z277NFJaw6N@!}%yBL2ejocdT~H)YplwsNL&u5xw>_TD0R`ZDVx@Z9tK)-mBO{j4-B z*!=tC<=cyA=M=|$yJoZRVM|rP7T@8QnHPl@{^x|p^t;lt!LaY<-={9qFTBrr&gqY( zcY|lY!@gU*cY1F@IHyXR@zVP?!5E{MWjIoUmOOmw>9ZMH0!3CuD@8KJ)clhCwEX7$ zSNVnc$@#E+NPb0rR(^Z_^ZeZWIOcicW!oKFr0tgNn(dzLvhAkrs_m}ritYAmkGf}% z#pWdPX!!|-mOUD2oWpyUJ-fsMAOsKy1Oyp|@Iope&IIq7hl#%^xn8Gf&Tq*NXC51y z7#oa3ZR~EWY;13=Z+ubmy5m|PdQ<$S*iDI7qOZhXiP5><@qXhfxk0%}xvJ#(#;ZVV zoc2D1A5sl@qL^%vVbRKrh+FCNM2Q{H5{lu`gh7}Tt1Vtwf_G=xYzn&}Ap<#_DAVvPoFPOO<05$+NTc6VsBDW!z9`qzFN%-la>@lW<7We`J?zP&_CThnM3nuH3d3RXT<@gED*EJP<>}(p=#h)#(>hMFih;|!%)}8> zF7%ZbH;M~bj8nWBWjA@J;=^ti-iaL7ygKiD{a0^mKu@t#oxUPjT3%c>>#GnRov3HE zc^2mR9FSZCY{;@Y%3P$IF0zfZS8FGKM%|63d!H1bL6c)3VnM%retSu=5!i7=ToL0M z7`n}DLce@=d-_jR^Sp>)C4>I3;ANU!Q2ea=Oi;%$2`sznB6JtvDE;&t7x9})nt{+V zwR<(yjm3rLX)m$Y--~`)#WM&Xu$LrAa`}gtiYoHk*Wr7<#j4SEy(C5E=-%ru*O3y> z(IAF)lD}p<)EO|>I|zw_LcZdJ(z|jl42_8;%O|SXUVVg5WE3)bEtH(0?n>^B+iC!z z%z|-cPOOM%-_yRh`fz-5^3Fu_H=a)*o=-ww4hOy%`tpdUAt@t;BQr@`*uAuOa%WWC zxVwRo7o@$KH0o~Gy01p6HPume#4uw1BKE~^>eNBP$mrf(ce^K-(M1H{?^3?=BWv3g zp^#x4T1H%>&_|_Q5r@JG;w%Lps%5*-q8}Mh$FqA`2`t|6C{Ty@z4i%<=WU;c*|}*H zal1kiC|&R2fXqKA-w} zJrMp|*oD*nnR=f*5_Jz`F;Fd)>faDcrG~|aO3mXZMj=}_loqe_Q!|KP&6Cs4R`@}B zp+va_z7~MeMJEPU!_nVp;X7A&6nh)25HjkH%g zL&hz{Tw4*82FVbj6|)m}ANN2NZ1yQn#3d9m+uU&@CQ+@9G4Ci+?o&>PO<-dLs67Iu zg=PrhirL+Bw@<@S$j^3PnYD zZBb#s?v7aQBvGO>tBC%$z6T*?)ndiwD)!YX^RF)iYP)P)?du3jqJ&<-xSF?0 zg#<`s*u42uE%Ide6W(eDL3IwH(8xGL7IN8#9TbO*`c&8GRwd<@A(71$?u6-(*2r>Q zlj{0|0i!`nW=5l@jy(oSs*^>1Xff;}zf~5bdVGnB7jO0OKt>#*cF@lSNiPz97W!Sq zv1JyVtsj^z7Kdlq1#EWVpQ1qr`aeA+ulfH3p^oX>**m3C|L4#IQ;1#iQYn>z!Y4%@0C~poaQ>$(Eni0)pg?4%k+md^L5Lg3-8_%aT0B`>-?xjP4I6`{otk_ z@OdSe?fljI0K1pr|D=WA8@F|xP3TDfIVL5ShkD^~8n$C!)h2A|-`*|CTHw zQ)GHiSU8rmrtq`s-zg72`$=*58J40Stoi&5(y1*HAIn`{;483p_Cdv&aM~gJ#q8+lH2?G>kt8@4OlGSoI# z=S1;irAdD1epDvH?;u8Swb7lF~ZD|?w)jtM+e^IrA(BjM6p_L^6CeuU^t^8m*<+TOJ!$Cmmwq)0j;qZ?! z@C-^smf4SL)gjSk&Z>)_lqAb8g_s2LLu4g<&FD%=Knv^&AVni_r|)+#2bqL!Gnr5< zH{YI?Z{+RpB(8{ZHT_3b{Ioopx5JyHJ^kxKD0XoMk>wWLB{j73Kd1=D4vD0G6?|j+ z_h|X1qM!lvQs+tp^!>}sVgW4S*{H7xG(jClBo*1N7muga-O;#9*s)K1=kK|W6O#7q zuPe8uA^$2wAg(L7e-}e{FH%FA2w(pF_5F2_@|OYb8UJJHR~x-V7nFJGE5b6rl0zIA zz2WfKjQNbJzbG!?r&x9ftt4(&KwA=C`@yaM5yM1u{i??dGXHZ{BxL>_pV|EOh@|3s z)ed}==m`7eer@nG;~8DvmwythXW+aqKgDS)OLhv1xrKzGh2-mx(Qa$#I;&)5#U1Nx zAr6uu+p1HA@yFzbx58lw$MZ8EdDw-8z&=G?b@zaV2XG&oD{%vO8 zK$glF)Ddxe%-6usFU$com8i<@>wS>;rB|tF#umj({X3^-{3x^T*kCfbOWixC`ur$; z#=^6G9bnc#Zvtk&OHncj@SRiUQZodTf8|v1>Ossk6#b1pX}nlzQifo5nM;ijOzxFa zxvK}^*HGWDV^{Hr{Z7L09UyZF3c+MvIhD97rEuTgE3}_GPbUww2nuOUzv3$*Zs?F% zRu6(30UXK`>f!xH+m_{?HE^t2O8oK2pFaX;P~d;`I4Jx^*#X!tPdI}2`)ymcdDbk7 z8@l{WOaG)cx*da>Py+r|qX7gr{x=Q%clDn={jGf$HNYP@R3r#b_or=J4tdrfu{~R$ z%~Qqvd)@|rryJTCbqcAwFH>Zw`6s`*vU;Ymdd}S#wWE+J z^3^PwdJifM&RkQJ5|SR@GW%IH1<)L7+w#n1C=&N-lxgl1%*a=#n-g|}BP}?NHFrc- zDD$XEET|KNVT}yTQuPlK;$Q2$DY|$5u)Cv9(lTba;+uwB)_zzDNo-;q$jUqJWogOn8XX966$j@%{ZHkj9n#jYJh)9ZLW2#eWE) z{D`UqdqC@2cUtE&TIb*7O}^+)EK!~{yixp3hA1c|K3ns();FcwL65$kL%+4oS8L@o zGQ?;pu}Sx%0GT~;j&3Z*H2vg?HQm_kbs9yb!v0Bf+rF+*q6mIdg)VHAB7<`4gn#WO zwK-q+<6aM3V(q|*Zn-C`!UNODvio83hGIPpIO!Y}22r_{pUPf%IE-~kdTHBQH{njI zJ)XaAU!g!u(ui=m5pidw#Z8b_{_TzX9%i=m3BrsXU)Z}oe}djBDKgf^$2(xNwt2&$ zHEZhD9^Jj;?=|%4TWdtq+Jfx^8>sna6C3UpmxqU3em*r7?ZW8B#w!Iy5h3yB+_AB{ z(GX__HmP)Ner&v@IPg=kLH-KXX=!u=ebc-$|4r>!*!@JMC+G-VY5rvZ+dJ)UjiSh0 z5Sd(N|cq=}H^Byn=`%6E++9>j{RU2(kcD!W6^jA*Kf6&<^XsolC1 zer8Fi_q!A%tBKVeyApVj$`t#d^y=t;6_x4Dp&y0)Uh#a>$S~vZ7(7!nG^bb=TLFA1&Z+OfK#bTF=jdp~X_8b!BO=JyPI(v=@DAbVqI(hQ?k zOTn4SZcJ{5uH%>}IlM|Tbd`~taO@kA8e#wAJyP1W(TxY;3gKcx;-7NIo)Sb8JhSyk zmCNs>q56B%YYT%fa%P-8Pc(GIzWsvfXRk58oqAtqZdWE{U^w+LRF2Tvj#DlpZbiOV zQb>F)cg&3-8iH*%1E<?+DO3jBXgbROqD=5{KuERo{$;2-|v;$>v+!rTW!`W1div02dkFpcE6VOttm| zlsj)wV*M$F#Ct+Slg;V7gCbYhAw{CkkypC?Sj)`%=yFq1i`VFK6?!Rz#M^Vm_HRT( z_-s8)Wb;?>sA$zkH+)_w^pX&5KkOX+C}2aenz8_46N-KphfrE45)u#38Ee9c9>%xz z0LkP(yGE5sGP;owqOg8lNF0zeCU!M?7}pk56M)47e1%_G(Q8;)l>;y<0hks09bv$% z;P3E>$AqMA#9g?@|75{^Jbq}C@yxO`gD!8IF)+5=J-*!C?{!xAM%=D@{2!F(9THPz z#>hO`m4yu`{~&T$oq_GlGAg5P^4Yl7h_b2_z>xG$c)By%M+NuQSC*9j73bQ7d22w^ z5J$KH50`z(Qn}u-@C&SGkc#tQVnR5HX$Gr69FM`Qfth&coUk6hYN}{ zC2iq2*4TmmeyL?1G&6m?9*IM`t#H-G_bSy#XR42TlrI%m8l4TVnm>no?NL^0e$dUm zvM&=QiQSQc5%%aR^7+lCbT8mM_9sZ!3kB{6!cR@X3L!mh>Az#lOkjI|6Ha+63-9`C zoM_RUHu8pqgUqhy38Jn71g)#r`|?K9%cgfnl;+w9gG>MYdkcJ|2X5r@&cH){lBkV0zxcU6K9bqaTSsGIjg2ND;suedS3 zP8Ap>vf}9~DJ^q-UBlHC^Ml8;WF>pNBvo%fVRTQtViv=vHUbTz|9_I1^QzPQ+Qadl z^bt$IW}v~44?X!d8t*hz-PnB3pwfgtWwbxC`Kf$uug)ic#~jhKPBSicfy3G;JVEUV zLCa%(HF}qxGE%3grhf7kyV6cIV_N5f*?ClLQ@_o#gdwj#IQQ62=H_m;8@lz{6SFmI5QhLPNclE#RQzeECfnQ#z4?#-(r{Dsdi4Y*GO64H#5XO zTx4S&@^ECn&UdZwE`f-XYop!EPTF*9_|!M0NPst-mj0JWw|E`g&@`EMSV1%ZD7HKAP(x7c zU9S}8^6uC$-+=WsmflvTt4)`*7V-V$e2}_;;%~uzpc8s`*kWeYemCreAYOH=R^X~A zvq*{!IlHGV)I}{9n%)uFHE*<|=u~T=bat=!SKVB<>jdwsbT9t-e{uh5LP(0+%qT@# zu*2ECw081l)T+a=Ba>>_bVi8<+GJJ6ph6Y^U7b^YD2bLNPR*``67W->y(~ ziT8BwXektpPoG$h{tht-@bo6#!QG81|FUM>>;N3U8)o_XUxoh{Nf=%Ah*4@n(ooQg zf#=Sq#|-4;>srK2vf3@Z#atEw?pno%{wDldVYke)3qAcN!1*G(!v7x$9slwKUY8sf z5n;K^hFSpjOt9JA93NX&q}#Up(;!<&&dCw6gO-ukzOA2Y|J(b;4_<8=7K`PMG;HVw zMuVpmcWT#3DaMTi^WDSFM{k*agSRWV>@u^_*&ZK{?(F8yBIIft!r4gu2I=`XL#$m0 zhZgD5+BQi;6pF40iQfoG{c3kysC|_x6K`}w=L&XWVKyCvYwMwM1>3P5wW1qDB*3Ai zA0e?iyo1poyi87+C*L+-auE)V(xv4}3Ca1}zADtd{W=1ORhYd7_A8bG2+Ol1h4}nz zzb{eK{x(ha$JgD@Da4t{{FEng|3}28Joy*M0brvHA3HZB^zED~J+8l<6B1epomGX@rqI~%i4B9@Gulw1{&o$Wsx7p?dO3%uV66F0hrkEvZHz54 z+4z3_X2=@9@R*TkHxLNihu?B5vNKp`_`o)8+v!{|rojzMO`$8k#6Ot6_ zhsKgaF8e~2-4m_k>W4;>Lk{0y*bnm(Hfd9ELHw35TOVCmo?sz9=YZskW+AUf${l$K zK3u;lJ%kgKb_*j!h_<8qIwASF$oGS~*WzDUQ1|)^U!qyX%#|Sq9TBVgg>E%;g zKAD3XO2Etm&w=TPtR~CJ&BT|WA{r0z)tm{ATbUrS4UcBoqKUiWna-n|9yq_nMt{cc zSf$2`wK73TOlBrU z{@b`Q2yN+o&C+H=$|Q5Kb87R~L_Q;jl-fr2LLpSQ@qTw|oV5Z-(EV*3;*F#=N;n_8 zko;R>;wZsD|`62f=xg&-5&DB~BNciAgQU5J__|^wVGGc=~eIl71u`akDz?L=A z_3xGG*tMBPT#%>tv-D3=GSLwAneZg=jT@~yGr8%d8uG)Zd51vyis$kqz1ZK75VB1;Ox(J`DE8G_<` zEu+asvEt%fPL_UI`}TA#Q?6!|ey%m)=EqV*&)@MIHWjbElxE}P5-EMR!w6uOii+Iy zrVym#)Gv5gv!f|UFK58J!k;Me(DRehS30kgl|CH_R?4OH3hWCw3Q+4>wLROp&B(&c z3fs8|Z1T=_&MmT#w#atwDK^Qoo$HS{9zCJ=!7e^8S!kv3^_ikofg8kbLIsv>PijOI|@iS#avYIup1mfd$z!)&Lb*FE-Q zj8#$6FOc*_Q0&4YNiICZE<=ey-^;@==NkJb&f_jTU1q^{eBaL+(5n9X>p5s`4U8s9 z@H@t!_bRQpsWJ;=4K5F@M63f2w?PC_rX2(O;JK(@rpt$I5| zetAN%w8sGM?5rn1PUZNl@}vi_vbS52@ZIVbd5NTsDj9GQA~LIF1>;3h=toeHi=^;f z@1A~vES>1qe}Np7-G}D*1gWu}cIWu;vS;0mw0VKF8xO`P9l$n`a4%$X zPNNt*kd{=$sf^1-g+j#nc7h0;Oe8d7+X>m6(@4(X@DiD(g48a}M-{z5Zn5txf0k}i zF{wXDZRKRIc)Vof`@}>{+i2hCnQ!-PH+c~|UyT4JcHYjz8VlsgP&ZVgN9#SBvLLYR z75bei=DUZgwW`{6P0C@^peBx-HQOEj>u>TDm>+Oz&YDoZ$RYBcA25B>5`y;*szB7e zV4U3*rQ_BK9r>K^>NZg5bDgiO#-;iDMA68>(W&*FrGWt9(e^boa^LW@AV3Gm?QPfReP;1?^Dcy-dq2VJL!?1I9)h(YFhQctUkq(`dJ);6R=OBpLEKV&=L=w1lvf{ zRRqX-vN+Wfdk0Wm@19)#VlK%?lK*Diw?LBnt4x#G=S2Z;3hYkmdIJOH)n)TqJxmpE zteT4FHL!oKDT-hJI+_9CtfEzntp z2E_O|jXs1&Yd}ySBRP)u)vb7ejJ1tlj3AtfZ^X5%``+cs-<+U%_^Q+N4yn|AB>|1- zS5GDNcDxHVG|Lp26^_DjH@!D1jZ_uF0%4)J9VNmxI@z=-!1VSKvRA7!jH@{u%bx{q zC0_XYCDGwD7CrG+RA^T9;K+Q=mpRaW&)?g|(j`L58j(->#zJ=U!8GlCFPj-FP|Ntv znp)rI=6Kk`Q9)bQaguv**PPL_@xnT)5jc%RUR#Y^KNlj&iJ(bG)BUBR z=S-fX7tL&0og-cWw4*R2nze@Qnci%U5H)N_CE+xwP(eT?KVA=>etSDyN%(p^=lJKA zaiY&Hlhp71vI~5(btEU6^t*)bn-F>@WhPX0ySeJkvToV4JWVjL(zltJn$obDxp*_{ zwv#lw6*!Hjj PzNR?Hp$LQADiZ!5=(r%} diff --git a/lib/combodo/tcpdf/fonts/dejavusansmonob.ctg.z b/lib/combodo/tcpdf/fonts/dejavusansmonob.ctg.z deleted file mode 100644 index 76b78bc8f8b3c9e0a41a83366385e280a50ca0ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6120 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 diff --git a/lib/combodo/tcpdf/fonts/dejavusansmonob.php b/lib/combodo/tcpdf/fonts/dejavusansmonob.php deleted file mode 100644 index 9028c6ec0..000000000 --- a/lib/combodo/tcpdf/fonts/dejavusansmonob.php +++ /dev/null @@ -1,16 +0,0 @@ -33,'FontBBox'=>'[-447 -394 731 1052]','ItalicAngle'=>0,'Ascent'=>928,'Descent'=>-236,'Leading'=>0,'CapHeight'=>729,'XHeight'=>547,'StemV'=>60,'StemH'=>26,'AvgWidth'=>602,'MaxWidth'=>602,'MissingWidth'=>602); -$cbbox=array(0=>array(51,-177,551,705),33=>array(236,0,366,729),34=>array(113,458,488,729),35=>array(1,0,600,718),36=>array(80,-147,533,760),37=>array(16,0,595,699),38=>array(18,-14,603,742),39=>array(238,458,363,729),40=>array(187,-132,451,759),41=>array(151,-132,415,759),42=>array(59,278,541,742),43=>array(32,45,569,582),44=>array(177,-140,378,179),45=>array(147,217,455,359),46=>array(219,0,382,179),47=>array(55,-93,547,729),48=>array(60,-14,542,742),49=>array(92,0,554,729),50=>array(56,0,519,742),51=>array(61,-14,537,742),52=>array(50,0,557,729),53=>array(70,-14,534,729),54=>array(64,-15,548,741),55=>array(66,0,527,729),56=>array(63,-14,539,742),57=>array(54,-19,538,736),58=>array(219,0,382,519),59=>array(181,-140,382,519),60=>array(43,53,559,574),61=>array(43,144,559,482),62=>array(43,53,559,574),63=>array(114,0,520,742),64=>array(3,-156,566,681),65=>array(16,0,586,729),66=>array(61,0,566,730),67=>array(74,-14,528,742),68=>array(67,0,557,729),69=>array(82,0,536,729),70=>array(89,0,543,729),71=>array(57,-14,552,742),72=>array(67,0,535,729),73=>array(84,0,518,729),74=>array(53,-14,492,729),75=>array(57,0,598,729),76=>array(110,0,562,729),77=>array(42,0,560,729),78=>array(58,0,543,729),79=>array(45,-14,557,742),80=>array(79,0,560,729),81=>array(45,-137,557,742),82=>array(65,0,602,729),83=>array(63,-14,542,742),84=>array(44,0,558,729),85=>array(52,-14,550,729),86=>array(28,0,574,729),87=>array(0,0,602,729),88=>array(13,0,589,729),89=>array(4,0,598,729),90=>array(56,0,567,729),91=>array(206,-132,454,760),92=>array(54,-93,547,729),93=>array(148,-132,396,760),94=>array(28,457,574,729),95=>array(0,-236,602,-143),96=>array(97,616,373,800),97=>array(46,-14,541,560),98=>array(73,-14,558,760),99=>array(82,-14,518,561),100=>array(44,-14,529,760),101=>array(45,-14,561,560),102=>array(85,0,529,760),103=>array(48,-207,535,561),104=>array(84,0,523,760),105=>array(70,0,569,813),106=>array(70,-207,415,813),107=>array(85,0,585,760),108=>array(44,0,534,760),109=>array(40,0,564,560),110=>array(84,0,523,560),111=>array(48,-14,554,560),112=>array(73,-208,558,560),113=>array(44,-208,529,560),114=>array(142,0,562,560),115=>array(84,-14,521,560),116=>array(54,0,524,702),117=>array(78,-14,518,547),118=>array(39,0,563,547),119=>array(0,0,602,547),120=>array(27,0,575,547),121=>array(29,-207,574,547),122=>array(79,0,528,547),123=>array(86,-163,514,760),124=>array(245,-236,356,764),125=>array(88,-163,516,760),126=>array(43,226,559,396),161=>array(236,0,366,729),162=>array(72,-153,506,699),163=>array(58,0,548,742),164=>array(91,86,546,541),165=>array(4,0,598,729),166=>array(245,-171,356,699),167=>array(83,-95,518,742),168=>array(147,654,455,774),169=>array(0,61,602,663),170=>array(125,209,479,742),171=>array(58,69,509,517),172=>array(43,177,559,439),173=>array(147,217,455,359),174=>array(0,61,602,663),175=>array(147,668,455,760),176=>array(138,417,463,742),177=>array(43,0,559,627),178=>array(134,326,459,742),179=>array(140,319,470,742),180=>array(229,616,505,800),181=>array(85,-209,580,547),182=>array(34,-96,520,729),183=>array(219,259,382,437),184=>array(179,-196,400,0),185=>array(153,326,469,734),186=>array(134,209,488,742),187=>array(94,69,545,517),188=>array(23,-132,558,810),189=>array(23,-132,558,810),190=>array(23,-132,558,818),191=>array(86,-13,491,729),192=>array(16,0,586,927),193=>array(16,0,586,927),194=>array(16,0,586,927),195=>array(16,0,586,928),196=>array(16,0,586,927),197=>array(16,0,586,928),198=>array(0,0,576,729),199=>array(74,-196,528,742),200=>array(82,0,536,927),201=>array(82,0,536,927),202=>array(82,0,536,927),203=>array(82,0,536,927),204=>array(84,0,518,927),205=>array(84,0,518,927),206=>array(84,0,518,927),207=>array(84,0,518,927),208=>array(0,0,557,729),209=>array(58,0,543,928),210=>array(45,-14,557,927),211=>array(45,-14,557,927),212=>array(45,-14,557,927),213=>array(45,-14,557,928),214=>array(45,-14,557,927),215=>array(58,72,543,556),216=>array(-3,-31,596,761),217=>array(52,-14,550,927),218=>array(52,-14,550,927),219=>array(52,-14,550,927),220=>array(52,-14,550,927),221=>array(4,0,598,927),222=>array(79,0,560,729),223=>array(62,-14,573,760),224=>array(46,-14,541,800),225=>array(46,-14,541,800),226=>array(46,-14,541,800),227=>array(46,-14,541,778),228=>array(46,-14,541,774),229=>array(46,-14,541,888),230=>array(7,-14,580,560),231=>array(82,-196,518,561),232=>array(45,-14,561,800),233=>array(45,-14,561,800),234=>array(45,-14,561,800),235=>array(45,-14,561,774),236=>array(70,0,569,800),237=>array(70,0,569,800),238=>array(70,0,569,800),239=>array(70,0,569,774),240=>array(48,-14,550,765),241=>array(84,0,523,778),242=>array(48,-14,554,801),243=>array(48,-14,554,800),244=>array(48,-14,554,800),245=>array(48,-14,554,762),246=>array(48,-14,554,762),247=>array(32,42,569,585),248=>array(12,-57,587,603),249=>array(78,-14,518,800),250=>array(78,-14,518,800),251=>array(78,-14,518,800),252=>array(78,-14,518,774),253=>array(29,-207,574,800),254=>array(73,-208,558,760),255=>array(29,-207,574,774),256=>array(16,0,586,913),257=>array(46,-14,541,760),258=>array(16,0,586,927),259=>array(46,-14,541,784),260=>array(16,-196,600,729),261=>array(46,-196,553,560),262=>array(74,-14,532,927),263=>array(82,-14,555,800),264=>array(74,-14,561,927),265=>array(82,-14,536,800),266=>array(74,-14,528,927),267=>array(82,-14,518,774),268=>array(74,-14,552,927),269=>array(82,-14,535,800),270=>array(67,0,557,936),271=>array(44,-14,711,760),272=>array(0,0,557,729),273=>array(44,-14,600,760),274=>array(82,0,536,913),275=>array(45,-14,561,760),276=>array(82,0,536,927),277=>array(45,-14,561,784),278=>array(82,0,536,927),279=>array(45,-14,561,774),280=>array(82,-196,537,729),281=>array(45,-196,561,560),282=>array(82,0,536,927),283=>array(45,-14,561,802),284=>array(57,-14,552,927),285=>array(48,-207,535,800),286=>array(57,-14,552,927),287=>array(48,-207,535,784),288=>array(57,-14,552,927),289=>array(48,-207,535,774),290=>array(57,-241,552,742),291=>array(48,-207,535,764),292=>array(67,0,535,927),293=>array(-30,0,523,927),294=>array(1,0,601,729),295=>array(6,0,523,760),296=>array(84,0,518,928),297=>array(70,0,569,778),298=>array(84,0,518,913),299=>array(70,0,569,760),300=>array(84,0,518,927),301=>array(70,0,569,784),302=>array(84,-196,518,729),303=>array(70,-196,569,813),304=>array(84,0,518,927),305=>array(70,0,569,547),306=>array(-4,-13,601,730),307=>array(4,-212,602,813),308=>array(53,-14,516,927),309=>array(70,-207,485,800),310=>array(57,-227,598,729),311=>array(85,-227,585,760),312=>array(85,0,585,547),313=>array(110,0,562,928),314=>array(44,0,534,928),315=>array(110,-227,562,729),316=>array(44,-227,534,760),317=>array(110,0,562,729),318=>array(44,0,581,760),319=>array(110,0,571,729),320=>array(44,0,597,760),321=>array(-19,0,562,729),322=>array(18,0,545,760),323=>array(58,0,543,928),324=>array(84,0,523,803),325=>array(58,-227,543,729),326=>array(84,-227,523,560),327=>array(58,0,543,927),328=>array(84,0,523,800),329=>array(-54,0,601,760),330=>array(52,-208,549,743),331=>array(84,-207,523,560),332=>array(45,-14,557,913),333=>array(48,-14,554,760),334=>array(45,-14,557,927),335=>array(48,-14,554,784),336=>array(45,-14,557,927),337=>array(48,-14,554,800),338=>array(33,0,594,729),339=>array(7,-14,591,560),340=>array(65,0,602,928),341=>array(142,0,580,803),342=>array(65,-227,602,729),343=>array(123,-227,562,560),344=>array(65,0,602,927),345=>array(142,0,562,800),346=>array(63,-14,542,928),347=>array(84,-14,521,803),348=>array(63,-14,542,927),349=>array(84,-14,521,800),350=>array(63,-196,542,742),351=>array(84,-196,521,560),352=>array(63,-14,542,927),353=>array(84,-14,521,800),354=>array(44,-196,558,729),355=>array(54,-196,524,702),356=>array(44,0,558,933),357=>array(54,0,582,824),358=>array(44,0,558,729),359=>array(54,0,524,702),360=>array(52,-14,550,928),361=>array(78,-14,518,778),362=>array(52,-14,550,913),363=>array(78,-14,518,760),364=>array(52,-14,550,927),365=>array(78,-14,518,784),366=>array(52,-14,550,1052),367=>array(78,-14,518,888),368=>array(52,-14,550,927),369=>array(78,-14,530,800),370=>array(52,-204,550,729),371=>array(78,-196,600,547),372=>array(0,0,602,931),373=>array(0,0,602,803),374=>array(4,0,598,931),375=>array(29,-207,574,803),376=>array(4,0,598,927),377=>array(56,0,567,928),378=>array(79,0,528,803),379=>array(56,0,567,927),380=>array(79,0,528,774),381=>array(56,0,567,927),382=>array(79,0,528,800),383=>array(85,0,529,760),384=>array(6,-14,558,760),385=>array(0,0,598,730),386=>array(79,0,560,729),387=>array(73,-14,558,760),388=>array(21,0,581,729),389=>array(22,-14,580,760),390=>array(74,-14,528,742),391=>array(74,-14,624,802),392=>array(82,-14,626,760),393=>array(0,0,557,729),394=>array(-14,0,589,729),395=>array(61,0,566,729),396=>array(73,-14,558,760),397=>array(47,-220,554,560),398=>array(82,0,536,729),399=>array(45,-14,557,742),400=>array(61,-14,537,742),401=>array(53,-207,549,729),402=>array(44,-207,558,760),403=>array(19,-14,583,802),404=>array(16,-142,586,729),405=>array(6,-1,596,760),406=>array(84,0,551,729),407=>array(84,0,518,729),408=>array(9,0,593,729),409=>array(85,0,585,760),410=>array(44,0,534,760),411=>array(39,0,563,760),412=>array(40,-13,564,729),413=>array(15,-208,587,729),414=>array(84,-208,523,560),415=>array(45,-14,557,742),416=>array(2,-14,600,759),417=>array(4,-14,598,570),418=>array(14,-14,588,742),419=>array(9,-208,602,560),420=>array(10,0,592,729),421=>array(73,-208,558,760),422=>array(65,-116,602,729),423=>array(63,-14,542,742),424=>array(84,-14,521,560),425=>array(48,0,559,729),426=>array(29,-207,558,760),427=>array(54,-207,524,702),428=>array(10,0,558,730),429=>array(54,0,524,760),430=>array(44,-208,558,729),431=>array(2,-14,600,759),432=>array(3,-14,599,570),433=>array(44,0,558,713),434=>array(57,0,540,729),435=>array(1,0,601,729),436=>array(14,-207,588,547),437=>array(56,0,567,729),438=>array(77,0,525,547),439=>array(5,-14,597,729),440=>array(5,-14,597,729),441=>array(54,-215,548,547),442=>array(64,-208,536,547),443=>array(56,0,519,742),444=>array(5,-14,597,729),445=>array(54,-215,548,547),446=>array(71,-15,531,702),447=>array(40,-208,556,560),448=>array(236,0,366,729),449=>array(124,0,478,729),450=>array(36,0,566,729),451=>array(236,0,366,729),461=>array(16,0,586,927),462=>array(46,-14,541,800),463=>array(84,0,518,927),464=>array(70,0,569,800),465=>array(45,-14,557,927),466=>array(48,-14,554,800),467=>array(52,-14,550,927),468=>array(78,-14,518,800),469=>array(52,-14,550,985),470=>array(78,-14,518,914),471=>array(52,-14,550,1008),472=>array(78,-14,518,1002),473=>array(52,-14,550,1008),474=>array(78,-14,518,1002),475=>array(52,-14,550,1008),476=>array(78,-14,518,1002),477=>array(45,-14,561,560),478=>array(16,0,586,985),479=>array(46,-14,541,914),480=>array(16,0,586,985),481=>array(46,-14,541,914),482=>array(0,0,576,913),483=>array(7,-14,580,760),486=>array(57,-14,552,927),487=>array(48,-207,535,800),488=>array(57,0,598,927),489=>array(85,0,585,927),490=>array(45,-204,557,742),491=>array(48,-204,554,560),492=>array(45,-204,557,913),493=>array(48,-204,554,760),494=>array(5,-14,597,927),495=>array(54,-215,548,800),496=>array(70,-207,493,802),500=>array(57,-14,552,927),501=>array(48,-207,535,800),502=>array(12,-14,590,729),504=>array(58,0,543,927),505=>array(84,0,523,801),508=>array(0,0,576,927),509=>array(7,-14,580,800),510=>array(-3,-31,596,927),511=>array(12,-57,587,800),512=>array(16,0,586,927),513=>array(46,-14,541,800),514=>array(16,0,586,927),515=>array(46,-14,541,784),516=>array(54,0,536,927),517=>array(45,-14,561,800),518=>array(82,0,536,927),519=>array(45,-14,561,784),520=>array(54,0,518,927),521=>array(69,0,569,800),522=>array(84,0,518,927),523=>array(70,0,569,784),524=>array(45,-14,557,927),525=>array(48,-14,554,800),526=>array(45,-14,557,927),527=>array(48,-14,554,784),528=>array(30,0,602,927),529=>array(118,0,562,800),530=>array(65,0,602,927),531=>array(142,0,562,784),532=>array(52,-14,550,927),533=>array(69,-14,518,800),534=>array(52,-14,550,927),535=>array(78,-14,518,784),536=>array(63,-246,542,742),537=>array(84,-246,521,560),538=>array(44,-246,558,729),539=>array(54,-246,524,702),540=>array(26,-210,576,742),541=>array(54,-211,548,560),542=>array(67,0,535,927),543=>array(84,0,523,927),544=>array(52,-208,549,743),545=>array(4,-68,598,760),548=>array(56,-207,567,729),549=>array(79,-207,528,547),550=>array(16,0,586,927),551=>array(46,-14,541,774),552=>array(82,-196,536,729),553=>array(45,-196,561,560),554=>array(45,-14,557,985),555=>array(48,-14,554,914),556=>array(45,-14,557,985),557=>array(48,-14,554,914),558=>array(45,-14,557,927),559=>array(48,-14,554,774),560=>array(45,-14,557,985),561=>array(48,-14,554,914),562=>array(4,0,598,913),563=>array(29,-207,574,760),564=>array(24,-68,578,760),565=>array(18,-68,584,560),566=>array(54,-68,524,702),567=>array(70,-207,415,547),568=>array(11,-14,591,760),569=>array(11,-214,591,560),570=>array(-3,-31,596,761),571=>array(-3,-31,596,761),572=>array(12,-57,587,603),573=>array(14,0,588,729),574=>array(6,-31,605,761),575=>array(84,-240,521,560),576=>array(79,-240,528,547),577=>array(14,0,588,729),579=>array(0,0,566,730),580=>array(10,-14,592,729),581=>array(28,0,574,729),588=>array(10,0,602,729),589=>array(94,0,562,560),592=>array(54,-14,549,560),593=>array(59,-14,543,560),594=>array(59,-14,543,560),595=>array(73,-14,558,759),596=>array(84,-14,520,561),597=>array(79,-69,523,561),598=>array(38,-162,538,760),599=>array(34,-14,539,759),600=>array(43,-14,559,560),601=>array(45,-14,561,560),602=>array(3,-14,599,560),603=>array(73,-11,510,557),604=>array(50,-11,552,560),605=>array(23,-11,579,560),606=>array(53,-21,549,559),607=>array(70,-207,514,547),608=>array(8,-208,594,760),609=>array(61,-208,542,547),610=>array(75,0,527,546),611=>array(48,-203,554,554),612=>array(48,-59,554,547),613=>array(82,-214,521,546),614=>array(82,0,521,759),615=>array(82,-208,521,759),616=>array(52,0,551,760),617=>array(70,-1,531,547),618=>array(52,0,551,547),619=>array(43,-1,560,759),620=>array(53,0,549,760),621=>array(56,-217,546,760),622=>array(13,-215,589,760),623=>array(39,-13,563,547),624=>array(39,-208,563,547),625=>array(39,-208,563,560),626=>array(31,-216,571,560),627=>array(33,-216,569,560),628=>array(59,0,543,547),629=>array(48,-14,554,560),630=>array(37,-1,565,547),631=>array(40,0,562,574),632=>array(10,-208,592,762),633=>array(91,-13,511,547),634=>array(91,-13,511,759),635=>array(38,-208,564,547),636=>array(91,-208,511,560),637=>array(91,-208,511,560),638=>array(66,0,536,547),639=>array(66,0,536,547),640=>array(51,0,551,547),641=>array(32,0,570,547),642=>array(83,-208,520,560),643=>array(44,-207,558,760),644=>array(44,-207,558,760),645=>array(44,-207,558,760),646=>array(29,-207,558,760),647=>array(66,-155,536,547),648=>array(66,-208,536,702),649=>array(43,-14,559,547),650=>array(42,-51,561,547),651=>array(41,-1,561,547),652=>array(39,0,563,547),653=>array(0,0,602,547),654=>array(28,0,574,754),655=>array(33,0,569,547),656=>array(22,-208,579,547),657=>array(58,-55,544,547),658=>array(54,-215,548,547),659=>array(49,-215,553,547),660=>array(81,0,521,759),661=>array(81,0,521,759),662=>array(81,0,521,759),663=>array(81,-208,521,759),664=>array(27,-28,575,582),665=>array(58,0,544,547),666=>array(53,-21,549,559),667=>array(30,0,572,759),668=>array(59,0,543,547),669=>array(46,-208,557,813),670=>array(51,-208,551,547),671=>array(115,0,487,547),672=>array(34,-208,538,759),673=>array(71,0,531,759),674=>array(71,0,531,759),675=>array(25,-14,577,760),676=>array(11,-219,591,756),677=>array(14,-55,588,760),678=>array(32,-14,570,702),679=>array(67,-207,535,760),680=>array(40,-69,563,702),681=>array(36,-207,566,760),682=>array(25,-14,577,760),683=>array(22,-2,580,760),684=>array(28,0,574,641),685=>array(140,86,462,641),686=>array(27,-214,575,759),687=>array(40,-208,563,759),688=>array(161,326,441,752),689=>array(161,326,441,751),690=>array(190,177,412,748),691=>array(167,326,436,640),692=>array(167,319,436,633),693=>array(132,209,470,632),694=>array(129,326,473,633),695=>array(108,326,494,633),696=>array(126,211,476,633),697=>array(244,557,384,800),699=>array(211,441,412,760),700=>array(211,441,412,760),701=>array(234,595,368,844),702=>array(231,481,371,760),703=>array(231,481,371,760),704=>array(160,326,442,751),705=>array(160,326,442,751),710=>array(117,616,485,800),711=>array(117,616,485,800),712=>array(254,488,348,759),713=>array(147,668,455,760),716=>array(254,-81,348,190),717=>array(147,-198,455,-106),718=>array(145,-285,421,-102),719=>array(181,-285,457,-102),720=>array(201,0,401,547),721=>array(201,361,401,547),722=>array(231,269,371,547),723=>array(231,269,371,547),726=>array(147,119,455,427),727=>array(191,229,411,317),728=>array(137,639,465,784),729=>array(234,654,368,774),730=>array(162,610,440,888),731=>array(218,-196,427,0),732=>array(131,638,471,778),733=>array(145,616,530,800),734=>array(-152,213,453,524),736=>array(139,216,463,640),737=>array(144,326,458,752),738=>array(161,319,441,640),739=>array(125,326,477,633),740=>array(160,326,442,751),741=>array(134,0,468,693),742=>array(134,0,468,693),743=>array(134,0,468,693),744=>array(134,0,468,693),745=>array(134,0,468,693),750=>array(73,441,528,760),755=>array(194,-245,408,-31),768=>array(97,616,373,800),769=>array(229,616,505,800),770=>array(117,616,485,800),771=>array(131,638,471,778),772=>array(147,668,455,760),773=>array(0,663,602,755),774=>array(137,639,465,784),775=>array(234,654,368,774),776=>array(147,654,455,774),777=>array(190,616,412,849),778=>array(162,610,440,888),779=>array(145,616,530,800),780=>array(117,616,485,800),781=>array(255,616,348,833),782=>array(116,616,487,833),783=>array(69,616,454,800),784=>array(137,639,465,879),785=>array(137,639,465,784),786=>array(218,441,399,590),787=>array(234,595,368,844),788=>array(234,595,368,844),789=>array(229,616,404,800),790=>array(163,-290,439,-106),791=>array(163,-290,439,-106),792=>array(179,-394,361,-123),793=>array(230,-394,413,-123),794=>array(166,658,437,929),795=>array(203,361,399,570),796=>array(248,-245,354,-31),797=>array(167,-305,438,-123),798=>array(154,-394,425,-212),799=>array(172,-394,443,-123),800=>array(166,-215,437,-123),801=>array(273,-207,523,82),802=>array(82,-208,332,81),803=>array(234,-226,368,-105),804=>array(147,-226,455,-105),805=>array(194,-245,408,-31),806=>array(182,-246,363,-97),807=>array(179,-196,400,0),808=>array(196,-196,406,0),809=>array(255,-323,347,-106),810=>array(147,-289,455,-106),811=>array(102,-239,500,-94),812=>array(117,-237,485,-53),813=>array(117,-237,485,-53),814=>array(137,-240,465,-95),815=>array(137,-239,465,-94),816=>array(131,-238,471,-98),817=>array(147,-198,455,-106),818=>array(0,-236,602,-143),819=>array(0,-236,602,-9),820=>array(43,226,559,396),821=>array(94,214,472,309),822=>array(0,214,602,309),823=>array(12,-57,587,603),824=>array(-3,-31,596,761),825=>array(248,-245,354,-31),826=>array(147,-254,455,-71),827=>array(161,-386,441,-106),828=>array(102,-239,500,-94),829=>array(172,582,430,839),830=>array(231,595,371,867),831=>array(0,528,602,755),835=>array(234,595,368,844),856=>array(465,654,600,774),865=>array(-118,735,720,880),884=>array(244,557,384,800),885=>array(218,-208,358,35),890=>array(253,-208,383,-45),894=>array(181,-140,382,519),900=>array(229,616,505,800),901=>array(147,654,505,999),902=>array(-40,0,586,800),903=>array(219,259,382,437),904=>array(-171,0,536,800),905=>array(-191,0,535,800),906=>array(-162,0,518,800),908=>array(-83,-14,557,800),910=>array(-242,0,598,800),911=>array(-62,0,558,800),912=>array(132,0,505,999),913=>array(16,0,586,729),914=>array(61,0,566,730),915=>array(89,0,543,729),916=>array(16,0,586,729),917=>array(82,0,536,729),918=>array(56,0,567,729),919=>array(67,0,535,729),920=>array(45,-14,557,742),921=>array(84,0,518,729),922=>array(57,0,598,729),923=>array(16,0,586,729),924=>array(42,0,560,729),925=>array(58,0,543,729),926=>array(67,0,535,729),927=>array(45,-14,557,742),928=>array(67,0,535,729),929=>array(79,0,560,729),931=>array(48,0,559,729),932=>array(44,0,558,729),933=>array(4,0,598,729),934=>array(45,0,557,729),935=>array(13,0,589,729),936=>array(39,0,563,729),937=>array(44,0,558,713),938=>array(84,0,518,927),939=>array(4,0,598,927),940=>array(26,-12,568,800),941=>array(73,-11,510,800),942=>array(84,-208,523,800),943=>array(132,0,505,800),944=>array(37,0,565,999),945=>array(26,-12,568,559),946=>array(64,-208,554,766),947=>array(27,-208,563,547),948=>array(48,-14,554,766),949=>array(73,-11,510,557),950=>array(70,-208,517,760),951=>array(84,-208,523,560),952=>array(47,-12,554,770),953=>array(132,0,478,547),954=>array(85,0,585,547),955=>array(39,0,563,760),956=>array(85,-209,580,547),957=>array(23,0,559,547),958=>array(70,-208,517,760),959=>array(48,-14,554,560),960=>array(7,-19,593,547),961=>array(73,-208,558,560),962=>array(82,-208,521,561),963=>array(48,-14,570,547),964=>array(66,0,536,547),965=>array(37,0,565,547),966=>array(32,-208,570,552),967=>array(35,-208,567,547),968=>array(34,-208,569,547),969=>array(31,-14,571,547),970=>array(132,0,478,774),971=>array(37,0,565,774),972=>array(48,-14,554,800),973=>array(37,0,565,800),974=>array(31,-14,571,800),976=>array(55,-11,508,768),977=>array(51,-11,553,768),978=>array(17,0,582,729),979=>array(-232,0,582,800),980=>array(17,0,582,927),981=>array(28,-208,573,760),982=>array(15,0,587,547),983=>array(25,-188,571,547),984=>array(45,-208,557,742),985=>array(48,-208,554,560),986=>array(47,-222,570,729),987=>array(44,-208,557,547),988=>array(89,0,543,729),989=>array(6,-208,491,760),990=>array(48,-2,566,729),991=>array(56,0,545,759),992=>array(0,-208,581,742),993=>array(22,-180,537,559),1008=>array(25,-3,571,547),1009=>array(73,-213,558,560),1010=>array(82,-14,518,561),1011=>array(70,-207,415,813),1012=>array(45,-14,557,742),1013=>array(78,-14,514,561),1014=>array(82,-14,518,561),1015=>array(79,0,560,729),1016=>array(73,-208,558,760),1017=>array(74,-14,528,742),1018=>array(42,0,560,729),1019=>array(42,-208,560,498),1020=>array(22,-208,558,560),1021=>array(74,-14,528,742),1022=>array(74,-14,528,742),1023=>array(74,-14,528,742),1024=>array(82,0,536,927),1025=>array(82,0,536,927),1026=>array(-17,-207,577,760),1027=>array(89,0,543,927),1028=>array(74,-14,528,742),1029=>array(63,-14,542,742),1030=>array(84,0,518,729),1031=>array(84,0,518,927),1032=>array(53,-14,492,729),1033=>array(-7,0,597,729),1034=>array(10,0,597,729),1035=>array(-17,0,577,760),1036=>array(57,0,598,927),1037=>array(58,0,543,927),1038=>array(14,0,588,927),1039=>array(67,-157,535,729),1040=>array(16,0,586,729),1041=>array(79,0,560,729),1042=>array(61,0,566,730),1043=>array(89,0,543,729),1044=>array(20,-157,582,729),1045=>array(82,0,536,729),1046=>array(6,0,596,729),1047=>array(61,-14,537,742),1048=>array(58,0,543,729),1049=>array(58,0,543,927),1050=>array(57,0,598,729),1051=>array(3,0,535,729),1052=>array(42,0,560,729),1053=>array(67,0,535,729),1054=>array(45,-14,557,742),1055=>array(67,0,535,729),1056=>array(79,0,560,729),1057=>array(74,-14,528,742),1058=>array(44,0,558,729),1059=>array(14,0,588,729),1060=>array(17,0,590,729),1061=>array(13,0,589,729),1062=>array(39,-157,574,729),1063=>array(49,0,550,760),1064=>array(38,0,563,729),1065=>array(38,-157,596,729),1066=>array(10,0,574,729),1067=>array(20,0,583,729),1068=>array(61,0,542,729),1069=>array(74,-14,528,742),1070=>array(0,-14,598,742),1071=>array(41,0,566,729),1072=>array(46,-14,541,560),1073=>array(32,-14,554,787),1074=>array(58,0,544,547),1075=>array(108,0,499,547),1076=>array(31,-140,577,547),1077=>array(45,-14,561,560),1078=>array(7,0,596,547),1079=>array(75,-11,527,560),1080=>array(74,0,533,547),1081=>array(74,0,533,784),1082=>array(85,0,585,547),1083=>array(34,0,551,547),1084=>array(42,0,560,547),1085=>array(84,0,523,547),1086=>array(48,-14,554,560),1087=>array(84,0,523,547),1088=>array(73,-208,558,560),1089=>array(82,-14,518,561),1090=>array(80,0,523,547),1091=>array(29,-207,574,547),1092=>array(39,-208,563,760),1093=>array(27,0,575,547),1094=>array(47,-140,563,547),1095=>array(67,0,518,547),1096=>array(38,0,563,547),1097=>array(28,-140,596,547),1098=>array(20,0,568,547),1099=>array(15,0,586,547),1100=>array(67,0,518,547),1101=>array(82,-14,518,560),1102=>array(27,-14,568,560),1103=>array(47,0,541,547),1104=>array(45,-14,561,800),1105=>array(45,-14,561,774),1106=>array(10,-207,558,760),1107=>array(108,0,505,800),1108=>array(82,-14,518,561),1109=>array(84,-14,521,560),1110=>array(70,0,569,813),1111=>array(70,0,569,774),1112=>array(70,-207,415,813),1113=>array(2,0,599,547),1114=>array(17,0,599,547),1115=>array(10,0,532,760),1116=>array(85,0,585,800),1117=>array(74,0,533,800),1118=>array(29,-207,574,784),1119=>array(83,-140,523,547),1122=>array(10,0,574,729),1123=>array(20,0,568,760),1138=>array(45,-14,557,742),1139=>array(48,-14,554,560),1168=>array(89,0,543,878),1169=>array(108,0,499,700),1170=>array(23,0,543,729),1171=>array(45,0,499,547),1172=>array(89,-207,566,729),1173=>array(108,-207,523,547),1174=>array(6,-157,596,729),1175=>array(7,-140,597,547),1176=>array(61,-196,537,742),1177=>array(75,-196,527,560),1178=>array(57,-157,598,729),1179=>array(85,-140,585,547),1186=>array(18,-157,602,729),1187=>array(14,-140,594,547),1188=>array(38,0,592,729),1189=>array(38,0,590,547),1194=>array(74,-196,528,742),1195=>array(82,-196,518,561),1196=>array(44,-157,558,729),1197=>array(80,-140,523,547),1198=>array(4,0,598,729),1199=>array(28,-208,574,547),1200=>array(4,0,598,729),1201=>array(28,-208,574,547),1202=>array(13,-157,589,729),1203=>array(27,-140,575,547),1210=>array(49,0,550,760),1211=>array(84,0,523,760),1216=>array(84,0,518,729),1217=>array(6,0,596,927),1218=>array(7,0,596,784),1219=>array(57,-207,590,729),1220=>array(85,-207,573,547),1223=>array(67,-207,535,729),1224=>array(84,-207,523,547),1227=>array(49,-157,550,760),1228=>array(67,-140,518,547),1231=>array(189,0,332,760),1232=>array(16,0,586,927),1233=>array(46,-14,541,784),1234=>array(16,0,586,927),1235=>array(46,-14,541,774),1236=>array(0,0,576,729),1237=>array(7,-14,580,560),1238=>array(82,0,536,927),1239=>array(45,-14,561,784),1240=>array(45,-14,557,742),1241=>array(45,-14,561,560),1242=>array(45,-14,557,927),1243=>array(45,-14,561,762),1244=>array(6,0,596,927),1245=>array(7,0,596,762),1246=>array(61,-14,537,927),1247=>array(75,-11,527,762),1248=>array(5,-14,597,729),1249=>array(54,-215,548,547),1250=>array(58,0,543,913),1251=>array(74,0,533,760),1252=>array(58,0,543,927),1253=>array(74,0,533,762),1254=>array(45,-14,557,927),1255=>array(48,-14,554,762),1256=>array(45,-14,557,742),1257=>array(48,-14,554,560),1258=>array(45,-14,557,927),1259=>array(48,-14,554,762),1260=>array(74,-14,528,927),1261=>array(82,-14,518,762),1262=>array(14,0,588,913),1263=>array(29,-207,574,760),1264=>array(14,0,588,927),1265=>array(29,-207,574,762),1266=>array(14,0,588,927),1267=>array(29,-207,574,800),1268=>array(49,0,550,927),1269=>array(67,0,518,762),1270=>array(89,-157,543,729),1271=>array(108,-140,499,547),1272=>array(20,0,583,927),1273=>array(15,0,586,762),1296=>array(61,-14,537,742),1297=>array(73,-11,510,557),1306=>array(45,-137,557,742),1307=>array(44,-208,529,560),1308=>array(0,0,602,729),1309=>array(0,0,602,547),1329=>array(35,-31,567,729),1330=>array(48,0,554,743),1331=>array(16,0,585,743),1332=>array(16,0,585,743),1333=>array(48,-14,561,729),1334=>array(38,0,564,743),1335=>array(55,0,547,729),1336=>array(48,0,554,743),1337=>array(21,-14,581,743),1338=>array(16,-14,585,729),1339=>array(52,0,550,729),1340=>array(75,0,527,729),1341=>array(38,-13,564,729),1342=>array(17,-14,584,742),1343=>array(52,0,550,729),1344=>array(31,-37,571,729),1345=>array(35,-31,567,743),1346=>array(16,0,585,743),1347=>array(35,0,567,741),1348=>array(16,-14,585,729),1349=>array(24,-14,577,741),1350=>array(16,-14,585,729),1351=>array(37,-13,565,729),1352=>array(52,0,550,743),1353=>array(38,-39,564,743),1354=>array(25,0,577,741),1355=>array(35,0,566,741),1356=>array(16,0,585,743),1357=>array(52,-14,550,729),1358=>array(16,0,585,729),1359=>array(51,-14,550,742),1360=>array(52,0,550,743),1361=>array(24,-13,577,741),1362=>array(55,0,547,729),1363=>array(15,0,586,729),1364=>array(25,0,577,741),1365=>array(45,-14,557,742),1366=>array(15,-14,586,729),1369=>array(231,481,371,760),1370=>array(200,411,401,730),1371=>array(133,616,468,800),1372=>array(66,618,535,893),1373=>array(133,616,468,800),1374=>array(33,590,569,906),1375=>array(92,618,510,760),1377=>array(39,-13,563,547),1378=>array(73,-208,529,560),1379=>array(32,-208,570,560),1380=>array(50,-208,552,560),1381=>array(70,-14,532,760),1382=>array(32,-208,570,560),1383=>array(88,0,514,760),1384=>array(73,-208,529,560),1385=>array(26,-208,575,560),1386=>array(32,-14,570,760),1387=>array(82,-208,521,760),1388=>array(160,-208,442,547),1389=>array(39,-208,563,760),1390=>array(48,-14,554,760),1391=>array(81,-208,521,760),1392=>array(82,0,521,760),1393=>array(75,-14,527,760),1394=>array(50,-208,552,560),1395=>array(67,-14,534,741),1396=>array(81,-14,583,760),1397=>array(128,-207,474,547),1398=>array(50,-13,552,760),1399=>array(77,-208,525,559),1400=>array(82,0,521,560),1401=>array(110,-208,492,579),1402=>array(39,-208,563,547),1403=>array(67,-208,535,559),1404=>array(57,0,545,560),1405=>array(81,-14,521,547),1406=>array(47,-208,555,760),1407=>array(40,-13,562,560),1408=>array(82,-208,521,560),1409=>array(57,-207,544,561),1410=>array(92,0,510,547),1411=>array(40,-208,562,760),1412=>array(32,-208,570,560),1413=>array(48,-14,554,560),1414=>array(21,-208,581,760),1415=>array(22,-14,580,760),1417=>array(220,0,382,519),1418=>array(147,188,455,359),1542=>array(29,-19,578,928),1543=>array(29,-19,578,928),1545=>array(0,0,602,635),1546=>array(0,0,602,635),1548=>array(215,0,388,274),1557=>array(168,623,425,896),1563=>array(195,0,368,637),1567=>array(82,0,488,742),1569=>array(203,13,522,483),1570=>array(109,0,492,973),1571=>array(211,0,388,1041),1572=>array(37,-244,572,633),1573=>array(211,-329,388,760),1574=>array(0,-171,602,609),1575=>array(229,0,372,760),1576=>array(13,-172,597,263),1577=>array(86,-28,518,549),1578=>array(13,-18,597,427),1579=>array(13,-18,597,598),1580=>array(43,-244,584,444),1581=>array(43,-244,584,444),1582=>array(43,-244,584,623),1583=>array(113,-19,537,456),1584=>array(113,-19,537,658),1585=>array(-25,-246,565,267),1586=>array(-25,-246,565,481),1587=>array(-96,-240,602,366),1588=>array(-96,-240,602,671),1589=>array(-139,-240,594,319),1590=>array(-139,-240,594,449),1591=>array(5,0,588,760),1592=>array(5,0,588,760),1593=>array(35,-244,589,549),1594=>array(35,-244,589,701),1600=>array(-16,0,618,110),1601=>array(-52,-64,602,619),1602=>array(0,-230,602,696),1603=>array(4,-46,593,760),1604=>array(0,-181,568,760),1605=>array(29,-240,563,357),1606=>array(9,-162,586,464),1607=>array(86,-28,518,358),1608=>array(37,-244,572,330),1609=>array(0,-171,602,432),1610=>array(0,-323,602,432),1611=>array(148,563,453,854),1612=>array(111,552,456,884),1613=>array(148,-295,453,-4),1614=>array(148,563,453,729),1615=>array(146,580,456,884),1616=>array(148,-171,453,-4),1617=>array(124,591,478,869),1618=>array(154,597,448,891),1619=>array(109,580,492,743),1620=>array(211,573,388,820),1621=>array(211,-293,388,-47),1626=>array(152,616,449,775),1632=>array(221,189,382,373),1633=>array(178,0,424,684),1634=>array(61,0,563,684),1635=>array(30,0,583,684),1636=>array(84,-10,486,684),1637=>array(50,-22,553,684),1638=>array(32,0,570,684),1639=>array(44,0,560,684),1640=>array(44,0,560,684),1641=>array(60,0,561,684),1642=>array(66,0,536,635),1643=>array(132,-129,470,318),1644=>array(215,485,388,760),1645=>array(71,101,531,537),1652=>array(211,629,388,876),1657=>array(13,-18,597,604),1658=>array(13,-18,597,549),1659=>array(13,-357,597,263),1662=>array(13,-355,597,263),1663=>array(13,-18,597,600),1664=>array(13,-340,597,263),1667=>array(43,-244,584,444),1668=>array(43,-244,584,444),1670=>array(43,-244,586,444),1671=>array(43,-244,586,444),1681=>array(-25,-246,598,611),1688=>array(-25,-246,598,655),1700=>array(-52,-64,602,785),1705=>array(5,-60,670,803),1711=>array(5,-60,671,991),1726=>array(-46,-42,602,498),1740=>array(0,-171,602,432),1776=>array(221,189,382,373),1777=>array(178,0,424,684),1778=>array(61,0,563,684),1779=>array(30,0,583,684),1780=>array(30,0,550,684),1781=>array(37,-13,564,684),1782=>array(104,0,497,684),1783=>array(44,0,560,684),1784=>array(44,0,560,684),1785=>array(60,0,561,684),3713=>array(30,-10,556,560),3714=>array(53,-39,609,568),3716=>array(59,-10,561,568),3719=>array(70,-238,535,568),3720=>array(37,-0,565,575),3722=>array(35,-238,598,563),3725=>array(50,-14,552,560),3732=>array(60,-14,542,560),3733=>array(26,-15,576,579),3734=>array(13,-240,554,560),3735=>array(41,-8,562,571),3737=>array(37,-14,564,568),3738=>array(61,-8,541,561),3739=>array(61,-8,541,760),3740=>array(41,-8,623,648),3741=>array(41,-8,561,760),3742=>array(35,-8,566,561),3743=>array(35,-8,566,760),3745=>array(8,-14,564,547),3746=>array(50,-14,552,760),3747=>array(49,-8,566,568),3749=>array(30,-8,572,568),3751=>array(39,-13,559,560),3754=>array(30,-8,634,648),3755=>array(15,-12,582,575),3757=>array(43,-8,567,568),3758=>array(26,-8,606,617),3759=>array(0,-126,602,579),3760=>array(40,-6,571,567),3761=>array(40,620,571,896),3762=>array(52,0,550,588),3763=>array(-426,0,550,846),3764=>array(5,622,597,950),3765=>array(-52,633,615,962),3766=>array(4,622,597,950),3767=>array(4,633,671,962),3768=>array(176,-385,437,-55),3769=>array(129,-316,428,-28),3771=>array(-10,610,612,896),3772=>array(-4,-311,606,-48),3784=>array(243,659,359,844),3785=>array(-2,622,604,918),3786=>array(25,619,731,963),3787=>array(133,612,469,917),3788=>array(-4,603,606,866),3789=>array(176,639,426,846),4304=>array(48,0,555,567),4305=>array(49,0,554,758),4306=>array(39,-196,562,521),4307=>array(13,-197,589,516),4308=>array(47,-196,555,521),4309=>array(48,-196,555,521),4310=>array(48,0,555,757),4311=>array(13,0,589,516),4312=>array(48,0,555,521),4313=>array(48,-196,555,512),4314=>array(48,-196,555,521),4315=>array(49,0,555,757),4316=>array(48,0,555,745),4317=>array(13,0,589,516),4318=>array(48,0,555,754),4319=>array(47,-196,555,539),4320=>array(13,0,589,765),4321=>array(47,0,555,741),4322=>array(9,-197,593,656),4323=>array(11,-197,555,531),4324=>array(13,-196,589,521),4325=>array(48,-196,554,741),4326=>array(13,-197,589,521),4327=>array(49,-196,555,506),4328=>array(1,0,558,757),4329=>array(48,0,555,757),4330=>array(28,-196,574,539),4331=>array(48,0,555,741),4332=>array(46,0,602,757),4333=>array(48,-196,554,741),4334=>array(47,0,554,741),4335=>array(47,-196,555,610),4336=>array(48,0,555,757),4337=>array(48,-196,555,757),4338=>array(48,-134,555,521),4339=>array(47,-196,555,521),4340=>array(47,-196,555,757),4341=>array(53,0,575,757),4342=>array(13,-196,589,521),4343=>array(38,-197,564,521),4344=>array(48,-197,555,534),4345=>array(39,-196,563,527),4346=>array(62,-95,541,521),4347=>array(132,24,470,492),4348=>array(187,359,415,758),7426=>array(26,-14,599,560),7432=>array(50,-11,552,560),7433=>array(51,-264,550,549),7444=>array(7,-14,591,560),7446=>array(48,273,554,560),7447=>array(47,-14,554,273),7453=>array(20,0,581,440),7454=>array(20,-2,571,438),7455=>array(21,-0,581,523),7468=>array(121,326,480,734),7469=>array(119,326,482,734),7470=>array(142,326,460,735),7472=>array(146,326,455,734),7473=>array(158,326,444,734),7474=>array(158,326,444,734),7475=>array(146,318,457,742),7476=>array(153,326,448,734),7477=>array(164,326,438,734),7478=>array(163,318,439,734),7479=>array(131,326,472,734),7480=>array(158,326,443,734),7481=>array(138,326,464,734),7482=>array(148,326,454,734),7483=>array(148,326,454,734),7484=>array(140,318,462,742),7486=>array(149,326,452,734),7487=>array(132,326,470,734),7488=>array(139,326,463,734),7489=>array(145,318,458,734),7490=>array(111,326,490,734),7491=>array(145,318,457,640),7492=>array(145,318,457,640),7493=>array(148,318,454,640),7494=>array(121,318,481,640),7495=>array(148,318,454,751),7496=>array(148,318,454,751),7497=>array(139,318,463,640),7498=>array(139,318,463,640),7499=>array(143,320,459,640),7500=>array(143,320,459,640),7501=>array(147,210,455,640),7502=>array(144,178,458,633),7503=>array(144,326,458,751),7504=>array(136,326,466,640),7505=>array(163,210,439,640),7506=>array(142,318,460,640),7507=>array(164,318,438,640),7508=>array(142,479,460,640),7509=>array(142,318,460,479),7510=>array(148,209,454,640),7511=>array(153,326,449,719),7512=>array(163,318,439,632),7513=>array(125,326,478,573),7514=>array(136,319,466,632),7515=>array(136,326,466,632),7522=>array(144,0,458,455),7523=>array(167,0,436,314),7524=>array(163,-8,439,306),7525=>array(136,0,466,306),7543=>array(48,-207,535,561),7544=>array(153,326,448,734),7547=>array(52,0,551,547),7557=>array(44,-207,534,760),7579=>array(148,318,454,640),7580=>array(164,318,438,640),7581=>array(161,288,441,640),7582=>array(143,318,459,755),7583=>array(143,320,459,640),7584=>array(161,326,441,751),7585=>array(182,205,420,632),7586=>array(149,209,453,632),7587=>array(163,207,439,632),7588=>array(144,326,458,751),7589=>array(156,325,446,632),7590=>array(144,326,458,632),7591=>array(144,326,458,632),7592=>array(140,210,462,781),7593=>array(146,205,456,751),7594=>array(146,210,456,751),7595=>array(184,326,418,632),7596=>array(136,209,466,640),7597=>array(136,209,466,632),7598=>array(131,205,471,640),7599=>array(132,205,470,640),7600=>array(148,326,454,632),7601=>array(142,318,460,640),7602=>array(118,209,484,753),7603=>array(164,209,438,640),7604=>array(139,210,463,751),7605=>array(153,210,449,719),7606=>array(139,318,463,632),7607=>array(138,298,464,632),7609=>array(137,326,465,632),7610=>array(136,326,466,632),7611=>array(160,326,442,632),7612=>array(125,209,477,632),7613=>array(147,295,455,632),7614=>array(145,206,457,632),7615=>array(142,319,460,757),7680=>array(16,-245,586,729),7681=>array(46,-245,541,560),7682=>array(61,0,566,927),7683=>array(73,-14,558,774),7684=>array(61,-226,566,730),7685=>array(73,-226,558,760),7686=>array(61,-198,566,730),7687=>array(73,-198,558,760),7688=>array(74,-196,532,927),7689=>array(82,-196,555,800),7690=>array(67,0,557,927),7691=>array(44,-14,529,774),7692=>array(67,-226,557,729),7693=>array(44,-226,529,760),7694=>array(67,-198,557,729),7695=>array(44,-198,529,760),7696=>array(67,-196,557,729),7697=>array(44,-196,529,760),7698=>array(67,-237,557,729),7699=>array(44,-237,529,760),7704=>array(82,-237,536,729),7705=>array(45,-237,561,560),7706=>array(82,-238,536,729),7707=>array(45,-238,561,560),7708=>array(82,-196,536,927),7709=>array(45,-196,561,784),7710=>array(89,0,543,927),7711=>array(85,0,529,927),7712=>array(57,-14,552,913),7713=>array(48,-207,535,760),7714=>array(67,0,535,927),7715=>array(84,0,523,927),7716=>array(67,-226,535,729),7717=>array(84,-226,523,760),7718=>array(67,0,535,927),7719=>array(84,0,523,934),7720=>array(16,-196,535,729),7721=>array(33,-196,523,760),7722=>array(67,-240,535,729),7723=>array(84,-240,523,760),7724=>array(84,-238,518,729),7725=>array(70,-238,569,813),7728=>array(57,0,598,927),7729=>array(85,0,585,927),7730=>array(57,-226,598,729),7731=>array(85,-226,585,760),7732=>array(57,-198,598,729),7733=>array(85,-198,585,760),7734=>array(110,-226,562,729),7735=>array(44,-226,534,760),7736=>array(110,-226,562,913),7737=>array(44,-226,534,913),7738=>array(110,-198,562,729),7739=>array(44,-198,534,760),7740=>array(110,-237,562,729),7741=>array(44,-237,534,760),7742=>array(42,0,560,927),7743=>array(40,0,564,800),7744=>array(42,0,560,927),7745=>array(40,0,564,774),7746=>array(42,-226,560,729),7747=>array(40,-226,564,560),7748=>array(58,0,543,927),7749=>array(84,0,523,774),7750=>array(58,-226,543,729),7751=>array(84,-226,523,560),7752=>array(58,-198,543,729),7753=>array(84,-198,523,560),7754=>array(58,-237,543,729),7755=>array(84,-237,523,560),7756=>array(45,-14,557,997),7757=>array(48,-14,554,997),7764=>array(79,0,560,931),7765=>array(73,-208,558,800),7766=>array(79,0,560,927),7767=>array(73,-208,558,774),7768=>array(65,0,602,927),7769=>array(142,0,562,774),7770=>array(65,-226,602,729),7771=>array(142,-226,562,560),7772=>array(65,-226,602,913),7773=>array(142,-226,562,760),7774=>array(65,-198,602,729),7775=>array(142,-198,562,560),7776=>array(63,-14,542,927),7777=>array(84,-14,521,774),7778=>array(63,-226,542,742),7779=>array(84,-226,521,560),7784=>array(63,-226,542,927),7785=>array(84,-226,521,774),7786=>array(44,0,558,927),7787=>array(54,0,524,927),7788=>array(44,-226,558,729),7789=>array(54,-226,524,702),7790=>array(44,-198,558,729),7791=>array(54,-198,524,702),7792=>array(44,-237,558,729),7793=>array(54,-237,524,702),7794=>array(52,-226,550,729),7795=>array(78,-226,518,547),7796=>array(52,-238,550,729),7797=>array(78,-238,518,547),7798=>array(52,-237,550,729),7799=>array(78,-237,518,547),7800=>array(52,-14,550,997),7801=>array(78,-14,518,997),7804=>array(28,0,574,916),7805=>array(39,0,563,758),7806=>array(28,-226,574,729),7807=>array(39,-226,563,547),7808=>array(0,0,602,931),7809=>array(0,0,602,803),7810=>array(0,0,602,931),7811=>array(0,0,602,803),7812=>array(0,0,602,922),7813=>array(0,0,602,740),7814=>array(0,0,602,927),7815=>array(0,0,602,774),7816=>array(0,-226,602,729),7817=>array(0,-226,602,547),7818=>array(13,0,589,927),7819=>array(27,0,575,774),7820=>array(13,0,589,927),7821=>array(27,0,575,734),7822=>array(4,0,598,927),7823=>array(29,-207,574,774),7824=>array(56,0,567,931),7825=>array(79,0,528,803),7826=>array(56,-226,567,729),7827=>array(79,-226,528,547),7828=>array(56,-198,567,729),7829=>array(79,-198,528,547),7830=>array(84,-198,523,760),7831=>array(54,0,524,876),7832=>array(0,0,602,898),7833=>array(29,-207,574,898),7835=>array(85,0,529,927),7839=>array(48,-14,554,766),7840=>array(16,-226,586,729),7841=>array(46,-226,541,560),7852=>array(16,-226,586,931),7853=>array(46,-226,541,803),7856=>array(16,0,586,997),7857=>array(46,-14,541,954),7862=>array(16,-226,586,927),7863=>array(46,-226,541,759),7864=>array(82,-226,536,729),7865=>array(45,-226,561,560),7868=>array(82,0,536,928),7869=>array(45,-14,561,762),7878=>array(82,-226,536,931),7879=>array(45,-226,561,803),7882=>array(84,-226,518,729),7883=>array(70,-226,569,813),7884=>array(45,-226,557,742),7885=>array(48,-226,554,560),7896=>array(45,-226,557,931),7897=>array(48,-226,554,803),7898=>array(2,-14,600,927),7899=>array(4,-14,598,800),7900=>array(2,-14,600,927),7901=>array(4,-14,598,800),7904=>array(2,-14,600,928),7905=>array(4,-14,598,778),7906=>array(2,-226,600,759),7907=>array(4,-226,598,570),7908=>array(52,-226,550,729),7909=>array(78,-226,518,547),7912=>array(2,-14,600,927),7913=>array(3,-14,599,800),7914=>array(2,-14,600,927),7915=>array(3,-14,599,800),7918=>array(2,-14,600,928),7919=>array(3,-14,599,778),7920=>array(2,-226,600,759),7921=>array(3,-226,599,570),7922=>array(4,0,598,931),7923=>array(29,-207,574,803),7924=>array(4,-226,598,729),7925=>array(29,-226,574,547),7928=>array(4,0,598,928),7929=>array(29,-207,574,762),7936=>array(26,-12,568,806),7937=>array(26,-12,568,806),7938=>array(26,-12,568,806),7939=>array(26,-12,568,806),7940=>array(26,-12,568,806),7941=>array(26,-12,568,806),7942=>array(26,-12,568,978),7943=>array(26,-12,568,978),7944=>array(7,0,586,806),7945=>array(-17,0,586,806),7946=>array(-300,0,586,806),7947=>array(-305,0,586,806),7948=>array(-195,0,586,806),7949=>array(-225,0,586,806),7950=>array(-84,0,586,978),7951=>array(-108,0,586,978),7952=>array(73,-11,510,806),7953=>array(73,-11,510,806),7954=>array(71,-11,524,806),7955=>array(66,-11,529,806),7956=>array(73,-11,559,806),7957=>array(73,-11,568,806),7960=>array(-117,0,536,806),7961=>array(-117,0,536,806),7962=>array(-400,0,536,806),7963=>array(-405,0,536,806),7964=>array(-325,0,536,806),7965=>array(-349,0,536,806),7968=>array(84,-208,523,806),7969=>array(84,-208,523,806),7970=>array(71,-208,524,806),7971=>array(66,-208,529,806),7972=>array(84,-208,559,806),7973=>array(84,-208,568,806),7974=>array(84,-208,523,978),7975=>array(84,-208,523,978),7976=>array(-142,0,535,806),7977=>array(-142,0,535,806),7978=>array(-427,0,535,806),7979=>array(-432,0,535,806),7980=>array(-354,0,535,806),7981=>array(-374,0,535,806),7982=>array(-230,0,535,978),7983=>array(-230,0,535,978),7984=>array(132,0,478,806),7985=>array(132,0,478,806),7986=>array(71,0,524,806),7987=>array(66,0,529,806),7988=>array(120,0,559,806),7989=>array(100,0,568,806),7990=>array(131,0,478,978),7991=>array(131,0,478,978),7992=>array(-117,0,518,806),7993=>array(-117,0,518,806),7994=>array(-388,0,518,806),7995=>array(-403,0,518,806),7996=>array(-320,0,518,806),7997=>array(-344,0,518,806),7998=>array(-208,0,518,978),7999=>array(-208,0,518,978),8000=>array(48,-14,554,806),8001=>array(48,-14,554,806),8002=>array(48,-14,554,806),8003=>array(48,-14,554,806),8004=>array(48,-14,559,806),8005=>array(48,-14,568,806),8008=>array(-81,-14,557,806),8009=>array(-117,-14,557,806),8010=>array(-391,-14,557,806),8011=>array(-396,-14,557,806),8012=>array(-232,-14,557,806),8013=>array(-256,-14,557,806),8016=>array(37,0,565,806),8017=>array(37,0,565,806),8018=>array(37,0,565,806),8019=>array(37,0,565,806),8020=>array(37,0,565,806),8021=>array(37,0,568,806),8022=>array(37,0,565,978),8023=>array(37,0,565,978),8025=>array(-190,0,598,806),8027=>array(-447,0,598,806),8029=>array(-425,0,598,806),8031=>array(-287,0,598,978),8032=>array(31,-14,571,806),8033=>array(31,-14,571,806),8034=>array(31,-14,571,806),8035=>array(31,-14,571,806),8036=>array(31,-14,571,806),8037=>array(31,-14,571,806),8038=>array(31,-14,571,978),8039=>array(31,-14,571,978),8040=>array(-71,0,558,806),8041=>array(-105,0,558,806),8042=>array(-391,0,558,806),8043=>array(-396,0,558,806),8044=>array(-220,0,558,806),8045=>array(-239,0,558,806),8046=>array(-152,0,558,978),8047=>array(-189,0,558,978),8048=>array(26,-12,568,800),8049=>array(26,-12,568,800),8050=>array(73,-11,510,800),8051=>array(73,-11,510,800),8052=>array(84,-208,523,800),8053=>array(84,-208,523,800),8054=>array(97,0,478,800),8055=>array(132,0,505,800),8056=>array(48,-14,554,800),8057=>array(48,-14,554,800),8058=>array(37,0,565,800),8059=>array(37,0,565,800),8060=>array(31,-14,571,800),8061=>array(31,-14,571,800),8064=>array(26,-208,568,806),8065=>array(26,-208,568,806),8066=>array(26,-208,568,806),8067=>array(26,-208,568,806),8068=>array(26,-208,568,806),8069=>array(26,-208,568,806),8070=>array(26,-208,568,978),8071=>array(26,-208,568,978),8072=>array(7,-208,586,806),8073=>array(-17,-208,586,806),8074=>array(-300,-208,586,806),8075=>array(-305,-208,586,806),8076=>array(-195,-208,586,806),8077=>array(-225,-208,586,806),8078=>array(-84,-208,586,978),8079=>array(-108,-208,586,978),8080=>array(84,-208,523,806),8081=>array(84,-208,523,806),8082=>array(71,-208,524,806),8083=>array(66,-208,529,806),8084=>array(84,-208,559,806),8085=>array(84,-208,568,806),8086=>array(84,-208,523,978),8087=>array(84,-208,523,978),8088=>array(-142,-208,535,806),8089=>array(-142,-208,535,806),8090=>array(-427,-208,535,806),8091=>array(-432,-208,535,806),8092=>array(-354,-208,535,806),8093=>array(-374,-208,535,806),8094=>array(-230,-208,535,978),8095=>array(-230,-208,535,978),8096=>array(31,-208,571,806),8097=>array(31,-208,571,806),8098=>array(31,-208,571,806),8099=>array(31,-208,571,806),8100=>array(31,-208,571,806),8101=>array(31,-208,571,806),8102=>array(31,-208,571,978),8103=>array(31,-208,571,978),8104=>array(-71,-208,558,806),8105=>array(-105,-208,558,806),8106=>array(-391,-208,558,806),8107=>array(-396,-208,558,806),8108=>array(-220,-208,558,806),8109=>array(-239,-208,558,806),8110=>array(-152,-208,558,978),8111=>array(-189,-208,558,978),8112=>array(26,-12,568,784),8113=>array(26,-12,568,760),8114=>array(26,-208,568,800),8115=>array(26,-208,568,559),8116=>array(26,-208,568,800),8118=>array(26,-12,568,778),8119=>array(26,-208,568,778),8120=>array(16,0,586,927),8121=>array(16,0,586,913),8122=>array(-132,0,586,800),8123=>array(-40,0,586,800),8124=>array(16,-208,586,729),8125=>array(222,595,379,806),8126=>array(253,-208,383,-45),8127=>array(222,595,379,806),8128=>array(131,638,471,778),8129=>array(131,654,471,944),8130=>array(84,-208,523,800),8131=>array(84,-208,523,560),8132=>array(84,-208,523,800),8134=>array(84,-208,523,778),8135=>array(84,-208,523,778),8136=>array(-245,0,536,800),8137=>array(-171,0,536,800),8138=>array(-259,0,535,800),8139=>array(-191,0,535,800),8140=>array(67,-208,535,729),8141=>array(71,595,524,806),8142=>array(120,595,559,806),8143=>array(131,595,471,978),8144=>array(132,0,478,784),8145=>array(132,0,478,760),8146=>array(97,0,478,980),8147=>array(132,0,505,999),8150=>array(131,0,478,778),8151=>array(131,0,478,944),8152=>array(84,0,518,927),8153=>array(84,0,518,913),8154=>array(-230,0,518,800),8155=>array(-162,0,518,800),8157=>array(66,595,529,806),8158=>array(100,595,568,806),8159=>array(131,595,471,978),8160=>array(37,0,565,784),8161=>array(37,0,565,760),8162=>array(37,0,565,980),8163=>array(37,0,565,999),8164=>array(73,-208,558,806),8165=>array(73,-208,558,806),8166=>array(37,0,565,778),8167=>array(37,0,565,944),8168=>array(4,0,598,927),8169=>array(4,0,598,913),8170=>array(-269,0,598,800),8171=>array(-242,0,598,800),8172=>array(-127,0,560,806),8173=>array(97,654,455,980),8174=>array(147,654,505,999),8175=>array(97,616,373,800),8178=>array(31,-208,571,800),8179=>array(31,-208,571,547),8180=>array(31,-208,571,800),8182=>array(31,-14,571,778),8183=>array(31,-208,571,778),8184=>array(-223,-14,557,800),8185=>array(-83,-14,557,800),8186=>array(-218,0,558,800),8187=>array(-62,0,558,800),8188=>array(44,-208,558,713),8189=>array(229,616,505,800),8190=>array(222,595,379,806),8208=>array(147,217,455,359),8209=>array(147,217,455,359),8210=>array(0,217,602,337),8211=>array(0,217,602,337),8212=>array(0,217,602,337),8213=>array(0,217,602,337),8214=>array(125,-236,476,764),8215=>array(0,-236,602,-9),8216=>array(211,441,412,760),8217=>array(211,441,412,760),8218=>array(177,-140,378,179),8219=>array(211,441,412,760),8220=>array(74,441,528,760),8221=>array(73,441,528,760),8222=>array(73,-140,528,179),8223=>array(73,441,528,760),8224=>array(76,-96,525,729),8225=>array(76,-96,525,729),8226=>array(125,195,477,547),8227=>array(125,156,516,586),8230=>array(28,0,574,179),8240=>array(0,0,602,699),8241=>array(0,0,602,699),8242=>array(191,547,411,729),8243=>array(99,547,503,729),8244=>array(8,547,594,729),8245=>array(191,547,411,729),8246=>array(98,547,504,729),8247=>array(8,547,594,729),8249=>array(169,69,398,517),8250=>array(205,69,434,517),8252=>array(85,0,517,729),8253=>array(114,0,520,742),8254=>array(0,663,602,755),8261=>array(206,-132,454,760),8262=>array(148,-132,396,760),8263=>array(19,0,583,742),8264=>array(19,0,525,742),8265=>array(77,0,583,742),8267=>array(82,-96,568,729),8304=>array(136,319,466,742),8305=>array(144,326,458,781),8308=>array(120,326,456,734),8309=>array(143,319,461,734),8310=>array(140,318,471,742),8311=>array(139,326,454,734),8312=>array(138,319,463,742),8313=>array(130,319,461,742),8314=>array(132,352,470,652),8315=>array(132,469,470,535),8316=>array(139,407,464,596),8317=>array(218,252,384,751),8318=>array(218,252,384,751),8319=>array(161,326,441,640),8320=>array(136,-7,466,416),8321=>array(153,0,469,408),8322=>array(134,0,459,416),8323=>array(140,-7,470,416),8324=>array(120,0,456,408),8325=>array(143,-7,461,408),8326=>array(140,-8,471,416),8327=>array(139,0,454,408),8328=>array(138,-7,463,416),8329=>array(130,-7,461,416),8330=>array(132,25,470,326),8331=>array(132,143,470,208),8332=>array(139,81,464,270),8333=>array(218,-74,384,425),8334=>array(218,-74,384,425),8336=>array(145,-8,457,313),8337=>array(139,-8,463,313),8338=>array(142,-8,460,313),8339=>array(125,0,477,307),8340=>array(139,-8,463,313),8341=>array(161,0,441,426),8342=>array(144,0,458,425),8343=>array(144,0,458,426),8344=>array(136,0,466,313),8345=>array(161,0,441,313),8346=>array(148,-117,454,313),8347=>array(161,-7,441,314),8348=>array(153,0,449,393),8352=>array(0,0,595,729),8353=>array(43,-44,554,778),8354=>array(34,-14,551,742),8355=>array(0,0,544,729),8356=>array(54,0,541,742),8357=>array(19,-93,582,640),8358=>array(0,0,602,729),8359=>array(2,-14,601,729),8360=>array(4,-14,598,729),8361=>array(0,0,602,729),8362=>array(2,-14,601,729),8363=>array(29,-196,585,760),8364=>array(3,-14,526,742),8365=>array(24,0,584,729),8366=>array(2,0,601,729),8367=>array(4,-223,593,742),8368=>array(12,-14,590,742),8369=>array(29,0,602,729),8370=>array(21,-81,573,809),8371=>array(12,0,590,729),8372=>array(0,-14,602,742),8373=>array(22,-147,580,760),8376=>array(44,0,558,729),8377=>array(50,0,560,729),8450=>array(68,-14,524,742),8453=>array(3,-24,598,752),8461=>array(11,0,588,729),8462=>array(29,0,547,760),8463=>array(29,0,547,760),8469=>array(24,0,580,729),8470=>array(0,0,597,729),8471=>array(0,61,602,663),8473=>array(36,0,573,729),8474=>array(0,-146,598,742),8477=>array(4,0,597,729),8482=>array(0,447,550,729),8484=>array(6,0,584,729),8486=>array(44,0,558,713),8490=>array(57,0,598,729),8491=>array(16,0,586,928),8494=>array(0,-12,602,647),8520=>array(-9,0,501,813),8531=>array(23,-139,568,810),8532=>array(8,-139,568,818),8533=>array(23,-139,559,810),8534=>array(8,-139,559,818),8535=>array(14,-139,559,818),8536=>array(-6,-139,559,810),8537=>array(23,-140,569,810),8538=>array(17,-140,569,810),8539=>array(23,-139,562,810),8540=>array(14,-139,562,818),8541=>array(17,-139,562,810),8542=>array(13,-139,562,810),8543=>array(23,244,558,810),8592=>array(32,97,570,451),8593=>array(124,0,478,538),8594=>array(32,97,570,451),8595=>array(124,0,478,538),8596=>array(32,97,570,451),8597=>array(124,0,478,538),8598=>array(75,-10,522,437),8599=>array(80,-10,527,437),8600=>array(80,-15,526,432),8601=>array(75,-15,522,432),8602=>array(32,97,570,451),8603=>array(32,97,570,451),8604=>array(29,178,566,437),8605=>array(36,178,573,437),8606=>array(32,97,570,451),8607=>array(124,0,478,538),8608=>array(32,97,570,451),8609=>array(124,0,478,538),8610=>array(32,97,570,451),8611=>array(32,97,570,451),8612=>array(32,97,570,451),8613=>array(124,0,478,538),8614=>array(32,97,570,451),8615=>array(124,0,478,538),8616=>array(124,0,478,538),8617=>array(32,97,570,509),8618=>array(32,97,570,509),8619=>array(32,97,570,509),8620=>array(32,97,570,509),8621=>array(32,97,570,451),8622=>array(32,87,570,460),8623=>array(28,-2,562,700),8624=>array(89,0,527,689),8625=>array(75,0,513,689),8626=>array(89,-15,527,674),8627=>array(75,-15,513,674),8628=>array(91,0,526,555),8629=>array(31,-15,586,421),8630=>array(24,168,578,506),8631=>array(24,168,578,506),8632=>array(24,-10,578,542),8633=>array(32,-15,570,634),8634=>array(27,-19,575,511),8635=>array(27,-19,575,511),8636=>array(32,219,570,451),8637=>array(32,97,570,329),8638=>array(246,0,478,538),8639=>array(124,0,356,538),8640=>array(32,219,570,451),8641=>array(32,97,570,329),8642=>array(246,0,478,538),8643=>array(124,0,356,538),8644=>array(32,-15,570,575),8645=>array(6,0,596,538),8646=>array(32,-15,570,575),8647=>array(32,-15,570,575),8648=>array(6,0,596,538),8649=>array(32,-15,570,575),8650=>array(6,0,596,538),8651=>array(32,-15,570,575),8652=>array(32,-15,570,575),8653=>array(32,97,570,451),8654=>array(32,97,570,451),8655=>array(32,97,570,451),8656=>array(32,97,570,451),8657=>array(124,0,478,538),8658=>array(32,97,570,451),8659=>array(124,0,478,538),8660=>array(32,97,570,451),8661=>array(124,0,478,538),8662=>array(61,-28,526,437),8663=>array(76,-28,541,437),8664=>array(76,-15,541,451),8665=>array(61,-15,526,451),8666=>array(32,97,570,451),8667=>array(32,97,570,451),8668=>array(32,97,570,451),8669=>array(32,97,570,451),8670=>array(124,0,478,538),8671=>array(124,0,478,538),8672=>array(32,97,570,451),8673=>array(124,0,478,538),8674=>array(32,97,570,451),8675=>array(124,0,478,538),8676=>array(32,97,570,451),8677=>array(32,97,570,451),8678=>array(2,67,570,480),8679=>array(94,0,508,567),8680=>array(32,67,600,480),8681=>array(94,0,508,567),8682=>array(94,0,508,567),8683=>array(94,0,508,567),8684=>array(94,0,508,567),8685=>array(94,0,508,567),8686=>array(94,0,508,567),8687=>array(94,0,508,567),8688=>array(32,70,600,483),8689=>array(19,-10,578,549),8690=>array(21,0,581,559),8691=>array(94,0,508,567),8692=>array(32,97,570,451),8693=>array(6,0,596,538),8694=>array(32,-139,570,687),8695=>array(32,97,570,451),8696=>array(32,97,570,451),8697=>array(32,92,570,451),8698=>array(32,97,570,451),8699=>array(32,97,570,451),8700=>array(32,97,570,457),8701=>array(2,67,570,480),8702=>array(32,67,600,480),8703=>array(2,67,600,480),8704=>array(16,0,586,729),8705=>array(11,-14,592,742),8706=>array(58,-14,544,674),8707=>array(80,0,533,729),8708=>array(80,-46,533,775),8709=>array(31,43,572,584),8710=>array(-3,0,606,695),8711=>array(-3,0,606,695),8712=>array(49,0,553,744),8713=>array(49,-96,558,840),8714=>array(48,63,554,564),8715=>array(49,0,553,744),8716=>array(49,-96,558,840),8717=>array(48,63,554,564),8719=>array(74,-213,528,741),8721=>array(62,-213,539,741),8722=>array(32,256,569,372),8723=>array(43,0,559,627),8725=>array(55,-93,547,729),8727=>array(59,77,541,542),8728=>array(138,182,463,507),8729=>array(125,168,477,520),8730=>array(24,-19,573,843),8731=>array(24,-19,573,933),8732=>array(24,-19,573,924),8733=>array(86,109,516,508),8734=>array(6,109,596,508),8735=>array(43,122,559,638),8736=>array(43,122,559,638),8743=>array(89,0,513,579),8744=>array(89,0,513,579),8745=>array(89,0,513,579),8746=>array(89,0,513,579),8747=>array(71,-204,530,892),8748=>array(0,-204,602,892),8749=>array(-21,-204,623,892),8756=>array(72,51,532,580),8757=>array(72,51,530,580),8758=>array(219,51,383,580),8759=>array(72,51,532,580),8760=>array(32,256,569,619),8761=>array(36,51,578,580),8762=>array(23,26,581,603),8763=>array(43,0,559,624),8764=>array(43,229,559,398),8765=>array(43,229,559,398),8769=>array(43,48,559,577),8770=>array(43,124,559,482),8771=>array(43,144,559,498),8772=>array(43,16,560,637),8773=>array(43,29,559,614),8774=>array(43,-42,559,614),8775=>array(43,-70,559,695),8776=>array(43,124,559,498),8777=>array(43,30,559,596),8778=>array(43,29,559,587),8779=>array(43,12,559,587),8780=>array(43,29,559,614),8781=>array(42,83,559,543),8782=>array(43,10,559,617),8783=>array(43,144,559,617),8784=>array(43,144,559,707),8785=>array(43,-81,559,707),8786=>array(43,-81,559,707),8787=>array(43,-81,560,707),8788=>array(40,124,563,503),8789=>array(40,124,563,503),8790=>array(43,144,559,482),8791=>array(43,144,559,814),8792=>array(43,144,559,715),8793=>array(43,144,559,824),8794=>array(43,144,559,824),8795=>array(43,144,559,935),8796=>array(43,144,559,889),8797=>array(43,144,559,750),8798=>array(42,144,559,801),8799=>array(42,144,559,903),8800=>array(38,-5,564,631),8801=>array(43,29,559,597),8802=>array(43,-55,559,685),8803=>array(43,-47,559,688),8804=>array(43,0,559,582),8805=>array(43,0,559,582),8806=>array(43,-116,559,633),8807=>array(43,-116,559,633),8808=>array(43,-189,559,633),8809=>array(43,-189,559,633),8813=>array(42,-54,559,680),8814=>array(43,-3,559,629),8815=>array(43,-3,559,629),8816=>array(43,-96,559,658),8817=>array(43,-96,559,656),8818=>array(43,-38,559,582),8819=>array(43,-38,559,582),8820=>array(43,-96,559,658),8821=>array(43,-98,559,656),8822=>array(43,-119,559,684),8823=>array(43,-119,559,684),8824=>array(43,-209,559,774),8825=>array(43,-209,559,774),8826=>array(42,-46,558,672),8827=>array(42,-46,558,672),8828=>array(43,-206,559,744),8829=>array(43,-206,559,744),8830=>array(43,-101,559,744),8831=>array(43,-101,559,744),8832=>array(42,-118,558,744),8833=>array(42,-118,558,744),8834=>array(43,67,559,559),8835=>array(43,67,559,559),8836=>array(43,-58,559,684),8837=>array(43,-58,559,684),8838=>array(43,-20,559,645),8839=>array(43,-20,559,645),8840=>array(43,-115,559,729),8841=>array(43,-115,559,729),8842=>array(43,-125,559,645),8843=>array(43,-125,559,645),8847=>array(43,42,559,584),8848=>array(43,42,559,584),8849=>array(43,-10,559,636),8850=>array(43,-10,559,636),8853=>array(13,25,589,604),8854=>array(13,25,589,604),8855=>array(13,25,589,604),8856=>array(13,25,589,604),8857=>array(13,25,589,604),8858=>array(13,25,589,604),8859=>array(13,25,589,604),8860=>array(13,25,589,604),8861=>array(13,25,589,604),8862=>array(24,37,579,591),8863=>array(24,37,579,591),8864=>array(24,37,579,591),8865=>array(24,37,579,591),8866=>array(32,0,569,627),8867=>array(32,0,569,627),8868=>array(32,0,569,627),8869=>array(32,0,569,627),8901=>array(219,259,382,437),8902=>array(110,183,492,545),8909=>array(43,144,559,498),8922=>array(43,-272,559,776),8923=>array(43,-272,559,776),8924=>array(43,0,559,582),8925=>array(43,0,559,582),8926=>array(43,-206,559,744),8927=>array(43,-206,559,744),8928=>array(43,-244,559,803),8929=>array(43,-244,559,803),8930=>array(43,-143,559,769),8931=>array(43,-143,559,769),8932=>array(43,-123,559,636),8933=>array(43,-123,559,636),8934=>array(43,-158,559,582),8935=>array(43,-158,559,582),8936=>array(43,-220,559,744),8937=>array(43,-220,559,744),8943=>array(28,225,574,404),8960=>array(31,43,572,584),8961=>array(56,152,540,453),8962=>array(54,0,548,596),8963=>array(71,406,530,746),8964=>array(71,-132,530,209),8965=>array(71,0,530,459),8966=>array(71,0,530,581),8968=>array(206,-132,454,760),8969=>array(148,-132,396,760),8970=>array(206,-132,454,760),8971=>array(148,-132,396,760),8972=>array(261,73,585,415),8973=>array(6,73,331,415),8974=>array(261,345,585,687),8975=>array(6,345,331,687),8976=>array(43,177,559,439),8977=>array(35,113,567,646),8978=>array(3,211,599,512),8979=>array(3,211,599,512),8980=>array(90,168,512,512),8981=>array(76,107,510,539),8984=>array(17,95,585,664),8985=>array(43,177,559,439),8988=>array(131,352,463,701),8989=>array(139,352,471,701),8990=>array(131,-70,463,279),8991=>array(139,-70,471,279),8992=>array(237,-250,566,925),8993=>array(33,-239,362,940),8997=>array(31,95,571,613),8998=>array(3,145,599,536),8999=>array(46,145,556,536),9000=>array(24,212,578,517),9003=>array(3,145,599,536),9013=>array(25,-33,576,296),9015=>array(125,-114,477,843),9016=>array(3,-114,599,843),9017=>array(3,-114,599,843),9018=>array(3,-114,599,843),9019=>array(3,-114,599,843),9020=>array(3,-114,599,843),9021=>array(3,-171,599,900),9022=>array(3,57,599,658),9025=>array(3,-100,599,829),9026=>array(3,-100,599,829),9027=>array(3,-114,599,843),9028=>array(3,-114,599,843),9031=>array(3,-114,599,843),9032=>array(3,-114,599,843),9033=>array(3,-29,599,729),9035=>array(16,-171,586,900),9036=>array(3,-100,599,829),9037=>array(3,-100,599,829),9040=>array(3,-114,599,843),9042=>array(16,-171,586,900),9043=>array(3,-100,599,829),9044=>array(3,-100,599,829),9047=>array(3,-114,599,843),9048=>array(113,-114,489,729),9049=>array(3,-114,599,729),9050=>array(3,-114,599,655),9051=>array(113,-114,489,496),9052=>array(3,-114,599,658),9054=>array(3,-114,599,843),9055=>array(-10,44,612,671),9056=>array(3,-114,599,843),9059=>array(110,183,492,652),9060=>array(147,222,455,676),9061=>array(3,57,599,847),9064=>array(43,226,559,676),9065=>array(43,53,559,676),9067=>array(16,0,586,729),9068=>array(43,-14,559,742),9069=>array(43,-171,559,900),9070=>array(113,-140,489,519),9071=>array(3,-114,599,843),9072=>array(3,-114,599,843),9075=>array(132,0,478,547),9076=>array(73,-208,558,560),9077=>array(31,-14,571,547),9078=>array(3,-114,599,559),9079=>array(64,-114,538,561),9080=>array(113,-114,489,547),9081=>array(3,-114,599,547),9082=>array(26,-12,568,559),9085=>array(8,-232,594,101),9088=>array(25,-33,576,528),9089=>array(3,92,599,528),9090=>array(3,92,599,528),9091=>array(3,172,599,572),9096=>array(35,27,566,601),9097=>array(34,46,567,579),9098=>array(34,46,567,579),9099=>array(34,46,567,579),9109=>array(3,-114,599,843),9115=>array(113,-252,488,928),9116=>array(113,-252,255,940),9117=>array(113,-240,488,940),9118=>array(114,-252,489,928),9119=>array(347,-252,489,940),9120=>array(114,-240,489,940),9121=>array(113,-252,488,928),9122=>array(113,-252,255,940),9123=>array(113,-240,488,940),9124=>array(113,-252,488,928),9125=>array(346,-252,488,940),9126=>array(113,-240,488,940),9127=>array(232,-261,594,928),9128=>array(8,-247,370,934),9129=>array(232,-240,594,934),9130=>array(232,-256,370,934),9131=>array(8,-261,370,928),9132=>array(232,-247,594,934),9133=>array(8,-240,370,934),9134=>array(237,-250,362,940),9166=>array(2,67,570,567),9167=>array(3,0,599,596),9251=>array(54,-232,548,101),9600=>array(-10,260,612,770),9601=>array(-10,-250,612,-123),9602=>array(-10,-250,612,5),9603=>array(-10,-250,612,132),9604=>array(-10,-250,612,260),9605=>array(-10,-250,612,387),9606=>array(-10,-250,612,515),9607=>array(-10,-250,612,642),9608=>array(-10,-250,612,770),9609=>array(-10,-250,534,770),9610=>array(-10,-250,457,770),9611=>array(-10,-250,379,770),9612=>array(-10,-250,301,770),9613=>array(-10,-250,223,770),9614=>array(-10,-250,146,770),9615=>array(-10,-250,68,770),9616=>array(301,-250,612,770),9617=>array(-10,-250,534,770),9618=>array(-10,-250,612,770),9619=>array(-10,-250,612,770),9620=>array(-10,642,612,770),9621=>array(534,-250,611,770),9622=>array(-10,-250,301,260),9623=>array(301,-250,612,260),9624=>array(-10,260,301,770),9625=>array(-10,-250,612,770),9626=>array(-10,-250,612,770),9627=>array(-10,-250,612,770),9628=>array(-10,-250,612,770),9629=>array(301,260,612,770),9630=>array(-10,-250,612,770),9631=>array(-10,-250,612,770),9632=>array(3,-39,599,558),9633=>array(3,-39,599,558),9634=>array(3,-39,599,558),9635=>array(3,-39,599,558),9636=>array(3,-39,599,558),9637=>array(3,-39,599,558),9638=>array(3,-39,599,558),9639=>array(3,-39,599,558),9640=>array(3,-39,599,558),9641=>array(3,-39,599,558),9642=>array(107,66,495,454),9643=>array(107,66,495,454),9644=>array(3,117,599,402),9645=>array(3,117,599,402),9646=>array(158,-39,444,558),9647=>array(158,-39,444,558),9648=>array(3,117,599,402),9649=>array(3,117,599,402),9650=>array(3,-39,599,558),9651=>array(3,-39,599,558),9652=>array(107,66,495,454),9653=>array(107,66,495,454),9654=>array(3,-39,599,558),9655=>array(3,-39,599,558),9656=>array(107,66,495,454),9657=>array(107,66,495,454),9658=>array(3,66,599,454),9659=>array(3,66,599,454),9660=>array(3,-39,599,558),9661=>array(3,-39,599,558),9662=>array(107,66,495,454),9663=>array(107,66,495,454),9664=>array(3,-39,599,558),9665=>array(3,-39,599,558),9666=>array(107,66,495,454),9667=>array(107,66,495,454),9668=>array(3,66,599,454),9669=>array(3,66,599,454),9670=>array(3,-39,599,558),9671=>array(3,-38,599,558),9672=>array(3,-38,599,558),9673=>array(3,-41,599,561),9674=>array(57,-233,545,807),9675=>array(3,-41,599,561),9676=>array(3,-41,599,561),9677=>array(3,-41,599,561),9678=>array(3,-41,599,561),9679=>array(3,-41,599,561),9680=>array(3,-41,599,561),9681=>array(3,-41,599,561),9682=>array(3,-41,599,561),9683=>array(3,-41,599,561),9684=>array(3,-41,599,561),9685=>array(3,-41,599,561),9686=>array(152,-41,450,561),9687=>array(152,-41,450,561),9688=>array(-10,-10,612,770),9689=>array(-10,-250,612,770),9690=>array(-10,260,612,770),9691=>array(-10,-250,612,260),9692=>array(152,260,450,561),9693=>array(152,260,450,561),9694=>array(152,-41,450,260),9695=>array(152,-41,450,260),9696=>array(3,260,599,561),9697=>array(3,-41,599,260),9698=>array(3,-39,599,558),9699=>array(3,-39,599,558),9700=>array(3,-39,599,558),9701=>array(3,-39,599,558),9702=>array(125,195,477,547),9703=>array(3,-39,599,558),9704=>array(3,-39,599,558),9705=>array(3,-39,599,558),9706=>array(3,-39,599,558),9707=>array(3,-39,599,558),9708=>array(3,-39,599,558),9709=>array(3,-39,599,558),9710=>array(3,-39,599,558),9711=>array(-10,-54,612,573),9712=>array(3,-39,599,558),9713=>array(3,-39,599,558),9714=>array(3,-39,599,558),9715=>array(3,-39,599,558),9716=>array(3,-41,599,561),9717=>array(3,-41,599,561),9718=>array(3,-41,599,561),9719=>array(3,-41,599,561),9720=>array(3,-39,599,558),9721=>array(3,-39,599,558),9722=>array(3,-39,599,558),9723=>array(47,6,554,513),9724=>array(47,6,554,513),9725=>array(85,44,516,475),9726=>array(85,44,516,475),9727=>array(3,-39,599,558),9728=>array(17,80,585,649),9729=>array(26,3,576,225),9730=>array(17,3,585,522),9731=>array(43,-3,559,708),9732=>array(14,23,588,681),9733=>array(28,7,574,525),9734=>array(28,10,574,528),9735=>array(98,2,504,729),9736=>array(29,0,573,731),9737=>array(21,3,581,563),9738=>array(7,2,595,639),9739=>array(9,-1,593,677),9740=>array(26,0,576,724),9741=>array(22,1,580,724),9742=>array(10,-0,592,598),9743=>array(4,5,598,598),9744=>array(54,2,548,504),9745=>array(48,-1,554,512),9746=>array(65,2,537,481),9747=>array(98,43,504,658),9748=>array(14,-2,588,651),9749=>array(38,3,564,688),9750=>array(27,3,575,734),9751=>array(23,1,579,728),9752=>array(19,3,583,596),9753=>array(23,203,579,557),9754=>array(23,132,579,560),9755=>array(23,132,579,560),9756=>array(7,138,595,516),9757=>array(68,0,534,724),9758=>array(7,138,595,516),9759=>array(68,-3,534,720),9760=>array(6,-1,596,593),9761=>array(4,-2,598,728),9762=>array(4,1,598,595),9763=>array(17,3,585,523),9764=>array(38,-0,564,671),9765=>array(47,-0,555,730),9766=>array(59,-1,543,731),9767=>array(47,3,555,751),9768=>array(100,-2,502,725),9769=>array(27,0,575,549),9770=>array(15,1,587,644),9771=>array(4,0,598,594),9772=>array(50,-3,552,669),9773=>array(7,2,595,642),9774=>array(13,2,589,578),9775=>array(7,2,595,591),9784=>array(13,82,589,642),9785=>array(16,80,586,650),9786=>array(16,80,586,650),9787=>array(16,80,586,650),9788=>array(16,80,586,650),9789=>array(76,2,526,722),9790=>array(73,3,529,734),9791=>array(92,-78,510,708),9792=>array(71,-49,531,655),9793=>array(71,-49,531,655),9794=>array(10,75,592,648),9795=>array(35,21,567,710),9796=>array(85,21,517,710),9797=>array(33,65,569,666),9798=>array(37,65,565,666),9799=>array(105,21,497,710),9800=>array(12,0,590,641),9801=>array(26,-4,576,596),9802=>array(13,6,589,601),9803=>array(25,24,577,632),9804=>array(30,-1,572,641),9805=>array(23,-136,579,562),9806=>array(42,88,561,614),9807=>array(24,-75,578,597),9808=>array(27,3,575,597),9809=>array(10,1,592,601),9810=>array(43,156,559,460),9811=>array(46,2,556,642),9812=>array(33,2,569,563),9813=>array(42,0,560,560),9814=>array(55,0,547,639),9815=>array(108,-4,494,596),9816=>array(70,3,532,597),9817=>array(76,3,526,551),9818=>array(52,-2,550,518),9819=>array(26,2,576,596),9820=>array(72,2,530,596),9821=>array(110,3,492,597),9822=>array(50,1,552,641),9823=>array(58,2,544,597),9824=>array(63,65,540,664),9825=>array(7,65,595,663),9826=>array(71,65,531,664),9827=>array(24,65,578,664),9828=>array(62,65,540,664),9829=>array(5,65,597,664),9830=>array(71,65,531,664),9831=>array(24,65,578,667),9832=>array(22,3,580,597),9833=>array(181,16,421,708),9834=>array(79,16,523,708),9835=>array(52,-79,550,706),9836=>array(8,61,594,664),9837=>array(158,18,444,710),9838=>array(211,21,391,710),9839=>array(152,21,450,710),9840=>array(47,-1,555,639),9841=>array(22,-8,580,632),9842=>array(23,-2,579,538),9843=>array(29,5,573,527),9844=>array(37,4,565,514),9845=>array(33,5,569,521),9846=>array(18,3,584,549),9847=>array(30,4,572,525),9848=>array(37,0,565,509),9849=>array(22,6,580,543),9850=>array(22,0,580,537),9851=>array(28,-0,574,528),9852=>array(22,3,580,561),9853=>array(27,2,575,550),9854=>array(22,3,580,561),9855=>array(39,4,563,643),9856=>array(29,2,573,546),9857=>array(29,2,573,546),9858=>array(29,2,573,546),9859=>array(29,0,573,544),9860=>array(29,2,573,546),9861=>array(29,-2,573,542),9862=>array(22,0,580,557),9863=>array(22,2,580,559),9864=>array(22,0,580,557),9865=>array(22,-5,580,552),9866=>array(40,3,562,73),9867=>array(40,3,562,73),9872=>array(73,-1,529,591),9873=>array(56,2,546,640),9874=>array(19,-0,583,520),9875=>array(15,0,587,603),9876=>array(63,6,539,553),9877=>array(92,-1,510,740),9878=>array(9,1,593,558),9879=>array(11,3,591,552),9880=>array(36,-1,566,640),9881=>array(15,0,587,603),9882=>array(21,6,582,656),9883=>array(40,5,562,597),9884=>array(21,-1,582,638),9888=>array(17,1,585,520),9889=>array(66,4,536,642),9904=>array(119,0,484,730),9905=>array(108,0,494,594),9985=>array(22,181,580,494),9986=>array(22,170,580,505),9987=>array(28,156,574,462),9988=>array(30,161,572,501),9990=>array(25,35,577,588),9991=>array(18,31,584,598),9992=>array(30,29,572,544),9993=>array(31,56,571,448),9996=>array(158,5,444,614),9997=>array(22,73,580,498),9998=>array(42,64,560,581),9999=>array(19,109,583,346),10000=>array(42,91,560,608),10001=>array(29,146,573,420),10002=>array(18,133,584,388),10003=>array(74,94,528,561),10004=>array(36,56,566,532),10005=>array(63,55,539,531),10006=>array(31,92,540,601),10007=>array(64,-10,538,593),10008=>array(25,-1,577,646),10009=>array(31,2,571,542),10010=>array(42,3,560,503),10011=>array(28,3,574,550),10012=>array(23,0,579,556),10013=>array(76,1,520,640),10014=>array(62,0,541,639),10015=>array(70,2,532,595),10016=>array(23,1,579,558),10017=>array(35,1,567,616),10018=>array(15,-10,587,562),10019=>array(14,-8,588,567),10020=>array(13,-9,589,567),10021=>array(11,-13,591,566),10022=>array(21,-12,581,552),10023=>array(18,-13,584,557),10025=>array(20,-8,583,527),10026=>array(33,-13,569,526),10027=>array(20,-13,583,522),10028=>array(17,-11,585,529),10029=>array(20,-8,583,527),10030=>array(30,-2,572,514),10031=>array(20,-5,583,531),10032=>array(22,8,580,502),10033=>array(26,-1,576,563),10034=>array(42,-0,560,547),10035=>array(23,-1,579,554),10036=>array(18,-8,584,560),10037=>array(13,-11,589,565),10038=>array(24,-14,578,625),10039=>array(15,-16,587,556),10040=>array(13,-11,589,565),10041=>array(18,-17,584,551),10042=>array(23,1,579,557),10043=>array(24,-8,578,613),10044=>array(27,-9,575,606),10045=>array(25,-10,573,609),10046=>array(16,-13,586,592),10047=>array(18,0,584,551),10048=>array(11,1,591,565),10049=>array(11,-9,591,572),10050=>array(18,-16,584,552),10051=>array(24,-9,578,653),10052=>array(16,1,586,667),10053=>array(23,-3,579,587),10054=>array(12,2,590,594),10055=>array(24,-9,578,605),10056=>array(20,-10,582,552),10057=>array(16,-14,586,556),10058=>array(11,-11,591,569),10059=>array(17,-11,585,513),10061=>array(18,-5,584,527),10063=>array(34,-31,568,504),10064=>array(30,0,572,542),10065=>array(27,-35,575,512),10066=>array(23,0,579,555),10070=>array(21,-3,581,557),10072=>array(263,-119,339,701),10073=>array(225,-120,377,700),10074=>array(165,-151,438,677),10075=>array(233,476,369,731),10076=>array(228,471,374,722),10077=>array(125,476,477,731),10078=>array(120,471,482,722),10081=>array(50,-80,552,688),10082=>array(125,-19,478,598),10083=>array(93,-14,509,603),10084=>array(22,51,580,507),10085=>array(56,-2,546,637),10086=>array(32,12,570,567),10087=>array(24,150,578,472),10088=>array(117,-49,485,688),10089=>array(117,-49,485,688),10090=>array(175,-59,427,665),10091=>array(179,-59,423,643),10092=>array(158,-64,444,667),10093=>array(158,-64,444,667),10094=>array(103,-83,500,647),10095=>array(103,-83,500,647),10096=>array(100,-93,502,727),10097=>array(101,-93,501,728),10098=>array(223,-138,379,683),10099=>array(223,-135,379,686),10100=>array(137,-160,465,671),10101=>array(122,-164,480,676),10132=>array(41,148,562,487),10136=>array(57,71,545,561),10137=>array(41,204,562,509),10138=>array(57,94,545,583),10139=>array(22,204,580,485),10140=>array(36,145,566,530),10141=>array(41,214,562,519),10142=>array(22,184,580,510),10143=>array(26,182,576,503),10144=>array(41,201,562,505),10145=>array(41,189,562,494),10146=>array(47,182,555,512),10147=>array(60,205,542,518),10148=>array(60,140,542,592),10149=>array(26,193,576,530),10150=>array(26,193,576,529),10151=>array(164,128,438,609),10152=>array(26,179,576,500),10153=>array(49,177,553,516),10154=>array(49,148,553,487),10155=>array(26,89,576,498),10156=>array(47,104,555,458),10157=>array(61,107,541,538),10158=>array(41,63,561,530),10159=>array(24,163,578,557),10161=>array(20,124,582,524),10162=>array(71,92,531,584),10163=>array(43,163,559,386),10164=>array(57,90,545,579),10165=>array(41,227,562,427),10166=>array(57,63,545,552),10167=>array(38,90,564,616),10168=>array(21,192,582,409),10169=>array(57,85,545,574),10170=>array(26,146,576,490),10171=>array(14,179,588,461),10172=>array(19,218,583,456),10173=>array(18,174,583,493),10174=>array(24,131,578,462),10175=>array(41,148,562,487),10178=>array(32,0,569,627),10181=>array(125,-163,477,769),10182=>array(125,-163,477,769),10208=>array(57,-233,545,807),10214=>array(145,-132,479,760),10215=>array(124,-132,457,760),10216=>array(165,-132,438,759),10217=>array(165,-132,438,759),10731=>array(57,-233,545,807),10746=>array(32,45,569,582),10747=>array(32,45,569,582),10799=>array(58,72,543,556),10858=>array(43,229,559,624),10859=>array(43,0,559,624),11013=>array(41,190,561,494),11014=>array(149,82,453,602),11015=>array(149,82,453,602),11016=>array(68,109,485,526),11017=>array(117,109,534,526),11018=>array(117,109,534,526),11019=>array(68,109,485,526),11020=>array(41,190,561,494),11021=>array(149,82,453,602),11026=>array(3,-39,599,558),11027=>array(3,-39,599,558),11028=>array(3,-39,599,558),11029=>array(3,-39,599,558),11030=>array(3,-39,599,558),11031=>array(3,-39,599,558),11032=>array(3,-39,599,558),11033=>array(3,-39,599,558),11034=>array(3,-39,599,558),11364=>array(65,-208,602,729),11373=>array(47,-14,562,742),11374=>array(42,-208,560,729),11375=>array(16,0,586,729),11376=>array(47,-14,562,742),11381=>array(67,0,535,729),11382=>array(84,0,523,547),11383=>array(32,0,570,552),11385=>array(91,-13,511,759),11386=>array(48,-14,554,560),11388=>array(190,-149,412,421),11389=>array(129,326,473,734),11390=>array(63,-239,575,742),11391=>array(56,-240,567,729),11800=>array(85,-13,491,729),11807=>array(43,0,559,398),11810=>array(206,403,454,760),11811=>array(148,403,396,760),11812=>array(206,-132,454,225),11813=>array(148,-132,396,225),11822=>array(82,0,488,742),42760=>array(134,0,468,693),42761=>array(134,0,468,693),42762=>array(134,0,468,693),42763=>array(134,0,468,693),42764=>array(134,0,468,693),42765=>array(134,0,468,693),42766=>array(134,0,468,693),42767=>array(134,0,468,693),42768=>array(134,0,468,693),42769=>array(134,0,468,693),42770=>array(134,0,468,693),42771=>array(134,0,468,693),42772=>array(134,0,468,693),42773=>array(134,0,468,693),42774=>array(134,0,468,693),42779=>array(159,326,443,736),42780=>array(159,324,443,734),42781=>array(245,326,356,734),42782=>array(245,326,356,734),42783=>array(245,0,356,408),42786=>array(125,0,492,729),42787=>array(160,0,467,547),42788=>array(90,224,514,742),42789=>array(90,42,514,560),42790=>array(67,-208,535,729),42791=>array(84,-207,523,760),42889=>array(219,0,382,519),42890=>array(191,141,411,405),42891=>array(236,235,366,729),42892=>array(238,458,363,729),42893=>array(49,0,550,760),42894=>array(53,-217,549,760),42896=>array(39,-157,574,729),42897=>array(47,-140,563,560),42922=>array(0,0,601,730),63173=>array(48,-14,554,760),64257=>array(6,0,536,760),64258=>array(6,0,536,760),64338=>array(13,-338,597,263),64339=>array(34,-338,612,264),64340=>array(-18,-324,366,293),64341=>array(-16,-311,618,313),64342=>array(13,-338,597,263),64343=>array(34,-338,612,264),64344=>array(-18,-322,437,293),64345=>array(-16,-322,618,313),64346=>array(13,-352,597,263),64347=>array(34,-328,612,264),64348=>array(-18,-326,420,293),64349=>array(-16,-328,618,313),64350=>array(13,-18,597,574),64351=>array(34,-10,612,565),64352=>array(-18,0,366,634),64353=>array(-16,0,618,650),64354=>array(13,-18,597,600),64355=>array(34,-10,612,604),64356=>array(-18,0,435,654),64357=>array(-16,0,618,671),64358=>array(13,-18,597,608),64359=>array(34,-10,612,628),64360=>array(-18,0,428,658),64361=>array(-16,0,618,656),64362=>array(-52,-64,602,766),64363=>array(-87,-47,612,750),64364=>array(-10,0,430,833),64365=>array(-10,0,612,761),64366=>array(-52,-64,602,774),64367=>array(-87,-47,612,754),64368=>array(-10,0,430,823),64369=>array(-10,0,612,751),64370=>array(43,-244,584,444),64371=>array(0,-350,622,339),64372=>array(-10,-313,545,423),64373=>array(-10,-269,623,423),64374=>array(43,-244,584,444),64375=>array(0,-350,622,339),64376=>array(-10,-152,545,423),64377=>array(-10,-133,623,423),64378=>array(43,-244,584,444),64379=>array(0,-350,622,339),64380=>array(-10,-321,545,423),64381=>array(-10,-312,623,423),64382=>array(43,-244,584,444),64383=>array(0,-350,622,339),64384=>array(-10,-308,545,423),64385=>array(-10,-312,623,423),64394=>array(-25,-246,603,627),64395=>array(-78,-244,612,627),64396=>array(-25,-246,591,612),64397=>array(-78,-244,612,626),64398=>array(5,-60,670,803),64399=>array(-71,-60,626,803),64400=>array(-10,0,521,760),64401=>array(-15,0,620,760),64402=>array(5,-60,673,998),64403=>array(-71,-60,631,1000),64404=>array(-10,0,521,962),64405=>array(-15,0,620,962),64414=>array(9,-162,586,336),64415=>array(-42,-242,612,256),64426=>array(-46,-42,602,498),64427=>array(-46,0,654,498),64428=>array(-10,-42,525,498),64429=>array(-19,0,654,498),64488=>array(-18,0,366,293),64489=>array(-16,0,618,313),64508=>array(0,-171,602,432),64509=>array(-39,-172,612,271),64510=>array(-18,-146,431,293),64511=>array(-16,-146,618,313),65136=>array(148,563,453,854),65137=>array(-16,0,618,854),65138=>array(111,552,456,884),65139=>array(339,0,612,197),65140=>array(148,-295,453,-4),65142=>array(148,563,453,729),65143=>array(-16,0,618,729),65144=>array(146,580,456,884),65145=>array(-16,0,618,884),65146=>array(148,-171,453,-4),65147=>array(-16,-171,618,110),65148=>array(124,591,478,869),65149=>array(-16,0,618,869),65150=>array(154,597,448,891),65151=>array(-16,0,618,891),65152=>array(203,13,522,483),65153=>array(109,0,492,963),65154=>array(109,0,612,963),65155=>array(207,0,383,1040),65156=>array(230,0,612,1040),65157=>array(37,-244,572,620),65158=>array(0,-244,612,618),65159=>array(208,-293,384,760),65160=>array(253,-293,612,760),65161=>array(0,-171,602,599),65162=>array(-39,-172,612,433),65163=>array(-18,0,377,625),65164=>array(-16,0,618,625),65165=>array(229,0,372,760),65166=>array(263,0,612,760),65167=>array(13,-171,597,263),65168=>array(34,-171,612,264),65169=>array(-18,-186,366,293),65170=>array(-16,-195,618,313),65171=>array(86,-28,518,551),65172=>array(42,0,612,622),65173=>array(13,-18,597,427),65174=>array(34,-10,612,427),65175=>array(-18,0,431,525),65176=>array(-16,0,618,525),65177=>array(13,-18,597,598),65178=>array(34,-10,612,598),65179=>array(-18,0,430,696),65180=>array(-16,0,618,677),65181=>array(43,-244,584,444),65182=>array(43,-244,622,444),65183=>array(-10,-146,545,423),65184=>array(-10,-146,623,423),65185=>array(43,-244,584,444),65186=>array(43,-244,622,444),65187=>array(-10,0,545,423),65188=>array(-10,0,623,423),65189=>array(43,-244,584,623),65190=>array(43,-244,622,623),65191=>array(-10,0,545,609),65192=>array(-10,0,623,574),65193=>array(113,-19,537,456),65194=>array(113,-19,612,456),65195=>array(113,-19,537,648),65196=>array(113,-19,612,660),65197=>array(-25,-246,565,267),65198=>array(-78,-244,612,269),65199=>array(-25,-246,565,491),65200=>array(-78,-244,612,499),65201=>array(-96,-240,602,366),65202=>array(-129,-240,614,366),65203=>array(-10,-14,602,366),65204=>array(-10,-14,613,366),65205=>array(-96,-240,602,671),65206=>array(-129,-240,614,671),65207=>array(-10,-14,602,671),65208=>array(-10,-14,613,671),65209=>array(-139,-240,594,319),65210=>array(-166,-240,615,319),65211=>array(-16,0,594,319),65212=>array(-16,0,618,319),65213=>array(-139,-240,594,437),65214=>array(-166,-240,615,437),65215=>array(-16,0,594,469),65216=>array(-16,0,618,462),65217=>array(5,0,588,760),65218=>array(0,0,612,760),65219=>array(-23,0,588,760),65220=>array(-18,0,612,760),65221=>array(5,0,588,760),65222=>array(0,0,612,760),65223=>array(-23,0,588,760),65224=>array(-18,0,612,760),65225=>array(35,-244,589,549),65226=>array(41,-244,619,396),65227=>array(-10,0,497,545),65228=>array(-10,0,612,396),65229=>array(35,-244,589,710),65230=>array(41,-244,619,574),65231=>array(-10,0,497,696),65232=>array(-10,0,612,574),65233=>array(-52,-64,602,630),65234=>array(-87,-47,612,578),65235=>array(-10,0,430,681),65236=>array(-10,0,612,598),65237=>array(0,-230,602,696),65238=>array(-9,-240,612,552),65239=>array(-10,0,430,671),65240=>array(-10,0,612,598),65241=>array(4,-46,593,760),65242=>array(-49,-46,621,760),65243=>array(-10,0,521,760),65244=>array(-15,0,620,760),65245=>array(0,-181,568,760),65246=>array(-37,-181,622,760),65247=>array(-10,0,513,760),65248=>array(-10,0,612,760),65249=>array(29,-240,563,357),65250=>array(0,-240,612,330),65251=>array(-15,-23,519,326),65252=>array(-15,-23,612,326),65253=>array(9,-162,586,480),65254=>array(-42,-242,612,382),65255=>array(-18,0,366,525),65256=>array(-16,0,618,525),65257=>array(86,-28,518,358),65258=>array(42,0,612,436),65259=>array(-10,-42,525,498),65260=>array(-10,-263,612,373),65261=>array(37,-244,572,330),65262=>array(0,-244,612,330),65263=>array(0,-171,602,432),65264=>array(-39,-172,612,271),65265=>array(0,-323,602,432),65266=>array(-39,-326,612,271),65267=>array(-18,-176,430,293),65268=>array(-16,-178,618,313),65269=>array(-67,-10,541,890),65270=>array(-72,-10,612,890),65271=>array(-8,-10,541,966),65272=>array(-21,-10,612,966),65273=>array(53,-320,541,760),65274=>array(53,-333,612,760),65275=>array(53,-10,541,760),65276=>array(53,-10,612,760),65533=>array(22,-138,579,927),65535=>array(51,-177,551,705)); -$cw=array(0=>602,32=>602,33=>602,34=>602,35=>602,36=>602,37=>602,38=>602,39=>602,40=>602,41=>602,42=>602,43=>602,44=>602,45=>602,46=>602,47=>602,48=>602,49=>602,50=>602,51=>602,52=>602,53=>602,54=>602,55=>602,56=>602,57=>602,58=>602,59=>602,60=>602,61=>602,62=>602,63=>602,64=>602,65=>602,66=>602,67=>602,68=>602,69=>602,70=>602,71=>602,72=>602,73=>602,74=>602,75=>602,76=>602,77=>602,78=>602,79=>602,80=>602,81=>602,82=>602,83=>602,84=>602,85=>602,86=>602,87=>602,88=>602,89=>602,90=>602,91=>602,92=>602,93=>602,94=>602,95=>602,96=>602,97=>602,98=>602,99=>602,100=>602,101=>602,102=>602,103=>602,104=>602,105=>602,106=>602,107=>602,108=>602,109=>602,110=>602,111=>602,112=>602,113=>602,114=>602,115=>602,116=>602,117=>602,118=>602,119=>602,120=>602,121=>602,122=>602,123=>602,124=>602,125=>602,126=>602,160=>602,161=>602,162=>602,163=>602,164=>602,165=>602,166=>602,167=>602,168=>602,169=>602,170=>602,171=>602,172=>602,173=>602,174=>602,175=>602,176=>602,177=>602,178=>602,179=>602,180=>602,181=>602,182=>602,183=>602,184=>602,185=>602,186=>602,187=>602,188=>602,189=>602,190=>602,191=>602,192=>602,193=>602,194=>602,195=>602,196=>602,197=>602,198=>602,199=>602,200=>602,201=>602,202=>602,203=>602,204=>602,205=>602,206=>602,207=>602,208=>602,209=>602,210=>602,211=>602,212=>602,213=>602,214=>602,215=>602,216=>602,217=>602,218=>602,219=>602,220=>602,221=>602,222=>602,223=>602,224=>602,225=>602,226=>602,227=>602,228=>602,229=>602,230=>602,231=>602,232=>602,233=>602,234=>602,235=>602,236=>602,237=>602,238=>602,239=>602,240=>602,241=>602,242=>602,243=>602,244=>602,245=>602,246=>602,247=>602,248=>602,249=>602,250=>602,251=>602,252=>602,253=>602,254=>602,255=>602,256=>602,257=>602,258=>602,259=>602,260=>602,261=>602,262=>602,263=>602,264=>602,265=>602,266=>602,267=>602,268=>602,269=>602,270=>602,271=>602,272=>602,273=>602,274=>602,275=>602,276=>602,277=>602,278=>602,279=>602,280=>602,281=>602,282=>602,283=>602,284=>602,285=>602,286=>602,287=>602,288=>602,289=>602,290=>602,291=>602,292=>602,293=>602,294=>602,295=>602,296=>602,297=>602,298=>602,299=>602,300=>602,301=>602,302=>602,303=>602,304=>602,305=>602,306=>602,307=>602,308=>602,309=>602,310=>602,311=>602,312=>602,313=>602,314=>602,315=>602,316=>602,317=>602,318=>602,319=>602,320=>602,321=>602,322=>602,323=>602,324=>602,325=>602,326=>602,327=>602,328=>602,329=>602,330=>602,331=>602,332=>602,333=>602,334=>602,335=>602,336=>602,337=>602,338=>602,339=>602,340=>602,341=>602,342=>602,343=>602,344=>602,345=>602,346=>602,347=>602,348=>602,349=>602,350=>602,351=>602,352=>602,353=>602,354=>602,355=>602,356=>602,357=>602,358=>602,359=>602,360=>602,361=>602,362=>602,363=>602,364=>602,365=>602,366=>602,367=>602,368=>602,369=>602,370=>602,371=>602,372=>602,373=>602,374=>602,375=>602,376=>602,377=>602,378=>602,379=>602,380=>602,381=>602,382=>602,383=>602,384=>602,385=>602,386=>602,387=>602,388=>602,389=>602,390=>602,391=>602,392=>602,393=>602,394=>602,395=>602,396=>602,397=>602,398=>602,399=>602,400=>602,401=>602,402=>602,403=>602,404=>602,405=>602,406=>602,407=>602,408=>602,409=>602,410=>602,411=>602,412=>602,413=>602,414=>602,415=>602,416=>602,417=>602,418=>602,419=>602,420=>602,421=>602,422=>602,423=>602,424=>602,425=>602,426=>602,427=>602,428=>602,429=>602,430=>602,431=>602,432=>602,433=>602,434=>602,435=>602,436=>602,437=>602,438=>602,439=>602,440=>602,441=>602,442=>602,443=>602,444=>602,445=>602,446=>602,447=>602,448=>602,449=>602,450=>602,451=>602,461=>602,462=>602,463=>602,464=>602,465=>602,466=>602,467=>602,468=>602,469=>602,470=>602,471=>602,472=>602,473=>602,474=>602,475=>602,476=>602,477=>602,478=>602,479=>602,480=>602,481=>602,482=>602,483=>602,486=>602,487=>602,488=>602,489=>602,490=>602,491=>602,492=>602,493=>602,494=>602,495=>602,496=>602,500=>602,501=>602,502=>602,504=>602,505=>602,508=>602,509=>602,510=>602,511=>602,512=>602,513=>602,514=>602,515=>602,516=>602,517=>602,518=>602,519=>602,520=>602,521=>602,522=>602,523=>602,524=>602,525=>602,526=>602,527=>602,528=>602,529=>602,530=>602,531=>602,532=>602,533=>602,534=>602,535=>602,536=>602,537=>602,538=>602,539=>602,540=>602,541=>602,542=>602,543=>602,544=>602,545=>602,548=>602,549=>602,550=>602,551=>602,552=>602,553=>602,554=>602,555=>602,556=>602,557=>602,558=>602,559=>602,560=>602,561=>602,562=>602,563=>602,564=>602,565=>602,566=>602,567=>602,568=>602,569=>602,570=>602,571=>602,572=>602,573=>602,574=>602,575=>602,576=>602,577=>602,579=>602,580=>602,581=>602,588=>602,589=>602,592=>602,593=>602,594=>602,595=>602,596=>602,597=>602,598=>602,599=>602,600=>602,601=>602,602=>602,603=>602,604=>602,605=>602,606=>602,607=>602,608=>602,609=>602,610=>602,611=>602,612=>602,613=>602,614=>602,615=>602,616=>602,617=>602,618=>602,619=>602,620=>602,621=>602,622=>602,623=>602,624=>602,625=>602,626=>602,627=>602,628=>602,629=>602,630=>602,631=>602,632=>602,633=>602,634=>602,635=>602,636=>602,637=>602,638=>602,639=>602,640=>602,641=>602,642=>602,643=>602,644=>602,645=>602,646=>602,647=>602,648=>602,649=>602,650=>602,651=>602,652=>602,653=>602,654=>602,655=>602,656=>602,657=>602,658=>602,659=>602,660=>602,661=>602,662=>602,663=>602,664=>602,665=>602,666=>602,667=>602,668=>602,669=>602,670=>602,671=>602,672=>602,673=>602,674=>602,675=>602,676=>602,677=>602,678=>602,679=>602,680=>602,681=>602,682=>602,683=>602,684=>602,685=>602,686=>602,687=>602,688=>602,689=>602,690=>602,691=>602,692=>602,693=>602,694=>602,695=>602,696=>602,697=>602,699=>602,700=>602,701=>602,702=>602,703=>602,704=>602,705=>602,710=>602,711=>602,712=>602,713=>602,716=>602,717=>602,718=>602,719=>602,720=>602,721=>602,722=>602,723=>602,726=>602,727=>602,728=>602,729=>602,730=>602,731=>602,732=>602,733=>602,734=>602,736=>602,737=>602,738=>602,739=>602,740=>602,741=>602,742=>602,743=>602,744=>602,745=>602,750=>602,755=>602,768=>602,769=>602,770=>602,771=>602,772=>602,773=>602,774=>602,775=>602,776=>602,777=>602,778=>602,779=>602,780=>602,781=>602,782=>602,783=>602,784=>602,785=>602,786=>602,787=>602,788=>602,789=>602,790=>602,791=>602,792=>602,793=>602,794=>602,795=>602,796=>602,797=>602,798=>602,799=>602,800=>602,801=>602,802=>602,803=>602,804=>602,805=>602,806=>602,807=>602,808=>602,809=>602,810=>602,811=>602,812=>602,813=>602,814=>602,815=>602,816=>602,817=>602,818=>602,819=>602,820=>602,821=>602,822=>602,823=>602,824=>602,825=>602,826=>602,827=>602,828=>602,829=>602,830=>602,831=>602,835=>602,856=>602,865=>602,884=>602,885=>602,890=>602,894=>602,900=>602,901=>602,902=>602,903=>602,904=>602,905=>602,906=>602,908=>602,910=>602,911=>602,912=>602,913=>602,914=>602,915=>602,916=>602,917=>602,918=>602,919=>602,920=>602,921=>602,922=>602,923=>602,924=>602,925=>602,926=>602,927=>602,928=>602,929=>602,931=>602,932=>602,933=>602,934=>602,935=>602,936=>602,937=>602,938=>602,939=>602,940=>602,941=>602,942=>602,943=>602,944=>602,945=>602,946=>602,947=>602,948=>602,949=>602,950=>602,951=>602,952=>602,953=>602,954=>602,955=>602,956=>602,957=>602,958=>602,959=>602,960=>602,961=>602,962=>602,963=>602,964=>602,965=>602,966=>602,967=>602,968=>602,969=>602,970=>602,971=>602,972=>602,973=>602,974=>602,976=>602,977=>602,978=>602,979=>602,980=>602,981=>602,982=>602,983=>602,984=>602,985=>602,986=>602,987=>602,988=>602,989=>602,990=>602,991=>602,992=>602,993=>602,1008=>602,1009=>602,1010=>602,1011=>602,1012=>602,1013=>602,1014=>602,1015=>602,1016=>602,1017=>602,1018=>602,1019=>602,1020=>602,1021=>602,1022=>602,1023=>602,1024=>602,1025=>602,1026=>602,1027=>602,1028=>602,1029=>602,1030=>602,1031=>602,1032=>602,1033=>602,1034=>602,1035=>602,1036=>602,1037=>602,1038=>602,1039=>602,1040=>602,1041=>602,1042=>602,1043=>602,1044=>602,1045=>602,1046=>602,1047=>602,1048=>602,1049=>602,1050=>602,1051=>602,1052=>602,1053=>602,1054=>602,1055=>602,1056=>602,1057=>602,1058=>602,1059=>602,1060=>602,1061=>602,1062=>602,1063=>602,1064=>602,1065=>602,1066=>602,1067=>602,1068=>602,1069=>602,1070=>602,1071=>602,1072=>602,1073=>602,1074=>602,1075=>602,1076=>602,1077=>602,1078=>602,1079=>602,1080=>602,1081=>602,1082=>602,1083=>602,1084=>602,1085=>602,1086=>602,1087=>602,1088=>602,1089=>602,1090=>602,1091=>602,1092=>602,1093=>602,1094=>602,1095=>602,1096=>602,1097=>602,1098=>602,1099=>602,1100=>602,1101=>602,1102=>602,1103=>602,1104=>602,1105=>602,1106=>602,1107=>602,1108=>602,1109=>602,1110=>602,1111=>602,1112=>602,1113=>602,1114=>602,1115=>602,1116=>602,1117=>602,1118=>602,1119=>602,1122=>602,1123=>602,1138=>602,1139=>602,1168=>602,1169=>602,1170=>602,1171=>602,1172=>602,1173=>602,1174=>602,1175=>602,1176=>602,1177=>602,1178=>602,1179=>602,1186=>602,1187=>602,1188=>602,1189=>602,1194=>602,1195=>602,1196=>602,1197=>602,1198=>602,1199=>602,1200=>602,1201=>602,1202=>602,1203=>602,1210=>602,1211=>602,1216=>602,1217=>602,1218=>602,1219=>602,1220=>602,1223=>602,1224=>602,1227=>602,1228=>602,1231=>602,1232=>602,1233=>602,1234=>602,1235=>602,1236=>602,1237=>602,1238=>602,1239=>602,1240=>602,1241=>602,1242=>602,1243=>602,1244=>602,1245=>602,1246=>602,1247=>602,1248=>602,1249=>602,1250=>602,1251=>602,1252=>602,1253=>602,1254=>602,1255=>602,1256=>602,1257=>602,1258=>602,1259=>602,1260=>602,1261=>602,1262=>602,1263=>602,1264=>602,1265=>602,1266=>602,1267=>602,1268=>602,1269=>602,1270=>602,1271=>602,1272=>602,1273=>602,1296=>602,1297=>602,1306=>602,1307=>602,1308=>602,1309=>602,1329=>602,1330=>602,1331=>602,1332=>602,1333=>602,1334=>602,1335=>602,1336=>602,1337=>602,1338=>602,1339=>602,1340=>602,1341=>602,1342=>602,1343=>602,1344=>602,1345=>602,1346=>602,1347=>602,1348=>602,1349=>602,1350=>602,1351=>602,1352=>602,1353=>602,1354=>602,1355=>602,1356=>602,1357=>602,1358=>602,1359=>602,1360=>602,1361=>602,1362=>602,1363=>602,1364=>602,1365=>602,1366=>602,1369=>602,1370=>602,1371=>602,1372=>602,1373=>602,1374=>602,1375=>602,1377=>602,1378=>602,1379=>602,1380=>602,1381=>602,1382=>602,1383=>602,1384=>602,1385=>602,1386=>602,1387=>602,1388=>602,1389=>602,1390=>602,1391=>602,1392=>602,1393=>602,1394=>602,1395=>602,1396=>602,1397=>602,1398=>602,1399=>602,1400=>602,1401=>602,1402=>602,1403=>602,1404=>602,1405=>602,1406=>602,1407=>602,1408=>602,1409=>602,1410=>602,1411=>602,1412=>602,1413=>602,1414=>602,1415=>602,1417=>602,1418=>602,1542=>602,1543=>602,1545=>602,1546=>602,1548=>602,1557=>602,1563=>602,1567=>602,1569=>602,1570=>602,1571=>602,1572=>602,1573=>602,1574=>602,1575=>602,1576=>602,1577=>602,1578=>602,1579=>602,1580=>602,1581=>602,1582=>602,1583=>602,1584=>602,1585=>602,1586=>602,1587=>602,1588=>602,1589=>602,1590=>602,1591=>602,1592=>602,1593=>602,1594=>602,1600=>602,1601=>602,1602=>602,1603=>602,1604=>602,1605=>602,1606=>602,1607=>602,1608=>602,1609=>602,1610=>602,1611=>602,1612=>602,1613=>602,1614=>602,1615=>602,1616=>602,1617=>602,1618=>602,1619=>602,1620=>602,1621=>602,1626=>602,1632=>602,1633=>602,1634=>602,1635=>602,1636=>602,1637=>602,1638=>602,1639=>602,1640=>602,1641=>602,1642=>602,1643=>602,1644=>602,1645=>602,1652=>602,1657=>602,1658=>602,1659=>602,1662=>602,1663=>602,1664=>602,1667=>602,1668=>602,1670=>602,1671=>602,1681=>602,1688=>602,1700=>602,1705=>602,1711=>602,1726=>602,1740=>602,1776=>602,1777=>602,1778=>602,1779=>602,1780=>602,1781=>602,1782=>602,1783=>602,1784=>602,1785=>602,3713=>602,3714=>602,3716=>602,3719=>602,3720=>602,3722=>602,3725=>602,3732=>602,3733=>602,3734=>602,3735=>602,3737=>602,3738=>602,3739=>602,3740=>602,3741=>602,3742=>602,3743=>602,3745=>602,3746=>602,3747=>602,3749=>602,3751=>602,3754=>602,3755=>602,3757=>602,3758=>602,3759=>602,3760=>602,3761=>602,3762=>602,3763=>602,3764=>602,3765=>602,3766=>602,3767=>602,3768=>602,3769=>602,3771=>602,3772=>602,3784=>602,3785=>602,3786=>602,3787=>602,3788=>602,3789=>602,4304=>602,4305=>602,4306=>602,4307=>602,4308=>602,4309=>602,4310=>602,4311=>602,4312=>602,4313=>602,4314=>602,4315=>602,4316=>602,4317=>602,4318=>602,4319=>602,4320=>602,4321=>602,4322=>602,4323=>602,4324=>602,4325=>602,4326=>602,4327=>602,4328=>602,4329=>602,4330=>602,4331=>602,4332=>602,4333=>602,4334=>602,4335=>602,4336=>602,4337=>602,4338=>602,4339=>602,4340=>602,4341=>602,4342=>602,4343=>602,4344=>602,4345=>602,4346=>602,4347=>602,4348=>602,7426=>602,7432=>602,7433=>602,7444=>602,7446=>602,7447=>602,7453=>602,7454=>602,7455=>602,7468=>602,7469=>602,7470=>602,7472=>602,7473=>602,7474=>602,7475=>602,7476=>602,7477=>602,7478=>602,7479=>602,7480=>602,7481=>602,7482=>602,7483=>602,7484=>602,7486=>602,7487=>602,7488=>602,7489=>602,7490=>602,7491=>602,7492=>602,7493=>602,7494=>602,7495=>602,7496=>602,7497=>602,7498=>602,7499=>602,7500=>602,7501=>602,7502=>602,7503=>602,7504=>602,7505=>602,7506=>602,7507=>602,7508=>602,7509=>602,7510=>602,7511=>602,7512=>602,7513=>602,7514=>602,7515=>602,7522=>602,7523=>602,7524=>602,7525=>602,7543=>602,7544=>602,7547=>602,7557=>602,7579=>602,7580=>602,7581=>602,7582=>602,7583=>602,7584=>602,7585=>602,7586=>602,7587=>602,7588=>602,7589=>602,7590=>602,7591=>602,7592=>602,7593=>602,7594=>602,7595=>602,7596=>602,7597=>602,7598=>602,7599=>602,7600=>602,7601=>602,7602=>602,7603=>602,7604=>602,7605=>602,7606=>602,7607=>602,7609=>602,7610=>602,7611=>602,7612=>602,7613=>602,7614=>602,7615=>602,7680=>602,7681=>602,7682=>602,7683=>602,7684=>602,7685=>602,7686=>602,7687=>602,7688=>602,7689=>602,7690=>602,7691=>602,7692=>602,7693=>602,7694=>602,7695=>602,7696=>602,7697=>602,7698=>602,7699=>602,7704=>602,7705=>602,7706=>602,7707=>602,7708=>602,7709=>602,7710=>602,7711=>602,7712=>602,7713=>602,7714=>602,7715=>602,7716=>602,7717=>602,7718=>602,7719=>602,7720=>602,7721=>602,7722=>602,7723=>602,7724=>602,7725=>602,7728=>602,7729=>602,7730=>602,7731=>602,7732=>602,7733=>602,7734=>602,7735=>602,7736=>602,7737=>602,7738=>602,7739=>602,7740=>602,7741=>602,7742=>602,7743=>602,7744=>602,7745=>602,7746=>602,7747=>602,7748=>602,7749=>602,7750=>602,7751=>602,7752=>602,7753=>602,7754=>602,7755=>602,7756=>602,7757=>602,7764=>602,7765=>602,7766=>602,7767=>602,7768=>602,7769=>602,7770=>602,7771=>602,7772=>602,7773=>602,7774=>602,7775=>602,7776=>602,7777=>602,7778=>602,7779=>602,7784=>602,7785=>602,7786=>602,7787=>602,7788=>602,7789=>602,7790=>602,7791=>602,7792=>602,7793=>602,7794=>602,7795=>602,7796=>602,7797=>602,7798=>602,7799=>602,7800=>602,7801=>602,7804=>602,7805=>602,7806=>602,7807=>602,7808=>602,7809=>602,7810=>602,7811=>602,7812=>602,7813=>602,7814=>602,7815=>602,7816=>602,7817=>602,7818=>602,7819=>602,7820=>602,7821=>602,7822=>602,7823=>602,7824=>602,7825=>602,7826=>602,7827=>602,7828=>602,7829=>602,7830=>602,7831=>602,7832=>602,7833=>602,7835=>602,7839=>602,7840=>602,7841=>602,7852=>602,7853=>602,7856=>602,7857=>602,7862=>602,7863=>602,7864=>602,7865=>602,7868=>602,7869=>602,7878=>602,7879=>602,7882=>602,7883=>602,7884=>602,7885=>602,7896=>602,7897=>602,7898=>602,7899=>602,7900=>602,7901=>602,7904=>602,7905=>602,7906=>602,7907=>602,7908=>602,7909=>602,7912=>602,7913=>602,7914=>602,7915=>602,7918=>602,7919=>602,7920=>602,7921=>602,7922=>602,7923=>602,7924=>602,7925=>602,7928=>602,7929=>602,7936=>602,7937=>602,7938=>602,7939=>602,7940=>602,7941=>602,7942=>602,7943=>602,7944=>602,7945=>602,7946=>602,7947=>602,7948=>602,7949=>602,7950=>602,7951=>602,7952=>602,7953=>602,7954=>602,7955=>602,7956=>602,7957=>602,7960=>602,7961=>602,7962=>602,7963=>602,7964=>602,7965=>602,7968=>602,7969=>602,7970=>602,7971=>602,7972=>602,7973=>602,7974=>602,7975=>602,7976=>602,7977=>602,7978=>602,7979=>602,7980=>602,7981=>602,7982=>602,7983=>602,7984=>602,7985=>602,7986=>602,7987=>602,7988=>602,7989=>602,7990=>602,7991=>602,7992=>602,7993=>602,7994=>602,7995=>602,7996=>602,7997=>602,7998=>602,7999=>602,8000=>602,8001=>602,8002=>602,8003=>602,8004=>602,8005=>602,8008=>602,8009=>602,8010=>602,8011=>602,8012=>602,8013=>602,8016=>602,8017=>602,8018=>602,8019=>602,8020=>602,8021=>602,8022=>602,8023=>602,8025=>602,8027=>602,8029=>602,8031=>602,8032=>602,8033=>602,8034=>602,8035=>602,8036=>602,8037=>602,8038=>602,8039=>602,8040=>602,8041=>602,8042=>602,8043=>602,8044=>602,8045=>602,8046=>602,8047=>602,8048=>602,8049=>602,8050=>602,8051=>602,8052=>602,8053=>602,8054=>602,8055=>602,8056=>602,8057=>602,8058=>602,8059=>602,8060=>602,8061=>602,8064=>602,8065=>602,8066=>602,8067=>602,8068=>602,8069=>602,8070=>602,8071=>602,8072=>602,8073=>602,8074=>602,8075=>602,8076=>602,8077=>602,8078=>602,8079=>602,8080=>602,8081=>602,8082=>602,8083=>602,8084=>602,8085=>602,8086=>602,8087=>602,8088=>602,8089=>602,8090=>602,8091=>602,8092=>602,8093=>602,8094=>602,8095=>602,8096=>602,8097=>602,8098=>602,8099=>602,8100=>602,8101=>602,8102=>602,8103=>602,8104=>602,8105=>602,8106=>602,8107=>602,8108=>602,8109=>602,8110=>602,8111=>602,8112=>602,8113=>602,8114=>602,8115=>602,8116=>602,8118=>602,8119=>602,8120=>602,8121=>602,8122=>602,8123=>602,8124=>602,8125=>602,8126=>602,8127=>602,8128=>602,8129=>602,8130=>602,8131=>602,8132=>602,8134=>602,8135=>602,8136=>602,8137=>602,8138=>602,8139=>602,8140=>602,8141=>602,8142=>602,8143=>602,8144=>602,8145=>602,8146=>602,8147=>602,8150=>602,8151=>602,8152=>602,8153=>602,8154=>602,8155=>602,8157=>602,8158=>602,8159=>602,8160=>602,8161=>602,8162=>602,8163=>602,8164=>602,8165=>602,8166=>602,8167=>602,8168=>602,8169=>602,8170=>602,8171=>602,8172=>602,8173=>602,8174=>602,8175=>602,8178=>602,8179=>602,8180=>602,8182=>602,8183=>602,8184=>602,8185=>602,8186=>602,8187=>602,8188=>602,8189=>602,8190=>602,8192=>602,8193=>602,8194=>602,8195=>602,8196=>602,8197=>602,8198=>602,8199=>602,8200=>602,8201=>602,8202=>602,8208=>602,8209=>602,8210=>602,8211=>602,8212=>602,8213=>602,8214=>602,8215=>602,8216=>602,8217=>602,8218=>602,8219=>602,8220=>602,8221=>602,8222=>602,8223=>602,8224=>602,8225=>602,8226=>602,8227=>602,8230=>602,8239=>602,8240=>602,8241=>602,8242=>602,8243=>602,8244=>602,8245=>602,8246=>602,8247=>602,8249=>602,8250=>602,8252=>602,8253=>602,8254=>602,8261=>602,8262=>602,8263=>602,8264=>602,8265=>602,8267=>602,8287=>602,8304=>602,8305=>602,8308=>602,8309=>602,8310=>602,8311=>602,8312=>602,8313=>602,8314=>602,8315=>602,8316=>602,8317=>602,8318=>602,8319=>602,8320=>602,8321=>602,8322=>602,8323=>602,8324=>602,8325=>602,8326=>602,8327=>602,8328=>602,8329=>602,8330=>602,8331=>602,8332=>602,8333=>602,8334=>602,8336=>602,8337=>602,8338=>602,8339=>602,8340=>602,8341=>602,8342=>602,8343=>602,8344=>602,8345=>602,8346=>602,8347=>602,8348=>602,8352=>602,8353=>602,8354=>602,8355=>602,8356=>602,8357=>602,8358=>602,8359=>602,8360=>602,8361=>602,8362=>602,8363=>602,8364=>602,8365=>602,8366=>602,8367=>602,8368=>602,8369=>602,8370=>602,8371=>602,8372=>602,8373=>602,8376=>602,8377=>602,8450=>602,8453=>602,8461=>602,8462=>602,8463=>602,8469=>602,8470=>602,8471=>602,8473=>602,8474=>602,8477=>602,8482=>602,8484=>602,8486=>602,8490=>602,8491=>602,8494=>602,8520=>602,8531=>602,8532=>602,8533=>602,8534=>602,8535=>602,8536=>602,8537=>602,8538=>602,8539=>602,8540=>602,8541=>602,8542=>602,8543=>602,8592=>602,8593=>602,8594=>602,8595=>602,8596=>602,8597=>602,8598=>602,8599=>602,8600=>602,8601=>602,8602=>602,8603=>602,8604=>602,8605=>602,8606=>602,8607=>602,8608=>602,8609=>602,8610=>602,8611=>602,8612=>602,8613=>602,8614=>602,8615=>602,8616=>602,8617=>602,8618=>602,8619=>602,8620=>602,8621=>602,8622=>602,8623=>602,8624=>602,8625=>602,8626=>602,8627=>602,8628=>602,8629=>602,8630=>602,8631=>602,8632=>602,8633=>602,8634=>602,8635=>602,8636=>602,8637=>602,8638=>602,8639=>602,8640=>602,8641=>602,8642=>602,8643=>602,8644=>602,8645=>602,8646=>602,8647=>602,8648=>602,8649=>602,8650=>602,8651=>602,8652=>602,8653=>602,8654=>602,8655=>602,8656=>602,8657=>602,8658=>602,8659=>602,8660=>602,8661=>602,8662=>602,8663=>602,8664=>602,8665=>602,8666=>602,8667=>602,8668=>602,8669=>602,8670=>602,8671=>602,8672=>602,8673=>602,8674=>602,8675=>602,8676=>602,8677=>602,8678=>602,8679=>602,8680=>602,8681=>602,8682=>602,8683=>602,8684=>602,8685=>602,8686=>602,8687=>602,8688=>602,8689=>602,8690=>602,8691=>602,8692=>602,8693=>602,8694=>602,8695=>602,8696=>602,8697=>602,8698=>602,8699=>602,8700=>602,8701=>602,8702=>602,8703=>602,8704=>602,8705=>602,8706=>602,8707=>602,8708=>602,8709=>602,8710=>602,8711=>602,8712=>602,8713=>602,8714=>602,8715=>602,8716=>602,8717=>602,8719=>602,8721=>602,8722=>602,8723=>602,8725=>602,8727=>602,8728=>602,8729=>602,8730=>602,8731=>602,8732=>602,8733=>602,8734=>602,8735=>602,8736=>602,8743=>602,8744=>602,8745=>602,8746=>602,8747=>602,8748=>602,8749=>602,8756=>602,8757=>602,8758=>602,8759=>602,8760=>602,8761=>602,8762=>602,8763=>602,8764=>602,8765=>602,8769=>602,8770=>602,8771=>602,8772=>602,8773=>602,8774=>602,8775=>602,8776=>602,8777=>602,8778=>602,8779=>602,8780=>602,8781=>602,8782=>602,8783=>602,8784=>602,8785=>602,8786=>602,8787=>602,8788=>602,8789=>602,8790=>602,8791=>602,8792=>602,8793=>602,8794=>602,8795=>602,8796=>602,8797=>602,8798=>602,8799=>602,8800=>602,8801=>602,8802=>602,8803=>602,8804=>602,8805=>602,8806=>602,8807=>602,8808=>602,8809=>602,8813=>602,8814=>602,8815=>602,8816=>602,8817=>602,8818=>602,8819=>602,8820=>602,8821=>602,8822=>602,8823=>602,8824=>602,8825=>602,8826=>602,8827=>602,8828=>602,8829=>602,8830=>602,8831=>602,8832=>602,8833=>602,8834=>602,8835=>602,8836=>602,8837=>602,8838=>602,8839=>602,8840=>602,8841=>602,8842=>602,8843=>602,8847=>602,8848=>602,8849=>602,8850=>602,8853=>602,8854=>602,8855=>602,8856=>602,8857=>602,8858=>602,8859=>602,8860=>602,8861=>602,8862=>602,8863=>602,8864=>602,8865=>602,8866=>602,8867=>602,8868=>602,8869=>602,8901=>602,8902=>602,8909=>602,8922=>602,8923=>602,8924=>602,8925=>602,8926=>602,8927=>602,8928=>602,8929=>602,8930=>602,8931=>602,8932=>602,8933=>602,8934=>602,8935=>602,8936=>602,8937=>602,8943=>602,8960=>602,8961=>602,8962=>602,8963=>602,8964=>602,8965=>602,8966=>602,8968=>602,8969=>602,8970=>602,8971=>602,8972=>602,8973=>602,8974=>602,8975=>602,8976=>602,8977=>602,8978=>602,8979=>602,8980=>602,8981=>602,8984=>602,8985=>602,8988=>602,8989=>602,8990=>602,8991=>602,8992=>602,8993=>602,8997=>602,8998=>602,8999=>602,9000=>602,9003=>602,9013=>602,9015=>602,9016=>602,9017=>602,9018=>602,9019=>602,9020=>602,9021=>602,9022=>602,9025=>602,9026=>602,9027=>602,9028=>602,9031=>602,9032=>602,9033=>602,9035=>602,9036=>602,9037=>602,9040=>602,9042=>602,9043=>602,9044=>602,9047=>602,9048=>602,9049=>602,9050=>602,9051=>602,9052=>602,9054=>602,9055=>602,9056=>602,9059=>602,9060=>602,9061=>602,9064=>602,9065=>602,9067=>602,9068=>602,9069=>602,9070=>602,9071=>602,9072=>602,9075=>602,9076=>602,9077=>602,9078=>602,9079=>602,9080=>602,9081=>602,9082=>602,9085=>602,9088=>602,9089=>602,9090=>602,9091=>602,9096=>602,9097=>602,9098=>602,9099=>602,9109=>602,9115=>602,9116=>602,9117=>602,9118=>602,9119=>602,9120=>602,9121=>602,9122=>602,9123=>602,9124=>602,9125=>602,9126=>602,9127=>602,9128=>602,9129=>602,9130=>602,9131=>602,9132=>602,9133=>602,9134=>602,9166=>602,9167=>602,9251=>602,9600=>602,9601=>602,9602=>602,9603=>602,9604=>602,9605=>602,9606=>602,9607=>602,9608=>602,9609=>602,9610=>602,9611=>602,9612=>602,9613=>602,9614=>602,9615=>602,9616=>602,9617=>602,9618=>602,9619=>602,9620=>602,9621=>602,9622=>602,9623=>602,9624=>602,9625=>602,9626=>602,9627=>602,9628=>602,9629=>602,9630=>602,9631=>602,9632=>602,9633=>602,9634=>602,9635=>602,9636=>602,9637=>602,9638=>602,9639=>602,9640=>602,9641=>602,9642=>602,9643=>602,9644=>602,9645=>602,9646=>602,9647=>602,9648=>602,9649=>602,9650=>602,9651=>602,9652=>602,9653=>602,9654=>602,9655=>602,9656=>602,9657=>602,9658=>602,9659=>602,9660=>602,9661=>602,9662=>602,9663=>602,9664=>602,9665=>602,9666=>602,9667=>602,9668=>602,9669=>602,9670=>602,9671=>602,9672=>602,9673=>602,9674=>602,9675=>602,9676=>602,9677=>602,9678=>602,9679=>602,9680=>602,9681=>602,9682=>602,9683=>602,9684=>602,9685=>602,9686=>602,9687=>602,9688=>602,9689=>602,9690=>602,9691=>602,9692=>602,9693=>602,9694=>602,9695=>602,9696=>602,9697=>602,9698=>602,9699=>602,9700=>602,9701=>602,9702=>602,9703=>602,9704=>602,9705=>602,9706=>602,9707=>602,9708=>602,9709=>602,9710=>602,9711=>602,9712=>602,9713=>602,9714=>602,9715=>602,9716=>602,9717=>602,9718=>602,9719=>602,9720=>602,9721=>602,9722=>602,9723=>602,9724=>602,9725=>602,9726=>602,9727=>602,9728=>602,9729=>602,9730=>602,9731=>602,9732=>602,9733=>602,9734=>602,9735=>602,9736=>602,9737=>602,9738=>602,9739=>602,9740=>602,9741=>602,9742=>602,9743=>602,9744=>602,9745=>602,9746=>602,9747=>602,9748=>602,9749=>602,9750=>602,9751=>602,9752=>602,9753=>602,9754=>602,9755=>602,9756=>602,9757=>602,9758=>602,9759=>602,9760=>602,9761=>602,9762=>602,9763=>602,9764=>602,9765=>602,9766=>602,9767=>602,9768=>602,9769=>602,9770=>602,9771=>602,9772=>602,9773=>602,9774=>602,9775=>602,9784=>602,9785=>602,9786=>602,9787=>602,9788=>602,9789=>602,9790=>602,9791=>602,9792=>602,9793=>602,9794=>602,9795=>602,9796=>602,9797=>602,9798=>602,9799=>602,9800=>602,9801=>602,9802=>602,9803=>602,9804=>602,9805=>602,9806=>602,9807=>602,9808=>602,9809=>602,9810=>602,9811=>602,9812=>602,9813=>602,9814=>602,9815=>602,9816=>602,9817=>602,9818=>602,9819=>602,9820=>602,9821=>602,9822=>602,9823=>602,9824=>602,9825=>602,9826=>602,9827=>602,9828=>602,9829=>602,9830=>602,9831=>602,9832=>602,9833=>602,9834=>602,9835=>602,9836=>602,9837=>602,9838=>602,9839=>602,9840=>602,9841=>602,9842=>602,9843=>602,9844=>602,9845=>602,9846=>602,9847=>602,9848=>602,9849=>602,9850=>602,9851=>602,9852=>602,9853=>602,9854=>602,9855=>602,9856=>602,9857=>602,9858=>602,9859=>602,9860=>602,9861=>602,9862=>602,9863=>602,9864=>602,9865=>602,9866=>602,9867=>602,9872=>602,9873=>602,9874=>602,9875=>602,9876=>602,9877=>602,9878=>602,9879=>602,9880=>602,9881=>602,9882=>602,9883=>602,9884=>602,9888=>602,9889=>602,9904=>602,9905=>602,9985=>602,9986=>602,9987=>602,9988=>602,9990=>602,9991=>602,9992=>602,9993=>602,9996=>602,9997=>602,9998=>602,9999=>602,10000=>602,10001=>602,10002=>602,10003=>602,10004=>602,10005=>602,10006=>602,10007=>602,10008=>602,10009=>602,10010=>602,10011=>602,10012=>602,10013=>602,10014=>602,10015=>602,10016=>602,10017=>602,10018=>602,10019=>602,10020=>602,10021=>602,10022=>602,10023=>602,10025=>602,10026=>602,10027=>602,10028=>602,10029=>602,10030=>602,10031=>602,10032=>602,10033=>602,10034=>602,10035=>602,10036=>602,10037=>602,10038=>602,10039=>602,10040=>602,10041=>602,10042=>602,10043=>602,10044=>602,10045=>602,10046=>602,10047=>602,10048=>602,10049=>602,10050=>602,10051=>602,10052=>602,10053=>602,10054=>602,10055=>602,10056=>602,10057=>602,10058=>602,10059=>602,10061=>602,10063=>602,10064=>602,10065=>602,10066=>602,10070=>602,10072=>602,10073=>602,10074=>602,10075=>602,10076=>602,10077=>602,10078=>602,10081=>602,10082=>602,10083=>602,10084=>602,10085=>602,10086=>602,10087=>602,10088=>602,10089=>602,10090=>602,10091=>602,10092=>602,10093=>602,10094=>602,10095=>602,10096=>602,10097=>602,10098=>602,10099=>602,10100=>602,10101=>602,10132=>602,10136=>602,10137=>602,10138=>602,10139=>602,10140=>602,10141=>602,10142=>602,10143=>602,10144=>602,10145=>602,10146=>602,10147=>602,10148=>602,10149=>602,10150=>602,10151=>602,10152=>602,10153=>602,10154=>602,10155=>602,10156=>602,10157=>602,10158=>602,10159=>602,10161=>602,10162=>602,10163=>602,10164=>602,10165=>602,10166=>602,10167=>602,10168=>602,10169=>602,10170=>602,10171=>602,10172=>602,10173=>602,10174=>602,10175=>602,10178=>602,10181=>602,10182=>602,10208=>602,10214=>602,10215=>602,10216=>602,10217=>602,10731=>602,10746=>602,10747=>602,10799=>602,10858=>602,10859=>602,11013=>602,11014=>602,11015=>602,11016=>602,11017=>602,11018=>602,11019=>602,11020=>602,11021=>602,11026=>602,11027=>602,11028=>602,11029=>602,11030=>602,11031=>602,11032=>602,11033=>602,11034=>602,11364=>602,11373=>602,11374=>602,11375=>602,11376=>602,11381=>602,11382=>602,11383=>602,11385=>602,11386=>602,11388=>602,11389=>602,11390=>602,11391=>602,11800=>602,11807=>602,11810=>602,11811=>602,11812=>602,11813=>602,11822=>602,42760=>602,42761=>602,42762=>602,42763=>602,42764=>602,42765=>602,42766=>602,42767=>602,42768=>602,42769=>602,42770=>602,42771=>602,42772=>602,42773=>602,42774=>602,42779=>602,42780=>602,42781=>602,42782=>602,42783=>602,42786=>602,42787=>602,42788=>602,42789=>602,42790=>602,42791=>602,42889=>602,42890=>602,42891=>602,42892=>602,42893=>602,42894=>602,42896=>602,42897=>602,42922=>602,63173=>602,64257=>602,64258=>602,64338=>602,64339=>602,64340=>602,64341=>602,64342=>602,64343=>602,64344=>602,64345=>602,64346=>602,64347=>602,64348=>602,64349=>602,64350=>602,64351=>602,64352=>602,64353=>602,64354=>602,64355=>602,64356=>602,64357=>602,64358=>602,64359=>602,64360=>602,64361=>602,64362=>602,64363=>602,64364=>602,64365=>602,64366=>602,64367=>602,64368=>602,64369=>602,64370=>602,64371=>602,64372=>602,64373=>602,64374=>602,64375=>602,64376=>602,64377=>602,64378=>602,64379=>602,64380=>602,64381=>602,64382=>602,64383=>602,64384=>602,64385=>602,64394=>602,64395=>602,64396=>602,64397=>602,64398=>602,64399=>602,64400=>602,64401=>602,64402=>602,64403=>602,64404=>602,64405=>602,64414=>602,64415=>602,64426=>602,64427=>602,64428=>602,64429=>602,64488=>602,64489=>602,64508=>602,64509=>602,64510=>602,64511=>602,65136=>602,65137=>602,65138=>602,65139=>602,65140=>602,65142=>602,65143=>602,65144=>602,65145=>602,65146=>602,65147=>602,65148=>602,65149=>602,65150=>602,65151=>602,65152=>602,65153=>602,65154=>602,65155=>602,65156=>602,65157=>602,65158=>602,65159=>602,65160=>602,65161=>602,65162=>602,65163=>602,65164=>602,65165=>602,65166=>602,65167=>602,65168=>602,65169=>602,65170=>602,65171=>602,65172=>602,65173=>602,65174=>602,65175=>602,65176=>602,65177=>602,65178=>602,65179=>602,65180=>602,65181=>602,65182=>602,65183=>602,65184=>602,65185=>602,65186=>602,65187=>602,65188=>602,65189=>602,65190=>602,65191=>602,65192=>602,65193=>602,65194=>602,65195=>602,65196=>602,65197=>602,65198=>602,65199=>602,65200=>602,65201=>602,65202=>602,65203=>602,65204=>602,65205=>602,65206=>602,65207=>602,65208=>602,65209=>602,65210=>602,65211=>602,65212=>602,65213=>602,65214=>602,65215=>602,65216=>602,65217=>602,65218=>602,65219=>602,65220=>602,65221=>602,65222=>602,65223=>602,65224=>602,65225=>602,65226=>602,65227=>602,65228=>602,65229=>602,65230=>602,65231=>602,65232=>602,65233=>602,65234=>602,65235=>602,65236=>602,65237=>602,65238=>602,65239=>602,65240=>602,65241=>602,65242=>602,65243=>602,65244=>602,65245=>602,65246=>602,65247=>602,65248=>602,65249=>602,65250=>602,65251=>602,65252=>602,65253=>602,65254=>602,65255=>602,65256=>602,65257=>602,65258=>602,65259=>602,65260=>602,65261=>602,65262=>602,65263=>602,65264=>602,65265=>602,65266=>602,65267=>602,65268=>602,65269=>602,65270=>602,65271=>602,65272=>602,65273=>602,65274=>602,65275=>602,65276=>602,65279=>602,65529=>602,65530=>602,65531=>602,65532=>602,65533=>602,65535=>602); -// --- EOF --- diff --git a/lib/combodo/tcpdf/fonts/dejavusansmonob.z b/lib/combodo/tcpdf/fonts/dejavusansmonob.z deleted file mode 100644 index ef5638e2510ab23891b82dfe8fc359f7578bef53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 193788 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

    E{_tkJ4!?@mFkBe}E!+Jh3z_`e}#CuQVEzj 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%0ArvMU%BO#8XyUOb+lsXvp9LAQ-V2>kkLg&tT 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

    @0pLwupYKFR))}5M5fKQsC6p zg#p71L6LQrD66{5R>d%VygXDMAj`99anMy0r$6M3#2MfShCsHH0jJqDp} zNvMQe&yu!ak5UX1QQTmUROw3lZ@jKEW+ibZg0MyE52)YW*^%EFHa&3apX`ChYUV^; z4c|*@sf+tXPxMziHJ92A?Qb;gm=-!~)UZ$}d*zl^Dcy!AG{F>unZNwH>zme27}O`! zJe-=*J7uQmcizs*9zA(b_1xLU0B0`t)2@)W>*E}~Ny5MDt)H~$H+- zSHHu4=U#J?YkRqxw~TQ=&Et@Z+Sh72G!nj<9FMx z8dEiTOhw#x43f8N8Pxk3u0YF(xq{gKeBroYdtAYf8us3~_%mE-s8g;xJCFjsvp6wvEZC~7@$Q(PRd!HoHXwjxco6e&{U4weJuakRQpA}7=Fm+hJq}FYE^qDxd z)99IlyuFUM>z~?lYV7v{=b4dwR7kYH9)9{acD*Lw?d;j`{oIB%X)HAAETy;UnVizG zZJW+*Qu>~J{>N_v;if&BwW+*2ufWxM%ebYh#trgkgfm_#zdZW5G`wy9?j4$@wCj-G zDlxjVQ?I17)UG)b*Yxvl4tFzqOc{S}y>QurQ9T>@!Wu0MU&*z+Gn!-1272;=L8E7i z`l)}pw&5SIl9M-gYbT2>n@;ajeLVW~+K2bAjUM`VQP;D2C-)sXJ#St`Ri~tsgyc4T zyLai)rb$AlL^<6z{j7@z4(mIj#qq4HZX;9Gc$LoORu*`sib4d%KFseawEBUpQy+JUP+Rt#h}o$r-N10Ud^C z8!n?$Y2BhZC4tOg%>r}tF`32V;(3!cj~;fg{JQft-dQwpj5TKt-B8iAf`KK#k~3b zI}T2nGJk4i-&w%{W=>~o^YXalg2| zCw9+q^Z3apVq2o;#3ro07QB`781uCmYac(}P|Mz%dpga;SUqne%FawB=?3Dk5z52T zgZj75w?z{NdlfI=0i<-y^k)?KiOfQRg$Qny;s_zv%;2(E~qky(dLX zZddHR^n!}IW>UME=We=mx^K|0n5APzq_@c(xjS9pn!cCvs?tSh>b!w%zfkQ=u$Z~B zA2FP6t8Dk+to1QU8+NzKrM-vw(>h=^k=DCs^vUPuZ|rv6%F@lQzW3!7-a7G|sr|=Y zc6IdU_iw#5U2JbZV9u3#bsXJwoY<*b|Fcs1oJ_m!g)LpI!bdZEy)>!Eh`blR{_)!S zjaP~_bz+ORE_{6Ud81}I@5%hay;GgVwI_dZ*3ZKl?Qx3jeOjH=!@hR*jc3W*<9k@t zBS}5%y(`Y%v)!lOA<#17TZu_ZHuq$_t!PO-l@;QUldo|Ph!p$H zLcR#2dtlt&$LFrsY{7lN^68I?ga2Uv<^9QNozez%Zr!~{+R#VFet++6*PS2zRu;R8 zsofUO9JHc367)9dlyk+b3zGURI=5i%jIp!3ir;kX(XVTYDE8^tDLW-4dcmAPuij^i z1J}=*vvyg(E^S)&?A;=1ME;t>-Zg%+SJ$<^4bhMJoLgneN8@^aBQW6SbQ4SN%7fn5{B7B)tQHS8&zj`G@A zdGwoTw|{%qXvYuIG-LIB3G2^E9Q>=$$>jtTFAaTrcRW8)e&VQl)HUB(o5mv!{ME~& zkV|>>M0xZN^(f0v{ii6e3MJ0TtFa`0B7A}QvEBZ+*2FKwWujkLB4ms6#eU)w!nwlv z!XrYBuvD0b)%r?djj%$f6rT`lgz3)l71kb|arYWwov>4QK&V5$ODIQvT$m~>5@rdv zBCSTNnZkVg7k!}}xUCU)fXV>p`iL+`*n+k*QE#_UfYz7d*p2H+I4{7xnPOL*RSGu? z6Hq@W3*}9^mq>85cSfrJLvW)zM zQvj4op{2u*3V%FPu)p2a0eCkE2964h;u~xm!lcUl3D7R7K+6;i6J&)#7Up9@{ z*eW(Gb0FzPxxme#&nhu$r~2y)@P9dthv_gxrGR|&h&b_~u|LYoD+wk<~f5Eh0xtqPEa2~|R=&?VYU=z{+2h`zDM-&`O(fYDYc*gmTt zN^J`E_`VsrJ+H3;Z&T5a*Kl_4tp5Nlu5m^>{6zgvLNZF~z<+yi-x+Oe`Ff#d6Pzu= zQ3nq*wL!XTfY@H>>PQz6#^Fdt?F$6^BN~%2mO^OpfiM)cn+n%Dn7bjzRL3sta=6=$ z@i`vjFJD-X)&tSHljFNGA&ou5lF@!Az0jqwAYDFbyCcGSaph@t<&^)J)j-#_EsH?WPL1cj zjnN)l#S^GG{Mhm=MGwz%yoVqRM_t>y6=1ej;cs7@&j;Ocf^Bz(;eKZ)nMk8iG8Vl! z!l~04Jw6}hRiNkvy-t`-*NM%9wMaRL3MK$0BosqSA^75}FuFn*|0AH?0?hE8z$gY! zJ47A%jkx|8E!IQ&9nk$m*qA!dn20t7_7}6oCoww)34@#YzGb6wz?hTiXxupJ9nDHinen~itO)VVf+S%^1aO)zb`gF=?GB*U9=xQWd^oImfAG-7 znMro^5Kr+q>de$QmU;m5(TSlj3gRghBYd4RV`FhsJe?6e!Lm$hNR6T>C)u;qwt;qX z;-^OGKgCb~6hmd9kFp$3biD^OT*3eUt#>vEtJjF$qIXMl(Oc9YiQao%OGIzcl4vUk z5+#J_tS$r_(FL1mi|C78to{4`%JZD(oacYe?0aV3_iQ=$+?|;_bLaKBI>Id#3>$?$ zfXg>GZ@j>N(N(gfw$n0eb20KWncYCfNcI~$NXDp%NvwdtjVJf>Wyx=^% z)LtV#>rwH%h>LO0P-eFp)Got!5{Ef0XT>v&k_sFXutdLADK+;meW_-yq5Ozm)r0r2 zB``YkY`TT40x9=i-ize=VBhc0R&McZ`7LnMAx9D6XScazqcHR<+r!K4mhTdvy|R{oARWj0m=tqg3#arF!m0lEPmg45FfRwaN`ysdSIT#!iZ?h+ znqxKzl^fzn)(7^YzlPrfe=T3f4-miN%=D;scrq05l3M9K+ojq!<*&nPCAeQdFV<a45Lp1d1K_6Sm^jM$#dD|`PjY?+3XN8;K&|Af@$4cXEl2(cf_~|~JD_Jn1AF9$y z-v&pQn+C>0GvA%mZLf-@beYLkO1yHTYtk%zx~AW=7#e{6fkL0 z)Fn%5g5?xv@scwHS0{BnI1vzh{Tp*HXyY39@dO7e+a5BB@^`nP#pJw%J)#;qp%PJd z;-)pV!3!O^m3_+h@`tC5W|U91;Gz{g_98FS#*25)XQ(bf$w`7WiD8V+BnICK%B!Cm z(8liB>J_fh%HX(XYJ;0-`p8MMUP`!fD=YGzGbGyP2>|wfg-F}LUy3xWnkN*8Cyc2- z-okg5;yHGy8!V*!29}XbQW=xF7iG=s@;0k?Qp=Ey2#5uFNbtBz$h#sYpsaWM_X`x9Q@=!cKeIlhacHkerW5==VU}T6r1Cb~hh;A~ zXxoeb=HRvPHS44*vW`{WBT@FDOJ^_|kN#)9&q^o4i0MGeblKXIzgNKM{yNZUlnhO6 z`w7TFxaw&$N#%xBHLklC1UvGQcf9XNS2mo(bCc5EJFka*cFw=yhX>}@OxW3o(*cfd z_z@*>Vm)P2Z5)`O^0ReUAoC zUv_UHwJh05z4TG~U8pz+LHZg|dapk=>YNkncXlOuzEPqu#@3vI6CF+UYAE^gsJVV} zlsY2qs%y`$|Ktf)GO5=DoK=#xE042?gga&-J^>6qjFECXTc(_^AN*CiST^Z4pJ83@ z;cN9mgovZUAL1^q#77o(6?~o-8`tUL{LwEn&v#d|uPVZQ`@j}BeQXpphKzf*;W`rEw36%kj@k4`Py!2Y!|GYkGJV%Tn*p?&`YNW~eWxzKZOO&&#xUK;~QAsOrpQC zd+)!pLNqe?+a*|eJ^oY=`AH&3yeQbd&KQ2+-^lL2tj0^mu3kZiK6?9Lk#mkw5fbZ3 zPA8$rJO3{|#LjJOiJ8d(76lxe3t^&b=z>_asS%Yc`A1grl#fPzsN+XoXp}f+k!kqB zk-6za@2&_wABBQ+HF4FTwODZ|uW6&&CM#a&uKct*mg-s2JKgN16-x5pm{!9iqW(Vp zdjuC<_E6SW-tXY%jHuF(3@$37dQj2bc4=L-6jO6C@$FQk=DpYI1>6V^fnXv5XQo@K zYtTIn7!8QDyj2%kn2}RJjeSn2Mk=oW%}u+VnAFthu^-E(HE;i*F6uxRH8++(wgz&Q-b=rG0*Cs2#m`vj zy)5mr3<#Ag_qxq2Cnd+|-!&UJ2j#LWnD*5Pj2-a%PO_ple)=jegY2CNPzw0n#(4Df zKjrBAaYGZ?(A<<7IoeZWjdf#!gYWHf%$E;0)}H?^N{@;_epMbTB8@bMrU@c~D4v%P z{1Ai{|F^_`j4KmFxCx;iF~mG#h%BNgd6KAFtua+wBS+nAm_YT*S9>{&sMy148IYd? z+YdfgWbZc8DcVKu?7GXb$0)M9zEB+54o3QsT*Z(C%MfFs!JRa8Epl!8kKKiDEpk+{bEer zINn|hCP-jJ>z^7&k8eaIPn(`WCcy(shWZj6@Vaw?uF00C2bGIS6}CZB5j9ePpeCkf z#)OxWdkmTYKKKjrZ~=&z0d#^6*-Uh45cibe2i>!R_ysd$!+q>i3dJh8sbH{0>g|{H z!1n-_GmxvQ`;XDLHh8y;aY@APb|n8E9b1vaj!XKEn_A(QSgR*7KuuEu%u<>xh_5V> z2|?To9X00Ek#p|W36f@nrCwZNqMP+vPel(GoPW$h78H-$?}Y$e(nViQ0q z&14(il2>5Ks}S;V`}nIJ$od&Dn$ zxEI-duh}7478sxP0@_2>X`lIRqC9~i+l_d8TMMzl^UR*8I}N&?@7_k&X+!?bD*iGb z+D7N|uhFvZu~U7^zPhonB+v>{Xj#)nac!w)z{Il#c_lDS7&4!_TfYk_5~ha|8O zq*e#%_Trjg8EYfia236Z75xXdMFxnDoZF&SY}2u=OkG~iMGFJ38xuwCDX)8Jf;`z# z?KCmHG>T7?V(myv>JwDwoqyD6f*TWh=Lx|o#|wAzd?hZR75|Z6+z(cDKVI}I8S58X zX*tODL-=o^_eJVK^yuG2s&e>I^n1Pp7Y}E0VfC;EKwBO+q6Wf&$GkS+GpT=z~=`JH*v#@^XU-Mva;tK<(RZSYI-ZmTHsOQH$W_*Rm=MKcyi ziteMoJR~v>gB&`*x+%}Y@cn?}VW9c0pJ8DYYrbP0tnyuuF4FFQpuT^@@~dgFtCS9F z2>~I1t3Moh>uIr_K*b*5!ljG-YEsmtv*AC&`WW~e7S_pm6^WpPpjARb%PQMb@tQOboE&SOgu6bcCA?}2~EsV^vhJLk% z=32uhgtJd9TcQ{)9fz4B8E(2MO1e{f!>O-gs1>8A&z%x7osu%0bb1y*mmzoiwL%<8 z4_TSy{NmPF-#vR0N$T4m7}@1s zYUVZ2N|*_b9d)Jziy}Q=hr}pS^so;z$)|SeaG#luMc?mKqu|JNxyP1xn-!ns3XPx& zQ6Zu^Tb>9!lGz_`XZ^9Tn8& z9pFC-dd{)eouqgKX}mPOP#s?*1#_xTbE=O3{ErC7F7dChgvd=oI1VowoO}xCU(m@u z<2^>xZvPEPKiYr>v7tF#m1EMQI4jmh1+JM6RQuVmMA2XZN7Y1CRpO(v_z^c`(li`b zme4lM{c8u=CJq|~W}i{c;s_Km1dn3z6?z|I3g2ovIj2VxUpYah8zmb1v{xHJ`%X+@ zxB;vm*Myw=8TCkiTlS?L9Lu<~4oX@t=jUi39B zlUn>*7St6-2v_@a!;jqOpT&_YUXjbIxl-ZMPs_@4oz%~Os2y>{E)a^k=)Cwz_*isfI%l4EXP8Q~tU-=_3p=@oD2 zZ?MGdH;DmgAPNISodLHO*WEAWmP_ys=;0W>7L}AHCaqP0U^~FOy{2BqWv&A)MS$?9!y?l_z|AAvZ z$c5*S|AWt8&iJ=^uZaFVnAIBykpj}~$q>d$<;f8Go)JAbo?$z%#bfnSYa&K_H&O1A zf(%J;-=RfR>6^yHO?=C3L~5e_#s;%KDUqU_p!m9alQoJK+drMH@vlPbxi!7U63#y? zvP60lI<)qOus*9+zsU2-j{C(J-9j9@(yyCcFS^%4oaF;qVeD>AH1shA7y(qCHpCC}igj(wRLV>o!8v{!#@Q zYOPv4`$)ihZUFj6)mh?nZ%FK&?&s{db%v16`1J;UBHDe2CZ!R}F!(;rS`=Od>E7k5 zI+gN`(mpa5am2G#;fvQ)J(8hU>TWS6ed0(Iu`f%*uee;2*lS2zZ2JO0`CO;(lC^|i~s-n%nt?hTxEEmN~sM zp?~4oZzal&YZ2s@$d7Vv7&F1|a{6qOFo7#)rcJijii7^_0}*6bWaY-1HNf~-4dkzT zdoMH(y~nbtOTYe9W%X&6l>EX4rg+eOK+A4b}27O z3}rkPIer0}{{tWO|B*ynBS#RJjyIW;?RP&|;uDbWD)xS`Jd1oq|DbydJ2hq`u27Px z(G@x<2~{JJ9?^K+vOujCj&itaLj{a3G%y6WA(w}T@28&SGT1^KfY&2J=&Zcl%F1q;Mm)| zqo$~cZI`dzKb9cwHY7eWmt6Sxq3@$clDXvQN9TWr3Ch39o$4xvncGKfpBCe@{~%g3 zMDBQ}*M9}MF`^_XUwq|W_g;)sfGUw*HXSldLyUIf*E2_N4P_ zc}~T5fD-XI)d`pm^Y&APWoz|biesykX8k-%$hr_}wF6o0+0ytrT_(GaM0r*t(>6Ut z5&o2{$N4}&OruQXwTJ=NK3#g&Ssa+-xjd)xvkU>pxKIP`!NlwX4b-nk$N=UmPX&J~ z^$`ZdA0E`MR!tD?xV6U1I?Us`gCR?3hD>og%asH5k2F)93-ZF{xQnFIj<9z=u1^ML zM_Jd(MDHcZvG5^l0g@H+1-I`HW`FKT`tMx8F01(*+Q;#NH7+eAuN~h~kWSRA_6f~i z>X$6XQPj&0lxvMzSg(Ls_Nzn1#i@OX*9}Rk|4BMU`#%A8{Wz;lIlK*$ywx~aIgM&L zo<4FP-+}NB<`zE^oLt4aAE@tlylNkDXAd#fUl`ra5Yh&j{?C{SzD9!e)x`S17i51V z`dq}ICS;LbO2(B;^%J*|rL&ZwW^$(5w~Mgb)0u53GZ_ zy$xjD2B}_w1KL1IZIC2(Xa}KmSll)Z{5Sr4CG{Xu_d~qN|1}Sw5lZfBH1FFIwh!RH z4zjO9QL6{=)dOVGilkAfMx&DRS=fiZP#2Md$GD?cv0(&Y{^S1<91UU}|3)beOnQ8T zcgqgzBSeSc;b`DPwr1V*=ZBAbluVC|X1o4VRH+jm{!i^Vf*;*YAH7DbdPGnb2AS@H z?KmLL#L}y~;$nbbjtDLspee02?Ud4CkZm#eZ{qh|>OnyFLxM>MXvcqPn?XNG=U2d~q(fT(b`vLx>3j8Mr(j5@oLaMm@AEPV^ zw!?AUK^lEXTo%>8<2bvT)){3QCcby5wb}z)r@Z+uiHZXQj*swfRbYLj=u12t2V$M@ z=D$ti+a6dSQ2K~?G73cR<$2-=?*^hT32=^xyEk9QfjN(l5^ik#(k?-_*Ic-mY@F&{ zbNb&0F7fY<{{P7l=`9x4$BDiq#Kj`k0XNqWu-ftenl=+@06ZK%LJjYRG!BP%%!zkP z2m|Ax|Jx+HA%)<$jyZ{L6JX$bXaE5Ygi!mBdG~SG|2F~PN(1h<+n zFd6#)F(EjKV@{IWK^T|`4IsohBh;vFlKx}feIwrgO=uBn1UEWyII?3-{99fam

    BU3W(oH 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 diff --git a/lib/combodo/tcpdf/fonts/dejavusansmonobi.ctg.z b/lib/combodo/tcpdf/fonts/dejavusansmonobi.ctg.z deleted file mode 100644 index aa6da4149775e834c28adb6d6fdd1439b9ec4c5c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4983 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 A0{{R3 diff --git a/lib/combodo/tcpdf/fonts/dejavusansmonobi.php b/lib/combodo/tcpdf/fonts/dejavusansmonobi.php deleted file mode 100644 index 3fb89bd95..000000000 --- a/lib/combodo/tcpdf/fonts/dejavusansmonobi.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php -// TCPDF FONT FILE DESCRIPTION -$type='TrueTypeUnicode'; -$name='DejaVuSansMono-BoldOblique'; -$up=-63; -$ut=44; -$dw=602; -$diff=''; -$originalsize=239876; -$enc=''; -$file='dejavusansmonobi.z'; -$ctg='dejavusansmonobi.ctg.z'; -$desc=array('Flags'=>97,'FontBBox'=>'[-425 -394 808 1053]','ItalicAngle'=>-11,'Ascent'=>928,'Descent'=>-236,'Leading'=>0,'CapHeight'=>729,'XHeight'=>547,'StemV'=>60,'StemH'=>26,'AvgWidth'=>602,'MaxWidth'=>602,'MissingWidth'=>602); -$cbbox=array(0=>array(51,-177,551,705),33=>array(165,0,437,729),34=>array(113,458,488,729),35=>array(-20,0,619,718),36=>array(19,-147,533,760),37=>array(16,0,595,699),38=>array(-16,-14,593,742),39=>array(238,458,363,729),40=>array(165,-132,527,759),41=>array(55,-132,417,759),42=>array(59,278,541,742),43=>array(32,45,569,582),44=>array(102,-140,365,179),45=>array(119,217,453,359),46=>array(170,0,367,179),47=>array(0,-93,525,729),48=>array(44,-14,558,742),49=>array(21,0,498,729),50=>array(-14,0,554,742),51=>array(-15,-14,547,742),52=>array(9,0,547,729),53=>array(3,-14,562,729),54=>array(47,-16,571,741),55=>array(53,0,598,729),56=>array(31,-14,555,742),57=>array(27,-15,551,742),58=>array(149,0,412,519),59=>array(83,-140,412,519),60=>array(43,53,559,574),61=>array(43,144,559,482),62=>array(43,53,559,574),63=>array(142,0,557,742),64=>array(-7,-156,600,681),65=>array(-55,0,515,729),66=>array(-10,0,575,730),67=>array(64,-14,595,742),68=>array(-4,0,569,729),69=>array(14,0,610,729),70=>array(23,0,619,729),71=>array(50,-14,582,742),72=>array(-4,0,606,729),73=>array(13,0,589,729),74=>array(-10,-14,563,729),75=>array(-9,0,668,729),76=>array(39,0,516,729),77=>array(-28,0,630,729),78=>array(-12,0,613,729),79=>array(30,-14,572,742),80=>array(8,0,591,729),81=>array(30,-137,572,742),82=>array(4,0,569,729),83=>array(2,-14,566,742),84=>array(88,0,629,729),85=>array(22,-14,621,729),86=>array(99,0,647,729),87=>array(20,0,669,729),88=>array(-70,0,656,729),89=>array(71,0,663,729),90=>array(-16,0,630,729),91=>array(109,-132,531,760),92=>array(166,-93,362,729),93=>array(52,-132,473,760),94=>array(28,457,574,729),95=>array(0,-236,602,-143),96=>array(181,616,422,800),97=>array(23,-14,557,560),98=>array(23,-14,569,760),99=>array(73,-14,565,560),100=>array(32,-14,621,760),101=>array(37,-14,564,561),102=>array(113,0,619,760),103=>array(9,-207,581,562),104=>array(29,0,547,760),105=>array(7,0,527,813),106=>array(-31,-207,512,813),107=>array(40,0,634,760),108=>array(114,0,505,760),109=>array(-16,0,589,560),110=>array(29,0,547,560),111=>array(43,-14,559,561),112=>array(-18,-208,571,560),113=>array(33,-208,579,561),114=>array(75,0,599,560),115=>array(44,-14,534,560),116=>array(80,0,571,702),117=>array(52,-14,569,547),118=>array(84,0,601,547),119=>array(44,0,647,547),120=>array(-37,0,599,547),121=>array(-44,-207,614,547),122=>array(24,0,580,547),123=>array(64,-163,591,760),124=>array(245,-236,356,764),125=>array(-15,-163,512,760),126=>array(43,226,559,396),161=>array(165,0,437,729),162=>array(51,-153,538,699),163=>array(-11,0,608,742),164=>array(91,86,546,541),165=>array(-14,0,656,729),166=>array(245,-171,356,699),167=>array(51,-95,517,742),168=>array(203,654,535,774),169=>array(0,61,602,663),170=>array(103,209,513,742),171=>array(38,69,538,517),172=>array(43,177,559,439),173=>array(119,217,453,359),174=>array(0,61,602,663),175=>array(206,668,532,760),176=>array(138,417,463,742),177=>array(43,0,559,627),178=>array(127,326,502,742),179=>array(135,319,508,742),180=>array(278,616,590,800),181=>array(-27,-209,560,547),182=>array(50,-96,581,729),183=>array(199,259,397,437),184=>array(74,-196,311,0),185=>array(141,326,476,734),186=>array(108,209,521,742),187=>array(40,69,541,517),188=>array(15,-132,558,810),189=>array(15,-132,577,810),190=>array(23,-132,558,818),191=>array(44,-13,459,729),192=>array(-55,0,515,927),193=>array(-55,0,558,927),194=>array(-55,0,556,927),195=>array(-55,0,572,928),196=>array(-55,0,554,927),197=>array(-55,0,515,928),198=>array(-73,0,640,729),199=>array(64,-196,595,742),200=>array(14,0,610,927),201=>array(14,0,610,927),202=>array(14,0,610,927),203=>array(14,0,610,927),204=>array(13,0,589,927),205=>array(13,0,589,927),206=>array(13,0,589,927),207=>array(13,0,589,927),208=>array(-8,0,569,729),209=>array(-12,0,613,928),210=>array(30,-14,572,927),211=>array(30,-14,572,927),212=>array(30,-14,572,927),213=>array(30,-14,572,928),214=>array(30,-14,572,927),215=>array(58,72,543,556),216=>array(-69,-31,662,761),217=>array(22,-14,621,927),218=>array(22,-14,621,927),219=>array(22,-14,621,927),220=>array(22,-14,621,927),221=>array(71,0,663,927),222=>array(8,0,569,729),223=>array(14,-14,565,761),224=>array(23,-14,557,800),225=>array(23,-14,605,800),226=>array(23,-14,557,800),227=>array(23,-14,566,778),228=>array(23,-14,557,774),229=>array(23,-14,557,888),230=>array(-15,-14,601,560),231=>array(73,-196,565,560),232=>array(37,-14,564,800),233=>array(37,-14,590,800),234=>array(37,-14,564,800),235=>array(37,-14,564,774),236=>array(7,0,527,800),237=>array(7,0,568,800),238=>array(7,0,527,800),239=>array(7,0,527,774),240=>array(40,-14,589,760),241=>array(29,0,551,778),242=>array(43,-14,559,800),243=>array(43,-14,590,800),244=>array(43,-14,559,800),245=>array(43,-14,559,778),246=>array(43,-14,559,774),247=>array(32,42,569,585),248=>array(-40,-57,640,603),249=>array(52,-14,569,800),250=>array(52,-14,590,800),251=>array(52,-14,569,800),252=>array(52,-14,569,774),253=>array(-44,-207,614,800),254=>array(-18,-208,571,760),255=>array(-44,-207,614,774),256=>array(-55,0,562,913),257=>array(23,-14,557,760),258=>array(-55,0,575,927),259=>array(23,-14,557,784),260=>array(-55,-196,515,729),261=>array(23,-196,557,560),262=>array(64,-14,627,927),263=>array(73,-14,632,800),264=>array(64,-14,625,927),265=>array(73,-14,576,800),266=>array(64,-14,595,927),267=>array(73,-14,565,774),268=>array(64,-14,650,927),269=>array(73,-14,613,800),270=>array(-4,0,592,927),271=>array(32,-14,808,760),272=>array(-8,0,569,729),273=>array(32,-14,681,760),274=>array(14,0,610,913),275=>array(37,-14,564,760),276=>array(14,0,610,927),277=>array(37,-14,566,784),278=>array(14,0,610,927),279=>array(37,-14,564,774),280=>array(14,-196,610,729),281=>array(37,-196,564,561),282=>array(14,0,610,927),283=>array(37,-14,603,800),284=>array(50,-14,621,927),285=>array(9,-207,581,800),286=>array(50,-14,599,927),287=>array(9,-207,581,784),288=>array(50,-14,582,927),289=>array(9,-207,581,774),290=>array(50,-241,582,742),291=>array(9,-207,581,771),292=>array(-4,0,606,927),293=>array(29,0,547,927),294=>array(-4,0,650,729),295=>array(10,0,527,760),296=>array(13,0,589,928),297=>array(7,0,529,778),298=>array(13,0,589,913),299=>array(7,0,532,760),300=>array(13,0,589,927),301=>array(7,0,547,784),302=>array(32,-196,608,729),303=>array(10,-196,530,813),304=>array(13,0,589,927),305=>array(7,0,527,547),306=>array(8,-16,718,729),307=>array(5,-193,710,827),308=>array(-10,-14,599,927),309=>array(-31,-207,516,800),310=>array(-9,-227,668,729),311=>array(40,-227,634,760),312=>array(32,0,626,547),313=>array(39,0,556,928),314=>array(114,0,556,928),315=>array(39,-227,516,729),316=>array(104,-224,505,760),317=>array(39,0,600,729),318=>array(114,0,641,760),319=>array(39,0,604,729),320=>array(114,0,678,760),321=>array(-34,0,516,729),322=>array(18,0,580,760),323=>array(-12,0,613,928),324=>array(29,0,587,804),325=>array(-12,-227,613,729),326=>array(29,-227,547,560),327=>array(-12,0,618,927),328=>array(29,0,581,800),329=>array(-84,0,625,760),330=>array(-0,-208,587,743),331=>array(50,-207,565,560),332=>array(30,-14,572,913),333=>array(43,-14,559,760),334=>array(30,-14,575,927),335=>array(43,-14,559,784),336=>array(30,-14,658,927),337=>array(43,-14,619,800),338=>array(15,0,660,729),339=>array(-10,-14,616,560),340=>array(4,0,569,928),341=>array(75,0,670,804),342=>array(4,-227,569,729),343=>array(16,-227,599,560),344=>array(4,0,583,927),345=>array(75,0,613,800),346=>array(2,-14,566,928),347=>array(44,-14,587,804),348=>array(2,-14,569,927),349=>array(44,-14,534,800),350=>array(2,-196,566,742),351=>array(44,-196,534,560),352=>array(2,-14,579,927),353=>array(44,-14,571,800),354=>array(74,-196,629,729),355=>array(80,-196,571,702),356=>array(88,0,629,927),357=>array(80,0,681,813),358=>array(88,0,629,729),359=>array(71,0,562,702),360=>array(22,-14,621,928),361=>array(52,-14,569,778),362=>array(22,-14,621,913),363=>array(52,-14,569,760),364=>array(22,-14,621,927),365=>array(52,-14,569,784),366=>array(22,-14,621,1053),367=>array(52,-14,569,891),368=>array(22,-14,658,927),369=>array(52,-14,619,800),370=>array(22,-204,621,729),371=>array(52,-196,569,547),372=>array(20,0,669,931),373=>array(44,0,647,804),374=>array(71,0,663,931),375=>array(-44,-207,614,804),376=>array(71,0,663,927),377=>array(-16,0,630,928),378=>array(24,0,587,804),379=>array(-16,0,630,927),380=>array(24,0,580,774),381=>array(-16,0,630,927),382=>array(24,0,580,800),383=>array(113,0,619,760),384=>array(23,-14,569,760),385=>array(17,0,607,730),386=>array(8,0,604,729),387=>array(0,-14,539,760),388=>array(29,0,555,729),389=>array(22,-14,561,760),390=>array(7,-14,528,742),391=>array(68,-14,704,802),392=>array(63,-14,702,760),393=>array(-8,0,569,729),394=>array(16,0,589,729),395=>array(29,0,637,729),396=>array(54,-14,634,760),397=>array(41,-220,574,560),398=>array(11,0,607,729),399=>array(44,-14,557,742),400=>array(29,-14,583,742),401=>array(-39,-207,641,729),402=>array(-50,-207,652,760),403=>array(12,-14,663,802),404=>array(41,-142,671,729),405=>array(-68,-1,611,760),406=>array(130,0,589,729),407=>array(13,0,589,729),408=>array(-62,0,649,729),409=>array(11,0,606,760),410=>array(86,0,482,760),411=>array(-35,0,489,760),412=>array(4,-13,636,729),413=>array(-77,-208,679,729),414=>array(49,-208,558,560),415=>array(30,-14,557,742),416=>array(-13,-14,661,759),417=>array(-0,-14,607,570),418=>array(-2,-14,659,742),419=>array(27,-208,675,560),420=>array(40,0,619,729),421=>array(-21,-208,558,760),422=>array(5,-116,561,729),423=>array(32,-14,574,742),424=>array(61,-14,544,560),425=>array(-23,0,629,729),426=>array(95,-207,600,760),427=>array(139,-207,630,702),428=>array(40,0,629,730),429=>array(65,0,557,760),430=>array(88,-208,627,729),431=>array(-27,-14,688,759),432=>array(-23,-14,608,570),433=>array(43,0,627,713),434=>array(30,0,538,729),435=>array(72,0,666,729),436=>array(-41,-207,659,547),437=>array(-15,0,631,729),438=>array(23,0,579,547),439=>array(-23,-14,629,729),440=>array(-26,-14,611,729),441=>array(22,-215,610,547),442=>array(-11,-208,585,547),443=>array(-16,0,551,742),444=>array(-23,-14,615,729),445=>array(-14,-215,573,547),446=>array(27,-15,514,702),447=>array(-18,-208,594,560),448=>array(165,0,438,729),449=>array(53,0,549,729),450=>array(8,0,604,729),451=>array(165,0,437,729),461=>array(-55,0,579,927),462=>array(23,-14,571,800),463=>array(13,0,589,927),464=>array(7,0,571,800),465=>array(30,-14,579,927),466=>array(43,-14,571,800),467=>array(22,-14,621,927),468=>array(52,-14,578,800),469=>array(22,-14,621,985),470=>array(52,-14,569,914),471=>array(22,-14,621,1007),472=>array(52,-14,648,1002),473=>array(22,-14,621,1008),474=>array(52,-14,626,1002),475=>array(22,-14,621,1008),476=>array(52,-14,569,1002),477=>array(41,-14,560,560),478=>array(-55,0,578,985),479=>array(23,-14,557,914),480=>array(-55,0,578,985),481=>array(23,-14,557,914),482=>array(-73,0,640,913),483=>array(-15,-14,601,760),486=>array(50,-14,646,927),487=>array(9,-207,581,800),488=>array(-9,0,668,927),489=>array(40,0,634,927),490=>array(30,-204,572,742),491=>array(43,-204,559,561),492=>array(30,-204,572,913),493=>array(43,-204,559,760),494=>array(-23,-14,629,927),495=>array(-14,-215,577,800),500=>array(50,-14,624,927),501=>array(9,-207,590,800),502=>array(-58,-14,608,729),504=>array(-12,0,613,927),505=>array(29,0,547,801),508=>array(-73,0,660,927),509=>array(-15,-14,601,800),510=>array(-69,-31,662,927),511=>array(-40,-57,640,800),512=>array(-55,0,558,927),513=>array(23,-14,557,800),514=>array(-55,0,550,927),515=>array(23,-14,557,784),516=>array(14,0,610,927),517=>array(37,-14,564,800),518=>array(14,0,610,927),519=>array(37,-14,564,784),520=>array(13,0,589,927),521=>array(7,0,527,800),522=>array(13,0,589,927),523=>array(7,0,527,784),524=>array(30,-14,572,927),525=>array(43,-14,559,800),526=>array(30,-14,572,927),527=>array(43,-14,559,784),528=>array(4,0,569,927),529=>array(75,0,599,800),530=>array(4,0,569,927),531=>array(75,0,599,784),532=>array(22,-14,621,927),533=>array(52,-14,569,800),534=>array(22,-14,621,927),535=>array(52,-14,569,784),536=>array(2,-246,566,742),537=>array(44,-246,534,560),538=>array(66,-246,629,729),539=>array(80,-246,571,702),540=>array(-18,-210,677,742),541=>array(9,-211,620,560),542=>array(-4,0,606,927),543=>array(29,0,556,927),545=>array(-10,-68,564,760),548=>array(5,-207,651,729),549=>array(46,-207,602,547),550=>array(-55,0,515,927),551=>array(23,-14,557,774),552=>array(14,-196,610,729),553=>array(37,-196,564,561),554=>array(30,-14,578,985),555=>array(43,-14,559,914),556=>array(30,-14,578,985),557=>array(43,-14,559,914),558=>array(30,-14,572,927),559=>array(43,-14,559,774),560=>array(30,-14,578,985),561=>array(43,-14,559,914),562=>array(71,0,663,913),563=>array(-44,-207,614,760),564=>array(83,-68,544,760),565=>array(-30,-68,569,560),566=>array(77,-68,569,702),567=>array(-31,-207,460,547),568=>array(-13,-14,576,760),569=>array(26,-214,615,560),570=>array(-69,-31,663,761),571=>array(-69,-31,663,761),572=>array(-41,-57,640,603),573=>array(-6,0,542,729),574=>array(-61,-31,671,761),575=>array(65,-240,556,560),576=>array(49,-240,604,547),577=>array(44,0,612,729),579=>array(-39,0,575,730),580=>array(-8,-14,621,729),581=>array(-45,0,503,729),588=>array(-4,0,569,729),589=>array(68,0,599,560),592=>array(46,-14,568,560),593=>array(59,-14,597,560),594=>array(5,-14,543,560),595=>array(-14,-14,524,759),596=>array(35,-14,519,561),597=>array(84,-69,568,561),598=>array(32,-162,569,760),599=>array(15,-14,614,759),600=>array(18,-14,559,560),601=>array(41,-14,560,560),602=>array(-18,-14,604,560),603=>array(22,-11,581,560),604=>array(-0,-11,559,560),605=>array(-27,-11,584,560),606=>array(53,-21,575,559),607=>array(-4,-207,541,547),608=>array(-26,-208,688,760),609=>array(48,-208,615,547),610=>array(75,0,556,546),611=>array(35,-203,628,554),612=>array(102,-59,613,547),613=>array(86,-214,595,546),614=>array(7,0,516,759),615=>array(28,-208,536,759),616=>array(-22,0,499,760),617=>array(102,-1,500,547),618=>array(-1,0,604,547),619=>array(13,-1,562,759),620=>array(53,0,497,760),621=>array(129,-217,472,760),622=>array(86,-215,609,760),623=>array(21,-13,618,547),624=>array(40,-208,637,547),625=>array(4,-208,602,560),626=>array(-44,-216,603,560),627=>array(-0,-216,519,560),628=>array(5,0,597,547),629=>array(48,-14,554,560),630=>array(37,-1,613,547),631=>array(31,0,564,574),632=>array(-10,-208,612,762),633=>array(42,-13,565,547),634=>array(21,-13,586,759),635=>array(7,-208,531,547),636=>array(16,-208,580,560),637=>array(60,-208,580,560),638=>array(13,0,589,547),639=>array(13,0,504,547),640=>array(-2,0,501,547),641=>array(-21,0,624,547),642=>array(61,-208,551,560),643=>array(-50,-207,652,760),644=>array(-50,-207,652,760),645=>array(117,-207,485,760),646=>array(-38,-207,652,760),647=>array(28,-155,520,547),648=>array(103,-208,595,702),649=>array(33,-14,578,547),650=>array(42,-51,619,547),651=>array(73,-1,564,547),652=>array(-14,0,510,547),653=>array(-53,0,554,547),654=>array(-45,0,614,754),655=>array(86,0,622,547),656=>array(-11,-208,545,547),657=>array(10,-55,565,547),658=>array(-14,-215,577,547),659=>array(6,-215,582,547),660=>array(94,0,542,759),661=>array(102,0,588,759),662=>array(14,0,500,759),663=>array(40,-208,608,759),664=>array(26,-28,575,582),665=>array(5,0,545,547),666=>array(27,-21,549,559),667=>array(9,0,646,759),668=>array(5,0,597,547),669=>array(-26,-208,574,813),670=>array(29,-208,625,547),671=>array(62,0,462,547),672=>array(34,-208,632,759),673=>array(15,0,552,759),674=>array(92,0,579,759),675=>array(-5,-14,611,760),676=>array(1,-219,617,756),677=>array(-13,-55,604,760),678=>array(50,-14,584,702),679=>array(98,-207,629,760),680=>array(63,-69,597,702),681=>array(62,-207,587,760),682=>array(77,-14,585,760),683=>array(73,-2,612,760),684=>array(25,0,637,641),685=>array(85,86,517,641),686=>array(100,-214,628,759),687=>array(110,-208,529,759),688=>array(119,326,439,752),689=>array(119,326,439,751),690=>array(135,177,467,748),691=>array(136,326,463,640),692=>array(139,319,466,633),693=>array(115,209,443,632),694=>array(99,326,503,633),695=>array(138,326,524,633),696=>array(107,211,517,633),697=>array(220,557,408,800),699=>array(205,441,468,760),700=>array(180,441,443,760),701=>array(235,595,393,844),702=>array(293,481,460,760),703=>array(264,481,431,760),704=>array(174,326,454,751),705=>array(171,326,480,751),710=>array(164,616,534,800),711=>array(202,616,571,800),712=>array(228,488,374,759),713=>array(206,668,532,760),716=>array(228,-81,374,190),717=>array(38,-198,364,-106),718=>array(229,-285,470,-102),719=>array(230,-285,542,-102),720=>array(147,0,455,547),721=>array(218,361,419,547),722=>array(252,269,418,547),723=>array(223,269,390,547),726=>array(139,119,463,427),727=>array(183,229,419,317),728=>array(218,639,547,784),729=>array(290,654,447,774),730=>array(226,610,504,888),731=>array(125,-196,335,0),732=>array(184,638,551,778),733=>array(182,616,619,800),734=>array(-165,213,440,524),736=>array(135,216,504,640),737=>array(173,326,429,752),738=>array(140,319,445,640),739=>array(96,326,496,633),740=>array(172,326,479,751),741=>array(183,0,536,693),742=>array(154,0,536,693),743=>array(125,0,536,693),744=>array(96,0,536,693),745=>array(66,0,536,693),750=>array(72,441,589,760),755=>array(94,-245,313,-31),768=>array(181,616,422,800),769=>array(278,616,590,800),770=>array(164,616,534,800),771=>array(184,638,551,778),772=>array(206,668,532,760),773=>array(0,663,602,755),774=>array(218,639,547,784),775=>array(290,654,447,774),776=>array(203,654,535,774),777=>array(196,616,419,849),778=>array(226,610,504,888),779=>array(182,616,619,800),780=>array(202,616,571,800),781=>array(233,616,369,833),782=>array(94,616,508,833),783=>array(154,616,503,800),784=>array(218,639,547,879),785=>array(190,639,521,784),786=>array(212,441,422,590),787=>array(209,595,393,844),788=>array(235,595,393,844),789=>array(278,616,500,800),790=>array(247,-290,488,-106),791=>array(212,-290,524,-106),792=>array(151,-394,369,-123),793=>array(179,-394,397,-123),794=>array(174,658,463,929),795=>array(193,361,409,570),796=>array(147,-245,278,-31),797=>array(122,-305,412,-123),798=>array(89,-394,378,-212),799=>array(110,-394,399,-123),800=>array(156,-215,446,-123),801=>array(245,-207,551,82),802=>array(98,-208,325,81),803=>array(119,-226,277,-105),804=>array(32,-226,364,-105),805=>array(94,-245,313,-31),806=>array(66,-246,276,-97),807=>array(74,-196,311,0),808=>array(104,-196,314,0),809=>array(233,-323,369,-106),810=>array(129,-289,473,-106),811=>array(112,-239,515,-94),812=>array(36,-237,404,-53),813=>array(0,-237,368,-53),814=>array(48,-240,377,-95),815=>array(20,-239,351,-94),816=>array(14,-238,381,-98),817=>array(38,-198,364,-106),818=>array(0,-236,602,-143),819=>array(0,-236,602,-9),820=>array(26,226,576,396),821=>array(84,214,481,309),822=>array(-9,214,611,309),823=>array(-41,-57,640,603),824=>array(-69,-31,663,761),825=>array(128,-245,259,-31),826=>array(129,-254,473,-71),827=>array(134,-386,468,-106),828=>array(87,-239,490,-94),829=>array(160,582,442,839),830=>array(206,595,396,867),831=>array(0,528,602,755),835=>array(209,595,393,844),856=>array(592,654,749,774),865=>array(-132,735,706,880),884=>array(220,557,408,800),885=>array(194,-208,382,35),890=>array(185,-208,306,-45),894=>array(83,-140,412,519),900=>array(278,616,590,800),901=>array(203,654,645,999),902=>array(-55,0,515,800),903=>array(199,259,397,437),904=>array(-123,0,610,800),905=>array(-142,0,606,800),906=>array(-113,0,589,800),908=>array(-35,-14,572,800),910=>array(-193,0,663,800),911=>array(-25,0,559,800),912=>array(164,0,645,999),913=>array(-55,0,515,729),914=>array(-10,0,575,730),915=>array(89,0,685,729),916=>array(-55,0,515,729),917=>array(14,0,610,729),918=>array(-16,0,630,729),919=>array(-4,0,606,729),920=>array(44,-14,557,742),921=>array(13,0,589,729),922=>array(-9,0,668,729),923=>array(-55,0,515,729),924=>array(-28,0,630,729),925=>array(-12,0,613,729),926=>array(-4,0,606,729),927=>array(30,-14,572,742),928=>array(67,0,677,729),929=>array(8,0,591,729),931=>array(-23,0,629,729),932=>array(88,0,629,729),933=>array(71,0,663,729),934=>array(44,0,557,729),935=>array(-70,0,656,729),936=>array(77,0,634,729),937=>array(-25,0,559,713),938=>array(13,0,589,927),939=>array(71,0,663,927),940=>array(26,-12,615,800),941=>array(49,-11,590,800),942=>array(49,-208,590,800),943=>array(164,0,590,800),944=>array(69,0,645,999),945=>array(26,-12,615,559),946=>array(-31,-208,563,766),947=>array(32,-208,590,547),948=>array(27,-14,561,766),949=>array(49,-11,540,557),950=>array(66,-208,604,760),951=>array(49,-208,558,560),952=>array(47,-12,554,770),953=>array(164,0,446,547),954=>array(32,0,626,547),955=>array(36,0,560,760),956=>array(-27,-209,560,547),957=>array(76,0,573,547),958=>array(55,-208,604,760),959=>array(43,-14,559,561),960=>array(4,-19,602,547),961=>array(-1,-208,577,560),962=>array(101,-208,585,561),963=>array(21,-14,598,547),964=>array(98,0,589,547),965=>array(69,0,580,547),966=>array(35,-208,574,552),967=>array(-30,-208,632,547),968=>array(56,-208,643,547),969=>array(31,-14,577,547),970=>array(164,0,535,774),971=>array(69,0,580,774),972=>array(43,-14,590,800),973=>array(69,0,590,800),974=>array(31,-14,590,800),976=>array(54,-11,542,768),977=>array(46,-11,553,768),978=>array(12,0,568,729),979=>array(-228,0,568,800),980=>array(12,0,568,927),981=>array(27,-208,573,760),982=>array(9,0,627,547),983=>array(3,-188,632,547),984=>array(63,-208,576,742),985=>array(66,-208,573,560),986=>array(44,-222,639,729),987=>array(36,-208,602,547),988=>array(23,0,619,729),989=>array(-83,-208,581,760),990=>array(9,-2,602,729),991=>array(42,0,560,759),992=>array(52,-208,563,742),993=>array(-15,-180,501,559),1008=>array(-17,-3,613,547),1009=>array(39,-213,578,560),1010=>array(73,-14,565,560),1011=>array(-31,-207,512,813),1012=>array(44,-14,557,742),1013=>array(78,-14,562,561),1014=>array(34,-14,518,561),1015=>array(8,0,569,729),1016=>array(-18,-208,571,760),1017=>array(64,-14,595,742),1018=>array(-29,0,631,729),1019=>array(-27,-208,629,498),1020=>array(-42,-208,577,560),1021=>array(7,-14,528,742),1022=>array(64,-14,595,742),1023=>array(7,-14,528,742),1024=>array(14,0,610,927),1025=>array(14,0,610,927),1026=>array(76,-207,631,760),1027=>array(89,0,685,927),1028=>array(61,-14,595,742),1029=>array(2,-14,566,742),1030=>array(13,0,589,729),1031=>array(13,0,589,927),1032=>array(-10,-14,563,729),1033=>array(-78,0,576,729),1034=>array(-61,0,576,729),1035=>array(76,0,631,760),1036=>array(-9,0,668,927),1037=>array(-13,0,614,927),1038=>array(20,0,659,927),1039=>array(11,-157,621,729),1040=>array(-55,0,515,729),1041=>array(8,0,604,729),1042=>array(-10,0,575,730),1043=>array(89,0,685,729),1044=>array(-66,-157,601,729),1045=>array(14,0,610,729),1046=>array(-64,0,667,729),1047=>array(-15,-14,547,742),1048=>array(-13,0,614,729),1049=>array(-13,0,614,927),1050=>array(-9,0,668,729),1051=>array(-68,0,606,729),1052=>array(-28,0,630,729),1053=>array(-4,0,606,729),1054=>array(30,-14,572,742),1055=>array(67,0,677,729),1056=>array(8,0,591,729),1057=>array(64,-14,595,742),1058=>array(88,0,629,729),1059=>array(20,0,659,729),1060=>array(11,0,599,729),1061=>array(-70,0,656,729),1062=>array(-17,-157,593,729),1063=>array(73,0,624,760),1064=>array(-33,0,634,729),1065=>array(-18,-157,649,729),1066=>array(61,0,553,729),1067=>array(-51,0,653,729),1068=>array(-10,0,521,729),1069=>array(7,-14,542,742),1070=>array(-51,-14,599,742),1071=>array(-30,0,637,729),1072=>array(23,-14,557,560),1073=>array(18,-14,565,787),1074=>array(5,0,548,547),1075=>array(55,0,552,547),1076=>array(-36,-140,583,547),1077=>array(37,-14,564,561),1078=>array(-46,0,647,547),1079=>array(25,-11,538,560),1080=>array(21,0,586,547),1081=>array(21,0,586,784),1082=>array(32,0,626,547),1083=>array(-20,0,604,547),1084=>array(-11,0,613,547),1085=>array(31,0,576,547),1086=>array(43,-14,559,561),1087=>array(31,0,576,547),1088=>array(-18,-208,571,560),1089=>array(73,-14,565,560),1090=>array(112,0,576,547),1091=>array(-44,-207,614,547),1092=>array(30,-208,571,760),1093=>array(-37,0,599,547),1094=>array(8,-140,553,547),1095=>array(145,0,624,547),1096=>array(-15,0,617,547),1097=>array(-11,-140,621,547),1098=>array(51,0,552,547),1099=>array(-38,0,640,547),1100=>array(14,0,501,547),1101=>array(34,-14,526,560),1102=>array(0,-14,655,560),1103=>array(-6,0,594,547),1104=>array(37,-14,564,800),1105=>array(37,-14,564,774),1106=>array(40,-207,543,760),1107=>array(55,0,590,800),1108=>array(135,-14,619,561),1109=>array(44,-14,534,560),1110=>array(7,0,527,813),1111=>array(7,0,554,774),1112=>array(-31,-207,512,813),1113=>array(-51,0,583,547),1114=>array(-36,0,583,547),1115=>array(20,0,502,760),1116=>array(32,0,626,800),1117=>array(21,0,586,800),1118=>array(-44,-207,614,784),1119=>array(44,-140,590,547),1122=>array(45,0,546,729),1123=>array(57,0,548,760),1138=>array(30,-14,557,742),1139=>array(48,-14,554,560),1168=>array(89,0,714,878),1169=>array(41,0,566,700),1170=>array(86,0,685,729),1171=>array(35,0,552,547),1172=>array(89,-207,685,729),1173=>array(108,-207,605,547),1174=>array(-64,-157,667,729),1175=>array(-46,-140,647,547),1176=>array(-15,-196,547,742),1177=>array(25,-196,538,560),1178=>array(-9,-193,668,729),1179=>array(85,-158,680,547),1186=>array(18,-193,628,729),1187=>array(14,-158,614,547),1188=>array(-33,0,663,729),1189=>array(-15,0,644,547),1194=>array(64,-196,595,742),1195=>array(73,-196,565,560),1196=>array(161,-193,700,729),1197=>array(167,-158,629,547),1198=>array(71,0,663,729),1199=>array(69,-208,615,547),1200=>array(62,0,665,729),1201=>array(44,-208,615,547),1202=>array(13,-193,725,729),1203=>array(27,-158,666,547),1210=>array(49,0,610,760),1211=>array(29,0,547,760),1216=>array(13,0,589,729),1217=>array(-64,0,667,927),1218=>array(-46,0,647,784),1219=>array(-9,-207,666,729),1220=>array(85,-207,680,547),1223=>array(-4,-207,606,729),1224=>array(84,-207,629,547),1227=>array(146,-193,698,760),1228=>array(145,-158,624,547),1231=>array(136,0,427,760),1232=>array(-55,0,575,927),1233=>array(23,-14,557,784),1234=>array(-55,0,554,927),1235=>array(23,-14,557,774),1236=>array(-73,0,640,729),1237=>array(-15,-14,601,560),1238=>array(14,0,610,927),1239=>array(37,-14,564,784),1240=>array(44,-14,557,742),1241=>array(41,-14,560,560),1242=>array(44,-14,557,927),1243=>array(41,-14,560,774),1244=>array(-64,0,667,927),1245=>array(-46,0,647,774),1246=>array(-15,-14,547,927),1247=>array(25,-11,582,774),1248=>array(-23,-14,629,729),1249=>array(-14,-215,577,547),1250=>array(-13,0,614,913),1251=>array(21,0,586,760),1252=>array(-13,0,614,927),1253=>array(21,0,586,762),1254=>array(30,-14,572,927),1255=>array(43,-14,559,774),1256=>array(44,-14,557,742),1257=>array(48,-14,554,560),1258=>array(44,-14,557,927),1259=>array(48,-14,554,774),1260=>array(7,-14,596,927),1261=>array(34,-14,563,774),1262=>array(20,0,659,913),1263=>array(-44,-207,614,760),1264=>array(20,0,659,927),1265=>array(-44,-207,614,774),1266=>array(20,0,659,927),1267=>array(-44,-207,619,800),1268=>array(73,0,640,927),1269=>array(145,0,624,774),1270=>array(89,-193,685,729),1271=>array(108,-158,605,547),1272=>array(-51,0,653,927),1273=>array(-38,0,640,774),1296=>array(29,-14,583,742),1297=>array(49,-11,540,557),1306=>array(30,-137,572,742),1307=>array(33,-208,579,561),1308=>array(20,0,669,729),1309=>array(44,0,647,547),1329=>array(9,-31,606,729),1330=>array(-24,0,574,743),1331=>array(27,0,577,743),1332=>array(27,0,577,743),1333=>array(20,-14,583,729),1334=>array(-20,0,584,743),1335=>array(-16,0,583,729),1336=>array(-24,0,574,743),1337=>array(-50,-14,593,743),1338=>array(-13,-14,618,729),1339=>array(-19,0,542,729),1340=>array(3,0,480,729),1341=>array(-31,-13,601,729),1342=>array(18,-14,646,742),1343=>array(59,0,585,729),1344=>array(12,-37,605,729),1345=>array(0,-31,583,743),1346=>array(27,0,542,743),1347=>array(-12,0,639,741),1348=>array(-12,-14,657,729),1349=>array(16,-14,584,741),1350=>array(59,-14,574,729),1351=>array(17,-13,568,729),1352=>array(-20,0,578,743),1353=>array(38,-39,589,743),1354=>array(30,0,601,741),1355=>array(-17,0,589,741),1356=>array(-56,0,577,743),1357=>array(24,-14,622,729),1358=>array(23,0,585,729),1359=>array(22,-14,577,742),1360=>array(-20,0,578,743),1361=>array(16,-13,584,741),1362=>array(-16,0,583,729),1363=>array(2,0,602,729),1364=>array(-32,0,608,741),1365=>array(30,-14,572,742),1366=>array(-13,-14,582,729),1369=>array(264,481,431,760),1370=>array(169,411,432,730),1371=>array(115,616,486,800),1372=>array(40,618,562,893),1373=>array(151,616,450,800),1374=>array(7,590,565,906),1375=>array(78,618,507,760),1377=>array(21,-13,617,547),1378=>array(-1,-208,546,560),1379=>array(40,-208,588,560),1380=>array(16,-208,539,560),1381=>array(34,-14,566,760),1382=>array(40,-208,588,560),1383=>array(14,0,546,760),1384=>array(-1,-208,546,560),1385=>array(-48,-208,594,560),1386=>array(3,-14,604,760),1387=>array(-12,-208,536,760),1388=>array(86,-208,390,547),1389=>array(-55,-208,615,760),1390=>array(22,-14,583,760),1391=>array(64,-208,573,760),1392=>array(27,0,545,760),1393=>array(33,-14,513,760),1394=>array(16,-208,524,560),1395=>array(45,-14,583,741),1396=>array(63,-14,677,760),1397=>array(55,-207,547,547),1398=>array(77,-13,585,760),1399=>array(26,-208,559,559),1400=>array(27,0,545,560),1401=>array(54,-208,502,579),1402=>array(40,-208,636,547),1403=>array(36,-208,570,559),1404=>array(2,0,532,560),1405=>array(55,-14,572,547),1406=>array(31,-208,581,760),1407=>array(21,-13,581,560),1408=>array(7,-208,555,560),1409=>array(18,-207,590,562),1410=>array(39,0,478,547),1411=>array(20,-208,580,760),1412=>array(-36,-208,599,560),1413=>array(43,-14,559,561),1414=>array(-10,-208,592,760),1415=>array(-13,-14,528,760),1417=>array(169,0,433,519),1418=>array(137,217,472,359),3713=>array(-6,-10,581,560),3714=>array(26,-39,574,568),3716=>array(38,-10,562,568),3719=>array(48,-238,563,568),3720=>array(42,-0,570,575),3722=>array(39,-238,601,563),3725=>array(35,-14,605,560),3732=>array(23,-14,567,560),3733=>array(-12,-15,601,579),3734=>array(74,-240,601,560),3735=>array(18,-8,593,571),3737=>array(-20,-14,617,568),3738=>array(38,-8,594,561),3739=>array(19,-8,616,760),3740=>array(7,-8,687,648),3741=>array(-3,-8,636,760),3742=>array(10,-8,619,561),3743=>array(-9,-8,641,760),3745=>array(-32,-14,619,547),3746=>array(16,-14,627,760),3747=>array(22,-8,599,568),3749=>array(-3,-8,592,568),3751=>array(11,-13,586,560),3754=>array(-11,-8,698,648),3755=>array(-7,-12,608,575),3757=>array(18,-8,595,568),3758=>array(-3,-8,661,617),3759=>array(31,-126,636,579),3760=>array(69,-6,656,567),3761=>array(190,620,720,896),3762=>array(126,0,622,588),3763=>array(-425,0,622,846),3764=>array(3,622,595,950),3765=>array(-54,633,601,962),3766=>array(2,622,595,950),3767=>array(3,633,657,962),3768=>array(147,-385,395,-55),3769=>array(90,-316,418,-28),3771=>array(-14,610,610,896),3772=>array(-11,-311,609,-48),3784=>array(225,659,376,844),3785=>array(-10,622,627,918),3786=>array(20,619,729,963),3787=>array(125,612,478,917),3788=>array(167,603,787,866),3789=>array(177,639,427,846),4304=>array(30,0,552,567),4305=>array(18,0,538,758),4306=>array(8,-196,544,521),4307=>array(7,-197,624,516),4308=>array(12,-196,589,521),4309=>array(13,-196,587,521),4310=>array(16,0,538,757),4311=>array(3,0,605,516),4312=>array(37,0,563,521),4313=>array(15,-196,580,512),4314=>array(28,-196,585,521),4315=>array(18,0,596,757),4316=>array(16,0,568,745),4317=>array(0,0,601,516),4318=>array(11,0,567,754),4319=>array(11,-196,626,539),4320=>array(-21,0,580,765),4321=>array(17,0,538,741),4322=>array(-18,-197,590,656),4323=>array(35,-197,589,531),4324=>array(28,-196,625,521),4325=>array(-7,-196,646,741),4326=>array(22,-197,621,521),4327=>array(18,-196,622,506),4328=>array(21,0,604,757),4329=>array(-26,0,538,757),4330=>array(10,-196,590,539),4331=>array(17,0,626,741),4332=>array(16,0,645,757),4333=>array(-9,-196,563,741),4334=>array(21,0,542,741),4335=>array(5,-196,572,610),4336=>array(10,0,584,757),4337=>array(-0,-196,616,757),4338=>array(3,-134,576,521),4339=>array(12,-196,625,521),4340=>array(-8,-196,614,757),4341=>array(9,0,599,757),4342=>array(16,-196,626,521),4343=>array(4,-197,540,521),4344=>array(12,-197,583,534),4345=>array(62,-196,596,527),4346=>array(38,-95,569,521),4347=>array(87,24,481,492),4348=>array(170,359,453,758),7426=>array(5,-14,621,560),7432=>array(21,-11,580,560),7433=>array(93,-264,613,549),7444=>array(-19,-14,607,560),7446=>array(101,273,607,560),7447=>array(100,-14,607,273),7453=>array(20,0,653,440),7454=>array(32,-2,647,438),7455=>array(21,-0,670,523),7468=>array(82,326,441,734),7469=>array(80,326,516,734),7470=>array(102,326,465,735),7472=>array(107,326,462,734),7473=>array(119,326,484,734),7474=>array(119,326,484,734),7475=>array(139,318,477,742),7476=>array(114,326,488,734),7477=>array(125,326,477,734),7478=>array(128,318,480,734),7479=>array(91,326,505,734),7480=>array(119,326,417,734),7481=>array(98,326,503,734),7482=>array(109,326,494,734),7483=>array(109,326,494,734),7484=>array(131,318,470,742),7486=>array(110,326,471,734),7487=>array(92,326,449,734),7488=>array(165,326,502,734),7489=>array(129,318,499,734),7490=>array(128,326,530,734),7491=>array(132,318,467,640),7492=>array(135,318,470,640),7493=>array(143,318,483,640),7494=>array(110,318,497,640),7495=>array(108,318,449,751),7496=>array(132,318,496,751),7497=>array(134,318,469,640),7498=>array(133,318,468,640),7499=>array(126,320,473,640),7500=>array(129,320,476,640),7501=>array(145,210,495,640),7502=>array(176,178,502,633),7503=>array(102,326,469,751),7504=>array(106,326,479,640),7505=>array(144,210,463,640),7506=>array(137,318,465,640),7507=>array(137,318,442,640),7508=>array(126,479,449,640),7509=>array(153,318,476,479),7510=>array(106,209,470,640),7511=>array(162,326,471,719),7512=>array(150,318,470,632),7513=>array(101,326,493,573),7514=>array(123,319,496,632),7515=>array(166,326,496,632),7522=>array(137,0,465,455),7523=>array(136,0,463,314),7524=>array(150,-8,470,306),7525=>array(166,0,496,306),7543=>array(15,-208,587,561),7544=>array(114,326,488,734),7547=>array(52,0,657,547),7557=>array(170,-207,556,760),7579=>array(119,318,459,640),7580=>array(159,318,465,640),7581=>array(160,288,466,640),7582=>array(127,318,472,755),7583=>array(114,320,463,640),7584=>array(167,326,482,751),7585=>array(140,205,416,632),7586=>array(146,209,494,632),7587=>array(162,207,481,632),7588=>array(103,326,429,751),7589=>array(174,325,429,632),7590=>array(114,326,488,632),7591=>array(114,326,488,632),7592=>array(98,210,466,781),7593=>array(188,205,415,751),7594=>array(187,210,438,751),7595=>array(154,326,404,632),7596=>array(117,209,490,640),7597=>array(134,209,507,632),7598=>array(89,205,494,640),7599=>array(114,205,440,640),7600=>array(119,326,483,632),7601=>array(137,318,465,640),7602=>array(112,209,490,753),7603=>array(147,209,454,640),7604=>array(86,210,516,751),7605=>array(173,210,482,719),7606=>array(133,318,472,632),7607=>array(135,298,497,632),7609=>array(155,326,469,632),7610=>array(106,326,436,632),7611=>array(130,326,472,632),7612=>array(107,209,450,632),7613=>array(121,295,463,632),7614=>array(107,206,470,632),7615=>array(134,319,468,757),7680=>array(-55,-245,515,729),7681=>array(23,-245,557,560),7682=>array(-10,0,575,927),7683=>array(23,-14,569,774),7684=>array(-10,-226,575,730),7685=>array(23,-226,569,760),7686=>array(-10,-198,575,730),7687=>array(23,-198,569,760),7688=>array(64,-196,600,927),7689=>array(73,-196,632,800),7690=>array(-4,0,569,927),7691=>array(32,-14,621,774),7692=>array(-4,-226,569,729),7693=>array(32,-226,621,760),7694=>array(-4,-198,569,729),7695=>array(32,-198,621,760),7696=>array(-17,-196,569,729),7697=>array(14,-196,621,760),7698=>array(-24,-237,569,729),7699=>array(0,-237,621,760),7704=>array(14,-237,610,729),7705=>array(19,-237,564,561),7706=>array(14,-238,610,729),7707=>array(33,-238,564,561),7708=>array(14,-196,610,927),7709=>array(37,-196,566,784),7710=>array(23,0,619,927),7711=>array(113,0,619,927),7712=>array(50,-14,586,913),7713=>array(9,-207,581,760),7714=>array(-4,0,606,927),7715=>array(29,0,547,927),7716=>array(-4,-226,606,729),7717=>array(29,-226,547,760),7718=>array(-4,0,606,915),7719=>array(29,0,547,934),7720=>array(-90,-196,606,729),7721=>array(-73,-196,547,760),7722=>array(-4,-240,606,729),7723=>array(29,-240,547,760),7724=>array(13,-238,589,729),7725=>array(7,-238,527,813),7728=>array(-9,0,668,927),7729=>array(40,0,634,927),7730=>array(-9,-226,668,729),7731=>array(40,-226,634,760),7732=>array(-9,-198,668,729),7733=>array(40,-198,634,760),7734=>array(39,-226,516,729),7735=>array(114,-226,505,760),7736=>array(39,-226,562,913),7737=>array(114,-226,562,913),7738=>array(39,-198,516,729),7739=>array(38,-198,505,760),7740=>array(24,-237,516,729),7741=>array(0,-237,505,760),7742=>array(-28,0,630,927),7743=>array(-16,0,590,800),7744=>array(-28,0,630,927),7745=>array(-16,0,589,774),7746=>array(-28,-226,630,729),7747=>array(-16,-226,589,560),7748=>array(-12,0,613,927),7749=>array(29,0,547,774),7750=>array(-12,-226,613,729),7751=>array(29,-226,547,560),7752=>array(-12,-198,613,729),7753=>array(29,-198,547,560),7754=>array(-12,-237,613,729),7755=>array(0,-237,547,560),7756=>array(30,-14,572,997),7757=>array(43,-14,625,997),7764=>array(8,0,591,931),7765=>array(-18,-208,590,800),7766=>array(8,0,591,927),7767=>array(-18,-208,571,774),7768=>array(4,0,569,927),7769=>array(75,0,599,774),7770=>array(4,-226,569,729),7771=>array(75,-226,599,560),7772=>array(4,-226,569,913),7773=>array(75,-226,599,760),7774=>array(4,-198,569,729),7775=>array(38,-198,599,560),7776=>array(2,-14,566,927),7777=>array(44,-14,534,774),7778=>array(2,-226,566,742),7779=>array(44,-226,534,560),7784=>array(2,-226,566,927),7785=>array(44,-226,534,774),7786=>array(88,0,629,927),7787=>array(80,0,571,927),7788=>array(88,-226,629,729),7789=>array(80,-226,571,702),7790=>array(38,-198,629,729),7791=>array(38,-198,571,702),7792=>array(0,-237,629,729),7793=>array(0,-237,571,702),7794=>array(22,-226,621,729),7795=>array(32,-226,569,547),7796=>array(14,-238,621,729),7797=>array(14,-238,569,547),7798=>array(0,-237,621,729),7799=>array(0,-237,569,547),7800=>array(22,-14,621,997),7801=>array(52,-14,625,997),7804=>array(99,0,647,916),7805=>array(84,0,601,758),7806=>array(99,-226,647,729),7807=>array(84,-226,601,547),7808=>array(20,0,669,931),7809=>array(44,0,647,804),7810=>array(20,0,669,931),7811=>array(44,0,647,804),7812=>array(20,0,669,922),7813=>array(44,0,647,741),7814=>array(20,0,669,927),7815=>array(44,0,647,774),7816=>array(20,-226,669,729),7817=>array(44,-226,647,547),7818=>array(-70,0,656,927),7819=>array(-37,0,599,774),7820=>array(-70,0,656,927),7821=>array(-37,0,599,734),7822=>array(71,0,663,927),7823=>array(-44,-207,614,774),7824=>array(-16,0,630,931),7825=>array(24,0,580,803),7826=>array(-16,-226,630,729),7827=>array(24,-226,580,547),7828=>array(-16,-198,630,729),7829=>array(24,-198,580,547),7830=>array(29,-198,547,760),7831=>array(80,0,571,876),7832=>array(44,0,647,898),7833=>array(-44,-207,614,898),7835=>array(113,0,619,927),7839=>array(27,-14,561,766),7840=>array(-55,-226,515,729),7841=>array(23,-226,557,560),7852=>array(-55,-226,531,931),7853=>array(23,-226,557,803),7856=>array(-55,0,575,997),7857=>array(23,-14,557,954),7862=>array(-55,-226,575,927),7863=>array(23,-226,557,759),7864=>array(14,-226,610,729),7865=>array(37,-226,564,561),7868=>array(14,0,610,928),7869=>array(37,-14,564,762),7878=>array(14,-226,610,931),7879=>array(37,-226,564,803),7882=>array(13,-226,589,729),7883=>array(7,-226,527,813),7884=>array(30,-226,572,742),7885=>array(43,-226,559,561),7896=>array(30,-226,572,931),7897=>array(43,-226,559,803),7898=>array(-13,-14,661,927),7899=>array(-0,-14,607,800),7900=>array(-13,-14,661,927),7901=>array(-0,-14,607,800),7904=>array(-13,-14,661,928),7905=>array(-0,-14,607,778),7906=>array(-13,-226,661,759),7907=>array(-0,-226,607,570),7908=>array(22,-226,621,729),7909=>array(52,-226,569,547),7912=>array(-27,-14,688,927),7913=>array(-23,-14,608,800),7914=>array(-27,-14,688,927),7915=>array(-23,-14,608,800),7918=>array(-27,-14,688,928),7919=>array(-23,-14,608,778),7920=>array(-27,-226,688,759),7921=>array(-23,-226,608,570),7922=>array(71,0,663,931),7923=>array(-44,-207,614,804),7924=>array(71,-226,663,729),7925=>array(-44,-226,614,547),7928=>array(71,0,663,928),7929=>array(-44,-207,614,762),7936=>array(26,-12,615,806),7937=>array(26,-12,615,806),7938=>array(26,-12,615,806),7939=>array(26,-12,615,806),7940=>array(26,-12,644,806),7941=>array(26,-12,653,806),7942=>array(26,-12,615,978),7943=>array(26,-12,615,978),7944=>array(-55,0,515,806),7945=>array(-55,0,515,806),7946=>array(-260,0,515,806),7947=>array(-240,0,515,806),7948=>array(-155,0,515,806),7949=>array(-160,0,515,806),7950=>array(-55,0,515,978),7951=>array(-55,0,515,978),7952=>array(49,-11,540,806),7953=>array(49,-11,540,806),7954=>array(49,-11,573,806),7955=>array(49,-11,578,806),7956=>array(49,-11,644,806),7957=>array(49,-11,653,806),7960=>array(-77,0,610,806),7961=>array(-52,0,610,806),7962=>array(-360,0,610,806),7963=>array(-340,0,610,806),7964=>array(-284,0,610,806),7965=>array(-284,0,610,806),7968=>array(49,-208,558,806),7969=>array(49,-208,558,806),7970=>array(49,-208,573,806),7971=>array(49,-208,578,806),7972=>array(49,-208,644,806),7973=>array(49,-208,653,806),7974=>array(49,-208,588,978),7975=>array(49,-208,588,978),7976=>array(-101,0,606,806),7977=>array(-77,0,606,806),7978=>array(-387,0,606,806),7979=>array(-367,0,606,806),7980=>array(-313,0,606,806),7981=>array(-309,0,606,806),7982=>array(-140,0,606,978),7983=>array(-140,0,606,978),7984=>array(164,0,461,806),7985=>array(164,0,461,806),7986=>array(111,0,573,806),7987=>array(131,0,578,806),7988=>array(160,0,644,806),7989=>array(164,0,653,806),7990=>array(164,0,588,978),7991=>array(164,0,588,978),7992=>array(-77,0,589,806),7993=>array(-52,0,589,806),7994=>array(-348,0,589,806),7995=>array(-338,0,589,806),7996=>array(-279,0,589,806),7997=>array(-279,0,589,806),7998=>array(-118,0,589,978),7999=>array(-118,0,589,978),8000=>array(43,-14,559,806),8001=>array(43,-14,559,806),8002=>array(43,-14,573,806),8003=>array(43,-14,578,806),8004=>array(43,-14,644,806),8005=>array(43,-14,653,806),8008=>array(-40,-14,572,806),8009=>array(-52,-14,572,806),8010=>array(-350,-14,572,806),8011=>array(-331,-14,572,806),8012=>array(-191,-14,572,806),8013=>array(-191,-14,572,806),8016=>array(69,0,580,806),8017=>array(69,0,580,806),8018=>array(69,0,580,806),8019=>array(69,0,580,806),8020=>array(69,0,644,806),8021=>array(69,0,653,806),8022=>array(69,0,588,978),8023=>array(69,0,588,978),8025=>array(-125,0,663,806),8027=>array(-382,0,663,806),8029=>array(-360,0,663,806),8031=>array(-196,0,663,978),8032=>array(31,-14,577,806),8033=>array(31,-14,577,806),8034=>array(31,-14,577,806),8035=>array(31,-14,578,806),8036=>array(31,-14,644,806),8037=>array(31,-14,653,806),8038=>array(31,-14,588,978),8039=>array(31,-14,588,978),8040=>array(-30,0,559,806),8041=>array(-40,0,559,806),8042=>array(-350,0,559,806),8043=>array(-331,0,559,806),8044=>array(-179,0,559,806),8045=>array(-174,0,559,806),8046=>array(-62,0,559,978),8047=>array(-98,0,559,978),8048=>array(26,-12,615,800),8049=>array(26,-12,615,800),8050=>array(49,-11,540,800),8051=>array(49,-11,590,800),8052=>array(49,-208,558,800),8053=>array(49,-208,590,800),8054=>array(164,0,446,800),8055=>array(164,0,590,800),8056=>array(43,-14,559,800),8057=>array(43,-14,590,800),8058=>array(69,0,580,800),8059=>array(69,0,590,800),8060=>array(31,-14,577,800),8061=>array(31,-14,590,800),8064=>array(26,-208,615,806),8065=>array(26,-208,615,806),8066=>array(26,-208,615,806),8067=>array(26,-208,615,806),8068=>array(26,-208,644,806),8069=>array(26,-208,653,806),8070=>array(26,-208,615,978),8071=>array(26,-208,615,978),8072=>array(-55,-208,515,806),8073=>array(-55,-208,515,806),8074=>array(-260,-208,515,806),8075=>array(-240,-208,515,806),8076=>array(-155,-208,515,806),8077=>array(-160,-208,515,806),8078=>array(-55,-208,515,978),8079=>array(-55,-208,515,978),8080=>array(33,-208,558,806),8081=>array(33,-208,558,806),8082=>array(33,-208,573,806),8083=>array(33,-208,578,806),8084=>array(33,-208,644,806),8085=>array(33,-208,653,806),8086=>array(33,-208,588,978),8087=>array(33,-208,588,978),8088=>array(-101,-208,606,806),8089=>array(-77,-208,606,806),8090=>array(-387,-208,606,806),8091=>array(-367,-208,606,806),8092=>array(-313,-208,606,806),8093=>array(-309,-208,606,806),8094=>array(-140,-208,606,978),8095=>array(-140,-208,606,978),8096=>array(31,-208,577,806),8097=>array(31,-208,577,806),8098=>array(31,-208,577,806),8099=>array(31,-208,578,806),8100=>array(31,-208,644,806),8101=>array(31,-208,653,806),8102=>array(31,-208,588,978),8103=>array(31,-208,588,978),8104=>array(-30,-208,559,806),8105=>array(-40,-208,559,806),8106=>array(-350,-208,559,806),8107=>array(-331,-208,559,806),8108=>array(-179,-208,559,806),8109=>array(-174,-208,559,806),8110=>array(-62,-208,559,978),8111=>array(-98,-208,559,978),8112=>array(26,-12,615,784),8113=>array(26,-12,615,760),8114=>array(26,-208,615,800),8115=>array(26,-208,615,559),8116=>array(26,-208,615,800),8118=>array(26,-12,615,778),8119=>array(26,-208,615,778),8120=>array(-55,0,575,927),8121=>array(-55,0,562,913),8122=>array(-55,0,515,800),8123=>array(-55,0,515,800),8124=>array(-55,-208,515,729),8125=>array(263,595,461,806),8126=>array(185,-208,306,-45),8127=>array(263,595,461,806),8128=>array(184,638,551,778),8129=>array(203,654,592,944),8130=>array(33,-208,558,800),8131=>array(33,-208,558,560),8132=>array(33,-208,590,800),8134=>array(49,-208,558,778),8135=>array(33,-208,558,778),8136=>array(-161,0,610,800),8137=>array(-123,0,610,800),8138=>array(-175,0,606,800),8139=>array(-142,0,606,800),8140=>array(-4,-208,606,729),8141=>array(111,595,573,806),8142=>array(160,595,644,806),8143=>array(222,595,588,978),8144=>array(164,0,547,784),8145=>array(164,0,532,760),8146=>array(164,0,535,980),8147=>array(164,0,645,999),8150=>array(164,0,551,778),8151=>array(164,0,592,944),8152=>array(13,0,589,927),8153=>array(13,0,589,913),8154=>array(-146,0,589,800),8155=>array(-113,0,589,800),8157=>array(131,595,578,806),8158=>array(165,595,653,806),8159=>array(222,595,588,978),8160=>array(69,0,580,784),8161=>array(69,0,580,760),8162=>array(69,0,580,980),8163=>array(69,0,645,999),8164=>array(-1,-208,577,806),8165=>array(-1,-208,577,806),8166=>array(69,0,580,778),8167=>array(69,0,592,944),8168=>array(71,0,663,927),8169=>array(71,0,663,913),8170=>array(-185,0,663,800),8171=>array(-193,0,663,800),8172=>array(-62,0,591,806),8173=>array(181,654,535,980),8174=>array(203,654,645,999),8175=>array(181,616,422,800),8178=>array(31,-208,577,800),8179=>array(31,-208,577,547),8180=>array(31,-208,590,800),8182=>array(31,-14,577,778),8183=>array(31,-208,577,778),8184=>array(-139,-14,572,800),8185=>array(-35,-14,572,800),8186=>array(-134,0,559,800),8187=>array(-25,0,559,800),8188=>array(-25,-208,559,713),8189=>array(278,616,590,800),8190=>array(287,595,461,806),8208=>array(119,217,453,359),8209=>array(119,217,453,359),8210=>array(-29,217,597,337),8211=>array(-29,217,597,337),8212=>array(-29,217,597,337),8213=>array(-29,217,597,337),8214=>array(125,-236,476,764),8215=>array(0,-236,602,-9),8216=>array(205,441,468,760),8217=>array(205,441,468,760),8218=>array(84,-140,347,179),8219=>array(242,441,422,760),8220=>array(95,441,612,760),8221=>array(72,441,589,760),8222=>array(-38,-140,478,179),8223=>array(108,441,543,760),8224=>array(89,-96,559,729),8225=>array(24,-96,560,729),8226=>array(125,195,477,547),8227=>array(125,156,516,586),8230=>array(-42,0,537,179),8240=>array(0,0,602,699),8241=>array(0,0,602,699),8242=>array(297,547,553,729),8243=>array(206,547,645,729),8244=>array(114,547,736,729),8245=>array(332,547,518,729),8246=>array(239,547,610,729),8247=>array(149,547,701,729),8249=>array(149,69,428,517),8250=>array(155,69,433,517),8252=>array(15,0,587,729),8253=>array(143,0,559,742),8254=>array(0,663,602,755),8261=>array(109,-132,531,760),8262=>array(52,-132,473,760),8263=>array(-17,0,619,742),8264=>array(14,0,587,742),8265=>array(15,0,588,742),8267=>array(2,-96,608,729),8304=>array(148,319,513,742),8305=>array(137,326,465,781),8308=>array(132,326,479,734),8309=>array(116,319,513,734),8310=>array(141,319,513,742),8311=>array(126,326,513,734),8312=>array(141,319,513,742),8313=>array(141,319,513,742),8314=>array(132,352,470,652),8315=>array(132,469,470,535),8316=>array(139,407,464,596),8317=>array(187,252,415,751),8318=>array(187,252,415,751),8319=>array(130,326,450,640),8320=>array(148,-7,513,416),8321=>array(141,0,476,408),8322=>array(127,0,502,416),8323=>array(135,-7,508,416),8324=>array(132,0,479,408),8325=>array(116,-7,513,408),8326=>array(141,-7,513,416),8327=>array(126,0,513,408),8328=>array(141,-7,513,416),8329=>array(141,-7,513,416),8330=>array(132,25,470,326),8331=>array(132,143,470,208),8332=>array(139,81,464,270),8333=>array(187,-74,415,425),8334=>array(187,-74,415,425),8336=>array(132,-8,467,313),8337=>array(134,-8,469,313),8338=>array(137,-8,465,313),8339=>array(96,0,496,307),8340=>array(133,-8,468,313),8341=>array(119,0,439,426),8342=>array(102,0,469,425),8343=>array(173,0,429,426),8344=>array(106,0,479,313),8345=>array(130,0,450,313),8346=>array(106,-117,470,313),8347=>array(140,-7,445,314),8348=>array(162,0,471,393),8352=>array(37,0,641,729),8353=>array(33,-44,630,778),8354=>array(32,-14,619,742),8355=>array(3,0,628,729),8356=>array(-13,0,604,742),8357=>array(-11,-93,580,640),8358=>array(-39,0,641,729),8359=>array(0,-14,658,729),8360=>array(0,-14,597,729),8361=>array(0,0,666,729),8362=>array(-24,-14,655,729),8363=>array(32,-198,681,760),8364=>array(-16,-14,603,742),8365=>array(0,0,625,729),8366=>array(83,0,630,729),8367=>array(0,-223,638,742),8368=>array(1,-14,626,742),8369=>array(8,0,632,729),8370=>array(34,-81,605,809),8371=>array(-57,0,583,729),8372=>array(-29,-14,632,742),8373=>array(26,-147,639,760),8376=>array(54,0,629,729),8377=>array(56,0,630,729),8450=>array(57,-14,590,742),8453=>array(57,-24,602,752),8461=>array(11,0,588,729),8462=>array(29,0,547,760),8463=>array(29,0,547,760),8469=>array(24,0,580,729),8470=>array(-71,0,582,729),8471=>array(0,61,602,663),8473=>array(36,0,573,729),8474=>array(0,-146,598,742),8477=>array(4,0,597,729),8482=>array(0,447,550,729),8484=>array(6,0,584,729),8486=>array(-25,0,559,713),8490=>array(-9,0,668,729),8491=>array(-55,0,515,928),8494=>array(0,-12,602,647),8520=>array(-9,0,501,813),8531=>array(15,-139,575,810),8532=>array(1,-139,575,818),8533=>array(15,-139,580,810),8534=>array(1,-139,580,818),8535=>array(23,-139,580,818),8536=>array(21,-139,580,810),8537=>array(15,-139,580,810),8538=>array(4,-139,580,810),8539=>array(15,-139,580,810),8540=>array(23,-139,580,818),8541=>array(4,-139,580,810),8542=>array(0,-139,580,810),8543=>array(15,244,558,810),8592=>array(32,97,570,451),8593=>array(124,0,478,538),8594=>array(32,97,570,451),8595=>array(124,0,478,538),8596=>array(32,97,570,451),8597=>array(124,0,478,538),8598=>array(75,-10,522,437),8599=>array(80,-10,527,437),8600=>array(80,-15,526,432),8601=>array(75,-15,522,432),8602=>array(32,97,570,451),8603=>array(32,97,570,451),8604=>array(29,178,566,437),8605=>array(36,178,573,437),8606=>array(32,97,570,451),8607=>array(124,0,478,538),8608=>array(32,97,570,451),8609=>array(124,0,478,538),8610=>array(32,97,570,451),8611=>array(32,97,570,451),8612=>array(32,97,570,451),8613=>array(124,0,478,538),8614=>array(32,97,570,451),8615=>array(124,0,478,538),8616=>array(124,0,478,538),8617=>array(32,97,570,509),8618=>array(32,97,570,509),8619=>array(32,97,570,509),8620=>array(32,97,570,509),8621=>array(32,97,570,451),8622=>array(32,87,570,460),8623=>array(28,-2,562,700),8624=>array(89,0,527,689),8625=>array(75,0,513,689),8626=>array(89,-15,527,674),8627=>array(75,-15,513,674),8628=>array(91,0,526,555),8629=>array(31,-15,586,421),8630=>array(24,168,578,506),8631=>array(24,168,578,506),8632=>array(24,-10,578,542),8633=>array(32,-15,570,634),8634=>array(27,-19,575,511),8635=>array(27,-19,575,511),8636=>array(32,219,570,451),8637=>array(32,97,570,329),8638=>array(246,0,478,538),8639=>array(124,0,356,538),8640=>array(32,219,570,451),8641=>array(32,97,570,329),8642=>array(246,0,478,538),8643=>array(124,0,356,538),8644=>array(32,-15,570,575),8645=>array(6,0,596,538),8646=>array(32,-15,570,575),8647=>array(32,-15,570,575),8648=>array(6,0,596,538),8649=>array(32,-15,570,575),8650=>array(6,0,596,538),8651=>array(32,-15,570,575),8652=>array(32,-15,570,575),8653=>array(32,97,570,451),8654=>array(32,97,570,451),8655=>array(32,97,570,451),8656=>array(32,97,570,451),8657=>array(124,0,478,538),8658=>array(32,97,570,451),8659=>array(124,0,478,538),8660=>array(32,97,570,451),8661=>array(124,0,478,538),8662=>array(61,-28,526,437),8663=>array(76,-28,541,437),8664=>array(76,-15,541,451),8665=>array(61,-15,526,451),8666=>array(32,97,570,451),8667=>array(32,97,570,451),8668=>array(32,97,570,451),8669=>array(32,97,570,451),8670=>array(124,0,478,538),8671=>array(124,0,478,538),8672=>array(32,97,570,451),8673=>array(124,0,478,538),8674=>array(32,97,570,451),8675=>array(124,0,478,538),8676=>array(32,97,570,451),8677=>array(32,97,570,451),8678=>array(2,67,570,480),8679=>array(94,0,508,567),8680=>array(32,67,600,480),8681=>array(94,0,508,567),8682=>array(94,0,508,567),8683=>array(94,0,508,567),8684=>array(94,0,508,567),8685=>array(94,0,508,567),8686=>array(94,0,508,567),8687=>array(94,0,508,567),8688=>array(32,70,600,483),8689=>array(19,-10,578,549),8690=>array(21,0,581,559),8691=>array(94,0,508,567),8692=>array(32,97,570,451),8693=>array(6,0,596,538),8694=>array(32,-139,570,687),8695=>array(32,97,570,451),8696=>array(32,97,570,451),8697=>array(32,92,570,451),8698=>array(32,97,570,451),8699=>array(32,97,570,451),8700=>array(32,97,570,457),8701=>array(2,67,570,480),8702=>array(32,67,600,480),8703=>array(2,67,600,480),8704=>array(16,0,586,729),8705=>array(11,-14,592,742),8706=>array(58,-14,544,674),8707=>array(80,0,533,729),8708=>array(80,-46,533,775),8709=>array(31,43,572,584),8710=>array(-3,0,606,695),8711=>array(-3,0,606,695),8712=>array(49,0,553,744),8713=>array(49,-96,558,840),8714=>array(48,63,554,564),8715=>array(49,0,553,744),8716=>array(49,-96,558,840),8717=>array(48,63,554,564),8719=>array(74,-213,528,741),8721=>array(62,-213,539,741),8722=>array(32,256,569,372),8723=>array(43,0,559,627),8725=>array(0,-93,525,729),8727=>array(59,77,541,542),8728=>array(138,182,463,507),8729=>array(125,168,477,520),8730=>array(24,-19,573,843),8731=>array(24,-19,573,933),8732=>array(24,-19,573,924),8733=>array(86,109,516,508),8734=>array(6,109,596,508),8735=>array(43,122,559,638),8736=>array(43,122,559,638),8743=>array(89,0,513,579),8744=>array(89,0,513,579),8745=>array(89,0,513,579),8746=>array(89,0,513,579),8747=>array(71,-204,530,892),8748=>array(0,-204,602,892),8749=>array(-21,-204,623,892),8756=>array(72,51,532,580),8757=>array(72,51,530,580),8758=>array(219,51,383,580),8759=>array(72,51,532,580),8760=>array(32,256,569,619),8761=>array(36,51,578,580),8762=>array(23,26,581,603),8763=>array(43,0,559,624),8764=>array(43,229,559,398),8765=>array(43,229,559,398),8769=>array(43,48,559,577),8770=>array(43,124,559,482),8771=>array(43,144,559,498),8772=>array(43,16,560,637),8773=>array(43,29,559,614),8774=>array(43,-42,559,614),8775=>array(43,-70,559,695),8776=>array(43,124,559,498),8777=>array(43,30,559,596),8778=>array(43,29,559,587),8779=>array(43,12,559,587),8780=>array(43,29,559,614),8781=>array(42,83,559,543),8782=>array(43,10,559,617),8783=>array(43,144,559,617),8784=>array(43,144,559,707),8785=>array(43,-81,559,707),8786=>array(43,-81,559,707),8787=>array(43,-81,560,707),8788=>array(40,124,563,503),8789=>array(40,124,563,503),8790=>array(43,144,559,482),8791=>array(43,144,559,814),8792=>array(43,144,559,715),8793=>array(43,144,559,824),8794=>array(43,144,559,824),8795=>array(43,144,559,935),8796=>array(43,144,559,889),8797=>array(43,144,559,750),8798=>array(42,144,559,801),8799=>array(42,144,559,903),8800=>array(38,-5,564,631),8801=>array(43,29,559,597),8802=>array(43,-55,559,685),8803=>array(43,-47,559,688),8804=>array(43,0,559,582),8805=>array(43,0,559,582),8806=>array(43,-116,559,633),8807=>array(43,-116,559,633),8808=>array(43,-189,559,633),8809=>array(43,-189,559,633),8813=>array(42,-54,559,680),8814=>array(43,-3,559,629),8815=>array(43,53,559,574),8816=>array(43,-96,559,658),8817=>array(43,-96,559,656),8818=>array(43,-38,559,582),8819=>array(43,-38,559,582),8820=>array(43,-96,559,658),8821=>array(43,-98,559,656),8822=>array(43,-119,559,684),8823=>array(43,-119,559,684),8824=>array(43,-209,559,774),8825=>array(43,-209,559,774),8826=>array(42,-46,558,672),8827=>array(42,-46,558,672),8828=>array(43,-206,559,744),8829=>array(43,-206,559,744),8830=>array(43,-101,559,744),8831=>array(43,-101,559,744),8832=>array(42,-118,558,744),8833=>array(42,-118,558,744),8834=>array(43,67,559,559),8835=>array(43,67,559,559),8836=>array(43,-58,559,684),8837=>array(43,-58,559,684),8838=>array(43,-20,559,645),8839=>array(43,-20,559,645),8840=>array(43,-115,559,729),8841=>array(43,-115,559,729),8842=>array(43,-125,559,645),8843=>array(43,-125,559,645),8847=>array(43,42,559,584),8848=>array(43,42,559,584),8849=>array(43,-10,559,636),8850=>array(43,-10,559,636),8853=>array(13,25,589,604),8854=>array(13,25,589,604),8855=>array(13,25,589,604),8856=>array(13,25,589,604),8857=>array(13,25,589,604),8858=>array(13,25,589,604),8859=>array(13,25,589,604),8860=>array(13,25,589,604),8861=>array(13,25,589,604),8862=>array(24,37,579,591),8863=>array(24,37,579,591),8864=>array(24,37,579,591),8865=>array(24,37,579,591),8866=>array(32,0,569,627),8867=>array(32,0,569,627),8868=>array(32,0,569,627),8869=>array(32,0,569,627),8901=>array(219,259,382,437),8902=>array(110,183,492,545),8909=>array(43,144,559,498),8922=>array(43,-272,559,776),8923=>array(43,-272,559,776),8924=>array(43,0,559,582),8925=>array(43,0,559,582),8926=>array(43,-206,559,744),8927=>array(43,-206,559,744),8928=>array(43,-244,559,803),8929=>array(43,-244,559,803),8930=>array(43,-143,559,769),8931=>array(43,-143,559,769),8932=>array(43,-123,559,636),8933=>array(43,-123,559,636),8934=>array(43,-158,559,582),8935=>array(43,-158,559,582),8936=>array(43,-220,559,744),8937=>array(43,-220,559,744),8943=>array(28,225,574,404),8960=>array(31,43,572,584),8961=>array(56,152,540,453),8962=>array(54,0,548,596),8963=>array(71,406,530,746),8964=>array(71,-132,530,209),8965=>array(71,0,530,459),8966=>array(71,0,530,581),8968=>array(119,-132,541,760),8969=>array(179,-132,483,760),8970=>array(119,-132,423,760),8971=>array(61,-132,483,760),8972=>array(261,73,585,415),8973=>array(6,73,331,415),8974=>array(261,345,585,687),8975=>array(6,345,331,687),8976=>array(43,177,559,439),8977=>array(35,113,567,646),8978=>array(3,211,599,512),8979=>array(3,211,599,512),8980=>array(90,168,512,512),8981=>array(76,107,510,539),8984=>array(17,95,585,664),8985=>array(43,177,559,439),8988=>array(131,352,463,701),8989=>array(139,352,471,701),8990=>array(131,-70,463,279),8991=>array(139,-70,471,279),8992=>array(237,-250,566,925),8993=>array(33,-239,362,940),8997=>array(31,95,571,613),8998=>array(3,145,599,536),8999=>array(46,145,556,536),9000=>array(24,212,578,517),9003=>array(3,145,599,536),9013=>array(25,-33,576,296),9015=>array(125,-114,477,843),9016=>array(3,-114,599,843),9017=>array(3,-114,599,843),9018=>array(3,-114,599,843),9019=>array(3,-114,599,843),9020=>array(3,-114,599,843),9021=>array(3,-171,599,900),9022=>array(3,57,599,658),9025=>array(3,-100,599,829),9026=>array(3,-100,599,829),9027=>array(3,-114,599,843),9028=>array(3,-114,599,843),9031=>array(3,-114,599,843),9032=>array(3,-114,599,843),9033=>array(3,-29,599,729),9035=>array(16,-171,586,900),9036=>array(3,-100,599,829),9037=>array(3,-100,599,829),9040=>array(3,-114,599,843),9042=>array(16,-171,586,900),9043=>array(3,-100,599,829),9044=>array(3,-100,599,829),9047=>array(3,-114,599,843),9048=>array(113,-114,489,729),9049=>array(3,-114,599,729),9050=>array(3,-114,599,655),9051=>array(113,-114,489,496),9052=>array(3,-114,599,658),9054=>array(3,-114,599,843),9055=>array(-10,44,612,671),9056=>array(3,-114,599,843),9059=>array(110,183,492,652),9060=>array(147,222,455,676),9061=>array(3,57,599,847),9064=>array(43,226,559,676),9065=>array(43,53,559,676),9067=>array(16,0,586,729),9068=>array(43,-14,559,742),9069=>array(43,-171,559,900),9070=>array(113,-140,489,519),9071=>array(3,-114,599,843),9072=>array(3,-114,599,843),9075=>array(132,0,478,547),9076=>array(73,-208,558,560),9077=>array(31,-14,571,547),9078=>array(3,-114,599,559),9079=>array(64,-114,538,561),9080=>array(113,-114,489,547),9081=>array(3,-114,599,547),9082=>array(26,-12,568,559),9085=>array(8,-232,594,101),9088=>array(25,-33,576,528),9089=>array(3,92,599,528),9090=>array(3,92,599,528),9091=>array(3,172,599,572),9096=>array(35,27,566,601),9097=>array(34,46,567,579),9098=>array(34,46,567,579),9099=>array(34,46,567,579),9109=>array(3,-114,599,843),9115=>array(113,-252,488,928),9116=>array(113,-252,255,940),9117=>array(113,-240,488,940),9118=>array(114,-252,489,928),9119=>array(347,-252,489,940),9120=>array(114,-240,489,940),9121=>array(113,-252,488,928),9122=>array(113,-252,255,940),9123=>array(113,-240,488,940),9124=>array(113,-252,488,928),9125=>array(346,-252,488,940),9126=>array(113,-240,488,940),9127=>array(232,-261,594,928),9128=>array(8,-247,370,934),9129=>array(232,-240,594,934),9130=>array(232,-256,370,934),9131=>array(8,-261,370,928),9132=>array(232,-247,594,934),9133=>array(8,-240,370,934),9134=>array(237,-250,362,940),9166=>array(2,67,570,567),9167=>array(3,0,599,596),9251=>array(14,-232,574,101),9600=>array(-10,260,612,770),9601=>array(-10,-250,612,-123),9602=>array(-10,-250,612,5),9603=>array(-10,-250,612,132),9604=>array(-10,-250,612,260),9605=>array(-10,-250,612,387),9606=>array(-10,-250,612,515),9607=>array(-10,-250,612,642),9608=>array(-10,-250,612,770),9609=>array(-10,-250,534,770),9610=>array(-10,-250,457,770),9611=>array(-10,-250,379,770),9612=>array(-10,-250,301,770),9613=>array(-10,-250,223,770),9614=>array(-10,-250,146,770),9615=>array(-10,-250,68,770),9616=>array(301,-250,612,770),9617=>array(-10,-250,534,770),9618=>array(-10,-250,612,770),9619=>array(-10,-250,612,770),9620=>array(-10,642,612,770),9621=>array(534,-250,611,770),9622=>array(-10,-250,301,260),9623=>array(301,-250,612,260),9624=>array(-10,260,301,770),9625=>array(-10,-250,612,770),9626=>array(-10,-250,612,770),9627=>array(-10,-250,612,770),9628=>array(-10,-250,612,770),9629=>array(301,260,612,770),9630=>array(-10,-250,612,770),9631=>array(-10,-250,612,770),9632=>array(3,-39,599,558),9633=>array(3,-39,599,558),9634=>array(3,-39,599,558),9635=>array(3,-39,599,558),9636=>array(3,-39,599,558),9637=>array(3,-39,599,558),9638=>array(3,-39,599,558),9639=>array(3,-39,599,558),9640=>array(3,-39,599,558),9641=>array(3,-39,599,558),9642=>array(107,66,495,454),9643=>array(107,66,495,454),9644=>array(3,117,599,402),9645=>array(3,117,599,402),9646=>array(158,-39,444,558),9647=>array(158,-39,444,558),9648=>array(3,117,599,402),9649=>array(3,117,599,402),9650=>array(3,-39,599,558),9651=>array(3,-39,599,558),9652=>array(107,66,495,454),9653=>array(107,66,495,454),9654=>array(3,-39,599,558),9655=>array(3,-39,599,558),9656=>array(107,66,495,454),9657=>array(107,66,495,454),9658=>array(3,66,599,454),9659=>array(3,66,599,454),9660=>array(3,-39,599,558),9661=>array(3,-39,599,558),9662=>array(107,66,495,454),9663=>array(107,66,495,454),9664=>array(3,-39,599,558),9665=>array(3,-39,599,558),9666=>array(107,66,495,454),9667=>array(107,66,495,454),9668=>array(3,66,599,454),9669=>array(3,66,599,454),9670=>array(3,-39,599,558),9671=>array(3,-38,599,558),9672=>array(3,-39,599,558),9673=>array(3,-41,599,561),9674=>array(57,-233,545,807),9675=>array(3,-41,599,561),9676=>array(3,-41,599,561),9677=>array(3,-41,599,561),9678=>array(3,-41,599,561),9679=>array(3,-41,599,561),9680=>array(3,-41,599,561),9681=>array(3,-41,599,561),9682=>array(3,-41,599,561),9683=>array(3,-41,599,561),9684=>array(3,-41,599,561),9685=>array(3,-41,599,561),9686=>array(152,-41,450,561),9687=>array(152,-41,450,561),9688=>array(-10,-10,612,770),9689=>array(-10,-250,612,770),9690=>array(-10,260,612,770),9691=>array(-10,-250,612,260),9692=>array(152,260,450,561),9693=>array(152,260,450,561),9694=>array(152,-41,450,260),9695=>array(152,-41,450,260),9696=>array(3,260,599,561),9697=>array(3,-41,599,260),9698=>array(3,-39,599,558),9699=>array(3,-39,599,558),9700=>array(3,-39,599,558),9701=>array(3,-39,599,558),9702=>array(125,195,477,547),9703=>array(3,-39,599,558),9704=>array(3,-39,599,558),9705=>array(3,-39,599,558),9706=>array(3,-39,599,558),9707=>array(3,-39,599,558),9708=>array(3,-39,599,558),9709=>array(3,-39,599,558),9710=>array(3,-39,599,558),9711=>array(-10,-54,612,573),9712=>array(3,-39,599,558),9713=>array(3,-39,599,558),9714=>array(3,-39,599,558),9715=>array(3,-39,599,558),9716=>array(3,-41,599,561),9717=>array(3,-41,599,561),9718=>array(3,-41,599,561),9719=>array(3,-41,599,561),9720=>array(3,-39,599,558),9721=>array(3,-39,599,558),9722=>array(3,-39,599,558),9723=>array(47,6,554,513),9724=>array(47,6,554,513),9725=>array(85,44,516,475),9726=>array(85,44,516,475),9727=>array(3,-39,599,558),9728=>array(17,80,585,649),9784=>array(13,82,589,642),9785=>array(16,80,586,650),9786=>array(16,80,586,650),9787=>array(16,80,586,650),9788=>array(16,80,586,650),9791=>array(92,-78,510,708),9792=>array(71,-49,531,655),9793=>array(71,-49,531,655),9794=>array(10,75,592,648),9795=>array(35,21,567,710),9796=>array(85,21,517,710),9797=>array(33,65,569,666),9798=>array(37,65,565,666),9799=>array(105,21,497,710),9824=>array(63,65,540,664),9825=>array(7,65,595,663),9826=>array(71,65,531,664),9827=>array(24,65,578,664),9828=>array(62,65,540,664),9829=>array(5,65,597,664),9830=>array(71,65,531,664),9831=>array(24,65,578,667),9833=>array(181,16,421,708),9834=>array(79,16,523,708),9835=>array(52,-79,550,706),9836=>array(8,61,594,664),9837=>array(158,18,444,710),9838=>array(211,21,391,710),9839=>array(152,21,450,710),10178=>array(32,0,569,627),10181=>array(76,-163,509,769),10182=>array(35,-163,547,769),10208=>array(57,-233,545,807),10214=>array(59,-132,565,760),10215=>array(37,-132,543,760),10216=>array(165,-132,524,759),10217=>array(78,-132,438,759),10731=>array(57,-233,545,807),10746=>array(32,45,569,582),10747=>array(32,45,569,582),10799=>array(58,72,543,556),10858=>array(43,229,559,624),10859=>array(43,0,559,624),11013=>array(41,190,561,494),11014=>array(149,82,453,602),11015=>array(149,82,453,602),11016=>array(68,109,485,526),11017=>array(117,109,534,526),11018=>array(117,109,534,526),11019=>array(68,109,485,526),11020=>array(41,190,561,494),11021=>array(149,82,453,602),11026=>array(3,-39,599,558),11027=>array(3,-39,599,558),11028=>array(3,-39,599,558),11029=>array(3,-39,599,558),11030=>array(3,-39,599,558),11031=>array(3,-39,599,558),11032=>array(3,-39,599,558),11033=>array(3,-39,599,558),11034=>array(3,-39,599,558),11364=>array(-3,-208,583,729),11373=>array(30,-14,632,742),11374=>array(-28,-208,632,729),11375=>array(158,0,728,729),11376=>array(-24,-14,579,742),11381=>array(-4,0,552,729),11382=>array(31,0,540,547),11383=>array(31,0,570,552),11385=>array(94,-13,614,759),11386=>array(48,-14,554,560),11388=>array(135,-149,467,421),11389=>array(271,326,616,734),11390=>array(2,-239,566,742),11391=>array(9,-240,654,729),11800=>array(42,-13,458,729),11807=>array(43,0,559,398),11810=>array(196,314,531,760),11811=>array(207,314,473,760),11812=>array(109,-132,375,314),11813=>array(52,-132,386,314),11822=>array(121,0,550,742),42760=>array(183,0,536,693),42761=>array(154,0,536,693),42762=>array(125,0,536,693),42763=>array(96,0,536,693),42764=>array(66,0,536,693),42765=>array(66,0,536,693),42766=>array(66,0,506,693),42767=>array(66,0,477,693),42768=>array(66,0,448,693),42769=>array(66,0,419,693),42770=>array(66,0,536,693),42771=>array(66,0,506,693),42772=>array(66,0,477,693),42773=>array(66,0,448,693),42774=>array(66,0,419,693),42779=>array(178,326,462,736),42780=>array(140,324,424,734),42781=>array(206,326,396,734),42782=>array(206,326,396,734),42783=>array(142,0,333,408),42786=>array(89,0,515,729),42787=>array(131,0,481,547),42788=>array(89,224,564,742),42789=>array(89,42,564,560),42790=>array(-4,-208,606,729),42791=>array(29,-207,547,760),42889=>array(149,0,412,519),42890=>array(167,141,436,405),42891=>array(228,235,437,729),42892=>array(211,458,389,729),42893=>array(73,0,624,760),42894=>array(54,-217,475,760),42896=>array(-17,-157,608,729),42897=>array(8,-140,544,560),42922=>array(17,1,705,730),63173=>array(20,-14,604,760),64257=>array(32,0,625,760),64258=>array(32,0,625,760),65533=>array(-56,-138,599,927),65535=>array(51,-177,551,705)); -$cw=array(0=>602,32=>602,33=>602,34=>602,35=>602,36=>602,37=>602,38=>602,39=>602,40=>602,41=>602,42=>602,43=>602,44=>602,45=>602,46=>602,47=>602,48=>602,49=>602,50=>602,51=>602,52=>602,53=>602,54=>602,55=>602,56=>602,57=>602,58=>602,59=>602,60=>602,61=>602,62=>602,63=>602,64=>602,65=>602,66=>602,67=>602,68=>602,69=>602,70=>602,71=>602,72=>602,73=>602,74=>602,75=>602,76=>602,77=>602,78=>602,79=>602,80=>602,81=>602,82=>602,83=>602,84=>602,85=>602,86=>602,87=>602,88=>602,89=>602,90=>602,91=>602,92=>602,93=>602,94=>602,95=>602,96=>602,97=>602,98=>602,99=>602,100=>602,101=>602,102=>602,103=>602,104=>602,105=>602,106=>602,107=>602,108=>602,109=>602,110=>602,111=>602,112=>602,113=>602,114=>602,115=>602,116=>602,117=>602,118=>602,119=>602,120=>602,121=>602,122=>602,123=>602,124=>602,125=>602,126=>602,160=>602,161=>602,162=>602,163=>602,164=>602,165=>602,166=>602,167=>602,168=>602,169=>602,170=>602,171=>602,172=>602,173=>602,174=>602,175=>602,176=>602,177=>602,178=>602,179=>602,180=>602,181=>602,182=>602,183=>602,184=>602,185=>602,186=>602,187=>602,188=>602,189=>602,190=>602,191=>602,192=>602,193=>602,194=>602,195=>602,196=>602,197=>602,198=>602,199=>602,200=>602,201=>602,202=>602,203=>602,204=>602,205=>602,206=>602,207=>602,208=>602,209=>602,210=>602,211=>602,212=>602,213=>602,214=>602,215=>602,216=>602,217=>602,218=>602,219=>602,220=>602,221=>602,222=>602,223=>602,224=>602,225=>602,226=>602,227=>602,228=>602,229=>602,230=>602,231=>602,232=>602,233=>602,234=>602,235=>602,236=>602,237=>602,238=>602,239=>602,240=>602,241=>602,242=>602,243=>602,244=>602,245=>602,246=>602,247=>602,248=>602,249=>602,250=>602,251=>602,252=>602,253=>602,254=>602,255=>602,256=>602,257=>602,258=>602,259=>602,260=>602,261=>602,262=>602,263=>602,264=>602,265=>602,266=>602,267=>602,268=>602,269=>602,270=>602,271=>602,272=>602,273=>602,274=>602,275=>602,276=>602,277=>602,278=>602,279=>602,280=>602,281=>602,282=>602,283=>602,284=>602,285=>602,286=>602,287=>602,288=>602,289=>602,290=>602,291=>602,292=>602,293=>602,294=>602,295=>602,296=>602,297=>602,298=>602,299=>602,300=>602,301=>602,302=>602,303=>602,304=>602,305=>602,306=>602,307=>602,308=>602,309=>602,310=>602,311=>602,312=>602,313=>602,314=>602,315=>602,316=>602,317=>602,318=>602,319=>602,320=>602,321=>602,322=>602,323=>602,324=>602,325=>602,326=>602,327=>602,328=>602,329=>602,330=>602,331=>602,332=>602,333=>602,334=>602,335=>602,336=>602,337=>602,338=>602,339=>602,340=>602,341=>602,342=>602,343=>602,344=>602,345=>602,346=>602,347=>602,348=>602,349=>602,350=>602,351=>602,352=>602,353=>602,354=>602,355=>602,356=>602,357=>602,358=>602,359=>602,360=>602,361=>602,362=>602,363=>602,364=>602,365=>602,366=>602,367=>602,368=>602,369=>602,370=>602,371=>602,372=>602,373=>602,374=>602,375=>602,376=>602,377=>602,378=>602,379=>602,380=>602,381=>602,382=>602,383=>602,384=>602,385=>602,386=>602,387=>602,388=>602,389=>602,390=>602,391=>602,392=>602,393=>602,394=>602,395=>602,396=>602,397=>602,398=>602,399=>602,400=>602,401=>602,402=>602,403=>602,404=>602,405=>602,406=>602,407=>602,408=>602,409=>602,410=>602,411=>602,412=>602,413=>602,414=>602,415=>602,416=>602,417=>602,418=>602,419=>602,420=>602,421=>602,422=>602,423=>602,424=>602,425=>602,426=>602,427=>602,428=>602,429=>602,430=>602,431=>602,432=>602,433=>602,434=>602,435=>602,436=>602,437=>602,438=>602,439=>602,440=>602,441=>602,442=>602,443=>602,444=>602,445=>602,446=>602,447=>602,448=>602,449=>602,450=>602,451=>602,461=>602,462=>602,463=>602,464=>602,465=>602,466=>602,467=>602,468=>602,469=>602,470=>602,471=>602,472=>602,473=>602,474=>602,475=>602,476=>602,477=>602,478=>602,479=>602,480=>602,481=>602,482=>602,483=>602,486=>602,487=>602,488=>602,489=>602,490=>602,491=>602,492=>602,493=>602,494=>602,495=>602,500=>602,501=>602,502=>602,504=>602,505=>602,508=>602,509=>602,510=>602,511=>602,512=>602,513=>602,514=>602,515=>602,516=>602,517=>602,518=>602,519=>602,520=>602,521=>602,522=>602,523=>602,524=>602,525=>602,526=>602,527=>602,528=>602,529=>602,530=>602,531=>602,532=>602,533=>602,534=>602,535=>602,536=>602,537=>602,538=>602,539=>602,540=>602,541=>602,542=>602,543=>602,545=>602,548=>602,549=>602,550=>602,551=>602,552=>602,553=>602,554=>602,555=>602,556=>602,557=>602,558=>602,559=>602,560=>602,561=>602,562=>602,563=>602,564=>602,565=>602,566=>602,567=>602,568=>602,569=>602,570=>602,571=>602,572=>602,573=>602,574=>602,575=>602,576=>602,577=>602,579=>602,580=>602,581=>602,588=>602,589=>602,592=>602,593=>602,594=>602,595=>602,596=>602,597=>602,598=>602,599=>602,600=>602,601=>602,602=>602,603=>602,604=>602,605=>602,606=>602,607=>602,608=>602,609=>602,610=>602,611=>602,612=>602,613=>602,614=>602,615=>602,616=>602,617=>602,618=>602,619=>602,620=>602,621=>602,622=>602,623=>602,624=>602,625=>602,626=>602,627=>602,628=>602,629=>602,630=>602,631=>602,632=>602,633=>602,634=>602,635=>602,636=>602,637=>602,638=>602,639=>602,640=>602,641=>602,642=>602,643=>602,644=>602,645=>602,646=>602,647=>602,648=>602,649=>602,650=>602,651=>602,652=>602,653=>602,654=>602,655=>602,656=>602,657=>602,658=>602,659=>602,660=>602,661=>602,662=>602,663=>602,664=>602,665=>602,666=>602,667=>602,668=>602,669=>602,670=>602,671=>602,672=>602,673=>602,674=>602,675=>602,676=>602,677=>602,678=>602,679=>602,680=>602,681=>602,682=>602,683=>602,684=>602,685=>602,686=>602,687=>602,688=>602,689=>602,690=>602,691=>602,692=>602,693=>602,694=>602,695=>602,696=>602,697=>602,699=>602,700=>602,701=>602,702=>602,703=>602,704=>602,705=>602,710=>602,711=>602,712=>602,713=>602,716=>602,717=>602,718=>602,719=>602,720=>602,721=>602,722=>602,723=>602,726=>602,727=>602,728=>602,729=>602,730=>602,731=>602,732=>602,733=>602,734=>602,736=>602,737=>602,738=>602,739=>602,740=>602,741=>602,742=>602,743=>602,744=>602,745=>602,750=>602,755=>602,768=>602,769=>602,770=>602,771=>602,772=>602,773=>602,774=>602,775=>602,776=>602,777=>602,778=>602,779=>602,780=>602,781=>602,782=>602,783=>602,784=>602,785=>602,786=>602,787=>602,788=>602,789=>602,790=>602,791=>602,792=>602,793=>602,794=>602,795=>602,796=>602,797=>602,798=>602,799=>602,800=>602,801=>602,802=>602,803=>602,804=>602,805=>602,806=>602,807=>602,808=>602,809=>602,810=>602,811=>602,812=>602,813=>602,814=>602,815=>602,816=>602,817=>602,818=>602,819=>602,820=>602,821=>602,822=>602,823=>602,824=>602,825=>602,826=>602,827=>602,828=>602,829=>602,830=>602,831=>602,835=>602,856=>602,865=>602,884=>602,885=>602,890=>602,894=>602,900=>602,901=>602,902=>602,903=>602,904=>602,905=>602,906=>602,908=>602,910=>602,911=>602,912=>602,913=>602,914=>602,915=>602,916=>602,917=>602,918=>602,919=>602,920=>602,921=>602,922=>602,923=>602,924=>602,925=>602,926=>602,927=>602,928=>602,929=>602,931=>602,932=>602,933=>602,934=>602,935=>602,936=>602,937=>602,938=>602,939=>602,940=>602,941=>602,942=>602,943=>602,944=>602,945=>602,946=>602,947=>602,948=>602,949=>602,950=>602,951=>602,952=>602,953=>602,954=>602,955=>602,956=>602,957=>602,958=>602,959=>602,960=>602,961=>602,962=>602,963=>602,964=>602,965=>602,966=>602,967=>602,968=>602,969=>602,970=>602,971=>602,972=>602,973=>602,974=>602,976=>602,977=>602,978=>602,979=>602,980=>602,981=>602,982=>602,983=>602,984=>602,985=>602,986=>602,987=>602,988=>602,989=>602,990=>602,991=>602,992=>602,993=>602,1008=>602,1009=>602,1010=>602,1011=>602,1012=>602,1013=>602,1014=>602,1015=>602,1016=>602,1017=>602,1018=>602,1019=>602,1020=>602,1021=>602,1022=>602,1023=>602,1024=>602,1025=>602,1026=>602,1027=>602,1028=>602,1029=>602,1030=>602,1031=>602,1032=>602,1033=>602,1034=>602,1035=>602,1036=>602,1037=>602,1038=>602,1039=>602,1040=>602,1041=>602,1042=>602,1043=>602,1044=>602,1045=>602,1046=>602,1047=>602,1048=>602,1049=>602,1050=>602,1051=>602,1052=>602,1053=>602,1054=>602,1055=>602,1056=>602,1057=>602,1058=>602,1059=>602,1060=>602,1061=>602,1062=>602,1063=>602,1064=>602,1065=>602,1066=>602,1067=>602,1068=>602,1069=>602,1070=>602,1071=>602,1072=>602,1073=>602,1074=>602,1075=>602,1076=>602,1077=>602,1078=>602,1079=>602,1080=>602,1081=>602,1082=>602,1083=>602,1084=>602,1085=>602,1086=>602,1087=>602,1088=>602,1089=>602,1090=>602,1091=>602,1092=>602,1093=>602,1094=>602,1095=>602,1096=>602,1097=>602,1098=>602,1099=>602,1100=>602,1101=>602,1102=>602,1103=>602,1104=>602,1105=>602,1106=>602,1107=>602,1108=>602,1109=>602,1110=>602,1111=>602,1112=>602,1113=>602,1114=>602,1115=>602,1116=>602,1117=>602,1118=>602,1119=>602,1122=>602,1123=>602,1138=>602,1139=>602,1168=>602,1169=>602,1170=>602,1171=>602,1172=>602,1173=>602,1174=>602,1175=>602,1176=>602,1177=>602,1178=>602,1179=>602,1186=>602,1187=>602,1188=>602,1189=>602,1194=>602,1195=>602,1196=>602,1197=>602,1198=>602,1199=>602,1200=>602,1201=>602,1202=>602,1203=>602,1210=>602,1211=>602,1216=>602,1217=>602,1218=>602,1219=>602,1220=>602,1223=>602,1224=>602,1227=>602,1228=>602,1231=>602,1232=>602,1233=>602,1234=>602,1235=>602,1236=>602,1237=>602,1238=>602,1239=>602,1240=>602,1241=>602,1242=>602,1243=>602,1244=>602,1245=>602,1246=>602,1247=>602,1248=>602,1249=>602,1250=>602,1251=>602,1252=>602,1253=>602,1254=>602,1255=>602,1256=>602,1257=>602,1258=>602,1259=>602,1260=>602,1261=>602,1262=>602,1263=>602,1264=>602,1265=>602,1266=>602,1267=>602,1268=>602,1269=>602,1270=>602,1271=>602,1272=>602,1273=>602,1296=>602,1297=>602,1306=>602,1307=>602,1308=>602,1309=>602,1329=>602,1330=>602,1331=>602,1332=>602,1333=>602,1334=>602,1335=>602,1336=>602,1337=>602,1338=>602,1339=>602,1340=>602,1341=>602,1342=>602,1343=>602,1344=>602,1345=>602,1346=>602,1347=>602,1348=>602,1349=>602,1350=>602,1351=>602,1352=>602,1353=>602,1354=>602,1355=>602,1356=>602,1357=>602,1358=>602,1359=>602,1360=>602,1361=>602,1362=>602,1363=>602,1364=>602,1365=>602,1366=>602,1369=>602,1370=>602,1371=>602,1372=>602,1373=>602,1374=>602,1375=>602,1377=>602,1378=>602,1379=>602,1380=>602,1381=>602,1382=>602,1383=>602,1384=>602,1385=>602,1386=>602,1387=>602,1388=>602,1389=>602,1390=>602,1391=>602,1392=>602,1393=>602,1394=>602,1395=>602,1396=>602,1397=>602,1398=>602,1399=>602,1400=>602,1401=>602,1402=>602,1403=>602,1404=>602,1405=>602,1406=>602,1407=>602,1408=>602,1409=>602,1410=>602,1411=>602,1412=>602,1413=>602,1414=>602,1415=>602,1417=>602,1418=>602,3713=>602,3714=>602,3716=>602,3719=>602,3720=>602,3722=>602,3725=>602,3732=>602,3733=>602,3734=>602,3735=>602,3737=>602,3738=>602,3739=>602,3740=>602,3741=>602,3742=>602,3743=>602,3745=>602,3746=>602,3747=>602,3749=>602,3751=>602,3754=>602,3755=>602,3757=>602,3758=>602,3759=>602,3760=>602,3761=>602,3762=>602,3763=>602,3764=>602,3765=>602,3766=>602,3767=>602,3768=>602,3769=>602,3771=>602,3772=>602,3784=>602,3785=>602,3786=>602,3787=>602,3788=>602,3789=>602,4304=>602,4305=>602,4306=>602,4307=>602,4308=>602,4309=>602,4310=>602,4311=>602,4312=>602,4313=>602,4314=>602,4315=>602,4316=>602,4317=>602,4318=>602,4319=>602,4320=>602,4321=>602,4322=>602,4323=>602,4324=>602,4325=>602,4326=>602,4327=>602,4328=>602,4329=>602,4330=>602,4331=>602,4332=>602,4333=>602,4334=>602,4335=>602,4336=>602,4337=>602,4338=>602,4339=>602,4340=>602,4341=>602,4342=>602,4343=>602,4344=>602,4345=>602,4346=>602,4347=>602,4348=>602,7426=>602,7432=>602,7433=>602,7444=>602,7446=>602,7447=>602,7453=>602,7454=>602,7455=>602,7468=>602,7469=>602,7470=>602,7472=>602,7473=>602,7474=>602,7475=>602,7476=>602,7477=>602,7478=>602,7479=>602,7480=>602,7481=>602,7482=>602,7483=>602,7484=>602,7486=>602,7487=>602,7488=>602,7489=>602,7490=>602,7491=>602,7492=>602,7493=>602,7494=>602,7495=>602,7496=>602,7497=>602,7498=>602,7499=>602,7500=>602,7501=>602,7502=>602,7503=>602,7504=>602,7505=>602,7506=>602,7507=>602,7508=>602,7509=>602,7510=>602,7511=>602,7512=>602,7513=>602,7514=>602,7515=>602,7522=>602,7523=>602,7524=>602,7525=>602,7543=>602,7544=>602,7547=>602,7557=>602,7579=>602,7580=>602,7581=>602,7582=>602,7583=>602,7584=>602,7585=>602,7586=>602,7587=>602,7588=>602,7589=>602,7590=>602,7591=>602,7592=>602,7593=>602,7594=>602,7595=>602,7596=>602,7597=>602,7598=>602,7599=>602,7600=>602,7601=>602,7602=>602,7603=>602,7604=>602,7605=>602,7606=>602,7607=>602,7609=>602,7610=>602,7611=>602,7612=>602,7613=>602,7614=>602,7615=>602,7680=>602,7681=>602,7682=>602,7683=>602,7684=>602,7685=>602,7686=>602,7687=>602,7688=>602,7689=>602,7690=>602,7691=>602,7692=>602,7693=>602,7694=>602,7695=>602,7696=>602,7697=>602,7698=>602,7699=>602,7704=>602,7705=>602,7706=>602,7707=>602,7708=>602,7709=>602,7710=>602,7711=>602,7712=>602,7713=>602,7714=>602,7715=>602,7716=>602,7717=>602,7718=>602,7719=>602,7720=>602,7721=>602,7722=>602,7723=>602,7724=>602,7725=>602,7728=>602,7729=>602,7730=>602,7731=>602,7732=>602,7733=>602,7734=>602,7735=>602,7736=>602,7737=>602,7738=>602,7739=>602,7740=>602,7741=>602,7742=>602,7743=>602,7744=>602,7745=>602,7746=>602,7747=>602,7748=>602,7749=>602,7750=>602,7751=>602,7752=>602,7753=>602,7754=>602,7755=>602,7756=>602,7757=>602,7764=>602,7765=>602,7766=>602,7767=>602,7768=>602,7769=>602,7770=>602,7771=>602,7772=>602,7773=>602,7774=>602,7775=>602,7776=>602,7777=>602,7778=>602,7779=>602,7784=>602,7785=>602,7786=>602,7787=>602,7788=>602,7789=>602,7790=>602,7791=>602,7792=>602,7793=>602,7794=>602,7795=>602,7796=>602,7797=>602,7798=>602,7799=>602,7800=>602,7801=>602,7804=>602,7805=>602,7806=>602,7807=>602,7808=>602,7809=>602,7810=>602,7811=>602,7812=>602,7813=>602,7814=>602,7815=>602,7816=>602,7817=>602,7818=>602,7819=>602,7820=>602,7821=>602,7822=>602,7823=>602,7824=>602,7825=>602,7826=>602,7827=>602,7828=>602,7829=>602,7830=>602,7831=>602,7832=>602,7833=>602,7835=>602,7839=>602,7840=>602,7841=>602,7852=>602,7853=>602,7856=>602,7857=>602,7862=>602,7863=>602,7864=>602,7865=>602,7868=>602,7869=>602,7878=>602,7879=>602,7882=>602,7883=>602,7884=>602,7885=>602,7896=>602,7897=>602,7898=>602,7899=>602,7900=>602,7901=>602,7904=>602,7905=>602,7906=>602,7907=>602,7908=>602,7909=>602,7912=>602,7913=>602,7914=>602,7915=>602,7918=>602,7919=>602,7920=>602,7921=>602,7922=>602,7923=>602,7924=>602,7925=>602,7928=>602,7929=>602,7936=>602,7937=>602,7938=>602,7939=>602,7940=>602,7941=>602,7942=>602,7943=>602,7944=>602,7945=>602,7946=>602,7947=>602,7948=>602,7949=>602,7950=>602,7951=>602,7952=>602,7953=>602,7954=>602,7955=>602,7956=>602,7957=>602,7960=>602,7961=>602,7962=>602,7963=>602,7964=>602,7965=>602,7968=>602,7969=>602,7970=>602,7971=>602,7972=>602,7973=>602,7974=>602,7975=>602,7976=>602,7977=>602,7978=>602,7979=>602,7980=>602,7981=>602,7982=>602,7983=>602,7984=>602,7985=>602,7986=>602,7987=>602,7988=>602,7989=>602,7990=>602,7991=>602,7992=>602,7993=>602,7994=>602,7995=>602,7996=>602,7997=>602,7998=>602,7999=>602,8000=>602,8001=>602,8002=>602,8003=>602,8004=>602,8005=>602,8008=>602,8009=>602,8010=>602,8011=>602,8012=>602,8013=>602,8016=>602,8017=>602,8018=>602,8019=>602,8020=>602,8021=>602,8022=>602,8023=>602,8025=>602,8027=>602,8029=>602,8031=>602,8032=>602,8033=>602,8034=>602,8035=>602,8036=>602,8037=>602,8038=>602,8039=>602,8040=>602,8041=>602,8042=>602,8043=>602,8044=>602,8045=>602,8046=>602,8047=>602,8048=>602,8049=>602,8050=>602,8051=>602,8052=>602,8053=>602,8054=>602,8055=>602,8056=>602,8057=>602,8058=>602,8059=>602,8060=>602,8061=>602,8064=>602,8065=>602,8066=>602,8067=>602,8068=>602,8069=>602,8070=>602,8071=>602,8072=>602,8073=>602,8074=>602,8075=>602,8076=>602,8077=>602,8078=>602,8079=>602,8080=>602,8081=>602,8082=>602,8083=>602,8084=>602,8085=>602,8086=>602,8087=>602,8088=>602,8089=>602,8090=>602,8091=>602,8092=>602,8093=>602,8094=>602,8095=>602,8096=>602,8097=>602,8098=>602,8099=>602,8100=>602,8101=>602,8102=>602,8103=>602,8104=>602,8105=>602,8106=>602,8107=>602,8108=>602,8109=>602,8110=>602,8111=>602,8112=>602,8113=>602,8114=>602,8115=>602,8116=>602,8118=>602,8119=>602,8120=>602,8121=>602,8122=>602,8123=>602,8124=>602,8125=>602,8126=>602,8127=>602,8128=>602,8129=>602,8130=>602,8131=>602,8132=>602,8134=>602,8135=>602,8136=>602,8137=>602,8138=>602,8139=>602,8140=>602,8141=>602,8142=>602,8143=>602,8144=>602,8145=>602,8146=>602,8147=>602,8150=>602,8151=>602,8152=>602,8153=>602,8154=>602,8155=>602,8157=>602,8158=>602,8159=>602,8160=>602,8161=>602,8162=>602,8163=>602,8164=>602,8165=>602,8166=>602,8167=>602,8168=>602,8169=>602,8170=>602,8171=>602,8172=>602,8173=>602,8174=>602,8175=>602,8178=>602,8179=>602,8180=>602,8182=>602,8183=>602,8184=>602,8185=>602,8186=>602,8187=>602,8188=>602,8189=>602,8190=>602,8192=>602,8193=>602,8194=>602,8195=>602,8196=>602,8197=>602,8198=>602,8199=>602,8200=>602,8201=>602,8202=>602,8208=>602,8209=>602,8210=>602,8211=>602,8212=>602,8213=>602,8214=>602,8215=>602,8216=>602,8217=>602,8218=>602,8219=>602,8220=>602,8221=>602,8222=>602,8223=>602,8224=>602,8225=>602,8226=>602,8227=>602,8230=>602,8239=>602,8240=>602,8241=>602,8242=>602,8243=>602,8244=>602,8245=>602,8246=>602,8247=>602,8249=>602,8250=>602,8252=>602,8253=>602,8254=>602,8261=>602,8262=>602,8263=>602,8264=>602,8265=>602,8267=>602,8287=>602,8304=>602,8305=>602,8308=>602,8309=>602,8310=>602,8311=>602,8312=>602,8313=>602,8314=>602,8315=>602,8316=>602,8317=>602,8318=>602,8319=>602,8320=>602,8321=>602,8322=>602,8323=>602,8324=>602,8325=>602,8326=>602,8327=>602,8328=>602,8329=>602,8330=>602,8331=>602,8332=>602,8333=>602,8334=>602,8336=>602,8337=>602,8338=>602,8339=>602,8340=>602,8341=>602,8342=>602,8343=>602,8344=>602,8345=>602,8346=>602,8347=>602,8348=>602,8352=>602,8353=>602,8354=>602,8355=>602,8356=>602,8357=>602,8358=>602,8359=>602,8360=>602,8361=>602,8362=>602,8363=>602,8364=>602,8365=>602,8366=>602,8367=>602,8368=>602,8369=>602,8370=>602,8371=>602,8372=>602,8373=>602,8376=>602,8377=>602,8450=>602,8453=>602,8461=>602,8462=>602,8463=>602,8469=>602,8470=>602,8471=>602,8473=>602,8474=>602,8477=>602,8482=>602,8484=>602,8486=>602,8490=>602,8491=>602,8494=>602,8520=>602,8531=>602,8532=>602,8533=>602,8534=>602,8535=>602,8536=>602,8537=>602,8538=>602,8539=>602,8540=>602,8541=>602,8542=>602,8543=>602,8592=>602,8593=>602,8594=>602,8595=>602,8596=>602,8597=>602,8598=>602,8599=>602,8600=>602,8601=>602,8602=>602,8603=>602,8604=>602,8605=>602,8606=>602,8607=>602,8608=>602,8609=>602,8610=>602,8611=>602,8612=>602,8613=>602,8614=>602,8615=>602,8616=>602,8617=>602,8618=>602,8619=>602,8620=>602,8621=>602,8622=>602,8623=>602,8624=>602,8625=>602,8626=>602,8627=>602,8628=>602,8629=>602,8630=>602,8631=>602,8632=>602,8633=>602,8634=>602,8635=>602,8636=>602,8637=>602,8638=>602,8639=>602,8640=>602,8641=>602,8642=>602,8643=>602,8644=>602,8645=>602,8646=>602,8647=>602,8648=>602,8649=>602,8650=>602,8651=>602,8652=>602,8653=>602,8654=>602,8655=>602,8656=>602,8657=>602,8658=>602,8659=>602,8660=>602,8661=>602,8662=>602,8663=>602,8664=>602,8665=>602,8666=>602,8667=>602,8668=>602,8669=>602,8670=>602,8671=>602,8672=>602,8673=>602,8674=>602,8675=>602,8676=>602,8677=>602,8678=>602,8679=>602,8680=>602,8681=>602,8682=>602,8683=>602,8684=>602,8685=>602,8686=>602,8687=>602,8688=>602,8689=>602,8690=>602,8691=>602,8692=>602,8693=>602,8694=>602,8695=>602,8696=>602,8697=>602,8698=>602,8699=>602,8700=>602,8701=>602,8702=>602,8703=>602,8704=>602,8705=>602,8706=>602,8707=>602,8708=>602,8709=>602,8710=>602,8711=>602,8712=>602,8713=>602,8714=>602,8715=>602,8716=>602,8717=>602,8719=>602,8721=>602,8722=>602,8723=>602,8725=>602,8727=>602,8728=>602,8729=>602,8730=>602,8731=>602,8732=>602,8733=>602,8734=>602,8735=>602,8736=>602,8743=>602,8744=>602,8745=>602,8746=>602,8747=>602,8748=>602,8749=>602,8756=>602,8757=>602,8758=>602,8759=>602,8760=>602,8761=>602,8762=>602,8763=>602,8764=>602,8765=>602,8769=>602,8770=>602,8771=>602,8772=>602,8773=>602,8774=>602,8775=>602,8776=>602,8777=>602,8778=>602,8779=>602,8780=>602,8781=>602,8782=>602,8783=>602,8784=>602,8785=>602,8786=>602,8787=>602,8788=>602,8789=>602,8790=>602,8791=>602,8792=>602,8793=>602,8794=>602,8795=>602,8796=>602,8797=>602,8798=>602,8799=>602,8800=>602,8801=>602,8802=>602,8803=>602,8804=>602,8805=>602,8806=>602,8807=>602,8808=>602,8809=>602,8813=>602,8814=>602,8815=>602,8816=>602,8817=>602,8818=>602,8819=>602,8820=>602,8821=>602,8822=>602,8823=>602,8824=>602,8825=>602,8826=>602,8827=>602,8828=>602,8829=>602,8830=>602,8831=>602,8832=>602,8833=>602,8834=>602,8835=>602,8836=>602,8837=>602,8838=>602,8839=>602,8840=>602,8841=>602,8842=>602,8843=>602,8847=>602,8848=>602,8849=>602,8850=>602,8853=>602,8854=>602,8855=>602,8856=>602,8857=>602,8858=>602,8859=>602,8860=>602,8861=>602,8862=>602,8863=>602,8864=>602,8865=>602,8866=>602,8867=>602,8868=>602,8869=>602,8901=>602,8902=>602,8909=>602,8922=>602,8923=>602,8924=>602,8925=>602,8926=>602,8927=>602,8928=>602,8929=>602,8930=>602,8931=>602,8932=>602,8933=>602,8934=>602,8935=>602,8936=>602,8937=>602,8943=>602,8960=>602,8961=>602,8962=>602,8963=>602,8964=>602,8965=>602,8966=>602,8968=>602,8969=>602,8970=>602,8971=>602,8972=>602,8973=>602,8974=>602,8975=>602,8976=>602,8977=>602,8978=>602,8979=>602,8980=>602,8981=>602,8984=>602,8985=>602,8988=>602,8989=>602,8990=>602,8991=>602,8992=>602,8993=>602,8997=>602,8998=>602,8999=>602,9000=>602,9003=>602,9013=>602,9015=>602,9016=>602,9017=>602,9018=>602,9019=>602,9020=>602,9021=>602,9022=>602,9025=>602,9026=>602,9027=>602,9028=>602,9031=>602,9032=>602,9033=>602,9035=>602,9036=>602,9037=>602,9040=>602,9042=>602,9043=>602,9044=>602,9047=>602,9048=>602,9049=>602,9050=>602,9051=>602,9052=>602,9054=>602,9055=>602,9056=>602,9059=>602,9060=>602,9061=>602,9064=>602,9065=>602,9067=>602,9068=>602,9069=>602,9070=>602,9071=>602,9072=>602,9075=>602,9076=>602,9077=>602,9078=>602,9079=>602,9080=>602,9081=>602,9082=>602,9085=>602,9088=>602,9089=>602,9090=>602,9091=>602,9096=>602,9097=>602,9098=>602,9099=>602,9109=>602,9115=>602,9116=>602,9117=>602,9118=>602,9119=>602,9120=>602,9121=>602,9122=>602,9123=>602,9124=>602,9125=>602,9126=>602,9127=>602,9128=>602,9129=>602,9130=>602,9131=>602,9132=>602,9133=>602,9134=>602,9166=>602,9167=>602,9251=>602,9600=>602,9601=>602,9602=>602,9603=>602,9604=>602,9605=>602,9606=>602,9607=>602,9608=>602,9609=>602,9610=>602,9611=>602,9612=>602,9613=>602,9614=>602,9615=>602,9616=>602,9617=>602,9618=>602,9619=>602,9620=>602,9621=>602,9622=>602,9623=>602,9624=>602,9625=>602,9626=>602,9627=>602,9628=>602,9629=>602,9630=>602,9631=>602,9632=>602,9633=>602,9634=>602,9635=>602,9636=>602,9637=>602,9638=>602,9639=>602,9640=>602,9641=>602,9642=>602,9643=>602,9644=>602,9645=>602,9646=>602,9647=>602,9648=>602,9649=>602,9650=>602,9651=>602,9652=>602,9653=>602,9654=>602,9655=>602,9656=>602,9657=>602,9658=>602,9659=>602,9660=>602,9661=>602,9662=>602,9663=>602,9664=>602,9665=>602,9666=>602,9667=>602,9668=>602,9669=>602,9670=>602,9671=>602,9672=>602,9673=>602,9674=>602,9675=>602,9676=>602,9677=>602,9678=>602,9679=>602,9680=>602,9681=>602,9682=>602,9683=>602,9684=>602,9685=>602,9686=>602,9687=>602,9688=>602,9689=>602,9690=>602,9691=>602,9692=>602,9693=>602,9694=>602,9695=>602,9696=>602,9697=>602,9698=>602,9699=>602,9700=>602,9701=>602,9702=>602,9703=>602,9704=>602,9705=>602,9706=>602,9707=>602,9708=>602,9709=>602,9710=>602,9711=>602,9712=>602,9713=>602,9714=>602,9715=>602,9716=>602,9717=>602,9718=>602,9719=>602,9720=>602,9721=>602,9722=>602,9723=>602,9724=>602,9725=>602,9726=>602,9727=>602,9728=>602,9784=>602,9785=>602,9786=>602,9787=>602,9788=>602,9791=>602,9792=>602,9793=>602,9794=>602,9795=>602,9796=>602,9797=>602,9798=>602,9799=>602,9824=>602,9825=>602,9826=>602,9827=>602,9828=>602,9829=>602,9830=>602,9831=>602,9833=>602,9834=>602,9835=>602,9836=>602,9837=>602,9838=>602,9839=>602,10178=>602,10181=>602,10182=>602,10208=>602,10214=>602,10215=>602,10216=>602,10217=>602,10731=>602,10746=>602,10747=>602,10799=>602,10858=>602,10859=>602,11013=>602,11014=>602,11015=>602,11016=>602,11017=>602,11018=>602,11019=>602,11020=>602,11021=>602,11026=>602,11027=>602,11028=>602,11029=>602,11030=>602,11031=>602,11032=>602,11033=>602,11034=>602,11364=>602,11373=>602,11374=>602,11375=>602,11376=>602,11381=>602,11382=>602,11383=>602,11385=>602,11386=>602,11388=>602,11389=>602,11390=>602,11391=>602,11800=>602,11807=>602,11810=>602,11811=>602,11812=>602,11813=>602,11822=>602,42760=>602,42761=>602,42762=>602,42763=>602,42764=>602,42765=>602,42766=>602,42767=>602,42768=>602,42769=>602,42770=>602,42771=>602,42772=>602,42773=>602,42774=>602,42779=>602,42780=>602,42781=>602,42782=>602,42783=>602,42786=>602,42787=>602,42788=>602,42789=>602,42790=>602,42791=>602,42889=>602,42890=>602,42891=>602,42892=>602,42893=>602,42894=>602,42896=>602,42897=>602,42922=>602,63173=>602,64257=>602,64258=>602,65529=>602,65530=>602,65531=>602,65532=>602,65533=>602,65535=>602); -// --- EOF --- diff --git a/lib/combodo/tcpdf/fonts/dejavusansmonobi.z b/lib/combodo/tcpdf/fonts/dejavusansmonobi.z deleted file mode 100644 index a866f79821ada258d10471c704595eaa9d7bcf0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 145530 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%0DmZLNFg<xIhPr!`z9P?<6^U^)uLtpSdD&N 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 diff --git a/lib/combodo/tcpdf/fonts/dejavusansmonoi.ctg.z b/lib/combodo/tcpdf/fonts/dejavusansmonoi.ctg.z deleted file mode 100644 index 0fa53ab2eff7b9fa20dfe3b891351d23f21a5b81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5221 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 M^lVFf{ch3oZwf6eC;$Ke diff --git a/lib/combodo/tcpdf/fonts/dejavusansmonoi.php b/lib/combodo/tcpdf/fonts/dejavusansmonoi.php deleted file mode 100644 index 753fa9a52..000000000 --- a/lib/combodo/tcpdf/fonts/dejavusansmonoi.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php -// TCPDF FONT FILE DESCRIPTION -$type='TrueTypeUnicode'; -$name='DejaVuSansMono-Oblique'; -$up=-63; -$ut=44; -$dw=602; -$diff=''; -$originalsize=245948; -$enc=''; -$file='dejavusansmonoi.z'; -$ctg='dejavusansmonoi.ctg.z'; -$desc=array('Flags'=>97,'FontBBox'=>'[-403 -375 746 1028]','ItalicAngle'=>-11,'Ascent'=>928,'Descent'=>-236,'Leading'=>0,'CapHeight'=>729,'XHeight'=>547,'StemV'=>34,'StemH'=>15,'AvgWidth'=>602,'MaxWidth'=>602,'MissingWidth'=>602); -$cbbox=array(0=>array(51,-177,551,705),33=>array(181,0,422,729),34=>array(165,458,437,729),35=>array(-3,0,602,718),36=>array(15,-147,529,760),37=>array(16,0,586,699),38=>array(-10,-14,581,742),39=>array(258,458,343,729),40=>array(182,-132,509,759),41=>array(73,-132,400,759),42=>array(81,286,521,742),43=>array(43,55,559,572),44=>array(99,-140,326,148),45=>array(148,234,419,314),46=>array(173,0,325,148),47=>array(8,-93,517,729),48=>array(48,-14,554,742),49=>array(60,0,478,729),50=>array(3,0,550,742),51=>array(-9,-14,538,742),52=>array(12,0,531,729),53=>array(2,-14,541,729),54=>array(45,-14,551,742),55=>array(85,0,592,729),56=>array(20,-14,550,742),57=>array(31,-14,537,742),58=>array(168,0,392,518),59=>array(99,-140,392,519),60=>array(43,69,559,558),61=>array(43,172,559,454),62=>array(43,69,559,558),63=>array(159,0,547,742),64=>array(-14,-155,593,682),65=>array(-52,0,513,729),66=>array(11,0,570,729),67=>array(56,-14,592,742),68=>array(-4,0,552,729),69=>array(26,0,600,729),70=>array(45,0,616,729),71=>array(38,-14,574,742),72=>array(-4,0,606,729),73=>array(28,0,574,729),74=>array(-12,-14,538,729),75=>array(-4,0,661,729),76=>array(38,0,505,729),77=>array(-29,0,631,729),78=>array(-3,0,605,729),79=>array(40,-14,562,742),80=>array(25,0,588,729),81=>array(40,-132,562,742),82=>array(6,0,562,729),83=>array(12,-14,560,742),84=>array(78,0,651,729),85=>array(39,-14,601,729),86=>array(97,0,646,729),87=>array(40,0,672,729),88=>array(-62,0,653,729),89=>array(95,0,658,729),90=>array(-3,0,622,729),91=>array(129,-132,510,760),92=>array(174,-93,354,729),93=>array(72,-132,453,760),94=>array(35,457,567,729),95=>array(0,-236,602,-197),96=>array(221,616,414,800),97=>array(35,-14,531,560),98=>array(29,-14,541,760),99=>array(76,-14,555,560),100=>array(58,-14,612,760),101=>array(48,-14,550,561),102=>array(129,0,608,760),103=>array(29,-215,559,560),104=>array(41,0,535,760),105=>array(30,0,490,760),106=>array(2,-208,482,760),107=>array(44,0,588,760),108=>array(152,0,477,765),109=>array(-7,0,575,560),110=>array(41,0,535,560),111=>array(57,-14,544,560),112=>array(-1,-208,551,560),113=>array(48,-208,560,560),114=>array(106,0,595,560),115=>array(56,-14,526,560),116=>array(95,0,549,702),117=>array(61,-13,553,547),118=>array(89,0,593,547),119=>array(45,0,642,547),120=>array(-34,0,590,547),121=>array(-19,-208,598,547),122=>array(38,0,553,547),123=>array(90,-163,574,760),124=>array(259,-236,343,764),125=>array(-7,-163,477,760),126=>array(43,240,559,381),161=>array(190,0,431,729),162=>array(60,-153,531,699),163=>array(-4,0,600,742),164=>array(100,95,537,532),165=>array(23,0,621,729),166=>array(259,-171,343,699),167=>array(49,-98,522,738),168=>array(213,659,522,758),169=>array(0,61,602,663),170=>array(109,229,506,742),171=>array(36,69,540,517),172=>array(43,181,559,421),173=>array(148,234,419,314),174=>array(0,61,602,663),175=>array(215,673,521,745),176=>array(146,432,456,742),177=>array(43,0,559,572),178=>array(150,326,484,742),179=>array(140,319,480,742),180=>array(281,616,550,800),181=>array(-19,-208,566,547),182=>array(61,-96,557,729),183=>array(222,273,374,422),184=>array(89,-193,306,0),185=>array(170,326,450,734),186=>array(109,229,520,742),187=>array(40,69,544,517),188=>array(23,-132,553,810),189=>array(23,-132,559,810),190=>array(23,-132,553,818),191=>array(70,-13,458,729),192=>array(-52,0,513,927),193=>array(-52,0,534,927),194=>array(-52,0,525,928),195=>array(-52,0,565,921),196=>array(-52,0,537,913),197=>array(-52,0,513,928),198=>array(-71,0,638,729),199=>array(56,-193,592,742),200=>array(26,0,600,927),201=>array(26,0,600,927),202=>array(26,0,600,928),203=>array(26,0,600,913),204=>array(28,0,574,927),205=>array(28,0,574,927),206=>array(28,0,574,928),207=>array(28,0,574,913),208=>array(-4,0,552,729),209=>array(-3,0,605,921),210=>array(40,-14,562,927),211=>array(40,-14,562,927),212=>array(40,-14,562,928),213=>array(40,-14,562,921),214=>array(40,-14,562,913),215=>array(73,85,529,541),216=>array(7,-34,586,761),217=>array(39,-14,601,927),218=>array(39,-14,601,927),219=>array(39,-14,601,928),220=>array(39,-14,601,913),221=>array(95,0,658,927),222=>array(25,0,566,729),223=>array(27,-14,550,760),224=>array(35,-14,531,800),225=>array(35,-14,552,800),226=>array(35,-14,531,800),227=>array(35,-14,544,777),228=>array(35,-14,531,758),229=>array(35,-14,531,913),230=>array(-23,-14,593,560),231=>array(76,-193,555,560),232=>array(48,-14,550,800),233=>array(48,-14,550,800),234=>array(48,-14,550,800),235=>array(48,-14,550,758),236=>array(30,0,490,800),237=>array(30,0,536,800),238=>array(30,0,490,800),239=>array(30,0,508,758),240=>array(58,-14,552,760),241=>array(41,0,542,777),242=>array(57,-14,544,800),243=>array(57,-14,550,800),244=>array(57,-14,544,800),245=>array(57,-14,544,777),246=>array(57,-14,544,758),247=>array(43,73,559,554),248=>array(23,-47,573,592),249=>array(61,-13,553,800),250=>array(61,-13,553,800),251=>array(61,-13,553,800),252=>array(61,-13,553,758),253=>array(-19,-208,598,800),254=>array(-1,-208,551,765),255=>array(-19,-208,598,758),256=>array(-52,0,551,898),257=>array(35,-14,531,745),258=>array(-52,0,564,928),259=>array(35,-14,536,785),260=>array(-52,-193,522,729),261=>array(35,-193,531,560),262=>array(56,-14,594,927),263=>array(76,-14,594,800),264=>array(56,-14,605,928),265=>array(76,-14,555,800),266=>array(56,-14,592,914),267=>array(76,-14,555,758),268=>array(56,-14,611,928),269=>array(76,-14,582,800),270=>array(-4,0,552,928),271=>array(58,-14,738,760),272=>array(-4,0,552,729),273=>array(58,-14,691,760),274=>array(26,0,600,898),275=>array(48,-14,550,745),276=>array(26,0,600,928),277=>array(48,-14,550,785),278=>array(26,0,600,914),279=>array(48,-14,550,758),280=>array(26,-193,600,729),281=>array(48,-193,550,561),282=>array(26,0,600,928),283=>array(48,-14,565,800),284=>array(38,-14,574,928),285=>array(29,-215,559,800),286=>array(38,-14,589,928),287=>array(29,-215,559,785),288=>array(38,-14,574,914),289=>array(29,-215,559,758),290=>array(38,-280,574,742),291=>array(29,-215,559,788),292=>array(-4,0,606,928),293=>array(41,0,535,928),294=>array(-4,0,650,729),295=>array(21,0,514,760),296=>array(28,0,574,921),297=>array(30,0,528,777),298=>array(28,0,574,898),299=>array(30,0,521,745),300=>array(28,0,574,928),301=>array(30,0,536,785),302=>array(45,-193,592,729),303=>array(32,-193,493,760),304=>array(28,0,574,914),305=>array(30,0,490,547),306=>array(1,-14,705,729),307=>array(2,-209,737,760),308=>array(-12,-14,566,928),309=>array(2,-208,488,800),310=>array(-4,-266,661,729),311=>array(44,-266,588,760),312=>array(62,0,606,547),313=>array(38,0,536,928),314=>array(152,0,536,928),315=>array(38,-266,505,729),316=>array(152,-266,477,765),317=>array(38,0,540,729),318=>array(152,0,604,766),319=>array(38,0,548,729),320=>array(152,0,653,765),321=>array(-14,0,507,728),322=>array(43,0,544,765),323=>array(-3,0,605,931),324=>array(41,0,546,803),325=>array(-3,-266,605,729),326=>array(41,-266,535,560),327=>array(-3,0,605,928),328=>array(41,0,562,800),329=>array(-17,0,595,760),330=>array(20,-208,573,743),331=>array(61,-208,554,560),332=>array(40,-14,562,898),333=>array(57,-14,544,745),334=>array(40,-14,564,928),335=>array(57,-14,544,785),336=>array(40,-14,621,927),337=>array(57,-14,598,800),338=>array(17,0,660,729),339=>array(-3,-14,621,560),340=>array(6,0,562,928),341=>array(106,0,651,803),342=>array(6,-266,562,729),343=>array(25,-266,595,560),344=>array(6,0,562,928),345=>array(106,0,595,800),346=>array(12,-14,560,931),347=>array(56,-14,546,803),348=>array(12,-14,560,928),349=>array(56,-14,536,813),350=>array(12,-193,560,742),351=>array(56,-193,526,560),352=>array(12,-14,560,928),353=>array(56,-14,538,800),354=>array(78,-193,651,729),355=>array(95,-193,549,702),356=>array(78,0,651,928),357=>array(95,0,626,820),358=>array(78,0,650,729),359=>array(87,0,542,702),360=>array(39,-14,601,921),361=>array(61,-13,553,777),362=>array(39,-14,601,898),363=>array(61,-13,553,745),364=>array(39,-14,601,928),365=>array(61,-13,553,785),366=>array(39,-14,601,1028),367=>array(61,-13,553,847),368=>array(39,-14,621,927),369=>array(61,-13,598,800),370=>array(39,-201,601,729),371=>array(61,-194,553,547),372=>array(40,0,672,932),373=>array(45,0,642,803),374=>array(95,0,658,932),375=>array(-19,-208,598,803),376=>array(95,0,658,913),377=>array(-3,0,622,931),378=>array(38,0,553,803),379=>array(-3,0,622,914),380=>array(38,0,553,758),381=>array(-3,0,622,928),382=>array(38,0,553,800),383=>array(129,0,608,760),384=>array(29,-14,541,760),385=>array(41,0,598,729),386=>array(10,0,593,729),387=>array(21,-14,537,760),388=>array(33,0,547,729),389=>array(51,-14,554,760),390=>array(2,-14,524,742),391=>array(23,-14,652,800),392=>array(33,-14,625,694),393=>array(-4,0,552,729),394=>array(35,0,598,729),395=>array(49,0,626,729),396=>array(32,0,609,729),397=>array(58,-14,601,760),398=>array(25,0,609,729),399=>array(57,-14,545,742),400=>array(35,-14,573,742),401=>array(-61,-208,663,729),402=>array(35,-208,613,760),403=>array(19,-14,656,800),404=>array(35,-210,673,661),405=>array(-42,0,579,760),406=>array(153,0,574,729),407=>array(27,0,574,729),408=>array(-17,0,640,729),409=>array(41,0,586,760),410=>array(93,0,446,765),411=>array(-22,0,549,729),412=>array(18,-13,626,729),413=>array(-77,-208,604,729),414=>array(61,-210,545,560),415=>array(57,-14,545,742),416=>array(-20,-14,634,760),417=>array(5,-14,595,560),418=>array(21,-14,651,742),419=>array(61,-210,650,560),420=>array(59,0,609,729),421=>array(4,-208,546,699),422=>array(11,-129,544,729),423=>array(36,-14,568,742),424=>array(82,-14,525,560),425=>array(-13,0,625,729),426=>array(131,-208,530,760),427=>array(108,-208,563,702),428=>array(54,0,650,729),429=>array(83,0,552,760),430=>array(78,-208,651,729),431=>array(-29,-14,652,760),432=>array(-15,-13,592,555),433=>array(38,0,635,713),434=>array(43,0,520,729),435=>array(79,0,658,730),436=>array(-13,-208,669,547),437=>array(5,0,631,729),438=>array(43,0,559,548),439=>array(-16,-14,602,729),440=>array(-16,-14,619,729),441=>array(1,-213,679,547),442=>array(-9,-208,533,547),443=>array(2,0,544,742),444=>array(-16,-14,628,729),445=>array(-6,-213,567,547),446=>array(32,-14,482,702),447=>array(-15,-208,593,560),448=>array(181,0,421,729),449=>array(82,0,520,729),450=>array(58,0,555,729),451=>array(181,0,422,729),461=>array(-52,0,554,928),462=>array(35,-14,553,800),463=>array(28,0,574,928),464=>array(30,0,538,800),465=>array(40,-14,571,928),466=>array(57,-14,563,800),467=>array(39,-14,601,928),468=>array(61,-13,553,800),469=>array(39,-14,601,953),470=>array(61,-13,553,899),471=>array(39,-14,601,997),472=>array(61,-13,585,954),473=>array(39,-14,601,998),474=>array(61,-13,579,954),475=>array(39,-14,601,997),476=>array(61,-13,553,954),477=>array(55,-14,542,560),479=>array(35,-14,559,899),480=>array(-52,0,556,953),481=>array(35,-14,559,899),482=>array(-71,0,638,898),483=>array(-23,-14,593,745),486=>array(38,-14,574,928),487=>array(29,-215,559,800),488=>array(-4,0,661,928),489=>array(44,0,588,928),490=>array(40,-201,562,742),491=>array(57,-201,544,560),492=>array(40,-201,562,898),493=>array(57,-201,544,745),494=>array(-16,-14,602,928),495=>array(-6,-213,572,800),500=>array(38,-14,574,927),501=>array(29,-215,559,800),502=>array(-40,-14,586,729),504=>array(-3,0,605,927),505=>array(41,0,535,800),508=>array(-71,0,654,927),509=>array(-23,-14,593,800),510=>array(7,-34,586,927),511=>array(23,-47,573,800),512=>array(-52,0,519,927),513=>array(35,-14,531,800),514=>array(-52,0,542,928),515=>array(35,-14,531,785),516=>array(26,0,600,927),517=>array(48,-14,550,800),518=>array(26,0,600,928),519=>array(48,-14,550,785),520=>array(28,0,574,927),521=>array(30,0,495,800),522=>array(28,0,574,928),523=>array(30,0,511,785),524=>array(40,-14,562,927),525=>array(57,-14,544,800),526=>array(40,-14,562,928),527=>array(57,-14,544,785),528=>array(6,0,562,927),529=>array(106,0,595,800),530=>array(6,0,562,928),531=>array(106,0,595,785),532=>array(39,-14,601,927),533=>array(61,-13,553,800),534=>array(39,-14,601,928),535=>array(61,-13,553,785),536=>array(12,-265,560,742),537=>array(56,-265,526,560),538=>array(78,-265,651,729),539=>array(95,-265,549,702),540=>array(17,-210,646,742),541=>array(40,-211,591,560),542=>array(-4,0,606,928),543=>array(41,0,535,928),545=>array(-5,-72,538,760),548=>array(25,-208,651,729),549=>array(66,-208,582,548),550=>array(-52,0,513,914),551=>array(35,-14,531,758),552=>array(26,-193,600,729),553=>array(48,-193,550,561),554=>array(40,-14,562,953),555=>array(57,-14,544,899),556=>array(40,-14,562,953),557=>array(57,-14,544,899),558=>array(40,-14,562,914),559=>array(57,-14,544,758),560=>array(40,-14,562,953),561=>array(57,-14,544,899),562=>array(95,0,658,898),563=>array(-19,-208,598,745),564=>array(146,-72,465,765),565=>array(4,-72,531,560),566=>array(95,-72,549,702),567=>array(2,-208,441,547),568=>array(32,-14,531,760),569=>array(71,-214,570,560),570=>array(-67,-34,656,761),571=>array(-67,-34,656,761),572=>array(-32,-47,628,592),573=>array(-6,0,537,729),574=>array(-55,-34,668,761),575=>array(77,-242,547,560),576=>array(69,-242,585,548),577=>array(59,0,604,729),579=>array(-32,0,570,729),580=>array(-4,-14,601,729),581=>array(-44,0,505,729),588=>array(-0,0,562,729),589=>array(58,0,595,560),592=>array(54,-14,549,560),593=>array(77,-14,579,560),594=>array(23,-14,525,560),595=>array(4,-14,507,760),596=>array(42,-14,513,560),597=>array(90,-72,572,558),598=>array(67,-208,556,760),599=>array(40,-14,601,760),600=>array(33,-14,542,560),601=>array(55,-14,542,560),602=>array(-3,-14,595,560),603=>array(60,-11,551,560),604=>array(32,-11,532,560),605=>array(-23,-11,582,560),606=>array(86,-21,542,559),607=>array(-5,-208,559,547),608=>array(36,-215,620,760),609=>array(69,-215,600,545),610=>array(59,0,574,574),611=>array(52,-210,626,547),612=>array(103,0,605,547),613=>array(100,-210,583,546),614=>array(18,0,502,760),615=>array(38,-208,522,760),616=>array(4,0,503,760),617=>array(136,0,466,547),618=>array(24,0,578,547),619=>array(15,0,559,765),620=>array(79,0,466,765),621=>array(168,-208,435,765),622=>array(101,-213,601,765),623=>array(33,0,606,560),624=>array(53,-210,626,560),625=>array(16,-208,589,560),626=>array(12,-208,568,560),627=>array(32,-208,484,560),628=>array(16,0,586,560),629=>array(67,-14,535,560),630=>array(34,0,616,547),631=>array(72,-15,523,560),632=>array(48,-208,561,759),633=>array(87,-13,516,547),634=>array(67,-13,536,755),635=>array(50,-208,479,547),636=>array(66,-208,535,560),637=>array(104,-208,535,560),638=>array(23,0,579,560),639=>array(23,0,483,560),640=>array(6,0,490,547),641=>array(6,0,596,547),642=>array(56,-208,550,560),643=>array(20,-208,582,760),644=>array(-33,-208,635,760),645=>array(173,-208,429,549),646=>array(-16,-208,639,760),647=>array(81,-155,535,547),648=>array(156,-208,610,702),649=>array(-25,-14,625,547),650=>array(47,-15,610,547),651=>array(71,0,555,547),652=>array(-19,0,514,547),653=>array(-46,0,542,547),654=>array(-39,0,591,755),655=>array(104,0,607,561),656=>array(62,-208,509,547),657=>array(33,-54,579,547),658=>array(-6,-213,572,547),659=>array(17,-213,552,547),660=>array(144,0,537,759),661=>array(124,0,575,759),662=>array(27,0,478,759),663=>array(44,-214,595,759),664=>array(46,22,556,532),665=>array(47,0,504,561),666=>array(60,-21,517,559),667=>array(8,0,627,759),668=>array(16,0,586,560),669=>array(25,-208,509,760),670=>array(38,-213,618,547),671=>array(65,0,444,560),672=>array(17,-208,654,759),673=>array(59,0,537,759),674=>array(124,0,575,759),675=>array(-7,-14,609,760),676=>array(10,-213,615,760),677=>array(8,-54,612,760),678=>array(79,-14,546,702),679=>array(105,-208,620,760),680=>array(98,-70,550,702),681=>array(64,-208,550,760),682=>array(40,-14,499,760),683=>array(33,0,527,760),684=>array(65,-15,596,641),685=>array(16,84,586,640),686=>array(160,-214,568,760),687=>array(147,-208,491,760),688=>array(115,318,440,744),689=>array(115,317,440,743),690=>array(185,202,417,744),691=>array(169,318,432,632),692=>array(170,311,433,625),693=>array(146,202,408,625),694=>array(119,318,483,625),695=>array(100,318,562,625),696=>array(123,202,510,625),697=>array(216,557,389,800),699=>array(226,472,453,760),700=>array(198,472,425,760),701=>array(242,595,384,844),702=>array(300,492,460,760),703=>array(292,492,452,760),704=>array(199,437,448,862),705=>array(187,437,469,862),710=>array(194,616,502,800),711=>array(230,616,538,800),712=>array(241,488,361,759),713=>array(215,673,521,745),716=>array(241,-148,361,123),717=>array(51,-174,357,-102),718=>array(269,-285,462,-102),719=>array(233,-285,502,-102),720=>array(164,0,438,517),721=>array(229,355,404,517),722=>array(252,249,413,517),723=>array(245,249,405,517),726=>array(148,125,455,417),727=>array(184,234,418,307),728=>array(229,645,536,785),729=>array(308,658,428,758),730=>array(246,645,514,913),731=>array(113,-193,293,0),732=>array(196,638,542,777),733=>array(215,616,598,800),734=>array(-176,233,420,504),736=>array(148,208,500,632),737=>array(201,326,402,755),738=>array(142,326,442,648),739=>array(104,326,491,632),740=>array(188,326,469,751),741=>array(199,0,521,668),742=>array(169,0,521,668),743=>array(140,0,521,668),744=>array(111,0,521,668),745=>array(82,0,521,668),750=>array(108,472,559,760),755=>array(94,-245,313,-31),768=>array(221,616,414,800),769=>array(281,616,550,800),770=>array(194,616,502,800),771=>array(196,638,542,777),772=>array(215,673,521,745),773=>array(0,716,602,755),774=>array(229,645,536,785),775=>array(308,658,428,758),776=>array(213,659,522,758),777=>array(207,618,408,847),778=>array(246,645,514,913),779=>array(215,616,598,800),780=>array(230,616,538,800),781=>array(245,616,354,833),782=>array(146,616,454,833),783=>array(188,616,495,800),784=>array(229,645,536,857),785=>array(203,645,511,785),786=>array(229,472,424,641),787=>array(218,595,384,844),788=>array(242,595,384,844),789=>array(281,616,458,800),790=>array(269,-285,462,-102),791=>array(233,-285,502,-102),792=>array(188,-375,370,-135),793=>array(229,-375,412,-135),794=>array(191,690,444,930),795=>array(197,373,406,555),796=>array(147,-245,278,-31),797=>array(178,-288,430,-135),798=>array(204,-288,456,-135),799=>array(183,-375,435,-135),800=>array(175,-202,427,-135),801=>array(151,-208,472,63),802=>array(39,-208,284,63),803=>array(141,-202,261,-102),804=>array(46,-201,356,-103),805=>array(94,-245,313,-31),806=>array(85,-265,280,-96),807=>array(89,-193,306,0),808=>array(118,-193,298,0),809=>array(247,-319,355,-102),810=>array(150,-263,452,-102),811=>array(114,-222,515,-82),812=>array(64,-237,376,-53),813=>array(28,-237,341,-53),814=>array(57,-238,365,-98),815=>array(31,-237,340,-97),816=>array(23,-238,370,-99),817=>array(51,-174,357,-102),818=>array(0,-236,602,-197),819=>array(0,-236,602,-80),820=>array(29,240,573,381),821=>array(69,221,519,301),822=>array(0,221,602,301),823=>array(-32,-47,628,592),824=>array(-67,-34,656,761),825=>array(129,-245,260,-31),826=>array(150,-188,452,-26),827=>array(140,-371,462,-102),828=>array(87,-222,488,-82),829=>array(181,599,421,816),830=>array(207,595,395,853),831=>array(0,599,602,755),835=>array(218,595,384,844),856=>array(626,658,746,758),865=>array(-131,742,702,902),884=>array(216,557,389,800),885=>array(213,-208,386,35),890=>array(197,-208,293,-45),894=>array(99,-140,392,519),900=>array(281,616,550,800),901=>array(213,659,601,980),902=>array(-52,0,513,800),903=>array(222,273,374,422),904=>array(-61,0,600,800),905=>array(-85,0,606,800),906=>array(-61,0,574,800),908=>array(12,-14,562,800),910=>array(-146,0,658,800),911=>array(-33,0,564,800),912=>array(191,0,601,980),913=>array(-52,0,513,729),914=>array(11,0,570,729),915=>array(34,0,627,729),916=>array(-53,0,513,729),917=>array(26,0,600,729),918=>array(-3,0,622,729),919=>array(-4,0,606,729),920=>array(57,-14,545,742),921=>array(28,0,574,729),922=>array(-4,0,661,729),923=>array(-53,0,513,729),924=>array(-29,0,631,729),925=>array(-3,0,605,729),926=>array(-4,0,606,729),927=>array(40,-14,562,742),928=>array(-4,0,606,729),929=>array(25,0,588,729),931=>array(-13,0,625,729),932=>array(78,0,651,729),933=>array(95,0,658,729),934=>array(57,0,544,729),935=>array(-62,0,653,729),936=>array(95,0,615,729),937=>array(-33,0,564,713),938=>array(28,0,574,913),939=>array(95,0,658,913),940=>array(34,-12,606,800),941=>array(64,-15,550,800),942=>array(61,-208,550,800),943=>array(191,0,550,800),944=>array(64,0,601,980),945=>array(34,-12,606,559),946=>array(-21,-208,553,766),947=>array(32,-208,584,547),948=>array(46,-14,535,767),949=>array(64,-15,536,553),950=>array(72,-210,613,760),951=>array(61,-208,545,560),952=>array(67,-14,535,732),953=>array(191,0,438,547),954=>array(62,0,606,547),955=>array(27,0,560,760),956=>array(-19,-208,566,547),957=>array(109,0,547,547),958=>array(68,-210,591,760),959=>array(57,-14,544,560),960=>array(35,-19,596,547),961=>array(18,-208,560,560),962=>array(114,-210,585,560),963=>array(60,-14,599,547),964=>array(113,0,578,547),965=>array(64,0,564,547),966=>array(57,-208,585,551),967=>array(0,-208,602,547),968=>array(76,-208,612,547),969=>array(24,-14,574,547),970=>array(191,0,522,758),971=>array(64,0,564,758),972=>array(57,-14,550,800),973=>array(64,0,564,800),974=>array(24,-14,574,800),976=>array(72,-11,526,768),977=>array(66,-11,540,768),978=>array(28,0,583,729),979=>array(-186,0,583,800),980=>array(28,0,583,913),981=>array(55,-208,551,729),982=>array(12,0,607,547),983=>array(-1,-188,636,547),984=>array(76,-208,564,742),985=>array(85,-208,554,560),986=>array(63,-210,604,729),987=>array(96,-210,594,547),988=>array(45,0,616,729),989=>array(-90,-208,594,760),990=>array(24,-2,599,729),991=>array(58,0,547,759),992=>array(80,-208,558,742),993=>array(6,-180,494,559),1008=>array(-21,-3,617,547),1009=>array(87,-208,560,560),1010=>array(76,-14,555,560),1011=>array(2,-208,482,760),1012=>array(57,-14,545,742),1013=>array(79,-14,557,560),1014=>array(27,-14,504,560),1015=>array(25,0,566,729),1016=>array(-1,-208,551,765),1017=>array(56,-14,592,742),1018=>array(-29,0,630,729),1019=>array(-12,-208,612,547),1020=>array(-23,-208,560,560),1021=>array(2,-14,524,742),1022=>array(56,-14,592,742),1023=>array(2,-14,524,742),1024=>array(26,0,600,985),1025=>array(26,0,600,900),1026=>array(39,-229,552,730),1027=>array(34,0,627,985),1028=>array(55,-14,590,742),1029=>array(12,-14,560,742),1030=>array(28,0,574,729),1031=>array(28,0,574,900),1032=>array(-12,-14,538,729),1033=>array(-80,0,575,729),1034=>array(-54,0,577,729),1035=>array(17,0,530,730),1036=>array(37,0,702,985),1037=>array(-3,0,605,985),1038=>array(19,0,634,928),1039=>array(11,-157,621,729),1040=>array(-52,0,513,729),1041=>array(10,0,593,729),1042=>array(11,0,570,729),1043=>array(34,0,627,729),1044=>array(-70,-157,613,729),1045=>array(26,0,600,729),1046=>array(-63,0,657,729),1047=>array(-9,-14,538,742),1048=>array(-3,0,605,729),1049=>array(-3,0,605,928),1050=>array(-4,0,661,729),1051=>array(-69,0,605,729),1052=>array(-29,0,631,729),1053=>array(-4,0,606,729),1054=>array(40,-14,562,742),1055=>array(-4,0,606,729),1056=>array(25,0,588,729),1057=>array(56,-14,592,742),1058=>array(78,0,651,729),1059=>array(19,0,634,729),1060=>array(23,0,583,729),1061=>array(-62,0,653,729),1062=>array(-17,-157,593,729),1063=>array(82,0,604,729),1064=>array(-15,0,618,729),1065=>array(-26,-157,606,729),1066=>array(70,0,529,729),1067=>array(-40,0,625,729),1068=>array(25,0,529,729),1069=>array(2,-14,537,742),1070=>array(-0,-14,621,742),1071=>array(-34,0,624,729),1072=>array(35,-14,531,560),1073=>array(35,-14,556,777),1074=>array(49,0,507,547),1075=>array(72,0,546,547),1076=>array(-16,-140,559,547),1077=>array(48,-14,550,561),1078=>array(-24,0,617,547),1079=>array(32,-11,532,560),1080=>array(42,0,566,547),1081=>array(42,0,566,785),1082=>array(62,0,606,547),1083=>array(-39,0,566,547),1084=>array(-23,0,629,547),1085=>array(42,0,566,547),1086=>array(57,-14,544,560),1087=>array(42,0,566,547),1088=>array(-1,-208,551,560),1089=>array(76,-14,555,560),1090=>array(149,0,557,547),1091=>array(-19,-208,598,547),1092=>array(36,-208,562,760),1093=>array(-34,0,590,547),1094=>array(21,-140,544,547),1095=>array(108,0,566,548),1096=>array(8,0,595,547),1097=>array(-0,-140,586,547),1098=>array(54,0,550,547),1099=>array(-2,0,604,547),1100=>array(43,0,507,547),1101=>array(47,-14,526,560),1102=>array(-15,-14,582,560),1103=>array(29,0,534,547),1104=>array(48,-14,550,803),1105=>array(48,-14,550,718),1106=>array(56,-208,526,760),1107=>array(72,0,589,803),1108=>array(95,-14,566,560),1109=>array(56,-14,526,560),1110=>array(30,0,490,760),1111=>array(30,0,500,718),1112=>array(2,-208,482,760),1113=>array(-48,0,582,547),1114=>array(-21,0,559,547),1115=>array(36,0,494,760),1116=>array(62,0,606,803),1117=>array(42,0,566,803),1118=>array(-19,-208,598,785),1119=>array(56,-140,580,547),1122=>array(50,0,529,729),1123=>array(54,0,547,760),1138=>array(57,-14,545,742),1139=>array(67,-14,535,560),1168=>array(34,0,656,878),1169=>array(72,0,576,700),1170=>array(34,0,627,729),1171=>array(56,0,546,547),1172=>array(34,-200,627,729),1173=>array(72,-208,546,547),1174=>array(-63,-157,657,729),1175=>array(-24,-140,617,547),1176=>array(-9,-193,538,742),1177=>array(32,-193,532,560),1178=>array(-4,-152,661,729),1179=>array(62,-135,606,547),1186=>array(-4,-152,606,729),1187=>array(42,-135,566,547),1188=>array(-15,0,662,729),1189=>array(8,0,639,547),1194=>array(56,-193,592,742),1195=>array(76,-193,555,560),1196=>array(78,-152,651,729),1197=>array(146,-135,557,547),1198=>array(95,0,658,729),1199=>array(86,-208,598,547),1200=>array(95,0,661,729),1201=>array(74,-208,598,547),1202=>array(-63,-152,648,729),1203=>array(-16,-135,599,547),1210=>array(-3,0,511,730),1211=>array(41,0,535,760),1216=>array(28,0,574,729),1217=>array(-63,0,657,928),1218=>array(-24,0,617,785),1219=>array(-4,-200,661,729),1220=>array(62,-208,606,547),1223=>array(-4,-200,606,729),1224=>array(42,-208,566,547),1227=>array(34,-152,627,729),1228=>array(72,-135,546,547),1231=>array(171,0,410,765),1232=>array(-52,0,564,928),1233=>array(35,-14,536,785),1234=>array(-52,0,537,913),1235=>array(35,-14,531,758),1236=>array(-71,0,638,729),1237=>array(-23,-14,593,560),1238=>array(26,0,600,928),1239=>array(48,-14,550,785),1240=>array(57,-14,545,742),1241=>array(55,-14,542,560),1242=>array(57,-14,545,913),1243=>array(55,-14,542,758),1244=>array(-63,0,657,913),1245=>array(-24,0,617,758),1246=>array(-9,-14,538,913),1247=>array(32,-11,532,758),1248=>array(-16,-14,602,729),1249=>array(-6,-213,572,547),1250=>array(-3,0,605,898),1251=>array(42,0,566,745),1252=>array(-3,0,605,913),1253=>array(42,0,566,758),1254=>array(40,-14,562,913),1255=>array(57,-14,544,758),1256=>array(57,-14,545,742),1257=>array(67,-14,535,560),1258=>array(57,-14,545,913),1259=>array(67,-14,535,758),1260=>array(2,-14,537,913),1261=>array(47,-14,526,758),1262=>array(19,0,634,898),1263=>array(-19,-208,598,745),1264=>array(19,0,634,913),1265=>array(-19,-208,598,758),1266=>array(19,0,634,927),1267=>array(-19,-208,598,800),1268=>array(82,0,604,913),1269=>array(108,0,566,758),1270=>array(95,-152,606,730),1271=>array(123,-135,567,548),1272=>array(-40,0,625,913),1273=>array(-2,0,604,758),1296=>array(35,-14,573,742),1297=>array(64,-15,536,553),1306=>array(40,-132,562,742),1307=>array(48,-208,560,560),1308=>array(40,0,672,729),1309=>array(45,0,642,547),1329=>array(28,-29,589,729),1330=>array(-9,0,551,742),1331=>array(56,0,547,742),1332=>array(37,0,562,742),1333=>array(31,-14,576,729),1334=>array(-3,0,575,742),1335=>array(-12,0,579,729),1336=>array(-9,0,551,743),1337=>array(-49,-14,593,742),1338=>array(15,-14,597,729),1339=>array(0,0,526,729),1340=>array(4,0,471,729),1341=>array(-24,-14,593,729),1342=>array(24,-14,640,742),1343=>array(75,0,565,729),1344=>array(23,-26,594,729),1345=>array(8,-23,577,742),1346=>array(37,0,520,742),1347=>array(-8,0,631,742),1348=>array(-5,-14,647,729),1349=>array(27,-14,578,742),1350=>array(82,-14,564,729),1351=>array(27,-14,551,729),1352=>array(0,0,561,743),1353=>array(53,-28,578,742),1354=>array(42,0,596,742),1355=>array(-4,0,577,742),1356=>array(-45,0,562,742),1357=>array(41,-14,602,729),1358=>array(20,0,545,729),1359=>array(22,-14,558,742),1360=>array(0,0,561,743),1361=>array(27,-14,578,742),1362=>array(-5,0,571,729),1363=>array(21,0,583,729),1364=>array(-24,0,610,742),1365=>array(40,-14,562,742),1366=>array(4,-14,563,729),1369=>array(292,492,452,760),1370=>array(207,499,395,729),1371=>array(233,620,502,803),1372=>array(83,618,518,893),1373=>array(269,616,462,800),1374=>array(61,613,511,885),1375=>array(78,618,507,760),1377=>array(26,-13,605,547),1378=>array(15,-208,539,560),1379=>array(45,-208,556,558),1380=>array(21,-208,525,560),1381=>array(48,-14,556,760),1382=>array(45,-208,556,558),1383=>array(27,0,533,760),1384=>array(15,-208,539,560),1385=>array(-42,-208,588,560),1386=>array(7,-14,600,760),1387=>array(-2,-208,522,760),1388=>array(86,-208,382,547),1389=>array(-43,-208,603,760),1390=>array(36,-14,566,771),1391=>array(78,-208,562,760),1392=>array(38,0,532,760),1393=>array(45,-15,503,760),1394=>array(21,-208,505,560),1395=>array(54,-14,586,760),1396=>array(19,-14,626,760),1397=>array(81,-208,520,547),1398=>array(101,-14,584,760),1399=>array(26,-208,553,561),1400=>array(38,0,532,560),1401=>array(58,-208,487,571),1402=>array(45,-208,625,547),1403=>array(28,-208,557,561),1404=>array(10,0,516,560),1405=>array(58,-13,550,547),1406=>array(36,-208,562,760),1407=>array(22,-13,579,560),1408=>array(17,-208,541,560),1409=>array(45,-215,576,560),1410=>array(68,0,440,547),1411=>array(21,-208,579,760),1412=>array(-22,-208,577,560),1413=>array(57,-14,544,560),1414=>array(-14,-208,591,760),1415=>array(3,-14,507,760),1417=>array(209,0,393,415),1418=>array(170,205,439,314),3713=>array(-6,-10,574,560),3714=>array(24,-17,572,568),3716=>array(38,-10,540,568),3719=>array(94,-238,510,568),3720=>array(66,-0,546,575),3722=>array(51,-238,588,563),3725=>array(30,-8,599,573),3732=>array(23,-14,567,560),3733=>array(35,-15,579,579),3734=>array(74,-240,578,560),3735=>array(30,-14,583,560),3737=>array(-20,-14,593,568),3738=>array(38,-8,594,561),3739=>array(19,-8,616,760),3740=>array(16,-8,664,638),3741=>array(4,-8,622,760),3742=>array(24,-8,604,561),3743=>array(5,-8,627,760),3745=>array(-32,-14,602,547),3746=>array(12,-8,620,760),3747=>array(22,-8,586,568),3749=>array(14,-8,575,568),3751=>array(27,-13,575,560),3754=>array(1,-8,679,701),3755=>array(-12,-12,619,575),3757=>array(33,-8,579,568),3758=>array(14,-8,662,605),3759=>array(52,-106,615,579),3760=>array(73,-13,640,563),3761=>array(199,639,702,880),3762=>array(145,0,586,560),3763=>array(-403,0,586,806),3764=>array(41,615,562,926),3765=>array(41,612,616,926),3766=>array(41,615,562,926),3767=>array(41,612,616,926),3768=>array(201,-350,404,-38),3769=>array(144,-306,440,-40),3771=>array(31,639,567,880),3772=>array(-15,-278,612,-39),3784=>array(240,618,362,792),3785=>array(34,609,582,891),3786=>array(46,598,664,869),3787=>array(154,609,448,890),3788=>array(-15,636,612,875),3789=>array(199,620,404,806),4304=>array(60,0,522,560),4305=>array(46,0,510,761),4306=>array(21,-208,528,510),4307=>array(42,-208,609,505),4308=>array(41,-208,562,510),4309=>array(41,-208,559,510),4310=>array(43,0,507,760),4311=>array(17,0,591,505),4312=>array(72,0,535,510),4313=>array(42,-207,553,501),4314=>array(62,-208,557,510),4315=>array(44,0,568,760),4316=>array(43,0,538,748),4317=>array(17,0,588,505),4318=>array(40,0,541,757),4319=>array(37,-207,596,524),4320=>array(-7,0,567,760),4321=>array(46,0,506,743),4322=>array(-3,-207,580,614),4323=>array(53,-207,579,506),4324=>array(38,-208,614,505),4325=>array(20,-208,616,743),4326=>array(37,-208,611,506),4327=>array(42,-207,592,496),4328=>array(45,0,573,760),4329=>array(3,0,509,760),4330=>array(25,-207,578,518),4331=>array(44,0,597,743),4332=>array(45,0,624,760),4333=>array(19,-207,532,743),4334=>array(46,0,512,743),4335=>array(35,-207,533,605),4336=>array(37,0,558,760),4337=>array(2,-207,590,760),4338=>array(36,-131,547,511),4339=>array(41,-208,595,510),4340=>array(17,-208,578,760),4341=>array(22,0,582,760),4342=>array(30,-207,615,511),4343=>array(17,-207,525,511),4344=>array(40,-207,554,520),4345=>array(78,-208,583,518),4346=>array(56,-66,551,511),4347=>array(97,24,470,486),4348=>array(181,370,441,760),7426=>array(13,-14,629,560),7432=>array(51,-11,542,560),7433=>array(130,-211,590,549),7444=>array(-23,-14,601,560),7446=>array(120,273,588,560),7447=>array(119,-14,588,273),7453=>array(21,1,648,419),7454=>array(42,-1,643,417),7455=>array(21,0,666,501),7468=>array(83,326,440,734),7469=>array(80,326,516,734),7470=>array(112,326,457,734),7472=>array(112,326,457,734),7473=>array(123,326,474,734),7474=>array(123,326,480,734),7475=>array(140,318,475,742),7476=>array(114,326,488,734),7477=>array(134,326,468,734),7478=>array(135,318,472,734),7479=>array(94,326,502,734),7480=>array(119,326,413,734),7481=>array(99,326,503,734),7482=>array(115,326,487,734),7483=>array(115,326,487,734),7484=>array(139,318,463,742),7486=>array(116,326,465,734),7487=>array(94,326,437,734),7488=>array(157,326,516,734),7489=>array(139,318,486,734),7490=>array(140,326,530,734),7491=>array(145,318,457,640),7492=>array(144,318,458,640),7493=>array(140,318,462,640),7494=>array(107,318,495,640),7495=>array(140,318,462,751),7496=>array(126,318,476,751),7497=>array(143,318,459,640),7498=>array(143,318,459,640),7499=>array(146,320,457,640),7500=>array(146,320,457,640),7501=>array(134,206,468,640),7502=>array(156,208,446,633),7503=>array(130,326,472,751),7504=>array(118,326,484,640),7505=>array(146,209,456,640),7506=>array(147,318,455,640),7507=>array(150,318,452,640),7508=>array(150,479,452,640),7509=>array(150,318,452,479),7510=>array(127,209,475,640),7511=>array(158,326,444,719),7512=>array(146,319,456,632),7513=>array(104,327,499,561),7514=>array(119,326,483,640),7515=>array(142,326,460,632),7522=>array(156,0,446,425),7523=>array(169,-8,432,306),7524=>array(146,-7,456,306),7525=>array(142,0,460,306),7543=>array(36,-215,566,560),7544=>array(114,326,488,734),7547=>array(78,0,630,547),7557=>array(196,-208,520,765),7579=>array(140,318,462,640),7580=>array(150,318,452,640),7581=>array(147,286,455,639),7582=>array(146,318,457,751),7583=>array(143,320,459,640),7584=>array(150,326,452,751),7585=>array(155,209,447,632),7586=>array(134,206,468,631),7587=>array(146,208,456,632),7588=>array(144,326,458,751),7589=>array(197,326,405,632),7590=>array(127,326,475,632),7591=>array(127,326,475,632),7592=>array(148,209,454,751),7593=>array(217,209,385,755),7594=>array(199,209,403,755),7595=>array(182,326,420,640),7596=>array(119,209,483,640),7597=>array(119,208,483,640),7598=>array(130,209,472,640),7599=>array(169,209,433,640),7600=>array(122,326,480,640),7601=>array(147,318,455,640),7602=>array(140,210,462,751),7603=>array(143,209,459,640),7604=>array(124,209,478,751),7605=>array(188,209,472,719),7606=>array(97,318,505,632),7607=>array(122,318,480,632),7609=>array(151,326,451,632),7610=>array(133,326,469,632),7611=>array(139,326,463,632),7612=>array(164,209,438,632),7613=>array(129,296,473,632),7614=>array(119,207,483,632),7615=>array(143,318,459,736),7680=>array(-52,-245,513,729),7681=>array(35,-245,531,560),7682=>array(11,0,570,914),7683=>array(29,-14,541,760),7684=>array(11,-202,570,729),7685=>array(29,-202,541,760),7686=>array(11,-174,570,729),7687=>array(29,-174,541,760),7688=>array(56,-193,594,927),7689=>array(76,-193,594,800),7690=>array(-4,0,552,914),7691=>array(58,-14,612,760),7692=>array(-4,-202,552,729),7693=>array(58,-202,612,760),7694=>array(-4,-174,552,729),7695=>array(51,-174,612,760),7696=>array(-43,-193,552,729),7697=>array(58,-193,612,760),7698=>array(-4,-237,552,729),7699=>array(28,-237,612,760),7704=>array(26,-237,600,729),7705=>array(35,-237,550,561),7706=>array(26,-238,600,729),7707=>array(30,-238,550,561),7708=>array(26,-193,600,928),7709=>array(48,-193,550,785),7710=>array(45,0,616,914),7711=>array(129,0,608,914),7712=>array(38,-14,576,898),7713=>array(29,-215,559,745),7714=>array(-4,0,606,914),7715=>array(41,0,535,914),7716=>array(-4,-202,606,729),7717=>array(41,-202,535,760),7718=>array(-4,0,606,913),7719=>array(41,0,535,918),7720=>array(-94,-193,606,729),7721=>array(-77,-193,535,760),7722=>array(-4,-238,606,729),7723=>array(41,-238,535,760),7724=>array(23,-238,574,729),7725=>array(23,-238,490,760),7728=>array(-4,0,661,927),7729=>array(44,0,588,927),7730=>array(-4,-202,661,729),7731=>array(44,-202,588,760),7732=>array(-4,-174,661,729),7733=>array(44,-174,588,760),7734=>array(38,-202,505,729),7735=>array(141,-202,477,765),7736=>array(38,-202,551,898),7737=>array(141,-202,551,898),7738=>array(38,-174,505,729),7739=>array(51,-174,477,765),7740=>array(38,-237,505,729),7741=>array(28,-237,477,765),7742=>array(-29,0,631,927),7743=>array(-7,0,575,800),7744=>array(-29,0,631,914),7745=>array(-7,0,575,758),7746=>array(-29,-202,631,729),7747=>array(-7,-202,575,560),7748=>array(-3,0,605,914),7749=>array(41,0,535,758),7750=>array(-3,-202,605,729),7751=>array(41,-202,535,560),7752=>array(-3,-174,605,729),7753=>array(41,-174,535,560),7754=>array(-3,-237,605,729),7755=>array(28,-237,535,560),7756=>array(40,-14,562,997),7757=>array(57,-14,585,997),7764=>array(25,0,588,931),7765=>array(-1,-208,551,800),7766=>array(25,0,588,914),7767=>array(-1,-208,551,758),7768=>array(6,0,562,914),7769=>array(106,0,595,758),7770=>array(6,-202,562,729),7771=>array(106,-202,595,560),7772=>array(6,-202,562,898),7773=>array(106,-202,595,745),7774=>array(6,-174,562,729),7775=>array(51,-174,595,560),7776=>array(12,-14,560,914),7777=>array(56,-14,526,758),7778=>array(12,-202,560,742),7779=>array(56,-202,526,560),7784=>array(12,-202,560,914),7785=>array(56,-202,526,758),7786=>array(78,0,651,914),7787=>array(95,0,549,914),7788=>array(78,-202,651,729),7789=>array(95,-202,549,702),7790=>array(51,-174,651,729),7791=>array(51,-174,549,702),7792=>array(28,-237,651,729),7793=>array(28,-237,549,702),7794=>array(39,-201,601,729),7795=>array(46,-201,553,547),7796=>array(23,-238,601,729),7797=>array(23,-238,553,547),7798=>array(28,-237,601,729),7799=>array(28,-237,553,547),7800=>array(39,-14,601,997),7801=>array(61,-13,585,997),7804=>array(97,0,646,909),7805=>array(89,0,593,757),7806=>array(97,-202,646,729),7807=>array(89,-202,593,547),7808=>array(40,0,672,931),7809=>array(45,0,642,803),7810=>array(40,0,672,931),7811=>array(45,0,642,803),7812=>array(40,0,672,900),7813=>array(45,0,642,718),7814=>array(40,0,672,914),7815=>array(45,0,642,758),7816=>array(40,-202,672,729),7817=>array(45,-202,642,547),7818=>array(-62,0,653,914),7819=>array(-34,0,590,758),7820=>array(-62,0,653,913),7821=>array(-34,0,590,718),7822=>array(95,0,658,914),7823=>array(-19,-208,598,758),7824=>array(-3,0,622,932),7825=>array(38,0,553,803),7826=>array(-3,-202,622,729),7827=>array(38,-202,553,547),7828=>array(-3,-174,622,729),7829=>array(38,-174,553,547),7830=>array(41,-174,535,760),7831=>array(95,0,549,860),7832=>array(45,0,642,923),7833=>array(-19,-208,598,923),7835=>array(129,0,608,914),7839=>array(46,-14,535,767),7840=>array(-52,-202,513,729),7841=>array(35,-202,531,560),7852=>array(-52,-202,513,932),7853=>array(35,-202,531,803),7856=>array(-52,0,564,997),7857=>array(35,-14,536,954),7862=>array(-52,-202,564,928),7863=>array(35,-202,531,760),7864=>array(26,-202,600,729),7865=>array(48,-202,550,561),7868=>array(26,0,600,921),7869=>array(48,-14,550,777),7878=>array(26,-202,600,932),7879=>array(48,-202,550,803),7882=>array(28,-202,574,729),7883=>array(30,-202,490,760),7884=>array(40,-202,562,742),7885=>array(57,-202,544,560),7896=>array(40,-202,562,932),7897=>array(57,-202,544,803),7898=>array(-20,-14,634,927),7899=>array(5,-14,595,800),7900=>array(-20,-14,634,927),7901=>array(5,-14,595,800),7904=>array(-20,-14,634,921),7905=>array(5,-14,595,777),7906=>array(-20,-202,634,760),7907=>array(5,-202,595,560),7908=>array(39,-202,601,729),7909=>array(61,-202,553,547),7912=>array(-29,-14,652,927),7913=>array(-15,-13,592,800),7914=>array(-29,-14,652,927),7915=>array(-15,-13,592,800),7918=>array(-29,-14,652,921),7919=>array(-15,-13,592,777),7920=>array(-29,-202,652,760),7921=>array(-15,-202,592,555),7922=>array(95,0,658,931),7923=>array(-19,-208,598,803),7924=>array(95,-202,658,729),7925=>array(-19,-208,598,547),7928=>array(95,0,658,921),7929=>array(-19,-208,598,777),7936=>array(34,-12,606,806),7937=>array(34,-12,606,806),7938=>array(34,-12,606,806),7939=>array(34,-12,606,806),7940=>array(34,-12,606,806),7941=>array(34,-12,606,806),7942=>array(34,-12,606,977),7943=>array(34,-12,606,977),7944=>array(-52,0,513,806),7945=>array(-52,0,513,806),7946=>array(-165,0,513,806),7947=>array(-141,0,513,806),7948=>array(-80,0,513,806),7949=>array(-65,0,513,806),7950=>array(-52,0,513,977),7951=>array(-52,0,513,977),7952=>array(64,-15,536,806),7953=>array(64,-15,536,806),7954=>array(64,-15,536,806),7955=>array(64,-15,536,806),7956=>array(64,-15,599,806),7957=>array(64,-15,599,806),7960=>array(-31,0,600,806),7961=>array(-6,0,600,806),7962=>array(-275,0,600,806),7963=>array(-250,0,600,806),7964=>array(-214,0,600,806),7965=>array(-199,0,600,806),7968=>array(61,-208,545,806),7969=>array(61,-208,545,806),7970=>array(61,-208,545,806),7971=>array(61,-208,545,806),7972=>array(61,-208,599,806),7973=>array(61,-208,599,806),7974=>array(61,-208,576,977),7975=>array(61,-208,572,977),7976=>array(-55,0,606,806),7977=>array(-31,0,606,806),7978=>array(-312,0,606,806),7979=>array(-287,0,606,806),7980=>array(-263,0,606,806),7981=>array(-248,0,606,806),7982=>array(-112,0,606,977),7983=>array(-116,0,606,977),7984=>array(191,0,438,806),7985=>array(191,0,438,806),7986=>array(152,0,536,806),7987=>array(177,0,536,806),7988=>array(177,0,599,806),7989=>array(191,0,599,806),7990=>array(191,0,576,977),7991=>array(191,0,572,977),7992=>array(-31,0,574,806),7993=>array(-6,0,574,806),7994=>array(-263,0,574,806),7995=>array(-238,0,574,806),7996=>array(-214,0,574,806),7997=>array(-199,0,574,806),7998=>array(-75,0,574,977),7999=>array(-79,0,574,977),8000=>array(57,-14,544,806),8001=>array(57,-14,544,806),8002=>array(57,-14,544,806),8003=>array(57,-14,544,806),8004=>array(57,-14,599,806),8005=>array(57,-14,599,806),8008=>array(6,-14,562,806),8009=>array(-6,-14,562,806),8010=>array(-275,-14,562,806),8011=>array(-250,-14,562,806),8012=>array(-141,-14,562,806),8013=>array(-126,-14,562,806),8016=>array(64,0,564,806),8017=>array(64,0,564,806),8018=>array(64,0,564,806),8019=>array(64,0,564,806),8020=>array(64,0,599,806),8021=>array(64,0,599,806),8022=>array(64,0,576,977),8023=>array(64,0,572,977),8025=>array(-80,0,658,806),8027=>array(-287,0,658,806),8029=>array(-285,0,658,806),8031=>array(-152,0,658,977),8032=>array(24,-14,574,806),8033=>array(24,-14,574,806),8034=>array(24,-14,574,806),8035=>array(24,-14,574,806),8036=>array(24,-14,599,806),8037=>array(24,-14,599,806),8038=>array(24,-14,576,977),8039=>array(24,-14,574,977),8040=>array(-33,0,564,806),8041=>array(-33,0,564,806),8042=>array(-275,0,564,806),8043=>array(-250,0,564,806),8044=>array(-128,0,564,806),8045=>array(-114,0,564,806),8046=>array(-39,0,564,977),8047=>array(-79,0,564,977),8048=>array(34,-12,606,800),8049=>array(34,-12,606,800),8050=>array(64,-15,536,800),8051=>array(64,-15,550,800),8052=>array(61,-208,545,800),8053=>array(61,-208,550,800),8054=>array(191,0,438,800),8055=>array(191,0,550,800),8056=>array(57,-14,544,800),8057=>array(57,-14,550,800),8058=>array(64,0,564,800),8059=>array(64,0,564,800),8060=>array(24,-14,574,800),8061=>array(24,-14,574,800),8064=>array(34,-208,606,806),8065=>array(34,-208,606,806),8066=>array(34,-208,606,806),8067=>array(34,-208,606,806),8068=>array(34,-208,606,806),8069=>array(34,-208,606,806),8070=>array(34,-208,606,977),8071=>array(34,-208,606,977),8072=>array(-52,-208,513,806),8073=>array(-52,-208,513,806),8074=>array(-165,-208,513,806),8075=>array(-141,-208,513,806),8076=>array(-80,-208,513,806),8077=>array(-65,-208,513,806),8078=>array(-52,-208,513,977),8079=>array(-52,-208,513,977),8080=>array(44,-208,545,806),8081=>array(44,-208,545,806),8082=>array(44,-208,545,806),8083=>array(44,-208,545,806),8084=>array(44,-208,599,806),8085=>array(44,-208,599,806),8086=>array(44,-208,576,977),8087=>array(44,-208,572,977),8088=>array(-55,-208,606,806),8089=>array(-31,-208,606,806),8090=>array(-312,-208,606,806),8091=>array(-287,-208,606,806),8092=>array(-263,-208,606,806),8093=>array(-248,-208,606,806),8094=>array(-112,-208,606,977),8095=>array(-116,-208,606,977),8096=>array(24,-208,574,806),8097=>array(24,-208,574,806),8098=>array(24,-208,574,806),8099=>array(24,-208,574,806),8100=>array(24,-208,599,806),8101=>array(24,-208,599,806),8102=>array(24,-208,576,977),8103=>array(24,-208,574,977),8104=>array(-33,-208,564,806),8105=>array(-33,-208,564,806),8106=>array(-275,-208,564,806),8107=>array(-250,-208,564,806),8108=>array(-128,-208,564,806),8109=>array(-114,-208,564,806),8110=>array(-39,-208,564,977),8111=>array(-79,-208,564,977),8112=>array(34,-12,606,785),8113=>array(34,-12,606,745),8114=>array(34,-208,606,800),8115=>array(34,-208,606,559),8116=>array(34,-208,606,800),8118=>array(34,-12,606,777),8119=>array(34,-208,606,777),8120=>array(-52,0,564,928),8121=>array(-52,0,551,898),8122=>array(-52,0,513,800),8123=>array(-52,0,513,800),8124=>array(-52,-208,513,729),8125=>array(274,595,434,806),8126=>array(197,-208,293,-45),8127=>array(274,595,434,806),8128=>array(196,638,542,777),8129=>array(213,659,580,943),8130=>array(44,-208,545,800),8131=>array(44,-208,545,560),8132=>array(44,-208,550,800),8134=>array(61,-208,545,777),8135=>array(44,-208,545,777),8136=>array(-96,0,600,800),8137=>array(-61,0,600,800),8138=>array(-121,0,606,800),8139=>array(-85,0,606,800),8140=>array(-4,-208,606,729),8141=>array(152,595,536,806),8142=>array(177,595,599,806),8143=>array(230,595,576,977),8144=>array(191,0,536,785),8145=>array(191,0,521,745),8146=>array(191,0,522,980),8147=>array(191,0,601,980),8150=>array(191,0,542,777),8151=>array(191,0,580,943),8152=>array(28,0,574,928),8153=>array(28,0,574,898),8154=>array(-72,0,574,800),8155=>array(-61,0,574,800),8157=>array(177,595,536,806),8158=>array(191,595,599,806),8159=>array(226,595,572,977),8160=>array(64,0,564,785),8161=>array(64,0,564,745),8162=>array(64,0,564,980),8163=>array(64,0,601,980),8164=>array(18,-208,560,806),8165=>array(18,-208,560,806),8166=>array(64,0,564,777),8167=>array(64,0,580,943),8168=>array(95,0,658,928),8169=>array(95,0,658,898),8170=>array(-121,0,658,800),8171=>array(-146,0,658,800),8172=>array(-6,0,588,806),8173=>array(213,659,522,980),8174=>array(213,659,601,980),8175=>array(221,616,414,800),8178=>array(24,-208,574,800),8179=>array(24,-208,574,547),8180=>array(24,-208,574,800),8182=>array(24,-14,574,777),8183=>array(24,-208,574,777),8184=>array(-84,-14,562,800),8185=>array(12,-14,562,800),8186=>array(-84,0,564,800),8187=>array(-33,0,564,800),8188=>array(-33,-208,564,713),8189=>array(281,616,550,800),8190=>array(299,595,434,806),8208=>array(148,234,419,314),8209=>array(148,234,419,314),8210=>array(-25,240,591,309),8211=>array(-25,240,591,309),8212=>array(-25,240,591,309),8213=>array(-25,240,591,309),8214=>array(139,-236,462,764),8215=>array(0,-236,602,-80),8216=>array(226,472,453,760),8217=>array(226,472,453,760),8218=>array(99,-140,326,148),8219=>array(263,472,407,760),8220=>array(120,472,571,760),8221=>array(108,472,559,760),8222=>array(-8,-140,443,148),8223=>array(145,472,513,760),8224=>array(95,-96,554,729),8225=>array(29,-96,554,729),8226=>array(156,227,446,516),8227=>array(156,188,485,555),8230=>array(-32,0,520,148),8240=>array(0,0,602,699),8241=>array(0,0,602,699),8242=>array(315,547,534,729),8243=>array(242,547,607,729),8244=>array(169,547,681,729),8245=>array(351,547,499,729),8246=>array(277,547,572,729),8247=>array(204,547,646,729),8249=>array(151,69,428,517),8250=>array(155,69,431,517),8252=>array(31,0,572,729),8253=>array(163,0,546,742),8254=>array(0,716,602,755),8261=>array(129,-132,510,760),8262=>array(72,-132,453,760),8263=>array(-13,0,615,743),8264=>array(59,0,587,743),8265=>array(31,0,603,743),8267=>array(19,-96,590,729),8304=>array(172,319,513,742),8305=>array(156,326,446,751),8308=>array(135,326,458,734),8309=>array(150,319,513,734),8310=>array(173,319,513,742),8311=>array(172,326,513,734),8312=>array(157,319,513,742),8313=>array(172,319,513,742),8314=>array(139,357,464,646),8315=>array(139,479,464,525),8316=>array(139,422,464,581),8317=>array(198,252,404,751),8318=>array(198,252,404,751),8319=>array(126,326,456,640),8320=>array(172,-7,513,416),8321=>array(170,0,450,408),8322=>array(150,0,484,416),8323=>array(140,-7,480,416),8324=>array(135,0,458,408),8325=>array(150,-7,513,408),8326=>array(173,-7,513,416),8327=>array(172,0,513,408),8328=>array(157,-7,513,416),8329=>array(172,-7,513,416),8330=>array(139,31,464,320),8331=>array(139,152,464,199),8332=>array(139,96,464,254),8333=>array(198,-74,404,425),8334=>array(198,-74,404,425),8336=>array(145,-8,457,313),8337=>array(143,-8,459,314),8338=>array(147,-8,455,313),8339=>array(104,0,491,306),8340=>array(143,-8,459,313),8341=>array(115,-8,440,418),8342=>array(130,0,472,425),8343=>array(201,0,402,429),8344=>array(118,0,484,313),8345=>array(126,0,456,313),8346=>array(127,-117,475,313),8347=>array(142,0,442,322),8348=>array(158,0,444,393),8352=>array(40,0,594,729),8353=>array(38,-44,579,778),8354=>array(38,-14,579,742),8355=>array(28,0,574,729),8356=>array(22,0,587,742),8357=>array(22,-93,536,640),8358=>array(-19,0,621,729),8359=>array(2,-14,595,729),8360=>array(4,-14,579,729),8361=>array(2,0,646,729),8362=>array(-19,-14,659,729),8363=>array(58,-175,691,760),8364=>array(-5,-14,582,742),8365=>array(16,0,650,729),8366=>array(78,0,648,729),8367=>array(5,-231,593,753),8368=>array(8,-14,526,742),8369=>array(25,0,641,729),8370=>array(29,-81,573,809),8371=>array(-28,0,604,729),8372=>array(-19,-14,621,742),8373=>array(65,-147,592,760),8376=>array(50,0,650,729),8377=>array(55,0,626,729),8450=>array(57,-14,590,742),8453=>array(0,-24,598,752),8461=>array(28,0,577,729),8462=>array(41,0,535,760),8463=>array(41,0,535,760),8469=>array(36,0,565,729),8470=>array(-66,0,581,729),8471=>array(0,61,602,663),8473=>array(32,0,575,729),8474=>array(8,-129,592,742),8477=>array(18,0,592,729),8482=>array(0,447,550,729),8484=>array(23,0,575,729),8486=>array(-33,0,564,713),8490=>array(-4,0,661,729),8491=>array(-52,0,513,928),8494=>array(5,-12,597,647),8520=>array(13,0,469,760),8531=>array(23,-139,553,810),8532=>array(23,-139,553,818),8533=>array(23,-139,580,810),8534=>array(23,-139,580,818),8535=>array(23,-139,580,818),8536=>array(23,-139,580,810),8537=>array(23,-139,580,810),8538=>array(23,-139,580,810),8539=>array(23,-139,580,810),8540=>array(23,-139,580,818),8541=>array(23,-139,580,810),8542=>array(23,-139,580,810),8543=>array(23,246,553,810),8592=>array(32,112,570,436),8593=>array(139,0,463,538),8594=>array(32,112,570,436),8595=>array(139,0,463,538),8596=>array(32,112,570,436),8597=>array(139,0,463,538),8598=>array(90,0,512,422),8599=>array(90,0,512,422),8600=>array(90,0,512,422),8601=>array(90,0,512,422),8602=>array(32,112,570,436),8603=>array(32,112,570,436),8604=>array(43,193,559,422),8605=>array(43,193,559,422),8606=>array(32,112,570,436),8607=>array(139,0,463,538),8608=>array(32,112,570,436),8609=>array(139,0,463,538),8610=>array(32,112,570,436),8611=>array(32,112,570,436),8612=>array(32,112,570,436),8613=>array(139,0,463,538),8614=>array(32,112,570,436),8615=>array(139,0,463,538),8616=>array(139,0,463,538),8617=>array(32,112,570,517),8618=>array(32,112,570,517),8619=>array(32,112,570,517),8620=>array(32,112,570,517),8621=>array(32,112,570,436),8622=>array(32,102,570,446),8623=>array(55,0,547,698),8624=>array(89,0,513,674),8625=>array(89,0,513,674),8626=>array(89,0,513,674),8627=>array(89,0,513,674),8628=>array(91,0,511,540),8629=>array(31,0,571,420),8630=>array(40,168,563,487),8631=>array(40,168,563,487),8632=>array(24,0,578,513),8633=>array(32,0,570,604),8634=>array(43,0,559,497),8635=>array(43,0,559,497),8636=>array(32,234,570,436),8637=>array(32,112,570,314),8638=>array(261,0,463,538),8639=>array(139,0,341,538),8640=>array(32,234,570,436),8641=>array(32,112,570,314),8642=>array(261,0,463,538),8643=>array(160,0,362,538),8644=>array(32,0,570,561),8645=>array(21,0,582,538),8646=>array(32,0,570,561),8647=>array(32,0,570,561),8648=>array(21,0,582,538),8649=>array(32,0,570,561),8650=>array(21,0,582,538),8651=>array(32,32,570,516),8652=>array(32,32,570,516),8653=>array(32,112,570,436),8654=>array(32,112,570,460),8655=>array(32,112,570,436),8656=>array(32,112,570,436),8657=>array(139,0,463,538),8658=>array(32,112,570,436),8659=>array(139,0,463,538),8660=>array(32,112,570,436),8661=>array(139,0,463,538),8662=>array(76,-28,526,422),8663=>array(76,-28,526,422),8664=>array(76,0,526,451),8665=>array(76,0,526,451),8666=>array(32,112,570,436),8667=>array(32,112,570,436),8668=>array(32,112,570,436),8669=>array(32,112,570,436),8670=>array(139,0,463,538),8671=>array(139,0,463,538),8672=>array(32,112,570,436),8673=>array(139,0,463,538),8674=>array(32,112,570,436),8675=>array(139,0,463,538),8676=>array(32,112,570,436),8677=>array(32,112,570,436),8678=>array(12,92,570,456),8679=>array(119,0,483,558),8680=>array(32,92,590,456),8681=>array(119,0,483,558),8682=>array(119,0,483,558),8683=>array(119,0,483,558),8684=>array(119,0,483,558),8685=>array(119,0,483,558),8686=>array(119,0,483,558),8687=>array(119,0,483,558),8688=>array(32,92,590,456),8689=>array(34,0,568,534),8690=>array(34,0,568,534),8691=>array(119,0,483,558),8692=>array(32,112,570,436),8693=>array(21,0,582,538),8694=>array(32,-125,570,672),8695=>array(32,112,570,436),8696=>array(32,112,570,436),8697=>array(32,112,570,436),8698=>array(32,112,570,436),8699=>array(32,112,570,436),8700=>array(32,112,570,436),8701=>array(12,92,570,456),8702=>array(32,92,590,456),8703=>array(12,92,590,456),8704=>array(18,0,584,729),8705=>array(57,-14,545,742),8706=>array(89,-14,513,662),8707=>array(87,0,514,729),8708=>array(87,-46,514,776),8709=>array(36,48,567,580),8710=>array(-3,0,606,695),8711=>array(-3,0,606,695),8712=>array(63,0,539,715),8713=>array(63,-86,539,801),8714=>array(63,81,539,545),8715=>array(63,0,539,715),8716=>array(63,-86,539,801),8717=>array(63,81,539,545),8719=>array(74,-213,528,741),8721=>array(70,-213,530,741),8722=>array(43,272,559,355),8723=>array(43,0,559,572),8725=>array(8,-93,517,729),8727=>array(81,85,521,542),8728=>array(146,160,456,470),8729=>array(156,200,446,489),8730=>array(29,-19,578,828),8731=>array(29,-19,578,933),8732=>array(29,-19,578,924),8733=>array(91,122,511,492),8734=>array(20,122,582,492),8735=>array(61,140,541,620),8736=>array(61,140,541,620),8743=>array(80,0,521,579),8744=>array(80,0,521,579),8745=>array(80,0,521,579),8746=>array(80,0,521,579),8747=>array(63,-183,539,871),8748=>array(31,-189,571,877),8749=>array(26,-176,577,864),8756=>array(91,65,512,564),8757=>array(92,65,510,564),8758=>array(238,65,363,564),8759=>array(91,65,512,564),8760=>array(43,272,559,564),8761=>array(36,65,566,564),8762=>array(42,65,561,564),8763=>array(43,65,559,564),8764=>array(43,243,559,384),8765=>array(43,243,559,384),8769=>array(43,85,559,535),8770=>array(43,149,559,454),8771=>array(43,172,559,470),8772=>array(43,48,560,604),8773=>array(43,94,559,570),8774=>array(43,24,559,570),8775=>array(43,0,559,647),8776=>array(43,149,559,470),8777=>array(43,23,559,595),8778=>array(43,94,559,572),8779=>array(43,73,559,572),8780=>array(43,94,559,570),8781=>array(42,108,559,519),8782=>array(43,33,560,593),8783=>array(43,172,560,593),8784=>array(43,172,559,637),8785=>array(43,-11,559,637),8786=>array(43,-10,559,637),8787=>array(42,-10,560,637),8788=>array(36,147,566,479),8789=>array(36,147,566,479),8790=>array(43,172,559,454),8791=>array(43,172,559,760),8792=>array(43,172,559,662),8793=>array(43,172,559,783),8794=>array(43,172,559,783),8795=>array(43,172,559,831),8796=>array(43,172,559,836),8797=>array(34,172,568,764),8798=>array(43,172,559,760),8799=>array(43,172,559,856),8800=>array(43,18,559,608),8801=>array(43,94,559,532),8802=>array(43,5,559,622),8803=>array(43,0,559,616),8804=>array(42,0,558,531),8805=>array(43,0,559,531),8806=>array(42,-84,558,578),8807=>array(42,-84,558,578),8808=>array(42,-162,558,578),8809=>array(42,-162,558,578),8813=>array(42,0,559,627),8814=>array(43,-14,559,641),8815=>array(43,-14,559,641),8816=>array(43,-119,559,629),8817=>array(43,-119,559,629),8818=>array(42,-21,558,531),8819=>array(42,-21,558,531),8820=>array(42,-119,558,629),8821=>array(42,-119,558,629),8822=>array(42,-89,558,603),8823=>array(42,-89,558,603),8824=>array(42,-195,558,711),8825=>array(42,-195,558,711),8826=>array(42,-22,558,648),8827=>array(43,-22,559,648),8828=>array(42,-123,558,711),8829=>array(42,-123,558,711),8830=>array(42,-56,558,711),8831=>array(42,-56,558,711),8832=>array(42,-81,558,707),8833=>array(42,-81,558,707),8834=>array(43,80,559,546),8835=>array(43,80,559,546),8836=>array(43,-29,559,655),8837=>array(43,-29,559,655),8838=>array(43,0,559,625),8839=>array(43,0,559,625),8840=>array(43,-104,559,729),8841=>array(43,-104,559,729),8842=>array(43,-102,559,625),8843=>array(43,-102,559,625),8847=>array(43,58,559,568),8848=>array(43,58,559,568),8849=>array(43,7,559,619),8850=>array(43,7,559,619),8853=>array(39,51,563,577),8854=>array(39,51,563,577),8855=>array(39,51,563,577),8856=>array(39,51,563,577),8857=>array(39,51,563,577),8858=>array(39,51,563,577),8859=>array(39,51,563,577),8860=>array(39,51,563,577),8861=>array(39,52,563,577),8862=>array(39,51,564,576),8863=>array(39,51,564,576),8864=>array(39,51,564,576),8865=>array(39,51,564,576),8866=>array(43,0,559,627),8867=>array(43,0,559,627),8868=>array(43,0,559,627),8869=>array(43,0,559,627),8901=>array(239,273,362,422),8902=>array(129,201,473,527),8909=>array(43,172,559,470),8922=>array(43,-218,559,760),8923=>array(43,-218,559,760),8924=>array(42,0,558,531),8925=>array(43,0,559,531),8926=>array(42,-123,558,711),8927=>array(42,-123,558,711),8928=>array(42,-182,558,770),8929=>array(42,-182,558,770),8930=>array(43,-81,559,707),8931=>array(43,-81,559,707),8932=>array(43,-95,559,619),8933=>array(43,-95,559,619),8934=>array(42,-134,558,531),8935=>array(42,-134,558,531),8936=>array(42,-213,558,711),8937=>array(42,-213,558,711),8943=>array(39,239,562,388),8960=>array(36,48,567,580),8961=>array(56,162,540,443),8962=>array(71,0,531,596),8963=>array(71,406,530,746),8964=>array(71,-132,530,209),8965=>array(71,0,530,444),8966=>array(71,0,530,566),8968=>array(139,-132,520,760),8969=>array(199,-132,463,760),8970=>array(139,-132,403,760),8971=>array(82,-132,463,760),8972=>array(268,73,585,408),8973=>array(6,73,324,408),8974=>array(268,352,585,687),8975=>array(6,352,324,687),8976=>array(43,181,559,421),8977=>array(47,126,555,634),8978=>array(3,211,599,512),8979=>array(3,211,599,512),8980=>array(90,168,512,512),8981=>array(81,112,510,539),8984=>array(35,114,567,646),8985=>array(43,181,559,421),8988=>array(146,352,463,687),8989=>array(139,352,456,687),8990=>array(146,-56,463,279),8991=>array(139,-56,456,279),8992=>array(250,-250,537,928),8993=>array(61,-237,347,942),8997=>array(51,114,551,598),8998=>array(3,145,599,536),8999=>array(61,145,541,536),9000=>array(24,212,578,517),9003=>array(3,145,599,536),9013=>array(35,-22,566,286),9015=>array(125,-100,477,829),9016=>array(3,-100,599,829),9017=>array(3,-100,599,829),9018=>array(3,-100,599,829),9019=>array(3,-100,599,829),9020=>array(3,-100,599,829),9021=>array(3,-171,599,900),9022=>array(3,57,599,658),9025=>array(3,-100,599,829),9026=>array(3,-100,599,829),9027=>array(3,-100,599,829),9028=>array(3,-100,599,829),9031=>array(3,-100,599,829),9032=>array(3,-100,599,829),9033=>array(3,-29,599,729),9035=>array(18,-171,584,900),9036=>array(3,-100,599,829),9037=>array(3,-100,599,829),9040=>array(3,-100,599,829),9042=>array(18,-171,584,900),9043=>array(3,-100,599,829),9044=>array(3,-100,599,829),9047=>array(3,-100,599,829),9048=>array(125,-100,477,729),9049=>array(3,-100,599,729),9050=>array(3,-100,599,656),9051=>array(125,-100,477,489),9052=>array(3,-100,599,658),9054=>array(3,-100,599,829),9055=>array(-10,44,612,671),9056=>array(3,-100,599,829),9059=>array(129,201,473,636),9060=>array(156,229,446,660),9061=>array(3,57,599,831),9064=>array(43,240,559,660),9065=>array(43,69,559,660),9067=>array(18,0,584,729),9068=>array(43,-14,559,742),9069=>array(43,-171,559,900),9070=>array(125,-140,477,519),9071=>array(3,-100,599,829),9072=>array(3,-100,599,829),9075=>array(151,0,476,547),9076=>array(93,-208,541,560),9077=>array(34,-14,568,547),9078=>array(3,-100,599,559),9079=>array(76,-100,526,560),9080=>array(125,-100,477,547),9081=>array(3,-100,599,547),9082=>array(34,-12,573,559),9085=>array(13,-228,589,88),9088=>array(35,-22,566,528),9089=>array(3,106,599,528),9090=>array(3,106,599,528),9091=>array(3,177,599,567),9096=>array(40,27,562,601),9097=>array(34,46,567,579),9098=>array(34,46,567,579),9099=>array(34,46,567,579),9109=>array(3,-100,599,829),9115=>array(137,-258,465,940),9116=>array(137,-252,232,942),9117=>array(137,-240,465,942),9118=>array(137,-258,465,940),9119=>array(370,-252,465,942),9120=>array(137,-240,465,942),9121=>array(137,-252,465,928),9122=>array(137,-252,232,942),9123=>array(137,-240,465,942),9124=>array(137,-252,465,928),9125=>array(370,-252,465,935),9126=>array(137,-240,465,935),9127=>array(256,-261,594,928),9128=>array(8,-252,347,940),9129=>array(256,-240,594,940),9130=>array(256,-256,347,943),9131=>array(8,-261,346,928),9132=>array(255,-252,594,940),9133=>array(8,-240,346,940),9134=>array(250,-250,347,942),9166=>array(12,92,570,558),9167=>array(3,0,599,596),9251=>array(28,-228,545,88),9472=>array(-10,242,612,326),9473=>array(-10,200,612,368),9474=>array(262,-302,340,973),9475=>array(223,-302,379,973),9476=>array(-10,242,612,326),9477=>array(-10,200,612,368),9478=>array(262,-302,340,973),9479=>array(223,-302,379,973),9480=>array(-10,242,612,326),9481=>array(-10,200,612,368),9482=>array(262,-302,340,973),9483=>array(223,-302,379,973),9484=>array(262,-302,612,326),9485=>array(262,-302,612,368),9486=>array(223,-302,612,326),9487=>array(223,-302,612,368),9488=>array(-10,-302,340,326),9489=>array(-10,-302,340,368),9490=>array(-10,-302,379,326),9491=>array(-10,-302,379,368),9492=>array(262,242,612,973),9493=>array(262,200,612,973),9494=>array(223,242,612,973),9495=>array(223,200,612,973),9496=>array(-10,242,340,973),9497=>array(-10,200,340,973),9498=>array(-10,242,379,973),9499=>array(-10,200,379,973),9500=>array(262,-302,612,973),9501=>array(262,-302,612,973),9502=>array(223,-302,612,973),9503=>array(223,-302,612,973),9504=>array(223,-302,612,973),9505=>array(223,-302,612,973),9506=>array(223,-302,612,973),9507=>array(223,-302,612,973),9508=>array(-10,-302,340,973),9509=>array(-10,-302,340,973),9510=>array(-10,-302,379,973),9511=>array(-10,-302,379,973),9512=>array(-10,-302,379,973),9513=>array(-10,-302,379,973),9514=>array(-10,-302,379,973),9515=>array(-10,-302,379,973),9516=>array(-10,-302,612,326),9517=>array(-10,-302,612,368),9518=>array(-10,-302,612,368),9519=>array(-10,-302,612,368),9520=>array(-10,-302,612,326),9521=>array(-10,-302,612,368),9522=>array(-10,-302,612,368),9523=>array(-10,-302,612,368),9524=>array(-10,242,612,973),9525=>array(-10,200,612,973),9526=>array(-10,200,612,973),9527=>array(-10,200,612,973),9528=>array(-10,242,612,973),9529=>array(-10,200,612,973),9530=>array(-10,200,612,973),9531=>array(-10,200,612,973),9532=>array(-10,-302,612,973),9533=>array(-10,-302,612,973),9534=>array(-10,-302,612,973),9535=>array(-10,-302,612,973),9536=>array(-10,-302,612,973),9537=>array(-10,-302,612,973),9538=>array(-10,-302,612,973),9539=>array(-10,-302,612,973),9540=>array(-10,-302,612,973),9541=>array(-10,-302,612,973),9542=>array(-10,-302,612,973),9543=>array(-10,-302,612,973),9544=>array(-10,-302,612,973),9545=>array(-10,-302,612,973),9546=>array(-10,-302,612,973),9547=>array(-10,-302,612,973),9548=>array(-10,242,612,326),9549=>array(-10,200,612,368),9550=>array(262,-302,340,973),9551=>array(223,-302,379,973),9552=>array(-10,158,612,410),9553=>array(184,-302,418,973),9554=>array(262,-302,612,410),9555=>array(184,-302,612,326),9556=>array(184,-302,612,410),9557=>array(-10,-302,340,410),9558=>array(-10,-302,418,326),9559=>array(-10,-302,418,410),9560=>array(262,158,612,973),9561=>array(184,242,612,973),9562=>array(184,158,612,973),9563=>array(-10,158,340,973),9564=>array(-10,242,418,973),9565=>array(-10,158,418,973),9566=>array(262,-302,612,973),9567=>array(184,-302,612,973),9568=>array(184,-302,612,973),9569=>array(-10,-302,340,973),9570=>array(-10,-302,418,973),9571=>array(-10,-302,418,973),9572=>array(-10,-302,612,410),9573=>array(-10,-302,612,326),9574=>array(-10,-302,612,410),9575=>array(-10,158,612,973),9576=>array(-10,242,612,973),9577=>array(-10,158,612,973),9578=>array(-10,-302,612,973),9579=>array(-10,-302,612,973),9580=>array(-10,-302,612,973),9581=>array(262,-302,612,326),9582=>array(-10,-302,340,326),9583=>array(-10,242,340,973),9584=>array(262,242,612,973),9585=>array(-53,-302,655,973),9586=>array(-53,-302,655,973),9587=>array(-53,-302,655,973),9588=>array(-10,242,311,326),9589=>array(262,284,340,973),9590=>array(311,242,612,326),9591=>array(262,-302,340,284),9592=>array(-10,200,311,368),9593=>array(223,284,379,973),9594=>array(311,200,612,368),9595=>array(223,-302,379,284),9596=>array(-10,200,612,368),9597=>array(223,-302,379,973),9598=>array(-10,200,612,368),9599=>array(223,-302,379,973),9600=>array(-10,260,612,770),9601=>array(-10,-250,612,-123),9602=>array(-10,-250,612,5),9603=>array(-10,-250,612,132),9604=>array(-10,-250,612,260),9605=>array(-10,-250,612,387),9606=>array(-10,-250,612,515),9607=>array(-10,-250,612,642),9608=>array(-10,-250,612,770),9609=>array(-10,-250,534,770),9610=>array(-10,-250,457,770),9611=>array(-10,-250,379,770),9612=>array(-10,-250,301,770),9613=>array(-10,-250,223,770),9614=>array(-10,-250,146,770),9615=>array(-10,-250,68,770),9616=>array(301,-250,612,770),9617=>array(-10,-250,534,770),9618=>array(-10,-250,612,770),9619=>array(-10,-250,612,770),9620=>array(-10,642,612,770),9621=>array(534,-250,611,770),9622=>array(-10,-250,301,260),9623=>array(301,-250,612,260),9624=>array(-10,260,301,770),9625=>array(-10,-250,612,770),9626=>array(-10,-250,612,770),9627=>array(-10,-250,612,770),9628=>array(-10,-250,612,770),9629=>array(301,260,612,770),9630=>array(-10,-250,612,770),9631=>array(-10,-250,612,770),9632=>array(3,-39,599,558),9633=>array(3,-39,599,558),9634=>array(3,-39,599,558),9635=>array(3,-39,599,558),9636=>array(3,-39,599,558),9637=>array(3,-39,599,558),9638=>array(3,-39,599,558),9639=>array(3,-39,599,558),9640=>array(3,-39,599,558),9641=>array(3,-39,599,558),9642=>array(107,66,495,454),9643=>array(107,66,495,454),9644=>array(3,117,599,402),9645=>array(3,117,599,402),9646=>array(158,-39,444,558),9647=>array(158,-39,444,558),9648=>array(3,117,599,402),9649=>array(3,117,599,402),9650=>array(3,-39,599,558),9651=>array(3,-39,599,558),9652=>array(107,66,495,454),9653=>array(107,66,495,454),9654=>array(3,-39,599,558),9655=>array(3,-39,599,558),9656=>array(107,66,495,454),9657=>array(107,66,495,454),9658=>array(3,66,599,454),9659=>array(3,66,599,454),9660=>array(3,-39,599,558),9661=>array(3,-39,599,558),9662=>array(107,66,495,454),9663=>array(107,66,495,454),9664=>array(3,-39,599,558),9665=>array(3,-39,599,558),9666=>array(107,66,495,454),9667=>array(107,66,495,454),9668=>array(3,66,599,454),9669=>array(3,66,599,454),9670=>array(3,-39,599,558),9671=>array(3,-39,599,558),9672=>array(3,-38,599,558),9673=>array(3,-41,599,561),9674=>array(57,-233,545,807),9675=>array(3,-41,599,561),9676=>array(3,-41,599,561),9677=>array(3,-41,599,561),9678=>array(3,-41,599,561),9679=>array(3,-41,599,561),9680=>array(3,-41,599,561),9681=>array(3,-41,599,561),9682=>array(3,-41,599,561),9683=>array(3,-41,599,561),9684=>array(3,-41,599,561),9685=>array(3,-41,599,561),9686=>array(152,-41,450,561),9687=>array(152,-41,450,561),9688=>array(-10,-10,612,770),9689=>array(-10,-250,612,770),9690=>array(-10,260,612,770),9691=>array(-10,-250,612,260),9692=>array(152,260,450,561),9693=>array(152,260,450,561),9694=>array(152,-41,450,260),9695=>array(152,-41,450,260),9696=>array(3,260,599,561),9697=>array(3,-41,599,260),9698=>array(3,-39,599,558),9699=>array(3,-39,599,558),9700=>array(3,-39,599,558),9701=>array(3,-39,599,558),9702=>array(156,227,446,516),9703=>array(3,-39,599,558),9704=>array(3,-39,599,558),9705=>array(3,-39,599,558),9706=>array(3,-39,599,558),9707=>array(3,-39,599,558),9708=>array(3,-39,599,558),9709=>array(3,-39,599,558),9710=>array(3,-39,599,558),9711=>array(-10,-54,612,573),9712=>array(3,-39,599,558),9713=>array(3,-39,599,558),9714=>array(3,-39,599,558),9715=>array(3,-39,599,558),9716=>array(3,-41,599,561),9717=>array(3,-41,599,561),9718=>array(3,-41,599,561),9719=>array(3,-41,599,561),9720=>array(3,-39,599,558),9721=>array(3,-39,599,558),9722=>array(3,-39,599,558),9723=>array(47,6,554,513),9724=>array(47,6,554,513),9725=>array(85,44,516,475),9726=>array(85,44,516,475),9727=>array(3,-39,599,558),9728=>array(17,80,585,649),9784=>array(13,82,589,642),9785=>array(16,80,586,650),9786=>array(16,80,586,650),9787=>array(16,80,586,650),9788=>array(16,80,586,650),9791=>array(92,-78,510,708),9792=>array(71,-49,531,655),9793=>array(71,-49,531,655),9794=>array(10,75,592,648),9795=>array(35,21,567,710),9796=>array(85,21,517,710),9797=>array(33,65,569,666),9798=>array(37,65,565,666),9799=>array(105,21,497,710),9824=>array(63,65,540,664),9825=>array(7,65,595,663),9826=>array(71,65,531,664),9827=>array(24,65,578,664),9828=>array(62,65,540,664),9829=>array(5,65,597,664),9830=>array(71,65,531,664),9831=>array(24,65,578,667),9833=>array(181,16,421,708),9834=>array(79,16,523,708),9835=>array(52,-79,550,706),9836=>array(8,61,594,664),9837=>array(158,18,444,710),9838=>array(211,21,391,710),9839=>array(152,21,450,710),10178=>array(43,0,559,627),10181=>array(103,-163,472,769),10182=>array(62,-163,508,769),10208=>array(57,-233,545,807),10214=>array(59,-132,544,760),10215=>array(58,-132,543,760),10216=>array(190,-132,498,759),10217=>array(104,-132,412,759),10731=>array(57,-233,545,807),10746=>array(43,55,559,572),10747=>array(43,55,559,572),10799=>array(73,85,529,541),10858=>array(43,243,559,564),10859=>array(43,65,559,564),11013=>array(41,190,561,494),11014=>array(149,82,453,602),11015=>array(149,82,453,602),11016=>array(68,109,485,526),11017=>array(117,109,534,526),11018=>array(117,109,534,526),11019=>array(68,109,485,526),11020=>array(41,190,561,494),11021=>array(149,82,453,602),11026=>array(3,-39,599,558),11027=>array(3,-39,599,558),11028=>array(3,-39,599,558),11029=>array(3,-39,599,558),11030=>array(3,-39,599,558),11031=>array(3,-39,599,558),11032=>array(3,-39,599,558),11033=>array(3,-39,599,558),11034=>array(3,-39,599,558),11364=>array(-4,-213,563,729),11373=>array(37,-14,611,742),11374=>array(-29,-208,630,729),11375=>array(89,0,655,729),11376=>array(-19,-14,555,742),11381=>array(-4,0,548,729),11382=>array(42,0,522,547),11383=>array(38,-12,566,551),11385=>array(6,-13,502,760),11386=>array(67,-14,535,560),11388=>array(185,-125,417,418),11389=>array(168,326,513,734),11390=>array(12,-242,560,742),11391=>array(-3,-242,622,729),11800=>array(73,-13,457,729),11807=>array(43,65,559,384),11810=>array(216,314,510,760),11811=>array(232,314,453,760),11812=>array(129,-132,350,314),11813=>array(72,-132,366,314),11822=>array(145,0,557,742),42760=>array(199,0,521,668),42761=>array(169,0,521,668),42762=>array(140,0,521,668),42763=>array(111,0,521,668),42764=>array(82,0,521,668),42765=>array(82,0,521,668),42766=>array(82,0,491,668),42767=>array(82,0,462,668),42768=>array(82,0,433,668),42769=>array(82,0,403,668),42770=>array(82,0,521,668),42771=>array(82,0,491,668),42772=>array(82,0,462,668),42773=>array(82,0,433,668),42774=>array(82,0,403,668),42779=>array(185,326,455,736),42780=>array(147,324,417,734),42781=>array(230,326,372,734),42782=>array(230,326,372,734),42783=>array(167,0,308,408),42786=>array(120,0,488,729),42787=>array(150,0,466,547),42788=>array(113,224,544,742),42789=>array(113,42,544,560),42790=>array(-4,-208,606,729),42791=>array(41,-208,535,760),42889=>array(168,0,392,518),42890=>array(169,161,433,380),42891=>array(237,235,422,729),42892=>array(231,458,369,729),42893=>array(82,0,604,729),42894=>array(80,-208,455,765),42896=>array(-5,-157,603,729),42897=>array(20,-140,521,560),42922=>array(41,0,704,729),63173=>array(47,-14,576,760),64257=>array(48,0,613,760),64258=>array(48,0,613,760),65533=>array(-16,-84,601,887),65535=>array(51,-177,551,705)); -$cw=array(0=>602,32=>602,33=>602,34=>602,35=>602,36=>602,37=>602,38=>602,39=>602,40=>602,41=>602,42=>602,43=>602,44=>602,45=>602,46=>602,47=>602,48=>602,49=>602,50=>602,51=>602,52=>602,53=>602,54=>602,55=>602,56=>602,57=>602,58=>602,59=>602,60=>602,61=>602,62=>602,63=>602,64=>602,65=>602,66=>602,67=>602,68=>602,69=>602,70=>602,71=>602,72=>602,73=>602,74=>602,75=>602,76=>602,77=>602,78=>602,79=>602,80=>602,81=>602,82=>602,83=>602,84=>602,85=>602,86=>602,87=>602,88=>602,89=>602,90=>602,91=>602,92=>602,93=>602,94=>602,95=>602,96=>602,97=>602,98=>602,99=>602,100=>602,101=>602,102=>602,103=>602,104=>602,105=>602,106=>602,107=>602,108=>602,109=>602,110=>602,111=>602,112=>602,113=>602,114=>602,115=>602,116=>602,117=>602,118=>602,119=>602,120=>602,121=>602,122=>602,123=>602,124=>602,125=>602,126=>602,160=>602,161=>602,162=>602,163=>602,164=>602,165=>602,166=>602,167=>602,168=>602,169=>602,170=>602,171=>602,172=>602,173=>602,174=>602,175=>602,176=>602,177=>602,178=>602,179=>602,180=>602,181=>602,182=>602,183=>602,184=>602,185=>602,186=>602,187=>602,188=>602,189=>602,190=>602,191=>602,192=>602,193=>602,194=>602,195=>602,196=>602,197=>602,198=>602,199=>602,200=>602,201=>602,202=>602,203=>602,204=>602,205=>602,206=>602,207=>602,208=>602,209=>602,210=>602,211=>602,212=>602,213=>602,214=>602,215=>602,216=>602,217=>602,218=>602,219=>602,220=>602,221=>602,222=>602,223=>602,224=>602,225=>602,226=>602,227=>602,228=>602,229=>602,230=>602,231=>602,232=>602,233=>602,234=>602,235=>602,236=>602,237=>602,238=>602,239=>602,240=>602,241=>602,242=>602,243=>602,244=>602,245=>602,246=>602,247=>602,248=>602,249=>602,250=>602,251=>602,252=>602,253=>602,254=>602,255=>602,256=>602,257=>602,258=>602,259=>602,260=>602,261=>602,262=>602,263=>602,264=>602,265=>602,266=>602,267=>602,268=>602,269=>602,270=>602,271=>602,272=>602,273=>602,274=>602,275=>602,276=>602,277=>602,278=>602,279=>602,280=>602,281=>602,282=>602,283=>602,284=>602,285=>602,286=>602,287=>602,288=>602,289=>602,290=>602,291=>602,292=>602,293=>602,294=>602,295=>602,296=>602,297=>602,298=>602,299=>602,300=>602,301=>602,302=>602,303=>602,304=>602,305=>602,306=>602,307=>602,308=>602,309=>602,310=>602,311=>602,312=>602,313=>602,314=>602,315=>602,316=>602,317=>602,318=>602,319=>602,320=>602,321=>602,322=>602,323=>602,324=>602,325=>602,326=>602,327=>602,328=>602,329=>602,330=>602,331=>602,332=>602,333=>602,334=>602,335=>602,336=>602,337=>602,338=>602,339=>602,340=>602,341=>602,342=>602,343=>602,344=>602,345=>602,346=>602,347=>602,348=>602,349=>602,350=>602,351=>602,352=>602,353=>602,354=>602,355=>602,356=>602,357=>602,358=>602,359=>602,360=>602,361=>602,362=>602,363=>602,364=>602,365=>602,366=>602,367=>602,368=>602,369=>602,370=>602,371=>602,372=>602,373=>602,374=>602,375=>602,376=>602,377=>602,378=>602,379=>602,380=>602,381=>602,382=>602,383=>602,384=>602,385=>602,386=>602,387=>602,388=>602,389=>602,390=>602,391=>602,392=>602,393=>602,394=>602,395=>602,396=>602,397=>602,398=>602,399=>602,400=>602,401=>602,402=>602,403=>602,404=>602,405=>602,406=>602,407=>602,408=>602,409=>602,410=>602,411=>602,412=>602,413=>602,414=>602,415=>602,416=>602,417=>602,418=>602,419=>602,420=>602,421=>602,422=>602,423=>602,424=>602,425=>602,426=>602,427=>602,428=>602,429=>602,430=>602,431=>602,432=>602,433=>602,434=>602,435=>602,436=>602,437=>602,438=>602,439=>602,440=>602,441=>602,442=>602,443=>602,444=>602,445=>602,446=>602,447=>602,448=>602,449=>602,450=>602,451=>602,461=>602,462=>602,463=>602,464=>602,465=>602,466=>602,467=>602,468=>602,469=>602,470=>602,471=>602,472=>602,473=>602,474=>602,475=>602,476=>602,477=>602,479=>602,480=>602,481=>602,482=>602,483=>602,486=>602,487=>602,488=>602,489=>602,490=>602,491=>602,492=>602,493=>602,494=>602,495=>602,500=>602,501=>602,502=>602,504=>602,505=>602,508=>602,509=>602,510=>602,511=>602,512=>602,513=>602,514=>602,515=>602,516=>602,517=>602,518=>602,519=>602,520=>602,521=>602,522=>602,523=>602,524=>602,525=>602,526=>602,527=>602,528=>602,529=>602,530=>602,531=>602,532=>602,533=>602,534=>602,535=>602,536=>602,537=>602,538=>602,539=>602,540=>602,541=>602,542=>602,543=>602,545=>602,548=>602,549=>602,550=>602,551=>602,552=>602,553=>602,554=>602,555=>602,556=>602,557=>602,558=>602,559=>602,560=>602,561=>602,562=>602,563=>602,564=>602,565=>602,566=>602,567=>602,568=>602,569=>602,570=>602,571=>602,572=>602,573=>602,574=>602,575=>602,576=>602,577=>602,579=>602,580=>602,581=>602,588=>602,589=>602,592=>602,593=>602,594=>602,595=>602,596=>602,597=>602,598=>602,599=>602,600=>602,601=>602,602=>602,603=>602,604=>602,605=>602,606=>602,607=>602,608=>602,609=>602,610=>602,611=>602,612=>602,613=>602,614=>602,615=>602,616=>602,617=>602,618=>602,619=>602,620=>602,621=>602,622=>602,623=>602,624=>602,625=>602,626=>602,627=>602,628=>602,629=>602,630=>602,631=>602,632=>602,633=>602,634=>602,635=>602,636=>602,637=>602,638=>602,639=>602,640=>602,641=>602,642=>602,643=>602,644=>602,645=>602,646=>602,647=>602,648=>602,649=>602,650=>602,651=>602,652=>602,653=>602,654=>602,655=>602,656=>602,657=>602,658=>602,659=>602,660=>602,661=>602,662=>602,663=>602,664=>602,665=>602,666=>602,667=>602,668=>602,669=>602,670=>602,671=>602,672=>602,673=>602,674=>602,675=>602,676=>602,677=>602,678=>602,679=>602,680=>602,681=>602,682=>602,683=>602,684=>602,685=>602,686=>602,687=>602,688=>602,689=>602,690=>602,691=>602,692=>602,693=>602,694=>602,695=>602,696=>602,697=>602,699=>602,700=>602,701=>602,702=>602,703=>602,704=>602,705=>602,710=>602,711=>602,712=>602,713=>602,716=>602,717=>602,718=>602,719=>602,720=>602,721=>602,722=>602,723=>602,726=>602,727=>602,728=>602,729=>602,730=>602,731=>602,732=>602,733=>602,734=>602,736=>602,737=>602,738=>602,739=>602,740=>602,741=>602,742=>602,743=>602,744=>602,745=>602,750=>602,755=>602,768=>602,769=>602,770=>602,771=>602,772=>602,773=>602,774=>602,775=>602,776=>602,777=>602,778=>602,779=>602,780=>602,781=>602,782=>602,783=>602,784=>602,785=>602,786=>602,787=>602,788=>602,789=>602,790=>602,791=>602,792=>602,793=>602,794=>602,795=>602,796=>602,797=>602,798=>602,799=>602,800=>602,801=>602,802=>602,803=>602,804=>602,805=>602,806=>602,807=>602,808=>602,809=>602,810=>602,811=>602,812=>602,813=>602,814=>602,815=>602,816=>602,817=>602,818=>602,819=>602,820=>602,821=>602,822=>602,823=>602,824=>602,825=>602,826=>602,827=>602,828=>602,829=>602,830=>602,831=>602,835=>602,856=>602,865=>602,884=>602,885=>602,890=>602,894=>602,900=>602,901=>602,902=>602,903=>602,904=>602,905=>602,906=>602,908=>602,910=>602,911=>602,912=>602,913=>602,914=>602,915=>602,916=>602,917=>602,918=>602,919=>602,920=>602,921=>602,922=>602,923=>602,924=>602,925=>602,926=>602,927=>602,928=>602,929=>602,931=>602,932=>602,933=>602,934=>602,935=>602,936=>602,937=>602,938=>602,939=>602,940=>602,941=>602,942=>602,943=>602,944=>602,945=>602,946=>602,947=>602,948=>602,949=>602,950=>602,951=>602,952=>602,953=>602,954=>602,955=>602,956=>602,957=>602,958=>602,959=>602,960=>602,961=>602,962=>602,963=>602,964=>602,965=>602,966=>602,967=>602,968=>602,969=>602,970=>602,971=>602,972=>602,973=>602,974=>602,976=>602,977=>602,978=>602,979=>602,980=>602,981=>602,982=>602,983=>602,984=>602,985=>602,986=>602,987=>602,988=>602,989=>602,990=>602,991=>602,992=>602,993=>602,1008=>602,1009=>602,1010=>602,1011=>602,1012=>602,1013=>602,1014=>602,1015=>602,1016=>602,1017=>602,1018=>602,1019=>602,1020=>602,1021=>602,1022=>602,1023=>602,1024=>602,1025=>602,1026=>602,1027=>602,1028=>602,1029=>602,1030=>602,1031=>602,1032=>602,1033=>602,1034=>602,1035=>602,1036=>602,1037=>602,1038=>602,1039=>602,1040=>602,1041=>602,1042=>602,1043=>602,1044=>602,1045=>602,1046=>602,1047=>602,1048=>602,1049=>602,1050=>602,1051=>602,1052=>602,1053=>602,1054=>602,1055=>602,1056=>602,1057=>602,1058=>602,1059=>602,1060=>602,1061=>602,1062=>602,1063=>602,1064=>602,1065=>602,1066=>602,1067=>602,1068=>602,1069=>602,1070=>602,1071=>602,1072=>602,1073=>602,1074=>602,1075=>602,1076=>602,1077=>602,1078=>602,1079=>602,1080=>602,1081=>602,1082=>602,1083=>602,1084=>602,1085=>602,1086=>602,1087=>602,1088=>602,1089=>602,1090=>602,1091=>602,1092=>602,1093=>602,1094=>602,1095=>602,1096=>602,1097=>602,1098=>602,1099=>602,1100=>602,1101=>602,1102=>602,1103=>602,1104=>602,1105=>602,1106=>602,1107=>602,1108=>602,1109=>602,1110=>602,1111=>602,1112=>602,1113=>602,1114=>602,1115=>602,1116=>602,1117=>602,1118=>602,1119=>602,1122=>602,1123=>602,1138=>602,1139=>602,1168=>602,1169=>602,1170=>602,1171=>602,1172=>602,1173=>602,1174=>602,1175=>602,1176=>602,1177=>602,1178=>602,1179=>602,1186=>602,1187=>602,1188=>602,1189=>602,1194=>602,1195=>602,1196=>602,1197=>602,1198=>602,1199=>602,1200=>602,1201=>602,1202=>602,1203=>602,1210=>602,1211=>602,1216=>602,1217=>602,1218=>602,1219=>602,1220=>602,1223=>602,1224=>602,1227=>602,1228=>602,1231=>602,1232=>602,1233=>602,1234=>602,1235=>602,1236=>602,1237=>602,1238=>602,1239=>602,1240=>602,1241=>602,1242=>602,1243=>602,1244=>602,1245=>602,1246=>602,1247=>602,1248=>602,1249=>602,1250=>602,1251=>602,1252=>602,1253=>602,1254=>602,1255=>602,1256=>602,1257=>602,1258=>602,1259=>602,1260=>602,1261=>602,1262=>602,1263=>602,1264=>602,1265=>602,1266=>602,1267=>602,1268=>602,1269=>602,1270=>602,1271=>602,1272=>602,1273=>602,1296=>602,1297=>602,1306=>602,1307=>602,1308=>602,1309=>602,1329=>602,1330=>602,1331=>602,1332=>602,1333=>602,1334=>602,1335=>602,1336=>602,1337=>602,1338=>602,1339=>602,1340=>602,1341=>602,1342=>602,1343=>602,1344=>602,1345=>602,1346=>602,1347=>602,1348=>602,1349=>602,1350=>602,1351=>602,1352=>602,1353=>602,1354=>602,1355=>602,1356=>602,1357=>602,1358=>602,1359=>602,1360=>602,1361=>602,1362=>602,1363=>602,1364=>602,1365=>602,1366=>602,1369=>602,1370=>602,1371=>602,1372=>602,1373=>602,1374=>602,1375=>602,1377=>602,1378=>602,1379=>602,1380=>602,1381=>602,1382=>602,1383=>602,1384=>602,1385=>602,1386=>602,1387=>602,1388=>602,1389=>602,1390=>602,1391=>602,1392=>602,1393=>602,1394=>602,1395=>602,1396=>602,1397=>602,1398=>602,1399=>602,1400=>602,1401=>602,1402=>602,1403=>602,1404=>602,1405=>602,1406=>602,1407=>602,1408=>602,1409=>602,1410=>602,1411=>602,1412=>602,1413=>602,1414=>602,1415=>602,1417=>602,1418=>602,3713=>602,3714=>602,3716=>602,3719=>602,3720=>602,3722=>602,3725=>602,3732=>602,3733=>602,3734=>602,3735=>602,3737=>602,3738=>602,3739=>602,3740=>602,3741=>602,3742=>602,3743=>602,3745=>602,3746=>602,3747=>602,3749=>602,3751=>602,3754=>602,3755=>602,3757=>602,3758=>602,3759=>602,3760=>602,3761=>602,3762=>602,3763=>602,3764=>602,3765=>602,3766=>602,3767=>602,3768=>602,3769=>602,3771=>602,3772=>602,3784=>602,3785=>602,3786=>602,3787=>602,3788=>602,3789=>602,4304=>602,4305=>602,4306=>602,4307=>602,4308=>602,4309=>602,4310=>602,4311=>602,4312=>602,4313=>602,4314=>602,4315=>602,4316=>602,4317=>602,4318=>602,4319=>602,4320=>602,4321=>602,4322=>602,4323=>602,4324=>602,4325=>602,4326=>602,4327=>602,4328=>602,4329=>602,4330=>602,4331=>602,4332=>602,4333=>602,4334=>602,4335=>602,4336=>602,4337=>602,4338=>602,4339=>602,4340=>602,4341=>602,4342=>602,4343=>602,4344=>602,4345=>602,4346=>602,4347=>602,4348=>602,7426=>602,7432=>602,7433=>602,7444=>602,7446=>602,7447=>602,7453=>602,7454=>602,7455=>602,7468=>602,7469=>602,7470=>602,7472=>602,7473=>602,7474=>602,7475=>602,7476=>602,7477=>602,7478=>602,7479=>602,7480=>602,7481=>602,7482=>602,7483=>602,7484=>602,7485=>602,7486=>602,7487=>602,7488=>602,7489=>602,7490=>602,7491=>602,7492=>602,7493=>602,7494=>602,7495=>602,7496=>602,7497=>602,7498=>602,7499=>602,7500=>602,7501=>602,7502=>602,7503=>602,7504=>602,7505=>602,7506=>602,7507=>602,7508=>602,7509=>602,7510=>602,7511=>602,7512=>602,7513=>602,7514=>602,7515=>602,7522=>602,7523=>602,7524=>602,7525=>602,7543=>602,7544=>602,7547=>602,7557=>602,7579=>602,7580=>602,7581=>602,7582=>602,7583=>602,7584=>602,7585=>602,7586=>602,7587=>602,7588=>602,7589=>602,7590=>602,7591=>602,7592=>602,7593=>602,7594=>602,7595=>602,7596=>602,7597=>602,7598=>602,7599=>602,7600=>602,7601=>602,7602=>602,7603=>602,7604=>602,7605=>602,7606=>602,7607=>602,7609=>602,7610=>602,7611=>602,7612=>602,7613=>602,7614=>602,7615=>602,7680=>602,7681=>602,7682=>602,7683=>602,7684=>602,7685=>602,7686=>602,7687=>602,7688=>602,7689=>602,7690=>602,7691=>602,7692=>602,7693=>602,7694=>602,7695=>602,7696=>602,7697=>602,7698=>602,7699=>602,7704=>602,7705=>602,7706=>602,7707=>602,7708=>602,7709=>602,7710=>602,7711=>602,7712=>602,7713=>602,7714=>602,7715=>602,7716=>602,7717=>602,7718=>602,7719=>602,7720=>602,7721=>602,7722=>602,7723=>602,7724=>602,7725=>602,7728=>602,7729=>602,7730=>602,7731=>602,7732=>602,7733=>602,7734=>602,7735=>602,7736=>602,7737=>602,7738=>602,7739=>602,7740=>602,7741=>602,7742=>602,7743=>602,7744=>602,7745=>602,7746=>602,7747=>602,7748=>602,7749=>602,7750=>602,7751=>602,7752=>602,7753=>602,7754=>602,7755=>602,7756=>602,7757=>602,7764=>602,7765=>602,7766=>602,7767=>602,7768=>602,7769=>602,7770=>602,7771=>602,7772=>602,7773=>602,7774=>602,7775=>602,7776=>602,7777=>602,7778=>602,7779=>602,7784=>602,7785=>602,7786=>602,7787=>602,7788=>602,7789=>602,7790=>602,7791=>602,7792=>602,7793=>602,7794=>602,7795=>602,7796=>602,7797=>602,7798=>602,7799=>602,7800=>602,7801=>602,7804=>602,7805=>602,7806=>602,7807=>602,7808=>602,7809=>602,7810=>602,7811=>602,7812=>602,7813=>602,7814=>602,7815=>602,7816=>602,7817=>602,7818=>602,7819=>602,7820=>602,7821=>602,7822=>602,7823=>602,7824=>602,7825=>602,7826=>602,7827=>602,7828=>602,7829=>602,7830=>602,7831=>602,7832=>602,7833=>602,7835=>602,7839=>602,7840=>602,7841=>602,7852=>602,7853=>602,7856=>602,7857=>602,7862=>602,7863=>602,7864=>602,7865=>602,7868=>602,7869=>602,7878=>602,7879=>602,7882=>602,7883=>602,7884=>602,7885=>602,7896=>602,7897=>602,7898=>602,7899=>602,7900=>602,7901=>602,7904=>602,7905=>602,7906=>602,7907=>602,7908=>602,7909=>602,7912=>602,7913=>602,7914=>602,7915=>602,7918=>602,7919=>602,7920=>602,7921=>602,7922=>602,7923=>602,7924=>602,7925=>602,7928=>602,7929=>602,7936=>602,7937=>602,7938=>602,7939=>602,7940=>602,7941=>602,7942=>602,7943=>602,7944=>602,7945=>602,7946=>602,7947=>602,7948=>602,7949=>602,7950=>602,7951=>602,7952=>602,7953=>602,7954=>602,7955=>602,7956=>602,7957=>602,7960=>602,7961=>602,7962=>602,7963=>602,7964=>602,7965=>602,7968=>602,7969=>602,7970=>602,7971=>602,7972=>602,7973=>602,7974=>602,7975=>602,7976=>602,7977=>602,7978=>602,7979=>602,7980=>602,7981=>602,7982=>602,7983=>602,7984=>602,7985=>602,7986=>602,7987=>602,7988=>602,7989=>602,7990=>602,7991=>602,7992=>602,7993=>602,7994=>602,7995=>602,7996=>602,7997=>602,7998=>602,7999=>602,8000=>602,8001=>602,8002=>602,8003=>602,8004=>602,8005=>602,8008=>602,8009=>602,8010=>602,8011=>602,8012=>602,8013=>602,8016=>602,8017=>602,8018=>602,8019=>602,8020=>602,8021=>602,8022=>602,8023=>602,8025=>602,8027=>602,8029=>602,8031=>602,8032=>602,8033=>602,8034=>602,8035=>602,8036=>602,8037=>602,8038=>602,8039=>602,8040=>602,8041=>602,8042=>602,8043=>602,8044=>602,8045=>602,8046=>602,8047=>602,8048=>602,8049=>602,8050=>602,8051=>602,8052=>602,8053=>602,8054=>602,8055=>602,8056=>602,8057=>602,8058=>602,8059=>602,8060=>602,8061=>602,8064=>602,8065=>602,8066=>602,8067=>602,8068=>602,8069=>602,8070=>602,8071=>602,8072=>602,8073=>602,8074=>602,8075=>602,8076=>602,8077=>602,8078=>602,8079=>602,8080=>602,8081=>602,8082=>602,8083=>602,8084=>602,8085=>602,8086=>602,8087=>602,8088=>602,8089=>602,8090=>602,8091=>602,8092=>602,8093=>602,8094=>602,8095=>602,8096=>602,8097=>602,8098=>602,8099=>602,8100=>602,8101=>602,8102=>602,8103=>602,8104=>602,8105=>602,8106=>602,8107=>602,8108=>602,8109=>602,8110=>602,8111=>602,8112=>602,8113=>602,8114=>602,8115=>602,8116=>602,8118=>602,8119=>602,8120=>602,8121=>602,8122=>602,8123=>602,8124=>602,8125=>602,8126=>602,8127=>602,8128=>602,8129=>602,8130=>602,8131=>602,8132=>602,8134=>602,8135=>602,8136=>602,8137=>602,8138=>602,8139=>602,8140=>602,8141=>602,8142=>602,8143=>602,8144=>602,8145=>602,8146=>602,8147=>602,8150=>602,8151=>602,8152=>602,8153=>602,8154=>602,8155=>602,8157=>602,8158=>602,8159=>602,8160=>602,8161=>602,8162=>602,8163=>602,8164=>602,8165=>602,8166=>602,8167=>602,8168=>602,8169=>602,8170=>602,8171=>602,8172=>602,8173=>602,8174=>602,8175=>602,8178=>602,8179=>602,8180=>602,8182=>602,8183=>602,8184=>602,8185=>602,8186=>602,8187=>602,8188=>602,8189=>602,8190=>602,8192=>602,8193=>602,8194=>602,8195=>602,8196=>602,8197=>602,8198=>602,8199=>602,8200=>602,8201=>602,8202=>602,8208=>602,8209=>602,8210=>602,8211=>602,8212=>602,8213=>602,8214=>602,8215=>602,8216=>602,8217=>602,8218=>602,8219=>602,8220=>602,8221=>602,8222=>602,8223=>602,8224=>602,8225=>602,8226=>602,8227=>602,8230=>602,8239=>602,8240=>602,8241=>602,8242=>602,8243=>602,8244=>602,8245=>602,8246=>602,8247=>602,8249=>602,8250=>602,8252=>602,8253=>602,8254=>602,8261=>602,8262=>602,8263=>602,8264=>602,8265=>602,8267=>602,8287=>602,8304=>602,8305=>602,8308=>602,8309=>602,8310=>602,8311=>602,8312=>602,8313=>602,8314=>602,8315=>602,8316=>602,8317=>602,8318=>602,8319=>602,8320=>602,8321=>602,8322=>602,8323=>602,8324=>602,8325=>602,8326=>602,8327=>602,8328=>602,8329=>602,8330=>602,8331=>602,8332=>602,8333=>602,8334=>602,8336=>602,8337=>602,8338=>602,8339=>602,8340=>602,8341=>602,8342=>602,8343=>602,8344=>602,8345=>602,8346=>602,8347=>602,8348=>602,8352=>602,8353=>602,8354=>602,8355=>602,8356=>602,8357=>602,8358=>602,8359=>602,8360=>602,8361=>602,8362=>602,8363=>602,8364=>602,8365=>602,8366=>602,8367=>602,8368=>602,8369=>602,8370=>602,8371=>602,8372=>602,8373=>602,8376=>602,8377=>602,8450=>602,8453=>602,8461=>602,8462=>602,8463=>602,8469=>602,8470=>602,8471=>602,8473=>602,8474=>602,8477=>602,8482=>602,8484=>602,8486=>602,8490=>602,8491=>602,8494=>602,8520=>602,8531=>602,8532=>602,8533=>602,8534=>602,8535=>602,8536=>602,8537=>602,8538=>602,8539=>602,8540=>602,8541=>602,8542=>602,8543=>602,8592=>602,8593=>602,8594=>602,8595=>602,8596=>602,8597=>602,8598=>602,8599=>602,8600=>602,8601=>602,8602=>602,8603=>602,8604=>602,8605=>602,8606=>602,8607=>602,8608=>602,8609=>602,8610=>602,8611=>602,8612=>602,8613=>602,8614=>602,8615=>602,8616=>602,8617=>602,8618=>602,8619=>602,8620=>602,8621=>602,8622=>602,8623=>602,8624=>602,8625=>602,8626=>602,8627=>602,8628=>602,8629=>602,8630=>602,8631=>602,8632=>602,8633=>602,8634=>602,8635=>602,8636=>602,8637=>602,8638=>602,8639=>602,8640=>602,8641=>602,8642=>602,8643=>602,8644=>602,8645=>602,8646=>602,8647=>602,8648=>602,8649=>602,8650=>602,8651=>602,8652=>602,8653=>602,8654=>602,8655=>602,8656=>602,8657=>602,8658=>602,8659=>602,8660=>602,8661=>602,8662=>602,8663=>602,8664=>602,8665=>602,8666=>602,8667=>602,8668=>602,8669=>602,8670=>602,8671=>602,8672=>602,8673=>602,8674=>602,8675=>602,8676=>602,8677=>602,8678=>602,8679=>602,8680=>602,8681=>602,8682=>602,8683=>602,8684=>602,8685=>602,8686=>602,8687=>602,8688=>602,8689=>602,8690=>602,8691=>602,8692=>602,8693=>602,8694=>602,8695=>602,8696=>602,8697=>602,8698=>602,8699=>602,8700=>602,8701=>602,8702=>602,8703=>602,8704=>602,8705=>602,8706=>602,8707=>602,8708=>602,8709=>602,8710=>602,8711=>602,8712=>602,8713=>602,8714=>602,8715=>602,8716=>602,8717=>602,8719=>602,8721=>602,8722=>602,8723=>602,8725=>602,8727=>602,8728=>602,8729=>602,8730=>602,8731=>602,8732=>602,8733=>602,8734=>602,8735=>602,8736=>602,8743=>602,8744=>602,8745=>602,8746=>602,8747=>602,8748=>602,8749=>602,8756=>602,8757=>602,8758=>602,8759=>602,8760=>602,8761=>602,8762=>602,8763=>602,8764=>602,8765=>602,8769=>602,8770=>602,8771=>602,8772=>602,8773=>602,8774=>602,8775=>602,8776=>602,8777=>602,8778=>602,8779=>602,8780=>602,8781=>602,8782=>602,8783=>602,8784=>602,8785=>602,8786=>602,8787=>602,8788=>602,8789=>602,8790=>602,8791=>602,8792=>602,8793=>602,8794=>602,8795=>602,8796=>602,8797=>602,8798=>602,8799=>602,8800=>602,8801=>602,8802=>602,8803=>602,8804=>602,8805=>602,8806=>602,8807=>602,8808=>602,8809=>602,8813=>602,8814=>602,8815=>602,8816=>602,8817=>602,8818=>602,8819=>602,8820=>602,8821=>602,8822=>602,8823=>602,8824=>602,8825=>602,8826=>602,8827=>602,8828=>602,8829=>602,8830=>602,8831=>602,8832=>602,8833=>602,8834=>602,8835=>602,8836=>602,8837=>602,8838=>602,8839=>602,8840=>602,8841=>602,8842=>602,8843=>602,8847=>602,8848=>602,8849=>602,8850=>602,8853=>602,8854=>602,8855=>602,8856=>602,8857=>602,8858=>602,8859=>602,8860=>602,8861=>602,8862=>602,8863=>602,8864=>602,8865=>602,8866=>602,8867=>602,8868=>602,8869=>602,8901=>602,8902=>602,8909=>602,8922=>602,8923=>602,8924=>602,8925=>602,8926=>602,8927=>602,8928=>602,8929=>602,8930=>602,8931=>602,8932=>602,8933=>602,8934=>602,8935=>602,8936=>602,8937=>602,8943=>602,8960=>602,8961=>602,8962=>602,8963=>602,8964=>602,8965=>602,8966=>602,8968=>602,8969=>602,8970=>602,8971=>602,8972=>602,8973=>602,8974=>602,8975=>602,8976=>602,8977=>602,8978=>602,8979=>602,8980=>602,8981=>602,8984=>602,8985=>602,8988=>602,8989=>602,8990=>602,8991=>602,8992=>602,8993=>602,8997=>602,8998=>602,8999=>602,9000=>602,9003=>602,9013=>602,9015=>602,9016=>602,9017=>602,9018=>602,9019=>602,9020=>602,9021=>602,9022=>602,9025=>602,9026=>602,9027=>602,9028=>602,9031=>602,9032=>602,9033=>602,9035=>602,9036=>602,9037=>602,9040=>602,9042=>602,9043=>602,9044=>602,9047=>602,9048=>602,9049=>602,9050=>602,9051=>602,9052=>602,9054=>602,9055=>602,9056=>602,9059=>602,9060=>602,9061=>602,9064=>602,9065=>602,9067=>602,9068=>602,9069=>602,9070=>602,9071=>602,9072=>602,9075=>602,9076=>602,9077=>602,9078=>602,9079=>602,9080=>602,9081=>602,9082=>602,9085=>602,9088=>602,9089=>602,9090=>602,9091=>602,9096=>602,9097=>602,9098=>602,9099=>602,9109=>602,9115=>602,9116=>602,9117=>602,9118=>602,9119=>602,9120=>602,9121=>602,9122=>602,9123=>602,9124=>602,9125=>602,9126=>602,9127=>602,9128=>602,9129=>602,9130=>602,9131=>602,9132=>602,9133=>602,9134=>602,9166=>602,9167=>602,9251=>602,9472=>602,9473=>602,9474=>602,9475=>602,9476=>602,9477=>602,9478=>602,9479=>602,9480=>602,9481=>602,9482=>602,9483=>602,9484=>602,9485=>602,9486=>602,9487=>602,9488=>602,9489=>602,9490=>602,9491=>602,9492=>602,9493=>602,9494=>602,9495=>602,9496=>602,9497=>602,9498=>602,9499=>602,9500=>602,9501=>602,9502=>602,9503=>602,9504=>602,9505=>602,9506=>602,9507=>602,9508=>602,9509=>602,9510=>602,9511=>602,9512=>602,9513=>602,9514=>602,9515=>602,9516=>602,9517=>602,9518=>602,9519=>602,9520=>602,9521=>602,9522=>602,9523=>602,9524=>602,9525=>602,9526=>602,9527=>602,9528=>602,9529=>602,9530=>602,9531=>602,9532=>602,9533=>602,9534=>602,9535=>602,9536=>602,9537=>602,9538=>602,9539=>602,9540=>602,9541=>602,9542=>602,9543=>602,9544=>602,9545=>602,9546=>602,9547=>602,9548=>602,9549=>602,9550=>602,9551=>602,9552=>602,9553=>602,9554=>602,9555=>602,9556=>602,9557=>602,9558=>602,9559=>602,9560=>602,9561=>602,9562=>602,9563=>602,9564=>602,9565=>602,9566=>602,9567=>602,9568=>602,9569=>602,9570=>602,9571=>602,9572=>602,9573=>602,9574=>602,9575=>602,9576=>602,9577=>602,9578=>602,9579=>602,9580=>602,9581=>602,9582=>602,9583=>602,9584=>602,9585=>602,9586=>602,9587=>602,9588=>602,9589=>602,9590=>602,9591=>602,9592=>602,9593=>602,9594=>602,9595=>602,9596=>602,9597=>602,9598=>602,9599=>602,9600=>602,9601=>602,9602=>602,9603=>602,9604=>602,9605=>602,9606=>602,9607=>602,9608=>602,9609=>602,9610=>602,9611=>602,9612=>602,9613=>602,9614=>602,9615=>602,9616=>602,9617=>602,9618=>602,9619=>602,9620=>602,9621=>602,9622=>602,9623=>602,9624=>602,9625=>602,9626=>602,9627=>602,9628=>602,9629=>602,9630=>602,9631=>602,9632=>602,9633=>602,9634=>602,9635=>602,9636=>602,9637=>602,9638=>602,9639=>602,9640=>602,9641=>602,9642=>602,9643=>602,9644=>602,9645=>602,9646=>602,9647=>602,9648=>602,9649=>602,9650=>602,9651=>602,9652=>602,9653=>602,9654=>602,9655=>602,9656=>602,9657=>602,9658=>602,9659=>602,9660=>602,9661=>602,9662=>602,9663=>602,9664=>602,9665=>602,9666=>602,9667=>602,9668=>602,9669=>602,9670=>602,9671=>602,9672=>602,9673=>602,9674=>602,9675=>602,9676=>602,9677=>602,9678=>602,9679=>602,9680=>602,9681=>602,9682=>602,9683=>602,9684=>602,9685=>602,9686=>602,9687=>602,9688=>602,9689=>602,9690=>602,9691=>602,9692=>602,9693=>602,9694=>602,9695=>602,9696=>602,9697=>602,9698=>602,9699=>602,9700=>602,9701=>602,9702=>602,9703=>602,9704=>602,9705=>602,9706=>602,9707=>602,9708=>602,9709=>602,9710=>602,9711=>602,9712=>602,9713=>602,9714=>602,9715=>602,9716=>602,9717=>602,9718=>602,9719=>602,9720=>602,9721=>602,9722=>602,9723=>602,9724=>602,9725=>602,9726=>602,9727=>602,9728=>602,9784=>602,9785=>602,9786=>602,9787=>602,9788=>602,9791=>602,9792=>602,9793=>602,9794=>602,9795=>602,9796=>602,9797=>602,9798=>602,9799=>602,9824=>602,9825=>602,9826=>602,9827=>602,9828=>602,9829=>602,9830=>602,9831=>602,9833=>602,9834=>602,9835=>602,9836=>602,9837=>602,9838=>602,9839=>602,10178=>602,10181=>602,10182=>602,10208=>602,10214=>602,10215=>602,10216=>602,10217=>602,10731=>602,10746=>602,10747=>602,10799=>602,10858=>602,10859=>602,11013=>602,11014=>602,11015=>602,11016=>602,11017=>602,11018=>602,11019=>602,11020=>602,11021=>602,11026=>602,11027=>602,11028=>602,11029=>602,11030=>602,11031=>602,11032=>602,11033=>602,11034=>602,11364=>602,11373=>602,11374=>602,11375=>602,11376=>602,11381=>602,11382=>602,11383=>602,11385=>602,11386=>602,11388=>602,11389=>602,11390=>602,11391=>602,11800=>602,11807=>602,11810=>602,11811=>602,11812=>602,11813=>602,11822=>602,42760=>602,42761=>602,42762=>602,42763=>602,42764=>602,42765=>602,42766=>602,42767=>602,42768=>602,42769=>602,42770=>602,42771=>602,42772=>602,42773=>602,42774=>602,42779=>602,42780=>602,42781=>602,42782=>602,42783=>602,42786=>602,42787=>602,42788=>602,42789=>602,42790=>602,42791=>602,42889=>602,42890=>602,42891=>602,42892=>602,42893=>602,42894=>602,42896=>602,42897=>602,42922=>602,63173=>602,64257=>602,64258=>602,65529=>602,65530=>602,65531=>602,65532=>602,65533=>602,65535=>602); -// --- EOF --- diff --git a/lib/combodo/tcpdf/fonts/dejavusansmonoi.z b/lib/combodo/tcpdf/fonts/dejavusansmonoi.z deleted file mode 100644 index 14be5c14e57e019eb6d5f7bd2e15c33f969a5a2d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 147290 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 D(9qMo diff --git a/lib/combodo/tcpdf/fonts/droidsansfallback.ctg.z b/lib/combodo/tcpdf/fonts/droidsansfallback.ctg.z deleted file mode 100644 index c57166dbde465937689ada0952437c52c39621d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58024 zcmbrFQ*dNmptj?Dv2EM7lZkC7GchK%?POxxp4hhSWYV#nbbR{MfBj#bs;=s;+N=9w z_1bH{c$VkpWe;>a=2|PWp5gU%=Whfkq|ko@WbH7)F#rAecYXbbbYO=pSU-_e3?j5Z zEVv7nW}T?(ulx1x`<2VJ(95+)ugC1gouBzE+eyuN-SyYncf!I-HM}h8w?{Y`uQ(~C zI2q?4DdQlSAUP>HIT?EqDSZ(czZogD85uW#lo>!Kj8001PDb|wpOWbhvTVXnQFijo z#OWW{lnj56ybvbh4@GySoyj{Aw|@{*viw2uf}Kdf6y24AC%+*JOC0=xRzj<WNEe?X zx+^0`UYfZ01FwWp4Vf-MLzJGJgfumA@&{H4y&6(w{IaMGc}wEv526z0doneY$^_p~ zPEmaFxWv)%zQL?v`=$0zTx%Hn2VRFD-(bJMW=TD=+9dAra@GgDMQrPcW*L6bZM3sc zSLx1=9SXNknuOh}8|j@S;sB2Gs7G;c3coMH7wDUaM;RDV5mY?PIV2d8U_`|oGhB8; zyr9@nD@@?2r^EC&;3*E8<ORhg|9gq4Pjs|g8sp2totz!+^?q*Quy4y8o*gSQT;aQ` z18-d6C-!60cTQ%=^yl6i<uTcVdNK5P0Hg#<urWj*qCfNpJ&^16;vY|9$>&Q`*zLrw zxMQ(LK_7wnzhe=*MqJ%sMyWKhX2DnY&+>Kc@wIWD@wRdJpHzS0b>nKpR>?0CpT=Q+ zQv8K`MczQ%vJ-11-%7kmx*A9Rc_MPzhwuu%5qBx}O#YrolJq$aen@(c;r!n#9$ze> zSUmZdN%p}w+#${(r87KVT+XYqzhB>1SG8r5%edDegfm)4sDX4Hsdkd>xZ5F&Ge$?) zw)8crN0QID-yzQ-_&ususGxKnsdAF#xXYo(A@n`ES6H|7E@h%5c@T92R30h%&tSQE zIO+lFcBp(*bTe_eaX6|%>gLcqR&<L&xpg?2ed_Me{QpoX(WuEXnoFpdtYzi(7XPIE z-#%{c5zv2@DoRGBNaAaR(%O?73MLCDkzI38vzI#1(Xba!id^T9L*#KKA+64R&lK;z zD+dtae4SnT-JYD@oFY6P^*z6$JAS6Wr5F#OSt`dFe<y1vQ#kB>mB07O9xCk6uNj{- z1l--3!XbWk9ZckoCy!^3!!qE8n?t=JQn0}nv%#3NAs?{q&k0E>4E|IY!c-VToE~OW z_(TzMiImcTPlJ(<DIHog$7_hyDf_-uhMhvpJNhmin}xqQ7SL&3UeMS1z%vi{lza%m z`C&Nqb<*|iAUK;u8+kP7JmzF{EBNoV!K2|rCurE`)G;s?HX!6r#3{ui+uPyXo%-cY zz?+9U?b8PQ*9=?l%gskF)+j&-T?$>QaZo48^Swx?v7IG86}ab(vO6X>>PJ`e*w>`l zvE2L7*JyP7{cnfm-8hJ-0bZ6!Ve^}ZiH(DeflYvohK+}fg-xW9w2`%uwvo4yvXQfq zu~G0&6L2xi6Xl4(fX;wXjb4pmi*Ac?fqsEOfKGssjlM_4P18!*O5IA;t8Axy`QuXI zQtl&hJ$F5MJ$pSJ$kr(0MC!zPrw&j7oDA;|Ck-zQHxAzoM-8(?B}b`8Ek$ue8Dm&t zoS>gz;GpARq@$-}XrpUmtf8-A@SyWxw4t|Qc%XY=yr92e^idI05`U5O^vXnyMbSi+ zM_ERlMD1a)ptE4qqt|0Nsz50g&_);X$`w$`6>?4%FisW<(tkvx7)x<!$RI6CGA&CJ zElUY4%Rq8UQgA{mhLlMy6`n01T1j(aWZ}&OTSzq(Iu>p$5T0&XDRJUt5zK@fOFb0c z6ud4#oOW4>Jqk6W>ftg4V@t&pjx3;`zFWyQW9s2Eg``PM6&@|XTS+}aHlyp|)dp)x zRTr)-;9Ds+W9t#rhOA17NL~~^EhKyi_QF_6G^1_e+6Qw>iAZM`&MaV`(pbqiV{PKw zhxkYPhqp>?6<#eMTgfzIY~o!7yGwNy?ko^nDL3P65?qBmOT8C<E`Wa@3$UURg(6Ew z6i6(Xp8j@);zuV6i<cfNFkf)8^3A1qL~s@42hRm6zvPAb!(IJ!h3Ci04Ofz}Ea3Pi z*_sx&9Q!1EoV&m+e3%F7Nu5Ht?&rJ2%#WP@;nl-$o0>m5)jnPOo|?NQc+_`=?!3>h zsd+;oHRb9&Cb3v8y7-!@T?=sp;{41b7~uIdzWgTY#M@*#)p8|x+$-K%AUaiwbT1SU z?Gl(s{QunT@83<PsST4lST*#LD-Gv5NHx@22-R^b1LtNWW={=o>oPi!HDs&**~W4W zWSNnC&*aTC9P1#QiVWzP)i$i^5L~KXa?~)bUW<4_T{R->$kbr0;#~y0jdYssG!pA5 z*Wj!YT!cK0yqSJBg0G9(p>pFA1S5@vn+`Rit^csY<i;lmi5nR;%{MnTIcS7im$XBF zrsBrS4ptl~GhJ%LTUW5d<|fDvnHf1YeQ1PU7q>%e#nlgH8c8#qYOHUlZ***MY{XiZ zv%_k|*AJ;3Sv9?AL|T`&!+0iY#oG$DA89q+Gv8_?`u;sF&}g`hqVsV@-U_=Fb2a2Y z{A>=}5VEekPIhT|$?6Uz5KS}`Z%)%-+>pFZcgg7v^NuADlRGqPj?)mcPIbxd4&4=P zI8<lO(~!N+bjj@w+ZD4jbZy>eiqa6VPI1Zh4CNCoG?ZuFXU@`)zRqyT^$a6(3l$H* zjX!`=0$?f~AkG2^XAdBl0qD#J@O1$Ex&s&o0Jg&c@-=|?`e48~fdu95Kjnd?k1N~3 zCBWJ3qbH0YMIPK-tmQxxVB@y!_R<si!(Nak4`D9uWZ(htdh2of;R*g>*iHIHZ1f*X zEY3g-VB{9y3HRaGO=$%G9pO^piPz0&gv^ql-Om6Z`ImY->50`%Z-i7Izt(RHXt~|= zB<g1VA~Qm%PY4L*=_dfh-Hv)<bklvY?IJqHxAlt*=mTnRS3L<n)IT`7nRbyK6Fm9_ z0J*obo;ckMyGS?jFa17%p4(kdl5Un=l$!*Uepo=r?EnzfmsS{&BtD^E22gyv0L1lW z6h{6g{DvS&Q0}JzB;T^!O#m@{>4lN<<LCM<0Zq3XKtf+;VU+yuz3&?m<3N^Soc)+P zDxjJ#UN7M{{5SqL%r~}iQ2ns>e)Sy}P|ugBmv}GGahPX+Z$JBv38>{u@a1>@wRJ}X zRPx37g6t*O3%MD2*%$d5;<y|``Pc#e>w5$S45I9d97Nnv098M5{Ru^azJv3JmG{f< zIDqv)-48;4;=VxRVV3>$I|iWU2fja1Ur@P`CQ08D3xD($km!TiAEhth``H*B8s%$Z zdoQ<sn56VM;d>%Y`L^8Y8!;e{|KVN4FAXO^`g^v%_Ey{T1A+2mhQu7;xEeX!cl?A- z8-&ISj-r?dB{dHv(NM`iIDi2`hK^2#0bhuYUx)!?ijHlHfxM4SypI8nhK`mbUP88r zeir#C2}4ei6a~^ZWPi~&BHJP_C6NL4<TOb!<BEr5_vo*Y9+4lC-~huS(mP_+NLmF< zvS{>?NPr|9z^{l>HJVm2g=`Z2DDqwsx`_Nv%$G7Xa#9kjh+Z|WLTNeBNwEmKx#ggR zU(ygT^z-@8|4kD7KT+}d!d*nHO0v0p!Gw+!87@gt#I_J>CFiTaNs)!Y6sc^|OSKRU z+Lp<Lse~yu(XS$(C1Hyw7NSlOZ4D#q=G`eeF@z%XBv~STF#IBWB}Ixvh9M(^hDps> z*`NT0|Ar#>hyOF9WQ)dCj3pZ#o#T%O5^l2ek6~a$M$Ide_fk@0s7F=~bK)w}SfFx5 z=?>eOA+x1t;M{QJ>xeQ^Vxz@GQ4KFH7aL=@O%3!xB-CgB@RjgIxQgaAlKt3uLXBD( z#y4Ynyoh`nhB2dPgah0}&J1IlF*L>j^VXFvN!`)AB1s~5hKbD_yXS-fGG-!9fxQ3S zDG!qYECH-eP=MlLHUO_vFffc4u2_B88i07mAZa-;hjvofBWe&!vXAbR+5X2HN;}GS z*bM;Vl-w@0O?{2(5#=-N2jBsK*9cJ(qa_puKzyZmN(<8X(-@($L}?G(W_U@E{|uHy z3mxuv`a?R=CrB=v#5s}3IFTes*RMlKrACdVM#ZH@6DN|F&M6zyT<Gy5{qaXW;&@^# zAQh7xDKkw0R@IvwGBasf(t^4vQFp@bP@gqDcUr7h@tD#jsbfO$rx82JEAsR)EQ@Hb zJT~P416Oj`_~1{pzqFDg<AC`z(mfh^abx&yPTg=u`80~DWUTS%Ls(XIxNhfeW30dQ zAgN3|#x<Vxlj$$FZbXf||BqFQi)4}{r15Z&bY|NKwUhH#;HJn<W*S!>Py5O6mun;Z z1M~R}v72cl-cH#)u!3SE>XJ}I59cofNKY$0lluJW8Q=X$@|R^J;Zhly6!uTZ_`o5m zGc8D1E5(z_{3#w^IK*9tZIF$p5TWTK9h2Y;%K4#0-bYCzAsCh;r$kYn%t4wbI~(lI z4J34C=1a&?W+uh?6Ei+?i0({>NAbr%34(Z{e!}rbKY2&6fovHd(Lk||Z0*m*_!CHr zQ^bM?fh4zuGs2_(g#F>mp}RBeu)u`j{Fmr8^-H49gx_Jpq5nOYSK>#MpyU@KL&OBd zq3S)Z<k$qpA<KL|rE*gF1P3ZO{6y0s-@Tw$Q1=g`;Dw`Q%RX@<s(P^iA>tiU$3JZa zeMtTh-SWE>H_3fsAA!C<gvm*gmB-5uIqvyh1zv-FWqX5D*A59lI|ZhkDW(z{rmQNa zA{(Z>6Q(j;$`9ET1-k#lEC1n_st1ZpmM~715k?yPPPnfOgeQxxz@$e?O_P%;EoWE3 zt5ndiphrkeorJLs6rvYM4T-K-QaUPeR_&-1)G(qac|uOjrx)#!$0{+qR1K>b)Ih7E z)r_TAN-fwe2lLRNtK!rQr<YGHo>a#&F-U^gR!yy#)WE6&=?B_=LQTkSYE1_JluZqy zDrT(j2rA74i0~5OB77C3LPtrivMd$F%7jV_jR%oknJQ>#LfIB5N2!*w&0&{(wR~0k zN_P#PD#(?jb4j<dP8GvS2MrIM3$drrR-BdWb4WkqDw5{UN^p=dMdixC7e^`$ADI4a z1I2~@ruwhAl5JVXhVY3Gno%~coLW>MDGTZ<{jN!|tV~6{(t6p|28JscLQ<`%l5g3- zhL|f~53D$BncRl01*)hN)8r3Cd`WLnZ&`0)Z>g3FL#5`jjSW&unx0H;IkyTyrQ)(j zWxYK|OW3BIeQ|GjtGYl%F6O_)H*mq;XYiJYP5G;0|4=Itx4`J{rtG&Ue#{pU^@u_t zaiY?A)v-zp%z{7svbjY{>XsG8l}*chxcTMGD*e&RROjq&VV!b@#dYdD71_&7=iF`) zod^ss74Mh@iQb|@CB&-z5z83obWgF~N}ozS1xABFtfwq*2?|#TF{_kOs~l>pKV?=~ z7AE1Pd{$n11yXuNzw`>hW16KeT&KgDW%ZkhWRR~GiLaKxk*rE6_@OsBUG?~ha`R?I zElW5SGS3)YweW9$^hsHkyUYhl^V4`T-)_4S^Rqm@o_d^qxPtTdb_y9L`X?|;;*`bA zOP!gyI(0%#_n;X4VU|iSn-Wd&hW6|vG|a0L)h-b!U|2{!qj%Np#5c^X6I&}Wmt1Ta zxR`f4!%cP->J<J&+W{*IcP;iTWAnu5q-!QwnmIjoMZjm3Z7b1Vs4aw5Sj=DSk9XDY zB-+Wl7WF6*SjatNcGd1A*vY*XgCsvQa&_!P*-5{ac`1jThddKw<;frxM=6b17&=3H z{Nar$ltnC&P&&4dzhpe$AM*&s-^<J{6a_=Mn0!X}sNsz-L<GQlRIsvKXgcG2G>AN2 zcsPRwB@t*n8K5x*n~&_?e4kjKT%Slt(?9A9w8gukjTGw(*A_2MpB`bnDSDz{7#Fk8 zm>yS`Uu+0Ig?e&##coQ#;~r5S9lTL`(syCmNRxJzNeWOFMHV7X^UsDJ(cWnNVuh9R z3%~;&W#2HH%g;C->p5vT{Nja`jSE;7(@!%n&KMpw-|+o%d&Txj4s0Rk+s*_Y4d00U zNC11Mu#XaNXp#wMG>__Uc%M06x&C5(CB_Q{6ORN?rl`~d1&E{n5C;+wp*c8*SQ&@d zK1gKd0_i!(Da05!;EUPui#Y<NMxomJ!Q&7cC=N#Tef|k!h!U`)B@dREE{Y?*O_x}* zv*Kkcp#HM>%c@&AHwvcAzA@lZBD}VxphS(6oINpg`0IWENJK579_W=$Hx8!H9+okv zfL2DU&bZsks~+r?PdAZbCdUz|P{ybpPdBGwLeGBpUCfc1F{yxcTFt&vP&*4|%+8gm zr(j=(tey^T!2YC`-{QaRKg?-@&mM;>O1%_njX&o%&1s&+!IYt#k*2^<#<djwngXuD zZlCF{;8O;<lyo-iYSG!Rpj}3=lzRrQs$7P%lnt8SUvF%mnc%D(sDup@h!)|j5}Bsc zzb&936((ZMq&duS=j|;BA@QglpgHm~`xSmtvl+7|XVS59q-KsPSX!`hWa=VXadXfJ z(~Ht@BxKGpM#>;$N==(tz%`}ljxr`#_L}ut^qThm(qd)E)SR}lK$@=owaRvpiG*0e z-4yj2zcFoR+RDC_ag%v<CoGVWi&&5hUiZ_T!v}YqIMeSA-Xvus|4oSqOl16HnDEV3 zY4T&5&?25yCewV{=~z<mL4I3YYa+)?iNg|i-UX&%3M_#ABokp;>KNT6vt!WUm*`aH z#Wd0}wM$IL%(m$@`%A|AwBt17F<FhE88L@)M)@?yG2es0L$GWQ3?!u7Y_|ni7vmtc zPRfW*4wcTIQk|?{I%!8bdC=2;$r&2is~h_BYevs&2C`~KHW^J)-E<S4HUg10A{9-S z8mu>5?Yy}mvy*0qEi9TEbT{lS_3hlbVc)qCVkeHxT$;Re{>gKbyd!7lGl4C1*@-<1 zwW8{0Fb!gVP9-&ttOM-ep8Z-W^`n_)K<@1C(fU0jEw6r39NUDJ8AFridX*hlD?iAj zO{|&)(QNSB8FC-Xwi4^-e@5E(bN?i0jN72LQ-3zkupi~N)NjadVA{~Kvu#B}$fQ7^ z{kiq`YW;cM!$jb3?)t19PAkJ!+|?`u{6?M~ODoT#-+Hf|NUMlIAQ7&}5UD$>Kq%29 zvUx-k#d^{utvjbcIMGzRxrk+-$ygJ{dekN5vpn{_v^%^&YM6I;?(D3I<=>|DjY~pz zW`Ts<Ic5`_zcK40m+0<v1SheV&d&_bw$B95`XB@N$8e<1Vy(e;!|l@B9TFkKoTqWG zF?)mQQp=s-T`0D#NnkzqlKC0dou?}Ty1DUv9Vo|m>HiFt?LC9_OoN>``ZY~#k<cJR z795)-gzO*u874H5XQtd_xo*7CbjgQJkNphclhiY8WKpPRS|4m|exQ)lGqC$py*_79 zymfrn^ycqNLEqe{wuot=w<*crg!QpYjAy#{Sijk?*<KUlzxC^DmjsFCq4K{~I)39u zxIn?WA;>s!j{RnoBph>rpm9d0ae*&)#xHk)f!!Y0&6(i~_!QVTm_6`C_Dn+Ph?L)7 z{B7OgYVhXC1nDWwjFJB8SS`eike)g<I`Z-h@YjW}y{#k1fSH*mJz{F==%65e|K0_< z-J>IT+sA;cj#WF9VG^9fd87k<``tjcPNUn>x(*RGYbNzz(gmwM8r82~6F~2x*<NM9 zRmZO#Qa!N(uyJu~?<6!ytR7oA5eA4>c7z*HAh##lLLl3X`%QBlWVtYrzJ=OOv;g#6 z?Aw()=Gt2g1nPv=f-c700Q@e7?R5q`bpmT47ZXp>2?acB5f@WW2L+wSfk+)e+oTSx zJfQ@WNC)9A6zxgdv<{p+)Vthu^&L)x4P-CSJb5AAN!jCKyW@TnipOQY)jO=WU6Idm zk(;yr_rlCb&iKsHvC~5b^tN~;j#Eqr)wY@gUR%yPz0qgZd-!{r{y^!jOQ8NpZM=_( zv;$Kc^5)Yvi~~hm)O-BawEcdo^H%!}ALt5fTk_TjID>OnhtRf>1IY^oP7|3&AY_WO zh*Jb_g;o2|HX1VOBvH&-ybBwSbKh^84)ty8YeZPaac~6Z{@`t|YY2~|uHm3?7wz`y zZLVv6kC3j39e{(2M|;<{(6un^_#yFcln$9~^J}=56d#y_lkJ;rglnpoXrGy$eKg^L zF^^0@VbQTu-apwqz?o<GzAka#)I)cFjGz?{%fnsItfz^D(Se&4((WM>@p86@XZnk0 zJ_?X^ml~iB<n+}OCd&V+w>spw#q*kX5a!4ao12tSn&=w|aem+fw!P+n%sWqh#2kSm zT<1*R&`H7pgy3PSuNdg3Kvw=Z=2q&}%-5+G>RT8k6`905g=Hqh|KZoG^L*L~!!6b; z3Q$gPd0p_7$2hef+fg&Oeqim;_O9iX-`9}1VRG%@;(_E22^j86(aVOydt|<HEOMNE zr*d%{s7d@+u9s>rI-=%}<50jPq~pE)D=^E^*QXb9FX?7jVrIr;zw3Snc<r0uSxQ4< zo_;g)vj2Yn3H-YIZ+;5p5cV$QU;*_O<S2prAOHDNibRvlB<zpf9{}gReb)-!_QxJD zfKeZmU-JI!B4PQH$_HdyhnBY-Ui~a0+4)0rM<-&O`NsV$hd6gJuT&pu{&;;k-_goF z=`i0&-%NcFZ>fSBfDapgq`oxcvHA#4NR-P-N5H{b#2#UrKCt$Kn^-4pZ}#S&$9<P) zKTBWs-q6j_%bm#m`zz#!*cZ(gD$4i~%7YBB_=D|>7bW9JtmifPgYJtnARKo3-tyH& z@Haz1P()`$->~s<{jK(^?cIaHiR0~EY9&x#@RmLxqHhYa{{H244+#4qLCmiF#r7Q< z0RPGH#n;^TzyeJFVEE$tK4xk2Lo0wmH$z0o2t)`Kg-;Phi0y~Z=|>1Ah5ti}5M2PD zRWP=N7fdI*O1B<N(H=|#6ekT8r!4u;8fu&~%vC&Amn<alF5yK9Y#BZ?j8R+*T!o>V z3d|;qaBvIav@=nDoaqn^tW8{apNOnaMbuN9mbRM)6CEBwDzr$Pt*~81+|wAW20l=; zuvtYql7W=$=~_?Rt1wta6)0LksexVfpGq#mO6a*bQehdGTcV171;sL!Fed2|<~hP$ zTbejzVd4A_D@M*J8AWIn&%(@k1F&ZJ{QsE3v>;40ttfoyeX$)Ew5({Farplu3R4od zER31gJf#-ZWPU{ThVKd86(=dIpJ&<q+s7)3ON)pOgCG%FcsI>z+RiE-XrPWu6^lLk zpLv)QM1eY(0sH~9iMDAG*d@I$UEnT)dT8am5=I#U$5*t8X&I}02Gca!G5ka5E5uLG zrfsU){Z~haoDnMxZVLLJ4tOHHFNLTkWeutpe0Au`AiimBgOUylC>Mp#4!sGT8N?>5 ziww0Nd>M2%g_RTtGlVcv2c?Zc?)44IK-F~?LR4gUkpW;L7!VT~K_;|#kZr&Hw|JzB z{C>%AIbNhsJaAO{9IRQmlQ4uqsr^5{b-}K1MBl?~2i^9=f2+4sZDU{m=Me@(jvw>` z_tXUI!6AkZR02PD*^j!_@T3;R@y9XxFVP&n9;zZP6lh~aPEIYU0p*Y7^cx}vlMann z>!+kjKoW+RDykG)??nl1OmsywzGSCWWSLb|>wkEGr_p(*F?TD7BPy}Om~2Rrfm&?2 z8Aj8j7ML7SnInwk%aUf?cT8+u84{s-hSPK)l@sGdI>~U1v4{2$13m095)AM$BWrBX zkz}OD#)uiR@m=G+^J^^8kz+(s#bX<-&{1M!(Lxn_kQx^rkt1iV(vhm6*TSfd;Tp~| zV`^*#<<AWMw5u3}Fz6!aVlN}%pzx*<6e`n?YR_S2N6n0218B_T8?j>bVpOtY5`&`i zqwGiA&3qa|)>SVl-LbnO4M!ZzJQ^d`)i0^Uuj!uA-lIQ<zW`uP1-w5986nK0B}Po= zk#S@qDMnOL<FLmf%}1O7CjcA(5co<Ri7_GzNC*6MisseKp;p4NjN};61=u;o^J?eN z%tqK_M<R?!0nD7D+BFQQ#aAds`B@;~M;!aXBLMJDrR{PCOm%2$(HD~c<eWm<Rby{< zC?NEsv%f{#+o@Xi=p8VEI7Y4j$WG<$@*iT`OxI{H(N0*D;tuq|*D<ieApm6n8CoJ8 zF?K?v%!oPp&k_I}+i01mnjlpk_MGTrwWpRK4TMKD&TtHX>h7<nR5v|@OLSstG|zB0 zfC)`Uy_;e;>^aX<WLM<L+ZO<NR|xz8N^OIHl|Thw<}YN`bF8!BbU^iYCS7#>2u}cb zK}w<uTm$_+I$09>^1WIP(vR3-xtwA7V9HVRb)7#{QfgHFRVDH&GxCXza%n&1;}7NX z4&{R|<&sj!OOqDm&PpEDVCafdWG5MaCH<A_FGfEsRdc6{cx+8kpQJiUyZ_PnCSUM{ zepsgFUm5sVr=jAlOiziG7X3r2)J)B(GW4-mLyevaT&|QIy+DJWCN-V@2UaOciJaO; zZ6{O~i)Lz->`E!Vnqp;|hJF>rN*JGtFPx`F6^kDwxKe5Ozqpc7^xKMMjp#;tu4KRs zZz(qVY45Tc#IRg#DL48*%{K)b1bczXo@KFfTDL#^@`fdKYCIW`+^OC_gi4Ln94k?V z{RV<mOTQMutpAbRG;;pHXGBU0mm2~s{Jur|M^UPJ=h@6Djn5Dla_R!tu8Gg0m`E*` zT*6X1v50A1#i^LZ3|=mG*V9^}yJ%+}&#4_fhba3{3cV-}$E&G_*ej_=&y)<dfKICS zrU$_(zbD5~l8R2-*Q}>UQ5)u;+ibK6_9<<h45gFCEw5ivyU0z~J6YOn2;q?GF4t8; zQnIs1Y+c{1{HD6eLX?OsCn6hBk`HP^(atJd75JHhj^+D)(3Gk#TEnR@eBz4?>YnAe z8g+s#NS&#j3;fpYBsWa0lU*w%SX4Yq137XEaOYB=MZYtiv!F*62<cQ}dF7JwMGm-S zqc=luvYr&MN_5t$M``K9(Ade0*r`y3$rOdD*y+if>8W7E@f0fEG%VdzF1%(V?w|c7 zb`!0a<8_x}ms9<P&a^Vl(K*se4CTp7Q+S85&eVKOIa0IqmdSg6nx^;;+m3QTnOz&= zG~G$+!$hDAU!Q@fzcw?i1T{Sl1PdchP-_JuRx%<XeR|^F_f&O?{A9s{vo&9@K$(FS zGfjFr!#LIv%AuU|ua0N~%{prBh*W%M#f~%s{W^-ZRFM>rYCK8+rF;?{Nr+s@+ma6S z0gOB$6&;A3%mL(WDf$xy7tRE)>aQFfwcAP#EFOshlevep&Nvx2^d8AwQ;B|)LIXY% z{rS%MK-{;<&%-bF!@PS@FVyCcBeDQra(1h3K?P#wghZLi;==`2e2RqBv5EXC<MD$d zxO+*jKOd!nx_RWvspS)iZj&5`nfHudt%5Rn40FjRQwWD)_vBuU-I7N1EXnCp#uLU< zfxLJ?btAI+6zvHWnhD#(mV17$o^G*STE{;J3hKLzj!A8kTZcDCSNF(X<=qI!{)rw_ z1qb&=UipZ=bT{cJ<FH5hhZ6U5cft`z6!)rpb%}=u_i%W)>cVvSf5fJaIPUB3bwOgz zDE`Km(Kv-=BK?TrUh_4}*RU6yBhh-Y?QrX!=(Ucpy2IC4>6iR#(1!|0Go=MF9hI{$ z%iX)Ydc1~#L=aV9+TKU$qbfRll?nW5yEtu$I9>A~ZOtHE<(><DFa)j!rIZ$?lqRQ? zHsXi|<A|2%5SI2GrZHTKN>mCa^rJrbr`BRnxi&j39@aQJR>fW_qns91HpFGc@Jqg? zGi|}4oDx;~AN`5sHw7;&6Ip1L%0q2<S`{)n=+qZX(NZ<s?npHax-u~8RCIU~HM&YL z^3+8+ywVyqCAxYI710GO71z=~YPyw08k$vfE2;Q$Gr&f&3k@3vx0Fu!+foSM%4KcR z8x4F~q*Q4+^U|nAjn{{&bvcgGjzw|sIt@Mg+LTo}f+O`K4ros`>+<G^){sTjvl3Ci z5?9sEQ6Dg4`W>wP%0>0FQZP9z(aJ^bvvSe65=0dk`jC`?Nz`8z><Zv%8q&i)VlY*) zYSIkmDUFl7M=sF3YIyYuD%AAJDJ*1pgpOQNnN<qvWeglCnV?OQds@`Kei|CKOyigV z0kh&dRcg}gSJYn(-7+wF`u;zYYm+?iq*}U#H5yuUPQU7FR9ERQQl2JZeii?feO211 z37lonPqm+XnRNdZ@mGDL^rPTX>zUTal$g`#Rdu7DPz9Mj(ThF;Q?$lehp&h*j^rxC z*?_O`qbNs1iLN}AW3qly7n<Jd$hX^DtfRs}jhR6^rMmLwg6pUgB16-Gz72EU^C;d~ zyQ6$t+h3iS79~|?(i}RmN>DS8ZZ35%6=zcZDD_^?tC*Z#Lz2GAjJ^(?zEX|8mYu%Z znZ6#rszR=+hQ6xGhMu*=rlQQIvh}>8?z~cX8p@_ZdcM5Edb!z#AIpY}D<n&GrUZg} zh0#U}t6ASqex~kNWlzhcs$+SZb+-6e^P%#lLZzu1df8(o_}s^atffIulBo(?J?0yW z$tK6L>ZY1%Ma{;#C00+1sXR@ap#p0KWm&F4O}Dm4OS8IiWd+|x5tRJu*A}m8ifCL^ zKCL7y!`Mi)ByH;07jbKX2ib76bZm-$O4?Tj%T@Qs*$_ObKXJ6wZYtT=y9YYSv?Rl? zt9MlxYWC-D8eSDXYxq?5tO(l}V`1uD)g!CGR)s7NoTFl`s}PkTYs*wntf-z_xyABp z5tWO#6#Ey7TU3JHl{9E7jjNJZ=*~6VviJ>i3uiSfE1M41xMXsxXVp)tRSqf;R;13& z+@d-)49l3c!OiJ^rqQz&ztzHn?6jI;X`R-ZXtS1Kd7U;-g-Td;_VUg0%sIAOb*JK| z(N5j9ibqwKMup?@&N;E0<9S!RGPHxnOEv6r2)&7-P{~&fu~tGwAm>wtw*j=2R)DIq zxR0DrZJw%F(n`}g-xFvB^i&wBu~cg>SD$k|b$UzmRPL%dR(mXW*_;!due_f-o<ly7 zNhU0hont&z!rN5{Ym@nC7+0{YXxp5BF0Sw-evs*jOK>R+afwrK$;CWK#VzQ>EqN-= z2cmI}V{_@Mb80Se8gg)|{F+&`n^^#G2xsB6^}=k{gz1%(TJ^{4=`rP|8BG=ZS_Zr) z*k-mc;xF^)aU->>PSqXF2jaBk=rLQl*!IWj88PKQ$EO)HfZcWJi6N!vF_eH)*hn=O z&0{Y`+fp^ZwEWSdt8LbjW~d(FYS%KVF3?;So~O4?ZK2oGtj*Fg1OX(=pvBU{-(aNu zu2NmTvL?JpYP*bY6UV7yRU5Uc@vdWA#<iwrm2bt=qNQhB8wcZ6^qje>Wn12|1{S0z zbE~9hSsR1hl)tKYQTH_OZPU}dt4C5>4}-h>W((OIv`NbJrS${Sel^@?sCi#++IRDZ zeG0c80px;?ea>?S%yfC&8nqQhi|l6l=1==*Zq4j6#Wf2njuzcbJ0x7?>}v2m>xUNT zO>z6ARvrB!rj<17e)mo7%{BZ2m3J-u!rEmm>*^M+O+EYER->%~`{jbx1<_ot3cF^e zO)dLu?30j9cl(G|b;z()|9N+bE}5-r@B?cRoA(yTO|dJQtHkFfcU+5jE14GaO{c5S z=NNZ2fzsU7S*t!9%NCbSFAy7}+Erq>S}?d;XS3FPv59n5<}Tk=yR&d@^V0mj>4>kf zif^LqQzEnq@F}-dZn4~Sx$?LQdsg!)?OEMDjm(=@B|66>T7%17E>v2u&Rx*WUGg%V zmoi-ZWw@Yexa77oueh^lPsFL?;imlJ)}Kjyo|IPvIs4e`%`eoG2VNBGO)b=vCpA}P zxwN;~biwB;nvsVgn4YIUS1jRIbh5O!5Onki!Cz5lq!OUaQUW>nNX}2Hz*2^@7IfgM zV%S6JNhkEQ3+9d2Q)8sWQm;MFa87dC@8<ohC)!A}zD#?~_LS>M&)dEy-bfpEX654S z=_vu!2T1gw#o}KmK9=#{=I$yu)=4l|1QfL`>z~y=ale(nS@K)e?kYLfLvB9Cd(-qZ z?MmHLc`S8Z2tDR`vt(S=h76wjJ^Ay~)(DG|RG=)vmJ{O?D3Vm6EJa*UJSOoklfPMk zssk;Oa>$#rKrX*-VX^!Q<>3EZwP15s%1_k`bFptk4D$=;mMzbkp7`Dj{PKj2L6yQX z&RNV8)tj1MX0HM4^-|Egt7z_5E%J7G{j&C1K_jSWsO?oUu6La0InRE)d2G*HZ9CO} zvY&^%f4uq^;6elMSKcfCO&0Hd;q%z@Cj2Sm*XJ)PQUQr_9^pD~@Y&!m2}`}4a5naY z@y7Bd`<ddeCsO=fmA^7~cJhSqCZ*F;VjTV)?XTHaX1wNj%JZcEX8#%QuiaO^w-&HO za*FaK^Je}T^`#L|CbAav`H1r-|C#!w7hp~*Jt&Ga-H!wzhPYUOxM_m8`VVmz6>%XE zaU(EgK?P|BESC!rl6S5FaqBnY+AZQ<WZx8<I0d^}ET^;{MQ+mWxXI7Z4h3loikPI8 zaf@L~huBML<O6$(a&SS*z*T&&*luaz10sq()qc-4TB~kLOm=tzsn{ZEw&HfxLC-x} z>lAi50+j&VUq~jr#oej{6;{3`8tn80nz2>VT*aNLLxFa46~C6b&vD(5M03G2^Hlc& z73Qo=I63k0;^L^K)ep=eZBUCl76t<e=d7%o+4TtQ5l#3GIErf*kl&uAVT+3wCQj{K z**fueVy|Hi-KCX_(-*eDw(<Os{_z&~vGwCxA+noo;|21YSFlavI>fR{;}^#+jN+Qt zu+0LufrGe?3ar%l$%vxaY#SM73S4D)OL2Ik3g+0;)7;0nE^%I?zL7Y%2ys%QX6A6i z@^QaLoevleY!3(y^v%N>7j=HsaIfOp#<`7pn};+mtpD`2wBrWRRB`sBFQd;QsJ}oI z6n?+$D9WgVc|zmby5)z}WyBr$LBU-zT7D_FKQ}UgOo50EAxAs`O{{Tj@+jRwGx$o~ zUA5CHuVoGoGcFENg-aYz8*3Enpvnp94FuZ8W{)x*v^tHo+ir7Q6ZGMs#72x#95mhy zd)f$c<Pr1{u*9a1G90wrjY>|3;sxZ}n^8NUQ(LQ1+q1J;4DeytAgQxTVQ{Xb3}C5q ziG?eQW?E;IS!cGMWi-}h<(*{*;fZ5r(plhRoFj4MX6{a#Sa5P=X3j9O&e~XT?6DUv zvbtnAX7kM$SU7Mbz$sXYhne=8AM+q&^t)P!JqUpSh;>FYY_6Ehks0*kcWTxg-AP9K zG`6X%qv?AK=%%9AAl-=?J1w^AtQCa{=NWwJf73O;R=F=S+!XsW;dnVNvPm+Lro$~L zni@BT?QHz*xH+=3nWmMe)2I)fEo_^Rn)9>rGwo;GEqt0nHWn^_x^s7B7|u9YfNE{i zXU?Fl>0JwwruvOJC<_kQ49FR=V-uH1zGXrSWFDCeiW${oE0<Wjd@Rnfpa2Jd(|8`5 z;e)8-lJ@V#96Kep@~oxlvtvXT>gj2A%WRkFj$=WWUbu~%j(LNh%;Ek~9m@t5%shSU zecXL)eO%fZ3^SUneVYd6bzEzi7c)r5qd+#E%)QL)8Kz^c$hOSJ=&Y?7qGKhO^w*G% zEl`lm^^z%)^*#gH;5-lY#g3BMZwzAaBE6OcEr`D%3y<M2stg`Vye0+h^VkBo=CV%I zv}dz%relt&Fjy^(*y^*^rZ0|>{&!HC*H*XrF4s-w%go+1?6JfH+O#lC0@sSK4Jb&? z?zcWhcqo0H^tJD81dKJKW80WwJAl{gmPqL~kLc8l3`Dj;$v0CXs94ga*;uDJjP%hq z1#U4;{bd@1*w)QE(hq{JXex+rP^;n8(qqU?-JLY~)y%G&S<9%U#gP4!mbx<ueo@e% zrNod9J#BH+c(3=$SYgAYqJ!|4_rkEc;3-dYoZb#ADj$w>mEHoYO-|=VpQ=_3^w5me zT!n~ln$*Vvjju(ik<<EB9j&=i1yg*kg@kZxx$@UW->s%|H9||Mx)++zlB)q<FRo@( z3nTKt#ea27i=(<@We_5-Nl&k~W>t&eLj8iHx)z$zvZak*hv?vnUpKdwSxdV*du1nj z?nzgu)=0~-I$>q)+;ZgPwFZ1u)Hac89p4P8C0ti!L@#klm!ej6)#{Wiy$LL7l^20? z^=%N}5u6w#K`1Ze5gu2vAcR-4EEL-;bU12tu{Cg332p1R=Hz-r5?cE8teE~{>&w@a zuCn8@wDtb&Z51`Gbp*|UZE4G-o_%fOs@_G-(<+Q@amz$-_w1&fePgTMR?SWA)he<r z&GhA8{|3_Hre_@$L!HDWT@k(aTF6zg3mOm*-vrH<3%zYg)Do{dR*SL9vMPI#;)ZWA ztD~Z=V_EC6>IH&97dn3$w$|xrGyM~~=yanHp3Pomx@dKSE$Uhox)6Ts3leD{)=Q`v zTgA9IGfv&{wh(IbZ!^+isnurnwjZ%nwi^z&S(Ub*9xbG?TP(BNw6I%+k=*QNS}$VS zaPF=(t8TTpXf@4l{k7F<-qmXPey3*=;r_E+G-VV9yLoBj><ZCcS|B-hW7f>FrD?-) zW8;eOdCOf%AU$_$*8HU9VdLh*$<E!EdXw3t&lab7uL)rz%wDwEaGBWxr%itSuFaqO zccI}VvweEw)aKFUJ*WsQ`V2CpGpe@JZmix6l<Dd;gxt(>XX<J-9IHcMV=XeAt8)za z$rIUT|KIMogB?#}_9n^J%;hnwgK2<STeJQ~?G-mSZT)8^5?}t#tb?ORgTQ9)<*YkS zS2fa8?at1%=}WWEM$eV7yD{!d)B6_WWe|viYCy`el?by%X^PmQxJ=?c^nSMTi4|HU zwhV9xFimKqS;sJS_(SwPxSD6D+*rQ3bb01}-XTbkv5@y`uJvTyMcwjv<KYVWSsYX` z@)EN&rf*JN9zAP6uRZfTx3M-28d=x>)!wqbY<cGQ=>gS_R%4bbcKyXY8@pzXEo~cn zTU%GWb4?zjS9Qx{5e9R+_BV|$o9~w-SD)O!ONqY!j(ttQ*tZ6;Tn%ymTN1V*X-e2q zdEM+!dzO7q@!J$O|F+3*ncFzILIBazfBZIj&5T>>Hwq@7k>1OQzKh0s?e`jQHdQ`1 zU#|8pVYxL(o+;iNKZpHoM4Ixq?sEMuasIJfX+PV($A$31(X3j*y8MRCSR^BwEF>B= zCF(DQ#J~D4{`5!uC2jn<Rs1z>{FzSt6>t27XZ(%m*GZ_-VF|A_p=e3+tnAIt-|YOE zIn&6ee<4%rl4rc8z<;?r^Y;HyQld#u-kLZ#bi3!f;eE}8nC(&$%LtgGI~0WmU^)d7 z<(erum4`m`sxQ(VrMOS>{>pV$@+uEjUwG}WJk)Tn>gU!RsODSA#aB`+#~ud3FT8HK zD7oHBekT;=K}+-2hn((#1i59iV@e#bDyPlAg`M>HYjakW2u{>bI5Mm+nq4*ph;rhU zXv#TayLb(A9gr)UmWIyG9-X}f{BnAgM9TX(`lIH8c|-bP1tf9`XIU-VIR^3I4pe8Y zEMqxV@lJfNefMKMsChARWoOf84@Fr2DL9q!FXf!gB3hPlOl4k)`dv)BfuMn0=vi?~ zv{-Bb`JB>OcFT^3)Q6UbxQE&%P!w3>tR-NZ(=yAyZr0N@uyJbV-0Q+Epr2Da%YEWw z*##Nt;?CcdLz1&IOAHGH{iPrOUHP8`y3B)1xg+z52=oUclTP!U6S~9;(Bv5BB+pg? z$CU&U!TJ06EpuIFy&{=;afrsjbEjspPO4mHz;pO`a<XTcPFh{YIxe<d0>N|la$sjA zPLdwhy#Qd}d~-P`vp2H{C#4UQURT{tXgvEx%*OzS^SFX-;J1OnWNG0qgViI0T`Yrz zRD%sogO#w4InayCU<n$}!yd=RaLr9<%>$ChRV-o$lP4~FRq>?EgQFd9N5R1&V+vs5 z)+F|wmc28x-+LuqdU5RR(&e???I4V^J~wlN{X;0+V<-69XCB8Hp-XDJ$bqemH&(9w zri*Gv&B3}YR)3Z0B+Y}N9cu?=Th8HETeSX4T!6=cmPgRjc2;EqRHO^IlLJv(-Fu<_ zT<wkjA@^^B&baMS2aLAL_eM}jeBJt6#7V!ic6*iiXE1X^-h1ZOs{Ki;hd_J5kOK`4 z>WRBkSLe?5wF639Il@K(=q5aPc6;ym+yMt6Qi%fVL;z&Bh>oEhwCf){!b`{T?gz%v z9p*bu*C*FF*Pf9y?HD_<*Xh?kJ)#9xa*vffKnupOg2!Oq$Rl20E%#(}^Md&|PG`*a z$Thl0W!JRfwf~X0{e?e9J@{S+!*=R?owIhA?RE>Oa_;FG2#cNHIrKjf_q%X#YU|uG z7>C`ta+vnKR`N)H59!+4fxI)q!Ce1b*tr4K(VZe45!?A7NFME_!e?6OI`4OYlX7SI z_R=*TPV<`3g*f$To(D@i&W`-`FHljv(sOL&A?CA_ea-aJ>ND1JvFmcv)z^Wt9dS*8 z!!G&~^}g(PEbI}qwvBTw|C0K?8Mm@3A*iB{^2BQ8lyLha;od6YPAB2PQ#nu<&EQ_t zQD{V6Xl6-hh(l<qNodSPXzrn>AE9Sl{%+CJy2sVXn+4JiL9;e}V(RkO-CyrOo*O2X zuJj>Dr3Ytkl@;%f9zi1`mi(9a^gV`uBi}OrupW2cAz6&bP}XN4N1md+N4fz<aFL=e zJ%5bo>YKGk84#TK>btcEs!vDylAh?jQhVr$8*;Q~s;^gW!Mu!^>RYwPsxSObS02uN z62ZNZy2Fhq>KoUFZO{EKxgN57m`t$$iqw~`P1;_y+zCGkKWutmbw9JNfp-_LO<Y{M z-F15J2%7NKN31Pf96de1dHVGLUpR~c90Pgg2@b_lFOcrSy@v`&uH$Z{y^FgSc5xkR zcxK<X-^q8ef1fDcQhO&0&g-MB&t?M@pUS+JdhkH5HH~L0`ygo6`=R@F7s8QDGNyZE z7u~V4ZCW3>xW2o-$FbY72WwZ(F|`ffVl}WH+W4gQg?o4oeEfmi>+Y2sW&XteuGM=> zP&B`7XKO!b)w`hC=p!z=ZENcQ9M=22o22J+7yPE+CD~&<X0FRCqK9Hv^)$h2tOsM4 zWmonl#bZ<80306Vj`?o7JqEf?4eyzKD!)%o44+6*9_xH~y0dqgZdzga3Osn+uJSzg zLImf1{s}#*-TXZf0<~5B;kz6+9kAn%MjvyIe%<N23^y$=qcR_%32zw*@BOjDXX^8d z!poz=7cRmTbu7Rlme)XKk+0gK`e57MYl7ahZ`FUKy-3%<x|>%ghf`SpQyKqgl0AZD z<%{x%rFXm!V4JZ&HRu5}GIwqnBjfnG@k#i#<*y`?p1(DBAdz}`@}S-%Dbj~xa0co9 z8T{qrPe!700fGVEMm_-kaNm9)T5po&Dm`f9uRmX(;3L*Y^cO5BAOCASQh%=fQ2pMY z?5{|IyI6m<c6af1=h*32k@5K^Y_jV3kLQu#HSUwzU;W#>FLQ4jcKR(J$aHX3;QXvV zrb_UwPJ+4Vc+vK-^&V*0SG)(eIqQ$pSG_lLbNzDbGuWQKw{>&y^7Q`t`3e3d8jy%G z{uBX}_%!|c9S|zANOF|$JO(uXbh<n6zYf?>c%cDee9C^MfBg)I7U9avKUR)#4;NX= zKbm_!0lIv8efb6i_01;)oE@<|rvv5vDl|ThzO=vAzIeXczTg8&`zDRA>hIRxE<T>V zU;>K!CcbB3bKdknYQMO@eFD1rhW5^G?gMTQzI*RqfIgpoUkP9S-+?Gz1>ea5<FKJ` z5uX(PzIihu#}Yf2`L|>UkIKRM_sZ`Di(mC$y5BhgyM6zRA6Z`0KN-F>zq0~%`u6u8 z$xt30-#vW$%LC^6ZXmfoVZS84lfKsj03uKMuXBF=B`6t>#&7i>YhT%5aOmLpCg8-V z;CL$FL}18}-2Wi@O-Z55NTHnzploi_lPQ0Iy%FLD;pqes@dgnLp9n&T1PZeL7ef03 zZV}2l#8vDK43`7!5jqoM{uIo4fYdgT$&+E6`0&47WM>!<{3J%4F+*^OunTt&3mxnc z5)9t(OXa`r-zt=}_?QUMu>Hy4w?9?bX|Ym}!92t^!03+(d{xLQaD7oV;OSvCgR8_^ z3cOV)D)5%!ZD8GkJHbtuD{z)kgyHd_RN|oGf=9)Y3#@OQ<`Jb6;b548m4nm7stera zslk3B3nOg8Tm?UiMS!L7onpEocS0FLR>%ZjizO6T&NG}6J;J@gfEMOJpos}9EiNG< zTsX{7@ILtR$iO)08@NP)%&_JmP6H<cI0HZvaaOhrOfVjp<Pf@nWfMJCp+Gsx47_Q0 z3)n<xnEv>IZWE9Z(7|Pd$A*;;E*<!5;&rQe>joB0=u1%ZpB7AY@XA1ziG2gJ4ha|o z3;|??NbpTCaO>DazJY5U+n2-+1$4|R#Bcy*;Mznv(YuUk9p?l05(OCw7IGXWL}FlW zVE=z7cU12;;)myNav&8iUJkqxtYxrqNYg;aKi}VE?YIW;%&^+Q)dMa6ynj=)<88w` zz<LCC4fOo;ztz7b^~4o~Cx%sqFzNZHdrP>v7lJb&e`*X}AHriw{~i{FiX@gKQ4uIX zPANfOB0>FAg85K_3{!$GMZ%;@1*t^^C2n3}XAb^q9&TqI;gj{hAy#<xK~B?6R-&3x z6pm25AqCT85aGc!jopi7f#MSC7?B7b-Z8jsn#byx!Qx9ZO@jU39#Y}te|rcBVPQk$ zrV9-^|79BMkVDypQ4Oh?o;4`wa5LgS6o+9AM&G#vfG7}#2o>8<O^I>vp>xx?1`8dA z8lqLW!gC}M#EY<}p@cyg)1d~{bzVDkZX^+8aAVVl1}UKIIy>mV8}e3Yet3SE{gAuq zdxOL}+a;zua#yI~kb~(<gUmX|CDwDe&|9eAkiY5oZ&6-WLQG`jh){_k)BW4ulDzDM zSn<eXq2@zQ`zQN2rXLsmtY6nGp>jMqP+z}z`Et;ekjlfBhVaNV+V^WvoqK;P@$%&0 z%%b3kcC#8_G9#yl%99ykGo$pu_aXPe^&x@4zah>2b5vIz1A;n)wFrX2xc#!*uHP;o z<^<mXLCkvSYCrzBWjn(M*)|b~Q44<;uV5Se+z+}n0jmF}X$N%i<b~1*lNkc0Gwt8q zN&@9Q*#)uk!qFPEfwrF9f;f37ETK3<^7}`(a-Lk>*hVOhp*%zS`}XSqrS6j*)bsUQ zf1o~)G?bs)7gHEHKU8_hvNFSy_=^}KCX8iBd%hQ$>?S6Wws*`fR9YugMiOd8T2jgt z$``v44d)K+r+*TzY!V?|625g3F<ug$ZW0ln>W8Asp;Tj<v>2weY6?221(XhKqV<Ea z!~PY^E|po#sJcq4|EQHBG>O(jbQJ3>)ln>{x=U;PsFWf?kJ>|k6}uY)FBMiyuDVd6 zqajF-)<cpSD>p!q0>grl8aF9*R1B{=^51=Tg_;H*M5vS|g{Y2(P!-xrtc{e4uB01z zzs{qn21^x*A0}61;7F0Q>OqC<GUpqw4K`PTo@C;Q6jQO5>P3a(qc!HY62A>WOAP5+ z48J5%v6AXZg}mSv*EzOWE6x+x4IW6W$oLiYs`ga`aFXKVib)Y5#fM8u6q_#GT1j%U z<736ek4l=G`WrlYJxXy3XQ3*_QcLy!TsX9n<K)VMK|B2gI<|#3^LCIN1?IAlW97if zl10K4i7g#d1Ui44p^qPABRy4IUsPZ0SmaoYwJ>R=+03tpAy$S{8?!3WMFu)%8{Hej zEu&vlyTG0CD!fT7=7x3^>n@eJBh^(bw6JSs{Ak`R!jDQ68#q%Wu`su=fBM6f6Jl9v ztoVPZI>+cZ+pZ1AHXGZvZ98d<#%+v74I69X#<m(KjT<z!&BnIByM11LYvu3En#sy! z_I2&^I8Mw-7Ia!mS9$<i2=|R1litg_nhfr=G@X=kEV0iYo=n=eb!GZNyc%XN-ITXH znYnN8%JPHc1xF~1SUNWE*JQ%J%{8MJG4Kjm@>0-qn7oME<;2u6=&TWv1B=n<{Ohpj zgOyFy7qFOvRnXOYvFM<ko3N;$FB`F#s9xKBBf#y8-qX29By1IV(D}-PFp4DU=vcF< zsqBW{NRKMFtIFn>RSVDyHEi8J-{rNowiYPZfS7Fx2y8&{r!WWhR0U%AP*A5=OniGQ zPpy6<eA#^SOHY*-F;-DrAGYDZ(Zf~YqFLc09pPf(!op<3qG-d?+CoG2;YzrAB^i6A zF;pU(!$R-jb`&Wk$tk4~D5OAnaNqIO1zU_D=)x1l<tZ#cwX%E#g6iO<VVdIf6k4D% zS*`+ph$@KE@ELJi3OCRXSs}_r$cTTr8)PvH=%$b!N8@m06$-GY@WG=)>cy7Gfi;gT zYyrg-{6UmIyTlLjRkZV3*+A|Bfhov?aLVzdxHVal0+uP%yjQq;L~}59G`z1!(jlZ0 zai#-~=1>ren0Ud@VNufkq#w{HtOq>IA>z*o0Y?Koc!&hpXSilWb9{E9)PNC5(opic zIKBY`bK-cxUlKT^+1U&fgTAT&U-plFfy`gX9J&?*JT|gIylb8OV-BTv4(Kh5G0^`` zbdG`m6g@y~&QS{;@Eq|;qLD%%XEpp-+?~Q3)IK0=E&}mh5`{bz)B|^Kumk6e#TViq zBcV*%6*NG%!wDf62E<Cp_TtRnF#lJ#a5g~lk8%N=klataC3;2dl>CnLN35Wz=r6KZ z&@Z@s-W~W$tiwOzg@0=oNV@_D^r2Y8!C=WjHgV?2oR{biUyDRLMK$tDCuXcKXP}iL zizKG=@g`U%qy8Y=*3_IFQI=wLd5aUr)+ku2;lIVZHF7*(_cSNk_Ia#@IYsm~T;5zT zWDv!~UcGT6%xGgUXv5WMk-xxLsG;ntfn(>=h{dTvYpEeaXNKaJga`f-wVM$$oRRp# zDJsD!{-K^#4~i)QM<O!6D~{HY5`i8SS|lo2Z20xAJSj+>7`k6Fp?K1os-7KT?OkPr zwnTY8*F>5%Q~j;qSyfQrt3<a`&W)NQ;eVO<zeM~$JUldGzMbkhzO_KT&=U9woLVgf z0`S=tYt36#73EAL#XpI;6%7!XG_rQ6M_s}_3B8r^6NSxzoD|zPafRc@A__r~k)gbc zk(9~Jfu5XH?f=8Z?|ZmH@S|sbef>)9;s%T@^!&)s^8o;qlvg*gxNij`1$@j^yEuM; zz2HF;=0{HSdgmypZm7B90jyC#m874TPHy=m7p=)V!_e1=DwR`kW+|S$^mtyUv3(rZ zBR@Zy<%tto6TH>%Q}KjUL08l?!B(-m+^0#%eX(n_-q1<&Oc5_Ap$KAyyzPDXYf3K! zq3A5J@w~l>t9|HeaxeJyC~+ehvg-W#iS<d5iKBhwYich<XvzF=Kk2ia!B<)=Q1qG% z0Q#s6T<m|iW&wsQtS=$LG6~~lGRAq;Ilj?>A(G&$`})^J2n*70Vj?*tlPd2Kju9ED zk`WZ53%jSx4!&Q%hdEYYq<|rYe!?IAYSCY7qFeLny*ndpGUjmbZvUl;CqTFRyxVc9 z0MkZe_zG^%hSihP&j#^7+6!<@Huwa#iRf<;Hs50KzJ=?4L;eEm!iIWP1BO^*ev1+b zcqq^-Xtj|TVv@S#%?eq&=(S-OB9nTCK45>3cu%#j(_dx+nyj%^E&IUrJ?%YH1-CXV zq`@EZ|3BP+fUgGaU+BMrY7XIJ^q0tn?j^I6@3-$^kyyjse)4}X{9g5*=UCv_yFy?N z@+kb~XV-(-m)DnNvoCBLIu#<fklbKP0SlxhupcD8=T4yXgnXd*9=AXn=GQCz;luZu zcaDtQ#OeM@z0{^6rU`5&I-lsdk<(*FyDZJ>zAr8ieq!cEO^;>j^6keli~QcVfbog0 z5ebsHPuqlnZA1MZ@c+x2LPTYczgW%90?a3hM)>6@yYAOWp-%*jM9Tpuy`<$IT5E(B zj6RVxk_h+*ko2RNhSscqrvO5q@7xIm0y2A*O^ew~RF4^9_=p5z4ZE1lK+`qD3)si> z?#NF>PmrxKt6lbHP2WXomKTVQncY!aV}-inThNZx)J6JVe`cAe)L1RJ9787y=5~Ww zEqtVP_}*F5^v;p?miP(w$^T2QaKMB@fL}myuf}HS1t;&0n;=mZ@wmTVxK(fG&(401 z&D0A<AfQQ*MKm4&>9W=0Xre5LnuYrYGakD43vmPbLYy}+pEqQiHz0vG7?NY_e_aCp z9D;-U%^^q40qM=b%gsTpydGF9zk+u3!XVeq-~C4mz<W+%guxP=(m%Xm;bbD&CTIj+ z9j5b>VO#6G44A0+jUcPxw;RsCB3|&z8Q!gTLKvZj9>>tMo}GtyP_(hFK{-V5^rTC4 zLId{$!A<?0eajnm7w#V3ZIEl|XJ0?}w{C2NUf8SpBVT+)zBu(jZKGL3Jd1{exai1U z?<83xIV3p;zZdmE6Mjbm(VlzHS`sRO7ZBSkv)L7SZ|#GGGK4`A8vBc81GIM`cdv49 zE|^-=Q@k~OesGWELoJL5OA|ESy|=ZIa6vh|jd-4Y5qwYX!`1<191)b#owChvo^;Q0 zPw&H(m4O=qN$xao#JhoR91F>?Mc`y2MaYZ34q?I2fxI4b*7bSIU&e>019m;~tmkeU z*0GBMg)xkz->)ZjWAN4TA2GmREr63Kl`oD+X!b9b4crTbdy9SJ?rPuHhw9BvznJ(2 z<a;+-p7Zp3re~FBZeQ5WNFckvjd~t>PXT20abKZ;lXOq^Hp_X+J%ga`v_B;5mfyC+ z#pio(LT7<j@V78Oa&@%uRx)*QIjI8bDKwjKS4l5&$P21C^!^U=4&^E<a&}DJunI|T za)G#@0l6J=XH3tqwq71dVR8{Qe_B~Aax@4ke^~eoQn+(2C@C;$_z)BLm<{*<H2823 ze6T8fwEu{b{}!d<Px4Pc$qar{_>hx|lRw_kP?_bis(q!E$D)Y9qza3dq|4(}3-NDL z0uv6ulnj1z1XGJEk<_FvL+gr=<jUip;R;KWWXj`K3kCa%aTE3^37JO*E*xsD2*!e; z6mBW$k_SB*Z!J|%-9fcPc{ZI47*lAvj?jq0m7#cv@({t{sD7ZYqpxGGk{yZx|7p?N z;k&3OQ}$)9X?#gx&>+LjZ)3o!C6LHMF#bjLgSW|2y3qGpn<0TWQ}&~8hr{<unqgdE zvZa0#_dlg9LZ1%D>s2(vVN3reF+%kl{VE)~cf42J4Bfy`k&!GJV>oQL7r~6`0<k9I zy;21kSZFW*mX4WFO~8WeCvt8~f8jqI|Gz1IfZ>0)sBlbiiwPSR1Z5J-i?qwL1?QB= zD@{nFj7Agw7v6VD=9S5yVMfCZSLn6aLI5wJs1lQ7m3bC3ps`2e3D<|(G2Y^K3iV%6 zSfMz@L=6k=rPyM-z`gkDArBZlFj>M<dKtF3E<*0pJrsbLHRc-{Nmy(zjlTo}21vSy zQX{T(kkecb7?3K0sk>zojN|bJs|TtF70oR%2vJg#Mv@JNm4B1E#1CQ;u=AvbjvzAe z+Om_RW<w#%;ZP#R!G*{B^J7>iQ_98{$flXgChy1+OGByuR|kMRMajgjTO-O}fY>1O zXf7IJF4=ExS_`L}$S93NqX5dm9aJ~BsYTLFW|W~Gw*#D4QneVmsTJZ7a|5>KH|F&) zx(O9hbJRy5x3^+9xrs3ImvJY^TC$nwfqrw$TDrw3C?iUJ5L2$bR3mjK)iNjtd(hq7 zo84*2T&5OtG4)s+;&H%!=d=0GX!Fmtu!{-DQn%Dkpf7R*!{&aMuo#!@d>}$e6zWir zgxrQC25%f-%%YTu6N%5k8f2q1i6xYYp`ig`4$AGQ?3e@otfUN>{OLiw9YtpxzI3Qe zS?Z%};Bn5vE&fpR63mpiagl>mJL=AOsTmUDfK)5K6I4#B_wrDzFHuDmfIVnD_?PRK zOdlBC!Et5)W<KRpQjzQ_NeG(w9MnOf9V2IwmTW;$VoKDw(82YAzc{~V2GqJz7Nv^V zmo!0%EUNLiL3)-;2+uemo=aT~(gDJ_XO!PbJu}<HsP|~%n+8M%mv@N5PUG(eo^~KF z$>3Add=y`$gvqkw#|QRy5HG17B7BrO9^SG&<fv8r2AXyRE`=UYfkdsWZ=SlUv1(Vi zCOthDbWEtcLSg=t23`pZ*_bSqKpL%yG(BeGh$ap_18|5`-pz4VZz);PBt`(qgR7VN zX!@3cX@Te^$u!x6#Q#SVfJi~urvX8wzVWGKM^FIak~e9`Nj@k~qbo5{PB&4BPm}#k z#xqexjJsHzKF_R-RqHD~f{^1LR<lbP6!d;!*NJLjDLa-UwN?zhidGK2`oEz6q>NHo ztzuhMu2MZsyD}85lrovwVgU9pmDc=#@IKyFo{FKf#GD6nHqchCAx}?ZUEQvvQB$By zXg1(b)-BJUhVJ}8QwM>a?}q3`Xg2duEFeGEORc?BSQB9VXR{vz@I{deVAO(2$!1h- z-*IK&iv<W2ORI^f|Hb_g5-GT{(nP6FGt!`TX=oEl>1H&6--A-Ir7B0ME|$4H{RQV= z*#Aw$Ps$ejh6B1I1Y)kBYf)99q;T+_-IlK*P*3hf90-1Dd@O00;YYaSN#Z3yaOMTV zo|1M&{$iz-Gu*ZU&_*FkawmE28s4<$Y?`&dLzYyCa!}N}^0CfoZwTDJ^2-zD$7s-$ zB+Sqqazf)}@GE5Ik7?kRME(K%p_xPe5dOZ!uQ>qaPb<pc7WtU)LuoblR2|^_vpcU~ zXCw~MZ{FpZ!+^XXcK@RO0g<^z>eVIlGXy}8lIbSKOXWp^sw(4A_RHhljVr<<BK~*z z;yjIMoBeuMetse33VBHFgQ#nr>v_(c#4$z4x~ai7lFaBa<-Hs+o2jl!S9^Zc%#_!V zF`2#M0Ih>S&U+{PT<~g6R)%PrYO)-#=xHpaX{6C9!d^ipQRJ$OWb0JzeW*H4ljJ#@ zAa0w;Mw?J~o7md}e-u-}ybt_*hEdGoG_9HYe{BGU|EK^aEDoGqJ@K6d4CAUKb&AR- zv<_@t-G0DiW_ZcW=Y5=Z+yC)L0<h|DFUun@O)#yrU*yX1gKss^Ual!mA4u-mS#N0m zoBZ$oGVQPV0}(kx{&Rk3KBjVE>$K2*mMcq`*EDGMpu<(<hsX=0B;<a;AQ5Q!pqrCc z*^5>vidZ=|M`kL2pX6Zj`kfb}Pz*7u4)p})ft;)JDUncWmbipbF?ijzs~3zA=92F9 zCodGC6d23Gy=g=M)(_^~NHkJp$xWFW-rv1O*sm<`%hj1Ix0y)eH23f#Lgp=;pC;Ik z<}6Y4;%E<s*^_X{PiVpOf<+#YKYNS{T)igtVrh>B@PGd`F?^6bNl~}Uw9I}!po-)D z5-2Q}ou~2^`>@Y(t&5+5_9d$W%&oRF3r0lJxTtzU=innJEf{`ta)<JIj>A-wwJO-P z-6P7Eln$BoViM6avX?Ml#WyLD+-&hPzybg>GR1PBGw2;~S%BGJh#6D3K6SQ#cP(-a z%fCn=<@eYLnfh)5T2Y=FJ0VT3r@&%Lj72CR0Q{OAFSYtxb*iGGB{gC~(qO;2l`|_} zsw67w2I!lhq7lsd<iTG%R`FKyieg1*L9DbvFHe~4yb`SbdLd@kA*TLzcrkL8<#++; zc;Rt)!D@KX;6g+1q6Xhbjq;+kM*X^1?E0$M+pB0=1gDV*?rssmLG>+Ok*<hSBZO`^ z@xu@Y_P3oDbdB)R5lz!F_O1#=w<4Gszzd){Z+Xb-mg=SWr3ic)WYf!OnZ~M=YN_Z_ z1U(&Z(^ntj-SP6g+Gx7Oe)8=W&CP_L-Cwte19D}^)xuvN&ruF3C;4FP+Qi>D)kx8y z2z5H;;FrIEnXd^9D`ct|5DA0hNW|+$vXW+{NL3qrdL8gbG3jUhkm@vY|Mv2d3J;iY zFs?8;Qo%!e!E94)MqDjnI1*C(Ml64`=D>dQ9PzOPPY?vRz+sR4);EG-Nmm!8J4R`> z$;Oas{7nnV8r%{Yvcy6Zp0$%5&;pD|!>A7X^O!ZV>ZjU`xLd;3B`o$GTi&vIr+yjn zg#ir_nxn9VrmlaZKnr3qi}~`p7Q;dFEdfB`I9)>chBH2lao~Q71g08xmtgSVA%AfT zuxzA_gqE=te||N{5vJcNzqwsPTZVyn7KgtY^~LE3#cwvq=OIDUEcWqldn1UysjebC zN83zaE!WsL7E<q!?#W>mlE7Wrvlp<AaX-m(YeisvvIP!U$x6S9tT?_K*W&38ydBSf zq6VUC!J|W#AL{D(7BYZC7f*WV=&*0k@1UcHTr3mB+TizJrF5hEbWK!oz7J4;q<NnP zeO|{nT=VSrO3e73j-hr?H=2<aT-!82O*eX0H;9X@_PuIVMbD3lUyq-*elLQe7rrr# z;Fw0%{#6D1KT*IZ=tgq=@Jgi5+NNR+wX+L{pO71=5f{uq*10YGV5HS*6khhX8{jr0 zs8d=f`ow|bEDX5a1{(t#xt^GoL+pkdKP=Y~EyR4HY2;WAh9<UXt?`%RHdSvFSPnWF zyfyQ#0|Wt#B^r$)Pmq8kU;xDowoYOp_mi_3N_xgwSIqr0W~{kP%|_h9Byb>P6o?@j zS2hs?{|<W7-OzAn7YNQAf=H>IUc^%!H&2*tJpP2k2?nHxevMh-eis4KLQ;eGX56|q z!^{>yLTC~DSU$|p6i5c?nrOK*r3)rm`B}`@5iCT@wS}*a*qb)hE-#!Mqqx(wMy`$m zNuS!M1@j~(Z-1cyVl&jb&YHmk&ttXQcix0cn8$LrSl($u2~j|Tr)F;vk<pRXJG_0w z$h5lFU-kAg&iSB`6?pcs(k%`m($Jda+4s+j-p6~-<H9EYxB-m+Z3m!MVOdO3HLB^# zJtnwyxMg~Z`GR^OatsSRgYTBQqp>4hi>AThTWh*PPvP#A(*fVW^GeE_7*<LgWQB8% zCf@`YkR|-90k8<=g-rwu04N@b!#x2;yB(WgO$NSIU^*a%UNXWVQ^GNH!a+5{Q8vP1 zC&F>~i~+ff5xR^an~X8MjKM#`fsA3#jB#j#0jal_M>Zgp2w|s&vXH<qmb4-7T-ZEi zfVZEt+coI2+k#*qRfVCGTK-dOx6Em_1s{+y;pn87_ss4dI&I`O!x%`QunWz9`}mV< zH_d6Z1;;?43LAE1kZNVHVUu*(<%D-bxe9VVP9dw&C9{RuK&Oh}jtKVM?hhBC<}3r2 zsz0Ux#1~%!Kj2w-{0Rn-w_sdA+by{(tN@80y&>(K&nrsJlcq2y;ryY+X~n}HLK3q@ zZbfCqJS=`senrzBpC>cDdvwRrsjh`@#lW68WnbMM9JXzcX$R-OrU3o!${pW;Ni9N0 z>ZTC=;mU2_-8mP6=I9k_dyb~y<srKuhUFHb6=jrKfu{83o|9eCVCN@36GcG&O6z&o zv*NIVeoFf}N?<H=L)p2wd3pu!lo1v$Q(#<7dXL#TrFnP-8|6M8lGC}<#m{lRg<wVL z6bDvz$KGWl?XMZ&^{o~HHUpSxiJb;B`0jA;zIqP{ZD+Z#G^eaE01?lSr*!Y(_U$#7 zH^*?CU10!Y!+OT`kr&3!PE+YA-krWUctG+Aln|zP!$yVM;kZbBVD!-zCdkeN4&ys6 z7cCEhK1Qzu!X(+*EM2%eh!=3Nm+xY)pj0lgRIZT5FA2x5AXqNpSuWYD&*`f#_#Muv z9WJ=f&Nsq6V(%XOQ6Iu$AAb7O7H6>x;ciD>QQgN2dXRN+CbA1QlXVapXH|FU>@Zv; zJ<$7Tb>JKSuNR<$IGgu#2lzS&kO2NpKUaFN^l|BcUXOR^Yx>=}yL@i<;Qnt5z~|qs z=YyxX9RzPgZ$j&tXWe%@-WTl;!al|wB<tC40VG{PS$|9b4`k1(#LXa*vDgin%lvzi zhsnW@zs^5AI6Zs#LWsm=_rCS2{4PG%c(8eP^@R~h073!3_s(4&JfD4h!QVJKL9qSX zxK|4Ih0pB3vOmyx@a<>ymd@43`v$>t!Z(J_to1I39iEGHPe-0-ZC`@U%=PZGozEAo z4?@pIz9gO5u#y+B4-(I&z*Zg3FHxkQWKZRs=0W4x<`u~=S>#s`>>kTG?t{X!1+gHq zUs7lP+t^#TF+ltCJm^1XKij>c_@#8h&YxbP-iJO@0Hi-I!1@n~Y-j%m^bdJU_Z#lq zUcY)fC%KP(E`D3?qVpjuz*2u%A7?4RnSvYCvnR_084Zwvd3}w7I8Qlm0Lcw70+;g$ zi(ik$+0U4EutZ@IT7m^t_pm$AFX118A;iUULH=+hV2>(Y(Bh=f@;T7bCeX?o(D#9X zw6cMWw1M>2fz0m$>D~u2@dh$@1hR-KV~dkvm{}wK7yhTEOT>^z9Q5_btpIDIO2nmy z!+v{-MW=^P3Z@s=%1u)>EFqi0vW0I5<`*~2%~CbCCZ!b6`6?~`Avb(N6S!Q*)q`U) zEl8TsyVtg+035FHC&4J<GPwy8y8Gm=*gxPwI>Bebr{bvA-v5F9RrXn)Ns-XN<bINx zvd&0+-KoGg{RUP+6@?~^kpGn=coM=fnN=H1g((V`8V)m9?x)I6bJGY`t#8zdxWGse ztP8<wV;aM%1Exbhf{Ozu0xW!`ewu-^mweZJPtAy{4F?i|Hemqds(SA!DzN9^I}whc z9Y=pkn<jkMT_FF2?O*xz1fto}wD`LM0QjSKaUni^efbH#nd2zS%jl1Y9s@V1;jsA) zY*B-kECWj!zBriUr!M%tJXjPw?$^klg*#cpKa&dD=?ySNx8eQZ=7R|!_60VR&x;-P z!R9bd#ld^wy9^*$lh0K>C<SpuH{n&F&dJ4{oukhUJjmLxx}t&ScifByw4&M`G;O%A z=)!O$!76457m<E%5oYpiN#FDoA=UK$;rD&%EWfVlY|Wcdv+)HekB|oj;nanL#QF%y zd94AjqCPN%V0WUEc}G0-L70ivfWpE`?iYi?nq|WZWW(zR!Zt)Dm7)4*5XkQ>)iA{N z!V$2vW+V+cB{k|L^<5=(t|g6;dR3z&Mf2akXC%kLjtuYX+fh{c%l$JYqYp>y_FkGn z*W|sIgG!>&Mi<)!{EUZY$Tdap6#(}v`ccG9@1q&yI|o{B41!3d-Xb%OnwA9!X}yTb z-np$NGlH7R1(e5=J`}TGI}ENE0+EKjRc1VF4<kqy-ZiZY632A67~YXzdOOTS(0xMh zgLp*=X#*8-U?U}fSH!DG$Q*+v6R{yAIgmsCJsr3hVt~N!yV!zq%Hx$&Y^#Oi)65`O z#xAC6KiG<T+aYx-g5y`oU>Za34hp;Keb|DyuyV?6mNj5xMo)<t?%myr7{9B+@<Z1N z2PyS&ZRt5>-j_EMZy|3<J0-xKN<f`rcJo9o_x_9Y|HJu%=Whu+b$W;j(h_5!Ms|kF z^yY7|p-<3dp(SLFZqZ%T1CB_BEX?spT*(P{@(qnPB<OQGac%7C@XkoTu=zfMEv1X( z`(h7$s811}`@G3F)O|>Wu}H#W`#O7R$W7Ft6eGs_aJLjLlJ51OtQcRJI<VKn&-(m& zQMY6+5)#E9#pUS$TvoxRpkAGyu02ugQ5^zH-dGMKQK+bHNf()@H3S3Po)3}jCOXTt zP??C)RbNLZstmDUgAn9{b7EynzRERA%5Lye%I6i1?~y1}^vZ=FfuQ6PDdm!};4?xB z<bIgT7MY8E`X5OEmO?PqK$*H)={HTnB@A`B(nL)?d0sW()+1pEa1%zTQ<c_gN<kpW z4{}JC{?L>FINo?$1-F79>O!R*fFY2UD;{4#sh~)mqqGIsgVF(<AHdMt6*OX)s6t@V zxPiceG4^>&ITD!%z1@<2$gRt*E38s&NR<}PC;&(9xJUVyg4Zcj0PfF$;!T86kSNH- zFn<rvtA<Y&ohU6QBA;K#Huc^ngVQLDR4I{KPDC!DkZwxTCXLe&VnvRl@GsO4<&p6F z57V!{<yjc4iX#Uc>&cmtlI4aAu>k=BF5TiZd1dmP?8id4sp=^&o1l8NB}%*GMp^wr zyD4`-p|7z-b&`B5>s|O|%J;zERh6HTDA^ymkOF{>zquOllVv6<%M}-LOzHlG_el*C zndMRn8K$)0vC^+wp<cy)Ft38_<(mpb3YRBZDOQtC<?ae$rz8&IuHQq9C1lC^vmB&e z8+efgIDm}gstb9h)~EF0Gb*o*9%UX$13rR;2kCZLb`qWG`5OKr`U-L4$}CnOviTuA zi-CsA`TxTDe^C7l=gT%JAjTVaHMB08STUM>H4MEI=uCzer-ql{gtt<O#GBB)I#fS0 zP%$#t#yF72I9OXTP*%~6O%y?vUQ4xHOVL_O^W;n#>P$&P(*`WT$N?+mHv<D^vXn%H z!NOg3XI(%(WdvO5B{B>q?b17IwWJvsR)K$>{|X_jUBxsXcO<T_QpLgpA{dI^=?66W zr7Mc|%uOKup~{`P%O+<6fZ{)0e*<f22iCl_pW_9F{TW-zSCn3rUyV+gA**(>RK3Iw znC{}9{-FGqsDRZoM^KiS5j8GgbI0`35wP&96H~p>#wPz7_^|7A>ERhDsFp<uSvQ!l zOLwX1nI>qMMK+#jHCVU16W$=GlSMP0f;%8GjJPXxY33Q;rfEdYk`geulf=HG>zUN1 z2LwQq<_9~6j&_kRr9Bhcbl1oolE{XKmMsQqFO_LqcUCWnJ*(SP)>wi96HtdjcX}=z zfL(KmkD@ShHb`Zt*yOq1M_QO6J7Iiy19m48xK*t6k?No~PVh^4162?6?4(~ZJ*Yf1 z`p9%JtS1CCm=6?PN<5&?#9DMEKTG=314GO(%TCHA!$ZTf^sBz_6G>5W!b|q0_X7#v z1q6GJ;%h;HYKN*ieQDy1JU&%rys})ixhmKPdFfq--H%iW@w$U~=32lFa1!Cako<gq zSgj5<FhhCYLVtBtx&qQa4geI2uj2HH;u5`p13(P%xeyLvM^#GQTuMz-O2f5JRk2U~ zQ(u77KMDY}E!ps-pYrI1CF+Xcx9ak=R7vXcHic2@+H}Q~b>8yOyLDL_^kM-9WtwVb z^s|YFXtS!e^bLti@<fGI@jhk2@w`xl0aL0r1)SPxv`R^q@-BtJQ|dN_{w!J;#$~`q zjQ%9?Rvs3(Rh2ua0C;`+Rjh$x1YY$*fka|?mBN%M{eyge8m&jVmn4!za5Q917`h<r z^MWB&i*M`(c)3xU(sUy9`AKX;?=3ReiK_r!UtCD;K`ymIQLRW^P)W``gSN|hNYNsh zT|YH{MC&)*RT4DoWnHbRZULiqGOa?A#e{Jc*kxkU5X%s~MMJH$Zh3`<Z*bgAwjU}% zV)PKTMP04bV%aB+Mg{?_uB=*x#Y*5jNdJ`hG6W7>_sa4i<#*D_B<2sX?KV3@c+n(j z4A}tjBW=Fo48V(lo1`#gu^Rz=G>UuxJ{qi!Za#@%ND1(%6g%s;<gaL*(%oTqWnZd# z76@v;s%O!vBv}o)>_SJiYsME3A<**eMqf5vYI_#9>Ab25(~=~q(5aWuX{tKg%5x>9 z=_%zGX-$_N%px78*h=3p+<fFpNYhnv|5>i9HIQZN&J~)bF<SUr`>Moq)<Lr?GmS(Z zydg(VR!UQ|Pt$-(Q@v1A&q7msSJMbvQ%%XIguXnYtSqgpJjAvv*|t39uq^AaJOIBe z4#B4gM?11aYSzrwso|?0#$(~klr0`MVTqnHQ#IgcElZjivc=|Fge}w7C@<%lNwZ~Y zXar=f<#QTG<;XK3wiL~C@8mHXN|zMvsv1@G%PMnFX*D{vmP_okOt>1_0kXM7yhBr< z+;FDKmghzQo3+SY$Gb#m*2vbO0rmQ^>}BTl5cTa9dItPZ)C~jxTX_)Wr9Cs7hj4BM z{PNJVMKRjHN<L^!d^+@S3*=YJyv}~}z<#H!q)kw!F;jZT>Gp$PBC|BmNW-e!Wv1m& z(5>T#=!>pl39~wxLz%)%p(=|;N;$(!(jm(sy<5W%X~Xg=4e*bLUT#4@)K&`u)is(* z^k>a^veHHzO9W;zZP`0>Pql#<{p^=R-y44~RX`1^?WYl25}vObTl#Ajlb)9QCeaK3 zkmFGICd11Jx?h8(EM;c+5c{UgOX<b%MWVfGO|@I5q-kb{5+D1r)Jvwld`;u59Car2 zkm9E1F(obIrbt*TyL3EZKNz5g3p=#MYD)deyS^L>+_XQ&K8n4R_)e)?`wK7?Cd(^i z_1f6f*X!{!wI_pbu{1>e;m!4^nJ!TEaG1(r_NQw<^3?+fK2uY&%y9Xa{N3rxkI?mj zdSu7|$vf>BJs}%CW&LmBUs7qxTxn9Y)FurkRg;5LqmEPGg;VE>(-^Uy^?^PP=VNd# zbbAr@Y=li;1BRYlWg>w2<tNPofAkFqdQz3~+PdX=0G4Mn+hBfI1M{F+UN}1k7!?}4 z^uAOE%&C4X;F?RbR%)=+bE%Ya)={WTf?1gM->l~b3=f%eMn^dTdedNE{xJG;T1Q1+ zioaC5&3jo3H5lnRygSRknSB&nHhvN#$U&ZgvDq+gAj2nBAt*wgmlhRJCn$U=iJt4X z9t`JP;<anz7K4nLrnV8WNob&3(zHwCHUv^MGnO`W4SY)mc3IrU`Z+HZOfxt(kquN! z>UOD(27l;$-^u^*`M2f&5c=FUgO6Hvk&Rl*MRxP<)&dQNOZIlLjXKN4C-bB!wy+Hn zOQt70Cvd$0laJ2}fy}D}`4zB`Oany~74FKAzsd|Jm~A)U>W7!GPs-eto(vV{tZe2R z2$n|u-t_DBRbOZ9KYp%nT@pI!fH^J_njyA{ZRo70S<*O3y*2R8ZJz;1um+x`b^II! z@8b6P*GXY(k_Htogcn4i!Yp}}m$Rn>o9ln*d$NNsrB*Xy4F|?Ysn;W3I6~!FO5;^~ z6E24>*DGGcLe(e{O5??Q^N9P<H{xEkLwYi9ilG%{nEbTdnNtAk-<^7xF?JNld>D^X zrK#hpHScQ3<Eqi*s{h$l=g!p_bwjU2#;XE%4&2mBjkfQ4i~nA|y}(GGr7~r5_;C07 z(hIsh4;Wo4fSdZm4VddgFXZ+jBZcb9`2Zus_ADb~ha8@-&2ek*9rAc)(+@^(aJ&@S zlh*X!v>hOImc(s}o8|@fiEfm${a`b1n7wq`(_b@DkcvOgd++BgUK@Fx?bwpESFfp@ zRYMLRKwbwtl79IvEcqWw|B;sHUWueKcJkL@mxC8OMUlz`&0)fI_Vpl;2PzX*%C4fZ z*UT=3tosMi7kZ$?`qI%M3hVIyIsH(@vg#SJo`Z7N^E|IwGgagA>YzuRFYSO4xWpmQ zqpm{=mZ!{Ny6H&ZI`fhFOH&8zqxa31N8cBJUsaI;k~zQW*nOEBb7n=6s_Y4s!{X~{ zKo(r#iy{r?{RsV%=PTD)VLVxVIDfr<BXWK8h)kqfygv0d<8bu(x)p7GI)SG35%Ps> zCieQ*qwyo=OX;hkUsdOX@nQA#{3F4O!%O9>vR^e#HdvwG1n?@eqp<pMrH8QSfNw%u zis(2Taz{jIFN&ax!nn!%q5Gu)b8~JW%@_Si+MOaaZhF9CCq&@#ohJaz$Bhp-VEH%Z zs11lB&2%BHkp3^~AGL#JEWvIr!4`i58DhB~V)_k@$~zR9AmT%F2yCSTl(e;^^cGIk zPigf0615Rp`$SfG{KBXyX}tUjwJ}-;O;*uiyg|=BX^Z>_wb>F&O&;5KU5?UB`HgD7 zz&cH4I7IvKkfTDRDInP^CVQ<B+&J=Ez!k0PIf0%SWD~yp=*e5-9lY$9AaImfAh^cK zkGG*5%`B~xpMH^f(GDIlwr_gP>4oPnl^+Y9Hnwkd9r_6S!JlnHRvQ67D0(M@=R*lN z^Xxl&$~x12*$;^q`D{z?K7c*pZAV@7Lw(3&8@wO<_DPXVbQNzp>YyL#LlN8XH@gwG z-}vyv(GUF)+g2ZPYX;tbVq{CkACB7XNBB^95m__z-mZde?x)aElrgfZTR+T){F=dq zPoLPpg8I2Xw1UU{T(AL(NhDf-Eqpu<a_@BNl6A)-2t}H3hvC(RT$tef7p$KE<AJzc z@6^xxk<$ATNwmPJyV;s@{48p?AG@SlTuxblNAv>E@7<toM?W$otL+Lq=^K7iw1Db5 z*D2l|@`luQ?!|z|C(3e@D4KqaZM=F=0J5rIzruFX#gfN|XS+78E|+&_(SA{={W9B_ zU{t}Wf;}AIm6r4z4XOQ#SrqC1IvnlriZ;GBmYe{N9zvUtx(GOyx$06EM+q&J-wj&) z=DzwiNF$f(ug{U4y3S~V!-<$07A{W0;grBChnZ0ckJ4+dI0pr5c3A}0U@c$t%tEgS z9bp?d&gC}Esx-}RhnW#}@J9$R=u-)gxAZJ1VhIs3`qL7<u0(f)(LR|~A+2y^idDOx z@nbT_a60x#ge4X55Z%5CTZo{v4XF`)OQpJG-Q|i8b6iKMH={6?5_NHl3!lumxzbZd zM{z6_nh~+`7MGsqpisD$)BN@8+84Wzt%21*y5UHbB@bX=_O5G%kC{KVxn&2h{)g#5 zc7Sk6gB%F}k{jRQWr4}4XJqp?oJ#@U(DNjrT@2f=wC$0L-%u`je1p$}{{s3I&xrw| zzX;d_*#Z4<X;&i;)b}V?RxY_Ma7%rFF0mATtj7SwBDiG=s)G}_8z1HRt>=;n?=@lI zV9%P6s_T-_vbbVq&()L)u>91#s4gl0M)?7d|F_r`$aCR&6i`QV#issJ8kqbo$H5oZ z4Mk*~#RdTUilRlH-EG!J>?{(leQmZz9N@8*@ui~x#eY@gISj>_)-)>c+wh85@^17G z#UJ<Z&P+7_q1VS20!OJU5B@!;aa#4r{BMFQhp_duvyr<Ah|g&xBeB0}7=mwtlcwY? z3LAkFbET`c7ef&A+We697mF`;7J;;NNqs}Mz|gDDSCOI3jQD<f=)-P9M-5;itAx-N zD+dL?FA47EwMWOXQNyug!}$n)%D9HXI2q5lsLnV$#kk7OI9<!Q?94cS$+(VCF%eO* z0Py@Z5qf<aTz!=o+H&QIT1)gFk{X6|cPkNqN~n0P#WFLkhBDpRN_=gl@?@>$vJbNj zz~EE~10-YPW*2NBs_kvL>eBR?Dw4Gs${TJfXZvkGHq<TY6IH}$)0EfE_8r=~)pgD4 zt?RE=5^JlJr_3%Nez<9P)P1QW`Ty*GPbE5Vz)!r%=UT#ttj7BoUDvOVSph)%h;6}K zi)m)y%evDQ2Xjb(L})n8ZnWmN-c`lJ9K_L;k>JPNh5@}#RCO;n_lO@;p}*CVBI+|R zi2`p#&rS@b@ei|aTnSM7h^iKLwcPsp6_q&6NFQ4pdX{WXYTfm{E86FT8B))hP~O8< zN=y(p`qstc`5l!&doJ+XXMR`KE3TLZ%9<+N#`qlqI=?gPrBn>#e9v^7{b31SRUuMw zG>3dt<TebUsM}O2FlTs_<+ko+B2-VT3xqKfZhF0J0qKrDOGU~Y!%@Rc|KqaPM*!o~ ze|t|-5j#gC5d0F1{K>MoR_t!kCa0hQ!0_!h*q;;x@{!ZVVYutSmE0|XdZpPhORFZA z1-=slcYDCSJ^$K2X0_LZxB$HwBd&@@&;YK&ZI7v%z->XZC%qgsx|A`x9LTh^@d<b? z0*?`GyU{tj9&TX&XJ^8;9K5wCJQF~)6i2iiY&YS@y)Qz*`WN8ea6VCYw`q+soMX01 zX<}HwK9P5~0Lq+Zt1NYzJ}z*b=(*dq#u(05S<N>QEFhmqyMJg6U!AeH<Z04hU^>xu z|M;Ze8ofGaZ`ITU@U|z)?pDC+ZuZpD&x)p8>G%|ggBGtM=B>Gtv{tW<pE|smp!&ax zdV_=(h|PkkzlSdNoS@&zhDk4qEajiD-M;tE5LyEwqxCe4B8v$pbbufX-vIV^EoQsb zczpsk_3fvpt1&+BDxvW#2bS-CjkrsZ$9=#JWht=uv#<W1Fy31OZg)#Bpo?q=;G;`9 z_n%DI2`($!yJ2P)(~n1QalFghM`4UV0^7i)*5lP%V(;qq@ihmM?_~2!{(Mj0kyGb{ z%}5$z7k`~#{z3CIE9UFQ7pzWPZatp@zf6V@euPX})HyD{<$C)3g!=U3OHYT*dhJ`i z!}90j)?1;c4&;X!Uu%(Cl4ZX|mE&UW^OTnrU(?Qd<HhO|p4)Y9UgW3Dm$lbluO@!= zB7AfiEE$Q)Wmt3>Gs^fhmH*K99j@&B{@i;XVZZ-2cdzBu&HSY7P7|6iJ-EB$e#z^Z z>5$>0>|5-wF+sOOigIXza*Bp>po(HLVoEr-Nk~lIjZQQO{*^BxpFa(fc#e&58a#7v zA!fTdX765kLo~*f9JV%JV}Wi9%PoShFB1c}Bg2aNf3!Y$@E!o`^J-<<D!UbjXiS&x z&bS`}s6GJd7Y9JD{j}NfZ*)oH%{j@iRCX!R=Vc-qh(&3B4||<C-EVV5IWz`txaaEF zHO!xxF{X@LTs}SeF!r!^aC+_N#owN>rc6>?Jw1MK_Pl}Q2*V$g(LII+yi+8X5CMve zxG`GTm0*q~U@&m&GUVOPgddZ%icc8v;7iD)10-)tZ=a!mBnZ~ISn_h@!d&wW7BBF+ zWVEP`yZjbF%*f6R9wWD^f%Ms9bW7$N&NROr);*xiHre|RvA?Hd1t9z2Gkob8qhmN$ z<&Xw@pFWH3@d;!as?vCKW(tiNS!LI)^KB5iqVR<RpgqNy+TJ&p6~4_3SJFuS;!KV) z-MtK#wU!M7S7yExq7A-3i2lRsLr=@;ilaS$Q-%nj%^=#Vav5(q6LcizA0+16tGP<K z>h(MXJIvTa*-_l1O4LziM?7kCdUappKg+lq6B&brT?t93uyEICHg4|nvZv>1NbgrV zDsq`_#WNVlw3ohPxckVHkiIzjhsJMNTqU$u=1ECk9^L-!)(QC6A66mk#hO5o%_Wg7 z&4`S9@yxqZ%#i3u&dg^BRr~T)$MjW)wpFM2RR?-iC;U}MUR7r>%%tPdE5L3A*v9_o zTiLRQ2U<pkptXJ{I}QKXUAeS}4rBO{v@&Fm-BhMOT6sF>`0+=BNqwXK-g;+A`Z1K# zQOnIL4716E9aLe>a<APXw@Z5K2D8D0wLJqa+P?2mqto(_la*V0SX|JayK}cjv*AjW zJ<pxMoj0yvFe3fv$pOTAOZ%#@y>V0a^7>0R(FTeuY)jB886e;LCa^-Z8RII`BJv}D zmF@KX=M2QLIbg->O4H&m{JB=3FY^%McIDs{>2s05aOTOF)83D(m4{P^JFCyRtpkR~ z%uXpkhF5k^5k40pE&$5K@>Q-=z0a9X<*jS08}_a|E$ORFr`n&>TUVhqTLe}OPwhX) zw$88aoqk4bhFz67HO2ilBD6*PLNc`a;nWG2GtGMn+O?&4mE%;`db}lP0&vGm-Nkz^ zLVs=1F?2*eJ!7Wj#1#zk?rA?*3%phNFQ5OH&cCa9N_p!2f-s-eGQNt-Y%=m?x5ItC zIcLORgXb>uX${)qx3B-@<jYRsc^91rUAv}{ElYIDoWfq=9lM7y;9dJenkyPvvP7oL z4*#~ebN1kCH!!kiiA|Y*>K}%!9zrej*O>_VbVx>gD8_x`2*Cc<-2@)>zdR~_dA8Ab zY}g77CJ6OGsvHGSockXE)8~JPe<4RGqkSo(W9*QUFrAqo!9(m&^`8s};LDzc?d+;4 zH$yM$4igM#TIcj$U7ki3)e$<g<-fJ=Y(2Qz^^EMQV|3=r_h#?#J&@a_jXqR|&(D1P z&2^{e!PKs8^zlp|HN$^??&Ds=9lr-ryE1Xk$kCSD%@5CY&vozBc48xy>XiBAqwSlU zN6(jbk~Z))Q3nvuyHiNq4dj~;&z^SlHCYF&Yu{^W?+<M?YrGC^Jl*O0N|(Nu)ZQ9x zrE8oHKX`f|nXfE8>)QF&3>>m}*7Y}Dj+w4;JR{qw0N-M2(~AD4*z2|Lg|=sT`;JX` z)13a^%c0oXHMa*ryV9DaLuAwJ@^8C4cMpMf!!>({*e2Yn)2mx=*tVcGva|27yjK{R zzlm;Q{_^<$qVcJU(LDFsu83*5&d3uL)-28<KF_xPemQ;FG`zF-;Az)i%QmVlUuoT5 zy*c%~YlmHvIE%YmcpCQJ0&i@y0-O!OcT?Wb7az}}@0#xByzf|wgj8SGMAl%>^6v&! zHvKk>uQeV@UpN7ATxPbg6oN<)>hZ4Cb?0U0EyqLZ3!|^LNP70__~zcVOLx+WFR@59 zYSr}k-rgOesQv`Y4u$Z&GRc)w_PJd4rA_vQZuXU@@wpU<W*W;=MD=4@^;3w$W3t0j z%-LfW>fs3L^F-|P0?YA#i2Q$ed>WS<UtQYW=SyGc&OGD6>SG-_>GH=7mX|}o)L&#g z{11+Q^Zdv<*98l6^)C?rFNXhmssC8{JSS|f(iy#uV>^)T`}Fo){Y3N}<4e<7w+_8! zZjrG*3h?hIzdzr3-wVAM3EwMq#;(tw?cLpVJ3K-@2fUK{eSdpMz<thrW%c8&r+AKg zrG1kDzAXDmj$*HVJz+kFzfzLC8_hme3GgZt8C78~K}8tLJ{Z5WdUAPgc@^~Q=-lXB zpB#S`FTs6?e4!G)hbA#7>0B}1tiJZU(0M3-;R2L;nQ!H&`&T^oAdwfPS4+RhPV79p zS9hQiU|Qujxz9lME3sd7=lJ>=$vNs{=yT7j!z;STCjZ+vzZH?q>}!>WVxT7A|HJp$ zohju&U%=-#)VCjgkX}5wE0=H2J|~TSzdDcBug;!OpF>|M-fG@b-g^BGMXs`+Se{c} z8QvP+`eA*q0@j~Dzk0u2?KM7;JjcEklS+XE5#dQ=VM+sM#L`IZK+Je@B<64(NbE4i z(8jQ-uV0ivd;=Kf$hFXmL4*^48ydkG)-$jT4U!ttq@C0ctON-GCK!TJ6q2zkR|d*l z6xtOmmCFQ@c>@xhoDBrQrwYL}0U^W+!SNkJz!8Gy96|&xkTooDr^Qf}mlgvHIRd)N zRV+NmT$P@d2#h<Z_H7skoYhEGxCBiTi5@yBh+b?qM^9C#1bqg{7P?_mFEhtpm8FD) z6Am8+Ao9WQXTY$GCK$njaqHpqU~<j_=LWsO<%77zmcdx@>rwfAUJ;0bl))WMCaCuD zT@kz5Vf@FzYV9T{_8->I@^vNz_95-obBrfMzzSd>0|Qi15nx~?0&}~+n|QF2gT<mp zA^0LmO9)WEBZxxmhs6vG?=ILVHgN`{MJ|Gw4m{|NGO=W3_(n7W{~PAY#8o&E`ptpq zoqs1X4oqZV-vl#!GK~K;Scctq^7nYp7!?TGupa{(CX8{P@hecdp$LMMx-It|;2U9< zA<l8TV@#~RGXP{0{4LB=;JB3(ENl+p^P5khMEB-K(}t`gCoc{msxlN!kVf|bsqQ#& z2J)EL7h$m9NX#%Pfy3QN8@7&2_d@p+&BQBk_ApI>B9I%S8_JG6&3A8J^H1GD<7%~M z<Q`apD6a@vP+bM!CEXjI=j0xEU@0&Fn%}+Ny}V&~E__b|^oAk{2h;sz`MGnv4`eO) z6)}sDr-KiAkTz3H`^~S*&yQF&zVVGfIBC-k3U9J{!|fxxgmjgd+S7XeY}@2{^Tjpo zVD)=X3WZCEgAj*?T!V%h4nisgp`?P4TgLA$a?v7kv4(On%E-)*|Iq$Ol@lnL6Uglo zs6nhq6wMf+0JKkbzlL_{_Fj+?JsC+MxUh%abn&~vdtsom0f`|vsfXTl7RYo6RiFcB zw%~>ye$&<OM(;&{1_va9;OHJ|ph!t~K@g~^MbZzh>~ZMfHeLR1xFCFt=8hx~>^}yi zJ-Ci>d~tnA+)>4#Lxg&aOxefLZ{eRpUVgrknXm%|4@j`VK|N%f6OQkB1qsn(kjNB5 zMMCm>*ftj&4S0n!(3FvAf<=N8dgwN19QAmGGSC6DQ*fPx<B!c1M<ZSl1GHB{W+dF; z$Q~-7%tyCb&;Y#($q!y9xV(pJbIH;0{$sQ73Yt9<PjGq<)8?F`ezOpeG5h*?0s9o? zPPCN=u<M|reub4duixAR(jl@QoPs#Ss48D+dNei<&{%P@kjI1fdJs4J&ec8m+AxfQ zYd&tCZIW!>puJ~n!&^gmLjpJ5%sgkFx%>IF8FX%XPwPYYiY*KeuCiHo?s-oRHH+JU zU>xf3vr}TD_uTMa_?hMz%@;{TiY|{OFHx<G)-91*KAl`Dky)O^BCI0{gHy^_YVZI? zt%%kokqSakYBBFvbuTPl#Xjs`$o+mgt??h^9y<y_O7<_^zrjMT>WhvY@GJUTSa4e8 zy=+*oY{ZUixafnFUV#iuy`{O7`;O?2v{7QlDgm_GJMgqTUV1|8@CfO?ye+kG+6T!3 zxO!tve)|7{`hO_>7ImsJe67eb8LqrEbdMOgX4W#y+2}(teG#CLFbZEPI-go?ns%|B z;18hBM6vO+#O>N{hWZbhza&GH7o%2O;sPK6_->IMksYx=WQ52~+Dmk11OP{J^rO@Z zg{bx)JRdm%Mn)npck;Wn2PZi`9(ZjYN&e*IH)}@8ZSr$Gphne<lkSl&jZi7PNP0T& z;O*5|3Y0)G5ja_4?aoP)Mlc%rTLv*NJ3n|bkCrchRu6+I8Ysr5aIBvkf)kXfr`IC_ zoPp9udB*uSlOfh0>gkpU?ZO+Sm-9}5_hfBV&miyfDbYt=sh$U*d1Fx|yBsHT_Z@)( zYD#{5qR1E-n!JR`(tTG~Y6zisnUP~MxOtJ2h5OE~R6p<yBYi{F9PuY__NAdxdF6$p zxgI%yNPqaL^j+T5WYE4TR28=u;S07<c$PFk+fGLATR;)ww8yMTf+F*qCR_Kv01taa z1H89=bX$~&zv#9#oep_{9+3`S!wlguG(SA6sLlv*Pp2Z_Ohg5<(zm#E4Ag5_WiS9I zlJKkkbs%r^>=e*!Vn8cx#@TNsNNvUrlZ`&jhFQmkdsTxLS%WoPgHc|Cb5w(#UW2_{ zgW2kso#F%QOW14r?AcEiv;EU4uGt!?4I4LBp_gh~-RYoN5h<0288;=Cp%;5wo{f|V z$fQP>_swqOJB>DLBhf}4^}20)IlVNCt*|QJuJ%Xga)u|2>&B+{jc(&O4Zj27G{tmA z1Lucrcc-Uji50d}tj{s6y@uQN7oXX77Mi`06me+yxKFX~Vt^5v>=5@ZHX(`b!r#M0 z5N@ga0_0&Wh(xX$cmYQXvf5U=h-KSZ^iV|FkNnlQy$uhDR55yU;I{`a5<TeafzoI; z6P7Hz@d&G507H7w_O8|r=!WJqddCt0?tKyOVFQ#w69dp^e`jy`*6c-^hg}=<E0+<8 zLl{qg`Udep<wf#4O%tH!nfNRW06NV?jWRZv*9guc?|y;ww}XI65Z3z6KA_V1qUPSi zhg=x`%lVIs1E3#-TNpPxHbG-~EApc7p1oej%%uI@iv6>vk|vUDRQFXs&sO?H<^A}* zyAKV_Z6r|4ybXKNbFY?hJQV&G0kD?aRu@<IQW+VdSe+5ZzZ}fE%#aA*1&M^O|9b1) z@ZOHSDE>)@;HSoGv8hR?j-_nKtF&1kEQXHr>bKy%_qnybWVN;N#C^UI&!zvHlkIZj zXS?ObKR<UnhU0gFd&VAq`^{Bs2}#FQRi{VO-YXw0EUBU6+3_{VO5-?XB`M-j<YLW5 z*~wEuBeFP@4DrZ=F*~B<EMbxjScB0!VwdC(pl4ZdN|f+XI~fGB;5b>xxI9_50$z29 za9cWcgm9r0#BhF-0!DQdx>!m6FhFll7KcI(s2C>SGYuWe_R^|jmIg~2vZ}+DM$SBC zuY+UU{Dg}zfs2uRMI%E;$VG=SMMv30_y4y70zY#Wjff2mGaxK@AuOm_cBY0@7=x4y zV=`Q_3e6^rQ~cGNoB<FMMQ}=_Q80m$Wf=;%reJI$>m`;bh(Iy2GzA<}&<7E&5<e(} zKv}XZ1w2!*2a(qj<n(divOA9;u>ljxLsd|&tRxjXAzpx_B>BYvtvM$<3|?fEL_Y;4 zD15R;4%p)$uw$o&D9VsCNm`QEffffctR0xyQNs;eq{xZm242V_L4Cl4MhB3CF%_cP z<mI4Q*@B<}J##}&>2|hS@Wpr0H8j=a>2XZ5Gufm7oDDh|KryGOMGVg%sf7(cWUWPA zjFogHS1XPp6i1<u0p-hThR1CWz*ElAQK%IMX2h`HR-o-LVmL))$S{+t8A_8UNitLD z<guAyw}cqT*psTQ2d;>l%{#{l3>fYZJCk_&3rZ4`#m3Q0))dR`fW_?%Ans6IB7~zy zw27@rZwu@QU4lP^`G^Zs7=x+@cmU`Q@*!MOKK%I%b1qIq?Ntgh2YzzkDK~tQ(z@W= zpC4yVXneJZB5{p;n~5-WPNFp8QGZKGj@;BqMr&<O0(?GUPFQ@Wh~MJ*G0>x!7Bh7@ zaeES1`Op)*^`t;5H3~-zkfcm(S;KQ~VKD_KOAqJNwD?%J&<^LL7X#ER2EO+gzaI2I zP6qTsYbDOI1?yfqJ=j0y6m%>pHY^$VL`gc%Tgs1#V!E7jojGcIK(ZEEQ<92PyWy`9 zVpa{3OYQ$Sd+(?wxV76Cq(qwZ-jt4j^xh%#8VDuy8bmtMs|XPgke1M!0wO93uOOfx zgh&(7fb<%=s3;&+DR;TsclQ3yckVs+KOMs{7><y&o;9C2e>2VDQI^W1-<sz!e`i88 zpCvvAJL?gBaKKZ{Fa_LEFsS}c2F`gM$Law5%YVQe(js(JtDW)Bt}DuoS~Wvv7_*$N za5%QoY$XFk=Y9H?&$mP%4{{40B#&JAjK8i*&3#Yb_^$rkgPqSJU_(X@ZUbFFXu+pn zuX*s<D~wWwx%`f~flrm}2;#GU*d-2SD5#R<%}Ub)R|LNIGeejt$Ln8rt{K>YqF9^H zH{?86oH^H2Kq`zF{2Rslr6UrbZNoUhg^{Fx_3n3_$Z8mw0k}Bur=N-UF2`KV+86mu zzb6tyt$wdU%i=*D{?ljnJ^!#ht{9$9x&VN8!4G|AmV3a^dB?>7?0rWZufG+Dfpli{ zt+P}ejzF%%yG9-r>ho4x;OjsROZnG@`1ChAuGK;K*3YVY>c6h2{H8xmNzm`Aavcf! z9JvPpt5DRL{&`hm6REw9_yanVOhIg($6%wOXcLpYv3P_ee*uR{a&7OZd((8BJ-IkP zOZa7bq&QUp^Uxjd{!lmNCMWwqaoPgbj3eBxXA`@fy%RbY>49qOv9Bqzhlz(~*@rwO zwPgTPW#2nD`gD8cr)svuPtt7e9*B9`G(NWXujPBHVoUNQU60zMrAfu!`6<sGH<3H; zFy{V?;t`s3EXVqpeMQ&3q%UQ#y(JQIYhoWRN*OG=U0-x(b3}|pRys|OnfrybFo*Md zT%35fj=2717GI$WI=>Y8z7lAxS+)Ni`F;mCi6&cnzo#@4EPkmi+4my4RXoZYKiIQA z{d%605srK13A5>s@#t(^u!nzYdSkEoR8xT{qoFp5ria{Mh0b4urCyk2JWO2SCmCmY zuV?jxt?T}#a`$@s+*g_?K=&4d0(<Fgv)+g9pPJaGO#N9DR8=$~8Q0$em~>N`zW<e% z7acPtj(;$U_ZGM}g}XLB3hJ}<c+xn2UY_nOjGgfK+PH5&rs>JqWHyELH~IG2_U}{& zy*Q8859YG;Qb2oG{8YlX?(?q!pvLP8fS8l2-qnk_%iVA8CavCU?%q`FFvb2&JmQjS zwqAz^Ym<rnn677To`+qN-$)eq>m)tnyS=vIxIoXy#z!-rhmDVBv3wipdaEAUjs5mD zkEX1}t>E93K{01~XOGMI58)`rHOFt<fb8&x>)@UX=>^4`O+ohX{ia7>JT;qKr-HuG z9<W;65`N3L1RL(pCm8K`o&UTP6{<$YQ>vO~09^qHi1WkF9ec@?^TT1fKOhL7xBrHK zFyP2Aa3T7bwSoP)Oura)cAoHxh$r<tvWwG2<Xuk`z1qtU#4gm5JXwO<c~PPraxUaR zI>QaEFmFG?^@%OzPAvZy)FFMc$8V)c`DxUu{Z7pPLXj{q&M-(>@keugSRrB!rY{UW z?&?BdZJaV*s_>M4yj!aD_B?XScCOFU&U@Q1GKBVUhlqCPR}@Ld6`pY8sP|V0^gB`3 z9SHv}WdM#$??)yqHB|d2w`TPLCWP9Tp`CkCb?5OLAEH>*ereu{#Jyfo->!&~>`(+k zP{twd_X^2&TD+Q-TbvY+G9*q!gPQkVcDKRu4tOre@z7^y_x3NX>`<I%%l(-%Dl;vx zo{>c>|Dr)uX7xX#S-!aweH0f*{D#gorQcStuaID};~kY5AE)Q<l>WSj|JRQEkwYB! z8=mZjx^xf|St{L;II@l7e8as+&pn;~qbG7Dc6&gT@O#_d4#nF|yPUd>JEA`kN%)qi zX|o!%!wAzKTdCVli$0-FV9A~%;c0g|xsX8Lm16LI#ctcMcE|5%|9VH#;@hC5)*aO& z=M$a;-o#r5Wh+fVsyqEhjA}3Q#CS&TY4*DkBzFMD?1biw1;{V`{Iz|W`o|RKnf=eW zmR)y(jv`MWXN=igq-UJx$>)L$0N?<Hdhk)?q7C&0ggw5#qnGYWheL1h(c~5w8oXsH z9nkU;kfAS57l+#NIqs?agAc*Cs0DqKG+?sIzss15WDJ37KcIsZiRds1-lgwNXK2!N z%@bkH%EbxtC7PfG-_ft7Q$qC~Fu;l*>A(d6cPyO)YW9GIzMbsBC0OAjgUh7GZlvbW zz=E{qlB$a(ZWjv(7b}QTw9-<b11SvUu=F$+9bxJofy?gn3QKhK4JigkP^}bb`~%{V z96%Kl;xkWw2$g-HJaYTGQ8S+dV?f$Vs4Cy6_XCoV+|ST3p;vVD`A|i^T?mx+fiQRp znC)HprT_dF{b@S!TP+Vd=^{2AYQa17xh#zQX}M4}>AP%ZnOFK4R?>FflJbTA1zn{` zd-Q_uAygStq;D#Wq?1iYKx=xTP<{|dFn}f$*lURku+V3u3%<4D3nhOW%D0?jZ}gPU zmeDV*1-j~;J}|_<nU)1z^-3Rp%kp<5#M=rAV^9M~pPM0gKo^@H|26?M|K%t_xr9Ih zAl(!CmM7$P+5rFA>xYKW6M7%;N4kx)pU|52x4q{kS3}a%lmwp9*`@ov4PPb?$#2tp zdm<K+ng%aSJGnsb__`c8_yzbl()-^s0@HqGlzGQx7lx)MQ*Zs2X?6;t3_650=y=mD zpx@3Im#KgkUq4QmuSGCH|2X5w?BvSXS)zB5si6>`XXJ}~qk$SP8JSR8FrfAE72h@G z&N|<eC@wHHcqlBJ!~O>xAwvbY5&B5sn>o3CdF=ypUKQsF*Cg2;1xw#suv}glxb1ZX z6n>|O8?*3d<kRPS8U4kCC=u5!5FE-~8>IBAdE&LoJMhkn`LC;ptf%G^m;Lf`BQN{q zhY!5+8uR``oM21OCuNVnp2z2#cLkBhAI*?+LG)~Kkxw*NratFteQs{hWq_Ty!oDf$ zo1dGPcWpCQgFWX8qS9YWA@d$o#aKb8G{<ZZ>2*^k0>U(%=MTscvpE5Oun~WeOy_=s zMhLymaUKl(J1-(LPK^E7_AgrYCL;g^&nFp3@~SCXbql?yjONn6By5nwKNtmgUnN|+ z_XPX(Hu~}z2hvvsLS@)PjLZe=a{tAODAWBQ2<+*DWM1E1hXV>&Q6|@gcC?fJHDM56 ztUk3_y%9<Sy5S6-2`lC_g}V=!ts-UCFAg-UDuk-GC(jvu=Znmb9q3%uka?K7O1yhH zT4aVt$nztLFFUV)U<Gi(1i(+M5UQ@Yn^`3AQSgZMeA)FRBXLLathej`@RxJFoQ*-M zRlQw?=;96?7s2PblY^YAX1grWr5(Bpf<Rv%gn-&M`r{%nxe8Y1ejH?7HQ8kby==Om z{5JQ;AnmHbF5_|Wi4H)^<}MEMu3GG}9+#fzp4Bo~Qq)7?9w17EHr5xc1CH!^IQ+&{ z8ccz)L2aFkC40Ro9C?)rgL$X#T^DMpT<-)Ayh@8Hd}pv$M`;-X*M3ZAQ*>2_x%Mus zx1IrR^q9$}<f<;F_8n}ko)WJ2n8Bv_v5rmcW7v2-2i)v2i%scc-SOHlu!|@wHk37~ zo)wdxHFd8QfKS|F5XsFGDYg>9jEa=Yh~(c!>rJC|+tCKca4i%({xR`*&JC#i!xBrg zdL;bjV=@ru&}(@(V;N8%0gru5GM@Vd8vgK=rE`5CJn}JQJpYT{{=;9E@%0Jt#2ZBN zIUG=$hj%P>>)pqKZ;;C8-3640zcC_iaQ#6<nAHfu{)UIR!69E>qCH%LguSR&{u>*j z(m_k2h6R>UFF0m(gB=t{X*bl^!k*O2k2&1nZmF2j3aC+lmDWp)*#aG>92kddK;Kcl z`k2cN-j+%gE$*62u+)0~F&OBDDO1rduQ7+!)ys|{zHo(CywY;6xdtn&7aOwyqEGoN z?fIHOSZlrNnDZB&@X8o1VB&>k*9(tXe_;ovU2R}&ggviU9CQ4_y<hPQl*wtpD(fZ3 z?7ndBmjnN8O#-Z|UUSS<g}6M&94h=UA8)kj6&9*OR-R|BSN9Om<u}8^VpK@VbHPUW z;R`%s(?2Xi1yY{>L2u*XPki)dTo@Q5xD8lqs76qme8Bn6=3I77yRgP&q;^v#3<1z; z70<NnYQ#n`n^(hZfSObOOnb7%Z=_{YCCvF1PZnMzYedNmFJLwzH;fk_9#NyYp2Xst zUf_$e_09SlD8kUO*-W+BB(~WC5@tAA$BC!e)DQD~MKO;K)K{!?#7k`2hWWjsnJ)-5 zXsuJlb8ni5`Mjb6xfK1#x>&sWrb}4RE86+O?*@l;5Io7I_MThJMRhcfK5d-=o_{kc zhDp7IM>o5+e`IBoVh<X_@Q3MOQCm0iX_I}=6qrv-D|A2BZjAigB-_)8q3<km(UGhL zM$t{?J>wYW&Jq`0fY%=Rx=FLAAH&#Lyr2_Q+d4A4$-QSD!`fL27Fo52Bfo*oQyWN7 zMH)K1wZPc9$+%|(%$y|}x|OvbM>aO8_Vj)+#215yL+$gC$xY5ZvtKOnrEhc>Yk!O! zZbJ5S!3|cFprct^Ir4Fnb<gA%^Jz(fZddK%$d66hJp=HjC_d8x#N?61P2N3=U#zF4 zfLrX%AVpCOHT4jp$VVIX3HVq^i5A06ZwS%k7Z~-|_{d1H7yk#f!O1jGh&I3Q53qq! zD&!Ba!MaGahspb{bZ;?(snJ6w>k?5M+8bm9iYZO?9x_-L*Z07^A4`uHbC{YvWU(#< zW_Ir{(if9u*pg*Qb!C`zWvOv8TsYZV^lZ7gY{f7(%m`b#G+TaBX75xcuI(RqhyMZ5 zfSi#ED2_0VeMs^tck^u+@|BcxaiD4BL&&H6&E7raFRA$A1k*$$5xAV*QX}t3=@z@c z4@Q#8=B4|9{-t8+_x4CG*^1(BQ!gRu{9@7fa3lxl^TEFNLQ20VR(|h<<dLmJbc=hj zNM{razPCcMzbHdspL&5}o?`j;4oL1771Q1RUJBBs#S-srk(@8efjiGDLi%;F`g<2( z#;a8B=K33Vf&V=W6eX1@W6Qiie@?ONd&D}|&5HJJP?#fKSS$v@8XPyv+p%+A0P<g~ z`rdh+=VoPex0)A^bat`ud+T-fpJl)y=j9^(yjbzQ<2v`xisSA$FAeF+V#)V*!1z{v zj6Ly6knSqheDA723@*60Ldg6^qiHYyPzAEmJn#xaeroic4)c#uASulqev3rDXhcl= z`$s51O7n+%*O5OPqo?Ei6J8Q=_Op0VHKC^Y{9&M?sZ0V38g!d#r)B&RFS#5m8oF)0 z#F{YESN&~XayXVZU?;r%np&n+{GDI&WHgFoG%1-h3Yav>4K)HlgBq265;GzlgFxB* z9n63jaCkbb@^mQX=|^(^fe9bZMw)4Te@}qTLkILJ_&7F7OxybVy`-5f2<U(5quR(l zZSL>$l4=&S)feFt+o(S6;ve*qcD8V<|G)>*NHVSc%`M`hDw@0Rl8-?n|8!IYlWGY! z?w)sl)5<gjxXBq*i_3e=z3Z9)LE)Qe1dD2EIqriuFpW%;0eC0<>mui#e~}X+m|vGT z<DPj>HhrC@`KBMi__}z$2ec|Q%}#TFGY17JrJzs18yF6zNxo@=A+1QghsQg+sek&P ztOVRYPzeAr#SmKzUTogLBsI<XhmjCl+KB`E?54wM$TwY3?OYV!qv2iI^l_T?o5=z5 z?-F2i@&*+o)3o0V4j6wIpY|kpcQq|e^M129VEtWsiaT3l2&QO<I(b~90C}`N!40dw zVH0j#qbV#f>95_831)9M{TC-;BQ#jK-N`BN8f{_WQ2*KnWpId-HW&|!#Cn+5?uPWX zGdLMNW3np|!(rCmh5Vm!2NzRA*-~$k8iX<#+@$Ug<?6qAi%}^zU#Zwy3G+#*TvjPR zxvY1(4A)-Pf9%waa*BUOJelM7R(`!C*sLAtbn_Y6WS(Dd%lb@kKzoE!>>n%wkgeBW z1v|F~Iz>K%Oy+;>-CzF|9N!Lj2!TW(Klheq{Z6oMyF0M_kSgY7Z0Ltnw@c622XZM^ zly;k~3Wemii~esI2#S@C-T#e$U>owJU4G61lwefMb_c8~gp{^R%-IHVwwBLgw^l*D zMZ5Z(OCWD+rD`|#>ZOp>cK$iocecnfRc!exs9R~5okM)*imZ6u?Ys(nFQAmd<~v7Z z`D^U_Dk!07SDkbI&J$S~+x>@eklijkXAMltWwF@KRhN+G?TT}b-?<Mfes{;OYJ^m_ zOU~JS=LD7%?CEMkNLRb&oT~;g2-3Y3UeDh)I`)bS)gY_Pv*@i`|FrFU92OU&K?0_& zw?6AHwh_nvaS<92khJUFSpT^leH<5;@P>%D{}1#4b<7tBd&A~hCW$RvHQA{>mWf0B zztIb_w?(pdlq|LdEOz8RZi|21QKOAYVvSBOj7Hf-XH7;YD@G4Eb_}a_48?YQgv1R@ zZg6hX9P7t<zM)t|2lXj#IBrWE+s63;reQ%)f9r<oHutf4oX;DoMa+-B$c@--^<$T~ zpf|LOg+KZaHz3<2$J!@u2^TfdynVDA2HX6{Q3*_%CA_%owf>!zV+s%kWY8?G?6Fv@ z+xc|Neqsv9hozOck82w{Kaa`4U`gLq<k};-R=6{C%zR>;z}!{hihI5WS__V8PV^HP zfj6QjXsvZ;_L%#`95fM>0vh7l;m+@4k`wJSy2K*Q9?&_k(|^o(VsyroSOU<9Yae$u zj;T)c&KMGlyLw#LK!3n7=ZP73BA0@`fVCexhsO{w!O{amLXYNJ<<7@r))SL6W`O_4 zb*(M#{5YmPF*sv9FFx-{T<h9dJmx*IIAc98J;$AsQE2JpTofQT(z42-7J!Iq8Rt;e zko#&m<XozOuxkN^z85({%QlC`3!<!Lo<p@t9<Ak)L%Rwg1Htc$lu12R7ey%VCM{Qy ziclCQfi^-Bs&`4dRTmyzyqff`it-WV<D@TD<c}zBB+XP^dPMbwn6!$BMCmdSg@_gj zdE+e-H6kq{zMNasOjQ?XK6eud-Ri!e5PXYDjgU-~Ql)X7h~u_?mGt!sCAX1P%GZe< zZrfJLUniNl9Z{wJnMmcfd6n$v3$JbmR;hj_j=AkprTCfT*X@KVO*SI(+uCkYY!~j_ zc6U=^Bi6qiB}JJ@?%8cGbtx0V*bSAUFeSI{hD*_yLS(y5rKsMM-|TjhqJ0mc>egwz zC{AwDZPiFE4iW1%Zlrul?$_<mc<CvGvs=HB!k^r++qRL$AEMfA-bnS0Jht1Vk@gz| z(ybkQk&E1*8x~B>1rhEx3Z^V0_vuCiUn+yJcIyRGIFZ|R+XT}%K@_{qf~n@nBfFi0 zY3Crc-MZTs)yOTnt+%PwAd=lC+ms#TLEVnqmpUN4-3HqfapbPucH1;@5Y29jZK@OU z#BSFsNja8=0s<^~7mZL}I-yrkIaY>(e~=Wus4$(FE6F*q0Rb--fGkA$>qJ~h&9NR3 zTxHq47>$b4Nw|NDPMC>_k^+U|(}CSDvUC!;f@U(Ns71->Anuo0x;(lJXZoL55&&Is zi=s{IVvQC>bN9uk-4q=}q}p_3Mmc19mSkplGF>S$k$<5pNOeTUSUE1zp#GgafwI-{ zyPt)(y)N9$s&bJVWv=6MKLc;`StyJZjISscouK>Kc)QQSd#vOaNl@B7ZtiJPa5f=o zR{e|os3>=|lmi=oCUYOf3W}l!>YgWsDB?3^en{~N#olA;ULfUI#Q&aoo#H2otVhQ^ zx6$67Pn@}cVhB_S82=Yu;wy^gzt|GsCP#7in7bD?I!^I}9sr8pD3TuSr5xZW-~-%$ zihdMhkI@nuxCi*lm_JZ#ps0HEmhymCfX|8f83jN|^q4Ib0Am3E95X=mqaZ!HOS#+j zQG5W%Pw^4O+GDbW*>(U>Smp(aA1K-$gQfg!1fa1pgQE$>+heg*xa|lisLYIM6unRn z59#zGxT%m3t96=aFWlpXbXJkAsqjNq*);ZEQxBwcMv={XAtWp4J?wSz2$aq)vU@MQ z&PtUQ@&_dGUpxo~52Gfuy@NPEP}kGfdMQ2hn)2)sK+j=*l0M$c;bGQPVDI>pe}egI zdRp4uqO^<@!@Fq1jLd<%Wdj*nOi&maihx7^ft^TsAUN}Y|J4KGUmln5c*FxVsHMMv z0!wL{SufJ#W)o`4%3ts$%WPUeZv>E+lL04KAcEy}nsaZUM`Tm#l=U~k1D4-u@x2Ki zi6OU?EV%?Ov81Ny_PQ?zhomT3WwIKiSNBRU+lQ1Xxs+WtXA(}&2m5SzND0_tU-`h~ zlm4PtdD$tXLdn(X@--&b^o(A?Wvh_lHYcYmU?NBdO~ik&5N$4Vmjjs;(@T3LmTf~y zfxYw!*d3?8?p0rQ38`#zRlCf?M4O)4%fAfUDT;DZyHdeqkzUs;yNuW=i*f<t5|d<l zVXxS-4OsL#cU)Ou3QBM7Rb6)8sfcp@Cjdft*?On=$SLm18z$HE=e>%{jyvT?E+?14 z-H=|{E4gg9Qwns=E8xgZ@9NcDb`?!RTN(=p7UUTk)p}WlilWd~#)7p4qlUh<VOBAs z$!OR+0q=sp3=y^dRuQ79XzO=^AbD&UT^nbWP=AX_m>ErJgsSEH8`i<;>J=bL7}eIw zfF|}bxXa_qHt4HHnA)pWHuWWN=f_vZ(Eu7*t77F`Uy<?;hC~h2sQIlS;74?j3TQJ3 z8s!P<SqYkr3hK%TiXieNl=H-*^CZcvM8*p_3~6fhtvmq)AAUnfzR<x?qSn^RuRaSr z<AqxaRSdan&8>XEHrD2gP<UaCp?a;0RZx94cx(&r7m^#2)M}5qfki8vLx`qO-;lpH z$`>u?z`>t|=`&iXr5J_!=E)&S_{=a5jXu?~kDB@x$T^nq4`cpDdl=R6&26@K_%G6f zFQ(bSfxiI*$`Na6M)iI3n-Md70hpIYv$fo#=Dvl^jx+pQ7~sXPB^lM;%n7qs;p4{K zGwQEp1QB&~n1c#`Ip%}WMlIE--ew+nsPj2vo*7Nna*mp97KAyz`ggEH44*ot!sufy z>!`^lX3rspALJd4e$>*A8f@n8A%5}2W8N4o*7A;8Y!>c0{^CEyFb+_xK|?*1(?QR> zkZ_^(fan@L^oDX)nJuWHE0i5zUo#CwDrc10d=T;}yg8t}<`f#JoLy%3L3pE(Y9J(3 zyFJIr{u&=ECS$O7jR6oq&`u85_zN*ZgKKM)z@n4qgm}hhhj}tMzQz%12IMuzXZ(|x zuY+ls?}{>qQcT~WO@}hyzbkt`q{ZR|EAT?tdf7~PIV*Ts-}yHtM0|VFoMoVZVnOME z*%~tRW;<%mDp0VsV0Iv2Eh01)=yR~|0+9v49=#SA8VRb$tiKB$7W^KFUrPv01dCxy zz;i7~9nf9-2gu=Gp}}DFn)I%HbeWn<#bpb$@PDT`DDOH&SE#wVT$V($4rZ(g?pgtb z&dKG<bF|&ylQntJW?$anvT!*FtvFb^CIMper5(<|S&NPwe7&Z=>k?hr;i_?&7fm~u zy2if?1Nxm4Ai$z62J6;jLA<Ff&gIQzSG43{;hNa44UqGk-&_I1-C*mQ>aO!~MVxEG zWiYP|X0HkFS_5^@Dd9>N8n{*06n7nu%THW@j})yrSh*&-YX`(W=d&y4=)}RUHO*aD z!K6G(qZ$F*JP{*|mvN{dD$mNOw#If;#1|8093z;V2OF&Mvi(a0f$=wv5KPUp9;{up z-4%((#QniGFw`-@DMe8jK4VyIk(HC^eKZ^ZU@$Vqh}tqMm-;F={HiDhbJf_Uwgh}P z?}IOxXbVQg*txdiw#cK~qHQ`NH9DfrJ%IHf+HrwNo1WPymst<SY&OEIE6x1K{%(WP z-6v6ZpOYFt8nfdNp~2`IdxCNmxbH(bI|mU7jIFU>ZPutQ2sGQNh;U=fjeTk}Mr}49 zhS>qeC&tA%s5X1lZnJLBj$DKUqYc_#(`4Z652@|+MffpM-e?&I_UcR<P)>}Ycn9^) zlR*?eFtvFo`U%7SA54aKI^MZ|*&`l^+Z2cnVVK_;dt?4`KvX}qnGpSop#gem{$Ggc z2jGP*I*Z|cXYO72m*aHxH=6^|-x!j2+G{zX_R0^qZ0?EnV;J8Vt)W95l&isaM05i~ z1-f1G0IKAHlg+b#(icMi$zH%f-s!I8f?v7^YBm+3A2F=&Ox7^q_o%wVW<m4^h875~ z`QTUML7dGS(M1gJJBzhK@M%|{*f2h#7>C~QkWVjxn>`e=vwkEx4!?0jKC8smtnQ(m z>?8JZ(;G<nj1rsShe*4dkCexqZUo9_m)H&0t=myO3b~=(lH*`6@qoo9qrP{X0i3L8 z2M3Aj0-K@wwQ))ywdOe>00-CRN&WaZ#|^WV0uYa{28sCkw7ZXs?mkH|evCGLlKJj& z*}ErNfZc$BBW&O{<8WtrxHal=?abrqSC8v{-Ke^ABfcdGh_*Efwxy5E#*sH}wxB@P zz4oOoKrf6(+=y*So`C@g)%Nux=kdTBku9kpbzXa5`}<M+c*2du@LMXDKvA_#eWW|? z{v{Zob*-}O4C<@LrN7t%dDW%7${a3SpFb}81s-0a;#__oBxdSgj4OX}3a?Ocb*{Pw zXRXf|7yM!sUi`|*`96r0*FPDT|Kb3|SC{#!K)7Ok>A1uf+wjs?&H%s*2Ze{@>R(*K zD_^;)SMk7U>r==1zrgm3Vw}|PSHLam>&E}VQ|PR6flJmGj*ES<*)NH4?!3PM2PJvq zs$ZP<D`H&Zt2E%e_1WXXU#$0wK@<D^H*nYb=i`cB9D#7_a$1!D*Q~D`m;7S4U;4}W z^gbv*ukRYy{NgH+RA6aRBRG+F-KfROAr#m{tW0WaCq}RPwuCvvNF*1)hHAVg{<@B6 z@pp)jNG-4)s$HAdy&l~X=aA5Fi=~cvjM5j?!sh^MD6(}DyN?+IoRk(B@Hv**x;&|} z8N2F>X}RiP(@<jT{N(=l*bU#778M8QhKf7aAKme7)4yJ$@7vsW{b`?X2f3U!qr6eR zyq>kZ*(Z5jS@}nZk_P3HC($L($s8VyPjXzRY0-D^1ja!)2r5p3KH(Ny2fv1_30uFq zmPwWC+%4w+Bq;ogp3smzVfVFef0Fz<NsIQ3TR@ru{BPid>-;TI0cZsW&g!i3KHrrV z3V>S9Q$UnHFdKj9`>BN;AUg^a980T*$Jc#-wvf%}1mwQ7cYGi*Uf?^_!aQRPE=~u> z>W1+N->)q+Gx`DfFA=j30>)qZ&bDyRm<JTTbeyf;8b9#;-9iG?`kV-R)d$?;_k8<X z7y-l?9pRu_4PuAB8!c2bdRuuBh}RE55b$qw1hcJz2*=meAlc`8*aDf+-O2@7y$9;! z6}}%^SZ7SY4ebzH-8sJC`=f<+#$YS|0P*`l{5S~5weZeZY!x0j{;ob9XZ%dD4~_8v z4oA4fL*Ys5&!YQq5S7fTu(hbGo0R>`zHbT&jx#E3K0frBy!lyq-zg?gJ-fp0?~sHL zum#8g)yEH5$1^s2_Zec0I?*l;lGPv=v$?iU8KVcvCK1mcfRM`O_&!IBS!aQZ<MZmt z@voa{_r4U}`<i0@1#SK{^TQvgf);BStS}7mFQ`K5tJ>LD)vsUG{f?<hjfw9}TCfbN zQJesYlYL~&%}x{ul+?CP%zh5okBEuwOkRNfsEM2ajg0$&F_E3A3)Vm#pZNVbem@~5 zG5(f@C2tMwMCxbVeRm)mrD#}XPa14i?@Rx(k1x}3sjRXX6W+|<7yShX%DHpp{f}cl ze@7t1S7^Ap{yY7^_5SlQyUi#2^1mG7%ip*F0`i#RX6e4fFI%9iJ1^e<F&4S`dSCsQ zOMK-USJ0#~M!T81&;JVsWOgTjL>{x)tlO6b$=k977hv5PliV!a7yD%cRCnjD`-@{i zo2~n*;9FOb;F?&aImWx0y)XRB8i?>tiTAt4TsNQZEB<mkEkAPsKA$no&B}erUv@x~ zcRs&=K9;!IwXgZhl|LyLZ|EhUkjG|}<)t6WkIEf2^sZ4DW%JDn`vX469r^Fb0|h`l z$cocXsJ=z-!z4$^j>_T#3#lU5oQOMG&X~P6OGY12T?Sit<OY|!%8tpps&7+W0-Jy2 zJ|+j2P+2Pa&eau3Y>$%I+qBtgwAq`nY)`T59mLdFI-0>8nqEtqVLS~^isrigodBgf zeo=S+@Dauofq6JfU*EGjePrx9Qclr<O(M%y-w&`2CV;P3QH6~=%Us{5I%8z~Gcrsu zhD|-oML(!Idt?&e3>3-PNV2s1+&t5y$Jmh6iu!E)Sy7(oKNN#Z`9AiQEDBH&mM1-3 z<Y6lRko{8@d!MOif%I&V=X-e|i)WGb>3HTgP1$>h%NMW@Wij^|dt#bq>^+~#gNSh! zO`pDJe$(`nhrj$w_Sr1%K6B4PP^IGeP5yxWcNR&X_DW93l#&OR{5|&mEJiS5qeEtt zJj>)iuy15h_35qTg-o}3ILSX_pUmRyGg~PLnQil&`vWJ)g7oRG<nByGd8o+)<7*b{ zKdA&A@(b)gvi<-G@^_|>JmTcvurFru_F1eH?#v!}p2#y6Q4B+o9<u4hW2Q(UMX)>> zh9hstW))AE`aD#WEn*)wMIvQ0ipSq0k%~8ql!u*=fwI}flka`j6{(6sK$lYvVoKbD zMLwgrcbEZb^a72T5%(;RA1YoOrbOz!$U{s&^{|zHQanEVZ)}0I^pc|V(iEc-v{7m1 zU`g3vX*ZMU2-<WSZaO|@IxlDXDdnN}%tOyt4}E?i-R>acUnEWA!D>UHw8(52iM;s& zH9hL@{Ze7JC}21O8T%r6dIW4b6o7_49Egm3kvje9oA-eNkhX^tkcl^MDdWN7Lm{<D zci4SB_-2aoXr`h;arLnDx;@x}ER?yK%Ly0f4~wqDZ<Z*}m$`qC^C^BYti0}YvqE{% z$?cjPYjMV~;JVe#;`TWw_h<h_9B5yda|@JHEG`|EShu}d+CD$${#`Dz`1P>*y35VV z_C+-}9y!|L)M5U0*w3QqIe@2@vnZ|`mR(1H4a!1?n~R)eapADoy3Nm$==lzJ5Opj5 zJ6xb5dNIyTLyosNdsukg`e*U+T%7wGIoIOn!;0&UV85~eL`*p#R1Qn7+x;v(o(Hs4 zIiMec>QL7rBB7LYH;*DxA=IE-Xwij-DfMnQipU?LHr-;1h><D9Zpb1sBx>3%qKITY zrQI#C2(pekc1y4)>cie{q!Xvk=zh@1CVt7JJFk&RoMx!|uSPC$TCwiCjSNqzpL9QN z<am0?ue+p?<tfeA?pKXG(94w4X}TBka&F6cU8YhV&?O=h(V=)}nRIom>JrU$or@CJ zbs?|t$r{vd7r)}j8?X42a^i#<Mg7T3aV(93{$!3gg+>W~$Sm$sBmXy2Rot~kv2WzB zaXgK}-^gNd8jX_QAir_M!I!y6A-F5SB3$IDIQn3L%+zYabtUq9s1-t#60vzoKEX?g z%pCQJ5T-=(A>{?ZUkUO7^^*|SMszJDgW%CddJQ#12yMIYEaeH|MjQDv)K@}G8*yMt zDFN9=7KoZ9M6{87PkBuUY=eA9{U#(t5%Hv?65OLmc~Jd?kf;k4DRl(jDDn!_1|d3% z*d?Wq;2lNgf|?|RN0BU~v=RcMAPcBNLi`btMoKop^N3Uf^^tJ%=)#+n=LEka@;9g- zgxDkEgp^8x&k<PyYLO6mL~@qWMF={AoV766Q#3$rJ;c(%?1B_*wXzp&fZN^>%fd{6 zslQdmp1r};76}Tg#@`{mTfxBH;A9&pmW`Qw=d;#IX&>^34q-EO)q}a^F5>?R^^k^g zC_*`==sBSE95Z_z%6c8U|AQ!TyTE(8z_Y!;=h)T_WgGt_X&isUOa5hvy;%d&_U04R z_~;GqmX|a30Sythu}_l6N4|K4zkFry+z@CR`6PAx(--gkm*6sNNU%-xyCsk3@S=Hn z$6mL=9mI@N<VWweg5$qIdcxkXOn#xn&8%4nk>4N+hN}|!`4acxW+dW8gYtxvUxoZ4 z@Mku&ATk;RC#?L6Tjm_x8=3*}szH9j!LPh!0nAm+V0LPd0Fzj0%RJyhHG`3+L4Cr- zud-!P#f`i95+b#Me**TkD11)Ey}a2RQP&_lf%sY$zVOP;x%nERut5xr`6c1=uiWRG z1OFTAp+OiR)r$A$V%$5M!RXPTIN|uUe1GAWTYR$yqOw5}%y^~y^S|6rn-dUS4Vn|K zpiT>K?j`&(f68dfD<V`CRXz%Ke=k2x`EG?p#Hc2hk9_d*dHG@rvE?5Tp_*F$39JHN z{+x>5ii=2ieT&<NwV7%fwZ#Wa7Ddi;*W3%6O{QzNWWax_%z5FNn_aWmG-m5+gbi2| z&OdXXZ1$UO*;0vceqE6@^(bq)&1|a1Y`S@P>gn)w2aP|LC19{1p!c7gi0h6o15{u7 z#l8%JL|p%$SP%bO(nDlx?3DVJOGMD??D@&>K8LN4DUvPi1Gm^TK+i(bwi-<FZ$-tT z)n|A-vs?P7SGFh)ps{)C(-j^TEp^kMw%89$V++)0D?C58Y)t>$B0JED&F!3W@sMmO zoF3X@J}{2Obk2Z)am(cN*Daa@{n-4@=>?CVme%RnE$##J*uu`)1y4|IJ^g!&<Uku# z=S=+@!XbV}!?UvG<MhTB6)<k+#ZSNSaBX=$J-NksVD`Hpe)f&$V#|-|!!5{x?(f{w zsRR$rmdfdmTdW5rzcHsX37%aoi_<^0Xb%j2=buiWc_g-UO)qZo9$5S?Je@uBJP&73 zq9})&djK7C%xGO8(n?9R9BzI?I4gg`Xrm@lMv1-L)Ep_Ckv~4T?iCrTq+IS~9w?lh zKRLLu8cC@XVy<16^Y1(cwDpYW3Of9q@>)41Ft6lUPuDNQ!yhY;mvfk#)fHIJ)~}3( ze^E|LRw+tWP0>|B>#AnrRLXFw-Sk`|xm?pQuJIABc|d+hy0`W(@<YlWdIPY*tja}{ zD4CT5bOWfc9raynjsSGF@(A<Ty5vtIo2y|Fuaun21I;7rQa^p#T-%EP1s&xH=7~PH zWby2))Dd@-bj#g81pB1Oj;2TID_56Gf3Wu{lU*n#n1%`cgVInUJ72s6sv?wMlq-L5 z@~MzrL=eQoSd=r$1wUAUJ9G}Q^fb&?`ANC_2M3?>7Yow_|1bsR(sGFpwmzjV=BJmw zg+(a8{!bXg|AJyLSN=~DL%G-on~jp2^X*G>VS&o6<*FZ?H!5x}MibP+c$Bltg+Ewt z6#txyUg`*QQGQ;o_`z|b{O7_kAudcqxw2gHgWX2y&-vq}lQ4iLFW3Cws+d%Y2YcLz z{5GR`ufR}{1{^h8dl>Pl&38U5Fh()CbOfO7BVM#2=KTXB6jMt-4X>?7{A`P!j|)s_ zy~Vk~5=PaIn&$(4rXt5ViKT)tllIzq8E}4-IW9C1Y{SIbG4odgZCXnJA!lhK%&)y= zUM0}Ewc_sx2a~oMllJDJwx>hw9aK(OX6HeSbFYo_@VGNh-ud%?F&qLvPegLI(ah@y zdbXy|js>hML^`%f%-aU~wPwvu1Z=#FRBhv)HwR>vjM?$6^@zyWHuZUzz@XOb*~zVq zgGfjl$-MS=x5zZrG4AzCkp^x2^HGs#)fw)Ud*S`<EAtfJp@0HAUA_!BAnl*#*}t1c z7O2jauY3sKX#Y7+1~Le_ucw@suZ0)356v@wH;%--o^f7z7Czbjb)E*emhxXu&o2jt zx3<sDbALCFEPOpXzw$l&u>JQu$#?C;9B^nX^Mq%&_s=r|^e#Gf2B7!DKelho{{yek zx$F}DynS+>^Sjw$LF_Ex@Q43sKb(hr*98dLsrY4$@X9|#h3_VZnBOz;D{sOV+kec{ z0((^c@9ER!gz&ER#d+TE7KequXHQqo_8FomI-%fDNiQ5TSr<IC`cKpX`~Lu07}{7n zq>Ku2(FR3UQ)0`^`*)*zI~f304{bLiwu0Gz7roX=>7w^M&u;q3vd#YE=<!Yt7qjOD zcC$}b#`nKOr=`XerN*Wh#GnmgGy7x8`eVBp)kgBwrmfY+KdH^js(nhXSevd`X|LEg zb|Ii#;-4o?;{8_T4@#oUI*~3npQ9#6{nlCzW}*T*BV1yiCj*n#YWTscDCf>Vm&oU- zlb^n>?H~M#itkKtNesHBi053TIk*$0+v&a#9F(FsnsKNfUEL`SD1T*&3#A0JJ)!9Q zPEjDylqk-ZE)DPf8$jVd@Cgljf7l7~3l2f$tqY*ia8Dt+v{PciHmJ09es*bVFCzMN zr}~0RP-W|)DuH|NQgmu3KX@7!Mb4=%mG7BH*LBJ+AbylZF1#i<?_G;7>=awD`B4%% z|9WYDFEF~bQ+2`lM@8gfEJ1ybCpx=R7`&s459eZ+I`>?npLZ%QIQ}R<T=-3h-_wY$ z?37%v`%!v0|9k0lFCn_CQ**&pGYJs=R)r7pkBm;e5<)dmm7`!qfAHzZ_cSaaMl%_> z%vOC4UK}A#{SzWUSK%kHu|N2E6nz?(kkECDcY}40>KJv(2dsldu5*%0g?lE)wWl)R zsxEU~cuug}6FbJ7UQMt8+x+?GOOtzk$1SHS;Ne`6ee@{%xXt3I#^Sj7<I&TP#~rkB zSl0N#!uVdh_~FTToMQZE$2VK5Z@$L9`2k7zJbB1@M02VSu99@{=3ZAkbUczcwN3B? zkc5e#jn+feBkoi41Rv0nIR4|GV1$IAe{vBZM<l1(fESbo9_Z_|hXzOdr%^!Lp5a}| z-tRwNIi)y*Cgy2QS1w!Z*ByU4We0%50?paVm5=)y$3IWWfT1q8Ysz(5a=-9+=#=@) z7_=kIxUM|kpFIA0N^_>4m=Er=<)Ho6<JnVgz%nfCnq6G^v442{`;_EN`#dLcN^_Za zKl`}<l<~|6i0Ct*G-3ba@y03DncjI`;&j)t>;CiO$y3fVv-5()S<s-c|Ks@Z6at)k zx#v@f%bNR@#~)8w&rHrS=QD{bUHgm2KTc`S49@e<r_YxY_q&c4PkGNQ02g8QeC3>m zfs`T{s=a*KC`S&Y4QZ`NMU&y$UoM;FC>XNV(8`dqC!1=oUpC2+A7JsK4JB1hcGCWS z*&;`AfOVCYk~BmcTV?rAf<bRGgZ5w*+)_n^5l!=sY%Q5mySK{9Quz@BoCa8ElR319 zt86V*A2E*6d?7QuMQ(o!0@WgiYe7uA$(_0(m+3D28!6#d67y6NV_OpIkv3h5_Gy(i zUg|oN+@%syvt*?9&ni8<%ys7GOEaVa$r0MWt90?wpt|?cD^lm=K<&dS1H9~K=Dkb5 zNaK?ew9nnNq@>uGs4v|i)lGKCZo5IHWYTE$$*Pm3u~TkNQW`~crqn`Y`N^W#F*gS( z^&<NB)JU=y$;#L{Hy0^Qd+;1%A<IY>#E!Zl8r49FEwwG#lVo}9jGJ?##uS}DHSp6V zOJFD592?cA=)X}%kiAY;$1b?JHfk!-aZz6)OHJm-ju7mF)s*PVsLjdhl4Y^e1gBt) zHaaKjYh;DVV%TwlL$G=q{Ty{5S!=Q?cAnr8tQke8M$JQ(oh*#~L_ln-MbURqyO8}s z6wDI-01E!#3CJpwC9#tP$8B|x6`=+Ikz`HmqLg-#lqr+YrTi2loR|BqlwOexSm9s# zl;VpEbN?l!TO|FS33=&73IgZvejsH~BnvkBmwu*1<Ko=U8nxJ1S*WQ{06pM70@nNg zH{gM^l<R4zD8m#lLsZy6ivIvA?xM~WCS6gqt{_}jVoaA`PM6K$KDWw!&Y1hW<nC+} zw45n4IDPk(Mx!Y?kj0{POp(CZx_@mnn^N#+eMzgD!i_U`-}pPFAc8hF<qx3XN2A4* z;y2a<T1W~BPJ4*}8Y<+tST4~Tr10a8g5gRkT#WZ<`cW%5ilw)~R!Yic4CXXo^1`t% zy$`lkQY~ZrK(m4Ri6dL;35K;PIWYjg9BK&1y!0;ErcK3(@fpn|>MM?BsV~^NO?i$X zkOuVP;JBAQ1lzT#&M|(cIYj-&kt|_Bk%f{P0}o9$svpO=G`J0qQc+|4PZ$9WxJq!G zOT*i?QK}t`3p4;mgM%#LwqZv~aSR$Xm8g$6)}^6sn<JGtM&O)6{lL*K^>14rDWB{n z&a~GNx+0Xc2&bpB3%@4*1c>MR28}}V%B=sMCZ1jQp8sARKeaI*Kb?A-h`epIYlgf% z8Fn^yd~-vxyer~t;y8ALw>&Z8jLZXMc`rz7i_>wQkT2hAyUdeD%Wx~@GW`+v|1V#X zw&g`8ay>1WB{dU7P|L`Y5>4){g|NJYhA?aCSyI5sZM1AGY2XlfEi+51G4gONXG_{K z2#uC5{-PYYnU*!4S`H$iWrC+{CJz7@olDISZY={mMHo4e)-57(Qp;{4$b~4a3uJQJ zNyIElbhqfjh@G_+@!Wev>e`Zc&OPFIZB0BcH4zE+vJ@LNu`X6hiYt?dA1flokxA@{ zRg&T{C1S)1NU@s|TVv&<xZe}WV#TF6-xJ@&s!8#R6H#ILfV4tvf|Y6HdP*dQy$Zw> zVn3`(Bac53CswGD-JjSItI){(jYt)Ht&#H^aV%D&k(Y}Ig1r*V#zky^l@8`ABNE1n z26L1V`(TxWd7Ow?v4X+uPQ-Rt`C#rjB1No3Fy|a`Bvw6`SB;1k%fHR0Mr?tV-R9~b zlEjK_b94{~VO6(z;)r;$yabDF)+5dnk~6Z(Zl7(kII_j=$Ze7n(k?e@wj`L8P$rot zZqbd4jkPa%$NfSPozU$r+*{zUqRhvxN|BjTSYyY4&5G(1c2A1r{Y6>qd*HUBe1ZKY z1$j?#6FUb?S5!Z-Cyhkn7pbs4z<WiRfn9DS6{j%4jsgo7)ev^K@xs%KV%T@UiADJY z`=ycmDTN<)1{kuazG8nh68m4|#P$JS7G)`Ry^+kH!Vx<G>{(Q^*n>urZx>YoPfqJ1 z{o5QZO7>MtEn4G8Rd+Px@H!9@wx0iQ8WI<o0ZuwtoD0&AqX_0JBNfJp245{Bufwqi z3zd=i;FN=}l|eReWWiUQNLg`$!J<y&g*fJ5K_@ahoP4l^6J!!c6U;wHs)&;a7Mmk) z#c>A<&yhvq)Pp7GAcr`T?aOMUv^f545jFB`9OJft8kq%7c3WHx@)1Y1&DTLHi4)tt z+Clyt$GI)kK^BBl-M-cV`GJFMUx_2-#R+eV#*tUzShoe^$Xs!X+Y)h*MI7xmKlr>T z&Tl8;5(!<~j3?Ax-Osl<Pc9{PS8lW3P2v-w?1eU2`tNbxO<sNwC8A+`i{SzEb0nHg zP}>M5gXXH$5`|qwbJS}4!c@>a-dgN1AvC+UHUg%A=3diMhFwE*u4zZZG|;@vT4b;* za5iRbJ(x6{3!^0n6NPhNw7p@<a2^{iW|$zH-A3C6CJ*Nx*OG@xz&XdY!(r-hUU@AV z82=cXytWxkc8se<O9Cb~#?hi308<^~3D@F=36HT8lhW(3(L?EVxhPhzq%(~U7?2}Y zEpO?Jk%jBcTSktN>_a;(gT^5HdZ(6&azr%HWW1XkDUBWuA1rqv3tEl8E=QiFw}Ow7 zBQ}HP<Gtj_%=A9t!{kVYp)c_Ma*$!YpZK_DA_-^)-lLgRLT?Bk+I*n_`UHQYnY=;o zD?X-~H~?CTM>dlM=*{9Inn|{xuknG+kS)F6_=GSbZfGjrJ&crFuOA;0cA*?vhxZL5 zFW1|^M}zYKT8Q@!BXic9#D|BG%tKr80b!7Ny+eFFI3%Fic+Wjjb-j=Hn|l{Jq0jMt zd*q#ZKk%{O<bZ;`%ZTgepgr1OtnoUPBdmMO@w$s6w0n%FJ<`FX21`XsEcdb!aUsD@ zT(tfD6u~-W7til8t_UcJn%~J^VNwz_M_I4PDM^^8ep;bc;{T8$yCSY6_TkQp6)q*= z52%|fYD$tHQh%;oXuEtZg=&SbP2}30j1`79fomv}6`3~iYpFvklx=*^Qp8rSwq1R8 z=gA63o6s|q--=4xwP&ecSIFD01g3DV2(^g@-YH#SX%h@YIj$(QNd%_Ou3T#4|DK}i zdFzTko9As&WRYi*x_DC$$L}e(4DL(8X|D;-+Bm=8izQUFv3}3`O?cDB`#l>%NQ$E4 z$xJ2Ok7DDwXF$k}V&ci_Cp1NI@nj2w<}-$h%sN7S6i3B9A3|{yOGVZOp*@PHBAb<f zilTSPEF{!MvAf)}BVeMKU9u(#Em7Pq*@}d$D8_}%RzgD*=fb^6LU|PHLe?RnGm3X1 zo0gD#M5mFNO{hL%)3|3r$UkDz$ofclam1yOElJ2YVtAAJobcp`<ITMwLg^99o2(y% z*GD{WvUv%qNAwAqm4vz@_Jn(`gu)}{gseqE>k)TCwk9F_i1tMIjOsk=9DBZOaU^?o zyK6b<NcAi!aoJUXJUvH*A^$C3(_j#wVwf!F9tjW|88YN98hPZU2nY@uhUVR_5vVu3 zk$0y?aMLg*FUd=w*bteA@)DdjjL1t~6=*jM%u8JrJT^?Qy2T`bGIX~}VG`^$46(Y6 z7N|A!wYq~ATr-TeN`ebu485&TaKUlIaI54offmC6tJE>UeZ%<CTXF(fhMuD-a)QH# zH%D(b3p5z|joxV%+%k+EO$rkzH}tu1Q6SAt=b~U{FkhO101V1l$>x#HPfTINI*JM7 zpEsf%&EMneG~yjC+~YqTB$COY=1U%=lR;DS;|4Fv<Yn?z53<P=Wb&^JlFH<o^5qXQ z$zV+RKMhjL<iF>8F~}uT_@4jg;Dx_(#Q8D?8U8|x^A8PD{+0KX@5vy?Uj<M3zYdcB zmFv$}I>_=D#-D$7@X}xT-}qh+^88i!jsN!`acB+~U+N%zD4L7Ee~<zU8hmww?4bo^ z{2PO0p}9_cg@eqY7$^S8L7LF~Ilk6G?$E+H{=-3%-5fQ(>_Ns|v>N}%L8{%n4!-Au zoVx`b{67XEyScz{Edbs_gPN<ZyXkR4t^;<vS#iRe0~Wg(eO2@vdY+^9atfzeefL9r z)i^4JswjN<eyN(7=HqMR*v-tX@n|__GqX?lW;t#%3t4=o9OJO*3;a_#&SCSL_%b=x zVY8q34msXo3o88WW;zMe4E%#;HVJbRd|oq?gxL`OuVyX@3o-oNW`+jSC-}$B91Z4v z_>yLp2D7jDSIs;P7M%Dy&GZ4LrTB-<>;dME_=0BU0JB;A%VzEX3swBRX2va3ViXh1 zl%f_5Gbh`BRCD*n7i(RKaJi~0TRN{t1DjR1v|~qIniaQne~%_KYjSHrMzzDFxOGxT z-NTf)wGBpLVRGEM{i7jaYUNtOqefve<vMkvzF{im+CHO*Fokm6jnU{Z4QDOZQN1u} zXPv@P?=WR&ZM#vMFnMR)$<gpI^?5DDQL`}Fd7akLfH2j0?Z{E*FvWS@!_oLKO?55W zQQbW$b)D={&pjn|ZHrOsJvnvVkE1vD)H<~!M@{x*I(43p`t7N7Y6p!v?kRNY{uqtj z(}>sN9W~gK21nqi&z^F;w(F?fo;)}SM<e&tPqj2hH9uGGN&ZqiO+7Qw9Qn9Mb!yx- z@?#HjYLwW-Cf@VF-jpSy7unUMBz`TUfB6Ne_!X142|novh61#p=OBWzAg|V=9>Gyi zQ0uvgATP-E_9#ZM6kxnPrxBM5^4C1t5j+KjYo5mlV%r>M4-|sl7R~J0i=eR0!+6vp z*li0io@)p)+guwD41(DfW8*oFps~##_h><I+ZK*{?juMha^yX-5R4OOdCy@4)kI#4 zM+1U$qM*fd3jvwP4fiN#cgwkQhus}5-B;|!lW!_L9EU9OzDFkR<!o;^krnQvZf`M> zv5$<mcb&-I_aT|mQb?mg>P}fIWYYNXPZ=uQ%|d!k*(==3@?o5UDx{kst*77$S!O=6 zQ>F?T!^oRcP72w>K2%dWFViHDCR0`~GbMb)ri@?SZ9w`>IlR2r;KMnk|1v!Q={RNk zGAqDGb;|r@#uhSm%H?JDmJeh~J0gu6X)pzg$mI4Bo-&HKTaNUZLPXpv_hFsVi%54y z+D+L+WI6jNPMJky%p)VGoFlU5eQ2k257N|;7E{&-nd&~0Qzi#@JCQ+CjtBQTeR!t~ z4j@1@?>$4FHzrOC9~8&CyG|<}l%Kk3PD}D68$>Z>4|?uQohb68_OI<k#Z}xAUQIvx zp(bt7lfUbwrfh+=-i52lTi`zJhN-E4?3Ud%Rg?YL^J3RuP4y%8=B|^P;z!)i-8eN( z$!@A$oen9<o{U|O4kbyf$*xt0oFr~&H?%|TdAHcEafi(Fo+rCEI#ixx{dOHX6rSV0 z?#6Uz1a))n>UT&7^_1=+JCuX4j=Q!U@<F)S-G~nLAKj|E<{h#SuF$vA!eya-%B*uM zd1BAnKhm_$?c7T3p!)Id_0D%NnhnP8EOgNR82Y_)1_tN>$PPB{BJaD@oh2}@4I1o> z#8LAO_3!M&U8o!o-WiOetbA9uvk8W{L7$!JxJ#8o8#~8w#I6IZJH2rfuI~zW*1%*p zXty&SN8>s)xw9WfvN)i)GaN^?_^x$l3ygb%kvsEow2MQBJEtc^ngg^uxRZ;T@3MDR zPDnKeEp|SgP-_l--1&KOp=&^LXXu2o>)rF6uP5YPgF!p9Czra0e(d}{Ax<3N-RVD} zNPJhhvvER}IOw`Fc|wyow77G4LUKNEPDtGCI$Av8J(E0ttNBy%MC`n;>nHDt@VTHz zT3Q-|w4OM<<B8C6S{q+Qnj}M73SaJ#vjB?`)GF6hfK?P~oNHXe;tO@iHLqc1hwA4V zd9fg%wz+0rtjbXHT$5FnXsAoB#VRWqR2yc<#G(g<!AzN01))YTV>F956ah0wvob^V zU`B8j8>kJ;49+SKHG`Rqv4lgNVHRVoG*I0ULpc^RsP%}c9IFJ>WW>0cB>?I;V&2Tk z4K)}s3S-gIN+M-}T4G6Ab)s}A1)H}~^tMX$X_jI1&U%U?&U<v~dXgiKd-U;oU;v}0 zBk8>?ZBI?F+bbpQlu5_mD<bWXN$=UKB<*5K$Ji?%jWDIR?v;~veorUcD=zK$p8jU9 znzXAp9aS%1lf5{-Nv}+k(^ERJ-m6UxPwD-7RhnG<={S3Znh^f<j=c&^&fn-%d#^P) zexr}=)o614e@Z*osHF0RjlVO^sH5ejvb-gAOq<M0NkLlXm^UiX@)BO~9;uiCi4d4N zX%01wsR@~REmKKEYfR0QOw9=uwE;~xx<!lX<Y?&V)-cg`&uOi9=FC~^e0jgHU;*FQ z>;F9L=Xri6y6T<VC;=vV9-VtA_(I(sojWN(g?iDQ_LNY(?&eN&N+4bj*SU`pGOCO2 zw59})>d`wLDPae7bvn&v0}kqWcOqx;ExNXyyJmx0^hlitW<xLNB03STyl3-12E&9? z{gP+Vvu+pkWzXodF3THRTMR;<!50VfLCf$MDb&QaW^?~lh55{S=9Lzi;92N;IKU@5 z_Mv>nhk37MAk+wE$n+gk5N7O{`7NT*O}4ze-kuL{X3jC2T1G=nZEN%TdldRJn#_!r z_E5cAE>5)T183$av%EzdY6t^o`aZ7)b6UDX^=qqey}S>DGel;6i!^jgZ4IuUr`R`R z#LR5@C3HjWy&+NDhx(ZyCcouns4)zu>5Ee&&NwiOTKY_9N?8Y|^s<<u*Tpjjy_wyT zVufKpvrnt##pf;I|JV`!ydpeo{OZpQVK!Q7{5li*h4EVO&6q3cIvOZ=g@q~@5`p2E zC+P-yq~LWg^p-Iv_!_P}=QIunzp{pIFnR>~V@FAxMrrVCm?FUVO|Wjvos<jTaeNgI zH84g5TgJRdd5t3@ucsk+8D6kv%vq65A3pHvZ+pQ-P#@!+Kx@oRah(n{zY2kB7()W% zF|6VSedKQ=!AY+ip<+hAVDs291!qy3^jZLoF%$xwF%N}~!dqdhASn=vFhwqWoAXsN z^n@W3AYk-P-cQ@i?2i7zesJoHvH;d%-RJF|cy8U$?fN@CKfogA2*EBNUy;3&V3{9O zkrPXB$PYc8ZAh@l4?LX{NI>O>yv?>J*yIPl&0!D@<%ey`{+h5YFkn-T8(~i%{zkSr zVP{|vd|DFh14H41kzgJe2%mw3eSsnHaYwKY42DlOf@5G9DtjHl3<yBwU<pV7-;ixh z*aZYN<iryW0HL((ErcCF;FsT+Uk_M+#5@<T`TodG&VV@2J?Q<ZtuBBYjRT&d11<|} z!6_2pvA|KCO11w^o1HEXw|CX%bjZo}hp(~A<T3W{*Ep}`=k1-n*tzmk_HJGriJWTh z(#NiopRxDo<IKq~G<|2ozABGwa<$>~$j>z$u3_`!#3uI|&Tn#Nlk-`2f&6rn+gZ+t zoYv&>f!!=W+vM?q^GTk<_|BBgl1DIHO*zly6vp9VcBMR);a<#nCucC6L)m$90>dqo zGbB%BxQwwI<?#%UG0vhqS^3=|c9uL!>3WFMFHcY&e!{Mm$0^;Pa1`<+rE>~9Rp|64 z?01qfYZ;evz2wbirGHAU?2V4ncg1IqpR3!wo0d0z<fr&j{P6nTow#rO4s$T7n)STx zmiLZUT<2}HEI(TA!`o}gKUyi~t+g!czH7&`vgCDF{LC}4tn4m7$2(|Q+g<rP@5`!E z%e$Jqe^hZTD}Lmyueu9=lV?{|4S$HIS#<|~&9khks;a2s8Nm<bM4m%cO;zP2Pp#@U z@vafiqUs*8;udcc{7!ig4^_n{R!Vu=Rb`WR9d?zL9@gA-ha36huG<IAIX*$k?r(X8 zntt5J+?uL_$r>iNxGHawzr=k~RWezt#=S_)Hmd%Cdz*OEsK%X}Lu4EAf8jnL78=!B zaIX-r->R<Q-Xq?+Rdbq~PrPx9|CZZCEWTB{iJL*p397!qEhpv&)tuyVh@2q)OKv@} zD5w_2%_QbZs~fm{Vu7@V#w{Y|N%;$00kK3{tIbWH%yy{0#x0w?=}_av&7EXB@cX!R zlZ6hoHr%U|*B@8caCwur9@m`Z7EIoF%>Te`o-BS`YszI!<}j;^xs{Xo%$iVc-Xw>~ zALBMo7BOoNakD0Mpvt9VFxlzEYL)k7-O`;WRiw%0rQ0c0VGciB`{%b?e4mRSKqQB2 z*Lbhre{{I$#oh2;21`8G9fMuebFiKsxJM-xxmOOpr!rw#J&;d5UE~%$2vBLTx*lkv zo-OitH>jkhz#@AfgBlUyx_PjZN`bZZKshxw#655D4V3{)?g0*!5aNa#9Hb_~%6p)m z8Xw{@Gzd|XVF5mnNsR(s(SyCz1Xza;@Tqa2d*k3VH3^pE14Y#6b$bUeQP{nMo(a|u zE6d?Ha+q;^z2u^H;%3mFE&&sDK;K2NAQ1uL79}d^e;kkNh|?imM?W1&2c+TXlO-;L z3>;5pNnS%=IiBzq=RzAD{k<g;Xsx4fzqk%Eam4jY=AbVH$8E(|q4fekTS*V3De$Qk z^B^O^$y&*8kec8GNn8MJ68MuOBapVhS0QeOOa(ZF<P-Eo@^OTi1?eUGAtcYCZ<2jV z#Fda?^2rj(JLv1=6Jg>!NI%&>Ofm$mOZJtC8=)=9IGJP-TBADdB+i01sQjEH{g9T* zr&U}F8LLjVN)(W~>cn4SsjxA488(koVN-{k=Dk%tSrZ=1-#S$wda|Zh-@>KdrP<|= zFt_}6iEtJ4p4u^+yVSKTPtk;zDZ0I<;g;{x`{j8UV_sI$)jt(ITek!(Po-!(RhIPh zPs63(CFSyR$`^2;R`?(5>2L>l>95=Av%ICj<-aedr>ud~w?fhs%sXG|U4EOQ1y5jf zlcwQ@@Y3}1LW+88nXF4OwFa>ye12&5UjKy;TC%zF+6&X4p3L$U%TIMwHYqr`MGPt? z7Uz?c0@b0Eu+|cp3^A@VudYm2ZCg1Gmx@Ob6It^f$}-iSm4MVjr?HZ8@A)0dT-8oE zVt>mCEScz^k5<;H?BTF)v6Bp*;hO)~Uiyj;92xxATKfNOrMHgB#!2&NWr50i<s{rd z24xe9dAhP$<+u`>TGA?W8b{3QC|N2q_=5Q_3+XHVa6cJrosi9wl#QwbaE!P(RhByL zG>=ebsdlXR!gb}*)QQ&lFlDU@y%M}yv^oas(D~Jw)%n%mR~J@iS0N{5iOO~b2RE6) z)rr;l)O-Vr$UB~%8+x9hTJ!f?)Le;vRq&O??IWjB&{weQa|gB~yRe$M;=6YDutvEr z?;_u0)pCD5WtWfLlsk9|31GEzC33qatZD9$9I3>9;rn8vT?SUqcVHv36Z?&?m~B^% zHS~SSM!vy*?fa{r9S5uLJLrcT#IEy|4A|9UxA+bXAR+7;$&0;qnb-}IfxXCHtd>Ol z(2kEamb`q3oW`n4euXXey4^3frmx#Gu)8C3cX5upVf+O+INbM@#oiE4oTQhEcJ%a? z^vt7@J;NmZ^XN6A?~uZ^C>POjq-ZVLOoTyp|AdMX1t9x=LT?bcBD*|Mz9K(luO}KQ z@<jHCPzfSDvR{PO5*@A+TA_}KeCkA2=v|_tb=}pdI8jhtUp3lT<X+cx1{EwiS=W08 zeL&<@*E5Am5{1_FPodRC&Iv*jl!xd<g2)8DLv$peyATyE3QXuLL~j<kC3N9YIFWxs zFCL8+VH0{rQFKvALjNdQN8~amJc#lZ`Ob+BqHRUT=DJ%@BvJ5OUke%`@|a^OCCh{r z6#Sd$-7yDT*b~-^o&%S6JN4QccetNnXU0YW!wYER=fBj?p1Dx))Z*clDFx~QHZoUw z3e|*-@Rj<Z>akH0DHSE?4M$2nQFXnMb<#7a=H7?|DIV3>8#O1rfNHf4*ODG?xNjYK zRT|mw$U5Sf)TiO0bySb^Ttf>#e3$fS!_WLko|M?|m>&@*4QgoMNBt&cHav+BH<r3L zJcy4hke+U6ijN4Eo@}U(j~bEE8U)kf2c%vNbzg4^I`zQ(M$qXd{g-uOOCFz;S^pAv z`UC8oiOs-=2G(?J5-<iE=(tb73hnzXG3r1Y?4yY+V1jmOORNX*D{QCZo&&SAw4#_D zKo{()iIu>6+7Css(EtFO>$rD-l6Em9W;4(Udu(DJ@P?KV5{m-{VXGZC1VFTOFa{0u z!j7BR2u#yhU@RQ~VdEXQ2&fjmcZ|^iI$-}z%mQ97Tyl){1|+ZzkLw5K7SaSUwm=W; z#)-ASZwo&NVoAUVY|7&lz^8?a$uS7v`NEZCVhQkWAtO093>aF-OpcQQiwo(h7}%^! zTc>0Th)=buQ%)nc3p~~7))B-)rRq)Oqsv#%?Fq5kJfeF0>d_;c;;V}Fk1pBdd;-mB zNANy*B6Ipq{L#Gba#}1tD6g-aZisi!>mtws@h9_o33PkBS6<H>8Ur7i*Z+q8HQpH~ z)Tg=OPvAuQbaVU>TsMbCzz5>`ICOoy8?MWr=8yNs_4?EI;jy@$L0Td{1lK=EUx#-Y z67Hj6@xDW%eROO5v7zpIT0A~@sIQ*B1@AG`l}LN)%rc=pJMr9v-p=rHc=K?si1N~Y z^P?Aul#meg5D1YSLu`jeAWCwG(~xW(c@4M~J-m+M0`5kSW|GaoZ_(0BN))&sJ%%N3 z0Joz7EX5bxiw1kiNYDyB(o0DI529t(WG(O?jl<TIW1wB*D4)Cwv}}~}DRH1f<5)b| z7_?{v;wix(su7$f9{_C{N2V!B;Gss@7P30HjXu1E;sNfVj~0=4fII2ZB1$x9Pag{* zZwAfjKnMi~?xTYs84X&~M?eZ4bfn81$vU9f;;<vd8$>RS3dpwLu0^SULIMvgjwO>3 ze+fG!mW)O(b|xpvM(K+kDr#$*f%EpunvrS`(uUhe&V^gg>e^mLY}Z(?b|p=g{>=IM z*4S(-jOkqspFepM7#KHUr<R{4a=x)OF56mYD%Uut)|58tT)dT(Z7W1<)PMmKY3<HA zr7_2?zBOfQ991h%6FcXZo;hywEy7R3QjL?=?aV199=GP24rmb7>eHmo|4xZ;&Ml37 zVHIQg2O@%>_R_haH2#H641%iRpjMRD_k~9I_g|W1f3IdWeo>?4J2lG}7ZEp~s@cGt z3V19xbLGhXpocNP-f_FS$@>5KM7o+;I+A)X38qgN&TBH&lhd9!x0a^v-fCa~Q#AhM zP8b;er0K36mG+?R5xmT~?WTdJriHq1+P$`i;mqA;Hw{Iar_~eEn%Y{zQ|@mKFtF0x zq<$=|yzS?3#{E~V{wLLVX@hOI!sGAT1R&06pwtS|dfRS<$KAIcHl5O-sWqp8ZN=fF z`?kXf6Af)OR$50}&Ug&jYQJfrhL>7pnxrj%{0!M<KLW2|vx0tCK7NjD{%9#|`j4E( zY#0OiNPkrO!&mh5q&C&K^UUr)fD*-Dd8bFW&5gUw*qzsJ(H{GXlulpGOj&hW9Cw-7 z^U>@h^5d?L2Vk<qV(Sg>ws+$_sc-(wZe;9f#~A3tFwTqz9kTZQ5u>|94V*l6E!J+x zXk}gL*d8H<w-^q3>Q$`u&A8XGH$u8Q<mMrf?&-D2jQkF(h?np*gQG~#%>8e1j)2`( z8#ifRz2w#r88Lg`HNXzuYtZhwMCdpdp}c=MU{CeNliIvX{vE^!=)QXZvReP;3aR+N zb0q$aB2na`+pe3jfBUv|fkGEO=IyoqTo<Rkx7URjT#6VrpE9CpHM1Psiz909(}#CV z882vkVy$VvI8jO_@851>q^-qbnYHIkaLLsD7AD5mw4Spzv|pLHOFp;XywJ!?tJ0&j z=JStkdewX4C-U1=Wi^?$e@CHlpVm8;R(r<89Wv$7cD#{|Rvv3tJ7=Pb46Xhc@Yfi} zK$pRuJ6@_hFOQ-t4#tTeTBS;^)``t!Hf|x;9<NV?`<Md|*Z2gw?5rDj?eScg0^}y0 zSS&MjRV=U8U^tjTOg#p|WMX<Te9Sba2m@jS7!@WR(}5|&yvF2WB$ztP9Of#f2gAes zhAF^|V45+XFf7b-OeN->#^t9PKaOi$d7*K2=JMt9dWI+Tw#=GYM4H*GcWuYyVTLe` zm_<w$rXN#_QD90iGE6IGRrtN|sjyTyF3c9b5Z)Kg2rmnTLay+i!kfZj;UnQk;U(cS z;a#Cz$QBL=9}4G%KM6&`YT=ZyP&g`VS!INwSi$Z5i3V~KJepw$W4TyK?ShFX<ka(9 z4;q+i>aaZ8%O)PooQF3w42w0rS<&rv6HPN0&ToVNv(mI>;o5l<^)pO(QUeBPkXZEg z<_W<}%Ezr23=U}`Sl;cGpV1i?3_p`I8Yh}(l0R-+{<yj{A6aoFA9eciO~a^)to&`K P(^uy{u705>e?k6VV?}1k diff --git a/lib/combodo/tcpdf/fonts/droidsansfallback.php b/lib/combodo/tcpdf/fonts/droidsansfallback.php deleted file mode 100644 index 83b9bdd1c..000000000 --- a/lib/combodo/tcpdf/fonts/droidsansfallback.php +++ /dev/null @@ -1,2975 +0,0 @@ -<?php -/** - * Copyright (C) 2013-2023 Combodo SARL - * - * This file is part of iTop. - * - * iTop is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * iTop is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - */ - -$type='TrueTypeUnicode'; -$name='DroidSansFallback'; -$desc=array('Ascent'=>1043,'Descent'=>-266,'CapHeight'=>0,'Flags'=>96,'FontBBox'=>'[-90 -266 1121 1043]','ItalicAngle'=>-6.5,'StemV'=>70,'MissingWidth'=>600); -$up=-78; -$ut=51; -$dw=600; -$cw=array( -0=>1000,32=>262,33=>270,34=>402,35=>645,36=>551,37=>824,38=>703,39=>227,40=>301, -41=>301,42=>551,43=>551,44=>250,45=>320,46=>270,47=>375,48=>551,49=>551,50=>551, -51=>551,52=>551,53=>551,54=>551,55=>551,56=>551,57=>551,58=>270,59=>270,60=>551, -61=>551,62=>551,63=>426,64=>867,65=>609,66=>621,67=>602,68=>684,69=>527,70=>492, -71=>691,72=>703,73=>340,74=>270,75=>578,76=>492,77=>871,78=>730,79=>742,80=>578, -81=>742,82=>590,83=>520,84=>520,85=>699,86=>566,87=>883,88=>547,89=>527,90=>539, -91=>305,92=>375,93=>305,94=>531,95=>410,96=>578,97=>531,98=>586,99=>465,100=>586, -101=>535,102=>328,103=>520,104=>590,105=>258,106=>258,107=>496,108=>258,109=>895,110=>590, -111=>578,112=>586,113=>586,114=>398,115=>453,116=>340,117=>590,118=>480,119=>746,120=>500, -121=>488,122=>441,123=>355,124=>551,125=>355,126=>551,8364=>551,8230=>805,8224=>484,8225=>496, -8240=>1168,338=>891,8216=>176,8217=>176,8220=>363,8221=>363,8211=>500,8212=>1000,8482=>1000,339=>910, -161=>270,728=>578,321=>492,164=>551,167=>484,168=>578,170=>332,358=>520,173=>320,174=>832, -175=>410,176=>430,177=>551,178=>332,179=>332,180=>578,182=>656,183=>270,184=>207,185=>332, -186=>352,188=>738,189=>738,190=>738,191=>426,1040=>609,1041=>574,1042=>621,1043=>492,1044=>648, -1045=>527,198=>852,1047=>547,1048=>730,1049=>730,1050=>578,1051=>668,1052=>871,1053=>703,1054=>742, -1055=>691,208=>684,1057=>602,1058=>520,1059=>586,1060=>766,1061=>547,1062=>699,215=>551,216=>742, -1065=>996,1066=>656,1067=>824,1068=>574,1069=>594,222=>578,223=>602,224=>531,225=>531,1074=>566, -1075=>398,1076=>547,1077=>535,230=>832,1079=>461,232=>535,233=>535,234=>535,1083=>547,236=>258, -237=>258,1086=>578,299=>258,240=>578,1089=>465,242=>578,243=>578,1092=>695,1093=>500,1094=>602, -247=>551,248=>578,249=>590,250=>590,1099=>750,252=>590,305=>258,254=>586,729=>258,257=>531, -273=>586,275=>535,283=>535,294=>703,295=>590,306=>609,307=>520,312=>496,319=>492,320=>301, -322=>258,329=>660,330=>730,331=>590,333=>578,359=>340,363=>590,711=>578,730=>578,731=>184, -733=>578,913=>609,914=>621,915=>492,916=>566,917=>527,918=>539,919=>703,920=>742,921=>340, -922=>578,923=>566,924=>871,925=>730,926=>531,927=>742,928=>691,929=>578,931=>531,932=>520, -933=>527,934=>766,935=>547,936=>766,937=>742,945=>586,946=>602,947=>488,948=>578,949=>453, -950=>453,951=>590,952=>566,953=>328,954=>496,955=>512,956=>594,957=>516,958=>445,959=>578, -960=>629,961=>578,963=>590,964=>449,965=>590,966=>699,967=>523,968=>738,969=>754,1025=>527, -1046=>816,1056=>578,1063=>660,1064=>996,1070=>1016,1071=>590,1072=>531,1073=>570,1078=>719,1080=>613, -1081=>613,1082=>492,1084=>719,1085=>613,1087=>594,1088=>586,1090=>441,1091=>488,1095=>586,1096=>867, -1097=>879,1098=>680,1100=>566,1101=>461,1102=>809,1103=>531,1105=>535,8213=>1000,8242=>227,8243=>402, -8453=>1000,8467=>1000,8470=>1000,8486=>742,8539=>738,8540=>738,8541=>738,8542=>738,8706=>1000,8719=>1000, -8721=>1000,8730=>1000,8734=>1000,8747=>500,8776=>1000,8800=>551,8804=>1000,8805=>1000,65281=>1000,65282=>1000, -65283=>1000,65284=>1000,65285=>1000,65286=>1000,65287=>1000,65288=>1000,65289=>1000,65290=>1000,65291=>1000,65292=>1000, -65293=>1000,65294=>1000,65295=>1000,65296=>1000,65297=>1000,65298=>1000,65299=>1000,65300=>1000,65301=>1000,65302=>1000, -65303=>1000,65304=>1000,65305=>1000,65306=>1000,65307=>1000,65308=>1000,65309=>1000,65310=>1000,65311=>1000,65312=>1000, -65313=>1000,65314=>1000,65315=>1000,65316=>1000,65317=>1000,65318=>1000,65319=>1000,65320=>1000,65321=>1000,65322=>1000, -65323=>1000,65324=>1000,65325=>1000,65326=>1000,65327=>1000,65328=>1000,65329=>1000,65330=>1000,65331=>1000,65332=>1000, -65333=>1000,65334=>1000,65335=>1000,65336=>1000,65337=>1000,65338=>1000,65339=>1000,65340=>1000,65341=>1000,65342=>1000, -65343=>1000,65344=>1000,65345=>1000,65346=>1000,65347=>1000,65348=>1000,65349=>1000,65350=>1000,65351=>1000,65352=>1000, -65353=>1000,65354=>1000,65355=>1000,65356=>1000,65357=>1000,65358=>1000,65359=>1000,65360=>1000,65361=>1000,65362=>1000, -65363=>1000,65364=>1000,65365=>1000,65366=>1000,65367=>1000,65368=>1000,65369=>1000,65370=>1000,65371=>1000,65372=>1000, -65373=>1000,65374=>1000,9312=>1000,9313=>1000,9314=>1000,9315=>1000,9316=>1000,9317=>1000,9318=>1000,9319=>1000, -9320=>1000,9321=>1000,9322=>1000,9323=>1000,9324=>1000,9325=>1000,9326=>1000,9327=>1000,9328=>1000,9329=>1000, -9330=>1000,9331=>1000,9332=>1000,9333=>1000,9334=>1000,9335=>1000,9336=>1000,9337=>1000,9338=>1000,9339=>1000, -9340=>1000,9341=>1000,9342=>1000,9343=>1000,9344=>1000,9345=>1000,9346=>1000,9347=>1000,9348=>1000,9349=>1000, -9350=>1000,9351=>1000,9352=>1000,9353=>1000,9354=>1000,9355=>1000,9356=>1000,9357=>1000,9358=>1000,9359=>1000, -9360=>1000,9361=>1000,9362=>1000,9363=>1000,9364=>1000,9365=>1000,9366=>1000,9367=>1000,9368=>1000,9369=>1000, -9370=>1000,9371=>1000,9372=>1000,9373=>1000,9374=>1000,9375=>1000,9376=>1000,9377=>1000,9378=>1000,9379=>1000, -9380=>1000,9381=>1000,9382=>1000,9383=>1000,9384=>1000,9385=>1000,9386=>1000,9387=>1000,9388=>1000,9389=>1000, -9390=>1000,9391=>1000,9392=>1000,9393=>1000,9394=>1000,9395=>1000,9396=>1000,9397=>1000,9424=>1000,9425=>1000, -9426=>1000,9427=>1000,9428=>1000,9429=>1000,9430=>1000,9431=>1000,9432=>1000,9433=>1000,9434=>1000,9435=>1000, -9436=>1000,9437=>1000,9438=>1000,9439=>1000,9440=>1000,9441=>1000,9442=>1000,9443=>1000,9444=>1000,9445=>1000, -9446=>1000,9447=>1000,9448=>1000,9449=>1000,8214=>512,8208=>320,8229=>535,8231=>270,9472=>602,9473=>602, -9474=>602,9475=>602,9476=>602,9477=>602,9478=>602,9479=>602,9480=>602,9481=>602,9482=>602,9483=>602, -9484=>602,9485=>602,9486=>602,9487=>602,9488=>602,9489=>602,9490=>602,9491=>602,9492=>602,9493=>602, -9494=>602,9495=>602,9496=>602,9497=>602,9498=>602,9499=>602,9500=>602,9501=>602,9502=>602,9503=>602, -9504=>602,9505=>602,9506=>602,9507=>602,9508=>602,9509=>602,9510=>602,9511=>602,9512=>602,9513=>602, -9514=>602,9515=>602,9516=>602,9517=>602,9518=>602,9519=>602,9520=>602,9521=>602,9522=>602,9523=>602, -9524=>602,9525=>602,9526=>602,9527=>602,9528=>602,9529=>602,9530=>602,9531=>602,9532=>602,9533=>602, -9534=>602,9535=>602,9536=>602,9537=>602,9538=>602,9539=>602,9540=>602,9541=>602,9542=>602,9543=>602, -9544=>602,9545=>602,9546=>602,9547=>602,9552=>602,9553=>602,9554=>602,9555=>602,9556=>602,9557=>602, -9558=>602,9559=>602,9560=>602,9561=>602,9562=>602,9563=>602,9564=>602,9565=>602,9566=>602,9567=>602, -9568=>602,9569=>602,9570=>602,9571=>602,9572=>602,9573=>602,9574=>602,9575=>602,9576=>602,9577=>602, -9578=>602,9579=>602,9580=>602,9581=>602,9582=>602,9583=>602,9584=>602,9585=>602,9586=>602,9587=>602, -9588=>602,9601=>602,9602=>602,9603=>602,9604=>602,9605=>602,9606=>602,9607=>602,9608=>602,9609=>602, -9610=>602,9611=>602,9612=>602,9613=>602,9614=>602,9615=>602,9618=>602,9619=>602,9620=>602,9621=>602, -9632=>602,9633=>602,9635=>602,9636=>602,9637=>602,9638=>602,9639=>602,9640=>602,9641=>602,9650=>602, -9651=>602,9654=>602,9655=>602,9660=>602,9661=>602,9664=>602,9665=>602,9670=>602,9671=>602,9672=>602, -9675=>602,9678=>602,9679=>602,9680=>602,9681=>602,9698=>602,9699=>602,9700=>602,9701=>602,9711=>602, -9733=>1000,9734=>1000,9742=>1000,9743=>1000,9756=>938,9758=>938,9792=>1000,9794=>1000,9824=>1000,9825=>1000, -9827=>1000,9828=>1000,9829=>1000,9831=>1000,9832=>1000,9833=>1000,9834=>1000,9836=>1000,9837=>1000,9839=>1000, -65104=>500,65106=>500,65108=>500,65109=>500,65110=>500,65111=>500,65113=>500,65114=>500,65115=>500,65116=>500, -65117=>500,65118=>500,65119=>500,65120=>500,65121=>500,65122=>500,65123=>500,65124=>500,65125=>500,65126=>500, -65128=>500,65129=>500,65130=>500,65131=>500,8245=>227,8308=>332,462=>531,464=>258,466=>578,468=>590, -470=>590,472=>590,474=>590,476=>590,720=>262,713=>559,714=>578,715=>578,717=>559,8251=>699, -8319=>367,8748=>1000,8750=>500,8756=>1000,8757=>1000,8758=>1000,8759=>1000,8764=>1000,8547=>1000,8321=>332, -8322=>332,8323=>332,8324=>332,8451=>1000,8457=>1000,8481=>1000,8491=>1000,8531=>738,8532=>738,8544=>1000, -8545=>1000,8546=>1000,8548=>1000,8549=>1000,8550=>1000,8551=>1000,8552=>1000,8553=>1000,8554=>1000,8555=>1000, -8560=>1000,8561=>1000,8562=>1000,8564=>1000,8569=>1000,8563=>1000,8565=>1000,8566=>1000,8567=>1000,8568=>1000, -65504=>1000,65505=>1000,65506=>1000,65508=>1000,65509=>1000,65507=>1000,8592=>1000,8593=>500,8594=>1000,8595=>500, -8596=>1000,8597=>500,8598=>1000,8599=>1000,8600=>1000,8601=>1000,8658=>1000,8660=>1000,8704=>1000,8707=>1000, -8711=>1000,8725=>1000,8733=>1000,8712=>1000,8715=>1000,8735=>1000,8736=>1000,8741=>500,8739=>500,8743=>1000, -8744=>1000,8745=>1000,8746=>1000,8765=>1000,8780=>1000,8786=>1000,8801=>1000,8806=>1000,8807=>1000,8810=>1000, -8811=>1000,8814=>1000,8815=>1000,8834=>1000,8835=>1000,8838=>1000,8839=>1000,8869=>1000,8895=>1000,8853=>1000, -8857=>1000,8978=>1000,65510=>1000,12288=>1000,12289=>1000,12290=>1000,12291=>1000,12293=>1000,12294=>1000,12295=>1000, -12296=>1000,12297=>1000,12298=>1000,12299=>1000,12300=>1000,12301=>1000,12302=>1000,12303=>1000,12304=>1000,12305=>1000, -12306=>1000,12307=>1000,12308=>1000,12309=>1000,12310=>1000,12311=>1000,12317=>1000,12318=>1000,12319=>1000,12321=>1000, -12322=>1000,12323=>1000,12324=>1000,12325=>1000,12326=>1000,12327=>1000,12328=>1000,12329=>1000,12353=>1000,12354=>1000, -12355=>1000,12356=>1000,12357=>1000,12358=>1000,12359=>1000,12360=>1000,12361=>1000,12362=>1000,12363=>1000,12364=>1000, -12365=>1000,12366=>1000,12367=>1000,12368=>1000,12369=>1000,12370=>1000,12371=>1000,12372=>1000,12373=>1000,12374=>1000, -12375=>1000,12376=>1000,12377=>1000,12378=>1000,12379=>1000,12380=>1000,12381=>1000,12382=>1000,12383=>1000,12384=>1000, -12385=>1000,12386=>1000,12387=>1000,12388=>1000,12389=>1000,12390=>1000,12391=>1000,12392=>1000,12393=>1000,12394=>1000, -12395=>1000,12396=>1000,12397=>1000,12398=>1000,12399=>1000,12400=>1000,12401=>1000,12402=>1000,12403=>1000,12404=>1000, -12405=>1000,12406=>1000,12407=>1000,12408=>1000,12409=>1000,12410=>1000,12411=>1000,12412=>1000,12413=>1000,12414=>1000, -12415=>1000,12416=>1000,12417=>1000,12418=>1000,12419=>1000,12420=>1000,12421=>1000,12422=>1000,12423=>1000,12424=>1000, -12425=>1000,12426=>1000,12427=>1000,12428=>1000,12429=>1000,12430=>1000,12431=>1000,12432=>1000,12433=>1000,12434=>1000, -12435=>1000,12443=>1000,12444=>1000,12445=>1000,12446=>1000,12449=>1000,12450=>1000,12451=>1000,12452=>1000,12453=>1000, -12454=>1000,12455=>1000,12456=>1000,12457=>1000,12458=>1000,12459=>1000,12460=>1000,12461=>1000,12462=>1000,12463=>1000, -12464=>1000,12465=>1000,12466=>1000,12467=>1000,12468=>1000,12469=>1000,12470=>1000,12471=>1000,12472=>1000,12473=>1000, -12474=>1000,12475=>1000,12476=>1000,12477=>1000,12478=>1000,12479=>1000,12480=>1000,12481=>1000,12482=>1000,12483=>1000, -12484=>1000,12485=>1000,12486=>1000,12487=>1000,12488=>1000,12489=>1000,12490=>1000,12491=>1000,12492=>1000,12493=>1000, -12494=>1000,12495=>1000,12496=>1000,12497=>1000,12498=>1000,12499=>1000,12500=>1000,12501=>1000,12502=>1000,12503=>1000, -12504=>1000,12505=>1000,12506=>1000,12507=>1000,12508=>1000,12509=>1000,12510=>1000,12511=>1000,12512=>1000,12513=>1000, -12514=>1000,12515=>1000,12516=>1000,12517=>1000,12518=>1000,12519=>1000,12520=>1000,12521=>1000,12522=>1000,12523=>1000, -12524=>1000,12525=>1000,12526=>1000,12527=>1000,12528=>1000,12529=>1000,12530=>1000,12531=>1000,12532=>1000,12533=>1000, -12534=>1000,12539=>1000,12540=>1000,12541=>1000,12542=>1000,12549=>1000,12550=>1000,12551=>1000,12552=>1000,12553=>1000, -12554=>1000,12555=>1000,12556=>1000,12557=>1000,12558=>1000,12559=>1000,12560=>1000,12561=>1000,12562=>1000,12563=>1000, -12564=>1000,12565=>1000,12566=>1000,12567=>1000,12568=>1000,12569=>1000,12570=>1000,12571=>1000,12572=>1000,12573=>1000, -12574=>1000,12575=>1000,12576=>1000,12577=>1000,12578=>1000,12579=>1000,12580=>1000,12581=>1000,12582=>1000,12583=>1000, -12584=>1000,12585=>1000,12593=>1000,12594=>1000,12595=>1000,12596=>1000,12597=>1000,12598=>1000,12599=>1000,12600=>1000, -12601=>1000,12602=>1000,12603=>1000,12604=>1000,12605=>1000,12606=>1000,12607=>1000,12608=>1000,12609=>1000,12610=>1000, -12611=>1000,12612=>1000,12613=>1000,12614=>1000,12615=>1000,12616=>1000,12617=>1000,12618=>1000,12619=>1000,12620=>1000, -12621=>1000,12622=>1000,12623=>1000,12624=>1000,12625=>1000,12626=>1000,12627=>1000,12628=>1000,12629=>1000,12630=>1000, -12631=>1000,12632=>1000,12633=>1000,12634=>1000,12635=>1000,12636=>1000,12637=>1000,12638=>1000,12639=>1000,12640=>1000, -12641=>1000,12642=>1000,12643=>1000,12644=>1000,12645=>1000,12646=>1000,12647=>1000,12648=>1000,12649=>1000,12650=>1000, -12651=>1000,12652=>1000,12653=>1000,12654=>1000,12655=>1000,12656=>1000,12657=>1000,12658=>1000,12659=>1000,12660=>1000, -12661=>1000,12662=>1000,12663=>1000,12664=>1000,12665=>1000,12666=>1000,12667=>1000,12668=>1000,12669=>1000,12670=>1000, -12671=>1000,12672=>1000,12673=>1000,12674=>1000,12675=>1000,12676=>1000,12677=>1000,12678=>1000,12679=>1000,12680=>1000, -12681=>1000,12682=>1000,12683=>1000,12684=>1000,12685=>1000,12686=>1000,12800=>1000,12801=>1000,12802=>1000,12803=>1000, -12804=>1000,12805=>1000,12806=>1000,12807=>1000,12808=>1000,12809=>1000,12810=>1000,12811=>1000,12812=>1000,12813=>1000, -12814=>1000,12815=>1000,12816=>1000,12817=>1000,12818=>1000,12819=>1000,12820=>1000,12821=>1000,12822=>1000,12823=>1000, -12824=>1000,12825=>1000,12826=>1000,12827=>1000,12828=>1000,12832=>1000,12833=>1000,12834=>1000,12835=>1000,12836=>1000, -12837=>1000,12838=>1000,12839=>1000,12840=>1000,12841=>1000,12849=>1000,12850=>1000,12857=>1000,12896=>1000,12897=>1000, -12898=>1000,12899=>1000,12900=>1000,12901=>1000,12902=>1000,12903=>1000,12904=>1000,12905=>1000,12906=>1000,12907=>1000, -12908=>1000,12909=>1000,12910=>1000,12911=>1000,12912=>1000,12913=>1000,12914=>1000,12915=>1000,12916=>1000,12917=>1000, -12918=>1000,12919=>1000,12920=>1000,12921=>1000,12922=>1000,12923=>1000,12927=>1000,12963=>1000,12964=>1000,12965=>1000, -12966=>1000,12967=>1000,12968=>1000,13059=>1000,13069=>1000,13076=>1000,13080=>1000,13090=>1000,13091=>1000,13094=>1000, -13095=>1000,13099=>1000,13110=>1000,13115=>1000,13129=>1000,13130=>1000,13133=>1000,13137=>1000,13143=>1000,13179=>1000, -13180=>1000,13181=>1000,13182=>1000,13184=>1000,13185=>1000,13186=>1000,13187=>1000,13188=>1000,13192=>1000,13193=>1000, -13194=>1000,13195=>1000,13196=>1000,13197=>1000,13198=>1000,13199=>1000,13200=>1000,13201=>1000,13202=>1000,13203=>1000, -13204=>1000,13205=>1000,13206=>1000,13207=>1000,13208=>1000,13209=>1000,13210=>1000,13211=>1000,13212=>1000,13213=>1000, -13214=>1000,13215=>1000,13216=>1000,13217=>1000,13218=>1000,13219=>1000,13220=>1000,13221=>1000,13222=>1000,13223=>1000, -13224=>1000,13225=>1000,13226=>1000,13227=>1000,13228=>1000,13229=>1000,13230=>1000,13231=>1000,13232=>1000,13233=>1000, -13234=>1000,13235=>1000,13236=>1000,13237=>1000,13238=>1000,13239=>1000,13240=>1000,13241=>1000,13242=>1000,13243=>1000, -13244=>1000,13245=>1000,13246=>1000,13247=>1000,13248=>1000,13249=>1000,13250=>1000,13251=>1000,13252=>1000,13253=>1000, -13254=>1000,13255=>1000,13256=>1000,13257=>1000,13258=>1000,13261=>1000,13262=>1000,13263=>1000,13264=>1000,13265=>1000, -13266=>1000,13267=>1000,13269=>1000,13270=>1000,13272=>1000,13275=>1000,13276=>1000,13277=>1000,19968=>1000,19969=>1000, -19971=>1000,19975=>1000,19976=>1000,19977=>1000,19978=>1000,19979=>1000,19980=>1000,19981=>1000,19982=>1000,19983=>1000, -19984=>1000,19985=>1000,19987=>1000,19988=>1000,19989=>1000,19990=>1000,19991=>1000,19992=>1000,19993=>1000,19994=>1000, -19995=>1000,19996=>1000,19997=>1000,19998=>1000,19999=>1000,20001=>1000,20002=>1000,20004=>1000,20005=>1000,20006=>1000, -20007=>1000,20008=>1000,20010=>1000,20011=>1000,20012=>1000,20013=>1000,20014=>1000,20016=>1000,20017=>1000,20018=>1000, -20019=>1000,20020=>1000,20022=>1000,20024=>1000,20025=>1000,20026=>1000,20027=>1000,20028=>1000,20029=>1000,20030=>1000, -20031=>1000,20034=>1000,20035=>1000,20037=>1000,20039=>1000,20040=>1000,20041=>1000,20043=>1000,20044=>1000,20045=>1000, -20046=>1000,20047=>1000,20048=>1000,20050=>1000,20051=>1000,20052=>1000,20053=>1000,20054=>1000,20055=>1000,20056=>1000, -20057=>1000,20060=>1000,20061=>1000,20062=>1000,20063=>1000,20064=>1000,20065=>1000,20066=>1000,20070=>1000,20073=>1000, -20075=>1000,20077=>1000,20080=>1000,20081=>1000,20083=>1000,20086=>1000,20087=>1000,20094=>1000,20095=>1000,20096=>1000, -20098=>1000,20099=>1000,20100=>1000,20101=>1000,20102=>1000,20104=>1000,20105=>1000,20106=>1000,20107=>1000,20108=>1000, -20109=>1000,20110=>1000,20111=>1000,20112=>1000,20113=>1000,20114=>1000,20115=>1000,20116=>1000,20117=>1000,20120=>1000, -20121=>1000,20122=>1000,20123=>1000,20124=>1000,20126=>1000,20127=>1000,20128=>1000,20129=>1000,20130=>1000,20132=>1000, -20133=>1000,20134=>1000,20135=>1000,20136=>1000,20137=>1000,20139=>1000,20140=>1000,20141=>1000,20142=>1000,20144=>1000, -20146=>1000,20147=>1000,20149=>1000,20150=>1000,20153=>1000,20154=>1000,20155=>1000,20159=>1000,20160=>1000,20161=>1000, -20162=>1000,20163=>1000,20164=>1000,20165=>1000,20166=>1000,20167=>1000,20168=>1000,20169=>1000,20170=>1000,20171=>1000, -20173=>1000,20174=>1000,20175=>1000,20177=>1000,20179=>1000,20180=>1000,20181=>1000,20182=>1000,20183=>1000,20184=>1000, -20185=>1000,20186=>1000,20188=>1000,20189=>1000,20190=>1000,20191=>1000,20193=>1000,20195=>1000,20196=>1000,20197=>1000, -20200=>1000,20201=>1000,20202=>1000,20203=>1000,20204=>1000,20205=>1000,20206=>1000,20208=>1000,20209=>1000,20210=>1000, -20211=>1000,20212=>1000,20213=>1000,20214=>1000,20215=>1000,20219=>1000,20220=>1000,20221=>1000,20223=>1000,20224=>1000, -20225=>1000,20226=>1000,20227=>1000,20228=>1000,20229=>1000,20232=>1000,20233=>1000,20234=>1000,20235=>1000,20237=>1000, -20238=>1000,20239=>1000,20240=>1000,20241=>1000,20242=>1000,20243=>1000,20244=>1000,20245=>1000,20247=>1000,20248=>1000, -20249=>1000,20250=>1000,20251=>1000,20252=>1000,20253=>1000,20254=>1000,20255=>1000,20256=>1000,20258=>1000,20260=>1000, -20261=>1000,20262=>1000,20263=>1000,20266=>1000,20267=>1000,20268=>1000,20269=>1000,20271=>1000,20272=>1000,20274=>1000, -20275=>1000,20276=>1000,20278=>1000,20280=>1000,20281=>1000,20282=>1000,20283=>1000,20284=>1000,20285=>1000,20286=>1000, -20287=>1000,20289=>1000,20291=>1000,20294=>1000,20295=>1000,20296=>1000,20297=>1000,20300=>1000,20301=>1000,20302=>1000, -20303=>1000,20304=>1000,20305=>1000,20306=>1000,20307=>1000,20308=>1000,20309=>1000,20310=>1000,20311=>1000,20312=>1000, -20313=>1000,20314=>1000,20315=>1000,20316=>1000,20317=>1000,20318=>1000,20319=>1000,20320=>1000,20321=>1000,20322=>1000, -20323=>1000,20324=>1000,20325=>1000,20327=>1000,20329=>1000,20330=>1000,20331=>1000,20332=>1000,20334=>1000,20335=>1000, -20336=>1000,20339=>1000,20340=>1000,20341=>1000,20342=>1000,20343=>1000,20344=>1000,20345=>1000,20346=>1000,20347=>1000, -20348=>1000,20349=>1000,20350=>1000,20351=>1000,20352=>1000,20353=>1000,20354=>1000,20355=>1000,20356=>1000,20357=>1000, -20358=>1000,20359=>1000,20360=>1000,20361=>1000,20362=>1000,20363=>1000,20365=>1000,20367=>1000,20368=>1000,20369=>1000, -20370=>1000,20372=>1000,20373=>1000,20374=>1000,20375=>1000,20376=>1000,20378=>1000,20379=>1000,20380=>1000,20381=>1000, -20382=>1000,20384=>1000,20385=>1000,20387=>1000,20389=>1000,20390=>1000,20391=>1000,20392=>1000,20393=>1000,20394=>1000, -20395=>1000,20396=>1000,20397=>1000,20398=>1000,20399=>1000,20402=>1000,20403=>1000,20405=>1000,20406=>1000,20407=>1000, -20409=>1000,20410=>1000,20411=>1000,20415=>1000,20416=>1000,20417=>1000,20418=>1000,20419=>1000,20420=>1000,20421=>1000, -20423=>1000,20425=>1000,20426=>1000,20427=>1000,20429=>1000,20430=>1000,20431=>1000,20432=>1000,20433=>1000,20435=>1000, -20436=>1000,20438=>1000,20439=>1000,20440=>1000,20441=>1000,20442=>1000,20443=>1000,20444=>1000,20445=>1000,20446=>1000, -20447=>1000,20448=>1000,20449=>1000,20451=>1000,20452=>1000,20453=>1000,20454=>1000,20456=>1000,20457=>1000,20458=>1000, -20460=>1000,20461=>1000,20462=>1000,20463=>1000,20465=>1000,20467=>1000,20468=>1000,20469=>1000,20470=>1000,20471=>1000, -20472=>1000,20474=>1000,20478=>1000,20479=>1000,20480=>1000,20482=>1000,20485=>1000,20486=>1000,20487=>1000,20489=>1000, -20491=>1000,20492=>1000,20493=>1000,20494=>1000,20495=>1000,20497=>1000,20498=>1000,20499=>1000,20500=>1000,20501=>1000, -20502=>1000,20503=>1000,20504=>1000,20505=>1000,20506=>1000,20507=>1000,20508=>1000,20510=>1000,20511=>1000,20512=>1000, -20513=>1000,20514=>1000,20515=>1000,20516=>1000,20517=>1000,20518=>1000,20519=>1000,20520=>1000,20521=>1000,20522=>1000, -20523=>1000,20524=>1000,20525=>1000,20526=>1000,20527=>1000,20528=>1000,20529=>1000,20531=>1000,20533=>1000,20534=>1000, -20535=>1000,20537=>1000,20538=>1000,20539=>1000,20540=>1000,20542=>1000,20544=>1000,20545=>1000,20546=>1000,20547=>1000, -20549=>1000,20550=>1000,20551=>1000,20552=>1000,20553=>1000,20554=>1000,20555=>1000,20556=>1000,20557=>1000,20558=>1000, -20559=>1000,20560=>1000,20561=>1000,20563=>1000,20565=>1000,20566=>1000,20567=>1000,20570=>1000,20571=>1000,20572=>1000, -20573=>1000,20574=>1000,20575=>1000,20576=>1000,20577=>1000,20578=>1000,20579=>1000,20580=>1000,20581=>1000,20584=>1000, -20585=>1000,20586=>1000,20587=>1000,20588=>1000,20589=>1000,20590=>1000,20591=>1000,20592=>1000,20594=>1000,20595=>1000, -20596=>1000,20597=>1000,20598=>1000,20599=>1000,20600=>1000,20602=>1000,20603=>1000,20605=>1000,20606=>1000,20607=>1000, -20608=>1000,20610=>1000,20611=>1000,20613=>1000,20615=>1000,20616=>1000,20619=>1000,20620=>1000,20621=>1000,20622=>1000, -20625=>1000,20626=>1000,20628=>1000,20629=>1000,20630=>1000,20632=>1000,20633=>1000,20634=>1000,20635=>1000,20636=>1000, -20637=>1000,20638=>1000,20642=>1000,20643=>1000,20645=>1000,20647=>1000,20648=>1000,20649=>1000,20652=>1000,20653=>1000, -20654=>1000,20655=>1000,20656=>1000,20657=>1000,20658=>1000,20659=>1000,20660=>1000,20661=>1000,20662=>1000,20663=>1000, -20664=>1000,20666=>1000,20667=>1000,20669=>1000,20670=>1000,20671=>1000,20673=>1000,20674=>1000,20676=>1000,20677=>1000, -20678=>1000,20679=>1000,20680=>1000,20681=>1000,20682=>1000,20683=>1000,20685=>1000,20686=>1000,20687=>1000,20689=>1000, -20691=>1000,20692=>1000,20693=>1000,20694=>1000,20695=>1000,20696=>1000,20698=>1000,20699=>1000,20701=>1000,20702=>1000, -20704=>1000,20707=>1000,20708=>1000,20709=>1000,20710=>1000,20711=>1000,20712=>1000,20713=>1000,20714=>1000,20716=>1000, -20717=>1000,20718=>1000,20719=>1000,20720=>1000,20721=>1000,20723=>1000,20724=>1000,20725=>1000,20726=>1000,20728=>1000, -20729=>1000,20731=>1000,20733=>1000,20734=>1000,20735=>1000,20736=>1000,20737=>1000,20738=>1000,20739=>1000,20740=>1000, -20741=>1000,20742=>1000,20743=>1000,20744=>1000,20745=>1000,20746=>1000,20747=>1000,20748=>1000,20752=>1000,20753=>1000, -20754=>1000,20755=>1000,20756=>1000,20757=>1000,20758=>1000,20759=>1000,20760=>1000,20762=>1000,20764=>1000,20767=>1000, -20768=>1000,20769=>1000,20770=>1000,20772=>1000,20773=>1000,20774=>1000,20777=>1000,20778=>1000,20781=>1000,20782=>1000, -20784=>1000,20785=>1000,20786=>1000,20787=>1000,20788=>1000,20789=>1000,20791=>1000,20792=>1000,20793=>1000,20794=>1000, -20795=>1000,20796=>1000,20797=>1000,20799=>1000,20800=>1000,20801=>1000,20803=>1000,20804=>1000,20805=>1000,20806=>1000, -20807=>1000,20808=>1000,20809=>1000,20810=>1000,20811=>1000,20812=>1000,20813=>1000,20814=>1000,20816=>1000,20817=>1000, -20818=>1000,20820=>1000,20821=>1000,20822=>1000,20823=>1000,20825=>1000,20826=>1000,20827=>1000,20828=>1000,20829=>1000, -20830=>1000,20831=>1000,20833=>1000,20834=>1000,20835=>1000,20836=>1000,20837=>1000,20839=>1000,20840=>1000,20841=>1000, -20842=>1000,20843=>1000,20844=>1000,20845=>1000,20846=>1000,20848=>1000,20849=>1000,20851=>1000,20852=>1000,20853=>1000, -20854=>1000,20855=>1000,20856=>1000,20857=>1000,20859=>1000,20860=>1000,20861=>1000,20864=>1000,20865=>1000,20866=>1000, -20869=>1000,20870=>1000,20871=>1000,20872=>1000,20873=>1000,20874=>1000,20876=>1000,20877=>1000,20879=>1000,20880=>1000, -20881=>1000,20882=>1000,20883=>1000,20884=>1000,20885=>1000,20886=>1000,20887=>1000,20888=>1000,20889=>1000,20891=>1000, -20892=>1000,20893=>1000,20894=>1000,20896=>1000,20898=>1000,20900=>1000,20901=>1000,20902=>1000,20904=>1000,20905=>1000, -20906=>1000,20907=>1000,20908=>1000,20911=>1000,20912=>1000,20913=>1000,20914=>1000,20915=>1000,20916=>1000,20917=>1000, -20918=>1000,20919=>1000,20921=>1000,20923=>1000,20924=>1000,20925=>1000,20926=>1000,20928=>1000,20932=>1000,20933=>1000, -20934=>1000,20935=>1000,20936=>1000,20937=>1000,20938=>1000,20939=>1000,20940=>1000,20941=>1000,20942=>1000,20943=>1000, -20944=>1000,20945=>1000,20948=>1000,20950=>1000,20951=>1000,20952=>1000,20955=>1000,20956=>1000,20957=>1000,20958=>1000, -20960=>1000,20961=>1000,20964=>1000,20966=>1000,20967=>1000,20969=>1000,20970=>1000,20971=>1000,20972=>1000,20973=>1000, -20975=>1000,20976=>1000,20977=>1000,20979=>1000,20981=>1000,20982=>1000,20984=>1000,20985=>1000,20986=>1000,20987=>1000, -20988=>1000,20989=>1000,20990=>1000,20991=>1000,20992=>1000,20993=>1000,20994=>1000,20995=>1000,20996=>1000,20998=>1000, -20999=>1000,21000=>1000,21001=>1000,21002=>1000,21003=>1000,21004=>1000,21005=>1000,21006=>1000,21008=>1000,21009=>1000, -21010=>1000,21011=>1000,21012=>1000,21013=>1000,21014=>1000,21015=>1000,21016=>1000,21017=>1000,21018=>1000,21019=>1000, -21020=>1000,21021=>1000,21022=>1000,21024=>1000,21025=>1000,21028=>1000,21029=>1000,21031=>1000,21032=>1000,21033=>1000, -21034=>1000,21035=>1000,21037=>1000,21038=>1000,21040=>1000,21041=>1000,21042=>1000,21043=>1000,21045=>1000,21046=>1000, -21047=>1000,21048=>1000,21049=>1000,21050=>1000,21051=>1000,21053=>1000,21055=>1000,21056=>1000,21057=>1000,21058=>1000, -21059=>1000,21060=>1000,21062=>1000,21063=>1000,21065=>1000,21066=>1000,21067=>1000,21068=>1000,21069=>1000,21070=>1000, -21071=>1000,21072=>1000,21073=>1000,21074=>1000,21076=>1000,21077=>1000,21078=>1000,21082=>1000,21083=>1000,21084=>1000, -21085=>1000,21086=>1000,21087=>1000,21089=>1000,21090=>1000,21091=>1000,21092=>1000,21093=>1000,21095=>1000,21097=>1000, -21098=>1000,21099=>1000,21100=>1000,21101=>1000,21102=>1000,21103=>1000,21104=>1000,21105=>1000,21106=>1000,21107=>1000, -21108=>1000,21109=>1000,21111=>1000,21112=>1000,21114=>1000,21115=>1000,21116=>1000,21117=>1000,21119=>1000,21120=>1000, -21121=>1000,21122=>1000,21123=>1000,21124=>1000,21127=>1000,21128=>1000,21129=>1000,21130=>1000,21131=>1000,21132=>1000, -21133=>1000,21136=>1000,21137=>1000,21138=>1000,21139=>1000,21140=>1000,21142=>1000,21143=>1000,21144=>1000,21145=>1000, -21147=>1000,21148=>1000,21149=>1000,21150=>1000,21151=>1000,21152=>1000,21153=>1000,21154=>1000,21155=>1000,21156=>1000, -21158=>1000,21160=>1000,21161=>1000,21162=>1000,21163=>1000,21164=>1000,21165=>1000,21166=>1000,21167=>1000,21169=>1000, -21170=>1000,21171=>1000,21172=>1000,21173=>1000,21177=>1000,21179=>1000,21180=>1000,21182=>1000,21183=>1000,21184=>1000, -21185=>1000,21186=>1000,21187=>1000,21189=>1000,21191=>1000,21193=>1000,21195=>1000,21197=>1000,21200=>1000,21202=>1000, -21203=>1000,21205=>1000,21206=>1000,21207=>1000,21208=>1000,21209=>1000,21211=>1000,21213=>1000,21214=>1000,21215=>1000, -21216=>1000,21218=>1000,21219=>1000,21220=>1000,21222=>1000,21223=>1000,21225=>1000,21227=>1000,21231=>1000,21232=>1000, -21233=>1000,21234=>1000,21235=>1000,21236=>1000,21237=>1000,21239=>1000,21240=>1000,21241=>1000,21242=>1000,21243=>1000, -21244=>1000,21246=>1000,21247=>1000,21248=>1000,21249=>1000,21250=>1000,21253=>1000,21254=>1000,21255=>1000,21256=>1000, -21257=>1000,21258=>1000,21259=>1000,21261=>1000,21262=>1000,21263=>1000,21264=>1000,21265=>1000,21266=>1000,21269=>1000, -21270=>1000,21271=>1000,21273=>1000,21274=>1000,21276=>1000,21277=>1000,21279=>1000,21280=>1000,21281=>1000,21282=>1000, -21283=>1000,21284=>1000,21286=>1000,21290=>1000,21293=>1000,21294=>1000,21295=>1000,21296=>1000,21297=>1000,21299=>1000, -21300=>1000,21303=>1000,21304=>1000,21305=>1000,21306=>1000,21307=>1000,21308=>1000,21309=>1000,21310=>1000,21311=>1000, -21312=>1000,21313=>1000,21315=>1000,21316=>1000,21317=>1000,21318=>1000,21319=>1000,21320=>1000,21321=>1000,21322=>1000, -21324=>1000,21325=>1000,21326=>1000,21327=>1000,21329=>1000,21330=>1000,21331=>1000,21332=>1000,21333=>1000,21334=>1000, -21335=>1000,21336=>1000,21338=>1000,21340=>1000,21342=>1000,21343=>1000,21344=>1000,21345=>1000,21346=>1000,21347=>1000, -21348=>1000,21350=>1000,21351=>1000,21352=>1000,21353=>1000,21355=>1000,21356=>1000,21358=>1000,21359=>1000,21360=>1000, -21361=>1000,21362=>1000,21363=>1000,21364=>1000,21365=>1000,21367=>1000,21368=>1000,21369=>1000,21370=>1000,21371=>1000, -21372=>1000,21373=>1000,21375=>1000,21378=>1000,21380=>1000,21381=>1000,21382=>1000,21385=>1000,21386=>1000,21387=>1000, -21388=>1000,21389=>1000,21390=>1000,21391=>1000,21394=>1000,21395=>1000,21396=>1000,21397=>1000,21398=>1000,21399=>1000, -21400=>1000,21401=>1000,21402=>1000,21404=>1000,21405=>1000,21406=>1000,21407=>1000,21408=>1000,21410=>1000,21411=>1000, -21412=>1000,21413=>1000,21414=>1000,21415=>1000,21416=>1000,21417=>1000,21420=>1000,21421=>1000,21422=>1000,21424=>1000, -21426=>1000,21427=>1000,21428=>1000,21430=>1000,21433=>1000,21435=>1000,21439=>1000,21441=>1000,21442=>1000,21443=>1000, -21448=>1000,21449=>1000,21450=>1000,21451=>1000,21452=>1000,21453=>1000,21454=>1000,21457=>1000,21460=>1000,21462=>1000, -21463=>1000,21464=>1000,21465=>1000,21467=>1000,21469=>1000,21471=>1000,21472=>1000,21473=>1000,21474=>1000,21475=>1000, -21476=>1000,21477=>1000,21478=>1000,21480=>1000,21481=>1000,21482=>1000,21483=>1000,21484=>1000,21485=>1000,21486=>1000, -21487=>1000,21488=>1000,21489=>1000,21490=>1000,21491=>1000,21493=>1000,21494=>1000,21495=>1000,21496=>1000,21497=>1000, -21498=>1000,21499=>1000,21500=>1000,21501=>1000,21505=>1000,21507=>1000,21508=>1000,21510=>1000,21511=>1000,21512=>1000, -21513=>1000,21514=>1000,21515=>1000,21516=>1000,21517=>1000,21518=>1000,21519=>1000,21520=>1000,21521=>1000,21522=>1000, -21523=>1000,21525=>1000,21526=>1000,21527=>1000,21528=>1000,21529=>1000,21531=>1000,21532=>1000,21533=>1000,21534=>1000, -21535=>1000,21536=>1000,21537=>1000,21539=>1000,21540=>1000,21541=>1000,21542=>1000,21543=>1000,21544=>1000,21545=>1000, -21546=>1000,21547=>1000,21548=>1000,21549=>1000,21550=>1000,21551=>1000,21552=>1000,21553=>1000,21554=>1000,21555=>1000, -21556=>1000,21557=>1000,21558=>1000,21559=>1000,21560=>1000,21561=>1000,21563=>1000,21564=>1000,21565=>1000,21566=>1000, -21568=>1000,21569=>1000,21570=>1000,21571=>1000,21573=>1000,21574=>1000,21575=>1000,21576=>1000,21577=>1000,21578=>1000, -21579=>1000,21582=>1000,21583=>1000,21584=>1000,21585=>1000,21586=>1000,21587=>1000,21588=>1000,21589=>1000,21590=>1000, -21591=>1000,21592=>1000,21593=>1000,21595=>1000,21596=>1000,21599=>1000,21600=>1000,21601=>1000,21602=>1000,21603=>1000, -21604=>1000,21605=>1000,21606=>1000,21607=>1000,21608=>1000,21610=>1000,21611=>1000,21612=>1000,21615=>1000,21616=>1000, -21617=>1000,21618=>1000,21619=>1000,21620=>1000,21621=>1000,21622=>1000,21623=>1000,21624=>1000,21626=>1000,21627=>1000, -21628=>1000,21629=>1000,21630=>1000,21631=>1000,21632=>1000,21633=>1000,21634=>1000,21636=>1000,21638=>1000,21639=>1000, -21640=>1000,21642=>1000,21643=>1000,21644=>1000,21645=>1000,21646=>1000,21647=>1000,21648=>1000,21649=>1000,21650=>1000, -21652=>1000,21653=>1000,21654=>1000,21656=>1000,21657=>1000,21658=>1000,21659=>1000,21660=>1000,21661=>1000,21664=>1000, -21665=>1000,21666=>1000,21667=>1000,21668=>1000,21669=>1000,21670=>1000,21671=>1000,21672=>1000,21673=>1000,21674=>1000, -21675=>1000,21676=>1000,21677=>1000,21678=>1000,21679=>1000,21680=>1000,21681=>1000,21682=>1000,21683=>1000,21684=>1000, -21686=>1000,21687=>1000,21688=>1000,21690=>1000,21691=>1000,21692=>1000,21693=>1000,21694=>1000,21695=>1000,21696=>1000, -21697=>1000,21698=>1000,21699=>1000,21700=>1000,21701=>1000,21702=>1000,21703=>1000,21704=>1000,21705=>1000,21708=>1000, -21709=>1000,21710=>1000,21711=>1000,21712=>1000,21713=>1000,21714=>1000,21715=>1000,21716=>1000,21717=>1000,21718=>1000, -21719=>1000,21720=>1000,21721=>1000,21722=>1000,21724=>1000,21725=>1000,21726=>1000,21727=>1000,21728=>1000,21729=>1000, -21730=>1000,21732=>1000,21733=>1000,21734=>1000,21735=>1000,21736=>1000,21737=>1000,21738=>1000,21739=>1000,21741=>1000, -21742=>1000,21745=>1000,21746=>1000,21747=>1000,21751=>1000,21752=>1000,21754=>1000,21755=>1000,21756=>1000,21757=>1000, -21759=>1000,21761=>1000,21763=>1000,21764=>1000,21765=>1000,21766=>1000,21767=>1000,21768=>1000,21769=>1000,21770=>1000, -21771=>1000,21772=>1000,21774=>1000,21775=>1000,21776=>1000,21777=>1000,21778=>1000,21780=>1000,21782=>1000,21783=>1000, -21786=>1000,21787=>1000,21788=>1000,21792=>1000,21794=>1000,21795=>1000,21796=>1000,21798=>1000,21799=>1000,21802=>1000, -21804=>1000,21805=>1000,21806=>1000,21807=>1000,21808=>1000,21809=>1000,21810=>1000,21811=>1000,21812=>1000,21813=>1000, -21814=>1000,21815=>1000,21816=>1000,21817=>1000,21819=>1000,21820=>1000,21822=>1000,21823=>1000,21824=>1000,21825=>1000, -21827=>1000,21828=>1000,21829=>1000,21830=>1000,21832=>1000,21833=>1000,21834=>1000,21835=>1000,21836=>1000,21837=>1000, -21838=>1000,21839=>1000,21840=>1000,21841=>1000,21842=>1000,21843=>1000,21845=>1000,21846=>1000,21847=>1000,21852=>1000, -21853=>1000,21854=>1000,21855=>1000,21857=>1000,21858=>1000,21859=>1000,21860=>1000,21861=>1000,21862=>1000,21863=>1000, -21866=>1000,21868=>1000,21869=>1000,21870=>1000,21877=>1000,21878=>1000,21879=>1000,21880=>1000,21883=>1000,21884=>1000, -21885=>1000,21886=>1000,21887=>1000,21888=>1000,21889=>1000,21890=>1000,21891=>1000,21892=>1000,21894=>1000,21895=>1000, -21896=>1000,21897=>1000,21898=>1000,21899=>1000,21900=>1000,21901=>1000,21902=>1000,21903=>1000,21905=>1000,21906=>1000, -21907=>1000,21908=>1000,21909=>1000,21912=>1000,21913=>1000,21914=>1000,21916=>1000,21917=>1000,21918=>1000,21919=>1000, -21921=>1000,21922=>1000,21923=>1000,21924=>1000,21925=>1000,21926=>1000,21927=>1000,21928=>1000,21929=>1000,21930=>1000, -21931=>1000,21932=>1000,21933=>1000,21934=>1000,21936=>1000,21937=>1000,21938=>1000,21939=>1000,21941=>1000,21942=>1000, -21943=>1000,21945=>1000,21947=>1000,21949=>1000,21950=>1000,21951=>1000,21952=>1000,21954=>1000,21955=>1000,21956=>1000, -21957=>1000,21958=>1000,21959=>1000,21960=>1000,21961=>1000,21962=>1000,21963=>1000,21964=>1000,21965=>1000,21966=>1000, -21967=>1000,21968=>1000,21969=>1000,21970=>1000,21971=>1000,21972=>1000,21973=>1000,21974=>1000,21977=>1000,21978=>1000, -21979=>1000,21980=>1000,21981=>1000,21983=>1000,21985=>1000,21986=>1000,21987=>1000,21988=>1000,21989=>1000,21990=>1000, -21991=>1000,21992=>1000,21993=>1000,21994=>1000,21995=>1000,21996=>1000,21999=>1000,22002=>1000,22003=>1000,22005=>1000, -22006=>1000,22007=>1000,22009=>1000,22010=>1000,22012=>1000,22013=>1000,22014=>1000,22015=>1000,22016=>1000,22017=>1000, -22018=>1000,22020=>1000,22022=>1000,22024=>1000,22025=>1000,22028=>1000,22029=>1000,22030=>1000,22031=>1000,22032=>1000, -22034=>1000,22035=>1000,22036=>1000,22037=>1000,22038=>1000,22039=>1000,22040=>1000,22043=>1000,22044=>1000,22045=>1000, -22046=>1000,22047=>1000,22051=>1000,22052=>1000,22055=>1000,22057=>1000,22058=>1000,22060=>1000,22061=>1000,22062=>1000, -22063=>1000,22064=>1000,22065=>1000,22066=>1000,22067=>1000,22068=>1000,22069=>1000,22070=>1000,22072=>1000,22073=>1000, -22074=>1000,22075=>1000,22077=>1000,22078=>1000,22079=>1000,22080=>1000,22081=>1000,22082=>1000,22085=>1000,22086=>1000, -22088=>1000,22089=>1000,22090=>1000,22092=>1000,22093=>1000,22094=>1000,22096=>1000,22099=>1000,22100=>1000,22103=>1000, -22104=>1000,22105=>1000,22106=>1000,22107=>1000,22108=>1000,22110=>1000,22112=>1000,22114=>1000,22115=>1000,22116=>1000, -22117=>1000,22118=>1000,22120=>1000,22121=>1000,22122=>1000,22123=>1000,22124=>1000,22125=>1000,22126=>1000,22127=>1000, -22128=>1000,22129=>1000,22130=>1000,22131=>1000,22132=>1000,22134=>1000,22135=>1000,22136=>1000,22137=>1000,22138=>1000, -22139=>1000,22140=>1000,22142=>1000,22143=>1000,22144=>1000,22145=>1000,22146=>1000,22147=>1000,22148=>1000,22149=>1000, -22150=>1000,22151=>1000,22154=>1000,22156=>1000,22157=>1000,22158=>1000,22159=>1000,22160=>1000,22163=>1000,22164=>1000, -22165=>1000,22167=>1000,22168=>1000,22169=>1000,22170=>1000,22172=>1000,22173=>1000,22176=>1000,22178=>1000,22179=>1000, -22181=>1000,22182=>1000,22183=>1000,22184=>1000,22186=>1000,22187=>1000,22188=>1000,22189=>1000,22190=>1000,22191=>1000, -22194=>1000,22195=>1000,22196=>1000,22197=>1000,22198=>1000,22199=>1000,22204=>1000,22205=>1000,22206=>1000,22208=>1000, -22209=>1000,22210=>1000,22211=>1000,22213=>1000,22214=>1000,22216=>1000,22217=>1000,22218=>1000,22219=>1000,22220=>1000, -22221=>1000,22222=>1000,22225=>1000,22227=>1000,22228=>1000,22231=>1000,22232=>1000,22234=>1000,22235=>1000,22237=>1000, -22238=>1000,22239=>1000,22240=>1000,22241=>1000,22242=>1000,22243=>1000,22244=>1000,22245=>1000,22247=>1000,22250=>1000, -22251=>1000,22253=>1000,22254=>1000,22256=>1000,22257=>1000,22258=>1000,22259=>1000,22260=>1000,22261=>1000,22263=>1000, -22265=>1000,22266=>1000,22269=>1000,22270=>1000,22271=>1000,22272=>1000,22273=>1000,22274=>1000,22275=>1000,22276=>1000, -22278=>1000,22279=>1000,22280=>1000,22281=>1000,22282=>1000,22283=>1000,22284=>1000,22285=>1000,22287=>1000,22290=>1000, -22291=>1000,22292=>1000,22294=>1000,22296=>1000,22298=>1000,22299=>1000,22300=>1000,22302=>1000,22303=>1000,22304=>1000, -22306=>1000,22307=>1000,22310=>1000,22311=>1000,22312=>1000,22313=>1000,22314=>1000,22316=>1000,22317=>1000,22318=>1000, -22319=>1000,22320=>1000,22323=>1000,22324=>1000,22327=>1000,22328=>1000,22329=>1000,22330=>1000,22331=>1000,22334=>1000, -22336=>1000,22337=>1000,22338=>1000,22341=>1000,22343=>1000,22345=>1000,22346=>1000,22347=>1000,22348=>1000,22349=>1000, -22350=>1000,22351=>1000,22352=>1000,22353=>1000,22354=>1000,22359=>1000,22361=>1000,22362=>1000,22363=>1000,22364=>1000, -22365=>1000,22366=>1000,22367=>1000,22368=>1000,22369=>1000,22370=>1000,22372=>1000,22373=>1000,22374=>1000,22376=>1000, -22377=>1000,22378=>1000,22379=>1000,22381=>1000,22382=>1000,22383=>1000,22384=>1000,22385=>1000,22386=>1000,22387=>1000, -22388=>1000,22389=>1000,22390=>1000,22391=>1000,22395=>1000,22396=>1000,22397=>1000,22399=>1000,22400=>1000,22402=>1000, -22403=>1000,22404=>1000,22405=>1000,22406=>1000,22408=>1000,22409=>1000,22411=>1000,22412=>1000,22415=>1000,22418=>1000, -22419=>1000,22420=>1000,22421=>1000,22423=>1000,22424=>1000,22425=>1000,22426=>1000,22427=>1000,22429=>1000,22430=>1000, -22431=>1000,22432=>1000,22433=>1000,22434=>1000,22435=>1000,22436=>1000,22437=>1000,22438=>1000,22439=>1000,22441=>1000, -22442=>1000,22443=>1000,22444=>1000,22445=>1000,22446=>1000,22448=>1000,22450=>1000,22451=>1000,22452=>1000,22453=>1000, -22454=>1000,22456=>1000,22457=>1000,22458=>1000,22460=>1000,22461=>1000,22463=>1000,22464=>1000,22465=>1000,22466=>1000, -22467=>1000,22470=>1000,22471=>1000,22472=>1000,22475=>1000,22476=>1000,22478=>1000,22479=>1000,22480=>1000,22482=>1000, -22483=>1000,22484=>1000,22485=>1000,22486=>1000,22488=>1000,22489=>1000,22490=>1000,22492=>1000,22493=>1000,22495=>1000, -22496=>1000,22497=>1000,22498=>1000,22499=>1000,22500=>1000,22501=>1000,22503=>1000,22505=>1000,22508=>1000,22509=>1000, -22510=>1000,22511=>1000,22512=>1000,22513=>1000,22514=>1000,22515=>1000,22516=>1000,22517=>1000,22518=>1000,22519=>1000, -22520=>1000,22521=>1000,22522=>1000,22523=>1000,22524=>1000,22525=>1000,22528=>1000,22529=>1000,22530=>1000,22532=>1000, -22533=>1000,22534=>1000,22535=>1000,22536=>1000,22537=>1000,22538=>1000,22539=>1000,22540=>1000,22541=>1000,22542=>1000, -22544=>1000,22545=>1000,22548=>1000,22549=>1000,22553=>1000,22555=>1000,22556=>1000,22557=>1000,22558=>1000,22560=>1000, -22561=>1000,22563=>1000,22564=>1000,22565=>1000,22567=>1000,22568=>1000,22569=>1000,22570=>1000,22572=>1000,22573=>1000, -22574=>1000,22575=>1000,22576=>1000,22577=>1000,22578=>1000,22579=>1000,22580=>1000,22581=>1000,22582=>1000,22583=>1000, -22584=>1000,22585=>1000,22586=>1000,22587=>1000,22589=>1000,22591=>1000,22592=>1000,22593=>1000,22596=>1000,22600=>1000, -22601=>1000,22602=>1000,22603=>1000,22604=>1000,22605=>1000,22606=>1000,22607=>1000,22609=>1000,22610=>1000,22611=>1000, -22612=>1000,22613=>1000,22615=>1000,22616=>1000,22617=>1000,22618=>1000,22619=>1000,22621=>1000,22622=>1000,22625=>1000, -22626=>1000,22627=>1000,22628=>1000,22629=>1000,22632=>1000,22633=>1000,22635=>1000,22636=>1000,22637=>1000,22639=>1000, -22640=>1000,22641=>1000,22642=>1000,22644=>1000,22645=>1000,22646=>1000,22649=>1000,22650=>1000,22651=>1000,22652=>1000, -22653=>1000,22654=>1000,22655=>1000,22656=>1000,22657=>1000,22658=>1000,22659=>1000,22661=>1000,22662=>1000,22663=>1000, -22664=>1000,22665=>1000,22666=>1000,22667=>1000,22670=>1000,22671=>1000,22672=>1000,22673=>1000,22674=>1000,22675=>1000, -22676=>1000,22679=>1000,22680=>1000,22681=>1000,22682=>1000,22684=>1000,22685=>1000,22686=>1000,22687=>1000,22688=>1000, -22689=>1000,22691=>1000,22693=>1000,22694=>1000,22696=>1000,22697=>1000,22699=>1000,22700=>1000,22702=>1000,22703=>1000, -22705=>1000,22706=>1000,22707=>1000,22712=>1000,22713=>1000,22714=>1000,22715=>1000,22716=>1000,22717=>1000,22718=>1000, -22719=>1000,22721=>1000,22722=>1000,22725=>1000,22726=>1000,22727=>1000,22728=>1000,22729=>1000,22730=>1000,22732=>1000, -22734=>1000,22735=>1000,22737=>1000,22738=>1000,22739=>1000,22740=>1000,22741=>1000,22742=>1000,22743=>1000,22744=>1000, -22745=>1000,22746=>1000,22747=>1000,22748=>1000,22749=>1000,22750=>1000,22751=>1000,22754=>1000,22755=>1000,22756=>1000, -22757=>1000,22759=>1000,22760=>1000,22761=>1000,22763=>1000,22764=>1000,22766=>1000,22767=>1000,22768=>1000,22769=>1000, -22770=>1000,22771=>1000,22772=>1000,22774=>1000,22775=>1000,22777=>1000,22778=>1000,22779=>1000,22780=>1000,22781=>1000, -22782=>1000,22783=>1000,22786=>1000,22787=>1000,22788=>1000,22790=>1000,22791=>1000,22793=>1000,22794=>1000,22795=>1000, -22796=>1000,22797=>1000,22798=>1000,22799=>1000,22800=>1000,22802=>1000,22804=>1000,22805=>1000,22806=>1000,22807=>1000, -22808=>1000,22809=>1000,22810=>1000,22811=>1000,22812=>1000,22815=>1000,22816=>1000,22818=>1000,22820=>1000,22821=>1000, -22823=>1000,22825=>1000,22826=>1000,22827=>1000,22828=>1000,22829=>1000,22830=>1000,22831=>1000,22833=>1000,22834=>1000, -22836=>1000,22839=>1000,22840=>1000,22841=>1000,22842=>1000,22844=>1000,22846=>1000,22848=>1000,22849=>1000,22850=>1000, -22852=>1000,22853=>1000,22855=>1000,22856=>1000,22857=>1000,22858=>1000,22859=>1000,22862=>1000,22863=>1000,22864=>1000, -22865=>1000,22867=>1000,22868=>1000,22869=>1000,22870=>1000,22871=>1000,22872=>1000,22874=>1000,22875=>1000,22876=>1000, -22877=>1000,22880=>1000,22881=>1000,22882=>1000,22883=>1000,22885=>1000,22887=>1000,22888=>1000,22889=>1000,22890=>1000, -22891=>1000,22892=>1000,22893=>1000,22894=>1000,22896=>1000,22897=>1000,22898=>1000,22899=>1000,22900=>1000,22902=>1000, -22903=>1000,22904=>1000,22905=>1000,22907=>1000,22908=>1000,22909=>1000,22910=>1000,22911=>1000,22912=>1000,22913=>1000, -22914=>1000,22915=>1000,22916=>1000,22917=>1000,22918=>1000,22919=>1000,22920=>1000,22922=>1000,22925=>1000,22926=>1000, -22927=>1000,22928=>1000,22930=>1000,22931=>1000,22934=>1000,22935=>1000,22936=>1000,22937=>1000,22939=>1000,22941=>1000, -22942=>1000,22944=>1000,22945=>1000,22946=>1000,22947=>1000,22948=>1000,22949=>1000,22950=>1000,22951=>1000,22952=>1000, -22953=>1000,22954=>1000,22955=>1000,22956=>1000,22958=>1000,22959=>1000,22961=>1000,22962=>1000,22963=>1000,22964=>1000, -22965=>1000,22966=>1000,22969=>1000,22970=>1000,22971=>1000,22972=>1000,22973=>1000,22974=>1000,22976=>1000,22977=>1000, -22979=>1000,22981=>1000,22982=>1000,22983=>1000,22984=>1000,22985=>1000,22986=>1000,22987=>1000,22988=>1000,22989=>1000, -22990=>1000,22991=>1000,22992=>1000,22993=>1000,22994=>1000,22995=>1000,22996=>1000,22998=>1000,22999=>1000,23000=>1000, -23001=>1000,23002=>1000,23003=>1000,23004=>1000,23005=>1000,23006=>1000,23008=>1000,23009=>1000,23011=>1000,23012=>1000, -23013=>1000,23014=>1000,23016=>1000,23017=>1000,23018=>1000,23019=>1000,23020=>1000,23021=>1000,23022=>1000,23025=>1000, -23026=>1000,23027=>1000,23028=>1000,23029=>1000,23030=>1000,23031=>1000,23032=>1000,23033=>1000,23034=>1000,23035=>1000, -23036=>1000,23037=>1000,23038=>1000,23039=>1000,23040=>1000,23041=>1000,23043=>1000,23044=>1000,23045=>1000,23046=>1000, -23047=>1000,23048=>1000,23049=>1000,23050=>1000,23052=>1000,23055=>1000,23057=>1000,23059=>1000,23061=>1000,23062=>1000, -23063=>1000,23064=>1000,23065=>1000,23066=>1000,23067=>1000,23068=>1000,23070=>1000,23071=>1000,23072=>1000,23075=>1000, -23077=>1000,23081=>1000,23085=>1000,23086=>1000,23087=>1000,23089=>1000,23090=>1000,23091=>1000,23092=>1000,23093=>1000, -23094=>1000,23095=>1000,23096=>1000,23097=>1000,23100=>1000,23102=>1000,23104=>1000,23105=>1000,23106=>1000,23107=>1000, -23108=>1000,23110=>1000,23111=>1000,23112=>1000,23113=>1000,23114=>1000,23116=>1000,23117=>1000,23120=>1000,23121=>1000, -23122=>1000,23123=>1000,23125=>1000,23126=>1000,23127=>1000,23128=>1000,23130=>1000,23131=>1000,23132=>1000,23133=>1000, -23134=>1000,23135=>1000,23136=>1000,23138=>1000,23140=>1000,23141=>1000,23142=>1000,23143=>1000,23145=>1000,23146=>1000, -23148=>1000,23149=>1000,23152=>1000,23156=>1000,23157=>1000,23158=>1000,23159=>1000,23160=>1000,23162=>1000,23163=>1000, -23164=>1000,23165=>1000,23167=>1000,23171=>1000,23172=>1000,23178=>1000,23179=>1000,23180=>1000,23182=>1000,23183=>1000, -23184=>1000,23186=>1000,23187=>1000,23188=>1000,23189=>1000,23191=>1000,23194=>1000,23195=>1000,23196=>1000,23197=>1000, -23198=>1000,23199=>1000,23202=>1000,23204=>1000,23205=>1000,23206=>1000,23207=>1000,23209=>1000,23210=>1000,23212=>1000, -23214=>1000,23215=>1000,23216=>1000,23217=>1000,23218=>1000,23219=>1000,23220=>1000,23221=>1000,23222=>1000,23223=>1000, -23224=>1000,23225=>1000,23226=>1000,23227=>1000,23228=>1000,23229=>1000,23230=>1000,23231=>1000,23232=>1000,23233=>1000, -23234=>1000,23236=>1000,23238=>1000,23239=>1000,23240=>1000,23241=>1000,23242=>1000,23243=>1000,23244=>1000,23245=>1000, -23248=>1000,23250=>1000,23252=>1000,23253=>1000,23254=>1000,23255=>1000,23256=>1000,23257=>1000,23258=>1000,23259=>1000, -23260=>1000,23261=>1000,23262=>1000,23263=>1000,23264=>1000,23265=>1000,23266=>1000,23267=>1000,23269=>1000,23270=>1000, -23272=>1000,23273=>1000,23274=>1000,23275=>1000,23276=>1000,23277=>1000,23278=>1000,23281=>1000,23283=>1000,23284=>1000, -23285=>1000,23286=>1000,23287=>1000,23288=>1000,23289=>1000,23290=>1000,23291=>1000,23293=>1000,23295=>1000,23297=>1000, -23298=>1000,23299=>1000,23301=>1000,23303=>1000,23304=>1000,23305=>1000,23307=>1000,23308=>1000,23311=>1000,23312=>1000, -23315=>1000,23316=>1000,23318=>1000,23319=>1000,23321=>1000,23322=>1000,23323=>1000,23325=>1000,23326=>1000,23328=>1000, -23329=>1000,23330=>1000,23331=>1000,23332=>1000,23333=>1000,23334=>1000,23335=>1000,23336=>1000,23338=>1000,23340=>1000, -23341=>1000,23342=>1000,23343=>1000,23344=>1000,23346=>1000,23348=>1000,23350=>1000,23351=>1000,23352=>1000,23356=>1000, -23357=>1000,23358=>1000,23359=>1000,23360=>1000,23363=>1000,23365=>1000,23367=>1000,23368=>1000,23371=>1000,23372=>1000, -23373=>1000,23374=>1000,23376=>1000,23377=>1000,23379=>1000,23380=>1000,23381=>1000,23382=>1000,23383=>1000,23384=>1000, -23385=>1000,23386=>1000,23387=>1000,23388=>1000,23389=>1000,23391=>1000,23394=>1000,23395=>1000,23396=>1000,23397=>1000, -23398=>1000,23401=>1000,23402=>1000,23403=>1000,23404=>1000,23406=>1000,23408=>1000,23409=>1000,23410=>1000,23411=>1000, -23413=>1000,23415=>1000,23416=>1000,23418=>1000,23419=>1000,23420=>1000,23421=>1000,23423=>1000,23424=>1000,23425=>1000, -23427=>1000,23428=>1000,23429=>1000,23431=>1000,23432=>1000,23433=>1000,23435=>1000,23436=>1000,23437=>1000,23438=>1000, -23439=>1000,23442=>1000,23443=>1000,23445=>1000,23446=>1000,23447=>1000,23448=>1000,23449=>1000,23450=>1000,23451=>1000, -23452=>1000,23453=>1000,23454=>1000,23455=>1000,23456=>1000,23457=>1000,23458=>1000,23459=>1000,23460=>1000,23461=>1000, -23462=>1000,23463=>1000,23464=>1000,23466=>1000,23467=>1000,23468=>1000,23469=>1000,23470=>1000,23472=>1000,23475=>1000, -23476=>1000,23477=>1000,23478=>1000,23480=>1000,23481=>1000,23485=>1000,23486=>1000,23487=>1000,23488=>1000,23489=>1000, -23490=>1000,23491=>1000,23492=>1000,23493=>1000,23494=>1000,23495=>1000,23497=>1000,23498=>1000,23499=>1000,23500=>1000, -23501=>1000,23502=>1000,23504=>1000,23505=>1000,23506=>1000,23507=>1000,23508=>1000,23510=>1000,23511=>1000,23512=>1000, -23513=>1000,23515=>1000,23517=>1000,23518=>1000,23519=>1000,23520=>1000,23521=>1000,23522=>1000,23523=>1000,23524=>1000, -23525=>1000,23526=>1000,23527=>1000,23528=>1000,23529=>1000,23530=>1000,23531=>1000,23532=>1000,23534=>1000,23535=>1000, -23536=>1000,23537=>1000,23538=>1000,23539=>1000,23541=>1000,23542=>1000,23544=>1000,23545=>1000,23546=>1000,23547=>1000, -23548=>1000,23550=>1000,23551=>1000,23553=>1000,23554=>1000,23555=>1000,23556=>1000,23557=>1000,23558=>1000,23559=>1000, -23560=>1000,23561=>1000,23562=>1000,23563=>1000,23564=>1000,23565=>1000,23566=>1000,23567=>1000,23568=>1000,23569=>1000, -23570=>1000,23571=>1000,23572=>1000,23573=>1000,23574=>1000,23576=>1000,23577=>1000,23578=>1000,23580=>1000,23581=>1000, -23582=>1000,23583=>1000,23584=>1000,23586=>1000,23588=>1000,23589=>1000,23591=>1000,23592=>1000,23594=>1000,23596=>1000, -23597=>1000,23600=>1000,23601=>1000,23603=>1000,23604=>1000,23607=>1000,23608=>1000,23609=>1000,23610=>1000,23611=>1000, -23612=>1000,23613=>1000,23614=>1000,23615=>1000,23616=>1000,23617=>1000,23618=>1000,23620=>1000,23621=>1000,23622=>1000, -23623=>1000,23624=>1000,23625=>1000,23626=>1000,23627=>1000,23628=>1000,23629=>1000,23630=>1000,23631=>1000,23632=>1000, -23633=>1000,23635=>1000,23636=>1000,23637=>1000,23638=>1000,23640=>1000,23641=>1000,23643=>1000,23644=>1000,23645=>1000, -23646=>1000,23648=>1000,23649=>1000,23650=>1000,23651=>1000,23652=>1000,23653=>1000,23654=>1000,23655=>1000,23656=>1000, -23657=>1000,23658=>1000,23660=>1000,23661=>1000,23662=>1000,23663=>1000,23665=>1000,23667=>1000,23668=>1000,23670=>1000, -23673=>1000,23674=>1000,23675=>1000,23676=>1000,23678=>1000,23679=>1000,23681=>1000,23682=>1000,23686=>1000,23688=>1000, -23689=>1000,23690=>1000,23691=>1000,23692=>1000,23693=>1000,23695=>1000,23696=>1000,23697=>1000,23698=>1000,23699=>1000, -23700=>1000,23701=>1000,23702=>1000,23703=>1000,23704=>1000,23705=>1000,23706=>1000,23707=>1000,23708=>1000,23709=>1000, -23711=>1000,23712=>1000,23713=>1000,23714=>1000,23715=>1000,23716=>1000,23717=>1000,23718=>1000,23719=>1000,23720=>1000, -23721=>1000,23722=>1000,23723=>1000,23724=>1000,23725=>1000,23726=>1000,23727=>1000,23728=>1000,23729=>1000,23731=>1000, -23733=>1000,23734=>1000,23735=>1000,23736=>1000,23738=>1000,23739=>1000,23740=>1000,23741=>1000,23742=>1000,23743=>1000, -23744=>1000,23745=>1000,23748=>1000,23749=>1000,23750=>1000,23751=>1000,23752=>1000,23753=>1000,23754=>1000,23755=>1000, -23756=>1000,23758=>1000,23759=>1000,23760=>1000,23762=>1000,23763=>1000,23764=>1000,23766=>1000,23767=>1000,23768=>1000, -23769=>1000,23770=>1000,23771=>1000,23774=>1000,23775=>1000,23776=>1000,23777=>1000,23780=>1000,23781=>1000,23782=>1000, -23784=>1000,23785=>1000,23786=>1000,23788=>1000,23789=>1000,23790=>1000,23791=>1000,23792=>1000,23793=>1000,23796=>1000, -23797=>1000,23798=>1000,23799=>1000,23800=>1000,23801=>1000,23802=>1000,23803=>1000,23805=>1000,23807=>1000,23808=>1000, -23809=>1000,23810=>1000,23811=>1000,23814=>1000,23815=>1000,23819=>1000,23820=>1000,23821=>1000,23822=>1000,23823=>1000, -23825=>1000,23826=>1000,23828=>1000,23829=>1000,23830=>1000,23831=>1000,23832=>1000,23833=>1000,23834=>1000,23835=>1000, -23837=>1000,23838=>1000,23839=>1000,23840=>1000,23842=>1000,23843=>1000,23844=>1000,23845=>1000,23846=>1000,23847=>1000, -23848=>1000,23849=>1000,23853=>1000,23854=>1000,23856=>1000,23857=>1000,23858=>1000,23859=>1000,23860=>1000,23861=>1000, -23862=>1000,23863=>1000,23864=>1000,23865=>1000,23866=>1000,23868=>1000,23869=>1000,23870=>1000,23871=>1000,23872=>1000, -23873=>1000,23874=>1000,23875=>1000,23877=>1000,23879=>1000,23881=>1000,23882=>1000,23883=>1000,23884=>1000,23886=>1000, -23888=>1000,23889=>1000,23890=>1000,23891=>1000,23893=>1000,23896=>1000,23897=>1000,23899=>1000,23900=>1000,23901=>1000, -23902=>1000,23906=>1000,23907=>1000,23909=>1000,23911=>1000,23912=>1000,23913=>1000,23915=>1000,23916=>1000,23917=>1000, -23919=>1000,23921=>1000,23922=>1000,23923=>1000,23924=>1000,23926=>1000,23927=>1000,23929=>1000,23930=>1000,23932=>1000, -23933=>1000,23934=>1000,23935=>1000,23936=>1000,23937=>1000,23938=>1000,23940=>1000,23942=>1000,23943=>1000,23944=>1000, -23945=>1000,23946=>1000,23947=>1000,23948=>1000,23949=>1000,23952=>1000,23954=>1000,23955=>1000,23956=>1000,23957=>1000, -23959=>1000,23961=>1000,23962=>1000,23964=>1000,23965=>1000,23966=>1000,23967=>1000,23968=>1000,23969=>1000,23970=>1000, -23975=>1000,23976=>1000,23977=>1000,23978=>1000,23980=>1000,23981=>1000,23982=>1000,23983=>1000,23984=>1000,23985=>1000, -23986=>1000,23988=>1000,23989=>1000,23991=>1000,23992=>1000,23993=>1000,23994=>1000,23996=>1000,23997=>1000,24000=>1000, -24002=>1000,24003=>1000,24005=>1000,24006=>1000,24007=>1000,24009=>1000,24011=>1000,24012=>1000,24013=>1000,24015=>1000, -24016=>1000,24017=>1000,24018=>1000,24019=>1000,24020=>1000,24021=>1000,24022=>1000,24024=>1000,24027=>1000,24029=>1000, -24030=>1000,24031=>1000,24032=>1000,24033=>1000,24034=>1000,24035=>1000,24037=>1000,24038=>1000,24039=>1000,24040=>1000, -24041=>1000,24043=>1000,24046=>1000,24047=>1000,24048=>1000,24049=>1000,24050=>1000,24051=>1000,24052=>1000,24053=>1000, -24055=>1000,24057=>1000,24059=>1000,24061=>1000,24062=>1000,24063=>1000,24065=>1000,24066=>1000,24067=>1000,24068=>1000, -24069=>1000,24070=>1000,24072=>1000,24074=>1000,24075=>1000,24076=>1000,24078=>1000,24079=>1000,24080=>1000,24081=>1000, -24084=>1000,24085=>1000,24086=>1000,24087=>1000,24088=>1000,24089=>1000,24090=>1000,24091=>1000,24092=>1000,24093=>1000, -24095=>1000,24096=>1000,24097=>1000,24098=>1000,24099=>1000,24100=>1000,24101=>1000,24102=>1000,24103=>1000,24104=>1000, -24105=>1000,24107=>1000,24109=>1000,24110=>1000,24111=>1000,24112=>1000,24113=>1000,24115=>1000,24116=>1000,24118=>1000, -24119=>1000,24120=>1000,24123=>1000,24124=>1000,24125=>1000,24126=>1000,24127=>1000,24128=>1000,24129=>1000,24130=>1000, -24131=>1000,24132=>1000,24133=>1000,24135=>1000,24138=>1000,24139=>1000,24140=>1000,24141=>1000,24142=>1000,24143=>1000, -24147=>1000,24148=>1000,24149=>1000,24151=>1000,24152=>1000,24153=>1000,24155=>1000,24156=>1000,24157=>1000,24158=>1000, -24159=>1000,24160=>1000,24161=>1000,24162=>1000,24163=>1000,24164=>1000,24166=>1000,24167=>1000,24168=>1000,24169=>1000, -24170=>1000,24171=>1000,24172=>1000,24173=>1000,24174=>1000,24175=>1000,24176=>1000,24178=>1000,24179=>1000,24180=>1000, -24181=>1000,24182=>1000,24183=>1000,24184=>1000,24185=>1000,24186=>1000,24187=>1000,24188=>1000,24189=>1000,24190=>1000, -24191=>1000,24192=>1000,24193=>1000,24194=>1000,24195=>1000,24196=>1000,24198=>1000,24199=>1000,24200=>1000,24201=>1000, -24202=>1000,24203=>1000,24204=>1000,24205=>1000,24207=>1000,24208=>1000,24209=>1000,24211=>1000,24212=>1000,24213=>1000, -24214=>1000,24215=>1000,24217=>1000,24218=>1000,24219=>1000,24220=>1000,24222=>1000,24223=>1000,24224=>1000,24226=>1000, -24227=>1000,24228=>1000,24229=>1000,24230=>1000,24231=>1000,24232=>1000,24234=>1000,24235=>1000,24236=>1000,24237=>1000, -24238=>1000,24240=>1000,24241=>1000,24242=>1000,24243=>1000,24244=>1000,24245=>1000,24246=>1000,24247=>1000,24248=>1000, -24249=>1000,24254=>1000,24257=>1000,24258=>1000,24259=>1000,24260=>1000,24261=>1000,24262=>1000,24263=>1000,24264=>1000, -24265=>1000,24266=>1000,24267=>1000,24268=>1000,24270=>1000,24271=>1000,24272=>1000,24273=>1000,24274=>1000,24275=>1000, -24276=>1000,24277=>1000,24278=>1000,24279=>1000,24280=>1000,24281=>1000,24282=>1000,24283=>1000,24284=>1000,24285=>1000, -24286=>1000,24287=>1000,24288=>1000,24289=>1000,24290=>1000,24291=>1000,24293=>1000,24294=>1000,24295=>1000,24296=>1000, -24297=>1000,24298=>1000,24300=>1000,24302=>1000,24303=>1000,24304=>1000,24305=>1000,24306=>1000,24307=>1000,24308=>1000, -24310=>1000,24311=>1000,24312=>1000,24314=>1000,24315=>1000,24316=>1000,24318=>1000,24319=>1000,24320=>1000,24321=>1000, -24322=>1000,24323=>1000,24324=>1000,24325=>1000,24327=>1000,24328=>1000,24329=>1000,24330=>1000,24331=>1000,24332=>1000, -24333=>1000,24335=>1000,24336=>1000,24337=>1000,24338=>1000,24339=>1000,24340=>1000,24341=>1000,24342=>1000,24343=>1000, -24344=>1000,24346=>1000,24347=>1000,24349=>1000,24351=>1000,24352=>1000,24353=>1000,24354=>1000,24355=>1000,24356=>1000, -24357=>1000,24358=>1000,24359=>1000,24360=>1000,24361=>1000,24362=>1000,24365=>1000,24366=>1000,24367=>1000,24368=>1000, -24369=>1000,24371=>1000,24372=>1000,24373=>1000,24374=>1000,24375=>1000,24376=>1000,24377=>1000,24378=>1000,24380=>1000, -24382=>1000,24384=>1000,24385=>1000,24387=>1000,24388=>1000,24389=>1000,24390=>1000,24392=>1000,24393=>1000,24394=>1000, -24395=>1000,24396=>1000,24398=>1000,24399=>1000,24400=>1000,24401=>1000,24402=>1000,24403=>1000,24404=>1000,24405=>1000, -24406=>1000,24407=>1000,24408=>1000,24409=>1000,24411=>1000,24412=>1000,24413=>1000,24417=>1000,24418=>1000,24420=>1000, -24421=>1000,24422=>1000,24423=>1000,24425=>1000,24426=>1000,24427=>1000,24428=>1000,24429=>1000,24431=>1000,24432=>1000, -24433=>1000,24435=>1000,24436=>1000,24438=>1000,24439=>1000,24440=>1000,24441=>1000,24443=>1000,24444=>1000,24445=>1000, -24446=>1000,24447=>1000,24448=>1000,24449=>1000,24450=>1000,24451=>1000,24452=>1000,24453=>1000,24454=>1000,24455=>1000, -24456=>1000,24457=>1000,24458=>1000,24459=>1000,24460=>1000,24464=>1000,24465=>1000,24466=>1000,24467=>1000,24469=>1000, -24470=>1000,24471=>1000,24472=>1000,24473=>1000,24475=>1000,24476=>1000,24478=>1000,24479=>1000,24480=>1000,24481=>1000, -24485=>1000,24486=>1000,24488=>1000,24489=>1000,24490=>1000,24491=>1000,24492=>1000,24493=>1000,24494=>1000,24495=>1000, -24498=>1000,24499=>1000,24500=>1000,24501=>1000,24502=>1000,24503=>1000,24505=>1000,24507=>1000,24508=>1000,24509=>1000, -24510=>1000,24511=>1000,24512=>1000,24513=>1000,24515=>1000,24516=>1000,24517=>1000,24518=>1000,24521=>1000,24524=>1000, -24525=>1000,24527=>1000,24528=>1000,24529=>1000,24530=>1000,24532=>1000,24533=>1000,24534=>1000,24535=>1000,24536=>1000, -24537=>1000,24540=>1000,24541=>1000,24542=>1000,24544=>1000,24545=>1000,24547=>1000,24548=>1000,24549=>1000,24551=>1000, -24552=>1000,24554=>1000,24555=>1000,24557=>1000,24558=>1000,24559=>1000,24560=>1000,24561=>1000,24563=>1000,24564=>1000, -24565=>1000,24567=>1000,24568=>1000,24570=>1000,24571=>1000,24573=>1000,24574=>1000,24575=>1000,24576=>1000,24577=>1000, -24578=>1000,24579=>1000,24580=>1000,24581=>1000,24582=>1000,24585=>1000,24586=>1000,24587=>1000,24588=>1000,24589=>1000, -24590=>1000,24591=>1000,24592=>1000,24593=>1000,24594=>1000,24595=>1000,24596=>1000,24597=>1000,24598=>1000,24599=>1000, -24601=>1000,24602=>1000,24603=>1000,24604=>1000,24605=>1000,24606=>1000,24608=>1000,24609=>1000,24610=>1000,24612=>1000, -24613=>1000,24614=>1000,24615=>1000,24616=>1000,24617=>1000,24618=>1000,24619=>1000,24620=>1000,24621=>1000,24622=>1000, -24623=>1000,24625=>1000,24626=>1000,24627=>1000,24628=>1000,24629=>1000,24631=>1000,24633=>1000,24634=>1000,24635=>1000, -24636=>1000,24639=>1000,24640=>1000,24641=>1000,24642=>1000,24643=>1000,24644=>1000,24645=>1000,24646=>1000,24647=>1000, -24649=>1000,24650=>1000,24651=>1000,24652=>1000,24653=>1000,24656=>1000,24658=>1000,24659=>1000,24660=>1000,24661=>1000, -24664=>1000,24665=>1000,24666=>1000,24667=>1000,24669=>1000,24670=>1000,24671=>1000,24672=>1000,24674=>1000,24675=>1000, -24676=>1000,24677=>1000,24678=>1000,24679=>1000,24680=>1000,24681=>1000,24682=>1000,24683=>1000,24684=>1000,24685=>1000, -24686=>1000,24687=>1000,24688=>1000,24690=>1000,24691=>1000,24693=>1000,24694=>1000,24695=>1000,24696=>1000,24697=>1000, -24698=>1000,24699=>1000,24700=>1000,24701=>1000,24703=>1000,24704=>1000,24705=>1000,24707=>1000,24708=>1000,24709=>1000, -24710=>1000,24711=>1000,24712=>1000,24713=>1000,24714=>1000,24715=>1000,24716=>1000,24717=>1000,24718=>1000,24720=>1000, -24722=>1000,24724=>1000,24725=>1000,24726=>1000,24727=>1000,24730=>1000,24731=>1000,24732=>1000,24733=>1000,24735=>1000, -24736=>1000,24738=>1000,24739=>1000,24740=>1000,24742=>1000,24743=>1000,24744=>1000,24745=>1000,24746=>1000,24747=>1000, -24748=>1000,24749=>1000,24751=>1000,24752=>1000,24753=>1000,24754=>1000,24755=>1000,24756=>1000,24757=>1000,24758=>1000, -24759=>1000,24760=>1000,24761=>1000,24762=>1000,24763=>1000,24764=>1000,24765=>1000,24766=>1000,24767=>1000,24768=>1000, -24769=>1000,24771=>1000,24772=>1000,24773=>1000,24774=>1000,24775=>1000,24776=>1000,24777=>1000,24778=>1000,24779=>1000, -24780=>1000,24781=>1000,24782=>1000,24783=>1000,24785=>1000,24787=>1000,24788=>1000,24789=>1000,24792=>1000,24793=>1000, -24794=>1000,24795=>1000,24796=>1000,24797=>1000,24798=>1000,24799=>1000,24800=>1000,24801=>1000,24802=>1000,24803=>1000, -24804=>1000,24806=>1000,24807=>1000,24808=>1000,24809=>1000,24811=>1000,24812=>1000,24813=>1000,24814=>1000,24815=>1000, -24816=>1000,24817=>1000,24818=>1000,24819=>1000,24820=>1000,24821=>1000,24822=>1000,24823=>1000,24824=>1000,24825=>1000, -24826=>1000,24827=>1000,24828=>1000,24830=>1000,24831=>1000,24832=>1000,24833=>1000,24835=>1000,24836=>1000,24837=>1000, -24838=>1000,24840=>1000,24841=>1000,24842=>1000,24843=>1000,24845=>1000,24846=>1000,24847=>1000,24848=>1000,24849=>1000, -24850=>1000,24851=>1000,24852=>1000,24853=>1000,24854=>1000,24856=>1000,24858=>1000,24859=>1000,24860=>1000,24861=>1000, -24863=>1000,24864=>1000,24865=>1000,24867=>1000,24868=>1000,24870=>1000,24871=>1000,24872=>1000,24873=>1000,24875=>1000, -24876=>1000,24878=>1000,24879=>1000,24880=>1000,24882=>1000,24884=>1000,24886=>1000,24887=>1000,24891=>1000,24892=>1000, -24893=>1000,24894=>1000,24895=>1000,24896=>1000,24897=>1000,24898=>1000,24900=>1000,24901=>1000,24902=>1000,24903=>1000, -24904=>1000,24905=>1000,24906=>1000,24907=>1000,24908=>1000,24909=>1000,24910=>1000,24911=>1000,24913=>1000,24914=>1000, -24915=>1000,24916=>1000,24917=>1000,24918=>1000,24920=>1000,24921=>1000,24922=>1000,24923=>1000,24925=>1000,24926=>1000, -24927=>1000,24929=>1000,24930=>1000,24931=>1000,24932=>1000,24933=>1000,24934=>1000,24935=>1000,24936=>1000,24938=>1000, -24939=>1000,24940=>1000,24942=>1000,24943=>1000,24944=>1000,24945=>1000,24946=>1000,24947=>1000,24948=>1000,24949=>1000, -24950=>1000,24951=>1000,24953=>1000,24954=>1000,24956=>1000,24957=>1000,24958=>1000,24960=>1000,24961=>1000,24962=>1000, -24963=>1000,24967=>1000,24969=>1000,24970=>1000,24971=>1000,24972=>1000,24973=>1000,24974=>1000,24976=>1000,24977=>1000, -24978=>1000,24979=>1000,24980=>1000,24982=>1000,24984=>1000,24985=>1000,24986=>1000,24987=>1000,24989=>1000,24991=>1000, -24993=>1000,24994=>1000,24996=>1000,24999=>1000,25000=>1000,25001=>1000,25002=>1000,25003=>1000,25004=>1000,25005=>1000, -25006=>1000,25007=>1000,25008=>1000,25009=>1000,25010=>1000,25011=>1000,25012=>1000,25013=>1000,25014=>1000,25015=>1000, -25016=>1000,25018=>1000,25020=>1000,25022=>1000,25023=>1000,25025=>1000,25026=>1000,25027=>1000,25029=>1000,25030=>1000, -25031=>1000,25032=>1000,25033=>1000,25034=>1000,25035=>1000,25036=>1000,25037=>1000,25040=>1000,25041=>1000,25042=>1000, -25044=>1000,25046=>1000,25048=>1000,25054=>1000,25055=>1000,25056=>1000,25059=>1000,25060=>1000,25061=>1000,25062=>1000, -25063=>1000,25064=>1000,25065=>1000,25066=>1000,25067=>1000,25069=>1000,25070=>1000,25072=>1000,25073=>1000,25074=>1000, -25076=>1000,25077=>1000,25078=>1000,25079=>1000,25080=>1000,25081=>1000,25082=>1000,25083=>1000,25084=>1000,25085=>1000, -25086=>1000,25087=>1000,25088=>1000,25089=>1000,25091=>1000,25092=>1000,25094=>1000,25095=>1000,25096=>1000,25097=>1000, -25098=>1000,25099=>1000,25100=>1000,25101=>1000,25102=>1000,25103=>1000,25104=>1000,25105=>1000,25106=>1000,25107=>1000, -25108=>1000,25109=>1000,25110=>1000,25111=>1000,25112=>1000,25113=>1000,25114=>1000,25115=>1000,25117=>1000,25118=>1000, -25119=>1000,25120=>1000,25121=>1000,25122=>1000,25123=>1000,25124=>1000,25125=>1000,25126=>1000,25127=>1000,25129=>1000, -25130=>1000,25131=>1000,25132=>1000,25133=>1000,25134=>1000,25135=>1000,25136=>1000,25137=>1000,25138=>1000,25139=>1000, -25140=>1000,25142=>1000,25143=>1000,25144=>1000,25146=>1000,25147=>1000,25149=>1000,25150=>1000,25151=>1000,25152=>1000, -25153=>1000,25154=>1000,25155=>1000,25158=>1000,25159=>1000,25160=>1000,25161=>1000,25162=>1000,25163=>1000,25164=>1000, -25165=>1000,25166=>1000,25168=>1000,25169=>1000,25170=>1000,25171=>1000,25172=>1000,25173=>1000,25176=>1000,25177=>1000, -25178=>1000,25179=>1000,25180=>1000,25182=>1000,25184=>1000,25185=>1000,25186=>1000,25187=>1000,25188=>1000,25189=>1000, -25190=>1000,25191=>1000,25192=>1000,25193=>1000,25194=>1000,25195=>1000,25196=>1000,25197=>1000,25198=>1000,25199=>1000, -25200=>1000,25201=>1000,25202=>1000,25203=>1000,25204=>1000,25206=>1000,25207=>1000,25209=>1000,25210=>1000,25211=>1000, -25212=>1000,25213=>1000,25214=>1000,25215=>1000,25216=>1000,25217=>1000,25218=>1000,25219=>1000,25220=>1000,25222=>1000, -25223=>1000,25224=>1000,25225=>1000,25226=>1000,25228=>1000,25230=>1000,25231=>1000,25233=>1000,25234=>1000,25235=>1000, -25236=>1000,25237=>1000,25238=>1000,25239=>1000,25240=>1000,25242=>1000,25243=>1000,25244=>1000,25246=>1000,25247=>1000, -25248=>1000,25249=>1000,25250=>1000,25252=>1000,25253=>1000,25254=>1000,25256=>1000,25257=>1000,25258=>1000,25259=>1000, -25260=>1000,25261=>1000,25262=>1000,25263=>1000,25264=>1000,25265=>1000,25267=>1000,25268=>1000,25269=>1000,25270=>1000, -25272=>1000,25273=>1000,25275=>1000,25276=>1000,25277=>1000,25278=>1000,25279=>1000,25282=>1000,25284=>1000,25285=>1000, -25286=>1000,25287=>1000,25288=>1000,25289=>1000,25290=>1000,25291=>1000,25292=>1000,25293=>1000,25294=>1000,25295=>1000, -25296=>1000,25297=>1000,25298=>1000,25299=>1000,25300=>1000,25302=>1000,25303=>1000,25304=>1000,25305=>1000,25306=>1000, -25307=>1000,25308=>1000,25309=>1000,25311=>1000,25312=>1000,25313=>1000,25314=>1000,25315=>1000,25317=>1000,25318=>1000, -25319=>1000,25320=>1000,25321=>1000,25323=>1000,25324=>1000,25325=>1000,25326=>1000,25327=>1000,25328=>1000,25329=>1000, -25330=>1000,25331=>1000,25332=>1000,25333=>1000,25334=>1000,25335=>1000,25336=>1000,25337=>1000,25338=>1000,25339=>1000, -25340=>1000,25341=>1000,25342=>1000,25343=>1000,25344=>1000,25345=>1000,25346=>1000,25347=>1000,25351=>1000,25352=>1000, -25353=>1000,25355=>1000,25356=>1000,25357=>1000,25358=>1000,25359=>1000,25360=>1000,25361=>1000,25363=>1000,25364=>1000, -25365=>1000,25366=>1000,25369=>1000,25370=>1000,25371=>1000,25373=>1000,25374=>1000,25375=>1000,25376=>1000,25377=>1000, -25378=>1000,25379=>1000,25380=>1000,25381=>1000,25383=>1000,25384=>1000,25385=>1000,25386=>1000,25387=>1000,25388=>1000, -25389=>1000,25391=>1000,25394=>1000,25395=>1000,25396=>1000,25398=>1000,25400=>1000,25401=>1000,25402=>1000,25403=>1000, -25404=>1000,25405=>1000,25406=>1000,25407=>1000,25408=>1000,25409=>1000,25410=>1000,25411=>1000,25412=>1000,25413=>1000, -25414=>1000,25415=>1000,25416=>1000,25417=>1000,25418=>1000,25419=>1000,25420=>1000,25421=>1000,25422=>1000,25423=>1000, -25424=>1000,25425=>1000,25428=>1000,25429=>1000,25430=>1000,25431=>1000,25432=>1000,25433=>1000,25434=>1000,25436=>1000, -25438=>1000,25439=>1000,25441=>1000,25442=>1000,25443=>1000,25445=>1000,25447=>1000,25448=>1000,25449=>1000,25451=>1000, -25453=>1000,25454=>1000,25455=>1000,25456=>1000,25457=>1000,25458=>1000,25461=>1000,25462=>1000,25463=>1000,25464=>1000, -25466=>1000,25467=>1000,25468=>1000,25469=>1000,25471=>1000,25472=>1000,25473=>1000,25474=>1000,25475=>1000,25476=>1000, -25477=>1000,25479=>1000,25480=>1000,25481=>1000,25482=>1000,25484=>1000,25485=>1000,25486=>1000,25487=>1000,25488=>1000, -25489=>1000,25490=>1000,25492=>1000,25494=>1000,25495=>1000,25496=>1000,25497=>1000,25499=>1000,25500=>1000,25501=>1000, -25502=>1000,25503=>1000,25504=>1000,25505=>1000,25506=>1000,25507=>1000,25508=>1000,25509=>1000,25511=>1000,25512=>1000, -25513=>1000,25514=>1000,25515=>1000,25516=>1000,25517=>1000,25518=>1000,25519=>1000,25520=>1000,25521=>1000,25522=>1000, -25523=>1000,25524=>1000,25525=>1000,25527=>1000,25528=>1000,25530=>1000,25531=>1000,25532=>1000,25533=>1000,25534=>1000, -25536=>1000,25538=>1000,25539=>1000,25540=>1000,25541=>1000,25542=>1000,25543=>1000,25544=>1000,25545=>1000,25546=>1000, -25547=>1000,25548=>1000,25549=>1000,25550=>1000,25551=>1000,25552=>1000,25554=>1000,25555=>1000,25557=>1000,25558=>1000, -25559=>1000,25560=>1000,25561=>1000,25562=>1000,25563=>1000,25564=>1000,25565=>1000,25566=>1000,25567=>1000,25568=>1000, -25569=>1000,25571=>1000,25572=>1000,25573=>1000,25575=>1000,25576=>1000,25577=>1000,25578=>1000,25579=>1000,25581=>1000, -25582=>1000,25583=>1000,25584=>1000,25585=>1000,25586=>1000,25587=>1000,25588=>1000,25589=>1000,25590=>1000,25591=>1000, -25592=>1000,25593=>1000,25594=>1000,25597=>1000,25599=>1000,25600=>1000,25601=>1000,25602=>1000,25605=>1000,25606=>1000, -25609=>1000,25610=>1000,25611=>1000,25612=>1000,25613=>1000,25614=>1000,25615=>1000,25616=>1000,25618=>1000,25619=>1000, -25620=>1000,25621=>1000,25622=>1000,25623=>1000,25624=>1000,25626=>1000,25627=>1000,25628=>1000,25630=>1000,25631=>1000, -25632=>1000,25633=>1000,25634=>1000,25635=>1000,25636=>1000,25637=>1000,25638=>1000,25639=>1000,25640=>1000,25642=>1000, -25643=>1000,25644=>1000,25645=>1000,25646=>1000,25647=>1000,25648=>1000,25651=>1000,25652=>1000,25653=>1000,25654=>1000, -25655=>1000,25657=>1000,25658=>1000,25661=>1000,25662=>1000,25663=>1000,25664=>1000,25665=>1000,25666=>1000,25667=>1000, -25668=>1000,25669=>1000,25670=>1000,25671=>1000,25672=>1000,25674=>1000,25675=>1000,25677=>1000,25678=>1000,25680=>1000, -25681=>1000,25682=>1000,25683=>1000,25684=>1000,25688=>1000,25689=>1000,25691=>1000,25692=>1000,25693=>1000,25694=>1000, -25695=>1000,25696=>1000,25697=>1000,25701=>1000,25702=>1000,25703=>1000,25704=>1000,25705=>1000,25707=>1000,25708=>1000, -25709=>1000,25710=>1000,25711=>1000,25712=>1000,25714=>1000,25715=>1000,25716=>1000,25717=>1000,25718=>1000,25719=>1000, -25720=>1000,25721=>1000,25722=>1000,25723=>1000,25725=>1000,25727=>1000,25730=>1000,25731=>1000,25732=>1000,25733=>1000, -25735=>1000,25736=>1000,25737=>1000,25738=>1000,25739=>1000,25740=>1000,25743=>1000,25744=>1000,25745=>1000,25746=>1000, -25747=>1000,25749=>1000,25750=>1000,25751=>1000,25752=>1000,25753=>1000,25754=>1000,25756=>1000,25757=>1000,25758=>1000, -25759=>1000,25760=>1000,25762=>1000,25763=>1000,25764=>1000,25765=>1000,25766=>1000,25769=>1000,25771=>1000,25772=>1000, -25773=>1000,25774=>1000,25776=>1000,25777=>1000,25778=>1000,25779=>1000,25781=>1000,25783=>1000,25784=>1000,25785=>1000, -25786=>1000,25787=>1000,25788=>1000,25789=>1000,25790=>1000,25791=>1000,25792=>1000,25793=>1000,25794=>1000,25795=>1000, -25796=>1000,25797=>1000,25799=>1000,25801=>1000,25802=>1000,25803=>1000,25805=>1000,25806=>1000,25807=>1000,25808=>1000, -25810=>1000,25812=>1000,25814=>1000,25815=>1000,25816=>1000,25817=>1000,25818=>1000,25819=>1000,25822=>1000,25824=>1000, -25825=>1000,25826=>1000,25827=>1000,25828=>1000,25829=>1000,25830=>1000,25831=>1000,25832=>1000,25833=>1000,25835=>1000, -25836=>1000,25837=>1000,25839=>1000,25840=>1000,25841=>1000,25842=>1000,25843=>1000,25844=>1000,25846=>1000,25847=>1000, -25848=>1000,25850=>1000,25851=>1000,25852=>1000,25853=>1000,25854=>1000,25855=>1000,25856=>1000,25857=>1000,25859=>1000, -25860=>1000,25861=>1000,25862=>1000,25863=>1000,25865=>1000,25868=>1000,25869=>1000,25870=>1000,25871=>1000,25872=>1000, -25874=>1000,25875=>1000,25876=>1000,25877=>1000,25878=>1000,25879=>1000,25880=>1000,25881=>1000,25883=>1000,25884=>1000, -25885=>1000,25888=>1000,25889=>1000,25890=>1000,25891=>1000,25892=>1000,25893=>1000,25894=>1000,25897=>1000,25898=>1000, -25899=>1000,25900=>1000,25901=>1000,25902=>1000,25903=>1000,25906=>1000,25907=>1000,25908=>1000,25909=>1000,25910=>1000, -25911=>1000,25912=>1000,25913=>1000,25915=>1000,25917=>1000,25918=>1000,25919=>1000,25921=>1000,25923=>1000,25925=>1000, -25926=>1000,25928=>1000,25929=>1000,25930=>1000,25932=>1000,25933=>1000,25934=>1000,25935=>1000,25937=>1000,25939=>1000, -25940=>1000,25941=>1000,25942=>1000,25943=>1000,25944=>1000,25945=>1000,25947=>1000,25948=>1000,25949=>1000,25950=>1000, -25954=>1000,25955=>1000,25956=>1000,25957=>1000,25958=>1000,25959=>1000,25960=>1000,25962=>1000,25963=>1000,25964=>1000, -25965=>1000,25967=>1000,25968=>1000,25970=>1000,25971=>1000,25972=>1000,25973=>1000,25974=>1000,25975=>1000,25976=>1000, -25977=>1000,25978=>1000,25979=>1000,25980=>1000,25982=>1000,25983=>1000,25984=>1000,25985=>1000,25986=>1000,25987=>1000, -25988=>1000,25989=>1000,25991=>1000,25992=>1000,25993=>1000,25995=>1000,25996=>1000,25998=>1000,26000=>1000,26001=>1000, -26002=>1000,26003=>1000,26004=>1000,26005=>1000,26006=>1000,26007=>1000,26009=>1000,26011=>1000,26012=>1000,26013=>1000, -26014=>1000,26015=>1000,26016=>1000,26017=>1000,26018=>1000,26020=>1000,26021=>1000,26023=>1000,26024=>1000,26025=>1000, -26026=>1000,26027=>1000,26028=>1000,26029=>1000,26030=>1000,26031=>1000,26032=>1000,26034=>1000,26035=>1000,26038=>1000, -26039=>1000,26040=>1000,26041=>1000,26043=>1000,26044=>1000,26045=>1000,26047=>1000,26049=>1000,26050=>1000,26051=>1000, -26052=>1000,26053=>1000,26054=>1000,26059=>1000,26060=>1000,26061=>1000,26062=>1000,26063=>1000,26064=>1000,26066=>1000, -26067=>1000,26070=>1000,26071=>1000,26073=>1000,26074=>1000,26075=>1000,26077=>1000,26078=>1000,26079=>1000,26080=>1000, -26081=>1000,26082=>1000,26083=>1000,26085=>1000,26086=>1000,26087=>1000,26088=>1000,26089=>1000,26092=>1000,26093=>1000, -26094=>1000,26095=>1000,26096=>1000,26097=>1000,26098=>1000,26099=>1000,26100=>1000,26101=>1000,26102=>1000,26103=>1000, -26106=>1000,26107=>1000,26108=>1000,26109=>1000,26111=>1000,26112=>1000,26114=>1000,26115=>1000,26116=>1000,26117=>1000, -26118=>1000,26119=>1000,26120=>1000,26121=>1000,26122=>1000,26123=>1000,26124=>1000,26125=>1000,26126=>1000,26127=>1000, -26128=>1000,26129=>1000,26130=>1000,26131=>1000,26132=>1000,26133=>1000,26137=>1000,26140=>1000,26141=>1000,26142=>1000, -26143=>1000,26144=>1000,26145=>1000,26146=>1000,26148=>1000,26149=>1000,26150=>1000,26151=>1000,26152=>1000,26155=>1000, -26157=>1000,26158=>1000,26159=>1000,26160=>1000,26161=>1000,26162=>1000,26163=>1000,26164=>1000,26165=>1000,26166=>1000, -26169=>1000,26170=>1000,26171=>1000,26172=>1000,26174=>1000,26175=>1000,26177=>1000,26178=>1000,26179=>1000,26180=>1000, -26181=>1000,26183=>1000,26185=>1000,26186=>1000,26187=>1000,26188=>1000,26191=>1000,26193=>1000,26194=>1000,26195=>1000, -26196=>1000,26197=>1000,26198=>1000,26199=>1000,26201=>1000,26202=>1000,26203=>1000,26204=>1000,26205=>1000,26206=>1000, -26207=>1000,26209=>1000,26210=>1000,26212=>1000,26213=>1000,26214=>1000,26215=>1000,26216=>1000,26217=>1000,26218=>1000, -26219=>1000,26220=>1000,26222=>1000,26223=>1000,26224=>1000,26225=>1000,26226=>1000,26227=>1000,26228=>1000,26230=>1000, -26231=>1000,26232=>1000,26233=>1000,26234=>1000,26235=>1000,26236=>1000,26238=>1000,26240=>1000,26241=>1000,26242=>1000, -26243=>1000,26244=>1000,26246=>1000,26247=>1000,26248=>1000,26249=>1000,26250=>1000,26251=>1000,26252=>1000,26253=>1000, -26254=>1000,26256=>1000,26257=>1000,26260=>1000,26261=>1000,26262=>1000,26263=>1000,26264=>1000,26265=>1000,26269=>1000, -26271=>1000,26272=>1000,26273=>1000,26274=>1000,26278=>1000,26279=>1000,26280=>1000,26281=>1000,26282=>1000,26283=>1000, -26286=>1000,26287=>1000,26288=>1000,26289=>1000,26290=>1000,26291=>1000,26292=>1000,26293=>1000,26295=>1000,26296=>1000, -26297=>1000,26298=>1000,26299=>1000,26300=>1000,26301=>1000,26302=>1000,26303=>1000,26304=>1000,26305=>1000,26308=>1000, -26310=>1000,26311=>1000,26312=>1000,26313=>1000,26314=>1000,26315=>1000,26316=>1000,26319=>1000,26322=>1000,26326=>1000, -26328=>1000,26329=>1000,26330=>1000,26331=>1000,26332=>1000,26333=>1000,26334=>1000,26336=>1000,26339=>1000,26340=>1000, -26342=>1000,26344=>1000,26345=>1000,26347=>1000,26348=>1000,26349=>1000,26350=>1000,26352=>1000,26354=>1000,26355=>1000, -26356=>1000,26357=>1000,26358=>1000,26359=>1000,26360=>1000,26361=>1000,26362=>1000,26363=>1000,26364=>1000,26365=>1000, -26366=>1000,26367=>1000,26368=>1000,26369=>1000,26371=>1000,26372=>1000,26373=>1000,26376=>1000,26377=>1000,26378=>1000, -26379=>1000,26381=>1000,26382=>1000,26383=>1000,26384=>1000,26386=>1000,26387=>1000,26388=>1000,26389=>1000,26390=>1000, -26391=>1000,26392=>1000,26395=>1000,26397=>1000,26398=>1000,26399=>1000,26400=>1000,26401=>1000,26402=>1000,26403=>1000, -26406=>1000,26407=>1000,26408=>1000,26410=>1000,26411=>1000,26412=>1000,26413=>1000,26414=>1000,26415=>1000,26417=>1000, -26419=>1000,26420=>1000,26421=>1000,26422=>1000,26423=>1000,26424=>1000,26425=>1000,26426=>1000,26427=>1000,26428=>1000, -26429=>1000,26430=>1000,26431=>1000,26432=>1000,26433=>1000,26434=>1000,26435=>1000,26437=>1000,26438=>1000,26439=>1000, -26440=>1000,26441=>1000,26443=>1000,26444=>1000,26445=>1000,26446=>1000,26447=>1000,26448=>1000,26449=>1000,26451=>1000, -26453=>1000,26454=>1000,26455=>1000,26457=>1000,26458=>1000,26460=>1000,26461=>1000,26462=>1000,26463=>1000,26464=>1000, -26465=>1000,26466=>1000,26467=>1000,26468=>1000,26469=>1000,26470=>1000,26472=>1000,26473=>1000,26474=>1000,26476=>1000, -26477=>1000,26479=>1000,26480=>1000,26481=>1000,26482=>1000,26483=>1000,26484=>1000,26485=>1000,26486=>1000,26487=>1000, -26488=>1000,26489=>1000,26490=>1000,26491=>1000,26492=>1000,26493=>1000,26494=>1000,26495=>1000,26497=>1000,26499=>1000, -26500=>1000,26501=>1000,26502=>1000,26503=>1000,26505=>1000,26507=>1000,26508=>1000,26509=>1000,26510=>1000,26511=>1000, -26512=>1000,26513=>1000,26514=>1000,26515=>1000,26516=>1000,26517=>1000,26519=>1000,26520=>1000,26521=>1000,26522=>1000, -26524=>1000,26525=>1000,26526=>1000,26527=>1000,26528=>1000,26529=>1000,26530=>1000,26531=>1000,26533=>1000,26534=>1000, -26535=>1000,26536=>1000,26537=>1000,26538=>1000,26539=>1000,26541=>1000,26542=>1000,26543=>1000,26544=>1000,26546=>1000, -26547=>1000,26548=>1000,26549=>1000,26550=>1000,26551=>1000,26552=>1000,26553=>1000,26554=>1000,26555=>1000,26558=>1000, -26560=>1000,26561=>1000,26562=>1000,26563=>1000,26564=>1000,26565=>1000,26566=>1000,26568=>1000,26569=>1000,26570=>1000, -26571=>1000,26572=>1000,26573=>1000,26574=>1000,26575=>1000,26576=>1000,26577=>1000,26578=>1000,26579=>1000,26580=>1000, -26584=>1000,26585=>1000,26586=>1000,26587=>1000,26588=>1000,26589=>1000,26590=>1000,26591=>1000,26592=>1000,26594=>1000, -26595=>1000,26596=>1000,26597=>1000,26598=>1000,26599=>1000,26601=>1000,26602=>1000,26603=>1000,26604=>1000,26605=>1000, -26606=>1000,26607=>1000,26608=>1000,26609=>1000,26610=>1000,26611=>1000,26612=>1000,26613=>1000,26614=>1000,26615=>1000, -26616=>1000,26618=>1000,26619=>1000,26620=>1000,26621=>1000,26622=>1000,26623=>1000,26624=>1000,26625=>1000,26626=>1000, -26627=>1000,26628=>1000,26629=>1000,26631=>1000,26632=>1000,26633=>1000,26634=>1000,26635=>1000,26636=>1000,26638=>1000, -26639=>1000,26641=>1000,26642=>1000,26643=>1000,26644=>1000,26646=>1000,26647=>1000,26648=>1000,26650=>1000,26652=>1000, -26653=>1000,26654=>1000,26655=>1000,26656=>1000,26657=>1000,26658=>1000,26661=>1000,26662=>1000,26664=>1000,26665=>1000, -26666=>1000,26667=>1000,26669=>1000,26670=>1000,26671=>1000,26673=>1000,26674=>1000,26675=>1000,26676=>1000,26677=>1000, -26679=>1000,26680=>1000,26681=>1000,26682=>1000,26683=>1000,26684=>1000,26685=>1000,26686=>1000,26688=>1000,26689=>1000, -26690=>1000,26691=>1000,26692=>1000,26693=>1000,26694=>1000,26696=>1000,26697=>1000,26698=>1000,26699=>1000,26700=>1000, -26701=>1000,26702=>1000,26703=>1000,26704=>1000,26705=>1000,26706=>1000,26707=>1000,26708=>1000,26709=>1000,26713=>1000, -26716=>1000,26717=>1000,26719=>1000,26720=>1000,26721=>1000,26722=>1000,26723=>1000,26724=>1000,26725=>1000,26726=>1000, -26727=>1000,26728=>1000,26729=>1000,26731=>1000,26733=>1000,26734=>1000,26735=>1000,26737=>1000,26738=>1000,26740=>1000, -26741=>1000,26742=>1000,26743=>1000,26744=>1000,26745=>1000,26747=>1000,26748=>1000,26749=>1000,26750=>1000,26751=>1000, -26752=>1000,26753=>1000,26754=>1000,26755=>1000,26757=>1000,26758=>1000,26759=>1000,26761=>1000,26762=>1000,26763=>1000, -26764=>1000,26765=>1000,26767=>1000,26768=>1000,26769=>1000,26770=>1000,26771=>1000,26772=>1000,26774=>1000,26775=>1000, -26779=>1000,26780=>1000,26781=>1000,26783=>1000,26784=>1000,26785=>1000,26786=>1000,26787=>1000,26788=>1000,26790=>1000, -26791=>1000,26792=>1000,26793=>1000,26794=>1000,26795=>1000,26796=>1000,26797=>1000,26798=>1000,26799=>1000,26800=>1000, -26801=>1000,26802=>1000,26803=>1000,26804=>1000,26805=>1000,26806=>1000,26809=>1000,26810=>1000,26812=>1000,26816=>1000, -26818=>1000,26820=>1000,26821=>1000,26822=>1000,26823=>1000,26824=>1000,26825=>1000,26826=>1000,26827=>1000,26828=>1000, -26829=>1000,26830=>1000,26831=>1000,26832=>1000,26833=>1000,26834=>1000,26835=>1000,26836=>1000,26837=>1000,26838=>1000, -26839=>1000,26840=>1000,26842=>1000,26844=>1000,26845=>1000,26846=>1000,26847=>1000,26848=>1000,26849=>1000,26851=>1000, -26852=>1000,26854=>1000,26855=>1000,26856=>1000,26857=>1000,26858=>1000,26859=>1000,26860=>1000,26862=>1000,26863=>1000, -26864=>1000,26865=>1000,26866=>1000,26867=>1000,26868=>1000,26869=>1000,26870=>1000,26871=>1000,26872=>1000,26873=>1000, -26874=>1000,26875=>1000,26876=>1000,26877=>1000,26880=>1000,26881=>1000,26884=>1000,26885=>1000,26886=>1000,26887=>1000, -26888=>1000,26890=>1000,26891=>1000,26892=>1000,26893=>1000,26894=>1000,26895=>1000,26896=>1000,26897=>1000,26898=>1000, -26899=>1000,26900=>1000,26901=>1000,26903=>1000,26905=>1000,26906=>1000,26907=>1000,26908=>1000,26911=>1000,26912=>1000, -26913=>1000,26914=>1000,26915=>1000,26916=>1000,26917=>1000,26918=>1000,26919=>1000,26920=>1000,26922=>1000,26925=>1000, -26927=>1000,26928=>1000,26930=>1000,26931=>1000,26932=>1000,26933=>1000,26934=>1000,26935=>1000,26936=>1000,26937=>1000, -26939=>1000,26940=>1000,26941=>1000,26943=>1000,26944=>1000,26945=>1000,26946=>1000,26948=>1000,26949=>1000,26952=>1000, -26953=>1000,26954=>1000,26955=>1000,26956=>1000,26958=>1000,26959=>1000,26961=>1000,26962=>1000,26963=>1000,26964=>1000, -26965=>1000,26966=>1000,26967=>1000,26968=>1000,26969=>1000,26970=>1000,26971=>1000,26972=>1000,26973=>1000,26974=>1000, -26975=>1000,26976=>1000,26977=>1000,26978=>1000,26979=>1000,26981=>1000,26982=>1000,26984=>1000,26985=>1000,26986=>1000, -26987=>1000,26988=>1000,26989=>1000,26990=>1000,26991=>1000,26992=>1000,26993=>1000,26995=>1000,26996=>1000,26997=>1000, -26998=>1000,26999=>1000,27000=>1000,27001=>1000,27002=>1000,27003=>1000,27004=>1000,27005=>1000,27006=>1000,27008=>1000, -27009=>1000,27010=>1000,27011=>1000,27012=>1000,27014=>1000,27015=>1000,27016=>1000,27017=>1000,27018=>1000,27021=>1000, -27022=>1000,27024=>1000,27025=>1000,27027=>1000,27028=>1000,27029=>1000,27030=>1000,27031=>1000,27032=>1000,27033=>1000, -27034=>1000,27035=>1000,27036=>1000,27038=>1000,27040=>1000,27041=>1000,27043=>1000,27044=>1000,27045=>1000,27046=>1000, -27047=>1000,27048=>1000,27049=>1000,27050=>1000,27051=>1000,27052=>1000,27053=>1000,27054=>1000,27055=>1000,27056=>1000, -27057=>1000,27058=>1000,27059=>1000,27060=>1000,27061=>1000,27062=>1000,27063=>1000,27065=>1000,27067=>1000,27068=>1000, -27069=>1000,27070=>1000,27071=>1000,27073=>1000,27074=>1000,27075=>1000,27076=>1000,27078=>1000,27079=>1000,27081=>1000, -27082=>1000,27083=>1000,27084=>1000,27085=>1000,27086=>1000,27087=>1000,27088=>1000,27091=>1000,27092=>1000,27096=>1000, -27097=>1000,27099=>1000,27101=>1000,27102=>1000,27103=>1000,27104=>1000,27106=>1000,27108=>1000,27109=>1000,27110=>1000, -27111=>1000,27112=>1000,27114=>1000,27115=>1000,27116=>1000,27117=>1000,27118=>1000,27121=>1000,27122=>1000,27123=>1000, -27124=>1000,27126=>1000,27127=>1000,27128=>1000,27129=>1000,27131=>1000,27132=>1000,27133=>1000,27134=>1000,27135=>1000, -27136=>1000,27137=>1000,27138=>1000,27140=>1000,27141=>1000,27142=>1000,27143=>1000,27144=>1000,27145=>1000,27146=>1000, -27147=>1000,27148=>1000,27149=>1000,27151=>1000,27153=>1000,27154=>1000,27155=>1000,27156=>1000,27157=>1000,27158=>1000, -27159=>1000,27160=>1000,27161=>1000,27163=>1000,27165=>1000,27166=>1000,27167=>1000,27168=>1000,27169=>1000,27170=>1000, -27171=>1000,27173=>1000,27174=>1000,27175=>1000,27176=>1000,27177=>1000,27178=>1000,27179=>1000,27182=>1000,27183=>1000, -27184=>1000,27185=>1000,27186=>1000,27188=>1000,27189=>1000,27190=>1000,27192=>1000,27193=>1000,27194=>1000,27195=>1000, -27196=>1000,27197=>1000,27198=>1000,27199=>1000,27200=>1000,27201=>1000,27204=>1000,27206=>1000,27207=>1000,27208=>1000, -27209=>1000,27211=>1000,27213=>1000,27214=>1000,27215=>1000,27216=>1000,27217=>1000,27218=>1000,27219=>1000,27220=>1000, -27221=>1000,27222=>1000,27224=>1000,27225=>1000,27226=>1000,27227=>1000,27229=>1000,27230=>1000,27231=>1000,27232=>1000, -27233=>1000,27234=>1000,27236=>1000,27237=>1000,27238=>1000,27239=>1000,27240=>1000,27241=>1000,27242=>1000,27243=>1000, -27245=>1000,27247=>1000,27249=>1000,27250=>1000,27251=>1000,27254=>1000,27256=>1000,27257=>1000,27260=>1000,27262=>1000, -27263=>1000,27264=>1000,27265=>1000,27267=>1000,27268=>1000,27269=>1000,27271=>1000,27273=>1000,27276=>1000,27277=>1000, -27278=>1000,27280=>1000,27281=>1000,27282=>1000,27283=>1000,27284=>1000,27285=>1000,27286=>1000,27287=>1000,27290=>1000, -27291=>1000,27292=>1000,27294=>1000,27295=>1000,27296=>1000,27297=>1000,27298=>1000,27299=>1000,27300=>1000,27301=>1000, -27302=>1000,27304=>1000,27305=>1000,27306=>1000,27307=>1000,27308=>1000,27309=>1000,27310=>1000,27311=>1000,27315=>1000, -27316=>1000,27318=>1000,27319=>1000,27320=>1000,27321=>1000,27322=>1000,27323=>1000,27325=>1000,27329=>1000,27330=>1000, -27331=>1000,27333=>1000,27334=>1000,27335=>1000,27339=>1000,27340=>1000,27341=>1000,27343=>1000,27344=>1000,27345=>1000, -27347=>1000,27353=>1000,27354=>1000,27355=>1000,27356=>1000,27357=>1000,27358=>1000,27359=>1000,27360=>1000,27361=>1000, -27362=>1000,27364=>1000,27365=>1000,27367=>1000,27368=>1000,27370=>1000,27371=>1000,27372=>1000,27374=>1000,27375=>1000, -27376=>1000,27377=>1000,27379=>1000,27382=>1000,27384=>1000,27385=>1000,27386=>1000,27387=>1000,27388=>1000,27392=>1000, -27394=>1000,27395=>1000,27396=>1000,27397=>1000,27400=>1000,27401=>1000,27402=>1000,27403=>1000,27404=>1000,27407=>1000, -27408=>1000,27409=>1000,27410=>1000,27411=>1000,27414=>1000,27415=>1000,27416=>1000,27417=>1000,27418=>1000,27421=>1000, -27422=>1000,27423=>1000,27424=>1000,27425=>1000,27426=>1000,27427=>1000,27428=>1000,27429=>1000,27431=>1000,27432=>1000, -27436=>1000,27437=>1000,27439=>1000,27441=>1000,27442=>1000,27443=>1000,27444=>1000,27446=>1000,27447=>1000,27448=>1000, -27449=>1000,27450=>1000,27451=>1000,27452=>1000,27453=>1000,27454=>1000,27455=>1000,27457=>1000,27458=>1000,27459=>1000, -27461=>1000,27462=>1000,27463=>1000,27464=>1000,27465=>1000,27466=>1000,27467=>1000,27468=>1000,27469=>1000,27470=>1000, -27472=>1000,27473=>1000,27475=>1000,27476=>1000,27477=>1000,27478=>1000,27481=>1000,27483=>1000,27484=>1000,27486=>1000, -27487=>1000,27488=>1000,27489=>1000,27490=>1000,27491=>1000,27492=>1000,27493=>1000,27494=>1000,27495=>1000,27497=>1000, -27498=>1000,27501=>1000,27503=>1000,27506=>1000,27507=>1000,27508=>1000,27510=>1000,27511=>1000,27512=>1000,27513=>1000, -27515=>1000,27516=>1000,27518=>1000,27519=>1000,27520=>1000,27521=>1000,27522=>1000,27523=>1000,27524=>1000,27526=>1000, -27527=>1000,27528=>1000,27529=>1000,27530=>1000,27531=>1000,27532=>1000,27533=>1000,27534=>1000,27535=>1000,27537=>1000, -27538=>1000,27539=>1000,27540=>1000,27541=>1000,27542=>1000,27543=>1000,27544=>1000,27545=>1000,27546=>1000,27547=>1000, -27550=>1000,27551=>1000,27552=>1000,27553=>1000,27554=>1000,27555=>1000,27556=>1000,27557=>1000,27558=>1000,27559=>1000, -27562=>1000,27563=>1000,27565=>1000,27566=>1000,27567=>1000,27568=>1000,27569=>1000,27570=>1000,27571=>1000,27572=>1000, -27573=>1000,27574=>1000,27575=>1000,27578=>1000,27579=>1000,27580=>1000,27581=>1000,27583=>1000,27584=>1000,27585=>1000, -27586=>1000,27587=>1000,27588=>1000,27589=>1000,27590=>1000,27591=>1000,27592=>1000,27593=>1000,27594=>1000,27595=>1000, -27596=>1000,27597=>1000,27598=>1000,27599=>1000,27600=>1000,27602=>1000,27603=>1000,27604=>1000,27605=>1000,27606=>1000, -27607=>1000,27608=>1000,27609=>1000,27610=>1000,27611=>1000,27614=>1000,27615=>1000,27616=>1000,27617=>1000,27618=>1000, -27619=>1000,27620=>1000,27622=>1000,27623=>1000,27624=>1000,27626=>1000,27627=>1000,27628=>1000,27631=>1000,27632=>1000, -27634=>1000,27635=>1000,27637=>1000,27639=>1000,27640=>1000,27641=>1000,27643=>1000,27644=>1000,27645=>1000,27646=>1000, -27647=>1000,27648=>1000,27649=>1000,27650=>1000,27651=>1000,27652=>1000,27653=>1000,27654=>1000,27655=>1000,27656=>1000, -27657=>1000,27659=>1000,27660=>1000,27661=>1000,27663=>1000,27664=>1000,27665=>1000,27667=>1000,27668=>1000,27669=>1000, -27670=>1000,27671=>1000,27672=>1000,27673=>1000,27674=>1000,27675=>1000,27677=>1000,27679=>1000,27680=>1000,27681=>1000, -27682=>1000,27683=>1000,27684=>1000,27685=>1000,27686=>1000,27687=>1000,27688=>1000,27689=>1000,27690=>1000,27691=>1000, -27692=>1000,27694=>1000,27695=>1000,27696=>1000,27698=>1000,27699=>1000,27700=>1000,27701=>1000,27702=>1000,27703=>1000, -27704=>1000,27707=>1000,27709=>1000,27710=>1000,27711=>1000,27712=>1000,27713=>1000,27714=>1000,27715=>1000,27718=>1000, -27719=>1000,27721=>1000,27722=>1000,27723=>1000,27724=>1000,27725=>1000,27726=>1000,27727=>1000,27728=>1000,27730=>1000, -27732=>1000,27733=>1000,27735=>1000,27737=>1000,27738=>1000,27739=>1000,27740=>1000,27741=>1000,27742=>1000,27743=>1000, -27744=>1000,27745=>1000,27746=>1000,27748=>1000,27749=>1000,27750=>1000,27751=>1000,27752=>1000,27753=>1000,27754=>1000, -27755=>1000,27757=>1000,27759=>1000,27760=>1000,27761=>1000,27762=>1000,27763=>1000,27764=>1000,27766=>1000,27768=>1000, -27769=>1000,27770=>1000,27771=>1000,27773=>1000,27774=>1000,27776=>1000,27777=>1000,27778=>1000,27779=>1000,27780=>1000, -27781=>1000,27782=>1000,27783=>1000,27784=>1000,27785=>1000,27786=>1000,27787=>1000,27788=>1000,27789=>1000,27790=>1000, -27791=>1000,27792=>1000,27794=>1000,27795=>1000,27796=>1000,27797=>1000,27798=>1000,27800=>1000,27801=>1000,27802=>1000, -27803=>1000,27804=>1000,27805=>1000,27807=>1000,27809=>1000,27810=>1000,27811=>1000,27812=>1000,27813=>1000,27814=>1000, -27815=>1000,27817=>1000,27818=>1000,27819=>1000,27820=>1000,27821=>1000,27822=>1000,27824=>1000,27825=>1000,27826=>1000, -27827=>1000,27828=>1000,27830=>1000,27831=>1000,27832=>1000,27833=>1000,27834=>1000,27835=>1000,27836=>1000,27837=>1000, -27838=>1000,27839=>1000,27840=>1000,27841=>1000,27842=>1000,27843=>1000,27844=>1000,27845=>1000,27846=>1000,27847=>1000, -27849=>1000,27850=>1000,27852=>1000,27853=>1000,27855=>1000,27856=>1000,27857=>1000,27858=>1000,27859=>1000,27860=>1000, -27861=>1000,27862=>1000,27863=>1000,27865=>1000,27866=>1000,27867=>1000,27868=>1000,27869=>1000,27870=>1000,27872=>1000, -27873=>1000,27874=>1000,27875=>1000,27877=>1000,27879=>1000,27880=>1000,27881=>1000,27882=>1000,27883=>1000,27884=>1000, -27885=>1000,27886=>1000,27887=>1000,27888=>1000,27889=>1000,27890=>1000,27891=>1000,27893=>1000,27894=>1000,27895=>1000, -27896=>1000,27897=>1000,27898=>1000,27899=>1000,27900=>1000,27901=>1000,27902=>1000,27904=>1000,27905=>1000,27907=>1000, -27908=>1000,27911=>1000,27912=>1000,27913=>1000,27914=>1000,27915=>1000,27916=>1000,27917=>1000,27918=>1000,27919=>1000, -27920=>1000,27921=>1000,27922=>1000,27926=>1000,27927=>1000,27928=>1000,27929=>1000,27930=>1000,27931=>1000,27933=>1000, -27934=>1000,27935=>1000,27936=>1000,27938=>1000,27941=>1000,27943=>1000,27944=>1000,27945=>1000,27946=>1000,27947=>1000, -27948=>1000,27949=>1000,27950=>1000,27951=>1000,27952=>1000,27953=>1000,27954=>1000,27955=>1000,27956=>1000,27957=>1000, -27958=>1000,27959=>1000,27960=>1000,27961=>1000,27962=>1000,27963=>1000,27964=>1000,27965=>1000,27966=>1000,27967=>1000, -27968=>1000,27969=>1000,27970=>1000,27971=>1000,27972=>1000,27973=>1000,27974=>1000,27975=>1000,27976=>1000,27978=>1000, -27979=>1000,27981=>1000,27982=>1000,27983=>1000,27985=>1000,27986=>1000,27987=>1000,27988=>1000,27992=>1000,27993=>1000, -27994=>1000,27996=>1000,27998=>1000,27999=>1000,28000=>1000,28001=>1000,28002=>1000,28003=>1000,28004=>1000,28005=>1000, -28006=>1000,28007=>1000,28008=>1000,28009=>1000,28010=>1000,28012=>1000,28013=>1000,28014=>1000,28015=>1000,28016=>1000, -28020=>1000,28021=>1000,28022=>1000,28023=>1000,28024=>1000,28025=>1000,28026=>1000,28027=>1000,28028=>1000,28029=>1000, -28030=>1000,28031=>1000,28032=>1000,28034=>1000,28035=>1000,28036=>1000,28037=>1000,28038=>1000,28039=>1000,28040=>1000, -28041=>1000,28042=>1000,28043=>1000,28044=>1000,28045=>1000,28046=>1000,28048=>1000,28049=>1000,28050=>1000,28051=>1000, -28052=>1000,28053=>1000,28054=>1000,28055=>1000,28056=>1000,28057=>1000,28059=>1000,28060=>1000,28061=>1000,28062=>1000, -28063=>1000,28064=>1000,28065=>1000,28067=>1000,28068=>1000,28070=>1000,28071=>1000,28072=>1000,28073=>1000,28074=>1000, -28075=>1000,28076=>1000,28078=>1000,28079=>1000,28082=>1000,28083=>1000,28084=>1000,28085=>1000,28087=>1000,28088=>1000, -28090=>1000,28091=>1000,28092=>1000,28093=>1000,28094=>1000,28095=>1000,28096=>1000,28098=>1000,28099=>1000,28100=>1000, -28101=>1000,28102=>1000,28103=>1000,28104=>1000,28105=>1000,28106=>1000,28107=>1000,28108=>1000,28109=>1000,28111=>1000, -28112=>1000,28113=>1000,28114=>1000,28115=>1000,28116=>1000,28117=>1000,28118=>1000,28119=>1000,28120=>1000,28121=>1000, -28122=>1000,28123=>1000,28124=>1000,28125=>1000,28126=>1000,28127=>1000,28128=>1000,28129=>1000,28130=>1000,28131=>1000, -28132=>1000,28133=>1000,28134=>1000,28136=>1000,28137=>1000,28138=>1000,28139=>1000,28140=>1000,28141=>1000,28142=>1000, -28143=>1000,28144=>1000,28145=>1000,28146=>1000,28147=>1000,28148=>1000,28149=>1000,28150=>1000,28151=>1000,28152=>1000, -28153=>1000,28154=>1000,28155=>1000,28156=>1000,28157=>1000,28160=>1000,28163=>1000,28165=>1000,28167=>1000,28168=>1000, -28169=>1000,28170=>1000,28171=>1000,28172=>1000,28173=>1000,28174=>1000,28176=>1000,28177=>1000,28179=>1000,28180=>1000, -28181=>1000,28182=>1000,28183=>1000,28185=>1000,28186=>1000,28187=>1000,28188=>1000,28189=>1000,28191=>1000,28192=>1000, -28193=>1000,28194=>1000,28195=>1000,28196=>1000,28197=>1000,28198=>1000,28199=>1000,28200=>1000,28201=>1000,28203=>1000, -28204=>1000,28205=>1000,28206=>1000,28207=>1000,28208=>1000,28209=>1000,28210=>1000,28211=>1000,28212=>1000,28213=>1000, -28214=>1000,28216=>1000,28217=>1000,28218=>1000,28219=>1000,28220=>1000,28221=>1000,28222=>1000,28223=>1000,28224=>1000, -28225=>1000,28227=>1000,28228=>1000,28229=>1000,28230=>1000,28231=>1000,28233=>1000,28234=>1000,28235=>1000,28237=>1000, -28238=>1000,28241=>1000,28242=>1000,28243=>1000,28244=>1000,28245=>1000,28246=>1000,28248=>1000,28250=>1000,28251=>1000, -28252=>1000,28253=>1000,28254=>1000,28255=>1000,28256=>1000,28257=>1000,28258=>1000,28259=>1000,28260=>1000,28261=>1000, -28262=>1000,28263=>1000,28264=>1000,28265=>1000,28267=>1000,28270=>1000,28271=>1000,28273=>1000,28274=>1000,28275=>1000, -28276=>1000,28278=>1000,28279=>1000,28280=>1000,28281=>1000,28282=>1000,28286=>1000,28287=>1000,28288=>1000,28290=>1000, -28291=>1000,28293=>1000,28294=>1000,28296=>1000,28297=>1000,28300=>1000,28301=>1000,28302=>1000,28303=>1000,28304=>1000, -28306=>1000,28307=>1000,28308=>1000,28310=>1000,28311=>1000,28312=>1000,28313=>1000,28315=>1000,28316=>1000,28317=>1000, -28318=>1000,28319=>1000,28320=>1000,28321=>1000,28322=>1000,28323=>1000,28324=>1000,28325=>1000,28326=>1000,28327=>1000, -28330=>1000,28331=>1000,28334=>1000,28335=>1000,28336=>1000,28337=>1000,28338=>1000,28339=>1000,28340=>1000,28342=>1000, -28343=>1000,28345=>1000,28346=>1000,28347=>1000,28348=>1000,28349=>1000,28350=>1000,28351=>1000,28352=>1000,28353=>1000, -28354=>1000,28355=>1000,28356=>1000,28357=>1000,28358=>1000,28359=>1000,28360=>1000,28361=>1000,28362=>1000,28363=>1000, -28364=>1000,28365=>1000,28366=>1000,28367=>1000,28368=>1000,28369=>1000,28370=>1000,28371=>1000,28372=>1000,28373=>1000, -28374=>1000,28375=>1000,28376=>1000,28378=>1000,28380=>1000,28381=>1000,28382=>1000,28383=>1000,28384=>1000,28385=>1000, -28386=>1000,28388=>1000,28389=>1000,28390=>1000,28392=>1000,28393=>1000,28395=>1000,28396=>1000,28397=>1000,28398=>1000, -28399=>1000,28401=>1000,28402=>1000,28404=>1000,28405=>1000,28406=>1000,28407=>1000,28408=>1000,28409=>1000,28411=>1000, -28412=>1000,28413=>1000,28414=>1000,28415=>1000,28416=>1000,28417=>1000,28418=>1000,28419=>1000,28421=>1000,28422=>1000, -28423=>1000,28424=>1000,28425=>1000,28426=>1000,28429=>1000,28430=>1000,28431=>1000,28433=>1000,28434=>1000,28435=>1000, -28436=>1000,28437=>1000,28440=>1000,28441=>1000,28442=>1000,28444=>1000,28446=>1000,28447=>1000,28448=>1000,28449=>1000, -28450=>1000,28451=>1000,28452=>1000,28453=>1000,28454=>1000,28455=>1000,28457=>1000,28458=>1000,28459=>1000,28460=>1000, -28461=>1000,28462=>1000,28463=>1000,28464=>1000,28465=>1000,28466=>1000,28467=>1000,28469=>1000,28470=>1000,28471=>1000, -28472=>1000,28473=>1000,28474=>1000,28475=>1000,28476=>1000,28478=>1000,28479=>1000,28480=>1000,28481=>1000,28483=>1000, -28485=>1000,28486=>1000,28487=>1000,28491=>1000,28493=>1000,28494=>1000,28495=>1000,28496=>1000,28497=>1000,28498=>1000, -28499=>1000,28500=>1000,28501=>1000,28503=>1000,28504=>1000,28506=>1000,28507=>1000,28508=>1000,28509=>1000,28510=>1000, -28511=>1000,28512=>1000,28513=>1000,28514=>1000,28515=>1000,28516=>1000,28518=>1000,28519=>1000,28521=>1000,28522=>1000, -28523=>1000,28524=>1000,28525=>1000,28526=>1000,28527=>1000,28528=>1000,28530=>1000,28531=>1000,28532=>1000,28534=>1000, -28535=>1000,28536=>1000,28538=>1000,28539=>1000,28540=>1000,28541=>1000,28542=>1000,28543=>1000,28544=>1000,28545=>1000, -28546=>1000,28548=>1000,28549=>1000,28550=>1000,28551=>1000,28552=>1000,28553=>1000,28555=>1000,28556=>1000,28557=>1000, -28558=>1000,28560=>1000,28561=>1000,28562=>1000,28563=>1000,28564=>1000,28565=>1000,28566=>1000,28567=>1000,28572=>1000, -28574=>1000,28576=>1000,28577=>1000,28578=>1000,28579=>1000,28580=>1000,28581=>1000,28582=>1000,28583=>1000,28584=>1000, -28585=>1000,28586=>1000,28587=>1000,28588=>1000,28589=>1000,28590=>1000,28591=>1000,28592=>1000,28593=>1000,28594=>1000, -28595=>1000,28596=>1000,28597=>1000,28598=>1000,28600=>1000,28601=>1000,28602=>1000,28604=>1000,28605=>1000,28606=>1000, -28607=>1000,28608=>1000,28609=>1000,28610=>1000,28611=>1000,28612=>1000,28614=>1000,28615=>1000,28616=>1000,28617=>1000, -28618=>1000,28619=>1000,28620=>1000,28621=>1000,28622=>1000,28623=>1000,28625=>1000,28626=>1000,28628=>1000,28629=>1000, -28632=>1000,28634=>1000,28635=>1000,28636=>1000,28637=>1000,28638=>1000,28639=>1000,28640=>1000,28641=>1000,28642=>1000, -28643=>1000,28644=>1000,28646=>1000,28647=>1000,28648=>1000,28649=>1000,28651=>1000,28652=>1000,28653=>1000,28654=>1000, -28655=>1000,28656=>1000,28657=>1000,28658=>1000,28659=>1000,28660=>1000,28661=>1000,28662=>1000,28663=>1000,28666=>1000, -28667=>1000,28668=>1000,28670=>1000,28671=>1000,28672=>1000,28673=>1000,28676=>1000,28677=>1000,28678=>1000,28679=>1000, -28681=>1000,28682=>1000,28683=>1000,28684=>1000,28685=>1000,28686=>1000,28687=>1000,28689=>1000,28692=>1000,28693=>1000, -28694=>1000,28695=>1000,28696=>1000,28697=>1000,28698=>1000,28699=>1000,28700=>1000,28701=>1000,28702=>1000,28703=>1000, -28704=>1000,28705=>1000,28706=>1000,28707=>1000,28708=>1000,28710=>1000,28711=>1000,28712=>1000,28713=>1000,28714=>1000, -28715=>1000,28716=>1000,28719=>1000,28720=>1000,28721=>1000,28722=>1000,28723=>1000,28724=>1000,28725=>1000,28727=>1000, -28728=>1000,28729=>1000,28730=>1000,28731=>1000,28732=>1000,28734=>1000,28735=>1000,28736=>1000,28737=>1000,28738=>1000, -28739=>1000,28740=>1000,28741=>1000,28742=>1000,28744=>1000,28745=>1000,28746=>1000,28748=>1000,28751=>1000,28752=>1000, -28753=>1000,28754=>1000,28757=>1000,28758=>1000,28759=>1000,28760=>1000,28762=>1000,28763=>1000,28765=>1000,28766=>1000, -28767=>1000,28768=>1000,28769=>1000,28770=>1000,28771=>1000,28772=>1000,28773=>1000,28774=>1000,28776=>1000,28777=>1000, -28778=>1000,28779=>1000,28780=>1000,28781=>1000,28783=>1000,28784=>1000,28785=>1000,28788=>1000,28789=>1000,28790=>1000, -28792=>1000,28794=>1000,28796=>1000,28797=>1000,28798=>1000,28799=>1000,28800=>1000,28802=>1000,28803=>1000,28804=>1000, -28805=>1000,28806=>1000,28809=>1000,28810=>1000,28814=>1000,28817=>1000,28818=>1000,28819=>1000,28820=>1000,28821=>1000, -28822=>1000,28824=>1000,28825=>1000,28826=>1000,28828=>1000,28829=>1000,28831=>1000,28833=>1000,28836=>1000,28841=>1000, -28843=>1000,28844=>1000,28845=>1000,28846=>1000,28847=>1000,28848=>1000,28849=>1000,28851=>1000,28852=>1000,28853=>1000, -28855=>1000,28856=>1000,28857=>1000,28858=>1000,28859=>1000,28860=>1000,28861=>1000,28862=>1000,28864=>1000,28865=>1000, -28866=>1000,28867=>1000,28869=>1000,28870=>1000,28871=>1000,28872=>1000,28874=>1000,28875=>1000,28877=>1000,28878=>1000, -28879=>1000,28881=>1000,28882=>1000,28883=>1000,28884=>1000,28887=>1000,28888=>1000,28889=>1000,28890=>1000,28891=>1000, -28892=>1000,28893=>1000,28894=>1000,28895=>1000,28896=>1000,28897=>1000,28898=>1000,28900=>1000,28902=>1000,28903=>1000, -28904=>1000,28905=>1000,28907=>1000,28908=>1000,28909=>1000,28911=>1000,28912=>1000,28913=>1000,28915=>1000,28916=>1000, -28918=>1000,28919=>1000,28920=>1000,28921=>1000,28922=>1000,28923=>1000,28924=>1000,28925=>1000,28927=>1000,28928=>1000, -28930=>1000,28932=>1000,28934=>1000,28937=>1000,28938=>1000,28939=>1000,28940=>1000,28941=>1000,28942=>1000,28943=>1000, -28944=>1000,28947=>1000,28948=>1000,28949=>1000,28950=>1000,28951=>1000,28952=>1000,28953=>1000,28954=>1000,28955=>1000, -28956=>1000,28958=>1000,28959=>1000,28960=>1000,28961=>1000,28962=>1000,28963=>1000,28965=>1000,28966=>1000,28968=>1000, -28974=>1000,28975=>1000,28976=>1000,28977=>1000,28978=>1000,28982=>1000,28986=>1000,28988=>1000,28993=>1000,28994=>1000, -28995=>1000,28996=>1000,28997=>1000,28998=>1000,28999=>1000,29001=>1000,29002=>1000,29003=>1000,29004=>1000,29005=>1000, -29006=>1000,29008=>1000,29010=>1000,29011=>1000,29012=>1000,29013=>1000,29014=>1000,29016=>1000,29017=>1000,29018=>1000, -29020=>1000,29021=>1000,29022=>1000,29023=>1000,29024=>1000,29025=>1000,29026=>1000,29027=>1000,29028=>1000,29029=>1000, -29030=>1000,29031=>1000,29032=>1000,29033=>1000,29034=>1000,29036=>1000,29038=>1000,29040=>1000,29042=>1000,29043=>1000, -29048=>1000,29050=>1000,29051=>1000,29053=>1000,29056=>1000,29057=>1000,29058=>1000,29060=>1000,29061=>1000,29062=>1000, -29063=>1000,29064=>1000,29065=>1000,29066=>1000,29071=>1000,29072=>1000,29074=>1000,29076=>1000,29077=>1000,29079=>1000, -29080=>1000,29081=>1000,29082=>1000,29083=>1000,29084=>1000,29085=>1000,29086=>1000,29087=>1000,29088=>1000,29089=>1000, -29090=>1000,29092=>1000,29093=>1000,29095=>1000,29096=>1000,29097=>1000,29098=>1000,29100=>1000,29103=>1000,29104=>1000, -29105=>1000,29106=>1000,29107=>1000,29109=>1000,29112=>1000,29113=>1000,29114=>1000,29116=>1000,29117=>1000,29118=>1000, -29119=>1000,29120=>1000,29121=>1000,29122=>1000,29123=>1000,29124=>1000,29125=>1000,29126=>1000,29127=>1000,29128=>1000, -29129=>1000,29130=>1000,29131=>1000,29134=>1000,29135=>1000,29136=>1000,29138=>1000,29140=>1000,29141=>1000,29142=>1000, -29143=>1000,29144=>1000,29145=>1000,29146=>1000,29147=>1000,29148=>1000,29151=>1000,29152=>1000,29153=>1000,29154=>1000, -29156=>1000,29157=>1000,29158=>1000,29159=>1000,29160=>1000,29164=>1000,29165=>1000,29166=>1000,29168=>1000,29169=>1000, -29170=>1000,29172=>1000,29173=>1000,29176=>1000,29177=>1000,29179=>1000,29180=>1000,29181=>1000,29182=>1000,29183=>1000, -29184=>1000,29185=>1000,29186=>1000,29187=>1000,29189=>1000,29190=>1000,29191=>1000,29194=>1000,29196=>1000,29197=>1000, -29200=>1000,29203=>1000,29204=>1000,29209=>1000,29210=>1000,29211=>1000,29213=>1000,29214=>1000,29215=>1000,29218=>1000, -29219=>1000,29222=>1000,29223=>1000,29224=>1000,29225=>1000,29226=>1000,29228=>1000,29229=>1000,29232=>1000,29233=>1000, -29234=>1000,29237=>1000,29238=>1000,29239=>1000,29240=>1000,29241=>1000,29242=>1000,29243=>1000,29244=>1000,29245=>1000, -29246=>1000,29247=>1000,29248=>1000,29249=>1000,29250=>1000,29252=>1000,29254=>1000,29255=>1000,29256=>1000,29257=>1000, -29258=>1000,29259=>1000,29260=>1000,29261=>1000,29263=>1000,29266=>1000,29267=>1000,29270=>1000,29272=>1000,29273=>1000, -29274=>1000,29275=>1000,29277=>1000,29278=>1000,29279=>1000,29280=>1000,29281=>1000,29282=>1000,29283=>1000,29286=>1000, -29287=>1000,29289=>1000,29290=>1000,29292=>1000,29294=>1000,29295=>1000,29296=>1000,29298=>1000,29299=>1000,29300=>1000, -29301=>1000,29302=>1000,29303=>1000,29304=>1000,29305=>1000,29306=>1000,29307=>1000,29308=>1000,29309=>1000,29310=>1000, -29311=>1000,29312=>1000,29313=>1000,29314=>1000,29316=>1000,29317=>1000,29318=>1000,29319=>1000,29320=>1000,29321=>1000, -29322=>1000,29323=>1000,29324=>1000,29325=>1000,29326=>1000,29327=>1000,29328=>1000,29329=>1000,29330=>1000,29331=>1000, -29333=>1000,29334=>1000,29335=>1000,29336=>1000,29338=>1000,29339=>1000,29341=>1000,29342=>1000,29343=>1000,29344=>1000, -29345=>1000,29346=>1000,29347=>1000,29348=>1000,29349=>1000,29350=>1000,29351=>1000,29352=>1000,29353=>1000,29354=>1000, -29356=>1000,29357=>1000,29358=>1000,29359=>1000,29360=>1000,29361=>1000,29362=>1000,29364=>1000,29365=>1000,29366=>1000, -29367=>1000,29368=>1000,29369=>1000,29370=>1000,29373=>1000,29374=>1000,29375=>1000,29376=>1000,29377=>1000,29378=>1000, -29379=>1000,29380=>1000,29381=>1000,29382=>1000,29384=>1000,29385=>1000,29386=>1000,29387=>1000,29388=>1000,29389=>1000, -29390=>1000,29392=>1000,29393=>1000,29394=>1000,29396=>1000,29398=>1000,29399=>1000,29400=>1000,29401=>1000,29402=>1000, -29403=>1000,29404=>1000,29406=>1000,29407=>1000,29408=>1000,29409=>1000,29410=>1000,29411=>1000,29412=>1000,29414=>1000, -29416=>1000,29417=>1000,29418=>1000,29419=>1000,29420=>1000,29421=>1000,29422=>1000,29423=>1000,29424=>1000,29425=>1000, -29426=>1000,29427=>1000,29428=>1000,29430=>1000,29431=>1000,29432=>1000,29433=>1000,29434=>1000,29435=>1000,29436=>1000, -29437=>1000,29438=>1000,29439=>1000,29440=>1000,29441=>1000,29443=>1000,29447=>1000,29448=>1000,29450=>1000,29451=>1000, -29452=>1000,29454=>1000,29455=>1000,29457=>1000,29458=>1000,29459=>1000,29461=>1000,29462=>1000,29463=>1000,29464=>1000, -29465=>1000,29467=>1000,29468=>1000,29469=>1000,29470=>1000,29471=>1000,29473=>1000,29474=>1000,29475=>1000,29476=>1000, -29477=>1000,29478=>1000,29479=>1000,29481=>1000,29482=>1000,29483=>1000,29484=>1000,29485=>1000,29486=>1000,29487=>1000, -29488=>1000,29489=>1000,29490=>1000,29491=>1000,29492=>1000,29493=>1000,29494=>1000,29495=>1000,29496=>1000,29497=>1000, -29498=>1000,29499=>1000,29500=>1000,29502=>1000,29503=>1000,29504=>1000,29506=>1000,29507=>1000,29508=>1000,29509=>1000, -29513=>1000,29514=>1000,29516=>1000,29517=>1000,29518=>1000,29519=>1000,29520=>1000,29521=>1000,29522=>1000,29527=>1000, -29528=>1000,29529=>1000,29530=>1000,29531=>1000,29533=>1000,29534=>1000,29535=>1000,29536=>1000,29537=>1000,29538=>1000, -29539=>1000,29541=>1000,29542=>1000,29543=>1000,29544=>1000,29545=>1000,29546=>1000,29547=>1000,29548=>1000,29549=>1000, -29550=>1000,29551=>1000,29552=>1000,29554=>1000,29555=>1000,29557=>1000,29558=>1000,29559=>1000,29560=>1000,29562=>1000, -29563=>1000,29564=>1000,29565=>1000,29566=>1000,29567=>1000,29568=>1000,29569=>1000,29570=>1000,29571=>1000,29572=>1000, -29573=>1000,29574=>1000,29575=>1000,29576=>1000,29577=>1000,29578=>1000,29579=>1000,29582=>1000,29585=>1000,29586=>1000, -29587=>1000,29588=>1000,29589=>1000,29590=>1000,29591=>1000,29592=>1000,29595=>1000,29597=>1000,29599=>1000,29600=>1000, -29601=>1000,29602=>1000,29604=>1000,29605=>1000,29606=>1000,29607=>1000,29608=>1000,29609=>1000,29611=>1000,29612=>1000, -29613=>1000,29614=>1000,29615=>1000,29616=>1000,29618=>1000,29619=>1000,29620=>1000,29621=>1000,29622=>1000,29623=>1000, -29624=>1000,29625=>1000,29626=>1000,29627=>1000,29628=>1000,29629=>1000,29630=>1000,29631=>1000,29632=>1000,29634=>1000, -29635=>1000,29637=>1000,29638=>1000,29639=>1000,29640=>1000,29641=>1000,29642=>1000,29643=>1000,29644=>1000,29645=>1000, -29646=>1000,29647=>1000,29648=>1000,29649=>1000,29650=>1000,29651=>1000,29652=>1000,29654=>1000,29655=>1000,29656=>1000, -29657=>1000,29658=>1000,29659=>1000,29660=>1000,29661=>1000,29662=>1000,29664=>1000,29667=>1000,29668=>1000,29669=>1000, -29670=>1000,29671=>1000,29672=>1000,29673=>1000,29674=>1000,29675=>1000,29677=>1000,29678=>1000,29681=>1000,29682=>1000, -29684=>1000,29685=>1000,29686=>1000,29687=>1000,29688=>1000,29689=>1000,29690=>1000,29692=>1000,29693=>1000,29694=>1000, -29695=>1000,29696=>1000,29697=>1000,29699=>1000,29700=>1000,29701=>1000,29702=>1000,29703=>1000,29704=>1000,29705=>1000, -29706=>1000,29707=>1000,29708=>1000,29709=>1000,29711=>1000,29712=>1000,29715=>1000,29718=>1000,29722=>1000,29723=>1000, -29725=>1000,29728=>1000,29729=>1000,29730=>1000,29731=>1000,29732=>1000,29733=>1000,29734=>1000,29736=>1000,29737=>1000, -29738=>1000,29739=>1000,29740=>1000,29741=>1000,29742=>1000,29743=>1000,29744=>1000,29745=>1000,29746=>1000,29747=>1000, -29748=>1000,29749=>1000,29750=>1000,29752=>1000,29754=>1000,29756=>1000,29759=>1000,29760=>1000,29761=>1000,29762=>1000, -29763=>1000,29764=>1000,29766=>1000,29770=>1000,29771=>1000,29773=>1000,29774=>1000,29775=>1000,29776=>1000,29777=>1000, -29778=>1000,29780=>1000,29781=>1000,29783=>1000,29785=>1000,29786=>1000,29787=>1000,29788=>1000,29790=>1000,29791=>1000, -29792=>1000,29794=>1000,29795=>1000,29796=>1000,29797=>1000,29799=>1000,29800=>1000,29801=>1000,29802=>1000,29805=>1000, -29806=>1000,29807=>1000,29808=>1000,29809=>1000,29810=>1000,29811=>1000,29813=>1000,29814=>1000,29815=>1000,29817=>1000, -29820=>1000,29821=>1000,29822=>1000,29823=>1000,29824=>1000,29825=>1000,29826=>1000,29827=>1000,29829=>1000,29830=>1000, -29831=>1000,29832=>1000,29833=>1000,29834=>1000,29835=>1000,29838=>1000,29840=>1000,29842=>1000,29844=>1000,29845=>1000, -29847=>1000,29848=>1000,29850=>1000,29852=>1000,29854=>1000,29855=>1000,29856=>1000,29857=>1000,29858=>1000,29859=>1000, -29861=>1000,29862=>1000,29863=>1000,29864=>1000,29865=>1000,29866=>1000,29867=>1000,29869=>1000,29871=>1000,29872=>1000, -29873=>1000,29874=>1000,29877=>1000,29878=>1000,29879=>1000,29880=>1000,29881=>1000,29882=>1000,29883=>1000,29885=>1000, -29886=>1000,29887=>1000,29888=>1000,29889=>1000,29890=>1000,29891=>1000,29893=>1000,29894=>1000,29898=>1000,29899=>1000, -29903=>1000,29906=>1000,29908=>1000,29909=>1000,29910=>1000,29911=>1000,29912=>1000,29913=>1000,29914=>1000,29915=>1000, -29916=>1000,29917=>1000,29918=>1000,29919=>1000,29920=>1000,29921=>1000,29922=>1000,29923=>1000,29924=>1000,29925=>1000, -29926=>1000,29927=>1000,29928=>1000,29929=>1000,29932=>1000,29934=>1000,29935=>1000,29936=>1000,29937=>1000,29938=>1000, -29940=>1000,29941=>1000,29942=>1000,29943=>1000,29944=>1000,29947=>1000,29949=>1000,29950=>1000,29951=>1000,29952=>1000, -29953=>1000,29954=>1000,29955=>1000,29956=>1000,29957=>1000,29959=>1000,29960=>1000,29963=>1000,29964=>1000,29965=>1000, -29966=>1000,29967=>1000,29968=>1000,29969=>1000,29970=>1000,29971=>1000,29972=>1000,29973=>1000,29974=>1000,29975=>1000, -29976=>1000,29977=>1000,29978=>1000,29979=>1000,29980=>1000,29981=>1000,29982=>1000,29983=>1000,29985=>1000,29986=>1000, -29987=>1000,29989=>1000,29990=>1000,29992=>1000,29993=>1000,29994=>1000,29995=>1000,29996=>1000,29997=>1000,29998=>1000, -29999=>1000,30000=>1000,30001=>1000,30002=>1000,30003=>1000,30005=>1000,30007=>1000,30008=>1000,30009=>1000,30010=>1000, -30011=>1000,30012=>1000,30013=>1000,30014=>1000,30015=>1000,30016=>1000,30020=>1000,30021=>1000,30022=>1000,30023=>1000, -30024=>1000,30025=>1000,30026=>1000,30027=>1000,30028=>1000,30029=>1000,30030=>1000,30031=>1000,30033=>1000,30035=>1000, -30036=>1000,30041=>1000,30042=>1000,30043=>1000,30044=>1000,30045=>1000,30047=>1000,30048=>1000,30050=>1000,30051=>1000, -30052=>1000,30053=>1000,30054=>1000,30055=>1000,30057=>1000,30058=>1000,30059=>1000,30060=>1000,30061=>1000,30063=>1000, -30064=>1000,30066=>1000,30067=>1000,30068=>1000,30069=>1000,30070=>1000,30071=>1000,30072=>1000,30073=>1000,30074=>1000, -30077=>1000,30078=>1000,30079=>1000,30080=>1000,30082=>1000,30083=>1000,30084=>1000,30086=>1000,30087=>1000,30089=>1000, -30090=>1000,30091=>1000,30092=>1000,30094=>1000,30095=>1000,30096=>1000,30097=>1000,30098=>1000,30100=>1000,30101=>1000, -30102=>1000,30103=>1000,30104=>1000,30105=>1000,30106=>1000,30109=>1000,30111=>1000,30112=>1000,30113=>1000,30114=>1000, -30115=>1000,30116=>1000,30117=>1000,30119=>1000,30122=>1000,30123=>1000,30124=>1000,30126=>1000,30127=>1000,30128=>1000, -30129=>1000,30130=>1000,30131=>1000,30132=>1000,30133=>1000,30134=>1000,30136=>1000,30137=>1000,30138=>1000,30139=>1000, -30140=>1000,30141=>1000,30142=>1000,30143=>1000,30144=>1000,30145=>1000,30146=>1000,30147=>1000,30148=>1000,30149=>1000, -30151=>1000,30152=>1000,30153=>1000,30154=>1000,30155=>1000,30156=>1000,30157=>1000,30158=>1000,30159=>1000,30160=>1000, -30161=>1000,30162=>1000,30164=>1000,30165=>1000,30166=>1000,30167=>1000,30168=>1000,30169=>1000,30170=>1000,30171=>1000, -30173=>1000,30174=>1000,30175=>1000,30176=>1000,30177=>1000,30178=>1000,30179=>1000,30180=>1000,30182=>1000,30183=>1000, -30184=>1000,30185=>1000,30186=>1000,30187=>1000,30189=>1000,30191=>1000,30192=>1000,30193=>1000,30194=>1000,30195=>1000, -30196=>1000,30197=>1000,30198=>1000,30199=>1000,30200=>1000,30201=>1000,30202=>1000,30203=>1000,30204=>1000,30205=>1000, -30206=>1000,30207=>1000,30208=>1000,30209=>1000,30211=>1000,30213=>1000,30216=>1000,30217=>1000,30218=>1000,30219=>1000, -30220=>1000,30221=>1000,30223=>1000,30224=>1000,30225=>1000,30227=>1000,30228=>1000,30229=>1000,30230=>1000,30231=>1000, -30232=>1000,30233=>1000,30234=>1000,30235=>1000,30236=>1000,30237=>1000,30238=>1000,30239=>1000,30240=>1000,30241=>1000, -30242=>1000,30243=>1000,30244=>1000,30245=>1000,30246=>1000,30247=>1000,30248=>1000,30249=>1000,30250=>1000,30251=>1000, -30253=>1000,30255=>1000,30256=>1000,30257=>1000,30258=>1000,30259=>1000,30260=>1000,30261=>1000,30264=>1000,30266=>1000, -30267=>1000,30268=>1000,30269=>1000,30270=>1000,30271=>1000,30272=>1000,30274=>1000,30275=>1000,30278=>1000,30279=>1000, -30280=>1000,30281=>1000,30284=>1000,30285=>1000,30286=>1000,30288=>1000,30290=>1000,30291=>1000,30292=>1000,30294=>1000, -30295=>1000,30296=>1000,30297=>1000,30298=>1000,30300=>1000,30302=>1000,30303=>1000,30304=>1000,30305=>1000,30306=>1000, -30307=>1000,30308=>1000,30309=>1000,30311=>1000,30312=>1000,30313=>1000,30314=>1000,30315=>1000,30316=>1000,30317=>1000, -30318=>1000,30319=>1000,30320=>1000,30321=>1000,30322=>1000,30325=>1000,30326=>1000,30328=>1000,30329=>1000,30330=>1000, -30331=>1000,30332=>1000,30333=>1000,30334=>1000,30335=>1000,30336=>1000,30337=>1000,30338=>1000,30339=>1000,30340=>1000, -30342=>1000,30343=>1000,30344=>1000,30345=>1000,30346=>1000,30347=>1000,30350=>1000,30351=>1000,30352=>1000,30353=>1000, -30354=>1000,30355=>1000,30357=>1000,30358=>1000,30361=>1000,30362=>1000,30363=>1000,30364=>1000,30365=>1000,30366=>1000, -30372=>1000,30374=>1000,30378=>1000,30379=>1000,30381=>1000,30382=>1000,30383=>1000,30384=>1000,30385=>1000,30386=>1000, -30388=>1000,30389=>1000,30391=>1000,30392=>1000,30393=>1000,30394=>1000,30395=>1000,30397=>1000,30398=>1000,30399=>1000, -30402=>1000,30403=>1000,30404=>1000,30405=>1000,30406=>1000,30408=>1000,30409=>1000,30410=>1000,30413=>1000,30414=>1000, -30415=>1000,30416=>1000,30417=>1000,30418=>1000,30419=>1000,30420=>1000,30422=>1000,30423=>1000,30424=>1000,30426=>1000, -30427=>1000,30428=>1000,30429=>1000,30430=>1000,30431=>1000,30433=>1000,30435=>1000,30436=>1000,30437=>1000,30438=>1000, -30439=>1000,30441=>1000,30442=>1000,30444=>1000,30445=>1000,30446=>1000,30447=>1000,30448=>1000,30449=>1000,30450=>1000, -30451=>1000,30452=>1000,30453=>1000,30455=>1000,30456=>1000,30457=>1000,30458=>1000,30459=>1000,30460=>1000,30462=>1000, -30465=>1000,30467=>1000,30468=>1000,30469=>1000,30471=>1000,30472=>1000,30473=>1000,30474=>1000,30475=>1000,30476=>1000, -30477=>1000,30480=>1000,30481=>1000,30482=>1000,30483=>1000,30485=>1000,30489=>1000,30490=>1000,30491=>1000,30493=>1000, -30494=>1000,30495=>1000,30496=>1000,30498=>1000,30499=>1000,30500=>1000,30501=>1000,30502=>1000,30503=>1000,30504=>1000, -30505=>1000,30509=>1000,30511=>1000,30513=>1000,30514=>1000,30515=>1000,30516=>1000,30517=>1000,30518=>1000,30519=>1000, -30520=>1000,30521=>1000,30522=>1000,30523=>1000,30524=>1000,30525=>1000,30526=>1000,30528=>1000,30529=>1000,30531=>1000, -30532=>1000,30533=>1000,30534=>1000,30535=>1000,30538=>1000,30539=>1000,30540=>1000,30541=>1000,30542=>1000,30543=>1000, -30544=>1000,30545=>1000,30546=>1000,30548=>1000,30549=>1000,30550=>1000,30553=>1000,30554=>1000,30555=>1000,30556=>1000, -30558=>1000,30559=>1000,30560=>1000,30561=>1000,30562=>1000,30563=>1000,30565=>1000,30566=>1000,30567=>1000,30568=>1000, -30569=>1000,30570=>1000,30571=>1000,30572=>1000,30573=>1000,30574=>1000,30575=>1000,30585=>1000,30588=>1000,30589=>1000, -30590=>1000,30591=>1000,30592=>1000,30593=>1000,30594=>1000,30595=>1000,30596=>1000,30597=>1000,30599=>1000,30600=>1000, -30601=>1000,30603=>1000,30604=>1000,30605=>1000,30606=>1000,30607=>1000,30609=>1000,30610=>1000,30613=>1000,30615=>1000, -30617=>1000,30618=>1000,30619=>1000,30620=>1000,30621=>1000,30622=>1000,30623=>1000,30624=>1000,30625=>1000,30626=>1000, -30627=>1000,30629=>1000,30631=>1000,30632=>1000,30633=>1000,30634=>1000,30635=>1000,30636=>1000,30637=>1000,30640=>1000, -30641=>1000,30642=>1000,30643=>1000,30644=>1000,30645=>1000,30646=>1000,30647=>1000,30649=>1000,30650=>1000,30651=>1000, -30652=>1000,30653=>1000,30655=>1000,30658=>1000,30660=>1000,30663=>1000,30665=>1000,30666=>1000,30668=>1000,30669=>1000, -30670=>1000,30671=>1000,30672=>1000,30675=>1000,30676=>1000,30677=>1000,30679=>1000,30680=>1000,30681=>1000,30682=>1000, -30683=>1000,30684=>1000,30686=>1000,30688=>1000,30690=>1000,30691=>1000,30693=>1000,30695=>1000,30696=>1000,30697=>1000, -30699=>1000,30700=>1000,30701=>1000,30702=>1000,30703=>1000,30704=>1000,30705=>1000,30706=>1000,30707=>1000,30710=>1000, -30711=>1000,30712=>1000,30713=>1000,30714=>1000,30715=>1000,30716=>1000,30717=>1000,30718=>1000,30719=>1000,30720=>1000, -30721=>1000,30722=>1000,30723=>1000,30725=>1000,30726=>1000,30729=>1000,30732=>1000,30733=>1000,30734=>1000,30735=>1000, -30736=>1000,30737=>1000,30738=>1000,30739=>1000,30740=>1000,30741=>1000,30742=>1000,30743=>1000,30744=>1000,30746=>1000, -30748=>1000,30749=>1000,30751=>1000,30752=>1000,30753=>1000,30754=>1000,30755=>1000,30757=>1000,30758=>1000,30759=>1000, -30760=>1000,30761=>1000,30762=>1000,30763=>1000,30764=>1000,30765=>1000,30766=>1000,30767=>1000,30768=>1000,30769=>1000, -30770=>1000,30771=>1000,30772=>1000,30773=>1000,30775=>1000,30776=>1000,30777=>1000,30778=>1000,30779=>1000,30780=>1000, -30782=>1000,30783=>1000,30784=>1000,30787=>1000,30789=>1000,30791=>1000,30792=>1000,30793=>1000,30794=>1000,30796=>1000, -30797=>1000,30798=>1000,30799=>1000,30800=>1000,30802=>1000,30805=>1000,30806=>1000,30807=>1000,30812=>1000,30813=>1000, -30814=>1000,30816=>1000,30818=>1000,30820=>1000,30821=>1000,30824=>1000,30825=>1000,30826=>1000,30827=>1000,30828=>1000, -30829=>1000,30830=>1000,30831=>1000,30832=>1000,30833=>1000,30834=>1000,30836=>1000,30839=>1000,30841=>1000,30842=>1000, -30843=>1000,30844=>1000,30846=>1000,30847=>1000,30848=>1000,30849=>1000,30851=>1000,30852=>1000,30853=>1000,30854=>1000, -30855=>1000,30857=>1000,30860=>1000,30861=>1000,30862=>1000,30863=>1000,30865=>1000,30867=>1000,30868=>1000,30869=>1000, -30870=>1000,30871=>1000,30872=>1000,30873=>1000,30874=>1000,30875=>1000,30876=>1000,30878=>1000,30879=>1000,30880=>1000, -30881=>1000,30882=>1000,30883=>1000,30884=>1000,30885=>1000,30887=>1000,30888=>1000,30889=>1000,30890=>1000,30891=>1000, -30892=>1000,30893=>1000,30895=>1000,30896=>1000,30897=>1000,30898=>1000,30899=>1000,30900=>1000,30901=>1000,30905=>1000, -30906=>1000,30907=>1000,30908=>1000,30910=>1000,30913=>1000,30915=>1000,30916=>1000,30917=>1000,30918=>1000,30920=>1000, -30921=>1000,30922=>1000,30923=>1000,30924=>1000,30925=>1000,30926=>1000,30927=>1000,30928=>1000,30929=>1000,30932=>1000, -30933=>1000,30937=>1000,30938=>1000,30939=>1000,30941=>1000,30942=>1000,30943=>1000,30944=>1000,30945=>1000,30946=>1000, -30947=>1000,30949=>1000,30951=>1000,30952=>1000,30953=>1000,30954=>1000,30956=>1000,30957=>1000,30959=>1000,30962=>1000, -30963=>1000,30964=>1000,30965=>1000,30967=>1000,30969=>1000,30970=>1000,30971=>1000,30972=>1000,30973=>1000,30974=>1000, -30975=>1000,30977=>1000,30978=>1000,30980=>1000,30981=>1000,30983=>1000,30985=>1000,30988=>1000,30990=>1000,30992=>1000, -30993=>1000,30994=>1000,30995=>1000,30996=>1000,30998=>1000,30999=>1000,31001=>1000,31003=>1000,31004=>1000,31005=>1000, -31006=>1000,31009=>1000,31011=>1000,31012=>1000,31013=>1000,31014=>1000,31015=>1000,31016=>1000,31017=>1000,31018=>1000, -31019=>1000,31020=>1000,31021=>1000,31023=>1000,31024=>1000,31025=>1000,31028=>1000,31029=>1000,31032=>1000,31033=>1000, -31034=>1000,31035=>1000,31036=>1000,31037=>1000,31038=>1000,31039=>1000,31040=>1000,31041=>1000,31042=>1000,31044=>1000, -31045=>1000,31046=>1000,31047=>1000,31048=>1000,31049=>1000,31050=>1000,31051=>1000,31052=>1000,31055=>1000,31056=>1000, -31057=>1000,31058=>1000,31059=>1000,31060=>1000,31061=>1000,31062=>1000,31063=>1000,31066=>1000,31067=>1000,31068=>1000, -31069=>1000,31070=>1000,31071=>1000,31072=>1000,31073=>1000,31074=>1000,31075=>1000,31076=>1000,31077=>1000,31079=>1000, -31080=>1000,31081=>1000,31082=>1000,31083=>1000,31085=>1000,31087=>1000,31088=>1000,31090=>1000,31091=>1000,31092=>1000, -31095=>1000,31096=>1000,31097=>1000,31098=>1000,31100=>1000,31101=>1000,31103=>1000,31104=>1000,31105=>1000,31106=>1000, -31108=>1000,31109=>1000,31112=>1000,31114=>1000,31115=>1000,31117=>1000,31118=>1000,31119=>1000,31120=>1000,31121=>1000, -31122=>1000,31123=>1000,31124=>1000,31125=>1000,31126=>1000,31127=>1000,31128=>1000,31130=>1000,31131=>1000,31132=>1000, -31133=>1000,31136=>1000,31137=>1000,31138=>1000,31140=>1000,31142=>1000,31143=>1000,31144=>1000,31146=>1000,31147=>1000, -31148=>1000,31149=>1000,31150=>1000,31152=>1000,31153=>1000,31154=>1000,31155=>1000,31156=>1000,31158=>1000,31159=>1000, -31160=>1000,31161=>1000,31162=>1000,31163=>1000,31165=>1000,31166=>1000,31167=>1000,31168=>1000,31169=>1000,31171=>1000, -31173=>1000,31174=>1000,31176=>1000,31177=>1000,31178=>1000,31179=>1000,31181=>1000,31182=>1000,31183=>1000,31185=>1000, -31186=>1000,31189=>1000,31190=>1000,31192=>1000,31196=>1000,31197=>1000,31198=>1000,31199=>1000,31200=>1000,31201=>1000, -31203=>1000,31204=>1000,31206=>1000,31207=>1000,31209=>1000,31210=>1000,31211=>1000,31212=>1000,31213=>1000,31214=>1000, -31215=>1000,31216=>1000,31222=>1000,31223=>1000,31224=>1000,31226=>1000,31227=>1000,31229=>1000,31232=>1000,31234=>1000, -31235=>1000,31236=>1000,31237=>1000,31238=>1000,31240=>1000,31242=>1000,31243=>1000,31244=>1000,31245=>1000,31246=>1000, -31248=>1000,31249=>1000,31250=>1000,31251=>1000,31252=>1000,31253=>1000,31255=>1000,31256=>1000,31257=>1000,31258=>1000, -31259=>1000,31260=>1000,31262=>1000,31263=>1000,31264=>1000,31266=>1000,31267=>1000,31270=>1000,31272=>1000,31275=>1000, -31278=>1000,31279=>1000,31280=>1000,31281=>1000,31282=>1000,31283=>1000,31286=>1000,31287=>1000,31289=>1000,31291=>1000, -31292=>1000,31293=>1000,31294=>1000,31295=>1000,31296=>1000,31298=>1000,31299=>1000,31300=>1000,31302=>1000,31303=>1000, -31304=>1000,31305=>1000,31306=>1000,31307=>1000,31308=>1000,31309=>1000,31310=>1000,31311=>1000,31312=>1000,31313=>1000, -31316=>1000,31318=>1000,31319=>1000,31320=>1000,31322=>1000,31323=>1000,31324=>1000,31327=>1000,31328=>1000,31329=>1000, -31330=>1000,31331=>1000,31335=>1000,31336=>1000,31337=>1000,31339=>1000,31340=>1000,31341=>1000,31342=>1000,31344=>1000, -31345=>1000,31348=>1000,31349=>1000,31350=>1000,31351=>1000,31352=>1000,31353=>1000,31354=>1000,31355=>1000,31357=>1000, -31358=>1000,31359=>1000,31360=>1000,31361=>1000,31363=>1000,31364=>1000,31365=>1000,31366=>1000,31367=>1000,31368=>1000, -31369=>1000,31370=>1000,31371=>1000,31372=>1000,31373=>1000,31375=>1000,31376=>1000,31377=>1000,31378=>1000,31379=>1000, -31380=>1000,31381=>1000,31382=>1000,31383=>1000,31384=>1000,31385=>1000,31388=>1000,31389=>1000,31390=>1000,31391=>1000, -31392=>1000,31394=>1000,31395=>1000,31397=>1000,31398=>1000,31400=>1000,31401=>1000,31402=>1000,31403=>1000,31404=>1000, -31405=>1000,31406=>1000,31407=>1000,31408=>1000,31409=>1000,31410=>1000,31411=>1000,31412=>1000,31413=>1000,31414=>1000, -31415=>1000,31416=>1000,31418=>1000,31422=>1000,31423=>1000,31424=>1000,31425=>1000,31427=>1000,31428=>1000,31429=>1000, -31431=>1000,31432=>1000,31434=>1000,31435=>1000,31437=>1000,31439=>1000,31441=>1000,31442=>1000,31443=>1000,31445=>1000, -31446=>1000,31447=>1000,31448=>1000,31449=>1000,31450=>1000,31452=>1000,31453=>1000,31454=>1000,31455=>1000,31456=>1000, -31457=>1000,31458=>1000,31459=>1000,31460=>1000,31461=>1000,31462=>1000,31463=>1000,31466=>1000,31467=>1000,31469=>1000, -31470=>1000,31471=>1000,31472=>1000,31478=>1000,31479=>1000,31480=>1000,31481=>1000,31482=>1000,31483=>1000,31485=>1000, -31487=>1000,31488=>1000,31489=>1000,31490=>1000,31491=>1000,31492=>1000,31493=>1000,31494=>1000,31496=>1000,31497=>1000, -31498=>1000,31499=>1000,31502=>1000,31503=>1000,31504=>1000,31505=>1000,31506=>1000,31507=>1000,31508=>1000,31509=>1000, -31512=>1000,31513=>1000,31514=>1000,31515=>1000,31517=>1000,31518=>1000,31520=>1000,31522=>1000,31523=>1000,31524=>1000, -31525=>1000,31526=>1000,31528=>1000,31530=>1000,31531=>1000,31532=>1000,31533=>1000,31534=>1000,31535=>1000,31536=>1000, -31537=>1000,31538=>1000,31539=>1000,31540=>1000,31541=>1000,31542=>1000,31544=>1000,31545=>1000,31546=>1000,31547=>1000, -31548=>1000,31550=>1000,31552=>1000,31556=>1000,31557=>1000,31558=>1000,31559=>1000,31560=>1000,31561=>1000,31562=>1000, -31563=>1000,31564=>1000,31565=>1000,31566=>1000,31567=>1000,31568=>1000,31569=>1000,31570=>1000,31572=>1000,31574=>1000, -31576=>1000,31578=>1000,31579=>1000,31581=>1000,31584=>1000,31585=>1000,31586=>1000,31587=>1000,31588=>1000,31589=>1000, -31590=>1000,31591=>1000,31593=>1000,31596=>1000,31597=>1000,31598=>1000,31600=>1000,31601=>1000,31602=>1000,31603=>1000, -31604=>1000,31605=>1000,31606=>1000,31607=>1000,31608=>1000,31609=>1000,31610=>1000,31611=>1000,31613=>1000,31614=>1000, -31616=>1000,31618=>1000,31620=>1000,31621=>1000,31622=>1000,31623=>1000,31624=>1000,31626=>1000,31627=>1000,31628=>1000, -31629=>1000,31630=>1000,31631=>1000,31632=>1000,31633=>1000,31634=>1000,31636=>1000,31637=>1000,31638=>1000,31639=>1000, -31640=>1000,31641=>1000,31642=>1000,31643=>1000,31644=>1000,31645=>1000,31646=>1000,31647=>1000,31648=>1000,31649=>1000, -31650=>1000,31652=>1000,31654=>1000,31655=>1000,31656=>1000,31657=>1000,31658=>1000,31659=>1000,31660=>1000,31661=>1000, -31663=>1000,31665=>1000,31668=>1000,31669=>1000,31671=>1000,31672=>1000,31673=>1000,31678=>1000,31680=>1000,31681=>1000, -31684=>1000,31686=>1000,31687=>1000,31689=>1000,31690=>1000,31691=>1000,31692=>1000,31694=>1000,31695=>1000,31697=>1000, -31698=>1000,31699=>1000,31700=>1000,31701=>1000,31704=>1000,31705=>1000,31706=>1000,31707=>1000,31708=>1000,31709=>1000, -31710=>1000,31711=>1000,31712=>1000,31713=>1000,31714=>1000,31715=>1000,31716=>1000,31717=>1000,31718=>1000,31719=>1000, -31720=>1000,31721=>1000,31722=>1000,31723=>1000,31725=>1000,31726=>1000,31728=>1000,31729=>1000,31730=>1000,31731=>1000, -31732=>1000,31734=>1000,31735=>1000,31736=>1000,31737=>1000,31739=>1000,31740=>1000,31741=>1000,31742=>1000,31743=>1000, -31744=>1000,31745=>1000,31746=>1000,31747=>1000,31749=>1000,31750=>1000,31751=>1000,31753=>1000,31754=>1000,31755=>1000, -31756=>1000,31757=>1000,31758=>1000,31759=>1000,31760=>1000,31761=>1000,31762=>1000,31763=>1000,31764=>1000,31766=>1000, -31767=>1000,31769=>1000,31772=>1000,31773=>1000,31774=>1000,31775=>1000,31776=>1000,31777=>1000,31778=>1000,31779=>1000, -31781=>1000,31782=>1000,31783=>1000,31784=>1000,31785=>1000,31786=>1000,31787=>1000,31788=>1000,31789=>1000,31792=>1000, -31795=>1000,31799=>1000,31800=>1000,31801=>1000,31803=>1000,31804=>1000,31805=>1000,31806=>1000,31807=>1000,31808=>1000, -31809=>1000,31811=>1000,31813=>1000,31815=>1000,31816=>1000,31817=>1000,31818=>1000,31820=>1000,31821=>1000,31823=>1000, -31824=>1000,31827=>1000,31828=>1000,31830=>1000,31831=>1000,31832=>1000,31833=>1000,31834=>1000,31835=>1000,31836=>1000, -31839=>1000,31840=>1000,31843=>1000,31844=>1000,31845=>1000,31846=>1000,31847=>1000,31849=>1000,31850=>1000,31851=>1000, -31852=>1000,31854=>1000,31855=>1000,31858=>1000,31859=>1000,31860=>1000,31861=>1000,31864=>1000,31865=>1000,31866=>1000, -31867=>1000,31868=>1000,31869=>1000,31870=>1000,31871=>1000,31872=>1000,31873=>1000,31874=>1000,31875=>1000,31876=>1000, -31877=>1000,31880=>1000,31881=>1000,31882=>1000,31883=>1000,31884=>1000,31885=>1000,31888=>1000,31889=>1000,31890=>1000, -31892=>1000,31893=>1000,31894=>1000,31895=>1000,31896=>1000,31899=>1000,31900=>1000,31901=>1000,31902=>1000,31903=>1000, -31905=>1000,31906=>1000,31907=>1000,31908=>1000,31909=>1000,31911=>1000,31912=>1000,31914=>1000,31915=>1000,31917=>1000, -31918=>1000,31919=>1000,31921=>1000,31922=>1000,31923=>1000,31924=>1000,31925=>1000,31929=>1000,31930=>1000,31931=>1000, -31932=>1000,31933=>1000,31934=>1000,31935=>1000,31936=>1000,31937=>1000,31938=>1000,31941=>1000,31943=>1000,31944=>1000, -31946=>1000,31947=>1000,31948=>1000,31949=>1000,31950=>1000,31952=>1000,31953=>1000,31954=>1000,31956=>1000,31957=>1000, -31958=>1000,31959=>1000,31960=>1000,31961=>1000,31964=>1000,31965=>1000,31966=>1000,31967=>1000,31968=>1000,31970=>1000, -31975=>1000,31976=>1000,31978=>1000,31980=>1000,31982=>1000,31983=>1000,31984=>1000,31985=>1000,31986=>1000,31988=>1000, -31990=>1000,31991=>1000,31992=>1000,31994=>1000,31995=>1000,31997=>1000,31998=>1000,32000=>1000,32001=>1000,32002=>1000, -32003=>1000,32004=>1000,32005=>1000,32006=>1000,32007=>1000,32008=>1000,32009=>1000,32010=>1000,32011=>1000,32012=>1000, -32013=>1000,32014=>1000,32015=>1000,32016=>1000,32017=>1000,32018=>1000,32019=>1000,32020=>1000,32021=>1000,32022=>1000, -32023=>1000,32024=>1000,32025=>1000,32026=>1000,32027=>1000,32028=>1000,32029=>1000,32030=>1000,32031=>1000,32032=>1000, -32033=>1000,32034=>1000,32039=>1000,32040=>1000,32041=>1000,32043=>1000,32044=>1000,32046=>1000,32047=>1000,32048=>1000, -32049=>1000,32050=>1000,32051=>1000,32053=>1000,32054=>1000,32056=>1000,32057=>1000,32058=>1000,32059=>1000,32060=>1000, -32061=>1000,32062=>1000,32063=>1000,32064=>1000,32065=>1000,32066=>1000,32067=>1000,32068=>1000,32069=>1000,32070=>1000, -32071=>1000,32072=>1000,32074=>1000,32075=>1000,32076=>1000,32078=>1000,32079=>1000,32080=>1000,32081=>1000,32082=>1000, -32083=>1000,32084=>1000,32085=>1000,32086=>1000,32088=>1000,32091=>1000,32092=>1000,32094=>1000,32095=>1000,32097=>1000, -32098=>1000,32099=>1000,32102=>1000,32103=>1000,32104=>1000,32105=>1000,32106=>1000,32107=>1000,32109=>1000,32110=>1000, -32111=>1000,32112=>1000,32113=>1000,32114=>1000,32115=>1000,32117=>1000,32118=>1000,32119=>1000,32121=>1000,32122=>1000, -32123=>1000,32124=>1000,32125=>1000,32127=>1000,32128=>1000,32129=>1000,32131=>1000,32132=>1000,32133=>1000,32134=>1000, -32136=>1000,32137=>1000,32140=>1000,32141=>1000,32142=>1000,32143=>1000,32145=>1000,32146=>1000,32147=>1000,32148=>1000, -32150=>1000,32153=>1000,32154=>1000,32155=>1000,32156=>1000,32157=>1000,32158=>1000,32159=>1000,32160=>1000,32161=>1000, -32162=>1000,32163=>1000,32166=>1000,32167=>1000,32169=>1000,32170=>1000,32171=>1000,32172=>1000,32173=>1000,32174=>1000, -32175=>1000,32176=>1000,32177=>1000,32178=>1000,32180=>1000,32181=>1000,32183=>1000,32184=>1000,32185=>1000,32186=>1000, -32187=>1000,32188=>1000,32189=>1000,32190=>1000,32191=>1000,32192=>1000,32193=>1000,32194=>1000,32196=>1000,32197=>1000, -32198=>1000,32199=>1000,32201=>1000,32202=>1000,32203=>1000,32204=>1000,32206=>1000,32207=>1000,32209=>1000,32210=>1000, -32213=>1000,32214=>1000,32215=>1000,32216=>1000,32217=>1000,32218=>1000,32219=>1000,32220=>1000,32221=>1000,32222=>1000, -32223=>1000,32224=>1000,32225=>1000,32227=>1000,32228=>1000,32230=>1000,32231=>1000,32232=>1000,32233=>1000,32234=>1000, -32236=>1000,32238=>1000,32239=>1000,32240=>1000,32241=>1000,32242=>1000,32243=>1000,32244=>1000,32246=>1000,32247=>1000, -32249=>1000,32250=>1000,32251=>1000,32257=>1000,32259=>1000,32260=>1000,32261=>1000,32264=>1000,32265=>1000,32266=>1000, -32267=>1000,32268=>1000,32269=>1000,32270=>1000,32271=>1000,32272=>1000,32273=>1000,32274=>1000,32275=>1000,32276=>1000, -32277=>1000,32278=>1000,32279=>1000,32282=>1000,32283=>1000,32284=>1000,32285=>1000,32286=>1000,32287=>1000,32288=>1000, -32289=>1000,32290=>1000,32291=>1000,32292=>1000,32293=>1000,32294=>1000,32297=>1000,32298=>1000,32299=>1000,32301=>1000, -32302=>1000,32303=>1000,32304=>1000,32305=>1000,32306=>1000,32307=>1000,32308=>1000,32309=>1000,32310=>1000,32311=>1000, -32312=>1000,32313=>1000,32314=>1000,32315=>1000,32316=>1000,32317=>1000,32318=>1000,32319=>1000,32320=>1000,32321=>1000, -32322=>1000,32323=>1000,32324=>1000,32325=>1000,32326=>1000,32327=>1000,32328=>1000,32329=>1000,32330=>1000,32331=>1000, -32332=>1000,32333=>1000,32336=>1000,32337=>1000,32338=>1000,32339=>1000,32340=>1000,32341=>1000,32342=>1000,32343=>1000, -32344=>1000,32345=>1000,32346=>1000,32348=>1000,32349=>1000,32350=>1000,32351=>1000,32352=>1000,32353=>1000,32354=>1000, -32355=>1000,32358=>1000,32359=>1000,32360=>1000,32361=>1000,32362=>1000,32363=>1000,32365=>1000,32367=>1000,32368=>1000, -32370=>1000,32371=>1000,32372=>1000,32373=>1000,32374=>1000,32375=>1000,32376=>1000,32377=>1000,32378=>1000,32379=>1000, -32380=>1000,32381=>1000,32382=>1000,32383=>1000,32384=>1000,32385=>1000,32386=>1000,32387=>1000,32390=>1000,32391=>1000, -32392=>1000,32393=>1000,32394=>1000,32395=>1000,32396=>1000,32397=>1000,32398=>1000,32399=>1000,32400=>1000,32401=>1000, -32402=>1000,32403=>1000,32404=>1000,32405=>1000,32406=>1000,32407=>1000,32408=>1000,32409=>1000,32410=>1000,32411=>1000, -32412=>1000,32415=>1000,32416=>1000,32417=>1000,32418=>1000,32419=>1000,32420=>1000,32421=>1000,32422=>1000,32423=>1000, -32424=>1000,32425=>1000,32426=>1000,32427=>1000,32428=>1000,32429=>1000,32431=>1000,32432=>1000,32433=>1000,32434=>1000, -32435=>1000,32437=>1000,32438=>1000,32439=>1000,32440=>1000,32441=>1000,32442=>1000,32445=>1000,32446=>1000,32447=>1000, -32448=>1000,32449=>1000,32450=>1000,32451=>1000,32452=>1000,32453=>1000,32454=>1000,32455=>1000,32456=>1000,32457=>1000, -32458=>1000,32459=>1000,32460=>1000,32461=>1000,32462=>1000,32463=>1000,32464=>1000,32465=>1000,32466=>1000,32467=>1000, -32468=>1000,32469=>1000,32471=>1000,32472=>1000,32473=>1000,32474=>1000,32475=>1000,32476=>1000,32477=>1000,32478=>1000, -32479=>1000,32480=>1000,32481=>1000,32482=>1000,32483=>1000,32485=>1000,32486=>1000,32487=>1000,32488=>1000,32489=>1000, -32490=>1000,32491=>1000,32493=>1000,32494=>1000,32495=>1000,32496=>1000,32497=>1000,32498=>1000,32499=>1000,32500=>1000, -32501=>1000,32502=>1000,32503=>1000,32504=>1000,32506=>1000,32507=>1000,32508=>1000,32509=>1000,32510=>1000,32511=>1000, -32512=>1000,32513=>1000,32514=>1000,32515=>1000,32516=>1000,32517=>1000,32518=>1000,32519=>1000,32520=>1000,32521=>1000, -32523=>1000,32524=>1000,32525=>1000,32526=>1000,32527=>1000,32529=>1000,32530=>1000,32531=>1000,32532=>1000,32533=>1000, -32534=>1000,32535=>1000,32536=>1000,32537=>1000,32538=>1000,32539=>1000,32540=>1000,32541=>1000,32543=>1000,32544=>1000, -32545=>1000,32546=>1000,32547=>1000,32548=>1000,32549=>1000,32550=>1000,32551=>1000,32552=>1000,32553=>1000,32554=>1000, -32555=>1000,32556=>1000,32557=>1000,32558=>1000,32559=>1000,32560=>1000,32561=>1000,32562=>1000,32563=>1000,32564=>1000, -32565=>1000,32566=>1000,32568=>1000,32569=>1000,32570=>1000,32573=>1000,32574=>1000,32575=>1000,32578=>1000,32579=>1000, -32580=>1000,32581=>1000,32583=>1000,32584=>1000,32586=>1000,32587=>1000,32588=>1000,32589=>1000,32590=>1000,32591=>1000, -32592=>1000,32593=>1000,32596=>1000,32597=>1000,32599=>1000,32600=>1000,32602=>1000,32603=>1000,32604=>1000,32605=>1000, -32606=>1000,32607=>1000,32608=>1000,32609=>1000,32610=>1000,32611=>1000,32613=>1000,32614=>1000,32615=>1000,32616=>1000, -32617=>1000,32618=>1000,32619=>1000,32620=>1000,32621=>1000,32622=>1000,32624=>1000,32625=>1000,32626=>1000,32627=>1000, -32628=>1000,32629=>1000,32630=>1000,32631=>1000,32632=>1000,32633=>1000,32634=>1000,32635=>1000,32636=>1000,32637=>1000, -32638=>1000,32639=>1000,32641=>1000,32642=>1000,32643=>1000,32645=>1000,32646=>1000,32647=>1000,32648=>1000,32649=>1000, -32650=>1000,32651=>1000,32652=>1000,32653=>1000,32654=>1000,32657=>1000,32658=>1000,32660=>1000,32661=>1000,32662=>1000, -32666=>1000,32667=>1000,32668=>1000,32669=>1000,32670=>1000,32671=>1000,32672=>1000,32673=>1000,32674=>1000,32675=>1000, -32676=>1000,32677=>1000,32678=>1000,32679=>1000,32680=>1000,32681=>1000,32684=>1000,32685=>1000,32686=>1000,32687=>1000, -32688=>1000,32689=>1000,32690=>1000,32691=>1000,32693=>1000,32694=>1000,32695=>1000,32696=>1000,32697=>1000,32698=>1000, -32699=>1000,32700=>1000,32701=>1000,32702=>1000,32703=>1000,32704=>1000,32705=>1000,32706=>1000,32707=>1000,32709=>1000, -32710=>1000,32711=>1000,32713=>1000,32714=>1000,32715=>1000,32716=>1000,32717=>1000,32718=>1000,32719=>1000,32720=>1000, -32721=>1000,32722=>1000,32724=>1000,32725=>1000,32727=>1000,32728=>1000,32731=>1000,32732=>1000,32734=>1000,32735=>1000, -32736=>1000,32737=>1000,32738=>1000,32739=>1000,32741=>1000,32742=>1000,32744=>1000,32745=>1000,32746=>1000,32747=>1000, -32748=>1000,32749=>1000,32750=>1000,32751=>1000,32752=>1000,32753=>1000,32754=>1000,32755=>1000,32756=>1000,32757=>1000, -32759=>1000,32760=>1000,32761=>1000,32763=>1000,32764=>1000,32765=>1000,32766=>1000,32767=>1000,32768=>1000,32769=>1000, -32771=>1000,32772=>1000,32773=>1000,32774=>1000,32775=>1000,32777=>1000,32779=>1000,32780=>1000,32781=>1000,32782=>1000, -32783=>1000,32784=>1000,32785=>1000,32786=>1000,32788=>1000,32789=>1000,32790=>1000,32791=>1000,32792=>1000,32793=>1000, -32795=>1000,32796=>1000,32798=>1000,32799=>1000,32800=>1000,32801=>1000,32802=>1000,32804=>1000,32805=>1000,32806=>1000, -32807=>1000,32808=>1000,32809=>1000,32810=>1000,32812=>1000,32813=>1000,32816=>1000,32817=>1000,32819=>1000,32820=>1000, -32821=>1000,32822=>1000,32823=>1000,32824=>1000,32825=>1000,32827=>1000,32829=>1000,32830=>1000,32831=>1000,32834=>1000, -32835=>1000,32838=>1000,32839=>1000,32840=>1000,32842=>1000,32843=>1000,32844=>1000,32845=>1000,32847=>1000,32848=>1000, -32849=>1000,32850=>1000,32852=>1000,32854=>1000,32856=>1000,32858=>1000,32860=>1000,32861=>1000,32862=>1000,32863=>1000, -32865=>1000,32866=>1000,32868=>1000,32871=>1000,32872=>1000,32873=>1000,32874=>1000,32876=>1000,32879=>1000,32880=>1000, -32881=>1000,32882=>1000,32883=>1000,32884=>1000,32885=>1000,32886=>1000,32887=>1000,32888=>1000,32889=>1000,32893=>1000, -32894=>1000,32895=>1000,32896=>1000,32898=>1000,32899=>1000,32900=>1000,32901=>1000,32902=>1000,32903=>1000,32905=>1000, -32906=>1000,32907=>1000,32908=>1000,32911=>1000,32912=>1000,32914=>1000,32915=>1000,32917=>1000,32918=>1000,32920=>1000, -32921=>1000,32922=>1000,32923=>1000,32924=>1000,32925=>1000,32927=>1000,32928=>1000,32929=>1000,32930=>1000,32931=>1000, -32932=>1000,32933=>1000,32937=>1000,32938=>1000,32939=>1000,32940=>1000,32941=>1000,32942=>1000,32943=>1000,32945=>1000, -32946=>1000,32948=>1000,32949=>1000,32951=>1000,32952=>1000,32954=>1000,32956=>1000,32957=>1000,32958=>1000,32959=>1000, -32960=>1000,32961=>1000,32962=>1000,32963=>1000,32964=>1000,32965=>1000,32966=>1000,32967=>1000,32968=>1000,32969=>1000, -32970=>1000,32972=>1000,32973=>1000,32974=>1000,32975=>1000,32976=>1000,32977=>1000,32980=>1000,32981=>1000,32982=>1000, -32983=>1000,32984=>1000,32985=>1000,32986=>1000,32987=>1000,32988=>1000,32989=>1000,32990=>1000,32992=>1000,32993=>1000, -32995=>1000,32996=>1000,32997=>1000,32998=>1000,32999=>1000,33000=>1000,33001=>1000,33002=>1000,33003=>1000,33004=>1000, -33005=>1000,33007=>1000,33008=>1000,33009=>1000,33010=>1000,33011=>1000,33012=>1000,33013=>1000,33014=>1000,33016=>1000, -33017=>1000,33018=>1000,33019=>1000,33020=>1000,33021=>1000,33022=>1000,33024=>1000,33025=>1000,33026=>1000,33029=>1000, -33030=>1000,33031=>1000,33032=>1000,33033=>1000,33034=>1000,33037=>1000,33038=>1000,33039=>1000,33040=>1000,33041=>1000, -33042=>1000,33043=>1000,33044=>1000,33045=>1000,33046=>1000,33048=>1000,33049=>1000,33050=>1000,33051=>1000,33053=>1000, -33054=>1000,33055=>1000,33057=>1000,33058=>1000,33059=>1000,33060=>1000,33061=>1000,33063=>1000,33065=>1000,33067=>1000, -33068=>1000,33069=>1000,33071=>1000,33072=>1000,33073=>1000,33074=>1000,33075=>1000,33078=>1000,33080=>1000,33081=>1000, -33082=>1000,33085=>1000,33086=>1000,33091=>1000,33092=>1000,33094=>1000,33095=>1000,33096=>1000,33098=>1000,33099=>1000, -33100=>1000,33101=>1000,33102=>1000,33103=>1000,33104=>1000,33105=>1000,33106=>1000,33107=>1000,33108=>1000,33109=>1000, -33113=>1000,33114=>1000,33115=>1000,33116=>1000,33118=>1000,33119=>1000,33120=>1000,33121=>1000,33122=>1000,33124=>1000, -33125=>1000,33126=>1000,33127=>1000,33129=>1000,33131=>1000,33133=>1000,33134=>1000,33135=>1000,33136=>1000,33137=>1000, -33138=>1000,33139=>1000,33140=>1000,33142=>1000,33143=>1000,33144=>1000,33145=>1000,33146=>1000,33147=>1000,33148=>1000, -33149=>1000,33150=>1000,33151=>1000,33152=>1000,33154=>1000,33155=>1000,33158=>1000,33159=>1000,33160=>1000,33161=>1000, -33162=>1000,33163=>1000,33164=>1000,33165=>1000,33167=>1000,33169=>1000,33171=>1000,33173=>1000,33175=>1000,33176=>1000, -33177=>1000,33178=>1000,33179=>1000,33180=>1000,33181=>1000,33182=>1000,33183=>1000,33184=>1000,33186=>1000,33187=>1000, -33188=>1000,33190=>1000,33191=>1000,33192=>1000,33193=>1000,33194=>1000,33195=>1000,33196=>1000,33198=>1000,33200=>1000, -33201=>1000,33202=>1000,33203=>1000,33204=>1000,33205=>1000,33207=>1000,33208=>1000,33209=>1000,33210=>1000,33211=>1000, -33212=>1000,33213=>1000,33214=>1000,33215=>1000,33216=>1000,33217=>1000,33218=>1000,33219=>1000,33220=>1000,33221=>1000, -33222=>1000,33223=>1000,33224=>1000,33225=>1000,33226=>1000,33228=>1000,33229=>1000,33231=>1000,33232=>1000,33233=>1000, -33234=>1000,33235=>1000,33237=>1000,33239=>1000,33240=>1000,33241=>1000,33242=>1000,33243=>1000,33245=>1000,33246=>1000, -33247=>1000,33248=>1000,33249=>1000,33250=>1000,33251=>1000,33253=>1000,33254=>1000,33255=>1000,33256=>1000,33257=>1000, -33258=>1000,33260=>1000,33261=>1000,33262=>1000,33266=>1000,33267=>1000,33268=>1000,33271=>1000,33272=>1000,33273=>1000, -33274=>1000,33275=>1000,33276=>1000,33278=>1000,33279=>1000,33280=>1000,33281=>1000,33282=>1000,33284=>1000,33285=>1000, -33286=>1000,33287=>1000,33288=>1000,33289=>1000,33290=>1000,33291=>1000,33292=>1000,33293=>1000,33294=>1000,33296=>1000, -33297=>1000,33298=>1000,33300=>1000,33301=>1000,33302=>1000,33303=>1000,33304=>1000,33307=>1000,33308=>1000,33309=>1000, -33310=>1000,33311=>1000,33312=>1000,33313=>1000,33314=>1000,33315=>1000,33317=>1000,33320=>1000,33321=>1000,33322=>1000, -33323=>1000,33324=>1000,33325=>1000,33326=>1000,33327=>1000,33328=>1000,33329=>1000,33330=>1000,33331=>1000,33332=>1000, -33333=>1000,33334=>1000,33335=>1000,33336=>1000,33337=>1000,33338=>1000,33339=>1000,33340=>1000,33341=>1000,33342=>1000, -33343=>1000,33344=>1000,33346=>1000,33348=>1000,33349=>1000,33351=>1000,33353=>1000,33355=>1000,33358=>1000,33359=>1000, -33360=>1000,33361=>1000,33362=>1000,33363=>1000,33365=>1000,33366=>1000,33367=>1000,33368=>1000,33369=>1000,33370=>1000, -33371=>1000,33372=>1000,33373=>1000,33374=>1000,33375=>1000,33377=>1000,33378=>1000,33379=>1000,33380=>1000,33382=>1000, -33384=>1000,33385=>1000,33386=>1000,33387=>1000,33388=>1000,33389=>1000,33390=>1000,33391=>1000,33392=>1000,33393=>1000, -33394=>1000,33395=>1000,33396=>1000,33397=>1000,33398=>1000,33399=>1000,33400=>1000,33401=>1000,33402=>1000,33404=>1000, -33405=>1000,33406=>1000,33407=>1000,33408=>1000,33410=>1000,33411=>1000,33412=>1000,33413=>1000,33416=>1000,33418=>1000, -33419=>1000,33421=>1000,33422=>1000,33423=>1000,33424=>1000,33425=>1000,33426=>1000,33427=>1000,33428=>1000,33431=>1000, -33432=>1000,33433=>1000,33434=>1000,33435=>1000,33436=>1000,33437=>1000,33438=>1000,33439=>1000,33440=>1000,33441=>1000, -33442=>1000,33443=>1000,33444=>1000,33445=>1000,33446=>1000,33447=>1000,33448=>1000,33449=>1000,33450=>1000,33451=>1000, -33452=>1000,33453=>1000,33454=>1000,33455=>1000,33456=>1000,33457=>1000,33459=>1000,33460=>1000,33461=>1000,33462=>1000, -33463=>1000,33464=>1000,33465=>1000,33466=>1000,33467=>1000,33468=>1000,33469=>1000,33470=>1000,33471=>1000,33472=>1000, -33473=>1000,33474=>1000,33475=>1000,33476=>1000,33477=>1000,33479=>1000,33480=>1000,33482=>1000,33483=>1000,33484=>1000, -33485=>1000,33486=>1000,33487=>1000,33489=>1000,33490=>1000,33491=>1000,33492=>1000,33493=>1000,33494=>1000,33495=>1000, -33496=>1000,33497=>1000,33499=>1000,33500=>1000,33502=>1000,33503=>1000,33504=>1000,33505=>1000,33507=>1000,33508=>1000, -33509=>1000,33510=>1000,33511=>1000,33512=>1000,33514=>1000,33515=>1000,33516=>1000,33517=>1000,33519=>1000,33520=>1000, -33521=>1000,33522=>1000,33523=>1000,33524=>1000,33525=>1000,33526=>1000,33527=>1000,33529=>1000,33530=>1000,33531=>1000, -33533=>1000,33534=>1000,33536=>1000,33537=>1000,33538=>1000,33539=>1000,33540=>1000,33541=>1000,33542=>1000,33543=>1000, -33544=>1000,33545=>1000,33548=>1000,33549=>1000,33550=>1000,33551=>1000,33553=>1000,33556=>1000,33557=>1000,33558=>1000, -33559=>1000,33560=>1000,33561=>1000,33562=>1000,33563=>1000,33564=>1000,33566=>1000,33568=>1000,33570=>1000,33571=>1000, -33572=>1000,33573=>1000,33574=>1000,33575=>1000,33576=>1000,33577=>1000,33578=>1000,33579=>1000,33580=>1000,33581=>1000, -33583=>1000,33585=>1000,33586=>1000,33587=>1000,33588=>1000,33589=>1000,33590=>1000,33591=>1000,33592=>1000,33593=>1000, -33594=>1000,33595=>1000,33596=>1000,33599=>1000,33600=>1000,33601=>1000,33602=>1000,33603=>1000,33604=>1000,33605=>1000, -33606=>1000,33607=>1000,33608=>1000,33609=>1000,33610=>1000,33611=>1000,33612=>1000,33613=>1000,33614=>1000,33615=>1000, -33616=>1000,33617=>1000,33618=>1000,33619=>1000,33620=>1000,33622=>1000,33624=>1000,33626=>1000,33627=>1000,33628=>1000, -33630=>1000,33631=>1000,33632=>1000,33633=>1000,33634=>1000,33635=>1000,33636=>1000,33637=>1000,33638=>1000,33639=>1000, -33640=>1000,33641=>1000,33642=>1000,33643=>1000,33644=>1000,33645=>1000,33646=>1000,33647=>1000,33651=>1000,33652=>1000, -33653=>1000,33654=>1000,33655=>1000,33656=>1000,33658=>1000,33659=>1000,33660=>1000,33661=>1000,33662=>1000,33663=>1000, -33665=>1000,33667=>1000,33669=>1000,33670=>1000,33671=>1000,33672=>1000,33673=>1000,33674=>1000,33675=>1000,33676=>1000, -33677=>1000,33678=>1000,33679=>1000,33680=>1000,33682=>1000,33683=>1000,33684=>1000,33685=>1000,33686=>1000,33687=>1000, -33688=>1000,33689=>1000,33690=>1000,33691=>1000,33692=>1000,33693=>1000,33694=>1000,33695=>1000,33696=>1000,33698=>1000, -33699=>1000,33700=>1000,33701=>1000,33702=>1000,33703=>1000,33704=>1000,33705=>1000,33706=>1000,33707=>1000,33710=>1000, -33711=>1000,33712=>1000,33713=>1000,33714=>1000,33715=>1000,33716=>1000,33717=>1000,33718=>1000,33719=>1000,33720=>1000, -33721=>1000,33722=>1000,33724=>1000,33725=>1000,33727=>1000,33728=>1000,33729=>1000,33730=>1000,33731=>1000,33732=>1000, -33733=>1000,33734=>1000,33735=>1000,33736=>1000,33737=>1000,33738=>1000,33739=>1000,33740=>1000,33742=>1000,33743=>1000, -33745=>1000,33747=>1000,33748=>1000,33749=>1000,33750=>1000,33751=>1000,33752=>1000,33753=>1000,33755=>1000,33756=>1000, -33757=>1000,33758=>1000,33759=>1000,33760=>1000,33761=>1000,33762=>1000,33763=>1000,33764=>1000,33765=>1000,33767=>1000, -33768=>1000,33769=>1000,33770=>1000,33771=>1000,33772=>1000,33774=>1000,33775=>1000,33776=>1000,33777=>1000,33778=>1000, -33779=>1000,33780=>1000,33781=>1000,33782=>1000,33783=>1000,33784=>1000,33785=>1000,33786=>1000,33787=>1000,33788=>1000, -33789=>1000,33790=>1000,33791=>1000,33793=>1000,33795=>1000,33796=>1000,33798=>1000,33799=>1000,33801=>1000,33802=>1000, -33803=>1000,33804=>1000,33805=>1000,33806=>1000,33807=>1000,33808=>1000,33809=>1000,33810=>1000,33811=>1000,33816=>1000, -33819=>1000,33820=>1000,33821=>1000,33824=>1000,33826=>1000,33827=>1000,33828=>1000,33829=>1000,33830=>1000,33831=>1000, -33832=>1000,33833=>1000,33834=>1000,33835=>1000,33836=>1000,33837=>1000,33839=>1000,33840=>1000,33841=>1000,33842=>1000, -33843=>1000,33844=>1000,33845=>1000,33846=>1000,33847=>1000,33848=>1000,33849=>1000,33850=>1000,33851=>1000,33852=>1000, -33853=>1000,33855=>1000,33856=>1000,33858=>1000,33859=>1000,33860=>1000,33861=>1000,33862=>1000,33863=>1000,33864=>1000, -33865=>1000,33867=>1000,33868=>1000,33869=>1000,33870=>1000,33872=>1000,33873=>1000,33874=>1000,33876=>1000,33878=>1000, -33879=>1000,33881=>1000,33882=>1000,33883=>1000,33884=>1000,33885=>1000,33886=>1000,33887=>1000,33888=>1000,33889=>1000, -33890=>1000,33891=>1000,33893=>1000,33894=>1000,33895=>1000,33896=>1000,33897=>1000,33899=>1000,33900=>1000,33901=>1000, -33902=>1000,33903=>1000,33904=>1000,33905=>1000,33907=>1000,33908=>1000,33909=>1000,33910=>1000,33911=>1000,33912=>1000, -33913=>1000,33914=>1000,33917=>1000,33918=>1000,33922=>1000,33924=>1000,33926=>1000,33927=>1000,33928=>1000,33929=>1000, -33931=>1000,33932=>1000,33933=>1000,33934=>1000,33935=>1000,33936=>1000,33937=>1000,33940=>1000,33943=>1000,33944=>1000, -33945=>1000,33946=>1000,33947=>1000,33948=>1000,33949=>1000,33950=>1000,33951=>1000,33952=>1000,33953=>1000,33954=>1000, -33956=>1000,33959=>1000,33960=>1000,33961=>1000,33962=>1000,33963=>1000,33964=>1000,33965=>1000,33966=>1000,33967=>1000, -33968=>1000,33969=>1000,33970=>1000,33972=>1000,33974=>1000,33976=>1000,33977=>1000,33978=>1000,33979=>1000,33980=>1000, -33981=>1000,33983=>1000,33984=>1000,33985=>1000,33986=>1000,33988=>1000,33989=>1000,33990=>1000,33991=>1000,33993=>1000, -33994=>1000,33995=>1000,33996=>1000,33997=>1000,33998=>1000,33999=>1000,34000=>1000,34001=>1000,34002=>1000,34003=>1000, -34004=>1000,34006=>1000,34007=>1000,34009=>1000,34010=>1000,34011=>1000,34012=>1000,34013=>1000,34015=>1000,34016=>1000, -34019=>1000,34021=>1000,34022=>1000,34023=>1000,34024=>1000,34025=>1000,34026=>1000,34027=>1000,34028=>1000,34030=>1000, -34031=>1000,34032=>1000,34033=>1000,34034=>1000,34035=>1000,34036=>1000,34038=>1000,34039=>1000,34041=>1000,34042=>1000, -34043=>1000,34044=>1000,34045=>1000,34046=>1000,34047=>1000,34048=>1000,34050=>1000,34054=>1000,34055=>1000,34056=>1000, -34057=>1000,34058=>1000,34059=>1000,34060=>1000,34061=>1000,34062=>1000,34063=>1000,34065=>1000,34066=>1000,34067=>1000, -34068=>1000,34069=>1000,34070=>1000,34071=>1000,34072=>1000,34073=>1000,34074=>1000,34076=>1000,34077=>1000,34078=>1000, -34079=>1000,34080=>1000,34081=>1000,34083=>1000,34084=>1000,34085=>1000,34086=>1000,34087=>1000,34088=>1000,34089=>1000, -34090=>1000,34091=>1000,34092=>1000,34093=>1000,34094=>1000,34095=>1000,34096=>1000,34097=>1000,34101=>1000,34103=>1000, -34104=>1000,34105=>1000,34106=>1000,34107=>1000,34108=>1000,34109=>1000,34110=>1000,34111=>1000,34112=>1000,34113=>1000, -34115=>1000,34116=>1000,34117=>1000,34118=>1000,34119=>1000,34120=>1000,34121=>1000,34122=>1000,34123=>1000,34125=>1000, -34126=>1000,34129=>1000,34131=>1000,34132=>1000,34133=>1000,34134=>1000,34135=>1000,34136=>1000,34137=>1000,34138=>1000, -34139=>1000,34141=>1000,34142=>1000,34144=>1000,34145=>1000,34146=>1000,34147=>1000,34148=>1000,34149=>1000,34150=>1000, -34151=>1000,34152=>1000,34153=>1000,34154=>1000,34155=>1000,34156=>1000,34157=>1000,34158=>1000,34161=>1000,34162=>1000, -34164=>1000,34165=>1000,34166=>1000,34167=>1000,34168=>1000,34169=>1000,34170=>1000,34171=>1000,34172=>1000,34174=>1000, -34176=>1000,34177=>1000,34178=>1000,34179=>1000,34180=>1000,34181=>1000,34182=>1000,34183=>1000,34184=>1000,34185=>1000, -34186=>1000,34187=>1000,34188=>1000,34189=>1000,34190=>1000,34191=>1000,34192=>1000,34193=>1000,34196=>1000,34197=>1000, -34198=>1000,34199=>1000,34200=>1000,34201=>1000,34202=>1000,34203=>1000,34204=>1000,34205=>1000,34206=>1000,34207=>1000, -34208=>1000,34209=>1000,34210=>1000,34211=>1000,34212=>1000,34214=>1000,34215=>1000,34216=>1000,34217=>1000,34218=>1000, -34219=>1000,34220=>1000,34222=>1000,34223=>1000,34224=>1000,34225=>1000,34227=>1000,34228=>1000,34229=>1000,34230=>1000, -34231=>1000,34232=>1000,34233=>1000,34234=>1000,34237=>1000,34238=>1000,34239=>1000,34240=>1000,34241=>1000,34242=>1000, -34243=>1000,34244=>1000,34245=>1000,34246=>1000,34247=>1000,34248=>1000,34249=>1000,34251=>1000,34253=>1000,34254=>1000, -34255=>1000,34256=>1000,34257=>1000,34258=>1000,34259=>1000,34261=>1000,34263=>1000,34264=>1000,34265=>1000,34266=>1000, -34268=>1000,34269=>1000,34270=>1000,34271=>1000,34273=>1000,34274=>1000,34275=>1000,34276=>1000,34277=>1000,34278=>1000, -34280=>1000,34281=>1000,34282=>1000,34283=>1000,34284=>1000,34285=>1000,34287=>1000,34288=>1000,34289=>1000,34290=>1000, -34294=>1000,34295=>1000,34296=>1000,34297=>1000,34298=>1000,34299=>1000,34301=>1000,34302=>1000,34303=>1000,34304=>1000, -34305=>1000,34306=>1000,34308=>1000,34309=>1000,34310=>1000,34311=>1000,34313=>1000,34314=>1000,34315=>1000,34316=>1000, -34321=>1000,34323=>1000,34326=>1000,34327=>1000,34328=>1000,34329=>1000,34330=>1000,34331=>1000,34332=>1000,34334=>1000, -34335=>1000,34336=>1000,34337=>1000,34338=>1000,34339=>1000,34340=>1000,34341=>1000,34342=>1000,34343=>1000,34345=>1000, -34346=>1000,34348=>1000,34349=>1000,34350=>1000,34351=>1000,34352=>1000,34353=>1000,34354=>1000,34355=>1000,34356=>1000, -34357=>1000,34358=>1000,34360=>1000,34361=>1000,34362=>1000,34363=>1000,34364=>1000,34366=>1000,34367=>1000,34368=>1000, -34371=>1000,34374=>1000,34375=>1000,34376=>1000,34379=>1000,34380=>1000,34381=>1000,34382=>1000,34383=>1000,34384=>1000, -34385=>1000,34386=>1000,34387=>1000,34388=>1000,34389=>1000,34390=>1000,34393=>1000,34394=>1000,34395=>1000,34396=>1000, -34398=>1000,34399=>1000,34401=>1000,34402=>1000,34403=>1000,34404=>1000,34405=>1000,34407=>1000,34408=>1000,34409=>1000, -34410=>1000,34411=>1000,34412=>1000,34413=>1000,34414=>1000,34415=>1000,34416=>1000,34417=>1000,34419=>1000,34420=>1000, -34423=>1000,34425=>1000,34426=>1000,34427=>1000,34428=>1000,34429=>1000,34430=>1000,34431=>1000,34432=>1000,34433=>1000, -34434=>1000,34437=>1000,34438=>1000,34439=>1000,34442=>1000,34443=>1000,34444=>1000,34445=>1000,34446=>1000,34448=>1000, -34449=>1000,34451=>1000,34452=>1000,34453=>1000,34454=>1000,34455=>1000,34456=>1000,34457=>1000,34458=>1000,34460=>1000, -34461=>1000,34462=>1000,34465=>1000,34466=>1000,34467=>1000,34468=>1000,34469=>1000,34471=>1000,34472=>1000,34473=>1000, -34474=>1000,34475=>1000,34476=>1000,34479=>1000,34480=>1000,34481=>1000,34483=>1000,34484=>1000,34485=>1000,34486=>1000, -34487=>1000,34488=>1000,34489=>1000,34490=>1000,34491=>1000,34492=>1000,34493=>1000,34494=>1000,34495=>1000,34496=>1000, -34497=>1000,34498=>1000,34499=>1000,34500=>1000,34501=>1000,34502=>1000,34503=>1000,34504=>1000,34505=>1000,34506=>1000, -34507=>1000,34508=>1000,34509=>1000,34510=>1000,34511=>1000,34512=>1000,34513=>1000,34515=>1000,34516=>1000,34518=>1000, -34519=>1000,34520=>1000,34521=>1000,34522=>1000,34523=>1000,34524=>1000,34525=>1000,34526=>1000,34527=>1000,34530=>1000, -34531=>1000,34532=>1000,34534=>1000,34536=>1000,34537=>1000,34538=>1000,34539=>1000,34540=>1000,34541=>1000,34542=>1000, -34543=>1000,34544=>1000,34545=>1000,34546=>1000,34547=>1000,34548=>1000,34549=>1000,34550=>1000,34551=>1000,34552=>1000, -34553=>1000,34554=>1000,34555=>1000,34558=>1000,34560=>1000,34561=>1000,34562=>1000,34563=>1000,34564=>1000,34565=>1000, -34566=>1000,34567=>1000,34568=>1000,34569=>1000,34570=>1000,34571=>1000,34572=>1000,34573=>1000,34574=>1000,34577=>1000, -34578=>1000,34579=>1000,34581=>1000,34583=>1000,34584=>1000,34585=>1000,34586=>1000,34587=>1000,34588=>1000,34590=>1000, -34592=>1000,34593=>1000,34594=>1000,34595=>1000,34596=>1000,34597=>1000,34598=>1000,34599=>1000,34600=>1000,34601=>1000, -34602=>1000,34604=>1000,34605=>1000,34606=>1000,34608=>1000,34609=>1000,34610=>1000,34611=>1000,34612=>1000,34613=>1000, -34615=>1000,34616=>1000,34618=>1000,34619=>1000,34620=>1000,34622=>1000,34623=>1000,34624=>1000,34625=>1000,34626=>1000, -34627=>1000,34630=>1000,34631=>1000,34632=>1000,34633=>1000,34635=>1000,34636=>1000,34637=>1000,34638=>1000,34639=>1000, -34640=>1000,34641=>1000,34642=>1000,34643=>1000,34644=>1000,34645=>1000,34646=>1000,34647=>1000,34648=>1000,34649=>1000, -34650=>1000,34651=>1000,34652=>1000,34653=>1000,34654=>1000,34655=>1000,34656=>1000,34657=>1000,34658=>1000,34659=>1000, -34660=>1000,34661=>1000,34662=>1000,34663=>1000,34664=>1000,34665=>1000,34666=>1000,34667=>1000,34668=>1000,34669=>1000, -34670=>1000,34671=>1000,34672=>1000,34675=>1000,34676=>1000,34677=>1000,34678=>1000,34679=>1000,34680=>1000,34681=>1000, -34682=>1000,34683=>1000,34684=>1000,34685=>1000,34686=>1000,34687=>1000,34689=>1000,34690=>1000,34691=>1000,34692=>1000, -34693=>1000,34695=>1000,34696=>1000,34697=>1000,34699=>1000,34701=>1000,34703=>1000,34704=>1000,34705=>1000,34706=>1000, -34707=>1000,34708=>1000,34710=>1000,34711=>1000,34712=>1000,34714=>1000,34715=>1000,34716=>1000,34717=>1000,34718=>1000, -34719=>1000,34722=>1000,34723=>1000,34724=>1000,34728=>1000,34730=>1000,34731=>1000,34732=>1000,34733=>1000,34734=>1000, -34735=>1000,34736=>1000,34738=>1000,34739=>1000,34740=>1000,34741=>1000,34742=>1000,34743=>1000,34744=>1000,34745=>1000, -34746=>1000,34747=>1000,34748=>1000,34749=>1000,34750=>1000,34751=>1000,34752=>1000,34754=>1000,34755=>1000,34756=>1000, -34757=>1000,34758=>1000,34759=>1000,34760=>1000,34761=>1000,34762=>1000,34763=>1000,34764=>1000,34768=>1000,34769=>1000, -34770=>1000,34771=>1000,34772=>1000,34775=>1000,34776=>1000,34777=>1000,34779=>1000,34780=>1000,34781=>1000,34782=>1000, -34783=>1000,34784=>1000,34785=>1000,34786=>1000,34787=>1000,34788=>1000,34789=>1000,34790=>1000,34791=>1000,34792=>1000, -34794=>1000,34795=>1000,34796=>1000,34797=>1000,34798=>1000,34799=>1000,34802=>1000,34803=>1000,34804=>1000,34806=>1000, -34807=>1000,34809=>1000,34810=>1000,34811=>1000,34812=>1000,34814=>1000,34815=>1000,34816=>1000,34817=>1000,34818=>1000, -34819=>1000,34821=>1000,34822=>1000,34823=>1000,34824=>1000,34825=>1000,34826=>1000,34827=>1000,34828=>1000,34829=>1000, -34830=>1000,34831=>1000,34832=>1000,34833=>1000,34835=>1000,34836=>1000,34837=>1000,34838=>1000,34839=>1000,34841=>1000, -34843=>1000,34844=>1000,34845=>1000,34847=>1000,34848=>1000,34849=>1000,34850=>1000,34851=>1000,34852=>1000,34853=>1000, -34854=>1000,34855=>1000,34856=>1000,34857=>1000,34858=>1000,34859=>1000,34860=>1000,34862=>1000,34863=>1000,34864=>1000, -34865=>1000,34866=>1000,34867=>1000,34869=>1000,34870=>1000,34871=>1000,34872=>1000,34873=>1000,34875=>1000,34876=>1000, -34877=>1000,34878=>1000,34879=>1000,34880=>1000,34881=>1000,34882=>1000,34883=>1000,34884=>1000,34885=>1000,34886=>1000, -34888=>1000,34890=>1000,34891=>1000,34892=>1000,34893=>1000,34894=>1000,34898=>1000,34899=>1000,34900=>1000,34901=>1000, -34902=>1000,34903=>1000,34905=>1000,34906=>1000,34907=>1000,34909=>1000,34910=>1000,34913=>1000,34914=>1000,34915=>1000, -34916=>1000,34917=>1000,34919=>1000,34920=>1000,34921=>1000,34922=>1000,34923=>1000,34924=>1000,34925=>1000,34926=>1000, -34927=>1000,34928=>1000,34929=>1000,34930=>1000,34932=>1000,34933=>1000,34934=>1000,34935=>1000,34937=>1000,34940=>1000, -34941=>1000,34942=>1000,34943=>1000,34944=>1000,34945=>1000,34946=>1000,34947=>1000,34948=>1000,34949=>1000,34952=>1000, -34953=>1000,34955=>1000,34956=>1000,34957=>1000,34958=>1000,34961=>1000,34962=>1000,34963=>1000,34965=>1000,34966=>1000, -34967=>1000,34968=>1000,34969=>1000,34970=>1000,34971=>1000,34972=>1000,34974=>1000,34975=>1000,34977=>1000,34978=>1000, -34980=>1000,34983=>1000,34984=>1000,34986=>1000,34987=>1000,34988=>1000,34989=>1000,34990=>1000,34992=>1000,34993=>1000, -34994=>1000,34996=>1000,34997=>1000,34998=>1000,34999=>1000,35000=>1000,35001=>1000,35002=>1000,35004=>1000,35005=>1000, -35006=>1000,35007=>1000,35008=>1000,35009=>1000,35010=>1000,35011=>1000,35012=>1000,35013=>1000,35014=>1000,35017=>1000, -35018=>1000,35019=>1000,35020=>1000,35021=>1000,35022=>1000,35023=>1000,35024=>1000,35026=>1000,35028=>1000,35029=>1000, -35030=>1000,35031=>1000,35032=>1000,35033=>1000,35034=>1000,35035=>1000,35036=>1000,35037=>1000,35038=>1000,35039=>1000, -35041=>1000,35042=>1000,35043=>1000,35044=>1000,35045=>1000,35047=>1000,35048=>1000,35051=>1000,35052=>1000,35054=>1000, -35055=>1000,35056=>1000,35057=>1000,35058=>1000,35059=>1000,35060=>1000,35061=>1000,35062=>1000,35063=>1000,35064=>1000, -35065=>1000,35066=>1000,35067=>1000,35068=>1000,35069=>1000,35070=>1000,35073=>1000,35074=>1000,35076=>1000,35077=>1000, -35078=>1000,35079=>1000,35081=>1000,35082=>1000,35083=>1000,35084=>1000,35086=>1000,35088=>1000,35089=>1000,35090=>1000, -35091=>1000,35092=>1000,35093=>1000,35094=>1000,35095=>1000,35096=>1000,35097=>1000,35098=>1000,35099=>1000,35100=>1000, -35101=>1000,35102=>1000,35103=>1000,35105=>1000,35106=>1000,35107=>1000,35109=>1000,35110=>1000,35111=>1000,35113=>1000, -35114=>1000,35115=>1000,35116=>1000,35117=>1000,35118=>1000,35119=>1000,35120=>1000,35121=>1000,35122=>1000,35123=>1000, -35124=>1000,35125=>1000,35126=>1000,35127=>1000,35128=>1000,35131=>1000,35132=>1000,35133=>1000,35134=>1000,35137=>1000, -35138=>1000,35139=>1000,35140=>1000,35142=>1000,35145=>1000,35147=>1000,35148=>1000,35149=>1000,35151=>1000,35152=>1000, -35153=>1000,35154=>1000,35155=>1000,35158=>1000,35159=>1000,35160=>1000,35161=>1000,35162=>1000,35163=>1000,35164=>1000, -35165=>1000,35166=>1000,35167=>1000,35168=>1000,35169=>1000,35170=>1000,35171=>1000,35172=>1000,35174=>1000,35177=>1000, -35178=>1000,35179=>1000,35180=>1000,35181=>1000,35182=>1000,35183=>1000,35185=>1000,35186=>1000,35187=>1000,35188=>1000, -35190=>1000,35191=>1000,35193=>1000,35194=>1000,35195=>1000,35196=>1000,35198=>1000,35199=>1000,35201=>1000,35202=>1000, -35203=>1000,35205=>1000,35206=>1000,35207=>1000,35208=>1000,35210=>1000,35211=>1000,35215=>1000,35219=>1000,35221=>1000, -35222=>1000,35223=>1000,35224=>1000,35226=>1000,35227=>1000,35228=>1000,35229=>1000,35230=>1000,35231=>1000,35233=>1000, -35234=>1000,35235=>1000,35236=>1000,35238=>1000,35239=>1000,35241=>1000,35242=>1000,35244=>1000,35245=>1000,35246=>1000, -35247=>1000,35250=>1000,35251=>1000,35254=>1000,35255=>1000,35257=>1000,35258=>1000,35261=>1000,35262=>1000,35263=>1000, -35264=>1000,35265=>1000,35266=>1000,35268=>1000,35269=>1000,35270=>1000,35271=>1000,35272=>1000,35273=>1000,35274=>1000, -35275=>1000,35276=>1000,35278=>1000,35279=>1000,35280=>1000,35281=>1000,35282=>1000,35283=>1000,35284=>1000,35285=>1000, -35286=>1000,35289=>1000,35290=>1000,35291=>1000,35292=>1000,35293=>1000,35294=>1000,35295=>1000,35296=>1000,35297=>1000, -35298=>1000,35299=>1000,35300=>1000,35301=>1000,35302=>1000,35303=>1000,35304=>1000,35305=>1000,35307=>1000,35308=>1000, -35309=>1000,35311=>1000,35312=>1000,35313=>1000,35314=>1000,35315=>1000,35316=>1000,35318=>1000,35319=>1000,35320=>1000, -35322=>1000,35323=>1000,35324=>1000,35326=>1000,35327=>1000,35328=>1000,35330=>1000,35331=>1000,35332=>1000,35335=>1000, -35336=>1000,35338=>1000,35340=>1000,35342=>1000,35343=>1000,35344=>1000,35345=>1000,35346=>1000,35347=>1000,35349=>1000, -35350=>1000,35351=>1000,35352=>1000,35355=>1000,35357=>1000,35358=>1000,35359=>1000,35362=>1000,35363=>1000,35365=>1000, -35367=>1000,35370=>1000,35372=>1000,35373=>1000,35376=>1000,35377=>1000,35379=>1000,35380=>1000,35382=>1000,35383=>1000, -35385=>1000,35386=>1000,35387=>1000,35388=>1000,35390=>1000,35391=>1000,35392=>1000,35393=>1000,35396=>1000,35397=>1000, -35398=>1000,35400=>1000,35402=>1000,35404=>1000,35405=>1000,35406=>1000,35407=>1000,35408=>1000,35409=>1000,35410=>1000, -35412=>1000,35413=>1000,35414=>1000,35415=>1000,35416=>1000,35417=>1000,35419=>1000,35422=>1000,35424=>1000,35425=>1000, -35426=>1000,35427=>1000,35430=>1000,35432=>1000,35433=>1000,35435=>1000,35436=>1000,35437=>1000,35438=>1000,35440=>1000, -35441=>1000,35442=>1000,35443=>1000,35444=>1000,35445=>1000,35446=>1000,35447=>1000,35449=>1000,35450=>1000,35451=>1000, -35452=>1000,35455=>1000,35457=>1000,35458=>1000,35459=>1000,35460=>1000,35461=>1000,35462=>1000,35463=>1000,35465=>1000, -35466=>1000,35467=>1000,35468=>1000,35469=>1000,35471=>1000,35473=>1000,35474=>1000,35475=>1000,35477=>1000,35478=>1000, -35480=>1000,35481=>1000,35482=>1000,35486=>1000,35488=>1000,35489=>1000,35491=>1000,35492=>1000,35493=>1000,35494=>1000, -35495=>1000,35496=>1000,35498=>1000,35499=>1000,35500=>1000,35501=>1000,35504=>1000,35506=>1000,35510=>1000,35512=>1000, -35513=>1000,35514=>1000,35515=>1000,35516=>1000,35517=>1000,35518=>1000,35519=>1000,35520=>1000,35522=>1000,35523=>1000, -35524=>1000,35525=>1000,35526=>1000,35527=>1000,35528=>1000,35529=>1000,35531=>1000,35532=>1000,35533=>1000,35535=>1000, -35537=>1000,35538=>1000,35539=>1000,35540=>1000,35541=>1000,35542=>1000,35543=>1000,35544=>1000,35545=>1000,35546=>1000, -35547=>1000,35548=>1000,35549=>1000,35550=>1000,35551=>1000,35552=>1000,35553=>1000,35554=>1000,35556=>1000,35558=>1000, -35559=>1000,35560=>1000,35562=>1000,35563=>1000,35565=>1000,35566=>1000,35567=>1000,35568=>1000,35569=>1000,35570=>1000, -35571=>1000,35572=>1000,35573=>1000,35574=>1000,35575=>1000,35576=>1000,35578=>1000,35579=>1000,35580=>1000,35582=>1000, -35583=>1000,35584=>1000,35585=>1000,35586=>1000,35588=>1000,35589=>1000,35590=>1000,35591=>1000,35592=>1000,35594=>1000, -35595=>1000,35596=>1000,35597=>1000,35598=>1000,35599=>1000,35600=>1000,35601=>1000,35602=>1000,35603=>1000,35604=>1000, -35605=>1000,35606=>1000,35607=>1000,35608=>1000,35609=>1000,35610=>1000,35611=>1000,35612=>1000,35613=>1000,35614=>1000, -35616=>1000,35617=>1000,35618=>1000,35619=>1000,35620=>1000,35621=>1000,35622=>1000,35623=>1000,35624=>1000,35626=>1000, -35627=>1000,35628=>1000,35630=>1000,35631=>1000,35632=>1000,35633=>1000,35635=>1000,35637=>1000,35638=>1000,35639=>1000, -35641=>1000,35642=>1000,35643=>1000,35644=>1000,35645=>1000,35646=>1000,35648=>1000,35649=>1000,35650=>1000,35653=>1000, -35654=>1000,35655=>1000,35656=>1000,35657=>1000,35658=>1000,35659=>1000,35660=>1000,35662=>1000,35663=>1000,35664=>1000, -35665=>1000,35666=>1000,35667=>1000,35668=>1000,35669=>1000,35670=>1000,35671=>1000,35672=>1000,35673=>1000,35674=>1000, -35675=>1000,35676=>1000,35677=>1000,35679=>1000,35680=>1000,35683=>1000,35685=>1000,35686=>1000,35687=>1000,35688=>1000, -35690=>1000,35691=>1000,35692=>1000,35693=>1000,35695=>1000,35696=>1000,35697=>1000,35698=>1000,35700=>1000,35703=>1000, -35704=>1000,35705=>1000,35706=>1000,35707=>1000,35709=>1000,35710=>1000,35711=>1000,35712=>1000,35714=>1000,35715=>1000, -35716=>1000,35717=>1000,35718=>1000,35720=>1000,35722=>1000,35723=>1000,35724=>1000,35726=>1000,35728=>1000,35730=>1000, -35731=>1000,35732=>1000,35733=>1000,35734=>1000,35736=>1000,35737=>1000,35738=>1000,35740=>1000,35742=>1000,35743=>1000, -35744=>1000,35745=>1000,35746=>1000,35747=>1000,35748=>1000,35749=>1000,35750=>1000,35751=>1000,35752=>1000,35753=>1000, -35754=>1000,35755=>1000,35757=>1000,35758=>1000,35759=>1000,35760=>1000,35762=>1000,35763=>1000,35764=>1000,35765=>1000, -35766=>1000,35767=>1000,35768=>1000,35769=>1000,35770=>1000,35772=>1000,35773=>1000,35774=>1000,35775=>1000,35776=>1000, -35777=>1000,35778=>1000,35779=>1000,35780=>1000,35781=>1000,35782=>1000,35784=>1000,35785=>1000,35786=>1000,35787=>1000, -35788=>1000,35789=>1000,35790=>1000,35791=>1000,35793=>1000,35794=>1000,35795=>1000,35796=>1000,35797=>1000,35798=>1000, -35799=>1000,35800=>1000,35801=>1000,35802=>1000,35803=>1000,35804=>1000,35805=>1000,35806=>1000,35807=>1000,35808=>1000, -35809=>1000,35810=>1000,35811=>1000,35812=>1000,35813=>1000,35814=>1000,35815=>1000,35816=>1000,35817=>1000,35819=>1000, -35820=>1000,35821=>1000,35822=>1000,35823=>1000,35824=>1000,35825=>1000,35826=>1000,35827=>1000,35828=>1000,35829=>1000, -35830=>1000,35831=>1000,35832=>1000,35833=>1000,35834=>1000,35835=>1000,35836=>1000,35837=>1000,35838=>1000,35839=>1000, -35840=>1000,35841=>1000,35842=>1000,35843=>1000,35844=>1000,35845=>1000,35846=>1000,35847=>1000,35848=>1000,35850=>1000, -35851=>1000,35852=>1000,35853=>1000,35854=>1000,35855=>1000,35856=>1000,35857=>1000,35858=>1000,35859=>1000,35860=>1000, -35861=>1000,35862=>1000,35863=>1000,35864=>1000,35865=>1000,35866=>1000,35867=>1000,35868=>1000,35869=>1000,35871=>1000, -35872=>1000,35873=>1000,35874=>1000,35875=>1000,35876=>1000,35877=>1000,35878=>1000,35879=>1000,35880=>1000,35881=>1000, -35882=>1000,35883=>1000,35884=>1000,35885=>1000,35886=>1000,35887=>1000,35888=>1000,35889=>1000,35890=>1000,35891=>1000, -35892=>1000,35893=>1000,35894=>1000,35895=>1000,35897=>1000,35898=>1000,35899=>1000,35900=>1000,35901=>1000,35902=>1000, -35903=>1000,35905=>1000,35906=>1000,35907=>1000,35909=>1000,35910=>1000,35911=>1000,35912=>1000,35913=>1000,35914=>1000, -35915=>1000,35916=>1000,35917=>1000,35918=>1000,35919=>1000,35920=>1000,35924=>1000,35925=>1000,35926=>1000,35927=>1000, -35930=>1000,35932=>1000,35933=>1000,35935=>1000,35937=>1000,35938=>1000,35940=>1000,35941=>1000,35942=>1000,35944=>1000, -35945=>1000,35946=>1000,35947=>1000,35948=>1000,35949=>1000,35951=>1000,35952=>1000,35953=>1000,35954=>1000,35955=>1000, -35957=>1000,35958=>1000,35959=>1000,35960=>1000,35961=>1000,35962=>1000,35963=>1000,35964=>1000,35965=>1000,35968=>1000, -35969=>1000,35970=>1000,35972=>1000,35973=>1000,35974=>1000,35977=>1000,35978=>1000,35980=>1000,35981=>1000,35982=>1000, -35983=>1000,35984=>1000,35985=>1000,35986=>1000,35987=>1000,35988=>1000,35989=>1000,35991=>1000,35992=>1000,35993=>1000, -35994=>1000,35996=>1000,35997=>1000,35998=>1000,36000=>1000,36001=>1000,36002=>1000,36003=>1000,36004=>1000,36005=>1000, -36007=>1000,36008=>1000,36009=>1000,36010=>1000,36011=>1000,36012=>1000,36013=>1000,36014=>1000,36015=>1000,36016=>1000, -36018=>1000,36019=>1000,36020=>1000,36021=>1000,36022=>1000,36023=>1000,36024=>1000,36025=>1000,36026=>1000,36027=>1000, -36028=>1000,36029=>1000,36030=>1000,36031=>1000,36032=>1000,36033=>1000,36034=>1000,36035=>1000,36036=>1000,36037=>1000, -36039=>1000,36040=>1000,36042=>1000,36044=>1000,36045=>1000,36046=>1000,36047=>1000,36049=>1000,36050=>1000,36051=>1000, -36053=>1000,36055=>1000,36057=>1000,36058=>1000,36059=>1000,36060=>1000,36061=>1000,36062=>1000,36063=>1000,36064=>1000, -36065=>1000,36066=>1000,36067=>1000,36068=>1000,36069=>1000,36070=>1000,36071=>1000,36072=>1000,36074=>1000,36076=>1000, -36077=>1000,36078=>1000,36080=>1000,36081=>1000,36083=>1000,36084=>1000,36085=>1000,36088=>1000,36089=>1000,36090=>1000, -36091=>1000,36092=>1000,36093=>1000,36094=>1000,36096=>1000,36098=>1000,36100=>1000,36101=>1000,36102=>1000,36103=>1000, -36104=>1000,36105=>1000,36106=>1000,36107=>1000,36109=>1000,36111=>1000,36112=>1000,36114=>1000,36115=>1000,36116=>1000, -36117=>1000,36118=>1000,36119=>1000,36121=>1000,36123=>1000,36125=>1000,36126=>1000,36127=>1000,36129=>1000,36130=>1000, -36131=>1000,36132=>1000,36133=>1000,36134=>1000,36135=>1000,36136=>1000,36137=>1000,36138=>1000,36139=>1000,36140=>1000, -36141=>1000,36142=>1000,36143=>1000,36144=>1000,36145=>1000,36146=>1000,36147=>1000,36148=>1000,36149=>1000,36150=>1000, -36151=>1000,36152=>1000,36153=>1000,36154=>1000,36155=>1000,36156=>1000,36157=>1000,36158=>1000,36159=>1000,36160=>1000, -36161=>1000,36162=>1000,36163=>1000,36164=>1000,36165=>1000,36166=>1000,36167=>1000,36168=>1000,36169=>1000,36170=>1000, -36171=>1000,36172=>1000,36173=>1000,36174=>1000,36175=>1000,36176=>1000,36179=>1000,36180=>1000,36181=>1000,36182=>1000, -36184=>1000,36185=>1000,36186=>1000,36187=>1000,36188=>1000,36189=>1000,36190=>1000,36192=>1000,36193=>1000,36194=>1000, -36195=>1000,36196=>1000,36198=>1000,36199=>1000,36200=>1000,36201=>1000,36203=>1000,36204=>1000,36205=>1000,36206=>1000, -36207=>1000,36208=>1000,36209=>1000,36210=>1000,36211=>1000,36212=>1000,36213=>1000,36214=>1000,36215=>1000,36216=>1000, -36217=>1000,36219=>1000,36221=>1000,36224=>1000,36225=>1000,36228=>1000,36229=>1000,36233=>1000,36234=>1000,36235=>1000, -36236=>1000,36237=>1000,36238=>1000,36239=>1000,36240=>1000,36241=>1000,36242=>1000,36243=>1000,36244=>1000,36245=>1000, -36246=>1000,36249=>1000,36251=>1000,36252=>1000,36255=>1000,36256=>1000,36257=>1000,36259=>1000,36261=>1000,36263=>1000, -36264=>1000,36266=>1000,36267=>1000,36268=>1000,36269=>1000,36270=>1000,36271=>1000,36273=>1000,36274=>1000,36275=>1000, -36276=>1000,36277=>1000,36278=>1000,36279=>1000,36280=>1000,36281=>1000,36282=>1000,36284=>1000,36286=>1000,36287=>1000, -36289=>1000,36290=>1000,36291=>1000,36292=>1000,36293=>1000,36294=>1000,36295=>1000,36296=>1000,36299=>1000,36300=>1000, -36301=>1000,36302=>1000,36303=>1000,36304=>1000,36305=>1000,36307=>1000,36309=>1000,36310=>1000,36311=>1000,36312=>1000, -36313=>1000,36314=>1000,36315=>1000,36316=>1000,36317=>1000,36318=>1000,36319=>1000,36320=>1000,36321=>1000,36322=>1000, -36323=>1000,36324=>1000,36326=>1000,36327=>1000,36328=>1000,36329=>1000,36330=>1000,36331=>1000,36332=>1000,36334=>1000, -36335=>1000,36336=>1000,36337=>1000,36338=>1000,36339=>1000,36340=>1000,36341=>1000,36343=>1000,36344=>1000,36345=>1000, -36346=>1000,36347=>1000,36348=>1000,36349=>1000,36350=>1000,36351=>1000,36352=>1000,36354=>1000,36355=>1000,36356=>1000, -36357=>1000,36358=>1000,36359=>1000,36360=>1000,36361=>1000,36362=>1000,36364=>1000,36365=>1000,36367=>1000,36368=>1000, -36369=>1000,36370=>1000,36371=>1000,36372=>1000,36373=>1000,36374=>1000,36375=>1000,36376=>1000,36377=>1000,36378=>1000, -36379=>1000,36380=>1000,36381=>1000,36382=>1000,36383=>1000,36384=>1000,36385=>1000,36386=>1000,36387=>1000,36388=>1000, -36389=>1000,36390=>1000,36391=>1000,36393=>1000,36394=>1000,36395=>1000,36396=>1000,36398=>1000,36399=>1000,36400=>1000, -36401=>1000,36403=>1000,36404=>1000,36405=>1000,36406=>1000,36408=>1000,36409=>1000,36410=>1000,36412=>1000,36413=>1000, -36414=>1000,36415=>1000,36416=>1000,36417=>1000,36418=>1000,36420=>1000,36421=>1000,36423=>1000,36424=>1000,36425=>1000, -36426=>1000,36427=>1000,36428=>1000,36429=>1000,36430=>1000,36432=>1000,36433=>1000,36434=>1000,36435=>1000,36436=>1000, -36437=>1000,36438=>1000,36439=>1000,36441=>1000,36442=>1000,36443=>1000,36444=>1000,36445=>1000,36446=>1000,36447=>1000, -36448=>1000,36449=>1000,36450=>1000,36451=>1000,36452=>1000,36453=>1000,36454=>1000,36455=>1000,36457=>1000,36458=>1000, -36460=>1000,36461=>1000,36463=>1000,36464=>1000,36466=>1000,36467=>1000,36468=>1000,36470=>1000,36472=>1000,36474=>1000, -36475=>1000,36476=>1000,36479=>1000,36481=>1000,36482=>1000,36484=>1000,36485=>1000,36486=>1000,36487=>1000,36488=>1000, -36489=>1000,36490=>1000,36491=>1000,36492=>1000,36493=>1000,36494=>1000,36495=>1000,36496=>1000,36497=>1000,36498=>1000, -36499=>1000,36500=>1000,36501=>1000,36502=>1000,36503=>1000,36504=>1000,36505=>1000,36506=>1000,36508=>1000,36509=>1000, -36510=>1000,36511=>1000,36512=>1000,36513=>1000,36515=>1000,36516=>1000,36517=>1000,36518=>1000,36520=>1000,36521=>1000, -36522=>1000,36523=>1000,36524=>1000,36527=>1000,36528=>1000,36529=>1000,36530=>1000,36538=>1000,36541=>1000,36542=>1000, -36544=>1000,36546=>1000,36549=>1000,36550=>1000,36552=>1000,36553=>1000,36554=>1000,36555=>1000,36556=>1000,36557=>1000, -36558=>1000,36559=>1000,36561=>1000,36562=>1000,36563=>1000,36564=>1000,36567=>1000,36568=>1000,36571=>1000,36572=>1000, -36573=>1000,36574=>1000,36575=>1000,36576=>1000,36577=>1000,36578=>1000,36579=>1000,36581=>1000,36582=>1000,36583=>1000, -36584=>1000,36585=>1000,36587=>1000,36588=>1000,36590=>1000,36591=>1000,36593=>1000,36596=>1000,36597=>1000,36598=>1000, -36599=>1000,36600=>1000,36601=>1000,36602=>1000,36603=>1000,36604=>1000,36605=>1000,36606=>1000,36607=>1000,36608=>1000, -36609=>1000,36610=>1000,36611=>1000,36613=>1000,36614=>1000,36615=>1000,36616=>1000,36617=>1000,36618=>1000,36619=>1000, -36620=>1000,36621=>1000,36622=>1000,36624=>1000,36625=>1000,36626=>1000,36627=>1000,36628=>1000,36629=>1000,36630=>1000, -36631=>1000,36632=>1000,36633=>1000,36634=>1000,36635=>1000,36636=>1000,36637=>1000,36638=>1000,36639=>1000,36640=>1000, -36643=>1000,36644=>1000,36645=>1000,36646=>1000,36647=>1000,36649=>1000,36650=>1000,36652=>1000,36654=>1000,36655=>1000, -36658=>1000,36659=>1000,36660=>1000,36661=>1000,36662=>1000,36663=>1000,36664=>1000,36665=>1000,36667=>1000,36670=>1000, -36671=>1000,36672=>1000,36674=>1000,36675=>1000,36676=>1000,36677=>1000,36678=>1000,36679=>1000,36680=>1000,36681=>1000, -36683=>1000,36684=>1000,36685=>1000,36686=>1000,36687=>1000,36688=>1000,36689=>1000,36690=>1000,36691=>1000,36692=>1000, -36693=>1000,36694=>1000,36695=>1000,36696=>1000,36697=>1000,36698=>1000,36699=>1000,36700=>1000,36701=>1000,36702=>1000, -36703=>1000,36704=>1000,36705=>1000,36706=>1000,36707=>1000,36708=>1000,36710=>1000,36711=>1000,36712=>1000,36713=>1000, -36715=>1000,36716=>1000,36717=>1000,36718=>1000,36719=>1000,36720=>1000,36721=>1000,36722=>1000,36723=>1000,36724=>1000, -36725=>1000,36726=>1000,36727=>1000,36728=>1000,36729=>1000,36730=>1000,36731=>1000,36732=>1000,36733=>1000,36734=>1000, -36735=>1000,36737=>1000,36738=>1000,36739=>1000,36740=>1000,36741=>1000,36742=>1000,36743=>1000,36744=>1000,36745=>1000, -36746=>1000,36747=>1000,36749=>1000,36750=>1000,36751=>1000,36752=>1000,36753=>1000,36755=>1000,36756=>1000,36757=>1000, -36758=>1000,36759=>1000,36760=>1000,36761=>1000,36762=>1000,36763=>1000,36764=>1000,36766=>1000,36767=>1000,36771=>1000, -36774=>1000,36775=>1000,36776=>1000,36777=>1000,36779=>1000,36781=>1000,36782=>1000,36783=>1000,36784=>1000,36785=>1000, -36786=>1000,36788=>1000,36790=>1000,36791=>1000,36793=>1000,36794=>1000,36795=>1000,36796=>1000,36797=>1000,36798=>1000, -36799=>1000,36801=>1000,36802=>1000,36804=>1000,36805=>1000,36806=>1000,36807=>1000,36808=>1000,36809=>1000,36811=>1000, -36813=>1000,36814=>1000,36816=>1000,36817=>1000,36818=>1000,36819=>1000,36820=>1000,36821=>1000,36822=>1000,36823=>1000, -36824=>1000,36825=>1000,36826=>1000,36827=>1000,36828=>1000,36829=>1000,36830=>1000,36831=>1000,36832=>1000,36833=>1000, -36834=>1000,36835=>1000,36836=>1000,36837=>1000,36838=>1000,36840=>1000,36841=>1000,36842=>1000,36843=>1000,36845=>1000, -36846=>1000,36847=>1000,36848=>1000,36850=>1000,36851=>1000,36852=>1000,36853=>1000,36854=>1000,36855=>1000,36856=>1000, -36857=>1000,36858=>1000,36859=>1000,36860=>1000,36861=>1000,36862=>1000,36863=>1000,36864=>1000,36865=>1000,36866=>1000, -36867=>1000,36868=>1000,36869=>1000,36870=>1000,36872=>1000,36873=>1000,36874=>1000,36875=>1000,36876=>1000,36877=>1000, -36878=>1000,36879=>1000,36880=>1000,36881=>1000,36882=>1000,36883=>1000,36884=>1000,36885=>1000,36886=>1000,36887=>1000, -36889=>1000,36890=>1000,36891=>1000,36892=>1000,36893=>1000,36894=>1000,36895=>1000,36896=>1000,36897=>1000,36898=>1000, -36899=>1000,36900=>1000,36902=>1000,36903=>1000,36909=>1000,36910=>1000,36911=>1000,36913=>1000,36914=>1000,36916=>1000, -36917=>1000,36918=>1000,36920=>1000,36921=>1000,36923=>1000,36924=>1000,36925=>1000,36926=>1000,36927=>1000,36929=>1000, -36930=>1000,36932=>1000,36933=>1000,36935=>1000,36937=>1000,36938=>1000,36939=>1000,36941=>1000,36942=>1000,36943=>1000, -36944=>1000,36945=>1000,36946=>1000,36947=>1000,36948=>1000,36949=>1000,36950=>1000,36951=>1000,36952=>1000,36953=>1000, -36955=>1000,36956=>1000,36957=>1000,36958=>1000,36960=>1000,36961=>1000,36962=>1000,36963=>1000,36965=>1000,36967=>1000, -36968=>1000,36969=>1000,36971=>1000,36973=>1000,36974=>1000,36975=>1000,36976=>1000,36978=>1000,36979=>1000,36980=>1000, -36981=>1000,36982=>1000,36983=>1000,36984=>1000,36985=>1000,36986=>1000,36987=>1000,36988=>1000,36989=>1000,36990=>1000, -36991=>1000,36992=>1000,36993=>1000,36994=>1000,36995=>1000,36996=>1000,36997=>1000,36998=>1000,36999=>1000,37000=>1000, -37001=>1000,37002=>1000,37003=>1000,37005=>1000,37007=>1000,37008=>1000,37009=>1000,37011=>1000,37012=>1000,37013=>1000, -37015=>1000,37016=>1000,37017=>1000,37019=>1000,37021=>1000,37022=>1000,37023=>1000,37024=>1000,37025=>1000,37026=>1000, -37027=>1000,37029=>1000,37030=>1000,37031=>1000,37032=>1000,37034=>1000,37036=>1000,37038=>1000,37039=>1000,37040=>1000, -37041=>1000,37042=>1000,37043=>1000,37044=>1000,37045=>1000,37046=>1000,37048=>1000,37049=>1000,37050=>1000,37051=>1000, -37053=>1000,37054=>1000,37055=>1000,37057=>1000,37059=>1000,37060=>1000,37061=>1000,37063=>1000,37064=>1000,37066=>1000, -37067=>1000,37070=>1000,37071=>1000,37072=>1000,37073=>1000,37075=>1000,37076=>1000,37077=>1000,37078=>1000,37079=>1000, -37080=>1000,37081=>1000,37082=>1000,37083=>1000,37084=>1000,37085=>1000,37086=>1000,37087=>1000,37088=>1000,37089=>1000, -37090=>1000,37091=>1000,37092=>1000,37093=>1000,37094=>1000,37095=>1000,37096=>1000,37097=>1000,37098=>1000,37099=>1000, -37100=>1000,37101=>1000,37103=>1000,37104=>1000,37105=>1000,37106=>1000,37107=>1000,37108=>1000,37109=>1000,37111=>1000, -37112=>1000,37113=>1000,37114=>1000,37115=>1000,37116=>1000,37117=>1000,37118=>1000,37119=>1000,37120=>1000,37121=>1000, -37122=>1000,37123=>1000,37124=>1000,37125=>1000,37126=>1000,37127=>1000,37128=>1000,37129=>1000,37131=>1000,37133=>1000, -37134=>1000,37135=>1000,37136=>1000,37137=>1000,37138=>1000,37140=>1000,37141=>1000,37142=>1000,37143=>1000,37144=>1000, -37145=>1000,37146=>1000,37147=>1000,37148=>1000,37149=>1000,37150=>1000,37151=>1000,37152=>1000,37153=>1000,37154=>1000, -37155=>1000,37156=>1000,37158=>1000,37159=>1000,37160=>1000,37161=>1000,37162=>1000,37163=>1000,37164=>1000,37165=>1000, -37166=>1000,37167=>1000,37168=>1000,37169=>1000,37170=>1000,37171=>1000,37172=>1000,37173=>1000,37174=>1000,37176=>1000, -37177=>1000,37178=>1000,37179=>1000,37182=>1000,37183=>1000,37184=>1000,37185=>1000,37187=>1000,37188=>1000,37189=>1000, -37190=>1000,37191=>1000,37192=>1000,37193=>1000,37194=>1000,37195=>1000,37196=>1000,37197=>1000,37198=>1000,37199=>1000, -37200=>1000,37202=>1000,37203=>1000,37204=>1000,37205=>1000,37206=>1000,37207=>1000,37208=>1000,37210=>1000,37213=>1000, -37214=>1000,37215=>1000,37216=>1000,37217=>1000,37218=>1000,37219=>1000,37220=>1000,37221=>1000,37224=>1000,37225=>1000, -37226=>1000,37228=>1000,37230=>1000,37231=>1000,37232=>1000,37233=>1000,37234=>1000,37235=>1000,37236=>1000,37237=>1000, -37238=>1000,37239=>1000,37240=>1000,37241=>1000,37242=>1000,37245=>1000,37246=>1000,37247=>1000,37248=>1000,37249=>1000, -37250=>1000,37251=>1000,37252=>1000,37253=>1000,37254=>1000,37255=>1000,37257=>1000,37258=>1000,37259=>1000,37260=>1000, -37261=>1000,37263=>1000,37264=>1000,37265=>1000,37266=>1000,37267=>1000,37271=>1000,37273=>1000,37274=>1000,37275=>1000, -37276=>1000,37277=>1000,37278=>1000,37279=>1000,37280=>1000,37281=>1000,37282=>1000,37283=>1000,37284=>1000,37285=>1000, -37287=>1000,37288=>1000,37290=>1000,37291=>1000,37292=>1000,37293=>1000,37294=>1000,37295=>1000,37296=>1000,37297=>1000, -37298=>1000,37299=>1000,37300=>1000,37301=>1000,37303=>1000,37304=>1000,37305=>1000,37306=>1000,37308=>1000,37309=>1000, -37310=>1000,37312=>1000,37313=>1000,37314=>1000,37315=>1000,37317=>1000,37318=>1000,37319=>1000,37320=>1000,37321=>1000, -37322=>1000,37323=>1000,37324=>1000,37325=>1000,37326=>1000,37327=>1000,37328=>1000,37329=>1000,37331=>1000,37332=>1000, -37333=>1000,37334=>1000,37335=>1000,37336=>1000,37337=>1000,37338=>1000,37339=>1000,37340=>1000,37341=>1000,37342=>1000, -37343=>1000,37345=>1000,37346=>1000,37347=>1000,37348=>1000,37349=>1000,37350=>1000,37351=>1000,37352=>1000,37353=>1000, -37354=>1000,37355=>1000,37356=>1000,37357=>1000,37358=>1000,37361=>1000,37363=>1000,37364=>1000,37365=>1000,37366=>1000, -37367=>1000,37368=>1000,37369=>1000,37372=>1000,37373=>1000,37375=>1000,37376=>1000,37377=>1000,37378=>1000,37379=>1000, -37380=>1000,37381=>1000,37382=>1000,37383=>1000,37385=>1000,37386=>1000,37388=>1000,37389=>1000,37390=>1000,37391=>1000, -37392=>1000,37393=>1000,37394=>1000,37396=>1000,37397=>1000,37398=>1000,37399=>1000,37401=>1000,37402=>1000,37404=>1000, -37406=>1000,37411=>1000,37412=>1000,37413=>1000,37414=>1000,37415=>1000,37417=>1000,37420=>1000,37421=>1000,37422=>1000, -37424=>1000,37425=>1000,37426=>1000,37427=>1000,37428=>1000,37430=>1000,37431=>1000,37432=>1000,37433=>1000,37434=>1000, -37436=>1000,37437=>1000,37438=>1000,37439=>1000,37440=>1000,37444=>1000,37445=>1000,37446=>1000,37448=>1000,37449=>1000, -37450=>1000,37451=>1000,37452=>1000,37453=>1000,37454=>1000,37455=>1000,37456=>1000,37457=>1000,37458=>1000,37459=>1000, -37460=>1000,37462=>1000,37463=>1000,37465=>1000,37466=>1000,37467=>1000,37470=>1000,37472=>1000,37473=>1000,37474=>1000, -37475=>1000,37476=>1000,37477=>1000,37478=>1000,37479=>1000,37484=>1000,37485=>1000,37487=>1000,37488=>1000,37489=>1000, -37490=>1000,37492=>1000,37494=>1000,37495=>1000,37496=>1000,37497=>1000,37498=>1000,37499=>1000,37500=>1000,37501=>1000, -37502=>1000,37503=>1000,37504=>1000,37506=>1000,37507=>1000,37509=>1000,37510=>1000,37511=>1000,37512=>1000,37514=>1000, -37515=>1000,37516=>1000,37517=>1000,37518=>1000,37521=>1000,37523=>1000,37524=>1000,37525=>1000,37526=>1000,37527=>1000, -37528=>1000,37529=>1000,37530=>1000,37531=>1000,37532=>1000,37533=>1000,37536=>1000,37537=>1000,37538=>1000,37539=>1000, -37540=>1000,37541=>1000,37542=>1000,37543=>1000,37544=>1000,37545=>1000,37546=>1000,37547=>1000,37548=>1000,37549=>1000, -37550=>1000,37554=>1000,37555=>1000,37556=>1000,37557=>1000,37558=>1000,37559=>1000,37561=>1000,37563=>1000,37564=>1000, -37568=>1000,37569=>1000,37570=>1000,37571=>1000,37572=>1000,37573=>1000,37574=>1000,37575=>1000,37576=>1000,37577=>1000, -37578=>1000,37579=>1000,37580=>1000,37581=>1000,37582=>1000,37583=>1000,37584=>1000,37585=>1000,37586=>1000,37587=>1000, -37589=>1000,37591=>1000,37592=>1000,37593=>1000,37597=>1000,37598=>1000,37599=>1000,37600=>1000,37601=>1000,37604=>1000, -37606=>1000,37607=>1000,37608=>1000,37609=>1000,37610=>1000,37613=>1000,37614=>1000,37615=>1000,37616=>1000,37617=>1000, -37618=>1000,37619=>1000,37623=>1000,37624=>1000,37625=>1000,37626=>1000,37627=>1000,37628=>1000,37630=>1000,37631=>1000, -37632=>1000,37633=>1000,37634=>1000,37636=>1000,37638=>1000,37640=>1000,37641=>1000,37643=>1000,37644=>1000,37645=>1000, -37646=>1000,37647=>1000,37648=>1000,37650=>1000,37651=>1000,37652=>1000,37653=>1000,37654=>1000,37656=>1000,37657=>1000, -37658=>1000,37659=>1000,37661=>1000,37662=>1000,37663=>1000,37664=>1000,37665=>1000,37666=>1000,37667=>1000,37668=>1000, -37669=>1000,37670=>1000,37671=>1000,37672=>1000,37673=>1000,37674=>1000,37675=>1000,37676=>1000,37677=>1000,37678=>1000, -37679=>1000,37682=>1000,37683=>1000,37684=>1000,37685=>1000,37686=>1000,37688=>1000,37689=>1000,37690=>1000,37691=>1000, -37692=>1000,37694=>1000,37700=>1000,37702=>1000,37703=>1000,37704=>1000,37705=>1000,37706=>1000,37707=>1000,37708=>1000, -37709=>1000,37710=>1000,37711=>1000,37712=>1000,37713=>1000,37714=>1000,37716=>1000,37717=>1000,37718=>1000,37719=>1000, -37720=>1000,37721=>1000,37722=>1000,37723=>1000,37724=>1000,37726=>1000,37728=>1000,37729=>1000,37731=>1000,37732=>1000, -37733=>1000,37735=>1000,37738=>1000,37740=>1000,37741=>1000,37742=>1000,37744=>1000,37745=>1000,37749=>1000,37750=>1000, -37751=>1000,37753=>1000,37754=>1000,37755=>1000,37756=>1000,37758=>1000,37760=>1000,37762=>1000,37763=>1000,37768=>1000, -37769=>1000,37770=>1000,37772=>1000,37773=>1000,37774=>1000,37775=>1000,37777=>1000,37778=>1000,37780=>1000,37781=>1000, -37782=>1000,37783=>1000,37784=>1000,37785=>1000,37786=>1000,37787=>1000,37789=>1000,37790=>1000,37791=>1000,37793=>1000, -37794=>1000,37795=>1000,37796=>1000,37797=>1000,37798=>1000,37799=>1000,37800=>1000,37801=>1000,37802=>1000,37804=>1000, -37805=>1000,37806=>1000,37807=>1000,37808=>1000,37809=>1000,37810=>1000,37811=>1000,37812=>1000,37813=>1000,37815=>1000, -37817=>1000,37824=>1000,37826=>1000,37827=>1000,37828=>1000,37830=>1000,37831=>1000,37832=>1000,37834=>1000,37836=>1000, -37837=>1000,37838=>1000,37839=>1000,37840=>1000,37841=>1000,37842=>1000,37844=>1000,37845=>1000,37846=>1000,37847=>1000, -37848=>1000,37849=>1000,37850=>1000,37852=>1000,37853=>1000,37854=>1000,37855=>1000,37857=>1000,37858=>1000,37859=>1000, -37860=>1000,37861=>1000,37862=>1000,37863=>1000,37864=>1000,37868=>1000,37870=>1000,37877=>1000,37878=>1000,37879=>1000, -37880=>1000,37881=>1000,37882=>1000,37883=>1000,37884=>1000,37885=>1000,37886=>1000,37887=>1000,37888=>1000,37891=>1000, -37892=>1000,37894=>1000,37895=>1000,37897=>1000,37898=>1000,37899=>1000,37900=>1000,37901=>1000,37902=>1000,37903=>1000, -37904=>1000,37905=>1000,37906=>1000,37907=>1000,37908=>1000,37909=>1000,37910=>1000,37912=>1000,37913=>1000,37914=>1000, -37920=>1000,37921=>1000,37925=>1000,37928=>1000,37929=>1000,37930=>1000,37931=>1000,37932=>1000,37934=>1000,37936=>1000, -37937=>1000,37938=>1000,37939=>1000,37941=>1000,37942=>1000,37943=>1000,37944=>1000,37945=>1000,37946=>1000,37947=>1000, -37948=>1000,37949=>1000,37950=>1000,37951=>1000,37952=>1000,37953=>1000,37956=>1000,37957=>1000,37958=>1000,37959=>1000, -37960=>1000,37961=>1000,37962=>1000,37963=>1000,37964=>1000,37967=>1000,37968=>1000,37969=>1000,37970=>1000,37971=>1000, -37973=>1000,37975=>1000,37978=>1000,37979=>1000,37981=>1000,37982=>1000,37984=>1000,37986=>1000,37987=>1000,37988=>1000, -37992=>1000,37993=>1000,37994=>1000,37995=>1000,37997=>1000,37998=>1000,37999=>1000,38000=>1000,38001=>1000,38002=>1000, -38003=>1000,38004=>1000,38005=>1000,38006=>1000,38007=>1000,38008=>1000,38012=>1000,38013=>1000,38014=>1000,38015=>1000, -38016=>1000,38017=>1000,38018=>1000,38019=>1000,38021=>1000,38022=>1000,38023=>1000,38024=>1000,38025=>1000,38026=>1000, -38027=>1000,38028=>1000,38029=>1000,38030=>1000,38031=>1000,38032=>1000,38034=>1000,38035=>1000,38036=>1000,38037=>1000, -38039=>1000,38041=>1000,38042=>1000,38043=>1000,38044=>1000,38045=>1000,38046=>1000,38047=>1000,38048=>1000,38049=>1000, -38050=>1000,38051=>1000,38052=>1000,38053=>1000,38054=>1000,38055=>1000,38056=>1000,38057=>1000,38058=>1000,38059=>1000, -38060=>1000,38061=>1000,38062=>1000,38063=>1000,38064=>1000,38065=>1000,38066=>1000,38067=>1000,38068=>1000,38069=>1000, -38070=>1000,38071=>1000,38072=>1000,38073=>1000,38074=>1000,38075=>1000,38076=>1000,38077=>1000,38078=>1000,38079=>1000, -38080=>1000,38081=>1000,38082=>1000,38083=>1000,38084=>1000,38085=>1000,38086=>1000,38088=>1000,38089=>1000,38090=>1000, -38091=>1000,38092=>1000,38093=>1000,38094=>1000,38096=>1000,38097=>1000,38098=>1000,38101=>1000,38102=>1000,38103=>1000, -38104=>1000,38105=>1000,38107=>1000,38108=>1000,38109=>1000,38110=>1000,38111=>1000,38112=>1000,38113=>1000,38114=>1000, -38115=>1000,38116=>1000,38117=>1000,38119=>1000,38120=>1000,38121=>1000,38122=>1000,38123=>1000,38124=>1000,38125=>1000, -38126=>1000,38127=>1000,38128=>1000,38129=>1000,38130=>1000,38131=>1000,38132=>1000,38133=>1000,38134=>1000,38135=>1000, -38136=>1000,38137=>1000,38138=>1000,38140=>1000,38141=>1000,38142=>1000,38143=>1000,38144=>1000,38145=>1000,38146=>1000, -38147=>1000,38148=>1000,38149=>1000,38150=>1000,38151=>1000,38152=>1000,38153=>1000,38154=>1000,38155=>1000,38156=>1000, -38157=>1000,38158=>1000,38159=>1000,38160=>1000,38161=>1000,38162=>1000,38163=>1000,38164=>1000,38165=>1000,38166=>1000, -38167=>1000,38168=>1000,38169=>1000,38170=>1000,38171=>1000,38173=>1000,38174=>1000,38175=>1000,38177=>1000,38178=>1000, -38179=>1000,38180=>1000,38181=>1000,38182=>1000,38184=>1000,38185=>1000,38186=>1000,38187=>1000,38188=>1000,38189=>1000, -38190=>1000,38191=>1000,38192=>1000,38193=>1000,38194=>1000,38196=>1000,38197=>1000,38198=>1000,38199=>1000,38200=>1000, -38201=>1000,38202=>1000,38203=>1000,38204=>1000,38206=>1000,38207=>1000,38208=>1000,38209=>1000,38210=>1000,38212=>1000, -38213=>1000,38214=>1000,38215=>1000,38217=>1000,38218=>1000,38220=>1000,38221=>1000,38222=>1000,38223=>1000,38224=>1000, -38225=>1000,38226=>1000,38227=>1000,38228=>1000,38230=>1000,38231=>1000,38232=>1000,38233=>1000,38235=>1000,38236=>1000, -38237=>1000,38238=>1000,38239=>1000,38241=>1000,38242=>1000,38243=>1000,38244=>1000,38245=>1000,38246=>1000,38247=>1000, -38248=>1000,38249=>1000,38250=>1000,38251=>1000,38252=>1000,38253=>1000,38255=>1000,38256=>1000,38257=>1000,38258=>1000, -38259=>1000,38262=>1000,38263=>1000,38266=>1000,38267=>1000,38268=>1000,38269=>1000,38271=>1000,38272=>1000,38274=>1000, -38275=>1000,38278=>1000,38279=>1000,38280=>1000,38281=>1000,38282=>1000,38283=>1000,38284=>1000,38285=>1000,38286=>1000, -38287=>1000,38288=>1000,38289=>1000,38290=>1000,38291=>1000,38292=>1000,38294=>1000,38296=>1000,38297=>1000,38299=>1000, -38300=>1000,38302=>1000,38303=>1000,38304=>1000,38305=>1000,38306=>1000,38307=>1000,38308=>1000,38309=>1000,38311=>1000, -38312=>1000,38313=>1000,38315=>1000,38316=>1000,38317=>1000,38318=>1000,38320=>1000,38321=>1000,38322=>1000,38325=>1000, -38326=>1000,38327=>1000,38329=>1000,38330=>1000,38331=>1000,38332=>1000,38333=>1000,38334=>1000,38335=>1000,38336=>1000, -38339=>1000,38341=>1000,38342=>1000,38343=>1000,38344=>1000,38345=>1000,38346=>1000,38347=>1000,38348=>1000,38349=>1000, -38352=>1000,38353=>1000,38354=>1000,38355=>1000,38356=>1000,38357=>1000,38358=>1000,38360=>1000,38362=>1000,38363=>1000, -38364=>1000,38366=>1000,38367=>1000,38368=>1000,38369=>1000,38370=>1000,38371=>1000,38372=>1000,38373=>1000,38376=>1000, -38377=>1000,38378=>1000,38379=>1000,38381=>1000,38382=>1000,38383=>1000,38384=>1000,38385=>1000,38386=>1000,38387=>1000, -38388=>1000,38389=>1000,38390=>1000,38391=>1000,38392=>1000,38393=>1000,38394=>1000,38395=>1000,38396=>1000,38397=>1000, -38398=>1000,38400=>1000,38401=>1000,38402=>1000,38403=>1000,38404=>1000,38405=>1000,38406=>1000,38408=>1000,38409=>1000, -38410=>1000,38411=>1000,38412=>1000,38413=>1000,38414=>1000,38415=>1000,38416=>1000,38417=>1000,38418=>1000,38420=>1000, -38421=>1000,38422=>1000,38423=>1000,38425=>1000,38426=>1000,38428=>1000,38429=>1000,38430=>1000,38431=>1000,38432=>1000, -38433=>1000,38434=>1000,38435=>1000,38436=>1000,38440=>1000,38442=>1000,38444=>1000,38445=>1000,38446=>1000,38447=>1000, -38448=>1000,38449=>1000,38450=>1000,38451=>1000,38452=>1000,38453=>1000,38454=>1000,38457=>1000,38458=>1000,38459=>1000, -38460=>1000,38461=>1000,38463=>1000,38464=>1000,38466=>1000,38467=>1000,38468=>1000,38469=>1000,38470=>1000,38471=>1000, -38472=>1000,38473=>1000,38474=>1000,38475=>1000,38476=>1000,38477=>1000,38478=>1000,38479=>1000,38480=>1000,38481=>1000, -38483=>1000,38484=>1000,38485=>1000,38488=>1000,38491=>1000,38492=>1000,38493=>1000,38494=>1000,38495=>1000,38497=>1000, -38498=>1000,38499=>1000,38500=>1000,38501=>1000,38502=>1000,38503=>1000,38504=>1000,38505=>1000,38506=>1000,38507=>1000, -38508=>1000,38509=>1000,38511=>1000,38512=>1000,38513=>1000,38514=>1000,38515=>1000,38516=>1000,38517=>1000,38518=>1000, -38519=>1000,38520=>1000,38522=>1000,38524=>1000,38525=>1000,38526=>1000,38528=>1000,38531=>1000,38532=>1000,38533=>1000, -38534=>1000,38535=>1000,38536=>1000,38537=>1000,38538=>1000,38539=>1000,38541=>1000,38542=>1000,38543=>1000,38544=>1000, -38545=>1000,38546=>1000,38547=>1000,38548=>1000,38549=>1000,38551=>1000,38552=>1000,38553=>1000,38555=>1000,38556=>1000, -38557=>1000,38558=>1000,38560=>1000,38561=>1000,38562=>1000,38563=>1000,38564=>1000,38567=>1000,38568=>1000,38569=>1000, -38570=>1000,38572=>1000,38574=>1000,38575=>1000,38576=>1000,38577=>1000,38578=>1000,38579=>1000,38580=>1000,38582=>1000, -38583=>1000,38584=>1000,38585=>1000,38587=>1000,38588=>1000,38589=>1000,38590=>1000,38591=>1000,38592=>1000,38593=>1000, -38594=>1000,38595=>1000,38596=>1000,38597=>1000,38598=>1000,38599=>1000,38600=>1000,38601=>1000,38602=>1000,38603=>1000, -38604=>1000,38605=>1000,38606=>1000,38607=>1000,38609=>1000,38610=>1000,38611=>1000,38612=>1000,38613=>1000,38614=>1000, -38615=>1000,38616=>1000,38617=>1000,38618=>1000,38619=>1000,38620=>1000,38621=>1000,38622=>1000,38623=>1000,38624=>1000, -38625=>1000,38626=>1000,38627=>1000,38629=>1000,38632=>1000,38633=>1000,38634=>1000,38635=>1000,38639=>1000,38640=>1000, -38641=>1000,38642=>1000,38643=>1000,38645=>1000,38646=>1000,38647=>1000,38648=>1000,38649=>1000,38650=>1000,38651=>1000, -38653=>1000,38654=>1000,38655=>1000,38656=>1000,38657=>1000,38658=>1000,38660=>1000,38661=>1000,38662=>1000,38663=>1000, -38664=>1000,38665=>1000,38666=>1000,38667=>1000,38669=>1000,38670=>1000,38671=>1000,38672=>1000,38673=>1000,38674=>1000, -38675=>1000,38678=>1000,38680=>1000,38681=>1000,38684=>1000,38685=>1000,38686=>1000,38687=>1000,38688=>1000,38690=>1000, -38691=>1000,38692=>1000,38693=>1000,38694=>1000,38695=>1000,38696=>1000,38697=>1000,38698=>1000,38699=>1000,38700=>1000, -38701=>1000,38702=>1000,38703=>1000,38704=>1000,38706=>1000,38707=>1000,38709=>1000,38712=>1000,38713=>1000,38714=>1000, -38715=>1000,38717=>1000,38718=>1000,38719=>1000,38722=>1000,38723=>1000,38724=>1000,38726=>1000,38727=>1000,38728=>1000, -38729=>1000,38731=>1000,38733=>1000,38735=>1000,38737=>1000,38738=>1000,38739=>1000,38741=>1000,38742=>1000,38744=>1000, -38745=>1000,38746=>1000,38747=>1000,38748=>1000,38750=>1000,38752=>1000,38753=>1000,38754=>1000,38756=>1000,38757=>1000, -38758=>1000,38760=>1000,38761=>1000,38762=>1000,38763=>1000,38764=>1000,38765=>1000,38766=>1000,38768=>1000,38769=>1000, -38770=>1000,38771=>1000,38772=>1000,38774=>1000,38775=>1000,38776=>1000,38777=>1000,38778=>1000,38779=>1000,38780=>1000, -38781=>1000,38782=>1000,38783=>1000,38784=>1000,38785=>1000,38786=>1000,38787=>1000,38788=>1000,38789=>1000,38790=>1000, -38792=>1000,38794=>1000,38795=>1000,38797=>1000,38798=>1000,38799=>1000,38800=>1000,38801=>1000,38802=>1000,38804=>1000, -38807=>1000,38808=>1000,38809=>1000,38810=>1000,38812=>1000,38813=>1000,38814=>1000,38816=>1000,38817=>1000,38818=>1000, -38819=>1000,38820=>1000,38821=>1000,38822=>1000,38824=>1000,38826=>1000,38827=>1000,38828=>1000,38829=>1000,38830=>1000, -38831=>1000,38834=>1000,38835=>1000,38836=>1000,38838=>1000,38839=>1000,38841=>1000,38843=>1000,38847=>1000,38849=>1000, -38851=>1000,38852=>1000,38853=>1000,38854=>1000,38855=>1000,38856=>1000,38857=>1000,38859=>1000,38860=>1000,38861=>1000, -38862=>1000,38863=>1000,38864=>1000,38867=>1000,38868=>1000,38869=>1000,38870=>1000,38871=>1000,38872=>1000,38873=>1000, -38876=>1000,38877=>1000,38878=>1000,38879=>1000,38881=>1000,38883=>1000,38885=>1000,38886=>1000,38887=>1000,38889=>1000, -38890=>1000,38891=>1000,38892=>1000,38893=>1000,38894=>1000,38896=>1000,38897=>1000,38898=>1000,38899=>1000,38901=>1000, -38902=>1000,38904=>1000,38905=>1000,38906=>1000,38907=>1000,38909=>1000,38910=>1000,38911=>1000,38912=>1000,38913=>1000, -38914=>1000,38915=>1000,38916=>1000,38917=>1000,38918=>1000,38919=>1000,38920=>1000,38922=>1000,38924=>1000,38925=>1000, -38926=>1000,38927=>1000,38928=>1000,38929=>1000,38930=>1000,38931=>1000,38934=>1000,38935=>1000,38936=>1000,38938=>1000, -38939=>1000,38940=>1000,38941=>1000,38942=>1000,38944=>1000,38945=>1000,38948=>1000,38950=>1000,38951=>1000,38952=>1000, -38953=>1000,38955=>1000,38956=>1000,38957=>1000,38959=>1000,38960=>1000,38962=>1000,38964=>1000,38965=>1000,38967=>1000, -38968=>1000,38969=>1000,38971=>1000,38972=>1000,38973=>1000,38977=>1000,38979=>1000,38980=>1000,38981=>1000,38982=>1000, -38984=>1000,38985=>1000,38986=>1000,38987=>1000,38988=>1000,38989=>1000,38990=>1000,38991=>1000,38992=>1000,38993=>1000, -38994=>1000,38995=>1000,38996=>1000,38997=>1000,38999=>1000,39000=>1000,39001=>1000,39002=>1000,39003=>1000,39004=>1000, -39005=>1000,39006=>1000,39007=>1000,39008=>1000,39010=>1000,39011=>1000,39012=>1000,39013=>1000,39015=>1000,39017=>1000, -39018=>1000,39019=>1000,39023=>1000,39024=>1000,39025=>1000,39026=>1000,39027=>1000,39028=>1000,39029=>1000,39030=>1000, -39031=>1000,39032=>1000,39033=>1000,39034=>1000,39035=>1000,39036=>1000,39037=>1000,39038=>1000,39039=>1000,39040=>1000, -39041=>1000,39042=>1000,39043=>1000,39044=>1000,39045=>1000,39046=>1000,39047=>1000,39048=>1000,39049=>1000,39050=>1000, -39052=>1000,39053=>1000,39055=>1000,39056=>1000,39057=>1000,39059=>1000,39060=>1000,39062=>1000,39063=>1000,39064=>1000, -39066=>1000,39067=>1000,39068=>1000,39069=>1000,39070=>1000,39071=>1000,39072=>1000,39073=>1000,39074=>1000,39076=>1000, -39077=>1000,39078=>1000,39079=>1000,39080=>1000,39081=>1000,39082=>1000,39084=>1000,39085=>1000,39086=>1000,39087=>1000, -39089=>1000,39090=>1000,39091=>1000,39094=>1000,39096=>1000,39098=>1000,39099=>1000,39100=>1000,39101=>1000,39102=>1000, -39103=>1000,39104=>1000,39105=>1000,39106=>1000,39107=>1000,39108=>1000,39110=>1000,39111=>1000,39113=>1000,39115=>1000, -39116=>1000,39118=>1000,39121=>1000,39122=>1000,39123=>1000,39125=>1000,39128=>1000,39129=>1000,39130=>1000,39131=>1000, -39132=>1000,39134=>1000,39135=>1000,39137=>1000,39138=>1000,39139=>1000,39141=>1000,39143=>1000,39144=>1000,39145=>1000, -39146=>1000,39147=>1000,39149=>1000,39150=>1000,39151=>1000,39154=>1000,39156=>1000,39158=>1000,39161=>1000,39162=>1000, -39164=>1000,39165=>1000,39166=>1000,39168=>1000,39170=>1000,39171=>1000,39173=>1000,39175=>1000,39176=>1000,39177=>1000, -39178=>1000,39180=>1000,39181=>1000,39184=>1000,39185=>1000,39186=>1000,39187=>1000,39188=>1000,39189=>1000,39190=>1000, -39191=>1000,39192=>1000,39194=>1000,39195=>1000,39197=>1000,39198=>1000,39199=>1000,39200=>1000,39201=>1000,39204=>1000, -39205=>1000,39207=>1000,39208=>1000,39209=>1000,39210=>1000,39211=>1000,39212=>1000,39213=>1000,39214=>1000,39215=>1000, -39216=>1000,39217=>1000,39218=>1000,39219=>1000,39221=>1000,39226=>1000,39228=>1000,39229=>1000,39230=>1000,39231=>1000, -39233=>1000,39234=>1000,39235=>1000,39237=>1000,39239=>1000,39240=>1000,39241=>1000,39243=>1000,39244=>1000,39245=>1000, -39246=>1000,39248=>1000,39249=>1000,39250=>1000,39251=>1000,39252=>1000,39253=>1000,39254=>1000,39255=>1000,39256=>1000, -39257=>1000,39259=>1000,39260=>1000,39262=>1000,39263=>1000,39265=>1000,39267=>1000,39269=>1000,39271=>1000,39272=>1000, -39273=>1000,39274=>1000,39275=>1000,39276=>1000,39277=>1000,39278=>1000,39279=>1000,39280=>1000,39281=>1000,39282=>1000, -39284=>1000,39285=>1000,39286=>1000,39287=>1000,39290=>1000,39292=>1000,39293=>1000,39295=>1000,39296=>1000,39297=>1000, -39300=>1000,39301=>1000,39302=>1000,39303=>1000,39304=>1000,39306=>1000,39307=>1000,39309=>1000,39311=>1000,39312=>1000, -39313=>1000,39314=>1000,39315=>1000,39316=>1000,39317=>1000,39318=>1000,39319=>1000,39320=>1000,39321=>1000,39324=>1000, -39325=>1000,39326=>1000,39329=>1000,39331=>1000,39333=>1000,39334=>1000,39335=>1000,39336=>1000,39339=>1000,39340=>1000, -39341=>1000,39342=>1000,39343=>1000,39344=>1000,39345=>1000,39346=>1000,39347=>1000,39348=>1000,39349=>1000,39353=>1000, -39354=>1000,39355=>1000,39356=>1000,39357=>1000,39361=>1000,39362=>1000,39363=>1000,39364=>1000,39365=>1000,39366=>1000, -39367=>1000,39368=>1000,39369=>1000,39371=>1000,39372=>1000,39373=>1000,39374=>1000,39375=>1000,39376=>1000,39377=>1000, -39378=>1000,39379=>1000,39380=>1000,39381=>1000,39382=>1000,39383=>1000,39384=>1000,39385=>1000,39387=>1000,39388=>1000, -39389=>1000,39391=>1000,39394=>1000,39395=>1000,39396=>1000,39397=>1000,39399=>1000,39401=>1000,39402=>1000,39404=>1000, -39405=>1000,39406=>1000,39408=>1000,39409=>1000,39410=>1000,39412=>1000,39414=>1000,39415=>1000,39416=>1000,39417=>1000, -39418=>1000,39419=>1000,39420=>1000,39421=>1000,39422=>1000,39423=>1000,39425=>1000,39426=>1000,39427=>1000,39428=>1000, -39429=>1000,39430=>1000,39431=>1000,39432=>1000,39433=>1000,39434=>1000,39435=>1000,39437=>1000,39438=>1000,39439=>1000, -39441=>1000,39442=>1000,39443=>1000,39444=>1000,39445=>1000,39446=>1000,39449=>1000,39450=>1000,39451=>1000,39452=>1000, -39453=>1000,39454=>1000,39456=>1000,39458=>1000,39459=>1000,39460=>1000,39461=>1000,39463=>1000,39464=>1000,39465=>1000, -39466=>1000,39467=>1000,39468=>1000,39469=>1000,39470=>1000,39472=>1000,39473=>1000,39474=>1000,39476=>1000,39477=>1000, -39478=>1000,39479=>1000,39480=>1000,39481=>1000,39482=>1000,39485=>1000,39486=>1000,39487=>1000,39488=>1000,39489=>1000, -39490=>1000,39491=>1000,39492=>1000,39493=>1000,39494=>1000,39496=>1000,39497=>1000,39498=>1000,39500=>1000,39501=>1000, -39502=>1000,39503=>1000,39504=>1000,39506=>1000,39507=>1000,39508=>1000,39509=>1000,39510=>1000,39511=>1000,39513=>1000, -39514=>1000,39515=>1000,39518=>1000,39519=>1000,39520=>1000,39522=>1000,39524=>1000,39525=>1000,39526=>1000,39527=>1000, -39528=>1000,39529=>1000,39530=>1000,39531=>1000,39532=>1000,39533=>1000,39534=>1000,39535=>1000,39536=>1000,39537=>1000, -39539=>1000,39540=>1000,39541=>1000,39542=>1000,39543=>1000,39544=>1000,39545=>1000,39546=>1000,39547=>1000,39548=>1000, -39549=>1000,39550=>1000,39551=>1000,39552=>1000,39553=>1000,39554=>1000,39556=>1000,39557=>1000,39558=>1000,39559=>1000, -39560=>1000,39562=>1000,39563=>1000,39564=>1000,39567=>1000,39568=>1000,39569=>1000,39570=>1000,39571=>1000,39574=>1000, -39575=>1000,39576=>1000,39578=>1000,39579=>1000,39580=>1000,39581=>1000,39582=>1000,39583=>1000,39584=>1000,39585=>1000, -39586=>1000,39587=>1000,39588=>1000,39589=>1000,39591=>1000,39592=>1000,39595=>1000,39597=>1000,39599=>1000,39600=>1000, -39601=>1000,39603=>1000,39604=>1000,39606=>1000,39607=>1000,39608=>1000,39609=>1000,39610=>1000,39611=>1000,39612=>1000, -39614=>1000,39615=>1000,39616=>1000,39617=>1000,39618=>1000,39620=>1000,39621=>1000,39622=>1000,39623=>1000,39626=>1000, -39627=>1000,39628=>1000,39629=>1000,39631=>1000,39632=>1000,39633=>1000,39634=>1000,39635=>1000,39636=>1000,39637=>1000, -39638=>1000,39640=>1000,39641=>1000,39644=>1000,39646=>1000,39647=>1000,39649=>1000,39650=>1000,39651=>1000,39653=>1000, -39654=>1000,39655=>1000,39658=>1000,39659=>1000,39660=>1000,39661=>1000,39662=>1000,39663=>1000,39665=>1000,39666=>1000, -39667=>1000,39668=>1000,39670=>1000,39671=>1000,39673=>1000,39674=>1000,39675=>1000,39676=>1000,39677=>1000,39678=>1000, -39681=>1000,39683=>1000,39684=>1000,39685=>1000,39686=>1000,39688=>1000,39690=>1000,39691=>1000,39692=>1000,39693=>1000, -39694=>1000,39695=>1000,39696=>1000,39697=>1000,39698=>1000,39699=>1000,39701=>1000,39702=>1000,39703=>1000,39704=>1000, -39705=>1000,39706=>1000,39710=>1000,39711=>1000,39712=>1000,39714=>1000,39715=>1000,39716=>1000,39717=>1000,39719=>1000, -39720=>1000,39721=>1000,39722=>1000,39723=>1000,39726=>1000,39727=>1000,39729=>1000,39730=>1000,39731=>1000,39733=>1000, -39735=>1000,39738=>1000,39739=>1000,39740=>1000,39742=>1000,39743=>1000,39745=>1000,39746=>1000,39747=>1000,39748=>1000, -39749=>1000,39750=>1000,39751=>1000,39752=>1000,39753=>1000,39754=>1000,39755=>1000,39756=>1000,39757=>1000,39758=>1000, -39759=>1000,39761=>1000,39762=>1000,39764=>1000,39765=>1000,39766=>1000,39768=>1000,39769=>1000,39770=>1000,39771=>1000, -39775=>1000,39776=>1000,39777=>1000,39780=>1000,39782=>1000,39783=>1000,39784=>1000,39788=>1000,39791=>1000,39792=>1000, -39793=>1000,39794=>1000,39796=>1000,39797=>1000,39798=>1000,39799=>1000,39802=>1000,39803=>1000,39804=>1000,39805=>1000, -39806=>1000,39808=>1000,39810=>1000,39811=>1000,39813=>1000,39814=>1000,39815=>1000,39816=>1000,39822=>1000,39823=>1000, -39824=>1000,39825=>1000,39826=>1000,39827=>1000,39829=>1000,39830=>1000,39831=>1000,39834=>1000,39835=>1000,39838=>1000, -39839=>1000,39840=>1000,39841=>1000,39842=>1000,39844=>1000,39845=>1000,39846=>1000,39848=>1000,39850=>1000,39851=>1000, -39853=>1000,39854=>1000,39855=>1000,39857=>1000,39860=>1000,39861=>1000,39862=>1000,39864=>1000,39865=>1000,39867=>1000, -39869=>1000,39871=>1000,39872=>1000,39873=>1000,39875=>1000,39876=>1000,39878=>1000,39879=>1000,39880=>1000,39881=>1000, -39882=>1000,39887=>1000,39889=>1000,39890=>1000,39891=>1000,39892=>1000,39893=>1000,39894=>1000,39895=>1000,39897=>1000, -39898=>1000,39899=>1000,39900=>1000,39902=>1000,39904=>1000,39905=>1000,39906=>1000,39907=>1000,39908=>1000,39909=>1000, -39910=>1000,39911=>1000,39912=>1000,39914=>1000,39915=>1000,39916=>1000,39920=>1000,39921=>1000,39922=>1000,39925=>1000, -39927=>1000,39928=>1000,39933=>1000,39936=>1000,39940=>1000,39941=>1000,39942=>1000,39943=>1000,39944=>1000,39945=>1000, -39946=>1000,39947=>1000,39948=>1000,39949=>1000,39950=>1000,39952=>1000,39954=>1000,39955=>1000,39956=>1000,39957=>1000, -39959=>1000,39963=>1000,39964=>1000,39965=>1000,39969=>1000,39971=>1000,39972=>1000,39973=>1000,39976=>1000,39977=>1000, -39979=>1000,39980=>1000,39981=>1000,39982=>1000,39983=>1000,39984=>1000,39985=>1000,39986=>1000,39987=>1000,39988=>1000, -39990=>1000,39991=>1000,39993=>1000,39994=>1000,39995=>1000,39996=>1000,39997=>1000,39998=>1000,39999=>1000,40000=>1000, -40001=>1000,40004=>1000,40006=>1000,40007=>1000,40008=>1000,40009=>1000,40010=>1000,40011=>1000,40012=>1000,40013=>1000, -40014=>1000,40016=>1000,40018=>1000,40020=>1000,40021=>1000,40022=>1000,40023=>1000,40024=>1000,40025=>1000,40026=>1000, -40030=>1000,40031=>1000,40032=>1000,40034=>1000,40035=>1000,40038=>1000,40039=>1000,40040=>1000,40045=>1000,40046=>1000, -40049=>1000,40051=>1000,40052=>1000,40053=>1000,40054=>1000,40055=>1000,40056=>1000,40057=>1000,40058=>1000,40060=>1000, -40063=>1000,40065=>1000,40066=>1000,40069=>1000,40070=>1000,40071=>1000,40072=>1000,40075=>1000,40077=>1000,40078=>1000, -40080=>1000,40081=>1000,40082=>1000,40084=>1000,40085=>1000,40090=>1000,40091=>1000,40092=>1000,40094=>1000,40095=>1000, -40096=>1000,40097=>1000,40098=>1000,40099=>1000,40100=>1000,40101=>1000,40102=>1000,40103=>1000,40104=>1000,40105=>1000, -40107=>1000,40109=>1000,40110=>1000,40112=>1000,40113=>1000,40114=>1000,40115=>1000,40116=>1000,40117=>1000,40118=>1000, -40119=>1000,40120=>1000,40122=>1000,40123=>1000,40124=>1000,40125=>1000,40131=>1000,40132=>1000,40133=>1000,40134=>1000, -40135=>1000,40138=>1000,40139=>1000,40140=>1000,40141=>1000,40142=>1000,40143=>1000,40144=>1000,40147=>1000,40148=>1000, -40149=>1000,40150=>1000,40151=>1000,40152=>1000,40153=>1000,40156=>1000,40157=>1000,40158=>1000,40159=>1000,40162=>1000, -40165=>1000,40166=>1000,40167=>1000,40169=>1000,40170=>1000,40171=>1000,40172=>1000,40173=>1000,40176=>1000,40177=>1000, -40178=>1000,40179=>1000,40180=>1000,40181=>1000,40182=>1000,40183=>1000,40185=>1000,40186=>1000,40187=>1000,40188=>1000, -40189=>1000,40191=>1000,40192=>1000,40195=>1000,40196=>1000,40197=>1000,40198=>1000,40199=>1000,40200=>1000,40201=>1000, -40206=>1000,40208=>1000,40210=>1000,40212=>1000,40213=>1000,40215=>1000,40216=>1000,40217=>1000,40219=>1000,40221=>1000, -40222=>1000,40223=>1000,40224=>1000,40226=>1000,40227=>1000,40229=>1000,40230=>1000,40232=>1000,40233=>1000,40234=>1000, -40235=>1000,40236=>1000,40237=>1000,40238=>1000,40239=>1000,40240=>1000,40241=>1000,40243=>1000,40246=>1000,40247=>1000, -40248=>1000,40251=>1000,40253=>1000,40254=>1000,40255=>1000,40256=>1000,40257=>1000,40258=>1000,40259=>1000,40260=>1000, -40261=>1000,40262=>1000,40264=>1000,40266=>1000,40267=>1000,40268=>1000,40271=>1000,40272=>1000,40273=>1000,40274=>1000, -40275=>1000,40276=>1000,40278=>1000,40279=>1000,40280=>1000,40281=>1000,40282=>1000,40283=>1000,40284=>1000,40285=>1000, -40286=>1000,40287=>1000,40288=>1000,40289=>1000,40292=>1000,40295=>1000,40296=>1000,40297=>1000,40298=>1000,40299=>1000, -40300=>1000,40303=>1000,40304=>1000,40305=>1000,40306=>1000,40307=>1000,40308=>1000,40309=>1000,40311=>1000,40312=>1000, -40313=>1000,40314=>1000,40315=>1000,40317=>1000,40319=>1000,40320=>1000,40321=>1000,40322=>1000,40324=>1000,40325=>1000, -40326=>1000,40327=>1000,40328=>1000,40329=>1000,40330=>1000,40331=>1000,40332=>1000,40335=>1000,40336=>1000,40338=>1000, -40340=>1000,40342=>1000,40343=>1000,40344=>1000,40345=>1000,40346=>1000,40347=>1000,40348=>1000,40349=>1000,40350=>1000, -40351=>1000,40352=>1000,40353=>1000,40354=>1000,40355=>1000,40356=>1000,40358=>1000,40359=>1000,40360=>1000,40361=>1000, -40362=>1000,40363=>1000,40364=>1000,40365=>1000,40367=>1000,40369=>1000,40370=>1000,40371=>1000,40372=>1000,40373=>1000, -40374=>1000,40375=>1000,40376=>1000,40377=>1000,40378=>1000,40379=>1000,40380=>1000,40382=>1000,40383=>1000,40385=>1000, -40386=>1000,40387=>1000,40388=>1000,40389=>1000,40390=>1000,40391=>1000,40392=>1000,40394=>1000,40395=>1000,40396=>1000, -40397=>1000,40398=>1000,40399=>1000,40400=>1000,40401=>1000,40402=>1000,40403=>1000,40405=>1000,40406=>1000,40407=>1000, -40408=>1000,40409=>1000,40410=>1000,40411=>1000,40412=>1000,40413=>1000,40414=>1000,40415=>1000,40417=>1000,40418=>1000, -40419=>1000,40420=>1000,40421=>1000,40422=>1000,40424=>1000,40425=>1000,40427=>1000,40428=>1000,40429=>1000,40430=>1000, -40431=>1000,40432=>1000,40434=>1000,40435=>1000,40436=>1000,40437=>1000,40438=>1000,40439=>1000,40440=>1000,40441=>1000, -40442=>1000,40443=>1000,40445=>1000,40446=>1000,40447=>1000,40448=>1000,40449=>1000,40450=>1000,40451=>1000,40452=>1000, -40453=>1000,40454=>1000,40455=>1000,40457=>1000,40459=>1000,40461=>1000,40463=>1000,40464=>1000,40465=>1000,40466=>1000, -40467=>1000,40468=>1000,40469=>1000,40471=>1000,40473=>1000,40474=>1000,40475=>1000,40477=>1000,40478=>1000,40479=>1000, -40480=>1000,40481=>1000,40482=>1000,40483=>1000,40485=>1000,40486=>1000,40488=>1000,40489=>1000,40490=>1000,40491=>1000, -40492=>1000,40493=>1000,40495=>1000,40497=>1000,40498=>1000,40499=>1000,40501=>1000,40502=>1000,40503=>1000,40504=>1000, -40505=>1000,40506=>1000,40509=>1000,40510=>1000,40511=>1000,40513=>1000,40514=>1000,40515=>1000,40516=>1000,40517=>1000, -40518=>1000,40519=>1000,40520=>1000,40521=>1000,40522=>1000,40523=>1000,40524=>1000,40526=>1000,40527=>1000,40529=>1000, -40533=>1000,40535=>1000,40536=>1000,40538=>1000,40539=>1000,40540=>1000,40542=>1000,40547=>1000,40548=>1000,40550=>1000, -40551=>1000,40552=>1000,40553=>1000,40554=>1000,40555=>1000,40556=>1000,40557=>1000,40560=>1000,40561=>1000,40563=>1000, -40565=>1000,40568=>1000,40569=>1000,40570=>1000,40572=>1000,40573=>1000,40574=>1000,40575=>1000,40576=>1000,40577=>1000, -40578=>1000,40579=>1000,40582=>1000,40583=>1000,40584=>1000,40585=>1000,40586=>1000,40587=>1000,40588=>1000,40589=>1000, -40590=>1000,40593=>1000,40594=>1000,40595=>1000,40596=>1000,40597=>1000,40599=>1000,40601=>1000,40602=>1000,40603=>1000, -40604=>1000,40605=>1000,40607=>1000,40608=>1000,40609=>1000,40612=>1000,40613=>1000,40614=>1000,40615=>1000,40617=>1000, -40618=>1000,40621=>1000,40622=>1000,40624=>1000,40628=>1000,40629=>1000,40630=>1000,40631=>1000,40632=>1000,40633=>1000, -40634=>1000,40635=>1000,40636=>1000,40637=>1000,40638=>1000,40639=>1000,40640=>1000,40642=>1000,40643=>1000,40644=>1000, -40648=>1000,40649=>1000,40652=>1000,40653=>1000,40654=>1000,40655=>1000,40656=>1000,40657=>1000,40658=>1000,40659=>1000, -40660=>1000,40661=>1000,40662=>1000,40664=>1000,40665=>1000,40666=>1000,40667=>1000,40668=>1000,40669=>1000,40670=>1000, -40671=>1000,40672=>1000,40674=>1000,40676=>1000,40677=>1000,40678=>1000,40679=>1000,40680=>1000,40681=>1000,40682=>1000, -40683=>1000,40685=>1000,40686=>1000,40687=>1000,40688=>1000,40690=>1000,40691=>1000,40692=>1000,40693=>1000,40694=>1000, -40695=>1000,40697=>1000,40698=>1000,40699=>1000,40700=>1000,40701=>1000,40702=>1000,40703=>1000,40704=>1000,40705=>1000, -40710=>1000,40711=>1000,40712=>1000,40713=>1000,40714=>1000,40715=>1000,40717=>1000,40718=>1000,40719=>1000,40720=>1000, -40722=>1000,40723=>1000,40725=>1000,40726=>1000,40727=>1000,40728=>1000,40729=>1000,40730=>1000,40731=>1000,40732=>1000, -40734=>1000,40736=>1000,40737=>1000,40738=>1000,40739=>1000,40740=>1000,40741=>1000,40744=>1000,40745=>1000,40746=>1000, -40747=>1000,40748=>1000,40749=>1000,40750=>1000,40751=>1000,40752=>1000,40753=>1000,40754=>1000,40755=>1000,40756=>1000, -40757=>1000,40758=>1000,40759=>1000,40760=>1000,40761=>1000,40763=>1000,40765=>1000,40766=>1000,40768=>1000,40769=>1000, -40770=>1000,40771=>1000,40772=>1000,40774=>1000,40775=>1000,40776=>1000,40777=>1000,40778=>1000,40779=>1000,40780=>1000, -40781=>1000,40782=>1000,40783=>1000,40784=>1000,40785=>1000,40786=>1000,40788=>1000,40789=>1000,40790=>1000,40791=>1000, -40792=>1000,40793=>1000,40795=>1000,40796=>1000,40797=>1000,40798=>1000,40799=>1000,40800=>1000,40801=>1000,40802=>1000, -40803=>1000,40804=>1000,40805=>1000,40806=>1000,40807=>1000,40810=>1000,40811=>1000,40812=>1000,40814=>1000,40815=>1000, -40816=>1000,40817=>1000,40818=>1000,40820=>1000,40821=>1000,40822=>1000,40823=>1000,40824=>1000,40825=>1000,40826=>1000, -40827=>1000,40830=>1000,40831=>1000,40832=>1000,40835=>1000,40836=>1000,40837=>1000,40838=>1000,40839=>1000,40840=>1000, -40841=>1000,40842=>1000,40843=>1000,40844=>1000,40845=>1000,40848=>1000,40849=>1000,40850=>1000,40852=>1000,40853=>1000, -40856=>1000,40857=>1000,40858=>1000,40859=>1000,40860=>1000,40861=>1000,40863=>1000,40864=>1000,40866=>1000,40868=>1000, -44032=>1000,44033=>1000,44034=>1000,44035=>1000,44036=>1000,44037=>1000,44038=>1000,44039=>1000,44040=>1000,44041=>1000, -44042=>1000,44043=>1000,44044=>1000,44045=>1000,44046=>1000,44047=>1000,44048=>1000,44049=>1000,44050=>1000,44051=>1000, -44052=>1000,44053=>1000,44054=>1000,44055=>1000,44056=>1000,44057=>1000,44058=>1000,44059=>1000,44060=>1000,44061=>1000, -44062=>1000,44063=>1000,44064=>1000,44065=>1000,44066=>1000,44067=>1000,44068=>1000,44069=>1000,44070=>1000,44071=>1000, -44072=>1000,44073=>1000,44074=>1000,44075=>1000,44076=>1000,44077=>1000,44078=>1000,44079=>1000,44080=>1000,44081=>1000, -44082=>1000,44083=>1000,44084=>1000,44085=>1000,44086=>1000,44087=>1000,44088=>1000,44089=>1000,44090=>1000,44091=>1000, -44092=>1000,44093=>1000,44094=>1000,44095=>1000,44096=>1000,44097=>1000,44098=>1000,44099=>1000,44100=>1000,44101=>1000, -44102=>1000,44103=>1000,44104=>1000,44105=>1000,44106=>1000,44107=>1000,44108=>1000,44109=>1000,44110=>1000,44111=>1000, -44112=>1000,44113=>1000,44114=>1000,44115=>1000,44116=>1000,44117=>1000,44118=>1000,44119=>1000,44120=>1000,44121=>1000, -44122=>1000,44123=>1000,44124=>1000,44125=>1000,44126=>1000,44127=>1000,44128=>1000,44129=>1000,44130=>1000,44131=>1000, -44132=>1000,44133=>1000,44134=>1000,44135=>1000,44136=>1000,44137=>1000,44138=>1000,44139=>1000,44140=>1000,44141=>1000, -44142=>1000,44143=>1000,44144=>1000,44145=>1000,44146=>1000,44147=>1000,44148=>1000,44149=>1000,44150=>1000,44151=>1000, -44152=>1000,44153=>1000,44154=>1000,44155=>1000,44156=>1000,44157=>1000,44158=>1000,44159=>1000,44160=>1000,44161=>1000, -44162=>1000,44163=>1000,44164=>1000,44165=>1000,44166=>1000,44167=>1000,44168=>1000,44169=>1000,44170=>1000,44171=>1000, -44172=>1000,44173=>1000,44174=>1000,44175=>1000,44176=>1000,44177=>1000,44178=>1000,44179=>1000,44180=>1000,44181=>1000, -44182=>1000,44183=>1000,44184=>1000,44185=>1000,44186=>1000,44187=>1000,44188=>1000,44189=>1000,44190=>1000,44191=>1000, -44192=>1000,44193=>1000,44194=>1000,44195=>1000,44196=>1000,44197=>1000,44198=>1000,44199=>1000,44200=>1000,44201=>1000, -44202=>1000,44203=>1000,44204=>1000,44205=>1000,44206=>1000,44207=>1000,44208=>1000,44209=>1000,44210=>1000,44211=>1000, -44212=>1000,44213=>1000,44214=>1000,44215=>1000,44216=>1000,44217=>1000,44218=>1000,44219=>1000,44220=>1000,44221=>1000, -44222=>1000,44223=>1000,44224=>1000,44225=>1000,44226=>1000,44227=>1000,44228=>1000,44229=>1000,44230=>1000,44231=>1000, -44232=>1000,44233=>1000,44234=>1000,44235=>1000,44236=>1000,44237=>1000,44238=>1000,44239=>1000,44240=>1000,44241=>1000, -44242=>1000,44243=>1000,44244=>1000,44245=>1000,44246=>1000,44247=>1000,44248=>1000,44249=>1000,44250=>1000,44251=>1000, -44252=>1000,44253=>1000,44254=>1000,44255=>1000,44256=>1000,44257=>1000,44258=>1000,44259=>1000,44260=>1000,44261=>1000, -44262=>1000,44263=>1000,44264=>1000,44265=>1000,44266=>1000,44267=>1000,44268=>1000,44269=>1000,44270=>1000,44271=>1000, -44272=>1000,44273=>1000,44274=>1000,44275=>1000,44276=>1000,44277=>1000,44278=>1000,44279=>1000,44280=>1000,44281=>1000, -44282=>1000,44283=>1000,44284=>1000,44285=>1000,44286=>1000,44287=>1000,44288=>1000,44289=>1000,44290=>1000,44291=>1000, -44292=>1000,44293=>1000,44294=>1000,44295=>1000,44296=>1000,44297=>1000,44298=>1000,44299=>1000,44300=>1000,44301=>1000, -44302=>1000,44303=>1000,44304=>1000,44305=>1000,44306=>1000,44307=>1000,44308=>1000,44309=>1000,44310=>1000,44311=>1000, -44312=>1000,44313=>1000,44314=>1000,44315=>1000,44316=>1000,44317=>1000,44318=>1000,44319=>1000,44320=>1000,44321=>1000, -44322=>1000,44323=>1000,44324=>1000,44325=>1000,44326=>1000,44327=>1000,44328=>1000,44329=>1000,44330=>1000,44331=>1000, -44332=>1000,44333=>1000,44334=>1000,44335=>1000,44336=>1000,44337=>1000,44338=>1000,44339=>1000,44340=>1000,44341=>1000, -44342=>1000,44343=>1000,44344=>1000,44345=>1000,44346=>1000,44347=>1000,44348=>1000,44349=>1000,44350=>1000,44351=>1000, -44352=>1000,44353=>1000,44354=>1000,44355=>1000,44356=>1000,44357=>1000,44358=>1000,44359=>1000,44360=>1000,44361=>1000, -44362=>1000,44363=>1000,44364=>1000,44365=>1000,44366=>1000,44367=>1000,44368=>1000,44369=>1000,44370=>1000,44371=>1000, -44372=>1000,44373=>1000,44374=>1000,44375=>1000,44376=>1000,44377=>1000,44378=>1000,44379=>1000,44380=>1000,44381=>1000, -44382=>1000,44383=>1000,44384=>1000,44385=>1000,44386=>1000,44387=>1000,44388=>1000,44389=>1000,44390=>1000,44391=>1000, -44392=>1000,44393=>1000,44394=>1000,44395=>1000,44396=>1000,44397=>1000,44398=>1000,44399=>1000,44400=>1000,44401=>1000, -44402=>1000,44403=>1000,44404=>1000,44405=>1000,44406=>1000,44407=>1000,44408=>1000,44409=>1000,44410=>1000,44411=>1000, -44412=>1000,44413=>1000,44414=>1000,44415=>1000,44416=>1000,44417=>1000,44418=>1000,44419=>1000,44420=>1000,44421=>1000, -44422=>1000,44423=>1000,44424=>1000,44425=>1000,44426=>1000,44427=>1000,44428=>1000,44429=>1000,44430=>1000,44431=>1000, -44432=>1000,44433=>1000,44434=>1000,44435=>1000,44436=>1000,44437=>1000,44438=>1000,44439=>1000,44440=>1000,44441=>1000, -44442=>1000,44443=>1000,44444=>1000,44445=>1000,44446=>1000,44447=>1000,44448=>1000,44449=>1000,44450=>1000,44451=>1000, -44452=>1000,44453=>1000,44454=>1000,44455=>1000,44456=>1000,44457=>1000,44458=>1000,44459=>1000,44460=>1000,44461=>1000, -44462=>1000,44463=>1000,44464=>1000,44465=>1000,44466=>1000,44467=>1000,44468=>1000,44469=>1000,44470=>1000,44471=>1000, -44472=>1000,44473=>1000,44474=>1000,44475=>1000,44476=>1000,44477=>1000,44478=>1000,44479=>1000,44480=>1000,44481=>1000, -44482=>1000,44483=>1000,44484=>1000,44485=>1000,44486=>1000,44487=>1000,44488=>1000,44489=>1000,44490=>1000,44491=>1000, -44492=>1000,44493=>1000,44494=>1000,44495=>1000,44496=>1000,44497=>1000,44498=>1000,44499=>1000,44500=>1000,44501=>1000, -44502=>1000,44503=>1000,44504=>1000,44505=>1000,44506=>1000,44507=>1000,44508=>1000,44509=>1000,44510=>1000,44511=>1000, -44512=>1000,44513=>1000,44514=>1000,44515=>1000,44516=>1000,44517=>1000,44518=>1000,44519=>1000,44520=>1000,44521=>1000, -44522=>1000,44523=>1000,44524=>1000,44525=>1000,44526=>1000,44527=>1000,44528=>1000,44529=>1000,44530=>1000,44531=>1000, -44532=>1000,44533=>1000,44534=>1000,44535=>1000,44536=>1000,44537=>1000,44538=>1000,44539=>1000,44540=>1000,44541=>1000, -44542=>1000,44543=>1000,44544=>1000,44545=>1000,44546=>1000,44547=>1000,44548=>1000,44549=>1000,44550=>1000,44551=>1000, -44552=>1000,44553=>1000,44554=>1000,44555=>1000,44556=>1000,44557=>1000,44558=>1000,44559=>1000,44560=>1000,44561=>1000, -44562=>1000,44563=>1000,44564=>1000,44565=>1000,44566=>1000,44567=>1000,44568=>1000,44569=>1000,44570=>1000,44571=>1000, -44572=>1000,44573=>1000,44574=>1000,44575=>1000,44576=>1000,44577=>1000,44578=>1000,44579=>1000,44580=>1000,44581=>1000, -44582=>1000,44583=>1000,44584=>1000,44585=>1000,44586=>1000,44587=>1000,44588=>1000,44589=>1000,44590=>1000,44591=>1000, -44592=>1000,44593=>1000,44594=>1000,44595=>1000,44596=>1000,44597=>1000,44598=>1000,44599=>1000,44600=>1000,44601=>1000, -44602=>1000,44603=>1000,44604=>1000,44605=>1000,44606=>1000,44607=>1000,44608=>1000,44609=>1000,44610=>1000,44611=>1000, -44612=>1000,44613=>1000,44614=>1000,44615=>1000,44616=>1000,44617=>1000,44618=>1000,44619=>1000,44620=>1000,44621=>1000, -44622=>1000,44623=>1000,44624=>1000,44625=>1000,44626=>1000,44627=>1000,44628=>1000,44629=>1000,44630=>1000,44631=>1000, -44632=>1000,44633=>1000,44634=>1000,44635=>1000,44636=>1000,44637=>1000,44638=>1000,44639=>1000,44640=>1000,44641=>1000, -44642=>1000,44643=>1000,44644=>1000,44645=>1000,44646=>1000,44647=>1000,44648=>1000,44649=>1000,44650=>1000,44651=>1000, -44652=>1000,44653=>1000,44654=>1000,44655=>1000,44656=>1000,44657=>1000,44658=>1000,44659=>1000,44660=>1000,44661=>1000, -44662=>1000,44663=>1000,44664=>1000,44665=>1000,44666=>1000,44667=>1000,44668=>1000,44669=>1000,44670=>1000,44671=>1000, -44672=>1000,44673=>1000,44674=>1000,44675=>1000,44676=>1000,44677=>1000,44678=>1000,44679=>1000,44680=>1000,44681=>1000, -44682=>1000,44683=>1000,44684=>1000,44685=>1000,44686=>1000,44687=>1000,44688=>1000,44689=>1000,44690=>1000,44691=>1000, -44692=>1000,44693=>1000,44694=>1000,44695=>1000,44696=>1000,44697=>1000,44698=>1000,44699=>1000,44700=>1000,44701=>1000, -44702=>1000,44703=>1000,44704=>1000,44705=>1000,44706=>1000,44707=>1000,44708=>1000,44709=>1000,44710=>1000,44711=>1000, -44712=>1000,44713=>1000,44714=>1000,44715=>1000,44716=>1000,44717=>1000,44718=>1000,44719=>1000,44720=>1000,44721=>1000, -44722=>1000,44723=>1000,44724=>1000,44725=>1000,44726=>1000,44727=>1000,44728=>1000,44729=>1000,44730=>1000,44731=>1000, -44732=>1000,44733=>1000,44734=>1000,44735=>1000,44736=>1000,44737=>1000,44738=>1000,44739=>1000,44740=>1000,44741=>1000, -44742=>1000,44743=>1000,44744=>1000,44745=>1000,44746=>1000,44747=>1000,44748=>1000,44749=>1000,44750=>1000,44751=>1000, -44752=>1000,44753=>1000,44754=>1000,44755=>1000,44756=>1000,44757=>1000,44758=>1000,44759=>1000,44760=>1000,44761=>1000, -44762=>1000,44763=>1000,44764=>1000,44765=>1000,44766=>1000,44767=>1000,44768=>1000,44769=>1000,44770=>1000,44771=>1000, -44772=>1000,44773=>1000,44774=>1000,44775=>1000,44776=>1000,44777=>1000,44778=>1000,44779=>1000,44780=>1000,44781=>1000, -44782=>1000,44783=>1000,44784=>1000,44785=>1000,44786=>1000,44787=>1000,44788=>1000,44789=>1000,44790=>1000,44791=>1000, -44792=>1000,44793=>1000,44794=>1000,44795=>1000,44796=>1000,44797=>1000,44798=>1000,44799=>1000,44800=>1000,44801=>1000, -44802=>1000,44803=>1000,44804=>1000,44805=>1000,44806=>1000,44807=>1000,44808=>1000,44809=>1000,44810=>1000,44811=>1000, -44812=>1000,44813=>1000,44814=>1000,44815=>1000,44816=>1000,44817=>1000,44818=>1000,44819=>1000,44820=>1000,44821=>1000, -44822=>1000,44823=>1000,44824=>1000,44825=>1000,44826=>1000,44827=>1000,44828=>1000,44829=>1000,44830=>1000,44831=>1000, -44832=>1000,44833=>1000,44834=>1000,44835=>1000,44836=>1000,44837=>1000,44838=>1000,44839=>1000,44840=>1000,44841=>1000, -44842=>1000,44843=>1000,44844=>1000,44845=>1000,44846=>1000,44847=>1000,44848=>1000,44849=>1000,44850=>1000,44851=>1000, -44852=>1000,44853=>1000,44854=>1000,44855=>1000,44856=>1000,44857=>1000,44858=>1000,44859=>1000,44860=>1000,44861=>1000, -44862=>1000,44863=>1000,44864=>1000,44865=>1000,44866=>1000,44867=>1000,44868=>1000,44869=>1000,44870=>1000,44871=>1000, -44872=>1000,44873=>1000,44874=>1000,44875=>1000,44876=>1000,44877=>1000,44878=>1000,44879=>1000,44880=>1000,44881=>1000, -44882=>1000,44883=>1000,44884=>1000,44885=>1000,44886=>1000,44887=>1000,44888=>1000,44889=>1000,44890=>1000,44891=>1000, -44892=>1000,44893=>1000,44894=>1000,44895=>1000,44896=>1000,44897=>1000,44898=>1000,44899=>1000,44900=>1000,44901=>1000, -44902=>1000,44903=>1000,44904=>1000,44905=>1000,44906=>1000,44907=>1000,44908=>1000,44909=>1000,44910=>1000,44911=>1000, -44912=>1000,44913=>1000,44914=>1000,44915=>1000,44916=>1000,44917=>1000,44918=>1000,44919=>1000,44920=>1000,44921=>1000, -44922=>1000,44923=>1000,44924=>1000,44925=>1000,44926=>1000,44927=>1000,44928=>1000,44929=>1000,44930=>1000,44931=>1000, -44932=>1000,44933=>1000,44934=>1000,44935=>1000,44936=>1000,44937=>1000,44938=>1000,44939=>1000,44940=>1000,44941=>1000, -44942=>1000,44943=>1000,44944=>1000,44945=>1000,44946=>1000,44947=>1000,44948=>1000,44949=>1000,44950=>1000,44951=>1000, -44952=>1000,44953=>1000,44954=>1000,44955=>1000,44956=>1000,44957=>1000,44958=>1000,44959=>1000,44960=>1000,44961=>1000, -44962=>1000,44963=>1000,44964=>1000,44965=>1000,44966=>1000,44967=>1000,44968=>1000,44969=>1000,44970=>1000,44971=>1000, -44972=>1000,44973=>1000,44974=>1000,44975=>1000,44976=>1000,44977=>1000,44978=>1000,44979=>1000,44980=>1000,44981=>1000, -44982=>1000,44983=>1000,44984=>1000,44985=>1000,44986=>1000,44987=>1000,44988=>1000,44989=>1000,44990=>1000,44991=>1000, -44992=>1000,44993=>1000,44994=>1000,44995=>1000,44996=>1000,44997=>1000,44998=>1000,44999=>1000,45000=>1000,45001=>1000, -45002=>1000,45003=>1000,45004=>1000,45005=>1000,45006=>1000,45007=>1000,45008=>1000,45009=>1000,45010=>1000,45011=>1000, -45012=>1000,45013=>1000,45014=>1000,45015=>1000,45016=>1000,45017=>1000,45018=>1000,45019=>1000,45020=>1000,45021=>1000, -45022=>1000,45023=>1000,45024=>1000,45025=>1000,45026=>1000,45027=>1000,45028=>1000,45029=>1000,45030=>1000,45031=>1000, -45032=>1000,45033=>1000,45034=>1000,45035=>1000,45036=>1000,45037=>1000,45038=>1000,45039=>1000,45040=>1000,45041=>1000, -45042=>1000,45043=>1000,45044=>1000,45045=>1000,45046=>1000,45047=>1000,45048=>1000,45049=>1000,45050=>1000,45051=>1000, -45052=>1000,45053=>1000,45054=>1000,45055=>1000,45056=>1000,45057=>1000,45058=>1000,45059=>1000,45060=>1000,45061=>1000, -45062=>1000,45063=>1000,45064=>1000,45065=>1000,45066=>1000,45067=>1000,45068=>1000,45069=>1000,45070=>1000,45071=>1000, -45072=>1000,45073=>1000,45074=>1000,45075=>1000,45076=>1000,45077=>1000,45078=>1000,45079=>1000,45080=>1000,45081=>1000, -45082=>1000,45083=>1000,45084=>1000,45085=>1000,45086=>1000,45087=>1000,45088=>1000,45089=>1000,45090=>1000,45091=>1000, -45092=>1000,45093=>1000,45094=>1000,45095=>1000,45096=>1000,45097=>1000,45098=>1000,45099=>1000,45100=>1000,45101=>1000, -45102=>1000,45103=>1000,45104=>1000,45105=>1000,45106=>1000,45107=>1000,45108=>1000,45109=>1000,45110=>1000,45111=>1000, -45112=>1000,45113=>1000,45114=>1000,45115=>1000,45116=>1000,45117=>1000,45118=>1000,45119=>1000,45120=>1000,45121=>1000, -45122=>1000,45123=>1000,45124=>1000,45125=>1000,45126=>1000,45127=>1000,45128=>1000,45129=>1000,45130=>1000,45131=>1000, -45132=>1000,45133=>1000,45134=>1000,45135=>1000,45136=>1000,45137=>1000,45138=>1000,45139=>1000,45140=>1000,45141=>1000, -45142=>1000,45143=>1000,45144=>1000,45145=>1000,45146=>1000,45147=>1000,45148=>1000,45149=>1000,45150=>1000,45151=>1000, -45152=>1000,45153=>1000,45154=>1000,45155=>1000,45156=>1000,45157=>1000,45158=>1000,45159=>1000,45160=>1000,45161=>1000, -45162=>1000,45163=>1000,45164=>1000,45165=>1000,45166=>1000,45167=>1000,45168=>1000,45169=>1000,45170=>1000,45171=>1000, -45172=>1000,45173=>1000,45174=>1000,45175=>1000,45176=>1000,45177=>1000,45178=>1000,45179=>1000,45180=>1000,45181=>1000, -45182=>1000,45183=>1000,45184=>1000,45185=>1000,45186=>1000,45187=>1000,45188=>1000,45189=>1000,45190=>1000,45191=>1000, -45192=>1000,45193=>1000,45194=>1000,45195=>1000,45196=>1000,45197=>1000,45198=>1000,45199=>1000,45200=>1000,45201=>1000, -45202=>1000,45203=>1000,45204=>1000,45205=>1000,45206=>1000,45207=>1000,45208=>1000,45209=>1000,45210=>1000,45211=>1000, -45212=>1000,45213=>1000,45214=>1000,45215=>1000,45216=>1000,45217=>1000,45218=>1000,45219=>1000,45220=>1000,45221=>1000, -45222=>1000,45223=>1000,45224=>1000,45225=>1000,45226=>1000,45227=>1000,45228=>1000,45229=>1000,45230=>1000,45231=>1000, -45232=>1000,45233=>1000,45234=>1000,45235=>1000,45236=>1000,45237=>1000,45238=>1000,45239=>1000,45240=>1000,45241=>1000, -45242=>1000,45243=>1000,45244=>1000,45245=>1000,45246=>1000,45247=>1000,45248=>1000,45249=>1000,45250=>1000,45251=>1000, -45252=>1000,45253=>1000,45254=>1000,45255=>1000,45256=>1000,45257=>1000,45258=>1000,45259=>1000,45260=>1000,45261=>1000, -45262=>1000,45263=>1000,45264=>1000,45265=>1000,45266=>1000,45267=>1000,45268=>1000,45269=>1000,45270=>1000,45271=>1000, -45272=>1000,45273=>1000,45274=>1000,45275=>1000,45276=>1000,45277=>1000,45278=>1000,45279=>1000,45280=>1000,45281=>1000, -45282=>1000,45283=>1000,45284=>1000,45285=>1000,45286=>1000,45287=>1000,45288=>1000,45289=>1000,45290=>1000,45291=>1000, -45292=>1000,45293=>1000,45294=>1000,45295=>1000,45296=>1000,45297=>1000,45298=>1000,45299=>1000,45300=>1000,45301=>1000, -45302=>1000,45303=>1000,45304=>1000,45305=>1000,45306=>1000,45307=>1000,45308=>1000,45309=>1000,45310=>1000,45311=>1000, -45312=>1000,45313=>1000,45314=>1000,45315=>1000,45316=>1000,45317=>1000,45318=>1000,45319=>1000,45320=>1000,45321=>1000, -45322=>1000,45323=>1000,45324=>1000,45325=>1000,45326=>1000,45327=>1000,45328=>1000,45329=>1000,45330=>1000,45331=>1000, -45332=>1000,45333=>1000,45334=>1000,45335=>1000,45336=>1000,45337=>1000,45338=>1000,45339=>1000,45340=>1000,45341=>1000, -45342=>1000,45343=>1000,45344=>1000,45345=>1000,45346=>1000,45347=>1000,45348=>1000,45349=>1000,45350=>1000,45351=>1000, -45352=>1000,45353=>1000,45354=>1000,45355=>1000,45356=>1000,45357=>1000,45358=>1000,45359=>1000,45360=>1000,45361=>1000, -45362=>1000,45363=>1000,45364=>1000,45365=>1000,45366=>1000,45367=>1000,45368=>1000,45369=>1000,45370=>1000,45371=>1000, -45372=>1000,45373=>1000,45374=>1000,45375=>1000,45376=>1000,45377=>1000,45378=>1000,45379=>1000,45380=>1000,45381=>1000, -45382=>1000,45383=>1000,45384=>1000,45385=>1000,45386=>1000,45387=>1000,45388=>1000,45389=>1000,45390=>1000,45391=>1000, -45392=>1000,45393=>1000,45394=>1000,45395=>1000,45396=>1000,45397=>1000,45398=>1000,45399=>1000,45400=>1000,45401=>1000, -45402=>1000,45403=>1000,45404=>1000,45405=>1000,45406=>1000,45407=>1000,45408=>1000,45409=>1000,45410=>1000,45411=>1000, -45412=>1000,45413=>1000,45414=>1000,45415=>1000,45416=>1000,45417=>1000,45418=>1000,45419=>1000,45420=>1000,45421=>1000, -45422=>1000,45423=>1000,45424=>1000,45425=>1000,45426=>1000,45427=>1000,45428=>1000,45429=>1000,45430=>1000,45431=>1000, -45432=>1000,45433=>1000,45434=>1000,45435=>1000,45436=>1000,45437=>1000,45438=>1000,45439=>1000,45440=>1000,45441=>1000, -45442=>1000,45443=>1000,45444=>1000,45445=>1000,45446=>1000,45447=>1000,45448=>1000,45449=>1000,45450=>1000,45451=>1000, -45452=>1000,45453=>1000,45454=>1000,45455=>1000,45456=>1000,45457=>1000,45458=>1000,45459=>1000,45460=>1000,45461=>1000, -45462=>1000,45463=>1000,45464=>1000,45465=>1000,45466=>1000,45467=>1000,45468=>1000,45469=>1000,45470=>1000,45471=>1000, -45472=>1000,45473=>1000,45474=>1000,45475=>1000,45476=>1000,45477=>1000,45478=>1000,45479=>1000,45480=>1000,45481=>1000, -45482=>1000,45483=>1000,45484=>1000,45485=>1000,45486=>1000,45487=>1000,45488=>1000,45489=>1000,45490=>1000,45491=>1000, -45492=>1000,45493=>1000,45494=>1000,45495=>1000,45496=>1000,45497=>1000,45498=>1000,45499=>1000,45500=>1000,45501=>1000, -45502=>1000,45503=>1000,45504=>1000,45505=>1000,45506=>1000,45507=>1000,45508=>1000,45509=>1000,45510=>1000,45511=>1000, -45512=>1000,45513=>1000,45514=>1000,45515=>1000,45516=>1000,45517=>1000,45518=>1000,45519=>1000,45520=>1000,45521=>1000, -45522=>1000,45523=>1000,45524=>1000,45525=>1000,45526=>1000,45527=>1000,45528=>1000,45529=>1000,45530=>1000,45531=>1000, -45532=>1000,45533=>1000,45534=>1000,45535=>1000,45536=>1000,45537=>1000,45538=>1000,45539=>1000,45540=>1000,45541=>1000, -45542=>1000,45543=>1000,45544=>1000,45545=>1000,45546=>1000,45547=>1000,45548=>1000,45549=>1000,45550=>1000,45551=>1000, -45552=>1000,45553=>1000,45554=>1000,45555=>1000,45556=>1000,45557=>1000,45558=>1000,45559=>1000,45560=>1000,45561=>1000, -45562=>1000,45563=>1000,45564=>1000,45565=>1000,45566=>1000,45567=>1000,45568=>1000,45569=>1000,45570=>1000,45571=>1000, -45572=>1000,45573=>1000,45574=>1000,45575=>1000,45576=>1000,45577=>1000,45578=>1000,45579=>1000,45580=>1000,45581=>1000, -45582=>1000,45583=>1000,45584=>1000,45585=>1000,45586=>1000,45587=>1000,45588=>1000,45589=>1000,45590=>1000,45591=>1000, -45592=>1000,45593=>1000,45594=>1000,45595=>1000,45596=>1000,45597=>1000,45598=>1000,45599=>1000,45600=>1000,45601=>1000, -45602=>1000,45603=>1000,45604=>1000,45605=>1000,45606=>1000,45607=>1000,45608=>1000,45609=>1000,45610=>1000,45611=>1000, -45612=>1000,45613=>1000,45614=>1000,45615=>1000,45616=>1000,45617=>1000,45618=>1000,45619=>1000,45620=>1000,45621=>1000, -45622=>1000,45623=>1000,45624=>1000,45625=>1000,45626=>1000,45627=>1000,45628=>1000,45629=>1000,45630=>1000,45631=>1000, -45632=>1000,45633=>1000,45634=>1000,45635=>1000,45636=>1000,45637=>1000,45638=>1000,45639=>1000,45640=>1000,45641=>1000, -45642=>1000,45643=>1000,45644=>1000,45645=>1000,45646=>1000,45647=>1000,45648=>1000,45649=>1000,45650=>1000,45651=>1000, -45652=>1000,45653=>1000,45654=>1000,45655=>1000,45656=>1000,45657=>1000,45658=>1000,45659=>1000,45660=>1000,45661=>1000, -45662=>1000,45663=>1000,45664=>1000,45665=>1000,45666=>1000,45667=>1000,45668=>1000,45669=>1000,45670=>1000,45671=>1000, -45672=>1000,45673=>1000,45674=>1000,45675=>1000,45676=>1000,45677=>1000,45678=>1000,45679=>1000,45680=>1000,45681=>1000, -45682=>1000,45683=>1000,45684=>1000,45685=>1000,45686=>1000,45687=>1000,45688=>1000,45689=>1000,45690=>1000,45691=>1000, -45692=>1000,45693=>1000,45694=>1000,45695=>1000,45696=>1000,45697=>1000,45698=>1000,45699=>1000,45700=>1000,45701=>1000, -45702=>1000,45703=>1000,45704=>1000,45705=>1000,45706=>1000,45707=>1000,45708=>1000,45709=>1000,45710=>1000,45711=>1000, -45712=>1000,45713=>1000,45714=>1000,45715=>1000,45716=>1000,45717=>1000,45718=>1000,45719=>1000,45720=>1000,45721=>1000, -45722=>1000,45723=>1000,45724=>1000,45725=>1000,45726=>1000,45727=>1000,45728=>1000,45729=>1000,45730=>1000,45731=>1000, -45732=>1000,45733=>1000,45734=>1000,45735=>1000,45736=>1000,45737=>1000,45738=>1000,45739=>1000,45740=>1000,45741=>1000, -45742=>1000,45743=>1000,45744=>1000,45745=>1000,45746=>1000,45747=>1000,45748=>1000,45749=>1000,45750=>1000,45751=>1000, -45752=>1000,45753=>1000,45754=>1000,45755=>1000,45756=>1000,45757=>1000,45758=>1000,45759=>1000,45760=>1000,45761=>1000, -45762=>1000,45763=>1000,45764=>1000,45765=>1000,45766=>1000,45767=>1000,45768=>1000,45769=>1000,45770=>1000,45771=>1000, -45772=>1000,45773=>1000,45774=>1000,45775=>1000,45776=>1000,45777=>1000,45778=>1000,45779=>1000,45780=>1000,45781=>1000, -45782=>1000,45783=>1000,45784=>1000,45785=>1000,45786=>1000,45787=>1000,45788=>1000,45789=>1000,45790=>1000,45791=>1000, -45792=>1000,45793=>1000,45794=>1000,45795=>1000,45796=>1000,45797=>1000,45798=>1000,45799=>1000,45800=>1000,45801=>1000, -45802=>1000,45803=>1000,45804=>1000,45805=>1000,45806=>1000,45807=>1000,45808=>1000,45809=>1000,45810=>1000,45811=>1000, -45812=>1000,45813=>1000,45814=>1000,45815=>1000,45816=>1000,45817=>1000,45818=>1000,45819=>1000,45820=>1000,45821=>1000, -45822=>1000,45823=>1000,45824=>1000,45825=>1000,45826=>1000,45827=>1000,45828=>1000,45829=>1000,45830=>1000,45831=>1000, -45832=>1000,45833=>1000,45834=>1000,45835=>1000,45836=>1000,45837=>1000,45838=>1000,45839=>1000,45840=>1000,45841=>1000, -45842=>1000,45843=>1000,45844=>1000,45845=>1000,45846=>1000,45847=>1000,45848=>1000,45849=>1000,45850=>1000,45851=>1000, -45852=>1000,45853=>1000,45854=>1000,45855=>1000,45856=>1000,45857=>1000,45858=>1000,45859=>1000,45860=>1000,45861=>1000, -45862=>1000,45863=>1000,45864=>1000,45865=>1000,45866=>1000,45867=>1000,45868=>1000,45869=>1000,45870=>1000,45871=>1000, -45872=>1000,45873=>1000,45874=>1000,45875=>1000,45876=>1000,45877=>1000,45878=>1000,45879=>1000,45880=>1000,45881=>1000, -45882=>1000,45883=>1000,45884=>1000,45885=>1000,45886=>1000,45887=>1000,45888=>1000,45889=>1000,45890=>1000,45891=>1000, -45892=>1000,45893=>1000,45894=>1000,45895=>1000,45896=>1000,45897=>1000,45898=>1000,45899=>1000,45900=>1000,45901=>1000, -45902=>1000,45903=>1000,45904=>1000,45905=>1000,45906=>1000,45907=>1000,45908=>1000,45909=>1000,45910=>1000,45911=>1000, -45912=>1000,45913=>1000,45914=>1000,45915=>1000,45916=>1000,45917=>1000,45918=>1000,45919=>1000,45920=>1000,45921=>1000, -45922=>1000,45923=>1000,45924=>1000,45925=>1000,45926=>1000,45927=>1000,45928=>1000,45929=>1000,45930=>1000,45931=>1000, -45932=>1000,45933=>1000,45934=>1000,45935=>1000,45936=>1000,45937=>1000,45938=>1000,45939=>1000,45940=>1000,45941=>1000, -45942=>1000,45943=>1000,45944=>1000,45945=>1000,45946=>1000,45947=>1000,45948=>1000,45949=>1000,45950=>1000,45951=>1000, -45952=>1000,45953=>1000,45954=>1000,45955=>1000,45956=>1000,45957=>1000,45958=>1000,45959=>1000,45960=>1000,45961=>1000, -45962=>1000,45963=>1000,45964=>1000,45965=>1000,45966=>1000,45967=>1000,45968=>1000,45969=>1000,45970=>1000,45971=>1000, -45972=>1000,45973=>1000,45974=>1000,45975=>1000,45976=>1000,45977=>1000,45978=>1000,45979=>1000,45980=>1000,45981=>1000, -45982=>1000,45983=>1000,45984=>1000,45985=>1000,45986=>1000,45987=>1000,45988=>1000,45989=>1000,45990=>1000,45991=>1000, -45992=>1000,45993=>1000,45994=>1000,45995=>1000,45996=>1000,45997=>1000,45998=>1000,45999=>1000,46000=>1000,46001=>1000, -46002=>1000,46003=>1000,46004=>1000,46005=>1000,46006=>1000,46007=>1000,46008=>1000,46009=>1000,46010=>1000,46011=>1000, -46012=>1000,46013=>1000,46014=>1000,46015=>1000,46016=>1000,46017=>1000,46018=>1000,46019=>1000,46020=>1000,46021=>1000, -46022=>1000,46023=>1000,46024=>1000,46025=>1000,46026=>1000,46027=>1000,46028=>1000,46029=>1000,46030=>1000,46031=>1000, -46032=>1000,46033=>1000,46034=>1000,46035=>1000,46036=>1000,46037=>1000,46038=>1000,46039=>1000,46040=>1000,46041=>1000, -46042=>1000,46043=>1000,46044=>1000,46045=>1000,46046=>1000,46047=>1000,46048=>1000,46049=>1000,46050=>1000,46051=>1000, -46052=>1000,46053=>1000,46054=>1000,46055=>1000,46056=>1000,46057=>1000,46058=>1000,46059=>1000,46060=>1000,46061=>1000, -46062=>1000,46063=>1000,46064=>1000,46065=>1000,46066=>1000,46067=>1000,46068=>1000,46069=>1000,46070=>1000,46071=>1000, -46072=>1000,46073=>1000,46074=>1000,46075=>1000,46076=>1000,46077=>1000,46078=>1000,46079=>1000,46080=>1000,46081=>1000, -46082=>1000,46083=>1000,46084=>1000,46085=>1000,46086=>1000,46087=>1000,46088=>1000,46089=>1000,46090=>1000,46091=>1000, -46092=>1000,46093=>1000,46094=>1000,46095=>1000,46096=>1000,46097=>1000,46098=>1000,46099=>1000,46100=>1000,46101=>1000, -46102=>1000,46103=>1000,46104=>1000,46105=>1000,46106=>1000,46107=>1000,46108=>1000,46109=>1000,46110=>1000,46111=>1000, -46112=>1000,46113=>1000,46114=>1000,46115=>1000,46116=>1000,46117=>1000,46118=>1000,46119=>1000,46120=>1000,46121=>1000, -46122=>1000,46123=>1000,46124=>1000,46125=>1000,46126=>1000,46127=>1000,46128=>1000,46129=>1000,46130=>1000,46131=>1000, -46132=>1000,46133=>1000,46134=>1000,46135=>1000,46136=>1000,46137=>1000,46138=>1000,46139=>1000,46140=>1000,46141=>1000, -46142=>1000,46143=>1000,46144=>1000,46145=>1000,46146=>1000,46147=>1000,46148=>1000,46149=>1000,46150=>1000,46151=>1000, -46152=>1000,46153=>1000,46154=>1000,46155=>1000,46156=>1000,46157=>1000,46158=>1000,46159=>1000,46160=>1000,46161=>1000, -46162=>1000,46163=>1000,46164=>1000,46165=>1000,46166=>1000,46167=>1000,46168=>1000,46169=>1000,46170=>1000,46171=>1000, -46172=>1000,46173=>1000,46174=>1000,46175=>1000,46176=>1000,46177=>1000,46178=>1000,46179=>1000,46180=>1000,46181=>1000, -46182=>1000,46183=>1000,46184=>1000,46185=>1000,46186=>1000,46187=>1000,46188=>1000,46189=>1000,46190=>1000,46191=>1000, -46192=>1000,46193=>1000,46194=>1000,46195=>1000,46196=>1000,46197=>1000,46198=>1000,46199=>1000,46200=>1000,46201=>1000, -46202=>1000,46203=>1000,46204=>1000,46205=>1000,46206=>1000,46207=>1000,46208=>1000,46209=>1000,46210=>1000,46211=>1000, -46212=>1000,46213=>1000,46214=>1000,46215=>1000,46216=>1000,46217=>1000,46218=>1000,46219=>1000,46220=>1000,46221=>1000, -46222=>1000,46223=>1000,46224=>1000,46225=>1000,46226=>1000,46227=>1000,46228=>1000,46229=>1000,46230=>1000,46231=>1000, -46232=>1000,46233=>1000,46234=>1000,46235=>1000,46236=>1000,46237=>1000,46238=>1000,46239=>1000,46240=>1000,46241=>1000, -46242=>1000,46243=>1000,46244=>1000,46245=>1000,46246=>1000,46247=>1000,46248=>1000,46249=>1000,46250=>1000,46251=>1000, -46252=>1000,46253=>1000,46254=>1000,46255=>1000,46256=>1000,46257=>1000,46258=>1000,46259=>1000,46260=>1000,46261=>1000, -46262=>1000,46263=>1000,46264=>1000,46265=>1000,46266=>1000,46267=>1000,46268=>1000,46269=>1000,46270=>1000,46271=>1000, -46272=>1000,46273=>1000,46274=>1000,46275=>1000,46276=>1000,46277=>1000,46278=>1000,46279=>1000,46280=>1000,46281=>1000, -46282=>1000,46283=>1000,46284=>1000,46285=>1000,46286=>1000,46287=>1000,46288=>1000,46289=>1000,46290=>1000,46291=>1000, -46292=>1000,46293=>1000,46294=>1000,46295=>1000,46296=>1000,46297=>1000,46298=>1000,46299=>1000,46300=>1000,46301=>1000, -46302=>1000,46303=>1000,46304=>1000,46305=>1000,46306=>1000,46307=>1000,46308=>1000,46309=>1000,46310=>1000,46311=>1000, -46312=>1000,46313=>1000,46314=>1000,46315=>1000,46316=>1000,46317=>1000,46318=>1000,46319=>1000,46320=>1000,46321=>1000, -46322=>1000,46323=>1000,46324=>1000,46325=>1000,46326=>1000,46327=>1000,46328=>1000,46329=>1000,46330=>1000,46331=>1000, -46332=>1000,46333=>1000,46334=>1000,46335=>1000,46336=>1000,46337=>1000,46338=>1000,46339=>1000,46340=>1000,46341=>1000, -46342=>1000,46343=>1000,46344=>1000,46345=>1000,46346=>1000,46347=>1000,46348=>1000,46349=>1000,46350=>1000,46351=>1000, -46352=>1000,46353=>1000,46354=>1000,46355=>1000,46356=>1000,46357=>1000,46358=>1000,46359=>1000,46360=>1000,46361=>1000, -46362=>1000,46363=>1000,46364=>1000,46365=>1000,46366=>1000,46367=>1000,46368=>1000,46369=>1000,46370=>1000,46371=>1000, -46372=>1000,46373=>1000,46374=>1000,46375=>1000,46376=>1000,46377=>1000,46378=>1000,46379=>1000,46380=>1000,46381=>1000, -46382=>1000,46383=>1000,46384=>1000,46385=>1000,46386=>1000,46387=>1000,46388=>1000,46389=>1000,46390=>1000,46391=>1000, -46392=>1000,46393=>1000,46394=>1000,46395=>1000,46396=>1000,46397=>1000,46398=>1000,46399=>1000,46400=>1000,46401=>1000, -46402=>1000,46403=>1000,46404=>1000,46405=>1000,46406=>1000,46407=>1000,46408=>1000,46409=>1000,46410=>1000,46411=>1000, -46412=>1000,46413=>1000,46414=>1000,46415=>1000,46416=>1000,46417=>1000,46418=>1000,46419=>1000,46420=>1000,46421=>1000, -46422=>1000,46423=>1000,46424=>1000,46425=>1000,46426=>1000,46427=>1000,46428=>1000,46429=>1000,46430=>1000,46431=>1000, -46432=>1000,46433=>1000,46434=>1000,46435=>1000,46436=>1000,46437=>1000,46438=>1000,46439=>1000,46440=>1000,46441=>1000, -46442=>1000,46443=>1000,46444=>1000,46445=>1000,46446=>1000,46447=>1000,46448=>1000,46449=>1000,46450=>1000,46451=>1000, -46452=>1000,46453=>1000,46454=>1000,46455=>1000,46456=>1000,46457=>1000,46458=>1000,46459=>1000,46460=>1000,46461=>1000, -46462=>1000,46463=>1000,46464=>1000,46465=>1000,46466=>1000,46467=>1000,46468=>1000,46469=>1000,46470=>1000,46471=>1000, -46472=>1000,46473=>1000,46474=>1000,46475=>1000,46476=>1000,46477=>1000,46478=>1000,46479=>1000,46480=>1000,46481=>1000, -46482=>1000,46483=>1000,46484=>1000,46485=>1000,46486=>1000,46487=>1000,46488=>1000,46489=>1000,46490=>1000,46491=>1000, -46492=>1000,46493=>1000,46494=>1000,46495=>1000,46496=>1000,46497=>1000,46498=>1000,46499=>1000,46500=>1000,46501=>1000, -46502=>1000,46503=>1000,46504=>1000,46505=>1000,46506=>1000,46507=>1000,46508=>1000,46509=>1000,46510=>1000,46511=>1000, -46512=>1000,46513=>1000,46514=>1000,46515=>1000,46516=>1000,46517=>1000,46518=>1000,46519=>1000,46520=>1000,46521=>1000, -46522=>1000,46523=>1000,46524=>1000,46525=>1000,46526=>1000,46527=>1000,46528=>1000,46529=>1000,46530=>1000,46531=>1000, -46532=>1000,46533=>1000,46534=>1000,46535=>1000,46536=>1000,46537=>1000,46538=>1000,46539=>1000,46540=>1000,46541=>1000, -46542=>1000,46543=>1000,46544=>1000,46545=>1000,46546=>1000,46547=>1000,46548=>1000,46549=>1000,46550=>1000,46551=>1000, -46552=>1000,46553=>1000,46554=>1000,46555=>1000,46556=>1000,46557=>1000,46558=>1000,46559=>1000,46560=>1000,46561=>1000, -46562=>1000,46563=>1000,46564=>1000,46565=>1000,46566=>1000,46567=>1000,46568=>1000,46569=>1000,46570=>1000,46571=>1000, -46572=>1000,46573=>1000,46574=>1000,46575=>1000,46576=>1000,46577=>1000,46578=>1000,46579=>1000,46580=>1000,46581=>1000, -46582=>1000,46583=>1000,46584=>1000,46585=>1000,46586=>1000,46587=>1000,46588=>1000,46589=>1000,46590=>1000,46591=>1000, -46592=>1000,46593=>1000,46594=>1000,46595=>1000,46596=>1000,46597=>1000,46598=>1000,46599=>1000,46600=>1000,46601=>1000, -46602=>1000,46603=>1000,46604=>1000,46605=>1000,46606=>1000,46607=>1000,46608=>1000,46609=>1000,46610=>1000,46611=>1000, -46612=>1000,46613=>1000,46614=>1000,46615=>1000,46616=>1000,46617=>1000,46618=>1000,46619=>1000,46620=>1000,46621=>1000, -46622=>1000,46623=>1000,46624=>1000,46625=>1000,46626=>1000,46627=>1000,46628=>1000,46629=>1000,46630=>1000,46631=>1000, -46632=>1000,46633=>1000,46634=>1000,46635=>1000,46636=>1000,46637=>1000,46638=>1000,46639=>1000,46640=>1000,46641=>1000, -46642=>1000,46643=>1000,46644=>1000,46645=>1000,46646=>1000,46647=>1000,46648=>1000,46649=>1000,46650=>1000,46651=>1000, -46652=>1000,46653=>1000,46654=>1000,46655=>1000,46656=>1000,46657=>1000,46658=>1000,46659=>1000,46660=>1000,46661=>1000, -46662=>1000,46663=>1000,46664=>1000,46665=>1000,46666=>1000,46667=>1000,46668=>1000,46669=>1000,46670=>1000,46671=>1000, -46672=>1000,46673=>1000,46674=>1000,46675=>1000,46676=>1000,46677=>1000,46678=>1000,46679=>1000,46680=>1000,46681=>1000, -46682=>1000,46683=>1000,46684=>1000,46685=>1000,46686=>1000,46687=>1000,46688=>1000,46689=>1000,46690=>1000,46691=>1000, -46692=>1000,46693=>1000,46694=>1000,46695=>1000,46696=>1000,46697=>1000,46698=>1000,46699=>1000,46700=>1000,46701=>1000, -46702=>1000,46703=>1000,46704=>1000,46705=>1000,46706=>1000,46707=>1000,46708=>1000,46709=>1000,46710=>1000,46711=>1000, -46712=>1000,46713=>1000,46714=>1000,46715=>1000,46716=>1000,46717=>1000,46718=>1000,46719=>1000,46720=>1000,46721=>1000, -46722=>1000,46723=>1000,46724=>1000,46725=>1000,46726=>1000,46727=>1000,46728=>1000,46729=>1000,46730=>1000,46731=>1000, -46732=>1000,46733=>1000,46734=>1000,46735=>1000,46736=>1000,46737=>1000,46738=>1000,46739=>1000,46740=>1000,46741=>1000, -46742=>1000,46743=>1000,46744=>1000,46745=>1000,46746=>1000,46747=>1000,46748=>1000,46749=>1000,46750=>1000,46751=>1000, -46752=>1000,46753=>1000,46754=>1000,46755=>1000,46756=>1000,46757=>1000,46758=>1000,46759=>1000,46760=>1000,46761=>1000, -46762=>1000,46763=>1000,46764=>1000,46765=>1000,46766=>1000,46767=>1000,46768=>1000,46769=>1000,46770=>1000,46771=>1000, -46772=>1000,46773=>1000,46774=>1000,46775=>1000,46776=>1000,46777=>1000,46778=>1000,46779=>1000,46780=>1000,46781=>1000, -46782=>1000,46783=>1000,46784=>1000,46785=>1000,46786=>1000,46787=>1000,46788=>1000,46789=>1000,46790=>1000,46791=>1000, -46792=>1000,46793=>1000,46794=>1000,46795=>1000,46796=>1000,46797=>1000,46798=>1000,46799=>1000,46800=>1000,46801=>1000, -46802=>1000,46803=>1000,46804=>1000,46805=>1000,46806=>1000,46807=>1000,46808=>1000,46809=>1000,46810=>1000,46811=>1000, -46812=>1000,46813=>1000,46814=>1000,46815=>1000,46816=>1000,46817=>1000,46818=>1000,46819=>1000,46820=>1000,46821=>1000, -46822=>1000,46823=>1000,46824=>1000,46825=>1000,46826=>1000,46827=>1000,46828=>1000,46829=>1000,46830=>1000,46831=>1000, -46832=>1000,46833=>1000,46834=>1000,46835=>1000,46836=>1000,46837=>1000,46838=>1000,46839=>1000,46840=>1000,46841=>1000, -46842=>1000,46843=>1000,46844=>1000,46845=>1000,46846=>1000,46847=>1000,46848=>1000,46849=>1000,46850=>1000,46851=>1000, -46852=>1000,46853=>1000,46854=>1000,46855=>1000,46856=>1000,46857=>1000,46858=>1000,46859=>1000,46860=>1000,46861=>1000, -46862=>1000,46863=>1000,46864=>1000,46865=>1000,46866=>1000,46867=>1000,46868=>1000,46869=>1000,46870=>1000,46871=>1000, -46872=>1000,46873=>1000,46874=>1000,46875=>1000,46876=>1000,46877=>1000,46878=>1000,46879=>1000,46880=>1000,46881=>1000, -46882=>1000,46883=>1000,46884=>1000,46885=>1000,46886=>1000,46887=>1000,46888=>1000,46889=>1000,46890=>1000,46891=>1000, -46892=>1000,46893=>1000,46894=>1000,46895=>1000,46896=>1000,46897=>1000,46898=>1000,46899=>1000,46900=>1000,46901=>1000, -46902=>1000,46903=>1000,46904=>1000,46905=>1000,46906=>1000,46907=>1000,46908=>1000,46909=>1000,46910=>1000,46911=>1000, -46912=>1000,46913=>1000,46914=>1000,46915=>1000,46916=>1000,46917=>1000,46918=>1000,46919=>1000,46920=>1000,46921=>1000, -46922=>1000,46923=>1000,46924=>1000,46925=>1000,46926=>1000,46927=>1000,46928=>1000,46929=>1000,46930=>1000,46931=>1000, -46932=>1000,46933=>1000,46934=>1000,46935=>1000,46936=>1000,46937=>1000,46938=>1000,46939=>1000,46940=>1000,46941=>1000, -46942=>1000,46943=>1000,46944=>1000,46945=>1000,46946=>1000,46947=>1000,46948=>1000,46949=>1000,46950=>1000,46951=>1000, -46952=>1000,46953=>1000,46954=>1000,46955=>1000,46956=>1000,46957=>1000,46958=>1000,46959=>1000,46960=>1000,46961=>1000, -46962=>1000,46963=>1000,46964=>1000,46965=>1000,46966=>1000,46967=>1000,46968=>1000,46969=>1000,46970=>1000,46971=>1000, -46972=>1000,46973=>1000,46974=>1000,46975=>1000,46976=>1000,46977=>1000,46978=>1000,46979=>1000,46980=>1000,46981=>1000, -46982=>1000,46983=>1000,46984=>1000,46985=>1000,46986=>1000,46987=>1000,46988=>1000,46989=>1000,46990=>1000,46991=>1000, -46992=>1000,46993=>1000,46994=>1000,46995=>1000,46996=>1000,46997=>1000,46998=>1000,46999=>1000,47000=>1000,47001=>1000, -47002=>1000,47003=>1000,47004=>1000,47005=>1000,47006=>1000,47007=>1000,47008=>1000,47009=>1000,47010=>1000,47011=>1000, -47012=>1000,47013=>1000,47014=>1000,47015=>1000,47016=>1000,47017=>1000,47018=>1000,47019=>1000,47020=>1000,47021=>1000, -47022=>1000,47023=>1000,47024=>1000,47025=>1000,47026=>1000,47027=>1000,47028=>1000,47029=>1000,47030=>1000,47031=>1000, -47032=>1000,47033=>1000,47034=>1000,47035=>1000,47036=>1000,47037=>1000,47038=>1000,47039=>1000,47040=>1000,47041=>1000, -47042=>1000,47043=>1000,47044=>1000,47045=>1000,47046=>1000,47047=>1000,47048=>1000,47049=>1000,47050=>1000,47051=>1000, -47052=>1000,47053=>1000,47054=>1000,47055=>1000,47056=>1000,47057=>1000,47058=>1000,47059=>1000,47060=>1000,47061=>1000, -47062=>1000,47063=>1000,47064=>1000,47065=>1000,47066=>1000,47067=>1000,47068=>1000,47069=>1000,47070=>1000,47071=>1000, -47072=>1000,47073=>1000,47074=>1000,47075=>1000,47076=>1000,47077=>1000,47078=>1000,47079=>1000,47080=>1000,47081=>1000, -47082=>1000,47083=>1000,47084=>1000,47085=>1000,47086=>1000,47087=>1000,47088=>1000,47089=>1000,47090=>1000,47091=>1000, -47092=>1000,47093=>1000,47094=>1000,47095=>1000,47096=>1000,47097=>1000,47098=>1000,47099=>1000,47100=>1000,47101=>1000, -47102=>1000,47103=>1000,47104=>1000,47105=>1000,47106=>1000,47107=>1000,47108=>1000,47109=>1000,47110=>1000,47111=>1000, -47112=>1000,47113=>1000,47114=>1000,47115=>1000,47116=>1000,47117=>1000,47118=>1000,47119=>1000,47120=>1000,47121=>1000, -47122=>1000,47123=>1000,47124=>1000,47125=>1000,47126=>1000,47127=>1000,47128=>1000,47129=>1000,47130=>1000,47131=>1000, -47132=>1000,47133=>1000,47134=>1000,47135=>1000,47136=>1000,47137=>1000,47138=>1000,47139=>1000,47140=>1000,47141=>1000, -47142=>1000,47143=>1000,47144=>1000,47145=>1000,47146=>1000,47147=>1000,47148=>1000,47149=>1000,47150=>1000,47151=>1000, -47152=>1000,47153=>1000,47154=>1000,47155=>1000,47156=>1000,47157=>1000,47158=>1000,47159=>1000,47160=>1000,47161=>1000, -47162=>1000,47163=>1000,47164=>1000,47165=>1000,47166=>1000,47167=>1000,47168=>1000,47169=>1000,47170=>1000,47171=>1000, -47172=>1000,47173=>1000,47174=>1000,47175=>1000,47176=>1000,47177=>1000,47178=>1000,47179=>1000,47180=>1000,47181=>1000, -47182=>1000,47183=>1000,47184=>1000,47185=>1000,47186=>1000,47187=>1000,47188=>1000,47189=>1000,47190=>1000,47191=>1000, -47192=>1000,47193=>1000,47194=>1000,47195=>1000,47196=>1000,47197=>1000,47198=>1000,47199=>1000,47200=>1000,47201=>1000, -47202=>1000,47203=>1000,47204=>1000,47205=>1000,47206=>1000,47207=>1000,47208=>1000,47209=>1000,47210=>1000,47211=>1000, -47212=>1000,47213=>1000,47214=>1000,47215=>1000,47216=>1000,47217=>1000,47218=>1000,47219=>1000,47220=>1000,47221=>1000, -47222=>1000,47223=>1000,47224=>1000,47225=>1000,47226=>1000,47227=>1000,47228=>1000,47229=>1000,47230=>1000,47231=>1000, -47232=>1000,47233=>1000,47234=>1000,47235=>1000,47236=>1000,47237=>1000,47238=>1000,47239=>1000,47240=>1000,47241=>1000, -47242=>1000,47243=>1000,47244=>1000,47245=>1000,47246=>1000,47247=>1000,47248=>1000,47249=>1000,47250=>1000,47251=>1000, -47252=>1000,47253=>1000,47254=>1000,47255=>1000,47256=>1000,47257=>1000,47258=>1000,47259=>1000,47260=>1000,47261=>1000, -47262=>1000,47263=>1000,47264=>1000,47265=>1000,47266=>1000,47267=>1000,47268=>1000,47269=>1000,47270=>1000,47271=>1000, -47272=>1000,47273=>1000,47274=>1000,47275=>1000,47276=>1000,47277=>1000,47278=>1000,47279=>1000,47280=>1000,47281=>1000, -47282=>1000,47283=>1000,47284=>1000,47285=>1000,47286=>1000,47287=>1000,47288=>1000,47289=>1000,47290=>1000,47291=>1000, -47292=>1000,47293=>1000,47294=>1000,47295=>1000,47296=>1000,47297=>1000,47298=>1000,47299=>1000,47300=>1000,47301=>1000, -47302=>1000,47303=>1000,47304=>1000,47305=>1000,47306=>1000,47307=>1000,47308=>1000,47309=>1000,47310=>1000,47311=>1000, -47312=>1000,47313=>1000,47314=>1000,47315=>1000,47316=>1000,47317=>1000,47318=>1000,47319=>1000,47320=>1000,47321=>1000, -47322=>1000,47323=>1000,47324=>1000,47325=>1000,47326=>1000,47327=>1000,47328=>1000,47329=>1000,47330=>1000,47331=>1000, -47332=>1000,47333=>1000,47334=>1000,47335=>1000,47336=>1000,47337=>1000,47338=>1000,47339=>1000,47340=>1000,47341=>1000, -47342=>1000,47343=>1000,47344=>1000,47345=>1000,47346=>1000,47347=>1000,47348=>1000,47349=>1000,47350=>1000,47351=>1000, -47352=>1000,47353=>1000,47354=>1000,47355=>1000,47356=>1000,47357=>1000,47358=>1000,47359=>1000,47360=>1000,47361=>1000, -47362=>1000,47363=>1000,47364=>1000,47365=>1000,47366=>1000,47367=>1000,47368=>1000,47369=>1000,47370=>1000,47371=>1000, -47372=>1000,47373=>1000,47374=>1000,47375=>1000,47376=>1000,47377=>1000,47378=>1000,47379=>1000,47380=>1000,47381=>1000, -47382=>1000,47383=>1000,47384=>1000,47385=>1000,47386=>1000,47387=>1000,47388=>1000,47389=>1000,47390=>1000,47391=>1000, -47392=>1000,47393=>1000,47394=>1000,47395=>1000,47396=>1000,47397=>1000,47398=>1000,47399=>1000,47400=>1000,47401=>1000, -47402=>1000,47403=>1000,47404=>1000,47405=>1000,47406=>1000,47407=>1000,47408=>1000,47409=>1000,47410=>1000,47411=>1000, -47412=>1000,47413=>1000,47414=>1000,47415=>1000,47416=>1000,47417=>1000,47418=>1000,47419=>1000,47420=>1000,47421=>1000, -47422=>1000,47423=>1000,47424=>1000,47425=>1000,47426=>1000,47427=>1000,47428=>1000,47429=>1000,47430=>1000,47431=>1000, -47432=>1000,47433=>1000,47434=>1000,47435=>1000,47436=>1000,47437=>1000,47438=>1000,47439=>1000,47440=>1000,47441=>1000, -47442=>1000,47443=>1000,47444=>1000,47445=>1000,47446=>1000,47447=>1000,47448=>1000,47449=>1000,47450=>1000,47451=>1000, -47452=>1000,47453=>1000,47454=>1000,47455=>1000,47456=>1000,47457=>1000,47458=>1000,47459=>1000,47460=>1000,47461=>1000, -47462=>1000,47463=>1000,47464=>1000,47465=>1000,47466=>1000,47467=>1000,47468=>1000,47469=>1000,47470=>1000,47471=>1000, -47472=>1000,47473=>1000,47474=>1000,47475=>1000,47476=>1000,47477=>1000,47478=>1000,47479=>1000,47480=>1000,47481=>1000, -47482=>1000,47483=>1000,47484=>1000,47485=>1000,47486=>1000,47487=>1000,47488=>1000,47489=>1000,47490=>1000,47491=>1000, -47492=>1000,47493=>1000,47494=>1000,47495=>1000,47496=>1000,47497=>1000,47498=>1000,47499=>1000,47500=>1000,47501=>1000, -47502=>1000,47503=>1000,47504=>1000,47505=>1000,47506=>1000,47507=>1000,47508=>1000,47509=>1000,47510=>1000,47511=>1000, -47512=>1000,47513=>1000,47514=>1000,47515=>1000,47516=>1000,47517=>1000,47518=>1000,47519=>1000,47520=>1000,47521=>1000, -47522=>1000,47523=>1000,47524=>1000,47525=>1000,47526=>1000,47527=>1000,47528=>1000,47529=>1000,47530=>1000,47531=>1000, -47532=>1000,47533=>1000,47534=>1000,47535=>1000,47536=>1000,47537=>1000,47538=>1000,47539=>1000,47540=>1000,47541=>1000, -47542=>1000,47543=>1000,47544=>1000,47545=>1000,47546=>1000,47547=>1000,47548=>1000,47549=>1000,47550=>1000,47551=>1000, -47552=>1000,47553=>1000,47554=>1000,47555=>1000,47556=>1000,47557=>1000,47558=>1000,47559=>1000,47560=>1000,47561=>1000, -47562=>1000,47563=>1000,47564=>1000,47565=>1000,47566=>1000,47567=>1000,47568=>1000,47569=>1000,47570=>1000,47571=>1000, -47572=>1000,47573=>1000,47574=>1000,47575=>1000,47576=>1000,47577=>1000,47578=>1000,47579=>1000,47580=>1000,47581=>1000, -47582=>1000,47583=>1000,47584=>1000,47585=>1000,47586=>1000,47587=>1000,47588=>1000,47589=>1000,47590=>1000,47591=>1000, -47592=>1000,47593=>1000,47594=>1000,47595=>1000,47596=>1000,47597=>1000,47598=>1000,47599=>1000,47600=>1000,47601=>1000, -47602=>1000,47603=>1000,47604=>1000,47605=>1000,47606=>1000,47607=>1000,47608=>1000,47609=>1000,47610=>1000,47611=>1000, -47612=>1000,47613=>1000,47614=>1000,47615=>1000,47616=>1000,47617=>1000,47618=>1000,47619=>1000,47620=>1000,47621=>1000, -47622=>1000,47623=>1000,47624=>1000,47625=>1000,47626=>1000,47627=>1000,47628=>1000,47629=>1000,47630=>1000,47631=>1000, -47632=>1000,47633=>1000,47634=>1000,47635=>1000,47636=>1000,47637=>1000,47638=>1000,47639=>1000,47640=>1000,47641=>1000, -47642=>1000,47643=>1000,47644=>1000,47645=>1000,47646=>1000,47647=>1000,47648=>1000,47649=>1000,47650=>1000,47651=>1000, -47652=>1000,47653=>1000,47654=>1000,47655=>1000,47656=>1000,47657=>1000,47658=>1000,47659=>1000,47660=>1000,47661=>1000, -47662=>1000,47663=>1000,47664=>1000,47665=>1000,47666=>1000,47667=>1000,47668=>1000,47669=>1000,47670=>1000,47671=>1000, -47672=>1000,47673=>1000,47674=>1000,47675=>1000,47676=>1000,47677=>1000,47678=>1000,47679=>1000,47680=>1000,47681=>1000, -47682=>1000,47683=>1000,47684=>1000,47685=>1000,47686=>1000,47687=>1000,47688=>1000,47689=>1000,47690=>1000,47691=>1000, -47692=>1000,47693=>1000,47694=>1000,47695=>1000,47696=>1000,47697=>1000,47698=>1000,47699=>1000,47700=>1000,47701=>1000, -47702=>1000,47703=>1000,47704=>1000,47705=>1000,47706=>1000,47707=>1000,47708=>1000,47709=>1000,47710=>1000,47711=>1000, -47712=>1000,47713=>1000,47714=>1000,47715=>1000,47716=>1000,47717=>1000,47718=>1000,47719=>1000,47720=>1000,47721=>1000, -47722=>1000,47723=>1000,47724=>1000,47725=>1000,47726=>1000,47727=>1000,47728=>1000,47729=>1000,47730=>1000,47731=>1000, -47732=>1000,47733=>1000,47734=>1000,47735=>1000,47736=>1000,47737=>1000,47738=>1000,47739=>1000,47740=>1000,47741=>1000, -47742=>1000,47743=>1000,47744=>1000,47745=>1000,47746=>1000,47747=>1000,47748=>1000,47749=>1000,47750=>1000,47751=>1000, -47752=>1000,47753=>1000,47754=>1000,47755=>1000,47756=>1000,47757=>1000,47758=>1000,47759=>1000,47760=>1000,47761=>1000, -47762=>1000,47763=>1000,47764=>1000,47765=>1000,47766=>1000,47767=>1000,47768=>1000,47769=>1000,47770=>1000,47771=>1000, -47772=>1000,47773=>1000,47774=>1000,47775=>1000,47776=>1000,47777=>1000,47778=>1000,47779=>1000,47780=>1000,47781=>1000, -47782=>1000,47783=>1000,47784=>1000,47785=>1000,47786=>1000,47787=>1000,47788=>1000,47789=>1000,47790=>1000,47791=>1000, -47792=>1000,47793=>1000,47794=>1000,47795=>1000,47796=>1000,47797=>1000,47798=>1000,47799=>1000,47800=>1000,47801=>1000, -47802=>1000,47803=>1000,47804=>1000,47805=>1000,47806=>1000,47807=>1000,47808=>1000,47809=>1000,47810=>1000,47811=>1000, -47812=>1000,47813=>1000,47814=>1000,47815=>1000,47816=>1000,47817=>1000,47818=>1000,47819=>1000,47820=>1000,47821=>1000, -47822=>1000,47823=>1000,47824=>1000,47825=>1000,47826=>1000,47827=>1000,47828=>1000,47829=>1000,47830=>1000,47831=>1000, -47832=>1000,47833=>1000,47834=>1000,47835=>1000,47836=>1000,47837=>1000,47838=>1000,47839=>1000,47840=>1000,47841=>1000, -47842=>1000,47843=>1000,47844=>1000,47845=>1000,47846=>1000,47847=>1000,47848=>1000,47849=>1000,47850=>1000,47851=>1000, -47852=>1000,47853=>1000,47854=>1000,47855=>1000,47856=>1000,47857=>1000,47858=>1000,47859=>1000,47860=>1000,47861=>1000, -47862=>1000,47863=>1000,47864=>1000,47865=>1000,47866=>1000,47867=>1000,47868=>1000,47869=>1000,47870=>1000,47871=>1000, -47872=>1000,47873=>1000,47874=>1000,47875=>1000,47876=>1000,47877=>1000,47878=>1000,47879=>1000,47880=>1000,47881=>1000, -47882=>1000,47883=>1000,47884=>1000,47885=>1000,47886=>1000,47887=>1000,47888=>1000,47889=>1000,47890=>1000,47891=>1000, -47892=>1000,47893=>1000,47894=>1000,47895=>1000,47896=>1000,47897=>1000,47898=>1000,47899=>1000,47900=>1000,47901=>1000, -47902=>1000,47903=>1000,47904=>1000,47905=>1000,47906=>1000,47907=>1000,47908=>1000,47909=>1000,47910=>1000,47911=>1000, -47912=>1000,47913=>1000,47914=>1000,47915=>1000,47916=>1000,47917=>1000,47918=>1000,47919=>1000,47920=>1000,47921=>1000, -47922=>1000,47923=>1000,47924=>1000,47925=>1000,47926=>1000,47927=>1000,47928=>1000,47929=>1000,47930=>1000,47931=>1000, -47932=>1000,47933=>1000,47934=>1000,47935=>1000,47936=>1000,47937=>1000,47938=>1000,47939=>1000,47940=>1000,47941=>1000, -47942=>1000,47943=>1000,47944=>1000,47945=>1000,47946=>1000,47947=>1000,47948=>1000,47949=>1000,47950=>1000,47951=>1000, -47952=>1000,47953=>1000,47954=>1000,47955=>1000,47956=>1000,47957=>1000,47958=>1000,47959=>1000,47960=>1000,47961=>1000, -47962=>1000,47963=>1000,47964=>1000,47965=>1000,47966=>1000,47967=>1000,47968=>1000,47969=>1000,47970=>1000,47971=>1000, -47972=>1000,47973=>1000,47974=>1000,47975=>1000,47976=>1000,47977=>1000,47978=>1000,47979=>1000,47980=>1000,47981=>1000, -47982=>1000,47983=>1000,47984=>1000,47985=>1000,47986=>1000,47987=>1000,47988=>1000,47989=>1000,47990=>1000,47991=>1000, -47992=>1000,47993=>1000,47994=>1000,47995=>1000,47996=>1000,47997=>1000,47998=>1000,47999=>1000,48000=>1000,48001=>1000, -48002=>1000,48003=>1000,48004=>1000,48005=>1000,48006=>1000,48007=>1000,48008=>1000,48009=>1000,48010=>1000,48011=>1000, -48012=>1000,48013=>1000,48014=>1000,48015=>1000,48016=>1000,48017=>1000,48018=>1000,48019=>1000,48020=>1000,48021=>1000, -48022=>1000,48023=>1000,48024=>1000,48025=>1000,48026=>1000,48027=>1000,48028=>1000,48029=>1000,48030=>1000,48031=>1000, -48032=>1000,48033=>1000,48034=>1000,48035=>1000,48036=>1000,48037=>1000,48038=>1000,48039=>1000,48040=>1000,48041=>1000, -48042=>1000,48043=>1000,48044=>1000,48045=>1000,48046=>1000,48047=>1000,48048=>1000,48049=>1000,48050=>1000,48051=>1000, -48052=>1000,48053=>1000,48054=>1000,48055=>1000,48056=>1000,48057=>1000,48058=>1000,48059=>1000,48060=>1000,48061=>1000, -48062=>1000,48063=>1000,48064=>1000,48065=>1000,48066=>1000,48067=>1000,48068=>1000,48069=>1000,48070=>1000,48071=>1000, -48072=>1000,48073=>1000,48074=>1000,48075=>1000,48076=>1000,48077=>1000,48078=>1000,48079=>1000,48080=>1000,48081=>1000, -48082=>1000,48083=>1000,48084=>1000,48085=>1000,48086=>1000,48087=>1000,48088=>1000,48089=>1000,48090=>1000,48091=>1000, -48092=>1000,48093=>1000,48094=>1000,48095=>1000,48096=>1000,48097=>1000,48098=>1000,48099=>1000,48100=>1000,48101=>1000, -48102=>1000,48103=>1000,48104=>1000,48105=>1000,48106=>1000,48107=>1000,48108=>1000,48109=>1000,48110=>1000,48111=>1000, -48112=>1000,48113=>1000,48114=>1000,48115=>1000,48116=>1000,48117=>1000,48118=>1000,48119=>1000,48120=>1000,48121=>1000, -48122=>1000,48123=>1000,48124=>1000,48125=>1000,48126=>1000,48127=>1000,48128=>1000,48129=>1000,48130=>1000,48131=>1000, -48132=>1000,48133=>1000,48134=>1000,48135=>1000,48136=>1000,48137=>1000,48138=>1000,48139=>1000,48140=>1000,48141=>1000, -48142=>1000,48143=>1000,48144=>1000,48145=>1000,48146=>1000,48147=>1000,48148=>1000,48149=>1000,48150=>1000,48151=>1000, -48152=>1000,48153=>1000,48154=>1000,48155=>1000,48156=>1000,48157=>1000,48158=>1000,48159=>1000,48160=>1000,48161=>1000, -48162=>1000,48163=>1000,48164=>1000,48165=>1000,48166=>1000,48167=>1000,48168=>1000,48169=>1000,48170=>1000,48171=>1000, -48172=>1000,48173=>1000,48174=>1000,48175=>1000,48176=>1000,48177=>1000,48178=>1000,48179=>1000,48180=>1000,48181=>1000, -48182=>1000,48183=>1000,48184=>1000,48185=>1000,48186=>1000,48187=>1000,48188=>1000,48189=>1000,48190=>1000,48191=>1000, -48192=>1000,48193=>1000,48194=>1000,48195=>1000,48196=>1000,48197=>1000,48198=>1000,48199=>1000,48200=>1000,48201=>1000, -48202=>1000,48203=>1000,48204=>1000,48205=>1000,48206=>1000,48207=>1000,48208=>1000,48209=>1000,48210=>1000,48211=>1000, -48212=>1000,48213=>1000,48214=>1000,48215=>1000,48216=>1000,48217=>1000,48218=>1000,48219=>1000,48220=>1000,48221=>1000, -48222=>1000,48223=>1000,48224=>1000,48225=>1000,48226=>1000,48227=>1000,48228=>1000,48229=>1000,48230=>1000,48231=>1000, -48232=>1000,48233=>1000,48234=>1000,48235=>1000,48236=>1000,48237=>1000,48238=>1000,48239=>1000,48240=>1000,48241=>1000, -48242=>1000,48243=>1000,48244=>1000,48245=>1000,48246=>1000,48247=>1000,48248=>1000,48249=>1000,48250=>1000,48251=>1000, -48252=>1000,48253=>1000,48254=>1000,48255=>1000,48256=>1000,48257=>1000,48258=>1000,48259=>1000,48260=>1000,48261=>1000, -48262=>1000,48263=>1000,48264=>1000,48265=>1000,48266=>1000,48267=>1000,48268=>1000,48269=>1000,48270=>1000,48271=>1000, -48272=>1000,48273=>1000,48274=>1000,48275=>1000,48276=>1000,48277=>1000,48278=>1000,48279=>1000,48280=>1000,48281=>1000, -48282=>1000,48283=>1000,48284=>1000,48285=>1000,48286=>1000,48287=>1000,48288=>1000,48289=>1000,48290=>1000,48291=>1000, -48292=>1000,48293=>1000,48294=>1000,48295=>1000,48296=>1000,48297=>1000,48298=>1000,48299=>1000,48300=>1000,48301=>1000, -48302=>1000,48303=>1000,48304=>1000,48305=>1000,48306=>1000,48307=>1000,48308=>1000,48309=>1000,48310=>1000,48311=>1000, -48312=>1000,48313=>1000,48314=>1000,48315=>1000,48316=>1000,48317=>1000,48318=>1000,48319=>1000,48320=>1000,48321=>1000, -48322=>1000,48323=>1000,48324=>1000,48325=>1000,48326=>1000,48327=>1000,48328=>1000,48329=>1000,48330=>1000,48331=>1000, -48332=>1000,48333=>1000,48334=>1000,48335=>1000,48336=>1000,48337=>1000,48338=>1000,48339=>1000,48340=>1000,48341=>1000, -48342=>1000,48343=>1000,48344=>1000,48345=>1000,48346=>1000,48347=>1000,48348=>1000,48349=>1000,48350=>1000,48351=>1000, -48352=>1000,48353=>1000,48354=>1000,48355=>1000,48356=>1000,48357=>1000,48358=>1000,48359=>1000,48360=>1000,48361=>1000, -48362=>1000,48363=>1000,48364=>1000,48365=>1000,48366=>1000,48367=>1000,48368=>1000,48369=>1000,48370=>1000,48371=>1000, -48372=>1000,48373=>1000,48374=>1000,48375=>1000,48376=>1000,48377=>1000,48378=>1000,48379=>1000,48380=>1000,48381=>1000, -48382=>1000,48383=>1000,48384=>1000,48385=>1000,48386=>1000,48387=>1000,48388=>1000,48389=>1000,48390=>1000,48391=>1000, -48392=>1000,48393=>1000,48394=>1000,48395=>1000,48396=>1000,48397=>1000,48398=>1000,48399=>1000,48400=>1000,48401=>1000, -48402=>1000,48403=>1000,48404=>1000,48405=>1000,48406=>1000,48407=>1000,48408=>1000,48409=>1000,48410=>1000,48411=>1000, -48412=>1000,48413=>1000,48414=>1000,48415=>1000,48416=>1000,48417=>1000,48418=>1000,48419=>1000,48420=>1000,48421=>1000, -48422=>1000,48423=>1000,48424=>1000,48425=>1000,48426=>1000,48427=>1000,48428=>1000,48429=>1000,48430=>1000,48431=>1000, -48432=>1000,48433=>1000,48434=>1000,48435=>1000,48436=>1000,48437=>1000,48438=>1000,48439=>1000,48440=>1000,48441=>1000, -48442=>1000,48443=>1000,48444=>1000,48445=>1000,48446=>1000,48447=>1000,48448=>1000,48449=>1000,48450=>1000,48451=>1000, -48452=>1000,48453=>1000,48454=>1000,48455=>1000,48456=>1000,48457=>1000,48458=>1000,48459=>1000,48460=>1000,48461=>1000, -48462=>1000,48463=>1000,48464=>1000,48465=>1000,48466=>1000,48467=>1000,48468=>1000,48469=>1000,48470=>1000,48471=>1000, -48472=>1000,48473=>1000,48474=>1000,48475=>1000,48476=>1000,48477=>1000,48478=>1000,48479=>1000,48480=>1000,48481=>1000, -48482=>1000,48483=>1000,48484=>1000,48485=>1000,48486=>1000,48487=>1000,48488=>1000,48489=>1000,48490=>1000,48491=>1000, -48492=>1000,48493=>1000,48494=>1000,48495=>1000,48496=>1000,48497=>1000,48498=>1000,48499=>1000,48500=>1000,48501=>1000, -48502=>1000,48503=>1000,48504=>1000,48505=>1000,48506=>1000,48507=>1000,48508=>1000,48509=>1000,48510=>1000,48511=>1000, -48512=>1000,48513=>1000,48514=>1000,48515=>1000,48516=>1000,48517=>1000,48518=>1000,48519=>1000,48520=>1000,48521=>1000, -48522=>1000,48523=>1000,48524=>1000,48525=>1000,48526=>1000,48527=>1000,48528=>1000,48529=>1000,48530=>1000,48531=>1000, -48532=>1000,48533=>1000,48534=>1000,48535=>1000,48536=>1000,48537=>1000,48538=>1000,48539=>1000,48540=>1000,48541=>1000, -48542=>1000,48543=>1000,48544=>1000,48545=>1000,48546=>1000,48547=>1000,48548=>1000,48549=>1000,48550=>1000,48551=>1000, -48552=>1000,48553=>1000,48554=>1000,48555=>1000,48556=>1000,48557=>1000,48558=>1000,48559=>1000,48560=>1000,48561=>1000, -48562=>1000,48563=>1000,48564=>1000,48565=>1000,48566=>1000,48567=>1000,48568=>1000,48569=>1000,48570=>1000,48571=>1000, -48572=>1000,48573=>1000,48574=>1000,48575=>1000,48576=>1000,48577=>1000,48578=>1000,48579=>1000,48580=>1000,48581=>1000, -48582=>1000,48583=>1000,48584=>1000,48585=>1000,48586=>1000,48587=>1000,48588=>1000,48589=>1000,48590=>1000,48591=>1000, -48592=>1000,48593=>1000,48594=>1000,48595=>1000,48596=>1000,48597=>1000,48598=>1000,48599=>1000,48600=>1000,48601=>1000, -48602=>1000,48603=>1000,48604=>1000,48605=>1000,48606=>1000,48607=>1000,48608=>1000,48609=>1000,48610=>1000,48611=>1000, -48612=>1000,48613=>1000,48614=>1000,48615=>1000,48616=>1000,48617=>1000,48618=>1000,48619=>1000,48620=>1000,48621=>1000, -48622=>1000,48623=>1000,48624=>1000,48625=>1000,48626=>1000,48627=>1000,48628=>1000,48629=>1000,48630=>1000,48631=>1000, -48632=>1000,48633=>1000,48634=>1000,48635=>1000,48636=>1000,48637=>1000,48638=>1000,48639=>1000,48640=>1000,48641=>1000, -48642=>1000,48643=>1000,48644=>1000,48645=>1000,48646=>1000,48647=>1000,48648=>1000,48649=>1000,48650=>1000,48651=>1000, -48652=>1000,48653=>1000,48654=>1000,48655=>1000,48656=>1000,48657=>1000,48658=>1000,48659=>1000,48660=>1000,48661=>1000, -48662=>1000,48663=>1000,48664=>1000,48665=>1000,48666=>1000,48667=>1000,48668=>1000,48669=>1000,48670=>1000,48671=>1000, -48672=>1000,48673=>1000,48674=>1000,48675=>1000,48676=>1000,48677=>1000,48678=>1000,48679=>1000,48680=>1000,48681=>1000, -48682=>1000,48683=>1000,48684=>1000,48685=>1000,48686=>1000,48687=>1000,48688=>1000,48689=>1000,48690=>1000,48691=>1000, -48692=>1000,48693=>1000,48694=>1000,48695=>1000,48696=>1000,48697=>1000,48698=>1000,48699=>1000,48700=>1000,48701=>1000, -48702=>1000,48703=>1000,48704=>1000,48705=>1000,48706=>1000,48707=>1000,48708=>1000,48709=>1000,48710=>1000,48711=>1000, -48712=>1000,48713=>1000,48714=>1000,48715=>1000,48716=>1000,48717=>1000,48718=>1000,48719=>1000,48720=>1000,48721=>1000, -48722=>1000,48723=>1000,48724=>1000,48725=>1000,48726=>1000,48727=>1000,48728=>1000,48729=>1000,48730=>1000,48731=>1000, -48732=>1000,48733=>1000,48734=>1000,48735=>1000,48736=>1000,48737=>1000,48738=>1000,48739=>1000,48740=>1000,48741=>1000, -48742=>1000,48743=>1000,48744=>1000,48745=>1000,48746=>1000,48747=>1000,48748=>1000,48749=>1000,48750=>1000,48751=>1000, -48752=>1000,48753=>1000,48754=>1000,48755=>1000,48756=>1000,48757=>1000,48758=>1000,48759=>1000,48760=>1000,48761=>1000, -48762=>1000,48763=>1000,48764=>1000,48765=>1000,48766=>1000,48767=>1000,48768=>1000,48769=>1000,48770=>1000,48771=>1000, -48772=>1000,48773=>1000,48774=>1000,48775=>1000,48776=>1000,48777=>1000,48778=>1000,48779=>1000,48780=>1000,48781=>1000, -48782=>1000,48783=>1000,48784=>1000,48785=>1000,48786=>1000,48787=>1000,48788=>1000,48789=>1000,48790=>1000,48791=>1000, -48792=>1000,48793=>1000,48794=>1000,48795=>1000,48796=>1000,48797=>1000,48798=>1000,48799=>1000,48800=>1000,48801=>1000, -48802=>1000,48803=>1000,48804=>1000,48805=>1000,48806=>1000,48807=>1000,48808=>1000,48809=>1000,48810=>1000,48811=>1000, -48812=>1000,48813=>1000,48814=>1000,48815=>1000,48816=>1000,48817=>1000,48818=>1000,48819=>1000,48820=>1000,48821=>1000, -48822=>1000,48823=>1000,48824=>1000,48825=>1000,48826=>1000,48827=>1000,48828=>1000,48829=>1000,48830=>1000,48831=>1000, -48832=>1000,48833=>1000,48834=>1000,48835=>1000,48836=>1000,48837=>1000,48838=>1000,48839=>1000,48840=>1000,48841=>1000, -48842=>1000,48843=>1000,48844=>1000,48845=>1000,48846=>1000,48847=>1000,48848=>1000,48849=>1000,48850=>1000,48851=>1000, -48852=>1000,48853=>1000,48854=>1000,48855=>1000,48856=>1000,48857=>1000,48858=>1000,48859=>1000,48860=>1000,48861=>1000, -48862=>1000,48863=>1000,48864=>1000,48865=>1000,48866=>1000,48867=>1000,48868=>1000,48869=>1000,48870=>1000,48871=>1000, -48872=>1000,48873=>1000,48874=>1000,48875=>1000,48876=>1000,48877=>1000,48878=>1000,48879=>1000,48880=>1000,48881=>1000, -48882=>1000,48883=>1000,48884=>1000,48885=>1000,48886=>1000,48887=>1000,48888=>1000,48889=>1000,48890=>1000,48891=>1000, -48892=>1000,48893=>1000,48894=>1000,48895=>1000,48896=>1000,48897=>1000,48898=>1000,48899=>1000,48900=>1000,48901=>1000, -48902=>1000,48903=>1000,48904=>1000,48905=>1000,48906=>1000,48907=>1000,48908=>1000,48909=>1000,48910=>1000,48911=>1000, -48912=>1000,48913=>1000,48914=>1000,48915=>1000,48916=>1000,48917=>1000,48918=>1000,48919=>1000,48920=>1000,48921=>1000, -48922=>1000,48923=>1000,48924=>1000,48925=>1000,48926=>1000,48927=>1000,48928=>1000,48929=>1000,48930=>1000,48931=>1000, -48932=>1000,48933=>1000,48934=>1000,48935=>1000,48936=>1000,48937=>1000,48938=>1000,48939=>1000,48940=>1000,48941=>1000, -48942=>1000,48943=>1000,48944=>1000,48945=>1000,48946=>1000,48947=>1000,48948=>1000,48949=>1000,48950=>1000,48951=>1000, -48952=>1000,48953=>1000,48954=>1000,48955=>1000,48956=>1000,48957=>1000,48958=>1000,48959=>1000,48960=>1000,48961=>1000, -48962=>1000,48963=>1000,48964=>1000,48965=>1000,48966=>1000,48967=>1000,48968=>1000,48969=>1000,48970=>1000,48971=>1000, -48972=>1000,48973=>1000,48974=>1000,48975=>1000,48976=>1000,48977=>1000,48978=>1000,48979=>1000,48980=>1000,48981=>1000, -48982=>1000,48983=>1000,48984=>1000,48985=>1000,48986=>1000,48987=>1000,48988=>1000,48989=>1000,48990=>1000,48991=>1000, -48992=>1000,48993=>1000,48994=>1000,48995=>1000,48996=>1000,48997=>1000,48998=>1000,48999=>1000,49000=>1000,49001=>1000, -49002=>1000,49003=>1000,49004=>1000,49005=>1000,49006=>1000,49007=>1000,49008=>1000,49009=>1000,49010=>1000,49011=>1000, -49012=>1000,49013=>1000,49014=>1000,49015=>1000,49016=>1000,49017=>1000,49018=>1000,49019=>1000,49020=>1000,49021=>1000, -49022=>1000,49023=>1000,49024=>1000,49025=>1000,49026=>1000,49027=>1000,49028=>1000,49029=>1000,49030=>1000,49031=>1000, -49032=>1000,49033=>1000,49034=>1000,49035=>1000,49036=>1000,49037=>1000,49038=>1000,49039=>1000,49040=>1000,49041=>1000, -49042=>1000,49043=>1000,49044=>1000,49045=>1000,49046=>1000,49047=>1000,49048=>1000,49049=>1000,49050=>1000,49051=>1000, -49052=>1000,49053=>1000,49054=>1000,49055=>1000,49056=>1000,49057=>1000,49058=>1000,49059=>1000,49060=>1000,49061=>1000, -49062=>1000,49063=>1000,49064=>1000,49065=>1000,49066=>1000,49067=>1000,49068=>1000,49069=>1000,49070=>1000,49071=>1000, -49072=>1000,49073=>1000,49074=>1000,49075=>1000,49076=>1000,49077=>1000,49078=>1000,49079=>1000,49080=>1000,49081=>1000, -49082=>1000,49083=>1000,49084=>1000,49085=>1000,49086=>1000,49087=>1000,49088=>1000,49089=>1000,49090=>1000,49091=>1000, -49092=>1000,49093=>1000,49094=>1000,49095=>1000,49096=>1000,49097=>1000,49098=>1000,49099=>1000,49100=>1000,49101=>1000, -49102=>1000,49103=>1000,49104=>1000,49105=>1000,49106=>1000,49107=>1000,49108=>1000,49109=>1000,49110=>1000,49111=>1000, -49112=>1000,49113=>1000,49114=>1000,49115=>1000,49116=>1000,49117=>1000,49118=>1000,49119=>1000,49120=>1000,49121=>1000, -49122=>1000,49123=>1000,49124=>1000,49125=>1000,49126=>1000,49127=>1000,49128=>1000,49129=>1000,49130=>1000,49131=>1000, -49132=>1000,49133=>1000,49134=>1000,49135=>1000,49136=>1000,49137=>1000,49138=>1000,49139=>1000,49140=>1000,49141=>1000, -49142=>1000,49143=>1000,49144=>1000,49145=>1000,49146=>1000,49147=>1000,49148=>1000,49149=>1000,49150=>1000,49151=>1000, -49152=>1000,49153=>1000,49154=>1000,49155=>1000,49156=>1000,49157=>1000,49158=>1000,49159=>1000,49160=>1000,49161=>1000, -49162=>1000,49163=>1000,49164=>1000,49165=>1000,49166=>1000,49167=>1000,49168=>1000,49169=>1000,49170=>1000,49171=>1000, -49172=>1000,49173=>1000,49174=>1000,49175=>1000,49176=>1000,49177=>1000,49178=>1000,49179=>1000,49180=>1000,49181=>1000, -49182=>1000,49183=>1000,49184=>1000,49185=>1000,49186=>1000,49187=>1000,49188=>1000,49189=>1000,49190=>1000,49191=>1000, -49192=>1000,49193=>1000,49194=>1000,49195=>1000,49196=>1000,49197=>1000,49198=>1000,49199=>1000,49200=>1000,49201=>1000, -49202=>1000,49203=>1000,49204=>1000,49205=>1000,49206=>1000,49207=>1000,49208=>1000,49209=>1000,49210=>1000,49211=>1000, -49212=>1000,49213=>1000,49214=>1000,49215=>1000,49216=>1000,49217=>1000,49218=>1000,49219=>1000,49220=>1000,49221=>1000, -49222=>1000,49223=>1000,49224=>1000,49225=>1000,49226=>1000,49227=>1000,49228=>1000,49229=>1000,49230=>1000,49231=>1000, -49232=>1000,49233=>1000,49234=>1000,49235=>1000,49236=>1000,49237=>1000,49238=>1000,49239=>1000,49240=>1000,49241=>1000, -49242=>1000,49243=>1000,49244=>1000,49245=>1000,49246=>1000,49247=>1000,49248=>1000,49249=>1000,49250=>1000,49251=>1000, -49252=>1000,49253=>1000,49254=>1000,49255=>1000,49256=>1000,49257=>1000,49258=>1000,49259=>1000,49260=>1000,49261=>1000, -49262=>1000,49263=>1000,49264=>1000,49265=>1000,49266=>1000,49267=>1000,49268=>1000,49269=>1000,49270=>1000,49271=>1000, -49272=>1000,49273=>1000,49274=>1000,49275=>1000,49276=>1000,49277=>1000,49278=>1000,49279=>1000,49280=>1000,49281=>1000, -49282=>1000,49283=>1000,49284=>1000,49285=>1000,49286=>1000,49287=>1000,49288=>1000,49289=>1000,49290=>1000,49291=>1000, -49292=>1000,49293=>1000,49294=>1000,49295=>1000,49296=>1000,49297=>1000,49298=>1000,49299=>1000,49300=>1000,49301=>1000, -49302=>1000,49303=>1000,49304=>1000,49305=>1000,49306=>1000,49307=>1000,49308=>1000,49309=>1000,49310=>1000,49311=>1000, -49312=>1000,49313=>1000,49314=>1000,49315=>1000,49316=>1000,49317=>1000,49318=>1000,49319=>1000,49320=>1000,49321=>1000, -49322=>1000,49323=>1000,49324=>1000,49325=>1000,49326=>1000,49327=>1000,49328=>1000,49329=>1000,49330=>1000,49331=>1000, -49332=>1000,49333=>1000,49334=>1000,49335=>1000,49336=>1000,49337=>1000,49338=>1000,49339=>1000,49340=>1000,49341=>1000, -49342=>1000,49343=>1000,49344=>1000,49345=>1000,49346=>1000,49347=>1000,49348=>1000,49349=>1000,49350=>1000,49351=>1000, -49352=>1000,49353=>1000,49354=>1000,49355=>1000,49356=>1000,49357=>1000,49358=>1000,49359=>1000,49360=>1000,49361=>1000, -49362=>1000,49363=>1000,49364=>1000,49365=>1000,49366=>1000,49367=>1000,49368=>1000,49369=>1000,49370=>1000,49371=>1000, -49372=>1000,49373=>1000,49374=>1000,49375=>1000,49376=>1000,49377=>1000,49378=>1000,49379=>1000,49380=>1000,49381=>1000, -49382=>1000,49383=>1000,49384=>1000,49385=>1000,49386=>1000,49387=>1000,49388=>1000,49389=>1000,49390=>1000,49391=>1000, -49392=>1000,49393=>1000,49394=>1000,49395=>1000,49396=>1000,49397=>1000,49398=>1000,49399=>1000,49400=>1000,49401=>1000, -49402=>1000,49403=>1000,49404=>1000,49405=>1000,49406=>1000,49407=>1000,49408=>1000,49409=>1000,49410=>1000,49411=>1000, -49412=>1000,49413=>1000,49414=>1000,49415=>1000,49416=>1000,49417=>1000,49418=>1000,49419=>1000,49420=>1000,49421=>1000, -49422=>1000,49423=>1000,49424=>1000,49425=>1000,49426=>1000,49427=>1000,49428=>1000,49429=>1000,49430=>1000,49431=>1000, -49432=>1000,49433=>1000,49434=>1000,49435=>1000,49436=>1000,49437=>1000,49438=>1000,49439=>1000,49440=>1000,49441=>1000, -49442=>1000,49443=>1000,49444=>1000,49445=>1000,49446=>1000,49447=>1000,49448=>1000,49449=>1000,49450=>1000,49451=>1000, -49452=>1000,49453=>1000,49454=>1000,49455=>1000,49456=>1000,49457=>1000,49458=>1000,49459=>1000,49460=>1000,49461=>1000, -49462=>1000,49463=>1000,49464=>1000,49465=>1000,49466=>1000,49467=>1000,49468=>1000,49469=>1000,49470=>1000,49471=>1000, -49472=>1000,49473=>1000,49474=>1000,49475=>1000,49476=>1000,49477=>1000,49478=>1000,49479=>1000,49480=>1000,49481=>1000, -49482=>1000,49483=>1000,49484=>1000,49485=>1000,49486=>1000,49487=>1000,49488=>1000,49489=>1000,49490=>1000,49491=>1000, -49492=>1000,49493=>1000,49494=>1000,49495=>1000,49496=>1000,49497=>1000,49498=>1000,49499=>1000,49500=>1000,49501=>1000, -49502=>1000,49503=>1000,49504=>1000,49505=>1000,49506=>1000,49507=>1000,49508=>1000,49509=>1000,49510=>1000,49511=>1000, -49512=>1000,49513=>1000,49514=>1000,49515=>1000,49516=>1000,49517=>1000,49518=>1000,49519=>1000,49520=>1000,49521=>1000, -49522=>1000,49523=>1000,49524=>1000,49525=>1000,49526=>1000,49527=>1000,49528=>1000,49529=>1000,49530=>1000,49531=>1000, -49532=>1000,49533=>1000,49534=>1000,49535=>1000,49536=>1000,49537=>1000,49538=>1000,49539=>1000,49540=>1000,49541=>1000, -49542=>1000,49543=>1000,49544=>1000,49545=>1000,49546=>1000,49547=>1000,49548=>1000,49549=>1000,49550=>1000,49551=>1000, -49552=>1000,49553=>1000,49554=>1000,49555=>1000,49556=>1000,49557=>1000,49558=>1000,49559=>1000,49560=>1000,49561=>1000, -49562=>1000,49563=>1000,49564=>1000,49565=>1000,49566=>1000,49567=>1000,49568=>1000,49569=>1000,49570=>1000,49571=>1000, -49572=>1000,49573=>1000,49574=>1000,49575=>1000,49576=>1000,49577=>1000,49578=>1000,49579=>1000,49580=>1000,49581=>1000, -49582=>1000,49583=>1000,49584=>1000,49585=>1000,49586=>1000,49587=>1000,49588=>1000,49589=>1000,49590=>1000,49591=>1000, -49592=>1000,49593=>1000,49594=>1000,49595=>1000,49596=>1000,49597=>1000,49598=>1000,49599=>1000,49600=>1000,49601=>1000, -49602=>1000,49603=>1000,49604=>1000,49605=>1000,49606=>1000,49607=>1000,49608=>1000,49609=>1000,49610=>1000,49611=>1000, -49612=>1000,49613=>1000,49614=>1000,49615=>1000,49616=>1000,49617=>1000,49618=>1000,49619=>1000,49620=>1000,49621=>1000, -49622=>1000,49623=>1000,49624=>1000,49625=>1000,49626=>1000,49627=>1000,49628=>1000,49629=>1000,49630=>1000,49631=>1000, -49632=>1000,49633=>1000,49634=>1000,49635=>1000,49636=>1000,49637=>1000,49638=>1000,49639=>1000,49640=>1000,49641=>1000, -49642=>1000,49643=>1000,49644=>1000,49645=>1000,49646=>1000,49647=>1000,49648=>1000,49649=>1000,49650=>1000,49651=>1000, -49652=>1000,49653=>1000,49654=>1000,49655=>1000,49656=>1000,49657=>1000,49658=>1000,49659=>1000,49660=>1000,49661=>1000, -49662=>1000,49663=>1000,49664=>1000,49665=>1000,49666=>1000,49667=>1000,49668=>1000,49669=>1000,49670=>1000,49671=>1000, -49672=>1000,49673=>1000,49674=>1000,49675=>1000,49676=>1000,49677=>1000,49678=>1000,49679=>1000,49680=>1000,49681=>1000, -49682=>1000,49683=>1000,49684=>1000,49685=>1000,49686=>1000,49687=>1000,49688=>1000,49689=>1000,49690=>1000,49691=>1000, -49692=>1000,49693=>1000,49694=>1000,49695=>1000,49696=>1000,49697=>1000,49698=>1000,49699=>1000,49700=>1000,49701=>1000, -49702=>1000,49703=>1000,49704=>1000,49705=>1000,49706=>1000,49707=>1000,49708=>1000,49709=>1000,49710=>1000,49711=>1000, -49712=>1000,49713=>1000,49714=>1000,49715=>1000,49716=>1000,49717=>1000,49718=>1000,49719=>1000,49720=>1000,49721=>1000, -49722=>1000,49723=>1000,49724=>1000,49725=>1000,49726=>1000,49727=>1000,49728=>1000,49729=>1000,49730=>1000,49731=>1000, -49732=>1000,49733=>1000,49734=>1000,49735=>1000,49736=>1000,49737=>1000,49738=>1000,49739=>1000,49740=>1000,49741=>1000, -49742=>1000,49743=>1000,49744=>1000,49745=>1000,49746=>1000,49747=>1000,49748=>1000,49749=>1000,49750=>1000,49751=>1000, -49752=>1000,49753=>1000,49754=>1000,49755=>1000,49756=>1000,49757=>1000,49758=>1000,49759=>1000,49760=>1000,49761=>1000, -49762=>1000,49763=>1000,49764=>1000,49765=>1000,49766=>1000,49767=>1000,49768=>1000,49769=>1000,49770=>1000,49771=>1000, -49772=>1000,49773=>1000,49774=>1000,49775=>1000,49776=>1000,49777=>1000,49778=>1000,49779=>1000,49780=>1000,49781=>1000, -49782=>1000,49783=>1000,49784=>1000,49785=>1000,49786=>1000,49787=>1000,49788=>1000,49789=>1000,49790=>1000,49791=>1000, -49792=>1000,49793=>1000,49794=>1000,49795=>1000,49796=>1000,49797=>1000,49798=>1000,49799=>1000,49800=>1000,49801=>1000, -49802=>1000,49803=>1000,49804=>1000,49805=>1000,49806=>1000,49807=>1000,49808=>1000,49809=>1000,49810=>1000,49811=>1000, -49812=>1000,49813=>1000,49814=>1000,49815=>1000,49816=>1000,49817=>1000,49818=>1000,49819=>1000,49820=>1000,49821=>1000, -49822=>1000,49823=>1000,49824=>1000,49825=>1000,49826=>1000,49827=>1000,49828=>1000,49829=>1000,49830=>1000,49831=>1000, -49832=>1000,49833=>1000,49834=>1000,49835=>1000,49836=>1000,49837=>1000,49838=>1000,49839=>1000,49840=>1000,49841=>1000, -49842=>1000,49843=>1000,49844=>1000,49845=>1000,49846=>1000,49847=>1000,49848=>1000,49849=>1000,49850=>1000,49851=>1000, -49852=>1000,49853=>1000,49854=>1000,49855=>1000,49856=>1000,49857=>1000,49858=>1000,49859=>1000,49860=>1000,49861=>1000, -49862=>1000,49863=>1000,49864=>1000,49865=>1000,49866=>1000,49867=>1000,49868=>1000,49869=>1000,49870=>1000,49871=>1000, -49872=>1000,49873=>1000,49874=>1000,49875=>1000,49876=>1000,49877=>1000,49878=>1000,49879=>1000,49880=>1000,49881=>1000, -49882=>1000,49883=>1000,49884=>1000,49885=>1000,49886=>1000,49887=>1000,49888=>1000,49889=>1000,49890=>1000,49891=>1000, -49892=>1000,49893=>1000,49894=>1000,49895=>1000,49896=>1000,49897=>1000,49898=>1000,49899=>1000,49900=>1000,49901=>1000, -49902=>1000,49903=>1000,49904=>1000,49905=>1000,49906=>1000,49907=>1000,49908=>1000,49909=>1000,49910=>1000,49911=>1000, -49912=>1000,49913=>1000,49914=>1000,49915=>1000,49916=>1000,49917=>1000,49918=>1000,49919=>1000,49920=>1000,49921=>1000, -49922=>1000,49923=>1000,49924=>1000,49925=>1000,49926=>1000,49927=>1000,49928=>1000,49929=>1000,49930=>1000,49931=>1000, -49932=>1000,49933=>1000,49934=>1000,49935=>1000,49936=>1000,49937=>1000,49938=>1000,49939=>1000,49940=>1000,49941=>1000, -49942=>1000,49943=>1000,49944=>1000,49945=>1000,49946=>1000,49947=>1000,49948=>1000,49949=>1000,49950=>1000,49951=>1000, -49952=>1000,49953=>1000,49954=>1000,49955=>1000,49956=>1000,49957=>1000,49958=>1000,49959=>1000,49960=>1000,49961=>1000, -49962=>1000,49963=>1000,49964=>1000,49965=>1000,49966=>1000,49967=>1000,49968=>1000,49969=>1000,49970=>1000,49971=>1000, -49972=>1000,49973=>1000,49974=>1000,49975=>1000,49976=>1000,49977=>1000,49978=>1000,49979=>1000,49980=>1000,49981=>1000, -49982=>1000,49983=>1000,49984=>1000,49985=>1000,49986=>1000,49987=>1000,49988=>1000,49989=>1000,49990=>1000,49991=>1000, -49992=>1000,49993=>1000,49994=>1000,49995=>1000,49996=>1000,49997=>1000,49998=>1000,49999=>1000,50000=>1000,50001=>1000, -50002=>1000,50003=>1000,50004=>1000,50005=>1000,50006=>1000,50007=>1000,50008=>1000,50009=>1000,50010=>1000,50011=>1000, -50012=>1000,50013=>1000,50014=>1000,50015=>1000,50016=>1000,50017=>1000,50018=>1000,50019=>1000,50020=>1000,50021=>1000, -50022=>1000,50023=>1000,50024=>1000,50025=>1000,50026=>1000,50027=>1000,50028=>1000,50029=>1000,50030=>1000,50031=>1000, -50032=>1000,50033=>1000,50034=>1000,50035=>1000,50036=>1000,50037=>1000,50038=>1000,50039=>1000,50040=>1000,50041=>1000, -50042=>1000,50043=>1000,50044=>1000,50045=>1000,50046=>1000,50047=>1000,50048=>1000,50049=>1000,50050=>1000,50051=>1000, -50052=>1000,50053=>1000,50054=>1000,50055=>1000,50056=>1000,50057=>1000,50058=>1000,50059=>1000,50060=>1000,50061=>1000, -50062=>1000,50063=>1000,50064=>1000,50065=>1000,50066=>1000,50067=>1000,50068=>1000,50069=>1000,50070=>1000,50071=>1000, -50072=>1000,50073=>1000,50074=>1000,50075=>1000,50076=>1000,50077=>1000,50078=>1000,50079=>1000,50080=>1000,50081=>1000, -50082=>1000,50083=>1000,50084=>1000,50085=>1000,50086=>1000,50087=>1000,50088=>1000,50089=>1000,50090=>1000,50091=>1000, -50092=>1000,50093=>1000,50094=>1000,50095=>1000,50096=>1000,50097=>1000,50098=>1000,50099=>1000,50100=>1000,50101=>1000, -50102=>1000,50103=>1000,50104=>1000,50105=>1000,50106=>1000,50107=>1000,50108=>1000,50109=>1000,50110=>1000,50111=>1000, -50112=>1000,50113=>1000,50114=>1000,50115=>1000,50116=>1000,50117=>1000,50118=>1000,50119=>1000,50120=>1000,50121=>1000, -50122=>1000,50123=>1000,50124=>1000,50125=>1000,50126=>1000,50127=>1000,50128=>1000,50129=>1000,50130=>1000,50131=>1000, -50132=>1000,50133=>1000,50134=>1000,50135=>1000,50136=>1000,50137=>1000,50138=>1000,50139=>1000,50140=>1000,50141=>1000, -50142=>1000,50143=>1000,50144=>1000,50145=>1000,50146=>1000,50147=>1000,50148=>1000,50149=>1000,50150=>1000,50151=>1000, -50152=>1000,50153=>1000,50154=>1000,50155=>1000,50156=>1000,50157=>1000,50158=>1000,50159=>1000,50160=>1000,50161=>1000, -50162=>1000,50163=>1000,50164=>1000,50165=>1000,50166=>1000,50167=>1000,50168=>1000,50169=>1000,50170=>1000,50171=>1000, -50172=>1000,50173=>1000,50174=>1000,50175=>1000,50176=>1000,50177=>1000,50178=>1000,50179=>1000,50180=>1000,50181=>1000, -50182=>1000,50183=>1000,50184=>1000,50185=>1000,50186=>1000,50187=>1000,50188=>1000,50189=>1000,50190=>1000,50191=>1000, -50192=>1000,50193=>1000,50194=>1000,50195=>1000,50196=>1000,50197=>1000,50198=>1000,50199=>1000,50200=>1000,50201=>1000, -50202=>1000,50203=>1000,50204=>1000,50205=>1000,50206=>1000,50207=>1000,50208=>1000,50209=>1000,50210=>1000,50211=>1000, -50212=>1000,50213=>1000,50214=>1000,50215=>1000,50216=>1000,50217=>1000,50218=>1000,50219=>1000,50220=>1000,50221=>1000, -50222=>1000,50223=>1000,50224=>1000,50225=>1000,50226=>1000,50227=>1000,50228=>1000,50229=>1000,50230=>1000,50231=>1000, -50232=>1000,50233=>1000,50234=>1000,50235=>1000,50236=>1000,50237=>1000,50238=>1000,50239=>1000,50240=>1000,50241=>1000, -50242=>1000,50243=>1000,50244=>1000,50245=>1000,50246=>1000,50247=>1000,50248=>1000,50249=>1000,50250=>1000,50251=>1000, -50252=>1000,50253=>1000,50254=>1000,50255=>1000,50256=>1000,50257=>1000,50258=>1000,50259=>1000,50260=>1000,50261=>1000, -50262=>1000,50263=>1000,50264=>1000,50265=>1000,50266=>1000,50267=>1000,50268=>1000,50269=>1000,50270=>1000,50271=>1000, -50272=>1000,50273=>1000,50274=>1000,50275=>1000,50276=>1000,50277=>1000,50278=>1000,50279=>1000,50280=>1000,50281=>1000, -50282=>1000,50283=>1000,50284=>1000,50285=>1000,50286=>1000,50287=>1000,50288=>1000,50289=>1000,50290=>1000,50291=>1000, -50292=>1000,50293=>1000,50294=>1000,50295=>1000,50296=>1000,50297=>1000,50298=>1000,50299=>1000,50300=>1000,50301=>1000, -50302=>1000,50303=>1000,50304=>1000,50305=>1000,50306=>1000,50307=>1000,50308=>1000,50309=>1000,50310=>1000,50311=>1000, -50312=>1000,50313=>1000,50314=>1000,50315=>1000,50316=>1000,50317=>1000,50318=>1000,50319=>1000,50320=>1000,50321=>1000, -50322=>1000,50323=>1000,50324=>1000,50325=>1000,50326=>1000,50327=>1000,50328=>1000,50329=>1000,50330=>1000,50331=>1000, -50332=>1000,50333=>1000,50334=>1000,50335=>1000,50336=>1000,50337=>1000,50338=>1000,50339=>1000,50340=>1000,50341=>1000, -50342=>1000,50343=>1000,50344=>1000,50345=>1000,50346=>1000,50347=>1000,50348=>1000,50349=>1000,50350=>1000,50351=>1000, -50352=>1000,50353=>1000,50354=>1000,50355=>1000,50356=>1000,50357=>1000,50358=>1000,50359=>1000,50360=>1000,50361=>1000, -50362=>1000,50363=>1000,50364=>1000,50365=>1000,50366=>1000,50367=>1000,50368=>1000,50369=>1000,50370=>1000,50371=>1000, -50372=>1000,50373=>1000,50374=>1000,50375=>1000,50376=>1000,50377=>1000,50378=>1000,50379=>1000,50380=>1000,50381=>1000, -50382=>1000,50383=>1000,50384=>1000,50385=>1000,50386=>1000,50387=>1000,50388=>1000,50389=>1000,50390=>1000,50391=>1000, -50392=>1000,50393=>1000,50394=>1000,50395=>1000,50396=>1000,50397=>1000,50398=>1000,50399=>1000,50400=>1000,50401=>1000, -50402=>1000,50403=>1000,50404=>1000,50405=>1000,50406=>1000,50407=>1000,50408=>1000,50409=>1000,50410=>1000,50411=>1000, -50412=>1000,50413=>1000,50414=>1000,50415=>1000,50416=>1000,50417=>1000,50418=>1000,50419=>1000,50420=>1000,50421=>1000, -50422=>1000,50423=>1000,50424=>1000,50425=>1000,50426=>1000,50427=>1000,50428=>1000,50429=>1000,50430=>1000,50431=>1000, -50432=>1000,50433=>1000,50434=>1000,50435=>1000,50436=>1000,50437=>1000,50438=>1000,50439=>1000,50440=>1000,50441=>1000, -50442=>1000,50443=>1000,50444=>1000,50445=>1000,50446=>1000,50447=>1000,50448=>1000,50449=>1000,50450=>1000,50451=>1000, -50452=>1000,50453=>1000,50454=>1000,50455=>1000,50456=>1000,50457=>1000,50458=>1000,50459=>1000,50460=>1000,50461=>1000, -50462=>1000,50463=>1000,50464=>1000,50465=>1000,50466=>1000,50467=>1000,50468=>1000,50469=>1000,50470=>1000,50471=>1000, -50472=>1000,50473=>1000,50474=>1000,50475=>1000,50476=>1000,50477=>1000,50478=>1000,50479=>1000,50480=>1000,50481=>1000, -50482=>1000,50483=>1000,50484=>1000,50485=>1000,50486=>1000,50487=>1000,50488=>1000,50489=>1000,50490=>1000,50491=>1000, -50492=>1000,50493=>1000,50494=>1000,50495=>1000,50496=>1000,50497=>1000,50498=>1000,50499=>1000,50500=>1000,50501=>1000, -50502=>1000,50503=>1000,50504=>1000,50505=>1000,50506=>1000,50507=>1000,50508=>1000,50509=>1000,50510=>1000,50511=>1000, -50512=>1000,50513=>1000,50514=>1000,50515=>1000,50516=>1000,50517=>1000,50518=>1000,50519=>1000,50520=>1000,50521=>1000, -50522=>1000,50523=>1000,50524=>1000,50525=>1000,50526=>1000,50527=>1000,50528=>1000,50529=>1000,50530=>1000,50531=>1000, -50532=>1000,50533=>1000,50534=>1000,50535=>1000,50536=>1000,50537=>1000,50538=>1000,50539=>1000,50540=>1000,50541=>1000, -50542=>1000,50543=>1000,50544=>1000,50545=>1000,50546=>1000,50547=>1000,50548=>1000,50549=>1000,50550=>1000,50551=>1000, -50552=>1000,50553=>1000,50554=>1000,50555=>1000,50556=>1000,50557=>1000,50558=>1000,50559=>1000,50560=>1000,50561=>1000, -50562=>1000,50563=>1000,50564=>1000,50565=>1000,50566=>1000,50567=>1000,50568=>1000,50569=>1000,50570=>1000,50571=>1000, -50572=>1000,50573=>1000,50574=>1000,50575=>1000,50576=>1000,50577=>1000,50578=>1000,50579=>1000,50580=>1000,50581=>1000, -50582=>1000,50583=>1000,50584=>1000,50585=>1000,50586=>1000,50587=>1000,50588=>1000,50589=>1000,50590=>1000,50591=>1000, -50592=>1000,50593=>1000,50594=>1000,50595=>1000,50596=>1000,50597=>1000,50598=>1000,50599=>1000,50600=>1000,50601=>1000, -50602=>1000,50603=>1000,50604=>1000,50605=>1000,50606=>1000,50607=>1000,50608=>1000,50609=>1000,50610=>1000,50611=>1000, -50612=>1000,50613=>1000,50614=>1000,50615=>1000,50616=>1000,50617=>1000,50618=>1000,50619=>1000,50620=>1000,50621=>1000, -50622=>1000,50623=>1000,50624=>1000,50625=>1000,50626=>1000,50627=>1000,50628=>1000,50629=>1000,50630=>1000,50631=>1000, -50632=>1000,50633=>1000,50634=>1000,50635=>1000,50636=>1000,50637=>1000,50638=>1000,50639=>1000,50640=>1000,50641=>1000, -50642=>1000,50643=>1000,50644=>1000,50645=>1000,50646=>1000,50647=>1000,50648=>1000,50649=>1000,50650=>1000,50651=>1000, -50652=>1000,50653=>1000,50654=>1000,50655=>1000,50656=>1000,50657=>1000,50658=>1000,50659=>1000,50660=>1000,50661=>1000, -50662=>1000,50663=>1000,50664=>1000,50665=>1000,50666=>1000,50667=>1000,50668=>1000,50669=>1000,50670=>1000,50671=>1000, -50672=>1000,50673=>1000,50674=>1000,50675=>1000,50676=>1000,50677=>1000,50678=>1000,50679=>1000,50680=>1000,50681=>1000, -50682=>1000,50683=>1000,50684=>1000,50685=>1000,50686=>1000,50687=>1000,50688=>1000,50689=>1000,50690=>1000,50691=>1000, -50692=>1000,50693=>1000,50694=>1000,50695=>1000,50696=>1000,50697=>1000,50698=>1000,50699=>1000,50700=>1000,50701=>1000, -50702=>1000,50703=>1000,50704=>1000,50705=>1000,50706=>1000,50707=>1000,50708=>1000,50709=>1000,50710=>1000,50711=>1000, -50712=>1000,50713=>1000,50714=>1000,50715=>1000,50716=>1000,50717=>1000,50718=>1000,50719=>1000,50720=>1000,50721=>1000, -50722=>1000,50723=>1000,50724=>1000,50725=>1000,50726=>1000,50727=>1000,50728=>1000,50729=>1000,50730=>1000,50731=>1000, -50732=>1000,50733=>1000,50734=>1000,50735=>1000,50736=>1000,50737=>1000,50738=>1000,50739=>1000,50740=>1000,50741=>1000, -50742=>1000,50743=>1000,50744=>1000,50745=>1000,50746=>1000,50747=>1000,50748=>1000,50749=>1000,50750=>1000,50751=>1000, -50752=>1000,50753=>1000,50754=>1000,50755=>1000,50756=>1000,50757=>1000,50758=>1000,50759=>1000,50760=>1000,50761=>1000, -50762=>1000,50763=>1000,50764=>1000,50765=>1000,50766=>1000,50767=>1000,50768=>1000,50769=>1000,50770=>1000,50771=>1000, -50772=>1000,50773=>1000,50774=>1000,50775=>1000,50776=>1000,50777=>1000,50778=>1000,50779=>1000,50780=>1000,50781=>1000, -50782=>1000,50783=>1000,50784=>1000,50785=>1000,50786=>1000,50787=>1000,50788=>1000,50789=>1000,50790=>1000,50791=>1000, -50792=>1000,50793=>1000,50794=>1000,50795=>1000,50796=>1000,50797=>1000,50798=>1000,50799=>1000,50800=>1000,50801=>1000, -50802=>1000,50803=>1000,50804=>1000,50805=>1000,50806=>1000,50807=>1000,50808=>1000,50809=>1000,50810=>1000,50811=>1000, -50812=>1000,50813=>1000,50814=>1000,50815=>1000,50816=>1000,50817=>1000,50818=>1000,50819=>1000,50820=>1000,50821=>1000, -50822=>1000,50823=>1000,50824=>1000,50825=>1000,50826=>1000,50827=>1000,50828=>1000,50829=>1000,50830=>1000,50831=>1000, -50832=>1000,50833=>1000,50834=>1000,50835=>1000,50836=>1000,50837=>1000,50838=>1000,50839=>1000,50840=>1000,50841=>1000, -50842=>1000,50843=>1000,50844=>1000,50845=>1000,50846=>1000,50847=>1000,50848=>1000,50849=>1000,50850=>1000,50851=>1000, -50852=>1000,50853=>1000,50854=>1000,50855=>1000,50856=>1000,50857=>1000,50858=>1000,50859=>1000,50860=>1000,50861=>1000, -50862=>1000,50863=>1000,50864=>1000,50865=>1000,50866=>1000,50867=>1000,50868=>1000,50869=>1000,50870=>1000,50871=>1000, -50872=>1000,50873=>1000,50874=>1000,50875=>1000,50876=>1000,50877=>1000,50878=>1000,50879=>1000,50880=>1000,50881=>1000, -50882=>1000,50883=>1000,50884=>1000,50885=>1000,50886=>1000,50887=>1000,50888=>1000,50889=>1000,50890=>1000,50891=>1000, -50892=>1000,50893=>1000,50894=>1000,50895=>1000,50896=>1000,50897=>1000,50898=>1000,50899=>1000,50900=>1000,50901=>1000, -50902=>1000,50903=>1000,50904=>1000,50905=>1000,50906=>1000,50907=>1000,50908=>1000,50909=>1000,50910=>1000,50911=>1000, -50912=>1000,50913=>1000,50914=>1000,50915=>1000,50916=>1000,50917=>1000,50918=>1000,50919=>1000,50920=>1000,50921=>1000, -50922=>1000,50923=>1000,50924=>1000,50925=>1000,50926=>1000,50927=>1000,50928=>1000,50929=>1000,50930=>1000,50931=>1000, -50932=>1000,50933=>1000,50934=>1000,50935=>1000,50936=>1000,50937=>1000,50938=>1000,50939=>1000,50940=>1000,50941=>1000, -50942=>1000,50943=>1000,50944=>1000,50945=>1000,50946=>1000,50947=>1000,50948=>1000,50949=>1000,50950=>1000,50951=>1000, -50952=>1000,50953=>1000,50954=>1000,50955=>1000,50956=>1000,50957=>1000,50958=>1000,50959=>1000,50960=>1000,50961=>1000, -50962=>1000,50963=>1000,50964=>1000,50965=>1000,50966=>1000,50967=>1000,50968=>1000,50969=>1000,50970=>1000,50971=>1000, -50972=>1000,50973=>1000,50974=>1000,50975=>1000,50976=>1000,50977=>1000,50978=>1000,50979=>1000,50980=>1000,50981=>1000, -50982=>1000,50983=>1000,50984=>1000,50985=>1000,50986=>1000,50987=>1000,50988=>1000,50989=>1000,50990=>1000,50991=>1000, -50992=>1000,50993=>1000,50994=>1000,50995=>1000,50996=>1000,50997=>1000,50998=>1000,50999=>1000,51000=>1000,51001=>1000, -51002=>1000,51003=>1000,51004=>1000,51005=>1000,51006=>1000,51007=>1000,51008=>1000,51009=>1000,51010=>1000,51011=>1000, -51012=>1000,51013=>1000,51014=>1000,51015=>1000,51016=>1000,51017=>1000,51018=>1000,51019=>1000,51020=>1000,51021=>1000, -51022=>1000,51023=>1000,51024=>1000,51025=>1000,51026=>1000,51027=>1000,51028=>1000,51029=>1000,51030=>1000,51031=>1000, -51032=>1000,51033=>1000,51034=>1000,51035=>1000,51036=>1000,51037=>1000,51038=>1000,51039=>1000,51040=>1000,51041=>1000, -51042=>1000,51043=>1000,51044=>1000,51045=>1000,51046=>1000,51047=>1000,51048=>1000,51049=>1000,51050=>1000,51051=>1000, -51052=>1000,51053=>1000,51054=>1000,51055=>1000,51056=>1000,51057=>1000,51058=>1000,51059=>1000,51060=>1000,51061=>1000, -51062=>1000,51063=>1000,51064=>1000,51065=>1000,51066=>1000,51067=>1000,51068=>1000,51069=>1000,51070=>1000,51071=>1000, -51072=>1000,51073=>1000,51074=>1000,51075=>1000,51076=>1000,51077=>1000,51078=>1000,51079=>1000,51080=>1000,51081=>1000, -51082=>1000,51083=>1000,51084=>1000,51085=>1000,51086=>1000,51087=>1000,51088=>1000,51089=>1000,51090=>1000,51091=>1000, -51092=>1000,51093=>1000,51094=>1000,51095=>1000,51096=>1000,51097=>1000,51098=>1000,51099=>1000,51100=>1000,51101=>1000, -51102=>1000,51103=>1000,51104=>1000,51105=>1000,51106=>1000,51107=>1000,51108=>1000,51109=>1000,51110=>1000,51111=>1000, -51112=>1000,51113=>1000,51114=>1000,51115=>1000,51116=>1000,51117=>1000,51118=>1000,51119=>1000,51120=>1000,51121=>1000, -51122=>1000,51123=>1000,51124=>1000,51125=>1000,51126=>1000,51127=>1000,51128=>1000,51129=>1000,51130=>1000,51131=>1000, -51132=>1000,51133=>1000,51134=>1000,51135=>1000,51136=>1000,51137=>1000,51138=>1000,51139=>1000,51140=>1000,51141=>1000, -51142=>1000,51143=>1000,51144=>1000,51145=>1000,51146=>1000,51147=>1000,51148=>1000,51149=>1000,51150=>1000,51151=>1000, -51152=>1000,51153=>1000,51154=>1000,51155=>1000,51156=>1000,51157=>1000,51158=>1000,51159=>1000,51160=>1000,51161=>1000, -51162=>1000,51163=>1000,51164=>1000,51165=>1000,51166=>1000,51167=>1000,51168=>1000,51169=>1000,51170=>1000,51171=>1000, -51172=>1000,51173=>1000,51174=>1000,51175=>1000,51176=>1000,51177=>1000,51178=>1000,51179=>1000,51180=>1000,51181=>1000, -51182=>1000,51183=>1000,51184=>1000,51185=>1000,51186=>1000,51187=>1000,51188=>1000,51189=>1000,51190=>1000,51191=>1000, -51192=>1000,51193=>1000,51194=>1000,51195=>1000,51196=>1000,51197=>1000,51198=>1000,51199=>1000,51200=>1000,51201=>1000, -51202=>1000,51203=>1000,51204=>1000,51205=>1000,51206=>1000,51207=>1000,51208=>1000,51209=>1000,51210=>1000,51211=>1000, -51212=>1000,51213=>1000,51214=>1000,51215=>1000,51216=>1000,51217=>1000,51218=>1000,51219=>1000,51220=>1000,51221=>1000, -51222=>1000,51223=>1000,51224=>1000,51225=>1000,51226=>1000,51227=>1000,51228=>1000,51229=>1000,51230=>1000,51231=>1000, -51232=>1000,51233=>1000,51234=>1000,51235=>1000,51236=>1000,51237=>1000,51238=>1000,51239=>1000,51240=>1000,51241=>1000, -51242=>1000,51243=>1000,51244=>1000,51245=>1000,51246=>1000,51247=>1000,51248=>1000,51249=>1000,51250=>1000,51251=>1000, -51252=>1000,51253=>1000,51254=>1000,51255=>1000,51256=>1000,51257=>1000,51258=>1000,51259=>1000,51260=>1000,51261=>1000, -51262=>1000,51263=>1000,51264=>1000,51265=>1000,51266=>1000,51267=>1000,51268=>1000,51269=>1000,51270=>1000,51271=>1000, -51272=>1000,51273=>1000,51274=>1000,51275=>1000,51276=>1000,51277=>1000,51278=>1000,51279=>1000,51280=>1000,51281=>1000, -51282=>1000,51283=>1000,51284=>1000,51285=>1000,51286=>1000,51287=>1000,51288=>1000,51289=>1000,51290=>1000,51291=>1000, -51292=>1000,51293=>1000,51294=>1000,51295=>1000,51296=>1000,51297=>1000,51298=>1000,51299=>1000,51300=>1000,51301=>1000, -51302=>1000,51303=>1000,51304=>1000,51305=>1000,51306=>1000,51307=>1000,51308=>1000,51309=>1000,51310=>1000,51311=>1000, -51312=>1000,51313=>1000,51314=>1000,51315=>1000,51316=>1000,51317=>1000,51318=>1000,51319=>1000,51320=>1000,51321=>1000, -51322=>1000,51323=>1000,51324=>1000,51325=>1000,51326=>1000,51327=>1000,51328=>1000,51329=>1000,51330=>1000,51331=>1000, -51332=>1000,51333=>1000,51334=>1000,51335=>1000,51336=>1000,51337=>1000,51338=>1000,51339=>1000,51340=>1000,51341=>1000, -51342=>1000,51343=>1000,51344=>1000,51345=>1000,51346=>1000,51347=>1000,51348=>1000,51349=>1000,51350=>1000,51351=>1000, -51352=>1000,51353=>1000,51354=>1000,51355=>1000,51356=>1000,51357=>1000,51358=>1000,51359=>1000,51360=>1000,51361=>1000, -51362=>1000,51363=>1000,51364=>1000,51365=>1000,51366=>1000,51367=>1000,51368=>1000,51369=>1000,51370=>1000,51371=>1000, -51372=>1000,51373=>1000,51374=>1000,51375=>1000,51376=>1000,51377=>1000,51378=>1000,51379=>1000,51380=>1000,51381=>1000, -51382=>1000,51383=>1000,51384=>1000,51385=>1000,51386=>1000,51387=>1000,51388=>1000,51389=>1000,51390=>1000,51391=>1000, -51392=>1000,51393=>1000,51394=>1000,51395=>1000,51396=>1000,51397=>1000,51398=>1000,51399=>1000,51400=>1000,51401=>1000, -51402=>1000,51403=>1000,51404=>1000,51405=>1000,51406=>1000,51407=>1000,51408=>1000,51409=>1000,51410=>1000,51411=>1000, -51412=>1000,51413=>1000,51414=>1000,51415=>1000,51416=>1000,51417=>1000,51418=>1000,51419=>1000,51420=>1000,51421=>1000, -51422=>1000,51423=>1000,51424=>1000,51425=>1000,51426=>1000,51427=>1000,51428=>1000,51429=>1000,51430=>1000,51431=>1000, -51432=>1000,51433=>1000,51434=>1000,51435=>1000,51436=>1000,51437=>1000,51438=>1000,51439=>1000,51440=>1000,51441=>1000, -51442=>1000,51443=>1000,51444=>1000,51445=>1000,51446=>1000,51447=>1000,51448=>1000,51449=>1000,51450=>1000,51451=>1000, -51452=>1000,51453=>1000,51454=>1000,51455=>1000,51456=>1000,51457=>1000,51458=>1000,51459=>1000,51460=>1000,51461=>1000, -51462=>1000,51463=>1000,51464=>1000,51465=>1000,51466=>1000,51467=>1000,51468=>1000,51469=>1000,51470=>1000,51471=>1000, -51472=>1000,51473=>1000,51474=>1000,51475=>1000,51476=>1000,51477=>1000,51478=>1000,51479=>1000,51480=>1000,51481=>1000, -51482=>1000,51483=>1000,51484=>1000,51485=>1000,51486=>1000,51487=>1000,51488=>1000,51489=>1000,51490=>1000,51491=>1000, -51492=>1000,51493=>1000,51494=>1000,51495=>1000,51496=>1000,51497=>1000,51498=>1000,51499=>1000,51500=>1000,51501=>1000, -51502=>1000,51503=>1000,51504=>1000,51505=>1000,51506=>1000,51507=>1000,51508=>1000,51509=>1000,51510=>1000,51511=>1000, -51512=>1000,51513=>1000,51514=>1000,51515=>1000,51516=>1000,51517=>1000,51518=>1000,51519=>1000,51520=>1000,51521=>1000, -51522=>1000,51523=>1000,51524=>1000,51525=>1000,51526=>1000,51527=>1000,51528=>1000,51529=>1000,51530=>1000,51531=>1000, -51532=>1000,51533=>1000,51534=>1000,51535=>1000,51536=>1000,51537=>1000,51538=>1000,51539=>1000,51540=>1000,51541=>1000, -51542=>1000,51543=>1000,51544=>1000,51545=>1000,51546=>1000,51547=>1000,51548=>1000,51549=>1000,51550=>1000,51551=>1000, -51552=>1000,51553=>1000,51554=>1000,51555=>1000,51556=>1000,51557=>1000,51558=>1000,51559=>1000,51560=>1000,51561=>1000, -51562=>1000,51563=>1000,51564=>1000,51565=>1000,51566=>1000,51567=>1000,51568=>1000,51569=>1000,51570=>1000,51571=>1000, -51572=>1000,51573=>1000,51574=>1000,51575=>1000,51576=>1000,51577=>1000,51578=>1000,51579=>1000,51580=>1000,51581=>1000, -51582=>1000,51583=>1000,51584=>1000,51585=>1000,51586=>1000,51587=>1000,51588=>1000,51589=>1000,51590=>1000,51591=>1000, -51592=>1000,51593=>1000,51594=>1000,51595=>1000,51596=>1000,51597=>1000,51598=>1000,51599=>1000,51600=>1000,51601=>1000, -51602=>1000,51603=>1000,51604=>1000,51605=>1000,51606=>1000,51607=>1000,51608=>1000,51609=>1000,51610=>1000,51611=>1000, -51612=>1000,51613=>1000,51614=>1000,51615=>1000,51616=>1000,51617=>1000,51618=>1000,51619=>1000,51620=>1000,51621=>1000, -51622=>1000,51623=>1000,51624=>1000,51625=>1000,51626=>1000,51627=>1000,51628=>1000,51629=>1000,51630=>1000,51631=>1000, -51632=>1000,51633=>1000,51634=>1000,51635=>1000,51636=>1000,51637=>1000,51638=>1000,51639=>1000,51640=>1000,51641=>1000, -51642=>1000,51643=>1000,51644=>1000,51645=>1000,51646=>1000,51647=>1000,51648=>1000,51649=>1000,51650=>1000,51651=>1000, -51652=>1000,51653=>1000,51654=>1000,51655=>1000,51656=>1000,51657=>1000,51658=>1000,51659=>1000,51660=>1000,51661=>1000, -51662=>1000,51663=>1000,51664=>1000,51665=>1000,51666=>1000,51667=>1000,51668=>1000,51669=>1000,51670=>1000,51671=>1000, -51672=>1000,51673=>1000,51674=>1000,51675=>1000,51676=>1000,51677=>1000,51678=>1000,51679=>1000,51680=>1000,51681=>1000, -51682=>1000,51683=>1000,51684=>1000,51685=>1000,51686=>1000,51687=>1000,51688=>1000,51689=>1000,51690=>1000,51691=>1000, -51692=>1000,51693=>1000,51694=>1000,51695=>1000,51696=>1000,51697=>1000,51698=>1000,51699=>1000,51700=>1000,51701=>1000, -51702=>1000,51703=>1000,51704=>1000,51705=>1000,51706=>1000,51707=>1000,51708=>1000,51709=>1000,51710=>1000,51711=>1000, -51712=>1000,51713=>1000,51714=>1000,51715=>1000,51716=>1000,51717=>1000,51718=>1000,51719=>1000,51720=>1000,51721=>1000, -51722=>1000,51723=>1000,51724=>1000,51725=>1000,51726=>1000,51727=>1000,51728=>1000,51729=>1000,51730=>1000,51731=>1000, -51732=>1000,51733=>1000,51734=>1000,51735=>1000,51736=>1000,51737=>1000,51738=>1000,51739=>1000,51740=>1000,51741=>1000, -51742=>1000,51743=>1000,51744=>1000,51745=>1000,51746=>1000,51747=>1000,51748=>1000,51749=>1000,51750=>1000,51751=>1000, -51752=>1000,51753=>1000,51754=>1000,51755=>1000,51756=>1000,51757=>1000,51758=>1000,51759=>1000,51760=>1000,51761=>1000, -51762=>1000,51763=>1000,51764=>1000,51765=>1000,51766=>1000,51767=>1000,51768=>1000,51769=>1000,51770=>1000,51771=>1000, -51772=>1000,51773=>1000,51774=>1000,51775=>1000,51776=>1000,51777=>1000,51778=>1000,51779=>1000,51780=>1000,51781=>1000, -51782=>1000,51783=>1000,51784=>1000,51785=>1000,51786=>1000,51787=>1000,51788=>1000,51789=>1000,51790=>1000,51791=>1000, -51792=>1000,51793=>1000,51794=>1000,51795=>1000,51796=>1000,51797=>1000,51798=>1000,51799=>1000,51800=>1000,51801=>1000, -51802=>1000,51803=>1000,51804=>1000,51805=>1000,51806=>1000,51807=>1000,51808=>1000,51809=>1000,51810=>1000,51811=>1000, -51812=>1000,51813=>1000,51814=>1000,51815=>1000,51816=>1000,51817=>1000,51818=>1000,51819=>1000,51820=>1000,51821=>1000, -51822=>1000,51823=>1000,51824=>1000,51825=>1000,51826=>1000,51827=>1000,51828=>1000,51829=>1000,51830=>1000,51831=>1000, -51832=>1000,51833=>1000,51834=>1000,51835=>1000,51836=>1000,51837=>1000,51838=>1000,51839=>1000,51840=>1000,51841=>1000, -51842=>1000,51843=>1000,51844=>1000,51845=>1000,51846=>1000,51847=>1000,51848=>1000,51849=>1000,51850=>1000,51851=>1000, -51852=>1000,51853=>1000,51854=>1000,51855=>1000,51856=>1000,51857=>1000,51858=>1000,51859=>1000,51860=>1000,51861=>1000, -51862=>1000,51863=>1000,51864=>1000,51865=>1000,51866=>1000,51867=>1000,51868=>1000,51869=>1000,51870=>1000,51871=>1000, -51872=>1000,51873=>1000,51874=>1000,51875=>1000,51876=>1000,51877=>1000,51878=>1000,51879=>1000,51880=>1000,51881=>1000, -51882=>1000,51883=>1000,51884=>1000,51885=>1000,51886=>1000,51887=>1000,51888=>1000,51889=>1000,51890=>1000,51891=>1000, -51892=>1000,51893=>1000,51894=>1000,51895=>1000,51896=>1000,51897=>1000,51898=>1000,51899=>1000,51900=>1000,51901=>1000, -51902=>1000,51903=>1000,51904=>1000,51905=>1000,51906=>1000,51907=>1000,51908=>1000,51909=>1000,51910=>1000,51911=>1000, -51912=>1000,51913=>1000,51914=>1000,51915=>1000,51916=>1000,51917=>1000,51918=>1000,51919=>1000,51920=>1000,51921=>1000, -51922=>1000,51923=>1000,51924=>1000,51925=>1000,51926=>1000,51927=>1000,51928=>1000,51929=>1000,51930=>1000,51931=>1000, -51932=>1000,51933=>1000,51934=>1000,51935=>1000,51936=>1000,51937=>1000,51938=>1000,51939=>1000,51940=>1000,51941=>1000, -51942=>1000,51943=>1000,51944=>1000,51945=>1000,51946=>1000,51947=>1000,51948=>1000,51949=>1000,51950=>1000,51951=>1000, -51952=>1000,51953=>1000,51954=>1000,51955=>1000,51956=>1000,51957=>1000,51958=>1000,51959=>1000,51960=>1000,51961=>1000, -51962=>1000,51963=>1000,51964=>1000,51965=>1000,51966=>1000,51967=>1000,51968=>1000,51969=>1000,51970=>1000,51971=>1000, -51972=>1000,51973=>1000,51974=>1000,51975=>1000,51976=>1000,51977=>1000,51978=>1000,51979=>1000,51980=>1000,51981=>1000, -51982=>1000,51983=>1000,51984=>1000,51985=>1000,51986=>1000,51987=>1000,51988=>1000,51989=>1000,51990=>1000,51991=>1000, -51992=>1000,51993=>1000,51994=>1000,51995=>1000,51996=>1000,51997=>1000,51998=>1000,51999=>1000,52000=>1000,52001=>1000, -52002=>1000,52003=>1000,52004=>1000,52005=>1000,52006=>1000,52007=>1000,52008=>1000,52009=>1000,52010=>1000,52011=>1000, -52012=>1000,52013=>1000,52014=>1000,52015=>1000,52016=>1000,52017=>1000,52018=>1000,52019=>1000,52020=>1000,52021=>1000, -52022=>1000,52023=>1000,52024=>1000,52025=>1000,52026=>1000,52027=>1000,52028=>1000,52029=>1000,52030=>1000,52031=>1000, -52032=>1000,52033=>1000,52034=>1000,52035=>1000,52036=>1000,52037=>1000,52038=>1000,52039=>1000,52040=>1000,52041=>1000, -52042=>1000,52043=>1000,52044=>1000,52045=>1000,52046=>1000,52047=>1000,52048=>1000,52049=>1000,52050=>1000,52051=>1000, -52052=>1000,52053=>1000,52054=>1000,52055=>1000,52056=>1000,52057=>1000,52058=>1000,52059=>1000,52060=>1000,52061=>1000, -52062=>1000,52063=>1000,52064=>1000,52065=>1000,52066=>1000,52067=>1000,52068=>1000,52069=>1000,52070=>1000,52071=>1000, -52072=>1000,52073=>1000,52074=>1000,52075=>1000,52076=>1000,52077=>1000,52078=>1000,52079=>1000,52080=>1000,52081=>1000, -52082=>1000,52083=>1000,52084=>1000,52085=>1000,52086=>1000,52087=>1000,52088=>1000,52089=>1000,52090=>1000,52091=>1000, -52092=>1000,52093=>1000,52094=>1000,52095=>1000,52096=>1000,52097=>1000,52098=>1000,52099=>1000,52100=>1000,52101=>1000, -52102=>1000,52103=>1000,52104=>1000,52105=>1000,52106=>1000,52107=>1000,52108=>1000,52109=>1000,52110=>1000,52111=>1000, -52112=>1000,52113=>1000,52114=>1000,52115=>1000,52116=>1000,52117=>1000,52118=>1000,52119=>1000,52120=>1000,52121=>1000, -52122=>1000,52123=>1000,52124=>1000,52125=>1000,52126=>1000,52127=>1000,52128=>1000,52129=>1000,52130=>1000,52131=>1000, -52132=>1000,52133=>1000,52134=>1000,52135=>1000,52136=>1000,52137=>1000,52138=>1000,52139=>1000,52140=>1000,52141=>1000, -52142=>1000,52143=>1000,52144=>1000,52145=>1000,52146=>1000,52147=>1000,52148=>1000,52149=>1000,52150=>1000,52151=>1000, -52152=>1000,52153=>1000,52154=>1000,52155=>1000,52156=>1000,52157=>1000,52158=>1000,52159=>1000,52160=>1000,52161=>1000, -52162=>1000,52163=>1000,52164=>1000,52165=>1000,52166=>1000,52167=>1000,52168=>1000,52169=>1000,52170=>1000,52171=>1000, -52172=>1000,52173=>1000,52174=>1000,52175=>1000,52176=>1000,52177=>1000,52178=>1000,52179=>1000,52180=>1000,52181=>1000, -52182=>1000,52183=>1000,52184=>1000,52185=>1000,52186=>1000,52187=>1000,52188=>1000,52189=>1000,52190=>1000,52191=>1000, -52192=>1000,52193=>1000,52194=>1000,52195=>1000,52196=>1000,52197=>1000,52198=>1000,52199=>1000,52200=>1000,52201=>1000, -52202=>1000,52203=>1000,52204=>1000,52205=>1000,52206=>1000,52207=>1000,52208=>1000,52209=>1000,52210=>1000,52211=>1000, -52212=>1000,52213=>1000,52214=>1000,52215=>1000,52216=>1000,52217=>1000,52218=>1000,52219=>1000,52220=>1000,52221=>1000, -52222=>1000,52223=>1000,52224=>1000,52225=>1000,52226=>1000,52227=>1000,52228=>1000,52229=>1000,52230=>1000,52231=>1000, -52232=>1000,52233=>1000,52234=>1000,52235=>1000,52236=>1000,52237=>1000,52238=>1000,52239=>1000,52240=>1000,52241=>1000, -52242=>1000,52243=>1000,52244=>1000,52245=>1000,52246=>1000,52247=>1000,52248=>1000,52249=>1000,52250=>1000,52251=>1000, -52252=>1000,52253=>1000,52254=>1000,52255=>1000,52256=>1000,52257=>1000,52258=>1000,52259=>1000,52260=>1000,52261=>1000, -52262=>1000,52263=>1000,52264=>1000,52265=>1000,52266=>1000,52267=>1000,52268=>1000,52269=>1000,52270=>1000,52271=>1000, -52272=>1000,52273=>1000,52274=>1000,52275=>1000,52276=>1000,52277=>1000,52278=>1000,52279=>1000,52280=>1000,52281=>1000, -52282=>1000,52283=>1000,52284=>1000,52285=>1000,52286=>1000,52287=>1000,52288=>1000,52289=>1000,52290=>1000,52291=>1000, -52292=>1000,52293=>1000,52294=>1000,52295=>1000,52296=>1000,52297=>1000,52298=>1000,52299=>1000,52300=>1000,52301=>1000, -52302=>1000,52303=>1000,52304=>1000,52305=>1000,52306=>1000,52307=>1000,52308=>1000,52309=>1000,52310=>1000,52311=>1000, -52312=>1000,52313=>1000,52314=>1000,52315=>1000,52316=>1000,52317=>1000,52318=>1000,52319=>1000,52320=>1000,52321=>1000, -52322=>1000,52323=>1000,52324=>1000,52325=>1000,52326=>1000,52327=>1000,52328=>1000,52329=>1000,52330=>1000,52331=>1000, -52332=>1000,52333=>1000,52334=>1000,52335=>1000,52336=>1000,52337=>1000,52338=>1000,52339=>1000,52340=>1000,52341=>1000, -52342=>1000,52343=>1000,52344=>1000,52345=>1000,52346=>1000,52347=>1000,52348=>1000,52349=>1000,52350=>1000,52351=>1000, -52352=>1000,52353=>1000,52354=>1000,52355=>1000,52356=>1000,52357=>1000,52358=>1000,52359=>1000,52360=>1000,52361=>1000, -52362=>1000,52363=>1000,52364=>1000,52365=>1000,52366=>1000,52367=>1000,52368=>1000,52369=>1000,52370=>1000,52371=>1000, -52372=>1000,52373=>1000,52374=>1000,52375=>1000,52376=>1000,52377=>1000,52378=>1000,52379=>1000,52380=>1000,52381=>1000, -52382=>1000,52383=>1000,52384=>1000,52385=>1000,52386=>1000,52387=>1000,52388=>1000,52389=>1000,52390=>1000,52391=>1000, -52392=>1000,52393=>1000,52394=>1000,52395=>1000,52396=>1000,52397=>1000,52398=>1000,52399=>1000,52400=>1000,52401=>1000, -52402=>1000,52403=>1000,52404=>1000,52405=>1000,52406=>1000,52407=>1000,52408=>1000,52409=>1000,52410=>1000,52411=>1000, -52412=>1000,52413=>1000,52414=>1000,52415=>1000,52416=>1000,52417=>1000,52418=>1000,52419=>1000,52420=>1000,52421=>1000, -52422=>1000,52423=>1000,52424=>1000,52425=>1000,52426=>1000,52427=>1000,52428=>1000,52429=>1000,52430=>1000,52431=>1000, -52432=>1000,52433=>1000,52434=>1000,52435=>1000,52436=>1000,52437=>1000,52438=>1000,52439=>1000,52440=>1000,52441=>1000, -52442=>1000,52443=>1000,52444=>1000,52445=>1000,52446=>1000,52447=>1000,52448=>1000,52449=>1000,52450=>1000,52451=>1000, -52452=>1000,52453=>1000,52454=>1000,52455=>1000,52456=>1000,52457=>1000,52458=>1000,52459=>1000,52460=>1000,52461=>1000, -52462=>1000,52463=>1000,52464=>1000,52465=>1000,52466=>1000,52467=>1000,52468=>1000,52469=>1000,52470=>1000,52471=>1000, -52472=>1000,52473=>1000,52474=>1000,52475=>1000,52476=>1000,52477=>1000,52478=>1000,52479=>1000,52480=>1000,52481=>1000, -52482=>1000,52483=>1000,52484=>1000,52485=>1000,52486=>1000,52487=>1000,52488=>1000,52489=>1000,52490=>1000,52491=>1000, -52492=>1000,52493=>1000,52494=>1000,52495=>1000,52496=>1000,52497=>1000,52498=>1000,52499=>1000,52500=>1000,52501=>1000, -52502=>1000,52503=>1000,52504=>1000,52505=>1000,52506=>1000,52507=>1000,52508=>1000,52509=>1000,52510=>1000,52511=>1000, -52512=>1000,52513=>1000,52514=>1000,52515=>1000,52516=>1000,52517=>1000,52518=>1000,52519=>1000,52520=>1000,52521=>1000, -52522=>1000,52523=>1000,52524=>1000,52525=>1000,52526=>1000,52527=>1000,52528=>1000,52529=>1000,52530=>1000,52531=>1000, -52532=>1000,52533=>1000,52534=>1000,52535=>1000,52536=>1000,52537=>1000,52538=>1000,52539=>1000,52540=>1000,52541=>1000, -52542=>1000,52543=>1000,52544=>1000,52545=>1000,52546=>1000,52547=>1000,52548=>1000,52549=>1000,52550=>1000,52551=>1000, -52552=>1000,52553=>1000,52554=>1000,52555=>1000,52556=>1000,52557=>1000,52558=>1000,52559=>1000,52560=>1000,52561=>1000, -52562=>1000,52563=>1000,52564=>1000,52565=>1000,52566=>1000,52567=>1000,52568=>1000,52569=>1000,52570=>1000,52571=>1000, -52572=>1000,52573=>1000,52574=>1000,52575=>1000,52576=>1000,52577=>1000,52578=>1000,52579=>1000,52580=>1000,52581=>1000, -52582=>1000,52583=>1000,52584=>1000,52585=>1000,52586=>1000,52587=>1000,52588=>1000,52589=>1000,52590=>1000,52591=>1000, -52592=>1000,52593=>1000,52594=>1000,52595=>1000,52596=>1000,52597=>1000,52598=>1000,52599=>1000,52600=>1000,52601=>1000, -52602=>1000,52603=>1000,52604=>1000,52605=>1000,52606=>1000,52607=>1000,52608=>1000,52609=>1000,52610=>1000,52611=>1000, -52612=>1000,52613=>1000,52614=>1000,52615=>1000,52616=>1000,52617=>1000,52618=>1000,52619=>1000,52620=>1000,52621=>1000, -52622=>1000,52623=>1000,52624=>1000,52625=>1000,52626=>1000,52627=>1000,52628=>1000,52629=>1000,52630=>1000,52631=>1000, -52632=>1000,52633=>1000,52634=>1000,52635=>1000,52636=>1000,52637=>1000,52638=>1000,52639=>1000,52640=>1000,52641=>1000, -52642=>1000,52643=>1000,52644=>1000,52645=>1000,52646=>1000,52647=>1000,52648=>1000,52649=>1000,52650=>1000,52651=>1000, -52652=>1000,52653=>1000,52654=>1000,52655=>1000,52656=>1000,52657=>1000,52658=>1000,52659=>1000,52660=>1000,52661=>1000, -52662=>1000,52663=>1000,52664=>1000,52665=>1000,52666=>1000,52667=>1000,52668=>1000,52669=>1000,52670=>1000,52671=>1000, -52672=>1000,52673=>1000,52674=>1000,52675=>1000,52676=>1000,52677=>1000,52678=>1000,52679=>1000,52680=>1000,52681=>1000, -52682=>1000,52683=>1000,52684=>1000,52685=>1000,52686=>1000,52687=>1000,52688=>1000,52689=>1000,52690=>1000,52691=>1000, -52692=>1000,52693=>1000,52694=>1000,52695=>1000,52696=>1000,52697=>1000,52698=>1000,52699=>1000,52700=>1000,52701=>1000, -52702=>1000,52703=>1000,52704=>1000,52705=>1000,52706=>1000,52707=>1000,52708=>1000,52709=>1000,52710=>1000,52711=>1000, -52712=>1000,52713=>1000,52714=>1000,52715=>1000,52716=>1000,52717=>1000,52718=>1000,52719=>1000,52720=>1000,52721=>1000, -52722=>1000,52723=>1000,52724=>1000,52725=>1000,52726=>1000,52727=>1000,52728=>1000,52729=>1000,52730=>1000,52731=>1000, -52732=>1000,52733=>1000,52734=>1000,52735=>1000,52736=>1000,52737=>1000,52738=>1000,52739=>1000,52740=>1000,52741=>1000, -52742=>1000,52743=>1000,52744=>1000,52745=>1000,52746=>1000,52747=>1000,52748=>1000,52749=>1000,52750=>1000,52751=>1000, -52752=>1000,52753=>1000,52754=>1000,52755=>1000,52756=>1000,52757=>1000,52758=>1000,52759=>1000,52760=>1000,52761=>1000, -52762=>1000,52763=>1000,52764=>1000,52765=>1000,52766=>1000,52767=>1000,52768=>1000,52769=>1000,52770=>1000,52771=>1000, -52772=>1000,52773=>1000,52774=>1000,52775=>1000,52776=>1000,52777=>1000,52778=>1000,52779=>1000,52780=>1000,52781=>1000, -52782=>1000,52783=>1000,52784=>1000,52785=>1000,52786=>1000,52787=>1000,52788=>1000,52789=>1000,52790=>1000,52791=>1000, -52792=>1000,52793=>1000,52794=>1000,52795=>1000,52796=>1000,52797=>1000,52798=>1000,52799=>1000,52800=>1000,52801=>1000, -52802=>1000,52803=>1000,52804=>1000,52805=>1000,52806=>1000,52807=>1000,52808=>1000,52809=>1000,52810=>1000,52811=>1000, -52812=>1000,52813=>1000,52814=>1000,52815=>1000,52816=>1000,52817=>1000,52818=>1000,52819=>1000,52820=>1000,52821=>1000, -52822=>1000,52823=>1000,52824=>1000,52825=>1000,52826=>1000,52827=>1000,52828=>1000,52829=>1000,52830=>1000,52831=>1000, -52832=>1000,52833=>1000,52834=>1000,52835=>1000,52836=>1000,52837=>1000,52838=>1000,52839=>1000,52840=>1000,52841=>1000, -52842=>1000,52843=>1000,52844=>1000,52845=>1000,52846=>1000,52847=>1000,52848=>1000,52849=>1000,52850=>1000,52851=>1000, -52852=>1000,52853=>1000,52854=>1000,52855=>1000,52856=>1000,52857=>1000,52858=>1000,52859=>1000,52860=>1000,52861=>1000, -52862=>1000,52863=>1000,52864=>1000,52865=>1000,52866=>1000,52867=>1000,52868=>1000,52869=>1000,52870=>1000,52871=>1000, -52872=>1000,52873=>1000,52874=>1000,52875=>1000,52876=>1000,52877=>1000,52878=>1000,52879=>1000,52880=>1000,52881=>1000, -52882=>1000,52883=>1000,52884=>1000,52885=>1000,52886=>1000,52887=>1000,52888=>1000,52889=>1000,52890=>1000,52891=>1000, -52892=>1000,52893=>1000,52894=>1000,52895=>1000,52896=>1000,52897=>1000,52898=>1000,52899=>1000,52900=>1000,52901=>1000, -52902=>1000,52903=>1000,52904=>1000,52905=>1000,52906=>1000,52907=>1000,52908=>1000,52909=>1000,52910=>1000,52911=>1000, -52912=>1000,52913=>1000,52914=>1000,52915=>1000,52916=>1000,52917=>1000,52918=>1000,52919=>1000,52920=>1000,52921=>1000, -52922=>1000,52923=>1000,52924=>1000,52925=>1000,52926=>1000,52927=>1000,52928=>1000,52929=>1000,52930=>1000,52931=>1000, -52932=>1000,52933=>1000,52934=>1000,52935=>1000,52936=>1000,52937=>1000,52938=>1000,52939=>1000,52940=>1000,52941=>1000, -52942=>1000,52943=>1000,52944=>1000,52945=>1000,52946=>1000,52947=>1000,52948=>1000,52949=>1000,52950=>1000,52951=>1000, -52952=>1000,52953=>1000,52954=>1000,52955=>1000,52956=>1000,52957=>1000,52958=>1000,52959=>1000,52960=>1000,52961=>1000, -52962=>1000,52963=>1000,52964=>1000,52965=>1000,52966=>1000,52967=>1000,52968=>1000,52969=>1000,52970=>1000,52971=>1000, -52972=>1000,52973=>1000,52974=>1000,52975=>1000,52976=>1000,52977=>1000,52978=>1000,52979=>1000,52980=>1000,52981=>1000, -52982=>1000,52983=>1000,52984=>1000,52985=>1000,52986=>1000,52987=>1000,52988=>1000,52989=>1000,52990=>1000,52991=>1000, -52992=>1000,52993=>1000,52994=>1000,52995=>1000,52996=>1000,52997=>1000,52998=>1000,52999=>1000,53000=>1000,53001=>1000, -53002=>1000,53003=>1000,53004=>1000,53005=>1000,53006=>1000,53007=>1000,53008=>1000,53009=>1000,53010=>1000,53011=>1000, -53012=>1000,53013=>1000,53014=>1000,53015=>1000,53016=>1000,53017=>1000,53018=>1000,53019=>1000,53020=>1000,53021=>1000, -53022=>1000,53023=>1000,53024=>1000,53025=>1000,53026=>1000,53027=>1000,53028=>1000,53029=>1000,53030=>1000,53031=>1000, -53032=>1000,53033=>1000,53034=>1000,53035=>1000,53036=>1000,53037=>1000,53038=>1000,53039=>1000,53040=>1000,53041=>1000, -53042=>1000,53043=>1000,53044=>1000,53045=>1000,53046=>1000,53047=>1000,53048=>1000,53049=>1000,53050=>1000,53051=>1000, -53052=>1000,53053=>1000,53054=>1000,53055=>1000,53056=>1000,53057=>1000,53058=>1000,53059=>1000,53060=>1000,53061=>1000, -53062=>1000,53063=>1000,53064=>1000,53065=>1000,53066=>1000,53067=>1000,53068=>1000,53069=>1000,53070=>1000,53071=>1000, -53072=>1000,53073=>1000,53074=>1000,53075=>1000,53076=>1000,53077=>1000,53078=>1000,53079=>1000,53080=>1000,53081=>1000, -53082=>1000,53083=>1000,53084=>1000,53085=>1000,53086=>1000,53087=>1000,53088=>1000,53089=>1000,53090=>1000,53091=>1000, -53092=>1000,53093=>1000,53094=>1000,53095=>1000,53096=>1000,53097=>1000,53098=>1000,53099=>1000,53100=>1000,53101=>1000, -53102=>1000,53103=>1000,53104=>1000,53105=>1000,53106=>1000,53107=>1000,53108=>1000,53109=>1000,53110=>1000,53111=>1000, -53112=>1000,53113=>1000,53114=>1000,53115=>1000,53116=>1000,53117=>1000,53118=>1000,53119=>1000,53120=>1000,53121=>1000, -53122=>1000,53123=>1000,53124=>1000,53125=>1000,53126=>1000,53127=>1000,53128=>1000,53129=>1000,53130=>1000,53131=>1000, -53132=>1000,53133=>1000,53134=>1000,53135=>1000,53136=>1000,53137=>1000,53138=>1000,53139=>1000,53140=>1000,53141=>1000, -53142=>1000,53143=>1000,53144=>1000,53145=>1000,53146=>1000,53147=>1000,53148=>1000,53149=>1000,53150=>1000,53151=>1000, -53152=>1000,53153=>1000,53154=>1000,53155=>1000,53156=>1000,53157=>1000,53158=>1000,53159=>1000,53160=>1000,53161=>1000, -53162=>1000,53163=>1000,53164=>1000,53165=>1000,53166=>1000,53167=>1000,53168=>1000,53169=>1000,53170=>1000,53171=>1000, -53172=>1000,53173=>1000,53174=>1000,53175=>1000,53176=>1000,53177=>1000,53178=>1000,53179=>1000,53180=>1000,53181=>1000, -53182=>1000,53183=>1000,53184=>1000,53185=>1000,53186=>1000,53187=>1000,53188=>1000,53189=>1000,53190=>1000,53191=>1000, -53192=>1000,53193=>1000,53194=>1000,53195=>1000,53196=>1000,53197=>1000,53198=>1000,53199=>1000,53200=>1000,53201=>1000, -53202=>1000,53203=>1000,53204=>1000,53205=>1000,53206=>1000,53207=>1000,53208=>1000,53209=>1000,53210=>1000,53211=>1000, -53212=>1000,53213=>1000,53214=>1000,53215=>1000,53216=>1000,53217=>1000,53218=>1000,53219=>1000,53220=>1000,53221=>1000, -53222=>1000,53223=>1000,53224=>1000,53225=>1000,53226=>1000,53227=>1000,53228=>1000,53229=>1000,53230=>1000,53231=>1000, -53232=>1000,53233=>1000,53234=>1000,53235=>1000,53236=>1000,53237=>1000,53238=>1000,53239=>1000,53240=>1000,53241=>1000, -53242=>1000,53243=>1000,53244=>1000,53245=>1000,53246=>1000,53247=>1000,53248=>1000,53249=>1000,53250=>1000,53251=>1000, -53252=>1000,53253=>1000,53254=>1000,53255=>1000,53256=>1000,53257=>1000,53258=>1000,53259=>1000,53260=>1000,53261=>1000, -53262=>1000,53263=>1000,53264=>1000,53265=>1000,53266=>1000,53267=>1000,53268=>1000,53269=>1000,53270=>1000,53271=>1000, -53272=>1000,53273=>1000,53274=>1000,53275=>1000,53276=>1000,53277=>1000,53278=>1000,53279=>1000,53280=>1000,53281=>1000, -53282=>1000,53283=>1000,53284=>1000,53285=>1000,53286=>1000,53287=>1000,53288=>1000,53289=>1000,53290=>1000,53291=>1000, -53292=>1000,53293=>1000,53294=>1000,53295=>1000,53296=>1000,53297=>1000,53298=>1000,53299=>1000,53300=>1000,53301=>1000, -53302=>1000,53303=>1000,53304=>1000,53305=>1000,53306=>1000,53307=>1000,53308=>1000,53309=>1000,53310=>1000,53311=>1000, -53312=>1000,53313=>1000,53314=>1000,53315=>1000,53316=>1000,53317=>1000,53318=>1000,53319=>1000,53320=>1000,53321=>1000, -53322=>1000,53323=>1000,53324=>1000,53325=>1000,53326=>1000,53327=>1000,53328=>1000,53329=>1000,53330=>1000,53331=>1000, -53332=>1000,53333=>1000,53334=>1000,53335=>1000,53336=>1000,53337=>1000,53338=>1000,53339=>1000,53340=>1000,53341=>1000, -53342=>1000,53343=>1000,53344=>1000,53345=>1000,53346=>1000,53347=>1000,53348=>1000,53349=>1000,53350=>1000,53351=>1000, -53352=>1000,53353=>1000,53354=>1000,53355=>1000,53356=>1000,53357=>1000,53358=>1000,53359=>1000,53360=>1000,53361=>1000, -53362=>1000,53363=>1000,53364=>1000,53365=>1000,53366=>1000,53367=>1000,53368=>1000,53369=>1000,53370=>1000,53371=>1000, -53372=>1000,53373=>1000,53374=>1000,53375=>1000,53376=>1000,53377=>1000,53378=>1000,53379=>1000,53380=>1000,53381=>1000, -53382=>1000,53383=>1000,53384=>1000,53385=>1000,53386=>1000,53387=>1000,53388=>1000,53389=>1000,53390=>1000,53391=>1000, -53392=>1000,53393=>1000,53394=>1000,53395=>1000,53396=>1000,53397=>1000,53398=>1000,53399=>1000,53400=>1000,53401=>1000, -53402=>1000,53403=>1000,53404=>1000,53405=>1000,53406=>1000,53407=>1000,53408=>1000,53409=>1000,53410=>1000,53411=>1000, -53412=>1000,53413=>1000,53414=>1000,53415=>1000,53416=>1000,53417=>1000,53418=>1000,53419=>1000,53420=>1000,53421=>1000, -53422=>1000,53423=>1000,53424=>1000,53425=>1000,53426=>1000,53427=>1000,53428=>1000,53429=>1000,53430=>1000,53431=>1000, -53432=>1000,53433=>1000,53434=>1000,53435=>1000,53436=>1000,53437=>1000,53438=>1000,53439=>1000,53440=>1000,53441=>1000, -53442=>1000,53443=>1000,53444=>1000,53445=>1000,53446=>1000,53447=>1000,53448=>1000,53449=>1000,53450=>1000,53451=>1000, -53452=>1000,53453=>1000,53454=>1000,53455=>1000,53456=>1000,53457=>1000,53458=>1000,53459=>1000,53460=>1000,53461=>1000, -53462=>1000,53463=>1000,53464=>1000,53465=>1000,53466=>1000,53467=>1000,53468=>1000,53469=>1000,53470=>1000,53471=>1000, -53472=>1000,53473=>1000,53474=>1000,53475=>1000,53476=>1000,53477=>1000,53478=>1000,53479=>1000,53480=>1000,53481=>1000, -53482=>1000,53483=>1000,53484=>1000,53485=>1000,53486=>1000,53487=>1000,53488=>1000,53489=>1000,53490=>1000,53491=>1000, -53492=>1000,53493=>1000,53494=>1000,53495=>1000,53496=>1000,53497=>1000,53498=>1000,53499=>1000,53500=>1000,53501=>1000, -53502=>1000,53503=>1000,53504=>1000,53505=>1000,53506=>1000,53507=>1000,53508=>1000,53509=>1000,53510=>1000,53511=>1000, -53512=>1000,53513=>1000,53514=>1000,53515=>1000,53516=>1000,53517=>1000,53518=>1000,53519=>1000,53520=>1000,53521=>1000, -53522=>1000,53523=>1000,53524=>1000,53525=>1000,53526=>1000,53527=>1000,53528=>1000,53529=>1000,53530=>1000,53531=>1000, -53532=>1000,53533=>1000,53534=>1000,53535=>1000,53536=>1000,53537=>1000,53538=>1000,53539=>1000,53540=>1000,53541=>1000, -53542=>1000,53543=>1000,53544=>1000,53545=>1000,53546=>1000,53547=>1000,53548=>1000,53549=>1000,53550=>1000,53551=>1000, -53552=>1000,53553=>1000,53554=>1000,53555=>1000,53556=>1000,53557=>1000,53558=>1000,53559=>1000,53560=>1000,53561=>1000, -53562=>1000,53563=>1000,53564=>1000,53565=>1000,53566=>1000,53567=>1000,53568=>1000,53569=>1000,53570=>1000,53571=>1000, -53572=>1000,53573=>1000,53574=>1000,53575=>1000,53576=>1000,53577=>1000,53578=>1000,53579=>1000,53580=>1000,53581=>1000, -53582=>1000,53583=>1000,53584=>1000,53585=>1000,53586=>1000,53587=>1000,53588=>1000,53589=>1000,53590=>1000,53591=>1000, -53592=>1000,53593=>1000,53594=>1000,53595=>1000,53596=>1000,53597=>1000,53598=>1000,53599=>1000,53600=>1000,53601=>1000, -53602=>1000,53603=>1000,53604=>1000,53605=>1000,53606=>1000,53607=>1000,53608=>1000,53609=>1000,53610=>1000,53611=>1000, -53612=>1000,53613=>1000,53614=>1000,53615=>1000,53616=>1000,53617=>1000,53618=>1000,53619=>1000,53620=>1000,53621=>1000, -53622=>1000,53623=>1000,53624=>1000,53625=>1000,53626=>1000,53627=>1000,53628=>1000,53629=>1000,53630=>1000,53631=>1000, -53632=>1000,53633=>1000,53634=>1000,53635=>1000,53636=>1000,53637=>1000,53638=>1000,53639=>1000,53640=>1000,53641=>1000, -53642=>1000,53643=>1000,53644=>1000,53645=>1000,53646=>1000,53647=>1000,53648=>1000,53649=>1000,53650=>1000,53651=>1000, -53652=>1000,53653=>1000,53654=>1000,53655=>1000,53656=>1000,53657=>1000,53658=>1000,53659=>1000,53660=>1000,53661=>1000, -53662=>1000,53663=>1000,53664=>1000,53665=>1000,53666=>1000,53667=>1000,53668=>1000,53669=>1000,53670=>1000,53671=>1000, -53672=>1000,53673=>1000,53674=>1000,53675=>1000,53676=>1000,53677=>1000,53678=>1000,53679=>1000,53680=>1000,53681=>1000, -53682=>1000,53683=>1000,53684=>1000,53685=>1000,53686=>1000,53687=>1000,53688=>1000,53689=>1000,53690=>1000,53691=>1000, -53692=>1000,53693=>1000,53694=>1000,53695=>1000,53696=>1000,53697=>1000,53698=>1000,53699=>1000,53700=>1000,53701=>1000, -53702=>1000,53703=>1000,53704=>1000,53705=>1000,53706=>1000,53707=>1000,53708=>1000,53709=>1000,53710=>1000,53711=>1000, -53712=>1000,53713=>1000,53714=>1000,53715=>1000,53716=>1000,53717=>1000,53718=>1000,53719=>1000,53720=>1000,53721=>1000, -53722=>1000,53723=>1000,53724=>1000,53725=>1000,53726=>1000,53727=>1000,53728=>1000,53729=>1000,53730=>1000,53731=>1000, -53732=>1000,53733=>1000,53734=>1000,53735=>1000,53736=>1000,53737=>1000,53738=>1000,53739=>1000,53740=>1000,53741=>1000, -53742=>1000,53743=>1000,53744=>1000,53745=>1000,53746=>1000,53747=>1000,53748=>1000,53749=>1000,53750=>1000,53751=>1000, -53752=>1000,53753=>1000,53754=>1000,53755=>1000,53756=>1000,53757=>1000,53758=>1000,53759=>1000,53760=>1000,53761=>1000, -53762=>1000,53763=>1000,53764=>1000,53765=>1000,53766=>1000,53767=>1000,53768=>1000,53769=>1000,53770=>1000,53771=>1000, -53772=>1000,53773=>1000,53774=>1000,53775=>1000,53776=>1000,53777=>1000,53778=>1000,53779=>1000,53780=>1000,53781=>1000, -53782=>1000,53783=>1000,53784=>1000,53785=>1000,53786=>1000,53787=>1000,53788=>1000,53789=>1000,53790=>1000,53791=>1000, -53792=>1000,53793=>1000,53794=>1000,53795=>1000,53796=>1000,53797=>1000,53798=>1000,53799=>1000,53800=>1000,53801=>1000, -53802=>1000,53803=>1000,53804=>1000,53805=>1000,53806=>1000,53807=>1000,53808=>1000,53809=>1000,53810=>1000,53811=>1000, -53812=>1000,53813=>1000,53814=>1000,53815=>1000,53816=>1000,53817=>1000,53818=>1000,53819=>1000,53820=>1000,53821=>1000, -53822=>1000,53823=>1000,53824=>1000,53825=>1000,53826=>1000,53827=>1000,53828=>1000,53829=>1000,53830=>1000,53831=>1000, -53832=>1000,53833=>1000,53834=>1000,53835=>1000,53836=>1000,53837=>1000,53838=>1000,53839=>1000,53840=>1000,53841=>1000, -53842=>1000,53843=>1000,53844=>1000,53845=>1000,53846=>1000,53847=>1000,53848=>1000,53849=>1000,53850=>1000,53851=>1000, -53852=>1000,53853=>1000,53854=>1000,53855=>1000,53856=>1000,53857=>1000,53858=>1000,53859=>1000,53860=>1000,53861=>1000, -53862=>1000,53863=>1000,53864=>1000,53865=>1000,53866=>1000,53867=>1000,53868=>1000,53869=>1000,53870=>1000,53871=>1000, -53872=>1000,53873=>1000,53874=>1000,53875=>1000,53876=>1000,53877=>1000,53878=>1000,53879=>1000,53880=>1000,53881=>1000, -53882=>1000,53883=>1000,53884=>1000,53885=>1000,53886=>1000,53887=>1000,53888=>1000,53889=>1000,53890=>1000,53891=>1000, -53892=>1000,53893=>1000,53894=>1000,53895=>1000,53896=>1000,53897=>1000,53898=>1000,53899=>1000,53900=>1000,53901=>1000, -53902=>1000,53903=>1000,53904=>1000,53905=>1000,53906=>1000,53907=>1000,53908=>1000,53909=>1000,53910=>1000,53911=>1000, -53912=>1000,53913=>1000,53914=>1000,53915=>1000,53916=>1000,53917=>1000,53918=>1000,53919=>1000,53920=>1000,53921=>1000, -53922=>1000,53923=>1000,53924=>1000,53925=>1000,53926=>1000,53927=>1000,53928=>1000,53929=>1000,53930=>1000,53931=>1000, -53932=>1000,53933=>1000,53934=>1000,53935=>1000,53936=>1000,53937=>1000,53938=>1000,53939=>1000,53940=>1000,53941=>1000, -53942=>1000,53943=>1000,53944=>1000,53945=>1000,53946=>1000,53947=>1000,53948=>1000,53949=>1000,53950=>1000,53951=>1000, -53952=>1000,53953=>1000,53954=>1000,53955=>1000,53956=>1000,53957=>1000,53958=>1000,53959=>1000,53960=>1000,53961=>1000, -53962=>1000,53963=>1000,53964=>1000,53965=>1000,53966=>1000,53967=>1000,53968=>1000,53969=>1000,53970=>1000,53971=>1000, -53972=>1000,53973=>1000,53974=>1000,53975=>1000,53976=>1000,53977=>1000,53978=>1000,53979=>1000,53980=>1000,53981=>1000, -53982=>1000,53983=>1000,53984=>1000,53985=>1000,53986=>1000,53987=>1000,53988=>1000,53989=>1000,53990=>1000,53991=>1000, -53992=>1000,53993=>1000,53994=>1000,53995=>1000,53996=>1000,53997=>1000,53998=>1000,53999=>1000,54000=>1000,54001=>1000, -54002=>1000,54003=>1000,54004=>1000,54005=>1000,54006=>1000,54007=>1000,54008=>1000,54009=>1000,54010=>1000,54011=>1000, -54012=>1000,54013=>1000,54014=>1000,54015=>1000,54016=>1000,54017=>1000,54018=>1000,54019=>1000,54020=>1000,54021=>1000, -54022=>1000,54023=>1000,54024=>1000,54025=>1000,54026=>1000,54027=>1000,54028=>1000,54029=>1000,54030=>1000,54031=>1000, -54032=>1000,54033=>1000,54034=>1000,54035=>1000,54036=>1000,54037=>1000,54038=>1000,54039=>1000,54040=>1000,54041=>1000, -54042=>1000,54043=>1000,54044=>1000,54045=>1000,54046=>1000,54047=>1000,54048=>1000,54049=>1000,54050=>1000,54051=>1000, -54052=>1000,54053=>1000,54054=>1000,54055=>1000,54056=>1000,54057=>1000,54058=>1000,54059=>1000,54060=>1000,54061=>1000, -54062=>1000,54063=>1000,54064=>1000,54065=>1000,54066=>1000,54067=>1000,54068=>1000,54069=>1000,54070=>1000,54071=>1000, -54072=>1000,54073=>1000,54074=>1000,54075=>1000,54076=>1000,54077=>1000,54078=>1000,54079=>1000,54080=>1000,54081=>1000, -54082=>1000,54083=>1000,54084=>1000,54085=>1000,54086=>1000,54087=>1000,54088=>1000,54089=>1000,54090=>1000,54091=>1000, -54092=>1000,54093=>1000,54094=>1000,54095=>1000,54096=>1000,54097=>1000,54098=>1000,54099=>1000,54100=>1000,54101=>1000, -54102=>1000,54103=>1000,54104=>1000,54105=>1000,54106=>1000,54107=>1000,54108=>1000,54109=>1000,54110=>1000,54111=>1000, -54112=>1000,54113=>1000,54114=>1000,54115=>1000,54116=>1000,54117=>1000,54118=>1000,54119=>1000,54120=>1000,54121=>1000, -54122=>1000,54123=>1000,54124=>1000,54125=>1000,54126=>1000,54127=>1000,54128=>1000,54129=>1000,54130=>1000,54131=>1000, -54132=>1000,54133=>1000,54134=>1000,54135=>1000,54136=>1000,54137=>1000,54138=>1000,54139=>1000,54140=>1000,54141=>1000, -54142=>1000,54143=>1000,54144=>1000,54145=>1000,54146=>1000,54147=>1000,54148=>1000,54149=>1000,54150=>1000,54151=>1000, -54152=>1000,54153=>1000,54154=>1000,54155=>1000,54156=>1000,54157=>1000,54158=>1000,54159=>1000,54160=>1000,54161=>1000, -54162=>1000,54163=>1000,54164=>1000,54165=>1000,54166=>1000,54167=>1000,54168=>1000,54169=>1000,54170=>1000,54171=>1000, -54172=>1000,54173=>1000,54174=>1000,54175=>1000,54176=>1000,54177=>1000,54178=>1000,54179=>1000,54180=>1000,54181=>1000, -54182=>1000,54183=>1000,54184=>1000,54185=>1000,54186=>1000,54187=>1000,54188=>1000,54189=>1000,54190=>1000,54191=>1000, -54192=>1000,54193=>1000,54194=>1000,54195=>1000,54196=>1000,54197=>1000,54198=>1000,54199=>1000,54200=>1000,54201=>1000, -54202=>1000,54203=>1000,54204=>1000,54205=>1000,54206=>1000,54207=>1000,54208=>1000,54209=>1000,54210=>1000,54211=>1000, -54212=>1000,54213=>1000,54214=>1000,54215=>1000,54216=>1000,54217=>1000,54218=>1000,54219=>1000,54220=>1000,54221=>1000, -54222=>1000,54223=>1000,54224=>1000,54225=>1000,54226=>1000,54227=>1000,54228=>1000,54229=>1000,54230=>1000,54231=>1000, -54232=>1000,54233=>1000,54234=>1000,54235=>1000,54236=>1000,54237=>1000,54238=>1000,54239=>1000,54240=>1000,54241=>1000, -54242=>1000,54243=>1000,54244=>1000,54245=>1000,54246=>1000,54247=>1000,54248=>1000,54249=>1000,54250=>1000,54251=>1000, -54252=>1000,54253=>1000,54254=>1000,54255=>1000,54256=>1000,54257=>1000,54258=>1000,54259=>1000,54260=>1000,54261=>1000, -54262=>1000,54263=>1000,54264=>1000,54265=>1000,54266=>1000,54267=>1000,54268=>1000,54269=>1000,54270=>1000,54271=>1000, -54272=>1000,54273=>1000,54274=>1000,54275=>1000,54276=>1000,54277=>1000,54278=>1000,54279=>1000,54280=>1000,54281=>1000, -54282=>1000,54283=>1000,54284=>1000,54285=>1000,54286=>1000,54287=>1000,54288=>1000,54289=>1000,54290=>1000,54291=>1000, -54292=>1000,54293=>1000,54294=>1000,54295=>1000,54296=>1000,54297=>1000,54298=>1000,54299=>1000,54300=>1000,54301=>1000, -54302=>1000,54303=>1000,54304=>1000,54305=>1000,54306=>1000,54307=>1000,54308=>1000,54309=>1000,54310=>1000,54311=>1000, -54312=>1000,54313=>1000,54314=>1000,54315=>1000,54316=>1000,54317=>1000,54318=>1000,54319=>1000,54320=>1000,54321=>1000, -54322=>1000,54323=>1000,54324=>1000,54325=>1000,54326=>1000,54327=>1000,54328=>1000,54329=>1000,54330=>1000,54331=>1000, -54332=>1000,54333=>1000,54334=>1000,54335=>1000,54336=>1000,54337=>1000,54338=>1000,54339=>1000,54340=>1000,54341=>1000, -54342=>1000,54343=>1000,54344=>1000,54345=>1000,54346=>1000,54347=>1000,54348=>1000,54349=>1000,54350=>1000,54351=>1000, -54352=>1000,54353=>1000,54354=>1000,54355=>1000,54356=>1000,54357=>1000,54358=>1000,54359=>1000,54360=>1000,54361=>1000, -54362=>1000,54363=>1000,54364=>1000,54365=>1000,54366=>1000,54367=>1000,54368=>1000,54369=>1000,54370=>1000,54371=>1000, -54372=>1000,54373=>1000,54374=>1000,54375=>1000,54376=>1000,54377=>1000,54378=>1000,54379=>1000,54380=>1000,54381=>1000, -54382=>1000,54383=>1000,54384=>1000,54385=>1000,54386=>1000,54387=>1000,54388=>1000,54389=>1000,54390=>1000,54391=>1000, -54392=>1000,54393=>1000,54394=>1000,54395=>1000,54396=>1000,54397=>1000,54398=>1000,54399=>1000,54400=>1000,54401=>1000, -54402=>1000,54403=>1000,54404=>1000,54405=>1000,54406=>1000,54407=>1000,54408=>1000,54409=>1000,54410=>1000,54411=>1000, -54412=>1000,54413=>1000,54414=>1000,54415=>1000,54416=>1000,54417=>1000,54418=>1000,54419=>1000,54420=>1000,54421=>1000, -54422=>1000,54423=>1000,54424=>1000,54425=>1000,54426=>1000,54427=>1000,54428=>1000,54429=>1000,54430=>1000,54431=>1000, -54432=>1000,54433=>1000,54434=>1000,54435=>1000,54436=>1000,54437=>1000,54438=>1000,54439=>1000,54440=>1000,54441=>1000, -54442=>1000,54443=>1000,54444=>1000,54445=>1000,54446=>1000,54447=>1000,54448=>1000,54449=>1000,54450=>1000,54451=>1000, -54452=>1000,54453=>1000,54454=>1000,54455=>1000,54456=>1000,54457=>1000,54458=>1000,54459=>1000,54460=>1000,54461=>1000, -54462=>1000,54463=>1000,54464=>1000,54465=>1000,54466=>1000,54467=>1000,54468=>1000,54469=>1000,54470=>1000,54471=>1000, -54472=>1000,54473=>1000,54474=>1000,54475=>1000,54476=>1000,54477=>1000,54478=>1000,54479=>1000,54480=>1000,54481=>1000, -54482=>1000,54483=>1000,54484=>1000,54485=>1000,54486=>1000,54487=>1000,54488=>1000,54489=>1000,54490=>1000,54491=>1000, -54492=>1000,54493=>1000,54494=>1000,54495=>1000,54496=>1000,54497=>1000,54498=>1000,54499=>1000,54500=>1000,54501=>1000, -54502=>1000,54503=>1000,54504=>1000,54505=>1000,54506=>1000,54507=>1000,54508=>1000,54509=>1000,54510=>1000,54511=>1000, -54512=>1000,54513=>1000,54514=>1000,54515=>1000,54516=>1000,54517=>1000,54518=>1000,54519=>1000,54520=>1000,54521=>1000, -54522=>1000,54523=>1000,54524=>1000,54525=>1000,54526=>1000,54527=>1000,54528=>1000,54529=>1000,54530=>1000,54531=>1000, -54532=>1000,54533=>1000,54534=>1000,54535=>1000,54536=>1000,54537=>1000,54538=>1000,54539=>1000,54540=>1000,54541=>1000, -54542=>1000,54543=>1000,54544=>1000,54545=>1000,54546=>1000,54547=>1000,54548=>1000,54549=>1000,54550=>1000,54551=>1000, -54552=>1000,54553=>1000,54554=>1000,54555=>1000,54556=>1000,54557=>1000,54558=>1000,54559=>1000,54560=>1000,54561=>1000, -54562=>1000,54563=>1000,54564=>1000,54565=>1000,54566=>1000,54567=>1000,54568=>1000,54569=>1000,54570=>1000,54571=>1000, -54572=>1000,54573=>1000,54574=>1000,54575=>1000,54576=>1000,54577=>1000,54578=>1000,54579=>1000,54580=>1000,54581=>1000, -54582=>1000,54583=>1000,54584=>1000,54585=>1000,54586=>1000,54587=>1000,54588=>1000,54589=>1000,54590=>1000,54591=>1000, -54592=>1000,54593=>1000,54594=>1000,54595=>1000,54596=>1000,54597=>1000,54598=>1000,54599=>1000,54600=>1000,54601=>1000, -54602=>1000,54603=>1000,54604=>1000,54605=>1000,54606=>1000,54607=>1000,54608=>1000,54609=>1000,54610=>1000,54611=>1000, -54612=>1000,54613=>1000,54614=>1000,54615=>1000,54616=>1000,54617=>1000,54618=>1000,54619=>1000,54620=>1000,54621=>1000, -54622=>1000,54623=>1000,54624=>1000,54625=>1000,54626=>1000,54627=>1000,54628=>1000,54629=>1000,54630=>1000,54631=>1000, -54632=>1000,54633=>1000,54634=>1000,54635=>1000,54636=>1000,54637=>1000,54638=>1000,54639=>1000,54640=>1000,54641=>1000, -54642=>1000,54643=>1000,54644=>1000,54645=>1000,54646=>1000,54647=>1000,54648=>1000,54649=>1000,54650=>1000,54651=>1000, -54652=>1000,54653=>1000,54654=>1000,54655=>1000,54656=>1000,54657=>1000,54658=>1000,54659=>1000,54660=>1000,54661=>1000, -54662=>1000,54663=>1000,54664=>1000,54665=>1000,54666=>1000,54667=>1000,54668=>1000,54669=>1000,54670=>1000,54671=>1000, -54672=>1000,54673=>1000,54674=>1000,54675=>1000,54676=>1000,54677=>1000,54678=>1000,54679=>1000,54680=>1000,54681=>1000, -54682=>1000,54683=>1000,54684=>1000,54685=>1000,54686=>1000,54687=>1000,54688=>1000,54689=>1000,54690=>1000,54691=>1000, -54692=>1000,54693=>1000,54694=>1000,54695=>1000,54696=>1000,54697=>1000,54698=>1000,54699=>1000,54700=>1000,54701=>1000, -54702=>1000,54703=>1000,54704=>1000,54705=>1000,54706=>1000,54707=>1000,54708=>1000,54709=>1000,54710=>1000,54711=>1000, -54712=>1000,54713=>1000,54714=>1000,54715=>1000,54716=>1000,54717=>1000,54718=>1000,54719=>1000,54720=>1000,54721=>1000, -54722=>1000,54723=>1000,54724=>1000,54725=>1000,54726=>1000,54727=>1000,54728=>1000,54729=>1000,54730=>1000,54731=>1000, -54732=>1000,54733=>1000,54734=>1000,54735=>1000,54736=>1000,54737=>1000,54738=>1000,54739=>1000,54740=>1000,54741=>1000, -54742=>1000,54743=>1000,54744=>1000,54745=>1000,54746=>1000,54747=>1000,54748=>1000,54749=>1000,54750=>1000,54751=>1000, -54752=>1000,54753=>1000,54754=>1000,54755=>1000,54756=>1000,54757=>1000,54758=>1000,54759=>1000,54760=>1000,54761=>1000, -54762=>1000,54763=>1000,54764=>1000,54765=>1000,54766=>1000,54767=>1000,54768=>1000,54769=>1000,54770=>1000,54771=>1000, -54772=>1000,54773=>1000,54774=>1000,54775=>1000,54776=>1000,54777=>1000,54778=>1000,54779=>1000,54780=>1000,54781=>1000, -54782=>1000,54783=>1000,54784=>1000,54785=>1000,54786=>1000,54787=>1000,54788=>1000,54789=>1000,54790=>1000,54791=>1000, -54792=>1000,54793=>1000,54794=>1000,54795=>1000,54796=>1000,54797=>1000,54798=>1000,54799=>1000,54800=>1000,54801=>1000, -54802=>1000,54803=>1000,54804=>1000,54805=>1000,54806=>1000,54807=>1000,54808=>1000,54809=>1000,54810=>1000,54811=>1000, -54812=>1000,54813=>1000,54814=>1000,54815=>1000,54816=>1000,54817=>1000,54818=>1000,54819=>1000,54820=>1000,54821=>1000, -54822=>1000,54823=>1000,54824=>1000,54825=>1000,54826=>1000,54827=>1000,54828=>1000,54829=>1000,54830=>1000,54831=>1000, -54832=>1000,54833=>1000,54834=>1000,54835=>1000,54836=>1000,54837=>1000,54838=>1000,54839=>1000,54840=>1000,54841=>1000, -54842=>1000,54843=>1000,54844=>1000,54845=>1000,54846=>1000,54847=>1000,54848=>1000,54849=>1000,54850=>1000,54851=>1000, -54852=>1000,54853=>1000,54854=>1000,54855=>1000,54856=>1000,54857=>1000,54858=>1000,54859=>1000,54860=>1000,54861=>1000, -54862=>1000,54863=>1000,54864=>1000,54865=>1000,54866=>1000,54867=>1000,54868=>1000,54869=>1000,54870=>1000,54871=>1000, -54872=>1000,54873=>1000,54874=>1000,54875=>1000,54876=>1000,54877=>1000,54878=>1000,54879=>1000,54880=>1000,54881=>1000, -54882=>1000,54883=>1000,54884=>1000,54885=>1000,54886=>1000,54887=>1000,54888=>1000,54889=>1000,54890=>1000,54891=>1000, -54892=>1000,54893=>1000,54894=>1000,54895=>1000,54896=>1000,54897=>1000,54898=>1000,54899=>1000,54900=>1000,54901=>1000, -54902=>1000,54903=>1000,54904=>1000,54905=>1000,54906=>1000,54907=>1000,54908=>1000,54909=>1000,54910=>1000,54911=>1000, -54912=>1000,54913=>1000,54914=>1000,54915=>1000,54916=>1000,54917=>1000,54918=>1000,54919=>1000,54920=>1000,54921=>1000, -54922=>1000,54923=>1000,54924=>1000,54925=>1000,54926=>1000,54927=>1000,54928=>1000,54929=>1000,54930=>1000,54931=>1000, -54932=>1000,54933=>1000,54934=>1000,54935=>1000,54936=>1000,54937=>1000,54938=>1000,54939=>1000,54940=>1000,54941=>1000, -54942=>1000,54943=>1000,54944=>1000,54945=>1000,54946=>1000,54947=>1000,54948=>1000,54949=>1000,54950=>1000,54951=>1000, -54952=>1000,54953=>1000,54954=>1000,54955=>1000,54956=>1000,54957=>1000,54958=>1000,54959=>1000,54960=>1000,54961=>1000, -54962=>1000,54963=>1000,54964=>1000,54965=>1000,54966=>1000,54967=>1000,54968=>1000,54969=>1000,54970=>1000,54971=>1000, -54972=>1000,54973=>1000,54974=>1000,54975=>1000,54976=>1000,54977=>1000,54978=>1000,54979=>1000,54980=>1000,54981=>1000, -54982=>1000,54983=>1000,54984=>1000,54985=>1000,54986=>1000,54987=>1000,54988=>1000,54989=>1000,54990=>1000,54991=>1000, -54992=>1000,54993=>1000,54994=>1000,54995=>1000,54996=>1000,54997=>1000,54998=>1000,54999=>1000,55000=>1000,55001=>1000, -55002=>1000,55003=>1000,55004=>1000,55005=>1000,55006=>1000,55007=>1000,55008=>1000,55009=>1000,55010=>1000,55011=>1000, -55012=>1000,55013=>1000,55014=>1000,55015=>1000,55016=>1000,55017=>1000,55018=>1000,55019=>1000,55020=>1000,55021=>1000, -55022=>1000,55023=>1000,55024=>1000,55025=>1000,55026=>1000,55027=>1000,55028=>1000,55029=>1000,55030=>1000,55031=>1000, -55032=>1000,55033=>1000,55034=>1000,55035=>1000,55036=>1000,55037=>1000,55038=>1000,55039=>1000,55040=>1000,55041=>1000, -55042=>1000,55043=>1000,55044=>1000,55045=>1000,55046=>1000,55047=>1000,55048=>1000,55049=>1000,55050=>1000,55051=>1000, -55052=>1000,55053=>1000,55054=>1000,55055=>1000,55056=>1000,55057=>1000,55058=>1000,55059=>1000,55060=>1000,55061=>1000, -55062=>1000,55063=>1000,55064=>1000,55065=>1000,55066=>1000,55067=>1000,55068=>1000,55069=>1000,55070=>1000,55071=>1000, -55072=>1000,55073=>1000,55074=>1000,55075=>1000,55076=>1000,55077=>1000,55078=>1000,55079=>1000,55080=>1000,55081=>1000, -55082=>1000,55083=>1000,55084=>1000,55085=>1000,55086=>1000,55087=>1000,55088=>1000,55089=>1000,55090=>1000,55091=>1000, -55092=>1000,55093=>1000,55094=>1000,55095=>1000,55096=>1000,55097=>1000,55098=>1000,55099=>1000,55100=>1000,55101=>1000, -55102=>1000,55103=>1000,55104=>1000,55105=>1000,55106=>1000,55107=>1000,55108=>1000,55109=>1000,55110=>1000,55111=>1000, -55112=>1000,55113=>1000,55114=>1000,55115=>1000,55116=>1000,55117=>1000,55118=>1000,55119=>1000,55120=>1000,55121=>1000, -55122=>1000,55123=>1000,55124=>1000,55125=>1000,55126=>1000,55127=>1000,55128=>1000,55129=>1000,55130=>1000,55131=>1000, -55132=>1000,55133=>1000,55134=>1000,55135=>1000,55136=>1000,55137=>1000,55138=>1000,55139=>1000,55140=>1000,55141=>1000, -55142=>1000,55143=>1000,55144=>1000,55145=>1000,55146=>1000,55147=>1000,55148=>1000,55149=>1000,55150=>1000,55151=>1000, -55152=>1000,55153=>1000,55154=>1000,55155=>1000,55156=>1000,55157=>1000,55158=>1000,55159=>1000,55160=>1000,55161=>1000, -55162=>1000,55163=>1000,55164=>1000,55165=>1000,55166=>1000,55167=>1000,55168=>1000,55169=>1000,55170=>1000,55171=>1000, -55172=>1000,55173=>1000,55174=>1000,55175=>1000,55176=>1000,55177=>1000,55178=>1000,55179=>1000,55180=>1000,55181=>1000, -55182=>1000,55183=>1000,55184=>1000,55185=>1000,55186=>1000,55187=>1000,55188=>1000,55189=>1000,55190=>1000,55191=>1000, -55192=>1000,55193=>1000,55194=>1000,55195=>1000,55196=>1000,55197=>1000,55198=>1000,55199=>1000,55200=>1000,55201=>1000, -55202=>1000,55203=>1000,63744=>1000,63746=>1000,63747=>1000,63748=>1000,63749=>1000,63750=>1000,63751=>1000,63752=>1000, -63753=>1000,63754=>1000,63755=>1000,63756=>1000,63757=>1000,63758=>1000,63759=>1000,63760=>1000,63761=>1000,63762=>1000, -63763=>1000,63764=>1000,63765=>1000,63766=>1000,63767=>1000,63768=>1000,63769=>1000,63770=>1000,63771=>1000,63772=>1000, -63773=>1000,63774=>1000,63775=>1000,63776=>1000,63777=>1000,63778=>1000,63779=>1000,63780=>1000,63781=>1000,63782=>1000, -63783=>1000,63784=>1000,63785=>1000,63786=>1000,63787=>1000,63788=>1000,63789=>1000,63790=>1000,63791=>1000,63792=>1000, -63793=>1000,63794=>1000,63795=>1000,63797=>1000,63798=>1000,63799=>1000,63800=>1000,63801=>1000,63802=>1000,63803=>1000, -63804=>1000,63805=>1000,63806=>1000,63807=>1000,63808=>1000,63809=>1000,63810=>1000,63811=>1000,63812=>1000,63813=>1000, -63814=>1000,63815=>1000,63816=>1000,63817=>1000,63818=>1000,63819=>1000,63820=>1000,63821=>1000,63822=>1000,63823=>1000, -63824=>1000,63825=>1000,63826=>1000,63827=>1000,63828=>1000,63829=>1000,63830=>1000,63831=>1000,63832=>1000,63833=>1000, -63834=>1000,63835=>1000,63836=>1000,63837=>1000,63839=>1000,63840=>1000,63841=>1000,63842=>1000,63844=>1000,63845=>1000, -63846=>1000,63848=>1000,63849=>1000,63850=>1000,63851=>1000,63852=>1000,63853=>1000,63854=>1000,63855=>1000,63856=>1000, -63857=>1000,63858=>1000,63859=>1000,63860=>1000,63861=>1000,63862=>1000,63863=>1000,63864=>1000,63865=>1000,63866=>1000, -63867=>1000,63868=>1000,63869=>1000,63871=>1000,63874=>1000,63875=>1000,63876=>1000,63877=>1000,63878=>1000,63879=>1000, -63880=>1000,63881=>1000,63883=>1000,63884=>1000,63885=>1000,63887=>1000,63888=>1000,63889=>1000,63890=>1000,63891=>1000, -63892=>1000,63893=>1000,63894=>1000,63895=>1000,63896=>1000,63897=>1000,63898=>1000,63899=>1000,63900=>1000,63901=>1000, -63902=>1000,63903=>1000,63904=>1000,63905=>1000,63906=>1000,63907=>1000,63908=>1000,63909=>1000,63910=>1000,63911=>1000, -63912=>1000,63913=>1000,63914=>1000,63915=>1000,63916=>1000,63917=>1000,63918=>1000,63919=>1000,63920=>1000,63921=>1000, -63922=>1000,63923=>1000,63924=>1000,63925=>1000,63926=>1000,63927=>1000,63928=>1000,63929=>1000,63931=>1000,63932=>1000, -63933=>1000,63934=>1000,63935=>1000,63936=>1000,63937=>1000,63938=>1000,63939=>1000,63940=>1000,63941=>1000,63942=>1000, -63943=>1000,63944=>1000,63945=>1000,63946=>1000,63947=>1000,63948=>1000,63949=>1000,63950=>1000,63951=>1000,63952=>1000, -63953=>1000,63954=>1000,63955=>1000,63956=>1000,63957=>1000,63958=>1000,63959=>1000,63960=>1000,63961=>1000,63962=>1000, -63963=>1000,63964=>1000,63965=>1000,63967=>1000,63968=>1000,63969=>1000,63970=>1000,63971=>1000,63972=>1000,63973=>1000, -63974=>1000,63975=>1000,63976=>1000,63977=>1000,63978=>1000,63979=>1000,63980=>1000,63981=>1000,63982=>1000,63983=>1000, -63984=>1000,63985=>1000,63986=>1000,63987=>1000,63988=>1000,63989=>1000,63990=>1000,63991=>1000,63992=>1000,63993=>1000, -63994=>1000,63995=>1000,63996=>1000,63997=>1000,63998=>1000,63999=>1000,64000=>1000,64001=>1000,64002=>1000,64003=>1000, -64004=>1000,64005=>1000,64006=>1000,64007=>1000,64008=>1000,64009=>1000,64010=>1000,64011=>1000,64012=>1000,64013=>1000, -64014=>1000,64015=>1000,64016=>1000,64017=>1000,64018=>1000,64019=>1000,64020=>1000,64021=>1000,64022=>1000,64023=>1000, -64024=>1000,64025=>1000,64026=>1000,64027=>1000,64028=>1000,64029=>1000,64030=>1000,64031=>1000,64032=>1000,64033=>1000, -64034=>1000,64035=>1000,64036=>1000,64037=>1000,64038=>1000,64039=>1000,64040=>1000,64041=>1000,64042=>1000,64043=>1000, -64044=>1000,64045=>1000,65072=>1000,65073=>1000,65075=>1000,65076=>1000,65077=>1000,65078=>1000,65079=>1000,65080=>1000, -65081=>1000,65082=>1000,65083=>1000,65084=>1000,65085=>1000,65086=>1000,65087=>1000,65088=>1000,65089=>1000,65090=>1000, -65091=>1000,65092=>1000,65097=>1000,65098=>1000,65099=>1000,65100=>1000,65101=>1000,65102=>1000,65103=>1000,65377=>500, -65378=>500,65379=>500,65380=>500,65381=>500,65382=>500,65383=>500,65384=>500,65385=>500,65386=>500,65387=>500, -65388=>500,65389=>500,65390=>500,65391=>500,65392=>500,65393=>500,65394=>500,65395=>500,65396=>500,65397=>500, -65398=>500,65399=>500,65400=>500,65401=>500,65402=>500,65403=>500,65404=>500,65405=>500,65406=>500,65407=>500, -65408=>500,65409=>500,65410=>500,65411=>500,65412=>500,65413=>500,65414=>500,65415=>500,65416=>500,65417=>500, -65418=>500,65419=>500,65420=>500,65421=>500,65422=>500,65423=>500,65424=>500,65425=>500,65426=>500,65427=>500, -65428=>500,65429=>500,65430=>500,65431=>500,65432=>500,65433=>500,65434=>500,65435=>500,65436=>500,65437=>500, -65438=>500,65439=>500); -$enc=''; -$diff=''; -$file='droidsansfallback.z'; -$ctg='droidsansfallback.ctg.z'; -$originalsize=3189464; -?> \ No newline at end of file diff --git a/lib/combodo/tcpdf/fonts/droidsansfallback.z b/lib/combodo/tcpdf/fonts/droidsansfallback.z deleted file mode 100644 index 852eafe3346a97f7d86d10a8b2bc128e78312d61..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1500903 zcmX_ncQl+)^M4Wvk_c&to<wia`yzTLdM^p0_s;GL5+Yjkuwiu(EqY%>^s;(etln8= zS$3`cdB5*_e&;-YJm<{4bLY-{X6DW<f%E%q_rEjrX0V+ny~edQ?^!N3>fCvL|0&Dc z?~Pw^FgWq(TcYirsav#hxYzfeKKA%l5SgT^I}=;bq>{OqaopEJUMcJXk7clmvTa>r z{$Sg+61QlQU`uZmvj0d$e19=_PYx-I+H0@bZF3jSWI;>5Zm}}7-#B*Igc7nOk_R{P z7P1!7y{QBCgMzQyuWATxa&H{m*>pnUDbQ9w8`nd<d?@hXfHwg_^T&I}#T(9{)|n>< z>jZ`3H|LM8R?ro)nui{&m`m6aH?<GN)=85C_zKC20VA8Jb$BmiJ^0|#Ckc$h(#O_# z>`rnU`}GMr6pQF@A$%{`(qX4ybSCt_)w9-fI2@ZGGWGxyJg(79tQf*;%xD5~TQ=zO z>LkE8R2DNda}BYmFpvyb2}Gq6*4m}ACNcPRycAKJ7~l1UEI?SGKlJ4#c>Z!JESYc} z9nX9t$A#>s_lUJctLMgUF+t^x>ij9L4nxfcZ4E3w8CmPcc(7m!Ey_`9SP#PRx=Oq< z-xX2<zHqPv)#ANE1yl+VUsvi7b|;`2B|RGMSqlnH)^@7bbf^g^D`ATTMJUhswiSxQ ztT9bxUtOqdCN9`Eg(lIZ18KIhVUWGVf+dwCYwH1g+$H~|VISVBf;dsd3&iP!I{C{? z5tINx$21?VGh!op2~*_+zRN|c5PpxTY>}qariJ3r4BV*>frpyi%^U*x^bI+T$D8S( zM7<t1rw^8^jW-u8!7KzY=1uhrB>i6r69w7O&A$st>vQ!#AqDa$3tD>LQ>^+9w81m5 z9W^to+=z~zR7D-2&cQ3`FH2BBdr6_$wO_#C{cF)jETAiB5)i2~e-yEBu@I1qx_;RN z%PKHVMyvGWb&~h4%|Os=!$W2O!B`DTqJ~Xg$E!4glPr*$13;k?LV^!NQzg6oHDn!w z>pweS0f}(hhExPM3?q`ku;fV)ThO(xyVVH-4&vVFiYwqns*ks*%|nK!#gYL~7P#>i zSJM>qTDA!h5ZbVHy~Q$>9qKC<id*#1W}PWj3&pS_K}nOR-g@V<n!C-(3++jtuzGrg z+!nlbng!yTicKW&hNDW;T+@gh<CF~!o*b~1>`({DQd=4+h&7W66)Pz|ANJ`7Ip|Gy zvf!`WgIUxl*pGa@34$dUio-N(toa2{%*nhwp$-jCM!&(DXq3w069RAsdocxOZFMf? zOi8dWf-oiIwQ$K^vfXvXHQM7a?HFHh;KBCicV~&HHsa8VNqZ?Y6W7M#;Wl*FognIj zux6c^54=AlqyBNLa{VLQj0)=SRsO<)o&6+MX2)YowS1wH9bZ12IRE4N`I<F^nQ0M} zjze4?YoC;zA0{LrnO0y%)^0LaLF2s`FMRTPP`R~;_*BpDY1q7pRolae^Mavy;Du7V zl@1nrux{4%H2roZ6RSNqrIo;P31SWFW$#DHYJ=NTJI=TIQ3SzDOBauF3Z!Pmcmh)U zWICHbp_YYWx5ZG59-5hlhJ#fJ1r&86dV5_BNi3j?we?FB>k&@4X?h&RhPrn0E}uF( zuvh{BsSmByu}mAV#DYrpgUaC<%ro)no?}^!-S+IEd~2<2{O+PaX<G<K&~*&XjHw+I zkUcZ4Dv>dmu<&IfGzm~Sj6yAejJ2n|Lk_LkcW!tSVp=?1bOwgEu5m3sTPrPoi~UU< z((Z>P1zL5!FG}jk-Pw2eyjg|VcMwT-WZ1*i@A65Z+DZOwB}oOvhw*dpWYOynhYeE| z{ijoEW=REGiBv3Sl*xP8`JWY*iEr3;JP$xgqU=uUNmOh*&PnmCPP_vp8`9|oR=^rs z_&JLc5xD((f!0M^eD=%<v`BJhZE?~Jr`x;A!kdqI_|BvJXKJ7R-s!VI49jltQ@4_h zASzIKs_EXIkXk0RpipgB0k)`ScCV31;c{;bQyADl+dh*MKaUq(&j{P%K3df4u%SD2 zK~b?fvCX%WBBz#+Ias!MZ>~6Rv%9my8soN~E&+h#Ew3bih07874(*DW#wBhPRx9kq zqjz|=fNsG}v;<&I^bT9@gIgd^UGa+xe|s<il_!uTiUF}$jO5N0v^OQ>DJbxS+DVlV zdE8opH7fP?KJ$fxa=pDh78glqi^&TzRK1y)Q#nNRtsbEon5U-ge&Y7*P#1eGE?z?8 zLLDveTLIeLbqtMdk<gE<PNBS^)eb{C<ELtwQG1#eTd$?#g-J?M3Y?SJSe>d_ht<bx zStyex)An6NG7ocG&<1f8leK9DBK>B#d(y%v_uu&IwE_>7!`1ZS<mwOmOoM-reOBY( zbeZS#0woXsWc(~}ew2QHk(Ayt;tSCg^{oKV{Ug&mt(zaLe?&?LK3S?GB1ne|-wsLJ zPZj$l<r32MObx=&tljMwt*-M@S}A0oHbsKM>CjSgncCCxtF$Ynr)cpR*YMjUTo9L* za$79!fr!;@oCDps=uke*rvrxCQ*zh}PNH#o6PaG+fRqbe$9vq~tn-ytlN!C|I!D|p z5v59YUP}nxyuHainr&vf=6TS8@~Sm%{Ul83Bsy+aK&dK_wC`{NA{n;}pSsHu#J)BY zU)^gPZ$Nr2<jL1x{9G?n*-3DKK1#6n{bJ9j0~XpYi5~$8t9aKA*qug7ukyN<dKpII zwmK?%t-Fu-8EaQ~%90;+`UC20>35l;1WNN@W_Wv+44o6JBct-R3Arf2SZG0YVFgHS zmqlDtVUBO~N4E(yi823Q(6^Kx+c=|lhjtxh)7ibpKu)j@$pP($wh=k$n(vhi`0THO z+1)_#I7zz$tuDOlP!#9I=Advo`^ubrY}|s5TrmBHrhKOSnq+@c=+l90MIUD_FkCrn zB5^a{QoaVB=a9sx#Iz1(#7aT1Q(@=ue~oa(pwrPAGo}%?op(tiEITg)zkK;L0qiiC zUKWoH`m(7`V{d$flRTQ@LEFFXbf{JrItH_Oj^ABK$iD>8h+hb#bosD%T*UWc0HOAa z8VL3rfKw>bd1{nQ1llvX9~fEkx>`~r_{GI|XLgE8X3RejX=3pwfv;8RiWf3>tk<5o zS}cS{d!{99G4_bcFY&!6gud{reWjDS>!e^Qvzv|-(mRxTx2ZT!$E3_uXg%~WO;_hh zki`}F>v^)u(VII!P$q@aq^aDTTOews3GKypKom5Dj}F8<Ug^ApWtv!G7|k}8hXCrR zsdln-koWFtFkKE@$msPKB4-jq1?}!7zcae;;xD+VDCH=&;(#~?X@UZk>zH#y81HBc zrr)X6v0<`_wVmJV)wkN&6JB26nxEB1aT^4r9_hSY<J~y;*O;<{`xNNE^pH6-UEr)l z6}j_Vw+WC|wd*r>0zs_a_GnI9F9ZZknx(jyfwSO7OXye+*}dmus2sHyAS->F9R(p| ztRLMXJcv#u^Xdth8m!EJtZd?bbkCf+org29W4b%yK>{vS-DDz@{BdTUVy%46b~M)* zi&7rD{Qiojt%PbtFgp(ZJa6q(vG=ZlN224~q5%5Tbll6<E6o(y=xxWHQ-js1;vCo9 z)6X-!Pvf}#_$_xPS_JF-G>C_(iU1D5Z}iaR>4{?RE?;+>du1@jl|H=gs3!*wFdt>x zBs%?LG3R<VEW>!xb(|)Hn<UQ7wLko<xD_>-_SNy+e_-!%8~0VL#-F3;X>!M<`Q;4u z?0@XoX@#uZ%=YB3Y-R5xl)`Pl4A?Mo76b^KiLku55H?m2Sz_$xTZbtkao+;$Xc74y z4}{rrX}J?F45F54I82@1uB~zWkbF?t`1|_nNzi8k11;u3U9P(AGwy3v`OtyikH&kr z%4fb096#6gRqN$Ca>*A+ZF)K(MB;~Y#$V8I=761Bw>f_F;q||f|MaAAYHd!)?4urQ zJ|k6e0SId!chh1VTR~6PgvbRoX!1)sgl_jkXYyJ(KU4Hfm}qtQy^fPzyPLiqHGG&p zLW-O_5#bul6@Y%269di*5e;7R%dH#;mP==c#D+4m2YueYtLQEof0B@2XQ0cU9x!p# zlC|DI*&K;BpO?t+C6gIGe$b=7t~X&|O8K{@BFWZ}7n}84J$C?Aaw5GOVwl>GAxqv# zVSl-xXHYGs7UT!ts2=g9@1N%W%|tnnkL$pfneDFbiT_Qe6ai1A1ato=rJRSG8kuX+ zJbPojsh)Dj0eYzLkZhu-@OO{LH~WQo-qXCio>5VmsT2W6v;`d5k(7=zD+C(|^~k7) zMI&++-6O7}9$~F@Z7sF?A%0NN_5n_xdS_EOS>?AvGNfMGo8&EZ(^PBc4`oEF_k3lH z>q^FNQOT(@yzepjXOP~bVe0egIOs<>U0y7Ti{{KA^9RxEEp79LxM>SkA{FDWVx=F4 zpgFhWEA57Q)gwd<hC7;4-!CVY`MnVS<Tw2y#i?>Iywc5WyQ<V=TH7qBJGLq1ymc|0 znW#=|cYSRBYxJ~EKIJ#zt(Y{w=Ui8227Un?At~hJpa7F`af@QJB`vMX9-|(-X6~x> zy~BH}o${;{CxR7L18rc&Um-ImG6oyl9&}Twso`uV|I%7v8>VkBEe#_fdiBt;BF`6Y zwW*!JMvR0`?yduEt2&j580}!=eQ|P<9<VwD!YlO$kid&4j~p8b`~kWzxLJd+%Zi() z78aO^ny|9QpF=*kSTMbk&=eo4a<6ZT!<y*wlYgbQyR?bke=VI<5@?56E$pLG>ao_X z?*4AaJD(ll#zxQ8@}aXIrgTlkflwDypgJ@^>`K`(tIr=?-KwIUG3l=au+E(D*p9h! zna)2csIAIakIQ+)tOovOu_LEx6#)+JnncDbJ1ffyXS&^2xm8)_(T00Ra2!^^2xU5e zm8}<_{}jty6HP+*aikSu3>=<&CLg`BFO1^gg4s0s9a(J`pt~X`Gzv&~$Cv22af3<Y z(W%Fvj0;t_n!aZHY3Z7{j~O<)ud}UuYXuI}urjqn`UwNvX7l-eZUSSX3syx>0+AR! z-*{N{E5B4(<s7hz`Z*1^goWuC%ioC_w{VrU$74%O<Dj|l7-2V|FOGcW8V(>$$awd~ zq_Wz*@Ev?@0*&^ic8^D-!(C}rO-Y^%#C(7O`h4|a2daomvOy7h`E=O230i<|)YoN0 z5a91ND4j;W;@^gRgSsR->Vg@cJhIBGV}+5g8PaGrz}cjdIca3-m9XVO^!0|EPkwUm zwj_=F4F>3^W_^C+@j#kSmm#dsP2WJ`_NCO$mD0F<8ma7VK(#x&xy`D`59Zu(bG806 zz?AW3p?U#@y>;@tovN7Mv9IUe>|9sF>kIrfptYd}1p|zg*_3KJy0x`2Ue;5B)Mvmq zzrA9du4^of689UvsTchd-4Zw())zfes-xg1V>7!@x1JNZPo7=q>Urm6>jjB*Nk0{% zNCz!x3gNBV<!)+UfLwx>ZruBf?BRDZ4}^G5OMdrMtKz;|Q7hR~8y7iL6>7omO$%7s zZX`T@66*$jP?hxXA4?QiaU+KJ;2WjoUqO3DxCEL35iLOzGN$S#NxRsPwD@MhSQs*V z_{TIzO?SnxN*AJd{)jb`V$I;%nRtYktJNy+(mGF+T7SCUN>*uVh8#QW+di8-{E}&* z<oA$Cr`q&i7JH(e*1TEw%~W3NTLc}*uqkcUmcu%R7c66nY@)$rceClHyMz>Pc#6)+ zo<1l|)oRFhWg?=52t!}MKhPa=GLco@mu2rwf>+JjOVWT=9pZyG3oeX;(olfGhPV^E zsjNt2=|PlmTU_!OHT%6tC%h+Q2vroT_A0;peS|kaB;H*;q?Oq1M9(*(LJ3@WD((z6 zGQ>^z#yk1U4jvtxX8sHim9{dotf+1oarQ{lF4ScLJY+;qX2Q8*?1|hXs%qjAA-DC- z!H~oGy6x4!Y<>go->yr>uE+%EY3yS4r-9SW+yO7JiZkOkxtE~Nm!EKgOH2`QM=+1u z><j;37PW*y1lU`Nai1aMY%?E1nYbVU(0vxmRfZo(Z(d)Bic7Al<WOExD3;2!(bly0 zUSS0HcZ#=R>wg&MaxOTVOO;PKKDBEX-X`xqiAK|nzNz>t0ggn~Mk?e+*X<S8&NZyp ztPF%Zo4+d5swm`hk~|C#Mu~R#Sv|1K6rBOF3Z3%+qKhPK2Sa#$&IBDz`Rua`cg{c} zV$6o_Ve5tWG$deo7|^|9)fE}(%4(b3ErlQBItiP3kF1=kUEn8f^Q~Gg&~o>gaT315 zgD=FF4>&Pa>PTh{>j#`ZgQC|rKHV{?(L|+(9ot4I`?EWpU1}}i9vwYIm|YC;>7+js z<CyWNK2$y(Ft$w>6{G8%X_#dyjPrYCyEH$Yo-PP)C0;|2T>&1x89RorrX2T~5dihs z_b{Rew#wTTCy<}X*QC40v_oDHX-irdT2*FE<VTd(fQfKT&lTHyVS1^0<)f3RutB#2 zj&Z=wCy$xCh46=yjBr6O<ZAlwOAD3D6XI`R&%W#|WR!a73Rg&te++~0Abu8Qvi3Fn zB+iewHNEIzU3*1Yi`RpZCo6_JXHjkib7D}CZ5<e4hz+m$HuE@17R)QH2F528UUb*U z6lzLtR4W<xInf_W)}inAf6m~`3a^$_g%3%td`0I8>`c{;)M)xB@A-r5OF2-z+>3Ua zr(y<@4#sDEIhZ^7{pvDS+G7$?1ImTJe4$D7yXLw($N_bBbA!`zyMAM%gBh<E1=r+- z4&1*ntTBLgP0%k6f@Xc&@uV32UYVvFdM6;N`u1w6#<}`WNzxvRih2?*PP%--6<*^F zNSMG!T=BP)UWaz7=<eUPWCnUyn2B|sD_6iVhiL2539<Mu#sQA7uM{u^eh+5)qR@u1 z=I_-Ap6K@X8PVky70H9&>$}nADaCuvH5cbTvA5kc@)2VngO;Y3>1M{$%1-V~#f!40 zPaQ=6Vzf@(GPmgyd}ofR)67PcVd#6SdvU)Rd&ij;1Jbc8Cg<Yr(2=c(o(Vju{_fU^ z2D%&~2#z0EGq;No72kHq<DUF8<yKo)r*$@HjQ7{Kq535%HA!q;S6&|WM#jZ;A@+Q? zzK%1qPb)0dB`gF|SW$aH&Z8g03+gjp|L4ZJmV-#v855IuaOh5~-M=eFc$1my6;3-A z3bVHg;p885h%JFuZHmPEWd0DVZ_1uxV$UCLJ_u@tmwJsr_5+!;2Wb6x{TxBz*$*o= zaKIi5Kc0|)>CDX&`avlO<GAiYL!8{wYjc00`D`(TweLl97qgqTR6pG=ifo+pt){ZX zm}3Y@4P{w?DHrp~AgraTQ$nPi+yQ6B#;#e9gv+65aCSqi=~6h{^{CJMWOmxu(KIyZ zA$Z84tg6i6UbtJDrODFx2#}Zu&o%?1OJ%j?^D21wyZvUhFurNoc_LG}RJ_vMS`Aso zydMCZ-Y>dW2SW$$f%0>XvLgdz?pY(Szr5a5wuC$Dzl9UAQhQS}?SH>c#=rXg8^1r; zas1@Q<vNW8dC#?uIYSfA|Amj+?)g1_Tn-11=XP7aGH4cypEA~}GXJIr{5o+JN_UAN zesmQ%0qi+>w6vk-zG`wM2~^UjOl7L5v}0(F%k8F~e1#-ct5IX?tWRdWrw>^W8Tr%A zG2yf0QLugT70Z4+35Z$H%^nVCILoJM`QXMrbW%~Rbp6B(9Hrj#JTq5dv)=5gt**=j zCvwSo+U@a|$zV_!|9)uV<K}N<0V*(G#Ad?hPpkNF!~DmY6^Dy@vGI^N7T6~T8d<nt zg{iSQAdH9LglKR&?bgU3auOg5XY*wn?jb(n0e=|Y_M(fk6smfXIczP!oB$ft1dz3N zN;-+kL?PGd>9v`z-p9TdIyj}<o{h}sc0-T2<k5$IUYpgtNe;n#WgaJ5yPNp;v14sR zh>z&}PST#XIsXgh9|Wss;@wQQ=@0!z3c6iRRJ_XW2m$FbLgJV<9A?Erm@R7Z@5LmZ zSD6Ag?JrmtTo{}@`C`Y#<L@SrZQ(t80t-YLFyn-A4zx$@GFVo>CUB4;|9nBiTjl;W zRB2#UT0SP5``!7<P>mGTqN+_$b|K%NRQo}uQIKk|I|MwcHP%+xZ>+%j>>&@>&Rv<V zE>_n0rT!EaE{uO`<J9i3e|#W)Z;xNe+NCDqx7o?vkK1#UX6#g^^K(NqD&)hQ<<u0s zM-+NCt4VI;359MW_a0qURRa$JF?_aZS&<VRB&vvc1a`-KeYJT+{=v^vb;kXoi`$K9 zXZFc8LC)F;pwoj#=ycbF3_s;}Hpda?v=`vn<&}>^_A)KH>p{8?tn5P9?rZf~x*of@ z3fAUj7RM3|(loNEcUCG5wg%`8I6#C{`m1U@E%K`^2ZKj;AEpnBUwnDL-_ESn%{L2^ z9{<tIpw%aiVm0yr$T#U5@yvf*g(!bKG8MzndWbtFIh+hH`@~h-^_4+K>q}Tq=l%`2 zh*o^8*|_{@=XHLCn=KxDgJ8<PzN?sE7&)dbYip6|<kBR^aKKFOBJ+&>VLezK3akTP zvEfh?STx<F%btFJUb176_7Z|FOSf?CGj2fJ|0fMCT+nDwSkIqFX3Qz~MCANAh(2+@ z(-^E)P2KwqP8ugI1K29zkP1%d>C%^BpBP#`4JlfiBV#!?UlFQSY>)`s7QeRC#g2Zf zW>1JFaC8-!yXHv1Mtt)cxYDWtQ{Z@0<09PeYJmhp)5Kt=ADs@_QQvyXzF&_i>riIq zG-dXi|Ct@2n#9Sg(_FQVuD8gmH<<>}SHDuz&{mc@>H4gZ-~2#p)2S#Hs2((2&w5jB zD5HGGgWTY!G<a3+nz;}+?xMAx5&knDEk>b;wOHe086z2~?34bgZkp!{eO0S5R4rsZ zob={lYq09_oME;Pjl!Qp5`<MV5B@#-3>|pT-d`iyT=`2n8|t;+_276tHH8Hxb_HqQ zsB!q#1D4U^+z@Lh{{^lg#PcS=_)K>>O|$n}m4q(n=^3DLaN@NSNrRw$%%DTJQ+wIl zDW@2v-=H>M3D!))c-n^tz;9{TalLM`_;w4muy*Kbz$PTui{EmCgmMf(`$o3>Amt$y z?tT4)FAwZRkYVIfi-o;InH#rTed)c_VjHJokE+|e1+)2*>NnNKvNOaj2p0CpGqbG> zdPjk7Vc~hpet7q}VS1KFUY1kP)pNSF@NPD7=*qM24d`~8{(QtfNBhT_56P|wV^Cdy zGsJF2Pz<P%T??91yL5x_U8eYp&f^wS+GM#CJUB~<Ta><8^(8qq)4<1pFMhJw<=2bb z$Nx3e{zk}vtUR+ht)!3Fku!>&)>DVj?Nn5w1NAlW`)f%w!Ao_?9}rLMM-#Op7Zqgg zHEi*sP6w|0Yi9o;HbcxLg89@2Q5*yz<SKGyG@zNMS5Mh$*sHy>@%hkbU^es0tA|>< z&*+83jl44UFXy(*w&%I}>BK$Cw%OuideGpqD`JsH45dJz^6f#(53Fk|FI??~#5bQ! zu$uK4)g3*%Lb$zb;5J)w35HWK|FGZpBDP+JplhIL8r|Umg|?8C<YvzEMT|b<o^WUW z<wxI<?=&MpfNOqi>B0G##H(w51Y_pP;0T^9$fITp`?>3L15__N{Uokj##)-f@FutY z&`XEtSv#8QSI`72L&~#qmDoxL{o|yS?Hn^G!U_QlTWkg=Wab(5$HxX)*&8jRWO3=# zndrbTn6)8YNCkW|bR#2oizZU*!uIn=*Mr3cVt;2*v%+DrIJ&IO-ZlG+PYW(gc(${? z_r&`OKB4G+xkx^hd>=vl`+Dwy(HO)P5kx|ELJYIHHP%O5r%OLE_O(3C$iGRgodH4- zhU`f1a2aPBWQfdiPkW^BeI;VdaY$ZBxV{uB=utCW=jMJ%<Ns$~rNPu<)^(_rhafDQ zkFP4+2lfEZRsN_PiEX^U*q+0-1jo859v0)j5F}jIJa?vTUZD3((60u2_+6JP`vtN- zbhG=E<sTP;sbY_2p526j&x(;E5rG4OI|xS62zXU=CvI2B5^b8OuSPN=oPX4x{2WA+ z(dkgW<HH_9gZ5zti;M0!7%G3<Htmh`b&LO7e6tu!pd^?M{|LBe=rKhmEoNrN0j#%m z+;<3WPIGut*I9S;E`HZVw?D^q3-Q@G>kCyjbKiH%!nxw2I76YUhDw_x${GvQF|AB} zBTFV@MbRu{@!0UIov!f_wLiyJ0OLDmNKq-jbh~##$A<#RAerxojtYdK|9UD}OCYtV z1a|Iu8LsxUTAhk6*!)tCi0Mm5o=WWoT=H4IF4ynNgQAN&!r$)EiQdO`tV*qjZFi|+ zi{DFR4{+M0g!28Fw11v?H0J3fE&N;7Id3?a$$e7Ux>I3L;vuK4gG>8)+qjqC11@Vb z98sY{eP=TCKK@+?*zy%9eYsdAHTJ99Q-zpEn|8k)TC4lf`s;;~J)rM@;oBEEO392u zq2m1v8y+Ip&S;*!eQ^XvRK}S+DK1+xpX9Yt#7PsVVtlU(%xVw>s^%NpvUZjzi=XTA zO1tqG$1d^0tlVm!M|~cD{m=8__`dSizJwmwx)hi1o22%OHYFCmkr6UzAIy7i`H=q3 zhJMNWzn~dOQR^{}dLb>5wz8FHTnL2f99M4|CNp5nVKyYq8*TEL)ALXNx{9DSAV9?8 zgNFH8tDUUyc|-Ise7y*b>89+dTB6cs_twO`&EvvYsM|s#{3@<KqxM+3b^62L>1Y8o zV-TtIn~<29A2#4I!8f;=9qA`GMfuzB3AagcIZ0dn>od2UlX*`)*Kv6C8P8g0)zRPQ z^dIPozh6w3;d!gew5AUf)4(KD3nepVHW>=KL^vZW62K<om_V3wL#vDapCeu$ej{M6 zRl}3H#tSOI`+URN5rOKVlG*T(h!p8pM&dIK9f1124p)0DXS0lU@S8{~K*3Cln`|79 zw|9?Ml@iSMRAKDI#<+iQHAR}OdZ=ZVERKoBydse%nD~oFqFB>|nfddQmtQL0OZyb; zQitS?eu#Qv>N~AF5Lndz%Qbkvk4(DM2nD*?$Nj>IdO+2ZU~*YN{rq~$4b6iKcLPWL zmJX{{IOP>b)O3uoB|qXl1^n6H3XX5&MDtEKKh00U(Q?z!cA4P%BtC9SoK>9!)eVQ} ztmMC2Va;y8rvZk4u+0aJuM&&C7L{=Alt)yNsZUslS~@ybmHYHJEGkowP)SD3T;E-F zV$fLnm@GAPr5k}0w<oBE$d3DyP|aJOMpe-O-vF5}=JnKuq2CIT!)Y7bve1t!FU-%W z&olVUuw{EwX!Ek|Z?h-yP(#{UxW=W`#0w`**;vuJ`7Lu#D<RuwqPjXZJ5fc0cOEji z4N`MM3=u$E0If-2b`n?1Z}fP4p^WT3#*OD!AG%b+3P(C#pOOl0{&2e{(ORZ3KKo+J zJZnQ`H?-C9m*O7h1s8NR->v3y6r0*H3!l}TXm959za?twsdfN$I`;m{=IXmXw@NHS zHar{d(7ikE@b~TjMZZ|wn%$h<?6MWq<M}UOSBXw<5vTCcz56^^MZ|x?uCC})lWmh7 zZK4aQkB&d9Yb74rUAPw1bqk$~n_;bbWgkw8U(#F)#V6_S$po|Efnmyj{CQzdhSz=c zugvaDT=4w7vHJwF4;--t`?<Dd;wom+v&(_h(YgH7JRp<*wy`+RReJD2sH9^0T|2SI z9Ed09BDGnRA1BKHRQ~hyV-=Ow>L-hDfa89pwMq3b8ZUl?$Sedn9c$FO0(c|AHC`5( zUko!DT4goqcp+{D9!><$)q7uP`1`(jt(m(HL8{_@7opp~-@%O9_2xPCu)k70rg;&4 zU?K!#%vCyEHg~mAW<E49Vp@FyOlKp)^SIIFr--ie3dZx8G-_dmn+BA7X?jd1$D83z z<&NASus$;(b~aDtJ!IhB7<W~YdGAL@3mt}2_{UQ!(dDrDsTOt_qFFCZu3Y@LfhGCV z5G?SAfA<<yN>*&V8+Tw~7n!tB%xN0kEFWbmk1-;`kjMXB7`Df-^+&zh>CotGPWFI# zu4px$6bh#_zglDdA|~DKvwd0t61uQB=U0MnoBJ}##EDGgxpr9?1jB#l#V9;vcxJX; z^ZhET^rPpHBa%#-FAbjihAVrpp)YMb5Ku%w89P4@?QrTS{+LxbSH`=ps%J*_<s&?g zJ|4g7IQw>qPh5C{u+r*tm}{}ch}#xBZaZ+*M*z?eM{8I#rt3goW}{)|R(6;Z5cWHi zVh_;whmu~6>*kWcRoju&633XCDWJFQAH@aFRibOv>I8P`7qUyuD;Z!>b)V5y92jIC ziLxr&o}Dd#Zp^5cqhA&}70f^ie1D4)#4GOu%?zvE<B2$s{&usG&v`_Ts*B?kq(G~b z@<QV05D((sofVKx^*E|(K~^xr7BIgqlDq05Z<}B`3|wP&Oepo$$?i5%?Y-IVfl7#) z+wE5o$;ZSeZFCM9`~T?N`diD1c;}`tTrct}&e(A*<}1EXquHb(tS!XoXZlJ39A^cf zt-6Z9y`4GA;QRT_d8FAn&S5MC{7rkJ2QmMlQzXx{?fG?}xWk@(>clS#J|c3fWWOa1 z+H!AY+yZ<hZ7=qZ_2rZE6|0f&WQO=dj#@sXU3<*{oi;ENm<%U6y%c9>Z|%j@*LX+y ze6(4*0|6%Uk02G=PdSlW!=r(><L1+tR<8OIY_ddfTHqgk>yXb0mD3Ke&KFyB7e_6R z=J^*)9O@hMF4?xUWQf3*Y=b_TLk`?C%m}}kN!x^BrlPVbCmY+zvY!HjFb9^CMP<Rg z#6C@wAytTMJHsAY$$8I_#Uo{qyYL7w#rN(+ruZQ9=$@7cIGFB?`JgPG%hJyZ&+|w* zZeZFW!hpxmfVQA|!?dciK}myV<Nc(e`w>qm%sY95>ZWk2SkLO~TQ}9UyxcFzqoI#l zZ0KvgdY%R2CANOmJrj38TWi^-;4P#w$FLhH1xu=;OhuN*%RWiWdeDm}O-ayoC5C4F zl?)wOGhgzdLrZver%2jX%b|I$JF2=#tb0AbY6i#J9K<j=%&Ip(+W$agD@zD$Jg(~z zl*x8EOaQI56^M6L1hRP9vlXF@ak2BOhEX3KV{1%y%-Ffxsie;(seZatRq~pw`~NiF zH~Ova{_DU9-E_CUrg!dRS<X5>_oguWf$Vjb{`|S-j*##Y#HC6kU})J#U7RZ0HZpsI zgTKCee(bmjXukz*m__2$!6v#geD#4kFr`D?cY)#tfwKI=&_@g=%lY<AqCrlbvuk;C zs}*S}Aa|=BQCA1}?8q^x=6R4`CSmI$@-jqIF8Qn|D>R9z`=4hFZLRGw$K2;f>^f8) z2PG1R89f4XuA(B6{+Zfd-`peG2PL6n4S<+QvBWCq-0Z$-Og(CR#817H8JV*$pM2@I zB}N&Gr?0A&X>`^mra9Yb{Std-=IFiXkfpmpgS)g2vXylis@q?2g0+}}hk@6Y%!Kui z`XpmDh3~Qb#oeg*q0tv8Q^{0ifoivFn)(+?_CgoHtdApS=RA_@wKcrsBWt8WKv?za zhNr2d=nG8N8UsQvdY_KP-zOTzoq?X!Dtv!&ilqr$V2XT{EA{}VD*nxXAm7wz8f-*Q z)OZ)u#Md=e>~K~!`<bydLx5{(?I(A<9s$qh7Ra6NNXM9g{*jBx%skK$s)~`G?_%g< zVAyErxH3^X9(Df~TBLCOc)m9?=u3Dv6fP8DtL66scWG#$9Bmhk)hxfsLSu)fz>9|i z#q)K2*78Y%KKnKPhVD5Rb>B{6ylyfTk}SS*YM;iXqML8L;b;s<ZYVc5=d~o*S*G~M zzfYO3(uT^!^~$&P!+~wjwZgo6!&~80hvVB1Qpx0dLCXSD{9K%{I-AHI2Cu0rYKU#U z)1)BvoAv@bl2$f=63!VwSJ+YVR&xGrxq0sgmz^;)pBvcJX*kP#x!GITe;QTv_Nd}V zr`N89kTBz)zWN|!2^T~qQm(V0x9n6c(k^CYmD}Wa0rD|%@ncp*`X<gp>LI72y#F=_ z<axVXM!k<i=1O|TbcM<M=8vA^`<c;g!@^bPZ4b4Ae}3VQ*sK_?Jf4hCI>~>QJw~PS zeIq)%KYofoV?DG>4Xb(a^!WY0%eKfXc5)tXMOpiVX#vSDVnEFBh-fQ?Xw7hT0Hujt zaTrZ7n@fRbTD=H)FMp7&X0q%y{<P;u0<H{)$(a(H7NtFY!On1Mf=uwI-McnqI(l9= z{;OyjNP|BE^Wo}*hOSssUk}!dX=Y9jLwX!mXGeOSe2wCD&J!uT3Cf7<Nd{#)b9@Wt z8ecu8p&Mi6d=SbTTq0tv%o$|c+O9*hHYw9nGSzNGkb&b}`qRzOdM*T)F^%#|!D``+ z+dAd=`c$)>^mHrd8ye2~rvGsInEC;<^Li=oKaIKTwhO7+CjamMhIrHHq|llwxJ0Su zhLAX_@x&66tCB}-|Bn+UJO(;%c(Hd~ciwK~Jf?9Yg%TgAYNyaS8Ryk9fOHQs8tywa z9jC#}x1Yo12sez<fF*T=8$Q#(%d4HWd2_U$25eHD_fqd>r2jFfTi58)uKQt{+{5n| zdkjYBU_8q7OG9}<3!Z0QP?F%1!i1aI@CNU6LilXk+V_MgdRBi1$PncZlgUIB=>pr! zgk0zc&*V_nh!@311m%WMie@0E<Nr<eKXb$V=)tzWvuya6sv|`atzU4WlI8$p*u$f4 zddO_R-p-Uw7M(PhW>X5D)M5iXoXU<fWP8qMuw<l2G8ssPsl|)J<?@c|ir(r_3heb3 zi1@VIA2~F~0ali9vJWc1Jo(b|AGs3hU~Awmonn%<(8R)aTT|=OP-~v6xoYeGYBUYF zBbUi%iaYjn`lNj6;_%LhgK`S*$Sy%)kYsy^nxmo!Cae!x$S^1GY^f7ro5$}y8riAY zhC;{M$Fyx1+y85!|Cuil8YP&9Yk|IwXtw5*?b(q-LDNrKweTb30XtV%Q*-5Pcyp+m z_0ctm>ckrY-UrX09@DH~!L<`67*x7kdmcQSY4CD2?ihIA{B+~t7wewj&;)(-lVNPV z-Hw2(ec|yOxn+$W6%u7qaU)mt(OaSF7b8qbGS=y@X861b)dLr0Sj-?*rQjcnnxyLr zT~l5{BVT>%OL|*uA*(g^13X<B7a~4@3n8PKHetoc?CJXkkK&3ko|Vzkcq_fq(0qv5 zahv(ghqKmTn#ts2E>7?94)y3Rb<JYBS;hpW{vWpfi_CAv8ClMIFh$P#{|z?s;y+q0 zM|W%UhM>~g0{%bT*JF>buXEP+Zm9LwJrth5Wo-EW3$y=$kmfSj<1^}TqfJ|>8c{hH zsi{Z<s}3#yP6$`1mlIgT*;)S;^}Cmpy5+@`3~Gr&&PVmA;MRjOTyJTtOLc?EZ%+C8 zP62fSucauj->_IK?l?R_G1!Ojzy}SA(W!eSqf&>(3OLoyRVhADd@9o?$Q^bk72PS3 zC&nfDZ~04qOIp&3xltTs<{r1d7TH`ynAXkeNKqkn&7>Ke0e50cE3w?R+fVlc-HFp+ ze|Q5`eE_O71b=6Tx1PT^8uyyz*S#iN8{!%&H>Uy(i)OjgonUn<W_kxFJg3s{@D2!2 zb`<4V+%iMLF4uVTd%B=rvUn0&lg&U)IH*okIx{568PxitfKF|Ib*CgG$NKOw*&qjB zFQ!SVNj_<lwZ9uh%Bkqw3;J1bYli%)qOhJtIvh}kykwE!DD?-u*Z_n(P>hLDtYNwW z#pp2P;|jk}?=36=AurB8Us!Sv=5N)tf|Gvtq4Ghu>+(MZEoBujWneGICj?}W2G>dx zQ;f&2D`eT|3*D-1fxTE=w{&Yr=+^VYM*`HrNwrdHh{RxBcpi(Ja&~~1Wp;s<+I&Vq zoZ5U$Ym}E|1fULMo?QD%4UtqUs}_|cETxw9D};Nuv<(>{y5A#K7o4zyNn-&~oS`}b zNRlR_JY3+@%qaKCx(wKXqIAozD@!!Y=+G>sh04uZ4dnu#$sIBS^&W?aZDJUmjSnE8 zPs6kTL<CCm_~1=#z_SxK#q5K=8ajMwor_Zvm;@808{dljisUYlt@EdsYcbAQ-19n6 zzNEXAU%uTNoYKPRHXGLp5pWRAg@IlmA_9#|T|_EE-t{uJA|j3x!EW-u+oTfe-R`y; zv+kgBnf6L#5nk=t^Jb-M38S)MsNml|e4E2^H{v17I#6}nxcAOD=YfWMc%-~vrHZ9s zv2#$1C!Q4Pc6Z1>Z|MMSF@TKqUQ&RanLO*QdZUxK$hUl{U298cQ%#8($GCmk5p6|i ztThs$M3;lu=ebVBZfW}GSkfgD6v}WLf$dMv$_oV2v7+yPo{!=0*Mh{BU*eH(`O}(O zQ?ZTNo6hXuP`ZO{#Vi-y5$9cK>>$@dyUM{KTcF$9xl&SaD9MI<uS{dc^gHU|@<oo2 zhc=u({?eP{W@w-L^PtD}6}ch<;wsZejI};u*=@0cqGPn>XB)iXF+<#)3{tlf;v7+2 zna1NYtY|!2hp%+p9NXVqm!n~>l$OXIH->DF9Em@PM>kcSeh5J?$^8{UZ^(&e=8<a5 z?PTqB^XO*LT=xuA<!Vco!L{;l6<D%gHSrA7Eh{?D_WQQXfxrCme!!MHdkWarl<A}) z0)>-IMfXLPf_d6RV_Ckm(JqMQU^X5$jjj3wLqv*}DPImI21snKdjCyuA+_3b0yd1% zCizw0y<EzxcV)F`yAKcez`)nF5R`tNK+SLD@_kDyr7dH6+B@9mkw4Q~8?a&I1BOfZ zYsC5D?KU5h5M&)oo1E{c($!&4T|HcjNZOA$q-u0*h<yN6`6C#ZNe*bgJ+HRS8&*6- zcsx_MjTA()zHWUJa^Uj|<=5fI>A7Rp@%~;mukxb6auYc`{Uzb_m&!%2%p{(EX=+}A z;w(m1`4OLG5sZ&zsgxMr6evS+>i%FXYReN3P6Epde@Jw_q<`qP^NeZjnJoKdz!ML> z&e=(<ul_ODtIl>+z_4jdrA?e{X3mAt$}9F2DG6I47At=KvzjTB`V$4N7U)t{r68{4 zk|o)na=6^KMum#8TGKD2!<tn{92Nputz+m8p&D8iCmn~+=z>*)PXD2VQ26TAXUyUH ze4B+GhsK)H?o~(3_COz_<J|zBGc~5AVhR1ffd;n|)X<A`EEB&LnOGN|jQ@E4$KM`= z<X5m&G*ELFCP9XN8DM+~zUG*p3Uin^ZZ*QVa71iyx~a#%i#T%|kGuYsgrp>8^!Y=~ zq%$slgw)V2jtCe}pGOs!Sk4>`D=z;{(A}(=jiJgfOYNYBkjnD*obfJy4QjN$HP=_8 zdip8GS^T5S`KRLJVRcq^^C;k&CxId5jB#!-X2Cu@llr!2a;%)#ro0=^^_w1x^FsUW z^jfbs*qVEAhIP}g^?b_N_I>TQj!fi3=7G)boegzWfk{i!U#?E8;Gl4CXzwYjqfa@X z@o2A<`uVfOt77UIsZXX~jvOfA0c)4`7E)owUm~RvK)K2)vJuGM<JM<@cYI3}%NRM9 zL_-ES7*{st<qb3?;&AvJ5V<XW=r-Q_`HUq80h-Hz>mYHx=gPJ0M*bd(<=h24c){>` z3E7>wtvF9XUqk0d+HTfe)AmV&Z+go<cI{PdKFJ2~5n6$L+3Nv_T+aG_dk`teB+fg8 zzept!C2ZqQkL!N3+7|!1J>pu$gf8pi+*m*dIB5;3X{WgG4cinCJI{JM=P;V!zS<d( z9}9Bq6-BQZu1iIp+$BywYJGUL&l)tOy)Juef%PPUsE@g|x{q;W8Gj$xLcIs1+ubfa z-oL9=#RQW0?4aU_{}FgL>}XAG!+b<~ym)&k)pC}pV0gT8?FEKZd~MHh&?q)$sDDcU zmgR^uT1}*Qf6dzoqQ<t7l#pzEHd(X$WK6LsPkpj@%cF_GZTD~Buw0ug38O?<@aKjd zMNrh&;<P5<*TAi|*{BxMY257?x9^;ccikr9u9@WM-sD!euj1sn0%VVeqB^=R1Ch~Q zlF=BCd>AjsDM_R3SN!JPsk#Rtt8!>JlIis)lXDSB%N*M~qr<&n6iVa*w{2^w?SFQh zTA8uqRAF@__UFrsa<sCEGpZ2(J4R9haM5Jf3gQ@*umJznIdE;4N)TWEe)2C5l5v0M z^yN$jM~vLx85LFKhGe_gq)^_a`vA;JNQo`Q!Qjky4~l+teNLI%a{tm_pm{<aGFq@b zs;QnnkYEes3#_V#fr;Fxnw-VPETjai?S>hP0VGEu)JIF2Wii7)gm40Uq4NCm@kl}0 zfTXfu)-wn8`K2#j2y!z!-X)ZhEcrONF{a1L?sfZvpMUP7;+I>@n)DOz)CN&!d*sPH zpbvQe#-k9Y^{>=JnNBR}XOK{TZ2c&#k;s$4xIsO)F2gd%r<CmrfgzQAKJxYB6|L%` zY<LdrLwgrlDl5-G#DS<`me3uRriiFBej1-@BZ6OE9QUsPvEkEl$AI!!R9?cfu!-Vu zQ5@T@Y@DcvQf5LOO;YS(X%60Kg4UE&(*HjAA-s+B)PsKPn>_W6L+I-+`SjJK1fB#n z$|Tee^|mNAj;NUG9a^Nc+zQ%UL$H^WU0z5-PezEOvE2WXAHW+vU;NR?`C|3=N}6Or z^lhLE-xz=IAL7qN$T;t!4?lHQT4Dn0pNPBP+JOGWF!tEW?nr+a!bx{L$$Ei%Az9VM zk`Nt+6#D=ph5m`zRCjZiiIhRzroY<`RSdC%BO?77L?hN79pqjvJT&=vJA0cLCaWnt z%HHR5%P*)_oBXv0#mbS}B*D+oMRtr|T2bFOTsD{vqf{1VHH7G5k>$=^Qcxs<61U#z zxP087>;C~tiC4V|UflCd)S%h7KJtOhYZqYA={@azpV#e&Ip_3jSV7`P2Bj#ve`2JE zd-7R=OC*jSPn#|tjF*)4(zkwT1|D&6^QXaITZ_RG1g-}?7bDNxwVKPd?pE?%w59i$ zuS>`?5gxZI`CD{f(7&AjMQXAA%>7i2c<c+1?@1d*(x&FQcl50@**h|Mq%TmfOmW2M z&InC==>cTirT%Ro{1qYQ$5uEqpu?T==+tgVh<fj$wVLzSOWDC=^-t7@NRo~w#&dKv z4KUL9Zt!1~kV6|SQj~R(Nb{{gcdjGrw|^SruGZAv7_wM4k~HTjp1)!ARF3uTX3NvW znSKdeGycU(qN*Hx&v(>5IF!h*9}9-=0`C1p3obEr)mWtjQHi6;=6xRR9g2IpQD9BE zF<jH<tg*Tj$3Knb9%5eJ=(`yVoQbFtXADZne^i`^A;TKFpzfuBh!3Q6K+*i|IytSC zuTiWWM=xMI#eQ>NBp$!Belrf@>p7X>r%uQpR{2Un9TZtsDD$^vu`l2SasY_@Bygx0 zL?Wl)XUo$vx}@+AXQcphU#-IGy7SrSK_c2?>S*&~^Jm#d-jC4Vqfc0aoH_2j%4@>D z+f*A`X)9oozSYRo{Ub|RVk?orgWY&vnR3h&bpl^S7=Nt<XnJQSZ_nHxYQv~rzxwms ztR8B|DhTU6I(&WX9&(h`mm5D03;c>+Y$pjM>DUW#0#H1S13zsPlsA1HBmV8mJY{H& zV>s*Cs9{{be^!nN?3Pan36g{ZMRv6L#LSlAUu9_4x?GzopKWXNcht*rSx%MB&$AWu zf3q=CeK^vy@@JRiPlhN)8OIgcDZVdkm`+;$y{<}kjD52j08<hbV~-X~0?5oU-u*EX z9zijIy8XB9_U0>u5@T2ET!LuZFJE<?eDLKaZ{B-`T3z&`Hv{6)xZ~Nin1M>pms#Ip z!+^4sm(W+V)mgrlbyqq$1lI9>K(w^hz_s8(qR>~-5XQ?7^UoBLe25FWe!Xii&g>L0 zRMM%X3XX89ZNH}o4gAhoT~U$ctN*6I3?L+IR9d_bw<w$$_p&CMM;v~S-}VEtyI_P5 zWs8EDX=5BbDHk<KhI9M3D@gz$B)B9Bz`AYRMaLB5bn-F@H6S&1F8JsZ_sdFat@^hg zChCb@93H_!sA|VgJHC9F+0>Kzr>u;AG^h&Z0Ia&Ecv0C8b)mRBgg}jN@|ye}z_o8x zP?ibhPJO(+mEGH#ar>uOH<?VOg>PPZG@DQKbPy$oR2Qi<l+P>-XMrWvHc;EvP$Mmi zE<LG`mc3#Vf0S{f#kL0NB(ngy!0SOpF?yAt-tUA5b73So&ww2{F=zsQ8{sw7sqvzn zbGu~{M1PPZ%J9k(aldv)cRXP*n**IUs$-m3`D?o(x&Zk&8_lvyHLv3+w8Gxv2+~r< zX*lLbdB~%isB6C@V00e4!e0|;QtD#n1#kTbR1Bg20-jLF_+b9(I7VBy-8~U@eRt(| zKp3()+W(*jC>{^~`4+1E@(YLYfJbqgiKh$2N%pI(0nQFy;tHCCt*y}t#!(^MS9jE_ zrnjH!UV48L3S=5@<ybMj`$CK5#lL?p(QnxE>NjuqGXAa7A6lLr;Cm|F>A%*-LEy#8 zuw-1^UxmItlAv~kl8^R+SCcm`<<WbBSp9!Lr5<Mc5+8MIhR@lXtyR9iY7y8JIzCAL zC8S6rUraoUR1z~}UD^`7#HR2Y$%|PLlW9M;N;*5CI=HtbknWIEp`X*$d@I>jHC#pe zHJo!_EWzgbE2HlN8}Fp;yoemA!YaWo-tCsQscP_YcOdNRekj!{=0P=I2yt~dWsV5- z_qM8SB(!^}>bqS^OkboUV^XX2t;HRS>M#q<;9dJZA*KUx(t0A?wk%s=$)SV2vbRR! zJ2il$wJp<*6n>k)qZp(y>Oa;#Xw^t+@1J+LmFRGPzV@pxPG=R&*sr{mch%H)O5fSv z+sx1rs8V~~y>uopWS&N8!3xQgC8_kxvU{)<y-9WpX-t~%FOceqbsc1%`ooPkY6H)2 zB3alaN3i@@D1rDQe?pOZa{iKh?f@8b6$@4cTe%YXd|m&E>&qtG>NmtZg&rm@o_tKA zJ7keMv>Fd6V`-V7w2NuW*cT?Mp0ZLF^+9|sdfNQ&RlE33uXvemx@XNky9TNCS@KXx z%*7dz9o+Y+;85~9HH&x0o5_&xuDbro6|e7-KZn?7nAh-cu|38Q*4AGz|6@^@d+Tq@ z%^yWntM7|@T`H@5`ttQ$<*XD;vwp)>#fvy(*OmiyzeDgJAhGJH?1RMjnmsklFMKGB zS04I5E(=yYY)?lMv;XM@sQd4}Zg@}kH-DC{=QbZ8CdiQ0a^F2^1I4<4dhdF3n~=Tb z^!4$$iW(F|k1RI;LN$UZj)|f_RenZ34ubVHeW9Lx+qz{`?Lsj|eT;a9yNXt%t2*fO zAIjzGdHGu6uXX{xR?MTY-c@<Y?KAG5`_d~&mXk@utA52h)iqpC0XMIYMPC2pPu&0R zzr4ts3D5cm8R-VS<zFDVs9*`6R|>sT-SDhskGwkdxhekibF%+$liNxsF^`+h5ibaX zIc?;ljnNEaA8Dncj+Uv`agQ+q^JioyZY*<G!IKRSE}EWQm2QhOSMQ16x@w5qe`9x0 z(d8$0jw|0re5^)L&z<^h=y2n@CQNP~4I@Z9gsfO4nr8<Mcwn}boS}*``M+)jf898| zSG~rwjAg7-yRbNZc=V^|v(@vK(5lYR>~-%|m6yR3=@&(e)uk<uX0zFXwrFCj`h*{j zYGrjbOGJX&Ac4$d#ZdOEI@;zPOSGlf(ZsD2SLT)`=2{AdSDE!uo<mk<2*kVk(T=}# zF>Y_!mtq*YDXU9^AKEr%tcSbw8@n>ixp>Gk<mv1%FG6Pp(BBtCSdd}KED;OZ!T%4d zKvciQon+&;jdZZ<XpFW49xF*+e3amLkoqS3w%`q+Rm4~62-y;`Ur{GrkAXjY3v*~6 zu75)9{%yd12Y$2O_5|j`Zv(DAt&9E0BX(h{shy(#?j(KeZra0oiLUwpa<U?HwQmE* zen37W$CXZ^hjfAafz$SoJ<e*PzYdTskl^(rfYBPlQ#)z>FNf{kuM*EGd!Oh@#TSX! z)(*&KHjv)^HQL9!$OdIK#$`L&v;cTvFWU7LvTulK4;MS90@;a%gjaXbesBYGK<pj2 zVD4<ExwIaA-9j|(M)EB?K)$XYp^y8B-gy=8cToA;$ku8T;YaaD6@6}==GsQ={TqPi zeuw;igqPVuwu>JUOm~pKr0kvRD6ja8%AU9%big*U_d7s7v@4Z8&>pgh>ZJDWqdtor z;G48Z93#Dek9qjMl0DzR+<#a3toXF|+*UsAA>n^V`GExFL*x@rQC2<^Zvwx)uk856 z=A_*Wj%CefRV^Z&1N*SB-+w{HA`m^d?8V=vXJQNI5ltrLd=KMPAX^IdgYv;!`q;-i z$Yx6Fy-L0}j`EGr@ic_bD$@Nq>@^p#E?tu6T_rvC1zh{UkM-eMKjrU3x`=TV{j%u2 zkC9(`H_0N;fadZr$LEkNPiWXvxXvN|Xfnzjhvy;(>jY0E`kJ#O1MWbZ=MermL-gw7 zBzqP5r<?p7zKJ?x=*J!Ks%4^+UGi(0jDD6uGoK`xCHopVw6`B6`K#Dg9X3PHOcgrj z9nuXxuJn0xNbcLAbd17JS0IboMf{CNI)iSqhY=rC*$3y7ow4Ao4)8k>@!z|Nr`t*P zKrZ>;R%i}$ES>R~^GxerB>45wJim^2eb_t4n|i$WSIF+-P4rD-jkJ-DMV=i(zORye zVkX*lk$ebt(fap@UcHDlaGLanT|^go#Oof%dOAmXlJlhZ>Ly#ge&F!)WS_en?bw6% z39QA2`2fD#iuJIM_V(j|MMU*hNSD2xc<4^DmFqx1gzqXMe}r}pkeo*Br%$6Doq(~- zgDqrx(nq#*VzVbUbM2^eo2kbk*g~=kk?o!&TdjVQ9hSi>KaKA?Og&D}WwMt&j=Im_ zTBSKI^!_Q*#mHW=oqQpV5WU<<dJ(bZ6(620*aOzlS{Iw9exkP}F2#3=m)V29?jjyN zrg7R!^oqzQ`^ZM6hv>&sDE~C+wAYZ`=>hVm*Z{wP<0Kb|X^%ZbHWVjN&S}tw-2}r; zBwG{y<OAS{9`XbDD%$>sprbp<9%KvIH+&6ndIh*jY>M}R#@j>iyhC$e#{2-yS+Nzk zh;qfJVjJi?u^|zAgHEzVTu;6Rdr`+h@?+ghz9<8vZ`w?LH9sbs&|W-~xqgcL54u6K zy-w@;W0Di?Ae$7?rSBu38yUlhWEMw3v&SfVKjD*YWRLwW+P04H;A`lw;G?~0_Yahh z+E$|1_mkiHZsLvh6Fy+OaM7`ROmNtSbO3dT9qR$|uaNnE5OXSzzV0HQ7V#^njpc9B zz9#LvL%u(U$j@gN@wr>cjz{+MHk1{R4euM|4-<fI>O}vx6I^~kHqQspjzw69C&_+l zHF(-JB*(Z-_LQAu4|kjN<38c<<rvqEggf@4u6N1*do$`>N%Kj3I(WZd1$fBw)nt>t zL-AC?n=C;eu8@7ui`b7HQ;!E%HiP4@y<-N)U&|AH?<@X-W6b4g@BhFIjtAz@?|}Tc zpCwxS8Q@6fk4_NHB6#p9*`4;0e)KfiZT8@I581o*l0E)j;Fmn!^^@O;WAT+{nnq}= zSlN^WM2B95E%^-Mw_k;Ra3<OO%pe_>jK_<l1NOmFoWeWN)Ao^lz}L;tm=3+@oA|iz zB!1;6+BlE;CVt4hipLVZ%A@^h9QrS~VI1kIr;!ht*prD3(=_}ZXX>%ODrRupixTk^ z6O8?=WzkctCfVr*;G%7$bCY;4f(s9j4nzF4L?*J9{5HCPkB;E^GV;L^f49w8`<|)C z8`+9=znb(Un*l@7V{9V*-#LuOb}DxT$)_ZiiF~t)aOe)me1#60Pco|&q=Q^*>T#*I zA&>Y(u2t)Lk*UW=*+S*)fIeA#7bT{O^!)%}wH|U8iFdP>e7AO~au;Jxii}nKIM$HN zMPm1ezuz+QMU%2BSoam=U4-`D0iIrF>akr!ZnKGO3nY$>wE6GhekWw$i%mVo(FT%* zt|Z!I6MT*&kH~~%|9O{i@gdmdt-}5Dm=|kN?<=MrGfaHYR)eqEi}$PWUSe5o1@2r- zW44iKhLz+G_$J=3B6?>h>VE<CNn18zj)_ghBGO;ahwfr4$xOG=Iuf1FVzluEQ;*>& zF>fT6(I(&`8IP6tei_M*C612VuOqqIF~}`8ldZ`PlASK4y;0)!{5q8(?fHhO$8-|; z@p`g}d<|__O1383L2pRxrw!DORiI5IzQlU`-b?LRLwYoMwgS(0pgtLw#iSDx8RPTF zCq8@2sh-WiiQ+G}irz_Fr{zRnETy!G*6BHvFY%ZpmY3Lzt|T4%YO;Hgetd{JBu3dn zT8F!cR$L8uEx{fr@tT&JdQ7FQG?u+IS0#4V3d|cBJ02T}%_uPv#cxpXiLCd{;B9|Q z{n<b={cixC%gAna190h5Q;*Xpv5|I~dW?*9G{0qDJqOrI{79aYPoti<@%|3kP>H?N z(<o;l)hpM9z>RCL4_!uE){sp91@iG+NA|oDXO8We1aCb@ZCXrw>2Z>etRh&fBs-Wz zH1{M<)*8t6c+U`fDS_82%w>V$666&>+qWRYeF4AMp`0_ID<y`>3c}$F2*0cYtk%=| zm%h(6^%!2u3I0;vD>N6Mr?%cgzD4NcBJ8y<1NW{n^|**)llFnB$HrQYelElJ>%m8_ zH1$}7%W2Hkg4Y(fi65_w?K1MGk=Uh+(U!HQ9s_0@=`I%H-BMf+0&cwipGW<x$aYQk zw_n5a50LjcQ;(zfJlO?`9pL*YU+C4Pkk@P@-10ox1+JyJwUTJ46@(9untEItp;gw< zcd{q0CYs@C!pGvT{GO@DuslP3ml$XQ_ZQ6Icv6e;>;<eTu`?NG>amsr*h`6Rz!A{E zMdCX|M%t%rog?ru$4G|$80e~#B%>5RGU2f%fQJZ39#I0k#P91E>hnpzT_pM9E|S3t zKXHlL5ke*)@?`OUubO%+i~u-eyQ#-Q3sBBM@<Tp`>nEf?E)Y!KKz-w}?{u1ajN$!c z3%3^h$po@H5cqx*Z4?>1_yGTosmG&^i5L1B`P7MC{w*5+4*;WYl0Cf-oH3E?GdoGX zy_<Ze#0RCDc;O!4mK(s062I><=1?ceyTopeW8@qn{eal|?4`DC22481A8$9{zXN;c zv!)*7NbG$-ApaeK)z?YKD|UugNxpv?G=_)v9V1&*hkOVe(r<|GLzk(?wdpnW_#S1_ zdG%q8#b>x3>$ynw*9WPMB6pVg{3BD3-6}o@^GrQvpvbl*zJ<h_+DrP8fNb7=M0OL` z$d~Ob=`%K=9+7YN&>Vit)Z^B^NAMS0MDZ8ePQH2^!=(rOir6!3Rq{oNK@yOSp7;xI zp>?#5^xY20^FA^4_#I*gyN!G#ZjpaiK(f++{OjH)S-^fgTMAhH8R@44b`sO83$Qpy z@^8_*9mF@?!2M$H@e$bqh|XTduy+3)$ZaI{p7;p8iFI)t^UNnXa~butlMT!sd?)dq z-p76;^6t%eFMgX>0T+=Q=4qY2Ml|$VvajAkviBX>*SC<Ycs=rqz4hC`9ajj4`WPb_ z<DZcH$02{c8>SxHUSb=*1e`5<*o#!2OExPaj}%+TuhM(bK|ZeJPERPCg7IWS7Zbj9 z$Um_}`;D~!Yk;%J*F;~KM?Z?>+y9uU$43=eRvEIrSAc5++)qF|WG{agWn3XYuYR=Y zimAtEoK7~a0puZ%AvvVmU>)rxlJ)JSJ-iR=G$xuLpl=+krvs$-*+}}Ion%L|p5)Wp z2#?5|+d=kb!biw{na6tFO}y-8qN~@Dj6h^_i_PG;_gl#3RN`YCAbH$YQ;+|%k@TNi zNS?Eq^ykY+t|x6`x>@2sZ=kdbWp|QXU<t_{wo+R*(waO#HjCSc-xImY2I3di5+CvR zi3bxI(<+khZz8$kTH+O#(z`XpKjeuI{~p@Dn|Suc#FwuiK5r56S!+oixrX+OrPQbO zN@lX0<X78?MweJ!65DAp#$`FKBD>m+`6TiP;c=D_FS(Xv6f1~dTnn4E=SUtUeCsm2 z+ePxv@g#4)0KD)R;hz9LH&xhz%p$+6nB>;tclQRq4S^4PXg`d}o~)qkg2iSzB)oUa z42^O74&lxzW@sE>w*3&>tM5Sm?vkx*mGE3(2FK$SeSq*N0s1n<3_fS$Hu}~<dqD+s zO$jub#PEEI{A|TG=A5a=T|5IBNf-9mko*$6Fa{CXaflveH_Gk6`hSgVr{6a9c*}=i zv-y_tIiG>=E)dNnG|3L|2@6oK#55C|pC0ll=t4OX``{qjb%^W`idf4R0f)<Ed*@;N zMbFa*+W08hnH8|6`_ZrSxIbv>XZRcdd<INChDibQ?=(Gkh-Ntt_=^u<p6t}lqEA({ zYrxcFOxyshP62NH<ZCnl7@Z;C&yP`t#O}O^Hf+WFlVra#4&`1n_4qKdpNhWkEb?@t zzKdj|A$GjtQ|z0;F%QL`;~@I~8>SwI<0Qs>C;1+Wz4cYB!6TSsq7xV(TJ<FPnRJq^ zgT$gZjQ(6S^|&J4v{v>J4|0I)Ciak@2*>aK2EG?v>qS$K!z%XF4*Bk#CR^JxWIG)Y z-+q|rmTvMb6Bu<7O?8BL649eeeJ`2%S!>7f{3WuzJdd>}I6!oI1DIbDGvp@C&y(a= zFELxskZ)HX&BsoH=Lyo4ici!*vIBp{)Z=s(&`$?=?kxFRY{y*aCi`iLGb*+sLJxG3 z{lrF+W5nPq<cz$DxJumqGT~&=(Ta`KM9jT*Gx#jx3f@nHzcTxv95RE?Dt?M+>wxsP zB72z$d_R%og(3MS3q5?6+Ax9kiz3-X$h<BCkBgnM*fLkm(DMn-5Z@V7zofirMB}r} z=o;-~$CQ3~fb3EwHl4)oI!U%bBBQ+pK9Bd-616e5*p#};mzK|>@`+{;+f4E4oMGzc z^vy<|+34qVz_o1Zu@~B@&t)_C+=0jpJ_kU2Tl!2rjtIBwJsQJ9Y8*n^Go>7+NhAi_ zqvS&+Z4v$c8B;%Zph$dP3Gzs>8=gk6nM(6Wd=Yn`-qU248<C76BKS^IHXQnX7V__= z_6Tn|pkOF6tzI?OQz+k0%;577LX2Oa*78&ugGiOP&0=>VXA?55_o14PTkw91smDa) zK9!Xn#S}9*PJK*v5?pVYY;uLy?IPN7Ji)R^v`mqF@<hhSXCIcyzN1KMS!_Q#Og%P> z*c<J)*tC~OuB6Xk6#EkKJL2}p_tO4JfZaIoJ~}24pAYHM{PvY^WtIFz576A<c{HAU z3yb6vQZz%)D2$bz5yu=VQ5z@G_aW&kD}*=re9Vw+QY(;U4B*PVhR6>jp2Q98h0`%U zQqEEGbGuIM6FNm~xW9wGpC-AB_?7q5o-H!ZgJfqYu?=K?^_jtOWcqQHb3#O>>X^at zu{`pF5r2u72(N@>Z*`Vr^;c*QmNNyfQ+bb)P4P>B)diGs75BG5oBcldf4q!(eX>P6 zM*i8oX#1NOhl{9Z0BsWcs|k>`2bAw5`Id-$Z-Cm|Lv+_!v`5-4bqrun75erP$y;lA zen|BAX`;)|0B%0XNX4H;_S$o(>pWm2yoKm&kKo-|%;78a{sPgbhbZq+Q;%(Pf@oop zll6km>xPW(BH3q&zrY#5TjF?~B74Gqnr{-jwuk(3`p5@Tc&H=j!&e}C?I#&_ANuwI z`S_nA9|xJ=M={pNz(<`T9~7bIPm=$E$Qwm}b{uo<IKihA-^v{L8orUZJrXZb;%J{D zzT`d9557lwz!QX{#P+hA^dp^Q(>q}5G3mRBSN6%SHX#3-bEba2M>p|xou(ekMtE;I zk3#fT61(#x*{sVN`z_=@NNevL(r#0aA9<Ykp(Er!DR!l=nR?v$eI%om7+u$ZGtMa- z&%S!>>k^Y3MdCLWiO!#ab+7G79ikuk9ADu#9#*tsYzCh%{#~kH_S_=*&XtMInMU#) z*^6Y%-XL12i2FOVKgYDE$^IDwPB&<*%cP^_xOx|;e-X)b4v-&_@MdSR&KH=$=P$=t z>laA3SS7l?Vv(<T=!^K;^(eXBZPeY4b_!fyRq``|uh2s80B62~_t!{Pca~&lSMiR| z$R20vXCw#Y;~A1qUI}gbCc%9=*)}^gK9|WBSmZ`$$p=YvY<!OLHGFr;)Z+)q{vo(Q zY=5sI-zB2m`Y=8b@$tt|#!XX?7tlkzjl`d;s(rnW###8_S4=&&?sSxSjoQ*rv`Me2 z#|jg=VkX)pdM?qc^w3^(9_7tMTY53Kr+{w%kn~fJlb`S71Y5CnKS{E=W2C=5YwB?T zYvb@`Q;)fJj$~*;16`v1SIRz1^u=O~*9yozdZ{kKm%9jGo+MpoH_ewX<JmFD*;%gJ zgT6?-sgty)o}fMUB<WN4ke&N=+7o*S4@(=rg6n*eu^b{l#7-rrIY#}I`0CvjJB!_z zE7M6<aFcisIXmqFtvTVxZxG!ru@;&47M<R4z~DvN3q&?5I@Al8SFf6S>^T>><_h7= zYq-CNZ>3$Yl3(s`U@Xo9u9r+bo^?OXJ)uSWRa?dPlKnhhF@xi+%pzVsBEGU}>ha`U z+V90S;|aozGYJnrPCOgOVqw1&kIG~J?JCLo1KPI&wGUQ_5A_wkm;Gv!g+C8y--~F^ z@YU~tWPCGeAAN$#c@)VfxRt5w*~E*=J{l<BUailOc{!2zG1m-^3lNxkOyOAZ;>>$a zAX(o=`nE!2$g-4!N**x<G(<_sAR-#ifN+3EbV3K|&;li6^U3$#Rk9$KbL=7+UQzMZ zXVAV1$us(hS3iRBW0~X;W#1Ij{dO}r-tuP3vzPiUa_Ds=3z?$i0z8KzS~D63((hBI z9<TXvH76>V$K3Y`SX=G1=N&Tjv-fQC>k{aW6C|UScfADPD#<q|k*v<gT<9m>JEHI8 z+}2gpuBwu41<EIDi&_sH`?`QN5RyE|C!FnB)=sSOK@ol4Nw8))56iwqZX`Ht6XAq* zs^<{lnGRDw8^~8SFRYIpPvuw0=4(6VtV8mFQ$)k)G?9MuxvYE4;J8^Ft2(x<-Ce5x zET3ckLdI?)@wS0lLlvbzkTI`d3}b@JY+55RWIxNPexVT$67M8_b}sq;$5e*cdkB8) zH$!8Vb1Zg`WQ?~g>s02)<HWlKr1My!bny}4U&f_8-^E^R2Ijm^KCnJ`lM1bU)_eJ6 zH^(u|CGolNlhoYnru~xf&{S%B73~{O>(C>c(17+??cb-*E@u9M^-%rvPIPI~rgqv} zW1>+fV7+uHAJ*m6$4QXGgyb8`F>qqSL-WAvKd<&#*?(42+hy&%MfxYEVfgIhBUDC_ z=%G90YkP`x!a7#{c`Ew`&7%Wqya%uk#TMMYlJbeqjZZRg_USDW?x+y%2ox?3NruXC zdM28o@mXbD*%!H><Pb6KFPqHZa{!ngj4-D|MT^S1UPXP4O#QqemQ8ff9uz@#=+k@^ zTUL+uQ-;A=!ZEC0@CiQ#YW=gm#5aTE4y~u}_ba)N$iNE<4prsP%({fUvY{-}`i|5- zlqdR)*HJ&scTdr1Zzx@fz`8)Pf-1pfr5PME>Sd*KDOq$|fyE!2b?N(Qe#rUS5&79g zup5&(A~BT?K`-Q*daUJVP5nH(r)ll>5I^XEANvYm_AOJ7@9$dZ6Vby8&nC3?X_O_g z4@Lg{68O9h;-#*l{TINGb<q7ajDzUOPZ6$=a}#b5eS4YoJU7Wc>OJt2G0`(8NG|mv z=}J$dzsF2HM*VTZUp09ACfV;CCAqfj+dazW=Pb#VL{=_xn=5F?8G=_4d-^v>&vS|7 zBo|5UohSLu8Nl!|$sGF8zg_U<@ridnOS+HKfW_OU9s~0n<rO){k8t0Oy`dN1og=-u z*i&_oZH`0sGSYVOPq+XWI%I1k{SkRunRumsl6m)_?Gg)q62bTc$^ZM!;PW4jV{M!v z-=v$Se)iW%vU@vCxbp<A>?<L%27#l*;QSqu*YuEFEKj~qOye9Q{dJM#I}+FKIKfb8 z!V{!dlo<G8vwoQLl_kQ(w;}%!Ta>p={fx5%<f9=zkz0uW*hv1i>y$t2Vlz1I1oP{U z5e_*`Hv4k6fY8bX#T!TD19-*M<Fxx^8zy_<QIY}6eT8I_XQ@un`-~$yE1_H71@8TT zbU#eviwrMPd-q<<KbQ18vffyZen8O^dkFXM#dz#T-@ZaH+)6x<#8KX1>gPXhH}$ik zy2;-yAe+w}7~3wQ;o3>w@2h?Nj^dLplU>MdQ;&)GGQD?*#?$+pL-r|E`aU2ThtN>( z;{KaxqtFG@N$*lczJUBhWZr!PcI3B7CMhu%D`@j|@@>0i>hUFCBi}&TCnW!?B;UD7 z`2>z)uX>7P^0H@19Ftdx203X4$EG~0WUjZ6Ut$T09{O>@^=FB07h40-AM^D)ga_rk zA~}C<fZiQP+2_c<cz|qJkCNS@oU<k|)Z}^;xTi|Cag3MWAm7bSz*v0c4x_Gqq9LTs zZ<D+yCYe>4^q3XW-O8Eb$1#3AsvTXVujnHjEN3m|$p__4Q$J6>i}J|%Y<tM==pgwh zZX+3*toz+$$GU@jTy|1<$H}izd|u?7gB{BMawqwP$r*D;$yRCy@cCZyC+i~L6p0@u zcA;B<W8~}r(Usk#{fFfs2MABd`o9di@NMD=`!KfWiDo_l{+oRrJq0hZ>kr80@;c_i zIifQMux5Km58FYw#Z_{SK<Rir$g~SeCKC~lI@t`4CCmO|ePqA$8riiJsn0&G?^D3_ z3&>tp{E#o>D)OYOWFu7~KWU-0=8+9i6}VE)DH0w*<UW_o;P|msx)*uwe#i@a?D<v2 zkKRQ8uMzLnNAR5t{4M9AZXx?B>Hm`$*Q<p4E<?^##M*SomgpU_bH0V|9J1FQfY0d1 zrXIUMd@J4{z0+l~<>^P>mw{^sDBlIl+bhWD63ux6`3CT<=$vm6zaus*qSw4cc%NzO zKGK^XSN4G}*@ww_-6u#^DtcWxxAZX0&EurAyG+l|kS}IG{r*E!kLh@p>}HP9UU0<J z&otRacu@9`edOoYOM19o@J}*7L}$65+W8vVCV2M^(7+Ot@C4!De(e8zR)*NKNE~yC z@wkrc+pnUYF4CojWDj$MaA`N%ATgIO5x;zybd$GfJkHVn9%1f?UjH2CmH5O5WIx&m zoOTv@&XA4Ud1dQ%9_5SOiJT>TjMkIz#IkpuA)7ln&#oVB`;csx`iVC@O!f({ksL?r z6B!`u!j783XK@}OdnU18I88P&`-uk<8>MR`r}!cHIqoC6LF^DDE}5LG&`smI2W4(F z^*Bp>o|5c)U9?w<Uxn=3GDo+Vdi=8;rXEv3WRAyBzWAoD1^gr)`&Qy{cba+}D)B$x zto&UiK9|I1+)2LTBJ-Ab6ML19>@L7@3-Y~-vZVa&<PW=@{4>|0taYY-w!uO2KbO4w z$Zucj5W3-I;v+dW{Z5oCzOdWDJ8mcXWh>bP%lQKWUs=E6tGNd4SV!>PY3gw%x2iJb zympBJBr&}<lRxKX^2^;}>hUYrQGdjTRO0qXJjQKQmc-=XGYG`Db0_)At~d2~F%swH zUFB1}m3(bQFEJhb=C?_194mcKkddm2C;I{6<r2|Nv4xK-C|YWq(oKro)urcEGc*pR z2O7bneJ&>5mzI@sOi!C$Rmyq9)Z>IY78|w|X7Jg$T%O2IBH{%+Wmn)+-#jz;%-s&y zOGw=j<lB+bU5f0OdEkPQ!;3s6R`w?@<+(|F$Of#vJERx*3TT?w$&cv<aQrRUtBXEQ z&W02^=_Y8H*Fi&G#9r|l$<(fr-0=cvtrxLB+$6gmk*!_8oV`YL(Iw#W0lL3L<28Uj zT%obNh_bFKo49`37tdjTxQu=20?}JyGhd)|m3*C9Z}d9)JV3m{X_PBAN!N)MJV*29 z8rdX@jnx&BDcmAmgglqC7+#_=5SyuskiQ%wTldSz|1tLJkZkTZU<}TX|Lr-N1LsJl z9FeX1HB&#=;YIZCCf4RvQ$J5Y&Z7{X{1nkdXOQ<MzV9~mGw)AfOgo5w6FHs8yt|0c z6Z`m=h>p5I<16y?^EBr!lKr5J`#G|=K1TlV*YVA9;C=D^y@@jAj3zm|?%UJ`ssA-o zKdb5x_NG@*{u%P=*ob?H{V%=(-=Q^ioanWyrhYENS>@aOA)cSXw_RA%*XWs?ku2wl zogmrq0Lhkwo;!^1ju0IvwB=q?k56-!=8K#Ua2&F?*YW%k`43ARq~9j{{PRR_9wd1c z$1XpM_K3f8FZ@R&?y|^-_L09rk!)?>GWBx|L}$}Ye9S45tvh7vd6eknQv_d$yVOm# zDzDRC)JAfDmvD)Tb?1^@+fCvN&zbre+j4H4;KKbx=buH{?~t!SAKBpclW)g+<kul* zPIQtz?N0E^?<1d_za?^uLo`=TlJC=Ava3Bn{u>e>OnfLV5-r~cdPmNSU5N2n4Ecw| z0hBXgpF%!4ANK{&MK53;ODqnFYbR&TK5y!=I_4qoGiLA^x+_dQZsIehexC0<Q;+v1 zw)0P$`nk4q(9UP+*<!SLv8kVTw-jY9p#DhvB#x$>hkMP`&kKGZ?T|BvpEiTf%6-bz z&jXgYf6Gvx#FLfSf)X!N;@xn*jmRf(68LVSHcNa$IZs$($~+6$2^=?4e;1m;aU~fp z3u(+N<nt~*GG)@C3J<@ZbfO2y2j>vUFD1^!Y2aHq`%U;giNX8|V7(9RmUwgHNtW-E zzTYF;=J}=`x4=`rhx5rkV4AY+jVb>rqMaqrIifROR5l-Hm2HCPNM;b7EVefbh$bzn za@c>ToxYu^=<7~;7n9D5ZM%fGzoqQZ<Xl*vZ2l%-ewIl#FoA5UeWJH~#g|k_W*!iq z5s<#eRs9SV&mc7XC&YKGR%Ko#+Uhyr%)r#+BF|T4UV%+|Ks4>I0cXEV<=)1AegSp9 zM)JTK41b-<I86ON2H&;;vX4Kf+R%%#E}^_VBt!8{J+9tmrMD8>dZ8n4kWY)qiC-lf zpsN-cw+|YO&$AE7mf~HD?Th%3yF_;f%C4LJr=>kNNGI&5_xzm$ytzU7`;R9c%v17I zsjonD#{s-N)xKEqeID6>dCK;W_1}5YTS#2U_bj}vi?!#GY%Q<s)`Wf#zlArIT~<hS zd=G8@7JOUY$McUcW)9wcjPd$_c(YGvt-g(Re1mA54~Qpv6RBY8=g@9IAKxQcrS$7M z*-x!T*<T^s8##kGkNNb9smJHbW6tJjJ>16kmuYNnVXt|X=FkP?y-4NA9KK}gXLntN zf2G)AzDImrp7_m+xL%=kdY$ye17vF?IOrhR@i@2+kWS$w`3Z?0a}Uwv{WMoDkUq|( zbccA^YlNeV7`GSc`DEgy#Aode=pB(&+#%W09kTJfM*5%E2o~Zm`Xb&5&bbVjy-a+T z++QMls;f$eC%o-<u_i?BeVJqn0*?rI?=bljT_G6vk-aJV!=0z=Ir1ZS$<C;cWbaqW zmaCuW_3r_%jZ^#WS+ecAjP+6`o9U_K?{)!w=pZ~VK5!n^<7HEi`EiHfa0BTI`3-)Z zWCRz9ufI%wYL`tt-q+hG^R^ip!y!<%{jt*1@|m9Uej@ozbSgiEi0nBdg=5(^HdZ#0 z>~j?<-<%Gz>7GWiIkxAXM!0eTQV}%wlc2Rrpz|k@|4m5x;J0!80Jv4w%4_8B`xLIX zO+CiKZSbOZ2uFx~ZXWWy40|cIEq7=yxI=X8O_Y6y>|k$$pL+>q-6Va`HRSm<wCyFx z4_>5obqD#jkd4(9l>0KuVcW@zm`9=myGHgeLW3M5T18}L5_{q@`rV6iMK^Sl@LnIu z#jaDH%VZ1Mt?ctwlHcg}Np>mmSWi<sw5;R?$*|5--C{2&@)OYmUsklmW#Ik+viEVR z4gKUV6p?+>O;e9G;*x!PKaII>>Sre1p*7-wwqB^{Ba!*sqP#4Zmsr)lvOm&i$ct~? zS81J=l&yPJ$@dH35j`b~mviM;o55%Ka?CDI+0D6%#&Xm%U)kjc790IEU5LOsZ}HI! zseYExi+*D>=%|4Fqcy%L(Rh@p|B=!q$UG@1oy2&8wcr3ggEUq&>43$5ASBrLD;V;a z1Y|!_HG|`FdBm?Vy}pp_GG)Blh!-g+n%gCw_AS)$Wh7VWbR5`Z%U)9k?8OIeA?XD? zvUzm~mf~X&kpA1DcOKT>3FXuE3fZQI!1qPkOG2XWJ_g<ClTYL_@{jOHC#CgOg%o=t z9uMa2KTxs<;k90*z5gotfGnjt=hE7LocQgKe8j(u>yxH_-rZ7+<rCnOMHV%O==0gY zH9qmep7KQ!p5Yeu&eu&nmeV!z8@fXC;2Gq3PNiqapXm+SPv!a=#_5joY4S;~BRs&X zfZtW(gKt1Kc9Hx#ZlnD|-&bgD3htVs^o_Cd{VrSlWCOK+#NX~K*e72FKO(Z162b0G zvd6oLZ*CDC=Mo(d5YO)`o_adLDTI9aP2%%~_IM3^<GZGQw%k`uJ?`5(<V*7^?!|uO zMU0i`B!%9*qx`^bD%x)bt<_hkJyMp~Xg#L<jXk3GijXP2M|}Oy@cw658$ZK5o<Yx_ zGxa#hKf~|m=(#P;QhB8ONuc!}$69&{dFGN2&-*0Pm}}~>73JBpC|~Yp0T0ZBOm8Nh z%_1LtZqF=y_c*m@HqukLm-hTj!R9%7_BhJX$usq{JKv-}%)mXj{|>cZ+LqRS&LibI zDSZ%_&LO{#v!wsKfcD&0bMSqXbqC*{q9i)Qr?A%LD*bzup3TQ|&NC0`NwjMYzMF%& zz~lH7;4lf_K1$`!qi<qUkJS-VTO@wcWQ@~f@}C&)+?5!t(^2;mc&_K}II>}l=>9o+ z#y;7cs+Kg9;H+W(6y=+z;9NEJGvp<9rNCu6?&qVQ@}6NoD<kn5ics%lntxK34K@+M zVS>8XiN|rWYI9_1%V@UuiInlsaDPhOR~781rCcTbEF+ajHX!%%&V?+~$2E_uJpVYQ z%#SR|!+zjW8Q%nsa#7YtwD(`5{rFvyb-oXLa#iURt^>~1jH|>{jx(+?`6IWJ?>JwF zv$kfdG*P8?l{jxT<r@v}DM<3&6xuhYSny0UxM(i$!n_n5B<<z((@uL%JFfF+Uzvq` zvr_h&ISMc6I-f&-ZqRkE>h}$N%fIJa)^Aoj&S$h^j;Y6ymw12On19zn_g*JE9LXoP z+4BgO>OGD3FaF)^J~kOV#Voad&7pm2wq^gCO?%etCikx|r|e&Iu|8%0ve8~sh<A%D z_l?%qJlgxK>iIl+&ucKEEB9US^|LfDBJ^iI&3}#WA5Fpgb7}vcMfKWX5M^Am_9?wb zJ>FoC(rukPjJD3Pz&$HPDQSvIKeOOINpH~g4YKtU+x)LW_S%m1_I2<+7s(c1>?G$| z)*Sakbo_FisqW*H`Krfirusf@KWNmRDwP*men%siJ33W|k<!X&SL3P2P+}XlV|?`W z>)=se#y&4H@{f@|LArr_ui*M3(M?ZK(({YYPnbYs!r$7iRr1Yh2F6uI8&oZ{!u=kL zDGkP=9kf$BbSfXx?{`V=E^!h>=J1Zi&NprD@*JK8SkJQTHS+8^!mEtK7SJ9uyUG1# z`Y`qz+rAU3eI{zKezVpx<CTc641*a8htE*F(Sj!NxNXmwJw|)ZEE=!TZtI*;UK2Ll z)DAwQ9Xv)A>)};Xk2lYH>i3BU=_h@+=*s7-G(#o5Ms@y~Dox2qY5jSNp1rN;p?OWT zN#}3WrpegHC(%`Ycfg*YJ>~k{6yEW>mefxB{fCz8*GV?X=~wWcuXijdP3FNo_axv1 z+m-P}Nc!<I*-O~y+AKU{Ym1fvNZo1INY$Tq9nC!|Yfb(fWBhaa9a(gQdFYWGTsggO z>Tz?cG?!V9C3df|<ytm_<12+~EchBV$>Z~ys;H#DpJ9f^ztw%r(^cYAPEs_@Br`ZB zd2Hzm?`yu&efgI0X;!8&k=FVoGdK<;+sTRUL*pwx4<}UjPpPDF&UlrElebJd#|r67 zS;y_u^-)R{eBWUP$FY%h{-`BY)i<%S!|~Nv<W=(McN_36<6|9j*d-eP&w{^wrGsR> zKF8FJl&>B8XnCZ2c+b?&X1;)Q33j#L0L~Tp-wl$BNSaCOR&)_n8Yj`svAwbFn~IvB z+MbHv#b)sNUu>h{tG+s*N9HP-_gu@qFjegf(`cMK%-}eO9mFFHm;Rh<Y11Us&)11` zovXf;e3F{sADFI?YkvyOz;s|E8lw?S!slMZ%1+B6-IxA-QNe1i!UdC{E8sNT{8h`` z(&<B7Kf?8!SQ{5<&4`V;mYKgqwpe1bsrgl*(Pz@L`AWZ_bz)C8Axo4sHW}YPj(eM4 zYy$Dv%ri^?O)v7q2}-s&5?-&7Y*AwAicN4u(PG2d=bo_08u<MLrDM{4XSw18i(GM* z;)}ENNzL+jy5F|`4_B_Zpg~*b-)9~#i>|D~7GC1ae@u1>5>Ilwsh>S`$kfkPSp*y- zakRweW()F_;hR!2_1F*_l&za@>Ssm<WNRqrQHoERk9sb^x2p@^bXn|v``|aVh3pJD z&g%jA(H$ULvBj`wUj|)+&@VI5FNp`c0d49;84@E};3?;xN(@tnY!xNW@G9Ith4$`M z{!bE%WFPt}aU9xBJ$9FedN$FXeVFW7*&cBv+JDg0<H3pTLkaS$vZ==|iYzuhVy_mH z@1?}M@W>ZH?A6XG8y*k+5Wl7~<gZ(6V_WV{u9VB=OzulbO1{ZGe7TZrzkeDh-+F(V zJb5+uqug)iemD2y+)s1=dF~(P{_EU7&i#wrzs~(-?tjhwyWC&r{(bKM&Habm-xy<x zrfepf$IKk_tXX7Mn=NLW*<<=lzxfOEkIg?Z|IGaVY}xfw+X=Wfe5iNp?k%OIwsopo zcikv)BgBXhBZMd<AwUu!gg}Ugx=X%F-QB5eyQS{F-K}?9-g7dYo#)KF_b>M~b6x+z z=X&yu<Uf-eo1JWSw%Pe+mzv#bcDwoN=9`-zZhpE&atmw=d`jn(o+*7&2BZv58J;pe zB|T+w%8V3EN@0pUW!vE9gIf-6JGk56o`X{d4;%dJ;EciS!P3F{!NI|o2VYH1N^PFn zCbeB^r_?T~JyQForlbx@O-mh}IyQA`>a5hIsVh?nsoYdisx(!RT9jIv>Pro#u1`HU zr0Y;*=<~D{X_~akG+)~4w9RQyT7BC7w8Lqq($1zeq&-f1JFL~PPQ&^S8#rw4u=&Hd z!vw=5!*Yfx#y20|Yy6<`Bga>dkB$F0{>Oxo6WkN~PaHXM;>76_jS~weZc1;S-XXnv zdhhfh>BG~1O`noJBYk=L@9Fq-N_s)MJ^f7jmGtZBH_~rok}=IOT`+?%shAO%v6xAi zDVRB!1(-#cWf&ZWhRMPRF=C7qlY>!VaxwWB3#J6)!$dG^Fq<(uFmVioK{0zVXE7Hs z4VXVMcQN-dk1=mBpD^FCEwSyeJ+LX*RP1o<80>iLB<vLI9PB*o0_-xZ04u`Euu5zh zwgT(L2Cy;gYV2C<PAr72$L_@*$DYKV#WrBCV((+0U|(S0V&7puW542(aLsV7acyy( zaQ$%;aOt?IxS6=wxCJ;oj)<e+1UMy5hcn_VxFTFJ&Vh5|ytrCi47V1y9=92{3%3_{ z5O)N37IzWXfV+Xag}Z~hhkJp0hx>^8g8PPVkME7|i|>z5#Sg=e!jHvI#?Qjf!(;FS zJO$6e3-EHh3a`hT@ix2*Ux5$eWB670HTVtqZTNcpZu|lKA$$Y=D*guk4*ov=5&kLu zHU1s`AN)r`3qnW2K*C@`8sS&MSVB5s24NOqAz=xDKp+!11OY)r$Rp?oW`dniL8u`F z3F`<O2s;S~VK-qP;V9ua;UwWS;Vj`i;S%8r;U?i0;U3`;;VI!c;U(b%;a_4iVmo42 zVlQG};sD}M;xOVU;soL(;ymJVB9=%c(uqtWpC~5Eh<QXav5;sZmJln6A>u0HX5tQF zoCp(9;%?$z;z8n3;ss&@@hb5q@fPtm@d@!C;`fZ?j20Q)GWui;&X}GtJ7Yn{iVRu? zGb1}gmZ8hAW!N(u8QzTAjA#a&u`A<r#-AAvGG1o9$@nMZbH?|KCQ>q~J*g|HJE<3` zKPiPYlr)?)iZq=xlQfUCm_#H|NF0)gBq7O3I+C4KN%E0Gq&m_L5=5#e?I!Id9U@&P z-6q{7y&}CO{X_ah`bus_Zb5EEZcFY=?oA#<9!efg9z~u)o<W{ZUQAw2#*lI33^J3< zCTEg`WDVIwE+xCj9<q-dB1g%q$ZN@)$UDjP<OAfR<P+oz<OcFp@(uDW@?-K-@=Nj? z@(1!K@>fa=N(V|ON_R?6N^eSkN(yBNWfWyRWfEluWj19#Wf5fwg+QTDvM54|l#)*| zQ!JDcijz`KsigQQVai6z4oaMYQua{xQ;t$jQO;2=QLa<|q}--FraYxQr+lY2qjscr zq4uEmp$?=DrlwIxQD;zRQRh(?Qn6GLl|f}w1ynILhpMJ(sYTQ>Y7I3+T}@p}-9X(; z-A3I>g{TLqN2q70=cpH{cd3u5&#AAd@2Q`tO|%xY*0j#FuC)HN6j~}RjW(P%jy91t ziS`?9CT%utK5Y?g1r1N5(pWSeO+b^=G&DWUL37bOv}#(A7N*5$+h{v!DD434FzqPq zD(w#KKJ5wZ4LzCu3%xzP6TJ()8@)e0g+7FyMjuHZN1slgNuNz$NMBC>olc}v>6!E_ zx`-~J=g^gO9o<YXq}%D`bPwG}_tWd>Yv>#4Tj<;9N9f1s=joT|m+24bPv~#x@95v? z-|0<^=8Tq%wv6_S&W!GiUW|T>fs7H1QH=47iHu2%X^gpy1&l?Er3?%M&tNe)3?W0t zkTY@_c?=!H%&;<w8BRteqnfdav4at3pp4y&lZ*?DtBjkBTZ~tXe;6Mb|1z4GJ(+!( zDa=%68gm456mtx70&@~`J`>L*GigjVQ^Hg*RZI<2%QP_ynKot#vw|6A0!)axi+PxN zj(LfBm3fPKpZSFOg87d5jrpC`oYk7uiPe?WkCnn2$r{W0jkSQah_!^Zl7(RrStJ&X z#b)tX0+yJS!&0y`tbCS%Wn<Y{6)X?S$MUm6tTn7HERcn;_OSM|4zZ51PO?t3&a<ww zZm@2#9<rXZUa~&0KC!;AzOkCvt=MhY?b%(}1K1<kzp^K=C$Xoo7qOSHv1}5X#^$q? zY&*MxUB&jZBkWb|P3#@)-RuMGbL@xg7wlK;_w3K?e>p8V9XP!?{Wt?Sqc{^dzj0=A zW^?9o7IRi|XdD(NizDLXa8w)(N6#teRC9uy2xm2C17|0vp0k^Cm~(=2nsc6WnRAnK zhjX9vnDdPDlJk!9f%BR3Ewfc-ugrm&shQ(4CudI0oSC^K^Y=_#CMlDVnVG4~%*`}s zS~K05o=k71KQo%SDsx@t_RPbX7c(0&uVp^Ue4hC)H<{at+m73l+nYOpJD59^JCZw^ zJDxj{JBd4$JD-c?lDP~nhnvlnar3zbZUMK5Tgr8FYq+)CFgMDr<F4VZ<L=__;qK!e z<R0ao=U(Ps<zDCB;NIiD<i6qlot2!`BCB84@T^H$)3Rn{Ey%)Tk+PUs>?}=IewIDU zl~tZqnH9*2WUa~CkOgF+S-Z0iW*y18nsqztVb*hAb6#6s7hX?ZKVBMd3~wB75^o9* z&!h90JPwb?6Y#`5DNoJQ@yxtpo{Q(@)$oG6^*n^Pi+6x`h<Ay1g?FF#nD>(RmG_<B zjNgjincth=pFe^>o<EiU8-FQ(1s}uD;M4eAzL>A%8~J8_A-|Yk&adW&_^bFE_?!7V z_z)lAALpOspXFcTU*=!s-{RllKj**Zzvq7zBnw&#+6p=g`UnOHh6%<ArVC~W<_P8q z76=v#mJ6@~ynrTP3$g_{0;RwtC>A&c<pQ_BF9-_O2-XYY0!Xl1uwQUca6)iNa7FNk z;FjQ_;JM(F;JYwM*hAPym?|70{8czbI8!)BxJbA}xKfA}QiL2~mQW_t2u;EQp<U<} zRtbZ`sBn#Ns}K<$79JCx6J8Wv7G4+L5#AF%5<U?=7rqhxB}x{x6txp|7WEeO6AclK z5RDT}5G@cb6X8Wf5k*872}Kf7j;K&%6_tvdBA+NES}WQrii`G&4v0>Ou8Qu7o{Bza zx6E#z-6^|!cJJ)I*{RvXvVYAUmpwUqcJ|_IQZ_A{l`YPeW-GGQ+4}6F?9%Lt?3!$U zb~JlkHk!RBdtdgU>?7GXvj5D!pZzHNRrYsrvbc@7hq#xxzj%arlz5DIym-2JmUzB+ zk$9yTE9QxXVwJc+Y!|!4ZgG`3B94hyi|fU^#RtX5#3#j<#8<^P#ka)w#1F*J#Bap! z#a|@NBpoE3Bz+|PBts;>N+wFCNajfvN|s4hNXQa~BugTd<VX~fT!~hqmzX40NwK6< z;*_{0en~{KL9$Z<OZH0kOO8rTO3q6fBv&L4B#$M}B(EgzB>zZ0O8%85Nn1+WOS?(? zO4Fnxq+_Jxq?4p`qzj}NDPBsJ(xgnONGg%$NEK3zR4+A2?b1qVSh`WVRa!6IFTEta zC4D4)CVeISOZt!WgY=86t*nEri>#k)fNZpEylk3mhHQasi3}$r$Vf7ZEK4Sp<;XNL zt;{GZka=XavZ$<1wo$f22Fp&$&dAQo{*c{~J(N9`{UiI4lbq8cr)y5XoRpl@oV1*! zIV*CoIT<<h9A=IrN10>EapwecR_CnC*_N|22g%u$b13J0&Xb()@+5h4c}samc^7#v z`2hJy`4ss)`4agGIYv&FQ{`g0RIZR~<OaD#UL-G(JLMjEjXWsdDBmiF<@NF#@;~Jd z<WJ<!<!|MG%fBd^D}GUQQuI*tRrFU3SEMUuD&{E`D3&NzC`bybg0B!MlnRYPr?4rU z3b(?qh$vzTRIx{KOmR_hS#eEqL-9!QT=7ZquQFNLTG>h2MLASCS~*!cQ@L2VT)9$7 zP*Rl)rBIopR4KJeozkGRC`*(srCV963@M|^I^}BRI^||1phT1hlt-1PlxLL}l~<Jy zl#i6pm9LfWl<$?_RY|I5surqNs?MtZsv)Xjsu8M*swt}9R5MjeR2UUbMOM*O5|vCP zS1DDwDxJ!xGOKJVm&&8^s(h+7s`aWZs%<Jrg{bzZ&Z;h{E~^?<4^+=oZ&ZJ)KB&H^ zo2y%^e^GZ(cUE^-_frp24^fX&k5Nxl&sQ&0|E|WWiE6T%q2{SYYKdB=R;q34YIQ&z zR&P;*>OJZc>I>@2>Z|HT^&|BY_50l9+~&D$a@*&2%I%ihCwEZp@Z6cXb8{EvF3%<8 zGIDvj%G}&sU2a*fJ2#LU&W+}-$=#eA&pniTH1}%mo!oo5FLU4I{+;_(ldS2W>8$Cd z>8a_b8K4=anWCAd`AsuZvrw~GvqD4AkTetxQ<JF?Xe63kO}<92Dbkc_+!~L@tMO?9 znvf=<S*zKq*{%UKdo@QjCp2d@7d4kP&o!?!e``K#zU8&dYm+x9Z%E#-y!5=ud2{oy zdHB4HJXT(2o+vLTPnl=Pv*g+HO7qI|ym_I#Xx{p~jd|Ph(7fY$m-BArJ<5BT_gb5* zZLV#p?V#<V{Z%_gJ6StTJ6F3vyG)DG;<OoBx|XRGXw_P+)~+qnR%>guG3`3-2JKcY zs717UwFk8)v}d$ewKuePwfD78wJ)?EwEt><<R|C1%<qujEx$*8zx<T^k@;it$K}t? zpO?QRpO8<^XXf+r75V!7;(TX*WxhAxm+#MCo4-DPdwzZX{``aaNAi#5pUgj#e<}Z3 zeq;Wf{CoKi^B?Cw&;Li)T-Qq1R@YnCS2sX6L^oMCQ#V()K(|P@T!+&UbQB$1m#NFr z33O_mMwhQM>8!d^ol{q-tI|bu>vh|8h;E<mfbOvFgswq%O?ON8Q1@8(LibwtR`)^o zN!O%rrf;clt#7MuukWbuuJ5JqqaUartRJJFpr5RtuV1OB=mmPIK1Z+AYxD-aS#Q%9 z>mB+seLx@8uhFm5Z_@A3!}`7Y!}_E86Z*6Ii~7s@>-rn|`}#-vr~1G2pY`AL-wjEI zR)#i)j)oqF{)QC85W_IT2*a<2bi-7`bi-W3LId8AVW1kA2A)A|kQ-D6qrqyZFa!;& z3~LP=47&__42KQJ4W|re4d)FP4Oa|*8lD<n8vZhTGkiC;GPX1JF!nPJG^QAb8AlkW z7-t%18|NAc#tb9bNHsEyEThOMHp-1gV}a3Pv>6>nuW^lWopHNyrx7qB#@)sP#>2*A z#*@Z##*4;l#+Sx7#`nfArsk&BrtYR*raq=2rZJ}RrgYPE(>&7x(<0My)9)snDZ|7x zWtv1LnMq;FGZmXEOkPvKRA*Xm+GN^l+G#>eM@+{}r%V@2mrXZK_e>8=&rB~&uS|cN z-kUy~zL|cQQ_UmIqs{5&Ddwf-m1eS;YG#@_W}aDU&Nb(o&1S2)#OyRznrqCp=C$UH zX3&h7kC;!I&zUcpFPrb1ADLg6Uzy*VKbgN3Bp0+S=v6SR;MaoR3+M&B0%<``fwG{e zAX2cs04ms1aIN5B!OMcrg>4Hv6%HtzQutfpoWezgOAGOZq(W*TuTWlCSXfl(F7y`G z7H%$t3Xc|^EWBKJt?))+W8uTXCxsshzgUtjtu1XWT`heq{Vl1MQI;{536|-W8J0Pg z1(v0j-z@}7hJ|dQTId#zCCkFMNGvjo-eR$oTFNaROSPre61A+i?6iOu#Inn>$8yHf zV7X(tZ+UI`X!&7nX8pz5)7sBE$eLyyZXIbIV@<bCvHoVAZCz+xY9(2j)-0>YDz-|k z8mq-xWUa7PTC1$pR-bj1b)9vab%zzPp0S>{Ua?-Y-m*TlzOcTrzPJ8sYi8?c>uT$5 z8)8ed&9%+9EwU}KEwin#5p5hB-zKyfY!+Lw&0#CE)z|>raoZ`|McYkVqwT)!neDah zlkJ=BM^W3NPDNdc`WFo>N+}vsG_Gi7QAQEDh+4!fQWWWm3X7~oMMa*XRYhBi_7v?e zI#+bDsG;a)(c_|5MNRf(dkcGOdpCP;`v7~2eT;pUeXf0(9b+fhGwc*Q&n~vB>;`** z-DbDjo%SkwjeU)MogK8pcGSM#e#Cy#e%1bm{kHv{{h|Gp{k{EDaZ+)!;!eeViw74^ zD4twAuXsf<rWjw$C}tPSi`B)Z;)3F;;&sK_ih<%i#ixtU7GEj8R{Ur2-Qp+3uZ#aK z{#Megq;*OAk}f6PO8S=!FBw%brDSHw+>!+)OH0Tl%o0wCphQ)oDakLfm6VpaOR7pj zC9#tACEH4Xl7^D2C3j06l{_i=R`R2?V`;b29;N+D2bPX19a}oNbXw`m(gmf<N|mLB zrNyPr(z4Qu(wfphX<g~M(oLoD(nF=^O0SmQEPYn`w)B1Jr_z5N%^h7Fy&QcU1016r z>5l1+#g3&8jDzA}IM@z>L+!|S=pDrlr^D^2c0?R?jx~;Tj!ljo4$!g3al&!QaoKU# z@!0Xq@yhYT+05D6+1}aFImkK0Ioyn$^IxUi*T<V_s>$6MlP23W*_dqGb+T<tw(UCE zwr$(C>r~JA{s+&m=XD+Jy{^6RUh8vlPI9id&a|$yPQ11!oE&fm%LXg$Pq?OM22cGi z>DM@_a8l)loZ>p>Iu<*|JeH+6sBpcqC$P_U)OF=^?Q-dI^>O(;mvm^fYqbB^v%Ee# zI=ehO#y!B@lXOIMjdF;xm$8#^ka3=LnslUdp>w8l{ZE?}tAEhtR$C}#h0OJ^UAjsL zeAf1<oB~}I+k~o80gZqJKs(LVcb(Gn*z<<-j`RF;|MR%>wDY3#`t$8NQxoek=;SC$ zJRSBt+D<FW)r-1U6Pj^#lQff#x{JC@X6Llx33XE{8Y;)cq?Fci9+O6sygG^1r8>9O z>^d|PtnuuWW-3B?zD6(E*8m4?&Z11+De7Zz)B!*4IOaG$dDwIp@1WLN&7({}qo+r} zz_05A1WCUR-q9Q`k9|@4s($8!WM13vkPrE(<EhhC8p==PXIsJcn-lJX5lC%^aRBE6 z)h(o*SIwxJN>hO`h|!4A8!j<;7T$<)PQ$KpQL&;_TfL`0SQZ`<PJ<Cct*hc?N73qQ z?`nta8sj2oCuje4lzpvxFw{b26Q{K|Wlyt-+q_iin6VLTlfiwUdkId%j-WR^H()kG zH^et6Hn29;HaRwsH>WqNH*7brsWa4EDx}MP>2d-coDN&YPLo)uk5%c*57feG;AzIG z%c)6{oRa`F9BMX|KWKKx-o^rx#Hr=fvMW2}UkmR{4)wBCvvsrcvUjuXv%|8fvQM)) zvtP4Cv&phC2+~6@cin#w)QX=ec#QF2WK+jXqdf%i0(dicw0PEeO3kW|bB}9|TaFWt zD@uCr*Y5Lx)++75Diz`KV&%!wbhY5}eAU_VA1d+G8cBJ;24Ft0ZA`DR%TftLv9aV# zU~v{00&G{Y1#YQ$m%UwCUw#a(FRqWTFRyQN&v0*W&v7qtkG^NPR=L)4^h@0`cUV=A zWbCVWvgt-NkDTAMb*gNYx`sAywXe5Ndk%U|dd_=pzmL54y~jLnpP4Sw0ku?`E3dRS z>)Z4mTh6E!S<21S7%Iq>S;|)zH!KAkOEnegs#R5v)iQwaK)OZI#j3M0OIzobwki)P zHbou1&h|I?$J#TcMKd6S+LwlR^P9$F`56b>Up6{R&E<!RQ!SPj@=8;u$(8hnbayry zz(2M^TuH=&5S;{#{_41;6U%T*9=0xA-^s9ac(xRP%@R-5>)H7+-T~fG#!1F$#<kX- z*3~#zCH$9OG{bVrHOo6~*KfV3>LsiPQLl6F3~z3)-0CgY5!VIRE!R!g{^b+T3(wPc zg>_&Pz`A;^t5Fyrz7P$}Qsgdov7zfqR+g$fTsT@dvqWr!YD`|M)6}!BVOMRha*?`h z(rj^Yy&PN%ZHxivEqyAzPi{|aPi;?b&u<Us>=9neJ<B~!-%Q^!JTTl>-+WySzlHhK z<(!(m*Mo$*H>z(_UhqGeyO;I$kzb8I5kF-<vwT+cuD36@&-qXIFZeIJ54umg&%3XE zPkhgO_rHd}X20lW$Zw=_wQ^nc_4V!a&Gn7-rS-k^4fP%LJ@i%eb@lE2&_@t{e$V$~ z-GNj70sPM9FQ6}@FQsn=0hjBq<8S1j;6Ly0=nwBt;}7s3>e=k+@7eDe?^*BJ_J8(| z@vrtL>@C#4*B{?u=tb(?>h%GGfd+jKJBOR*oy?tpo&23TB610M=D<uMjuCjcfHQrc z85CBSN<r}&TJ`@BppAMLdmDRY1W8-?-MHLX+_>F1UjDqWzWjb6e{sF>uAy3>U!YoG zVP#B2m4uH%ltK8w)cmDM&=*WeEJn$ah@lv4MJ!&*ql^z1v=qu7+!WFj>WA`c4T}qv z3x|uaji3$35@8dO7l9YC6R{K78}8#LMW|NrdQf}tdx%n>#jalee&6Zt=x*6=+AgPo zRVoU3D2{<mD&Z8;c;A_wPYaP1ELJf7?pY20FQjT%+n=^@wusjVkOr(B+#MVp{9b>& zXuZh2m_Xt!OkNZqS`anJ^+ou_@x_yrYL01+bB<(=hM9=@Pdp|LP8xa|ZW@*bcCU!t ze?mb7qmehiSO0St!C(@Rj_dnJxA!kmbmKqU0jw|)cJU@L7ZDfHCvjOZdQls(D=`9* zY%yJNKG81mgna7){DQ0kodVu`@BEK^s#)S$gIU<whm(er$dkR3xsx$-u|&K>ag*7O zQYOpjwfsW`xdpt+u&M}~n5)RE2!hD$aNV%2D84Yhm`{ukOaMLr4}f)!a{k{r#yJ)q zDjp^t8XlHZ%m-!$nifv~&<&GfB(BlW3X=~lMREAy(4Aq3y21qh{UE5;+{)R?$V$pe zoR)waog0%Izn!2R%M-;D=bh%MjJ~x>N9VZB#`)tMdZ}npraD7`qus^;KQCI90+_H^ zb{^@R+!oGdn^jG(*$lLi*=*xq^1;71>Wc~H|H)6uAH-iMb5Yz@Od%ul_sf&&Z+ZL@ znYHv<d;>46%vuU#2Y>t(Deqs8<Ok~0>cZ{>z7N8FykrpIF6h8w)G<DV>?>PZ0`v0= zck480chlUZ-CgCrank=tT#K~%B$KhjhN@HPt)#H9uqaY4?ImYd<11ztQ5KuPp3%te zNdHiOTCN|Ey!Q6R)bS0rA1@osvlP!Jazawl#^jO;$CRwg$iQzfLF!CQP7IN%FLs|- zEvl4(oS$j%wg{b*EzFW>k9{J#ysSy?=lV2rOY3**7wI?dN8e8vYW~Hq58AoC9||3= zCit=z8iz$ACzp{<`(v>85S9jJS5@E^7sdI|57rJ7e#Gfio4>AwIda{}J|rKQ<goL< z=5gl{S+H5qS>RX*SfE%CSqSTY*8iygF5JWT#lk~Ij#V&-u5X16L+%%5uw>9=xQC4r zsPAHgWH@Dn%c#Z}mHM6<nrfEX&A81dv%<cDw4w{9RPq;;7k@59z?7;XXqRrNY9PGE zu;N!nL}ibvA)to%f*Q=IJZS%k*0k5c)c&t%dt9qlvs{Z@J6%&<b6xYL-)-o-lfJ9D zx3;&o+qMI}H)o$<KW|@e?`R)kC-MtceAr}v;Sc0gWc_ZqeNhXuHbxaRR!?Pb<*@aD zb^m4W<uLvbet*_5+fLQa=fLLBW<T#hXWvKQd*pk_d-OGU!vtUQUchr#FSjpcFPtw> zZol{-<@z0Oe|MnfL~!iUy%>6NcA*l=VsCMQ$U(ATK&1;J1~GwDK+YgK5HE-Xga&d1 zX@U4(kYA>QRD-61(EH^3?E0|#-1?0BX#0Nk8TK&?LHo<@po;upBF@n#LPwQ^B@m(` zmR=E95rO#G4(kaE^BJ?NL#|D-@q2@uhluAd_Lf#3MIW-Elp%~EvLT_N?_O@uZWM7b zS_vu^iW=%IY`+m&un3ic?1UV4cGd~0N7#RRxO?ni8U?nA(6AEJ5LaFUH`lP~e}v5O z;76i2jGe^IG8jn=MMk#bL@+brL?XzBkP62cjMSJV8n-Z8GJnS@XP$}V#W`liWg#%> zm~u<GrP>Gd-J~aQ#kVDR#J|NWN|Y5E6e<+X7UC4H7D5#kk)nqE-HRtB#i5EZCQXV3 zN_<lcYDh<?AcpN<m*Wy@``aefCg&mbmhs^K5d2`<ce56|p3olu9v2!Lnjju8o=_5J z7Kas=60a6-Z~Qwgp0R`0fn7t2o~V7~@W8Sz=NEDH?`q;|3R~j918=Zk)c%1Im^@+J z5gzc5Hjm1UGK^G@`o{6cb;ouqX)16jw2>oJGnf#OB{4@br^m~tNv6r9WiWP_pu+`= z?JCt#aiWtH#Tpj;p)^U93{TlB5uwVUvWJsc6<rnQl;9NPlxh`dm2MTZDBO_2-lDNY z1$$YRM(#%BMnbk=t{|>Vu5_*luF$sFw#4uf#Zp@8lysRSMGR#`6*;=%wlW{fptj_; z?6$DBq_#jfc~=Ewr5L4Y1qOM%Qsh#(GKMnSQo=Gl^GWkcb88D7i%p9_^RkA#hTVp^ z2H1wb4P~(X8B$sjT0;FZ|5&-`63BDI%q7#4O$%GiF<2QYlQD}$Ey~Tg%^|EgE>Xa| z=?}OLLvTraiF1kH`RW_89LRT5vKy5rCxN}C{bu+k$rUY|KYyy>#HS;jGMnUtxGBI; zh&8L@#IY&$JTLsf_Tc<5`C$Ek|6ufh2HW2*=_~Ck<}3b1Vc<3jrb|naE|Id4Hj&wp ze39QG(T6C9PJ(u23?`(pw@`=RprZwi?XWcvn1rX~neVV)5g-d<6$Ze|%G7~CXar9( z<%ivl{f<+DlY+gB(~RAWV~b6QorA-lIy$j6@j0P<B!6UgM0sR><Yvm{NbN|RFjB~j zGa+3ZS!Q^|+$hak?`L6>%!ofBX^M|#_<MqP!e|11VtnF!f_p-I!fZlq;(6kFf?SnG zm0J}{)pZF%l^TEm-~pKS-6YpC(*BAV$gjh$piTB8GyJOommFSXa;ia|oTbutSJOeu zPcsr;!(P`^tFOunAOw4-pXYzhS<h+D4f}3v>IuM1X$!>KaeZOzg7?I55q)uWA$Xy; zYP52CL3M$1L3VLy^*f`_v?kb!tvyI*w8|7_mFWrh3DYIh+s`}I+y5i=Bm5)eBMzLn z2F|C?hs~$3__6$B2}#Ii>}bt|$}IYY5Zb%z@bZgEym$1_oKq}1bbmjHlWEFhiX3TV zb#ir_a}1ow4Y!W8j#(UR?DHJ(9Cqw<9D({@2VTcsvsc;c<xC}yW+q_Mlvqm4rbe}s z!^TOC6<IXWG}6u{Iwtxi@`H94jYF8vnU{@iMmEyiS?h`KC6A&eDAE{MeC;wE*X_9N zJRRR1VC+NfLhXGIqrujWeuZ!)M4v5nSl6Om6-0A<)=FL#48}+fyc?P}L<Vl<t>-Ox zXd$kCo~fRho~I?do4b4mT}PjT-Z_gr<tj^l6>%C$bw1<iNsWKtQ$!~X%}h)!>K`=7 zG!8YcDu5O8s<Z%|rD9r2fZEbl1&PLRU6tA9q(|ms{Brto^m5d4D2E?MCPy?!97ixm zR7$VW-3kxATo2l9VaG3Bg6STbgQUALceV~q-PGndwdwVK?g8$;_KEf(&k@ft&&l^G zz+Uq~^P%hEGq@5SvsZFoa&LB<a_@V*|Dwzn$gm^zdKR?1`cedv?1~}Wt=_dgvOOGr z{n?%E8}FO$%V*%W{ObDh{KD{R`%3t#2Q>+04Rr~n1NHHPDj+T(EC44!1GZm_RGnI# zst5kx_Yfi}qW>s=SPJ^*D$A4G!Se*<649zttWZKgmFidT<nGk$RP5C4wCxn{H0{*x zB<+;v{#}t?5ns{!qx@2C7irgK*JPJ%7iO1+LNfqwAygI1kO<!h=0>9GzaM@Af)ot0 z>;mmVYjoYD-S)t1jRIyy=wN1q)`k8_2GUy4UJzRlTu@n%V-;YPW|d?WOr+N&)g=BM zF7Z44AJrJ<s0dt~iZZD~_?U=~f=GjIgU$~yGeQcJ4YT=2@Gm=}%d~mwDs_{r-OOeC z;&atvm85RiSZ*XcotMMY0?drkCP$M^kB!Ug*j9%w_N>fYOkAv8{<PD33O`-tgt*ea zPhSjOgs#ffZU0Lcpd080kDI*zgCRq(&2-Cm3vr8f%X2HkCK-x=+Ox8+TKP@?pV~j( zJxhD(4#^JH4y_I~FLf^=FHJ8|FJUh!FD;M&NCG4T_N)pZnK_}kzjLB<a?Aqp<Tx~G zq-o?Dlp3@e#IHI+Nj0RPpxrW3%`jQRcyx(y)DSiLTM41~RO5sn@wxFI@%{1p@%8Z$ z@ig%n@#66%@mTR3u>J3}GV$yQO>r*qPl-seNGZ|D(FwA#vT;)h^znOzB2+SCv2{gz z;Lk16EK|@VqKi}gYcxkUcR9y97dSUQ$2~_ehc(wc*Ih(dm{YiId}*9zylD(+9B6E0 zf@Z>ETyGp<GH(1sBP8;7!RSlfuQZ|Jq*G(lG|{6ZC}Zck#k$G57KEg%<g5gp#LdLb z1m0xcB=3>GV;0%-T;RLcFK8EWS|j`36NxW0y??^sc*KE~v+0+d>>o4hsgO*3PJLPL zsq9P=PAtc4aMZSRH+5%o$9E@qr*}9HZo?Qq=pMgy0A|vsj2${8Y11&ot{)6Kgm!3O zB`uHjgZne^9hAGYK1(_jJ|#Y-KNUY^KXpH4W))`zXGLeVX7!llnG~5cn6zpIY9(rg zZrcO$b7_L$YK1Cis1e}W^QCveaR~Jw{UF~UtY{#(#1^tAH;6VUHK;a-YyxkhWrAhm zddPVA=TQ03>QM1el1%ll;#?A~Nt0sU0x80DVFOi`WOJP)j=b0>OGl-oghn+_Ax{-g z0Z+A+{AZq5p;x|FnO8YT{8eG~Vg6<f*j5G&oKq%IHuA;Y;#p({vmki|6>w-=qI#+f zoupx+u&R<oT@4gFRI607R<>5UR3--M0KLK4{W!23*bWp2ssX!|uT^qXwioCYyGz&0 zxy#$j-b-Ohl@|LK3KsVl6BgkYBNo-!1Z7l}7HJ#h=~TxT92zyP)!r9~os~Of5X+y- z|L3Z!fz{>Lr8%WJW&B6%)7Dw<QZ~aI^sT%O?}tcJ_-WkSu0B_F8%eE++NxDVYFQa6 zfDz|oRWgKXdRLvRC2huMiL2X<^VVkv!lSM!@054GXFVB5nUbL0$3=vhLUS>&hv7^g zOg~KDX2Zb^4=FYP)Up1Si6)mTSWaaf<VUO)+n2-Em9E#V*Qr+uG=Bm_1Exq3u7O8M zM^Q(eM;S++y5}7(?t%AncVY)JQyJ;ajL13S69tF%cXf9I?%_Pn*__kKYVpStj>n4! zqW5Qa>_^t4>v7FA*T!3m9qaCLce=-&GT6F!))e4)0vjAnuwL4(y{-+eC23|R=aK=^ zG@DclC+E)^$TXXmN)X8rY$IISF_)GA&wv<nIg4pPHQ;MuYng9>Z@FvEM-p529<=nD zb?<rbJW3dwlg`)y`|5a)b-*w^JyLR5e-HKg=B4Cg;iKWB(svW^dVbGwG<@&+W#(3L zKYge-`bA>khI|JmJd?g@Ukb~LV8WxjthTJjA(2v?0nEr^>>z7P;tGf^G$KccsUDZb z&em1SrJ3V&K5V1bX{0Y+FI_KN2VYgtrqov6meID}Hr!Uyrq<Tn*6p0*r1voThWUk~ zYvwKIP3X=4q5pyM@#ll|gY`p*S5<B~;(^m67%acAobeFs(Y}@EdP?&^{6YP}^#T2X z>8%}e_Iw_57IQ9lI(?4!u>8RB5cL-NM)7w17V}mO+Yc}`H+mVIS)CbYoQZv#zZt?U z#xBM)#XbV3yUYm2kefYB{}2=d=W>}+5k*5Jg$HVeYPM=dYliK5>=x|i?8pt=5JLbV zV*T*_fPV3QSK)-(sM><sW_v%T!Bop%2ER-)lNmdL`4MAmjB!|^3=1YoS<}%%%sAR2 z*@m2l5MlcRqaMNdMi`85(1zxR;D@015%&T6dP6Zow#CWCO~u(@eDhfh&c0;WCc)7m z>bxY{k_c;@%r9_95BsQ$Wx~_}qq{U)ag9ZzMS(?xMLR6xB|APx7Hbxh4zms$TRK5% zHaWs|)M@8w!D;zvJLf3R2B_S<!oAKt-MtmZs5l+Rv?&dMneI5@Zra&8qiyVxIzFj# zr0F=*(c7_#ka0daJW(=<HGy~pI0`+YI8r;}IEp!9fEtCGgkM8{pu^T+EQV0)p+&(w zK&OOTfFgr(hT?{g4fufaMdzV+)46G^(J@Hr6AYe*GsBo-&{k~eU@VALlwd$dr-rW# z9t>6qW(&^ivksQnz3rP1R)hbd>`-wlxv}4^?~@DOrkw<1n@ieFx(`}NI$^p3x_!F; zVH=I)*W|(EL(B``kl_Y9I<JV4-}RKVrV*2S4a%Awm^oznW%X7~5SS~9wyQ>~W}IfN zmaS&)=I(%3E19~c2A7(rCZrl9a9UWsWWPkUWU-{N1hq7{bf}u1WPM11z%UGKT&p1a z!pYul8*1xq>jxKpwWc)~G^;hfYPOpAn!4&ftv`%E3;+h_R_8Y7W>WQ0HDF8wvT(!3 z8y#wdwO(aUm^5`<(Qbmv*oIz}U7K3LwQ9C<wL-RLu(Gw*v)Yb`4`0J_raA+MmJ9jz zqG;hqqzEy(1N38b%%lj_EhAbD#pdF(UHO5cSmC(gRp^`49-0qB*;ckTwkEcKYwK$> zx!RJo;nm}n<8`$a`zHkMRoQy@3q{YWO>kO_>Y3I#bk$s4Zwn6k>E8w4ncgklo!@2N zb>4;Fjo$Iz#otr*Ob08&+tHsH2o!l*-7Ied_O>H#2L}vQ?M-We>Pp)3R#a6~Tk;(R z*wkBkUQI7vw~c%J;dl|(So}0TTA<n&&%Y7zO|bpv8q77u#-k_k7G(8On2EIX8VW)* z1}Sz@B4n*(uVioWd#Gw*C53IIigj(qMx#@xr3aFukMS^Ma+29eAW9kPOU1Q<2DQ_k zxx~5IqJ627<WE(ub|?GO@VN~|fQ3ch4Yd?NO1KCh$&qA31tk@es7w7(@Su7cG1o1{ zpX@{Rv1@*Ma&)qPa*Ta|eV%%ex~qPsens@h94R^Q9EFn=sk8sU?$6jS6{H-JBlS!5 z<CT+@y?@;L!+gUQ!zRNj!`{P6!&1X|W_9(!^_BGn_4ST5ER&pboc){(25vN&>J+O~ zPT^V9B}-+ln13p#3`=MX-1y8!TGv{8TUT2rVYw8JZH|48nU0~3WsaqewT{J))sB(X zSk%sgcAcFb?H(Nw?TS8GJ7%kHtDKh6mz|camivNsE1gV85g6vloJ`sa>5HVUshu=* zWYvnw#||B#w3(Kvmo=A@b3&TOod=wkoM#tzJPtheJa#=U-_G6?mhvxB>JsY|OpM0o z#>rD;7&5e)N)eQXsP>a!$4E`WnPoJ5(po1}k0>3<5T>;-DI*dG$C^_7P2R_3lh_hF zX}^lR<X<1|+z%thSjJ8dCmdusn=|#Yb*d<*X_^z)$FmL(4?piDUV(Q}hx)IhcPxj; zV|d`oL_J9KwfwGo?2GCPY-gAl_|#k~PT(ZOFT59H0M1g>G`L16osmZ>xU)~=zlxt~ z3*gAoXfPQr*HCZJKfE8qjHXIiyWCCjws<e0J*~a7J;Afkvx0k*canF$bEb13%5i?f zuz8}=t{i+$+F`X-+O%`;>7H*LY@KfHZ{;v{>|ZHeK|d2-X<ZFprCf1bxn4ad(a~_L zA(j2o;B0fSIvg0oNvfwgR;wySSCyoxOu|T7OsXAgOv0mXR<)@PqM04rObVrmQOU04 z(Q_}m(>OdI>*lrQ@#g90G2%hvN#L31Vd1&wf#;Rt8RzNt#LkwE=^?q3;N>J}Ea_7^ zEqi+5HIQ4V2j?B!JncO1yrI0}ycE1<JXkzxJhr?!z%>=;(lcGQ3QNt!3m}wA5VZ$J zId!|FDp@tN8fQ6mIY^}!7^R{GJS%@v!3T2bIv1V!EVcuEfuEI@cTJB?&o0kT;Mfi2 zTH@OL+U*+sTKZb(T9IK@>b|ZsO*c(#chRj;H=}vw{7%)qytBL`*R|QT`Z@MF{TUg2 zERbBIT?4Kuu496B8_R6eHXGYqAN|h47Uxkznp?OE(si;lCZ({mD>OB-)GERCr^+=2 z9bFw29VPrqU7gO$l3n~VJ_YaMH|@v8v!S#1FM!)3p=J7V1JFWizMZ@X%v40cOy!m> z0f4!rj}{_cZLny(WV~p+e6Wye84l=R`%KrLEK8SSTeh@W<f(jJ=IG&A;ppQS<ydc? zX`X1F6Mtgz($48CdBpJw=F6xaP&<cz>FY|hEwC+TxDxhi_ZIga_D=EQ@bZ1TddYs( zT_#^_D!bHOFKP1ayAfNKt<F;7?oL*hsx(<}0AMtRXew0}HI+8yFX`b`>8P~Vx@cWS zYc{ypS_@z9ubDO40{9nvo||u6Z=N5XpPrvfz}}zYz2w#G_4pm@i<PG%=b+?m^;4RE zJLgjEt<fiR`>^_E`Q_vDpKp?Hf^P)jL%|o$mcp0D7lyA<-wnZg&imJ$?~U)1FER+# zobUwa1Wy7M0TBTngo}-pik*s{iVGeXz*0w1$Ibmw2PP<ga(^bmP(v>IuL)4r(AUsG zkRsU1?TG9+?O5#y<r3S`*^$^$*zw=|xnaF|E7|pi1>s4<vBNhZG$A!1yC6LwBK<@{ zM3Tean%L<8gOm83a3cDVpLO8=5z10n+<;<zgBb!RD4KwzUWvY&C75PtR~TfNX=q!h zYiPnBInX&UdQe|*UC2HNWT9L^Z9#8Aib7?1yLq>HfAci*it>_(h5lh0hSmvz<ZVU> z9D=EZ8}sDN!T;1HBo_sj3xx}l3#|>i?LROuf!##rMe6+73Ga>I4NDQ45xO4a3;X;N z8KER3G;}zG0vzNv-(1{uF!E*oR~*7=;G>S69E@Qgvx3qTWWBpr!+ilC+E;tic2j(l zeDlPJ64KueK2R9FSiOFGF>Ro9;dG&OVfp;`Ndqp?QW>~`wd6^3NIHLi{0<}${!Q|` zTdY{5SR7Lf6YQT!`l5|RgW@v(QO9R6@&F3|C}NiVbNkH}Cr^sGin~e>CjKN6EjA@m zC4x(W{5ytZn#5PMOC&vi(id0v*}U4k`^3-Ol9i6@cRE29YSw>Q7&^E*1cPFu3O>r{ zDkAp<N9G0#1eMa*y4Fs@PG;!f#G4>GJ4`oXD~2zkEAkWn<8%IoYtUoxZ2)>;&XB}# z-w@3(!KmKw-Y_+2SHbWBn|mk%)@Uqf_tdah{ci>JQ4ExkbFFjjWbI|G8$vXGSXOve z#O6QVf4t$H(I5Elip#(%VV&hR0%yo`#WS&m$<hoJj%FKs9Wnd@Sw)KK`2~yxj79e| z%d_v!&ft4;J-&<d1N)2QW4MkGhu@sPE+ampMF#xn<oNgu0&+4oe5<wXhHKx?s^T~D zTnnZ7^kQ?R8mgHC+dH;JRuwk)bm|Q1bhz{hnKg2agqE=F#8na7G4tQ-1{tPoAITfM zty&Jt2lS&^3EX6^(pNVhHj0*WJB3}_4Bp)@onOyB+wH#BPqzErSf9MU-BeVkpA66I z8@5S_PS@j|)5uMHeuM`+^1L&f^&4LvwgVr?&u^RO_xw8T@5@)$E$_o$sQcc}-gn+} z9|~caF0KQcyU(86_z(Q8;~&vq^*k=u`igT|&(B*Mo}b+jp37G{t*$Ryy`DF`J6q|V zQ=ap-(_Op|F3aoqwjAwQ3oo^|!u#h#DN%BGgdAJ89qVrGw_f|TLs?N7xFk`#V!{Po zajPTdg&cFZWonFSKHYT>WAQZm)sY>{ps`pQ$f}2qj?cUF@!j#R@$m7w@p0TOb{>nC zWxMuW%l^ZV2*hDLB#s_L{r;&CI>aJGGDK0tC1@#OgTU5o1-a^yg@p6Jk2sG59zwib z1Zpv5U!6WCAK`C@k5cDYiwvbXdSK~W*^i62v`3{gie))qjyivykJm@bTkWIKnfP)H zkWiPug0IrY{3G^l;jQ;E@C;_@x%^sdyS+=zd-{#war3-=$+hfSd%LX5$UF4y>9KpE zxy)8)8`x#yeg9_qIQsb49PJJABl<JKN3=UPXBPRy^MUZe_5uG5>kZR8uuDuYk6{+; zMCk$c?WgxYK7s3k=b82s{0H{6e_KLdBDVP)Gv_BN4{#nh)&dN9ShMgaoDT>dxV*sx z;xT#Rv;8N;4@4din=x0y&-tD+n<w-Q1fufT!SX0jGk@CfH$!YhISMjn5Kp+A=-Qxl zqN;?>XRvWaNzAbk^8{J_mh#!m+0I1E<&ibR+GgPz5S;U57yK~`L`xAHbAwB9*z&{{ z{LU2c(_<`Wd6WZz3K&2UjM86|f+nTtNx6o~|KQ~L#)RwT>C?mN6v)Q}PAL(K^3ho# z$?|`o$Lz_|h70<NtL2W*nw%&)!M0)R1ksCN<vPxCo>)1Nb3tZB%L<p|E6t3ah&b_Z zA>ju`i}{L*=aJ0*cVg#+ogRWD8k$>X4#)Kq-|tEIJ>Ppq*IcdvW)1%`+(nQ(AAhFF z9MC|v_T4&~T{vNuv=H_c>ovqnw2LSwPHqG&;B`mvisv5MA-Y9W9h))&f53T%0M6hA z35b#7U`BWk=pA5Mqc((Wh<u5b;{YQn2XGEJ76SCYk7Mgca1PKNP&xg7iANKQ$B~SD zGv=?uS`F;^`42+k*Q&pjcoVT!9NmbiF<RY!t9}*2OTPiJDiR1`zyBkR42mT}6|nq| zP%+94g+tLlk;LR5yggBo1gv5tI<e|N0QzsJe>hCUVj?joD0K0m<|u6WLW%#rj|vV* zu>Tec`boG;tWAoxOJo%k#)!ftBwYFvhnN`W=eJ&xKR+V$W4GflMjVW(>aaEb(Fz<9 zJH~O2ARKTQb1@^Pg-Z*~#f6RhFy>*##EAlhM+%AkCW+l0VI)Pw2`~IjH9}-e#0+s7 z^C0~8+dEcQ0=bZT4)HX=Nra2&GR|d$K|-q#aSqoaj8!;3j<f~#6UjHQyH9Ut`bPW( z5`+vw`h@p^@AlX0uii<yfq#JoVf*~#_q*<Y-r>HnZuzeZ>I-%|=*zFVe|e|;2BYO$ z*AKlQhMwbH#~Y0oRxda{*c`u@{^1>x8-o`VFNiJV>%iwe&z;R1dhFo;umc3K{q}EU z-C#Npx8Q93Ir=kpqHdtwcsnq4A*(~qcd&m2lh|P+^?h4`@!X|uL3QcJu;bK*<~D%Q zhD+%gtih)bsI>cL6(UnZu+-C9gR9yL_Xj4qS5f_Y#IBY44|sjPiNJb&`U(G4MtIXc zgjA$?eQN0t7X9DSez%NBLw(pUu5M%<-*w>_La=(_cVBOK+~|2=vZ1E^d;?4R=Xc6( z(A}7MU}Zxo`u2D2Z`9ooKr}pX1W3q%^E-JrD1R^r5K4Licl>W4TKG4Rui&5kJ^MR% zvh7@3@HU{X5L^Se`|x+3?6_aBTIe>QZJ?Tiw0cJEP#1oD_;m??32o;x%$S{^J^bf^ z{DIgR_!+PzP@ShX1AjvG@WTUvH-JFsIk$ZV|Ac+v=VriXkc|*W?)ePc3G)JkP5`|S zR_^@_=LxM7G#6r4fULl9p3#iL$xkPUHRQ{{Cn3*V9eLg$p`Sm5QGN*7n^QDEt|3_m zHwk3q$;^nELpBg-!c+#U3YX_{Q9_I6{X`E4h$RI21Bn@wq1<yNM-Wv64&`wU0y1ME z>x9`y;52fDN+Fnq$wz+T5b+iU-VxIk`a2M_6$T{6evcRCj72~dUXA^UD)jvy@@=m4 zKge2QOcAh^L;V&erG)$~@aHGIL2l9voH=I$f+ifDKc;X*Zt%=^a{^YZbjZmNQ$dzI zoEax`Tvn)bgd$<IJlGjG^Ixo(xR6mHKEYywB)PjYjFgDDaEShjdA&14=0vOzXULC% zZ$jR=Tk;I06bq1NNX~(6LOQuq@)V`K3rKHJmhg>WdCSV&WO?{f&IJUk@4kN9y}rG+ zJ8EDv#sU5Cf!GfG0`K#6Pj?T;4&Vmk1=Z_2-*>_Q<ev8(-W&S=86|r_a}R$n-VWgo z+YPlFR0jgPUrJBJ4iwl<ka*y;zsUub^d#)S-e9|-^L!_OM)rs4_1@97LvDeufKfpC zMvU^~n;k_9<OY%rWOIO4&*Tod9b^lEHcS=NvR`?xiatIzWP$z<gg|1(pU?vQ>hNzp zmNW1k0vzh!k^@b0;hp@7^qI_IA_VZ%e`5NH%|M(9;-?}X`QyqX0tLuQAshv8D51!5 zu_vHKb5YR!ykcP-dZob|CWtxm1BVE|FaSLk!PM^u3XGv3!V7l`s`fW}m=u4hUa}oS zyKjF8GhwEnj{WL;HFl)!pkMI*;AcY1LY4R>^f=l5{`2h@WHhw6KS}R@J9dnSzrGg- z1oryt`_>Syz+50c{qXeL?6uKXt6^Dzz4++@u^xEYqu0}<k5|LC0%!G&Jn(Oi>kb}x zO%cFr3h@Qu`we_|_t5N+-FyeH9Ax%)IY03p;hk^)TdECcTz{>eoF17S=o=V2{1#|! zs49pQf9M@lyZ>4sz(4YvnLkU9#SXgN_diI#Adw(L{Q`Tw>GRhhufSh?bAfD!Ko@|( z_Jcry@cUDP|G%$ihs^Mc>VekhtwB<UulS}4$wUMv;)jCr!}1%UJft$DZZ6ynM3MlM zJah{L#SVm|pJDFLns2H--_gHA`N1-NhZaCS@$(XZKls+_hb#Y0QsCQ&|1SY(iEpq( z&>|3oJKr=Qutt9Tfq>Wlj^Kwh13?YG00Nfi`ws|Y{ci|2+%>4`-)Lcyze)L%^%&|C z*FdDgOh6q$)cb4nAnb7H<1%8TelLVX^M~zG*GFK4!-kE72!SZ;(I<k!{(<lV95?uF z2{7csfc^J(r|(?fFa7lVngsB2*}(S?Yy(94w^0Gb4ysSyPg@WGBn9r4Py!i&gh4qk z?Js(_9JkB2YPVRo$G2v;6t}~-;<ur<Ft_iwp119{+_&quLobytlP^&(k1vfci!Vtp zhi<|kMUWww7<qxTK~^AXkP}E5WDF7kxq;L{=3tg&2a*Trg9N;Mz4W|nz2v-HJNS@> z^ZsDR47(1w4m1xp4{{813~~%{3@i^V52y{R4W94Sy0LzK)w(YAsvK@7^K)>_uwKd9 z!C%=B|9FPzwMZYzd(RXTvU4rD-TB3_LDs^CzaeB78XH83dNhA;x|NZZ-d$n|lvw-} zoZ>a}Ue*O%dec8{U3Vg0dAMe^FX`-8xu~_$Y#d%OyOy;N=v>e{V70+-yk7CRR&lRq z9Zor!wajmnU7@??;~mM`32)k8sk=tLm(a9zw-;<GTuHbFac|%sAvuS(1a59`2wn+1 zV>NfLPhXxt*?YEkZe-j1Tc1R9X>Zfnn6ja0E?DoizHV|{Z?oPYY7WLbVRwbxFtt%? z4qG3wK4G^zZ+G70vY~4(*6Oc3Qgx<jPud8#fm+_CJ5IKjYA@P|w}EX=)mnITjA#ko z46xzjh{;%=JUnu8Y+2oqwh?<a;|P3D$k>uOerwZR-iMoVrI>s@@^bF_lar-PG5FU7 zHA_ym1MPT#>pF9J3jVnDe#QMjgc~`F^4Q;TyY+a(`RWfx<~g{@pYRyyINExmZ8ybz zoLN7GbDW5_n`sx#EuKX(WpJG9*t2?mVei6Swg0Edh%2OkGrWFt^~lPeopW~z+AOPn zNn^jlMU|5#^KgpUEUbP-<ABx)^Ur;j`;@j>G|PJ0;e=f=_k3pA6uMa*%V^q35GPuu z{gk>{<b4SVXa0TYeLKq<&LM(p2xm8EV5VM{{}jU%L`ly4@af@$lTapstZPXI+J%#I z+n+3O2nbV>HNRxB-{7LjDJYveKVfmk>VnIOm<28CT~ehqTz0x(2jpJN1j=HR)G3XY z?YwXwX4T2!lq4$6QSG9;hI5MI^OyWnTA?~Xce>+#&Fqk+r)W=D9NjZ^VCLfI=I1=k za*AHQwdaY}_idiPV0bd)UX*P>yO49~z&9ISV|s#l@BEnZ0d&{utukC<J+Zu(eGK?m z@z)hxhPotv^mN&7*I%zRUur$cyoY#CMmK!bel;<yr(8rlLA`f)Pw@eAn&ejhdxCv$ z@m}E5zixhBX}{EI0&q8(WHi|Tnk;FWtgaheSJp4BpD;b^J4d(7ZEKd-02hl-lAghx z8@i?pjacgu7f?@Lp4q&M*;aCO6l(@9rMz1NW-*P!EAez|zAFWn3Qs>hTX-i343V3B z>tR;A*B~$Tz=s}xd-dk}l||?Z@5Pl12lvXArE3%SD*h#si)VY~<{VO;){4K2-{ypk zAx9J5D&i%y3vYXs&Ty6Wavfj|Tm*A5X^+>LeQF+GGr5>^p=vMG>7zHrYW%qP?PAa# zt1~lYdt86N=6<o^LeCwVwK)Y=QfFDkxkPaB;Lf@Pcv=%`)pTiDEODGiJg!PMDpruv z%u3eqY22!2VgS4w3@ebAJkPTphdiu1YqGVbD@vAxX~sPCH|wu7T`Sg?=+29s``c_p zHNVt-wNff0mY~i%oTs<|SxvGU|1H6umpTt{S>ZPzslS7TqzM4cjpGh<!_0L3b71W# zy21F$tR*BsM&sg|xpmEw)_DcnlHL+Eps2A=(}u1-SyQTFaOpdsi)}g`Fj;G=#Zrm0 z#0mhi4W@%Z1G%Qb(hr&iT-&JnAx&S+c(yfMlc<^yt^SI<C6sdxK<r~V+sxY_uKpvq zec8KmOO=6U;LOIku}wXzQdU*GJaBQ#63|$ysUfHePcs8oldc(68KMeVo~^PBG+J!3 z)L^T$RK+N-QyB%CtJI8X9abo+{w)tu*`PMXXarUKRyCmMPMRJA9M(E$wN_-RBGF_d zEshzQ)G=%FYvEMnR6MA1jRRiQ3GUlpCqb4zO#B&Trr~K;<Y}-+6f9ejEJl+trjf5h zUe;Z#IT>=36h|a1Ymv-^sn3(1NBH;2?(-c6x-2A<z7yp~+eaApb?&1b=Gh$6>1Gr2 zra|s=JO%_DF=^tHBuB*exvkS1Mpx{vX;r7GO%~}PWf|#Z>ETov+>`i6E{++kiyMYE z?ERBbN6?O)txMY0pC(nzYUwl+heyngWvv6+R`je`srM7BN3@Q`oST`ZvTP-(36qSD z0XUY?9K&fwlT5|N;YWl=*GJ}#iJX1EOp(|^Qv<=B)PhIVM*@z1tJ@cVCsyGJ0@Iq+ z#S23hcJ4I%NhDLx`pVTIE9)j^t#m<Cc$OI}8|c)@iDFZ<`r6eID|2?n^9<(+O;efr z5RJ_WQ&lFK42(&*;%<#CTC-#}sf?nDc<>Z`i^c@4B_<PmM)1UUQy-R`wB-q-BX-9$ z&dFb<E-V>oixY;X%q;0R6FCzPrd;#O59tI-j9qvZLmd0{ah8SHqhj%K=A_uSVwwK| zyjTq*k%v6@vu>B%j5^qLaTuaXhKxwo+{{IAkR#uRc=xO9hg+;Sm~C)5BG1JNZ=3B0 zTdcI1>9LO^>xV4%6aO>FWR=Apjxrij*#Bq0^2huaSODrhvU7-_pY2yaJFPGWt1uh7 zQAut8ij5UZ6Lv<Fj95!;uexmo%MxyRRClDxkfc#??S{H3En6}+d=%7>mr*v;c&ddo zM=_346xEQiQT%_VLAd*oOhY*##{Y&0hs=!<nfkCz5!gbo1EU0os)rbcAPTx?r%#L? z*gbHF#gGd!{<CsoYs1cpk`)s#2%OzAH)~+h#G{KMDhU41oR#Byq^X!vLG5f$sqF&G z8E#`Fu9$N{y24<ol`=CmE(U^cL5IQ=B_NSW60aySUJSONbk_`>2@VG;>bsZ^Np;-% zh{*wC9o}kWg%~DDLfq`j>WDtbxRAvQv3l3Y?cv%Z{Zr*D-*-vr5uH~<ZVv5H&Lfkc zeE5X$;rUJLBkEJqx2$_6=Y0C1<PGhk_EWyQdVBu*%=KaYjqan^M<-?h+%msZeUkDR z@dowL;Umjmo--?V{@>f*k02jy{$j#e<a3xu$TuJF>Mrr^qV~3e^|m6swkkjykfyET zdZzhY>yhrw)H{Ko%64Y?{QRNu4cEKzGo?#NuZm$l<t*Y+^v%mVn@=sLV0y{yl;siU z&B;5RPbDW`Zi(U)?UB(tfB+b?JbY^O$nX3Y>v8*W_KniJkWYxP7<n=DBoI8EDEL<W zCh&pf?YE_OUGlv6e$x4<>mkQ0a-HY8+<w~YVb)o&C1_jSJimTs{jlUg!z*E%$FU6g zVCtdN8MdWvTgb71ck=k?;i1zRt*cdCw7dW~S$qU~V06~${;e)moB4RW^Wf~P&=q4S zN?DLP8GJPKP}r1XsK8pdKXrfD@Q~#V&DNPNHe0MeNqdy`5aSK}Ovu)iD|tWD1?ys* z1U%_T&39SoH8QN3(Wywy#y67EDM-!mS=?%7VwMk@6E-}rabH$GiFp?BF6B3dY9_kq zwU=xz+5k8j@z$I#(=p3*7C)D&%u^a7)}SssTvWLWvgUp_B&@++wzx=h1Mz2(05A>S zYr57kO<L<kt?31;=|ySjd8g^cW$F2&YqHi6O&aTk!2rBQ#5E7=tR_{hg36`OIaLdq zMvOHF>$E0it$eyAObhr%s5LL^Y<9Jbg2^RQ3zkNlH7DzIcF~LqnK^PxgS8)Y%6QdL z^F!vomht44-GG9IxV4|wsqD&l`H0}*H)zXlaK8Jg$zNH$Bz|7`xFFPUrO833ehze= z1^b+aXicrks3l228I%QG14L!ok}@ElZ4TGcxsglLx-wZ+sXPySx?8F=NTzqI>e7@X zElFCCH5#VpsEW`O9xmTmxHs~EJx@xq(s-W9a-F3{!^E1LrUzZtQMo%C;bei2+WZ1o zJBv+4Mj>I5lub8E$!IagGV)CjY@15k!0AP^Go{C{H+Anqv2x_a_cPwd5D%Fs<u8S5 zAl9Pe8TdhB9+FY=a;3uy1!w;~#(K!}=3c2im$s{jH>yansR%Es$fzi5Y?fWgH<zz3 zRGwiv*SGyeRO0~REj*raIaju6>J(KetCfx~6rG_u*S1OMl+w!|mpd+Up3yoNbLnIi z%c_)=CM<+mrg8})stlL!FYv4U#aP^4oIRs-F67e22O=rJly{c}F6b@lEqt@|ZOmCy z16zioCy>|@xv_ms<`U?l2;T68Crj?es5MRNGUzh81pzhz>tc2Vyz;1p5KG9$E={@0 z@+Ad8dE-Jlc;u!{Q>GHAsz6hYu?Pq3*3_jdNmh_5FItGVWNIuuE5THNFN0bDS@N+} zr;ATk9w|BkITtQ0+1Vn}H6{x`D@^5m73a%OmGu_O-zc|}SPwJqR9^GFR27p*$rS#| z^HJSOW}=pRDH|p}k8vMX-if(ab|~snPbZm;p&i!VNrb5qP%DgiA7+CG+A22`ZKydC z&&Sxv6kCCyN^J#tDy$^<F`UB&2gxvbS!#;J{V}G)QU?*vieHLI)G&$OW4b0WbyD^i z;<Xq`vluc87#gcpRtoGi8Hsi#fpxkXB^4@5l;ug?i7I1~Cc$;m8bDeFOqz(q;4v?g zY-Y8zf(cbqYL>*)F;){GvuIjj5EWXYyh$drDoz2YOd`A#lozQgMn#geJH}{I$}I9K zgHs3sA}B*sekA!w>J`PzDZwguP;Msb7lDVdPYa!txhOA_TqL!Ml28j9<i95tOQIFU z&B<HjE~r^ju_c{JsuYDQYLpc!D^pV*COJrI6h$g(QWYgChg17V{#R6^C_z<vpmays znsfoiq6zT|uNtGdg-TxNF(4h;gzizj!)b71+;58UzjqXzy3tA7<F<z!cYxO-kdO~K ze;na>%z^o9mzP`@&32sac=G|6QiDsfq<XQ_qh^QmcT}80e8hxt$m5|0fp_2ByF28z zXs+X2$J>p?n~as%jdfH_M7OAHQ<}%L4kqu&IkmyX+mz)|z#-e6<tu}G5_s!~8B$V4 zr4GsN4Bg{8<aLRrQ;tU+4>|9w+>?2fvWewVN=B6qM!~WV`M;=RQiey3OcXwa3Fu<t z#mD*&4en50IoxAG<vj8PM9(SjW8MeZ4*xb}uBct(xW}^&qQOPsPH<~3S#x6G0j5Ll zFCvbFj4_#mAqSGyJZ-%yisdB0INRZw16ymjwni1HnzpM9$`Aq$i#m$e@N4uV{{H;I z^wihKR~tEhaP-&n7k#$;NzKjIPRUH}*T?kNIWPX_y=^7j<NI_sG94?(x7BRNHxD#@ z9t@3zOAUH?y}jQ*9-fZLA>`-x@d5omU-%lH2Ks*WA7A?F+=LzTck~Gu{9{~L*Tp7B zz!LjO60DG&pKX}E$EV?4=Q;LzaPxXqcJ}Du-FfPz*m2s)@6O`p`(*lHdT07%dTaV< zdT;uCba!-f^mKH4^mufC^sw-xdZYTFdaL@h@T_{T`n+_v^t5!l^vHS>cK`Qj>7MnD z{eks~^_KmP9dr1|mna%-I3jQF2a|Lrr7S8%gwjCS9;<!ZAK^@@DO9rv$AQ*89{a8q z0d26-I97zzK+ztveQS%5HdPhs7phtWV4!i2%f7QkaDy@=B4c2357WN9MP`Hk3dJ?N zu2flBRAoU#hgC$WK}5?*L~VoY3iJ7&=b-nV&#j-EJP#=WX3RhFL8CqU+aNc^NEErS zl0lX|joVB&-3}sMbcV2$L7KhoJ(XKRCgx4A+jKXb4&p6PYl53p2i?|R4v7w$Ewt+h z<N?atJZw5XRKf_kfs#Fz+twE$FRCt7y$IWZ<~{D)&X+tvQ6_Sutcs+;7{dx|ilK;{ zfgel?(qpld<PlVcma=-c^)I3zY9F-uf$Ml8cT&Ppnperw!iPCIMd(vAs)EG7W3(o5 zb&{)v7m7$!C5cjFbcb<wlCOmz#cyS~$`aJH7;&J&d_|_R7G)u7sw7EQ5o)@mxG~AY z!n^oxWkDb%cs^80r4XpdR@SC045V6&x0G@&Y*XYd>sk=7q-2Z7m69neR%D?Pu%w5Q zq$?yUGa1S$QdI<$MJ=dWQZ%M;N#GaBDw>r=EU3UGxBcBLB2fIdpmav|nEWQ;UF4(a zYvK10!7Bfzf=l{Aj+h)GAzWlIXJ-+_s)$P#mF$!987uNP{xfk%!l=l8&W%brohbM( zTG8J*V~cQBm2`5M6jKS7B8@pKi)gUg0L5eqrUZPE=$xTN7`P9NoGwLGf~H7iPH)a~ zG*)^v-fA>X+ahHe$~$6O)YixLo2{Vjf40Q72DaR4r6+KMG_cm2@LB6^{LYsc4iYzR zUDLW7_r4h!s9)lb`Naye0XwH6oyPGYO7)ak;l`!RN^E6U3+9%*jVY37KlB*A#1++` zh;_u^I-JDI-UDL0;2SgEsDJXa6+_Fjl;Q`(ew#pGepE;Cv61NAJ?=;EHhak9k~b=q zS-_zFi^BZz{&iJ{&lcQ9^fPT<>7&#-Aa*b%KninenmKe2RDn|(j_z&p5vVCJtE75U z$A=YU<&_=fQ|F(A&$kMrbTgSv^po=shj=2<!NlKQ?qfJfj3DjIgmNk<Rr-dp$!*7e z77ngMe?5YiL)d~D5@hdV#KI6o^Z4gtq5~T7$GjE2*Lp?$BQr+~KcjC`R1l`Uzy$%g zs^A@!(lcL>+zUKi-j3$KclZJg124+HW6_?QeJlQ{CoLI!x!E;kN(_>pgFD(4L?%jR zlnqqTU4t+Rc3|xU^qD#l1IhfG+#en(KiWytlLzYK0Z@79U5R6ID#bJP3-;mJlC{B7 zXnAw)Wklhhl7ULNdXfdg77g_MEG9ivkg_;`lE_$0I25m;@_w}(?r0&&9`0yIdnN8? z-wjfNXypjT`|Ei+lS-QJT+5b~!--z*Bl&S|hQ)m!Zp2x99S)|CKfQFn$zqJjpJ;va zrs-+_{-NgQC^}UkF-0>6AZsZ7kuzqT&%8msuV#{69pI~S(+u~lk{1KiS1~~X#^(VK z3epJ&R~K8lasMo)C7g{@z5xZN*<L&m9dwQOp>$<#0Qm+orUm5LO9vC_6AG1Q=x+-F zzI3Lwm><h~9@fl?87!88Dj7IHneN8kiq2pMs)o{jUgtl}NW2TX6<j=8DI3eduA5Q; z@-frr{t7V!XS>$C4jMV{=kr?Lre&W>g62KEh%;^9e&I5%BkruBeBi}*hGedyMB&Yu z2{W(6u9{0!M~z66xUm`9;M#Zo=kAw3(}FRGz%EumeozA2k-npcW?BmS!Nw_?XQGsC zI|eB;tZ-u^iImYx3^4)0`2B_&BJxNZFva4(fj5%<v+xV^22N-k{IJuoXu45RDIVLT z44{;~EX|E33tDB`;?l`>I^Q}YjCJZN`@>9fn#FkQ<xK<r^4hK^_uXo=bhB{5llfA1 zWCKk12kF@_Q5&vY9hkb6-8Lep!tUskwYUn`@9k*bE`~!~^IB%6osM{L8&mo&g5C5J zmTE_}G#}2Q=T%>y(c--atf^^8V&nQQ!i*o#3Dq{**F&9~GgWxp#oVczz2{Tf&J;$x zk_s>Lf%l#_?#M1`KVRVl15ubU`+kM^Vf9^v_B2y0dj>4tvzO;YJ{WF!FfnwlDs;}~ zbEJCDv?7~5>~`@Pm;E1IXC4oA+rIx0vRAh36;ZN<tivRs5-OEjmeFk)lAW1h#vW7I zLfMy4BxPjCz6{y2j7c^28B3N7GuFWvek1q&Jooc`p5JSZ*ZVxK<MY2U=jXhx3k5Vv z+4gk-R{TOr(P4!Iu)$n{J{?yCgrk8&qRkB~M72ZuEY-8ZzU!ukoH<)A`HMZ_ZCcqv zIU$Y?iCsx(nwWK10jAZ6Gc!&=#Plaes3=@H8a=h_?JvdDesu$Pbw`pFb&J%Do1TLD zGtR@=i3f#x)A=@vj^sQxKaQn8Eews&jYh;fH^mv@eMW)t?_*79H+}V(2(r(MI7p@Y za@BYsX=E&`!o^PkGdD!#-8x}!@wns4cKTzX<T<#nN}GZ?rmh&K`x09ievzl4Xll>D zA_t?V)|~#d9Zg|0R?%tXp`P|fGcLRtJrmd(N_Kbf>fnXd&0u}}Y-=FXj!-}0vTEJY z5UypnV_=2+gtnf~$JK2vLsC`Irb9g4oj+75sRIkXi2E2`yYSHS6V*xf_i)|v`g<|r zDC5@e0CaRcYJytn@F9wDe+DdpMHvF`m6YY!e&|?Ocdg0M|IzBD*YH73TC5+!(%?zl z<$*PYgEdx`Mz2CNCs&ORX{bhu;hdzY$W^;j;`El~i{gAO>6zYrye3$0ShN~AlUVt5 zYxs(!rVm!uTO+)I1Ee{z>Y}27KCe-Lb8&H3tJhfFanbT{0eWEYih#N(Fk=)+C}*q% zZ3BaxAGGQEbuVY^3)&_SavtmXbLa!0jwj*M_aYcX4C`4y@SqI0gGX>~y2D<xHH+Tk z@xYOJH}=^@;x=z7nSr$-jJ0lhc=l!$zXkN`thsMxa&RR-pYzTOZIc;s5v)_Wv|5L% z-+S+P=9~xur}f=x#yw~+wQtveoIBq2q<vBP-uXH@MRZd%*cDbf_0)V%hpZ>@C>t6V z&#sexfilo+!D7!QDKhF<#>MT@;Q$pSsYHrggz=?qx|W~6QJppl_Kl8P;yuCmpcjY@ zt$p5<p$Tnag6-~TTjP+CCv-JuIL;V82jy!dGr9BWkxtdYI~OIl2U|S{4MX9Wk?zK^ z4u!=?g8telQi;|dD5XVf9>RiY%bvh2svrH3p462ELj)vk%=_^e^s&21=jN^QkQc$e zu~5u~nQg66i&woI<Dqhlqn>ATUMD0wQDtn+C0{o`bx1i)JQluj3?>yWSJeMYKqrTp zEKr+kygHB-n&H>ij~7|fk2D7N)3^zaeb2+uw!m&`q@TAA(s;J>YfWe<Sg3EJO*=== z0@8;z#rk0bxAhYEX4AV?NiSEk0&?KWufDVT*Iu<(@?AW>)$rM~>2Y6b`a(CQsb{@= zdRkR2Bz>!)Mb8RWWp@g0)m#^`7uvezRSta_3o=SBi8&io%b6P5zbn<Zh18?*)oCZq zN-ygkA9Y7Scu4Lr|Lg_)^16<89cEQ?c~zF2mbnuWqc9qQRjg<*>hr?<)DRslq>jLR zGjELLb?DAPQx~Aivr6f8-8}@yy)j2)YpIrC$Y$`ya`1L7wvNV>qxUL-okVA!TMe_9 zBzCiGGd338$`XrOy0x?Woci4m5$BR>RA8l!y;1;I*V8+lnV_|LEC_JgA_2F1VHQw` z?dX}|AJ?`>tC1tc6fq7$ChVQvXtvxA<lI#&UyXeah{XH#!FXr<s`X~;+Wq<h&1G{6 zmbuhJFk8y7UDlxbS6E^15Q7x^q{UR%l_Wp=mMKB>^0OQeuH(Efoii5SGv+=Xi5jv% z;dXgM0wc}6($Q6$>+$ssQ)s9YQST4(@(fFEo3{(M^;T!&?h(QtT5T(~;^I@CP5?B& z1uB<F<=8u(_Vlp&HR4$ERqRtzjg0zL7p0_S?WpYJ%WSuC7hg8&`^|tMpM??IEsS}; zP0+-iphQ#4s@VNt!%X#=4c+wJ5M#;_`X;-ZGiE9|^S%tMUa+_*qQmMqV1B1q0F&G( zTX~PN^CEfpJWTa5M^3Kc+l~miDQ`@2@rg<h#i`V6IWXnjH*HLEz@dO^6sHo4#iM|s z0m}tei}>5$<T1$u$jL0*z~VnJ$#9`{d&)GEGGBF|#;sgdi*a)S>}=fYM$Q}rrAss8 zzL|tDU?;OTIrL<}b&7ziVYuCMG-u04VgSanGvU4g=A#N&$kRwd0AN&I)G5PhyPG|; z90|u=dgg9~d-ccBw$-)?8-%o=H0=7}n<mAFF_x-nljBKNhb@X@1%_WvX5B{It3CNW z{41+PdW*o$7h6Gq^ZXkHozyo3U&C|$iXDXRDZ{`W3i<LGjvP+2;y{5xL0l2z${v4K zi#OZ?A$Nb7_r7}cjCQ`@nzQ$Lzfk88)b05EJ^4AiDEoK$26sbHL4Q#0v@Sesc&jZS zYGv5^%k`GT;=7VN6~tnU-bJ=sqac=E_ZF0F!#5ee%Ii0?uuXA*%1^iETAHE&m3y!H zOL*^p%fsrJzD<rO@^pDNyD<4cudf(szP|Zha`u~?<9gS%;O)1eHWc+vi^N<u%d<PK zVVXRhmkd?EJy#QJLERGJ^b$2I*rn4eiEcMGL<d40gFKj1WnJ;=x@~@DCbwNjxTP{C ztkt$%jV+j5g$@;kRYeqOQ#DYgi6t{xL*f?96UU$Mg*&Mq1+gsaQEG^8;ZllPC{_`V zQ<iI^r_Csb^L&nO8ceG`QD6%nNvf}u0V;~^CNMXh0e_O2{m}nWu=;~1XU>mJoT&0} z7%mz<{K`g5Wn_i=X>(l2Vk9vY;`*cUf)Pprac+%#3A>ZoG2o*Tm73i=_gOEyc`^20 zc9*9x%->+3)Ruf*wl;!4)*Le}e?l(;S0GjkT`<HHi=~Z~SUSDd4J8{a!M#C88jxZ5 zWbuv9dpX3l%TxAq{h7N#QzlXySETCa4exD75QHV^{cohS=Piu4{eFb`2#D@n4rRdw zp7c{WDi!)O3#1J`3SiHpdiDJB+R;wS;x-;QwWj?T!2L7lfz!hiet@ji=t$kHomgVc zF()^fj072ALFe#UOG<1z0hgsMY7t_hYp<6BY`^J!bmHXKg2OqFn?k>?o>1xN@BX7t zqT70kk{Ox{YahUF)<wv@@VmV1$}DOgW_4oMOlE{X(B(MTEMm$DLKNsr`x27zMZqj` z%3nRxARbKV>EVh%hWf!=rbb9Gj2in+&8-Nq<WLS)GR=Zl*n5e28`K%dg>yX?XxoEO zbYWL^$yJybf8$!gJ(l9v=L_ju8H)h3>iV|{agM&+X?!-c8&khid4uwP2L0W&oDGGa zoVveK79U*6+qW?9#)7U(gtvCx(8|(Cob7e;;>z$eN@aX0$Ax@CJAO*0OUyMSi=Xwj z?6=|(1c>IkZI(v9Nd`p@sZv@GCzDGglez!sdD(ko*y%@}1(HrmvPxB0%*T(dRb-A+ z%QC4g0m@j?6q-Km4;+>_Y02KK-&v~Dna+;U{!B&^5hqXy{rsSLfC+Br#JIR)W4urM z1z(tWX-C(V&zg3)q+CDc@Ci90EW*!xg?4RiO1DTZLhl%cAU(G%0M7k0-W)gLR-qLa zTC}B0xS$6n`ll#l|J?F}1;uCk<uqbfw^;R?E-4F7AQFT9kMSrcRhni6b0{h&BD*(( z(z)%~W;v~EF7u-L$pj~om&=ko-IkRquf2x^!`{G8cR^(ujLWI03sn3d91l|l&DJlh z!6V1uk@aKEa*cdJo)N)ZSvKC)QC3yUMBbX3NF;O!3>~6UJ9qRdYC3jnEKt<0X_htE zp(^$)dRY3?)0(%kgrml9O#`06^ZQp$;iY`(r!toHu>8G`Oj>~%)Q9Tmqj8N1l+9!M z09kefY85b1FE_XG*xe#<<{Tnd)elj$3UFlCo2mi#wD_%s^wBo7#Wy8q12ME%vS&`J z>vqzD^2Ew<CDbNeP_({KsxdckoVYHgLg-%=E2pr9jz_Gg#5NiUH=+Z_6RFU-72Z%n z-lFczw8U^zD;hewx<r8YPw831`3O{pM)qVfG>1_`&%yM|*n!Wfe6TepeW`v53ysK9 zvvY|}|CQ$6<K@p~hK>})XhcW9A$LQ^^MVsID$$aE&P_<yY<0pXr9%*}kqN}m$54fO z#|ep;rjMkoKYWjyn*Z5lqTnaVSWl~`kWczdpNmJdU9j=#xhY<EK0a8aWBiFU+@}W) zsFRljP7aMNld@nl07>lB7O!B!r)5$kY%Sh|Yyn&400Jjw<?6Su%;<mA<Zm`}fE<Sv z$u(;;^>KKchxsvQF~%W|%wExwn>0J!D6<lB)d?k|%Kp>|n3$c>`Top=;c<N#1_I6g zT-xeexON(UZCaayB(o`lkrUBJ2ye)=%B3UD6qu+6$^0i?zcS$rIzY27>v%CK`c8#~ z5siT}-NjB@YC}6WQh>=nv76f>AmG#j7(tIff+!R&$q-DdGHjETuPJPmHA|U@V4CI9 z0%5i|`>ebh%aKh<G*l1CYTOVM7#ey;3e?qMwX)2kL>PQZ=%j19EQzU6<93QBEJgL- z{EgW+KK7!2V;tH?>kA|-&*@4AcNCD%MI=0bDR1<>sMb=tSmfLNFNJ+K6N+Up9m(nP z1{Vt>iYLCQKfLICyXbA*omk@3l&N5W=xw{VdEW#c3cj(FD<1g<$8=<duM|AI?eUiB zo7Tf)Z*F%KXMVF``a@p%ZXzdRLJ;>&;b8+YIo^G~I^{Q(2<}P&@z3%nS##I2Qgc?n z4)|@Ge{*0Q1`;t@e~@%=>I2^taaw*azIO-skh?N$`0`>==@ESqwp$Orsa`LPzwMgH zq!`k7HLnd@Sq%AhN&dzC%ZsmgEfc?){wg6RUy!>Se|a``E^C?ZA#Y{ku$kSfe8yM5 z9RJ{sO*ez-&3%U<vi^OK`_lWh`E|gTXK&194IzJbJG9kwz=h<Vwe0jpwE?Khc3*6t zb-y;34%lE;!8L=`4E@SYNWC|r(7OLcD0a)qV1SVdnxXUE?g4r@A@|gK87M<XWDAns zJ23v#iVY4m_pw1V%Fuak8tT2#g+u-7V#CgL<_(2k59g9<&V{}^XJm{v{RVi*Uzu8a zCC?60(H#!a?pI<T{&}fR+)15Xq}RaM?>TPYHcmIEW;v;Y4c^HMURlp;?&E+c)%QfD z*1%+ivD1_3wt(bJu<z;(&z!DawVFU#P5T*R^5|T)Sc6}I<{o1RJ#sv-Uzaaq+8`M) zmyNWYJ%tbabc?;X<eT3wG%;D&Y$gAiy>H4vRqry**<Y)7nYgSZrX!qWrDmt6vUakP zbNyDP+;=a%6E<>LNlrfq3W7r_l*2YywTceS3S6QwZ{82{<McLXs!(p$-VcX`FVP}g zK}Q$4@`DX3lsiMtKGA2zHJ%(6zCw#2AsM=Spnzgtfnnjxw9BrbBNAMBj;DNWo{S2~ zRz-DrJn*$iV_2K0u6qy4@1{Kx{M$Z$B>2EY@PU1d3d*QcXwR5>?((N+&p(`YDmg+I z%mV^vzVq>hcvB)HrTpfRsUfg=c6OlF=ENH*d!e@Oe3-R>a!gC!S+pgiPCDNzdp2Qx zVM)<E<yk?XkGe9G3rEGdF8%Xc<XqP~&m>I;EZnMJFcopHTBkgE;S5cgBKgAZ<Vb!| zlls|pIZ&nBuMtT5o(tb0Taq$3y;04j#SC3ylW(qJ-V~g#I-YxXa{T&^eLDL5l%?SI z`v~aW{t9{BPxAJ63Q`{u87Ei&A{B}{70G6N{}YS<vk2cFGdy>bR!p>Hj}Oo);2r<o zR#IzQ($VuR(lmI*GB^F<C4Et%m*JAf<EFT@55}$oX(3`$Ajh4Dv7or+5{@DF%NrS# zNBpYek4YC#!Oc2h{5fvdH!_kM3fKB$B{OjrYC&G@flO<{m&i=Ee6Og7R-`U@F-@z6 z*|PPU9)fEe>Scj7YS%n6SISK8o|!J!_8ZBv)sRc=?Q-_3aOEY>tO*?<U#j4g;Sb*w zzADSStnfTov{RqwGwPB$w-cL<Q&Fb@m+x2R-1|h!quLy&<qTZK9`hRXAPyFc+EC@> za(@MJUf(^c{lnnwhxD!=j7tr;D~xA<z;L33;pQTqtdZvg4PupZ;c(LWC#MDpZ8s!z zvGbbl3O+s?7e79NgX`|Nb?DaV*?$5{4y*AkYNJ`QbYJAb@Q{=25}hXO<4h7nJX46o z;5CUsL5a=>CJ-YNSb&q2|7TSE=J#VwI_2ke@=Z+E=AKAO;0mPuhB<O|C;a4QD)@(% z9&2RJHSojV@~h#Vrq3OQ$W=q5;oyH`!wy{DpRV99%az@ASs1Yxfnw~a=4uGYt5RC~ z5j9@>)y67l;kuXIP>kKYa@uah|H8!48=+%!C^33KL6heiK5n-b2h!YLF#czly&FX7 zn=>edtIX<khVr@Ov2V?VC+MZUlyu5tr&5W#N2?z<pE;~_%9|tH^oZ?c;&JBGzaqVf zulz~}z$|dsTTp_0?kV^EYO`+8DiO|IpG4aueq`!>&CLF>uc5itM{5r>wpGM})8h1d zjHT2`k<r1OccfImBX`yh9;C-L_85c8hf@I?&KldQV!;Q2OMx;PmpU|OB1F3&Mo)_i z=`jYb3@6lYL|Onh*BF?2C8fQXaF5<~Ikdb#cbql=4-Fz)km-!qPYu)}>h79;*f@JX z?NGT&m;(1nE|$)g1M48Q!`uWSQn_|Q!U@V08fyqkjsEim7Tk^%<Ohm`Hdxbp(#VdZ zp4^ta0%1$cHgKBNETy+s5~?@Ez<e_#i~}#5pUQnks}kd?ou-B?i;QN7vMbg?^EyKF zI6}@jRS%D*>>O1=hB5xx=RK8R*fn)?Me7BC_vcPt)<uC2$o%!26_U|ETKj`ez+F$M zF^(pTzQEs_hMa)uXYKIF`L%ZS9oe89f&9EW<0L~(n2t@%y6_A-<f^Kbp$FV1G$n5l z(mw$ExA@Ap*>#>cUAkg&Ou`6K+If+KAX9C+wk{V;zXl2|x7?jhzp$wjjqP}zaADe! zJF7#L-7!7#V-MyJtvJJh<>?TBwYY^)M{?V;lMi4#p@X(ejP0P_+yI@WDZii#Khw;E z@jq+Kn-hBm&VvbEFTC7!=WKdL^ANuloH;$?QlaegVh*Q=%(~vp2-#*Z1Ft3yt8*K+ zs+6@h^Rno2lm2bSjUFJHGM||9PXL~7WnN*EOKiC2<fW=_HbYRf)Piyj-!Q_vkxJa= z^s=+nCEm|F^b)f~veZ}>!QR*#Ihoh=U6K;gz4oR;vpt1$`c7-2tMy|R&|TleOM6e9 z_ao}3s?B^Iu?@;J)t^nm1`>Ou<yJep0IK>4;F;vstu@tLK<{k*R#sIQSSYOF5Q)`6 znb;GRRdaMF%E|Xsx^1U6*K)vq^@}0aAJG%SwVw8^NRy~fi&Zp;JmXsScr}%xWY<#X ze@?CHMKJmWN%0KabQy6jN1-*@nPSgIcJ}@wTCSVoB=S31tK_ywndnjlSjWqCYeTi~ zD|RIRT>B`_+dc2j8vKEnCD^mU>06rwKwX(){C-M`EtM%apT7Qbt}Myk>g&SwAiHa* zlDPoES=8jt-K?f(YF0ioASb%A@0KtaHADK|^X;LF(?zw)jK+ItcDxFU`(Wh0I+sLe ze0a#?mBbIMUWzdHd9Wh={hQoM2NWw@F>RsQ)&#gP2bR$F*w>J~#V367;yU6}4)({u z0%I7+0=0mH>*=6o?HY3$HT$V-+v8!4Vx8aF`o^2#a29mqF&>S4jIsLQ6E-m%;|{t< zS0dv`b#e7HMr(JZQ`bX!RiY0rBi_`ytos{T5<-2voM85-<aF<PJ~_3_&L6THUu4T0 z)0@0x!I@n{E*o7gkaic}CXv$2E~<-*vzlME2)2s2B?KTu%-Zz3a*28v6ezk@u*Q9Q zg%eUAzTWq#-15`c0gVlsM*Uzr>5*fT*VN7;tSp;+c0?Pj8%Qu8|CC&{xLGa%g7g!3 zw?_;@b?3a;>5H$Mvg_rbUkT>hBiBN8wZU?;r0J~ewW{P@NQCl0@(l}By{@b?eknKj zRQ1lTy`p5b_;F&-xt6}FY4MZC76Xb_vYrXa-+$|UXX0(kt*8P{6Tx`VAzc4uLoOag z^@{#~7-?nEKwMXhxvalxUNT4ajX9^wCSZx|0RJBoZ(DI;1x%lqK4By;4i>P%e_Rq~ zvE%l?(BF1RnBVROLKD|^W#4S8&0}8!lXq|UUzo?{17mg-w$c4<5s|FyT)aZ!3R;5* zVf2=g3!23vrxMpLo4_0B-&tTNDX}v5+yn{GnZ|{uvM96L^VZwCe0AQdrua_$Z0Y`~ zH=AUV3aE9R%8!fDs3X?JEYwvu9zc7zSA5YW9#SymsXo#hKg?4#=FO;sztatG4?g@x zGn9`YyiWwR1*(joeqFGyAB{<c2MRC!4E~fVQT{LSHPVQ63Hlqj4*gQ{)OJWId3HNw zd(c9PHtz_`AkD_ovwXtTcqu(hIoel4+2^N@hKQdoLJqz`R_`69OSB{yZu%Sn@-8!O zK?i<bMb2-jpaauLlI;bpF#p2|@kHEy2fFo^mUz@(P)Udg6zC~%kYrswn`VLmaL!!N zk|-cMZu)cQ#!n1fK<GqUbP$8MOFJm@C-f!c20FUdd{l$8ZseXEkn0@d@P$Sk*fkE- zV1{kZ<tNqfZ~7&XJ>}+CWrB02vwe=6%hix&sM*tv$(yhw+G)xKW-004=nOer6LS)J zY+5N|)aZHLk#Z@64U0s&rMFfa^oga@p1=@r-;h=;y@64hMg2e3YqN|~2j+Z5?aT|h z-L(F>@Yjng1^2IW*XB$}ct?|RAIN1r_=Hs%0ryXE>tq=q)#ki~B>GnDwYuRG3gUe$ zeY!CrU>uoY^9j~#y6i|lZ>|3?_>imKS_xINUDK>N4Po}e{R_-Nb`FwC`FNwX+9&qH zxP{X}c2`g_a{<R1_Cw#$L~6&GaVf^-thSSMpQqH-Gxd#+@u|chj?#TJDCOautL<m% zyS*E@@&6aobE?|4m*Y#H7o4A-<FrMo0Ikw;&(E!E`fX@Z>Ak^LHDr0J-Ot97=|y?* zQeVQ|8Irso<fV2UC$hwQlifoar*V8ANl;H2^5|6;xg^q+d?Ok1*Q<?QMk@`|q9S$e zv?)<?g1ZxGpY>Ixe&m2g3&xE}3)9PtMt?Z3W?GY2&o>^IUu<dt$qHkyn=;p+$-ACk z31%?DW2z#I5J6Sk=u}**Z=+&t5K{HMRLlsYnC*H_(LGk6nLA@Mx+IUj`rh;^?Ntr% zIHp9GQpeJyTTfUjD_AN^_^pDauwZtQt^>g+rq0zzSaB)8O>d_fDMh7BNrsHJCcrm+ z_!_B1I0I=<;XR*&x2v%?M!`yCwNxr@Pk&FT)`Cs)c{n=-aR~c=a295qSbSDh(5NuK z^Nv9Jv(uKhoaCR~FuD-Q=<&1#@@bP#&FW3pBeST_B_+Qas{0-7g`dr^j-8=}s1s%j zmgPlJk`v#hD`21XVUMj6D8G)`>rLvmOG8$rwSW=(h+cKv3A*7am7Lz;G;^UQm|+VB z`1?XyhAgyb9J+J+$^o8|vPgR=*Ym|P2zH&%Vt(SB9^ehKh=Sn6f{8$uJ&{dpS_~NB z70gBjdxtX6)28OKDWbL$3!U?WZ1_Qj{HlRSnjZod&xc)}(AEdYX=1y2{d`v=M(a;% zDtFSjs++?8g3A)CWK;8$Fl>h$`ex>gWRuK-a@V$L`EHWE{nzgEu!acy-?%(r<+{yj z2FjavR}YRWM0MfaSJpES4YHsED{2NR*neb*^_tt_(Q9I&@eF!3hp=pjl@Y?|Y$Qzw zMx;3Cg$d!>uqh)<;%#<<VnANY3x8$0WrT1#ZyX^p89F^Jp&e*pK0fsw?y{t(MwJAO zqg(Zxms!Mt45(3<viOLf!}wXuxy2ocCs;a8RKyt6F@Q-ufq05ZO>m_q>Mb8z)XyI? z@ueKp6?!5fRE8kc1y$IJkFrvz|8qi+9i;_pOU%<!73e_w0K^z@Ivda3w){w3=W~G} zK<D#RFhK1@0(BWC#lV^XR`Mx0v;*A){MZCsCO@(0>6crfKHUjE9hy70${!rUsGS74 zjjPOXnQ*<NX31*~`uvpBOv=aq4dU}7$SYbhEvJt0KJ~u(*zmOY@h;HmEmN7$r_;($ zcg`d>$*iPa*-h#M9T%0&d%(co$xvmNYg#OC*WB}-_^U1^GHB@}oQeofGVYWJk7d6K zEAP4KQ&A#U!wosbZxf$0BL%cxH=knVE%v?|WhgIxJ5clWis#jzb{Sv93-b--bzbiS zVT{CX(nXqpQ&ezu$jlfe9l8V_ugMLZ4Vh`6uwomDL&DV|;S0h5S_BwGA#vpdW6;Xp zbY?utoBl<g#?Uii(DLMYdqi6d%6pR&$-woQ#>5&grzJ7*M$7~Q6K$IHo6+`!&QVR( z%yvn0N4}!GP|=1W99*;^)TD{*v_<2^oL4U_y=lRCN43y({bl|y%j~xW5%?nE_4||{ z;hQ#Z=@IxUjrF^fLN!*eZARw^L$eHe<_@$HtQRpXUJ$@K-{7xL_qD7g_KIIwEG)f^ zEyhM@#+-+t`wBD|!$q1l&JTG5tSBx>la0y<O(b7sEc5x<lk(RoGosQkKkzFdj&VT9 zH%?4u)oH;?Q8$URtUwTiGj?Y!W3P~?sFIao{6VOmb^haX<-4)@MVDP~9Z}@WGkQ>Q zHde@p@kJwl{Aym5R4BDT6Bx7_X>n`UzK7A0qcUEU*@!DX6E0NZ7(Xs|ZZqYHaQ&GH zo8unWmGb(VrXR>B1zpRtE6%#3%~|>;;#_q~ggXP57j74w^*_gW_hs5z=WoE-U|Qfl zum9pop0itpLPP50&e#23pN*{A-H3Ol0k8T$-Z&9e>g>dc>h3oc*_Jm1IWNC|5B&b( zmwDW4mz%EEDIwioy{xwtO`CqsRf*G6O3W+s`x^kYsmg{IU)SC=EI#*5{+YrHlhl=} zVrm3lDwK{JlJeL`Hhu3^XZW7+vz|@Rt4?HS1o6Z3#1=HCgVmur=0U;c(nAo|vh!hf zOe98hxbF0zAg1&P#Hj3igxxXHvwuWq%Fbizjt{<UE<Frk_;5Q8(sc(b=KTm$$_;TY zE9nmv+(tc9zPtQJzVS|5>buR`f}nSkrgss=`(eF&j#b<0LzsQsYzgLr=;*uO@F?KD z-E;k7xh;=bNr78H^<AXRKQQxFXX`_J==Wt5+wS+~CQ<LVOh^U{mL4V*XE?o+O@DW- z@ZnduSrF<PxpJ;SsP@O7LJu$CE7KP4Pge?Izn?}`cDgH8<0Ie<M8iE+?q}BjkVREu zN_ik2W$ux72g@#Z3IF0qrGVyA7KlXILYN&pNyh=tRL48Wh+;|uaFt56-;7dg=WYwz z{mM7B1C+#o119W*#~I+W`;}*^=U<FeTJL`&S^Lc}H3)W(5BqDvS`Sdd2MI1)h_sU; zZ9CxE>-6ET^)v7$tJ|*jQoRcWfh=WWVPl6#Yz~@->X-(3nmrFe7?BErXHbM^=s-3+ zLyA1?mdR%!mWD5N%s)nos;b4Mr5igH9!q!o+@t=><l}(oN3hs|Ccx4gx1`H5oAWrt zGs;FXVhdevEu2GmwFH}0qd2G+qYN#z)PKX-GgGz7EPbS~$HQ{w(>cEp0p4C>Klfi4 z<mmmEC@7KLi>*zEcDS0G4*5!4DrD}wb10qjB%WznC(M?;%!_$YlgX(-d&t#XBO^I( z=0ELVFUFG>a&j=-fjvUv$bXqmC9Vkfqd}~BRtKP+e?k{LY;Q`rAAvt!pF*rWj5-5T z#JF=DM9<*&eHsL@m4ABPpStT_|1i$VV=#GNoi}V$2U2<}e%5>f;DsbTCUEiD!|{?M zI7i)}M<xl2a~~x{JWPy75^)fx3Wmi#ssw);PTt#?ZqnQGve?yqUdKCK%2Km%X-Vg| zm9ANMa!&&HPWpbpm6G_iA5Y&y{^Zs1F_!C_`z(^JRlpDSpNZ|u!lkR}_!)!s7ka?i zTkpAY118W)h#yhdTJI3yK61-Wz=Pddl~B7h#^@GEcxT~RsNMXB^9=!Ss!G>>yd1A> zDLy|7VXZqqXoult(>+0QD2q%_ba0VL6X9?%jySMeTr(1baZm@%as1fB+tX+<wXbmq zh;;5)Cs=c3=)iV?p({h#2uR235^P)oTbGPonnvs9Ks)M|VEF88eB^<k_xQ%G^*TfN z${72_SxAx&)I)XbgQpyjVG_)cBZGQ1Rl>Ve*}aD4JWc(z2S2tcH$dBD(>*%nwUpl= zA8>mB6uP}&5lYA2B84$!T?nIvVzA+)lznYpJle#zvUO>D?<G3qO#%q#cr=tZKi9ws zc2s1S$1cRNFw}8_z3N!KVJG?Mitghb-ie;Pp1qrE62?Nvk0#N6!CG4qn4ScO855ON z>3;vi8S$@Dk4*>2WW-KqC6bW00J@yY#y%Toef2VI6WH9<>%7$wi~}VPuq7IYEm#gz z*H37lB`j}25xWw(q3jF$RU*U$3GCnDQy1RaJ(Hi=8Gn4})@k|^(%EBiSJaQ<E=8aY zgPwwAf}VHg9ghASe4I+Zw%f5{=d1vZbyjMhZ2O}$t~Ju9hoCj%CBCYevn7TNo=X3| z-17^zfrssgS?ISXCoE4p0=7>4wl^z|oRP}Q663_*1n@E3w6p;E^0Lwk#N(s{j%i2c zt+Yc$9Nrm+s2tvW(oGLG1&l*lDQCGqwD#-7HXLgoKjPSdoG=@-!RX$4wQ?Jwoc%<J zALo2J#NsjG%BI=B5kZjIH2dFh+BAzMIIZZW-!N;R>T<A<HBIjN>ZGckPHk~Q<o3WH zaAsH-te$gn;uJ||-VoTB*q5&=t6kBn1p)u;XQh_70Qp*TBYg3kj-Xvp3tYbbAHcvx z1JjM|3lme_rkxqq+`ce5b$;4eM;E*=dkgUFjsH}S!|dOhaUoK<A$|MWAac7nu))0< zlGP27rNL#@RFg&0uf@Bla;eR`$?EmKE=pfhPtI}qI-n4gVPt`xa}(0*%`dWEQ;*4U z!TmEVEE<Ac5L0%E)Dt5OIbhk~8iVKwJ+W~HkRlna+`SK?XH*RR+HaB8wMpUH(@<WT z6R${)Vf1Xd;Y<>;X8M6rU|M%pPaC=hrXh@-nH;hOWX6D3DUT#`dRx(fFpY%wz0&Th zox_0ge_2GiM(+DwcDVlFDkjH5awbwwinQf`JqYX%Z7^@!gh9CGyqM^UubNml%MXDV zBZSP5&zBk6wz(S0HSaZX=-IAN%Y#$mf8&_A5az+(z!6SwH1EsB?HIb^iS_*+-uv9U z$0?~{O^0{R^b8z0dde%p@iiOf{Ra_E0y}Sr%B-R1Hcc_0>j|dwKIin5+FIXCJBn=m zVXkqHxX8Ex>p1D9w;jh1d4Joe_>#E^W$)e7;Lwl4dl3T<XW$oC8#2;uBK6%Vp*-m7 zXnXwgn96CGVkiiyywH4~x&hq9cD^qv;+b}5*&08Dj3XiAvKkU?J$9&2-^#?<)~>r+ z)f2?%NU=WgXtk+{Y56SMsN^AURWWlH&BP%y2hWIE*}l=kd%e>RYCD>(p=x+dzu?s- z{18{>5SLAV5Z8S#g9Sy`23C8UiHeu$BW$xCPHti+Mw$oN+9A7**-c(@9lHH)?5kCg zTO*jAMWS6<BoxEgrpk_Ph#VTnJR&=Mf~t<_rY~mKCqv4Mpess)U3Cs}aD*KBbN1Z1 zR*UFdZlK5qr;6MC*D;2ye1a8Ll$#7Q&RH)AJ5RYs{7~j~cjxA^p^=3k-`$nGB)*r3 zx6_73HavP4%S-a|%u54SUJWD|0NENcN!OF@+*(GA{W8<5mfPFKGG{&NKQ6ap#Ml+s zy~LONC=82K&?145^o3XG$Udbs#)pP?-m4{nQUm?8N6y43S^KAJGJJZK9c4Ibx2``_ zID>q7)o!kdD-M!}Q&Jy}GOp`))f8PcE*NvI5Q~Ep;5^kCvy64P{V;D&Z><TrHP{+5 zbfE5#p>F7lhRt$e(8gr9Jz^+E8NTeS+(<GSX>hIM^PuJ}>Q{^*KhgRjQo~CuaH&CB z^Ems4ei=2qLCTyqQSpC4*obV9BC$9~9ikl?WXy>i+F&Z<3kyDU5S>&DdM@FAprcZJ zlT!vR6DQTYp9BX#0rN&ePt>;(CD_O+FeGmMNUfv+UV1L*aBe(t>J|XlZm%5;?Wl%u zljA3beEfm&OC8HIhj(+D3H;uA92?ilEPQ9K&5&hQp-E`zw5B67%FMjS>eWuez*i`J zPl&++7~0tg>aD}%f+HKf=NQV-YeN^oHq@~>GeZLacm~*FmE@MA*NZL+{8tza#!{4Y zBZa{Ilic^S3}Vz=eb^NHh(jWf0qY<gQw?kjU11d#-;+J{e${D~ImmXpCI$d~iU7@| zH+9VtNS~Slk-NP$R$Z-kx9RM_Jq-40`SEM_PA{t+2TK2iq%4#Cp^LsDJX!A3JEGc6 z?dkZ=Eyg-73uM@R5JgMjm#1_>Y&#Mb=7J>}P|2$c(>praO}zMnYS8EPyjaZX7n`_e z^TgjcNYZPW$eEk|{G?0=!eN^1peCk~W5cY>D<YT?Q5spvHoq|!$|d2M*Q)4W9R;Zx zbgt^3&=B|ZBX}&;nT1x(lQr%W9zaJiMY@~*?72(C0Xsx(j0JRgUP*s!iVEKeNg$Bv zG~I22;U0Vw!bezIEv?2vb7<4c`ZTIO`3J4uhP>+8fQ2Gyq_^x@t6|x+10BlY8?4zE zaqBN@cZ)Q77UC&DD9Ue+XV&E;oh>W)w+T72VOS;=K|e}DIsmUkB3&uZ$0fgx7zV+Q zK-8_D$a3LGajw3{d&i%+cwIqj<`0SCrq7Am<p+X+r;!OTFmN)P{=^z_Wkd49NJ83x zNzaC~3+))1ek52b5#8YcY@h0Y?VL!Enp$=Qgv53vEN@<rJO~db<f_D2q^-(10GVhU zgBHyp%p3e=xncCfBu2zaJ6E6E@;@O`pNpZ13}Tx@*f!M4a>MDdI{;}QwiByXzLjMQ zkjunQ(8b4pLz%M8YTwknAPl23qd>%UE=UL0%pU9N9`hn7pKe+a+6664MaUt#>ekLQ zHh#vZZf+k3fhHFiPohvL%DP}<V+-DDbDI+cnpilG2>v@{rd=FFVM5|isO9yGjg9Si z{N}bO2oy;dCE@q`GmMr^|18gTy+LjjfSNKpzA|c)1LrEL@($|u^9o#2#5PRTKmk-< zb24%5e?iimJh3K8qB=CO)AR=Sy*U{Z!nXl00}_YW0WlNUw9viBHr%6s5``k67hu8+ zOrMUn{ro&8VR}*;y_Yz&*GUR>+5oE3q|)gLFzPX~{^XcReN0>3A1*p6>G94RjzbL} zN#lQP{HZ{u|1nPcSWk5fBzLSdKACEe>VN~|$3&4RpG{GdT%R?O1B6U=Spc@4%2Ag$ zMH5g5a6OR_y}Tx3k-NOM#lZv2n~+oAc^sYFPvI90VW#m9<~HwM(Ex^LAA&FsayZC^ zWna?Z?{r}vx^a@qF|8jyD)*drW!qFH^Qn_s;v?Cl-Yezloj1;?T0ZT$b9(qpz8wR3 zcE{CTK89R#P5m!)Imkt3b3;@I|J$5%C?cA24l+tub_-lHit5Qp9usI(dqYvWHlg?O zi|&P&&_CtLpYI^9wWa<SwqliYmw$3uZ(mMne6=jBz8ldF>fhuN4K<oVx$f|wnm#r) zg>Uincug;f)zI1-2-Q?EYN3ypXrQUIm)o>rT;tcd^Z!KS03NDN>nq)4C|-)NJf)iv zT!bR`Y(rh>@Fe1Sr$Twl@Nb76idQ}vHkNpO(0f72>E4Zgcs1%~L9z8Wp@+bLs35a9 z9F6+F2WP%#i(cz}rEv>ceDzlYaiRCp)~$=h8V9pPw~ME~nf>}eTsVI-u=v@XL*Elb z4HaJziCpX;txf$mw+|Eit&4Bp34X`V3ehPW`0(b@FYbWcXM%`<BF5yA?qNc1^`6|O z^C4Z9L6PQN5l>)&MSGS&z1r5zEmlI0H<p{)gS!(!%seA~_Xef+ORlxWEhsDD(OP1h zetBfFM7(y&&8%b=314sX_|$J!7)`lB?e1G~#SRa(F2>zAOBaA?W4cA8H)o8IqYY;f zU(A|n<~8}~GkF961#8$8IJdtr=mvOqvLFGj>FkQD`Ofw#E77-XyF2{0U`kThpHnpm zKx)G5%CfC~PB)dT2T0AGU0Jma0dyv?Z*>`j_&(1Sp9WdfeAAYH_DmSTMf74)mk%>$ z?JqkdDs<A3wet_AYT<*bdM_+iP{xt9>kk9fdu3b~Uu0Ykw>wITa1g$neA)H(5i`!b zYp2xDJ(i6ME{?c!SN_Q_!)xCF&qf7}$t`nsCmOg4pvTsfBF2sS>y88o8<0=?y^Z_k z`HMLUWkmVT2c%QJqcpz9i(ZYo4cni;aiE1SvVW2qG{PuxLT;7CMA!+C@+nH3<bUH& ziV_?7{{miYDlpjAti%iPDT`4<w{=}w2A+ipBcVROv8E88bEY4CI4I>3_V}DNv!3ZI z@YB05%(Gv6S~}Irq$^!3G%e@59$|N!l;p6#({1n!M(L>)15r|MC<Ou`FIpCE!|X&+ zrc(iK^-6L0H_Nr^_Nna)Uw?<I2)7(%o+?%E^DI@W({H)8<qhM%JTFjnNM)+y9(3-6 zh?Lu<JW4%N;N0bEt$Lrg;md@PcKunT@J~v<xc!UP7+=_}_?#~|%fKLc3yYug#Q?pR zMMW##@_he-#V2~#C*aVA+{mu?3Njg(wX-MI79c@zZrJ5RG_Bs%GSN0^E6Ddha<$`a zT)ama6N@o4Zb|aw@vjmr?XD*rV_j5?uQIN52-CWJ<ysr_Pbwg^UP>OZgs0ub2M{Lj z94Wf2CD>AYv>|Fv@rKufAg%$MwDFcTp=i4kkOzZN4}_!b(#B7h#WX81*Bv4Kx5+Py zX;I>=J4^a6qa3qbenL40qr_Hsg7jzEKMil47HP69rd7#vJSLMmInz)bsC-}n=fa^J z^`=C-7KIloTxWVOUqjza+B>raVj$q%Yx9@iij#EiG8SWZzu3JQJ;1a0+x{=|3trS+ zuPOPBin{A{B@7_7H{fo%)fE!9!%GScBNx=(^xk-t&hah$k{bUL!;`$>I!E8K9AM@` zf6w8JbXAwa*z|LblHF+?sxu#B0~P+Z+$7bq?iMAkIt5bs%*XfX=S)G?+h4v~r8JhW zz5I^y-M(wy^kv>kn=W4j`q^_sTg|es=S8xmw)V>c6d?HL{CUuqyaNLqxaRGBHo-7Z zT%LF{yhE_ZgVoQ53CXE-r#UYIa2|%et0E>??;iO-G#gR>4>in2FywQj{nQDhgLp)s zc+ZprxyWG<Qx@54XXIyf3}Q4W_`vG19nSuptMc87RQX|3K`-6LGxE!M$EE%QNn^LV z?BBgMeChwTocC@a>Niw_U(T1@069xq&G<M6e|T?r*Z=J^-n$oQcfH?67z%E`>$i$( zlwZ4x$>Zd`8;rfvJM{wkOFLVfT>TDE`eo{!&Yku8)~SbpQrX#uzWdnlya=z#;JrJL z_fY4KS>N|*Tf4sR^Cjk>fbDk!R@sfe*6tRebb=3})jwJRKU5Mf_BitVwnQHu@rT5l zEJ)GDmk&Epvb-04-WGRU+`5^}_c!>F8Cu_3@`QLRdu}VD?{q7CSFNh-@%YP{R{ASm z!C&@Q{Hzc~JQ`v6B+JnI2<Fsb<Wcd<-ba2Kp5@IeKhk#Un?h8^o16NNS5Cd)%X2yR zd#QpJa7k(Dxt(Ussb=~Bab(KygjCDs(RQSYHa^AALmMA$CkFA@emG#2**LuRy%41l zTsdE22$HCI43`~Mo5<n7$9ZE9e65scYSe;pwda*N<Hyv?k3Fxzl&=gr9|JrkUOQ}Y z+P@$NzJR-vP#C2C-Oo$!#Ja<`$Ximz!Sr`n{5FDdVahh-PO$E~Mmrk<H(s-KeQ|iZ zJnn_Z>qpYPE;1pBn?{quPeC%Is~M-=p1m$+GUIXjamh<`&WxqO?Ug1^k0Z<KU_U@( z4Ph8^aoS3HSPVD*WWyMy*;03GJdWZi6JuQN`WMbxU+Fr1UFcT%lO&@T4MNT+qapWO zkn1n9kGJ95eLWRs+iQRPK@eMjI|h3_%3=J<Y@ez580h&ZMKtq`tV{7z>xX})WTgGu z&fVmfc$jZ!=KuDoq-NBZ0K{_8>;c2XruM>y{tvQJdjl%8$r-Dqf8jo*l$CtH^G%fP z{pN>EC9Lm-%I*(ZC@vPItazQ<OMw`g*5$n!>;LNM>ZV!oBJ{ju)ugF=lgDD!2e(IN zj_#r({e#i%8tR|&KJvtQxIQv;6g!AMX;pkjeWHx4lzdPa-XcSG>$3MesZDz+X1YTa ztql$4l~5}<9IdB3++C&@x42%_Kp!3t@kj_|&(hhnW8cwjUU=0c;o$%6Wqj?|r>WVL zd8bmH`G;V;c?Eo*@8Uk<Qry+a1%XnFRNPX`Ot88=?swFSQ#TnHjhazXhvwCA_1eJ( zjKH;XH-rc69H8N2tPra~y9dyyF~NVDu^t0W`+%vt3=ANbcF28uk~8nv$w8ec<PHNx zb?{&A7Qu`2OF2tR45)9cl+L#?Zr3BVjWEDkBK)3FoIQimGso4}e$d9fgIec#iZrtr zW}rVani1k&>eqfXA#cywNi{4KK!evyQ6ft*aFE()Dk`|w8zi#+y|poD(29>XG(tz1 ztglLZw}8+|aUmPVK<l+spU~~?0eo)b?%H}0s!5lf;(n-!?Vku!VC(#ofv*>yOR+d# zxGBW4?sZavW&Xs~j!Qa>^ysXC7GF!?(Y{D;$;YcFv)Cs9NA{yn%4`e64zxeZ%z1xw zVYbx=8&5m}aeq{frg$779H83kEgbo4=w^eIe0N^C_-{P?gxqRBA)9$(FLsLnbQX{< zI3d#3dDhtYg6gxxTihNODtL-Ks=+2Om&ah^|BcsR;}u64;6Ci7mqnlAuhtt+UObLU zgvCA9`vUiTK^;A->%^dN{cgk(Zb`g%;lh%*bjinZ(eouAbu@m^+};Q4{%Dk7Y+?dP zAX~M@M2l=d!@{7I71OOyx0DW=xu`O7**A?iri!U^j(~O_CXaB8SMk?-$xU9s1@k-W zCZ;^CxRLLCTrt@-U8bpPDT7qnwUS8+23S|gF8pvB%OItngX{{7rRNt|?u5uIS}s0w z+eKtRG3rC+tv;gh13p<xx}LS<>iJDGs)XhkEx49S^C$SI&E;ZNMb@yyE$*CuAqd=@ z!Q?LcKE2GPC4=MNrqHV;9oAEUb{V!tlipiHekka=3!%XCg9;LvZyeG7k3Plsrr;k1 z{sS0yUVA@EM(dO|Ag6Vz212*33n`^e+tzuNj%nf*dVhA<uIl1<`Yty41*)ZLuEMkv zQW?N1^r&&I_Ot-dDhwN`$F~6({8;Arpra)|N`i}Vfw|TXP1E;YDSu=?VXWbef!SE< z)=U7SDi3U_W-I4zsoI?!VEv8lnoB_8IY!GwxW6uJoOMm<6_lxgYu@fE`ErnOi~SM! zDN<C~zs!_F2PQsJf?byvB2Lm8^eOv0fG0N8cjj0-VHF}8I!BfBLyys8=0I2WPH#`m zClmp5c47ZvH2IfZPLJPEm|6UDwPFyU82#}?`|%T|4hrEP5AU04^cDRBz^Wf38BU=6 z_Ljm+?BDpl{$^wDHr!t%))}VI>L?=FP5C3bLluxR@o}`O-<NQ?`+)-Tqj<aTYPonj zr~U`xz<)rc<b2OBPBQA{IOzOVMUuq<oXc*ro&P7Uvz3rK?ru!U(|lgitG|TUI!mF- z6RZZxGCE2E>ocOikF%C6rXHr9!Gv6+C|x}e(SkYj_-1l*?%`dTK|y!Yvx|@)qLQeI zWzjl^IJ>gwPZujbOkhO^-5pTj*++DbK~9sd3_dO6e<0Ul{y5u}@652_(=vREJr`V& zRQW$lvV$DPJR*CVCf!9fNs>r)>NqpRe{JJRl3t>d#e1~ek0Jhr&Bl20J~S6#Xa)|J zISO@7Lua~`tRY?HrZaY`<fOpV_qknKGE-&a`qo~#@2f0+OqEF@*R|evJZR9X%V}I+ z`%vV?5-c`1;$Y=bR-!R@SInu&V1ofn>?8jUW9UBUV{d=Y8ok%-3QFDw`n~1?&Lv1= z0G*!GTc*)E%<ZoBUa_|PCDJCa`ri=T`>^RXHK8Ht$-vg5)=;tC5egxCPh+QQ*;|ay z5|-A|DzIZovG4&u)3qE;pX?KW7N#u=s5RO_t5&`1W+5<7<X`A-XpJ9#U_ve{fDYnx zNpljAHC|nvmqo<@v!8D7=(!K~iiY=!H$vapTK>#<W+_j~E`zp=bHL@KAd?mRMcG=5 zFBZ&emiAFN@gmwX1A05dc3?U~7O&p;dihM8vK!(WIu|k&Tt{lO8@H>guY(L()FDzy zD}94Mvp;t0I;KL~mB_JU<05svW1e-+RSjh$_JbbEq))<-5w5z$sIiR}Pxym`v2v3p zD&+y6)CRGZ9j{ltgbCm)g?o?1EZC!)@Fem@8oYPcK5&UqeFkG%?Zr1HDT3stNxD`2 z-ZLs_qKR)Wc$18-qb_?(@lgXIxeXsJQa9$m>e~$$nbHE>nv@ptZ|HzgY%ATxv1w>9 z0UxqMoobTWV{w@}#K%XW9P;9&%rM;CB2$Cjt19-jjj(aaZzGW#O9pW2NiW`&ncsLd z1aw7-S6J~5*Rd~-8P;n%ktJ23$Z5Z;UVQVNr?z=<&?k+CYZCcnm0;w&?hV3&ZQcRs zA11sDoew0m-%BF{rpw~Raf#Av5_#k!!6tLME!2Pe%Y<9o@n4}Y8VlAW-jLst629!7 zB_yoS8Tbl~ZFF>*O&ij7fy57aboBIHK>PKO#9Jp$@OF4>^-WFb_>Ow&dumEmWhSg{ zYVmgXXerUA%7IEW{&L`{e<8e;L)@I`&5Y#N%6d-cpzC%`B?I(-!>uW&0%WnWDU)C^ z43t~UwcNm-qs_k9%`OL74Dl4f5MMmCoY~CN!!2EiFGRGQHM2g6nP;{R%up)EAj6(o zW&}6M+?i#!ZSw(WMxz=)-;o!a)~Z$;9NhtiA&jfAo#fb^zJ6$QBWj+O(TEB}q_m^e zbKWe!56S(GL+b?HGr|6vvlhjEh4sZ|PZ6|5u{fA{Lf<@2TMfcUk|(r9a*`(kMRHOn z0yk&Z=jyeaniIHosu|FM8q6xqjT&Xwz4a3gSjs2ZuZ_g)RJ$tMRir8no9;(_c3*2u zb)eT~l_ucVWK*4d{|2SuG1(cRJO#HNPhD<^B|D2NEwnl7u9x3XT3zHMlu{1xEZe)y zvp%0{wF!yxI=~j>Woe1O-S^&-YWs_DtKRXuXy|v69m58!W_a2U#JC6f#DVeN)zPgN zbL^&u_R)H=p}JHUzdl)OZ`(1U!;AN+j&BXnXZYHoy7*R2EkxvBn3?)}SP7TwwKgk8 zugL>y_H^*9`m`cORireX5ti+LV?eUjjc-g<x~gYh(J!bwYy4}TjgG%5(sOxINV1Aj zeI~(XW%HgS;medwAi|yfFO}pHe$7^GZ)Nv|6rl;}UF7K`rBwf#*WG8v#0xW9{r%EB zc?WtQ)N0?Dh3b5Ox;7LPLH*a_<Hr-XBzDNeQ1(6DO#)_*cNa=&irKT<Ay0-1@6~M* z+V+%oq09e{;G2ZjJ;_}vr3tyGw?m!?<zuwr32Gqf+H_;iC_b4M<O?#U29O&A={YIn z07`hM{;T=$5Flem27T9nAX&R-(nQC3g?t;3T3<8KqhC`F$zPYdADX{@>_dWU@RbGW z`%<{=CqGOo^jAiuv3d;9Lq2zOAP}U!jwM9TzWW<xQmrA}G!BwnSuUeR{<mrAkV7E; zLJ<PNNjpa>D$8vN`G-k22M)}Gb?7&Wa_867;KX!2N{=MWlMjIZK3ltOYn8k3%g-J# z+vb;%Gq9Fb2y)tJk=*&Nuv6I46u1F}(jUm}Oc3^_S962tMfOdf_s;ApFNZ$eGu;7A z?tOuFgH(3Qb$826_f~p9Ia}Roq3Kagy)6Wn2`@CI%6fA|q5hK%XygNG@drL=`@RKe zVcuPLvQlDsI37k<A@+tHnl)scS3Tx7vj%C`?#^25J16)5__`Nxru+YY;CHEXq_f1R zTSX~yKFsJ&(g~F!IV?HlOxQ4+j&>JO2{|W8g%LT9Erc9q&U4z9(-^a1V{FF%gHHE- ze}Dh$dR>pt^ZmN6;<~!7(rfSc`$L|Cd?PG!rDc<M44%?%ZUlZF{v5wJ(W^Jlltyub zw<Ka3ha0VAYrBT6V5p7$>?gsR76~_vjnW^slEhhGz?KPijmL&#?r2bh>T8Ey`2Cq6 z(s<FSB=5*K!e&+bTLZmY{8jAW!_L5O+VIWZ=bV;pIDT>X^Bs-FsIJ2!S75It@ryBt z#UV;?F&D}dEXTrLel&u5n`OyF)|Yt}bB}RxLzKdnguGRrxGjA5PEQlq?2I~<LhI?7 z_m7v3osE9v`5TVlM~ybauVo^G>j$ZvdCNnK(Y1JoDNo7*5W{`cwG0y^8ri^iz&4RZ z?-*(G?$)|5L<y?NWBJd3h`50+_(Y&np%3L52^=h3I>!u7JPF)R`KYy3eBh{;x+Xed zOhk`5FpQWFib!TnvLSKQ)H#6r0x1Hkd47q6SXzUs(_1YSLacM+1s}&amDcaAIb<9) zeTf=AvUG*z<uYgi6?m(l);B9ZDd6kg&D8zMy5g&|cz0NDVqUlid8cQEq{Xd;qTc-f zO@tSJePP7N!n>r_+D9AwRYDsbo4bydL>j<zM~ruqYhQyce249VbUP9w{D$qwbJyVi ziY##UYRdd6MZM;F6VBA~rwMCjWOMY+`c2HONzR<LuacF|&Ye0UpJm}pIOl3+<1lm; zAWcm^tLqlww5$5{yymzk9d4f-Q`IE0y6h8-ssXI4yV#mTpzC?9afuxamBclM!MS6= z|LtlqdRiP=^ul0MvLr83Klt{DiHM*!MNi9EvoH}VL}`evO;MCZY7wlBdAD0)d>-mU z8&$&R2nJ9E-tFd?P@Gj@^m*cKx`l!T?YRTMYeg|+F}?nYzK7)Pfu|DaUd_Sk{Td?0 z-d};1)Nr4-l;qU6r^09*&B5~hq7m$`iV^cu%hV}m&rdDW?G!McS2|;1!#}DR!R~)5 zh7QsktlTdxGUxRbt*<LNb<Dd!>vp5;aFAw@3k$hYM}|$jXMI0ZqD|%|4omAs`JgNY zV+;Ul)bNm~#Z87>_CTC8X}*Y7lm7>1t=F+TuB)szja*-4E&s}Ot#8&H%&yNVe~7I0 zlKYCj7bN$${$G+C`!7BfT|0MiD-6hWufHX)@<h#G>@d2KRZb-{u^8lA*JOG(5XGf+ zRbrC63?4FGpDZyuL)u8czF&7|zy5xUozD&STg$(3eaK14(cSqr`#AEUUseugS4VzD ziCL$cn0n7c0?angdT`6|j`Rom&~3cOP38}9e{y!EWUogWjL4saUgAA&F~8Di5McfS zzJjgTL+hQeOPy6W#O_;fhJD<c9wqdzDQu+zFok73W@DBqntxoM{e5|E0<(to4<1Ox zG!1OmzH$<MZuH_=O4OH>10n~#<sRvul|0vfaXb3C=8G>WFGQkRQZ8%0s7To<lIA7% zQ2(&xxxR}V(Lk#@MO7qiysCv#pXM#+9(^u8t>t^ud;ORFThS-x*48ODVb*_=Up=jP zF+zxN`IW`S7f|uJsAvD=qkLWGE(gYAWtf3D_I0N9rH-%{YBCOlGhGXfr-Wg@Cb9$G zTD-bu^Kjg44lsaCKt-o!OCpCx<PD(#yt-ENB-|7yN+W%U;2a<oLm~o;bYM8U%j?}8 z{k2PD*}wGUN1WCQGG8U{;^f^!0Uv<eZ-74KT0bq59z=@Si>~d`|EqLUzx7t+U!1kg zVyB?T8Ow85Tj5HP5YT4u9vINz-J@s7;U9CZa&VXtq;)gD<TdExCDbl@#u=yq_|<dk zYqbiQ_F`r&Dd)7WY(SsWyi$>}T_lQA^jylkK<G%%s;Ie(;-os1c^B(Q{p(!n)#`j@ zOq6%lJ=a~x?ANYW8!qp%&H$diS&xr?`1*Py=BiiLk<br3oA#qu)y`ifT)vuj<!6-q z(0`F|^s37F_8aE+t&JiwYK!9%miRG_MSmE(=m!E`XV-3Pj<yED{Itvq(I40;+R`o) zDeHa`B1L+Y4J=2zxA0t=%$G;5Us9H*v5)kPBwhM1{%qyjU#c%OJ%-Fan0FmzUe9uw zvp$B;7=q`|D|}&{wBP+Ya=*6tGWT59WA+z?jM)Ee9MZq{vFkg^gSgO(KHFRrPC9Hm z5_%E!a7unN>3HnJt{&T&>o1R1*l(kOb^zsA7}Awx3v+eH<`=L^yNfzH;=2P)Ej?Yv zjNDn1-8c&u{^@swZ0-3EsaU_+>osm2eXby@u@Q5S;KO}a5PlPB(rW?Dx7J*&bl%9t zdc{=$kMIr4^{6R(y_F0{z9PY3La#z0^tjVD+R@b{py!np>S}E@)-B^Vcbz2l-Zi34 zZId72q;=j!QbN0$)3nz+v@1k%wC}noI#9E%GDS*c+AFJu6d07{*)hh>$BDF&?((#4 zlC!7ht}i1^I%6f{{bbPf090mfZ!PHzD57oh7wdA}_w@jLCanuvV&3I*_Bu_~Z|3?q z^)LA;iA`HcA-V2yJt3N^s++bDP6D&tFZtUrPZ(*Z=Uu*JpPsoagHr1^|HV%HYX(^k zWiTm!PBfJfE(Zy#P}@k7vr6@HcaxHcuc@Ye{3xYPGq<yn80fwxym#z`omKp|?o*;a z_~NFfRA@BY{ow7PAoqK&rdIJ&`G=t^#AUs8%y{4B;(}Js*N^W`Auz%n9W!FPT&hWq zLGH_hxT;vi_jUI!4yX;g`ry<_BwCPrBZ*eDlmPD195Wt5n(n>bJ@5IK>87~rBPTY2 zZryd=1aT`T?Jg>K^Zp>_n6ryBF~2R%EZ5`U7=VN5r(EIdT|Qaf?(VXM1(B9LwOMoB zaoJhZIr&lrGj6Vu*T-xnAZ{`}>hmr_*ewk8pj(ybe=ug<W#;Ja&;j6AniXC+ZB35G z6>##S3@j}^wMM|SyNwNd`bZ*p*ld1HHUu?3=^6n=%xiyrb$_$=%WM%|%U@9Kk@Lbx z`YS~cCoL7{>kBu8!#P%lM87u~GS(pasQs{CE?c|HA<_3;q;*HF!kB%GUq9Rl1y|=L z60DpcOgBB>jwg*J%@z^hF>j~5wyyBU1*xycTW`f0vNf*Lnkm`Muq&THyT%vCQU$@t zPm9^CKiLY(OXM>CtpCBy=#mj@u_WJiA|{tHnuKA}X-OW-l(d6R!}pMFebLQ80I@_; z!C}mj9--5sdmx+?VQSz+7C>Eg`uqx$@5CYkCsW1rek1-pg-7bSFkK*wU@x6Z80fWJ z3><@c3dY<EIUg-~BbL%W<Qglk5(zomjFtv4G)4}#0SvW~q!_MFTs0vi;RIBriL{y1 z{tU+>nJ@B2p?ZQb*+`Tor!qxaMBp_7WMw))=_p!1Sd!OsOyE5dv6Kdyq|pnSoS3u0 zv7DINKOmr2@<P52calV!T33}QpD<rHQul}Cx^Ktthzd>L+$RF?%4YK?m37^oLeub9 z3nE`^_ermdtNaUAy$>ha&);Vw+CL4TEPtO9v=wuIQ2QF@{?K<cgvV$%EH+11{h-=* zy@<Zoo_m#BB}2X)e;}$qyM))C)rj?slpJ)0l*<fyly*^fvzm&&_Z}A;bQ~$g(fuWL z3ma>zxw+DIk4UB0o{-Ap2-lZoYGKgI*<GoXO4^dC!Ai=Z&n&`<!<9%t0-$N1Mx)25 zUIK|mbYIXOOmOA2r>00HVcbhHB%a%+xmklH)4*TP)~zUwXsX?&t#xv@jJ?t__e5o8 zk3SccnVTra1!GvLz8*UhQ*Qw0YnqE9p4DHI3XiPP1oxkZ2h*8~bm?p&@Zt77n+u=v z4$=D#KoU;19*A2>U-)O434@Kb%mhYbZE11?AK>U>Ei)G2cH(NMjR}X9WB-i&#rx8v zy0PDwH6EJ2Vq-EL{&Ezg)XsN{>xvH<Q?*K`3slRJ*CF;YoO9C4la>NKC%rPM5ls)& zv!=At<1yUUX;cZtBxb-@tMTc;X0680e(MM-x03ePh~G~5furZ!u6SoI@eSgTh>G{i zN0k>O9s7^(K*wq}e6igvlIQi(fO?eY*sKwXv)~Y(SGkE3qbL81x@R64TvO)L3$6h> zg(s@jND`C`eHxl2#T%QGwX}5%Q9h+Uw78*S#{djO(_E1@T4jas!UQCw3$Ymw0$>$7 zl!n%a0VT&xM2G3sItb^aGF76@<NTPLLwoAuuTj2C9Ws-?IlX^3>?q^f@+g~#hDgr@ zb+T=V!+hZ3oe(h)Bsn~wDP6NxQ{l7sU1Z*8oW%|5(Qo|KJh3MH3F_{zsJjfYI#ddP zuJK!MN6kk5!A1>(1kcBs$VaU)0PG71PP=P;pLJOcl5@UdZJ)s_|73+2z^4Di25zH- zPS`wv>rf{BYX(3OOM$mNTk#j6(+*0EsvI%4y^_i9UsT#`Mkp~3=EQuqS&i7R5-L~+ z=WV`|Hg8kMS|Tz{#{!_F=!NWgznkxkkG4N@(EfNqHk$rLIq}-t9reC9W5ul;*Tuw^ zJHYCc5jSEJbFHY+V?DR6tuUeWe%{3j3Z$x`nJ>3diW<~<0(T?3>>gE~e*G-zT!~pr z{&P%}Z`K=E;0K<O>kg;QVxL`gwBKcuF?ro+*rg~Vpdij^gU<PH7ORQd2cPYWSQBvI ztIS_g8>Y@oFfU9ro|&LrA1KSOma>!?Q_Hpa9~ieqoC?}8E%UE&_4@x~NKL9Rt^jXf z9Vm^oPdqSoAnCy5fk(^(C6Ob>xdWuG$uY*PA8cM5j7kLI8{M*67yWW=WXHZ^9PO8z z8R?L?87vM{X4qTERvL#S9v!n!!VJ>`EwW>#f1t5AM(7C4%cr<yX;=brU0!~<n|qF> zdgn0-M)Vd~J<#|oLVcupU8jV7*`*GN@u?@JJzs%S{Qu?v+en%Eras=j^lXd<ed>@; zZf$~_vTVFP?kp`npfDB=U_pzw^$aPCg<H<%Jq$Uf>Xu>~it}hD9pjZ4Knq94%#h>{ z*_O_o=PJ$i7PRC<g=DF^rP<1Fv7F0$qSrIK!j>6zR;s(Btpvk8r?9KOhcUDhp;cvL z{4vI~;pAhBGfJBdJMK4dT3I{`e(d2+${H`pPt@xfpC5-Uz`()SL_E2X>M`tzE(6Vo zbb@cN?vx3wgr+ReeAoU(&=ht5;+47dI=!n4@25<nf<IU+F>gAQ{K4{lNxo?ztfep# zm&h6C;K*lzTLM;=r9HJ+Rmm2wGnM<dpj8FNt*qr$<fXVU*rb=3D7Od^f#r@+q`DYN zV~7TxR35G-lLf>foOw34&OO_P)jo#g<rA3{CzJ8K^qD@KC>L48(tz>_BosTJD&Ujx z0KkIFf-j;#S|@5&X^S*@-w7A;m3%eu2T0iW+ba>tw!8PWy)FuijDG$Lr1?%rcvA20 z#pQ(d{kAniWO4+6{&~MZdkudpLqA8fT=zhFrH*z(>I%2DkET~@dtDP28T)Jt(!7}z z@$zme4|RnaG0MM$)ce3P^wxPipcEKB_Qg9<6SG6s-|wWNaldy9BjFx$<ILgC^bx(G z1z@s8Yj>7PxErvJMw)3^`u_REmfO+MdB+=<AD<G`<edn73pT2wG+B)WL@hSTSZa6> zA(HGf4`Ic!leE6GNx9@31>hA_Z2WB~to0yOB_^oG`gzU40IUA4gGtuQRI`)`F@4aG z;I%WmI?ZoD?;@i#%*UU*!fMs9gL_L|VIyiPzKJx6S@IzJSe!?*Z|Gag;~wQjLm1Bh z?lDD=F{--&n-xqgW`p6Vnrz>Iw0e1K8@g9ZKwM+1FDi|_w3<4{T{u@WAR+~yD7s$* zDq%MHp)p`)i9TsL8-~E`{mqHY(Jt%a-u66fAZ%p;!DcwYrx}<eawGww&209L2uJw# zrVdCcGAH|`l3BI1BsXR)O?RB@;6u&q)sW{B>X2H!F_kO$pr{GKo{e}?F^ka6bsR_J z&6HX2ZH%e)bOh@uYy5i&!@dfE2k(NWK1=EyuMusS6w=lGHUO})@R`5wv2Y`J@fA_; zD?^yfzf07cm=o?=*w-WNJ1lIW^9e8AO%)wyp=Y@Ie13{R(1h(vfmiDLOm3ag?-aFN zT+cV`)T>z7HWQH({6HYXkp9`)Fk_MvT)~$uUE%wFRlUhU*(9C*TABY3v|2lq9*z5h z5W$`qyUqw(y%52gnH`-bH}vlQkFayb6s1?iKTI*1L_OvLd1#qh(<GgtT9qW7fuGzL zY@Si+B;L?l3O=30NfhQjF<?3`cD74*Zta5NL~yx4j8fJ_7t<D;OoxteHYK7`S`~eH z4~_B5%?#tk53Tsofo$GvhVH^4EY+SH&p_qHqu4f!1cU&N9fpJXa6F&PLXmp(I5VO_ z3!jHYRVLA~vy~U->BL3OaPSn@WMQF}syD}%4PN{*`D5`MuQ<mCfGoDK6$x$URi;}m zl&P8mQC?-b?n0TeX?DX>d|Y7usqFQ56r3T?>NJOyLyHz3jzKAk!2$UBs#ZLQp$Orh zCoc4pp@B1ECW|yWbt-T?mUP?y*Z@fx1pwo?7G?M0P?Asg?`wGkTbZgU&*Lu`OQn~Z z66u5U+n@GHD>Yt_E$<pnfJ?2hpT#>Gdkz!tZ1&{%Rf8vuKloG^kIiB=sD4x6U5O!$ z)K%ij7hus^J&C5qC2Yirkg!GXDXqUm!o|HCG%I4q4`?G2LmMmaY+l^#rR)1xvmF$) z@QA2aqvhTB7HGQkb9}2cHzjOo+&^5xR^3-=DW2eFd|0-@d0?~e1Y#4u@E4N^34G!I zr2YZ)(7bYA%m)00S%(V69jMre`ZeGkj0-s`<qO=$z}KOF3t~3-Jx@S3It&M#2!Zzs z!m(6uE|`g`Ap<X)2f^_J%pXlG6GbAkO8C}r{1_8X7GSVcKQ6X3fcv*h4SZ;lvOEAr zJFzAikfgGjJg)ytQc`KUEQ@~D5mK8e8#{d<FUh_mvO)W~g`x7;8AniUrVL9Fm=Pu+ zffqO;X7EXZY$rXru~V8H)bX}hW+resnR1YSeKR(KLz5|+`<fg)NX(mc+PyeG3ryj5 z^!qQ^5rY|X5duNYBA=hvh#bCpBE&=)yf(287(}I;c=6V(kg4fVbyyx^L9ab$ViuU& z5*d}0$+1scnb1mP=T08^7x5^E)@(Oklr=tg%p4}D!$7;H<*_ISQZ@r<3g?cUfPubZ zgtY7v^sE1Y5KN>~>&Eb%#2ql>PA%Kv2md2%f+=(s-x$7^_&u~FTk#^7v+Zz5q6EyN zv-m$D;KuOXL}8dz=kKAJpi>fSuE8F4wCN169Ug+)pnjmcm`DsBW>e=DxKwixVysm| zaxVDDqRG&rvwS*UrpLsA|K3e6YCJtxaHU|*As+f2a+EX-)j4N7j86RCT5E54qF{v^ zVt1_nfUW9WyAuBDTx%=#z#164{yWS#<p6)3h%<;f(68)=zrcCjOtc@qqYvL-vZ>Wt zGseziV|;u?Aha_{&dp?Jf$YYf9S_GJRp_m?mzxrm4gLP1L*n~zkm;%22KJW#94=ki zZ7}}m^~|YDh}Z8Rm)er#TugT6%Ra6vewPs1axpCArs~erls&<Z=_n<#;#+<dC+{U{ zcWcT`?JEg0{h!3RRvTiYK9{Xw9`sVQbv*yFYrA8?gV<xs@p7QqIpR6G#bJninp0XY zv`&!5$^4WQ^)`*8RFfp<Zn6e9G;wGvYTx{c*}D@$eZm!@52V-YZAHCGyjX24XD9pO z<BqyhT4WF|rVk<h6AN5SRaqu3s=Y9mXJ!T)vNt#W#mtaB)Od;Th1;AMQp{A+`){!u z|4(!_-S&KnxZf)=NZDt-xuxm{_dsh_2A)ehPyaCijXTnEWqB9s+|`d6spoh3y??E6 zwJq&&$(2hnM+B|4eIu6-T7P(RK57<vHs%QZ@<A4_u1XT0UBUjqGbJ$0TR*yJn;F%7 z7`x^N%D~vQ`(>6;ucUv}exk;CAEMjdl)jgDML*eP#B>YtLyF0dW*qFY5%~SvvP-R$ zckkuZ{L*$4@^4`be2&GrHd}?#uB(z>7e`}Visipp?`LlGHvb!YvUgVnaVsihLghj7 z{`t*)PI7wsbK)DpJ7IE+i=8Ps`nKo_k%yqA#vaD;PTQQy8|ZS8RGF~w<JvCl;sTov z+9mh0%&eIF>0DsZQQsYCVW>DZ;s7ekOpWp5<c8aHG}mkYXo`o_AGZqWQ{GI9@Di*C z2&|xQNS94WS_+R|$=*v^ANc3Uf5ZDtSOrE&&R7LzDFkxbQqz;HMr+dm>eFz)6W_;k zEW(LnJVVBoqGrox!$9*>D>Zul4cy>+F;9&ezhSC2C9W%JJpteQ+2ames8r$``484Q z9p}%H0AC|R{58H{_fxh^di)L7FO`^jv)^Rz3fOIUiOK)KI1RfX13pw&c;<!YGdXI` zC7f+)!-W^Ik8)*FM?zmKKE}!M_O_C)iR~RbX=i;abJG*Q6eZSPcE$#L+{6+iCw72t zy%sX^a(QfOnh@9Dwlm!k)zjb^Kj*H3(n!Z^2?%sg<6xiS{0XOH^A?+eJ1Ua%XQ|1x zxet$8e$7quDCoDA=UtEQQm1TjZ*Yr`Gu~8Fh>)N%-Gi`&UHzR|?js)ha7%1{7P-5_ z!#$(Y-LEK1q_DlOK)ZMMV!>=-75>=5_=G1q7(Cz8M{P_T_wNo*UtzG_*k*jF-RA!U z4Ic3l1~LD@3Nb`-z@L`_1vJ6@wy32&8yp@!H7b`4aEt28F&-O9?6_nDDr?o|&5Zk3 zPFj=C+9Yy5M(V;^YK(cEXQjb(J6R;-%~+y8^(-uLsM$g)k#Nb$r!AJ77(o4<W{v?{ zAr9VL8cMTPWxWm%BVcb)zPH9IunMJPC!u1zk|xqaoC0U*h6rBC*R)Wpk`_|?1>bxV zYzrw0hvE38WoPKZ+G{Yp&a2YcX3`U!2d~pe8cVm+Kr-G&kQ;7m@Jg22OpafAHWuec zie)+$V=b5-(b)JQW)8NMl!#-NwCfiJjs%K!LT+%MLPh7M0eFE;r2D{4bY}wtBRCu> zdhI}x4)c+|iDY1Z(++f!Cg+8Zq89hLkD?T}-&;|a)32{6U<@H!>lZC&fUXvorthi6 zjrQ^M>FTkX0T#L(V4=$ak`@13w=hY!Xr?@06od2{mkIrm?VHVaBME1qDlMcij+)F; zWVec;ahjZ}lw?605j9$qjVhXHMWc94Cepmx%w!z5m5bt0pwhfCM6eaVK2s0MXXpQb zPyRzi<AmqB5yBs3;;%G-cW~a}vj2!%H^Tgb40?qXDoYlg^4kX$4%8Fnprqbmh32%M zW&<?MZyp@mhZAYZ{)?w}2EVRZbq}#T5PZ#37#o~pCCqkNpB*x>!rzUXpOLl}>3<Ws z3qEC|@9X%kadUfYiq4)7D*6G(uh{5M!{kImrfvYVsD}wx&gzD-Dt+x=ic33Iqk)NF z%^pcRdubW|9#r+`$9+zlla&0czlq;p4k9%^nn{)85q&c?UY(V;qG*WZ%=fT*W_^O; zH=XUn&om=cO=SpeXH=%OsCry#a{aUqd2gC!s;}#d($n+~Ir3hI;fR*3OSktNL|?i+ zTY(SmqvB_&_<H+K7f%0z@3?n7-ucr)*bGWyT%f);Ldid@+-@_gdcq?tKq6Jlj&n22 zCagJBNn7VMy5{B3M^1RYVoeJ;ngXOW_|Y;uI_Ny>S|HF0r+Al2*3|z%Hpct*Tnif- zh|)<Kn3Rkd_SdNy(2^of2I|@nYuI)=dWR<LR{ze(&>HHK9YGq#6CllU_`oT)ZZpF1 zwRqgEkV6$o>k)r49_7gX4CP5{5Zf7Nb7aet?89XzZ)_Jm^qpL!dY5jz8`PxW{GpzM zk$$LLB%}+M)IhDBPh{|IAI~M+)J^Y<GG){qrg>}(PM?5pWE{>(|D3cMv61mUC%qzR zBjO0-eW2b|R{E&mN?Gy;uBqRx4~)099&t<T4NmVeZRMbV=OjFiV$#ZY21cQ*^mqY1 zH(mitFHLUb(<y6P$CK$ZL|?vBi9m(C5No^Ga6CiBU!xL;W=@@YDvZzK6h9S?ZwRIF z8~Fl-F!(!=#P{(kem-wK8rujKC0ge-oN9xj8=Pt#qOBa4ne^Dra-8%~XF0N02={30 zBTG^UzfcPG@$<o0B)B>?<g3u8JQP^}K#E11^Z=j>bUN8Lh|8OIeRPQlM3rIojhZQi zX!ys{&>`zg<eqx$HA>Zw204gA7$yfHJa7;Vr~*4cBN_e!YJ=i&_9jO6TG;q%EbOi| z7P!NpbJGpQJ7p)*#YQ+M6K&qLZVD)T3SVK`BZYEokbDxrS`z8ascIHWm+;p7LO-40 z@uhDoT3=GcTk~jz?KY86uWJt~|CHR_m$M#iu-rn1j#!?8>L4dMRjpzsP#uOpub&=@ z26<xo30F%!j&?k$nzC#dsM4|d!Ib4uJkZPJpC2qdh5DZ`qSIjYm$449l%uIg@$vdw z(9`_eWfmBXdNS6^GdjL_2xk&KHh4SHib)w_S}$WuGkaOQi)r0Q`8R=iEoJg#Y>Tnw zS^l|h^C`cBQ1iIrs37ZF5<nH{YLK;qf>~_nRn5!_+g&0V4OK@Z&H8dSqT4kyt8Md( zq3%rcft+p|Yr<mtJoGzj7Gx*%%H0mVB&^Ac{k*umT!mgEx!vp9{mQ+P9baKj+(@0x zu8a{i7-z5Up_a%qCVxU61wOxJDBIoqhyq_K+P-GV19A6H`Q(_Lc6Im^ZSEQXTy>OR zdc8j57Y9HWTFL>Q2S1;W985m2cwkPpcK;*cvpQ$`%eAF42fl;wODrof#*@lzgb^Ty zUrwa0>_B1|T$xhq|L-t1Y2%3^#Z#wg@G^2?5`L_#u!C(6F<C}^!d{56B}d~k<qyQa z!+L~_iTafNZ!n(ZXjD+-utvE(2e3wtPLT_4Ey+f_ytA<Q(nxjs#37z~>&mord1U$z zygS1xcS{z0%UO#)rs-C0yGg{-tFr=oth5Ipr?7%@j%vm$Xeo@sWpUiw`?9o4+Yxpd z3vTVn?txf>E|mts5)iO>E<>Hw<qm662OqA|HF;+7xZ$#W^q+Y<xo?X!s>%*Cjl4Y{ zBMPx_upX?)2MvZ7`3Rf9Cwy0cfJe@z$wnnz3A{`P!Y+>^y;q9fdztpVtsrlJ%Vxu- zTmY7L1~U>l3{_Duz3Z$=T)-I>QD@rzCk3kAEw|369$OBj87-w5umDfy45ind%bMYn zQTQGfoQ;eCl?qcKv&?e1A`UT04rQ4uFPy7}*3Qa{2Ok{Bwl5XMBWK4WhjcBNKX}P+ zDA)DLp-M_NwF{L5o-h~fh6;~|--p%wg&lYb7A<DyfJL!Out)y3_WuIr05@)bydM!r zd*>7mfb?lY%*weNI)e`t+EFTNMl@;Gw;Qm7FX6RHdunb--uK>It%R6=2|@Kr=`lgU zy$aw)^gxiN2w#&ikP}g<yA*chn0(e<#b5I)L@oqO1uy#6oP{SWbGzm+nExUX`Iu%p zn+z=A3BQ2VIKvY<;#E+=)hy!Ifz6&c_47`Cj7+J7_Mtr7-Nw49grmgTDM?Qvou@_C z9A**c_&y5@rFcCSi^%7*OZA9+_RN<6M1Lv7+XhaIA7VSs0r9U!vB98UteRQdDdso+ z8e`p-7z$$<u-ebV>JR3@YZ=xRliR~%e5Z5g6~<;AK={mo7_whiBi?NoTA+a`8hecW zji$h=M*QmmbKm*L;ZQ%;RSWB(`l~prp@FNqHp{f<XOzIMk}&jcHBiZ0{gvITl9*Nm z2tCHJN$0MEdQ1$3aGSRf$(&xJy`EF7Xa#D^kSC$ZeU1!cxpOH$K^b!4zQJe~eD*C? zgIq>u8o@nF5UtK88dN$BOb$wqXMt(_@HyQ5R!{=-o3C&>Sh=X4h@Ho}cCgB^h9t;5 za{x}YDe+V!7sfDq&Qtm0T+N_}N^a?55|=tg5rXS^aers=4qvor@fAXEgd$qPy~vds zr7TTA^&SYC5ThyFHht=!qR3F4Pc_oK-E+-_Un6h^sKNS(pt-Xldh~e{rr_+bG<{yi z0-|gl(a<iF1nKXR;p*OI{Q$<Y<LauLM-bZWe5O0CAj@l7y&X=6R=?wVaue@ChwLZa zl<5u0NfY$<0`?V06Nj0$g#edD9W}5Cq0tmE6k9eG7DKdWUr;B`vKuz*3@oZF==l&; zxH>*WAFdAkpA?dk<B7vL$(1M(KJbrt<%0MOF()`gpu!5K35cbOv0Od&f)i!&PcC$D zA+&4`s7)07H^C+b^v2?Aef-G0qW0p+Vd%?zF~{+T76{u8o7oU#pTx|=M%=`f=?a~) z<0gs?t=TlXxy8Io5=zYkAD0d#v}QYU&C3?9W(Vhsp&kk(7*u;sd>E>AY~>l*?5WH% zI*qR#(GV9Xq*AAW!P{&ij!NeP1aQGD)G(P<$_JtKyk>>|2Rm4LlM4V4c8iMQ4+^R0 zsVK$qyD_xUG>@{jEb~C_IhGBbEMJCr$dxaJ_6at!%>D7X!V5EtJA=pCsM^zo#)2%< zr3mAEuafyf1$@ZdUYhI6Y+KxKAx<niV3HSbqWVs-wpPN4^zhb3amEEdGtKvn;=>rW z(~0UuE+&%teni!`Kf!2~_~NA_`vw*reCF9t8blH_zLl;T-lFOG890n&+VRLsTT@?1 z+0n~$9hWCv8@9Rj<;QFl$|KRQvqUrCmqyhT?|nLXY>%fo9JS@^OXor#-F*XiyTs(x z$_q8D1)q*$)@T130c)r45%48r_;Bc*Fcz+_SLEx<E<Ke+(9=mltnob|7Sf-k=QTeU zyg0V=_6KdFgrvqjPIvRlwFa%=N$c$A_ubd$3i}3crG4^VryZH-&<GoT5y_mFdOBIT zs5zIgPZk&%-w0mM*YA|BSlBv)&e6Lk*v5#s5xj;k(<xoPuztqyR|~v}VlmNp55BuJ z?_1(p*zQh?8%}qZgLLJ>n$u=;PD4g!HjYNX_eikr>W%uryn+NYul@)&Gq+wH>y`&# zwUol`NzWMC&-D#&`}*m^Y1(HSb%%3hvJ)1)ay6?Y_ug)K8X1zHI@oWbu<!%Sws6$o zIo}y=u|)JLaUWq#X>9{Z@>g;LeLT#Eqg-f1)9vr|@`Z?I1pt5oM!xDBN@-6uJwu1< z_zn(TwXqpmroAvIRua-+PI*7<d)q%c!fDPwnsp~Nbxumye*Q|KuHehzz6Y8mbI!p| zuk*fi(Gt8k6Q(P(#qUGL2yb5%ya$a$m@kQy{xw+qIbr-6{xf0xK66}}G2RGX$5-i0 zE??L@<J2moyu06fzm(WAEuklmZ!DKvle#tRq+|NiuEUx4ANu9wi0lrz)EOoga>+j` zlJ>H-g7zs#cb8JSL4)(Nr6~nN?3uwfi=6;kV$XaoX^Bm{T@oB#m$%2J>Xrf~y=wZC zrY=BH(r!|EKktfF^5Zen4ag&RO*RCb8`0koY+gZ)nt&e^Sf90)r?bw*#XP5_y$Lw{ zUg)6Tt2ZJq1|81YME5%!{sl-bO(?BEvqn;&_{7y&#j;y6syh1<HHsGCjEbU}19U{S z=!gc@e>^WV-f{xBZq(xyb6v}}Glu&xcZ=5bUtdR3E{ZPC-;8naI#zjKIp|nrymIMb zyMns7tXyrIj`<hU*j$u(^xIt3sI>P-jU1*+GC>y`MdZ+~T2}Ra*TZ9m{4D^y<k0$B zUD1*50Rp*f>7nV=Qq+qW{Q#{OH7TXcC;+$m`hrq7`L6}{+~hmUcQL+g%+1=@v%-wQ zTGZM}`7`)?9QpO=eM|Xo=wI_2`^~rF@6GNC(?2d!uDNDl>(7w6Sk99U(>Kt)^2zQ< zx6-cZjMu2Es$;vn-`$G1^2zYXsJVgQ!vp<;l1KV3o~@Cuef|9Ck=obGN9LCk0I(nP z=n-~NF6e4k_y;$`s|BgRN;yJ)iHwP&jS(3mM!U-1pM?H8Cg111OUhhH?<zgx9P}#h zLyLJ7?gQs)TJ{kn(E1R0)h{>B*lfUCP0Bnqdv8QW0Njkt%&cBIKY#ka2jo3W%)TF$ z57*zKVpZAD)|9_j`-(mqI3ll4a_JmUW3=uKdPj$=2{3P|?Hp`eQO7c0@(*Fu94?*T z4eZWbW)tapQAb7oZcKiI$uYL+STy_miR!IB+iohHY%uuSGi)pC`LB{Z$$^}r>W_0S zB1NMN-W>(DXMSL%@T7n}nidc0{=Bl=c7CHurETu|*4pEe6<+Hr_lH4&7O-OFbW?2e zz2802cSp6;%zqGV;U3%GJg2Q1(z?gkPV-40<=9g3c4IsN!VNX0`utA;uPQZMBehL? zTgr~#kuDD{DSa1eXst6k^;$u32`Rtvyb_A1-_RuzKTAq+l<okrX&W#AXsr({eOD72 zIQ1?aJnfsVD>Ci<E<zt^(>81XppiTsaEa>HR-<+~SVo|5x#mxSLQCP5H)UeZEQ7jZ z&z+v>gbrE=C8>SRUxnG?-|<<&`Gl!Z+}@_PJ5Io|Nm8SY9TG^nNR${2&?h^;18?z5 zPhqNl$=?r^=sx&_@%(fkWj*?|rfNmXHjyV@w+010U-^a4n5zBez+TKCr_*zdVN;3X zLtvFUupCh5f>Rmq<zfxWJ&xv8E4u;&c3pFP;?Myw*Yr~K3ElMqbcagYm(6NQ`bLcR zhhPpncyUdn2e?BVwUq2fkoFh2w;Z*!?872P-nSm>n@Yy@H(d#iugiQd?&27u8fl@T z($)ZMQFA5CHie0<;N>3f>SGl@&@H*N39}|&3qzRBC`NWzIT8qnO;(oQx+`ovflZhK zm-6i0^Dg`IcB|&UdY?wk=U}5%S7@sQ60kcHYB`k;Fqyw=8KW#tPLxzZOQjhtW!HF? zeNWxOEqBFF1!C7*+pZU6IrPN6?NH6{Aa#5y>>#Q0x~mxllaP+;hEFN)w-~wKa?v-H zi0f`@3wc{mR8W<F%*fr_J=E25p>P`G;%Znp6l`hLGinQlxTT}VIXQ_^1uEF_1`n`R zPhWQ<#?^_GUzrcVj1RThi1rM0+ZZn;<8g0y792?BEbXSYyKhBqkM2tsQT2QE{(ge? z$Q5BNza~=n?NPaOfLkO#RZ9@T%n<QbW)a-&2l5{ON-_=_|MH!ZmJMiQP2Y-?NQ`g4 zxh%?$W)7VHcf)}Pn#9qKFl#3^xhn`>V5i-qlt^&@RQzOy@`z@xihn(~i;#T_Wx&qZ z#I*Ke-9w0h#%?P5eiSQ-%f~ooWmt^4bS%XpcvYD^)7qQ$7-6mpAMnxm#Vq;T_XbpB z!H>jd&W|<XnMLsQkKiX{XNJciY|k)xoGledxgQLfCH=r_<gUJ`WZ;OWs9^m44v61t z*(VTZ#`|H&9JRizthWb%+!OCq7SPdS%y5^T=`)bF;d~#k4#esv(d)->rOcW!R7sbK z2A}SzN1V<(FZ@mUv*)^5!U??ih=!2B@fCIRAb(|pWx~2X)vwm~d({9YL1C;LZ1qlr z|8e3vwp)&eNC%;OX6{C!#OC1R^ZO^zpQTp^ub<zqxw+i-Z&uiTn%&=Xdv5B6yo^}h zUAYk<x3bOhAHg;UT`si_v4>&n==ris!f__#`!dJwMorUBebdcGN~%@MVe#gySS5bX zLe)f&CK1j44yAHZDxAAC4~=LdZz}<xgd2`9*ONghSQ&rK=V+O}@CV@S%rgjwHx`0k zV?l2w%EL@gBO|#-K6z|%IB>pLDi~9<6t$0^i!h{5%0Z;kYEn7=FGQZSq+HTgJ%>I` zZ<2#7oQ%LX4JdMEH?cZ_)3Zwz<Qde57}$hEmKQ3{s>gYz&izh7^QR|o-Bqcl+3uUE z)nDxaCYI8Kdze7G8U?a*dh$`Drb#0N_Yu}`O+~pQEKE(tjxKSYdW~1zq7jYz$a$ic zK2VCU2>=etEJzJY+)Q9b<Y8;drGycZ3~${2>HujZ9mzS!!VQvRO8L*>(29kYd8G3K zPBj?X4PB}!4;@x@JbseqSvn_?%^nEQNP+`UMD}<JhZW)vbwYPAvNz0-*6>|dvkpyo zEOSqwR_<nUyk`et=2RZ!8GJ{8#wEo=qgAIUMlES)m6H#!0p6UC^mWcvFzQIFEm5_I zIW$JFPr5*>wJ((&fQYkd{Y}adj~mjz1}(FZVp>|C?jK|FtbS+lg{b-~#TV4%O$l{Z z@|4>%f5xjcQwQCvv{rlIg+#3rNg-U-()2#a7M8Pe@>^`HFFcNEOd``A9ZDL~>w}ij zMgkj76=LYh$qF&zw`2G7V>JmC&e6k;0UpZ~biH&}r%l`xQKU`XRQOK6l2}Bse?yg> zlp<~Nrj+8%fNk}m*Tk#qj+=#ibOc9>eJuTZ$RHCjjD_ne(%3iuH@hcpu2NiKWO20s zDi`@s+2URLrfJ`lB!#wCO~{kh|A6{3DHAU0?Revv_%-`=yJPPf0I^i8+-4188^a)H zDS)M5!0@tjGH1ZHrZOB268+f_TiMYG?DVX(aT7ikQnqL2W@o6aVn|sVRdJeoULd%v zbu_B-vX){L8z7Rc9B?d>w8HWdZ$Z<j7dRGEk8<OOP<g$c(R{*fyoGJJ*~`>ju%>h3 znH+4CZ)RIhR3P@Ur+J-A8Z!5?nS5W?Yk1TJ^IG2}?DK=6<5cr{jq;#_FSFO=#eXC2 zm=CB}T#z)o*Jb48bPv3v!Q)<+wH=J~lB_mE*^BUe@?+%)f6`?%sQ;(*c88~5(@*Ih zoI3o><WbP|(AMkXnQA_+-q29~b!wa|(iJo9j_c4Eyw1(?gFfd!?~SoHKhU-7EY9zF zknn*n{j)O{p9dJX^c?^J_<hPubpRb3yJeB?H0J9Mf_6+g0MNaZ7oYoSTA(BU#rO+* zpBHZ79r3Btv|D9b-8YQYCwzq#BqpeL7T3*de8aC=d{X58#a+fj!n^11p3}YR0UnXV zKiHA1F&Pj!*F7l6JzEg(-4oX1*sDHJAYMo)a<6t*@c>$GIQ9D5d2`+OdUp2~d@HC5 z^L&WkwO}@DIobV~WL8=*<tGm<obr=^7Eb;SvuCi#D7=U9&3(eO!SnH)krMteO`~f5 z?S$IH?88Au<&dQZIh+qG>&4)E2qYLgpB&__0bPoc1p_%CG)R*%AwvFZKx8kxsi=|# zn<b0jd-|+DRW_c_XJ7U<s#3c;eA!PSO6+~<nIVHCikF9897#_s?R2(*$B_~Pi%dn~ zaW#oF@AQCPXDN7GexjocAv3KnF2r>&#<}P%5cKzoIK%#mvwrF*_NHqsmT}KI2VPED zix6WhhqM8#Z%|A)t7Vd`jkBzQ#}mmp@Jh-Sga%_d=r2mC<ko~SCg-JytYzAx%1Uz0 zBe+xWY!62JlQJ9xH#I)Fi;7de51nHn7ZAydlwmw~(n&gaCbkyocsuzhw|0quWTpm- zPxy*b$(5c#SukUUR)CMgNq@Z*wv~Diu$8tPUQF&6mu?~I^8(Jm(Dv}J;o28iwt=Fp zh?kT~j?`Q3@iH_W(oYPZ&68PR{H+I`0^WPU+O{Co$GWs2HN?6^l`uqlN=}z~ztA(B z^Z7*>zNQ!6fCSh)qtsb*L;61QXONun?yPZuTfvr*oeO$Sl%1x((M@bikL3BbxFxm; zOiO~#aZTt8hsk<X*{1W_zc?6gnyX2OX${g^CaX2wHaP^jcgDGMIjoxz?{vD6d>8qj zAjrRfi>@Up&s{$Rtsiua4LUZQJv5)6fRARAa)=eWoA^f=dH*Yv>k9KF89q70e}n{) zL{bV{+t&u&IMx(^m??!<2LONMM-{&I|ChS{*GCoV`nM;=OqANgt#h#obGpTY{K4n3 zCH6Lov83~~>E{7uN7?ntcmQTGBk8~NC&@F50hIB7vH@1}AM08-r_1wv4U#bxxQ+ZH zjEtP@pJ9@@mxcKqZ5F0}zN8_083Yu{9fy$%>3*zdV>7LOe7XcsSe`^6K83pi)s8wV z#jggBN?<t>KCsFJa#OlQj^}6GD*if#1kYDL*<+-23$i4|M8h5x8KV&pU`o?)KmknR z9&wFIJ^PV6Sn>YUFZ|t<LVMJC8nydwAtbnmy@EHEkliz1axAnbw`hska42<h42(k7 zWV2?cL3rE%2|mv=-c9YI0!5#Jmn_Dd;Vy2cJA%n>=?K!Br80T@TTzrE;SGZza!INs z+;=S8gFKm3s$U7(%WU#OhhSBE)A|&)z~_8o^nSoyG_|67YrnLRt{x^E!SdHPgHz$B zSz(PgK3#gvJ-)|1Og)eV-1fNbFAhcK-U#I0$gw~T9-pk&=maM;uy9NtjE^31lz6NR zpT;emUQn0zVD~Lkz$e4-Jxq9yzynKl=VAx)`of7JVBYN-ZVniSCQnwAl}KP(V2u^) z<rt_7UIdGAg*#BAkmfViT|k(Ik%zjiG33Z#lLZJ)kQ%%=Le=AOBNoW!q8!>?VxMpz z`-G>|2tlYU;FSi@dPWT%<R%x@>=1$UHJO$L&@jZ_=~%4pK!u8ejz;~k<6Q62<oF>U z1)bpvfEs}$*9Q`?f9zqVSgy^)<il9}w}DN%xL*tooY%!I)5eP72`=NIH~k;=r7>c1 zp>?Q({3wQbF0}SPp&oUNpU)uWLVpY6sBAJTpI_#U*I;t11(YJH1Q#)Y^6X`8AyFp= zx0q0txEZj$KJr@9mq6;xGS82c!fPzcOzyD`{_Zhk=rpeEXAOO`6v0Ia%w{aRJRR^$ z0o=>-!dD7Jxc?1^UY0k$Mj*unf&)HAU^9d0S`JcN;a+L4;Ln0p{|Zk9mu3vRq#c4^ z2rl9EM!AN9g?CixX?`jyxQ%5}q}R9bfWLzYgf6Pd3^!6Bun*P?IKNaqRN@RbPat3* z2A!w`-JWq`gi!yQpp?rQt3Nz;c^mja$t5LFZ0qpi_V;cdK9xvs9fqd2L#7Y!Ys3r2 zffA#>lN_}_k)S9b$4Io>`Wcmp{LM~YQ^#7=cwd)RmvMX-CImQpnBSeP@F9JbcmKR$ z+SR{+=jjZ(%foJot+G<p{(A<r<dgFHzk|!`7yi)yp}-}bmvPu7w)=hWejNBq&5J)w zS6|q0{NU$*252q6jw*Zf{mCem9oi}>DtH);)HvVG3L0<7PMpgJ){cK7&-xl7*Z&=P zEqObi`iRVu;PR^lIB&e?hxfZb6z)ymok19VSCVp5sQ<v(ce!%IvfilYA}+5UU#f5S z@H30O)bdA^)zGE#4<AS0o_<&ClBNAhA!B%z_w!>{d!ptJR>sXk>&TH<#BI1qxW-z_ zPJh#HXYa}$OnTvex&Q2=|AdFKyOOT>U+z2m-vBa9Gk<t>OZ$<1#(VRO?K+$}kSDnG zX6`3mteIZxluTCe`E)d$b39S%ZEK}(;7eoCR$F7I4mv@*%p!d_Fc6bId?`>WEhf<h zwr<$|?<+gnw&$zuGp^44aCbEG^x7}AZKt&qcSx&DD(zriC{pPY`2u<;dpB_V|KPcW ziSpQ4$3<}7V&Yn#-3=DUoyrq{fNXrMB~QzoZ>S^wz~!_BK`ukwK`qs-D7UXJL_Qu; z3$uZ2{yUPalb3#F?#jU-j21^7O`&-WOEMEG6Mc$&MBt6yR^-bwdg%h9^P*4pV#4$l z*`b7l##;JMh7znAYnN%iVjzdCSA%AmquX{(EAKOA`X5O>^5NtQ3N8F{<W5;1A7zat z3I(-xlz;|sgw0TMhE8CVVfNI>RjIPN`r1-nviTx=G}uN!%vcPV*2`WPZeJ|rC7R>e z^k7{9v8FaCq2V7m#uMGxvF@lm0<m_U7Y(IOjaj0Q_1T_t)5q|*AyVOTbK{8RDx~}? z&$XPaJGfm<g{ygHO~HyIc(HkEFsbrh;I)gQn?`M)O0A>+L`(Lo)?bYqZW})ZuPN5w z50@JhdDxrs6uk2``Xuw>SJ1|PG-2op=EY9XMy$RqT<$0~hf$Hcsa}C0@{pYJH{;LT z(60)AV*eZ7F<$3})+rpp{t6VaD(jtarLHP_u}JF+u;rjax=Fj<U=<qcs^oLb5mQCT zFDl-xLF%Vn@3jhzclGu;=7Fhl5R0+4f^FzJXdg4N`=5o1nOKP7?0%7Jp2oO(7;&}E z^5SE7n!oukx^>QB&7HYN#%<Eb8J`eQu<RD*)$7D_V;0U3d3UA*aLYwmU6Hvs_sD>a z11B>K5#^n&tc$3dWgNbrax^4&PhDU{-5mKgsxX0iEFC|@DNI<1Zl&JlS=t2G56DHN z>V!{e)(yP-rn}4DY$8C)E&1NKX%2E@fk`=Vwx;YJS^hV4uYNMwHEwF)bk)~vnS%n% z8)_5>`y6H7!aB#ZK8u&91JioUz2XljvjG=1%o12@f`@rtPy5F!HJ3r>{f_=OsO7YM zzFfK4HO|%unfX3KZTjO|N?TieT%f6`r%Qj<qryX!IDdW4p;MkGf6*ZKCG6x+T(k<K zeO$E)3w&I`g#~b&h|{Ro+aDC!fgqUF8o!3D@ZyJYmhXxm-j;2PmmD<`nbz7q>T{s2 zXYZ)Wk+$JW?}+b8a1w3P<X0F*N$yx3W>{gmHw{;qvQ*qx|E*Pvdq=#5ARe!3wv-BQ zDSf|1V67iaYND!f;J-!N1%(FcL;Bg5Ne})9s#7*<KvlGzfys0|Ij$Z}x@NPZ{R*v+ z$H^jAdLpGz;8TPv8LRtMRqi`FHZ=qg5=j4x-T*=(=?CPrVyr4WhQ@5^?K(E^6uKx# zXIpCH)4=&{q0xcOmldy%8ptQ}vyd_F<NRB$R6|Rjy!=FuadugL@hA0|4q8jM)%E!E zu0GCo3hoVQPl`WzC#y4CX(vx46gakal=XPyLEN5Lcd+=lW{=2uaHHP@A5^A6)nbF4 zP{S;3J7#}^!p!krJetq-I@))w;^PCm4KX{I@a0gmJv>c58gs4WCcW+%Mv`8K$IOrY zj>r61HGYLX*g4}S0{or_Zig>B@l`x)4LL}5go&_(Q+rDINnK=a12eFl41dF<bTcV{ zD*?#e>#@?dT$x_I3gGk*>H#?-hrbP`SHUzaLOg(s+nOLcTcu_`p_k(bR8%nbvz0WR zlMc~piIf2_g_(3g9JnvYKf`&LVpo|x_c{4z*aTPXE%V}5kR{-ry=C6qXtE{D6GG3D zEt`H*n8fLbqy)AYn(#)>N<-+WvPjOGh$K#Pq%P2eNp~Ubxz9j{!Ixog7-zbk<;r*) z_J@A~JpylsA7J8&`2EaKtm1DWu*KYjH+mKddDIdqw+v#3gXe38(TlQ2xf+*d4%Jak zb;ZjeT8R`+o`!&7r1x7CnHjjH$8RCxIE9J=2W|`*3JdP~SD5*uOUPdIGvp8MAH70e zKY|wIX{*rx;Jzm0@7Dj5=7eyXuWEX#7KlK<#ST@+|Dv3x(K){^o_d2V;fA_T@XVRp zqK^Nqc@w4I;Q9C57A5?Cn#Py;keAf0Y>6LDHGB$9qisH9wDKZy&j(TcY1?<Yo7>ST zyyHMKj(VIe@wTRt<Ns1hv~|EXQ0GDfnm&0PBK4z58tBVK*Gq*XG?{%xhA+F;t4KII z%9MHkqmXDRI+$~YnqtUH0MUJ5Z%QvsovxKQ=()4w(ltX{&_loPAx$)O+V+!fSO>b9 zcl^5a>9NXN$URv<n@YUnr=_dEO35I?7)rS{zlBs$yJ_1@-LQ7_N8WKW>FUwSYsftr zznVogeNr{~-a1k>1OFghc7S8AL#$@It&ZMs?a+<bI}YE&2)61J_1K}nbXlH<QnS<i zspQEW$ZC@*alKln`2)$;k)`Cw(&@+`n9)?1TCEf54YE!`x3&k;wOp~okpa2@iF#dg zkq#!&5Q`c6E+9OE7|iVKGPVCta4?C2T%EbnW%@mURog|3^7T!}o34O&+M#bUE{1^~ zKLb_X-y`*9Vqb``5>GreS&64*q?b+~Ruv??O>X7*#G#B^iOxI~Lgw4pcGbK%53^Q+ zONoV%Mh4wcjhy*5zTJ1Z>0lBAv7Xu7rD9Kf3TZ_VK0#H+Nf-EP^)|#@QXXUaC<3w) z9f-76H(kOrJ;Mb_c-)w=57`+5CQK_dOmlq%0;^y>5|ud3WqT1TArZoC|KrP0JsJun z*yGhfSS28mBIg2?p(eDk+LbjI<a?L(YEzJ~^*8XyYU*ENvmzyTWH<Teem*Mpa%gp) z)s5&)4YyM)6jbXUIu>8Vi^UC{%(J=`y@~L%`Sqw+t<3?%GloI#ze827SiQ|r#7D-z z0w2*uWe*~ff{2l<|3}xEM<tc`efU>R`)GTXrcEoUnOYbbE;G|qV}VqZj+*9fXyV$v zDXHz2rdF6DZqs%P%?&KHo0++VYlRskSEt;@x?U?yCP{t4ElS^WzUT4bGk^5obb17C z&?i&MqjrJR<Vy-}c+9%JyC?8M%7*8{HNg-5pv3>%G2hhw`p}rL{$u@ykM#rpWb_x= z$xicor~7oyX?(r>;XU(XUSS`;{Re=<S2}_hXXv!m;{2V4z#+8l^r?zzWGyc+G!J$O zjqSgIE_WMTC)+7DuNc_dyHQ-}s?RJSjgz0Hl)SJf{R^;E-@(-~oY-72V9`tAhF$4r zqOIKcN{38b<!9IYl=ZKet-;)b@;8hM{7r4-qubzmnTOcCa=@mymKzq=&qGs3Cx;b` zv*;qO_0tJNn{mq~6JL4NJ^#geYj*1{-a%TNZngg!iq$9AMHH)#j75dk6Cmu3RDapm zv!@GvKd2E0Battq*jHyTG>2FyN<M_vc*4Bb*xmc_>78FaiTSTBGkbfp<aa+kz4M)? z&!GD7b#<!$cmnmVk+ba*C{FC<mi0NGTi;$Wq*n{9dTqt;U9*@4mc3gi61S}Q0*BsU z@q53l@`6UYdp}%}-Mx_`=KV(5{I6h|srYZ4Mvv?1lq1iWQCvbr<2uF-bV$xKR$)<j zgtv|78O#J9u1jLoab`c_8b%N|k$XWU<@F;+HY8TNZ8}%IWV4Itq7zT%4HQ;md~yGM zN6{&#+2{0@{3sd0`~zM0U&m+kx}}GRJrDh$4;#v0@1(}EjxoUALtEn|@5W1=io2~i zjF0r+hns*#?{;Jao&O-J(uOyoM2Szhtkbtp6XS1-0ssA|YT76t3#Na&{2ZnR5%IY# z>kKSR#`wa1AirsYw4pT0ULyL2TOiy+k8kX}Qef8wyhrF_*sUwBz^+$G7_MEH3wHKu zi5Wfgn8wcMuxT)VXIHOCYzhGK*PjQlqlE>%o>}~mZzt=NZ%aZ;Kj@x2RNZCWEqnQO z_=Vxuh&R?h7X}l0{SK#sE~#HSHx-5~>2(r?J1svamxLy>?uK@~{_3xxn+lt%x(MB} zYWQO!*sPGTt-&W$_9Z_xRaRi};~_qUvi_RdCZr4WdC`SQVOc*GS_n5Ov^KLT1n9@e zeMn;9<HW!d8q@Rq#t?QwHa%|`dwPEpPj_41)2J!Gl90L5p_j2Ciaq@6*Gs9(KXq@z zjy^3=&40B*y0yh2EbrBF>~lDy|ILKzL=XRrW~XS@^NNE3R(H5@n1~qq?M$Ls<@36? zIBV^!YCa#d%rItEn_r3YxGp}%|I50j=ue$;us`qRnR(XltnRyGv%Iyz@R4To2sSKl z{$%(ap8IKOwvR!ox=dQ5Id<_OzxU1*<6KiOjmqPY$<mn;oNwx5`J*T;BsjlR#WN|D z#Vz$p$gW;(Q{!8>+dVC@DM>GwR4zqewni3<Qu{(|3n}lVw0^UUrrV!oxuL1`UBaO; zv6aR%af$P&`gGAI#jtXd$<}6G=S4!B^4$f$jvS%wuJUP`culVjF0cJ^gxJpOOscI8 zFeB7{k(k^D+k3DiS#m&O00!3d*Cc)k+GIZRcEx0{u=}7{ZR-dIn3Z9{?E^ikUul$q zTwK^|rg^6z^`K(*|3cX?C}^GC+j8oQy+PsZHgHn$)SuO=x`tnx-QMtDQeS2NfPZ13 zq)T5a`=;=}pne|`87jTfRL}zIe?fM;hY0TKCwyMho#(0*U)6ji=-|fpmF^+pyZVWr z-FT0VXvJ4Ia|Z@92E*PDHuVki2L?NnbXi%VPF+A2fjn|vYmN3U>d(8r+`6YZBJ|+% znDjosm-IvT8mv2e55SC<n8Q8Tx)U2#qptKCxb30W2;9LeG2#VC*+{{ts>f#rbZi}g zOJQ{XkUv1*bF(TRt&p8VHMl-cClGBJgeG!*DjtoAKsfaJ7LMQ35|<)*!L$qZ-%X)+ z2=q+zN5^_*LumW`ru<HjE=yKYVrYBxBjh=s*az%v!v1a041sU>fIXejFyc3$+1_-N z4`aY9ME>Pe_8|P84kDeIF!F6Qm4CdSE|qkqz(@d}fdRD$mfxTltK}yP9~}HJxO`x6 zRo8N2PmJaRpKz?<nhf~&(U8ippwvR?7ls_hL8(ls@s|_KIa?I?Pj;ek7{@+84mG>f z|7-6y@f<hv*#12V=`2%z<z{}R|Igl4;uzO);$|M#|5vXILn>-C9Wrsu$Rwt?nqTh! zqj!Org1%S)_mm`lRld5!uZpuYzuLdQmnx>XDGRB0lepH^oZ0`gbd#jk*SuIEiY31P zU~ho9*6l~pe<&C_ss2OxP15%*{IIt0pW@kO4@a=u>|smsH|UxbzI~^g`RE1wDp+dU z<q*(pL}>JFR#9s@CTtu!=g!~n+MoZ-&l%WU-&FR=B(6QjB&IcJeXUE-KwP^|LHv)0 z3}(m*j}G#&!J7W2{6V5LtbL%XA7c~*XIU$L7RvUTn}3q73Nv^9dj8{rGRoKf5_vXm zT~JoL#N6fU#gCg5GH2#_jXm3qsHQKM+}q>5ANNx8^NL@v!H^sNcXp+5BKF*<JAThW zbDwn`d?Igf*G(?x#kYQ%M!!Ru<TseSzja^h0oE+*;<_XEY&)&hUJ6g-9a_ETWLjQY z#%s=iCuDo8moxjF->(w=!abY=lUhR$J!p#G>v_dieXg|dzd_<}dVB4rye-pClNi^$ zIg#g=Q&y_3<|Uc(jvK5sm*B9h75n&A`riQKxHO^*Y}U6*yvkVfEcK^Q+{v#$^)Y`9 zoBuCma=*pj<})3pmGtYRyhzRJY1i%lva810|B-*2b<Nj`ghR&Ny6vk;cer=1=<M&H z{N8VI$9(2z+_iz#b*X3ix<7~Qw_S8IO}qb#ZP=rf>v5dqcexL4_n2L7#J!OH5uEyG z*!+aBmHies%`e>7?WVX6To}ByFYU>!ZEsa)ZFBzlg5m12OH1U^<oMsTV#1O~MITho z`4}8O{YGPSy0S%oX491qdKVgT&t<D$)xAHFXHmVCV}sL6SHDvekv{yw=>1Li<hr}e zgrggImYesK-f8vZZ%xOhmyosY_813soygPf*>YCvcGZoqj9r5%`v$4+!giVO{!*CQ z5w@$J!WraL8DEv`_ooWTYY0O!{Z7j+D^DAa+pV~(w#q_ty=9TrV@Otcxof+Q7WBqR zT?;bKq-!%`>$PsRTG*!C%(%UkbJ)mUU|Gq}?Om5)18u4dJV+`39O#}9{l24WWAf1A zo=~%1nCKSFBc)ROj7+VC0Y74j^(NQ-y{opJ_q^fiaVhyXV48TTLW+o&pAVm8Bin9A zK;>cj(rUdM`EGdr#kRQTl8yO?)=Dc|LKDzEYl*Rf<c;}MNOU6aq-0J@=r7VKL26Io zUwJd|k>60|ep$SJW8!vq-qRzC6RKD8Y+U1#Z2)(1f}2NN@^)ac*v8f4@;JGgd;qW# z+qiisWOIlB(iiuvNqpogj6c$Mg?xzHv3qocAGyAYNBgeWAL72>4TK0X^~ImpjE<*k zjsHt3HVI&PsCHL5S^NJ}bAgD%lJWxHj*78)e0RV{9KXNH+dQD5R?@p^NV`R~CcT?t z`m0>bC(`2dhYu^>M?IBa<SPB>hrs5n<Z3UE?$=_urhYyCsayVa(7l@r30oES_3NkZ z%36K%Q7JsZSnOLn8MFB{bkdipEozqz4M|V-39ZF-#it(XJ#82UaQp9|Mfj{!Z3mt` zJXNLpR2g}5UG-0+mX`{C=Encl%e_>v-c^6LxbpW=6>N~d7Hn7zUm7mkip0GV$ay;J zo^|q^^LBNGYM;BdC)?B|{D9IVo2rB#@o;LX{HnMt{@;1_+H~uPhO2KIPmNrSKKAwP z5avvI8<*X@20b>jKxYMf2A$8{&7xRz>(d6-<nO(rA;$}JSD%fxxo)e+t-QSv8n<lM z@pP*{zF4NOfNpipi0ONq-KxHQ@k{KRV@spsCxZOl)I5E!UbpH;cg68WGOqifdbE-q zA|ER=xMp)IKBg_p8pD16hdSly-|*?7UTuRMU5xEP^524X{t+bI(AC(Azz-SmVAm|n zzNkPq51cB^{HJlzajX4HZa>sqG<Ncb#B2V1|8x;xAX1&yP~=Ela%B4H{3TWKj*ouo zzP0j@&Zk=|^>sd7A4NsxI`}#o!PTwEJOj_icID~58J6IE78IQhi#4X4o4Bi=Z*o)i z*E1`E_t{W%-dnhta_%aR+kr*m1FqJW?Y9F59IRU1hG67i)$FE#r4hDYj?tHHMqoNd ze~Dx~fDeHDcbFA|q``JaYpmn#?SZ4>mu{~v*>3|>#73^Kp7GWDthP0I{%fZak}l|G zn`BLlxj`#F{oZo+>Fgr)mHH(Yw^eN!fmec`-lj~qvU^o|aZ6uqY_@ejSh>tIVVhpS z9XI*Y$*$dB`f79YYxjc<7rk6EyjAa2U%PKyw>kWE+n$DH?^xS31Maw}9<90-ZCqy< zzO{FAUC8eUZeqN9-SD9Ier7?&`>6Dh<K<`8wmk?wWZm^Xc)`1hOdOno26NvF#z|#n z7D1)w?n#D`Z`L%kW{v+Y`uw};(Y0Fcx!#A@Onna5YP|0LQRnd5oqA2GQo_aE1`Mrp zhCjQoy5=}NGCw0wWg<gK-j#4=0ul9Vz+o;@A9NrJDa=93xEhu8^{_$`pVC*t7tpl| zdE1oOCxr$IIAK2ThP39$yDIm_1b2ydrtJs*)G)gtJh0v^_3UuaL(*?C?)8LzyFg&K zN3Q=4-5((JY<0+xq+ey+^Utd1+Evm!C7Wx!n@4c)NO9@r?{WX&5ifV|>brVs4gNV9 zHuvulygSKu3}HP(Xax|(ovwT)VhIq5;u_2QJZ2~AI;@J3A?|eJ$0H6u2!ER<x@S7E zu1NK0_BKsl@G&w8oGy{ehsMC+>uC&BzT9n^ogO=7;^(12ZmOmmcm=TlaN=Zi4~|$T zP(Au7Zse{Y35Cg>$32Km;u`RNcX9z`<U0TKAifYs2i{+0kN&Afd{G)5n6t{h=X#_= z;Pc20!OyqrKRA{uzb9_tm8$WY8;A#iJk(eGhFd%`!0BdSX~O~i2k*997yO&1X8-xR zZe!*#c<3dhhV)!dbO;ni(u1Fq^&fO>ClvfUI=+g;f}h(1pcwgl9d-z8cLKElIZ|&R zA<;YjTNd@fSp7`^{z?1cp9)tUA6~4sA4^~P@W8yrv>84J=8RnkwgL`EwfZF6QW^hX zC*kRsRvzOmb^*p=DdWT;kMRau1IMEdT!vss8f!W`Jqr5o@>4(e@)|?yWntz4bRY0t zr)7wQ6GQy$ciRlBD^Kprqb>*EH7kt^J1j2)x-S}cyl(iDp+WOm^;vgc;YvB=zjk=U zmA!6w)O$axpwr7|0*&JG_i}Hz?i56S(%K#rbN%7Yy^S~4b?uEMtcaM?pI0B_HH?Sl z{o}8oyuaY+$R!&+wwaPN0@G=E<^Pi|`A2Jt#N`CzXWy8UnBkt7Y44u@YN~!`=akQf z|JG8eyKyoYKQ#UVE?sSI8=Cv|@R#R}^@qU=K)e#V8XV;pqV7EXoap2V!1281l2N@Q zc@yd*fAdLZYVqfQyinCwwQu^251NO+Z};tAHc;49YB0I@PuOT5_GeescjqHoCqLMz zLSwVy=uup|8)&_Jc-^45GNrRB`)jF-+eN0KW!aXc&8`=_Rik;bX2g4P+e{YDG37+i zkOWU(E5D%8b4osQ^okbg#c7LR1B*FpJBn7DvRpA{bqF_~vRNvqNpNnXRvnK>pcr;* zyPK6(-DZE;zbVzTjaq#?Z7Ip<G{@cG<<C$>vJRLg;rP3>ls%2QtWkV>iCO8>=*ya` zh&zCb=n}EemBKV7_u>^&Y@*VQuNq!_+>cS+|Lq{b1R++P%h=TUl|(cb*3@#ldFa>m zMDxm;+P5!{ge2V159o1=epK~5-negL`O<(S!x3~FR23V{DK?QNwug30e6-5j{Eo<x zP<%Xq<)hkN?exgFiV*&#%^;Q7ozHt_Gdua-vm<JK2W_9mpFM6PhkL=ZyJ`<=SMnTO z>m#dzFWcyEJiYz6O-pDbTD_9Nd)m03ONi{Oc4qKIjqC3ZsnqU>&*Fx}HN7q~d)J7< zE*0$W-6!7drvH+EtM9(tH*9EqyDv4Uvd3*{z1v^$9hH=tK7mbT@;!+HPvp<cu^PD^ zt4zg}W%cl``de4nYlF8Wa_Lje-bJzQ=+LqJddkBn#pqc5KQ_&oUXr6xg?7zd_5Z;} z?)hcwU$I)%c?Z4XysG^(Y%+~1?=^OPJ6653Z6r+-I?AedvJF=V_f<#p)|9(rsdpso ze)cOc%Y0S-xi7C##*^R4bd9_RqsV`7IbEamNG#8yX035z%aJE}HZ_Y=d_MB+zIHAS zgG-y}a_#T53WKY==-qIG#3NC5Bp}rr<5h>;&#&Dq6=P-%hzBe?0;YDF1ps+MRq*v2 zOQM7pPVDr(t@#(=D8Ar^i%b3lRy1jc-To?<2SQ8mbq5*g2=IunO|~}^0$)fCtyM_l zJJTA``|eI_iR{B*n>4IjR@mKp!bY>D;<wCYL&)7Wz4O^`#K32&n)t5MZ6VL@&Pn*Z zf@kJhA70gWsnEPdh1epiTwX)GyL@L)^ZC$aIRQJ5G0yOJqLO(;u%t$_yQ@4Ypvt)1 zZ&`WB?=hDD$rc0$?u)T}eVdB;&XUpwgI<TF_{D58ORfD^xRe-JrkecbvyEj6FQy%B zHkKW$DX4MT8q@KxYkyd9y#BG#`wy8NDm~TIUnx5}@BMa?T8=|Wuw3rSrN`{x*nKiP zIPr=71s;`aQuX4G-#=JiSlI{K3~p$MuWWo)Sa2<jv2C#T+(4&FzeaJBq_5#frsIQC zgAuYr&zZWx{@W>;?*s=L4+abvwIBL_Ar%9N%nxaQe>An}RY>Te_7a7B{_sG{;Z^bb z#&a6q?wUq#`?M|}QL5tSE4pv{xdg<3mv|5s+)Hc=5FV$qYsuaDG&4fbac21_BFp*5 zjwhP)zXS}S;VwP#rD>3KOK>e6;n@xTD>Ls4ZK~CJ8hZZAinegp@;+&J@RvX9SHV3` zzr;v7FXx-S=-%1*c4x43M!SpYu_KRSjHM#U@`mJctoyGlEn<64?Pc88W2ZVVFwCC| zacv*Z5GfCXDF1yf(M)+)ODzcVq*MIN@9`+eXKm>AU#aY_O|p+wNhuwIP5q%|w>*0P zO$ajERO=BetvZ+zfaQlUYD(LCzvOF~6AIh0fn~w~lD<K~<DSXF*<%tC;^eOX<-?WT z`kz1D0$Xkk6xQ92e;6Xjj|X}efer~mUDbzgrMhr`giF>#a#mIMBFLKM;1V3wVFbMz zlSknX@5_I&^+CnF(YH&*r-@aq;qz647g~IS0IZH{%4yS(zyHvP|JS3^*SG#+%zfW& zxL9aM@-ZwZ?NOG2N8Qm6yEhc@cwG+}U3vdSw|8y%R5Q3UxSjZl=ups(GGrebHx#tL zV5AbezDQGW@?Ya=38#~m8-zUWnWQAd-pgUjJ1cf}J>Kaf+zJ2pTtjwQy1cV)r%waU zrxn-r6zB61C;KSCLb&|YuY>m~CSOXJ6qcDw-^GqiP_2>_&OWbp>EKk(>olJFt++eL zyX(Q4bGrr~?ftS}<>hZG)Y&hAqYkEX&P%hl=tSydu{rCE>@yDRd|7bf*x<nLZu@T? zaCvD*-kV;x;;8N~jcSv0GITQ4@60gzP0w2P(ny}D8sk}yN_y5n`i3DFI(Cx|Irq&M z#<K>Pds_D$*srlDqb;raU2gEQxm|@H_itWw*Y=JgLuEy$%O-u4zj@Iq;<UCZw1xH7 z@tY*>TV!=j=U~*{-7g)E+LTT!iHzUBXwQl?ruwzT>B;X-1uvbeAG-3awi)yv>#a*f z%!uqdq5a$6I_d1RKNsDwN-utA`Rl{1fm<)qujr6I?`PJ{I{GWJCw21MHKYuKH6^ig zslStE8ji>zm%gnrY0zuV3eQKc(`w{zto%5C%^u_ZYhLbB+0T2q<LEy5yYJ#zxC=p7 zmQbBZ7Yx^w#g0mk3gi=!7Mzx-emjm6@-E^neLlAK%>-z**q5@pG<G3%AIZXS&9Ddz z))dEHgavtt-yuIS2^NgQDOmg1l~XuvgIkYdCsSvUMr0RB+wfKkeHR8PLkEN2(#NBX z?wNA4&BBw!F}zh4t4<w~qS$FvbrLNv@f`de;$T{S;y85VB}U^qj$KiuZY6aX+$xS8 z62n{Nv0Bt%3~Hx;!!*qOANqK-(05?&EfzacTuWl-QFoA*8oDWDEh)jk?MdtfI3X`_ z3>r_7U$JTagiG*AiAoFo7jR0xe5#UES0Pm<f+}VeYoklWMeR*c6^rXwaY}nOw4TNF zCCmnS-{4Qs1$pD30rLC^8Wirw)f&(d7T2lboVEspvbZi4(b_}^l~mUtqbNd_Nvg*o zNm4C96ksNq2rg*jpd^;RbHxR1HRvGA->KrPwi+1VM;Ju_fdB@K!yK^NmmtT7)pIDH z94k(1&w)%>pPVZqwe_Kg3aLaMN~(uYjvSX%PlQ_JtE5^E6G1KWE9;X>MU1vNG?_Ka zQRf8be+u#C{|}r!1b_Z7;OrkkI1m3OQF%+B3!XkUzl8Y<={MFXgQ-qBXE<}A-&wPU z1f1>1pR0fYI6GiGB7ONYz+rs2IfD}6sB?-l1G>(NaMp?7tQ(dJ<hn$!0&$k;l}(7Z z61^H^7$({^%(tuv7oBL%PtbhUE=Qe{!{W>T3Eb_=Uk&c|p8$URh2ZW{P<DO1xe(gN z+U2AZ#lb@_Si4+?MWR=YypZS>BO50GSE5&mjDg8D(T?P-hx}O;PCDV7Wn%(X`teP` z%7F3E_2o|nmGI%_WQvYs+6nC?R0GJ7RKz-EIMroV*}^Ks5wmKcZ=V2bFsrw8C8X?s zYq5rO)$l;s{-snmCCRr-fDh!^ot*$z;RE@0O28cm+P8>mM0#m(pm@KEl3-Tt^rI6% z1*`vu{yi*IQtBS>UqB_3j0|6vd=n<TLZb49J_FpAr||@ti=Fc&oRLo%rHJhhFyWLk zU$Z=2(xNz<A!P~RtAg)+$75T*Mg_75JLgY`g|A6eTIuU3zX$D8quP^>8on&uuOy~e zeKUPL+UX%!{g1Gil7fF+_dn_sl8S+ml3apS@*Bp%NuttBUji2AX_O%b*f~GKMcB!N zR>IuDQg`w^!<h$-Nf}E$fNuzDjKfSY(U<=tDC|!+wIPVbcJ_?mj7o<csmWhzhlN%m zKKU{|u&@>5OZwyB>b!=F6Cep!9rR)uHGouYXjEP|CX=bNvHSnff52|+ehYm(-dgCU z<UXmJMb(x6&3JD_4DXfIvEhvTh97Va_Reb<kDwQEIB&yyrFDy`cBBy@k~$6UHPeaM zePuAP`|b2`0REv*PYL|TVme9F;OOJJNz@UUN8L%%%x}01e}@Zja$dtYG|9hOJLPye z^SejdvbMUsyU5uD)kr$4kZ;%^>3o7r1Yhi2_v$3v8`cxUvo5pB7e;F@qgs>f4Ud-A zU4`xQ8@?e5M)DfQBflXTMuJ`>;}FB6<#n1=kfe}>C$%S2e}ZOUJA4VJ;CYg$f9OAf z3}62A34j9`{(KxI_|r`sl)?&jes_U`gB)1FPVdfg)F1~*XDKp@YNS!pIT4BxGf8JL z)6AsfG-nQE#_Dr?cUpTsbv5)S=`w3&zJ>t#6WifWxB`ddH^h&JMk%rm+u=uu!0k1; z@MPgx?OD`?&^l7T!RO+-IaG5}e_lfjJc?AfKfhrdrsNS%zzX1|9NYLm;r~ce3{)QD z=L&x%O)*p{Q3$5mf(_vpO!X}`4m$z}Z1}k(s*R4PTo0NbrL9iILx)MH4OPnUON5RJ zX~P^b)gipW=3=Vjum@9Z#fFjcbE{wvX`7)+DgI}n0jbzPrFdBKh!^4FA><R2;No#O z1+U5@4g<I9*v84i8KhMPQ6>2K!aqr?42K1aZo&S<qTgccCct4Vx(yqH;Bd;tGQ7I* zFv-Orst7+#xMWz)!7h13Ir52d6CfIH&LfWE*v4pFvq4lbUQ2k4)NB}4J}T|lF)X?r z`w6rBX9Bcfe_)oQNFlWd{va(dBtOB=6s{&Q4Mru8cmZbS6B8!DS(utfR058AY~xhn zLK4-GT#8>L+&?CmWh?z>&?Qf!7+Hdq`4Y~-hLWf^^69o8sIH8UuId!Xi5*Sb3U#m` zmv2&oER`e|O^5_ZvH($nNrHfxz;btDpQSB^Y?Q<g+zfgIj7PgKs0w}$O4|olRVbg; z=FE<yZBP<Payb$-0lr9*Ymx84{9<Brf;I`7%3ADbt0XHxHGgm-%mdZ@!0+(UbslB0 zi|s|4AympzlD-tUDL~4=LTiz(e3>aI|F^JI(w_qF&V$d4!?90OD4~ygra;RL`cHIB zCz(6;O%l#wg+9)Wg?Hz}<6!PD-H8o6MV9BwR)JwHSd66qGHm|Ibtxsz$@Uy=Ddff) zlh7wU3&60q7)8>50XFxO;;?}dBsC9Cf-CbUK+va6l+d!CO;D;~|HTdulDSLYQeiF2 z%F(t6StPOl0RrTz#C{wOnAnsu53sD9Y|qjbL1S{rp#KSSC{H#U410s=OZv~kg}zcX zEVB*soB--6ci#xqNnQpSMY+?2BeGa%OY+Kx<KXWQ4ZqKWCqfGDeGpem7)*L^m{FcP zEZ&cECkdxv^nbAL(1Pv2=;N>!qrVlbO*!%;ccySHDbc`tL=3&laueXhd{`NFdGJ|y zJg&laLENi2J45f%+(kkw(vYYKH<KC+yqmGj82uaCF#w~FgDQsogQ=#V{|Hn`M1#)9 zxl@EgQj)tsXh|aG!%X-a;5;}I9*;yA&W96ma1d8RNGHLDon^TiLM;-*ptC4<x=;(l z-eBM0fMKoJI1E%Ehw^2*l+ac|7Av&0M;AI|*dIY#4u!CKonD92mV;71a0Fq^n2)4C z3NG}M60m_Xq$y9P0m{cv3~L{PAT$Ln&s{DICCLms%X^4WlVN{!2S_Rmkb>Ai4bqe^ zBZ6~$rT?1%zkqZ6rE+{~`GunDy!Cv?FVJb0s?*jp9dn^=3MoOhNlZszo+q0Q4*r8J zm-L^8!+fQ4uz@1PJdeSG!}Apg@@L_~4K>RGmk6CmI}J380)G<DQ^*@^9;P*fR%|b( zH4cWDRx>t?lx58VLsGecW^v%pLO)Wup=NpDGKJ(blHeiW@))P!@wfux@)^Ux;e!0< z3oS@E!{jG{vxM5D+XlmerM$(ov6ME9HZk5{OR<z;2$rTK6$MTcE+u&wCYJ^-7TOF; z9PE+Lh=ben7||0T1#Zu0j3UTC1=ntvTpp+;Ol1v}^xz<K!~P2$6jGSKl!6TiklB)g z$K%l-35WSf^|66cq%cpWMj3c3IK&!w5;#vNFSdsEC8N@UZO0tmVrwQw8|H>Nj3VV= zo4}0}Z`dEz;X?{@>C+H4u?EU|2vA|Zi~wf&N@q;~9WcvZssu{rrxqP3ot5eI;9Q3~ z<TWOef->a2q@ZR36d@Xt0wpjtO!7~5tc4O;bms>blmztglP;bBn?aud>38UE*-W9k zJUHE<3K3bD<2NZrU`c`eE0@Qi9AQWbzJp1AIWx?l|8&Q4(x7ACbfGzGpr~gKB%g{A znWUh0JVG8L(<R@-B<L|SoTcR)e7<7^q%3~YdEoMKFa(zeNPh%HtGi_;gkz;R2A}Fs zlG~Dy3S>OW5D!Vnk6^Z&1VwikL+z{-mtZBC3Lf&6j)%W=4S47Wd}>)lac~Mg+cDIJ z$HXPL8hIrN`2ocUK@u_!@{g>4TD_RM9{P)v!*Vt(b&e=q7}=o*@g*UZ$PWM|A?3(; z)H0<eK`|Yskd)Qv5<Dzsj(sOOl)oC*eB_&ASAp`sxX0sT%L0m-Q{S161(3W356e&u zu0m=h{oioh{Fl(jVf(+&rC$eS@w>8irR`aiS$5}^XV!ze@=tIN>T-1c{(V2r=yyFU z;>)S>4+{?zF5sA?u|02}yYs~}eQSEkw35M<Co8V$Xp;^(_DvS5u^v6{nL5^k&v8=Z z?=QTjdPn0O_1CY1H?6iGFnvjmqE^<K9o=3q`}|;2i_V`ftylw*9fhM9O~OK@{JNYF zU2(l4-CbuF+1l&n-lO`zgg(^YzvF<dkrnH$Q$)D77IaJ@BRLqfx*`9tww?X{tSN7C z|Ltg{8ttEMMAF;e@G|JL$u9%eGY@Pyu>Ia%)}tpqi-w*_uDt>}!<z5B>%6v;kJ0vw zec^Q(C;mG${Z4LLp6A~y>wda-u+#cgUHFOrF38_*7=gQR?8*%4O40>`HBVw^d~3pQ z4;xu~Tit%yeB!^R5~_HAw&%6J^aRg>t(kd=XJCsV9J_J`XJN3WDE24ne3D$ons6(9 zAGUS`8?m*`^zmq?`(tb6NLk%(;ZG76t|^aQ_ALd=n{ZyDJQEKgKk*8zJpnj*i4m{@ zIL@&vv#2^Gj=`-bu_GyXs0m|`JQFLRjzMoGKr7uAgNC7acVcPmVyZ2PW;mLH6-_uA z?vQ6<1ybOS{P9?tmv|B$#<43WaZ3%{9>-4lmV$?x@Ng!kuf^Qoj>mUNIB5P;=C7oa ztjUIMWwA@C?xchf!Q9*E?wI=<`r-*-g}JxV$6#TV;#wNJh`O01HgGGBRT-5iSe%zA zM}A`R1UL;F=OvEf*p<^bV}sVmu?wh{BxA$Yl2K`)TVic*=^G{h9cyc&D<P$&&4NzK zH*776oleyv1sRM=USc>Ll%E(s0b<}Ud5KEEeK~ez4mFhY#jv$JcDa&ZZSC|)*y4XC zKnwjhY_Sq7eoI+cvha-d4C-8Hv<T07vakgCU7|M;s*ooVz3*V6UB!ID8cD$`mBg37 z4vh4l0Dk->VB~k8M0~ut1sX}gN-|%fSA<N2D-t~c@;#VWOtjB(MpCen;KAJi{BfxC z<^K%+hz~c{Q!1Qw6e*a?QkHVWU!pe-pCo#<$d54LJZ8>fDN-<JGBhUgA}mp9qZ@#y z^EDJncv=8~1s6#&o+1(B!Q5rSIm4L`?PBRTrH#o&&PGr-fd2z#f$6^d@%VI8hmz); z7QxYh(pcZbDXk3glw|yX8swcMV;s~?I7Li#mZxLdNzOEAMAkxVmZv{|E$F3$p$t4> z8D`p=aL#fTL$)kWr?e3ns=}aG0DrR*CW^xEeHAs>WM-?yI%p5+8tZq%v(B?h7e;V4 zKo3~&{P`Qe_sY-$-}~{$BY<y4dDnf@4C-UOb4iQgC`8@S^8{xSG)?0D82N^C67Q$T zM3C3ukE<`@oLEl`&N|I1UU*LXXX+|al!5%S`{&`PyoPUJ!BP1Q<3P@9I0KW9y*Ps- z8yFSU{X|_r8j^)nDv4}p)Jmsfo5%2D5pEjE#O@OBGQ{14R>pK^v7J26ah5`Iaq*1i z7(;C=b^zZPOdP>f(9V}X9{&6_pq(5P+fO&wKyfTvXU_|qHINm{*2(iMXAxv2@h(M1 zQH|6~yvJd)#Jd<#fVtU(cABFCZDzf8^o-=_LHAj&ofQH$`142M$JYcK#=#V92;j@n zebbck+Ql=5V+!@MwmQB$!I=W7D&#SuD(M`;QzTl_IS!VR&Jtu8CLJYAOV(DWcV{>Y zpznh4*h3hBHo6Bk9%>lyhCYmxz&93ZBzuFSMMD{Q3*<{0>cRnpB>0U)rJZh#0j(3D znNGlfVOS7S0*mWZsDz;kJeGs&<c(Mnibq25syvM%WULK$79m=aF_?4|F|}C1j_*#& zEAUtjmW#X*D?+gv$ncv00ek|;7zHJ``z8Tu9IC)$Iand`Mm!pVFH53Y=&Qk1qivY4 z56b+<@ad*LrO)|Y<VXnK%ero`-6`V9LPaO;ZKj(~fH17LovwtGo_32cQoo_R0*~e3 zAsGtA`NT``lyNu@pUxvH0eAY?#u-By_&Mvk;dYmZvV}uk7@Qse8cc|AUvLJfgb%JW zDCZp2BWUZOYpiq5-=qR@l4zDqfEwhDMDshCEUjU_VeN2KKS}!unx`bb;A(KE{{-*@ z7lJ##17*iYS3LBbwZla{il!un63t>{JSveKiRO=B=9nxEr!9m0SY=M?N@4<*2Y};% z^93h^KjMSyO3GSi_IcV$=mJYwN)QW4@;C@2$yLaYFiCjA)Mi1B>{GN^(3o&okUyvc z-u@mFL}A6mq?sg~qp3qQmOKZKiM$Jgw*$Z*Fb(wZ1;^u)>spGtGy4K<EhNvuW8%av zMQkL=KcE^BOOnUI*d(EtY0PSKWS^#~LL)MigZ;q`V7oH3z;-`yJOV&7N?W(98T5tK z=E9Dl4a;y2me@Z=rYhqpa#mtL4%;R6CCu$6HfLz_pzW;1PPPh>=iou}($7oQT0h8k z%B?Zpv~*2Jis-&~!_e_u6hDDa8C~T8)i?JZ?E<sx6Q1LD3YP)x*~D<f7_D&vRp9_p zawT>UXy+2+k$kkq4cq_+h~<+B(C)V}h8e_eqp@$(QlKHpqCJAXu-kaVROAaP|DHQD zxLa)h7@G{JWy2?ssptkra1uOQB%gi<)VS~^=Gmn6b-8<lzmsPh=_zC-ITEk;BKJJ9 z9o^sz&VwUG_9d7zpvHq)NGZC(9W;a^#r9S5X`4vJiExHF*YbD#*~7D*FTAe(hj2c5 zH(u{~u3UilZ1@ba2HoHU&V+Z1?JKZ-Ks*<YMQ))R+(2!`REBK?;{CW6nQrVjnk__2 zfaKz3n@P)uTG??tI0<P*H+X=?u&&6y2%801XTztEMQElYI8`wTuw8&P7rw&0nsm1= zcb{+<S=T6|E_atuhn$Yjc##`{96&Rj!9{So$i5o$1gv>58+nOlx`Re=x>!D`1Fy2- zbBIyW-8ZgLkP*B7u<Z?626T^I?`fN^5H!;b)Pudm_T|`C;8hMBjT}WYT|iCvy=Zvi z!70dRG_&2+6!+dJ<5jMMFqo`?_kNc9n{b*!9Kk8Dh6s6#?EnZ|_%afO(p|w-u!b0U zs+e-%3kVsdJA(^wiCe@sX-tUB-b{Oam&Svt*_*xOvI$NUBUP9?z|V%yB6=v@37iev ziI6AQV#Rb7$w29Dpe}4@EUpk(k?oAUU*?j9o5>A$Z{e_rkTPsDz~{lqNGD470Euve z7^%U4;Ykz49Kq=@QG^r;R4swSudmU<p=37T`I<w!JuCvu5&*eyBw~+Z&Y&6$i;z-m z0|4g8Cj`aZK>`emk!p-?2?TKMgmf}&)cHJjr%;Q`zz+)`&4$B~0u*xt^<jn>sl*%r zDHo1cOfKMZSSCWsF*88w$BkizuzP8*vuK4-KfBj!RCsVIG6mIgl>QH%E;4<LO#<d* zGfpTbSLrYCbg}7E>^EQzmvM=CI%!#5;2z-$ayVY|Mc|*Kavs@+YPm}d;Bc{N73KuY z;W1c9v0|D5?-ZFn!R7%m*^D#Ds-$IaTFyf^*wLO_(>m@b3998LT>_VjOv^AsASQ=# z5phAaTojYov<CA7Vt9-sq#2bzh<*#M+$i~3;P1kjWE}pRI7(N;II*b!vj8Yu#ubE# zrnt(d+al9aOdFu&Fd`5tn&K>7h`YVT_*O?QBxGB9ZO!;5c-TW^T8u3PYO@*VkWFZc zlk{iBREgODwOmFV!b4Nsr0Zc1W8+GJF}WR|EDW?1DvQXp77GGud5jdK8%^<$n!xR1 z`7{;K&t{xNW}^;{(#f!zsNk_+s^tdH2X{KILy>G{DZ$nN`Z<gX$ZpiZSvnt%7ZsFX zZh$_Ik$_a94(`&8aJ;yn3Ujl}^!48^Ttv3U+dmIfk^?{%mvI$IM;+XxI<U34paPRm zIgBX83w3ajs>82D1!b5Kkmcu}%zV$z^m>rl@c<eV4K_WSaT?J;8y%(7V1lTi2vY%k zvKdSy5p8spu7wHW0s%$_e7FoI(=JK!B5=1*kIcs-V^SZOh%}&$?$XWj2d)-WW8Q!d zj}eX#(MBh!Dh!GWiZM-~D_cInNs`u<ObBLUo)6MH#v}z|pp7n4Em$flD922Jt{g@T zB10QJq-L;GTu_UJ09`yrs(dp0r)3gu4&L-x&#%HM<Pq6Mo?~R{DqR835r;g*wgJnz zvP(!fYUV7R2gis)O0ZSH@*LTDWT#>>#Kjl~-R;PM%Gp|8!NZbrIQV+UOqe1Hd4eqf zQnO`e5FBdeCe?;1;*biA3Z!ynvB+)3v=px05>zJGM6Sh~3VTSx5jiLfAlHgRYOnwx zl_yI=+EFtP=~P%>6jFrE1`cJ*P9bXOBS*y~4iN};TRM0Kb2@H8@$4bF3R$xqXu+kJ zE^sJE{uKb$=p$#T5u7Cssm8p3Lp&K9d4)c5AD)Ua4a-K~PdkJfWFLIN^PV9wDtOsr zCA0&YxUx8ek3Mpf>cL&2kaCO&H08*m5fFXkBGpt(wHO0v3iy=5l(HMWg0ngbAcge( z-EkV4!#2y7okZrKp^nli@N!ZAQ*0+-&Xrw8V$e`m=_+`+SU%wZ^Bma)CMD_kiyjLh zj+}}QdC_Ad^dP4ih1B;XAhl?yyL1zrD(-)RsR4!Ava^Uj8tNpS4IdH>Ph8nmBrEB7 zYfCzm#eU@3m)4OE`LG|+`k;<P$OjE|k!rwAqW&@r1PXbwWTXoX^^g+bCUJj_d<x5! zoko_U1OK#4$C=~%pY?1L&LPXCu7@h5kj;(yU8OkKT--0fC_q?_ED||{4meBI;6hP< zDW(sEh5UR*^$c&nRh7Dpd7|_C&Ro+uX9j9h;~szdOXa=uf+P1d`Q;~{4fa>R{Yy37 zS@Xz6J$^A@KDRGyQlyj3-Bb5+=54M8ULO$lBtlL2eyD>$E~NE&$9dn2?A<)KPnsQ9 zHOt2Iy_@jJjpTdrC!bv#xc^67t)~qk(Utu>ZPu-hIpnazecOb~*#pmd!XfkDj}#*J zyG}j}+mZ9LRhg}5uAL*?`5;8~%z*BxTRHRVOQwmI347w9LVSNlhYvZ-tItl@#2%>c zk=hbzlquH+XS#h{AAdmpx$GLN*LxXDW@z>mF0SO-tnu==afCygm7$#r8L*!mo^?a} z;;`_L4Gpqi|IIFndlK>2l=m*1j_{KCuTDPu?V8?&McG^Hi?_^tyZTS+CCHIn#6D#- z)oWJ$!n@jkQ9t|!dzs7sz$o{GyGi%BPWPYoz9!4mXJ~G?a*MaGzG~W1+?y>kZ)+z( zAJ|X4W@TwV92FDzjX3Ht{U=~mw#G?h2D-zMFd3dFl23mCtGF7Mk@M&dSHenop7DjJ z7JrcE8Et>D(1N;}d>KC~qNozOE3k^Ek$^l!ceoQa!k5KSRr2XZw#Hdx9lFDbFbm!* zih5$P(DM4>h&1gq=nnh3=QpXK<AEDF8d1n$bcYK;9eyr~DjS}Xk$=%09)zv%b8%D+ zJ<#%cz<hh9CrFGvN&;}<YA_KNTINbv3mb}~1ay*OibVcG%bW>|;T%y^DSbWQ;x|8% z`4`*SD<VVtJ|t2So<=yb1ub(TsKS1tsABpupgCJU<)LM6gblEtII5C<5NPIV#541f zN`wn3R1@+?e5sP8BLAUf9t1P^qd2OTejI4#X(*<(j)Y0@OcD7peKN2hJMjeaQ_|{x zR$qh8u;+X3x}&Wmf1qof3G?6!B610RC9ohT@jN1*+zE#81u?mb?hGv8C9;qbbZy(} znK%pln&+{9Q0J4C#f_j1TZqXO^nC!6n;47SMAy0zmcjxNxs1LMVCE!VL|oCeE`+5x zfw4uVc0Sa?zT&lOOs;89g|$WGBKj<Vnw@wGS%^Z8gf+0Xm@J_00;t@?D@ZH~xhf`O zi&6_6G6#R_MeHu>n0S&oVsbUz6QJ@E*+?A<xf6_FnuuIXR|kaIiRTbJ3ONx}6jP;z zt>p{PUFq5xP%itM&~}y6w*tbP#AqZCg<J@laEFLoOAiKwyu=iw2ZcNcrf`Q?K25XS z=zHZi>NN6FyxX(b5vhyaOWgr%;wD~3E~4(PgjMiTadioOEwCvk@d83Z-JJ;w-~`d| z6mTVhS;gMyRdH9F2aQN1w4Tk)PCSdON8OzWvtb)i^%J@kz~d%fMed^RZUkM}MqFK? zm~s-Mm`9Rag|TGnX0jOXHX=rDuVRxC6m|C?5Mi;nx`qw_0ojSCk!5I`BVjshEUGS| zt12cYl9bfavidfZ#P;{B;AjsCt>Tt;JaiCkb0(<4`J(Dl`UW6?mzao1&^C7h0nQg! zSJUZ=DI76D+up36gA2m9K9Ai=)gljxHPwL}WYp?L(1(M>)s=JypqrZ*gB(ZOTnNkI zFQV#lx*5=&BcHyaZ5{-3+!td(mUbcZmHo-9B8zhZn#`VcSm$rf|KO=2y~p%P!0c?h z6UZrau`B-<c&b?MDg8HKHrMWwVshrsh0ku$F0oiaK8s)UV*j61xfm^~-~SiYiF{V9 zS4DRMX7lV=$Vzmv6MqK0U8MJfJ`ae@wmYMk-1zI@?P9$Oi@lZ+o;qoqJJ5BuTp;;B z$eq~{G@UZKArP5kcM)+$7kluxz@=in8oD14$+JsB-YTY_;58z>BKl0rUB3H%r_Lm= z!C!s0e;?I?yvFEiokD=!T)QjC6*SJ3zYxA9(krEF1G{tVB9MJ(oU>vQ>s8Zf!0v#3 zY~~C0E-#%7PA;^OU2$0F2IrzevhB_x8__r?{(9I=tXE050V=t6aR?WUbCXZ4BE53D zF;JOf7tQofiWTm+q#Bc3@mF8%cc2E5TaDzBf_y^bJoqN?B2mU;`cyzS+wLSX3$=3O zPgYD%>DvKauH9uMB58li&FfGETgNl)Cg%#Yi>*T&7Szg_KOep-&Zwfh0lGZ91f&AB za_4Uxo)!V=*>-0U9n|X0%~`ku_yf=PZ>Jt0A22%ba{qy0apUX22gDg=bR!@=$1V!- zM6F!->hMdEd^!rG^X!t5cc_&Ie=F{#F(;Gr0D8yvJe+ooa}H7;mT9n&D5Ho@2E4d- zOoWZryYkn<M&b;CV#=|LL~PM|XZ~XN-WE=&g&z4H{$>4sJE}MNp3$g?GpgyD!24{w zaAYf5@5EPykBTyiho^Yt0b1|I-vA#KXH;6)TfXy5OXs9O!R&XmwA-UnPB#VK^XyWQ zKD6G0Zw7xBXVlU|<Ws{5WE#5Jkv|Dm5qUqRPq9?@eIb7w7+J;0sIG1gb=#N#8r+8S z$PRR~Gk+c&CGswzuL3l3<Wm{C*`03)M~S_w=q`XpzzY_$jLkmmd7X0sTB{`44Y3G> zZg%5q!(_2{1)T~ca^;gdy4i)l6s{I|m(e!?i8&1yneIt=VckJ$0J+-8=+!q#LKdU< z9r;sXJ&|`2eKug1-Ec}Vx$@V*dSY(@eK%moZMcHOCFQo<yb4*dZE2pjILd<Fcjp_y z8Dj5hx))%_YhWYwib)0b7I_!bHGqcfhI7bf^!}ThDmZVWdoSy(sCHy!ap7yiog(jY zIuU5dX^2Ju^u7z<6z&vz*U}k41Fs<k=|%5*@J(@@#vStKZ$YZ;t%u(!$tqY=-1(Hg z6CiRME+f$>;L2YGCyP2u=s19w({KT?L;+|10yud~N0o&KIoarFeVq+eN$f?PPv~j@ zoZWC1*?<C0{MoR4s-Rl~Ft_0<l8FLtd|lXH+*x5kuzWy!2XPW1I{TY=y{n;v0L*Jh zMlclc;1gj)+*w4Q12D21P9s`quOojtY$}pZ6w6@$7gQ>RY-;qmu5L_rQ}qExPD3Q( zfc84`)!+hAXDQtWVDK6ekw&!Folk%Z#GTdhN#^?^oN31HJN)hjCk7gkEa(xtkJ}KB zJVJZj`1){&xU-Ue2$1D8#2}$)uM2-U+%M`Zr<*ILROUcZ&#Ssa)G%_t(dS{Af>(Kl zKY>g_RUN_q!Ba$<kFoy&)49Y;$VpVy75oLBBG!D0{i>MGBflm6{MPjn^c#B`P5mZq zMDEhEp(0e(9W;PXi#4k-M_@XScm`R4sycx);B6w!C)ivdJX=0pLseT{*WtDqsl3GR z7w#bs2}x)`F2<|4fJ@+Fk!BfY0EFidFCuSHRS$3rTrAeC!F+*m9x+KiMLU8&;Z|)~ zdX07ln#bO8SY08P**iSdIkeUADzT;j`xDs7C0;@HqS4OaLimPAvlLqg?93rXC?<Ch z58p6eS}izCzF`zqkGB;L$#eV;;S#coNV6DQ0+eSH&mo3rv>Uh{b`fh<Vt)bUTw)xO zqnMV#%_7Zm!4}Ihn)+>866D90OBU@R^pRcWrCy621Il^C6yzgn=?G4S7l@J{V?P17 zY~o2|=Ex*Yev18Jxz>N<Ug00)1xDmL{9fT|G80dJfwvH@25>pV3y1}3=?rd!nd0Os z%oV`#hzW=QwRD$HR8jI1Y$0&lcjH;6HXAz3zD|pP<l@OrqoqL{HpC@fML4LX8>j;d zMag9t9vFGvo23h=u9#}DK;Slyn9S@*BE7=f3j@hQqv~h)ZNi_)oA7cujVwiL9KmVu zCULR=BLN;<A`?kKYh1y#!_#`eBZnA?*d$fGb&Z2;*zPp;E!urZ%y#!;XD9@%aR)cU zJaKX{HZG$UD`nJH*A2J;qw1G<YvDn1H@;ekrwC0H;sR>H-J;}j>^RW=T}Dl=l}~El zGAeHN7Ms6mC!wkA#h$izXxE^#!?FUNEw+D(tpwC^;O{f4d{WM+#x_*~XL6*GUcI87 zQqMzk$t&3Mn3}Eeggyh_EwX=t{g6>b-(}QRS8d#GBfXcoB;iJKC0<WBDlXtsxKd<a zgZTsTN*T3MET6v1s5sp%HrHrpp{r~wPg@S{)~Kw3b;b6jm=0i_11o3L(jPObu}!tW zlbmjp@jQ2jP@U|B9~F^(F=h+A;=*yrw~Sh;n10Bpf~}VIG}|m%0rZ(&@AXY;v0#9Z z4WC3*Q2JO#ou-(6$f%Z^{keOEYsrat?-#iiN&*mgZ~{_|(%r$aj4GeTWmI48S*9NQ zzUS*SS~`@WBwRQO@kZ$`pa$G9l2LQy)A)?a>`X$R<!%$Il8N|EC1E1TDCP>{V4@fq z$*4oqj~UfI34QCzhY&X4^*V#5B&I0l1kQmOBBU788qTQlX@ZQ}>be{!!*>dEDMB-{ zvUq^zuuP29VxfRkkx~0m%wv2;m6uiAbYtT?9e+co*{Ysf$K+<mTsT~0T7s<r=HxJj zGODvwKK+<c<z>~__=#X1c_&`;dEg(yG1*JrDK@RZ_5v|nMl5nekx|!8m{CQhH3C1& zXs@lA9eGeQdrT}3Z!N-R0+ejVDP#ef;wb$I#)(XS%&0?URol|i&wrOtn|vFe{338f z>H}?sG=Rcmun{4e;x5I*x5cItWYnR_-#?DYW7l|YP4Bo1jYtv{z^=(*L?Z!cii>m^ z+%7ULpD3dS4P{j3?4*Ow0)G=uC9C1>N5sg!F7PrEi8{DSSHf!If~VN_@fmfftjaTL z(!sVCE>y|h;Pv2che9$BKe*lz0qLR+PSRPhwW#0;wrIkPswk`SjN06yjvM`7D|txl zg-6M+jO;z6Tj5vYf*R~7kj0xQqn;kgs5pXgKBohM64`Xm2MV!c(`gTGbu5PYqJmOP z5AexhM2^p>LuGX+qi)GB7HE<|Jn}qnr%*0N$jd-$p*<NC7gS>QKo^%0k4%tJ<<n?J z6@*w~UJtT59zilT<`w*R$4O{9TkCM}V{8hrJX>}GnU0!GkWpR7GODGP-={x?tH?2U z(-%E|30=rBMyB-&0haS*ETkMYbC-_Gs7{J$B%}I&ie=trr+5aZb#NdLb_y*R>PS#X zj_e}hfttBUjp1<_)mS;BGS!kEKI{2iIGe1GFR1I;C)`ceH<HU0Bp!X_DqRC-i9){5 zsEZWSw~U(fu&w1D^os4^6?~&33L>x@4-X6a$VsXK`-nm+vF|ggk61o^%c#vQnz$}} zfw0F?$RKwa6};+k7#0tyDcmLQe~e8B%)ig5kH62TxaG!Q?sVLMV%TQ1zMCCPh%zh- z;8an63FZNq^JK~ywMssHmr=KTc_L6FAHs*c>^UH`CLb~y6>)zBMgR(PWKoE6Mje{I z%cug-@{w0xW=A-*oE>_&@7kyoVRL{mu8fJKq65kql`H!pqgsagecCO|>N;s~a$Q_e z#b2{EoM#{5+w*Hr8Vp`=q}@GZlrw2_`TYhr#_}26O^&;rw%<MZIcMp8aZQ8pSJvQJ z?y<PaG#i|Thi>N`)1S|L=~QZ#nz?ZArnzm>!*PNN8(j_e$Rk+@o_q~|_Qk?o)c@n_ z-s73jA3u(NyXuBcrE-aLsH8&WeqEi4q;X1-dlwm&JHzIZR8lTysbpppCfB(nGOXO? zG7K}!<Tlq0!!WboFw*({&iC=yLvNq|QpB^@XFIWBSn-uE{?_s8_NKJ^S`S}j<P&B! z_YUF#vVjBHB5f7N+Z{BVB7g*I#8UIBpC%2<0|V?A^a<A1TkbA}+YG0_R?5AwqPeWY zI~azl`VT77;WN3WpIhZRI?umrMEnU}@zb?&T;k*1(nVX>)4{j01(Yk_cHYHG?AWh- z=j`d1x3ZL#OP4KI+2FC_Hv3)82NGqL4fS{61qAmXIM2qodc;&d##VGZy_owOW;*NJ z%%{Kg%+>qcW+1W#r!I(6`(4X|${WjY%8z&QhLq)sqR10t&p;}gt8n@cOI2Ni)0P9* zjaCG8d2j`F8BUKvq_Rar$XCX6?y2lsgVTRn>MERmka>YVf#3=%Z#ca8?sOB9kR$qr z{Bca@fyznjby64)PJgvj9-Mjro0KjS4_F%U2KU8yA@{RHgUE-+D(|Rl$DVBu`?d<F z|7EE>IJJL~B=Z){71ZUiBB;5dG355KN?R3WY&I#Zehp4lf3;K|oVFe?F|q)<DpjnG z6+w+4dyiG#R}sffwue<YX|BO(<u8`H2B(4Ot%!YgSL0<?22W7Oj@zjGf!#?0Ry+L( z*`E`$0;m79)D<{AD;=VAtnKw}qkF)W!4uTGDm$@y?Z8r}eUQkkH8}m%QrF;ARSzu_ zjkZC&vcI}Kc!H{itswy$oZKLhxiQF9IQ=h6<-uu<-c_KCQc}z78%9?*2x>d9!s#T$ zC_Cl_`Q|E|{+Fe$z-gJDh(WX6)dZO^v?78#)&;fJ$qYisiFr%@v<|1gS}G4tp$5(F zudIxqz+t5%;%lo7f(lW{iU}m|8MD2!3a8ahzglWE4^CZQg+yLMoU{L)C=<B`rz?V* z8xu{g8?&`tgVTeM++Qtq1x~q^8kvr?X?=am$QWp<v<9ckf*MACIA(iaMRW~Lb8}-h zS}G4txt5CT?>QQb7DKq%eSg0Sr#wL&8?;f8#;TE4;WRtuCD~$wrLMr~ilq)7RgwOp zG|=|i+=vIKJVCvyB8c^AUxU*qa?#k}MoV3WQ{NR!m7Z6vNtTI2`>w$0x}eGcu=AvP z{2H8Y9y@p^|EHz$;B>`O)nuymE&#VF3AL=k>AIk{%a%L+u?nZ9V+U>X&tRXfTj~m& zu34(yZw4>yPJUQ}({(}p?sR<}PVeU*##Xe;@+_4Hr)!pK@WTCug^}wjoURKhcR=*B z*5LFg_83XF#))UCYjDc5RM#6XB5$n0>AIkDN3J<y6;AhHAGFJsISE5*d6v2iryDFa zG6(s(bq!9}1(k3!d<{+qNV0e*A4qMk`Ld-N^WgNSr6O<kBtBk+(~l`UL0uU<IBm}; zcRB_+m2DnEzPfzGgVUduI+%EF4NirCJV9L<cUR%`yVEU5T8{Y}a_X4zvZb!T=`WTl z-Kxri(^PQks-Uh69-Q(+z**)&WRbD9JNeur9-MBpRJ9ZyoHpOoH(C)?-dKiHM+i9A zJcisc)@GZpjLjph!RarSx(272=t9Jbpso!2)D<|*Hjf}f$J*}ai(_ZnGpbhL^q-cx z4yTGrjV&vJx;(gox(ug(lb?+#+vNX&<tI5-ufeI#ua>$Bry^j7^ptFLC4x7&f|}L& zgnWEV`ELGBEU?|N)M@`JoTC3}sXREnW~2bDS5zXjtc+zrMUn@{ltKAw*m{y<gOfWX zCU+H1|7oc!aGHdEi!gI=NJ-(16+s>Qd@o-Jo6+uA;dBaOp1lUAzgp@VoGRuuwdfd$ z0v%V!il9Eom&H1g9BZA-A)Ps$Z&%^;zbthXPVF%%#pqc?2iReG@C0=W_DK8qS0_G* zMpkFw8k`>ar=_mIX}O*>FjmpCxkb-tW$*-*G+yTff@tJ+Mw1)X;q+Ha<-w_mL7~G) zYDyY96R|RQf?DaM0>Nf?hLN4dAoo|{^q-chwG5|%22hvgi$;P#EybC}mWvw%6#~oY zj3lGRW^LBs^uH{18BSsD%`uVP2q<_YBPAc*y+Kg3I)lmDW3zYj1=r#9S4-u=X+)$y za+=U$XaoSV6=w)P1vQSmG&T#$2VmKxRXEMk_|;NZ;FN2r$UXfw@#sLrb_bD<YjC<E zsAB^6y!K*)+SlOp9eJar^5B$fsXuIXNMBUsZ&JKO*t-g+JVAZnbpm^lbmaRQoZcN1 z*l4M%aJp=%(q(GGt1q+7gHxWMZpBKqANfYxu?nZ~v2Yu&jh4Csrz@7KDqK->0+^r} z*1QI%JV7NLsi)bk!|7eGJ=mX?%7fEYORc$WQ0X9&W}m(ar|W`RMN@@TWv{?#ILJ#A z+ebRGZmDZ<x?-sY$6d}{AZ%TO({(|;1d-0sfUm;oK5S%rY&q?xr7pwinx(p*i;k>8 z90#w#>AIk1X*^wnQzKIBciK%zGS5<ZaJpuxk@m=I1V!KqoUZ<K&lObeh$Rp6;IuvV z8*L8+l%>J5R34nJSt_!w-v+$~r|W{s9qVvfPkRUf<!Z!`d6w$l{)?slun~}USLDIz zx}b8$gEctihN;;a5oDjSh80UCt-$F9OO<A*MPpXs)Xt12sLO*JrY^(jYM4rXIwoi1 zwPLB||Fl$9({di1e!5Lq71WjS$Jnz~JN;!~e`csWQgz9B5}AZ}>tL2@pMu^vvazA$ z2V-(PKV9ilv$5+L>WZJPl4_(7GQIKBpM+h&Q;HcI#w+rhu}mAU6+d0;Q#WL&KS>pt zK4_DNZbcY_%`)uQ2e(2U%e?Ewj|DILDX&lchoACDb-?C`^r&J6;gbPD9r$x7Wq`c2 zu%jf)Wj`gZ_No8yQy!^GNsFqHKH4Xs!w||29qS{}em^#*om@^kzM)Uu=%?$XYOYEu ztvLuZS9EOpbeX^#w+P${l|=qdGlt~nV0nG&uYUTIR2ym_2A{zlnf6%pID$8hAh;Fk zH<|#%D+?P$KEmr$fAv!ysd6(^1Bh#mK0ywMRUB{r#2am&xD_hID;FEHp-<iDr|YE3 z%~0KPq9ThCvko0;_89caNVbndb1T$rYy{bFy-)qcPuECwHA9Wuf)s1?I8WFF<WoGd zJT3tFl#aA`{7nwp(5L>xPkE%elA$8S2K%$nWe5SVdirn{S_%<vr~YC1Ia+E={O*Q6 zb%US&B-ND+wXgrMbd}-}g2y$&Ss-^1JuC>Wz$&F9Ag1bCpZX6!<&o-IhAJ(srj|0C zh>k=UIH;!#zeXD&4D8jDh7WA$Q#bl)J&i}I3cL(eRjsT>7zk2~ZSv3|m;ymcv8^7) z%Y&q~-luN#Q#A;lN2+TXYK@OU16Un1T!dyI<m?LLhaaPNFORQled<5_GzYdqs_Pl* zF#|bQH$B2JV3eX|vxh0+0WeC*vTb>+_o*BGGz<2Wyh5r!GgLRXH<4+GOozhMVFVhC z$h0p+uMS?H`m3MDl1Im^mXB1{Gt{6+QDj%6$3+4^P(_K{;$cJpt`1(G`m3Lsk9FT; za*x(CRIZ;Qy9WC|qdO5!;KGFAaI^-3X16+ced-23#g279V9H^+q`ID=a{aWgUtF50 zNG5n#6a0WoB{FesEW@f`yWd7Xy~EtJdh|0x<&vtjpqkIe;rD1=gt$F4aTvZfR{GRB z+D1P;i;W=p)osX7SNv4fr?h52&`?pUb^0d32xzFZHkM&k0TQ?Fr`$fZ-LG=_Xgxz+ zCDj^t0~8qge)uW+5W>pt=lDj`hgj#Z*8NnT+ovuct!Jn!e##|P11s05s{}9*qg32B zZMI=RC|Rs$WR-P4<@Tw|N9!5til1^x)oto+q!*&w9-2HHi{3c0Stv4dtYp<s{Z{(a zT<($JdWO12s*!?7-<Ij?1YMwnlHZ0ALN*-pzsKbH>1v<4AwymE(^XPM`VRKLM9U*e z>=r%@Zy1;{{|DTs#kF4cQxgborBB_Eq5dS*zJ3j9ijp63+LGV}+%VX8n0#13JA1`X zd41}g4H@cBQkBN3&L<5=p{)`A_6xkh4N&<P?RTDzXw8yS{$||i3KQGGildwkAILh{ z_N}trP2(YR%UzCW*5S7eS4|Z}Z5R)eE%PD*vpBm!De3Q&a{QHRKX+V)iSA&T-`2N% znvR;uvH#rE&{2E7ox=Hi2|eru#DNzq33P-%aT<&MYdJ)HQ*rXPsOa54K2w}JndjR9 zA8v0ybzk=3bJ;91gsjb1x+MIq`5l^@)20j?0s|Ztj0kZ&NS!j39kq>om=XIaIWQ|A z_#c$ZrY=)%G&(?$oiHo`<k&6f5&)}^>ai1iZ_C4Q$Nbt^?Y+v^vXZhS+rBQe@9BI< z9ryhGVSD4-@?G!HS%^}HU1>7u+`*I7n>8Jz6Xp(l<C*L|Px!<Ck)N`hkM{Lj8!WX> zW6%Lg?6hHPAje@1QCqXcl`Gmh?eBBl^j|5}K+<L31*5IN-xM!59#|PlmscG1mpJwR zqty1W<px#CeP48BH9`{nB3&j2UA=)%H^!-?u>Xfr*Rs?|JLDz80icm0uu1VU;U}MN zj8nfk{SQh-miHgs@cfB9KIJ;<hB);h<o-V?_2FuR%B9pFM+Kx^6)Tz!=o*Rr<WsJr zuE(idH_aCPFG|f`X;7CbReDk_1S3;|o<sD4*Z6eVQGdp%IWd2epZq(es_K>NNdiL@ zk2Sx(vc{(?j=CPFJ|Q0+JN_%BK3Q#0S1DERhQTX`tEn<6KlyaUQF(DHlH5Ob9HjC; zDAnMG%d0<)b^&D+d3?I&sH<@**G=!K2w_wHol@OjAtGB4H^4vnl;^0tIQ4;wEY_X` z+(@YpRvXkcN{#eDCK6s7{Nz)fqb|p(TsPf<6>hKp>a_jeDHUnce>4Fdy2hvLj(Tl5 zPF280lj`f7Y#|Ekl&Y}Wp#G%PA4hjfn<_q7=hOAE9H)}n>noj<SK`!lN^M_hP&ZJj zG)b){Q)Zn{*9SLFCDqrg+-i#9#;N~Ksj4*<dU8M>pE_+Ar1~-^aR?)8HBRMGYT0Uo z`U|D%Ss6^(f9LV(hJknThcI$u;&^fDDy90bHmJW)s=+Ro8-E$`_;kbIx@orgbMl|O zIQ8Et)&0hkNJ+#BpFT%#969E%$sc~ksmqj_v)Z8kN~xidy~qQ^o6CG!p(M06xB=>8 z^1iXRch=+7WlDX#+MxbQsjrZ)dlO%yxqNDWGAU(!d_p&my|v9(T#r-#ol*x9PfI^g zdeeH-*vJ&PKDYtu{d}>FaVptuwL$%rQs08|H%kktro^W_M(;wLv`gg;ht!WLl2{?q zhB)<KD3zO~s-@KFJpjH@y47~m)QC4O8*%xxJ)_h~XgyB-AC#)6WWZ~w)}yKs1eZ@6 zevMOC8`OVLYWs47YT)2@!^j8-R8nefxw$;J0qP2${u-zLzm&R?rMlb*j#NjC*rg_< zgriqRTFMHa=9q7cQ~w90MlK**h&Qc`{D3n`t;>TOpf2<2uW{=CL#f=O<pxy;so0wc zN9!O&>>UzQ;6M4aazmWTb<=;R)PY19>7O3~r8PcPRN5G)=63!MN|lyXwSS-T6nzk3 zX7`g%Q&Kj@sV~UJ|D@Cxs|_lbQq}D1^}xUkrM$Klv!8s*b=37Z^)31H*ysO2sd^d) z9rg~%DY0nC8lSE>>Ux|iFb27k|0|_(kCq$MRZ2BbcWb_GqzgQv^pj6l9CbZTwar(+ z#{NpFwyO>53Z=R<KaG?_6xxk^_{pa$j>?Nu@8^qR$?fC+gHj`DNDpF*rIFVfpYj}) z7pF>NwMgSNPKFyOReH5SU87XwbZ=r5+Uh5tt~u&*oXU06_VF?&2?%Q=rM9m&s60v? zNR*fMQ<`c0$)`L=U5Qgk<9Me42rIYqe^9FQ7FFSR`$ubhy6&heacVj3cL-m$1~*P! zr_}P*2K6VUstMQC+yVaN({)E}Kk}XS7bG}G<Mnc!x=yLwqvZy51EtoSG2q^=U**$h z;Gd&m*-f)F9+Q7tiBtcbQVn$6&fOsJ`1I<A0nyFXK#-ewaq23ia*tLT)Qyzta_(7V zHiE~e8%MTAIN5b9{5~&E{dY=@oJ3x0R9xXxMc{@3Cx?s~*my}|_pijM|4ymMYlAj9 z=oLOqx8E>i#tiOy?OKmhmnoHdwA`TngHi`<M5LGP^dAo;AjnG{OCYVsssBo;+ocuM zqEqbA=xBtk17dw7*&oE_w#Qb`*5cH$hI^|G>VHwHYIIqR7?8`SE7$zjh6T`l`9i<N zFL(S`8q|MKYI`ic#@ApFjNo1KUme^4)z0j{?)d*3r5YS`&AGC6&7U{gmiZKNXk(m8 zTE5&*-pjk?&l_IctNf~_r8V4Z{$0#tr{yNa^({wlSk`{RxcHq?z5N4~>0)Ry#}@Jr zctf!qfEv$}Z#8)5!E!3u7G>=s#N0|@j3<RyNFTKzs1rXm6kAi5(y89XB{K~Vi&+KV zz>X7UqD5^wODct#VGU5J$e6?3{YA=Of@2gPy79+o>Bhw3ZNrswi%Duu5a;{?d2@>@ z<H~$Byd!N=nU1Sha$<CJ`cU3`@+D}PQU*xv<Gv6q2&>jH?$enNAg=)<clx0M{ZO^b zj|NzrJBeyaqRx{sFdWqb$DrWL{W19zMiIrY1JAgCacxv^Z5)-D(g?Pw{R6*vm+01> zCkBxXwygaP<6b^0HmR;#)UZC4#26Y?YT7iC`j1e<h51O@H$CQHVy@=EX+yPIqlT&1 zvxLlHMf2p?8henNPL(jTHy!30{>>d##h|f$IR4$t25?c&X?fM!-3?QZDcBySoHs<i z0Dp*7JOq+oAieaT{V@8azesMhsMp_m5@q6PJwr_^#Q4O5t*C_{#xq9YurRh_R2JVT z8&FdJ^$33SNF3P9ySPt;zObiYw2t<LkJ%N((iRn0O%Arubn}a_phyv!)p>xa!U!eJ z$xy9Hb;F{D{TRkHhnj~{BZ3-cqCxa8__{-=r-xAZC~a%21z(?<uloL0g@aKjOjP%1 z623C32scfdXr3>+H}nSdBQGvsoNCRQC;BhtfnnnvRvHP!hM_zK=y+(iYJy6`P?!R= z&#KrJ)9pRD{FoE-?#ms{U~$@teXB|}{JZCi1vBYem=cQ(e8m#J{(g;%*BQF?5@dP= zDtP(f>pP7M@Cb`5SS%lqrY_Wc@rR(}$V@zq1&VXG_7x9sMO$m~S*tCKJjBh{aRwO! zF|5gY>VyiuRRuIlrdA4KW+Fr4GJhn4=Z3X8EzDX^_EesA$!slyQJcH+@MODL;w*^r z0V-^$=#E{B_NN?imU+a$c+MP?1IfPr`RnHndzc+%%LNYB4!`9BPBy<dFrISJd~@wx z|0QN0R}2oMKCeFq*#DirG?|~2168h3Mi3V+R>j?weL3G9cYn;~_aThM=Qbz4$K1B7 zxQ@svk=U^yeaAKZ$@~I<y5+)qKUt6CX%8}GKDC`GEPb8rGpJtrOaUX>HuE(0ex}Na zxG?UskjvEJ`63kPEDV5?Mx`VK#=C^1$EwA-0JdEC!B+E?61^wC<-%`QO;0hbexq%F zEV<xct`0e~_dpFxC)Kt=>J>8t`E7x8!+rbpd+(TGz1I@D_H4cEY5hSR|1q`>f5{Wo zguI|g6mcw8;|y5=3P+#QW)c7bTPv>EmPjas%w%B#<8PPMu_`hT?0CW8xW~F)+<am3 z_}0h08ZmRwUb-?a?(4jC<Lj@iW2&M%t`6aM#$Nw$qVi8k%aGVxz2kxLM>7>d;`G!j z7X5E%)hzm+BgWK$kGfmckR!Mqkw!v4&C?C^>T%!!+Vx#bKt;{@zpi3po54vQWEnE? zW~R(7esh}!)jS2@IHK7*L$L&9n`bGwHOW)ko^V^p-I|~t=fPjcLbJqnT*d1^aZ#w3 zdomS*V6U2lK^~RDSYe51$#>jOdC=hPN-JAyd~aT^%bN#}e8}kyvT1QOXr&lf?702! zC$Myo7g-JIDPUbYT<BJqiKOWo5Tk2x)aExVoN+bM+DT{1`}mZ1M$y95>{;tt>NUpX zTRd#Q%XnT3ux-&`6Eh`#@Ug<?3r~BaN9Fq|yTP*Qd0C*0=in2)l$YN1AFc__XkTXg zp9NUgc^)L(=wg_5DO|Szx#C@2nT40s8K`5(2YQ(6%~~ghLHa^x$Voo3<K0mZ>)N4H zeSWotZ*v;b(kZ7#LA5??w-W1aa1`h8j?};Fy;FyZPeGkdsRdo_IC=I)jbF;xm$b3G zQ&`L`q@xi2`Yr11H+YBce8gzR;GR_M>_|6OC(CDC1T~Lnsw>6}fb-fvj+=pDn2tSd zlOmprxtR(XX&AZW84E)#yt5w@TS85{Aj<G*Y|QPdo>6wNy{0&OO$j0)q7ikR2HYPP z2#j?%imfj)QNZiD6UjwS=h+7{zdY@J3#?;151X0IliC){VE8r~NEFan2{JQ(+gT_v zUSyzguoI@;fvpsvS@RKzO#lsOY<MW7xv2*4;g%U|Ix@yAEI`T83{CLoRqDy@BUTMX zx`KF9L25_P3<_0c)twf_7)r{{XEk<$E=gbrRru+dJ+o|1z=9Qk*g;{<GErN);x;wd z-r2@j<ac8SX$A!`4x3-}4S3%DzT5pHSZt8`Y<|gwuG9r8-(e}WecNN5LW)%M;bB;U z_u+AM9oXlp0?Ly0*=o+A?O}b6Nc^M8BX#q@o_mjHLkf=zDKPKlxTD5E$*LF`4#zOe zDDT<~jDRF42B2t#$ylNSa%K<yJ;!S&VpzfVEdbvO{mjzr)SBi9Us&Qu+GSRL>0k$3 zY}CZ4;puf=l!Iq-zmCfF+x?ODQt`B#|I2yPx<8*Q?3q;iT&`taI(&oaL2@4Sdka&3 z%UU#h@BS2kacMh6j(f8QGmT1HY;cG(NsA?mfC?*x(>-aUT@juQp2fH=MC>zuZH)2| zX$YabKs}Bxw`Ka~j&}93KQCywp5p6l@2Koow(RtDVup^n$ZE`W*D&NLlqA>u+>ZJs zaV9td+&MbKRFCoV_ll!>;kvib*qi9?Um4KGVvYV80iWWsZh97I`uVI>NBBaz>fjf^ zAU&>+R_n@SY?YGsqXblKk9ETtV$ljq1{$Mm{FHA4=!cpzUL$CC!{p}LLw@X6mD~m% zc0ALYo@QY=<KtPM>!<a4o;CWcGDbVu*#~2Ox@(q6b7amc8+rNC!*h#9i|JpU!D6;t zU=~+xc_zNlanUm39jsqdoW+_CK__dM#Z5Ai^@nKnyNPt%u^=lb#e_yUMP+nQo;r6? zRWex_I51^_p%I6pD;0SaOCTq8nF|Tb`Tjg@Sh%*rYz2&)F4q??p!+lcOXjDCg7Gin zv?crt`EU+fA8!%b{Ed^%S#pfp@{N-wv|~vY6}EdTN4%zu@A1W3+3dg`z=v&*Ig9lM ze2+O(Gq^PFJ2iJRHh+7sPr{#fdAC<XVuwJd<lZp=<Z%%9UxgsPt&chNLOTRZPV5yc zx$wK{pRdllT;hnkI{&WP95?7E1%Cdj&S3lF1c&Dbzxx89apzq^uLkzKyIzMcw>YvR zy!H5AG1#BKs~Y^qK)JFFG_@v+A)D#ZcXWPNy&G}f<->u%o^sc*hriEpPGmB@W4>c{ z_bALn9*xb#JI49R9o?yS<<*m;dat;Ty~}Tw53amA%Kc^Kz2&$2{-o6muuB3$@!hZt zYP5UZ*(%>QD<Owc_!aCW{x>au=^^!5W#}tur>zGn;E-t5TgsQrZe^#AKmSzQYHDfO z3eqtPd$a{^oO`A@)8U{!D%;*f{`sel*|vjy2ralV^>$)w-e>WW84K)NC!#>ar-kT8 zV86-C{q(}_GxE(MJ#BY<6D=`qqkLOX{F4t=HJY8`EBJd=ZUjgvbzdQhs_2^C2aBp~ zT2QW>KkkQ3*?leI)A1?A6oF6n+>h*Tsf-jD(ADupr|g1f?Tag5<;`}mw3+<xu+i^V zz?stZ^Y6cm<_~OfG%KK+Mz?Lobav{R>1)~PvEIU@#sxI#Uw;Td^Y(EXB+r~_Hj{p2 zLUY6M*LU>vlHRr11|*UlIb{F*q|4^MG~q+`<I^eR)GJt%OxQTiM6iR^El!**dlY^I zu>}CRz0dwgYbX5Kk@4|44sNDj8%hbL`xUk6;WbP<Lm;u>K=0U$;SUXR4p`jLp;~sr ze=wQTBi~gl=YMP}@jmY-`0(W?r(2H%#cxJY?K*-SMjAB8ljE5Yf=d6Hg!Yi`+b3#; z63cqEuf?D=n<5(`UT@2td_Ge=olbmx1$NUh;>F|%GIZ3Ho&uje94kJ$Z4fOO%X-fA z*6K;BnopHCFl=W&DVbrABA&6Qm-Ng4DV5R#-pz$eT2kXON}9(as16<fDdKBn4`;fZ zXx^S`-_w5uR*3@5IsMHJnq!!rjZ323$rDh%A2f6S`R$7{;Ey74Wn_0H$M%pbFe}Tl zc^g%rbtCgoi^gU=ye+ic`E^Oehk=)2fgBye9mR305B2)~5v~HE?^(AQfVXi~!;`f% z9~8Ryp14&LW@pi2s>1ybYOsuR4<kP5LAC9T6N@uxH4eyYku|nM{91_8VCUwE`dGMf zYq!0vZ6Siv`!v5i=8uNXk=T^CUM?`=msux`GoW1V_vK5Z0(|#Adv~O+`}94526tCP zt*E=tuom?@49Z6Nc;nU186IJH+o9-m28Gq;ZHul~>10&Qf7SGhe<nD=J|DZg%lvE5 zZltF~A@hCL?%3Gft#nhwEW86y>IcvDx^C?<eqU=s6KH;V>0TEA&e*RR^${Eb(@&p2 zz%;C1xPfAYZjbvh9o>D}-9VPWd0^Y`&Y1lIeVYbW3oH33VSlRb+b*Q>yK#B@$z!r6 zQ>7*&obO`L5_HB5)=3basLK6RaGqGwkp)|Dj2E3<%|;iz8eY=9Cp1b-t0X9lE@+qk z1Z)dg<@AeB5<X+Po{J}{A{L9`G*NbUb(&~|Zik^NJ5eRZ+a+?I9Ub6r%(C^PT<f#8 zo7!!e|1MfqbMaKM|M=FnheEJZ9LLrmirqvE9Y@Lqk~{lnH4Ru~pKS8X_{c(#TtH88 zStxs0lWi0l>p@8YXbdwBIePub*XKY?al3J3C@w}0HqlvT1VdT}^l|dP%$wH-#Do<O zf-y_<qyg>RJVTV9V!Ji}^ngSOE7*WD_TtkPsL!Lfd=;wIM7~(H;33#^FTs?)EQCO3 zz&m5zIrek$BTcml4(eCS65PZHW%n~B$~e|}M@(3*xh`TjPRp!>mf=MEPEg%WD6)L~ z_3dOA?FV@Kc>_$?^x^%(pqs%$aH~X6Vw~xzX8f+9UHVe&fMUsFyS^&`4dLO6ocBW4 zf~Da82Bt0?WGvjO=#K)ct{L~>Zy{IYo3^y+F8BZ?ixb($Dl~EX6odWG?EicTYIgSH z7R#^QpM2mbtE~<}lwt4VBZ2G?PdMuOc4&}q^sH^$)-UIxbfLzsLtAqtwKVuUf=1Pz zHtsm63vHgU(Lem3Q&L(g+e)aki0RkrH$1L5KA+Z9?{DSPWSlB1zaoEP*FB-<=D!=? zRXe<=N~-v#{o!4~lEofIhqvZ_E8gAWw#nc@|H(e6u)3uk`{_u*U&x$e?*$)*O~17B z{f+;7jZx;N(1_`m3U}`$Mn&N?`D+cIPwzVRpZpi|@ex7;#alW0L$^{SJ+^8Uy`GIK zw2n4@!wN!Kps7(mTuI$mFn@NQ>^slCWpCkmHPM87O-lRLeq2Z36`Vy}THkFyheYcO zQK$O9JQg=WzL*w~l4M_9%)H5Z(<xPq76EsdyPtdbayo6AdJ<}>q}dE6nS*a6S_AQE z890P;UPa0{Lu97438(HSRh%i_T7k>#7@fLN49Pm)j2ZX__QM^dFDPc<w-B59)E6<4 z*uWCycClfixjVb`it|T7e%-R{E4cUD<{tJF0@9{+Mhdg}hc4eYQ*2|zq;49I`Ir|1 z2KE<y(HyF;Uub#lpWoxMJ2U^`i)mX`<+Asr@GH1Cbf*F8V5Smf|8V|fzvCyTKWuj| zP%>vb=iet4cny({___y^?4Mpt+XnYfE}_&=GF+WAoHOiUhcY@oZJ+6O)S-RGWfXQc z=VUB8+Pg;}=#!*|LWo1bp}1Mqd=oD|b+0p>N63r-8Mbz=cU)fVG%nH#GDvAyAXgN5 z4hzgtBJk`sh?4x0XcFM7gy6?wQDEVhwlJJ{e+plHO^||QF%~SCLj5DR<01$8oE-E_ z3vzj(Y&zifBC4pHkf)2d43*a&dq7W^)$EXMhB2I-i=m-b5kK0hKyhL4B~^on(bhg_ zqe;CXa+@ObPc62~Fx3j+-e`!Do*B?XvN}5h{1X8c5r(agTH)G{lKC2E>}RxOm(Gi5 z_w5lbj|#F=eC~`IAc7`EPgmVR2wtz+TO$5}@8Yn=YXSTu$z5O4?;S~`(itBEr?xUR zGs|3sOHMRf$1`?A0h{CCBce6?rDoh-D|oz~hr)FdTtzc<6Y59x8=|5ngfB*&9T5RH zR89>QoQwy^$0S9~|9Bu0nr~YKwfYVAxWr&D^Oll9xsN0b^J50#6MKoHw=h*Wiit@g z&UoaQ#?)POZr7+l$rKdTTr~2FyNa>*h#fqQY`9Ozh;Gnzjwa>Xsc(tMpBZ*kvz?l_ zmaAYCMsEZijI~V}uvDX13JvGZ`wGNTCuS_na8#xy3TBO`B$IuqB;RbnUxdwmrgvtw z``J(1PTyqey2*YZRgEm&=6|Ubq5T_czw2A??$b@dhLcM-my!}B*$RHFy67*Vg4!md zZXI$ehpZdHPxGvsd-RLVWGb&tmh5AmBAQH2pDe-|{72q@e2-bZa~heYgK29F2vcuU z%_Tl(W>8zr6!P9Oak)&5(YCy>X?g`)oIX?Z$=@`Q(^J&(h_RjMpE#;R?bq>9Ze~d@ z29(0~YXcZ$+fik6&dXfdAtlH6^_aHBk<(q@gK*LH6mNI#mu&_S;<^-1lJL#Bctpcx z&d7jc+3eN4B=27E662NTqmsdVo?kVC8z+O=R%Z0RJobd3^HKtyuf_MP!ce@wSpUq$ zdlH|Q&S(e6S_aQdJXa4-<-8N&BoSS;H4K6|78-Xm4ON{Dr`R$K*YBrMRtG~49|=)_ za=&06ARP`-pz8FdBeInCUB*AY2tQ%G^`LGq(iMKf>eN2!_US+w_zC!<S-2|Z!qKa? zrBhds)_j$hBpqFjHnT2EHXYw5eC*DRqvtBBbCkh`M{^=BOM>nleHA1L?>xIthRAqP z_ToyvbI7G{rB@Dg7<~r~N4xyK@6gRBH24X^xqXM;hFl^|-3c&Vlq((m&<8(}ueR?H zCj8R;B>dx@fQoyM3@@|f?ZrZ_@=N_NjVWj;{yu90Vdo6OKi>0eO@V)W);B<qx^5YI zDm?|hy;IWln3W0Y#U<c8SnhfGtuo2$FLm;Ktt_?n<;Cdqim*l=zPMyr*piot(j>Np zUt){H3o?&-yu1`747a<jxKHKgW4SZ(`@-zHKK?f6pFmgn{2w)^mf*^n3*nXC-HEiA zwo4!MlohvhbX{Y{1ebMRQFPp$N&Yk0+z$HEUpW#NjW=&~Jr(AB%i3MbspQ<g{5RYE z94-VOTyTY%`~}vZH~;R(M>fB;sj$mb(D$=(t>qj=No}9wkdI1zrx~HG`}6+u&U82j z)fTV9JRNdLW3=-}XLuzO{ivInI%DPMWSB6!<r`gK)-#Ly;z~z4znxIs7s6_BlfZfA z<VWVk+I5-A#<EJAuXxyR&Xsh<X)?VwXBReqOj9px&ORjp=wWSfpy`x3v7{#ND8&<l zG&^IZ3uB(rKKVWG7W_iFSgh63QHGq3A1})UbnS1u{6Sh<%Mx}8FaDk_1tshbw$hv$ zdVXbEZYy-!N+_f%-KXy13_Kx%5)rixDG`+*@5kz3UE<%HFA=uT#L-)15k7F9UD15X zG@28PAAb}J_ckj@9#;OlYCEDVkfwG28DBK^f`;Ve>2CZBKs)_guGHCb>RzqG9UA-a zlf&*%)llZM$sY_wD5@%$(daU1-9tT8H?~_*_`>LKgSJoJN!7EjEQEgecEZ;>vGe7K zSXiH(Qc)s0s)e=B>c02AJ@il|#{FT%wz|+VcjOmeVSLm~--EN2j3sYB-^&0ixbtS* zwXDHg?h0@TX)~q>y`=IYW^yp`dwf1BdMCcFe6++6&9H$Me-kw-kN!}pVn2@t8;!>} zP!y>IMTN6r^2v-A4`z2MOV;Y$kM7QCA9G6gU~Y5~Gn_(i^nS~*dE1RU)r|#9osFpi zjn0de#3i7=WJpe;qWujs7<Fx$t`rr0Mg<CYVxPps@Mb07k9@oRIMwqLaQ4gox%TMk zvzaev9L^g0eyED8&MS{*q!j447T&~bGyH@N<;(1a!?cr|sGU;TNJCA)e(QG>c?;`5 zx_8a^)?iN66Rx_JG-GbfpO3=CzOg3sfR{`&m}&N$uqEFhstQ&zdpq9QlGVn}TPSE_ z^k|r6<k}u_#1WY@6I<dI@36OfF4-xojLaAoIPP=bALcK|M{_>NJOpYxNUb~Q8=xeL zO9iEYaX*Uc3n{KkmV)_&KEdwJKk#t{oEj4i9}j6u&WBNJ#f6vBoO6_bkYfEzOMiNA z9@&jP7)5rV1Tn>3m)i1iGb7Gc9cchq@MBU(as&(M$3n`o#wqj;fX7lWn)BTAk&56u zLXfr~qW)q-@WqCxiwkb=!h>63m*m46mv%Jhx~MtSUk8Ve1Tq)P&*m+Gm6v8%s^j5( z5G0Lb%9H@0zK&lCh;P;NS51;nwg3!tscD@)_dyc*JX9g|+fcP??$Pw;p}B~!rPXuR z_CtathkzIEPp}_S@Zx)gQLVxig=Md+RjZipg^yIJ&#zmI_151#I~E%1e(Him`$6Gj z<??66!Y@_&l*FkBLN4pn*xupH-;1U2E9>f*0pD$6NlB5}9^n1<XT;0D+ijx3sQBu1 zK7y1~+PQ)_%WVta3ahJS1ZyRwqMuluId#rW|39>phw-`&V4MDsC>6lDsmc1Pih!Wd z&FTmCZ1dd({yI{9;+AM(=~(p%@_&wh4XiGRSL!i3e&@hP_Me{C&%vf@@~=1_AZL`$ zegAR2VdkazW7r{c^AhRC4}VJC78Vw&E$yl<NYuU-9(tAgG+rouOWaN8lZ51{$JG-w zlxwtEDsr2@i6<_#=vI`DPTuSz#(>9{BEEKOOZl`k>Wj}=$Im%@OxwO>GD3PY)pj%3 zYdSQoO;<-&tvC*3ks)t_4ahUYRAwuO=P@r;DtQz<6Y#V%4wfG&FeWk!XIuJ$px)M} zD)VZk60{A7LVQIcjTxH)EFuUqP{Llk=(#{znD?-bNVn>Vb0XNbcM>9)7ojnT$LcXd zAzqWA$43g)HcdZFl?G;f*@iLicQEFg`(a#+y9KOg=~O!Ux`}F;KPQwTI>DP7^0AbC zac>t~g1x<Zx?cdy9AAWLRA7yO8I#~*sdKbm5?0`{j;MGE_ceL#eN>hlrFEWheit5J zbn?<XM{DKG7Jm!%Jfm`C9E&+IH0cLzOyM8805bFX@lCFTBJXUn<Q>0f0;&QlOkscX z-J7h@AjlsYD(>4-Mh{lGq+_V%d+A8TgrWQwiB_uaaHA-_yJ)ffUG<O@wQt(DNUXh& ztd@X@hCbG2`_hA1k)M3rU^dedhlCAl&OQp>J~T>Dkh&kQgzuRPr3ZQ6`J3eT);MVL za43E6l30$)xo1<|?h8yYC)B(!zK^3BAs9v7CJqa9k}4OgQILwbTzP_NeUtNYTBKf7 zez^58Tf9u-euZ$dbl-Hlg693AdEafgor>PKfcxw5;05KHu@a|x8z$up)2M}goaT%m zrTD6bnV@4|gyzpNWxs%WCY1qD=lXXc_|x;<6#<_a_XXq|DwtXwMTWJ^)`=2@J0%O$ zQKm0bJD$!Ld&kk{^j=ut!l5C0urK?)>C)fHho&n2Ts+jvhQlOMoZ;Rtz3KO}wINP& z#+~=f<Ofp>TRtU9^~}qJ>kk*c){gt}rS4ilLqc3k0)BW(&8c?A^$SW)CC+-H@{o5x zAa$1~CcbYM)VGFXJyLa51oN7DiaKc0P==W>eVXP)4!t$!S8r|2=yT9AEk1Fs<b9dS z0w+upY++s&40f4^T(U_YfagtHf+=280l|26XnNm_=g1Q3Go|lSw{M15=Hk~Fz(>a* zUr}$CF6euNZ_agD!0?Qr?Y#7;a?=FJb1^+2roP(NRk@bA`$)ibyu7M29Q4wkb8;4Q z@8LioMHB1aSL3)aiJf0OLLIlA6!g)eDnJ@tgINI!C6U%k`}*XyNdvy5Bs95zc72qh zSxhv|GwJdx!diz0*g?-{2F;1JL|*iTw&#_7QvZ`GWy^kkSa%rqni#HrDm-QQ9gCAn zwJtouWECtF9Re*<8BaiCJ3%u$QCfEe45z4i3vr6c(mt%$1<6RG<bHr-w*l4*>S+Tt z2I&N}?~4X`JU#|DP25!%QKyjht+!e;P4rrL9p~8HGwC69A3X2u84Ih+%>ZCkPKVXq ztB6<L6I2iPF_6k4YIxaB3d4Pzv_A#Dft!BNE-<<0XM-{k(J4!*K5b8*x9?%jcS<P$ zyFWdJM?3jRa{nUOzJ9U^9xY>K3s(It+VrKQf+$8z%<bSM+kMRb$?CdWy0paVYq8rh z?(BUY1+o;U`S?>)WN_!MZSC6i{j2w1M(>rLCY%qyA$#YR&D%_Yxi@IyHvX?2yOl57 zM(>L+IhT7^*T(7{f7pevZiYgwKv><&UGM+sxt)2!W0Tq2vYB2)qoB(P!>XxFldnmS z-wBnce_VRu*YlT+)d%^g+a@We>q6`FCvmS2My2MR6Ms{Yat&8&=SG^UPVco6Vx^9F zwLXBGW^A9c0(R97`>3I!=pl6@syCAdgn)OAZQ8O1uX<Y7$SX~L{PM>+jDvumRPI|d zho&KiY)za3nDA+~pt@)~9z3XHd!(afc+-Lzkqw>Vegy;%dyN-Wr$@m2Ml<`$Ms+UP zZi(Y}DHe|!olm~2fBUy+m7#C^4i9e%D(eh}mHoJFqg?rZ5?);t!a+3V@06gV%L84V zM;2rkn)l?}&URgmGxt-bGCJo5m6_%fjPY5r97rE&_T4kM<WuTa@?Ee^cM3COCM6H) zHB7ZsC0A^5ET2R+6vb$J^|iGjK5P02Vkilfkcw{|5I#vpcM6<j1?XfzU}EakO-+U2 z3!SbYn{Jh3=QMsa*$3D_DpM33)zgyniPc589YZE2dD?#ocz=pP3L-N2S{p4Jg6r@X z7rKM|xql=Q$~Y}Pok6J)ZyQUS*&OP1b-?$?V%HHMw#vIi&`?uusc(*XOW(Q+Ww+f; z>su~+x?c|g2r&szpFPBqQQz~o^P}5_W#_w4*C`6K0#ozpo<RzMIu{qkzf<th#nig0 ztYP@PFRNNCoU?nxFR(<aZg@wD*n|2Le%{yRtrJQ54Uf()DsGR+b~pkit1iJztt&?- zy~X{WCLjOExaH^5S`u<ZilO9>x)e!lU3`|?7iI}p+ZHS{Whmr~=pqcO#u`#?1XCe{ zd$dq@ODME$s`Vaz=mLe|IRSCHs=RHDR&8jBeuP&&`JsCK!TX<m-jx};dqcui-R%@j zFw|!5Yn0KIHu<5d1Q~USUSoC4`hM2JObMMa9*a?t=$YL_@sDp1oCXCloHhact4$<Q z$1nO>e6-#j8!gc^A~mo5iW2as?lMjO1G%cezfNC5L+TKNc#pve@s~e~(XT5_o}O!= z-q5nXnvgW>J9v5_R3d7)_MG36MQq&5Y>UMKTELH`LkmTZpIJA9lGIE?h$i>^AFxk? z%83oZtsWM@KIfs5XF8Or?tBM}QI;39SZ-T^zcU`Xkm=0l!2V-X!zYQkAwExM7c1v8 z=Aw0t+ffU@Q6*xV0I3h8<V5G46I1~|<|CJ!Ka3tPbi7f9_npWs28@2QHFJiHA1Yk> zK*c>Tu85vb>j+5tVJzb0smvZ^IxjB8lsK2!$DkJFC=jiVO!<I<S-t>T{G>n^ryMLT zuHn-oZ^3bMj+(=IKgjnXk9Tzh;l;bOI0{U4uUWHPK{^{c89|z>@|F0T^}7>atIHMH z;4VPAwC*(fxs`;HMpZfMP(+`mn?)!`)7fC6Rqw1}uiJ~Z<mm;EzUmi`Ea9G&@2XEW zE9Epi+-r&=n{xDnX5hCxTx?=3rE*@Fnm^RFiB&k6^MV<Y?#_3~cqgnOM$Gh>%B8k> zX~|Q?yF#CN!rxRs`JAPgb1pULop77atnCBHlVdJNb8;NY605(<@uf+gO4gd*#*8dD zHmN7@v>yJ(T%;VYC2pFcenw#SlChQiS0%ts$2&k9A&(d7rIL@pKO|L!Op{vvx{7Re zd)+N=dg!(}df!J@X`9RMIdY{ll1fphc3Vo0_V&VWS#?c$zqS@L6&kv6!BPmVYkXPB z7`b!Sve)XE`mGVcQ<9@Mka88d=fY0*4aTaD<_N=YC2gI4b`gH7bs=@uBq<>8Tn|)< z`%TO)DakbTrPhk#$2uk--|JkAr@q;Fc!xu(9w+TakC&`S8$#67B<e{R{1$9;BUQwc z_*-uHJ5Td(-PNhOePBz5IPzA2m5n8n<3i3=OuHbMMPJZ4vtv5t?jN@)e-HA{Ft>kk zvfEj99wU;1f%}DhzT6f@BYy;iz5EmKci(ZAb1CPz55gvB5%^iBtsZ!u67!Z1hUj(K zU6Ma^L4oazp0&-D95puUa^PfmI6DQni#s?`9BCAt{LX`$i_M=C?>X3z4H7zidS+$e zt*;tnedq$N^hPH42^7>1nxdLay_!3*9&MJOKr@<|sHx-JdwvWos-e)l>$7IFG1+ml zSht?p*ruSK7TeubyM_7Po&GT12-a<fQ^-+o?+jcz;+=3`BfiN`u^>X6Nh0d;#}2jb z#55?<A8uD41sxLc`axlh2I4c{TtM=9a{?d0TY(wma^J>9&tz_81fTi4K=4O*kS?rX zDJxHq#m<`18mFf;=+=>?+%!MXtoo!zo6NrI7uR2R7WYj*UO)+^uzK2c!>fXW5Uk$j zs0gjTT-4rNiEhJ@@yMbkistm8WZaD5@bDvtuN=de<Ybl0ZRZ&idooayetTn4LM&6Q z!($6~P~z!>e=MARg1%T05bmYP$bD9$QWrf{q*PYl>jDeLgr*;w9@$3JotU~p)ES|i zaMye>E8okJ)Y4@%+p$F)E3MAK?oWsWQQBqTN&=WDSAWxzNq<~vAEx^3x1tgUC#$5+ zOa9T-eVC?l&f|2wHpAvzB38G}X7o6g`AiLQkB07<KaRVWXPfE|%(WE}G^_$W6UWCB zJ8j+3-E}vK8jET#L7>T+)1F0OD^RCGFlTV0%L3&ek;!ObYKt=}VgbLkOa@x)b}@^$ zmKdoCZj(zK|C6QNOt}2X(k7Pb-F6Q|lx}!!SXaI;TU%(<s8IgaD9GXVVD~v+fY)(Z z6NX#KTq&ub)MqM5^He>8Ii3C{)9)DPWXYmg17_T`UV}2xt|BW5=C3bNN~Sc=nRj3Y z7<5g(k{Aio?y}sHDz9SG>AHr63zmSMqD@i!MR|b+fZoqd>@eF|X$3~4zf;aENK83x zJZb@+S3y0fwDh9Nm|AD->c1Zr(~cu}V#SyK7?fDZDRUn*WK1Xf)2F`}@dx~vJ7k6R zrIotoGwcNUIc+L*k}1sRZk+oA0AR7qns2%<eo4HPnpF_Y*1p#eF)_mZVfGYt5(S@$ zGu6BhxqmiJu}^vcKt7R^0JMoadphT3df1pk=LLzw5+u-@XEIr`IUJ(+_REl_-ZLk2 z@CHGZS?W12-vn;TQp?eD&VBjPq)VLsl|-e5jqTea#VQiXI+>%d{Nxzi&tJFwH<CRq z$vo=g=G~GS7io3J;jy=NLcjf~DnugH-w_*oF(yWF*C~Tn8?-%H%F@bl-~Im7!?3Xf z+9^WtSQBAiJVrq3Yu;nuA%5=zwim72_mYw}n|*Drmb2tLUi!UymKHNkR$)EXf?Gbb zdT?BK_Gz1y>f!PUu?D%$1Gc4at4prP9;y!;a|2!Q+S}Kg)3`<8GQ`K?`^z6Bq~!%! zA(zxEqc7YnZfu?S!u@Y-7tE83N&De`_U^aENN*H2F~5sSv2r@jb51&B=E&uwjp(-S zJkM~LGl>x=MG>alM2z!s>f$DecdpwIzb0=FH!-7<kbX)2tu2vhL#}TQ=lNoi;!H+a zty4s&-BZ>^yT`DDw{3_id>5s#neRL+KI%q7GtOIQzM*$0!7XtjLo83(yH++TCw96i zH)2L-7NBM-H;pcWon6@5)kKFcB=o`k?&GSRLJj-$;C_+qDor2s&i<VcV&;UV)-SZ( zG(<En9rP=F8XQwYerRMvxymwU>O$PV#1Lw7RanYI^NEJ>MQ?1OSz+5Nh}Y1?Q)*_> zK^pTz24LE!&q@-X+g@T9OY}LNJsq~!Y+%w2CFb4O3cHtvox*Uxh@$awyDI1L=^iUz zT1A=`E{{l<?e**-3P6e1ooNIPt9--;t=^Qaprz5*xh<GgfeV1xc)h`;6$wswtH7|p zura=wPgqUzsmF7IKc@dO+>7HA(3%_mG4(Z0aMTDd2WLOGKqZqRCLH8_VUy(vzSAFl zi!B2}XZ^-}ECR%-!zK4L--r8W&JgI*8FYENku6(BZ2KNQEm#LVdB)-Qu(<hvo-;c@ z_=d3ygDlcKT<bRK4+pW{j=waYeV<2y@m~Pf1cQIf6}kWLQPWb%4aRad<3nAX6W=9F z`yRj*RYxVbN@PgLN9RZRhF|C0?g&?K@2l&sZHSAScP>I$zo%~1j_c|2egoM*fcgl+ zG|`k8DmA7mdUR_q+BK&mB<G0*(M8p#;zn~L^-gfDH-|K(bCYXS!h+ERd-W3M=sw|z z&s_=?epT0Sxe7TTQw{Ts+{w7UqG&J&rn!h(Dh6>hm5MRWbjG}|8sP6Tn9J;D|GB?Q zc28PdDT`RNdeT?b@U_ChD!t8c?oLg5_0j=)lEdv(`MBu!4`}jzWdm-qRl~cf!@Jas z-@)bQ9g^IKPWdlfrJICI=BeX8Get{G?`z|PoMrtflf&vLwv}L8+FdPvV&7B{Omuow zSHyev0gU#**-d+~P9mn2^HQzzg9;82nBmbms5wXO7;j_$*wYCQ9Rsu$MoMs+Uy>UN zwA^6Mb={*2+J2M>B4A`rH<oWqD?U8PcKUaI0YubA4?w@E$L*yuMa?=B-Eu9-%HOEX z*Js2%1;mp$XO}bvLs`VUfcj<}N}?)5BNM=hPT4;K_?9a@scp}e0d>egk%MePv843( zuc6gy384N1GTVcC{^~~#cbm!_7E|NYJ}b!rxV;d6iOjV;_4bhr+})tQTE^<YcAbVV zm*Wp2Um*AONm4ag4dDH1$7;($s?`GA`V&nfmASVi#`O=$p9Q#`6VWw5cSR>iN~ej7 zg&@a-;E_f<dI!fskTwb~fG-MeZld1?tM!zExBU*W@_ctdZGMxeWODrW0;?0jR0{+9 zyw@~wwL^&)bZ_qvl}Zk!Jb0$l@DzC0v;Xz@Ce=3;KR(E1Nx6Nmv2+6VTXcy+E*toW zys;Km6B<jq5^+`4<iq7-V7ZF<8>8}hgEwHO2=P<iUs*ZVzRu?)!Hu@zPP$7apJb=K zF!D6&zX{&#Z5ci~Fp}CW@JzQsXu9~ruG24&BC=A{@4l*g)s!j<Q*ZRQqzWqH%wkP2 zVaN{91?hNqM|CSBf%IZq<%chk>QIv^l=}3?Ag?3P*4C&(sFl}|=eGoL(0eUqqh?@C z-fYJ)xRC^9!Q&%fe-}2KMr;~ZS5o@89oluruiwHjc+?)s{?Bb8HU0|c=dg>uPCal@ zJHIXCA~SqiQ&tG~1XY#rK+|}yFzHJTz-g?WA>w1oPA$Y(7&4}_^h_4o9?%$R?yFo@ z&$4UC&~{F`@9t-(t>os^hwGecWSmLfCLlY3jYZ{;2Iwz2q;zW>4D!zKP7`t_llaOD z3B_%1E)=zON>SwyUB|3reBkc+>NI0r^NvpgO)v{*;(uI<OzOvnTQ^Y!idwQIpSxO* zRu3nFV)aX>tB0G<xY4TU{>;MEADh%Qzv_}Fd>V`SDu$el#ogF{poaeFE*nge&X9ON zETzgUeeV@g?Gs8}7@F*xot51UoxEg!25Wem7$MHCa{^fTzQQcjc3J}shgn9NXZ|CP zFGOzgWqs;Eq3h41j?8i5K0%-1<KEZ)?k|=YeqmM{jL(H?7Kl!K-OGG7#M)adnxo|Q ztXJ!`_C;4QsHPh#f$k1vig5(e_!ksHo$#HEB85I5Gk(k#2VsM<L(`mX#jp!N`9|+2 zx22{*M**SzOgL2W<W9}ASJMv-z~Dq{MR)n{Dk7MsUR;ZKUFBhL)kjd>RJCy0Qg(0H z8xRuN=k1Klr9U8A4^BqepR=m(o9Pi^T7MgUBMVpf_V8LfVJo5}^$@1n=fjeL$MGT^ zI&tW1h(P27%BJLa6U)<ms<6<S`mM&>5Mm7c%;ERxb_sal6D?VF0E~VYtYRJrMXT>d zBl=P_mFn5{y}*P~4|a4W(Rr9<-cXV64c$(`XU#e;QXr1UBk(r~8bwnAY+E%^P>SE% zJh~YxlLRx7uuTJf9?i7}=!UuXBSwABnBcn;sIYtW?t^usyNc#ZgrRW)jQRoJl32rB z!4^&+ew(*!eEnuM?fy4U-Q+w_{+E~$i%ZpY^7~-$b_oWvssUc%oAoXq(3EdD?HEGQ zw_8fN9hd4VgZI_J<A>&j!=h50qu<35mfWFoUQTjVqq`S;1M$1mOd36(7F$ozqXtK6 zAHZ{)XWopkzIXXvreek{2Tog5Y)SL(0gskIv@_fA&gtyR^nkKRu=gE)obO9wzUC)m zdWiy#GF+kFk?DTW*IA$>nF{r@kZ%)gsFUcTd=&(!1N;^50}$`S{GAUlrHkkFC@Paf z_`xaAq6&d|$Ti@{uyx&AuTiAz2>X^SZmQf^VJ60kJ=oQ5i&q8_==-HW8vdR2-4eD- zg6yul-JF}uxB~i3iowiye;%%G$-04QS(InaeZD&ynjy|!Fh3GNaKaph*<%eOX4Uv+ z3H|_Wj<@YnLgtp)BY)Ly@)hj$`WqvV!u}gy=Aiy?{I~4z3EFi9uh-Jy|3}f4M?>|# zaT3asWZ#QK*+aG&Dr?D>kUjMkk$syn7)x10Qe+op$ucB6Gi1*)#+r5PGYqrXhGE9f z@0@$yd+wj_x%YhD=YE#wAuTDLp8X*BX{*Z<pi`$(<jYE?qk9)4q)6&-HcXp?vuUMy zkkV<xyA*@n4`I)*4T$H7gI{a>;~A(6HQ0sHD~sC(n%_jqvsCA`-}=<^({MNU$ybqq z6?T`fn@BnOgC(Pz#!nL0z+TIGH;ql>*Nzz^vaEGJZGMr+s=0N;#sFtTasD*)mc?Eo zYZCZrX5Gd6W`IZMFQZ$nf4&)Q{LRz?ekwOe8<Jrkl*saNesH7T@wxJ+AAb#gshIxY zGu*vU`?sw4LlYmxvEkB^uSJDXMnL=gtdUdO-B0UtdSk5tza9=6SwHjaVNYwjh%heE z`}GO^C02iTY~_X5IxVfO^3lzT@Aqjxk8ING1cCB>oBrgAIm>Y4o3O9K1A<$yTBT1m z-YNf?oOpOAty!^3*m_C}C;jK8I@P<H{k8*_eVkSqW9B%G!>9h&&Y9L0>~Ise8lI=h zZl|{!3J|&%%aGRQa{s2#@nZax+SXih=+tus!SS72%|3RV1GkFB!OA8+C5D#s*?+^0 zQ;qHw+bcVG|L_b5Z#OxeBfk9>J15gQWYjQ$%ut_?g2*V@C8w<AZFwwQ{}gh(1H3mA ztA_6__u?ts1HSw{UL5SvK0SN5BR=yWRV$w{M;u&mnl~}g9DK8Nw4OEJvB7XRBDZyH ziyk8Sk8{BLrOrRuPYa%rkcCvk-5a%#&-4hf-m_(^w0-UDFg?5zRs6Wjq5XJCN%g=F z!GS(l?&*6&eK%WBsIN1f|GD_=tC6<;9{mc(5-dtxTVmvT0I`yGWr_hgyJn6CTBdhp z80><<aTT5yIZ{=Wi@Qa<(8m7oZiQD9$_Bt!Sj7y5-Z5`sos?p76EH2TS)wv!4HOR1 z&$nSR^uHhqvpcziG+P@?SZT|ko0dXB$0m&6BbfA_tRWkp(NGozvn-wgwJI=ITsfD7 zh6%DHNn;_q(Ny1`$!v(*?G~Icx*`&hCwV3d1ldp*Wzy>=6?4uu;x*z380(AFf<Xv@ zbO-?`rWS0VsML*)g1yNt@aNM=KAq=$1B`*rFQ{=Z!Mu`uTLXrN^4FkgVCvTboqI7! zZ#D!zpMDR&nMpjCy}~@aGk%7bYif_jA=m5;VqBZTMvw(34o=K#$A92Fp}#I<Doh?r zI$Cd`A7ch>rXqT@Dq85xpu-Z*6$hU6)f*?1Do3%I@LIRzc28fYSLjCdaO2YYK)VVA zI^is@9@lN(sQhWsF&#bb->!^j);@}oQp27zBN1!MVm<$)H_Q&HYqPhqPb>2a))$7x z5&KN-Gesfx-Dg(Fh8BbsGNKMDRN%e(1wA|-Jbkv*s58+P6Rbr<yI2R8k<GGC%MGEL z%(UMTr89E_gIdEU&TVU1>GQ7CYW=kNs<_sjIk`SjLBetzVv^K&3OR--a1grO#KiEW z!x6`{&J(eAU|}P3_Z~bKAdPu|=FlWx83>7w<3KIfh>8VIozGoVtV;bC(EUWjV$Xt< zy5jdtEOl&$e>hbm=WKl%T6JbqxjNZVx7O6&M><PI(255yQ}R17?^LDo*w2ki-<@(- zsFvyl*3)m4Onp-4vF8v${t&7t(xB(fIi2|S!@P1u$4zzaX16czQ)+JbpV^3I=y{`x zmh3F1N4(jm^1Zxjduycpk>`EL#2Z0gUoRPoljk!O8N(D@91~E!*Zq-Pm^Ohl`(0Tq z>tTTo8}ZQ~^T`;Kp?4@JmYr2X&Ekr+p0|Ng%{|@fC!W752RxW^B-HHj+d*kLmYlC+ z+6H13h41NmSO07FdLb>GI{!@PA7?X|>Jq-TF_@F;9F@&FVf$RLrNiMLZ}X3>NWzbt zj+OrQLi#0NdXc~VmP`m%&&YaL`>0dCplHVH-Wn}m>_waTY#4$Z-{yrJ&hLg=Mrrd9 z%Oc%+8qNz~1wX>IgJ+K~<jD^+k>wq^n!ilifv;nST~{0%)ch;rZS_U04jS*!CM(Mu zr2Q2XuGAMoj<o1@qDpLTzR+HBj*(X-B0i1StXNngJWZK|Vg5Tmv(oI1+w8c+$y?k< zm5xmA_V!-Wqo;zxu;mI(RhNrP){R#UI?Ma3`aGw{_GiDO*%!zknCanz0I0&7OXnVy z>GA#07S%w+xBSKHee7*hM(oMmh%`6vZF&kC<gm8*Zq8&+yz!A_$JuLb_zb*c%S-c? zzYnU;e#*dGc~*5b!5$J7nlt`W1F=vt-MBncB=s-k<XK1k`cZ$ou1Lt&Wb5H5Gko^| zB*fd3GXH+saku^rOP@H|+mFytBIiZ;h6Elq%5a>bP0jH27$=|yTFPImtdW5bBunps zEn7SxHgmvCcSEdo-DsPYA&%I|_ZYklhB_6vepam>!m~#oFltiijn^?sXFe`!)eh{# zecP(J;}5}la*)MJ7P?*|q|6RJ6F9+QoW*=8?Y?23GutXKhYg2HP7y;-4wviuhKE)+ znqf`h;H?DjjvT5lWK0-v+YLHR!L3{R1A15)h=MQRZKW7(xsm&`+OHb^Pq=v_R}`Ob zcOJ1VFWjIge{Mi#t)B}LilqDyCZJDmYz2<79?~}=q9o&QXw5_wyp5Cw8)Q}SkwB<+ z)Kv1}iR6j%H3-{T%8&Jbu4!5+cm*w~-U<wlApB3v;+Fs^ETMvOdS~a{lrlTkpZ6ac zx7$|TJFo%%)q-9k-v*hbkxlH{2F5MHFMiJCZID&KrS`Z5HL_g(-eQhc49zE}xv?rM zVRdLS?IcAbTM{kn1kQ9KjCtKdBA2r?riOcbs&N66C;7AJ;#B~q7Z7lyor*9c9B-Z6 zujT-GJSgs`nlFeY)_n{X%W6yo`KH<N&79Qky{gsJNrNT`8)J8GR~rvw+?wP9n2yjN zPn!2Y&1mO%G9$FIhG2}a$<F!WAMqouV$H#oFue=o^{E#)WolGiss1+8_%eJ@#?$d+ zWHzW8#)W}kddVL4FnK~jv(CT9PKww;L~$0{Jvd@zuK-&=Fi(>mL3+%{p1lS@QAy6Z zmiD<Z_Sh2{ug2Y8pOI)Zkve?pRg5Eq{?1FKDQZF0<AVP+>N=l&A2)5EeH51$NFAgi z_I>z#wy$}rDc~0cnj!lxsqj;|J}1hK<%zcFoD?l$nzmfa@KX3Up)fq|=&%N}=z>9V zDy59>NPDGZ6~8*9CZQ2{5t}o=df|}8Q#HDy?TgR?U(tLOgw$~FqdI>U*tm*DyYy4k zy{B&6$<NaK6*Zr_O~v)3X;xelj-NQ=HTa1wGs*)hKJ8)B-^#uDHu2fHl&aZi`~C4h zs1wgW&hk%j;z1FqMn6<zJ8OVXH!UT;Tvd~J;q?7(IMP9=T-L8ns59)Jz-{E{vtM_I zlAqy0>YU}zPK?&&;-Aqfjd+&KrQL2r9^0f&F#0<wDnE7gRS3BAl+QHb*-U#{i@W3Z zzXN_s-s{HqhmEW{nxoZugbcQ>l}*S$&AdfNHnuVRxw~uR*dYGY>hA@UpYb+9_TPVc zB}}YWNm#Y(f3NO1OSDS+`HhK?RGw`t5oD!3S~fLh<k+tBv_9NvT<2*}C2a2I(}Oj5 zM*hK^-d2m>{Q@Scco5KOnj`61mwZ~wgAs$@a0?N&u|iU<(ZYAyt$p}ROHQBO&)bgP zkMw`qa$>p4?OP3gHf#D6+p}iR!)2e!`L!1FzWwk_rp-R{;_<9X{KUe7#5y?5qxIH# zyz0X<EnrKdXjw5e-zaD_HHG3^kelZ|ZVMl20`Y#w_m#>3#R@GOAEkx*UM#C`<>%Nm z=9oS7rMk2L#oZJTVpW{wi~G<IDXBOpTJw4z*VayHzSMCk0%W$l|JzBsYO(YnyfBoR z0vsho?T6nI3XRreT2}3^cY8zIrt1i=X^H{+*JQ^{Fp2U%F8<~rtf}-A$rD|V+?-Ji zi$!6<;b2iT#!tu;woJKu3i|G}G{ZNcT*TjWFFIBN>~%B0*jG^X##4nBauG;jYtJ1h zI_#scxnq2kT<caTn$i<c*}i)8R#@Rf*Pg3r=**Mk%vXRbuu%+8c+My{mUPFb-2+__ zs#(kT^~dzzn3h`uzyv<$(jDAX8-DgbP1B85wTZLdPevwhuKWh4-}9jWt>(*hB~(qs zN=bt%<dVIiK;gx^YCh%ASXJetWiP?D;Uu4&)U2#g_KAZOVFGrhGBI+mHSnt!liQ$9 zsmi(WmX_a24_XIO5T$&3zF_C}e6jLl*ZcDvv4$S>XYxy39P3BsFupO8glfcpv3$$z zMo8XeTJ33)pS>(u3ecceEjbnT7-N<vWemnBhv_KS4T2z9kiq@kfZ4E-!NGM(w6*gn zjg@5m{Nx8n#@^s>on-yve3&2APRHhimVD&tOXEe<gDQJ=w3Mbvr{r*ndMD(RS?UBw z(_3>wDy7aMTnFWr?wNz#Rd&3WL>}BWqTV6EJkWQhtm}4jju4w9A4>f&%`3Eac;--R z0g8#*0o3Q&G!POe#P(-g&{s%jYYRG?@N}BiWKFshZI=pLtkHhj+P$zYJEMQH5csdE z@w`iUmp!Bs-K7l09ivC;+uyusAltQa5W>~B)jac6%c0oaR3t-BR4ntn7IyK0sD@sj zt~N(bd6$aD6O6=Z;6$@8H>TJ_r`N5Ic+7`}f>)d1G`9$|BfuL|)4aqs=?`tnj~|xy z%Zw@Rj^ql0-9!@G&RqZSe-#7kC+XV!;{m%(N7|;@RI;(XH%SXI4gYry++%-Uk!UrF z@5kw<**wg>c9`*85R9phW=OO7CG|F?Z7;{rDSJNO5WKlkVqbt|+;t0l_dYFihQGnU zX^PfAn4wV0vLD5hmbpz|A+FGP?@4^yXCPR8Z6_Xp{LvO&66w6W)-UrTWz1EAa6#$s z+PND}rXn`U_m0$A50?b&G_t?q>UD$n>}fWB7b}z7jDJ0-H12NJ+kR~FLVYRljfr`{ zx<{mqYnZ$z^GnAD;O@_OXIHm1E1rs<=t)XvTYsxCX0Yd{_MP48!cHE%^MhhR^{MB) zV4DU;gy&Qg>3({JV8?EM#pESky~W9c`{9e7yB;A?L1`h$PL9Q5)7S-7LvdKjY0$Y9 zAvuVw=L7`cHYe-%%V6k(gMCe$5H~%rIU;mTbs{siX|XWYK%X9C0FfXVkc7soYJqB- zmgyJSJ^+w^+DbgU@6hCm=}TW9q7y9xYO`_2ULGC~qzKkvx#RO>S;Mchk-8U8*XpNE zS}Wfa!&^yvw9g@C&gLOnwR6kCFd%vCdwb{{&X{>Na49Wi{e{EYLaEgMQE6o46!k;1 zKSU>-&^Nw!7v`xpTFg9gO2^(R8Fk3<mweqPa5@toAVK)1^09*1`S2so1xOYi#?7#$ z7%obvfc4s(JT`x%rjBi)ywavyC71U9UH3(#IzdAI;$)nh^TYnMM1;;GMF}Qg>OqZ; z7*HQgug>1FzIpFHrqofWKZ$_^HW14f;04D#jyV>%IbHX9b>>T&+H*6Y=N{9lT6fEh zK!GCkV)<_DSV);R#}4}zxSIcW++>>C5Zr~LK6HSQVem$dgPU+&Z*&|KoC+6MtD;gQ zhLSNpi}74(YEKmmR+Rn2*OKotEOzZWt;O(#r}Vn)f9QvlpJRBN(nyTbRC14>tXax< zPUa->F0AdtDhSuxN`4GB@4D#Ld$Hc+{O&0=x@;xvGzqhr1g81i%05Uqgj-+sg$&!? zOR!F#IMCFF*=uE4rw?xn?MHOkl9<FyEmpZb7X$I_Z=BHFke~TxKf0a;Xb!hMDW(Pr zK52B*L?U|nd^RW9W`{?~jd`3txXC%nZUazxQ^OL8ULFjYAYC~_K1It?q0^XFfTB?8 z%m(O6@<!7==D6mjp&w+(f`m^#ZZFq`fLl1(MV20fDep(si^bPPDrm2L<EWyVSFz>^ ziIw9d^6hROieo1G+9*oeNt?}I@dah;Tm{Axq}%v{G5_0V3P0xDep7~o6)gLHNv4sT z>(&Fp9krEr;T<mT1#Q&35Zoum0PE}mSZ=#BY1bxn(>Aa1Z*GK_DE!`ZMUP_@-Una^ z_gk#2rP(XjO*Q|rJ|!Hv<TX1;O_5h3bhLJ-_NGGHpjXMvb%@Sw?+%h-z1M!Y1U`Qq zoRf>lsXP;yE*Ktu?KYus<byhKe)H?#Y?<N{)@CAtXr;C8`Lss7%_MLfhY)dB!p^>* zm{N}hbMa&31wdopajl^ktz^$>{!p{;aC0X@6R(!TOa#2x;K;7mr9i)iTp2&UB$6_= z%70p6*5^k{^)WpHB;an-wDiZv?Im=04QT>h5(pz$zfPUT+r-m44+Gj+wtfWaUK;dp zv|nL^q7fs3IQrhNqsCQYKm%W{f&F(Gdr?{Z?DX!^$#H;-*;?sj+(3=S?zpk8AyLb5 zQIGX29o+3R14-H1Fyi&KwP6Q=V_TCK#%pdNNvF9MHTQPYArd;|XKSTQ1`$r@&psw= zm{#YH(e%DIcUe!OgMM@?0OfZTu9BnI)0_?DTzg|Q6)M@M9Gj$f2me|Hhpst46K?qv z+pi#HtwH|lm2{f)#$O4}mt-Saz~XP?ehF_SEOMM#wtTJLS=>Of>GxG@{RmgjJFDSY zN0}l?r*~L8-K;czRwtc$c)38=Y)W4p^xh|I$%vmN))n%^hxb(X!z@I*Vc$w*{NPV> zv$v|=gqsLg|GfCp$<<5FZn|i1Qr!V4x$8L{6_EyIXRqdjnd-YU2Ub*Mv?xm;^5IkV zV#m`{(cnnSa6#wN5!_mnx8a&v8FMHkoTsDq#*R>8i0(<h&-vUQKksKgt8Yioa<IPX zi)x*9ms8aCOe~dhex79r*4*69Nsd3YKd3$~>_?d7^6sLYc(3S340@zN4H<l4R>n1W zQ@e%?gsNyr0why(p<a1+j_8@A<SV{Qz;jUM4)3p_iw_}0gxjmN##LmnibrWFnJJK2 zv!T=wLi6$A)x-uc!|}d=U9GW_V$sD+rckKZj@G7y6i#y$ZHt%R-@MC7Y)7aO-E7D$ ziKrmRn$D;os9A`%FmZOh0MMVhVEj<5a8-9JEPfH#4gPl!cXnne0_*|lIg6#iG6C(O zdT{dEsbQvmgiqZ%IRET9CqGl*<|{abcuwZhR>MX^g4cA?H~^!m)zp2=z*b}k6imTw zS~`kD>0s=IgLH_3jhrYGi8BFk0jl-EYnp9t!H=F7kT`AzZGprSb6|w2N!Pqk?CM^q zPA(FVxo1cmza*IQtjoy3V0pjD3Et0Kye?YBtk8VVz^oU${yab<rLXVc!)fL*#<fn< z2?$%FuuyOHlYiP~m0`H5^2#u<&7PatZKiVryCzP8$39=tYHN^md7l*xlcCMuIrv#N zw<)$`bjiUJ%J5odmPdqP72#`nNUl!Z(2%Tl?vMPCDk$IC3`IGI*-eXUgE%e>KM>8) zu^A#)hNmJo%GblsHO$xOzE|2+8+#+num6j}vAX}hU&(R2uY1gwNak$U_UD!J;64^x zt@%pO>4YYP73?0B{yv>(rraJe&a*OJfBx64U^6RZ=F~N`^@GzO=p+E5-3Qj#$;fF{ z=sx))aMDxR?;JJAg0m(LXSSXGIFZ?`dwTlibeG4`2Icd`32Fj^<*`<P_l3gX%gd?} z(27#e9$T5kkp0v1e?E^BCwBDeevBY=sgqruhJAZ%0aeSME|@q;7raM8-@+^)0nJ%g z5KG5Ns`kFeR<tTW!xtJNp*8s|0<*U>Qma#W(j~h+O32&Aua!Fjn$9Dv8d||wjSFEl z_6i|;tD-GC%UQsUEuTfooGnp}dN>AxIh=IQm%5!Ch3Qn0Pv8a2G$k~1ZYT56(8*ic zgJX_tOiYv51WcC_-k&Q{)aP<~MT?vgAM}ndWd$?=f3+e~x8Xc}7BoUl!uinvBZ#x* zgM#N$xmr>~Lzh+ay3cOzm@WsikjF>J<GAAMvxc1lt}h(9xdp@+-R`|>xA3)Q_$thJ zCdATLROp^At==j-lpOtXp=c>L+gF+;ksK*!;fo)WmR`;$&qaUgDqcFZQxwe5e=u7q zZ6wCYczOC-U-5NI_!B?nD&*t)3jYKdXG~m}o~Oqcrg%OocmxQ@>DrezvWi=`_&9yd zcO+8*YQfFT{m`DD4#X22C23*)Q#vs2(TnigwZ`OkI~KkV48Jm$78QOta6L5ae6OwW z%xq@2Fy&XZ<4wH2OmSiE{JKHZ0UwzO_gCthOuy9)cFLa;>9XhSC3;bAL7kG+2f2?u z$|pE{n<ny&-3%YN*2>I5Y}w6ETn&o~AB*ra2g2+Gw#yApJgOeh1}8(Cv*k;558f6A z1S!FMcM^{+%!}38K19pBfk^InX3&LsCWd^$*;J)O+wE6Mq9>;ufNT@bAc~`u?3aa7 zL19z1CGy%q2SxdII8^mwigXiifhP%8z(E1!ML3jBvmX`FpVv5Zk-gK6k*XG>HJ04- z<`+TROb$Zq7n;2%VCP*29=w_t@`;bmnE;Ldly-j^p6+Pj8=$Pt$!Kz1TTVkqhbRMm zN@DG0qSS|l=)--uiWx`bD0F7?DT6z##f6fH`rNCGA@SjH=#b}gkI{sQ94#BY2e@(z zUmN{G$DAk6g&0EyA?G22Ns!r_8idGMgS{{#IXeq7e4eM@G{4rX_rS1#Tu#t#Z{a|j zs$jq8kEjQiK=^<y1ykf!w3S)w7=~UH9I4il#~2tfDhrf$3#r@Ca3p@52NE|s-8cp( zEi3aWW0q*KaxupC?oItJ!{OoLuyK2n)X9`+ZOTI5V&9uXbtHKmCbbpSjCJ!uFjy?L zw-zG8%$BLoggX2pfo82bAK?s}D~_!%uCg=le28`<iO6DJ%wAbuy&+WmLK>!np#>bV ztzt08|22WS{KC(L%+oWe2#KLiquJCVvb6GnxQO#a42p7m4gCRCr?fAsJ6F4s8ifB) zag9+Sr!;f86GTZ3@d9wbALiIpg5Tfbnox=Ag{^3yXbD^Avkq^SuLiZ4-h-u29>nIG zS>SR`aT<<_Ry*TIAVGv_>1JSPTaS%0h~ibJJl>LZ)V`XVqd#bSN~?~58xPL3Y4@=W zuQ!t?w9ItSm~(eMDeBnvek(^F4=Y)((@=%-58jhpyu?Ly_>>rJmS<=T-cb%{9l~JL z<uN%5xn?q;&>!>8<$hnZp~+;AY_K+OW$&_(UAS(YDm|smV8N4k+8{zC+Raaoy_OR} zaFMm#wnLgKi^-Y=Xxt>(!x<Teo2+qyi_M>OF0zL;xIExKl|EN8e_2!}0}j%Ia@=bM zj%juIr<GH~Q{Ee?&J(Tr91X-i*cA0ApMBNL&kQt?#!m18y{#jMP|onQV9cl(erG9N z#N#ymp4P#V!ZB?n-SH*C|MhmT4@dGLabI+ApRBi3*FLqg-V^?EJ75HlnWnxbiD580 zD`JXV%=?EOL(>0`-ybi1Jc<hw-H<?zMRx&w^-haliu~BL2omes`<hLgoQ4kXA=(0k z8&_4d@c;@^gIdrg<*T{;R^#@@BdUfz!V+I#P2L=~;I}F?<IcC>jx}^idt4*Sf|O+y zDk4@!SsWq$j<WF@xL8alRVV+cYwgUJmYtGdK@P;JT0C!a=FZ2RG$$3;=w0ULdXM=M zL;u2Tz+h?d*sEAkj<LGbz97Z$VQ%-L^bl6yeb%mPb;_U0n?vz`wr{<Fj!Z~D$%s0z z_-ZdiF?4yH|16|K(oEzy0)tHbb0LU_E%DDEJ4G25;{n^2OHCmUMELpMyZTD6lHZG* zzktwK-i)4O@d7@%<UjuBDFJS$dDd<P1t-SbJ8Ut@7SAmfjXmhRzl3&?q$?{I|0Wd? zfA!u^zjM&J__MgECYzdBLEi1Ocutiio+QfqinG9EnSNK_4l&8C&gOn!kM#{Q{wMmr zp44p6KHYEO=E*&E(C#GkkLUe#V#rRKbfu0G3oM{LYJPfrlOk#H&m5?R^^&Odes-38 zQe0CDP;>1nmwp?a6N3Cx@}@?a#b;CK{jhtmj8``9z-zzF1Zr3L;m=%;cLLNH-qc0b z+V-iJWFf3&POa20a=#C$Px^C@tBB|=jPI?JGh46}*)Pnap)2qZl9vvUMT_{%a5e<M z{hquDEseGKr$HZx`y)gi{~;4DS_8AkNr!#R;8>YkAmhVGAL08S2`)g;^D3a5!LkHp zcCg*h58Do45sT4gE~<gqQO0TtPR+(vAGJgL9k~x}JfWUI8<v7Uo^%UL#6vn&pd%-U z@<x<D9@imaar6O=ByL<61vRKYS8L)L4Z3v3K8g5-*HM#XiQ|bDWv|-+hXRmNU44ej ztZm298vNg?(?H4l;h$#>y^{X$+2}311EG%)PS<=s*!7LN$cpr$UJE<70TfvJR<)dV zR>3=8o?uxH%@p~#*1kp}D?*R&6qtVYDbj8$F@%+$sFH6DP($mbbBDOnH}{zGO0YZJ zdus2`N{Ev=Rrhx+*YiB6&nQnU_f+=OlQYIs^p^t<ObSHa``GSfAO%3krQ${s2%^V5 z@|~;|2r@ji{hjp#UAMpGNLpOaobex-!f8w)J3ZxL2sITJ3~8usz~TtroDG9>91$6` z9j}uw)M`H)eCVM43u*ybN=iMTa@9xt*(*3|*Bg=yC?;A$+GTj<*$XjGBWO={3d+5* z1T(Ypki!%VrJ?QiC^?B~sm<O+-ntBD3_lv9ehF<KqrrTgez;ZmQtS}cd!uTHRd23@ z9#v^h{|uJ{BDhwy_I{au2nyW;YNJzA{v3ogEjIsl0_v#SM11s#*$ZLd@afnzTs%dw zd40x7DMkDVN!LEB#1{-BU(@Ed_xS2h|Jd8RxAX{5WEL8?aMq%y$)*U>*1g#?{D<QO z+D>S_2tj9!(lxZL2!Yz2NmT{!PB`z=2A|+pVivak?X)d)6+<h+VesvGw}RZ0iDo4D zHyZrQnLzutpwo1=dP0xpz%I~Zx*lkXd|!T$uc?R84b*&_!I2c8mzq*`QWmf$z1TN@ z#z$Bk>0LcNbq0<i&)fr}8%@<$P1Qq8w^kqRK@xdOiJI$S8dZqWyt;F1b9vd7Vi%jw zny;Kb-x*`!H7HlMR8)Tqc9uOrXx0E8^T>(*7?J1wk;o{V_!OhURM3MlEDs3R2|4H6 zpGpe;`79l@_*L5K7e{5vQ_OVC=2Ap<{Ttol&u(_*fuwQ6&NS&SAGMSiO!dpz(8^PW z<wMs-MS}IpD-CLHJa)}w@T;@YFBcB;pZ${{{Y9AfhkyDg(=CJYXOdX4AG;Hu+)VQS zflrE`MVOeIMF}&4c=H*<JL{jW7C+mZRlM=o(Oht?jgD|P>-xs~LnmyVtdpyuUU|}; zuD{Y&)m(2=p7M=vy|fDrk+sTC;n{{Qh4cj1$USx(6Mt-Vhl90f;>T~qXVEX4HelQt zrw6aOMfDB^q0gvy-{ZA=iQ9esn>%_v_}-D72G2P;q1M`~Jgl`>Eov+{Ywc@WTWgU% z|M1iuLgkq)6bXmBERw<arfOWoB6wPJ#pVwGe~Hdlo1>S$tEe*Xg(x2DUZAUwZHeS2 zvBq>Mf>_*4^wcA9cT*zs|E?uE+y0hiEnOci5(Z?D8P{NR%sjR>X+b;#wh5wl0$~36 zM^@jUi`3Jfoi_DROSwl@Qf4<>495cgYdD%L%*fuZ(9bPnTCow5^RU$Q@}KNf2r5s< z{BUkhUa=7~6&!uVuyXHvzQIwk5>RDRA;M%}=5uJaUzJ9)-EU4rMp(lisVY>BYFqsS zasyGsB;UQsYufU3HuXZcXX>KJ3f(D*wlPgAJPPu-V4C3Ub{JeTCGXfNK*F&wJ1(~h z35L9K43X&|ixNj;vLWUW<m3w3o;4B~N}6Fs(oz}_b=7KN`z3g7cNDYE!3_iFwn;VH zQwn3$<;XB9>YEOUGCmy{x>S3_{v8(Ot92=#d3CZAtNArMu4C|Opg`gk-EtDgAuTF3 zwsY8*B5(yMu@rH$?%pRS!*mE6G_`Z}6>}0=U0uvDpHwM;JT;9ZUp{&%e()shc0~G; z=Ur7(JX=}FE*~k$#fvSh55R}eu|1QjeM$0@RpvK_)?zgoX{Aptfc*c4lXCvHl&@tc zDwK3~{r*M=HE}a2>6&3v&!tBwTgRiHY`ETnxcT22de~^Y+U;{M2#IGe^Ge}WbPm9} z$xm<G9o!oY77e&tV23edcCV!q;qz4(5&Woih0xQv{BR@NtpzQ<5yUww|B`mDTkqHM z%V%~hU-Pg_gl0VLd%BhC<_G{PbomToZ$|+xyQkfU4IV=@a2cz6Jf?J_Hs&XfRcs#( zeaTHtz<xGDCSW@uCFnaNRaV62>^e_XZ3hM^PvWv50Fhxg^~+790N0eMH*^!wD!MSe z+J10!Lm>Q9IfTLCZ6Pdq8{J>|cIC;xca8Tt_g+)x*v#zvJNFiSSo3Eep55Muf0=E- zb0MCEnz)AF0XLxL?g75W^1jJceskomg=?sbU_Kxe#)?dQNf{9U>BLa(V%?->@i(XB zs|kMwPwx@u*u@}a5DpFU(q_B+AmO4;gw)YaaU69Ujm*Wn$=}t$-6j2@57f9n64MRn zuGbyfxv}D^q+^>K9!J8t1P=Gk&4A7>sqPAOD#R`NFDWyRq!#U=fGZ&%_ICK40HzCl zq@l|jn2XJ(=jZ6iX}Wt5OSNelP9;KXIA0m-&(uERPnFFsSX~6;^ZIo8MvpFd%HJL5 zBXvqvJFl=ccZWIL+Hf5?c4*5^BKwoNc}}5>PB4F7XZ@H8(1Bn?^T@ViU)?k~f*7$K zlHRViOy;c%Wo7s7+Vna^KZw(sfbfOmKVjs<(J`qIcW42G152gHiTP^-x_wfKof5Ax zN+)8)JzTrmQRLF09?Ow`ZfjsB0uptok=q`L<MSnc%63v}g_Ujc0NPh%LBo}Z-W(s| zsr^=X67yowoYv`azHKOSW{(~beq9G4b*eo!C*==~J_7`vXLSM9;RfjnAOdSXjpYp8 zzsD{QUtJIb?J?(4zc&`>=*g8A$&Yg8a@AW&ew5vcPI*yW#=6<5Yr&Votf21&d@^xw z{eDTASFyfhH}Ay7K0PlR!wLN=I@0!B46Y~`%L-4J_2Yg4t=%jNzRQ5usOtsCl{r3N z{bfB-z4#)tY$2X-s6WB7B9l<M&0d{oXT<^FtA{}E%cdH<s4oMyCe02CUhSLXlI5)D zPzu8*&W040QJXM^Y(YG}k0!FsKT3OeF?^Ibj|m3J=vBGF@+oZckzbiSl%B>YT{ee3 zVsD9Nv&bo?6F#y`(g9vnk2)@rzXFvEjb<&9-(-5(39(@AO=#gh$PAVBh~O(TPOng@ zXSSi+7yKl%W&SemX#hW|D~HbC-~(rnfEFFXwb?r3WIdGrWkxA}*G<onKKV|Eb5D6u zbvOFUa^+oIh28~9MWX0rSst2UYYS^75+R<zbD2+dw3!L)QDi1}IQjQl(1e4<bnM`) zucKRT8SYO&yKkhzmS?BEg&IHoKeXaiVmoJ>DsPS9gb5aL+b?IO;5BjL11($OLZwfq zo3Y2+gi<>Ti06@~rNM+3>ZaggG3uL0!KtZvV=3}bOn-r1Tk}`-`H3sJH9}8^Z+Xib zWD~menC5-E2ybe(K+@;%AY3LRZ13l_XGfJ5(SQaMZT1x>()2-xKVWe8f2joO=ntrj z1xJSrLzxR*DBBwC{uKM4y_kNjukE^JK}Pvyaeq)^N8$Y8R|a_xd=FFqNo}QpT)8PJ zuWuP3cn`jgL^cZ=LtiZi3zI?9)~SZD%b>U7s%9+L4*m<w8mi~_NPRG;Q+|VYr?e)R z#la-+_SPGa=d727na+(Zf$ppXH8(#fZ~chr)dOKrPRvxBWd-K=!tO{ZhH;-K&Xg4u zas%#sF*7OaeGeA?PB7z_c7E0e!&29y>rr-GqaGSS*b8s#KdX;VKlium9ogx7Rcv~y zIyopmn(!ozYaYTR@S35fFRiDA=$k(^Bk0jS-AO{Wh|5*?xI$PxEuW`fNVVS#mkBL- z>U?MKSF(1)a;XYs{z~7RMscuW(xz{E=lp-8<ECv5T#muD!F*)UMmhQ8D~<@XF`|v5 zg1nqV)z#0t9MZ;60fv{KUmQi~8y<s2v6Ux9+71_d6>_wHm6I+3G3J)0*=4CKov*L~ zYy>gP2f#=R*M8_HP1B;D+W>zSN3(#8+#6@MA#^azb7(#sSx377bbQy9G~t(Ukhu)V zM8Fj7ZDs=4*<s6bxXN~VgqntePueOk4L-c6wSUe~5Q;j1fZ&1_v8x1nw;|or!%OX= zsIylp5o}~L?9OdcfyKD;YoZ3VJ+d#eJ1oJ*Ic-(7t=*t+8he^80O_KsbwgSE2w!K& zL&uP&<NNGlSp{a3dU<^`z{a-nJhWs{VPf}-2K6u8$DJesM2w$s1fD$lP@tt}d0$4b zLi2@$`i<;pYNsxWJM?z;pY~1-)N>uaWRqz3w{D3gM%O_yf~{;QZpWK~5WbF(I9!om zu6*{(_Z^-n^*qjGWhF=J_+C|874I+`%_v}zMeU+4M|EOvI=|Bz2`?>J;8#RikP_6H z`e~M6P^YId8(M_&b9CnV*wq1CwL^WyC-y!OhI+8PfRg-+ZgWaze|k+cQHkolt-td? zqv*DXLiUnH(dAk`6YNFQyPkww0Be;t<eR^vKDH~F?F!ku){%=c=FpzEsApU9*?&<* z<qzeo25jWaR3>f3Hg9JOPU=|()VO=7GBE3NshX?Qe<^Ht-@1yBSHf9cGYO}8yK|dJ zOsW38X0mFIQu)?fvOoTLHs?68L<87x-P?GoF;_0zy4%BK*lR(LYvG~FPFX#b5f%77 z-;`Z%JWI5t(9y>5zSn|rqyuVyDHK`0l;j?PlgW14Khvr|z_Vd1ID`*28Als@Y>3ZQ zsMsH3n)`jsRG*~Rbm8nB%nao&SHsvmE^H*eR%~Y%W$IUZ_fNNr9!D#TbFtD>cF<G) zbG}{UHwI%!qp4(%i=*x;N(Pn$e*feLaY{!nvTy<8lv*M{p6)6{__!~V-uIp;yOcTZ z;*{yTxP(`9f={9mkLC;X<_D@elu+H~kn<{NX+UR_WcIS>si7>ew<P{G3w$-)SecPp z@(2BF%7iMN{bsu$)~sZ8bF;iC>p{K%R)x#St!Q;f1vT`rz&4>M%Zq(9KEOelId9|Y zEAN|yC19nca`%lo?<g&!YbL@@Nw~{p0XJG?|633TAmSlO<snLbyu}08v@=5)HpKHa zKDbR~BwsbT;0KBula0$+A3`Nwk94-V79i<lqBpJ=XwTSKF$z`<t?ZSmSPozZR?o<0 z*H6@B0C8mjjwSA&uxghbr!39xl0Pl$Wbq3vc`^ifzdJGU=vW*kwrAxxC|cTMRVDe& zSFLwTo?6}s^^V!|B4!#?z486ni=JynP}|*um$Cv^evCV70$mG@nSu!K;vA3Oldlis zztM>t7IGmOhn+m;`y93<&b0T@X0#`}!uMNaKxbDMhl=pBBT-#P;yIeXjsXwF4CC{3 z35EmE580`;Wc51V=zmhEvzy`hFL_P52yB3Y=9}4d*szRd&A5CFmJFD6j>NEbw_Sn( zSXJ7(+~voi@|X@DK+u=H9l=mXH$u=zwa`RRdban<7yC8%fv!p;sZ#`wcGbqG5wuC7 zzW21dPg1{5_PHOtQ#T{xEj>bej}L^soR(7gayb=j_pZU<y#cV}ur7zT^?8WlHrc)7 z<oyQ2Y52Q6vx)q;g5CZut@j(Osu9h%vtdN)7eV;9GY-nx8%aCAi{(Xfqt3sryY%dR zYus7&lNxFS0en>l{HWPBZZFQM*)LbUP>V(Nm{wiMk94AmQ)##qi4J=duP5C-hAH*; zG5GV3AkQ<peksS@v47p)>UXtkhd8RG{z9XE1;4bN>x~+V-*=YqO#K8-mj3leqR8f@ z5AN;p7=3`x)^5th)eb%sWuLKB4`<K*U;LEMokDrlpz=+_ajV~UEADO#9upe$yIT?Q z)@Fn@LwELWCDW@_1A<R3G#9B(Gfb@cu=Xz_41d#y@k&AcLKSEhza?Ml+mDHMC*7+N z_;+LW>Ara);fKGT5I5anLc?!`$e1xcJ)vCj*{dt>X6gOk*WQxl?65qNzAwiqLLc_! z#_KFxk(|)Qc-s`Gzl~SD7(L327I-#WpPHep@oXsx4UZK%C_gJJn8YSWn>BIbj2$lQ z>Xm-xzg1C%x8^7Q@_KQLmYHm88td6-HU-T%`;@rj#vu%cYAQ($780m?)z@cljqA^` z(XzX&0z%)oTqMp$BkZl|iHj^=cC8H6jlD8$YVLD)=#`3#>6(l7^yaP<{4Sn8B+f_h zffQ!1?4y=T+_iRRNN{&8l&;jvkX{AH(QmAj;B}{SQM(uJZCkWs3dirG7(_!04b1`x zmopKa`U-6mxLS8;DSk1G5dQFYcv&-t=w^&|csqUjepd{&30*LQO?6@zb)^#(H4<YW z^<Uo->(1|tifoB1Jia=`7FF<VTZF|1dXYgzs8^P~IBt1Ow6ld16nrx``FpGd=oNQ_ z=&)>ZNwpFPBx{$tN>dLNGIQo~N(vVDywwvQe3$wpHjck3Ig5ixC<vmXQMq<rCGaJQ zy)1vl5|RDT%kpbQxw|S)a_Mr_o3*d8^5e^%n(+Jw1<L)(=~-VBINU7GDtYMSUXPEz zJ<8WzY@X2OLyi<<z!myhVq!z3nT+ngBDGihIStL)VD8|CH+-CKoCQfJh*FEJ%feHN z9Sa8uq^SMq_aK1&;3k$n!roM2a2dilTNO$8a&$e-&YGQP$3w13W>$6mzEDS7^)UC2 zCgArK7_4~l=9VM!ZB-oXzu(5DTsurt-tRJ#hgNQZ7WL+bK@qHVpD!5R9{Oh;I>W+O zK4f(V=v5r&6=wG8EZAewR77h@J}+pKSU}IAr7;)0vgvr*-rDX?HlKEy!Wa82y8J#_ zmgO>4PS=M-1~G4*Ts`LaX2|Oxd~4dJtzh^-;s}2U;$Mc7)&TpUL`yTdKqnWQ&F<!u zk`@I(nq8E-{qPhVMm=C;oN&$vnjtYH7UZ2BMi3$rBY#(-4dJd(M3w}#bPI%LIb=3N z1%?C4wK6?zMh{uqob@Xz_QToD9A1f57xx7Lf@4Cxe-Unl&)=Mq3-iwj^)AMVfZDn$ z7xn8Pz7eTSWLt9NKMsvXv1^%R;hk3_g?;moXpVwE<CY^srS81}rYE@q;1s0OXkU_X zQTV_RTpTTP*j|)6oofjLm$cnj6xt7snMUu1g(e}<e!T6)1o9C9=&3V0XBbHBZ>A(b z!0rWcecD|j$Ok)_0Y%iuAAF9EgdBEh#Z*(g81XP>hV}rev$=`UKs{1fsyhc5+n)I9 zLSX+@#~YITEb{TyzKTZNdG!kXjQ;v=t5;fLDvIjXTfE#*q|*tW%}e;ik!lvBtBxrD z>rR1(m5pvN>TQ(9XF6qlOuuTMQ<2QZ#T7lw#KrINBQtEl2_rvv)TK3TRE@au>=`;D z7{NT#`lU~J@_t^s4u^1q6f{#G742=`)>N?X2!+iR?JeHW6k9oYTI{ThDxWESo%;G6 z_V<o{>8o~m`#=iMQXG~oN8jx&gLdM`_T?sw&VxYuZq~^3NLdt52t&8b6@?z>q-s6Z z8s0EY$ARj|P-8f^;|s=*7kBk+JQNEzu2a}o?5<8fp1xQ?U(ak9y%~9WgZ>47WSn^u z+qxZp+q)f3NA>!5b!yQd*N6Hx)*b4oFS>)fQIXGi@)N7Y{bV>xuZ3Gp#r%h|irTv~ z;qZlEwcH>$Yn{U~+9v2=#c{#?d0u@RVN<+<-lN)uee`FqE^6{!S9Sosh6g8tS5<#G zM_N5;CBh5zvt2JRXcRu8gqnOG(*mk=66qjQx~o#rf*mdlf$l~ru_t=d{fym-)#t2J z?CLF7z3FGHO9+9*HzQ=;{n=<$xy^bjD5~CIdWx(+9SfiBfCzbb8Rs@&XESn9AgSz# zVpP$>eLA%rk}YIw`+m5{XdMGt^C`rz3IB{^)XWXAAOLI~4dFYTVoYvL;dE33;W8vz z@b2j1s~s?)?Kqcd=t>=WiJ;cBt!f{LD4rv1<C3LLYDzfr347Lo;mfsRs)sR2G%Q+7 zl)0ntK0u3Df@P|WP>c{AI%O*vx#14@4~_+qC)iy@!RKr7;_}4ZuwtwMh+#{V9wSj6 z#O-IWyn}MrqU2zE#|EDR6t6h;r3C;q`s#cx2%Ei2PdEy@2G4tf=LcLJ6z*F|zCEGx zMcGA=TuSCyU<=H>98yQbzHR#2Ro}e!HO^p9D8ZXPKOv^|{R>V_xrZ_O?loUelTfdf zFum76b{Ck9Nw}vY2}gZJ_OY>-_jBmZ26yP}6m%q7c!ma8+ThVG)}J7f5D@c(<Xz8% zT!xAxI7@`JGO}XxJ*LE)ow7$OwNI+{R7mg^3A?#mca!quA?9G{$z60h$@K30+rW$G zP)1pznl)xQ-RnBw^+5lb$#|G*Pa3rjHP%OZRiX_>RCeFSorzSM^&vNhUNMCe&U0)Y zi^BqqLe#^;VbT4S=JL6uJ~GPw*6Hg%d-NM?bU?B1`7!PhA3fvBa907Y%NW_$+loOV z23m{9fip+AOM;@`$ijgdf2pr3wV0&(5+J9|Skt8{F5l2kb$d6%Ne+{FMZK0s2iyUH zvzL}|Dzo{o(E?4HF=8WE32c7I!UJ1C7%y#P45QH&lG27jtpk*h#Z+(;{C+Mg5gKKu zuv^&_FD74vk=$?B+ctI&%W8%{A!KGXJNzEd$2hDw-x%Q;>8k*(-Jv?ZFRgGu^d5(> z4_8|ff;KRk;q#G5Az~;)gwNQViAu|R(Z>Feq_9Q}F7K`xuh7;Q?U2!R`4hq}I28%0 zL>SUe)({1^Th67zNQ&qfS$E`P+{AIbpxAP4ACdUAZsl@B_@7fiXN=kM$!!c)xf)np zg27U91)V#P#_HgKMVq4~9^v+ql4;NeyXRuzfqfHXPN;(q>ARps2}^}8t`2bIu8TF% z(z0m%@YJCJDgW@I6hQSl>cp)YT0&3&5n1<+z6c!swIwA}5a}mcWW;Kg80bJs`79s} z+jDs>9)4f4qtwdK_whcXTO#};>pxk_pT+AY`%{&*PB%hx%s*ZawO9QoO%b2G-+<jI zNrFq06SaBUsrD$XC)e6v*$|)Y_gE(_CLr=g;upbXSjWl^MpWw+?sj`dU&nnG|2xg4 zKW~SIZ26-lLR0ID$R9X?goaQbGor=5_V(TmW7#-T@T1vq5PNOCgdWUOA{3}9RMulO zY=F;cNm>-X9(uM|#Bn{CuAWCN+NVfifYNcfNI^gK0a@Q!Q}`-kUjxN#X|G6*PK^>P z;<#~(P(t~5-f#G+8TM^QzT)mX6qNtG#tk{Tf-?LU{W=mcIO>xn?Q6g9I!J#cEp?rD zo;w`upJB!u&M5iy4kfV?c8UDu$SEQ0%TkfQz{eYuJNp*zsaD5M2i4e$NqU05bKdMv zOPlYag@){uiU%LEU)LD#*Kg6EqaWniPpoH`g;!{$E_={`We6OL`}U^&32M5um$K%5 z|BU^bKKdh${rIgONAeQFPlEV#-=v5hsP?|N#90shHUXP+5)DE%O4Iiv>uk`84ps6A z@E{pfW0Y8aE2Uv#I^!$KotJ99zjO4~%x7owTbBbW<a<F%a}nX4f~I8v-_h1Xsv|ie zAM+C~1Pqok<?z^i<b!CYKibikLs)hZP8V8Bu_uL=VwCMca>P-+j_{Qig!^sx$`Dv) zE}u(K4%ZzqIX#^Zh`8dO`0J6u5(!$@ybU^0(yw3t7I`u34&sl2zry;-Qj@(nM*W5B zKNOFUtnTMxrIunYPpEL3NIk{ry)-S#d^9xnU$x0={L6lkbSa8X7DC54Njrm3dlby# zS;7>}jWT=1R1yHy+*64`3i#ejpZR*3P)A&TdpNYQDEvD|ml{Cqb@2Gw_hBdod3+cN zw!6x<B$r~xTZDV4V*jo>=@_C^o599Q9Wz4p)oJJR4}Q(M*p_jBdwrrQ8g3)X9WFj! zRg^O6TN7LNQVsyqExoDkfXqKwd!DM0zI-PuT*!c4Tdio%zym!Y;A{G}ByJd6%V^qA zc+A_@!szqE+>!<JgvG&I^30ktmuOuMy31qsR(I8FKPxtM>}WnkevUL944Ui2TmhL* zUwAFWa7CGTU^=z^y&(_umQT5n)hT%O$HFT*9QkShN6=2E1Z3GuL3`17_+%+Wr)@`! zNnQD_Z9&2mb2eS5hS37^K)|IPj!rXPrC&t6%Sc97<zVdU+as+%Gzs6_uAz-W{VR~v zA|<3NRY@IanzEX!Dz!wq=mbn)lA3|AaO4XzfBiO249`{t#2vV)*Np)9sJ6eglKMtE zsTy1ANN|W~HHbXvd>z9$(wCGA&Rkl)=BL0VlbPFmw8c^j^WAXJ@2VhzlAWqM2|;-0 z(h{NWmQI0?^nCBJ6S<LXdu)&p0v%hYb+mIOXkH)ITG`4hMaCX$W2P8hYF|g|27-(# z4T*d48ev0O#Eb0(if3k{xZAb)yT>2$^DV{$M&dF1r04^MC6Z);!VEc47=~R}%?HQy z`Yhq);1Gz_KB0dv-$|!%j(O|Ys4~@^lt9s0?rOV9XH!60<pb>Vq(Xb3=&}PXRj6Ts zSnhkB<!#JuB_klwgpHAs*!eS>pJg^0_)_|}5!?Hnj#o<0`{Fx$*?x7u(6V9EpN+|R zxn%1uy(Pm0p_l1iGG|^(?DVVRPvp7K*t4Yah;8J-QaQgv6XvmOWByBXP_*Pr^9=fl zZ{pPub^aSn9M#~K$csuK#`sSA%ZrJfZkhaHtKCa#PuM)F%Ucs4jI)Mu#{}o{2QEB_ z<=@{{HqTMAW-IZ3sR&8xEO0vINW2j_n`9WB`BJ*G<<sHIOV1e8FNxc{p<UUqBQh$z z>tG;!ja3X~g<T%&zDh6ViY*^<RQkN`q%rjwaVM5#!kp6-lp=7)!gF2hW!bI++vI$= zxrmcQ{mZfkBC2vA=~z4G?yEhNS)m^DIO@StyY|7onhSM3qlzpYHm@je$1ZGN)wQH~ zYjQhW(^Zy;9DIGc0O0R<6R`3-vXQr)9=iAB?(gq#Yu^Qr>o2@K59@D52zk<FdSP4T z01ZD%+^6&`ZCaI<+WBYG8-aEW7{V3e7`>?$(*<?B-iYbMSc0hL>X#AX<okb)@u>ID z9TSH421k=yTGL_7rw1K6!15|7VOnpCQ}_1!D+o;dH??U9CgGczo6`RKGq~>@$09gI zfT@E_*QRpSnN6?mfxE^fZRYw5zKZd}F~{0XmzQWuZ<W}hnDawoZ}_Tnx5uSi*e5aD zoj&k_F1>e|Q2Q_&yTI2)^q|wZQhLbQEz((^CVBrSzX58xY?98~fD6iIm;8p|Fd@pV z$Ynds_aWQr=nIEL{@ztG>CwxtOP8Lj(JMS*V?1)XM*DivEqy>JM(rhWqJSu7++ORD zvvP$<;y%hvjId15s><RoDW>lKr!-V}4q11(Xl_q&vL1Q*&UMGR!v`9~|C2Z?>&>7* zCqpHosK@jBd45Cx2?KWlDzbV>`t$Z5IC#hVUbfX<T+CEdFfO?e)_f6|F*f-0b--qj zQupe>Q74^`Tuh&<`|l6)mx=jwI+rV*M^5E2G!}~O10NaE;A8bi?~?TP9rQ&imY}L9 zHgyr~vz6cQ^}da~3e~Uj)1RmR4}?H_zr>pL^spZPCDUs%+;5<cjcBp)wHP+x>&?u{ zW@_4u|F+QE7W&)*w<+kFLawdk*b0BCaF$AqsjN%Id)x4F8oj1b^LEah?VL?J&WItM zeCcSEF;fgX;bkYj+yzIw$+Me2_n^sMW@8^U?}M-X%zP&PJ;1yl<oY2zbcmj^@atjf zJd9Tk<Hc+=&8GHjdN{)MBZ*?jA!ZKs=D^`m&eo&&|0uN`V^)uGmK|f?ar!t;yc5Jd zfo>-`XHPPdC(nuD6njtM(bLp-8okfpkuzv|7N4D^uXFHn9v;u*kqh*H0X}#iHSj)a z;Q45{L_L?#{Sx(GhMUXm&1GFK`sR}B3iVyVmsjZXD%Y=~!!>+!jeFOr=X$&tZgBSV z+%()k@0;*=6RvOZ47f$E+YJEv-=X(A$HZ`#`M-;Q?=cVeodE0Z!`}nW;|Jt;NM8@} z!6SNn#NUt5<T3dlv-b(!e!{#y#amB#Ry?EkXVm+g*?)n?FW~hRetQLfukqR&`g{w| zyki>P(dT=3c#khW;F*t{v7dN;<dGwfSfA1SGoN2r`<2=JMt$GG4`%OY88M1C_#wsu zYsF~QN{j`|fwy8TbWV(gUyIQu7^H~Nwi?(c#v=X2XvZ46Jz^}X1tY+HG1`9=qeEZt zP>hc4!BlWtjKzpqY_k}hjG!k-7NfH}m@P&ZJJ13w5u+>DT#4bvcej^f<k@LdyceUg z9>@}-s+kzwZNWH@Cq|FyV)UeT&qOhL5!Z{Fy;qCTCti%cT=$(XMn7_^O91w3=tXBO zM!g!)tHBIX#b^u%nPN0Wf*diL$zwhtM*q&>pcn%h0Ad%<5Mzl-V1*b<T7j-0Ta1D9 z6$lrl+(2(Yt|0OUT@qvID8Tn%JxCB^h$ol;=reSn7{jWFG29-+h%sUeNCR+LCJ=N7 z*Tq<t`(^2)EOE*O0oImdfBBjKUCMtGV+Hb7fa{7K0ku@B19HV!nY@)Zim?j4R-u=w z^j4KP)!?BT@vEH@WA!Eg4XfW2W8^S!L5ww=z+ixGH3I;=)FNgrc#mRz)E6<<?j^=L zj(~dVRsfI1SdZT7aj$-y7#k3y0eUnfe<SiXqQ1t|*96b-u4!yaJ<Z^txeK7C7U<l9 z+FPP~EB3dh#@6)M8c((H6=PdCZwsf<a28FS(e&32AM(CwY)8%Q@n?Jb=|G(wh}{vL zJ1!DqCjn=~*cqR6!CPGmfmktiV{bR=?S==sQ$u(3@6Ns+_`3)F@-AxZ$z1$Kyx(?- zu@|21^<0d<<E!4R?M==;=+c+E`ciklp<?Wh7y47f0CEj%B*sCk8_bLiLHD85F_e3M z;HN+6V;Ecvqpsn^9f8Ip=8AD7T#jNUMzePGT``W~+E}>d*=rn!C&rBu<9N6j&${vW zWCHw6z>gE~_C#i2BKl0?-emkY8IQ*>Q!&&Q!yNsIcmHIjW63v#Ihulhr{Mdk?3)JH z)98IVy-!EK8EpXhXR>w{I?iGiX2a2JJTaU3or4eOOcLW<V$NkQ=5a>MJ0`~Y%=`j+ zUBH?+^oWCph1^?6-;40~V*IigPb>)q<XZ{{@#qncmdlvugqdPoj<(D3_ex@~#0QD+ zk%+$&S-*;YR?)+1=4uT!uh}8SwZvS@zIDt(5`87%ha}Dq-d&B!crBSTYXfJ-M(%AS z-X?sp32ru%dkeL0!6RGHA%*$n9o4uMJ-1TBR^}>|8A+vwZOp(nv`E7fY2-@dJlIZs z+u>>lb?-onbUrhvD}#7D@%v8l?xN3K?B5M{yWx2^e%eFsJ;dINmV4=CA6)OFkNt3; zNxhlqnTehU@cjX1>L5BDWOfd*{t!B5!DANt4>OzD%ttm{9pNm^Ay-b47>{z^9VO>6 z{Bj&$9jBKQaCj2GpJe|jcsfm;XNYr_n$E)gIruqG|L3Xi0vudqW-mnpJaC!$$fcJn zT)WCFT!Zgxe7{beH^5ES-DECq(bsMCzr%dqg|EAujrW+d`|$FB`X1t?hxq;xeLN=L z6Y6=27oL*y85}%g?w`@ibIzCN^zj@ozaZZW&hr=i{Swc;q~}*$d&PXdM!VP4#<S4) z7Omfb_i*?g?mnRL2fX^>sTe<UPJP4=pP2PLdd!2H&zy&!sr?IjeqpwFhctdeqi=ZZ zJJ-I$?+@ntXQr5BzL*Ns6qA)TxGJWCEx-hDK}?0B!51+VZUXYeWIa$!HcBuKycCmd zXOJbPBJN<inC!d(@pz{+73I2pJ#b7+4n4s>F*yc;!5~LW#fVcZLrhLpK(?5i8-R0S za_KK7S2u7|Om5VnFoQi}Qc|Pxu9#F)#pE6Yx`M}I@<<kwCow$9<3+vRy~N~W1jO|1 z4yfBNNla>L*HE8^I<%w2q@!2;DKQy30<Ia!W85Vs6E&JHiOIZHO#WrW6rcyxRUBSQ zsKI72m5dcrU=&CdQ>mdKO-w<yfLKAV#Z;PFgIz$Pm_pzvggQg#iYY7{us^&6AXh{q zF_p0ga8;JI<@jD6{wll|Q$=D|CSPUtR-w15<g7-{>gZG*{vz!F{6?Z-4K1L*8eFf* zI-X^wS}OoOM$u2yFfr9G1o*5&zB<%gm)`24Mcs#Ds>k2;#)zrD6__ce2K3rshnO0c z6H}x10IeI7yD?s9g3e9J-ISi2QEzkNHt!4Gii!7DQ%grc&n>CD6&$wuA*R;xVrqjH zZPB&u2{A?UcQkq15u^PgF?9$AeD633+!j+O@^@li=Z#|Og3evxp(`HfM!s%%pgUak zpq?K0#nh7+zu~Xn$k&U%e{UtG-qhC{4g182sV{!&N4$RY)t~(X1Q2&1*9YN~!PGk# z&WG@Q2t5oX<{wMMGz^anhu7iMI|5EeIsx{LV%=!sj7H}%_+l*U#!~Y*{vJ=?<Edi; zKA1q9iR_t3>`9)0&&lMTjHhF$FD6Dzf1(rbjiy-onSwW`z|&OLPDRUUa5WA7rUwB0 zJ7a{HW}^K}G?__Fv*>j;TFilmImDhzthw~dJELhH@#o>M`FL_ZvpXMN=cDHW^o}E5 z99qXw-$MMe5I-*bCZ<J^fc%TuyBI!~FvCmWa4DW$x>`)})E7@(@z2Gy4F4`euY}ov zzLzs2%h7Q;oUEt@n9&vRuoCaAgtJ8UCNkeV<4mi_vkGsnrkB;!%{!!N4Kuu!8D9HT zOzWsEiF-+SB#B(>S(}Xh$*kExj~lLwX(PRCLeov0ADf#2=3@){x1d8xDB$~6)^264 zQklin6fte%%-F`>G&tB!z1x|u9h?>E%tJael)?3#%*8JF*+tE}In#Di?;d*CL)^W1 zVjq6l$F==@?q{Ae(IS(W2hiXEy&UB8ATx3ZzOvc?_8o?^Y&6bh-w|f<2z}&Ga}G0g z6i**RpJVWR9L`Tr`w8kg3HK)x#B_?eI7MxzncFk)aTZ?AlKUKdoP&e&)PI5by8z!8 z;o}mXxx~4789!ZSesWoJg}7HaYp>zGYxw0lHQ#`X8|Z)YjF@iWncLjIP0e@E^$zFe zT|9aZkKe-=Jl{+YnC}OyeTWu3-%O90u_wfM!u_Z4@(e#dC+7=h^(Fp&Nvv1!_?q+J z4eQ?UEO|@Zcl5!#oasHWJ}^@s;r0_fePR|q;e$N(=i%EtYX40CU+DEKXVO<Z{f*q; z$@>E?f7TQ;?{#K*F6IKO#cb6}%mwR-xlm{DMa+fIiP^dhcq(Sz@65JZF&AkjX1gFU z7j+V|y&GVS!yYj^?htdacriO|7PIqhF}o1M<)N5eLqVFD-IO3s%nEm~1Y8%hk~PY= zVpb7bHA&3w#B`r4W{*~Y`<{9*0o)a{S69G3Z#5VPzKPjqjF^4d<2wSp7PH@MF{}Bm zUMpq|F*O-t)~*n<&JkpaSx*i_Z!sIG!T3_lCTcd91Kjf`b^yKcd@>g&UkPHA<X%bQ z2C}ZyU@-?x6?16;QDP4E1k@P}Zz0?ZjRe#hdO^%#<P5h1m&6=V0T8bYYs>JxEIG>l z5OcZy0G`TE7jp$-RUlu*K!6sN62)A(r<kjds|s~i-6iH~)Lxyvk+y*RksHNagFQ9i zzosuBUd=2q*D?d{MZtCLDu6Y07Kyp;C^6Tw2WV99zL@I=h`9mr8ypjJ!xS+$LW{=q z(Ii&PP4Pj~6Jl=0TAoYh=4Zs*f<9WXt|k1ngx6L>0Ul{xP0Vdvz%Vhlg@b535zXFq z0|ENCXI%&KbRd66YXF~};IlJ*cm62mE;Gg46<>8l({5<n4K2FUL-#x}_dt^##OO(H zJ*ks-Ec0*l)eA56!VkUZ<9BN5jgNcNV;^ehb5+cJJBqm<zU!AH=KgRsfV>0XZ(w&o zZG-UiAUGO?4uc<yc?h}<rRSmi{Rf}J=y_POn1_>p1e%ZRE9OyneiS;6Ce9cmppLQR z8A}Y_wagR1L^zrR7n93~IR>p_h#Lb(f8G>xY>t?xP}3CrJ%yg8QpYrOpGN=F;AA>p zn@;`H(SHWL%tWi1@5MZeYqQaOc8r+kQ2!j_%*7}3*gKC}=EK!|t}TF%1=JFUh6`E0 z5DzX27xQBDSWKKH@V}Hb@%SMgA1;IQW%I?H05=KfmVhS9;dMFdmQ(Kv^jOI(C8Awo z6MzR-F^{Xbz8bHrrv5d|%3AncOF!$-XB}QmV%CzFy(IP|!CMmjC81FgdamcJSr13+ znT7T6yZ#hlPcn5S(@Qd%By-kmfWHmw+kn0s;e8_-Y$EO^u5Uu0O$Py5Y=(o)cw;lQ zZRQ-=0>4|(b_=|3A!iD6o<hD9;-}#26#Sb)-6{BPE8J{l?N-)qO#o<+3RkJDPfZ2P zRVvzTBj+}_=b2|tqpvj1oU~jqZ;u9C-%g$#@U(+<JE&zxwwTlTo(?bR)SXVwbk=83 ze+GPH;G2wn0H5x(0{CVp{@uyFooKU@wYxYwc2UPJuI)m{UCi|^xY&)ZyU}|$dhO=k zZqC}>aJU=J_ON~re%ymTd+2X3TJEg`&~q=^>|?g}F^fER&HK?|KXLbSeLv@DCSJ|N zH<|FC$*dp1-v{XB0P}Nz*azw7ApIRA=RxuvM9V|?=Mc||L&Q8ptV6`gB1aZ|XR$X6 z4`(sUS<KX7_8(^dVXhzMY&*;unT_wVxt5Kd*_;L0<jy8`Hhwrl|3}dB2sIsnuOoQ# z2zun;zZ|&AVGeT8BZu0La_uPk9!0Zb@N=v^pzh;vdmMd^!~b!-a)S9f!I^Y|Svkp! zp5!b!N#2v}JBb#jsPPo_okD|CtT{#Br|IW3yq+fCX|A6p=V@l_Od~+7GvqmoerMtN zENjlP<}9;z4i3)YsdL0Qk5=c2cOHLUpw<iMae<r{xOb8B`63><h$fdfb1rcvUt(@9 z;nhp<b{QTn6YDY@T_)FMIL@WVT;k-yLoPFu%idhPdxbi#pvM)Sg;!X61s$)T(^Y!7 zN{p-Yc9rW_spTrUuW`OyD*+k+biKy2^BP=TW8XF6U5BIV`29NdUgtS*9nW5;w;TBC z26=Aqe7eC|b^~2*QqxUpx``KVqWevByhY!)(B&2!-(u!&Gpo1Ba~m(;f$KZ;bO){P zGNX6V;x4|pi}&ww?;c#<qn3McaG$>J<Lmoqc^|*uXAT|^`vGen(9Z)nc}Oo0ITIh! z<3nnCh`%0D=OfOUN9=pV?~h0H^@w?Xj1L|&yN}`hF?v0QqbK<N2|YgHcgz#wKc$za z==+pee#Wdkqt|Ef{2b1olY`%A=I6wE!7RR@wio#GCFkTz{QQ!-UQ*XfIC#k%zJlXd zaPW#6Ug4kD==_>%ubH{maQhmcyk`Gv*1v}LH}L)jAH3nY`iArA4RyTXoPNVO^9G;3 z!GCYj^er5`CD&W}cndFY(cvw+zQgzL;QAffy@S_xoYn6*<KEHRJL-AQdHNpzzGvTi z&fxd(_ko%|P}2wEec;^vfJZ)1%SY<?h#x=VsgLyhk+mQ3@h9ScqP|be=O;M)gl>6w zHIG@z!vlHDY#w~)5#uv4K2yhMVt?kG_{^E`ncqEMSpS6?|H8a}!S7#~i7)iW?^N?w z_IxGpS9tu&wQuPAjT!p}_ur`F8~MJW+jlhoj(@*12jBS}_MNrg(d7sA{h-GmX#a!0 ze^B#JwE9V|pK$r}nD~o;a4;AogU8}uz!yY=x!{cWTRDOXpchyKvcY@tFX#;-L2oc0 z>;Z4ZzmOTU2V5&ej>6<9Opd~=E1U>&#owBk*6g(&0aCz2@I(A<LIHVfR)9<5Z)*?q zfc&=205NQ5gEVkc{EJX)k!qkb;93!4+cf}vK^!1PQT7)lPf>cYr)K-1;EVV>aNVH= z*bK<;NDjvskON+de=#Mf2Q~us7Nch;Cr}O$&nW@y5`SlEbPfV*0o=G)18Q}FPgi<( zC59{a+yVgC-N@la?F!;6Is!OVTor#MYn5=PggfOvV7Ue-Dtc7Wqlz9?V?Yu>CwKC? zmjGOIhgbK5;_p!gv;yNmrucipvu9U8onF-CMLw_l;_uCM?<#=Y-WlTWV+H8TXA~fo z54!nMk1y+ervkY3rDi`{5DeOY34k8`&H?yTQ;V9~)##(97Bzfn;7bEH8aU9PohBBf z0(_!%0o10YR^Ctib?~991n5V1Lj3hwFbrggzX1*m)Menh0ZxqQW<(bwy_k%E_$EAT zq8_sy;F=i^o7rzhUo-ufsmC9G`8NV+;Ez}QxfXyf0pt&WuK;*0jt0f?NO5wNpoS9E zT>@Q8MuGl-I!e-SAbkb)1ZY(XUP{4dDL5&GKBe$W5PS!92V4sxcF=Y4FYO7Kh0@eo z8lFm@68~Uy42Jt)Vg=*bVEPS)pAgoDpnC|MhEQ(^c|+(UgnOZI7a9oa0CI$KKNOFJ zQfKI0@egwc^cu!2g>f&884G(Y{^8^bCuTS?!{IL+uZP2D1ocEPuMx~}1ih7^*E0CK z4E&Tuld|}v9QBlAZ#mYMgPZbrraX0*r;qY@wE{I&U|$9NQh|IG;I|?^tH>-?<XT1c zRD|D3@Lj1UzzdaD17@!>oL8pS%H*j`50&Ym3bj^2*DB0f6?mz_-l}+{>U2QuRWFEt zH8;RqRKvs7$yFWiSI1wG^d5=+kuw4DYp|{cv1-6!jpyQDli9D?1kiI$W}_zgYQb48 z{89@q)Pk2<cq@t;qKFkmtf)yK9xw}0^b*DW+UQ;z-`B=dwc({U_1A{O+T^Um-a2Sq zhZ(Aa$LrwDI{2c_NAa)AIaC)8>f)`s^i!9b>oP}m(Y7A<>T$0gUaPkRFiZ8Gihq52 zsLvTypP8x8p8EK%KAJYbqYXG$8lZCnJkS9C8j!ys{%gn_G$d9-JkpT+4Y}VCA2$3Z z{*9R9MsUyw9U9@;M$C6(ax|vj#sdN8e`D%xOpYdatqJF96Y@5}gH5QXDSS2MylG18 zrtsL5zMH~HGx}~ujAn4wjPr!|Xa8p0YewE?<ZVuW&FP~#_nULSIlVWh_ZD#30<X2e zn=Odff;=rbgIcNq8n<MQS~43g$<d0wTG3Z4YH!85*5quB7h5w!t?^20*0qMqHtcPK zC)>bf8?<S|9JawnZ8?|P;<>iWY+F3jmiujq)fQj1rRTQzKAQfbsWTe=qVYuZZSil1 zZ`zTg9elMTPJ6U(kB05>dwceEAZ`cFg$~5)z+7~&T!X)kT<=JI9nr2Mp6rNUI})!G zJ$GV#Cu-<~M>@epC;ID*&pT6hXT0ATzjemzUGR4ou62QjF7Vj}A9ZDKSLUWGbJP|6 zx-p~O@Ip7%bfczjc)dH^bcd_%=+vD)y2C+tX1oV$dr(sk&hj4c-2)zb76M%BiI;og z*Phh!8|!|<-@oCX-`LxWx$gxpy*Q_P(MK<0{f^$hb7ua|_uu*68*Y1ZM)ziBdec*H zdhJ8~eVB(n=-Y=_eK?o<@O<vW`O}wv`{J>_)Y+H&eTmf<@At*yeVNUEc)1_vMn62* zkG%cZ+mC+x6SF^_>CYL{pYy6e=V^c94d8h(fVBg-J^;Q45N81E2XJp7wGG7g1M%KK z=3yXv2Eyea_6(xWL2x$+&Id6=gNZ+wx(3tBU}_pnj={tl%)KGhGz1?GA<q!{9D;X- zQ0owK3?;`<d@>Xd3}qgNa{UkH?GL#AgKNXsJB+=<*gK4w8pioK94&_vXE^nYVE+i> zjewt#cw{6V9Eq<-a&HtK97SKFsC^V398Ha*;dL}V9L>2j8t;xF*BEk*!SiF#Yz#Gx zCEr;5H<mMSEWRAewQ=}&9P7s6{c-qZ9B1};W^O$B$HT>V&cpG<7>};w(QpE_OyJ%G z?oGhs6X<0E`zEk&B6Uopj)~MUk$4l)eIheB3I9xD{UokW;;fwn7n7N-$>=f}9VgRc z4Eo1VTMYOAB+j4A!=LPr#aFTTA(lL`^g0ENrl7?XxS4`xQ_*HB`=-LhRC=FE@6+(f zG@dup*guW$(>ZUZ6Jt7_o6fmDoq3!AKQr+7j2!@v&*a%PlUOs!JClBAqS;L9oP{Q{ z*gK2)n?<bI#G1{yHJjO(15b09wK;fVPM-MB#ZPmoV=i3GW8XaX%|o+!%;0=@nU7}k zISc3G!v)OQ0=Qqmxwe4weF5ib95uu-dvRQgqy9K_ii3|h&c-<IFJ$f(qTxcG`3s4) zkn?#V^)JLbi-@;~dy6<97IAhjVxAXqZxOXDVjdUcnZ^9xUd$P=7#<dLel3QJ#c;ZW zyi1tpCEQyA&r8U;gx;6(J8CIBErs8u^s$unONkXv-SPM~9{uB~A)Z-@N5gnHSccZi zh_#H~mvNpgqlaaj#mktN1iX`gHVHh36R1CdTnT8D0JjNfxg1X{r~l>fyBu#U$8*c6 zV+GHo70mbw=4l1_R&e&M;P?4Te6o_~&r0}O312IzV<p@sk|&Y66N!^ZuZj3G5sp^D z(JC}vg~qFx@l|+e6?Lyh$JNxe8ZB3IwycJm)o{L=XVn@wU4wVma1O8G+8X@4mKxVG zGi&K>ExN3Or*+h@jvCgnW*r<Q@jEGrb2*9rlE}Rt?befHJ?GAPVy$QIdd}PR<VdEb zWac}W-jd;J10LG|hZ{HxHgK+Qz&{%~!#7gjMm)O_Z8vfTZA80GXt#;Ao6v3(oNYq$ zO>nT8^JOz}HxqX=aW@lpGaPSWcDJD07P#MnH@2Wz3eUh4)}_#Q3L2*ncPswgO3bay z=T_z;70pxWF%{pZat>@`Ubms~HvGJe`)T|JNu%F1Vx%!&+sVD1dEd?%zMYuc$-M&) z?x6o2^uL4tchLV1_)Nz$>BLS)lXR}7!)XTkWw0)T{TcW%0}gkRV<+0}<QcXT-F9&n z?1GbB)UXTQccc4me6kzOcaw7u&)hxa+e3^!{Px&O{=M|Hmm2qyV;_Fo$Ma?%obIEZ zeVmE=I1~4y`F{MppYwh{v%R0QU_XA#gwsrNW-`l}+|MLdCVt6eZzgLpiFp7|9-#IE zoKXkx_yKA;K#T+Ea)7h@AU-(A{)2FJkn0D@d5CL=xONDCAELKI=#qt}vd}dP4`&f0 z3l6g2;4nToj9!P)>oB?=#$Si&JsWRl<I8L~&!(PiX6gtrju7Jr=fM$rKEnPSdd}he z$l-j>A!ZKxAH|nP$$gZw>nQt<QO_~-KZd@?$bAeC9E0y;aC01Pj^q8~JhP7TTse+@ zC*bu2{hlD^31XhWuP5Q@By)2T51%CODdL?X)+uy24d<uP>@<7Na9*7u?-}OcELxqV z&a>n>hpy+)<s5!E2e0Sp`8++J=S(?IEf?V70-m|RS$zR*E>goq{Bn_5zsOm0iM}uK z{Sy3MMw82&VVB|MGX3VlbuO`U`JT)DT=HGP-&g4C3Ld<I$FIQY73TOVp1aC3@G9C} zBgZvjUSrR7c(~4af1PzVn5i51;0D~?gv*=6zR7&v!jHG;=@z}-qNdw$aGU+NnZ-NQ zbO$frp@uu~b(fm%(%W77y~lZX5AN^5#XUH>PcQf3?ml@RFe?w}<pG*JpqGc7GY`?? zA)Gwox9%f+^@wxu5j{O--(zZd%-YA~f5QDI^!SAH;|X;?g~O*j6Q0uZQ*?XE^X(Zt zJR|-yX66}dp5vkC<akc6&x!k-T3^7!3+j6T_b;gFC2L+1=OrAx#OE*3;}!h8V$Ca_ z8?WH*HM8@Yd3a5oZ<x_HX#N%s-r~)-_~RY>-*Fzlr}y{dde52if#<{rYX8Vt^AQa` za_)R$-6z)NG23}u%fnBfx%L^ZzEH;({Qre~U*Y;I^?ik-Z}9w$XUTW^|4y&p;o=9r z`@wnn1I>QI=}+eDCtCcxF9G@g*BhjQ_YzRR4Mc-cU>~?C0amsk7;xQc64(eXfNv5| zP!C#wSg;E`mw-aPpd%Ou4oX1bLZBvKP2pn_U~LZ?fZ5=>1lX|NhV?dyfc3Vlw`IL8 z>up(Ig!M&OUxf8V&PjkBHQJHWZV|`?x!|<~6xD)eAO>WBrxIZA4cKc>E%x+iPtOiY z5Cw*TwICbNyCZQOtAWm70${!4V+knc4v0}~3`hgSaPkC=0N0%M0Qz=@OXpS~4iM9Y zK3s_B(jO#%6X1&kxS9cbUCHmd0^|VdcY_DFdSC=t0=Vv$Cjko9D~PLr55*2Zex(bj z0*I~Tx{~WkuB+%l6$u7|)!>o@xKoEa`nkig`&<BL?r$Z)Lk*e$xbdJ@54iOdKt9hl z01iBpf#o`Nd%>?)9WW43pBGwr!Lc{Bc$Wk4<~<b<%loPX_*elr@gau~J^7%o4|@8L z+ZX<P(aLuwpie*6`c(i!K?)$Q8gHrTMGePl^i-p>hFlufX{bSy1n{Spp0((sg$FG) zY4N2l9Kel^`gQQ4C!Ze9^>{;%Uiyy`U<d-e06ZCpV?<{owHl`b^faM`39p;+pP3mk zqo02Xz<q!22XH-r>j8WZ;Cpet7w3L)yjdJhi<7%Jb5i_=1e7oWYAiv2CGbLtGZIje zo=b*;?f@^BMC(9m2*ekGd=JEHfz(wBUzCD_QtT_mj0G`|K|KNe1`)e7_e(P`rRl9S z`GVm*nEb)i8$#X?>ImU_s5NL0h!u)o!khp)hvA7Z?uVgqI2woJwQ%?je<=YG)Eu!H zz+oA@QHI!M;H(TfmU$=vWtp$Cd@sxQa@;RRf93FhInIu9)K(r2%cFaF_^yCoE8v@o z)LW7HtB5Bm;;l;bQ;B<(*jMSc1XPBD%G6bv9x9`8WjLr(3DAEP&Woz(UzNR8@mMw1 zR)eo<^iz!)u1@{c(YZQ3R!6()tcir@Na~J6+er3BQcn%8)xfVc@OX{85>S&lt;zSA ze6Pv<THLQy2B1T&Qvg3k;j<__8-*@We6J0kwfSC~@3r|}hxw{Q&2^}`4(CQ)JXjZR z)TO6-<gdrsS)X3(GmG`R0(@AXS!lq$2JCA9hYiWwkh~44vms|gLuR8PJT^kNMsV5~ zjvJGwF*P<}Z4>6B3I1(@7EPJkrfAWWnwxU|G^MX*c(NH9G$UR!_-%%c&6%O*c&9ma zHpho8@IedWx1f)fc7UE*qIoOoY{i-1iWzN1{MPi}npmyL-5S5QVLscyX`A@~U$!A% zTl8p)9&M?;Ew#7hT#M#fH2Oy4*=YKVroL!qJevE_a1)L1+u@^jtZ4@??WnCC+O?za z_UPDwyd8KRb)?Qt)ZUrzo$*8$_~^=>Zuqr3e(C{lJ(<7X;JFu^_KFAS(wmz5&`)3L z?F$F}(4Ze2_Ji;K#27#w1F2^aH4o+)Glc$!@{AbDO#DIKVa(8QcpMJbBZxnO{zp>R zDB_GF#%R1cnzduNH->)4!s9shji<H=oUs#FKaq2D5-}!aNx)<{n@rC!)bb~K#d1E! z;*(f7o<jdq;AARuHx*8&G1Jr8KLcOR;B1>oo>_d(W@hKm_gv1OdGt4*xmv)wIAX<d zZy~xZ!VkO`2P}rO#pGE`?xpauv@c+e;@KBZj%Db)3?C-2CxN+Njt7?GmlgE2l37c1 z1e~{tcxM%SuI8*?O<lY%2CPBzwfwz~yzB5&5@*?Z?yo0TGCd^2=?1QCpyrMAwh_N= zqJ~Y({btVJ&E)0XEFguvTZxm(+HHY==hrsoBaL%A4d0~E$986WJ8QP%iyfTpJK$mm zXMH;QWe|HO`tCxvUHEY~v$-2>cC(guqJX{hv=?3Xa)#_9ChtK3`_O7XXXF9uJ%Ha1 za&8=i`$PEW5c*`{<1Fes4EKi<#Y*am$aYDWf?^{Q5u(sVgoNqp_Uh%(uwi<-!!lO5 z{QM@t`74UCLT3t5xmoM9#<0-vkYHs%F>5a?+h6}eC$2AI`Dbe@>~oeO(&C@UHf#j` zg&hmm0O{5EXIW)U{^hLl5<kl-3b4^d<RdI3A0amRQ1GD}X{$39bt!7FbFtItZMBA? zE_QmpYq}V04gLL{!};g@_lLh&D*pLKM#@3)7L6E*uh4~QO<~HAFr%gZh_DcaQe|T_ zDU?cun<>m%;igiAhlMt9_Hp)5c(|$*&MH@17bh>5N=lQ;(Z{=pqG-6S!pTWlP^m0n z>uOsd)XuG#u0>!W7iV2yK{qEUEDk?^NVe>hqN1WFlZ22ppD9H?YZ0MFot8Yxkl=7Q ziLm)U?m4))=KpgkYiCy^|G$pi+`7ASA^*R!Tq(kTcH?}!y?rcDxVb6Z6pFg(>Hl>J zSa@)xsubBJo}!l$RP;+dg`15kJR-!}Mx`_T(lmnp|0+Xe`m2@@H<e1EGL~>Ctg>;_ zc`H2BUOrA{9|t@8q7_PexfFBnrc$~nl`fvjKnJC-n?dRB>F(sAa&|6aU)0XIU5Jy) z(MhC0z90Pa{gCel|G!*dxnuV;S88ylh{b`H%sMIwQs{IFV|sAqN<qb|N3zP6Rn`Am zrP5KQDTMlc@>iLIDpe^RSiPDhmNb-!a!4F4St3+6DjSoHDZ&(?GBqt+x=@gxQt77h zEmf$r^`T%#_k#ZRB}>}-7j$<Fw$$N(OUB83v=fW<a0hl&=qd&Ux$<9Q%l`yPekHf0 zl=xb_8=<nc(S=8pw6ZDYY+Km3pr=;nonJ*ciJ}rquY|FyR8FC=?EGt%{PHvWYl?#Z zo*>76=BI#VueAGzuZVV$%E<Kebj!@xqvm+jw0P|QbeFx4k8l2e?OmOnTwR@<U876= z`WK+~D_+7+O%5eFT9bo>A-b^82&f8att_Cm4{{youJ9>lWQ{#*#^7jG{+fvJzYJny z`jytkMiDY*U<oe=Cr39|2X`NLZ)Y!E3%61}o{o-A&czg-N+-3ip}=1{|HzM|rRu*b zw#;I1en9vR{_n_*OKLTKE-DYDQswUK?51>fRJqx!)SliQt&JW&MU?g~E>4!l?28q1 za`AA}TbQwM7AqO>?_$xAai?NrwDhK<)L1WNv!*Jq(pCiuTZj7l`@4-CQ9`M9C{mB= zoTzRrTzFbEQ~swK%b{rV564a}-b|IUsI$FIi)w`(9K6(8wYQDZ-i^5|XwyOwYUShZ zqqfxIn6J`KQQ#_09!so{|45ZDyv^TYk!o-e`!ZHm_MYzEz8+p0v)Mu8q~NG=c1m|G zSV!UG>7({Hg@?6LIJkK#6t1ooK5-El(k(vBKPweBx>_BE)=X5mtbqy3Ni+_ZxQdVE z|4$_1pTz%~{{Ia7e+n_RHu-sa`|5qY-BsQpKE;YTI(qmyJG;0zDmp2=mEN8zwX=)2 ztA~fHkBx)UfqzPMF;7G&R@B*!z8(JEcZh{asQ<_6`9(wo|C3nhRm48Rs(`(hySJZ* zr`BwC)Ho@X#hjg;X<O<0ciV1`zuNx$c{Jmf``!Lm=>I)YfBze4%Um&AL;v-Jvdr;c zkzD>elFeUJ{ZEj>e~tIwF}nXX=J_XvFC53`p9H3`2!)Mm+@L|x(Y|3072E>NmK+We z!HUtpo`M#QfWx3cgMN2$38kO^jzJKW!p0#wdeER?bD&!VhcHWw!gSm%e*$%u7@?J{ z{%cSitrUuXKa+K~-nPXYiz#hA+}yqF{A~W=Ahb|1XZK?E_KtQg_8tmHH*fo*R>ptv z;rR23oWW0lQkFdb1XS55{xQej$4i9bfAMbm&#h_p?k-9ncLnocTg1_%HkUH%y}VR@ zC4$QbnoE1QD0p-gb17=?UNBhcq4M;z4z(>%w5Yqg)*M{i=wH;iXmH8Wm4X9&v@HrM z-HJJxsLb*&p1HQMoa-Sb%kP5_mC0l@G1HUWBHi4pD<VT&t*r`LyOb@Pkx@U)+1{~O znB~dm!Ol7K<iJ^H`GxV9?-lt)6Xe(7qfq?%%OhCtV+io`uBh^Jb9Qs{*0{O4xuvUA zTI&KfdUv1SEYncGnzOT$)2|a_UcS@iUwrU`;%_RZyLcG_N*cZ0>|9+vHNHMh9&R?J zN|h*W=VoWp=?xanE%mL)KY^Vs)AEZ>(?9ium`aukP`Pmw`lXjDUNUIaEWKW@vv|+4 za~L~|=AX-!CsjU%b?6XPy?Ru-qKsSBf2}I=?^Qu6%bIjW6~(VE66nGs|M%bjtBr^- zUFQnk8bgUv0p7|YN`;TsPhHH}(5X$4pg@{Y6gBGghC<=LvMv3mCd>KD;TsmR)V--n z)zrOt^Yr@l^Pi3)_5WEF5oWTCg+f)ox>Cu14u$7&uJS)p;OCQ{r*Wf2J+b-gOlGOY zZYn!F2M3j>d(l8QD@VulG!L&|+2{Wq*JP8Qo!^f0J<GVLR8gK)TRPTGkB)BiFIEcY za}FgQs;Klt#jiWr+;PqKnNnd1q6)D*11ygao30TBtQ6YN0wFq8fdUaLbWVNJ7c5Bc z=d51wYi}ZZi{<D4XS0!_6TRB7(W`X<E9FAHQ<wCG8ker9Z{dFP|L;le6kyO7FRnKP z#CUsod0P-27*x7sU{I-2dV_)g48MF7LvA}u<(A*Me>>@KiwCJns?}PJtCNR<ajsP> z-OJ0%&&|cv*(JY@6Zv&G@k^N}h2=N#zsB42uVTg)@o@4fYG(+r6y^SRK?U8MU6kIX zN?GcvQRBa>vM6Hz*NptC%JOsbUv-txsP(~KC44B$RpnN%Ub?5J-l0i7R~N?2az4V* zaQvzH&vTi<H~zOveXa6&b8uI>x!M#~D_nd$y%e?zS0^WjFlV)|kG0ayv6#JWVMjZ6 zSA~b2YY|6#M+cS4S>^rfm(~QTwE4@mmMLkV3LP7osIWLfMgDm1I$JvU>zK8e@Gm#U z>;3$6DqbHH=|j~zoqFgWD*pXpnNRt3^4MAC%JTZ7Qu1SaxO+uaMGr$^>w>oYnj7rw z;o|YDg4?Whx2(-ym%k<deEWN6HxKXsq3une<T$Pa!OY64yze`+j;^b#`tC+oS66of zjkD1>2!I4Y90YiS03{v}DS{v+$QEqUkeVVbfx0Y_Hf`FXEbk0u9af7JB};-VTON;( zH}+WbX1!j|K0l9Ve2%qiza5LcKO!@$vaariG+RJ*RYk_}<HwJGMEv-{C#aO?O}GQ8 zREipKrrb;_nM|!dTmpUj;_8!{oe`c~eV38RSz-Inw`N1B0rfzw&->%!?tI-F9&zip z-g@t;<>gZmv>ymGLDV)3RkgNf)SGkWyfb$_wr~0IaNb^R@{&N~s9n8$$H~X;xKsa# zrGEtSSfHiv3vlU#{AS<ubS5+O=f<0zS}l-)7iqO5K|{&;uw*S51v-<d)$BKoKS$3~ zU?V&OG62iT8kA*HftcNkL@w?F)bJ3<Fe+&Kp@$wC(op&q;7Rur-@y{NQ~_>dJNGN5 zoZ-ZmG&^BxkxqRH@Z})w6lQ*?DmCJg)~Ygeq$izAl1kdJ792^|4A!=N*U=qK5H!O8 zJ!K?8vWmiMqV3+jha_c55KN@I*wD%c!8*}F<`c-wMU)g%3*(B>cp{|&laYKUn{_~o z23-)pZcGZgRW6mvdfNAWJC}1%ACb0s5#UGjjOit&FEXlV=sHX)5d8T<#(36XeBbj~ zlYzR*k;Zxzpwj~ATB4waICQBRlmD|1lQIU(Q%KU*lSmg=k&<Yl%1pCyV@E3I_yD0D z)%-qyPRA5p>e3*pHB|NcP8tTxUnf({dv5mRc16kVbX?x#%Ee-(kWB?zZxSfzZWv9g zrQyd}fmJ)2b6nT7M2Y5Ep36P`^wT^G`c6ut1XV&hL2B&=^z(UQ5GZ3in$=9G!{ENf zG|5IwTXvjS=b2JWalh)Zp3No%jt2@U7Sn!CR9)W@7zR{h5&f5KNmf<I5msaX!E{N6 zPo)gqbwDcsmL&6h#__08SwY%`d{`6(0TS8JKKp4H5fjO&001kPb^$>?BFh@cHWKt_ z$2qO3PI}*s1>N$zGYIQY3hdOc0|!t#^joN7l3{54KjAp9Gw@;=<|`{iV(ni5J3%S0 zqg0y&ZkBJ*pjtYH&PTQUgP!1pU-)^;B*Gs2B=kTE_=*$BWoERVp04{NvTY~!?cRE1 z2VcK&rWlnNhZ0nvv5Y&;jWG3(V9W|_m}sHIsbNA5(DJ4vYMLWSs^;iPQuK2iDP?UN zA;>-if9=e^72R?ijHd|8&tsY2S!EN+sG=s4SDH9Rlzk1#t}DUiLfS7D(&@szdidH~ z9IO;T1uXjLl}=;ca07S)nj=V0ZE6oK4Lh!ck0%lcqL4XAnjW$THM#KJfIA$5`G**U z6+jtKd@!>EbtXQ+<1_mqlG1ImIlZHq{gnRQ1q;va!>ySe;O;)CS!wc}CfN5;EUlQ1 zPLZm`eaIqR>)?uq<gEZWdk2&mXi4;mL@#kJ*oLAA<C5oCCTq%~#7{`jCE5~rp5-h} z)J$Fn<Avo+T{Q3tOA_inMtm-&lOqPv2$phC|Bi7Ia4D0MN+piv4J~QexAJ^8uiYw% zSbibvbtTmQI;4HgdRIUNwhWaxy6Jg$oCYETf{0}36)1}&E*9D~EXOA&U6)Of6z92< zD~DWL&m39_CE;6;+e5i4$fjwPX_oy-i)6_GzvO7iB$-M&uANGfR7!J7hpF<Vl>?@q zkq;lXEYCWy67t3nf>7L}30JC(`2z#~*o0Rs`pbK2wLQy?2IMAzD&7aVtx)R-nxvz3 znMQ+j(_8`ocimaeR(YObO_o_Xl#!M6p_e>8p(kuJ)C(SjdfN1Y2k+Xm<K(U-^&Ogi zAzZz?9i)2}WHVsXLU;wDt0T0|%r-1UIM^=R!3#DLcB*X)d@h&Zd6+IEqG*WXu&$E^ z&ky^lM9POc7Xkj;0#4DWX{ANOxUm*#632tK8Z(W0*b-9GaLcGA8n>LuW(C0sT5|-U ziYp%Gd4tsTVcg^hG|uzbN<RQI=wVFfbu=d<2?k0hWGr!#0v}~oI$%kPVoEYzsrVye z8uJFFoi{k3zUYxv&M9=}z1Rrnxa_lNwkkv!c;<DyeoUaXOEfbY4ue%^2CdYhHBFeh zaha6YBo&NaQI#}~Q$<x&WcZ_UM|8vtMM-}W{X$P9SrMY|A_yEHWl7X^-16EQ@d(J) z5u)B)C64AK5C~c(XF68yuqN){ZwL}+(DWSBVoXI6X)3L$x}NrY1x;iwt4s5;Y-y7D zGlC%-oW?RNok~coAvyxDs}^et9LKN{t4q!dCv!4OtDJ<_CMsZAJxYA7d(|ht^05Pm z7rmGXI()s3f8zi657fkgF1R1;iC{e-T=#C&+7&(M3ZC(cNlp>PlE^TENUJci9#AF! z01tBAOC(vA7Fk)DtC9-HY?=V<g)6@a8f+;7<|DFRz8CHXR6wq_OVrr-RZ&N(rN~BV z+DG4;t5h3}YGqEIEEFdvi-pOZV1N0dnYGMmPT&QeJ6mZqaHin-WO|Y$$Hv~JYGwj2 z?I4PJ7<8sLy0I6B;BH4%T^AG;1vC<*mB=rG(t;EhHTWsx^(-P>BUjp2$<ex2xKcj# zM6gy~!0THy%$y?_-za~N_2b%+{k{sC126Hau4tTQOdpW5ngnx05M@;c24G^|wvRZx z>D6P%V(F45i-IH~g^Fb*iBrMaeTFtQjnUBl2~ZfvGMp$XlF?}=%%ZgrrnE)m(~_mU zqSy&b5A^K+lXwAmj)H9rG+YrfYcD9i!t!Z9li8R5gFm>C7#PSG(3(H=e;Q_0zcv3e z;i_UFy>6f#BV=njk*y0XIp}UON%Nc~D2%D=scjNT(_G4yQyP|AEVR;ytWCUF0hp~; zG##Xd$gN)7CChY@6Va+C^zmqu7W!x`tf{G{sjAjIAHIIpf~f{NlLcxj(o|tQU}6$q zz_y$WQY;tjQ<Pe*JM9bb%qPy97w!rn`kbOqPU=d5%z^nALH7aImG>{ZqBw=Lbg2Ey zVeNxG>h4KOAG=_jzY{f)68O*W1F~Wn0h5)^Yx<U0Q?IlrOp`f8VM#1K-^3JF0a}>b z9GwAJ9sNW)aX;!iecn7jrs@-unpz~2w9$te$5&ThiEzPjImETr{(yKVmL;VQS%MdU zu|?$s)U`cPuTMqP<>SR*)n+}*^|?ILlr$;Xa1=q31w-^~$pk@25#dVfzr$--Mz9)! zmRh5=#VXk4|L&e`o^$LyXpQm3nmj*`7aHeIM0>fvh*x{?T4J;W1(h^{@&WE>121Y$ z7$YMicwzJWF|@LI+wtwzHoUlr=1c`NlMe@aOv8!x@#d>ibyymzio;du%#c)tFGFIr zDglkCYyV8VPJ9!fPGby3Vk!`nSb#E(fWF}whUAw;XSD39ye2p!gO0}EwO`cInR5rw z->(?n#KaV<aJsi;Vv1Kk^%OH$E}po|3=ZaFt8J}yEvtLI&9P$(ZbL(>dC>C*48zbg zq&I_H_%QIA(GDFrX4`~g43gKxk{7zORR`(K75I`2QxKGJ&o3u^iFaKGbYel^L`&fm zU*vg7{=_F>u4?K44T_`A>w;y1bP85EzLTgBOV9(F*z-?BkJLvQWF?DOay<{&942P) zzC%RzP9P*(W_%<>8`z9zTB{^?g{vb4UP?RJ+YQ|^bf>6ldDC8)+$zhNbhv18JX|iZ z3t1VP{Fw}1MKO%o=JE+Z8muEANcYF!?@WD^kM_Jj0~nTwJl^{+q180RH5xVBVfw8> zd`1xzjaMw1a+BV0_kzSrjH=N|hhezPJsoQkYinyig!U&eBp(mp`#l67vXKtNQXl=R zmgV>z!pG3nDwtHO4Lj8ITAPG1v+og-aq?VR<T+i+aBc<Jl)1FO6`7PKs9FyL)?}4S zfgI9grMyrE(6agMmhE|}Wk<NWhG97tK=`k{QUeT1pdno)K7nO@x^pc6bo|)w6UgvK z*8lz|Mx(FSLKXyic@cdwXqO3%%RfU~FScfCYlcQ0uXfDT2@YmyA)`pF#;b+2s!X$j zt}jh9@HYvJ)hrYT8T6Sil`BV+V4BX}mP-4G;sbjQ_3U)e-~XHFk@~3EO8r_h^*li| z?eZG{ZyxCdO>-Pu=o+BGX*0|tlN=0mha@Az{3&dc8(^N3#DYHFw9T8d@Ac;F`|R5h zb$kq3^#a;$TZ@ZnU47T&rlxGujIYZTi^Y;@nwsNiFD<4rKoOp2wPw%j&Drx=qSu^y zjfkYfm+|h16YOR-0jUQv(1B0SIqrI%d))D!IsS74@Y1iHIB`v%$ROK45w2)u+SXcH zJ!)UsGEHZ4GFaU@juu{azl7j-(CW(xG~WPK#4?6Gm|36w&#e`tmDmc>3ewC$g8mG^ zUO^r(kazqP>Zb{#`#AA+NIis85ASZRTCE^$w-zo~nGCX~AHWM%4S%}6$k$d%n!dbv z2x<xUlM-0Nhgv?j?e%cppMbtrh+Biy%CCkt`qROl7Q!G9J?eO!sd`S9tL(o=<WAgw zyRJI()(%Di8y!qqpo|+>7KZszZrhP~2j2HQZ~}Pe=>x2Sa|Zh@72+spt29~qA>Jv3 zo}+y!uc=kGZ%$!)z8meR-4kt6xn8idhBvET%xVvO+4r&3x`9{9vdx+r-Rotjw!^>x zSTeqF26prUS{Qt^wSaaJ%cOw!yx!zJpG^?q&e)$|?}Z#1MW#vqO<knkB>X?Q$3gp1 zfD5FR+yk;ElSzvSv>inu?S%YL5^YF@GU0y*`2BziVtd?OA}#Kyg{9hi)qJ{8NDpXA z4rD<f7z){FLGL8U2Fgnh7K?+xlS3i4jF!pZJ!}}2*gg|pLuhT;V%>4({WF7u&ftY@ zmbFd4{dPURmX(dKWz}NqS#4`t(W+LV5UpzsXajg<3qB>W$=_aY^0&_>Q7d_{dY-^? z67a!*l*Ah(ASIvhk}ky>ilEA(@~sTda5lxL3R;&gL79g^-=YF*qqKkj>)3)SL;Aaj zZ(u6~A+d(>`7WwdO31uyliw(nI0k!znV=~KtITb3rMapcEhZycn1EU@5P#IeVu>-{ z2}KfBRg@Gdl0RP&6|mjm%>*xu(ci(dUk3WMBFi7!`eO_$iKeRY%#fTAB~{TR0kxfh zwx7l}q0+JnqtA>Wc(N&ti@YaUQeY$|RSW)xbMa;3s|gygLWDfxI`9Y@Su^c>&<#ul zPw#VAtyi&!7qWd`z|X`$zeMYDVBS<KFMM#$5$II@WS#-W{+jQp_uOsAI1o(?5y3hH z-m8P(i_O+w!oNY|#QJh;=Q-Wq4y?lHcJDu*-o3kX3wp|oT0M+g8EdxsG5mXih*n5n z46M{zw7uD=z32_H6rCFM7TqV(s;6CAjmmx(mz`?X^(y|o1^0l*JUZ|%6#_a$+`$2C zDGxm)+<yB5m#}SOVJR2(7fMezvHz*oo-g8GpK@<=ufF=~YS`8_+*S?e=EIqbR(9(R zyc^~)HH)uJKXziOc8_s*$*^|cVnNApjzh@?hC19=h2PsS)M!0u75j|j@akUEaKL;Z zTuE>Osvf0+VW^#SxlDO*Am!2n<x-Y&DUh)S<1&Wh+SD6%B{xvXWGVx>%4OemJkN3c zu;u4*%Ug-SSBZd@S0ha>YA;yb#^M(*aj%y1xE<GVD3@{^_sT$dZmyhL+~ztDKkPV* z5k7tcs3#p-KP`_kB+8n5n71DstBec|j#S1Ej-=tG>sGd29UH6GvzDHnL%P9SsO!84 zu%;31HfqQt)oN{DR{QKzJWM82I+LQQB+Z(s1k$^5p3gTmE-7UdXBdW5DHCs793Z1@ zi$JIQS(w#29s?`dU}+j%Ot-;LTlbA;v#x4`zMVazTe{)c5^tE$nEnou9``fM?(b#> z()Qr(ykY33p=+vQ;ynqp&W={)5eK2I(oCbZ(0_~IN;6KHqsSEPIf?v$Tm8U(SGSD= zZ5BegYc<x6OhUxMnwyb(^0wu<oMrO7BD-!OoyqSVM~1<Zy003tE`jAQvvS@VC=B=$ zv^1nyww)uwJ(-8GwTDKuWBVAbp||@49Y-iuO-pluBe=ff8Xzb@+-pY-Q4qmg<8002 zNY+s;UgvmD;PKko?-Lh6lko#hh7LD+m{Mf?g3Pc_4GoB6s$wfr)y|Aq(&tURJO?Vj zD2cjl%D~t&j$a>6#Iz9uX(Jo#+bw>)rFVQX)C7K-_$`>xYL`^0K~+vE*tyGwFK0PX zC@d`-FxvNTnVv@fcPyP6%?~1326Y_?w8cgoZ}m}@<5?t|SMHTW3W?-<BYP0EOPHBI zhi2y5+ZdMbAWf&#s8*1&fwveOr#T1E1`*n;Z7@lJV`!FDb$&R-BHGs(l}DR2*=wfE zk$OVQyhlbvU(ZUqv!7_<DcI*}?qrqlys9F0SsRyRUAJ{AA$l4|I?k40PfIt2+|YL; zzWrXP0RVSEh`*#!9ebn9)@vpRK-c4vV9~q2yK>Oi&HDJnjtmhS>5&#S0l~HnbsZCK z39CT?O`W$4M;xa)H1-w8RMUf+#NNg@Y2A32W@{kdQ*1~BjBjgxD#2tjLc-J?RhC*- z?DK%vW0>Pn@cUB$wH?!+qLsQpar!td$nvz4(SF8H(X^pcs(SkJWsWya1|E^fIzYR- zGN#%1stlm6rF$@=PTqI(1HLKCriPq$HIgfqf4Vq0SS*zXB%}p;UO1yaf+@wrn2Fi> zPRys^BLy2Q`+Tv)vaYQgKtF~%kOS2YOh`8a4Bo*z<%zW)5|2P_dZ0nXDG&Pi$OJEN z950&Ypt@oll4MMPM>syD*bfG~oQ-IAGjOQK#Z3p9jI6`va+%D^0oTptviX65Y9*hK zc9VYv`<mp?%tHf-{D++;au};A0}k)-b!*5ltV}64qVOEMxRqKOEQpzb$<!g&Ef)$^ za_iyLwC~CanhQUKx_^dv4(q(g;If;Ys$w6eXmU8qWqaDDIS>FWBf}gR_U27SOePuL z<aZvpZyU@7Eg_rZw>~&$!K@g-y}kiDz_)`nyQss+nhK<#Q-632`n<>4=?s7S3#lyw zrQ*Qe)Yh$uy-Rzil3$FxY`zG1D}^T&nhp`|7>q;~hzo@m1&|ZGqPj}jOfv~4ZTTz3 za@y6jN<{<ySuPgK#gc88ishyr_m`lf4~1(GBb~Zrxc>NoX#KGkSP~uUkKVak^kOle zw@u5kJQY+S<Y!=Nnxb}Tqiy=*=Wz>(wLio*qlot+LJes)SmFjw^s0TymWPvvyr}|R znwpy0d-%kwFC17RIyF%w{jldo;6Dd~FYw89N=Vu=rM<iTUG^@2_fmSdy~n@%4*a_N zE_gvX4zT?bo8Ixcb)r<r;qwBX>)MW|D~=_i!z%YOgZR9FrlW%piqt$W(B`q(z@Au5 zN6(UHC&)9t1%J}34@i|yuAbA2pNw$-D)G0We+(Yz8m3ZoNU2r+7ZMYmZIOcPQjb|s z2~>AS`frB}3(WS}2WnA$0Sq5+>co-L>c=ztU3b}EzU!{lJMK6gc(?r!>&{A`u{O8q zVNhOlCKcP}Seg|S^~|g99i`0V@K5&9p_^7fr&b(3{}g`yR`YjL4-WHxlz0PvSMcvP zZ8zk&s4s{kF);{X+(Fy<cwNp|60jsmWp;aYDp6hisiI9eDM9<-<9zZQsxj1$p~i1D z_2;-2>j7PUKG4K5u0s#wPuccWP~WY+Q>(AOit<^Z_oarh75C!+)#JLGL8p{t*-E>h zf!PO^6`8*y9E-n-`Bc|}_h0?Kv*hk^p=zi+fZ>Nts%gT2bJ}*0H-H4e5}ZnTsWn@B z?G{Xo?lubHY&CuLRqJqTwuWBpZ-(BzPUy4TQ3IM-p4*)AP|3TU)mAMhR##(ugAaV2 zx@(EmfS5)c3X)*3)W9c!8r7B@432n!5df1><;?Wp_*m7~U2SXP)+33WtG{IOlcQ5x z7?W8tGXn?;sOJaJ9}RQ)&`Z3x{dso8bw}yt((rJpH1vKyd?82j+mQJ=T5I_lBP_qa zxhDg%BCw^P_Ig-dZU1m)syL9JbRFc@Zy!2zOssm|>Y-CAsK|)g6oBk0tU)YMfj`9C zAdS8Q8U*q_cH~6+5uV0uV>Y%t|Ni8hsgMaJZD;anzaVou>mi3rMRC7la-8p3`COqi zGBV|9Z1O^(04A1$Mi=RW&tk10@JR?yCxngw(Y6^AeK}W1`}6azdn~6Yl3XY#VDKCu zQ)$y&(KK&p5bY(-jS2$Rxl!HsL*1ze)A!e%LzgeF1m{Zr5U63LgU8n+9{&ORq%9Qo z7$a`d0~Wt$%ihc9w+%Pfh7p$bH#z(pP>&X_P`21RO#I{Kj8|Xq=gc{Oq3-QN=RWr> z!)xDe>=pDj@la@Wbg*;A>Sp;9nkLH%m>Njq%w*CT#j>#>auie@p3`|twONw$HJh~r zFhfKm#J~qbpQw;Q19jBL61%cCyjPCrpIA9sd;()6$a^DPX~J4Z$lGHjpQR=|i?m2l zb`!gy28-O8y8(<{=A4CQWkI_?0qq9<-%iNd@9}2l{f2F?AS|rx##-Fl#AV1QckuN_ z?Xr_kc_x#js5E=a<^59$m3(isI{hk?FazGkU{7&u`2?QhubNb<pcPU{GgC+~sbn$z zm?)n-DawznoJu*GaH<n4ScAaBKfdHROU}yt{L13uN-v!{@ReK%*G+J-apw_x$I8lO zWZ48hjF9^{=H3RBeggkqP6a;P1X!6XfhTsrIUgRfhb~;cd>QZWg&t{;|4t&<D?*wk z@<_JvT7w;Em!;<UT?QT6#md|RxnePA4HOG`%Np4+{2{869T=pxZlx-@+#ogg#Rrp< zQ|BH`PEDeALO(fZ=WNg`m<gW<u;Ik``6uj$oE^3~HMIf&qI?GCF)QI&fIyf;E+F+0 zpf@n5Z7|<gYJ#9FtSqXwJ`-W>dm*+1WaAdD%-LUZ=4|6KVDEAS$Dai&1x}k>v1)&2 ze*v=2MbM!9!8+k9cm`Y1*(SW-4h14^aR9rR&W|tUk(=95)3B_|#x0`)F9;Fu`87<X z!JbaDj#drGmwr5pYMF7;XmRD7<KTK$f@-#}gfr*au%4c^jF-?#_`HMJRlIm4S&(;w z9qxu>aT4?FfUlq~Ctx&-lENrJ*QKnPGTAX>h%wl5xmYGb@A_|JFV_v_%B@9orfbG6 z<b5x92Vx=cPXn5t--i5h^VODLE~1rpM>wv<#7e0V36`u^&U*Holgs5LNl_Qr0U&`{ zV_e`xvB@vL*4#@w|F1-NM)-2<jPN7j8DWB0Aju%TUN2ZA8K$HB|4%Ic--PKDXxk&f zDNvBg=rngKL8}@^Jx%$=LBAtMaI$d-9cbjJRmf5Cu<U%AID>OY&00#qM?J`TAYNxs zaaXyZ?pj+DLAhkmQqUYg1oTZj8t!RTol=9TJJlM~cyyS_Fkt6pnBn&&uU<{s$$C8* z<$nzFBPwrLQHiJ+BrK1NFllCFgr=h}+mlXmauWWOOG%rWoTThz3E)MiN56(oU<aou z`*;#My*#z{Mqid#CfLx9&TDfWp9F9?&}7MhwnzXwP_%^~B^p5E$BYs%V1%!mi5p;b z#SuU!jxP~2&?hR`x1Y&K`WF^cJAo3=ll$-!CV1wA&zHhHEXo&1{FU%D7cyJX9#(6m z7w>M>W}~IX+U(qx32qQAq|S+^uA8Z{@9Mmwl%Ld;lr|13<u1+CibX-^V4jY`T>BH^ zt3V|lKHJgfB#g5TrXNiTEOObBI8HKc%NFmrV4Tlcnrd5`X3cYfFC6z}IVmf$l9H34 zDcj`g>I<fWHme;Id&gl<$=h(ug*OO4TrI#d0_M|fqq)kA+pI=QCBGsjin`9rEN~)G z8|68p;?p4AN5*VBo1~OPYCDXoKJE<4@=>J>P>RUI6rJ+;8*GgrDjV%Sd+7A(EArv^ zh<__dS^g0+VHw!v58e$fASP~ldvI2<s6Ft`ruQFuDay{kUwE9ji}(+C7X_cj2{tvI zKo`OKQk^-edb_>-u7b|Rsoq_OWckq2(wV(`&(xKraL4F3um$=Z_?E)jP~=lsB*u_k z+3ESW$%E|G51%*Bp9y^dKV_p;a6{D<MawHNa~b3&4JeMe1fCZ)8FY1B5Kv43QKc9G zZ5s*>iyQ@6kwfsM0KPXuAHfA;3GM7})=O}+aL>Wu832nQqT@q?z_DWBJa`Of(eLUA z^5lk&^!FtEiOuwj#&$QtdlqKSR$@88JJak`XCQ=4cjqO5`ln<C>=6;np2iTx(i-p_ z?ZfRoVVS5WFeLAUeh55I(RI})4aGn{?3){#fOdEyM-1WEE2s~_iG)o9{2}0>4-U=j z8+zI@S`f-i2qDK~qPbg@?o&2~DnaZ9sJ;Od;|8bq1G=b(?YEdxYhHfVKuVUL&iH2D zaVlwtV{9!g3Toz&RLXS)n=KX_<&5i<#)jQ;T9J{*<N|2Q-wjVsh6k@df4B4e;-CNd z4}O3+_bfdB-C$+IiS1y{9yzq~j(rC&Ez0k{AY1o5Vg`BNhP;1_{CmM{3Fh)ut>_G9 zcj}4zwPU{l7@i@fiQfZD07aLmc6(BEgal}s$X7K>1DnlJR7bUJ#dSp$bR=HQ0cItM zQ;wu<O>;8%?~o($yyW1&D1Hp|;9Z~tIAJu6;21|V?Qq-g0^IYq#W5@`3Z^A|Q>SF* zGq#=3DMkK_?Z9X(6O+W7VACtX>7(|O98AaWWl0xHoUBN?RASKwI^dz=U(z{Kk`+r* z_5|lW6uiS~5m$*{!WwWCzR1BLjnKO~HZY_#c4(S}K6k2G!zk!wHlr7eB7-4AYdk0p z1mBD%fmrmLmoD9T=cP-|HfftVIWdZ3V6^8AqDEMdcNyipG&(V9LT(40mrM|kfyVQZ ze({?=s4$s6@tf`<o+N&`Gk(+Ml#*J8cQbwym^VNNn~dM|t8A&l8#sPbzQn<IoyXtr zFSF&I@tY2={Uh;}n~vYKg5x*&x^3Tl{H7ex{(t%L<2U6DteWXYQ!~2&Y*3H%wK<fA z-kXfy)Bvdd6O6bAJY;me_)Xp6o9?vSSoo%_<qf2>bL&TM%IDjIH<6&*J&Dhfhq0TU zZ^dr9f9?CkThV%K5W5Kh_bcx1-EMYpaCPXwzN)lX9$bXHOOW>$LLL-Ga6+iNGt4_w z-FIL}SsW~*ybHuZ;Ag$!IK4n`qvk7iF6~t2sjVp-$7w>Go)#yfI8MtzEpK+mae8XY z79IY#;y69B_UDi*9>?iLFj{mj*^J|KAHeZS%jUW-isKZ_sjfIqAL$jx3D5-mzZu8r z8|S=pVH~Gr7}Ym7ivF-1?Lgm!_MXueMq3=G(L9RdbR63FL`NK_Pjtj_+J{%^){W!z z#=FOSxigNFr*y_~3gF)CzRU~Vahxn+gE&seSLR#m#ButTZ=X2s`covCWTH4uekO?H zbRg7Z){o<KKu=qiZ3()-oZOR=#r|=eqTX&Yj?=&Ch-W0_!FE84l>Os4?S<Zctu2nz zUCVbj<2dcZ8t0D?$LXV$0Y8&1Wz(*knaLuv#LsKGrc3L`aRS8?$8l=w_r`IYZtv`O zL0LbJQ!s}%h~xB;&BSqf2h8Ia*NNlwVq~r-NxT>lkK<Hz1CHT@@-&jXSn7r{7gGUP zB5!uaaasmp+l=EBuOpDiSQ>}I7}c>4dc3;%I8GP&Jf~~6%VqpbPAKE<Be&Wpj+3AW zy3{L<)4<wa6MymJ$8mbOR~)B|n;VbfIDxXR=%U~yHXX-l94P%i^ois2rhUNj_S^es zEjp24OdQ8)UKLq$9!Wst8~>fn$8lO(DCGu6@|h*4VrjZv9$qhw(>zf6Z?6}}>6>PD zcznxn&gLyETh14NO)*mwqtmfCPKyBF@Ar@6w77_lJQZ?1;y5jbdwU&moDcz?I(26h z$0^Fy7RTvs7v%}#IL$yWes7~VP9NHpD-BOfPh>sLxATLgqGpWTcZS<C4xNd`aastY zAa%rX`mS@g1OKBqP7&Ygh~xCN%afDvU!gvlP}RgoDag4KVEbI;^B#{PvC}j_g)8PV zDT_7r_rKpq(hQCDAK;z5SR5x%BL5(}S9cs`IdkNsynppB<KS_GzuO@9Z^mOe-R7PO zVmXb#lRpi1qg%0@nmhDQ2BDm0N^XLj>xkqOX|+8fIsKmd2$XXl?ug_x20i@ajb!=Q z*idzRygD@YkzDw~ZnWcDrY2hZm<K}K_l@LqpSy?-mK6uk!Lm|EB&V^p-@|Zh9Leby zxsp=U_#q6G8v#UFilG*#CJ<c9%Ppvo7W41dkK}a5-G(ALWk$!!re!##u1HRZ3ck6? zNKQMmVBm7hP}(ZwGdV8pSf;XM7E41xBqxTJIbSz@!2~WSi>{;jD2`GsgfbS%>3Mh8 zr*{RBoC3SHXC$Xa{dcS7QpNFo*CSUi50uLTQ79)e<XT~T(lAUz<4td$yU&}XQvzsn z@6+{i5aW~}{(gfvPM5q4N44TOC3DUeFGIn%)rX5(+QM<1Jo(AhcgckTbnba7<SZR= zoPIx3tNXha{K*M#{^-$rPVe7;0zoj{<U_4EPFHK`-R|ymGmaDTr1-7QI8MLy+{5p9 z_Mu0kI8G0OuKs#^9H-a!?VFm4;yA^%S|Eb6kyc9*$Drh=+T%DK+p=Zfz9^2<F5nx# z*%rrXS9csIk__TFr3&=|Nxr>Cl0)d!<o(1;ps}|_a{8ERC>b6{a<Ub~iT7fCY4ees zK9?f30o&b^RyEUMy-eD-?TjVMrqdS52^e1($;r|~?dZ2Q8OiCcL{f90Y%Y^8q%$6< zn5J!*VI(KyA&4V6IoT}MMGl7W_l@NA24koWipHQTe!f&L+O0@V<zfj-qpetXyAkb# ztryAZGYKV|$>-BqB|$nGjUY44VckSk1#z6RE^?cOT6aOMzlrzPa1^KB2Po;^yg-im zj+M?=%Gq@B!eQvBwR4g;xk|oJEoM@>X@>Ok=6X?_zA)ts4LQE5q$EiZrk;NKX*nsn zc2cKA1xIn(x^@Fb;CZ3~G{0lxC{7!Nar!Nn&H7AA<OR=hE0tWXBx<sfNsF9>b_dbh z@Ijk3G8qZSaWcHFI8I4hwEZ4|oS?sZpub-aA~`i$@tax^jP?M5D7mcXfNEztD2S8m zpE<27c4l8F6IO|D0}rq|G+Z>E$cMM_0y-dqj?Q?6xv`6*UuN;~8D@!6o}v_m3RWU- zfPRW<N%xNIR1Kx_%h4&EGn%0)Gq<GEW>nt~jFc>WfKq<WcA-~?u~v2ipHhiOce;O1 zdU02}4rID_DU9ueC>!_U2IiwpxSuS}jXgU0g@pPA3?_+YE%ASBHqz5?OE5Y%`r{ZB zDf$B(DP?S@U!<pC6#7PbdJQ8VDncU>Ab$l91j619p#E=d6zOS4DVHsy_d~%Rnq}fh zPw3s+QC<!yH{=~%k)9ecvb>9gS(!|znKY7vY0E_C&J11WYv0vO(BH~eTy)$NW@s?) zZ@{dIYHoTn_B=rG%OqtuiG-3%=kuA28cuu^<|(D(*?%~i`N8_aS9(Wz`U<T`V7KTL zspXVw7HvCWl&8ahuP;NHeBUTf%`*&#JzLZGStadzV0vka!WAtglgR~vo>*HGRf{vg zW@8wc)kWQoRv~@^WK`csPhVCQ$0-zesnHNcF^Kde(&fQ0($gL&|Mk!Z+UjtNhq}(h zX<;QI2GdC+KfyV`$8QI|J+*36&_6!!mISbYOV0et$uyT5IJtt)$`RP7!wIBOOA%;k z2(Ju~G-ahru9`}wQnqK&$z)1%%9nE7VHD%ZS7R}r0^PhT#?uqC{_u!5JMWK;`OAA| zX7()4%^^sEBEB8^z~fUVGi@=Rp!qp>5Da5}z**p2Qv!A;$uzxk(v%VdCtr3^kS9Ub z!rA+k&L~e`dF0rU3rCMfQJxNi?EhLAd8s?fQ>_){=_5Aibuj!+zF^tKA|*<?We(zy zOJ%hCB@N`0iDVv)^Hb1+l~$Cer*u7t^0XJ)`chYvr|Iq}PmdLgmL0WbTSZ*+fFy!= zFXI*mO-l!oz*g1)m_I$EJT14a{x_pMQAB#}Ux>d1&L9LDN5AMgOtgR5sQu-(;o)st zM@F{tvx9@P=zUBkDOzAM;+?}=w+@eN-8zEP>vereP^lEh*+fT6lk2wBb9Jw~+4&`3 zWjRie7+IG!UbSjn?F(5=L3>^t^qe<zo9uvNVV#IZ8?Oy^gLHewGIc>#BpF2^0&?VJ zk&z8W>x8VDv{j9k7_?6)@B+(nyr76S+7WLbk&$&E>|R;yhG?rQ)uv@NOOj-2pc4w( zb;W}Rd_$($@ea(?))}GLx@70VWH$is6I4->B$`Pw$(bRFr&Yr=y6_=O3_5rPK-R>3 zLYED_0~6zTHK-pZHeA>2hHELsf^N>JvZgDl>AH-;OA>OA=mhPokQkRhe=<EcpRY@d zq==Frc2ab19ef4crW=IEM&_1>yJ+@4QMe!N2ghq4CF;b^4QX}b&EaksZgX@{4=r7j zWo<x1ON)wuDAMYLYe>{3kZtf#6BI?zlff>rWN>JPaiY*kyA$ipu8@Y-TaxXD^{EuA zX~B@GN;G6>AF2~pLrmDV*c>yFjmE4Ut0mw=>v4d7o+s<^!t-dC1HI>X0nKfJzeOSw ztiWW2PACU6@IqT<HnxZCJaEedjk)DbaDf;!4)R#(3Dx5f47((=2PFEEsNj|#T}o@+ z?XQcae*Ah}EEV^r72tWI$SRtma+)=BvLBYZdAQgQPYY;G@5kWh>w>(PHi5MR3=)ba zCrSX1#3(R%j`xEcc)X%_^Z4ye@Kar*T)zo!uO!w3H`nC*iR6IW55%|t7;M7TNqyTl zM}0RX7M_kk(ghXm-q0+C<palnd@$8sngj;!o!x?>1CK~jEd4mLVqG#A=@uKJh{VQ@ zemD;0hi<gVkA=S29^M?b`w5jMVh2X&dq|h4*+;RMp?gS~{r?N(4AYkr%{zvoYnG-e zNZz2GEY(14(yI65OdCp_TF9|dU9xBIk0pK9C4zfGL8Pb=5pc4^!89N0M+AXH0!iC0 zk!pQ-0g_Dnek94XN!|HumzdhV!%<KeO989|S>Y6YVncZ)WOSr}2b@_quy(COFaD1B zCfHd<V8ur_Vzq9)s<u!&CzQ)VWmPDZ#liED74gln`Nmjv+u|>dHRi{L7PrxHD<WS1 zXy5vKVj<qxp)T8@tJPk%L%j9bKCN#oXX1c7*w13<gl9*8i=iFom3~<1vKHcS9E{70 z&bD*yc0#<p$v&;EBMjorez>P~(AhrU%Q}cdF^nZ=FE|2UyLGsI9GcrxjHa=Qq8W;6 zI4+|H`X%29&l5tzv3uJDaj5)0Fa@kT-taTX66m79$P$RxStYh0|B`hmZxb%Mv6j#E z)Bii6*|{10KMv_g-x(4t-K@ub;}Cu@iI^?g#|XJCYjVAZCDljmZ^z&O@Qr?uZLIOf zA$z*NuHOmT;(EINCg*RLo*#$h*>(-Tn}>F3`0bo@_U3qLAB@!d>-8J+SFs;XW{F)t zGOz6e=xrNn^F8?QM%sMmIBwY_Cys0KaUi$!)Zy1-&T$>S9h!xWscMrf`$Ow%?!Bb< zI+}YY7vH%KAK$Fj9*1^uLw&smbKgK;Z^!K5#+dD9_#bN1();2p($c#nz|xN?1DGB> z<k0%M`AtiNmTulD7j~_yHEdEZkAwd14K?!K!eU*Gyi;oIxoN4fp&oj%haT?AF+E&1 zCN`8MLROdCIO*CNF}L=wU`wnfD&%c{iDGFU-hxgJPebaT5^q52(f^K9_o37+&D3MD z)GAK>Dx@BdrOx0~RPXIQYd8^0MXlYyc~AZ=POY_IcoR}j^{nA^lnOIVh19<f{gR3( z3SVPm2_1JrygTiq$ZdZ5xGKvkdOv8BG|!1u<1>*@X44^gbO2o}J23Tb*Mb312BPBx z0G$AE{AGa6uM$LsJbVJdc$*Q#B1AC05kXknSYpN@yz$N<SCmCvlkBwZD{lVqd%7Sr zCv$F_8?)63B7#E$IQ|y<H3w_uHzgb6AiX@2%M7SyTGLHamNZ?K3|+7?PWo~L*{hLD z>b-Qu&vZCJyH@2wH+)G##&`<6q61&x_2gh2pnq@M2M;**Sc0TeBV{MSaJ)EVycVHn zczD=&-+RZ*yvps{{%+ssiJ8C0K56(|Wv#c&>kxTy+xwQN<F4YOTgZ4tOdVaMM8V1C zGyYFTfJD9i^>#<>+<+PZ6JY_}ClQTPV4-YMw8hc#CM$S8DY&+ub=>^mpqP_P19@+p z=|a(}K@ARCnRGTkG=%+_Ef4uI-`5LU3PAWb7+cu?rq(6L;+Q!GnBfd@${5{s`y;zf zMLxcOi4><Ol~v>g-aJl_3VR=UgU?`TziE%~K4|!*O4dtfN?G5r(_4H=mLxZaf|!Zs z{w_S+XJ(!BI#&Rz!ig@Fw8jkil8>R?^Nsz<`@s4TE7lUE;8}jgbq6YgQeHMqNm1m5 zE>Mx<dA4)FPWFI~0qA}Z^2kZ#9oM)?c@zimG0*ey|09Zo4h2fe(F+w%kin{wfcto| zJ8;Vf`f^TSR9<v%wwBKhl1yy=Z_eImdc1X9X;W%?yv4=msRYRzvOKJ!@Xsj}A_DYz zg#~54+uV>u$s<!7NAs*K&kd3I%%<20*<gRIor&FDx1Pazm85u?Bst`6rD+N}=?scR zCqOEHDFaL&-Np@IgT|%Ho$Cj~eIV)SSJ$S<Q4;hKrh)((oMl;E*f=31K~+*xV#+q{ zE_)04r1il;%ondx?{vnCgK&oAbaV%c#wAFZPoh)lqUd$Pfe>IiB9qErs!$4`K~=lP zqwgwTZx6mW5C;~?v?5EY;n<pLZkrGUyAy)33@y@*VY-%@5QWW-Ku@2)c*{q#vI{a> zVA1IVCfnKSk^TGOi6kcknD%U^hCBz_{n37QP|Q#8rZ0PpL%5`*G$lnbFw12W-`rw& zP1R_cjjqfQU{VR7ATyo7pJoAQQ6W<)26+fVo+QPwG}u^5!Vf3>1Oo{yN2fY5TJ6)X zDAq~LSuPIkixSKynB6=FJgF0)_l`@7TCa1wq>Xgaa=Nd5W|oTe84$EhU%q&I7Z86_ z%%Z>B?`-XHF#X39+<ubd$nMrgH)yTHS25n^J*drDLE!lOICQmFyPp&(mOYx_&dPEJ zUJL!!8soQC##?(|RU53Tc}|uSoh?lcmnSOBz@>WEihH&n*Y1VGCjouCx~BYNB=-<T zU3<;_)^9iTp^Ue<hXv}DSqA<H36fEa6v=8mWC0=-c^v*K%E&PRi43*ANjmM}ciAS8 zFo8njh+2ELtDzQAd&w^Q@}{iIc&i_`bj`M44)2su)CIA7icCfkK2!y<S!MGae_j91 zI1oQY0;8u$9$&qss|X5U`CVd9Ob$H7i%9MrR23aCfui$m7Mk^aLgUb!B@+S?!hsOt z`^cZe!c(P$fQ8URAb*q&Iw-9xgPW*nm%bbeN~J)Oyv}vDcv7S!dF+^?b+l7ke;=jy z4Wsc^pI0QFr}G?Gxl$4YKbI<k2BLRurHBkor&1D%>`V*j1V>WlSy9}q<m>6H+P1Qa z=9X#FY@xs~UESAsN|L4+%C`9_hV5vx-^zE~zcpw+-r&!KQx1l@YsQ_fqeYQXG~<-n zP3}&%JYwUmJXMq}h9ntFE_O}pV>4PZsm&bQEDoz}m!*bIt?|b0)D6{AxFktZKrM2L zO!0D;=0fk?du&V<4Q67(XU(y$)(86cFY>yLw|P0Qc%E7)s=nWa#);v4et4u<>}X-A z-z<#~7`u!$-qfdMJ4KNRTQ1SE$TCSzrjwmbo|@tLWNOFViU2y2!f#RzH9dRd%^lgf zWpZ)LbQk`(9lWsE?X|X!pCME2eH^D{oOJKBFH;>B3h3ovp@>rF_Bty_lIW3S3e+Zn ziJK_x5C;2deLY0hJ<HR>2Qf5O0zQc@0!3`Q6SkD_WF{p7*EW&0qNuVSM0RcWyXo(* z(9>e+24+uEM0SfL3%r8umQFbKA-hFUk=+6Ugt$4(tZTb;19LF2;6QjF!InfeoG5r* zm=RG7Es;$Yo~%%4conq+s^N9-P3>dF^l;>Dvt<@1c){+3Wgv@e8Pfn;h6>^%ZgzZn z+A}@Ir)kyD99T7-?bonXBg+)BYM4%+oUOz@;`a6YvI5Jd^rILy-Js5Zd80CM>qgf! zCe>}-bavt%E<y8xlBDUtxB(jpCM2!NGMNr<pPYbcNn_)t9m8Ym^sd*bscxvR22)X$ zL8b|ECurwOSdP_!m1v_KR5q}l-&nV;)7|v(mc`TA?j0Q#PkXzQn`pPg>gjI%5Vn0p zKCped_|HRt_YWi6=RkrxE_a?=7+eQ}Hv6Z$-HR<NsIyIfxI9^*^H0uNoinMhPJ8QM z_<pmH?ndtEmOT`2V{Sd~wO%$+%p~e=dKzsgNh~AqvY230ohBJg?&7XAP?juBz+Xif zJr05()SB9T1UCa$tv@LH!0Hl^d4}k`7X(1t&^Bs0+2s>=(;ji%?LXUPD|G@<Hf;x; z>o<c1scwG0u9vQ}j=9tg%@a+d2_#KuGzneagO=8`nPd&wOkk#TKsAbE4ff?eq1{yP zZ8&wqbxYHHLTi{@AK`Zt%%@~Bg;y~rC{4zIwbM&wL#-g9-X0<^2}X(tv?AziXVV9y zmK_yuZ#^umYfJSwxdIlIzzlGpaY&&2aBQl8EUHdONRg)LBrOUIFNPMCBruYAGxE2m zRn-mAZm?!rwpAw}RA5^rEo56U9j&i-j;Pzd>TdeU(8>Zz?V7c>w5@Aw{!CfRQ0Q*& zftJ11*&GwMw>Hb00-Gy5wisAkJ*XbrT}m<`DH4@HR#(?C7zV7aeLC1&yh7Wf$2uS= zttS~;c2|#MBcb)Br2Q`RmWBofh63wrv-H&CtYo8yM0!@XlN3qoaw#QCEKTteo$PX7 z2SY5O&jf~;%HM=6WSZ7kkEtElWL^B94{WjoQCPb{+>g&qGQr773f{LG#)M(qSR+Vc zjfkR3?~g^54kDZ-aGd0)!Z^u&qa=4nM(zxVjPLS3Kui;lbjC_+mOT?jW5T!p5T}Tj ziAOOs(D9dFdF7NHq#uFw_r%hVjN&L1YrjLBCh$EZPD!hsw(U8x0qG4$Ki5h>H#UaS zDX8ZTsOMty&OoS(3EwYQt6PVLwhay4VWAg+b4RWA&wXSRz0jDpU}@&I!Z*N$UY|Mh zJ9qrfnIN8D1YcKPfEB%>yvYujm3BBVEUr7|dE@wh06c)7?0|lQazQsnkxty+52YQt zSZ{3mTidVWe@K$H_ozpyuwP?ity01Gp}sY5r+9hEK6A(Q*ILis)BfzpwJ#9i__mju zA3GnGYjl-^XF<8OAL72@azT9k)Aru8bJwlbv-fm7yEYm<I~Ol^ZfxN~tlYVHIsEKe zK%aQ*)&f{iaH5yb*h_c3c0G7@r2E;CFI>ZY=qh)9Y(6a4=qd-#f^wKvPPd*xAI|Qz z@35{%bExatk<n(kbMa^AE-Z}2%5^;p%7tUJ7TxEdA!wFt=;C#<aebZVN3M~LYt6A* z!x14$(M>v#LxA31zaI9tBM%Pp1Y;_oW?sAAmM7lM{1~bvfMcC@j$FGI;=F%5Kt0#4 zt=CT2pOA*u!l*d`mhHWJZ6KBF#Cp%Kh2s#;q8OZjZ^7ORqj5b}N0`TH-kc3Ix7QX> zGi`Zd?Ldx&vAOO#I@<w!bivZq4rIBuZac9$&^(RZ_W@Yn`wHqz>-l@S#%1qW7~5;3 zLZ3WAEqj3*T({ctbhd*!(+`gMv4subfE*X*H-H23ESz5#4%AK)j&NQxt;nP=zp@ty zIU2WcZnx9m(pi*67`@h=CmNTR&j1xI9TBYS*W!6P+c^@ATQ4{kV7{yi$NUA9Wqml# z!|2bi4+qK+qaXBKh~qS%0MzB{ae7`a-?a#)b@QQNx_)gl`L1mY-vVY)8^AY@rpwZ% z^7X7w3i8Es3PIDtwaz|E%{p693V1ZGT@yO`Ew#5FK`LNshwOdxHlY;)bPAin)5iD= z@U*FX7*89GcaU%6@s9EZ?V|fM_dvd9L!CL)TtM4=<&}%}E}Ovd^?nEVNTBCn-I9X$ zMcW?3s^{C^12wZL_nvLd9~3_g=`Tx5d#=1?;~2tYAx~=Z6WrDW=v9vaAs}5Q5$1Uo zWUmmb3FSLuKQ>`6U3~4WT~}g~<=Ggw4m6m(pu=3TEj!9{F=#Qo?F;e%?Dpj2bJsB^ zOoVyD7K56YFyGn7$Lz_ybFbNNU9qwLvL`nG!wcz=4g-CJ96=vLKGV#DvHln|IRV-X zqIKwFSWl{{35WM10lp?4v(H?-er4BNuLay>50;)`ZS_ctfjPSex_BkxY!_pBaGMt& zpM)k6bGsgm^2K<Ib#x#I{_fs8X^%aA*1l-NAiWmTUxb#t4@VMr^9tEO9gW6mEz;(L zoDBR$<2i8#+D3}VYsdy^=1l>Nk)Dk6I+2!(3Y<Zsd;Q8=WaBLu;Fjhf#K$)rVbCA0 z1pSZ357DO((Pxko)9B=6K&40xpqhDOkko5Nvkb-tF0~gBf=K)A@4?6?!rAm}&_*Mo z$zY}+sS9)E$`v~<cZC>@M^rwEq%WpADpq3)Cm0({R4<_83<d<~{dxdJNH<J-obP%d z>ClY5a%Gntmv%y&CXghW#Ds{*;(B23wJ0$*G7){?kpY~Xfw}<%L?dzDV#Ih$E9!V4 zQ;<|a^n!;em>b>YT6_sZhjA1@i18FanQWFrP-@sZZ-X<2wFuq_cLC4={?Pn2iJuR3 zq9VGMe75%U*&(}LxnnppSP$@KVrvQW!XUWPX?rMJshgQ$tKPCVzJzmx(Uwln4rYhG zG+4KWGm!=K^I;BjQ>tm#e!fzNTJES1W`=|Nt{mdi#IHwp3Vr%H^|@bqPI<1!6ZJW@ zqCBU>o(T9!5E#DUFrQWz7uD_C@!yKFxTq{{M}N16knYA-G{)ENy?gIyjl$aBqjVI} znR;ceT5XMv9ZNrQq?NuHOMmjoR{FVE`b#gh(w~c^fBW05^e@EH|N5_6>EFlcT1|s= zQhoa$;`9=G0uwTNaxL~`rR~WRu_u??p4=OIa<1*k;n<Vg+MX=Lo-DRKsl=WPw>>dp zPwemsAbIUA;?tziTrn{4jSB-r3EyHgNz}m7-Ae3$Ik}Ixg}9YCPMjjn688X(A0!?o z-Ua=7inv0&pLmA&0P!K>!^B64PZEG~17=+#e3xS1t9{b@<+<7Xo5|yQUd{L6|5f~V z#`6yU|DQq%e)C28?Jp9Y?MZi~_RK|~D35Dj$79xSj0i&u6`6XUH!wGJKMe!#&3u0P zum^o<y=J_c=X-~`-lXvM7f}pU^!Cyo{^rjFDflmRp!vP|!hGTT(X6WCdH8)i|A}j@ z+2#P<UW@1!-Q_q8lIoL~lR!_Oz4*zC7lXS)qjV;C0=&5P?8OJpo`nqDo%pWBRt}++ zr;2NVeD(y+xp#aV?fkdrR-#*FBFseZXD?pl&jzpIi=L{Y|BB+PYQH+dRvWSRvr$1@ z76TEy2z>KqXC3|KX%oIu?Csp-Z`2=!S2_51w$CT-XYgu$QNouWrJy_bTCk&=a%4h> z6t4-VQ?CZ^s)ep+MQ_x)B>DE#cKgVQ9rBj6BoAM7<SlmkguUZVc*8eY-k|1^)hIE+ zyUx_myH;nQ=2KxkXK%N+PuadSe36sow7q4AJ!hYQPpBB`h}SGY%?7R+-GDPlj1UvV zG*Kt!h;76!Vj1S#ZNL{#f^54JIAhql!&FO*Q*C`Zbp~~>UWH%5+j5-nM<aNKzr~-` z(8F5uX{pN8s;CbtL(zPK7ZjRe(5K8KZ=-Hcp5+C>74Vzi1)m<gcR>0)e2&AjZ32(d z`Gk-DY=<W&lGM&5H9}E<g(S`Mf))Pd8H!>Qs5*Q>D@^#6r74P5L=mNhk7z;Uc~KA; zREkOB7n-FGF$<F6Wtf+MmBurV%+6kb@2yn4n%RJ!!J|s0I(y;H{rd?Vt#gD}AwGf2 zG4+)T_s%{7-&?6EoDLMTa^ctkcsN@*gj*{^z0U=us?W^MK6l{)f!mAHak;8fa^T^e zhpX_MJAm3#q2{N;_NtAi9(-_Qb{3UvrKj){rp~}aem^|E^H7Dr`znLP2SMV6+R+EM zZryq>ywToG^GS3UBa9__K0ZD%f%0sfn3zERfU$f+D`!+2%8f#xM<qZZbz*!j*cpl) zxpQJ}a)+IK-a&6Y?Hfiq{mI~$lRuwEKjBRz+iD7Y6Jn>qs`2A{ebSq)pej*If~E<A zstPR6vp_V%U9BEa@pC~P2Z}*dBg8nm(0=mEj!NGfHbb=aUT@DG_P$xDf#8WsI=IK3 zrQ^M-x1$Z9Z355TiA%TOOkggK1P{@X>Xht@D7ihA358Tg4b>nOQJ717ocPsnMEl`7 zH!_k#Z@*mjy}>~@_>~*ER`yYnU&i+r|1<I5u!kwSwW(TbI5oz(y5#S?&G&EH;Z-J& zOddKkc?93p8|5_Od8-ZsG}r)k(<=4C7`m}(ykQto`6mjEVzE(ZGzj32!03s8AXeAa z9HCeE)?U=BQmI-&SB2EDlTi)b;ma`S4s3KoS*_%t3m+H;T}~4I?)N<{jBOWpj0)8x z#Tlel{)Mtenk<#9IpZp+Y*$FlCuK5Wl3ETPFKY>X+9j=ml`wBL64rc%^aj0zbH+({ zR~g&)ZARiL={=_T9x2I5z9fwyapr39%AhU1EZ)~sWBo<_T*UG84}ivglsEx$;4b1m z;ym$A;!(sky8Bs*;i1|<-yEkljSn}Yv94h}Fz^TXJp;W&*X!0C28HR5e)swQjbwr| z11zX4ok&(g?EG3XY20p7NuR53<F{4W6V7!0`TSmmRQG74QUwgDfHqGfjYE1u8@EU| zV<xPVR>G)xWM%-cb3b6|szj%RE4qF~NHS7@t&}LsV$v{8BWVbN@dVF5!D0=7K`3)u zC_{Jg0&V;S@i8Jx%z*6NPV6U+0j7w?WCFQMmWtJCy@8on4Ihlzk*HbKhV59$LArTi z4#S|k#z8(-QG9tIQ&iA_>Cyfz{Q5o8Bzd0|L?P+Yc3NYOa$a79ME56M)z73TO?NFx zq-E-HN&1rLrTJ1yl6a1$Sy@j?Qi@4Yw1mD<B$cF+Qi-D^oleX$P$w-qLXv%ahilU* zTB8}$a6FpPlZjLzu|IKuro~~7p~M8ou?c}>S(ao;ga-xi@PBpS;Vj<yA4p*Lw`uG^ z>R1fEj<;A<5{=o00|Zh<#1ycD8jgMe>H=bUpk*-FHv-+!-T9576&HFe<~{Bxqor-y zO#(hxpNGV<ueu^7)1qX#x<;ikB}w{OPdvyErBs=vX^xlFq$1H2AOgNg65t>ymmX)6 zf&={*SY|ds>k`FnrENErNa_sjIflsqI*Nb;1#n<;TtcJ-jw6Kxk8wZ(=LzCizZu@= zh0Kyl>)3Q~Q(WBt?Wsb+a<iVB8_Va7QC(HhWhQ!FPg5Dk%jLWYHm&EMK?hZJ9pATz z?r-=C%+K)r0BB*B-SWk)gAx#{{eA2xpEli`>t)9?{81E13RS;4BIqMj*7mYlZ;~0& zg*!BKYF;<O`#}DX_&UCWA@sbe1`d<;P!P{v6&H9*S0#JNmQ>y1=fAEtOu?{(a!S)u zWx+B8vk}}B^)JMKA-)D$ehKWH$gL~n{xlO^P!+;!UzK<1X*Z+m8JMIy6n2|#8=h%; zhOKR9&0R&u%eZdFbBenX!eYTNoLtT^jQox!)NkN3BX$p<TSwPFJ8YT?0$r9(bC|MC z)4rN4TV@2jX_b>KuUnSR<JDt=_!E#LE<SbK2OpsNMqvsnRXGv5(KFUnX<l(nQM8ZP zqG&qO!l<pOsv*pA+?-&js%C%Fm~v&yVJzBlXp3<y$({ZTOOGkK#+x%dKV$Nmu8h(6 zj)xXDyK&i$x^`p{&3=3X@UyrfhL~n|s-4IDQLp~ZFn}pQp9IOWhZ3%ByDIcc(?^o{ z4((ALe%Q}2W$2fU`ej4E$_&dIu4}N*aHw~BkrD*OFcd+ciaP2czRT7I+Wv1acNU0K z=w>l!5``K-3;_Y?gbB9Onb0Kv<^yyuTcw0QiVXf}sv7rl5~V1lWU`7x`AJfeSV)<h zT3DFcNs98RWRj;7tOfQ5lQ0A@M;LN?bb5O9->Ql*F0vd+vBH?74^WN{pD^#qBnJ;< zhf*bROyu|!3b!FTsT7Nn-Kzo(EP@qyj^sFzPDx;uap;DC`=Gb4;5ZK0H!AGIM@2)C zlx<f&s++P<3?k77Hx61jADZk89++xW<Y|$b$|U7%%8(^>+ZAcp^pq5|l98VbDoGH7 z_|}(Ie0O=%PpSd-aPuoj+j{8@R733+Q<jwJ`%m6-OBt7^cAgGCuMFEz*QvFCC4QZ_ z0dS++Mxr<c(1Y2CT+WGE)tnj@ova{8+DXqc(qqZrev2wPl5E=n7hA(zEWFnhs1Utt z7JdVfp?9ec?*=?MkJg8{G8cYu<#I`Kr4h-IO9Og2FT3)v>`9{)eQ1|9qN7`i*8T=` z7Cm<J=6)C?K1t~b#lpAgp}U$60uRM2%YhI4L3HW>G<yNTw*_iA2pSK*NiNC}-uHJ9 z-K|Om6+$6lPf#h83Ti!pC1JCa6|Wz?P?^JFJ0&P_C-E-qr{DL^zMy<Pr6pMqTS-M! z6k1QEP+;u=iWOxP>;<1lVnw7IIbq!aG#8_N6m&ChP}34esR;zhz^xZ>UXqwt`>!CY zgWbaBxvjmDZHdmsTxBrp4-L2HYMtrYDp{7~xY@yKHa$E9xrQOvDae(DT<hM_aFAwX z93EVf8Cus#bfQD>7)E3mWZ=`Zr-E{#5bbrYe;dQB2KtI5qgrK&p<M-PP`$32QJteu z=ZRqd!NIpOTF!})kxa&QPPwXlQ0dHrZlD9zWi*o+8R3+Jvg)34urDL<R<!TAsXK~K zr)-xNXbavZ=zlgNFgC-}=2kmt?{S4Zyabmoz>9ZX<jZHlOt}mc@*~{MJ1R=DEIDb0 zl9QsPNs6JV1r6QfQ_iX!FE7gY(5)h6SV@y?NmhU*3p@>?nVZX@Yu*6^8L)UBAfD`T zQ|>-0m&oXnB+7awk)@u@aZ18v(`nXCC|nL<FAE&v99Rt<H{~v5vqCN>Y!Toy8|2#p z`L;z~qS@swf)J$ZkbZaU-pq5$%X4#jo*9(VZfB0*R?KXpvAmpf)6yV=E$S@jVdub3 zYr9!9yS%)-QxFCOWS<Yh_?->+ZUCFp!_x3YwB||?d9Whyg}!?rH%o2zLt~C<O$WC_ z$1jK8%WJ$W`981kDNaZa0+V7vuaKAmYgm*lr-US#=QOL9NeF_ONr)WS$0&l;(=f(A z=B?1I7_4K7#T1QSsf9&hQAR1~NfD)>Cx^B0B}(W#gEW5eVrLS<9KH4r#CwT{L3e1h z-}8Ahw|pLD6hYEuiBCY&jAOVN$5u62Pv=S*H>>axz{K+mqmUU{krjg~v$U*$%IZ5V zBha~Yb};AZ=1f8odCq~+qKQjDk#7W}#Z<GplzC%kY7yW?_gEdn@vF41*i}IE$5ee{ zQd5g$k~Z#hUHQO1PY_u?2e=o3Q(hvzlc?akA!*{Ze<jw|K-(gKZcysSgVgV%IA}8D zy@ped1*rr|wIKDUaO&wGm29Q{S(sV@%NafUY+|zc?C(0BJ*tiLefApB|Jk1ZF#`Pu zO#;ShCAJ>e05fxZ+*v7=R!Rt>67dp@=<5l90>ixpe%}vp)5xN4`@IMMF0K71;^DQw zNiaD7cBoe(Sb*f$o2zPD+xJMTF+y;9UAfzl{u;f!k6vD;_bt=QV4JdZie)S46W(`) zpOr9OrVk&cj~r%>9AOS;@e_ED!Xu7L1wYW|So8$(2N`(RQJ@wbOV_sJEFe2}F(B_% zDZ#0-^uP>A40-f8FRIEcU~qEn2JuIr<pg)(1Tnzk0o#JP&?o(8S%w!Z3+S2^1h6d* zpw&Rj;#iguMAH(!sZ+A@8QV_ilp=q|cBqcuIBMMu;xT9+t;$bg=wt0+i;rn*7F(H^ z1u=*j)uDA7wW?Z{iXcG?ma1ujlB7RT3R^5BeO2?4Lt(=e_^JBJENd7O=np`#h$93( z)AQ^^AFuu9oys#&5V{AWl*dEY{YN_8_}6dA>C@_+T@BPaTjDxeB$_uvKXa2eLqFbC zQ?di*$<0CStlNVJ`y!3&gFKj}=w7KeU|!S2ee=O8GC}+kzSGlgzdN^izvyh^^lr=A zZQDQXEjo+tV2Vz%QtG2A3H|xC)zwRyr+ZK{yY{=lQRaXjJWl)+{HEde5n=&;Ka77T z@oql){RnU+;K6I(1HL#H@L*?M9z4*_gH_;bD27{wcqfTCTIEi}e?UC|n-{0bD0TQD ztP>G;5&s?c&j@zKtnkL-$T!6*Ir!JB)k0xtu5pi=JCwURG^c*fk~7koGlyh(hja$V zy2SUH{sq)uo<{Zm+N=uovjEE%@$I8Bw)>GT7o5*S5#yYV12<kjZ(ca9>0~M?av!tN zjbmUuV$muHEYjFjL)BMTS1<08Wje`;=V?>Z7!8F8MQRtYB~emE9KA9HuzVHABlNND z-ZMsA4S~1`xDM^}Rm2G-Uey(y*Yqt%FBs=N1fitKVjG0IrXP^A8VVUJh_Wj4VBFum zy807+Kn-qd{9^Zg&0jn}G<3dFX;N2nHDWdJgNo;^f<^i#pDUH%|3bZ4BK6Ua64-Z( zApSWlWptNAySxAVcZCA{-@3)A#Y;nZ6mb>Ge-Fyj#QYqZC7|SlRD^D?Yu06zs?D2q zYoEiDWcS@HMW+T~s%-a~^-4>==Bt;`t+WZGTM|FOcR}0Hoqdh4HUuSuOzp;$<I~B( z7hLxz9Ao^c{OUu#^HOWl=|L|+uOZMq?keccZctZuO;)WwG3w;=ugda=C2{ziGwH0p z)Ls|rbifJz5%<w)$Cwkl>o;TtpYq2h-1)jUGVHc+FWq|Uy{DF!PXYd-Tf1pu>jLVt z(!`(Bfxp;Ex?i>JJ@EhDx;rxL)#u%bF~3zeuKC_uZ$<s)L!KpL4*;SORuuvnY#&3{ z|H*YfT*!Ol!+tvJ*y+-f`Bhxi!Grgn+O_M~;OoI7xaa>X?lh&)?UKY_<60aXajG9r zZ`O&iQ2Wj3hSRg~2h1s&*<G9;``&0_ZYgSo>1gddd?J}*;{BIzhcab;b268S8jk&S ztPe;1+ZBEJ>FCQ_1!rOe|1Wj|6n%azfGK(hcKFTQOnEamNm7_n|2`bALcbAnT48yZ zTOu5L`f%pf%!3F9lEgrCj-=j%io$nj|KmpOFtG!g{}Hu<-mWp6y)|=b-U<5ZuG0*R zBWU2n|JxkL+B&)cYRd}xRBIbY$NJx*wilw#erepw@MMC`SmWciQYoobr*i<mwsJB@ zi|)yl)&NpU2+{v+LbRtpWig%51sLz3u7Dl=j|jpo5ot|FDfbUq4nqN~&QzK&q=kZT zUE<1p$!+DRs|mTIF@gj56YoK@&<Du>>qcW1r?Fd`Gg}|d-j;dim_LyB#wPt@!S5Wj znLV}Ip5+GitG^9o?XQEZ^@2NJq1MpQx1CmioYy5yo1D~inE|n<>$)~=GM>lm*a`YL zNt@`dY_EBP`5Q#0b*C*pH;&ea>a%t1u!ef@RaRGJ87jQ%eV*r~9ryD(r>JG!cX`X8 zbG|-gdBNSG1>#MxW>UdAM5+F!ao+=brtrFB>kd<V7B|p^o<ci1H|}4&FMe;k9o(cG zW@)(-<6GS4E0dFxF1!cl(r50vS2MLj0sh>J{Z?)ee@6Uq<lp*dZ@zg$L-mfpnEXfL z>EQlX(7MpZZ?Rg%A(&>-+9z}D*=Mz6l1h!z^k|AoCihE420p4__tRB)z(6e=!2cAq zU<Z9eyMti`PFUlzSY)YWs+xjg)fANa^q>BzhMaLm83tF|0SoF9+HVaiV8R+-?|@}% z1PfH#0~QA@MhCsX8<t^>3u1|h!@^qM|9)GwXs-rf`3ryrN73$q6{Z(>Z@gQlpkiE2 zlA`qXpIbZdR_qV^FoL}Y7OOqG(}CGiXYW4WhG^~coqb(c`=7w)KZrdo(CQ#w01C`i z)VaIg!M;<3oFv7tr8FZv@=o?0Wr21p?ElBvdjLs5w!gs1T~&+Y-`@MZ-!{F^?Cj3A z+1c4mHoNJCR6+tF34{`)hzbJw7ev8lMJ!lQ0`e5GA^P;G6hS~N#3xU&M$u;hJ2eWH z&wG;pz4!Z_+1Zj1f6LBnnEBpw&OP_sQ|>+YTnT-)00Le~Agh_tA}0p+Y1~2+lSK)s z6P9Ps#t;z^G$%==grLrYfEOZS<S{AjTL=w2M>C>SN(!1!XizF}Aq{w?055aK$SW-Z zYbR<@R)u6q5*g&xv$-A;Mu6HQefaM4>f+*urSePS8?RJ)8K_+O#+9mW;i?p!vE&3> zL$kUAF{)2>oHEodB1Kpf{j+;<s9Wcv+<LMo?nQ<(LK+DaCs+%Jz{SR}erX`@?*~YG zM7tp*ghUZXWc`1z-di8K8@yAX$gsS7=UsPAPHvtAvZYNDtwkZNMPh>XY?5wq?P<Gq zop$M^?g}{J690LM-1L4Y(r#LGgMASvvta~NZ=DDxUcMuXB2@8C<5Qm!_nArPcWzt1 zmqckKLc15mTz5v^_)4Vj?x)^>>_#bCxvb8vUUmwLh+eZfyH0r@D+Z?R+R(Lp)A9vg zWH?jTO<_#4WL;CNF(#GtY}-#IX^X~bYr3N7n2HhP2Y;9PIFTC{UxDHl5o9;U_ubVq z;x*UE%T}*!3=I!_91MYBr>{_`&u`hn<;q*lC}tyqJF<G2e9blD^qN)u!$S?z8AfgE zg#tO#Fo=5oeZnm&T2vo&-gD=zI0kFP-w4=0BZ_{IeknZn9p)!*C6*$GG{l+nt2S%_ zV31sU-KpBpMo(>+y%W3Lxf6Q@vIF;1ABa}ladM8hqNPv4MqlyLOK~>u+$W;dhMj#4 zIHk8fuy^mJm*OYJ&<H<FeL7mB?J1N*=KI4Sn@DCrf4)%HR+rGv>NWM@p@I4BnzIE_ zVpjlUl8G$hPrm=tYf8mpY0aAcp`re$-6(4J22z8{@2pCr5ISaawI}^18nfNBg0Dxi zB-PR^*E1P>nU$z25`ebry}`x<A83|>rGfm9WNJh-u%|MH{P%}Zyk17LwsE`|#dueu zi&=5hg_yZZFTM0GOIK9Q*G<)PY|o0ZCve52D*))jyO3Nw=e`uj$=P}SQjDv2t?MP7 zrKTK0(fRjB<0YmQjxz>8rCUXVMes8S{%oFk3=zN9UW$L-2tX74I!^R7rsi959&=|O zr_<oeSa5Kg)l*22h6ab?UMy@E?e4f8L{Y0tcMT39>6%JL%^0eHeA{18H=$N~7gw~o z=fD4wOZM*FfZzNG7mWVIt$x{U6=AAIe_o0aZP>f_l1us{R51F3TCJrdMB#0S%MRHa zb4Ag2Nx+JnQL!z4Qp?nwCCj1hSC-plC39QGf^Z-W^TTbZ=lk{~ENUSXgc9%Yv<MY# zQEY$GtF5waEm;N=(?Hb<w~a%+SWD^98A`$Y(At#Ut4r)i3q^@kvr33erPX*!eB9~G zu)g{2T0P4~u?p(8tD9toA>EblC;Q`QbiPa7f!eu?VZ=k!!8$P5XzafE4uCH$0M$&c zat9fyxeylM#t=IA8;!yKH8=MIeD49M<TBNMvWJh?1|KI@iHeU7yXoD|ZgA_Z7=A|+ za`AbIY8ypY-@lc9?-iHdd8hsHTd$c@{m?>GBo@q-N~P)|`zSX3@$q)C=z0EZ;U&n{ z(oVXMS?{E3-1^;IE!C-&Q%Lu*8#b`@)TwMWm8!C9|AiVvJ)d_mfsuTE1iw~x?{(-@ z<tYpg7xKfy`FO745ykt5zoo7vk{m%UM!NO;7zDrotGF3%j&t@T#HYW{$!{Gas}9J6 zA#nk+^yEeMwaMN#zGwk+vw}V**{VKz)JK2(B6@SBBA*GZ(CkOA0V6bnG+(ILfivLv z;6%~niwUl{FXW4(MLt*|*fM>tWQl7~oH0dy&_D2j##8c68{(f6$~A5vCmg|+>1)&l z)DIbv#8yw>y}%=nAv;wewNb=Mwe4*%Va_bsdM?n?WC!zcY9s1Zv_jRpYudAgDL~VJ z&@iE;;yn^kQhEIU_$A@BPzC3KZKi5Sqh2?g^Nw#0`BD+269tgEc0YFxzn|Yva<u+J z{WtPtFg`)7j^p$bY@|dlA`m$=J1yw+1&$<NSS`4&(HND1Gwxg+1o}uzb8K5#k<fII zbsbTzj!;B9iAbk?K0b{ZK_alRN%5oLQvAh?EZK^LJOx97fo5AXTV;t?+z*fABmkv0 zVB79U(wST%>jOCd|Hz-IXQ_uG&iF^k$-Zi6#fl;Ps*bm6)$ws-W}ts&rhj1O>#b60 zY^+pjp&nm#<SEqOhodn-uDAGgv(++3HSrY}iRYv5r_lFTMc)(OzI_$?cGTSa3h})2 zMMMd1{~PkX+JO+g|HeQVM;!u9l`yn($vbM3?7~z#Q2id*?zq`(A`H^G=ZhDScT6X> zw?k)i(*5fVfA!s`T|{+h+#A=}L8|1c)eRpwr(y2n&wtd#6`g-=q3F5wqvGgJs|9XY zc2N;*!~4(uT_|b?4mqvlUbVB(v_Jtgr}k}~0x{1XK`^E0Ig$tb$hK{xqu`fv|J0HO zrfE3tWAqG8wn1c}N45c}v1F>B<jd92JopLmfajf*{>kS)x7pkLxm(;5UiLClZ>x!< z=V9uTb1M%#d;|KqtoeZ^MQD1Gx(_`gl2K?OhPwC3t(IJ6?bIhzHoTskSAUYw6wiSc zV*6F-iK^U^@DtEZQSpfWh){0#^sh=bC=mmHv~y=Z@8JvShQKeC{-sO$IeXF%ChP~h zJe+MC^&7D<+VQ*!HQi|qDVC)GrGLrNe&u@)+7p34X`{9uqYhC2q<$J(@gkaTO;3#e z{L{7sI^?R3DKa5<pct}=GJZp?Sk!8Fw-rh7YDO7@&E0}!%Un1V{rPcNEGJm}hFcx^ zC2EzKZB@nhrIJ6pB`#z{Gb^(pBUqV28nvkg=nZrERY(3rT|<34@~qwBt04ULuQAWI zBF=t}d>*gh;B%cfLAV(`@XN1#2z!=C{zzn|<8}3%{k#{#w?eoI!iOLK?tgydJs6LB z<Z0y5JV@f<rqH7^A|>=iUk@`WJ)IiZtZpmx^~;UA_u!^}&v$&c4S+k8@|_@A#FQ;P z@=r8x?v5)33gX<lzc>XG=`?XxX?$I;l*@@kVJH>qW>{562cQjH<3DQ&uMiY-emY}7 zd~cp08DV*65SqXR28i}!c2R#pGRl)IG(s{qI9C{AAn3b(_q$KRKnmeF@eXz5U;l-A zfIO@BK8^SNE;mJ2G*Jt1&pi*oPz+I@#sKmJO!VJj>R{Z;p5G4teXTCKf_~~_k9q&` zAJz|lc+hr5&mKmTw+1j@Q^=10k@^P7L&K`Q!`dF+VmYXe??Vy!=~A;iCCoIq{;WQd zfQD^?KIKFtyqRx^mcD8@&ADuu3shhNKdGibxdALak9s$RX2JK6TsF|WU54gC1?PKK zg_!SSX#OH!3o&2B_N9nZWKmq(_M=SLs)&<j5m9j#*uT-@@|;z-4KPgCOhaQ_rtQ*j zDXqvXOVchrROkb=8ZtDK6a@)zHkbG1zA7}To~A;E4cLHT04vE1&GG`n>NP*Li?J-h zOewbIKtYab4nB+gj)$lL6mLx(h33&VCK~;c3!i&PE}#KJB)3`-$!}))t^Hu!xBMA; zTyqtj_1M$tGih8Km!>^-S$)v3SXgB1x~N*J$~OvXdn^QFp<{UrEqZj4aaq~H%QHM9 znax!3A})~+Dt69x^RgLbcs@^k2hBw@veglpoit|@pNyfwbT5NYwK<O!7+$~7hn`y< ztqz2JT(*!*7KdnkSxa295<^QMx%eG*5Aq`u3!se?a9B7z_oX0dJ6yoaJgW=W1*YPu z*7Vv|t5p(e{k6VKu#8svcBh5RzCHwX2Fbx!sT+{I63dT4Akmt)`};Y*IKm7U#KDwi z2g5=mpGefMfimy1pK^sDX=$cwhC#kU^6`I5{Tjto$AtHJzOt6x*j6`<xbD~*aqUFD zxa>|>mOSx)Jf)oW+`tR+*~%!<)=wi%{~-i#umjJJ*38DRPlBdI6>pfM=$EXfiBZ}O z$scRq%q7Oz(tZFu2T7t|wCW?Y>y_x-jG&8rnKp3Nv>;plb)Lk#^ru)0ML}@D7#m_Z zhVfX=qy?7C(~@a80>>h1f+L5i-y;d+$$Hr=HBquCP6O{D2uWT{PBh{l<I*eXi3?rm zLP-#HC9K-b6?7_Bqk}zyEsfE(B<YgwB=2@5!DYU~%4R}EPPac|POqkUG)s8Skk~O= z0gkT{disw%gSc}8HB4$n<4nO02jDE%XA`iC(G0<P)a@b~m`He9KeDvIPSUcJ%}*(5 z$8|+nQ{8L}CUjerJZRBI;k>-9@n=~UG#MJwNm$jOXehc)*Ks~i!3@x($meLrN=zw0 z(8!vek37}iBU$KD=Xa?S#Ol$gt77V^v()|G1O*!AX;rQESF6%YCZnjjku0t(`L=GD zw4VjE(f7Im*B0Mk2T8~<S*DN-3cQE(7GNfQE9=#rqDRxUD$UYXZjB!5j!8!IY3gr? zz5@1g{IM#=PN<5;F>-*>%<7hLCIfyd?duXND<(`O+(hX4oY5zVo^JX91om59kONu8 zP(?M}HdXqxmOQ?VVLgURCWMCXZ5ZC6EFaQ_@hS?&e}wumlBODx?y>HCIbKR4fB%TC z8k%*}F{!#jS54j0JdkyApO<|@Hotca3jY&7VO<i_NmCAz`d=f@VYm|;ERvP!Bh!S_ zqucR2q7J*+?O!j0wpOSn6RAwg$yDm~ay9g5z;AAhEis$LT-}6>y_Q{OtiOoQBI{+K zz6b#q23|^|15xz&0GY6a%%=pG4@7bY$YB&s{*3s*Q(d0L4EYzS`@61Lnyr#|?YJqu zQ}%Sl%qi&IIPtis#{T~wsQan!;uRP?Y{XF|p&RyYy!#>8V#tNIVe%USd7Wsd)*CXf zrH2h$n1(DZt-$sV!-(W1Ag7SJJ)Z|H`r?Rz<)Sqg@+u+-kqCTeA(pqxo*CJ$?2#u> z{QFJh#pI%MGKgwyZwjJM&W0dHMkR%jgFfD#mKdLrzAhE$wmm{uy)X+6NCz}@zc#vh zDrBaeO=D}AiK(2O7#U}1pQcCY5t>1B0ON`Jgm+#C=8k9e#qb_66ic@y^8T@-((pwE zn2J@9@w;|RdKjv5<o~Egsn4M30H011<GRWIJmdZFDW$x(q(5(rCZ_A2<K#xY*7Ypw zGt8%j(08(ir)xUN-^1|!PW_zp50brtp8knPga3C8$)hc5ST5}y7*{QC_u#r)aSg>R zVhJ>Bi{PcH^pU?&k0W2cx?s+V^JWF|@d-EEkFQR-W@0dv%obCFY=5p^ua*4-?V2Sp z!YtR2&+c!&P8jtJ&$2X!^VziTWpz4CF&<r(2k_j)SP#c@bL^ONQ|!r9m`lcCtj`P` zznk77B*|HME=_mKuBI4C{H~ABr%&R02t<6DIr3NP56FUBSgJeMj7I6^?LX*4wL*~# zguu^Km7T46HXC04Uf`7n@a&6PK1^zoq-L%EJQ!8-@nf29s}7h0PsX2t+Z0z*jq`h8 zFIQcpM@Yp4G#8#l7;@1(aAP~!uJ-T>A7UbhV%ohq^3QIU3j^v>iMDKzO1gr{y!utN z$DDM)R5i=cHS>D9qQOeT_N*FhCjm(DNa1^ot7|U3L$UA$r6##+`w8l~c>D%BR(o~? z{{@Pk!$te?<*|lpm0paxdlXkyw1B*~j)zj3GSFxoM*0cwev46s^R|!p-x3iOv&x?= zb2r6yi(FcKc$7vouqir)#NtFo@N!{2+1E<ZqfMj(PW0)~%b6OqS)UX20<%1nMc(Ja z@^YkD#+pnzne%BZ2^ja0m`mgHc@)z^gyERP9MM!qbI=?|Qek!oOVUT9>>kBIQ=)+1 z&6O`sCAQknQ%_T0BN_m&LE?GW7Nc>CeAMxF8)wxM&sjuHSNrM2U^>iXl8n->L!Gup zik#8El|G$$rD#c8YlVrk#H``iw4Y9D8G)t+-etIHTJm|;MuFQTEzk_H(9cu<jCEdf z9)FILl7DIjQtF~+n3@S+j4CWXs#a1xMb%C}E(-l4e?~F(w~#eXk+~*Beirh)Mv0$= zUY&Tw_r<x&`Q28{1s(+WTq@7_V#YfOKw~LAlC+^f59*~duyvTtyqjgtoRHe5(t^c! z4qIZFWsKm8%qv3H^&C&LCA{;^6Iu=<&mgkuwVqkG2vrdik4oENqIY&Ipl}`eJY1B{ z&#Fix>7xs%<y5Gv`sPJw#@6L|WL^H7$d(|^di6McpyxJq6lJt<AS58tA5Whu=}bA1 zFEs`-1v*{G<vq8r<XGBdCMWs~e?sN`9G6SeVJ=Lk*`#PY7AP8tmPglF(`R{d(hA{y zfk;+s4wsGte>6Ks+b<AS7%xW6c-=5m2Zf2;J%kTSjzJs40Y%fHNaNk{Bmba&K)nfP zuKLxvVec;S0yHWcr1kksR`l6%*Ks^Mojw7zN*p<YV*AgM70CtB@>b!*u~eadm9)7u z+P9qc_;M)~!oVq22Aeo@4Yhp%`7C(0rRVt<3t+vVT0j9Jeur<F1NS~1bwVj<4toFU zTpTos<o-x~DcV0oVJ?w2F`B<(^^f$pYW3CI{3V%yzJ&P_QcPp%WGY}chNC8<l3i;I z;b{UP_FWf1@p}lL2k{Vcc64MZu<yD6`WSI$izH?t`C>>r|B5;otv__v5!-kT(U0%w z`xU(ed2f?~FW4K!^IEwf*9o{(vM({7rz?E|@WLXn@U1c!*3)P_dBoY`EN>Tw8h!gT z2_~2Y7@FvF-TE8}8osayw(H3^xTX+_>7OOKDd?Pwi=)6<VfMT6pD^pqp^toT*2Nls zr(N_zWPhL?K-p)71l*@5>uSDF^IX<PaSr;*qgmu9HGP1K3OV|946}Jq?ORKGbd}d3 z&18WOf%zV&OOEYY7T{BLdW%Bx9!0VyS2^-5l8gsP)zj>}NTD^}oUfo(i^xiepI_f< zo}e;$ceG+cEvSI|CRSDkm}+hF*f8gD?+n<$b$z7Oqr2HdBs+gcwjQthEv43woq?Wg z8?vd}@x$T;Qp}<#Hw*<4qUYkp%6OEz4EnnU?VRUB2PW8TO0<V9(<=x#5OxzR>j^aw z^2#NyZD^ik+6pgS>FKhhsz7&i*U?QIx#z{=#&y}`P$unj(9<{&uvITn_buTfPFunt z+-*N&LrE0`o<sV}M!Np*)YqvYvj4fD7X`90kFBAIuWN!L9&IsR&*>T3zZ=lVh9Lw_ zNCPJ~f?R}zV`S+*x=tf)B(n-VR7zzyqt7#BNjDtJF#}+kj;i^^)Y7xpmQ7Hru|ZwT z(IzVyLzU5_DKi>QBS%z1q-CE(b2Y#>H$|(gl_FVQ>pjR+jT~O|CAR7B<b-Vl1=f;0 z!!0czZY=$(r-+7Va$-5D>WZ>9RpW%jOg1~1?Vlbi?^x~U(y1kuU{|pe70?L(6?x^@ z{>2`{ENifCz{^5tSUr3}U=Jf^14Qqyy5mTrK`Qh-kKIY9{XF7|2k1UF7zqIKxy}5` z1mtxJmJM|!=UFBYwxCCtfqt6N6?T)RaSH08eE0AkZ;%-YHc!!L-ebyMh<!bLFX-y| z{@$D^I9A2Fc9vRXnR;hr54kTOw^y|V<N&L-s{=G4Q<!!D7{ePt)Tfw$_8l5{OseVG zn0%mL7}5U~#X;^)QL$0H^J$2zl!ZIP!^zp+F!ae9C*j`6pX=#Pw?B`PUD+jQE^Ryd zuJ!+O-@au=CCW@g<arUlvj18SA5cw8!60}^!Vtdrul15f68sGHJau0b{Z=d0*)65m z;f$AyJ6lR<B%cSS!PCM}IbU^c+5t8<Bid3a46`}gGd5U>z@SscK(khKCPPMK*g)Vk zR$y1<6N%yB%&3HIF~-}GmieCVankWZv{XkH_55SfbO&CnvC72!U2^>N{U7yXGWs*e z8u{a+^&v||5g8h6Llk%sAL`E?lj3{vmMnf@sX$Nvf5$^LM`=iApQFBtxSB&6snO+Y zyXP*qXq(XMT^_AQvFcsy<P?3vaxo>M8J81P-$`kKnF{2$de8*cEsl)Z{D)`oE`PtL z7>ei=G+s1Z)8iOD^i3G1<aK#D?U-vFrM83;2tEHBdt5fLN|W=~b^ZnV{ueo<c&!Hw zx?MaTTJKa`BpnsiLvu#`SLuF^Iz&c4O{!<DIl2t|OMUnX76ePt(2S4D0*K&vdh!(_ z4|tx7QKRGU4L)}*P=BUwAuBm}4HR3?>NJD1vj1$<R@p2oPdeI!CaBi_5ahN&b&aj9 zlI#n~nM>UEJ~D!-g&MsV*3UE@h3TqhpfG)EKHLxC*hwqkcjKBxaeR|-yLN0X+l%i5 zJ<3xMB{WSo&&PT@<~4o@=XY|FaKk*zIpmW)gS-q0S*(fJCo5LRh}YO-R&kyvF3p4! z;@Vi9<7Eopo6T6Bk&v#Hzo{cZ>rW(o<dV^Sb*46uc8WO^He~3E?b5-p>#B;Oryp!= ztPk&8-~NhYNl9p$K%PKuWC_J99?g^(k6ESBvLNyjn$eiTNKXzUE3~S21dc{vq(a?= zR8~9Pdx3b~>;iH#b}`pZtD2+f3Z$!!%lI9d&mld$i>#x5V?Nysdc;M62VLwT{>!A7 z>n5nU7yn27lp3LyQR|2$?UHvaR?jJ8(L3W7cIo?eL@!))3`R3_q)ufP8ChZ~`{#7* zQ&LR3y`XO#t6HX}nh9h;v7FsDuXi}s{xgd4zd@CweV^X`v~cbu>QJ%e<BI)pH6`CG z&bkAS8+|!;JWOX3hOMt3G29)kj8AVtKlJcA<cZq04RjeK^nTYe1Gb1=Sf9>i8J|wF z9$U9KeDGW+6}$e3eC9i-0;x^Y$%Ghh&k}^9M`WFFo<zHe{r#APzbg)8L1;mT$)?@1 z<<?6wT~5(^I5CrC0ycbOkdS#1uJRN)SA;;%XEgSd0H!LV42xJ)%X9MN3Pqtqpr~0i zuYx1bQBR@BvVrtHww_VC5lK5}`8YY3q#DE)vK^Vo&JmBX-jR-^eNqD<pofxZNE?H+ z5i*|F@94<SxBQ`zlqB<#A##fO6+4+Vs#!WP6It3uJfgFVM=Pf0=NuWuVUpmwWv<^# zE4pP11Ck0&MTPxVF|_j7w+_)b{+{|T<Xe~Vu6493QC%1>A^u^np0IHoI{;BXu2y#C zQdZM8f(nX_Sk4VO6f$z<`b(k3OD3OTCDqqBq^i}WL4jVirs$8P5+MUUg@FMNA=_Wr z_-0mu<+^bKr#E2M!gn_Wh$_4ekH@rtSCHGq83r$Lxj5p%@4b#j#}nBOE6bQ^dWQ4Z z?08}sTW%#*vLKUAsjksit7W$$F;YF3uCrAd1#(QD=6!}O%E+TqHCu+jO@<-aA1NPs z8tI>#h-PljE*T*eBSiIw#-kl3{MMPQ|HhdP;<1V58I(OG<)%ua7AmeHBxF}s#4w%o z?V8IQ$Pm(jnB=$%gbOr}l`2Ao;nRGENkK?X+F3`QL^1w1BkZG#p<jsojVx0VY~Vp& zR6I2avtG6#4Qrm}1)8fXa<-ID1x=543=`5BvB2|h<==|F9u=BASCQ&;KJc?>J`ErF z1N8{?A><pQdF@3>MdNK!@s3QLID8kxCcz(>dz{Qb){@?u)jSbjKkI5V?N$+!c~4+y zSVMXR@6zxzZ2=%Sj;;z&6fI6rL75*l708tRfdZE<H58xr*?gGDpS?tt8P~LM#kbUv zKT*Fy^3aFR5w?4BoiJ5M7UIyN*%aJ4bdmCXh_3g^H7lbeLo)#wCgUY(mlI`)m*`{* z$waZ%Ut}4knGC$Zu}mp2U0zm$aWPf)vrIkPY%o)q86`t!m|8Add+kJ^%Ur`xMOi$5 zroKykAkI#kx8xGllA99<eOE#A6ee8X_f?(qrj|05rQ}Ly&5<<6&>YJ)bcdPlFY-Ry zR#_I8OcEoF`yA4^4^m-gpKuPQHuT%`gRaNbQVlOkrjkhm3O=(rY_cQk9m_IJ)7OCO z>LGAV$Kx)Bw4UR9nq6lw94V<lvPYh$enfo@S>gO_u1=3VigJs)0{CfZbdZ}^#s{ft z6)|!|aunH>gmNig86Hb~8VRN=ek0%<fSfg5%C2F?-DECE<PfG&6nA_F^$g;*KfgNO zo<$L#!J7>qU#hi`wUSs<Fd+oc4t5H(&xp1shwe;(2F6O4E6Wq5`}-@f#8$vi74xoy zc=vPU(e;tItJyWF)yO!EceWPh)nLKAjMVjq>0&wvnhq~tOpny)a~Z*8wx#WC-$)~y z1(sbjpksKB#2H%J^jt?&&!9PEC1}QCSY|n`6@pB~vvfOzz9gzNndOJ6e^B2hnM*>P zv_!Im+~Qay;z;#X+t_yCjia8-rGLoKuq|1V^Fwq%D~@gCXe(p}0)}S=gC5GeQ04_i z8O%Tcb{X>clHug2mb5^vj11@?Q=>Um)d!%zTN0~?lFE_4qIl(AELZ;A1@h`_VAr#X zKFyR;rDD<>X&9|GJyD=vCOEQi0-bf!m7#_sg?s>XkaudMG>cc9Oh#bDWwep=QzQqq zhCHL6PzOj&*6tcK>UP{~jIxQ7^y2Y&lUT`Ec2Gq+L{=?m(|Njp{w?rYCG@kF%O*nr zilgaC#WX!D%K*AmpmkZv<dUmNwEq|CNu*6nz1ZC1_#A9aB+4<mx5^`x&?^oFG_9Fd z=tS#gv>>tCU^!D(J+7DwlOtyZ!v-*Opo(0mM%~~PqgE;GAbE&?rhbdKSs^PzRC~?} zB(|kwGfSK&YOy^X_h&c3zbO|Ax}7yGI8b3|o>|JAs!0QbwY(R&mYv-*f!vc|j}0YJ z(;OwK!bG@!DD?9qk|2gOA25@(e69v`-Lcl&qna_$X9zs<1<6X|Qz!<wpIS|AAsHul zG8E%6pRMmV-ZRzlK5i@s-Dy%JGT}GzF@S2P^xyb1(1W_qIc&l&SlLp-w*Zt<Nze1^ zd3Ahp*DFL*QYN9E$=3Uf1g(ldriFx&-zUqm5^AE>aGhe+N~a~D*oG=fG;+-~9RTD% zh%UoeG{?{>8u>MD3eaL`*foyhd6|t)pP<qHE%hy8CvXMN=vdI`>{@@PLjpdrA0@Dg zBIyG1Y<|1an+!ua-C&zWv$&Zy6p&0<nXurlMjCTEqzkKjns)^|U}sJ-1}ZjG6)s?0 zuM~(X%o~M%H0N_-$RJ;c$?-BUbh3Z*7wUIN0`v1{daOg|q$U1N$R_|!cC~EHb!$ae zFg+UD7GPz$DD0l9dtRTac+M*6s*SRl8>K@R)-~-EQh)A4Xha|FoJyFDT2~v2V>pI^ z=mB4lT}O8Eit8wl!Z|h{M^gH;W1mpr7A)C)H3~9KEebMm4%2E%LsI`qa(-5fM2Q&b zdpSWmO|A^kBPp0!?qz_kG5(3dDcJkOZ62XMk0^GcjGBn%p4QPvk09?=v87%})954F zd5;1$SvzMI>Ja{bR1X|RKHMSdy(rQSIz9tZXR#E!QJBzbea|ged7WOn;=R1NjZRe5 ztao`aX{T(OK|{$JEN|C}CDT>XsR~6-emqM(f%>V>p0JtSo9+PpZDPR6CF#%5Uly$W zG@T#Rs_Bok${<~*IV2k<%cX|<8;+}2N`r`VRb&aiO5IHA@Crm|G1#xVnIM-lcQ)VU z`xotVEvJre{>J|Lk5QB{_t_tZwXim*ziioE$@Dv~O!{zq1vy3g6q*S)ku?w)g+<-V zPQNv<L>ntHXZusZ^u;sdrZ3l;qZ`ucS?~8-BtJcF*XlO>S!;tfJ<Pl@*b;1e-?lY& zptRc7@?GU}bm!wgsUK2r=$=1`Z-)HgC)dxsZ+Zjk@AAA|WCa$<-ILU9-MXCdb5H){ zjIDQUJ%jUK9R#nAs-NNv)&ry-hUj;9a9dHYaRHE~-~7=at*fHTg#uk1wI+%?Pe(>> zKYglhpfHYGS<8TIzeneCWTz7E>^~IM?COCR9ZkS~HS*a0ILTPL6mm&PWct=yn+7hT zFQ>!Fw_IjfY{&|yjSPVP31kua`p9Z>h<uAj5x2<hs?gnJMru9|MNu3)-fBYeQDh8V z%j1%Yp)&MZzEZIZMQ+6^WW#Sfbs)zkcqhM-ZmmR4*(9<)Fp+>!g!UZL)rZKe?wh|F zbu4_(=(?*SFH?6l*FHM#JF(koW;KA`b4R5E$7Ii-Nbz7)BO#7Lx>Xnb_U})T1Nn63 zG;TY+jq~w4f9eMQB<3VO;2XTp_t7=Z=Nkfvl%MJDNoVKxXd&bm3>9jwrK5LGJ!uY> z&CDi#=N+nRs&+z!mTJFdF^u@s#8YV2e4A9}h`Chls$VjBzwb<po5K?pvm0dXdgu$n z4#9cPnsuS;u4pq%F=y4*NtRCY7E9_f1qk8`WK>ce&mU(SEDAgN@&(O+s#~xpV?0jQ z>EQ8n9jd_{DjEo*y?Q;uxqM<CP8*Mp9i6N>j5N@<N$u-m2V;8{;}a`rx-o`)6`EdQ z2X-9<g8c3`_=A(cvj!_Zo$>AdRk90dQrq`1^&FaEcqDT3b8!}d{hY2r-8IO7q!z>T zc`^zq6<C@*xfo9D{rwerf1jFrlj~1{4}S3dpHXc85>j)xL~^Kp9_M||T|Mu%Ibz@y zJziI!4$bfbA9&wqzN`XMHOdIPYJD?;MN<IH`KQpF56J1cDD%DdGD<Y%n@=_NTVu7Y z!Qf!9l@1%1XSOCiwZH1FSrd#RZG$L6P|$3T_HK|TS)RkGqd=u816d<iG)xrNX>(EB ztvZ%!meKswjFt1zbx*T=mDD>0J^6%WL?XOb8L2*{|KGCPSF0;GW?v#D28GIpT^sqp zLsKiE?<`x|z~#;*a?bc!>aX!Q+erIm7u%7T3;nNnzPUCYYH#Zzn8-+589dTXxER*x z3>dD@7DQRiv9ZJjsY#|F{?B^?4&=%!td|v;jn&ukP^6L1rS&mZE7{1yvHdg?a0bhY zoRD(uJds$O75`{w92V@hE`|dM3ea2?%dV#{itkPpA{A1=U2^U@3T}M+&vVqDkOs{4 z_!H2d%~x&5;TlH$SXj4<9=)IDmBH))+s=&m^awi^(ytJ}>jtV$zCg>nEQa9{3`p+a zLv9J(mROtRaV0W@=bv#O=jA;6FNXJ@I_j%u;&)d*1`VXgPDTO9ubMt4J$U8eF!ea~ z0Nx{td)^U}$K7`uYu7911a9bN?)rG%vv%${L!Zd&HM|0zN9|sSXR%GrB`uIStc@!e z-V3^EtFD6ld=<VX^evcri*mv`R$0GHxmSalX5_G$($CN)L%l!Tc9J0(`kL){erJ$G zJVrfC>~93Evus%{c27WK*8IX*xr9?D^4W~m4^@lVZjV??U7r)Sh|ULBZ3!hksCp*! zb*sT78+LnKQB}@hc#^aDbXOnEv%%sqaUMY$0NGz%MZ=*xE0%J~WG<7{2B4`iCz+%6 zl<V_6!vAHg4y>H&n3`Qiw8&aaOIV6&(G)@p_F)c_ihxnwQ5f+rD(BTf?Kc0or#QkW zwcNga`99%-F+HsB*+bVG4(}-CBJHDy$rl|cOa0MFoWpVND!qLpfZWAUxcK~l;-HS1 zlB4;3d-oPb8Ko~vu$?=m!@Fe1R-BUJShg(o`!VK9A;K&;v|^K+qMt$D;`<O@b5_f@ z4F+#^#RB$jS974ZS#Sr3)#`vF?D5e5Tc@g-lvYg63>9==%2cM;tGNV<W>|7&=J(W> z=Ru4|s3WxRaRGqtx!TlbMp>6iXjizF50jT@)tpwaPu=JXwo}Y+->T;;S{>(IBAA_B zdwc>ux9D!}d}-F8>hl`XI{t|S-2k)#H*tfyZWW^}TPfeG*~r$HbVt|CwFL7LJy+HG z%bT~`f~}vh4v$NSwD#|*yHLO4+nW7i<c{N!c=+a<lc!`ytij;4?|j7H(HwGIvosJy z8Bxz7TlMq!p6BFTYbDNuLsO>gAol|WhdK;zx+&cOdKc0SDhd<<8p%Wt0-8D*$;+>h zMU~@IW!QW7ekG5!f?(xoE>JJ~@dh2+u$|;&&_g8q%k6!(mw&%f#>T>M<%o{)>x7C9 zjDE#&6ep)3St6c~hb;M@P#o>dk^D}Th(GNuk4gM+mOf)2@@h}J+?pK1#cC>jzK={Q zgRGE3{h{{+I*w3&bo=e#kw>ocZ^o6~b4VWlfMUBiPjc?O7H1bgyg%6Ke03$S&Q$V6 zEm!e0dgaWUMIcySHQ}U!;k2atL!JfApqN8(WI*#sk+Q@2Bpy|8<az2aiWj0x$8HQ4 zn=QO#jL}3neBTK3VWrO+*=f<Mmz@v}NLJAp$m@OYNCxNZ2y6&j4$XR%3e8!pa5~Ib zq%O%6>c`iR?;y^4yI<4WO>20>xM%mS1n{=*Cg%wblQp28)dFHZThD+=IS@~!r@$oV ztot|il8dk0YHhfbA}0V2cRhEz=L~1hfwKt43wXr=m}JGl>B5`%0$Fy*;dkfGF6{M} zbznb7Jrd_16py_p-obN!cV$8lqLqolEcJIpSqG+u-2hG!V~nreMljOU1UUusAn~MQ zOWKSUgj`}?AE#$B<31X`ZFRGGvM82oZi0i^4{r98ZYnVX@lBj8f%4B-Kg{=`<IH}1 zW|2U}>Hf$<L(SKTg%$|{e``O2&s&+=U9lg60vhWRy|^ry?cn;~I7egP7#vy*??cgU za5r^;7xj7A?~Pb#l7tJy&D$4HfY&OXq5g;ZBGE`4Z5PjsL;9L^ytH<ScKr>4|G|x$ z98Ga%Rx%+LP99T_+jdSyBp0=!U06qS6-7Lvt~eSrdf|RWwRKg`YPPN!)de^hg5z%p zN0MZBMQMq%kb5@Qdv{zP<wR}GdR|<!RK5NH$3`-xb#~1^&e1&AgNhZzh*611;>75l zQ;~X>`bb<4q(F8Rnxp=+)@vAX30x;gij#y_%j=wNBB>t`J^ujV#e#V>+y3X+A@VgW zGG40()`wz2K`PpQ<3hNzb$*VX!_~z>a!T-SzY+DAlQ#BX`uMC+kj}ol7n@CV$T!gp zN)XvEx;<+&#TKq#+3cCF?LVAm*pkJ1ytH>uaGD59z;j+@=G~0_mRH*b8*<8}0bQ$I zYqTe&R{x4Yy>B_<P=w{tc!pIL_{1-U^=aZ08-$7Jqf!vX0BOupXZ%H|IUHxn;q0!7 zV{rM!D7!aeEn<IXVfE<r-7{|>CXY%ZUX#Lp(49oH^_Kpricw(nD}QM^fRodDkZUC9 z+rA_^2WrbwNo#c-nyJAWO$VIK2zZ2x$Orj3i9=Pg9@wMlqxT;PCvIm?pB9$xWH;@S zW?sp>?2`fDLwQ#K<UqPG2((a*b1t8xzCq3~h{UwUhgL9*Cp~TQH4KxS;KQl4!wJ)M zMI|AMqC?*V<&Seh)7Nv|6{rV0@o;a+3!I<udpnmcZ8FyvidCgjHnqSsD??7on<}}P zNze35H#;JYXM^tf$2+5S#Yk5c+s&vf4XH7O2k~*X<|6JaNB>QJZXf;9m(p@>2qYNW zo$`l$^t(jm$?n<HNH#x2Je)W>>+aDLUG@XFVr3wGg6n&O>;Rg2yLfP3IcEncT6zU{ zG3RpyzAPdI#*uSb&r(mL7&GYDZjxO&7vOKz0bmu<v^dg81*taMk^}it!F`+C)a_)Q zW_a!z;T?R)H~3+NGkJ2?6pC7q-FOrB*_!dSP@;e6vlsKHzgj5!yS$f2nXzb`@w%)` zYS-bXe6jiDPu{~_`2k^&r~S(U`da+lQsjw!oq7kZd@{R+gI{0wF1h4_3od%IA^UZ| z=tnna{TX5Y!op_{1=nBy?svcMcEj|S2Ezf?-g)%wFR6R*dJCbz@2p8waWOj7^>5#F zlWs3xtFKt5(Kp>9cpqT`W=p%J`*NcXIa&;Fb2yWJ@(8Xi^&pB@N&a8#Dz;G!gMF-r z=z%sXRSKf8Ck!8ad2LveED>6IW$)YGh^a7+JVpHj>1H#kr6G_Su=s*HoY@@ZG`8^F zWB;()kmVS_hBRF%2{(ipYmiQyoS4)kTln&)>2zCChuc0ZOfNNTQsMP!G`0_td4!^z z=qMm^IWXL(-Jxbm6dBgwk;6gLTig2*eQB8yeD3bowdlk~vLlbza6TW^-|?dh<w=F7 z9|e~Ow*{9gx_-~~uYW!9Y_JTG@oD3WE^$DGpFU_;2eoR^q|XT6vAmhpJt-(RCbp6_ z|HDX%?<NsGjQ25ci%0#D34KlD>hSJOYig#iPjB6L7DY}0Jc}gdp}1ClPa)^{j;$sp z@5xs1_E!C>pwVb;p013K`<sGFCD^oSQ*=iNkG%OWA{u9BPP}e|tJz~Xzep6EtVbXC zu;_9>+#Bw@emLhOOGr5(w!e?|&pRK>SBYq-JL5CE(LiH3*q#14vt%77j}0sDdM`(h zpL^$7CpogN_m_eSP5Wdw=PzWhmM5H=vkG>pS*Yp#?@66_lCW`O;#xQ1Lm!^7+6uL0 zYskr#r@Ow)ymM7<yk|1I*>XfTOx4je!_u7b_4>>ZL%$)|7;gKD1{F=skoOV1m!gi% z?xi%5w)=1D#wY`|XPv)Q?5^`8fo{70&CtNnEZ&o3nI2&?IV&5oV=dZy_4-oC2E5@n zYfaCFeMOgscA1=kdIs6Ao1+!vm|A3>x(gRS9xL{1<@B)Wm_@_m#f#5$3Ju%UiWw_m zS;aBQHV~Bas5R6FsY~bIDt?}!C<cD*#eZbOh;E(Vg2w2jo$B2`zx(bj>8Pf7g}MXv zk?(Nu4p3`Z!{gTYpj{y~I4jimNS)ap>(d);d{5Oa#ZgqUJxJPqP=>0kmB}{XSrHr@ z**%XU)~^z+5>01vM@hRF_4rq`pk%E~O1E_S77>lKoO=72URF#f=}jP&*3>NS1A_5C zNa7RG*__^bOEKTD5&9ozd|+CdDA&qrqZXLgC>{W+`)1wDrv!Vjpm<WsM{!#sS@wfa zH+;LlN_JOp4Z%mzY>2DU7K??rC@p5}qk(*h6sY30vM#(!mfwA|s3^qiEFd2JB03pJ z?sp~)T-+8mo4@#!q$<)UKd2}NSXp?7Abax5<Y>k0dFnBwhl02cWPD*uBmi+|9`h0) zoicQ=HoaVJC)P_@01fZjbBCos2~Rq;>XbJ)xljW>*>nG2G>h(wtZAhhZOt{~(t`*p z;nQzjL42Rym)dl)BKWMfd%s(MjjT8cK{fScFfi#RU0%((Lu1g?wKCZ!_y_fq&X~=L zf3Zqpckw5DI-_Ojq;C1#3ORhqWvYMm?m;=Bg)7Yw4>U+E#J^F$Mv-u4PCwgo`Wcb= zYd7VFX*~RsnYHS&<W?=|J8HN>W<7zw=G*}xl+zne%Q&gcFqt)sbk^n4fN12uA&vai z&Mohi2&UKZxyIX<1uzqOo)czX>81k|5T-I7tqczhO(`RTBiGbNDh*|DXmpJ1QT;FR zNyt70A`A+%Bok^;w;#Vqa$cz>T{D$33_vp%7?!c@p^sR($(kz$q6f2%pYozSi09Fm z+)XTbtT0;5-@co+T>z|4+_Gj}-b|mcC91XjSL$1+4;Ha0#2Lb6jY%b-Zv|)bvg|AD z$$_#d5XGxsD#P>eUO&>C_aYBK?(OxxpuBv%3=54h#vB-1I&KV&_LF}7jrtAs<!IF< zvJ<~K)!%jSqqpDgNA*G}^!<HUi#CZ3=@39v=V)AG8CjIyd~5eoNe!eyzpnVI+}`Dm zsq)s<^1glY>aDUmhQ=e3Y@D-Z_0+%Y?2><KNlTk-t}oQR@{n=Pw*MS*AgqrRQv0@g z5R|u*nSpOOzQ1#0OC%|nhOxLX>|?rg8DF*v?CTWe?H`o1OC@b}$tiA-3$m+9Xg2m8 z!MlR@kaf5Crikvu#5o@E)JDA<jfz1WQsuWvvMOC8DxUHRS$>6*urhhAXi17HeNa?2 z>6+Ke^6TXZC+9l>(Pj7q>%H;reD_Rq#M)m$p!ghA40(^=zW3}jABd^R&wt(}<AC!A zzZvfvHvM=O#8XvlK7N^hfn_hz2CY|1$%$2(=vo)Px#p~fp3*Xg+yF>LavLWet$RuQ zA8SE!<`nhhH?Fa1i`p)D$)<a@0}`s5QcSRYhrDV#XXeyC!r#9l{@xewBjD>TA`SXj zeZ(KA*p+&9;PzVIIp>V!%tE7B@9LJj;?-`kQysKZ6J?zE9KYRR0uW@9Edaw6wf<^# z-+$dQY0@}(bXr@V4^#PJkL2MzPx5e55v=ZwmVUR!RAjDyw*#rZbTXM%Tz7f3zVVDR zf*o(GTDD_CKclY5hhu!+t<?xm|ADyi0I><t1yC@qLEM3bU%wd)R>-fsT2%Y`f)&Bw zMN5|Kl08LyiMtg2knC1GL+&T*UeVl-2dAs3$h~4%S^Z`?Cl8yv?HST=W~II~xy;n~ z!oia#6=A7#TaeW!+EV`*l4obeE_<$90%4>L{*UY?iX9D&^s%=jd8%+xQZ?6~>3YeF z$>{tanLWv#_-b~9qa9#ezQpIm9jnxlktHdumIKLjX&^Mf*t(bKE|3)2F-$Mll6cV9 zFbX-I%R*z_jFV7{1j7pm!<WfE{JaPbD|Mtq9&?h_fo0-kxj3ZO2VD1U@3Dih;=pXC zp&$>$gV0GPMm%RKn<kw53z0@^)`yJQg;jgCh&g6VI&J=1$xw%H(nY6KUgxb*c5leQ zplO$KF0hAZX1wTj^XHJYxG%1!*<&GoZ3RK7-K4sfZy48|v#zd`ruFgw-<Rxaw+A}A zF`dyD<`}`>Y*D5*ib`h8S>kOuiAOODxBH4Sune4WQqd`G@%(^sFf^PE`zvGvBywMJ z)c99-NvjHOxp_0=Y&%KXz9z~A{wtcxU!fFicl=q686UVBZ#}+FRD7lVW;+EEvLI;6 zXFe+5e*R2WPv#T*NpGpGsJG{KJhERu_~2HuTb?`ePoiDm{1J+S>|fda`M$bU8>pA9 zOj#`#tZc2STSLWq%`P?SMJruas}-wQ?~A+|mij4*{p=o1NC?Gh{inL}R#^??SIWLC zDT;LSb+UXN$@)PO_}{Tti0i}_`)`5oyz#1+kq8le_fzUXylPFpjo$OS;OdubhtmgM ze<67Nh4GV5A}?1X`vp-FV>4P<Ck^gY%le=I>stP1)b#9uq?KCXdMiTH-;dhk8*9?Y z_q-vd0yP<hZ~ylj&IeIN<TRR32awzaq_%eiHo{SCA+HB3DDh{NVXY*qC2fGO?SknP zTWlNv$`apn>y^L^CKN!QXWAx%Pu^zHNIpT`LMrK+$YZI;H_^nP@W1iukvE$(>h}~% z{;#Q5z-*SS3_W~h3pg<0`3W~=q94PuZn16oJkgTrvmK|X>x^qyo@be^sp6tT61fS! zf%@}p#PO(7Il0L2n{T@2<{QB-@H*VzGWz~;^1VI#1i8eAXyRY2-f;REC(Tr{+`tHF zLxYoLAX70HA3>Z_XYU2VHoke_E!W)qmNy?*T>+ai5l55AZsKtTopHs(6fI!m7H`=G zr}m$^wmQHz+w0ciQC?N0MMq>dr^y*{)c$9vy&m5%Kc_9ZugE3mk&4CbGx;(%I6O0b zmpcgI;NXES9PoNcdj0+r3A9uUEhIX54m6(>FDAjAi*JN0Zk@`N*ny#`rME&jgnow( zEUy!g+Y+$)I-Y-Bb*9n4S?CCAB$0_lBytwPtYjWIX?ZHg*7}#v%#qKTep+xu`oxgj z;EpK#MNI2_N;?cke@okE3Ke#6WM=wH)2mL|K7C+ijR4t_%7QYu5@aJTrqS#_KyE2Z z$M-zVhuEpfF8*xq-mO!aJlofpTKbi9e9qw=(Gd;+u%eF^Y>D2QJQ;v(=!cvvN8|D* zBHy^)esou9uMBme6DeO*$Pcz(zIjO|$JGZWCmwqBs8a}BH*f>ZFi>P|ATgI#^zpWU z@Cvq_LlIKec1dE2CgXc7WG%WkAVWP&Bw3C77t6)N@Dd0wx#Y$x1>s601Gr)}e)5Ls zj>vXo%E{yS9+@V*7?R(MZ>UtR5QMM~S93$-`}4R(bQk-)R`dVA0!JYE9XSCGL-IR} z;9be{C?Jae;<W}OFHaM>35f49Pjcpfyh|x)bsqNX`2$_xr<4OLT$0Z(^(^<i4p<UB zCXg<@ncQv>r+MOwO%T*K!!>H(5Ch94b>h6yl%tIo3?o0LIYi=o)b1%lPdJ~N-v9ZW z+NX{1u&Grqkc)ah=jQeB^jg9Umu7QQf#nbNC9TA=L}D0MQ(>q!>fL`)pGMRqqB}i~ zqU&A_viVA}RLS=x(N7|oywS4QLON3{X3_;S2m;>^f*@LTNTQi>Bk7-8oXrm^wtl*W z+p0}FV1>Gk-+Cih?K|P<P|68b5$%pO$P=iYO)`wIcK3SKdvVSu<fGs8B|NpH%0;!G zEhtsjR#TEvP(etSZUjcEE<0|$<~wky0f6e4WXCSnJX@}(R6u4hrt`LV)f3BO54D)w zPoH%4W^Ri%V>>I=>HxF#HUKJM)Nx>?<T+BsBbA{WNM5nklw<vglY)wk55sGiYp=cW z%4HB(8FJsotUh*UudV&g+uro1xBvSAkaa5H%BZq?8tLO3<J^OYrtZvt<inr%k6{gJ zeL6I51mL9rY(+n42J|7B_$l=%vd0d|j!@ik&aCbo%@41>@^f22E1S<{XFT-dd)}u2 zD54H(8dm|nkN%;@Ke(3{965~q$AfW|a#C;p0ys4V51tBMiof53zP}xPug;x)dte_# zzhB>b#-aVE;OEXq&)q%yT<1Ev^C7+h0v=oj`@jj954*eY7SRH`VI7j+`qx{Nhc-^1 zh*urfp%$O$Qb^+6_d>X7)4@X*6X|NlnAvU>^$29^V-PkWTzc@(6}ukVi}&%@#*oxm zNHMg{=;z>}HK3nB9PL6hXX~<eo{pd{M?VJ-{otV`ppGGXNT)nOeIT~?BvN_eM`yrE z08T%>Q_~e^x|y?FCi2vD+aE>V8+<3b6s|mYCOCUq1>F9#_)eQcaegp*uGPaU+;$~g z3NsM>zLp(+?-u?wr=4}^teumnd6Zjx82KNwJ&keQ3E@rba=7u}q16r$Pv1k%W&$Le zPjw}@E0a$>IxRq9OosAO08Tk&-@d5Q2hNp!PsgvpOnKrgaMpXAcfHH$WIla|jFmad zV;mm2C^-Exgss*~may+!1`i%O9b{M_0q*6bT2<6jmfZh5hvS{LUxToL<zn*?dr=)V z|G_s;0+4lNz@8K3q#j1LrKi79pYMWjCEUb*?BJoRxwFpXffD8WK7;yjU1!D?<4FIB zrEn51xemPRUDsX<qP?3b#Fwqaqeo9X_0z2YbZ|Y?BaaBr7a;r)`{9F!P}ppeI{^+; z*O2~n?gTh^sN?nhj(EU&M-HlyKU#b<+;qm7ZlS=`n#d)7?fJ;RjJ)&6e-LA>(eV>W zo1d><zh^(pXW8oT0dNYqlJ2xhB8?yUMR1{YBTetps``ik`?UP6u#jhKqh}4IkUQl2 zD?-aZCxXKw+n7Q0ehfj3DE5nOvDpFfnaN9+W|n>y=5kDB_+xL{bHaI~8H?H^sox{) z7Wx;~_p{h5Eu1(q*EfrV<W?=o!nCef3@eE5Ue*^TxpK9yZ^Z;Gr7Ul}Qf+ybTvP;8 z(=O{eYd9>yu^amD_k>68ERW`TS&y$;xBH@#ris5cJwup<eJTWHYZ7VMH0tRyF~xOq zesEEmM~~(JMnJj0uzp5Qa543w_`%7t1GsdyRDL-CA^HuY9*nz|Tu>!l*Iu=}j@_y` z&MdCxivD{#<~Hczc27UPgn7Q?i#uj=MQ&hdW;tg2`N-YIJwa|e?ny}IGQJBTs%yHy zZ$C!Vlio2?D6@@`ndOgMG6F1^0B#5q*dJ6)^FS950HCDnZ0NX&gzJQcr5mQD>lVUa zjQxC-RN+rXen&5>sy!a!L$P<Cg(Pmcq|1$$yjB!ndlsH~Sd#yQMy3;m^vZIj7uILx zf?mVEk&~Q`{Jx#VzzQadr3u9M+>RI`rZ9sbc4XS_^0^1r7uv6wNVRuHR1p?;TdzFw zSLy-ke&X#WNOosWyJK+n0eCWmC!d@HelnL#<&t^ey1;SW`*-sE&SmwJZJS8~H<@%n z(z12k#;@p}+$4!b`1n>W!c1`<Pv5o^t|&p+M!#(o$HB_$MDcZ%=>bwlH%VqAo*nTm z+_4Us2jj6dC!E%Wf#*lH2MUKg$t2<$KKYa)86%6#ka++jQZLleyw2!~jpy|M0BH!* z=_^*jp%faMY;MxG<ccO5roMT0@bRqXh-dy(7h~;sFveY56z7)<eanu46ZaT%%SHWs znyf>lVsC5SO2j;zk5@<avV!0Z2-QNDeMZ|eVYLvL{<sc$7>Vb25^2-}B-bT5I~sVB z&hO5zXI7uGeP&4v^t>phROgJ!Dk6<v>sjHL2jdtLc{_wV(eKVI2$H!}I+rX!*M&$d zKjZD;`8{4Ek*F^&l>${ocz+h-#c|mnz8QSMOh0~FkRqs|-`Z6Ccj-c!cJushZy*c@ zy8r68ti`Bf(8wi`&0K7qDw4@PYE>WN-7&qE-Um1Ct0k=DvM{kMFuna`oy#Ux`oQAt z5rh+zyn!OZAsq#+o6b17=vhHKlWltzIPZKgr~Q2E+Zpaz2=83GabGWl^NAqhm_E{@ zi$$pO8687wXoX8-h1!9LR3BW?V`K1*JZb8A0yn(~ZF59@wVc<h0vyyz|6U!@DzZ}6 z2l?vGf@k^dY_5$!p9eIY22?8tX3$oN=UgXie76$q8f(_8w|(N2@t55Cmi;H<OlqWs z{)8ek9Fz8us<KCyier4W3fNxSb<;sYa~w@`>|Ma})2^2a5?Bt<hc}uQS4`zfrCg?H zCW0UggCOCU7F!}8rb{OJgnUSDm(5W3QMbHkr2HxnqzkEZK2^YVK2a?7P6(N-7v{1F zFKf9LULLVrQhyae`dtjMdQ6yp?;y;eex*D&>4%zSX{alwDM(iF%2n?Dy3XaobUvR> z<Sm@i;X~+W>uKb*L3c&M^bvP4*5AjrEs7Q++jey9pPjs9NoMJ_^U-3Xw|_B&SnCWN zd5-!%vVm;xx@vDUD;{HA_4=DXUYDRapa8kqGs`{Tc<%iGtOTHnerlG*BIhHO^gzNy z^V)I9+{Sl^+0>t@kH&XqMffL4UA0Jy634$|-~M&E+Sj^mJb&S@U$)-CYrbB>OXw!P zG}zn+Y&YTgp_{}XXqNd=<OG2%e#<Kg>sgNPJGN&UilXa^s@scwh${l3k$H-&+Bsww z{n-B4Q$IZ$cwsh?$R@Hjgf@EJ0^zu6vMJX~r#&}iIi}$_hUvud;!|-Y-ku1&6Z_%U z?QmeA(SX-;HCTd`gX=&ItX!c1cHimT?o;s%Hx9Y&@LREUid)T(JjuP!Foa2Rog=)0 zD_#WQ^(QeWZe=cSFZ=P<)f0-tK~k9_foS@#ZrnSEmOCIkz*J!w)(#$uXkhmc8r*Iy z=g*DPJFy@hWE9yI(9f&;*!Pv(B#N(AAzxc#P(;aGd=YaYMNSwVrhXVl@yUg8d@r;I zh~Y`2pEL99s{;T@gxLZvkQg8U`rMb$`{U^M;ojcNi8T8WPwVWh2M_%ld-hrEX?t06 zi}<<JDira(ibR_|w=!O(8itBqtBfdNmE1_MA?DWXx<gM3#IKWxD{dG#(8P^Z%|OpG z<mBwbBxfSTyH~h~Pm>gv!gb9^c_Gs8Uz^F4m3}0dG}GzaYu$6f@bvPL#_CmH99cd+ z+`npdWBiKqjvF3=*bA=@zWfaf;5E+y^WY_q0xvd<y%0Zg)_Jd80C5ED0GH2$nLT=+ zJG&#jaI3G}yZ`^&d-?*<qpNCQ3yz`Y(wjXh#a+L@7y1X_N(fi3Tu3;!!Y?_Ang>5i zYPKu}f4(=^gX66bZUkWC#sx@DDP6(ySCppv`>A<6DjWsN+*RscB>RmaHJN8%E~5@F zKy>y<%27u1ww)c-oW#676>tQ7v_2h0)AeHB1-w)~nJA=kw(r|Whb}-rgfw6&nJtyF zDP-J{p2n}^?D5=n>t4LKOfb{>u&xbiO{Kk1JODDX;YcHErdEJ?J@&DUKbn-p7#BtP z#tr8$VVCJ%fzun>h%&waE3z<EFz%U3#i=DxI5B@drH?V+$$E7!w#t?8<?O}hFP!$T zXh9I&c78nbs%MqE7y7^NKmGJYbigRGk`?f}1sp3LlVe?9q8G!5uYT*hax#!BCNLMl z(_J=45z1U#NfbYh9UI?K*VB6mxN6l!?_Ul^GO0{@DFgsw^FN=C3II6(N{Ygju=y|H zN@Obf)fQ-$;<0oq(*04wgV0OBTVOT|&r_F)GdtJ?n88V4d&)|!279P~8CSffw*c2= zaG=4CPA`h<#?w?wUx2CnqL_+D!FB2Gwaq-&oLm&yEnu4n#0A*;juV?W-wF_nuiU=8 z($9{LFJHWaA6q?u*Xg!r@P6xjtMK9+Ew<<B?WmVKcdi^<6x~NI1zWZ(z*Ib{Zs}r* z?*8=`!*<3HJOu@Wi{g82`Bkqv8<~pvJgvV7zN6a=f^wBoRGkC^J)mY6#d}sgbmZYe zKA#;_9Jr9Tb$rXuF)27cJ3^>A5jo&#2vdHj+P13M_M#-+uIXGkQ>a#o*@~G;BvSab za25@`2wn3-=mpexr6H{(X=N1CRTrOAKtkHyDHS{vQj1^_xf^;>8n8a=p<@v;GHXt* z*7S@hm-K$Vz9=D|!G?z(v`ssk0VZsKh1{sU2qlsFis}F@AYquLSMFlhs}*ZzaZPra zZh|uhY*<sk|I@5Lx}Le@)HTbOH&R@^y(r=jVS^<CVG-W<9|!N7J}I{6BI~;VGuUqc zJ`~XFLe^ar`3)$nnPHYqkw6B;xC^z;Fu9BO#U<eQEE*xJvUJCV4NwYPFBrtz!kVrh zO(u$tlb2+^2s{szbZptMZKD==fc4|@zWjI#v6rHcEnzljOH8A!Pb(8QYzCVbkODzY z$0_cXX=K6aVEcA*a*{jpB=vt?iyzh9jS2#HZ?(p9@mrj$<^M7a4bS6lza4TDW6cSE zX{$XsGBY#64=$S;zS_n8nF}wuIK*~*ysa0i`mT4`U--gefbWDC!yZa;CRCopd0oKO zcF~^;9eZ+xdkh5Kw}iVS1EbLOkA76X?mEvL=!;Qs0B|vy!RjZ$1i(H}Zx52>&eP^m zdeIZhkW5=b2}u|i@i~^>-hJG;3c{=Mik!)s`}ovV$>d@^edr$BzUPL5Ebk}|XS8#+ z2s`#CD@9x#FQ%#1*_#rv)b{q@>tR52tPb%65jOmx6V$aSn=pd=0>ctcSp8PLp-#8f zw7%%H&M-$B9e$_+-(g6z-`wJ~-oIrYM?!KYzV9d;nY~3kTAw5T-^+&`n&1lR%Fljw z&<PV(=FB8;oy20S_`c(dD1w2mGF33@!~IRURi7`fm7`GMi?a!^(aK3L37=q26E<yE zlqq%wE{6F7P~OM`S=lT=apm&)GEL4GFWz_3*&^w9FTPiDg+QAyh5_H!M;1f)Ky#<( zj$O`Ny2NhH>*3KPuSp84k<$^;g{qMNb`E6qq8A%9q$f04pdlj)zN;4b(*MufdjQCB zR0+c~opY+{?#Xd?W^<a&N!nFdNmjJ7WXrZ>$+C@YY%R{l0Sq{iIgVh?q=N&F4B`w2 z1{s@RkZlfr?)W$kI45ijHYS7hS5^1S_Vo5jG9Ujx){b{;daB-g^>S6cO3Rrv(-j5F z2Vf!rZx-bOSC%D7Ju*3JnQ*8pO!@p$nqsKFOQQ(}VY9Pki?cauz*{$OwlBXNQ#l^c zgzcmrXr#9GM<8YP{qq!MvOjsKk-Q@l(fAO%u=uy1!)y*_zMIX$bXv$j*HtA|f}*aa zq}17fViZ^`cD9&F1z6C?s97V|Ve!1Cfj$H)QKZY35k=b3-VQ8HwZN4ZXKbx?sGm`! z)>hCCDvoWpZr#<MHnQ!Y-H`PJ_R@lQ4ade~(@SBta8Rk%bX>cE36^IYFUtoov1=Ry zXlB>BGP57wM#=(--vSj?FT;-BE$Fof{EVV8vJ71I8bzfbC0PSUbVVz*t#YPp58ht{ z;^aZRMimLKcc29U=Hg3J8)qSKez1a`^_4*o)?O$o(2`2;re-)@VmZd*f!Zo`(w#Ko zQ97*)rm&dYJeNuR)3r(1F95!;<m9;8s!0|wg-UB~!muREK)e}0@ndodQufa-EO8Fr z%ZkR=4Go@g#^BI8Wo2*giWR+mD+X?YFFR{!-MXQnb!QCru3U+lRxlUuioK+sQQwPu z9)XwM67E^p4Z=O=PtvoWGg#dBrw(3nbGUB_tO1vXdoQ1yBK2(F;t@u#yWrAWF1TRP zAj^tiF6qf^5Qp+fv1r)J2u$EM2)Atuk0W2fvRCYx3ynh}yCo|fgz|rj$GRKBt?1v@ z@L;-o8N*!W&h+$zs8>13Xw5O*;=!&AWCOzk_O;lS*q(+k)h+@Ure=jy4ql3yOGk2x zVR#vEv!zU?m?`4K3UJ*pAc`c>#YC!9OeYJ5YvHFXH_StAC+E<n_-!!^pC4VW^s8F8 zI?9hMW?6pF)<L-lb!UJFAv%z_`ea-c@{Jdd{npv@N2z6Mzp8YrHEA?Fyk%Kg&}r#r zAqRE5k+B)?;wiKV$rdgibnJSZGd#QqS3hNV`tljb8ZI8?(}&JI_o7!WCTJ35uoehY zvU*BNHu8rNQ~0Vo-clBUR8pY2cto%V0CI|q3yqm4_mG@&+~yqj$r<`B%P)BSGGHe% zsdReS^j=|zAOL9;cF7XuEiac;3HdV;dRwHms;AQG3pvFI=E7BJ&yt6@p);5;49OK> z)-+SoV8`Dyrk`6}V$1`urA&7WE*f(=SoOM%oFOdM&h4i)X8EL}9^5?Ho@ILaqK3T# ztdfDec--#O9JjICZppEyN)@KJe`+#n^gAaDan9ta)sE-GG~1=qqc_PsE;agw4P&i~ z2A&3Uw;upgQ;Wx}k~?EgIp#tRa*1)bl;Ap8Dn*TaY3{-cci<Wge+$JM+b5z87a4n8 zD#@J`gr=N{BKhVLFyU}Iooo>-GfV+&zsCP23swhlF;E+T4pJ6K!i0=mT~XJEi1dX( z(^QqoB{KPZCYjUmLc0xsokj32qEp{#(CO5+jgZR9RMjjmwkln0F^X2N2Yd}88&iO~ zTf;T07W3%fX+aapQZ5Zqc5r2}qGmX;s8pk2dXs5pET*g)n(OMi-a=c8DAaWtFp=tw ze!g-ESURYY4fJxkMIE7{0J)eKz>ca3DjN8kwa2M6*MW`WwOVVQ>F<o59^1-rkd2y` z-qW0yKn8OO7}VV|WB?0Ua6X-kRALb3#^YlnagxT2@ez7#Ft+@(`DE!_<`MuFhS%<E zg;~5tSCzb16qs)@&7@@&M3KoG02p~i63I&<cXvJ?dph<Ff2Ue(q)hGwDtp&m)JAMX zBDY-S3BgE^TXVc(7;A?nde>#4(37tAQ{`$Q)lzg4B3!p>vU5WgYVG-AA3d;rcxuim z^t6_9+2TM&$ZabRPOr`+yIb*@fdH*=#yPMDq#8h-uLWEx?`VAarlB*=AOz`|nd#}C znYrTjk-@>~cP2n?c^Q4MZr$L}8P6{7!Jqal@35+7&9crs^Ws=&)bdG3ZHyTnZ3eDh zz3F|+7LSzZ1*-tj6~R%kW$9gdr1}nvdeI*qpAtk!hDR-dA!`V%vF3(`=7tuJJ-uC6 zwMyFA-agUZ-X6lU^%T^t=U*1l^``f)FC|sig)0^h*bg!gSU}(M>d<I|CmW4ajKC=q zJ`l)yp}?ZS2WSd1JI`hq?!5k~e^}L~=vq<fTntG~)7b=&1r2mUh#~{EwTx|S5T<^- z2lJ#*H8MHnPy#0m)(xXH1>(%s-GY2B*a#Fu=`{NLH*SoekfPGE3~YU`B&|{;BU?Vu zjd+7O@zdA~u}8@LBALcr?9sQ3;8L@EqmGyzE+jUuJCdoyTWjYr;$YlL3XXo?!Go`G zlN247DLo!HY-YV?NXfYI)vP7!fTH3?oRZ>{nsyVC#se!=(rz!BtW58pO2yS2%Ota^ zYUOi+6eD-L{*2W5Ps9qb7R1Fh0xiE#J)~Z1f~c-wX)zw>8NJ$Ryk9eSo{A>~g*I4@ zi<g+HTxLpT{Uh3>wo99w8m8E!NyWPi<68$0{(E0LWzd3I9!Sb|ryfrvwsPEg>!+tX zraNR-;uM8jzIOGrjyO*|@pKH|(ctf4in?JU2-a2IjL!7O`>4)%2c=UT@ph``Di4G= z(Vg*5TBmJVr<}NheuMPqcpeXnD8ZfhdF%yJOA^;-X^joX)->PVfa`{NMK8Px-hNdu zzZM-KMYZe|qvJ^dlz~7Y!`lUXAC4vFvtpl4r47lH9Zh4~X<6m*>xymLII+}9apfEz z-@Khxuhsb6G|h=wTF)1gs-P&}WF?+uv*n7W!a<6%EXk>`8ZA+jz~N7nxE}AxWO!OZ zoR5A-pU_|AG=?$an^bOloK7i%iRFer@xQS@#QuYvf9N5%sCww>6l|1^_Y?K59l*4H z3xHQ6nruI8log*>U0FBcWi8Gn%mkIwZH-A%8GS-tB?4P;H|U*ROtq?A(F@XiWniGf zjAjJQ?){kS$Qq0@@ot`?%{VJ(9ZIKj@eC)&89~(*MUmTD1f9>fzTZwrx=_$9MyDl} zWuS-4&jYxOzGPe)m8VY^fy=pcTGz`j0q*yz5;t{4g-4v#gEYfmk+gYruNya{F0Os; zF0B%-@c@9Bp?I3G)w`S&MNwEEP{73cKupAqyZvF4oXl}7B<~+<C;}sm6hTh$6#<PP zdjiqXgUk&=<u=jFAN=ellGI0fxvHrc?XswI1!R&$qzQjcYVOKpoeKL)-LdttGh=(g z9#d^#Xs}!g)^B!6Ew4Hh)yC}x3zr+z_uwv?)bo+N3Ic~IgZ`OHp4FM2ctOcMdhj64 zD?ry1Z;}*6<>Hw*FN+{<%Z6gbfl*d^MNJpXAu*q0GfDBgxackJ3UzZ(uCAh{CTF{( z>eQrmt0HhyN2&scQ{+aR>1G+qh|4<CYE&-6%5j>PHAPm%wvvbhxkA?Leu^mk!<Z8* z#g@f3#C8xWgfxqPIRGCh!s~{rjW<0Q;1l#Ak8c~9qH0(l|60r;Rinl0s)nZ98Tl${ zS)9%*EiB84w$eih2}P6yL1g%NLbQ~msKsfAk?)aVoQ{i>78j&0ydaZXz4{B~s*3bZ zJnrcofy0VtnYxmx$nBi;%4I1=RDsCLtjM|OAt>jv9Lv*UoGz6OTBG)DkIPxA3o3dk zZ;tA9?sy^g5aEtIS;Oo_R(vuxyA*c>h=R5KqMCnh@CJ(Q-qf)I;etW{^UoYScnOi7 zDZy~K#9AIdN9Shwma0)>wKVH|B{1>p>Nu9QJw%8sRTMNqA-|_5fgu;N36&Ex2K$8? zvZs&59&Oxgk&CK~>(;M@!4q`}-QGhD6q#I4yt|VvO~%LW9_I2YvXc)ONTit_U1D`^ zL|1v8?LyX3=Ph?|?dq6<EY{B&GV94#E3)7Cj^Q=2jY!I3BaIS{^?Jy4s=3Wn3-C}i z@X1J>pI}`gA4}vAY=;TR`we3z0CkR#^c?}#c?%&dqhNb`17@RlLDjl*_3H0W+bQ1Q z&BUNiFkCS=5WsPa5O#clX)>hYT(NCMeA@IGD88~Pm6stlVq=1@Qvt~h_v2k9Q8j?; zxcgddY5jV&Y#LU(STQZg*%r_10uSywc<?$;^W7b#YF{hsQVys_2Dzw$Y^2z%p-|du ze6^@Ap>$(HEJa}dK}<rvA|&hh-LWa+cZ8g)=1U|NIRBK`971ka${=pndvHk~sgp~V z;(WnodlX()xb~Bv^@C+~Uu<UGT)$vxg2}fPMOx<5Ek!}I1nJGEK#`3ZNXDOz9rvZ7 zK-Lc6LJ`?hAolW9r%+DK=wCPq=*Ne;B%Lj^SBJV!1|q)sgV?y^WCe9yY%|ipUiA-; zK^n`YKIfp|rKyM>k%1v{Z+T-=MSW?VoTc`JhUlPYIw(fqOcC)8Ljw-7I;&WUtt#=3 z7E$F`h8HLrIHo;e#i1l<y!4r^$WH;StvQ{eOp0HP7|#?xY%Ncw+L*~ww!{wr9U7{g zY+K*DF+o`r=rhK<q~4*;)oNALWL4q7KCpEw*k@*QY$3xitqC@VwXA;PsTe+ukwM<Z zD3Xrlh`-jyw#9bgQ&s*&E=_Cq{#`EB0Q!xBbAd%eJ5)Z25B&Z~MUV_b#x>tKUNLwJ z7Y<JB9G7&4qj`p9;wo*)8l`ZSW||s$Jz|=MVVYY_V447YOXZk$%QQ3%9Ncf4TCv3{ z$0?oTHl%5THiu`Dnlr3_$;y3W{lx1gHy^Xp-@N<IZ5Qaq;WgwAdJ*CLo7i__7FjFw zHzEWUrA8uB4pteqRgrsXt7<`Rr^}aK(%#wGd%X@4{cl*d3~cEIrLp0%HF(AvumbD= z;JWKRhIFug;upw<9gi8vuHzH;gJeI!EYZN8g(oHQ{ObLLt^|&1(}n_1TnQC1Wnq=D zl{-|<QnewE-TeJK0V3ZARmCtFPE!P(Nu*e{VrUAAlqHD~XrAS48mcxTW*mZS!7S+d zxp<$OY8i}XXlGkF%gW`Bb7O!ObWO;&h>k>CnVM?qP?a7~WaP=n<Fyv8vVF&7=iwex z+5eI3gBvC%jmgP2N!JXyiy7$=`g<<a^$XXIVqaW7aV+-R*cW0vqDu~Ed}`%tnMcHS zt5B!B3Q=yYVc4s7AW`;PSMN96T0(%FdP_X+Sae*4_*g!~=hQHV=woAFxOfwls!iDA z4_J0fxuv|GO_3K_8&zU4G!x$F#o*XTRFMw#ZlU!-ATYe(>H|6&lGm6x7<6!H02k14 z7D&*>V~y&<rVYCdBbl7L%@UPl(mPjhEcT*5N_PlDj8oa$ae<oZ7txP+zasVWVtqis zsa>L}GI1GjN?dmGt`-+LNnun+k8=z|Fl7?8;Ut7Sv-*Ku94|_`y=^~oUSzWK2jTh` zABvtJ6da=S0;)|ollyov-hWBx{d%I7<RQhVHJ4?1&Orv2a{(3S6_bt&rm7JT45hYV zH*$`R-QN3c25?=E4#<4Peiu7N&IYFm1m1x~-b*JoNRNDiOH*x%<HY;ZeP479H1c4A zR~d?;^<~n~u|36^iH&%$nt?)xQG}Ut;zcx%$4J$V3by7oQsdI2EWRgsq<#stS2mUN z>0Dj7-+aVwT%Y`c>sCxAt|bhZPC-S{EgnKQ;pTuSspeKrlXYMkx~^EMTp?*4JBI5S zfJ8iw0s+ZXT(_#k@c}n@9^_N0BqAE$QYzt^%rt`YuLMqu+#bHR0jW=k+K5LBzlP{b z0{gGF{eeVLux*MGvx&A(n~VSyqa7Iv<o}rl05;HhUXn&QSx^;Ck`+k<sT9<X9h(-0 zkL@ggj<L-M71)NHF;kHYm0+Uk2$ORG!X%YIn3T)qR&sORF>)K9=<S6bshc%~%SmPS z=`|}>xaWK&9>-#%*uJ!CL|C==Ew?uu{U8z5a!XKDaTTqYKVG(Zv@pXu_S18-vx#%& zUD+2-G>T1nK3W${J4q^!DF}xbNS_@|eV$4tUmycqM5IxI4QUj3ERC*#rICzxPf!#! z#}`E=CZTbE7rPUA-u+1LpNoA@pHlw)(v58Yi2p+bk#D*SB#^4CE&z-~2ZJ1j_;;?5 zaA`&sMF^Z?A(_l5hLdn4zH^&*LPwFy4q|l8vE}s$FE%b>yii1nFw;FXgAij`<~mw3 zVIt0p91G2a3qYD@HN;D4H%WKlNz`@YBGjFX8U>pWK+t<1*rf_GRz@64DBx-RzaIto zQ!23ECWM5;(6T7lz%CRK1!Ti@6Nm!a5wzrA*~XRs97o>avK)u?8^?P3&0ylZrD{v! zo=7alor+R|Ow2@>|BC3q0fhM(AuafSNrqRXs!01#1F7DR`REE_09`!cT^_pV2cfHy z39qZv?w2yPSbk7Ij=aR9-mR*&`i89<$?J}I>g*PGm5csecGm3lj@gwvb{yTX;iz%g zv<}rR(w`A6aIML5kP<bb1f%-fixiyWQ1NP_?Nx5YaVqYb<!zP8wvK6j<k-&K#Q3Jr z7&NhZN6Ebk)n+J>q>PlYk?<APNMM{Vc%ARI<MFs<Sn)V?+<3yddwDw=tlb-9wEN(} z?$M(+-@Gsyi}d?nV)r6^TFHuIKu?ofsT;aF8oND6FDuBkWjUi_K$yup;IIeC93HsZ z_6Z=Cs;#Zeu)SOA>FepcH-e%bw!p7|9>CTMIu=IzEb15azNg?6cD!$STkAyCL(G2P z`)t2U8b!*-Q2cXmED<Y_tZzN!L7HZ07@4P$`qIg;$B_QI#L3j>rx*!4p*dR+C4o<Y zl%lq_B+?8cE1*Nb%11)ZPF!+{i-VLZt-5-gW!Svph~*?5cjFW{)>DMAb&A#ca<ZK6 zT(_WV1sSVap7FdM?!;eXe?su%IDaSt{>9)U4dStdW7qlOGakfwo5v8h<t4pRb~6}Y ztKX*Lc{?AcoMJYfDF#3kyLJ-@)qV_N$NmF!*PGwm!5%nz`|U&n{x$Y%#QRn(k0PvD z&mUW0j~Xs*%=@~G(9b<J<*&lV&UG>w$5AQDbqxcHtZuBMgWwZ_SIQp2Eep1kORdnP zM_z@kZ9189#Q>SddkR4$NR=Q2`O`#$5gu>$;!X|ZHFX`;w~s|JsA1#-eBgs6gSt-Y z4Z_l0Y=)(-f$m58XQUx*jre+`E@`JQ4Ht2eD2e&JlT1Qeew&MYB*Eo5QN+%JpaU*0 z*t&6_Ma#NoUVXJBAo%a!YbmO=XOC`}){fgu=s1Z)1D-oQUaOsQ<S6guIpkb(oM(Yh zK*M3<Bbb_cQzO{G{!D~%*%R_^I3&4$BCyP!7A&U{+dny6Gho>3w^a2?(a@UwpoY7E z{GbRpSJXw7=RBW)ctsShG#dLofp^7ArCszBzYm8ggp#UueS~?(?U6K%iexB1-oUVq zoDQr@g&91Ln2h6nPBQ>YIPDE6I>);qHC-`Nc@$vm1+t+x^ICgzWI^E@Du_N&n`P3s zq^E#yo<v&|4!1tx5sl?B(dx5|*sl?HEfL${+51!M31oMMVmnC{_>p0pfcIk;$niD) z?=Yu-ssUXTL|#@URfZ+{B~I}_%Fq;LK|rC8pgSKp?HQ-ZjMwoy<8Q?;nh!!aai_}` zA!JU6OG<%R`WtZwL7Q=L@i7O#VQAG<PK>J=#|=~3FdTP1e$QYHRi~=afQLwZG(<0r zmqYNq=G3em0`+t`9YcH&SGTG=<M>XOCg^=<-u*l9{R0YKauY-m8z+fZR9TggL#|X` zq5!;G<$2U7bF9n@k|L-qi(JmPpROP*$N|QF_umKmXsK8V<CfDEk0nq&wU`9t#N*1p z1CC2!qb(smOU+Y+7%fOq5$XOdrvvXxm8qqmKkL-OwFDw36*62C`LD63kY7h5A9D_S zcIA;%%ZTga-9vkhpU+k~n&AB1OXW+pm?(;1E%d`!8bz_9iXhcwsmC;Ag*6f)0H(p2 zvLtcn4;$L|Kk&e{bNE#F+?*+*_e)hBU%!5rDdN2Xf}#nk!Rsh!U~$+X=y>lfjsahc z{RdfF93?Umq1CXD#n<7bn&8Dn%e^GPNiZfI{jSSU1y0~)NtQ%2Gd7}(uqME{9L0ga z5==!zsJOc8CT2Y6jl7ZRF<3l1uNN&H=}JM8Bwhub4?OS{8~rNErlpurwD3m?Bbf%U zBhwiO+cd)VF%)s)yJNa=?Fv$h&c77d_W95~btZPe?ab$jc~f;92;XP0(b-qcn43GA zPG$0EtpS#0z8}~Q0Pf<%Ys}BJ{)Ko%2_zX~evB35`)Ej)0@Q;OCm>Mxf)fxc-AW>f z?4P9Tns&X(@}^=WOe86?ENGSm+zjFish*e+FyPso54d3g6Q<*FRaFE-cHF@PofAbp z*2oci6m5-76aJ5Y6v@L#bCh~ADto|R>z0y<v@3DCp=qr!4h$<!;mn5X{1YNMMj&a( zVjTe|i$qtNYXTf6J<5`o^;jAQrjZ9J#@b>ve|>$)Tu31GuTv4Y?iLlC7g0IZsG1O_ z^N#f?M=DBA#fb|PMbW|;0nGG8SrWWf&?TFO(!~Xl!I1I@(myuh@ENQ>NhBT!#jBx6 zoIfR<eT&u**FRcJoYF*6(Tk7AU00HD?Fd0xV<M_Ms+EMgC~7KiSkQJ`kbzUjD4tbK zY`Zli$bwvMDYcq#@U@zoz(KlQ0XDQiim<+D%9!=3tR%q;?0CXncUv+O<H;=im1t2L zS+wOy7wwN-Ue~5g*@iHR?h>lW*Gn%2fAq=sJC)8Zq-rTiRSij`<8c!yVh+W*3_GsM zJn~UQLsex~LQ1vO)U?ZFCQd7&3KS0CA<jvfq8NZdUnx>7%}JI{@hXFq^ZmM6ZfPy) zc7KB~MH`<H6M-dJK(KgG&@(QClx|u8q^P*6sJz}pE*osR%}(H*6&}4j&E1Z4*|yjv zu`6S@o<xKH|4GHacIc|W3OwG=FB<8#|8IzjEP}!N7D2N*|E?sak+nF6ti_#3)&^qB z7Ce;@fpU~jA;&)1Qqr4%rKn1a;v!qeTMDv)RVCrNmrzu2ZAnAQ*-&(ivk}aK3`}I% zBn#PZ5h0);DKgmR^`>;vyUX`QAJV~7!x^zq{AOSxKc_`@k(46G8x2i>E4i|w>kdH9 z2M}$0DWIsPC1hNg^jPd!0?qPMLUXD-&bu&VQbkDsfM!pTWRGl#g*1+rc}2i9(l`W8 zNr1>e*g-gxkt<wO3?S<LlE6FjQm7a0*S*uSq5v*8@=>gd^HHj|N~023MG1sqrIv{2 zbVS?dh`r5{bwDK4H5YI2LBE}x0iUZSYsmsjQB2{}i<u5DXdXR!^hQ&b%^N>x(H@tT zTY{^aroVzBdArmDBS)}QV7T+$#?AwX*r+kg(GcJ8Bzuqh?{4mY(Td?BHu*y>QA-qQ znqmukL_aA{Rs`KbW3AKC@sc1OT{b1_#(Nf)`<gZ%Q2xq4hNE*yJO`V!olo=Mc{s-r z6zAc@DDQ{5bR(kma7UvbT_RV9Y5Xk7SG$W=+ZupenXa##eH7uHED*fwLCS@71W|7k z>g`2>Np2A);bnst2?-fAVa3A^P34??oU)6Vc&4;4VPsXHizcfAbWB6@^*rj`Mqbm9 z*FV27#%Z$U^C<ur-AcP6ja(zykr^sZi=Rgvirf$d;-c|T(eMTt6?5n<ZF`PxOgibr zx^>BvlicXDYD+oDs`wszggJ)IBIj@sR9L|v(0st6c^1Kf0xba2u0}Bk6q?dr=BYp| zvVidJ9wl?j(HrpiiS!L&4rUQW{!H#M9;=TEBS>;8rT1q92Td^=0z^c<Se+`;eysH< zF*<pTKr<3T0g)$fBvb3wrIK!9<2}KZriJ}AxL#Qdd6GvFmo*@bn!8hJyFX%z(M|J5 z(+JXwmr!>INI8qA&`Dw#K>@)SDGK$~2^<ks!m*GCFSi)rBMTw^r_vUpVH^=L<w(f! z@aB`E#RWM*^itCZ7B|tL7aBK?#yx>3<J9$QW29!ngyrW%8Z(bKptdmF#m!4@N9&{B z&=~V*aIKB<cX?qA(6(sT(a><+V<X{U<183odwF9q{qrMP<k^7ia4y%9PM34}M)tx= zjTO*qEM?j0!S?R%_Q7;RN8B4rd%5_fhlo@f!&zW?gO$_imR#<pX4Mffq#Z<;RPOr= z8XvDtjK@~QHpTXy-g?TZ{82ZszrGsy{eN7BWm)vbu|%pR9dRadJ?}JdW==B$!3}gs zaPvXDy&j*mxRd-J{f4Aof_wMcqOR|)Cm@%Ia1!_n0($xX#~6FNDvlz~c912-drD$8 zFN);tP}sZ>>EmN+3(osUv+r(pXS0RYOe&wmTTI=IVOr+Dx^bi>u!VQzI1OB6;8kqu zk0NIT#c?gk%=^c2E?~nf-kAE9aT{WLZ(D2YE34#=uoq)bp}Da=OBj{;<Re?3;&l}T zt(Ix1FjFXG;emRCsiB5q2Hx68V<Oev!Z-az&h)+*dj?5?i7eOPqV?u*>=K=neFpnD z3B1DWsyL1%E6loKoQGhsKmZoJtX#%d>NHlB&u)eXpKZaK{eF_ati;yGc9Cp4Qr~V+ zLZjhugWF;3z^0kto|)m1rS{3Zszd3R0~T#raR?Gyc@b}R!-d3jH<7W8TSZAVWR7tq zMpuv{pmHLbenXd3%;@OFC@elHBnmu^LC1vtV>_MN_&JtXuC%ry410U~dOpQ#sw`&{ z4y{qL?z(Yalx-so0g$ZS#5vUUixqG06{)wuA*sbX6>KE8UbU5I)R(Ga6llL*uuLbD zOzMv57ONe_q@GPAa=C<?OW<8R_$J?tb;<h#lqzKcbx&V+|0{4DRBCN4d4@l=wJv0A zV~-`~pDyH`OrMg6+*63))mD(390zd|`B&-5WQ!Ffd#-6%rk%7*%UaA(ZAk1&+#<0< zGUn|r!`Uai2WJ7mPzDNl4VY_ibTTqR%w7$tzU$p&wxwEdEHvjJ={S;-8@#4p1ez>x zqRtCF30sUKx7X&y-rk-*8Hg>dB-hmTu9QhxaXayvl{qD4tRy#~5NSUagJ?!WE5+FG zdTHxZCr7V!P^hjuP8^ZThL<6|swNG9^pK)zmH=VGb#hP=H4~{(J3Du59Pa_xgST=< zCP$eVjd%^`81W4|E%-zs-i2!Wdr$Gs=UV-U|58f-9j+@ElRbT@3V);PcBXoIQ?2|r zFhgO+y3spE$MZ)wCq~y@vWwqxbkipM|5ah-P43De9v-PjSc|ZTL2&-;__iM#!));< zuDc>Ny*xE!1WX`u2=;8gV5f%fLPhldG4Xg7?=SPKEe?(N^%e+UymrCexeez)A(Yfo z2}QzO-R7@nY-f`sWeeseMa4IEKm`9YWKVC4M@RQmdHYV+{VH~XwZ;}zDUlJBlx-h7 z)>z^3wsQEM8?qI#?~^gy#beY1fmzpmi;Eb-LROek(yr_EmhrcQa3mUhk@SLZADWGA z#AgjiZ~vG3PnS?hIoJK4sBM=C7jHbR*Uv50w_ScN>n5@}#LBKtw3MbFTk}%3B(4bQ zE^;GNEcOF}v0kSe4iJ#ABMz8x-M6KRrBrVhzQd^d*s+n3x!GE67O!fc?>**!ug|lV zNVf&h<WDun<lvj*tf~tF4DX)t7GS#3EI}d*JpZAnRoL776{SD<(4=Eii=hb;{WMna z9p?tbYd8!{yNaTy=szXvZ9DR#>xFGc$6kr`F3te@R6QpuwqX4;4%p|c#g-Fmep)`~ zN%x8`?Qmiv?BF+&0+D@(^8pI)DyJk9C)!QIU#ci8-{k$*optpT;cc!VyUt6kE#>uM zB0;i%I~MDzRx}eoLRf0#p3LU_EPv88*N<qCH6Q}dw8c;0#HE+evQP*o`U$N&>Z$wJ zkZhY+&tQqXh<;arjiXG@i@TTj2#w4d3aBcTs8Q<)irV1F2!ys_@@(4D(@p~LmW7<x zE+dypeX}Fi;W{iw$qwg8$fp%pO~m(GN>If9t?eTJ_m10cTW{pp_Vr{>=!>yG5KkbB zYujRdy<pDBECwdA8kxiRFvXb2G&S;N{;SZGx=?H{bzxb@db1=$JC}1X4?5ettc9Iw zWG%?uwz0EgzlgoOe)FvT{qMh=+*xa!cp60q_mlfBiKbsTqBm4FesYcibdAw<fqU8g z;A5IXL7L@1gubVqcrNyv*f+`Do36K~9#>}|UPI$3`E%5*Qd_&g(Kcg^)i`Y}z21I3 z(9h-=mdSG!gJQus0ua`(#gO20b-#*zmE5#OuIfTTVAF{?a>{Yb%ujBoF4r9ed8mpg zQu~;ENy}6|j?|xhVH*RO#MYjPq+!hx7=J-v%q^T*gUFX#IJf2<XGMrQSHm@H<Eg$W zaoIr2lsr)=x~7wNuX;~srzOP)$~olXmWs&J%B0(cmSnz<iIJ$`&xqf?<li|Kt5@a5 z2N?_Z-6wzKBkm7>_$9CctnzLRKJh~A+1R(6@4+6bU2N~)f9Zei{Pt>iA%x!T&K@1q zIvwiOW-dMJ$Cvb%v|<ZH*p6m1Am?6*p4SkT&!Xq?orDNKOr~jS$oppbJ)<;N&a0`s zJoDp8`0@3iJYX1FwSOZ3_Y-gMDdY_vBd28v{G{ToU&@6H3;uIEFFBPyeZ{~fZ|rC@ z%Du;+s(<9JzLMUvv9r``baoQSdm3@qanwr!ugKQ8`n-*h^N%)`0K2^A?X=};Ii{$h zV1ao%eBTe=`OdfZ?ruS|CYux2wt@qI^z{ow)dx{eS)V6s93S8V?{p#3i$i7j!$W)H zvXIqn%Fz{>eIFd!cg1RI&4ZwFjSCs{U&nbH4<58#kN!`Se$&kmHhLWLrsOsIDII8e zrlbly{c$+D?}vxZyryk!mIIvLzhlJ#0NQW`P4mRFL~hjj{i~!9PNOV2l6&;i^%1@8 zzlWr1yVN(no!jE<=C<E|41kUJHkwavBy){%Jx=Oldfz3*e*7Pfub(K#M@7+(wVq$T zigDOI`}nJG5HE7F2C|YfVmX_D=L$SK_o@uYQfZI@8JM+2(aO4(teOd+;2U_g6Te2% z@PL0m9w1a8r#0(`Pw~$~)yLZ5CFJ!0g7nx-_oY3T^^m<yzm5GGQBU*dn2>9MTN)>L zuRZj`Jq!!m`i*6~suiQyb<=<S*Jl9`ggY<qFB|PGrEasc<3>Es`iVcpo{K$9>aF|o zS^x1b-zKGnaOFU~2&z^;=<nZA{pgpA@9BT@z`!(mfgL;M!E0BnSb^YEPy7;L_ieu- zXZ`;8U~k?If5JLL<xV(k592EiZicxW93DPnc=+EZ)~=nJ0=KB@E#MXV_wOgSVxn1o zKK77Lulng;k8H#EXz9b&&b1$^O+J?2yXxF?AF>p>8(ajy7n!eIL^RryB&S&QDhC9Q zrv}c>;?9PLe2w=re8_=yWNtMTFBXhMUhmXKxD{|0b@*q8;%~f5Q4v>5uaKo|tDeud zq>cRO+diyW$XIILdd=_2*<^e=+znFIE_(;5y~DEl23UX_e)e^!CxG)-D7hk#?n5u| zA%479>KW=D5k`Bwot@94{*EIq_inwd*>(f+p=!+zC{uj-c=;Y^cIg$}?3b6H1L+LZ z3`Z|oLjyni+3{IsWyUG=_2psv<nj*7G#v<yp@KHJ;XR%_dFOsh<UWGBh71zTJ4)Rs zhgI|RQ<b1~Biy!4(o}^}Rem>{0u!qQ&Q@-Cjpfdc7t&fff1U|D)V4c%z-nEl042|Y zR0}XnCJS0pg+$RTrxdB2F;e7qz~3W%`rVj=yomn#d1LReaJ^K>@W^mAx*5avJ*&{t znqxbM*;FExVal!rknI-FwhFD~4BI}4nv*G}=vY=hX-Qjt^rLt2lO<lzHQq>+SQ-|G zx&AywYbHNc#?1n1rYTq$;`;J&TECgp)|Qd|eFoXKqJJ;Br!D-_3}i}z#2X&*^hwqG zrQH1<JIM)2TT7;4i#D7>qp5~YE2frD+?3dsn2<-n^7s#b_)SMwkptl939X#6IyX}B zi$#eAEOWVOw1H)<Mrq(G;Bz|OVckM_uC7YSPw2F^SFOH%!>+II+PLxH^{z8IB`F|f z+0xoGxq`dlf(@@P0Z>B!^;nc(8e*YM!Uw6{E>MaEWU8fZ8=4Er`{hQ7IwK?LKf7Qb za?~s~q44YS@LHH(2lriY4CLPE)rP-%^U#_#L!00JkzA~S$3sM71JWLe13uPYt`7V_ zs`hT$bm)559h;WaCQLR|I=H<LSu9fmWzYjC!3v^N21VK=deFmYz}q3Vq@Gx$G<-Va z!U{jrR7qtmQD~tUsH;c{pq8d9aoR-Av@Bqw+XkmL{A><ZD!1RRC~**%u1Ek~w@eL5 zX?Dic6xmYc9QxYW8{Ss|pi-%j)0j`ieu=ccN$$TcHfX+3y@6;`K2WNm^x*XDr;287 zVrF}xFsurISKkdp8K@5;KPb`Hsg^rCSFKv57*GbL$ho>?#YioQ=Mm+Pqu*RI5}tuZ zuYt;UNCWVp5jV>`;H4{US)EwD@uzE7y-FV|m6kyj4e&`@w}5?Iw?v@xoNa(R0QzTt z=8kl^Q|hP)e1B1DBYG42LC0g2SQn{EURx+*L2l^tYxh>`SA=>hH3-D(4j+)!tfhi< zrXuzYsXb|jPPK>~2Y2m)yLYd(WJ|K%Vw#q29{?E@r}8vg1X^GFW=tDd+y`b+tOW$< zN{%f_DP1!WKVFHn;_b+)`Cj{#5Ptio-WiLhV!uQ1DtLeEh`YcU!`K0RrOlRCDJxpr zmTTR8Dul;baXR5-C&yZhbl<?6(D$?G`;Q|&=ZTl;-E-jEhVOyyUVG$~)r^s?KBV=e z?|fUaD_1mIb9mfg#H;T@x>0Q0bn2B`BHw&1goUcqTN+1t#Yuek@pF)Iv7PNOZRYUp zHklJo#2!QTUT@qtA6domF}Mb<g1h1FRjYQd`IqaAoja`?s?}YHWr#=r6tc$;dj1mh z4pey&N7)XQ55Ygiy(prkELxQfUfwV^Ha7?7=BB4tK6v0jC)?^Kx?kN6TCH8XtX9xY zys^iTPxpv-C+xyy8{uBFyHI?*dGnz|@W6phn|6JqT1DEb1*}?y-b$ECNd)E3iPzxW zE(?7lfw~+X8428(yBn^RCmA;@0v8OyZixOpbi;I;Rp=E2@yH>LzwDaxZj^Uo`M@*w zzi7r?|F)-UGmHUJmPdR_)+t)uWN+HE8?LeuSvSFniOmylTeWJ>s(WpFm9s<d?FD-r zt57IhUn~~A8ahv+k-kf6_O%lmI2@ZGJCcGPRb$McKB|vgADzdJ4OS2kzm;pC0}KvM zgHAADv=}8d4<>7%P^fi);=YcK$yTO)th-~Xv-7h!j-3E=(z0c3NhOh0)&k4LuSqbi zD#;}JIdLN9AUL0m9j7W+JQs__xGSEIVGX_+!TpKYTgffsgewoA@HpN3*1i#CxF3CP z`jXyV$H!0Wd9kaP*lSX?b^klR%3ddOqQr4=JFc6es|!Ok=K|FP)|fJ^yD1T8^HzSO zwRP_@iC0s60c!T}){e9Zfo1fSL8;5sELC$0F|wQCNyN!tBNeS$d|!M~36qh!d+zx< z->z0ANp;zj$X&`8L6L2(B42$}L<U*>+67>>qS6k{&yKdq-EH843$|%)n$J3TG{@(j zx@Prn*MSRB&~SZ3zd8zeFRh{M`1w3=RFyS!RbtN+w#)0pxx69SqJGej98tR?Tdihy z4_P#%rLp1t-Jr5#BX9)AI@d``DUz4bi5K|@nv-OGRzfvu$<K{4XLHi_|2S{kHstJX z-FnU=n#Egs1q_3g0R0;#r(#HS{2g*bR&_B?E^s8VO^8Lk@e;joE$r(X8G&brgK~#B zIMRFP+JucJ1pafiTB(55V9S>Nf|Y6otI=y*u}rAONWG;e(0E_Nej%Et4pLzd$NBzT zx&HMvi|(`G10}(XpZw$?GRYzf`9AodrV0|P^TIG3Whs;5uIDL}=D!B)w<~HK#-$tY z`OLy^y~PsSQlQa$YaZES6>-fANQZhgHHYfdbQ?I=>#~w&@3RnfFkP-u7?+j@I#c6P zzdiMOO-ia-|FTS%T)W<sfn=iasHbPo9=K~)=fk$mC*ZnX2U>ZM$sv9MMZ->9W!f^d zE=Z+78XyglMv~QsX67yw5lcij`+10KAj7s6wM<FAe}_{Uu`I1~$k*e~#lA|Ss%Ed1 zNZj&7XRBz-ZCwM>NN2~avb@@p`r@u?`&sPSeMQx_N>u~s<@U4utkJVXjz|pNlz13v zTo;vpzcR|WDcxbyy3Ppnq`H#Hw3x*-)AzM?2Rpcgpu$z_&RU<-)2ny*e&BBr$GV<% z#IxJ%idBctg{-g@$Sp(iNV#L9cy)G-TQF*mFo<#Jnl+km(qj`zr*vg|%INa*WzWaH zPJAeAZ@n^~-cFpx^;S4*hWmb4?x>B9(4*sex<#iUqlvwpU<ZG8p)4HwI^fs|inbW~ z42G4mTr1v{vzfN337WDQyr&EK3{N8oVe8P>gOfTt;+9Kbc^ph`ghPX)D-_MjL5Jlw zY!KIdhu=IZPvnG`wNbhY#kM{X1qKwDB6%6?8-J@wiX-OkMiim4YKJ=7rvhcLWkeon zZ=aSXDx>DNvN^7hfnyV08`&)bSqIuJB^S84(Ul~N^(2Y^a-?q(%^<bRm%OstXcB8R z!r+zaRVu%IYOUGT)61=%DKoU_7%78iwsd`97cU=oQr1jOmRuCmW{tc$)&pHDM)nr` z0%^d9iB<FFG?-hooBkp`rd>Yl(A-WHs1|K$JVRafZVe~~V=4kmy{nVmaL+vt^P)WJ zP!^?RH*CzJXhI)4qP!FMT=^S>O`^^}O^yU9IXQeL!totf?caas5J>S>QcGr!vxWvL zpbDlwDW#y{wvjmR7l;!dLh*Nr)RL)3B~5u+ufo`X8wm0LkJLVJ(M7lz4`TtAzWCy{ zZtmPQwhk=&W}ra@JY;dqPB5z}h`$(N3hbccz~x($QZA9qO4$_2sbDGiHmSW>uJe*x z*Wb9r+oB2jFLlo)@_x=h?yj-=-)ft4>wDQXGc61)IeN<ExOD^X{I+SyP)ulsZ0KdH zzhEFgSV-z=d~6*@-@iZ+$MO0de9?ITPh@z!P}xX6T?e;pk#$XFG)>$n@zgoXg_WCW zX2meD3r6ntWD>yiJ%iQ`U8VsopQ(1YF}kI)rEH7TTGR`LbgNb>)-CgI{G3lRI_u*R z`hGCC>L2=MA8S8z`ph$vW}#c}cnD}r3XB49C3pSkRy7BqL3(`Zlsyt0ntI&Qk~6ZU zrXII}q?rO_X0RW8ocMwyR^=D8e!v!x`Ksaj1H2M}-w}7x?2#$EPa1ct?yNLouUOC0 z`Mj_%4dEsT^LiQ_w<J>sMIC^?Ufom+Kr?9yutyFb?rk?srHr^6SA)Y@%b{jm>_tYf zykOi3i~3RH@c$^)p0#T?Z{DOLTgYfUKLH2e>bbeu*=k2hw_kqT<QWIwqCG3iNW8?3 zZQEAv#Mf#=I=*&#SnD6!OA%kdvxZizKx!P+VJSBxg7;i){~`%|p=MC+Y82MGk4i0F z2M)kPhstf-j*G?tNaXlZdi;$b1=VDUm4JYvW#rG<>cb{SJK%#K1U8bDvlBPuL>}@& zv9m=s4XCvuG0Jd=$wirD&O8k;NNNNI=ybA6{OYCi>hg>TSVeyyM-ZNUb`^GYwQk8z z>Z4^?8dnEfHkR7jVEf*^<tn#*xH{E-++=BBW&yCWR>HQDxfLr)u4&~gyhAT*npE7n zA&XzJ0DO4A%4~Dx!UdpClaAhjpzn*VJ?Ed_IVFv?!j1r4K%&24d3oodLoIFGu7jfx zCbN7oGx}PXu$5GvMdD5YS}nLThS;{|dMs$SubpcLrqexV0R-ndWlj`PR4-_`geV)T z$TJM5a<(KWi2sr#SMW6=OGpnzc<_jx>3iq<(xch{pj<XRkeWl*{?I>s%{;3ni-M6B zijD;g(6R-`4DyNJ_|ZSErP**GhIp^zq2YzD{e`XX>j_0?OiiMhLwZL^v3bhnQ?q8P zTjR&!KX1t*8z^a=>2r7%FXTyOS=RQemcC(4%=dnNOLCpDg?lcY&_$PCU1E&LB(f}L zvVtnaZAuhUwzP~jVVhjG3})hPH=TCh#4!ruSy_^_SI_2K)0SJ#jgTzCGqI<T7bAMw z+sm60jj#mG)&Thp@3f)O#@xQAlIqvm3<@%dw!~~+O>8*y2<L!2P%0&Jswi-rmFHU> zU6WO3m{`1LiAM5nZzXl4n@L$7id-e^hl6mF=87_{$Rfpz!9i_wLKPUmCfBYM)s#^B z{FuIC+CD26M*)U0Xzbdm@8c+>wZyW{F#0|oh?t)XNEiHf>^@QloJ8F);0o6DtEaaM zU*;@b(^=D$DfVAF$|bp6KFo~G3G42=Y6C<el##zFAvu;S_gZ<^aS(QSG-D6>-iep! z9r21|kAxGzAAns$eHEUzrFC0`1BKcISIU=LneHr1R9ceYlfv>UFPV@XpV4f+SLRKp zz)~Pz<9f0b4Pz*-waH2bj%$BI;@THt7(cu!_#}Z~!7jqE7t=^m;DFVSd=A0YJkzfm zI&uUIj;43QZQG`&$9Z;OI^}3i@_4sNRkRg(9KZFSa}F2;b9R34avd6uPNHnACmu%7 z{FXq2U_!0xiKqS8`**0da>eh-XMZ4{Dde*U{Li>6{usk?6eO9%V=*D7k=pWIe$IMf zr4e5$f#aw;n>L4{iHAkql({bqCQ($K=(vQBLvF{}i7m#O#DQD_wYk@}m5f65nB}^X zX{kCiU45hF_Vfb)`ctOex{)+(04XyKFr2=R)}ZsBVhgR0pw>SJ@U;m}kD}JUkk-GF zRui@Un$YG&()t&lHdwlG>j~U?B<8pN!lxq{?FioYEt34|pJI=a`%dsp5jfAXA~r{= zXt>13YUEo(`oYhIj`$MYobd_&e-4N{IALt#S!Y@KvPPS<B=q$-+qRvtN8rx19I2BT z9X(^>HTdlfGc()P-i_ZL<wRZN*GOwbhUOD&N)!ZHLx1vuB3j0%EXx)2Gwc7~qX*Gz zROJXoaHI+5GQqq-=OavmgGlQUwoYf9y+N&SAgih*Z?@p$UI!J6Y((I>`@iCELqN}` zk<|YjSpwj5Q)ta2{f$bmrdk%Q1EsV0(XZM0)YX#2Acyyr$pjt`pzq`ScBQd`Qs>FA zgI!Mpb$_5GCyMKJ+p^>pvLVZitg`IIhtnC=2D$XD4_YOQW35z5g7$gHxdsT(vw$XR zf@rwD=Y}K8ZtsSbk@^J~WUA{+l|eUZ!GRhc;qjcJpN(!#>2potY*8FYr{R=r=_+Fw z;>L}K4=>v-bMDmC)W?#Bku6G+p~*d9OfG9OBAS#(@p>94N@qIVlTMSJtDYa=ap2fO zo{#X|B7laQAVPZ8=dx-b6`nd9?%TI1nS>LvZlF0cSZ4e7i!a{3{p`!}1&T8=Z}HL% zmLQwTmymF_w}U~^))mU88NmPv;DGi?$C*i-r)Ywv@VqWdGJ;eke);i$oP@Kqr-Zh? zUQzSuh<^<1`ki^^cGrb73Q`da035S-@1a9`_iov8pfWYJWqNvMX6Bfp0J)|VL5H9r z{sR=ti$Dh`B&^Aus;Vy2w4$!p&jLLc`!v}VQoqT(+;a4&^Yfp78r%s;g#IMSS<v3j z0UPhP55;uV&wh5x1wY;|>1bj#WaqvHW&n7ZE+fB!5xjjnPa)lNpYH>eBV)pH@!z)` zI3Qalids?Zb>W4(?nB+|AY91^TfhvijfAB0SFr~WEQug20mFjL=fFMpq$YoImwJPl z(hUykI>X=k0GPC_j@4O23qh;a_Y&b%z{~>Pp?<vW5rwZ@A>H*B;TF4)%yPw~%kr<& z#-^pwV<`A7oKa*Ur)XU@Q1Nny7|$;+z{f|e$F+X$bIwnX<g&vvvWj9PTUfVF>~ME{ z84Q4x8A?eyLR-I>(BrUul=wxzL2<)Z>pM3{pY`n<Rb-Av%DnUa*GSjqrk;G8IxpnL z@77<YeHE0!6##S_7atxNh!M(Re#DT$I_11f|8RZtP35znedWx6nv(hDKc9eK22-tT zl7^N9lK{Nh>){22TQeL@yGVx0sfP}0=NA5F2n>yBo0lEf{8cb{F#x;3<cD^V^Lr#a zd7NZJPa_xV*5E2QFfcj_S98O1H#a&~yK~ihd(aCk16#Ka7D2iSmZ6ttv7bj#-q-!z zO}ejR$quIxf42xGTKZexa^LeFcqMub{P2fg2bou_%x%tZ@YeL7M|}PuqEE`-J%HEk z>y!@Ke&5C)zm=jdON{^cF83_tBc-I_GqXwEO~>;oEt!1~0_!#u2M_iLGh0?^mI2kY z0d-p^HI8w1?S2BM@Bc02mPr;kkQ#9wUb*@4jVrG%oCOus=j(J9vikktUjg`6^tzoN z?vy$Px_Y?&4q~UC!+9xWr#NE0@JTk#-~IL=S;<;hk7-)>Ci-TA@+y!wDv_g~U8{dI zH$J}M@iWH8KwH~br7~ZwPPC!dXOS-4*G}H%NAYXE-P?omYk#bKK-L3!bDZHFBEhy@ zga5f|V&aU)*Nl$MZtt9!=olM)5OnV90ib7R*QaI%rkC{-P5LbA@fgWQWJ!b?X+2%L zUKxF)ws=Lv-$~H&iBboynMzBFSW4eDF$h4hcw{YY>Z+!wFrlP1!%|E`psCuM9)J9p z4a^Hg2}RV*Wtvvr>>QfzGTU>wCb{aWmI5@zP*fnv*N{DPYHSyR^xe3w6v+w_L;OmK zJNWoTob+xd4S);0b^GVYJ{7VmN#JX&QR$Zn5>SMFAARrV%I}4y=p?}H;BMa|dmeja zM+7pnxONrhq$jZV=HDpP9_-HzWSd-fF-5HXtYC}W{vRzfQte9lnqped<Yi!_dIyx{ zmA)xyx{`HFJD2>puJDEhc(nk5k%1{IYnO$*o0e^m%Ii=~IcYUx+vIFJUXgqlY1EE7 z1r|pigeXk_4Zlic_g!bD+cUaiWM)RCnQW=T<m@vJv;1z;aa%HGrloJ4v}(h{nhEkY z#p$M2?X`fN<Y;IYfhwP`rJ<WLvq=Oa?2GwXtmjDvwMtgcJQ@dGmEh*Xx=effb8e8i z^H)o{Brvkfw$WU%pr&&2#tT{LfNR*AdlT7-^e}Y6U7CWzT<NyuX0A&!m14&XfX0^A zE~yh?)>W2^Bq#a=(oEk$bCe`9(clc%&$arS6MT8UnWxYB?k<|0c6oK#r?Mb(nX+0& zMn?LMssbQO-Mk4vUo|fmDx+3{tT|y$Fo>1LoPhWEwFbxGeI3Y0NX;!gbKZX+V%XUa ze$c-D`j#&j+f-H4Xjzx@sdqlCXvl9AYU5^N6k2*ll4wBDEsBEp(OVJ3{3sEAl!>3b z(5jGDwGm@@tukrVV%|wVycY7P4{?(4%mVlNFuRQ#4??qN9-<hVWA^>H`0jVZ`S}mS z&%nan%Vi6g420s^FNr)SDW=+QnBDz_TyMeZ*04Jwb`U6^YJyUagwh}qW|9>=OjqxA zhlu$LgXU>E50l|w()ZN@z2lo_(cG*nN~8Pt?v*TArd37QyZ7KIhs2(rR(2@)id4L& zHLvGd9@fZ&cL+$)<iL<B(-tKRpkED@Gk|%PnKFQy0tq8&dbIzg55Gy^xBU1vh->8t zAfG`W<7d4n&!>a!&*867D~cYEIHc8$d08hM34E&_>nv=fo40$W<qa8kn|$H7Mv`Y0 z?6xiIdcpK=^qpDsoev<|NsV0__#1BmvI&7Bjy%j|GXHW%3W6~-s#K3}k0i*bNdk+6 zWXEewk=BIY+Wc(VZ+#NqHPdL#L_VAKqr9i_&J5I=Bdz(+vjx&xY_vX3sO0rfYP5Qm zwoF=E8Zi8hv=&KgYvWlj(yY|`B{v)5T`>>Gl$b?)fO=YHVKKC^3GSw@X?0_pMbQJJ z%4k2{(k89>Xh+#7<zD}ZzMR=HC^K|l0;WvM;azLk8qetIPA_jt;31xd+r0P2%d~sS z=X%K2MwP+go(Xy59E3aJnA~@q;|EeOJyOeCo$YtsIXRHGl9f6(&joO-`V@V_%Of0V zBdzTLDlO2i!+-W!|JhE`+U2)C<F|H`*3J-}dqQ*Kwf2Vi;`zXw^fl(>HvxG21J5o% zHqdDOMc~<*57|>q@D7Gx@SYv=pZ!(Sv%`&NpAI}b65=<nbu_>&k2G4xLZf-`j{7|H z1mPjPgSM~`pNCjzVO#c1-BXy6*uHUPcu>ZCwECmPOiHazNV!xx@%m5p<gB&<neR%% zBs3sz8+}&0gN&|gDXN`ABNqJ#Tt^X3&dXc|Ecr;)PqzDux1WU!mvc>+OpK^KMddB9 zm=nug>NL_^dh+<@HdtykTk_or6ArJKevb}J$JX9mY>``vQL;M`nq{wbvN6lQ4bXBb z^4aM|>o3V1Eer9~9|Jus5A{1kTFasNoF!Uy1^H}c;~RenaMr3w4p<%13|{M8qxFeE z>zWWQUhCROJ+v;Qhddb0h($^6`bZcyL~{4WNEkLn^6};vjszqWPyIgj2;$B3BF)ou z`O+&L9_h7_!Ja93O95`!aPEIsVeccH*o`z=e;-mma2yAr=bvA<2tf$8G$8nOp!Li~ zE6MvF*&3SXKLnoL7HGw@wmtN0kbibW(tKy6p4k=ZVK-^r6UnW68_x!<$61jU?CeJC z?*lOGi=2sbLNk1B2)E|~J)9TG4f|u>PW>m)vyUQM<=rA4bl=@3cObOQ{whdOxi$Js zzO+JGw*ux%TAQJD%0uTsDq$)bP;+L_qZ~u`Ct;><I0N&oWp326Q<X{z6uR5;vZMpc z)LUJxJm}NSqx^v;y<ey1`Sn&mcZu&|R!CKXW|;X#>L|R`<R+V82Zoiw!LBK3vw7i# z*4(34IL^S3ESs6MA<C;ZaQR1gjz!Fw7)08#qYQchsG78d;>u*%P!)}_>}L8N4B4n4 zeGfJKoM7t(ja+olmK+ZGITtRneG6LWqDcO|xY0vUwqF+MyIc~2*X!ZZ5TALxb6H5o zy*vcjbAcW%j~wlaNd7$%(1(vSdYF&YMX!iO>4z&r{a)210Z%qzado6@UK8>Ryl1bC zgyFi#XRi;za6_bq@t%EU1BPcv>y5;|+(bURIbzJpkz2@TuZo<lSBH4RgYwo!>yv?z zUlXZUUK`oN>l#pcklYrsjb7{Rk$Bz_diFN~uDvsoKko|B@AaX6gLC+XNIrUFgEu^$ zdsB!Dg7f|6NUi&p5EgGe2@G$Gv`PO!qTc$RNbHf<R~Fr7#l(jL%3vx7yXwQpdFz^x zHt3gL+WqyNlBr0Hs&czKO~*CT*JY67mVTJyJ8hWg?#Y4nqLl%&D0&2pxJ;E=9W9k{ zlSbAhJ2ap2p{ef{ZGt6mHl_)lK&}MA(>JD!)G$1gd%7>}-dP8T-}8=S%CxiR>TXfZ zA%NOlnCR(60BuSGkOs@i8jm<-*l8o3l9hsOnf3Yb^u^mF`NyN?KSs{;J0g9pcgC9g z^}Mxr1!jMNv)|ol{dHjW?+!@U!wt!M5Bcn$LXg}Og8In-B=3#1^Y8OH<9U+H!}cmg zcw@26;u~9L8(SLD`?WSr^-e0IgI(j&`ozsQSFcZ~wqcEZ=RBM&);jPpV(>6e)9tRE z=;_IVwkkN-)yemiz=iodSIV*EJwjK%zX9)`8rq0E@_~?+`(Oy;AU*#%a`rwH@T0I^ z|8S)K@SgpbNE!P`NZ)y_9}Us>W06?{uit--Z2fqshfgfR4Yz)BkwssK*FF{K0k?iS z^z82gqkSe)1AR8s@8<}&c^G~^(u+76(x%?CUkLdND@Z^8Mn1bYg#8y!G6P=<wR-aN z?~(NTawzWiTEEip$bL&sg|v{fiuKi>&@Qg#Y<2LD%wD)_SNn`K*#g^!mE|3K%NE5N znx^2&-TBvng+B_POQpc*YzAhB_n%cug3S1Gmep0&)OFR=v`jVdN48F-pxwJKWQV=h zuSU+-*Fx6CYdzLzeWv06SB~6IKKpv)d_552JuhN-FftzdM&wL=Gtz#3D`2e`yr^$C zdiYfU!-xD8BQhG%MeU8%|3x0OZxy^H+`zFOH*m7%MnE&QVR?ACeOlZEF1h4whR(9A zDDf?z49XCe%fn^Ra-3tBvISsUIbjvDz`RgV;ugc@`_XIamVrEeHAQqD4&RCNeZSji zeTLxcVRpPh1rOhcn>fCnz4Cf^Bt-K^L(&nP(eE|+W{>-G=Z*Ovku?5(1CqxAv-AVM z^)X*3de8npjc0!u!25?GJ9jUE#M93I8S<~ae*P=u@p}FID3E1ckk<bbc=nNowfiyo z?7t&<{U?pqpmzJ8kVWty`Dvu@{j*rJ6nZ`UJTl(?-$;w_SRl8v(8J@6exD7<)DscD zcjd^F<g=$jGX4wl+0!8o@ZfnS<VXHKFvc%KUWW(evkg88+O1!OJVvke*CBo2wLTZh zVmwb;S44WPzlqQ@l_M{Z&wd-C!S6!21iA3{kvixP0Zv=cD}VIY9e#;V0-)AEk=8#4 zA~_7nUqW{E8Pe)msK17E<kJD{UkpKgVrd_7KGsZ=`FQBrfWDunqBQb69f)8X@-fdu zS-yETvIj28E1Kt{{J?p<vdhObB8`s{-JA1u?^u-fZQ621ZWJ$9>zcT6MLT-%YDhDK z<I4C@*PygcyYRy6fn<t2BZwTkM%M&J75f3eigq6Wk0L!>vY=gQbIo$rQeLhpaY!-3 z1(zza#jvpV))s5f>fh^Ysz7`*FE(c~=B3C8$$M6gY*j+q(rZ;iv#6b9#`Tc*?zI}t z{mz?9XTj#JW{WZp2uFGn{nw}%dmc7c4~fLg+oaVAaRc$0=G_L3f*2-3&w8!NfFwTJ zXiY^@E*;`0B1iKX@>w>@tC-J)aPi>FH$OXHXwrI5HgR?_lmqZuOU)k0d^u!ggBZ3% z&Ub56v^HOf(uMO?;;qR3`8S2^ZfRYpgs~tmoVUjAFE8UF1o(JIZO9FHEZ5o$GcqEN zjdcyn8&bS&q}H*#Aq#Wxrkiex-<$%M1917}kMIng*MM0n+E(tGuCmfr8xaLrF*Z%9 zhCtI=&x|O}RA5kd&9^n_=qJ5>xOl@%h?5tn+tIxKIo}zeqgsy)Fqffu?jqmlj_^*n z`JQGiI^P@c6z*-d#PfY2cmh7le1EfFKR*z%he0l?g>0_ZIv9dvC@`8@-^WZa;^v1V zxqKwV8D8sXl%1Flt(wh`FTGAUKM{I%GDL@`0?$rG!Z01OkDmOI)us96k(z2I(pt<m zTZ{P>i*jX{Mk`OEzg9(3Zgr&e%!ND&uQhVDX?|_UzxC#HT~ri4e@3X4_{sC@$!8m) zyubO4QBm#urjUm5S~oX8JHMrg8czg0sQEKPGrM(>7l-M&t*P}f|Jm)K6$V1(`5g=L zGru#EQoBO-%ENvS>1}sNJMIn5<nPF=pLG(waCX#6-u%8O|7`x85ccPWun*4Ud7%|E zuZR7C)&(neAmnL#ke%O5jroI1XSwGOMPhM5)H>Sy;ea+-pu>exk?#COk^1Q3NbY)B zRBSPSNu>Nlu6oR07STgxo~(Uf*^l7e%LBUgkp_HMgy!kU(%I?x`KX-J{3}A%;>r;1 zgWk|p&GF&<)lHoFR3PT#=C6sw``QqPUl)*x>mz02hDg8cm63dOW3y(QziA=+HGgyD zOx_adN7PqD{<q1;4y}mH-?~Tw7a(~}B=)b3<kHuLtgjcze4TuDTZr2|%Y1tXdyg0H zh|rzf{GFj$_aM0|z+)Jf*9R!|hDh#tV*vX{>iOLHH$~c_H%G<O^KS{@vcM;AZH|EF z-?qqZE%fjYk+gn$B(483Dq5a@M?m%$yvcWlX25HGSER(fyLqi}{_e=VMc!!d3618p z{!?@7{5??;H~-#{B>yhp$-l3WX?vdR&~i!r?rHxtRd5xiaaN?cdO>hYMg0Tf=vIS| z-RSWBHF>bsJt=M4bRj%^7+yGzA~|5lhGm*^?rMv3EZG98B0D+`@eIW<<FYO%4_Gu~ z>56VhwwyW6vw6)j%SC8r?z-wKtF7&3hUX<k(<Dn&tt5&fRZT^Kr3!2Y`@^~>$2DAH z3_qr#zcf_^&6558C8=KbojwrCrF)e7V93(^bEu!d+RyxlA}!5_BemVXM8;tsiPUHx zZT97TIsI4!7gy&0m3;Q`$j`|7!u%&gV|a4;seteCy~Y@yj?_P&X{OZtXG0Pgl;O`c z`x|~7`}vR+I=V0qM{bOi&M!o^{#$5W&6Bu$0~kKqz~ze}&-P29crz$*{~oC~z8uQm zdKi8sa(?fNSjX`EGj9H?k$%e8LcZoP@{RjL9%oQfe?5{W4}>h{gHhSU`ELaD_ctT6 zRNso!sNas^N>~cnE%H78^ow`Wqsz-2EnZ(9@pD6DU-**iEjMda->5P?*gYZ7syE)4 z*}NIFw{P0A1$1_9hYXj18gO-6E!_anAGQV^1FEI($yCOGR=Er;I|cMH3j*}h#Y&>8 z>xKeUEl~{q(VTI3sL307qKN~(6UyU!m(0fTP;4Fa2Oo}FjhcTXG#ihGaumTHz884* z(T1%2N8~JjKg2EnFJa#SAjeUqJ)v{%s_MzJGqba^vpGlYYNcIim2<XomgO9@v+ICy z5;$NuOt1lyj4?-sJC1zdoNdV_92_~>#yJu$@mE*%^mO-*{SVR@y{@UQ@aoljuU>uc zrvaUxw)#KjX?LfqaULgrM(X)_9cz+1@t<}4IL#-1L7x3GpuN-f{3;;(Xg$BK+xFko z-TQtUkhH(6XT><2AN1hU)%6GR?2myH89KIq^6ZQDe(-d?2+I@Ckb0gC%n><xKJn*z z+S`fe=6S7Zt$e<&uJb}&`{_l;H{s||Ctf1dm+MN3R|3A2SL>Y^+1{9HwCIV~0^IU? z;1_@MwEB&@bM|H+MxK`aOQ0-$+h6Ni>VFH&B&GhnuD1DK0gdOs1LqE}xMiD95byqp z{|&4tTF?IlRurZFBM=clT0IjASTJPu&4m4HhpZZ>_cM`t{hWz<sICS!!+2z@+s_%+ zU&9PHkDF>``M~%Qo}UqFJLin(8G|RQb2KCQt-~3)u1AMx0W(UVJ!;+a9$K#!m^n(- z{Wi~xQFl+LZ706*8Bk9e%)o$;h1QPhosrB~0Y4cn8}pnK*5)BzFH&|U5s=-q4ava1 zNI4=E*e__kX@ARRGPV76CL6FBiTs@*w?Srd0lua4koQD)*IF4oO`>HRJ$zehPtmV; z%{0|LA)zfPkzX_iPVQ;j%K;mVwxq>lE4g~tOlw^}X{$?Z_gF=z-M(}Lv@zN~az|sP z%YEnTo|be6)*!8?$8U4Z^wzuvGkqjt91xU+2eAH<a&8%U0DH<VO5e>$i0e`WvPQB1 zmZB(|OKb6r_`naCsFD^M4OzKs2WlBIOtpQO++4D;y6>sp>7}*0cuL-TfZ&%)I28#@ z*a{0qHmP+oT&bvL8<nN^z&ja+HS=64E=tOmS6Rh=!_ZoK*AXl@dLyEvinik1_4WYB zI4~GCN)EjyVSgV*ne2i^nqlS|3{d2?B*TVd5m9JP8xVz6y&aUZ;Y5OKKgA6vqawD| zvMpwUJ;X9B-@rGExFN@*;h|*4GR)4NNEkL$v3B1G{V)`zcs<o<!ufr++c8*d`u4Yt zpG`AdM&@k19@GSs4g+?|ExAQMggx*88)eiKmxH{hoH>%pno#TRA-8<(KHulu<aY1? zoOjeffyg_`Si{`d_LY8Kw`A6ShgeRT<w&8~Xv)HqCwCn`zKOvTm*h&KAS!3H4?xpw zA6XLe-P0rTai-siBBI!P=};@l3RZ=8qESQvo^dW$dT@W=XJt(z(cG3(8ya{mBZX1K zY)KizXoI{w*CezyjwF&sEOTlK#g$wPKobCMnqkBk-=InIqnA&%f~JA6WyTG-#!4Hh zRQ2A!ox1~)EGl(y2IEENwtLa#it1e0B{nAGF%77(RNRQCnv!Zd9ZR4=^dYoRFw!g= zMq$y&XUs-smAd3^RW(fs00S5hq-0Y?ntEpC(7~CNm_@k;E(>^3-mnQmBjn_4c+EkO zwIc^T7w+8&<7y3|x9{!$w*;|#C)%{>;7VSzM7$;<Msw0EGt1P4?BtOlNdei%IMZlr zgY9rN!`N(627<b28-nIC*ly`ssT%Y3>U@Me?=02c?7jCsV;xv2#Z4Z+Sj{z}g1k&y zEKTj-3ZbRNt_8UN)~P*k2gC3QzCjh`eOn7=b_HB5=b;);pp2GGP?VQvsBD@UAUre} z3OW31N1{1s^!`EV9~z#|#=|Zghj|zsJ-TLy(_<hKiNGkw_BY6RzT6^|@@)6o!|f+e zemfqAnbiZFomv%1NuCk31?4gigof<u%$8<)U)OHI69lcWg~$$1P;J~ZMlPE;&9E)D zJBnqw+_VhlTa{Au=2iiu#BhwT2*^hZtwuS^<k4AYJ<(`FR8pjJ9H8XJ1(=CbeA47Z zWisDtgXN`QyK__8jyr7+_0T9U7s=->P`<oKK0_4vf!k!sJ4I>1Vi9B|vdCMrfD<$E zk~)zX+o=efk`QzW-E3rNdhuBJG_RY6x?u>nD9Pmo%&!YGNlS!A&jwXbC~9UeNVK)Z z?WkCd?3OmFV+psgw~CzSfV|b0I~0z|252f0geC{x_9xQX^SRwy*P<=s0!&J_Fp}(c zN?^UQ%A7_+k?`o+$dmyM)dY{4dK9)nxOxKfwi4rtwse|a)L^9gvC%52vRaywb<<Qs z9Kl<9E%b<sJ&`BammcJavJ<Z18_z1t;W-yxh*sjyc7zTg(M;l<Eh_S*oW2m*D36Ip zDob-4a!XFA6D%X);SzaKUDDE`m`aYIRuJu<pgOeH@H^jPfsvSQ%4uJWX?kl5E2p$5 zWKk)uHpxr038{IPx#OaXbX^3Zeu|43dneeaWZE09I<+JXVncha{UeJsQ#N!gU8>0L zoj%OK8rpxb8P%mUbhc5*Em&~f(9qcWZoHC|C}LqDt+#}W9eR5%+|zo>P?<E$Hh>0r zVg(Zwk&sp;WldYR2GvsIIV`=KO(Ku*>akJ3#|b{&FvTmS<G}It7=)`aNU@)D*`sBj zDs3@D-RMAw<@U<T&{8p$R_uLIk~;HH8fa3N#+INVHnMPIm>G{jLo>iXshY-#ayrWi zSQ;uDM(oWjPT6H7(;-500D?puwoNOB2~`JA=MB79RJo+T-bf+N!DgYr^ZkR3Yl>?| zcmpqVgavWhDCfK6vZ)PTv%2X6508vow$xtTT)~j!)gA3Rlq|D&=E%s_t#luCG`g7~ zqI1#RbU0MqW8d`bvGg=utlH8uqlCJ^iBPZls_lF&{bVinyV&YJ=^gj(bn{l`U~vZR zMW09emO;(XjSF-E2%30fNdhT`vDu$174)1f@#P#kbm&yiU}NK8hlC_e)-+w#wH3?S z7={z#Tmi2JrMusPMhWKYwS0`kR2kIL3P~X?1PBUgcW5!?SqktnRK+_fyKu+l!J%OX zw}g*7oEu!jCt{IkxU?n7NH#1@Q8IyMa3C$kuNv%YC~QY;sjQX?BS-=<$%Y2yiUs`? zEAWvEFO(K!S7$eyBD0qjOj(dGiH5I$JI-gCngx^3H`uZ<!R16Ot?Tq^JTOZO33b$e z<}))vsEg{(=wiQbV}{&rotX-hUE-<NMj#<KBxgwc!OV21iVkT@02^-yE4~epINud1 zm+5%T$|_8kS~7-_PDqy3-y}Ep+-3o#bbMGhg-lawaBOK3WtQQ38b}s`Qxsj^d)Xvb zQ=<mTMXQRe@CQxTEjF!+3)MK#^Dte|nsVXQXuBW*Mf~)~G?lR!`Kq>(Vp!utS)*Y* z68_A$p((*M$t3nVksJ*KYjQqF&7l8)rN8;{spZReJ-%o8@@Z9<);C&g--x2`$~IkH zx>#y~Eq0o%7EusTdk@F=r7dA~KA9%c`B{>ODuZS7Q2iV*F79mHt1p(l|1f`Z<P1$y z4K^l=({{RvqaTdxfaL^P(eUQEGHw8l!{&g_^WuXr_W{L5{E{wv?|VP`<=o;@hhXYZ z)6AHm@#G(tLjGZ|3!YfBPdRr^D5~1Rda;I8!caNbdN<P0Epnw5jdt4?%sUqA>y`7) zI|Nn3RFHyDR+eRxF=c)PLK`yZQ&7<X)?Y0<?l97X7gt+LT({E?@lB~rPHxWS3&#~T z48p41^{%2hVD|C3cseULHDrjbV{`9)_9>d9KQ)(&bg6z`U#K>8@soH37WK*dZdj1W zT(mN>{$LYYT*aq+BXmE}zA^#b%f;z(jJdC-+tkkdGL&uwoo5#ilvXSkyHlu;>z~lf z`xh4D9n&1YqE+i&+|nh-m59~5LfDjxh>2K;+^~8XOCDQ)p%^`$i~`<kUGG!{#A`c# z@r&i4++y^c)81g@+8#wIE`>&5Oj=sjdWO6E&5>@ZQ`78IcI$Kg)(23`2#DEj<zA(; zqsz=KP)76*9}~}onOK}l$4vPmEp@6ljnc!4*x#s^T42MHY!pR7xtD0De<L|=L^lTt z)h%44n(A4?*AkjB@yLw14Jtr}<`=$@`R#8{@mUMPbOy%c7`hM+z$%uCovX^OElaba z1afp#!KXYUlkP;zP*>N;uZBA(mo4L9z7e#XTgany(<i&}$3~i)oSfVvH(N$B8_yYp zGj!*cU5+5(xQ5NppeN}7@@F2nTHmT~mACH<ufM<$Vxl&%BYbd2YL&WdlO~vgI=&zU z6GM=XlwdL?#1ZTa!y%Z6pE9xjXjXGCP{euN%|GNqg?cY-dFQ=i3YMU6zNuiuKz8i6 zxj0sD;v=9?G+U3f74%~Hkzxnm(R8f4kMC=NXQlIUE_0#Wk<xRGsU}cP;ZfDeuKcir z*PVMi3~>6+2f+G;AL^O>LwVEq#*M6*Y0*owO*tc5d>Clatc~7%346uJCN&L_mM{}$ z(je#5_73`ld$Lp_S?}Ls{;K);yl>4E&_R^XxBsc9FnExBBrQE4b{=gjXvLO)$>0w< z8-TMDi6yD2c#n>BBq0r&mWJh&LbTk6Tx_>0|J2C|7<}&&rDvMa3Fi}2Qv+hh9;`jL zv_5njgtxWE#;tMux6KAelz?a=Bw>yh9nDhrVWxEw>%IzH;B=i2WRZ#2;o)B;Urdgm zB09gRX{3mnK4AZ+INa2<(r9SY%LmI%VsrC1u7dC?8}E9`X6x?rY=xq0nG)BLY{-TM zWh%EQ%9D=UvYKKM4Y|v*3St!m`K=1F^4mV$Ec3lGZwbPp|D52Yk7+E3M2l@S`&$k| zGZQxz2{e{7@hH0|_!Ok^Q`w|XPXh~BJkT&%|7<41%970L$r2MWvt4X^DjbCtH{Hzg zlF0g=X1dvqr01!N9RDP?(ub<pOV$3?zJfUN4kV$igrch2Ry;!zyJR6INd0GoqZ_wI z*$Wq@TIIoprp$!cnVQ_hGD}x6XAE(?i1fGyv~>tQshPULX)+K6QxpKgPa2z4C|W=e zO}y;I>q?DS8%XCjJ8>MZ<Canc^~Is3p%wo2RuMm|m)(j%EOqB^IX+m-MjU=}_-d1? zmNg;9t5a*n;_;qro7C0-i!jlwmQ&rMt5**XFPk)07mKiUAO8EKeX)&~71Ju2SdT`q zX?*3%v4RCa-bDC+mWdWv_zQnZ_E$)7HG40=w-fJLwFi{N%JVUMEt>h+DlUu^t(^*A zl9+gui*|giOVP*2*N@#`e|_sue;R_Hf|s6BbzR|kf!(pg90ULi;J>|KnYw(L0xY~a z%2fn0EJ2GtgyHp}t)X2WZ(q>Q=fQxlm#rt5Ws1k+Z}t1HGT#Urb5gNINJ1%UFnYFV zc0<@u;#vyJmi2z2(9<*V$BDka0vsJ(Gjgr{)wp=^;-$r+)YLSlWm=WeX_FH*iD#Jz zCvhfb?3M``TZNdXjL~JXshIeW+#yL)v#P2svYb^4EGF}sq6#KQb!_Ke)yy)YV=pH< zcH=)@#Jcg_Bzsy={rZEZkrbTbN6_8hRTKs?((QNuIOJ;7r=2`_{coSra|Z3yHKI^U z%fr!9PRry#t2D$eLEBGvew-@PCsn1PY?d?a4X|aw=e}#pqauFC??U(BmN~g}>nMlz zaR1IQK!Rz|)ej@Ic=490dw!@WHu})obAG;S#flY<m;NQZekjVkXN?DHq)mn^1P(IX z<tG*8-HM{enS>^skAS6jq$a+h>5QsCOP^D<Fbr$^-gyNwv|_vM_sih+{t0W0#(X=& zZfzaM?VogA))*kkpGHIJgr!0~X5noKB^$NIcrtz8U5brQD}Mf=U-VeXbeb*X;z=VJ z%O>=6#?B|jlDLf52`XY9zm@v>=3S|Gz|g%LN_8{&c`BuADq!P^bUn&s)}pneqie^n zx4*{!Z3ec{NiQu~0%y``8=CWAxm?D2flMs3$FPml7-}Zydeyhqt_gW^%?`#ro7ZpR zaa}`9Om2oHSVFNFDwRg?pXTPr_QP$80;BxK0|)l+zu*G6fB#zh<IP1vF^}!{4bD%9 z;&|k3BF~q7Bu^tw#5N`piXteCBJwSGLx~A|j)@7)F&IlGVRQ45mX^o%?b`>pYFZeD zwe{x0CZRYXZkDx37-?(uiK5UrA;5k6R<B+ia*(6nz%yT+gC5r!d&{XP#sf29{q(?w zRLamveoo~kluT~e-!wkHar`FxYy3W#+zXrObQC5g;NIj)yq&MciVc2$j^s3Zka$kA zPF^2B1TtknpC)fhtv>=&HQBf<2%msgCUjFvbR#2frnrL#;rRH2_YwYM*)Ki%>vS?B zWs(BdjMPN)deDw{r3O4BPh;J%>X&RHJ|{1xqAS1Mw%BsK-`;tiMxR1W@5G-lyi<{7 zoi!xE{^!G6CMUNv8oGI?<H{qdVrLXmCJocZlNJcZ`Jb>wS<}?q(RMQX1|)HOzRaM_ zO7B9u9)T-X>|Sw){Uyk<WH5%r-vA5e;m_TsxoyBOj6VFgbH9CEIHIgPI@f3zrfu2U z((m`K##r6c>h|4h#oB*=4?hVSuEU>?z^fs=ntUGGJUO{JkM#llN>RMB(dae$OkB6_ zoNm<i{57Esb+C>9f1Kum<2u_?PzG3|Xbde_(A~ZG=-Omb*JPc6l62A*2get6b&Xy( zHa1qoThi!B`)l+r9e+&Cz<SICfU+DlqoUr{1|~4U(D0`LuMl1D!b2A#Srcs8`!L>h zR*<vZm1OT(<%v(Na?lv=<#e4<40>A!1D<CqaArW<u0Mu1!NP_3qoOFgo)-qjq(okX zVY96W_|!^iL8=LE7r8YkrglYo*~rM+C^P!->e12F8AH?=F3RX4KWZ^i(d1I9B&C~G zC?wbkUXTUdn36EVSa@fNh4zJ>3*Aoe&7F2XhrWbvU((Y<P8sbJvcK3FAZAvRey<6I zTrcfuysNc3zpLgrag$*8BYvJ!{|{&bi;}%^G6g_%9Bst1NkyWNS0h*`2pvh~&dIJ7 z`EmxTX)x5%x!4x1J?As5l40%hPu0oO@S>+Z^u`Rtn!!sR>N>~!M)Ciut2&re*>Pmn zCSf?vKaEy!8jP!^nM!vUtC|!!2HA$RoXAMa@{?$fgoLjRH|fn8fYg}Tm_`HJW6EYp zGNB@`w=|Sr-8`BX5=2{hCG;j~(|XdT)h=4%Yo3;Fa6OH$g&xAxjfBTGk!PEozS*m& z_KPjf4dQ2=+R06vnQczlXMLly{cURB;nwc`#TiaEj2C=VazDq(totbDmFimF>E(9+ zs;(Iy^*nk$d&G~aO)If&mY3nTV5$hmVN+9nf0Q{nV3iC_QDjkNOo8oz9Z1oXjM=(~ zW!iJaq4DwDW%$zvdo*de_-JQ3-I>Gcq+|+{EDKZxtD1&Fa!_$?ZTS{~(^afEu#<uy z6vTqKTv0?(w7GjV$y`DGUm>qoVqXSZ2$@z>OIexw6DhMHu~i-&FnS5rw7r8qg=J|2 zK?@31&se<blH)<M*LvK8P_q|u{BbK=?vwiax)v$p<(Q?L=71P)$e6oX*jH2wJ&oJO z)X^<Zak6aYEg<7fEFnP=V3DP$O(HPNIJZGIprJHq2qN8?^*@tYC-<mkcDr{8sSZu4 zdt9vBH$7$dx@DiQm32@VgEj1PPfA`5-H)l{9@WeNPuW_%2mM&W4)svL+rG<#ET+1r zGqmhs&yC1h8;;bYUi>{L3ygy?GIMku#)x|_+4;pk`}4+-UvM+WTq<qfnS^@Or9Mx3 zNXs7g)LU!ySstWRyN0vLIy{FwJGWj-X3ldntGrR`k$q3o+s_l!4%+38)bpOPKHq7d z6LU%1=iDV!NgS&EwhMeUyyP3z3qAcl?e_2@569TM;>DgC<Z4Wu)3+0D4S)5FC%unl zRHGtiDz&J{nORS(pTN)N$Vgq{8*wL|(5dZG5A`XRdYOm+>~~!5X(gTCC#oFbi|Ug} zJrB7(c!#r-*j5V7Ogiu2-=cn$!NGs!6kQ~Vy|PJpZ7QoJlJ|UvWz-zkq)4Lv#T6Y3 z;wBjG+(>p%yJhz|II+P4PFm%lqw;=-(`6Frkx8jr<4LWpw*f%2;l6KijF@Edrl@^k zWf!ixv}yC=T$5bPyD@jR1iymxgT^xoE(a3KyqT*!@p*Px8gF)WUFtP;sn@#W{4yDR za${`fU3JU8+u6CEp>cmR*OAdD=y)?XIQ!0XPWx^o&)!3x-Bh=>_quN;=vy=IBft13 z^6dSgs#QZ{H%3DXLrWYFiG5&Iu0<i$Gy*pRI)2zkLN}aU%=VU1ymfoOipAgJ;6A-u zP^W-uavZiuu@%HxhHh9etCv!1Gi5mmlA5N5O@6v?9f)$%Kc8Y*6COO6EpyRPb`>Y7 zJT}PnWL#Prv2tn-gdZ^#8N^wU=S10doCu1nh>B#IaaFQZT@XzPD@8(oA1?zS38vAH z|J|I&1+ht_iz+ltLFa&Fb8zY(f5Vo?cgT+Bo=IE%Pa^ag{O3D&iPGJ7*n3}!_y8Wl zwn_FaVzv6IVs7=XDCS~10?A~|K=DkI-jXVmZbj%@=rccPEH-vBgXM;tk;|5oT0>Jy zQM^m~)*Ur3!vnY_FcgYcQ^wnP+eI25@#Lpb@3CIgySV4my)3wK)216A-ne-)`Q<D4 zm-o|O4%bqzQ~Lz}-*ej5qfaCB>GGzQ`?qiZiDCTYUp~2gJIO6Y&rj1%OhGl?tXhTh z-!xjb0gYp00*x(0=o_2Y9NIXsY170G{?MAUWSSM{IdbZgC02~vayJ{KGctok<JhK6 zXxp|UM;0RV2{d}_{1#X$!4|l2(SB{yqK#DZva_S!hdK9V!m}R;)u{G9`oVeB2Ql>n zg!&<O&!v*^!-RSZkySA=zW34`JBUarH)l^Z#H9QKPUKb7U?CJE?EY|bSu5qE!}rdu zm-q;b8o6uN@5t-9wQKOGC-J+V!S&JexnM3nq8BBf5TGSVtg3*h@V%?K-o@h5duP|g zuzqhgzB3QUyRAN4(|RmhzZ80cWHbom1hajVw;}~=GmNV7+)9L=cvM%S7Q^yi|4fLq z;u(@1%*_Z`OO;pcl#?>|`!H@Mqe)X0qf_DD0d2S?yeS6QxM|&U`v3!(ruQ6Kkv5X6 zww9UBMyWvJ-DnJKj-Uz>{fw9|eA(@)!~SI~IjGR+h8ZTj^53I*DH&}v6HF4Ak?uxy zsWz!Zvgz$%uGkTY+?tAI+u+_l-r{=jn~Pd(phYhZg{{U?e<7~4tgq(cc*BWxD+JFg z>-F=qr8c##yg)B>Y3<PuYB8F~n2$_Eo7#<*Jlp=nf`(XrLRZFGV4-<WQ^bm(>9#&( zg0`ZoC)iwbE8&`txN`JqLj5SAe$35}@H~;#w-M^c17$zqDQm}CQR*i>RNXE6sVWuo zsD-J&cGgkNI`$_>Blhq?{N#Y9_n^;z{<hmbKVwQeVg<GT6f24#4c`Y~BmQ439y9cm zvmR(`$<5N4+uV4K=gDqQ`*6FPi-Wf7GoIEOZrM9LHP8{Wsh{;wHCH>nvr5IYDG_gh zoyD##G--1x=bb^CCdspg>?q^vnhY$hYP$1#!T`xJCZUQ#WP`F^o>o^KJ<e%B6j?=< zSf(k`ssRwmouEWUmX!!wCEhcf<q)Um7ids!+qAH3yTgRW#_0xKYicwnnpOO7ULRhD z|6OXV&A8py&w2V<o5g<)j25MSj8H%CTBcqqy&)QN>;2-qxv^*LOTLkP*2i^UcFH~* zdY07i6+->0t8vnLzvijIaFGeg9rGD_R}=*}f!-AbRRqYHfA!QLxqbVFr^jmbuF}lE z5$ZQRZLqb>Z+U7^s+lonzU`@@#x-7~Nt3j}ZrOKzeCKcP_d?aoj9%*ZJ#Vw?{ddpX z<m%0fnI9194?XqP#`iAQCZN>2-=+=s1T4dQJ!N^f?0tb6$o-5NIu{RkM%^y^U|`H> zy$=PrgpMTTsE0je?Rp>al$G5Y9wqu9ZS`X=57s!ddFFBQ><Q1j*zGyxYkPG}PS@pH zTKkiMk$TEgHWOGQKMJg;AA4rYz18Q``x6h>*53A0w`J5`BsV5!eioRQpSv=NCmi!i z=qVC=k?~-rxp^LG+=>@6ZSbulnQ-CFG7ov_+_)@H{^nh3I}|mV&vT2SiZY`M!UzC% z1k>3NKBXFhu5!Go0swm6t;<owD3@MEgRtU5A8SiYCWg-O?<)Tp7?YPsKgnIrnO_E0 z@~`G`Pi>@r9pH%H%;S?9U;ox)&D%BnZl3h3@!#(~QmQsve{gf-zCf@+TS*Sig?>#Z zIIdJ_Bq}2rV|un%J$bdq`sYwo4VBRhZlS8k27@HNRnu4LS}TMDB(HYrU_#^!R=f(r zQ&?$YELQo!1Bwy_5$S@}<E!zXn|{3*AP#6<B1yw(ez0nX(GmEgPjdQs@J|7$^|Vh$ zI#PD#8IMmzbM=d7=gD;YZGWEkHhW~Bdz*QDKCnVxm{+zok1x7qY0F;nv`lyJy1h)w zzT&PVTJ}|+XUM;UyykL^m-@QvL-kVMsJq*|8Caoz32-C9@0lUlmuLRw$jGXMqc!|J zFc<$-R~z~7x+D2N9x4}T@Bap5FMZqp5q_2_Djl{avZ1liG_j$p$Io?Ln`Mtp<TI<C z9JAH)%(!1Oa<rX~o8ib3g)@vepR(dfDPu?ii!Bu(stWhb7FaHKv?L5{0z)&YH0b4? zmY;t&Yov-Fj~GyiGbxqlBg-SH4!N8Ncb#TA)<n9*0#4I8gOeq!L#Z)Vv-4)CsvU12 zYl@i30LiXW*$4{7f|6?JFAirJ#OS$9MlnUp@*}6vG5d!Hzxc^2wGyhQaaO_}iQ{s0 zCF0j8oEoBj=~Q7n^Cna!PKEX84lYMkxVk&3{kG-`$#q!~JiLNiQV|375bs|_BEKLJ z?-eDm_GsHxPurhz+pY!Lt_O4jZ$Ax>yv5^JF$4Rnw=8gTXnDsPy8V2~#{aO_45lKF z#%}k}3XI8L?Xs1ar>sIo^+^XOn5)EHFBL^yrEg1k#`-C@Y|_7LIMh^#`U;*6{SMo8 z>FSB6U+b?P>t~mtvv|`ouq_TGk=?pm-n{Jgj*deMvDFrl7cXHBF9Hj;Gu3gSGn5YG zZ-18bl^|MHvM!qV>%`+xAo)z^z29+K+6m@87Uu!9QiQZIio^}HwrMS;>FE<dL9+QF zs8|r4YCE_TL}O8Da_RE57C=iE!M0+n*k0hcwt|$ejuJsssgN7Pm7FuHPg7ii3c<~+ z6x@A*U=LLq3AKjdNU$0z<Q8zH<czbO-`M6Xk}0lI_T#ry2##c>mGobxh!R-e84hhE zQ8TtlAF#$8p~E{5QPBLdZ(|Jmem3k{ak&*?6h3C#W^pE|3PN}bXT&>{wmi2~Z3)A0 zmkL#d(R3ja&B|r1Q7X;kBOp8&QRA`}HDoc$g^T1t_6LF}3IiD|a@0%`izOh(jO`-+ ztV!GEncB5517khV5QL2x1~MY(m`G!SZ=`A8+uRjMsRS3Z(&COD@w-+!$oi&Z*y$f{ z+oHkLCU+guS?KamWtZCRp(=QGy))M1$K0s&2I?jE$}0pXv(oRbPH$fZT)#fqvnzw7 z)kEajuxE#T96uW&)KULAO@*LZR>lH-q3xr0L@c)@<c>&X!Xr~^WfysBIPFpwI~t6G za8sEi?VBRcmbf~Er$;lBt}LasFReSO(;lkswvU|jR2I5kd|Gz7rz|8|>cg12f>2kw z(t%ij6%w&fS?#ur*09D?gIdJ_tE~0BO>x_>&O@!O(Dj}gg5$X%Py?lIbldBtZt{%I zLzudmj3+^#tZWU`v(3{Ikw%bV>UKii;f^OQdxod1i-J-iC)$-=t}ROYLhv~%1YxqW z$K7?vNnT|yq3#RtHRXl<t~N`@`T(itAbEDkJy)XbIb3&ak9erG?e;s5dZ?UB?I+Y@ zo;f@1j^deq<OZkg@xc6^<ym(;Idie4>e+;Pj_X08HJs}yt5#7(D(8_No==`#;K%T( zT<H0Q7--2wE(cR8IXyga%H4@+`)Jt{b^9_yc2|XBr4ygDt&h%=-Ahq~`4C9xakfEK zqWtw%T5CGZisDCxu>}enXIhhbiJZedZ|50s{K|D}qWj}|#Bw(oahPRGh7@J5vQm0W zp^!Gxxl^2~ynleVcq4aSQ`~6I#q+S3aAud_xr<ajRoprEQfKQ@=ju`~sY|^yM6;Pb z7y5hXapJ}9^kht}@5yeClitP3MIK?by;oMWCSXO`TbY<>uni!^HtK4$x0D&zCS&Pq zqD!M{WAmVBWyQ-3MQ<KuW%)=u2bm&^SfnS16K0|Z^)_$nZA_dE!r4TFx1ALm1Ct}I zjXI~yPlgcIOWK2DULEq_AuC0tUJ9e!do{@Ltio{IH6X5)ETwxTh#*drH;uz{(e(6_ zj4Gd94qM^Ox(1{+9_wKvlEr64PSCDcHQZ#MCD;<<X{?zIkT^^_ME*(l<m?>wrUkDm z4NefpBx2Z)N<vzTu~|i7_&lqbnyPBac2!RbdJc7|EtaB*n#xBT&4{e(r3q70m`3Ia zMpJGmq@z|;OI3P{iV78_BL}3U5=W(s887lY;CPV8;Bs22Q<So8**Y_SxvT3vLwLBg zitSy8i|b@L=baO<Q50ow2T2vNX<3PKx2UF`Jz!|2scD*FA`JmxUp6uJql?kUPBD^n z%P?axAb-Nrv{W2hNC0R6kS}P;rUArFTaHy%|BGaYCRyDoSGaPBWbmwzlibRcb*Wc{ z>eX;{fO-v~zQfH3NOyv33H79d{6;-8DH7{zV;b~1_a*Fc3b@>fT}vSb2>2Tf-XAPG z5r>u&z%&RW(a(o<Ac#>};3C||!rYZN@`9dbF1rkD->#rr(D~inlU-e)`xL|TpY4u< zh}v*6tQex8C!4x-<5F?^cCp(DGc@Y;^j(3TzPs8}Ed4tF@mlDQp~uL*GhfWV3yIK) zRxeVgH<`^naU~k#jP%$*{ITt^9LUEvvMdjaTx&{@0A)a$zts6zF)G)Q2tVx~FW`Oe z@sLVlaeX%k-r|j05Xv+P&G{uu#!zE}T5J;`q-ZgEHfKKmyJ4iqOtcg&SZ&5Y5*%O{ zR?BdCB#5#%XG(>{15|DZ(NpW!@IL#X6P-w|Ed24Ccm4Q5_*M85dvu)Vcs-DqwhG0E z4N~7zmwHoO>U--_-&dFVPj#v9_fsq6bXVNuQeX9y{Xn4X2Lol_AXFPKw)%??2Yzu& z;1`s7YhCI`Jk;brUcuByFqNG5RX$d?FSpgDe!MRA6J*BpfBXga@Y^BLMZUp*yK=w( z>K)(yEQGhgdcXW+h(;b%=Q>@R?Rrw{>2Kfl<Bvg@NGFVV3Uw<DjoE^cPsa#X6r@~3 zI%{Op$s$0dY+6aBQuW^XDYp-=c&MMQ+q2sPBSyTymCw{Idq-f*KU*DhGBz|GTK1r- zU}>TswQ*;UUbSu=JbBVCNAE>H5(1vviu7>Q9)(k8e9_UP=*W>mhdTEN-X$jBMHj)b zXcUR$9nax+JVqiUyb+nsO$L1!twF=&>%<QHfwTBSGuYGH2{{*aA@IxEHH03k5A~vA z5r6fynx$g#kxlE?ZP@}Zzx>1rWx7La8B?H}hrwRa<b1U9ImatP(CSFk6X~1hEwzgd zc0aEZ<Ed4suMe$Sqz;db#S;9)qd?%s_wR=nU(7CPGn<E4ILtCotlqSLo$P@WqowE> zH6qfdEaCkd4<AP7oi}KhX5kbc15@zeK{!=}YD*RM<`ptK1^@i;fzhD$e|jg{wF~W( zJJ2E2+KLWG`_wk3{VRn692#2EhCguU&Z(3UAEX(Ai52VKLG{LsIBoReL!@_EJ9i#E zY8^Ya>&w7^I=m7oP=;4y4rzm{R>8JyV$RfH93|w0<?Vg(EoZNGlLgavqdY30R0@CP zQ4VD?DEG+b&6~GxhnHP;;>66%WtYJnJM4NBn2(<e-AB2}!Q$wzUCK{fG=;Y9Kd~I` z+I#QrJr}Hodk@;-@loe4^XZU;HN0VuE^6<p*08gC^izKd4WuGko?Xg|=scpyYI_Vw zI$CYTRMW_onFw#_S|l2=7-Nt(<b-5^iw@z%fDT=+@n&PI1kvVedR0MJQz$M)!eNF( zVuLDamT0o#o>U4hSWt_Jwz-p>XjeY(#Pd`1tQgT2ilG)48Ol3ZHLw_Z3&BN7vA@ob zvD}f-b?eZ{LLM$$#P=^+w0ZJ_Lu_<nQ-oc)NscWz#mVAXIoR6^6?m4qAe~MxlQmUI zwgWXsZY<lp@+6j^G28-z;pHS|d7IpS-cie*!EjLIwm;NoF+4Oi-7uk+pMfkNM;fpc zUCn&xxIJXYzb%QJtU;Dl6+F78k}~vcCu3+jv@iT>dU_N>xMT_Sr_no*^sY!1sVcz3 z_U%G?N_Z|j^USSl&pHboKfZFR^D6u~Wk9$O!uEFjpE4SS&K$hznS(EoIWS2q|C1rs zy;<BIIIHx(awvG~a;q!=UOsN|a`T$Qhpoeh*Ib|;9~oIYa?<{KQq}}b7FeL48wXfH zi=PV@<2_=zy-(nG0{r$Dv2B0|;sZrg@<)0(K^*So^?s@~I{rc$Elv+U4s6+iwr)Kn zDyG2QHDUo3pziZ+NHt;eE_JL~UY<H!v<wBnN^?QaHNPhg6A2gx5K5{R7F9!+2IBcV zrWPWAZCWU*x+ab4$h7p3i!x_>I7fUEC2(#_4->r?Z9QYxTvm_cDcb2=la%g&yN_>H zg@nK%j?axuOu$8pMjCnXTex9~>lHPEBGN_g|4gD=!<s9r$sh*W+VGbo+ULyGTfW|z z>z#kk-zW6~b4TUhoF*bsS#%kaVv?C%d*+$e@#E{!*w}{A>&cfYB0+i5M51MMB-27H zw#R~9UC<h~ENd(liybqe01b!3{!-(x6Es5Z2;L)46YK_?kDWuRBdEVgD>kE3YYKT( zOka&h*dk|ur*VIv7n#D%$XT2-B_Np_|Kn(9UT?^wJ*N#UrHwAw5|3F4u=_ULf<*P~ z_+skc{vy$Jnn{cvy;1C0OLW5Qu{awYJ$eSZ0ZsSbaKot%*ga>Ob6Y0yFCDKL-lZ(h zZF|eU7+G!C$+LdB7p*^px*OF(5q&g=(3VCxk+LAP%%xPff7(79!umz5T1U}I0Y$6A zjd}N0^gh-y6Km1o;(OnFXXX&<DyuF1<I^$N-HPQwjz;-7x5uir)LJu0r+E<1={t6y z_o7wkc<H_8o_ogUGM~}4+m~AK<L4zN64RLst}9K?s>o=x)UV4IiOM_5;3fOfhjGOh zHGjA<X+dnO0t@H>MRF-A-e4u~NZxK3w=Ye=ThBS?m<ddvVDl8|7L3?V_9Qf`xIOgr zj6@(+zU=6FRVqQJuY84^g(m6w8(wkr&S;ls?&_?&e!jm3yFl&9bK&vh8`7F4X)F|_ zFTsYP##OBs4-cPvE?mC+lmg6U+Z8nmBhupi7cDE41_$BLpb2fBU5elR{m{MSmUGd6 zC2{Zzo6wvnqCDHIv0r=W7w=b94i6R8IN!vw^lmcGc1)w!*rmL4WXX56m=g%fteg4G zwy(g8O4zs;z}7n<(bgMCCS%(_NYMBzUkgzr&F6_OtNYN+s0KF_pNEd;ef59H%lCit zn|VEbWN44v-j9U}D+?1N;G_vvEvji^G<piCQ3RV84QahY`@=`JFi{EeDS;QYvxd_Q zWH^z=^Vmq&r`?u)-I=>TJ5-Wem^_O*7#U9z4Q$Ad<44*|_E2&$XMWpjhelg0X^*U| z`f33-0I65rp^2NdE4Rw+T}s$uBw@iQxFRg8svgy~Xyi#w*9{epc6VvTj-?97H>j#H zy^e{>F+MBez8oG*L|{a8&rI*bQi7fz{HtR{*gd%m_v9PZo_OO~DkKJt{DL8C=sBWc zy1B~94YxrG@;OWpyW&C4q2iW`w)6F3M>>Yqs6ARDEB0PLi1tdd0@;|ry+^jMqhF(P zkW)^Z27dv^Z{Ijp2C)X7m);}5dw=>-MTuHb?)-FtE2JZtB3H~(e4iIc?zyqhWN3M4 z?Yvv%fsyvz3iCl(R8cJY9XuMUEq_l@WRn3hze#Q%rhGItYJ!+jjQ20$#FZNb1~L5p zGg<zfgNY_N(X&{Tk4gt6*$~w$k*JyKsvKrH#Axa;8<j0SYqQvtt{Slf<gl<vL}Cc4 zGEA$M+^0y=39LM6n#==DR($alm2Xz(!j0pyso(NY?UR^SLXTo9i3hBF$1|HY^}B%@ zsO>~DPglP0#*)#KYRV=5?#2#M|M(AxPyUDG*<EC(qj{koBs-nU>M#Af1>l2l^O7NX zaM6AjhuXGbN!FFh-JYCMwhem^v0-obQ=PK+x){f=c&PUUYPkPxYIq<}_QAI)`;Z6m z*)IFAr>scI+V(k#2dq3ADEnBTUT=FJ_u!Y;s87^w!zq6amD6w2-Y4Cby-r&8D4{;( zZ<$l}M;;{U8uiD4Ui>8RHg9`>>ZexzBT&{m$3Lsv-k%5N;y(j5yzG{3u8?@V$}im> z{?*gNUwN?iYqkH{E&GP2>~B0M+4ehs8+fO8jDF|IDpI5VzHZq+c<}yettPQ<l|R)T zlc(MGz3FM+GXd_RR1(`pPOSbCdW!gyCqhd?J45>&-xU#I7D3Un@Mcr<pE`@svFYfy zgCXPS3U(>#!|?mQ+;fLF9vEgKearbg-e>@5EJsBV7(j0jB%n)Of(SIR!H|F;T-ky@ z7HruK_)&$|bvqpih)FR+5n0_5MMY*Bz79Hh!NB{ju_|gX*(A?`NO+qv(It0}ZjnV< zGi6!UfnmyubO7{&{wO0~#wE?sG{8oH5fe-ip|mWwpgc&m*5UR)hbZ34bD?LkzF<&I z+J_<cm15kIHf|J$@>Xld;<bi#=FlQBgCcO_Wx@@kVOTDNeEy{8JpLq=;?VniHe}?g zNaIx;7u(v%?m*kNoqcgbwtq}g%?1l=0IODs9qHX??)Xx%2>VfgGO7VnD0N7>1|n9j z3-#k&j3R_Sgf#~jo8qlr;YCV#xb<DJ_+&rcZBi*+5SMM`((&mwY;M_~hpvTrljS8z zj%N*7k~kCP;kBKqWvS^D-8o;i<9mq>)$QPBlNZ$ibsFZ1wZW|7&e?zOOvH6w$mXK# zJC-E6g^^5edPr=KO{^6XNj4t`2()$x;_5Tc)ULfY{k`wq1CqKRFcC?B2@%Sz&A`-> z(1_@uk<F_SP7uz91_Y4ats^JFArouD9icvAgT{kH!uLCSxVOFZnvMfPM!t^&WOen5 zl95c{<}P2)mKSZ3U?h6!WMiY!+S-v>Aa+@k*QqUwrKt&ZV6(h+oicH;Ja?K+X?Ck* zkT3*6jG9Kb&NB>5s91Mw)Pam7J&Da|PR|)8h-jUvY1nqEOytLpaNCQa!O&D_MQB}U zOTG5T=TXXa%lQ6L?G^n#f()&xSrqjwFj;nN3EQy6ltj~H8N*Zn!{(b<xW~j?kYqVi z<;`%Uxt+B(fM}#=Tpk{4AC}jb<#eAkG%9s%mUgUD7Mv$u_#+NV5r*SMfFzFPqK1-Y zO)(PXI3C3XN#G*bG-rW~RZ@X95gUzajINqoBn)MsBx5=Nf|BHQF{+d#U6r(UJW5qu zhnERrQJh)~J_!^jw;yAD`q!nw#t~(xrFEgUq;YU*yL>`I!dKzuv0TE6H#f&%qOho^ zd%TcW97Ot8iRI$l-SSJdV!tiZC@K2`X{4n`8ffpB)RvVxb9yP;+9R!ssX&R{yLr43 zoA>3W1d8Xo)=#(ej%!w2iaGvIdrx`5L385!=N}pj7t3zs)~#TXUe2`X<$R$}?#*T` z!^$=&11y*nCe&fR;{mg8aS3y}nMjzXVI>=}KG{$<`)(dF``%6PQSDJWjjccuS?7ae z^7qa46%7rWD>%&3SDj?o^HO?4humH)^@%<CjKW%-$^v8Qel-zOzFdr$1~N^^^x6=A zS~{ayaw1zEX*I@H4;ErpV=W5f9xMr;Cz9|57q#8?4CIM~A{H6PJF$IS)ns-}G;)dU zw6b*PEqoW3>69|*TuiVMa!a<=<Qnzt{ywwR%%1{!v~@vy)X<=a7Z2tqsK9)GV!Ti5 z>N^@<-;vIjsiorF-6w6~Dla;Bq3n~_C$L3Aa}m@BM6hQj?s|uKo5$$tx`1Ubf|-Vr z*j6m{N?rLRh_`7IaD=m<*(qRKggbwIO5X~Gu$VHeD|A(Fju|pkVsROXCd#zrwEl%= z57U}zWOE6$3#3vX)Sw1H)$XTJFC;>|^0FIQ@uq$IvhoU{l4r!{@)AK5rT+U~YC+mK z>v8AyMA3u%>0&(BWAvX%>n`N>tc@#rEBYF`1uRlnY_@cgZ}x*A+1M`+wR9{{Mw_s} zXf@Ia?G%tAKo{bmE1m920uAs$XEYPrAnQOD=%OX#WdI}q)0S?aYRnwTK~o_S?UmR3 z8G$OVSGmUNG4+GLL8x!KRC2SlLZZ|we|0#FU<u&49B{m%Lmpi7ejm1Z{oc2%+g?m* z$=uM;QfsoWuW#AbwN|+}AS~?Y98-tNX#`tQrifO;U7TdcZG+hU{V|Y$N1>SlGK)B9 z3fKlUl1SAci2!^NbJ%0JoizIQ?{4d<*N;TVlT7bCIeD@@784F;-iFY@(6QQiN!8r+ z;^SF;^w7fA-G+TIgjJyB{&+v;SHJ33zw7%z8UY@6fomJ*hjy-Ad#u8-QJ#mTj;M)_ zY}l}SKo~4@g02WKGQv$W<sSS=#d<dEmrTtTbRe!+Iuyi=sH?)MOeUkMoGb#>luglG z6xJhQgtr(FS&9ECn<}tD*0r3<?NVFS_DEFf(i1@70k5h&-~<?hl49anZN)bF&qCiP z7)D++m*UURbr4>6-S<z&Vy8d%K?k$oC4y!h_iJ0OqnRXtunr$yg|0x$5BFYi#mD>l zK;H$Xc|qS5qgWys<Sy~)5F&VQ!Pp-M0?E^a)sUAyYQ~Ki6E|cra<gekt%uMugqAHk z&FT94d!r~?s>Ds$)W2UtM;CSCcf>H4{xNhv$v2R%Wg3Y4qCMO&UaUQR<Rj?93!70m zaxj7gU_6>s6e+R+td^#X6>INb4_lW;RcU#NgKWHO8bNaqI(NyQ4c!}Qo}s>{|90aa zsmF#=|A+WyXcXt&q(!RZ@uh9@L|%8@aR<8m@`LSpGuJ+5<~y~XyDx#8XR-ye)SxKs zNh9lclYdP(`+r?;GL8TF4c=j4^=t;szjNvt)bxFNoZMKJ_{bJ{v%ErG{zG&Up_3=? zU6F~xsL{O!AZ>i#al<&ie1NPn+sd&u`u`(urFS0^B--Y_Nb_tc(3UrFUrom^>_hdk zPj};1wH@j+&3Jbc8CjC~FJHa}p^=fh;TJXgW*E!gS>B-?o$kXmTGX3@^@l_ijoN2D zc)RxXrWjPVZx;s|P_bcrrDhJGYZ1Ek+JDVA$xw^H!k{o>MPyUocHA_NFB=FsGKAVI zcH|2;8+QDKe|GZd<f^BtL3^xvQ@jd8R<X8ji-Ml@+{WR|kkFM(0|Tav=(cTBQ&Za) zFFw_<s~nF<t!O4DBHjQoIj(`mT`L9$2Z>JcJlVaI6kEXO{PG|skrlR{XRIiH$(0Ja z30;I>TpdNrr!TtbvoIb-5H`dw0^kVHL8;^F1@j{mW+Tq*IdXqC8kjvh$5hmb!l;Hp z5xMAHJj2DdJMTnST+#dV?ZQn_!%SqEe4OVaH*4JwOvBt#m>)?;P(;ny_EVm$$OlMv zffPCU_j}9v0MuOJUPXafrUCL_4ZrVw*P@LGZQS_4J(`AV)c!dI<9ikTz(hOgg{{fo zjeEgVdqLKwlVx$1^{mZA;8wyHUFx6hbv(;?sEB9>Si`!wxylnx*;nk<J<I#bzC`!c zS;4b9G&k0kocqj*ZVkkXFe~|LuzBqPOqHuO;8An(@e%ZS%K7tf=RIR~g%xG`hLypA z?s0iz`IcKgg|0^E>Z_mP7^WqL;$0nS(A<I2hYjQKWS2YBkGbbJL7Zw&)#Qk9#{)Z$ zKTM^>m-2a-M<~DckYOBJ+-YkDSqIZ2<K_{2D;$5Doq9esZJ#(AY)lfDVQIc|Ihvb$ zU_*LZQL#LiI`{2cy*CZp92rBoRB^eKAy^R4gdTKoRWo&wRY^)2^0sH}S230>+=-g6 zxkf#H98FF>ct1VM{PN?!?S`3ku*Jy@_6H|dj31T2U40%y4_AD|V!4Y-TQ5hKAZTgV z_noPmhGsxT0}F&pE;+^Xyt$y^OkLl@GBG%*DVlC5qM#K%+3)DaFNPlX&aFN6RVX3f zF8C8^dhgf2julr!J$n^8jL_l3j{}L#!Ko2!$_*|Z<<2?R1m~?BB4`rN6C`r`^tB`C z6R9V?sz9Dte}RY4p+j4?v0CpMZo_bTK<J1=&D4R)Y}|6FxOnlF#ow_k7+ak&V-YKo zwgkj!sxE7?7F!)#SIUSb%FS<3?Q2$bxj9OF*MG!PJmyG%cpdcGeizpBXo8bxHB~j4 zn9P5|8kNjLhv3A-X<juxPnqQXU%OXdvJLdnH@;x=GJd1xS%HXfxV^G<&#KDf)%qJp zJJ7v*F<--J?*7!LFhlC-hv=63H^GiC$Id-34tskYx$vqTjX7)hc0$`8wAZg0Sk;tw zfv;5#9@i|Kx7Ka@wb?<IcA`0g9O#~ncp^^h{U`U0#>Nv-^+q&@45T#2+Xgvi{gz00 z`iyX7)%qyA{X)FLI$$Sno}sEsHOYhp%&1UNRVCS>DXA-(9Z5!abmWnGZbrsg%OlAs zmYF@eF%Ok$3RvpR#sf1!_3?j@vI$35vd@O_SYAwSvCJkt(iGcevnfv-Q1u*tHeGjy zGajl!sCd7d&5{}#Ja4o6mh-%gQtf*4KB{B=%ocpq=V-LbtS!--XN#U^nmb11KFDmz zZ6D>9W?x?%^t;)zhiX+(&1PGw^%9g~`;`4Ok#tnHR*}J~F+p}%yjNCCAxkT+<FTDC ztwuNAm_+9ybndxFh4vxKEUaBC2#R8?8*Ay=Z<q%bwpYiNzPUBP({yCod_4Uuy=yqz zPR5|a!^8BZ%p;E8U8=3Daz90P^?OQ(u+XuykFC7^dUW8x1iB-=JGE3;n^SkG8?_y~ z!y68VCm&e}i{a&cuq0XXXpd!>O^^*I(@d_G>G0usdOlgkwe%J4y6GYc%i#L2ua6$t zo|+cc<cw|FI%E4@=Hca_xDx<f1ughRV;u>AazOQuO{ZsUtm;j$*{%TBP#*2}@iWn= zFtvwJdtEBYK|9;$tM>(Jx6k$mc$Da;vjb$z2g$P`Pwn<EhCTIA9o$|4BOY$F2;be0 z*W1~?_B}`Mxe~pXn;j+6x`6xr8!V5^kcBl;GPYhn$FQRn4i?+LusO;cMjuAgOmqtC z8`6hA{J?fiJzF=<!4`V&KMz$$k>HQcE|@n4_UagO^={k8@U)GOTGfN!>K?iM{*F6W zoVl&ouZ$K^<ES=R*m@>5JFj?P6ILBiEYrVhXKxlHTVWb@cymV2j+3`74AG1cui_DZ zsGhzX#K`aX+~?3c-&uNO_r{IKetl@ehMf;#wP6FUJrD7pwCxi&DYh%A&5iW5+_4&T z)`2(w#<nZ3L}#3_;|m`^A87pTN+aK?wq8(d)EinKSOyv|Z8&dNFJzT8Ftvmc*R7cM zW^at#X9(u4tcJUKWx^uFaXo1J_A{S8YmAr7<Y%cK_XKY!O---~!X`yg8}=X6^@EE$ zz4Cf?VxA1PCFr7n41SgDy^8~7iLO06>Cpk~JK%rE5~AS5^!1al1ma`ypvBU5JJt?8 z^dBs0+l6Sc%$;$DRPK)Qm8nFprpo9tl-7omD+jO5g0h*p?6UW1dNd4mz%zyhbHL=d zJ*s+!W+d`mFrD1l=kWV$w#DG=MN^@w2Jxn6hg#y{P`ejPeUjRV;lKEZZ<Rhv@lR*T z{mt2B?l`<++Yz(N-EpvU;XI8;=V3<&N%^E#4LjOV1)b|>{kPnL&OiU3(Di5y>RO<U zw1&IN%|@Z~;R%=+-?wJ%{#<jaMFDa?5l*1AkxJs)v*bn%<;PC%JA4MYFR02{-*`s) zh!XT^2t=7R1W{ZajTACkI*XMuy`)Z}-O&gPM;^e7VADQDWe~%%%X!X>nQ;@Ex}Gl_ znUf?&<jL4P??|Z?9@&*3lE<d53}{WX>?#kJ!Rl^wF}Y1KyV_IM9`iLmDf%2enV((j znF+eT+B31vH*3!A-P!d%ndrm@&u;L|`*SqTVwRvN&yt(Svzy%AlD2xY$4-%n&ifFS zp`}nOnSuFO{{#smm?Ox+wwD#%V&fWrYYJ*|b2sYg8NQ;wTRLz6j*UHJTQDG^erfa4 zK_%DQw66z35Cb4KywFU$yld-5TYS5Em7})?tlj6yh;0k(as;V*c6&h6d4sI?9Ra<M zTHI&&YIqUXV3*w)*t2NaUB2DmIT|xFyE~vOy-w`=J%N@{`9v}{68|nYyVq^W3#2dm ze7|^;_T}QM2?p>r^LA*Pi}nXbirlN6J>VHBi}<|k9vyVGwCY*tQ*L%slIuEXst0Tx zkGb(qi|-p!h6cLEqz&1tuf9Xm1jSx*J?IRu4z@nU@l60(EzJo~D1q3Ns)ntw+<Ihg zJ39M-1pBB|d()B4hXQ?|TzS~%@pz3QhhO~P^VXfMcOUVM+iNtYV)kfY#Qsd`Jr<a4 za#MQtOwVjvWY>5iQe7{{-5I31^jSX6c+T;poIOv=x2flNsA4tBZ}wadngpumVV^zE zQ`SW=o+WrEv*){QpwtTjTHI@-y%z>_e>##Ek+pxZ=b7Sacqa&T#?wRFy7^2%vb;iS zuLOEXkTLA5IJovX@{3E{@uRZnQeQnUI(q44^E4`(dU?Q4OKW&Xz-vW&bcJsY?b}<m z*&;VF9qc};B_)U*QVQrw!&dE-B<?*7>G{Mb;M`pMW669T9$XkrCp+v!V?9exJhT9d zDzGyGBXNrh!|*`>hQPuI16{tgx$a6=n%d~|cKqDKZXRLi%_Cg)c`Ae6%JOjW#vMCQ zZ|}(+J79l5^Odipes`;UV^}v$#30DAk#`Gf@5AFD0r1}i06^H2h$2Qz8J07bRAOD_ z<B8`TJML=V%)H{*(ANa4ep<t|0h^CRa?YM4Qt7*%wV=3M|1QE4@AgUCKRb59bpbA- zJaN5;Cur6gTlc<!P;YeGLv`=>%v))84L8-Z-e=z%kj!-Tyf3gvzDVqvf0`#R?6U6< zj0u$tH~VU+_WJ{YRY_a+!FiI~rhX`}JN%W%=ns2jG(|i=O-`cS3_QhZRC#|NMRP9u zj>(CcJ=l-po~)D(pS`*?DrpkZEkk0XkWnQBVOGuqlQ|dzvN#itg`0Q=GW<KYZe>@k zf=x|dg@cXhGC$bZ+QyY)ohf7_GXrBQ#=GQndwz>ynnpoVc}<#z@l}9&V_u_Y(X+P% zdPisZ)+)E)-ZhXBevm|1(3=+|Mk$y<ry8Hcd$f#48vqa$))YkH4j9|ja{lt=0|UyQ zJz#Y7!L8?G&CbrBbH?2DTenWdI?_`U<Q$5g$vli(@sW8e!k*EO)}1ASx;T4VRl2#h z%;}Km=ts4iPE}K{Hb=gs9rlH6creOZ9JB9dJ#nB8mlxkTrRZ^_A}f`bR_6gqAtqIn zqL*L(9g*i{1-wh)Oi);|#L{KcFeD^fnJJ)j2qIJ@>7ra!(*4=v9ZY*|IIl_NJtuAd z!WYmr*9^f?2uDZnf+TzE{o7&hjth1D!VMFE{>SBFTdsXPz}p1z<l@Hz_QcC%g??gQ zS$ix$8Q4{*we>0A`g++J_fOB067~wc-Q&Bd+LU$<M?0&W$8Ss)K!0GVcvi}wn=_sF zj7h8;c6Cift?1<9s9-1nAcg0nkWFYXnUk7g3j4m1?r%WFl;Hw|1@3|c|B}suY-3wT z9%OP>Ml2^AitJ!Ht^*KnYy;UQ7?Waf_YNs}Y+<`=ciM8|Grk?r9*L(g^^SUS&9Ux2 z>&mLX*gSmkSA8S=vLi3=^if~MZ?mQP=K}oxI#~ro51l1<jAlRYKBMdO3-h!KoBG9o z59UQr`@ZDSIevu8emPJBmAhZ@X<1e6?W?3EUkhkpln=f>uO6Eh|0TdluM+O~SD(yz z#_7v90vt;Bzkdsi3AK{GNm}x)fPVKn;puO?yeE(|ycc}?x|{#Dwx<ujMgG!(k9-82 zIFbAM*U|Ol(`4k@)t24e1tr({@PG-r=eC-CX20327&72hK`|APwB%_=XZucF-~4y0 zJmu!DeALYnMzh5^ci7@yEy%0l*N(a4KT4xJtTWF<ix>AlU6f2&VpN6y>J7UfT(RO& zxM71iXjnsVjV4D>R9vYK>&u$`TF3Y5a?tk!GL~w?|L)sMUv+emAIzI$dtdn>v7WYj zv`xC#+qS{0J{{sYpN4x^U?;jepea-8Jszs+u2!mn-|JaFHb2})c;$W{uh^Qr{p^8& z#zZ~p56*k1&9x8B^Wxhp`Qf^|(IY+%f12i&n0?e!RwpsvcD;|0_EGu#gv-m6`%n2e z=xN6@d^#YN==tuG^Yj$E_9Q9$lvDN@>KS%q!H??2w$J|9Df_%*q5q_=hVaw6o{s;h zD@}eDkR~Joe)i`9D)kiqC(%~#pU0K<vtM|qlB>)8l2Cu;lzqjS0ow0hdnA}WTfdp7 z_u0Jq+kiBt`{?iL`oe!dPkXh?{$buqw_8Tm`0O7YK7YZ{NdH8rPrGI5o=ZLC&v<lj zyM||dTJiIaUHfOkG0)Z2Y-zur_v}LUFJ2(OcrhShUm^4R61ltZgMd{38)@syfmK7L z!z&*CtJ&c6&98b;?ri>hjZk0raF5-}H$3&i>K!B7^M+gbCVBQ3cO+gUo~FP0c;3Nt znf;q@460oCcb{+W8K>3%6*%|!i-%ACJ21=tGtXC58{7Z&obK5@{68Y;?hB0VU&$}1 zr5n%`=0ZLjylO#{+ULTqra-83k$`1R%i5gPJV&By<`~b|+Usf=c}AjB<~R?QA?DLL z{;hdtPH@}vH+xmgiGlS=+atMl4~<>5qo?vtoIXW9a`o(br|?**qls?3NxG|>Fx=0u z7S9~$lB9l3<MCd`i#MZQLF(GtCJAfAux=!j__8=qU~G8H7OVw+SKxU`fk1l~1^qt% zJ)bc3ykY1qQe4w?px6-x4U3GNuMcuy$D*8Y2^lvM3o@sAX6!Ea8HoUx(>-SsPgGa# zoZ(6j`VMoRhX?b@9GK_ZvCERv`Z?s0gm@k&DAn@YsB^IZpLwL+T-<HhOJrvz@@FpL z`c~=cAoDs`tAY5*=Td<&AyR%W9askhdv`7qXan*1&1HRSx+>4fn!cF$Hs-3Q<*(DT z!nvGpG#oGd962qYEBJYIu5q50VZXB&&@W!D%_P06IM?L&-OZH(lA5gHxn^HI4$_x1 z>*OSTuEpKUU-gW5tE+3gR9o+JZH`xfqFSUKv;q&>h8Odp8ja_*0IQmxI?RivCZugJ zn4M{XkMaD_pB{tnf$%-=N$%VUhK8;tx2VbhAy769PM3i`CyH}>Rx5p`QS%Dc_?w`% z&UMt40G;mK(b?}Jzv%Xyida<(Z?0$F`IJrV^=N%V9{F2)N1uy6PVkoJ`UCp|*)`?{ z>e(1`gZ0+!9I=n)hJ7;iWoog^jm*>JY#ta5*c2oK>)e8QE6e7vvAUij+Lv*kpP_2q z1_3dAvpneK02e63JNKIfc7$iF2tT}g<Ho&v(;RED?8wt23=4TCvv1$Vjk|jp_QUAi z2)+B=r)5P_c}_BQ(=gMD!bt)E5+<l=Owdh%`{+_xUfL4(VsOt9G|#ySceaV2aBh*u zPq^CeNuOIB&~mBmK+wPECVeCC#H!3q&6`1cK9+c>63OXfk32a6otyUPhxR+^KDIot z3z2BkxfP!FK)01E=bhi#ytFE?=TY8X9nfEi20XVW&`*-La&B!v3chShuM^kQ<<WHk zt&#R+y-#DRQa89>HqP~uP#d+GAPLTooUFxm+Z<J8C@=dMN6@ijXWX~_Nb-wc1Sd}> zcxH-YV&eGI;|zNXyb;11Z@fpf!}?9RrPtJpf+UKZVwxP+x=@l9Hkw|q(TRhB(SNyi zGUmwFjh=nPp36=3H21m9^VXKl4O@I?e~!&FM@|ptwt3FZpLBQG?ScJihigmo&i?eE z&(<%^xAeV{L!PW^x84dazPNA87SPpo!ImwkvvUA0h43q2`oV=DIlj<LoA|GMcJs74 z(oB2tlC#sFQBOk5?VM)`*}S;R<5x9^g>}j~zqRwG_~zT|nk-h+3H!Lf^&Reqd-ona zt{Mpdv~;2<Y;Wu=q@uYtF@J2oxMT^)<<6d(0u2q{!@I;5Xlb$yB&u*RZRKJ~hMFv{ zgIkP2J!TB(mVcG(_Go)FN8%~sKPfwTw?p&dD{7&H_6;TyViEVp1=ONw?Z%&y+J~a- zRsHcsIhB}+HSjI*(Uoj;gxfYI@Ke0Vu3vwXs?j)s+d<dy<6wIFl*vaq4kQ#L$J$CZ zFUJ7KM!<xPb)Gj`SCh=_(%{B}nJz=~*)DT?T#gZ)HCOWv<-9xf{Ij38!xp-6+cwzK zbLIB!pto24)~4fjSo20WF|ld!&Gy&B{U$K*-=1v-XlcR!7XUB-DFzDFpningw$~>+ zo~LnEbNhUj&-3);cy7PP19pjfo=Ru!KwZuKV1OgZS;`za)15mU(6;>1Coej7Jk@TF z`p?Pdjs?~>ZNr%!&T-BlojYzlgm<dBk85#XHiNtQkpDkXM_2PUc>Sg5i|G9t9~0$w z$Q<CLB#1I)xM<PtpC0QIB`tn4xD>)mFFmCioS~L_bGhCa;*s7gE3zsNvI1vf&cT0V zL57nnBxyxw#?eHH=XLHl>F-(YSr-|FIdXnHcTT{jJ2$Y)P+4|fz!OV7x>PSeKOiwK z2xvF-Z5MhZTovO{$2w)%bJi5xCE{KnH&0x79St+J3+&&2*6)w*YJ-BIDVm|!0lP?m zx?%uDSCWI^W(aS-8U8=Uz5~FKqe@hvbMCHgWsPP=8fkLUgx%TQ+1c5g(`@kO9Gvrx zG_r93j4?LY1RKK{W3s`A2?w8?9l+STHU~a}F&x<7yiRZjcmCB?tyXnU@BS})v@=ho z>Q}E`z4xl>h4atXSFZfNsv7ozdX$!VL6vxkleJjmcXi?Uf^h!EMN)?%*Z0V;6ZX=j zzWZ(rz07-}HhsB|Pf?_U!+Te__8r;pmF}s)i*~k?=@Y(P0rIGto}RV$wW(h5&Cn}^ zwy6?c!*<&lpB?Z9fkTbx*T&&0pM8PX)zv=x0-fAVzirleiv6@}X5G!$>-Abs56?Q5 z&vm|Y%r^*&`+DDq-|p)dp90~w?+7)bmTY|A8DzIOb8&-vC;d9w%{3yN1mvywvLjh- zuYAm@3sG#OD_eb$IyOtPL6IE|p2a`p{g`#+h&eH__o%>&fU-DxD!O<vCyEq9@f2-m zKUSblRGKucS<}up(uR>vKRj-vlm|pH0wT<pGKO%KAV%~E-#aj{aN&yE=9cVNbc>>I zA1!+J*m%@85+_jZ8Q=7~iG5ImCvGBY-`Lbd_u<nwd+)fNUDhqWGa<BRn|^PQY;`bs zA0cZVa-p~S?oTlEHp1K2USsd~_4_8#_5;4X4u*cv<qTAr+u2Q`Tkz@IiEr3)^Nt`% zhQDz+It!luFwxs%zTWQi-9_N%f5fL>K03=%Z}fw1K&S8W+29{TpWTh#KklKnQ-xvr z9-r-wSKKFvwFPk86oh_~*lXzS9_mx5cXYcq{Tc6$+2M)Lx-*PU2&X?c>!!`_=U$Ju z#<LC--Rn(%!AI@;e7kLO*8Y{C+9NLXi$wi$yI*vpH~l5z=HTZL`ejeQUYY$Bf=0G% z{i;XezKT!KFaL&bXGlt#fAh+!>95VAy$$_3q9?l1oBoDR<9?HnO#pdd+q3m8&;HfX zKhxiyb-HEmKfZ%{|8CG3l3g_de)c`jXU^)L{{F1HEvwD}4uyZ<-q@h5Mu;z&=^uJ` z15Vo?`R4w|v*xq0x_?5f?w`5P2VC6$?ydr6`au_KRM+V8U-`y~t-^<Vqrm%=hkfV% zrx6ZV*8P;Y4Y%hA)xw;9WY&tZd;hs_mA*;f_b9=e_G~;h>xQmz28V9ErcV+5*iU}k zhdX}e6SGbyZRjroZQ_6T;fEyY^e=sS9<Q@s%{uY2b@!9AB($yly?0wLI(8rC{9hCO zLP>J@FJ|FjWA>X_cYHQxzeUve9pb-Re7uSMlCYFT_fgYNokarw-kmAr(K`LK@1zXx z4*uYSVp{&uGrE`XikbdT0xBbU@ly!>6T%qXc}+j#TfxtItc#c6tlG5u%PhHL&-Gtt z=@h&7=gwlEJWtRWQfB&vS^YNF;ETTdDLhjzdGAuEy|-bG?m}9tIQ@#xuM$P7O`rC0 z9a=}zuLj<^V@zIi?F-D!uY07NbDuZ;MqSFmU95<2H{D%qcW4OiuqHxFf_AZRLtwJ* z4ULmJX?7StX=2^Hc{AwlzGmY_qo*gnnF@nwZ<JDbu4PSPKD#_C^Mmd3yyTJ{W(NQr z9iK6~O|!fEA!uY7@MjS(M0k#hikx6q31!>lByF%p&sv^eJJ@XCfAC)1w&{O@PHob} zPP|O!`ftR{lze9({?nZ+5B~b#x#u2v`pEI)o0lvxnwt-!_nXlBx#;~XhOy4rWWfIy z4eLOMKkJ=;8?$cn*qfd?e8HL7zj>f96F%e2^xx02?*5D5Rh!%YdzRF*=l35zS>3pg zV5a}+yN$(C`G1Ihe*t^=U*B!aEA9;|GyRs=?yH1m?FihlRKnhvGGtp7D-i-ey)KU{ zQS=##maov>-mVDy^m{|PGZn^nyNRK!_jDKIUg3Oqvgj<bg6^~`f>&ZYBM^zT4drb` znzbh3ELUWo#76j4lvykOA+NPsQN7xyqWQ-8D(YSL$!grz@KDjwREUa91q4Z?is?%2 zzoW5OK1q!GjrnlEJ7`SRc#tlxB)rnrp<FT$n)3OMV`!Q<6?)u-W{4XDNVzLg9y&bh z_z7bivR-*uX(C2}eJ5>7=FohjJHkqfJMPo=TB@|pT1z&K@;*&U+!115gGvGUiYYi+ z(UCs3FYmF?`Jsy&d21S%HjM=J!%qAinQg^W(;?_I*Yz|df)3Ha4SbC4g!TgXvaxT? zn%%q2J$u%!9UEIWHnzE~K<C?XQnsBh^bdd`b9lI?XYm0;7de&VK#E<TiwL5j(#aU# z6qEXL%i%_LV0vh1=pAkGcpF<}VKWu}V+n%LALV3@5_y)9qZZ5Zyu!=8s?i(|K~z-d zIyuImX_cdSL!nhsQ{m_E72_Kbpf<hR&|ILq(@KfZTaA_7?s|Bj`LA^NZfKCrUg`A3 z86atLMZqTnUv&4KOr^`ak{oDv(2c$$k9yq5a%6i{P;_mj&#gy?_8S#+t63Q!Y`lgX z8FcILp^EbrbaPo5a_=+IZn1*yC@UlA6a>eyKjLa;TpN8sXbY-z?9<J*Q(qaWI&{`N zf)jh9s0X*IvE!$Bh8&)a;$b)L-VH`auid#53=e<*dyAO4>o`kg*{E(VqEyW=^x*<} z?KGHSk=BeD9|yn`VyeJVv|@>zDAKt{`gBEuKkY_A&=g4<kAzh!4g@2zLMXS3?fok@ zN$pZ6EgWNj-jdNpAeu2=7k~^nR?JJLs%IOT%BIbz@9rJ%Ves6|A>^^$cJ3@W`l#D> zEO7Scd9BOJe4mbb&6Tdj3c3NUj1%907Gh-~@eLJuTiIMbfxdxmIV+RC-WH?J(EVj4 zO6;m_UPrN-m1RCJAIwY3eSS=M1S<%98oa*Jt$dDd%qy$VGqE;YL+m>m5_)Z*jJIzl zC3K7PIyysc*jNig>qFZhPaecM%e<$_{=fZ}7E9cB50g1(oxj;Ln3Ym5=<91g)X_U# z|K*bX`;7$)j-dC8sA!go8qsL{(s(5LZqHv$U>tz)@rUt0KawO})-+jn{_PylbPfI# zIF93KmezHeW{BV07l`757G1;tpxJy5Ye<JT&|Ph1gKK@@m^@7HjXwW8OxaCd-BQ`? zMj=E(aVL6WRtB`cn)jOKz4t!&l%hQKoqM5-NTF&DKL}~{7z_W6S#aILXB0(LX;a`o zX)b27c|L4LdA7GxInP|Y_y^ySq%a5zpZdv@SG3U)-ei*;%PE(v9Ld`lJGe!P67rL% zOof7=TLPh5k#Bzn<>vW;d*kXEVf~Kb&*sNX^Wz_H*|WzS8TrAJhVkTA?#>+m^Wm87 z*pjD1r$TZ_uV<EQWCF0&;b=gOuEQ~gz0|zZ9OKTvb4JtSaZ?5HM3a_FW^!sS6+6YK z(t`jzsD0^{Tizk2lChW)vl4MBk%Vutcp_jl+XBb9-3zUtn_g*7VA~ym(4B6q<X=z^ z=svZwJFx8@<V});&_6;e#HI+;Lvf49R&NJ%+P}uV^?5v1B+F*EK*eb88uKHY3?2$$ z3Cd$tQDr5W=bK}|OmhiMhJQ;!#Ck|mX+?U-0yp3ME+(b{kYSo*imEC~LesRk4rEQz zB~j!BISAvuKKkrC3w`znLJuIQGiKNWx{a(H3T%5g5PHOi!_l+gaLm{C_*vSX8wfow z5PH6^-wTL-{d0d|0JK;^wQegH`#wW=e|C$2el87!UKR+w+y}klEd5>?2t5%9oeqRn z&|ReiMUp{xd_yOE^1*Tb94=esvxLjVi6o1qk-va@0l4?x>jWNh<%OHU;6Q{GIYZJp znu=%?&&#4@2&N=Qw=k2FdUNwgxTT%ye()(-e(HPoQ8Xj5w3bL{tx1q(iwVP^O(`ym zilP=e)FCz2t%<zBdB;^f3%zCnp|wEhRe{i}1EFsVgkBQ}y*3bfT_E)OK<L{8q3=Lh z(3Q8|L|MPo*|tGyr@4Fg@jo5i`L1Ql!1(~2k1Z!>A74SYhm{-L3h~&=!qKK7$EvaY zWq%Bz==QL3qkGqmJj^OMu9S8xs~7N1W925)_B}|ya=7w*D1jq(8@UbLtoUV|+R%fz zwwz^5n!fHP!!SijF?E?2$CuAH$H$j{V#WOXHH}hbP>f%>TM{+X(iLmLzyMeVz%s{^ z_7yY|j2-LjESyYz6%^lkf^)r^h_;nmLO2ul%P1eC>aW-5>?S>b7dBcOH}3!CzKxO1 z*5=KJpE|VpzSdUI3P9_DLILCf$fM`HgwKDS=e*aAIe3GBzR$%JpA#TVE4R8dN9Xw! z6fs+Qx4U0L{=pS=V_3P_^(B6dpn&SOeU9k&14Mk!Nf(C?dMlGSZ9n8fQ3Q@d!y>U~ zbKBavj!?g^kT_IscPpX4PV{>RQM>n17y4nhEjr6{`i;A7Um)gjt^<7m->o=3-09Nn z^#-3-KH}m_WcYGuCf6fVD(L32@-Hq9sBTN;E+2i-X`4ge!9Y4>oIKdCBJWc*lnHeN zSns5vP$K`xZ8f)VhiiB1hs_8bk87HxSZc9W|3i+cZHsTd8FT^Abt|oF$()u-HpkVj zIrTr9l4@5SFTCDS+~{Rn5ngy@+ch&=>UE=C`?YSqj+8L2=q$v~_fN@fU1C<}B7jmd z?WS4y7+AV=9@C!ZnYz^Zkr7v$D2mhBgd)mE`qW&>?9~m4mx|deXab<AjvtXbi<l1- z-{j24-Gn@P%#}wUclTc8I=aW5yVJycEcMMOhAwwk!3%^$TS?@(b9t@ui2zP1R?tmz z<x>QIH~8?=#53)FK0}PKv37CW&pMdAN{;2Se>iR5z_%|B)(2fl@miyY6IT;_=&q&{ zhke|Mx!@{dgpD4yxN8j22xrkD@I`03mCt#gZ{TwR)C113!d!N}`wisrQ@PjkjrvLI z=Y72sSwRRW@~5kO0r|AzGoAaKxMkb3#nyXv<a<|upVh20zs6_9jpo*^hkkQ#<Bhqj znrdCIHMgiGeZ9GH<GIfsU;ouq3S<Gu4yl%EnmnIUWW5!#tex)5p*zZL<ILQ@2FW%% z*HC~|*zMyJJR9}VKI_cf7d<p^;-+xh%KgM_xVcK)wskFzpLW3UWVI_DKjQIZb#u4R z&UWVf*#4o8e~;yOQT|dW^&e>K?9A`m^T>|ft(~2Pz3Z8sbGyv;_V)Q*kJtwQMjjN9 zACCc*pAm}~JM-{0S|}7Sey=&&29NtafwK2Y&RAX~xx4aZcZ9DJ(62Z?7^j^xtaqU` ziToWZ|K|3CZwrtQgZ*SzzWmHx#mG~$@_$^~zGQ!fqw)z}#B=ryUq5)xFz(+ZX5Ag< ziT68alds?t%L?*>sC?V;vwy`I5sKffeAMj$TMW2|4-vC|%7GRu$Ty<$J>nZ~rV<Bh z;jQN#?)g4~{(xBb4X$j^_Kk+dt^Ck|I=N1qw%55m5P3)l{v+hnWnXk==M{XLTlo<& zJ0A^NAC(_F&{s+PDnD_cuXxtd^~Ah1?1X!Wd9m9*;CY&pBfx3<NkXgGx&}oS+dSlv zQy7Pb+<xC6c=cho?aPE^be97??Pwr8ho1@5DnIpc7l!_fpl1X6h)=>JE;xa67~JnW zLC4?td7xf;lz3(Xlg9{o)8K-Wgf_L?o@#j4IBNi}N&6d*dsfCvPVdO$qw))4-PxG@ zJK_aQ#a|M7r-9|KLb!hROQ@=OQ)nnO=~m>eClB-su+g$LGTWFb;ZOpn3|DUZkt6vI zX4`hYt>@68ZQG9g@!0ljjJPhxax`bLVIv~7nBom1cAa@9ml`P@G|Xt&P;`c}jDv<{ z7}og-UQsoXp`x_Rm;xtu$g3oV(rH=^nuRBw@!65)4gUR^&mR4yXC*n&<PPtgB>1<n zF8;%}0)Fl3;k0M9eAlHh=7it)bj;rg9rIhCltA@SPy7d=sT(-_j%eG^iBA!n@q`Qg zJ%K}G#XjUfUnVRGrt);iV;wrsKlr%(kBEy9ewF_usA2c>C!f{v0@3@QU5WB0v6`Q8 zcN1^AQkJPaOYBD)H2RARC8T5Juc5l0BgSG!Qab&<;aW4y<%@$>tQ|q>kq6KDbP&l` z&%3in*tC@wh_;P&{30RM9(PCal8?%mk}n5Ijp?+jPw@(V#Ulfpc-v{shi{`_CtF|T zwA(uo#ZL6|yer$7>5QunUTxU4mv1LH#*M;udQj?qb`|8uQ+dt3_rXw90jKghVS_g) z_lD2X#n3mA6(wL^aqneZ&wer{h%C)Uq(cihH?TU4y`ZzRJTKlR_GT8P2E;C7Y@lP_ zUi1?C&Hn!F-=FILt`1+ulwpaMk#Dwi!!V{)bwD377R6#n6gBKVH-dSV#qzgVJk%KT z-w8|G)m4`d5EenB?SDC$b6-KVVB$_JPAu-JqEn9~j|bS6w)CD<g`}B~`IsOMn_n^q zIFY?&!PL~@-yYnuWr2C*$Rj$mCv}6-<Z??(S&=6v;6MSejF{f!a66G*z_VX`(6#4~ z-%jNpK0SwJ>Fa3!U|VDM$rKr<k*~WCICGUhn~iMW{MO@(3Y!LohrxO<Jlwxw!_J*k zQ%8P(c+;j`yEa|FzGdOU%?qxPbB1nDUQQlV3>p51-jt29yiidT?{4XzfxE7oiR=cA z(f-dY>!vQRixuQ!H2sLzrghf+TdqWUy|LP=A@91chCP_P;K)_nHsaW{FJk<v$S<Z! zxjhiO%_>b;1dvOs48jlD1y$CS#ANTBcL!PJeKbKfSXJ;zj+Y3TyMmB+?g%fx+-oai z3(AR+{V0K@-MgKKpjbuzNR=mos92SQG~(q)UHyx>4(&;*$XBVVx>)^<=tuMRj^jFs zalPJ<p;hFoR5e@)NbL2e=lG;9mZ3)p?E|TQ`4v9fjo7tT0a_ap_N9h<Yx{I)%~?)C zM=i&w3c82(--tS*v2CNddGmo^?Aa*gL3?{wPnnCE`AdqRRO-2~w^(_4Ezf1eh!GXo z_Jq_SEK%kQi+(7>)nXXRu%Z|`t?~>AM}YzVuwVT~GevU-on{$cF7_Be&ef?y*x#4$ zA+p%o^J~`Yo4G6M;kqSIwSvw;t1-etwz)DMsGISeCcNhwP7lc--E7A|d!#MyA>}&{ z#?Z9SHp9@2*XFKf5wA3Pc=uIolT@*f7XDr{!7;97GCfJio(BC66VG@E_R~VF;#PMA zr)NDQPkisE_5DD#Ks?#CN2+ZE)m-{ii-fGPXRd@shpHu1qwbT5)nD!K)zU`szSU0e z`lxn!=Ff>3u6EDTE2rvurHX0+RC~R<{AwTi40|Vi!7Bl)13{9@nfICx`Y|GMt1*{@ z1f9!1iyu>M$fqlCKNtG!Vcd2&kbg!93FOAHIWj^+>&TYd$U~?)Cy0lubKSK;@cZ<2 zUYUwUfw_~Zju8^trqnzir3jnWiG1^&Wmo4Dy2BlJbpdgj=4#IAtG(2yj(en_SNkmV ztz8VAaL0n=sI$fv5o-){%So48P?m-2VjsP*_5W=`!?~7sb%`5O^oqSIs>n;Jy3Dt4 z!flra(3YvLa5?|gM*gkp%Anm;byc9`T1{914XUp3X~(r5+43yO*VT2t6H$!sdLKXH zwi|-Zr|qaI&m9oPVIzS9l-1Quh{~IN8k$&3)hX|Ksc!LURwA0n!E!5c-tmMxTVHmc z{5SVZqj)9K)75Rha}(UpcJH|fIx(q#b`HTUkGnc&hj&*~-RWBoFA=@(^3Gg!H!&`$ z9)DX!5$n~xzO{qtzR$;h7`oqkMunq?oM#>&R)sB>4tnI>UmXB%K#;$S23sj8>v;9B zk7tgc&yITL%M)MZ_U1&mINb1uAU>V`rdLZ%|8kZ#wy`|svv!Dh6&Ly<d0JaN9>_`O z5@Y$9yV}kpYNpyxJ0I<Hk*8wy0s<5F%<=MH5dGLI{6a*NBLqz(6bEW^>qY1@6nS2~ z<Sd_E>T0kzi8b^WuWrZjScHBeCBbEZW4_$COUAo+<eOW)B5;LX>9tv_CwwP@h^wm8 zghs0nTEM;O!O<Ais&~~@XNd3B0<{~y*P=agn5kav<c)s`=aqDNc$-(xUM3N}UqhS> z*Y6dW>a~Q`ZO4Ya<&!3VBe>|gpxc}3^}bsS41K!`{d>a-tG>fW89Y<(^xbMG9vtc` z?FM2j?;^g@&@?x?{Dfk)98P+-Z>8b3Hxcr(aV{43X=*%{_xP+<e4-TduAb`6vt)o9 z3qa75@IQB<e{s$!u$)0rcGdS1`2F0)`hD*G1;XU=hY4ABtMBv<<9?e<6SQI+n!Mk) zXTu}v@Xl`)WhbwG&}YA5O3fvtPeUJm$fx-*^md<)y915$!#*ANIx)^Wkspxx)|<8@ z5Ap*t_ge=K?s({&{WmUKW?Trsg}83|t0=ol%zGO++&Eu<QtTKw_uM^??mBj?y@%QR zFyN>OunEBb$D?6T&rOQ??IQ@2k9u`V6-9bi?{Y@;EWQP=Vp`wrW=uhmxm6VNUA@P# zIGy$3KtJL5EIjArV2a}$FlVS+>2qYj0dyn7V2`<H&!(?!*mKhSl=(hZj!O|UVz#BE zzG$XhX-|F|;Md%tmi$P^0-6#nCT$3EUoIzULbeF^#n`K*o&~D(|I7g8dRZHX!QsQ3 zzqREs_|liaO*d(VG^%nYCoK5$IIq}we@w$LM;05oQ6pvnQJ3tJWc52kl4_qs-g}1Y zp;V8;3(ho>$CXBgedkxBZXS62WB+a(G7lZv^v$V5YvzLAfI0pBYk#+9U|^uBX?;`E zK>dF^!H5b`Tij9}$i?R+3?nfw9`A_TuSE$vmyCjLYaVlIi*}%_;%BKaiYqp_WWuyV z2`CXho4+-6=r`aiAor1vMDH<aX8b>wGMr^rtHmLjTE*F!vSeMCySg*EzN{(_YLc$2 zvIZ8)s)FM_Ud9$)^;3v?pZ1;CV48j=RBwxNy;e~!@9O8g*&(XPhoSm;SEgXQ3$MWY ze474abxj|Ngsivzf%0A@kT;oA`|=EdA<R~jVU9GLg;905)G<dGY0IjDq!$&bHK%Ti zKFI0{U>2B=?jX~m#Kd$WtEut;*Op56F>p<bC|lkGh~|jtagAbh{(@Z9M^XLW031+B z(Dh=Ml1@fCzNYk2BA-zcbXHYqmMUxe!_jpztEq~jr1L`F(hOPCc>2id9xb<O4OqE9 z9gAAD3RbObNhy&wSyACU<P}rSDv}IG0P5=(YO+u&)PnpqTw2(Oc&LF3lrp1b%gI|c z4k%^;5Uuff{Jil*s=ycGiYO{d6A(3(?F%2U*KsUso@7j5vXf>q5w^m~benFft?~A_ zrIwk_Otv>Nxk67EmbS~O!uq$+DU@-1ZlmgJ@Wimbc(Hn(Df?%aNzvzn=Jq~*L4Vgm zd8i0fQBu1EE7N4|8Qf%T+O&4<o;{WwE4Jwr#j!?A6&S#&st7nykXS}Bc|{QPbx`&w zKnK|@d{Z3%HKcE=DBt^)twbg^oA=PYZ}on}WjOBX(NGie)Avs6tdZHjkBnZNjBA<( zbe_>@)=~i@oR{coALGZn+UM}YhD0aQ9iS)Psw;|SO0p(NO+^~wIFZk4_GLsI#I6QR zA(=0SXq5X1?qyKz?`&uoWtw%0bdNSN91$Kl@w3tUm=TW+4vUhJPgoqkdW!Bkr@d8e zZXcJMy2bvKNwMc8n%hR0Mcv(F!f**9Z)t;ZJ&`pZXPT5KBk+7OCx`+c(Tu!iX)#q% zlaj6qG|z*ysYR?v(&7ONhp&oiDjI_$wC{Kftj`>uqH<`?*}aO+$}^?)=9Vo-o;tMt zZSBo!uDD80w2SS%Ix8HF=UT>?g}q&4Lb(W0SERC{CNkigmIds4j!xCoEmc)xvLQzV zK>!IuiCU3_$(gL88VajrR5&L()JG<&B6AYurSC<nKF$&{bv9<B_!7K+F@+Fa2AG>Z zAl|Z%X3y1|n)|r1_Tq@#mp2qmSKF-?UQ}Ami{T4sR$4zvDTcO&;|xpTX^Sxw0kEQ- zS>MnTi$q?{cF7&mgenMX-2)S!9HIIH)i0x)G@K{vA=e*igs3ukMzkF_;YK9@TS=I| zIufC_9;2CKM!Ktmp6u$L#}5`vC8o)xRQos;Ij3|3dM#_xwiyo@40DvBbs+O$5H@7i zq*+l`XibS9WtdK-Q|?qY@`_?>SQ+J<d;;Z8o(wGutqQFRZT8iMMrh_6#q+SEnJu_* zA=2Qnl*mEY^xvUGqq})-j=4P2lwyVzNk}rS(zwYobdPwHXLm|w_g5~V=!>LGa~Hj^ zuYWAsRxo6dms_JZqn8!SW{f9<NK|3zwpb)eDH0Q<Rf@5iB4JH5XqLHd(<YiyWu6Kf zVNs0gVVY%`s4lGLb9^)3Coqf<5*^Rshfv*d6Zve9g~mfm;OGy8j^kOvs@k3mI0X2U zjg*I7KT$gzvTTi_3JE58^p7IZh?LT$vr1dW_}w8oJ!wTEN3L#xubrA{nvqpeQIoEm z->vFQSdTJvI>u}1^iefak~+@oX%d<`$26MR70;H2=tX@U!+dwECJCa{MeA0^+#G($ z;J0q2=vG093xX^N6LB?5>8c)?SP)rUmRMS%0Zp+&i?xK0E2<)ia1lzBz)-p&3y^Mx z%or5MLx5tcGAl^o5Tu#>)*tLWgqs(k4C%E3a?4ccywD}&igfBXJ0W=N{~!6zK)tgN z?;eX^bUcz?s7Jzw=0$11(Pd7}!Pj;J06nrMs_Mceqb1d(BU(htT7njjpQ|SGQriU` z88KBFP^2ZIo*iW7be2Z=o}4Tws?^6Tz!2u0WHp1InxZL#XBk0~CIlhI+rh^ZX)Q+S ziXIsqiYyut8Jeebo)vTPWqbk}15n6nnke#;rixtH467PzQ9R4>oRSa(mJ^}vl7zhX zB$T~LWV?_V@}QBxGI*IC=fy-qvr>vGK-)k#tS1UR^MrRbe^irVX+4#cc+fn-CIMF% z%C_n8)@nVr0q-$zWt01yh=&*O-5G{fzv|YDd#(Y!@{35js>oJ&0BVIn6!}-Lgi|aL z(Z5bcb(ZlLj33SaJ3~hzAZjXF_@<-+vXzAtHDM^_7H+dO%xSVLD;zK8<l+N+%R?RX zyzWhFR!w#5g{i47ph<wwB?|&DSIB~_LdIpaWEtyxyHf8dl(W&5Ouk2tmR(J2e?k!U zTDbk#TzU_8ZGMYwN=Yijq8Eh2dfZ^xwcQ`#ZY!?S1sTFMMUm#6q6E%ZV48A2$MNtB za1m%qSlq$Ww6P*?>SGdR=NW{{NH^hZ;w+61h6?q1=7BggV(Xi~P`Zv~&n?}+U)6Fb z9Dzbh&~!^ECs%*|eeb*D!F537z+}wQ%21%`qOOT7Fj}B7VmYU8Xup0LzOh9$X{ujy z&U~Dx&nxk%)z=AcAe$pl?y4&C=tSDe_K9!gIGLR7<1tL^nVb)X(SGI(1B4$b6JXp} zw5aP_JrkS9$GZ!K(IRNegM$paH(%wCw`_}qMGjiY&=_n@i~zXFg4--*WCR-9gXn&9 zpgqR2Mt2+-xp0K#Wr61?&4|T2?7Rqe7Awfzp;nZWc*K?1ghlH*WjHty<tc~V<SqV` zsieR;0!`dQ#a=pkz)pR@w083Q%WJ5pPBBoK4mK}e{Nc%^cY~p!6@yj#Z70{%&2;SQ z%!=ub$0(Z8V*<yw$71a=Lm5nrrUj1W7)8B+S5<yVhbW3|k|bp{k<lrU6*Pf!&KB_A z?VI(PLpvOMt{)8<4a<xmc5HX-z@GFvad}H@o4B9Z^?|W5b8l;`W!uU=FuE2;OWAz+ zqk3g)Z>?}_XAI|CzP%-U=s;$jvNCOKkp_CHJ^R9&e*}gYusmnw=Pk^c`d|UbJ#Y;= zz9mpwrW}m?<;StXXdbY_`ww(46erq~o5XX}y@!CNXyDF~c9sSEOR=tP>&wR2rh}3O zl?_@yD8mr0Ozm*r>_Y1K=FR4g9fx-{FX2|U#-_y0+OB<@Ki$y*Iw*6}GOg8PMWb!V z?7`KwaR%!&+<n#ioaM7*7mGtf7%r?bH)eJvmy2t&(b!sXDVW+BS+ys!5ca+jjGD33 z@_9wj+6@Gu6>8KGe4>P_C1vaJB(n>#52J&n$E8wV_}u+qgT5+}SSPOodk;p6UCfT3 z0fBDiICEjq>R7s@)9jjOa$GJNG40)Bog(!LQ4MOi<S3);42?1TBDW{GOkCB(&FK`^ zfqmJP=E|Y)@XGMmXV-xdGnQDI7}WKaZm_OYT1QiZgA_flPANR6eNN08>mwA@-@|sI zCbO}xt~)oFQyc??i<V{j#nI-b+<d8=S&>>4F(Yf#1TWCCC`G6-W0^FrFZi;mvT>tB zH{+wj89mXyO3|aLygm~F5l-!0VHo--qAK!ta^tTZW(XuM!eIhXbicV_LuB9X+zNSJ z3a*E>vF-aJbD{RlJ_s$I?rzWww-s;%&BMd3ptT21VsqM1TH)An)r&__To4hj=N)|A zJ8C!&HgnL5W-eZp9hAnJQ_b_mfy^>_o4IwXx$S;MV<i!^t7d#?AfqMPb_@-H<;z3p z91Um6HK2{zgzJ5cj0~4e*2H@N`!P=K5u9=uzL%6M8OjW^+xDclh-=~(jAavQJT0U5 z8w*)wVzX9Uwjz>=fq5At-FZFS_CW(rv-G&SBNf*N@d*Up-?_VvhFm9SlN6D--aS6G zf<h6_Gpijn4<FvNDY9R&Se_DCfeA0SHj3+0u_<m!*}!htw(aQ5_*7&(@*P`xkBNLq zhYUbV?WP&)D$AzSH)aB(%{1rnqKTu#o<}DmHg6BiqPv^6yIvFBU*i;Nnf3NO(C07A z^ogn1W$`TEo1GXts3~pA(ub~RPS9pdH>o(Zhoe=g|Nn?GBXA(ATA~gWyrhF{vtod< zVV2X-I+If+M5|})lWnL6+sNn|lMN6WBlYlKoFO_t1-HKJu`T8*b%Pa+ua%Zq8_!|G zQ+FGxs_7L~0KEFe=4LRE0NqK@GCIErWV%2y7f~f4qd`m4h=~?(YB$&`(SjHZoS7dj zPX#u69SoN-<CvQ{JCO9EW$6KNPR?GA{n=&jG)G26O_eD{rRl4$UZ;tcp#Gbzup$rI zbu%&CpEhFoIVmuv+F58Rb_8TVf=`$z>gZWVHYDKQuy98CVA+XdkY$L}OhYI@ESl#@ zgPG;`nC9Eeez7!enqQL?7Jzomj1Lc_^mu+zrPABiWF%WVFRWLvu<eo<Tq*qo*P0DG zV;D~WVKozf#P^!}_C>Snlr_oBYVr8qHb66)0?j>1SF*POxJ|V8`hub)@6Y8xi!3i| zvI=8!+syKs7LnFfMb~vH0hG2r8vbr+rV4deOZ{{d#RpeWL`(JCL?p0%W{M(Os^1M^ z`Hk+!pq<iz<f^-qo~6~$78>uRZO(#X0j|7VCc|wL#KGjY^b%=Bld((Or0-7dm$(gP zLhhkP!r?h<!lNfCf!Bbt7!>6g7#fHfW*#iI_a3Ts9>+zR+QLFV!ti+yhTn7W{)-3t zeNTN%%Q<DSXMET(X$ib%R{?Zvs?0fIbI0y*c&JP1?oW)1E9K4VGetqyWJ=T7FSH&y z1jfg|9*!qKG$QNJp0Wf(vgUwoxG3P1KG%rhO5=4rk`Rx6EWggM9s;l-thv}`sAFm7 z=tQbtD>pT@ED(BflXDIo>i+H)DJF{)v^%%t^+Zz5z9W%Pt@PJKg%NlVw?MYFBW@U( z5=er1ifC6!o+Ah?K!M1ov{VAwS12|Xov4-@dtVYq@+h@_j9Q<2{L`|YGO6AB*@NeC z@95N<wN`UV(nihE(e>-0UK`U4xNYqj7e*GctG;7Kpq?~T5HpQ*i>AcmaF<&u0iemE z1}vZ&I^w-&oO8YQpff#t1J2CWr=zo+8dod?OO|Z@+J=P#<^>V<z|PF1xUxCBR#=oe z=Uggsw0ALBx^(NeHZA_KDC!biH0HFffFy4zrB(w#j%1lNJdds{>imZ94p9}w>JJ?* zeA&Z=KMG-+1l==+N})xB%yBPId;-}$FRM5484CII&PdpZ?AXWbJx0;j4aD+7XL?nt zQ*4S2F5##J%c<y=zVo{yTX#glLq(;dH#U!7WUSpB>G>X9MT(*69B0HNpck5Anhp$} zg@AK(-JqgSHpJzatjj5b;~RYYgmW^S$7k)0Lo}2`YXqJ8u-=GGoD0)y<gEtGHjbNT z-e@Xn=O&I_NsGHpNf*sFLrKW7<$I!GGje!aVXipd$qjYNi<4WPpy22HIm?zW7nHQb zi=31;Ou;k+x(Uw2fFMUC9%L2E>;SDS5Lz463+<Uf)hVl}-eL6t_Z}0^4~iB;vlMmw zAZ)$R?5@nS8BU%gbosjR7+(X`xNyO|Y?nCHT5KK@x|$aB4VnW3=3sfqTw|8Y=2{Nw z40iDAqQV*=r<$?u&V&w{`g1uWm+Q!6vRSZTK`~)~q-Putc}C!P0##Ao<?6$M((k9f zwx~L0^%1vr*6VPU(<pmL9C--avo`3l0$kJ0X1zc*W%B4Y0_&@h(UJO<!IR?pOPM|E z?Mo(Y4rkZW9^#=$U~ful2F>J}BGiRDGmFJ_ISOu2=7Tjm>1bP9G@p#cqOCDqNu^Cq z(R+uM7Fh0-B}ak6ThPoAp^DceNo7=d$Vv(vM@I$T0BlUo7bL)&kYOVRFGa(unxugm zi3+0BqDMK7^Y~#@QB-L4QE#2g>SG=Xdue&niNi(F%;=<kGPD9w%~y@;jEmVRL^TZU zFMESdcvC|&ql|a$J9ws>Wh|CmxN2-|IC^X<GlyH!LM2uUW2r3%qLB^r!mH=g?9xPd z?u|vB%d$B!&bA(;TW-AZ#*>l)jS!L3<pV6ETPzR@dCA}`ona3!tS$(HGRw?`G*jcU z!b2sYPKu2)lZT*I$J%ia%hzDh<POJol#i?>yG7#UVQTC8D0R`?SV=5rI&vdY3V;Qh z8EVM{wYBXX=ye2uDL{3K`G<6V7ftKXc9PR+s7rZ4r|DgML1-0P`L*T2ZoyzY-fYgy zog(~d9)wWj7ga^RGH{OU)%|!#hWnBN(zDC_d9T>UvUN5H1k=}(<^(C`6R{|Dj(MB8 ziXEK;m6@q!<c!>YT;+LLSZ3eC@mqCGQNZ<k;g%Q9-`3QmxH=cMHt-YH=ErH4z463} z8`af?g5KR0*Az`F^D-y$f?)sjNH%1c6DXDiF~L%cB^mGuTQ)VuG*VxwL>4ciD3DY8 z46aHiwvrsh|7%R9VI+lw-Vu*d3P%fOj2ar^V`+(@v?!J6PsG^xd+P&BFA~=@g=6da zg|WuKE=guhNfGQMa6B)>!YZpqBXLn+ILLpBsutkbpcx(GEw!x(#}@a>CzPkV`m;a_ z^xuhSS{sTy1*^XzJlGo0CkeS{L;s`RufrYozO?}Dh;FyW5^0ZP6NWH&>eji#>m~Ox zps@zD!{)JLVMdKnEmJL2Zb@cHT+(c<6n7u~m>oQS=Tx4`Ess&Txc!&CrCi8RF>^UI zYt_|lz)Vk!wi$g(7Os@Llr<2vTJ46vx%n+mp;K#&t1WXjgr-8<&uBZw8`-BlaZhL; zVT+vlr3IOex_)eE|E@3RS(9R}Dkq!8uI7cAZn-5sIH|IQ2m{#2{6!P+wfeJ?Aoh&+ zQuOHP=svrG&BVmi_-*#v`1g5^Vi`l>fu2m-nb8!UXXz-*sl37~f;zy_N>b)2$QrzT zZQi_sWmhBxLCC|O#?0BCQ>a$4qqlxTNb6IsHv6sDGq(CW1bxb}xKL#g<gMVzTtr^G z*zy<Orps#t&f>W1d*w_=LCFqwE)eIpwv-HY$u33BWtxP$l8H#l0+TIP+>ECRvMHxD zBcCrMWu<wJ#~MUckgt5f)g<_&8fAd5{=tP}y^eCdSO3!oMUk)7-xIpX_QbmtL7(<Q zt0*sg_0PT@F!UK;TbvPIbfM2RFmv(=$#uWdD#{aI{j1|!Q}5w9-_u?op7y*8{VTeG zK^ftzFS^jbHK<d0uh)OC`VwmUvTqcaX0Nz)w6UhfzG|o4w$C^Et-k6)Uv6M_LU*C3 z8+53?=A#aN+Uq_#;LQE$kk{hJJ-p#UUnQV#`ly4UfAjT#Y4&#?^uK)kfP8bE9{$_4 zU*90+?Vg}foaiCw`*R3IF}l@%_~HZq?D6mOQ2m7ILa|rXKLa@xWA;Bmd{+J6K$^Yf zn+x=`nUFg+bf-6iA{S>OzJAdh&qTd5G(-8;1?Cb&-x)e+HfN|Hd}kORN8z??&>YWj zJ}7R>`+C4_1>btZP%#iQ$xHPalsA1wA;t#zVMawzEod%g^uXC%<(muqG{Z+pP^Tn{ zA;jnPLrC{5^6a{i_2iePgt^;ru0n^d_7BRcxy#(WdqW~|n7wgK&<f2`rnj(87%M=# zbiqn0I(NgNLmM{ix_JKl`G@2YL;L}>rBt{rQh+J*ydg?}0b%>t3$U!N7>ceoD+>I7 zLX$+Dlrb|XGH^yFWP!^OC-xI7!)|NMk~}9}TE>X^JXxQO6T7_JGZUZ1e>ODXTQ4N1 zC4Fu2e5SnXdj?g9u0HFPXfv50sMBwj;L64tX!7#vi48vLyh(6c&IfItC68=qiw_5a zr<{yeey(iw;@~_j@1sM(*Dsoj8B|kxMh)WY%kK8#;PhJz#G&Nf+o86_85D&$)8W%n zcztwwCHYKOAb#CG{K)m(6NpK#3q{#%9KQNwVB0?5juiLXA4H9rfk0U`=o>f6!ZkDG z9r1~`&*I`IT+Hqxq_Z89hHCT93<pZPk-$-m5<S=w3}tqmnH$7GCvGR8wr~GWef&!3 zIVTg2&z6}PBXEG)Z)P5v>G_^{dN%amh#CugV?l9d&baRhq~~}b?HBsi-qS?3r3Qy% z{+tN15M~znG%kit64W^5K5em22H}2}cx4;b`ZG)25u<(5%(D83(YY6j7z*`-R);pC z{IQKhu_L}rv5uz<QUlm6G|)-TJ-tL{f~V(2c!>v!A+QlDYEZJEs;VU>6_vWwF!Z-u z37XLa?%sW!6g8*-kr#O--o|7tMdR5-j*hnW>q3EH?l;Qa=^{Ja+A6d#C97!Znw1=# zSh=82>>ZoR<#<k%v<^)cjV6=hRbBv+&TAapjvA7*(Xdo8V9u61r(yV3(L#6Y^Fxd4 zJ}>^FyW~Lud*&Sl9(e3ZYxk;Lk1z;T<$&DPv~>4+T`?82rU`)8avM3;VwkJDq(r`5 z?J0IG6Xv(%vxc(x>a@5*5K@ozfwW{Ah4!w3X~=2NCjwEG6h#v?<tkC61Wr%rwnLU+ zusS2~jH>1pOBU!L>uN=ylw27ou~zwb=>9;<9P{StKwEB2;QCnWJ$;>7N31)gzG`OH zqm_y^)JCt=nb|aJr8aus9B7YC`JTB2^}f~D50Wx7+dQ)USqGo(XOVR01Y)wo?SY6J zo!RN@hosjoV&By0eYaOWJ9D<jXQ$vE_6F+meJ=Fx4VgBx--|WQT1CixQqmm=v|bJp zG-{0EkWW|2M4l$QEwZ3apgsL%-}F)AMfV%U8B`m2<_KX6+4FD|eRgaX&phbx3^Q}w zJ99Xv5b=yRi4mOZ<E-;g@2IxO%=v**_yQj%UFhk(-VciDoK{`=%7s)MKkRyTVPE78 zWVV{RCl7Ig94t^h9$roe5c(U*o7C=&mbKBe-?m*qGw<vYV)>HV*WR_98!EIlDN@fu zmRa1qV8O-(w=A&#|H!IUdzLJTi<@cYQYEFNWjPK1>1P>Tkyt^KIhofOj-`2CXV@d6 zDCPxWT+_5oyhu}C%No<@Vy~uh`0Wz!I&<1y>Rb04(G1|3yv(~woPI73(s<RdPq$s+ zn->((>CEhvfzT6yl5IM0zf|#!uo`$G^E8odt6?S1oY{(<sRgdzs{-Zo)q%47Z9Xdz zkK&p@E8$v#_7A!1=Q@JJ?F<tAzV$=c?bBl5F7<k1-WoW(J?La=<{e(SFwF)%&FSHt z-c?rlyRR)dZ#Vc>B%WhmMo45A6=!ZlpS?TqnKuRLlj)pKD!pfxJo=eS&zl2je@h^Z z-b*~Kv2xz$+Ye%nkNfto>l@jLW^N6#HmBzYoqo;S=3P0{UkcJt4kqspTn!%x)PEoJ zY0wXyMGoKY<K;VM?XMc+P6V!;4->S17`D9=%`7@0oLTSFpda<E);AhwYcu~6$OU%= z&f&)b*TgyQxRFepx!Wg+Ff~4Y7T&$bcP5Ih_fG_l`;&n)@+qGV{<M#tm=2%u(4mg+ zXU}5kd@g9cPp@!$z?EtrLA1ZuH*Q?}`CUO=;L!8)K~N{_mAjvE+J1q+q_G>iFNj9d z7X(uIUx`&^ueC3pMe^M5oIE?#LU9(NnJ*FeHZc2g;A;3vpsn=Pz*Y8dKH2p(!YcW? zPeNcj8F|0Ye8VS|zIhf~^IJYU=G#HLU#IPN0yWKd1NWof3#9e;eH!-%XXb)xm#>Eb z->x6af*+#1ExUa?c|4XM1?>+Utbgn~MZ?ga`1Sw~1fAqLV|g%8vpf_CeK?SJf9k^* zxBXe*`hLVWik}CafjIp>8p3`$X#PV&C>JV*mZEsC`Ucf@$Fcoc7&gw58&xMv*SRhv z{b!wPPbUwgi9;dmR<UxKwF75dFU43qKAiu&9;N0j=0zp`0S#_Po1(I+GZGLrSynkl z1}w)%6lNtyS*^{2&hnJV(sV?NW|XX)pxC9Wd5wxFnT()ljF8F-oGhlJT7-!*Q95yw zmIQkP-zxS}oy)sTNk|!*)}*T~g@rudRL<{LfziCH7&W5Cnl(M*(CQXLl^1JFoED`% zeK2aMhNY|dWs!W65u)_D0qgWJSC61v4l^eSd-RmoGQv5C2nmPoXl5RtCHLHuy_qKh zPl0~nN*ByKD5LTW+K<ir$}8s_nfM7OzeRoiF@8@5uJr#1)S{~cCC{(D>vZ~afh*}Z z2tSmM>hguY^HRJ<eivl1R#*9K^rw83dWDc9zYnC;(*)KH`{)neDj^Ov{usDt{ZAhb zfAZmgvnBm;)~@bUeOKqK)<65K`e!`r@>$R6_Oo7H>OlVzpi7H0D4)^Hb3O_2e4q{S zLZC&3>Gz^<oG;Bf>#)y5v1Rc}pfov6;Lw1+>ci}{S^YL}c-^Z@ab71vc9GiTjlgr8 zH@)|tPTRkoML+)Cr&G{9>db#T*@Vc`C1&Oy1SU_o&-|wkzyI;gEanCLwErbeRvKe@ zi=d}_c3unlW)JmH3wwL0MS^ycP7l$beRYkz!*uH|6ZpPCJdF;rZfcB|o;5bea;tHH zCmpz7-b)=!$y(#S^A$q!yvNI#HIe9-N2g^!g%%d_>!?XVQmQ6<ZT*^3xAH>@%AE0v z6M@k}RLZdH!7hT@a8Kw;?6-=JR!XerXayhGjs^tLl>%V#@@U!g25{g5;!@c@Hl7Wy z=uA4I2!bXFoPhioIY!kfQHY2P+qZJ1E{YkkWWW7%^=e&`vQmfrHf4s5aA#Ol1tBU5 zbTpEPX4FK~cpnHG9bu?fg{Z(Y(MT+sP|c`ulImFAE6I`pWI<Ciic}~Wv1)d>n5!O` zn@A)k;Llw5w@Hm>Cvp)GQM-ndQmh*))J0A3PksRXiRR?baHb$1*U))ZO$)MVYI-2Q z89uuTw*@{M>^F@X(KRzjI@BzJXWVbpQ2p(h-}?A8K1-`K@JV>BXNUijzGtG0`n6P$ zl~zj!@pLWYTR~X@2MIxKIe=>I)|vuWP%aSKjAA8mo`nZ+458(ucp`%WhRef{z1qK0 z=st49&Z`?$fOPa|N6Q@##F|n%*v<<Spr|R3PR2uyZ~x1%zYJOlWKVYBI$8?$Q$}8l z9IE$rh&l$lgAW+K2q>Fye`_RDYE8yX_>351_X|*N!v|1)oLIckQ5;>L5RWOATAPP( ze=U<jxmbV7g5ou4qYro4#q%a3&c}}$H*<(OPR5iPx_7R%hU(GNr$Y~i5}_fRK4g|0 zCrOSIOmRlS74MRVBOGn8JS}q+9Uhez%VX-O*xR*FGY=ioG)0bzihlgKt}K7JYfM+d z@rcseHQBBeM#fE`)1a5<BSs|J1yq~^9Q##205Q!Io>sb>2L|O|trZadPKHA$vC4$M z`K-cvXGULN&d`9n_T9Q}ijr)pl0q-oae;0vS|rOnA7yzNN)vU<*JPP7K|XfvaVU5! zON$Gsn4ybcM6k1HM9aWx;ErrAjC-vO?J96aiH4_mImlDIek0bHdOya$64qVJ>|SqZ zKr<IhJYeN6i36;dJ<^o8=B`Zs+;c@yRicv0966=y6cG5dqN=>2^O{CU8n4Q`Bvmm? zQ;&c?L5x~as>_2js*+wSc~`VElJ*deZnf9$DV%3()K_Z0ahG=%g2Mri=6i-(E}fc~ zFvrFUxs+^x!BvX3E}P%E(~kO%N}953S0=uy)WZ$v=K~{YSeB8Drxc(W0uMBqF*<l5 z3Zhh-p^1W>HLRX3?lt=^qlPND*Xn);&pEOU=hgdK$U9HS8=+S8TH+4pokO&>Wq3D| zoGANot(W-BKIuidK5KoU1_!&(to8eziRnDx;&+;$^PrP~!M2Tm2%%;4%pvsIu-gx^ zVemJcy8*?`6o{<K+K3zZ|C((R)bOgA<396MyGo_=%(>pN)W#5Wo)2qu^Iu!w^!tn> ztx*Qy+Cpy+Rg^ioHs(TKK{(_+HjGn)#lc|$`4-nB$#HdwRiX7x#ubORoP;uDuz(vC zirt7u%Z}r&+n|x93e{;H&By9-H#T?XJ<MqsaXO+$qD{sqBWm#1XtZhRiX9BYrKDW0 zTpk(O-p-g*q)VgeroPTj(ACw~L^E=i&J~!M+tV$Fjwo^}A}G=Y7g)vx4{CxMfrdm* zWI2vv=>nTy5{{^}*ddMxdli}&G)>fXJ&}NKikwc%2Xvm-HI6sJQCSyg+M{u6D9dtf zlJMev+?_4#%V0p7y%_owgra)ywWV%_aFj{5hP)PP%N^)x4|IiFH~tMm&aOmq)~?d| zBC3JigX1-b3KzDMJW_=?1l&z@Z|g%iH`lTBUh~W5L5kka7rQQuTr4I#;Wr|ZST2~` zqdUjgEvH1eC!Ox$xlx^C+eIJ_P!z+anKq8&A*Fy&;!F;C&^qIAa9ic%Np$i|I^$UF zK)w264Y4vC(6vr=C40<|qk7iejrzY0{|rwae=?!sX#QF2Q`Vj+WwFt1x89mNImxOi zK5Rv_Qc5o}r6NDhE%-)HGT8&IOi}3rX)r-ie2Q(>cxicO4{xdquy6457+Yry>)bW{ zDuL~KcMN#m&<%fe)Xn6Axnv^&1<0beq3GVfw#?<7mxz8hJ8hryJZ;L=yCluGcsa^} zZViNPb9e`3?1t3s45DrDfmnPv|Gagd%{3-R?Yn2`k|pux0k(5-pDxAKPS%WaW_rc9 zx>Lz6l!T{j^cejS3#2k}wRavJw_2F<>-(Hn2#mH9^~+r773%}n!#VDHAo9M~cDNaG z$bNUa5f>!S?Q-c#Qf0S${`49F-Q)O(zv`Kpy$&C|?3tN;ZoXx*-~G<hUh_Z?IMA1z zu^lA11M52*dWe7;K70>5J$U)x2$6}l0X^!jNOBa%0=eV3+m@umxegA0_4Iq5Z;w2R zPA%}B;QYYeFL0#*IZqe5y_0P(@@X#&z1ZC;lk%{B6aS27MlKDQ5hn*v?J~D_l8-JY z&Pp55D}0&SG4x7zge3GtphTN?xb|7k2rF*Z#0Cz<8oGI}%@8Mmjc?RkEsgo+Dvwn0 z_Kt7UITTNBw|yJx{TlSywSlwKsEB|qj_VP<@Mmv#$Mu5S8&i9SJD(($?+jcCHxSh) z8qjwIVsfLq%E|eBx4X*8wl{@5GR48{Jx&haXB{nsp*Oqn7Jnz8x45->-z1>#b<eP0 zAn5l#^x3V%c}?RRw|Q$0I?(q!ZU5|net?MOYCu02^5!PQBm5BIP1JziPE=NEK<{v9 z|BQ#qANI;e=V^DkP?E|YA?lMf+J4l5KIfU~e{t~rlLv>p9O&~N=*Nf(;0@^AE*;(^ zpdWYJlH7KWcTG6ZPXto(lg`+l^*qhawJRVfwwwA;KB{%0O`)x!9ie@pBYs_Ik=X!8 z;U>wmdBRB(9c_u~4UIan0ZyPeK4NpDNr_AcFM_Xt15paFlop9DVOX9~8Bt_ez{w09 zVOYxII8ocVx;dS0?dWB@(&^M8MGz%v_ZPlkz8$@q<kTqNzoVmrYcKsEr>Z#y+Gjk7 zGPEqPlFVufP4jtyizpGM#fFHoBukXS&?=?KlFpi<C}p?I7n=EIKBe$1fYvZ;@RXfp z(nJx7HjP?B#n8sk0Z5y3XITmjqaGRZ_)ZNP^P^>dc{055jLnOTU~3H*@*d864r}UB zdp5Cb0v)7m0xjdHPC3e^&xc06)=tr~!R6^y#_H88RxF3FB}*7!aUvVmDYaLyq!lX+ zQQ#E{4rtUcM&axGEt=NC&<w}NI6-F>Xy3zsn6f2wii*@Bsgfe9G!qRoI-3x9;kcaH zDoJ5IEHU{Do0M)f#G_nhm}k1(tecxc+e3STImQ_?N^xzUtRk-Pu*-;tU;aNiB|Mq$ z>r3c|v}AvOoMuG%*cQ9`vtH_A3)yU|cF#TFD)dST%|*WTXj>~=DEuHJiD|?e78Qv? z9?-;iLegZ3p(Kt{Ay+^s%h*gIjzM;45nIKyEHFA`2TtQ@Cx`D#jvp}*RZ8Zy!QsW) zZRVUgf|`!gsT4)sHk#IfmcFN_2i&Mjbc~_7w}a+3vCu-EeO-y-K2As>oKfa4P9F0D zvP{oZ-OH0f1U)*t-P*qW_%p}0b009vWkEG{%CzVY3>zX4j4w4cnRZ$C4Y3%QqexMU z5{5W4CdN$oOnl1sU`RwcRh>GnZr1eKCni`Lblh?07r*>3cU)`s_e+rDC|MG2zx_}g z$Y$(r%h+ecdK1QwB1NpI&~G$Jil&Pp%6*od$*&vdY|J~Gv_>^D6k2rVC!hQfn6reT zqJR?Fb<2|Gb%qZILpH4kCjo2{F+_`@1bHXOWDWzPq}Z9|g}jj#WK9*^%>VX|A9>W& zKI3M@vCqc(L&MIgk~gWxEYv(H0Z<0kdd`f*<_L%!Jx(1w8l~RZQ!I*xCPy`mKM-q{ zi`gY>sObDf)P_6PM4^C^4N>{F6#<3?2Ls>AIFn0%E~#e*4M8-lgBB+z6`&Y~!$BDL z&$_rXj+U!OLidM;P{wC}mTcb{n43J&lV=dK^kL)p@eSFL5kUu#rA+qr+ppVrxHLY# zVZqJz+X>t2UHzV>>Do3;Z<9qhFMO;0N7*opVfeE`)kR&krK*l_I~mHL3{5tEi$crm z*b%|aPIdEOtj@dyto`O7FAH4iz!X?yPMA~sTP7x^7Jblu`{v!CyIasrJ!+cV-Sd&V z{daVohw{!)4wwd{t<s~aYA^hmFUz1w7AZjUX<E`GRY9jqPCkj+=jzmUpy&qU3T*e^ z>pKVeJhGZlF8bPiL?suyzRX<+`me~F7&sCp?N%`zfKt|1->>dEJUDuW39~~vM$WQk z<9o~l2iCHhq|@xGLsWmqnl*b0V`J;a-etc*wcC}Y;93%ayOu0n2H;1Mq>C$6P2e~_ zY(&(RVuzwA9kML9Gqe(p%SK8TBSx5u8wpm>M9!0`rH1^lYWEY|c?xkRj(XqZ=GtJ- z&Y(l1^-LRfaZkpVX~PyFIMf}DbQ{lhGmIrJ-!u>E3j2bNl4bU;yKa~hUcZQDmSsk7 z=Gd&##I^`=w&gHuu-wfz-z@8jr0S;xNst)LkdLUksX#WMcwJYIge8Mzdt`YI8|FkM zDXN?-P|>iqL|)7Zs>Go@BDNL&2$ZA=bVoT4XWXbSFcv2h#(Hn`Od~}(h4Jb8z4zX6 z+iiCky9=dg_XyKfJnwK*M~7$_8U=vx$xjZM<Kr7GLjvX_t8~#27wZ<Sa*RR6wGqR} zK-5i|Pa1}9t`+Q}*kt_}JRh|$5mspf`em>6SVI|iYhMlFoE13Rm4tEx+T&{sphW2H ziYe$ZK*eM17%(zs?)_OaW@H}wImYV4?CN28WXasc!m>H_ojkfbtl|CX*W3(WFNPk4 zPvxOTjA3ey`f}BmMn*0-%{6Jm)Kiz5dKzTzR3>M{<(nV<@HM$MzSP9BW9?E$v$i1) z^d2(n$YuDP{p-%Nkmm=qj}s`v2<c-LFO$liL|~oCa(8^fH1(cErV=+)O4lWBNt0=T z>~SmEY_^?bbPePTxjS_oR6Za=vwJ)G`N0y$4j05O;<+ly!PMc@hai#$vuAwxQd2RC zy2-G2$Usy0jlmdvD6c4;Wr&6mgZf1=g79$mt1qFO3gmlO`v!6T@N)=7zK6BCm*Hs~ zeO^OehWIl#4;r2=EaB0Nk!%s4ZSZ2-?+VjwH=6TW`_(PYTBbNxRs@+gc>WeJxN#%s z>UwO=q)@QbL@JimGU<6$$sUDp;F|Y$E!JD$+G~PO{}X(=o$s~r?6UuHo=~sGvv=A% z0y-vgcbVHZ0t2Y#RghGYRy=UP92<LV@+L`&f~auWt)HAPrZfdMh$$x6wE=W`YIfDW zgXH~p5mmm2_{zdLuF)M^8fOXgS7dG=gBh+~o59HocBPrn#F(TEn*VC<?^gsJinD94 zZF~4)%Ph|kB(2E+!m<r?Q+)EVvXx+B`rKmsyl&Ot4Q(xmgMt=eB~eIaMO}y*AP;8> z?>A4n*+(2r)5ts0NK@z+P-OWEH|^zYtKHhjGJv8lSk9Xg2Sibgi9jEdO@XIGNnWG^ z9%!N@s<JLDTe!twvvT@e_@b0lL2kW1ozi1XUzcP?;0>sD1VQ3>2C)2Ck1E=>YsWm1 z*Ljg=RVaDof?<FGwNL91Q@XCijHDco)z2>Qtb8Bk?Rd9agAc9#8uD4aax1z+)ZuRZ zG|GX9vk01v({)doTqm3HhOimFXf3D5L^^Cmc)mTWsnPCUabtA-$E{S#0`H7cl$2l! zJSPb6S+ptvI*$<fA~h(>O5~FmPiED!uRJf<8ZpBcUQ9vFJjHJLprtE@X+ZIs79wU; zU`x&F2U0C9DKK|=0<`a5EolajHyxrWsflS5I9_&EH@-RjA>vJ(yAC)vrv;P+AkNN? z5Usn@K$X=v9Cz(?PZ_7t{I4Ph;Ep<`Cekqj?k54I$=Rl+WCuT*SHzXkMKonF>^Z+( z%POfT4Jl|8l3Hsd)2p;+B1<0xsv*g`U3{C@n3$I3Ik*{@Q~>ucJP$Xj$G|W}QE(TP zlX-D|z7;Y?HfxW9K|86FkeA1itzKsF2GhO+BHw+p>6AyVBadmX^}!9oN3U#&YuT>e zoLU@N(5aRe%T28s8#W`7INW9GnqbBOok?rS6y1BPuE?tXsje>2A}BJDl3Gm4YO#1) zD#XJ!6C@E6@C>EX+}oC}NGr+3<Kw)nDMHA}>iY)Na5+ykrrCVw<hz|+?_A56^AcJ| zyU9Yt6?y(}LJhYmxp3y##l4-K<!ZT9>it+>A9yFEod}p_mJ|7#ujo}f&Km%o#t;BQ zMknHr`d;G4h(CT33b|QcAA|Nx&QrxIAWfeA6F<|96vRDqj=6oid5+R$9yI&<;9D2< z>&2{^u!|08g_PFEw6*cM96kOm(}bI~LMoL^f^-`G2Fg*2i!oV+lji2zc)(^;_4C!! zc1DpJ^6joY=&h4jLwWUT4~M*MQD(r}PYLKr7y2_7`Wn&p5wub`xKf@D{TS8X2#w-^ zX**&Xm+*SzmR8eHzi!@g%lY!;u#_8Y-F<Xwux>5A8u|&6{Vnd^8qti*4qdNUZ<*S* ziTj$G_8D`<K4Z>!WZV5qBg>cGR03mQY^VjKOVBhoK&doVGQ>LnydL@yw8dhm{sDm& zKC^?^P38emzi5sa>(x!>svB-NE-WrfP5t@Z$CM@Qpl`$SA)M(LWnF{zkAm(~8-0~f zM4~OH%yNBh?RzmI6W-hmP^E8~?|=UeGrTA&&@7aSs>aJ=INU=`igW1BuJARvC6F`& zg}uv%T9T@~K~~aCtHo<e7iW#c2#_5dUWYjFAsJa<^|*8g1#%s`i(`Hc<i2X&eDk?r zY)~GZRFi#xG8si0>(tQ`hZoupZ0>@4W>e{)DFF&ao)x4<CX|OzO%>Z}@KDgDA4}xB z9?t<?zCSMxigV@syWVxlXi+W<M;DCnV{>cDyk05YmD{vtLB?!ZGq>0c?cccG4$@}M zsGqyPf&3eh&wuSv_cZ=Z0{WN>eSv_UbfK>j&{Gcd8E88<ppUz4pC_PCxaavV5zt=* zw*B`&=r04IzX~<#4cbstAGG!#fo*^7LSH7@{>Il9Lx1ZVF^2xmM>FJcZujm$PZMo_ zAM#TDNo1R0Pu4#KKJ$-0D2iyT{mJ$ELq66ulv}Cx4DzDFV|fVWSj72ski|<{P>w1p z4LhM1^{NgwXQ5>Hwj8&2wYClQjo~eVYRHPJfRwN#lQVQKmR54Ct|z_&SDf*|4}LJ* zS1L{R_4TdLb(xb@kr7$LoI8i*G*Of%yPM_i(F^7$jjbttfESWR627{UL8E=v$p-XS zRBh5;a~+{6|EfEie<EA=vS@f(kjHq~*J2bY+Fs32FE&@MEN)Wtd|sACG0KZ#PmeAy z$a1Qdi?p;yI^~XRBpr!H0L3wrBW6BYOh=nUiEV#x*Ro-8cw*mJN1_Pgre@4X?s?Q4 zBW38_DhrJQoiSM*B1DD5QN|S0EX^xP8%pa8h(<K7PJtH@1yGbg?Jt2m_SXQuVQSC0 z&{q%?dGObs^l=RG;IF;tTf_KiFZrH^+rI4jM4cvlqF!-V_G_r^X~es@pH~B)`I_6$ z8*V?v+Uw}EH+*v9X`;6`i5zT=C;bh5_JY@k8}(MKp(x$jsQbLviO(?h{}ni<|Ay}} zIv08|^mAvmOrV-fYeE}C+d?}-dqamq=eae<FvG>+rWY+3ydN5M?-ClT$z*Y={W4kl z#XS^r7vM<AuH)p}k51fEjYi)s>7pLZ(e&y$yd+U0lhKLM(Oy9k7*)3({bn>K86W=i zr*Ft+dz<xKrBoViXXvakk4ZICO;^ofMwY>S2a_$(`PI!WOmptC0u^1FiYQ^DpKH;e z2~F!!zJ+6Hxw{~h7ar;yv*Mg^k+e;+U#mEdOVV8Uc8Q9LQHl{MvCWW}s2rgplte|K zZdcLG{?E`Ft)CCpYl|)nEe<V5IbODfc83lIXwAANi#Mt!)Gu26S9GJkzsXWFqr~sS zmTvsiyyu=9Z%9G8kjX@Q>12jZm<8h?dbO@wr}d)O>dl+AGJ0)=f=vLussuNHs{}<C zjc#2P741{wi^t@_@k7Og2o^;diK97=r<5qw%f{(A+p(mNPq8U(!1>n{L{?;ZhLbo( zLca?vC-KN%xdn3SA48AeO1t>_347XE<rC&&bDO!<oP6YMyDr+i`GOsGd+n_kQI4Eq zJui%NWtI2Y7{l%@)+OeVBMSgnASH@w)T9)lzof4PWBd0%)&w?99#r~iN=!qGpAn>y zO$#>x`zcKjtKUN#Uv{x_p3($ynl#P(?s(4+e|XDR43C%QW!Ss&AISQ&&&{7jc6hNd zGP@tvDR<%tO{kw5EHQs<F4+b5j*){=U|4A?1GnFi_1sWNUTJK4Y+>KzWZ$r)L?v-; z8)Ze~gRO%c(C46i;d7xsqvtjIo(JDe|FfJYC6_&_#Z-%msUjEI!*vwI3H*$?#*S7R z&|t~HpkU~AZ=P3?jg4{-*8a!wfO*NO<NRI({io~sgKC^RZU5KxmU#m~-y+(Y5Q-wQ zY{!rgb5+=Fi+uZW4_D#bgIUBYcH1a|QV#S5+}458zNg__iT~w7PdA`fF%I+v&(m<0 z!5s1(`U&h8McrJ*yFI){^dJ!4JvI&~lIAMOZTmWb!|N^-RhGxO5?z|r{iOd%<f4@7 zr@YSCWVbE$`}il3i_-YNw7mzMB}KI`e&^oKxx4!2xs&Hk+{s~QHqYjq1MCu)B`d-% zJ7Jj{2E+gYCJ<BvMbza93Pw~EB}v)^#RvwF3`>w?c#p5Us&935Z-MXo|GxjAcV|x5 zt*$zC>ZCe#PNgFD)PEEG;<#IH7FzJu;xxQZG9ANFW5js99E{b-ONZxX5Lrl_w$mo@ zHk8fsK?iEVwjdJl>Ucfa&{D1SDAql}96<MhNIDH(-f=GmRXi=;R&<H`^n|cc0iwdF z63<qheQi{;7@1L7o{fI7lNC+Z@y6OMw!P18KE&(uQ&pf!X<oarHU?tm$a!)r%wE5x zuVslcy9LtH5fnu|9VhT&LrQR=@V3jejPd=JzhZ87zN2wCjWR?uI9%(g$eq!=05cIz zr-D9w4=-tA_u!r8R#o$;2Hy37(EM};ej|%xD^Wl2TzWbe@vB|C&>CXYE<K<<R2!Jf z>*Q|n@&=;#PIrcziMEMKj-Y9nk8rvkkMBhS8xp1xf)k9N;6a}yY5hRfgT5Nrg$*9` zO_a&QgErzgt5@)h^V2X_;l4wdwjrjb-CGm+^I^7w>3j&|Ef6XYd)mE8)DYN_&qtnv z{j`Rl#Qq;&LqvG_D_N;$|4e}H+c8f5?$2|4GnKD&;M(m+h#oqF<MrC2yoNRJKJCz$ z-?q!+jxTuY-Azz*+8Nn1MB5&M>-uBprBEI>-G^5I#(a7-*H7hx0|YPjdl(G*eWu|} zqG@!~An)|>IP4c{pwqLxw|Vh{-rGhz=&J~49(2^h!}A_*n-ieV7XoxNm*CL;$mU@v zq*|0?lHky96Ih=gsYG1En2_lOp|)=jZ5QHMpj)GhA+$QU_of#eMQ8rV#yp(8N>EgO z8uhcp+u48fRvJB93ZE^*mhc+{u9su!0&|nNF~5PG{2DR#N<4psmJzO3V$OqZ1Fj0p zsB!}Y^{^@!F*&_DwD(A?uE9}|<apN-yZ%8uhING8d(?rh58>|x0)HC_TK1`6Bet^8 z++cM3^k#xK{E=-T>fO6s0cIYU-WHUGUfb<NH0WVG-W||-uZ5iQQ7>+w7oS=pWi}-A z_)5xNUpIDs+Zm5Bd#?QUw{MH7reHEa;MnN5yV<&#nVIc&FZif!_dLo9{Cd?;7iD91 zOl|+TlrfB2!#F9MZZk(xf!gODj*r0+zwZ$1d@PRNML34J^QL!svwj9?GTy9@!#%v| z@73{N5m3M1<7r%P!p1w8<P0YSZ(@7A<wPRF+h6CC2p!8`yOTZWYk@tr8`I@W#M>&l z^PUb+;2tW6JQc4qDSuBR=7#0Cm&GhhRi}G1elD;UXApM=eCV0PJt!X!XVG-c>9a#^ zQ4c7ZJ?p&fZv^y%_-*9MpF_lj`)xl&XrM0iTw>3eP+#!*@p&|9<z)pkAw~HdeXqB> zUI}PK`*6Q+5F<OEn6b}g_Ir}}8LtPlm&b|y>9?JruF!|Qx4jhLbdz}Bze0>`imG`X zz?Awl(e?ryn?Yi7+LO=Edr})g3k03{lv>1k6S;0BY`whc&&|u8Wma~8H?lI;NXVTv zL+E2Z?OaIQ8gkoS6wnldy2pnJ>&5TkVnUMmSpNvt&q$j5C{_RYSmbCPm7o4Ne0B*Q zHOT;DK%BqJFU8V;9LXo}>XCGHnb-Cea{Z?-C!)*UwpYM+ev*)lW<>|^u==UsP4wwc z6K&;6UXtn0z<xdppIwQmpOg$&VHx{|>#v^vTtJ#Wi?osHt3#I7-wDiI1HbWktdo#j z>I+1cWgqWf405#TYl+?yFaqLU2l^!lo${b>c(yvi;&lY2`MdslDo^}!$Qu0$9Q6$Z zzBCxS<d5&G7*j_G=#3%%^R<Aj`vSUQJN<RoJB<39K1gUPkK*y%grVd*{1+j&{jq<O zDrs)Ua_u#u?JdMzLZ1tLi{KXi+rAyN{Jk08ipTIO!5?q)+P)mn#lJ)7;%>j+CFsV4 zbx{2tzK8FCkt6#)v4%c&et^e|Xyb>0e!a>+UfbKTRY*#(9}(K!Lzp)`L2z#OZ9fi4 z4^l(;NhA=bGYunj+);b?cTn4(!j=A6V2^s9AFrP~srtvy3CZHm`xlr4kaG7fn%y>i zx7Wk#o(*yjfg=OU-Fu0Vr2~>XKMl{jr+-P@bn&0TJnPf<5n8MJ?12EjDi}vA`5;vW zqjR=6mIjDhJPe;5!W{Dm!KDuq9Lm+~-y-IvQn}6}A&K*7fLh$swukX}ensHjhyI$l zk?zmvF^m}`d4B`niJtw|>*t8)OM97kXB^JRUDaLiKG>=7+3yHB^C+I}@2TAC55a6! z9v%FV&?S7S@i<lgdLnp3(DT0iDd_*0{xh+jJ_Vo|{srR?TBy^1C1#k#6oE$eB-JK= z3S;#hqTjz^3PrmZo{dgFLvS5`U7p1f`(>hs=b#;9c-fRuCA4GzAJ;-l2Hfr+iZjd! z)@Q(CuG+G)a@Ooj#~6)gm3We!JuIZE6+UJ$Ou8?V<kOd(5UT=J(bG3ok4j5(Vq%>z zFTMeQ1@?T)y5TU##7^D1^;B+$YU+~C%Ni3C1;MIPdCmEnD6l-M@q(!UmW?qnOXq-` ztC0X}w5M8HQhg$p5B?r|9_LyhsrLoK=J&bfi&T0;r*?d3cOjZSLU1*IWnKwpIrHe? z)ez4_(AO}1A?f`(g#I1hc_VG#H}JjGBN&>WhIxUe-y&$lAN$)LJ-z5@Mu?u?A$Sy~ z$jM=>jU6H0`Hx^FByZIJ#9Anc)qjO7BQ%D8dt<1`;{PT%#s3ie-(QD!Lw2ppDY!xe zYa;$T^95M{s1OZi0QR22Tw#S6eg`qzg6rRxoq3^ZvvNd-cWAOO2iD5ST6}Vf3B3~B zTFG>kMCnja9+yfay0@=j=n*_M#N{8|5cTBIDa&CvGz|W%v6k6Oz%S0;xzijODZ<Y? ze>xV6j;v#1wxPuY(W-5V3A|xh=3q1Y*=2HrBCDIWm;h#6vUN#hST!NJhpzR%Q~^+{ z`BqKQod4Gw)y}3=8Ak7o>d`98U}I+0h|pdy*R{@BBGw9Z47ZKb^lVZQfT&x7$!m(i zaZ-(9Dn`P^m4UoLkwl~|G8$PJ*%8?lIWcldWM5<^@=^c94@Fty8W@#YutZ_r7B})} z(97%L{5$N$X(stlw3~Z8-5=)(<X6I-{b*;LC&b}IsGkGItXTsLr!vto(GY9r0V4$% zpeh_IYFZWeguya~VW$LB`l-MwoG`m88*?xGX)zg?q7+s1%<|>2MT_)?hS`!7V;P0* z)-97`lo%susw%QE2YQHCMO9V=o?o-5OY9xl*0^w?xw*$|9vrQgM>ej#EgJpU4YDNg zU%i?+s2QxGWz`rPt706+$nydlRid((*Z6u_t{E1^Dvi(2Th$~<jL6H$WG&CL0_UE@ zWZ!)?@<QaUi0IH~4)Jj~%OTot%Yl{5T5+p7z0Dzrv>7)u$sNG7GcGK37eCzE-LK5) z>lxyQTDu11(Z23s2iDaukM{I9?{Y1=$0PT<)lR%K-#~Hq`)vF3c7s{F#<uVO)9;Vj z(5Ln+-TXtC(d8M}yBXo(_u`e<JpY?5p?e123Ao)aw_j!3>utMRmuyih0YNsEwTfW# z@}a#ex<Kokz0dsh@q^7B;;bf)8>mwo+nd_O&PFf7@=d=YUV-&0lpJyMO1ZI?&Tg)U zk#{cnyf4;xA_lbPo_q2@2exh-nbcOGnLx9Rl!HVABy`)X&Rlo@ac4ez#xeH*flrtw zkkj!*n)2If&<{XA9OsKDlB>YE;~Y5+%Ohxg7ho>If~$e>o<HYNA|}DR^Fk)W3D;T~ zJUSO2k!z~CV5<)8XE&U-rO8?Fyxllk?QPz?X9Mu+8*H4n(U45h>~uek8xkqm)^{o( zqr|P|d2<?orDcIK1OOOz{=Zu_BwZ8WC(OI{nlp<#omGzv6F5vieEjK8p1SK!a1ell zD5KPCu9gV%sRc4f;jegc;0xF&h{lQ+N!lk@?L2hiJTsy9TB8Roz?cT8Pl4qCEU!-L zgLC|>N<VXOD8k6|T6nhK499ejN5MpZugi&Fy6w8_e(<1u>81C8SzEfmW92UFyS&rs zM}li1!xK>R-M3(*seAXRIXJ(hpTUGD)0y!3%p=F0^4Bv?{Ia4OS=DCvbW*oIN&I2n z4ZZ=uH+D9s^zKz`I#u1Q*W{c(dRBUWRIue}$j;gaswQ(sU77R|=T|~^^|>vw&?|FE zUL4vPjqNyI94`yvMQe_^=a`{XMsCk7TFbJlHpHSk2RQywRo7Ks5rHgQ382ZK0f2_M zWSOl%R4v(!6(=)z7hvwpf{Hay1cmt}3p$MaZ*X?ts}8@)dUv%NDUob$UFUDx7u)li zqjiiU-B^j=u(JA^FWz;Iwu57;qA`an=0#rA&Yk1*m~uGaD-M;_1bQ4A><irec7<%} z2lj=aue#cnxGI~kUT4or*%#h$=Xu6@o~^3l<CZW>m(@$^=Q?!K<k*HT?ZzW%7~?|( zsI=r!$geB8XKSM?t*Ffz@`fd{db54;#mBAXVoI8C6nTczzjv;>alS(>IheiWPN+fD z9yLxpO!ws6RR(fDwXd>Aa=D}uv-!;Ccu)1#MT@qL-Fcq8mUBjG<is{ZR=&Py(IQ8e zm*0KajR|w;8P%SSAT>Q+5wSzz5MD1-$sNHTmDPK```w(LI<rUV8quOQtB8x|T36b$ zW-aWx-x8|;s9ijw4UTNDx~iUu35FwtIZ-=v*+4@>1B_;T2}Z2DRauA{z@a;ol{*Z? zObPasgn?1ecyPX%>9^<E{rzJLv&{-H_ZuDYxFI>?iZ8VCNua4M>4l5>m(QDLo-9iv zl5+A7lFkpvf}9zb^{y1lRtZ4J%96ZN<1MQOWV6}jimK%@nM!t^zq_YU1q0G#CF|zP zNLCbJ<U;|#JEF*5ejs8xG~jYuH}Y#`WIag@BszIIG=vX4VM5Mb&82FED!^!M&C0Q0 zVBpIv@wYWFFt^oS3R+v|J~O{{?$V{KUfZFzp5EFhHs`O<*r=l}07=l+&gsY+!9UlU z&X1L_tVANwso1I|nX(2<$=NftFp}UAc%v|UWeZ&d?vFp|=rR`T=zELfi|y_4n=Vn* zm>rY$-g3(oU&-eYCvt76hbvJ_aE8>*oc~YSd-iNM3|?|9G<C5X9d`EF57*c=rzom> zM|{o9%o!Kd*lw>$2k*~D?t}Y;-W|M?>k|1NHBHi3Ac}M2bL|an-TcYB<@UahoQe9} zbm^sM6&hnzwq|p&CY%TK5l4DPe9JaC>LKDi`%gQS<>MlA>S^mtLsVH)<oQv1)L!>_ zpzEw<f`(o2MJ&5ydV2SMckHrv-?lA~i4v_pWh!VBm@7rzRtg`Hi~)OvrpnHYBw@hr zw+&lu%`Lduw749w)A{@+bSrN3yz`FRZkuZR0O`{ohcQ?M8~YfZhZGHCVG4=hiEjbs zcrB!GTWAv&(nMRUV!IVGM8DPWyv^+w*3>Li6DL)!wgU6E7HSCZhyS)(Z2i4JK<jW@ z^fqWe7LtTlrSi6X0Y-T2?+l&Z<cM$JljA}oF>36CE5LfDg(kw{JB&xtjB{K;|5E{G zXe_h@y~<wOR;Wu@(6{n{qXTpXZyuwX;P15=oX@szeB-m1T=Lnw>~$+OO;i~}6bEf* z^*7oNY;lxIeO+fd(TlEJI>yG}@<eqvj6`}q@@F_=nBB6F#q%KX+z#~<8)dVBd7OtT z`T7VSPbGg!qpLzB--`znIOgOQQJQOi%bp|1`CSY<w%wskaX?iSov|f;wmodGwjYsI z3mC15L@O{XQD`)PxnwRHe$&>ii?^lIo;Lt`q6!_v=+T@GVT$Su`dA9Hh}AVKr-t54 zyMoz~3ouHi(1U#sFiPgUcOdPc-g~h}6;?|s^g(Dp#F&NZuQ(FA(YsebxpRer*Kp1E z_rlw#-D<bkt?<KcX}Qh5&AvlXWu3JpVbC75SK5bC?o9zuTU%38TMI_Js&n0avk}Vb zH*H$5F_l6ye%jlcXvPD<GgS{dNbD?3&tB9-yb{My7=mqw@lCT=;Vo!%hXN}LI42*T z_j~hn7ZJ|mS8k63d$*hZkeO}Ib!OYLR8a+m(FLwI-fJ&yZE4vsckYj@wTt?c-nqx{ zJTJ*9M<khfFn}hUTd`v9I*>O_+xK-nj45I^^jKObpPc7~A=U?H_w*!?t3&<A{dd0A zV>dQlT~}v!cXyBV^bFY>mTQ_Iv$`M;+I?W@di#-#qgS-H0_W2iZ2hcEqEAt(K$VnT zxpH((BHI;+w<*AU6opah`pgOOI0T)GcP~7>@u2hIY<2G@pc{2Q2i_9thgVkzgG3n) zn|9~uxnP|?{v(xIjdqo7RXdt}TN~@FSe5C>vP4`?EKIO1ay4H!QC)N>_ZPY@%Fc4i zjzJEV+276BTn7FCn~5<dOtd3qT3Tv#UA7%u<+`%Do}Mm*t>ls=Ln{&q&ufkLDa;pJ zSO6&zpc+fgs=7B6D7Uqdl;+=0yKoKMeRi$H#|5F={<hu438up5Mm{>S5pq{k5a&5s z<;FSS<dY9I=?16C?df#8stCH(IAV3nO4N#qnI%gGmsv(SAYBRzL;U9mv4V@RHy*~I zpm`m*F~q@8+c6@iuZx4le$C{<652PsDpvS}(UV<EiP+-%qWSY-rq9AMq6c51Eyv?~ z(;wf&TIyU@5P8kq9#%rApI!A0zlXx=U=B1`Jt<#U1D~xVPAL3utR?b1`k1;mD9H=! z2wWSLjBsAtpJFdDg2H&Q!hEbJpz$rP)S!WNd|*uod}m|h(bkE7a`E2U*<e3urg&HH zz0$pnoHc5Xfzi>rQ)28#2IH-|qrNGU##kcTXLnngAvIZji^bmh(RE{E4Q?7Wrr++< z<z;S7c1<(ol^koDy2T5&BD+MW^!DaEL_r6p^GufIR;5MR;QX#A-aL=^^DJy2_=>;k z8>uU>iCD=;D^TyuG_)>-&B0g-^tOrL5N-Wkyal&?i&%jp1oSY5`lnZ~6IAdPbqpxS zY_hVl2c9ITD_M#B^r&>3SDnN=<1cIvQQ|v(zZXRD$l%$5hshoIWcn>)ZpQ@U0X*oj z#7T<V7Dm+-cF|_xoekmBac_l=qfu?)c<Q>HK%ANTBRertsTc5a<c^9jmdtcr_p@!g zciX#nZ@U950cV{BmZ00wFF0eq+w;L5^&K)3ef7ON_Uy4wJ8kEUan-az5vXy+x*MDV zHf{u`D12K^Zph`D#3q;#K!^SQ3RVmWMnw9;*}IzV%B6*XVXj`YeEE(Y_IbIjW3r=4 z)@@z%D^`&}8|Vh}=7F&`+f<B(v%9--e$>01xx+};!pTr>xEU@{KK**=f5UgCi1+$F z1~(ehdGl&bH56lCLQ&@Q&YNeC#TLjzvHA16C$y@uM^sBS44F%rU<4d<%t(_}Gt2oc zaq`Frn&Y!DV^k9Pj7g6x;b~1$QjQPBn{@$*a&ui>9ou8hVtaZzuLHc$*WK4=H#IfY z$zP4fxwsC7!JNF>&<BR+a<==|2`4xoap&D$<c%}Wj$no=dV+Jrtz3U;!&ZCSw$poA zv1RjVr#Y*+rAv}K&)hmTDssEz@265A1#|;sKyR<}VQL_?N;mXCR^S566<jz4(pv|N zcY6T(X?@>j#lbl=j6U-%Kdjc0EH}1}>uhUk<yz|F)lK=@lsz<OUazREZ0!*&Qx~nq zA)W<Ii-e&jj&J67c8ij2p?VZAJNCbuwX6eCQzbvk(eLvkZij~k8_$S0w$`RO!HR1( z%eVA!xokGa*4hbBleIJZtE_~g$4o_v2`618tnK6kT@@PIM9WccKy9zUB=QTnxeZZf z^>satRd05kS=qbDYJv5X_qRgoLl(rLh#F~)EDhf?a|ahlDRVT2XwQb?)_Qv#0KZse zfONVlX7DjHn#eGwp*jLZwq#Ql&N1UDO>v$HQTG{Z5zn|=zjoJMU;CwT9XBU0i6WE9 zus~w<bTb>Z>IT@pY*n<Do7cp$&a-qj@T@0S71hzMf|-sZBav;9eeS#lV2Pf5OMfDX z{Uv_d66YVHtUclHZmc+ThlXiOM_bIH3T{A`qc?UbRd$uq%5bL0<+cclty`9@OKi** zY%^2SDz>E!aVVO!H63UTYMan`wWbKXmB|5<w`9)E+TY09wgqAd)snZXoE42Vw6Mv9 zqqL@UOSMcz;H>JJ1c)&!ctPM>Pdd3p5(HUy<gsFiKvk1MV^SAQQ2_}-(R5XER7Ydh zS<#rRa2=@_qq26IbH2hFMv9FYRt=kOiDx-UlsUu7axoLsvDHSDktD7&&2R$m?jaHS z3=YG*7I8nZ1;p*k-^&6`If3DAk+~JDTF@ouX4P&}WL`78`@K-&Sn%Fg;Z%I<_hkZl z8j%stl^3wmci{{SeVu@wN$ue*+!jgGvmx|!3`J7!0|BU4g|`5!d5=Gi+roawVWqpm zImEpre+(ar_&3FU=(!k5wmpy9!`|TAJm@}rJAj0qPsPK2YQN(|^$Z_76CpgHwv!n8 z8ZqN3e1nc0!vQMRFCgxP`)#Ljzi$xG0+H9je_IjX9zR0#TcXam99m-poe8zQFto<x z7%rl&+lQ%`yqMa<N2rwgQR3de5B(U%Bsq(Z2gmE-;Sy@Umxjjh2^yt(Z7&Pr*MnY8 zWUBU|S5Q~}lT_?{ii-75W9VB%51%2j7x>W667=9oXIK-ua1}hSKs4!|3(mt)DjOqP z$t){`$NN9{cHD|>$kyq{w^)1|$o+RX12p-#C}VT6ZJU-F#?lpz<>T1eA`2ZTW6sZp z4P)DSdwa+G`j!n2E`y(w8I%lX7t8RxXsKB}t8S8|s8J;d4Gj&atGd#zwknE}Rg|TU zh1Bl+pTw_+v(I6AATfD0mG4|bg?>In>t6`b1GyGor1o$vhQ3WezeH_&9hFkACo*67 ztNG<1m3VExLZycrsQrEwW9Ll_twcNB7~BWmH@+6!GamHo1h4bQ_YI<!v)}e0v2Xph zHwEQ`*Y>}HT+M@ilgKsWLvN;z?3N%G_MqPi@>>u3ZE6p<5}5PHds}G6-+`Eek=cbS zgZtm>=X=z3`975jen6$JA5vC}E8I?{jUQ35{A212e?sL<cTk}}rQ-8v1g-dQyVHX{ z9l+eri81)lUj+B5*Y90as=XV(?O#L>_Ym0eq4#3wYXtN@>I(fbQaPD>D{>Ev5`gh^ zEtSwbR~>aL&tN@PkQA;t+B~=h7>!IkzG;oHWLr)Jilu16rj(xOFo%FulUmdiuZm|( z&2$XpT6{0x^;^UE@4^GbZG9K|AcWo@@|VC&O@)U;P#EJ~I7C42!O+80=p$aGLwBb= z=vb*C|G4Mgcc#43US$sr*{f#D-J_!qZrQR095}$Q=(5`8@PM#20qTR6b#Aax?X`E= zz3^k{u3cYn(~W@Zs;jR%_gv3Xem!y*Jb4QE7|0B4{U{aF&m6gAuaJiHK5^cHs?LQ~ z%kBcpz&YovYt-w;fUI=)%F;48suy6^Rs-f44aC(r76$JncJv2|UUjf0XNuyQt!!J) z&SZw>rZ1ZxwW}7|3l`Xmg#n>en0tG=L6s#bW+uD14l638PX~@w+|dD6uU;qtvCFSG zbDx807#m;s6;X%gVGR8>0sRGrK1M*@b%hmtC%@>$qQQK>5zRZ(==X9$`r%uy;l)*Q z#=O@gOF-zEEoXBlrnBmLW^DqnOF#d4d+**kiyaGUt~=KS(xA{L%zuOvYE4VjRYjMr zT8EgKfg#HplN4D_CP8<12M5?RIoc_B$D!~W+8heM4OKUOveFiwi@LP=u;*oR=2S5i zQDRGH8cDQ<Pe)IeM=g=HxJ-Jfx|P|+*i2I<p(fLxwuIrO9qj0uF%EDw`F!;P&2lU~ z6nO>XrXvZM*W95n*deq_{rC8}JsZs#2N5flvp^HMn8haaS^R~!T5jg)YtK37x<opi z0883y8`<G4o90WZu1otsgbBSR|G#(-a-Y5T+dg;l$sb?_7x9Z}?>r9F0H6aMo<pLn zrEXs2S+w`U5G3-=m4r*fgN@d7G*PvB6$@0sK`W~(rkUmo-!@fMGrn-<tm<TJaE!?$ z+ir*_k~SFYuI=Vq(v5=~+!UF*bSzlNxL=LOn8lDnUxcSnZnnOfNCV38+u{v|iUS`H z>WAHdtc=!+91|CkdKdGN9{?4|_GgbjKDKAihhjrx%!*5vv{r-Bx$VNp@@1RiDLEC7 zfo-7HR;7eUMwJ&}PO!r7y&6LmYY0LA06AZ^)Ap&z-OgAc&#C0-=^OG=Fx7td8t#^u zWhFAP0iI)S)vmn$?$vF}8>&D|?^)mM`E-srJ)}K9X5-*dm%5>MXHFC;!RK$gbK5D7 zk+15ksYrZmZTv)iV|>w~W0x+t6|Afq%rYP**Pe9J(#CCd?zmG<|G$H?f%S0<k9&LN z4OmMS#hDQ!_sXw&S)=N2yNbQZd08sQ)Fxz}`KJ1*FX>M_anGXMKqhKO<?6-R{{k*o zF})nKf%s7J)FV6}KT8!(<psq>qsylG%sjiz9vxi~)pS{9G>K=U{dT9cSQ?Q=_`!J_ z+wA;kn?v!<(eG9}KT8`1GH#GiZqueEx~=rDsC9p~G-$FYNm>IukFKog6A%l3g6Ewn z6j$O!wuU^cN3B4`Dsje#NU!FDikKATImetD1-5E1rXmZm_3>kjm77mrdhBez#t_}$ z)p(MR8;h#@GVaP`R<9n*X0xlRt3Rf>@v7c^4>-0-cyF}uXW~}sz0QbXF2llK@d^5i z&WKTFus|dxIbt+qAIC7}!W;W`MQTu`q@)aOJ}IW@AQ4l=Bpa(*Z8y%==GLy3)*m;Q z7nUs8JU@0=Gj)Sk<+0pQ*1<Mwo7+~kr_D^$;%Xp?`ReL5xm?7<F3g$;@yZqIiTm1) zuCVvIz`VTsuy96P;YlLW#g%LDe$)85!TWQlt(W)2g#H<q`)fqM{y8S<VO8+<ty@u* z7=s(L;Ee2mT){2AspjtRr=b1~Gv^haCRXDfJnCnNn_>6j@s&c6A*hFE@mUJ;PCN&p z&xaz1P!B)B=kP}&_d9ZI*s-b?JL`<sF|bpiAG76so(&T**N;W3)(eZ5?_3gF%bB{S z#DE|&P3=tY`e@Y#5kFAX7!U>bLEp)WVn`bL9551NS+J;jS8EhR8%#N_m>y(jn+q|N zxY7%&XvmdX8aliW=;G`Jc;dDrc#9vc(}YEwCc5$HF9z1s+Zm|sfiiLD*@eDDv_<)J z+#cW^sKN`uTZ3K?ml0>b_f?>UBY1^ghpYJtT>n?$v)2gf!lN#{PUM$xp|J98;SGY8 z?{}bYhQ<eTFCuJAe9nWufGSRVIC=;}(c2)j@D_3Y=t5!M#=<+qdFg$)-{0WO0qC?7 z_4_QQ;x}MhM8*Fg&b%Lp<|qCMp|4`-+i<)j6xr173Ff~bj$me~0?Zy(_#fgPtBY}j zzjwX(>(?WHjNI;J$7}S<(d55tfAy<ZU3LBK_vv5^%t!gkUx)E+ZcS8}<13D8Z@I?P za3g;#Q1;c${==pElyI?edh!9L4qOhvTr;|GVI{5*Mf$<aTW+B=m^lo_u)+NNxk}uq zKZ;6rex%Usw>R0}_{R0ue{Jg$+cCiGgYYo&@TSjdpvC!bMJg+2QxadFkTXa#^rL1* zTnX+S2tuYD$g)qydwQCa^Jcz(7(Kt~gIpHGq94kPoWu*&wgECtb#h0Ko-#B>H&n5; zhac!T<BFBiDdHt*TeFiNGlm$JvqnHY$LdKnsmEp8Y|J}*+h$n4E(L5mnFk{PY*2K! zGE>Z>{9i(8*H31ue$R2Db3IhM0Ai=F^sz6toupb02hbCVMq_TRq^mNcDh#vx`jTKs zmS`+sW;IE}UrK^4AZ<BAH#K0`4gJe>*{z)|>;%aHw=|EQ1T}ix_G)jrm0IUV#wusI zP_ZM2#V5#t4Ul)$hFkoo2}mUCK{R?!a`b~-oUco3X58q|J1x1&G<c2G6jrF}nJ=xF zRTXQSEe&-@)qTQXX6qHg2e}KxJ>nw_%UHb@W2TIZW@#O!X?JtHkj*++HFTD(Gk{gc z@fpL^GLq%iMY0S%Y8aKX?$=<2pJ8-D7plla&|J&=JWB?s^Wrwp-rmyE-R+o&&CPB5 zf`4kagM$YhV*Qz}o4V=DHST;kzmk9LIzzM)mhEb4h$|m*>_5xV(^f}zkod;<OD6Hf z4%@>%=Nr;UdkbXh9`pjxTl(X^X|UR%=JS)ofBrQ0A+9K%A!N;HtS1|-t*^3m+0iUm zO%!vi^QXY_nzkCm4K<!)WsS3{<V;+<9Msn8YRpQChZvT%x-3g|@!ZRCoRKs+MpX?> z7I>M}&5S9jvLIV#1GFgGn3!Y0r4>QmU2XI-ti^L8&L!bU+akQ5S&VuS_t4UI_ziHh z;o3;EqrI+=?7>{3pWFj2UXEEmW`QTK5)xWhAcH1^g|q1+Xx&Y%&)jsy6`wn3CS=R5 z(~P8?nx#pOfjmzVRY7Lj&Gvdrm7E1t6LMUwDXvphMu<r)6RWCb>*NfpmluEq_MAEP zm^dV~iX->+8;))%4QQe!IEor@aHBfEI@+)x%aRn&<#b8Z6tTM2l-+`fO?J$P31*F= z3!qO`6~$_9u4gUAh=}lJ>uX+x>ZDh_W<g{#s*VnMoku(FU;lsMNV}TZ%i0z*ZVf#- zayEDN^#3DVwFx6v2}(;$(Cdx7{QnJKiXzJ)e7)-7s|VgsK@}ADQ}Kn)pDU-;m5aKS z^J!8j(NRbu{JmT?VdQPd2!fW#wR5uSAcsj=AkLVks>L)(=gSa}8=Z}*%Im|}yd4;v zWwnWBTmVyxszB8|7m*9a*+Pdfhd|^qNBVH4#&M#fI&v)2P#3FGcrjWf^9t+sFG-T< z{wpRzsO339lUPNOIE`s^_Blu3Hs)B{uSNb6dC-lrbM|Uvn5+)v{qs$=YpZ-rpW1W0 zJbP}xwrE0LvHn4$Rk8F2y+<{rY@0r!n@SzdCg@l#MVKkI$lw@91Z68wM<W-#%mq1Y z-FlJj<gIB3mV_MAv9&6Bm@9{1Nn)%Y<zgpv@Mb(A)a2^t2>Em>$tL?)OZ?<cuFxm+ zE|ZqDOs5^h-=q#~lD3U0!>3DUALa$qkU8Fv1cfnU49Dn<RK+_}+HQ(z#Z=6`)_U2l ziH~+@Io&i^tyM9#O7?o!HqSth5~|1O$K?~JbkI!XVF(X7T=aPn#~k0ti@o1X0aY60 z<@}Bq6B`z}ZPM{--x_7Zh&FqxvTKnx_gwk>M<m4phBeaFEGHXMW6rOFu+%b*Zru>w zf<<XZ9Z(%Qu{7k7gq{_6d)v(uzAor}f;)u#3`c+v3P8XsG>n7G)S_d(u3b|VO=?Ce z!`4bhvRVKtu#%d<MJ+aN#*>XoKH<oH)fqXfN{+r1i<W*MyLWy+2P;!8k97_)a}HW| z+yp?^G%=%EDTi*YxS8N<K)i_^t~V4@)g5NU8G_=LGUY^&o-I3EMOm@R$}a<s*(Cck z=IF?fy0{|ed6-^6zTG0ceOnZ;#{ITyO%&mM(xQa(K0v$H{X3E`LOXUs!L^xDuGDW6 zbS>b1;C<4fLeyb*C8A37uHrp_#-~A_QNIJd6~?|9<lggm(Pf}+zBZ@FGIMq{(3U?U zx8<zrtdvOZ-Qz5Iqjx3&vq=<Tj6l&Ks?qyUGnnzqgId(KAefohgWADUup+#RR7?a< zAQ5!(Mp_ShKM_0|n}qf9+;8CXBd6_Nm~pF^j0EZ+7GbRA-pi;XOA*;-{kI*UwoPN` zn?BU@J17-Th1WJi!_N2@aW!k0PX^6+{0ichtUrcZs94Y9xxL`yZ0}cbMh<wMScI7? zin-u9s)zNO;MtfrhTq|ly-xJ|E_D`95_oXi!W_izv!iEGtRvb!f}!<P+Gz-$UZQm? zHqx+OYznT><lCV!z`JS1W&-Nd8R|EW+mbt=g*LK@2+nPS)&k}$F2b1o@gw*fule8D zcN(!G4s;)kSS?m#EWhcm|Gx97<7*@0fG`yo+lkyOPTPIE1N}aaazLSeC(6OoRqt&# z;vU}c=dusxy)AYGN3!orf&CQNr^QY@m$wP%EQ~2g8~b4G7mpsh-sjET!OT>}9tiCX z?r#qVeZhBl{lGJTVn0FMk5;~MKJz|r9(bSL2H)q|5RsG6-*dynsXAVX$q~%G-XZ3J z?lWmH8?dWEAzeNaEJo+ZS1k&!gcEw@sZBYfre26k$!eXeibo~8rNRENttJ$3jV)`o z`Cz;T)F(PFW*Anl<r))$sLae7l4f_Z{NgTo*p(e)&KQ5_Se>F5HSTG#=mqE7)wXV! zb`G$XWghBHCgMr!3*TqkYo!`kJJUT6a>wl29^J&4gB9P<$dO`9CiM6~#sGR+vin<s zWA&$UDw;&T!A|GI#_CR+wQc)WpxG*TFjFhnWIIpjJVE?Gug)@@-oQ5}T~*c6OprK} z9qEyKJ39Nt!S*26hxf4drtx|_2ce^o9&Yg><c>J&dbb0GIi`zq3Fy5JbRGf4xhMC| zhS2#Qy?U8Wi-?vMV(9CzUj&62q2Y~{$~j^~q!;>;|HD}#CIsR-IY|cSh;bR?9x+A% zo6x(s3%{?5mY^P|iKeJJ_*0lFJ1VCV@-mo4f1|~ymIluq?Zq9nj)t^l;{xdSS!B2Y zwav>!&frqAs4k7Cq*PpB8go*P+=CZD&th?uh<S47KNf<b{R;0h6qgWK@o}}3fIf_& z%R;gnu2*q+FkS{lc@<Z{({mYSGQ2O6_B83)xQ<OQ7a7cYK^Bx9Bwg_cp-tc48spAg zo*FiWYig<&Dx-;2+c;+Ja$C|&ov|!tM@j%<GOkIssID^Ygpt0_(p6BK0S)cl)kbwK zQ1$h@HHD3H(z2EouA?bh-y*ivaZ-C)M|gb2lg4nq<8cBDE)?ElDXzlveUZT9>Yzl} zy8}WOWBNqch4(_nEh6uh%Ln0|tm4|x`m7^*kSekYRkSFM1nJ(@>@eNqw&UHQbw_e{ zeW2fp<c2$Pyq%CHuH^n4Z47YT^TiGD*~Sp}hBGW~!ryqu$I;|9MD8?)|Bfe#QKOyh za^=mToegj86}N<DNbr$yn~*DRzkLLbq{_V@uWg=q+piqxT-bK2_qJy}d5LDR&FkTa zmyZmdpB1+gZ*y1rL;^=*rLEWR4g&fxh8{zsisG>}OnMbUWV}wO?M@=Uzl$@NTdjCp zFk-KGJe=|AgjS02a6k@L2=ID1fjY7igVJ>T?4#DrZF>^2Znz!^8pGaC;vQb~@jJdN zm}l2}+sQ<~Zrk0E+7RYW2~y%dr0c<V6!(PimkLn~tTcgU@79~}-b~K()DU%@7TRm5 z?de3nAxwF;3DzvVdG5y4Mc{h!Tf{u?a-e5~=>A1wWM>8`v3M3ii89t9VcW@XP$}l@ z5LR7$<|n@cpMAjl#*5xFct4<cPKd{#8BT|=yo<2D{5_0T>qEHhs{}UIhNRQEAuPk) zI({aE?h0W8zHNLPhQ3YA@VsCaao9G$zaM^MBXzYt9>U4q00mcOxG%)X39OE9Ay(Gy z;rtNIz3K0P;(lTcT^zytkHv8UdKg0|LUthPVUpT*ippaS&~RV8fVi>YN|P}H_d(j= ziqnKO<MWt8$PR@2saOor3T(Ug<{;L`uL)u2b)O#<OSB$}W$G+ug0zC#?mrl$K~w{S z*iR^~;mXkNB`9dTjC**?J@xhQaA9yYC+{YtYG`+0AA)C%9q2g<zrJj^h)TsD4z0z- zfmyuh_3#l0{a}!@yPgIIdVGjiY==A&*61mI4D$wZ-WLUH5qWasOQAjU@c`y3o&>Z` zmjq`xeldLKrJ)rdImRalPVQ3eWe|Ef?)_z`8KLpr5aN^we^&%~t?QE^sOt!dKPi6l zD4Bh@qK}MU9?X^MQSC#t-Mbh1w4grg#@)IRQ0TN`>^-t+H3m~>(R5qF=1TX0F>7F8 z!Mt={?#hi+cWbSg`E&c0j*TgnsHt*H)z}>=!`2gLL&f$KQ?@1jdv0<PtI0~KHpsUm zEi-F1H8rg`Mstsi#Rb(3j=2_-n&MhIo30US(>}i3{ro9{!y<gS82@xgvcL!mZymlI z)EOu53uuQ&P*eosN|X0csE{juhFHma@JfEx^SB22+Lgo&i^@89{JeNoFrTfrcRojx zzQwCU`a0}q@9pr}H3TR5HU7ruLwoxR1g22E1cy7gH4+@?7YT~>W&7`GI#=;p8od?$ zeFnXTFs6y*l5hAFTfC0o1CL@!eSIjR{&xf)2y@gg6FlxAyaHdLN`M;(nRgiX@KwsX zaQoDd)I{UGF*t_t9~`AQ`fvLhb@jeZm4x4*X+GnB42=Qtv7ZyP?6y4!d$<X={Rc7L z{|eDPTFpNMIpO4AsI~~=DR)ri!e2uC`<swI-W=lM1m-6H82ZL7L|b1|`&Iy2@#7-Q zeLHCP?Y*1Om2VC0dbHzi3(0}+RQ7j7g4y>Ry7!{sD-odcBTFKyi2DQN`M+1aoh&`; z9l!QhvPn|hCh0><1_xLDaplm^;)#Z##>Sxr(6GIsL5N$LWjEMLu9ju1;#Hud&Hgx0 z<Fa*?t?D+o&x+4+bLh>9J3no1w!!3rM5m;irV?w5F$|mFbDAi3C$dr|CGfQgIbF## zh_DWC4;8-`@u98;@O=Ur(*24*z)*B<@<WJUBtsU2?6dj+udV1##}hvE&~BJIL~xr& zF}Jy$=7E_=&}{kQk8ozGm)vu#`N&7`<De}v{*Qp3UFqQ`M{zuV40i<YetJ9Sry*?t z;$cFjL5n}5+MaiYu!H*jc}Pn_ZGRE+FCa|bMNsv_n5yp%$#dkjBIVPAxb3|m{371A zjAn&+rx9``(h*UG7oUmeHu;aEv=TSlaUY}=^v?UJ9+Y1OYoQh4ZKdKtiVcy!pa`Em z5Sr(M6)6xAoPOL2Mi1ef#J!QFusZVpN_VN$Jx-Fo??5hCas%6Wa0+N^>l#ki%d@ge zGF@`3HPn$GIR*aoTCyow4K^dEqw!cQ3St5~CnFXt%h2N=GYvzx?$DhdYpn%D+pMht z4$NAs>s{I`t=+UF%M?1eSXEV&vE?Mk3Tm^JR+9-y${8BKCu%-TJcKzWqMwIDJoin) ziaA8nDkieT`KZ6U4%6g*@sZFzdNgFkBA*kqO!wUdpZ$s^FN(jWN|ApPJ~3Y&H;3fr zW3YF4d!hK7knBVD^BbYcPiSBNmY}VB@s6mRJy!VS?;-RL)SdRn5FbJ-@Hk<^`M$L$ zFdurwpW(g~?%^GRL;i{CUHG$iw&#w_#p?Iqo<g$uuM}SZS9~()-9(z;#9_F~omB7J zWq6b%|9UE9f1(-vEu<GA{`E9<eV?If$IpiRVTgyW3qmIrA4OAGQ}IqK5l#+!IN^%V z5p#PK&*J%zhVcT#AJQmaq>lQfkS6`IuTkv1J(vr^<D6$uIsFkD{_v@+w|^&wVegMY z91KxCAFohl&M`DB?mM04Gbp}F?e{egi(VC`;_F0BG~Wx3X!Gwu?l2_=yjjl$=;n<O z#u2XH3`GJU`Scc{iMVU_c1RN;=z8CUgazTh?VXVS8_~@_h*%AGyvd_{oW2J6PnzXE z1!%M}F`LF|ivJ=wjmuO1O<+>T+!xjoDgF=q#=F5?REh+A8kM;q>N=jl=OYz-ma3?u zUO-#DQZ(panyQ5(fio(_f?n^5J)wQ~s^5EwA*c)Q#;H8buUcY*<12CR?K3R#LC!Zd z%lCy(b<xiAN&=x7J&K_s&Hq`FXw+1a33_}K<NC|N8}#1z6xt4)>ZH+mNu|+ENef9Y zGzOizT84)W?^Z?$)<rK_gw)2AR{}w6z2xR)%$MQ>{h{$ah{u<p@v5mInp`L)L-8L7 z%PCy(2Gyv6a<!DE`F%?n0vp)VRmz598W2ajkfw*1s)PKplsif;_;T!aEXV%t%ixJZ zXcmz3O!d;Vpi&LZn=o;Z3jHQ^O>2YD60B`rs;BuLC%!{iDgJ)iL8YsP(0Cv7rFyB6 zO7~3!Z*?rAQZvC@an=@(=JKIEg0!nc@L5YJ_6B}qY7Gr1`yQa^9$cw4IHOWqz@GQ` z<HVH&S8Ate4yBGr(3*vEztkDzDWzE<zYwYE_<HhN1a7-%_?y~E#7#QmE5UQ-Qcp0q zgtsSp@t%0Y*ELIhG+r>Znz~y3RL(d+Sl>R44HCDmeudi(c~zp^ejkN5#hW6nkxuNv zJw5UPvdT!X^bv|v_R{XeNr%Q!UR=+y;nh#z-JZf#qK5N>Zp?Gy^`&!vcn2%#9COe% z!Lc#M<{7C2bar+w=m4#o6iJelK3!H6rL4%Rq-?h&DK1r+QMJM1_GqbizcA9+GN5$T zTB@WfwR)^Cp{=ujVae^1u4<wvM8^i?fqBQV495#O+4;#T?#~b>DiX(umMp89q)V#G zo6%TIVGTi0b(v!Uuc(~K2!bf`ij`#8VP2B`GhKgY3=@`BMY`qppA4VPCiso7Biu}t zha;h=FvJ0FplN2MaAXT=dut@<*+#VB#tn(^PVB3Z2e9AD&Ca+fvORKK<sNsu-_Nx? zOtE(<OWV-$zH5s}!g~Ci*w$+BU67d<JGQF`e};8MQnj7BWQh6)Y)z{Xqh`!#NwfTU zW=+EYyR@@)Q0{Q=5GYEW8STwkyFiyF8;bFODJ^bJB$^jX^<u5_UxpPFk>d?ZG)-P- zV!XlvsY+CJg{!ins?3@(P7no7HPbO>l$YhD5|CA;!X*$_MO=bBTXJl<(mdY|D9xvx z=9d-_a?aJ7U_H&!!lPuX&qo$fp!pI!eJm{w+000W{F>O`cugn%O4IF1ONjBfvVJM- zeOX{UUIvVbhX_9k*6m8mL#KjJ6ECfR{j5C7^WyW}RWyz@@feoZkorsTB(k)I+V(e8 z3Hn=tpJO|&w3fOW>!@;TJx$(B917VQ5IPwlcA(ESH{cjjl5=mQ=-h~AxYDMeEmYd< z+lQqs6n>3baHXwO&2SrStq;5yj5eEiG$7N0IsnY5H32gi?DH-8mk2!ng}5`|M#Mfv zjCgy<0z+%CBRJO5F(J<`;g2jG>t#Hyc>M~Yvq)kMN;_%VXK5GF7R%HFZxfW{jI4AV zL7`%3=N(Us%%_eM2v1FA3|{PP=|q|aIq}bswSoFMDM+WKlOg^PrgjJSb?KCleoFXr zC*GpTlBol*pFN>n32V(3AERZmDxDULF!OqUjX3l2_wMO5o3eC9kRm+jnY5Fz(pf>S zHkE@keRjaZ=xN-g55Q+=P0k5gETs<xFhk>!=Mq}f;mVu59eEzjvr*bh^YNAT;a%{K z?+KcWhxj?!`}s7F_!QL_Qrb_Yk#U;$X;Pu=Sgte?Jjp6ehPX9BGv{Z5K9<r{=p=)D zTO&0BD~H<>y8SrJLQpzD+Xbac{7g_wo(}2RaG#foAsJH&a0)MCs8oh+KM*=oL71B% zcGp9g16@e-HB63#xFy2pMN}+*n7U3E(^h(NE=@j7Ry2SYJudhWNUJc$r1UY`8FlI7 zL3%7*5|GZ%cs2tZ-}&7{o;x=)!Mg;HcW;cp0=XWNs+STTPZ#=$iY*t3!m}^8E^H&L z^pwQ6<NaW6PkRgIyLu{mCU4ZH>|BFZCyFtf%V-^D=cqKlCC;slt&JsOEta90))#H1 zz9wBSwPx*P8#^bL%2)uTTAD;#%r!Pt&y{suSKM*bpsKYI*0DIeX#Av~Lg1*;RIY;$ zqWJS$Oifqy#oJlUEoqsQlAOp`Tw1D8b9u2X9cNY~6JoYe-Bo2*Jt8TFCRT&~#_A@q zs}{uT*xpnk2dqSO=iF)4G!sC(){4h1XH=eU5NU^_qK${g1H!gYf5Jo3%Ud|b(f~+^ zafWxsV~f>#Reh(}m(_*UwPy8kQD->OT*A`K__cPvE>SHur$H*mcc*ey)s~gWHuf*+ zouxK+?nq`b$zIveO&M2fa&gsH!4-U|yL!YD(pC_D+z1mY3_0&UF?wQ*IV*a)AZHR< zDw8r~25{AKgFb7HINGTS$1ppX*rM22^byUJO<k->OF*)89cXdGO=D)%)UrKEkg$M} zNF)`Y=oSz748HH=QX7m~DqT+8g7TqPz)TuCvYH%=vmHghhi+;naJI1gQFk)Yu^ci- z!FW}?YTeqXXzQk(5|TU{i*u?Z*T~sMF`rbK@tZZ#6!b52*==pH5xFPUb)%h3+F)+F zx>@M0u~M_7=6EKVvCMd;e%XA-_|w$$dV1`^2CKTQa*GjiiT&`lOzD$w4|)8+S&z9C z+C>%-k(Du&2dZ*e)=fwDb6K!>d2mV0d9|%13^B$>Ein#kkd#uE#T>h&N--oQrpRnG z)}3;UptGa#szb6Ss7j4BJD+P82Ak@2O=xdQs<xKwTHe0A+0CjoR~nfmXWMEv<Za8# zjp*=Jc*5ybSq$U+=wW+TWBfF`IN!)1Ht+X~R(wG$5naBF5i|vuwkE`cs3|5aD_tu! z#T8~z!eZh{Nw*BvviMYn$)$&enuURBTe0N$FD-^?s?E35*mX5_Mruyg%M#zzlF*&q z(AeF|ayHNPn+lU))i#bzuxyuI&)KZv?D+(!tPs+HVC+`u)A(N2KOyup5c*lK5);bB z$ih27oABC^Tc~2ql6%N?cF<cM-SBdt%Z7DA^kh-BEk!pID#OLBn64)4yB5fc@{+bW zwo2ekLChGctQluT&y<w7yOC0`C6`V%_AQWB)~eFZ*haUZbeQE;fmMJci@c(Xf+hks zX{Ai(nIak@;8l$^v{k&Iio9+~vLwiwB&d?bwI&Uxkz?ZumZ0dYsRmAgN>D$Xx;BDx zdOYu94Ccy1ULaJt>F8}q+m+-^X}#oLlxAdIu?!#p4&L+;vT`yf)!7zX{+TS;oOJEB zZFX1J+F0K_X7NFXNFDZ^Z4kR_KqAi$r{Y-)#Is%VMx6N?%JS8qc_lEUxD>b_Sh@<X z?dO8EcuH48D2kM`E81xZ#@UuW59t8qetguKb>+nWe<6R!R4ZiaX%2~jmi{<d8S`OH zQ53CvZj@C-OSM>?iB;LW$t8Hzl5JIqp4V=5bo6vcsv^f^Md*&|mU&T?eU71Mn!ZL6 z3|@Ye7oByCTZ=L^o&3BeJ<%eJB!O+}@l@01W%J@@(psuYQ8Owp9BPw$Mz+@0jtjM> z3X&EOfrWDFx#xAi#8u!IU=L4Y*t5g;zjvtwk}a4|oW&e->k{U;)=S|}>te=^#+Jlb zn~!x&D4;f@*olNLGY-+~HO+nV#F17@Ui(W^*|SG!SKHJUrAy&B=z}v=Nl;XY7ZM!M zEtxe~K`|<Mw9smPp|YCpopF>E3;V5B{4e}fA@LaAv91_}Q??#IgWXhP{Rq^~V^8QQ zz@IClCrVl-saST_<fC>>Q)*kf7D{v4G-*|AjEUJXb{50w5`VuTugS;b`89I0*x>xv zX>qbBs+ue)DK23ob<X4^NoOrqQWP=9vZ5f7HLE;I{vwR0RlF>k?#;0Ik!6upD4T)( zzN><BFW|Hcd6b30&kEA$m5O%J@}+oe&S;dEcvH~?j$=$ll^nXWMR(z@Zeay$gkf!t z>33G7gV|BdvjhAU4&M>fVSAZvFLQnl&1wLk4kU$qvbu?DvYSlBQ4m@hfMo$m;AGYL zrK!oV%^r{v687=usoLK5<ieDfy8zC6|28=9t8k6**S#EA!(Q#Hm6bdb?>X`KaNJ8D zFg)lbpYT?Hco0=*cQd}D+*r}r*uogEIf@NX8L7&0#HwLfNil7Rd?Nr>X9sJ?FOS7e z8iYUb<BzvSM!q0(HYXqItg{+wk~Km{CR4}dtUBPRLw0J;wx|`Y%drfIo?tb!p9_Y- z9L~IU#7wGIl1~EvPMf>R*TUIegDp#B1Hn7XrRzL<ywdi1qAiZ;EPc6xFVgb%c-vQq z+#^2phTs`=3C6>hZp8T<(7DssAoT0ON@}HV5N|U={f51THxaWCaNGYPW`WPPOW!1* z{)}%XpneaxP}_d10(CeWs^NVIW+Pkf@bmSN&5`YqosknFdm?9%`LhQ5sX8XHhX%>i zw4vC|a4mY?JNh8GesVULJ$s2&HR|jwN8RC5jKaiX7NZE7q3Vvhtj4Yxn|+7kDt$Li zXKHI(KigDYow1smhZ>J@KQhhD&8(J8tGR`?DO=!9&G}+ShdHOAv5gt(kgZ0c7Bm1u zNhBIKm}-q~2|$~_*ezSHO9m`I&@9Vxi>hX%oM1_cBU)rl6<w{>mHSUe9)?+)Bg05+ z4S5x}TimIPav8n)l$FZz;}0IZa!GH8);qL2s#r?2dfl7`t~KK6kxx3fb}LJx2v<}b zYZ$Q}7dKa~`BGJt0nEDSMpm$;b(dW7wXIB3XIyU>+HUDQ*xv0}0D>cdpN-t**6oQ{ zsHY@WjA8ld-2M00ISfYouKkHm+yzb+hT7#!Yj(|=k$i;YASIZeq;xB$eHa;7x(!0V zgEKv&wlJQx^gSXgv=9A$FhZsTqq0js#5)4k-Y&ri`O=SY+h>WkKgQ7K3FuF-HUA<3 zy(8qOLC~LK=yL@0XQ5qrCxrey=%?}8{vznxD8YC-_^b+NB5xw<tOt~tN~S)qPWA7k zeD~I^r=BXCrp_29$DV!m&YkT&{E3Gxk!!P?>_J_L#Tl0GaemJ;(YW)D)y|u5cWA7J z*mp;n5s+1H=&(CFY%2y5lBy|;s&Q?6Psg=AJz#+2Es<ZS%TW+j29>xn>W<z<Uh+tW z==rEzh>iBA?EZem1SVqvo*iATuA6(=muJlamuhagR+c||akJ67IuNZ=f_Iln_h5bo z??mp0kprc>gHf*gzezxGRAuR2812;@^cA71)}?!ccXmtge#lhl%*GqTFM~axey5%Z z#=;|L>3$-T9YZHS9qeK1)zBE=jK^VapwfNRxBV>`ujsw)0ldG^7+@Uj<R^nZGj!9Q zc-ynY+(I{qynY`J_TWJeQAhS<@T>@7vUHe+-_j$&xarBy21e$^rykf7!o#z~7#_tl zevz2*l|&6w7n88Esr&3`?2OmbW-)nH=&a;dw6!Rjq45%T!%O#tdVn*YygC&5g7ENb zJhHclk<F)K@-ag4x=@%cf9hSVDZJrBCqEaAv_w6O_fbZcpMW{gO24JP^LHWI{$yp| zj$}Z267G$3IC}76C?g1_6}H0sEUbfW)`UvFPq$!3OFt4(4!rH=#*S>Zp`o)=mTV9+ z;#^BhU0pWYoV)DDT0Cji=-mpaih*A&sH)DXDOrnl+zWsynMvorR!NM3SgaZTVQX50 zk<{kr%<cemK#RY#Skutd`D01bN>z6S&v))4G6;mArQe5m0D}GjuNaJHMk`iaAL8q% z-&w&uHT5PzHU5d?A49tmNvFp{w1nsbo(qn56Plz?HMO+ydRYzdDS}6hUk>(*GBkK^ z!x^Grzj-$wk@M_NgapU$JP-+<a(FoUbMPDjLHC{*lHjQAU#NWNub9@6OodcE-V!|h zLT$(M5ntoLBP%@_(zf9#X$fZQE<H{3j`vLI8Jg56Jxis6=V(xz_aNBz`5;g7R%=Bt zF4=qA3q%DZANnG7W%tqe*K|kdZ7_d!>E)0<^8}GQAVjs3H->DQ`vN!ggL6AVa5cB> zD*-yH;P)jW&wzkw8DafZf;YSO0AZ$r(n~>!=<TPqG|pOjEf^8#QN?EJo_?JwtN%`= z!8eE~I*f<$lW@O;JR3hDsE2qfbS7=Q<EKz(@n&d$L7a`BNn7IsX7D7_gDS-7tuN1R z3FbBPsBax@48_wzHX|C@TOrBt1d+YpU->8C{(2gI<89iC97qMTT6px@>W%MNl9zdT zCU7oaH$#5}<?QE5?*yYVyixvxM)%`;X!G2A9Zjn_AQ1N^{MrALkkE(me)<=NzT$Hi zbkDc+Z$dM{-x%K&;_rwSP7C#edjIcWY`n)^WTFnV8}kHX&r9zHV?9yZa)h=6%T*Mf z$d#iZX@c6uX!xAGHKebgwtiOCX9*~a_xo%9elK%0J!5>D-~x}}9(WA(<&mEc!W(Z{ zAmnFAChq+fb#5Y+BYz?!YY`@;NWh*Qcm19DGR(zUdJ6BYR|uNB7FY3j)2lnO?0<RR zo@({^%9CUB<$A#)(AztAC|$4Q>lbA^)yCB9`MpaPE!rX_a~n7A-Yx2e#+W9%d-vwe zUEIiz+`FY#$}$z(s;zPU0ahxNns3IUx@lUbD#rjLYL;ngQ7cf_;#oL*B|^D>Ukcs+ zLmZ*3QfW@3?ZC2*xd)NcgXs4)qF*DZO_a@$u0m3xg|%TqN1nV7^O!gMT~-D(n)C7n z=oM%gS`g(pZu>UzwnWg1L43r^D-x!z>+x<tmI<tYTKY{eY5?_6PU0~j=sS?+U~Zst znyT+V9F&*kOh^vD>FcWFmj@$xP`(e0`wHd|?z6ZDxK4W?BJ3#@*YtZB^8R<=H>zov z8o!dN&&`DFGKAF}jYE`cLLMa4wl;#YAEU|wY($Qjk$RYwpGd3Sf_;YMuKQ2B&2_O% zC?epM?LajEnAAmERFjX7WSXV!>}ak}ZK;`ewFHt|w(Q=m0AMgSkoWA_w#`bgJ&))> zv`m3Zo03}xT>@r{m62_`xhZaH8DO$8%QCH`Dl>o;ZRb}bT4iA$th<77xaRP_LAl<G zL-Fphpz1Q^2I?+s4DB}rtz<WShTJWCe;vgC_(5WIeftE_WHUvB%$M`<S?E?VdgtWJ zL>|*eF!kL=lPhkv3M>bGN@xwvaQrtRswQ?b&NA^F!8`KfKZS9W+i5r%{}YY+yvz$O zrr!2<Z@Dd)g9i1m_bHqckKCv2@EaXe9r)eQjzsh942>O8{481z`>2wA{4pvmbcO6N zH1FSI4noM~1G}hLy(y%fp||}uq*J0<bW?Y8Pl)gRfZ%(+pXM(F<%MU_OQV=_A0ETY zgnsh-Aiwfv@ulDxJWZrOcuIpZkd&UF%Buk?bdbi2$L|T|3`V+Pc?hom-Be5NMp`x% zLK+elOnI258+ut<luDGfhojj+O}RXB)c*11-hISMW9Z~z>bysTJ-E3>0;@;1okNAr z4aLVI=sfI;KSHeke4;j=FY*3H)$A5f_t!$A>h`ZNM_UxsWe=Pmn8kA_D%#sKuY_Ve zA#@^7-5vi3*(b1VX>%~Ew>Ppen$=fc9JD6OOZ@CV9({)9J^7E2=LYq&G;~(?n?S~Z zXGw0juY+dgO+<s)t37VGjOO(zFQ;kX<rM_f*X&n@@QEy(so*}HNQ8I=(XW?zBjn$i zfG70jRiWD%KO!(ERJ0Zk8&6Q}oOh^HyPC?0*3j}N5PXEdXL&8n^E45%F}yLn<<*IU z@wHw=#bR{c?%ENRnt&*-A{gZJzIsh#OW!Jq%i7f<m*9my`!>6e<5^hQ^%AkEbKAC4 zPn8TqjTr`a+G*RiHMVeDA5zWwdQIn4sWp{ulck;xUCkS@sHUrirAUm$3c8`{YL$7k zhq`zVO&>0=3;9tHe%6OL)&_!O`KRHC&%PG&Rv?OPz*aK6Z(H67x$h=Iix0`e@@ASu zov00IByiOGdPBDuP!C%Oo!961Tj8^9!Lc7G1ZX;7y-YqAl&fwQ59|vI@#~2m8dvnH z=Y_nq69$!6ZpYdSvUGO9Q6Cesci=jpdV9n<%4@zoQ9hQ6Ka-|UjK4wkXa9@pyZJXo z=gOCN!guZp%K7qf0k7e6WbftUiMjZk_XHaL$|n-*`>@mRN${QUeqecbaFpd!;4^qe zRX&yG|0|z{<-@B4?>jw+TMv3hC>|H#_Dn*DcE(;l3tC!F5n8Q+;<TM-XNPd`j=w9) zAE2Fpl|P6j0cmfaLzPJ%qV1iD^)%>|6pCp<{hk}-atE#qd3uR8^D<PR9v<|pA+CHL zb^q=S^6H7XA^uB9;qpGJhIu~iEU~;lbYAfUk&`2IVpkrg&7wR(JDKoueT4VR$+VqI z<QE~vFtH`*lbrYxq{K=1ITi3s1$LB|??QR^Z{*nbT||3_R~I5Aw{fnP=RAKUItBVV z&4)Xcq;Z{z4b&M8($-~yl(*P|oLEJ})YR8#zN3A|(<o-&+0-$t3)bX-=U(2k{dWZO z%6i`zAY_fZJCA`YfN1pqvC0^K2d<#abKeK3x(u`!$`=q^`fz0@9QX=tj}}8da5rO5 zKz{t)?|sUGy-(9@wy7*JuS21E6+#*zTGhog{xY#ESPRF~+};TJ^NK#6%O#o>zYpGh zE0?Ld=nR#!T}ahAE}}v|9Kz2_aJDdqZTTa?omT#+pQkFY$J}Qh3-Pm;{d1AMFgJhs z<Dv65L`A1lwaQBfT>wk1eb<D}#SqpmC8VJ%2|f{$1cc9`d>K_szdTqI$J<kLsJ^5t zXlDQ=ovQDCGPrLh${`zuu!SZrrtJ+cYe`6_oH#%`&n$n6z=N-!e3~|kiHm}{>bxF4 z6U=4ewY`w0S4@;bT05fo4^nm;SN<&KkT3htiSdxH6rQ(F!8@nrD??`=h$^n4>AdC7 z(RT5~{-E!^d^NGpt_hu7AU=LKl@dQ6%mC}j__koyQ4cy0teISf(c$GU67s><kFSNF zFuJyU9gQj{E}%iZ>^31j;N`Ii`*^M=u;}Z~Q$dXy<svM9nMP?|78+ce%Io3WU~U?u z?|HdtLc4R~!vq&}`NUU3d;)1LlcAk~^x7Ljo)x6&ky`0jy-`0)dh;e`sPg~Qw6oyy zja2H{N8Qg~3uy(AV#{BL&%S}ZH?I)iI7sWq%lITzaN@1jO_ZIQFT)t+$t9ut$LJZ1 z_bcB_)i-aU>@KeSt&rylN#O6%XdGws35<Q;9-6c+!#LN8D`~r;d~1+Dd({0EDkr{; zMzQ7Z&?HCsyVO0noF)+uJdF1sNf9>_yd1x+GzYgmLh!Kf(Y*YnUh3Y4IcUp2pwiF} zsZ@A-upSD!8(;oW$cjWG`7vQVV|<o>LO^})e+NZ>%9r7}K>24O{S9e2cVg&U_#}oa z|2!m*pYk&{m489oL0)#Eu+@DRq5WVFf|ofav|p!IQ+69yzMCq4YlGaYd=G4UFU{60 z4F)q+P3<^JD*HS*lozXfU!ZNk^I85SKBt28c;GO^HIf1MQ@O(fv{T247ib#m0eF+V z{9q`q8ujx~q;e|>=G832jH%^Ap-2qa&pvpvz3;h@eYlyBj)#N!S3GO}5h_o8DRkn1 z*67h7jhBBF(8Ql3_X^5jQT}yshff>|;F(5sk5P1$N^idj<^V<WI`C{zBk*SXTVh_= z^RVyNG)<`dJDQz4@f^+0E&raT<xQPIUGZNB_xZ#FzMrG~2P$3umTFu7=6x{yN9qap z;~`HR8v7GezVoM0ED+M-9;K`iSN=2AGje7q5&^aS3++5@-{Fu2iQ4{^syja)lu6JJ zUirq8p?E$t@26;ctPJBL%TH6~=`&PrPUe60Y3ezuMT>a)^Hdr6!uwG3i=p!d^o^GY zsBe?MLZJYz{4#Zoj!>ewxbiE+8u=9QDiw>b1v4Ug8p69YOJ-`C=AoE)J>uV|e8}UO zT={jHCV74p4G$A<1y{?HSATyW9{L7V+x{ojyY?o{<6SzAI7{)h?YF3O^R`#bI5@s{ zg0b`7TwbH?(b6eY@7h1!XRrS=m@~$UNQehl-~yE@_mC|67tLzCfTzW=TwoG<#3Oiy z|E8P@aOMBT844U85}6k{5yplM1#bMHSg}SNE!I!Q&&U5S<5>8XKFO|$Yw=90^E2B> z&oa8ZXLUC>H#N16+Ow?&zALf8oFzBvL)VK|V)5dWPnHc$iD^2&d-tkU?QHMfjf|iP zF~xBH%Vrx#HAC%l|Im%?hQXU+ZB{o$L)BwZMVAd#k)l>ikPKOuq6WF^%Krm-%)24) z2@%^jbt!G1&O~Umd_MGG%~Vluz8HiA$J8|w4QBQ6s6q+(G?9M{=EInY(d57kL!-wT zHkif7>%B2(yLoLn%wt~j-#G*C{mckNT|eB<j7Y_dMA5#v8JQTLKa%R;3G|E-ScgCl zUX~$W^CbB9jEZkTySLS>NLyq<WK-ny$ffAs8Va_8H#Xhd9hHnAm2$A&MX<^pu^_Zk z{hdfs$m4^~|Eu7w#+JS-G+q>VNffi9Bsu?6WpRIv6_4wZ#0!?BE4GxpyxPpBfu_ic zDXJ=v62m~?o$rZ)^9@xKWtkT@ZQ?mI8r?sdX%M@r2dhWK4tw6G1>G1M+r8T%bBR$E z?&OmfE|e6u@i5Qx46E|2rZFtXNG!)$sg%J;qAu~Z&8DX6mYGZ%nr7%qQ<I@Of3ph5 z3(og=MRfkv7=dNG9Y`!{8iJ)&XLUo-I4u?x4cU-2$&J_)oL~7W{pgs4(j<)s&uBF1 zHKP-<+ocG@*MVou&@+p81_<w)-<wVG-EuQ=n!Y}h2-#|gZj*SFFz?%Bd*~zwwmrWo z043wkxtSDom!v~hE`nxgCqy$@8rPnwruiFZax_h5rY4x{%G-S-gck@~+B3C8+>ZaY zI+{0Prk*B|W*S0w%@MSb%D0+=mH)i9%>>RI+v$QDD5t(a?IBO`!f-P!G@s}B?ZoM# zkDb<#wSoF=BcuWDq3~|V!;0FrQ)#(_I<ihEZB0azkzAyKyl);#hl=8`-RtMpZhOz3 zb#_}*zcAX-y?~vQZ%P^KcaLQ1Tfoir^`OP<sW!xfm`)287ti#9meE-t-QwB4P;;4q zd5dSdf@?MdvkuSnz)>X~TlfWsgQn4K-1iz2%#ZOwd)Kaw>E?!hVRmc#kUZE_lQ70| z@mwP~+z6WVzASKtlg%h`+0J$W(2__uId7<QM)L<}-f1{*#6^!z0Xvi&9&%W!^WX%) z31?L^wKbh$cU}E}I#`oPh?1i@%u;x<YH^GMhnS=dmN%qz+o;W2z)YsvG)2$$kDFR^ zQjlRzrc4C~7r=V<`(Gw}!Y&SaArAV2Ck`|4?!*O%I;;wG>IDLdW7GH7!X5@f{SHFt zP*8)M8HRdgUFdDI38-0-<1;WmZf4Z0K~(7%*7Ba28+se8*E=&W$XRA!#=V&ZUN(ea z+l4_3--9k9_QS&t6h^|&EDpVG34t@r31^l<=zQ#TfpeRHF~c*<f_c7YV7AzqIYBFH zW(9!<5o2d%2xlZ7Rt4L7Z(AM0?;4^9e->+rSx6Phvj6W8x-OXA)9ZJAP{;S68wmWm zSl>v@&0jYd^D~2dT>wKj6Hp~Ii!B75`OvMw+g50er*8MK?s>pwV5XFr?Ox=*7sWBN zgTRAU;g2)N5WGPR&F$F#!`XWP#!;M$<5%{!_uVTxl{=NYQ?(__YF2UYy%#VT+t>yI z2}rhN$xXUDkpd||3JD>kk&uM+guD=v(2Ii$Chd`skPuT1m`?H%e!DY!v$N}g_x}F{ z%ktdZ?94ace0{#pn*(>^JZx=JiE=xA&nNECR^JG)6?(#BXbu;G*3H;_-4$;`7zO)Y zg!Pqu=WV+)volWL9iVk58W-*m?0YeGy6wKZT#apFH)g>*iDtdWtBX%ug6*E{Tj8bX zG~-ad4CJnXQ8K424p0m7)+}`LO2t7^Y!F3f)*`xSN7Pw=g9JU`Q!?QMQmmWF$R?t( zEi$`}V>^w7!7jQwZB)@|WsV_6TBY3_bDo&^(SH8g3du}0N4logFW}m0<C?Ar)rlJ8 zTJS74W%k0dQyeX^kxVSe%N)%|6pD^kQL3oZ3^R2tt0){5)Pg)mX~Bpkp+*$W?B&vY znwv$_w21o$9T<E7qde|zTu!8)S73fLcZ3fT`+mrG4zKj=j-z`W0{22DuEH`i+b09m zEuI+io`H$IKo8mnJ{xv4Wm|qYR^pN<fs&6;w%c4%-OcfuB3zVXYsI==vAd;lK<;a3 z&@#PRCL?`akwrajWV@O2Xw0Zf#f@lXeSc?ly2~RmAAp>D#G7?`0{G`9M!k8ECqTB} ziTz#~Y~lcDJxCnkkni>l9O1CH;=sfa00-bLpP0ZTXf(PLbHf6UvJHE1pJ<|h=mdOc z5wuRCJw0RFn4G>>qb#IAf0zK7P$xbDZm%U^+#|S869>|XbyUEq=yGn;fS<RRJ)vH+ z82<3)nxs^jX6mZsRPFJr8G~82L@|_MC91{LM(a;P^+Z)qeAL7HN)Q71RVS{&v;ddO zeH6PB^{~}?Er1Zz(m#Rd0UQU^@SX6*DZti!8@#&v#HX-#N@xUd&+X6-Z|-tu-0MNM z78%I*j|NOETZ<iw>m<qPd_r1q{<r(g^BOEsY5Svw6mBqzMS6C(T-jE+AqYpX^Lif( zq_Gi7>M%faY_vZJ3$}h|QMO7dt1>HVxQgVeT1As~9Mi;5qcKf2G*z0jR1!3fZ)|99 zk>hpok)RztEIZj`?VC|4kew9IhU8PVZFN14t;I<}v|6ofkTO^1GD0RN=!!PAm7m#I zvw-ie)n!GCnq@-!+}j4sO_55aYVmQgT+`)*5Yx*<nUi>h(FI+XbY9{GLFD;1O$tSg zdGl)1a=NZD=+$U`j`AIbEKUGCm4QrPhK+xnNPP9CtpSAE&Ln12V|?zk13A4mLhBJ~ zT8}7InCY}Cg%!<gqbd`v7DX+8l&@*oTxr$^MMagwuJ33%r7A{MES=V?LSdZ>_e^JF zVXDT6Rd#AT-D2(G!1So3cP;3pOLcvK+_rBDz>OOMZtEi!#(=ygqyNTkGuwFd8LV%# zlyQIJvskN$T0e)iN~M^G36M2&;zqAWcH;A%zV--5QQt3Mt;bO7P1sFnn=*j-`H7oR z#>Us}5um?m;!7A0_zh~k1)K&I+Ry<m1Nv+-?IxB~6(;zA3E;*gX4^-CSE>og2pf{f zg)WTD5~@{s&Tg7NVaAM@enDNx48`XyuhF%d)B?j$@%kAPUj`>1WLlf}s<+~>^BIVm znE1MnR^JLf1DVt&zUj>a;2HBaKmqL?csB4@fDM!fdP}S7XtxQUFZ3Rk&H(p#vGjge zO4)ImI{)}qwuWcs^GuXsTg}_dsZx#Hrq)%2doK*rCKEY79}JCz^_Ui=;wmo$AL9kX zkTbF@$&A3&Xj+XnQX5m1+LX>RG$-m3Keaq$gp@d{aAmLKTVNfxf^~e`n<>ayKe*#J z@f~ko0ncZ*d+%2}qkR{<LvsSPe$OWxLpXx$Zxi1l!Wh2e2fpw95c}*_@2y(TzWwNZ z*7Rd<{)3615XXcZ8q{3`GomN%@MZ(>jQKOHf|&c+e}T__?#+tsK;%xsX!O{d-Wo7Y z-(L_ReHXSy`=tI7wEoH`O~BS)W4e^v_il$n*|WYE<P(E9Y1>LYMT|Sp4Rq^A)qUp& zsms?fYC1v(qanSeT;;S?@?v%U7AmyvUL#dzTwqrvPS8~<C+u9_sy5Fy%2L*w6tGwK z1aklTn{u|uZT($&@9Ge}YXz%RQFPD@X^qy)j8*DVeIad{S|1a-;2xu{(pVR!B9SCr zZM|^IyeV2^mo`1pQdtKy8JjELXRY}ju;zP#RXPUi9|pL9WJxY9mZZNHSw5^qmU2(J zv#e!kG%*^?i~-ru+)Tq+JL6ra^$im?!RoO+CPg=GDx-xq>sdS05TsgCn!qJ>sZnXB zb%SNnkzh}`RFR`CCLS`va;lCuQdgM~HWJiB5h|*&Cn$+O|9okBY({jxkxd%G+IYRD zG<WNrR3cH9yI7TZjSf>LUBR%*>?AAB<+xNN%Q2i}Q>bPO>ZbztS=x=AJ=V^K?nxnf z$~<hEb^)LJo-m9jHZS<fVvt$)4Qr?Dyndx`Ik$#jhS_Ls>sP*Fj#^LG>C^Y!v~k+L zww;D8N7TIga^T6puk5T(AX6>;p6`t{ruhr=JkvbSdVY1{#EG)96RQV4HOu~f4%~q_ zZpo6cny>wRC+{4FCb?`!+&5;<TscQtv_T!{mN^R&iN#BJ`TOR$X^vaZ@d{4X6bncp zDqPN{WQvlr2NmVul=4MMn8)0f(H?Yi>$(-cYu${I_B-mow_?v8bJwor=GE5o;1!j| ztXW3otnx+W4%Y@*E%t#Z!HN64UeXDWJ#FFv#NlBpxM4W)5T@NcXth2JS|7pmR2zSf zg4W-l)>p8;k7Bt69|&bfe*s#LIW`SD2bFc|M_&M~#~tn39^u!eEOHYtilEZc&!4hK zm;jM66DOS!oXQ5nqGyEX@vLml2->@^S#<m!OG*Q`JtvN0dW<{nVKj#~fII<YgwZ#g z))yV=AGGfOJn9SQpkr^-LB#~rcLK&(BtTY57doe~><M=3<G{xa>M>0G)@w<e0G`^3 z-=o&oz^p;*Agqtm`0fkVJKfR$fYolWTR|1!iT_6Pd%>NblebAnlGqd2T3|No(){R& zKVcYjueEM)%W(omYE@aSPhoTTGur7h0QOH{`xFOpO|~xdBxr>ZCl#f8$A>^h{E5G! znY|7;1l*DTAUI%|>(EZW=-hy4FYPpthfW8c3p`@U;|&&FEzx<CaZ@}x6dwOsI$<rh z4Kdtj8QPT1NV!PUDSf57RI9F@DRre96+>-^Re=Nj$X1?TW~#wxFgm?2qorG0l4?9H z3aVMwW%igb5Bl@KmT%y+#G6|M<x}y|l6bp0$L#3n|66bS!Z~vW%`wv)v!0(Mt;eV~ zjOyy@c|(FQ)Lb?<;lS*yjm5(t%fZC&kR|aYY=@q5u*9}fxLEQxz>S>BA%UbN7dKkk zS0~VA05>x2T*>W>o88v_3pgKa=H#e>{sr{u!El$xrxw@IRjaZUIi@Zlb1biBSV2+P zruAk`nHW!)GtB*_x!-z@Qyi;>>IBV<#|51=EG3LrQoJgtiEK1xs-`wQw~gbr)#>f3 zdlv6Or|$1gCYzV76+axP27B*PQD6RDu#Px`(bb0UE#0(f)vAmBv}?tRIlQDNMT72M z35e{&=O^^Io-hpSFIAKiRg9A8G`r2x*?QAGvrdLE4aus2UJfroc>SDv4xM~T2C~Y6 zc&6c%fs!t4ozB3N!1O>js0@Jwd8Q-}l=Saf<dO!W5%^(ub<<ZT*Mx&cFm%b~^kr93 z^fl9rYE_lY-KL~S716etOk~C!D!gJA!(PVF7wop4UvhkyWi?&pI4x=zqO?_#wg{YN zSdsv5HO}W*mhXx6$K1LWHa>yOR}NO4Mr(e{h0pML811pM2YkSDmY;{Qj}Fw%M}40M zyypa#SqkPfwBPv*_RePk?4T6?h$A=DpDQ;&>jl7Q$DRO;3mvs>H{WcGSWo+tJ2!4D zZ?0j=2WIPPTy0{_P(&}^^~iahMwdBVPwJ_NnTS>xYRwc%mg3xe2#1%gRoQcT4$S6Z z=d`^7Yco4%(51d-F}Pex<Nz?1tjxlYe_-eJMMTvhC;6Q(-yDcAn*g_9CtkuR>IrmK zUPkuov-Z8?ebCSF3bJ26kKUG@I14^|2CMLOzxCOx;4|nADOJ0F1M+=`yS{;DiLJ=V z)TJVfc@u*a!U{M`CpQtyplJ666}l%LC*sw()B39Qw)@cu`z*%c(YX5`K^fw$-LkO6 z1hk?p&=KfyvPWC!;MkZLfFC)31Jiyk!Hb_db)71SRu@i*N-CXch(x!lk`zy{ZbS9y z(+?SW)684XgO+GrAqFD?$3+vo$b=Ln9jTN;G|$@&0uxr$tS;>ogq?MIhYnWqiX(@? z_2m&XAtpdc?rmfdIb&O|hrfo&KpNl(?w-HnNL<eb{*GbTKQSuyAUcm<bfEcyqa#De ze+%`681^shZBQ1lxjv{%KJjmCpC3Wk_#bRXPoma$omMCA+j-k5gjFEwV(cP}+rcyS zKxu@00C}>W19Jcwh4VqM`-+9hXF=tvT%ZY62`Ks7f!yuq8KplUUpvU%?xiZ(WyZ?N z%9UHUUi#!k>({SXv17-w3wwKeKlANx8%67x^3+rJ^L&|7#w&Jyb@-pv!1L>8<%C+H zPAx$UL<%_E;0esCi}oiULi7@NEruV$U@jxd0<a+;#`f}lw3mM+L3jTN-+B2RmhlHl z+K-m9;y5&$1M(umr#yw7dNe{lf;b((oII$=KJhe~*{d$E%rhho3bJdsRUPd764lnu z!F>bvt`c{2cPyKWqcSqNQcV`miCrzR%`6jTn3)UL{A1O;4u+jpUcN>XL|Hs6FgnA3 z-5fQ6hIw38Kt>6zUDw++j@!^4;i94_tBS_z@<RKFW{gh5wVb;6#(I6ac@DJlh~8t_ z6Ocaf3@%d)zl}xy9z**okl>UT9XqWpZ6ltOm$3L4cV;ru_+G_uOF=mBqRU<OzkzhS zXY9BeXAUYl<(LGM*U$*qD#rGbsK?=l(Fm`h5wdxpUF8i-|2c+m$;8gOg<*LRznYH` z*AjPN^b(F?&YgA?NpbFt^n3!%3RrENJuAcX+oM)1$Xk~$C(+7$1;)=GD$V`iB+`Yz zeDXk>%2#4ge6$2bCsP2_u^%dpd+=s7F5rIoDvbVVh<3nrt_At#AU+-ib(p4G9IhXi ziZM@xb2ec8g=t-$QWa50NnwDb{GIdX%&E_&MI)A5qG)T(VKc)fqOow@C7b5V={E}2 zqYqyy4G$lkFRPLkl_f!A=yg2b%WE`EOPZw04Pr(dm#Cafz~K}|g%GBUx+msU+oJE_ z&+8cUPokACaawKaX5ss2+`|FwT|I{0mc}YRS^GEI=HXus=8QID6bs7cHU?CK5t3+x zH?VPQoSIRNbf2#U`<KUTwAR}=V8zeZVSEv-IG+LawQcOR_fNItl!Qg`N)Z7ooqg;o zRnWGp*7!|^UOQ&oXBV{Tp(XWJh9EPGU9fCwB%&CiLQz#YPM={tTlUlkL#-WRN{kDs zh^VshaBxbuMH(YPHAIEuDwq7m^+%3;?=OEjIyWsuC{EQmI>IsRI=)t@*EB&*o01lj zlawiF(@iEUM3e|c3+0Ozl?#F<2w5GSG?zMN11>MLeQoXMK>q|fJ*9kpj+}WIL}BIY zF|Uw)#&7aq!1K^9Jp^tT<Qvdl1F6KBLn9{FAj}$Fk8Dw|VHB?kXwcBN^@yYC+fv0k zuLkPRqv|<cP6ZfikFdDna|-5x&F*TvJ=@ya*BY(n8<Q(y4N|qy+~3-o)jw=K+bx;H zGzE^<SSA@0Q`M!Y-*i2jj5F51Sm}|))*;k&-cVCjx+?3s_0MK8CpJn_m6R!?c!3vK zK~fA^m-&zp<`hlVInEAD7HDVvAmVfcRQ1Vo1S(GFn=#$P#p+U~z!#uru4gxBor3N7 zL!}W$eutflhtUXA5fy#irJ`ehLnA=j5u8IS#(hsZdz&2s84mJoXouf$sn6K!2pe8@ zF>=JVF7VD-JmpyI8!U}seqeE6d0=&5{rg(({Z{*^Q-0J!imvxRlf7m*JmsPkrS)6S z=1ag~lu}~CI*fuwMH1oQ)Qt-w&GnqVbiR8kHMVprPf;}0)5BD<m7M1^S{td&*F=S; zxCTbjhzHZNrw$zM!#ry){hH>S%+nsu*zQ2G6m11}WIDDZ$I!UPvDOpl40d36^)MQt z)7k%*Ej`u3pgf40%y*+GE=;G*_n>j#K;t@5T=^L!$!z3b=$)?s9p!24u7{7G=X+7# zv+f8-1~Gnsxbf&DwiZNX#{Y%!{)f=I`!H*>i}(GQ%=j2;9l&I37jiSv+RkF*&LYa9 zvoUE0#jJzRSSPpWQOA?ACa@u}C2&DtyQ3#VFSF0K0`C2ItZp&SO$i72y=1UN3gZ|l ztpD*^YUfjz&`b4CT2I9mqto2l+27yMG4CQVs&NV@M9aAq>1ecrs;y#^QK6&Zyty46 z{r%I`o}Nql`of)^oku%aNn+Dn1v@RpvZ)j++5hn@%koTw4r@|1OB=Gp(`<|mD-i*F z%vu^b*T%9@7WsB9cprrDo`Z3K-yj&yby`n5QYmb;BVi?nejP=AtZ1MtP#KuxRO8zf z_<(DnD%F^)jpBMr7ZlZOxB?J6!6Y^W+dE3NgX37KIuI&I2m*vQ+gs<&(`stA&Y7cC zS69^=hMjf$;fY*0l<B4=mI+59x)~2s;Yd_98lvDCP^daCEQ$)J2!g_?TqF_<NirXa zFd^k=i=rsjpRbhNxv1+%SDTuN(267}10gvSEHfezEx44QUe7nQE?grwD$SI5DIHg; zD=q%R8wRfkrl>?Be66I3Mj{Xj)V%vf;K{%pwwCVq6h>>GG;c7?8*UgMzvCW5zx$?- z%rLBew*A7cB&MKhj?mWb7IFk8_foaBQsuR{^XG5o7tLNXXYR}8dUIy(i}qjk|6jjL zQSNHAo)x|J^I=;cnqkY-FjDDcpeB$FG+KOqx~IPLxn%|IQ_^njNv^g%ZoeAF0Je8L zu`<F{lu2ckT7?)kBC3>4_6-QjT6k)nxhxnBF7FNXtO(7yZdNeVzd9Hi_}Nv4CTf<1 zW;91K@wCYpf)b6%N6N}tD=RCPNvbARLYW^}_%TTY$sy-PQMozY@rrcO-)&#LCM>ip zp_jK;%wXFSrlsuae0b%mZFPNptNO3Ce>`YJw<XnRI2tOCu?B4k`_^ts=C){mEEemt z{#a5Gv<};Ka$zl4Xk~M<T<6}S5+y2(-Q|Iq^~-nddUxW1<smb;Wp$WMmy6}qMp~pa zN|hSRBQ0~qB`qwq(d-S*SRR~r-K<cse^qGK2~lE2v7**ccPhG|$hwe7M=FeLP@xS@ zG>l$rt^>Rfjh5=XJ`E^0)N<#edV$Zop0WG_$7=#~E(gy4KdeZ8n?&78b9FMgdef%M zp1yef`c<ngzIf%1fq?<jyw>{PdhWB9p_Ge?s3;=%Pm-hxQQW$g<JMNmO)?(4<w(d2 zk(~1~CO0p_;=J5dEk<$auOLf7HopXX2IJ;a);Io&*_W09J^@=F11GQyL@q<Cn#VR% zs;CL;A9vXh0M?mv>@o`9C~;Aq@3?!KC5FzQpAuM&5thu&TAQVc9mdtVZaZd9$cm!U zvaoTZz-{T^B$c&P%Z?6?j>??cd$FQiTnp`{3X)9WoR?#3cV&eYUWhnwS_vdS7=w8V z)H{UMrwq2=aR$E{XxF`^QHIn1WvvHebbF^zQGRiGieE|3H8pwZ9d{VBW~F#qrny<O zYE*`m*(v$~!#H3)r)WAZ8mz#xGH)bBmgBN>)ao$HTfYg_)f6qVEH`Z($E~Z98|4x< zzv*hA`BhjRa0?p_f;yu4)sFY<S!<0C15MM8U_PfdvBPJ8fNP$z_(439P}l=p(uiv2 z$VhPi$iw%^a@Y*ZEzNa8dV0;ana!6qn<9vBur1Fg9GdBklJvX>d9z9&GL|v4K}AL; zSYce2m1v|~;yz?*hSHpzGxtN*^J7`2MA1-`Bcc>CLwvO3psvVuO^Xw=<0z`j!sa}< zWszU&Xlu5g<6*F$6~OvGgS29dvF6?j9N^REMTu7^g=gC$x)C>9t*2QOc_pIq%v8!S zB;K52JrCb4%hnv_Y148-=j?60x$X63yGw0t^+LKW3me@yZ+qtJKs@kU*v$%iN7t7; zhIn-*XO$bUntsPht)p&?7}lEKh(&x^GR?j%Koe?o>_^YqUO8~4ZET;7G#$W6Yu&Ic zDEc|J*7o;+Bt)HyO_ob_#C1I$X%*@tS;K5!$hQlO#_%TuK~O1;XFBOhIc-dz9_*NY zA`;j1h3y;Ewkkc5nLllz9*fBut19=2Qcw>{9c^`LcHO$Z#$8Q{fMWIB^=<Or*MY5L z8y)Z3voJe(9^4+tZ^0tvPL^Qd_#G5W=Kz_G^5CXR{(NM01S4DpZi|C)m{QbDV2a~Q zpB0z~YD|0N-gC>W_>O|-(grXdl>XIY>E;=2T2nS_>@*r0rgS9Iysip@Y*JB)xzsRs zf@crMEMeG7t!FXEDypi_(0S{z{xVpD;TBpaMh{7J=5DT<t>zjTmSw7>M#;0T{8lW2 z7u`6@UjSB%-#9v2g6+XCJD#bRp%w+;mCb{DJo#<jcux3@L+jD#XI<RRUxaRL;JV3n zrv@pgqzbFYl5S`l+sz&4XZyvTj9Jqy&#c~ZV|%-~#De4EtFNBls85+^kK#mhTlkIN zw)Bl;Z&%%FbM4x#t1{g}Z=G4!BlV?MU9kE#3;Y?QD-lce?Ag<u*3<1qrZnms|Cdp< zo#w?CpSQBEPw35>wKJp{HOsc_{AMnvXN_rzSY_w#-JR8Xs@=$zMzv+BD*uYzKrtu0 zH@eN-wz|%mYNn^h?C!P(PISntzuMAbEUJ#?mTolK+KlxJ8g+G`%8_lLMH<|Q+CK^W z=uW-^aIYc>{pik0YTeq#CIhc!MoZC$c8r|5-Q2y~+<s$Jmo@VuQ<PIeGWKIhs!~jg zMc>rkZrpOqd_h$-Vd3mVg<?p}t$K))c5SC9=LYPVz%grI%in8f;oJ2c=FUyE9YR-) zS<@kPr#Idh(`7Y!eQ&R^FdfY-xO#F<R;!=A#FCXX0pAs;YVG@OjQv}mNil8Ku3xe> zGeek>wRT<Zue<P)US3ekj#9eX*l08vt+7~n`_?T}EA+}1qe+vL3JaoiDMwEpWJuii zA0$J*;KCVHfDHlt@TI^*7ALYJR?uw#+c0F!%z`RIgu%_TLPk<4(|5DkCQ&F}U|zVq zx|Q#!Giy4f_Npa6Nu^X-u80|(qAm*4D=UpA(=405eq(!uR@UI&#j~vgATM+t=7pv~ z%`<C`dqK7A{7y7;aPxd0xF?(6jas240aU`vUxG$>!(IDe7WMrLXoVKPOHnJN0+(Uq z(xuzvaD@B^P%Bmq7kn0UvZWojq%p+3A?@@)%h3ZJnrrR(ld>FPDV3YqG{9Lqo9hy0 z*AJL$cJ4H{Z~u6=AOtloUDg*j5>vNq?I_dJebN3^aU*X1@Ax-CcD(%MU?x`}D)p8N zjo}Eo#Q^P#z)PF|ptF`|a2O3!Xoas}>;8~;-LTcEs_W~!|Kr3FuEc7cyRg3sqpI%i z4U%>btEvlkdI-!{@YcM`gL)JPvfg;pJh&S-%%M5Fip^oz*9u`KqB*>Xt@s7h7lZHN zIV2o(Y8j)f3ZtMRXnw>8$^Aau#%d1d_mJR_A4RR$xz3NF*0->|_=Hn)_F0Dq*xJJX z!UszFx4zS2+^gqhdMwgy@dJ5A&79RcbN&6R`+pXX>xtz#J(g%$xvDv72|~*gYjU|9 z0YhFv(V)O9mOp@Dp78Eje0TB(G40lB-G74z2G8Q-<`02&@rbw8!Wg^vT^HtmFWYKv z-FnH!nl7-mUU^3Krc1VdTh}zzJfH~%uicSI7_*G2u~=o#j*B|dHbI?53rWS|B4$j8 znWTL=jCSA*)_MfZA6W5+HP3!Oi(`ya`Ih$9m-XPr3Dh^|qgt@F0{Nhzw+YHF<3N6P zvi&$%;KZZ;UofF$iIMggmtD4IR&AHqn=xv;l&+dNYxXn_46Gjbg#F_#UDu6m)ml8> zym&!F+=y0hGiF4i(Y`3OW{BRX=lm|;8J)l)dg)RQ9fvAS^WG0}&c04MxlZ+Em(uLP z>ilwuD&;Zk;*i~Z50DNE;2SmGafXw=Gl}D4kuXlF&M%E<(<JGv!@i?$lJ?W7f9-2M ztPy$B)g+3Q|1gO*jlS-K(MNpHz#uockVxJB+l#^bzu<$;>lhXI4`~(ok9u!24TB5; z`H%T_8r*KpUqj?S|0caHe=TY~i?x27$Wxxe_z#Nc#%K;U?x7TsgM9*xa0bJ+*@P8) zYlhQEd)Zma*5T;5uLd3fmMdT6@VV!+%XdDrKU%eCV@;<xqt>kJl&9CO-?h^0?OoaT zG5f~@dkmvSi^ZE3FKUeI(Hg_(D=RCTlSm{ycf*{M)kx&apG1*X7=AcavHkq$Q{Jl6 zaNPWLBwQM!z1bx5*Mq({pgCY?YIr_++soM7K8?kIx%2%D3DSqE9S!;)j)w$D4EfIz zarARY2Y(A&#f?~o)W<CO6rStP6Y0)+(zs(a-qwRn7~Y{A-6J4xL;ed$PQ$UW(JKu* z^Sz0<iZ6OIUf427AbS;vV!i5Z%sS(qx0^97!H$kTADbV#HwvM#|EJ!QWmkaqP&s@i zU-D65*m?`vX}s^3i5%{b_kOCgBVWO6B`y}PBuR`;1#sUSoTz1&Rztk{s#p3LOJHmB z)19w*?<EdHS!W1?z0J>dfmZjH?MoP5-Ri4Q{R&1AeY9jhxGRw_Ajmy~LGBygoOKQ! zeUrE&w_)=;R>F<_;5JbHTV4rv3{-{6e;boy;X58i@A!`I)I)5#9nJDZ4B{91G|@d+ z^=}s+A&wE}K6nc{_4tauOWMid50E6T{P$4bS1}#vAgS-*wZsv=Pm)ZWs_lv;;o>yr z2WS--RUO_z)Y&%sFyvzZ_CEyU{0Myp{V4FW9|KLkowNgXRKFtuzUD}PwwI{w{~`hU z{RZ03=+2$%X4ke0J(+0D45=eMYu(PeS+go-R%4|_vr?uYn97}|^=zt9qp_A1%NrBA zS-r{JJdIK`UQ^_0(;|_mLhGg7!{pjS83d!}Flg*1(t@p6q=gIRpAado=GENBOdmyi z8G|y2#@hEQ0@bARcc8qiFv<(mw9fwwjs6mb8~^2#AlLb%EKL5(|C~tA?{s`5FF7!R zEBpnPO$tFSe;0AwUwUca;RHsNe7rUPE21ss*Qga@+ufjQJIDo}zsH+3$-%Z#R;tq; z-hVH^K^QlA!l^o320X%;W_C_|G{N3<)RYWWTPRDKptQ@fCaMpb-#7V<=9Y!k9m0${ zv${iSOU*mM>#8Elk}jzlC#sU7)O6L=cJ`%GMq4~u)qC+p9VxB673`*SQ$2qlph1E+ zTbBce`vU|?DgOZKi*vLGiL~}1V(Y_1dG!&JG?70_+~eOMoO})8WQjvOis9AC(l-wF zV4UV8;*8f3<d5tqfXV3nK3n-v=_ZD~lQ0?y>6LASXhRQO>2QK;@HhzlPmB6C?^>7X z;QO*>rd#T)UAuE*-=gtsZ+(4l)~J8Th|P@|)v_6FTsS`$)%29zU_ExkL1krW7qH6c z=yaFlN{F4;c_9lcqhqHMTJ}EelgOZb5_0cjSYP`@96zV8?I8eFkMiIK$jBumj2ga% zhz}=8bZ5-<{X@QZH|YBqQCm8N@BvV@@p=rak#ynoecUG_{nkStym<CIqTKU)Z{M*2 z4?G>aNB$2!di$C?2dA#R?`>n#i0AE(zHtFH%7fe0!*3Ab`2<GQ>`YayzL~s<@$K)C zY?n@DdG{>-=^SktQQ?Cfz%pfLDS8L^+@=SX;#@Y{K?pQKxBr}UnkAP8F$Zvby3yL& zA2LI;XN6grGh|cY8A_+)Oq4ULgc@Cpe7tY^4>iGJwO{Qp+S(GDB+G_bDc0-Lep*(h zCsWy6m7cDQRx<VFnM|ZBZpJh<8qYTA$tum{O>KL5xh_efE^^&7lQFft`doY*{k{)N z|BOk6K1wtU?DxapC-U$wdvkm^XY@1P*5PpsD^ax*M>f2NNSSW+(z5)MzH^9ixc$el zJOuVm{sl-PI>J9p_Zuz{b+o^FGo?5)dxW^+yaS^W?|sUK5tJi_HWH*hdhk&U*0yI8 zQue=Nt&du*Ph(a!AK%zdrry^QEk^&qZU)%8-%mWSe-=M4`P04?LaOu(MpG>PIRC6~ z_b{noY!T^{k1ck_{fCFEK1Y&~#xo?TI{!S0_Kz*`X|OPN+P|=TFz(u3Anx>w*oqN9 z&7UDqlk708$a;o2zn6%#>SYo=-~U&VmXd#ks5PJU@g~^%Dq0~9`}0xj8SHI;L~}Uf z_8srRW`;1_xfMtwNpvR`&*1Wuk6|_KWi$e~vzve2C*i`@H%NRU|0YR3b?U&|t?vMu z^Bod5c68UbFe>Gj@7^ZPdW!F4!<oF}oMESa7^t;a(gptMjDFgKyZ<6d%K85x;+SjK ze9qnPv8_JK$A5gB8na*zgL~h@&lBm-&q%Z&|1ROYWDCH*InsquV?=igLGS2=(0g<E zLYV09IEnNGjKYpLpekozMFq;OW?6`M?K}rB@Yq<KyPgFad;{E+Dlq6~GN{B+U_mQ~ z=JUKep8`*!odp5&OS%4+yL@yDu2V#`{Vi8JEJ)t$%3~h^8CO6y$AV0Pmvbu?Wj!t^ z0DA%FEvQ8Ob~#BlD`+GsXZY{l5yqB!cJ3LRyE^ekNK+hd@kw_Wl^MH`bb<;x$<|dc zy!A~Wqz>PL;RzbIV3Kt1;Xiu)M;@p~Nwjfn4GD6E*!zqVC!Li-f+YDB%8)e*qw|F% zh+u*K>Bj;y(T%xSyrda{NGdEym!K|{BD6|PmWG_o+38|B;~g-8<^h)8-EL|U%T-mi z8oAuuJsT`txX03kyX0x<HM{0!GDd4U9nqE9JE`zonx^LnTysyW+4>kK>VmAWbT|~3 zB)wYEV?tC-Pis%<njF`aYF!j#p`gr4dL+_7g=vuqEz+!qK+g*0MEQOx2@4Aqq}>=_ z=9BLs6f1$A>6}ayO+NeFEH?g|ZE-AYjU2sVWQ<GnY_@q?yh^C6UY2N*vc~krO!p<= z(R+=7#)^8eq1H&X$o1)l`vmLJmS{3(%9Z7sC0lDt6lIFqEcNQT9+yp{x_3re*QBJ! zgED;9cW!VTsUpHBMT#{jq)EC`q1wmo#yot^BMTI2ND_CUmc-xpzv<PT#*X-CJfsw0 zgu~S&N$&8SPAvhL8MoHLe~-=ay~1PS@BI;qoH2HoJ9jQKdOEUV^%OJH!S&_(ja57D zH+rXZi7m}$T{kxXT6UN_cHGbNI-iTPvY{Dj%rtq8H`zoze`Q-*jEja8YiKT$bvenU zT6v9SHQv(VU|qlyfox!HV6$i5q%h&q{NAe@aWODnTdy~onwms`W+)*NNf>%ms4{gU zQ-5WnF=fgWfu}i2q{HPFiY8UVObRt|)5tZ}NUX+)cUU@Iyh9YidYDUHKfg}Z%9>hc zu8wPVd#51U?dkef&BDyZi|TYe(b6!mD!yCMd0q8NdSD+9ox$`TB=HpLNSew1cZsw; zgJHsB2$x>+YK(;}rp34xSU5t?hoew3SV+`j{s(JC*tq`;#?4NlaqE3CIe@Q1sjJX{ zWV#nI-rY!&Tt>=C+Qt57Nqph(ac}(rV8hK8fXA=UjC})X6NMJ97BCX>c*dQXj0Qce zPdiYZ;*$!&{0dXCbIX)QfZBNh*h30!UhkE&qIZb=Z<<dth8WV0$+AaFvTR{G(UQcV z5ngd|?6A+`Ug!W)52#;K==4f{9xmPGM2Uj$1!94gK#zyckc%iq{Z*9Q3rTUCJC~S9 zF4}BnGNvMmf~m%oWGr_@y)kuaWlS;*LsaF2R2wnq>P5=Dn%eo?sua(4m=$V58JsEp zJQ~$0Nzx>~r8QxwT1vMXXjRp9scEWxb4G8Y>7-<66;+yMu!5|ml42~T%LIPl<gIY= z9JG$;M47dlC?k$|J#K{_Pqf1`P+!^qqR)Sec{B<$yqR4Ky*_Niz53%`?sIU5k9S}i z?$9QZUOxOf$+tF=@@hQebA8r07?1M2uk}sWS~vu9{1y7p=peu12<KZ1zV3dXj}F*5 z3Io`z?K<tPK7TDX!r0{``Z@L-$tJu1DH1daGf5Vh!YnUEgQsPb^4-J$+T0+>6h1yL zK%n~LmykT@W7l|N@*HT)#%$5ZBQywXbcH!+^mj1YFqgy;3iG@<i=DpnNwHLg1xN>g zG*Nan?!rQ^v_E#EkJ_Deshy)oE+W2pvDXe%Sb|{$Q-ZrgHG$4lScYcxCgu$+BkgKo zIo20xJR@^R7>Z?rp~pu_GWAF|8qHlDJ#>K=N^q_qi%qt$0?cA1iOv^R5q$$`()lZ_ zCSm7D4=L7SJda89uAcZ!uN`lcd(T)rdhB{M0xs{aAz|xi9PQN0*iNm*d;^GbIkVpC zgKdS+Qi)4I>quItlO4xLtH+1EP##TUlz~CMSctvrN$Vah^U6j0eu;TqKjt01umS8c zoaIKW0-fu_lfh@32-ravHv9D7j{?pLA_5Crh#K>GJ_-kLwg6&;3R_9|<>bt9wMB?Y z7hw2>B)73o67jtcgZ@c$dd?$R5yr3dQoqrd&w`C%z+obfDO~8aZxpuq{E1){!#9C- zU*w_s9-HFW*PYg<J^J2uECcUxbn|ftvlJW;v|BRF%)orFhKmx5y|-JnqjaacvkUjD zODoN^xpF$g^=;d*VfUJvW}&mjtnHAS>sIgHxbdPHG&g-2$Fy>hCPj=&#^(%0R?IKi zcLxnw)D`PLlZ&cVZPQYkCdNR6EQ+!u%@H))$u7#WB9mmr9VFX&VJ9hqp>Q#>2V$qX zu#2P%jNOEt57#ES+v{T}?7{X1N~X3A5K5+(lH#fhmk~~RcBB)0_5rVVt8lr`uZnZd z8%UD<$VQSCcw`SLUaN40SNAS_(8JYAEBp}Xd!?736|VBhGH<w2%aImT_XSXv0;nle z7$R`Q>^O*Q9KV{x9Y%H&EfIS$=>m;22=d$%_IY7j81_V4JcoI7>B0ypW~{KEq<0lY ziBxKgv@eANzIDRZgP5#v6771M&nJhya}=+fcr27X1pF3-L*A1;{#hUX!5BcO(Htht zZ{z@xMjs(ro5y~My$zj#gFhl^XJdDJWh9tg>^-dY<D@wpVF{EyI|3@?6(&eNu0zYw zx`BjU05SK40+HetN%Had*Sz)kocT?XJc%PCL|yf2pO@mp=d2rHX#w)QkCLKg$3VS= zeOoaKZ~{pf5F=WBZ@R|!rng)kSGbm>wT=DU8T~ZG6KC%~PKxLo`w1xycI<~<cojb3 zkzgIHbZCZ;&lW!AlYPKG6s{vtl94f=H50z=dQv3K_?Jm~AIxLtiS~D8Nw=EXo5%x1 z7jD3)q@8i~X8`t}#{Bv|E^{Q|qt~E<P~k%)d(mhQA##B(eAat%M_Yh2HN|7Oa#la| zdEbiO#4rogBO3oaqB5`^;gvrA0qOCLK5GvaQ84y^SL1YA?;^?GM`$c#t9y1n@2$V$ zoRTkitz3nhNT;Om#dAE4F5kQv)23ZK{}NVR#(mo@1geuQ06f{7Az2g;K1$@ua6i97 zJojJ4Jl?MT?`yuZ4Jq;0Nz~ub6mKQs#WzR*WI&t0baQkmsxAj3%kBU?6lAF_P}m82 zti<I;zDDx79a`z7rbiY7`5wagn?8Fa)E7Yon~}SSwtzokutPF(;Wn=fKLVnM^LP7h zVnFzO3!TTevGe$C%!cRg_;-*M71NRmw-d+xt`~|U-}0RxOhy`AMY0=>;+lvnWqlR1 zLAW#f9+3-wpFnG}g&%;=eu(XZo2Bt??EZjjv;C3xY&+}zF($9LGx-T-hedrymwDGc z3bM5oe(J@1fb*r%?;vVbKl4!zNK=1Gw9y?yqXSu?@L$;IKPPEig*$zkH{6F6B#+Se z{R9e>Er4n)g}c0vDF6&E{EBq0#{No_QhrUeasGznH5>agQI5FV3-Pf>eH`$0j6baR z;vdWe>bJ9xF7a_d$V2b(`PYF}p>XdxF>UT1-bd1F3-^090(kbvZwH?}K*WUyz4A)o zArHrS20u$<&yegJN2a53|LI0H6+kxU!Xub2;^OfRpF9uG$5ABPyo}L>-;ng7!lPb^ zd+a5W)x*K-zmaBLI7YJXjXdXr#&K8bb6|q#{D?Oa{27ee(nF_+cAOK~J0C-q?Z+{E zM0-{^3BK`|SA!b)oez85Z_tHP#53@?PmjLa%_>>=Ey(^-s^7t(*z84t3!EChwXlLf z$-eL&^<YXVm;K&zuQ$bOjp)~yul|r1)haWoC-n;JzgR5wL`||enQX48m{L*k@n$_! z7ga=2(p7<z6GrCBtT8pCRLBX%(35hlmOe=fI?swmMs*%7s%cRt4WO#(wqHf)>4}S+ ztfzFVp)9T@DrR++nR2|+;X#;Hw(vWz_iN<1Px`{+vRW}}ZufoMha<R$@b|>%<u|?F zkFnF(-XdFD;ST^CK#uUjf0LxRu@?wdY`X9S#(Q0C_!Bm3SC07uCdc^wtbZnY8lFV- z0lO18@>i0rd*oS?t~l}#Nnag#-pB8M@1uYKQb!j0Y^7i=BM<v_07P>+(D(~+6@NvX z9gN`N>`!4feIzLr{^s100$d_c7ibJj39JoVf_whGdCFmqaxByYW<|2Abi`cee`m*Z zPXTP0?T{ReGL$hYEBUyE*>X*X5b4;XaiXkoe9yE@a$Y|bo;R;s6%}1mStX)K3==lW zxs(y2bUSXFlQoeO`z|*3tV&H4x@*mvE~&M8)%}8?YPv2+qQ-?6H84tq<s*!yEfGSY z8ex!=#AH*{3`N7dAPZ%ZrX*=b<W*J_IF9A{&q;QM=BS!#om!#kg5lx1ht~Tvg)=VC z9C^xHebJF_Hxnt@-$_zS;c2J!A0AKhKZxF&(*)~3J^m<?M{#?~Gen!+>m*-H0Yons zp7T=W!t+2ThqT!}qc36ac#$OK70&o1u9q;0>t(M;@<7OUKA`sg$~oNd6yo9kL-JgV zP9Vt_z;=`Y>jDu;g;y~Sa?-~^UL(fyz3#OpICCdP>=xc6N$rKVe6xhK=xrh=e+Sd- zT?zW1gnN5*;a|v;4P=!9sP$6#w@>ngy9%Ob$8YzpWp5CpGHzu3-+=`P)GsZ(``(&p z5$1b{l<c@;|H5n&zI7FY7<EE=hciwH`^MuI?fVZ&LMeuQ5(;dk&WV10tVG|65$}E; z{Id_gfFwTl7D?I~`}a9i*;-+dc4v*|cN&i4tdsG^^Vxp5(zz+Jr28C2&L^uwYsQBN zn4KL3QLaUvBpDV3l84mEiOr&O4B%b_l^lx_N!LHXc=e2;jA?;<DFWPir$XZ4`&Eo{ zx{y&xad?ORiOH7M&g~a5*s>+v6>8u`&8LY%sOnzbVZZE?b6#<0Ry5EmFjyB&5*(Zi z;XY1Zj3WB_w#$+CM}07h0Vu~Y$gw4@x|jgx5v*uGh1rYHX)l(MyuHPw&z}eJWb}Q` zXSw6~uxlY6wcZT8y~Rq>9hPDhwr6Nv#T3cbR7|73z@L3&txMC3)g<phu?DMyW5b{p zzz5_MEM~AhaletpY%umWaxT=0^$0s&LpV)Oh@_hf#RlI^5ZKy?ELX3&)Tjtz)W&{F zuzAzPW|9t6Y$4IwBCwYhr=o8F3*r7o-(6cQvSxn+=3POynqn)#_C*)le3%VaG|dYy z2U6|cyG>5t>8NVP>nMZrlEA9KE^v?4k@-5H)aNPh<V_FT)$SHD_twk>PFdR}TN@*b zeRlrQpdO;C^iG!7A|WkAr57)|AVM?cLaMT>YsQR?jf@cqH>(jk)z;i>G&N04MHsnR zkA$<#7k3-GHq>?s-B}~sCHGWscu*6Rpe$%9kzrYirt7%c1)-o!i%nv;aFIfByrv48 zrd3s0KNPWClBGR@pqB|zEj_)xO4qcwCsqY!yF?V;W8*4zcqJOAwUeaT7rT714sZv% z(YQEe=^=S94<s>fh#T$MLy|s<c(j_^x62!SGEwfMO7CF!(u>xHNp{7)fSb9%T}3}> z4*UB^5>Rn~AZgOYnM6u7i!|<mO3coR_F^JK<omO++e(Q4Ow?oi+TG1L2o4x6Db6Lr zcOIe|ue)~P;(UxUxZKXpQZ75u4UYz*foz~JumaU_7z!K?<O5d+t_fWCo|!hSbB8C4 zkCT%FFm8Q^T$iJ0MNz6GCtVU$<}d}#(%Ha3_P09XrMh}{#(a1e*R0Z#aYf**gTu>` zDI^X^v|YV{6J(ZSS(b}eRccjnRS^Y6vlJ?wi|KYv0><v5u~CKNdG@l0AJ$u11{$^I zl?#n%R8Uo!QWZL~ke6g$VY4-y-qX{=MCja=0;4d(ow}~Dtjw_$Wum3L$<<6GLW>cK zjz}RYOj+->I;d7prL0^ML{Sd$G(|;3Cc@AX$M95y&e|0btY@kqXsse|(UmaWT;4Cq zoXAq#CYk4Bf>1|C%vMohRFS~n7b1N47lsduKvcg3IZi+gq)PdOOJ#bkU+t8vrJWcE ztux|U#xSVJxXSAaz1j>_t&|s)%jXM?Q<Tp(#gxnfN>_~V6jLa#5@PzIs%TC3K&2^W znw(pMKt|jPB5{g~u^YQ~ZsZDImN;;#_BDXMOT4W`V52QA#cF$@T93{MsNz>~8R)y* zONsVDezw9J?Oj}n^)=B5tFXSP()q{$)>lMxn2Gg8HliYk+bgd2)<ziuHLZ(lP?bH{ zcR6TX>(wpxEyTt}(zY}1I_z!sD%N9tWmJ&}u6Tnt@AAZr*ec|bbOy(r*x<DQ+26JL zZuCaQ6gPqU%|G!%$C=q?uOwI8at_Q;-+dc=Bfz(v=j4a+j(fgu1lV^gS}~B(9W1%P zw+cAIg;+%YakLlPywGvRy$D6y;Ly3qdk?6%9oUMW@Xc%owin2w=8U`3*Y{$quUkp# zG7qLc1J~xvcNcbJ(B65F&u-stuRjd-J@OrFZ70wieAY~-^%Ac(=D_Sy@6JzLiD4Ay zgXCqz6Yv4=Id=M9j%J3pUg6D2SNvcJz93uoYaqf-fzlnac3Zy}%ysL|JDoH8jxRPY zH;kKahW*c4{qG4F-mE6hmAu-r$F{6pyZv<5?A&>eG1pjc7!woUwyC4=?n`zZK8rfm zqc?$&ye{jDT~-62mLN@ar}e8GvNJ5NHZz&JaQA%5G^^&D>2j$$$4CZG1*1V$ttwNF z%{R93hAu|KU;ZL}*D^`hP5I(5MJW|b%CvY*ARJKNecHZNVXe=u4sp&JqwvLmMCU++ z;68K3id}zgFdNKF!c4AT%5~+Mv}jySo=6!f!|3l%&yS_qOsk^v>S8_<RmwnJaF|op zuFp^d>T6gsZacix7=v}hZ1!qbPI0nXfHF;9AjqEx1&#2W*|fs5G#ymKilECT{mHvk z-r(gMckXO6o15FH{$)(uthm0sy3d%EOU9z%T%xLe%@WPzVrp1#uhZK(L*k9_mW>f) z=dyPl#JP;V4XnDbCgm}wE=bCfKhA-SJ$X1;2p5<!wsXW>y?WPES+gZ*7)vTOU9H%o z#;c{8NvY=wVa|eMm3oC?%$QNWXiizVP*KM6b*37ZR0~`}xm%6<zEF1bPH^_0LnjwV zSa6mH=LAaid|m~(nF0B^de5CD^FDdVVZ>)wJJdU(?fWcz-t%<5**s&0Ib&KyLX4N0 z(Q>iUoSLu%6<)qXwPQFNO!K?u=Z|ZeZWs*>bL;ChS=UUpxj8N=iqXl6q9E|RB{J~T zwc_{(?I=|NMl4wKoM}mM>j<#4CkS(#Feaf85iAu2%kE@z&>IC01h^arK|gA2*|PKR zQ;epO-cX2=MO{!iIl=|CkR+Ol9_N!f7rrW{8O5LxjE5;j`R4YV$m*5-e7RcB>y)So zCly`P^}4!@UMcBj6`hJpk!T{E)Y7`7DMn38U2BU}+tMk~3`OyJjou=ubazY<!~rp! zFc}@>H+tS#Z9iD;miJii|6#dtpd&IK@w20}Ubu<as>8G_z(w;x6)rl#;fqc%63c#T zdzMoKjuOR41E*7hCae${jTTQTc5Ov_=?#Xv@-iK+ysE9Va*4Hs#TspqB!mr$o3DnG zF~&@&?)^ZgA}Oq~SG*E&G*CCO2x3i(gP3mqh$VA?=!N1C;;KMHD1!WD#eIMdM}Z&h z-arMUtG3`s!*WZW+EBI8-+zeVb|kV*vxVW@CW<yqMT_cDp)0=XUPD*)zI0a8)7xmq zNT~6sA!>EK*67fp{Y#XKibQN}e@#2#jmqDa)m2G#O{^B>sGu2SwaQ9$HboBzTg8=1 zE6td)C>ac^)T%ANG!|GuHsr-&Dk4?T77^z8+jMoPMXx?jk$72`1?#9y?S&leAF$@$ zD9GSa91fIPVH`N)YlZXyM9CIMQ0p7Ob_H5T-*F@y`!rfRR0KChilbQH2SVAwe_`WF zpysH(7a)f3$SX*4g4Q_DT0DS80CtkGD&Ndt72|IK>&`*nXK<(CtPi1g0>2O(-N`;? z_kGjtJJy2D8nrt4)$9>owP`3E!O4B%gOQWvL@L=Fiig1*#;~`!@I2ys+qiEPZ`%33 ziW8)Laz@Cb*0-?M0yZvs+t^hY<c^`fMbeHO+>h1PIaO+PZmuHu9^7*d)ZK9>F__(p z_Vj9OW)GphAI3(wztlSNVGO?Z%s%45pb~uHxF7Y&-mvv!Xby0MYp}hLO0kzt-)m9d zm$4B(PCN&n@MhR3eiHbrpq=AW#Br{}s%1Y^YIQ2QN+46Z)q3b1-~8Uf@b&L#N3dBR z;7L1Oyx!|2FM_Dr;tfu#U9I*QYW+0G6{Z3&{(}KMPzUloqiP!+r3xH?GUC<p><b>9 zU3W6|&7!bAXe6Y#n)+d~Hq*h*n9@9hpPo&}^@eD5b^O5|i+>2sH7P+6DjN5gshG+| z`FNB!E!vh!=z7AfCi-AW-yONkdzYp78LSoR0FPR&Ahx}@->dbEK#k*bUXP>GdZQ12 zK*a2!*RZ~J>lb`;z~bwRH(`2{HQxf%&%fx?yl%!u&`|4_uvWF?U2?{~1@SakDgGkt zcAs3DuhaL--nA9K;(HsI8PvR-5hNcRz6vVUNf3tvQHuk11{PaV#kRm;U<BsFwCzqE z?Isk{ZKG5t5cj$u8!M?HolXHxTb%A}#}LO6I2b4*f<y$hPBjv1;5cl;QOd5q80%v# zu0~TT6H^6U;#elev*CzH4GXfCv>sIqE2>I|x#;qUU7A#rWqBnVil|c<mZLaI;i%Ax zNUy{Sx~Pbjs8S&dQ6^%Bk1Gt_6q1$x&25d6tfZ(2cT;3{SeKWuT3%$S8l_grS@IiA zwM_|Wp&O}Q){<-5DpHy#SEqM{4fQj>{|v{gbfGCE@Rh0@Zct*XqQsJdA|=ac%`^j` z!s8iRCJE#MJ%Lq$^8<SVd+j<lP)fth@^lnq_N5X#o^uCk7covvO5fpQP+8fI_Aczw zcn-5XcFvA(yyOGZLgA@pRq3Fi@``3juW`DnMy4o9`aEsKIj%Ms69hIGj2Rp~dn3zh zvZ!gX3f^9sx#JJpFL~y&c^Ye|lA`gVlH99>DfkabN&aHJx>t?RvLpwC3?~V!$Vwb9 zOA(5fk|wWN0(+7XBC@fNW>{8LWS(JUjuB~vVj@(pruAuBPef*URb)j@G~yAO<^)yb zC0;b_TCva@V(UxQAP#0)V4j7ey91X8t_(~BCIcV!<?#U3VSNznU|_km_NXNSx7!Il z&IKnxJX`z)yW_vp)<xImrh$^1G^p3;PrMO#Y`f7mZQ8VkosDgGMJm%AR~Cx#B6CH^ z5Y26BB2k~bRK9?d6oX9~u?h>j#Y&lNWUJWbo=|AKSx>PkeN>A|<!19DDqcpdt=}4< zmNJnoTRvq$l%e<tf3x1QbEi6Q-h&JyF`~%m8ZBFZjnYDdS5_#z$eGbhnIuVq#0yL~ zq);pymP27CNJS#$3Kg=NxQN0CWl@@zXjY+u7RHAodL*9X_>dB0qD?(|T4Z28Rh#!e z0J1bUTM}#+tWwzSMjn-*(B-7Mu{A&-#nu87c<DEq5o*JsZw5n^RiSVqN#z8ciU~$| zzE-YAm3}%>{qs<;GZ;3*p&sf0-5p_L9NitJM(gV9>x`;$qb;NbQ&llpi`LZ}l@;l- zvUJa~o{VW^Q%P8_;6;mfJpihZ!)n5TuC8`_hD@zBrP>Z_Htp@!52oGrlXcZL3SWy< zRMKYfCcgZGolNIaYC5yd`g?94)pPmg&Bhh6O~yj&*}P!E0-z7u^1}nbl93CvKs&>G zKmx%4s!?(5cR3B9P+k$D$|~qu00o8m922R!BNUtnhMTIQO04QaDm+0^(<@`v?}PPC zP4#+p%BTzJK`qy8{aRDiqw0#O9;!~&R(7kJYHEPy0N;6lw={NmPP$NCLKt4z=>Wv~ zWBO*>QOo4453K!SYAxW<iwr9A>06YjmThVYhpr1{vQ$NtCbKf7acpRkp_*<FHBm}) zxUoMxH8Qg)(hxpD^Squkq}nx=sXj~5ll71p5-ZYr)NE*I=(YaXwQqHJ1H+l6UHi88 z|I;iTkh&0cXPT|IXIhu>%{2SX(52z2x@hpmlJEz@REI7Yy#9W(%?h$0i5nVXMpm%h z8IYns>)7h-+QvPBfxz5z=}x>faoTn0IOhV;ka)ZG?{?bu=%6E_?=*MqTK9`}J0A)r zlOaV5%8G1;qH=^;AeyqoEr`Stw9*@#u_8DS4$TaOqg1#*{3}&8bnEG8G%D1n7S_T7 zA5|4jYBm}hMOhY;iz_VBt5*c@>bJ$O0j~db%nEDE4Yz{UZvan9wNpV*4Adao0<?yB z?S#;-knO0B4h&Q$sdOX1J6db0s*OUG!i5Y<Eo+GWW}$h7AVn>b|Hq}WsmIjq6eT9u zYE_h+On4yY%0Br1Z=(EoP%^y@w0_HJebH*QWj&DdzX+|s*>_*C<ZDZ>EP}}Mi9aCw zKZpV^ei!up9*}V~=!tY{jZY2iw0QF6fvZZm2cszMtpa7mX&7rvT5t|n4bgW%mM?FQ z63+mxryRf#o9Nh>U2D^ej#Ua3*~qe8x6zE0UBc2!>EQVIG9y#Lr<-Uc&4skE(pVv` zn?tE8MXim{Gpl5s6%4MT%&v*8*JX|BnS57Sk1Qn&nN=4pT*)nsOpk>7)`X~m$5<*X z(o}6F6_zy3BKk=#$wz3BiG(dOZ;^hEu>=@F3WvgWj;EZ=i=u^7oXnUK&&O+dorzVm zk|>4PMp|j-EJS5!$+nXyAUEbwV6g;}VI2N(R_~ZHY!MLt={zbmw_Xt1c2#IdsmLi| zJuF1)o6HU2%}c{8mhk5vRe7#XHsp+AsLhcGAEOgmgqPYxL(B+<P{$iQuqiz6XjtC| z`}qS$l6?{S(u<%HLGee9zwAY5C$Rr*wf@-AjLtZo1&~3u_)}l&9ia6mjs?Sh+ap#h zxGh!uKC+R%V`Jsse$e_~UZ2N45D8iQIT{zr<G{*V{DtprcM)5ES!%U-jg9Ru1x^Jx zz|G14r2*j_uv)ZJMY)uj-rk8$dm9MI+CgKxG0svK{pn(gp81up7zYpDZv4#nAyb=c ztPZbeuMfAhiRBGKNDt}L>y4UBc*#I`b`QPg6vt~CLpL-kVy51bUt+R_Tok3UVkDwQ zD8bIcM{5GdD&deC5hIEvq^n`i%D^p~;;*pvK8{*{?Slerz1!>SngEq$i}xT6<~2Yc zz^#?yeON|IdjybKrg%T{Q9_Li+<PfL;M*Vgwg-Jao_jDK8slqy$Z37SX?+;mcLmTW z8zUb9tw(*<h~HqVK=<sNaZ7oX9nadtC0JkoxW1h4MR0ed2)xDz2E6&BozYMFJams? zqsM?;WA{A;S|2Cw$ZxUMQ>gWK=p@3m{N8g4p7lWP4_;5O)A~o^xc^PuktYCu%7Ar0 zV##+kkP5*h=5G4(61(c?WU?Jh^n_YhPpw|T*9jb@(`8z#v^-l$)lTJh(&2@VXbe@C zG@Dv0B2#<2H}Je63H)8m^71s@5eNtBK)lYeK$TO~52#h{+kCH!TW2#0Ym^)lYHEX_ z<x3+C5*;yUNiaJj%Z(_LNDG_kP;k*wmDf4-m>n{eG+H|AxoUH6=O$J(6hXQ#w6eT5 z(z97Nc|#9?Sv&_M&x$}A)J(K>llPiLyc8_*m-)f)vPGPwfdr!=MOIpb^$jU1GmSH^ zpA!x)e_*L0Tc^AtQf{<Pnay&BrKLS;WHOr-z1sB&+16c<VSacSun%d_Ck^OQIev2| z4#XZ4+k^pwzWG*J*DH-relmUw%S9-iF;z2o%}GW!Dq}*Os+&FC6?9YUT*%)`vIvL- zE<WklFiyies)wO<<u3tJ-@g)DpCY#Y4b^GE$Nf7NYhkq(LH_c?%P<;ZxBdfbl}l0T zMR1#@_>8abv+vXQId5NQ4$nKS-kH5X?E9i`+%ur{wA0rMvzLe?yo^Ok*dx5+8KJa_ zv+uKtSADIoVIyd0gx9eV^mm{3%;62<xNo9;gH#E`fEVA!tXFQ|cZjY31a!iQwFo3Z zW#jf}smy`5pm=9Tt`sCxJ8W`7O_`RgPqm0M>IBWyD8ry5J62^f!Zfx2ctb22O-r@$ z&Z>Ch+7Vf#%m~GP++a7=XjA4|r(>BlkI!4w0@jlWIL>CMt^lXn6$w+0#+mY%953tF zj2g4{n3m9zdaD*!%k(y3T8q+TjUxej$9)0Q(lndE+-<JzS{rOJGG1DW9aiQpq3*|x zHN0#ZlxZ?*dE&EoX^Cnxr*tOONTlLt>vB19nlbY}Ef*b9gs@48c`a5iR~glDBQsx= z1x+!S1?76pbZZu(lP5K4QJu#3hhWL8?o48zDbO`#MrE#is@hd0YKBJX1{0Z=jLNYx zb!~l4oURWX@2eD&^?XZZW0l#^zfBftlcCsO$c7e`I}B!dm6n?U>czr4gAri+2_OeP zc`hCH-9RT>;=<kzuDjc~BtoZSYN9sPD7L40UQJS!0=>R$Q`ro$)0}&f6{0d*krjkk zm9?{N@mTfDje-z1!t}LiV^*D3(^kSTkiTgV#%ccxaaqVC!R?OXzfmiY6pR1C`U<6+ zG{txA*2w_M6aJd5)l7oh9)p#bb>Hp_yk&z)r;Z1}atjjB_TVYZ@m^a~%J2%g(hp3{ z+Ko?MXl_4`Qw-TOV~Iv#PKuWe-NJM#+%%o-nQ~#Zrs=YIk{2!Avn-P_YRlsld?s3F z#;Vs|rifJ3!ur12WW2nlkB?T$$)p?gatzHm<CQoj!Tq7)|DaXB<gPmZLj)lJ3kadX zG$uuqTC<bjrpY9QApNWhr^yJS2G4+9fvq%ZeH-h`c<<G~nM|@i>pkqtq1H24E01Ok z^$obMf;Sp)u*Zi3&$~D<*p7Li5acF)gIZs4TPH=#bL6&42%c|ZtB|odxP28Y8ykZ1 zqzZ5g&f#8*Zsh{4Zfp^}O6Z<7|7pvW&RY7eH5dMN`^Jr?AjK6;OT;32RG3lAOR8dN zu=M6-W!>U*qw`)PWtyoTQ<bBp7&ncu$eLyCb1X_~P~v&|jI>tO<g5qVmB9`Kz1Oi5 zq@mVVu=VKPcsSTPETPsjSYN{@r@~!15AzHm=<WX;cH&)_nrPf-v2mlsx5Y>!IJIk~ zQl#r-+=nkOVk=H~Gx0mEWj<LMwk9!Ox{I^rJ`D<<)lDQkoUA~tAhYJ-l|IS`aBH|1 zYZXhY7zBMMgBaGkaHu5h(B2EZbC|61!Ql<;jHO8UFzCjrz6@|D4f<AN)EA8~xSmLH zF2qi>JKq}22kydbx3}+PEtv1SSgQ?(4Opw6s?-s&Izya8HUJ}?fKM<G4>SWWU7%!; zBb-Z^&)fvgBbeYjj`*|9sclK!u@cy3f^V6IA}8YINkxnClE_nnNDrDhJvvP`<3ZEN z&8sgnr4$!yHk5`~Oyxr+ofuFvvEu`xszk-gtXf$yLlHt|Sp0HzcUByoqL}mN@D07P zD$kC~+1AGMB9S1ca}^vf;1~~~ad-uyWbhp1Fbsm#G!Q-5djY~WaB~B+!VHL|O4;6% zlidrfK9lw6dvBrd(SsLYXTs$g4PI?^vJtBYZqMfxjNUe36dSE*xE-s^>%MIPkv2CI zF{FifE~g+%!K>J~tI-G$CR4HVgKjcUf~>%kZD`yVuoX`u(Y?cFfW+OeLTh`)ox@~1 zg3ehCI@1x=I*Va+2Z?G8UV)uUxAlXl^#$ytbfQ%}kHM@9yUpg#teZ$9d%UfO_jyjM zhtoP$R3Xl}lFRKFKDc}F8Pp1-LuU>%FdFIdwi__`qP;lsGJ+XS1$v#<XFL)|pO@x1 zF#8;8eGXf3KZ#!rPLd><y*r51dw}@1y#cS60mAHhBL2=KjXQV%wZ4VDZ5C>M25X&- z;jg<xpC{7vVFdN(Fr1v@JuS`%pC!=_m`i$cF3O1d2FS-yZ_(fm<hOcH)yR&0wbLs& zML!&IX($?|Hm(%aq^TMe<r$%`j+b>yNz$qC@_CVt4_i;;hIo&ytDT6j^!X88kqpU@ z6SA3{)(12<irsuZH`VCWyY;CRdc39tk!OG&4A(P6gvh78F)j`sUWfXg#_(kxg5Jw6 zrG<Gb_Vr`@7C~zt$VD_cAJM4Suv55zz}vDz2Ka0t7Kv=j6&L#?2pro!igwSXw@#(p z;g^V5yNC#hgCt%%_%UqmF2*eO#S8rltHTWSHCI;r9_c&{ewZk2?)Pbukaz4My>0)k z*m**I2d_a?0jIA^uvMHyt5`~;uOBDs7RylIr?GLDlTP~Z5^o$i#FI&IS7LG{_L+}c zANYnhL-gQ?Pl|FiKl<>6*a<uy$OdKw76g{rGEm71>3CkfWp_$HEa~TctryThQ?`MM zhPUqyQ#&pbJ~pE)BTT7SSe6qj%qatWxMvO(UVXl)$ehLt6)~x{PLKslQW7HJ21OKP zxhYbaW$W+K!-~#xnxUJ5snw)nif-x>t#SN@6f20l#L1GL(9^Q*YoVBVj5P{tYKo{! z&OTyt@!+QrCcK1kxm8}d`0#$8oC)GnCs%{MYp`6EHa>$K<omiwm@v7{tBp8sTTi0R zgIA-y!{$4=0b%2d7}jhg-~c_jiKxMCCP_$#PNQ+biU&{nFa=-57L0q^Z#xg`E0!q3 z;MYA8rp-&-(|$f0_bkR~x00yH<OM`I{z4+<x(&??aG1$$fWzDmzHt$8^z9fQcW1H# zqsy)=@f&P}W5{9x@={D*OrS~GNl-(0|F5tW9Cc<zPwpnoXGruyeDKcq*@rzu9rO|( zt+>=j=`l@j@K$e*OlO^s5NZ5n2)1uw5dSrCCqLkwFMvaK_zS+Zyy<@9aHUVfeb_T= z+(tzY{ut3-T>iTp^?e!ZdxD5PS72JJyTT6=b;A#NPv_u|&Y=az9a@l`1UKC#uOezO zgT&J~gl7FLHov`?r1U7lV<0IFo+9#?+p%w)M6Jg$ONl%BKH^Cj#&*)}J3@rXexiMF zl&EujAG5@|v}p|67k9qjBypz614Pb#k9Td82R+#3#QZuV9KtA;+j`h(Jq^##;N$0< zH8iumyS+5e8Q}=J0SvXmaexKjCc$JLi?+8dmB07l4Vd-dA3Sy#ujQ%Wm6rh>bEwDQ zAHAI2fyonyiob@P@;_nYoG6XsyrW3Og-I_z8M+<3`D)LZ^zzZacr~iY5BqilAN?af z>Hx5N;s)^9N4?oV2H$#biDmL*7$tE}{8<7lvlAWQ8`qGi)ewcrh_1|a4-xaPC2G1K z$7FREzdk{-NDjV@Q3qFY{3K?dacRb<2(&Ug39WzE5qIu-Oy6}im3N4|CW29P7k+1m zcJ~`dx+bb!TC#LNjSl3G+Itg8su>CqTC<ZNv-jj@h!p6vM9%dTQRDarCdHr;hFnj= zOD?`mf;`=mH~J{;=Y6saI7dUYj~n5dz!!+T`6dTmr>(xO%>P9MMZEQ9Yy=nLU&3H( z&+L|SETC@RFB7d^U%~nwMeF`5`0Q&$?EX4t4{%}qKNxl&Lw#@cS!lljvM+^wvxFS_ zn;6Ae>0Ouej{ji(tYZlOZ^Pbk46Oj<j-LFs*Y7v@>N)h^-Hq>H^Fi+%ZzI|+ZYOY? z?BEMvmd_J(a(YN2a5zWyoBXa963%?SN90o9C&;wfNnj0_{2@u+9a4z6_ak%)UcyHI zu~%9=oc4JDU}pP=T^=*}6HJ<Rapb3{^(CzJ4kBLu%!}ERAm{Yt&wV@fBG}tIF&z1Y z@3XrIpE<n1nd>hJmh9{#sG&6ZYfQF8^5Re<l6{}Uq{zDo78!c-9<PPek;lL~ChsNT z*5rNIEKj0Y-j8954edET*&NsO9>A!UJMM#M)^EAoWABGZXKJV(qo;1`d<?&ld^3{8 zY^rG8Lo<Bm?;+pm#x#M+htUXcyQgV{!ziiC?H(af@541-N<TE$LyK*nwo4g~l4OWU z5CJ&(s8@z?=64K1?ku*#ZZtpOOPoA@j<)1NZYicKx^(b_S0eDt<RqHO3)rc6jJR7p z=+xqPbjnMkhWgLJ7(^Fgt;5O3z4O@%ZjVlGL#xNU8k4^zTGD@q`5EldfB)XL!lA`P z4dV~kx{o95|04+(hUO6^s{ekU6ZZs(0u4>aWKCDg{?mK!&d@SUTDGO!CLea=dfJ~! z^7c?GrgOS;f0A^bhZcI{Xq}n-1$^VLKKsp6KJOf+IqkiYq&e-q!aKjA6+Srz@W`P> zzMVXa;ql*yye;Fi^=!j<(%(tEZSSQdYCHKfMxR|e@DGgZyBzqm_nkvEB)x3%86S0U z@!F9>CZ9$7`vQg$&yjfMNPy%C9a>4`ug??rH;qx9$E;Z=&(U1mIlSP_tvU(nuuh)A zGy|8?y+ri5y-YlfyGVAxp#?rk@)aL$oW=I(EM^gM=kO|8+Zk*XuMuUN*NJ=j1{xRV zt8Wr*oNsy8=Dh7~qJ~7&Y$pFn)FenzAK6I|TQ+z<c9Pw-{2R4m(G7>6BvP#ZkalG9 zT`y0AYuS4hY1UT<NaGG&gV7^&-meaN>&T6*cB@-o9U{rVSBHr_?J^QBUrl*w0X+4? zYrtm_f>uFaO?&mItC@3XsXKR;M8B`*h%otolzj(aT*VRS>B{T<y=&_AR4m)FC0Vj% z*>dmL#@*Q9LJNdy8Of3>He54=5J*A_Aqgp@Ktg~dBq4ziy0HzU6GBKr?--NLe{Xkh z-|o|z|Nq%KTXTE+c4ud1XJ@BKgw({cYH*Nc89|@rF=k%&=_D%?{Eg`^t1z?(E~~O+ zeO9C8ZdUi7nKc+vh|8KRyKmNFodNg#lST7co3)aIXE0AifA;IhW*yoNjz$@$*BY%V z@NLc}0v4Z3s2%8KQuoRxX<ad!3RwDyd%bL$w!flzl{446f}t~KvOufJRxwwqnmDhz z7|zyEy3Q-qYSgmqdV{-Ysf|Wb7kJuD{;4Qi&(J8iYy+XK`<A8cOsyeDb5OQ1FlxdB zB3s&j|3=!lvKf|5B-_k7gAHz`Z!HE#fv&ilcxFJ$%C>;sTItWSZGmsVwI4U8pC>U+ z+F3IiJdbr=8oY>>*n@?DugLqpHEVDuy*k<P0a-(M1r8Pi`aK-OKAQfr6UN+3V7>wz zmGLSwyYu`r&869if$x#>tb^Wlvy%e5F0ngiC$luYY$ub_x|lv&JFu=pXsy|9mj05R z!t#E}_OSM^Y%fb2&Q4|R{Ml&))R)y;m}BT;_B)-{2hfcBSsG<_22+O24A90vV1-CJ zp9OaQds+To+1WJbqLIv@?Xlp*Rr+i$ZCggrdBk}9JzzdfX=v;VXb(#ST^Nv{PY};s zM64OMGGrGMc3uCOOy7j;(m-?{gf63Z7zFh*g@WCDWHOK>K!4gf#Nz7gawbi!VA(qd zzr{EoaoLr4?O!KW=XAmn>$hD+(3C&#)r4l}L)S1zww4~5SLYMsdL6-yzKmPXvO{Dy zfX_A(WA|mx=b5L6&(OSsPV^v4Z1xO%Pep2OH?eGpgI{84dD%_O-E%XR8H84!J(Iwq zkD0TW)V+nSjEkUK32#fR;f(Y#>2Di>4S!eu8X?R5k!@#LaI$9;XA^(M=P+$7-(Xq2 zv*$8t_dKTVdOm*I+r)Z9z54=&-z=BCkk;YQTs}_lI_BKLFR*T_vlkIk5$h;}U!i$F zd-18Q7uic#_fy$RS^7fuGNu%|oOw>zL7$q?+y-eWiEy+NyaON5>=0AK9%kLCQ`LBV zxxR~<?MuWtFOvm(b#|0Kk)UVnrsIOLdjh&EpziG6z<tkqgcRHt$UF^l6=(OetTNdH z^gfxrk~lLQWYXdx2JX1*Rm7dEzfxB-wZJUvT%XMaZe-w^fLw3c0?W%HTV&Z1vWGGL zz+F)G8XzIzXV=np*X$?2Gp-A0h(NMtKN(m*2)*84Kk73d`=4UT+d+`GVDJtacaY)` zO+dQ4f#rLWy^*O&e43`M>}NnfpAF20)XZ*TYDJ$T?j$i~jI77lebcvxjcj64(dQXw zD6}^W{*c%SeNOrU&Dm(RK~3N6&4i}tt<smq%*a0n-NLd+WWP*2^Jy%P?j%<KX^fMv z1iUmL^sDrZJMf#}vbPeRv+fwOUkg|($-C=^So=oy>+}f{LBGMeugHFraT?~bw=s9; z`&jETvVgvAMl$?Y%+tWPh%xwl{cU1b_4m2&Fn4S6Uea%SJH1OG=pD3u1VO*Y)M>xZ z@}kJz$=a<4f5cpiA2V$iKOizL_;TnjmPdc~Zp;lQedzw0fW;T$_op-_(RlBnZ7t+I z=HMfQU%x-TA2NCPN37fr*&h?R9|E?#?7a*qvg>Dm61e|_d<b$dWPe8Ea`5rMttcVW z2k)i%IeQ<)voE1MEf5nwXKFLQVBOPX@27ov(D)u8GSowU_UY}HOe@MS0=LLB3BCD2 z8qe8Z1?CBMDNupC#8(@bbovm}KJqZF1)~-J89^idN%S$M&i@Eg<~~YT>AaHwsN0!+ zjCG@$eVmSE%7WXa>=9xXKD9i_I{Rdg5_f;zu6hit!*TF_4P`fYiSUm=pJkt7-7LYn ze%Ys)`{f<rvu6T2)vtlRbx(k{2p`bFS6DK0@KvV%@Eg`{ICz|~GjZA9vOILMpkitk zV*U@ToqPBxR_u57k4)M1XV&TuKSI!<Pvy@tt;K&LDw{urq0ce3UC95>(>HC|zXa}L zi74E`V>BI7C%_kI35MqRSH`VOCJS<FWdBZJ)c*|RZ^*vHI%N$0f#pFu_;=#Tp1%BY z;MVO8LbksWunqo!kOHr=wB5nKFs&o6v8dtDX7JhT#5bP6-*|)IAJ2OD^q8}dPit=y zr$}Fpyv5`bkl!r(QznhPP5X#t-yt;NcbWGA@3C&EvnLoQe=hqzEhh$FA9DxlJ@e!k zZ!3R2-yrVb{il7v#P~m$lJTFX);qKRVnxQI3c+~Z*?$MlQN#&&@CD-R=*#Hevd$^! zng3x}8%m%3m#M@5kACv-F@hpLWbMtcLU=Aj`?|x=JZOm9C$Z=!SH{|Pb77VTUJl$& z=c2SvGWskAKI3ScJ^BpXspSNgl_4k6{0=xB%`_*SS{CGF!UlwOtenEScgm@Rw8gYD zc!G5wnA2F^1Ua3hLFEkAuDbtY3><JdlQ@<67_~t3Fi)>&&Sv={dgtzvrjc_{-W-&( zegvFDa&c^LBQ&2}g65H2GO$k)Cyrc-v9??;P1yeN{;@O4+9z}6ga+f)!itTV3!eP} zkee}A!P@n5m4xlcA72&AO1LvZpWk8cfM>W|HDNdLyc<3o<4NLEPYogGFmxwR+#2E& zZ?2XlqjPmEZ~I(5L(V}>pUX9{Bv`JIA$c;nCh(pC)H{>5m*twrc#-;8YoT`;B(eT? z>XS#VmB7BQ1HDM!b)mLxteeu@xKrzIxpwB9$Fp>oog96_%1r<`0QXn94*JQtNd$*X zrmbkXPL@A@u8U>Ofn(hdZj!SPu;!5iUirBxEV+{FVck;glvy79JL62+?`7h7Dhtm$ zZI<0FH;vX-bA4lMB|d%YOkSAII^pkBSaZwu)6{}+1nS4-X0mJoJ2jTQBRB97JKHRl z{+*l6It%CKu-fi4m~=Xqb%U9k$2uG5=7Y}`ur!g}!hqg$2f<B?h`2A`_f=x)%}6FL zW}R1ZOPF-Al;CcE{g$0t$IhKb*QU>bxQyHimKQ?~#ERxlr+v%OXCPuUx0*gL!nM3o zVfxsmS=w}N4a<XcXD#jTi{`bK(J$N^x!gLYTv<=-y#7A5f#pAu+eqA!_|P-xJq?Xy z6LbID%(7ta1im1-GXq?CR$wOv6qwsWL0_gkncfHeY$e9yQ{Xn%o`L9TJ8csN@(X<r zYagD^jo;hZOikb%LgM*+doGg;&tquBT<&~^tl)AVWA1k#0yK9aD;{TOJ#n`2srBRF z8yB(cFu98ZJ`jH(c8g0`nttw5<_s=l%8|=ik$Slutdj_=HJuw|O75L>JTsct71Unz z67p|`@n=xG9-=e4<UquHZWpcHQ#3Jxd;0*NNHhDvZCq}Y6-|)a&GHG&?O|xPTy8Ie zdy#D?w~uxEmfO#i4F`w{Hf}#T;wCD05bL|d*(rC3wxOZkucB|kQQNB-RK(@7EZbZz z$J{6LM9i_T*8?x0T#>-ArwdOa_JqSMAG_Q&AJN;j4DUHE_lbZGblsTqwvU-lGNIQq zrRJxYt8oKM8`?D&e0C%AJoRaoML+i$dJoNg*2m0&zp*ri+)eb@(VpH$XTCwucE<W; zc0#WE9DQGedjC8Fn#qA&6uB=ldjq~(J0}pM@_W0P5z(E=f%~f5Ed<y5D-3Suc0~zE zjBP}@FB2AUANm!hKJ-<l#JZK>P@i(YMnn<&ZNJWxO5Z^8;6=Dw=0IFr4&>p_eT$%S ze@3AGRPNjKDGv4a9fn6rCI_X`?F?O<%iV#q5xP_!GC~Phk<a1%DmhbnrofVzut4KZ zr>ttZy13k4r*w?xqf;H(w(Xl8J#D9tE)0ujG&*gwm(<yIS6zHEKe0}!Yvw1`D|Ml0 zNC{1FpE827wI)j$HJgd5n-Frub}S=VtB7%4*<e|g8K192lM#6&Rd3eTNaeL+U3pAu zPUz+3l~sIg1<I>?GIYO-L2&b%`#!q0LE2{yWUTj!ba~@|_j4iDoohX;&+6w@28l}? zzjQU6G#p)`GaL_JcfHiBbx0k%;+b(;x1-NgYU`xAj%JwFW?L~0>&~ihg?;H9yYC#m zkDuYhtH)1D*-C9w2iKPH>J>GoluA?!;x&J4J8xo*IQIi0SDMGqcLC_#xGm5N4ubpf z+@0vw0o|77fZaZKSD;^zc|YghYQ641ZR9mNGh6P*L=R?358e&6^?Pv-ARE{&5Urj2 zA%=omr5wmsad1C|zUz-+<Rl$`m;<+9yS_+Qn;&vOzds{J_HYRgS3XMD=0^R#k7rEI z?E|_7F>E_DndsMp-bdjKX)Oq6KMz2`+=j;Eej)T1#9CmVkQ}H$Ff@^chur=2Y9i<Z zxCfwF4rRvR;W(y;U*h^>0B2W%o5LX+kN0(dytxNi^f0tAFfwo_m-`7lx6xz(3RZqp zrl9EVd)M~}dcdoR@UWP;Q}w*{Zz=VF@(p=aaOF^WXd=k?<yBgSRlGX+&MDm_tCCf> zP_iM!t5?LQJ9j(Nx3!hU!#90iX*L?9%w4vkB`T!O+Qdw0TuUq-j!BAkrX?AsakQ<v zqoX<_@G;3+FvXbMSIJk$P05b8O*Cw2Vn@s|R5_92s}pj(gg>woK>Y2x2hZ~jf1bO( zh5RF5Mdy--fK7Z2%D0WGPwoSC;c^e-9!~f@>>H$OWWzN?bvpxeKeU^*vZE$_e~sFH zoEVvB2M3kkb6zwj4|H8ue+)H%oNJRqy`dSQxv(CFSM;LO`{S1h!sT|nN*P|2C(f&A zlq6DdmqdG<?`rN-gf!1N@-o?#<9b}yV+m1=L~bz*qq}Z#J;(RY;rsX%!UgdiTGWmy zaV6?R<s}y9*zswiBOKK&!-`f<oVcVa5|4;lo2h86b1g-hSEct?RaMwl%>5fr#F9=V zT3abqrV{CJr8So8Mg<mS<{rgV46FXN1*rIaf{Ir&CF^6j?Yl(3kK<K%hv3C00_*q_ zBJ&cagnic#oKKH8GX(5@L*FB$&2daS*Ar`e1g&u<cLen2SG0JWpr9OWsmOuY*W59h zTSo^7eh=<UAWIa|GM))lglbSNYrifQEZ*c-YXa%Qc&~^;DZ6?=8@MPL<+t2&@4a_L ztTb;#EkPAycTE>M4$oFy+E8XHQ7bC%wME6&rUPnuCMJn9EZdw@?f#~Z%PKXg)Sg6w zOT}Y`OCClUSDTQ^y}EPdi4xvE@Yiazjb7~oB7uJ&3kwJ=NTr)e*u#z^gxqv_Zg&T@ zHzLae#QDMB5j5cQ=O>6B+?5#m3f04_=xI*{poBEoGmG%KeZ+-=8_?V{A$rE(hX26Y z0EN9qQ29;t&M-QIn73Z?`at{UZwT5yhI_b@$tS<1@tOM_wTmEo*yy4FmQVQoUioj_ zmgx83Yl!NRbcH_Yx!+SV_9b$?bAO;~dIC&ka(@J$Jxk2~7~b>$NXyiN?*>Lm>;bty z5q$ep3A$%Fjn#v12YMi7$8$729+CsA^}dgj1MPHuh8*xZxZ+X*tC+?{*RiBp?s?XZ zllu#6cRJ8PoKQUI3x4jF++PFz{Ee6)&QhQIJHR!(d3=c&`{S5mU&j4_ysD#{OEeEE z#JvdWwAk)WH6hd$nid-HbE*6F*+G>!Ey8;uWr|lA&Ql@yF@gpjMAA=fUB3KdFOIic zH@8K;QO1jkQW<F|<Akzr%1-!mQx(DFmCI~VxAg52=ftF>6mw$YL+-xhzA~Av^R&7~ zg)1ww%gVx5b$>*#GMXV7n!s1svhC<LZyQlF!6z)zzOe7>1lDl2M}QwL_X?p~dD7tN z0I$G^&$9@qR^m3av%d-|vcY@!hh2QZYK3rTU(Bd@;VD<_3aHJcVpyj*yiNR6d7YxF zN<>nn%H+`HhOThaPZxDV*L2-Zs7YPd4lG#U)Yg92lpV>)sFEWnTP)KwodpV)h{+E- zachkvMeJ~7lcD!ZvZ}hDS*m6js;QWYDvOOP&57%h<x+W)kEg_BLXfIV-FD(>F6}V% z&F2Xj`xKTyuVLt${)r&>I+L#k2;MG1GdU0`xnm}_5WYk3#(3IJmwS`o#DIj{b&|HL zj^;t{a7TrHC~<J#@TmI@C@J1yX%71yBIMHX5_HcFrVjoe7IZk_zRRT(AgJkC=kDOG zq48i3?+?uZS<uOy92PBbe?V0tkog?`0KP*%{1`Ta|L?P+u`fH7mGv(+R91?TQTxd% zyV9<#teoint*RO}HO(~dvedY2ZB+%APL?UI5~v)DiGn@Bnqa$cjgp|IdnbU`0C-<4 zRT#Qu+es-A7p#PsG({^eCQSNn21>hk37PXCmO1aSPH&?-2_8BMDpWNi-KO8K7Z)dg zP%Yb}SH#vu4IlUL1Ab1yJO@=_>57H!YxQ?*QIs1DN1n=w+U)RL_w~6`@XJx%v>Y?; zvIxIk7Oj?cJ}paqPSnW6<4ul}IyIk&rTg^U2|{+@r~*$KxpWBbMh^XqwKpB)1Lu9f zLkCvix_+c~a5A7*!CS5m2*1jsSm*pl;8gujFp_^!yX4Cx<sNjH^xVtbQUA?a-`s!b z6E}kXmySS0I02Prav#$D41b@gse_Dl`(9-2w)qfie230rX-xUDfCU3^_wYJw^#NnZ zhk=jA6!2LOU4c9g{fwT*_yfE4!Rj&kt=Bd>W{>eC(@oSKgKpOHz!xRY5l?%}h4KJX zfTQvP?Y{xA$n85p;1Ba;US#PSBLcBAK33Wp^Af9VUdA&7ns#0Z*iL*skISoghJb?e zT7brg)f)X;fbu>7cQ3#qo7a)&5W?yeo4n8R1`(?iSo_f%Lafur7g%kFSJ3D6ya`qr z?Cp7rnAbz4&+<00)_DC6EoN!id#(=HbqK24a}`lN(O-=uT|Xi31a>#TL5D7*_yK9; z`FOzI@urVU=+k*<6S01nE=Iq};Mz<+0VK}n=sW*BuvCq7(KjBD>JEIK#r^pdhQ38W z)2ubhmlJD*&)cJSFjx6r)=oV<8o03rBOAV$&>1`qs=yqS$%C8jd=-l>Q6#0W^+U?8 zrq{?@9T!?d)9}b7iZ@8TGm{4y;YONS_!=3<;=KJFeOo$wSwJEZl6CZMdhgBGfoIlJ zGK!YwpADSBpP+WFSE2O-uKoT#3<VScF`RF}P)LigZ5NHdd}Ck?#Myq&5!$N&_Aq=q zYFj#k18P11_JiS1Gh}=w-vq{!VSUg0hWlAFIxGDh;r(F%ZDCl=Gx=8VSzF+)8dB>x z41Jq;2G}9;?M%uUPf)$z&ji+rj~>CN=YIlxOa$ZUAmjl&?LFas2JUI|lZj{ue}{)> z(xa^XFyD!1aKhhF^TAc?4#*&q3r}DvM(z_+m{04$(Hs7b%8kB>dm!45zQpQb_%|%M zGyEWnrt`h5H9PP-ln)BcI1j6uZ6x9Z+;dER8t7pvbH?xESpd5OoW<ZXnBGqMm>hnY zKC1wlMm`0H$c*6bX9po4^)Yv;7g!WB{4~bg>jd<9R@;Left7}Hd5<MS^V0)+P(Prq z8PvX4!Znn-uhWt2P?yUCfARbP{TYCkq(;e>R<bEof$z;G_Aw3D5eBxj{2YQyA1>W( z<>%5dSNm6iet-nY&%+iq@O%*EoVfz*hxz#!D};SFzkueTJ%6I?vZXU1(33_EFe!Z@ zYj+zy$+EWP7txXv;tooxt3p@@1>b<QmR}rLVYtHs&H2E0Sv$h;yL1k#gFsu!FJaNd z?g%k<A16zR-R(G*wadU~rxE)Yw#4O^pL$-yZ(|+;`PbmQMh+AAHxFaEyn@BYBUiJi zd^hv%VK-0fr)a-k$vRCO2%cb|L_8gHH(WUY-KDYaS@Wxiod>tguV$@FehnQj3%O!v zIbGKVj5o9IRq&0q7^^_Pff6OZ4t%zrSWkcDHV`X^$3u8K0>8Lj;65gwr1=PO&_?Di zaR%*O1joK>DieR30v232hAfkJHY3_V`URr-Gg+&(YdSr*p=SX$fW0oi1xrUbKKRTQ zVlMvbY{hFv^q$`aZtY4on+rpigm#36LZhMULZ61V8qY2Pe>`ibXVdFJMjIYhtt%CA zDH$xlr#=*VM~p4=LbP??y_(dZdL<|d15AYQLbivxrG@5>1-x#SRaBIfmzULVtShUm zDyy!kogCGzmfDo9NxEUEj^xNr?c&;$CQGs+7|{dc0B1m$zpZMiIlUy+Ay!-C=ZC|( zoRDnAsco^0Sh8d4RDRsJvI!HEM1r#;f}%*A&heEM(J9@jUcRfbPV)-C98-ArGf7nz zEmBlTk<|rFNktV!O%W3*O;SWfRTP!yHIa7&A!>@8tt8^A$xCLqtkfXcG&?e{kCTN; zN!%Tg#j>y@#Uvrd>l$Z7ji{}~+%5&Qt|y5V-0r@YxoZV&NGVX!JK-V6!wx_{C?VM0 zJ>?mtKAKAD>GGK6IH~e_qk8L6o13@1(QaIGS|ohmPs3&NX7y^Fz3ao|-CrJ5AIYBs zXd(`?iC~YLu264iI;4r_$*=%VGhvD10Zl;56;<NbTjCyM()+cv^dfHK3fsGgovjKE zuTIoON7SsXOK(pmPm^s!i<+jiV#U@wrcIl6+*TvDD5X_hlT=;NRZdnEMV=M6TkMu< z&8uxImD_PU9&d4vg)vvE!n@~KXd<@fgVFMxQ;^va)g7X((gaxoyEQqjUrS3a<TtK6 ztZ;E&P7RiY4_w7v9&4y>6DBt`w7C?OFs*uRoZU4wTsCRIN>>Ww1<r~I6J_4wq+_NY zv3nAUXu`5Y!LsU;Ld@X|O>km@mS{*DwVjqAF0f_Q+$*bsB6E`WjyxIQT&mo8%)>KD zBs-hYWjco#&|@EehCFR^Z_bqF2d3sOz$M(KPEn|lOi`$oIfvtGom-uZSkucz<I&hv z*NFS9%Gx$=T1(R;vANoc$()tc>yi`Z+7)%iF<TDXaYZ*2#jq^iP+JnoR(+1D#bnts zjie@)IblQLoG33xB|d3r$>us!mQBwxEW;`Vn4&sDQ$l^AS)m1?WuaB4rYvybGS+FJ zyW4XZa48<R4L}+stf39SW#G5cX_s=FS6YUlnKQ(g!HFG0%!~?Okm{wlmXM7oa3T1H zq?z^hCETEJjdXo@pA@ko(nWU6w(T?Is2!CY!4ZyIder76TT)a`lqE^z1yK?OyUB_V zq}@h>Tvwh{J7(HVcA3}_ml`!aW@u%x@}!hV*cKPJ>}0rH4@sb6`+K1BxOd0xS%UjR z%Uukt3vDLXIYTcr@Q~<kfDSF4-KAR6bp1M43dcQ??kQ0~chYO?{y@kJ(z@N;`Taty zJsLClXp6wd1wM6OBFb@@OmB<TvS^-_N=cf_hq@7q&Xbl_CBsq8l=Nt{woSCBx-XeG zIq69=7B=IeA_y@_Ry9r$Cr=jLRq|earfJR8WEY81zOQysMJyJHh^ET`9M21v=(=91 z>tVwZ9NqID)WI3~AwU&1X#QvoDHk0$t0}AO+KkzHdA%#sn&XyJ+1f4jwl~aH`s*tk z+p4I3NSaik*JP@i%}isj(pptx#jVEbq@Ap&Y!ezQs!?TD&xa2_ank?&nLOok;4$4M zqq<egTv*#EH`OOBJKjD~nbBIeRGQZ47=~3|e(ud>hUsoQmK5W{OP$uEN`+}_Nu|oJ z)6$|YtDGa5hH8t7w~ffk!1UTkBBD2*br$e|c#{|(DR)0&j7g6a0DJVnLb3H3mqQxj zePJ-#Hq{%gl<`KJ7(Y>-n;ADC^)^_#VWlf3Ut><rgzKWQh#j+54kYJKo@{q@9aZ9* zCD~%qu8?g}lNHXE4a1cik|?<wq}(?*9gCKgg`)|%To%=BW_`V%S<KU{K+S^ud2}2? z{(PXnfE-tOFP0#Ty|!$Z6TF)cdeiS=&v)Xaw)%2CRnb(VHjHbUrA%sWXt~<4D#vw8 z(<Y4Tm!~#YCG2=r#iNG1Jceypj+Jz2)7DL0TOu@6q_l)yU2P<^RJu{9Nu_{R{w}gL z0I#YYUc9lltAJ=iS6+<^%?zC$I@i1LEb$(pn{;<W5z82B5Jo6AxEbSX&NgT3*08f$ zS(LWd3B41xnWm{qswk^o{ko*(?whK5z%pEz;K6h)VM)5BYL{rLyC8xj@UrQcqUH+V zA85SbHc?f@6<neu35qKGD3!80O>KI4yu53s?ub)*Iz?V`6((1#xil&og25>~r!!z( zysIO*yK&6j%q&qCbe@a5O+;B&WXV-yc#hY3QS|T!Pg#$+*z=^^w$K$W{ya^=)e)hb zYNpf$w564NhC6u*F)p3}m;iYENkZ5t_h37>|9;yXO_%E`RZkJqqmIPSb7na_C)Sm_ zpk8-lc4z6zG*@R-q_}E{XKJEosk|UVfQy9FU5KIZJZK_Hva70{<$?rW;RMO$3(;i` zx08D;tAdYduIduIPFA8;L_BoMEw_9%5;kO87WjnVu8`<9lm%IIxyz7b7h?GUcMRQv zu2_mY7O!7-#RSpSWOc>+nn=Jrov_@+@h<=e0S^Y>s}Aa9-*KD;kv_F6+;R8<XYJ7! z*UmQ_t;=p%(ND(L<UoCkk(+7z(-5>G1ZuDy{3F#C<*>+uNS{654sbkxj{X;DuO9U8 zp(7y&`(~Cdg5jn<!CCCg`|57z0>0X4cw%~gzuofj4O1G_wtlMCVg4d8s*4FfG7KF} z(G{Li+e?U?Cr`Uja6&%RLffuU4_6U&k31-_MCUIeGIks-^|0qaz>)-?b~$k~c^pG` z(D7~gK>*!JL?U`UfVd*idl{;m`cSAI-JEwL)(I%taJ`#*;*xw(;i<0PUfGOW(Rf0L zPF}4p8^4|VdNi4wY1=dHv!LF5#*BKiro#lDzpuhdUil&L++lpm@VxrVOV8~jE~Wut zd5@gs#P}{}_3G{0ol7t6S533-Va_r-I_&B8s#W&%3P)`tEopg>XYb&J*!J`?uvJun z=k7v&$SCJ=9{8o_M`=4%9%LHc^-0>Mhx&!FQ#Lq(V_)<99@<-dH?Se)_tHL8u;2VX z+DjYud*x)>-*E^;E$4UBR>J&#s$WzAG!JtB<qshH9EwBBgLtVth>zTp3EWH62gdiB zKfX~Z@J!hIA-eu-{wmNm9hf0(do}j<hT{Wc$Y*Km(OwYAozDe4xaS7u4e~@G%;f_& zzz|wsV!0T=@?kLE(^y_@2oG?)9>)NG*8H_BJPbPlD0te?kBA$LN8R-YzGV4N(0Dim z@~`JXow@vV$SPaH(I<(|u4g@CbQnY5@}Y;CnJe%qIyNj1VjuE1(w>~KhkZwBpB&f& z^2rgg9D+|9z<yqEWS<VuBZ%sOxXyouUV%ev!3^Q*d^SK$5aTxy{-=0+=vEc`s^&ij z{EGh&pp*BB*?%7Q13BR^ad(NmsZj6VWzy6a0u=m3e|6AZxme0yhrV$$edD?pV&+S9 z*1-HNjJq%t?=%WLU3Y`qf&7<Q6tH(qV7BndU%?UyWV{E@;PPK3*3X~UtxR6|8tqe# zpjTk%2Y@Re^y>k>g3xc!UZ@EAP1?f}L2nE6@GZg$3ac6)!xZstoWB{~`@p$<CqSE! z-o8sm&a1#HD1STHX{LYpdgv>m<Do{l(<I0PZ5L&tfm+<PHfJPlThL>=Dhg%k7QM4P z#@m&8y`@@~E=$Lwsd)2@=9Xw8R#m0SH3>W2kWg(yw{6Q16<zn^0KIVoFZlfT=u8lM zpm)Ug>5Kz;5Dm1)kBt8Z(e?-QtvrI>MQ0#@&?}#y`-RXUfw-yhZi+yK+o2Szhg~<) z(YmMylODsq)2Q*5DBx~zx>-xlI1eJe@;{^_4Po1>E9jb^@M-&&)2lj^qBO<QeGceh zsD+M!-2aEb$lfE`I&|)WAv@5PSfP>k=$eseWJ`#Q0X}vXu%4Fx5jf?U0F#e|A|c*A zb?c#4s7dz#TQ>YjCV6Ok8)MFH{qA?2tH7%#9-Sx}BHy?^HJ~i4EQ>D}XE`f3Mjp9r zxjtTN*D?`HmL<imRT5UmB+Zd)ZHdGdqM9GG);xcR#v!7Fdx-c{f39Z{Ij1}vZU|8B z`vkt12PgqTFQ9YjAn39H4(}OLJ3g=$L!0Q>Q8br(nKU`d;-Q?M1NCJex~GM1yJIKl z_ik1XLwf>z3}}7VuUNFcBT!8d_AuHJ=;3Z6(gJ4>MbJ;PR&VGUI<F#ZJDOpQVRSxA zKIDHwR|P@iJ;K7|(C1kF=6^~@7b8qAVoHLa(Od}I9(;|?*a`dH^#+6IGkM^-ng2OW zwdgYt>6pKtwJt-yqw#m}L)OZodH#{ExQ<q9GmFy?OlMO6Z<!Qxl+MJ3pik3lh@Q5N zMKMFiY5YM>83M79`3C}Xff)Z~V9nq+K(4-_H)!61ScIC^j(b^H9CYa17YMg+GggD! z^(yVVi!k#K6ej^r*T7m`7itd82(2tdUxQl*2jA~;_@V*(XnQf2ouCC_D(h(|8PEvO zU6!tC#tmmi%IwH_o9hRJMGazCt1`QM_309)angtw(_-SCtzoOIt-UOr&@4x;)0(;F ziyQ6kaZ<C?qR35hBiC@06LgWYWF;(1R+V5Yt!6c6NtIpR^_#>=iXcnnt}dWkv8ZP2 zrdA%;<4sn5z13)0PD>_fChKTwhIITObFcajahvS(*{@jqi#+U;xL**_nZJ+KcGRzl z4z)q(C-4X@0Z`kESn_7n&wu|G?g8bh$v+yH%VVeJu>9jpURuh64ku_|pkWYqoWF-9 zJM&KvSv7p<k${Z5XN+fOpr3tjvY-cc1h@~5ujK1k^56ql9VusFb$B6j4}OvbJ+z&L zx#4Z}&Wxa^v)2323gj13(!7Bud;S<p29Msv;^E;<Ea-uq^e(>V=726m@cZ!h>D_F2 z7Le3XZhV2(H_<-zP5PM!E+gnj#dLn0qI0T;yuuvyK^8vu3jtdl<cX(P>wjoBYn={! znW+IjO=mws*w{~NP-w>YW7_~B8?M}j>53fLGj!Hx$btD^gU^1$)CTTjL5DA6;b>$9 zoy7yq<+sGC);$@HfO-=7-_h%hbmzqZzh~I*n!x%0VLxwU{`bg^^&*-PJn8>2Fls<C z!>{7D5GSzhv&0%=oWLy6`9INlV-QYWVoI7<h>X(yp7#oC)%UImXeV%dN10soG*bpX z$D%RhCF#@op9AvTe;Udwn}43AQ|JG}+P{bY#nQ@$-(~0s-0=HE56|GX|D!Xc!L~bN zcm+NnX!QlcdgPtYF7~r6=KmVdazQ_P|HY!!k*kT>KZP}Ig@F@pm%+lu$YCNb6!(z- zTR?Y%Jyg+|H4#2H5MHOgEd4v0cc}+RdC!8+yckjuc+9$34JF*u-^9?u(9+O~(CW}R zp<VE<0+_#{vV#0<I+J7d7^L?k`O<A{=`NOU?&<a%8K65AaB&J=d<F0PJyZL9YtEe2 zoS?;`ml>wsvANu;ujI>BN8&9#8BPyKyunG!!d<dlTUJ(PlxdA=EfG$c%{z98TeevJ z{p%%}7o#c{TVYkm(Wu5nc`m9)qGHlW91~Pgm1KeAmd>0cO`5v4W!^k%#RRjVucuk* zS-Q}$c}K5Q`LakjTIMQXA}2&6YD5uR6rom@s=Fj9Y?KKNGZxo!F-{OgA;xiPGD-Oi zA_{wn_N7BBIF)gpEcv|AGKkB+%xar|g$aF?sXx6Ipg2g$9|Aj+1wHq`9W+`8&tC{$ zr}LCk#grbn*49=*vJ7d<V5*_5(zfls+4Fm4&91f`j$3j@ti83dCEAo;{vAb;P0Mbt zD2q5repxFg7=}{ctf;cgnH4ROuwBtk-ys2=KmP`r!yD)x3qs$-b~kwLl|kk!cz5#_ zQQ^?@Ck7eE!S}-M{N8u<oBKm{C_N_58T>%KJ$+=;nl)!Xd-m$pn{T#NTej}E2kh0B zwb~xo5-%50N!ZuB?wIcTzx7r1$mTU`&VO#(%9ZPGuuMaX-)Aqi7ufFKrHYwS;&F)g z(zuvCrH^c0w(Oi|w=Y?;>3(~my~K9^F7$WX2g4bVnTgB4P3U$HxYz>s2Rkwd`i|Sy zg?c%W+_vvvJiQL=vhM^k7{N0Zyn%R^*s<KFjr@)3p`=NI9`f%IH;)gLpa(BS&^KL) z_E0#p>l0KDo<8(Y>1oJ<hv|06qUMG&<f68Hfm=!ltsu0HU%Ai|gk4W9<%NfBNB&3K zz(*qi?7ZgPn7~<F`DfY__{#l6RwAErLBIQdkD%|l{XS5#_7Sr<8Tw_Z?P!$lVRuUa zJ8yfl*ah^~{0Rho9pV9wVaEd8_H};@C|40&w_oD%RwC$&(EmFBJ~1+-<cFU>N!Z0y zV0-s&0a}3m2Ju;nJpBMh6vAg7{1Wj@jOC$o2&g-kJ>vq{c+Vg8zVk58gJ<r#=hSUc zCM3(HD|l7{=k@$QY1s+qz3c0^-;<t)3xwwXg{hdJcx17I_<R^+?kqfpS3$%TTs;{> zU-o<0L*A-mUL4v?S7d{j99n_ff^)&p)&LCxDYxr33J>q1XvKF*emW>yFkFAnZzr<@ zWM9w!hZqUwvi*MjaF7)de1kjqATg2><}wGt3S9AXA`kZCB?`&^m*7A=`~7bb_a%6> zMm3rz0JOvz{|oF^P?~&**X%uFCGVtZp+HN&k}mo-VYT${xB$ivsI&$+bb#Wm5{-ej zqXW2KpoPLQ6v~MD>qjuZ+)PN-NAVbD1?C2!GiV<TL}NKjk3c4(r-cdWhsS_yuK{^< z@EP0#@BtXQj>67sFi&Lx$hj-`6El7oQ|W#@<2OA0bLiFp2Y%r556bqV(wTNBZhaDA zGBX5nnho87K6{Je<S(=MyAWk?a;5;{rLR1IR^YYJzkrkn6kOnlbLit3e>@%i3|DsF z7Xs%1$c;b2<9iqM3r4c*c{;ZrTEnyG-0*M=gDYui=jG2JaQzajt%F7;5cqo#Lq%fV z{?2%upraC2OZjc!Zim|*3=!*%p$EE%86U@3mKeCt6hNMwg2LL}3MwH9A1#e~-_3z| z`L_w%Fw{RD#2h%CplG~L6g2v53^N0<Is1@9)D3yKB=bPsE3Tl^vJ<WBAL+RuTpKvb z68M>Tw&YNWntWa4AGn`P0ca!zo8Vu6=XjYoV;#p5>lgujx-=fb^9txG2j&E%&<R2U zI0Uahf}wF@fA%~^IHCt!n*d=3L_il3m_PpE>qf&O3tziV(y?&6-k`=u?_qDV_I+%D zeGTnaplu<E+r9y`AlSnP#7=^#d*~g4VqNH=h5(Mh3`chcpdWaYR!EJ}9Nk&$s|(Bm ztlqw#2cWRNO+}#J*L*2?Xev#shw1}8oW$746w+Yc<sd^NJpVlke0{q><`bmncN4ll z3)W0Jbn>MG8a#(NEw#0oZLRh7E!zj1>*~ONTek~FB+}l;4RlPH&dqOG&T*zB&a0cG zHCJ4FwQic0WtzHW;s1r@NI0%KW_h)4TXj6A$eP*c7<vk1(0ScmZ+8s~AgaCqsR>#i z99RE($D_&u$c0g;q4&Fk{3&-=bhlHe#dJdK(uF#DcS8GHCBZeAP73t|O?e|}2&~3i zVC7B_7FV@YEgV7**5We?u}dE+NqBF!@^*BPalFt-aM-bu+#jADu<SuDUqqis5y!2d zYp@>z{?_@E1aILU3Qcs|LFkYA@4!iSKVe0Ok_JoWkt88gyr*3<hKn97<zJ!r8}IY` zPSAN~3K{CufMWc?Ek(w=r69&f<w*&0?(lhmXA-+Vvhv&Dtm9E0s19EMzLJGzdOV|d zvw9yHNA0|*M&|G*0;grL-h~#bhqql!;oW~YNADb?_fc)VeqHK1@EHP{aCKI&pTHR8 zLMt&|Ov}T=7=J)}8tEFdvhKV`rchEH<%A!e<nL31>u4=(^k-xCO>cF+5WqE&V**3p zAoZK!tMLp0Hqfrq7SLx;u<j;M+i@)YyU@<kv`3Z@HPA3u4c<fRi?H9T4kO9)I;>ka z3as;m@vM;*Cg54Xdx8^0h6}G>P;m{lorqTi`p<ze9Jq_#Ly!*hD`LOFJskKRU8fc9 zzQZ8PdZB~Pl?Xp8fE*%&zr!-{T|z#76MSzn6XTuqsv|6}!8y_2!g>)`=p-~%jN3vN zg1!l}z9TvIGJS$T66-I-nmvJ`uOnL=8a2!pSpc~t3R4K`#@g}zxmZHI?#txi=P{I+ z;pj_*Hjm{Yy7_=3c@(c)4_zw{p2$W|BIp~?UIHT1OSA7Ks2h)@Fg2iULg+Ns%E25D zg}#8b9b)m{C<nzGkdg}1LEC=fnSSpx=vZ)ssj~^~6I)nzhXcO-pog7h#5}P!T$o8@ zP*L&S$O+<ZL@ia#82%R_D-~dUc@)#h0MYvsn5N0>1+Wg;5&Vr=csC{Zez!o>c=Y7d zJ;Z9v#uV_LuQ~6QSdwBl&?u1I=P1gr*BzP)V<^XjYWMh|+91%{vu3*rRWRP#Ps&%a zeU~h-lgi4|Wi=bC!{rram6c`HlVXN*mt({nOHj4SRBtce-d@(;u3FaOZ!BA|pd}o( zqmhPRZ<{-J;Z25ao_)5h8}6Sit*KP&hN!3t5nb<CC2C@`Y%DN!GZl++ykJ==Q}=1l zr|dZ>EAZ<s^odYgXnN?h&{?5NLOJM#@)6NPezXJ(4Mo}`5g|lFV4G7k0oH$vqX3F- zZ)o5ZS&7D?LM%GZp6&1g*H|s+9owHhcdDYyl{j9LcrSj(5=AdgYSS3VX#isQfXxyo z2vRI2%YtdjqICU{vsSHY<8)E1{>_#ZE6(^aujtXavK%(b#Hq`dFI^Qb(>cY6CQLIC z38(m2%=>mMDhkmUA9epX22ukcGDkGwVo@m?ahvcGALW`%)v!2O5G~6xRB{hM``cVh z(f{x{w=j?3QEYEO_j&<MurQynclyu;1gAVy>i4Q@I>QHqUa1fo8{UWZj|B4jz<w7J zoP3Pt<ia9atKHd1Xd?mXR#;3t^Ksn!5|HE31hU|9moI08R)n^=lzJd^W9W0G+YNM! z#G+bEw9PO`9Y;J92@%M+H@9&qfDnd&(!V#4`9g_)NzzSbnj7L9KQ++oh>5ruj;Jcf zN9CB*VzpROEM*E({j7yEnj;fqx~?h_OO&G%g{Jo1a@2i^kti1vxtJuyqBCTk7x~h! zk!V!%evfhJ_pUKtxcr%|Yigv-pU+vn`mE1Kx$4KwIInQB7A`wY6vJAWpSN-2#w}qj zCaYXr?=mN)B32~RX*I>TXe27SWEv5oQGt&{_?YB9s`P8Lmj0a^^My&KWNDWBS8C&V z&98upbslstiFJFl?n?=}^y(B$r)cCQ!s5UcmN7IT?#d=2hRoMQP6IcP3XI)=p72Cw z2RfkJ&+_nyULUKh(yD7XmpwIJG~&7y<Kh*9ZD;JJRY%R(!j&1TX~T+0*=^C7rt;N| zf~E+(@PlyKxHJ2eo=v?mO7AFunsWv66y-rz0O(5Ef`_1|6Ta{s6y)W+;t=xvDD|)! zv|WQS0yM?~$aYj%N1q!D>%ra){FMtE2_GC!i#UV$hUcsBZ_qn9aTPX$Th0``rvsjf zfa6>~iaVVy6M>6(?<T&hr-6s{XiC0{spHqhE|p{}R#p}dOLEdt#Laedb973pP&xig zLoy}vLA!BlMo<(!p~`yW%FzgC%2DG-r==>S@)T+N*$MJ$70x8?2i?=<UT9A|i<qk` zH@sG^_R>e^lerRPb1rPb9$^rN;9jJ#4c+;?2Ky~+2a<6qZ8byvPNy|R1ntMUqF}!u z=SSfjoRJ1XLF{(nJR(ZOom=62Vq`G;kGCoymV4*3v=--$)NOkK@icd2J3;>c!r64q zfdV-H7yP;sfMW_EX0mWGjhzChJyf^^;Q>kO!llH>lv0MW0yy0jE+o8L{T?nSqAk20 zb^z!gF$QmBz_wPnh_K{&m;@1;h3&-LJm?THH>*_DuP{vH;`$<yZSWYL_by`R@tz4H z9}7Fs`o9Y86KH&+2wLiWH{g~%p!ZtZ@`-xii)RF(`v7!5k@w$QS#SqbxDxeVqK$*Z zJRw%SwugxE;Tv$&?^OiFJmo^KCffQ~%>rnSfO_}?HAM^iXm30;?*gth^&W_GPKGK< zarmXIGjJbGqG%1Z%{kv`Z+G9?W}NT7zSicx?AvVnw%*=@y`dP$y5?ma@TyjIfGi81 z-$!?+0|Pv~eK+ZO?lhNNdd57eyEBQ@LGw_VQ#OBI)K*14Y{e3KJ9pI&Rnb+Dud_R> zM8fK@)9E=K?(3`ZWXiGUx7RerdRDKQp&7EF&q=0I)&-_@p=G75N>AI>K77YJ-{2hD z<3N@Qa<({Xy1Ub#a~!D&r92T<i+#4;*4BRKw|-XD-qLqAcs1!}xtg9`TPajm|HMnz zVXe2OTc^42R<}LHZj<AtY8kR_SrWO|6^dXT4ih#e?}iD)gpSq`Ifp$80TE(_Ymt@W z6?l_Y0G6l1bzraaaxJ_EGGUL2FD8@|Zz?lwPMqqjTeoc4_P<=PY}p)HGio2^;`Wp& zc8~kVdrO#VGZ^c;@NTH^N${lWfyEhRLJo;8#bipgXkb1Sn1_K>l0X&>n9acp_c`^b z3eoTxPi_iFIvN`*6Ka+FrMlYk0imX%<*uKnY*m_Kac$0=IsN@Bez>ZyubUUl_))<< z<Z!WSUK9jPj`4=<>i1TZ6EfDM)>_4`j!#Q-ify~fwhjKuqL}ii9@dC^%B6-HSEq#D zNy$<&qtb9)V1ws5){x*o8lP1gV=-IX+QKXSKTTPRG?^EgmrYjq)q-qCqiyzr1p@=i zf3l&!ztbJG^J9@0)3&LZ(<Wx*M1A=jL$7fUbFG}@Y8htQOxw2mrix-kNk+UztiY#` z6`&+JK&)%wMi6o3-30tK^vh7n<-b~YW!l`CjnRrxW{pzf8&5foJ3a3I{;DX76}4qy zmNO^j*t+5j46L5@=~?dEFMq0OVJEDOn=_}aNvWPxzj=CVYwJ0!ajB-Y6+RhOGVn66 zPeh!L9@I&X0J!i?o>EdB`ok_Zy&>>kHY+a|`&2Gr8Oq&?DrqrY68hyTO_lgEJ8HG5 zRo3+BEBjZtKl3_U<m$-{XMIXj!**Dcr*W||P7~6+tjxMJlgU`+iu<1N#^&+cbD<|O z-%l)M%x7Vy+pB&v1~uD~QT|dzk&T!s3w_Qk!Le$_^EG{a%lodG;l4c?Q<d+4k*KY+ zXJ;DJj+smJxeW~s8yX^p-O%959~1aMJmrojgQ`7D@nb$PX)%s4WZHi8?;Wa_DddK8 z;%A?|T2nPEnpA{=_<*zeoTh<+HKo5#38E$m$+|krxmr;oc0@|Gw@>+!Gf-Y$J};e4 zd$_4}NA;J`W3GPe)t2&PHmp72@iS{I=ny|<L~XaGYhtlkimF<%q{7dM&$ZUZ6G}3k zv=0h%=WduYX9IYDOivl%NI_8}PDHBc?d|)T$Qy#FXlqib)SMK^8DoMo-~-{zZjcqA z@M(N9{5#m`K0`nq;GyC{L1oR|aL2p}a6{dPZ@KIKQxtt@g9?Xe9whO5|9{T8(Q!Pa z-3T!E(<8QhWc93Bvu+p|7ywv$IrKcJfu`eq60eTufJ*oFeEie#HHozY18WC9?Y#|r z<zC0Rcl`LpJv}}9-5<BddRP8D8+wS<BWrxmIy2or&diysW?t{T&3x#q#?qz6R|m$A zAAgbi1A2TV^k;XBrT%K@9$Dl3voqW6b(Q1xw`%r{-rMZ&-e?XC7&p|{Pj#8+%%-L$ zx94(bNg!%Zcs&!0%)>(feh#WSQ5A-}>r<<wO4HJ~aKb%yPF5?;erKgS6{o-7nR)xc zT9<JpTdax3WTjcXuCA`veQJ~Ky&+xb1y9Sp3RKN3d=6NyJdOCp(9`Zb$uW66?H}-6 zBIQB!R1#<x-k97|d8e1R%bWXLJH~&$%uF~Hk!o9t2xT{jQBBesM=!N5X>`1&JB^J` z#}w&HlVWzvoN%EWQ+U0i;qr8GVwL-{tKFA379HLK5mYwL&t}v^U>yESSs^^%=7!92 zXVpE9D@tZw>%IN>FE{ho#S-Q5bhOgZ)yR$7`1>_&UAM05liZ&Pw$)kbiQ@7mzs8`; zD+LhQT=)XWGpGZ*{zEwO)*Dp=Ji8?sqw2w?%y_5%*S}8Qz1yy@@2*?xy*0<<x4M5H zvJ<-(G&VMFbP>~cn_+w_>*odWSLci9e(hx#xm5rjhPz;XhjJJC9Du_5us=q6@!L=r zy6W4Yhg%4nt#|7BGJt*s_3(;I3*IUBs{nc{)~rD+P~mF;`t`us_ZtBEO)M?m0=p*g zeJgwmjrUcg<ACvA@jlKl0C!k8vYRm!>gJ$r;XA0`l0Om1r44%Lk)HQ3!I907Ht1mI zu{7eq@`>IJ{r4NI>Xnw}$(0lJ#)?K~+O*}<^4{A{Ct0agSSuap;R|imvFhs_TS?4x zrMf5C7iKcDB~{j}L920+81Z+BQ=SLCy%Z7e(y{^CK1R?@yC1V1q+>E8R6`sb{<|B- z-*%fbWy<271K!)6&z~>bmKxWsbfdhku4!7Vxj}Au?CicoA~7Q#k592(0@r0r(Zoc0 z?jqfkd1+Ni>wVeJLSDFosHEyuN(NbH3*W=k2DRz$6Pb#tKu#nN3i1mSfR8dbLwyiB z4yq_l2~Be~zuBcdnB#dO>uLj$c@=r41Bdly&r70#3kuS2R#fPMSY2c6?=5ds+zok; zt*UZOa^ifEud0bPm0M0?Vpn4A6`DFA*<D==yZ3l+-M@-g>yi|Wxaz6waKaWz+9L3# zVOoL^E;Fr$ShW%6owFrbbXDi%KoUj)_$PF*c317jnQ(yT$su^UyNmYlD}ej#!aX1= zLkILquCu2H_drdUvD#!^9H2RkP4<}tF%}JtKl+ikOZ8vpy`>wgwW|6pX1qzRo8*3H zn_bgBLGJ1rH&d9><Q|E1twVCk%WCwEk8S92Wm~6dn$4<VSgIx_bzK!=qTnPAgSVx) zp<0qEyJtZ?CF_dnWm&2Ndfiiajem$_pLh0s3~8dB?yUMkGfS3YT7@s2_0SKfOg5I% z;lB+(UEOL;oLIf#+;g4t&);0v-fp+9wr9<9RR-^EPit#`>tkz7SA(`K)2gj?-)u`! z%*pPYCb>TwY}-azJV3-x;YVQ1KgQ=dD6N28+B2JwHOESny{8+seGAGOB*X3{?qNMY z6_8ndqz?D+fzKO-pAzv!u4Eel^i%j5pb68J#IVXJjk!5^H-mX-1IM4zPbbQW$)7@6 zG%vSTBoZsutl9qi?Q7O7Uw+Ox%ePIRKK%=K++p|ioz|E4-tKztxrg2JnURtV(QyAt zx@d@^m=?v=vs)xds&{`H4Dt>FVevjJ-QOoL^K)!9f^Bav#hYUecnC{ozjhSzo}y<u zW=7s8Ufn3dGLY_S{$WdZ_w*NLbk+6uublA-@2$mEBExcKg4B9$XM<8dX+v`D+N71X ztn?W!L3Fu{-;f;VN^IRyY|&J7_vAxaXW{&QfmZX4(3{>Gj{uLe!u?p1Lwa}sKyOF$ zd&BcC9<!PY{{L1p>1j?d;Uy3MX-3t58&)~X%FCCnT6OlH&e^bG)vEK(TXo*FY11Ot z%xG`7#*MSU`{nkxoZ}BFO4=wF;gY(G3YJuoR?nR2%D$u|rThApg(Q$0`89Apl8N0C zjvQs`M3u@q<5*w8nXONuH~-Sq4b9qTsETGRbhgF6>ul+{@=9ydro4UFw)@?a<YDh^ z`cslFD3UD5nk>o<J()~T?PSC1I9n9Y&bS-ZRL60A$@{P?V<(nyjkpZhXgu#k7y5ld zf56;Z_@(=<x;w0Qd;d74nfdhR&GwX98vhY+=l8!i@4nlc(9BPGZ$Etg`8fIe-OoMu zxFybRk!88j`>}*Mt?2&^798!H$ol#HQk5-tbPmw19wA2SkCl=SV@GwW6=^;NyzSfH zc6xi4^d9uy#@YRr<)xtR_uk^C(Z4>j&f}YI_ori2RYyH_e2M!rK>h+N!vU%4o(|@R zwue3zx+rv6XeW$3gf__xPCWxP8DO3S_DQs{H4x!xSO;Lmu8sYWj|XSz{j2Pd9l13e zHlvaHjf$)Ln3}0cV$_VOikyz<wqU7-KD<`ujYznrDQX(kk)&?OmMV#&k*>7OaO4{I z!*GQDP!f#tO2_?h<!akbrCL+7yti{E^v`UMMPr;`RVVCnq0X`DxGKx!RhJQ!blYOf z;oVnMlfBf$6|uNc7M2vQ&W=Q5G2V<*A0~9-!=)?K&2@%hOwcsVqYRYK0@B31(DKlR z(ALm72<PDDE!iCuGNrB97etB9P99?)Ng#aV>MNVX|4v0^MLQ};nM`|oQ`7kI_T<TJ zlGN7Lrr9>9*3`+Ipqo=tsnnf@;3cvbHMPy~(vBLUuC^M22>z#(TQ1cllg){K?=3Mc zno@;nrfs@AyStye+L_rHH!CBSrdzsJJLpPs+dhv=+fG8PNTw>>|JiY|Jf2E(Nz-=3 zbUd+SNL7d0D=I1$0t(e!dE!+Lej=cUH39B|ytUw?G%_d^$qd~XA4sT^R_t+r!<P0Q z^4`8Yxn8X6cu;Jfz_%`x8m0(S=Jhm*josVqd+Z<8|F+h-2)v${<?Xu-?oUNDrpBVG z!bR1HBgdjzBoc|Lv53@?O0}fsS=PL?R4Y^qXrBTa`Q9}Fc?ja<kT&xSalhv7X?y<( z+CE4~R9|oT71D6ug#HMHhrkUDh(9fOHPRhddwI>p<dKh%s~%;}2`xcc!B2UrVV#Xn zDccxW9)IhtR&Vd3-UHs-ZCke*>2ynamiJag{*tnOZ2hqDw>8$K;B}<CRuF^=_ouqc z`(LHIN7mr~RW~FO4ar%$J}W8JNHt=p48*FQ2>k+`>Kzn9O)?Q*($+oJOFb=f36Wp8 zW{p!mO_<y_(Q@}Wvx$#K_*BJ~Us&O4m9w0=_L4}lyrDX78T~6_H5DEF7on{j=vBZU zs-MWz%wpX*`BakOOF7eZPklZ;kvM(Ln#%DFT-BU8mXcH&I42y5S1nnxapS^;=Z?&n zG2=edw2el)$+44B+cwG^%}it>vSjnqY|C~(YcS15%c6Ya3y%Vdc#Mu9D}YQadsT2c zaL^4ENgs=-IT1!zCWVYaHI3=&_0EP3Tb<kOE$f{xe$kmUY3}4JytiAQ<Ya@7&Yv<R zSwE3$-5KX%vR)pu%EC&^nGedcDK|Mzlbo49&fSwUilQ_bx+aQ}YG`GNq{K^lqB1H7 zYP5~AZafZV`~<kC7l0Ig%H@V~T>aF+k=5vO#uXCRbCLDmud>o%%@7ji`bc!U6t$w# zQ<7{ipEX&Y(5y%aSwBPIGKpj?9Y?1Y=yM3F)fb+`83_sK-g8;d!civl7!!INpYuVD ztOBT~-ng5{x9PWin%ToM82SzY{WY`gZ<x^E64@3#DD=oY!fg9{BDbRt{R5GY(}Vso z&;!}_S$f8eAZKLZPt3N@VIK{041Z?M_<1JI{z6or^r0^VW(=W!WsdA`%%}Z5fSnhK z8S}sv>8<8V0QxeshgXP-RsPdnWsdhXCiHdYc;7(K7h&cL1bvg)_AMsX-wt5?osXc0 zcbU-lm`^*wguc)0;Uu%|2TV-<gW1DBnK=6w6YKwGKJ7oue*eqt;eX7wAF`mu5bJ5h zGS=LRVP@M16B=cWtQcdCfn)Z-(>N;%ft80)k$?t!keE-CnQavsT2uqFkL*Fi)d&gB zD(cLB4JOoNLM<lLW<njpChJ4v%(e*@XBCqy8C6U%dq^|!P)<XO6)fH?R<c&8SViF1 z!{omJ6vmsq#2i@-a}2f2wskc97V85eBP4CHfjQ&Gz%ByYHZh?Y=E#}@cxXAb<SMqZ zWOcEP$wT8Xl#r>#cIGU`Gkci8Y&$WqLLI~k1=~(yQr~1ei+>Tb=w$SeDT2tTVmGt* zDNJao4(Ur2w3pd-DsD^8dm6KCAG6=-0c`XKutD}ag9)9<gbpw<H;brR?n7rYdzizV z#axX0lNk4z;ym!#eEiw_#JVhCj$|Qf>*?uFyYpTIpo^JnxCDH*l<udv>?7#rG$#Kn zXUeA)c+_wORuZxy*zf5~o>&!F!_^<LhHIGpu4S&vIwt1UGgg2rZeX_Ei1i{8dIob} z*~A?0=D^&}1S@jZN8o-7b7i+Od*8-{ZfDN$Y$mUrgJ(#N;any@&%^zmAo@L@Io^*k zCFKRU?fXRA3z_)*I1@V;F=u=+vxiHVZ7;=RI7y7*GNN*^-^1lhs@TEocaS-TolNXp z!Q_J>X1~KsJnUk&9l=lg2l2E~=G=BO@vsL&-y@)VnJd4KIk){xDRzK4iz}Hu9Au8{ z5Qd&0pjTn~JwZr3;QL$5GQW{yJ~NM@9}v(2bJRs<4~LmgyN1DErSV<Mm}jO4d{v9r z0k2~vq`S|!D`W$ECsCoyH|}~4dOVf?_=X7Y=!Tu<g`{Ozm3FPZ!rs2Y)LK*0%*5P? zWoU+Vmt*S*wZhO;Gp$zG<(4(+VnI_|YR1WS#d=3EO<Q%J4?O{ng`7|$xb+_Ud@umA z`V|iCBQL)_OHp^jXCi{58hSd$Cw0R}+qGKD6yf}hRdbXYTQ@XQ*Mxa}E33**UtJcS z(xFc1iqB9ME2pomJ?4#Bb#zhCEcYKrH=X%yvNh0T8kQnzf^3>ota>XJv&yXsyV|s^ zMvJdN9x}k@RRmt4#p{6u2;MF~8Co1V4f*kPlBK&ye~nJ$!G-*{p!*gKg28UB{><Ia z>Nlu~(<=olDx`J8so?mui|v$MrKRl3S+h8~QVBZ|NoY+g^^4_Mvt}jYDW%HAilJ+k zH2356kJuH7`i7XhFoqOYMM2RdOEzRvGTQ8Mv8Y_m)ro?rPAZ#FWv1%O>^4I&HC<I@ zNj2?@+uBOepX97Rg}sG*Xr>4}Vv9EdI;)3XM<F$2hT<i^Ph{c)ex9Dq_M&8rKi9dz znJISN;J%K<4E3S7^DATXG*`2Vpqt4DKo2N4AK6Qf?<@YBZPC~o=b$q)7Tw%>(0x5% zTl&{b^J|8=ZNkOlQPvCKrLiAmsxCq=#%31^a(xwnZ{yxp?Ai3T$6Hr`=#}DU=}e2o zn~1iapB%_0RRkV#MOYIiUaHXK<>7OoFh5a!DbvbTz`9=iB6`|eu-}6qBB*#Xx?M&- zH$~vJb>(kS+t;CQR1s7tDSjE%k3q3X#jlidy@Bi`AX*D~>H(j7=v9MjtB&!8io;tR z92j7ot}N|~MVv@<`$}oY%!)R-tG2bKM;TW>qv;y=73ueU3Hvt~t0gfi@T(2mksYh9 z-Zu64T4R!NQB{@Q*obBW^Ui^@Me$4c1|8OkY6j4+f|x@M-5v_AtTIBCq54ouXaew$ zO~Trtn0$C*sN_X;l5m?j&*8THV0v`CH{90qoC_{+&U;8qH}ds2R8|TV<s(gvd_!YL zq&CB~9E)lzSBkCrME!~tE3C@Ot%k~5F*zogax58BOocOai8pyvXAG_bz<BXiJRjio zv1e&%KBz6Yr5*x41;wvm8ha~rzuN=wo-2MGwSA3T$wM-Zf&t!h2SMaj@f)ZIl;5NX zeDy}!f&YO6v+BG5^EeOM*-Q5arQ)kT0-0RN=GF6ED%kezu2|C{_a!({eu_QAN(tHw z_jNV=)lS1-k9oAPS{!Fg)Ec8A|1m}RnA8!U<}4w9K{x<;P~Z$u<s_}7BNjo%gyL<u zMiMyZBaD9w<Mv%2Unoa_QHt#cQT?d*;<xc<ANbEKeg{V;!I1!e%Hr*Kjevh5YI_Hg z_3$R6)uqZ%51_!()dU9v9q}zTs0dyP!SDq7sIx{8;{w;eKp0n1k(RsbYdh7Bng&&! zIzMe|(rlxqPP)T$Vlp^Y?dWLms&DIYN3&(4GGliv>YJccjH_L>wl1Eo!e>`++#n;{ z-mP^0*egKwwBq-X#(;9h3<DpE;+;6+3wW^<fv4W^L^`s$co%4UH&GwSg94wn;yrY2 zL<IdIrdbmDBjT*!jrYd@`aPo3)N$PQUS_{Pq5bNLKP5(n^Gz2)zLes9Kmw{CzVG7U zUVJkd>LKn8OFz%WUyM7AjlJOSy?5I7op*l8d!bzq<bB%>{2q%x$2m4g=r3@71dtVN zH;6MU-cLZitW;2Udw_s?F}Gg?&|ebJN8C9)2r?raq<bj-YD`;?N5F2jyNzy(#_({U zheyWr@HB4wC_OT7q%P-x8@%G<jL*2@6Da2JO_b{t_H!iA_DQcFkV}M~k@wkA);#xJ zO+b}W+aV8{*>{+UnPX$19%ewM{^C;v)T6McSv`!d1ThR?J%_SHzKh4*Z#)C~`E}r# zzX8zS63{0w4t^JyC&-dt{C%K@KLkbsY5k7??;w+R@pz!0KM_zFjL*~Yp94@YU%P~& zF^^JSgyhXTign=|JaN^-&g+d6g7eH9_^}*xfwgVh<-8RMpR+!^Q5e@Ka}gtIPwF<t zg~v}$7|xQ~Yp=D&kMAFUf%jHpJ`uNSYbSxfM+HsPA}S{;o|8i~94S+Ilj9^VtVWbY zQ@fRMJ?rPs$Vie@=ea{<3?q|CcrP*|N%48GdJy-2p|h2YQ~`Xx06zOofI|K{h8B+F zmHiu#AZ@N(c{=nUDM5U{my+kf)6N0MIRIV{{xOmG<Mh_EThDGm{_R9o=i=W9pHmlF ze37W1W&`c=7cTVgr98`_SSe#)NDC!G<)La&IThY7qj<^YBx68_xX8Kpe&Z*p^SHCE zD{cEq@H#HacG_;Y)ibWvw5#il$!50$MuXx2_ALNod=Wg?0zRqaZM{o9NNa=y0CY+3 zcoHWbJQ9zbxh*=s=}!&QqMNtQgsv<X9ZlG&qHPyb_6p0YGdrzryW}+rcUORi-T%cg z0U%2O!UN<+4%9^Qa*u%s@8U~H-+CQ!&C7suYq2*f$PEhn9r-T-Jz9buEa0^OzA+>J zBW4dX#6F24`MiiRpgTGIm;(rO0P*q{@Kd~G2IMOIS!!qvuU%IbUgTWn^o7fo%c?0$ zgL=5Rz3DRWdeY??Np-jV!;<?~lNL`)YIe_p{z$VdN6M@fR*(C~r9G6z*E>DCROnFw zj4(u*1j$P3oqqZao*2s&j?-zU(njT{Q--6Zc(t+P9DAQ#EnV2L54?`fo+j5jda^uO zC03-%^`v=F6fYH=#ALJ6>@*;*UV?G@5QDqEg7Nw`&|?9#_zI58fGhJVaeA>z(HdyI z#^d;Z0=n;X97*%{(8I1w(?S-a{S1hzECn}uXK8P;EDq>P+p2t@=MX>VHs^B3xg5L> z)z9lvY9`m8HK(Jhs;Z$VNyR3s$L_Jfh*4gtgLzB|Q4p!``H3~5%tU|=cx;a73`8t| zp8)Eg6DD+XTRz4gxHcBcIfG6-E!C$w=Lnts+-&~b&Oz{c!ia=*TeXGQK0&z9)@-N3 z{Y{IQkpp^%`^UqG1hi4#Cp3*LIDyK3&G<+}`baOh=_UtyJk56QKik>dr<Qk#<1cAx z6f>DeE?c3E*T-w~ciD>;NqWk%HAl0YgaTLcU6@k~uJ0%p@}Uo4XcBYNTbRc(gJ6H( z(}+KN-RHkurMRGy{`w+ONzW;H5P8|B;aVUG33T+)YC@VSrAnSfc+!3yKkWmb{)WyV z;*GFu@ha&7Z`GH)9<YSXfG8CZK_3T)Wpa;f&U7c42q%#}*;&~WnYmQ!=~4Ko9ZSrg zD=O)0uCdPpuNlt0Pxk5c9ZLHJnI@sJ=~!Hp4ONJRBVk)eNs*XZvw4oxC^ty`TkVLV zNhYtvBwOYHSAbjzgj{X~QMLaMvY8y<s1sg)MtFY13z?bWGq=v(0biC`-KI2cZEBL6 zGDj^-AGWMv-I}Fo)q1-&PHWH%$rLnRwGH0i$9`2>yP>5xw*~N^FM=Gi#Ww@;0JPoz zE+IP}#;df9t|nZBtN#W%>7i`z#kYxU?@lR$`>0G&%ByJg!8#Y;A@*H729$B$DP<!> zl)Ql07cl)4-^KFl144cs!fio*>Ee6D7`(Z?3TzwG2&h%c#D{vg4rAvHpyl2|_3#!t z4?xL!f<FJiy4J<_aS!kMd^B`7!AG9u;d-K9vy}IH2;_<?zKv(`Hi4ZS5!vx*33@=l zJ;0}dwJ4s%r$dlCw)g>n{sW!CKpkY1m0~*7Uq~Ai_YtBL#66R8{S29J7h{Qt)O&7p z)AmSoZ;p$M*caJWQfp22Efo6a#@6)3cpWMp#}!@Cc}}x5Q{XKjaw*TR*JLf8wscdo zMDbd+O>I?6GlJUR+e8gWrxd{gVpsfiK~>&{eipzg@TY}6?E5-u`x;62$e!brvVKA8 zLb=BspyRl>9^E`<wT_nhMLEqKkoEaE?qMr_8ps@uXn85NO2O57naG_DJ)j>cK@Zt@ z3@82Z7XOK$@1R-yi=t&}Hy^H`ZF&%TU<n=d2=hA^UuN|%Qbu6im)-xw`9V(rtq#uk zVir&DdW|)P{9`O=@!xb0UcEm8>m|(+=C9p{pl_l51Ljl>6SBhRy%Wf;g7QKZ{{#B{ zFC8<q>s0~|Ucc{nx(DK?{}FaWpUXbPI6LXjVstOD-{DNzXcjOljJw8%!TIBG89{v* zzlXzkWFQMOT1^8(L8fdkM>er;uaILHJ`dG`M3_9_W#G;n26YJzM_KEHY79E1EdFRs zZzU|>M@qdPjscw<+T@SnlkF^Q&n&qQ`@i7mLS%x2KRCMtIL~^?MUva%k?19Bmn}Q5 zJH}5~edd|=S!b;pALF~uUAlC2Z>+7kd1{l@JUJR$z{QTm1g=-MWK)t&!>XvT3|E;q zT|lqc0Zybl1yz#$=oc>^Koib4F&)Ia20WeFaj#x<3`Z)EJ%ly;0(;Y@OY9$5Yp2~Z zr+zN4Yxc0MX!4xu{_3+T9J6&8yhhV;Ig#2a>2-X?Q9&15Q^}S}BcoW6=w?CK9E+Jw z{X{*Tm?&qIjJ!isG)<DcBpW<c+3YX}))8drJS^Z9d*9!a@}I{(nt)pl1E0LZ60s+_ z>v$OM&94%BhsST*h~3A;J1eMIa99ETsMsbB&WRv{ZsxE?eeV^LPlvN~ro>^8HR`aA zZ%GJ#8s3XJ9h?9m^sqtm$mlPqvA>Eux?m3@M6PR>iVvHh2Mbd%$aOw4iQ@E<UICwG z6HweQ%KK}VFa@=k!wz8w_i!C2@L+)`49t;-6L`EQ{TUxl2IMO|AD@QDK+NrMie9b# zodK+aENr7sP-A$Tl&^<=K|JkoEN#+s&aeHoU`@+G_Sjm`qJnj{KU|4r48YW0P#@@U z1kV$+9e#ltB_%(HUm?yYSmqq|^WK9TP-y3TgOE>H`^op>6?mJVm}=I_j=n~$R%r|< z%kbeE{2BR;cQC#{Hs!;$L^fr!l+7Da$j9(AiS-@*8!-|*zJnc@`iZ9vAHidI6JP_* zrH(bS-4WtxPhkywIf0|6O8DHno@k4yY4ihp*8se~4%e4fFQlN{s!xoGAo6kq%nvOd zd%_L=4sNlUeY+SDWex)5JsSZ!4Ark$V^0LH)oa(H|7~!^;v}!m{n}NF+}FC>ZCO?_ ztLA#IC(fFqxH3|ii~g;O@f@#+lBpP~p_t+#NiZu6MX6HNN(Eu#AHMAgWq78kpj21V zDP_EeZTD^@PQ=G?4-&y~zT9XavR`<4J~x!4R7eB)!ru!$$-t)<)wU$GIkfHn0jH<J zrgsVJ>f~;VcnPt*7qv|#Ch%Mr64mS1TV3F_;fyn^9`K4sBOBK*bzhsl;|P*mtC^9G za75^fc-MyE#CMEDbqhab+@v{jS0>q8Zf<a%TrgRvaQ}3of8!qhRrik)Z5KErk&1EA zXq6a?CPdNw+oWrX5Di;VNsd|3m=KQfJdQ=j+Rfoc9HIW6e;Pa7gjefbUz0zap?U3a zb3hWlL##^+k#qiOw{0s}!)g$L3@Zja73z0&mwBN@p=F_!p*5im0C7N$zwUZ?5t|o; zE-u}0!*l%D6Mat!_J1gQ4*;u*t8x78d++vMUfbSxX$#8&3%js10R^N=v4bF>u^V03 zbysl#g}mMOHqBI%7*kA4kEVQS8oN=!<onXQ(Wo@L(Io!vJu`Ri%;lPY{!dxhbLX8q zbIzGFXJ$^B)ddMZ!%b4S<EQ@!kyKISZ|~VGKlRs*c5>6X$t8uRWZT4Ki*co1m7LU3 zabbo38_y+Yc5}85Nw(!rt2l4V;z9Irr%%6{{eS-S!shAIpH7Opuv8N@;S60rL(oL; zUrQ=9A!Sso@P5;l3VOTXZNo%M6iuG*6$GJx|Kxe8LPYd@mRW@+k~`ZIz8)SJgVh3R zK@=xb>y~e2OaW*IWaN`kejI#C$_u$LRF5Rrnl+PbHvNcB?;jKIo!I0o)5WYR&R6Y> zlXf#A*RoVw)_C5fl~sC6eeDMxva1ZmPPUqSu5y>5rZXHTZ0c(@Cv-ciWSW{C<l#hX zH0;rf(_klT!v5}Oi3y3G#Hz%)z)vU>?bl4~14JkNI;FTO$p{ieL!;?C@vdy`a!Io! zZnmeRl$53kTwAZ!)v)RuMY9aG+CB6=-4J9>7nD!i)4aJ<FbrN;B#LU@^*DBc-P7|k zTlbopvMlFSIc;-drrNW0O<NEYNtTrh&r#K+lav>4xn@o}rR$a=@I0q#jv)$@Ehjhw z0&P|7B;&6D?N72KLhQW2R-1(rb^o6$UG>n~^p<lgSE$SC^-bzo>gMy)71MOvYJQ5Z zaq99;Zzh}Xo8II!bUL~Ef~~cX*i}CdG2|RAPA65x;2fq17R>bx<ctaYeu^`oHUpBV zne4rD5vp|z`~ySrDK&h9AIedgJxSZa<&m}kEq2F3XS4O?F@}M-J{-J*<XSx*wjDYg z*A{0XSAsPhzikfqE+{ZB9>6)-Vh&z>{owrOIwyO`z1}q~qqBAO-0QD@z-g;IU^`dX zy4iZ#9jn4@tM?~cZ~hSA?;)pukhQni3(&cVP#zu#paahke}vZ(KlY&DVSmFr7>etF zAn3reB<mvV0sLDc4{smF>sKPXFTm^9Lj?>kA^QwrD9)#1KfJcXutWBHO|pFYH5t(; z7LcAD0~-u5jNC-B>z)Y5hO3)Ogw6}7I}Ir~8!axR-X;Y5=HeoF+hQsk@RI@FLtm!O zwf(k`m9)5oU^q@;SV}OUb1JxJFZNQ|fS)3~SVpoUgLPOu9ia25{(55@lBxcRK|M1> zhasMD2=?cgL+?;=I1dN%uzwFF4-XQ~ze@0;o+0{<Q*95E{+>a6jNx3exE!F1a9g}P zz?{Dy_W@TzMZ7rp8u2-K6HY-OYN5E2iZ1Xm^a1otN>WK5`Y$7L1{t5PeVd{0OP)*; z=_{_H@ZJ}22-gXfgFAfOb~WV%Oz6<RJ|a<&mAtr?(Cp=~?Qk>Y4Ij$GI%;N-w#D^C z9^lRf^<l6;%^}jWL5s{GL<fZ7EFwE^gn03}I=O)v{wv(WPo{cJGF{_wZ=k45s>c?? zI2_dLjg({xus`>E0`&m*+)Giz(;b5%BgFwdf&U|)p~fBdVKeE&35wHO@!Nc!K1}F& zHo@>Rh2b3PZ4VL+crHr~Ja5m#7*3!a0LE}Wp(n-D;stCTYmE0o!s!=7c^%ovYLxyl zYIX?0od%Y{&yco|uMdxH3!x+>gM%FjW(7wTSuuyCAm=se+2CSI`;f8WY*}(}bAU&@ zmCWW7q-U)~I0Nc`4L`#bE>Zsm=M(HlVfG^VoJ7gJUmfRtj8?!|g77<osFi1FtvhrE zZu=}F72C-?eK}mIMotpEFHj>~Lq-S{Sg{0sHxb%?q%E$QDUjU*^kL-RRQv?#+5Q{J zX&U0l#gr}%Z7S5?9aIgmaFy6ecuLLFp_P<g@$=NV)LJJ2bsh?MIuuCeNjx?rnY&0I z;GSyloX9#ut@%TnsNDHalAc{c)^WIXKqJPt4rng^j9^$5t2-{Gv@U5|d=C{H;<vpF zs-U3r!^?@(zDdo~D=5l&JsI&Mr&{-}gJ-8v>%S+v!*GXLTtVhAEiqTdY09B(6t|9$ z5iQ5rQ(>l%yD<NJ<CIM3*qV=Ch>@TNHbFYLZ~Kr!i?hvXZl2VYt(Q%Gn|g(Nfn!)| zt5vHRYKuF&vt{-+_*|hYXUKZyf(w4Cc^`YJZAmUK3VN?7wko3Gc)#$bZrMvU|8`8B zA!(|-$Uap92XCPwx}GAd>s4fK9EElNYD!Ynpz<>Ew<}%)&#tAsQ~fjBX%x++;Qj$= zbX=)ZU~fB$n<yL6lf!)tl#M75-Hjx!Hxai(>80kQ&&&718Cgr5ejA=oNgSEcHxE&G zi7kh#rpiH0AuKu9#aV-c*HO_v1UkZ#won6ZUt2`q(Yodu-1cv@_Ag#fX6YN$3e-=n zR=$=-yx2|X0CRT`eAA2XrF8BQ(%&+{OY5c3?t6*a2MiGC$xxRM-Ogqg#kyvYXhFzj zi)ZZ(v8(G4)ratH!;~f_ZyR1ht&L9xqu4#0ibD(6CCFyI_bU{qA0YG$b_37R>)X%> zHEtizUPeRW`#s#ho2j}Ihl#Z+QJf}J-nTPit&T7f{}L@Ldq*f+{wcCb-$AWxA)odU z3*=--`+a3HikB%_*-wovTwM=PZ+j#dMe!CQL9bA@#;ugC;py&u<IEh#z6*E-x|@vn zWJrhNL5e!WMz~2KeRwsrONxi6w>=(crrl6i1mbm$<J`c$7u`I#NhCYra2Ff|okcds zZSmmBC--vV&~28hPb|#px$3IUOXf)P+=&j)>v^@Nb>hU^JiuIs0z7Ps;+$qxvdltv zrrUPTRMieqFtXK)YS`b<2#+x|`Zgu^zAV3w(PA&ql-oTJ(QQbsK0xi-hzt%sL}nS9 z>HfuW>mbCf><jj=$7y{!Fgeb?DUOo1uZ3-Q4-z|%ZaWr{a0D$;_0gWfJ>iRGN@E<x zoDFVO#tEKd6rT4}E5;MSE@JTagnlnkbK(P}ErNa!bODknI(GOlS?xYdMIRptun(`M z_Os!9xh>8<9A3-r;D^B{r}z<SA9sYj?W3`KzK^k$<e+|PpwB-}@%~ZrjZaXKzJ4yN z9%?os>`#!kpCs$~iO`-Y-cI-nw`O=nI7XdOJQnEE!RO%{pQ2XzCxa2;yD1^KXG3@n z&ZeSa!}akwYLyS6uTxqmTrECLjoV+xUZHr1Mo4VX-Tz0;1h3cELuRkyXCiAfSOh~) zN32cMhgV~vuTg6$iA4hYlrP>vo}oIn%OWyHe*^LUvxE;PDVe&HdPgV`pCgq4!Pjg6 ztwo=YNH=Qx1*#`xP9D6I@b}e_Qp5kCDxe%r24neRtQ~k474=PK2ENTgZ}a8mOVIYq zk)1y3+1(IFDtg+&j~8AIcO|~H92EV;H&ZBkbeI{B&VEPP(|o)^orAREz6O`w+Kis5 zZ1+ChR(^`z(J^^yOG|Tedym`eOc1KFXGv<mbE%^nQcKo#3UZs>-FuZRo+(sZdg<jG zInfZ)nyFb@O-;)@%`#?s|1>S@eA^KnUXw&|F2{8Uys7DmCYf@^5fx>1hOBgt5sg}m z<<nQ#><7iKQquIb1bgey3(p`TtoRMez6ojjO=^ab`CI%Jr5A|SIe0cTNBx!e+mx)L znu0zCh|wzEOWE8+huky}H}8tyiM15In+SZJ{e1C;w?@xPtV`@k+?W_a9zS7K$lNRv z02;W_kWkh*uz-TF+i+|<u9Mm|3*AQiH*(_NpnXsgL{sszM(e7pJMuuST~lKy9@LgK zEvHnM>O6p}tBPVvy5`7vOW}D@R2(s-N#2)4QI|xie;v=++<Ut#n`O6hy&zxbT<#dA z)RI%(YGp!Y@1iZTG)pmkCq{|aRPQUAAgHn`sg7gus$wcqTdV2e&s!cKt*MqKPnhCg z-DGr?=XgQUxfGYud7euv-mlZWL36e(If5ba+}t!bMc_<Dl_b$n3{#M#<ypeHN66g% z9>t?43H1Baj1SLM|A(zPTKoYc5y6^;F#M2O4MGe*qE=HM!<VTllR{A47-RS`@h*KO zai6Cr{M?K6L6yV|d!0td1Gn6Jul<{gR992dx~^`&qq)+mY`V~{uC<!(bEY_#=}Lv0 zlrAYWx0{oiRb^(K(UPc0%=Wa<k321u#}%vm+i`s3O(bR6B#yVGberwe<#Z?G7INyG z=2hR+6ka!-`n+R1uCa4RUbSl%kqY4c%>%@{6@Nn3F{r9jybpB2pIM*ZB6uT>48*p5 zk&UI?QwF^EQT1zm3=q3l{3*3+5)8L~m(7xepf~-3#XIm13a=F8OGj;s4^SsUJ``dW z_k4t4fSg=Kh*|7!jqAgn+v1=%|CY`5g`m_O!}0KK#fJ%om&3OWiji{})b^1`TfjTq zPM|M9ZENsfD?UW_rF7dCYRBZ?z@YPv2U)A`;J+v+p(Mg^?b~c#J4~JRadg1<5fLc9 zyNEys8`-z@pT+Pkke!EuXp960o)3PUk?$`O#y|w;Q)sPiLhEfNcAilo1{3Wbceb-) zvGWuAw3T<?UHHSriY1FFS&??k(=wB!mfeljMpga8+1lD{oA-ZPwswJS+mlr}Wu?Rk zf}S-UHDhMXta+-e7awKsI8mg)$UQ{*D0vvv<EUPIj5>J?<>7JaoPt2HFT4~)HWb0@ zZEzy-7C8Yr402Z$pJc0nVhm%fJm7h8Kf8OyoWBEClmm+_F)cAOu{5y~`~`6BH2>1S zD^3FiE;uNQ3vgmq_kYxe^W0Q=M#0?GV!9Q{B}&GvmGjPEu3B8_Os+6ARnt>RT~#$h zQ0w=IvLSx$p>qR1ZZ0=go0at&fSZTYf?#tUT2l|lS$Q|3xU#7WhUhqRD<s9xq-09g z3{&CsY=xy6##Po-#OcYRnYD7J4*Ujc{0-9{s4?<<+`R4oE}4rI<%&;5_=KQ`sohw} z=_3)^gH#;4pE~Cb+dfU?iiZB2x@8S}_7cnK!99_g|4Jx9yR)%6=@(QTCEte#qKAwB zM|=p7jrU8~TS2Va;34X)^hn^VP4pE*jYIi3Y7CCW^<<<vuI=vgV(IxS^0wpD2v3jG zZTq&wQF%b3?%D|S##du?{IBEY)4ny7H!|tNKrU`<*w;Md2=we=nvG$?Z9fq=r}y^9 zYLG|{Vl0EdC1-|IAFv0q4e@6_Pk#q?J4AV3e|{{L|G@SdpQHVZI-d)%?~dtTYw?e; z(*GmEEr_5VsH3o{gfd9}{v6Sw4^cbcFn?c9q(2lV@jg4khuw76XMbPw7s|Jk9ewM5 zxQp!nV(hH>D|Mzycz=TuH}7r`BC9??i_b(f0)qZ6V!I&dvxJ|NL=>MR@(0p$>mWe? z4&G0-9)@QUPvaO?#@8!S(gI=wygkV?x@Ndsr6#U4-I_W{u?nWm@$FNDj5*icAZCQS zKc{QSOi~%`ZA>b*B{xr!y{~ZDrnz7LX)9mv@16_b=kz3<0Vb~ACDViH-9aLD?~ng` z5I6C^a@*A9%P;gcBYxdWeubu`(w@?`IDXpvbWQbA_nhU++dKFRX3v_neAbgTmv;K> zRjOLyRLI?x70Gm3c5|{UNhvp3vtg&*XQwKhmHB)gDjh=X6N#7T3F=1uSN)78DVX@B z6<c)8+W<MTxKh{BoMowYnw!?=^>Uee?h3cNdqwxn{*Onu+Ut=!TW?J=<!#flm7**w zDK}Mj&gJ%;OeWLo{qc7iHrz)%osbgMiRQ!#Y99b*4^?&-?JAM6lw;ftDPFUzwlCtu zjKXjE?QN!F*{0@Zn{sM4*Q!(&GP|Ak+uwQ6wp5eLD57|ts@B#EqLWb^zN3q`^lo<p z@237o5_v_nQ{K)}5Oqb=d4rc!U6iDX&d$Z=au_7Xb!F5fCkech=T#|X>Djg0bY2W< zwR-!Jgz8y;6BB18&c)S3gf<jS?w1*Zz!X2u9M>iDolsku@kWcgMx@%`Nc$9O;)k=` z)EP?QlU4HSc0Se9(pcXzKgG>Zvbrj}Mmk$BwHhX0m2<CfZgJM8liM{-kkYCkc4(TJ z;wDYyHF=V=Je^uHr?Oh+>!rg&Dyukxripe&kQL2wG*N8ORF2mrE-4DSoaQud8=h=$ z?-BSOMM;?zVzXv>du1_YDSF=;UYJ?IscFNXt-(#LUmX;CT2g08<TCcU4Z^NX(!`D( zXV)$?`s&=KIa+t)#vR`fy^h#C*WoN`aN6eY8Cu+CH!pDLY+-{f;6d{-QbCS_7N2MD z>xW@Q=)at*(C9(0LviX4QW<}q@OEe5H9quV7CQ7{%I{7IJV_9=_yWoc2z_{*)W^*U zbg7Bxz?l*g-c$_kq<<l8*uH&rF4xo0rOa-18+x>^hQ4*%x362bb?XX#vo_cJJZ^bf z!)$OG@@mFvTDY(wYg$#d;TX0DPFmZHP6NjZ08NSz*FD%mo#Xq^qtJKy#5sgM969p> z=)k|(ds`IeUpyMu_ST<7?o5tGeER^ywdmCLI2*N$sd|DyktYU<gK!B3v>QJjiF<~V z6O7>{mRlHuO!<615qP8xeV96B3F+`MZu=a9BD{FVO1wsIdNodB(A&U2D;4z2Tf6$8 z<~S3-8_gpJv)p$`&jpJOB{sNVq1U={b1LanBrn*`pTASwKgq3AT61Srwd!@5j`<un zW4^HN{aUtq)hfH8OY3OpTjQ;7r`s(JQd859B{41Vwq|QiR&kxi+Jf$89A2=s(+xgl z+Y9E@*|t`&tz?Cno-6CFB@^m~bgYk@dn1ayLiUxfgl+L&JiOyVZC|DMPUaZp7koU# zaBwfnAC$oW%bo(e7=mGVBIy~D>DQ>XY7psEd>x=~#B!~Nf)a_uo?THHd6T^D7$xbS zrtZ=LXloIj{Jce3PoWI|mc8vjcqs3uS3>B>%aL2Nqd|SZ7%IO_=y^1xQSqN~v$psz zihG9%r!OSbcsZm|@!xShE51Y8z7S%-{$7z8K0K4nwYC?|Fh>&v`cn9|(F)4m_Rsv@ zp)^Od51o{rBGlP8g?if&(z9#h^wjPa$~XN<BE>IJbRd#Bnxw2=!p+eX+g}9T*AmC$ z(KM@(FxB^9k0;on<7|X}7SEZC<rGvA4E}zXb=F^Ej2)>|hD%-im&&{Ewr{z`x#%Lh zuWygkK5fU!#twN-o7>c*bvCcLcnyF4Pq{QF2$sCr=uw(AdA5;C>XsoodiB&vdEJss zOH10sr;>~WdlyN8PT2Ezic4}Jm!lk|og=)%`$q}Rgb3XRzep%_ETqtY6eq)@e8e{d zQT|NoPAF_E#PwlRByT$r%J8T}@V-g$S!Ulhs!$^iW#SKvv_8kYO{L_L$lBn;aWXvk z<5*eKNEGc$iC=hqfcV}~BTmcg4t@7vCJw{B?x;zfbcA@VI7$voii3{Yk<)Ahbt2~p z2<o!FSHrsinqh4=+%`+y<NNf@0W=@m-vWD+Jz5FSDk@4O<YqOSrEwH$YTWWf?AU54 ztL13|t&8ky5wxB<;|?)2#EtDxPb@bZ<Ju0s!j28MZDQ>y3~i2W+rm<Ex37a+N5TJZ ze}Xy<48PGDi@lA_g^4hXwv%4dvtt6m`({YFJ$~G^f>-UQaC{~5=Um`fM;pAI)7D5` zGir<478pfwD(;lbLMZ=G8%fDWAF$sz$(cO4dvEt7yHJ>1xJowN=H{HGYKHA?APZJg zdlNrt(Pfu8OX1Tch^pf1xq^|oL3avjZf2n%<nupO)k&(iJ2o^;%UkIr+$5T++}M&; zb)#UJNqgOei?ufIzxw&SsOY-Zlb+D7)U{<6Du!YSs-Rk$$eg?&+D(k5{v=8|2t`Nw zsQC~|=;SyJFghhxZaZSzP9@QUaLRSVQh-jw(e+0?sQ0!}@BkfdC2ipx%KzPKI~})u z4z<P5E-F)92%Uj5KmQ$_!j8@a=q%j!C3Ffm&<)V;SPZjCW|k8ahB+k9^vhJ+9&$=Y zzpWSd;RHIv!qB-?_SO)?JPdt-!O%x?570fE9}8VTMtqXOun<%77}A=faIZhQn94d6 zVmOV&G1GlmLh=B=O0``|a`GOh@Gc|y1Ze2#gk}gY<iQ^WFYM8oRBm7Y8TgQmLdNFN zMYxy884jFDMWKf8SVd*;_MxjO>?kX0(D&9G!TV)&4dn$LVqZ)8gLt-%!lMQD-spOO zo)rt-z@CWW{%xePQ-p0dk$lHAy*9_v_Uu^bIppl~D6H3zwS4qE!ZXBm$YC^k0g3yE zoyaIuDH+{DWx)2^Zl!2%zVj^R3wV!>LWIcZHj+~V_2dG8ZjT+|#q6xdz1~46_Ywu& zNn(gkP<VF{KD|!0y(AXzrLi1&5618u!;#CVSrojjb@Xz0b_Hcchu^r8%B&UA<SKY} zHF*c!%WFus2bw$AQdu{`w(m^@G1sqAZLh<<WNCdp9_LXkrKs=ya7S}5e)cTx`!;xn zD6u=1M|((?{MV^>43J*ZBO1gs@b3k~Ufw{)`369T;GM(p>_#f<LimlFNKT|zDd=8; z=NLc{hMS38yhTArsQcv*x)07sw0B;Hto0Jq5{{e>qpa&FIeq>@Ud&3|c}G5-GYTu8 z9jV%$SF>vFj*Km23XZ@no$WXa=6Cjrb2~%H^5+iZ@*X{qV4=5wRr?o0Ww47!Z-ur8 z!AC|#HCDWyp=_o&gDj+0!x@z5BU>DG?x#ya*2qml`odpakmi;-lDw#0adb6p81mh7 z1=-Q$ZgXhYE_cC#rxn$4Bypl@sLsW@9~Uogbu3-9Gj`uXy9V{{7_wH;$=m3yR2^c{ z=Yb&i)yw{AWD-Xcjvk5|A3l%MAl4+r@ZCfV-G-)6t7wQ}2)xZu*8Ri4xoO0f!*s&j zgH%#}X%a{r)ig6G<Iz1GWroCsJbIHen*{XNUOs(xD<{nR!(2{mJ}1SgbHvmdA-Dbq z8<Z;3Q2C^rwx+8!*8KVI!i6sUJglg;q1v{t*^=0&YuYWFHmQ8NLeRyWBrBUOt0Abo z`wGqf17D@;K=@WI_=ArYu~)})aC+yD4&~1J4<i#ud6JnyPUuK|2!B{@DbX7iFEpQ% zPOCj~axLF^SEp#zNKS>-R%_JjOO^S`RLF^ZSW+xmvu#zeM1GdVD-+i?q*JoV=QT-c zo31)yQ>QW2@cM~Qe4(E~w$=aKPb$|J-Mdzv4|_L9NU!EQKY#kpo$k(^%iUq`<9Epr zgD$CxGI@>eR8~6rRBM_Q?nT2nHyS6YqhsVe9%;Q2b&5s2yAX7=405KwbJDNx10(du z7u?Flj1n@a<mmKf!GU}9vg;;3ea>W#U;O93BscZkRJwypE#Xr0zP@Vn=1ZR0xoOiX zr?+=??;-!k&;7(TvSlfr;m*%cyie_!nx%X4W@&yw`N@W1Fm;{LNDn<qW*_7n#N!_) z_7B8=j6#md(GNt{Lp1&mQeJ2TFOL7wf)gp+_CwT)L7;;l#n2aV&rsVBLk3p`^$c`x zlPBYTzVls)%V;g!7V2Xv|D;dpw#e_OdUMzGFe!Qy@)w<jXfL3-AMDKF*)0FTfo6_3 zWnsd$YyE#n;)HGQlQ@^>T#m22BA4bbVt%`7v%{-gg_V?Zrf5}Im3mGRO?$?S_gb4h zhNPTI52`u3sU~O4_&(43)p#uQS4!1XjZ-Ac5(Sz1_vD`GqLAgPHBp&eU#}UWp;cP> z2|YcNCCSniskfnC)1~Uk`S5<<U&U^NmGdL;6Dr$`ehlZ5htrURoyaF9d3y1*#OaBZ zK-a5$%C<$tHU|?k_JKcPW60JPL@{D@8b|b?joqHMxa0&Ym8!Y2GMTa_*r{|~dUbo+ zPBT!UF1<f<e#X#Jc2+VgEK{#b_jsQ@?ge?yBe;>2GrDM2m<2r}iAn#__iawrOk1=p zU9FTXt%m-+QtMx}szDTORg$JwSBko}*6c9rSFLIi_-wjH73B$qf@1KhyugF|IX1B0 zgGaTtFh^nJ8rT~<e$a$|{ivJbSJi8t=1=Ro$k&^?S$&QNTh!)ire;<hNxQaFHq?}x z;)M6LyT+uxv|~G8{&Kr*Oh7Z^H9X@!4m|t>nJ>tihDsBox0AVrpio<A^wUI>(QQA2 zp)WDeJFwOH5`Nof0eUAD5$!`EZgBMT)cg*iUx<Z%F#^2{pkE@n`2jivIqyb47ikNA z!lR#zK<}oYp_PnA@s$W2P#?Y;!SFSJem&9_{OU))LF@@+4}X*DnG*QJj6y!&(QmOH zHA5Oh_26yaX2y05L+@ew@I2Fpdm~Wvw(msvhM?b#@EAeA7mMNhu^jrJ2o(IgNAF4m z_6RK{Ka9}qM@-wJ4Bj8dy=|y2mP0>bJ&Q0M?u)EBXcR%Mm6OcaeoFQ#H1q+&AzJ!^ zyY*+0><mqe<s0hRLu}?r41G8<3cx#5AB*9U*ctFB?%A_U+s7h!5!D}$p;_xFcr1-R z5up+K#*?uec?v^M;I@d$hht^%NQ~}i9eo;}{XBM@zliJzQ7^&EZ1n%w`Hs2sOUnKV zPe{H_S@dDsUq#;eYk>YH0(~0ZiAM0-2xU+&e;2`y@ccf~_dif_Ek$JYk5ru&ANr^N zAU%JM)xdvY^#({p>j2USe<eJkrRAB}neewbDI9$^BC*hRXh!6nP-}Da@3FmpK2~C1 zh-uq83SJzeN2!xN{~6?07(E`LHNt)(7W>H<>ETCTinM(h-if~PN-UmNV@LEFb*~b( zeLVtwgVAOz-Zx{V=^v4{kVkv;*AWecxc+ve?LVop{427)pxFksOGe*`>(5w%(3a9m zV-<1Z97{&}j-aVnyy>`cj&X64Hpa6U#sr3b$C<Wb?As(N#x;b>WTm5|eN2ht?3fxi zGsd)-8OD$4v2-vZx)MQ6_H9GM%-FC*k69rP$872>BkZ3;zVS*pGsfJQb*Xg>SwSzy zXsFgP$YMU0Bj<)MQ`qwCxW)>A=egLnm67vE1g#=>26Wr%cVBnLYT{PbvD(OJ5e@1h zbO)U~Rv+8HhFCdijL-zps|lVpM^+K^jg~k)I@TJCy)B}9Q2*K^V?odftaOh}q-K0{ zER$m8ZE{>6hN9=q2*Z?!)rc^3#ExQWgj=Y;(_&|CXWVKqHa)h#T@gAUXk<Ns)vI-E zW}F5cn?*rYb_E~nj<lT(ZI7|}3WjcFFktA|oY=SZ#6gFaQZuzTmVR>yt!WO-i_EP) z80Y-hl>&WZK`eA3<>5eP^$1id8(S0^0ce%6#ne0WK#s>wqv*qO3au#o*pj$acWh}y z#^D=7P}_EFS*-M)9ytd?{5m66vo2@toUs+mIv7-7`(NlK!oD)nO9VZW^aN3R6*F3P z7Oalt;u_Zax&A7O?`vb{*t*C{igXLyXN;Z2$}Ey{jBP_?r-<mYF(Tz?W^H2U(AZ{b zT!ijpXGeI8pyyC>pfK{okDZG#9A&6@UIfGWad?NGq{ebVEG;jL@Cc1%OT^ZD4)Sb$ z0-kLpYbj0Pi&!~;ihjX6wnZ#t1l>;FLBILp2yGGe9TDk8ZFf?Ytix3le0s(%iO2!^ z#--#Q>Gg12_#5vbUYhhbE~7^Kv`1&S@f*7$!qqDoUO&h5{i;}9adnK&ZXJWnA7j_X zj`qFeE{%p>7i-I1AE7OJXFvPSq0dr0+D&AS{>C2a-YtX<kXvM0%MZqBAG9|dyCHG| ziTXao%FNhs*dJ2w5n~&>F?=@ku?U?Jwwq!#+}?<WL!-T!)gVaY<7XogEspT)qw+L_ z@7y0ti35?{8NzT&>?(b0<ZVa}4#Lkv;9>JuGOpJNw$?GYB^oP6bTVzLjz;zgsBdEt z3l{aQMC9cpCFNyu4vBaGmE!Tp-_J_e*as-R|G~)Y_z?B%!?CmeHp)vk?A1qN?YobX zG1Id2v552`3?FCTcIaWMC!Zj_1Uy6kM?L!_8_$T}aeJ&ReJa*U{&b8jz>j?<7Q-E} zH2Ex5Q9B&bov~8>xftuVb?o!-><bY*NasO)?y<Xw7dtH@Uy5if)SoYt{llqpXvOyG zZpueK9PL;BgT?SwHZB+U=WDUpzfSst=I}S5Ki>>AF;t_66ZC|YXvC3eixL+lyp^Hb zZ3^lkV25RV)*l8#2oWbh;^s^$R+9YZky}2#36hQgo>{Xh{KO)v!_RNvQZ^^7bdt$c z?fyT-f+(rR@Gf`PuJu3MxU1%_yQ~8TzTw>KRDHoR4Ox`xYS*s4`1jk_tZ8meW|jK= zf;ipQ`o3AAO1hcjWK$4%MXpJ6X_FUtSyBW|Yv6gES5-b=uL*@Z+pcpo?<G8!^3(ep zhM)^cljDSRN=jA4Q1n}|>&~|+-}A8TJ+U^>y%Fyl#PRP$c5ev7cjL~J#=aNvMM8ML zPkKh{Cpv3MC@nvTvGw?|AF}r4*pI0Fb96WK<Ji^nCsc$&*!Di$_C;ov-XDwMr;(na z{yq?~`cT^k*;#_$_7H2ofaMa<=;8nH?2*_R^eFX>kgAWx_Wki#yX<EX4j||gu_JmC zd~I}G4>yyjN;HJNwvi-2;46!KZmjL@j`j6jYIl>{&~41DS^cf7WoDd_yy58i-J3Q! z-Ick91=n5I*X%UTIA5yEDusN$N~y{-mF&l$p6P)k8zVFd`CG;g6X@H}7HX1@9bxlS z+zi>^2mZ$TbR+1s3D%2m03xi%o+fQy3^5EP;_#0BoQ*v~(CdE7_7_2K_(Cj(Ur-iY z2>oB`EXe0ERLCCtB^yUJ_A4qIJi&nIaQ$lpdNPC#32|-5e$Dm_L5rtTv+T)a>wYB5 zzhSE|U<~1ip~l15@4^}n6rU*UW51`Oj6y!WLGdZ1#vkJ7i9K*4^rWJ}UI;lo+{EHV zeYok>IOw%+$8p5Z{+<wmIfJ97XD9lCdPy)J;C4CQ*PQ$TM-u-JS-|{TdE{;G2Vl3Z zcGp!^t(!NmE~_~iH(RUK=cdnHv*waZR&QIdV8J!AX!Ft*TU1PCuUjxPUvk|CG_BEY zm}-lLVVmlNIhA=WU$CcIrfpePlWDf8hG3`yZ>yp%HFP&>byFG!89xx8s~(;I$kG|h z!MOzb62(8bTfrVgk5E;Q=8-sZv;gC(IHU?-HV6NhMK9eHp<3JAU!FGSzMdsFw#{j6 zozv#F6g9cdtuZ7^lBTa~>{Pp(-G*8El*YB4g8Yc>ELh-ppN?w(Gt00W8!b!L6g#hG z?55tH2FKDXZB1ol4UJ%MQe-cVXz=HVv_f`-vA^QnS1&-swjW#70rdrmry*4OiHz-( zp`qYSo;W6WDzj-vHkrQU$Md=AAN^>nEa<l3Sp*!HnLJU+<m_y%T$`DiOY`&o_8I;| zDW}rRrmA#ZPJUGGILrzBl~+nTR&bKyy0Rh)yl&~5l+7BVCa5~kpJ$uRPRdS+YD2g- z_+xqoY%ZvAH++JPazi?0<X9}v=^B^5Rzj=P-`OZPgkfkdyEj14;SN?0V@_;}(-1?O zSidfm!Fud@N(&K>!?70_-SjN2n{a-05}S#7GI%C%6tAto(OEE)S&l;N$h*s`?|0){ zj??2fd$pTNZF^t^*Y~MU9S{pOj%Plm()lU2E#|Ve+n_YKot3GyE^tP^lIy+fnNJDj zv{T5}r0R3JocfU7d4%KB{r$q_8<IvUX-gu{a~dz{n&4zKN#`Zavj|1es?c}ZW_>1U zR)}gn9gT^(_F~+u9^4<N`^Jt^kyf70A44|4akg#_ZhIn@uD8VD9o!SQYT*3xN{}ZT zL;K_UJ9aX5-Fb<PKZV)aI@k`fb{Z8IO8Pe{uq*Z$+*|I0bGWfrC`mpXd}Hj@$T%T7 zc<e8cHzTS41{GHxzVpLz(6QGeD>P`Dq3^LVt_XVY6R~UP8<9RB=$mmfZ|om&+}eMT zy>s&81--VvVxePi!OTON@NFvJoc~U^EA9UsJo^{BFU50yHSq^RS_AG*$KHu>8IAry zf&p2>03CcfB2y^)a3)UgloFA)fT2{u=2I^v!OL<kwbKnTq~fSr3S(|5ZtZud$j|U? z=uVaoEa?&tP$9OzA{%>Gf_kncna%WG@}oq9XKF-B(K|Kl6YpnrdCId-rlFh?bgmnL z_Bsb87SuGG)jdm~0^RO%X3X#Fk`-?!>Im{|S=ZIHrgN?Bd`nYZL%O{(lWl4$xMyg! z&2rr>UL(8i9&vUfFQ}?g->m4mxY+dl=G1xVl;u?NDZ8peXe%T+`%<&fb<C#fdZn(K zq32CtdzW--6i>hy=KhzXz#}<zEOz(Y`7vXez_m2i)u$VCJ<5$Uj0rv2+NMfpxj&-% z12Cd52(xNAK~a>NMn%`ed1yr4>6B^bJyo8mPugk0;?nh*6lZKRz3&+Hl{HFrB{R?Z z6T!Ifdi6)(rva;Mc(eFM2rZec1m6VNkxLdke}Pi;o&vH4l%O8&p7#^HVDAioCrHU) zeSb@K1PXj8ITV!0Dyjiia@qX{dRr-+hw!!={!R54<!kcoaEMMXWmyaZuSLcN^RSeQ zKtWRv{4>%ARD~xWhvC+rMB2U*_IG4|<ZTE;fn8rvTU^15%<lvB6gLTVZu(Umbp{~g zKq=2wzw=uqT8nTS+dqlb>gb&~#)3p#mnwtE5~kN~B<BgrJ0ZtWV}Ry}7ElgLTNOJ( z%+u<)o(<PgG&&OWVc;z)OODre|D6#|gI$R*;H;v)1qoRIN)Sa|swGf}Kq=LMwnMaT zi0}~TH?j|;|LZIta4*|gt&TEPmg?EuE~Q2)w~H3!J;(2CqI&tL2L%t0QZvO#zb#}A zI`lP)Qiq8&wZ`<CANdrUC!l|8L~dRV+x8E|K@YwYkpjf6Hg=|z+T&&l!Z6qnf##{) zEaA+~Q&r3&qrjEaNbVd2-G2kSDxrKUR3BcX=&&(@!GBxp&0m0TOo;1AX(GG&;&D%6 z+oH@ol=Pnn-&vYW&e{=%DG}{=G@KJuJQJKDAZYXq0r#PU%@TuVYw^N3$sGAngnLs# z&Owe!(<s}?e`jZ8&b~^`+3D2z9eHP|i|7qB7O0w8ni(fChrZA5@BDZhhFhrZtXMfh z<L;(x_mIl76XE%tU-t^?*_Xf@q|`%Z6<VtxXL@OFWOh>YD$R@Q``~F5*L^&FkzO7P zb<@zChy(+zho`U>vcD^3FdU`k%cRKY!M|j1DVu8wkA6V}1Crf^BqA5dBg9yi7PEP# zOW-{+JeBApq#u`1ns6!AYd^QtyjZ&cQEpiT3fk^anjLrP^ix*J!$I5984+nmBU~Og z_e(3t2%+s>s4%}5YC@G(l5aduQT2RQTi`ixCYehR^@JpNa4S1*{LWSE`61R#|BTg5 zH?eEGA6?~PSWRU?@!PI}$|evuURuj$CBo9QhMJ=xt=C0nBlNoeuk2aG(D@9v@c9SE zu%6vtBYjwc?9rtSu{PqyIBTG^DKd+|m*v(!uyY+t<=GJ}iMW1FL>3U<b6LD2kP)TS z$oAoSSd&ZVMf5k!mr~>mrgQ;i8>s|}G}eWYwp#!?pVBNx0-Z<BAcB38zoNDt0x!$b zMG+dcP&MRKBG*WFZew@6SRS`WFkDQ@4O!Dr?qA%$P%9w}J4kH>Kiah}(UfRQOiFA_ zoQEpH$JC)~dY7_uIW}wQDVv~hCr4+ScG{fFoW{nsx!HDkTFu<*PNgl^JEg7XGWeWh zw|8~6i;`JwSsY)e7Bx*tsVd*p%GK6%rCRfrQK)ovw>qa5D$i7^8l;*B{TN1To@L37 zQCDr5nrY2blxDd}nI;shRGQ~x%awROopg0MX;sL2Drrh;T2~!TSCT2AN7fBPQN2B) zDKMTpi2FFdRyc!^mG#p&OQf`uIxX-sKg^4@`jNcvV)-*XpK7ZH*>_5pQ2O>#A}Plx z>3k1$s^ov;G6v7{Oxw!|h7%O@ipYurGjHG2Sh>8C@~b2m_Vtpty%|D>u8iy((A%zx zqsHLw$V!0p(ABYR_eZqKHO#(-T_3Jx&$KY~y%C*&=EilAxr;Q=^${rQS$`}~cSriL z8BYIp!m~ZGYw-YOM-u58x{<Byi77WovNAvgy}fY$d_6?Rmu`rxNkfbj1bTc1Q(ye= zw8eeX7fG%3kl(E(@MSOE7;9bJ6gLNk7e(X|(Q9v<?O(b%LKCQLSK1tzacE}ji>wcb zXZzWTBUnlgus3Fylea`{*ITLeL4D^L+IHP{QKT)b#ifH(O~6nKH&R*Klpv1?-m&~9 zR!$DZtx5aVM5G7p2tP;o@<!Od!7s$oerP|@9>}7d5viMq@Pe;RsWN7Se5n|jTc{7W z$L=XdBWp82hnGb-jU;+6dxq(sg$Fy0!S;weqFv}1IdME0Rz)k763l%(=65;Lzn1XS zy)@3Ax?{<Ef80txbTHDkg{oW`+DKc&igTq8#K}VGgK_U172+sU`Va*@LZtn}#Daw# zw4Vz;(R%QcjHQn2HX_dLy)Aafa$Cd-XoTB^kASW6R;2F`|K0z^i1qMNsE-d`8z*&p zKSS)+6MnS<Ul)12g*fuk$H<C!g0f>iPDv!0wYc(NXoELWbq-asuS2@<6NG;>^pmmY zfwxoiIug)p_du*=`Kh@58O~)G(O%Sj33W2C|5i5RE}ko&j@w@pBPV}@-=b)*2bJqk zhQrclV)fr0Y<=_V!2`VXSt@tF-}XF!-br>d)V`qfx!6_u^X%E|hz&eNCn9U&cA%v% z#@fzzu_N63jaV5&d_i;POYAKx)=OWG%qT?FyV)FwNK22PbL6kE-m}cJuST#TIr&<w zP4{&Q`ZRg-H{xvh(l^PhMS2M0GD_cy?9z}%yq}exVusqoM5s9UvzRj-bPL9pzD-qr z@Xzqz=Bsp1jLzaq_eOLLqWE_x2_UOR>AURR8RGKr>WG#><NhAyH|k^fK4p`Tvloo_ zf2ebjP<nnqY#XQoj&;Zn;n_zcdm+^8AF(#c;O_$~(7!uJeDQ1OB&@`|#NxymiOUk# zBzB{_8<cvXZ92-On0vP!40Rb5-1s10GW0VS=4R=hi3`Vif6wYhel>uay7&2+(l|kE zo*_-{<GVU6S+Vrps$`{-x-OZrlu{Jl$#A)hWvB9{t-7Wv%XVFJZ6VDa5_yx8GLrXG z&ROZcrb&}Bw%yt&J1KX{6pI%P`&vuZEpx5PS-kR;ZYq{wnnud8_)1%HCuXYzNlYad z>PpH@OTFF($Z*q1%WdGR?24443hnt6Cy5LEd?9*T)nr|*<P@vQp2StnGbK*$oR~~c zwW}0Kb-MW)SIQK!m3&o}oCA>4ioy2)7k*6bgF-0@Js;nMbppxceQX@hAiCYWKeD1D zp8quNJfZXeB?)2M2V-sghp3b3aG&uoTWJ<s6^}&p9K3Dtc<kxaqpW>{Y=psk;n`zk z9#9%~=oiFRqxWKuM@E>ZDx5~G9=b})(**CY*|T@3y&6#JiCA6#WaKOxX}G7@96T^1 z`O@J?|Iq9`!rpLTT0c#+*2~oV|2d_XL%XvgVzHw>{361`MoRC69*Jnr2_A{17S>M@ z>+oNa8Ve@?N?RzuBAEzbEw~XpcS^sGrTA~ycixa>*0DfVkzD`wKUj^wqbgbZdBfj~ zoJ=BqBH8>sB|YH|=MNEzBR>2wMq*p{LgZfQPZ22uJVU={Z_sXnESY!&e<t5J8A=P~ zVel$72meC)gW|U22scjc&tKzq52bW0_GcorgwYNhpicaW-*M@0ajV6l(}*n6JL+dy zE9cfUj2^tmN`EIKLKY^>BUI0a>`<B6ezOTTidJMbMf`dpVgtYk_E$!@2z@<xJ+&4- z5zM?p4@Im^#G@Cfc@yrHk4E~wmFoMk$UP|f#_`DgD#Csuazl^i>Pa>N2|@RCM^13i z%zG(vD}(U99ML$4%dbRkoVHT6KSQewwS6^K54{$dD^MY!^hT^6^5<MKvFM$nP}MV= zs1E!(a?!;ft>Smujcu(p{N!#fo5@$DTMBljsnRxD(p~d~g`X1UHVKlYiKbJ@CGFPv zd~Z`SmD%N3x~m5?`~z6%$aCQz5ibYOY5f9~&454$PO^Cmaa)!3IK*xLLj3)KhW#SE z?XAeI;#*X;&=3RMR^Dil8=p7Bwg<mOMWy<A@jt}iJ&w4$r}XY`EB%wY!}RmE*E4N{ zc>!(r+(F{}0D9~FOxvT3Kf_yWUPw%xDdcVFp7&pow#UK|_b*H^8SfBuq)f#c61+D( zA2~I7i^^Du;(Nmp|2wifL2X}SV?}%q1cs6nFZx|7V=cijn24;P03CTK;!W`ub-S*; z^9C&?_}*V5d(^k7sxXMh;V6QfA}`Z#yEe>FLVFIpMI!ycBjM23BJx1VZ#fZ1o&FmL z^f~AmYFk0wmHX0%_MvZ+*$&hx!)n|g`Y=6DQF13MeW;!*)iY`q4s}v<h(L#*rR0qC ztp5t?q}H$3?%&qoo|ID&j=W9X)JEoQIUTuuMf2b>meYf0M8^FJ8Fy<xWHRdiTEuEY z{C<&*oPzqI;pkt$H`H%YH`E$gm*1jpUnBh+nn|LeUZ=Rl#ZhW-TI{%al8cLy+OiPw zcR;lMVT7}9Q8%~YKL4%ouCgp9m|ULt8|TH%*0Mz8oW2o!E3&hFi>fE1k$V*2Y*~&Q z;qaok*;-a2ItM{xb^74$2uI*;`x>cLIFzmfl<p;MZ)}OBy+$+~C7)%T<utyRdMh$w zz_70-7O%nHJ)zk!d@Q1o-=gZRM6`F=q%=JlMcHB_k@1MHW@Q^=uqn+M@@-$_?)ojN z9%^Ks?wiV1%|=jsGoz7HxVIv=5HRB1Drf=lTr4Lk>;%t2DOM-C)XY8{%<R1oUAFg@ zSlPIf$~Hh~UC!XP&(P9E?lhid-kBw|rf7oi7gUIuCU|!zskls{d2R)7zFXgknf2@$ zJUfe6uXqhkCCM{%LcRB6adXGNzaTsy954PR@_r;UIZAE`bnuHT^~?FlYVaB*2Wujy z?Qc`3?HV~teTzB~j#vkS-(suwVY(N{TKOu$i_S-b`ljI-=-X7~8!gD-jz?G-C#U5q zD)&&x>uQRg;jDNl;&X^F#LjJe5*eNGwQ=Jv-bUn&){=Fs<$$5}aWix9_mLTo-qsMe z{_TARo;5~#g0MG5=!x(&6CNI?*1yAqa@1Ic|AF6$^OvJ{LIoPW9BNm}V!k06XWx`t z*_#i92b~I(+o+5LVc*-Kc5D#o)fncJ4a>3Pg6#gOqX0Q`Pjl1U`#0{~xxjTl@Ah4K z>2x`zh-TwqUXh(HXZ_-f)HU<gJ6#s130foUqfR2qlqbMUu-TdeWyoB0>r?C<a~Yy3 z%abW@9v=$#(d8-Z4!PVxwN(jpDnO@Edw|D1D0mu{r?Wc)fTDXae(-*FPYCrB@X2Ah zi&X4^TZJ+@LH{FrR#u)#ot2TjI)avGvDHD!-Jp?R$5Wn7o+0euYg6vQwJH2Fw?~t$ zH=z1ems4#Y$9VYSJ(SfNzO$FDQd|Zv#PSR(S~_eyFA>)DeK27rniAd7io$+o0aTI} zm0m?9TDzGlwFvfiLzgwqmgFzEE8LW%$&PB|)k;;jEmcmhcGH@!8nR**)Jns2OkEQm zykFIlZc_fzqra<5HPvNuQgw5|tZOM`MBT^~QteIoN;BuyWzDMks!GLm^NDmK@6q`A z#3KnSkxMi{BnX=i+3zr&LBWrA%i=uT-cLve?FYC$Z`-EJRcVrVmwSfHTfDf^5#`o{ ztCg(C&)UYVS}#l1yfpX7gR15yO6I=u#Gfj4Q!q7=cTL-NCn&02<BeBpv?V^M@NhEm zP_p$p$V64{!}VyMPyF8ZvUne4dMwW;St5>6P~=}(>5UEAmLW2?yokEL3!#hg8RT(4 zK9xXEqxKq}<dl~HbScRu`hpJ~fJo5tGE$M^IA8#8$uio#HiE4jwmpO7m4wXfWvF}e zzBfp9jbl_FR^aodV;(f@!%B?zxy0`hk9p8DL3(YfZi@#k!hKp9`97vW*M%5X6VHX$ zskUp#9ob0=x|XUE6Jl6L>aDy&jcq-tIdp=8p2cFo&<z;s+cDwWHj?@J7kC@&+VD3v zlXsqkXOL-Y;5U>#8Dc+&IwSDgo(q+J?q$C5cSIBT2FfwUm(Qa-aKm1qolG5^6ot?W zNX3|w)SE9P80h|NA$t251>H)m*#X|x8!O=1MbtT3_|9#ldJ5gY?ZjXDSqh3WZB=`1 z|4Ko3P^)MN-AQP29ApY|OO!96B+JMC9QBP$;XcoRx-yR^dK2>#ixbNdD<HrBCRAlD ztd9`J#71->U4WJffA6N_z`aKPA}R#_jR5xDA8Q_**4tZmA%AmcrpeG1RRMj;bvhlk zryFaW$qQ5IX${@oQ{DFVo{3g_$HIjR8%Mm4I>qTw<t5_d9il1D<xNGlI9^qhq*WoN zTU%=y1>VpUGnJa_JvR;i(<X{}u}-WJ=P8OH3IR8dQWSX);mu1F^fJo&B|HZD^5x5^ zU2yc-6_jNjV!IN~Mv-(qov86v7}n|ti*BGlILF3UbCS_};n`>J+U4%pv0=k`L*_Y_ zY)jVDT;6e-y#IQ7;ICZXv=rMw5$w=ozrt|Bfo%CusR5zy#u*IgBs#&1`(3xwapug~ zZqJ%!?_cMxUw_FZ?xmNmd+dxe&Zu{?S*Jd$X->T}Z=O@{*-sWa>q^W)wKjqXYCaQ` zDL@rZx+4`&u(-@X(ba2ob)qU}CAn`)#iq>_$xBuVR$fVEIJ>#Vl=Y3uQfJe-$%>V$ zD$ec}<-@vdn!KSnnqq5;Ge4bHGh(%+Xp0v#IF&OTMY9#nQDkDT`YSx>hk+lm_UetW z0~~mqtU<8TEnf}1x`y3Bm#?LAW#~c0xbk~p2eE;PF|SLsBo;!9IYp6Ztr4h)f#Mvy zGPDiB%rWm7BG_4q(5VV8$9Hepuwmz)JSn(v7AIKKrU_H0)?O^hm8N0k@(t3AdfA%} zX<OjeRBtHE(5GbQ9nmyZ7rf<LGc^l-2*L$vZ)$LwAxoyKW(`YroW^EFNjWKgwq`cz zmYijFh-mct_e5+*M3aqV^@E*U`8uHA_3SwcYFqA4#NaLO#?hcBeY+Uy=qzBV7yR*m zagiN^Dq%+oW1}h~-Az!*X1y*=mBp+m&bl~x{?_!K8&l~kgsN}#r0bj0^_7#g?%axX zspR~{$@Sg5yn04*y4qcloOQ&o41@P%%k=(}L{ph!+qUJjRojizZBg`qiu@U8mMF)J zV-FeK8x(YaR9}0IlCMGbq^b<JQRQnX3H5DT@HZ_FQ#Ba<wl@OwrU-@iG8h;hmDaJD z&B`}Z6?F{KGw>5FqpDjbvgtvZFA3|tyqi1+&gg=#+`F<U{}z(!uIXs{2j+28raO14 zSIEquh<SE4FPf@2OXf4Y)N|pwb=!WwecieX?~z4IP<n;Q3(}sIoLW4eOM8okrpuy~ zv{SlgSQqM*NxI0L)}ET=3A>uobv{=}Rp&fK=JMU&@fvEnrg7f<&@8_)r=|6&ny9I1 zo!2efF)c%sBwdk=Ebr<CU9ogYxAnBio0^ieD?}xgw38{*QY(^Xitx_YE>O#;d?3Qn z{eg#Of)DOvftr&Not})J{a?_Oa&zgXJ!G0rS#;4C-C(7zoWY5%%uiEzPi4$Hf77O& zf4q3zx^q=aHw^1$k#jg<wISJ}woUY`d2wnwvtF2+Uw2`$V%4g(-(A0YO~tPDg&twq z_eH^vjFttFw`4=M{2#Mqk1mod`u~ZNBFnNQNxUqbTQ51BWu-aOZ)b98%itWIj>W?i zxt%>rFCqYZK!d-jyE!s<5KV8v`B<KVI%_`lu1oCsZ#65b2;0_03nNv33(2D|kch(A z)?t%-%nXaj`k6xbEh0Zf;9Q=ceg3+2+kbP>nl<MwNORX)x~ds{f}5T13Fks@O_D`h zvN=7SN;^qa6|$n8)wABVifgwG#d4%f{S<CSS~FEWWvW~{*(GN!rAlk*ZRKV(7UZX8 zRaQ7jurvb|k+pb!lOU;*AnM5qxw6vqRyZYXo3f@ToTtHcL-sbDX}ch)x+zOJL#{HD zMv{~AqNHo8DSE&3<uq1f+)R1FD4+#=X$Jr8@<9sv^JMEFL}iz6jp%Q{P(Fn9)89PF z_uAe7u}kIm0q+cy9U;+?n33p7Tm!rlPGKJAKrWg`DPSc|2@qww8!QTun3@QVRhq(g z%R)vF=bY~?pVhkT$*A&iMe{yV&Ca!J&*>J#31Z4hN%JJ$<i%b^n&-_OUY@yS-MWfh zmsTWqtg7n~PH*C~tAyU{vh}It)@^IoZt>ROBWYd`C7$ODN%fea%DO5Drq4c2RwW~y zS}IALETsimki?|ynYn36)Fh2dB{iPYEYIexs~2rg$#A?Tdk=UX(;e{$aid7MfzDYF zbd;)&;aQnCz)47X4AcEZZ|C|@!c9y_OhvWfV{~pTP@qVjy+~EfLb_mzb(54C4Xdu+ zrm9w+t2Bk$N$Sk{Rhw+Zk?j#%b!GdZAM3iOPV_F<b~BlC9rjnZP@~io6!=N*-5(6{ z6O>ETX|A`&8iqP2<uX|h!Rx9#4jI8dLhU8}`%t(gEx(^SqkO_^3%BOw4`3R-fbK`i z9|Y)!SU-oG(TUlIN$t#|u=?Hx(2o$0vR45L{!QiZ4E;slo45?Mp~@d5XP<C3dkEbd ze1g5@M?Kr!M%_*OyWBFg{Um$7S-u@k81BKfwectp?WEp@yo3Cn!RdbaQ`8*&8KJ|c zsZ-e}3G_2$&kwuI{oe)X9YoqrP%`*g)}wGQc%qc=WV7gD`hJe}E-yo_)AAQ6Z=p!k zaQTa*C-hkEV(%1jufIfg=`T=izf7HggwVT5ui;#LaFFS>4}I8c`xStGmGTG)F?@~6 zhUNDGZiLI<piY(j83~z9%U@^ri)HXUFMpeOlf&&{8S2a&dM~x&Jsxnnd@t$mo6xiG z0Q9?1Hx8|tPk4K}9PAz^QG518H?jjlYYP9njhfA2dQ@uX7uj~^B2^H#ui54_P2@U0 zfc~CxFk^_idtJtmG<S>hJ*RM{y=Kj-RhM06@7lF;<(b}QbY;&0|Hoa9wb=A5Xh918 zQAqLLTBpL#wkB`yT1cl2ak1c8*tW1(Z1il2M$ed_?@};TzDJ$xg#7wGnXktvYX1-G zW4I6ERm(phJb;L6ET=!DVm$ph_#<jw>7aG|8Fc3<Uel5JS^jb4<_q$Yly4`x=P1m% z`v7_m;X5S_`*%g~f-gq-eo9WCB;)=msYwc6-DBXfQ+@z@KjNCL2ygj8vUfNEQid=* z#QGB9whvQzm3`<VaO1+mO^FN{?w?A`4zq%W8PhyF3;v0A``$nGBy9JQEavcXTt7dv zU_otLy`Hb?+f*}Qez!VzsWrLT5mVWenwvhSkj+Wem0HHxxpw~7>*}1k>L#Nq<G7ie znXz)FnNFwFJYVhbiabk^9B-{nDXLS4dIvYPiD_Q%niwPEl%Aeq<einxX2srVyEZLc z=q_AX+uoq%t9mw@4FiMxja;rWQ%F~5bS=Gir6gKz!O1&$@Bc!rp0gd<baI`Qyu)h+ z=Dv9U&w-wg!cGd`%Osi;?TN{8)PoIe6O%<U2nlXl=FXVmO!T`n@0@9uyH~reD|JuV zcK))CtG&-XRaJIXWu1|8?8<9ZZL1(UcFwN4rm(mW-Zc4~d<^>YIH_9f_b2b^5dY*a z=ut=_(hKkJOfEyZ=07Lqf?u_h7yOPkFR^Evx|Yc;yrBCGY38K!&slPbZO)jw%GOP7 zO5RSTt}wE?o32viRQeK`lY4r8;JSvY>W*pG<t-~?XS0fuJ+DieDT`X6f#cF^>e6;v zF*=o0qlM42eExPMy56PFSO6K$&OBu#f%a=^Ti`Cy6wS$YZ>pNKc7ooy=|Ix31S4(p z0-xI7A<mj|(b)^GaP0*(_8QyMa6j_Qa8c9^e-D-B4bw=A%j;53%AC=nTZV0AGP07{ zF<+AAx41|aj$_(GwVv`5FpJO`(SvZ`7@TLEdZyZxK{l-Z%%!}rOVb1?t?@#;)9$vp z%S3M5gN|z-RJEj2Azyv7_bGqYcEdfDXH%7*1k2u_^4>le<h?CFNo7{|wHxH#Egz;< zci#v5>lBpahAkff=+iJ3Bu7trdorIJ)Lf%XdPb-xuGqNI-MI10Gq-PU?osEoxXs;q zPt%62D{jp>)zwbUn_83HY@uWQ`pK1cWxJCPtXq_|4b7>a6Pp+G<RPd<S^fnJEkj*{ zgU1pK2EP@_NGlN^p(?=ezi}9FMp`NG14h|y$lIR9+7sHA|Bv+%D*qCE#BOK%FqDhD z?F~42fu5Cr#opl~4CP<5o(N@h`|w+W;gxV~#m-0{P}|?J7>1xyNclIc*8;R{EknFd z`45yWP4Ezp3kF*LBXx&!B!C{I&!I@$q5C6HG{Qf{LHAd(o+sr$L)%~C69HfL9!gk= zOrnse#rGAU0YKuqsjLdVHDvw1wLO)|x+^!OC$;tN@;-B>?s~}Cm$p;Mu1=A6Q{{$+ zjg9A~xf&)P8hDPE|3clbd-Lde$cu64<CM3xXOk3v3T^*NS*%{K2f%75gBJyy8=p)( zozN1MIJ2;SW6KA+HM~Q{zvOcMa9}iW#6zn3dVhUY*EOR<a8q1OwUr+-YxPdaP4TX& znjc6`v_Fw*sePhp&rbN<X=}3H(4N-ST3y#`vW`~Qp4L45Ynmf=GM^Le<YwDmJKvsR zP1S5Bsu_*7IF+)g9t)u5zp+u0H;w`HSvDF5w|$O{EXB~j<7~^Yw<5WPr+Ab(!@nDO z_u)ffW9Hf&>Uy_jk+H!(YCE26b3d7CtAC<?U<Z8Wh!<;?Qz_Kuv(<8?Z8sWXr+lMh zDZ=R&$cCzT#L3mmwT@+8VJCG>u#@X;`^-M0L!Y9%ot9Q(s=OnbhG6rG#cP(ONQ$Cc zTHcf-!?R69ThJ7Vi7Y5XM%(fWBwrqiPuvKegkzLP0+F!ti)?J_d!K@eQO)q|DEsXC zAH(cD3eS#VyBJ62mX8DUMC?0GQgvT_4c|}o2hD?rJm^c%_IYYO@%?5ysJ1BgiEo>~ z9DzdHL+^_~U-#cOvY8qE36z0h1nzsUf#{v`E38k-;0mTE&!HRQy->Hb{3;v!GPI3q zOQL1UuTjtp_^f*vZbj619q%(<z+PXFmkHDF4JrcWG0ab#$)Oy{#fo@M<=KGMW9YUB z=U#(zihrEa%O{Dnyv0Twm*0+X=QYwc=*d4L-b4t`zo>Ym5c|K`xK#{&hq46xC@PSw zy|AMhPmmov^4f#5knsw*O}5c49b!Xk6B7~(6KfM25@#pQ_jMeq=Yck%5W>kQJ)*Z~ zbs-xf+tnomHwJ#Ay5zg7g8L*@t4y0|+f<Bk!>m`TS9y>EXI7+jMUm$ll3~lD(!AB~ z>9IWHvU-&VQL9o`MOv~qMK#0MR9UlgDO1sOeUg~73|;deRz4+)f~?DmsA*lTLfUX- zL$9zbO)~Y`q$Wwpopyy~@>X(zW%W)|nw2I=W8x<fb;pyG<Px1Zo}yN0Z<jU>5mVzF zJmXpU9Rz6{7ucw_;mr}*LS9gy561my6`e%ynhDpl{i|U&GA%I!P7pRE&P}{0akamW z!cAJZF`+N>+o+=gI%$zW-9co6NFO*{Y@&~E{q*<rZ7`CA-HqwV)6z~wa%N9@&K0(% z)oPah;03aMnzvjv!>7v4^thHKi>a!Hl%~2D3=c0*1cO&*YnrASi!9zyg`}O<GkHB@ z3X&mz$h7lmS+>nSqu&24GM~EII@2_#=pEK-$Fdy5u1FdpXD2JNlkAjcN``0p=k#1I z-I`7bn&8Tk+Q!v5QWme~5DPaBnR&-$lD*car=RI*YD{f_Q?B#b!T>F+pa8%*=UjG~ zyJN@NwX0X}*s<!OzP`R6+IGA5pJO}i?T-If#?E9iZJ7+z=Ro@)f0e9@ytC=lcT8U9 zuBxqF<*rz9@x{x|?dj?HW=&0(GjsK7r_rgatDD}4ycGY2cdelN{jyfxnvC;&;y1P7 zTdV)iHwsjVgElHb)r1x9nYFcNx+_=i*s<cmIdkTG(y7*SpLN|9L$)NN&z2Nh^Y&Qn z&V;M4cCwB);`VH|yK0uJTOIjr=M}2u>Vn8O=jCd~YyS{r%^g>OBO=^ZJcWH(A{@c) zoWWkZ3+=Sf-Wv%lew@j~aI0ypy*ZcLe8vp7-f<e-nP=FiCA-{4&eF0Kc8xP_@!GYQ zT(WlCk|j$Xl;t|RzFTc}vj-<N&rnZ0O`Xx4v$foU#%!jkLhZJ7Psp`8U8g;MVFdiR zitQoTZ+LUo@#bikH#aX#cxxGQEyO$YnXrw`ko_-h?%?oy&k}Nl|DRI1Aer(^;<hz{ zx7D?JdoQ;tl8ZFnva8gpjFpodT^2b`b5&W_g~?Z+<}7P!TDE4*#TPqUwyaoj+G$(2 zp0;V`%$fIdX-*JkII?2rt6OtgJC{zGp0y+xq9Uht|H_0*%MP!KvRcurC<U{i>Z*~; z8UA0gDa&%DEGLqQ0#q7#D$(RgU&I%a9x~oA=UhRc?dVy5_tb;QWfWm`MaAS=t-9Tq zsCUYX-Sd(aPEyUJxRy$_vdNsJHP(FXZsdOX!E`cL<J4qpvqn|(w;$H+l&PJb(v(cW zuFO<rY_lO;Up>2F1R`R_HR=@naRSw;b(*xj?tN^Hw{f^F8#h@yYy>Qt8~#PvR!;>` zKNGXJ2SR>iM?9;!9?q5$NH{Xs%f~<Mjry))eZ5aeZ~0>R&c>Z-Zl`HzHkVh_Vb>k@ zK1U?QDcF-7K{)$raP^d}sfSvfSys@Gqu_}Pu?f%{F45#cf9LTCttySs6JO#YFYgLm z!07Tp*SV_=!*IBQrW|rt_a5>-CCAAcxdU0v(K1i<mJwH~=YDx=_44X|xzf;0*Ul&z zo3;uOW&JGKUVqxa$MjK89|+#wum;sJ3d)0>;vGA)sV3Pqv-6HS+<}3QIJTm5jx0%I z?j2)ek1lcQ7F?&QDJR8o#-w6<#+w4UQ~5D6kcg8Bi?#C*bmSUp-6m}Zo}q4XLJT(H zKG>)z3(d$)RIS5DgFay2968u+An3rGY{j;IIDNSOoQM?;Z4Z5!k~M;NxDsfJA_tM} z(Bj#4Q;4+r+TNq3FK!-p-&N!e3hDJ<&wKmOv(wzx+iy4hgETIyD0>`dkN0^>(PlUI zO;c*7)NPc7Cb#hlRjqI;WPQ?s7N^^$t2d#3;SAFePTYDwYcJ#Zk|WULA#~hf?J7)j z7vG-32>>;>=yG#i|6!m5?#7MV|JvqGJI@nrm#fs2{jR&;`#j~?uH#Ie+;lZalx$4# z=GAP6*+HY8`8mM7KDclzal~7Hk)4(Zls}yxGN@4UuKhV6q|X_)?5=K(x3U>i6qm2( zYO;%Vcx*5X-Qsepc9ZMg<b96Fs*_Vwo@Q39oF<8K+SKxnC|-1ls(6cnq))i1*`8tH z)0dYLKlfHAziM9}@?wm7zzfWod!%=$<3S%EFf!Hkwc>;cGp5On6YJ{4$rD;XwoVqT zG}nJX5QbG%vD3CH47iT2G&C;k8}L3qR~1!~ZBLG5OHf7LloYK`Q6$0Jm<!ugHEAVP zsqF$?G~9;i=5&k5khgam_*bC6=$r;f0<OJ>lA)gwX~~e8bRx_MHJ*)=!b5k*N#Qum zy+jR2))Ss~^6e_0ud}g!%I3P`&MthT`(3%a!gUuaX3AAJyvNMt8o7zp*=i|o8}b&{ z{id$#o@Q00J+AA|u_rECYO57m*47&=Z*nDVjkh^bH|y6M+dOhPNm**Uq0yLToH|#E z4^!I3(`CaA6#eAjv<%ZEPoQv$i7-GUvzVy$F#IX;2<T>1ON!izgj<c^=J8!eU3>ri z?&8Ip7JtnDAsdG5D{Xn7>+bVDk8JF+ENi;=XWGSz>h1C*xoxP?=rsNJSA%c*5%TsN z-UX3cng6;E)n~hBKjbc1a`uwj{U2U0%uKpUQx3T90q=9aVQldG(CPi@xJXr!c2ZJW z_cZ7oIzuz8W!vL)?|6ZguHt%z>iAp~>$p}nld+%0+-rLl*{{P5<N)07k0YIK<63{3 zXI=SHI2Umtyg=^mqHpzrUE8}-<UH4{YvJ1)moDva8*7!Ob}4VkNhfVpHMq+S6PX!9 zt~=y?o;usrWLr^9)6R*qsfunoCA&hECaHCv>Q6gq*_eEw#hz&~UST5}K$gy?<c?5a zu$Iu}C2H1Hky9`5PZ)vow()BA{0MVlBAcxPRTLPnVNbF^%JKck$Ue4y3+_ptT3-(b z^J4!Etlt|R%W?`kY1@ApHNsFH!Vx}CLF?EPGQ5t}$Mvj#J*An*+xFbcju5xq&c^nS z!<-*)j2qiHNE<*sK6y4*OJXKe%v%+$>Jm)?LY2g0&j#L2%06l}PH3n~bEfI73F*nR zxaxwPNmbjnuh^6;-GY_<j9ZcBxe6<#c&Z_z>586qBx#}JEc8A<<QwxG&+~$l6D2|7 z4c$#A4YP{N7!@h0de@nqddH$25A#W-N@y}9ed|Sv>Q7#M;y{Br&Gc436gTs*XX$o< zuW|w_ZP<r|hgYp_nedG3T_;Wd1&2l1;8IKG&vy!Qg_+Yk3!14{dE1V3b?zb)*~aQE zu6v93xyQD=C6D85%SbwkUXd~MLVH?~jdb01WG5>Vha1gKlW-`M$@(}Rk2l9cTd3T3 zPY`HpBs(~gvo=<9A$g#(I>0^D@L%CP3nG)pCnT7?1lC^*DLkQMK1QVYjj(@1eUuE6 z6&hD6AhL~jP}5kvLo*{Q*U_-oxCVe6*yad2)WhmqKjQ*pL(}%aM0VZ|%{@h9hoe|P z^*6A>TT6hwG?nTJvCwfn11lKI_#~j}WcUenF2*~ks>}YI1;4iOY1HYWN3U^+1Rb`h z8yOEe2+^qH)5)7pQWDX{<|Z1P4bT}BZGGtC2xVydX(ol?aG?F(_j;T@y7>gy3iuAn z+fz2cp2PQI>`g56S1I3-H!dIvoOFF96SLK%)1~*j6)C%Gf@B%~J|vw{l<S;=y0h;5 zI@_3Xo%i{eSkovpexkZsuC951U7b=}zcN+T$TvNus&%cJ!wXx`l5S1DR<`QhOnrT? z+wFY7lG7H)rDap*Ezz=FNi<}^7Gid0rR8xP9-qZls>RT5N`6A<Y<3ky>(V%Q(~bAU zTA;n`*)x{exg@R<BpJ=p8#)OFsL_CD$ks>()J=?hKgWzP-a4GeX1oA7K(|-?cwc1I zI~kd)=%j3Z1o|3<eE|gxWp5!Rdrt<kH@=9y|3=V}e^B@J{!J%3UtCOafM|yC)7Wui zeQ^Qt7lm2T4}J^dOW1rG?}b`J<4fZ-!}v1RCcvi*FUQ&hr&Dd8CVf~<@yTmjoPEm7 z3~kSuRNTU&ggR$XXAh5)5ih5-Uf72fapwu+E2*=Gu<e<wj~T+dub0)*xM%ZO&5PRZ zZi!nd##gcVS}}BW9ES#r)NUq}?Sa^}a7~<bRqTwj+Q!#XbO>c~9jhhrh><QYfVKLF zC)G3HmTfI$!C1#~WFKhpkqt4KyIaTC!%wspZ@^x{I1j)$*t+|cP#WD|lXjdktH=oU zHL_52gF3Q~jch>@GI(9wxNzPWIgoP%C3$0lGb_NbJCKEEnK`_Pl~N4d9NXV(Vkv$$ zB@0CIiUZUs5ShcpU$Yt)%h>WbOW@#>6khVSL#=Urz?s>j+Anqn;vDyKaI=i<gHZx~ zgR)V+K-u-7ZFVk^b7XfEsrgPaUm#sOh@@g8g@<6@x12~2%x{pOKs%pDtsbGwpU=ig zqIVQ;q%!)G^UDE=(L&GBd)=WCO1eYr7qGhxJlYG{yf@=pnE8SABbGdu)r1)DR@S!& z>%5D|=wA;<e=tks%#ni(6`0H4Vm-FTx4~@O4%jY^ee(|XoF7AX#z<l7IK&c<U&78` z{EbWF<f~lG$|9oI*z1&MyuX6J=aifu=o@7H7{4rL&&!Wr&RT)vR{-=%N~4FIyDDy8 zjbBYgs{2tMYfj-@__k}}<{-(GgEdL1BEXQ4z+&{c<5`MmXXZz>pOx60IFCBN#rw4X zN85M6SyfyQzkToa-rjrL`@Ze$F3axHk&g5tV8sf8EjAQc7C}G-X}hm%nnq(xVq&T# zrkO;IH7a6yVyZ1xR76er``tS;Z|=-x^q=qd{l2Fx?78#i&YU@O+MGG3AKXEt?k0oi z0%(l}hZX-9zMu`>Ip<s<$QqY8v$;AxSN1Y$+~%zAdb1<Z)t9zYb6an}-5D5|*S|IR zVQ8wXB}_@!Xxo9Z`K+i1_YP&AR}%?cC`rUQnb##jN+is<ws2aH(miqY34OJaBvtr- zs;0_PTrUw4=_M(tN;=-Bu=A%Ze!Y1<!B0XgU%_1ID_MH^@J6DCr|^nA&(i*e9%NGV zRiK}%2^|nigPl*(_7K`(zoav9ZG}5^6W*y{E^wz_4|2&2UqjoBXzZH_eiv%X;5Nwc z76uO!hKDc|Xut@%m1ygaa`4@cr(krmPAaYgl*cI3HPk*r4sb0ozHq;6W9g{F+iC7K zd>zQa51;J-wiAqFJp`g7gD7u!N95w*3^kyA;EZVoiPeE)CJ9f$g1C6>pAj0M^I~i< zO?z|X_!XZ)2ZmNsOc9UAHG?DB@70Q;WGI3aS2fj0aE8EJ);Ke6xmIn$w7B5rXu_0j zT?vkhP1};BHbvnDPUHmNxUy6`_&jaes+JHEA}`sdXMN|wsk~4vRMh!BOZvU4qUcUX zdAVI#X-?|4_0n---0;#RdZvvZn=WyaVt;LdyXrAjE3r$|$>TE0_^D@4YFpbj-<eil zuN$1rDRs3opZe2rct#nqhj$WsY`7P8(eeP+Q5n9TSg+@>ru1)22k&9IA`IU^NHHA2 zLuh$~K0kaT%Xc`uo5*fdwChp6rr|yGDKq-UO{@&rNK#3dp5XZQ(sw;k5BqT2x5K$? zdWY!YFz#VLU5gX-aDc#ENdE_kT^rK>Fkyv0QH0_gU^F&HSo-Lm&_*LNXk*QY+E<&e zC&v3k5sET%M=Z@fb69(OIE$h05SYv{$D79^1F=QBzf6owDr#A<hb?KAG(9+(kjJ6r zRv>N?`7}5Tq7H{YO>n5tp8E_Q?}x-JK8quGkANP)-Nr4|_|_%VbwCvP@XdI<0F&2& z9QB|dE>`o=(b%i8pX0L@c)oznQJejrB8oaWaN3iPow8tla_-!@BO~)f_gS}P<xq>; z)iq<x7?3sU73k?32Dhz-zW{ig{n0x<jvm6jH-wQ`Nh+=-iQY6oTozBGyfnez_St9G zR94oEt(rKosw&r7TibGRPu0|^RaFl?>vpYZYipa_<#cr&aN1UMxzA2+Yn$G6X;)X^ z@0MYHRp6H@-oy(yY?%2V_?ygp-~sJ}yr2}s95wf*2a35snD}|OH^FIAaLHCm#7pdi z=jd*!RPM;!*|uYp7;#tCOO&=o$Jtoom83=9;>4-R1<NW@DckeBwl?p(&I#q!Ey9H6 zR@>pmwU(KVRo%RF!L)9*vuToRn%z#tiQ{{!s;VTPCrfu)JM2{Ni77LgY%D87Ii285 z*{^{WxYhruqO<eIj$46Qv3aqj|M%+vPK=|MxziwVjR(Sc(r2C9P*z$qw!F8utZZj} zd0EqW?djg$($edfiGn9wJie@1?W*mlousr@PP)PK<|eHwHKjjxk!5vQmQ`bzmbDQ4 z`=VOQsxmq)t4<UJ$+6^=SzB#8s*@f+zAP=<ydBVQqd&ht_)=6y_Y8{Jde8+OkqCjj zD4meb^$vJbq@DxdbBI@s$35?HV^+f{{(m?k-rwohW&x-FJI((gboe$R`ZnOCAgA!~ z?KE#22DP_`?*R93oR5z9JMtlrO$fyYK>034QX@cwmOpiAvb1kP+Nr2;t;s7_u6_R8 zl`9*Yg}Sm?54lZlTqx7Z8_krEaXVc9|E5HV>t(1r0h>UM@!>DykwR}YxUo1~tXCA= zYJS*<-U*;z!#**P%W?SYK(_-t2;?~qqTL`3)%aTb9P*Z25`~)<BY28;xDc5L$IY?< zkPRT9etm<xVZ+J?R&6N1>n`{D>+g2%cPhS`c5OwLYHF4*KmX5bmo9B=il^+R-HO`d z+Or>(WlJ^;xi(`cb<JgE&83EB__}x^uED$(YTOc3T@(x<PUe(_Ga9}NtVnRi|5txs zAc{dLC2^__FoFJy?S{6wb3Z?O_Ka2D=e@4S98;R;&YbQ}cb{_HM<tk@5@_Y%hE>>4 zZ<6ecj05RE-7Kr_?w;<=?Cl*p=cL-X`l7P(CCXA~Ny8(S&R5%YgIDp5R*kc%JLy)B z8B^_5HD4x@Z)yjaN5@v|ag$H<^$V3%tMsO}3oe*3Zrr#NlLfD-+$^u{?LA?AzCv<E z-4XaIcc{Usb$810kf7TdU+FXs6@6cS13EOY;fB9KWB~Aa{Z>$UWcZsPXBNtv9P5O% zL0{$!@0uN#kSw4C5mg_cr;}+;uNK^R$=T}@-1(o9_6<~3s)p`e<!QQF<Mo~(@B`Dh z#L}6vpq0BuX;oL(Rb5^E6D{K>w#f62BwCh}Qe9D6qbR2YH$zj7Bw3;~T@zJ7F*QE8 z5@@GvO)s9czvkn&E!G|Dk4=uvU{l6%*DK+&ritV)WKiuTMtR+Y3A<;^n6+xNmba3s z&7~AMkvL!`t&CTlIaQZ!NjGKQ^Hpa>@OY)%RV>GP#+10UQ&#GfI_uoIRh-ModaG^N z>B@8X5htl69o|WaX{W?170WzctW2t2uv0adBi!eOV^QSK$IPRz|M+XR#JWTc>rZKQ zZ8K-yJZH{~l@E4xJ$Op|yb>p+mnSL>MU1a1Tc}McUwCSwWTiK2*6Nv`4SqbM^KsQO zbX#|p%u6hvr)E;VA}`wwvLkplFSP5r-s1l$#%TxqWri=67Q?%Wa3oOJ2viz0Dl8Up z6@q$T3z107b4o)!r%FazvW40f(Z_CCSvozl!T;3v884dUj$x<j{m-I?gjLg_w_My< zE7#Yb?>d@gr#aWQ^dP;IT~lpW*>%oA$JxcJroyM}TC28Zyk2U#nxomSr-7LOuQ`as zo<d?C@dZ5SWG{OnWJaNRhMlbQKiy7go73IhKCa3CG!7UqT4l9XO}o*uzP(9qX?e;Y zOod%zS5KTccSXvsTwU$|QtxCP=LX>pFuauRdMO>oj0argNfaU2gU{=j<2-I`h|3o_ zJ&EKK48y7PKaHn1RQR9rPV*%rHFn}eVa%9BON(w8^?JHXZrPBjHR>`?T5^CsyEdDx z^~YN4WL@`q{-*7^rO&ro&oVvJQys&xJtN>Os2-}1&t-w`_FthgQoy-LAFO<OU9GMC zb~0nPwr2V={-<q<*=g694c=K!qgi8hnq{_WCtH)f-nem#7kf*V^yVzvtgr8wqT0?R z%Qt^5XRYJfPFYoT+HdKc!7KiTHtf}=Z!cR74VFdKve*V?^S6*c4CJZCt1-b}joGmi zV~hT)HEE#NC5a_4Trlzi$ZXYgtNl-AbtbrNQ8!j`?{<`QcVD02tIut^Wi4%csolL0 ze4f!{UN=nBI^zt>G!4r<Et5)RRtTpo)l{`X)u%4E?d6qfMr+pm^?`YQACHxTTb{(I zi&6Ygu^AiilHVyUJ?qvj@pgIh*R5;m6waKuYuDqpn8>)9b-KPT<2L%r%y)ayoqS)D z@-^26kR34{hTKs(rNVcBOD<bnY1~A0Vt@O1b+L7R^U9Soy(_)hD_3^#S6=z7AlEs* zs??aa>#Cfzo%UB~wg1<~MsVl8_`V9(8zZ_7aZjCkW1HL7cJc!&+IIMF^&)RfrQDR` zq^7Mh%~gF3RJQKxW`UEAx9EIv!ytlb_&Ye}30id^kID69-teb!+q-Ey7D4Z!b5ak3 zToS|g5x$8K`aQa?(lE&BI($En@zBS2$kzcoX#Foh2TWk>{~i1#AS(*mOwIk*P4H@K z8ymeTLdubqF%uSe96w$;Nt<J|Boy0}ElV@1?rd&$7kl&PJCnHbip3K+$KKUzw_GHb z%9>}$uGw9baPNW&hpw-^)x>&19!Ff&Fx35{6${~zh`>!eez7?IVEBKLPue7$w;-h( z9qzsEs6A2U9bOru3XY&!j?gEZtt?eqf;>`ckVdM0Rgas=w3oEG<AjuLH}*VZ33101 zT%#pj*5;b3As8yJ8G@<x3+8FHPU$q$S72316x3SVah!Iiz1?gUs@wg!!3@WT01sFe zJ0o^pY<+-dXmbUO7a$Z&F``++34|s@66jAT=VB1oFT!78s1x~bsD%eJZ=Dd_xj3b! zT$EK+k<-aKL$)~HaaXTiv&LJ&YpHXpYIsX)O?LTKn%X@}7&}*3cFAO)%c=dMEGzP) z38rnU<3w3eWt|s#WGOR$=7a}Dk(X<NtPQ*<w^taZA`0;mpR4%lm;YTYUSf(`MZ2mf zvSXU&iJGEFuyFta|7sEhRg6zG0mm%n#;8P*-$8Wftk`K_#~z<;4&1as%t1tEY%zy} z_}`Po36^|ox~|T7INi`7t7h$`m6cspRUPH!S64b!PPuFg<Ak%6#cHdhtE#`;g4M7x zq>QvL2YL?qx^=0O1j#fcL3J~w!Dm_$e0=JfTkhDMiXa%0AaI&*)o6CLU0-ij@Ln~{ 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%0Aep#_0Q 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%0DxxtONw<5=ag5s}uDiURfU_8gpBzuQvz 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 diff --git a/lib/combodo/tcpdf/fonts/helvetica.php b/lib/combodo/tcpdf/fonts/helvetica.php deleted file mode 100644 index d1aa6d851..000000000 --- a/lib/combodo/tcpdf/fonts/helvetica.php +++ /dev/null @@ -1,13 +0,0 @@ -<?php -// TCPDF FONT FILE DESCRIPTION -$type='core'; -$name='Helvetica'; -$up=-100; -$ut=50; -$dw=513; -$diff=''; -$enc=''; -$desc=array('Flags'=>32,'FontBBox'=>'[-166 -225 1000 931]','ItalicAngle'=>0,'Ascent'=>931,'Descent'=>-225,'Leading'=>0,'CapHeight'=>718,'XHeight'=>523,'StemV'=>88,'StemH'=>76,'AvgWidth'=>513,'MaxWidth'=>1015,'MissingWidth'=>513); -$cw=array(0=>500,1=>500,2=>500,3=>500,4=>500,5=>500,6=>500,7=>500,8=>500,9=>500,10=>500,11=>500,12=>500,13=>500,14=>500,15=>500,16=>500,17=>500,18=>500,19=>500,20=>500,21=>500,22=>500,23=>500,24=>500,25=>500,26=>500,27=>500,28=>500,29=>500,30=>500,31=>500,32=>278,33=>278,34=>355,35=>556,36=>556,37=>889,38=>667,39=>191,40=>333,41=>333,42=>389,43=>584,44=>278,45=>333,46=>278,47=>278,48=>556,49=>556,50=>556,51=>556,52=>556,53=>556,54=>556,55=>556,56=>556,57=>556,58=>278,59=>278,60=>584,61=>584,62=>584,63=>556,64=>1015,65=>667,66=>667,67=>722,68=>722,69=>667,70=>611,71=>778,72=>722,73=>278,74=>500,75=>667,76=>556,77=>833,78=>722,79=>778,80=>667,81=>778,82=>722,83=>667,84=>611,85=>722,86=>667,87=>944,88=>667,89=>667,90=>611,91=>278,92=>278,93=>277,94=>469,95=>556,96=>333,97=>556,98=>556,99=>500,100=>556,101=>556,102=>278,103=>556,104=>556,105=>222,106=>222,107=>500,108=>222,109=>833,110=>556,111=>556,112=>556,113=>556,114=>333,115=>500,116=>278,117=>556,118=>500,119=>722,120=>500,121=>500,122=>500,123=>334,124=>260,125=>334,126=>584,127=>500,128=>655,129=>500,130=>222,131=>278,132=>333,133=>1000,134=>556,135=>556,136=>333,137=>1000,138=>667,139=>250,140=>1000,141=>500,142=>611,143=>500,144=>500,145=>222,146=>221,147=>333,148=>333,149=>350,150=>556,151=>1000,152=>333,153=>1000,154=>500,155=>250,156=>938,157=>500,158=>500,159=>667,160=>278,161=>278,162=>556,163=>556,164=>556,165=>556,166=>260,167=>556,168=>333,169=>737,170=>370,171=>448,172=>584,173=>333,174=>737,175=>333,176=>606,177=>584,178=>350,179=>350,180=>333,181=>556,182=>537,183=>278,184=>333,185=>350,186=>365,187=>448,188=>869,189=>869,190=>879,191=>556,192=>667,193=>667,194=>667,195=>667,196=>667,197=>667,198=>1000,199=>722,200=>667,201=>667,202=>667,203=>667,204=>278,205=>278,206=>278,207=>278,208=>722,209=>722,210=>778,211=>778,212=>778,213=>778,214=>778,215=>584,216=>778,217=>722,218=>722,219=>722,220=>722,221=>667,222=>666,223=>611,224=>556,225=>556,226=>556,227=>556,228=>556,229=>556,230=>896,231=>500,232=>556,233=>556,234=>556,235=>556,236=>251,237=>251,238=>251,239=>251,240=>556,241=>556,242=>556,243=>556,244=>556,245=>556,246=>556,247=>584,248=>611,249=>556,250=>556,251=>556,252=>556,253=>500,254=>555,255=>500); - -// --- EOF --- diff --git a/lib/combodo/tcpdf/fonts/helveticab.php b/lib/combodo/tcpdf/fonts/helveticab.php deleted file mode 100644 index 8d6047f6a..000000000 --- a/lib/combodo/tcpdf/fonts/helveticab.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php -// TCPDF FONT FILE DESCRIPTION -$type='core'; -$name='Helvetica-Bold'; -$up=-100; -$ut=50; -$dw=535; -$diff=''; -$enc=''; -$desc=array('Flags'=>32,'FontBBox'=>'[-170 -228 1003 962]','ItalicAngle'=>0,'Ascent'=>962,'Descent'=>-228,'Leading'=>0,'CapHeight'=>718,'XHeight'=>532,'StemV'=>140,'StemH'=>118,'AvgWidth'=>535,'MaxWidth'=>1000,'MissingWidth'=>535); -$cw=array(0=>278,1=>278,2=>278,3=>278,4=>278,5=>278,6=>278,7=>278,8=>278,9=>278,10=>278,11=>278,12=>278,13=>278,14=>278,15=>278,16=>278,17=>278,18=>278,19=>278,20=>278,21=>278,22=>278,23=>278,24=>278,25=>278,26=>278,27=>278,28=>278,29=>278,30=>278,31=>278,32=>278,33=>333,34=>474,35=>556,36=>556,37=>889,38=>722,39=>238,40=>333,41=>333,42=>389,43=>584,44=>278,45=>333,46=>278,47=>278,48=>556,49=>556,50=>556,51=>556,52=>556,53=>556,54=>556,55=>556,56=>556,57=>556,58=>333,59=>333,60=>584,61=>584,62=>584,63=>611,64=>975,65=>722,66=>722,67=>722,68=>722,69=>667,70=>611,71=>778,72=>722,73=>278,74=>556,75=>722,76=>611,77=>833,78=>722,79=>778,80=>667,81=>778,82=>722,83=>667,84=>611,85=>722,86=>667,87=>944,88=>667,89=>667,90=>611,91=>333,92=>278,93=>333,94=>584,95=>556,96=>333,97=>556,98=>611,99=>556,100=>611,101=>556,102=>333,103=>611,104=>611,105=>278,106=>278,107=>556,108=>278,109=>889,110=>611,111=>611,112=>611,113=>611,114=>389,115=>556,116=>333,117=>611,118=>556,119=>778,120=>556,121=>556,122=>500,123=>389,124=>280,125=>389,126=>584,127=>350,128=>556,129=>350,130=>278,131=>556,132=>500,133=>1000,134=>556,135=>556,136=>333,137=>1000,138=>667,139=>333,140=>1000,141=>350,142=>611,143=>350,144=>350,145=>278,146=>278,147=>500,148=>500,149=>350,150=>556,151=>1000,152=>333,153=>1000,154=>556,155=>333,156=>944,157=>350,158=>500,159=>667,160=>278,161=>333,162=>556,163=>556,164=>556,165=>556,166=>280,167=>556,168=>333,169=>737,170=>370,171=>556,172=>584,173=>333,174=>737,175=>333,176=>400,177=>584,178=>333,179=>333,180=>333,181=>611,182=>556,183=>278,184=>333,185=>333,186=>365,187=>556,188=>834,189=>834,190=>834,191=>611,192=>722,193=>722,194=>722,195=>722,196=>722,197=>722,198=>1000,199=>722,200=>667,201=>667,202=>667,203=>667,204=>278,205=>278,206=>278,207=>278,208=>722,209=>722,210=>778,211=>778,212=>778,213=>778,214=>778,215=>584,216=>778,217=>722,218=>722,219=>722,220=>722,221=>667,222=>667,223=>611,224=>556,225=>556,226=>556,227=>556,228=>556,229=>556,230=>889,231=>556,232=>556,233=>556,234=>556,235=>556,236=>278,237=>278,238=>278,239=>278,240=>611,241=>611,242=>611,243=>611,244=>611,245=>611,246=>611,247=>584,248=>611,249=>611,250=>611,251=>611,252=>611,253=>556,254=>611,255=>556); -// --- EOF --- diff --git a/lib/combodo/tcpdf/fonts/helveticabi.php b/lib/combodo/tcpdf/fonts/helveticabi.php deleted file mode 100644 index e2ecf38df..000000000 --- a/lib/combodo/tcpdf/fonts/helveticabi.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php -// TCPDF FONT FILE DESCRIPTION -$type='core'; -$name='Helvetica-BoldOblique'; -$up=-100; -$ut=50; -$dw=535; -$diff=''; -$enc=''; -$desc=array('Flags'=>96,'FontBBox'=>'[-174 -228 1114 962]','ItalicAngle'=>-12,'Ascent'=>962,'Descent'=>-228,'Leading'=>0,'CapHeight'=>718,'XHeight'=>532,'StemV'=>140,'StemH'=>118,'AvgWidth'=>535,'MaxWidth'=>1000,'MissingWidth'=>535); -$cw=array(0=>278,1=>278,2=>278,3=>278,4=>278,5=>278,6=>278,7=>278,8=>278,9=>278,10=>278,11=>278,12=>278,13=>278,14=>278,15=>278,16=>278,17=>278,18=>278,19=>278,20=>278,21=>278,22=>278,23=>278,24=>278,25=>278,26=>278,27=>278,28=>278,29=>278,30=>278,31=>278,32=>278,33=>333,34=>474,35=>556,36=>556,37=>889,38=>722,39=>238,40=>333,41=>333,42=>389,43=>584,44=>278,45=>333,46=>278,47=>278,48=>556,49=>556,50=>556,51=>556,52=>556,53=>556,54=>556,55=>556,56=>556,57=>556,58=>333,59=>333,60=>584,61=>584,62=>584,63=>611,64=>975,65=>722,66=>722,67=>722,68=>722,69=>667,70=>611,71=>778,72=>722,73=>278,74=>556,75=>722,76=>611,77=>833,78=>722,79=>778,80=>667,81=>778,82=>722,83=>667,84=>611,85=>722,86=>667,87=>944,88=>667,89=>667,90=>611,91=>333,92=>278,93=>333,94=>584,95=>556,96=>333,97=>556,98=>611,99=>556,100=>611,101=>556,102=>333,103=>611,104=>611,105=>278,106=>278,107=>556,108=>278,109=>889,110=>611,111=>611,112=>611,113=>611,114=>389,115=>556,116=>333,117=>611,118=>556,119=>778,120=>556,121=>556,122=>500,123=>389,124=>280,125=>389,126=>584,127=>350,128=>556,129=>350,130=>278,131=>556,132=>500,133=>1000,134=>556,135=>556,136=>333,137=>1000,138=>667,139=>333,140=>1000,141=>350,142=>611,143=>350,144=>350,145=>278,146=>278,147=>500,148=>500,149=>350,150=>556,151=>1000,152=>333,153=>1000,154=>556,155=>333,156=>944,157=>350,158=>500,159=>667,160=>278,161=>333,162=>556,163=>556,164=>556,165=>556,166=>280,167=>556,168=>333,169=>737,170=>370,171=>556,172=>584,173=>333,174=>737,175=>333,176=>400,177=>584,178=>333,179=>333,180=>333,181=>611,182=>556,183=>278,184=>333,185=>333,186=>365,187=>556,188=>834,189=>834,190=>834,191=>611,192=>722,193=>722,194=>722,195=>722,196=>722,197=>722,198=>1000,199=>722,200=>667,201=>667,202=>667,203=>667,204=>278,205=>278,206=>278,207=>278,208=>722,209=>722,210=>778,211=>778,212=>778,213=>778,214=>778,215=>584,216=>778,217=>722,218=>722,219=>722,220=>722,221=>667,222=>667,223=>611,224=>556,225=>556,226=>556,227=>556,228=>556,229=>556,230=>889,231=>556,232=>556,233=>556,234=>556,235=>556,236=>278,237=>278,238=>278,239=>278,240=>611,241=>611,242=>611,243=>611,244=>611,245=>611,246=>611,247=>584,248=>611,249=>611,250=>611,251=>611,252=>611,253=>556,254=>611,255=>556); -// --- EOF --- diff --git a/lib/combodo/tcpdf/fonts/helveticai.php b/lib/combodo/tcpdf/fonts/helveticai.php deleted file mode 100644 index 0404aebd6..000000000 --- a/lib/combodo/tcpdf/fonts/helveticai.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php -// TCPDF FONT FILE DESCRIPTION -$type='core'; -$name='Helvetica-Oblique'; -$up=-100; -$ut=50; -$dw=513; -$diff=''; -$enc=''; -$desc=array('Flags'=>96,'FontBBox'=>'[-170 -225 1116 931]','ItalicAngle'=>-12,'Ascent'=>931,'Descent'=>-225,'Leading'=>0,'CapHeight'=>718,'XHeight'=>523,'StemV'=>88,'StemH'=>76,'AvgWidth'=>513,'MaxWidth'=>1015,'MissingWidth'=>513); -$cw=array(0=>278,1=>278,2=>278,3=>278,4=>278,5=>278,6=>278,7=>278,8=>278,9=>278,10=>278,11=>278,12=>278,13=>278,14=>278,15=>278,16=>278,17=>278,18=>278,19=>278,20=>278,21=>278,22=>278,23=>278,24=>278,25=>278,26=>278,27=>278,28=>278,29=>278,30=>278,31=>278,32=>278,33=>278,34=>355,35=>556,36=>556,37=>889,38=>667,39=>191,40=>333,41=>333,42=>389,43=>584,44=>278,45=>333,46=>278,47=>278,48=>556,49=>556,50=>556,51=>556,52=>556,53=>556,54=>556,55=>556,56=>556,57=>556,58=>278,59=>278,60=>584,61=>584,62=>584,63=>556,64=>1015,65=>667,66=>667,67=>722,68=>722,69=>667,70=>611,71=>778,72=>722,73=>278,74=>500,75=>667,76=>556,77=>833,78=>722,79=>778,80=>667,81=>778,82=>722,83=>667,84=>611,85=>722,86=>667,87=>944,88=>667,89=>667,90=>611,91=>278,92=>278,93=>278,94=>469,95=>556,96=>333,97=>556,98=>556,99=>500,100=>556,101=>556,102=>278,103=>556,104=>556,105=>222,106=>222,107=>500,108=>222,109=>833,110=>556,111=>556,112=>556,113=>556,114=>333,115=>500,116=>278,117=>556,118=>500,119=>722,120=>500,121=>500,122=>500,123=>334,124=>260,125=>334,126=>584,127=>350,128=>556,129=>350,130=>222,131=>556,132=>333,133=>1000,134=>556,135=>556,136=>333,137=>1000,138=>667,139=>333,140=>1000,141=>350,142=>611,143=>350,144=>350,145=>222,146=>222,147=>333,148=>333,149=>350,150=>556,151=>1000,152=>333,153=>1000,154=>500,155=>333,156=>944,157=>350,158=>500,159=>667,160=>278,161=>333,162=>556,163=>556,164=>556,165=>556,166=>260,167=>556,168=>333,169=>737,170=>370,171=>556,172=>584,173=>333,174=>737,175=>333,176=>400,177=>584,178=>333,179=>333,180=>333,181=>556,182=>537,183=>278,184=>333,185=>333,186=>365,187=>556,188=>834,189=>834,190=>834,191=>611,192=>667,193=>667,194=>667,195=>667,196=>667,197=>667,198=>1000,199=>722,200=>667,201=>667,202=>667,203=>667,204=>278,205=>278,206=>278,207=>278,208=>722,209=>722,210=>778,211=>778,212=>778,213=>778,214=>778,215=>584,216=>778,217=>722,218=>722,219=>722,220=>722,221=>667,222=>667,223=>611,224=>556,225=>556,226=>556,227=>556,228=>556,229=>556,230=>889,231=>500,232=>556,233=>556,234=>556,235=>556,236=>278,237=>278,238=>278,239=>278,240=>556,241=>556,242=>556,243=>556,244=>556,245=>556,246=>556,247=>584,248=>611,249=>556,250=>556,251=>556,252=>556,253=>500,254=>556,255=>500); -// --- EOF --- diff --git a/lib/combodo/tcpdf/fonts/symbol.php b/lib/combodo/tcpdf/fonts/symbol.php deleted file mode 100644 index 15f7f1ddd..000000000 --- a/lib/combodo/tcpdf/fonts/symbol.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php -// TCPDF FONT FILE DESCRIPTION -$type='core'; -$name='Symbol'; -$up=-100; -$ut=50; -$dw=587; -$diff=''; -$enc=''; -$desc=array('Flags'=>4,'FontBBox'=>'[-180 -293 1090 1010]','ItalicAngle'=>0,'Ascent'=>1010,'Descent'=>-293,'Leading'=>0,'CapHeight'=>1010,'StemV'=>85,'StemH'=>92,'AvgWidth'=>587,'MaxWidth'=>1042,'MissingWidth'=>587); -$cw=array(0=>587,1=>587,2=>587,3=>587,4=>587,5=>587,6=>587,7=>587,8=>587,9=>587,10=>587,11=>587,12=>587,13=>587,14=>587,15=>587,16=>587,17=>587,18=>587,19=>587,20=>587,21=>587,22=>587,23=>587,24=>587,25=>587,26=>587,27=>587,28=>587,29=>587,30=>587,31=>587,32=>250,33=>333,34=>713,35=>500,36=>549,37=>833,38=>778,39=>439,40=>333,41=>333,42=>500,43=>549,44=>250,45=>549,46=>250,47=>278,48=>500,49=>500,50=>500,51=>500,52=>500,53=>500,54=>500,55=>500,56=>500,57=>500,58=>278,59=>278,60=>549,61=>549,62=>549,63=>444,64=>549,65=>722,66=>667,67=>722,68=>612,69=>611,70=>763,71=>603,72=>722,73=>333,74=>631,75=>722,76=>686,77=>889,78=>722,79=>722,80=>768,81=>741,82=>556,83=>592,84=>611,85=>690,86=>439,87=>768,88=>645,89=>795,90=>611,91=>333,92=>863,93=>333,94=>658,95=>500,96=>500,97=>631,98=>549,99=>549,100=>494,101=>439,102=>521,103=>411,104=>603,105=>329,106=>603,107=>549,108=>549,109=>576,110=>521,111=>549,112=>549,113=>521,114=>549,115=>603,116=>439,117=>576,118=>713,119=>686,120=>493,121=>686,122=>494,123=>480,124=>200,125=>480,126=>549,127=>587,128=>587,129=>587,130=>587,131=>587,132=>587,133=>587,134=>587,135=>587,136=>587,137=>587,138=>587,139=>587,140=>587,141=>587,142=>587,143=>587,144=>587,145=>587,146=>587,147=>587,148=>587,149=>587,150=>587,151=>587,152=>587,153=>587,154=>587,155=>587,156=>587,157=>587,158=>587,159=>587,160=>750,161=>620,162=>247,163=>549,164=>167,165=>713,166=>500,167=>753,168=>753,169=>753,170=>753,171=>1042,172=>987,173=>603,174=>987,175=>603,176=>400,177=>549,178=>411,179=>549,180=>549,181=>713,182=>494,183=>460,184=>549,185=>549,186=>549,187=>549,188=>1000,189=>603,190=>1000,191=>658,192=>823,193=>686,194=>795,195=>987,196=>768,197=>768,198=>823,199=>768,200=>768,201=>713,202=>713,203=>713,204=>713,205=>713,206=>713,207=>713,208=>768,209=>713,210=>790,211=>790,212=>890,213=>823,214=>549,215=>250,216=>713,217=>603,218=>603,219=>1042,220=>987,221=>603,222=>987,223=>603,224=>494,225=>329,226=>790,227=>790,228=>786,229=>713,230=>384,231=>384,232=>384,233=>384,234=>384,235=>384,236=>494,237=>494,238=>494,239=>494,240=>587,241=>329,242=>274,243=>686,244=>686,245=>686,246=>384,247=>384,248=>384,249=>384,250=>384,251=>384,252=>494,253=>494,254=>494,255=>587); -// --- EOF --- diff --git a/lib/combodo/tcpdf/fonts/times.php b/lib/combodo/tcpdf/fonts/times.php deleted file mode 100644 index cfcaf06cc..000000000 --- a/lib/combodo/tcpdf/fonts/times.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php -// TCPDF FONT FILE DESCRIPTION -$type='core'; -$name='Times-Roman'; -$up=-100; -$ut=50; -$dw=495; -$diff=''; -$enc=''; -$desc=array('Flags'=>32,'FontBBox'=>'[-168 -218 1000 898]','ItalicAngle'=>0,'Ascent'=>898,'Descent'=>-218,'Leading'=>0,'CapHeight'=>662,'XHeight'=>450,'StemV'=>84,'StemH'=>28,'AvgWidth'=>495,'MaxWidth'=>1000,'MissingWidth'=>495); -$cw=array(0=>250,1=>250,2=>250,3=>250,4=>250,5=>250,6=>250,7=>250,8=>250,9=>250,10=>250,11=>250,12=>250,13=>250,14=>250,15=>250,16=>250,17=>250,18=>250,19=>250,20=>250,21=>250,22=>250,23=>250,24=>250,25=>250,26=>250,27=>250,28=>250,29=>250,30=>250,31=>250,32=>250,33=>333,34=>408,35=>500,36=>500,37=>833,38=>778,39=>180,40=>333,41=>333,42=>500,43=>564,44=>250,45=>333,46=>250,47=>278,48=>500,49=>500,50=>500,51=>500,52=>500,53=>500,54=>500,55=>500,56=>500,57=>500,58=>278,59=>278,60=>564,61=>564,62=>564,63=>444,64=>921,65=>722,66=>667,67=>667,68=>722,69=>611,70=>556,71=>722,72=>722,73=>333,74=>389,75=>722,76=>611,77=>889,78=>722,79=>722,80=>556,81=>722,82=>667,83=>556,84=>611,85=>722,86=>722,87=>944,88=>722,89=>722,90=>611,91=>333,92=>278,93=>333,94=>469,95=>500,96=>333,97=>444,98=>500,99=>444,100=>500,101=>444,102=>333,103=>500,104=>500,105=>278,106=>278,107=>500,108=>278,109=>778,110=>500,111=>500,112=>500,113=>500,114=>333,115=>389,116=>278,117=>500,118=>500,119=>722,120=>500,121=>500,122=>444,123=>480,124=>200,125=>480,126=>541,127=>350,128=>500,129=>350,130=>333,131=>500,132=>444,133=>1000,134=>500,135=>500,136=>333,137=>1000,138=>556,139=>333,140=>889,141=>350,142=>611,143=>350,144=>350,145=>333,146=>333,147=>444,148=>444,149=>350,150=>500,151=>1000,152=>333,153=>980,154=>389,155=>333,156=>722,157=>350,158=>444,159=>722,160=>250,161=>333,162=>500,163=>500,164=>500,165=>500,166=>200,167=>500,168=>333,169=>760,170=>276,171=>500,172=>564,173=>333,174=>760,175=>333,176=>400,177=>564,178=>300,179=>300,180=>333,181=>500,182=>453,183=>250,184=>333,185=>300,186=>310,187=>500,188=>750,189=>750,190=>750,191=>444,192=>722,193=>722,194=>722,195=>722,196=>722,197=>722,198=>889,199=>667,200=>611,201=>611,202=>611,203=>611,204=>333,205=>333,206=>333,207=>333,208=>722,209=>722,210=>722,211=>722,212=>722,213=>722,214=>722,215=>564,216=>722,217=>722,218=>722,219=>722,220=>722,221=>722,222=>556,223=>500,224=>444,225=>444,226=>444,227=>444,228=>444,229=>444,230=>667,231=>444,232=>444,233=>444,234=>444,235=>444,236=>278,237=>278,238=>278,239=>278,240=>500,241=>500,242=>500,243=>500,244=>500,245=>500,246=>500,247=>564,248=>500,249=>500,250=>500,251=>500,252=>500,253=>500,254=>500,255=>500); -// --- EOF --- diff --git a/lib/combodo/tcpdf/fonts/timesb.php b/lib/combodo/tcpdf/fonts/timesb.php deleted file mode 100644 index 9c41a7b51..000000000 --- a/lib/combodo/tcpdf/fonts/timesb.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php -// TCPDF FONT FILE DESCRIPTION -$type='core'; -$name='Times-Bold'; -$up=-100; -$ut=50; -$dw=516; -$diff=''; -$enc=''; -$desc=array('Flags'=>32,'FontBBox'=>'[-168 -218 1000 935]','ItalicAngle'=>0,'Ascent'=>935,'Descent'=>-218,'Leading'=>0,'CapHeight'=>676,'XHeight'=>461,'StemV'=>139,'StemH'=>44,'AvgWidth'=>516,'MaxWidth'=>1000,'MissingWidth'=>516); -$cw=array(0=>250,1=>250,2=>250,3=>250,4=>250,5=>250,6=>250,7=>250,8=>250,9=>250,10=>250,11=>250,12=>250,13=>250,14=>250,15=>250,16=>250,17=>250,18=>250,19=>250,20=>250,21=>250,22=>250,23=>250,24=>250,25=>250,26=>250,27=>250,28=>250,29=>250,30=>250,31=>250,32=>250,33=>333,34=>555,35=>500,36=>500,37=>1000,38=>833,39=>278,40=>333,41=>333,42=>500,43=>570,44=>250,45=>333,46=>250,47=>278,48=>500,49=>500,50=>500,51=>500,52=>500,53=>500,54=>500,55=>500,56=>500,57=>500,58=>333,59=>333,60=>570,61=>570,62=>570,63=>500,64=>930,65=>722,66=>667,67=>722,68=>722,69=>667,70=>611,71=>778,72=>778,73=>389,74=>500,75=>778,76=>667,77=>944,78=>722,79=>778,80=>611,81=>778,82=>722,83=>556,84=>667,85=>722,86=>722,87=>1000,88=>722,89=>722,90=>667,91=>333,92=>278,93=>333,94=>581,95=>500,96=>333,97=>500,98=>556,99=>444,100=>556,101=>444,102=>333,103=>500,104=>556,105=>278,106=>333,107=>556,108=>278,109=>833,110=>556,111=>500,112=>556,113=>556,114=>444,115=>389,116=>333,117=>556,118=>500,119=>722,120=>500,121=>500,122=>444,123=>394,124=>220,125=>394,126=>520,127=>350,128=>500,129=>350,130=>333,131=>500,132=>500,133=>1000,134=>500,135=>500,136=>333,137=>1000,138=>556,139=>333,140=>1000,141=>350,142=>667,143=>350,144=>350,145=>333,146=>333,147=>500,148=>500,149=>350,150=>500,151=>1000,152=>333,153=>1000,154=>389,155=>333,156=>722,157=>350,158=>444,159=>722,160=>250,161=>333,162=>500,163=>500,164=>500,165=>500,166=>220,167=>500,168=>333,169=>747,170=>300,171=>500,172=>570,173=>333,174=>747,175=>333,176=>400,177=>570,178=>300,179=>300,180=>333,181=>556,182=>540,183=>250,184=>333,185=>300,186=>330,187=>500,188=>750,189=>750,190=>750,191=>500,192=>722,193=>722,194=>722,195=>722,196=>722,197=>722,198=>1000,199=>722,200=>667,201=>667,202=>667,203=>667,204=>389,205=>389,206=>389,207=>389,208=>722,209=>722,210=>778,211=>778,212=>778,213=>778,214=>778,215=>570,216=>778,217=>722,218=>722,219=>722,220=>722,221=>722,222=>611,223=>556,224=>500,225=>500,226=>500,227=>500,228=>500,229=>500,230=>722,231=>444,232=>444,233=>444,234=>444,235=>444,236=>278,237=>278,238=>278,239=>278,240=>500,241=>556,242=>500,243=>500,244=>500,245=>500,246=>500,247=>570,248=>500,249=>556,250=>556,251=>556,252=>556,253=>500,254=>556,255=>500); -// --- EOF --- diff --git a/lib/combodo/tcpdf/fonts/timesbi.php b/lib/combodo/tcpdf/fonts/timesbi.php deleted file mode 100644 index 4feed7489..000000000 --- a/lib/combodo/tcpdf/fonts/timesbi.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php -// TCPDF FONT FILE DESCRIPTION -$type='core'; -$name='Times-BoldItalic'; -$up=-100; -$ut=50; -$dw=501; -$diff=''; -$enc=''; -$desc=array('Flags'=>96,'FontBBox'=>'[-200 -218 996 921]','ItalicAngle'=>-15,'Ascent'=>921,'Descent'=>-218,'Leading'=>0,'CapHeight'=>669,'XHeight'=>462,'StemV'=>121,'StemH'=>42,'AvgWidth'=>501,'MaxWidth'=>1000,'MissingWidth'=>501); -$cw=array(0=>250,1=>250,2=>250,3=>250,4=>250,5=>250,6=>250,7=>250,8=>250,9=>250,10=>250,11=>250,12=>250,13=>250,14=>250,15=>250,16=>250,17=>250,18=>250,19=>250,20=>250,21=>250,22=>250,23=>250,24=>250,25=>250,26=>250,27=>250,28=>250,29=>250,30=>250,31=>250,32=>250,33=>389,34=>555,35=>500,36=>500,37=>833,38=>778,39=>278,40=>333,41=>333,42=>500,43=>570,44=>250,45=>333,46=>250,47=>278,48=>500,49=>500,50=>500,51=>500,52=>500,53=>500,54=>500,55=>500,56=>500,57=>500,58=>333,59=>333,60=>570,61=>570,62=>570,63=>500,64=>832,65=>667,66=>667,67=>667,68=>722,69=>667,70=>667,71=>722,72=>778,73=>389,74=>500,75=>667,76=>611,77=>889,78=>722,79=>722,80=>611,81=>722,82=>667,83=>556,84=>611,85=>722,86=>667,87=>889,88=>667,89=>611,90=>611,91=>333,92=>278,93=>333,94=>570,95=>500,96=>333,97=>500,98=>500,99=>444,100=>500,101=>444,102=>333,103=>500,104=>556,105=>278,106=>278,107=>500,108=>278,109=>778,110=>556,111=>500,112=>500,113=>500,114=>389,115=>389,116=>278,117=>556,118=>444,119=>667,120=>500,121=>444,122=>389,123=>348,124=>220,125=>348,126=>570,127=>350,128=>500,129=>350,130=>333,131=>500,132=>500,133=>1000,134=>500,135=>500,136=>333,137=>1000,138=>556,139=>333,140=>944,141=>350,142=>611,143=>350,144=>350,145=>333,146=>333,147=>500,148=>500,149=>350,150=>500,151=>1000,152=>333,153=>1000,154=>389,155=>333,156=>722,157=>350,158=>389,159=>611,160=>250,161=>389,162=>500,163=>500,164=>500,165=>500,166=>220,167=>500,168=>333,169=>747,170=>266,171=>500,172=>606,173=>333,174=>747,175=>333,176=>400,177=>570,178=>300,179=>300,180=>333,181=>576,182=>500,183=>250,184=>333,185=>300,186=>300,187=>500,188=>750,189=>750,190=>750,191=>500,192=>667,193=>667,194=>667,195=>667,196=>667,197=>667,198=>944,199=>667,200=>667,201=>667,202=>667,203=>667,204=>389,205=>389,206=>389,207=>389,208=>722,209=>722,210=>722,211=>722,212=>722,213=>722,214=>722,215=>570,216=>722,217=>722,218=>722,219=>722,220=>722,221=>611,222=>611,223=>500,224=>500,225=>500,226=>500,227=>500,228=>500,229=>500,230=>722,231=>444,232=>444,233=>444,234=>444,235=>444,236=>278,237=>278,238=>278,239=>278,240=>500,241=>556,242=>500,243=>500,244=>500,245=>500,246=>500,247=>570,248=>500,249=>556,250=>556,251=>556,252=>556,253=>444,254=>500,255=>444); -// --- EOF --- diff --git a/lib/combodo/tcpdf/fonts/timesi.php b/lib/combodo/tcpdf/fonts/timesi.php deleted file mode 100644 index 1e8b67349..000000000 --- a/lib/combodo/tcpdf/fonts/timesi.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php -// TCPDF FONT FILE DESCRIPTION -$type='core'; -$name='Times-Italic'; -$up=-100; -$ut=50; -$dw=491; -$diff=''; -$enc=''; -$desc=array('Flags'=>96,'FontBBox'=>'[-169 -217 1010 883]','ItalicAngle'=>-15.5,'Ascent'=>883,'Descent'=>-217,'Leading'=>0,'CapHeight'=>653,'XHeight'=>441,'StemV'=>76,'StemH'=>32,'AvgWidth'=>491,'MaxWidth'=>1000,'MissingWidth'=>491); -$cw=array(0=>250,1=>250,2=>250,3=>250,4=>250,5=>250,6=>250,7=>250,8=>250,9=>250,10=>250,11=>250,12=>250,13=>250,14=>250,15=>250,16=>250,17=>250,18=>250,19=>250,20=>250,21=>250,22=>250,23=>250,24=>250,25=>250,26=>250,27=>250,28=>250,29=>250,30=>250,31=>250,32=>250,33=>333,34=>420,35=>500,36=>500,37=>833,38=>778,39=>214,40=>333,41=>333,42=>500,43=>675,44=>250,45=>333,46=>250,47=>278,48=>500,49=>500,50=>500,51=>500,52=>500,53=>500,54=>500,55=>500,56=>500,57=>500,58=>333,59=>333,60=>675,61=>675,62=>675,63=>500,64=>920,65=>611,66=>611,67=>667,68=>722,69=>611,70=>611,71=>722,72=>722,73=>333,74=>444,75=>667,76=>556,77=>833,78=>667,79=>722,80=>611,81=>722,82=>611,83=>500,84=>556,85=>722,86=>611,87=>833,88=>611,89=>556,90=>556,91=>389,92=>278,93=>389,94=>422,95=>500,96=>333,97=>500,98=>500,99=>444,100=>500,101=>444,102=>278,103=>500,104=>500,105=>278,106=>278,107=>444,108=>278,109=>722,110=>500,111=>500,112=>500,113=>500,114=>389,115=>389,116=>278,117=>500,118=>444,119=>667,120=>444,121=>444,122=>389,123=>400,124=>275,125=>400,126=>541,127=>350,128=>500,129=>350,130=>333,131=>500,132=>556,133=>889,134=>500,135=>500,136=>333,137=>1000,138=>500,139=>333,140=>944,141=>350,142=>556,143=>350,144=>350,145=>333,146=>333,147=>556,148=>556,149=>350,150=>500,151=>889,152=>333,153=>980,154=>389,155=>333,156=>667,157=>350,158=>389,159=>556,160=>250,161=>389,162=>500,163=>500,164=>500,165=>500,166=>275,167=>500,168=>333,169=>760,170=>276,171=>500,172=>675,173=>333,174=>760,175=>333,176=>400,177=>675,178=>300,179=>300,180=>333,181=>500,182=>523,183=>250,184=>333,185=>300,186=>310,187=>500,188=>750,189=>750,190=>750,191=>500,192=>611,193=>611,194=>611,195=>611,196=>611,197=>611,198=>889,199=>667,200=>611,201=>611,202=>611,203=>611,204=>333,205=>333,206=>333,207=>333,208=>722,209=>667,210=>722,211=>722,212=>722,213=>722,214=>722,215=>675,216=>722,217=>722,218=>722,219=>722,220=>722,221=>556,222=>611,223=>500,224=>500,225=>500,226=>500,227=>500,228=>500,229=>500,230=>667,231=>444,232=>444,233=>444,234=>444,235=>444,236=>278,237=>278,238=>278,239=>278,240=>500,241=>500,242=>500,243=>500,244=>500,245=>500,246=>500,247=>675,248=>500,249=>500,250=>500,251=>500,252=>500,253=>444,254=>500,255=>444); -// --- EOF --- diff --git a/lib/combodo/tcpdf/fonts/zapfdingbats.php b/lib/combodo/tcpdf/fonts/zapfdingbats.php deleted file mode 100644 index 4c0bd75d5..000000000 --- a/lib/combodo/tcpdf/fonts/zapfdingbats.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php -// TCPDF FONT FILE DESCRIPTION -$type='core'; -$name='ZapfDingbats'; -$up=-100; -$ut=50; -$dw=746; -$diff=''; -$enc=''; -$desc=array('Flags'=>4,'FontBBox'=>'[-1 -143 981 820]','ItalicAngle'=>0,'Ascent'=>820,'Descent'=>-143,'Leading'=>0,'CapHeight'=>820,'StemV'=>90,'StemH'=>28,'AvgWidth'=>746,'MaxWidth'=>1016,'MissingWidth'=>746); -$cw=array(0=>746,1=>746,2=>746,3=>746,4=>746,5=>746,6=>746,7=>746,8=>746,9=>746,10=>746,11=>746,12=>746,13=>746,14=>746,15=>746,16=>746,17=>746,18=>746,19=>746,20=>746,21=>746,22=>746,23=>746,24=>746,25=>746,26=>746,27=>746,28=>746,29=>746,30=>746,31=>746,32=>278,33=>974,34=>961,35=>974,36=>980,37=>719,38=>789,39=>790,40=>791,41=>690,42=>960,43=>939,44=>549,45=>855,46=>911,47=>933,48=>911,49=>945,50=>974,51=>755,52=>846,53=>762,54=>761,55=>571,56=>677,57=>763,58=>760,59=>759,60=>754,61=>494,62=>552,63=>537,64=>577,65=>692,66=>786,67=>788,68=>788,69=>790,70=>793,71=>794,72=>816,73=>823,74=>789,75=>841,76=>823,77=>833,78=>816,79=>831,80=>923,81=>744,82=>723,83=>749,84=>790,85=>792,86=>695,87=>776,88=>768,89=>792,90=>759,91=>707,92=>708,93=>682,94=>701,95=>826,96=>815,97=>789,98=>789,99=>707,100=>687,101=>696,102=>689,103=>786,104=>787,105=>713,106=>791,107=>785,108=>791,109=>873,110=>761,111=>762,112=>762,113=>759,114=>759,115=>892,116=>892,117=>788,118=>784,119=>438,120=>138,121=>277,122=>415,123=>392,124=>392,125=>668,126=>668,127=>746,128=>390,129=>390,130=>317,131=>317,132=>276,133=>276,134=>509,135=>509,136=>410,137=>410,138=>234,139=>234,140=>334,141=>334,142=>746,143=>746,144=>746,145=>746,146=>746,147=>746,148=>746,149=>746,150=>746,151=>746,152=>746,153=>746,154=>746,155=>746,156=>746,157=>746,158=>746,159=>746,160=>746,161=>732,162=>544,163=>544,164=>910,165=>667,166=>760,167=>760,168=>776,169=>595,170=>694,171=>626,172=>788,173=>788,174=>788,175=>788,176=>788,177=>788,178=>788,179=>788,180=>788,181=>788,182=>788,183=>788,184=>788,185=>788,186=>788,187=>788,188=>788,189=>788,190=>788,191=>788,192=>788,193=>788,194=>788,195=>788,196=>788,197=>788,198=>788,199=>788,200=>788,201=>788,202=>788,203=>788,204=>788,205=>788,206=>788,207=>788,208=>788,209=>788,210=>788,211=>788,212=>894,213=>838,214=>1016,215=>458,216=>748,217=>924,218=>748,219=>918,220=>927,221=>928,222=>928,223=>834,224=>873,225=>828,226=>924,227=>924,228=>917,229=>930,230=>931,231=>463,232=>883,233=>836,234=>836,235=>867,236=>867,237=>696,238=>696,239=>874,240=>746,241=>874,242=>760,243=>946,244=>771,245=>865,246=>771,247=>888,248=>967,249=>888,250=>831,251=>873,252=>927,253=>970,254=>918,255=>746); -// --- EOF --- diff --git a/lib/combodo/tcpdf/include/barcodes/datamatrix.php b/lib/combodo/tcpdf/include/barcodes/datamatrix.php deleted file mode 100644 index 38bd625f7..000000000 --- a/lib/combodo/tcpdf/include/barcodes/datamatrix.php +++ /dev/null @@ -1,1176 +0,0 @@ -<?php -//============================================================+ -// File name : datamatrix.php -// Version : 1.0.008 -// Begin : 2010-06-07 -// Last Update : 2014-05-06 -// Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com -// License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html) -// ------------------------------------------------------------------- -// Copyright (C) 2010-2014 Nicola Asuni - Tecnick.com LTD -// -// This file is part of TCPDF software library. -// -// TCPDF is free software: you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// TCPDF is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with TCPDF. If not, see <http://www.gnu.org/licenses/>. -// -// See LICENSE.TXT file for more information. -// ------------------------------------------------------------------- -// -// DESCRIPTION : -// -// Class to create DataMatrix ECC 200 barcode arrays for TCPDF class. -// DataMatrix (ISO/IEC 16022:2006) is a 2-dimensional bar code. -//============================================================+ - -/** -* @file -* Class to create DataMatrix ECC 200 barcode arrays for TCPDF class. -* DataMatrix (ISO/IEC 16022:2006) is a 2-dimensional bar code. -* -* @package com.tecnick.tcpdf -* @author Nicola Asuni -* @version 1.0.008 -*/ - -// custom definitions -if (!defined('DATAMATRIXDEFS')) { - - /** - * Indicate that definitions for this class are set - */ - define('DATAMATRIXDEFS', true); - - // ----------------------------------------------------- - -} // end of custom definitions - -// #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*# - - -/** -* ASCII encoding: ASCII character 0 to 127 (1 byte per CW) -*/ -define('ENC_ASCII', 0); - -/** -* C40 encoding: Upper-case alphanumeric (3/2 bytes per CW) -*/ -define('ENC_C40', 1); - -/** -* TEXT encoding: Lower-case alphanumeric (3/2 bytes per CW) -*/ -define('ENC_TXT', 2); - -/** -* X12 encoding: ANSI X12 (3/2 byte per CW) -*/ -define('ENC_X12', 3); - -/** -* EDIFACT encoding: ASCII character 32 to 94 (4/3 bytes per CW) -*/ -define('ENC_EDF', 4); - -/** -* BASE 256 encoding: ASCII character 0 to 255 (1 byte per CW) -*/ -define('ENC_BASE256', 5); - -/** -* ASCII extended encoding: ASCII character 128 to 255 (1/2 byte per CW) -*/ -define('ENC_ASCII_EXT', 6); - -/** -* ASCII number encoding: ASCII digits (2 bytes per CW) -*/ -define('ENC_ASCII_NUM', 7); - -/** -* @class Datamatrix -* Class to create DataMatrix ECC 200 barcode arrays for TCPDF class. -* DataMatrix (ISO/IEC 16022:2006) is a 2-dimensional bar code. -* -* @package com.tecnick.tcpdf -* @author Nicola Asuni -* @version 1.0.004 -*/ -class Datamatrix { - - /** - * Barcode array to be returned which is readable by TCPDF. - * @protected - */ - protected $barcode_array = array(); - - /** - * Store last used encoding for data codewords. - * @protected - */ - protected $last_enc = ENC_ASCII; - - /** - * Table of Data Matrix ECC 200 Symbol Attributes:<ul> - * <li>total matrix rows (including finder pattern)</li> - * <li>total matrix cols (including finder pattern)</li> - * <li>total matrix rows (without finder pattern)</li> - * <li>total matrix cols (without finder pattern)</li> - * <li>region data rows (with finder pattern)</li> - * <li>region data col (with finder pattern)</li> - * <li>region data rows (without finder pattern)</li> - * <li>region data col (without finder pattern)</li> - * <li>horizontal regions</li> - * <li>vertical regions</li> - * <li>regions</li> - * <li>data codewords</li> - * <li>error codewords</li> - * <li>blocks</li> - * <li>data codewords per block</li> - * <li>error codewords per block</li> - * </ul> - * @protected - */ - protected $symbattr = array( - // square form --------------------------------------------------------------------------------------- - array(0x00a,0x00a,0x008,0x008,0x00a,0x00a,0x008,0x008,0x001,0x001,0x001,0x003,0x005,0x001,0x003,0x005), // 10x10 - array(0x00c,0x00c,0x00a,0x00a,0x00c,0x00c,0x00a,0x00a,0x001,0x001,0x001,0x005,0x007,0x001,0x005,0x007), // 12x12 - array(0x00e,0x00e,0x00c,0x00c,0x00e,0x00e,0x00c,0x00c,0x001,0x001,0x001,0x008,0x00a,0x001,0x008,0x00a), // 14x14 - array(0x010,0x010,0x00e,0x00e,0x010,0x010,0x00e,0x00e,0x001,0x001,0x001,0x00c,0x00c,0x001,0x00c,0x00c), // 16x16 - array(0x012,0x012,0x010,0x010,0x012,0x012,0x010,0x010,0x001,0x001,0x001,0x012,0x00e,0x001,0x012,0x00e), // 18x18 - array(0x014,0x014,0x012,0x012,0x014,0x014,0x012,0x012,0x001,0x001,0x001,0x016,0x012,0x001,0x016,0x012), // 20x20 - array(0x016,0x016,0x014,0x014,0x016,0x016,0x014,0x014,0x001,0x001,0x001,0x01e,0x014,0x001,0x01e,0x014), // 22x22 - array(0x018,0x018,0x016,0x016,0x018,0x018,0x016,0x016,0x001,0x001,0x001,0x024,0x018,0x001,0x024,0x018), // 24x24 - array(0x01a,0x01a,0x018,0x018,0x01a,0x01a,0x018,0x018,0x001,0x001,0x001,0x02c,0x01c,0x001,0x02c,0x01c), // 26x26 - array(0x020,0x020,0x01c,0x01c,0x010,0x010,0x00e,0x00e,0x002,0x002,0x004,0x03e,0x024,0x001,0x03e,0x024), // 32x32 - array(0x024,0x024,0x020,0x020,0x012,0x012,0x010,0x010,0x002,0x002,0x004,0x056,0x02a,0x001,0x056,0x02a), // 36x36 - array(0x028,0x028,0x024,0x024,0x014,0x014,0x012,0x012,0x002,0x002,0x004,0x072,0x030,0x001,0x072,0x030), // 40x40 - array(0x02c,0x02c,0x028,0x028,0x016,0x016,0x014,0x014,0x002,0x002,0x004,0x090,0x038,0x001,0x090,0x038), // 44x44 - array(0x030,0x030,0x02c,0x02c,0x018,0x018,0x016,0x016,0x002,0x002,0x004,0x0ae,0x044,0x001,0x0ae,0x044), // 48x48 - array(0x034,0x034,0x030,0x030,0x01a,0x01a,0x018,0x018,0x002,0x002,0x004,0x0cc,0x054,0x002,0x066,0x02a), // 52x52 - array(0x040,0x040,0x038,0x038,0x010,0x010,0x00e,0x00e,0x004,0x004,0x010,0x118,0x070,0x002,0x08c,0x038), // 64x64 - array(0x048,0x048,0x040,0x040,0x012,0x012,0x010,0x010,0x004,0x004,0x010,0x170,0x090,0x004,0x05c,0x024), // 72x72 - array(0x050,0x050,0x048,0x048,0x014,0x014,0x012,0x012,0x004,0x004,0x010,0x1c8,0x0c0,0x004,0x072,0x030), // 80x80 - array(0x058,0x058,0x050,0x050,0x016,0x016,0x014,0x014,0x004,0x004,0x010,0x240,0x0e0,0x004,0x090,0x038), // 88x88 - array(0x060,0x060,0x058,0x058,0x018,0x018,0x016,0x016,0x004,0x004,0x010,0x2b8,0x110,0x004,0x0ae,0x044), // 96x96 - array(0x068,0x068,0x060,0x060,0x01a,0x01a,0x018,0x018,0x004,0x004,0x010,0x330,0x150,0x006,0x088,0x038), // 104x104 - array(0x078,0x078,0x06c,0x06c,0x014,0x014,0x012,0x012,0x006,0x006,0x024,0x41a,0x198,0x006,0x0af,0x044), // 120x120 - array(0x084,0x084,0x078,0x078,0x016,0x016,0x014,0x014,0x006,0x006,0x024,0x518,0x1f0,0x008,0x0a3,0x03e), // 132x132 - array(0x090,0x090,0x084,0x084,0x018,0x018,0x016,0x016,0x006,0x006,0x024,0x616,0x26c,0x00a,0x09c,0x03e), // 144x144 - // rectangular form (currently unused) --------------------------------------------------------------------------- - array(0x008,0x012,0x006,0x010,0x008,0x012,0x006,0x010,0x001,0x001,0x001,0x005,0x007,0x001,0x005,0x007), // 8x18 - array(0x008,0x020,0x006,0x01c,0x008,0x010,0x006,0x00e,0x001,0x002,0x002,0x00a,0x00b,0x001,0x00a,0x00b), // 8x32 - array(0x00c,0x01a,0x00a,0x018,0x00c,0x01a,0x00a,0x018,0x001,0x001,0x001,0x010,0x00e,0x001,0x010,0x00e), // 12x26 - array(0x00c,0x024,0x00a,0x020,0x00c,0x012,0x00a,0x010,0x001,0x002,0x002,0x00c,0x012,0x001,0x00c,0x012), // 12x36 - array(0x010,0x024,0x00e,0x020,0x010,0x012,0x00e,0x010,0x001,0x002,0x002,0x020,0x018,0x001,0x020,0x018), // 16x36 - array(0x010,0x030,0x00e,0x02c,0x010,0x018,0x00e,0x016,0x001,0x002,0x002,0x031,0x01c,0x001,0x031,0x01c) // 16x48 - ); - - /** - * Map encodation modes whit character sets. - * @protected - */ - protected $chset_id = array(ENC_C40 => 'C40', ENC_TXT => 'TXT', ENC_X12 =>'X12'); - - /** - * Basic set of characters for each encodation mode. - * @protected - */ - protected $chset = array( - 'C40' => array( // Basic set for C40 ---------------------------------------------------------------------------- - 'S1'=>0x00,'S2'=>0x01,'S3'=>0x02,0x20=>0x03,0x30=>0x04,0x31=>0x05,0x32=>0x06,0x33=>0x07,0x34=>0x08,0x35=>0x09, // - 0x36=>0x0a,0x37=>0x0b,0x38=>0x0c,0x39=>0x0d,0x41=>0x0e,0x42=>0x0f,0x43=>0x10,0x44=>0x11,0x45=>0x12,0x46=>0x13, // - 0x47=>0x14,0x48=>0x15,0x49=>0x16,0x4a=>0x17,0x4b=>0x18,0x4c=>0x19,0x4d=>0x1a,0x4e=>0x1b,0x4f=>0x1c,0x50=>0x1d, // - 0x51=>0x1e,0x52=>0x1f,0x53=>0x20,0x54=>0x21,0x55=>0x22,0x56=>0x23,0x57=>0x24,0x58=>0x25,0x59=>0x26,0x5a=>0x27),// - 'TXT' => array( // Basic set for TEXT --------------------------------------------------------------------------- - 'S1'=>0x00,'S2'=>0x01,'S3'=>0x02,0x20=>0x03,0x30=>0x04,0x31=>0x05,0x32=>0x06,0x33=>0x07,0x34=>0x08,0x35=>0x09, // - 0x36=>0x0a,0x37=>0x0b,0x38=>0x0c,0x39=>0x0d,0x61=>0x0e,0x62=>0x0f,0x63=>0x10,0x64=>0x11,0x65=>0x12,0x66=>0x13, // - 0x67=>0x14,0x68=>0x15,0x69=>0x16,0x6a=>0x17,0x6b=>0x18,0x6c=>0x19,0x6d=>0x1a,0x6e=>0x1b,0x6f=>0x1c,0x70=>0x1d, // - 0x71=>0x1e,0x72=>0x1f,0x73=>0x20,0x74=>0x21,0x75=>0x22,0x76=>0x23,0x77=>0x24,0x78=>0x25,0x79=>0x26,0x7a=>0x27),// - 'SH1' => array( // Shift 1 set ---------------------------------------------------------------------------------- - 0x00=>0x00,0x01=>0x01,0x02=>0x02,0x03=>0x03,0x04=>0x04,0x05=>0x05,0x06=>0x06,0x07=>0x07,0x08=>0x08,0x09=>0x09, // - 0x0a=>0x0a,0x0b=>0x0b,0x0c=>0x0c,0x0d=>0x0d,0x0e=>0x0e,0x0f=>0x0f,0x10=>0x10,0x11=>0x11,0x12=>0x12,0x13=>0x13, // - 0x14=>0x14,0x15=>0x15,0x16=>0x16,0x17=>0x17,0x18=>0x18,0x19=>0x19,0x1a=>0x1a,0x1b=>0x1b,0x1c=>0x1c,0x1d=>0x1d, // - 0x1e=>0x1e,0x1f=>0x1f), // - 'SH2' => array( // Shift 2 set ---------------------------------------------------------------------------------- - 0x21=>0x00,0x22=>0x01,0x23=>0x02,0x24=>0x03,0x25=>0x04,0x26=>0x05,0x27=>0x06,0x28=>0x07,0x29=>0x08,0x2a=>0x09, // - 0x2b=>0x0a,0x2c=>0x0b,0x2d=>0x0c,0x2e=>0x0d,0x2f=>0x0e,0x3a=>0x0f,0x3b=>0x10,0x3c=>0x11,0x3d=>0x12,0x3e=>0x13, // - 0x3f=>0x14,0x40=>0x15,0x5b=>0x16,0x5c=>0x17,0x5d=>0x18,0x5e=>0x19,0x5f=>0x1a,'F1'=>0x1b,'US'=>0x1e), // - 'S3C' => array( // Shift 3 set for C40 -------------------------------------------------------------------------- - 0x60=>0x00,0x61=>0x01,0x62=>0x02,0x63=>0x03,0x64=>0x04,0x65=>0x05,0x66=>0x06,0x67=>0x07,0x68=>0x08,0x69=>0x09, // - 0x6a=>0x0a,0x6b=>0x0b,0x6c=>0x0c,0x6d=>0x0d,0x6e=>0x0e,0x6f=>0x0f,0x70=>0x10,0x71=>0x11,0x72=>0x12,0x73=>0x13, // - 0x74=>0x14,0x75=>0x15,0x76=>0x16,0x77=>0x17,0x78=>0x18,0x79=>0x19,0x7a=>0x1a,0x7b=>0x1b,0x7c=>0x1c,0x7d=>0x1d, // - 0x7e=>0x1e,0x7f=>0x1f), - 'S3T' => array( // Shift 3 set for TEXT ------------------------------------------------------------------------- - 0x60=>0x00,0x41=>0x01,0x42=>0x02,0x43=>0x03,0x44=>0x04,0x45=>0x05,0x46=>0x06,0x47=>0x07,0x48=>0x08,0x49=>0x09, // - 0x4a=>0x0a,0x4b=>0x0b,0x4c=>0x0c,0x4d=>0x0d,0x4e=>0x0e,0x4f=>0x0f,0x50=>0x10,0x51=>0x11,0x52=>0x12,0x53=>0x13, // - 0x54=>0x14,0x55=>0x15,0x56=>0x16,0x57=>0x17,0x58=>0x18,0x59=>0x19,0x5a=>0x1a,0x7b=>0x1b,0x7c=>0x1c,0x7d=>0x1d, // - 0x7e=>0x1e,0x7f=>0x1f), // - 'X12' => array( // Set for X12 ---------------------------------------------------------------------------------- - 0x0d=>0x00,0x2a=>0x01,0x3e=>0x02,0x20=>0x03,0x30=>0x04,0x31=>0x05,0x32=>0x06,0x33=>0x07,0x34=>0x08,0x35=>0x09, // - 0x36=>0x0a,0x37=>0x0b,0x38=>0x0c,0x39=>0x0d,0x41=>0x0e,0x42=>0x0f,0x43=>0x10,0x44=>0x11,0x45=>0x12,0x46=>0x13, // - 0x47=>0x14,0x48=>0x15,0x49=>0x16,0x4a=>0x17,0x4b=>0x18,0x4c=>0x19,0x4d=>0x1a,0x4e=>0x1b,0x4f=>0x1c,0x50=>0x1d, // - 0x51=>0x1e,0x52=>0x1f,0x53=>0x20,0x54=>0x21,0x55=>0x22,0x56=>0x23,0x57=>0x24,0x58=>0x25,0x59=>0x26,0x5a=>0x27) // - ); - -// ----------------------------------------------------------------------------- - - /** - * This is the class constructor. - * Creates a datamatrix object - * @param string $code Code to represent using Datamatrix. - * @public - */ - public function __construct($code) { - $barcode_array = array(); - if ((is_null($code)) OR ($code == '\0') OR ($code == '')) { - return false; - } - // get data codewords - $cw = $this->getHighLevelEncoding($code); - // number of data codewords - $nd = count($cw); - // check size - if ($nd > 1558) { - return false; - } - // get minimum required matrix size. - foreach ($this->symbattr as $params) { - if ($params[11] >= $nd) { - break; - } - } - if ($params[11] < $nd) { - // too much data - return false; - } elseif ($params[11] > $nd) { - // add padding - if ((($params[11] - $nd) > 1) AND ($cw[($nd - 1)] != 254)) { - if ($this->last_enc == ENC_EDF) { - // switch to ASCII encoding - $cw[] = 124; - ++$nd; - } elseif (($this->last_enc != ENC_ASCII) AND ($this->last_enc != ENC_BASE256)) { - // switch to ASCII encoding - $cw[] = 254; - ++$nd; - } - } - if ($params[11] > $nd) { - // add first pad - $cw[] = 129; - ++$nd; - // add remaining pads - for ($i = $nd; $i < $params[11]; ++$i) { - $cw[] = $this->get253StateCodeword(129, $i); - } - } - } - // add error correction codewords - $cw = $this->getErrorCorrection($cw, $params[13], $params[14], $params[15]); - // initialize empty arrays - $grid = array_fill(0, ($params[2] * $params[3]), 0); - // get placement map - $places = $this->getPlacementMap($params[2], $params[3]); - // fill the grid with data - $grid = array(); - $i = 0; - // region data row max index - $rdri = ($params[4] - 1); - // region data column max index - $rdci = ($params[5] - 1); - // for each vertical region - for ($vr = 0; $vr < $params[9]; ++$vr) { - // for each row on region - for ($r = 0; $r < $params[4]; ++$r) { - // get row - $row = (($vr * $params[4]) + $r); - // for each horizontal region - for ($hr = 0; $hr < $params[8]; ++$hr) { - // for each column on region - for ($c = 0; $c < $params[5]; ++$c) { - // get column - $col = (($hr * $params[5]) + $c); - // braw bits by case - if ($r == 0) { - // top finder pattern - if ($c % 2) { - $grid[$row][$col] = 0; - } else { - $grid[$row][$col] = 1; - } - } elseif ($r == $rdri) { - // bottom finder pattern - $grid[$row][$col] = 1; - } elseif ($c == 0) { - // left finder pattern - $grid[$row][$col] = 1; - } elseif ($c == $rdci) { - // right finder pattern - if ($r % 2) { - $grid[$row][$col] = 1; - } else { - $grid[$row][$col] = 0; - } - } else { // data bit - if ($places[$i] < 2) { - $grid[$row][$col] = $places[$i]; - } else { - // codeword ID - $cw_id = (floor($places[$i] / 10) - 1); - // codeword BIT mask - $cw_bit = pow(2, (8 - ($places[$i] % 10))); - $grid[$row][$col] = (($cw[$cw_id] & $cw_bit) == 0) ? 0 : 1; - } - ++$i; - } - } - } - } - } - $this->barcode_array['num_rows'] = $params[0]; - $this->barcode_array['num_cols'] = $params[1]; - $this->barcode_array['bcode'] = $grid; - } - - /** - * Returns a barcode array which is readable by TCPDF - * @return array barcode array readable by TCPDF; - * @public - */ - public function getBarcodeArray() { - return $this->barcode_array; - } - - /** - * Product of two numbers in a Power-of-Two Galois Field - * @param int $a first number to multiply. - * @param int $b second number to multiply. - * @param array $log Log table. - * @param array $alog Anti-Log table. - * @param int $gf Number of Factors of the Reed-Solomon polynomial. - * @return int product - * @protected - */ - protected function getGFProduct($a, $b, $log, $alog, $gf) { - if (($a == 0) OR ($b == 0)) { - return 0; - } - return ($alog[($log[$a] + $log[$b]) % ($gf - 1)]); - } - - /** - * Add error correction codewords to data codewords array (ANNEX E). - * @param array $wd Array of datacodewords. - * @param int $nb Number of blocks. - * @param int $nd Number of data codewords per block. - * @param int $nc Number of correction codewords per block. - * @param int $gf numner of fields on log/antilog table (power of 2). - * @param int $pp The value of its prime modulus polynomial (301 for ECC200). - * @return array data codewords + error codewords - * @protected - */ - protected function getErrorCorrection($wd, $nb, $nd, $nc, $gf=256, $pp=301) { - // generate the log ($log) and antilog ($alog) tables - $log[0] = 0; - $alog[0] = 1; - for ($i = 1; $i < $gf; ++$i) { - $alog[$i] = ($alog[($i - 1)] * 2); - if ($alog[$i] >= $gf) { - $alog[$i] ^= $pp; - } - $log[$alog[$i]] = $i; - } - ksort($log); - // generate the polynomial coefficients (c) - $c = array_fill(0, ($nc + 1), 0); - $c[0] = 1; - for ($i = 1; $i <= $nc; ++$i) { - $c[$i] = $c[($i-1)]; - for ($j = ($i - 1); $j >= 1; --$j) { - $c[$j] = $c[($j - 1)] ^ $this->getGFProduct($c[$j], $alog[$i], $log, $alog, $gf); - } - $c[0] = $this->getGFProduct($c[0], $alog[$i], $log, $alog, $gf); - } - ksort($c); - // total number of data codewords - $num_wd = ($nb * $nd); - // total number of error codewords - $num_we = ($nb * $nc); - // for each block - for ($b = 0; $b < $nb; ++$b) { - // create interleaved data block - $block = array(); - for ($n = $b; $n < $num_wd; $n += $nb) { - $block[] = $wd[$n]; - } - // initialize error codewords - $we = array_fill(0, ($nc + 1), 0); - // calculate error correction codewords for this block - for ($i = 0; $i < $nd; ++$i) { - $k = ($we[0] ^ $block[$i]); - for ($j = 0; $j < $nc; ++$j) { - $we[$j] = ($we[($j + 1)] ^ $this->getGFProduct($k, $c[($nc - $j - 1)], $log, $alog, $gf)); - } - } - // add error codewords at the end of data codewords - $j = 0; - for ($i = $b; $i < $num_we; $i += $nb) { - $wd[($num_wd + $i)] = $we[$j]; - ++$j; - } - } - // reorder codewords - ksort($wd); - return $wd; - } - - /** - * Return the 253-state codeword - * @param int $cwpad Pad codeword. - * @param int $cwpos Number of data codewords from the beginning of encoded data. - * @return int pad codeword - * @protected - */ - protected function get253StateCodeword($cwpad, $cwpos) { - $pad = ($cwpad + (((149 * $cwpos) % 253) + 1)); - if ($pad > 254) { - $pad -= 254; - } - return $pad; - } - - /** - * Return the 255-state codeword - * @param int $cwpad Pad codeword. - * @param int $cwpos Number of data codewords from the beginning of encoded data. - * @return int pad codeword - * @protected - */ - protected function get255StateCodeword($cwpad, $cwpos) { - $pad = ($cwpad + (((149 * $cwpos) % 255) + 1)); - if ($pad > 255) { - $pad -= 256; - } - return $pad; - } - - /** - * Returns true if the char belongs to the selected mode - * @param int $chr Character (byte) to check. - * @param int $mode Current encoding mode. - * @return boolean true if the char is of the selected mode. - * @protected - */ - protected function isCharMode($chr, $mode) { - $status = false; - switch ($mode) { - case ENC_ASCII: { // ASCII character 0 to 127 - $status = (($chr >= 0) AND ($chr <= 127)); - break; - } - case ENC_C40: { // Upper-case alphanumeric - $status = (($chr == 32) OR (($chr >= 48) AND ($chr <= 57)) OR (($chr >= 65) AND ($chr <= 90))); - break; - } - case ENC_TXT: { // Lower-case alphanumeric - $status = (($chr == 32) OR (($chr >= 48) AND ($chr <= 57)) OR (($chr >= 97) AND ($chr <= 122))); - break; - } - case ENC_X12: { // ANSI X12 - $status = (($chr == 13) OR ($chr == 42) OR ($chr == 62)); - break; - } - case ENC_EDF: { // ASCII character 32 to 94 - $status = (($chr >= 32) AND ($chr <= 94)); - break; - } - case ENC_BASE256: { // Function character (FNC1, Structured Append, Reader Program, or Code Page) - $status = (($chr == 232) OR ($chr == 233) OR ($chr == 234) OR ($chr == 241)); - break; - } - case ENC_ASCII_EXT: { // ASCII character 128 to 255 - $status = (($chr >= 128) AND ($chr <= 255)); - break; - } - case ENC_ASCII_NUM: { // ASCII digits - $status = (($chr >= 48) AND ($chr <= 57)); - break; - } - } - return $status; - } - - /** - * The look-ahead test scans the data to be encoded to find the best mode (Annex P - steps from J to S). - * @param string $data data to encode - * @param int $pos current position - * @param int $mode current encoding mode - * @return int encoding mode - * @protected - */ - protected function lookAheadTest($data, $pos, $mode) { - $data_length = strlen($data); - if ($pos >= $data_length) { - return $mode; - } - $charscount = 0; // count processed chars - // STEP J - if ($mode == ENC_ASCII) { - $numch = array(0, 1, 1, 1, 1, 1.25); - } else { - $numch = array(1, 2, 2, 2, 2, 2.25); - $numch[$mode] = 0; - } - while (true) { - // STEP K - if (($pos + $charscount) == $data_length) { - if ($numch[ENC_ASCII] <= ceil(min($numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_EDF], $numch[ENC_BASE256]))) { - return ENC_ASCII; - } - if ($numch[ENC_BASE256] < ceil(min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_EDF]))) { - return ENC_BASE256; - } - if ($numch[ENC_EDF] < ceil(min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_BASE256]))) { - return ENC_EDF; - } - if ($numch[ENC_TXT] < ceil(min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_X12], $numch[ENC_EDF], $numch[ENC_BASE256]))) { - return ENC_TXT; - } - if ($numch[ENC_X12] < ceil(min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_EDF], $numch[ENC_BASE256]))) { - return ENC_X12; - } - return ENC_C40; - } - // get char - $chr = ord($data[$pos + $charscount]); - $charscount++; - // STEP L - if ($this->isCharMode($chr, ENC_ASCII_NUM)) { - $numch[ENC_ASCII] += (1 / 2); - } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) { - $numch[ENC_ASCII] = ceil($numch[ENC_ASCII]); - $numch[ENC_ASCII] += 2; - } else { - $numch[ENC_ASCII] = ceil($numch[ENC_ASCII]); - $numch[ENC_ASCII] += 1; - } - // STEP M - if ($this->isCharMode($chr, ENC_C40)) { - $numch[ENC_C40] += (2 / 3); - } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) { - $numch[ENC_C40] += (8 / 3); - } else { - $numch[ENC_C40] += (4 / 3); - } - // STEP N - if ($this->isCharMode($chr, ENC_TXT)) { - $numch[ENC_TXT] += (2 / 3); - } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) { - $numch[ENC_TXT] += (8 / 3); - } else { - $numch[ENC_TXT] += (4 / 3); - } - // STEP O - if ($this->isCharMode($chr, ENC_X12) OR $this->isCharMode($chr, ENC_C40)) { - $numch[ENC_X12] += (2 / 3); - } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) { - $numch[ENC_X12] += (13 / 3); - } else { - $numch[ENC_X12] += (10 / 3); - } - // STEP P - if ($this->isCharMode($chr, ENC_EDF)) { - $numch[ENC_EDF] += (3 / 4); - } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) { - $numch[ENC_EDF] += (17 / 4); - } else { - $numch[ENC_EDF] += (13 / 4); - } - // STEP Q - if ($this->isCharMode($chr, ENC_BASE256)) { - $numch[ENC_BASE256] += 4; - } else { - $numch[ENC_BASE256] += 1; - } - // STEP R - if ($charscount >= 4) { - if (($numch[ENC_ASCII] + 1) <= min($numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_EDF], $numch[ENC_BASE256])) { - return ENC_ASCII; - } - if ((($numch[ENC_BASE256] + 1) <= $numch[ENC_ASCII]) - OR (($numch[ENC_BASE256] + 1) < min($numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_EDF]))) { - return ENC_BASE256; - } - if (($numch[ENC_EDF] + 1) < min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_BASE256])) { - return ENC_EDF; - } - if (($numch[ENC_TXT] + 1) < min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_X12], $numch[ENC_EDF], $numch[ENC_BASE256])) { - return ENC_TXT; - } - if (($numch[ENC_X12] + 1) < min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_EDF], $numch[ENC_BASE256])) { - return ENC_X12; - } - if (($numch[ENC_C40] + 1) < min($numch[ENC_ASCII], $numch[ENC_TXT], $numch[ENC_EDF], $numch[ENC_BASE256])) { - if ($numch[ENC_C40] < $numch[ENC_X12]) { - return ENC_C40; - } - if ($numch[ENC_C40] == $numch[ENC_X12]) { - $k = ($pos + $charscount + 1); - while ($k < $data_length) { - $tmpchr = ord($data[$k]); - if ($this->isCharMode($tmpchr, ENC_X12)) { - return ENC_X12; - } elseif (!($this->isCharMode($tmpchr, ENC_X12) OR $this->isCharMode($tmpchr, ENC_C40))) { - break; - } - ++$k; - } - return ENC_C40; - } - } - } - } // end of while - } - - /** - * Get the switching codeword to a new encoding mode (latch codeword) - * @param int $mode New encoding mode. - * @return int Switch codeword. - * @protected - */ - protected function getSwitchEncodingCodeword($mode) { - switch ($mode) { - case ENC_ASCII: { // ASCII character 0 to 127 - $cw = 254; - if ($this->last_enc == ENC_EDF) { - $cw = 124; - } - break; - } - case ENC_C40: { // Upper-case alphanumeric - $cw = 230; - break; - } - case ENC_TXT: { // Lower-case alphanumeric - $cw = 239; - break; - } - case ENC_X12: { // ANSI X12 - $cw = 238; - break; - } - case ENC_EDF: { // ASCII character 32 to 94 - $cw = 240; - break; - } - case ENC_BASE256: { // Function character (FNC1, Structured Append, Reader Program, or Code Page) - $cw = 231; - break; - } - } - return $cw; - } - - /** - * Choose the minimum matrix size and return the max number of data codewords. - * @param int $numcw Number of current codewords. - * @return int number of data codewords in matrix - * @protected - */ - protected function getMaxDataCodewords($numcw) { - foreach ($this->symbattr as $key => $matrix) { - if ($matrix[11] >= $numcw) { - return $matrix[11]; - } - } - return 0; - } - - /** - * Get high level encoding using the minimum symbol data characters for ECC 200 - * @param string $data data to encode - * @return array of codewords - * @protected - */ - protected function getHighLevelEncoding($data) { - // STEP A. Start in ASCII encodation. - $enc = ENC_ASCII; // current encoding mode - $pos = 0; // current position - $cw = array(); // array of codewords to be returned - $cw_num = 0; // number of data codewords - $data_length = strlen($data); // number of chars - while ($pos < $data_length) { - // set last used encoding - $this->last_enc = $enc; - switch ($enc) { - case ENC_ASCII: { // STEP B. While in ASCII encodation - if (($data_length > 1) AND ($pos < ($data_length - 1)) AND ($this->isCharMode(ord($data[$pos]), ENC_ASCII_NUM) AND $this->isCharMode(ord($data[$pos + 1]), ENC_ASCII_NUM))) { - // 1. If the next data sequence is at least 2 consecutive digits, encode the next two digits as a double digit in ASCII mode. - $cw[] = (intval(substr($data, $pos, 2)) + 130); - ++$cw_num; - $pos += 2; - } else { - // 2. If the look-ahead test (starting at step J) indicates another mode, switch to that mode. - $newenc = $this->lookAheadTest($data, $pos, $enc); - if ($newenc != $enc) { - // switch to new encoding - $enc = $newenc; - $cw[] = $this->getSwitchEncodingCodeword($enc); - ++$cw_num; - } else { - // get new byte - $chr = ord($data[$pos]); - ++$pos; - if ($this->isCharMode($chr, ENC_ASCII_EXT)) { - // 3. If the next data character is extended ASCII (greater than 127) encode it in ASCII mode first using the Upper Shift (value 235) character. - $cw[] = 235; - $cw[] = ($chr - 127); - $cw_num += 2; - } else { - // 4. Otherwise process the next data character in ASCII encodation. - $cw[] = ($chr + 1); - ++$cw_num; - } - } - } - break; - } - case ENC_C40 : // Upper-case alphanumeric - case ENC_TXT : // Lower-case alphanumeric - case ENC_X12 : { // ANSI X12 - $temp_cw = array(); - $p = 0; - $epos = $pos; - // get charset ID - $set_id = $this->chset_id[$enc]; - // get basic charset for current encoding - $charset = $this->chset[$set_id]; - do { - // 2. process the next character in C40 encodation. - $chr = ord($data[$epos]); - ++$epos; - // check for extended character - if ($chr & 0x80) { - if ($enc == ENC_X12) { - return false; - } - $chr = ($chr & 0x7f); - $temp_cw[] = 1; // shift 2 - $temp_cw[] = 30; // upper shift - $p += 2; - } - if (isset($charset[$chr])) { - $temp_cw[] = $charset[$chr]; - ++$p; - } else { - if (isset($this->chset['SH1'][$chr])) { - $temp_cw[] = 0; // shift 1 - $shiftset = $this->chset['SH1']; - } elseif (isset($chr, $this->chset['SH2'][$chr])) { - $temp_cw[] = 1; // shift 2 - $shiftset = $this->chset['SH2']; - } elseif (($enc == ENC_C40) AND isset($this->chset['S3C'][$chr])) { - $temp_cw[] = 2; // shift 3 - $shiftset = $this->chset['S3C']; - } elseif (($enc == ENC_TXT) AND isset($this->chset['S3T'][$chr])) { - $temp_cw[] = 2; // shift 3 - $shiftset = $this->chset['S3T']; - } else { - return false; - } - $temp_cw[] = $shiftset[$chr]; - $p += 2; - } - if ($p >= 3) { - $c1 = array_shift($temp_cw); - $c2 = array_shift($temp_cw); - $c3 = array_shift($temp_cw); - $p -= 3; - $tmp = ((1600 * $c1) + (40 * $c2) + $c3 + 1); - $cw[] = ($tmp >> 8); - $cw[] = ($tmp % 256); - $cw_num += 2; - $pos = $epos; - // 1. If the C40 encoding is at the point of starting a new double symbol character and if the look-ahead test (starting at step J) indicates another mode, switch to that mode. - $newenc = $this->lookAheadTest($data, $pos, $enc); - if ($newenc != $enc) { - // switch to new encoding - $enc = $newenc; - if ($enc != ENC_ASCII) { - // set unlatch character - $cw[] = $this->getSwitchEncodingCodeword(ENC_ASCII); - ++$cw_num; - } - $cw[] = $this->getSwitchEncodingCodeword($enc); - ++$cw_num; - $pos -= $p; - $p = 0; - break; - } - } - } while (($p > 0) AND ($epos < $data_length)); - // process last data (if any) - if ($p > 0) { - // get remaining number of data symbols - $cwr = ($this->getMaxDataCodewords($cw_num) - $cw_num); - if (($cwr == 1) AND ($p == 1)) { - // d. If one symbol character remains and one C40 value (data character) remains to be encoded - $c1 = array_shift($temp_cw); - --$p; - $cw[] = ($chr + 1); - ++$cw_num; - $pos = $epos; - $enc = ENC_ASCII; - $this->last_enc = $enc; - } elseif (($cwr == 2) AND ($p == 1)) { - // c. If two symbol characters remain and only one C40 value (data character) remains to be encoded - $c1 = array_shift($temp_cw); - --$p; - $cw[] = 254; - $cw[] = ($chr + 1); - $cw_num += 2; - $pos = $epos; - $enc = ENC_ASCII; - $this->last_enc = $enc; - } elseif (($cwr == 2) AND ($p == 2)) { - // b. If two symbol characters remain and two C40 values remain to be encoded - $c1 = array_shift($temp_cw); - $c2 = array_shift($temp_cw); - $p -= 2; - $tmp = ((1600 * $c1) + (40 * $c2) + 1); - $cw[] = ($tmp >> 8); - $cw[] = ($tmp % 256); - $cw_num += 2; - $pos = $epos; - $enc = ENC_ASCII; - $this->last_enc = $enc; - } else { - // switch to ASCII encoding - if ($enc != ENC_ASCII) { - $enc = ENC_ASCII; - $this->last_enc = $enc; - $cw[] = $this->getSwitchEncodingCodeword($enc); - ++$cw_num; - $pos = ($epos - $p); - } - } - } - break; - } - case ENC_EDF: { // F. While in EDIFACT (EDF) encodation - // initialize temporary array with 0 length - $temp_cw = array(); - $epos = $pos; - $field_length = 0; - $newenc = $enc; - do { - // 2. process the next character in EDIFACT encodation. - $chr = ord($data[$epos]); - if ($this->isCharMode($chr, ENC_EDF)) { - ++$epos; - $temp_cw[] = $chr; - ++$field_length; - } - if (($field_length == 4) OR ($epos == $data_length) OR !$this->isCharMode($chr, ENC_EDF)) { - if (($epos == $data_length) AND ($field_length < 3)) { - $enc = ENC_ASCII; - $cw[] = $this->getSwitchEncodingCodeword($enc); - ++$cw_num; - break; - } - if ($field_length < 4) { - // set unlatch character - $temp_cw[] = 0x1f; - ++$field_length; - // fill empty characters - for ($i = $field_length; $i < 4; ++$i) { - $temp_cw[] = 0; - } - $enc = ENC_ASCII; - $this->last_enc = $enc; - } - // encodes four data characters in three codewords - $tcw = (($temp_cw[0] & 0x3F) << 2) + (($temp_cw[1] & 0x30) >> 4); - if ($tcw > 0) { - $cw[] = $tcw; - $cw_num++; - } - $tcw= (($temp_cw[1] & 0x0F) << 4) + (($temp_cw[2] & 0x3C) >> 2); - if ($tcw > 0) { - $cw[] = $tcw; - $cw_num++; - } - $tcw = (($temp_cw[2] & 0x03) << 6) + ($temp_cw[3] & 0x3F); - if ($tcw > 0) { - $cw[] = $tcw; - $cw_num++; - } - $temp_cw = array(); - $pos = $epos; - $field_length = 0; - if ($enc == ENC_ASCII) { - break; // exit from EDIFACT mode - } - } - } while ($epos < $data_length); - break; - } - case ENC_BASE256: { // G. While in Base 256 (B256) encodation - // initialize temporary array with 0 length - $temp_cw = array(); - $field_length = 0; - while (($pos < $data_length) AND ($field_length <= 1555)) { - $newenc = $this->lookAheadTest($data, $pos, $enc); - if ($newenc != $enc) { - // 1. If the look-ahead test (starting at step J) indicates another mode, switch to that mode. - $enc = $newenc; - break; // exit from B256 mode - } else { - // 2. Otherwise, process the next character in Base 256 encodation. - $chr = ord($data[$pos]); - ++$pos; - $temp_cw[] = $chr; - ++$field_length; - } - } - // set field length - if ($field_length <= 249) { - $cw[] = $this->get255StateCodeword($field_length, ($cw_num + 1)); - ++$cw_num; - } else { - $cw[] = $this->get255StateCodeword((floor($field_length / 250) + 249), ($cw_num + 1)); - $cw[] = $this->get255StateCodeword(($field_length % 250), ($cw_num + 2)); - $cw_num += 2; - } - if (!empty($temp_cw)) { - // add B256 field - foreach ($temp_cw as $p => $cht) { - $cw[] = $this->get255StateCodeword($cht, ($cw_num + $p + 1)); - } - } - break; - } - } // end of switch enc - } // end of while - return $cw; - } - - /** - * Places "chr+bit" with appropriate wrapping within array[]. - * (Annex F - ECC 200 symbol character placement) - * @param array $marr Array of symbols. - * @param int $nrow Number of rows. - * @param int $ncol Number of columns. - * @param int $row Row number. - * @param int $col Column number. - * @param int $chr Char byte. - * @param int $bit Bit. - * @return array - * @protected - */ - protected function placeModule($marr, $nrow, $ncol, $row, $col, $chr, $bit) { - if ($row < 0) { - $row += $nrow; - $col += (4 - (($nrow + 4) % 8)); - } - if ($col < 0) { - $col += $ncol; - $row += (4 - (($ncol + 4) % 8)); - } - $marr[(($row * $ncol) + $col)] = ((10 * $chr) + $bit); - return $marr; - } - - /** - * Places the 8 bits of a utah-shaped symbol character. - * (Annex F - ECC 200 symbol character placement) - * @param array $marr Array of symbols. - * @param int $nrow Number of rows. - * @param int $ncol Number of columns. - * @param int $row Row number. - * @param int $col Column number. - * @param int $chr Char byte. - * @return array - * @protected - */ - protected function placeUtah($marr, $nrow, $ncol, $row, $col, $chr) { - $marr = $this->placeModule($marr, $nrow, $ncol, $row-2, $col-2, $chr, 1); - $marr = $this->placeModule($marr, $nrow, $ncol, $row-2, $col-1, $chr, 2); - $marr = $this->placeModule($marr, $nrow, $ncol, $row-1, $col-2, $chr, 3); - $marr = $this->placeModule($marr, $nrow, $ncol, $row-1, $col-1, $chr, 4); - $marr = $this->placeModule($marr, $nrow, $ncol, $row-1, $col, $chr, 5); - $marr = $this->placeModule($marr, $nrow, $ncol, $row, $col-2, $chr, 6); - $marr = $this->placeModule($marr, $nrow, $ncol, $row, $col-1, $chr, 7); - $marr = $this->placeModule($marr, $nrow, $ncol, $row, $col, $chr, 8); - return $marr; - } - - /** - * Places the 8 bits of the first special corner case. - * (Annex F - ECC 200 symbol character placement) - * @param array $marr Array of symbols. - * @param int $nrow Number of rows. - * @param int $ncol Number of columns. - * @param int $chr Char byte. - * @return array - * @protected - */ - protected function placeCornerA($marr, $nrow, $ncol, $chr) { - $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 0, $chr, 1); - $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 1, $chr, 2); - $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 2, $chr, 3); - $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-2, $chr, 4); - $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-1, $chr, 5); - $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-1, $chr, 6); - $marr = $this->placeModule($marr, $nrow, $ncol, 2, $ncol-1, $chr, 7); - $marr = $this->placeModule($marr, $nrow, $ncol, 3, $ncol-1, $chr, 8); - return $marr; - } - - /** - * Places the 8 bits of the second special corner case. - * (Annex F - ECC 200 symbol character placement) - * @param array $marr Array of symbols. - * @param int $nrow Number of rows. - * @param int $ncol Number of columns. - * @param int $chr Char byte. - * @return array - * @protected - */ - protected function placeCornerB($marr, $nrow, $ncol, $chr) { - $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-3, 0, $chr, 1); - $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-2, 0, $chr, 2); - $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 0, $chr, 3); - $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-4, $chr, 4); - $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-3, $chr, 5); - $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-2, $chr, 6); - $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-1, $chr, 7); - $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-1, $chr, 8); - return $marr; - } - - /** - * Places the 8 bits of the third special corner case. - * (Annex F - ECC 200 symbol character placement) - * @param array $marr Array of symbols. - * @param int $nrow Number of rows. - * @param int $ncol Number of columns. - * @param int $chr Char byte. - * @return array - * @protected - */ - protected function placeCornerC($marr, $nrow, $ncol, $chr) { - $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-3, 0, $chr, 1); - $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-2, 0, $chr, 2); - $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 0, $chr, 3); - $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-2, $chr, 4); - $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-1, $chr, 5); - $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-1, $chr, 6); - $marr = $this->placeModule($marr, $nrow, $ncol, 2, $ncol-1, $chr, 7); - $marr = $this->placeModule($marr, $nrow, $ncol, 3, $ncol-1, $chr, 8); - return $marr; - } - - /** - * Places the 8 bits of the fourth special corner case. - * (Annex F - ECC 200 symbol character placement) - * @param array $marr Array of symbols. - * @param int $nrow Number of rows. - * @param int $ncol Number of columns. - * @param int $chr Char byte. - * @return array - * @protected - */ - protected function placeCornerD($marr, $nrow, $ncol, $chr) { - $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 0, $chr, 1); - $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, $ncol-1, $chr, 2); - $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-3, $chr, 3); - $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-2, $chr, 4); - $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-1, $chr, 5); - $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-3, $chr, 6); - $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-2, $chr, 7); - $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-1, $chr, 8); - return $marr; - } - - /** - * Build a placement map. - * (Annex F - ECC 200 symbol character placement) - * @param int $nrow Number of rows. - * @param int $ncol Number of columns. - * @return array - * @protected - */ - protected function getPlacementMap($nrow, $ncol) { - // initialize array with zeros - $marr = array_fill(0, ($nrow * $ncol), 0); - // set starting values - $chr = 1; - $row = 4; - $col = 0; - do { - // repeatedly first check for one of the special corner cases, then - if (($row == $nrow) AND ($col == 0)) { - $marr = $this->placeCornerA($marr, $nrow, $ncol, $chr); - ++$chr; - } - if (($row == ($nrow - 2)) AND ($col == 0) AND ($ncol % 4)) { - $marr = $this->placeCornerB($marr, $nrow, $ncol, $chr); - ++$chr; - } - if (($row == ($nrow - 2)) AND ($col == 0) AND (($ncol % 8) == 4)) { - $marr = $this->placeCornerC($marr, $nrow, $ncol, $chr); - ++$chr; - } - if (($row == ($nrow + 4)) AND ($col == 2) AND (!($ncol % 8))) { - $marr = $this->placeCornerD($marr, $nrow, $ncol, $chr); - ++$chr; - } - // sweep upward diagonally, inserting successive characters, - do { - if (($row < $nrow) AND ($col >= 0) AND (!$marr[(($row * $ncol) + $col)])) { - $marr = $this->placeUtah($marr, $nrow, $ncol, $row, $col, $chr); - ++$chr; - } - $row -= 2; - $col += 2; - } while (($row >= 0) AND ($col < $ncol)); - ++$row; - $col += 3; - // & then sweep downward diagonally, inserting successive characters,... - do { - if (($row >= 0) AND ($col < $ncol) AND (!$marr[(($row * $ncol) + $col)])) { - $marr = $this->placeUtah($marr, $nrow, $ncol, $row, $col, $chr); - ++$chr; - } - $row += 2; - $col -= 2; - } while (($row < $nrow) AND ($col >= 0)); - $row += 3; - ++$col; - // ... until the entire array is scanned - } while (($row < $nrow) OR ($col < $ncol)); - // lastly, if the lower righthand corner is untouched, fill in fixed pattern - if (!$marr[(($nrow * $ncol) - 1)]) { - $marr[(($nrow * $ncol) - 1)] = 1; - $marr[(($nrow * $ncol) - $ncol - 2)] = 1; - } - return $marr; - } - -} // end DataMatrix class -//============================================================+ -// END OF FILE -//============================================================+ diff --git a/lib/combodo/tcpdf/include/barcodes/pdf417.php b/lib/combodo/tcpdf/include/barcodes/pdf417.php deleted file mode 100644 index 742802e1f..000000000 --- a/lib/combodo/tcpdf/include/barcodes/pdf417.php +++ /dev/null @@ -1,996 +0,0 @@ -<?php -//============================================================+ -// File name : pdf417.php -// Version : 1.0.005 -// Begin : 2010-06-03 -// Last Update : 2014-04-25 -// Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com -// License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html) -// ------------------------------------------------------------------- -// Copyright (C) 2010-2013 Nicola Asuni - Tecnick.com LTD -// -// This file is part of TCPDF software library. -// -// TCPDF is free software: you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// TCPDF is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with TCPDF. If not, see <http://www.gnu.org/licenses/>. -// -// See LICENSE.TXT file for more information. -// ------------------------------------------------------------------- -// -// DESCRIPTION : -// -// Class to create PDF417 barcode arrays for TCPDF class. -// PDF417 (ISO/IEC 15438:2006) is a 2-dimensional stacked bar code created by Symbol Technologies in 1991. -// It is one of the most popular 2D codes because of its ability to be read with slightly modified handheld laser or linear CCD scanners. -// TECHNICAL DATA / FEATURES OF PDF417: -// Encodable Character Set: All 128 ASCII Characters (including extended) -// Code Type: Continuous, Multi-Row -// Symbol Height: 3 - 90 Rows -// Symbol Width: 90X - 583X -// Bidirectional Decoding: Yes -// Error Correction Characters: 2 - 512 -// Maximum Data Characters: 1850 text, 2710 digits, 1108 bytes -// -//============================================================+ - -/** - * @file - * Class to create PDF417 barcode arrays for TCPDF class. - * PDF417 (ISO/IEC 15438:2006) is a 2-dimensional stacked bar code created by Symbol Technologies in 1991. - * (requires PHP bcmath extension) - * @package com.tecnick.tcpdf - * @author Nicola Asuni - * @version 1.0.005 - */ - -// definitions -if (!defined('PDF417DEFS')) { - - /** - * Indicate that definitions for this class are set - */ - define('PDF417DEFS', true); - - // ----------------------------------------------------- - - /** - * Row height respect X dimension of single module - */ - define('ROWHEIGHT', 4); - - /** - * Horizontal quiet zone in modules - */ - define('QUIETH', 2); - - /** - * Vertical quiet zone in modules - */ - define('QUIETV', 2); - -} // end of definitions - -// #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*# - -/** - * @class PDF417 - * Class to create PDF417 barcode arrays for TCPDF class. - * PDF417 (ISO/IEC 15438:2006) is a 2-dimensional stacked bar code created by Symbol Technologies in 1991. - * @package com.tecnick.tcpdf - * @author Nicola Asuni - * @version 1.0.003 - */ -class PDF417 { - - /** - * Barcode array to be returned which is readable by TCPDF. - * @protected - */ - protected $barcode_array = array(); - - /** - * Start pattern. - * @protected - */ - protected $start_pattern = '11111111010101000'; - - /** - * Stop pattern. - * @protected - */ - protected $stop_pattern = '111111101000101001'; - - /** - * Array of text Compaction Sub-Modes (values 0xFB - 0xFF are used for submode changers). - * @protected - */ - protected $textsubmodes = array( - array(0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x20,0xFD,0xFE,0xFF), // Alpha - array(0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x20,0xFD,0xFE,0xFF), // Lower - array(0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x26,0x0d,0x09,0x2c,0x3a,0x23,0x2d,0x2e,0x24,0x2f,0x2b,0x25,0x2a,0x3d,0x5e,0xFB,0x20,0xFD,0xFE,0xFF), // Mixed - array(0x3b,0x3c,0x3e,0x40,0x5b,0x5c,0x5d,0x5f,0x60,0x7e,0x21,0x0d,0x09,0x2c,0x3a,0x0a,0x2d,0x2e,0x24,0x2f,0x22,0x7c,0x2a,0x28,0x29,0x3f,0x7b,0x7d,0x27,0xFF) // Puntuaction - ); - - /** - * Array of switching codes for Text Compaction Sub-Modes. - * @protected - */ - protected $textlatch = array( - '01' => array(27), '02' => array(28), '03' => array(28,25), // - '10' => array(28,28), '12' => array(28), '13' => array(28,25), // - '20' => array(28), '21' => array(27), '23' => array(25), // - '30' => array(29), '31' => array(29,27), '32' => array(29,28) // - ); - - /** - * Clusters of codewords (0, 3, 6)<br/> - * Values are hex equivalents of binary representation of bars (1 = bar, 0 = space).<br/> - * The codewords numbered from 900 to 928 have special meaning, some enable to switch between modes in order to optimise the code:<ul> - * <li>900 : Switch to "Text" mode</li> - * <li>901 : Switch to "Byte" mode</li> - * <li>902 : Switch to "Numeric" mode</li> - * <li>903 - 912 : Reserved</li> - * <li>913 : Switch to "Octet" only for the next codeword</li> - * <li>914 - 920 : Reserved</li> - * <li>921 : Initialization</li> - * <li>922 : Terminator codeword for Macro PDF control block</li> - * <li>923 : Sequence tag to identify the beginning of optional fields in the Macro PDF control block</li> - * <li>924 : Switch to "Byte" mode (If the total number of byte is multiple of 6)</li> - * <li>925 : Identifier for a user defined Extended Channel Interpretation (ECI)</li> - * <li>926 : Identifier for a general purpose ECI format</li> - * <li>927 : Identifier for an ECI of a character set or code page</li> - * <li>928 : Macro marker codeword to indicate the beginning of a Macro PDF Control Block</li> - * </ul> - * @protected - */ - protected $clusters = array( - array( // cluster 0 ----------------------------------------------------------------------- - 0x1d5c0,0x1eaf0,0x1f57c,0x1d4e0,0x1ea78,0x1f53e,0x1a8c0,0x1d470,0x1a860,0x15040, // 10 - 0x1a830,0x15020,0x1adc0,0x1d6f0,0x1eb7c,0x1ace0,0x1d678,0x1eb3e,0x158c0,0x1ac70, // 20 - 0x15860,0x15dc0,0x1aef0,0x1d77c,0x15ce0,0x1ae78,0x1d73e,0x15c70,0x1ae3c,0x15ef0, // 30 - 0x1af7c,0x15e78,0x1af3e,0x15f7c,0x1f5fa,0x1d2e0,0x1e978,0x1f4be,0x1a4c0,0x1d270, // 40 - 0x1e93c,0x1a460,0x1d238,0x14840,0x1a430,0x1d21c,0x14820,0x1a418,0x14810,0x1a6e0, // 50 - 0x1d378,0x1e9be,0x14cc0,0x1a670,0x1d33c,0x14c60,0x1a638,0x1d31e,0x14c30,0x1a61c, // 60 - 0x14ee0,0x1a778,0x1d3be,0x14e70,0x1a73c,0x14e38,0x1a71e,0x14f78,0x1a7be,0x14f3c, // 70 - 0x14f1e,0x1a2c0,0x1d170,0x1e8bc,0x1a260,0x1d138,0x1e89e,0x14440,0x1a230,0x1d11c, // 80 - 0x14420,0x1a218,0x14410,0x14408,0x146c0,0x1a370,0x1d1bc,0x14660,0x1a338,0x1d19e, // 90 - 0x14630,0x1a31c,0x14618,0x1460c,0x14770,0x1a3bc,0x14738,0x1a39e,0x1471c,0x147bc, // 100 - 0x1a160,0x1d0b8,0x1e85e,0x14240,0x1a130,0x1d09c,0x14220,0x1a118,0x1d08e,0x14210, // 110 - 0x1a10c,0x14208,0x1a106,0x14360,0x1a1b8,0x1d0de,0x14330,0x1a19c,0x14318,0x1a18e, // 120 - 0x1430c,0x14306,0x1a1de,0x1438e,0x14140,0x1a0b0,0x1d05c,0x14120,0x1a098,0x1d04e, // 130 - 0x14110,0x1a08c,0x14108,0x1a086,0x14104,0x141b0,0x14198,0x1418c,0x140a0,0x1d02e, // 140 - 0x1a04c,0x1a046,0x14082,0x1cae0,0x1e578,0x1f2be,0x194c0,0x1ca70,0x1e53c,0x19460, // 150 - 0x1ca38,0x1e51e,0x12840,0x19430,0x12820,0x196e0,0x1cb78,0x1e5be,0x12cc0,0x19670, // 160 - 0x1cb3c,0x12c60,0x19638,0x12c30,0x12c18,0x12ee0,0x19778,0x1cbbe,0x12e70,0x1973c, // 170 - 0x12e38,0x12e1c,0x12f78,0x197be,0x12f3c,0x12fbe,0x1dac0,0x1ed70,0x1f6bc,0x1da60, // 180 - 0x1ed38,0x1f69e,0x1b440,0x1da30,0x1ed1c,0x1b420,0x1da18,0x1ed0e,0x1b410,0x1da0c, // 190 - 0x192c0,0x1c970,0x1e4bc,0x1b6c0,0x19260,0x1c938,0x1e49e,0x1b660,0x1db38,0x1ed9e, // 200 - 0x16c40,0x12420,0x19218,0x1c90e,0x16c20,0x1b618,0x16c10,0x126c0,0x19370,0x1c9bc, // 210 - 0x16ec0,0x12660,0x19338,0x1c99e,0x16e60,0x1b738,0x1db9e,0x16e30,0x12618,0x16e18, // 220 - 0x12770,0x193bc,0x16f70,0x12738,0x1939e,0x16f38,0x1b79e,0x16f1c,0x127bc,0x16fbc, // 230 - 0x1279e,0x16f9e,0x1d960,0x1ecb8,0x1f65e,0x1b240,0x1d930,0x1ec9c,0x1b220,0x1d918, // 240 - 0x1ec8e,0x1b210,0x1d90c,0x1b208,0x1b204,0x19160,0x1c8b8,0x1e45e,0x1b360,0x19130, // 250 - 0x1c89c,0x16640,0x12220,0x1d99c,0x1c88e,0x16620,0x12210,0x1910c,0x16610,0x1b30c, // 260 - 0x19106,0x12204,0x12360,0x191b8,0x1c8de,0x16760,0x12330,0x1919c,0x16730,0x1b39c, // 270 - 0x1918e,0x16718,0x1230c,0x12306,0x123b8,0x191de,0x167b8,0x1239c,0x1679c,0x1238e, // 280 - 0x1678e,0x167de,0x1b140,0x1d8b0,0x1ec5c,0x1b120,0x1d898,0x1ec4e,0x1b110,0x1d88c, // 290 - 0x1b108,0x1d886,0x1b104,0x1b102,0x12140,0x190b0,0x1c85c,0x16340,0x12120,0x19098, // 300 - 0x1c84e,0x16320,0x1b198,0x1d8ce,0x16310,0x12108,0x19086,0x16308,0x1b186,0x16304, // 310 - 0x121b0,0x190dc,0x163b0,0x12198,0x190ce,0x16398,0x1b1ce,0x1638c,0x12186,0x16386, // 320 - 0x163dc,0x163ce,0x1b0a0,0x1d858,0x1ec2e,0x1b090,0x1d84c,0x1b088,0x1d846,0x1b084, // 330 - 0x1b082,0x120a0,0x19058,0x1c82e,0x161a0,0x12090,0x1904c,0x16190,0x1b0cc,0x19046, // 340 - 0x16188,0x12084,0x16184,0x12082,0x120d8,0x161d8,0x161cc,0x161c6,0x1d82c,0x1d826, // 350 - 0x1b042,0x1902c,0x12048,0x160c8,0x160c4,0x160c2,0x18ac0,0x1c570,0x1e2bc,0x18a60, // 360 - 0x1c538,0x11440,0x18a30,0x1c51c,0x11420,0x18a18,0x11410,0x11408,0x116c0,0x18b70, // 370 - 0x1c5bc,0x11660,0x18b38,0x1c59e,0x11630,0x18b1c,0x11618,0x1160c,0x11770,0x18bbc, // 380 - 0x11738,0x18b9e,0x1171c,0x117bc,0x1179e,0x1cd60,0x1e6b8,0x1f35e,0x19a40,0x1cd30, // 390 - 0x1e69c,0x19a20,0x1cd18,0x1e68e,0x19a10,0x1cd0c,0x19a08,0x1cd06,0x18960,0x1c4b8, // 400 - 0x1e25e,0x19b60,0x18930,0x1c49c,0x13640,0x11220,0x1cd9c,0x1c48e,0x13620,0x19b18, // 410 - 0x1890c,0x13610,0x11208,0x13608,0x11360,0x189b8,0x1c4de,0x13760,0x11330,0x1cdde, // 420 - 0x13730,0x19b9c,0x1898e,0x13718,0x1130c,0x1370c,0x113b8,0x189de,0x137b8,0x1139c, // 430 - 0x1379c,0x1138e,0x113de,0x137de,0x1dd40,0x1eeb0,0x1f75c,0x1dd20,0x1ee98,0x1f74e, // 440 - 0x1dd10,0x1ee8c,0x1dd08,0x1ee86,0x1dd04,0x19940,0x1ccb0,0x1e65c,0x1bb40,0x19920, // 450 - 0x1eedc,0x1e64e,0x1bb20,0x1dd98,0x1eece,0x1bb10,0x19908,0x1cc86,0x1bb08,0x1dd86, // 460 - 0x19902,0x11140,0x188b0,0x1c45c,0x13340,0x11120,0x18898,0x1c44e,0x17740,0x13320, // 470 - 0x19998,0x1ccce,0x17720,0x1bb98,0x1ddce,0x18886,0x17710,0x13308,0x19986,0x17708, // 480 - 0x11102,0x111b0,0x188dc,0x133b0,0x11198,0x188ce,0x177b0,0x13398,0x199ce,0x17798, // 490 - 0x1bbce,0x11186,0x13386,0x111dc,0x133dc,0x111ce,0x177dc,0x133ce,0x1dca0,0x1ee58, // 500 - 0x1f72e,0x1dc90,0x1ee4c,0x1dc88,0x1ee46,0x1dc84,0x1dc82,0x198a0,0x1cc58,0x1e62e, // 510 - 0x1b9a0,0x19890,0x1ee6e,0x1b990,0x1dccc,0x1cc46,0x1b988,0x19884,0x1b984,0x19882, // 520 - 0x1b982,0x110a0,0x18858,0x1c42e,0x131a0,0x11090,0x1884c,0x173a0,0x13190,0x198cc, // 530 - 0x18846,0x17390,0x1b9cc,0x11084,0x17388,0x13184,0x11082,0x13182,0x110d8,0x1886e, // 540 - 0x131d8,0x110cc,0x173d8,0x131cc,0x110c6,0x173cc,0x131c6,0x110ee,0x173ee,0x1dc50, // 550 - 0x1ee2c,0x1dc48,0x1ee26,0x1dc44,0x1dc42,0x19850,0x1cc2c,0x1b8d0,0x19848,0x1cc26, // 560 - 0x1b8c8,0x1dc66,0x1b8c4,0x19842,0x1b8c2,0x11050,0x1882c,0x130d0,0x11048,0x18826, // 570 - 0x171d0,0x130c8,0x19866,0x171c8,0x1b8e6,0x11042,0x171c4,0x130c2,0x171c2,0x130ec, // 580 - 0x171ec,0x171e6,0x1ee16,0x1dc22,0x1cc16,0x19824,0x19822,0x11028,0x13068,0x170e8, // 590 - 0x11022,0x13062,0x18560,0x10a40,0x18530,0x10a20,0x18518,0x1c28e,0x10a10,0x1850c, // 600 - 0x10a08,0x18506,0x10b60,0x185b8,0x1c2de,0x10b30,0x1859c,0x10b18,0x1858e,0x10b0c, // 610 - 0x10b06,0x10bb8,0x185de,0x10b9c,0x10b8e,0x10bde,0x18d40,0x1c6b0,0x1e35c,0x18d20, // 620 - 0x1c698,0x18d10,0x1c68c,0x18d08,0x1c686,0x18d04,0x10940,0x184b0,0x1c25c,0x11b40, // 630 - 0x10920,0x1c6dc,0x1c24e,0x11b20,0x18d98,0x1c6ce,0x11b10,0x10908,0x18486,0x11b08, // 640 - 0x18d86,0x10902,0x109b0,0x184dc,0x11bb0,0x10998,0x184ce,0x11b98,0x18dce,0x11b8c, // 650 - 0x10986,0x109dc,0x11bdc,0x109ce,0x11bce,0x1cea0,0x1e758,0x1f3ae,0x1ce90,0x1e74c, // 660 - 0x1ce88,0x1e746,0x1ce84,0x1ce82,0x18ca0,0x1c658,0x19da0,0x18c90,0x1c64c,0x19d90, // 670 - 0x1cecc,0x1c646,0x19d88,0x18c84,0x19d84,0x18c82,0x19d82,0x108a0,0x18458,0x119a0, // 680 - 0x10890,0x1c66e,0x13ba0,0x11990,0x18ccc,0x18446,0x13b90,0x19dcc,0x10884,0x13b88, // 690 - 0x11984,0x10882,0x11982,0x108d8,0x1846e,0x119d8,0x108cc,0x13bd8,0x119cc,0x108c6, // 700 - 0x13bcc,0x119c6,0x108ee,0x119ee,0x13bee,0x1ef50,0x1f7ac,0x1ef48,0x1f7a6,0x1ef44, // 710 - 0x1ef42,0x1ce50,0x1e72c,0x1ded0,0x1ef6c,0x1e726,0x1dec8,0x1ef66,0x1dec4,0x1ce42, // 720 - 0x1dec2,0x18c50,0x1c62c,0x19cd0,0x18c48,0x1c626,0x1bdd0,0x19cc8,0x1ce66,0x1bdc8, // 730 - 0x1dee6,0x18c42,0x1bdc4,0x19cc2,0x1bdc2,0x10850,0x1842c,0x118d0,0x10848,0x18426, // 740 - 0x139d0,0x118c8,0x18c66,0x17bd0,0x139c8,0x19ce6,0x10842,0x17bc8,0x1bde6,0x118c2, // 750 - 0x17bc4,0x1086c,0x118ec,0x10866,0x139ec,0x118e6,0x17bec,0x139e6,0x17be6,0x1ef28, // 760 - 0x1f796,0x1ef24,0x1ef22,0x1ce28,0x1e716,0x1de68,0x1ef36,0x1de64,0x1ce22,0x1de62, // 770 - 0x18c28,0x1c616,0x19c68,0x18c24,0x1bce8,0x19c64,0x18c22,0x1bce4,0x19c62,0x1bce2, // 780 - 0x10828,0x18416,0x11868,0x18c36,0x138e8,0x11864,0x10822,0x179e8,0x138e4,0x11862, // 790 - 0x179e4,0x138e2,0x179e2,0x11876,0x179f6,0x1ef12,0x1de34,0x1de32,0x19c34,0x1bc74, // 800 - 0x1bc72,0x11834,0x13874,0x178f4,0x178f2,0x10540,0x10520,0x18298,0x10510,0x10508, // 810 - 0x10504,0x105b0,0x10598,0x1058c,0x10586,0x105dc,0x105ce,0x186a0,0x18690,0x1c34c, // 820 - 0x18688,0x1c346,0x18684,0x18682,0x104a0,0x18258,0x10da0,0x186d8,0x1824c,0x10d90, // 830 - 0x186cc,0x10d88,0x186c6,0x10d84,0x10482,0x10d82,0x104d8,0x1826e,0x10dd8,0x186ee, // 840 - 0x10dcc,0x104c6,0x10dc6,0x104ee,0x10dee,0x1c750,0x1c748,0x1c744,0x1c742,0x18650, // 850 - 0x18ed0,0x1c76c,0x1c326,0x18ec8,0x1c766,0x18ec4,0x18642,0x18ec2,0x10450,0x10cd0, // 860 - 0x10448,0x18226,0x11dd0,0x10cc8,0x10444,0x11dc8,0x10cc4,0x10442,0x11dc4,0x10cc2, // 870 - 0x1046c,0x10cec,0x10466,0x11dec,0x10ce6,0x11de6,0x1e7a8,0x1e7a4,0x1e7a2,0x1c728, // 880 - 0x1cf68,0x1e7b6,0x1cf64,0x1c722,0x1cf62,0x18628,0x1c316,0x18e68,0x1c736,0x19ee8, // 890 - 0x18e64,0x18622,0x19ee4,0x18e62,0x19ee2,0x10428,0x18216,0x10c68,0x18636,0x11ce8, // 900 - 0x10c64,0x10422,0x13de8,0x11ce4,0x10c62,0x13de4,0x11ce2,0x10436,0x10c76,0x11cf6, // 910 - 0x13df6,0x1f7d4,0x1f7d2,0x1e794,0x1efb4,0x1e792,0x1efb2,0x1c714,0x1cf34,0x1c712, // 920 - 0x1df74,0x1cf32,0x1df72,0x18614,0x18e34,0x18612,0x19e74,0x18e32,0x1bef4), // 929 - array( // cluster 3 ----------------------------------------------------------------------- - 0x1f560,0x1fab8,0x1ea40,0x1f530,0x1fa9c,0x1ea20,0x1f518,0x1fa8e,0x1ea10,0x1f50c, // 10 - 0x1ea08,0x1f506,0x1ea04,0x1eb60,0x1f5b8,0x1fade,0x1d640,0x1eb30,0x1f59c,0x1d620, // 20 - 0x1eb18,0x1f58e,0x1d610,0x1eb0c,0x1d608,0x1eb06,0x1d604,0x1d760,0x1ebb8,0x1f5de, // 30 - 0x1ae40,0x1d730,0x1eb9c,0x1ae20,0x1d718,0x1eb8e,0x1ae10,0x1d70c,0x1ae08,0x1d706, // 40 - 0x1ae04,0x1af60,0x1d7b8,0x1ebde,0x15e40,0x1af30,0x1d79c,0x15e20,0x1af18,0x1d78e, // 50 - 0x15e10,0x1af0c,0x15e08,0x1af06,0x15f60,0x1afb8,0x1d7de,0x15f30,0x1af9c,0x15f18, // 60 - 0x1af8e,0x15f0c,0x15fb8,0x1afde,0x15f9c,0x15f8e,0x1e940,0x1f4b0,0x1fa5c,0x1e920, // 70 - 0x1f498,0x1fa4e,0x1e910,0x1f48c,0x1e908,0x1f486,0x1e904,0x1e902,0x1d340,0x1e9b0, // 80 - 0x1f4dc,0x1d320,0x1e998,0x1f4ce,0x1d310,0x1e98c,0x1d308,0x1e986,0x1d304,0x1d302, // 90 - 0x1a740,0x1d3b0,0x1e9dc,0x1a720,0x1d398,0x1e9ce,0x1a710,0x1d38c,0x1a708,0x1d386, // 100 - 0x1a704,0x1a702,0x14f40,0x1a7b0,0x1d3dc,0x14f20,0x1a798,0x1d3ce,0x14f10,0x1a78c, // 110 - 0x14f08,0x1a786,0x14f04,0x14fb0,0x1a7dc,0x14f98,0x1a7ce,0x14f8c,0x14f86,0x14fdc, // 120 - 0x14fce,0x1e8a0,0x1f458,0x1fa2e,0x1e890,0x1f44c,0x1e888,0x1f446,0x1e884,0x1e882, // 130 - 0x1d1a0,0x1e8d8,0x1f46e,0x1d190,0x1e8cc,0x1d188,0x1e8c6,0x1d184,0x1d182,0x1a3a0, // 140 - 0x1d1d8,0x1e8ee,0x1a390,0x1d1cc,0x1a388,0x1d1c6,0x1a384,0x1a382,0x147a0,0x1a3d8, // 150 - 0x1d1ee,0x14790,0x1a3cc,0x14788,0x1a3c6,0x14784,0x14782,0x147d8,0x1a3ee,0x147cc, // 160 - 0x147c6,0x147ee,0x1e850,0x1f42c,0x1e848,0x1f426,0x1e844,0x1e842,0x1d0d0,0x1e86c, // 170 - 0x1d0c8,0x1e866,0x1d0c4,0x1d0c2,0x1a1d0,0x1d0ec,0x1a1c8,0x1d0e6,0x1a1c4,0x1a1c2, // 180 - 0x143d0,0x1a1ec,0x143c8,0x1a1e6,0x143c4,0x143c2,0x143ec,0x143e6,0x1e828,0x1f416, // 190 - 0x1e824,0x1e822,0x1d068,0x1e836,0x1d064,0x1d062,0x1a0e8,0x1d076,0x1a0e4,0x1a0e2, // 200 - 0x141e8,0x1a0f6,0x141e4,0x141e2,0x1e814,0x1e812,0x1d034,0x1d032,0x1a074,0x1a072, // 210 - 0x1e540,0x1f2b0,0x1f95c,0x1e520,0x1f298,0x1f94e,0x1e510,0x1f28c,0x1e508,0x1f286, // 220 - 0x1e504,0x1e502,0x1cb40,0x1e5b0,0x1f2dc,0x1cb20,0x1e598,0x1f2ce,0x1cb10,0x1e58c, // 230 - 0x1cb08,0x1e586,0x1cb04,0x1cb02,0x19740,0x1cbb0,0x1e5dc,0x19720,0x1cb98,0x1e5ce, // 240 - 0x19710,0x1cb8c,0x19708,0x1cb86,0x19704,0x19702,0x12f40,0x197b0,0x1cbdc,0x12f20, // 250 - 0x19798,0x1cbce,0x12f10,0x1978c,0x12f08,0x19786,0x12f04,0x12fb0,0x197dc,0x12f98, // 260 - 0x197ce,0x12f8c,0x12f86,0x12fdc,0x12fce,0x1f6a0,0x1fb58,0x16bf0,0x1f690,0x1fb4c, // 270 - 0x169f8,0x1f688,0x1fb46,0x168fc,0x1f684,0x1f682,0x1e4a0,0x1f258,0x1f92e,0x1eda0, // 280 - 0x1e490,0x1fb6e,0x1ed90,0x1f6cc,0x1f246,0x1ed88,0x1e484,0x1ed84,0x1e482,0x1ed82, // 290 - 0x1c9a0,0x1e4d8,0x1f26e,0x1dba0,0x1c990,0x1e4cc,0x1db90,0x1edcc,0x1e4c6,0x1db88, // 300 - 0x1c984,0x1db84,0x1c982,0x1db82,0x193a0,0x1c9d8,0x1e4ee,0x1b7a0,0x19390,0x1c9cc, // 310 - 0x1b790,0x1dbcc,0x1c9c6,0x1b788,0x19384,0x1b784,0x19382,0x1b782,0x127a0,0x193d8, // 320 - 0x1c9ee,0x16fa0,0x12790,0x193cc,0x16f90,0x1b7cc,0x193c6,0x16f88,0x12784,0x16f84, // 330 - 0x12782,0x127d8,0x193ee,0x16fd8,0x127cc,0x16fcc,0x127c6,0x16fc6,0x127ee,0x1f650, // 340 - 0x1fb2c,0x165f8,0x1f648,0x1fb26,0x164fc,0x1f644,0x1647e,0x1f642,0x1e450,0x1f22c, // 350 - 0x1ecd0,0x1e448,0x1f226,0x1ecc8,0x1f666,0x1ecc4,0x1e442,0x1ecc2,0x1c8d0,0x1e46c, // 360 - 0x1d9d0,0x1c8c8,0x1e466,0x1d9c8,0x1ece6,0x1d9c4,0x1c8c2,0x1d9c2,0x191d0,0x1c8ec, // 370 - 0x1b3d0,0x191c8,0x1c8e6,0x1b3c8,0x1d9e6,0x1b3c4,0x191c2,0x1b3c2,0x123d0,0x191ec, // 380 - 0x167d0,0x123c8,0x191e6,0x167c8,0x1b3e6,0x167c4,0x123c2,0x167c2,0x123ec,0x167ec, // 390 - 0x123e6,0x167e6,0x1f628,0x1fb16,0x162fc,0x1f624,0x1627e,0x1f622,0x1e428,0x1f216, // 400 - 0x1ec68,0x1f636,0x1ec64,0x1e422,0x1ec62,0x1c868,0x1e436,0x1d8e8,0x1c864,0x1d8e4, // 410 - 0x1c862,0x1d8e2,0x190e8,0x1c876,0x1b1e8,0x1d8f6,0x1b1e4,0x190e2,0x1b1e2,0x121e8, // 420 - 0x190f6,0x163e8,0x121e4,0x163e4,0x121e2,0x163e2,0x121f6,0x163f6,0x1f614,0x1617e, // 430 - 0x1f612,0x1e414,0x1ec34,0x1e412,0x1ec32,0x1c834,0x1d874,0x1c832,0x1d872,0x19074, // 440 - 0x1b0f4,0x19072,0x1b0f2,0x120f4,0x161f4,0x120f2,0x161f2,0x1f60a,0x1e40a,0x1ec1a, // 450 - 0x1c81a,0x1d83a,0x1903a,0x1b07a,0x1e2a0,0x1f158,0x1f8ae,0x1e290,0x1f14c,0x1e288, // 460 - 0x1f146,0x1e284,0x1e282,0x1c5a0,0x1e2d8,0x1f16e,0x1c590,0x1e2cc,0x1c588,0x1e2c6, // 470 - 0x1c584,0x1c582,0x18ba0,0x1c5d8,0x1e2ee,0x18b90,0x1c5cc,0x18b88,0x1c5c6,0x18b84, // 480 - 0x18b82,0x117a0,0x18bd8,0x1c5ee,0x11790,0x18bcc,0x11788,0x18bc6,0x11784,0x11782, // 490 - 0x117d8,0x18bee,0x117cc,0x117c6,0x117ee,0x1f350,0x1f9ac,0x135f8,0x1f348,0x1f9a6, // 500 - 0x134fc,0x1f344,0x1347e,0x1f342,0x1e250,0x1f12c,0x1e6d0,0x1e248,0x1f126,0x1e6c8, // 510 - 0x1f366,0x1e6c4,0x1e242,0x1e6c2,0x1c4d0,0x1e26c,0x1cdd0,0x1c4c8,0x1e266,0x1cdc8, // 520 - 0x1e6e6,0x1cdc4,0x1c4c2,0x1cdc2,0x189d0,0x1c4ec,0x19bd0,0x189c8,0x1c4e6,0x19bc8, // 530 - 0x1cde6,0x19bc4,0x189c2,0x19bc2,0x113d0,0x189ec,0x137d0,0x113c8,0x189e6,0x137c8, // 540 - 0x19be6,0x137c4,0x113c2,0x137c2,0x113ec,0x137ec,0x113e6,0x137e6,0x1fba8,0x175f0, // 550 - 0x1bafc,0x1fba4,0x174f8,0x1ba7e,0x1fba2,0x1747c,0x1743e,0x1f328,0x1f996,0x132fc, // 560 - 0x1f768,0x1fbb6,0x176fc,0x1327e,0x1f764,0x1f322,0x1767e,0x1f762,0x1e228,0x1f116, // 570 - 0x1e668,0x1e224,0x1eee8,0x1f776,0x1e222,0x1eee4,0x1e662,0x1eee2,0x1c468,0x1e236, // 580 - 0x1cce8,0x1c464,0x1dde8,0x1cce4,0x1c462,0x1dde4,0x1cce2,0x1dde2,0x188e8,0x1c476, // 590 - 0x199e8,0x188e4,0x1bbe8,0x199e4,0x188e2,0x1bbe4,0x199e2,0x1bbe2,0x111e8,0x188f6, // 600 - 0x133e8,0x111e4,0x177e8,0x133e4,0x111e2,0x177e4,0x133e2,0x177e2,0x111f6,0x133f6, // 610 - 0x1fb94,0x172f8,0x1b97e,0x1fb92,0x1727c,0x1723e,0x1f314,0x1317e,0x1f734,0x1f312, // 620 - 0x1737e,0x1f732,0x1e214,0x1e634,0x1e212,0x1ee74,0x1e632,0x1ee72,0x1c434,0x1cc74, // 630 - 0x1c432,0x1dcf4,0x1cc72,0x1dcf2,0x18874,0x198f4,0x18872,0x1b9f4,0x198f2,0x1b9f2, // 640 - 0x110f4,0x131f4,0x110f2,0x173f4,0x131f2,0x173f2,0x1fb8a,0x1717c,0x1713e,0x1f30a, // 650 - 0x1f71a,0x1e20a,0x1e61a,0x1ee3a,0x1c41a,0x1cc3a,0x1dc7a,0x1883a,0x1987a,0x1b8fa, // 660 - 0x1107a,0x130fa,0x171fa,0x170be,0x1e150,0x1f0ac,0x1e148,0x1f0a6,0x1e144,0x1e142, // 670 - 0x1c2d0,0x1e16c,0x1c2c8,0x1e166,0x1c2c4,0x1c2c2,0x185d0,0x1c2ec,0x185c8,0x1c2e6, // 680 - 0x185c4,0x185c2,0x10bd0,0x185ec,0x10bc8,0x185e6,0x10bc4,0x10bc2,0x10bec,0x10be6, // 690 - 0x1f1a8,0x1f8d6,0x11afc,0x1f1a4,0x11a7e,0x1f1a2,0x1e128,0x1f096,0x1e368,0x1e124, // 700 - 0x1e364,0x1e122,0x1e362,0x1c268,0x1e136,0x1c6e8,0x1c264,0x1c6e4,0x1c262,0x1c6e2, // 710 - 0x184e8,0x1c276,0x18de8,0x184e4,0x18de4,0x184e2,0x18de2,0x109e8,0x184f6,0x11be8, // 720 - 0x109e4,0x11be4,0x109e2,0x11be2,0x109f6,0x11bf6,0x1f9d4,0x13af8,0x19d7e,0x1f9d2, // 730 - 0x13a7c,0x13a3e,0x1f194,0x1197e,0x1f3b4,0x1f192,0x13b7e,0x1f3b2,0x1e114,0x1e334, // 740 - 0x1e112,0x1e774,0x1e332,0x1e772,0x1c234,0x1c674,0x1c232,0x1cef4,0x1c672,0x1cef2, // 750 - 0x18474,0x18cf4,0x18472,0x19df4,0x18cf2,0x19df2,0x108f4,0x119f4,0x108f2,0x13bf4, // 760 - 0x119f2,0x13bf2,0x17af0,0x1bd7c,0x17a78,0x1bd3e,0x17a3c,0x17a1e,0x1f9ca,0x1397c, // 770 - 0x1fbda,0x17b7c,0x1393e,0x17b3e,0x1f18a,0x1f39a,0x1f7ba,0x1e10a,0x1e31a,0x1e73a, // 780 - 0x1ef7a,0x1c21a,0x1c63a,0x1ce7a,0x1defa,0x1843a,0x18c7a,0x19cfa,0x1bdfa,0x1087a, // 790 - 0x118fa,0x139fa,0x17978,0x1bcbe,0x1793c,0x1791e,0x138be,0x179be,0x178bc,0x1789e, // 800 - 0x1785e,0x1e0a8,0x1e0a4,0x1e0a2,0x1c168,0x1e0b6,0x1c164,0x1c162,0x182e8,0x1c176, // 810 - 0x182e4,0x182e2,0x105e8,0x182f6,0x105e4,0x105e2,0x105f6,0x1f0d4,0x10d7e,0x1f0d2, // 820 - 0x1e094,0x1e1b4,0x1e092,0x1e1b2,0x1c134,0x1c374,0x1c132,0x1c372,0x18274,0x186f4, // 830 - 0x18272,0x186f2,0x104f4,0x10df4,0x104f2,0x10df2,0x1f8ea,0x11d7c,0x11d3e,0x1f0ca, // 840 - 0x1f1da,0x1e08a,0x1e19a,0x1e3ba,0x1c11a,0x1c33a,0x1c77a,0x1823a,0x1867a,0x18efa, // 850 - 0x1047a,0x10cfa,0x11dfa,0x13d78,0x19ebe,0x13d3c,0x13d1e,0x11cbe,0x13dbe,0x17d70, // 860 - 0x1bebc,0x17d38,0x1be9e,0x17d1c,0x17d0e,0x13cbc,0x17dbc,0x13c9e,0x17d9e,0x17cb8, // 870 - 0x1be5e,0x17c9c,0x17c8e,0x13c5e,0x17cde,0x17c5c,0x17c4e,0x17c2e,0x1c0b4,0x1c0b2, // 880 - 0x18174,0x18172,0x102f4,0x102f2,0x1e0da,0x1c09a,0x1c1ba,0x1813a,0x1837a,0x1027a, // 890 - 0x106fa,0x10ebe,0x11ebc,0x11e9e,0x13eb8,0x19f5e,0x13e9c,0x13e8e,0x11e5e,0x13ede, // 900 - 0x17eb0,0x1bf5c,0x17e98,0x1bf4e,0x17e8c,0x17e86,0x13e5c,0x17edc,0x13e4e,0x17ece, // 910 - 0x17e58,0x1bf2e,0x17e4c,0x17e46,0x13e2e,0x17e6e,0x17e2c,0x17e26,0x10f5e,0x11f5c, // 920 - 0x11f4e,0x13f58,0x19fae,0x13f4c,0x13f46,0x11f2e,0x13f6e,0x13f2c,0x13f26), // 929 - array( // cluster 6 ----------------------------------------------------------------------- - 0x1abe0,0x1d5f8,0x153c0,0x1a9f0,0x1d4fc,0x151e0,0x1a8f8,0x1d47e,0x150f0,0x1a87c, // 10 - 0x15078,0x1fad0,0x15be0,0x1adf8,0x1fac8,0x159f0,0x1acfc,0x1fac4,0x158f8,0x1ac7e, // 20 - 0x1fac2,0x1587c,0x1f5d0,0x1faec,0x15df8,0x1f5c8,0x1fae6,0x15cfc,0x1f5c4,0x15c7e, // 30 - 0x1f5c2,0x1ebd0,0x1f5ec,0x1ebc8,0x1f5e6,0x1ebc4,0x1ebc2,0x1d7d0,0x1ebec,0x1d7c8, // 40 - 0x1ebe6,0x1d7c4,0x1d7c2,0x1afd0,0x1d7ec,0x1afc8,0x1d7e6,0x1afc4,0x14bc0,0x1a5f0, // 50 - 0x1d2fc,0x149e0,0x1a4f8,0x1d27e,0x148f0,0x1a47c,0x14878,0x1a43e,0x1483c,0x1fa68, // 60 - 0x14df0,0x1a6fc,0x1fa64,0x14cf8,0x1a67e,0x1fa62,0x14c7c,0x14c3e,0x1f4e8,0x1fa76, // 70 - 0x14efc,0x1f4e4,0x14e7e,0x1f4e2,0x1e9e8,0x1f4f6,0x1e9e4,0x1e9e2,0x1d3e8,0x1e9f6, // 80 - 0x1d3e4,0x1d3e2,0x1a7e8,0x1d3f6,0x1a7e4,0x1a7e2,0x145e0,0x1a2f8,0x1d17e,0x144f0, // 90 - 0x1a27c,0x14478,0x1a23e,0x1443c,0x1441e,0x1fa34,0x146f8,0x1a37e,0x1fa32,0x1467c, // 100 - 0x1463e,0x1f474,0x1477e,0x1f472,0x1e8f4,0x1e8f2,0x1d1f4,0x1d1f2,0x1a3f4,0x1a3f2, // 110 - 0x142f0,0x1a17c,0x14278,0x1a13e,0x1423c,0x1421e,0x1fa1a,0x1437c,0x1433e,0x1f43a, // 120 - 0x1e87a,0x1d0fa,0x14178,0x1a0be,0x1413c,0x1411e,0x141be,0x140bc,0x1409e,0x12bc0, // 130 - 0x195f0,0x1cafc,0x129e0,0x194f8,0x1ca7e,0x128f0,0x1947c,0x12878,0x1943e,0x1283c, // 140 - 0x1f968,0x12df0,0x196fc,0x1f964,0x12cf8,0x1967e,0x1f962,0x12c7c,0x12c3e,0x1f2e8, // 150 - 0x1f976,0x12efc,0x1f2e4,0x12e7e,0x1f2e2,0x1e5e8,0x1f2f6,0x1e5e4,0x1e5e2,0x1cbe8, // 160 - 0x1e5f6,0x1cbe4,0x1cbe2,0x197e8,0x1cbf6,0x197e4,0x197e2,0x1b5e0,0x1daf8,0x1ed7e, // 170 - 0x169c0,0x1b4f0,0x1da7c,0x168e0,0x1b478,0x1da3e,0x16870,0x1b43c,0x16838,0x1b41e, // 180 - 0x1681c,0x125e0,0x192f8,0x1c97e,0x16de0,0x124f0,0x1927c,0x16cf0,0x1b67c,0x1923e, // 190 - 0x16c78,0x1243c,0x16c3c,0x1241e,0x16c1e,0x1f934,0x126f8,0x1937e,0x1fb74,0x1f932, // 200 - 0x16ef8,0x1267c,0x1fb72,0x16e7c,0x1263e,0x16e3e,0x1f274,0x1277e,0x1f6f4,0x1f272, // 210 - 0x16f7e,0x1f6f2,0x1e4f4,0x1edf4,0x1e4f2,0x1edf2,0x1c9f4,0x1dbf4,0x1c9f2,0x1dbf2, // 220 - 0x193f4,0x193f2,0x165c0,0x1b2f0,0x1d97c,0x164e0,0x1b278,0x1d93e,0x16470,0x1b23c, // 230 - 0x16438,0x1b21e,0x1641c,0x1640e,0x122f0,0x1917c,0x166f0,0x12278,0x1913e,0x16678, // 240 - 0x1b33e,0x1663c,0x1221e,0x1661e,0x1f91a,0x1237c,0x1fb3a,0x1677c,0x1233e,0x1673e, // 250 - 0x1f23a,0x1f67a,0x1e47a,0x1ecfa,0x1c8fa,0x1d9fa,0x191fa,0x162e0,0x1b178,0x1d8be, // 260 - 0x16270,0x1b13c,0x16238,0x1b11e,0x1621c,0x1620e,0x12178,0x190be,0x16378,0x1213c, // 270 - 0x1633c,0x1211e,0x1631e,0x121be,0x163be,0x16170,0x1b0bc,0x16138,0x1b09e,0x1611c, // 280 - 0x1610e,0x120bc,0x161bc,0x1209e,0x1619e,0x160b8,0x1b05e,0x1609c,0x1608e,0x1205e, // 290 - 0x160de,0x1605c,0x1604e,0x115e0,0x18af8,0x1c57e,0x114f0,0x18a7c,0x11478,0x18a3e, // 300 - 0x1143c,0x1141e,0x1f8b4,0x116f8,0x18b7e,0x1f8b2,0x1167c,0x1163e,0x1f174,0x1177e, // 310 - 0x1f172,0x1e2f4,0x1e2f2,0x1c5f4,0x1c5f2,0x18bf4,0x18bf2,0x135c0,0x19af0,0x1cd7c, // 320 - 0x134e0,0x19a78,0x1cd3e,0x13470,0x19a3c,0x13438,0x19a1e,0x1341c,0x1340e,0x112f0, // 330 - 0x1897c,0x136f0,0x11278,0x1893e,0x13678,0x19b3e,0x1363c,0x1121e,0x1361e,0x1f89a, // 340 - 0x1137c,0x1f9ba,0x1377c,0x1133e,0x1373e,0x1f13a,0x1f37a,0x1e27a,0x1e6fa,0x1c4fa, // 350 - 0x1cdfa,0x189fa,0x1bae0,0x1dd78,0x1eebe,0x174c0,0x1ba70,0x1dd3c,0x17460,0x1ba38, // 360 - 0x1dd1e,0x17430,0x1ba1c,0x17418,0x1ba0e,0x1740c,0x132e0,0x19978,0x1ccbe,0x176e0, // 370 - 0x13270,0x1993c,0x17670,0x1bb3c,0x1991e,0x17638,0x1321c,0x1761c,0x1320e,0x1760e, // 380 - 0x11178,0x188be,0x13378,0x1113c,0x17778,0x1333c,0x1111e,0x1773c,0x1331e,0x1771e, // 390 - 0x111be,0x133be,0x177be,0x172c0,0x1b970,0x1dcbc,0x17260,0x1b938,0x1dc9e,0x17230, // 400 - 0x1b91c,0x17218,0x1b90e,0x1720c,0x17206,0x13170,0x198bc,0x17370,0x13138,0x1989e, // 410 - 0x17338,0x1b99e,0x1731c,0x1310e,0x1730e,0x110bc,0x131bc,0x1109e,0x173bc,0x1319e, // 420 - 0x1739e,0x17160,0x1b8b8,0x1dc5e,0x17130,0x1b89c,0x17118,0x1b88e,0x1710c,0x17106, // 430 - 0x130b8,0x1985e,0x171b8,0x1309c,0x1719c,0x1308e,0x1718e,0x1105e,0x130de,0x171de, // 440 - 0x170b0,0x1b85c,0x17098,0x1b84e,0x1708c,0x17086,0x1305c,0x170dc,0x1304e,0x170ce, // 450 - 0x17058,0x1b82e,0x1704c,0x17046,0x1302e,0x1706e,0x1702c,0x17026,0x10af0,0x1857c, // 460 - 0x10a78,0x1853e,0x10a3c,0x10a1e,0x10b7c,0x10b3e,0x1f0ba,0x1e17a,0x1c2fa,0x185fa, // 470 - 0x11ae0,0x18d78,0x1c6be,0x11a70,0x18d3c,0x11a38,0x18d1e,0x11a1c,0x11a0e,0x10978, // 480 - 0x184be,0x11b78,0x1093c,0x11b3c,0x1091e,0x11b1e,0x109be,0x11bbe,0x13ac0,0x19d70, // 490 - 0x1cebc,0x13a60,0x19d38,0x1ce9e,0x13a30,0x19d1c,0x13a18,0x19d0e,0x13a0c,0x13a06, // 500 - 0x11970,0x18cbc,0x13b70,0x11938,0x18c9e,0x13b38,0x1191c,0x13b1c,0x1190e,0x13b0e, // 510 - 0x108bc,0x119bc,0x1089e,0x13bbc,0x1199e,0x13b9e,0x1bd60,0x1deb8,0x1ef5e,0x17a40, // 520 - 0x1bd30,0x1de9c,0x17a20,0x1bd18,0x1de8e,0x17a10,0x1bd0c,0x17a08,0x1bd06,0x17a04, // 530 - 0x13960,0x19cb8,0x1ce5e,0x17b60,0x13930,0x19c9c,0x17b30,0x1bd9c,0x19c8e,0x17b18, // 540 - 0x1390c,0x17b0c,0x13906,0x17b06,0x118b8,0x18c5e,0x139b8,0x1189c,0x17bb8,0x1399c, // 550 - 0x1188e,0x17b9c,0x1398e,0x17b8e,0x1085e,0x118de,0x139de,0x17bde,0x17940,0x1bcb0, // 560 - 0x1de5c,0x17920,0x1bc98,0x1de4e,0x17910,0x1bc8c,0x17908,0x1bc86,0x17904,0x17902, // 570 - 0x138b0,0x19c5c,0x179b0,0x13898,0x19c4e,0x17998,0x1bcce,0x1798c,0x13886,0x17986, // 580 - 0x1185c,0x138dc,0x1184e,0x179dc,0x138ce,0x179ce,0x178a0,0x1bc58,0x1de2e,0x17890, // 590 - 0x1bc4c,0x17888,0x1bc46,0x17884,0x17882,0x13858,0x19c2e,0x178d8,0x1384c,0x178cc, // 600 - 0x13846,0x178c6,0x1182e,0x1386e,0x178ee,0x17850,0x1bc2c,0x17848,0x1bc26,0x17844, // 610 - 0x17842,0x1382c,0x1786c,0x13826,0x17866,0x17828,0x1bc16,0x17824,0x17822,0x13816, // 620 - 0x17836,0x10578,0x182be,0x1053c,0x1051e,0x105be,0x10d70,0x186bc,0x10d38,0x1869e, // 630 - 0x10d1c,0x10d0e,0x104bc,0x10dbc,0x1049e,0x10d9e,0x11d60,0x18eb8,0x1c75e,0x11d30, // 640 - 0x18e9c,0x11d18,0x18e8e,0x11d0c,0x11d06,0x10cb8,0x1865e,0x11db8,0x10c9c,0x11d9c, // 650 - 0x10c8e,0x11d8e,0x1045e,0x10cde,0x11dde,0x13d40,0x19eb0,0x1cf5c,0x13d20,0x19e98, // 660 - 0x1cf4e,0x13d10,0x19e8c,0x13d08,0x19e86,0x13d04,0x13d02,0x11cb0,0x18e5c,0x13db0, // 670 - 0x11c98,0x18e4e,0x13d98,0x19ece,0x13d8c,0x11c86,0x13d86,0x10c5c,0x11cdc,0x10c4e, // 680 - 0x13ddc,0x11cce,0x13dce,0x1bea0,0x1df58,0x1efae,0x1be90,0x1df4c,0x1be88,0x1df46, // 690 - 0x1be84,0x1be82,0x13ca0,0x19e58,0x1cf2e,0x17da0,0x13c90,0x19e4c,0x17d90,0x1becc, // 700 - 0x19e46,0x17d88,0x13c84,0x17d84,0x13c82,0x17d82,0x11c58,0x18e2e,0x13cd8,0x11c4c, // 710 - 0x17dd8,0x13ccc,0x11c46,0x17dcc,0x13cc6,0x17dc6,0x10c2e,0x11c6e,0x13cee,0x17dee, // 720 - 0x1be50,0x1df2c,0x1be48,0x1df26,0x1be44,0x1be42,0x13c50,0x19e2c,0x17cd0,0x13c48, // 730 - 0x19e26,0x17cc8,0x1be66,0x17cc4,0x13c42,0x17cc2,0x11c2c,0x13c6c,0x11c26,0x17cec, // 740 - 0x13c66,0x17ce6,0x1be28,0x1df16,0x1be24,0x1be22,0x13c28,0x19e16,0x17c68,0x13c24, // 750 - 0x17c64,0x13c22,0x17c62,0x11c16,0x13c36,0x17c76,0x1be14,0x1be12,0x13c14,0x17c34, // 760 - 0x13c12,0x17c32,0x102bc,0x1029e,0x106b8,0x1835e,0x1069c,0x1068e,0x1025e,0x106de, // 770 - 0x10eb0,0x1875c,0x10e98,0x1874e,0x10e8c,0x10e86,0x1065c,0x10edc,0x1064e,0x10ece, // 780 - 0x11ea0,0x18f58,0x1c7ae,0x11e90,0x18f4c,0x11e88,0x18f46,0x11e84,0x11e82,0x10e58, // 790 - 0x1872e,0x11ed8,0x18f6e,0x11ecc,0x10e46,0x11ec6,0x1062e,0x10e6e,0x11eee,0x19f50, // 800 - 0x1cfac,0x19f48,0x1cfa6,0x19f44,0x19f42,0x11e50,0x18f2c,0x13ed0,0x19f6c,0x18f26, // 810 - 0x13ec8,0x11e44,0x13ec4,0x11e42,0x13ec2,0x10e2c,0x11e6c,0x10e26,0x13eec,0x11e66, // 820 - 0x13ee6,0x1dfa8,0x1efd6,0x1dfa4,0x1dfa2,0x19f28,0x1cf96,0x1bf68,0x19f24,0x1bf64, // 830 - 0x19f22,0x1bf62,0x11e28,0x18f16,0x13e68,0x11e24,0x17ee8,0x13e64,0x11e22,0x17ee4, // 840 - 0x13e62,0x17ee2,0x10e16,0x11e36,0x13e76,0x17ef6,0x1df94,0x1df92,0x19f14,0x1bf34, // 850 - 0x19f12,0x1bf32,0x11e14,0x13e34,0x11e12,0x17e74,0x13e32,0x17e72,0x1df8a,0x19f0a, // 860 - 0x1bf1a,0x11e0a,0x13e1a,0x17e3a,0x1035c,0x1034e,0x10758,0x183ae,0x1074c,0x10746, // 870 - 0x1032e,0x1076e,0x10f50,0x187ac,0x10f48,0x187a6,0x10f44,0x10f42,0x1072c,0x10f6c, // 880 - 0x10726,0x10f66,0x18fa8,0x1c7d6,0x18fa4,0x18fa2,0x10f28,0x18796,0x11f68,0x18fb6, // 890 - 0x11f64,0x10f22,0x11f62,0x10716,0x10f36,0x11f76,0x1cfd4,0x1cfd2,0x18f94,0x19fb4, // 900 - 0x18f92,0x19fb2,0x10f14,0x11f34,0x10f12,0x13f74,0x11f32,0x13f72,0x1cfca,0x18f8a, // 910 - 0x19f9a,0x10f0a,0x11f1a,0x13f3a,0x103ac,0x103a6,0x107a8,0x183d6,0x107a4,0x107a2, // 920 - 0x10396,0x107b6,0x187d4,0x187d2,0x10794,0x10fb4,0x10792,0x10fb2,0x1c7ea) // 929 - ); // end of $clusters array - - /** - * Array of factors of the Reed-Solomon polynomial equations used for error correction; one sub array for each correction level (0-8). - * @protected - */ - protected $rsfactors = array( - array( // ECL 0 (2 factors) ------------------------------------------------------------------------------- - 0x01b,0x395), // 2 - array( // ECL 1 (4 factors) ------------------------------------------------------------------------------- - 0x20a,0x238,0x2d3,0x329), // 4 - array( // ECL 2 (8 factors) ------------------------------------------------------------------------------- - 0x0ed,0x134,0x1b4,0x11c,0x286,0x28d,0x1ac,0x17b), // 8 - array( // ECL 3 (16 factors) ------------------------------------------------------------------------------ - 0x112,0x232,0x0e8,0x2f3,0x257,0x20c,0x321,0x084,0x127,0x074,0x1ba,0x1ac,0x127,0x02a,0x0b0,0x041),// 16 - array( // ECL 4 (32 factors) ------------------------------------------------------------------------------ - 0x169,0x23f,0x39a,0x20d,0x0b0,0x24a,0x280,0x141,0x218,0x2e6,0x2a5,0x2e6,0x2af,0x11c,0x0c1,0x205, // 16 - 0x111,0x1ee,0x107,0x093,0x251,0x320,0x23b,0x140,0x323,0x085,0x0e7,0x186,0x2ad,0x14a,0x03f,0x19a),// 32 - array( // ECL 5 (64 factors) ------------------------------------------------------------------------------ - 0x21b,0x1a6,0x006,0x05d,0x35e,0x303,0x1c5,0x06a,0x262,0x11f,0x06b,0x1f9,0x2dd,0x36d,0x17d,0x264, // 16 - 0x2d3,0x1dc,0x1ce,0x0ac,0x1ae,0x261,0x35a,0x336,0x21f,0x178,0x1ff,0x190,0x2a0,0x2fa,0x11b,0x0b8, // 32 - 0x1b8,0x023,0x207,0x01f,0x1cc,0x252,0x0e1,0x217,0x205,0x160,0x25d,0x09e,0x28b,0x0c9,0x1e8,0x1f6, // 48 - 0x288,0x2dd,0x2cd,0x053,0x194,0x061,0x118,0x303,0x348,0x275,0x004,0x17d,0x34b,0x26f,0x108,0x21f),// 64 - array( // ECL 6 (128 factors) ----------------------------------------------------------------------------- - 0x209,0x136,0x360,0x223,0x35a,0x244,0x128,0x17b,0x035,0x30b,0x381,0x1bc,0x190,0x39d,0x2ed,0x19f, // 16 - 0x336,0x05d,0x0d9,0x0d0,0x3a0,0x0f4,0x247,0x26c,0x0f6,0x094,0x1bf,0x277,0x124,0x38c,0x1ea,0x2c0, // 32 - 0x204,0x102,0x1c9,0x38b,0x252,0x2d3,0x2a2,0x124,0x110,0x060,0x2ac,0x1b0,0x2ae,0x25e,0x35c,0x239, // 48 - 0x0c1,0x0db,0x081,0x0ba,0x0ec,0x11f,0x0c0,0x307,0x116,0x0ad,0x028,0x17b,0x2c8,0x1cf,0x286,0x308, // 64 - 0x0ab,0x1eb,0x129,0x2fb,0x09c,0x2dc,0x05f,0x10e,0x1bf,0x05a,0x1fb,0x030,0x0e4,0x335,0x328,0x382, // 80 - 0x310,0x297,0x273,0x17a,0x17e,0x106,0x17c,0x25a,0x2f2,0x150,0x059,0x266,0x057,0x1b0,0x29e,0x268, // 96 - 0x09d,0x176,0x0f2,0x2d6,0x258,0x10d,0x177,0x382,0x34d,0x1c6,0x162,0x082,0x32e,0x24b,0x324,0x022, // 112 - 0x0d3,0x14a,0x21b,0x129,0x33b,0x361,0x025,0x205,0x342,0x13b,0x226,0x056,0x321,0x004,0x06c,0x21b),// 128 - array( // ECL 7 (256 factors) ----------------------------------------------------------------------------- - 0x20c,0x37e,0x04b,0x2fe,0x372,0x359,0x04a,0x0cc,0x052,0x24a,0x2c4,0x0fa,0x389,0x312,0x08a,0x2d0, // 16 - 0x35a,0x0c2,0x137,0x391,0x113,0x0be,0x177,0x352,0x1b6,0x2dd,0x0c2,0x118,0x0c9,0x118,0x33c,0x2f5, // 32 - 0x2c6,0x32e,0x397,0x059,0x044,0x239,0x00b,0x0cc,0x31c,0x25d,0x21c,0x391,0x321,0x2bc,0x31f,0x089, // 48 - 0x1b7,0x1a2,0x250,0x29c,0x161,0x35b,0x172,0x2b6,0x145,0x0f0,0x0d8,0x101,0x11c,0x225,0x0d1,0x374, // 64 - 0x13b,0x046,0x149,0x319,0x1ea,0x112,0x36d,0x0a2,0x2ed,0x32c,0x2ac,0x1cd,0x14e,0x178,0x351,0x209, // 80 - 0x133,0x123,0x323,0x2c8,0x013,0x166,0x18f,0x38c,0x067,0x1ff,0x033,0x008,0x205,0x0e1,0x121,0x1d6, // 96 - 0x27d,0x2db,0x042,0x0ff,0x395,0x10d,0x1cf,0x33e,0x2da,0x1b1,0x350,0x249,0x088,0x21a,0x38a,0x05a, // 112 - 0x002,0x122,0x2e7,0x0c7,0x28f,0x387,0x149,0x031,0x322,0x244,0x163,0x24c,0x0bc,0x1ce,0x00a,0x086, // 128 - 0x274,0x140,0x1df,0x082,0x2e3,0x047,0x107,0x13e,0x176,0x259,0x0c0,0x25d,0x08e,0x2a1,0x2af,0x0ea, // 144 - 0x2d2,0x180,0x0b1,0x2f0,0x25f,0x280,0x1c7,0x0c1,0x2b1,0x2c3,0x325,0x281,0x030,0x03c,0x2dc,0x26d, // 160 - 0x37f,0x220,0x105,0x354,0x28f,0x135,0x2b9,0x2f3,0x2f4,0x03c,0x0e7,0x305,0x1b2,0x1a5,0x2d6,0x210, // 176 - 0x1f7,0x076,0x031,0x31b,0x020,0x090,0x1f4,0x0ee,0x344,0x18a,0x118,0x236,0x13f,0x009,0x287,0x226, // 192 - 0x049,0x392,0x156,0x07e,0x020,0x2a9,0x14b,0x318,0x26c,0x03c,0x261,0x1b9,0x0b4,0x317,0x37d,0x2f2, // 208 - 0x25d,0x17f,0x0e4,0x2ed,0x2f8,0x0d5,0x036,0x129,0x086,0x036,0x342,0x12b,0x39a,0x0bf,0x38e,0x214, // 224 - 0x261,0x33d,0x0bd,0x014,0x0a7,0x01d,0x368,0x1c1,0x053,0x192,0x029,0x290,0x1f9,0x243,0x1e1,0x0ad, // 240 - 0x194,0x0fb,0x2b0,0x05f,0x1f1,0x22b,0x282,0x21f,0x133,0x09f,0x39c,0x22e,0x288,0x037,0x1f1,0x00a),// 256 - array( // ECL 8 (512 factors) ----------------------------------------------------------------------------- - 0x160,0x04d,0x175,0x1f8,0x023,0x257,0x1ac,0x0cf,0x199,0x23e,0x076,0x1f2,0x11d,0x17c,0x15e,0x1ec, // 16 - 0x0c5,0x109,0x398,0x09b,0x392,0x12b,0x0e5,0x283,0x126,0x367,0x132,0x058,0x057,0x0c1,0x160,0x30d, // 32 - 0x34e,0x04b,0x147,0x208,0x1b3,0x21f,0x0cb,0x29a,0x0f9,0x15a,0x30d,0x26d,0x280,0x10c,0x31a,0x216, // 48 - 0x21b,0x30d,0x198,0x186,0x284,0x066,0x1dc,0x1f3,0x122,0x278,0x221,0x025,0x35a,0x394,0x228,0x029, // 64 - 0x21e,0x121,0x07a,0x110,0x17f,0x320,0x1e5,0x062,0x2f0,0x1d8,0x2f9,0x06b,0x310,0x35c,0x292,0x2e5, // 80 - 0x122,0x0cc,0x2a9,0x197,0x357,0x055,0x063,0x03e,0x1e2,0x0b4,0x014,0x129,0x1c3,0x251,0x391,0x08e, // 96 - 0x328,0x2ac,0x11f,0x218,0x231,0x04c,0x28d,0x383,0x2d9,0x237,0x2e8,0x186,0x201,0x0c0,0x204,0x102, // 112 - 0x0f0,0x206,0x31a,0x18b,0x300,0x350,0x033,0x262,0x180,0x0a8,0x0be,0x33a,0x148,0x254,0x312,0x12f, // 128 - 0x23a,0x17d,0x19f,0x281,0x09c,0x0ed,0x097,0x1ad,0x213,0x0cf,0x2a4,0x2c6,0x059,0x0a8,0x130,0x192, // 144 - 0x028,0x2c4,0x23f,0x0a2,0x360,0x0e5,0x041,0x35d,0x349,0x200,0x0a4,0x1dd,0x0dd,0x05c,0x166,0x311, // 160 - 0x120,0x165,0x352,0x344,0x33b,0x2e0,0x2c3,0x05e,0x008,0x1ee,0x072,0x209,0x002,0x1f3,0x353,0x21f, // 176 - 0x098,0x2d9,0x303,0x05f,0x0f8,0x169,0x242,0x143,0x358,0x31d,0x121,0x033,0x2ac,0x1d2,0x215,0x334, // 192 - 0x29d,0x02d,0x386,0x1c4,0x0a7,0x156,0x0f4,0x0ad,0x023,0x1cf,0x28b,0x033,0x2bb,0x24f,0x1c4,0x242, // 208 - 0x025,0x07c,0x12a,0x14c,0x228,0x02b,0x1ab,0x077,0x296,0x309,0x1db,0x352,0x2fc,0x16c,0x242,0x38f, // 224 - 0x11b,0x2c7,0x1d8,0x1a4,0x0f5,0x120,0x252,0x18a,0x1ff,0x147,0x24d,0x309,0x2bb,0x2b0,0x02b,0x198, // 240 - 0x34a,0x17f,0x2d1,0x209,0x230,0x284,0x2ca,0x22f,0x03e,0x091,0x369,0x297,0x2c9,0x09f,0x2a0,0x2d9, // 256 - 0x270,0x03b,0x0c1,0x1a1,0x09e,0x0d1,0x233,0x234,0x157,0x2b5,0x06d,0x260,0x233,0x16d,0x0b5,0x304, // 272 - 0x2a5,0x136,0x0f8,0x161,0x2c4,0x19a,0x243,0x366,0x269,0x349,0x278,0x35c,0x121,0x218,0x023,0x309, // 288 - 0x26a,0x24a,0x1a8,0x341,0x04d,0x255,0x15a,0x10d,0x2f5,0x278,0x2b7,0x2ef,0x14b,0x0f7,0x0b8,0x02d, // 304 - 0x313,0x2a8,0x012,0x042,0x197,0x171,0x036,0x1ec,0x0e4,0x265,0x33e,0x39a,0x1b5,0x207,0x284,0x389, // 320 - 0x315,0x1a4,0x131,0x1b9,0x0cf,0x12c,0x37c,0x33b,0x08d,0x219,0x17d,0x296,0x201,0x038,0x0fc,0x155, // 336 - 0x0f2,0x31d,0x346,0x345,0x2d0,0x0e0,0x133,0x277,0x03d,0x057,0x230,0x136,0x2f4,0x299,0x18d,0x328, // 352 - 0x353,0x135,0x1d9,0x31b,0x17a,0x01f,0x287,0x393,0x1cb,0x326,0x24e,0x2db,0x1a9,0x0d8,0x224,0x0f9, // 368 - 0x141,0x371,0x2bb,0x217,0x2a1,0x30e,0x0d2,0x32f,0x389,0x12f,0x34b,0x39a,0x119,0x049,0x1d5,0x317, // 384 - 0x294,0x0a2,0x1f2,0x134,0x09b,0x1a6,0x38b,0x331,0x0bb,0x03e,0x010,0x1a9,0x217,0x150,0x11e,0x1b5, // 400 - 0x177,0x111,0x262,0x128,0x0b7,0x39b,0x074,0x29b,0x2ef,0x161,0x03e,0x16e,0x2b3,0x17b,0x2af,0x34a, // 416 - 0x025,0x165,0x2d0,0x2e6,0x14a,0x005,0x027,0x39b,0x137,0x1a8,0x0f2,0x2ed,0x141,0x036,0x29d,0x13c, // 432 - 0x156,0x12b,0x216,0x069,0x29b,0x1e8,0x280,0x2a0,0x240,0x21c,0x13c,0x1e6,0x2d1,0x262,0x02e,0x290, // 448 - 0x1bf,0x0ab,0x268,0x1d0,0x0be,0x213,0x129,0x141,0x2fa,0x2f0,0x215,0x0af,0x086,0x00e,0x17d,0x1b1, // 464 - 0x2cd,0x02d,0x06f,0x014,0x254,0x11c,0x2e0,0x08a,0x286,0x19b,0x36d,0x29d,0x08d,0x397,0x02d,0x30c, // 480 - 0x197,0x0a4,0x14c,0x383,0x0a5,0x2d6,0x258,0x145,0x1f2,0x28f,0x165,0x2f0,0x300,0x0df,0x351,0x287, // 496 - 0x03f,0x136,0x35f,0x0fb,0x16e,0x130,0x11a,0x2e2,0x2a3,0x19a,0x185,0x0f4,0x01f,0x079,0x12f,0x107) // 512 - ); - - /** - * This is the class constructor. - * Creates a PDF417 object - * @param string $code code to represent using PDF417 - * @param int $ecl error correction level (0-8); default -1 = automatic correction level - * @param float $aspectratio the width to height of the symbol (excluding quiet zones) - * @param array $macro information for macro block - * @public - */ - public function __construct($code, $ecl=-1, $aspectratio=2, $macro=array()) { - $barcode_array = array(); - if ((is_null($code)) OR ($code == '\0') OR ($code == '')) { - return false; - } - // get the input sequence array - $sequence = $this->getInputSequences($code); - $codewords = array(); // array of code-words - foreach($sequence as $seq) { - $cw = $this->getCompaction($seq[0], $seq[1], true); - $codewords = array_merge($codewords, $cw); - } - if ($codewords[0] == 900) { - // Text Alpha is the default mode, so remove the first code - array_shift($codewords); - } - // count number of codewords - $numcw = count($codewords); - if ($numcw > 925) { - // reached maximum data codeword capacity - return false; - } - // build macro control block codewords - if (!empty($macro)) { - $macrocw = array(); - // beginning of macro control block - $macrocw[] = 928; - // segment index - $cw = $this->getCompaction(902, sprintf('%05d', $macro['segment_index']), false); - $macrocw = array_merge($macrocw, $cw); - // file ID - $cw = $this->getCompaction(900, $macro['file_id'], false); - $macrocw = array_merge($macrocw, $cw); - // optional fields - $optmodes = array(900,902,902,900,900,902,902); - $optsize = array(-1,2,4,-1,-1,-1,2); - foreach ($optmodes as $k => $omode) { - if (isset($macro['option_'.$k])) { - $macrocw[] = 923; - $macrocw[] = $k; - if ($optsize[$k] == 2) { - $macro['option_'.$k] = sprintf('%05d', $macro['option_'.$k]); - } elseif ($optsize[$k] == 4) { - $macro['option_'.$k] = sprintf('%010d', $macro['option_'.$k]); - } - $cw = $this->getCompaction($omode, $macro['option_'.$k], false); - $macrocw = array_merge($macrocw, $cw); - } - } - if ($macro['segment_index'] == ($macro['segment_total'] - 1)) { - // end of control block - $macrocw[] = 922; - } - // update total codewords - $numcw += count($macrocw); - } - // set error correction level - $ecl = $this->getErrorCorrectionLevel($ecl, $numcw); - // number of codewords for error correction - $errsize = (2 << $ecl); - // calculate number of columns (number of codewords per row) and rows - $nce = ($numcw + $errsize + 1); - $cols = round((sqrt(4761 + (68 * $aspectratio * ROWHEIGHT * $nce)) - 69) / 34); - // adjust cols - if ($cols < 1) { - $cols = 1; - } elseif ($cols > 30) { - $cols = 30; - } - $rows = ceil($nce / $cols); - $size = ($cols * $rows); - // adjust rows - if (($rows < 3) OR ($rows > 90)) { - if ($rows < 3) { - $rows = 3; - } elseif ($rows > 90) { - $rows = 90; - } - $cols = ceil($size / $rows); - $size = ($cols * $rows); - } - if ($size > 928) { - // set dimensions to get maximum capacity - if (abs($aspectratio - (17 * 29 / 32)) < abs($aspectratio - (17 * 16 / 58))) { - $cols = 29; - $rows = 32; - } else { - $cols = 16; - $rows = 58; - } - $size = 928; - } - // calculate padding - $pad = ($size - $nce); - if ($pad > 0) { - if (($size - $rows) == $nce) { - --$rows; - $size -= $rows; - } else { - // add pading - $codewords = array_merge($codewords, array_fill(0, $pad, 900)); - } - } - if (!empty($macro)) { - // add macro section - $codewords = array_merge($codewords, $macrocw); - } - // Symbol Length Descriptor (number of data codewords including Symbol Length Descriptor and pad codewords) - $sld = $size - $errsize; - // add symbol length description - array_unshift($codewords, $sld); - // calculate error correction - $ecw = $this->getErrorCorrection($codewords, $ecl); - // add error correction codewords - $codewords = array_merge($codewords, $ecw); - // add horizontal quiet zones to start and stop patterns - $pstart = str_repeat('0', QUIETH).$this->start_pattern; - $pstop = $this->stop_pattern.str_repeat('0', QUIETH); - $barcode_array['num_rows'] = ($rows * ROWHEIGHT) + (2 * QUIETV); - $barcode_array['num_cols'] = (($cols + 2) * 17) + 35 + (2 * QUIETH); - $barcode_array['bcode'] = array(); - // build rows for vertical quiet zone - if (QUIETV > 0) { - $empty_row = array_fill(0, $barcode_array['num_cols'], 0); - for ($i = 0; $i < QUIETV; ++$i) { - // add vertical quiet rows - $barcode_array['bcode'][] = $empty_row; - } - } - $k = 0; // codeword index - $cid = 0; // initial cluster - // for each row - for ($r = 0; $r < $rows; ++$r) { - // row start code - $row = $pstart; - switch ($cid) { - case 0: { - $L = ((30 * intval($r / 3)) + intval(($rows - 1) / 3)); - break; - } - case 1: { - $L = ((30 * intval($r / 3)) + ($ecl * 3) + (($rows - 1) % 3)); - break; - } - case 2: { - $L = ((30 * intval($r / 3)) + ($cols - 1)); - break; - } - } - // left row indicator - $row .= sprintf('%17b', $this->clusters[$cid][$L]); - // for each column - for ($c = 0; $c < $cols; ++$c) { - $row .= sprintf('%17b', $this->clusters[$cid][$codewords[$k]]); - ++$k; - } - switch ($cid) { - case 0: { - $L = ((30 * intval($r / 3)) + ($cols - 1)); - break; - } - case 1: { - $L = ((30 * intval($r / 3)) + intval(($rows - 1) / 3)); - break; - } - case 2: { - $L = ((30 * intval($r / 3)) + ($ecl * 3) + (($rows - 1) % 3)); - break; - } - } - // right row indicator - $row .= sprintf('%17b', $this->clusters[$cid][$L]); - // row stop code - $row .= $pstop; - // convert the string to array - $arow = preg_split('//', $row, -1, PREG_SPLIT_NO_EMPTY); - // duplicate row to get the desired height - for ($h = 0; $h < ROWHEIGHT; ++$h) { - $barcode_array['bcode'][] = $arow; - } - ++$cid; - if ($cid > 2) { - $cid = 0; - } - } - if (QUIETV > 0) { - for ($i = 0; $i < QUIETV; ++$i) { - // add vertical quiet rows - $barcode_array['bcode'][] = $empty_row; - } - } - $this->barcode_array = $barcode_array; - } - - /** - * Returns a barcode array which is readable by TCPDF - * @return array barcode array readable by TCPDF; - * @public - */ - public function getBarcodeArray() { - return $this->barcode_array; - } - - /** - * Returns the error correction level (0-8) to be used - * @param int $ecl error correction level - * @param int $numcw number of data codewords - * @return int error correction level - * @protected - */ - protected function getErrorCorrectionLevel($ecl, $numcw) { - $maxecl = 8; // starting error level - // check for automatic levels - if (($ecl < 0) OR ($ecl > 8)) { - if ($numcw < 41) { - $ecl = 2; - } elseif ($numcw < 161) { - $ecl = 3; - } elseif ($numcw < 321) { - $ecl = 4; - } elseif ($numcw < 864) { - $ecl = 5; - } else { - $ecl = $maxecl; - } - } - // get maximum correction level - $maxerrsize = (928 - $numcw); // available codewords for error - while ($maxecl > 0) { - $errsize = (2 << $ecl); - if ($maxerrsize >= $errsize) { - break; - } - --$maxecl; - } - if ($ecl > $maxecl) { - $ecl = $maxecl; - } - return $ecl; - } - - /** - * Returns the error correction codewords - * @param array $cw array of codewords including Symbol Length Descriptor and pad - * @param int $ecl error correction level 0-8 - * @return array of error correction codewords - * @protected - */ - protected function getErrorCorrection($cw, $ecl) { - // get error correction coefficients - $ecc = $this->rsfactors[$ecl]; - // number of error correction factors - $eclsize = (2 << $ecl); - // maximum index for $rsfactors[$ecl] - $eclmaxid = ($eclsize - 1); - // initialize array of error correction codewords - $ecw = array_fill(0, $eclsize, 0); - // for each data codeword - foreach($cw as $k => $d) { - $t1 = ($d + $ecw[$eclmaxid]) % 929; - for ($j = $eclmaxid; $j > 0; --$j) { - $t2 = ($t1 * $ecc[$j]) % 929; - $t3 = 929 - $t2; - $ecw[$j] = ($ecw[($j - 1)] + $t3) % 929; - } - $t2 = ($t1 * $ecc[0]) % 929; - $t3 = 929 - $t2; - $ecw[0] = $t3 % 929; - } - foreach($ecw as $j => $e) { - if ($e != 0) { - $ecw[$j] = 929 - $e; - } - } - $ecw = array_reverse($ecw); - return $ecw; - } - - /** - * Create array of sequences from input - * @param string $code code - * @return array bi-dimensional array containing characters and classification - * @protected - */ - protected function getInputSequences($code) { - $sequence_array = array(); // array to be returned - $numseq = array(); - // get numeric sequences - preg_match_all('/([0-9]{13,44})/', $code, $numseq, PREG_OFFSET_CAPTURE); - $numseq[1][] = array('', strlen($code)); - $offset = 0; - foreach($numseq[1] as $seq) { - $seqlen = strlen($seq[0]); - if ($seq[1] > 0) { - // extract text sequence before the number sequence - $prevseq = substr($code, $offset, ($seq[1] - $offset)); - $textseq = array(); - // get text sequences - preg_match_all('/([\x09\x0a\x0d\x20-\x7e]{5,})/', $prevseq, $textseq, PREG_OFFSET_CAPTURE); - $textseq[1][] = array('', strlen($prevseq)); - $txtoffset = 0; - foreach($textseq[1] as $txtseq) { - $txtseqlen = strlen($txtseq[0]); - if ($txtseq[1] > 0) { - // extract byte sequence before the text sequence - $prevtxtseq = substr($prevseq, $txtoffset, ($txtseq[1] - $txtoffset)); - if (strlen($prevtxtseq) > 0) { - // add BYTE sequence - if ((strlen($prevtxtseq) == 1) AND ((count($sequence_array) > 0) AND ($sequence_array[(count($sequence_array) - 1)][0] == 900))) { - $sequence_array[] = array(913, $prevtxtseq); - } elseif ((strlen($prevtxtseq) % 6) == 0) { - $sequence_array[] = array(924, $prevtxtseq); - } else { - $sequence_array[] = array(901, $prevtxtseq); - } - } - } - if ($txtseqlen > 0) { - // add numeric sequence - $sequence_array[] = array(900, $txtseq[0]); - } - $txtoffset = $txtseq[1] + $txtseqlen; - } - } - if ($seqlen > 0) { - // add numeric sequence - $sequence_array[] = array(902, $seq[0]); - } - $offset = $seq[1] + $seqlen; - } - return $sequence_array; - } - - /** - * Compact data by mode. - * @param int $mode compaction mode number - * @param string $code data to compact - * @param boolean $addmode if true add the mode codeword at first position - * @return array of codewords - * @protected - */ - protected function getCompaction($mode, $code, $addmode=true) { - $cw = array(); // array of codewords to return - switch($mode) { - case 900: { // Text Compaction mode latch - $submode = 0; // default Alpha sub-mode - $txtarr = array(); // array of characters and sub-mode switching characters - $codelen = strlen($code); - for ($i = 0; $i < $codelen; ++$i) { - $chval = ord($code[$i]); - if (($k = array_search($chval, $this->textsubmodes[$submode])) !== false) { - // we are on the same sub-mode - $txtarr[] = $k; - } else { - // the sub-mode is changed - for ($s = 0; $s < 4; ++$s) { - // search new sub-mode - if (($s != $submode) AND (($k = array_search($chval, $this->textsubmodes[$s])) !== false)) { - // $s is the new submode - if (((($i + 1) == $codelen) OR ((($i + 1) < $codelen) AND (array_search(ord($code[($i + 1)]), $this->textsubmodes[$submode]) !== false))) AND (($s == 3) OR (($s == 0) AND ($submode == 1)))) { - // shift (temporary change only for this char) - if ($s == 3) { - // shift to puntuaction - $txtarr[] = 29; - } else { - // shift from lower to alpha - $txtarr[] = 27; - } - } else { - // latch - $txtarr = array_merge($txtarr, $this->textlatch[''.$submode.$s]); - // set new submode - $submode = $s; - } - // add characted code to array - $txtarr[] = $k; - break; - } - } - } - } - $txtarrlen = count($txtarr); - if (($txtarrlen % 2) != 0) { - // add padding - $txtarr[] = 29; - ++$txtarrlen; - } - // calculate codewords - for ($i = 0; $i < $txtarrlen; $i += 2) { - $cw[] = (30 * $txtarr[$i]) + $txtarr[($i + 1)]; - } - break; - } - case 901: - case 924: { // Byte Compaction mode latch - while (($codelen = strlen($code)) > 0) { - if ($codelen > 6) { - $rest = substr($code, 6); - $code = substr($code, 0, 6); - $sublen = 6; - } else { - $rest = ''; - $sublen = strlen($code); - } - if ($sublen == 6) { - $t = bcmul(''.ord($code[0]), '1099511627776'); - $t = bcadd($t, bcmul(''.ord($code[1]), '4294967296')); - $t = bcadd($t, bcmul(''.ord($code[2]), '16777216')); - $t = bcadd($t, bcmul(''.ord($code[3]), '65536')); - $t = bcadd($t, bcmul(''.ord($code[4]), '256')); - $t = bcadd($t, ''.ord($code[5])); - // tmp array for the 6 bytes block - $cw6 = array(); - do { - $d = bcmod($t, '900'); - $t = bcdiv($t, '900'); - // prepend the value to the beginning of the array - array_unshift($cw6, $d); - } while ($t != '0'); - // append the result array at the end - $cw = array_merge($cw, $cw6); - } else { - for ($i = 0; $i < $sublen; ++$i) { - $cw[] = ord($code[$i]); - } - } - $code = $rest; - } - break; - } - case 902: { // Numeric Compaction mode latch - while (($codelen = strlen($code)) > 0) { - if ($codelen > 44) { - $rest = substr($code, 44); - $code = substr($code, 0, 44); - } else { - $rest = ''; - } - $t = '1'.$code; - do { - $d = bcmod($t, '900'); - $t = bcdiv($t, '900'); - array_unshift($cw, $d); - } while ($t != '0'); - $code = $rest; - } - break; - } - case 913: { // Byte Compaction mode shift - $cw[] = ord($code); - break; - } - } - if ($addmode) { - // add the compaction mode codeword at the beginning - array_unshift($cw, $mode); - } - return $cw; - } - -} // end PDF417 class - -//============================================================+ -// END OF FILE -//============================================================+ diff --git a/lib/combodo/tcpdf/include/barcodes/qrcode.php b/lib/combodo/tcpdf/include/barcodes/qrcode.php deleted file mode 100644 index 2e7f2f576..000000000 --- a/lib/combodo/tcpdf/include/barcodes/qrcode.php +++ /dev/null @@ -1,2842 +0,0 @@ -<?php -//============================================================+ -// File name : qrcode.php -// Version : 1.0.010 -// Begin : 2010-03-22 -// Last Update : 2012-07-25 -// Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com -// License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html) -// ------------------------------------------------------------------- -// Copyright (C) 2010-2012 Nicola Asuni - Tecnick.com LTD -// -// This file is part of TCPDF software library. -// -// TCPDF is free software: you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// TCPDF is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with TCPDF. If not, see <http://www.gnu.org/licenses/>. -// -// See LICENSE.TXT file for more information. -// ------------------------------------------------------------------- -// -// DESCRIPTION : -// -// Class to create QR-code arrays for TCPDF class. -// QR Code symbol is a 2D barcode that can be scanned by -// handy terminals such as a mobile phone with CCD. -// The capacity of QR Code is up to 7000 digits or 4000 -// characters, and has high robustness. -// This class supports QR Code model 2, described in -// JIS (Japanese Industrial Standards) X0510:2004 -// or ISO/IEC 18004. -// Currently the following features are not supported: -// ECI and FNC1 mode, Micro QR Code, QR Code model 1, -// Structured mode. -// -// This class is derived from the following projects: -// --------------------------------------------------------- -// "PHP QR Code encoder" -// License: GNU-LGPLv3 -// Copyright (C) 2010 by Dominik Dzienia <deltalab at poczta dot fm> -// http://phpqrcode.sourceforge.net/ -// https://sourceforge.net/projects/phpqrcode/ -// -// The "PHP QR Code encoder" is based on -// "C libqrencode library" (ver. 3.1.1) -// License: GNU-LGPL 2.1 -// Copyright (C) 2006-2010 by Kentaro Fukuchi -// http://megaui.net/fukuchi/works/qrencode/index.en.html -// -// Reed-Solomon code encoder is written by Phil Karn, KA9Q. -// Copyright (C) 2002-2006 Phil Karn, KA9Q -// -// QR Code is registered trademark of DENSO WAVE INCORPORATED -// http://www.denso-wave.com/qrcode/index-e.html -// --------------------------------------------------------- -//============================================================+ - -/** - * @file - * Class to create QR-code arrays for TCPDF class. - * QR Code symbol is a 2D barcode that can be scanned by handy terminals such as a mobile phone with CCD. - * The capacity of QR Code is up to 7000 digits or 4000 characters, and has high robustness. - * This class supports QR Code model 2, described in JIS (Japanese Industrial Standards) X0510:2004 or ISO/IEC 18004. - * Currently the following features are not supported: ECI and FNC1 mode, Micro QR Code, QR Code model 1, Structured mode. - * - * This class is derived from "PHP QR Code encoder" by Dominik Dzienia (http://phpqrcode.sourceforge.net/) based on "libqrencode C library 3.1.1." by Kentaro Fukuchi (http://megaui.net/fukuchi/works/qrencode/index.en.html), contains Reed-Solomon code written by Phil Karn, KA9Q. QR Code is registered trademark of DENSO WAVE INCORPORATED (http://www.denso-wave.com/qrcode/index-e.html). - * Please read comments on this class source file for full copyright and license information. - * - * @package com.tecnick.tcpdf - * @author Nicola Asuni - * @version 1.0.010 - */ - -// definitions -if (!defined('QRCODEDEFS')) { - - /** - * Indicate that definitions for this class are set - */ - define('QRCODEDEFS', true); - - // ----------------------------------------------------- - - // Encoding modes (characters which can be encoded in QRcode) - - /** - * Encoding mode - */ - define('QR_MODE_NL', -1); - - /** - * Encoding mode numeric (0-9). 3 characters are encoded to 10bit length. In theory, 7089 characters or less can be stored in a QRcode. - */ - define('QR_MODE_NM', 0); - - /** - * Encoding mode alphanumeric (0-9A-Z $%*+-./:) 45characters. 2 characters are encoded to 11bit length. In theory, 4296 characters or less can be stored in a QRcode. - */ - define('QR_MODE_AN', 1); - - /** - * Encoding mode 8bit byte data. In theory, 2953 characters or less can be stored in a QRcode. - */ - define('QR_MODE_8B', 2); - - /** - * Encoding mode KANJI. A KANJI character (multibyte character) is encoded to 13bit length. In theory, 1817 characters or less can be stored in a QRcode. - */ - define('QR_MODE_KJ', 3); - - /** - * Encoding mode STRUCTURED (currently unsupported) - */ - define('QR_MODE_ST', 4); - - // ----------------------------------------------------- - - // Levels of error correction. - // QRcode has a function of an error correcting for miss reading that white is black. - // Error correcting is defined in 4 level as below. - - /** - * Error correction level L : About 7% or less errors can be corrected. - */ - define('QR_ECLEVEL_L', 0); - - /** - * Error correction level M : About 15% or less errors can be corrected. - */ - define('QR_ECLEVEL_M', 1); - - /** - * Error correction level Q : About 25% or less errors can be corrected. - */ - define('QR_ECLEVEL_Q', 2); - - /** - * Error correction level H : About 30% or less errors can be corrected. - */ - define('QR_ECLEVEL_H', 3); - - // ----------------------------------------------------- - - // Version. Size of QRcode is defined as version. - // Version is from 1 to 40. - // Version 1 is 21*21 matrix. And 4 modules increases whenever 1 version increases. - // So version 40 is 177*177 matrix. - - /** - * Maximum QR Code version. - */ - define('QRSPEC_VERSION_MAX', 40); - - /** - * Maximum matrix size for maximum version (version 40 is 177*177 matrix). - */ - define('QRSPEC_WIDTH_MAX', 177); - - // ----------------------------------------------------- - - /** - * Matrix index to get width from $capacity array. - */ - define('QRCAP_WIDTH', 0); - - /** - * Matrix index to get number of words from $capacity array. - */ - define('QRCAP_WORDS', 1); - - /** - * Matrix index to get remainder from $capacity array. - */ - define('QRCAP_REMINDER', 2); - - /** - * Matrix index to get error correction level from $capacity array. - */ - define('QRCAP_EC', 3); - - // ----------------------------------------------------- - - // Structure (currently usupported) - - /** - * Number of header bits for structured mode - */ - define('STRUCTURE_HEADER_BITS', 20); - - /** - * Max number of symbols for structured mode - */ - define('MAX_STRUCTURED_SYMBOLS', 16); - - // ----------------------------------------------------- - - // Masks - - /** - * Down point base value for case 1 mask pattern (concatenation of same color in a line or a column) - */ - define('N1', 3); - - /** - * Down point base value for case 2 mask pattern (module block of same color) - */ - define('N2', 3); - - /** - * Down point base value for case 3 mask pattern (1:1:3:1:1(dark:bright:dark:bright:dark)pattern in a line or a column) - */ - define('N3', 40); - - /** - * Down point base value for case 4 mask pattern (ration of dark modules in whole) - */ - define('N4', 10); - - // ----------------------------------------------------- - - // Optimization settings - - /** - * if true, estimates best mask (spec. default, but extremally slow; set to false to significant performance boost but (propably) worst quality code - */ - define('QR_FIND_BEST_MASK', true); - - /** - * if false, checks all masks available, otherwise value tells count of masks need to be checked, mask id are got randomly - */ - define('QR_FIND_FROM_RANDOM', 2); - - /** - * when QR_FIND_BEST_MASK === false - */ - define('QR_DEFAULT_MASK', 2); - - // ----------------------------------------------------- - -} // end of definitions - -/** - * @class QRcode - * Class to create QR-code arrays for TCPDF class. - * QR Code symbol is a 2D barcode that can be scanned by handy terminals such as a mobile phone with CCD. - * The capacity of QR Code is up to 7000 digits or 4000 characters, and has high robustness. - * This class supports QR Code model 2, described in JIS (Japanese Industrial Standards) X0510:2004 or ISO/IEC 18004. - * Currently the following features are not supported: ECI and FNC1 mode, Micro QR Code, QR Code model 1, Structured mode. - * - * This class is derived from "PHP QR Code encoder" by Dominik Dzienia (http://phpqrcode.sourceforge.net/) based on "libqrencode C library 3.1.1." by Kentaro Fukuchi (http://megaui.net/fukuchi/works/qrencode/index.en.html), contains Reed-Solomon code written by Phil Karn, KA9Q. QR Code is registered trademark of DENSO WAVE INCORPORATED (http://www.denso-wave.com/qrcode/index-e.html). - * Please read comments on this class source file for full copyright and license information. - * - * @package com.tecnick.tcpdf - * @author Nicola Asuni - * @version 1.0.010 - */ -class QRcode { - - /** - * Barcode array to be returned which is readable by TCPDF. - * @protected - */ - protected $barcode_array = array(); - - /** - * QR code version. Size of QRcode is defined as version. Version is from 1 to 40. Version 1 is 21*21 matrix. And 4 modules increases whenever 1 version increases. So version 40 is 177*177 matrix. - * @protected - */ - protected $version = 0; - - /** - * Levels of error correction. See definitions for possible values. - * @protected - */ - protected $level = QR_ECLEVEL_L; - - /** - * Encoding mode. - * @protected - */ - protected $hint = QR_MODE_8B; - - /** - * Boolean flag, if true the input string will be converted to uppercase. - * @protected - */ - protected $casesensitive = true; - - /** - * Structured QR code (not supported yet). - * @protected - */ - protected $structured = 0; - - /** - * Mask data. - * @protected - */ - protected $data; - - // FrameFiller - - /** - * Width. - * @protected - */ - protected $width; - - /** - * Frame. - * @protected - */ - protected $frame; - - /** - * X position of bit. - * @protected - */ - protected $x; - - /** - * Y position of bit. - * @protected - */ - protected $y; - - /** - * Direction. - * @protected - */ - protected $dir; - - /** - * Single bit value. - * @protected - */ - protected $bit; - - // ---- QRrawcode ---- - - /** - * Data code. - * @protected - */ - protected $datacode = array(); - - /** - * Error correction code. - * @protected - */ - protected $ecccode = array(); - - /** - * Blocks. - * @protected - */ - protected $blocks; - - /** - * Reed-Solomon blocks. - * @protected - */ - protected $rsblocks = array(); //of RSblock - - /** - * Counter. - * @protected - */ - protected $count; - - /** - * Data length. - * @protected - */ - protected $dataLength; - - /** - * Error correction length. - * @protected - */ - protected $eccLength; - - /** - * Value b1. - * @protected - */ - protected $b1; - - // ---- QRmask ---- - - /** - * Run length. - * @protected - */ - protected $runLength = array(); - - // ---- QRsplit ---- - - /** - * Input data string. - * @protected - */ - protected $dataStr = ''; - - /** - * Input items. - * @protected - */ - protected $items; - - // Reed-Solomon items - - /** - * Reed-Solomon items. - * @protected - */ - protected $rsitems = array(); - - /** - * Array of frames. - * @protected - */ - protected $frames = array(); - - /** - * Alphabet-numeric convesion table. - * @protected - */ - protected $anTable = array( - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // - 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, // - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, // - -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, // - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // - ); - - /** - * Array Table of the capacity of symbols. - * See Table 1 (pp.13) and Table 12-16 (pp.30-36), JIS X0510:2004. - * @protected - */ - protected $capacity = array( - array( 0, 0, 0, array( 0, 0, 0, 0)), // - array( 21, 26, 0, array( 7, 10, 13, 17)), // 1 - array( 25, 44, 7, array( 10, 16, 22, 28)), // - array( 29, 70, 7, array( 15, 26, 36, 44)), // - array( 33, 100, 7, array( 20, 36, 52, 64)), // - array( 37, 134, 7, array( 26, 48, 72, 88)), // 5 - array( 41, 172, 7, array( 36, 64, 96, 112)), // - array( 45, 196, 0, array( 40, 72, 108, 130)), // - array( 49, 242, 0, array( 48, 88, 132, 156)), // - array( 53, 292, 0, array( 60, 110, 160, 192)), // - array( 57, 346, 0, array( 72, 130, 192, 224)), // 10 - array( 61, 404, 0, array( 80, 150, 224, 264)), // - array( 65, 466, 0, array( 96, 176, 260, 308)), // - array( 69, 532, 0, array( 104, 198, 288, 352)), // - array( 73, 581, 3, array( 120, 216, 320, 384)), // - array( 77, 655, 3, array( 132, 240, 360, 432)), // 15 - array( 81, 733, 3, array( 144, 280, 408, 480)), // - array( 85, 815, 3, array( 168, 308, 448, 532)), // - array( 89, 901, 3, array( 180, 338, 504, 588)), // - array( 93, 991, 3, array( 196, 364, 546, 650)), // - array( 97, 1085, 3, array( 224, 416, 600, 700)), // 20 - array(101, 1156, 4, array( 224, 442, 644, 750)), // - array(105, 1258, 4, array( 252, 476, 690, 816)), // - array(109, 1364, 4, array( 270, 504, 750, 900)), // - array(113, 1474, 4, array( 300, 560, 810, 960)), // - array(117, 1588, 4, array( 312, 588, 870, 1050)), // 25 - array(121, 1706, 4, array( 336, 644, 952, 1110)), // - array(125, 1828, 4, array( 360, 700, 1020, 1200)), // - array(129, 1921, 3, array( 390, 728, 1050, 1260)), // - array(133, 2051, 3, array( 420, 784, 1140, 1350)), // - array(137, 2185, 3, array( 450, 812, 1200, 1440)), // 30 - array(141, 2323, 3, array( 480, 868, 1290, 1530)), // - array(145, 2465, 3, array( 510, 924, 1350, 1620)), // - array(149, 2611, 3, array( 540, 980, 1440, 1710)), // - array(153, 2761, 3, array( 570, 1036, 1530, 1800)), // - array(157, 2876, 0, array( 570, 1064, 1590, 1890)), // 35 - array(161, 3034, 0, array( 600, 1120, 1680, 1980)), // - array(165, 3196, 0, array( 630, 1204, 1770, 2100)), // - array(169, 3362, 0, array( 660, 1260, 1860, 2220)), // - array(173, 3532, 0, array( 720, 1316, 1950, 2310)), // - array(177, 3706, 0, array( 750, 1372, 2040, 2430)) // 40 - ); - - /** - * Array Length indicator. - * @protected - */ - protected $lengthTableBits = array( - array(10, 12, 14), - array( 9, 11, 13), - array( 8, 16, 16), - array( 8, 10, 12) - ); - - /** - * Array Table of the error correction code (Reed-Solomon block). - * See Table 12-16 (pp.30-36), JIS X0510:2004. - * @protected - */ - protected $eccTable = array( - array(array( 0, 0), array( 0, 0), array( 0, 0), array( 0, 0)), // - array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), // 1 - array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), // - array(array( 1, 0), array( 1, 0), array( 2, 0), array( 2, 0)), // - array(array( 1, 0), array( 2, 0), array( 2, 0), array( 4, 0)), // - array(array( 1, 0), array( 2, 0), array( 2, 2), array( 2, 2)), // 5 - array(array( 2, 0), array( 4, 0), array( 4, 0), array( 4, 0)), // - array(array( 2, 0), array( 4, 0), array( 2, 4), array( 4, 1)), // - array(array( 2, 0), array( 2, 2), array( 4, 2), array( 4, 2)), // - array(array( 2, 0), array( 3, 2), array( 4, 4), array( 4, 4)), // - array(array( 2, 2), array( 4, 1), array( 6, 2), array( 6, 2)), // 10 - array(array( 4, 0), array( 1, 4), array( 4, 4), array( 3, 8)), // - array(array( 2, 2), array( 6, 2), array( 4, 6), array( 7, 4)), // - array(array( 4, 0), array( 8, 1), array( 8, 4), array(12, 4)), // - array(array( 3, 1), array( 4, 5), array(11, 5), array(11, 5)), // - array(array( 5, 1), array( 5, 5), array( 5, 7), array(11, 7)), // 15 - array(array( 5, 1), array( 7, 3), array(15, 2), array( 3, 13)), // - array(array( 1, 5), array(10, 1), array( 1, 15), array( 2, 17)), // - array(array( 5, 1), array( 9, 4), array(17, 1), array( 2, 19)), // - array(array( 3, 4), array( 3, 11), array(17, 4), array( 9, 16)), // - array(array( 3, 5), array( 3, 13), array(15, 5), array(15, 10)), // 20 - array(array( 4, 4), array(17, 0), array(17, 6), array(19, 6)), // - array(array( 2, 7), array(17, 0), array( 7, 16), array(34, 0)), // - array(array( 4, 5), array( 4, 14), array(11, 14), array(16, 14)), // - array(array( 6, 4), array( 6, 14), array(11, 16), array(30, 2)), // - array(array( 8, 4), array( 8, 13), array( 7, 22), array(22, 13)), // 25 - array(array(10, 2), array(19, 4), array(28, 6), array(33, 4)), // - array(array( 8, 4), array(22, 3), array( 8, 26), array(12, 28)), // - array(array( 3, 10), array( 3, 23), array( 4, 31), array(11, 31)), // - array(array( 7, 7), array(21, 7), array( 1, 37), array(19, 26)), // - array(array( 5, 10), array(19, 10), array(15, 25), array(23, 25)), // 30 - array(array(13, 3), array( 2, 29), array(42, 1), array(23, 28)), // - array(array(17, 0), array(10, 23), array(10, 35), array(19, 35)), // - array(array(17, 1), array(14, 21), array(29, 19), array(11, 46)), // - array(array(13, 6), array(14, 23), array(44, 7), array(59, 1)), // - array(array(12, 7), array(12, 26), array(39, 14), array(22, 41)), // 35 - array(array( 6, 14), array( 6, 34), array(46, 10), array( 2, 64)), // - array(array(17, 4), array(29, 14), array(49, 10), array(24, 46)), // - array(array( 4, 18), array(13, 32), array(48, 14), array(42, 32)), // - array(array(20, 4), array(40, 7), array(43, 22), array(10, 67)), // - array(array(19, 6), array(18, 31), array(34, 34), array(20, 61)) // 40 - ); - - /** - * Array Positions of alignment patterns. - * This array includes only the second and the third position of the alignment patterns. Rest of them can be calculated from the distance between them. - * See Table 1 in Appendix E (pp.71) of JIS X0510:2004. - * @protected - */ - protected $alignmentPattern = array( - array( 0, 0), - array( 0, 0), array(18, 0), array(22, 0), array(26, 0), array(30, 0), // 1- 5 - array(34, 0), array(22, 38), array(24, 42), array(26, 46), array(28, 50), // 6-10 - array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48), // 11-15 - array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(34, 62), // 16-20 - array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58), // 21-25 - array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52), // 26-30 - array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54), // 31-35 - array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58) // 35-40 - ); - - /** - * Array Version information pattern (BCH coded). - * See Table 1 in Appendix D (pp.68) of JIS X0510:2004. - * size: [QRSPEC_VERSION_MAX - 6] - * @protected - */ - protected $versionPattern = array( - 0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d, // - 0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9, // - 0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75, // - 0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64, // - 0x27541, 0x28c69 - ); - - /** - * Array Format information - * @protected - */ - protected $formatInfo = array( - array(0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976), // - array(0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0), // - array(0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed), // - array(0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b) // - ); - - - // ------------------------------------------------- - // ------------------------------------------------- - - - /** - * This is the class constructor. - * Creates a QRcode object - * @param string $code code to represent using QRcode - * @param string $eclevel error level: <ul><li>L : About 7% or less errors can be corrected.</li><li>M : About 15% or less errors can be corrected.</li><li>Q : About 25% or less errors can be corrected.</li><li>H : About 30% or less errors can be corrected.</li></ul> - * @public - * @since 1.0.000 - */ - public function __construct($code, $eclevel = 'L') { - $barcode_array = array(); - if ((is_null($code)) OR ($code == '\0') OR ($code == '')) { - return false; - } - // set error correction level - $this->level = array_search($eclevel, array('L', 'M', 'Q', 'H')); - if ($this->level === false) { - $this->level = QR_ECLEVEL_L; - } - if (($this->hint != QR_MODE_8B) AND ($this->hint != QR_MODE_KJ)) { - return false; - } - if (($this->version < 0) OR ($this->version > QRSPEC_VERSION_MAX)) { - return false; - } - $this->items = array(); - $this->encodeString($code); - if (is_null($this->data)) { - return false; - } - $qrTab = $this->binarize($this->data); - $size = count($qrTab); - $barcode_array['num_rows'] = $size; - $barcode_array['num_cols'] = $size; - $barcode_array['bcode'] = array(); - foreach ($qrTab as $line) { - $arrAdd = array(); - foreach (str_split($line) as $char) { - $arrAdd[] = ($char=='1')?1:0; - } - $barcode_array['bcode'][] = $arrAdd; - } - $this->barcode_array = $barcode_array; - } - - /** - * Returns a barcode array which is readable by TCPDF - * @return array barcode array readable by TCPDF; - * @public - */ - public function getBarcodeArray() { - return $this->barcode_array; - } - - /** - * Convert the frame in binary form - * @param array $frame array to binarize - * @return array frame in binary form - */ - protected function binarize($frame) { - $len = count($frame); - // the frame is square (width = height) - foreach ($frame as &$frameLine) { - for ($i=0; $i<$len; $i++) { - $frameLine[$i] = (ord($frameLine[$i])&1)?'1':'0'; - } - } - return $frame; - } - - /** - * Encode the input string to QR code - * @param string $string input string to encode - */ - protected function encodeString($string) { - $this->dataStr = $string; - if (!$this->casesensitive) { - $this->toUpper(); - } - $ret = $this->splitString(); - if ($ret < 0) { - return NULL; - } - $this->encodeMask(-1); - } - - /** - * Encode mask - * @param int $mask masking mode - */ - protected function encodeMask($mask) { - $spec = array(0, 0, 0, 0, 0); - $this->datacode = $this->getByteStream($this->items); - - if (is_null($this->datacode)) { - return NULL; - } - $spec = $this->getEccSpec($this->version, $this->level, $spec); - $this->b1 = $this->rsBlockNum1($spec); - $this->dataLength = $this->rsDataLength($spec); - $this->eccLength = $this->rsEccLength($spec); - $this->ecccode = array_fill(0, $this->eccLength, 0); - $this->blocks = $this->rsBlockNum($spec); - $ret = $this->init($spec); - if ($ret < 0) { - return NULL; - } - $this->count = 0; - $this->width = $this->getWidth($this->version); - $this->frame = $this->newFrame($this->version); - $this->x = $this->width - 1; - $this->y = $this->width - 1; - $this->dir = -1; - $this->bit = -1; - // inteleaved data and ecc codes - for ($i=0; $i < ($this->dataLength + $this->eccLength); $i++) { - $code = $this->getCode(); - $bit = 0x80; - for ($j=0; $j<8; $j++) { - $addr = $this->getNextPosition(); - $this->setFrameAt($addr, 0x02 | (($bit & $code) != 0)); - $bit = $bit >> 1; - } - } - // remainder bits - $j = $this->getRemainder($this->version); - for ($i=0; $i<$j; $i++) { - $addr = $this->getNextPosition(); - $this->setFrameAt($addr, 0x02); - } - // masking - $this->runLength = array_fill(0, QRSPEC_WIDTH_MAX + 1, 0); - if ($mask < 0) { - if (QR_FIND_BEST_MASK) { - $masked = $this->mask($this->width, $this->frame, $this->level); - } else { - $masked = $this->makeMask($this->width, $this->frame, (intval(QR_DEFAULT_MASK) % 8), $this->level); - } - } else { - $masked = $this->makeMask($this->width, $this->frame, $mask, $this->level); - } - if ($masked == NULL) { - return NULL; - } - $this->data = $masked; - } - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - // FrameFiller - - /** - * Set frame value at specified position - * @param array $at x,y position - * @param int $val value of the character to set - */ - protected function setFrameAt($at, $val) { - $this->frame[$at['y']][$at['x']] = chr($val); - } - - /** - * Get frame value at specified position - * @param array $at x,y position - * @return value at specified position - */ - protected function getFrameAt($at) { - return ord($this->frame[$at['y']][$at['x']]); - } - - /** - * Return the next frame position - * @return array of x,y coordinates - */ - protected function getNextPosition() { - do { - if ($this->bit == -1) { - $this->bit = 0; - return array('x'=>$this->x, 'y'=>$this->y); - } - $x = $this->x; - $y = $this->y; - $w = $this->width; - if ($this->bit == 0) { - $x--; - $this->bit++; - } else { - $x++; - $y += $this->dir; - $this->bit--; - } - if ($this->dir < 0) { - if ($y < 0) { - $y = 0; - $x -= 2; - $this->dir = 1; - if ($x == 6) { - $x--; - $y = 9; - } - } - } else { - if ($y == $w) { - $y = $w - 1; - $x -= 2; - $this->dir = -1; - if ($x == 6) { - $x--; - $y -= 8; - } - } - } - if (($x < 0) OR ($y < 0)) { - return NULL; - } - $this->x = $x; - $this->y = $y; - } while(ord($this->frame[$y][$x]) & 0x80); - return array('x'=>$x, 'y'=>$y); - } - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - // QRrawcode - - /** - * Initialize code. - * @param array $spec array of ECC specification - * @return int 0 in case of success, -1 in case of error - */ - protected function init($spec) { - $dl = $this->rsDataCodes1($spec); - $el = $this->rsEccCodes1($spec); - $rs = $this->init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el); - $blockNo = 0; - $dataPos = 0; - $eccPos = 0; - $endfor = $this->rsBlockNum1($spec); - for ($i=0; $i < $endfor; ++$i) { - $ecc = array_slice($this->ecccode, $eccPos); - $this->rsblocks[$blockNo] = array(); - $this->rsblocks[$blockNo]['dataLength'] = $dl; - $this->rsblocks[$blockNo]['data'] = array_slice($this->datacode, $dataPos); - $this->rsblocks[$blockNo]['eccLength'] = $el; - $ecc = $this->encode_rs_char($rs, $this->rsblocks[$blockNo]['data'], $ecc); - $this->rsblocks[$blockNo]['ecc'] = $ecc; - $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc); - $dataPos += $dl; - $eccPos += $el; - $blockNo++; - } - if ($this->rsBlockNum2($spec) == 0) { - return 0; - } - $dl = $this->rsDataCodes2($spec); - $el = $this->rsEccCodes2($spec); - $rs = $this->init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el); - if ($rs == NULL) { - return -1; - } - $endfor = $this->rsBlockNum2($spec); - for ($i=0; $i < $endfor; ++$i) { - $ecc = array_slice($this->ecccode, $eccPos); - $this->rsblocks[$blockNo] = array(); - $this->rsblocks[$blockNo]['dataLength'] = $dl; - $this->rsblocks[$blockNo]['data'] = array_slice($this->datacode, $dataPos); - $this->rsblocks[$blockNo]['eccLength'] = $el; - $ecc = $this->encode_rs_char($rs, $this->rsblocks[$blockNo]['data'], $ecc); - $this->rsblocks[$blockNo]['ecc'] = $ecc; - $this->ecccode = array_merge(array_slice($this->ecccode, 0, $eccPos), $ecc); - $dataPos += $dl; - $eccPos += $el; - $blockNo++; - } - return 0; - } - - /** - * Return Reed-Solomon block code. - * @return array rsblocks - */ - protected function getCode() { - if ($this->count < $this->dataLength) { - $row = $this->count % $this->blocks; - $col = $this->count / $this->blocks; - if ($col >= $this->rsblocks[0]['dataLength']) { - $row += $this->b1; - } - $ret = $this->rsblocks[$row]['data'][$col]; - } elseif ($this->count < $this->dataLength + $this->eccLength) { - $row = ($this->count - $this->dataLength) % $this->blocks; - $col = ($this->count - $this->dataLength) / $this->blocks; - $ret = $this->rsblocks[$row]['ecc'][$col]; - } else { - return 0; - } - $this->count++; - return $ret; - } - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - // QRmask - - /** - * Write Format Information on frame and returns the number of black bits - * @param int $width frame width - * @param array $frame frame - * @param array $mask masking mode - * @param int $level error correction level - * @return int blacks - */ - protected function writeFormatInformation($width, &$frame, $mask, $level) { - $blacks = 0; - $format = $this->getFormatInfo($mask, $level); - for ($i=0; $i<8; ++$i) { - if ($format & 1) { - $blacks += 2; - $v = 0x85; - } else { - $v = 0x84; - } - $frame[8][$width - 1 - $i] = chr($v); - if ($i < 6) { - $frame[$i][8] = chr($v); - } else { - $frame[$i + 1][8] = chr($v); - } - $format = $format >> 1; - } - for ($i=0; $i<7; ++$i) { - if ($format & 1) { - $blacks += 2; - $v = 0x85; - } else { - $v = 0x84; - } - $frame[$width - 7 + $i][8] = chr($v); - if ($i == 0) { - $frame[8][7] = chr($v); - } else { - $frame[8][6 - $i] = chr($v); - } - $format = $format >> 1; - } - return $blacks; - } - - /** - * mask0 - * @param int $x X position - * @param int $y Y position - * @return int mask - */ - protected function mask0($x, $y) { - return ($x + $y) & 1; - } - - /** - * mask1 - * @param int $x X position - * @param int $y Y position - * @return int mask - */ - protected function mask1($x, $y) { - return ($y & 1); - } - - /** - * mask2 - * @param int $x X position - * @param int $y Y position - * @return int mask - */ - protected function mask2($x, $y) { - return ($x % 3); - } - - /** - * mask3 - * @param int $x X position - * @param int $y Y position - * @return int mask - */ - protected function mask3($x, $y) { - return ($x + $y) % 3; - } - - /** - * mask4 - * @param int $x X position - * @param int $y Y position - * @return int mask - */ - protected function mask4($x, $y) { - return (((int)($y / 2)) + ((int)($x / 3))) & 1; - } - - /** - * mask5 - * @param int $x X position - * @param int $y Y position - * @return int mask - */ - protected function mask5($x, $y) { - return (($x * $y) & 1) + ($x * $y) % 3; - } - - /** - * mask6 - * @param int $x X position - * @param int $y Y position - * @return int mask - */ - protected function mask6($x, $y) { - return ((($x * $y) & 1) + ($x * $y) % 3) & 1; - } - - /** - * mask7 - * @param int $x X position - * @param int $y Y position - * @return int mask - */ - protected function mask7($x, $y) { - return ((($x * $y) % 3) + (($x + $y) & 1)) & 1; - } - - /** - * Return bitmask - * @param int $maskNo mask number - * @param int $width width - * @param array $frame frame - * @return array bitmask - */ - protected function generateMaskNo($maskNo, $width, $frame) { - $bitMask = array_fill(0, $width, array_fill(0, $width, 0)); - for ($y=0; $y<$width; ++$y) { - for ($x=0; $x<$width; ++$x) { - if (ord($frame[$y][$x]) & 0x80) { - $bitMask[$y][$x] = 0; - } else { - $maskFunc = call_user_func(array($this, 'mask'.$maskNo), $x, $y); - $bitMask[$y][$x] = ($maskFunc == 0)?1:0; - } - } - } - return $bitMask; - } - - /** - * makeMaskNo - * @param int $maskNo - * @param int $width - * @param int $s - * @param int $d - * @param boolean $maskGenOnly - * @return int b - */ - protected function makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly=false) { - $b = 0; - $bitMask = array(); - $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d); - if ($maskGenOnly) { - return; - } - $d = $s; - for ($y=0; $y<$width; ++$y) { - for ($x=0; $x<$width; ++$x) { - if ($bitMask[$y][$x] == 1) { - $d[$y][$x] = chr(ord($s[$y][$x]) ^ ((int)($bitMask[$y][$x]))); - } - $b += (int)(ord($d[$y][$x]) & 1); - } - } - return $b; - } - - /** - * makeMask - * @param int $width - * @param array $frame - * @param int $maskNo - * @param int $level - * @return array mask - */ - protected function makeMask($width, $frame, $maskNo, $level) { - $masked = array_fill(0, $width, str_repeat("\0", $width)); - $this->makeMaskNo($maskNo, $width, $frame, $masked); - $this->writeFormatInformation($width, $masked, $maskNo, $level); - return $masked; - } - - /** - * calcN1N3 - * @param int $length - * @return int demerit - */ - protected function calcN1N3($length) { - $demerit = 0; - for ($i=0; $i<$length; ++$i) { - if ($this->runLength[$i] >= 5) { - $demerit += (N1 + ($this->runLength[$i] - 5)); - } - if ($i & 1) { - if (($i >= 3) AND ($i < ($length-2)) AND ($this->runLength[$i] % 3 == 0)) { - $fact = (int)($this->runLength[$i] / 3); - if (($this->runLength[$i-2] == $fact) - AND ($this->runLength[$i-1] == $fact) - AND ($this->runLength[$i+1] == $fact) - AND ($this->runLength[$i+2] == $fact)) { - if (($this->runLength[$i-3] < 0) OR ($this->runLength[$i-3] >= (4 * $fact))) { - $demerit += N3; - } elseif ((($i+3) >= $length) OR ($this->runLength[$i+3] >= (4 * $fact))) { - $demerit += N3; - } - } - } - } - } - return $demerit; - } - - /** - * evaluateSymbol - * @param int $width - * @param array $frame - * @return int demerit - */ - protected function evaluateSymbol($width, $frame) { - $head = 0; - $demerit = 0; - for ($y=0; $y<$width; ++$y) { - $head = 0; - $this->runLength[0] = 1; - $frameY = $frame[$y]; - if ($y > 0) { - $frameYM = $frame[$y-1]; - } - for ($x=0; $x<$width; ++$x) { - if (($x > 0) AND ($y > 0)) { - $b22 = ord($frameY[$x]) & ord($frameY[$x-1]) & ord($frameYM[$x]) & ord($frameYM[$x-1]); - $w22 = ord($frameY[$x]) | ord($frameY[$x-1]) | ord($frameYM[$x]) | ord($frameYM[$x-1]); - if (($b22 | ($w22 ^ 1)) & 1) { - $demerit += N2; - } - } - if (($x == 0) AND (ord($frameY[$x]) & 1)) { - $this->runLength[0] = -1; - $head = 1; - $this->runLength[$head] = 1; - } elseif ($x > 0) { - if ((ord($frameY[$x]) ^ ord($frameY[$x-1])) & 1) { - $head++; - $this->runLength[$head] = 1; - } else { - $this->runLength[$head]++; - } - } - } - $demerit += $this->calcN1N3($head+1); - } - for ($x=0; $x<$width; ++$x) { - $head = 0; - $this->runLength[0] = 1; - for ($y=0; $y<$width; ++$y) { - if (($y == 0) AND (ord($frame[$y][$x]) & 1)) { - $this->runLength[0] = -1; - $head = 1; - $this->runLength[$head] = 1; - } elseif ($y > 0) { - if ((ord($frame[$y][$x]) ^ ord($frame[$y-1][$x])) & 1) { - $head++; - $this->runLength[$head] = 1; - } else { - $this->runLength[$head]++; - } - } - } - $demerit += $this->calcN1N3($head+1); - } - return $demerit; - } - - /** - * mask - * @param int $width - * @param array $frame - * @param int $level - * @return array best mask - */ - protected function mask($width, $frame, $level) { - $minDemerit = PHP_INT_MAX; - $bestMaskNum = 0; - $bestMask = array(); - $checked_masks = array(0, 1, 2, 3, 4, 5, 6, 7); - if (QR_FIND_FROM_RANDOM !== false) { - $howManuOut = 8 - (QR_FIND_FROM_RANDOM % 9); - for ($i = 0; $i < $howManuOut; ++$i) { - $remPos = rand (0, count($checked_masks)-1); - unset($checked_masks[$remPos]); - $checked_masks = array_values($checked_masks); - } - } - $bestMask = $frame; - foreach ($checked_masks as $i) { - $mask = array_fill(0, $width, str_repeat("\0", $width)); - $demerit = 0; - $blacks = 0; - $blacks = $this->makeMaskNo($i, $width, $frame, $mask); - $blacks += $this->writeFormatInformation($width, $mask, $i, $level); - $blacks = (int)(100 * $blacks / ($width * $width)); - $demerit = (int)((int)(abs($blacks - 50) / 5) * N4); - $demerit += $this->evaluateSymbol($width, $mask); - if ($demerit < $minDemerit) { - $minDemerit = $demerit; - $bestMask = $mask; - $bestMaskNum = $i; - } - } - return $bestMask; - } - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - // QRsplit - - /** - * Return true if the character at specified position is a number - * @param string $str string - * @param int $pos characted position - * @return boolean true of false - */ - protected function isdigitat($str, $pos) { - if ($pos >= strlen($str)) { - return false; - } - return ((ord($str[$pos]) >= ord('0'))&&(ord($str[$pos]) <= ord('9'))); - } - - /** - * Return true if the character at specified position is an alphanumeric character - * @param string $str string - * @param int $pos characted position - * @return boolean true of false - */ - protected function isalnumat($str, $pos) { - if ($pos >= strlen($str)) { - return false; - } - return ($this->lookAnTable(ord($str[$pos])) >= 0); - } - - /** - * identifyMode - * @param int $pos - * @return int mode - */ - protected function identifyMode($pos) { - if ($pos >= strlen($this->dataStr)) { - return QR_MODE_NL; - } - $c = $this->dataStr[$pos]; - if ($this->isdigitat($this->dataStr, $pos)) { - return QR_MODE_NM; - } elseif ($this->isalnumat($this->dataStr, $pos)) { - return QR_MODE_AN; - } elseif ($this->hint == QR_MODE_KJ) { - if ($pos+1 < strlen($this->dataStr)) { - $d = $this->dataStr[$pos+1]; - $word = (ord($c) << 8) | ord($d); - if (($word >= 0x8140 && $word <= 0x9ffc) OR ($word >= 0xe040 && $word <= 0xebbf)) { - return QR_MODE_KJ; - } - } - } - return QR_MODE_8B; - } - - /** - * eatNum - * @return int run - */ - protected function eatNum() { - $ln = $this->lengthIndicator(QR_MODE_NM, $this->version); - $p = 0; - while($this->isdigitat($this->dataStr, $p)) { - $p++; - } - $run = $p; - $mode = $this->identifyMode($p); - if ($mode == QR_MODE_8B) { - $dif = $this->estimateBitsModeNum($run) + 4 + $ln - + $this->estimateBitsMode8(1) // + 4 + l8 - - $this->estimateBitsMode8($run + 1); // - 4 - l8 - if ($dif > 0) { - return $this->eat8(); - } - } - if ($mode == QR_MODE_AN) { - $dif = $this->estimateBitsModeNum($run) + 4 + $ln - + $this->estimateBitsModeAn(1) // + 4 + la - - $this->estimateBitsModeAn($run + 1);// - 4 - la - if ($dif > 0) { - return $this->eatAn(); - } - } - $this->items = $this->appendNewInputItem($this->items, QR_MODE_NM, $run, str_split($this->dataStr)); - return $run; - } - - /** - * eatAn - * @return int run - */ - protected function eatAn() { - $la = $this->lengthIndicator(QR_MODE_AN, $this->version); - $ln = $this->lengthIndicator(QR_MODE_NM, $this->version); - $p =1 ; - while($this->isalnumat($this->dataStr, $p)) { - if ($this->isdigitat($this->dataStr, $p)) { - $q = $p; - while($this->isdigitat($this->dataStr, $q)) { - $q++; - } - $dif = $this->estimateBitsModeAn($p) // + 4 + la - + $this->estimateBitsModeNum($q - $p) + 4 + $ln - - $this->estimateBitsModeAn($q); // - 4 - la - if ($dif < 0) { - break; - } else { - $p = $q; - } - } else { - $p++; - } - } - $run = $p; - if (!$this->isalnumat($this->dataStr, $p)) { - $dif = $this->estimateBitsModeAn($run) + 4 + $la - + $this->estimateBitsMode8(1) // + 4 + l8 - - $this->estimateBitsMode8($run + 1); // - 4 - l8 - if ($dif > 0) { - return $this->eat8(); - } - } - $this->items = $this->appendNewInputItem($this->items, QR_MODE_AN, $run, str_split($this->dataStr)); - return $run; - } - - /** - * eatKanji - * @return int run - */ - protected function eatKanji() { - $p = 0; - while($this->identifyMode($p) == QR_MODE_KJ) { - $p += 2; - } - $this->items = $this->appendNewInputItem($this->items, QR_MODE_KJ, $p, str_split($this->dataStr)); - $run = $p; - return $run; - } - - /** - * eat8 - * @return int run - */ - protected function eat8() { - $la = $this->lengthIndicator(QR_MODE_AN, $this->version); - $ln = $this->lengthIndicator(QR_MODE_NM, $this->version); - $p = 1; - $dataStrLen = strlen($this->dataStr); - while($p < $dataStrLen) { - $mode = $this->identifyMode($p); - if ($mode == QR_MODE_KJ) { - break; - } - if ($mode == QR_MODE_NM) { - $q = $p; - while($this->isdigitat($this->dataStr, $q)) { - $q++; - } - $dif = $this->estimateBitsMode8($p) // + 4 + l8 - + $this->estimateBitsModeNum($q - $p) + 4 + $ln - - $this->estimateBitsMode8($q); // - 4 - l8 - if ($dif < 0) { - break; - } else { - $p = $q; - } - } elseif ($mode == QR_MODE_AN) { - $q = $p; - while($this->isalnumat($this->dataStr, $q)) { - $q++; - } - $dif = $this->estimateBitsMode8($p) // + 4 + l8 - + $this->estimateBitsModeAn($q - $p) + 4 + $la - - $this->estimateBitsMode8($q); // - 4 - l8 - if ($dif < 0) { - break; - } else { - $p = $q; - } - } else { - $p++; - } - } - $run = $p; - $this->items = $this->appendNewInputItem($this->items, QR_MODE_8B, $run, str_split($this->dataStr)); - return $run; - } - - /** - * splitString - * @return int - */ - protected function splitString() { - while (strlen($this->dataStr) > 0) { - $mode = $this->identifyMode(0); - switch ($mode) { - case QR_MODE_NM: { - $length = $this->eatNum(); - break; - } - case QR_MODE_AN: { - $length = $this->eatAn(); - break; - } - case QR_MODE_KJ: { - if ($this->hint == QR_MODE_KJ) { - $length = $this->eatKanji(); - } else { - $length = $this->eat8(); - } - break; - } - default: { - $length = $this->eat8(); - break; - } - } - if ($length == 0) { - return 0; - } - if ($length < 0) { - return -1; - } - $this->dataStr = substr($this->dataStr, $length); - } - return 0; - } - - /** - * toUpper - */ - protected function toUpper() { - $stringLen = strlen($this->dataStr); - $p = 0; - while ($p < $stringLen) { - $mode = $this->identifyMode(substr($this->dataStr, $p), $this->hint); - if ($mode == QR_MODE_KJ) { - $p += 2; - } else { - if ((ord($this->dataStr[$p]) >= ord('a')) AND (ord($this->dataStr[$p]) <= ord('z'))) { - $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32); - } - $p++; - } - } - return $this->dataStr; - } - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - // QRinputItem - - /** - * newInputItem - * @param int $mode - * @param int $size - * @param array $data - * @param array $bstream - * @return array input item - */ - protected function newInputItem($mode, $size, $data, $bstream=null) { - $setData = array_slice($data, 0, $size); - if (count($setData) < $size) { - $setData = array_merge($setData, array_fill(0, ($size - count($setData)), 0)); - } - if (!$this->check($mode, $size, $setData)) { - return NULL; - } - $inputitem = array(); - $inputitem['mode'] = $mode; - $inputitem['size'] = $size; - $inputitem['data'] = $setData; - $inputitem['bstream'] = $bstream; - return $inputitem; - } - - /** - * encodeModeNum - * @param array $inputitem - * @param int $version - * @return array input item - */ - protected function encodeModeNum($inputitem, $version) { - $words = (int)($inputitem['size'] / 3); - $inputitem['bstream'] = array(); - $val = 0x1; - $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, $val); - $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], $this->lengthIndicator(QR_MODE_NM, $version), $inputitem['size']); - for ($i=0; $i < $words; ++$i) { - $val = (ord($inputitem['data'][$i*3 ]) - ord('0')) * 100; - $val += (ord($inputitem['data'][$i*3+1]) - ord('0')) * 10; - $val += (ord($inputitem['data'][$i*3+2]) - ord('0')); - $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 10, $val); - } - if ($inputitem['size'] - $words * 3 == 1) { - $val = ord($inputitem['data'][$words*3]) - ord('0'); - $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, $val); - } elseif (($inputitem['size'] - ($words * 3)) == 2) { - $val = (ord($inputitem['data'][$words*3 ]) - ord('0')) * 10; - $val += (ord($inputitem['data'][$words*3+1]) - ord('0')); - $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 7, $val); - } - return $inputitem; - } - - /** - * encodeModeAn - * @param array $inputitem - * @param int $version - * @return array input item - */ - protected function encodeModeAn($inputitem, $version) { - $words = (int)($inputitem['size'] / 2); - $inputitem['bstream'] = array(); - $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, 0x02); - $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], $this->lengthIndicator(QR_MODE_AN, $version), $inputitem['size']); - for ($i=0; $i < $words; ++$i) { - $val = (int)($this->lookAnTable(ord($inputitem['data'][$i*2])) * 45); - $val += (int)($this->lookAnTable(ord($inputitem['data'][($i*2)+1]))); - $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 11, $val); - } - if ($inputitem['size'] & 1) { - $val = $this->lookAnTable(ord($inputitem['data'][($words * 2)])); - $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 6, $val); - } - return $inputitem; - } - - /** - * encodeMode8 - * @param array $inputitem - * @param int $version - * @return array input item - */ - protected function encodeMode8($inputitem, $version) { - $inputitem['bstream'] = array(); - $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, 0x4); - $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], $this->lengthIndicator(QR_MODE_8B, $version), $inputitem['size']); - for ($i=0; $i < $inputitem['size']; ++$i) { - $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 8, ord($inputitem['data'][$i])); - } - return $inputitem; - } - - /** - * encodeModeKanji - * @param array $inputitem - * @param int $version - * @return array input item - */ - protected function encodeModeKanji($inputitem, $version) { - $inputitem['bstream'] = array(); - $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, 0x8); - $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], $this->lengthIndicator(QR_MODE_KJ, $version), (int)($inputitem['size'] / 2)); - for ($i=0; $i<$inputitem['size']; $i+=2) { - $val = (ord($inputitem['data'][$i]) << 8) | ord($inputitem['data'][$i+1]); - if ($val <= 0x9ffc) { - $val -= 0x8140; - } else { - $val -= 0xc140; - } - $h = ($val >> 8) * 0xc0; - $val = ($val & 0xff) + $h; - $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 13, $val); - } - return $inputitem; - } - - /** - * encodeModeStructure - * @param array $inputitem - * @return array input item - */ - protected function encodeModeStructure($inputitem) { - $inputitem['bstream'] = array(); - $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, 0x03); - $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, ord($inputitem['data'][1]) - 1); - $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, ord($inputitem['data'][0]) - 1); - $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 8, ord($inputitem['data'][2])); - return $inputitem; - } - - /** - * encodeBitStream - * @param array $inputitem - * @param int $version - * @return array input item - */ - protected function encodeBitStream($inputitem, $version) { - $inputitem['bstream'] = array(); - $words = $this->maximumWords($inputitem['mode'], $version); - if ($inputitem['size'] > $words) { - $st1 = $this->newInputItem($inputitem['mode'], $words, $inputitem['data']); - $st2 = $this->newInputItem($inputitem['mode'], $inputitem['size'] - $words, array_slice($inputitem['data'], $words)); - $st1 = $this->encodeBitStream($st1, $version); - $st2 = $this->encodeBitStream($st2, $version); - $inputitem['bstream'] = array(); - $inputitem['bstream'] = $this->appendBitstream($inputitem['bstream'], $st1['bstream']); - $inputitem['bstream'] = $this->appendBitstream($inputitem['bstream'], $st2['bstream']); - } else { - switch($inputitem['mode']) { - case QR_MODE_NM: { - $inputitem = $this->encodeModeNum($inputitem, $version); - break; - } - case QR_MODE_AN: { - $inputitem = $this->encodeModeAn($inputitem, $version); - break; - } - case QR_MODE_8B: { - $inputitem = $this->encodeMode8($inputitem, $version); - break; - } - case QR_MODE_KJ: { - $inputitem = $this->encodeModeKanji($inputitem, $version); - break; - } - case QR_MODE_ST: { - $inputitem = $this->encodeModeStructure($inputitem); - break; - } - default: { - break; - } - } - } - return $inputitem; - } - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - // QRinput - - /** - * Append data to an input object. - * The data is copied and appended to the input object. - * @param array $items input items - * @param int $mode encoding mode. - * @param int $size size of data (byte). - * @param array $data array of input data. - * @return array items - * - */ - protected function appendNewInputItem($items, $mode, $size, $data) { - $newitem = $this->newInputItem($mode, $size, $data); - if (!empty($newitem)) { - $items[] = $newitem; - } - return $items; - } - - /** - * insertStructuredAppendHeader - * @param array $items - * @param int $size - * @param int $index - * @param int $parity - * @return array items - */ - protected function insertStructuredAppendHeader($items, $size, $index, $parity) { - if ($size > MAX_STRUCTURED_SYMBOLS) { - return -1; - } - if (($index <= 0) OR ($index > MAX_STRUCTURED_SYMBOLS)) { - return -1; - } - $buf = array($size, $index, $parity); - $entry = $this->newInputItem(QR_MODE_ST, 3, buf); - array_unshift($items, $entry); - return $items; - } - - /** - * calcParity - * @param array $items - * @return int parity - */ - protected function calcParity($items) { - $parity = 0; - foreach ($items as $item) { - if ($item['mode'] != QR_MODE_ST) { - for ($i=$item['size']-1; $i>=0; --$i) { - $parity ^= $item['data'][$i]; - } - } - } - return $parity; - } - - /** - * checkModeNum - * @param int $size - * @param array $data - * @return boolean true or false - */ - protected function checkModeNum($size, $data) { - for ($i=0; $i<$size; ++$i) { - if ((ord($data[$i]) < ord('0')) OR (ord($data[$i]) > ord('9'))){ - return false; - } - } - return true; - } - - /** - * Look up the alphabet-numeric conversion table (see JIS X0510:2004, pp.19). - * @param int $c character value - * @return int value - */ - protected function lookAnTable($c) { - return (($c > 127)?-1:$this->anTable[$c]); - } - - /** - * checkModeAn - * @param int $size - * @param array $data - * @return boolean true or false - */ - protected function checkModeAn($size, $data) { - for ($i=0; $i<$size; ++$i) { - if ($this->lookAnTable(ord($data[$i])) == -1) { - return false; - } - } - return true; - } - - /** - * estimateBitsModeNum - * @param int $size - * @return int number of bits - */ - protected function estimateBitsModeNum($size) { - $w = (int)($size / 3); - $bits = ($w * 10); - switch($size - ($w * 3)) { - case 1: { - $bits += 4; - break; - } - case 2: { - $bits += 7; - break; - } - } - return $bits; - } - - /** - * estimateBitsModeAn - * @param int $size - * @return int number of bits - */ - protected function estimateBitsModeAn($size) { - $bits = (int)($size * 5.5); // (size / 2 ) * 11 - if ($size & 1) { - $bits += 6; - } - return $bits; - } - - /** - * estimateBitsMode8 - * @param int $size - * @return int number of bits - */ - protected function estimateBitsMode8($size) { - return (int)($size * 8); - } - - /** - * estimateBitsModeKanji - * @param int $size - * @return int number of bits - */ - protected function estimateBitsModeKanji($size) { - return (int)($size * 6.5); // (size / 2 ) * 13 - } - - /** - * checkModeKanji - * @param int $size - * @param array $data - * @return boolean true or false - */ - protected function checkModeKanji($size, $data) { - if ($size & 1) { - return false; - } - for ($i=0; $i<$size; $i+=2) { - $val = (ord($data[$i]) << 8) | ord($data[$i+1]); - if (($val < 0x8140) OR (($val > 0x9ffc) AND ($val < 0xe040)) OR ($val > 0xebbf)) { - return false; - } - } - return true; - } - - /** - * Validate the input data. - * @param int $mode encoding mode. - * @param int $size size of data (byte). - * @param array $data data to validate - * @return boolean true in case of valid data, false otherwise - */ - protected function check($mode, $size, $data) { - if ($size <= 0) { - return false; - } - switch($mode) { - case QR_MODE_NM: { - return $this->checkModeNum($size, $data); - } - case QR_MODE_AN: { - return $this->checkModeAn($size, $data); - } - case QR_MODE_KJ: { - return $this->checkModeKanji($size, $data); - } - case QR_MODE_8B: { - return true; - } - case QR_MODE_ST: { - return true; - } - default: { - break; - } - } - return false; - } - - /** - * estimateBitStreamSize - * @param array $items - * @param int $version - * @return int bits - */ - protected function estimateBitStreamSize($items, $version) { - $bits = 0; - if ($version == 0) { - $version = 1; - } - foreach ($items as $item) { - switch($item['mode']) { - case QR_MODE_NM: { - $bits = $this->estimateBitsModeNum($item['size']); - break; - } - case QR_MODE_AN: { - $bits = $this->estimateBitsModeAn($item['size']); - break; - } - case QR_MODE_8B: { - $bits = $this->estimateBitsMode8($item['size']); - break; - } - case QR_MODE_KJ: { - $bits = $this->estimateBitsModeKanji($item['size']); - break; - } - case QR_MODE_ST: { - return STRUCTURE_HEADER_BITS; - } - default: { - return 0; - } - } - $l = $this->lengthIndicator($item['mode'], $version); - $m = 1 << $l; - $num = (int)(($item['size'] + $m - 1) / $m); - $bits += $num * (4 + $l); - } - return $bits; - } - - /** - * estimateVersion - * @param array $items - * @return int version - */ - protected function estimateVersion($items) { - $version = 0; - $prev = 0; - do { - $prev = $version; - $bits = $this->estimateBitStreamSize($items, $prev); - $version = $this->getMinimumVersion((int)(($bits + 7) / 8), $this->level); - if ($version < 0) { - return -1; - } - } while ($version > $prev); - return $version; - } - - /** - * lengthOfCode - * @param int $mode - * @param int $version - * @param int $bits - * @return int size - */ - protected function lengthOfCode($mode, $version, $bits) { - $payload = $bits - 4 - $this->lengthIndicator($mode, $version); - switch($mode) { - case QR_MODE_NM: { - $chunks = (int)($payload / 10); - $remain = $payload - $chunks * 10; - $size = $chunks * 3; - if ($remain >= 7) { - $size += 2; - } elseif ($remain >= 4) { - $size += 1; - } - break; - } - case QR_MODE_AN: { - $chunks = (int)($payload / 11); - $remain = $payload - $chunks * 11; - $size = $chunks * 2; - if ($remain >= 6) { - ++$size; - } - break; - } - case QR_MODE_8B: { - $size = (int)($payload / 8); - break; - } - case QR_MODE_KJ: { - $size = (int)(($payload / 13) * 2); - break; - } - case QR_MODE_ST: { - $size = (int)($payload / 8); - break; - } - default: { - $size = 0; - break; - } - } - $maxsize = $this->maximumWords($mode, $version); - if ($size < 0) { - $size = 0; - } - if ($size > $maxsize) { - $size = $maxsize; - } - return $size; - } - - /** - * createBitStream - * @param array $items - * @return array of items and total bits - */ - protected function createBitStream($items) { - $total = 0; - foreach ($items as $key => $item) { - $items[$key] = $this->encodeBitStream($item, $this->version); - $bits = count($items[$key]['bstream']); - $total += $bits; - } - return array($items, $total); - } - - /** - * convertData - * @param array $items - * @return array items - */ - protected function convertData($items) { - $ver = $this->estimateVersion($items); - if ($ver > $this->version) { - $this->version = $ver; - } - while (true) { - $cbs = $this->createBitStream($items); - $items = $cbs[0]; - $bits = $cbs[1]; - if ($bits < 0) { - return -1; - } - $ver = $this->getMinimumVersion((int)(($bits + 7) / 8), $this->level); - if ($ver < 0) { - return -1; - } elseif ($ver > $this->version) { - $this->version = $ver; - } else { - break; - } - } - return $items; - } - - /** - * Append Padding Bit to bitstream - * @param array $bstream - * @return array bitstream - */ - protected function appendPaddingBit($bstream) { - if (is_null($bstream)) { - return null; - } - $bits = count($bstream); - $maxwords = $this->getDataLength($this->version, $this->level); - $maxbits = $maxwords * 8; - if ($maxbits == $bits) { - return $bstream; - } - if ($maxbits - $bits < 5) { - return $this->appendNum($bstream, $maxbits - $bits, 0); - } - $bits += 4; - $words = (int)(($bits + 7) / 8); - $padding = array(); - $padding = $this->appendNum($padding, $words * 8 - $bits + 4, 0); - $padlen = $maxwords - $words; - if ($padlen > 0) { - $padbuf = array(); - for ($i=0; $i<$padlen; ++$i) { - $padbuf[$i] = ($i&1)?0x11:0xec; - } - $padding = $this->appendBytes($padding, $padlen, $padbuf); - } - return $this->appendBitstream($bstream, $padding); - } - - /** - * mergeBitStream - * @param array $items items - * @return array bitstream - */ - protected function mergeBitStream($items) { - $items = $this->convertData($items); - if (!is_array($items)) { - return null; - } - $bstream = array(); - foreach ($items as $item) { - $bstream = $this->appendBitstream($bstream, $item['bstream']); - } - return $bstream; - } - - /** - * Returns a stream of bits. - * @param int $items - * @return array padded merged byte stream - */ - protected function getBitStream($items) { - $bstream = $this->mergeBitStream($items); - return $this->appendPaddingBit($bstream); - } - - /** - * Pack all bit streams padding bits into a byte array. - * @param int $items - * @return array padded merged byte stream - */ - protected function getByteStream($items) { - $bstream = $this->getBitStream($items); - return $this->bitstreamToByte($bstream); - } - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - // QRbitstream - - /** - * Return an array with zeros - * @param int $setLength array size - * @return array - */ - protected function allocate($setLength) { - return array_fill(0, $setLength, 0); - } - - /** - * Return new bitstream from number - * @param int $bits number of bits - * @param int $num number - * @return array bitstream - */ - protected function newFromNum($bits, $num) { - $bstream = $this->allocate($bits); - $mask = 1 << ($bits - 1); - for ($i=0; $i<$bits; ++$i) { - if ($num & $mask) { - $bstream[$i] = 1; - } else { - $bstream[$i] = 0; - } - $mask = $mask >> 1; - } - return $bstream; - } - - /** - * Return new bitstream from bytes - * @param int $size size - * @param array $data bytes - * @return array bitstream - */ - protected function newFromBytes($size, $data) { - $bstream = $this->allocate($size * 8); - $p=0; - for ($i=0; $i<$size; ++$i) { - $mask = 0x80; - for ($j=0; $j<8; ++$j) { - if ($data[$i] & $mask) { - $bstream[$p] = 1; - } else { - $bstream[$p] = 0; - } - $p++; - $mask = $mask >> 1; - } - } - return $bstream; - } - - /** - * Append one bitstream to another - * @param array $bitstream original bitstream - * @param array $append bitstream to append - * @return array bitstream - */ - protected function appendBitstream($bitstream, $append) { - if ((!is_array($append)) OR (count($append) == 0)) { - return $bitstream; - } - if (count($bitstream) == 0) { - return $append; - } - return array_values(array_merge($bitstream, $append)); - } - - /** - * Append one bitstream created from number to another - * @param array $bitstream original bitstream - * @param int $bits number of bits - * @param int $num number - * @return array bitstream - */ - protected function appendNum($bitstream, $bits, $num) { - if ($bits == 0) { - return 0; - } - $b = $this->newFromNum($bits, $num); - return $this->appendBitstream($bitstream, $b); - } - - /** - * Append one bitstream created from bytes to another - * @param array $bitstream original bitstream - * @param int $size size - * @param array $data bytes - * @return array bitstream - */ - protected function appendBytes($bitstream, $size, $data) { - if ($size == 0) { - return 0; - } - $b = $this->newFromBytes($size, $data); - return $this->appendBitstream($bitstream, $b); - } - - /** - * Convert bitstream to bytes - * @param array $bstream original bitstream - * @return array of bytes - */ - protected function bitstreamToByte($bstream) { - if (is_null($bstream)) { - return null; - } - $size = count($bstream); - if ($size == 0) { - return array(); - } - $data = array_fill(0, (int)(($size + 7) / 8), 0); - $bytes = (int)($size / 8); - $p = 0; - for ($i=0; $i<$bytes; $i++) { - $v = 0; - for ($j=0; $j<8; $j++) { - $v = $v << 1; - $v |= $bstream[$p]; - $p++; - } - $data[$i] = $v; - } - if ($size & 7) { - $v = 0; - for ($j=0; $j<($size & 7); $j++) { - $v = $v << 1; - $v |= $bstream[$p]; - $p++; - } - $data[$bytes] = $v; - } - return $data; - } - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - // QRspec - - /** - * Replace a value on the array at the specified position - * @param array $srctab - * @param int $x X position - * @param int $y Y position - * @param string $repl value to replace - * @param int $replLen length of the repl string - * @return array srctab - */ - protected function qrstrset($srctab, $x, $y, $repl, $replLen=false) { - $srctab[$y] = substr_replace($srctab[$y], ($replLen !== false)?substr($repl,0,$replLen):$repl, $x, ($replLen !== false)?$replLen:strlen($repl)); - return $srctab; - } - - /** - * Return maximum data code length (bytes) for the version. - * @param int $version version - * @param int $level error correction level - * @return int maximum size (bytes) - */ - protected function getDataLength($version, $level) { - return $this->capacity[$version][QRCAP_WORDS] - $this->capacity[$version][QRCAP_EC][$level]; - } - - /** - * Return maximum error correction code length (bytes) for the version. - * @param int $version version - * @param int $level error correction level - * @return int ECC size (bytes) - */ - protected function getECCLength($version, $level){ - return $this->capacity[$version][QRCAP_EC][$level]; - } - - /** - * Return the width of the symbol for the version. - * @param int $version version - * @return int width - */ - protected function getWidth($version) { - return $this->capacity[$version][QRCAP_WIDTH]; - } - - /** - * Return the numer of remainder bits. - * @param int $version version - * @return int number of remainder bits - */ - protected function getRemainder($version) { - return $this->capacity[$version][QRCAP_REMINDER]; - } - - /** - * Return a version number that satisfies the input code length. - * @param int $size input code length (bytes) - * @param int $level error correction level - * @return int version number - */ - protected function getMinimumVersion($size, $level) { - for ($i = 1; $i <= QRSPEC_VERSION_MAX; ++$i) { - $words = ($this->capacity[$i][QRCAP_WORDS] - $this->capacity[$i][QRCAP_EC][$level]); - if ($words >= $size) { - return $i; - } - } - // the size of input data is greater than QR capacity, try to lover the error correction mode - return -1; - } - - /** - * Return the size of length indicator for the mode and version. - * @param int $mode encoding mode - * @param int $version version - * @return int the size of the appropriate length indicator (bits). - */ - protected function lengthIndicator($mode, $version) { - if ($mode == QR_MODE_ST) { - return 0; - } - if ($version <= 9) { - $l = 0; - } elseif ($version <= 26) { - $l = 1; - } else { - $l = 2; - } - return $this->lengthTableBits[$mode][$l]; - } - - /** - * Return the maximum length for the mode and version. - * @param int $mode encoding mode - * @param int $version version - * @return int the maximum length (bytes) - */ - protected function maximumWords($mode, $version) { - if ($mode == QR_MODE_ST) { - return 3; - } - if ($version <= 9) { - $l = 0; - } else if ($version <= 26) { - $l = 1; - } else { - $l = 2; - } - $bits = $this->lengthTableBits[$mode][$l]; - $words = (1 << $bits) - 1; - if ($mode == QR_MODE_KJ) { - $words *= 2; // the number of bytes is required - } - return $words; - } - - /** - * Return an array of ECC specification. - * @param int $version version - * @param int $level error correction level - * @param array $spec an array of ECC specification contains as following: {# of type1 blocks, # of data code, # of ecc code, # of type2 blocks, # of data code} - * @return array spec - */ - protected function getEccSpec($version, $level, $spec) { - if (count($spec) < 5) { - $spec = array(0, 0, 0, 0, 0); - } - $b1 = $this->eccTable[$version][$level][0]; - $b2 = $this->eccTable[$version][$level][1]; - $data = $this->getDataLength($version, $level); - $ecc = $this->getECCLength($version, $level); - if ($b2 == 0) { - $spec[0] = $b1; - $spec[1] = (int)($data / $b1); - $spec[2] = (int)($ecc / $b1); - $spec[3] = 0; - $spec[4] = 0; - } else { - $spec[0] = $b1; - $spec[1] = (int)($data / ($b1 + $b2)); - $spec[2] = (int)($ecc / ($b1 + $b2)); - $spec[3] = $b2; - $spec[4] = $spec[1] + 1; - } - return $spec; - } - - /** - * Put an alignment marker. - * @param array $frame frame - * @param int $ox X center coordinate of the pattern - * @param int $oy Y center coordinate of the pattern - * @return array frame - */ - protected function putAlignmentMarker($frame, $ox, $oy) { - $finder = array( - "\xa1\xa1\xa1\xa1\xa1", - "\xa1\xa0\xa0\xa0\xa1", - "\xa1\xa0\xa1\xa0\xa1", - "\xa1\xa0\xa0\xa0\xa1", - "\xa1\xa1\xa1\xa1\xa1" - ); - $yStart = $oy - 2; - $xStart = $ox - 2; - for ($y=0; $y < 5; $y++) { - $frame = $this->qrstrset($frame, $xStart, $yStart+$y, $finder[$y]); - } - return $frame; - } - - /** - * Put an alignment pattern. - * @param int $version version - * @param array $frame frame - * @param int $width width - * @return array frame - */ - protected function putAlignmentPattern($version, $frame, $width) { - if ($version < 2) { - return $frame; - } - $d = $this->alignmentPattern[$version][1] - $this->alignmentPattern[$version][0]; - if ($d < 0) { - $w = 2; - } else { - $w = (int)(($width - $this->alignmentPattern[$version][0]) / $d + 2); - } - if ($w * $w - 3 == 1) { - $x = $this->alignmentPattern[$version][0]; - $y = $this->alignmentPattern[$version][0]; - $frame = $this->putAlignmentMarker($frame, $x, $y); - return $frame; - } - $cx = $this->alignmentPattern[$version][0]; - $wo = $w - 1; - for ($x=1; $x < $wo; ++$x) { - $frame = $this->putAlignmentMarker($frame, 6, $cx); - $frame = $this->putAlignmentMarker($frame, $cx, 6); - $cx += $d; - } - $cy = $this->alignmentPattern[$version][0]; - for ($y=0; $y < $wo; ++$y) { - $cx = $this->alignmentPattern[$version][0]; - for ($x=0; $x < $wo; ++$x) { - $frame = $this->putAlignmentMarker($frame, $cx, $cy); - $cx += $d; - } - $cy += $d; - } - return $frame; - } - - /** - * Return BCH encoded version information pattern that is used for the symbol of version 7 or greater. Use lower 18 bits. - * @param int $version version - * @return string BCH encoded version information pattern - */ - protected function getVersionPattern($version) { - if (($version < 7) OR ($version > QRSPEC_VERSION_MAX)) { - return 0; - } - return $this->versionPattern[($version - 7)]; - } - - /** - * Return BCH encoded format information pattern. - * @param array $mask - * @param int $level error correction level - * @return string BCH encoded format information pattern - */ - protected function getFormatInfo($mask, $level) { - if (($mask < 0) OR ($mask > 7)) { - return 0; - } - if (($level < 0) OR ($level > 3)) { - return 0; - } - return $this->formatInfo[$level][$mask]; - } - - /** - * Put a finder pattern. - * @param array $frame frame - * @param int $ox X center coordinate of the pattern - * @param int $oy Y center coordinate of the pattern - * @return array frame - */ - protected function putFinderPattern($frame, $ox, $oy) { - $finder = array( - "\xc1\xc1\xc1\xc1\xc1\xc1\xc1", - "\xc1\xc0\xc0\xc0\xc0\xc0\xc1", - "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", - "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", - "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", - "\xc1\xc0\xc0\xc0\xc0\xc0\xc1", - "\xc1\xc1\xc1\xc1\xc1\xc1\xc1" - ); - for ($y=0; $y < 7; $y++) { - $frame = $this->qrstrset($frame, $ox, ($oy + $y), $finder[$y]); - } - return $frame; - } - - /** - * Return a copy of initialized frame. - * @param int $version version - * @return array array of unsigned char. - */ - protected function createFrame($version) { - $width = $this->capacity[$version][QRCAP_WIDTH]; - $frameLine = str_repeat ("\0", $width); - $frame = array_fill(0, $width, $frameLine); - // Finder pattern - $frame = $this->putFinderPattern($frame, 0, 0); - $frame = $this->putFinderPattern($frame, $width - 7, 0); - $frame = $this->putFinderPattern($frame, 0, $width - 7); - // Separator - $yOffset = $width - 7; - for ($y=0; $y < 7; ++$y) { - $frame[$y][7] = "\xc0"; - $frame[$y][$width - 8] = "\xc0"; - $frame[$yOffset][7] = "\xc0"; - ++$yOffset; - } - $setPattern = str_repeat("\xc0", 8); - $frame = $this->qrstrset($frame, 0, 7, $setPattern); - $frame = $this->qrstrset($frame, $width-8, 7, $setPattern); - $frame = $this->qrstrset($frame, 0, $width - 8, $setPattern); - // Format info - $setPattern = str_repeat("\x84", 9); - $frame = $this->qrstrset($frame, 0, 8, $setPattern); - $frame = $this->qrstrset($frame, $width - 8, 8, $setPattern, 8); - $yOffset = $width - 8; - for ($y=0; $y < 8; ++$y,++$yOffset) { - $frame[$y][8] = "\x84"; - $frame[$yOffset][8] = "\x84"; - } - // Timing pattern - $wo = $width - 15; - for ($i=1; $i < $wo; ++$i) { - $frame[6][7+$i] = chr(0x90 | ($i & 1)); - $frame[7+$i][6] = chr(0x90 | ($i & 1)); - } - // Alignment pattern - $frame = $this->putAlignmentPattern($version, $frame, $width); - // Version information - if ($version >= 7) { - $vinf = $this->getVersionPattern($version); - $v = $vinf; - for ($x=0; $x<6; ++$x) { - for ($y=0; $y<3; ++$y) { - $frame[($width - 11)+$y][$x] = chr(0x88 | ($v & 1)); - $v = $v >> 1; - } - } - $v = $vinf; - for ($y=0; $y<6; ++$y) { - for ($x=0; $x<3; ++$x) { - $frame[$y][$x+($width - 11)] = chr(0x88 | ($v & 1)); - $v = $v >> 1; - } - } - } - // and a little bit... - $frame[$width - 8][8] = "\x81"; - return $frame; - } - - /** - * Set new frame for the specified version. - * @param int $version version - * @return array array of unsigned char. - */ - protected function newFrame($version) { - if (($version < 1) OR ($version > QRSPEC_VERSION_MAX)) { - return NULL; - } - if (!isset($this->frames[$version])) { - $this->frames[$version] = $this->createFrame($version); - } - if (is_null($this->frames[$version])) { - return NULL; - } - return $this->frames[$version]; - } - - /** - * Return block number 0 - * @param array $spec - * @return int value - */ - protected function rsBlockNum($spec) { - return ($spec[0] + $spec[3]); - } - - /** - * Return block number 1 - * @param array $spec - * @return int value - */ - protected function rsBlockNum1($spec) { - return $spec[0]; - } - - /** - * Return data codes 1 - * @param array $spec - * @return int value - */ - protected function rsDataCodes1($spec) { - return $spec[1]; - } - - /** - * Return ecc codes 1 - * @param array $spec - * @return int value - */ - protected function rsEccCodes1($spec) { - return $spec[2]; - } - - /** - * Return block number 2 - * @param array $spec - * @return int value - */ - protected function rsBlockNum2($spec) { - return $spec[3]; - } - - /** - * Return data codes 2 - * @param array $spec - * @return int value - */ - protected function rsDataCodes2($spec) { - return $spec[4]; - } - - /** - * Return ecc codes 2 - * @param array $spec - * @return int value - */ - protected function rsEccCodes2($spec) { - return $spec[2]; - } - - /** - * Return data length - * @param array $spec - * @return int value - */ - protected function rsDataLength($spec) { - return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]); - } - - /** - * Return ecc length - * @param array $spec - * @return int value - */ - protected function rsEccLength($spec) { - return ($spec[0] + $spec[3]) * $spec[2]; - } - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - // QRrs - - /** - * Initialize a Reed-Solomon codec and add it to existing rsitems - * @param int $symsize symbol size, bits - * @param int $gfpoly Field generator polynomial coefficients - * @param int $fcr first root of RS code generator polynomial, index form - * @param int $prim primitive element to generate polynomial roots - * @param int $nroots RS code generator polynomial degree (number of roots) - * @param int $pad padding bytes at front of shortened block - * @return array Array of RS values:<ul><li>mm = Bits per symbol;</li><li>nn = Symbols per block;</li><li>alpha_to = log lookup table array;</li><li>index_of = Antilog lookup table array;</li><li>genpoly = Generator polynomial array;</li><li>nroots = Number of generator;</li><li>roots = number of parity symbols;</li><li>fcr = First consecutive root, index form;</li><li>prim = Primitive element, index form;</li><li>iprim = prim-th root of 1, index form;</li><li>pad = Padding bytes in shortened block;</li><li>gfpoly</ul>. - */ - protected function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) { - foreach ($this->rsitems as $rs) { - if (($rs['pad'] != $pad) OR ($rs['nroots'] != $nroots) OR ($rs['mm'] != $symsize) - OR ($rs['gfpoly'] != $gfpoly) OR ($rs['fcr'] != $fcr) OR ($rs['prim'] != $prim)) { - continue; - } - return $rs; - } - $rs = $this->init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad); - array_unshift($this->rsitems, $rs); - return $rs; - } - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - // QRrsItem - - /** - * modnn - * @param array $rs RS values - * @param int $x X position - * @return int X osition - */ - protected function modnn($rs, $x) { - while ($x >= $rs['nn']) { - $x -= $rs['nn']; - $x = ($x >> $rs['mm']) + ($x & $rs['nn']); - } - return $x; - } - - /** - * Initialize a Reed-Solomon codec and returns an array of values. - * @param int $symsize symbol size, bits - * @param int $gfpoly Field generator polynomial coefficients - * @param int $fcr first root of RS code generator polynomial, index form - * @param int $prim primitive element to generate polynomial roots - * @param int $nroots RS code generator polynomial degree (number of roots) - * @param int $pad padding bytes at front of shortened block - * @return array Array of RS values:<ul><li>mm = Bits per symbol;</li><li>nn = Symbols per block;</li><li>alpha_to = log lookup table array;</li><li>index_of = Antilog lookup table array;</li><li>genpoly = Generator polynomial array;</li><li>nroots = Number of generator;</li><li>roots = number of parity symbols;</li><li>fcr = First consecutive root, index form;</li><li>prim = Primitive element, index form;</li><li>iprim = prim-th root of 1, index form;</li><li>pad = Padding bytes in shortened block;</li><li>gfpoly</ul>. - */ - protected function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) { - // Based on Reed solomon encoder by Phil Karn, KA9Q (GNU-LGPLv2) - $rs = null; - // Check parameter ranges - if (($symsize < 0) OR ($symsize > 8)) { - return $rs; - } - if (($fcr < 0) OR ($fcr >= (1<<$symsize))) { - return $rs; - } - if (($prim <= 0) OR ($prim >= (1<<$symsize))) { - return $rs; - } - if (($nroots < 0) OR ($nroots >= (1<<$symsize))) { - return $rs; - } - if (($pad < 0) OR ($pad >= ((1<<$symsize) -1 - $nroots))) { - return $rs; - } - $rs = array(); - $rs['mm'] = $symsize; - $rs['nn'] = (1 << $symsize) - 1; - $rs['pad'] = $pad; - $rs['alpha_to'] = array_fill(0, ($rs['nn'] + 1), 0); - $rs['index_of'] = array_fill(0, ($rs['nn'] + 1), 0); - // PHP style macro replacement ;) - $NN =& $rs['nn']; - $A0 =& $NN; - // Generate Galois field lookup tables - $rs['index_of'][0] = $A0; // log(zero) = -inf - $rs['alpha_to'][$A0] = 0; // alpha**-inf = 0 - $sr = 1; - for ($i=0; $i<$rs['nn']; ++$i) { - $rs['index_of'][$sr] = $i; - $rs['alpha_to'][$i] = $sr; - $sr <<= 1; - if ($sr & (1 << $symsize)) { - $sr ^= $gfpoly; - } - $sr &= $rs['nn']; - } - if ($sr != 1) { - // field generator polynomial is not primitive! - return NULL; - } - // Form RS code generator polynomial from its roots - $rs['genpoly'] = array_fill(0, ($nroots + 1), 0); - $rs['fcr'] = $fcr; - $rs['prim'] = $prim; - $rs['nroots'] = $nroots; - $rs['gfpoly'] = $gfpoly; - // Find prim-th root of 1, used in decoding - for ($iprim=1; ($iprim % $prim) != 0; $iprim += $rs['nn']) { - ; // intentional empty-body loop! - } - $rs['iprim'] = (int)($iprim / $prim); - $rs['genpoly'][0] = 1; - for ($i = 0,$root=$fcr*$prim; $i < $nroots; $i++, $root += $prim) { - $rs['genpoly'][$i+1] = 1; - // Multiply rs->genpoly[] by @**(root + x) - for ($j = $i; $j > 0; --$j) { - if ($rs['genpoly'][$j] != 0) { - $rs['genpoly'][$j] = $rs['genpoly'][$j-1] ^ $rs['alpha_to'][$this->modnn($rs, $rs['index_of'][$rs['genpoly'][$j]] + $root)]; - } else { - $rs['genpoly'][$j] = $rs['genpoly'][$j-1]; - } - } - // rs->genpoly[0] can never be zero - $rs['genpoly'][0] = $rs['alpha_to'][$this->modnn($rs, $rs['index_of'][$rs['genpoly'][0]] + $root)]; - } - // convert rs->genpoly[] to index form for quicker encoding - for ($i = 0; $i <= $nroots; ++$i) { - $rs['genpoly'][$i] = $rs['index_of'][$rs['genpoly'][$i]]; - } - return $rs; - } - - /** - * Encode a Reed-Solomon codec and returns the parity array - * @param array $rs RS values - * @param array $data data - * @param array $parity parity - * @return parity array - */ - protected function encode_rs_char($rs, $data, $parity) { - $MM =& $rs['mm']; // bits per symbol - $NN =& $rs['nn']; // the total number of symbols in a RS block - $ALPHA_TO =& $rs['alpha_to']; // the address of an array of NN elements to convert Galois field elements in index (log) form to polynomial form - $INDEX_OF =& $rs['index_of']; // the address of an array of NN elements to convert Galois field elements in polynomial form to index (log) form - $GENPOLY =& $rs['genpoly']; // an array of NROOTS+1 elements containing the generator polynomial in index form - $NROOTS =& $rs['nroots']; // the number of roots in the RS code generator polynomial, which is the same as the number of parity symbols in a block - $FCR =& $rs['fcr']; // first consecutive root, index form - $PRIM =& $rs['prim']; // primitive element, index form - $IPRIM =& $rs['iprim']; // prim-th root of 1, index form - $PAD =& $rs['pad']; // the number of pad symbols in a block - $A0 =& $NN; - $parity = array_fill(0, $NROOTS, 0); - for ($i=0; $i < ($NN - $NROOTS - $PAD); $i++) { - $feedback = $INDEX_OF[$data[$i] ^ $parity[0]]; - if ($feedback != $A0) { - // feedback term is non-zero - // This line is unnecessary when GENPOLY[NROOTS] is unity, as it must - // always be for the polynomials constructed by init_rs() - $feedback = $this->modnn($rs, $NN - $GENPOLY[$NROOTS] + $feedback); - for ($j=1; $j < $NROOTS; ++$j) { - $parity[$j] ^= $ALPHA_TO[$this->modnn($rs, $feedback + $GENPOLY[($NROOTS - $j)])]; - } - } - // Shift - array_shift($parity); - if ($feedback != $A0) { - array_push($parity, $ALPHA_TO[$this->modnn($rs, $feedback + $GENPOLY[0])]); - } else { - array_push($parity, 0); - } - } - return $parity; - } - -} // end QRcode class - -//============================================================+ -// END OF FILE -//============================================================+ diff --git a/lib/combodo/tcpdf/include/sRGB.icc b/lib/combodo/tcpdf/include/sRGB.icc deleted file mode 100644 index 1d8f7419c3bf2c6a3dd78f2c679fdefbda1776a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6922 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 VE+#f@4I@33!-(c_IEmSS@NW)(3LO9d diff --git a/lib/combodo/tcpdf/include/tcpdf_colors.php b/lib/combodo/tcpdf/include/tcpdf_colors.php deleted file mode 100644 index 7f337f31a..000000000 --- a/lib/combodo/tcpdf/include/tcpdf_colors.php +++ /dev/null @@ -1,462 +0,0 @@ -<?php -//============================================================+ -// File name : tcpdf_colors.php -// Version : 1.0.004 -// Begin : 2002-04-09 -// Last Update : 2014-04-25 -// Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com -// License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html) -// ------------------------------------------------------------------- -// Copyright (C) 2002-2013 Nicola Asuni - Tecnick.com LTD -// -// This file is part of TCPDF software library. -// -// TCPDF is free software: you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// TCPDF is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with TCPDF. If not, see <http://www.gnu.org/licenses/>. -// -// See LICENSE.TXT file for more information. -// ------------------------------------------------------------------- -// -// Description : Array of WEB safe colors -// -//============================================================+ - -/** - * @file - * PHP color class for TCPDF - * @author Nicola Asuni - * @package com.tecnick.tcpdf - */ - -/** - * @class TCPDF_COLORS - * PHP color class for TCPDF - * @package com.tecnick.tcpdf - * @version 1.0.004 - * @author Nicola Asuni - info@tecnick.com - */ -class TCPDF_COLORS { - - /** - * Array of WEB safe colors - * @public static - */ - public static $webcolor = array ( - 'aliceblue' => 'f0f8ff', - 'antiquewhite' => 'faebd7', - 'aqua' => '00ffff', - 'aquamarine' => '7fffd4', - 'azure' => 'f0ffff', - 'beige' => 'f5f5dc', - 'bisque' => 'ffe4c4', - 'black' => '000000', - 'blanchedalmond' => 'ffebcd', - 'blue' => '0000ff', - 'blueviolet' => '8a2be2', - 'brown' => 'a52a2a', - 'burlywood' => 'deb887', - 'cadetblue' => '5f9ea0', - 'chartreuse' => '7fff00', - 'chocolate' => 'd2691e', - 'coral' => 'ff7f50', - 'cornflowerblue' => '6495ed', - 'cornsilk' => 'fff8dc', - 'crimson' => 'dc143c', - 'cyan' => '00ffff', - 'darkblue' => '00008b', - 'darkcyan' => '008b8b', - 'darkgoldenrod' => 'b8860b', - 'dkgray' => 'a9a9a9', - 'darkgray' => 'a9a9a9', - 'darkgrey' => 'a9a9a9', - 'darkgreen' => '006400', - 'darkkhaki' => 'bdb76b', - 'darkmagenta' => '8b008b', - 'darkolivegreen' => '556b2f', - 'darkorange' => 'ff8c00', - 'darkorchid' => '9932cc', - 'darkred' => '8b0000', - 'darksalmon' => 'e9967a', - 'darkseagreen' => '8fbc8f', - 'darkslateblue' => '483d8b', - 'darkslategray' => '2f4f4f', - 'darkslategrey' => '2f4f4f', - 'darkturquoise' => '00ced1', - 'darkviolet' => '9400d3', - 'deeppink' => 'ff1493', - 'deepskyblue' => '00bfff', - 'dimgray' => '696969', - 'dimgrey' => '696969', - 'dodgerblue' => '1e90ff', - 'firebrick' => 'b22222', - 'floralwhite' => 'fffaf0', - 'forestgreen' => '228b22', - 'fuchsia' => 'ff00ff', - 'gainsboro' => 'dcdcdc', - 'ghostwhite' => 'f8f8ff', - 'gold' => 'ffd700', - 'goldenrod' => 'daa520', - 'gray' => '808080', - 'grey' => '808080', - 'green' => '008000', - 'greenyellow' => 'adff2f', - 'honeydew' => 'f0fff0', - 'hotpink' => 'ff69b4', - 'indianred' => 'cd5c5c', - 'indigo' => '4b0082', - 'ivory' => 'fffff0', - 'khaki' => 'f0e68c', - 'lavender' => 'e6e6fa', - 'lavenderblush' => 'fff0f5', - 'lawngreen' => '7cfc00', - 'lemonchiffon' => 'fffacd', - 'lightblue' => 'add8e6', - 'lightcoral' => 'f08080', - 'lightcyan' => 'e0ffff', - 'lightgoldenrodyellow' => 'fafad2', - 'ltgray' => 'd3d3d3', - 'lightgray' => 'd3d3d3', - 'lightgrey' => 'd3d3d3', - 'lightgreen' => '90ee90', - 'lightpink' => 'ffb6c1', - 'lightsalmon' => 'ffa07a', - 'lightseagreen' => '20b2aa', - 'lightskyblue' => '87cefa', - 'lightslategray' => '778899', - 'lightslategrey' => '778899', - 'lightsteelblue' => 'b0c4de', - 'lightyellow' => 'ffffe0', - 'lime' => '00ff00', - 'limegreen' => '32cd32', - 'linen' => 'faf0e6', - 'magenta' => 'ff00ff', - 'maroon' => '800000', - 'mediumaquamarine' => '66cdaa', - 'mediumblue' => '0000cd', - 'mediumorchid' => 'ba55d3', - 'mediumpurple' => '9370d8', - 'mediumseagreen' => '3cb371', - 'mediumslateblue' => '7b68ee', - 'mediumspringgreen' => '00fa9a', - 'mediumturquoise' => '48d1cc', - 'mediumvioletred' => 'c71585', - 'midnightblue' => '191970', - 'mintcream' => 'f5fffa', - 'mistyrose' => 'ffe4e1', - 'moccasin' => 'ffe4b5', - 'navajowhite' => 'ffdead', - 'navy' => '000080', - 'oldlace' => 'fdf5e6', - 'olive' => '808000', - 'olivedrab' => '6b8e23', - 'orange' => 'ffa500', - 'orangered' => 'ff4500', - 'orchid' => 'da70d6', - 'palegoldenrod' => 'eee8aa', - 'palegreen' => '98fb98', - 'paleturquoise' => 'afeeee', - 'palevioletred' => 'd87093', - 'papayawhip' => 'ffefd5', - 'peachpuff' => 'ffdab9', - 'peru' => 'cd853f', - 'pink' => 'ffc0cb', - 'plum' => 'dda0dd', - 'powderblue' => 'b0e0e6', - 'purple' => '800080', - 'red' => 'ff0000', - 'rosybrown' => 'bc8f8f', - 'royalblue' => '4169e1', - 'saddlebrown' => '8b4513', - 'salmon' => 'fa8072', - 'sandybrown' => 'f4a460', - 'seagreen' => '2e8b57', - 'seashell' => 'fff5ee', - 'sienna' => 'a0522d', - 'silver' => 'c0c0c0', - 'skyblue' => '87ceeb', - 'slateblue' => '6a5acd', - 'slategray' => '708090', - 'slategrey' => '708090', - 'snow' => 'fffafa', - 'springgreen' => '00ff7f', - 'steelblue' => '4682b4', - 'tan' => 'd2b48c', - 'teal' => '008080', - 'thistle' => 'd8bfd8', - 'tomato' => 'ff6347', - 'turquoise' => '40e0d0', - 'violet' => 'ee82ee', - 'wheat' => 'f5deb3', - 'white' => 'ffffff', - 'whitesmoke' => 'f5f5f5', - 'yellow' => 'ffff00', - 'yellowgreen' => '9acd32' - ); // end of web colors - - /** - * Array of valid JavaScript color names - * @public static - */ - public static $jscolor = array ('transparent', 'black', 'white', 'red', 'green', 'blue', 'cyan', 'magenta', 'yellow', 'dkGray', 'gray', 'ltGray'); - - /** - * Array of Spot colors (C,M,Y,K,name) - * Color keys must be in lowercase and without spaces. - * As long as no open standard for spot colours exists, you have to buy a colour book by one of the colour manufacturers and insert the values and names of spot colours directly. - * Common industry standard spot colors are: ANPA-COLOR, DIC, FOCOLTONE, GCMI, HKS, PANTONE, TOYO, TRUMATCH. - * @public static - */ - public static $spotcolor = array ( - // special registration colors - 'none' => array( 0, 0, 0, 0, 'None'), - 'all' => array(100, 100, 100, 100, 'All'), - // standard CMYK colors - 'cyan' => array(100, 0, 0, 0, 'Cyan'), - 'magenta' => array( 0, 100, 0, 0, 'Magenta'), - 'yellow' => array( 0, 0, 100, 0, 'Yellow'), - 'key' => array( 0, 0, 0, 100, 'Key'), - // alias - 'white' => array( 0, 0, 0, 0, 'White'), - 'black' => array( 0, 0, 0, 100, 'Black'), - // standard RGB colors - 'red' => array( 0, 100, 100, 0, 'Red'), - 'green' => array(100, 0, 100, 0, 'Green'), - 'blue' => array(100, 100, 0, 0, 'Blue'), - // Add here standard spot colors or dynamically define them with AddSpotColor() - // ... - ); // end of spot colors - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /** - * Return the Spot color array. - * @param string $name Name of the spot color. - * @param array $spotc Reference to an array of spot colors. - * @return array|false Spot color array or false if not defined. - * @since 5.9.125 (2011-10-03) - * @public static - */ - public static function getSpotColor($name, &$spotc) { - if (isset($spotc[$name])) { - return $spotc[$name]; - } - $color = preg_replace('/[\s]*/', '', $name); // remove extra spaces - $color = strtolower($color); - if (isset(self::$spotcolor[$color])) { - if (!isset($spotc[$name])) { - $i = (1 + count($spotc)); - $spotc[$name] = array('C' => self::$spotcolor[$color][0], 'M' => self::$spotcolor[$color][1], 'Y' => self::$spotcolor[$color][2], 'K' => self::$spotcolor[$color][3], 'name' => self::$spotcolor[$color][4], 'i' => $i); - } - return $spotc[self::$spotcolor[$color][4]]; - } - return false; - } - - /** - * Returns an array (RGB or CMYK) from an html color name, or a six-digit (i.e. #3FE5AA), or three-digit (i.e. #7FF) hexadecimal color, or a javascript color array, or javascript color name. - * @param string $hcolor HTML color. - * @param array $spotc Reference to an array of spot colors. - * @param array $defcol Color to return in case of error. - * @return array|false RGB or CMYK color, or false in case of error. - * @public static - */ - public static function convertHTMLColorToDec($hcolor, &$spotc, $defcol=array('R'=>128,'G'=>128,'B'=>128)) { - $color = preg_replace('/[\s]*/', '', $hcolor); // remove extra spaces - $color = strtolower($color); - // check for javascript color array syntax - if (strpos($color, '[') !== false) { - if (preg_match('/[\[][\"\'](t|g|rgb|cmyk)[\"\'][\,]?([0-9\.]*)[\,]?([0-9\.]*)[\,]?([0-9\.]*)[\,]?([0-9\.]*)[\]]/', $color, $m) > 0) { - $returncolor = array(); - switch ($m[1]) { - case 'cmyk': { - // RGB - $returncolor['C'] = max(0, min(100, (floatval($m[2]) * 100))); - $returncolor['M'] = max(0, min(100, (floatval($m[3]) * 100))); - $returncolor['Y'] = max(0, min(100, (floatval($m[4]) * 100))); - $returncolor['K'] = max(0, min(100, (floatval($m[5]) * 100))); - break; - } - case 'rgb': { - // RGB - $returncolor['R'] = max(0, min(255, (floatval($m[2]) * 255))); - $returncolor['G'] = max(0, min(255, (floatval($m[3]) * 255))); - $returncolor['B'] = max(0, min(255, (floatval($m[4]) * 255))); - break; - } - case 'g': { - // grayscale - $returncolor['G'] = max(0, min(255, (floatval($m[2]) * 255))); - break; - } - case 't': - default: { - // transparent (empty array) - break; - } - } - return $returncolor; - } - } elseif ((substr($color, 0, 4) != 'cmyk') AND (substr($color, 0, 3) != 'rgb') AND (($dotpos = strpos($color, '.')) !== false)) { - // remove class parent (i.e.: color.red) - $color = substr($color, ($dotpos + 1)); - if ($color == 'transparent') { - // transparent (empty array) - return array(); - } - } - if (strlen($color) == 0) { - return $defcol; - } - // RGB ARRAY - if (substr($color, 0, 3) == 'rgb') { - $codes = substr($color, 4); - $codes = str_replace(')', '', $codes); - $returncolor = explode(',', $codes); - foreach ($returncolor as $key => $val) { - if (strpos($val, '%') > 0) { - // percentage - $returncolor[$key] = (255 * intval($val) / 100); - } else { - $returncolor[$key] = intval($val); - } - // normalize value - $returncolor[$key] = max(0, min(255, $returncolor[$key])); - } - return $returncolor; - } - // CMYK ARRAY - if (substr($color, 0, 4) == 'cmyk') { - $codes = substr($color, 5); - $codes = str_replace(')', '', $codes); - $returncolor = explode(',', $codes); - foreach ($returncolor as $key => $val) { - if (strpos($val, '%') !== false) { - // percentage - $returncolor[$key] = (100 * intval($val) / 100); - } else { - $returncolor[$key] = intval($val); - } - // normalize value - $returncolor[$key] = max(0, min(100, $returncolor[$key])); - } - return $returncolor; - } - if ($color[0] != '#') { - // COLOR NAME - if (isset(self::$webcolor[$color])) { - // web color - $color_code = self::$webcolor[$color]; - } else { - // spot color - $returncolor = self::getSpotColor($hcolor, $spotc); - if ($returncolor === false) { - $returncolor = $defcol; - } - return $returncolor; - } - } else { - $color_code = substr($color, 1); - } - // HEXADECIMAL REPRESENTATION - switch (strlen($color_code)) { - case 3: { - // 3-digit RGB hexadecimal representation - $r = substr($color_code, 0, 1); - $g = substr($color_code, 1, 1); - $b = substr($color_code, 2, 1); - $returncolor = array(); - $returncolor['R'] = max(0, min(255, hexdec($r.$r))); - $returncolor['G'] = max(0, min(255, hexdec($g.$g))); - $returncolor['B'] = max(0, min(255, hexdec($b.$b))); - break; - } - case 6: { - // 6-digit RGB hexadecimal representation - $returncolor = array(); - $returncolor['R'] = max(0, min(255, hexdec(substr($color_code, 0, 2)))); - $returncolor['G'] = max(0, min(255, hexdec(substr($color_code, 2, 2)))); - $returncolor['B'] = max(0, min(255, hexdec(substr($color_code, 4, 2)))); - break; - } - case 8: { - // 8-digit CMYK hexadecimal representation - $returncolor = array(); - $returncolor['C'] = max(0, min(100, round(hexdec(substr($color_code, 0, 2)) / 2.55))); - $returncolor['M'] = max(0, min(100, round(hexdec(substr($color_code, 2, 2)) / 2.55))); - $returncolor['Y'] = max(0, min(100, round(hexdec(substr($color_code, 4, 2)) / 2.55))); - $returncolor['K'] = max(0, min(100, round(hexdec(substr($color_code, 6, 2)) / 2.55))); - break; - } - default: { - $returncolor = $defcol; - break; - } - } - return $returncolor; - } - - /** - * Convert a color array into a string representation. - * @param array $c Array of colors. - * @return string The color array representation. - * @since 5.9.137 (2011-12-01) - * @public static - */ - public static function getColorStringFromArray($c) { - $c = array_values($c); - $color = '['; - switch (count($c)) { - case 4: { - // CMYK - $color .= sprintf('%F %F %F %F', (max(0, min(100, floatval($c[0]))) / 100), (max(0, min(100, floatval($c[1]))) / 100), (max(0, min(100, floatval($c[2]))) / 100), (max(0, min(100, floatval($c[3]))) / 100)); - break; - } - case 3: { - // RGB - $color .= sprintf('%F %F %F', (max(0, min(255, floatval($c[0]))) / 255), (max(0, min(255, floatval($c[1]))) / 255), (max(0, min(255, floatval($c[2]))) / 255)); - break; - } - case 1: { - // grayscale - $color .= sprintf('%F', (max(0, min(255, floatval($c[0]))) / 255)); - break; - } - } - $color .= ']'; - return $color; - } - - /** - * Convert color to javascript color. - * @param string $color color name or "#RRGGBB" - * @protected - * @since 2.1.002 (2008-02-12) - * @public static - */ - public static function _JScolor($color) { - if (substr($color, 0, 1) == '#') { - return sprintf("['RGB',%F,%F,%F]", (hexdec(substr($color, 1, 2)) / 255), (hexdec(substr($color, 3, 2)) / 255), (hexdec(substr($color, 5, 2)) / 255)); - } - if (!in_array($color, self::$jscolor)) { - // default transparent color - $color = self::$jscolor[0]; - } - return 'color.'.$color; - } - - -} // END OF TCPDF_COLORS CLASS - -//============================================================+ -// END OF FILE -//============================================================+ diff --git a/lib/combodo/tcpdf/include/tcpdf_filters.php b/lib/combodo/tcpdf/include/tcpdf_filters.php deleted file mode 100644 index 3009cff7c..000000000 --- a/lib/combodo/tcpdf/include/tcpdf_filters.php +++ /dev/null @@ -1,481 +0,0 @@ -<?php -//============================================================+ -// File name : tcpdf_filters.php -// Version : 1.0.001 -// Begin : 2011-05-23 -// Last Update : 2014-04-25 -// Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com -// License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html) -// ------------------------------------------------------------------- -// Copyright (C) 2011-2013 Nicola Asuni - Tecnick.com LTD -// -// This file is part of TCPDF software library. -// -// TCPDF is free software: you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// TCPDF is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// -// You should have received a copy of the License -// along with TCPDF. If not, see -// <http://www.tecnick.com/pagefiles/tcpdf/LICENSE.TXT>. -// -// See LICENSE.TXT file for more information. -// ------------------------------------------------------------------- -// -// Description : This is a PHP class for decoding common PDF filters (PDF 32000-2008 - 7.4 Filters). -// -//============================================================+ - -/** - * @file - * This is a PHP class for decoding common PDF filters (PDF 32000-2008 - 7.4 Filters).<br> - * @package com.tecnick.tcpdf - * @author Nicola Asuni - * @version 1.0.001 - */ - -/** - * @class TCPDF_FILTERS - * This is a PHP class for decoding common PDF filters (PDF 32000-2008 - 7.4 Filters).<br> - * @package com.tecnick.tcpdf - * @brief This is a PHP class for decoding common PDF filters. - * @version 1.0.001 - * @author Nicola Asuni - info@tecnick.com - */ -class TCPDF_FILTERS { - - /** - * Define a list of available filter decoders. - * @private static - */ - private static $available_filters = array('ASCIIHexDecode', 'ASCII85Decode', 'LZWDecode', 'FlateDecode', 'RunLengthDecode'); - -// ----------------------------------------------------------------------------- - - /** - * Get a list of available decoding filters. - * @return array Array of available filter decoders. - * @since 1.0.000 (2011-05-23) - * @public static - */ - public static function getAvailableFilters() { - return self::$available_filters; - } - - /** - * Decode data using the specified filter type. - * @param string $filter Filter name. - * @param string $data Data to decode. - * @return string Decoded data string. - * @since 1.0.000 (2011-05-23) - * @public static - */ - public static function decodeFilter($filter, $data) { - switch ($filter) { - case 'ASCIIHexDecode': { - return self::decodeFilterASCIIHexDecode($data); - break; - } - case 'ASCII85Decode': { - return self::decodeFilterASCII85Decode($data); - break; - } - case 'LZWDecode': { - return self::decodeFilterLZWDecode($data); - break; - } - case 'FlateDecode': { - return self::decodeFilterFlateDecode($data); - break; - } - case 'RunLengthDecode': { - return self::decodeFilterRunLengthDecode($data); - break; - } - case 'CCITTFaxDecode': { - return self::decodeFilterCCITTFaxDecode($data); - break; - } - case 'JBIG2Decode': { - return self::decodeFilterJBIG2Decode($data); - break; - } - case 'DCTDecode': { - return self::decodeFilterDCTDecode($data); - break; - } - case 'JPXDecode': { - return self::decodeFilterJPXDecode($data); - break; - } - case 'Crypt': { - return self::decodeFilterCrypt($data); - break; - } - default: { - return self::decodeFilterStandard($data); - break; - } - } - } - - // --- FILTERS (PDF 32000-2008 - 7.4 Filters) ------------------------------ - - /** - * Standard - * Default decoding filter (leaves data unchanged). - * @param string $data Data to decode. - * @return string Decoded data string. - * @since 1.0.000 (2011-05-23) - * @public static - */ - public static function decodeFilterStandard($data) { - return $data; - } - - /** - * ASCIIHexDecode - * Decodes data encoded in an ASCII hexadecimal representation, reproducing the original binary data. - * @param string $data Data to decode. - * @return string Decoded data string. - * @since 1.0.000 (2011-05-23) - * @public static - */ - public static function decodeFilterASCIIHexDecode($data) { - // initialize string to return - $decoded = ''; - // all white-space characters shall be ignored - $data = preg_replace('/[\s]/', '', $data); - // check for EOD character: GREATER-THAN SIGN (3Eh) - $eod = strpos($data, '>'); - if ($eod !== false) { - // remove EOD and extra data (if any) - $data = substr($data, 0, $eod); - $eod = true; - } - // get data length - $data_length = strlen($data); - if (($data_length % 2) != 0) { - // odd number of hexadecimal digits - if ($eod) { - // EOD shall behave as if a 0 (zero) followed the last digit - $data = substr($data, 0, -1).'0'.substr($data, -1); - } else { - self::Error('decodeFilterASCIIHexDecode: invalid code'); - } - } - // check for invalid characters - if (preg_match('/[^a-fA-F\d]/', $data) > 0) { - self::Error('decodeFilterASCIIHexDecode: invalid code'); - } - // get one byte of binary data for each pair of ASCII hexadecimal digits - $decoded = pack('H*', $data); - return $decoded; - } - - /** - * ASCII85Decode - * Decodes data encoded in an ASCII base-85 representation, reproducing the original binary data. - * @param string $data Data to decode. - * @return string Decoded data string. - * @since 1.0.000 (2011-05-23) - * @public static - */ - public static function decodeFilterASCII85Decode($data) { - // initialize string to return - $decoded = ''; - // all white-space characters shall be ignored - $data = preg_replace('/[\s]/', '', $data); - // remove start sequence 2-character sequence <~ (3Ch)(7Eh) - if (strpos($data, '<~') !== false) { - // remove EOD and extra data (if any) - $data = substr($data, 2); - } - // check for EOD: 2-character sequence ~> (7Eh)(3Eh) - $eod = strpos($data, '~>'); - if ($eod !== false) { - // remove EOD and extra data (if any) - $data = substr($data, 0, $eod); - } - // data length - $data_length = strlen($data); - // check for invalid characters - if (preg_match('/[^\x21-\x75,\x74]/', $data) > 0) { - self::Error('decodeFilterASCII85Decode: invalid code'); - } - // z sequence - $zseq = chr(0).chr(0).chr(0).chr(0); - // position inside a group of 4 bytes (0-3) - $group_pos = 0; - $tuple = 0; - $pow85 = array((85*85*85*85), (85*85*85), (85*85), 85, 1); - $last_pos = ($data_length - 1); - // for each byte - for ($i = 0; $i < $data_length; ++$i) { - // get char value - $char = ord($data[$i]); - if ($char == 122) { // 'z' - if ($group_pos == 0) { - $decoded .= $zseq; - } else { - self::Error('decodeFilterASCII85Decode: invalid code'); - } - } else { - // the value represented by a group of 5 characters should never be greater than 2^32 - 1 - $tuple += (($char - 33) * $pow85[$group_pos]); - if ($group_pos == 4) { - $decoded .= chr($tuple >> 24).chr($tuple >> 16).chr($tuple >> 8).chr($tuple); - $tuple = 0; - $group_pos = 0; - } else { - ++$group_pos; - } - } - } - if ($group_pos > 1) { - $tuple += $pow85[($group_pos - 1)]; - } - // last tuple (if any) - switch ($group_pos) { - case 4: { - $decoded .= chr($tuple >> 24).chr($tuple >> 16).chr($tuple >> 8); - break; - } - case 3: { - $decoded .= chr($tuple >> 24).chr($tuple >> 16); - break; - } - case 2: { - $decoded .= chr($tuple >> 24); - break; - } - case 1: { - self::Error('decodeFilterASCII85Decode: invalid code'); - break; - } - } - return $decoded; - } - - /** - * LZWDecode - * Decompresses data encoded using the LZW (Lempel-Ziv-Welch) adaptive compression method, reproducing the original text or binary data. - * @param string $data Data to decode. - * @return string Decoded data string. - * @since 1.0.000 (2011-05-23) - * @public static - */ - public static function decodeFilterLZWDecode($data) { - // initialize string to return - $decoded = ''; - // data length - $data_length = strlen($data); - // convert string to binary string - $bitstring = ''; - for ($i = 0; $i < $data_length; ++$i) { - $bitstring .= sprintf('%08b', ord($data[$i])); - } - // get the number of bits - $data_length = strlen($bitstring); - // initialize code length in bits - $bitlen = 9; - // initialize dictionary index - $dix = 258; - // initialize the dictionary (with the first 256 entries). - $dictionary = array(); - for ($i = 0; $i < 256; ++$i) { - $dictionary[$i] = chr($i); - } - // previous val - $prev_index = 0; - // while we encounter EOD marker (257), read code_length bits - while (($data_length > 0) AND (($index = bindec(substr($bitstring, 0, $bitlen))) != 257)) { - // remove read bits from string - $bitstring = substr($bitstring, $bitlen); - // update number of bits - $data_length -= $bitlen; - if ($index == 256) { // clear-table marker - // reset code length in bits - $bitlen = 9; - // reset dictionary index - $dix = 258; - $prev_index = 256; - // reset the dictionary (with the first 256 entries). - $dictionary = array(); - for ($i = 0; $i < 256; ++$i) { - $dictionary[$i] = chr($i); - } - } elseif ($prev_index == 256) { - // first entry - $decoded .= $dictionary[$index]; - $prev_index = $index; - } else { - // check if index exist in the dictionary - if ($index < $dix) { - // index exist on dictionary - $decoded .= $dictionary[$index]; - $dic_val = $dictionary[$prev_index].$dictionary[$index][0]; - // store current index - $prev_index = $index; - } else { - // index do not exist on dictionary - $dic_val = $dictionary[$prev_index].$dictionary[$prev_index][0]; - $decoded .= $dic_val; - } - // update dictionary - $dictionary[$dix] = $dic_val; - ++$dix; - // change bit length by case - if ($dix == 2047) { - $bitlen = 12; - } elseif ($dix == 1023) { - $bitlen = 11; - } elseif ($dix == 511) { - $bitlen = 10; - } - } - } - return $decoded; - } - - /** - * FlateDecode - * Decompresses data encoded using the zlib/deflate compression method, reproducing the original text or binary data. - * @param string $data Data to decode. - * @return string Decoded data string. - * @since 1.0.000 (2011-05-23) - * @public static - */ - public static function decodeFilterFlateDecode($data) { - // initialize string to return - $decoded = @gzuncompress($data); - if ($decoded === false) { - self::Error('decodeFilterFlateDecode: invalid code'); - } - return $decoded; - } - - /** - * RunLengthDecode - * Decompresses data encoded using a byte-oriented run-length encoding algorithm. - * @param string $data Data to decode. - * @since 1.0.000 (2011-05-23) - * @public static - */ - public static function decodeFilterRunLengthDecode($data) { - // initialize string to return - $decoded = ''; - // data length - $data_length = strlen($data); - $i = 0; - while($i < $data_length) { - // get current byte value - $byte = ord($data[$i]); - if ($byte == 128) { - // a length value of 128 denote EOD - break; - } elseif ($byte < 128) { - // if the length byte is in the range 0 to 127 - // the following length + 1 (1 to 128) bytes shall be copied literally during decompression - $decoded .= substr($data, ($i + 1), ($byte + 1)); - // move to next block - $i += ($byte + 2); - } else { - // if length is in the range 129 to 255, - // the following single byte shall be copied 257 - length (2 to 128) times during decompression - $decoded .= str_repeat($data[($i + 1)], (257 - $byte)); - // move to next block - $i += 2; - } - } - return $decoded; - } - - /** - * CCITTFaxDecode (NOT IMPLEMETED - RETURN AN EXCEPTION) - * Decompresses data encoded using the CCITT facsimile standard, reproducing the original data (typically monochrome image data at 1 bit per pixel). - * @param string $data Data to decode. - * @return string Decoded data string. - * @since 1.0.000 (2011-05-23) - * @public static - */ - public static function decodeFilterCCITTFaxDecode($data) { - self::Error('~decodeFilterCCITTFaxDecode: this method has not been yet implemented'); - //return $data; - } - - /** - * JBIG2Decode (NOT IMPLEMETED - RETURN AN EXCEPTION) - * Decompresses data encoded using the JBIG2 standard, reproducing the original monochrome (1 bit per pixel) image data (or an approximation of that data). - * @param string $data Data to decode. - * @return string Decoded data string. - * @since 1.0.000 (2011-05-23) - * @public static - */ - public static function decodeFilterJBIG2Decode($data) { - self::Error('~decodeFilterJBIG2Decode: this method has not been yet implemented'); - //return $data; - } - - /** - * DCTDecode (NOT IMPLEMETED - RETURN AN EXCEPTION) - * Decompresses data encoded using a DCT (discrete cosine transform) technique based on the JPEG standard, reproducing image sample data that approximates the original data. - * @param string $data Data to decode. - * @return string Decoded data string. - * @since 1.0.000 (2011-05-23) - * @public static - */ - public static function decodeFilterDCTDecode($data) { - self::Error('~decodeFilterDCTDecode: this method has not been yet implemented'); - //return $data; - } - - /** - * JPXDecode (NOT IMPLEMETED - RETURN AN EXCEPTION) - * Decompresses data encoded using the wavelet-based JPEG2000 standard, reproducing the original image data. - * @param string $data Data to decode. - * @return string Decoded data string. - * @since 1.0.000 (2011-05-23) - * @public static - */ - public static function decodeFilterJPXDecode($data) { - self::Error('~decodeFilterJPXDecode: this method has not been yet implemented'); - //return $data; - } - - /** - * Crypt (NOT IMPLEMETED - RETURN AN EXCEPTION) - * Decrypts data encrypted by a security handler, reproducing the data as it was before encryption. - * @param string $data Data to decode. - * @return string Decoded data string. - * @since 1.0.000 (2011-05-23) - * @public static - */ - public static function decodeFilterCrypt($data) { - self::Error('~decodeFilterCrypt: this method has not been yet implemented'); - //return $data; - } - - // --- END FILTERS SECTION ------------------------------------------------- - - /** - * Throw an exception. - * @param string $msg The error message - * @since 1.0.000 (2011-05-23) - * @public static - */ - public static function Error($msg) { - throw new Exception('TCPDF_PARSER ERROR: '.$msg); - } - -} // END OF TCPDF_FILTERS CLASS - -//============================================================+ -// END OF FILE -//============================================================+ diff --git a/lib/combodo/tcpdf/include/tcpdf_font_data.php b/lib/combodo/tcpdf/include/tcpdf_font_data.php deleted file mode 100644 index 974e72ec7..000000000 --- a/lib/combodo/tcpdf/include/tcpdf_font_data.php +++ /dev/null @@ -1,18447 +0,0 @@ -<?php -//============================================================+ -// File name : tcpdf_font_data.php -// Version : 1.0.001 -// Begin : 2008-01-01 -// Last Update : 2013-04-01 -// Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com -// License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html) -// ------------------------------------------------------------------- -// Copyright (C) 2008-2013 Nicola Asuni - Tecnick.com LTD -// -// This file is part of TCPDF software library. -// -// TCPDF is free software: you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// TCPDF is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with TCPDF. If not, see <http://www.gnu.org/licenses/>. -// -// See LICENSE.TXT file for more information. -// ------------------------------------------------------------------- -// -// Description : Unicode data and encoding maps for TCPDF. -// -//============================================================+ - -/** - * @file - * Unicode data and encoding maps for TCPDF. - * @author Nicola Asuni - * @package com.tecnick.tcpdf - */ - -/** - * @class TCPDF_FONT_DATA - * Unicode data and encoding maps for TCPDF. - * @package com.tecnick.tcpdf - * @version 1.0.001 - * @author Nicola Asuni - info@tecnick.com - */ -class TCPDF_FONT_DATA { - -/** - * Unicode code for Left-to-Right Mark. - * @public - */ -public static $uni_LRM = 8206; - -/** - * Unicode code for Right-to-Left Mark. - * @public - */ -public static $uni_RLM = 8207; - -/** - * Unicode code for Left-to-Right Embedding. - * @public - */ -public static $uni_LRE = 8234; - -/** - * Unicode code for Right-to-Left Embedding. - * @public - */ -public static $uni_RLE = 8235; - -/** - * Unicode code for Pop Directional Format. - * @public - */ -public static $uni_PDF = 8236; - -/** - * Unicode code for Left-to-Right Override. - * @public - */ -public static $uni_LRO = 8237; - -/** - * Unicode code for Right-to-Left Override. - * @public - */ -public static $uni_RLO = 8238; - -/** - * Pattern to test RTL (Righ-To-Left) strings using regular expressions. - * @public - */ -public static $uni_RE_PATTERN_RTL = "/( - \xD6\xBE # R - | \xD7[\x80\x83\x86\x90-\xAA\xB0-\xB4] # R - | \xDF[\x80-\xAA\xB4\xB5\xBA] # R - | \xE2\x80\x8F # R - | \xEF\xAC[\x9D\x9F\xA0-\xA8\xAA-\xB6\xB8-\xBC\xBE] # R - | \xEF\xAD[\x80\x81\x83\x84\x86-\x8F] # R - | \xF0\x90\xA0[\x80-\x85\x88\x8A-\xB5\xB7\xB8\xBC\xBF] # R - | \xF0\x90\xA4[\x80-\x99] # R - | \xF0\x90\xA8[\x80\x90-\x93\x95-\x97\x99-\xB3] # R - | \xF0\x90\xA9[\x80-\x87\x90-\x98] # R - | \xE2\x80[\xAB\xAE] # RLE & RLO - )/x"; - -/** - * Pattern to test Arabic strings using regular expressions. Source: http://www.w3.org/International/questions/qa-forms-utf-8 - * @public - */ -public static $uni_RE_PATTERN_ARABIC = "/( - \xD8[\x80-\x83\x8B\x8D\x9B\x9E\x9F\xA1-\xBA] # AL - | \xD9[\x80-\x8A\xAD-\xAF\xB1-\xBF] # AL - | \xDA[\x80-\xBF] # AL - | \xDB[\x80-\x95\x9D\xA5\xA6\xAE\xAF\xBA-\xBF] # AL - | \xDC[\x80-\x8D\x90\x92-\xAF] # AL - | \xDD[\x8D-\xAD] # AL - | \xDE[\x80-\xA5\xB1] # AL - | \xEF\xAD[\x90-\xBF] # AL - | \xEF\xAE[\x80-\xB1] # AL - | \xEF\xAF[\x93-\xBF] # AL - | \xEF[\xB0-\xB3][\x80-\xBF] # AL - | \xEF\xB4[\x80-\xBD] # AL - | \xEF\xB5[\x90-\xBF] # AL - | \xEF\xB6[\x80-\x8F\x92-\xBF] # AL - | \xEF\xB7[\x80-\x87\xB0-\xBC] # AL - | \xEF\xB9[\xB0-\xB4\xB6-\xBF] # AL - | \xEF\xBA[\x80-\xBF] # AL - | \xEF\xBB[\x80-\xBC] # AL - | \xD9[\xA0-\xA9\xAB\xAC] # AN - )/x"; - -/** - * Array of Unicode types. - * @public - */ -public static $uni_type = array( -0=>'BN', -1=>'BN', -2=>'BN', -3=>'BN', -4=>'BN', -5=>'BN', -6=>'BN', -7=>'BN', -8=>'BN', -9=>'S', -10=>'B', -11=>'S', -12=>'WS', -13=>'B', -14=>'BN', -15=>'BN', -16=>'BN', -17=>'BN', -18=>'BN', -19=>'BN', -20=>'BN', -21=>'BN', -22=>'BN', -23=>'BN', -24=>'BN', -25=>'BN', -26=>'BN', -27=>'BN', -28=>'B', -29=>'B', -30=>'B', -31=>'S', -32=>'WS', -33=>'ON', -34=>'ON', -35=>'ET', -36=>'ET', -37=>'ET', -38=>'ON', -39=>'ON', -40=>'ON', -41=>'ON', -42=>'ON', -43=>'ES', -44=>'CS', -45=>'ES', -46=>'CS', -47=>'CS', -48=>'EN', -49=>'EN', -50=>'EN', -51=>'EN', -52=>'EN', -53=>'EN', -54=>'EN', -55=>'EN', -56=>'EN', -57=>'EN', -58=>'CS', -59=>'ON', -60=>'ON', -61=>'ON', -62=>'ON', -63=>'ON', -64=>'ON', -65=>'L', -66=>'L', -67=>'L', -68=>'L', -69=>'L', -70=>'L', -71=>'L', -72=>'L', -73=>'L', -74=>'L', -75=>'L', -76=>'L', -77=>'L', -78=>'L', -79=>'L', -80=>'L', -81=>'L', -82=>'L', -83=>'L', -84=>'L', -85=>'L', -86=>'L', -87=>'L', -88=>'L', -89=>'L', -90=>'L', -91=>'ON', -92=>'ON', -93=>'ON', -94=>'ON', -95=>'ON', -96=>'ON', -97=>'L', -98=>'L', -99=>'L', -100=>'L', -101=>'L', -102=>'L', -103=>'L', -104=>'L', -105=>'L', -106=>'L', -107=>'L', -108=>'L', -109=>'L', -110=>'L', -111=>'L', -112=>'L', -113=>'L', -114=>'L', -115=>'L', -116=>'L', -117=>'L', -118=>'L', -119=>'L', -120=>'L', -121=>'L', -122=>'L', -123=>'ON', -124=>'ON', -125=>'ON', -126=>'ON', -127=>'BN', -128=>'BN', -129=>'BN', -130=>'BN', -131=>'BN', -132=>'BN', -133=>'B', -134=>'BN', -135=>'BN', -136=>'BN', -137=>'BN', -138=>'BN', -139=>'BN', -140=>'BN', -141=>'BN', -142=>'BN', -143=>'BN', -144=>'BN', -145=>'BN', -146=>'BN', -147=>'BN', -148=>'BN', -149=>'BN', -150=>'BN', -151=>'BN', -152=>'BN', -153=>'BN', -154=>'BN', -155=>'BN', -156=>'BN', -157=>'BN', -158=>'BN', -159=>'BN', -160=>'CS', -161=>'ON', -162=>'ET', -163=>'ET', -164=>'ET', -165=>'ET', -166=>'ON', -167=>'ON', -168=>'ON', -169=>'ON', -170=>'L', -171=>'ON', -172=>'ON', -173=>'BN', -174=>'ON', -175=>'ON', -176=>'ET', -177=>'ET', -178=>'EN', -179=>'EN', -180=>'ON', -181=>'L', -182=>'ON', -183=>'ON', -184=>'ON', -185=>'EN', -186=>'L', -187=>'ON', -188=>'ON', -189=>'ON', -190=>'ON', -191=>'ON', -192=>'L', -193=>'L', -194=>'L', -195=>'L', -196=>'L', -197=>'L', -198=>'L', -199=>'L', -200=>'L', -201=>'L', -202=>'L', -203=>'L', -204=>'L', -205=>'L', -206=>'L', -207=>'L', -208=>'L', -209=>'L', -210=>'L', -211=>'L', -212=>'L', -213=>'L', -214=>'L', -215=>'ON', -216=>'L', -217=>'L', -218=>'L', -219=>'L', -220=>'L', -221=>'L', -222=>'L', -223=>'L', -224=>'L', -225=>'L', -226=>'L', -227=>'L', -228=>'L', -229=>'L', -230=>'L', -231=>'L', -232=>'L', -233=>'L', -234=>'L', -235=>'L', -236=>'L', -237=>'L', -238=>'L', -239=>'L', -240=>'L', -241=>'L', -242=>'L', -243=>'L', -244=>'L', -245=>'L', -246=>'L', -247=>'ON', -248=>'L', -249=>'L', -250=>'L', -251=>'L', -252=>'L', -253=>'L', -254=>'L', -255=>'L', -256=>'L', -257=>'L', -258=>'L', -259=>'L', -260=>'L', -261=>'L', -262=>'L', -263=>'L', -264=>'L', -265=>'L', -266=>'L', -267=>'L', -268=>'L', -269=>'L', -270=>'L', -271=>'L', -272=>'L', -273=>'L', -274=>'L', -275=>'L', -276=>'L', -277=>'L', -278=>'L', -279=>'L', -280=>'L', -281=>'L', -282=>'L', -283=>'L', -284=>'L', -285=>'L', -286=>'L', -287=>'L', -288=>'L', -289=>'L', -290=>'L', -291=>'L', -292=>'L', -293=>'L', -294=>'L', -295=>'L', -296=>'L', -297=>'L', -298=>'L', -299=>'L', -300=>'L', -301=>'L', -302=>'L', -303=>'L', -304=>'L', -305=>'L', -306=>'L', -307=>'L', -308=>'L', -309=>'L', -310=>'L', -311=>'L', -312=>'L', -313=>'L', -314=>'L', -315=>'L', -316=>'L', -317=>'L', -318=>'L', -319=>'L', -320=>'L', -321=>'L', -322=>'L', -323=>'L', -324=>'L', -325=>'L', -326=>'L', -327=>'L', -328=>'L', -329=>'L', -330=>'L', -331=>'L', -332=>'L', -333=>'L', -334=>'L', -335=>'L', -336=>'L', -337=>'L', -338=>'L', -339=>'L', -340=>'L', -341=>'L', -342=>'L', -343=>'L', -344=>'L', -345=>'L', -346=>'L', -347=>'L', -348=>'L', -349=>'L', -350=>'L', -351=>'L', -352=>'L', -353=>'L', -354=>'L', -355=>'L', -356=>'L', -357=>'L', -358=>'L', -359=>'L', -360=>'L', -361=>'L', -362=>'L', -363=>'L', -364=>'L', -365=>'L', -366=>'L', -367=>'L', -368=>'L', -369=>'L', -370=>'L', -371=>'L', -372=>'L', -373=>'L', -374=>'L', -375=>'L', -376=>'L', -377=>'L', -378=>'L', -379=>'L', -380=>'L', -381=>'L', -382=>'L', -383=>'L', -384=>'L', -385=>'L', -386=>'L', -387=>'L', -388=>'L', -389=>'L', -390=>'L', -391=>'L', -392=>'L', -393=>'L', -394=>'L', -395=>'L', -396=>'L', -397=>'L', -398=>'L', -399=>'L', -400=>'L', -401=>'L', -402=>'L', -403=>'L', -404=>'L', -405=>'L', -406=>'L', -407=>'L', -408=>'L', -409=>'L', -410=>'L', -411=>'L', -412=>'L', -413=>'L', -414=>'L', -415=>'L', -416=>'L', -417=>'L', -418=>'L', -419=>'L', -420=>'L', -421=>'L', -422=>'L', -423=>'L', -424=>'L', -425=>'L', -426=>'L', -427=>'L', -428=>'L', -429=>'L', -430=>'L', -431=>'L', -432=>'L', -433=>'L', -434=>'L', -435=>'L', -436=>'L', -437=>'L', -438=>'L', -439=>'L', -440=>'L', -441=>'L', -442=>'L', -443=>'L', -444=>'L', -445=>'L', -446=>'L', -447=>'L', -448=>'L', -449=>'L', -450=>'L', -451=>'L', -452=>'L', -453=>'L', -454=>'L', -455=>'L', -456=>'L', -457=>'L', -458=>'L', -459=>'L', -460=>'L', -461=>'L', -462=>'L', -463=>'L', -464=>'L', -465=>'L', -466=>'L', -467=>'L', -468=>'L', -469=>'L', -470=>'L', -471=>'L', -472=>'L', -473=>'L', -474=>'L', -475=>'L', -476=>'L', -477=>'L', -478=>'L', -479=>'L', -480=>'L', -481=>'L', -482=>'L', -483=>'L', -484=>'L', -485=>'L', -486=>'L', -487=>'L', -488=>'L', -489=>'L', -490=>'L', -491=>'L', -492=>'L', -493=>'L', -494=>'L', -495=>'L', -496=>'L', -497=>'L', -498=>'L', -499=>'L', -500=>'L', -501=>'L', -502=>'L', -503=>'L', -504=>'L', -505=>'L', -506=>'L', -507=>'L', -508=>'L', -509=>'L', -510=>'L', -511=>'L', -512=>'L', -513=>'L', -514=>'L', -515=>'L', -516=>'L', -517=>'L', -518=>'L', -519=>'L', -520=>'L', -521=>'L', -522=>'L', -523=>'L', -524=>'L', -525=>'L', -526=>'L', -527=>'L', -528=>'L', -529=>'L', -530=>'L', -531=>'L', -532=>'L', -533=>'L', -534=>'L', -535=>'L', -536=>'L', -537=>'L', -538=>'L', -539=>'L', -540=>'L', -541=>'L', -542=>'L', -543=>'L', -544=>'L', -545=>'L', -546=>'L', -547=>'L', -548=>'L', -549=>'L', -550=>'L', -551=>'L', -552=>'L', -553=>'L', -554=>'L', -555=>'L', -556=>'L', -557=>'L', -558=>'L', -559=>'L', -560=>'L', -561=>'L', -562=>'L', -563=>'L', -564=>'L', -565=>'L', -566=>'L', -567=>'L', -568=>'L', -569=>'L', -570=>'L', -571=>'L', -572=>'L', -573=>'L', -574=>'L', -575=>'L', -576=>'L', -577=>'L', -578=>'L', -579=>'L', -580=>'L', -581=>'L', -582=>'L', -583=>'L', -584=>'L', -585=>'L', -586=>'L', -587=>'L', -588=>'L', -589=>'L', -590=>'L', -591=>'L', -592=>'L', -593=>'L', -594=>'L', -595=>'L', -596=>'L', -597=>'L', -598=>'L', -599=>'L', -600=>'L', -601=>'L', -602=>'L', -603=>'L', -604=>'L', -605=>'L', -606=>'L', -607=>'L', -608=>'L', -609=>'L', -610=>'L', -611=>'L', -612=>'L', -613=>'L', -614=>'L', -615=>'L', -616=>'L', -617=>'L', -618=>'L', -619=>'L', -620=>'L', -621=>'L', -622=>'L', -623=>'L', -624=>'L', -625=>'L', -626=>'L', -627=>'L', -628=>'L', -629=>'L', -630=>'L', -631=>'L', -632=>'L', -633=>'L', -634=>'L', -635=>'L', -636=>'L', -637=>'L', -638=>'L', -639=>'L', -640=>'L', -641=>'L', -642=>'L', -643=>'L', -644=>'L', -645=>'L', -646=>'L', -647=>'L', -648=>'L', -649=>'L', -650=>'L', -651=>'L', -652=>'L', -653=>'L', -654=>'L', -655=>'L', -656=>'L', -657=>'L', -658=>'L', -659=>'L', -660=>'L', -661=>'L', -662=>'L', -663=>'L', -664=>'L', -665=>'L', -666=>'L', -667=>'L', -668=>'L', -669=>'L', -670=>'L', -671=>'L', -672=>'L', -673=>'L', -674=>'L', -675=>'L', -676=>'L', -677=>'L', -678=>'L', -679=>'L', -680=>'L', -681=>'L', -682=>'L', -683=>'L', -684=>'L', -685=>'L', -686=>'L', -687=>'L', -688=>'L', -689=>'L', -690=>'L', -691=>'L', -692=>'L', -693=>'L', -694=>'L', -695=>'L', -696=>'L', -697=>'ON', -698=>'ON', -699=>'L', -700=>'L', -701=>'L', -702=>'L', -703=>'L', -704=>'L', -705=>'L', -706=>'ON', -707=>'ON', -708=>'ON', -709=>'ON', -710=>'ON', -711=>'ON', -712=>'ON', -713=>'ON', -714=>'ON', -715=>'ON', -716=>'ON', -717=>'ON', -718=>'ON', -719=>'ON', -720=>'L', -721=>'L', -722=>'ON', -723=>'ON', -724=>'ON', -725=>'ON', -726=>'ON', -727=>'ON', -728=>'ON', -729=>'ON', -730=>'ON', -731=>'ON', -732=>'ON', -733=>'ON', -734=>'ON', -735=>'ON', -736=>'L', -737=>'L', -738=>'L', -739=>'L', -740=>'L', -741=>'ON', -742=>'ON', -743=>'ON', -744=>'ON', -745=>'ON', -746=>'ON', -747=>'ON', -748=>'ON', -749=>'ON', -750=>'L', -751=>'ON', -752=>'ON', -753=>'ON', -754=>'ON', -755=>'ON', -756=>'ON', -757=>'ON', -758=>'ON', -759=>'ON', -760=>'ON', -761=>'ON', -762=>'ON', -763=>'ON', -764=>'ON', -765=>'ON', -766=>'ON', -767=>'ON', -768=>'NSM', -769=>'NSM', -770=>'NSM', -771=>'NSM', -772=>'NSM', -773=>'NSM', -774=>'NSM', -775=>'NSM', -776=>'NSM', -777=>'NSM', -778=>'NSM', -779=>'NSM', -780=>'NSM', -781=>'NSM', -782=>'NSM', -783=>'NSM', -784=>'NSM', -785=>'NSM', -786=>'NSM', -787=>'NSM', -788=>'NSM', -789=>'NSM', -790=>'NSM', -791=>'NSM', -792=>'NSM', -793=>'NSM', -794=>'NSM', -795=>'NSM', -796=>'NSM', -797=>'NSM', -798=>'NSM', -799=>'NSM', -800=>'NSM', -801=>'NSM', -802=>'NSM', -803=>'NSM', -804=>'NSM', -805=>'NSM', -806=>'NSM', -807=>'NSM', -808=>'NSM', -809=>'NSM', -810=>'NSM', -811=>'NSM', -812=>'NSM', -813=>'NSM', -814=>'NSM', -815=>'NSM', -816=>'NSM', -817=>'NSM', -818=>'NSM', -819=>'NSM', -820=>'NSM', -821=>'NSM', -822=>'NSM', -823=>'NSM', -824=>'NSM', -825=>'NSM', -826=>'NSM', -827=>'NSM', -828=>'NSM', -829=>'NSM', -830=>'NSM', -831=>'NSM', -832=>'NSM', -833=>'NSM', -834=>'NSM', -835=>'NSM', -836=>'NSM', -837=>'NSM', -838=>'NSM', -839=>'NSM', -840=>'NSM', -841=>'NSM', -842=>'NSM', -843=>'NSM', -844=>'NSM', -845=>'NSM', -846=>'NSM', -847=>'NSM', -848=>'NSM', -849=>'NSM', -850=>'NSM', -851=>'NSM', -852=>'NSM', -853=>'NSM', -854=>'NSM', -855=>'NSM', -856=>'NSM', -857=>'NSM', -858=>'NSM', -859=>'NSM', -860=>'NSM', -861=>'NSM', -862=>'NSM', -863=>'NSM', -864=>'NSM', -865=>'NSM', -866=>'NSM', -867=>'NSM', -868=>'NSM', -869=>'NSM', -870=>'NSM', -871=>'NSM', -872=>'NSM', -873=>'NSM', -874=>'NSM', -875=>'NSM', -876=>'NSM', -877=>'NSM', -878=>'NSM', -879=>'NSM', -884=>'ON', -885=>'ON', -890=>'L', -891=>'L', -892=>'L', -893=>'L', -894=>'ON', -900=>'ON', -901=>'ON', -902=>'L', -903=>'ON', -904=>'L', -905=>'L', -906=>'L', -908=>'L', -910=>'L', -911=>'L', -912=>'L', -913=>'L', -914=>'L', -915=>'L', -916=>'L', -917=>'L', -918=>'L', -919=>'L', -920=>'L', -921=>'L', -922=>'L', -923=>'L', -924=>'L', -925=>'L', -926=>'L', -927=>'L', -928=>'L', -929=>'L', -931=>'L', -932=>'L', -933=>'L', -934=>'L', -935=>'L', -936=>'L', -937=>'L', -938=>'L', -939=>'L', -940=>'L', -941=>'L', -942=>'L', -943=>'L', -944=>'L', -945=>'L', -946=>'L', -947=>'L', -948=>'L', -949=>'L', -950=>'L', -951=>'L', -952=>'L', -953=>'L', -954=>'L', -955=>'L', -956=>'L', -957=>'L', -958=>'L', -959=>'L', -960=>'L', -961=>'L', -962=>'L', -963=>'L', -964=>'L', -965=>'L', -966=>'L', -967=>'L', -968=>'L', -969=>'L', -970=>'L', -971=>'L', -972=>'L', -973=>'L', -974=>'L', -976=>'L', -977=>'L', -978=>'L', -979=>'L', -980=>'L', -981=>'L', -982=>'L', -983=>'L', -984=>'L', -985=>'L', -986=>'L', -987=>'L', -988=>'L', -989=>'L', -990=>'L', -991=>'L', -992=>'L', -993=>'L', -994=>'L', -995=>'L', -996=>'L', -997=>'L', -998=>'L', -999=>'L', -1000=>'L', -1001=>'L', -1002=>'L', -1003=>'L', -1004=>'L', -1005=>'L', -1006=>'L', -1007=>'L', -1008=>'L', -1009=>'L', -1010=>'L', -1011=>'L', -1012=>'L', -1013=>'L', -1014=>'ON', -1015=>'L', -1016=>'L', -1017=>'L', -1018=>'L', -1019=>'L', -1020=>'L', -1021=>'L', -1022=>'L', -1023=>'L', -1024=>'L', -1025=>'L', -1026=>'L', -1027=>'L', -1028=>'L', -1029=>'L', -1030=>'L', -1031=>'L', -1032=>'L', -1033=>'L', -1034=>'L', -1035=>'L', -1036=>'L', -1037=>'L', -1038=>'L', -1039=>'L', -1040=>'L', -1041=>'L', -1042=>'L', -1043=>'L', -1044=>'L', -1045=>'L', -1046=>'L', -1047=>'L', -1048=>'L', -1049=>'L', -1050=>'L', -1051=>'L', -1052=>'L', -1053=>'L', -1054=>'L', -1055=>'L', -1056=>'L', -1057=>'L', -1058=>'L', -1059=>'L', -1060=>'L', -1061=>'L', -1062=>'L', -1063=>'L', -1064=>'L', -1065=>'L', -1066=>'L', -1067=>'L', -1068=>'L', -1069=>'L', -1070=>'L', -1071=>'L', -1072=>'L', -1073=>'L', -1074=>'L', -1075=>'L', -1076=>'L', -1077=>'L', -1078=>'L', -1079=>'L', -1080=>'L', -1081=>'L', -1082=>'L', -1083=>'L', -1084=>'L', -1085=>'L', -1086=>'L', -1087=>'L', -1088=>'L', -1089=>'L', -1090=>'L', -1091=>'L', -1092=>'L', -1093=>'L', -1094=>'L', -1095=>'L', -1096=>'L', -1097=>'L', -1098=>'L', -1099=>'L', -1100=>'L', -1101=>'L', -1102=>'L', -1103=>'L', -1104=>'L', -1105=>'L', -1106=>'L', -1107=>'L', -1108=>'L', -1109=>'L', -1110=>'L', -1111=>'L', -1112=>'L', -1113=>'L', -1114=>'L', -1115=>'L', -1116=>'L', -1117=>'L', -1118=>'L', -1119=>'L', -1120=>'L', -1121=>'L', -1122=>'L', -1123=>'L', -1124=>'L', -1125=>'L', -1126=>'L', -1127=>'L', -1128=>'L', -1129=>'L', -1130=>'L', -1131=>'L', -1132=>'L', -1133=>'L', -1134=>'L', -1135=>'L', -1136=>'L', -1137=>'L', -1138=>'L', -1139=>'L', -1140=>'L', -1141=>'L', -1142=>'L', -1143=>'L', -1144=>'L', -1145=>'L', -1146=>'L', -1147=>'L', -1148=>'L', -1149=>'L', -1150=>'L', -1151=>'L', -1152=>'L', -1153=>'L', -1154=>'L', -1155=>'NSM', -1156=>'NSM', -1157=>'NSM', -1158=>'NSM', -1160=>'NSM', -1161=>'NSM', -1162=>'L', -1163=>'L', -1164=>'L', -1165=>'L', -1166=>'L', -1167=>'L', -1168=>'L', -1169=>'L', -1170=>'L', -1171=>'L', -1172=>'L', -1173=>'L', -1174=>'L', -1175=>'L', -1176=>'L', -1177=>'L', -1178=>'L', -1179=>'L', -1180=>'L', -1181=>'L', -1182=>'L', -1183=>'L', -1184=>'L', -1185=>'L', -1186=>'L', -1187=>'L', -1188=>'L', -1189=>'L', -1190=>'L', -1191=>'L', -1192=>'L', -1193=>'L', -1194=>'L', -1195=>'L', -1196=>'L', -1197=>'L', -1198=>'L', -1199=>'L', -1200=>'L', -1201=>'L', -1202=>'L', -1203=>'L', -1204=>'L', -1205=>'L', -1206=>'L', -1207=>'L', -1208=>'L', -1209=>'L', -1210=>'L', -1211=>'L', -1212=>'L', -1213=>'L', -1214=>'L', -1215=>'L', -1216=>'L', -1217=>'L', -1218=>'L', -1219=>'L', -1220=>'L', -1221=>'L', -1222=>'L', -1223=>'L', -1224=>'L', -1225=>'L', -1226=>'L', -1227=>'L', -1228=>'L', -1229=>'L', -1230=>'L', -1231=>'L', -1232=>'L', -1233=>'L', -1234=>'L', -1235=>'L', -1236=>'L', -1237=>'L', -1238=>'L', -1239=>'L', -1240=>'L', -1241=>'L', -1242=>'L', -1243=>'L', -1244=>'L', -1245=>'L', -1246=>'L', -1247=>'L', -1248=>'L', -1249=>'L', -1250=>'L', -1251=>'L', -1252=>'L', -1253=>'L', -1254=>'L', -1255=>'L', -1256=>'L', -1257=>'L', -1258=>'L', -1259=>'L', -1260=>'L', -1261=>'L', -1262=>'L', -1263=>'L', -1264=>'L', -1265=>'L', -1266=>'L', -1267=>'L', -1268=>'L', -1269=>'L', -1270=>'L', -1271=>'L', -1272=>'L', -1273=>'L', -1274=>'L', -1275=>'L', -1276=>'L', -1277=>'L', -1278=>'L', -1279=>'L', -1280=>'L', -1281=>'L', -1282=>'L', -1283=>'L', -1284=>'L', -1285=>'L', -1286=>'L', -1287=>'L', -1288=>'L', -1289=>'L', -1290=>'L', -1291=>'L', -1292=>'L', -1293=>'L', -1294=>'L', -1295=>'L', -1296=>'L', -1297=>'L', -1298=>'L', -1299=>'L', -1329=>'L', -1330=>'L', -1331=>'L', -1332=>'L', -1333=>'L', -1334=>'L', -1335=>'L', -1336=>'L', -1337=>'L', -1338=>'L', -1339=>'L', -1340=>'L', -1341=>'L', -1342=>'L', -1343=>'L', -1344=>'L', -1345=>'L', -1346=>'L', -1347=>'L', -1348=>'L', -1349=>'L', -1350=>'L', -1351=>'L', -1352=>'L', -1353=>'L', -1354=>'L', -1355=>'L', -1356=>'L', -1357=>'L', -1358=>'L', -1359=>'L', -1360=>'L', -1361=>'L', -1362=>'L', -1363=>'L', -1364=>'L', -1365=>'L', -1366=>'L', -1369=>'L', -1370=>'L', -1371=>'L', -1372=>'L', -1373=>'L', -1374=>'L', -1375=>'L', -1377=>'L', -1378=>'L', -1379=>'L', -1380=>'L', -1381=>'L', -1382=>'L', -1383=>'L', -1384=>'L', -1385=>'L', -1386=>'L', -1387=>'L', -1388=>'L', -1389=>'L', -1390=>'L', -1391=>'L', -1392=>'L', -1393=>'L', -1394=>'L', -1395=>'L', -1396=>'L', -1397=>'L', -1398=>'L', -1399=>'L', -1400=>'L', -1401=>'L', -1402=>'L', -1403=>'L', -1404=>'L', -1405=>'L', -1406=>'L', -1407=>'L', -1408=>'L', -1409=>'L', -1410=>'L', -1411=>'L', -1412=>'L', -1413=>'L', -1414=>'L', -1415=>'L', -1417=>'L', -1418=>'ON', -1425=>'NSM', -1426=>'NSM', -1427=>'NSM', -1428=>'NSM', -1429=>'NSM', -1430=>'NSM', -1431=>'NSM', -1432=>'NSM', -1433=>'NSM', -1434=>'NSM', -1435=>'NSM', -1436=>'NSM', -1437=>'NSM', -1438=>'NSM', -1439=>'NSM', -1440=>'NSM', -1441=>'NSM', -1442=>'NSM', -1443=>'NSM', -1444=>'NSM', -1445=>'NSM', -1446=>'NSM', -1447=>'NSM', -1448=>'NSM', -1449=>'NSM', -1450=>'NSM', -1451=>'NSM', -1452=>'NSM', -1453=>'NSM', -1454=>'NSM', -1455=>'NSM', -1456=>'NSM', -1457=>'NSM', -1458=>'NSM', -1459=>'NSM', -1460=>'NSM', -1461=>'NSM', -1462=>'NSM', -1463=>'NSM', -1464=>'NSM', -1465=>'NSM', -1466=>'NSM', -1467=>'NSM', -1468=>'NSM', -1469=>'NSM', -1470=>'R', -1471=>'NSM', -1472=>'R', -1473=>'NSM', -1474=>'NSM', -1475=>'R', -1476=>'NSM', -1477=>'NSM', -1478=>'R', -1479=>'NSM', -1488=>'R', -1489=>'R', -1490=>'R', -1491=>'R', -1492=>'R', -1493=>'R', -1494=>'R', -1495=>'R', -1496=>'R', -1497=>'R', -1498=>'R', -1499=>'R', -1500=>'R', -1501=>'R', -1502=>'R', -1503=>'R', -1504=>'R', -1505=>'R', -1506=>'R', -1507=>'R', -1508=>'R', -1509=>'R', -1510=>'R', -1511=>'R', -1512=>'R', -1513=>'R', -1514=>'R', -1520=>'R', -1521=>'R', -1522=>'R', -1523=>'R', -1524=>'R', -1536=>'AL', -1537=>'AL', -1538=>'AL', -1539=>'AL', -1547=>'AL', -1548=>'CS', -1549=>'AL', -1550=>'ON', -1551=>'ON', -1552=>'NSM', -1553=>'NSM', -1554=>'NSM', -1555=>'NSM', -1556=>'NSM', -1557=>'NSM', -1563=>'AL', -1566=>'AL', -1567=>'AL', -1569=>'AL', -1570=>'AL', -1571=>'AL', -1572=>'AL', -1573=>'AL', -1574=>'AL', -1575=>'AL', -1576=>'AL', -1577=>'AL', -1578=>'AL', -1579=>'AL', -1580=>'AL', -1581=>'AL', -1582=>'AL', -1583=>'AL', -1584=>'AL', -1585=>'AL', -1586=>'AL', -1587=>'AL', -1588=>'AL', -1589=>'AL', -1590=>'AL', -1591=>'AL', -1592=>'AL', -1593=>'AL', -1594=>'AL', -1600=>'AL', -1601=>'AL', -1602=>'AL', -1603=>'AL', -1604=>'AL', -1605=>'AL', -1606=>'AL', -1607=>'AL', -1608=>'AL', -1609=>'AL', -1610=>'AL', -1611=>'NSM', -1612=>'NSM', -1613=>'NSM', -1614=>'NSM', -1615=>'NSM', -1616=>'NSM', -1617=>'NSM', -1618=>'NSM', -1619=>'NSM', -1620=>'NSM', -1621=>'NSM', -1622=>'NSM', -1623=>'NSM', -1624=>'NSM', -1625=>'NSM', -1626=>'NSM', -1627=>'NSM', -1628=>'NSM', -1629=>'NSM', -1630=>'NSM', -1632=>'AN', -1633=>'AN', -1634=>'AN', -1635=>'AN', -1636=>'AN', -1637=>'AN', -1638=>'AN', -1639=>'AN', -1640=>'AN', -1641=>'AN', -1642=>'ET', -1643=>'AN', -1644=>'AN', -1645=>'AL', -1646=>'AL', -1647=>'AL', -1648=>'NSM', -1649=>'AL', -1650=>'AL', -1651=>'AL', -1652=>'AL', -1653=>'AL', -1654=>'AL', -1655=>'AL', -1656=>'AL', -1657=>'AL', -1658=>'AL', -1659=>'AL', -1660=>'AL', -1661=>'AL', -1662=>'AL', -1663=>'AL', -1664=>'AL', -1665=>'AL', -1666=>'AL', -1667=>'AL', -1668=>'AL', -1669=>'AL', -1670=>'AL', -1671=>'AL', -1672=>'AL', -1673=>'AL', -1674=>'AL', -1675=>'AL', -1676=>'AL', -1677=>'AL', -1678=>'AL', -1679=>'AL', -1680=>'AL', -1681=>'AL', -1682=>'AL', -1683=>'AL', -1684=>'AL', -1685=>'AL', -1686=>'AL', -1687=>'AL', -1688=>'AL', -1689=>'AL', -1690=>'AL', -1691=>'AL', -1692=>'AL', -1693=>'AL', -1694=>'AL', -1695=>'AL', -1696=>'AL', -1697=>'AL', -1698=>'AL', -1699=>'AL', -1700=>'AL', -1701=>'AL', -1702=>'AL', -1703=>'AL', -1704=>'AL', -1705=>'AL', -1706=>'AL', -1707=>'AL', -1708=>'AL', -1709=>'AL', -1710=>'AL', -1711=>'AL', -1712=>'AL', -1713=>'AL', -1714=>'AL', -1715=>'AL', -1716=>'AL', -1717=>'AL', -1718=>'AL', -1719=>'AL', -1720=>'AL', -1721=>'AL', -1722=>'AL', -1723=>'AL', -1724=>'AL', -1725=>'AL', -1726=>'AL', -1727=>'AL', -1728=>'AL', -1729=>'AL', -1730=>'AL', -1731=>'AL', -1732=>'AL', -1733=>'AL', -1734=>'AL', -1735=>'AL', -1736=>'AL', -1737=>'AL', -1738=>'AL', -1739=>'AL', -1740=>'AL', -1741=>'AL', -1742=>'AL', -1743=>'AL', -1744=>'AL', -1745=>'AL', -1746=>'AL', -1747=>'AL', -1748=>'AL', -1749=>'AL', -1750=>'NSM', -1751=>'NSM', -1752=>'NSM', -1753=>'NSM', -1754=>'NSM', -1755=>'NSM', -1756=>'NSM', -1757=>'AL', -1758=>'NSM', -1759=>'NSM', -1760=>'NSM', -1761=>'NSM', -1762=>'NSM', -1763=>'NSM', -1764=>'NSM', -1765=>'AL', -1766=>'AL', -1767=>'NSM', -1768=>'NSM', -1769=>'ON', -1770=>'NSM', -1771=>'NSM', -1772=>'NSM', -1773=>'NSM', -1774=>'AL', -1775=>'AL', -1776=>'EN', -1777=>'EN', -1778=>'EN', -1779=>'EN', -1780=>'EN', -1781=>'EN', -1782=>'EN', -1783=>'EN', -1784=>'EN', -1785=>'EN', -1786=>'AL', -1787=>'AL', -1788=>'AL', -1789=>'AL', -1790=>'AL', -1791=>'AL', -1792=>'AL', -1793=>'AL', -1794=>'AL', -1795=>'AL', -1796=>'AL', -1797=>'AL', -1798=>'AL', -1799=>'AL', -1800=>'AL', -1801=>'AL', -1802=>'AL', -1803=>'AL', -1804=>'AL', -1805=>'AL', -1807=>'BN', -1808=>'AL', -1809=>'NSM', -1810=>'AL', -1811=>'AL', -1812=>'AL', -1813=>'AL', -1814=>'AL', -1815=>'AL', -1816=>'AL', -1817=>'AL', -1818=>'AL', -1819=>'AL', -1820=>'AL', -1821=>'AL', -1822=>'AL', -1823=>'AL', -1824=>'AL', -1825=>'AL', -1826=>'AL', -1827=>'AL', -1828=>'AL', -1829=>'AL', -1830=>'AL', -1831=>'AL', -1832=>'AL', -1833=>'AL', -1834=>'AL', -1835=>'AL', -1836=>'AL', -1837=>'AL', -1838=>'AL', -1839=>'AL', -1840=>'NSM', -1841=>'NSM', -1842=>'NSM', -1843=>'NSM', -1844=>'NSM', -1845=>'NSM', -1846=>'NSM', -1847=>'NSM', -1848=>'NSM', -1849=>'NSM', -1850=>'NSM', -1851=>'NSM', -1852=>'NSM', -1853=>'NSM', -1854=>'NSM', -1855=>'NSM', -1856=>'NSM', -1857=>'NSM', -1858=>'NSM', -1859=>'NSM', -1860=>'NSM', -1861=>'NSM', -1862=>'NSM', -1863=>'NSM', -1864=>'NSM', -1865=>'NSM', -1866=>'NSM', -1869=>'AL', -1870=>'AL', -1871=>'AL', -1872=>'AL', -1873=>'AL', -1874=>'AL', -1875=>'AL', -1876=>'AL', -1877=>'AL', -1878=>'AL', -1879=>'AL', -1880=>'AL', -1881=>'AL', -1882=>'AL', -1883=>'AL', -1884=>'AL', -1885=>'AL', -1886=>'AL', -1887=>'AL', -1888=>'AL', -1889=>'AL', -1890=>'AL', -1891=>'AL', -1892=>'AL', -1893=>'AL', -1894=>'AL', -1895=>'AL', -1896=>'AL', -1897=>'AL', -1898=>'AL', -1899=>'AL', -1900=>'AL', -1901=>'AL', -1920=>'AL', -1921=>'AL', -1922=>'AL', -1923=>'AL', -1924=>'AL', -1925=>'AL', -1926=>'AL', -1927=>'AL', -1928=>'AL', -1929=>'AL', -1930=>'AL', -1931=>'AL', -1932=>'AL', -1933=>'AL', -1934=>'AL', -1935=>'AL', -1936=>'AL', -1937=>'AL', -1938=>'AL', -1939=>'AL', -1940=>'AL', -1941=>'AL', -1942=>'AL', -1943=>'AL', -1944=>'AL', -1945=>'AL', -1946=>'AL', -1947=>'AL', -1948=>'AL', -1949=>'AL', -1950=>'AL', -1951=>'AL', -1952=>'AL', -1953=>'AL', -1954=>'AL', -1955=>'AL', -1956=>'AL', -1957=>'AL', -1958=>'NSM', -1959=>'NSM', -1960=>'NSM', -1961=>'NSM', -1962=>'NSM', -1963=>'NSM', -1964=>'NSM', -1965=>'NSM', -1966=>'NSM', -1967=>'NSM', -1968=>'NSM', -1969=>'AL', -1984=>'R', -1985=>'R', -1986=>'R', -1987=>'R', -1988=>'R', -1989=>'R', -1990=>'R', -1991=>'R', -1992=>'R', -1993=>'R', -1994=>'R', -1995=>'R', -1996=>'R', -1997=>'R', -1998=>'R', -1999=>'R', -2000=>'R', -2001=>'R', -2002=>'R', -2003=>'R', -2004=>'R', -2005=>'R', -2006=>'R', -2007=>'R', -2008=>'R', -2009=>'R', -2010=>'R', -2011=>'R', -2012=>'R', -2013=>'R', -2014=>'R', -2015=>'R', -2016=>'R', -2017=>'R', -2018=>'R', -2019=>'R', -2020=>'R', -2021=>'R', -2022=>'R', -2023=>'R', -2024=>'R', -2025=>'R', -2026=>'R', -2027=>'NSM', -2028=>'NSM', -2029=>'NSM', -2030=>'NSM', -2031=>'NSM', -2032=>'NSM', -2033=>'NSM', -2034=>'NSM', -2035=>'NSM', -2036=>'R', -2037=>'R', -2038=>'ON', -2039=>'ON', -2040=>'ON', -2041=>'ON', -2042=>'R', -2305=>'NSM', -2306=>'NSM', -2307=>'L', -2308=>'L', -2309=>'L', -2310=>'L', -2311=>'L', -2312=>'L', -2313=>'L', -2314=>'L', -2315=>'L', -2316=>'L', -2317=>'L', -2318=>'L', -2319=>'L', -2320=>'L', -2321=>'L', -2322=>'L', -2323=>'L', -2324=>'L', -2325=>'L', -2326=>'L', -2327=>'L', -2328=>'L', -2329=>'L', -2330=>'L', -2331=>'L', -2332=>'L', -2333=>'L', -2334=>'L', -2335=>'L', -2336=>'L', -2337=>'L', -2338=>'L', -2339=>'L', -2340=>'L', -2341=>'L', -2342=>'L', -2343=>'L', -2344=>'L', -2345=>'L', -2346=>'L', -2347=>'L', -2348=>'L', -2349=>'L', -2350=>'L', -2351=>'L', -2352=>'L', -2353=>'L', -2354=>'L', -2355=>'L', -2356=>'L', -2357=>'L', -2358=>'L', -2359=>'L', -2360=>'L', -2361=>'L', -2364=>'NSM', -2365=>'L', -2366=>'L', -2367=>'L', -2368=>'L', -2369=>'NSM', -2370=>'NSM', -2371=>'NSM', -2372=>'NSM', -2373=>'NSM', -2374=>'NSM', -2375=>'NSM', -2376=>'NSM', -2377=>'L', -2378=>'L', -2379=>'L', -2380=>'L', -2381=>'NSM', -2384=>'L', -2385=>'NSM', -2386=>'NSM', -2387=>'NSM', -2388=>'NSM', -2392=>'L', -2393=>'L', -2394=>'L', -2395=>'L', -2396=>'L', -2397=>'L', -2398=>'L', -2399=>'L', -2400=>'L', -2401=>'L', -2402=>'NSM', -2403=>'NSM', -2404=>'L', -2405=>'L', -2406=>'L', -2407=>'L', -2408=>'L', -2409=>'L', -2410=>'L', -2411=>'L', -2412=>'L', -2413=>'L', -2414=>'L', -2415=>'L', -2416=>'L', -2427=>'L', -2428=>'L', -2429=>'L', -2430=>'L', -2431=>'L', -2433=>'NSM', -2434=>'L', -2435=>'L', -2437=>'L', -2438=>'L', -2439=>'L', -2440=>'L', -2441=>'L', -2442=>'L', -2443=>'L', -2444=>'L', -2447=>'L', -2448=>'L', -2451=>'L', -2452=>'L', -2453=>'L', -2454=>'L', -2455=>'L', -2456=>'L', -2457=>'L', -2458=>'L', -2459=>'L', -2460=>'L', -2461=>'L', -2462=>'L', -2463=>'L', -2464=>'L', -2465=>'L', -2466=>'L', -2467=>'L', -2468=>'L', -2469=>'L', -2470=>'L', -2471=>'L', -2472=>'L', -2474=>'L', -2475=>'L', -2476=>'L', -2477=>'L', -2478=>'L', -2479=>'L', -2480=>'L', -2482=>'L', -2486=>'L', -2487=>'L', -2488=>'L', -2489=>'L', -2492=>'NSM', -2493=>'L', -2494=>'L', -2495=>'L', -2496=>'L', -2497=>'NSM', -2498=>'NSM', -2499=>'NSM', -2500=>'NSM', -2503=>'L', -2504=>'L', -2507=>'L', -2508=>'L', -2509=>'NSM', -2510=>'L', -2519=>'L', -2524=>'L', -2525=>'L', -2527=>'L', -2528=>'L', -2529=>'L', -2530=>'NSM', -2531=>'NSM', -2534=>'L', -2535=>'L', -2536=>'L', -2537=>'L', -2538=>'L', -2539=>'L', -2540=>'L', -2541=>'L', -2542=>'L', -2543=>'L', -2544=>'L', -2545=>'L', -2546=>'ET', -2547=>'ET', -2548=>'L', -2549=>'L', -2550=>'L', -2551=>'L', -2552=>'L', -2553=>'L', -2554=>'L', -2561=>'NSM', -2562=>'NSM', -2563=>'L', -2565=>'L', -2566=>'L', -2567=>'L', -2568=>'L', -2569=>'L', -2570=>'L', -2575=>'L', -2576=>'L', -2579=>'L', -2580=>'L', -2581=>'L', -2582=>'L', -2583=>'L', -2584=>'L', -2585=>'L', -2586=>'L', -2587=>'L', -2588=>'L', -2589=>'L', -2590=>'L', -2591=>'L', -2592=>'L', -2593=>'L', -2594=>'L', -2595=>'L', -2596=>'L', -2597=>'L', -2598=>'L', -2599=>'L', -2600=>'L', -2602=>'L', -2603=>'L', -2604=>'L', -2605=>'L', -2606=>'L', -2607=>'L', -2608=>'L', -2610=>'L', -2611=>'L', -2613=>'L', -2614=>'L', -2616=>'L', -2617=>'L', -2620=>'NSM', -2622=>'L', -2623=>'L', -2624=>'L', -2625=>'NSM', -2626=>'NSM', -2631=>'NSM', -2632=>'NSM', -2635=>'NSM', -2636=>'NSM', -2637=>'NSM', -2649=>'L', -2650=>'L', -2651=>'L', -2652=>'L', -2654=>'L', -2662=>'L', -2663=>'L', -2664=>'L', -2665=>'L', -2666=>'L', -2667=>'L', -2668=>'L', -2669=>'L', -2670=>'L', -2671=>'L', -2672=>'NSM', -2673=>'NSM', -2674=>'L', -2675=>'L', -2676=>'L', -2689=>'NSM', -2690=>'NSM', -2691=>'L', -2693=>'L', -2694=>'L', -2695=>'L', -2696=>'L', -2697=>'L', -2698=>'L', -2699=>'L', -2700=>'L', -2701=>'L', -2703=>'L', -2704=>'L', -2705=>'L', -2707=>'L', -2708=>'L', -2709=>'L', -2710=>'L', -2711=>'L', -2712=>'L', -2713=>'L', -2714=>'L', -2715=>'L', -2716=>'L', -2717=>'L', -2718=>'L', -2719=>'L', -2720=>'L', -2721=>'L', -2722=>'L', -2723=>'L', -2724=>'L', -2725=>'L', -2726=>'L', -2727=>'L', -2728=>'L', -2730=>'L', -2731=>'L', -2732=>'L', -2733=>'L', -2734=>'L', -2735=>'L', -2736=>'L', -2738=>'L', -2739=>'L', -2741=>'L', -2742=>'L', -2743=>'L', -2744=>'L', -2745=>'L', -2748=>'NSM', -2749=>'L', -2750=>'L', -2751=>'L', -2752=>'L', -2753=>'NSM', -2754=>'NSM', -2755=>'NSM', -2756=>'NSM', -2757=>'NSM', -2759=>'NSM', -2760=>'NSM', -2761=>'L', -2763=>'L', -2764=>'L', -2765=>'NSM', -2768=>'L', -2784=>'L', -2785=>'L', -2786=>'NSM', -2787=>'NSM', -2790=>'L', -2791=>'L', -2792=>'L', -2793=>'L', -2794=>'L', -2795=>'L', -2796=>'L', -2797=>'L', -2798=>'L', -2799=>'L', -2801=>'ET', -2817=>'NSM', -2818=>'L', -2819=>'L', -2821=>'L', -2822=>'L', -2823=>'L', -2824=>'L', -2825=>'L', -2826=>'L', -2827=>'L', -2828=>'L', -2831=>'L', -2832=>'L', -2835=>'L', -2836=>'L', -2837=>'L', -2838=>'L', -2839=>'L', -2840=>'L', -2841=>'L', -2842=>'L', -2843=>'L', -2844=>'L', -2845=>'L', -2846=>'L', -2847=>'L', -2848=>'L', -2849=>'L', -2850=>'L', -2851=>'L', -2852=>'L', -2853=>'L', -2854=>'L', -2855=>'L', -2856=>'L', -2858=>'L', -2859=>'L', -2860=>'L', -2861=>'L', -2862=>'L', -2863=>'L', -2864=>'L', -2866=>'L', -2867=>'L', -2869=>'L', -2870=>'L', -2871=>'L', -2872=>'L', -2873=>'L', -2876=>'NSM', -2877=>'L', -2878=>'L', -2879=>'NSM', -2880=>'L', -2881=>'NSM', -2882=>'NSM', -2883=>'NSM', -2887=>'L', -2888=>'L', -2891=>'L', -2892=>'L', -2893=>'NSM', -2902=>'NSM', -2903=>'L', -2908=>'L', -2909=>'L', -2911=>'L', -2912=>'L', -2913=>'L', -2918=>'L', -2919=>'L', -2920=>'L', -2921=>'L', -2922=>'L', -2923=>'L', -2924=>'L', -2925=>'L', -2926=>'L', -2927=>'L', -2928=>'L', -2929=>'L', -2946=>'NSM', -2947=>'L', -2949=>'L', -2950=>'L', -2951=>'L', -2952=>'L', -2953=>'L', -2954=>'L', -2958=>'L', -2959=>'L', -2960=>'L', -2962=>'L', -2963=>'L', -2964=>'L', -2965=>'L', -2969=>'L', -2970=>'L', -2972=>'L', -2974=>'L', -2975=>'L', -2979=>'L', -2980=>'L', -2984=>'L', -2985=>'L', -2986=>'L', -2990=>'L', -2991=>'L', -2992=>'L', -2993=>'L', -2994=>'L', -2995=>'L', -2996=>'L', -2997=>'L', -2998=>'L', -2999=>'L', -3000=>'L', -3001=>'L', -3006=>'L', -3007=>'L', -3008=>'NSM', -3009=>'L', -3010=>'L', -3014=>'L', -3015=>'L', -3016=>'L', -3018=>'L', -3019=>'L', -3020=>'L', -3021=>'NSM', -3031=>'L', -3046=>'L', -3047=>'L', -3048=>'L', -3049=>'L', -3050=>'L', -3051=>'L', -3052=>'L', -3053=>'L', -3054=>'L', -3055=>'L', -3056=>'L', -3057=>'L', -3058=>'L', -3059=>'ON', -3060=>'ON', -3061=>'ON', -3062=>'ON', -3063=>'ON', -3064=>'ON', -3065=>'ET', -3066=>'ON', -3073=>'L', -3074=>'L', -3075=>'L', -3077=>'L', -3078=>'L', -3079=>'L', -3080=>'L', -3081=>'L', -3082=>'L', -3083=>'L', -3084=>'L', -3086=>'L', -3087=>'L', -3088=>'L', -3090=>'L', -3091=>'L', -3092=>'L', -3093=>'L', -3094=>'L', -3095=>'L', -3096=>'L', -3097=>'L', -3098=>'L', -3099=>'L', -3100=>'L', -3101=>'L', -3102=>'L', -3103=>'L', -3104=>'L', -3105=>'L', -3106=>'L', -3107=>'L', -3108=>'L', -3109=>'L', -3110=>'L', -3111=>'L', -3112=>'L', -3114=>'L', -3115=>'L', -3116=>'L', -3117=>'L', -3118=>'L', -3119=>'L', -3120=>'L', -3121=>'L', -3122=>'L', -3123=>'L', -3125=>'L', -3126=>'L', -3127=>'L', -3128=>'L', -3129=>'L', -3134=>'NSM', -3135=>'NSM', -3136=>'NSM', -3137=>'L', -3138=>'L', -3139=>'L', -3140=>'L', -3142=>'NSM', -3143=>'NSM', -3144=>'NSM', -3146=>'NSM', -3147=>'NSM', -3148=>'NSM', -3149=>'NSM', -3157=>'NSM', -3158=>'NSM', -3168=>'L', -3169=>'L', -3174=>'L', -3175=>'L', -3176=>'L', -3177=>'L', -3178=>'L', -3179=>'L', -3180=>'L', -3181=>'L', -3182=>'L', -3183=>'L', -3202=>'L', -3203=>'L', -3205=>'L', -3206=>'L', -3207=>'L', -3208=>'L', -3209=>'L', -3210=>'L', -3211=>'L', -3212=>'L', -3214=>'L', -3215=>'L', -3216=>'L', -3218=>'L', -3219=>'L', -3220=>'L', -3221=>'L', -3222=>'L', -3223=>'L', -3224=>'L', -3225=>'L', -3226=>'L', -3227=>'L', -3228=>'L', -3229=>'L', -3230=>'L', -3231=>'L', -3232=>'L', -3233=>'L', -3234=>'L', -3235=>'L', -3236=>'L', -3237=>'L', -3238=>'L', -3239=>'L', -3240=>'L', -3242=>'L', -3243=>'L', -3244=>'L', -3245=>'L', -3246=>'L', -3247=>'L', -3248=>'L', -3249=>'L', -3250=>'L', -3251=>'L', -3253=>'L', -3254=>'L', -3255=>'L', -3256=>'L', -3257=>'L', -3260=>'NSM', -3261=>'L', -3262=>'L', -3263=>'L', -3264=>'L', -3265=>'L', -3266=>'L', -3267=>'L', -3268=>'L', -3270=>'L', -3271=>'L', -3272=>'L', -3274=>'L', -3275=>'L', -3276=>'NSM', -3277=>'NSM', -3285=>'L', -3286=>'L', -3294=>'L', -3296=>'L', -3297=>'L', -3298=>'NSM', -3299=>'NSM', -3302=>'L', -3303=>'L', -3304=>'L', -3305=>'L', -3306=>'L', -3307=>'L', -3308=>'L', -3309=>'L', -3310=>'L', -3311=>'L', -3313=>'ON', -3314=>'ON', -3330=>'L', -3331=>'L', -3333=>'L', -3334=>'L', -3335=>'L', -3336=>'L', -3337=>'L', -3338=>'L', -3339=>'L', -3340=>'L', -3342=>'L', -3343=>'L', -3344=>'L', -3346=>'L', -3347=>'L', -3348=>'L', -3349=>'L', -3350=>'L', -3351=>'L', -3352=>'L', -3353=>'L', -3354=>'L', -3355=>'L', -3356=>'L', -3357=>'L', -3358=>'L', -3359=>'L', -3360=>'L', -3361=>'L', -3362=>'L', -3363=>'L', -3364=>'L', -3365=>'L', -3366=>'L', -3367=>'L', -3368=>'L', -3370=>'L', -3371=>'L', -3372=>'L', -3373=>'L', -3374=>'L', -3375=>'L', -3376=>'L', -3377=>'L', -3378=>'L', -3379=>'L', -3380=>'L', -3381=>'L', -3382=>'L', -3383=>'L', -3384=>'L', -3385=>'L', -3390=>'L', -3391=>'L', -3392=>'L', -3393=>'NSM', -3394=>'NSM', -3395=>'NSM', -3398=>'L', -3399=>'L', -3400=>'L', -3402=>'L', -3403=>'L', -3404=>'L', -3405=>'NSM', -3415=>'L', -3424=>'L', -3425=>'L', -3430=>'L', -3431=>'L', -3432=>'L', -3433=>'L', -3434=>'L', -3435=>'L', -3436=>'L', -3437=>'L', -3438=>'L', -3439=>'L', -3458=>'L', -3459=>'L', -3461=>'L', -3462=>'L', -3463=>'L', -3464=>'L', -3465=>'L', -3466=>'L', -3467=>'L', -3468=>'L', -3469=>'L', -3470=>'L', -3471=>'L', -3472=>'L', -3473=>'L', -3474=>'L', -3475=>'L', -3476=>'L', -3477=>'L', -3478=>'L', -3482=>'L', -3483=>'L', -3484=>'L', -3485=>'L', -3486=>'L', -3487=>'L', -3488=>'L', -3489=>'L', -3490=>'L', -3491=>'L', -3492=>'L', -3493=>'L', -3494=>'L', -3495=>'L', -3496=>'L', -3497=>'L', -3498=>'L', -3499=>'L', -3500=>'L', -3501=>'L', -3502=>'L', -3503=>'L', -3504=>'L', -3505=>'L', -3507=>'L', -3508=>'L', -3509=>'L', -3510=>'L', -3511=>'L', -3512=>'L', -3513=>'L', -3514=>'L', -3515=>'L', -3517=>'L', -3520=>'L', -3521=>'L', -3522=>'L', -3523=>'L', -3524=>'L', -3525=>'L', -3526=>'L', -3530=>'NSM', -3535=>'L', -3536=>'L', -3537=>'L', -3538=>'NSM', -3539=>'NSM', -3540=>'NSM', -3542=>'NSM', -3544=>'L', -3545=>'L', -3546=>'L', -3547=>'L', -3548=>'L', -3549=>'L', -3550=>'L', -3551=>'L', -3570=>'L', -3571=>'L', -3572=>'L', -3585=>'L', -3586=>'L', -3587=>'L', -3588=>'L', -3589=>'L', -3590=>'L', -3591=>'L', -3592=>'L', -3593=>'L', -3594=>'L', -3595=>'L', -3596=>'L', -3597=>'L', -3598=>'L', -3599=>'L', -3600=>'L', -3601=>'L', -3602=>'L', -3603=>'L', -3604=>'L', -3605=>'L', -3606=>'L', -3607=>'L', -3608=>'L', -3609=>'L', -3610=>'L', -3611=>'L', -3612=>'L', -3613=>'L', -3614=>'L', -3615=>'L', -3616=>'L', -3617=>'L', -3618=>'L', -3619=>'L', -3620=>'L', -3621=>'L', -3622=>'L', -3623=>'L', -3624=>'L', -3625=>'L', -3626=>'L', -3627=>'L', -3628=>'L', -3629=>'L', -3630=>'L', -3631=>'L', -3632=>'L', -3633=>'NSM', -3634=>'L', -3635=>'L', -3636=>'NSM', -3637=>'NSM', -3638=>'NSM', -3639=>'NSM', -3640=>'NSM', -3641=>'NSM', -3642=>'NSM', -3647=>'ET', -3648=>'L', -3649=>'L', -3650=>'L', -3651=>'L', -3652=>'L', -3653=>'L', -3654=>'L', -3655=>'NSM', -3656=>'NSM', -3657=>'NSM', -3658=>'NSM', -3659=>'NSM', -3660=>'NSM', -3661=>'NSM', -3662=>'NSM', -3663=>'L', -3664=>'L', -3665=>'L', -3666=>'L', -3667=>'L', -3668=>'L', -3669=>'L', -3670=>'L', -3671=>'L', -3672=>'L', -3673=>'L', -3674=>'L', -3675=>'L', -3713=>'L', -3714=>'L', -3716=>'L', -3719=>'L', -3720=>'L', -3722=>'L', -3725=>'L', -3732=>'L', -3733=>'L', -3734=>'L', -3735=>'L', -3737=>'L', -3738=>'L', -3739=>'L', -3740=>'L', -3741=>'L', -3742=>'L', -3743=>'L', -3745=>'L', -3746=>'L', -3747=>'L', -3749=>'L', -3751=>'L', -3754=>'L', -3755=>'L', -3757=>'L', -3758=>'L', -3759=>'L', -3760=>'L', -3761=>'NSM', -3762=>'L', -3763=>'L', -3764=>'NSM', -3765=>'NSM', -3766=>'NSM', -3767=>'NSM', -3768=>'NSM', -3769=>'NSM', -3771=>'NSM', -3772=>'NSM', -3773=>'L', -3776=>'L', -3777=>'L', -3778=>'L', -3779=>'L', -3780=>'L', -3782=>'L', -3784=>'NSM', -3785=>'NSM', -3786=>'NSM', -3787=>'NSM', -3788=>'NSM', -3789=>'NSM', -3792=>'L', -3793=>'L', -3794=>'L', -3795=>'L', -3796=>'L', -3797=>'L', -3798=>'L', -3799=>'L', -3800=>'L', -3801=>'L', -3804=>'L', -3805=>'L', -3840=>'L', -3841=>'L', -3842=>'L', -3843=>'L', -3844=>'L', -3845=>'L', -3846=>'L', -3847=>'L', -3848=>'L', -3849=>'L', -3850=>'L', -3851=>'L', -3852=>'L', -3853=>'L', -3854=>'L', -3855=>'L', -3856=>'L', -3857=>'L', -3858=>'L', -3859=>'L', -3860=>'L', -3861=>'L', -3862=>'L', -3863=>'L', -3864=>'NSM', -3865=>'NSM', -3866=>'L', -3867=>'L', -3868=>'L', -3869=>'L', -3870=>'L', -3871=>'L', -3872=>'L', -3873=>'L', -3874=>'L', -3875=>'L', -3876=>'L', -3877=>'L', -3878=>'L', -3879=>'L', -3880=>'L', -3881=>'L', -3882=>'L', -3883=>'L', -3884=>'L', -3885=>'L', -3886=>'L', -3887=>'L', -3888=>'L', -3889=>'L', -3890=>'L', -3891=>'L', -3892=>'L', -3893=>'NSM', -3894=>'L', -3895=>'NSM', -3896=>'L', -3897=>'NSM', -3898=>'ON', -3899=>'ON', -3900=>'ON', -3901=>'ON', -3902=>'L', -3903=>'L', -3904=>'L', -3905=>'L', -3906=>'L', -3907=>'L', -3908=>'L', -3909=>'L', -3910=>'L', -3911=>'L', -3913=>'L', -3914=>'L', -3915=>'L', -3916=>'L', -3917=>'L', -3918=>'L', -3919=>'L', -3920=>'L', -3921=>'L', -3922=>'L', -3923=>'L', -3924=>'L', -3925=>'L', -3926=>'L', -3927=>'L', -3928=>'L', -3929=>'L', -3930=>'L', -3931=>'L', -3932=>'L', -3933=>'L', -3934=>'L', -3935=>'L', -3936=>'L', -3937=>'L', -3938=>'L', -3939=>'L', -3940=>'L', -3941=>'L', -3942=>'L', -3943=>'L', -3944=>'L', -3945=>'L', -3946=>'L', -3953=>'NSM', -3954=>'NSM', -3955=>'NSM', -3956=>'NSM', -3957=>'NSM', -3958=>'NSM', -3959=>'NSM', -3960=>'NSM', -3961=>'NSM', -3962=>'NSM', -3963=>'NSM', -3964=>'NSM', -3965=>'NSM', -3966=>'NSM', -3967=>'L', -3968=>'NSM', -3969=>'NSM', -3970=>'NSM', -3971=>'NSM', -3972=>'NSM', -3973=>'L', -3974=>'NSM', -3975=>'NSM', -3976=>'L', -3977=>'L', -3978=>'L', -3979=>'L', -3984=>'NSM', -3985=>'NSM', -3986=>'NSM', -3987=>'NSM', -3988=>'NSM', -3989=>'NSM', -3990=>'NSM', -3991=>'NSM', -3993=>'NSM', -3994=>'NSM', -3995=>'NSM', -3996=>'NSM', -3997=>'NSM', -3998=>'NSM', -3999=>'NSM', -4000=>'NSM', -4001=>'NSM', -4002=>'NSM', -4003=>'NSM', -4004=>'NSM', -4005=>'NSM', -4006=>'NSM', -4007=>'NSM', -4008=>'NSM', -4009=>'NSM', -4010=>'NSM', -4011=>'NSM', -4012=>'NSM', -4013=>'NSM', -4014=>'NSM', -4015=>'NSM', -4016=>'NSM', -4017=>'NSM', -4018=>'NSM', -4019=>'NSM', -4020=>'NSM', -4021=>'NSM', -4022=>'NSM', -4023=>'NSM', -4024=>'NSM', -4025=>'NSM', -4026=>'NSM', -4027=>'NSM', -4028=>'NSM', -4030=>'L', -4031=>'L', -4032=>'L', -4033=>'L', -4034=>'L', -4035=>'L', -4036=>'L', -4037=>'L', -4038=>'NSM', -4039=>'L', -4040=>'L', -4041=>'L', -4042=>'L', -4043=>'L', -4044=>'L', -4047=>'L', -4048=>'L', -4049=>'L', -4096=>'L', -4097=>'L', -4098=>'L', -4099=>'L', -4100=>'L', -4101=>'L', -4102=>'L', -4103=>'L', -4104=>'L', -4105=>'L', -4106=>'L', -4107=>'L', -4108=>'L', -4109=>'L', -4110=>'L', -4111=>'L', -4112=>'L', -4113=>'L', -4114=>'L', -4115=>'L', -4116=>'L', -4117=>'L', -4118=>'L', -4119=>'L', -4120=>'L', -4121=>'L', -4122=>'L', -4123=>'L', -4124=>'L', -4125=>'L', -4126=>'L', -4127=>'L', -4128=>'L', -4129=>'L', -4131=>'L', -4132=>'L', -4133=>'L', -4134=>'L', -4135=>'L', -4137=>'L', -4138=>'L', -4140=>'L', -4141=>'NSM', -4142=>'NSM', -4143=>'NSM', -4144=>'NSM', -4145=>'L', -4146=>'NSM', -4150=>'NSM', -4151=>'NSM', -4152=>'L', -4153=>'NSM', -4160=>'L', -4161=>'L', -4162=>'L', -4163=>'L', -4164=>'L', -4165=>'L', -4166=>'L', -4167=>'L', -4168=>'L', -4169=>'L', -4170=>'L', -4171=>'L', -4172=>'L', -4173=>'L', -4174=>'L', -4175=>'L', -4176=>'L', -4177=>'L', -4178=>'L', -4179=>'L', -4180=>'L', -4181=>'L', -4182=>'L', -4183=>'L', -4184=>'NSM', -4185=>'NSM', -4256=>'L', -4257=>'L', -4258=>'L', -4259=>'L', -4260=>'L', -4261=>'L', -4262=>'L', -4263=>'L', -4264=>'L', -4265=>'L', -4266=>'L', -4267=>'L', -4268=>'L', -4269=>'L', -4270=>'L', -4271=>'L', -4272=>'L', -4273=>'L', -4274=>'L', -4275=>'L', -4276=>'L', -4277=>'L', -4278=>'L', -4279=>'L', -4280=>'L', -4281=>'L', -4282=>'L', -4283=>'L', -4284=>'L', -4285=>'L', -4286=>'L', -4287=>'L', -4288=>'L', -4289=>'L', -4290=>'L', -4291=>'L', -4292=>'L', -4293=>'L', -4304=>'L', -4305=>'L', -4306=>'L', -4307=>'L', -4308=>'L', -4309=>'L', -4310=>'L', -4311=>'L', -4312=>'L', -4313=>'L', -4314=>'L', -4315=>'L', -4316=>'L', -4317=>'L', -4318=>'L', -4319=>'L', -4320=>'L', -4321=>'L', -4322=>'L', -4323=>'L', -4324=>'L', -4325=>'L', -4326=>'L', -4327=>'L', -4328=>'L', -4329=>'L', -4330=>'L', -4331=>'L', -4332=>'L', -4333=>'L', -4334=>'L', -4335=>'L', -4336=>'L', -4337=>'L', -4338=>'L', -4339=>'L', -4340=>'L', -4341=>'L', -4342=>'L', -4343=>'L', -4344=>'L', -4345=>'L', -4346=>'L', -4347=>'L', -4348=>'L', -4352=>'L', -4353=>'L', -4354=>'L', -4355=>'L', -4356=>'L', -4357=>'L', -4358=>'L', -4359=>'L', -4360=>'L', -4361=>'L', -4362=>'L', -4363=>'L', -4364=>'L', -4365=>'L', -4366=>'L', -4367=>'L', -4368=>'L', -4369=>'L', -4370=>'L', -4371=>'L', -4372=>'L', -4373=>'L', -4374=>'L', -4375=>'L', -4376=>'L', -4377=>'L', -4378=>'L', -4379=>'L', -4380=>'L', -4381=>'L', -4382=>'L', -4383=>'L', -4384=>'L', -4385=>'L', -4386=>'L', -4387=>'L', -4388=>'L', -4389=>'L', -4390=>'L', -4391=>'L', -4392=>'L', -4393=>'L', -4394=>'L', -4395=>'L', -4396=>'L', -4397=>'L', -4398=>'L', -4399=>'L', -4400=>'L', -4401=>'L', -4402=>'L', -4403=>'L', -4404=>'L', -4405=>'L', -4406=>'L', -4407=>'L', -4408=>'L', -4409=>'L', -4410=>'L', -4411=>'L', -4412=>'L', -4413=>'L', -4414=>'L', -4415=>'L', -4416=>'L', -4417=>'L', -4418=>'L', -4419=>'L', -4420=>'L', -4421=>'L', -4422=>'L', -4423=>'L', -4424=>'L', -4425=>'L', -4426=>'L', -4427=>'L', -4428=>'L', -4429=>'L', -4430=>'L', -4431=>'L', -4432=>'L', -4433=>'L', -4434=>'L', -4435=>'L', -4436=>'L', -4437=>'L', -4438=>'L', -4439=>'L', -4440=>'L', -4441=>'L', -4447=>'L', -4448=>'L', -4449=>'L', -4450=>'L', -4451=>'L', -4452=>'L', -4453=>'L', -4454=>'L', -4455=>'L', -4456=>'L', -4457=>'L', -4458=>'L', -4459=>'L', -4460=>'L', -4461=>'L', -4462=>'L', -4463=>'L', -4464=>'L', -4465=>'L', -4466=>'L', -4467=>'L', -4468=>'L', -4469=>'L', -4470=>'L', -4471=>'L', -4472=>'L', -4473=>'L', -4474=>'L', -4475=>'L', -4476=>'L', -4477=>'L', -4478=>'L', -4479=>'L', -4480=>'L', -4481=>'L', -4482=>'L', -4483=>'L', -4484=>'L', -4485=>'L', -4486=>'L', -4487=>'L', -4488=>'L', -4489=>'L', -4490=>'L', -4491=>'L', -4492=>'L', -4493=>'L', -4494=>'L', -4495=>'L', -4496=>'L', -4497=>'L', -4498=>'L', -4499=>'L', -4500=>'L', -4501=>'L', -4502=>'L', -4503=>'L', -4504=>'L', -4505=>'L', -4506=>'L', -4507=>'L', -4508=>'L', -4509=>'L', -4510=>'L', -4511=>'L', -4512=>'L', -4513=>'L', -4514=>'L', -4520=>'L', -4521=>'L', -4522=>'L', -4523=>'L', -4524=>'L', -4525=>'L', -4526=>'L', -4527=>'L', -4528=>'L', -4529=>'L', -4530=>'L', -4531=>'L', -4532=>'L', -4533=>'L', -4534=>'L', -4535=>'L', -4536=>'L', -4537=>'L', -4538=>'L', -4539=>'L', -4540=>'L', -4541=>'L', -4542=>'L', -4543=>'L', -4544=>'L', -4545=>'L', -4546=>'L', -4547=>'L', -4548=>'L', -4549=>'L', -4550=>'L', -4551=>'L', -4552=>'L', -4553=>'L', -4554=>'L', -4555=>'L', -4556=>'L', -4557=>'L', -4558=>'L', -4559=>'L', -4560=>'L', -4561=>'L', -4562=>'L', -4563=>'L', -4564=>'L', -4565=>'L', -4566=>'L', -4567=>'L', -4568=>'L', -4569=>'L', -4570=>'L', -4571=>'L', -4572=>'L', -4573=>'L', -4574=>'L', -4575=>'L', -4576=>'L', -4577=>'L', -4578=>'L', -4579=>'L', -4580=>'L', -4581=>'L', -4582=>'L', -4583=>'L', -4584=>'L', -4585=>'L', -4586=>'L', -4587=>'L', -4588=>'L', -4589=>'L', -4590=>'L', -4591=>'L', -4592=>'L', -4593=>'L', -4594=>'L', -4595=>'L', -4596=>'L', -4597=>'L', -4598=>'L', -4599=>'L', -4600=>'L', -4601=>'L', -4608=>'L', -4609=>'L', -4610=>'L', -4611=>'L', -4612=>'L', -4613=>'L', -4614=>'L', -4615=>'L', -4616=>'L', -4617=>'L', -4618=>'L', -4619=>'L', -4620=>'L', -4621=>'L', -4622=>'L', -4623=>'L', -4624=>'L', -4625=>'L', -4626=>'L', -4627=>'L', -4628=>'L', -4629=>'L', -4630=>'L', -4631=>'L', -4632=>'L', -4633=>'L', -4634=>'L', -4635=>'L', -4636=>'L', -4637=>'L', -4638=>'L', -4639=>'L', -4640=>'L', -4641=>'L', -4642=>'L', -4643=>'L', -4644=>'L', -4645=>'L', -4646=>'L', -4647=>'L', -4648=>'L', -4649=>'L', -4650=>'L', -4651=>'L', -4652=>'L', -4653=>'L', -4654=>'L', -4655=>'L', -4656=>'L', -4657=>'L', -4658=>'L', -4659=>'L', -4660=>'L', -4661=>'L', -4662=>'L', -4663=>'L', -4664=>'L', -4665=>'L', -4666=>'L', -4667=>'L', -4668=>'L', -4669=>'L', -4670=>'L', -4671=>'L', -4672=>'L', -4673=>'L', -4674=>'L', -4675=>'L', -4676=>'L', -4677=>'L', -4678=>'L', -4679=>'L', -4680=>'L', -4682=>'L', -4683=>'L', -4684=>'L', -4685=>'L', -4688=>'L', -4689=>'L', -4690=>'L', -4691=>'L', -4692=>'L', -4693=>'L', -4694=>'L', -4696=>'L', -4698=>'L', -4699=>'L', -4700=>'L', -4701=>'L', -4704=>'L', -4705=>'L', -4706=>'L', -4707=>'L', -4708=>'L', -4709=>'L', -4710=>'L', -4711=>'L', -4712=>'L', -4713=>'L', -4714=>'L', -4715=>'L', -4716=>'L', -4717=>'L', -4718=>'L', -4719=>'L', -4720=>'L', -4721=>'L', -4722=>'L', -4723=>'L', -4724=>'L', -4725=>'L', -4726=>'L', -4727=>'L', -4728=>'L', -4729=>'L', -4730=>'L', -4731=>'L', -4732=>'L', -4733=>'L', -4734=>'L', -4735=>'L', -4736=>'L', -4737=>'L', -4738=>'L', -4739=>'L', -4740=>'L', -4741=>'L', -4742=>'L', -4743=>'L', -4744=>'L', -4746=>'L', -4747=>'L', -4748=>'L', -4749=>'L', -4752=>'L', -4753=>'L', -4754=>'L', -4755=>'L', -4756=>'L', -4757=>'L', -4758=>'L', -4759=>'L', -4760=>'L', -4761=>'L', -4762=>'L', -4763=>'L', -4764=>'L', -4765=>'L', -4766=>'L', -4767=>'L', -4768=>'L', -4769=>'L', -4770=>'L', -4771=>'L', -4772=>'L', -4773=>'L', -4774=>'L', -4775=>'L', -4776=>'L', -4777=>'L', -4778=>'L', -4779=>'L', -4780=>'L', -4781=>'L', -4782=>'L', -4783=>'L', -4784=>'L', -4786=>'L', -4787=>'L', -4788=>'L', -4789=>'L', -4792=>'L', -4793=>'L', -4794=>'L', -4795=>'L', -4796=>'L', -4797=>'L', -4798=>'L', -4800=>'L', -4802=>'L', -4803=>'L', -4804=>'L', -4805=>'L', -4808=>'L', -4809=>'L', -4810=>'L', -4811=>'L', -4812=>'L', -4813=>'L', -4814=>'L', -4815=>'L', -4816=>'L', -4817=>'L', -4818=>'L', -4819=>'L', -4820=>'L', -4821=>'L', -4822=>'L', -4824=>'L', -4825=>'L', -4826=>'L', -4827=>'L', -4828=>'L', -4829=>'L', -4830=>'L', -4831=>'L', -4832=>'L', -4833=>'L', -4834=>'L', -4835=>'L', -4836=>'L', -4837=>'L', -4838=>'L', -4839=>'L', -4840=>'L', -4841=>'L', -4842=>'L', -4843=>'L', -4844=>'L', -4845=>'L', -4846=>'L', -4847=>'L', -4848=>'L', -4849=>'L', -4850=>'L', -4851=>'L', -4852=>'L', -4853=>'L', -4854=>'L', -4855=>'L', -4856=>'L', -4857=>'L', -4858=>'L', -4859=>'L', -4860=>'L', -4861=>'L', -4862=>'L', -4863=>'L', -4864=>'L', -4865=>'L', -4866=>'L', -4867=>'L', -4868=>'L', -4869=>'L', -4870=>'L', -4871=>'L', -4872=>'L', -4873=>'L', -4874=>'L', -4875=>'L', -4876=>'L', -4877=>'L', -4878=>'L', -4879=>'L', -4880=>'L', -4882=>'L', -4883=>'L', -4884=>'L', -4885=>'L', -4888=>'L', -4889=>'L', -4890=>'L', -4891=>'L', -4892=>'L', -4893=>'L', -4894=>'L', -4895=>'L', -4896=>'L', -4897=>'L', -4898=>'L', -4899=>'L', -4900=>'L', -4901=>'L', -4902=>'L', -4903=>'L', -4904=>'L', -4905=>'L', -4906=>'L', -4907=>'L', -4908=>'L', -4909=>'L', -4910=>'L', -4911=>'L', -4912=>'L', -4913=>'L', -4914=>'L', -4915=>'L', -4916=>'L', -4917=>'L', -4918=>'L', -4919=>'L', -4920=>'L', -4921=>'L', -4922=>'L', -4923=>'L', -4924=>'L', -4925=>'L', -4926=>'L', -4927=>'L', -4928=>'L', -4929=>'L', -4930=>'L', -4931=>'L', -4932=>'L', -4933=>'L', -4934=>'L', -4935=>'L', -4936=>'L', -4937=>'L', -4938=>'L', -4939=>'L', -4940=>'L', -4941=>'L', -4942=>'L', -4943=>'L', -4944=>'L', -4945=>'L', -4946=>'L', -4947=>'L', -4948=>'L', -4949=>'L', -4950=>'L', -4951=>'L', -4952=>'L', -4953=>'L', -4954=>'L', -4959=>'NSM', -4960=>'L', -4961=>'L', -4962=>'L', -4963=>'L', -4964=>'L', -4965=>'L', -4966=>'L', -4967=>'L', -4968=>'L', -4969=>'L', -4970=>'L', -4971=>'L', -4972=>'L', -4973=>'L', -4974=>'L', -4975=>'L', -4976=>'L', -4977=>'L', -4978=>'L', -4979=>'L', -4980=>'L', -4981=>'L', -4982=>'L', -4983=>'L', -4984=>'L', -4985=>'L', -4986=>'L', -4987=>'L', -4988=>'L', -4992=>'L', -4993=>'L', -4994=>'L', -4995=>'L', -4996=>'L', -4997=>'L', -4998=>'L', -4999=>'L', -5000=>'L', -5001=>'L', -5002=>'L', -5003=>'L', -5004=>'L', -5005=>'L', -5006=>'L', -5007=>'L', -5008=>'ON', -5009=>'ON', -5010=>'ON', -5011=>'ON', -5012=>'ON', -5013=>'ON', -5014=>'ON', -5015=>'ON', -5016=>'ON', -5017=>'ON', -5024=>'L', -5025=>'L', -5026=>'L', -5027=>'L', -5028=>'L', -5029=>'L', -5030=>'L', -5031=>'L', -5032=>'L', -5033=>'L', -5034=>'L', -5035=>'L', -5036=>'L', -5037=>'L', -5038=>'L', -5039=>'L', -5040=>'L', -5041=>'L', -5042=>'L', -5043=>'L', -5044=>'L', -5045=>'L', -5046=>'L', -5047=>'L', -5048=>'L', -5049=>'L', -5050=>'L', -5051=>'L', -5052=>'L', -5053=>'L', -5054=>'L', -5055=>'L', -5056=>'L', -5057=>'L', -5058=>'L', -5059=>'L', -5060=>'L', -5061=>'L', -5062=>'L', -5063=>'L', -5064=>'L', -5065=>'L', -5066=>'L', -5067=>'L', -5068=>'L', -5069=>'L', -5070=>'L', -5071=>'L', -5072=>'L', -5073=>'L', -5074=>'L', -5075=>'L', -5076=>'L', -5077=>'L', -5078=>'L', -5079=>'L', -5080=>'L', -5081=>'L', -5082=>'L', -5083=>'L', -5084=>'L', -5085=>'L', -5086=>'L', -5087=>'L', -5088=>'L', -5089=>'L', -5090=>'L', -5091=>'L', -5092=>'L', -5093=>'L', -5094=>'L', -5095=>'L', -5096=>'L', -5097=>'L', -5098=>'L', -5099=>'L', -5100=>'L', -5101=>'L', -5102=>'L', -5103=>'L', -5104=>'L', -5105=>'L', -5106=>'L', -5107=>'L', -5108=>'L', -5121=>'L', -5122=>'L', -5123=>'L', -5124=>'L', -5125=>'L', -5126=>'L', -5127=>'L', -5128=>'L', -5129=>'L', -5130=>'L', -5131=>'L', -5132=>'L', -5133=>'L', -5134=>'L', -5135=>'L', -5136=>'L', -5137=>'L', -5138=>'L', -5139=>'L', -5140=>'L', -5141=>'L', -5142=>'L', -5143=>'L', -5144=>'L', -5145=>'L', -5146=>'L', -5147=>'L', -5148=>'L', -5149=>'L', -5150=>'L', -5151=>'L', -5152=>'L', -5153=>'L', -5154=>'L', -5155=>'L', -5156=>'L', -5157=>'L', -5158=>'L', -5159=>'L', -5160=>'L', -5161=>'L', -5162=>'L', -5163=>'L', -5164=>'L', -5165=>'L', -5166=>'L', -5167=>'L', -5168=>'L', -5169=>'L', -5170=>'L', -5171=>'L', -5172=>'L', -5173=>'L', -5174=>'L', -5175=>'L', -5176=>'L', -5177=>'L', -5178=>'L', -5179=>'L', -5180=>'L', -5181=>'L', -5182=>'L', -5183=>'L', -5184=>'L', -5185=>'L', -5186=>'L', -5187=>'L', -5188=>'L', -5189=>'L', -5190=>'L', -5191=>'L', -5192=>'L', -5193=>'L', -5194=>'L', -5195=>'L', -5196=>'L', -5197=>'L', -5198=>'L', -5199=>'L', -5200=>'L', -5201=>'L', -5202=>'L', -5203=>'L', -5204=>'L', -5205=>'L', -5206=>'L', -5207=>'L', -5208=>'L', -5209=>'L', -5210=>'L', -5211=>'L', -5212=>'L', -5213=>'L', -5214=>'L', -5215=>'L', -5216=>'L', -5217=>'L', -5218=>'L', -5219=>'L', -5220=>'L', -5221=>'L', -5222=>'L', -5223=>'L', -5224=>'L', -5225=>'L', -5226=>'L', -5227=>'L', -5228=>'L', -5229=>'L', -5230=>'L', -5231=>'L', -5232=>'L', -5233=>'L', -5234=>'L', -5235=>'L', -5236=>'L', -5237=>'L', -5238=>'L', -5239=>'L', -5240=>'L', -5241=>'L', -5242=>'L', -5243=>'L', -5244=>'L', -5245=>'L', -5246=>'L', -5247=>'L', -5248=>'L', -5249=>'L', -5250=>'L', -5251=>'L', -5252=>'L', -5253=>'L', -5254=>'L', -5255=>'L', -5256=>'L', -5257=>'L', -5258=>'L', -5259=>'L', -5260=>'L', -5261=>'L', -5262=>'L', -5263=>'L', -5264=>'L', -5265=>'L', -5266=>'L', -5267=>'L', -5268=>'L', -5269=>'L', -5270=>'L', -5271=>'L', -5272=>'L', -5273=>'L', -5274=>'L', -5275=>'L', -5276=>'L', -5277=>'L', -5278=>'L', -5279=>'L', -5280=>'L', -5281=>'L', -5282=>'L', -5283=>'L', -5284=>'L', -5285=>'L', -5286=>'L', -5287=>'L', -5288=>'L', -5289=>'L', -5290=>'L', -5291=>'L', -5292=>'L', -5293=>'L', -5294=>'L', -5295=>'L', -5296=>'L', -5297=>'L', -5298=>'L', -5299=>'L', -5300=>'L', -5301=>'L', -5302=>'L', -5303=>'L', -5304=>'L', -5305=>'L', -5306=>'L', -5307=>'L', -5308=>'L', -5309=>'L', -5310=>'L', -5311=>'L', -5312=>'L', -5313=>'L', -5314=>'L', -5315=>'L', -5316=>'L', -5317=>'L', -5318=>'L', -5319=>'L', -5320=>'L', -5321=>'L', -5322=>'L', -5323=>'L', -5324=>'L', -5325=>'L', -5326=>'L', -5327=>'L', -5328=>'L', -5329=>'L', -5330=>'L', -5331=>'L', -5332=>'L', -5333=>'L', -5334=>'L', -5335=>'L', -5336=>'L', -5337=>'L', -5338=>'L', -5339=>'L', -5340=>'L', -5341=>'L', -5342=>'L', -5343=>'L', -5344=>'L', -5345=>'L', -5346=>'L', -5347=>'L', -5348=>'L', -5349=>'L', -5350=>'L', -5351=>'L', -5352=>'L', -5353=>'L', -5354=>'L', -5355=>'L', -5356=>'L', -5357=>'L', -5358=>'L', -5359=>'L', -5360=>'L', -5361=>'L', -5362=>'L', -5363=>'L', -5364=>'L', -5365=>'L', -5366=>'L', -5367=>'L', -5368=>'L', -5369=>'L', -5370=>'L', -5371=>'L', -5372=>'L', -5373=>'L', -5374=>'L', -5375=>'L', -5376=>'L', -5377=>'L', -5378=>'L', -5379=>'L', -5380=>'L', -5381=>'L', -5382=>'L', -5383=>'L', -5384=>'L', -5385=>'L', -5386=>'L', -5387=>'L', -5388=>'L', -5389=>'L', -5390=>'L', -5391=>'L', -5392=>'L', -5393=>'L', -5394=>'L', -5395=>'L', -5396=>'L', -5397=>'L', -5398=>'L', -5399=>'L', -5400=>'L', -5401=>'L', -5402=>'L', -5403=>'L', -5404=>'L', -5405=>'L', -5406=>'L', -5407=>'L', -5408=>'L', -5409=>'L', -5410=>'L', -5411=>'L', -5412=>'L', -5413=>'L', -5414=>'L', -5415=>'L', -5416=>'L', -5417=>'L', -5418=>'L', -5419=>'L', -5420=>'L', -5421=>'L', -5422=>'L', -5423=>'L', -5424=>'L', -5425=>'L', -5426=>'L', -5427=>'L', -5428=>'L', -5429=>'L', -5430=>'L', -5431=>'L', -5432=>'L', -5433=>'L', -5434=>'L', -5435=>'L', -5436=>'L', -5437=>'L', -5438=>'L', -5439=>'L', -5440=>'L', -5441=>'L', -5442=>'L', -5443=>'L', -5444=>'L', -5445=>'L', -5446=>'L', -5447=>'L', -5448=>'L', -5449=>'L', -5450=>'L', -5451=>'L', -5452=>'L', -5453=>'L', -5454=>'L', -5455=>'L', -5456=>'L', -5457=>'L', -5458=>'L', -5459=>'L', -5460=>'L', -5461=>'L', -5462=>'L', -5463=>'L', -5464=>'L', -5465=>'L', -5466=>'L', -5467=>'L', -5468=>'L', -5469=>'L', -5470=>'L', -5471=>'L', -5472=>'L', -5473=>'L', -5474=>'L', -5475=>'L', -5476=>'L', -5477=>'L', -5478=>'L', -5479=>'L', -5480=>'L', -5481=>'L', -5482=>'L', -5483=>'L', -5484=>'L', -5485=>'L', -5486=>'L', -5487=>'L', -5488=>'L', -5489=>'L', -5490=>'L', -5491=>'L', -5492=>'L', -5493=>'L', -5494=>'L', -5495=>'L', -5496=>'L', -5497=>'L', -5498=>'L', -5499=>'L', -5500=>'L', -5501=>'L', -5502=>'L', -5503=>'L', -5504=>'L', -5505=>'L', -5506=>'L', -5507=>'L', -5508=>'L', -5509=>'L', -5510=>'L', -5511=>'L', -5512=>'L', -5513=>'L', -5514=>'L', -5515=>'L', -5516=>'L', -5517=>'L', -5518=>'L', -5519=>'L', -5520=>'L', -5521=>'L', -5522=>'L', -5523=>'L', -5524=>'L', -5525=>'L', -5526=>'L', -5527=>'L', -5528=>'L', -5529=>'L', -5530=>'L', -5531=>'L', -5532=>'L', -5533=>'L', -5534=>'L', -5535=>'L', -5536=>'L', -5537=>'L', -5538=>'L', -5539=>'L', -5540=>'L', -5541=>'L', -5542=>'L', -5543=>'L', -5544=>'L', -5545=>'L', -5546=>'L', -5547=>'L', -5548=>'L', -5549=>'L', -5550=>'L', -5551=>'L', -5552=>'L', -5553=>'L', -5554=>'L', -5555=>'L', -5556=>'L', -5557=>'L', -5558=>'L', -5559=>'L', -5560=>'L', -5561=>'L', -5562=>'L', -5563=>'L', -5564=>'L', -5565=>'L', -5566=>'L', -5567=>'L', -5568=>'L', -5569=>'L', -5570=>'L', -5571=>'L', -5572=>'L', -5573=>'L', -5574=>'L', -5575=>'L', -5576=>'L', -5577=>'L', -5578=>'L', -5579=>'L', -5580=>'L', -5581=>'L', -5582=>'L', -5583=>'L', -5584=>'L', -5585=>'L', -5586=>'L', -5587=>'L', -5588=>'L', -5589=>'L', -5590=>'L', -5591=>'L', -5592=>'L', -5593=>'L', -5594=>'L', -5595=>'L', -5596=>'L', -5597=>'L', -5598=>'L', -5599=>'L', -5600=>'L', -5601=>'L', -5602=>'L', -5603=>'L', -5604=>'L', -5605=>'L', -5606=>'L', -5607=>'L', -5608=>'L', -5609=>'L', -5610=>'L', -5611=>'L', -5612=>'L', -5613=>'L', -5614=>'L', -5615=>'L', -5616=>'L', -5617=>'L', -5618=>'L', -5619=>'L', -5620=>'L', -5621=>'L', -5622=>'L', -5623=>'L', -5624=>'L', -5625=>'L', -5626=>'L', -5627=>'L', -5628=>'L', -5629=>'L', -5630=>'L', -5631=>'L', -5632=>'L', -5633=>'L', -5634=>'L', -5635=>'L', -5636=>'L', -5637=>'L', -5638=>'L', -5639=>'L', -5640=>'L', -5641=>'L', -5642=>'L', -5643=>'L', -5644=>'L', -5645=>'L', -5646=>'L', -5647=>'L', -5648=>'L', -5649=>'L', -5650=>'L', -5651=>'L', -5652=>'L', -5653=>'L', -5654=>'L', -5655=>'L', -5656=>'L', -5657=>'L', -5658=>'L', -5659=>'L', -5660=>'L', -5661=>'L', -5662=>'L', -5663=>'L', -5664=>'L', -5665=>'L', -5666=>'L', -5667=>'L', -5668=>'L', -5669=>'L', -5670=>'L', -5671=>'L', -5672=>'L', -5673=>'L', -5674=>'L', -5675=>'L', -5676=>'L', -5677=>'L', -5678=>'L', -5679=>'L', -5680=>'L', -5681=>'L', -5682=>'L', -5683=>'L', -5684=>'L', -5685=>'L', -5686=>'L', -5687=>'L', -5688=>'L', -5689=>'L', -5690=>'L', -5691=>'L', -5692=>'L', -5693=>'L', -5694=>'L', -5695=>'L', -5696=>'L', -5697=>'L', -5698=>'L', -5699=>'L', -5700=>'L', -5701=>'L', -5702=>'L', -5703=>'L', -5704=>'L', -5705=>'L', -5706=>'L', -5707=>'L', -5708=>'L', -5709=>'L', -5710=>'L', -5711=>'L', -5712=>'L', -5713=>'L', -5714=>'L', -5715=>'L', -5716=>'L', -5717=>'L', -5718=>'L', -5719=>'L', -5720=>'L', -5721=>'L', -5722=>'L', -5723=>'L', -5724=>'L', -5725=>'L', -5726=>'L', -5727=>'L', -5728=>'L', -5729=>'L', -5730=>'L', -5731=>'L', -5732=>'L', -5733=>'L', -5734=>'L', -5735=>'L', -5736=>'L', -5737=>'L', -5738=>'L', -5739=>'L', -5740=>'L', -5741=>'L', -5742=>'L', -5743=>'L', -5744=>'L', -5745=>'L', -5746=>'L', -5747=>'L', -5748=>'L', -5749=>'L', -5750=>'L', -5760=>'WS', -5761=>'L', -5762=>'L', -5763=>'L', -5764=>'L', -5765=>'L', -5766=>'L', -5767=>'L', -5768=>'L', -5769=>'L', -5770=>'L', -5771=>'L', -5772=>'L', -5773=>'L', -5774=>'L', -5775=>'L', -5776=>'L', -5777=>'L', -5778=>'L', -5779=>'L', -5780=>'L', -5781=>'L', -5782=>'L', -5783=>'L', -5784=>'L', -5785=>'L', -5786=>'L', -5787=>'ON', -5788=>'ON', -5792=>'L', -5793=>'L', -5794=>'L', -5795=>'L', -5796=>'L', -5797=>'L', -5798=>'L', -5799=>'L', -5800=>'L', -5801=>'L', -5802=>'L', -5803=>'L', -5804=>'L', -5805=>'L', -5806=>'L', -5807=>'L', -5808=>'L', -5809=>'L', -5810=>'L', -5811=>'L', -5812=>'L', -5813=>'L', -5814=>'L', -5815=>'L', -5816=>'L', -5817=>'L', -5818=>'L', -5819=>'L', -5820=>'L', -5821=>'L', -5822=>'L', -5823=>'L', -5824=>'L', -5825=>'L', -5826=>'L', -5827=>'L', -5828=>'L', -5829=>'L', -5830=>'L', -5831=>'L', -5832=>'L', -5833=>'L', -5834=>'L', -5835=>'L', -5836=>'L', -5837=>'L', -5838=>'L', -5839=>'L', -5840=>'L', -5841=>'L', -5842=>'L', -5843=>'L', -5844=>'L', -5845=>'L', -5846=>'L', -5847=>'L', -5848=>'L', -5849=>'L', -5850=>'L', -5851=>'L', -5852=>'L', -5853=>'L', -5854=>'L', -5855=>'L', -5856=>'L', -5857=>'L', -5858=>'L', -5859=>'L', -5860=>'L', -5861=>'L', -5862=>'L', -5863=>'L', -5864=>'L', -5865=>'L', -5866=>'L', -5867=>'L', -5868=>'L', -5869=>'L', -5870=>'L', -5871=>'L', -5872=>'L', -5888=>'L', -5889=>'L', -5890=>'L', -5891=>'L', -5892=>'L', -5893=>'L', -5894=>'L', -5895=>'L', -5896=>'L', -5897=>'L', -5898=>'L', -5899=>'L', -5900=>'L', -5902=>'L', -5903=>'L', -5904=>'L', -5905=>'L', -5906=>'NSM', -5907=>'NSM', -5908=>'NSM', -5920=>'L', -5921=>'L', -5922=>'L', -5923=>'L', -5924=>'L', -5925=>'L', -5926=>'L', -5927=>'L', -5928=>'L', -5929=>'L', -5930=>'L', -5931=>'L', -5932=>'L', -5933=>'L', -5934=>'L', -5935=>'L', -5936=>'L', -5937=>'L', -5938=>'NSM', -5939=>'NSM', -5940=>'NSM', -5941=>'L', -5942=>'L', -5952=>'L', -5953=>'L', -5954=>'L', -5955=>'L', -5956=>'L', -5957=>'L', -5958=>'L', -5959=>'L', -5960=>'L', -5961=>'L', -5962=>'L', -5963=>'L', -5964=>'L', -5965=>'L', -5966=>'L', -5967=>'L', -5968=>'L', -5969=>'L', -5970=>'NSM', -5971=>'NSM', -5984=>'L', -5985=>'L', -5986=>'L', -5987=>'L', -5988=>'L', -5989=>'L', -5990=>'L', -5991=>'L', -5992=>'L', -5993=>'L', -5994=>'L', -5995=>'L', -5996=>'L', -5998=>'L', -5999=>'L', -6000=>'L', -6002=>'NSM', -6003=>'NSM', -6016=>'L', -6017=>'L', -6018=>'L', -6019=>'L', -6020=>'L', -6021=>'L', -6022=>'L', -6023=>'L', -6024=>'L', -6025=>'L', -6026=>'L', -6027=>'L', -6028=>'L', -6029=>'L', -6030=>'L', -6031=>'L', -6032=>'L', -6033=>'L', -6034=>'L', -6035=>'L', -6036=>'L', -6037=>'L', -6038=>'L', -6039=>'L', -6040=>'L', -6041=>'L', -6042=>'L', -6043=>'L', -6044=>'L', -6045=>'L', -6046=>'L', -6047=>'L', -6048=>'L', -6049=>'L', -6050=>'L', -6051=>'L', -6052=>'L', -6053=>'L', -6054=>'L', -6055=>'L', -6056=>'L', -6057=>'L', -6058=>'L', -6059=>'L', -6060=>'L', -6061=>'L', -6062=>'L', -6063=>'L', -6064=>'L', -6065=>'L', -6066=>'L', -6067=>'L', -6068=>'L', -6069=>'L', -6070=>'L', -6071=>'NSM', -6072=>'NSM', -6073=>'NSM', -6074=>'NSM', -6075=>'NSM', -6076=>'NSM', -6077=>'NSM', -6078=>'L', -6079=>'L', -6080=>'L', -6081=>'L', -6082=>'L', -6083=>'L', -6084=>'L', -6085=>'L', -6086=>'NSM', -6087=>'L', -6088=>'L', -6089=>'NSM', -6090=>'NSM', -6091=>'NSM', -6092=>'NSM', -6093=>'NSM', -6094=>'NSM', -6095=>'NSM', -6096=>'NSM', -6097=>'NSM', -6098=>'NSM', -6099=>'NSM', -6100=>'L', -6101=>'L', -6102=>'L', -6103=>'L', -6104=>'L', -6105=>'L', -6106=>'L', -6107=>'ET', -6108=>'L', -6109=>'NSM', -6112=>'L', -6113=>'L', -6114=>'L', -6115=>'L', -6116=>'L', -6117=>'L', -6118=>'L', -6119=>'L', -6120=>'L', -6121=>'L', -6128=>'ON', -6129=>'ON', -6130=>'ON', -6131=>'ON', -6132=>'ON', -6133=>'ON', -6134=>'ON', -6135=>'ON', -6136=>'ON', -6137=>'ON', -6144=>'ON', -6145=>'ON', -6146=>'ON', -6147=>'ON', -6148=>'ON', -6149=>'ON', -6150=>'ON', -6151=>'ON', -6152=>'ON', -6153=>'ON', -6154=>'ON', -6155=>'NSM', -6156=>'NSM', -6157=>'NSM', -6158=>'WS', -6160=>'L', -6161=>'L', -6162=>'L', -6163=>'L', -6164=>'L', -6165=>'L', -6166=>'L', -6167=>'L', -6168=>'L', -6169=>'L', -6176=>'L', -6177=>'L', -6178=>'L', -6179=>'L', -6180=>'L', -6181=>'L', -6182=>'L', -6183=>'L', -6184=>'L', -6185=>'L', -6186=>'L', -6187=>'L', -6188=>'L', -6189=>'L', -6190=>'L', -6191=>'L', -6192=>'L', -6193=>'L', -6194=>'L', -6195=>'L', -6196=>'L', -6197=>'L', -6198=>'L', -6199=>'L', -6200=>'L', -6201=>'L', -6202=>'L', -6203=>'L', -6204=>'L', -6205=>'L', -6206=>'L', -6207=>'L', -6208=>'L', -6209=>'L', -6210=>'L', -6211=>'L', -6212=>'L', -6213=>'L', -6214=>'L', -6215=>'L', -6216=>'L', -6217=>'L', -6218=>'L', -6219=>'L', -6220=>'L', -6221=>'L', -6222=>'L', -6223=>'L', -6224=>'L', -6225=>'L', -6226=>'L', -6227=>'L', -6228=>'L', -6229=>'L', -6230=>'L', -6231=>'L', -6232=>'L', -6233=>'L', -6234=>'L', -6235=>'L', -6236=>'L', -6237=>'L', -6238=>'L', -6239=>'L', -6240=>'L', -6241=>'L', -6242=>'L', -6243=>'L', -6244=>'L', -6245=>'L', -6246=>'L', -6247=>'L', -6248=>'L', -6249=>'L', -6250=>'L', -6251=>'L', -6252=>'L', -6253=>'L', -6254=>'L', -6255=>'L', -6256=>'L', -6257=>'L', -6258=>'L', -6259=>'L', -6260=>'L', -6261=>'L', -6262=>'L', -6263=>'L', -6272=>'L', -6273=>'L', -6274=>'L', -6275=>'L', -6276=>'L', -6277=>'L', -6278=>'L', -6279=>'L', -6280=>'L', -6281=>'L', -6282=>'L', -6283=>'L', -6284=>'L', -6285=>'L', -6286=>'L', -6287=>'L', -6288=>'L', -6289=>'L', -6290=>'L', -6291=>'L', -6292=>'L', -6293=>'L', -6294=>'L', -6295=>'L', -6296=>'L', -6297=>'L', -6298=>'L', -6299=>'L', -6300=>'L', -6301=>'L', -6302=>'L', -6303=>'L', -6304=>'L', -6305=>'L', -6306=>'L', -6307=>'L', -6308=>'L', -6309=>'L', -6310=>'L', -6311=>'L', -6312=>'L', -6313=>'NSM', -6400=>'L', -6401=>'L', -6402=>'L', -6403=>'L', -6404=>'L', -6405=>'L', -6406=>'L', -6407=>'L', -6408=>'L', -6409=>'L', -6410=>'L', -6411=>'L', -6412=>'L', -6413=>'L', -6414=>'L', -6415=>'L', -6416=>'L', -6417=>'L', -6418=>'L', -6419=>'L', -6420=>'L', -6421=>'L', -6422=>'L', -6423=>'L', -6424=>'L', -6425=>'L', -6426=>'L', -6427=>'L', -6428=>'L', -6432=>'NSM', -6433=>'NSM', -6434=>'NSM', -6435=>'L', -6436=>'L', -6437=>'L', -6438=>'L', -6439=>'NSM', -6440=>'NSM', -6441=>'NSM', -6442=>'NSM', -6443=>'NSM', -6448=>'L', -6449=>'L', -6450=>'NSM', -6451=>'L', -6452=>'L', -6453=>'L', -6454=>'L', -6455=>'L', -6456=>'L', -6457=>'NSM', -6458=>'NSM', -6459=>'NSM', -6464=>'ON', -6468=>'ON', -6469=>'ON', -6470=>'L', -6471=>'L', -6472=>'L', -6473=>'L', -6474=>'L', -6475=>'L', -6476=>'L', -6477=>'L', -6478=>'L', -6479=>'L', -6480=>'L', -6481=>'L', -6482=>'L', -6483=>'L', -6484=>'L', -6485=>'L', -6486=>'L', -6487=>'L', -6488=>'L', -6489=>'L', -6490=>'L', -6491=>'L', -6492=>'L', -6493=>'L', -6494=>'L', -6495=>'L', -6496=>'L', -6497=>'L', -6498=>'L', -6499=>'L', -6500=>'L', -6501=>'L', -6502=>'L', -6503=>'L', -6504=>'L', -6505=>'L', -6506=>'L', -6507=>'L', -6508=>'L', -6509=>'L', -6512=>'L', -6513=>'L', -6514=>'L', -6515=>'L', -6516=>'L', -6528=>'L', -6529=>'L', -6530=>'L', -6531=>'L', -6532=>'L', -6533=>'L', -6534=>'L', -6535=>'L', -6536=>'L', -6537=>'L', -6538=>'L', -6539=>'L', -6540=>'L', -6541=>'L', -6542=>'L', -6543=>'L', -6544=>'L', -6545=>'L', -6546=>'L', -6547=>'L', -6548=>'L', -6549=>'L', -6550=>'L', -6551=>'L', -6552=>'L', -6553=>'L', -6554=>'L', -6555=>'L', -6556=>'L', -6557=>'L', -6558=>'L', -6559=>'L', -6560=>'L', -6561=>'L', -6562=>'L', -6563=>'L', -6564=>'L', -6565=>'L', -6566=>'L', -6567=>'L', -6568=>'L', -6569=>'L', -6576=>'L', -6577=>'L', -6578=>'L', -6579=>'L', -6580=>'L', -6581=>'L', -6582=>'L', -6583=>'L', -6584=>'L', -6585=>'L', -6586=>'L', -6587=>'L', -6588=>'L', -6589=>'L', -6590=>'L', -6591=>'L', -6592=>'L', -6593=>'L', -6594=>'L', -6595=>'L', -6596=>'L', -6597=>'L', -6598=>'L', -6599=>'L', -6600=>'L', -6601=>'L', -6608=>'L', -6609=>'L', -6610=>'L', -6611=>'L', -6612=>'L', -6613=>'L', -6614=>'L', -6615=>'L', -6616=>'L', -6617=>'L', -6622=>'ON', -6623=>'ON', -6624=>'ON', -6625=>'ON', -6626=>'ON', -6627=>'ON', -6628=>'ON', -6629=>'ON', -6630=>'ON', -6631=>'ON', -6632=>'ON', -6633=>'ON', -6634=>'ON', -6635=>'ON', -6636=>'ON', -6637=>'ON', -6638=>'ON', -6639=>'ON', -6640=>'ON', -6641=>'ON', -6642=>'ON', -6643=>'ON', -6644=>'ON', -6645=>'ON', -6646=>'ON', -6647=>'ON', -6648=>'ON', -6649=>'ON', -6650=>'ON', -6651=>'ON', -6652=>'ON', -6653=>'ON', -6654=>'ON', -6655=>'ON', -6656=>'L', -6657=>'L', -6658=>'L', -6659=>'L', -6660=>'L', -6661=>'L', -6662=>'L', -6663=>'L', -6664=>'L', -6665=>'L', -6666=>'L', -6667=>'L', -6668=>'L', -6669=>'L', -6670=>'L', -6671=>'L', -6672=>'L', -6673=>'L', -6674=>'L', -6675=>'L', -6676=>'L', -6677=>'L', -6678=>'L', -6679=>'NSM', -6680=>'NSM', -6681=>'L', -6682=>'L', -6683=>'L', -6686=>'L', -6687=>'L', -6912=>'NSM', -6913=>'NSM', -6914=>'NSM', -6915=>'NSM', -6916=>'L', -6917=>'L', -6918=>'L', -6919=>'L', -6920=>'L', -6921=>'L', -6922=>'L', -6923=>'L', -6924=>'L', -6925=>'L', -6926=>'L', -6927=>'L', -6928=>'L', -6929=>'L', -6930=>'L', -6931=>'L', -6932=>'L', -6933=>'L', -6934=>'L', -6935=>'L', -6936=>'L', -6937=>'L', -6938=>'L', -6939=>'L', -6940=>'L', -6941=>'L', -6942=>'L', -6943=>'L', -6944=>'L', -6945=>'L', -6946=>'L', -6947=>'L', -6948=>'L', -6949=>'L', -6950=>'L', -6951=>'L', -6952=>'L', -6953=>'L', -6954=>'L', -6955=>'L', -6956=>'L', -6957=>'L', -6958=>'L', -6959=>'L', -6960=>'L', -6961=>'L', -6962=>'L', -6963=>'L', -6964=>'NSM', -6965=>'L', -6966=>'NSM', -6967=>'NSM', -6968=>'NSM', -6969=>'NSM', -6970=>'NSM', -6971=>'L', -6972=>'NSM', -6973=>'L', -6974=>'L', -6975=>'L', -6976=>'L', -6977=>'L', -6978=>'NSM', -6979=>'L', -6980=>'L', -6981=>'L', -6982=>'L', -6983=>'L', -6984=>'L', -6985=>'L', -6986=>'L', -6987=>'L', -6992=>'L', -6993=>'L', -6994=>'L', -6995=>'L', -6996=>'L', -6997=>'L', -6998=>'L', -6999=>'L', -7000=>'L', -7001=>'L', -7002=>'L', -7003=>'L', -7004=>'L', -7005=>'L', -7006=>'L', -7007=>'L', -7008=>'L', -7009=>'L', -7010=>'L', -7011=>'L', -7012=>'L', -7013=>'L', -7014=>'L', -7015=>'L', -7016=>'L', -7017=>'L', -7018=>'L', -7019=>'NSM', -7020=>'NSM', -7021=>'NSM', -7022=>'NSM', -7023=>'NSM', -7024=>'NSM', -7025=>'NSM', -7026=>'NSM', -7027=>'NSM', -7028=>'L', -7029=>'L', -7030=>'L', -7031=>'L', -7032=>'L', -7033=>'L', -7034=>'L', -7035=>'L', -7036=>'L', -7424=>'L', -7425=>'L', -7426=>'L', -7427=>'L', -7428=>'L', -7429=>'L', -7430=>'L', -7431=>'L', -7432=>'L', -7433=>'L', -7434=>'L', -7435=>'L', -7436=>'L', -7437=>'L', -7438=>'L', -7439=>'L', -7440=>'L', -7441=>'L', -7442=>'L', -7443=>'L', -7444=>'L', -7445=>'L', -7446=>'L', -7447=>'L', -7448=>'L', -7449=>'L', -7450=>'L', -7451=>'L', -7452=>'L', -7453=>'L', -7454=>'L', -7455=>'L', -7456=>'L', -7457=>'L', -7458=>'L', -7459=>'L', -7460=>'L', -7461=>'L', -7462=>'L', -7463=>'L', -7464=>'L', -7465=>'L', -7466=>'L', -7467=>'L', -7468=>'L', -7469=>'L', -7470=>'L', -7471=>'L', -7472=>'L', -7473=>'L', -7474=>'L', -7475=>'L', -7476=>'L', -7477=>'L', -7478=>'L', -7479=>'L', -7480=>'L', -7481=>'L', -7482=>'L', -7483=>'L', -7484=>'L', -7485=>'L', -7486=>'L', -7487=>'L', -7488=>'L', -7489=>'L', -7490=>'L', -7491=>'L', -7492=>'L', -7493=>'L', -7494=>'L', -7495=>'L', -7496=>'L', -7497=>'L', -7498=>'L', -7499=>'L', -7500=>'L', -7501=>'L', -7502=>'L', -7503=>'L', -7504=>'L', -7505=>'L', -7506=>'L', -7507=>'L', -7508=>'L', -7509=>'L', -7510=>'L', -7511=>'L', -7512=>'L', -7513=>'L', -7514=>'L', -7515=>'L', -7516=>'L', -7517=>'L', -7518=>'L', -7519=>'L', -7520=>'L', -7521=>'L', -7522=>'L', -7523=>'L', -7524=>'L', -7525=>'L', -7526=>'L', -7527=>'L', -7528=>'L', -7529=>'L', -7530=>'L', -7531=>'L', -7532=>'L', -7533=>'L', -7534=>'L', -7535=>'L', -7536=>'L', -7537=>'L', -7538=>'L', -7539=>'L', -7540=>'L', -7541=>'L', -7542=>'L', -7543=>'L', -7544=>'L', -7545=>'L', -7546=>'L', -7547=>'L', -7548=>'L', -7549=>'L', -7550=>'L', -7551=>'L', -7552=>'L', -7553=>'L', -7554=>'L', -7555=>'L', -7556=>'L', -7557=>'L', -7558=>'L', -7559=>'L', -7560=>'L', -7561=>'L', -7562=>'L', -7563=>'L', -7564=>'L', -7565=>'L', -7566=>'L', -7567=>'L', -7568=>'L', -7569=>'L', -7570=>'L', -7571=>'L', -7572=>'L', -7573=>'L', -7574=>'L', -7575=>'L', -7576=>'L', -7577=>'L', -7578=>'L', -7579=>'L', -7580=>'L', -7581=>'L', -7582=>'L', -7583=>'L', -7584=>'L', -7585=>'L', -7586=>'L', -7587=>'L', -7588=>'L', -7589=>'L', -7590=>'L', -7591=>'L', -7592=>'L', -7593=>'L', -7594=>'L', -7595=>'L', -7596=>'L', -7597=>'L', -7598=>'L', -7599=>'L', -7600=>'L', -7601=>'L', -7602=>'L', -7603=>'L', -7604=>'L', -7605=>'L', -7606=>'L', -7607=>'L', -7608=>'L', -7609=>'L', -7610=>'L', -7611=>'L', -7612=>'L', -7613=>'L', -7614=>'L', -7615=>'L', -7616=>'NSM', -7617=>'NSM', -7618=>'NSM', -7619=>'NSM', -7620=>'NSM', -7621=>'NSM', -7622=>'NSM', -7623=>'NSM', -7624=>'NSM', -7625=>'NSM', -7626=>'NSM', -7678=>'NSM', -7679=>'NSM', -7680=>'L', -7681=>'L', -7682=>'L', -7683=>'L', -7684=>'L', -7685=>'L', -7686=>'L', -7687=>'L', -7688=>'L', -7689=>'L', -7690=>'L', -7691=>'L', -7692=>'L', -7693=>'L', -7694=>'L', -7695=>'L', -7696=>'L', -7697=>'L', -7698=>'L', -7699=>'L', -7700=>'L', -7701=>'L', -7702=>'L', -7703=>'L', -7704=>'L', -7705=>'L', -7706=>'L', -7707=>'L', -7708=>'L', -7709=>'L', -7710=>'L', -7711=>'L', -7712=>'L', -7713=>'L', -7714=>'L', -7715=>'L', -7716=>'L', -7717=>'L', -7718=>'L', -7719=>'L', -7720=>'L', -7721=>'L', -7722=>'L', -7723=>'L', -7724=>'L', -7725=>'L', -7726=>'L', -7727=>'L', -7728=>'L', -7729=>'L', -7730=>'L', -7731=>'L', -7732=>'L', -7733=>'L', -7734=>'L', -7735=>'L', -7736=>'L', -7737=>'L', -7738=>'L', -7739=>'L', -7740=>'L', -7741=>'L', -7742=>'L', -7743=>'L', -7744=>'L', -7745=>'L', -7746=>'L', -7747=>'L', -7748=>'L', -7749=>'L', -7750=>'L', -7751=>'L', -7752=>'L', -7753=>'L', -7754=>'L', -7755=>'L', -7756=>'L', -7757=>'L', -7758=>'L', -7759=>'L', -7760=>'L', -7761=>'L', -7762=>'L', -7763=>'L', -7764=>'L', -7765=>'L', -7766=>'L', -7767=>'L', -7768=>'L', -7769=>'L', -7770=>'L', -7771=>'L', -7772=>'L', -7773=>'L', -7774=>'L', -7775=>'L', -7776=>'L', -7777=>'L', -7778=>'L', -7779=>'L', -7780=>'L', -7781=>'L', -7782=>'L', -7783=>'L', -7784=>'L', -7785=>'L', -7786=>'L', -7787=>'L', -7788=>'L', -7789=>'L', -7790=>'L', -7791=>'L', -7792=>'L', -7793=>'L', -7794=>'L', -7795=>'L', -7796=>'L', -7797=>'L', -7798=>'L', -7799=>'L', -7800=>'L', -7801=>'L', -7802=>'L', -7803=>'L', -7804=>'L', -7805=>'L', -7806=>'L', -7807=>'L', -7808=>'L', -7809=>'L', -7810=>'L', -7811=>'L', -7812=>'L', -7813=>'L', -7814=>'L', -7815=>'L', -7816=>'L', -7817=>'L', -7818=>'L', -7819=>'L', -7820=>'L', -7821=>'L', -7822=>'L', -7823=>'L', -7824=>'L', -7825=>'L', -7826=>'L', -7827=>'L', -7828=>'L', -7829=>'L', -7830=>'L', -7831=>'L', -7832=>'L', -7833=>'L', -7834=>'L', -7835=>'L', -7840=>'L', -7841=>'L', -7842=>'L', -7843=>'L', -7844=>'L', -7845=>'L', -7846=>'L', -7847=>'L', -7848=>'L', -7849=>'L', -7850=>'L', -7851=>'L', -7852=>'L', -7853=>'L', -7854=>'L', -7855=>'L', -7856=>'L', -7857=>'L', -7858=>'L', -7859=>'L', -7860=>'L', -7861=>'L', -7862=>'L', -7863=>'L', -7864=>'L', -7865=>'L', -7866=>'L', -7867=>'L', -7868=>'L', -7869=>'L', -7870=>'L', -7871=>'L', -7872=>'L', -7873=>'L', -7874=>'L', -7875=>'L', -7876=>'L', -7877=>'L', -7878=>'L', -7879=>'L', -7880=>'L', -7881=>'L', -7882=>'L', -7883=>'L', -7884=>'L', -7885=>'L', -7886=>'L', -7887=>'L', -7888=>'L', -7889=>'L', -7890=>'L', -7891=>'L', -7892=>'L', -7893=>'L', -7894=>'L', -7895=>'L', -7896=>'L', -7897=>'L', -7898=>'L', -7899=>'L', -7900=>'L', -7901=>'L', -7902=>'L', -7903=>'L', -7904=>'L', -7905=>'L', -7906=>'L', -7907=>'L', -7908=>'L', -7909=>'L', -7910=>'L', -7911=>'L', -7912=>'L', -7913=>'L', -7914=>'L', -7915=>'L', -7916=>'L', -7917=>'L', -7918=>'L', -7919=>'L', -7920=>'L', -7921=>'L', -7922=>'L', -7923=>'L', -7924=>'L', -7925=>'L', -7926=>'L', -7927=>'L', -7928=>'L', -7929=>'L', -7936=>'L', -7937=>'L', -7938=>'L', -7939=>'L', -7940=>'L', -7941=>'L', -7942=>'L', -7943=>'L', -7944=>'L', -7945=>'L', -7946=>'L', -7947=>'L', -7948=>'L', -7949=>'L', -7950=>'L', -7951=>'L', -7952=>'L', -7953=>'L', -7954=>'L', -7955=>'L', -7956=>'L', -7957=>'L', -7960=>'L', -7961=>'L', -7962=>'L', -7963=>'L', -7964=>'L', -7965=>'L', -7968=>'L', -7969=>'L', -7970=>'L', -7971=>'L', -7972=>'L', -7973=>'L', -7974=>'L', -7975=>'L', -7976=>'L', -7977=>'L', -7978=>'L', -7979=>'L', -7980=>'L', -7981=>'L', -7982=>'L', -7983=>'L', -7984=>'L', -7985=>'L', -7986=>'L', -7987=>'L', -7988=>'L', -7989=>'L', -7990=>'L', -7991=>'L', -7992=>'L', -7993=>'L', -7994=>'L', -7995=>'L', -7996=>'L', -7997=>'L', -7998=>'L', -7999=>'L', -8000=>'L', -8001=>'L', -8002=>'L', -8003=>'L', -8004=>'L', -8005=>'L', -8008=>'L', -8009=>'L', -8010=>'L', -8011=>'L', -8012=>'L', -8013=>'L', -8016=>'L', -8017=>'L', -8018=>'L', -8019=>'L', -8020=>'L', -8021=>'L', -8022=>'L', -8023=>'L', -8025=>'L', -8027=>'L', -8029=>'L', -8031=>'L', -8032=>'L', -8033=>'L', -8034=>'L', -8035=>'L', -8036=>'L', -8037=>'L', -8038=>'L', -8039=>'L', -8040=>'L', -8041=>'L', -8042=>'L', -8043=>'L', -8044=>'L', -8045=>'L', -8046=>'L', -8047=>'L', -8048=>'L', -8049=>'L', -8050=>'L', -8051=>'L', -8052=>'L', -8053=>'L', -8054=>'L', -8055=>'L', -8056=>'L', -8057=>'L', -8058=>'L', -8059=>'L', -8060=>'L', -8061=>'L', -8064=>'L', -8065=>'L', -8066=>'L', -8067=>'L', -8068=>'L', -8069=>'L', -8070=>'L', -8071=>'L', -8072=>'L', -8073=>'L', -8074=>'L', -8075=>'L', -8076=>'L', -8077=>'L', -8078=>'L', -8079=>'L', -8080=>'L', -8081=>'L', -8082=>'L', -8083=>'L', -8084=>'L', -8085=>'L', -8086=>'L', -8087=>'L', -8088=>'L', -8089=>'L', -8090=>'L', -8091=>'L', -8092=>'L', -8093=>'L', -8094=>'L', -8095=>'L', -8096=>'L', -8097=>'L', -8098=>'L', -8099=>'L', -8100=>'L', -8101=>'L', -8102=>'L', -8103=>'L', -8104=>'L', -8105=>'L', -8106=>'L', -8107=>'L', -8108=>'L', -8109=>'L', -8110=>'L', -8111=>'L', -8112=>'L', -8113=>'L', -8114=>'L', -8115=>'L', -8116=>'L', -8118=>'L', -8119=>'L', -8120=>'L', -8121=>'L', -8122=>'L', -8123=>'L', -8124=>'L', -8125=>'ON', -8126=>'L', -8127=>'ON', -8128=>'ON', -8129=>'ON', -8130=>'L', -8131=>'L', -8132=>'L', -8134=>'L', -8135=>'L', -8136=>'L', -8137=>'L', -8138=>'L', -8139=>'L', -8140=>'L', -8141=>'ON', -8142=>'ON', -8143=>'ON', -8144=>'L', -8145=>'L', -8146=>'L', -8147=>'L', -8150=>'L', -8151=>'L', -8152=>'L', -8153=>'L', -8154=>'L', -8155=>'L', -8157=>'ON', -8158=>'ON', -8159=>'ON', -8160=>'L', -8161=>'L', -8162=>'L', -8163=>'L', -8164=>'L', -8165=>'L', -8166=>'L', -8167=>'L', -8168=>'L', -8169=>'L', -8170=>'L', -8171=>'L', -8172=>'L', -8173=>'ON', -8174=>'ON', -8175=>'ON', -8178=>'L', -8179=>'L', -8180=>'L', -8182=>'L', -8183=>'L', -8184=>'L', -8185=>'L', -8186=>'L', -8187=>'L', -8188=>'L', -8189=>'ON', -8190=>'ON', -8192=>'WS', -8193=>'WS', -8194=>'WS', -8195=>'WS', -8196=>'WS', -8197=>'WS', -8198=>'WS', -8199=>'WS', -8200=>'WS', -8201=>'WS', -8202=>'WS', -8203=>'BN', -8204=>'BN', -8205=>'BN', -8206=>'L', -8207=>'R', -8208=>'ON', -8209=>'ON', -8210=>'ON', -8211=>'ON', -8212=>'ON', -8213=>'ON', -8214=>'ON', -8215=>'ON', -8216=>'ON', -8217=>'ON', -8218=>'ON', -8219=>'ON', -8220=>'ON', -8221=>'ON', -8222=>'ON', -8223=>'ON', -8224=>'ON', -8225=>'ON', -8226=>'ON', -8227=>'ON', -8228=>'ON', -8229=>'ON', -8230=>'ON', -8231=>'ON', -8232=>'WS', -8233=>'B', -8234=>'LRE', -8235=>'RLE', -8236=>'PDF', -8237=>'LRO', -8238=>'RLO', -8239=>'CS', -8240=>'ET', -8241=>'ET', -8242=>'ET', -8243=>'ET', -8244=>'ET', -8245=>'ON', -8246=>'ON', -8247=>'ON', -8248=>'ON', -8249=>'ON', -8250=>'ON', -8251=>'ON', -8252=>'ON', -8253=>'ON', -8254=>'ON', -8255=>'ON', -8256=>'ON', -8257=>'ON', -8258=>'ON', -8259=>'ON', -8260=>'CS', -8261=>'ON', -8262=>'ON', -8263=>'ON', -8264=>'ON', -8265=>'ON', -8266=>'ON', -8267=>'ON', -8268=>'ON', -8269=>'ON', -8270=>'ON', -8271=>'ON', -8272=>'ON', -8273=>'ON', -8274=>'ON', -8275=>'ON', -8276=>'ON', -8277=>'ON', -8278=>'ON', -8279=>'ON', -8280=>'ON', -8281=>'ON', -8282=>'ON', -8283=>'ON', -8284=>'ON', -8285=>'ON', -8286=>'ON', -8287=>'WS', -8288=>'BN', -8289=>'BN', -8290=>'BN', -8291=>'BN', -8298=>'BN', -8299=>'BN', -8300=>'BN', -8301=>'BN', -8302=>'BN', -8303=>'BN', -8304=>'EN', -8305=>'L', -8308=>'EN', -8309=>'EN', -8310=>'EN', -8311=>'EN', -8312=>'EN', -8313=>'EN', -8314=>'ES', -8315=>'ES', -8316=>'ON', -8317=>'ON', -8318=>'ON', -8319=>'L', -8320=>'EN', -8321=>'EN', -8322=>'EN', -8323=>'EN', -8324=>'EN', -8325=>'EN', -8326=>'EN', -8327=>'EN', -8328=>'EN', -8329=>'EN', -8330=>'ES', -8331=>'ES', -8332=>'ON', -8333=>'ON', -8334=>'ON', -8336=>'L', -8337=>'L', -8338=>'L', -8339=>'L', -8340=>'L', -8352=>'ET', -8353=>'ET', -8354=>'ET', -8355=>'ET', -8356=>'ET', -8357=>'ET', -8358=>'ET', -8359=>'ET', -8360=>'ET', -8361=>'ET', -8362=>'ET', -8363=>'ET', -8364=>'ET', -8365=>'ET', -8366=>'ET', -8367=>'ET', -8368=>'ET', -8369=>'ET', -8370=>'ET', -8371=>'ET', -8372=>'ET', -8373=>'ET', -8400=>'NSM', -8401=>'NSM', -8402=>'NSM', -8403=>'NSM', -8404=>'NSM', -8405=>'NSM', -8406=>'NSM', -8407=>'NSM', -8408=>'NSM', -8409=>'NSM', -8410=>'NSM', -8411=>'NSM', -8412=>'NSM', -8413=>'NSM', -8414=>'NSM', -8415=>'NSM', -8416=>'NSM', -8417=>'NSM', -8418=>'NSM', -8419=>'NSM', -8420=>'NSM', -8421=>'NSM', -8422=>'NSM', -8423=>'NSM', -8424=>'NSM', -8425=>'NSM', -8426=>'NSM', -8427=>'NSM', -8428=>'NSM', -8429=>'NSM', -8430=>'NSM', -8431=>'NSM', -8448=>'ON', -8449=>'ON', -8450=>'L', -8451=>'ON', -8452=>'ON', -8453=>'ON', -8454=>'ON', -8455=>'L', -8456=>'ON', -8457=>'ON', -8458=>'L', -8459=>'L', -8460=>'L', -8461=>'L', -8462=>'L', -8463=>'L', -8464=>'L', -8465=>'L', -8466=>'L', -8467=>'L', -8468=>'ON', -8469=>'L', -8470=>'ON', -8471=>'ON', -8472=>'ON', -8473=>'L', -8474=>'L', -8475=>'L', -8476=>'L', -8477=>'L', -8478=>'ON', -8479=>'ON', -8480=>'ON', -8481=>'ON', -8482=>'ON', -8483=>'ON', -8484=>'L', -8485=>'ON', -8486=>'L', -8487=>'ON', -8488=>'L', -8489=>'ON', -8490=>'L', -8491=>'L', -8492=>'L', -8493=>'L', -8494=>'ET', -8495=>'L', -8496=>'L', -8497=>'L', -8498=>'L', -8499=>'L', -8500=>'L', -8501=>'L', -8502=>'L', -8503=>'L', -8504=>'L', -8505=>'L', -8506=>'ON', -8507=>'ON', -8508=>'L', -8509=>'L', -8510=>'L', -8511=>'L', -8512=>'ON', -8513=>'ON', -8514=>'ON', -8515=>'ON', -8516=>'ON', -8517=>'L', -8518=>'L', -8519=>'L', -8520=>'L', -8521=>'L', -8522=>'ON', -8523=>'ON', -8524=>'ON', -8525=>'ON', -8526=>'L', -8531=>'ON', -8532=>'ON', -8533=>'ON', -8534=>'ON', -8535=>'ON', -8536=>'ON', -8537=>'ON', -8538=>'ON', -8539=>'ON', -8540=>'ON', -8541=>'ON', -8542=>'ON', -8543=>'ON', -8544=>'L', -8545=>'L', -8546=>'L', -8547=>'L', -8548=>'L', -8549=>'L', -8550=>'L', -8551=>'L', -8552=>'L', -8553=>'L', -8554=>'L', -8555=>'L', -8556=>'L', -8557=>'L', -8558=>'L', -8559=>'L', -8560=>'L', -8561=>'L', -8562=>'L', -8563=>'L', -8564=>'L', -8565=>'L', -8566=>'L', -8567=>'L', -8568=>'L', -8569=>'L', -8570=>'L', -8571=>'L', -8572=>'L', -8573=>'L', -8574=>'L', -8575=>'L', -8576=>'L', -8577=>'L', -8578=>'L', -8579=>'L', -8580=>'L', -8592=>'ON', -8593=>'ON', -8594=>'ON', -8595=>'ON', -8596=>'ON', -8597=>'ON', -8598=>'ON', -8599=>'ON', -8600=>'ON', -8601=>'ON', -8602=>'ON', -8603=>'ON', -8604=>'ON', -8605=>'ON', -8606=>'ON', -8607=>'ON', -8608=>'ON', -8609=>'ON', -8610=>'ON', -8611=>'ON', -8612=>'ON', -8613=>'ON', -8614=>'ON', -8615=>'ON', -8616=>'ON', -8617=>'ON', -8618=>'ON', -8619=>'ON', -8620=>'ON', -8621=>'ON', -8622=>'ON', -8623=>'ON', -8624=>'ON', -8625=>'ON', -8626=>'ON', -8627=>'ON', -8628=>'ON', -8629=>'ON', -8630=>'ON', -8631=>'ON', -8632=>'ON', -8633=>'ON', -8634=>'ON', -8635=>'ON', -8636=>'ON', -8637=>'ON', -8638=>'ON', -8639=>'ON', -8640=>'ON', -8641=>'ON', -8642=>'ON', -8643=>'ON', -8644=>'ON', -8645=>'ON', -8646=>'ON', -8647=>'ON', -8648=>'ON', -8649=>'ON', -8650=>'ON', -8651=>'ON', -8652=>'ON', -8653=>'ON', -8654=>'ON', -8655=>'ON', -8656=>'ON', -8657=>'ON', -8658=>'ON', -8659=>'ON', -8660=>'ON', -8661=>'ON', -8662=>'ON', -8663=>'ON', -8664=>'ON', -8665=>'ON', -8666=>'ON', -8667=>'ON', -8668=>'ON', -8669=>'ON', -8670=>'ON', -8671=>'ON', -8672=>'ON', -8673=>'ON', -8674=>'ON', -8675=>'ON', -8676=>'ON', -8677=>'ON', -8678=>'ON', -8679=>'ON', -8680=>'ON', -8681=>'ON', -8682=>'ON', -8683=>'ON', -8684=>'ON', -8685=>'ON', -8686=>'ON', -8687=>'ON', -8688=>'ON', -8689=>'ON', -8690=>'ON', -8691=>'ON', -8692=>'ON', -8693=>'ON', -8694=>'ON', -8695=>'ON', -8696=>'ON', -8697=>'ON', -8698=>'ON', -8699=>'ON', -8700=>'ON', -8701=>'ON', -8702=>'ON', -8703=>'ON', -8704=>'ON', -8705=>'ON', -8706=>'ON', -8707=>'ON', -8708=>'ON', -8709=>'ON', -8710=>'ON', -8711=>'ON', -8712=>'ON', -8713=>'ON', -8714=>'ON', -8715=>'ON', -8716=>'ON', -8717=>'ON', -8718=>'ON', -8719=>'ON', -8720=>'ON', -8721=>'ON', -8722=>'ES', -8723=>'ET', -8724=>'ON', -8725=>'ON', -8726=>'ON', -8727=>'ON', -8728=>'ON', -8729=>'ON', -8730=>'ON', -8731=>'ON', -8732=>'ON', -8733=>'ON', -8734=>'ON', -8735=>'ON', -8736=>'ON', -8737=>'ON', -8738=>'ON', -8739=>'ON', -8740=>'ON', -8741=>'ON', -8742=>'ON', -8743=>'ON', -8744=>'ON', -8745=>'ON', -8746=>'ON', -8747=>'ON', -8748=>'ON', -8749=>'ON', -8750=>'ON', -8751=>'ON', -8752=>'ON', -8753=>'ON', -8754=>'ON', -8755=>'ON', -8756=>'ON', -8757=>'ON', -8758=>'ON', -8759=>'ON', -8760=>'ON', -8761=>'ON', -8762=>'ON', -8763=>'ON', -8764=>'ON', -8765=>'ON', -8766=>'ON', -8767=>'ON', -8768=>'ON', -8769=>'ON', -8770=>'ON', -8771=>'ON', -8772=>'ON', -8773=>'ON', -8774=>'ON', -8775=>'ON', -8776=>'ON', -8777=>'ON', -8778=>'ON', -8779=>'ON', -8780=>'ON', -8781=>'ON', -8782=>'ON', -8783=>'ON', -8784=>'ON', -8785=>'ON', -8786=>'ON', -8787=>'ON', -8788=>'ON', -8789=>'ON', -8790=>'ON', -8791=>'ON', -8792=>'ON', -8793=>'ON', -8794=>'ON', -8795=>'ON', -8796=>'ON', -8797=>'ON', -8798=>'ON', -8799=>'ON', -8800=>'ON', -8801=>'ON', -8802=>'ON', -8803=>'ON', -8804=>'ON', -8805=>'ON', -8806=>'ON', -8807=>'ON', -8808=>'ON', -8809=>'ON', -8810=>'ON', -8811=>'ON', -8812=>'ON', -8813=>'ON', -8814=>'ON', -8815=>'ON', -8816=>'ON', -8817=>'ON', -8818=>'ON', -8819=>'ON', -8820=>'ON', -8821=>'ON', -8822=>'ON', -8823=>'ON', -8824=>'ON', -8825=>'ON', -8826=>'ON', -8827=>'ON', -8828=>'ON', -8829=>'ON', -8830=>'ON', -8831=>'ON', -8832=>'ON', -8833=>'ON', -8834=>'ON', -8835=>'ON', -8836=>'ON', -8837=>'ON', -8838=>'ON', -8839=>'ON', -8840=>'ON', -8841=>'ON', -8842=>'ON', -8843=>'ON', -8844=>'ON', -8845=>'ON', -8846=>'ON', -8847=>'ON', -8848=>'ON', -8849=>'ON', -8850=>'ON', -8851=>'ON', -8852=>'ON', -8853=>'ON', -8854=>'ON', -8855=>'ON', -8856=>'ON', -8857=>'ON', -8858=>'ON', -8859=>'ON', -8860=>'ON', -8861=>'ON', -8862=>'ON', -8863=>'ON', -8864=>'ON', -8865=>'ON', -8866=>'ON', -8867=>'ON', -8868=>'ON', -8869=>'ON', -8870=>'ON', -8871=>'ON', -8872=>'ON', -8873=>'ON', -8874=>'ON', -8875=>'ON', -8876=>'ON', -8877=>'ON', -8878=>'ON', -8879=>'ON', -8880=>'ON', -8881=>'ON', -8882=>'ON', -8883=>'ON', -8884=>'ON', -8885=>'ON', -8886=>'ON', -8887=>'ON', -8888=>'ON', -8889=>'ON', -8890=>'ON', -8891=>'ON', -8892=>'ON', -8893=>'ON', -8894=>'ON', -8895=>'ON', -8896=>'ON', -8897=>'ON', -8898=>'ON', -8899=>'ON', -8900=>'ON', -8901=>'ON', -8902=>'ON', -8903=>'ON', -8904=>'ON', -8905=>'ON', -8906=>'ON', -8907=>'ON', -8908=>'ON', -8909=>'ON', -8910=>'ON', -8911=>'ON', -8912=>'ON', -8913=>'ON', -8914=>'ON', -8915=>'ON', -8916=>'ON', -8917=>'ON', -8918=>'ON', -8919=>'ON', -8920=>'ON', -8921=>'ON', -8922=>'ON', -8923=>'ON', -8924=>'ON', -8925=>'ON', -8926=>'ON', -8927=>'ON', -8928=>'ON', -8929=>'ON', -8930=>'ON', -8931=>'ON', -8932=>'ON', -8933=>'ON', -8934=>'ON', -8935=>'ON', -8936=>'ON', -8937=>'ON', -8938=>'ON', -8939=>'ON', -8940=>'ON', -8941=>'ON', -8942=>'ON', -8943=>'ON', -8944=>'ON', -8945=>'ON', -8946=>'ON', -8947=>'ON', -8948=>'ON', -8949=>'ON', -8950=>'ON', -8951=>'ON', -8952=>'ON', -8953=>'ON', -8954=>'ON', -8955=>'ON', -8956=>'ON', -8957=>'ON', -8958=>'ON', -8959=>'ON', -8960=>'ON', -8961=>'ON', -8962=>'ON', -8963=>'ON', -8964=>'ON', -8965=>'ON', -8966=>'ON', -8967=>'ON', -8968=>'ON', -8969=>'ON', -8970=>'ON', -8971=>'ON', -8972=>'ON', -8973=>'ON', -8974=>'ON', -8975=>'ON', -8976=>'ON', -8977=>'ON', -8978=>'ON', -8979=>'ON', -8980=>'ON', -8981=>'ON', -8982=>'ON', -8983=>'ON', -8984=>'ON', -8985=>'ON', -8986=>'ON', -8987=>'ON', -8988=>'ON', -8989=>'ON', -8990=>'ON', -8991=>'ON', -8992=>'ON', -8993=>'ON', -8994=>'ON', -8995=>'ON', -8996=>'ON', -8997=>'ON', -8998=>'ON', -8999=>'ON', -9000=>'ON', -9001=>'ON', -9002=>'ON', -9003=>'ON', -9004=>'ON', -9005=>'ON', -9006=>'ON', -9007=>'ON', -9008=>'ON', -9009=>'ON', -9010=>'ON', -9011=>'ON', -9012=>'ON', -9013=>'ON', -9014=>'L', -9015=>'L', -9016=>'L', -9017=>'L', -9018=>'L', -9019=>'L', -9020=>'L', -9021=>'L', -9022=>'L', -9023=>'L', -9024=>'L', -9025=>'L', -9026=>'L', -9027=>'L', -9028=>'L', -9029=>'L', -9030=>'L', -9031=>'L', -9032=>'L', -9033=>'L', -9034=>'L', -9035=>'L', -9036=>'L', -9037=>'L', -9038=>'L', -9039=>'L', -9040=>'L', -9041=>'L', -9042=>'L', -9043=>'L', -9044=>'L', -9045=>'L', -9046=>'L', -9047=>'L', -9048=>'L', -9049=>'L', -9050=>'L', -9051=>'L', -9052=>'L', -9053=>'L', -9054=>'L', -9055=>'L', -9056=>'L', -9057=>'L', -9058=>'L', -9059=>'L', -9060=>'L', -9061=>'L', -9062=>'L', -9063=>'L', -9064=>'L', -9065=>'L', -9066=>'L', -9067=>'L', -9068=>'L', -9069=>'L', -9070=>'L', -9071=>'L', -9072=>'L', -9073=>'L', -9074=>'L', -9075=>'L', -9076=>'L', -9077=>'L', -9078=>'L', -9079=>'L', -9080=>'L', -9081=>'L', -9082=>'L', -9083=>'ON', -9084=>'ON', -9085=>'ON', -9086=>'ON', -9087=>'ON', -9088=>'ON', -9089=>'ON', -9090=>'ON', -9091=>'ON', -9092=>'ON', -9093=>'ON', -9094=>'ON', -9095=>'ON', -9096=>'ON', -9097=>'ON', -9098=>'ON', -9099=>'ON', -9100=>'ON', -9101=>'ON', -9102=>'ON', -9103=>'ON', -9104=>'ON', -9105=>'ON', -9106=>'ON', -9107=>'ON', -9108=>'ON', -9109=>'L', -9110=>'ON', -9111=>'ON', -9112=>'ON', -9113=>'ON', -9114=>'ON', -9115=>'ON', -9116=>'ON', -9117=>'ON', -9118=>'ON', -9119=>'ON', -9120=>'ON', -9121=>'ON', -9122=>'ON', -9123=>'ON', -9124=>'ON', -9125=>'ON', -9126=>'ON', -9127=>'ON', -9128=>'ON', -9129=>'ON', -9130=>'ON', -9131=>'ON', -9132=>'ON', -9133=>'ON', -9134=>'ON', -9135=>'ON', -9136=>'ON', -9137=>'ON', -9138=>'ON', -9139=>'ON', -9140=>'ON', -9141=>'ON', -9142=>'ON', -9143=>'ON', -9144=>'ON', -9145=>'ON', -9146=>'ON', -9147=>'ON', -9148=>'ON', -9149=>'ON', -9150=>'ON', -9151=>'ON', -9152=>'ON', -9153=>'ON', -9154=>'ON', -9155=>'ON', -9156=>'ON', -9157=>'ON', -9158=>'ON', -9159=>'ON', -9160=>'ON', -9161=>'ON', -9162=>'ON', -9163=>'ON', -9164=>'ON', -9165=>'ON', -9166=>'ON', -9167=>'ON', -9168=>'ON', -9169=>'ON', -9170=>'ON', -9171=>'ON', -9172=>'ON', -9173=>'ON', -9174=>'ON', -9175=>'ON', -9176=>'ON', -9177=>'ON', -9178=>'ON', -9179=>'ON', -9180=>'ON', -9181=>'ON', -9182=>'ON', -9183=>'ON', -9184=>'ON', -9185=>'ON', -9186=>'ON', -9187=>'ON', -9188=>'ON', -9189=>'ON', -9190=>'ON', -9191=>'ON', -9216=>'ON', -9217=>'ON', -9218=>'ON', -9219=>'ON', -9220=>'ON', -9221=>'ON', -9222=>'ON', -9223=>'ON', -9224=>'ON', -9225=>'ON', -9226=>'ON', -9227=>'ON', -9228=>'ON', -9229=>'ON', -9230=>'ON', -9231=>'ON', -9232=>'ON', -9233=>'ON', -9234=>'ON', -9235=>'ON', -9236=>'ON', -9237=>'ON', -9238=>'ON', -9239=>'ON', -9240=>'ON', -9241=>'ON', -9242=>'ON', -9243=>'ON', -9244=>'ON', -9245=>'ON', -9246=>'ON', -9247=>'ON', -9248=>'ON', -9249=>'ON', -9250=>'ON', -9251=>'ON', -9252=>'ON', -9253=>'ON', -9254=>'ON', -9280=>'ON', -9281=>'ON', -9282=>'ON', -9283=>'ON', -9284=>'ON', -9285=>'ON', -9286=>'ON', -9287=>'ON', -9288=>'ON', -9289=>'ON', -9290=>'ON', -9312=>'ON', -9313=>'ON', -9314=>'ON', -9315=>'ON', -9316=>'ON', -9317=>'ON', -9318=>'ON', -9319=>'ON', -9320=>'ON', -9321=>'ON', -9322=>'ON', -9323=>'ON', -9324=>'ON', -9325=>'ON', -9326=>'ON', -9327=>'ON', -9328=>'ON', -9329=>'ON', -9330=>'ON', -9331=>'ON', -9332=>'ON', -9333=>'ON', -9334=>'ON', -9335=>'ON', -9336=>'ON', -9337=>'ON', -9338=>'ON', -9339=>'ON', -9340=>'ON', -9341=>'ON', -9342=>'ON', -9343=>'ON', -9344=>'ON', -9345=>'ON', -9346=>'ON', -9347=>'ON', -9348=>'ON', -9349=>'ON', -9350=>'ON', -9351=>'ON', -9352=>'EN', -9353=>'EN', -9354=>'EN', -9355=>'EN', -9356=>'EN', -9357=>'EN', -9358=>'EN', -9359=>'EN', -9360=>'EN', -9361=>'EN', -9362=>'EN', -9363=>'EN', -9364=>'EN', -9365=>'EN', -9366=>'EN', -9367=>'EN', -9368=>'EN', -9369=>'EN', -9370=>'EN', -9371=>'EN', -9372=>'L', -9373=>'L', -9374=>'L', -9375=>'L', -9376=>'L', -9377=>'L', -9378=>'L', -9379=>'L', -9380=>'L', -9381=>'L', -9382=>'L', -9383=>'L', -9384=>'L', -9385=>'L', -9386=>'L', -9387=>'L', -9388=>'L', -9389=>'L', -9390=>'L', -9391=>'L', -9392=>'L', -9393=>'L', -9394=>'L', -9395=>'L', -9396=>'L', -9397=>'L', -9398=>'L', -9399=>'L', -9400=>'L', -9401=>'L', -9402=>'L', -9403=>'L', -9404=>'L', -9405=>'L', -9406=>'L', -9407=>'L', -9408=>'L', -9409=>'L', -9410=>'L', -9411=>'L', -9412=>'L', -9413=>'L', -9414=>'L', -9415=>'L', -9416=>'L', -9417=>'L', -9418=>'L', -9419=>'L', -9420=>'L', -9421=>'L', -9422=>'L', -9423=>'L', -9424=>'L', -9425=>'L', -9426=>'L', -9427=>'L', -9428=>'L', -9429=>'L', -9430=>'L', -9431=>'L', -9432=>'L', -9433=>'L', -9434=>'L', -9435=>'L', -9436=>'L', -9437=>'L', -9438=>'L', -9439=>'L', -9440=>'L', -9441=>'L', -9442=>'L', -9443=>'L', -9444=>'L', -9445=>'L', -9446=>'L', -9447=>'L', -9448=>'L', -9449=>'L', -9450=>'ON', -9451=>'ON', -9452=>'ON', -9453=>'ON', -9454=>'ON', -9455=>'ON', -9456=>'ON', -9457=>'ON', -9458=>'ON', -9459=>'ON', -9460=>'ON', -9461=>'ON', -9462=>'ON', -9463=>'ON', -9464=>'ON', -9465=>'ON', -9466=>'ON', -9467=>'ON', -9468=>'ON', -9469=>'ON', -9470=>'ON', -9471=>'ON', -9472=>'ON', -9473=>'ON', -9474=>'ON', -9475=>'ON', -9476=>'ON', -9477=>'ON', -9478=>'ON', -9479=>'ON', -9480=>'ON', -9481=>'ON', -9482=>'ON', -9483=>'ON', -9484=>'ON', -9485=>'ON', -9486=>'ON', -9487=>'ON', -9488=>'ON', -9489=>'ON', -9490=>'ON', -9491=>'ON', -9492=>'ON', -9493=>'ON', -9494=>'ON', -9495=>'ON', -9496=>'ON', -9497=>'ON', -9498=>'ON', -9499=>'ON', -9500=>'ON', -9501=>'ON', -9502=>'ON', -9503=>'ON', -9504=>'ON', -9505=>'ON', -9506=>'ON', -9507=>'ON', -9508=>'ON', -9509=>'ON', -9510=>'ON', -9511=>'ON', -9512=>'ON', -9513=>'ON', -9514=>'ON', -9515=>'ON', -9516=>'ON', -9517=>'ON', -9518=>'ON', -9519=>'ON', -9520=>'ON', -9521=>'ON', -9522=>'ON', -9523=>'ON', -9524=>'ON', -9525=>'ON', -9526=>'ON', -9527=>'ON', -9528=>'ON', -9529=>'ON', -9530=>'ON', -9531=>'ON', -9532=>'ON', -9533=>'ON', -9534=>'ON', -9535=>'ON', -9536=>'ON', -9537=>'ON', -9538=>'ON', -9539=>'ON', -9540=>'ON', -9541=>'ON', -9542=>'ON', -9543=>'ON', -9544=>'ON', -9545=>'ON', -9546=>'ON', -9547=>'ON', -9548=>'ON', -9549=>'ON', -9550=>'ON', -9551=>'ON', -9552=>'ON', -9553=>'ON', -9554=>'ON', -9555=>'ON', -9556=>'ON', -9557=>'ON', -9558=>'ON', -9559=>'ON', -9560=>'ON', -9561=>'ON', -9562=>'ON', -9563=>'ON', -9564=>'ON', -9565=>'ON', -9566=>'ON', -9567=>'ON', -9568=>'ON', -9569=>'ON', -9570=>'ON', -9571=>'ON', -9572=>'ON', -9573=>'ON', -9574=>'ON', -9575=>'ON', -9576=>'ON', -9577=>'ON', -9578=>'ON', -9579=>'ON', -9580=>'ON', -9581=>'ON', -9582=>'ON', -9583=>'ON', -9584=>'ON', -9585=>'ON', -9586=>'ON', -9587=>'ON', -9588=>'ON', -9589=>'ON', -9590=>'ON', -9591=>'ON', -9592=>'ON', -9593=>'ON', -9594=>'ON', -9595=>'ON', -9596=>'ON', -9597=>'ON', -9598=>'ON', -9599=>'ON', -9600=>'ON', -9601=>'ON', -9602=>'ON', -9603=>'ON', -9604=>'ON', -9605=>'ON', -9606=>'ON', -9607=>'ON', -9608=>'ON', -9609=>'ON', -9610=>'ON', -9611=>'ON', -9612=>'ON', -9613=>'ON', -9614=>'ON', -9615=>'ON', -9616=>'ON', -9617=>'ON', -9618=>'ON', -9619=>'ON', -9620=>'ON', -9621=>'ON', -9622=>'ON', -9623=>'ON', -9624=>'ON', -9625=>'ON', -9626=>'ON', -9627=>'ON', -9628=>'ON', -9629=>'ON', -9630=>'ON', -9631=>'ON', -9632=>'ON', -9633=>'ON', -9634=>'ON', -9635=>'ON', -9636=>'ON', -9637=>'ON', -9638=>'ON', -9639=>'ON', -9640=>'ON', -9641=>'ON', -9642=>'ON', -9643=>'ON', -9644=>'ON', -9645=>'ON', -9646=>'ON', -9647=>'ON', -9648=>'ON', -9649=>'ON', -9650=>'ON', -9651=>'ON', -9652=>'ON', -9653=>'ON', -9654=>'ON', -9655=>'ON', -9656=>'ON', -9657=>'ON', -9658=>'ON', -9659=>'ON', -9660=>'ON', -9661=>'ON', -9662=>'ON', -9663=>'ON', -9664=>'ON', -9665=>'ON', -9666=>'ON', -9667=>'ON', -9668=>'ON', -9669=>'ON', -9670=>'ON', -9671=>'ON', -9672=>'ON', -9673=>'ON', -9674=>'ON', -9675=>'ON', -9676=>'ON', -9677=>'ON', -9678=>'ON', -9679=>'ON', -9680=>'ON', -9681=>'ON', -9682=>'ON', -9683=>'ON', -9684=>'ON', -9685=>'ON', -9686=>'ON', -9687=>'ON', -9688=>'ON', -9689=>'ON', -9690=>'ON', -9691=>'ON', -9692=>'ON', -9693=>'ON', -9694=>'ON', -9695=>'ON', -9696=>'ON', -9697=>'ON', -9698=>'ON', -9699=>'ON', -9700=>'ON', -9701=>'ON', -9702=>'ON', -9703=>'ON', -9704=>'ON', -9705=>'ON', -9706=>'ON', -9707=>'ON', -9708=>'ON', -9709=>'ON', -9710=>'ON', -9711=>'ON', -9712=>'ON', -9713=>'ON', -9714=>'ON', -9715=>'ON', -9716=>'ON', -9717=>'ON', -9718=>'ON', -9719=>'ON', -9720=>'ON', -9721=>'ON', -9722=>'ON', -9723=>'ON', -9724=>'ON', -9725=>'ON', -9726=>'ON', -9727=>'ON', -9728=>'ON', -9729=>'ON', -9730=>'ON', -9731=>'ON', -9732=>'ON', -9733=>'ON', -9734=>'ON', -9735=>'ON', -9736=>'ON', -9737=>'ON', -9738=>'ON', -9739=>'ON', -9740=>'ON', -9741=>'ON', -9742=>'ON', -9743=>'ON', -9744=>'ON', -9745=>'ON', -9746=>'ON', -9747=>'ON', -9748=>'ON', -9749=>'ON', -9750=>'ON', -9751=>'ON', -9752=>'ON', -9753=>'ON', -9754=>'ON', -9755=>'ON', -9756=>'ON', -9757=>'ON', -9758=>'ON', -9759=>'ON', -9760=>'ON', -9761=>'ON', -9762=>'ON', -9763=>'ON', -9764=>'ON', -9765=>'ON', -9766=>'ON', -9767=>'ON', -9768=>'ON', -9769=>'ON', -9770=>'ON', -9771=>'ON', -9772=>'ON', -9773=>'ON', -9774=>'ON', -9775=>'ON', -9776=>'ON', -9777=>'ON', -9778=>'ON', -9779=>'ON', -9780=>'ON', -9781=>'ON', -9782=>'ON', -9783=>'ON', -9784=>'ON', -9785=>'ON', -9786=>'ON', -9787=>'ON', -9788=>'ON', -9789=>'ON', -9790=>'ON', -9791=>'ON', -9792=>'ON', -9793=>'ON', -9794=>'ON', -9795=>'ON', -9796=>'ON', -9797=>'ON', -9798=>'ON', -9799=>'ON', -9800=>'ON', -9801=>'ON', -9802=>'ON', -9803=>'ON', -9804=>'ON', -9805=>'ON', -9806=>'ON', -9807=>'ON', -9808=>'ON', -9809=>'ON', -9810=>'ON', -9811=>'ON', -9812=>'ON', -9813=>'ON', -9814=>'ON', -9815=>'ON', -9816=>'ON', -9817=>'ON', -9818=>'ON', -9819=>'ON', -9820=>'ON', -9821=>'ON', -9822=>'ON', -9823=>'ON', -9824=>'ON', -9825=>'ON', -9826=>'ON', -9827=>'ON', -9828=>'ON', -9829=>'ON', -9830=>'ON', -9831=>'ON', -9832=>'ON', -9833=>'ON', -9834=>'ON', -9835=>'ON', -9836=>'ON', -9837=>'ON', -9838=>'ON', -9839=>'ON', -9840=>'ON', -9841=>'ON', -9842=>'ON', -9843=>'ON', -9844=>'ON', -9845=>'ON', -9846=>'ON', -9847=>'ON', -9848=>'ON', -9849=>'ON', -9850=>'ON', -9851=>'ON', -9852=>'ON', -9853=>'ON', -9854=>'ON', -9855=>'ON', -9856=>'ON', -9857=>'ON', -9858=>'ON', -9859=>'ON', -9860=>'ON', -9861=>'ON', -9862=>'ON', -9863=>'ON', -9864=>'ON', -9865=>'ON', -9866=>'ON', -9867=>'ON', -9868=>'ON', -9869=>'ON', -9870=>'ON', -9871=>'ON', -9872=>'ON', -9873=>'ON', -9874=>'ON', -9875=>'ON', -9876=>'ON', -9877=>'ON', -9878=>'ON', -9879=>'ON', -9880=>'ON', -9881=>'ON', -9882=>'ON', -9883=>'ON', -9884=>'ON', -9888=>'ON', -9889=>'ON', -9890=>'ON', -9891=>'ON', -9892=>'ON', -9893=>'ON', -9894=>'ON', -9895=>'ON', -9896=>'ON', -9897=>'ON', -9898=>'ON', -9899=>'ON', -9900=>'L', -9901=>'ON', -9902=>'ON', -9903=>'ON', -9904=>'ON', -9905=>'ON', -9906=>'ON', -9985=>'ON', -9986=>'ON', -9987=>'ON', -9988=>'ON', -9990=>'ON', -9991=>'ON', -9992=>'ON', -9993=>'ON', -9996=>'ON', -9997=>'ON', -9998=>'ON', -9999=>'ON', -10000=>'ON', -10001=>'ON', -10002=>'ON', -10003=>'ON', -10004=>'ON', -10005=>'ON', -10006=>'ON', -10007=>'ON', -10008=>'ON', -10009=>'ON', -10010=>'ON', -10011=>'ON', -10012=>'ON', -10013=>'ON', -10014=>'ON', -10015=>'ON', -10016=>'ON', -10017=>'ON', -10018=>'ON', -10019=>'ON', -10020=>'ON', -10021=>'ON', -10022=>'ON', -10023=>'ON', -10025=>'ON', -10026=>'ON', -10027=>'ON', -10028=>'ON', -10029=>'ON', -10030=>'ON', -10031=>'ON', -10032=>'ON', -10033=>'ON', -10034=>'ON', -10035=>'ON', -10036=>'ON', -10037=>'ON', -10038=>'ON', -10039=>'ON', -10040=>'ON', -10041=>'ON', -10042=>'ON', -10043=>'ON', -10044=>'ON', -10045=>'ON', -10046=>'ON', -10047=>'ON', -10048=>'ON', -10049=>'ON', -10050=>'ON', -10051=>'ON', -10052=>'ON', -10053=>'ON', -10054=>'ON', -10055=>'ON', -10056=>'ON', -10057=>'ON', -10058=>'ON', -10059=>'ON', -10061=>'ON', -10063=>'ON', -10064=>'ON', -10065=>'ON', -10066=>'ON', -10070=>'ON', -10072=>'ON', -10073=>'ON', -10074=>'ON', -10075=>'ON', -10076=>'ON', -10077=>'ON', -10078=>'ON', -10081=>'ON', -10082=>'ON', -10083=>'ON', -10084=>'ON', -10085=>'ON', -10086=>'ON', -10087=>'ON', -10088=>'ON', -10089=>'ON', -10090=>'ON', -10091=>'ON', -10092=>'ON', -10093=>'ON', -10094=>'ON', -10095=>'ON', -10096=>'ON', -10097=>'ON', -10098=>'ON', -10099=>'ON', -10100=>'ON', -10101=>'ON', -10102=>'ON', -10103=>'ON', -10104=>'ON', -10105=>'ON', -10106=>'ON', -10107=>'ON', -10108=>'ON', -10109=>'ON', -10110=>'ON', -10111=>'ON', -10112=>'ON', -10113=>'ON', -10114=>'ON', -10115=>'ON', -10116=>'ON', -10117=>'ON', -10118=>'ON', -10119=>'ON', -10120=>'ON', -10121=>'ON', -10122=>'ON', -10123=>'ON', -10124=>'ON', -10125=>'ON', -10126=>'ON', -10127=>'ON', -10128=>'ON', -10129=>'ON', -10130=>'ON', -10131=>'ON', -10132=>'ON', -10136=>'ON', -10137=>'ON', -10138=>'ON', -10139=>'ON', -10140=>'ON', -10141=>'ON', -10142=>'ON', -10143=>'ON', -10144=>'ON', -10145=>'ON', -10146=>'ON', -10147=>'ON', -10148=>'ON', -10149=>'ON', -10150=>'ON', -10151=>'ON', -10152=>'ON', -10153=>'ON', -10154=>'ON', -10155=>'ON', -10156=>'ON', -10157=>'ON', -10158=>'ON', -10159=>'ON', -10161=>'ON', -10162=>'ON', -10163=>'ON', -10164=>'ON', -10165=>'ON', -10166=>'ON', -10167=>'ON', -10168=>'ON', -10169=>'ON', -10170=>'ON', -10171=>'ON', -10172=>'ON', -10173=>'ON', -10174=>'ON', -10176=>'ON', -10177=>'ON', -10178=>'ON', -10179=>'ON', -10180=>'ON', -10181=>'ON', -10182=>'ON', -10183=>'ON', -10184=>'ON', -10185=>'ON', -10186=>'ON', -10192=>'ON', -10193=>'ON', -10194=>'ON', -10195=>'ON', -10196=>'ON', -10197=>'ON', -10198=>'ON', -10199=>'ON', -10200=>'ON', -10201=>'ON', -10202=>'ON', -10203=>'ON', -10204=>'ON', -10205=>'ON', -10206=>'ON', -10207=>'ON', -10208=>'ON', -10209=>'ON', -10210=>'ON', -10211=>'ON', -10212=>'ON', -10213=>'ON', -10214=>'ON', -10215=>'ON', -10216=>'ON', -10217=>'ON', -10218=>'ON', -10219=>'ON', -10224=>'ON', -10225=>'ON', -10226=>'ON', -10227=>'ON', -10228=>'ON', -10229=>'ON', -10230=>'ON', -10231=>'ON', -10232=>'ON', -10233=>'ON', -10234=>'ON', -10235=>'ON', -10236=>'ON', -10237=>'ON', -10238=>'ON', -10239=>'ON', -10240=>'L', -10241=>'L', -10242=>'L', -10243=>'L', -10244=>'L', -10245=>'L', -10246=>'L', -10247=>'L', -10248=>'L', -10249=>'L', -10250=>'L', -10251=>'L', -10252=>'L', -10253=>'L', -10254=>'L', -10255=>'L', -10256=>'L', -10257=>'L', -10258=>'L', -10259=>'L', -10260=>'L', -10261=>'L', -10262=>'L', -10263=>'L', -10264=>'L', -10265=>'L', -10266=>'L', -10267=>'L', -10268=>'L', -10269=>'L', -10270=>'L', -10271=>'L', -10272=>'L', -10273=>'L', -10274=>'L', -10275=>'L', -10276=>'L', -10277=>'L', -10278=>'L', -10279=>'L', -10280=>'L', -10281=>'L', -10282=>'L', -10283=>'L', -10284=>'L', -10285=>'L', -10286=>'L', -10287=>'L', -10288=>'L', -10289=>'L', -10290=>'L', -10291=>'L', -10292=>'L', -10293=>'L', -10294=>'L', -10295=>'L', -10296=>'L', -10297=>'L', -10298=>'L', -10299=>'L', -10300=>'L', -10301=>'L', -10302=>'L', -10303=>'L', -10304=>'L', -10305=>'L', -10306=>'L', -10307=>'L', -10308=>'L', -10309=>'L', -10310=>'L', -10311=>'L', -10312=>'L', -10313=>'L', -10314=>'L', -10315=>'L', -10316=>'L', -10317=>'L', -10318=>'L', -10319=>'L', -10320=>'L', -10321=>'L', -10322=>'L', -10323=>'L', -10324=>'L', -10325=>'L', -10326=>'L', -10327=>'L', -10328=>'L', -10329=>'L', -10330=>'L', -10331=>'L', -10332=>'L', -10333=>'L', -10334=>'L', -10335=>'L', -10336=>'L', -10337=>'L', -10338=>'L', -10339=>'L', -10340=>'L', -10341=>'L', -10342=>'L', -10343=>'L', -10344=>'L', -10345=>'L', -10346=>'L', -10347=>'L', -10348=>'L', -10349=>'L', -10350=>'L', -10351=>'L', -10352=>'L', -10353=>'L', -10354=>'L', -10355=>'L', -10356=>'L', -10357=>'L', -10358=>'L', -10359=>'L', -10360=>'L', -10361=>'L', -10362=>'L', -10363=>'L', -10364=>'L', -10365=>'L', -10366=>'L', -10367=>'L', -10368=>'L', -10369=>'L', -10370=>'L', -10371=>'L', -10372=>'L', -10373=>'L', -10374=>'L', -10375=>'L', -10376=>'L', -10377=>'L', -10378=>'L', -10379=>'L', -10380=>'L', -10381=>'L', -10382=>'L', -10383=>'L', -10384=>'L', -10385=>'L', -10386=>'L', -10387=>'L', -10388=>'L', -10389=>'L', -10390=>'L', -10391=>'L', -10392=>'L', -10393=>'L', -10394=>'L', -10395=>'L', -10396=>'L', -10397=>'L', -10398=>'L', -10399=>'L', -10400=>'L', -10401=>'L', -10402=>'L', -10403=>'L', -10404=>'L', -10405=>'L', -10406=>'L', -10407=>'L', -10408=>'L', -10409=>'L', -10410=>'L', -10411=>'L', -10412=>'L', -10413=>'L', -10414=>'L', -10415=>'L', -10416=>'L', -10417=>'L', -10418=>'L', -10419=>'L', -10420=>'L', -10421=>'L', -10422=>'L', -10423=>'L', -10424=>'L', -10425=>'L', -10426=>'L', -10427=>'L', -10428=>'L', -10429=>'L', -10430=>'L', -10431=>'L', -10432=>'L', -10433=>'L', -10434=>'L', -10435=>'L', -10436=>'L', -10437=>'L', -10438=>'L', -10439=>'L', -10440=>'L', -10441=>'L', -10442=>'L', -10443=>'L', -10444=>'L', -10445=>'L', -10446=>'L', -10447=>'L', -10448=>'L', -10449=>'L', -10450=>'L', -10451=>'L', -10452=>'L', -10453=>'L', -10454=>'L', -10455=>'L', -10456=>'L', -10457=>'L', -10458=>'L', -10459=>'L', -10460=>'L', -10461=>'L', -10462=>'L', -10463=>'L', -10464=>'L', -10465=>'L', -10466=>'L', -10467=>'L', -10468=>'L', -10469=>'L', -10470=>'L', -10471=>'L', -10472=>'L', -10473=>'L', -10474=>'L', -10475=>'L', -10476=>'L', -10477=>'L', -10478=>'L', -10479=>'L', -10480=>'L', -10481=>'L', -10482=>'L', -10483=>'L', -10484=>'L', -10485=>'L', -10486=>'L', -10487=>'L', -10488=>'L', -10489=>'L', -10490=>'L', -10491=>'L', -10492=>'L', -10493=>'L', -10494=>'L', -10495=>'L', -10496=>'ON', -10497=>'ON', -10498=>'ON', -10499=>'ON', -10500=>'ON', -10501=>'ON', -10502=>'ON', -10503=>'ON', -10504=>'ON', -10505=>'ON', -10506=>'ON', -10507=>'ON', -10508=>'ON', -10509=>'ON', -10510=>'ON', -10511=>'ON', -10512=>'ON', -10513=>'ON', -10514=>'ON', -10515=>'ON', -10516=>'ON', -10517=>'ON', -10518=>'ON', -10519=>'ON', -10520=>'ON', -10521=>'ON', -10522=>'ON', -10523=>'ON', -10524=>'ON', -10525=>'ON', -10526=>'ON', -10527=>'ON', -10528=>'ON', -10529=>'ON', -10530=>'ON', -10531=>'ON', -10532=>'ON', -10533=>'ON', -10534=>'ON', -10535=>'ON', -10536=>'ON', -10537=>'ON', -10538=>'ON', -10539=>'ON', -10540=>'ON', -10541=>'ON', -10542=>'ON', -10543=>'ON', -10544=>'ON', -10545=>'ON', -10546=>'ON', -10547=>'ON', -10548=>'ON', -10549=>'ON', -10550=>'ON', -10551=>'ON', -10552=>'ON', -10553=>'ON', -10554=>'ON', -10555=>'ON', -10556=>'ON', -10557=>'ON', -10558=>'ON', -10559=>'ON', -10560=>'ON', -10561=>'ON', -10562=>'ON', -10563=>'ON', -10564=>'ON', -10565=>'ON', -10566=>'ON', -10567=>'ON', -10568=>'ON', -10569=>'ON', -10570=>'ON', -10571=>'ON', -10572=>'ON', -10573=>'ON', -10574=>'ON', -10575=>'ON', -10576=>'ON', -10577=>'ON', -10578=>'ON', -10579=>'ON', -10580=>'ON', -10581=>'ON', -10582=>'ON', -10583=>'ON', -10584=>'ON', -10585=>'ON', -10586=>'ON', -10587=>'ON', -10588=>'ON', -10589=>'ON', -10590=>'ON', -10591=>'ON', -10592=>'ON', -10593=>'ON', -10594=>'ON', -10595=>'ON', -10596=>'ON', -10597=>'ON', -10598=>'ON', -10599=>'ON', -10600=>'ON', -10601=>'ON', -10602=>'ON', -10603=>'ON', -10604=>'ON', -10605=>'ON', -10606=>'ON', -10607=>'ON', -10608=>'ON', -10609=>'ON', -10610=>'ON', -10611=>'ON', -10612=>'ON', -10613=>'ON', -10614=>'ON', -10615=>'ON', -10616=>'ON', -10617=>'ON', -10618=>'ON', -10619=>'ON', -10620=>'ON', -10621=>'ON', -10622=>'ON', -10623=>'ON', -10624=>'ON', -10625=>'ON', -10626=>'ON', -10627=>'ON', -10628=>'ON', -10629=>'ON', -10630=>'ON', -10631=>'ON', -10632=>'ON', -10633=>'ON', -10634=>'ON', -10635=>'ON', -10636=>'ON', -10637=>'ON', -10638=>'ON', -10639=>'ON', -10640=>'ON', -10641=>'ON', -10642=>'ON', -10643=>'ON', -10644=>'ON', -10645=>'ON', -10646=>'ON', -10647=>'ON', -10648=>'ON', -10649=>'ON', -10650=>'ON', -10651=>'ON', -10652=>'ON', -10653=>'ON', -10654=>'ON', -10655=>'ON', -10656=>'ON', -10657=>'ON', -10658=>'ON', -10659=>'ON', -10660=>'ON', -10661=>'ON', -10662=>'ON', -10663=>'ON', -10664=>'ON', -10665=>'ON', -10666=>'ON', -10667=>'ON', -10668=>'ON', -10669=>'ON', -10670=>'ON', -10671=>'ON', -10672=>'ON', -10673=>'ON', -10674=>'ON', -10675=>'ON', -10676=>'ON', -10677=>'ON', -10678=>'ON', -10679=>'ON', -10680=>'ON', -10681=>'ON', -10682=>'ON', -10683=>'ON', -10684=>'ON', -10685=>'ON', -10686=>'ON', -10687=>'ON', -10688=>'ON', -10689=>'ON', -10690=>'ON', -10691=>'ON', -10692=>'ON', -10693=>'ON', -10694=>'ON', -10695=>'ON', -10696=>'ON', -10697=>'ON', -10698=>'ON', -10699=>'ON', -10700=>'ON', -10701=>'ON', -10702=>'ON', -10703=>'ON', -10704=>'ON', -10705=>'ON', -10706=>'ON', -10707=>'ON', -10708=>'ON', -10709=>'ON', -10710=>'ON', -10711=>'ON', -10712=>'ON', -10713=>'ON', -10714=>'ON', -10715=>'ON', -10716=>'ON', -10717=>'ON', -10718=>'ON', -10719=>'ON', -10720=>'ON', -10721=>'ON', -10722=>'ON', -10723=>'ON', -10724=>'ON', -10725=>'ON', -10726=>'ON', -10727=>'ON', -10728=>'ON', -10729=>'ON', -10730=>'ON', -10731=>'ON', -10732=>'ON', -10733=>'ON', -10734=>'ON', -10735=>'ON', -10736=>'ON', -10737=>'ON', -10738=>'ON', -10739=>'ON', -10740=>'ON', -10741=>'ON', -10742=>'ON', -10743=>'ON', -10744=>'ON', -10745=>'ON', -10746=>'ON', -10747=>'ON', -10748=>'ON', -10749=>'ON', -10750=>'ON', -10751=>'ON', -10752=>'ON', -10753=>'ON', -10754=>'ON', -10755=>'ON', -10756=>'ON', -10757=>'ON', -10758=>'ON', -10759=>'ON', -10760=>'ON', -10761=>'ON', -10762=>'ON', -10763=>'ON', -10764=>'ON', -10765=>'ON', -10766=>'ON', -10767=>'ON', -10768=>'ON', -10769=>'ON', -10770=>'ON', -10771=>'ON', -10772=>'ON', -10773=>'ON', -10774=>'ON', -10775=>'ON', -10776=>'ON', -10777=>'ON', -10778=>'ON', -10779=>'ON', -10780=>'ON', -10781=>'ON', -10782=>'ON', -10783=>'ON', -10784=>'ON', -10785=>'ON', -10786=>'ON', -10787=>'ON', -10788=>'ON', -10789=>'ON', -10790=>'ON', -10791=>'ON', -10792=>'ON', -10793=>'ON', -10794=>'ON', -10795=>'ON', -10796=>'ON', -10797=>'ON', -10798=>'ON', -10799=>'ON', -10800=>'ON', -10801=>'ON', -10802=>'ON', -10803=>'ON', -10804=>'ON', -10805=>'ON', -10806=>'ON', -10807=>'ON', -10808=>'ON', -10809=>'ON', -10810=>'ON', -10811=>'ON', -10812=>'ON', -10813=>'ON', -10814=>'ON', -10815=>'ON', -10816=>'ON', -10817=>'ON', -10818=>'ON', -10819=>'ON', -10820=>'ON', -10821=>'ON', -10822=>'ON', -10823=>'ON', -10824=>'ON', -10825=>'ON', -10826=>'ON', -10827=>'ON', -10828=>'ON', -10829=>'ON', -10830=>'ON', -10831=>'ON', -10832=>'ON', -10833=>'ON', -10834=>'ON', -10835=>'ON', -10836=>'ON', -10837=>'ON', -10838=>'ON', -10839=>'ON', -10840=>'ON', -10841=>'ON', -10842=>'ON', -10843=>'ON', -10844=>'ON', -10845=>'ON', -10846=>'ON', -10847=>'ON', -10848=>'ON', -10849=>'ON', -10850=>'ON', -10851=>'ON', -10852=>'ON', -10853=>'ON', -10854=>'ON', -10855=>'ON', -10856=>'ON', -10857=>'ON', -10858=>'ON', -10859=>'ON', -10860=>'ON', -10861=>'ON', -10862=>'ON', -10863=>'ON', -10864=>'ON', -10865=>'ON', -10866=>'ON', -10867=>'ON', -10868=>'ON', -10869=>'ON', -10870=>'ON', -10871=>'ON', -10872=>'ON', -10873=>'ON', -10874=>'ON', -10875=>'ON', -10876=>'ON', -10877=>'ON', -10878=>'ON', -10879=>'ON', -10880=>'ON', -10881=>'ON', -10882=>'ON', -10883=>'ON', -10884=>'ON', -10885=>'ON', -10886=>'ON', -10887=>'ON', -10888=>'ON', -10889=>'ON', -10890=>'ON', -10891=>'ON', -10892=>'ON', -10893=>'ON', -10894=>'ON', -10895=>'ON', -10896=>'ON', -10897=>'ON', -10898=>'ON', -10899=>'ON', -10900=>'ON', -10901=>'ON', -10902=>'ON', -10903=>'ON', -10904=>'ON', -10905=>'ON', -10906=>'ON', -10907=>'ON', -10908=>'ON', -10909=>'ON', -10910=>'ON', -10911=>'ON', -10912=>'ON', -10913=>'ON', -10914=>'ON', -10915=>'ON', -10916=>'ON', -10917=>'ON', -10918=>'ON', -10919=>'ON', -10920=>'ON', -10921=>'ON', -10922=>'ON', -10923=>'ON', -10924=>'ON', -10925=>'ON', -10926=>'ON', -10927=>'ON', -10928=>'ON', -10929=>'ON', -10930=>'ON', -10931=>'ON', -10932=>'ON', -10933=>'ON', -10934=>'ON', -10935=>'ON', -10936=>'ON', -10937=>'ON', -10938=>'ON', -10939=>'ON', -10940=>'ON', -10941=>'ON', -10942=>'ON', -10943=>'ON', -10944=>'ON', -10945=>'ON', -10946=>'ON', -10947=>'ON', -10948=>'ON', -10949=>'ON', -10950=>'ON', -10951=>'ON', -10952=>'ON', -10953=>'ON', -10954=>'ON', -10955=>'ON', -10956=>'ON', -10957=>'ON', -10958=>'ON', -10959=>'ON', -10960=>'ON', -10961=>'ON', -10962=>'ON', -10963=>'ON', -10964=>'ON', -10965=>'ON', -10966=>'ON', -10967=>'ON', -10968=>'ON', -10969=>'ON', -10970=>'ON', -10971=>'ON', -10972=>'ON', -10973=>'ON', -10974=>'ON', -10975=>'ON', -10976=>'ON', -10977=>'ON', -10978=>'ON', -10979=>'ON', -10980=>'ON', -10981=>'ON', -10982=>'ON', -10983=>'ON', -10984=>'ON', -10985=>'ON', -10986=>'ON', -10987=>'ON', -10988=>'ON', -10989=>'ON', -10990=>'ON', -10991=>'ON', -10992=>'ON', -10993=>'ON', -10994=>'ON', -10995=>'ON', -10996=>'ON', -10997=>'ON', -10998=>'ON', -10999=>'ON', -11000=>'ON', -11001=>'ON', -11002=>'ON', -11003=>'ON', -11004=>'ON', -11005=>'ON', -11006=>'ON', -11007=>'ON', -11008=>'ON', -11009=>'ON', -11010=>'ON', -11011=>'ON', -11012=>'ON', -11013=>'ON', -11014=>'ON', -11015=>'ON', -11016=>'ON', -11017=>'ON', -11018=>'ON', -11019=>'ON', -11020=>'ON', -11021=>'ON', -11022=>'ON', -11023=>'ON', -11024=>'ON', -11025=>'ON', -11026=>'ON', -11027=>'ON', -11028=>'ON', -11029=>'ON', -11030=>'ON', -11031=>'ON', -11032=>'ON', -11033=>'ON', -11034=>'ON', -11040=>'ON', -11041=>'ON', -11042=>'ON', -11043=>'ON', -11264=>'L', -11265=>'L', -11266=>'L', -11267=>'L', -11268=>'L', -11269=>'L', -11270=>'L', -11271=>'L', -11272=>'L', -11273=>'L', -11274=>'L', -11275=>'L', -11276=>'L', -11277=>'L', -11278=>'L', -11279=>'L', -11280=>'L', -11281=>'L', -11282=>'L', -11283=>'L', -11284=>'L', -11285=>'L', -11286=>'L', -11287=>'L', -11288=>'L', -11289=>'L', -11290=>'L', -11291=>'L', -11292=>'L', -11293=>'L', -11294=>'L', -11295=>'L', -11296=>'L', -11297=>'L', -11298=>'L', -11299=>'L', -11300=>'L', -11301=>'L', -11302=>'L', -11303=>'L', -11304=>'L', -11305=>'L', -11306=>'L', -11307=>'L', -11308=>'L', -11309=>'L', -11310=>'L', -11312=>'L', -11313=>'L', -11314=>'L', -11315=>'L', -11316=>'L', -11317=>'L', -11318=>'L', -11319=>'L', -11320=>'L', -11321=>'L', -11322=>'L', -11323=>'L', -11324=>'L', -11325=>'L', -11326=>'L', -11327=>'L', -11328=>'L', -11329=>'L', -11330=>'L', -11331=>'L', -11332=>'L', -11333=>'L', -11334=>'L', -11335=>'L', -11336=>'L', -11337=>'L', -11338=>'L', -11339=>'L', -11340=>'L', -11341=>'L', -11342=>'L', -11343=>'L', -11344=>'L', -11345=>'L', -11346=>'L', -11347=>'L', -11348=>'L', -11349=>'L', -11350=>'L', -11351=>'L', -11352=>'L', -11353=>'L', -11354=>'L', -11355=>'L', -11356=>'L', -11357=>'L', -11358=>'L', -11360=>'L', -11361=>'L', -11362=>'L', -11363=>'L', -11364=>'L', -11365=>'L', -11366=>'L', -11367=>'L', -11368=>'L', -11369=>'L', -11370=>'L', -11371=>'L', -11372=>'L', -11380=>'L', -11381=>'L', -11382=>'L', -11383=>'L', -11392=>'L', -11393=>'L', -11394=>'L', -11395=>'L', -11396=>'L', -11397=>'L', -11398=>'L', -11399=>'L', -11400=>'L', -11401=>'L', -11402=>'L', -11403=>'L', -11404=>'L', -11405=>'L', -11406=>'L', -11407=>'L', -11408=>'L', -11409=>'L', -11410=>'L', -11411=>'L', -11412=>'L', -11413=>'L', -11414=>'L', -11415=>'L', -11416=>'L', -11417=>'L', -11418=>'L', -11419=>'L', -11420=>'L', -11421=>'L', -11422=>'L', -11423=>'L', -11424=>'L', -11425=>'L', -11426=>'L', -11427=>'L', -11428=>'L', -11429=>'L', -11430=>'L', -11431=>'L', -11432=>'L', -11433=>'L', -11434=>'L', -11435=>'L', -11436=>'L', -11437=>'L', -11438=>'L', -11439=>'L', -11440=>'L', -11441=>'L', -11442=>'L', -11443=>'L', -11444=>'L', -11445=>'L', -11446=>'L', -11447=>'L', -11448=>'L', -11449=>'L', -11450=>'L', -11451=>'L', -11452=>'L', -11453=>'L', -11454=>'L', -11455=>'L', -11456=>'L', -11457=>'L', -11458=>'L', -11459=>'L', -11460=>'L', -11461=>'L', -11462=>'L', -11463=>'L', -11464=>'L', -11465=>'L', -11466=>'L', -11467=>'L', -11468=>'L', -11469=>'L', -11470=>'L', -11471=>'L', -11472=>'L', -11473=>'L', -11474=>'L', -11475=>'L', -11476=>'L', -11477=>'L', -11478=>'L', -11479=>'L', -11480=>'L', -11481=>'L', -11482=>'L', -11483=>'L', -11484=>'L', -11485=>'L', -11486=>'L', -11487=>'L', -11488=>'L', -11489=>'L', -11490=>'L', -11491=>'L', -11492=>'L', -11493=>'ON', -11494=>'ON', -11495=>'ON', -11496=>'ON', -11497=>'ON', -11498=>'ON', -11513=>'ON', -11514=>'ON', -11515=>'ON', -11516=>'ON', -11517=>'ON', -11518=>'ON', -11519=>'ON', -11520=>'L', -11521=>'L', -11522=>'L', -11523=>'L', -11524=>'L', -11525=>'L', -11526=>'L', -11527=>'L', -11528=>'L', -11529=>'L', -11530=>'L', -11531=>'L', -11532=>'L', -11533=>'L', -11534=>'L', -11535=>'L', -11536=>'L', -11537=>'L', -11538=>'L', -11539=>'L', -11540=>'L', -11541=>'L', -11542=>'L', -11543=>'L', -11544=>'L', -11545=>'L', -11546=>'L', -11547=>'L', -11548=>'L', -11549=>'L', -11550=>'L', -11551=>'L', -11552=>'L', -11553=>'L', -11554=>'L', -11555=>'L', -11556=>'L', -11557=>'L', -11568=>'L', -11569=>'L', -11570=>'L', -11571=>'L', -11572=>'L', -11573=>'L', -11574=>'L', -11575=>'L', -11576=>'L', -11577=>'L', -11578=>'L', -11579=>'L', -11580=>'L', -11581=>'L', -11582=>'L', -11583=>'L', -11584=>'L', -11585=>'L', -11586=>'L', -11587=>'L', -11588=>'L', -11589=>'L', -11590=>'L', -11591=>'L', -11592=>'L', -11593=>'L', -11594=>'L', -11595=>'L', -11596=>'L', -11597=>'L', -11598=>'L', -11599=>'L', -11600=>'L', -11601=>'L', -11602=>'L', -11603=>'L', -11604=>'L', -11605=>'L', -11606=>'L', -11607=>'L', -11608=>'L', -11609=>'L', -11610=>'L', -11611=>'L', -11612=>'L', -11613=>'L', -11614=>'L', -11615=>'L', -11616=>'L', -11617=>'L', -11618=>'L', -11619=>'L', -11620=>'L', -11621=>'L', -11631=>'L', -11648=>'L', -11649=>'L', -11650=>'L', -11651=>'L', -11652=>'L', -11653=>'L', -11654=>'L', -11655=>'L', -11656=>'L', -11657=>'L', -11658=>'L', -11659=>'L', -11660=>'L', -11661=>'L', -11662=>'L', -11663=>'L', -11664=>'L', -11665=>'L', -11666=>'L', -11667=>'L', -11668=>'L', -11669=>'L', -11670=>'L', -11680=>'L', -11681=>'L', -11682=>'L', -11683=>'L', -11684=>'L', -11685=>'L', -11686=>'L', -11688=>'L', -11689=>'L', -11690=>'L', -11691=>'L', -11692=>'L', -11693=>'L', -11694=>'L', -11696=>'L', -11697=>'L', -11698=>'L', -11699=>'L', -11700=>'L', -11701=>'L', -11702=>'L', -11704=>'L', -11705=>'L', -11706=>'L', -11707=>'L', -11708=>'L', -11709=>'L', -11710=>'L', -11712=>'L', -11713=>'L', -11714=>'L', -11715=>'L', -11716=>'L', -11717=>'L', -11718=>'L', -11720=>'L', -11721=>'L', -11722=>'L', -11723=>'L', -11724=>'L', -11725=>'L', -11726=>'L', -11728=>'L', -11729=>'L', -11730=>'L', -11731=>'L', -11732=>'L', -11733=>'L', -11734=>'L', -11736=>'L', -11737=>'L', -11738=>'L', -11739=>'L', -11740=>'L', -11741=>'L', -11742=>'L', -11776=>'ON', -11777=>'ON', -11778=>'ON', -11779=>'ON', -11780=>'ON', -11781=>'ON', -11782=>'ON', -11783=>'ON', -11784=>'ON', -11785=>'ON', -11786=>'ON', -11787=>'ON', -11788=>'ON', -11789=>'ON', -11790=>'ON', -11791=>'ON', -11792=>'ON', -11793=>'ON', -11794=>'ON', -11795=>'ON', -11796=>'ON', -11797=>'ON', -11798=>'ON', -11799=>'ON', -11804=>'ON', -11805=>'ON', -11904=>'ON', -11905=>'ON', -11906=>'ON', -11907=>'ON', -11908=>'ON', -11909=>'ON', -11910=>'ON', -11911=>'ON', -11912=>'ON', -11913=>'ON', -11914=>'ON', -11915=>'ON', -11916=>'ON', -11917=>'ON', -11918=>'ON', -11919=>'ON', -11920=>'ON', -11921=>'ON', -11922=>'ON', -11923=>'ON', -11924=>'ON', -11925=>'ON', -11926=>'ON', -11927=>'ON', -11928=>'ON', -11929=>'ON', -11931=>'ON', -11932=>'ON', -11933=>'ON', -11934=>'ON', -11935=>'ON', -11936=>'ON', -11937=>'ON', -11938=>'ON', -11939=>'ON', -11940=>'ON', -11941=>'ON', -11942=>'ON', -11943=>'ON', -11944=>'ON', -11945=>'ON', -11946=>'ON', -11947=>'ON', -11948=>'ON', -11949=>'ON', -11950=>'ON', -11951=>'ON', -11952=>'ON', -11953=>'ON', -11954=>'ON', -11955=>'ON', -11956=>'ON', -11957=>'ON', -11958=>'ON', -11959=>'ON', -11960=>'ON', -11961=>'ON', -11962=>'ON', -11963=>'ON', -11964=>'ON', -11965=>'ON', -11966=>'ON', -11967=>'ON', -11968=>'ON', -11969=>'ON', -11970=>'ON', -11971=>'ON', -11972=>'ON', -11973=>'ON', -11974=>'ON', -11975=>'ON', -11976=>'ON', -11977=>'ON', -11978=>'ON', -11979=>'ON', -11980=>'ON', -11981=>'ON', -11982=>'ON', -11983=>'ON', -11984=>'ON', -11985=>'ON', -11986=>'ON', -11987=>'ON', -11988=>'ON', -11989=>'ON', -11990=>'ON', -11991=>'ON', -11992=>'ON', -11993=>'ON', -11994=>'ON', -11995=>'ON', -11996=>'ON', -11997=>'ON', -11998=>'ON', -11999=>'ON', -12000=>'ON', -12001=>'ON', -12002=>'ON', -12003=>'ON', -12004=>'ON', -12005=>'ON', -12006=>'ON', -12007=>'ON', -12008=>'ON', -12009=>'ON', -12010=>'ON', -12011=>'ON', -12012=>'ON', -12013=>'ON', -12014=>'ON', -12015=>'ON', -12016=>'ON', -12017=>'ON', -12018=>'ON', -12019=>'ON', -12032=>'ON', -12033=>'ON', -12034=>'ON', -12035=>'ON', -12036=>'ON', -12037=>'ON', -12038=>'ON', -12039=>'ON', -12040=>'ON', -12041=>'ON', -12042=>'ON', -12043=>'ON', -12044=>'ON', -12045=>'ON', -12046=>'ON', -12047=>'ON', -12048=>'ON', -12049=>'ON', -12050=>'ON', -12051=>'ON', -12052=>'ON', -12053=>'ON', -12054=>'ON', -12055=>'ON', -12056=>'ON', -12057=>'ON', -12058=>'ON', -12059=>'ON', -12060=>'ON', -12061=>'ON', -12062=>'ON', -12063=>'ON', -12064=>'ON', -12065=>'ON', -12066=>'ON', -12067=>'ON', -12068=>'ON', -12069=>'ON', -12070=>'ON', -12071=>'ON', -12072=>'ON', -12073=>'ON', -12074=>'ON', -12075=>'ON', -12076=>'ON', -12077=>'ON', -12078=>'ON', -12079=>'ON', -12080=>'ON', -12081=>'ON', -12082=>'ON', -12083=>'ON', -12084=>'ON', -12085=>'ON', -12086=>'ON', -12087=>'ON', -12088=>'ON', -12089=>'ON', -12090=>'ON', -12091=>'ON', -12092=>'ON', -12093=>'ON', -12094=>'ON', -12095=>'ON', -12096=>'ON', -12097=>'ON', -12098=>'ON', -12099=>'ON', -12100=>'ON', -12101=>'ON', -12102=>'ON', -12103=>'ON', -12104=>'ON', -12105=>'ON', -12106=>'ON', -12107=>'ON', -12108=>'ON', -12109=>'ON', -12110=>'ON', -12111=>'ON', -12112=>'ON', -12113=>'ON', -12114=>'ON', -12115=>'ON', -12116=>'ON', -12117=>'ON', -12118=>'ON', -12119=>'ON', -12120=>'ON', -12121=>'ON', -12122=>'ON', -12123=>'ON', -12124=>'ON', -12125=>'ON', -12126=>'ON', -12127=>'ON', -12128=>'ON', -12129=>'ON', -12130=>'ON', -12131=>'ON', -12132=>'ON', -12133=>'ON', -12134=>'ON', -12135=>'ON', -12136=>'ON', -12137=>'ON', -12138=>'ON', -12139=>'ON', -12140=>'ON', -12141=>'ON', -12142=>'ON', -12143=>'ON', -12144=>'ON', -12145=>'ON', -12146=>'ON', -12147=>'ON', -12148=>'ON', -12149=>'ON', -12150=>'ON', -12151=>'ON', -12152=>'ON', -12153=>'ON', -12154=>'ON', -12155=>'ON', -12156=>'ON', -12157=>'ON', -12158=>'ON', -12159=>'ON', -12160=>'ON', -12161=>'ON', -12162=>'ON', -12163=>'ON', -12164=>'ON', -12165=>'ON', -12166=>'ON', -12167=>'ON', -12168=>'ON', -12169=>'ON', -12170=>'ON', -12171=>'ON', -12172=>'ON', -12173=>'ON', -12174=>'ON', -12175=>'ON', -12176=>'ON', -12177=>'ON', -12178=>'ON', -12179=>'ON', -12180=>'ON', -12181=>'ON', -12182=>'ON', -12183=>'ON', -12184=>'ON', -12185=>'ON', -12186=>'ON', -12187=>'ON', -12188=>'ON', -12189=>'ON', -12190=>'ON', -12191=>'ON', -12192=>'ON', -12193=>'ON', -12194=>'ON', -12195=>'ON', -12196=>'ON', -12197=>'ON', -12198=>'ON', -12199=>'ON', -12200=>'ON', -12201=>'ON', -12202=>'ON', -12203=>'ON', -12204=>'ON', -12205=>'ON', -12206=>'ON', -12207=>'ON', -12208=>'ON', -12209=>'ON', -12210=>'ON', -12211=>'ON', -12212=>'ON', -12213=>'ON', -12214=>'ON', -12215=>'ON', -12216=>'ON', -12217=>'ON', -12218=>'ON', -12219=>'ON', -12220=>'ON', -12221=>'ON', -12222=>'ON', -12223=>'ON', -12224=>'ON', -12225=>'ON', -12226=>'ON', -12227=>'ON', -12228=>'ON', -12229=>'ON', -12230=>'ON', -12231=>'ON', -12232=>'ON', -12233=>'ON', -12234=>'ON', -12235=>'ON', -12236=>'ON', -12237=>'ON', -12238=>'ON', -12239=>'ON', -12240=>'ON', -12241=>'ON', -12242=>'ON', -12243=>'ON', -12244=>'ON', -12245=>'ON', -12272=>'ON', -12273=>'ON', -12274=>'ON', -12275=>'ON', -12276=>'ON', -12277=>'ON', -12278=>'ON', -12279=>'ON', -12280=>'ON', -12281=>'ON', -12282=>'ON', -12283=>'ON', -12288=>'WS', -12289=>'ON', -12290=>'ON', -12291=>'ON', -12292=>'ON', -12293=>'L', -12294=>'L', -12295=>'L', -12296=>'ON', -12297=>'ON', -12298=>'ON', -12299=>'ON', -12300=>'ON', -12301=>'ON', -12302=>'ON', -12303=>'ON', -12304=>'ON', -12305=>'ON', -12306=>'ON', -12307=>'ON', -12308=>'ON', -12309=>'ON', -12310=>'ON', -12311=>'ON', -12312=>'ON', -12313=>'ON', -12314=>'ON', -12315=>'ON', -12316=>'ON', -12317=>'ON', -12318=>'ON', -12319=>'ON', -12320=>'ON', -12321=>'L', -12322=>'L', -12323=>'L', -12324=>'L', -12325=>'L', -12326=>'L', -12327=>'L', -12328=>'L', -12329=>'L', -12330=>'NSM', -12331=>'NSM', -12332=>'NSM', -12333=>'NSM', -12334=>'NSM', -12335=>'NSM', -12336=>'ON', -12337=>'L', -12338=>'L', -12339=>'L', -12340=>'L', -12341=>'L', -12342=>'ON', -12343=>'ON', -12344=>'L', -12345=>'L', -12346=>'L', -12347=>'L', -12348=>'L', -12349=>'ON', -12350=>'ON', -12351=>'ON', -12353=>'L', -12354=>'L', -12355=>'L', -12356=>'L', -12357=>'L', -12358=>'L', -12359=>'L', -12360=>'L', -12361=>'L', -12362=>'L', -12363=>'L', -12364=>'L', -12365=>'L', -12366=>'L', -12367=>'L', -12368=>'L', -12369=>'L', -12370=>'L', -12371=>'L', -12372=>'L', -12373=>'L', -12374=>'L', -12375=>'L', -12376=>'L', -12377=>'L', -12378=>'L', -12379=>'L', -12380=>'L', -12381=>'L', -12382=>'L', -12383=>'L', -12384=>'L', -12385=>'L', -12386=>'L', -12387=>'L', -12388=>'L', -12389=>'L', -12390=>'L', -12391=>'L', -12392=>'L', -12393=>'L', -12394=>'L', -12395=>'L', -12396=>'L', -12397=>'L', -12398=>'L', -12399=>'L', -12400=>'L', -12401=>'L', -12402=>'L', -12403=>'L', -12404=>'L', -12405=>'L', -12406=>'L', -12407=>'L', -12408=>'L', -12409=>'L', -12410=>'L', -12411=>'L', -12412=>'L', -12413=>'L', -12414=>'L', -12415=>'L', -12416=>'L', -12417=>'L', -12418=>'L', -12419=>'L', -12420=>'L', -12421=>'L', -12422=>'L', -12423=>'L', -12424=>'L', -12425=>'L', -12426=>'L', -12427=>'L', -12428=>'L', -12429=>'L', -12430=>'L', -12431=>'L', -12432=>'L', -12433=>'L', -12434=>'L', -12435=>'L', -12436=>'L', -12437=>'L', -12438=>'L', -12441=>'NSM', -12442=>'NSM', -12443=>'ON', -12444=>'ON', -12445=>'L', -12446=>'L', -12447=>'L', -12448=>'ON', -12449=>'L', -12450=>'L', -12451=>'L', -12452=>'L', -12453=>'L', -12454=>'L', -12455=>'L', -12456=>'L', -12457=>'L', -12458=>'L', -12459=>'L', -12460=>'L', -12461=>'L', -12462=>'L', -12463=>'L', -12464=>'L', -12465=>'L', -12466=>'L', -12467=>'L', -12468=>'L', -12469=>'L', -12470=>'L', -12471=>'L', -12472=>'L', -12473=>'L', -12474=>'L', -12475=>'L', -12476=>'L', -12477=>'L', -12478=>'L', -12479=>'L', -12480=>'L', -12481=>'L', -12482=>'L', -12483=>'L', -12484=>'L', -12485=>'L', -12486=>'L', -12487=>'L', -12488=>'L', -12489=>'L', -12490=>'L', -12491=>'L', -12492=>'L', -12493=>'L', -12494=>'L', -12495=>'L', -12496=>'L', -12497=>'L', -12498=>'L', -12499=>'L', -12500=>'L', -12501=>'L', -12502=>'L', -12503=>'L', -12504=>'L', -12505=>'L', -12506=>'L', -12507=>'L', -12508=>'L', -12509=>'L', -12510=>'L', -12511=>'L', -12512=>'L', -12513=>'L', -12514=>'L', -12515=>'L', -12516=>'L', -12517=>'L', -12518=>'L', -12519=>'L', -12520=>'L', -12521=>'L', -12522=>'L', -12523=>'L', -12524=>'L', -12525=>'L', -12526=>'L', -12527=>'L', -12528=>'L', -12529=>'L', -12530=>'L', -12531=>'L', -12532=>'L', -12533=>'L', -12534=>'L', -12535=>'L', -12536=>'L', -12537=>'L', -12538=>'L', -12539=>'ON', -12540=>'L', -12541=>'L', -12542=>'L', -12543=>'L', -12549=>'L', -12550=>'L', -12551=>'L', -12552=>'L', -12553=>'L', -12554=>'L', -12555=>'L', -12556=>'L', -12557=>'L', -12558=>'L', -12559=>'L', -12560=>'L', -12561=>'L', -12562=>'L', -12563=>'L', -12564=>'L', -12565=>'L', -12566=>'L', -12567=>'L', -12568=>'L', -12569=>'L', -12570=>'L', -12571=>'L', -12572=>'L', -12573=>'L', -12574=>'L', -12575=>'L', -12576=>'L', -12577=>'L', -12578=>'L', -12579=>'L', -12580=>'L', -12581=>'L', -12582=>'L', -12583=>'L', -12584=>'L', -12585=>'L', -12586=>'L', -12587=>'L', -12588=>'L', -12593=>'L', -12594=>'L', -12595=>'L', -12596=>'L', -12597=>'L', -12598=>'L', -12599=>'L', -12600=>'L', -12601=>'L', -12602=>'L', -12603=>'L', -12604=>'L', -12605=>'L', -12606=>'L', -12607=>'L', -12608=>'L', -12609=>'L', -12610=>'L', -12611=>'L', -12612=>'L', -12613=>'L', -12614=>'L', -12615=>'L', -12616=>'L', -12617=>'L', -12618=>'L', -12619=>'L', -12620=>'L', -12621=>'L', -12622=>'L', -12623=>'L', -12624=>'L', -12625=>'L', -12626=>'L', -12627=>'L', -12628=>'L', -12629=>'L', -12630=>'L', -12631=>'L', -12632=>'L', -12633=>'L', -12634=>'L', -12635=>'L', -12636=>'L', -12637=>'L', -12638=>'L', -12639=>'L', -12640=>'L', -12641=>'L', -12642=>'L', -12643=>'L', -12644=>'L', -12645=>'L', -12646=>'L', -12647=>'L', -12648=>'L', -12649=>'L', -12650=>'L', -12651=>'L', -12652=>'L', -12653=>'L', -12654=>'L', -12655=>'L', -12656=>'L', -12657=>'L', -12658=>'L', -12659=>'L', -12660=>'L', -12661=>'L', -12662=>'L', -12663=>'L', -12664=>'L', -12665=>'L', -12666=>'L', -12667=>'L', -12668=>'L', -12669=>'L', -12670=>'L', -12671=>'L', -12672=>'L', -12673=>'L', -12674=>'L', -12675=>'L', -12676=>'L', -12677=>'L', -12678=>'L', -12679=>'L', -12680=>'L', -12681=>'L', -12682=>'L', -12683=>'L', -12684=>'L', -12685=>'L', -12686=>'L', -12688=>'L', -12689=>'L', -12690=>'L', -12691=>'L', -12692=>'L', -12693=>'L', -12694=>'L', -12695=>'L', -12696=>'L', -12697=>'L', -12698=>'L', -12699=>'L', -12700=>'L', -12701=>'L', -12702=>'L', -12703=>'L', -12704=>'L', -12705=>'L', -12706=>'L', -12707=>'L', -12708=>'L', -12709=>'L', -12710=>'L', -12711=>'L', -12712=>'L', -12713=>'L', -12714=>'L', -12715=>'L', -12716=>'L', -12717=>'L', -12718=>'L', -12719=>'L', -12720=>'L', -12721=>'L', -12722=>'L', -12723=>'L', -12724=>'L', -12725=>'L', -12726=>'L', -12727=>'L', -12736=>'ON', -12737=>'ON', -12738=>'ON', -12739=>'ON', -12740=>'ON', -12741=>'ON', -12742=>'ON', -12743=>'ON', -12744=>'ON', -12745=>'ON', -12746=>'ON', -12747=>'ON', -12748=>'ON', -12749=>'ON', -12750=>'ON', -12751=>'ON', -12784=>'L', -12785=>'L', -12786=>'L', -12787=>'L', -12788=>'L', -12789=>'L', -12790=>'L', -12791=>'L', -12792=>'L', -12793=>'L', -12794=>'L', -12795=>'L', -12796=>'L', -12797=>'L', -12798=>'L', -12799=>'L', -12800=>'L', -12801=>'L', -12802=>'L', -12803=>'L', -12804=>'L', -12805=>'L', -12806=>'L', -12807=>'L', -12808=>'L', -12809=>'L', -12810=>'L', -12811=>'L', -12812=>'L', -12813=>'L', -12814=>'L', -12815=>'L', -12816=>'L', -12817=>'L', -12818=>'L', -12819=>'L', -12820=>'L', -12821=>'L', -12822=>'L', -12823=>'L', -12824=>'L', -12825=>'L', -12826=>'L', -12827=>'L', -12828=>'L', -12829=>'ON', -12830=>'ON', -12832=>'L', -12833=>'L', -12834=>'L', -12835=>'L', -12836=>'L', -12837=>'L', -12838=>'L', -12839=>'L', -12840=>'L', -12841=>'L', -12842=>'L', -12843=>'L', -12844=>'L', -12845=>'L', -12846=>'L', -12847=>'L', -12848=>'L', -12849=>'L', -12850=>'L', -12851=>'L', -12852=>'L', -12853=>'L', -12854=>'L', -12855=>'L', -12856=>'L', -12857=>'L', -12858=>'L', -12859=>'L', -12860=>'L', -12861=>'L', -12862=>'L', -12863=>'L', -12864=>'L', -12865=>'L', -12866=>'L', -12867=>'L', -12880=>'ON', -12881=>'ON', -12882=>'ON', -12883=>'ON', -12884=>'ON', -12885=>'ON', -12886=>'ON', -12887=>'ON', -12888=>'ON', -12889=>'ON', -12890=>'ON', -12891=>'ON', -12892=>'ON', -12893=>'ON', -12894=>'ON', -12895=>'ON', -12896=>'L', -12897=>'L', -12898=>'L', -12899=>'L', -12900=>'L', -12901=>'L', -12902=>'L', -12903=>'L', -12904=>'L', -12905=>'L', -12906=>'L', -12907=>'L', -12908=>'L', -12909=>'L', -12910=>'L', -12911=>'L', -12912=>'L', -12913=>'L', -12914=>'L', -12915=>'L', -12916=>'L', -12917=>'L', -12918=>'L', -12919=>'L', -12920=>'L', -12921=>'L', -12922=>'L', -12923=>'L', -12924=>'ON', -12925=>'ON', -12926=>'ON', -12927=>'L', -12928=>'L', -12929=>'L', -12930=>'L', -12931=>'L', -12932=>'L', -12933=>'L', -12934=>'L', -12935=>'L', -12936=>'L', -12937=>'L', -12938=>'L', -12939=>'L', -12940=>'L', -12941=>'L', -12942=>'L', -12943=>'L', -12944=>'L', -12945=>'L', -12946=>'L', -12947=>'L', -12948=>'L', -12949=>'L', -12950=>'L', -12951=>'L', -12952=>'L', -12953=>'L', -12954=>'L', -12955=>'L', -12956=>'L', -12957=>'L', -12958=>'L', -12959=>'L', -12960=>'L', -12961=>'L', -12962=>'L', -12963=>'L', -12964=>'L', -12965=>'L', -12966=>'L', -12967=>'L', -12968=>'L', -12969=>'L', -12970=>'L', -12971=>'L', -12972=>'L', -12973=>'L', -12974=>'L', -12975=>'L', -12976=>'L', -12977=>'ON', -12978=>'ON', -12979=>'ON', -12980=>'ON', -12981=>'ON', -12982=>'ON', -12983=>'ON', -12984=>'ON', -12985=>'ON', -12986=>'ON', -12987=>'ON', -12988=>'ON', -12989=>'ON', -12990=>'ON', -12991=>'ON', -12992=>'L', -12993=>'L', -12994=>'L', -12995=>'L', -12996=>'L', -12997=>'L', -12998=>'L', -12999=>'L', -13000=>'L', -13001=>'L', -13002=>'L', -13003=>'L', -13004=>'ON', -13005=>'ON', -13006=>'ON', -13007=>'ON', -13008=>'L', -13009=>'L', -13010=>'L', -13011=>'L', -13012=>'L', -13013=>'L', -13014=>'L', -13015=>'L', -13016=>'L', -13017=>'L', -13018=>'L', -13019=>'L', -13020=>'L', -13021=>'L', -13022=>'L', -13023=>'L', -13024=>'L', -13025=>'L', -13026=>'L', -13027=>'L', -13028=>'L', -13029=>'L', -13030=>'L', -13031=>'L', -13032=>'L', -13033=>'L', -13034=>'L', -13035=>'L', -13036=>'L', -13037=>'L', -13038=>'L', -13039=>'L', -13040=>'L', -13041=>'L', -13042=>'L', -13043=>'L', -13044=>'L', -13045=>'L', -13046=>'L', -13047=>'L', -13048=>'L', -13049=>'L', -13050=>'L', -13051=>'L', -13052=>'L', -13053=>'L', -13054=>'L', -13056=>'L', -13057=>'L', -13058=>'L', -13059=>'L', -13060=>'L', -13061=>'L', -13062=>'L', -13063=>'L', -13064=>'L', -13065=>'L', -13066=>'L', -13067=>'L', -13068=>'L', -13069=>'L', -13070=>'L', -13071=>'L', -13072=>'L', -13073=>'L', -13074=>'L', -13075=>'L', -13076=>'L', -13077=>'L', -13078=>'L', -13079=>'L', -13080=>'L', -13081=>'L', -13082=>'L', -13083=>'L', -13084=>'L', -13085=>'L', -13086=>'L', -13087=>'L', -13088=>'L', -13089=>'L', -13090=>'L', -13091=>'L', -13092=>'L', -13093=>'L', -13094=>'L', -13095=>'L', -13096=>'L', -13097=>'L', -13098=>'L', -13099=>'L', -13100=>'L', -13101=>'L', -13102=>'L', -13103=>'L', -13104=>'L', -13105=>'L', -13106=>'L', -13107=>'L', -13108=>'L', -13109=>'L', -13110=>'L', -13111=>'L', -13112=>'L', -13113=>'L', -13114=>'L', -13115=>'L', -13116=>'L', -13117=>'L', -13118=>'L', -13119=>'L', -13120=>'L', -13121=>'L', -13122=>'L', -13123=>'L', -13124=>'L', -13125=>'L', -13126=>'L', -13127=>'L', -13128=>'L', -13129=>'L', -13130=>'L', -13131=>'L', -13132=>'L', -13133=>'L', -13134=>'L', -13135=>'L', -13136=>'L', -13137=>'L', -13138=>'L', -13139=>'L', -13140=>'L', -13141=>'L', -13142=>'L', -13143=>'L', -13144=>'L', -13145=>'L', -13146=>'L', -13147=>'L', -13148=>'L', -13149=>'L', -13150=>'L', -13151=>'L', -13152=>'L', -13153=>'L', -13154=>'L', -13155=>'L', -13156=>'L', -13157=>'L', -13158=>'L', -13159=>'L', -13160=>'L', -13161=>'L', -13162=>'L', -13163=>'L', -13164=>'L', -13165=>'L', -13166=>'L', -13167=>'L', -13168=>'L', -13169=>'L', -13170=>'L', -13171=>'L', -13172=>'L', -13173=>'L', -13174=>'L', -13175=>'ON', -13176=>'ON', -13177=>'ON', -13178=>'ON', -13179=>'L', -13180=>'L', -13181=>'L', -13182=>'L', -13183=>'L', -13184=>'L', -13185=>'L', -13186=>'L', -13187=>'L', -13188=>'L', -13189=>'L', -13190=>'L', -13191=>'L', -13192=>'L', -13193=>'L', -13194=>'L', -13195=>'L', -13196=>'L', -13197=>'L', -13198=>'L', -13199=>'L', -13200=>'L', -13201=>'L', -13202=>'L', -13203=>'L', -13204=>'L', -13205=>'L', -13206=>'L', -13207=>'L', -13208=>'L', -13209=>'L', -13210=>'L', -13211=>'L', -13212=>'L', -13213=>'L', -13214=>'L', -13215=>'L', -13216=>'L', -13217=>'L', -13218=>'L', -13219=>'L', -13220=>'L', -13221=>'L', -13222=>'L', -13223=>'L', -13224=>'L', -13225=>'L', -13226=>'L', -13227=>'L', -13228=>'L', -13229=>'L', -13230=>'L', -13231=>'L', -13232=>'L', -13233=>'L', -13234=>'L', -13235=>'L', -13236=>'L', -13237=>'L', -13238=>'L', -13239=>'L', -13240=>'L', -13241=>'L', -13242=>'L', -13243=>'L', -13244=>'L', -13245=>'L', -13246=>'L', -13247=>'L', -13248=>'L', -13249=>'L', -13250=>'L', -13251=>'L', -13252=>'L', -13253=>'L', -13254=>'L', -13255=>'L', -13256=>'L', -13257=>'L', -13258=>'L', -13259=>'L', -13260=>'L', -13261=>'L', -13262=>'L', -13263=>'L', -13264=>'L', -13265=>'L', -13266=>'L', -13267=>'L', -13268=>'L', -13269=>'L', -13270=>'L', -13271=>'L', -13272=>'L', -13273=>'L', -13274=>'L', -13275=>'L', -13276=>'L', -13277=>'L', -13278=>'ON', -13279=>'ON', -13280=>'L', -13281=>'L', -13282=>'L', -13283=>'L', -13284=>'L', -13285=>'L', -13286=>'L', -13287=>'L', -13288=>'L', -13289=>'L', -13290=>'L', -13291=>'L', -13292=>'L', -13293=>'L', -13294=>'L', -13295=>'L', -13296=>'L', -13297=>'L', -13298=>'L', -13299=>'L', -13300=>'L', -13301=>'L', -13302=>'L', -13303=>'L', -13304=>'L', -13305=>'L', -13306=>'L', -13307=>'L', -13308=>'L', -13309=>'L', -13310=>'L', -13311=>'ON', -13312=>'L', -19893=>'L', -19904=>'ON', -19905=>'ON', -19906=>'ON', -19907=>'ON', -19908=>'ON', -19909=>'ON', -19910=>'ON', -19911=>'ON', -19912=>'ON', -19913=>'ON', -19914=>'ON', -19915=>'ON', -19916=>'ON', -19917=>'ON', -19918=>'ON', -19919=>'ON', -19920=>'ON', -19921=>'ON', -19922=>'ON', -19923=>'ON', -19924=>'ON', -19925=>'ON', -19926=>'ON', -19927=>'ON', -19928=>'ON', -19929=>'ON', -19930=>'ON', -19931=>'ON', -19932=>'ON', -19933=>'ON', -19934=>'ON', -19935=>'ON', -19936=>'ON', -19937=>'ON', -19938=>'ON', -19939=>'ON', -19940=>'ON', -19941=>'ON', -19942=>'ON', -19943=>'ON', -19944=>'ON', -19945=>'ON', -19946=>'ON', -19947=>'ON', -19948=>'ON', -19949=>'ON', -19950=>'ON', -19951=>'ON', -19952=>'ON', -19953=>'ON', -19954=>'ON', -19955=>'ON', -19956=>'ON', -19957=>'ON', -19958=>'ON', -19959=>'ON', -19960=>'ON', -19961=>'ON', -19962=>'ON', -19963=>'ON', -19964=>'ON', -19965=>'ON', -19966=>'ON', -19967=>'ON', -19968=>'L', -40891=>'L', -40960=>'L', -40961=>'L', -40962=>'L', -40963=>'L', -40964=>'L', -40965=>'L', -40966=>'L', -40967=>'L', -40968=>'L', -40969=>'L', -40970=>'L', -40971=>'L', -40972=>'L', -40973=>'L', -40974=>'L', -40975=>'L', -40976=>'L', -40977=>'L', -40978=>'L', -40979=>'L', -40980=>'L', -40981=>'L', -40982=>'L', -40983=>'L', -40984=>'L', -40985=>'L', -40986=>'L', -40987=>'L', -40988=>'L', -40989=>'L', -40990=>'L', -40991=>'L', -40992=>'L', -40993=>'L', -40994=>'L', -40995=>'L', -40996=>'L', -40997=>'L', -40998=>'L', -40999=>'L', -41000=>'L', -41001=>'L', -41002=>'L', -41003=>'L', -41004=>'L', -41005=>'L', -41006=>'L', -41007=>'L', -41008=>'L', -41009=>'L', -41010=>'L', -41011=>'L', -41012=>'L', -41013=>'L', -41014=>'L', -41015=>'L', -41016=>'L', -41017=>'L', -41018=>'L', -41019=>'L', -41020=>'L', -41021=>'L', -41022=>'L', -41023=>'L', -41024=>'L', -41025=>'L', -41026=>'L', -41027=>'L', -41028=>'L', -41029=>'L', -41030=>'L', -41031=>'L', -41032=>'L', -41033=>'L', -41034=>'L', -41035=>'L', -41036=>'L', -41037=>'L', -41038=>'L', -41039=>'L', -41040=>'L', -41041=>'L', -41042=>'L', -41043=>'L', -41044=>'L', -41045=>'L', -41046=>'L', -41047=>'L', -41048=>'L', -41049=>'L', -41050=>'L', -41051=>'L', -41052=>'L', -41053=>'L', -41054=>'L', -41055=>'L', -41056=>'L', -41057=>'L', -41058=>'L', -41059=>'L', -41060=>'L', -41061=>'L', -41062=>'L', -41063=>'L', -41064=>'L', -41065=>'L', -41066=>'L', -41067=>'L', -41068=>'L', -41069=>'L', -41070=>'L', -41071=>'L', -41072=>'L', -41073=>'L', -41074=>'L', -41075=>'L', -41076=>'L', -41077=>'L', -41078=>'L', -41079=>'L', -41080=>'L', -41081=>'L', -41082=>'L', -41083=>'L', -41084=>'L', -41085=>'L', -41086=>'L', -41087=>'L', -41088=>'L', -41089=>'L', -41090=>'L', -41091=>'L', -41092=>'L', -41093=>'L', -41094=>'L', -41095=>'L', -41096=>'L', -41097=>'L', -41098=>'L', -41099=>'L', -41100=>'L', -41101=>'L', -41102=>'L', -41103=>'L', -41104=>'L', -41105=>'L', -41106=>'L', -41107=>'L', -41108=>'L', -41109=>'L', -41110=>'L', -41111=>'L', -41112=>'L', -41113=>'L', -41114=>'L', -41115=>'L', -41116=>'L', -41117=>'L', -41118=>'L', -41119=>'L', -41120=>'L', -41121=>'L', -41122=>'L', -41123=>'L', -41124=>'L', -41125=>'L', -41126=>'L', -41127=>'L', -41128=>'L', -41129=>'L', -41130=>'L', -41131=>'L', -41132=>'L', -41133=>'L', -41134=>'L', -41135=>'L', -41136=>'L', -41137=>'L', -41138=>'L', -41139=>'L', -41140=>'L', -41141=>'L', -41142=>'L', -41143=>'L', -41144=>'L', -41145=>'L', -41146=>'L', -41147=>'L', -41148=>'L', -41149=>'L', -41150=>'L', -41151=>'L', -41152=>'L', -41153=>'L', -41154=>'L', -41155=>'L', -41156=>'L', -41157=>'L', -41158=>'L', -41159=>'L', -41160=>'L', -41161=>'L', -41162=>'L', -41163=>'L', -41164=>'L', -41165=>'L', -41166=>'L', -41167=>'L', -41168=>'L', -41169=>'L', -41170=>'L', -41171=>'L', -41172=>'L', -41173=>'L', -41174=>'L', -41175=>'L', -41176=>'L', -41177=>'L', -41178=>'L', -41179=>'L', -41180=>'L', -41181=>'L', -41182=>'L', -41183=>'L', -41184=>'L', -41185=>'L', -41186=>'L', -41187=>'L', -41188=>'L', -41189=>'L', -41190=>'L', -41191=>'L', -41192=>'L', -41193=>'L', -41194=>'L', -41195=>'L', -41196=>'L', -41197=>'L', -41198=>'L', -41199=>'L', -41200=>'L', -41201=>'L', -41202=>'L', -41203=>'L', -41204=>'L', -41205=>'L', -41206=>'L', -41207=>'L', -41208=>'L', -41209=>'L', -41210=>'L', -41211=>'L', -41212=>'L', -41213=>'L', -41214=>'L', -41215=>'L', -41216=>'L', -41217=>'L', -41218=>'L', -41219=>'L', -41220=>'L', -41221=>'L', -41222=>'L', -41223=>'L', -41224=>'L', -41225=>'L', -41226=>'L', -41227=>'L', -41228=>'L', -41229=>'L', -41230=>'L', -41231=>'L', -41232=>'L', -41233=>'L', -41234=>'L', -41235=>'L', -41236=>'L', -41237=>'L', -41238=>'L', -41239=>'L', -41240=>'L', -41241=>'L', -41242=>'L', -41243=>'L', -41244=>'L', -41245=>'L', -41246=>'L', -41247=>'L', -41248=>'L', -41249=>'L', -41250=>'L', -41251=>'L', -41252=>'L', -41253=>'L', -41254=>'L', -41255=>'L', -41256=>'L', -41257=>'L', -41258=>'L', -41259=>'L', -41260=>'L', -41261=>'L', -41262=>'L', -41263=>'L', -41264=>'L', -41265=>'L', -41266=>'L', -41267=>'L', -41268=>'L', -41269=>'L', -41270=>'L', -41271=>'L', -41272=>'L', -41273=>'L', -41274=>'L', -41275=>'L', -41276=>'L', -41277=>'L', -41278=>'L', -41279=>'L', -41280=>'L', -41281=>'L', -41282=>'L', -41283=>'L', -41284=>'L', -41285=>'L', -41286=>'L', -41287=>'L', -41288=>'L', -41289=>'L', -41290=>'L', -41291=>'L', -41292=>'L', -41293=>'L', -41294=>'L', -41295=>'L', -41296=>'L', -41297=>'L', -41298=>'L', -41299=>'L', -41300=>'L', -41301=>'L', -41302=>'L', -41303=>'L', -41304=>'L', -41305=>'L', -41306=>'L', -41307=>'L', -41308=>'L', -41309=>'L', -41310=>'L', -41311=>'L', -41312=>'L', -41313=>'L', -41314=>'L', -41315=>'L', -41316=>'L', -41317=>'L', -41318=>'L', -41319=>'L', -41320=>'L', -41321=>'L', -41322=>'L', -41323=>'L', -41324=>'L', -41325=>'L', -41326=>'L', -41327=>'L', -41328=>'L', -41329=>'L', -41330=>'L', -41331=>'L', -41332=>'L', -41333=>'L', -41334=>'L', -41335=>'L', -41336=>'L', -41337=>'L', -41338=>'L', -41339=>'L', -41340=>'L', -41341=>'L', -41342=>'L', -41343=>'L', -41344=>'L', -41345=>'L', -41346=>'L', -41347=>'L', -41348=>'L', -41349=>'L', -41350=>'L', -41351=>'L', -41352=>'L', -41353=>'L', -41354=>'L', -41355=>'L', -41356=>'L', -41357=>'L', -41358=>'L', -41359=>'L', -41360=>'L', -41361=>'L', -41362=>'L', -41363=>'L', -41364=>'L', -41365=>'L', -41366=>'L', -41367=>'L', -41368=>'L', -41369=>'L', -41370=>'L', -41371=>'L', -41372=>'L', -41373=>'L', -41374=>'L', -41375=>'L', -41376=>'L', -41377=>'L', -41378=>'L', -41379=>'L', -41380=>'L', -41381=>'L', -41382=>'L', -41383=>'L', -41384=>'L', -41385=>'L', -41386=>'L', -41387=>'L', -41388=>'L', -41389=>'L', -41390=>'L', -41391=>'L', -41392=>'L', -41393=>'L', -41394=>'L', -41395=>'L', -41396=>'L', -41397=>'L', -41398=>'L', -41399=>'L', -41400=>'L', -41401=>'L', -41402=>'L', -41403=>'L', -41404=>'L', -41405=>'L', -41406=>'L', -41407=>'L', -41408=>'L', -41409=>'L', -41410=>'L', -41411=>'L', -41412=>'L', -41413=>'L', -41414=>'L', -41415=>'L', -41416=>'L', -41417=>'L', -41418=>'L', -41419=>'L', -41420=>'L', -41421=>'L', -41422=>'L', -41423=>'L', -41424=>'L', -41425=>'L', -41426=>'L', -41427=>'L', -41428=>'L', -41429=>'L', -41430=>'L', -41431=>'L', -41432=>'L', -41433=>'L', -41434=>'L', -41435=>'L', -41436=>'L', -41437=>'L', -41438=>'L', -41439=>'L', -41440=>'L', -41441=>'L', -41442=>'L', -41443=>'L', -41444=>'L', -41445=>'L', -41446=>'L', -41447=>'L', -41448=>'L', -41449=>'L', -41450=>'L', -41451=>'L', -41452=>'L', -41453=>'L', -41454=>'L', -41455=>'L', -41456=>'L', -41457=>'L', -41458=>'L', -41459=>'L', -41460=>'L', -41461=>'L', -41462=>'L', -41463=>'L', -41464=>'L', -41465=>'L', -41466=>'L', -41467=>'L', -41468=>'L', -41469=>'L', -41470=>'L', -41471=>'L', -41472=>'L', -41473=>'L', -41474=>'L', -41475=>'L', -41476=>'L', -41477=>'L', -41478=>'L', -41479=>'L', -41480=>'L', -41481=>'L', -41482=>'L', -41483=>'L', -41484=>'L', -41485=>'L', -41486=>'L', -41487=>'L', -41488=>'L', -41489=>'L', -41490=>'L', -41491=>'L', -41492=>'L', -41493=>'L', -41494=>'L', -41495=>'L', -41496=>'L', -41497=>'L', -41498=>'L', -41499=>'L', -41500=>'L', -41501=>'L', -41502=>'L', -41503=>'L', -41504=>'L', -41505=>'L', -41506=>'L', -41507=>'L', -41508=>'L', -41509=>'L', -41510=>'L', -41511=>'L', -41512=>'L', -41513=>'L', -41514=>'L', -41515=>'L', -41516=>'L', -41517=>'L', -41518=>'L', -41519=>'L', -41520=>'L', -41521=>'L', -41522=>'L', -41523=>'L', -41524=>'L', -41525=>'L', -41526=>'L', -41527=>'L', -41528=>'L', -41529=>'L', -41530=>'L', -41531=>'L', -41532=>'L', -41533=>'L', -41534=>'L', -41535=>'L', -41536=>'L', -41537=>'L', -41538=>'L', -41539=>'L', -41540=>'L', -41541=>'L', -41542=>'L', -41543=>'L', -41544=>'L', -41545=>'L', -41546=>'L', -41547=>'L', -41548=>'L', -41549=>'L', -41550=>'L', -41551=>'L', -41552=>'L', -41553=>'L', -41554=>'L', -41555=>'L', -41556=>'L', -41557=>'L', -41558=>'L', -41559=>'L', -41560=>'L', -41561=>'L', -41562=>'L', -41563=>'L', -41564=>'L', -41565=>'L', -41566=>'L', -41567=>'L', -41568=>'L', -41569=>'L', -41570=>'L', -41571=>'L', -41572=>'L', -41573=>'L', -41574=>'L', -41575=>'L', -41576=>'L', -41577=>'L', -41578=>'L', -41579=>'L', -41580=>'L', -41581=>'L', -41582=>'L', -41583=>'L', -41584=>'L', -41585=>'L', -41586=>'L', -41587=>'L', -41588=>'L', -41589=>'L', -41590=>'L', -41591=>'L', -41592=>'L', -41593=>'L', -41594=>'L', -41595=>'L', -41596=>'L', -41597=>'L', -41598=>'L', -41599=>'L', -41600=>'L', -41601=>'L', -41602=>'L', -41603=>'L', -41604=>'L', -41605=>'L', -41606=>'L', -41607=>'L', -41608=>'L', -41609=>'L', -41610=>'L', -41611=>'L', -41612=>'L', -41613=>'L', -41614=>'L', -41615=>'L', -41616=>'L', -41617=>'L', -41618=>'L', -41619=>'L', -41620=>'L', -41621=>'L', -41622=>'L', -41623=>'L', -41624=>'L', -41625=>'L', -41626=>'L', -41627=>'L', -41628=>'L', -41629=>'L', -41630=>'L', -41631=>'L', -41632=>'L', -41633=>'L', -41634=>'L', -41635=>'L', -41636=>'L', -41637=>'L', -41638=>'L', -41639=>'L', -41640=>'L', -41641=>'L', -41642=>'L', -41643=>'L', -41644=>'L', -41645=>'L', -41646=>'L', -41647=>'L', -41648=>'L', -41649=>'L', -41650=>'L', -41651=>'L', -41652=>'L', -41653=>'L', -41654=>'L', -41655=>'L', -41656=>'L', -41657=>'L', -41658=>'L', -41659=>'L', -41660=>'L', -41661=>'L', -41662=>'L', -41663=>'L', -41664=>'L', -41665=>'L', -41666=>'L', -41667=>'L', -41668=>'L', -41669=>'L', -41670=>'L', -41671=>'L', -41672=>'L', -41673=>'L', -41674=>'L', -41675=>'L', -41676=>'L', -41677=>'L', -41678=>'L', -41679=>'L', -41680=>'L', -41681=>'L', -41682=>'L', -41683=>'L', -41684=>'L', -41685=>'L', -41686=>'L', -41687=>'L', -41688=>'L', -41689=>'L', -41690=>'L', -41691=>'L', -41692=>'L', -41693=>'L', -41694=>'L', -41695=>'L', -41696=>'L', -41697=>'L', -41698=>'L', -41699=>'L', -41700=>'L', -41701=>'L', -41702=>'L', -41703=>'L', -41704=>'L', -41705=>'L', -41706=>'L', -41707=>'L', -41708=>'L', -41709=>'L', -41710=>'L', -41711=>'L', -41712=>'L', -41713=>'L', -41714=>'L', -41715=>'L', -41716=>'L', -41717=>'L', -41718=>'L', -41719=>'L', -41720=>'L', -41721=>'L', -41722=>'L', -41723=>'L', -41724=>'L', -41725=>'L', -41726=>'L', -41727=>'L', -41728=>'L', -41729=>'L', -41730=>'L', -41731=>'L', -41732=>'L', -41733=>'L', -41734=>'L', -41735=>'L', -41736=>'L', -41737=>'L', -41738=>'L', -41739=>'L', -41740=>'L', -41741=>'L', -41742=>'L', -41743=>'L', -41744=>'L', -41745=>'L', -41746=>'L', -41747=>'L', -41748=>'L', -41749=>'L', -41750=>'L', -41751=>'L', -41752=>'L', -41753=>'L', -41754=>'L', -41755=>'L', -41756=>'L', -41757=>'L', -41758=>'L', -41759=>'L', -41760=>'L', -41761=>'L', -41762=>'L', -41763=>'L', -41764=>'L', -41765=>'L', -41766=>'L', -41767=>'L', -41768=>'L', -41769=>'L', -41770=>'L', -41771=>'L', -41772=>'L', -41773=>'L', -41774=>'L', -41775=>'L', -41776=>'L', -41777=>'L', -41778=>'L', -41779=>'L', -41780=>'L', -41781=>'L', -41782=>'L', -41783=>'L', -41784=>'L', -41785=>'L', -41786=>'L', -41787=>'L', -41788=>'L', -41789=>'L', -41790=>'L', -41791=>'L', -41792=>'L', -41793=>'L', -41794=>'L', -41795=>'L', -41796=>'L', -41797=>'L', -41798=>'L', -41799=>'L', -41800=>'L', -41801=>'L', -41802=>'L', -41803=>'L', -41804=>'L', -41805=>'L', -41806=>'L', -41807=>'L', -41808=>'L', -41809=>'L', -41810=>'L', -41811=>'L', -41812=>'L', -41813=>'L', -41814=>'L', -41815=>'L', -41816=>'L', -41817=>'L', -41818=>'L', -41819=>'L', -41820=>'L', -41821=>'L', -41822=>'L', -41823=>'L', -41824=>'L', -41825=>'L', -41826=>'L', -41827=>'L', -41828=>'L', -41829=>'L', -41830=>'L', -41831=>'L', -41832=>'L', -41833=>'L', -41834=>'L', -41835=>'L', -41836=>'L', -41837=>'L', -41838=>'L', -41839=>'L', -41840=>'L', -41841=>'L', -41842=>'L', -41843=>'L', -41844=>'L', -41845=>'L', -41846=>'L', -41847=>'L', -41848=>'L', -41849=>'L', -41850=>'L', -41851=>'L', -41852=>'L', -41853=>'L', -41854=>'L', -41855=>'L', -41856=>'L', -41857=>'L', -41858=>'L', -41859=>'L', -41860=>'L', -41861=>'L', -41862=>'L', -41863=>'L', -41864=>'L', -41865=>'L', -41866=>'L', -41867=>'L', -41868=>'L', -41869=>'L', -41870=>'L', -41871=>'L', -41872=>'L', -41873=>'L', -41874=>'L', -41875=>'L', -41876=>'L', -41877=>'L', -41878=>'L', -41879=>'L', -41880=>'L', -41881=>'L', -41882=>'L', -41883=>'L', -41884=>'L', -41885=>'L', -41886=>'L', -41887=>'L', -41888=>'L', -41889=>'L', -41890=>'L', -41891=>'L', -41892=>'L', -41893=>'L', -41894=>'L', -41895=>'L', -41896=>'L', -41897=>'L', -41898=>'L', -41899=>'L', -41900=>'L', -41901=>'L', -41902=>'L', -41903=>'L', -41904=>'L', -41905=>'L', -41906=>'L', -41907=>'L', -41908=>'L', -41909=>'L', -41910=>'L', -41911=>'L', -41912=>'L', -41913=>'L', -41914=>'L', -41915=>'L', -41916=>'L', -41917=>'L', -41918=>'L', -41919=>'L', -41920=>'L', -41921=>'L', -41922=>'L', -41923=>'L', -41924=>'L', -41925=>'L', -41926=>'L', -41927=>'L', -41928=>'L', -41929=>'L', -41930=>'L', -41931=>'L', -41932=>'L', -41933=>'L', -41934=>'L', -41935=>'L', -41936=>'L', -41937=>'L', -41938=>'L', -41939=>'L', -41940=>'L', -41941=>'L', -41942=>'L', -41943=>'L', -41944=>'L', -41945=>'L', -41946=>'L', -41947=>'L', -41948=>'L', -41949=>'L', -41950=>'L', -41951=>'L', -41952=>'L', -41953=>'L', -41954=>'L', -41955=>'L', -41956=>'L', -41957=>'L', -41958=>'L', -41959=>'L', -41960=>'L', -41961=>'L', -41962=>'L', -41963=>'L', -41964=>'L', -41965=>'L', -41966=>'L', -41967=>'L', -41968=>'L', -41969=>'L', -41970=>'L', -41971=>'L', -41972=>'L', -41973=>'L', -41974=>'L', -41975=>'L', -41976=>'L', -41977=>'L', -41978=>'L', -41979=>'L', -41980=>'L', -41981=>'L', -41982=>'L', -41983=>'L', -41984=>'L', -41985=>'L', -41986=>'L', -41987=>'L', -41988=>'L', -41989=>'L', -41990=>'L', -41991=>'L', -41992=>'L', -41993=>'L', -41994=>'L', -41995=>'L', -41996=>'L', -41997=>'L', -41998=>'L', -41999=>'L', -42000=>'L', -42001=>'L', -42002=>'L', -42003=>'L', -42004=>'L', -42005=>'L', -42006=>'L', -42007=>'L', -42008=>'L', -42009=>'L', -42010=>'L', -42011=>'L', -42012=>'L', -42013=>'L', -42014=>'L', -42015=>'L', -42016=>'L', -42017=>'L', -42018=>'L', -42019=>'L', -42020=>'L', -42021=>'L', -42022=>'L', -42023=>'L', -42024=>'L', -42025=>'L', -42026=>'L', -42027=>'L', -42028=>'L', -42029=>'L', -42030=>'L', -42031=>'L', -42032=>'L', -42033=>'L', -42034=>'L', -42035=>'L', -42036=>'L', -42037=>'L', -42038=>'L', -42039=>'L', -42040=>'L', -42041=>'L', -42042=>'L', -42043=>'L', -42044=>'L', -42045=>'L', -42046=>'L', -42047=>'L', -42048=>'L', -42049=>'L', -42050=>'L', -42051=>'L', -42052=>'L', -42053=>'L', -42054=>'L', -42055=>'L', -42056=>'L', -42057=>'L', -42058=>'L', -42059=>'L', -42060=>'L', -42061=>'L', -42062=>'L', -42063=>'L', -42064=>'L', -42065=>'L', -42066=>'L', -42067=>'L', -42068=>'L', -42069=>'L', -42070=>'L', -42071=>'L', -42072=>'L', -42073=>'L', -42074=>'L', -42075=>'L', -42076=>'L', -42077=>'L', -42078=>'L', -42079=>'L', -42080=>'L', -42081=>'L', -42082=>'L', -42083=>'L', -42084=>'L', -42085=>'L', -42086=>'L', -42087=>'L', -42088=>'L', -42089=>'L', -42090=>'L', -42091=>'L', -42092=>'L', -42093=>'L', -42094=>'L', -42095=>'L', -42096=>'L', -42097=>'L', -42098=>'L', -42099=>'L', -42100=>'L', -42101=>'L', -42102=>'L', -42103=>'L', -42104=>'L', -42105=>'L', -42106=>'L', -42107=>'L', -42108=>'L', -42109=>'L', -42110=>'L', -42111=>'L', -42112=>'L', -42113=>'L', -42114=>'L', -42115=>'L', -42116=>'L', -42117=>'L', -42118=>'L', -42119=>'L', -42120=>'L', -42121=>'L', -42122=>'L', -42123=>'L', -42124=>'L', -42128=>'ON', -42129=>'ON', -42130=>'ON', -42131=>'ON', -42132=>'ON', -42133=>'ON', -42134=>'ON', -42135=>'ON', -42136=>'ON', -42137=>'ON', -42138=>'ON', -42139=>'ON', -42140=>'ON', -42141=>'ON', -42142=>'ON', -42143=>'ON', -42144=>'ON', -42145=>'ON', -42146=>'ON', -42147=>'ON', -42148=>'ON', -42149=>'ON', -42150=>'ON', -42151=>'ON', -42152=>'ON', -42153=>'ON', -42154=>'ON', -42155=>'ON', -42156=>'ON', -42157=>'ON', -42158=>'ON', -42159=>'ON', -42160=>'ON', -42161=>'ON', -42162=>'ON', -42163=>'ON', -42164=>'ON', -42165=>'ON', -42166=>'ON', -42167=>'ON', -42168=>'ON', -42169=>'ON', -42170=>'ON', -42171=>'ON', -42172=>'ON', -42173=>'ON', -42174=>'ON', -42175=>'ON', -42176=>'ON', -42177=>'ON', -42178=>'ON', -42179=>'ON', -42180=>'ON', -42181=>'ON', -42182=>'ON', -42752=>'ON', -42753=>'ON', -42754=>'ON', -42755=>'ON', -42756=>'ON', -42757=>'ON', -42758=>'ON', -42759=>'ON', -42760=>'ON', -42761=>'ON', -42762=>'ON', -42763=>'ON', -42764=>'ON', -42765=>'ON', -42766=>'ON', -42767=>'ON', -42768=>'ON', -42769=>'ON', -42770=>'ON', -42771=>'ON', -42772=>'ON', -42773=>'ON', -42774=>'ON', -42775=>'ON', -42776=>'ON', -42777=>'ON', -42778=>'ON', -42784=>'ON', -42785=>'ON', -43008=>'L', -43009=>'L', -43010=>'NSM', -43011=>'L', -43012=>'L', -43013=>'L', -43014=>'NSM', -43015=>'L', -43016=>'L', -43017=>'L', -43018=>'L', -43019=>'NSM', -43020=>'L', -43021=>'L', -43022=>'L', -43023=>'L', -43024=>'L', -43025=>'L', -43026=>'L', -43027=>'L', -43028=>'L', -43029=>'L', -43030=>'L', -43031=>'L', -43032=>'L', -43033=>'L', -43034=>'L', -43035=>'L', -43036=>'L', -43037=>'L', -43038=>'L', -43039=>'L', -43040=>'L', -43041=>'L', -43042=>'L', -43043=>'L', -43044=>'L', -43045=>'NSM', -43046=>'NSM', -43047=>'L', -43048=>'ON', -43049=>'ON', -43050=>'ON', -43051=>'ON', -43072=>'L', -43073=>'L', -43074=>'L', -43075=>'L', -43076=>'L', -43077=>'L', -43078=>'L', -43079=>'L', -43080=>'L', -43081=>'L', -43082=>'L', -43083=>'L', -43084=>'L', -43085=>'L', -43086=>'L', -43087=>'L', -43088=>'L', -43089=>'L', -43090=>'L', -43091=>'L', -43092=>'L', -43093=>'L', -43094=>'L', -43095=>'L', -43096=>'L', -43097=>'L', -43098=>'L', -43099=>'L', -43100=>'L', -43101=>'L', -43102=>'L', -43103=>'L', -43104=>'L', -43105=>'L', -43106=>'L', -43107=>'L', -43108=>'L', -43109=>'L', -43110=>'L', -43111=>'L', -43112=>'L', -43113=>'L', -43114=>'L', -43115=>'L', -43116=>'L', -43117=>'L', -43118=>'L', -43119=>'L', -43120=>'L', -43121=>'L', -43122=>'L', -43123=>'L', -43124=>'ON', -43125=>'ON', -43126=>'ON', -43127=>'ON', -44032=>'L', -55203=>'L', -55296=>'L', -56191=>'L', -56192=>'L', -56319=>'L', -56320=>'L', -57343=>'L', -57344=>'L', -63743=>'L', -63744=>'L', -63745=>'L', -63746=>'L', -63747=>'L', -63748=>'L', -63749=>'L', -63750=>'L', -63751=>'L', -63752=>'L', -63753=>'L', -63754=>'L', -63755=>'L', -63756=>'L', -63757=>'L', -63758=>'L', -63759=>'L', -63760=>'L', -63761=>'L', -63762=>'L', -63763=>'L', -63764=>'L', -63765=>'L', -63766=>'L', -63767=>'L', -63768=>'L', -63769=>'L', -63770=>'L', -63771=>'L', -63772=>'L', -63773=>'L', -63774=>'L', -63775=>'L', -63776=>'L', -63777=>'L', -63778=>'L', -63779=>'L', -63780=>'L', -63781=>'L', -63782=>'L', -63783=>'L', -63784=>'L', -63785=>'L', -63786=>'L', -63787=>'L', -63788=>'L', -63789=>'L', -63790=>'L', -63791=>'L', -63792=>'L', -63793=>'L', -63794=>'L', -63795=>'L', -63796=>'L', -63797=>'L', -63798=>'L', -63799=>'L', -63800=>'L', -63801=>'L', -63802=>'L', -63803=>'L', -63804=>'L', -63805=>'L', -63806=>'L', -63807=>'L', -63808=>'L', -63809=>'L', -63810=>'L', -63811=>'L', -63812=>'L', -63813=>'L', -63814=>'L', -63815=>'L', -63816=>'L', -63817=>'L', -63818=>'L', -63819=>'L', -63820=>'L', -63821=>'L', -63822=>'L', -63823=>'L', -63824=>'L', -63825=>'L', -63826=>'L', -63827=>'L', -63828=>'L', -63829=>'L', -63830=>'L', -63831=>'L', -63832=>'L', -63833=>'L', -63834=>'L', -63835=>'L', -63836=>'L', -63837=>'L', -63838=>'L', -63839=>'L', -63840=>'L', -63841=>'L', -63842=>'L', -63843=>'L', -63844=>'L', -63845=>'L', -63846=>'L', -63847=>'L', -63848=>'L', -63849=>'L', -63850=>'L', -63851=>'L', -63852=>'L', -63853=>'L', -63854=>'L', -63855=>'L', -63856=>'L', -63857=>'L', -63858=>'L', -63859=>'L', -63860=>'L', -63861=>'L', -63862=>'L', -63863=>'L', -63864=>'L', -63865=>'L', -63866=>'L', -63867=>'L', -63868=>'L', -63869=>'L', -63870=>'L', -63871=>'L', -63872=>'L', -63873=>'L', -63874=>'L', -63875=>'L', -63876=>'L', -63877=>'L', -63878=>'L', -63879=>'L', -63880=>'L', -63881=>'L', -63882=>'L', -63883=>'L', -63884=>'L', -63885=>'L', -63886=>'L', -63887=>'L', -63888=>'L', -63889=>'L', -63890=>'L', -63891=>'L', -63892=>'L', -63893=>'L', -63894=>'L', -63895=>'L', -63896=>'L', -63897=>'L', -63898=>'L', -63899=>'L', -63900=>'L', -63901=>'L', -63902=>'L', -63903=>'L', -63904=>'L', -63905=>'L', -63906=>'L', -63907=>'L', -63908=>'L', -63909=>'L', -63910=>'L', -63911=>'L', -63912=>'L', -63913=>'L', -63914=>'L', -63915=>'L', -63916=>'L', -63917=>'L', -63918=>'L', -63919=>'L', -63920=>'L', -63921=>'L', -63922=>'L', -63923=>'L', -63924=>'L', -63925=>'L', -63926=>'L', -63927=>'L', -63928=>'L', -63929=>'L', -63930=>'L', -63931=>'L', -63932=>'L', -63933=>'L', -63934=>'L', -63935=>'L', -63936=>'L', -63937=>'L', -63938=>'L', -63939=>'L', -63940=>'L', -63941=>'L', -63942=>'L', -63943=>'L', -63944=>'L', -63945=>'L', -63946=>'L', -63947=>'L', -63948=>'L', -63949=>'L', -63950=>'L', -63951=>'L', -63952=>'L', -63953=>'L', -63954=>'L', -63955=>'L', -63956=>'L', -63957=>'L', -63958=>'L', -63959=>'L', -63960=>'L', -63961=>'L', -63962=>'L', -63963=>'L', -63964=>'L', -63965=>'L', -63966=>'L', -63967=>'L', -63968=>'L', -63969=>'L', -63970=>'L', -63971=>'L', -63972=>'L', -63973=>'L', -63974=>'L', -63975=>'L', -63976=>'L', -63977=>'L', -63978=>'L', -63979=>'L', -63980=>'L', -63981=>'L', -63982=>'L', -63983=>'L', -63984=>'L', -63985=>'L', -63986=>'L', -63987=>'L', -63988=>'L', -63989=>'L', -63990=>'L', -63991=>'L', -63992=>'L', -63993=>'L', -63994=>'L', -63995=>'L', -63996=>'L', -63997=>'L', -63998=>'L', -63999=>'L', -64000=>'L', -64001=>'L', -64002=>'L', -64003=>'L', -64004=>'L', -64005=>'L', -64006=>'L', -64007=>'L', -64008=>'L', -64009=>'L', -64010=>'L', -64011=>'L', -64012=>'L', -64013=>'L', -64014=>'L', -64015=>'L', -64016=>'L', -64017=>'L', -64018=>'L', -64019=>'L', -64020=>'L', -64021=>'L', -64022=>'L', -64023=>'L', -64024=>'L', -64025=>'L', -64026=>'L', -64027=>'L', -64028=>'L', -64029=>'L', -64030=>'L', -64031=>'L', -64032=>'L', -64033=>'L', -64034=>'L', -64035=>'L', -64036=>'L', -64037=>'L', -64038=>'L', -64039=>'L', -64040=>'L', -64041=>'L', -64042=>'L', -64043=>'L', -64044=>'L', -64045=>'L', -64048=>'L', -64049=>'L', -64050=>'L', -64051=>'L', -64052=>'L', -64053=>'L', -64054=>'L', -64055=>'L', -64056=>'L', -64057=>'L', -64058=>'L', -64059=>'L', -64060=>'L', -64061=>'L', -64062=>'L', -64063=>'L', -64064=>'L', -64065=>'L', -64066=>'L', -64067=>'L', -64068=>'L', -64069=>'L', -64070=>'L', -64071=>'L', -64072=>'L', -64073=>'L', -64074=>'L', -64075=>'L', -64076=>'L', -64077=>'L', -64078=>'L', -64079=>'L', -64080=>'L', -64081=>'L', -64082=>'L', -64083=>'L', -64084=>'L', -64085=>'L', -64086=>'L', -64087=>'L', -64088=>'L', -64089=>'L', -64090=>'L', -64091=>'L', -64092=>'L', -64093=>'L', -64094=>'L', -64095=>'L', -64096=>'L', -64097=>'L', -64098=>'L', -64099=>'L', -64100=>'L', -64101=>'L', -64102=>'L', -64103=>'L', -64104=>'L', -64105=>'L', -64106=>'L', -64112=>'L', -64113=>'L', -64114=>'L', -64115=>'L', -64116=>'L', -64117=>'L', -64118=>'L', -64119=>'L', -64120=>'L', -64121=>'L', -64122=>'L', -64123=>'L', -64124=>'L', -64125=>'L', -64126=>'L', -64127=>'L', -64128=>'L', -64129=>'L', -64130=>'L', -64131=>'L', -64132=>'L', -64133=>'L', -64134=>'L', -64135=>'L', -64136=>'L', -64137=>'L', -64138=>'L', -64139=>'L', -64140=>'L', -64141=>'L', -64142=>'L', -64143=>'L', -64144=>'L', -64145=>'L', -64146=>'L', -64147=>'L', -64148=>'L', -64149=>'L', -64150=>'L', -64151=>'L', -64152=>'L', -64153=>'L', -64154=>'L', -64155=>'L', -64156=>'L', -64157=>'L', -64158=>'L', -64159=>'L', -64160=>'L', -64161=>'L', -64162=>'L', -64163=>'L', -64164=>'L', -64165=>'L', -64166=>'L', -64167=>'L', -64168=>'L', -64169=>'L', -64170=>'L', -64171=>'L', -64172=>'L', -64173=>'L', -64174=>'L', -64175=>'L', -64176=>'L', -64177=>'L', -64178=>'L', -64179=>'L', -64180=>'L', -64181=>'L', -64182=>'L', -64183=>'L', -64184=>'L', -64185=>'L', -64186=>'L', -64187=>'L', -64188=>'L', -64189=>'L', -64190=>'L', -64191=>'L', -64192=>'L', -64193=>'L', -64194=>'L', -64195=>'L', -64196=>'L', -64197=>'L', -64198=>'L', -64199=>'L', -64200=>'L', -64201=>'L', -64202=>'L', -64203=>'L', -64204=>'L', -64205=>'L', -64206=>'L', -64207=>'L', -64208=>'L', -64209=>'L', -64210=>'L', -64211=>'L', -64212=>'L', -64213=>'L', -64214=>'L', -64215=>'L', -64216=>'L', -64217=>'L', -64256=>'L', -64257=>'L', -64258=>'L', -64259=>'L', -64260=>'L', -64261=>'L', -64262=>'L', -64275=>'L', -64276=>'L', -64277=>'L', -64278=>'L', -64279=>'L', -64285=>'R', -64286=>'NSM', -64287=>'R', -64288=>'R', -64289=>'R', -64290=>'R', -64291=>'R', -64292=>'R', -64293=>'R', -64294=>'R', -64295=>'R', -64296=>'R', -64297=>'ES', -64298=>'R', -64299=>'R', -64300=>'R', -64301=>'R', -64302=>'R', -64303=>'R', -64304=>'R', -64305=>'R', -64306=>'R', -64307=>'R', -64308=>'R', -64309=>'R', -64310=>'R', -64312=>'R', -64313=>'R', -64314=>'R', -64315=>'R', -64316=>'R', -64318=>'R', -64320=>'R', -64321=>'R', -64323=>'R', -64324=>'R', -64326=>'R', -64327=>'R', -64328=>'R', -64329=>'R', -64330=>'R', -64331=>'R', -64332=>'R', -64333=>'R', -64334=>'R', -64335=>'R', -64336=>'AL', -64337=>'AL', -64338=>'AL', -64339=>'AL', -64340=>'AL', -64341=>'AL', -64342=>'AL', -64343=>'AL', -64344=>'AL', -64345=>'AL', -64346=>'AL', -64347=>'AL', -64348=>'AL', -64349=>'AL', -64350=>'AL', -64351=>'AL', -64352=>'AL', -64353=>'AL', -64354=>'AL', -64355=>'AL', -64356=>'AL', -64357=>'AL', -64358=>'AL', -64359=>'AL', -64360=>'AL', -64361=>'AL', -64362=>'AL', -64363=>'AL', -64364=>'AL', -64365=>'AL', -64366=>'AL', -64367=>'AL', -64368=>'AL', -64369=>'AL', -64370=>'AL', -64371=>'AL', -64372=>'AL', -64373=>'AL', -64374=>'AL', -64375=>'AL', -64376=>'AL', -64377=>'AL', -64378=>'AL', -64379=>'AL', -64380=>'AL', -64381=>'AL', -64382=>'AL', -64383=>'AL', -64384=>'AL', -64385=>'AL', -64386=>'AL', -64387=>'AL', -64388=>'AL', -64389=>'AL', -64390=>'AL', -64391=>'AL', -64392=>'AL', -64393=>'AL', -64394=>'AL', -64395=>'AL', -64396=>'AL', -64397=>'AL', -64398=>'AL', -64399=>'AL', -64400=>'AL', -64401=>'AL', -64402=>'AL', -64403=>'AL', -64404=>'AL', -64405=>'AL', -64406=>'AL', -64407=>'AL', -64408=>'AL', -64409=>'AL', -64410=>'AL', -64411=>'AL', -64412=>'AL', -64413=>'AL', -64414=>'AL', -64415=>'AL', -64416=>'AL', -64417=>'AL', -64418=>'AL', -64419=>'AL', -64420=>'AL', -64421=>'AL', -64422=>'AL', -64423=>'AL', -64424=>'AL', -64425=>'AL', -64426=>'AL', -64427=>'AL', -64428=>'AL', -64429=>'AL', -64430=>'AL', -64431=>'AL', -64432=>'AL', -64433=>'AL', -64467=>'AL', -64468=>'AL', -64469=>'AL', -64470=>'AL', -64471=>'AL', -64472=>'AL', -64473=>'AL', -64474=>'AL', -64475=>'AL', -64476=>'AL', -64477=>'AL', -64478=>'AL', -64479=>'AL', -64480=>'AL', -64481=>'AL', -64482=>'AL', -64483=>'AL', -64484=>'AL', -64485=>'AL', -64486=>'AL', -64487=>'AL', -64488=>'AL', -64489=>'AL', -64490=>'AL', -64491=>'AL', -64492=>'AL', -64493=>'AL', -64494=>'AL', -64495=>'AL', -64496=>'AL', -64497=>'AL', -64498=>'AL', -64499=>'AL', -64500=>'AL', -64501=>'AL', -64502=>'AL', -64503=>'AL', -64504=>'AL', -64505=>'AL', -64506=>'AL', -64507=>'AL', -64508=>'AL', -64509=>'AL', -64510=>'AL', -64511=>'AL', -64512=>'AL', -64513=>'AL', -64514=>'AL', -64515=>'AL', -64516=>'AL', -64517=>'AL', -64518=>'AL', -64519=>'AL', -64520=>'AL', -64521=>'AL', -64522=>'AL', -64523=>'AL', -64524=>'AL', -64525=>'AL', -64526=>'AL', -64527=>'AL', -64528=>'AL', -64529=>'AL', -64530=>'AL', -64531=>'AL', -64532=>'AL', -64533=>'AL', -64534=>'AL', -64535=>'AL', -64536=>'AL', -64537=>'AL', -64538=>'AL', -64539=>'AL', -64540=>'AL', -64541=>'AL', -64542=>'AL', -64543=>'AL', -64544=>'AL', -64545=>'AL', -64546=>'AL', -64547=>'AL', -64548=>'AL', -64549=>'AL', -64550=>'AL', -64551=>'AL', -64552=>'AL', -64553=>'AL', -64554=>'AL', -64555=>'AL', -64556=>'AL', -64557=>'AL', -64558=>'AL', -64559=>'AL', -64560=>'AL', -64561=>'AL', -64562=>'AL', -64563=>'AL', -64564=>'AL', -64565=>'AL', -64566=>'AL', -64567=>'AL', -64568=>'AL', -64569=>'AL', -64570=>'AL', -64571=>'AL', -64572=>'AL', -64573=>'AL', -64574=>'AL', -64575=>'AL', -64576=>'AL', -64577=>'AL', -64578=>'AL', -64579=>'AL', -64580=>'AL', -64581=>'AL', -64582=>'AL', -64583=>'AL', -64584=>'AL', -64585=>'AL', -64586=>'AL', -64587=>'AL', -64588=>'AL', -64589=>'AL', -64590=>'AL', -64591=>'AL', -64592=>'AL', -64593=>'AL', -64594=>'AL', -64595=>'AL', -64596=>'AL', -64597=>'AL', -64598=>'AL', -64599=>'AL', -64600=>'AL', -64601=>'AL', -64602=>'AL', -64603=>'AL', -64604=>'AL', -64605=>'AL', -64606=>'AL', -64607=>'AL', -64608=>'AL', -64609=>'AL', -64610=>'AL', -64611=>'AL', -64612=>'AL', -64613=>'AL', -64614=>'AL', -64615=>'AL', -64616=>'AL', -64617=>'AL', -64618=>'AL', -64619=>'AL', -64620=>'AL', -64621=>'AL', -64622=>'AL', -64623=>'AL', -64624=>'AL', -64625=>'AL', -64626=>'AL', -64627=>'AL', -64628=>'AL', -64629=>'AL', -64630=>'AL', -64631=>'AL', -64632=>'AL', -64633=>'AL', -64634=>'AL', -64635=>'AL', -64636=>'AL', -64637=>'AL', -64638=>'AL', -64639=>'AL', -64640=>'AL', -64641=>'AL', -64642=>'AL', -64643=>'AL', -64644=>'AL', -64645=>'AL', -64646=>'AL', -64647=>'AL', -64648=>'AL', -64649=>'AL', -64650=>'AL', -64651=>'AL', -64652=>'AL', -64653=>'AL', -64654=>'AL', -64655=>'AL', -64656=>'AL', -64657=>'AL', -64658=>'AL', -64659=>'AL', -64660=>'AL', -64661=>'AL', -64662=>'AL', -64663=>'AL', -64664=>'AL', -64665=>'AL', -64666=>'AL', -64667=>'AL', -64668=>'AL', -64669=>'AL', -64670=>'AL', -64671=>'AL', -64672=>'AL', -64673=>'AL', -64674=>'AL', -64675=>'AL', -64676=>'AL', -64677=>'AL', -64678=>'AL', -64679=>'AL', -64680=>'AL', -64681=>'AL', -64682=>'AL', -64683=>'AL', -64684=>'AL', -64685=>'AL', -64686=>'AL', -64687=>'AL', -64688=>'AL', -64689=>'AL', -64690=>'AL', -64691=>'AL', -64692=>'AL', -64693=>'AL', -64694=>'AL', -64695=>'AL', -64696=>'AL', -64697=>'AL', -64698=>'AL', -64699=>'AL', -64700=>'AL', -64701=>'AL', -64702=>'AL', -64703=>'AL', -64704=>'AL', -64705=>'AL', -64706=>'AL', -64707=>'AL', -64708=>'AL', -64709=>'AL', -64710=>'AL', -64711=>'AL', -64712=>'AL', -64713=>'AL', -64714=>'AL', -64715=>'AL', -64716=>'AL', -64717=>'AL', -64718=>'AL', -64719=>'AL', -64720=>'AL', -64721=>'AL', -64722=>'AL', -64723=>'AL', -64724=>'AL', -64725=>'AL', -64726=>'AL', -64727=>'AL', -64728=>'AL', -64729=>'AL', -64730=>'AL', -64731=>'AL', -64732=>'AL', -64733=>'AL', -64734=>'AL', -64735=>'AL', -64736=>'AL', -64737=>'AL', -64738=>'AL', -64739=>'AL', -64740=>'AL', -64741=>'AL', -64742=>'AL', -64743=>'AL', -64744=>'AL', -64745=>'AL', -64746=>'AL', -64747=>'AL', -64748=>'AL', -64749=>'AL', -64750=>'AL', -64751=>'AL', -64752=>'AL', -64753=>'AL', -64754=>'AL', -64755=>'AL', -64756=>'AL', -64757=>'AL', -64758=>'AL', -64759=>'AL', -64760=>'AL', -64761=>'AL', -64762=>'AL', -64763=>'AL', -64764=>'AL', -64765=>'AL', -64766=>'AL', -64767=>'AL', -64768=>'AL', -64769=>'AL', -64770=>'AL', -64771=>'AL', -64772=>'AL', -64773=>'AL', -64774=>'AL', -64775=>'AL', -64776=>'AL', -64777=>'AL', -64778=>'AL', -64779=>'AL', -64780=>'AL', -64781=>'AL', -64782=>'AL', -64783=>'AL', -64784=>'AL', -64785=>'AL', -64786=>'AL', -64787=>'AL', -64788=>'AL', -64789=>'AL', -64790=>'AL', -64791=>'AL', -64792=>'AL', -64793=>'AL', -64794=>'AL', -64795=>'AL', -64796=>'AL', -64797=>'AL', -64798=>'AL', -64799=>'AL', -64800=>'AL', -64801=>'AL', -64802=>'AL', -64803=>'AL', -64804=>'AL', -64805=>'AL', -64806=>'AL', -64807=>'AL', -64808=>'AL', -64809=>'AL', -64810=>'AL', -64811=>'AL', -64812=>'AL', -64813=>'AL', -64814=>'AL', -64815=>'AL', -64816=>'AL', -64817=>'AL', -64818=>'AL', -64819=>'AL', -64820=>'AL', -64821=>'AL', -64822=>'AL', -64823=>'AL', -64824=>'AL', -64825=>'AL', -64826=>'AL', -64827=>'AL', -64828=>'AL', -64829=>'AL', -64830=>'ON', -64831=>'ON', -64848=>'AL', -64849=>'AL', -64850=>'AL', -64851=>'AL', -64852=>'AL', -64853=>'AL', -64854=>'AL', -64855=>'AL', -64856=>'AL', -64857=>'AL', -64858=>'AL', -64859=>'AL', -64860=>'AL', -64861=>'AL', -64862=>'AL', -64863=>'AL', -64864=>'AL', -64865=>'AL', -64866=>'AL', -64867=>'AL', -64868=>'AL', -64869=>'AL', -64870=>'AL', -64871=>'AL', -64872=>'AL', -64873=>'AL', -64874=>'AL', -64875=>'AL', -64876=>'AL', -64877=>'AL', -64878=>'AL', -64879=>'AL', -64880=>'AL', -64881=>'AL', -64882=>'AL', -64883=>'AL', -64884=>'AL', -64885=>'AL', -64886=>'AL', -64887=>'AL', -64888=>'AL', -64889=>'AL', -64890=>'AL', -64891=>'AL', -64892=>'AL', -64893=>'AL', -64894=>'AL', -64895=>'AL', -64896=>'AL', -64897=>'AL', -64898=>'AL', -64899=>'AL', -64900=>'AL', -64901=>'AL', -64902=>'AL', -64903=>'AL', -64904=>'AL', -64905=>'AL', -64906=>'AL', -64907=>'AL', -64908=>'AL', -64909=>'AL', -64910=>'AL', -64911=>'AL', -64914=>'AL', -64915=>'AL', -64916=>'AL', -64917=>'AL', -64918=>'AL', -64919=>'AL', -64920=>'AL', -64921=>'AL', -64922=>'AL', -64923=>'AL', -64924=>'AL', -64925=>'AL', -64926=>'AL', -64927=>'AL', -64928=>'AL', -64929=>'AL', -64930=>'AL', -64931=>'AL', -64932=>'AL', -64933=>'AL', -64934=>'AL', -64935=>'AL', -64936=>'AL', -64937=>'AL', -64938=>'AL', -64939=>'AL', -64940=>'AL', -64941=>'AL', -64942=>'AL', -64943=>'AL', -64944=>'AL', -64945=>'AL', -64946=>'AL', -64947=>'AL', -64948=>'AL', -64949=>'AL', -64950=>'AL', -64951=>'AL', -64952=>'AL', -64953=>'AL', -64954=>'AL', -64955=>'AL', -64956=>'AL', -64957=>'AL', -64958=>'AL', -64959=>'AL', -64960=>'AL', -64961=>'AL', -64962=>'AL', -64963=>'AL', -64964=>'AL', -64965=>'AL', -64966=>'AL', -64967=>'AL', -65008=>'AL', -65009=>'AL', -65010=>'AL', -65011=>'AL', -65012=>'AL', -65013=>'AL', -65014=>'AL', -65015=>'AL', -65016=>'AL', -65017=>'AL', -65018=>'AL', -65019=>'AL', -65020=>'AL', -65021=>'ON', -65024=>'NSM', -65025=>'NSM', -65026=>'NSM', -65027=>'NSM', -65028=>'NSM', -65029=>'NSM', -65030=>'NSM', -65031=>'NSM', -65032=>'NSM', -65033=>'NSM', -65034=>'NSM', -65035=>'NSM', -65036=>'NSM', -65037=>'NSM', -65038=>'NSM', -65039=>'NSM', -65040=>'ON', -65041=>'ON', -65042=>'ON', -65043=>'ON', -65044=>'ON', -65045=>'ON', -65046=>'ON', -65047=>'ON', -65048=>'ON', -65049=>'ON', -65056=>'NSM', -65057=>'NSM', -65058=>'NSM', -65059=>'NSM', -65072=>'ON', -65073=>'ON', -65074=>'ON', -65075=>'ON', -65076=>'ON', -65077=>'ON', -65078=>'ON', -65079=>'ON', -65080=>'ON', -65081=>'ON', -65082=>'ON', -65083=>'ON', -65084=>'ON', -65085=>'ON', -65086=>'ON', -65087=>'ON', -65088=>'ON', -65089=>'ON', -65090=>'ON', -65091=>'ON', -65092=>'ON', -65093=>'ON', -65094=>'ON', -65095=>'ON', -65096=>'ON', -65097=>'ON', -65098=>'ON', -65099=>'ON', -65100=>'ON', -65101=>'ON', -65102=>'ON', -65103=>'ON', -65104=>'CS', -65105=>'ON', -65106=>'CS', -65108=>'ON', -65109=>'CS', -65110=>'ON', -65111=>'ON', -65112=>'ON', -65113=>'ON', -65114=>'ON', -65115=>'ON', -65116=>'ON', -65117=>'ON', -65118=>'ON', -65119=>'ET', -65120=>'ON', -65121=>'ON', -65122=>'ES', -65123=>'ES', -65124=>'ON', -65125=>'ON', -65126=>'ON', -65128=>'ON', -65129=>'ET', -65130=>'ET', -65131=>'ON', -65136=>'AL', -65137=>'AL', -65138=>'AL', -65139=>'AL', -65140=>'AL', -65142=>'AL', -65143=>'AL', -65144=>'AL', -65145=>'AL', -65146=>'AL', -65147=>'AL', -65148=>'AL', -65149=>'AL', -65150=>'AL', -65151=>'AL', -65152=>'AL', -65153=>'AL', -65154=>'AL', -65155=>'AL', -65156=>'AL', -65157=>'AL', -65158=>'AL', -65159=>'AL', -65160=>'AL', -65161=>'AL', -65162=>'AL', -65163=>'AL', -65164=>'AL', -65165=>'AL', -65166=>'AL', -65167=>'AL', -65168=>'AL', -65169=>'AL', -65170=>'AL', -65171=>'AL', -65172=>'AL', -65173=>'AL', -65174=>'AL', -65175=>'AL', -65176=>'AL', -65177=>'AL', -65178=>'AL', -65179=>'AL', -65180=>'AL', -65181=>'AL', -65182=>'AL', -65183=>'AL', -65184=>'AL', -65185=>'AL', -65186=>'AL', -65187=>'AL', -65188=>'AL', -65189=>'AL', -65190=>'AL', -65191=>'AL', -65192=>'AL', -65193=>'AL', -65194=>'AL', -65195=>'AL', -65196=>'AL', -65197=>'AL', -65198=>'AL', -65199=>'AL', -65200=>'AL', -65201=>'AL', -65202=>'AL', -65203=>'AL', -65204=>'AL', -65205=>'AL', -65206=>'AL', -65207=>'AL', -65208=>'AL', -65209=>'AL', -65210=>'AL', -65211=>'AL', -65212=>'AL', -65213=>'AL', -65214=>'AL', -65215=>'AL', -65216=>'AL', -65217=>'AL', -65218=>'AL', -65219=>'AL', -65220=>'AL', -65221=>'AL', -65222=>'AL', -65223=>'AL', -65224=>'AL', -65225=>'AL', -65226=>'AL', -65227=>'AL', -65228=>'AL', -65229=>'AL', -65230=>'AL', -65231=>'AL', -65232=>'AL', -65233=>'AL', -65234=>'AL', -65235=>'AL', -65236=>'AL', -65237=>'AL', -65238=>'AL', -65239=>'AL', -65240=>'AL', -65241=>'AL', -65242=>'AL', -65243=>'AL', -65244=>'AL', -65245=>'AL', -65246=>'AL', -65247=>'AL', -65248=>'AL', -65249=>'AL', -65250=>'AL', -65251=>'AL', -65252=>'AL', -65253=>'AL', -65254=>'AL', -65255=>'AL', -65256=>'AL', -65257=>'AL', -65258=>'AL', -65259=>'AL', -65260=>'AL', -65261=>'AL', -65262=>'AL', -65263=>'AL', -65264=>'AL', -65265=>'AL', -65266=>'AL', -65267=>'AL', -65268=>'AL', -65269=>'AL', -65270=>'AL', -65271=>'AL', -65272=>'AL', -65273=>'AL', -65274=>'AL', -65275=>'AL', -65276=>'AL', -65279=>'BN', -65281=>'ON', -65282=>'ON', -65283=>'ET', -65284=>'ET', -65285=>'ET', -65286=>'ON', -65287=>'ON', -65288=>'ON', -65289=>'ON', -65290=>'ON', -65291=>'ES', -65292=>'CS', -65293=>'ES', -65294=>'CS', -65295=>'CS', -65296=>'EN', -65297=>'EN', -65298=>'EN', -65299=>'EN', -65300=>'EN', -65301=>'EN', -65302=>'EN', -65303=>'EN', -65304=>'EN', -65305=>'EN', -65306=>'CS', -65307=>'ON', -65308=>'ON', -65309=>'ON', -65310=>'ON', -65311=>'ON', -65312=>'ON', -65313=>'L', -65314=>'L', -65315=>'L', -65316=>'L', -65317=>'L', -65318=>'L', -65319=>'L', -65320=>'L', -65321=>'L', -65322=>'L', -65323=>'L', -65324=>'L', -65325=>'L', -65326=>'L', -65327=>'L', -65328=>'L', -65329=>'L', -65330=>'L', -65331=>'L', -65332=>'L', -65333=>'L', -65334=>'L', -65335=>'L', -65336=>'L', -65337=>'L', -65338=>'L', -65339=>'ON', -65340=>'ON', -65341=>'ON', -65342=>'ON', -65343=>'ON', -65344=>'ON', -65345=>'L', -65346=>'L', -65347=>'L', -65348=>'L', -65349=>'L', -65350=>'L', -65351=>'L', -65352=>'L', -65353=>'L', -65354=>'L', -65355=>'L', -65356=>'L', -65357=>'L', -65358=>'L', -65359=>'L', -65360=>'L', -65361=>'L', -65362=>'L', -65363=>'L', -65364=>'L', -65365=>'L', -65366=>'L', -65367=>'L', -65368=>'L', -65369=>'L', -65370=>'L', -65371=>'ON', -65372=>'ON', -65373=>'ON', -65374=>'ON', -65375=>'ON', -65376=>'ON', -65377=>'ON', -65378=>'ON', -65379=>'ON', -65380=>'ON', -65381=>'ON', -65382=>'L', -65383=>'L', -65384=>'L', -65385=>'L', -65386=>'L', -65387=>'L', -65388=>'L', -65389=>'L', -65390=>'L', -65391=>'L', -65392=>'L', -65393=>'L', -65394=>'L', -65395=>'L', -65396=>'L', -65397=>'L', -65398=>'L', -65399=>'L', -65400=>'L', -65401=>'L', -65402=>'L', -65403=>'L', -65404=>'L', -65405=>'L', -65406=>'L', -65407=>'L', -65408=>'L', -65409=>'L', -65410=>'L', -65411=>'L', -65412=>'L', -65413=>'L', -65414=>'L', -65415=>'L', -65416=>'L', -65417=>'L', -65418=>'L', -65419=>'L', -65420=>'L', -65421=>'L', -65422=>'L', -65423=>'L', -65424=>'L', -65425=>'L', -65426=>'L', -65427=>'L', -65428=>'L', -65429=>'L', -65430=>'L', -65431=>'L', -65432=>'L', -65433=>'L', -65434=>'L', -65435=>'L', -65436=>'L', -65437=>'L', -65438=>'L', -65439=>'L', -65440=>'L', -65441=>'L', -65442=>'L', -65443=>'L', -65444=>'L', -65445=>'L', -65446=>'L', -65447=>'L', -65448=>'L', -65449=>'L', -65450=>'L', -65451=>'L', -65452=>'L', -65453=>'L', -65454=>'L', -65455=>'L', -65456=>'L', -65457=>'L', -65458=>'L', -65459=>'L', -65460=>'L', -65461=>'L', -65462=>'L', -65463=>'L', -65464=>'L', -65465=>'L', -65466=>'L', -65467=>'L', -65468=>'L', -65469=>'L', -65470=>'L', -65474=>'L', -65475=>'L', -65476=>'L', -65477=>'L', -65478=>'L', -65479=>'L', -65482=>'L', -65483=>'L', -65484=>'L', -65485=>'L', -65486=>'L', -65487=>'L', -65490=>'L', -65491=>'L', -65492=>'L', -65493=>'L', -65494=>'L', -65495=>'L', -65498=>'L', -65499=>'L', -65500=>'L', -65504=>'ET', -65505=>'ET', -65506=>'ON', -65507=>'ON', -65508=>'ON', -65509=>'ET', -65510=>'ET', -65512=>'ON', -65513=>'ON', -65514=>'ON', -65515=>'ON', -65516=>'ON', -65517=>'ON', -65518=>'ON', -65529=>'ON', -65530=>'ON', -65531=>'ON', -65532=>'ON', -65533=>'ON', -65536=>'L', -65537=>'L', -65538=>'L', -65539=>'L', -65540=>'L', -65541=>'L', -65542=>'L', -65543=>'L', -65544=>'L', -65545=>'L', -65546=>'L', -65547=>'L', -65549=>'L', -65550=>'L', -65551=>'L', -65552=>'L', -65553=>'L', -65554=>'L', -65555=>'L', -65556=>'L', -65557=>'L', -65558=>'L', -65559=>'L', -65560=>'L', -65561=>'L', -65562=>'L', -65563=>'L', -65564=>'L', -65565=>'L', -65566=>'L', -65567=>'L', -65568=>'L', -65569=>'L', -65570=>'L', -65571=>'L', -65572=>'L', -65573=>'L', -65574=>'L', -65576=>'L', -65577=>'L', -65578=>'L', -65579=>'L', -65580=>'L', -65581=>'L', -65582=>'L', -65583=>'L', -65584=>'L', -65585=>'L', -65586=>'L', -65587=>'L', -65588=>'L', -65589=>'L', -65590=>'L', -65591=>'L', -65592=>'L', -65593=>'L', -65594=>'L', -65596=>'L', -65597=>'L', -65599=>'L', -65600=>'L', -65601=>'L', -65602=>'L', -65603=>'L', -65604=>'L', -65605=>'L', -65606=>'L', -65607=>'L', -65608=>'L', -65609=>'L', -65610=>'L', -65611=>'L', -65612=>'L', -65613=>'L', -65616=>'L', -65617=>'L', -65618=>'L', -65619=>'L', -65620=>'L', -65621=>'L', -65622=>'L', -65623=>'L', -65624=>'L', -65625=>'L', -65626=>'L', -65627=>'L', -65628=>'L', -65629=>'L', -65664=>'L', -65665=>'L', -65666=>'L', -65667=>'L', -65668=>'L', -65669=>'L', -65670=>'L', -65671=>'L', -65672=>'L', -65673=>'L', -65674=>'L', -65675=>'L', -65676=>'L', -65677=>'L', -65678=>'L', -65679=>'L', -65680=>'L', -65681=>'L', -65682=>'L', -65683=>'L', -65684=>'L', -65685=>'L', -65686=>'L', -65687=>'L', -65688=>'L', -65689=>'L', -65690=>'L', -65691=>'L', -65692=>'L', -65693=>'L', -65694=>'L', -65695=>'L', -65696=>'L', -65697=>'L', -65698=>'L', -65699=>'L', -65700=>'L', -65701=>'L', -65702=>'L', -65703=>'L', -65704=>'L', -65705=>'L', -65706=>'L', -65707=>'L', -65708=>'L', -65709=>'L', -65710=>'L', -65711=>'L', -65712=>'L', -65713=>'L', -65714=>'L', -65715=>'L', -65716=>'L', -65717=>'L', -65718=>'L', -65719=>'L', -65720=>'L', -65721=>'L', -65722=>'L', -65723=>'L', -65724=>'L', -65725=>'L', -65726=>'L', -65727=>'L', -65728=>'L', -65729=>'L', -65730=>'L', -65731=>'L', -65732=>'L', -65733=>'L', -65734=>'L', -65735=>'L', -65736=>'L', -65737=>'L', -65738=>'L', -65739=>'L', -65740=>'L', -65741=>'L', -65742=>'L', -65743=>'L', -65744=>'L', -65745=>'L', -65746=>'L', -65747=>'L', -65748=>'L', -65749=>'L', -65750=>'L', -65751=>'L', -65752=>'L', -65753=>'L', -65754=>'L', -65755=>'L', -65756=>'L', -65757=>'L', -65758=>'L', -65759=>'L', -65760=>'L', -65761=>'L', -65762=>'L', -65763=>'L', -65764=>'L', -65765=>'L', -65766=>'L', -65767=>'L', -65768=>'L', -65769=>'L', -65770=>'L', -65771=>'L', -65772=>'L', -65773=>'L', -65774=>'L', -65775=>'L', -65776=>'L', -65777=>'L', -65778=>'L', -65779=>'L', -65780=>'L', -65781=>'L', -65782=>'L', -65783=>'L', -65784=>'L', -65785=>'L', -65786=>'L', -65792=>'L', -65793=>'ON', -65794=>'L', -65799=>'L', -65800=>'L', -65801=>'L', -65802=>'L', -65803=>'L', -65804=>'L', -65805=>'L', -65806=>'L', -65807=>'L', -65808=>'L', -65809=>'L', -65810=>'L', -65811=>'L', -65812=>'L', -65813=>'L', -65814=>'L', -65815=>'L', -65816=>'L', -65817=>'L', -65818=>'L', -65819=>'L', -65820=>'L', -65821=>'L', -65822=>'L', -65823=>'L', -65824=>'L', -65825=>'L', -65826=>'L', -65827=>'L', -65828=>'L', -65829=>'L', -65830=>'L', -65831=>'L', -65832=>'L', -65833=>'L', -65834=>'L', -65835=>'L', -65836=>'L', -65837=>'L', -65838=>'L', -65839=>'L', -65840=>'L', -65841=>'L', -65842=>'L', -65843=>'L', -65847=>'L', -65848=>'L', -65849=>'L', -65850=>'L', -65851=>'L', -65852=>'L', -65853=>'L', -65854=>'L', -65855=>'L', -65856=>'ON', -65857=>'ON', -65858=>'ON', -65859=>'ON', -65860=>'ON', -65861=>'ON', -65862=>'ON', -65863=>'ON', -65864=>'ON', -65865=>'ON', -65866=>'ON', -65867=>'ON', -65868=>'ON', -65869=>'ON', -65870=>'ON', -65871=>'ON', -65872=>'ON', -65873=>'ON', -65874=>'ON', -65875=>'ON', -65876=>'ON', -65877=>'ON', -65878=>'ON', -65879=>'ON', -65880=>'ON', -65881=>'ON', -65882=>'ON', -65883=>'ON', -65884=>'ON', -65885=>'ON', -65886=>'ON', -65887=>'ON', -65888=>'ON', -65889=>'ON', -65890=>'ON', -65891=>'ON', -65892=>'ON', -65893=>'ON', -65894=>'ON', -65895=>'ON', -65896=>'ON', -65897=>'ON', -65898=>'ON', -65899=>'ON', -65900=>'ON', -65901=>'ON', -65902=>'ON', -65903=>'ON', -65904=>'ON', -65905=>'ON', -65906=>'ON', -65907=>'ON', -65908=>'ON', -65909=>'ON', -65910=>'ON', -65911=>'ON', -65912=>'ON', -65913=>'ON', -65914=>'ON', -65915=>'ON', -65916=>'ON', -65917=>'ON', -65918=>'ON', -65919=>'ON', -65920=>'ON', -65921=>'ON', -65922=>'ON', -65923=>'ON', -65924=>'ON', -65925=>'ON', -65926=>'ON', -65927=>'ON', -65928=>'ON', -65929=>'ON', -65930=>'ON', -66304=>'L', -66305=>'L', -66306=>'L', -66307=>'L', -66308=>'L', -66309=>'L', -66310=>'L', -66311=>'L', -66312=>'L', -66313=>'L', -66314=>'L', -66315=>'L', -66316=>'L', -66317=>'L', -66318=>'L', -66319=>'L', -66320=>'L', -66321=>'L', -66322=>'L', -66323=>'L', -66324=>'L', -66325=>'L', -66326=>'L', -66327=>'L', -66328=>'L', -66329=>'L', -66330=>'L', -66331=>'L', -66332=>'L', -66333=>'L', -66334=>'L', -66336=>'L', -66337=>'L', -66338=>'L', -66339=>'L', -66352=>'L', -66353=>'L', -66354=>'L', -66355=>'L', -66356=>'L', -66357=>'L', -66358=>'L', -66359=>'L', -66360=>'L', -66361=>'L', -66362=>'L', -66363=>'L', -66364=>'L', -66365=>'L', -66366=>'L', -66367=>'L', -66368=>'L', -66369=>'L', -66370=>'L', -66371=>'L', -66372=>'L', -66373=>'L', -66374=>'L', -66375=>'L', -66376=>'L', -66377=>'L', -66378=>'L', -66432=>'L', -66433=>'L', -66434=>'L', -66435=>'L', -66436=>'L', -66437=>'L', -66438=>'L', -66439=>'L', -66440=>'L', -66441=>'L', -66442=>'L', -66443=>'L', -66444=>'L', -66445=>'L', -66446=>'L', -66447=>'L', -66448=>'L', -66449=>'L', -66450=>'L', -66451=>'L', -66452=>'L', -66453=>'L', -66454=>'L', -66455=>'L', -66456=>'L', -66457=>'L', -66458=>'L', -66459=>'L', -66460=>'L', -66461=>'L', -66463=>'L', -66464=>'L', -66465=>'L', -66466=>'L', -66467=>'L', -66468=>'L', -66469=>'L', -66470=>'L', -66471=>'L', -66472=>'L', -66473=>'L', -66474=>'L', -66475=>'L', -66476=>'L', -66477=>'L', -66478=>'L', -66479=>'L', -66480=>'L', -66481=>'L', -66482=>'L', -66483=>'L', -66484=>'L', -66485=>'L', -66486=>'L', -66487=>'L', -66488=>'L', -66489=>'L', -66490=>'L', -66491=>'L', -66492=>'L', -66493=>'L', -66494=>'L', -66495=>'L', -66496=>'L', -66497=>'L', -66498=>'L', -66499=>'L', -66504=>'L', -66505=>'L', -66506=>'L', -66507=>'L', -66508=>'L', -66509=>'L', -66510=>'L', -66511=>'L', -66512=>'L', -66513=>'L', -66514=>'L', -66515=>'L', -66516=>'L', -66517=>'L', -66560=>'L', -66561=>'L', -66562=>'L', -66563=>'L', -66564=>'L', -66565=>'L', -66566=>'L', -66567=>'L', -66568=>'L', -66569=>'L', -66570=>'L', -66571=>'L', -66572=>'L', -66573=>'L', -66574=>'L', -66575=>'L', -66576=>'L', -66577=>'L', -66578=>'L', -66579=>'L', -66580=>'L', -66581=>'L', -66582=>'L', -66583=>'L', -66584=>'L', -66585=>'L', -66586=>'L', -66587=>'L', -66588=>'L', -66589=>'L', -66590=>'L', -66591=>'L', -66592=>'L', -66593=>'L', -66594=>'L', -66595=>'L', -66596=>'L', -66597=>'L', -66598=>'L', -66599=>'L', -66600=>'L', -66601=>'L', -66602=>'L', -66603=>'L', -66604=>'L', -66605=>'L', -66606=>'L', -66607=>'L', -66608=>'L', -66609=>'L', -66610=>'L', -66611=>'L', -66612=>'L', -66613=>'L', -66614=>'L', -66615=>'L', -66616=>'L', -66617=>'L', -66618=>'L', -66619=>'L', -66620=>'L', -66621=>'L', -66622=>'L', -66623=>'L', -66624=>'L', -66625=>'L', -66626=>'L', -66627=>'L', -66628=>'L', -66629=>'L', -66630=>'L', -66631=>'L', -66632=>'L', -66633=>'L', -66634=>'L', -66635=>'L', -66636=>'L', -66637=>'L', -66638=>'L', -66639=>'L', -66640=>'L', -66641=>'L', -66642=>'L', -66643=>'L', -66644=>'L', -66645=>'L', -66646=>'L', -66647=>'L', -66648=>'L', -66649=>'L', -66650=>'L', -66651=>'L', -66652=>'L', -66653=>'L', -66654=>'L', -66655=>'L', -66656=>'L', -66657=>'L', -66658=>'L', -66659=>'L', -66660=>'L', -66661=>'L', -66662=>'L', -66663=>'L', -66664=>'L', -66665=>'L', -66666=>'L', -66667=>'L', -66668=>'L', -66669=>'L', -66670=>'L', -66671=>'L', -66672=>'L', -66673=>'L', -66674=>'L', -66675=>'L', -66676=>'L', -66677=>'L', -66678=>'L', -66679=>'L', -66680=>'L', -66681=>'L', -66682=>'L', -66683=>'L', -66684=>'L', -66685=>'L', -66686=>'L', -66687=>'L', -66688=>'L', -66689=>'L', -66690=>'L', -66691=>'L', -66692=>'L', -66693=>'L', -66694=>'L', -66695=>'L', -66696=>'L', -66697=>'L', -66698=>'L', -66699=>'L', -66700=>'L', -66701=>'L', -66702=>'L', -66703=>'L', -66704=>'L', -66705=>'L', -66706=>'L', -66707=>'L', -66708=>'L', -66709=>'L', -66710=>'L', -66711=>'L', -66712=>'L', -66713=>'L', -66714=>'L', -66715=>'L', -66716=>'L', -66717=>'L', -66720=>'L', -66721=>'L', -66722=>'L', -66723=>'L', -66724=>'L', -66725=>'L', -66726=>'L', -66727=>'L', -66728=>'L', -66729=>'L', -67584=>'R', -67585=>'R', -67586=>'R', -67587=>'R', -67588=>'R', -67589=>'R', -67592=>'R', -67594=>'R', -67595=>'R', -67596=>'R', -67597=>'R', -67598=>'R', -67599=>'R', -67600=>'R', -67601=>'R', -67602=>'R', -67603=>'R', -67604=>'R', -67605=>'R', -67606=>'R', -67607=>'R', -67608=>'R', -67609=>'R', -67610=>'R', -67611=>'R', -67612=>'R', -67613=>'R', -67614=>'R', -67615=>'R', -67616=>'R', -67617=>'R', -67618=>'R', -67619=>'R', -67620=>'R', -67621=>'R', -67622=>'R', -67623=>'R', -67624=>'R', -67625=>'R', -67626=>'R', -67627=>'R', -67628=>'R', -67629=>'R', -67630=>'R', -67631=>'R', -67632=>'R', -67633=>'R', -67634=>'R', -67635=>'R', -67636=>'R', -67637=>'R', -67639=>'R', -67640=>'R', -67644=>'R', -67647=>'R', -67840=>'R', -67841=>'R', -67842=>'R', -67843=>'R', -67844=>'R', -67845=>'R', -67846=>'R', -67847=>'R', -67848=>'R', -67849=>'R', -67850=>'R', -67851=>'R', -67852=>'R', -67853=>'R', -67854=>'R', -67855=>'R', -67856=>'R', -67857=>'R', -67858=>'R', -67859=>'R', -67860=>'R', -67861=>'R', -67862=>'R', -67863=>'R', -67864=>'R', -67865=>'R', -67871=>'ON', -68096=>'R', -68097=>'NSM', -68098=>'NSM', -68099=>'NSM', -68101=>'NSM', -68102=>'NSM', -68108=>'NSM', -68109=>'NSM', -68110=>'NSM', -68111=>'NSM', -68112=>'R', -68113=>'R', -68114=>'R', -68115=>'R', -68117=>'R', -68118=>'R', -68119=>'R', -68121=>'R', -68122=>'R', -68123=>'R', -68124=>'R', -68125=>'R', -68126=>'R', -68127=>'R', -68128=>'R', -68129=>'R', -68130=>'R', -68131=>'R', -68132=>'R', -68133=>'R', -68134=>'R', -68135=>'R', -68136=>'R', -68137=>'R', -68138=>'R', -68139=>'R', -68140=>'R', -68141=>'R', -68142=>'R', -68143=>'R', -68144=>'R', -68145=>'R', -68146=>'R', -68147=>'R', -68152=>'NSM', -68153=>'NSM', -68154=>'NSM', -68159=>'NSM', -68160=>'R', -68161=>'R', -68162=>'R', -68163=>'R', -68164=>'R', -68165=>'R', -68166=>'R', -68167=>'R', -68176=>'R', -68177=>'R', -68178=>'R', -68179=>'R', -68180=>'R', -68181=>'R', -68182=>'R', -68183=>'R', -68184=>'R', -73728=>'L', -73729=>'L', -73730=>'L', -73731=>'L', -73732=>'L', -73733=>'L', -73734=>'L', -73735=>'L', -73736=>'L', -73737=>'L', -73738=>'L', -73739=>'L', -73740=>'L', -73741=>'L', -73742=>'L', -73743=>'L', -73744=>'L', -73745=>'L', -73746=>'L', -73747=>'L', -73748=>'L', -73749=>'L', -73750=>'L', -73751=>'L', -73752=>'L', -73753=>'L', -73754=>'L', -73755=>'L', -73756=>'L', -73757=>'L', -73758=>'L', -73759=>'L', -73760=>'L', -73761=>'L', -73762=>'L', -73763=>'L', -73764=>'L', -73765=>'L', -73766=>'L', -73767=>'L', -73768=>'L', -73769=>'L', -73770=>'L', -73771=>'L', -73772=>'L', -73773=>'L', -73774=>'L', -73775=>'L', -73776=>'L', -73777=>'L', -73778=>'L', -73779=>'L', -73780=>'L', -73781=>'L', -73782=>'L', -73783=>'L', -73784=>'L', -73785=>'L', -73786=>'L', -73787=>'L', -73788=>'L', -73789=>'L', -73790=>'L', -73791=>'L', -73792=>'L', -73793=>'L', -73794=>'L', -73795=>'L', -73796=>'L', -73797=>'L', -73798=>'L', -73799=>'L', -73800=>'L', -73801=>'L', -73802=>'L', -73803=>'L', -73804=>'L', -73805=>'L', -73806=>'L', -73807=>'L', -73808=>'L', -73809=>'L', -73810=>'L', -73811=>'L', -73812=>'L', -73813=>'L', -73814=>'L', -73815=>'L', -73816=>'L', -73817=>'L', -73818=>'L', -73819=>'L', -73820=>'L', -73821=>'L', -73822=>'L', -73823=>'L', -73824=>'L', -73825=>'L', -73826=>'L', -73827=>'L', -73828=>'L', -73829=>'L', -73830=>'L', -73831=>'L', -73832=>'L', -73833=>'L', -73834=>'L', -73835=>'L', -73836=>'L', -73837=>'L', -73838=>'L', -73839=>'L', -73840=>'L', -73841=>'L', -73842=>'L', -73843=>'L', -73844=>'L', -73845=>'L', -73846=>'L', -73847=>'L', -73848=>'L', -73849=>'L', -73850=>'L', -73851=>'L', -73852=>'L', -73853=>'L', -73854=>'L', -73855=>'L', -73856=>'L', -73857=>'L', -73858=>'L', -73859=>'L', -73860=>'L', -73861=>'L', -73862=>'L', -73863=>'L', -73864=>'L', -73865=>'L', -73866=>'L', -73867=>'L', -73868=>'L', -73869=>'L', -73870=>'L', -73871=>'L', -73872=>'L', -73873=>'L', -73874=>'L', -73875=>'L', -73876=>'L', -73877=>'L', -73878=>'L', -73879=>'L', -73880=>'L', -73881=>'L', -73882=>'L', -73883=>'L', -73884=>'L', -73885=>'L', -73886=>'L', -73887=>'L', -73888=>'L', -73889=>'L', -73890=>'L', -73891=>'L', -73892=>'L', -73893=>'L', -73894=>'L', -73895=>'L', -73896=>'L', -73897=>'L', -73898=>'L', -73899=>'L', -73900=>'L', -73901=>'L', -73902=>'L', -73903=>'L', -73904=>'L', -73905=>'L', -73906=>'L', -73907=>'L', -73908=>'L', -73909=>'L', -73910=>'L', -73911=>'L', -73912=>'L', -73913=>'L', -73914=>'L', -73915=>'L', -73916=>'L', -73917=>'L', -73918=>'L', -73919=>'L', -73920=>'L', -73921=>'L', -73922=>'L', -73923=>'L', -73924=>'L', -73925=>'L', -73926=>'L', -73927=>'L', -73928=>'L', -73929=>'L', -73930=>'L', -73931=>'L', -73932=>'L', -73933=>'L', -73934=>'L', -73935=>'L', -73936=>'L', -73937=>'L', -73938=>'L', -73939=>'L', -73940=>'L', -73941=>'L', -73942=>'L', -73943=>'L', -73944=>'L', -73945=>'L', -73946=>'L', -73947=>'L', -73948=>'L', -73949=>'L', -73950=>'L', -73951=>'L', -73952=>'L', -73953=>'L', -73954=>'L', -73955=>'L', -73956=>'L', -73957=>'L', -73958=>'L', -73959=>'L', -73960=>'L', -73961=>'L', -73962=>'L', -73963=>'L', -73964=>'L', -73965=>'L', -73966=>'L', -73967=>'L', -73968=>'L', -73969=>'L', -73970=>'L', -73971=>'L', -73972=>'L', -73973=>'L', -73974=>'L', -73975=>'L', -73976=>'L', -73977=>'L', -73978=>'L', -73979=>'L', -73980=>'L', -73981=>'L', -73982=>'L', -73983=>'L', -73984=>'L', -73985=>'L', -73986=>'L', -73987=>'L', -73988=>'L', -73989=>'L', -73990=>'L', -73991=>'L', -73992=>'L', -73993=>'L', -73994=>'L', -73995=>'L', -73996=>'L', -73997=>'L', -73998=>'L', -73999=>'L', -74000=>'L', -74001=>'L', -74002=>'L', -74003=>'L', -74004=>'L', -74005=>'L', -74006=>'L', -74007=>'L', -74008=>'L', -74009=>'L', -74010=>'L', -74011=>'L', -74012=>'L', -74013=>'L', -74014=>'L', -74015=>'L', -74016=>'L', -74017=>'L', -74018=>'L', -74019=>'L', -74020=>'L', -74021=>'L', -74022=>'L', -74023=>'L', -74024=>'L', -74025=>'L', -74026=>'L', -74027=>'L', -74028=>'L', -74029=>'L', -74030=>'L', -74031=>'L', -74032=>'L', -74033=>'L', -74034=>'L', -74035=>'L', -74036=>'L', -74037=>'L', -74038=>'L', -74039=>'L', -74040=>'L', -74041=>'L', -74042=>'L', -74043=>'L', -74044=>'L', -74045=>'L', -74046=>'L', -74047=>'L', -74048=>'L', -74049=>'L', -74050=>'L', -74051=>'L', -74052=>'L', -74053=>'L', -74054=>'L', -74055=>'L', -74056=>'L', -74057=>'L', -74058=>'L', -74059=>'L', -74060=>'L', -74061=>'L', -74062=>'L', -74063=>'L', -74064=>'L', -74065=>'L', -74066=>'L', -74067=>'L', -74068=>'L', -74069=>'L', -74070=>'L', -74071=>'L', -74072=>'L', -74073=>'L', -74074=>'L', -74075=>'L', -74076=>'L', -74077=>'L', -74078=>'L', -74079=>'L', -74080=>'L', -74081=>'L', -74082=>'L', -74083=>'L', -74084=>'L', -74085=>'L', -74086=>'L', -74087=>'L', -74088=>'L', -74089=>'L', -74090=>'L', -74091=>'L', -74092=>'L', -74093=>'L', -74094=>'L', -74095=>'L', -74096=>'L', -74097=>'L', -74098=>'L', -74099=>'L', -74100=>'L', -74101=>'L', -74102=>'L', -74103=>'L', -74104=>'L', -74105=>'L', -74106=>'L', -74107=>'L', -74108=>'L', -74109=>'L', -74110=>'L', -74111=>'L', -74112=>'L', -74113=>'L', -74114=>'L', -74115=>'L', -74116=>'L', -74117=>'L', -74118=>'L', -74119=>'L', -74120=>'L', -74121=>'L', -74122=>'L', -74123=>'L', -74124=>'L', -74125=>'L', -74126=>'L', -74127=>'L', -74128=>'L', -74129=>'L', -74130=>'L', -74131=>'L', -74132=>'L', -74133=>'L', -74134=>'L', -74135=>'L', -74136=>'L', -74137=>'L', -74138=>'L', -74139=>'L', -74140=>'L', -74141=>'L', -74142=>'L', -74143=>'L', -74144=>'L', -74145=>'L', -74146=>'L', -74147=>'L', -74148=>'L', -74149=>'L', -74150=>'L', -74151=>'L', -74152=>'L', -74153=>'L', -74154=>'L', -74155=>'L', -74156=>'L', -74157=>'L', -74158=>'L', -74159=>'L', -74160=>'L', -74161=>'L', -74162=>'L', -74163=>'L', -74164=>'L', -74165=>'L', -74166=>'L', -74167=>'L', -74168=>'L', -74169=>'L', -74170=>'L', -74171=>'L', -74172=>'L', -74173=>'L', -74174=>'L', -74175=>'L', -74176=>'L', -74177=>'L', -74178=>'L', -74179=>'L', -74180=>'L', -74181=>'L', -74182=>'L', -74183=>'L', -74184=>'L', -74185=>'L', -74186=>'L', -74187=>'L', -74188=>'L', -74189=>'L', -74190=>'L', -74191=>'L', -74192=>'L', -74193=>'L', -74194=>'L', -74195=>'L', -74196=>'L', -74197=>'L', -74198=>'L', -74199=>'L', -74200=>'L', -74201=>'L', -74202=>'L', -74203=>'L', -74204=>'L', -74205=>'L', -74206=>'L', -74207=>'L', -74208=>'L', -74209=>'L', -74210=>'L', -74211=>'L', -74212=>'L', -74213=>'L', -74214=>'L', -74215=>'L', -74216=>'L', -74217=>'L', -74218=>'L', -74219=>'L', -74220=>'L', -74221=>'L', -74222=>'L', -74223=>'L', -74224=>'L', -74225=>'L', -74226=>'L', -74227=>'L', -74228=>'L', -74229=>'L', -74230=>'L', -74231=>'L', -74232=>'L', -74233=>'L', -74234=>'L', -74235=>'L', -74236=>'L', -74237=>'L', -74238=>'L', -74239=>'L', -74240=>'L', -74241=>'L', -74242=>'L', -74243=>'L', -74244=>'L', -74245=>'L', -74246=>'L', -74247=>'L', -74248=>'L', -74249=>'L', -74250=>'L', -74251=>'L', -74252=>'L', -74253=>'L', -74254=>'L', -74255=>'L', -74256=>'L', -74257=>'L', -74258=>'L', -74259=>'L', -74260=>'L', -74261=>'L', -74262=>'L', -74263=>'L', -74264=>'L', -74265=>'L', -74266=>'L', -74267=>'L', -74268=>'L', -74269=>'L', -74270=>'L', -74271=>'L', -74272=>'L', -74273=>'L', -74274=>'L', -74275=>'L', -74276=>'L', -74277=>'L', -74278=>'L', -74279=>'L', -74280=>'L', -74281=>'L', -74282=>'L', -74283=>'L', -74284=>'L', -74285=>'L', -74286=>'L', -74287=>'L', -74288=>'L', -74289=>'L', -74290=>'L', -74291=>'L', -74292=>'L', -74293=>'L', -74294=>'L', -74295=>'L', -74296=>'L', -74297=>'L', -74298=>'L', -74299=>'L', -74300=>'L', -74301=>'L', -74302=>'L', -74303=>'L', -74304=>'L', -74305=>'L', -74306=>'L', -74307=>'L', -74308=>'L', -74309=>'L', -74310=>'L', -74311=>'L', -74312=>'L', -74313=>'L', -74314=>'L', -74315=>'L', -74316=>'L', -74317=>'L', -74318=>'L', -74319=>'L', -74320=>'L', -74321=>'L', -74322=>'L', -74323=>'L', -74324=>'L', -74325=>'L', -74326=>'L', -74327=>'L', -74328=>'L', -74329=>'L', -74330=>'L', -74331=>'L', -74332=>'L', -74333=>'L', -74334=>'L', -74335=>'L', -74336=>'L', -74337=>'L', -74338=>'L', -74339=>'L', -74340=>'L', -74341=>'L', -74342=>'L', -74343=>'L', -74344=>'L', -74345=>'L', -74346=>'L', -74347=>'L', -74348=>'L', -74349=>'L', -74350=>'L', -74351=>'L', -74352=>'L', -74353=>'L', -74354=>'L', -74355=>'L', -74356=>'L', -74357=>'L', -74358=>'L', -74359=>'L', -74360=>'L', -74361=>'L', -74362=>'L', -74363=>'L', -74364=>'L', -74365=>'L', -74366=>'L', -74367=>'L', -74368=>'L', -74369=>'L', -74370=>'L', -74371=>'L', -74372=>'L', -74373=>'L', -74374=>'L', -74375=>'L', -74376=>'L', -74377=>'L', -74378=>'L', -74379=>'L', -74380=>'L', -74381=>'L', -74382=>'L', -74383=>'L', -74384=>'L', -74385=>'L', -74386=>'L', -74387=>'L', -74388=>'L', -74389=>'L', -74390=>'L', -74391=>'L', -74392=>'L', -74393=>'L', -74394=>'L', -74395=>'L', -74396=>'L', -74397=>'L', -74398=>'L', -74399=>'L', -74400=>'L', -74401=>'L', -74402=>'L', -74403=>'L', -74404=>'L', -74405=>'L', -74406=>'L', -74407=>'L', -74408=>'L', -74409=>'L', -74410=>'L', -74411=>'L', -74412=>'L', -74413=>'L', -74414=>'L', -74415=>'L', -74416=>'L', -74417=>'L', -74418=>'L', -74419=>'L', -74420=>'L', -74421=>'L', -74422=>'L', -74423=>'L', -74424=>'L', -74425=>'L', -74426=>'L', -74427=>'L', -74428=>'L', -74429=>'L', -74430=>'L', -74431=>'L', -74432=>'L', -74433=>'L', -74434=>'L', -74435=>'L', -74436=>'L', -74437=>'L', -74438=>'L', -74439=>'L', -74440=>'L', -74441=>'L', -74442=>'L', -74443=>'L', -74444=>'L', -74445=>'L', -74446=>'L', -74447=>'L', -74448=>'L', -74449=>'L', -74450=>'L', -74451=>'L', -74452=>'L', -74453=>'L', -74454=>'L', -74455=>'L', -74456=>'L', -74457=>'L', -74458=>'L', -74459=>'L', -74460=>'L', -74461=>'L', -74462=>'L', -74463=>'L', -74464=>'L', -74465=>'L', -74466=>'L', -74467=>'L', -74468=>'L', -74469=>'L', -74470=>'L', -74471=>'L', -74472=>'L', -74473=>'L', -74474=>'L', -74475=>'L', -74476=>'L', -74477=>'L', -74478=>'L', -74479=>'L', -74480=>'L', -74481=>'L', -74482=>'L', -74483=>'L', -74484=>'L', -74485=>'L', -74486=>'L', -74487=>'L', -74488=>'L', -74489=>'L', -74490=>'L', -74491=>'L', -74492=>'L', -74493=>'L', -74494=>'L', -74495=>'L', -74496=>'L', -74497=>'L', -74498=>'L', -74499=>'L', -74500=>'L', -74501=>'L', -74502=>'L', -74503=>'L', -74504=>'L', -74505=>'L', -74506=>'L', -74507=>'L', -74508=>'L', -74509=>'L', -74510=>'L', -74511=>'L', -74512=>'L', -74513=>'L', -74514=>'L', -74515=>'L', -74516=>'L', -74517=>'L', -74518=>'L', -74519=>'L', -74520=>'L', -74521=>'L', -74522=>'L', -74523=>'L', -74524=>'L', -74525=>'L', -74526=>'L', -74527=>'L', -74528=>'L', -74529=>'L', -74530=>'L', -74531=>'L', -74532=>'L', -74533=>'L', -74534=>'L', -74535=>'L', -74536=>'L', -74537=>'L', -74538=>'L', -74539=>'L', -74540=>'L', -74541=>'L', -74542=>'L', -74543=>'L', -74544=>'L', -74545=>'L', -74546=>'L', -74547=>'L', -74548=>'L', -74549=>'L', -74550=>'L', -74551=>'L', -74552=>'L', -74553=>'L', -74554=>'L', -74555=>'L', -74556=>'L', -74557=>'L', -74558=>'L', -74559=>'L', -74560=>'L', -74561=>'L', -74562=>'L', -74563=>'L', -74564=>'L', -74565=>'L', -74566=>'L', -74567=>'L', -74568=>'L', -74569=>'L', -74570=>'L', -74571=>'L', -74572=>'L', -74573=>'L', -74574=>'L', -74575=>'L', -74576=>'L', -74577=>'L', -74578=>'L', -74579=>'L', -74580=>'L', -74581=>'L', -74582=>'L', -74583=>'L', -74584=>'L', -74585=>'L', -74586=>'L', -74587=>'L', -74588=>'L', -74589=>'L', -74590=>'L', -74591=>'L', -74592=>'L', -74593=>'L', -74594=>'L', -74595=>'L', -74596=>'L', -74597=>'L', -74598=>'L', -74599=>'L', -74600=>'L', -74601=>'L', -74602=>'L', -74603=>'L', -74604=>'L', -74605=>'L', -74606=>'L', -74752=>'L', -74753=>'L', -74754=>'L', -74755=>'L', -74756=>'L', -74757=>'L', -74758=>'L', -74759=>'L', -74760=>'L', -74761=>'L', -74762=>'L', -74763=>'L', -74764=>'L', -74765=>'L', -74766=>'L', -74767=>'L', -74768=>'L', -74769=>'L', -74770=>'L', -74771=>'L', -74772=>'L', -74773=>'L', -74774=>'L', -74775=>'L', -74776=>'L', -74777=>'L', -74778=>'L', -74779=>'L', -74780=>'L', -74781=>'L', -74782=>'L', -74783=>'L', -74784=>'L', -74785=>'L', -74786=>'L', -74787=>'L', -74788=>'L', -74789=>'L', -74790=>'L', -74791=>'L', -74792=>'L', -74793=>'L', -74794=>'L', -74795=>'L', -74796=>'L', -74797=>'L', -74798=>'L', -74799=>'L', -74800=>'L', -74801=>'L', -74802=>'L', -74803=>'L', -74804=>'L', -74805=>'L', -74806=>'L', -74807=>'L', -74808=>'L', -74809=>'L', -74810=>'L', -74811=>'L', -74812=>'L', -74813=>'L', -74814=>'L', -74815=>'L', -74816=>'L', -74817=>'L', -74818=>'L', -74819=>'L', -74820=>'L', -74821=>'L', -74822=>'L', -74823=>'L', -74824=>'L', -74825=>'L', -74826=>'L', -74827=>'L', -74828=>'L', -74829=>'L', -74830=>'L', -74831=>'L', -74832=>'L', -74833=>'L', -74834=>'L', -74835=>'L', -74836=>'L', -74837=>'L', -74838=>'L', -74839=>'L', -74840=>'L', -74841=>'L', -74842=>'L', -74843=>'L', -74844=>'L', -74845=>'L', -74846=>'L', -74847=>'L', -74848=>'L', -74849=>'L', -74850=>'L', -74864=>'L', -74865=>'L', -74866=>'L', -74867=>'L', -118784=>'L', -118785=>'L', -118786=>'L', -118787=>'L', -118788=>'L', -118789=>'L', -118790=>'L', -118791=>'L', -118792=>'L', -118793=>'L', -118794=>'L', -118795=>'L', -118796=>'L', -118797=>'L', -118798=>'L', -118799=>'L', -118800=>'L', -118801=>'L', -118802=>'L', -118803=>'L', -118804=>'L', -118805=>'L', -118806=>'L', -118807=>'L', -118808=>'L', -118809=>'L', -118810=>'L', -118811=>'L', -118812=>'L', -118813=>'L', -118814=>'L', -118815=>'L', -118816=>'L', -118817=>'L', -118818=>'L', -118819=>'L', -118820=>'L', -118821=>'L', -118822=>'L', -118823=>'L', -118824=>'L', -118825=>'L', -118826=>'L', -118827=>'L', -118828=>'L', -118829=>'L', -118830=>'L', -118831=>'L', -118832=>'L', -118833=>'L', -118834=>'L', -118835=>'L', -118836=>'L', -118837=>'L', -118838=>'L', -118839=>'L', -118840=>'L', -118841=>'L', -118842=>'L', -118843=>'L', -118844=>'L', -118845=>'L', -118846=>'L', -118847=>'L', -118848=>'L', -118849=>'L', -118850=>'L', -118851=>'L', -118852=>'L', -118853=>'L', -118854=>'L', -118855=>'L', -118856=>'L', -118857=>'L', -118858=>'L', -118859=>'L', -118860=>'L', -118861=>'L', -118862=>'L', -118863=>'L', -118864=>'L', -118865=>'L', -118866=>'L', -118867=>'L', -118868=>'L', -118869=>'L', -118870=>'L', -118871=>'L', -118872=>'L', -118873=>'L', -118874=>'L', -118875=>'L', -118876=>'L', -118877=>'L', -118878=>'L', -118879=>'L', -118880=>'L', -118881=>'L', -118882=>'L', -118883=>'L', -118884=>'L', -118885=>'L', -118886=>'L', -118887=>'L', -118888=>'L', -118889=>'L', -118890=>'L', -118891=>'L', -118892=>'L', -118893=>'L', -118894=>'L', -118895=>'L', -118896=>'L', -118897=>'L', -118898=>'L', -118899=>'L', -118900=>'L', -118901=>'L', -118902=>'L', -118903=>'L', -118904=>'L', -118905=>'L', -118906=>'L', -118907=>'L', -118908=>'L', -118909=>'L', -118910=>'L', -118911=>'L', -118912=>'L', -118913=>'L', -118914=>'L', -118915=>'L', -118916=>'L', -118917=>'L', -118918=>'L', -118919=>'L', -118920=>'L', -118921=>'L', -118922=>'L', -118923=>'L', -118924=>'L', -118925=>'L', -118926=>'L', -118927=>'L', -118928=>'L', -118929=>'L', -118930=>'L', -118931=>'L', -118932=>'L', -118933=>'L', -118934=>'L', -118935=>'L', -118936=>'L', -118937=>'L', -118938=>'L', -118939=>'L', -118940=>'L', -118941=>'L', -118942=>'L', -118943=>'L', -118944=>'L', -118945=>'L', -118946=>'L', -118947=>'L', -118948=>'L', -118949=>'L', -118950=>'L', -118951=>'L', -118952=>'L', -118953=>'L', -118954=>'L', -118955=>'L', -118956=>'L', -118957=>'L', -118958=>'L', -118959=>'L', -118960=>'L', -118961=>'L', -118962=>'L', -118963=>'L', -118964=>'L', -118965=>'L', -118966=>'L', -118967=>'L', -118968=>'L', -118969=>'L', -118970=>'L', -118971=>'L', -118972=>'L', -118973=>'L', -118974=>'L', -118975=>'L', -118976=>'L', -118977=>'L', -118978=>'L', -118979=>'L', -118980=>'L', -118981=>'L', -118982=>'L', -118983=>'L', -118984=>'L', -118985=>'L', -118986=>'L', -118987=>'L', -118988=>'L', -118989=>'L', -118990=>'L', -118991=>'L', -118992=>'L', -118993=>'L', -118994=>'L', -118995=>'L', -118996=>'L', -118997=>'L', -118998=>'L', -118999=>'L', -119000=>'L', -119001=>'L', -119002=>'L', -119003=>'L', -119004=>'L', -119005=>'L', -119006=>'L', -119007=>'L', -119008=>'L', -119009=>'L', -119010=>'L', -119011=>'L', -119012=>'L', -119013=>'L', -119014=>'L', -119015=>'L', -119016=>'L', -119017=>'L', -119018=>'L', -119019=>'L', -119020=>'L', -119021=>'L', -119022=>'L', -119023=>'L', -119024=>'L', -119025=>'L', -119026=>'L', -119027=>'L', -119028=>'L', -119029=>'L', -119040=>'L', -119041=>'L', -119042=>'L', -119043=>'L', -119044=>'L', -119045=>'L', -119046=>'L', -119047=>'L', -119048=>'L', -119049=>'L', -119050=>'L', -119051=>'L', -119052=>'L', -119053=>'L', -119054=>'L', -119055=>'L', -119056=>'L', -119057=>'L', -119058=>'L', -119059=>'L', -119060=>'L', -119061=>'L', -119062=>'L', -119063=>'L', -119064=>'L', -119065=>'L', -119066=>'L', -119067=>'L', -119068=>'L', -119069=>'L', -119070=>'L', -119071=>'L', -119072=>'L', -119073=>'L', -119074=>'L', -119075=>'L', -119076=>'L', -119077=>'L', -119078=>'L', -119082=>'L', -119083=>'L', -119084=>'L', -119085=>'L', -119086=>'L', -119087=>'L', -119088=>'L', -119089=>'L', -119090=>'L', -119091=>'L', -119092=>'L', -119093=>'L', -119094=>'L', -119095=>'L', -119096=>'L', -119097=>'L', -119098=>'L', -119099=>'L', -119100=>'L', -119101=>'L', -119102=>'L', -119103=>'L', -119104=>'L', -119105=>'L', -119106=>'L', -119107=>'L', -119108=>'L', -119109=>'L', -119110=>'L', -119111=>'L', -119112=>'L', -119113=>'L', -119114=>'L', -119115=>'L', -119116=>'L', -119117=>'L', -119118=>'L', -119119=>'L', -119120=>'L', -119121=>'L', -119122=>'L', -119123=>'L', -119124=>'L', -119125=>'L', -119126=>'L', -119127=>'L', -119128=>'L', -119129=>'L', -119130=>'L', -119131=>'L', -119132=>'L', -119133=>'L', -119134=>'L', -119135=>'L', -119136=>'L', -119137=>'L', -119138=>'L', -119139=>'L', -119140=>'L', -119141=>'L', -119142=>'L', -119143=>'NSM', -119144=>'NSM', -119145=>'NSM', -119146=>'L', -119147=>'L', -119148=>'L', -119149=>'L', -119150=>'L', -119151=>'L', -119152=>'L', -119153=>'L', -119154=>'L', -119155=>'BN', -119156=>'BN', -119157=>'BN', -119158=>'BN', -119159=>'BN', -119160=>'BN', -119161=>'BN', -119162=>'BN', -119163=>'NSM', -119164=>'NSM', -119165=>'NSM', -119166=>'NSM', -119167=>'NSM', -119168=>'NSM', -119169=>'NSM', -119170=>'NSM', -119171=>'L', -119172=>'L', -119173=>'NSM', -119174=>'NSM', -119175=>'NSM', -119176=>'NSM', -119177=>'NSM', -119178=>'NSM', -119179=>'NSM', -119180=>'L', -119181=>'L', -119182=>'L', -119183=>'L', -119184=>'L', -119185=>'L', -119186=>'L', -119187=>'L', -119188=>'L', -119189=>'L', -119190=>'L', -119191=>'L', -119192=>'L', -119193=>'L', -119194=>'L', -119195=>'L', -119196=>'L', -119197=>'L', -119198=>'L', -119199=>'L', -119200=>'L', -119201=>'L', -119202=>'L', -119203=>'L', -119204=>'L', -119205=>'L', -119206=>'L', -119207=>'L', -119208=>'L', -119209=>'L', -119210=>'NSM', -119211=>'NSM', -119212=>'NSM', -119213=>'NSM', -119214=>'L', -119215=>'L', -119216=>'L', -119217=>'L', -119218=>'L', -119219=>'L', -119220=>'L', -119221=>'L', -119222=>'L', -119223=>'L', -119224=>'L', -119225=>'L', -119226=>'L', -119227=>'L', -119228=>'L', -119229=>'L', -119230=>'L', -119231=>'L', -119232=>'L', -119233=>'L', -119234=>'L', -119235=>'L', -119236=>'L', -119237=>'L', -119238=>'L', -119239=>'L', -119240=>'L', -119241=>'L', -119242=>'L', -119243=>'L', -119244=>'L', -119245=>'L', -119246=>'L', -119247=>'L', -119248=>'L', -119249=>'L', -119250=>'L', -119251=>'L', -119252=>'L', -119253=>'L', -119254=>'L', -119255=>'L', -119256=>'L', -119257=>'L', -119258=>'L', -119259=>'L', -119260=>'L', -119261=>'L', -119296=>'ON', -119297=>'ON', -119298=>'ON', -119299=>'ON', -119300=>'ON', -119301=>'ON', -119302=>'ON', -119303=>'ON', -119304=>'ON', -119305=>'ON', -119306=>'ON', -119307=>'ON', -119308=>'ON', -119309=>'ON', -119310=>'ON', -119311=>'ON', -119312=>'ON', -119313=>'ON', -119314=>'ON', -119315=>'ON', -119316=>'ON', -119317=>'ON', -119318=>'ON', -119319=>'ON', -119320=>'ON', -119321=>'ON', -119322=>'ON', -119323=>'ON', -119324=>'ON', -119325=>'ON', -119326=>'ON', -119327=>'ON', -119328=>'ON', -119329=>'ON', -119330=>'ON', -119331=>'ON', -119332=>'ON', -119333=>'ON', -119334=>'ON', -119335=>'ON', -119336=>'ON', -119337=>'ON', -119338=>'ON', -119339=>'ON', -119340=>'ON', -119341=>'ON', -119342=>'ON', -119343=>'ON', -119344=>'ON', -119345=>'ON', -119346=>'ON', -119347=>'ON', -119348=>'ON', -119349=>'ON', -119350=>'ON', -119351=>'ON', -119352=>'ON', -119353=>'ON', -119354=>'ON', -119355=>'ON', -119356=>'ON', -119357=>'ON', -119358=>'ON', -119359=>'ON', -119360=>'ON', -119361=>'ON', -119362=>'NSM', -119363=>'NSM', -119364=>'NSM', -119365=>'ON', -119552=>'ON', -119553=>'ON', -119554=>'ON', -119555=>'ON', -119556=>'ON', -119557=>'ON', -119558=>'ON', -119559=>'ON', -119560=>'ON', -119561=>'ON', -119562=>'ON', -119563=>'ON', -119564=>'ON', -119565=>'ON', -119566=>'ON', -119567=>'ON', -119568=>'ON', -119569=>'ON', -119570=>'ON', -119571=>'ON', -119572=>'ON', -119573=>'ON', -119574=>'ON', -119575=>'ON', -119576=>'ON', -119577=>'ON', -119578=>'ON', -119579=>'ON', -119580=>'ON', -119581=>'ON', -119582=>'ON', -119583=>'ON', -119584=>'ON', -119585=>'ON', -119586=>'ON', -119587=>'ON', -119588=>'ON', -119589=>'ON', -119590=>'ON', -119591=>'ON', -119592=>'ON', -119593=>'ON', -119594=>'ON', -119595=>'ON', -119596=>'ON', -119597=>'ON', -119598=>'ON', -119599=>'ON', -119600=>'ON', -119601=>'ON', -119602=>'ON', -119603=>'ON', -119604=>'ON', -119605=>'ON', -119606=>'ON', -119607=>'ON', -119608=>'ON', -119609=>'ON', -119610=>'ON', -119611=>'ON', -119612=>'ON', -119613=>'ON', -119614=>'ON', -119615=>'ON', -119616=>'ON', -119617=>'ON', -119618=>'ON', -119619=>'ON', -119620=>'ON', -119621=>'ON', -119622=>'ON', -119623=>'ON', -119624=>'ON', -119625=>'ON', -119626=>'ON', -119627=>'ON', -119628=>'ON', -119629=>'ON', -119630=>'ON', -119631=>'ON', -119632=>'ON', -119633=>'ON', -119634=>'ON', -119635=>'ON', -119636=>'ON', -119637=>'ON', -119638=>'ON', -119648=>'L', -119649=>'L', -119650=>'L', -119651=>'L', -119652=>'L', -119653=>'L', -119654=>'L', -119655=>'L', -119656=>'L', -119657=>'L', -119658=>'L', -119659=>'L', -119660=>'L', -119661=>'L', -119662=>'L', -119663=>'L', -119664=>'L', -119665=>'L', -119808=>'L', -119809=>'L', -119810=>'L', -119811=>'L', -119812=>'L', -119813=>'L', -119814=>'L', -119815=>'L', -119816=>'L', -119817=>'L', -119818=>'L', -119819=>'L', -119820=>'L', -119821=>'L', -119822=>'L', -119823=>'L', -119824=>'L', -119825=>'L', -119826=>'L', -119827=>'L', -119828=>'L', -119829=>'L', -119830=>'L', -119831=>'L', -119832=>'L', -119833=>'L', -119834=>'L', -119835=>'L', -119836=>'L', -119837=>'L', -119838=>'L', -119839=>'L', -119840=>'L', -119841=>'L', -119842=>'L', -119843=>'L', -119844=>'L', -119845=>'L', -119846=>'L', -119847=>'L', -119848=>'L', -119849=>'L', -119850=>'L', -119851=>'L', -119852=>'L', -119853=>'L', -119854=>'L', -119855=>'L', -119856=>'L', -119857=>'L', -119858=>'L', -119859=>'L', -119860=>'L', -119861=>'L', -119862=>'L', -119863=>'L', -119864=>'L', -119865=>'L', -119866=>'L', -119867=>'L', -119868=>'L', -119869=>'L', -119870=>'L', -119871=>'L', -119872=>'L', -119873=>'L', -119874=>'L', -119875=>'L', -119876=>'L', -119877=>'L', -119878=>'L', -119879=>'L', -119880=>'L', -119881=>'L', -119882=>'L', -119883=>'L', -119884=>'L', -119885=>'L', -119886=>'L', -119887=>'L', -119888=>'L', -119889=>'L', -119890=>'L', -119891=>'L', -119892=>'L', -119894=>'L', -119895=>'L', -119896=>'L', -119897=>'L', -119898=>'L', -119899=>'L', -119900=>'L', -119901=>'L', -119902=>'L', -119903=>'L', -119904=>'L', -119905=>'L', -119906=>'L', -119907=>'L', -119908=>'L', -119909=>'L', -119910=>'L', -119911=>'L', -119912=>'L', -119913=>'L', -119914=>'L', -119915=>'L', -119916=>'L', -119917=>'L', -119918=>'L', -119919=>'L', -119920=>'L', -119921=>'L', -119922=>'L', -119923=>'L', -119924=>'L', -119925=>'L', -119926=>'L', -119927=>'L', -119928=>'L', -119929=>'L', -119930=>'L', -119931=>'L', -119932=>'L', -119933=>'L', -119934=>'L', -119935=>'L', -119936=>'L', -119937=>'L', -119938=>'L', -119939=>'L', -119940=>'L', -119941=>'L', -119942=>'L', -119943=>'L', -119944=>'L', -119945=>'L', -119946=>'L', -119947=>'L', -119948=>'L', -119949=>'L', -119950=>'L', -119951=>'L', -119952=>'L', -119953=>'L', -119954=>'L', -119955=>'L', -119956=>'L', -119957=>'L', -119958=>'L', -119959=>'L', -119960=>'L', -119961=>'L', -119962=>'L', -119963=>'L', -119964=>'L', -119966=>'L', -119967=>'L', -119970=>'L', -119973=>'L', -119974=>'L', -119977=>'L', -119978=>'L', -119979=>'L', -119980=>'L', -119982=>'L', -119983=>'L', -119984=>'L', -119985=>'L', -119986=>'L', -119987=>'L', -119988=>'L', -119989=>'L', -119990=>'L', -119991=>'L', -119992=>'L', -119993=>'L', -119995=>'L', -119997=>'L', -119998=>'L', -119999=>'L', -120000=>'L', -120001=>'L', -120002=>'L', -120003=>'L', -120005=>'L', -120006=>'L', -120007=>'L', -120008=>'L', -120009=>'L', -120010=>'L', -120011=>'L', -120012=>'L', -120013=>'L', -120014=>'L', -120015=>'L', -120016=>'L', -120017=>'L', -120018=>'L', -120019=>'L', -120020=>'L', -120021=>'L', -120022=>'L', -120023=>'L', -120024=>'L', -120025=>'L', -120026=>'L', -120027=>'L', -120028=>'L', -120029=>'L', -120030=>'L', -120031=>'L', -120032=>'L', -120033=>'L', -120034=>'L', -120035=>'L', -120036=>'L', -120037=>'L', -120038=>'L', -120039=>'L', -120040=>'L', -120041=>'L', -120042=>'L', -120043=>'L', -120044=>'L', -120045=>'L', -120046=>'L', -120047=>'L', -120048=>'L', -120049=>'L', -120050=>'L', -120051=>'L', -120052=>'L', -120053=>'L', -120054=>'L', -120055=>'L', -120056=>'L', -120057=>'L', -120058=>'L', -120059=>'L', -120060=>'L', -120061=>'L', -120062=>'L', -120063=>'L', -120064=>'L', -120065=>'L', -120066=>'L', -120067=>'L', -120068=>'L', -120069=>'L', -120071=>'L', -120072=>'L', -120073=>'L', -120074=>'L', -120077=>'L', -120078=>'L', -120079=>'L', -120080=>'L', -120081=>'L', -120082=>'L', -120083=>'L', -120084=>'L', -120086=>'L', -120087=>'L', -120088=>'L', -120089=>'L', -120090=>'L', -120091=>'L', -120092=>'L', -120094=>'L', -120095=>'L', -120096=>'L', -120097=>'L', -120098=>'L', -120099=>'L', -120100=>'L', -120101=>'L', -120102=>'L', -120103=>'L', -120104=>'L', -120105=>'L', -120106=>'L', -120107=>'L', -120108=>'L', -120109=>'L', -120110=>'L', -120111=>'L', -120112=>'L', -120113=>'L', -120114=>'L', -120115=>'L', -120116=>'L', -120117=>'L', -120118=>'L', -120119=>'L', -120120=>'L', -120121=>'L', -120123=>'L', -120124=>'L', -120125=>'L', -120126=>'L', -120128=>'L', -120129=>'L', -120130=>'L', -120131=>'L', -120132=>'L', -120134=>'L', -120138=>'L', -120139=>'L', -120140=>'L', -120141=>'L', -120142=>'L', -120143=>'L', -120144=>'L', -120146=>'L', -120147=>'L', -120148=>'L', -120149=>'L', -120150=>'L', -120151=>'L', -120152=>'L', -120153=>'L', -120154=>'L', -120155=>'L', -120156=>'L', -120157=>'L', -120158=>'L', -120159=>'L', -120160=>'L', -120161=>'L', -120162=>'L', -120163=>'L', -120164=>'L', -120165=>'L', -120166=>'L', -120167=>'L', -120168=>'L', -120169=>'L', -120170=>'L', -120171=>'L', -120172=>'L', -120173=>'L', -120174=>'L', -120175=>'L', -120176=>'L', -120177=>'L', -120178=>'L', -120179=>'L', -120180=>'L', -120181=>'L', -120182=>'L', -120183=>'L', -120184=>'L', -120185=>'L', -120186=>'L', -120187=>'L', -120188=>'L', -120189=>'L', -120190=>'L', -120191=>'L', -120192=>'L', -120193=>'L', -120194=>'L', -120195=>'L', -120196=>'L', -120197=>'L', -120198=>'L', -120199=>'L', -120200=>'L', -120201=>'L', -120202=>'L', -120203=>'L', -120204=>'L', -120205=>'L', -120206=>'L', -120207=>'L', -120208=>'L', -120209=>'L', -120210=>'L', -120211=>'L', -120212=>'L', -120213=>'L', -120214=>'L', -120215=>'L', -120216=>'L', -120217=>'L', -120218=>'L', -120219=>'L', -120220=>'L', -120221=>'L', -120222=>'L', -120223=>'L', -120224=>'L', -120225=>'L', -120226=>'L', -120227=>'L', -120228=>'L', -120229=>'L', -120230=>'L', -120231=>'L', -120232=>'L', -120233=>'L', -120234=>'L', -120235=>'L', -120236=>'L', -120237=>'L', -120238=>'L', -120239=>'L', -120240=>'L', -120241=>'L', -120242=>'L', -120243=>'L', -120244=>'L', -120245=>'L', -120246=>'L', -120247=>'L', -120248=>'L', -120249=>'L', -120250=>'L', -120251=>'L', -120252=>'L', -120253=>'L', -120254=>'L', -120255=>'L', -120256=>'L', -120257=>'L', -120258=>'L', -120259=>'L', -120260=>'L', -120261=>'L', -120262=>'L', -120263=>'L', -120264=>'L', -120265=>'L', -120266=>'L', -120267=>'L', -120268=>'L', -120269=>'L', -120270=>'L', -120271=>'L', -120272=>'L', -120273=>'L', -120274=>'L', -120275=>'L', -120276=>'L', -120277=>'L', -120278=>'L', -120279=>'L', -120280=>'L', -120281=>'L', -120282=>'L', -120283=>'L', -120284=>'L', -120285=>'L', -120286=>'L', -120287=>'L', -120288=>'L', -120289=>'L', -120290=>'L', -120291=>'L', -120292=>'L', -120293=>'L', -120294=>'L', -120295=>'L', -120296=>'L', -120297=>'L', -120298=>'L', -120299=>'L', -120300=>'L', -120301=>'L', -120302=>'L', -120303=>'L', -120304=>'L', -120305=>'L', -120306=>'L', -120307=>'L', -120308=>'L', -120309=>'L', -120310=>'L', -120311=>'L', -120312=>'L', -120313=>'L', -120314=>'L', -120315=>'L', -120316=>'L', -120317=>'L', -120318=>'L', -120319=>'L', -120320=>'L', -120321=>'L', -120322=>'L', -120323=>'L', -120324=>'L', -120325=>'L', -120326=>'L', -120327=>'L', -120328=>'L', -120329=>'L', -120330=>'L', -120331=>'L', -120332=>'L', -120333=>'L', -120334=>'L', -120335=>'L', -120336=>'L', -120337=>'L', -120338=>'L', -120339=>'L', -120340=>'L', -120341=>'L', -120342=>'L', -120343=>'L', -120344=>'L', -120345=>'L', -120346=>'L', -120347=>'L', -120348=>'L', -120349=>'L', -120350=>'L', -120351=>'L', -120352=>'L', -120353=>'L', -120354=>'L', -120355=>'L', -120356=>'L', -120357=>'L', -120358=>'L', -120359=>'L', -120360=>'L', -120361=>'L', -120362=>'L', -120363=>'L', -120364=>'L', -120365=>'L', -120366=>'L', -120367=>'L', -120368=>'L', -120369=>'L', -120370=>'L', -120371=>'L', -120372=>'L', -120373=>'L', -120374=>'L', -120375=>'L', -120376=>'L', -120377=>'L', -120378=>'L', -120379=>'L', -120380=>'L', -120381=>'L', -120382=>'L', -120383=>'L', -120384=>'L', -120385=>'L', -120386=>'L', -120387=>'L', -120388=>'L', -120389=>'L', -120390=>'L', -120391=>'L', -120392=>'L', -120393=>'L', -120394=>'L', -120395=>'L', -120396=>'L', -120397=>'L', -120398=>'L', -120399=>'L', -120400=>'L', -120401=>'L', -120402=>'L', -120403=>'L', -120404=>'L', -120405=>'L', -120406=>'L', -120407=>'L', -120408=>'L', -120409=>'L', -120410=>'L', -120411=>'L', -120412=>'L', -120413=>'L', -120414=>'L', -120415=>'L', -120416=>'L', -120417=>'L', -120418=>'L', -120419=>'L', -120420=>'L', -120421=>'L', -120422=>'L', -120423=>'L', -120424=>'L', -120425=>'L', -120426=>'L', -120427=>'L', -120428=>'L', -120429=>'L', -120430=>'L', -120431=>'L', -120432=>'L', -120433=>'L', -120434=>'L', -120435=>'L', -120436=>'L', -120437=>'L', -120438=>'L', -120439=>'L', -120440=>'L', -120441=>'L', -120442=>'L', -120443=>'L', -120444=>'L', -120445=>'L', -120446=>'L', -120447=>'L', -120448=>'L', -120449=>'L', -120450=>'L', -120451=>'L', -120452=>'L', -120453=>'L', -120454=>'L', -120455=>'L', -120456=>'L', -120457=>'L', -120458=>'L', -120459=>'L', -120460=>'L', -120461=>'L', -120462=>'L', -120463=>'L', -120464=>'L', -120465=>'L', -120466=>'L', -120467=>'L', -120468=>'L', -120469=>'L', -120470=>'L', -120471=>'L', -120472=>'L', -120473=>'L', -120474=>'L', -120475=>'L', -120476=>'L', -120477=>'L', -120478=>'L', -120479=>'L', -120480=>'L', -120481=>'L', -120482=>'L', -120483=>'L', -120484=>'L', -120485=>'L', -120488=>'L', -120489=>'L', -120490=>'L', -120491=>'L', -120492=>'L', -120493=>'L', -120494=>'L', -120495=>'L', -120496=>'L', -120497=>'L', -120498=>'L', -120499=>'L', -120500=>'L', -120501=>'L', -120502=>'L', -120503=>'L', -120504=>'L', -120505=>'L', -120506=>'L', -120507=>'L', -120508=>'L', -120509=>'L', -120510=>'L', -120511=>'L', -120512=>'L', -120513=>'L', -120514=>'L', -120515=>'L', -120516=>'L', -120517=>'L', -120518=>'L', -120519=>'L', -120520=>'L', -120521=>'L', -120522=>'L', -120523=>'L', -120524=>'L', -120525=>'L', -120526=>'L', -120527=>'L', -120528=>'L', -120529=>'L', -120530=>'L', -120531=>'L', -120532=>'L', -120533=>'L', -120534=>'L', -120535=>'L', -120536=>'L', -120537=>'L', -120538=>'L', -120539=>'L', -120540=>'L', -120541=>'L', -120542=>'L', -120543=>'L', -120544=>'L', -120545=>'L', -120546=>'L', -120547=>'L', -120548=>'L', -120549=>'L', -120550=>'L', -120551=>'L', -120552=>'L', -120553=>'L', -120554=>'L', -120555=>'L', -120556=>'L', -120557=>'L', -120558=>'L', -120559=>'L', -120560=>'L', -120561=>'L', -120562=>'L', -120563=>'L', -120564=>'L', -120565=>'L', -120566=>'L', -120567=>'L', -120568=>'L', -120569=>'L', -120570=>'L', -120571=>'L', -120572=>'L', -120573=>'L', -120574=>'L', -120575=>'L', -120576=>'L', -120577=>'L', -120578=>'L', -120579=>'L', -120580=>'L', -120581=>'L', -120582=>'L', -120583=>'L', -120584=>'L', -120585=>'L', -120586=>'L', -120587=>'L', -120588=>'L', -120589=>'L', -120590=>'L', -120591=>'L', -120592=>'L', -120593=>'L', -120594=>'L', -120595=>'L', -120596=>'L', -120597=>'L', -120598=>'L', -120599=>'L', -120600=>'L', -120601=>'L', -120602=>'L', -120603=>'L', -120604=>'L', -120605=>'L', -120606=>'L', -120607=>'L', -120608=>'L', -120609=>'L', -120610=>'L', -120611=>'L', -120612=>'L', -120613=>'L', -120614=>'L', -120615=>'L', -120616=>'L', -120617=>'L', -120618=>'L', -120619=>'L', -120620=>'L', -120621=>'L', -120622=>'L', -120623=>'L', -120624=>'L', -120625=>'L', -120626=>'L', -120627=>'L', -120628=>'L', -120629=>'L', -120630=>'L', -120631=>'L', -120632=>'L', -120633=>'L', -120634=>'L', -120635=>'L', -120636=>'L', -120637=>'L', -120638=>'L', -120639=>'L', -120640=>'L', -120641=>'L', -120642=>'L', -120643=>'L', -120644=>'L', -120645=>'L', -120646=>'L', -120647=>'L', -120648=>'L', -120649=>'L', -120650=>'L', -120651=>'L', -120652=>'L', -120653=>'L', -120654=>'L', -120655=>'L', -120656=>'L', -120657=>'L', -120658=>'L', -120659=>'L', -120660=>'L', -120661=>'L', -120662=>'L', -120663=>'L', -120664=>'L', -120665=>'L', -120666=>'L', -120667=>'L', -120668=>'L', -120669=>'L', -120670=>'L', -120671=>'L', -120672=>'L', -120673=>'L', -120674=>'L', -120675=>'L', -120676=>'L', -120677=>'L', -120678=>'L', -120679=>'L', -120680=>'L', -120681=>'L', -120682=>'L', -120683=>'L', -120684=>'L', -120685=>'L', -120686=>'L', -120687=>'L', -120688=>'L', -120689=>'L', -120690=>'L', -120691=>'L', -120692=>'L', -120693=>'L', -120694=>'L', -120695=>'L', -120696=>'L', -120697=>'L', -120698=>'L', -120699=>'L', -120700=>'L', -120701=>'L', -120702=>'L', -120703=>'L', -120704=>'L', -120705=>'L', -120706=>'L', -120707=>'L', -120708=>'L', -120709=>'L', -120710=>'L', -120711=>'L', -120712=>'L', -120713=>'L', -120714=>'L', -120715=>'L', -120716=>'L', -120717=>'L', -120718=>'L', -120719=>'L', -120720=>'L', -120721=>'L', -120722=>'L', -120723=>'L', -120724=>'L', -120725=>'L', -120726=>'L', -120727=>'L', -120728=>'L', -120729=>'L', -120730=>'L', -120731=>'L', -120732=>'L', -120733=>'L', -120734=>'L', -120735=>'L', -120736=>'L', -120737=>'L', -120738=>'L', -120739=>'L', -120740=>'L', -120741=>'L', -120742=>'L', -120743=>'L', -120744=>'L', -120745=>'L', -120746=>'L', -120747=>'L', -120748=>'L', -120749=>'L', -120750=>'L', -120751=>'L', -120752=>'L', -120753=>'L', -120754=>'L', -120755=>'L', -120756=>'L', -120757=>'L', -120758=>'L', -120759=>'L', -120760=>'L', -120761=>'L', -120762=>'L', -120763=>'L', -120764=>'L', -120765=>'L', -120766=>'L', -120767=>'L', -120768=>'L', -120769=>'L', -120770=>'L', -120771=>'L', -120772=>'L', -120773=>'L', -120774=>'L', -120775=>'L', -120776=>'L', -120777=>'L', -120778=>'L', -120779=>'L', -120782=>'EN', -120783=>'EN', -120784=>'EN', -120785=>'EN', -120786=>'EN', -120787=>'EN', -120788=>'EN', -120789=>'EN', -120790=>'EN', -120791=>'EN', -120792=>'EN', -120793=>'EN', -120794=>'EN', -120795=>'EN', -120796=>'EN', -120797=>'EN', -120798=>'EN', -120799=>'EN', -120800=>'EN', -120801=>'EN', -120802=>'EN', -120803=>'EN', -120804=>'EN', -120805=>'EN', -120806=>'EN', -120807=>'EN', -120808=>'EN', -120809=>'EN', -120810=>'EN', -120811=>'EN', -120812=>'EN', -120813=>'EN', -120814=>'EN', -120815=>'EN', -120816=>'EN', -120817=>'EN', -120818=>'EN', -120819=>'EN', -120820=>'EN', -120821=>'EN', -120822=>'EN', -120823=>'EN', -120824=>'EN', -120825=>'EN', -120826=>'EN', -120827=>'EN', -120828=>'EN', -120829=>'EN', -120830=>'EN', -120831=>'EN', -131072=>'L', -173782=>'L', -194560=>'L', -194561=>'L', -194562=>'L', -194563=>'L', -194564=>'L', -194565=>'L', -194566=>'L', -194567=>'L', -194568=>'L', -194569=>'L', -194570=>'L', -194571=>'L', -194572=>'L', -194573=>'L', -194574=>'L', -194575=>'L', -194576=>'L', -194577=>'L', -194578=>'L', -194579=>'L', -194580=>'L', -194581=>'L', -194582=>'L', -194583=>'L', -194584=>'L', -194585=>'L', -194586=>'L', -194587=>'L', -194588=>'L', -194589=>'L', -194590=>'L', -194591=>'L', -194592=>'L', -194593=>'L', -194594=>'L', -194595=>'L', -194596=>'L', -194597=>'L', -194598=>'L', -194599=>'L', -194600=>'L', -194601=>'L', -194602=>'L', -194603=>'L', -194604=>'L', -194605=>'L', -194606=>'L', -194607=>'L', -194608=>'L', -194609=>'L', -194610=>'L', -194611=>'L', -194612=>'L', -194613=>'L', -194614=>'L', -194615=>'L', -194616=>'L', -194617=>'L', -194618=>'L', -194619=>'L', -194620=>'L', -194621=>'L', -194622=>'L', -194623=>'L', -194624=>'L', -194625=>'L', -194626=>'L', -194627=>'L', -194628=>'L', -194629=>'L', -194630=>'L', -194631=>'L', -194632=>'L', -194633=>'L', -194634=>'L', -194635=>'L', -194636=>'L', -194637=>'L', -194638=>'L', -194639=>'L', -194640=>'L', -194641=>'L', -194642=>'L', -194643=>'L', -194644=>'L', -194645=>'L', -194646=>'L', -194647=>'L', -194648=>'L', -194649=>'L', -194650=>'L', -194651=>'L', -194652=>'L', -194653=>'L', -194654=>'L', -194655=>'L', -194656=>'L', -194657=>'L', -194658=>'L', -194659=>'L', -194660=>'L', -194661=>'L', -194662=>'L', -194663=>'L', -194664=>'L', -194665=>'L', -194666=>'L', -194667=>'L', -194668=>'L', -194669=>'L', -194670=>'L', -194671=>'L', -194672=>'L', -194673=>'L', -194674=>'L', -194675=>'L', -194676=>'L', -194677=>'L', -194678=>'L', -194679=>'L', -194680=>'L', -194681=>'L', -194682=>'L', -194683=>'L', -194684=>'L', -194685=>'L', -194686=>'L', -194687=>'L', -194688=>'L', -194689=>'L', -194690=>'L', -194691=>'L', -194692=>'L', -194693=>'L', -194694=>'L', -194695=>'L', -194696=>'L', -194697=>'L', -194698=>'L', -194699=>'L', -194700=>'L', -194701=>'L', -194702=>'L', -194703=>'L', -194704=>'L', -194705=>'L', -194706=>'L', -194707=>'L', -194708=>'L', -194709=>'L', -194710=>'L', -194711=>'L', -194712=>'L', -194713=>'L', -194714=>'L', -194715=>'L', -194716=>'L', -194717=>'L', -194718=>'L', -194719=>'L', -194720=>'L', -194721=>'L', -194722=>'L', -194723=>'L', -194724=>'L', -194725=>'L', -194726=>'L', -194727=>'L', -194728=>'L', -194729=>'L', -194730=>'L', -194731=>'L', -194732=>'L', -194733=>'L', -194734=>'L', -194735=>'L', -194736=>'L', -194737=>'L', -194738=>'L', -194739=>'L', -194740=>'L', -194741=>'L', -194742=>'L', -194743=>'L', -194744=>'L', -194745=>'L', -194746=>'L', -194747=>'L', -194748=>'L', -194749=>'L', -194750=>'L', -194751=>'L', -194752=>'L', -194753=>'L', -194754=>'L', -194755=>'L', -194756=>'L', -194757=>'L', -194758=>'L', -194759=>'L', -194760=>'L', -194761=>'L', -194762=>'L', -194763=>'L', -194764=>'L', -194765=>'L', -194766=>'L', -194767=>'L', -194768=>'L', -194769=>'L', -194770=>'L', -194771=>'L', -194772=>'L', -194773=>'L', -194774=>'L', -194775=>'L', -194776=>'L', -194777=>'L', -194778=>'L', -194779=>'L', -194780=>'L', -194781=>'L', -194782=>'L', -194783=>'L', -194784=>'L', -194785=>'L', -194786=>'L', -194787=>'L', -194788=>'L', -194789=>'L', -194790=>'L', -194791=>'L', -194792=>'L', -194793=>'L', -194794=>'L', -194795=>'L', -194796=>'L', -194797=>'L', -194798=>'L', -194799=>'L', -194800=>'L', -194801=>'L', -194802=>'L', -194803=>'L', -194804=>'L', -194805=>'L', -194806=>'L', -194807=>'L', -194808=>'L', -194809=>'L', -194810=>'L', -194811=>'L', -194812=>'L', -194813=>'L', -194814=>'L', -194815=>'L', -194816=>'L', -194817=>'L', -194818=>'L', -194819=>'L', -194820=>'L', -194821=>'L', -194822=>'L', -194823=>'L', -194824=>'L', -194825=>'L', -194826=>'L', -194827=>'L', -194828=>'L', -194829=>'L', -194830=>'L', -194831=>'L', -194832=>'L', -194833=>'L', -194834=>'L', -194835=>'L', -194836=>'L', -194837=>'L', -194838=>'L', -194839=>'L', -194840=>'L', -194841=>'L', -194842=>'L', -194843=>'L', -194844=>'L', -194845=>'L', -194846=>'L', -194847=>'L', -194848=>'L', -194849=>'L', -194850=>'L', -194851=>'L', -194852=>'L', -194853=>'L', -194854=>'L', -194855=>'L', -194856=>'L', -194857=>'L', -194858=>'L', -194859=>'L', -194860=>'L', -194861=>'L', -194862=>'L', -194863=>'L', -194864=>'L', -194865=>'L', -194866=>'L', -194867=>'L', -194868=>'L', -194869=>'L', -194870=>'L', -194871=>'L', -194872=>'L', -194873=>'L', -194874=>'L', -194875=>'L', -194876=>'L', -194877=>'L', -194878=>'L', -194879=>'L', -194880=>'L', -194881=>'L', -194882=>'L', -194883=>'L', -194884=>'L', -194885=>'L', -194886=>'L', -194887=>'L', -194888=>'L', -194889=>'L', -194890=>'L', -194891=>'L', -194892=>'L', -194893=>'L', -194894=>'L', -194895=>'L', -194896=>'L', -194897=>'L', -194898=>'L', -194899=>'L', -194900=>'L', -194901=>'L', -194902=>'L', -194903=>'L', -194904=>'L', -194905=>'L', -194906=>'L', -194907=>'L', -194908=>'L', -194909=>'L', -194910=>'L', -194911=>'L', -194912=>'L', -194913=>'L', -194914=>'L', -194915=>'L', -194916=>'L', -194917=>'L', -194918=>'L', -194919=>'L', -194920=>'L', -194921=>'L', -194922=>'L', -194923=>'L', -194924=>'L', -194925=>'L', -194926=>'L', -194927=>'L', -194928=>'L', -194929=>'L', -194930=>'L', -194931=>'L', -194932=>'L', -194933=>'L', -194934=>'L', -194935=>'L', -194936=>'L', -194937=>'L', -194938=>'L', -194939=>'L', -194940=>'L', -194941=>'L', -194942=>'L', -194943=>'L', -194944=>'L', -194945=>'L', -194946=>'L', -194947=>'L', -194948=>'L', -194949=>'L', -194950=>'L', -194951=>'L', -194952=>'L', -194953=>'L', -194954=>'L', -194955=>'L', -194956=>'L', -194957=>'L', -194958=>'L', -194959=>'L', -194960=>'L', -194961=>'L', -194962=>'L', -194963=>'L', -194964=>'L', -194965=>'L', -194966=>'L', -194967=>'L', -194968=>'L', -194969=>'L', -194970=>'L', -194971=>'L', -194972=>'L', -194973=>'L', -194974=>'L', -194975=>'L', -194976=>'L', -194977=>'L', -194978=>'L', -194979=>'L', -194980=>'L', -194981=>'L', -194982=>'L', -194983=>'L', -194984=>'L', -194985=>'L', -194986=>'L', -194987=>'L', -194988=>'L', -194989=>'L', -194990=>'L', -194991=>'L', -194992=>'L', -194993=>'L', -194994=>'L', -194995=>'L', -194996=>'L', -194997=>'L', -194998=>'L', -194999=>'L', -195000=>'L', -195001=>'L', -195002=>'L', -195003=>'L', -195004=>'L', -195005=>'L', -195006=>'L', -195007=>'L', -195008=>'L', -195009=>'L', -195010=>'L', -195011=>'L', -195012=>'L', -195013=>'L', -195014=>'L', -195015=>'L', -195016=>'L', -195017=>'L', -195018=>'L', -195019=>'L', -195020=>'L', -195021=>'L', -195022=>'L', -195023=>'L', -195024=>'L', -195025=>'L', -195026=>'L', -195027=>'L', -195028=>'L', -195029=>'L', -195030=>'L', -195031=>'L', -195032=>'L', -195033=>'L', -195034=>'L', -195035=>'L', -195036=>'L', -195037=>'L', -195038=>'L', -195039=>'L', -195040=>'L', -195041=>'L', -195042=>'L', -195043=>'L', -195044=>'L', -195045=>'L', -195046=>'L', -195047=>'L', -195048=>'L', -195049=>'L', -195050=>'L', -195051=>'L', -195052=>'L', -195053=>'L', -195054=>'L', -195055=>'L', -195056=>'L', -195057=>'L', -195058=>'L', -195059=>'L', -195060=>'L', -195061=>'L', -195062=>'L', -195063=>'L', -195064=>'L', -195065=>'L', -195066=>'L', -195067=>'L', -195068=>'L', -195069=>'L', -195070=>'L', -195071=>'L', -195072=>'L', -195073=>'L', -195074=>'L', -195075=>'L', -195076=>'L', -195077=>'L', -195078=>'L', -195079=>'L', -195080=>'L', -195081=>'L', -195082=>'L', -195083=>'L', -195084=>'L', -195085=>'L', -195086=>'L', -195087=>'L', -195088=>'L', -195089=>'L', -195090=>'L', -195091=>'L', -195092=>'L', -195093=>'L', -195094=>'L', -195095=>'L', -195096=>'L', -195097=>'L', -195098=>'L', -195099=>'L', -195100=>'L', -195101=>'L', -917505=>'BN', -917536=>'BN', -917537=>'BN', -917538=>'BN', -917539=>'BN', -917540=>'BN', -917541=>'BN', -917542=>'BN', -917543=>'BN', -917544=>'BN', -917545=>'BN', -917546=>'BN', -917547=>'BN', -917548=>'BN', -917549=>'BN', -917550=>'BN', -917551=>'BN', -917552=>'BN', -917553=>'BN', -917554=>'BN', -917555=>'BN', -917556=>'BN', -917557=>'BN', -917558=>'BN', -917559=>'BN', -917560=>'BN', -917561=>'BN', -917562=>'BN', -917563=>'BN', -917564=>'BN', -917565=>'BN', -917566=>'BN', -917567=>'BN', -917568=>'BN', -917569=>'BN', -917570=>'BN', -917571=>'BN', -917572=>'BN', -917573=>'BN', -917574=>'BN', -917575=>'BN', -917576=>'BN', -917577=>'BN', -917578=>'BN', -917579=>'BN', -917580=>'BN', -917581=>'BN', -917582=>'BN', -917583=>'BN', -917584=>'BN', -917585=>'BN', -917586=>'BN', -917587=>'BN', -917588=>'BN', -917589=>'BN', -917590=>'BN', -917591=>'BN', -917592=>'BN', -917593=>'BN', -917594=>'BN', -917595=>'BN', -917596=>'BN', -917597=>'BN', -917598=>'BN', -917599=>'BN', -917600=>'BN', -917601=>'BN', -917602=>'BN', -917603=>'BN', -917604=>'BN', -917605=>'BN', -917606=>'BN', -917607=>'BN', -917608=>'BN', -917609=>'BN', -917610=>'BN', -917611=>'BN', -917612=>'BN', -917613=>'BN', -917614=>'BN', -917615=>'BN', -917616=>'BN', -917617=>'BN', -917618=>'BN', -917619=>'BN', -917620=>'BN', -917621=>'BN', -917622=>'BN', -917623=>'BN', -917624=>'BN', -917625=>'BN', -917626=>'BN', -917627=>'BN', -917628=>'BN', -917629=>'BN', -917630=>'BN', -917631=>'BN', -917760=>'NSM', -917761=>'NSM', -917762=>'NSM', -917763=>'NSM', -917764=>'NSM', -917765=>'NSM', -917766=>'NSM', -917767=>'NSM', -917768=>'NSM', -917769=>'NSM', -917770=>'NSM', -917771=>'NSM', -917772=>'NSM', -917773=>'NSM', -917774=>'NSM', -917775=>'NSM', -917776=>'NSM', -917777=>'NSM', -917778=>'NSM', -917779=>'NSM', -917780=>'NSM', -917781=>'NSM', -917782=>'NSM', -917783=>'NSM', -917784=>'NSM', -917785=>'NSM', -917786=>'NSM', -917787=>'NSM', -917788=>'NSM', -917789=>'NSM', -917790=>'NSM', -917791=>'NSM', -917792=>'NSM', -917793=>'NSM', -917794=>'NSM', -917795=>'NSM', -917796=>'NSM', -917797=>'NSM', -917798=>'NSM', -917799=>'NSM', -917800=>'NSM', -917801=>'NSM', -917802=>'NSM', -917803=>'NSM', -917804=>'NSM', -917805=>'NSM', -917806=>'NSM', -917807=>'NSM', -917808=>'NSM', -917809=>'NSM', -917810=>'NSM', -917811=>'NSM', -917812=>'NSM', -917813=>'NSM', -917814=>'NSM', -917815=>'NSM', -917816=>'NSM', -917817=>'NSM', -917818=>'NSM', -917819=>'NSM', -917820=>'NSM', -917821=>'NSM', -917822=>'NSM', -917823=>'NSM', -917824=>'NSM', -917825=>'NSM', -917826=>'NSM', -917827=>'NSM', -917828=>'NSM', -917829=>'NSM', -917830=>'NSM', -917831=>'NSM', -917832=>'NSM', -917833=>'NSM', -917834=>'NSM', -917835=>'NSM', -917836=>'NSM', -917837=>'NSM', -917838=>'NSM', -917839=>'NSM', -917840=>'NSM', -917841=>'NSM', -917842=>'NSM', -917843=>'NSM', -917844=>'NSM', -917845=>'NSM', -917846=>'NSM', -917847=>'NSM', -917848=>'NSM', -917849=>'NSM', -917850=>'NSM', -917851=>'NSM', -917852=>'NSM', -917853=>'NSM', -917854=>'NSM', -917855=>'NSM', -917856=>'NSM', -917857=>'NSM', -917858=>'NSM', -917859=>'NSM', -917860=>'NSM', -917861=>'NSM', -917862=>'NSM', -917863=>'NSM', -917864=>'NSM', -917865=>'NSM', -917866=>'NSM', -917867=>'NSM', -917868=>'NSM', -917869=>'NSM', -917870=>'NSM', -917871=>'NSM', -917872=>'NSM', -917873=>'NSM', -917874=>'NSM', -917875=>'NSM', -917876=>'NSM', -917877=>'NSM', -917878=>'NSM', -917879=>'NSM', -917880=>'NSM', -917881=>'NSM', -917882=>'NSM', -917883=>'NSM', -917884=>'NSM', -917885=>'NSM', -917886=>'NSM', -917887=>'NSM', -917888=>'NSM', -917889=>'NSM', -917890=>'NSM', -917891=>'NSM', -917892=>'NSM', -917893=>'NSM', -917894=>'NSM', -917895=>'NSM', -917896=>'NSM', -917897=>'NSM', -917898=>'NSM', -917899=>'NSM', -917900=>'NSM', -917901=>'NSM', -917902=>'NSM', -917903=>'NSM', -917904=>'NSM', -917905=>'NSM', -917906=>'NSM', -917907=>'NSM', -917908=>'NSM', -917909=>'NSM', -917910=>'NSM', -917911=>'NSM', -917912=>'NSM', -917913=>'NSM', -917914=>'NSM', -917915=>'NSM', -917916=>'NSM', -917917=>'NSM', -917918=>'NSM', -917919=>'NSM', -917920=>'NSM', -917921=>'NSM', -917922=>'NSM', -917923=>'NSM', -917924=>'NSM', -917925=>'NSM', -917926=>'NSM', -917927=>'NSM', -917928=>'NSM', -917929=>'NSM', -917930=>'NSM', -917931=>'NSM', -917932=>'NSM', -917933=>'NSM', -917934=>'NSM', -917935=>'NSM', -917936=>'NSM', -917937=>'NSM', -917938=>'NSM', -917939=>'NSM', -917940=>'NSM', -917941=>'NSM', -917942=>'NSM', -917943=>'NSM', -917944=>'NSM', -917945=>'NSM', -917946=>'NSM', -917947=>'NSM', -917948=>'NSM', -917949=>'NSM', -917950=>'NSM', -917951=>'NSM', -917952=>'NSM', -917953=>'NSM', -917954=>'NSM', -917955=>'NSM', -917956=>'NSM', -917957=>'NSM', -917958=>'NSM', -917959=>'NSM', -917960=>'NSM', -917961=>'NSM', -917962=>'NSM', -917963=>'NSM', -917964=>'NSM', -917965=>'NSM', -917966=>'NSM', -917967=>'NSM', -917968=>'NSM', -917969=>'NSM', -917970=>'NSM', -917971=>'NSM', -917972=>'NSM', -917973=>'NSM', -917974=>'NSM', -917975=>'NSM', -917976=>'NSM', -917977=>'NSM', -917978=>'NSM', -917979=>'NSM', -917980=>'NSM', -917981=>'NSM', -917982=>'NSM', -917983=>'NSM', -917984=>'NSM', -917985=>'NSM', -917986=>'NSM', -917987=>'NSM', -917988=>'NSM', -917989=>'NSM', -917990=>'NSM', -917991=>'NSM', -917992=>'NSM', -917993=>'NSM', -917994=>'NSM', -917995=>'NSM', -917996=>'NSM', -917997=>'NSM', -917998=>'NSM', -917999=>'NSM', -983040=>'L', -1048573=>'L', -1048576=>'L', -1114109=>'L' -); - -/** - * Mirror unicode characters. For information on bidi mirroring, see UAX #9: Bidirectional Algorithm, at http://www.unicode.org/unicode/reports/tr9/ - * @public - */ -public static $uni_mirror = array ( -0x0028=>0x0029, -0x0029=>0x0028, -0x003C=>0x003E, -0x003E=>0x003C, -0x005B=>0x005D, -0x005D=>0x005B, -0x007B=>0x007D, -0x007D=>0x007B, -0x00AB=>0x00BB, -0x00BB=>0x00AB, -0x0F3A=>0x0F3B, -0x0F3B=>0x0F3A, -0x0F3C=>0x0F3D, -0x0F3D=>0x0F3C, -0x169B=>0x169C, -0x169C=>0x169B, -0x2018=>0x2019, -0x2019=>0x2018, -0x201C=>0x201D, -0x201D=>0x201C, -0x2039=>0x203A, -0x203A=>0x2039, -0x2045=>0x2046, -0x2046=>0x2045, -0x207D=>0x207E, -0x207E=>0x207D, -0x208D=>0x208E, -0x208E=>0x208D, -0x2208=>0x220B, -0x2209=>0x220C, -0x220A=>0x220D, -0x220B=>0x2208, -0x220C=>0x2209, -0x220D=>0x220A, -0x2215=>0x29F5, -0x223C=>0x223D, -0x223D=>0x223C, -0x2243=>0x22CD, -0x2252=>0x2253, -0x2253=>0x2252, -0x2254=>0x2255, -0x2255=>0x2254, -0x2264=>0x2265, -0x2265=>0x2264, -0x2266=>0x2267, -0x2267=>0x2266, -0x2268=>0x2269, -0x2269=>0x2268, -0x226A=>0x226B, -0x226B=>0x226A, -0x226E=>0x226F, -0x226F=>0x226E, -0x2270=>0x2271, -0x2271=>0x2270, -0x2272=>0x2273, -0x2273=>0x2272, -0x2274=>0x2275, -0x2275=>0x2274, -0x2276=>0x2277, -0x2277=>0x2276, -0x2278=>0x2279, -0x2279=>0x2278, -0x227A=>0x227B, -0x227B=>0x227A, -0x227C=>0x227D, -0x227D=>0x227C, -0x227E=>0x227F, -0x227F=>0x227E, -0x2280=>0x2281, -0x2281=>0x2280, -0x2282=>0x2283, -0x2283=>0x2282, -0x2284=>0x2285, -0x2285=>0x2284, -0x2286=>0x2287, -0x2287=>0x2286, -0x2288=>0x2289, -0x2289=>0x2288, -0x228A=>0x228B, -0x228B=>0x228A, -0x228F=>0x2290, -0x2290=>0x228F, -0x2291=>0x2292, -0x2292=>0x2291, -0x2298=>0x29B8, -0x22A2=>0x22A3, -0x22A3=>0x22A2, -0x22A6=>0x2ADE, -0x22A8=>0x2AE4, -0x22A9=>0x2AE3, -0x22AB=>0x2AE5, -0x22B0=>0x22B1, -0x22B1=>0x22B0, -0x22B2=>0x22B3, -0x22B3=>0x22B2, -0x22B4=>0x22B5, -0x22B5=>0x22B4, -0x22B6=>0x22B7, -0x22B7=>0x22B6, -0x22C9=>0x22CA, -0x22CA=>0x22C9, -0x22CB=>0x22CC, -0x22CC=>0x22CB, -0x22CD=>0x2243, -0x22D0=>0x22D1, -0x22D1=>0x22D0, -0x22D6=>0x22D7, -0x22D7=>0x22D6, -0x22D8=>0x22D9, -0x22D9=>0x22D8, -0x22DA=>0x22DB, -0x22DB=>0x22DA, -0x22DC=>0x22DD, -0x22DD=>0x22DC, -0x22DE=>0x22DF, -0x22DF=>0x22DE, -0x22E0=>0x22E1, -0x22E1=>0x22E0, -0x22E2=>0x22E3, -0x22E3=>0x22E2, -0x22E4=>0x22E5, -0x22E5=>0x22E4, -0x22E6=>0x22E7, -0x22E7=>0x22E6, -0x22E8=>0x22E9, -0x22E9=>0x22E8, -0x22EA=>0x22EB, -0x22EB=>0x22EA, -0x22EC=>0x22ED, -0x22ED=>0x22EC, -0x22F0=>0x22F1, -0x22F1=>0x22F0, -0x22F2=>0x22FA, -0x22F3=>0x22FB, -0x22F4=>0x22FC, -0x22F6=>0x22FD, -0x22F7=>0x22FE, -0x22FA=>0x22F2, -0x22FB=>0x22F3, -0x22FC=>0x22F4, -0x22FD=>0x22F6, -0x22FE=>0x22F7, -0x2308=>0x2309, -0x2309=>0x2308, -0x230A=>0x230B, -0x230B=>0x230A, -0x2329=>0x232A, -0x232A=>0x2329, -0x2768=>0x2769, -0x2769=>0x2768, -0x276A=>0x276B, -0x276B=>0x276A, -0x276C=>0x276D, -0x276D=>0x276C, -0x276E=>0x276F, -0x276F=>0x276E, -0x2770=>0x2771, -0x2771=>0x2770, -0x2772=>0x2773, -0x2773=>0x2772, -0x2774=>0x2775, -0x2775=>0x2774, -0x27C3=>0x27C4, -0x27C4=>0x27C3, -0x27C5=>0x27C6, -0x27C6=>0x27C5, -0x27D5=>0x27D6, -0x27D6=>0x27D5, -0x27DD=>0x27DE, -0x27DE=>0x27DD, -0x27E2=>0x27E3, -0x27E3=>0x27E2, -0x27E4=>0x27E5, -0x27E5=>0x27E4, -0x27E6=>0x27E7, -0x27E7=>0x27E6, -0x27E8=>0x27E9, -0x27E9=>0x27E8, -0x27EA=>0x27EB, -0x27EB=>0x27EA, -0x2983=>0x2984, -0x2984=>0x2983, -0x2985=>0x2986, -0x2986=>0x2985, -0x2987=>0x2988, -0x2988=>0x2987, -0x2989=>0x298A, -0x298A=>0x2989, -0x298B=>0x298C, -0x298C=>0x298B, -0x298D=>0x2990, -0x298E=>0x298F, -0x298F=>0x298E, -0x2990=>0x298D, -0x2991=>0x2992, -0x2992=>0x2991, -0x2993=>0x2994, -0x2994=>0x2993, -0x2995=>0x2996, -0x2996=>0x2995, -0x2997=>0x2998, -0x2998=>0x2997, -0x29B8=>0x2298, -0x29C0=>0x29C1, -0x29C1=>0x29C0, -0x29C4=>0x29C5, -0x29C5=>0x29C4, -0x29CF=>0x29D0, -0x29D0=>0x29CF, -0x29D1=>0x29D2, -0x29D2=>0x29D1, -0x29D4=>0x29D5, -0x29D5=>0x29D4, -0x29D8=>0x29D9, -0x29D9=>0x29D8, -0x29DA=>0x29DB, -0x29DB=>0x29DA, -0x29F5=>0x2215, -0x29F8=>0x29F9, -0x29F9=>0x29F8, -0x29FC=>0x29FD, -0x29FD=>0x29FC, -0x2A2B=>0x2A2C, -0x2A2C=>0x2A2B, -0x2A2D=>0x2A2E, -0x2A2E=>0x2A2D, -0x2A34=>0x2A35, -0x2A35=>0x2A34, -0x2A3C=>0x2A3D, -0x2A3D=>0x2A3C, -0x2A64=>0x2A65, -0x2A65=>0x2A64, -0x2A79=>0x2A7A, -0x2A7A=>0x2A79, -0x2A7D=>0x2A7E, -0x2A7E=>0x2A7D, -0x2A7F=>0x2A80, -0x2A80=>0x2A7F, -0x2A81=>0x2A82, -0x2A82=>0x2A81, -0x2A83=>0x2A84, -0x2A84=>0x2A83, -0x2A8B=>0x2A8C, -0x2A8C=>0x2A8B, -0x2A91=>0x2A92, -0x2A92=>0x2A91, -0x2A93=>0x2A94, -0x2A94=>0x2A93, -0x2A95=>0x2A96, -0x2A96=>0x2A95, -0x2A97=>0x2A98, -0x2A98=>0x2A97, -0x2A99=>0x2A9A, -0x2A9A=>0x2A99, -0x2A9B=>0x2A9C, -0x2A9C=>0x2A9B, -0x2AA1=>0x2AA2, -0x2AA2=>0x2AA1, -0x2AA6=>0x2AA7, -0x2AA7=>0x2AA6, -0x2AA8=>0x2AA9, -0x2AA9=>0x2AA8, -0x2AAA=>0x2AAB, -0x2AAB=>0x2AAA, -0x2AAC=>0x2AAD, -0x2AAD=>0x2AAC, -0x2AAF=>0x2AB0, -0x2AB0=>0x2AAF, -0x2AB3=>0x2AB4, -0x2AB4=>0x2AB3, -0x2ABB=>0x2ABC, -0x2ABC=>0x2ABB, -0x2ABD=>0x2ABE, -0x2ABE=>0x2ABD, -0x2ABF=>0x2AC0, -0x2AC0=>0x2ABF, -0x2AC1=>0x2AC2, -0x2AC2=>0x2AC1, -0x2AC3=>0x2AC4, -0x2AC4=>0x2AC3, -0x2AC5=>0x2AC6, -0x2AC6=>0x2AC5, -0x2ACD=>0x2ACE, -0x2ACE=>0x2ACD, -0x2ACF=>0x2AD0, -0x2AD0=>0x2ACF, -0x2AD1=>0x2AD2, -0x2AD2=>0x2AD1, -0x2AD3=>0x2AD4, -0x2AD4=>0x2AD3, -0x2AD5=>0x2AD6, -0x2AD6=>0x2AD5, -0x2ADE=>0x22A6, -0x2AE3=>0x22A9, -0x2AE4=>0x22A8, -0x2AE5=>0x22AB, -0x2AEC=>0x2AED, -0x2AED=>0x2AEC, -0x2AF7=>0x2AF8, -0x2AF8=>0x2AF7, -0x2AF9=>0x2AFA, -0x2AFA=>0x2AF9, -0x2E02=>0x2E03, -0x2E03=>0x2E02, -0x2E04=>0x2E05, -0x2E05=>0x2E04, -0x2E09=>0x2E0A, -0x2E0A=>0x2E09, -0x2E0C=>0x2E0D, -0x2E0D=>0x2E0C, -0x2E1C=>0x2E1D, -0x2E1D=>0x2E1C, -0x3008=>0x3009, -0x3009=>0x3008, -0x300A=>0x300B, -0x300B=>0x300A, -0x300C=>0x300D, -0x300D=>0x300C, -0x300E=>0x300F, -0x300F=>0x300E, -0x3010=>0x3011, -0x3011=>0x3010, -0x3014=>0x3015, -0x3015=>0x3014, -0x3016=>0x3017, -0x3017=>0x3016, -0x3018=>0x3019, -0x3019=>0x3018, -0x301A=>0x301B, -0x301B=>0x301A, -0x301D=>0x301E, -0x301E=>0x301D, -0xFE59=>0xFE5A, -0xFE5A=>0xFE59, -0xFE5B=>0xFE5C, -0xFE5C=>0xFE5B, -0xFE5D=>0xFE5E, -0xFE5E=>0xFE5D, -0xFE64=>0xFE65, -0xFE65=>0xFE64, -0xFF08=>0xFF09, -0xFF09=>0xFF08, -0xFF1C=>0xFF1E, -0xFF1E=>0xFF1C, -0xFF3B=>0xFF3D, -0xFF3D=>0xFF3B, -0xFF5B=>0xFF5D, -0xFF5D=>0xFF5B, -0xFF5F=>0xFF60, -0xFF60=>0xFF5F, -0xFF62=>0xFF63, -0xFF63=>0xFF62); - -/** - * Arabic shape substitutions: char code => (isolated, final, initial, medial). - * @public - */ -public static $uni_arabicsubst = array( -1569=>array(65152), -1570=>array(65153, 65154, 65153, 65154), -1571=>array(65155, 65156, 65155, 65156), -1572=>array(65157, 65158), -1573=>array(65159, 65160, 65159, 65160), -1574=>array(65161, 65162, 65163, 65164), -1575=>array(65165, 65166, 65165, 65166), -1576=>array(65167, 65168, 65169, 65170), -1577=>array(65171, 65172), -1578=>array(65173, 65174, 65175, 65176), -1579=>array(65177, 65178, 65179, 65180), -1580=>array(65181, 65182, 65183, 65184), -1581=>array(65185, 65186, 65187, 65188), -1582=>array(65189, 65190, 65191, 65192), -1583=>array(65193, 65194, 65193, 65194), -1584=>array(65195, 65196, 65195, 65196), -1585=>array(65197, 65198, 65197, 65198), -1586=>array(65199, 65200, 65199, 65200), -1587=>array(65201, 65202, 65203, 65204), -1588=>array(65205, 65206, 65207, 65208), -1589=>array(65209, 65210, 65211, 65212), -1590=>array(65213, 65214, 65215, 65216), -1591=>array(65217, 65218, 65219, 65220), -1592=>array(65221, 65222, 65223, 65224), -1593=>array(65225, 65226, 65227, 65228), -1594=>array(65229, 65230, 65231, 65232), -1601=>array(65233, 65234, 65235, 65236), -1602=>array(65237, 65238, 65239, 65240), -1603=>array(65241, 65242, 65243, 65244), -1604=>array(65245, 65246, 65247, 65248), -1605=>array(65249, 65250, 65251, 65252), -1606=>array(65253, 65254, 65255, 65256), -1607=>array(65257, 65258, 65259, 65260), -1608=>array(65261, 65262, 65261, 65262), -1609=>array(65263, 65264, 64488, 64489), -1610=>array(65265, 65266, 65267, 65268), -1649=>array(64336, 64337), -1655=>array(64477), -1657=>array(64358, 64359, 64360, 64361), -1658=>array(64350, 64351, 64352, 64353), -1659=>array(64338, 64339, 64340, 64341), -1662=>array(64342, 64343, 64344, 64345), -1663=>array(64354, 64355, 64356, 64357), -1664=>array(64346, 64347, 64348, 64349), -1667=>array(64374, 64375, 64376, 64377), -1668=>array(64370, 64371, 64372, 64373), -1670=>array(64378, 64379, 64380, 64381), -1671=>array(64382, 64383, 64384, 64385), -1672=>array(64392, 64393), -1676=>array(64388, 64389), -1677=>array(64386, 64387), -1678=>array(64390, 64391), -1681=>array(64396, 64397), -1688=>array(64394, 64395, 64394, 64395), -1700=>array(64362, 64363, 64364, 64365), -1702=>array(64366, 64367, 64368, 64369), -1705=>array(64398, 64399, 64400, 64401), -1709=>array(64467, 64468, 64469, 64470), -1711=>array(64402, 64403, 64404, 64405), -1713=>array(64410, 64411, 64412, 64413), -1715=>array(64406, 64407, 64408, 64409), -1722=>array(64414, 64415), -1723=>array(64416, 64417, 64418, 64419), -1726=>array(64426, 64427, 64428, 64429), -1728=>array(64420, 64421), -1729=>array(64422, 64423, 64424, 64425), -1733=>array(64480, 64481), -1734=>array(64473, 64474), -1735=>array(64471, 64472), -1736=>array(64475, 64476), -1737=>array(64482, 64483), -1739=>array(64478, 64479), -1740=>array(64508, 64509, 64510, 64511), -1744=>array(64484, 64485, 64486, 64487), -1746=>array(64430, 64431), -1747=>array(64432, 64433) -); - -/** - * Arabic laa letter: (char code => isolated, final, initial, medial). - * @public - */ -public static $uni_laa_array = array ( -1570 =>array(65269, 65270, 65269, 65270), -1571 =>array(65271, 65272, 65271, 65272), -1573 =>array(65273, 65274, 65273, 65274), -1575 =>array(65275, 65276, 65275, 65276) -); - -/** - * Array of character substitutions for sequences of two diacritics symbols. - * Putting the combining mark and character in the same glyph allows us to avoid the two marks overlapping each other in an illegible manner. - * second NSM char code => substitution char - * @public - */ -public static $uni_diacritics = array ( -1612=>64606, # Shadda + Dammatan -1613=>64607, # Shadda + Kasratan -1614=>64608, # Shadda + Fatha -1615=>64609, # Shadda + Damma -1616=>64610 # Shadda + Kasra -); - -/** - * Array of character substitutions from UTF-8 Unicode to Latin1. - * @public - */ -public static $uni_utf8tolatin = array ( -8364=>128, # Euro1 -338=>140, # OE -352=>138, # Scaron -376=>159, # Ydieresis -381=>142, # Zcaron2 -8226=>149, # bullet3 -710=>136, # circumflex -8224=>134, # dagger -8225=>135, # daggerdbl -8230=>133, # ellipsis -8212=>151, # emdash -8211=>150, # endash -402=>131, # florin -8249=>139, # guilsinglleft -8250=>155, # guilsinglright -339=>156, # oe -8240=>137, # perthousand -8222=>132, # quotedblbase -8220=>147, # quotedblleft -8221=>148, # quotedblright -8216=>145, # quoteleft -8217=>146, # quoteright -8218=>130, # quotesinglbase -353=>154, # scaron -732=>152, # tilde -8482=>153, # trademark -382=>158 # zcaron2 -); - -/** - * Array of Encoding Maps. - * @public static - */ -public static $encmap = array( - -// encoding map for: cp874 -'cp874' => array(0=>'.notdef',1=>'.notdef',2=>'.notdef',3=>'.notdef',4=>'.notdef',5=>'.notdef',6=>'.notdef',7=>'.notdef',8=>'.notdef',9=>'.notdef',10=>'.notdef',11=>'.notdef',12=>'.notdef',13=>'.notdef',14=>'.notdef',15=>'.notdef',16=>'.notdef',17=>'.notdef',18=>'.notdef',19=>'.notdef',20=>'.notdef',21=>'.notdef',22=>'.notdef',23=>'.notdef',24=>'.notdef',25=>'.notdef',26=>'.notdef',27=>'.notdef',28=>'.notdef',29=>'.notdef',30=>'.notdef',31=>'.notdef',32=>'space',33=>'exclam',34=>'quotedbl',35=>'numbersign',36=>'dollar',37=>'percent',38=>'ampersand',39=>'quotesingle',40=>'parenleft',41=>'parenright',42=>'asterisk',43=>'plus',44=>'comma',45=>'hyphen',46=>'period',47=>'slash',48=>'zero',49=>'one',50=>'two',51=>'three',52=>'four',53=>'five',54=>'six',55=>'seven',56=>'eight',57=>'nine',58=>'colon',59=>'semicolon',60=>'less',61=>'equal',62=>'greater',63=>'question',64=>'at',65=>'A',66=>'B',67=>'C',68=>'D',69=>'E',70=>'F',71=>'G',72=>'H',73=>'I',74=>'J',75=>'K',76=>'L',77=>'M',78=>'N',79=>'O',80=>'P',81=>'Q',82=>'R',83=>'S',84=>'T',85=>'U',86=>'V',87=>'W',88=>'X',89=>'Y',90=>'Z',91=>'bracketleft',92=>'backslash',93=>'bracketright',94=>'asciicircum',95=>'underscore',96=>'grave',97=>'a',98=>'b',99=>'c',100=>'d',101=>'e',102=>'f',103=>'g',104=>'h',105=>'i',106=>'j',107=>'k',108=>'l',109=>'m',110=>'n',111=>'o',112=>'p',113=>'q',114=>'r',115=>'s',116=>'t',117=>'u',118=>'v',119=>'w',120=>'x',121=>'y',122=>'z',123=>'braceleft',124=>'bar',125=>'braceright',126=>'asciitilde',127=>'.notdef',128=>'Euro',129=>'.notdef',130=>'.notdef',131=>'.notdef',132=>'.notdef',133=>'ellipsis',134=>'.notdef',135=>'.notdef',136=>'.notdef',137=>'.notdef',138=>'.notdef',139=>'.notdef',140=>'.notdef',141=>'.notdef',142=>'.notdef',143=>'.notdef',144=>'.notdef',145=>'quoteleft',146=>'quoteright',147=>'quotedblleft',148=>'quotedblright',149=>'bullet',150=>'endash',151=>'emdash',152=>'.notdef',153=>'.notdef',154=>'.notdef',155=>'.notdef',156=>'.notdef',157=>'.notdef',158=>'.notdef',159=>'.notdef',160=>'space',161=>'kokaithai',162=>'khokhaithai',163=>'khokhuatthai',164=>'khokhwaithai',165=>'khokhonthai',166=>'khorakhangthai',167=>'ngonguthai',168=>'chochanthai',169=>'chochingthai',170=>'chochangthai',171=>'sosothai',172=>'chochoethai',173=>'yoyingthai',174=>'dochadathai',175=>'topatakthai',176=>'thothanthai',177=>'thonangmonthothai',178=>'thophuthaothai',179=>'nonenthai',180=>'dodekthai',181=>'totaothai',182=>'thothungthai',183=>'thothahanthai',184=>'thothongthai',185=>'nonuthai',186=>'bobaimaithai',187=>'poplathai',188=>'phophungthai',189=>'fofathai',190=>'phophanthai',191=>'fofanthai',192=>'phosamphaothai',193=>'momathai',194=>'yoyakthai',195=>'roruathai',196=>'ruthai',197=>'lolingthai',198=>'luthai',199=>'wowaenthai',200=>'sosalathai',201=>'sorusithai',202=>'sosuathai',203=>'hohipthai',204=>'lochulathai',205=>'oangthai',206=>'honokhukthai',207=>'paiyannoithai',208=>'saraathai',209=>'maihanakatthai',210=>'saraaathai',211=>'saraamthai',212=>'saraithai',213=>'saraiithai',214=>'sarauethai',215=>'saraueethai',216=>'sarauthai',217=>'sarauuthai',218=>'phinthuthai',219=>'.notdef',220=>'.notdef',221=>'.notdef',222=>'.notdef',223=>'bahtthai',224=>'saraethai',225=>'saraaethai',226=>'saraothai',227=>'saraaimaimuanthai',228=>'saraaimaimalaithai',229=>'lakkhangyaothai',230=>'maiyamokthai',231=>'maitaikhuthai',232=>'maiekthai',233=>'maithothai',234=>'maitrithai',235=>'maichattawathai',236=>'thanthakhatthai',237=>'nikhahitthai',238=>'yamakkanthai',239=>'fongmanthai',240=>'zerothai',241=>'onethai',242=>'twothai',243=>'threethai',244=>'fourthai',245=>'fivethai',246=>'sixthai',247=>'seventhai',248=>'eightthai',249=>'ninethai',250=>'angkhankhuthai',251=>'khomutthai',252=>'.notdef',253=>'.notdef',254=>'.notdef',255=>'.notdef'), - -// encoding map for: cp1250 -'cp1250' => array(0=>'.notdef',1=>'.notdef',2=>'.notdef',3=>'.notdef',4=>'.notdef',5=>'.notdef',6=>'.notdef',7=>'.notdef',8=>'.notdef',9=>'.notdef',10=>'.notdef',11=>'.notdef',12=>'.notdef',13=>'.notdef',14=>'.notdef',15=>'.notdef',16=>'.notdef',17=>'.notdef',18=>'.notdef',19=>'.notdef',20=>'.notdef',21=>'.notdef',22=>'.notdef',23=>'.notdef',24=>'.notdef',25=>'.notdef',26=>'.notdef',27=>'.notdef',28=>'.notdef',29=>'.notdef',30=>'.notdef',31=>'.notdef',32=>'space',33=>'exclam',34=>'quotedbl',35=>'numbersign',36=>'dollar',37=>'percent',38=>'ampersand',39=>'quotesingle',40=>'parenleft',41=>'parenright',42=>'asterisk',43=>'plus',44=>'comma',45=>'hyphen',46=>'period',47=>'slash',48=>'zero',49=>'one',50=>'two',51=>'three',52=>'four',53=>'five',54=>'six',55=>'seven',56=>'eight',57=>'nine',58=>'colon',59=>'semicolon',60=>'less',61=>'equal',62=>'greater',63=>'question',64=>'at',65=>'A',66=>'B',67=>'C',68=>'D',69=>'E',70=>'F',71=>'G',72=>'H',73=>'I',74=>'J',75=>'K',76=>'L',77=>'M',78=>'N',79=>'O',80=>'P',81=>'Q',82=>'R',83=>'S',84=>'T',85=>'U',86=>'V',87=>'W',88=>'X',89=>'Y',90=>'Z',91=>'bracketleft',92=>'backslash',93=>'bracketright',94=>'asciicircum',95=>'underscore',96=>'grave',97=>'a',98=>'b',99=>'c',100=>'d',101=>'e',102=>'f',103=>'g',104=>'h',105=>'i',106=>'j',107=>'k',108=>'l',109=>'m',110=>'n',111=>'o',112=>'p',113=>'q',114=>'r',115=>'s',116=>'t',117=>'u',118=>'v',119=>'w',120=>'x',121=>'y',122=>'z',123=>'braceleft',124=>'bar',125=>'braceright',126=>'asciitilde',127=>'.notdef',128=>'Euro',129=>'.notdef',130=>'quotesinglbase',131=>'.notdef',132=>'quotedblbase',133=>'ellipsis',134=>'dagger',135=>'daggerdbl',136=>'.notdef',137=>'perthousand',138=>'Scaron',139=>'guilsinglleft',140=>'Sacute',141=>'Tcaron',142=>'Zcaron',143=>'Zacute',144=>'.notdef',145=>'quoteleft',146=>'quoteright',147=>'quotedblleft',148=>'quotedblright',149=>'bullet',150=>'endash',151=>'emdash',152=>'.notdef',153=>'trademark',154=>'scaron',155=>'guilsinglright',156=>'sacute',157=>'tcaron',158=>'zcaron',159=>'zacute',160=>'space',161=>'caron',162=>'breve',163=>'Lslash',164=>'currency',165=>'Aogonek',166=>'brokenbar',167=>'section',168=>'dieresis',169=>'copyright',170=>'Scedilla',171=>'guillemotleft',172=>'logicalnot',173=>'hyphen',174=>'registered',175=>'Zdotaccent',176=>'degree',177=>'plusminus',178=>'ogonek',179=>'lslash',180=>'acute',181=>'mu',182=>'paragraph',183=>'periodcentered',184=>'cedilla',185=>'aogonek',186=>'scedilla',187=>'guillemotright',188=>'Lcaron',189=>'hungarumlaut',190=>'lcaron',191=>'zdotaccent',192=>'Racute',193=>'Aacute',194=>'Acircumflex',195=>'Abreve',196=>'Adieresis',197=>'Lacute',198=>'Cacute',199=>'Ccedilla',200=>'Ccaron',201=>'Eacute',202=>'Eogonek',203=>'Edieresis',204=>'Ecaron',205=>'Iacute',206=>'Icircumflex',207=>'Dcaron',208=>'Dcroat',209=>'Nacute',210=>'Ncaron',211=>'Oacute',212=>'Ocircumflex',213=>'Ohungarumlaut',214=>'Odieresis',215=>'multiply',216=>'Rcaron',217=>'Uring',218=>'Uacute',219=>'Uhungarumlaut',220=>'Udieresis',221=>'Yacute',222=>'Tcommaaccent',223=>'germandbls',224=>'racute',225=>'aacute',226=>'acircumflex',227=>'abreve',228=>'adieresis',229=>'lacute',230=>'cacute',231=>'ccedilla',232=>'ccaron',233=>'eacute',234=>'eogonek',235=>'edieresis',236=>'ecaron',237=>'iacute',238=>'icircumflex',239=>'dcaron',240=>'dcroat',241=>'nacute',242=>'ncaron',243=>'oacute',244=>'ocircumflex',245=>'ohungarumlaut',246=>'odieresis',247=>'divide',248=>'rcaron',249=>'uring',250=>'uacute',251=>'uhungarumlaut',252=>'udieresis',253=>'yacute',254=>'tcommaaccent',255=>'dotaccent'), - -// encoding map for: cp1251 -'cp1251' => array(0=>'.notdef',1=>'.notdef',2=>'.notdef',3=>'.notdef',4=>'.notdef',5=>'.notdef',6=>'.notdef',7=>'.notdef',8=>'.notdef',9=>'.notdef',10=>'.notdef',11=>'.notdef',12=>'.notdef',13=>'.notdef',14=>'.notdef',15=>'.notdef',16=>'.notdef',17=>'.notdef',18=>'.notdef',19=>'.notdef',20=>'.notdef',21=>'.notdef',22=>'.notdef',23=>'.notdef',24=>'.notdef',25=>'.notdef',26=>'.notdef',27=>'.notdef',28=>'.notdef',29=>'.notdef',30=>'.notdef',31=>'.notdef',32=>'space',33=>'exclam',34=>'quotedbl',35=>'numbersign',36=>'dollar',37=>'percent',38=>'ampersand',39=>'quotesingle',40=>'parenleft',41=>'parenright',42=>'asterisk',43=>'plus',44=>'comma',45=>'hyphen',46=>'period',47=>'slash',48=>'zero',49=>'one',50=>'two',51=>'three',52=>'four',53=>'five',54=>'six',55=>'seven',56=>'eight',57=>'nine',58=>'colon',59=>'semicolon',60=>'less',61=>'equal',62=>'greater',63=>'question',64=>'at',65=>'A',66=>'B',67=>'C',68=>'D',69=>'E',70=>'F',71=>'G',72=>'H',73=>'I',74=>'J',75=>'K',76=>'L',77=>'M',78=>'N',79=>'O',80=>'P',81=>'Q',82=>'R',83=>'S',84=>'T',85=>'U',86=>'V',87=>'W',88=>'X',89=>'Y',90=>'Z',91=>'bracketleft',92=>'backslash',93=>'bracketright',94=>'asciicircum',95=>'underscore',96=>'grave',97=>'a',98=>'b',99=>'c',100=>'d',101=>'e',102=>'f',103=>'g',104=>'h',105=>'i',106=>'j',107=>'k',108=>'l',109=>'m',110=>'n',111=>'o',112=>'p',113=>'q',114=>'r',115=>'s',116=>'t',117=>'u',118=>'v',119=>'w',120=>'x',121=>'y',122=>'z',123=>'braceleft',124=>'bar',125=>'braceright',126=>'asciitilde',127=>'.notdef',128=>'afii10051',129=>'afii10052',130=>'quotesinglbase',131=>'afii10100',132=>'quotedblbase',133=>'ellipsis',134=>'dagger',135=>'daggerdbl',136=>'Euro',137=>'perthousand',138=>'afii10058',139=>'guilsinglleft',140=>'afii10059',141=>'afii10061',142=>'afii10060',143=>'afii10145',144=>'afii10099',145=>'quoteleft',146=>'quoteright',147=>'quotedblleft',148=>'quotedblright',149=>'bullet',150=>'endash',151=>'emdash',152=>'.notdef',153=>'trademark',154=>'afii10106',155=>'guilsinglright',156=>'afii10107',157=>'afii10109',158=>'afii10108',159=>'afii10193',160=>'space',161=>'afii10062',162=>'afii10110',163=>'afii10057',164=>'currency',165=>'afii10050',166=>'brokenbar',167=>'section',168=>'afii10023',169=>'copyright',170=>'afii10053',171=>'guillemotleft',172=>'logicalnot',173=>'hyphen',174=>'registered',175=>'afii10056',176=>'degree',177=>'plusminus',178=>'afii10055',179=>'afii10103',180=>'afii10098',181=>'mu',182=>'paragraph',183=>'periodcentered',184=>'afii10071',185=>'afii61352',186=>'afii10101',187=>'guillemotright',188=>'afii10105',189=>'afii10054',190=>'afii10102',191=>'afii10104',192=>'afii10017',193=>'afii10018',194=>'afii10019',195=>'afii10020',196=>'afii10021',197=>'afii10022',198=>'afii10024',199=>'afii10025',200=>'afii10026',201=>'afii10027',202=>'afii10028',203=>'afii10029',204=>'afii10030',205=>'afii10031',206=>'afii10032',207=>'afii10033',208=>'afii10034',209=>'afii10035',210=>'afii10036',211=>'afii10037',212=>'afii10038',213=>'afii10039',214=>'afii10040',215=>'afii10041',216=>'afii10042',217=>'afii10043',218=>'afii10044',219=>'afii10045',220=>'afii10046',221=>'afii10047',222=>'afii10048',223=>'afii10049',224=>'afii10065',225=>'afii10066',226=>'afii10067',227=>'afii10068',228=>'afii10069',229=>'afii10070',230=>'afii10072',231=>'afii10073',232=>'afii10074',233=>'afii10075',234=>'afii10076',235=>'afii10077',236=>'afii10078',237=>'afii10079',238=>'afii10080',239=>'afii10081',240=>'afii10082',241=>'afii10083',242=>'afii10084',243=>'afii10085',244=>'afii10086',245=>'afii10087',246=>'afii10088',247=>'afii10089',248=>'afii10090',249=>'afii10091',250=>'afii10092',251=>'afii10093',252=>'afii10094',253=>'afii10095',254=>'afii10096',255=>'afii10097'), - -// encoding map for: cp1252 -'cp1252' => array(0=>'.notdef',1=>'.notdef',2=>'.notdef',3=>'.notdef',4=>'.notdef',5=>'.notdef',6=>'.notdef',7=>'.notdef',8=>'.notdef',9=>'.notdef',10=>'.notdef',11=>'.notdef',12=>'.notdef',13=>'.notdef',14=>'.notdef',15=>'.notdef',16=>'.notdef',17=>'.notdef',18=>'.notdef',19=>'.notdef',20=>'.notdef',21=>'.notdef',22=>'.notdef',23=>'.notdef',24=>'.notdef',25=>'.notdef',26=>'.notdef',27=>'.notdef',28=>'.notdef',29=>'.notdef',30=>'.notdef',31=>'.notdef',32=>'space',33=>'exclam',34=>'quotedbl',35=>'numbersign',36=>'dollar',37=>'percent',38=>'ampersand',39=>'quotesingle',40=>'parenleft',41=>'parenright',42=>'asterisk',43=>'plus',44=>'comma',45=>'hyphen',46=>'period',47=>'slash',48=>'zero',49=>'one',50=>'two',51=>'three',52=>'four',53=>'five',54=>'six',55=>'seven',56=>'eight',57=>'nine',58=>'colon',59=>'semicolon',60=>'less',61=>'equal',62=>'greater',63=>'question',64=>'at',65=>'A',66=>'B',67=>'C',68=>'D',69=>'E',70=>'F',71=>'G',72=>'H',73=>'I',74=>'J',75=>'K',76=>'L',77=>'M',78=>'N',79=>'O',80=>'P',81=>'Q',82=>'R',83=>'S',84=>'T',85=>'U',86=>'V',87=>'W',88=>'X',89=>'Y',90=>'Z',91=>'bracketleft',92=>'backslash',93=>'bracketright',94=>'asciicircum',95=>'underscore',96=>'grave',97=>'a',98=>'b',99=>'c',100=>'d',101=>'e',102=>'f',103=>'g',104=>'h',105=>'i',106=>'j',107=>'k',108=>'l',109=>'m',110=>'n',111=>'o',112=>'p',113=>'q',114=>'r',115=>'s',116=>'t',117=>'u',118=>'v',119=>'w',120=>'x',121=>'y',122=>'z',123=>'braceleft',124=>'bar',125=>'braceright',126=>'asciitilde',127=>'.notdef',128=>'Euro',129=>'.notdef',130=>'quotesinglbase',131=>'florin',132=>'quotedblbase',133=>'ellipsis',134=>'dagger',135=>'daggerdbl',136=>'circumflex',137=>'perthousand',138=>'Scaron',139=>'guilsinglleft',140=>'OE',141=>'.notdef',142=>'Zcaron',143=>'.notdef',144=>'.notdef',145=>'quoteleft',146=>'quoteright',147=>'quotedblleft',148=>'quotedblright',149=>'bullet',150=>'endash',151=>'emdash',152=>'tilde',153=>'trademark',154=>'scaron',155=>'guilsinglright',156=>'oe',157=>'.notdef',158=>'zcaron',159=>'Ydieresis',160=>'space',161=>'exclamdown',162=>'cent',163=>'sterling',164=>'currency',165=>'yen',166=>'brokenbar',167=>'section',168=>'dieresis',169=>'copyright',170=>'ordfeminine',171=>'guillemotleft',172=>'logicalnot',173=>'hyphen',174=>'registered',175=>'macron',176=>'degree',177=>'plusminus',178=>'twosuperior',179=>'threesuperior',180=>'acute',181=>'mu',182=>'paragraph',183=>'periodcentered',184=>'cedilla',185=>'onesuperior',186=>'ordmasculine',187=>'guillemotright',188=>'onequarter',189=>'onehalf',190=>'threequarters',191=>'questiondown',192=>'Agrave',193=>'Aacute',194=>'Acircumflex',195=>'Atilde',196=>'Adieresis',197=>'Aring',198=>'AE',199=>'Ccedilla',200=>'Egrave',201=>'Eacute',202=>'Ecircumflex',203=>'Edieresis',204=>'Igrave',205=>'Iacute',206=>'Icircumflex',207=>'Idieresis',208=>'Eth',209=>'Ntilde',210=>'Ograve',211=>'Oacute',212=>'Ocircumflex',213=>'Otilde',214=>'Odieresis',215=>'multiply',216=>'Oslash',217=>'Ugrave',218=>'Uacute',219=>'Ucircumflex',220=>'Udieresis',221=>'Yacute',222=>'Thorn',223=>'germandbls',224=>'agrave',225=>'aacute',226=>'acircumflex',227=>'atilde',228=>'adieresis',229=>'aring',230=>'ae',231=>'ccedilla',232=>'egrave',233=>'eacute',234=>'ecircumflex',235=>'edieresis',236=>'igrave',237=>'iacute',238=>'icircumflex',239=>'idieresis',240=>'eth',241=>'ntilde',242=>'ograve',243=>'oacute',244=>'ocircumflex',245=>'otilde',246=>'odieresis',247=>'divide',248=>'oslash',249=>'ugrave',250=>'uacute',251=>'ucircumflex',252=>'udieresis',253=>'yacute',254=>'thorn',255=>'ydieresis'), - -// encoding map for: cp1253 -'cp1253' => array(0=>'.notdef',1=>'.notdef',2=>'.notdef',3=>'.notdef',4=>'.notdef',5=>'.notdef',6=>'.notdef',7=>'.notdef',8=>'.notdef',9=>'.notdef',10=>'.notdef',11=>'.notdef',12=>'.notdef',13=>'.notdef',14=>'.notdef',15=>'.notdef',16=>'.notdef',17=>'.notdef',18=>'.notdef',19=>'.notdef',20=>'.notdef',21=>'.notdef',22=>'.notdef',23=>'.notdef',24=>'.notdef',25=>'.notdef',26=>'.notdef',27=>'.notdef',28=>'.notdef',29=>'.notdef',30=>'.notdef',31=>'.notdef',32=>'space',33=>'exclam',34=>'quotedbl',35=>'numbersign',36=>'dollar',37=>'percent',38=>'ampersand',39=>'quotesingle',40=>'parenleft',41=>'parenright',42=>'asterisk',43=>'plus',44=>'comma',45=>'hyphen',46=>'period',47=>'slash',48=>'zero',49=>'one',50=>'two',51=>'three',52=>'four',53=>'five',54=>'six',55=>'seven',56=>'eight',57=>'nine',58=>'colon',59=>'semicolon',60=>'less',61=>'equal',62=>'greater',63=>'question',64=>'at',65=>'A',66=>'B',67=>'C',68=>'D',69=>'E',70=>'F',71=>'G',72=>'H',73=>'I',74=>'J',75=>'K',76=>'L',77=>'M',78=>'N',79=>'O',80=>'P',81=>'Q',82=>'R',83=>'S',84=>'T',85=>'U',86=>'V',87=>'W',88=>'X',89=>'Y',90=>'Z',91=>'bracketleft',92=>'backslash',93=>'bracketright',94=>'asciicircum',95=>'underscore',96=>'grave',97=>'a',98=>'b',99=>'c',100=>'d',101=>'e',102=>'f',103=>'g',104=>'h',105=>'i',106=>'j',107=>'k',108=>'l',109=>'m',110=>'n',111=>'o',112=>'p',113=>'q',114=>'r',115=>'s',116=>'t',117=>'u',118=>'v',119=>'w',120=>'x',121=>'y',122=>'z',123=>'braceleft',124=>'bar',125=>'braceright',126=>'asciitilde',127=>'.notdef',128=>'Euro',129=>'.notdef',130=>'quotesinglbase',131=>'florin',132=>'quotedblbase',133=>'ellipsis',134=>'dagger',135=>'daggerdbl',136=>'.notdef',137=>'perthousand',138=>'.notdef',139=>'guilsinglleft',140=>'.notdef',141=>'.notdef',142=>'.notdef',143=>'.notdef',144=>'.notdef',145=>'quoteleft',146=>'quoteright',147=>'quotedblleft',148=>'quotedblright',149=>'bullet',150=>'endash',151=>'emdash',152=>'.notdef',153=>'trademark',154=>'.notdef',155=>'guilsinglright',156=>'.notdef',157=>'.notdef',158=>'.notdef',159=>'.notdef',160=>'space',161=>'dieresistonos',162=>'Alphatonos',163=>'sterling',164=>'currency',165=>'yen',166=>'brokenbar',167=>'section',168=>'dieresis',169=>'copyright',170=>'.notdef',171=>'guillemotleft',172=>'logicalnot',173=>'hyphen',174=>'registered',175=>'afii00208',176=>'degree',177=>'plusminus',178=>'twosuperior',179=>'threesuperior',180=>'tonos',181=>'mu',182=>'paragraph',183=>'periodcentered',184=>'Epsilontonos',185=>'Etatonos',186=>'Iotatonos',187=>'guillemotright',188=>'Omicrontonos',189=>'onehalf',190=>'Upsilontonos',191=>'Omegatonos',192=>'iotadieresistonos',193=>'Alpha',194=>'Beta',195=>'Gamma',196=>'Delta',197=>'Epsilon',198=>'Zeta',199=>'Eta',200=>'Theta',201=>'Iota',202=>'Kappa',203=>'Lambda',204=>'Mu',205=>'Nu',206=>'Xi',207=>'Omicron',208=>'Pi',209=>'Rho',210=>'.notdef',211=>'Sigma',212=>'Tau',213=>'Upsilon',214=>'Phi',215=>'Chi',216=>'Psi',217=>'Omega',218=>'Iotadieresis',219=>'Upsilondieresis',220=>'alphatonos',221=>'epsilontonos',222=>'etatonos',223=>'iotatonos',224=>'upsilondieresistonos',225=>'alpha',226=>'beta',227=>'gamma',228=>'delta',229=>'epsilon',230=>'zeta',231=>'eta',232=>'theta',233=>'iota',234=>'kappa',235=>'lambda',236=>'mu',237=>'nu',238=>'xi',239=>'omicron',240=>'pi',241=>'rho',242=>'sigma1',243=>'sigma',244=>'tau',245=>'upsilon',246=>'phi',247=>'chi',248=>'psi',249=>'omega',250=>'iotadieresis',251=>'upsilondieresis',252=>'omicrontonos',253=>'upsilontonos',254=>'omegatonos',255=>'.notdef'), - -// encoding map for: cp1254 -'cp1254' => array(0=>'.notdef',1=>'.notdef',2=>'.notdef',3=>'.notdef',4=>'.notdef',5=>'.notdef',6=>'.notdef',7=>'.notdef',8=>'.notdef',9=>'.notdef',10=>'.notdef',11=>'.notdef',12=>'.notdef',13=>'.notdef',14=>'.notdef',15=>'.notdef',16=>'.notdef',17=>'.notdef',18=>'.notdef',19=>'.notdef',20=>'.notdef',21=>'.notdef',22=>'.notdef',23=>'.notdef',24=>'.notdef',25=>'.notdef',26=>'.notdef',27=>'.notdef',28=>'.notdef',29=>'.notdef',30=>'.notdef',31=>'.notdef',32=>'space',33=>'exclam',34=>'quotedbl',35=>'numbersign',36=>'dollar',37=>'percent',38=>'ampersand',39=>'quotesingle',40=>'parenleft',41=>'parenright',42=>'asterisk',43=>'plus',44=>'comma',45=>'hyphen',46=>'period',47=>'slash',48=>'zero',49=>'one',50=>'two',51=>'three',52=>'four',53=>'five',54=>'six',55=>'seven',56=>'eight',57=>'nine',58=>'colon',59=>'semicolon',60=>'less',61=>'equal',62=>'greater',63=>'question',64=>'at',65=>'A',66=>'B',67=>'C',68=>'D',69=>'E',70=>'F',71=>'G',72=>'H',73=>'I',74=>'J',75=>'K',76=>'L',77=>'M',78=>'N',79=>'O',80=>'P',81=>'Q',82=>'R',83=>'S',84=>'T',85=>'U',86=>'V',87=>'W',88=>'X',89=>'Y',90=>'Z',91=>'bracketleft',92=>'backslash',93=>'bracketright',94=>'asciicircum',95=>'underscore',96=>'grave',97=>'a',98=>'b',99=>'c',100=>'d',101=>'e',102=>'f',103=>'g',104=>'h',105=>'i',106=>'j',107=>'k',108=>'l',109=>'m',110=>'n',111=>'o',112=>'p',113=>'q',114=>'r',115=>'s',116=>'t',117=>'u',118=>'v',119=>'w',120=>'x',121=>'y',122=>'z',123=>'braceleft',124=>'bar',125=>'braceright',126=>'asciitilde',127=>'.notdef',128=>'Euro',129=>'.notdef',130=>'quotesinglbase',131=>'florin',132=>'quotedblbase',133=>'ellipsis',134=>'dagger',135=>'daggerdbl',136=>'circumflex',137=>'perthousand',138=>'Scaron',139=>'guilsinglleft',140=>'OE',141=>'.notdef',142=>'.notdef',143=>'.notdef',144=>'.notdef',145=>'quoteleft',146=>'quoteright',147=>'quotedblleft',148=>'quotedblright',149=>'bullet',150=>'endash',151=>'emdash',152=>'tilde',153=>'trademark',154=>'scaron',155=>'guilsinglright',156=>'oe',157=>'.notdef',158=>'.notdef',159=>'Ydieresis',160=>'space',161=>'exclamdown',162=>'cent',163=>'sterling',164=>'currency',165=>'yen',166=>'brokenbar',167=>'section',168=>'dieresis',169=>'copyright',170=>'ordfeminine',171=>'guillemotleft',172=>'logicalnot',173=>'hyphen',174=>'registered',175=>'macron',176=>'degree',177=>'plusminus',178=>'twosuperior',179=>'threesuperior',180=>'acute',181=>'mu',182=>'paragraph',183=>'periodcentered',184=>'cedilla',185=>'onesuperior',186=>'ordmasculine',187=>'guillemotright',188=>'onequarter',189=>'onehalf',190=>'threequarters',191=>'questiondown',192=>'Agrave',193=>'Aacute',194=>'Acircumflex',195=>'Atilde',196=>'Adieresis',197=>'Aring',198=>'AE',199=>'Ccedilla',200=>'Egrave',201=>'Eacute',202=>'Ecircumflex',203=>'Edieresis',204=>'Igrave',205=>'Iacute',206=>'Icircumflex',207=>'Idieresis',208=>'Gbreve',209=>'Ntilde',210=>'Ograve',211=>'Oacute',212=>'Ocircumflex',213=>'Otilde',214=>'Odieresis',215=>'multiply',216=>'Oslash',217=>'Ugrave',218=>'Uacute',219=>'Ucircumflex',220=>'Udieresis',221=>'Idotaccent',222=>'Scedilla',223=>'germandbls',224=>'agrave',225=>'aacute',226=>'acircumflex',227=>'atilde',228=>'adieresis',229=>'aring',230=>'ae',231=>'ccedilla',232=>'egrave',233=>'eacute',234=>'ecircumflex',235=>'edieresis',236=>'igrave',237=>'iacute',238=>'icircumflex',239=>'idieresis',240=>'gbreve',241=>'ntilde',242=>'ograve',243=>'oacute',244=>'ocircumflex',245=>'otilde',246=>'odieresis',247=>'divide',248=>'oslash',249=>'ugrave',250=>'uacute',251=>'ucircumflex',252=>'udieresis',253=>'dotlessi',254=>'scedilla',255=>'ydieresis'), - -// encoding map for: cp1255 -'cp1255' => array(0=>'.notdef',1=>'.notdef',2=>'.notdef',3=>'.notdef',4=>'.notdef',5=>'.notdef',6=>'.notdef',7=>'.notdef',8=>'.notdef',9=>'.notdef',10=>'.notdef',11=>'.notdef',12=>'.notdef',13=>'.notdef',14=>'.notdef',15=>'.notdef',16=>'.notdef',17=>'.notdef',18=>'.notdef',19=>'.notdef',20=>'.notdef',21=>'.notdef',22=>'.notdef',23=>'.notdef',24=>'.notdef',25=>'.notdef',26=>'.notdef',27=>'.notdef',28=>'.notdef',29=>'.notdef',30=>'.notdef',31=>'.notdef',32=>'space',33=>'exclam',34=>'quotedbl',35=>'numbersign',36=>'dollar',37=>'percent',38=>'ampersand',39=>'quotesingle',40=>'parenleft',41=>'parenright',42=>'asterisk',43=>'plus',44=>'comma',45=>'hyphen',46=>'period',47=>'slash',48=>'zero',49=>'one',50=>'two',51=>'three',52=>'four',53=>'five',54=>'six',55=>'seven',56=>'eight',57=>'nine',58=>'colon',59=>'semicolon',60=>'less',61=>'equal',62=>'greater',63=>'question',64=>'at',65=>'A',66=>'B',67=>'C',68=>'D',69=>'E',70=>'F',71=>'G',72=>'H',73=>'I',74=>'J',75=>'K',76=>'L',77=>'M',78=>'N',79=>'O',80=>'P',81=>'Q',82=>'R',83=>'S',84=>'T',85=>'U',86=>'V',87=>'W',88=>'X',89=>'Y',90=>'Z',91=>'bracketleft',92=>'backslash',93=>'bracketright',94=>'asciicircum',95=>'underscore',96=>'grave',97=>'a',98=>'b',99=>'c',100=>'d',101=>'e',102=>'f',103=>'g',104=>'h',105=>'i',106=>'j',107=>'k',108=>'l',109=>'m',110=>'n',111=>'o',112=>'p',113=>'q',114=>'r',115=>'s',116=>'t',117=>'u',118=>'v',119=>'w',120=>'x',121=>'y',122=>'z',123=>'braceleft',124=>'bar',125=>'braceright',126=>'asciitilde',127=>'.notdef',128=>'Euro',129=>'.notdef',130=>'quotesinglbase',131=>'florin',132=>'quotedblbase',133=>'ellipsis',134=>'dagger',135=>'daggerdbl',136=>'circumflex',137=>'perthousand',138=>'.notdef',139=>'guilsinglleft',140=>'.notdef',141=>'.notdef',142=>'.notdef',143=>'.notdef',144=>'.notdef',145=>'quoteleft',146=>'quoteright',147=>'quotedblleft',148=>'quotedblright',149=>'bullet',150=>'endash',151=>'emdash',152=>'tilde',153=>'trademark',154=>'.notdef',155=>'guilsinglright',156=>'.notdef',157=>'.notdef',158=>'.notdef',159=>'.notdef',160=>'space',161=>'exclamdown',162=>'cent',163=>'sterling',164=>'afii57636',165=>'yen',166=>'brokenbar',167=>'section',168=>'dieresis',169=>'copyright',170=>'multiply',171=>'guillemotleft',172=>'logicalnot',173=>'sfthyphen',174=>'registered',175=>'macron',176=>'degree',177=>'plusminus',178=>'twosuperior',179=>'threesuperior',180=>'acute',181=>'mu',182=>'paragraph',183=>'middot',184=>'cedilla',185=>'onesuperior',186=>'divide',187=>'guillemotright',188=>'onequarter',189=>'onehalf',190=>'threequarters',191=>'questiondown',192=>'afii57799',193=>'afii57801',194=>'afii57800',195=>'afii57802',196=>'afii57793',197=>'afii57794',198=>'afii57795',199=>'afii57798',200=>'afii57797',201=>'afii57806',202=>'.notdef',203=>'afii57796',204=>'afii57807',205=>'afii57839',206=>'afii57645',207=>'afii57841',208=>'afii57842',209=>'afii57804',210=>'afii57803',211=>'afii57658',212=>'afii57716',213=>'afii57717',214=>'afii57718',215=>'gereshhebrew',216=>'gershayimhebrew',217=>'.notdef',218=>'.notdef',219=>'.notdef',220=>'.notdef',221=>'.notdef',222=>'.notdef',223=>'.notdef',224=>'afii57664',225=>'afii57665',226=>'afii57666',227=>'afii57667',228=>'afii57668',229=>'afii57669',230=>'afii57670',231=>'afii57671',232=>'afii57672',233=>'afii57673',234=>'afii57674',235=>'afii57675',236=>'afii57676',237=>'afii57677',238=>'afii57678',239=>'afii57679',240=>'afii57680',241=>'afii57681',242=>'afii57682',243=>'afii57683',244=>'afii57684',245=>'afii57685',246=>'afii57686',247=>'afii57687',248=>'afii57688',249=>'afii57689',250=>'afii57690',251=>'.notdef',252=>'.notdef',253=>'afii299',254=>'afii300',255=>'.notdef'), - -// encoding map for: cp1256 -'cp1256' => array(0=>'.notdef',1=>'.notdef',2=>'.notdef',3=>'.notdef',4=>'.notdef',5=>'.notdef',6=>'.notdef',7=>'.notdef',8=>'.notdef',9=>'.notdef',10=>'.notdef',11=>'.notdef',12=>'.notdef',13=>'.notdef',14=>'.notdef',15=>'.notdef',16=>'.notdef',17=>'.notdef',18=>'.notdef',19=>'.notdef',20=>'.notdef',21=>'.notdef',22=>'.notdef',23=>'.notdef',24=>'.notdef',25=>'.notdef',26=>'.notdef',27=>'.notdef',28=>'.notdef',29=>'.notdef',30=>'.notdef',31=>'.notdef',32=>'space',33=>'exclam',34=>'quotedbl',35=>'numbersign',36=>'dollar',37=>'percent',38=>'ampersand',39=>'quotesingle',40=>'parenleft',41=>'parenright',42=>'asterisk',43=>'plus',44=>'comma',45=>'hyphen',46=>'period',47=>'slash',48=>'zero',49=>'one',50=>'two',51=>'three',52=>'four',53=>'five',54=>'six',55=>'seven',56=>'eight',57=>'nine',58=>'colon',59=>'semicolon',60=>'less',61=>'equal',62=>'greater',63=>'question',64=>'at',65=>'A',66=>'B',67=>'C',68=>'D',69=>'E',70=>'F',71=>'G',72=>'H',73=>'I',74=>'J',75=>'K',76=>'L',77=>'M',78=>'N',79=>'O',80=>'P',81=>'Q',82=>'R',83=>'S',84=>'T',85=>'U',86=>'V',87=>'W',88=>'X',89=>'Y',90=>'Z',91=>'bracketleft',92=>'backslash',93=>'bracketright',94=>'asciicircum',95=>'underscore',96=>'grave',97=>'a',98=>'b',99=>'c',100=>'d',101=>'e',102=>'f',103=>'g',104=>'h',105=>'i',106=>'j',107=>'k',108=>'l',109=>'m',110=>'n',111=>'o',112=>'p',113=>'q',114=>'r',115=>'s',116=>'t',117=>'u',118=>'v',119=>'w',120=>'x',121=>'y',122=>'z',123=>'braceleft',124=>'bar',125=>'braceright',126=>'asciitilde',127=>'.notdef',128=>'Euro',129=>'afii57506',130=>'quotesinglbase',131=>'florin',132=>'quotedblbase',133=>'ellipsis',134=>'dagger',135=>'daggerdbl',136=>'circumflex',137=>'perthousand',138=>'afii57511',139=>'guilsinglleft',140=>'OE',141=>'afii57507',142=>'afii57508',143=>'afii57512',144=>'afii57509',145=>'quoteleft',146=>'quoteright',147=>'quotedblleft',148=>'quotedblright',149=>'bullet',150=>'endash',151=>'emdash',152=>'.notdef',153=>'trademark',154=>'afii57513',155=>'guilsinglright',156=>'oe',157=>'afii61664',158=>'afii301',159=>'afii57514',160=>'space',161=>'afii57388',162=>'cent',163=>'sterling',164=>'currency',165=>'yen',166=>'brokenbar',167=>'section',168=>'dieresis',169=>'copyright',170=>'.notdef',171=>'guillemotleft',172=>'logicalnot',173=>'hyphen',174=>'registered',175=>'macron',176=>'degree',177=>'plusminus',178=>'twosuperior',179=>'threesuperior',180=>'acute',181=>'mu',182=>'paragraph',183=>'periodcentered',184=>'cedilla',185=>'onesuperior',186=>'afii57403',187=>'guillemotright',188=>'onequarter',189=>'onehalf',190=>'threequarters',191=>'afii57407',192=>'.notdef',193=>'afii57409',194=>'afii57410',195=>'afii57411',196=>'afii57412',197=>'afii57413',198=>'afii57414',199=>'afii57415',200=>'afii57416',201=>'afii57417',202=>'afii57418',203=>'afii57419',204=>'afii57420',205=>'afii57421',206=>'afii57422',207=>'afii57423',208=>'afii57424',209=>'afii57425',210=>'afii57426',211=>'afii57427',212=>'afii57428',213=>'afii57429',214=>'afii57430',215=>'multiply',216=>'afii57431',217=>'afii57432',218=>'afii57433',219=>'afii57434',220=>'afii57440',221=>'afii57441',222=>'afii57442',223=>'afii57443',224=>'agrave',225=>'afii57444',226=>'acircumflex',227=>'afii57445',228=>'afii57446',229=>'afii57470',230=>'afii57448',231=>'ccedilla',232=>'egrave',233=>'eacute',234=>'ecircumflex',235=>'edieresis',236=>'afii57449',237=>'afii57450',238=>'icircumflex',239=>'idieresis',240=>'afii57451',241=>'afii57452',242=>'afii57453',243=>'afii57454',244=>'ocircumflex',245=>'afii57455',246=>'afii57456',247=>'divide',248=>'afii57457',249=>'ugrave',250=>'afii57458',251=>'ucircumflex',252=>'udieresis',253=>'afii299',254=>'afii300',255=>'afii57519'), - -// encoding map for: cp1257 -'cp1257' => array(0=>'.notdef',1=>'.notdef',2=>'.notdef',3=>'.notdef',4=>'.notdef',5=>'.notdef',6=>'.notdef',7=>'.notdef',8=>'.notdef',9=>'.notdef',10=>'.notdef',11=>'.notdef',12=>'.notdef',13=>'.notdef',14=>'.notdef',15=>'.notdef',16=>'.notdef',17=>'.notdef',18=>'.notdef',19=>'.notdef',20=>'.notdef',21=>'.notdef',22=>'.notdef',23=>'.notdef',24=>'.notdef',25=>'.notdef',26=>'.notdef',27=>'.notdef',28=>'.notdef',29=>'.notdef',30=>'.notdef',31=>'.notdef',32=>'space',33=>'exclam',34=>'quotedbl',35=>'numbersign',36=>'dollar',37=>'percent',38=>'ampersand',39=>'quotesingle',40=>'parenleft',41=>'parenright',42=>'asterisk',43=>'plus',44=>'comma',45=>'hyphen',46=>'period',47=>'slash',48=>'zero',49=>'one',50=>'two',51=>'three',52=>'four',53=>'five',54=>'six',55=>'seven',56=>'eight',57=>'nine',58=>'colon',59=>'semicolon',60=>'less',61=>'equal',62=>'greater',63=>'question',64=>'at',65=>'A',66=>'B',67=>'C',68=>'D',69=>'E',70=>'F',71=>'G',72=>'H',73=>'I',74=>'J',75=>'K',76=>'L',77=>'M',78=>'N',79=>'O',80=>'P',81=>'Q',82=>'R',83=>'S',84=>'T',85=>'U',86=>'V',87=>'W',88=>'X',89=>'Y',90=>'Z',91=>'bracketleft',92=>'backslash',93=>'bracketright',94=>'asciicircum',95=>'underscore',96=>'grave',97=>'a',98=>'b',99=>'c',100=>'d',101=>'e',102=>'f',103=>'g',104=>'h',105=>'i',106=>'j',107=>'k',108=>'l',109=>'m',110=>'n',111=>'o',112=>'p',113=>'q',114=>'r',115=>'s',116=>'t',117=>'u',118=>'v',119=>'w',120=>'x',121=>'y',122=>'z',123=>'braceleft',124=>'bar',125=>'braceright',126=>'asciitilde',127=>'.notdef',128=>'Euro',129=>'.notdef',130=>'quotesinglbase',131=>'.notdef',132=>'quotedblbase',133=>'ellipsis',134=>'dagger',135=>'daggerdbl',136=>'.notdef',137=>'perthousand',138=>'.notdef',139=>'guilsinglleft',140=>'.notdef',141=>'dieresis',142=>'caron',143=>'cedilla',144=>'.notdef',145=>'quoteleft',146=>'quoteright',147=>'quotedblleft',148=>'quotedblright',149=>'bullet',150=>'endash',151=>'emdash',152=>'.notdef',153=>'trademark',154=>'.notdef',155=>'guilsinglright',156=>'.notdef',157=>'macron',158=>'ogonek',159=>'.notdef',160=>'space',161=>'.notdef',162=>'cent',163=>'sterling',164=>'currency',165=>'.notdef',166=>'brokenbar',167=>'section',168=>'Oslash',169=>'copyright',170=>'Rcommaaccent',171=>'guillemotleft',172=>'logicalnot',173=>'hyphen',174=>'registered',175=>'AE',176=>'degree',177=>'plusminus',178=>'twosuperior',179=>'threesuperior',180=>'acute',181=>'mu',182=>'paragraph',183=>'periodcentered',184=>'oslash',185=>'onesuperior',186=>'rcommaaccent',187=>'guillemotright',188=>'onequarter',189=>'onehalf',190=>'threequarters',191=>'ae',192=>'Aogonek',193=>'Iogonek',194=>'Amacron',195=>'Cacute',196=>'Adieresis',197=>'Aring',198=>'Eogonek',199=>'Emacron',200=>'Ccaron',201=>'Eacute',202=>'Zacute',203=>'Edotaccent',204=>'Gcommaaccent',205=>'Kcommaaccent',206=>'Imacron',207=>'Lcommaaccent',208=>'Scaron',209=>'Nacute',210=>'Ncommaaccent',211=>'Oacute',212=>'Omacron',213=>'Otilde',214=>'Odieresis',215=>'multiply',216=>'Uogonek',217=>'Lslash',218=>'Sacute',219=>'Umacron',220=>'Udieresis',221=>'Zdotaccent',222=>'Zcaron',223=>'germandbls',224=>'aogonek',225=>'iogonek',226=>'amacron',227=>'cacute',228=>'adieresis',229=>'aring',230=>'eogonek',231=>'emacron',232=>'ccaron',233=>'eacute',234=>'zacute',235=>'edotaccent',236=>'gcommaaccent',237=>'kcommaaccent',238=>'imacron',239=>'lcommaaccent',240=>'scaron',241=>'nacute',242=>'ncommaaccent',243=>'oacute',244=>'omacron',245=>'otilde',246=>'odieresis',247=>'divide',248=>'uogonek',249=>'lslash',250=>'sacute',251=>'umacron',252=>'udieresis',253=>'zdotaccent',254=>'zcaron',255=>'dotaccent'), - -// encoding map for: cp1258 -'cp1258' => array(0=>'.notdef',1=>'.notdef',2=>'.notdef',3=>'.notdef',4=>'.notdef',5=>'.notdef',6=>'.notdef',7=>'.notdef',8=>'.notdef',9=>'.notdef',10=>'.notdef',11=>'.notdef',12=>'.notdef',13=>'.notdef',14=>'.notdef',15=>'.notdef',16=>'.notdef',17=>'.notdef',18=>'.notdef',19=>'.notdef',20=>'.notdef',21=>'.notdef',22=>'.notdef',23=>'.notdef',24=>'.notdef',25=>'.notdef',26=>'.notdef',27=>'.notdef',28=>'.notdef',29=>'.notdef',30=>'.notdef',31=>'.notdef',32=>'space',33=>'exclam',34=>'quotedbl',35=>'numbersign',36=>'dollar',37=>'percent',38=>'ampersand',39=>'quotesingle',40=>'parenleft',41=>'parenright',42=>'asterisk',43=>'plus',44=>'comma',45=>'hyphen',46=>'period',47=>'slash',48=>'zero',49=>'one',50=>'two',51=>'three',52=>'four',53=>'five',54=>'six',55=>'seven',56=>'eight',57=>'nine',58=>'colon',59=>'semicolon',60=>'less',61=>'equal',62=>'greater',63=>'question',64=>'at',65=>'A',66=>'B',67=>'C',68=>'D',69=>'E',70=>'F',71=>'G',72=>'H',73=>'I',74=>'J',75=>'K',76=>'L',77=>'M',78=>'N',79=>'O',80=>'P',81=>'Q',82=>'R',83=>'S',84=>'T',85=>'U',86=>'V',87=>'W',88=>'X',89=>'Y',90=>'Z',91=>'bracketleft',92=>'backslash',93=>'bracketright',94=>'asciicircum',95=>'underscore',96=>'grave',97=>'a',98=>'b',99=>'c',100=>'d',101=>'e',102=>'f',103=>'g',104=>'h',105=>'i',106=>'j',107=>'k',108=>'l',109=>'m',110=>'n',111=>'o',112=>'p',113=>'q',114=>'r',115=>'s',116=>'t',117=>'u',118=>'v',119=>'w',120=>'x',121=>'y',122=>'z',123=>'braceleft',124=>'bar',125=>'braceright',126=>'asciitilde',127=>'.notdef',128=>'Euro',129=>'.notdef',130=>'quotesinglbase',131=>'florin',132=>'quotedblbase',133=>'ellipsis',134=>'dagger',135=>'daggerdbl',136=>'circumflex',137=>'perthousand',138=>'.notdef',139=>'guilsinglleft',140=>'OE',141=>'.notdef',142=>'.notdef',143=>'.notdef',144=>'.notdef',145=>'quoteleft',146=>'quoteright',147=>'quotedblleft',148=>'quotedblright',149=>'bullet',150=>'endash',151=>'emdash',152=>'tilde',153=>'trademark',154=>'.notdef',155=>'guilsinglright',156=>'oe',157=>'.notdef',158=>'.notdef',159=>'Ydieresis',160=>'space',161=>'exclamdown',162=>'cent',163=>'sterling',164=>'currency',165=>'yen',166=>'brokenbar',167=>'section',168=>'dieresis',169=>'copyright',170=>'ordfeminine',171=>'guillemotleft',172=>'logicalnot',173=>'hyphen',174=>'registered',175=>'macron',176=>'degree',177=>'plusminus',178=>'twosuperior',179=>'threesuperior',180=>'acute',181=>'mu',182=>'paragraph',183=>'periodcentered',184=>'cedilla',185=>'onesuperior',186=>'ordmasculine',187=>'guillemotright',188=>'onequarter',189=>'onehalf',190=>'threequarters',191=>'questiondown',192=>'Agrave',193=>'Aacute',194=>'Acircumflex',195=>'Abreve',196=>'Adieresis',197=>'Aring',198=>'AE',199=>'Ccedilla',200=>'Egrave',201=>'Eacute',202=>'Ecircumflex',203=>'Edieresis',204=>'gravecomb',205=>'Iacute',206=>'Icircumflex',207=>'Idieresis',208=>'Dcroat',209=>'Ntilde',210=>'hookabovecomb',211=>'Oacute',212=>'Ocircumflex',213=>'Ohorn',214=>'Odieresis',215=>'multiply',216=>'Oslash',217=>'Ugrave',218=>'Uacute',219=>'Ucircumflex',220=>'Udieresis',221=>'Uhorn',222=>'tildecomb',223=>'germandbls',224=>'agrave',225=>'aacute',226=>'acircumflex',227=>'abreve',228=>'adieresis',229=>'aring',230=>'ae',231=>'ccedilla',232=>'egrave',233=>'eacute',234=>'ecircumflex',235=>'edieresis',236=>'acutecomb',237=>'iacute',238=>'icircumflex',239=>'idieresis',240=>'dcroat',241=>'ntilde',242=>'dotbelowcomb',243=>'oacute',244=>'ocircumflex',245=>'ohorn',246=>'odieresis',247=>'divide',248=>'oslash',249=>'ugrave',250=>'uacute',251=>'ucircumflex',252=>'udieresis',253=>'uhorn',254=>'dong',255=>'ydieresis'), - -// encoding map for: iso-8859-1 -'iso-8859-1' => array(0=>'.notdef',1=>'.notdef',2=>'.notdef',3=>'.notdef',4=>'.notdef',5=>'.notdef',6=>'.notdef',7=>'.notdef',8=>'.notdef',9=>'.notdef',10=>'.notdef',11=>'.notdef',12=>'.notdef',13=>'.notdef',14=>'.notdef',15=>'.notdef',16=>'.notdef',17=>'.notdef',18=>'.notdef',19=>'.notdef',20=>'.notdef',21=>'.notdef',22=>'.notdef',23=>'.notdef',24=>'.notdef',25=>'.notdef',26=>'.notdef',27=>'.notdef',28=>'.notdef',29=>'.notdef',30=>'.notdef',31=>'.notdef',32=>'space',33=>'exclam',34=>'quotedbl',35=>'numbersign',36=>'dollar',37=>'percent',38=>'ampersand',39=>'quotesingle',40=>'parenleft',41=>'parenright',42=>'asterisk',43=>'plus',44=>'comma',45=>'hyphen',46=>'period',47=>'slash',48=>'zero',49=>'one',50=>'two',51=>'three',52=>'four',53=>'five',54=>'six',55=>'seven',56=>'eight',57=>'nine',58=>'colon',59=>'semicolon',60=>'less',61=>'equal',62=>'greater',63=>'question',64=>'at',65=>'A',66=>'B',67=>'C',68=>'D',69=>'E',70=>'F',71=>'G',72=>'H',73=>'I',74=>'J',75=>'K',76=>'L',77=>'M',78=>'N',79=>'O',80=>'P',81=>'Q',82=>'R',83=>'S',84=>'T',85=>'U',86=>'V',87=>'W',88=>'X',89=>'Y',90=>'Z',91=>'bracketleft',92=>'backslash',93=>'bracketright',94=>'asciicircum',95=>'underscore',96=>'grave',97=>'a',98=>'b',99=>'c',100=>'d',101=>'e',102=>'f',103=>'g',104=>'h',105=>'i',106=>'j',107=>'k',108=>'l',109=>'m',110=>'n',111=>'o',112=>'p',113=>'q',114=>'r',115=>'s',116=>'t',117=>'u',118=>'v',119=>'w',120=>'x',121=>'y',122=>'z',123=>'braceleft',124=>'bar',125=>'braceright',126=>'asciitilde',127=>'.notdef',128=>'.notdef',129=>'.notdef',130=>'.notdef',131=>'.notdef',132=>'.notdef',133=>'.notdef',134=>'.notdef',135=>'.notdef',136=>'.notdef',137=>'.notdef',138=>'.notdef',139=>'.notdef',140=>'.notdef',141=>'.notdef',142=>'.notdef',143=>'.notdef',144=>'.notdef',145=>'.notdef',146=>'.notdef',147=>'.notdef',148=>'.notdef',149=>'.notdef',150=>'.notdef',151=>'.notdef',152=>'.notdef',153=>'.notdef',154=>'.notdef',155=>'.notdef',156=>'.notdef',157=>'.notdef',158=>'.notdef',159=>'.notdef',160=>'space',161=>'exclamdown',162=>'cent',163=>'sterling',164=>'currency',165=>'yen',166=>'brokenbar',167=>'section',168=>'dieresis',169=>'copyright',170=>'ordfeminine',171=>'guillemotleft',172=>'logicalnot',173=>'hyphen',174=>'registered',175=>'macron',176=>'degree',177=>'plusminus',178=>'twosuperior',179=>'threesuperior',180=>'acute',181=>'mu',182=>'paragraph',183=>'periodcentered',184=>'cedilla',185=>'onesuperior',186=>'ordmasculine',187=>'guillemotright',188=>'onequarter',189=>'onehalf',190=>'threequarters',191=>'questiondown',192=>'Agrave',193=>'Aacute',194=>'Acircumflex',195=>'Atilde',196=>'Adieresis',197=>'Aring',198=>'AE',199=>'Ccedilla',200=>'Egrave',201=>'Eacute',202=>'Ecircumflex',203=>'Edieresis',204=>'Igrave',205=>'Iacute',206=>'Icircumflex',207=>'Idieresis',208=>'Eth',209=>'Ntilde',210=>'Ograve',211=>'Oacute',212=>'Ocircumflex',213=>'Otilde',214=>'Odieresis',215=>'multiply',216=>'Oslash',217=>'Ugrave',218=>'Uacute',219=>'Ucircumflex',220=>'Udieresis',221=>'Yacute',222=>'Thorn',223=>'germandbls',224=>'agrave',225=>'aacute',226=>'acircumflex',227=>'atilde',228=>'adieresis',229=>'aring',230=>'ae',231=>'ccedilla',232=>'egrave',233=>'eacute',234=>'ecircumflex',235=>'edieresis',236=>'igrave',237=>'iacute',238=>'icircumflex',239=>'idieresis',240=>'eth',241=>'ntilde',242=>'ograve',243=>'oacute',244=>'ocircumflex',245=>'otilde',246=>'odieresis',247=>'divide',248=>'oslash',249=>'ugrave',250=>'uacute',251=>'ucircumflex',252=>'udieresis',253=>'yacute',254=>'thorn',255=>'ydieresis'), - -// encoding map for: iso-8859-2 -'iso-8859-2' => array(0=>'.notdef',1=>'.notdef',2=>'.notdef',3=>'.notdef',4=>'.notdef',5=>'.notdef',6=>'.notdef',7=>'.notdef',8=>'.notdef',9=>'.notdef',10=>'.notdef',11=>'.notdef',12=>'.notdef',13=>'.notdef',14=>'.notdef',15=>'.notdef',16=>'.notdef',17=>'.notdef',18=>'.notdef',19=>'.notdef',20=>'.notdef',21=>'.notdef',22=>'.notdef',23=>'.notdef',24=>'.notdef',25=>'.notdef',26=>'.notdef',27=>'.notdef',28=>'.notdef',29=>'.notdef',30=>'.notdef',31=>'.notdef',32=>'space',33=>'exclam',34=>'quotedbl',35=>'numbersign',36=>'dollar',37=>'percent',38=>'ampersand',39=>'quotesingle',40=>'parenleft',41=>'parenright',42=>'asterisk',43=>'plus',44=>'comma',45=>'hyphen',46=>'period',47=>'slash',48=>'zero',49=>'one',50=>'two',51=>'three',52=>'four',53=>'five',54=>'six',55=>'seven',56=>'eight',57=>'nine',58=>'colon',59=>'semicolon',60=>'less',61=>'equal',62=>'greater',63=>'question',64=>'at',65=>'A',66=>'B',67=>'C',68=>'D',69=>'E',70=>'F',71=>'G',72=>'H',73=>'I',74=>'J',75=>'K',76=>'L',77=>'M',78=>'N',79=>'O',80=>'P',81=>'Q',82=>'R',83=>'S',84=>'T',85=>'U',86=>'V',87=>'W',88=>'X',89=>'Y',90=>'Z',91=>'bracketleft',92=>'backslash',93=>'bracketright',94=>'asciicircum',95=>'underscore',96=>'grave',97=>'a',98=>'b',99=>'c',100=>'d',101=>'e',102=>'f',103=>'g',104=>'h',105=>'i',106=>'j',107=>'k',108=>'l',109=>'m',110=>'n',111=>'o',112=>'p',113=>'q',114=>'r',115=>'s',116=>'t',117=>'u',118=>'v',119=>'w',120=>'x',121=>'y',122=>'z',123=>'braceleft',124=>'bar',125=>'braceright',126=>'asciitilde',127=>'.notdef',128=>'.notdef',129=>'.notdef',130=>'.notdef',131=>'.notdef',132=>'.notdef',133=>'.notdef',134=>'.notdef',135=>'.notdef',136=>'.notdef',137=>'.notdef',138=>'.notdef',139=>'.notdef',140=>'.notdef',141=>'.notdef',142=>'.notdef',143=>'.notdef',144=>'.notdef',145=>'.notdef',146=>'.notdef',147=>'.notdef',148=>'.notdef',149=>'.notdef',150=>'.notdef',151=>'.notdef',152=>'.notdef',153=>'.notdef',154=>'.notdef',155=>'.notdef',156=>'.notdef',157=>'.notdef',158=>'.notdef',159=>'.notdef',160=>'space',161=>'Aogonek',162=>'breve',163=>'Lslash',164=>'currency',165=>'Lcaron',166=>'Sacute',167=>'section',168=>'dieresis',169=>'Scaron',170=>'Scedilla',171=>'Tcaron',172=>'Zacute',173=>'hyphen',174=>'Zcaron',175=>'Zdotaccent',176=>'degree',177=>'aogonek',178=>'ogonek',179=>'lslash',180=>'acute',181=>'lcaron',182=>'sacute',183=>'caron',184=>'cedilla',185=>'scaron',186=>'scedilla',187=>'tcaron',188=>'zacute',189=>'hungarumlaut',190=>'zcaron',191=>'zdotaccent',192=>'Racute',193=>'Aacute',194=>'Acircumflex',195=>'Abreve',196=>'Adieresis',197=>'Lacute',198=>'Cacute',199=>'Ccedilla',200=>'Ccaron',201=>'Eacute',202=>'Eogonek',203=>'Edieresis',204=>'Ecaron',205=>'Iacute',206=>'Icircumflex',207=>'Dcaron',208=>'Dcroat',209=>'Nacute',210=>'Ncaron',211=>'Oacute',212=>'Ocircumflex',213=>'Ohungarumlaut',214=>'Odieresis',215=>'multiply',216=>'Rcaron',217=>'Uring',218=>'Uacute',219=>'Uhungarumlaut',220=>'Udieresis',221=>'Yacute',222=>'Tcommaaccent',223=>'germandbls',224=>'racute',225=>'aacute',226=>'acircumflex',227=>'abreve',228=>'adieresis',229=>'lacute',230=>'cacute',231=>'ccedilla',232=>'ccaron',233=>'eacute',234=>'eogonek',235=>'edieresis',236=>'ecaron',237=>'iacute',238=>'icircumflex',239=>'dcaron',240=>'dcroat',241=>'nacute',242=>'ncaron',243=>'oacute',244=>'ocircumflex',245=>'ohungarumlaut',246=>'odieresis',247=>'divide',248=>'rcaron',249=>'uring',250=>'uacute',251=>'uhungarumlaut',252=>'udieresis',253=>'yacute',254=>'tcommaaccent',255=>'dotaccent'), - -// encoding map for: iso-8859-4 -'iso-8859-4' => array(0=>'.notdef',1=>'.notdef',2=>'.notdef',3=>'.notdef',4=>'.notdef',5=>'.notdef',6=>'.notdef',7=>'.notdef',8=>'.notdef',9=>'.notdef',10=>'.notdef',11=>'.notdef',12=>'.notdef',13=>'.notdef',14=>'.notdef',15=>'.notdef',16=>'.notdef',17=>'.notdef',18=>'.notdef',19=>'.notdef',20=>'.notdef',21=>'.notdef',22=>'.notdef',23=>'.notdef',24=>'.notdef',25=>'.notdef',26=>'.notdef',27=>'.notdef',28=>'.notdef',29=>'.notdef',30=>'.notdef',31=>'.notdef',32=>'space',33=>'exclam',34=>'quotedbl',35=>'numbersign',36=>'dollar',37=>'percent',38=>'ampersand',39=>'quotesingle',40=>'parenleft',41=>'parenright',42=>'asterisk',43=>'plus',44=>'comma',45=>'hyphen',46=>'period',47=>'slash',48=>'zero',49=>'one',50=>'two',51=>'three',52=>'four',53=>'five',54=>'six',55=>'seven',56=>'eight',57=>'nine',58=>'colon',59=>'semicolon',60=>'less',61=>'equal',62=>'greater',63=>'question',64=>'at',65=>'A',66=>'B',67=>'C',68=>'D',69=>'E',70=>'F',71=>'G',72=>'H',73=>'I',74=>'J',75=>'K',76=>'L',77=>'M',78=>'N',79=>'O',80=>'P',81=>'Q',82=>'R',83=>'S',84=>'T',85=>'U',86=>'V',87=>'W',88=>'X',89=>'Y',90=>'Z',91=>'bracketleft',92=>'backslash',93=>'bracketright',94=>'asciicircum',95=>'underscore',96=>'grave',97=>'a',98=>'b',99=>'c',100=>'d',101=>'e',102=>'f',103=>'g',104=>'h',105=>'i',106=>'j',107=>'k',108=>'l',109=>'m',110=>'n',111=>'o',112=>'p',113=>'q',114=>'r',115=>'s',116=>'t',117=>'u',118=>'v',119=>'w',120=>'x',121=>'y',122=>'z',123=>'braceleft',124=>'bar',125=>'braceright',126=>'asciitilde',127=>'.notdef',128=>'.notdef',129=>'.notdef',130=>'.notdef',131=>'.notdef',132=>'.notdef',133=>'.notdef',134=>'.notdef',135=>'.notdef',136=>'.notdef',137=>'.notdef',138=>'.notdef',139=>'.notdef',140=>'.notdef',141=>'.notdef',142=>'.notdef',143=>'.notdef',144=>'.notdef',145=>'.notdef',146=>'.notdef',147=>'.notdef',148=>'.notdef',149=>'.notdef',150=>'.notdef',151=>'.notdef',152=>'.notdef',153=>'.notdef',154=>'.notdef',155=>'.notdef',156=>'.notdef',157=>'.notdef',158=>'.notdef',159=>'.notdef',160=>'space',161=>'Aogonek',162=>'kgreenlandic',163=>'Rcommaaccent',164=>'currency',165=>'Itilde',166=>'Lcommaaccent',167=>'section',168=>'dieresis',169=>'Scaron',170=>'Emacron',171=>'Gcommaaccent',172=>'Tbar',173=>'hyphen',174=>'Zcaron',175=>'macron',176=>'degree',177=>'aogonek',178=>'ogonek',179=>'rcommaaccent',180=>'acute',181=>'itilde',182=>'lcommaaccent',183=>'caron',184=>'cedilla',185=>'scaron',186=>'emacron',187=>'gcommaaccent',188=>'tbar',189=>'Eng',190=>'zcaron',191=>'eng',192=>'Amacron',193=>'Aacute',194=>'Acircumflex',195=>'Atilde',196=>'Adieresis',197=>'Aring',198=>'AE',199=>'Iogonek',200=>'Ccaron',201=>'Eacute',202=>'Eogonek',203=>'Edieresis',204=>'Edotaccent',205=>'Iacute',206=>'Icircumflex',207=>'Imacron',208=>'Dcroat',209=>'Ncommaaccent',210=>'Omacron',211=>'Kcommaaccent',212=>'Ocircumflex',213=>'Otilde',214=>'Odieresis',215=>'multiply',216=>'Oslash',217=>'Uogonek',218=>'Uacute',219=>'Ucircumflex',220=>'Udieresis',221=>'Utilde',222=>'Umacron',223=>'germandbls',224=>'amacron',225=>'aacute',226=>'acircumflex',227=>'atilde',228=>'adieresis',229=>'aring',230=>'ae',231=>'iogonek',232=>'ccaron',233=>'eacute',234=>'eogonek',235=>'edieresis',236=>'edotaccent',237=>'iacute',238=>'icircumflex',239=>'imacron',240=>'dcroat',241=>'ncommaaccent',242=>'omacron',243=>'kcommaaccent',244=>'ocircumflex',245=>'otilde',246=>'odieresis',247=>'divide',248=>'oslash',249=>'uogonek',250=>'uacute',251=>'ucircumflex',252=>'udieresis',253=>'utilde',254=>'umacron',255=>'dotaccent'), - -// encoding map for: iso-8859-5 -'iso-8859-5' => array(0=>'.notdef',1=>'.notdef',2=>'.notdef',3=>'.notdef',4=>'.notdef',5=>'.notdef',6=>'.notdef',7=>'.notdef',8=>'.notdef',9=>'.notdef',10=>'.notdef',11=>'.notdef',12=>'.notdef',13=>'.notdef',14=>'.notdef',15=>'.notdef',16=>'.notdef',17=>'.notdef',18=>'.notdef',19=>'.notdef',20=>'.notdef',21=>'.notdef',22=>'.notdef',23=>'.notdef',24=>'.notdef',25=>'.notdef',26=>'.notdef',27=>'.notdef',28=>'.notdef',29=>'.notdef',30=>'.notdef',31=>'.notdef',32=>'space',33=>'exclam',34=>'quotedbl',35=>'numbersign',36=>'dollar',37=>'percent',38=>'ampersand',39=>'quotesingle',40=>'parenleft',41=>'parenright',42=>'asterisk',43=>'plus',44=>'comma',45=>'hyphen',46=>'period',47=>'slash',48=>'zero',49=>'one',50=>'two',51=>'three',52=>'four',53=>'five',54=>'six',55=>'seven',56=>'eight',57=>'nine',58=>'colon',59=>'semicolon',60=>'less',61=>'equal',62=>'greater',63=>'question',64=>'at',65=>'A',66=>'B',67=>'C',68=>'D',69=>'E',70=>'F',71=>'G',72=>'H',73=>'I',74=>'J',75=>'K',76=>'L',77=>'M',78=>'N',79=>'O',80=>'P',81=>'Q',82=>'R',83=>'S',84=>'T',85=>'U',86=>'V',87=>'W',88=>'X',89=>'Y',90=>'Z',91=>'bracketleft',92=>'backslash',93=>'bracketright',94=>'asciicircum',95=>'underscore',96=>'grave',97=>'a',98=>'b',99=>'c',100=>'d',101=>'e',102=>'f',103=>'g',104=>'h',105=>'i',106=>'j',107=>'k',108=>'l',109=>'m',110=>'n',111=>'o',112=>'p',113=>'q',114=>'r',115=>'s',116=>'t',117=>'u',118=>'v',119=>'w',120=>'x',121=>'y',122=>'z',123=>'braceleft',124=>'bar',125=>'braceright',126=>'asciitilde',127=>'.notdef',128=>'.notdef',129=>'.notdef',130=>'.notdef',131=>'.notdef',132=>'.notdef',133=>'.notdef',134=>'.notdef',135=>'.notdef',136=>'.notdef',137=>'.notdef',138=>'.notdef',139=>'.notdef',140=>'.notdef',141=>'.notdef',142=>'.notdef',143=>'.notdef',144=>'.notdef',145=>'.notdef',146=>'.notdef',147=>'.notdef',148=>'.notdef',149=>'.notdef',150=>'.notdef',151=>'.notdef',152=>'.notdef',153=>'.notdef',154=>'.notdef',155=>'.notdef',156=>'.notdef',157=>'.notdef',158=>'.notdef',159=>'.notdef',160=>'space',161=>'afii10023',162=>'afii10051',163=>'afii10052',164=>'afii10053',165=>'afii10054',166=>'afii10055',167=>'afii10056',168=>'afii10057',169=>'afii10058',170=>'afii10059',171=>'afii10060',172=>'afii10061',173=>'hyphen',174=>'afii10062',175=>'afii10145',176=>'afii10017',177=>'afii10018',178=>'afii10019',179=>'afii10020',180=>'afii10021',181=>'afii10022',182=>'afii10024',183=>'afii10025',184=>'afii10026',185=>'afii10027',186=>'afii10028',187=>'afii10029',188=>'afii10030',189=>'afii10031',190=>'afii10032',191=>'afii10033',192=>'afii10034',193=>'afii10035',194=>'afii10036',195=>'afii10037',196=>'afii10038',197=>'afii10039',198=>'afii10040',199=>'afii10041',200=>'afii10042',201=>'afii10043',202=>'afii10044',203=>'afii10045',204=>'afii10046',205=>'afii10047',206=>'afii10048',207=>'afii10049',208=>'afii10065',209=>'afii10066',210=>'afii10067',211=>'afii10068',212=>'afii10069',213=>'afii10070',214=>'afii10072',215=>'afii10073',216=>'afii10074',217=>'afii10075',218=>'afii10076',219=>'afii10077',220=>'afii10078',221=>'afii10079',222=>'afii10080',223=>'afii10081',224=>'afii10082',225=>'afii10083',226=>'afii10084',227=>'afii10085',228=>'afii10086',229=>'afii10087',230=>'afii10088',231=>'afii10089',232=>'afii10090',233=>'afii10091',234=>'afii10092',235=>'afii10093',236=>'afii10094',237=>'afii10095',238=>'afii10096',239=>'afii10097',240=>'afii61352',241=>'afii10071',242=>'afii10099',243=>'afii10100',244=>'afii10101',245=>'afii10102',246=>'afii10103',247=>'afii10104',248=>'afii10105',249=>'afii10106',250=>'afii10107',251=>'afii10108',252=>'afii10109',253=>'section',254=>'afii10110',255=>'afii10193'), - -// encoding map for: iso-8859-7 -'iso-8859-7' => array(0=>'.notdef',1=>'.notdef',2=>'.notdef',3=>'.notdef',4=>'.notdef',5=>'.notdef',6=>'.notdef',7=>'.notdef',8=>'.notdef',9=>'.notdef',10=>'.notdef',11=>'.notdef',12=>'.notdef',13=>'.notdef',14=>'.notdef',15=>'.notdef',16=>'.notdef',17=>'.notdef',18=>'.notdef',19=>'.notdef',20=>'.notdef',21=>'.notdef',22=>'.notdef',23=>'.notdef',24=>'.notdef',25=>'.notdef',26=>'.notdef',27=>'.notdef',28=>'.notdef',29=>'.notdef',30=>'.notdef',31=>'.notdef',32=>'space',33=>'exclam',34=>'quotedbl',35=>'numbersign',36=>'dollar',37=>'percent',38=>'ampersand',39=>'quotesingle',40=>'parenleft',41=>'parenright',42=>'asterisk',43=>'plus',44=>'comma',45=>'hyphen',46=>'period',47=>'slash',48=>'zero',49=>'one',50=>'two',51=>'three',52=>'four',53=>'five',54=>'six',55=>'seven',56=>'eight',57=>'nine',58=>'colon',59=>'semicolon',60=>'less',61=>'equal',62=>'greater',63=>'question',64=>'at',65=>'A',66=>'B',67=>'C',68=>'D',69=>'E',70=>'F',71=>'G',72=>'H',73=>'I',74=>'J',75=>'K',76=>'L',77=>'M',78=>'N',79=>'O',80=>'P',81=>'Q',82=>'R',83=>'S',84=>'T',85=>'U',86=>'V',87=>'W',88=>'X',89=>'Y',90=>'Z',91=>'bracketleft',92=>'backslash',93=>'bracketright',94=>'asciicircum',95=>'underscore',96=>'grave',97=>'a',98=>'b',99=>'c',100=>'d',101=>'e',102=>'f',103=>'g',104=>'h',105=>'i',106=>'j',107=>'k',108=>'l',109=>'m',110=>'n',111=>'o',112=>'p',113=>'q',114=>'r',115=>'s',116=>'t',117=>'u',118=>'v',119=>'w',120=>'x',121=>'y',122=>'z',123=>'braceleft',124=>'bar',125=>'braceright',126=>'asciitilde',127=>'.notdef',128=>'.notdef',129=>'.notdef',130=>'.notdef',131=>'.notdef',132=>'.notdef',133=>'.notdef',134=>'.notdef',135=>'.notdef',136=>'.notdef',137=>'.notdef',138=>'.notdef',139=>'.notdef',140=>'.notdef',141=>'.notdef',142=>'.notdef',143=>'.notdef',144=>'.notdef',145=>'.notdef',146=>'.notdef',147=>'.notdef',148=>'.notdef',149=>'.notdef',150=>'.notdef',151=>'.notdef',152=>'.notdef',153=>'.notdef',154=>'.notdef',155=>'.notdef',156=>'.notdef',157=>'.notdef',158=>'.notdef',159=>'.notdef',160=>'space',161=>'quoteleft',162=>'quoteright',163=>'sterling',164=>'.notdef',165=>'.notdef',166=>'brokenbar',167=>'section',168=>'dieresis',169=>'copyright',170=>'.notdef',171=>'guillemotleft',172=>'logicalnot',173=>'hyphen',174=>'.notdef',175=>'afii00208',176=>'degree',177=>'plusminus',178=>'twosuperior',179=>'threesuperior',180=>'tonos',181=>'dieresistonos',182=>'Alphatonos',183=>'periodcentered',184=>'Epsilontonos',185=>'Etatonos',186=>'Iotatonos',187=>'guillemotright',188=>'Omicrontonos',189=>'onehalf',190=>'Upsilontonos',191=>'Omegatonos',192=>'iotadieresistonos',193=>'Alpha',194=>'Beta',195=>'Gamma',196=>'Delta',197=>'Epsilon',198=>'Zeta',199=>'Eta',200=>'Theta',201=>'Iota',202=>'Kappa',203=>'Lambda',204=>'Mu',205=>'Nu',206=>'Xi',207=>'Omicron',208=>'Pi',209=>'Rho',210=>'.notdef',211=>'Sigma',212=>'Tau',213=>'Upsilon',214=>'Phi',215=>'Chi',216=>'Psi',217=>'Omega',218=>'Iotadieresis',219=>'Upsilondieresis',220=>'alphatonos',221=>'epsilontonos',222=>'etatonos',223=>'iotatonos',224=>'upsilondieresistonos',225=>'alpha',226=>'beta',227=>'gamma',228=>'delta',229=>'epsilon',230=>'zeta',231=>'eta',232=>'theta',233=>'iota',234=>'kappa',235=>'lambda',236=>'mu',237=>'nu',238=>'xi',239=>'omicron',240=>'pi',241=>'rho',242=>'sigma1',243=>'sigma',244=>'tau',245=>'upsilon',246=>'phi',247=>'chi',248=>'psi',249=>'omega',250=>'iotadieresis',251=>'upsilondieresis',252=>'omicrontonos',253=>'upsilontonos',254=>'omegatonos',255=>'.notdef'), - -// encoding map for: iso-8859-9 -'iso-8859-9' => array(0=>'.notdef',1=>'.notdef',2=>'.notdef',3=>'.notdef',4=>'.notdef',5=>'.notdef',6=>'.notdef',7=>'.notdef',8=>'.notdef',9=>'.notdef',10=>'.notdef',11=>'.notdef',12=>'.notdef',13=>'.notdef',14=>'.notdef',15=>'.notdef',16=>'.notdef',17=>'.notdef',18=>'.notdef',19=>'.notdef',20=>'.notdef',21=>'.notdef',22=>'.notdef',23=>'.notdef',24=>'.notdef',25=>'.notdef',26=>'.notdef',27=>'.notdef',28=>'.notdef',29=>'.notdef',30=>'.notdef',31=>'.notdef',32=>'space',33=>'exclam',34=>'quotedbl',35=>'numbersign',36=>'dollar',37=>'percent',38=>'ampersand',39=>'quotesingle',40=>'parenleft',41=>'parenright',42=>'asterisk',43=>'plus',44=>'comma',45=>'hyphen',46=>'period',47=>'slash',48=>'zero',49=>'one',50=>'two',51=>'three',52=>'four',53=>'five',54=>'six',55=>'seven',56=>'eight',57=>'nine',58=>'colon',59=>'semicolon',60=>'less',61=>'equal',62=>'greater',63=>'question',64=>'at',65=>'A',66=>'B',67=>'C',68=>'D',69=>'E',70=>'F',71=>'G',72=>'H',73=>'I',74=>'J',75=>'K',76=>'L',77=>'M',78=>'N',79=>'O',80=>'P',81=>'Q',82=>'R',83=>'S',84=>'T',85=>'U',86=>'V',87=>'W',88=>'X',89=>'Y',90=>'Z',91=>'bracketleft',92=>'backslash',93=>'bracketright',94=>'asciicircum',95=>'underscore',96=>'grave',97=>'a',98=>'b',99=>'c',100=>'d',101=>'e',102=>'f',103=>'g',104=>'h',105=>'i',106=>'j',107=>'k',108=>'l',109=>'m',110=>'n',111=>'o',112=>'p',113=>'q',114=>'r',115=>'s',116=>'t',117=>'u',118=>'v',119=>'w',120=>'x',121=>'y',122=>'z',123=>'braceleft',124=>'bar',125=>'braceright',126=>'asciitilde',127=>'.notdef',128=>'.notdef',129=>'.notdef',130=>'.notdef',131=>'.notdef',132=>'.notdef',133=>'.notdef',134=>'.notdef',135=>'.notdef',136=>'.notdef',137=>'.notdef',138=>'.notdef',139=>'.notdef',140=>'.notdef',141=>'.notdef',142=>'.notdef',143=>'.notdef',144=>'.notdef',145=>'.notdef',146=>'.notdef',147=>'.notdef',148=>'.notdef',149=>'.notdef',150=>'.notdef',151=>'.notdef',152=>'.notdef',153=>'.notdef',154=>'.notdef',155=>'.notdef',156=>'.notdef',157=>'.notdef',158=>'.notdef',159=>'.notdef',160=>'space',161=>'exclamdown',162=>'cent',163=>'sterling',164=>'currency',165=>'yen',166=>'brokenbar',167=>'section',168=>'dieresis',169=>'copyright',170=>'ordfeminine',171=>'guillemotleft',172=>'logicalnot',173=>'hyphen',174=>'registered',175=>'macron',176=>'degree',177=>'plusminus',178=>'twosuperior',179=>'threesuperior',180=>'acute',181=>'mu',182=>'paragraph',183=>'periodcentered',184=>'cedilla',185=>'onesuperior',186=>'ordmasculine',187=>'guillemotright',188=>'onequarter',189=>'onehalf',190=>'threequarters',191=>'questiondown',192=>'Agrave',193=>'Aacute',194=>'Acircumflex',195=>'Atilde',196=>'Adieresis',197=>'Aring',198=>'AE',199=>'Ccedilla',200=>'Egrave',201=>'Eacute',202=>'Ecircumflex',203=>'Edieresis',204=>'Igrave',205=>'Iacute',206=>'Icircumflex',207=>'Idieresis',208=>'Gbreve',209=>'Ntilde',210=>'Ograve',211=>'Oacute',212=>'Ocircumflex',213=>'Otilde',214=>'Odieresis',215=>'multiply',216=>'Oslash',217=>'Ugrave',218=>'Uacute',219=>'Ucircumflex',220=>'Udieresis',221=>'Idotaccent',222=>'Scedilla',223=>'germandbls',224=>'agrave',225=>'aacute',226=>'acircumflex',227=>'atilde',228=>'adieresis',229=>'aring',230=>'ae',231=>'ccedilla',232=>'egrave',233=>'eacute',234=>'ecircumflex',235=>'edieresis',236=>'igrave',237=>'iacute',238=>'icircumflex',239=>'idieresis',240=>'gbreve',241=>'ntilde',242=>'ograve',243=>'oacute',244=>'ocircumflex',245=>'otilde',246=>'odieresis',247=>'divide',248=>'oslash',249=>'ugrave',250=>'uacute',251=>'ucircumflex',252=>'udieresis',253=>'dotlessi',254=>'scedilla',255=>'ydieresis'), - -// encoding map for: iso-8859-11 -'iso-8859-11' => array(0=>'.notdef',1=>'.notdef',2=>'.notdef',3=>'.notdef',4=>'.notdef',5=>'.notdef',6=>'.notdef',7=>'.notdef',8=>'.notdef',9=>'.notdef',10=>'.notdef',11=>'.notdef',12=>'.notdef',13=>'.notdef',14=>'.notdef',15=>'.notdef',16=>'.notdef',17=>'.notdef',18=>'.notdef',19=>'.notdef',20=>'.notdef',21=>'.notdef',22=>'.notdef',23=>'.notdef',24=>'.notdef',25=>'.notdef',26=>'.notdef',27=>'.notdef',28=>'.notdef',29=>'.notdef',30=>'.notdef',31=>'.notdef',32=>'space',33=>'exclam',34=>'quotedbl',35=>'numbersign',36=>'dollar',37=>'percent',38=>'ampersand',39=>'quotesingle',40=>'parenleft',41=>'parenright',42=>'asterisk',43=>'plus',44=>'comma',45=>'hyphen',46=>'period',47=>'slash',48=>'zero',49=>'one',50=>'two',51=>'three',52=>'four',53=>'five',54=>'six',55=>'seven',56=>'eight',57=>'nine',58=>'colon',59=>'semicolon',60=>'less',61=>'equal',62=>'greater',63=>'question',64=>'at',65=>'A',66=>'B',67=>'C',68=>'D',69=>'E',70=>'F',71=>'G',72=>'H',73=>'I',74=>'J',75=>'K',76=>'L',77=>'M',78=>'N',79=>'O',80=>'P',81=>'Q',82=>'R',83=>'S',84=>'T',85=>'U',86=>'V',87=>'W',88=>'X',89=>'Y',90=>'Z',91=>'bracketleft',92=>'backslash',93=>'bracketright',94=>'asciicircum',95=>'underscore',96=>'grave',97=>'a',98=>'b',99=>'c',100=>'d',101=>'e',102=>'f',103=>'g',104=>'h',105=>'i',106=>'j',107=>'k',108=>'l',109=>'m',110=>'n',111=>'o',112=>'p',113=>'q',114=>'r',115=>'s',116=>'t',117=>'u',118=>'v',119=>'w',120=>'x',121=>'y',122=>'z',123=>'braceleft',124=>'bar',125=>'braceright',126=>'asciitilde',127=>'.notdef',128=>'.notdef',129=>'.notdef',130=>'.notdef',131=>'.notdef',132=>'.notdef',133=>'.notdef',134=>'.notdef',135=>'.notdef',136=>'.notdef',137=>'.notdef',138=>'.notdef',139=>'.notdef',140=>'.notdef',141=>'.notdef',142=>'.notdef',143=>'.notdef',144=>'.notdef',145=>'.notdef',146=>'.notdef',147=>'.notdef',148=>'.notdef',149=>'.notdef',150=>'.notdef',151=>'.notdef',152=>'.notdef',153=>'.notdef',154=>'.notdef',155=>'.notdef',156=>'.notdef',157=>'.notdef',158=>'.notdef',159=>'.notdef',160=>'space',161=>'kokaithai',162=>'khokhaithai',163=>'khokhuatthai',164=>'khokhwaithai',165=>'khokhonthai',166=>'khorakhangthai',167=>'ngonguthai',168=>'chochanthai',169=>'chochingthai',170=>'chochangthai',171=>'sosothai',172=>'chochoethai',173=>'yoyingthai',174=>'dochadathai',175=>'topatakthai',176=>'thothanthai',177=>'thonangmonthothai',178=>'thophuthaothai',179=>'nonenthai',180=>'dodekthai',181=>'totaothai',182=>'thothungthai',183=>'thothahanthai',184=>'thothongthai',185=>'nonuthai',186=>'bobaimaithai',187=>'poplathai',188=>'phophungthai',189=>'fofathai',190=>'phophanthai',191=>'fofanthai',192=>'phosamphaothai',193=>'momathai',194=>'yoyakthai',195=>'roruathai',196=>'ruthai',197=>'lolingthai',198=>'luthai',199=>'wowaenthai',200=>'sosalathai',201=>'sorusithai',202=>'sosuathai',203=>'hohipthai',204=>'lochulathai',205=>'oangthai',206=>'honokhukthai',207=>'paiyannoithai',208=>'saraathai',209=>'maihanakatthai',210=>'saraaathai',211=>'saraamthai',212=>'saraithai',213=>'saraiithai',214=>'sarauethai',215=>'saraueethai',216=>'sarauthai',217=>'sarauuthai',218=>'phinthuthai',219=>'.notdef',220=>'.notdef',221=>'.notdef',222=>'.notdef',223=>'bahtthai',224=>'saraethai',225=>'saraaethai',226=>'saraothai',227=>'saraaimaimuanthai',228=>'saraaimaimalaithai',229=>'lakkhangyaothai',230=>'maiyamokthai',231=>'maitaikhuthai',232=>'maiekthai',233=>'maithothai',234=>'maitrithai',235=>'maichattawathai',236=>'thanthakhatthai',237=>'nikhahitthai',238=>'yamakkanthai',239=>'fongmanthai',240=>'zerothai',241=>'onethai',242=>'twothai',243=>'threethai',244=>'fourthai',245=>'fivethai',246=>'sixthai',247=>'seventhai',248=>'eightthai',249=>'ninethai',250=>'angkhankhuthai',251=>'khomutthai',252=>'.notdef',253=>'.notdef',254=>'.notdef',255=>'.notdef'), - -// encoding map for: iso-8859-15 -'iso-8859-15' => array(0=>'.notdef',1=>'.notdef',2=>'.notdef',3=>'.notdef',4=>'.notdef',5=>'.notdef',6=>'.notdef',7=>'.notdef',8=>'.notdef',9=>'.notdef',10=>'.notdef',11=>'.notdef',12=>'.notdef',13=>'.notdef',14=>'.notdef',15=>'.notdef',16=>'.notdef',17=>'.notdef',18=>'.notdef',19=>'.notdef',20=>'.notdef',21=>'.notdef',22=>'.notdef',23=>'.notdef',24=>'.notdef',25=>'.notdef',26=>'.notdef',27=>'.notdef',28=>'.notdef',29=>'.notdef',30=>'.notdef',31=>'.notdef',32=>'space',33=>'exclam',34=>'quotedbl',35=>'numbersign',36=>'dollar',37=>'percent',38=>'ampersand',39=>'quotesingle',40=>'parenleft',41=>'parenright',42=>'asterisk',43=>'plus',44=>'comma',45=>'hyphen',46=>'period',47=>'slash',48=>'zero',49=>'one',50=>'two',51=>'three',52=>'four',53=>'five',54=>'six',55=>'seven',56=>'eight',57=>'nine',58=>'colon',59=>'semicolon',60=>'less',61=>'equal',62=>'greater',63=>'question',64=>'at',65=>'A',66=>'B',67=>'C',68=>'D',69=>'E',70=>'F',71=>'G',72=>'H',73=>'I',74=>'J',75=>'K',76=>'L',77=>'M',78=>'N',79=>'O',80=>'P',81=>'Q',82=>'R',83=>'S',84=>'T',85=>'U',86=>'V',87=>'W',88=>'X',89=>'Y',90=>'Z',91=>'bracketleft',92=>'backslash',93=>'bracketright',94=>'asciicircum',95=>'underscore',96=>'grave',97=>'a',98=>'b',99=>'c',100=>'d',101=>'e',102=>'f',103=>'g',104=>'h',105=>'i',106=>'j',107=>'k',108=>'l',109=>'m',110=>'n',111=>'o',112=>'p',113=>'q',114=>'r',115=>'s',116=>'t',117=>'u',118=>'v',119=>'w',120=>'x',121=>'y',122=>'z',123=>'braceleft',124=>'bar',125=>'braceright',126=>'asciitilde',127=>'.notdef',128=>'.notdef',129=>'.notdef',130=>'.notdef',131=>'.notdef',132=>'.notdef',133=>'.notdef',134=>'.notdef',135=>'.notdef',136=>'.notdef',137=>'.notdef',138=>'.notdef',139=>'.notdef',140=>'.notdef',141=>'.notdef',142=>'.notdef',143=>'.notdef',144=>'.notdef',145=>'.notdef',146=>'.notdef',147=>'.notdef',148=>'.notdef',149=>'.notdef',150=>'.notdef',151=>'.notdef',152=>'.notdef',153=>'.notdef',154=>'.notdef',155=>'.notdef',156=>'.notdef',157=>'.notdef',158=>'.notdef',159=>'.notdef',160=>'space',161=>'exclamdown',162=>'cent',163=>'sterling',164=>'Euro',165=>'yen',166=>'Scaron',167=>'section',168=>'scaron',169=>'copyright',170=>'ordfeminine',171=>'guillemotleft',172=>'logicalnot',173=>'hyphen',174=>'registered',175=>'macron',176=>'degree',177=>'plusminus',178=>'twosuperior',179=>'threesuperior',180=>'Zcaron',181=>'mu',182=>'paragraph',183=>'periodcentered',184=>'zcaron',185=>'onesuperior',186=>'ordmasculine',187=>'guillemotright',188=>'OE',189=>'oe',190=>'Ydieresis',191=>'questiondown',192=>'Agrave',193=>'Aacute',194=>'Acircumflex',195=>'Atilde',196=>'Adieresis',197=>'Aring',198=>'AE',199=>'Ccedilla',200=>'Egrave',201=>'Eacute',202=>'Ecircumflex',203=>'Edieresis',204=>'Igrave',205=>'Iacute',206=>'Icircumflex',207=>'Idieresis',208=>'Eth',209=>'Ntilde',210=>'Ograve',211=>'Oacute',212=>'Ocircumflex',213=>'Otilde',214=>'Odieresis',215=>'multiply',216=>'Oslash',217=>'Ugrave',218=>'Uacute',219=>'Ucircumflex',220=>'Udieresis',221=>'Yacute',222=>'Thorn',223=>'germandbls',224=>'agrave',225=>'aacute',226=>'acircumflex',227=>'atilde',228=>'adieresis',229=>'aring',230=>'ae',231=>'ccedilla',232=>'egrave',233=>'eacute',234=>'ecircumflex',235=>'edieresis',236=>'igrave',237=>'iacute',238=>'icircumflex',239=>'idieresis',240=>'eth',241=>'ntilde',242=>'ograve',243=>'oacute',244=>'ocircumflex',245=>'otilde',246=>'odieresis',247=>'divide',248=>'oslash',249=>'ugrave',250=>'uacute',251=>'ucircumflex',252=>'udieresis',253=>'yacute',254=>'thorn',255=>'ydieresis'), - -// encoding map for: iso-8859-16 -'iso-8859-16' => array(0=>'.notdef',1=>'.notdef',2=>'.notdef',3=>'.notdef',4=>'.notdef',5=>'.notdef',6=>'.notdef',7=>'.notdef',8=>'.notdef',9=>'.notdef',10=>'.notdef',11=>'.notdef',12=>'.notdef',13=>'.notdef',14=>'.notdef',15=>'.notdef',16=>'.notdef',17=>'.notdef',18=>'.notdef',19=>'.notdef',20=>'.notdef',21=>'.notdef',22=>'.notdef',23=>'.notdef',24=>'.notdef',25=>'.notdef',26=>'.notdef',27=>'.notdef',28=>'.notdef',29=>'.notdef',30=>'.notdef',31=>'.notdef',32=>'space',33=>'exclam',34=>'quotedbl',35=>'numbersign',36=>'dollar',37=>'percent',38=>'ampersand',39=>'quotesingle',40=>'parenleft',41=>'parenright',42=>'asterisk',43=>'plus',44=>'comma',45=>'hyphen',46=>'period',47=>'slash',48=>'zero',49=>'one',50=>'two',51=>'three',52=>'four',53=>'five',54=>'six',55=>'seven',56=>'eight',57=>'nine',58=>'colon',59=>'semicolon',60=>'less',61=>'equal',62=>'greater',63=>'question',64=>'at',65=>'A',66=>'B',67=>'C',68=>'D',69=>'E',70=>'F',71=>'G',72=>'H',73=>'I',74=>'J',75=>'K',76=>'L',77=>'M',78=>'N',79=>'O',80=>'P',81=>'Q',82=>'R',83=>'S',84=>'T',85=>'U',86=>'V',87=>'W',88=>'X',89=>'Y',90=>'Z',91=>'bracketleft',92=>'backslash',93=>'bracketright',94=>'asciicircum',95=>'underscore',96=>'grave',97=>'a',98=>'b',99=>'c',100=>'d',101=>'e',102=>'f',103=>'g',104=>'h',105=>'i',106=>'j',107=>'k',108=>'l',109=>'m',110=>'n',111=>'o',112=>'p',113=>'q',114=>'r',115=>'s',116=>'t',117=>'u',118=>'v',119=>'w',120=>'x',121=>'y',122=>'z',123=>'braceleft',124=>'bar',125=>'braceright',126=>'asciitilde',127=>'.notdef',128=>'.notdef',129=>'.notdef',130=>'.notdef',131=>'.notdef',132=>'.notdef',133=>'.notdef',134=>'.notdef',135=>'.notdef',136=>'.notdef',137=>'.notdef',138=>'.notdef',139=>'.notdef',140=>'.notdef',141=>'.notdef',142=>'.notdef',143=>'.notdef',144=>'.notdef',145=>'.notdef',146=>'.notdef',147=>'.notdef',148=>'.notdef',149=>'.notdef',150=>'.notdef',151=>'.notdef',152=>'.notdef',153=>'.notdef',154=>'.notdef',155=>'.notdef',156=>'.notdef',157=>'.notdef',158=>'.notdef',159=>'.notdef',160=>'space',161=>'Aogonek',162=>'aogonek',163=>'Lslash',164=>'Euro',165=>'quotedblbase',166=>'Scaron',167=>'section',168=>'scaron',169=>'copyright',170=>'Scommaaccent',171=>'guillemotleft',172=>'Zacute',173=>'hyphen',174=>'zacute',175=>'Zdotaccent',176=>'degree',177=>'plusminus',178=>'Ccaron',179=>'lslash',180=>'Zcaron',181=>'quotedblright',182=>'paragraph',183=>'periodcentered',184=>'zcaron',185=>'ccaron',186=>'scommaaccent',187=>'guillemotright',188=>'OE',189=>'oe',190=>'Ydieresis',191=>'zdotaccent',192=>'Agrave',193=>'Aacute',194=>'Acircumflex',195=>'Abreve',196=>'Adieresis',197=>'Cacute',198=>'AE',199=>'Ccedilla',200=>'Egrave',201=>'Eacute',202=>'Ecircumflex',203=>'Edieresis',204=>'Igrave',205=>'Iacute',206=>'Icircumflex',207=>'Idieresis',208=>'Dcroat',209=>'Nacute',210=>'Ograve',211=>'Oacute',212=>'Ocircumflex',213=>'Ohungarumlaut',214=>'Odieresis',215=>'Sacute',216=>'Uhungarumlaut',217=>'Ugrave',218=>'Uacute',219=>'Ucircumflex',220=>'Udieresis',221=>'Eogonek',222=>'Tcommaaccent',223=>'germandbls',224=>'agrave',225=>'aacute',226=>'acircumflex',227=>'abreve',228=>'adieresis',229=>'cacute',230=>'ae',231=>'ccedilla',232=>'egrave',233=>'eacute',234=>'ecircumflex',235=>'edieresis',236=>'igrave',237=>'iacute',238=>'icircumflex',239=>'idieresis',240=>'dcroat',241=>'nacute',242=>'ograve',243=>'oacute',244=>'ocircumflex',245=>'ohungarumlaut',246=>'odieresis',247=>'sacute',248=>'uhungarumlaut',249=>'ugrave',250=>'uacute',251=>'ucircumflex',252=>'udieresis',253=>'eogonek',254=>'tcommaaccent',255=>'ydieresis'), - -// encoding map for: koi8-r -'koi8-r' => array(0=>'.notdef',1=>'.notdef',2=>'.notdef',3=>'.notdef',4=>'.notdef',5=>'.notdef',6=>'.notdef',7=>'.notdef',8=>'.notdef',9=>'.notdef',10=>'.notdef',11=>'.notdef',12=>'.notdef',13=>'.notdef',14=>'.notdef',15=>'.notdef',16=>'.notdef',17=>'.notdef',18=>'.notdef',19=>'.notdef',20=>'.notdef',21=>'.notdef',22=>'.notdef',23=>'.notdef',24=>'.notdef',25=>'.notdef',26=>'.notdef',27=>'.notdef',28=>'.notdef',29=>'.notdef',30=>'.notdef',31=>'.notdef',32=>'space',33=>'exclam',34=>'quotedbl',35=>'numbersign',36=>'dollar',37=>'percent',38=>'ampersand',39=>'quotesingle',40=>'parenleft',41=>'parenright',42=>'asterisk',43=>'plus',44=>'comma',45=>'hyphen',46=>'period',47=>'slash',48=>'zero',49=>'one',50=>'two',51=>'three',52=>'four',53=>'five',54=>'six',55=>'seven',56=>'eight',57=>'nine',58=>'colon',59=>'semicolon',60=>'less',61=>'equal',62=>'greater',63=>'question',64=>'at',65=>'A',66=>'B',67=>'C',68=>'D',69=>'E',70=>'F',71=>'G',72=>'H',73=>'I',74=>'J',75=>'K',76=>'L',77=>'M',78=>'N',79=>'O',80=>'P',81=>'Q',82=>'R',83=>'S',84=>'T',85=>'U',86=>'V',87=>'W',88=>'X',89=>'Y',90=>'Z',91=>'bracketleft',92=>'backslash',93=>'bracketright',94=>'asciicircum',95=>'underscore',96=>'grave',97=>'a',98=>'b',99=>'c',100=>'d',101=>'e',102=>'f',103=>'g',104=>'h',105=>'i',106=>'j',107=>'k',108=>'l',109=>'m',110=>'n',111=>'o',112=>'p',113=>'q',114=>'r',115=>'s',116=>'t',117=>'u',118=>'v',119=>'w',120=>'x',121=>'y',122=>'z',123=>'braceleft',124=>'bar',125=>'braceright',126=>'asciitilde',127=>'.notdef',128=>'SF100000',129=>'SF110000',130=>'SF010000',131=>'SF030000',132=>'SF020000',133=>'SF040000',134=>'SF080000',135=>'SF090000',136=>'SF060000',137=>'SF070000',138=>'SF050000',139=>'upblock',140=>'dnblock',141=>'block',142=>'lfblock',143=>'rtblock',144=>'ltshade',145=>'shade',146=>'dkshade',147=>'integraltp',148=>'filledbox',149=>'periodcentered',150=>'radical',151=>'approxequal',152=>'lessequal',153=>'greaterequal',154=>'space',155=>'integralbt',156=>'degree',157=>'twosuperior',158=>'periodcentered',159=>'divide',160=>'SF430000',161=>'SF240000',162=>'SF510000',163=>'afii10071',164=>'SF520000',165=>'SF390000',166=>'SF220000',167=>'SF210000',168=>'SF250000',169=>'SF500000',170=>'SF490000',171=>'SF380000',172=>'SF280000',173=>'SF270000',174=>'SF260000',175=>'SF360000',176=>'SF370000',177=>'SF420000',178=>'SF190000',179=>'afii10023',180=>'SF200000',181=>'SF230000',182=>'SF470000',183=>'SF480000',184=>'SF410000',185=>'SF450000',186=>'SF460000',187=>'SF400000',188=>'SF540000',189=>'SF530000',190=>'SF440000',191=>'copyright',192=>'afii10096',193=>'afii10065',194=>'afii10066',195=>'afii10088',196=>'afii10069',197=>'afii10070',198=>'afii10086',199=>'afii10068',200=>'afii10087',201=>'afii10074',202=>'afii10075',203=>'afii10076',204=>'afii10077',205=>'afii10078',206=>'afii10079',207=>'afii10080',208=>'afii10081',209=>'afii10097',210=>'afii10082',211=>'afii10083',212=>'afii10084',213=>'afii10085',214=>'afii10072',215=>'afii10067',216=>'afii10094',217=>'afii10093',218=>'afii10073',219=>'afii10090',220=>'afii10095',221=>'afii10091',222=>'afii10089',223=>'afii10092',224=>'afii10048',225=>'afii10017',226=>'afii10018',227=>'afii10040',228=>'afii10021',229=>'afii10022',230=>'afii10038',231=>'afii10020',232=>'afii10039',233=>'afii10026',234=>'afii10027',235=>'afii10028',236=>'afii10029',237=>'afii10030',238=>'afii10031',239=>'afii10032',240=>'afii10033',241=>'afii10049',242=>'afii10034',243=>'afii10035',244=>'afii10036',245=>'afii10037',246=>'afii10024',247=>'afii10019',248=>'afii10046',249=>'afii10045',250=>'afii10025',251=>'afii10042',252=>'afii10047',253=>'afii10043',254=>'afii10041',255=>'afii10044'), - -// encoding map for: koi8-u -'koi8-u' => array(0=>'.notdef',1=>'.notdef',2=>'.notdef',3=>'.notdef',4=>'.notdef',5=>'.notdef',6=>'.notdef',7=>'.notdef',8=>'.notdef',9=>'.notdef',10=>'.notdef',11=>'.notdef',12=>'.notdef',13=>'.notdef',14=>'.notdef',15=>'.notdef',16=>'.notdef',17=>'.notdef',18=>'.notdef',19=>'.notdef',20=>'.notdef',21=>'.notdef',22=>'.notdef',23=>'.notdef',24=>'.notdef',25=>'.notdef',26=>'.notdef',27=>'.notdef',28=>'.notdef',29=>'.notdef',30=>'.notdef',31=>'.notdef',32=>'space',33=>'exclam',34=>'quotedbl',35=>'numbersign',36=>'dollar',37=>'percent',38=>'ampersand',39=>'quotesingle',40=>'parenleft',41=>'parenright',42=>'asterisk',43=>'plus',44=>'comma',45=>'hyphen',46=>'period',47=>'slash',48=>'zero',49=>'one',50=>'two',51=>'three',52=>'four',53=>'five',54=>'six',55=>'seven',56=>'eight',57=>'nine',58=>'colon',59=>'semicolon',60=>'less',61=>'equal',62=>'greater',63=>'question',64=>'at',65=>'A',66=>'B',67=>'C',68=>'D',69=>'E',70=>'F',71=>'G',72=>'H',73=>'I',74=>'J',75=>'K',76=>'L',77=>'M',78=>'N',79=>'O',80=>'P',81=>'Q',82=>'R',83=>'S',84=>'T',85=>'U',86=>'V',87=>'W',88=>'X',89=>'Y',90=>'Z',91=>'bracketleft',92=>'backslash',93=>'bracketright',94=>'asciicircum',95=>'underscore',96=>'grave',97=>'a',98=>'b',99=>'c',100=>'d',101=>'e',102=>'f',103=>'g',104=>'h',105=>'i',106=>'j',107=>'k',108=>'l',109=>'m',110=>'n',111=>'o',112=>'p',113=>'q',114=>'r',115=>'s',116=>'t',117=>'u',118=>'v',119=>'w',120=>'x',121=>'y',122=>'z',123=>'braceleft',124=>'bar',125=>'braceright',126=>'asciitilde',127=>'.notdef',128=>'SF100000',129=>'SF110000',130=>'SF010000',131=>'SF030000',132=>'SF020000',133=>'SF040000',134=>'SF080000',135=>'SF090000',136=>'SF060000',137=>'SF070000',138=>'SF050000',139=>'upblock',140=>'dnblock',141=>'block',142=>'lfblock',143=>'rtblock',144=>'ltshade',145=>'shade',146=>'dkshade',147=>'integraltp',148=>'filledbox',149=>'bullet',150=>'radical',151=>'approxequal',152=>'lessequal',153=>'greaterequal',154=>'space',155=>'integralbt',156=>'degree',157=>'twosuperior',158=>'periodcentered',159=>'divide',160=>'SF430000',161=>'SF240000',162=>'SF510000',163=>'afii10071',164=>'afii10101',165=>'SF390000',166=>'afii10103',167=>'afii10104',168=>'SF250000',169=>'SF500000',170=>'SF490000',171=>'SF380000',172=>'SF280000',173=>'afii10098',174=>'SF260000',175=>'SF360000',176=>'SF370000',177=>'SF420000',178=>'SF190000',179=>'afii10023',180=>'afii10053',181=>'SF230000',182=>'afii10055',183=>'afii10056',184=>'SF410000',185=>'SF450000',186=>'SF460000',187=>'SF400000',188=>'SF540000',189=>'afii10050',190=>'SF440000',191=>'copyright',192=>'afii10096',193=>'afii10065',194=>'afii10066',195=>'afii10088',196=>'afii10069',197=>'afii10070',198=>'afii10086',199=>'afii10068',200=>'afii10087',201=>'afii10074',202=>'afii10075',203=>'afii10076',204=>'afii10077',205=>'afii10078',206=>'afii10079',207=>'afii10080',208=>'afii10081',209=>'afii10097',210=>'afii10082',211=>'afii10083',212=>'afii10084',213=>'afii10085',214=>'afii10072',215=>'afii10067',216=>'afii10094',217=>'afii10093',218=>'afii10073',219=>'afii10090',220=>'afii10095',221=>'afii10091',222=>'afii10089',223=>'afii10092',224=>'afii10048',225=>'afii10017',226=>'afii10018',227=>'afii10040',228=>'afii10021',229=>'afii10022',230=>'afii10038',231=>'afii10020',232=>'afii10039',233=>'afii10026',234=>'afii10027',235=>'afii10028',236=>'afii10029',237=>'afii10030',238=>'afii10031',239=>'afii10032',240=>'afii10033',241=>'afii10049',242=>'afii10034',243=>'afii10035',244=>'afii10036',245=>'afii10037',246=>'afii10024',247=>'afii10019',248=>'afii10046',249=>'afii10045',250=>'afii10025',251=>'afii10042',252=>'afii10047',253=>'afii10043',254=>'afii10041',255=>'afii10044'), - -// encoding map for: symbol -'symbol' => array(0=>'.notdef',1=>'.notdef',2=>'.notdef',3=>'.notdef',4=>'.notdef',5=>'.notdef',6=>'.notdef',7=>'.notdef',8=>'.notdef',9=>'.notdef',10=>'.notdef',11=>'.notdef',12=>'.notdef',13=>'.notdef',14=>'.notdef',15=>'.notdef',16=>'.notdef',17=>'.notdef',18=>'.notdef',19=>'.notdef',20=>'.notdef',21=>'.notdef',22=>'.notdef',23=>'.notdef',24=>'.notdef',25=>'.notdef',26=>'.notdef',27=>'.notdef',28=>'.notdef',29=>'.notdef',30=>'.notdef',31=>'.notdef',32=>'space',33=>'exclam',34=>'universal',35=>'numbersign',36=>'existential',37=>'percent',38=>'ampersand',39=>'suchthat',40=>'parenleft',41=>'parenright',42=>'asteriskmath',43=>'plus',44=>'comma',45=>'minus',46=>'period',47=>'slash',48=>'zero',49=>'one',50=>'two',51=>'three',52=>'four',53=>'five',54=>'six',55=>'seven',56=>'eight',57=>'nine',58=>'colon',59=>'semicolon',60=>'less',61=>'equal',62=>'greater',63=>'question',64=>'congruent',65=>'Alpha',66=>'Beta',67=>'Chi',68=>'Delta',69=>'Epsilon',70=>'Phi',71=>'Gamma',72=>'Eta',73=>'Iota',74=>'theta1',75=>'Kappa',76=>'Lambda',77=>'Mu',78=>'Nu',79=>'Omicron',80=>'Pi',81=>'Theta',82=>'Rho',83=>'Sigma',84=>'Tau',85=>'Upsilon',86=>'sigma1',87=>'Omega',88=>'Xi',89=>'Psi',90=>'Zeta',91=>'bracketleft',92=>'therefore',93=>'bracketright',94=>'perpendicular',95=>'underscore',96=>'radicalex',97=>'alpha',98=>'beta',99=>'chi',100=>'delta',101=>'epsilon',102=>'phi',103=>'gamma',104=>'eta',105=>'iota',106=>'phi1',107=>'kappa',108=>'lambda',109=>'mu',110=>'nu',111=>'omicron',112=>'pi',113=>'theta',114=>'rho',115=>'sigma',116=>'tau',117=>'upsilon',118=>'omega1',119=>'omega',120=>'xi',121=>'psi',122=>'zeta',123=>'braceleft',124=>'bar',125=>'braceright',126=>'similar',127=>'.notdef',128=>'.notdef',129=>'.notdef',130=>'.notdef',131=>'.notdef',132=>'.notdef',133=>'.notdef',134=>'.notdef',135=>'.notdef',136=>'.notdef',137=>'.notdef',138=>'.notdef',139=>'.notdef',140=>'.notdef',141=>'.notdef',142=>'.notdef',143=>'.notdef',144=>'.notdef',145=>'.notdef',146=>'.notdef',147=>'.notdef',148=>'.notdef',149=>'.notdef',150=>'.notdef',151=>'.notdef',152=>'.notdef',153=>'.notdef',154=>'.notdef',155=>'.notdef',156=>'.notdef',157=>'.notdef',158=>'.notdef',159=>'.notdef',160=>'Euro',161=>'Upsilon1',162=>'minute',163=>'lessequal',164=>'fraction',165=>'infinity',166=>'florin',167=>'club',168=>'diamond',169=>'heart',170=>'spade',171=>'arrowboth',172=>'arrowleft',173=>'arrowup',174=>'arrowright',175=>'arrowdown',176=>'degree',177=>'plusminus',178=>'second',179=>'greaterequal',180=>'multiply',181=>'proportional',182=>'partialdiff',183=>'bullet',184=>'divide',185=>'notequal',186=>'equivalence',187=>'approxequal',188=>'ellipsis',189=>'arrowvertex',190=>'arrowhorizex',191=>'carriagereturn',192=>'aleph',193=>'Ifraktur',194=>'Rfraktur',195=>'weierstrass',196=>'circlemultiply',197=>'circleplus',198=>'emptyset',199=>'intersection',200=>'union',201=>'propersuperset',202=>'reflexsuperset',203=>'notsubset',204=>'propersubset',205=>'reflexsubset',206=>'element',207=>'notelement',208=>'angle',209=>'gradient',210=>'registerserif',211=>'copyrightserif',212=>'trademarkserif',213=>'product',214=>'radical',215=>'dotmath',216=>'logicalnot',217=>'logicaland',218=>'logicalor',219=>'arrowdblboth',220=>'arrowdblleft',221=>'arrowdblup',222=>'arrowdblright',223=>'arrowdbldown',224=>'lozenge',225=>'angleleft',226=>'registersans',227=>'copyrightsans',228=>'trademarksans',229=>'summation',230=>'parenlefttp',231=>'parenleftex',232=>'parenleftbt',233=>'bracketlefttp',234=>'bracketleftex',235=>'bracketleftbt',236=>'bracelefttp',237=>'braceleftmid',238=>'braceleftbt',239=>'braceex',240=>'.notdef',241=>'angleright',242=>'integral',243=>'integraltp',244=>'integralex',245=>'integralbt',246=>'parenrighttp',247=>'parenrightex',248=>'parenrightbt',249=>'bracketrighttp',250=>'bracketrightex',251=>'bracketrightbt',252=>'bracerighttp',253=>'bracerightmid',254=>'bracerightbt',255=>'.notdef',1226=>'registered',1227=>'copyright',1228=>'trademark') - -); // end of encoding maps - -/** - * ToUnicode map for Identity-H stream - * @public static - */ -public static $uni_identity_h = "/CIDInit /ProcSet findresource begin\n12 dict begin\nbegincmap\n/CIDSystemInfo << /Registry (Adobe) /Ordering (UCS) /Supplement 0 >> def\n/CMapName /Adobe-Identity-UCS def\n/CMapType 2 def\n/WMode 0 def\n1 begincodespacerange\n<0000> <FFFF>\nendcodespacerange\n100 beginbfrange\n<0000> <00ff> <0000>\n<0100> <01ff> <0100>\n<0200> <02ff> <0200>\n<0300> <03ff> <0300>\n<0400> <04ff> <0400>\n<0500> <05ff> <0500>\n<0600> <06ff> <0600>\n<0700> <07ff> <0700>\n<0800> <08ff> <0800>\n<0900> <09ff> <0900>\n<0a00> <0aff> <0a00>\n<0b00> <0bff> <0b00>\n<0c00> <0cff> <0c00>\n<0d00> <0dff> <0d00>\n<0e00> <0eff> <0e00>\n<0f00> <0fff> <0f00>\n<1000> <10ff> <1000>\n<1100> <11ff> <1100>\n<1200> <12ff> <1200>\n<1300> <13ff> <1300>\n<1400> <14ff> <1400>\n<1500> <15ff> <1500>\n<1600> <16ff> <1600>\n<1700> <17ff> <1700>\n<1800> <18ff> <1800>\n<1900> <19ff> <1900>\n<1a00> <1aff> <1a00>\n<1b00> <1bff> <1b00>\n<1c00> <1cff> <1c00>\n<1d00> <1dff> <1d00>\n<1e00> <1eff> <1e00>\n<1f00> <1fff> <1f00>\n<2000> <20ff> <2000>\n<2100> <21ff> <2100>\n<2200> <22ff> <2200>\n<2300> <23ff> <2300>\n<2400> <24ff> <2400>\n<2500> <25ff> <2500>\n<2600> <26ff> <2600>\n<2700> <27ff> <2700>\n<2800> <28ff> <2800>\n<2900> <29ff> <2900>\n<2a00> <2aff> <2a00>\n<2b00> <2bff> <2b00>\n<2c00> <2cff> <2c00>\n<2d00> <2dff> <2d00>\n<2e00> <2eff> <2e00>\n<2f00> <2fff> <2f00>\n<3000> <30ff> <3000>\n<3100> <31ff> <3100>\n<3200> <32ff> <3200>\n<3300> <33ff> <3300>\n<3400> <34ff> <3400>\n<3500> <35ff> <3500>\n<3600> <36ff> <3600>\n<3700> <37ff> <3700>\n<3800> <38ff> <3800>\n<3900> <39ff> <3900>\n<3a00> <3aff> <3a00>\n<3b00> <3bff> <3b00>\n<3c00> <3cff> <3c00>\n<3d00> <3dff> <3d00>\n<3e00> <3eff> <3e00>\n<3f00> <3fff> <3f00>\n<4000> <40ff> <4000>\n<4100> <41ff> <4100>\n<4200> <42ff> <4200>\n<4300> <43ff> <4300>\n<4400> <44ff> <4400>\n<4500> <45ff> <4500>\n<4600> <46ff> <4600>\n<4700> <47ff> <4700>\n<4800> <48ff> <4800>\n<4900> <49ff> <4900>\n<4a00> <4aff> <4a00>\n<4b00> <4bff> <4b00>\n<4c00> <4cff> <4c00>\n<4d00> <4dff> <4d00>\n<4e00> <4eff> <4e00>\n<4f00> <4fff> <4f00>\n<5000> <50ff> <5000>\n<5100> <51ff> <5100>\n<5200> <52ff> <5200>\n<5300> <53ff> <5300>\n<5400> <54ff> <5400>\n<5500> <55ff> <5500>\n<5600> <56ff> <5600>\n<5700> <57ff> <5700>\n<5800> <58ff> <5800>\n<5900> <59ff> <5900>\n<5a00> <5aff> <5a00>\n<5b00> <5bff> <5b00>\n<5c00> <5cff> <5c00>\n<5d00> <5dff> <5d00>\n<5e00> <5eff> <5e00>\n<5f00> <5fff> <5f00>\n<6000> <60ff> <6000>\n<6100> <61ff> <6100>\n<6200> <62ff> <6200>\n<6300> <63ff> <6300>\nendbfrange\n100 beginbfrange\n<6400> <64ff> <6400>\n<6500> <65ff> <6500>\n<6600> <66ff> <6600>\n<6700> <67ff> <6700>\n<6800> <68ff> <6800>\n<6900> <69ff> <6900>\n<6a00> <6aff> <6a00>\n<6b00> <6bff> <6b00>\n<6c00> <6cff> <6c00>\n<6d00> <6dff> <6d00>\n<6e00> <6eff> <6e00>\n<6f00> <6fff> <6f00>\n<7000> <70ff> <7000>\n<7100> <71ff> <7100>\n<7200> <72ff> <7200>\n<7300> <73ff> <7300>\n<7400> <74ff> <7400>\n<7500> <75ff> <7500>\n<7600> <76ff> <7600>\n<7700> <77ff> <7700>\n<7800> <78ff> <7800>\n<7900> <79ff> <7900>\n<7a00> <7aff> <7a00>\n<7b00> <7bff> <7b00>\n<7c00> <7cff> <7c00>\n<7d00> <7dff> <7d00>\n<7e00> <7eff> <7e00>\n<7f00> <7fff> <7f00>\n<8000> <80ff> <8000>\n<8100> <81ff> <8100>\n<8200> <82ff> <8200>\n<8300> <83ff> <8300>\n<8400> <84ff> <8400>\n<8500> <85ff> <8500>\n<8600> <86ff> <8600>\n<8700> <87ff> <8700>\n<8800> <88ff> <8800>\n<8900> <89ff> <8900>\n<8a00> <8aff> <8a00>\n<8b00> <8bff> <8b00>\n<8c00> <8cff> <8c00>\n<8d00> <8dff> <8d00>\n<8e00> <8eff> <8e00>\n<8f00> <8fff> <8f00>\n<9000> <90ff> <9000>\n<9100> <91ff> <9100>\n<9200> <92ff> <9200>\n<9300> <93ff> <9300>\n<9400> <94ff> <9400>\n<9500> <95ff> <9500>\n<9600> <96ff> <9600>\n<9700> <97ff> <9700>\n<9800> <98ff> <9800>\n<9900> <99ff> <9900>\n<9a00> <9aff> <9a00>\n<9b00> <9bff> <9b00>\n<9c00> <9cff> <9c00>\n<9d00> <9dff> <9d00>\n<9e00> <9eff> <9e00>\n<9f00> <9fff> <9f00>\n<a000> <a0ff> <a000>\n<a100> <a1ff> <a100>\n<a200> <a2ff> <a200>\n<a300> <a3ff> <a300>\n<a400> <a4ff> <a400>\n<a500> <a5ff> <a500>\n<a600> <a6ff> <a600>\n<a700> <a7ff> <a700>\n<a800> <a8ff> <a800>\n<a900> <a9ff> <a900>\n<aa00> <aaff> <aa00>\n<ab00> <abff> <ab00>\n<ac00> <acff> <ac00>\n<ad00> <adff> <ad00>\n<ae00> <aeff> <ae00>\n<af00> <afff> <af00>\n<b000> <b0ff> <b000>\n<b100> <b1ff> <b100>\n<b200> <b2ff> <b200>\n<b300> <b3ff> <b300>\n<b400> <b4ff> <b400>\n<b500> <b5ff> <b500>\n<b600> <b6ff> <b600>\n<b700> <b7ff> <b700>\n<b800> <b8ff> <b800>\n<b900> <b9ff> <b900>\n<ba00> <baff> <ba00>\n<bb00> <bbff> <bb00>\n<bc00> <bcff> <bc00>\n<bd00> <bdff> <bd00>\n<be00> <beff> <be00>\n<bf00> <bfff> <bf00>\n<c000> <c0ff> <c000>\n<c100> <c1ff> <c100>\n<c200> <c2ff> <c200>\n<c300> <c3ff> <c300>\n<c400> <c4ff> <c400>\n<c500> <c5ff> <c500>\n<c600> <c6ff> <c600>\n<c700> <c7ff> <c700>\nendbfrange\n56 beginbfrange\n<c800> <c8ff> <c800>\n<c900> <c9ff> <c900>\n<ca00> <caff> <ca00>\n<cb00> <cbff> <cb00>\n<cc00> <ccff> <cc00>\n<cd00> <cdff> <cd00>\n<ce00> <ceff> <ce00>\n<cf00> <cfff> <cf00>\n<d000> <d0ff> <d000>\n<d100> <d1ff> <d100>\n<d200> <d2ff> <d200>\n<d300> <d3ff> <d300>\n<d400> <d4ff> <d400>\n<d500> <d5ff> <d500>\n<d600> <d6ff> <d600>\n<d700> <d7ff> <d700>\n<d800> <d8ff> <d800>\n<d900> <d9ff> <d900>\n<da00> <daff> <da00>\n<db00> <dbff> <db00>\n<dc00> <dcff> <dc00>\n<dd00> <ddff> <dd00>\n<de00> <deff> <de00>\n<df00> <dfff> <df00>\n<e000> <e0ff> <e000>\n<e100> <e1ff> <e100>\n<e200> <e2ff> <e200>\n<e300> <e3ff> <e300>\n<e400> <e4ff> <e400>\n<e500> <e5ff> <e500>\n<e600> <e6ff> <e600>\n<e700> <e7ff> <e700>\n<e800> <e8ff> <e800>\n<e900> <e9ff> <e900>\n<ea00> <eaff> <ea00>\n<eb00> <ebff> <eb00>\n<ec00> <ecff> <ec00>\n<ed00> <edff> <ed00>\n<ee00> <eeff> <ee00>\n<ef00> <efff> <ef00>\n<f000> <f0ff> <f000>\n<f100> <f1ff> <f100>\n<f200> <f2ff> <f200>\n<f300> <f3ff> <f300>\n<f400> <f4ff> <f400>\n<f500> <f5ff> <f500>\n<f600> <f6ff> <f600>\n<f700> <f7ff> <f700>\n<f800> <f8ff> <f800>\n<f900> <f9ff> <f900>\n<fa00> <faff> <fa00>\n<fb00> <fbff> <fb00>\n<fc00> <fcff> <fc00>\n<fd00> <fdff> <fd00>\n<fe00> <feff> <fe00>\n<ff00> <ffff> <ff00>\nendbfrange\nendcmap\nCMapName currentdict /CMap defineresource pop\nend\nend"; - -} // END OF TCPDF_FONT_DATA CLASS - -//============================================================+ -// END OF FILE -//============================================================+ diff --git a/lib/combodo/tcpdf/include/tcpdf_fonts.php b/lib/combodo/tcpdf/include/tcpdf_fonts.php deleted file mode 100644 index c692ef87d..000000000 --- a/lib/combodo/tcpdf/include/tcpdf_fonts.php +++ /dev/null @@ -1,2656 +0,0 @@ -<?php -//============================================================+ -// File name : tcpdf_fonts.php -// Version : 1.1.0 -// Begin : 2008-01-01 -// Last Update : 2014-12-10 -// Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com -// License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html) -// ------------------------------------------------------------------- -// Copyright (C) 2008-2014 Nicola Asuni - Tecnick.com LTD -// -// This file is part of TCPDF software library. -// -// TCPDF is free software: you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// TCPDF is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with TCPDF. If not, see <http://www.gnu.org/licenses/>. -// -// See LICENSE.TXT file for more information. -// ------------------------------------------------------------------- -// -// Description :Font methods for TCPDF library. -// -//============================================================+ - -/** - * @file - * Unicode data and font methods for TCPDF library. - * @author Nicola Asuni - * @package com.tecnick.tcpdf - */ - -/** - * @class TCPDF_FONTS - * Font methods for TCPDF library. - * @package com.tecnick.tcpdf - * @version 1.1.0 - * @author Nicola Asuni - info@tecnick.com - */ -class TCPDF_FONTS { - - /** - * Static cache used for speed up uniord performances - * @protected - */ - protected static $cache_uniord = array(); - - /** - * Convert and add the selected TrueType or Type1 font to the fonts folder (that must be writeable). - * @param string $fontfile Font file (full path). - * @param string $fonttype Font type. Leave empty for autodetect mode. Valid values are: TrueTypeUnicode, TrueType, Type1, CID0JP = CID-0 Japanese, CID0KR = CID-0 Korean, CID0CS = CID-0 Chinese Simplified, CID0CT = CID-0 Chinese Traditional. - * @param string $enc Name of the encoding table to use. Leave empty for default mode. Omit this parameter for TrueType Unicode and symbolic fonts like Symbol or ZapfDingBats. - * @param int $flags Unsigned 32-bit integer containing flags specifying various characteristics of the font (PDF32000:2008 - 9.8.2 Font Descriptor Flags): +1 for fixed font; +4 for symbol or +32 for non-symbol; +64 for italic. Fixed and Italic mode are generally autodetected so you have to set it to 32 = non-symbolic font (default) or 4 = symbolic font. - * @param string $outpath Output path for generated font files (must be writeable by the web server). Leave empty for default font folder. - * @param int $platid Platform ID for CMAP table to extract (when building a Unicode font for Windows this value should be 3, for Macintosh should be 1). - * @param int $encid Encoding ID for CMAP table to extract (when building a Unicode font for Windows this value should be 1, for Macintosh should be 0). When Platform ID is 3, legal values for Encoding ID are: 0=Symbol, 1=Unicode, 2=ShiftJIS, 3=PRC, 4=Big5, 5=Wansung, 6=Johab, 7=Reserved, 8=Reserved, 9=Reserved, 10=UCS-4. - * @param boolean $addcbbox If true includes the character bounding box information on the php font file. - * @param boolean $link If true link to system font instead of copying the font data (not transportable) - Note: do not work with Type1 fonts. - * @return string|false TCPDF font name or boolean false in case of error. - * @author Nicola Asuni - * @since 5.9.123 (2010-09-30) - * @public static - */ - public static function addTTFfont($fontfile, $fonttype='', $enc='', $flags=32, $outpath='', $platid=3, $encid=1, $addcbbox=false, $link=false) { - if (!TCPDF_STATIC::file_exists($fontfile)) { - // Could not find file - return false; - } - // font metrics - $fmetric = array(); - // build new font name for TCPDF compatibility - $font_path_parts = pathinfo($fontfile); - if (!isset($font_path_parts['filename'])) { - $font_path_parts['filename'] = substr($font_path_parts['basename'], 0, -(strlen($font_path_parts['extension']) + 1)); - } - $font_name = strtolower($font_path_parts['filename']); - $font_name = preg_replace('/[^a-z0-9_]/', '', $font_name); - $search = array('bold', 'oblique', 'italic', 'regular'); - $replace = array('b', 'i', 'i', ''); - $font_name = str_replace($search, $replace, $font_name); - if (empty($font_name)) { - // set generic name - $font_name = 'tcpdffont'; - } - // set output path - if (empty($outpath)) { - $outpath = self::_getfontpath(); - } - // check if this font already exist - if (@TCPDF_STATIC::file_exists($outpath.$font_name.'.php')) { - // this font already exist (delete it from fonts folder to rebuild it) - return $font_name; - } - $fmetric['file'] = $font_name; - $fmetric['ctg'] = $font_name.'.ctg.z'; - // get font data - $font = file_get_contents($fontfile); - $fmetric['originalsize'] = strlen($font); - // autodetect font type - if (empty($fonttype)) { - if (TCPDF_STATIC::_getULONG($font, 0) == 0x10000) { - // True Type (Unicode or not) - $fonttype = 'TrueTypeUnicode'; - } elseif (substr($font, 0, 4) == 'OTTO') { - // Open Type (Unicode or not) - //Unsupported font format: OpenType with CFF data - return false; - } else { - // Type 1 - $fonttype = 'Type1'; - } - } - // set font type - switch ($fonttype) { - case 'CID0CT': - case 'CID0CS': - case 'CID0KR': - case 'CID0JP': { - $fmetric['type'] = 'cidfont0'; - break; - } - case 'Type1': { - $fmetric['type'] = 'Type1'; - if (empty($enc) AND (($flags & 4) == 0)) { - $enc = 'cp1252'; - } - break; - } - case 'TrueType': { - $fmetric['type'] = 'TrueType'; - break; - } - case 'TrueTypeUnicode': - default: { - $fmetric['type'] = 'TrueTypeUnicode'; - break; - } - } - // set encoding maps (if any) - $fmetric['enc'] = preg_replace('/[^A-Za-z0-9_\-]/', '', $enc); - $fmetric['diff'] = ''; - if (($fmetric['type'] == 'TrueType') OR ($fmetric['type'] == 'Type1')) { - if (!empty($enc) AND ($enc != 'cp1252') AND isset(TCPDF_FONT_DATA::$encmap[$enc])) { - // build differences from reference encoding - $enc_ref = TCPDF_FONT_DATA::$encmap['cp1252']; - $enc_target = TCPDF_FONT_DATA::$encmap[$enc]; - $last = 0; - for ($i = 32; $i <= 255; ++$i) { - if ($enc_target[$i] != $enc_ref[$i]) { - if ($i != ($last + 1)) { - $fmetric['diff'] .= $i.' '; - } - $last = $i; - $fmetric['diff'] .= '/'.$enc_target[$i].' '; - } - } - } - } - // parse the font by type - if ($fmetric['type'] == 'Type1') { - // ---------- TYPE 1 ---------- - // read first segment - $a = unpack('Cmarker/Ctype/Vsize', substr($font, 0, 6)); - if ($a['marker'] != 128) { - // Font file is not a valid binary Type1 - return false; - } - $fmetric['size1'] = $a['size']; - $data = substr($font, 6, $fmetric['size1']); - // read second segment - $a = unpack('Cmarker/Ctype/Vsize', substr($font, (6 + $fmetric['size1']), 6)); - if ($a['marker'] != 128) { - // Font file is not a valid binary Type1 - return false; - } - $fmetric['size2'] = $a['size']; - $encrypted = substr($font, (12 + $fmetric['size1']), $fmetric['size2']); - $data .= $encrypted; - // store compressed font - $fmetric['file'] .= '.z'; - $fp = TCPDF_STATIC::fopenLocal($outpath.$fmetric['file'], 'wb'); - fwrite($fp, gzcompress($data)); - fclose($fp); - // get font info - $fmetric['Flags'] = $flags; - preg_match ('#/FullName[\s]*\(([^\)]*)#', $font, $matches); - $fmetric['name'] = preg_replace('/[^a-zA-Z0-9_\-]/', '', $matches[1]); - preg_match('#/FontBBox[\s]*{([^}]*)#', $font, $matches); - $fmetric['bbox'] = trim($matches[1]); - $bv = explode(' ', $fmetric['bbox']); - $fmetric['Ascent'] = intval($bv[3]); - $fmetric['Descent'] = intval($bv[1]); - preg_match('#/ItalicAngle[\s]*([0-9\+\-]*)#', $font, $matches); - $fmetric['italicAngle'] = intval($matches[1]); - if ($fmetric['italicAngle'] != 0) { - $fmetric['Flags'] |= 64; - } - preg_match('#/UnderlinePosition[\s]*([0-9\+\-]*)#', $font, $matches); - $fmetric['underlinePosition'] = intval($matches[1]); - preg_match('#/UnderlineThickness[\s]*([0-9\+\-]*)#', $font, $matches); - $fmetric['underlineThickness'] = intval($matches[1]); - preg_match('#/isFixedPitch[\s]*([^\s]*)#', $font, $matches); - if ($matches[1] == 'true') { - $fmetric['Flags'] |= 1; - } - // get internal map - $imap = array(); - if (preg_match_all('#dup[\s]([0-9]+)[\s]*/([^\s]*)[\s]put#sU', $font, $fmap, PREG_SET_ORDER) > 0) { - foreach ($fmap as $v) { - $imap[$v[2]] = $v[1]; - } - } - // decrypt eexec encrypted part - $r = 55665; // eexec encryption constant - $c1 = 52845; - $c2 = 22719; - $elen = strlen($encrypted); - $eplain = ''; - for ($i = 0; $i < $elen; ++$i) { - $chr = ord($encrypted[$i]); - $eplain .= chr($chr ^ ($r >> 8)); - $r = ((($chr + $r) * $c1 + $c2) % 65536); - } - if (preg_match('#/ForceBold[\s]*([^\s]*)#', $eplain, $matches) > 0) { - if ($matches[1] == 'true') { - $fmetric['Flags'] |= 0x40000; - } - } - if (preg_match('#/StdVW[\s]*\[([^\]]*)#', $eplain, $matches) > 0) { - $fmetric['StemV'] = intval($matches[1]); - } else { - $fmetric['StemV'] = 70; - } - if (preg_match('#/StdHW[\s]*\[([^\]]*)#', $eplain, $matches) > 0) { - $fmetric['StemH'] = intval($matches[1]); - } else { - $fmetric['StemH'] = 30; - } - if (preg_match('#/BlueValues[\s]*\[([^\]]*)#', $eplain, $matches) > 0) { - $bv = explode(' ', $matches[1]); - if (count($bv) >= 6) { - $v1 = intval($bv[2]); - $v2 = intval($bv[4]); - if ($v1 <= $v2) { - $fmetric['XHeight'] = $v1; - $fmetric['CapHeight'] = $v2; - } else { - $fmetric['XHeight'] = $v2; - $fmetric['CapHeight'] = $v1; - } - } else { - $fmetric['XHeight'] = 450; - $fmetric['CapHeight'] = 700; - } - } else { - $fmetric['XHeight'] = 450; - $fmetric['CapHeight'] = 700; - } - // get the number of random bytes at the beginning of charstrings - if (preg_match('#/lenIV[\s]*([0-9]*)#', $eplain, $matches) > 0) { - $lenIV = intval($matches[1]); - } else { - $lenIV = 4; - } - $fmetric['Leading'] = 0; - // get charstring data - $eplain = substr($eplain, (strpos($eplain, '/CharStrings') + 1)); - preg_match_all('#/([A-Za-z0-9\.]*)[\s][0-9]+[\s]RD[\s](.*)[\s]ND#sU', $eplain, $matches, PREG_SET_ORDER); - if (!empty($enc) AND isset(TCPDF_FONT_DATA::$encmap[$enc])) { - $enc_map = TCPDF_FONT_DATA::$encmap[$enc]; - } else { - $enc_map = false; - } - $fmetric['cw'] = ''; - $fmetric['MaxWidth'] = 0; - $cwidths = array(); - foreach ($matches as $k => $v) { - $cid = 0; - if (isset($imap[$v[1]])) { - $cid = $imap[$v[1]]; - } elseif ($enc_map !== false) { - $cid = array_search($v[1], $enc_map); - if ($cid === false) { - $cid = 0; - } elseif ($cid > 1000) { - $cid -= 1000; - } - } - // decrypt charstring encrypted part - $r = 4330; // charstring encryption constant - $c1 = 52845; - $c2 = 22719; - $cd = $v[2]; - $clen = strlen($cd); - $ccom = array(); - for ($i = 0; $i < $clen; ++$i) { - $chr = ord($cd[$i]); - $ccom[] = ($chr ^ ($r >> 8)); - $r = ((($chr + $r) * $c1 + $c2) % 65536); - } - // decode numbers - $cdec = array(); - $ck = 0; - $i = $lenIV; - while ($i < $clen) { - if ($ccom[$i] < 32) { - $cdec[$ck] = $ccom[$i]; - if (($ck > 0) AND ($cdec[$ck] == 13)) { - // hsbw command: update width - $cwidths[$cid] = $cdec[($ck - 1)]; - } - ++$i; - } elseif (($ccom[$i] >= 32) AND ($ccom[$i] <= 246)) { - $cdec[$ck] = ($ccom[$i] - 139); - ++$i; - } elseif (($ccom[$i] >= 247) AND ($ccom[$i] <= 250)) { - $cdec[$ck] = ((($ccom[$i] - 247) * 256) + $ccom[($i + 1)] + 108); - $i += 2; - } elseif (($ccom[$i] >= 251) AND ($ccom[$i] <= 254)) { - $cdec[$ck] = ((-($ccom[$i] - 251) * 256) - $ccom[($i + 1)] - 108); - $i += 2; - } elseif ($ccom[$i] == 255) { - $sval = chr($ccom[($i + 1)]).chr($ccom[($i + 2)]).chr($ccom[($i + 3)]).chr($ccom[($i + 4)]); - $vsval = unpack('li', $sval); - $cdec[$ck] = $vsval['i']; - $i += 5; - } - ++$ck; - } - } // end for each matches - $fmetric['MissingWidth'] = $cwidths[0]; - $fmetric['MaxWidth'] = $fmetric['MissingWidth']; - $fmetric['AvgWidth'] = 0; - // set chars widths - for ($cid = 0; $cid <= 255; ++$cid) { - if (isset($cwidths[$cid])) { - if ($cwidths[$cid] > $fmetric['MaxWidth']) { - $fmetric['MaxWidth'] = $cwidths[$cid]; - } - $fmetric['AvgWidth'] += $cwidths[$cid]; - $fmetric['cw'] .= ','.$cid.'=>'.$cwidths[$cid]; - } else { - $fmetric['cw'] .= ','.$cid.'=>'.$fmetric['MissingWidth']; - } - } - $fmetric['AvgWidth'] = round($fmetric['AvgWidth'] / count($cwidths)); - } else { - // ---------- TRUE TYPE ---------- - $offset = 0; // offset position of the font data - if (TCPDF_STATIC::_getULONG($font, $offset) != 0x10000) { - // sfnt version must be 0x00010000 for TrueType version 1.0. - return false; - } - if ($fmetric['type'] != 'cidfont0') { - if ($link) { - // creates a symbolic link to the existing font - symlink($fontfile, $outpath.$fmetric['file']); - } else { - // store compressed font - $fmetric['file'] .= '.z'; - $fp = TCPDF_STATIC::fopenLocal($outpath.$fmetric['file'], 'wb'); - fwrite($fp, gzcompress($font)); - fclose($fp); - } - } - $offset += 4; - // get number of tables - $numTables = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - // skip searchRange, entrySelector and rangeShift - $offset += 6; - // tables array - $table = array(); - // ---------- get tables ---------- - for ($i = 0; $i < $numTables; ++$i) { - // get table info - $tag = substr($font, $offset, 4); - $offset += 4; - $table[$tag] = array(); - $table[$tag]['checkSum'] = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - $table[$tag]['offset'] = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - $table[$tag]['length'] = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - } - // check magicNumber - $offset = $table['head']['offset'] + 12; - if (TCPDF_STATIC::_getULONG($font, $offset) != 0x5F0F3CF5) { - // magicNumber must be 0x5F0F3CF5 - return false; - } - $offset += 4; - $offset += 2; // skip flags - // get FUnits - $fmetric['unitsPerEm'] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - // units ratio constant - $urk = (1000 / $fmetric['unitsPerEm']); - $offset += 16; // skip created, modified - $xMin = round(TCPDF_STATIC::_getFWORD($font, $offset) * $urk); - $offset += 2; - $yMin = round(TCPDF_STATIC::_getFWORD($font, $offset) * $urk); - $offset += 2; - $xMax = round(TCPDF_STATIC::_getFWORD($font, $offset) * $urk); - $offset += 2; - $yMax = round(TCPDF_STATIC::_getFWORD($font, $offset) * $urk); - $offset += 2; - $fmetric['bbox'] = ''.$xMin.' '.$yMin.' '.$xMax.' '.$yMax.''; - $macStyle = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - // PDF font flags - $fmetric['Flags'] = $flags; - if (($macStyle & 2) == 2) { - // italic flag - $fmetric['Flags'] |= 64; - } - // get offset mode (indexToLocFormat : 0 = short, 1 = long) - $offset = $table['head']['offset'] + 50; - $short_offset = (TCPDF_STATIC::_getSHORT($font, $offset) == 0); - $offset += 2; - // get the offsets to the locations of the glyphs in the font, relative to the beginning of the glyphData table - $indexToLoc = array(); - $offset = $table['loca']['offset']; - if ($short_offset) { - // short version - $tot_num_glyphs = floor($table['loca']['length'] / 2); // numGlyphs + 1 - for ($i = 0; $i < $tot_num_glyphs; ++$i) { - $indexToLoc[$i] = TCPDF_STATIC::_getUSHORT($font, $offset) * 2; - if (isset($indexToLoc[($i - 1)]) && ($indexToLoc[$i] == $indexToLoc[($i - 1)])) { - // the last glyph didn't have an outline - unset($indexToLoc[($i - 1)]); - } - $offset += 2; - } - } else { - // long version - $tot_num_glyphs = floor($table['loca']['length'] / 4); // numGlyphs + 1 - for ($i = 0; $i < $tot_num_glyphs; ++$i) { - $indexToLoc[$i] = TCPDF_STATIC::_getULONG($font, $offset); - if (isset($indexToLoc[($i - 1)]) && ($indexToLoc[$i] == $indexToLoc[($i - 1)])) { - // the last glyph didn't have an outline - unset($indexToLoc[($i - 1)]); - } - $offset += 4; - } - } - // get glyphs indexes of chars from cmap table - $offset = $table['cmap']['offset'] + 2; - $numEncodingTables = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - $encodingTables = array(); - for ($i = 0; $i < $numEncodingTables; ++$i) { - $encodingTables[$i]['platformID'] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - $encodingTables[$i]['encodingID'] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - $encodingTables[$i]['offset'] = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - } - // ---------- get os/2 metrics ---------- - $offset = $table['OS/2']['offset']; - $offset += 2; // skip version - // xAvgCharWidth - $fmetric['AvgWidth'] = round(TCPDF_STATIC::_getFWORD($font, $offset) * $urk); - $offset += 2; - // usWeightClass - $usWeightClass = round(TCPDF_STATIC::_getUFWORD($font, $offset) * $urk); - // estimate StemV and StemH (400 = usWeightClass for Normal - Regular font) - $fmetric['StemV'] = round((70 * $usWeightClass) / 400); - $fmetric['StemH'] = round((30 * $usWeightClass) / 400); - $offset += 2; - $offset += 2; // usWidthClass - $fsType = TCPDF_STATIC::_getSHORT($font, $offset); - $offset += 2; - if ($fsType == 2) { - // This Font cannot be modified, embedded or exchanged in any manner without first obtaining permission of the legal owner. - return false; - } - // ---------- get font name ---------- - $fmetric['name'] = ''; - $offset = $table['name']['offset']; - $offset += 2; // skip Format selector (=0). - // Number of NameRecords that follow n. - $numNameRecords = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - // Offset to start of string storage (from start of table). - $stringStorageOffset = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - for ($i = 0; $i < $numNameRecords; ++$i) { - $offset += 6; // skip Platform ID, Platform-specific encoding ID, Language ID. - // Name ID. - $nameID = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - if ($nameID == 6) { - // String length (in bytes). - $stringLength = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - // String offset from start of storage area (in bytes). - $stringOffset = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - $offset = ($table['name']['offset'] + $stringStorageOffset + $stringOffset); - $fmetric['name'] = substr($font, $offset, $stringLength); - $fmetric['name'] = preg_replace('/[^a-zA-Z0-9_\-]/', '', $fmetric['name']); - break; - } else { - $offset += 4; // skip String length, String offset - } - } - if (empty($fmetric['name'])) { - $fmetric['name'] = $font_name; - } - // ---------- get post data ---------- - $offset = $table['post']['offset']; - $offset += 4; // skip Format Type - $fmetric['italicAngle'] = TCPDF_STATIC::_getFIXED($font, $offset); - $offset += 4; - $fmetric['underlinePosition'] = round(TCPDF_STATIC::_getFWORD($font, $offset) * $urk); - $offset += 2; - $fmetric['underlineThickness'] = round(TCPDF_STATIC::_getFWORD($font, $offset) * $urk); - $offset += 2; - $isFixedPitch = (TCPDF_STATIC::_getULONG($font, $offset) == 0) ? false : true; - $offset += 2; - if ($isFixedPitch) { - $fmetric['Flags'] |= 1; - } - // ---------- get hhea data ---------- - $offset = $table['hhea']['offset']; - $offset += 4; // skip Table version number - // Ascender - $fmetric['Ascent'] = round(TCPDF_STATIC::_getFWORD($font, $offset) * $urk); - $offset += 2; - // Descender - $fmetric['Descent'] = round(TCPDF_STATIC::_getFWORD($font, $offset) * $urk); - $offset += 2; - // LineGap - $fmetric['Leading'] = round(TCPDF_STATIC::_getFWORD($font, $offset) * $urk); - $offset += 2; - // advanceWidthMax - $fmetric['MaxWidth'] = round(TCPDF_STATIC::_getUFWORD($font, $offset) * $urk); - $offset += 2; - $offset += 22; // skip some values - // get the number of hMetric entries in hmtx table - $numberOfHMetrics = TCPDF_STATIC::_getUSHORT($font, $offset); - // ---------- get maxp data ---------- - $offset = $table['maxp']['offset']; - $offset += 4; // skip Table version number - // get the the number of glyphs in the font. - $numGlyphs = TCPDF_STATIC::_getUSHORT($font, $offset); - // ---------- get CIDToGIDMap ---------- - $ctg = array(); - $c = 0; - foreach ($encodingTables as $enctable) { - // get only specified Platform ID and Encoding ID - if (($enctable['platformID'] == $platid) AND ($enctable['encodingID'] == $encid)) { - $offset = $table['cmap']['offset'] + $enctable['offset']; - $format = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - switch ($format) { - case 0: { // Format 0: Byte encoding table - $offset += 4; // skip length and version/language - for ($c = 0; $c < 256; ++$c) { - $g = TCPDF_STATIC::_getBYTE($font, $offset); - $ctg[$c] = $g; - ++$offset; - } - break; - } - case 2: { // Format 2: High-byte mapping through table - $offset += 4; // skip length and version/language - $numSubHeaders = 0; - for ($i = 0; $i < 256; ++$i) { - // Array that maps high bytes to subHeaders: value is subHeader index * 8. - $subHeaderKeys[$i] = (TCPDF_STATIC::_getUSHORT($font, $offset) / 8); - $offset += 2; - if ($numSubHeaders < $subHeaderKeys[$i]) { - $numSubHeaders = $subHeaderKeys[$i]; - } - } - // the number of subHeaders is equal to the max of subHeaderKeys + 1 - ++$numSubHeaders; - // read subHeader structures - $subHeaders = array(); - $numGlyphIndexArray = 0; - for ($k = 0; $k < $numSubHeaders; ++$k) { - $subHeaders[$k]['firstCode'] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - $subHeaders[$k]['entryCount'] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - $subHeaders[$k]['idDelta'] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - $subHeaders[$k]['idRangeOffset'] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - $subHeaders[$k]['idRangeOffset'] -= (2 + (($numSubHeaders - $k - 1) * 8)); - $subHeaders[$k]['idRangeOffset'] /= 2; - $numGlyphIndexArray += $subHeaders[$k]['entryCount']; - } - for ($k = 0; $k < $numGlyphIndexArray; ++$k) { - $glyphIndexArray[$k] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - } - for ($i = 0; $i < 256; ++$i) { - $k = $subHeaderKeys[$i]; - if ($k == 0) { - // one byte code - $c = $i; - $g = $glyphIndexArray[0]; - $ctg[$c] = $g; - } else { - // two bytes code - $start_byte = $subHeaders[$k]['firstCode']; - $end_byte = $start_byte + $subHeaders[$k]['entryCount']; - for ($j = $start_byte; $j < $end_byte; ++$j) { - // combine high and low bytes - $c = (($i << 8) + $j); - $idRangeOffset = ($subHeaders[$k]['idRangeOffset'] + $j - $subHeaders[$k]['firstCode']); - $g = ($glyphIndexArray[$idRangeOffset] + $subHeaders[$k]['idDelta']) % 65536; - if ($g < 0) { - $g = 0; - } - $ctg[$c] = $g; - } - } - } - break; - } - case 4: { // Format 4: Segment mapping to delta values - $length = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - $offset += 2; // skip version/language - $segCount = floor(TCPDF_STATIC::_getUSHORT($font, $offset) / 2); - $offset += 2; - $offset += 6; // skip searchRange, entrySelector, rangeShift - $endCount = array(); // array of end character codes for each segment - for ($k = 0; $k < $segCount; ++$k) { - $endCount[$k] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - } - $offset += 2; // skip reservedPad - $startCount = array(); // array of start character codes for each segment - for ($k = 0; $k < $segCount; ++$k) { - $startCount[$k] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - } - $idDelta = array(); // delta for all character codes in segment - for ($k = 0; $k < $segCount; ++$k) { - $idDelta[$k] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - } - $idRangeOffset = array(); // Offsets into glyphIdArray or 0 - for ($k = 0; $k < $segCount; ++$k) { - $idRangeOffset[$k] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - } - $gidlen = (floor($length / 2) - 8 - (4 * $segCount)); - $glyphIdArray = array(); // glyph index array - for ($k = 0; $k < $gidlen; ++$k) { - $glyphIdArray[$k] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - } - for ($k = 0; $k < $segCount - 1; ++$k) { - for ($c = $startCount[$k]; $c <= $endCount[$k]; ++$c) { - if ($idRangeOffset[$k] == 0) { - $g = ($idDelta[$k] + $c) % 65536; - } else { - $gid = (floor($idRangeOffset[$k] / 2) + ($c - $startCount[$k]) - ($segCount - $k)); - $g = ($glyphIdArray[$gid] + $idDelta[$k]) % 65536; - } - if ($g < 0) { - $g = 0; - } - $ctg[$c] = $g; - } - } - break; - } - case 6: { // Format 6: Trimmed table mapping - $offset += 4; // skip length and version/language - $firstCode = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - $entryCount = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - for ($k = 0; $k < $entryCount; ++$k) { - $c = ($k + $firstCode); - $g = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - $ctg[$c] = $g; - } - break; - } - case 8: { // Format 8: Mixed 16-bit and 32-bit coverage - $offset += 10; // skip reserved, length and version/language - for ($k = 0; $k < 8192; ++$k) { - $is32[$k] = TCPDF_STATIC::_getBYTE($font, $offset); - ++$offset; - } - $nGroups = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - for ($i = 0; $i < $nGroups; ++$i) { - $startCharCode = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - $endCharCode = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - $startGlyphID = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - for ($k = $startCharCode; $k <= $endCharCode; ++$k) { - $is32idx = floor($c / 8); - if ((isset($is32[$is32idx])) AND (($is32[$is32idx] & (1 << (7 - ($c % 8)))) == 0)) { - $c = $k; - } else { - // 32 bit format - // convert to decimal (http://www.unicode.org/faq//utf_bom.html#utf16-4) - //LEAD_OFFSET = (0xD800 - (0x10000 >> 10)) = 55232 - //SURROGATE_OFFSET = (0x10000 - (0xD800 << 10) - 0xDC00) = -56613888 - $c = ((55232 + ($k >> 10)) << 10) + (0xDC00 + ($k & 0x3FF)) -56613888; - } - $ctg[$c] = 0; - ++$startGlyphID; - } - } - break; - } - case 10: { // Format 10: Trimmed array - $offset += 10; // skip reserved, length and version/language - $startCharCode = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - $numChars = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - for ($k = 0; $k < $numChars; ++$k) { - $c = ($k + $startCharCode); - $g = TCPDF_STATIC::_getUSHORT($font, $offset); - $ctg[$c] = $g; - $offset += 2; - } - break; - } - case 12: { // Format 12: Segmented coverage - $offset += 10; // skip length and version/language - $nGroups = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - for ($k = 0; $k < $nGroups; ++$k) { - $startCharCode = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - $endCharCode = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - $startGlyphCode = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - for ($c = $startCharCode; $c <= $endCharCode; ++$c) { - $ctg[$c] = $startGlyphCode; - ++$startGlyphCode; - } - } - break; - } - case 13: { // Format 13: Many-to-one range mappings - // to be implemented ... - break; - } - case 14: { // Format 14: Unicode Variation Sequences - // to be implemented ... - break; - } - } - } - } - if (!isset($ctg[0])) { - $ctg[0] = 0; - } - // get xHeight (height of x) - $offset = ($table['glyf']['offset'] + $indexToLoc[$ctg[120]] + 4); - $yMin = TCPDF_STATIC::_getFWORD($font, $offset); - $offset += 4; - $yMax = TCPDF_STATIC::_getFWORD($font, $offset); - $offset += 2; - $fmetric['XHeight'] = round(($yMax - $yMin) * $urk); - // get CapHeight (height of H) - $offset = ($table['glyf']['offset'] + $indexToLoc[$ctg[72]] + 4); - $yMin = TCPDF_STATIC::_getFWORD($font, $offset); - $offset += 4; - $yMax = TCPDF_STATIC::_getFWORD($font, $offset); - $offset += 2; - $fmetric['CapHeight'] = round(($yMax - $yMin) * $urk); - // ceate widths array - $cw = array(); - $offset = $table['hmtx']['offset']; - for ($i = 0 ; $i < $numberOfHMetrics; ++$i) { - $cw[$i] = round(TCPDF_STATIC::_getUFWORD($font, $offset) * $urk); - $offset += 4; // skip lsb - } - if ($numberOfHMetrics < $numGlyphs) { - // fill missing widths with the last value - $cw = array_pad($cw, $numGlyphs, $cw[($numberOfHMetrics - 1)]); - } - $fmetric['MissingWidth'] = $cw[0]; - $fmetric['cw'] = ''; - $fmetric['cbbox'] = ''; - for ($cid = 0; $cid <= 65535; ++$cid) { - if (isset($ctg[$cid])) { - if (isset($cw[$ctg[$cid]])) { - $fmetric['cw'] .= ','.$cid.'=>'.$cw[$ctg[$cid]]; - } - if ($addcbbox AND isset($indexToLoc[$ctg[$cid]])) { - $offset = ($table['glyf']['offset'] + $indexToLoc[$ctg[$cid]]); - $xMin = round(TCPDF_STATIC::_getFWORD($font, $offset + 2) * $urk); - $yMin = round(TCPDF_STATIC::_getFWORD($font, $offset + 4) * $urk); - $xMax = round(TCPDF_STATIC::_getFWORD($font, $offset + 6) * $urk); - $yMax = round(TCPDF_STATIC::_getFWORD($font, $offset + 8) * $urk); - $fmetric['cbbox'] .= ','.$cid.'=>array('.$xMin.','.$yMin.','.$xMax.','.$yMax.')'; - } - } - } - } // end of true type - if (($fmetric['type'] == 'TrueTypeUnicode') AND (count($ctg) == 256)) { - $fmetric['type'] = 'TrueType'; - } - // ---------- create php font file ---------- - $pfile = '<'.'?'.'php'."\n"; - $pfile .= '// TCPDF FONT FILE DESCRIPTION'."\n"; - $pfile .= '$type=\''.$fmetric['type'].'\';'."\n"; - $pfile .= '$name=\''.$fmetric['name'].'\';'."\n"; - $pfile .= '$up='.$fmetric['underlinePosition'].';'."\n"; - $pfile .= '$ut='.$fmetric['underlineThickness'].';'."\n"; - if ($fmetric['MissingWidth'] > 0) { - $pfile .= '$dw='.$fmetric['MissingWidth'].';'."\n"; - } else { - $pfile .= '$dw='.$fmetric['AvgWidth'].';'."\n"; - } - $pfile .= '$diff=\''.$fmetric['diff'].'\';'."\n"; - if ($fmetric['type'] == 'Type1') { - // Type 1 - $pfile .= '$enc=\''.$fmetric['enc'].'\';'."\n"; - $pfile .= '$file=\''.$fmetric['file'].'\';'."\n"; - $pfile .= '$size1='.$fmetric['size1'].';'."\n"; - $pfile .= '$size2='.$fmetric['size2'].';'."\n"; - } else { - $pfile .= '$originalsize='.$fmetric['originalsize'].';'."\n"; - if ($fmetric['type'] == 'cidfont0') { - // CID-0 - switch ($fonttype) { - case 'CID0JP': { - $pfile .= '// Japanese'."\n"; - $pfile .= '$enc=\'UniJIS-UTF16-H\';'."\n"; - $pfile .= '$cidinfo=array(\'Registry\'=>\'Adobe\', \'Ordering\'=>\'Japan1\',\'Supplement\'=>5);'."\n"; - $pfile .= 'include(dirname(__FILE__).\'/uni2cid_aj16.php\');'."\n"; - break; - } - case 'CID0KR': { - $pfile .= '// Korean'."\n"; - $pfile .= '$enc=\'UniKS-UTF16-H\';'."\n"; - $pfile .= '$cidinfo=array(\'Registry\'=>\'Adobe\', \'Ordering\'=>\'Korea1\',\'Supplement\'=>0);'."\n"; - $pfile .= 'include(dirname(__FILE__).\'/uni2cid_ak12.php\');'."\n"; - break; - } - case 'CID0CS': { - $pfile .= '// Chinese Simplified'."\n"; - $pfile .= '$enc=\'UniGB-UTF16-H\';'."\n"; - $pfile .= '$cidinfo=array(\'Registry\'=>\'Adobe\', \'Ordering\'=>\'GB1\',\'Supplement\'=>2);'."\n"; - $pfile .= 'include(dirname(__FILE__).\'/uni2cid_ag15.php\');'."\n"; - break; - } - case 'CID0CT': - default: { - $pfile .= '// Chinese Traditional'."\n"; - $pfile .= '$enc=\'UniCNS-UTF16-H\';'."\n"; - $pfile .= '$cidinfo=array(\'Registry\'=>\'Adobe\', \'Ordering\'=>\'CNS1\',\'Supplement\'=>0);'."\n"; - $pfile .= 'include(dirname(__FILE__).\'/uni2cid_aj16.php\');'."\n"; - break; - } - } - } else { - // TrueType - $pfile .= '$enc=\''.$fmetric['enc'].'\';'."\n"; - $pfile .= '$file=\''.$fmetric['file'].'\';'."\n"; - $pfile .= '$ctg=\''.$fmetric['ctg'].'\';'."\n"; - // create CIDToGIDMap - $cidtogidmap = str_pad('', 131072, "\x00"); // (256 * 256 * 2) = 131072 - foreach ($ctg as $cid => $gid) { - $cidtogidmap = self::updateCIDtoGIDmap($cidtogidmap, $cid, $ctg[$cid]); - } - // store compressed CIDToGIDMap - $fp = TCPDF_STATIC::fopenLocal($outpath.$fmetric['ctg'], 'wb'); - fwrite($fp, gzcompress($cidtogidmap)); - fclose($fp); - } - } - $pfile .= '$desc=array('; - $pfile .= '\'Flags\'=>'.$fmetric['Flags'].','; - $pfile .= '\'FontBBox\'=>\'['.$fmetric['bbox'].']\','; - $pfile .= '\'ItalicAngle\'=>'.$fmetric['italicAngle'].','; - $pfile .= '\'Ascent\'=>'.$fmetric['Ascent'].','; - $pfile .= '\'Descent\'=>'.$fmetric['Descent'].','; - $pfile .= '\'Leading\'=>'.$fmetric['Leading'].','; - $pfile .= '\'CapHeight\'=>'.$fmetric['CapHeight'].','; - $pfile .= '\'XHeight\'=>'.$fmetric['XHeight'].','; - $pfile .= '\'StemV\'=>'.$fmetric['StemV'].','; - $pfile .= '\'StemH\'=>'.$fmetric['StemH'].','; - $pfile .= '\'AvgWidth\'=>'.$fmetric['AvgWidth'].','; - $pfile .= '\'MaxWidth\'=>'.$fmetric['MaxWidth'].','; - $pfile .= '\'MissingWidth\'=>'.$fmetric['MissingWidth'].''; - $pfile .= ');'."\n"; - if (!empty($fmetric['cbbox'])) { - $pfile .= '$cbbox=array('.substr($fmetric['cbbox'], 1).');'."\n"; - } - $pfile .= '$cw=array('.substr($fmetric['cw'], 1).');'."\n"; - $pfile .= '// --- EOF ---'."\n"; - // store file - $fp = TCPDF_STATIC::fopenLocal($outpath.$font_name.'.php', 'w'); - fwrite($fp, $pfile); - fclose($fp); - // return TCPDF font name - return $font_name; - } - - /** - * Returs the checksum of a TTF table. - * @param string $table table to check - * @param int $length length of table in bytes - * @return int checksum - * @author Nicola Asuni - * @since 5.2.000 (2010-06-02) - * @public static - */ - public static function _getTTFtableChecksum($table, $length) { - $sum = 0; - $tlen = ($length / 4); - $offset = 0; - for ($i = 0; $i < $tlen; ++$i) { - $v = unpack('Ni', substr($table, $offset, 4)); - $sum += $v['i']; - $offset += 4; - } - $sum = unpack('Ni', pack('N', $sum)); - return $sum['i']; - } - - /** - * Returns a subset of the TrueType font data without the unused glyphs. - * @param string $font TrueType font data. - * @param array $subsetchars Array of used characters (the glyphs to keep). - * @return string A subset of TrueType font data without the unused glyphs. - * @author Nicola Asuni - * @since 5.2.000 (2010-06-02) - * @public static - */ - public static function _getTrueTypeFontSubset($font, $subsetchars) { - ksort($subsetchars); - $offset = 0; // offset position of the font data - if (TCPDF_STATIC::_getULONG($font, $offset) != 0x10000) { - // sfnt version must be 0x00010000 for TrueType version 1.0. - return $font; - } - $c = 0; - $offset += 4; - // get number of tables - $numTables = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - // skip searchRange, entrySelector and rangeShift - $offset += 6; - // tables array - $table = array(); - // for each table - for ($i = 0; $i < $numTables; ++$i) { - // get table info - $tag = substr($font, $offset, 4); - $offset += 4; - $table[$tag] = array(); - $table[$tag]['checkSum'] = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - $table[$tag]['offset'] = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - $table[$tag]['length'] = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - } - // check magicNumber - $offset = $table['head']['offset'] + 12; - if (TCPDF_STATIC::_getULONG($font, $offset) != 0x5F0F3CF5) { - // magicNumber must be 0x5F0F3CF5 - return $font; - } - $offset += 4; - // get offset mode (indexToLocFormat : 0 = short, 1 = long) - $offset = $table['head']['offset'] + 50; - $short_offset = (TCPDF_STATIC::_getSHORT($font, $offset) == 0); - $offset += 2; - // get the offsets to the locations of the glyphs in the font, relative to the beginning of the glyphData table - $indexToLoc = array(); - $offset = $table['loca']['offset']; - if ($short_offset) { - // short version - $tot_num_glyphs = floor($table['loca']['length'] / 2); // numGlyphs + 1 - for ($i = 0; $i < $tot_num_glyphs; ++$i) { - $indexToLoc[$i] = TCPDF_STATIC::_getUSHORT($font, $offset) * 2; - $offset += 2; - } - } else { - // long version - $tot_num_glyphs = ($table['loca']['length'] / 4); // numGlyphs + 1 - for ($i = 0; $i < $tot_num_glyphs; ++$i) { - $indexToLoc[$i] = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - } - } - // get glyphs indexes of chars from cmap table - $subsetglyphs = array(); // glyph IDs on key - $subsetglyphs[0] = true; // character codes that do not correspond to any glyph in the font should be mapped to glyph index 0 - $offset = $table['cmap']['offset'] + 2; - $numEncodingTables = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - $encodingTables = array(); - for ($i = 0; $i < $numEncodingTables; ++$i) { - $encodingTables[$i]['platformID'] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - $encodingTables[$i]['encodingID'] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - $encodingTables[$i]['offset'] = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - } - foreach ($encodingTables as $enctable) { - // get all platforms and encodings - $offset = $table['cmap']['offset'] + $enctable['offset']; - $format = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - switch ($format) { - case 0: { // Format 0: Byte encoding table - $offset += 4; // skip length and version/language - for ($c = 0; $c < 256; ++$c) { - if (isset($subsetchars[$c])) { - $g = TCPDF_STATIC::_getBYTE($font, $offset); - $subsetglyphs[$g] = true; - } - ++$offset; - } - break; - } - case 2: { // Format 2: High-byte mapping through table - $offset += 4; // skip length and version/language - $numSubHeaders = 0; - for ($i = 0; $i < 256; ++$i) { - // Array that maps high bytes to subHeaders: value is subHeader index * 8. - $subHeaderKeys[$i] = (TCPDF_STATIC::_getUSHORT($font, $offset) / 8); - $offset += 2; - if ($numSubHeaders < $subHeaderKeys[$i]) { - $numSubHeaders = $subHeaderKeys[$i]; - } - } - // the number of subHeaders is equal to the max of subHeaderKeys + 1 - ++$numSubHeaders; - // read subHeader structures - $subHeaders = array(); - $numGlyphIndexArray = 0; - for ($k = 0; $k < $numSubHeaders; ++$k) { - $subHeaders[$k]['firstCode'] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - $subHeaders[$k]['entryCount'] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - $subHeaders[$k]['idDelta'] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - $subHeaders[$k]['idRangeOffset'] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - $subHeaders[$k]['idRangeOffset'] -= (2 + (($numSubHeaders - $k - 1) * 8)); - $subHeaders[$k]['idRangeOffset'] /= 2; - $numGlyphIndexArray += $subHeaders[$k]['entryCount']; - } - for ($k = 0; $k < $numGlyphIndexArray; ++$k) { - $glyphIndexArray[$k] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - } - for ($i = 0; $i < 256; ++$i) { - $k = $subHeaderKeys[$i]; - if ($k == 0) { - // one byte code - $c = $i; - if (isset($subsetchars[$c])) { - $g = $glyphIndexArray[0]; - $subsetglyphs[$g] = true; - } - } else { - // two bytes code - $start_byte = $subHeaders[$k]['firstCode']; - $end_byte = $start_byte + $subHeaders[$k]['entryCount']; - for ($j = $start_byte; $j < $end_byte; ++$j) { - // combine high and low bytes - $c = (($i << 8) + $j); - if (isset($subsetchars[$c])) { - $idRangeOffset = ($subHeaders[$k]['idRangeOffset'] + $j - $subHeaders[$k]['firstCode']); - $g = ($glyphIndexArray[$idRangeOffset] + $subHeaders[$k]['idDelta']) % 65536; - if ($g < 0) { - $g = 0; - } - $subsetglyphs[$g] = true; - } - } - } - } - break; - } - case 4: { // Format 4: Segment mapping to delta values - $length = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - $offset += 2; // skip version/language - $segCount = floor(TCPDF_STATIC::_getUSHORT($font, $offset) / 2); - $offset += 2; - $offset += 6; // skip searchRange, entrySelector, rangeShift - $endCount = array(); // array of end character codes for each segment - for ($k = 0; $k < $segCount; ++$k) { - $endCount[$k] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - } - $offset += 2; // skip reservedPad - $startCount = array(); // array of start character codes for each segment - for ($k = 0; $k < $segCount; ++$k) { - $startCount[$k] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - } - $idDelta = array(); // delta for all character codes in segment - for ($k = 0; $k < $segCount; ++$k) { - $idDelta[$k] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - } - $idRangeOffset = array(); // Offsets into glyphIdArray or 0 - for ($k = 0; $k < $segCount; ++$k) { - $idRangeOffset[$k] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - } - $gidlen = (floor($length / 2) - 8 - (4 * $segCount)); - $glyphIdArray = array(); // glyph index array - for ($k = 0; $k < $gidlen; ++$k) { - $glyphIdArray[$k] = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - } - for ($k = 0; $k < $segCount; ++$k) { - for ($c = $startCount[$k]; $c <= $endCount[$k]; ++$c) { - if (isset($subsetchars[$c])) { - if ($idRangeOffset[$k] == 0) { - $g = ($idDelta[$k] + $c) % 65536; - } else { - $gid = (floor($idRangeOffset[$k] / 2) + ($c - $startCount[$k]) - ($segCount - $k)); - $g = ($glyphIdArray[$gid] + $idDelta[$k]) % 65536; - } - if ($g < 0) { - $g = 0; - } - $subsetglyphs[$g] = true; - } - } - } - break; - } - case 6: { // Format 6: Trimmed table mapping - $offset += 4; // skip length and version/language - $firstCode = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - $entryCount = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - for ($k = 0; $k < $entryCount; ++$k) { - $c = ($k + $firstCode); - if (isset($subsetchars[$c])) { - $g = TCPDF_STATIC::_getUSHORT($font, $offset); - $subsetglyphs[$g] = true; - } - $offset += 2; - } - break; - } - case 8: { // Format 8: Mixed 16-bit and 32-bit coverage - $offset += 10; // skip reserved, length and version/language - for ($k = 0; $k < 8192; ++$k) { - $is32[$k] = TCPDF_STATIC::_getBYTE($font, $offset); - ++$offset; - } - $nGroups = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - for ($i = 0; $i < $nGroups; ++$i) { - $startCharCode = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - $endCharCode = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - $startGlyphID = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - for ($k = $startCharCode; $k <= $endCharCode; ++$k) { - $is32idx = floor($c / 8); - if ((isset($is32[$is32idx])) AND (($is32[$is32idx] & (1 << (7 - ($c % 8)))) == 0)) { - $c = $k; - } else { - // 32 bit format - // convert to decimal (http://www.unicode.org/faq//utf_bom.html#utf16-4) - //LEAD_OFFSET = (0xD800 - (0x10000 >> 10)) = 55232 - //SURROGATE_OFFSET = (0x10000 - (0xD800 << 10) - 0xDC00) = -56613888 - $c = ((55232 + ($k >> 10)) << 10) + (0xDC00 + ($k & 0x3FF)) -56613888; - } - if (isset($subsetchars[$c])) { - $subsetglyphs[$startGlyphID] = true; - } - ++$startGlyphID; - } - } - break; - } - case 10: { // Format 10: Trimmed array - $offset += 10; // skip reserved, length and version/language - $startCharCode = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - $numChars = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - for ($k = 0; $k < $numChars; ++$k) { - $c = ($k + $startCharCode); - if (isset($subsetchars[$c])) { - $g = TCPDF_STATIC::_getUSHORT($font, $offset); - $subsetglyphs[$g] = true; - } - $offset += 2; - } - break; - } - case 12: { // Format 12: Segmented coverage - $offset += 10; // skip length and version/language - $nGroups = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - for ($k = 0; $k < $nGroups; ++$k) { - $startCharCode = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - $endCharCode = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - $startGlyphCode = TCPDF_STATIC::_getULONG($font, $offset); - $offset += 4; - for ($c = $startCharCode; $c <= $endCharCode; ++$c) { - if (isset($subsetchars[$c])) { - $subsetglyphs[$startGlyphCode] = true; - } - ++$startGlyphCode; - } - } - break; - } - case 13: { // Format 13: Many-to-one range mappings - // to be implemented ... - break; - } - case 14: { // Format 14: Unicode Variation Sequences - // to be implemented ... - break; - } - } - } - // include all parts of composite glyphs - $new_sga = $subsetglyphs; - while (!empty($new_sga)) { - $sga = $new_sga; - $new_sga = array(); - foreach ($sga as $key => $val) { - if (isset($indexToLoc[$key])) { - $offset = ($table['glyf']['offset'] + $indexToLoc[$key]); - $numberOfContours = TCPDF_STATIC::_getSHORT($font, $offset); - $offset += 2; - if ($numberOfContours < 0) { // composite glyph - $offset += 8; // skip xMin, yMin, xMax, yMax - do { - $flags = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - $glyphIndex = TCPDF_STATIC::_getUSHORT($font, $offset); - $offset += 2; - if (!isset($subsetglyphs[$glyphIndex])) { - // add missing glyphs - $new_sga[$glyphIndex] = true; - } - // skip some bytes by case - if ($flags & 1) { - $offset += 4; - } else { - $offset += 2; - } - if ($flags & 8) { - $offset += 2; - } elseif ($flags & 64) { - $offset += 4; - } elseif ($flags & 128) { - $offset += 8; - } - } while ($flags & 32); - } - } - } - $subsetglyphs += $new_sga; - } - // sort glyphs by key (and remove duplicates) - ksort($subsetglyphs); - // build new glyf and loca tables - $glyf = ''; - $loca = ''; - $offset = 0; - $glyf_offset = $table['glyf']['offset']; - for ($i = 0; $i < $tot_num_glyphs; ++$i) { - if (isset($subsetglyphs[$i])) { - $length = ($indexToLoc[($i + 1)] - $indexToLoc[$i]); - $glyf .= substr($font, ($glyf_offset + $indexToLoc[$i]), $length); - } else { - $length = 0; - } - if ($short_offset) { - $loca .= pack('n', floor($offset / 2)); - } else { - $loca .= pack('N', $offset); - } - $offset += $length; - } - // array of table names to preserve (loca and glyf tables will be added later) - // the cmap table is not needed and shall not be present, since the mapping from character codes to glyph descriptions is provided separately - $table_names = array ('head', 'hhea', 'hmtx', 'maxp', 'cvt ', 'fpgm', 'prep'); // minimum required table names - // get the tables to preserve - $offset = 12; - foreach ($table as $tag => $val) { - if (in_array($tag, $table_names)) { - $table[$tag]['data'] = substr($font, $table[$tag]['offset'], $table[$tag]['length']); - if ($tag == 'head') { - // set the checkSumAdjustment to 0 - $table[$tag]['data'] = substr($table[$tag]['data'], 0, 8)."\x0\x0\x0\x0".substr($table[$tag]['data'], 12); - } - $pad = 4 - ($table[$tag]['length'] % 4); - if ($pad != 4) { - // the length of a table must be a multiple of four bytes - $table[$tag]['length'] += $pad; - $table[$tag]['data'] .= str_repeat("\x0", $pad); - } - $table[$tag]['offset'] = $offset; - $offset += $table[$tag]['length']; - // check sum is not changed (so keep the following line commented) - //$table[$tag]['checkSum'] = self::_getTTFtableChecksum($table[$tag]['data'], $table[$tag]['length']); - } else { - unset($table[$tag]); - } - } - // add loca - $table['loca']['data'] = $loca; - $table['loca']['length'] = strlen($loca); - $pad = 4 - ($table['loca']['length'] % 4); - if ($pad != 4) { - // the length of a table must be a multiple of four bytes - $table['loca']['length'] += $pad; - $table['loca']['data'] .= str_repeat("\x0", $pad); - } - $table['loca']['offset'] = $offset; - $table['loca']['checkSum'] = self::_getTTFtableChecksum($table['loca']['data'], $table['loca']['length']); - $offset += $table['loca']['length']; - // add glyf - $table['glyf']['data'] = $glyf; - $table['glyf']['length'] = strlen($glyf); - $pad = 4 - ($table['glyf']['length'] % 4); - if ($pad != 4) { - // the length of a table must be a multiple of four bytes - $table['glyf']['length'] += $pad; - $table['glyf']['data'] .= str_repeat("\x0", $pad); - } - $table['glyf']['offset'] = $offset; - $table['glyf']['checkSum'] = self::_getTTFtableChecksum($table['glyf']['data'], $table['glyf']['length']); - // rebuild font - $font = ''; - $font .= pack('N', 0x10000); // sfnt version - $numTables = count($table); - $font .= pack('n', $numTables); // numTables - $entrySelector = floor(log($numTables, 2)); - $searchRange = pow(2, $entrySelector) * 16; - $rangeShift = ($numTables * 16) - $searchRange; - $font .= pack('n', $searchRange); // searchRange - $font .= pack('n', $entrySelector); // entrySelector - $font .= pack('n', $rangeShift); // rangeShift - $offset = ($numTables * 16); - foreach ($table as $tag => $data) { - $font .= $tag; // tag - $font .= pack('N', $data['checkSum']); // checkSum - $font .= pack('N', ($data['offset'] + $offset)); // offset - $font .= pack('N', $data['length']); // length - } - foreach ($table as $data) { - $font .= $data['data']; - } - // set checkSumAdjustment on head table - $checkSumAdjustment = 0xB1B0AFBA - self::_getTTFtableChecksum($font, strlen($font)); - $font = substr($font, 0, $table['head']['offset'] + 8).pack('N', $checkSumAdjustment).substr($font, $table['head']['offset'] + 12); - return $font; - } - - /** - * Outputs font widths - * @param array $font font data - * @param int $cidoffset offset for CID values - * @return string PDF command string for font widths - * @author Nicola Asuni - * @since 4.4.000 (2008-12-07) - * @public static - */ - public static function _putfontwidths($font, $cidoffset=0) { - ksort($font['cw']); - $rangeid = 0; - $range = array(); - $prevcid = -2; - $prevwidth = -1; - $interval = false; - // for each character - foreach ($font['cw'] as $cid => $width) { - $cid -= $cidoffset; - if ($font['subset'] AND (!isset($font['subsetchars'][$cid]))) { - // ignore the unused characters (font subsetting) - continue; - } - if ($width != $font['dw']) { - if ($cid == ($prevcid + 1)) { - // consecutive CID - if ($width == $prevwidth) { - if ($width == $range[$rangeid][0]) { - $range[$rangeid][] = $width; - } else { - array_pop($range[$rangeid]); - // new range - $rangeid = $prevcid; - $range[$rangeid] = array(); - $range[$rangeid][] = $prevwidth; - $range[$rangeid][] = $width; - } - $interval = true; - $range[$rangeid]['interval'] = true; - } else { - if ($interval) { - // new range - $rangeid = $cid; - $range[$rangeid] = array(); - $range[$rangeid][] = $width; - } else { - $range[$rangeid][] = $width; - } - $interval = false; - } - } else { - // new range - $rangeid = $cid; - $range[$rangeid] = array(); - $range[$rangeid][] = $width; - $interval = false; - } - $prevcid = $cid; - $prevwidth = $width; - } - } - // optimize ranges - $prevk = -1; - $nextk = -1; - $prevint = false; - foreach ($range as $k => $ws) { - $cws = count($ws); - if (($k == $nextk) AND (!$prevint) AND ((!isset($ws['interval'])) OR ($cws < 4))) { - if (isset($range[$k]['interval'])) { - unset($range[$k]['interval']); - } - $range[$prevk] = array_merge($range[$prevk], $range[$k]); - unset($range[$k]); - } else { - $prevk = $k; - } - $nextk = $k + $cws; - if (isset($ws['interval'])) { - if ($cws > 3) { - $prevint = true; - } else { - $prevint = false; - } - if (isset($range[$k]['interval'])) { - unset($range[$k]['interval']); - } - --$nextk; - } else { - $prevint = false; - } - } - // output data - $w = ''; - foreach ($range as $k => $ws) { - if (count(array_count_values($ws)) == 1) { - // interval mode is more compact - $w .= ' '.$k.' '.($k + count($ws) - 1).' '.$ws[0]; - } else { - // range mode - $w .= ' '.$k.' [ '.implode(' ', $ws).' ]'; - } - } - return '/W ['.$w.' ]'; - } - - - - - /** - * Update the CIDToGIDMap string with a new value. - * @param string $map CIDToGIDMap. - * @param int $cid CID value. - * @param int $gid GID value. - * @return string CIDToGIDMap. - * @author Nicola Asuni - * @since 5.9.123 (2011-09-29) - * @public static - */ - public static function updateCIDtoGIDmap($map, $cid, $gid) { - if (($cid >= 0) AND ($cid <= 0xFFFF) AND ($gid >= 0)) { - if ($gid > 0xFFFF) { - $gid -= 0x10000; - } - $map[($cid * 2)] = chr($gid >> 8); - $map[(($cid * 2) + 1)] = chr($gid & 0xFF); - } - return $map; - } - - /** - * Return fonts path - * @return string - * @public static - */ - public static function _getfontpath() { - if (!defined('K_PATH_FONTS') AND is_dir($fdir = realpath(dirname(__FILE__).'/../fonts'))) { - if (substr($fdir, -1) != '/') { - $fdir .= '/'; - } - define('K_PATH_FONTS', $fdir); - } - return defined('K_PATH_FONTS') ? K_PATH_FONTS : ''; - } - - - - /** - * Return font full path - * @param string $file Font file name. - * @param string $fontdir Font directory (set to false fto search on default directories) - * @return string Font full path or empty string - * @author Nicola Asuni - * @since 6.0.025 - * @public static - */ - public static function getFontFullPath($file, $fontdir=false) { - $fontfile = ''; - // search files on various directories - if (($fontdir !== false) AND @TCPDF_STATIC::file_exists($fontdir.$file)) { - $fontfile = $fontdir.$file; - } elseif (@TCPDF_STATIC::file_exists(self::_getfontpath().$file)) { - $fontfile = self::_getfontpath().$file; - } elseif (@TCPDF_STATIC::file_exists($file)) { - $fontfile = $file; - } - return $fontfile; - } - - - - - /** - * Get a reference font size. - * @param string $size String containing font size value. - * @param float $refsize Reference font size in points. - * @return float value in points - * @public static - */ - public static function getFontRefSize($size, $refsize=12) { - switch ($size) { - case 'xx-small': { - $size = ($refsize - 4); - break; - } - case 'x-small': { - $size = ($refsize - 3); - break; - } - case 'small': { - $size = ($refsize - 2); - break; - } - case 'medium': { - $size = $refsize; - break; - } - case 'large': { - $size = ($refsize + 2); - break; - } - case 'x-large': { - $size = ($refsize + 4); - break; - } - case 'xx-large': { - $size = ($refsize + 6); - break; - } - case 'smaller': { - $size = ($refsize - 3); - break; - } - case 'larger': { - $size = ($refsize + 3); - break; - } - } - return $size; - } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// ==================================================================================================================== -// REIMPLEMENTED -// ==================================================================================================================== - - - - - - - - - /** - * Returns the unicode caracter specified by the value - * @param int $c UTF-8 value - * @param boolean $unicode True if we are in unicode mode, false otherwise. - * @return string Returns the specified character. - * @since 2.3.000 (2008-03-05) - * @public static - */ - public static function unichr($c, $unicode=true) { - $c = intval($c); - if (!$unicode) { - return chr($c); - } elseif ($c <= 0x7F) { - // one byte - return chr($c); - } elseif ($c <= 0x7FF) { - // two bytes - return chr(0xC0 | $c >> 6).chr(0x80 | $c & 0x3F); - } elseif ($c <= 0xFFFF) { - // three bytes - return chr(0xE0 | $c >> 12).chr(0x80 | $c >> 6 & 0x3F).chr(0x80 | $c & 0x3F); - } elseif ($c <= 0x10FFFF) { - // four bytes - return chr(0xF0 | $c >> 18).chr(0x80 | $c >> 12 & 0x3F).chr(0x80 | $c >> 6 & 0x3F).chr(0x80 | $c & 0x3F); - } else { - return ''; - } - } - - /** - * Returns the unicode caracter specified by UTF-8 value - * @param int $c UTF-8 value - * @return string Returns the specified character. - * @public static - */ - public static function unichrUnicode($c) { - return self::unichr($c, true); - } - - /** - * Returns the unicode caracter specified by ASCII value - * @param int $c UTF-8 value - * @return string Returns the specified character. - * @public static - */ - public static function unichrASCII($c) { - return self::unichr($c, false); - } - - /** - * Converts array of UTF-8 characters to UTF16-BE string.<br> - * Based on: http://www.faqs.org/rfcs/rfc2781.html - * <pre> - * Encoding UTF-16: - * - * Encoding of a single character from an ISO 10646 character value to - * UTF-16 proceeds as follows. Let U be the character number, no greater - * than 0x10FFFF. - * - * 1) If U < 0x10000, encode U as a 16-bit unsigned integer and - * terminate. - * - * 2) Let U' = U - 0x10000. Because U is less than or equal to 0x10FFFF, - * U' must be less than or equal to 0xFFFFF. That is, U' can be - * represented in 20 bits. - * - * 3) Initialize two 16-bit unsigned integers, W1 and W2, to 0xD800 and - * 0xDC00, respectively. These integers each have 10 bits free to - * encode the character value, for a total of 20 bits. - * - * 4) Assign the 10 high-order bits of the 20-bit U' to the 10 low-order - * bits of W1 and the 10 low-order bits of U' to the 10 low-order - * bits of W2. Terminate. - * - * Graphically, steps 2 through 4 look like: - * U' = yyyyyyyyyyxxxxxxxxxx - * W1 = 110110yyyyyyyyyy - * W2 = 110111xxxxxxxxxx - * </pre> - * @param array $unicode array containing UTF-8 unicode values - * @param boolean $setbom if true set the Byte Order Mark (BOM = 0xFEFF) - * @return string - * @protected - * @author Nicola Asuni - * @since 2.1.000 (2008-01-08) - * @public static - */ - public static function arrUTF8ToUTF16BE($unicode, $setbom=false) { - $outstr = ''; // string to be returned - if ($setbom) { - $outstr .= "\xFE\xFF"; // Byte Order Mark (BOM) - } - foreach ($unicode as $char) { - if ($char == 0x200b) { - // skip Unicode Character 'ZERO WIDTH SPACE' (DEC:8203, U+200B) - } elseif ($char == 0xFFFD) { - $outstr .= "\xFF\xFD"; // replacement character - } elseif ($char < 0x10000) { - $outstr .= chr($char >> 0x08); - $outstr .= chr($char & 0xFF); - } else { - $char -= 0x10000; - $w1 = 0xD800 | ($char >> 0x0a); - $w2 = 0xDC00 | ($char & 0x3FF); - $outstr .= chr($w1 >> 0x08); - $outstr .= chr($w1 & 0xFF); - $outstr .= chr($w2 >> 0x08); - $outstr .= chr($w2 & 0xFF); - } - } - return $outstr; - } - - /** - * Convert an array of UTF8 values to array of unicode characters - * @param array $ta The input array of UTF8 values. - * @param boolean $isunicode True for Unicode mode, false otherwise. - * @return array Return array of unicode characters - * @since 4.5.037 (2009-04-07) - * @public static - */ - public static function UTF8ArrayToUniArray($ta, $isunicode=true) { - if ($isunicode) { - return array_map(array('TCPDF_FONTS', 'unichrUnicode'), $ta); - } - return array_map(array('TCPDF_FONTS', 'unichrASCII'), $ta); - } - - /** - * Extract a slice of the $strarr array and return it as string. - * @param string[] $strarr The input array of characters. - * @param int $start the starting element of $strarr. - * @param int $end first element that will not be returned. - * @param boolean $unicode True if we are in unicode mode, false otherwise. - * @return string Return part of a string - * @public static - */ - public static function UTF8ArrSubString($strarr, $start='', $end='', $unicode=true) { - if (strlen($start) == 0) { - $start = 0; - } - if (strlen($end) == 0) { - $end = count($strarr); - } - $string = ''; - for ($i = $start; $i < $end; ++$i) { - $string .= self::unichr($strarr[$i], $unicode); - } - return $string; - } - - /** - * Extract a slice of the $uniarr array and return it as string. - * @param string[] $uniarr The input array of characters. - * @param int $start the starting element of $strarr. - * @param int $end first element that will not be returned. - * @return string Return part of a string - * @since 4.5.037 (2009-04-07) - * @public static - */ - public static function UniArrSubString($uniarr, $start='', $end='') { - if (strlen($start) == 0) { - $start = 0; - } - if (strlen($end) == 0) { - $end = count($uniarr); - } - $string = ''; - for ($i=$start; $i < $end; ++$i) { - $string .= $uniarr[$i]; - } - return $string; - } - - /** - * Converts UTF-8 characters array to array of Latin1 characters array<br> - * @param array $unicode array containing UTF-8 unicode values - * @return array - * @author Nicola Asuni - * @since 4.8.023 (2010-01-15) - * @public static - */ - public static function UTF8ArrToLatin1Arr($unicode) { - $outarr = array(); // array to be returned - foreach ($unicode as $char) { - if ($char < 256) { - $outarr[] = $char; - } elseif (array_key_exists($char, TCPDF_FONT_DATA::$uni_utf8tolatin)) { - // map from UTF-8 - $outarr[] = TCPDF_FONT_DATA::$uni_utf8tolatin[$char]; - } elseif ($char == 0xFFFD) { - // skip - } else { - $outarr[] = 63; // '?' character - } - } - return $outarr; - } - - /** - * Converts UTF-8 characters array to Latin1 string<br> - * @param array $unicode array containing UTF-8 unicode values - * @return string - * @author Nicola Asuni - * @since 4.8.023 (2010-01-15) - * @public static - */ - public static function UTF8ArrToLatin1($unicode) { - $outstr = ''; // string to be returned - foreach ($unicode as $char) { - if ($char < 256) { - $outstr .= chr($char); - } elseif (array_key_exists($char, TCPDF_FONT_DATA::$uni_utf8tolatin)) { - // map from UTF-8 - $outstr .= chr(TCPDF_FONT_DATA::$uni_utf8tolatin[$char]); - } elseif ($char == 0xFFFD) { - // skip - } else { - $outstr .= '?'; - } - } - return $outstr; - } - - /** - * Converts UTF-8 character to integer value.<br> - * Uses the getUniord() method if the value is not cached. - * @param string $uch character string to process. - * @return int Unicode value - * @public static - */ - public static function uniord($uch) { - if (!isset(self::$cache_uniord[$uch])) { - self::$cache_uniord[$uch] = self::getUniord($uch); - } - return self::$cache_uniord[$uch]; - } - - /** - * Converts UTF-8 character to integer value.<br> - * Invalid byte sequences will be replaced with 0xFFFD (replacement character)<br> - * Based on: http://www.faqs.org/rfcs/rfc3629.html - * <pre> - * Char. number range | UTF-8 octet sequence - * (hexadecimal) | (binary) - * --------------------+----------------------------------------------- - * 0000 0000-0000 007F | 0xxxxxxx - * 0000 0080-0000 07FF | 110xxxxx 10xxxxxx - * 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx - * 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - * --------------------------------------------------------------------- - * - * ABFN notation: - * --------------------------------------------------------------------- - * UTF8-octets = *( UTF8-char ) - * UTF8-char = UTF8-1 / UTF8-2 / UTF8-3 / UTF8-4 - * UTF8-1 = %x00-7F - * UTF8-2 = %xC2-DF UTF8-tail - * - * UTF8-3 = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) / - * %xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail ) - * UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) / - * %xF4 %x80-8F 2( UTF8-tail ) - * UTF8-tail = %x80-BF - * --------------------------------------------------------------------- - * </pre> - * @param string $uch character string to process. - * @return int Unicode value - * @author Nicola Asuni - * @public static - */ - public static function getUniord($uch) { - if (function_exists('mb_convert_encoding')) { - list(, $char) = @unpack('N', mb_convert_encoding($uch, 'UCS-4BE', 'UTF-8')); - if ($char >= 0) { - return $char; - } - } - $bytes = array(); // array containing single character byte sequences - $countbytes = 0; - $numbytes = 1; // number of octetc needed to represent the UTF-8 character - $length = strlen($uch); - for ($i = 0; $i < $length; ++$i) { - $char = ord($uch[$i]); // get one string character at time - if ($countbytes == 0) { // get starting octect - if ($char <= 0x7F) { - return $char; // use the character "as is" because is ASCII - } elseif (($char >> 0x05) == 0x06) { // 2 bytes character (0x06 = 110 BIN) - $bytes[] = ($char - 0xC0) << 0x06; - ++$countbytes; - $numbytes = 2; - } elseif (($char >> 0x04) == 0x0E) { // 3 bytes character (0x0E = 1110 BIN) - $bytes[] = ($char - 0xE0) << 0x0C; - ++$countbytes; - $numbytes = 3; - } elseif (($char >> 0x03) == 0x1E) { // 4 bytes character (0x1E = 11110 BIN) - $bytes[] = ($char - 0xF0) << 0x12; - ++$countbytes; - $numbytes = 4; - } else { - // use replacement character for other invalid sequences - return 0xFFFD; - } - } elseif (($char >> 0x06) == 0x02) { // bytes 2, 3 and 4 must start with 0x02 = 10 BIN - $bytes[] = $char - 0x80; - ++$countbytes; - if ($countbytes == $numbytes) { - // compose UTF-8 bytes to a single unicode value - $char = $bytes[0]; - for ($j = 1; $j < $numbytes; ++$j) { - $char += ($bytes[$j] << (($numbytes - $j - 1) * 0x06)); - } - if ((($char >= 0xD800) AND ($char <= 0xDFFF)) OR ($char >= 0x10FFFF)) { - // The definition of UTF-8 prohibits encoding character numbers between - // U+D800 and U+DFFF, which are reserved for use with the UTF-16 - // encoding form (as surrogate pairs) and do not directly represent - // characters. - return 0xFFFD; // use replacement character - } else { - return $char; - } - } - } else { - // use replacement character for other invalid sequences - return 0xFFFD; - } - } - return 0xFFFD; - } - - /** - * Converts UTF-8 strings to codepoints array.<br> - * Invalid byte sequences will be replaced with 0xFFFD (replacement character)<br> - * @param string $str string to process. - * @param boolean $isunicode True when the documetn is in Unicode mode, false otherwise. - * @param array $currentfont Reference to current font array. - * @return array containing codepoints (UTF-8 characters values) - * @author Nicola Asuni - * @public static - */ - public static function UTF8StringToArray($str, $isunicode, &$currentfont) { - if ($isunicode) { - // requires PCRE unicode support turned on - $chars = TCPDF_STATIC::pregSplit('//','u', $str, -1, PREG_SPLIT_NO_EMPTY); - $carr = array_map(array('TCPDF_FONTS', 'uniord'), $chars); - } else { - $chars = str_split($str); - $carr = array_map('ord', $chars); - } - if (is_array($currentfont['subsetchars']) && is_array($carr)) { - $currentfont['subsetchars'] += array_fill_keys($carr, true); - } else { - $currentfont['subsetchars'] = array_merge($currentfont['subsetchars'], $carr); - } - return $carr; - } - - /** - * Converts UTF-8 strings to Latin1 when using the standard 14 core fonts.<br> - * @param string $str string to process. - * @param boolean $isunicode True when the documetn is in Unicode mode, false otherwise. - * @param array $currentfont Reference to current font array. - * @return string - * @since 3.2.000 (2008-06-23) - * @public static - */ - public static function UTF8ToLatin1($str, $isunicode, &$currentfont) { - $unicode = self::UTF8StringToArray($str, $isunicode, $currentfont); // array containing UTF-8 unicode values - return self::UTF8ArrToLatin1($unicode); - } - - /** - * Converts UTF-8 strings to UTF16-BE.<br> - * @param string $str string to process. - * @param boolean $setbom if true set the Byte Order Mark (BOM = 0xFEFF) - * @param boolean $isunicode True when the documetn is in Unicode mode, false otherwise. - * @param array $currentfont Reference to current font array. - * @return string - * @author Nicola Asuni - * @since 1.53.0.TC005 (2005-01-05) - * @public static - */ - public static function UTF8ToUTF16BE($str, $setbom, $isunicode, &$currentfont) { - if (!$isunicode) { - return $str; // string is not in unicode - } - $unicode = self::UTF8StringToArray($str, $isunicode, $currentfont); // array containing UTF-8 unicode values - return self::arrUTF8ToUTF16BE($unicode, $setbom); - } - - /** - * Reverse the RLT substrings using the Bidirectional Algorithm (http://unicode.org/reports/tr9/). - * @param string $str string to manipulate. - * @param bool $setbom if true set the Byte Order Mark (BOM = 0xFEFF) - * @param bool $forcertl if true forces RTL text direction - * @param boolean $isunicode True if the document is in Unicode mode, false otherwise. - * @param array $currentfont Reference to current font array. - * @return string - * @author Nicola Asuni - * @since 2.1.000 (2008-01-08) - * @public static - */ - public static function utf8StrRev($str, $setbom, $forcertl, $isunicode, &$currentfont) { - return self::utf8StrArrRev(self::UTF8StringToArray($str, $isunicode, $currentfont), $str, $setbom, $forcertl, $isunicode, $currentfont); - } - - /** - * Reverse the RLT substrings array using the Bidirectional Algorithm (http://unicode.org/reports/tr9/). - * @param array $arr array of unicode values. - * @param string $str string to manipulate (or empty value). - * @param bool $setbom if true set the Byte Order Mark (BOM = 0xFEFF) - * @param bool $forcertl if true forces RTL text direction - * @param boolean $isunicode True if the document is in Unicode mode, false otherwise. - * @param array $currentfont Reference to current font array. - * @return string - * @author Nicola Asuni - * @since 4.9.000 (2010-03-27) - * @public static - */ - public static function utf8StrArrRev($arr, $str, $setbom, $forcertl, $isunicode, &$currentfont) { - return self::arrUTF8ToUTF16BE(self::utf8Bidi($arr, $str, $forcertl, $isunicode, $currentfont), $setbom); - } - - /** - * Reverse the RLT substrings using the Bidirectional Algorithm (http://unicode.org/reports/tr9/). - * @param array $ta array of characters composing the string. - * @param string $str string to process - * @param bool $forcertl if 'R' forces RTL, if 'L' forces LTR - * @param boolean $isunicode True if the document is in Unicode mode, false otherwise. - * @param array $currentfont Reference to current font array. - * @return array of unicode chars - * @author Nicola Asuni - * @since 2.4.000 (2008-03-06) - * @public static - */ - public static function utf8Bidi($ta, $str, $forcertl, $isunicode, &$currentfont) { - // paragraph embedding level - $pel = 0; - // max level - $maxlevel = 0; - if (TCPDF_STATIC::empty_string($str)) { - // create string from array - $str = self::UTF8ArrSubString($ta, '', '', $isunicode); - } - // check if string contains arabic text - if (preg_match(TCPDF_FONT_DATA::$uni_RE_PATTERN_ARABIC, $str)) { - $arabic = true; - } else { - $arabic = false; - } - // check if string contains RTL text - if (!($forcertl OR $arabic OR preg_match(TCPDF_FONT_DATA::$uni_RE_PATTERN_RTL, $str))) { - return $ta; - } - - // get number of chars - $numchars = count($ta); - - if ($forcertl == 'R') { - $pel = 1; - } elseif ($forcertl == 'L') { - $pel = 0; - } else { - // P2. In each paragraph, find the first character of type L, AL, or R. - // P3. If a character is found in P2 and it is of type AL or R, then set the paragraph embedding level to one; otherwise, set it to zero. - for ($i=0; $i < $numchars; ++$i) { - $type = TCPDF_FONT_DATA::$uni_type[$ta[$i]]; - if ($type == 'L') { - $pel = 0; - break; - } elseif (($type == 'AL') OR ($type == 'R')) { - $pel = 1; - break; - } - } - } - - // Current Embedding Level - $cel = $pel; - // directional override status - $dos = 'N'; - $remember = array(); - // start-of-level-run - $sor = $pel % 2 ? 'R' : 'L'; - $eor = $sor; - - // Array of characters data - $chardata = Array(); - - // X1. Begin by setting the current embedding level to the paragraph embedding level. Set the directional override status to neutral. Process each character iteratively, applying rules X2 through X9. Only embedding levels from 0 to 61 are valid in this phase. - // In the resolution of levels in rules I1 and I2, the maximum embedding level of 62 can be reached. - for ($i=0; $i < $numchars; ++$i) { - if ($ta[$i] == TCPDF_FONT_DATA::$uni_RLE) { - // X2. With each RLE, compute the least greater odd embedding level. - // a. If this new level would be valid, then this embedding code is valid. Remember (push) the current embedding level and override status. Reset the current level to this new level, and reset the override status to neutral. - // b. If the new level would not be valid, then this code is invalid. Do not change the current level or override status. - $next_level = $cel + ($cel % 2) + 1; - if ($next_level < 62) { - $remember[] = array('num' => TCPDF_FONT_DATA::$uni_RLE, 'cel' => $cel, 'dos' => $dos); - $cel = $next_level; - $dos = 'N'; - $sor = $eor; - $eor = $cel % 2 ? 'R' : 'L'; - } - } elseif ($ta[$i] == TCPDF_FONT_DATA::$uni_LRE) { - // X3. With each LRE, compute the least greater even embedding level. - // a. If this new level would be valid, then this embedding code is valid. Remember (push) the current embedding level and override status. Reset the current level to this new level, and reset the override status to neutral. - // b. If the new level would not be valid, then this code is invalid. Do not change the current level or override status. - $next_level = $cel + 2 - ($cel % 2); - if ( $next_level < 62 ) { - $remember[] = array('num' => TCPDF_FONT_DATA::$uni_LRE, 'cel' => $cel, 'dos' => $dos); - $cel = $next_level; - $dos = 'N'; - $sor = $eor; - $eor = $cel % 2 ? 'R' : 'L'; - } - } elseif ($ta[$i] == TCPDF_FONT_DATA::$uni_RLO) { - // X4. With each RLO, compute the least greater odd embedding level. - // a. If this new level would be valid, then this embedding code is valid. Remember (push) the current embedding level and override status. Reset the current level to this new level, and reset the override status to right-to-left. - // b. If the new level would not be valid, then this code is invalid. Do not change the current level or override status. - $next_level = $cel + ($cel % 2) + 1; - if ($next_level < 62) { - $remember[] = array('num' => TCPDF_FONT_DATA::$uni_RLO, 'cel' => $cel, 'dos' => $dos); - $cel = $next_level; - $dos = 'R'; - $sor = $eor; - $eor = $cel % 2 ? 'R' : 'L'; - } - } elseif ($ta[$i] == TCPDF_FONT_DATA::$uni_LRO) { - // X5. With each LRO, compute the least greater even embedding level. - // a. If this new level would be valid, then this embedding code is valid. Remember (push) the current embedding level and override status. Reset the current level to this new level, and reset the override status to left-to-right. - // b. If the new level would not be valid, then this code is invalid. Do not change the current level or override status. - $next_level = $cel + 2 - ($cel % 2); - if ( $next_level < 62 ) { - $remember[] = array('num' => TCPDF_FONT_DATA::$uni_LRO, 'cel' => $cel, 'dos' => $dos); - $cel = $next_level; - $dos = 'L'; - $sor = $eor; - $eor = $cel % 2 ? 'R' : 'L'; - } - } elseif ($ta[$i] == TCPDF_FONT_DATA::$uni_PDF) { - // X7. With each PDF, determine the matching embedding or override code. If there was a valid matching code, restore (pop) the last remembered (pushed) embedding level and directional override. - if (count($remember)) { - $last = count($remember ) - 1; - if (($remember[$last]['num'] == TCPDF_FONT_DATA::$uni_RLE) OR - ($remember[$last]['num'] == TCPDF_FONT_DATA::$uni_LRE) OR - ($remember[$last]['num'] == TCPDF_FONT_DATA::$uni_RLO) OR - ($remember[$last]['num'] == TCPDF_FONT_DATA::$uni_LRO)) { - $match = array_pop($remember); - $cel = $match['cel']; - $dos = $match['dos']; - $sor = $eor; - $eor = ($cel > $match['cel'] ? $cel : $match['cel']) % 2 ? 'R' : 'L'; - } - } - } elseif (($ta[$i] != TCPDF_FONT_DATA::$uni_RLE) AND - ($ta[$i] != TCPDF_FONT_DATA::$uni_LRE) AND - ($ta[$i] != TCPDF_FONT_DATA::$uni_RLO) AND - ($ta[$i] != TCPDF_FONT_DATA::$uni_LRO) AND - ($ta[$i] != TCPDF_FONT_DATA::$uni_PDF)) { - // X6. For all types besides RLE, LRE, RLO, LRO, and PDF: - // a. Set the level of the current character to the current embedding level. - // b. Whenever the directional override status is not neutral, reset the current character type to the directional override status. - if ($dos != 'N') { - $chardir = $dos; - } else { - if (isset(TCPDF_FONT_DATA::$uni_type[$ta[$i]])) { - $chardir = TCPDF_FONT_DATA::$uni_type[$ta[$i]]; - } else { - $chardir = 'L'; - } - } - // stores string characters and other information - $chardata[] = array('char' => $ta[$i], 'level' => $cel, 'type' => $chardir, 'sor' => $sor, 'eor' => $eor); - } - } // end for each char - - // X8. All explicit directional embeddings and overrides are completely terminated at the end of each paragraph. Paragraph separators are not included in the embedding. - // X9. Remove all RLE, LRE, RLO, LRO, PDF, and BN codes. - // X10. The remaining rules are applied to each run of characters at the same level. For each run, determine the start-of-level-run (sor) and end-of-level-run (eor) type, either L or R. This depends on the higher of the two levels on either side of the boundary (at the start or end of the paragraph, the level of the 'other' run is the base embedding level). If the higher level is odd, the type is R; otherwise, it is L. - - // 3.3.3 Resolving Weak Types - // Weak types are now resolved one level run at a time. At level run boundaries where the type of the character on the other side of the boundary is required, the type assigned to sor or eor is used. - // Nonspacing marks are now resolved based on the previous characters. - $numchars = count($chardata); - - // W1. Examine each nonspacing mark (NSM) in the level run, and change the type of the NSM to the type of the previous character. If the NSM is at the start of the level run, it will get the type of sor. - $prevlevel = -1; // track level changes - $levcount = 0; // counts consecutive chars at the same level - for ($i=0; $i < $numchars; ++$i) { - if ($chardata[$i]['type'] == 'NSM') { - if ($levcount) { - $chardata[$i]['type'] = $chardata[$i]['sor']; - } elseif ($i > 0) { - $chardata[$i]['type'] = $chardata[($i-1)]['type']; - } - } - if ($chardata[$i]['level'] != $prevlevel) { - $levcount = 0; - } else { - ++$levcount; - } - $prevlevel = $chardata[$i]['level']; - } - - // W2. Search backward from each instance of a European number until the first strong type (R, L, AL, or sor) is found. If an AL is found, change the type of the European number to Arabic number. - $prevlevel = -1; - $levcount = 0; - for ($i=0; $i < $numchars; ++$i) { - if ($chardata[$i]['char'] == 'EN') { - for ($j=$levcount; $j >= 0; $j--) { - if ($chardata[$j]['type'] == 'AL') { - $chardata[$i]['type'] = 'AN'; - } elseif (($chardata[$j]['type'] == 'L') OR ($chardata[$j]['type'] == 'R')) { - break; - } - } - } - if ($chardata[$i]['level'] != $prevlevel) { - $levcount = 0; - } else { - ++$levcount; - } - $prevlevel = $chardata[$i]['level']; - } - - // W3. Change all ALs to R. - for ($i=0; $i < $numchars; ++$i) { - if ($chardata[$i]['type'] == 'AL') { - $chardata[$i]['type'] = 'R'; - } - } - - // W4. A single European separator between two European numbers changes to a European number. A single common separator between two numbers of the same type changes to that type. - $prevlevel = -1; - $levcount = 0; - for ($i=0; $i < $numchars; ++$i) { - if (($levcount > 0) AND (($i+1) < $numchars) AND ($chardata[($i+1)]['level'] == $prevlevel)) { - if (($chardata[$i]['type'] == 'ES') AND ($chardata[($i-1)]['type'] == 'EN') AND ($chardata[($i+1)]['type'] == 'EN')) { - $chardata[$i]['type'] = 'EN'; - } elseif (($chardata[$i]['type'] == 'CS') AND ($chardata[($i-1)]['type'] == 'EN') AND ($chardata[($i+1)]['type'] == 'EN')) { - $chardata[$i]['type'] = 'EN'; - } elseif (($chardata[$i]['type'] == 'CS') AND ($chardata[($i-1)]['type'] == 'AN') AND ($chardata[($i+1)]['type'] == 'AN')) { - $chardata[$i]['type'] = 'AN'; - } - } - if ($chardata[$i]['level'] != $prevlevel) { - $levcount = 0; - } else { - ++$levcount; - } - $prevlevel = $chardata[$i]['level']; - } - - // W5. A sequence of European terminators adjacent to European numbers changes to all European numbers. - $prevlevel = -1; - $levcount = 0; - for ($i=0; $i < $numchars; ++$i) { - if ($chardata[$i]['type'] == 'ET') { - if (($levcount > 0) AND ($chardata[($i-1)]['type'] == 'EN')) { - $chardata[$i]['type'] = 'EN'; - } else { - $j = $i+1; - while (($j < $numchars) AND ($chardata[$j]['level'] == $prevlevel)) { - if ($chardata[$j]['type'] == 'EN') { - $chardata[$i]['type'] = 'EN'; - break; - } elseif ($chardata[$j]['type'] != 'ET') { - break; - } - ++$j; - } - } - } - if ($chardata[$i]['level'] != $prevlevel) { - $levcount = 0; - } else { - ++$levcount; - } - $prevlevel = $chardata[$i]['level']; - } - - // W6. Otherwise, separators and terminators change to Other Neutral. - $prevlevel = -1; - $levcount = 0; - for ($i=0; $i < $numchars; ++$i) { - if (($chardata[$i]['type'] == 'ET') OR ($chardata[$i]['type'] == 'ES') OR ($chardata[$i]['type'] == 'CS')) { - $chardata[$i]['type'] = 'ON'; - } - if ($chardata[$i]['level'] != $prevlevel) { - $levcount = 0; - } else { - ++$levcount; - } - $prevlevel = $chardata[$i]['level']; - } - - //W7. Search backward from each instance of a European number until the first strong type (R, L, or sor) is found. If an L is found, then change the type of the European number to L. - $prevlevel = -1; - $levcount = 0; - for ($i=0; $i < $numchars; ++$i) { - if ($chardata[$i]['char'] == 'EN') { - for ($j=$levcount; $j >= 0; $j--) { - if ($chardata[$j]['type'] == 'L') { - $chardata[$i]['type'] = 'L'; - } elseif ($chardata[$j]['type'] == 'R') { - break; - } - } - } - if ($chardata[$i]['level'] != $prevlevel) { - $levcount = 0; - } else { - ++$levcount; - } - $prevlevel = $chardata[$i]['level']; - } - - // N1. A sequence of neutrals takes the direction of the surrounding strong text if the text on both sides has the same direction. European and Arabic numbers act as if they were R in terms of their influence on neutrals. Start-of-level-run (sor) and end-of-level-run (eor) are used at level run boundaries. - $prevlevel = -1; - $levcount = 0; - for ($i=0; $i < $numchars; ++$i) { - if (($levcount > 0) AND (($i+1) < $numchars) AND ($chardata[($i+1)]['level'] == $prevlevel)) { - if (($chardata[$i]['type'] == 'N') AND ($chardata[($i-1)]['type'] == 'L') AND ($chardata[($i+1)]['type'] == 'L')) { - $chardata[$i]['type'] = 'L'; - } elseif (($chardata[$i]['type'] == 'N') AND - (($chardata[($i-1)]['type'] == 'R') OR ($chardata[($i-1)]['type'] == 'EN') OR ($chardata[($i-1)]['type'] == 'AN')) AND - (($chardata[($i+1)]['type'] == 'R') OR ($chardata[($i+1)]['type'] == 'EN') OR ($chardata[($i+1)]['type'] == 'AN'))) { - $chardata[$i]['type'] = 'R'; - } elseif ($chardata[$i]['type'] == 'N') { - // N2. Any remaining neutrals take the embedding direction - $chardata[$i]['type'] = $chardata[$i]['sor']; - } - } elseif (($levcount == 0) AND (($i+1) < $numchars) AND ($chardata[($i+1)]['level'] == $prevlevel)) { - // first char - if (($chardata[$i]['type'] == 'N') AND ($chardata[$i]['sor'] == 'L') AND ($chardata[($i+1)]['type'] == 'L')) { - $chardata[$i]['type'] = 'L'; - } elseif (($chardata[$i]['type'] == 'N') AND - (($chardata[$i]['sor'] == 'R') OR ($chardata[$i]['sor'] == 'EN') OR ($chardata[$i]['sor'] == 'AN')) AND - (($chardata[($i+1)]['type'] == 'R') OR ($chardata[($i+1)]['type'] == 'EN') OR ($chardata[($i+1)]['type'] == 'AN'))) { - $chardata[$i]['type'] = 'R'; - } elseif ($chardata[$i]['type'] == 'N') { - // N2. Any remaining neutrals take the embedding direction - $chardata[$i]['type'] = $chardata[$i]['sor']; - } - } elseif (($levcount > 0) AND ((($i+1) == $numchars) OR (($i+1) < $numchars) AND ($chardata[($i+1)]['level'] != $prevlevel))) { - //last char - if (($chardata[$i]['type'] == 'N') AND ($chardata[($i-1)]['type'] == 'L') AND ($chardata[$i]['eor'] == 'L')) { - $chardata[$i]['type'] = 'L'; - } elseif (($chardata[$i]['type'] == 'N') AND - (($chardata[($i-1)]['type'] == 'R') OR ($chardata[($i-1)]['type'] == 'EN') OR ($chardata[($i-1)]['type'] == 'AN')) AND - (($chardata[$i]['eor'] == 'R') OR ($chardata[$i]['eor'] == 'EN') OR ($chardata[$i]['eor'] == 'AN'))) { - $chardata[$i]['type'] = 'R'; - } elseif ($chardata[$i]['type'] == 'N') { - // N2. Any remaining neutrals take the embedding direction - $chardata[$i]['type'] = $chardata[$i]['sor']; - } - } elseif ($chardata[$i]['type'] == 'N') { - // N2. Any remaining neutrals take the embedding direction - $chardata[$i]['type'] = $chardata[$i]['sor']; - } - if ($chardata[$i]['level'] != $prevlevel) { - $levcount = 0; - } else { - ++$levcount; - } - $prevlevel = $chardata[$i]['level']; - } - - // I1. For all characters with an even (left-to-right) embedding direction, those of type R go up one level and those of type AN or EN go up two levels. - // I2. For all characters with an odd (right-to-left) embedding direction, those of type L, EN or AN go up one level. - for ($i=0; $i < $numchars; ++$i) { - $odd = $chardata[$i]['level'] % 2; - if ($odd) { - if (($chardata[$i]['type'] == 'L') OR ($chardata[$i]['type'] == 'AN') OR ($chardata[$i]['type'] == 'EN')) { - $chardata[$i]['level'] += 1; - } - } else { - if ($chardata[$i]['type'] == 'R') { - $chardata[$i]['level'] += 1; - } elseif (($chardata[$i]['type'] == 'AN') OR ($chardata[$i]['type'] == 'EN')) { - $chardata[$i]['level'] += 2; - } - } - $maxlevel = max($chardata[$i]['level'],$maxlevel); - } - - // L1. On each line, reset the embedding level of the following characters to the paragraph embedding level: - // 1. Segment separators, - // 2. Paragraph separators, - // 3. Any sequence of whitespace characters preceding a segment separator or paragraph separator, and - // 4. Any sequence of white space characters at the end of the line. - for ($i=0; $i < $numchars; ++$i) { - if (($chardata[$i]['type'] == 'B') OR ($chardata[$i]['type'] == 'S')) { - $chardata[$i]['level'] = $pel; - } elseif ($chardata[$i]['type'] == 'WS') { - $j = $i+1; - while ($j < $numchars) { - if ((($chardata[$j]['type'] == 'B') OR ($chardata[$j]['type'] == 'S')) OR - (($j == ($numchars-1)) AND ($chardata[$j]['type'] == 'WS'))) { - $chardata[$i]['level'] = $pel; - break; - } elseif ($chardata[$j]['type'] != 'WS') { - break; - } - ++$j; - } - } - } - - // Arabic Shaping - // Cursively connected scripts, such as Arabic or Syriac, require the selection of positional character shapes that depend on adjacent characters. Shaping is logically applied after the Bidirectional Algorithm is used and is limited to characters within the same directional run. - if ($arabic) { - $endedletter = array(1569,1570,1571,1572,1573,1575,1577,1583,1584,1585,1586,1608,1688); - $alfletter = array(1570,1571,1573,1575); - $chardata2 = $chardata; - $laaletter = false; - $charAL = array(); - $x = 0; - for ($i=0; $i < $numchars; ++$i) { - if ((TCPDF_FONT_DATA::$uni_type[$chardata[$i]['char']] == 'AL') OR ($chardata[$i]['char'] == 32) OR ($chardata[$i]['char'] == 8204)) { - $charAL[$x] = $chardata[$i]; - $charAL[$x]['i'] = $i; - $chardata[$i]['x'] = $x; - ++$x; - } - } - $numAL = $x; - for ($i=0; $i < $numchars; ++$i) { - $thischar = $chardata[$i]; - if ($i > 0) { - $prevchar = $chardata[($i-1)]; - } else { - $prevchar = false; - } - if (($i+1) < $numchars) { - $nextchar = $chardata[($i+1)]; - } else { - $nextchar = false; - } - if (TCPDF_FONT_DATA::$uni_type[$thischar['char']] == 'AL') { - $x = $thischar['x']; - if ($x > 0) { - $prevchar = $charAL[($x-1)]; - } else { - $prevchar = false; - } - if (($x+1) < $numAL) { - $nextchar = $charAL[($x+1)]; - } else { - $nextchar = false; - } - // if laa letter - if (($prevchar !== false) AND ($prevchar['char'] == 1604) AND (in_array($thischar['char'], $alfletter))) { - $arabicarr = TCPDF_FONT_DATA::$uni_laa_array; - $laaletter = true; - if ($x > 1) { - $prevchar = $charAL[($x-2)]; - } else { - $prevchar = false; - } - } else { - $arabicarr = TCPDF_FONT_DATA::$uni_arabicsubst; - $laaletter = false; - } - if (($prevchar !== false) AND ($nextchar !== false) AND - ((TCPDF_FONT_DATA::$uni_type[$prevchar['char']] == 'AL') OR (TCPDF_FONT_DATA::$uni_type[$prevchar['char']] == 'NSM')) AND - ((TCPDF_FONT_DATA::$uni_type[$nextchar['char']] == 'AL') OR (TCPDF_FONT_DATA::$uni_type[$nextchar['char']] == 'NSM')) AND - ($prevchar['type'] == $thischar['type']) AND - ($nextchar['type'] == $thischar['type']) AND - ($nextchar['char'] != 1567)) { - if (in_array($prevchar['char'], $endedletter)) { - if (isset($arabicarr[$thischar['char']][2])) { - // initial - $chardata2[$i]['char'] = $arabicarr[$thischar['char']][2]; - } - } else { - if (isset($arabicarr[$thischar['char']][3])) { - // medial - $chardata2[$i]['char'] = $arabicarr[$thischar['char']][3]; - } - } - } elseif (($nextchar !== false) AND - ((TCPDF_FONT_DATA::$uni_type[$nextchar['char']] == 'AL') OR (TCPDF_FONT_DATA::$uni_type[$nextchar['char']] == 'NSM')) AND - ($nextchar['type'] == $thischar['type']) AND - ($nextchar['char'] != 1567)) { - if (isset($arabicarr[$chardata[$i]['char']][2])) { - // initial - $chardata2[$i]['char'] = $arabicarr[$thischar['char']][2]; - } - } elseif ((($prevchar !== false) AND - ((TCPDF_FONT_DATA::$uni_type[$prevchar['char']] == 'AL') OR (TCPDF_FONT_DATA::$uni_type[$prevchar['char']] == 'NSM')) AND - ($prevchar['type'] == $thischar['type'])) OR - (($nextchar !== false) AND ($nextchar['char'] == 1567))) { - // final - if (($i > 1) AND ($thischar['char'] == 1607) AND - ($chardata[$i-1]['char'] == 1604) AND - ($chardata[$i-2]['char'] == 1604)) { - //Allah Word - // mark characters to delete with false - $chardata2[$i-2]['char'] = false; - $chardata2[$i-1]['char'] = false; - $chardata2[$i]['char'] = 65010; - } else { - if (($prevchar !== false) AND in_array($prevchar['char'], $endedletter)) { - if (isset($arabicarr[$thischar['char']][0])) { - // isolated - $chardata2[$i]['char'] = $arabicarr[$thischar['char']][0]; - } - } else { - if (isset($arabicarr[$thischar['char']][1])) { - // final - $chardata2[$i]['char'] = $arabicarr[$thischar['char']][1]; - } - } - } - } elseif (isset($arabicarr[$thischar['char']][0])) { - // isolated - $chardata2[$i]['char'] = $arabicarr[$thischar['char']][0]; - } - // if laa letter - if ($laaletter) { - // mark characters to delete with false - $chardata2[($charAL[($x-1)]['i'])]['char'] = false; - } - } // end if AL (Arabic Letter) - } // end for each char - /* - * Combining characters that can occur with Arabic Shadda (0651 HEX, 1617 DEC) are replaced. - * Putting the combining mark and shadda in the same glyph allows us to avoid the two marks overlapping each other in an illegible manner. - */ - for ($i = 0; $i < ($numchars-1); ++$i) { - if (($chardata2[$i]['char'] == 1617) AND (isset(TCPDF_FONT_DATA::$uni_diacritics[($chardata2[$i+1]['char'])]))) { - // check if the subtitution font is defined on current font - if (isset($currentfont['cw'][(TCPDF_FONT_DATA::$uni_diacritics[($chardata2[$i+1]['char'])])])) { - $chardata2[$i]['char'] = false; - $chardata2[$i+1]['char'] = TCPDF_FONT_DATA::$uni_diacritics[($chardata2[$i+1]['char'])]; - } - } - } - // remove marked characters - foreach ($chardata2 as $key => $value) { - if ($value['char'] === false) { - unset($chardata2[$key]); - } - } - $chardata = array_values($chardata2); - $numchars = count($chardata); - unset($chardata2); - unset($arabicarr); - unset($laaletter); - unset($charAL); - } - - // L2. From the highest level found in the text to the lowest odd level on each line, including intermediate levels not actually present in the text, reverse any contiguous sequence of characters that are at that level or higher. - for ($j=$maxlevel; $j > 0; $j--) { - $ordarray = Array(); - $revarr = Array(); - $onlevel = false; - for ($i=0; $i < $numchars; ++$i) { - if ($chardata[$i]['level'] >= $j) { - $onlevel = true; - if (isset(TCPDF_FONT_DATA::$uni_mirror[$chardata[$i]['char']])) { - // L4. A character is depicted by a mirrored glyph if and only if (a) the resolved directionality of that character is R, and (b) the Bidi_Mirrored property value of that character is true. - $chardata[$i]['char'] = TCPDF_FONT_DATA::$uni_mirror[$chardata[$i]['char']]; - } - $revarr[] = $chardata[$i]; - } else { - if ($onlevel) { - $revarr = array_reverse($revarr); - $ordarray = array_merge($ordarray, $revarr); - $revarr = Array(); - $onlevel = false; - } - $ordarray[] = $chardata[$i]; - } - } - if ($onlevel) { - $revarr = array_reverse($revarr); - $ordarray = array_merge($ordarray, $revarr); - } - $chardata = $ordarray; - } - $ordarray = array(); - foreach ($chardata as $cd) { - $ordarray[] = $cd['char']; - // store char values for subsetting - $currentfont['subsetchars'][$cd['char']] = true; - } - return $ordarray; - } - -} // END OF TCPDF_FONTS CLASS - -//============================================================+ -// END OF FILE -//============================================================+ diff --git a/lib/combodo/tcpdf/include/tcpdf_images.php b/lib/combodo/tcpdf/include/tcpdf_images.php deleted file mode 100644 index 6f2860c60..000000000 --- a/lib/combodo/tcpdf/include/tcpdf_images.php +++ /dev/null @@ -1,359 +0,0 @@ -<?php -//============================================================+ -// File name : tcpdf_images.php -// Version : 1.0.005 -// Begin : 2002-08-03 -// Last Update : 2014-11-15 -// Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com -// License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html) -// ------------------------------------------------------------------- -// Copyright (C) 2002-2014 Nicola Asuni - Tecnick.com LTD -// -// This file is part of TCPDF software library. -// -// TCPDF is free software: you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// TCPDF is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// -// You should have received a copy of the License -// along with TCPDF. If not, see -// <http://www.tecnick.com/pagefiles/tcpdf/LICENSE.TXT>. -// -// See LICENSE.TXT file for more information. -// ------------------------------------------------------------------- -// -// Description : -// Static image methods used by the TCPDF class. -// -//============================================================+ - -/** - * @file - * This is a PHP class that contains static image methods for the TCPDF class.<br> - * @package com.tecnick.tcpdf - * @author Nicola Asuni - * @version 1.0.005 - */ - -/** - * @class TCPDF_IMAGES - * Static image methods used by the TCPDF class. - * @package com.tecnick.tcpdf - * @brief PHP class for generating PDF documents without requiring external extensions. - * @version 1.0.005 - * @author Nicola Asuni - info@tecnick.com - */ -class TCPDF_IMAGES { - - /** - * Array of hinheritable SVG properties. - * @since 5.0.000 (2010-05-02) - * @public static - * - * @var string[] - */ - public static $svginheritprop = array('clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cursor', 'direction', 'display', 'fill', 'fill-opacity', 'fill-rule', 'font', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'glyph-orientation-horizontal', 'glyph-orientation-vertical', 'image-rendering', 'kerning', 'letter-spacing', 'marker', 'marker-end', 'marker-mid', 'marker-start', 'pointer-events', 'shape-rendering', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'text-anchor', 'text-rendering', 'visibility', 'word-spacing', 'writing-mode'); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /** - * Return the image type given the file name or array returned by getimagesize() function. - * @param string $imgfile image file name - * @param array $iminfo array of image information returned by getimagesize() function. - * @return string image type - * @since 4.8.017 (2009-11-27) - * @public static - */ - public static function getImageFileType($imgfile, $iminfo=array()) { - $type = ''; - if (isset($iminfo['mime']) AND !empty($iminfo['mime'])) { - $mime = explode('/', $iminfo['mime']); - if ((count($mime) > 1) AND ($mime[0] == 'image') AND (!empty($mime[1]))) { - $type = strtolower(trim($mime[1])); - } - } - if (empty($type)) { - $type = strtolower(trim(pathinfo(parse_url($imgfile, PHP_URL_PATH), PATHINFO_EXTENSION))); - } - if ($type == 'jpg') { - $type = 'jpeg'; - } - return $type; - } - - /** - * Set the transparency for the given GD image. - * @param resource $new_image GD image object - * @param resource $image GD image object. - * @return resource GD image object $new_image - * @since 4.9.016 (2010-04-20) - * @public static - */ - public static function setGDImageTransparency($new_image, $image) { - // default transparency color (white) - $tcol = array('red' => 255, 'green' => 255, 'blue' => 255); - // transparency index - $tid = imagecolortransparent($image); - $palletsize = imagecolorstotal($image); - if (($tid >= 0) AND ($tid < $palletsize)) { - // get the colors for the transparency index - $tcol = imagecolorsforindex($image, $tid); - } - $tid = imagecolorallocate($new_image, $tcol['red'], $tcol['green'], $tcol['blue']); - imagefill($new_image, 0, 0, $tid); - imagecolortransparent($new_image, $tid); - return $new_image; - } - - /** - * Convert the loaded image to a PNG and then return a structure for the PDF creator. - * This function requires GD library and write access to the directory defined on K_PATH_CACHE constant. - * @param resource $image Image object. - * @param string $tempfile Temporary file name. - * return image PNG image object. - * @since 4.9.016 (2010-04-20) - * @public static - */ - public static function _toPNG($image, $tempfile) { - // turn off interlaced mode - imageinterlace($image, 0); - // create temporary PNG image - imagepng($image, $tempfile); - // remove image from memory - imagedestroy($image); - // get PNG image data - $retvars = self::_parsepng($tempfile); - // tidy up by removing temporary image - unlink($tempfile); - return $retvars; - } - - /** - * Convert the loaded image to a JPEG and then return a structure for the PDF creator. - * This function requires GD library and write access to the directory defined on K_PATH_CACHE constant. - * @param resource $image Image object. - * @param int $quality JPEG quality. - * @param string $tempfile Temporary file name. - * return array|false image JPEG image object. - * @public static - */ - public static function _toJPEG($image, $quality, $tempfile) { - imagejpeg($image, $tempfile, $quality); - imagedestroy($image); - $retvars = self::_parsejpeg($tempfile); - // tidy up by removing temporary image - unlink($tempfile); - return $retvars; - } - - /** - * Extract info from a JPEG file without using the GD library. - * @param string $file image file to parse - * @return array|false structure containing the image data - * @public static - */ - public static function _parsejpeg($file) { - // check if is a local file - if (!@TCPDF_STATIC::file_exists($file)) { - return false; - } - $a = getimagesize($file); - if (empty($a)) { - //Missing or incorrect image file - return false; - } - if ($a[2] != 2) { - // Not a JPEG file - return false; - } - // bits per pixel - $bpc = isset($a['bits']) ? intval($a['bits']) : 8; - // number of image channels - if (!isset($a['channels'])) { - $channels = 3; - } else { - $channels = intval($a['channels']); - } - // default colour space - switch ($channels) { - case 1: { - $colspace = 'DeviceGray'; - break; - } - case 3: { - $colspace = 'DeviceRGB'; - break; - } - case 4: { - $colspace = 'DeviceCMYK'; - break; - } - default: { - $channels = 3; - $colspace = 'DeviceRGB'; - break; - } - } - // get file content - $data = file_get_contents($file); - // check for embedded ICC profile - $icc = array(); - $offset = 0; - while (($pos = strpos($data, "ICC_PROFILE\0", $offset)) !== false) { - // get ICC sequence length - $length = (TCPDF_STATIC::_getUSHORT($data, ($pos - 2)) - 16); - // marker sequence number - $msn = max(1, ord($data[($pos + 12)])); - // number of markers (total of APP2 used) - $nom = max(1, ord($data[($pos + 13)])); - // get sequence segment - $icc[($msn - 1)] = substr($data, ($pos + 14), $length); - // move forward to next sequence - $offset = ($pos + 14 + $length); - } - // order and compact ICC segments - if (count($icc) > 0) { - ksort($icc); - $icc = implode('', $icc); - if ((ord($icc[36]) != 0x61) OR (ord($icc[37]) != 0x63) OR (ord($icc[38]) != 0x73) OR (ord($icc[39]) != 0x70)) { - // invalid ICC profile - $icc = false; - } - } else { - $icc = false; - } - return array('w' => $a[0], 'h' => $a[1], 'ch' => $channels, 'icc' => $icc, 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'DCTDecode', 'data' => $data); - } - - /** - * Extract info from a PNG file without using the GD library. - * @param string $file image file to parse - * @return array|false structure containing the image data - * @public static - */ - public static function _parsepng($file) { - $f = @fopen($file, 'rb'); - if ($f === false) { - // Can't open image file - return false; - } - //Check signature - if (fread($f, 8) != chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) { - // Not a PNG file - return false; - } - //Read header chunk - fread($f, 4); - if (fread($f, 4) != 'IHDR') { - //Incorrect PNG file - return false; - } - $w = TCPDF_STATIC::_freadint($f); - $h = TCPDF_STATIC::_freadint($f); - $bpc = ord(fread($f, 1)); - $ct = ord(fread($f, 1)); - if ($ct == 0) { - $colspace = 'DeviceGray'; - } elseif ($ct == 2) { - $colspace = 'DeviceRGB'; - } elseif ($ct == 3) { - $colspace = 'Indexed'; - } else { - // alpha channel - fclose($f); - return 'pngalpha'; - } - if (ord(fread($f, 1)) != 0) { - // Unknown compression method - fclose($f); - return false; - } - if (ord(fread($f, 1)) != 0) { - // Unknown filter method - fclose($f); - return false; - } - if (ord(fread($f, 1)) != 0) { - // Interlacing not supported - fclose($f); - return false; - } - fread($f, 4); - $channels = ($ct == 2 ? 3 : 1); - $parms = '/DecodeParms << /Predictor 15 /Colors '.$channels.' /BitsPerComponent '.$bpc.' /Columns '.$w.' >>'; - //Scan chunks looking for palette, transparency and image data - $pal = ''; - $trns = ''; - $data = ''; - $icc = false; - $n = TCPDF_STATIC::_freadint($f); - do { - $type = fread($f, 4); - if ($type == 'PLTE') { - // read palette - $pal = TCPDF_STATIC::rfread($f, $n); - fread($f, 4); - } elseif ($type == 'tRNS') { - // read transparency info - $t = TCPDF_STATIC::rfread($f, $n); - if ($ct == 0) { // DeviceGray - $trns = array(ord($t[1])); - } elseif ($ct == 2) { // DeviceRGB - $trns = array(ord($t[1]), ord($t[3]), ord($t[5])); - } else { // Indexed - if ($n > 0) { - $trns = array(); - for ($i = 0; $i < $n; ++ $i) { - $trns[] = ord($t[$i]); - } - } - } - fread($f, 4); - } elseif ($type == 'IDAT') { - // read image data block - $data .= TCPDF_STATIC::rfread($f, $n); - fread($f, 4); - } elseif ($type == 'iCCP') { - // skip profile name - $len = 0; - while ((ord(fread($f, 1)) != 0) AND ($len < 80)) { - ++$len; - } - // get compression method - if (ord(fread($f, 1)) != 0) { - // Unknown filter method - fclose($f); - return false; - } - // read ICC Color Profile - $icc = TCPDF_STATIC::rfread($f, ($n - $len - 2)); - // decompress profile - $icc = gzuncompress($icc); - fread($f, 4); - } elseif ($type == 'IEND') { - break; - } else { - TCPDF_STATIC::rfread($f, $n + 4); - } - $n = TCPDF_STATIC::_freadint($f); - } while ($n); - if (($colspace == 'Indexed') AND (empty($pal))) { - // Missing palette - fclose($f); - return false; - } - fclose($f); - return array('w' => $w, 'h' => $h, 'ch' => $channels, 'icc' => $icc, 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'FlateDecode', 'parms' => $parms, 'pal' => $pal, 'trns' => $trns, 'data' => $data); - } - -} // END OF TCPDF_IMAGES CLASS - -//============================================================+ -// END OF FILE -//============================================================+ diff --git a/lib/combodo/tcpdf/include/tcpdf_static.php b/lib/combodo/tcpdf/include/tcpdf_static.php deleted file mode 100644 index a118d0588..000000000 --- a/lib/combodo/tcpdf/include/tcpdf_static.php +++ /dev/null @@ -1,2669 +0,0 @@ -<?php -//============================================================+ -// File name : tcpdf_static.php -// Version : 1.1.4 -// Begin : 2002-08-03 -// Last Update : 2019-11-01 -// Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com -// License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html) -// ------------------------------------------------------------------- -// Copyright (C) 2002-2021 Nicola Asuni - Tecnick.com LTD -// -// This file is part of TCPDF software library. -// -// TCPDF is free software: you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// TCPDF is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// -// You should have received a copy of the License -// along with TCPDF. If not, see -// <http://www.tecnick.com/pagefiles/tcpdf/LICENSE.TXT>. -// -// See LICENSE.TXT file for more information. -// ------------------------------------------------------------------- -// -// Description : -// Static methods used by the TCPDF class. -// -//============================================================+ - -/** - * @file - * This is a PHP class that contains static methods for the TCPDF class.<br> - * @package com.tecnick.tcpdf - * @author Nicola Asuni - * @version 1.1.2 - */ - -/** - * @class TCPDF_STATIC - * Static methods used by the TCPDF class. - * @package com.tecnick.tcpdf - * @brief PHP class for generating PDF documents without requiring external extensions. - * @version 1.1.1 - * @author Nicola Asuni - info@tecnick.com - */ -class TCPDF_STATIC { - - /** - * Current TCPDF version. - * @private static - */ - private static $tcpdf_version = '6.4.4'; - - /** - * String alias for total number of pages. - * @public static - */ - public static $alias_tot_pages = '{:ptp:}'; - - /** - * String alias for page number. - * @public static - */ - public static $alias_num_page = '{:pnp:}'; - - /** - * String alias for total number of pages in a single group. - * @public static - */ - public static $alias_group_tot_pages = '{:ptg:}'; - - /** - * String alias for group page number. - * @public static - */ - public static $alias_group_num_page = '{:png:}'; - - /** - * String alias for right shift compensation used to correctly align page numbers on the right. - * @public static - */ - public static $alias_right_shift = '{rsc:'; - - /** - * Encryption padding string. - * @public static - */ - public static $enc_padding = "\x28\xBF\x4E\x5E\x4E\x75\x8A\x41\x64\x00\x4E\x56\xFF\xFA\x01\x08\x2E\x2E\x00\xB6\xD0\x68\x3E\x80\x2F\x0C\xA9\xFE\x64\x53\x69\x7A"; - - /** - * ByteRange placemark used during digital signature process. - * @since 4.6.028 (2009-08-25) - * @public static - */ - public static $byterange_string = '/ByteRange[0 ********** ********** **********]'; - - /** - * Array page boxes names - * @public static - */ - public static $pageboxes = array('MediaBox', 'CropBox', 'BleedBox', 'TrimBox', 'ArtBox'); - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /** - * Return the current TCPDF version. - * @return string TCPDF version string - * @since 5.9.012 (2010-11-10) - * @public static - */ - public static function getTCPDFVersion() { - return self::$tcpdf_version; - } - - /** - * Return the current TCPDF producer. - * @return string TCPDF producer string - * @since 6.0.000 (2013-03-16) - * @public static - */ - public static function getTCPDFProducer() { - return "\x54\x43\x50\x44\x46\x20".self::getTCPDFVersion()."\x20\x28\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x74\x63\x70\x64\x66\x2e\x6f\x72\x67\x29"; - } - - /** - * Sets the current active configuration setting of magic_quotes_runtime (if the set_magic_quotes_runtime function exist) - * @param boolean $mqr FALSE for off, TRUE for on. - * @since 4.6.025 (2009-08-17) - * @public static - */ - public static function set_mqr($mqr) { - if (!defined('PHP_VERSION_ID')) { - $version = PHP_VERSION; - define('PHP_VERSION_ID', (($version[0] * 10000) + ($version[2] * 100) + $version[4])); - } - if (PHP_VERSION_ID < 50300) { - @set_magic_quotes_runtime($mqr); - } - } - - /** - * Gets the current active configuration setting of magic_quotes_runtime (if the get_magic_quotes_runtime function exist) - * @return int Returns 0 if magic quotes runtime is off or get_magic_quotes_runtime doesn't exist, 1 otherwise. - * @since 4.6.025 (2009-08-17) - * @public static - */ - public static function get_mqr() { - if (!defined('PHP_VERSION_ID')) { - $version = PHP_VERSION; - define('PHP_VERSION_ID', (($version[0] * 10000) + ($version[2] * 100) + $version[4])); - } - if (PHP_VERSION_ID < 50300) { - return @get_magic_quotes_runtime(); - } - return 0; - } - - /** - * Check if the URL exist. - * @param string $url URL to check. - * @return boolean true if the URl exist, false otherwise. - * @since 5.9.204 (2013-01-28) - * @public static - */ - public static function isValidURL($url) { - $headers = @get_headers($url); - if ($headers === false) { - return false; - } - return (strpos($headers[0], '200') !== false); - } - - /** - * Removes SHY characters from text. - * Unicode Data:<ul> - * <li>Name : SOFT HYPHEN, commonly abbreviated as SHY</li> - * <li>HTML Entity (decimal): "&amp;#173;"</li> - * <li>HTML Entity (hex): "&amp;#xad;"</li> - * <li>HTML Entity (named): "&amp;shy;"</li> - * <li>How to type in Microsoft Windows: [Alt +00AD] or [Alt 0173]</li> - * <li>UTF-8 (hex): 0xC2 0xAD (c2ad)</li> - * <li>UTF-8 character: chr(194).chr(173)</li> - * </ul> - * @param string $txt input string - * @param boolean $unicode True if we are in unicode mode, false otherwise. - * @return string without SHY characters. - * @since (4.5.019) 2009-02-28 - * @public static - */ - public static function removeSHY($txt='', $unicode=true) { - $txt = preg_replace('/([\\xc2]{1}[\\xad]{1})/', '', $txt); - if (!$unicode) { - $txt = preg_replace('/([\\xad]{1})/', '', $txt); - } - return $txt; - } - - - /** - * Get the border mode accounting for multicell position (opens bottom side of multicell crossing pages) - * @param string|array|int $brd Indicates if borders must be drawn around the cell block. The value can be a number:<ul><li>0: no border (default)</li><li>1: frame</li></ul>or a string containing some or all of the following characters (in any order):<ul><li>L: left</li><li>T: top</li><li>R: right</li><li>B: bottom</li></ul> or an array of line styles for each border group: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - * @param string $position multicell position: 'start', 'middle', 'end' - * @param boolean $opencell True when the cell is left open at the page bottom, false otherwise. - * @return array border mode array - * @since 4.4.002 (2008-12-09) - * @public static - */ - public static function getBorderMode($brd, $position='start', $opencell=true) { - if ((!$opencell) OR empty($brd)) { - return $brd; - } - if ($brd == 1) { - $brd = 'LTRB'; - } - if (is_string($brd)) { - // convert string to array - $slen = strlen($brd); - $newbrd = array(); - for ($i = 0; $i < $slen; ++$i) { - $newbrd[$brd[$i]] = array('cap' => 'square', 'join' => 'miter'); - } - $brd = $newbrd; - } - foreach ($brd as $border => $style) { - switch ($position) { - case 'start': { - if (strpos($border, 'B') !== false) { - // remove bottom line - $newkey = str_replace('B', '', $border); - if (strlen($newkey) > 0) { - $brd[$newkey] = $style; - } - unset($brd[$border]); - } - break; - } - case 'middle': { - if (strpos($border, 'B') !== false) { - // remove bottom line - $newkey = str_replace('B', '', $border); - if (strlen($newkey) > 0) { - $brd[$newkey] = $style; - } - unset($brd[$border]); - $border = $newkey; - } - if (strpos($border, 'T') !== false) { - // remove bottom line - $newkey = str_replace('T', '', $border); - if (strlen($newkey) > 0) { - $brd[$newkey] = $style; - } - unset($brd[$border]); - } - break; - } - case 'end': { - if (strpos($border, 'T') !== false) { - // remove bottom line - $newkey = str_replace('T', '', $border); - if (strlen($newkey) > 0) { - $brd[$newkey] = $style; - } - unset($brd[$border]); - } - break; - } - } - } - return $brd; - } - - /** - * Determine whether a string is empty. - * @param string $str string to be checked - * @return bool true if string is empty - * @since 4.5.044 (2009-04-16) - * @public static - */ - public static function empty_string($str) { - return (is_null($str) OR (is_string($str) AND (strlen($str) == 0))); - } - - /** - * Returns a temporary filename for caching object on filesystem. - * @param string $type Type of file (name of the subdir on the tcpdf cache folder). - * @param string $file_id TCPDF file_id. - * @return string filename. - * @since 4.5.000 (2008-12-31) - * @public static - */ - public static function getObjFilename($type='tmp', $file_id='') { - return tempnam(K_PATH_CACHE, '__tcpdf_'.$file_id.'_'.$type.'_'.md5(TCPDF_STATIC::getRandomSeed()).'_'); - } - - /** - * Add "\" before "\", "(" and ")" - * @param string $s string to escape. - * @return string escaped string. - * @public static - */ - public static function _escape($s) { - // the chr(13) substitution fixes the Bugs item #1421290. - return strtr($s, array(')' => '\\)', '(' => '\\(', '\\' => '\\\\', chr(13) => '\r')); - } - - /** - * Escape some special characters (&lt; &gt; &amp;) for XML output. - * @param string $str Input string to convert. - * @return string converted string - * @since 5.9.121 (2011-09-28) - * @public static - */ - public static function _escapeXML($str) { - $replaceTable = array("\0" => '', '&' => '&amp;', '<' => '&lt;', '>' => '&gt;'); - $str = strtr($str, $replaceTable); - return $str; - } - - /** - * Creates a copy of a class object - * @param object $object class object to be cloned - * @return object cloned object - * @since 4.5.029 (2009-03-19) - * @public static - */ - public static function objclone($object) { - if (($object instanceof Imagick) AND (version_compare(phpversion('imagick'), '3.0.1') !== 1)) { - // on the versions after 3.0.1 the clone() method was deprecated in favour of clone keyword - return @$object->clone(); - } - return @clone($object); - } - - /** - * Output input data and compress it if possible. - * @param string $data Data to output. - * @param int $length Data length in bytes. - * @since 5.9.086 - * @public static - */ - public static function sendOutputData($data, $length) { - if (!isset($_SERVER['HTTP_ACCEPT_ENCODING']) OR empty($_SERVER['HTTP_ACCEPT_ENCODING'])) { - // the content length may vary if the server is using compression - header('Content-Length: '.$length); - } - echo $data; - } - - /** - * Replace page number aliases with number. - * @param string $page Page content. - * @param array $replace Array of replacements (array keys are replacement strings, values are alias arrays). - * @param int $diff If passed, this will be set to the total char number difference between alias and replacements. - * @return array replaced page content and updated $diff parameter as array. - * @public static - */ - public static function replacePageNumAliases($page, $replace, $diff=0) { - foreach ($replace as $rep) { - foreach ($rep[3] as $a) { - if (strpos($page, $a) !== false) { - $page = str_replace($a, $rep[0], $page); - $diff += ($rep[2] - $rep[1]); - } - } - } - return array($page, $diff); - } - - /** - * Returns timestamp in seconds from formatted date-time. - * @param string $date Formatted date-time. - * @return int seconds. - * @since 5.9.152 (2012-03-23) - * @public static - */ - public static function getTimestamp($date) { - if (($date[0] == 'D') AND ($date[1] == ':')) { - // remove date prefix if present - $date = substr($date, 2); - } - return strtotime($date); - } - - /** - * Returns a formatted date-time. - * @param int $time Time in seconds. - * @return string escaped date string. - * @since 5.9.152 (2012-03-23) - * @public static - */ - public static function getFormattedDate($time) { - return substr_replace(date('YmdHisO', intval($time)), '\'', (0 - 2), 0).'\''; - } - - /** - * Returns a string containing random data to be used as a seed for encryption methods. - * @param string $seed starting seed value - * @return string containing random data - * @author Nicola Asuni - * @since 5.9.006 (2010-10-19) - * @public static - */ - public static function getRandomSeed($seed='') { - $rnd = uniqid(rand().microtime(true), true); - if (function_exists('posix_getpid')) { - $rnd .= posix_getpid(); - } - if (function_exists('openssl_random_pseudo_bytes') AND (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')) { - // this is not used on windows systems because it is very slow for a know bug - $rnd .= openssl_random_pseudo_bytes(512); - } else { - for ($i = 0; $i < 23; ++$i) { - $rnd .= uniqid('', true); - } - } - return $rnd.$seed.__FILE__.serialize($_SERVER).microtime(true); - } - - /** - * Encrypts a string using MD5 and returns it's value as a binary string. - * @param string $str input string - * @return string MD5 encrypted binary string - * @since 2.0.000 (2008-01-02) - * @public static - */ - public static function _md5_16($str) { - return pack('H*', md5($str)); - } - - /** - * Returns the input text encrypted using AES algorithm and the specified key. - * This method requires openssl or mcrypt. Text is padded to 16bytes blocks - * @param string $key encryption key - * @param string $text input text to be encrypted - * @return string encrypted text - * @author Nicola Asuni - * @since 5.0.005 (2010-05-11) - * @public static - */ - public static function _AES($key, $text) { - // padding (RFC 2898, PKCS #5: Password-Based Cryptography Specification Version 2.0) - $padding = 16 - (strlen($text) % 16); - $text .= str_repeat(chr($padding), $padding); - if (extension_loaded('openssl')) { - $algo = 'aes-256-cbc'; - if (strlen($key) == 16) { - $algo = 'aes-128-cbc'; - } - $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($algo)); - $text = openssl_encrypt($text, $algo, $key, OPENSSL_RAW_DATA, $iv); - return $iv.substr($text, 0, -16); - } - $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_RAND); - $text = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv); - $text = $iv.$text; - return $text; - } - - /** - * Returns the input text encrypted using AES algorithm and the specified key. - * This method requires openssl or mcrypt. Text is not padded - * @param string $key encryption key - * @param string $text input text to be encrypted - * @return string encrypted text - * @author Nicola Asuni - * @since TODO - * @public static - */ - public static function _AESnopad($key, $text) { - if (extension_loaded('openssl')) { - $algo = 'aes-256-cbc'; - if (strlen($key) == 16) { - $algo = 'aes-128-cbc'; - } - $iv = str_repeat("\x00", openssl_cipher_iv_length($algo)); - $text = openssl_encrypt($text, $algo, $key, OPENSSL_RAW_DATA, $iv); - return substr($text, 0, -16); - } - $iv = str_repeat("\x00", mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC)); - $text = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv); - return $text; - } - - /** - * Returns the input text encrypted using RC4 algorithm and the specified key. - * RC4 is the standard encryption algorithm used in PDF format - * @param string $key Encryption key. - * @param string $text Input text to be encrypted. - * @param string $last_enc_key Reference to last RC4 key encrypted. - * @param string $last_enc_key_c Reference to last RC4 computed key. - * @return string encrypted text - * @since 2.0.000 (2008-01-02) - * @author Klemen Vodopivec, Nicola Asuni - * @public static - */ - public static function _RC4($key, $text, &$last_enc_key, &$last_enc_key_c) { - if (function_exists('mcrypt_encrypt') AND ($out = @mcrypt_encrypt(MCRYPT_ARCFOUR, $key, $text, MCRYPT_MODE_STREAM, ''))) { - // try to use mcrypt function if exist - return $out; - } - if ($last_enc_key != $key) { - $k = str_repeat($key, (int) ((256 / strlen($key)) + 1)); - $rc4 = range(0, 255); - $j = 0; - for ($i = 0; $i < 256; ++$i) { - $t = $rc4[$i]; - $j = ($j + $t + ord($k[$i])) % 256; - $rc4[$i] = $rc4[$j]; - $rc4[$j] = $t; - } - $last_enc_key = $key; - $last_enc_key_c = $rc4; - } else { - $rc4 = $last_enc_key_c; - } - $len = strlen($text); - $a = 0; - $b = 0; - $out = ''; - for ($i = 0; $i < $len; ++$i) { - $a = ($a + 1) % 256; - $t = $rc4[$a]; - $b = ($b + $t) % 256; - $rc4[$a] = $rc4[$b]; - $rc4[$b] = $t; - $k = $rc4[($rc4[$a] + $rc4[$b]) % 256]; - $out .= chr(ord($text[$i]) ^ $k); - } - return $out; - } - - /** - * Return the permission code used on encryption (P value). - * @param array $permissions the set of permissions (specify the ones you want to block). - * @param int $mode encryption strength: 0 = RC4 40 bit; 1 = RC4 128 bit; 2 = AES 128 bit; 3 = AES 256 bit. - * @since 5.0.005 (2010-05-12) - * @author Nicola Asuni - * @public static - */ - public static function getUserPermissionCode($permissions, $mode=0) { - $options = array( - 'owner' => 2, // bit 2 -- inverted logic: cleared by default - 'print' => 4, // bit 3 - 'modify' => 8, // bit 4 - 'copy' => 16, // bit 5 - 'annot-forms' => 32, // bit 6 - 'fill-forms' => 256, // bit 9 - 'extract' => 512, // bit 10 - 'assemble' => 1024,// bit 11 - 'print-high' => 2048 // bit 12 - ); - $protection = 2147422012; // 32 bit: (01111111 11111111 00001111 00111100) - foreach ($permissions as $permission) { - if (isset($options[$permission])) { - if (($mode > 0) OR ($options[$permission] <= 32)) { - // set only valid permissions - if ($options[$permission] == 2) { - // the logic for bit 2 is inverted (cleared by default) - $protection += $options[$permission]; - } else { - $protection -= $options[$permission]; - } - } - } - } - return $protection; - } - - /** - * Convert hexadecimal string to string - * @param string $bs byte-string to convert - * @return string - * @since 5.0.005 (2010-05-12) - * @author Nicola Asuni - * @public static - */ - public static function convertHexStringToString($bs) { - $string = ''; // string to be returned - $bslength = strlen($bs); - if (($bslength % 2) != 0) { - // padding - $bs .= '0'; - ++$bslength; - } - for ($i = 0; $i < $bslength; $i += 2) { - $string .= chr(hexdec($bs[$i].$bs[($i + 1)])); - } - return $string; - } - - /** - * Convert string to hexadecimal string (byte string) - * @param string $s string to convert - * @return string byte string - * @since 5.0.010 (2010-05-17) - * @author Nicola Asuni - * @public static - */ - public static function convertStringToHexString($s) { - $bs = ''; - $chars = preg_split('//', $s, -1, PREG_SPLIT_NO_EMPTY); - foreach ($chars as $c) { - $bs .= sprintf('%02s', dechex(ord($c))); - } - return $bs; - } - - /** - * Convert encryption P value to a string of bytes, low-order byte first. - * @param string $protection 32bit encryption permission value (P value) - * @return string - * @since 5.0.005 (2010-05-12) - * @author Nicola Asuni - * @public static - */ - public static function getEncPermissionsString($protection) { - $binprot = sprintf('%032b', $protection); - $str = chr(bindec(substr($binprot, 24, 8))); - $str .= chr(bindec(substr($binprot, 16, 8))); - $str .= chr(bindec(substr($binprot, 8, 8))); - $str .= chr(bindec(substr($binprot, 0, 8))); - return $str; - } - - /** - * Encode a name object. - * @param string $name Name object to encode. - * @return string Encoded name object. - * @author Nicola Asuni - * @since 5.9.097 (2011-06-23) - * @public static - */ - public static function encodeNameObject($name) { - $escname = ''; - $length = strlen($name); - for ($i = 0; $i < $length; ++$i) { - $chr = $name[$i]; - if (preg_match('/[0-9a-zA-Z#_=-]/', $chr) == 1) { - $escname .= $chr; - } else { - $escname .= sprintf('#%02X', ord($chr)); - } - } - return $escname; - } - - /** - * Convert JavaScript form fields properties array to Annotation Properties array. - * @param array $prop javascript field properties. Possible values are described on official Javascript for Acrobat API reference. - * @param array $spot_colors Reference to spot colors array. - * @param boolean $rtl True if in Right-To-Left text direction mode, false otherwise. - * @return array of annotation properties - * @author Nicola Asuni - * @since 4.8.000 (2009-09-06) - * @public static - */ - public static function getAnnotOptFromJSProp($prop, &$spot_colors, $rtl=false) { - if (isset($prop['aopt']) AND is_array($prop['aopt'])) { - // the annotation options are already defined - return $prop['aopt']; - } - $opt = array(); // value to be returned - // alignment: Controls how the text is laid out within the text field. - if (isset($prop['alignment'])) { - switch ($prop['alignment']) { - case 'left': { - $opt['q'] = 0; - break; - } - case 'center': { - $opt['q'] = 1; - break; - } - case 'right': { - $opt['q'] = 2; - break; - } - default: { - $opt['q'] = ($rtl)?2:0; - break; - } - } - } - // lineWidth: Specifies the thickness of the border when stroking the perimeter of a field's rectangle. - if (isset($prop['lineWidth'])) { - $linewidth = intval($prop['lineWidth']); - } else { - $linewidth = 1; - } - // borderStyle: The border style for a field. - if (isset($prop['borderStyle'])) { - switch ($prop['borderStyle']) { - case 'border.d': - case 'dashed': { - $opt['border'] = array(0, 0, $linewidth, array(3, 2)); - $opt['bs'] = array('w'=>$linewidth, 's'=>'D', 'd'=>array(3, 2)); - break; - } - case 'border.b': - case 'beveled': { - $opt['border'] = array(0, 0, $linewidth); - $opt['bs'] = array('w'=>$linewidth, 's'=>'B'); - break; - } - case 'border.i': - case 'inset': { - $opt['border'] = array(0, 0, $linewidth); - $opt['bs'] = array('w'=>$linewidth, 's'=>'I'); - break; - } - case 'border.u': - case 'underline': { - $opt['border'] = array(0, 0, $linewidth); - $opt['bs'] = array('w'=>$linewidth, 's'=>'U'); - break; - } - case 'border.s': - case 'solid': { - $opt['border'] = array(0, 0, $linewidth); - $opt['bs'] = array('w'=>$linewidth, 's'=>'S'); - break; - } - default: { - break; - } - } - } - if (isset($prop['border']) AND is_array($prop['border'])) { - $opt['border'] = $prop['border']; - } - if (!isset($opt['mk'])) { - $opt['mk'] = array(); - } - if (!isset($opt['mk']['if'])) { - $opt['mk']['if'] = array(); - } - $opt['mk']['if']['a'] = array(0.5, 0.5); - // buttonAlignX: Controls how space is distributed from the left of the button face with respect to the icon. - if (isset($prop['buttonAlignX'])) { - $opt['mk']['if']['a'][0] = $prop['buttonAlignX']; - } - // buttonAlignY: Controls how unused space is distributed from the bottom of the button face with respect to the icon. - if (isset($prop['buttonAlignY'])) { - $opt['mk']['if']['a'][1] = $prop['buttonAlignY']; - } - // buttonFitBounds: If true, the extent to which the icon may be scaled is set to the bounds of the button field. - if (isset($prop['buttonFitBounds']) AND ($prop['buttonFitBounds'] == 'true')) { - $opt['mk']['if']['fb'] = true; - } - // buttonScaleHow: Controls how the icon is scaled (if necessary) to fit inside the button face. - if (isset($prop['buttonScaleHow'])) { - switch ($prop['buttonScaleHow']) { - case 'scaleHow.proportional': { - $opt['mk']['if']['s'] = 'P'; - break; - } - case 'scaleHow.anamorphic': { - $opt['mk']['if']['s'] = 'A'; - break; - } - } - } - // buttonScaleWhen: Controls when an icon is scaled to fit inside the button face. - if (isset($prop['buttonScaleWhen'])) { - switch ($prop['buttonScaleWhen']) { - case 'scaleWhen.always': { - $opt['mk']['if']['sw'] = 'A'; - break; - } - case 'scaleWhen.never': { - $opt['mk']['if']['sw'] = 'N'; - break; - } - case 'scaleWhen.tooBig': { - $opt['mk']['if']['sw'] = 'B'; - break; - } - case 'scaleWhen.tooSmall': { - $opt['mk']['if']['sw'] = 'S'; - break; - } - } - } - // buttonPosition: Controls how the text and the icon of the button are positioned with respect to each other within the button face. - if (isset($prop['buttonPosition'])) { - switch ($prop['buttonPosition']) { - case 0: - case 'position.textOnly': { - $opt['mk']['tp'] = 0; - break; - } - case 1: - case 'position.iconOnly': { - $opt['mk']['tp'] = 1; - break; - } - case 2: - case 'position.iconTextV': { - $opt['mk']['tp'] = 2; - break; - } - case 3: - case 'position.textIconV': { - $opt['mk']['tp'] = 3; - break; - } - case 4: - case 'position.iconTextH': { - $opt['mk']['tp'] = 4; - break; - } - case 5: - case 'position.textIconH': { - $opt['mk']['tp'] = 5; - break; - } - case 6: - case 'position.overlay': { - $opt['mk']['tp'] = 6; - break; - } - } - } - // fillColor: Specifies the background color for a field. - if (isset($prop['fillColor'])) { - if (is_array($prop['fillColor'])) { - $opt['mk']['bg'] = $prop['fillColor']; - } else { - $opt['mk']['bg'] = TCPDF_COLORS::convertHTMLColorToDec($prop['fillColor'], $spot_colors); - } - } - // strokeColor: Specifies the stroke color for a field that is used to stroke the rectangle of the field with a line as large as the line width. - if (isset($prop['strokeColor'])) { - if (is_array($prop['strokeColor'])) { - $opt['mk']['bc'] = $prop['strokeColor']; - } else { - $opt['mk']['bc'] = TCPDF_COLORS::convertHTMLColorToDec($prop['strokeColor'], $spot_colors); - } - } - // rotation: The rotation of a widget in counterclockwise increments. - if (isset($prop['rotation'])) { - $opt['mk']['r'] = $prop['rotation']; - } - // charLimit: Limits the number of characters that a user can type into a text field. - if (isset($prop['charLimit'])) { - $opt['maxlen'] = intval($prop['charLimit']); - } - if (!isset($ff)) { - $ff = 0; // default value - } - // readonly: The read-only characteristic of a field. If a field is read-only, the user can see the field but cannot change it. - if (isset($prop['readonly']) AND ($prop['readonly'] == 'true')) { - $ff += 1 << 0; - } - // required: Specifies whether a field requires a value. - if (isset($prop['required']) AND ($prop['required'] == 'true')) { - $ff += 1 << 1; - } - // multiline: Controls how text is wrapped within the field. - if (isset($prop['multiline']) AND ($prop['multiline'] == 'true')) { - $ff += 1 << 12; - } - // password: Specifies whether the field should display asterisks when data is entered in the field. - if (isset($prop['password']) AND ($prop['password'] == 'true')) { - $ff += 1 << 13; - } - // NoToggleToOff: If set, exactly one radio button shall be selected at all times; selecting the currently selected button has no effect. - if (isset($prop['NoToggleToOff']) AND ($prop['NoToggleToOff'] == 'true')) { - $ff += 1 << 14; - } - // Radio: If set, the field is a set of radio buttons. - if (isset($prop['Radio']) AND ($prop['Radio'] == 'true')) { - $ff += 1 << 15; - } - // Pushbutton: If set, the field is a pushbutton that does not retain a permanent value. - if (isset($prop['Pushbutton']) AND ($prop['Pushbutton'] == 'true')) { - $ff += 1 << 16; - } - // Combo: If set, the field is a combo box; if clear, the field is a list box. - if (isset($prop['Combo']) AND ($prop['Combo'] == 'true')) { - $ff += 1 << 17; - } - // editable: Controls whether a combo box is editable. - if (isset($prop['editable']) AND ($prop['editable'] == 'true')) { - $ff += 1 << 18; - } - // Sort: If set, the field's option items shall be sorted alphabetically. - if (isset($prop['Sort']) AND ($prop['Sort'] == 'true')) { - $ff += 1 << 19; - } - // fileSelect: If true, sets the file-select flag in the Options tab of the text field (Field is Used for File Selection). - if (isset($prop['fileSelect']) AND ($prop['fileSelect'] == 'true')) { - $ff += 1 << 20; - } - // multipleSelection: If true, indicates that a list box allows a multiple selection of items. - if (isset($prop['multipleSelection']) AND ($prop['multipleSelection'] == 'true')) { - $ff += 1 << 21; - } - // doNotSpellCheck: If true, spell checking is not performed on this editable text field. - if (isset($prop['doNotSpellCheck']) AND ($prop['doNotSpellCheck'] == 'true')) { - $ff += 1 << 22; - } - // doNotScroll: If true, the text field does not scroll and the user, therefore, is limited by the rectangular region designed for the field. - if (isset($prop['doNotScroll']) AND ($prop['doNotScroll'] == 'true')) { - $ff += 1 << 23; - } - // comb: If set to true, the field background is drawn as series of boxes (one for each character in the value of the field) and each character of the content is drawn within those boxes. The number of boxes drawn is determined from the charLimit property. It applies only to text fields. The setter will also raise if any of the following field properties are also set multiline, password, and fileSelect. A side-effect of setting this property is that the doNotScroll property is also set. - if (isset($prop['comb']) AND ($prop['comb'] == 'true')) { - $ff += 1 << 24; - } - // radiosInUnison: If false, even if a group of radio buttons have the same name and export value, they behave in a mutually exclusive fashion, like HTML radio buttons. - if (isset($prop['radiosInUnison']) AND ($prop['radiosInUnison'] == 'true')) { - $ff += 1 << 25; - } - // richText: If true, the field allows rich text formatting. - if (isset($prop['richText']) AND ($prop['richText'] == 'true')) { - $ff += 1 << 25; - } - // commitOnSelChange: Controls whether a field value is committed after a selection change. - if (isset($prop['commitOnSelChange']) AND ($prop['commitOnSelChange'] == 'true')) { - $ff += 1 << 26; - } - $opt['ff'] = $ff; - // defaultValue: The default value of a field - that is, the value that the field is set to when the form is reset. - if (isset($prop['defaultValue'])) { - $opt['dv'] = $prop['defaultValue']; - } - $f = 4; // default value for annotation flags - // readonly: The read-only characteristic of a field. If a field is read-only, the user can see the field but cannot change it. - if (isset($prop['readonly']) AND ($prop['readonly'] == 'true')) { - $f += 1 << 6; - } - // display: Controls whether the field is hidden or visible on screen and in print. - if (isset($prop['display'])) { - if ($prop['display'] == 'display.visible') { - // - } elseif ($prop['display'] == 'display.hidden') { - $f += 1 << 1; - } elseif ($prop['display'] == 'display.noPrint') { - $f -= 1 << 2; - } elseif ($prop['display'] == 'display.noView') { - $f += 1 << 5; - } - } - $opt['f'] = $f; - // currentValueIndices: Reads and writes single or multiple values of a list box or combo box. - if (isset($prop['currentValueIndices']) AND is_array($prop['currentValueIndices'])) { - $opt['i'] = $prop['currentValueIndices']; - } - // value: The value of the field data that the user has entered. - if (isset($prop['value'])) { - if (is_array($prop['value'])) { - $opt['opt'] = array(); - foreach ($prop['value'] AS $key => $optval) { - // exportValues: An array of strings representing the export values for the field. - if (isset($prop['exportValues'][$key])) { - $opt['opt'][$key] = array($prop['exportValues'][$key], $prop['value'][$key]); - } else { - $opt['opt'][$key] = $prop['value'][$key]; - } - } - } else { - $opt['v'] = $prop['value']; - } - } - // richValue: This property specifies the text contents and formatting of a rich text field. - if (isset($prop['richValue'])) { - $opt['rv'] = $prop['richValue']; - } - // submitName: If nonempty, used during form submission instead of name. Only applicable if submitting in HTML format (that is, URL-encoded). - if (isset($prop['submitName'])) { - $opt['tm'] = $prop['submitName']; - } - // name: Fully qualified field name. - if (isset($prop['name'])) { - $opt['t'] = $prop['name']; - } - // userName: The user name (short description string) of the field. - if (isset($prop['userName'])) { - $opt['tu'] = $prop['userName']; - } - // highlight: Defines how a button reacts when a user clicks it. - if (isset($prop['highlight'])) { - switch ($prop['highlight']) { - case 'none': - case 'highlight.n': { - $opt['h'] = 'N'; - break; - } - case 'invert': - case 'highlight.i': { - $opt['h'] = 'i'; - break; - } - case 'push': - case 'highlight.p': { - $opt['h'] = 'P'; - break; - } - case 'outline': - case 'highlight.o': { - $opt['h'] = 'O'; - break; - } - } - } - // Unsupported options: - // - calcOrderIndex: Changes the calculation order of fields in the document. - // - delay: Delays the redrawing of a field's appearance. - // - defaultStyle: This property defines the default style attributes for the form field. - // - style: Allows the user to set the glyph style of a check box or radio button. - // - textColor, textFont, textSize - return $opt; - } - - /** - * Format the page numbers. - * This method can be overridden for custom formats. - * @param int $num page number - * @return string - * @since 4.2.005 (2008-11-06) - * @public static - */ - public static function formatPageNumber($num) { - return number_format((float)$num, 0, '', '.'); - } - - /** - * Format the page numbers on the Table Of Content. - * This method can be overridden for custom formats. - * @param int $num page number - * @return string - * @since 4.5.001 (2009-01-04) - * @see addTOC(), addHTMLTOC() - * @public static - */ - public static function formatTOCPageNumber($num) { - return number_format((float)$num, 0, '', '.'); - } - - /** - * Extracts the CSS properties from a CSS string. - * @param string $cssdata string containing CSS definitions. - * @return array An array where the keys are the CSS selectors and the values are the CSS properties. - * @author Nicola Asuni - * @since 5.1.000 (2010-05-25) - * @public static - */ - public static function extractCSSproperties($cssdata) { - if (empty($cssdata)) { - return array(); - } - // remove comments - $cssdata = preg_replace('/\/\*[^\*]*\*\//', '', $cssdata); - // remove newlines and multiple spaces - $cssdata = preg_replace('/[\s]+/', ' ', $cssdata); - // remove some spaces - $cssdata = preg_replace('/[\s]*([;:\{\}]{1})[\s]*/', '\\1', $cssdata); - // remove empty blocks - $cssdata = preg_replace('/([^\}\{]+)\{\}/', '', $cssdata); - // replace media type parenthesis - $cssdata = preg_replace('/@media[\s]+([^\{]*)\{/i', '@media \\1§', $cssdata); - $cssdata = preg_replace('/\}\}/si', '}§', $cssdata); - // trim string - $cssdata = trim($cssdata); - // find media blocks (all, braille, embossed, handheld, print, projection, screen, speech, tty, tv) - $cssblocks = array(); - $matches = array(); - if (preg_match_all('/@media[\s]+([^\§]*)§([^§]*)§/i', $cssdata, $matches) > 0) { - foreach ($matches[1] as $key => $type) { - $cssblocks[$type] = $matches[2][$key]; - } - // remove media blocks - $cssdata = preg_replace('/@media[\s]+([^\§]*)§([^§]*)§/i', '', $cssdata); - } - // keep 'all' and 'print' media, other media types are discarded - if (isset($cssblocks['all']) AND !empty($cssblocks['all'])) { - $cssdata .= $cssblocks['all']; - } - if (isset($cssblocks['print']) AND !empty($cssblocks['print'])) { - $cssdata .= $cssblocks['print']; - } - // reset css blocks array - $cssblocks = array(); - $matches = array(); - // explode css data string into array - if (substr($cssdata, -1) == '}') { - // remove last parethesis - $cssdata = substr($cssdata, 0, -1); - } - $matches = explode('}', $cssdata); - foreach ($matches as $key => $block) { - // index 0 contains the CSS selector, index 1 contains CSS properties - $cssblocks[$key] = explode('{', $block); - if (!isset($cssblocks[$key][1])) { - // remove empty definitions - unset($cssblocks[$key]); - } - } - // split groups of selectors (comma-separated list of selectors) - foreach ($cssblocks as $key => $block) { - if (strpos($block[0], ',') > 0) { - $selectors = explode(',', $block[0]); - foreach ($selectors as $sel) { - $cssblocks[] = array(0 => trim($sel), 1 => $block[1]); - } - unset($cssblocks[$key]); - } - } - // covert array to selector => properties - $cssdata = array(); - foreach ($cssblocks as $block) { - $selector = $block[0]; - // calculate selector's specificity - $matches = array(); - $a = 0; // the declaration is not from is a 'style' attribute - $b = intval(preg_match_all('/[\#]/', $selector, $matches)); // number of ID attributes - $c = intval(preg_match_all('/[\[\.]/', $selector, $matches)); // number of other attributes - $c += intval(preg_match_all('/[\:]link|visited|hover|active|focus|target|lang|enabled|disabled|checked|indeterminate|root|nth|first|last|only|empty|contains|not/i', $selector, $matches)); // number of pseudo-classes - $d = intval(preg_match_all('/[\>\+\~\s]{1}[a-zA-Z0-9]+/', ' '.$selector, $matches)); // number of element names - $d += intval(preg_match_all('/[\:][\:]/', $selector, $matches)); // number of pseudo-elements - $specificity = $a.$b.$c.$d; - // add specificity to the beginning of the selector - $cssdata[$specificity.' '.$selector] = $block[1]; - } - // sort selectors alphabetically to account for specificity - ksort($cssdata, SORT_STRING); - // return array - return $cssdata; - } - - /** - * Cleanup HTML code (requires HTML Tidy library). - * @param string $html htmlcode to fix - * @param string $default_css CSS commands to add - * @param array|null $tagvs parameters for setHtmlVSpace method - * @param array|null $tidy_options options for tidy_parse_string function - * @param array $tagvspaces Array of vertical spaces for tags. - * @return string XHTML code cleaned up - * @author Nicola Asuni - * @since 5.9.017 (2010-11-16) - * @see setHtmlVSpace() - * @public static - */ - public static function fixHTMLCode($html, $default_css, $tagvs, $tidy_options, &$tagvspaces) { - // configure parameters for HTML Tidy - if (TCPDF_STATIC::empty_string($tidy_options)) { - $tidy_options = array ( - 'clean' => 1, - 'drop-empty-paras' => 0, - 'drop-proprietary-attributes' => 1, - 'fix-backslash' => 1, - 'hide-comments' => 1, - 'join-styles' => 1, - 'lower-literals' => 1, - 'merge-divs' => 1, - 'merge-spans' => 1, - 'output-xhtml' => 1, - 'word-2000' => 1, - 'wrap' => 0, - 'output-bom' => 0, - //'char-encoding' => 'utf8', - //'input-encoding' => 'utf8', - //'output-encoding' => 'utf8' - ); - } - // clean up the HTML code - $tidy = tidy_parse_string($html, $tidy_options); - // fix the HTML - $tidy->cleanRepair(); - // get the CSS part - $tidy_head = tidy_get_head($tidy); - $css = $tidy_head->value; - $css = preg_replace('/<style([^>]+)>/ims', '<style>', $css); - $css = preg_replace('/<\/style>(.*)<style>/ims', "\n", $css); - $css = str_replace('/*<![CDATA[*/', '', $css); - $css = str_replace('/*]]>*/', '', $css); - preg_match('/<style>(.*)<\/style>/ims', $css, $matches); - if (isset($matches[1])) { - $css = strtolower($matches[1]); - } else { - $css = ''; - } - // include default css - $css = '<style>'.$default_css.$css.'</style>'; - // get the body part - $tidy_body = tidy_get_body($tidy); - $html = $tidy_body->value; - // fix some self-closing tags - $html = str_replace('<br>', '<br />', $html); - // remove some empty tag blocks - $html = preg_replace('/<div([^\>]*)><\/div>/', '', $html); - $html = preg_replace('/<p([^\>]*)><\/p>/', '', $html); - if (!TCPDF_STATIC::empty_string($tagvs)) { - // set vertical space for some XHTML tags - $tagvspaces = $tagvs; - } - // return the cleaned XHTML code + CSS - return $css.$html; - } - - /** - * Returns true if the CSS selector is valid for the selected HTML tag - * @param array $dom array of HTML tags and properties - * @param int $key key of the current HTML tag - * @param string $selector CSS selector string - * @return true if the selector is valid, false otherwise - * @since 5.1.000 (2010-05-25) - * @public static - */ - public static function isValidCSSSelectorForTag($dom, $key, $selector) { - $valid = false; // value to be returned - $tag = $dom[$key]['value']; - $class = array(); - if (isset($dom[$key]['attribute']['class']) AND !empty($dom[$key]['attribute']['class'])) { - $class = explode(' ', strtolower($dom[$key]['attribute']['class'])); - } - $id = ''; - if (isset($dom[$key]['attribute']['id']) AND !empty($dom[$key]['attribute']['id'])) { - $id = strtolower($dom[$key]['attribute']['id']); - } - $selector = preg_replace('/([\>\+\~\s]{1})([\.]{1})([^\>\+\~\s]*)/si', '\\1*.\\3', $selector); - $matches = array(); - if (preg_match_all('/([\>\+\~\s]{1})([a-zA-Z0-9\*]+)([^\>\+\~\s]*)/si', $selector, $matches, PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE) > 0) { - $parentop = array_pop($matches[1]); - $operator = $parentop[0]; - $offset = $parentop[1]; - $lasttag = array_pop($matches[2]); - $lasttag = strtolower(trim($lasttag[0])); - if (($lasttag == '*') OR ($lasttag == $tag)) { - // the last element on selector is our tag or 'any tag' - $attrib = array_pop($matches[3]); - $attrib = strtolower(trim($attrib[0])); - if (!empty($attrib)) { - // check if matches class, id, attribute, pseudo-class or pseudo-element - switch ($attrib[0]) { - case '.': { // class - if (in_array(substr($attrib, 1), $class)) { - $valid = true; - } - break; - } - case '#': { // ID - if (substr($attrib, 1) == $id) { - $valid = true; - } - break; - } - case '[': { // attribute - $attrmatch = array(); - if (preg_match('/\[([a-zA-Z0-9]*)[\s]*([\~\^\$\*\|\=]*)[\s]*["]?([^"\]]*)["]?\]/i', $attrib, $attrmatch) > 0) { - $att = strtolower($attrmatch[1]); - $val = $attrmatch[3]; - if (isset($dom[$key]['attribute'][$att])) { - switch ($attrmatch[2]) { - case '=': { - if ($dom[$key]['attribute'][$att] == $val) { - $valid = true; - } - break; - } - case '~=': { - if (in_array($val, explode(' ', $dom[$key]['attribute'][$att]))) { - $valid = true; - } - break; - } - case '^=': { - if ($val == substr($dom[$key]['attribute'][$att], 0, strlen($val))) { - $valid = true; - } - break; - } - case '$=': { - if ($val == substr($dom[$key]['attribute'][$att], -strlen($val))) { - $valid = true; - } - break; - } - case '*=': { - if (strpos($dom[$key]['attribute'][$att], $val) !== false) { - $valid = true; - } - break; - } - case '|=': { - if ($dom[$key]['attribute'][$att] == $val) { - $valid = true; - } elseif (preg_match('/'.$val.'[\-]{1}/i', $dom[$key]['attribute'][$att]) > 0) { - $valid = true; - } - break; - } - default: { - $valid = true; - } - } - } - } - break; - } - case ':': { // pseudo-class or pseudo-element - if ($attrib[1] == ':') { // pseudo-element - // pseudo-elements are not supported! - // (::first-line, ::first-letter, ::before, ::after) - } else { // pseudo-class - // pseudo-classes are not supported! - // (:root, :nth-child(n), :nth-last-child(n), :nth-of-type(n), :nth-last-of-type(n), :first-child, :last-child, :first-of-type, :last-of-type, :only-child, :only-of-type, :empty, :link, :visited, :active, :hover, :focus, :target, :lang(fr), :enabled, :disabled, :checked) - } - break; - } - } // end of switch - } else { - $valid = true; - } - if ($valid AND ($offset > 0)) { - $valid = false; - // check remaining selector part - $selector = substr($selector, 0, $offset); - switch ($operator) { - case ' ': { // descendant of an element - while ($dom[$key]['parent'] > 0) { - if (self::isValidCSSSelectorForTag($dom, $dom[$key]['parent'], $selector)) { - $valid = true; - break; - } else { - $key = $dom[$key]['parent']; - } - } - break; - } - case '>': { // child of an element - $valid = self::isValidCSSSelectorForTag($dom, $dom[$key]['parent'], $selector); - break; - } - case '+': { // immediately preceded by an element - for ($i = ($key - 1); $i > $dom[$key]['parent']; --$i) { - if ($dom[$i]['tag'] AND $dom[$i]['opening']) { - $valid = self::isValidCSSSelectorForTag($dom, $i, $selector); - break; - } - } - break; - } - case '~': { // preceded by an element - for ($i = ($key - 1); $i > $dom[$key]['parent']; --$i) { - if ($dom[$i]['tag'] AND $dom[$i]['opening']) { - if (self::isValidCSSSelectorForTag($dom, $i, $selector)) { - break; - } - } - } - break; - } - } - } - } - } - return $valid; - } - - /** - * Returns the styles array that apply for the selected HTML tag. - * @param array $dom array of HTML tags and properties - * @param int $key key of the current HTML tag - * @param array $css array of CSS properties - * @return array containing CSS properties - * @since 5.1.000 (2010-05-25) - * @public static - */ - public static function getCSSdataArray($dom, $key, $css) { - $cssarray = array(); // style to be returned - // get parent CSS selectors - $selectors = array(); - if (isset($dom[($dom[$key]['parent'])]['csssel'])) { - $selectors = $dom[($dom[$key]['parent'])]['csssel']; - } - // get all styles that apply - foreach($css as $selector => $style) { - $pos = strpos($selector, ' '); - // get specificity - $specificity = substr($selector, 0, $pos); - // remove specificity - $selector = substr($selector, $pos); - // check if this selector apply to current tag - if (self::isValidCSSSelectorForTag($dom, $key, $selector)) { - if (!in_array($selector, $selectors)) { - // add style if not already added on parent selector - $cssarray[] = array('k' => $selector, 's' => $specificity, 'c' => $style); - $selectors[] = $selector; - } - } - } - if (isset($dom[$key]['attribute']['style'])) { - // attach inline style (latest properties have high priority) - $cssarray[] = array('k' => '', 's' => '1000', 'c' => $dom[$key]['attribute']['style']); - } - // order the css array to account for specificity - $cssordered = array(); - foreach ($cssarray as $key => $val) { - $skey = sprintf('%04d', $key); - $cssordered[$val['s'].'_'.$skey] = $val; - } - // sort selectors alphabetically to account for specificity - ksort($cssordered, SORT_STRING); - return array($selectors, $cssordered); - } - - /** - * Compact CSS data array into single string. - * @param array $css array of CSS properties - * @return string containing merged CSS properties - * @since 5.9.070 (2011-04-19) - * @public static - */ - public static function getTagStyleFromCSSarray($css) { - $tagstyle = ''; // value to be returned - foreach ($css as $style) { - // split single css commands - $csscmds = explode(';', $style['c']); - foreach ($csscmds as $cmd) { - if (!empty($cmd)) { - $pos = strpos($cmd, ':'); - if ($pos !== false) { - $cmd = substr($cmd, 0, ($pos + 1)); - if (strpos($tagstyle, $cmd) !== false) { - // remove duplicate commands (last commands have high priority) - $tagstyle = preg_replace('/'.$cmd.'[^;]+/i', '', $tagstyle); - } - } - } - } - $tagstyle .= ';'.$style['c']; - } - // remove multiple semicolons - $tagstyle = preg_replace('/[;]+/', ';', $tagstyle); - return $tagstyle; - } - - /** - * Returns the Roman representation of an integer number - * @param int $number number to convert - * @return string roman representation of the specified number - * @since 4.4.004 (2008-12-10) - * @public static - */ - public static function intToRoman($number) { - $roman = ''; - if ($number >= 4000) { - // do not represent numbers above 4000 in Roman numerals - return strval($number); - } - while ($number >= 1000) { - $roman .= 'M'; - $number -= 1000; - } - while ($number >= 900) { - $roman .= 'CM'; - $number -= 900; - } - while ($number >= 500) { - $roman .= 'D'; - $number -= 500; - } - while ($number >= 400) { - $roman .= 'CD'; - $number -= 400; - } - while ($number >= 100) { - $roman .= 'C'; - $number -= 100; - } - while ($number >= 90) { - $roman .= 'XC'; - $number -= 90; - } - while ($number >= 50) { - $roman .= 'L'; - $number -= 50; - } - while ($number >= 40) { - $roman .= 'XL'; - $number -= 40; - } - while ($number >= 10) { - $roman .= 'X'; - $number -= 10; - } - while ($number >= 9) { - $roman .= 'IX'; - $number -= 9; - } - while ($number >= 5) { - $roman .= 'V'; - $number -= 5; - } - while ($number >= 4) { - $roman .= 'IV'; - $number -= 4; - } - while ($number >= 1) { - $roman .= 'I'; - --$number; - } - return $roman; - } - - /** - * Find position of last occurrence of a substring in a string - * @param string $haystack The string to search in. - * @param string $needle substring to search. - * @param int $offset May be specified to begin searching an arbitrary number of characters into the string. - * @return int|false Returns the position where the needle exists. Returns FALSE if the needle was not found. - * @since 4.8.038 (2010-03-13) - * @public static - */ - public static function revstrpos($haystack, $needle, $offset = 0) { - $length = strlen($haystack); - $offset = ($offset > 0)?($length - $offset):abs($offset); - $pos = strpos(strrev($haystack), strrev($needle), $offset); - return ($pos === false)?false:($length - $pos - strlen($needle)); - } - - /** - * Returns an array of hyphenation patterns. - * @param string $file TEX file containing hypenation patterns. TEX patterns can be downloaded from http://www.ctan.org/tex-archive/language/hyph-utf8/tex/generic/hyph-utf8/patterns/ - * @return array of hyphenation patterns - * @author Nicola Asuni - * @since 4.9.012 (2010-04-12) - * @public static - */ - public static function getHyphenPatternsFromTEX($file) { - // TEX patterns are available at: - // http://www.ctan.org/tex-archive/language/hyph-utf8/tex/generic/hyph-utf8/patterns/ - $data = file_get_contents($file); - $patterns = array(); - // remove comments - $data = preg_replace('/\%[^\n]*/', '', $data); - // extract the patterns part - preg_match('/\\\\patterns\{([^\}]*)\}/i', $data, $matches); - $data = trim(substr($matches[0], 10, -1)); - // extract each pattern - $patterns_array = preg_split('/[\s]+/', $data); - // create new language array of patterns - $patterns = array(); - foreach($patterns_array as $val) { - if (!TCPDF_STATIC::empty_string($val)) { - $val = trim($val); - $val = str_replace('\'', '\\\'', $val); - $key = preg_replace('/[0-9]+/', '', $val); - $patterns[$key] = $val; - } - } - return $patterns; - } - - /** - * Get the Path-Painting Operators. - * @param string $style Style of rendering. Possible values are: - * <ul> - * <li>S or D: Stroke the path.</li> - * <li>s or d: Close and stroke the path.</li> - * <li>f or F: Fill the path, using the nonzero winding number rule to determine the region to fill.</li> - * <li>f* or F*: Fill the path, using the even-odd rule to determine the region to fill.</li> - * <li>B or FD or DF: Fill and then stroke the path, using the nonzero winding number rule to determine the region to fill.</li> - * <li>B* or F*D or DF*: Fill and then stroke the path, using the even-odd rule to determine the region to fill.</li> - * <li>b or fd or df: Close, fill, and then stroke the path, using the nonzero winding number rule to determine the region to fill.</li> - * <li>b or f*d or df*: Close, fill, and then stroke the path, using the even-odd rule to determine the region to fill.</li> - * <li>CNZ: Clipping mode using the even-odd rule to determine which regions lie inside the clipping path.</li> - * <li>CEO: Clipping mode using the nonzero winding number rule to determine which regions lie inside the clipping path</li> - * <li>n: End the path object without filling or stroking it.</li> - * </ul> - * @param string $default default style - * @return string - * @author Nicola Asuni - * @since 5.0.000 (2010-04-30) - * @public static - */ - public static function getPathPaintOperator($style, $default='S') { - $op = ''; - switch($style) { - case 'S': - case 'D': { - $op = 'S'; - break; - } - case 's': - case 'd': { - $op = 's'; - break; - } - case 'f': - case 'F': { - $op = 'f'; - break; - } - case 'f*': - case 'F*': { - $op = 'f*'; - break; - } - case 'B': - case 'FD': - case 'DF': { - $op = 'B'; - break; - } - case 'B*': - case 'F*D': - case 'DF*': { - $op = 'B*'; - break; - } - case 'b': - case 'fd': - case 'df': { - $op = 'b'; - break; - } - case 'b*': - case 'f*d': - case 'df*': { - $op = 'b*'; - break; - } - case 'CNZ': { - $op = 'W n'; - break; - } - case 'CEO': { - $op = 'W* n'; - break; - } - case 'n': { - $op = 'n'; - break; - } - default: { - if (!empty($default)) { - $op = self::getPathPaintOperator($default, ''); - } else { - $op = ''; - } - } - } - return $op; - } - - /** - * Get the product of two SVG tranformation matrices - * @param array $ta first SVG tranformation matrix - * @param array $tb second SVG tranformation matrix - * @return array transformation array - * @author Nicola Asuni - * @since 5.0.000 (2010-05-02) - * @public static - */ - public static function getTransformationMatrixProduct($ta, $tb) { - $tm = array(); - $tm[0] = ($ta[0] * $tb[0]) + ($ta[2] * $tb[1]); - $tm[1] = ($ta[1] * $tb[0]) + ($ta[3] * $tb[1]); - $tm[2] = ($ta[0] * $tb[2]) + ($ta[2] * $tb[3]); - $tm[3] = ($ta[1] * $tb[2]) + ($ta[3] * $tb[3]); - $tm[4] = ($ta[0] * $tb[4]) + ($ta[2] * $tb[5]) + $ta[4]; - $tm[5] = ($ta[1] * $tb[4]) + ($ta[3] * $tb[5]) + $ta[5]; - return $tm; - } - - /** - * Get the tranformation matrix from SVG transform attribute - * @param string $attribute transformation - * @return array of transformations - * @author Nicola Asuni - * @since 5.0.000 (2010-05-02) - * @public static - */ - public static function getSVGTransformMatrix($attribute) { - // identity matrix - $tm = array(1, 0, 0, 1, 0, 0); - $transform = array(); - if (preg_match_all('/(matrix|translate|scale|rotate|skewX|skewY)[\s]*\(([^\)]+)\)/si', $attribute, $transform, PREG_SET_ORDER) > 0) { - foreach ($transform as $key => $data) { - if (!empty($data[2])) { - $a = 1; - $b = 0; - $c = 0; - $d = 1; - $e = 0; - $f = 0; - $regs = array(); - switch ($data[1]) { - case 'matrix': { - if (preg_match('/([a-z0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)/si', $data[2], $regs)) { - $a = $regs[1]; - $b = $regs[2]; - $c = $regs[3]; - $d = $regs[4]; - $e = $regs[5]; - $f = $regs[6]; - } - break; - } - case 'translate': { - if (preg_match('/([a-z0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)/si', $data[2], $regs)) { - $e = $regs[1]; - $f = $regs[2]; - } elseif (preg_match('/([a-z0-9\-\.]+)/si', $data[2], $regs)) { - $e = $regs[1]; - } - break; - } - case 'scale': { - if (preg_match('/([a-z0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)/si', $data[2], $regs)) { - $a = $regs[1]; - $d = $regs[2]; - } elseif (preg_match('/([a-z0-9\-\.]+)/si', $data[2], $regs)) { - $a = $regs[1]; - $d = $a; - } - break; - } - case 'rotate': { - if (preg_match('/([0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)/si', $data[2], $regs)) { - $ang = deg2rad($regs[1]); - $x = $regs[2]; - $y = $regs[3]; - $a = cos($ang); - $b = sin($ang); - $c = -$b; - $d = $a; - $e = ($x * (1 - $a)) - ($y * $c); - $f = ($y * (1 - $d)) - ($x * $b); - } elseif (preg_match('/([0-9\-\.]+)/si', $data[2], $regs)) { - $ang = deg2rad($regs[1]); - $a = cos($ang); - $b = sin($ang); - $c = -$b; - $d = $a; - $e = 0; - $f = 0; - } - break; - } - case 'skewX': { - if (preg_match('/([0-9\-\.]+)/si', $data[2], $regs)) { - $c = tan(deg2rad($regs[1])); - } - break; - } - case 'skewY': { - if (preg_match('/([0-9\-\.]+)/si', $data[2], $regs)) { - $b = tan(deg2rad($regs[1])); - } - break; - } - } - $tm = self::getTransformationMatrixProduct($tm, array($a, $b, $c, $d, $e, $f)); - } - } - } - return $tm; - } - - /** - * Returns the angle in radiants between two vectors - * @param int $x1 X coordinate of first vector point - * @param int $y1 Y coordinate of first vector point - * @param int $x2 X coordinate of second vector point - * @param int $y2 Y coordinate of second vector point - * @author Nicola Asuni - * @since 5.0.000 (2010-05-04) - * @public static - */ - public static function getVectorsAngle($x1, $y1, $x2, $y2) { - $dprod = ($x1 * $x2) + ($y1 * $y2); - $dist1 = sqrt(($x1 * $x1) + ($y1 * $y1)); - $dist2 = sqrt(($x2 * $x2) + ($y2 * $y2)); - $angle = acos($dprod / ($dist1 * $dist2)); - if (is_nan($angle)) { - $angle = M_PI; - } - if ((($x1 * $y2) - ($x2 * $y1)) < 0) { - $angle *= -1; - } - return $angle; - } - - /** - * Split string by a regular expression. - * This is a wrapper for the preg_split function to avoid the bug: https://bugs.php.net/bug.php?id=45850 - * @param string $pattern The regular expression pattern to search for without the modifiers, as a string. - * @param string $modifiers The modifiers part of the pattern, - * @param string $subject The input string. - * @param int $limit If specified, then only substrings up to limit are returned with the rest of the string being placed in the last substring. A limit of -1, 0 or NULL means "no limit" and, as is standard across PHP, you can use NULL to skip to the flags parameter. - * @param int $flags The flags as specified on the preg_split PHP function. - * @return array Returns an array containing substrings of subject split along boundaries matched by pattern.modifier - * @author Nicola Asuni - * @since 6.0.023 - * @public static - */ - public static function pregSplit($pattern, $modifiers, $subject, $limit=NULL, $flags=NULL) { - // PHP 8.1 deprecates nulls for $limit and $flags - $limit = $limit === null ? -1 : $limit; - $flags = $flags === null ? 0 : $flags; - // the bug only happens on PHP 5.2 when using the u modifier - if ((strpos($modifiers, 'u') === FALSE) OR (count(preg_split('//u', "\n\t", -1, PREG_SPLIT_NO_EMPTY)) == 2)) { - return preg_split($pattern.$modifiers, $subject, $limit, $flags); - } - // preg_split is bugged - try alternative solution - $ret = array(); - while (($nl = strpos($subject, "\n")) !== FALSE) { - $ret = array_merge($ret, preg_split($pattern.$modifiers, substr($subject, 0, $nl), $limit, $flags)); - $ret[] = "\n"; - $subject = substr($subject, ($nl + 1)); - } - if (strlen($subject) > 0) { - $ret = array_merge($ret, preg_split($pattern.$modifiers, $subject, $limit, $flags)); - } - return $ret; - } - - /** - * Wrapper to use fopen only with local files - * @param string $filename Name of the file to open - * @param string $mode - * @return resource|false Returns a file pointer resource on success, or FALSE on error. - * @public static - */ - public static function fopenLocal($filename, $mode) { - if (strpos($filename, '://') === false) { - $filename = 'file://'.$filename; - } elseif (stream_is_local($filename) !== true) { - return false; - } - return fopen($filename, $mode); - } - - /** - * Check if the URL exist. - * @param string $url URL to check. - * @return bool Returns TRUE if the URL exists; FALSE otherwise. - * @public static - * @since 6.2.25 - */ - public static function url_exists($url) { - $crs = curl_init(); - // encode query params in URL to get right response form the server - $url = self::encodeUrlQuery($url); - curl_setopt($crs, CURLOPT_URL, $url); - curl_setopt($crs, CURLOPT_NOBODY, true); - curl_setopt($crs, CURLOPT_FAILONERROR, true); - if ((ini_get('open_basedir') == '') && (!ini_get('safe_mode'))) { - curl_setopt($crs, CURLOPT_FOLLOWLOCATION, true); - } - curl_setopt($crs, CURLOPT_CONNECTTIMEOUT, 5); - curl_setopt($crs, CURLOPT_TIMEOUT, 30); - curl_setopt($crs, CURLOPT_SSL_VERIFYPEER, false); - curl_setopt($crs, CURLOPT_SSL_VERIFYHOST, false); - curl_setopt($crs, CURLOPT_USERAGENT, 'tc-lib-file'); - curl_setopt($crs, CURLOPT_MAXREDIRS, 5); - if (defined('CURLOPT_PROTOCOLS')) { - curl_setopt($crs, CURLOPT_PROTOCOLS, CURLPROTO_HTTPS | CURLPROTO_HTTP | CURLPROTO_FTP | CURLPROTO_FTPS); - } - curl_exec($crs); - $code = curl_getinfo($crs, CURLINFO_HTTP_CODE); - curl_close($crs); - return ($code == 200); - } - - /** - * Encode query params in URL - * - * @param string $url - * @return string - * @since 6.3.3 (2019-11-01) - * @public static - */ - public static function encodeUrlQuery($url) { - $urlData = parse_url($url); - if (isset($urlData['query']) && $urlData['query']) { - $urlQueryData = array(); - parse_str(urldecode($urlData['query']), $urlQueryData); - $updatedUrl = $urlData['scheme'] . '://' . $urlData['host'] . $urlData['path'] . '?' . http_build_query($urlQueryData); - } else { - $updatedUrl = $url; - } - return $updatedUrl; - } - - /** - * Wrapper for file_exists. - * Checks whether a file or directory exists. - * Only allows some protocols and local files. - * @param string $filename Path to the file or directory. - * @return bool Returns TRUE if the file or directory specified by filename exists; FALSE otherwise. - * @public static - */ - public static function file_exists($filename) { - if (preg_match('|^https?://|', $filename) == 1) { - return self::url_exists($filename); - } - if (strpos($filename, '://')) { - return false; // only support http and https wrappers for security reasons - } - return @file_exists($filename); - } - - /** - * Reads entire file into a string. - * The file can be also an URL. - * @param string $file Name of the file or URL to read. - * @return string|false The function returns the read data or FALSE on failure. - * @author Nicola Asuni - * @since 6.0.025 - * @public static - */ - public static function fileGetContents($file) { - $alt = array($file); - // - if ((strlen($file) > 1) - && ($file[0] === '/') - && ($file[1] !== '/') - && !empty($_SERVER['DOCUMENT_ROOT']) - && ($_SERVER['DOCUMENT_ROOT'] !== '/') - ) { - $findroot = strpos($file, $_SERVER['DOCUMENT_ROOT']); - if (($findroot === false) || ($findroot > 1)) { - $alt[] = htmlspecialchars_decode(urldecode($_SERVER['DOCUMENT_ROOT'].$file)); - } - } - // - $protocol = 'http'; - if (!empty($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) != 'off')) { - $protocol .= 's'; - } - // - $url = $file; - if (preg_match('%^//%', $url) && !empty($_SERVER['HTTP_HOST'])) { - $url = $protocol.':'.str_replace(' ', '%20', $url); - } - $url = htmlspecialchars_decode($url); - $alt[] = $url; - // - if (preg_match('%^(https?)://%', $url) - && empty($_SERVER['HTTP_HOST']) - && empty($_SERVER['DOCUMENT_ROOT']) - ) { - $urldata = parse_url($url); - if (empty($urldata['query'])) { - $host = $protocol.'://'.$_SERVER['HTTP_HOST']; - if (strpos($url, $host) === 0) { - // convert URL to full server path - $tmp = str_replace($host, $_SERVER['DOCUMENT_ROOT'], $url); - $alt[] = htmlspecialchars_decode(urldecode($tmp)); - } - } - } - // - if (isset($_SERVER['SCRIPT_URI']) - && !preg_match('%^(https?|ftp)://%', $file) - && !preg_match('%^//%', $file) - ) { - $urldata = @parse_url($_SERVER['SCRIPT_URI']); - $alt[] = $urldata['scheme'].'://'.$urldata['host'].(($file[0] == '/') ? '' : '/').$file; - } - // - $alt = array_unique($alt); - foreach ($alt as $path) { - if (!self::file_exists($path)) { - continue; - } - $ret = @file_get_contents($path); - if ( $ret != false ) { - return $ret; - } - // try to use CURL for URLs - if (!ini_get('allow_url_fopen') - && function_exists('curl_init') - && preg_match('%^(https?|ftp)://%', $path) - ) { - // try to get remote file data using cURL - $crs = curl_init(); - curl_setopt($crs, CURLOPT_URL, $path); - curl_setopt($crs, CURLOPT_BINARYTRANSFER, true); - curl_setopt($crs, CURLOPT_FAILONERROR, true); - curl_setopt($crs, CURLOPT_RETURNTRANSFER, true); - if ((ini_get('open_basedir') == '') && (!ini_get('safe_mode'))) { - curl_setopt($crs, CURLOPT_FOLLOWLOCATION, true); - } - curl_setopt($crs, CURLOPT_CONNECTTIMEOUT, 5); - curl_setopt($crs, CURLOPT_TIMEOUT, 30); - curl_setopt($crs, CURLOPT_SSL_VERIFYPEER, false); - curl_setopt($crs, CURLOPT_SSL_VERIFYHOST, false); - curl_setopt($crs, CURLOPT_USERAGENT, 'tc-lib-file'); - curl_setopt($crs, CURLOPT_MAXREDIRS, 5); - if (defined('CURLOPT_PROTOCOLS')) { - curl_setopt($crs, CURLOPT_PROTOCOLS, CURLPROTO_HTTPS | CURLPROTO_HTTP | CURLPROTO_FTP | CURLPROTO_FTPS); - } - $ret = curl_exec($crs); - curl_close($crs); - if ($ret !== false) { - return $ret; - } - } - } - return false; - } - - /** - * Get ULONG from string (Big Endian 32-bit unsigned integer). - * @param string $str string from where to extract value - * @param int $offset point from where to read the data - * @return int 32 bit value - * @author Nicola Asuni - * @since 5.2.000 (2010-06-02) - * @public static - */ - public static function _getULONG($str, $offset) { - $v = unpack('Ni', substr($str, $offset, 4)); - return $v['i']; - } - - /** - * Get USHORT from string (Big Endian 16-bit unsigned integer). - * @param string $str string from where to extract value - * @param int $offset point from where to read the data - * @return int 16 bit value - * @author Nicola Asuni - * @since 5.2.000 (2010-06-02) - * @public static - */ - public static function _getUSHORT($str, $offset) { - $v = unpack('ni', substr($str, $offset, 2)); - return $v['i']; - } - - /** - * Get SHORT from string (Big Endian 16-bit signed integer). - * @param string $str String from where to extract value. - * @param int $offset Point from where to read the data. - * @return int 16 bit value - * @author Nicola Asuni - * @since 5.2.000 (2010-06-02) - * @public static - */ - public static function _getSHORT($str, $offset) { - $v = unpack('si', substr($str, $offset, 2)); - return $v['i']; - } - - /** - * Get FWORD from string (Big Endian 16-bit signed integer). - * @param string $str String from where to extract value. - * @param int $offset Point from where to read the data. - * @return int 16 bit value - * @author Nicola Asuni - * @since 5.9.123 (2011-09-30) - * @public static - */ - public static function _getFWORD($str, $offset) { - $v = self::_getUSHORT($str, $offset); - if ($v > 0x7fff) { - $v -= 0x10000; - } - return $v; - } - - /** - * Get UFWORD from string (Big Endian 16-bit unsigned integer). - * @param string $str string from where to extract value - * @param int $offset point from where to read the data - * @return int 16 bit value - * @author Nicola Asuni - * @since 5.9.123 (2011-09-30) - * @public static - */ - public static function _getUFWORD($str, $offset) { - $v = self::_getUSHORT($str, $offset); - return $v; - } - - /** - * Get FIXED from string (32-bit signed fixed-point number (16.16). - * @param string $str string from where to extract value - * @param int $offset point from where to read the data - * @return int 16 bit value - * @author Nicola Asuni - * @since 5.9.123 (2011-09-30) - * @public static - */ - public static function _getFIXED($str, $offset) { - // mantissa - $m = self::_getFWORD($str, $offset); - // fraction - $f = self::_getUSHORT($str, ($offset + 2)); - $v = floatval(''.$m.'.'.$f.''); - return $v; - } - - /** - * Get BYTE from string (8-bit unsigned integer). - * @param string $str String from where to extract value. - * @param int $offset Point from where to read the data. - * @return int 8 bit value - * @author Nicola Asuni - * @since 5.2.000 (2010-06-02) - * @public static - */ - public static function _getBYTE($str, $offset) { - $v = unpack('Ci', substr($str, $offset, 1)); - return $v['i']; - } - /** - * Binary-safe and URL-safe file read. - * Reads up to length bytes from the file pointer referenced by handle. Reading stops as soon as one of the following conditions is met: length bytes have been read; EOF (end of file) is reached. - * @param resource $handle - * @param int $length - * @return string|false Returns the read string or FALSE in case of error. - * @author Nicola Asuni - * @since 4.5.027 (2009-03-16) - * @public static - */ - public static function rfread($handle, $length) { - $data = fread($handle, $length); - if ($data === false) { - return false; - } - $rest = ($length - strlen($data)); - if (($rest > 0) && !feof($handle)) { - $data .= self::rfread($handle, $rest); - } - return $data; - } - - /** - * Read a 4-byte (32 bit) integer from file. - * @param resource $f file resource. - * @return int 4-byte integer - * @public static - */ - public static function _freadint($f) { - $a = unpack('Ni', fread($f, 4)); - return $a['i']; - } - - /** - * Array of page formats - * measures are calculated in this way: (inches * 72) or (millimeters * 72 / 25.4) - * @public static - * - * @var array<string,float[]> - */ - public static $page_formats = array( - // ISO 216 A Series + 2 SIS 014711 extensions - 'A0' => array( 2383.937, 3370.394), // = ( 841 x 1189 ) mm = ( 33.11 x 46.81 ) in - 'A1' => array( 1683.780, 2383.937), // = ( 594 x 841 ) mm = ( 23.39 x 33.11 ) in - 'A2' => array( 1190.551, 1683.780), // = ( 420 x 594 ) mm = ( 16.54 x 23.39 ) in - 'A3' => array( 841.890, 1190.551), // = ( 297 x 420 ) mm = ( 11.69 x 16.54 ) in - 'A4' => array( 595.276, 841.890), // = ( 210 x 297 ) mm = ( 8.27 x 11.69 ) in - 'A5' => array( 419.528, 595.276), // = ( 148 x 210 ) mm = ( 5.83 x 8.27 ) in - 'A6' => array( 297.638, 419.528), // = ( 105 x 148 ) mm = ( 4.13 x 5.83 ) in - 'A7' => array( 209.764, 297.638), // = ( 74 x 105 ) mm = ( 2.91 x 4.13 ) in - 'A8' => array( 147.402, 209.764), // = ( 52 x 74 ) mm = ( 2.05 x 2.91 ) in - 'A9' => array( 104.882, 147.402), // = ( 37 x 52 ) mm = ( 1.46 x 2.05 ) in - 'A10' => array( 73.701, 104.882), // = ( 26 x 37 ) mm = ( 1.02 x 1.46 ) in - 'A11' => array( 51.024, 73.701), // = ( 18 x 26 ) mm = ( 0.71 x 1.02 ) in - 'A12' => array( 36.850, 51.024), // = ( 13 x 18 ) mm = ( 0.51 x 0.71 ) in - // ISO 216 B Series + 2 SIS 014711 extensions - 'B0' => array( 2834.646, 4008.189), // = ( 1000 x 1414 ) mm = ( 39.37 x 55.67 ) in - 'B1' => array( 2004.094, 2834.646), // = ( 707 x 1000 ) mm = ( 27.83 x 39.37 ) in - 'B2' => array( 1417.323, 2004.094), // = ( 500 x 707 ) mm = ( 19.69 x 27.83 ) in - 'B3' => array( 1000.630, 1417.323), // = ( 353 x 500 ) mm = ( 13.90 x 19.69 ) in - 'B4' => array( 708.661, 1000.630), // = ( 250 x 353 ) mm = ( 9.84 x 13.90 ) in - 'B5' => array( 498.898, 708.661), // = ( 176 x 250 ) mm = ( 6.93 x 9.84 ) in - 'B6' => array( 354.331, 498.898), // = ( 125 x 176 ) mm = ( 4.92 x 6.93 ) in - 'B7' => array( 249.449, 354.331), // = ( 88 x 125 ) mm = ( 3.46 x 4.92 ) in - 'B8' => array( 175.748, 249.449), // = ( 62 x 88 ) mm = ( 2.44 x 3.46 ) in - 'B9' => array( 124.724, 175.748), // = ( 44 x 62 ) mm = ( 1.73 x 2.44 ) in - 'B10' => array( 87.874, 124.724), // = ( 31 x 44 ) mm = ( 1.22 x 1.73 ) in - 'B11' => array( 62.362, 87.874), // = ( 22 x 31 ) mm = ( 0.87 x 1.22 ) in - 'B12' => array( 42.520, 62.362), // = ( 15 x 22 ) mm = ( 0.59 x 0.87 ) in - // ISO 216 C Series + 2 SIS 014711 extensions + 5 EXTENSION - 'C0' => array( 2599.370, 3676.535), // = ( 917 x 1297 ) mm = ( 36.10 x 51.06 ) in - 'C1' => array( 1836.850, 2599.370), // = ( 648 x 917 ) mm = ( 25.51 x 36.10 ) in - 'C2' => array( 1298.268, 1836.850), // = ( 458 x 648 ) mm = ( 18.03 x 25.51 ) in - 'C3' => array( 918.425, 1298.268), // = ( 324 x 458 ) mm = ( 12.76 x 18.03 ) in - 'C4' => array( 649.134, 918.425), // = ( 229 x 324 ) mm = ( 9.02 x 12.76 ) in - 'C5' => array( 459.213, 649.134), // = ( 162 x 229 ) mm = ( 6.38 x 9.02 ) in - 'C6' => array( 323.150, 459.213), // = ( 114 x 162 ) mm = ( 4.49 x 6.38 ) in - 'C7' => array( 229.606, 323.150), // = ( 81 x 114 ) mm = ( 3.19 x 4.49 ) in - 'C8' => array( 161.575, 229.606), // = ( 57 x 81 ) mm = ( 2.24 x 3.19 ) in - 'C9' => array( 113.386, 161.575), // = ( 40 x 57 ) mm = ( 1.57 x 2.24 ) in - 'C10' => array( 79.370, 113.386), // = ( 28 x 40 ) mm = ( 1.10 x 1.57 ) in - 'C11' => array( 56.693, 79.370), // = ( 20 x 28 ) mm = ( 0.79 x 1.10 ) in - 'C12' => array( 39.685, 56.693), // = ( 14 x 20 ) mm = ( 0.55 x 0.79 ) in - 'C76' => array( 229.606, 459.213), // = ( 81 x 162 ) mm = ( 3.19 x 6.38 ) in - 'DL' => array( 311.811, 623.622), // = ( 110 x 220 ) mm = ( 4.33 x 8.66 ) in - 'DLE' => array( 323.150, 637.795), // = ( 114 x 225 ) mm = ( 4.49 x 8.86 ) in - 'DLX' => array( 340.158, 666.142), // = ( 120 x 235 ) mm = ( 4.72 x 9.25 ) in - 'DLP' => array( 280.630, 595.276), // = ( 99 x 210 ) mm = ( 3.90 x 8.27 ) in (1/3 A4) - // SIS 014711 E Series - 'E0' => array( 2491.654, 3517.795), // = ( 879 x 1241 ) mm = ( 34.61 x 48.86 ) in - 'E1' => array( 1757.480, 2491.654), // = ( 620 x 879 ) mm = ( 24.41 x 34.61 ) in - 'E2' => array( 1247.244, 1757.480), // = ( 440 x 620 ) mm = ( 17.32 x 24.41 ) in - 'E3' => array( 878.740, 1247.244), // = ( 310 x 440 ) mm = ( 12.20 x 17.32 ) in - 'E4' => array( 623.622, 878.740), // = ( 220 x 310 ) mm = ( 8.66 x 12.20 ) in - 'E5' => array( 439.370, 623.622), // = ( 155 x 220 ) mm = ( 6.10 x 8.66 ) in - 'E6' => array( 311.811, 439.370), // = ( 110 x 155 ) mm = ( 4.33 x 6.10 ) in - 'E7' => array( 221.102, 311.811), // = ( 78 x 110 ) mm = ( 3.07 x 4.33 ) in - 'E8' => array( 155.906, 221.102), // = ( 55 x 78 ) mm = ( 2.17 x 3.07 ) in - 'E9' => array( 110.551, 155.906), // = ( 39 x 55 ) mm = ( 1.54 x 2.17 ) in - 'E10' => array( 76.535, 110.551), // = ( 27 x 39 ) mm = ( 1.06 x 1.54 ) in - 'E11' => array( 53.858, 76.535), // = ( 19 x 27 ) mm = ( 0.75 x 1.06 ) in - 'E12' => array( 36.850, 53.858), // = ( 13 x 19 ) mm = ( 0.51 x 0.75 ) in - // SIS 014711 G Series - 'G0' => array( 2715.591, 3838.110), // = ( 958 x 1354 ) mm = ( 37.72 x 53.31 ) in - 'G1' => array( 1919.055, 2715.591), // = ( 677 x 958 ) mm = ( 26.65 x 37.72 ) in - 'G2' => array( 1357.795, 1919.055), // = ( 479 x 677 ) mm = ( 18.86 x 26.65 ) in - 'G3' => array( 958.110, 1357.795), // = ( 338 x 479 ) mm = ( 13.31 x 18.86 ) in - 'G4' => array( 677.480, 958.110), // = ( 239 x 338 ) mm = ( 9.41 x 13.31 ) in - 'G5' => array( 479.055, 677.480), // = ( 169 x 239 ) mm = ( 6.65 x 9.41 ) in - 'G6' => array( 337.323, 479.055), // = ( 119 x 169 ) mm = ( 4.69 x 6.65 ) in - 'G7' => array( 238.110, 337.323), // = ( 84 x 119 ) mm = ( 3.31 x 4.69 ) in - 'G8' => array( 167.244, 238.110), // = ( 59 x 84 ) mm = ( 2.32 x 3.31 ) in - 'G9' => array( 119.055, 167.244), // = ( 42 x 59 ) mm = ( 1.65 x 2.32 ) in - 'G10' => array( 82.205, 119.055), // = ( 29 x 42 ) mm = ( 1.14 x 1.65 ) in - 'G11' => array( 59.528, 82.205), // = ( 21 x 29 ) mm = ( 0.83 x 1.14 ) in - 'G12' => array( 39.685, 59.528), // = ( 14 x 21 ) mm = ( 0.55 x 0.83 ) in - // ISO Press - 'RA0' => array( 2437.795, 3458.268), // = ( 860 x 1220 ) mm = ( 33.86 x 48.03 ) in - 'RA1' => array( 1729.134, 2437.795), // = ( 610 x 860 ) mm = ( 24.02 x 33.86 ) in - 'RA2' => array( 1218.898, 1729.134), // = ( 430 x 610 ) mm = ( 16.93 x 24.02 ) in - 'RA3' => array( 864.567, 1218.898), // = ( 305 x 430 ) mm = ( 12.01 x 16.93 ) in - 'RA4' => array( 609.449, 864.567), // = ( 215 x 305 ) mm = ( 8.46 x 12.01 ) in - 'SRA0' => array( 2551.181, 3628.346), // = ( 900 x 1280 ) mm = ( 35.43 x 50.39 ) in - 'SRA1' => array( 1814.173, 2551.181), // = ( 640 x 900 ) mm = ( 25.20 x 35.43 ) in - 'SRA2' => array( 1275.591, 1814.173), // = ( 450 x 640 ) mm = ( 17.72 x 25.20 ) in - 'SRA3' => array( 907.087, 1275.591), // = ( 320 x 450 ) mm = ( 12.60 x 17.72 ) in - 'SRA4' => array( 637.795, 907.087), // = ( 225 x 320 ) mm = ( 8.86 x 12.60 ) in - // German DIN 476 - '4A0' => array( 4767.874, 6740.787), // = ( 1682 x 2378 ) mm = ( 66.22 x 93.62 ) in - '2A0' => array( 3370.394, 4767.874), // = ( 1189 x 1682 ) mm = ( 46.81 x 66.22 ) in - // Variations on the ISO Standard - 'A2_EXTRA' => array( 1261.417, 1754.646), // = ( 445 x 619 ) mm = ( 17.52 x 24.37 ) in - 'A3+' => array( 932.598, 1369.134), // = ( 329 x 483 ) mm = ( 12.95 x 19.02 ) in - 'A3_EXTRA' => array( 912.756, 1261.417), // = ( 322 x 445 ) mm = ( 12.68 x 17.52 ) in - 'A3_SUPER' => array( 864.567, 1440.000), // = ( 305 x 508 ) mm = ( 12.01 x 20.00 ) in - 'SUPER_A3' => array( 864.567, 1380.472), // = ( 305 x 487 ) mm = ( 12.01 x 19.17 ) in - 'A4_EXTRA' => array( 666.142, 912.756), // = ( 235 x 322 ) mm = ( 9.25 x 12.68 ) in - 'A4_SUPER' => array( 649.134, 912.756), // = ( 229 x 322 ) mm = ( 9.02 x 12.68 ) in - 'SUPER_A4' => array( 643.465, 1009.134), // = ( 227 x 356 ) mm = ( 8.94 x 14.02 ) in - 'A4_LONG' => array( 595.276, 986.457), // = ( 210 x 348 ) mm = ( 8.27 x 13.70 ) in - 'F4' => array( 595.276, 935.433), // = ( 210 x 330 ) mm = ( 8.27 x 12.99 ) in - 'SO_B5_EXTRA' => array( 572.598, 782.362), // = ( 202 x 276 ) mm = ( 7.95 x 10.87 ) in - 'A5_EXTRA' => array( 490.394, 666.142), // = ( 173 x 235 ) mm = ( 6.81 x 9.25 ) in - // ANSI Series - 'ANSI_E' => array( 2448.000, 3168.000), // = ( 864 x 1118 ) mm = ( 34.00 x 44.00 ) in - 'ANSI_D' => array( 1584.000, 2448.000), // = ( 559 x 864 ) mm = ( 22.00 x 34.00 ) in - 'ANSI_C' => array( 1224.000, 1584.000), // = ( 432 x 559 ) mm = ( 17.00 x 22.00 ) in - 'ANSI_B' => array( 792.000, 1224.000), // = ( 279 x 432 ) mm = ( 11.00 x 17.00 ) in - 'ANSI_A' => array( 612.000, 792.000), // = ( 216 x 279 ) mm = ( 8.50 x 11.00 ) in - // Traditional 'Loose' North American Paper Sizes - 'USLEDGER' => array( 1224.000, 792.000), // = ( 432 x 279 ) mm = ( 17.00 x 11.00 ) in - 'LEDGER' => array( 1224.000, 792.000), // = ( 432 x 279 ) mm = ( 17.00 x 11.00 ) in - 'ORGANIZERK' => array( 792.000, 1224.000), // = ( 279 x 432 ) mm = ( 11.00 x 17.00 ) in - 'BIBLE' => array( 792.000, 1224.000), // = ( 279 x 432 ) mm = ( 11.00 x 17.00 ) in - 'USTABLOID' => array( 792.000, 1224.000), // = ( 279 x 432 ) mm = ( 11.00 x 17.00 ) in - 'TABLOID' => array( 792.000, 1224.000), // = ( 279 x 432 ) mm = ( 11.00 x 17.00 ) in - 'ORGANIZERM' => array( 612.000, 792.000), // = ( 216 x 279 ) mm = ( 8.50 x 11.00 ) in - 'USLETTER' => array( 612.000, 792.000), // = ( 216 x 279 ) mm = ( 8.50 x 11.00 ) in - 'LETTER' => array( 612.000, 792.000), // = ( 216 x 279 ) mm = ( 8.50 x 11.00 ) in - 'USLEGAL' => array( 612.000, 1008.000), // = ( 216 x 356 ) mm = ( 8.50 x 14.00 ) in - 'LEGAL' => array( 612.000, 1008.000), // = ( 216 x 356 ) mm = ( 8.50 x 14.00 ) in - 'GOVERNMENTLETTER' => array( 576.000, 756.000), // = ( 203 x 267 ) mm = ( 8.00 x 10.50 ) in - 'GLETTER' => array( 576.000, 756.000), // = ( 203 x 267 ) mm = ( 8.00 x 10.50 ) in - 'JUNIORLEGAL' => array( 576.000, 360.000), // = ( 203 x 127 ) mm = ( 8.00 x 5.00 ) in - 'JLEGAL' => array( 576.000, 360.000), // = ( 203 x 127 ) mm = ( 8.00 x 5.00 ) in - // Other North American Paper Sizes - 'QUADDEMY' => array( 2520.000, 3240.000), // = ( 889 x 1143 ) mm = ( 35.00 x 45.00 ) in - 'SUPER_B' => array( 936.000, 1368.000), // = ( 330 x 483 ) mm = ( 13.00 x 19.00 ) in - 'QUARTO' => array( 648.000, 792.000), // = ( 229 x 279 ) mm = ( 9.00 x 11.00 ) in - 'GOVERNMENTLEGAL' => array( 612.000, 936.000), // = ( 216 x 330 ) mm = ( 8.50 x 13.00 ) in - 'FOLIO' => array( 612.000, 936.000), // = ( 216 x 330 ) mm = ( 8.50 x 13.00 ) in - 'MONARCH' => array( 522.000, 756.000), // = ( 184 x 267 ) mm = ( 7.25 x 10.50 ) in - 'EXECUTIVE' => array( 522.000, 756.000), // = ( 184 x 267 ) mm = ( 7.25 x 10.50 ) in - 'ORGANIZERL' => array( 396.000, 612.000), // = ( 140 x 216 ) mm = ( 5.50 x 8.50 ) in - 'STATEMENT' => array( 396.000, 612.000), // = ( 140 x 216 ) mm = ( 5.50 x 8.50 ) in - 'MEMO' => array( 396.000, 612.000), // = ( 140 x 216 ) mm = ( 5.50 x 8.50 ) in - 'FOOLSCAP' => array( 595.440, 936.000), // = ( 210 x 330 ) mm = ( 8.27 x 13.00 ) in - 'COMPACT' => array( 306.000, 486.000), // = ( 108 x 171 ) mm = ( 4.25 x 6.75 ) in - 'ORGANIZERJ' => array( 198.000, 360.000), // = ( 70 x 127 ) mm = ( 2.75 x 5.00 ) in - // Canadian standard CAN 2-9.60M - 'P1' => array( 1587.402, 2437.795), // = ( 560 x 860 ) mm = ( 22.05 x 33.86 ) in - 'P2' => array( 1218.898, 1587.402), // = ( 430 x 560 ) mm = ( 16.93 x 22.05 ) in - 'P3' => array( 793.701, 1218.898), // = ( 280 x 430 ) mm = ( 11.02 x 16.93 ) in - 'P4' => array( 609.449, 793.701), // = ( 215 x 280 ) mm = ( 8.46 x 11.02 ) in - 'P5' => array( 396.850, 609.449), // = ( 140 x 215 ) mm = ( 5.51 x 8.46 ) in - 'P6' => array( 303.307, 396.850), // = ( 107 x 140 ) mm = ( 4.21 x 5.51 ) in - // North American Architectural Sizes - 'ARCH_E' => array( 2592.000, 3456.000), // = ( 914 x 1219 ) mm = ( 36.00 x 48.00 ) in - 'ARCH_E1' => array( 2160.000, 3024.000), // = ( 762 x 1067 ) mm = ( 30.00 x 42.00 ) in - 'ARCH_D' => array( 1728.000, 2592.000), // = ( 610 x 914 ) mm = ( 24.00 x 36.00 ) in - 'BROADSHEET' => array( 1296.000, 1728.000), // = ( 457 x 610 ) mm = ( 18.00 x 24.00 ) in - 'ARCH_C' => array( 1296.000, 1728.000), // = ( 457 x 610 ) mm = ( 18.00 x 24.00 ) in - 'ARCH_B' => array( 864.000, 1296.000), // = ( 305 x 457 ) mm = ( 12.00 x 18.00 ) in - 'ARCH_A' => array( 648.000, 864.000), // = ( 229 x 305 ) mm = ( 9.00 x 12.00 ) in - // -- North American Envelope Sizes - // - Announcement Envelopes - 'ANNENV_A2' => array( 314.640, 414.000), // = ( 111 x 146 ) mm = ( 4.37 x 5.75 ) in - 'ANNENV_A6' => array( 342.000, 468.000), // = ( 121 x 165 ) mm = ( 4.75 x 6.50 ) in - 'ANNENV_A7' => array( 378.000, 522.000), // = ( 133 x 184 ) mm = ( 5.25 x 7.25 ) in - 'ANNENV_A8' => array( 396.000, 584.640), // = ( 140 x 206 ) mm = ( 5.50 x 8.12 ) in - 'ANNENV_A10' => array( 450.000, 692.640), // = ( 159 x 244 ) mm = ( 6.25 x 9.62 ) in - 'ANNENV_SLIM' => array( 278.640, 638.640), // = ( 98 x 225 ) mm = ( 3.87 x 8.87 ) in - // - Commercial Envelopes - 'COMMENV_N6_1/4' => array( 252.000, 432.000), // = ( 89 x 152 ) mm = ( 3.50 x 6.00 ) in - 'COMMENV_N6_3/4' => array( 260.640, 468.000), // = ( 92 x 165 ) mm = ( 3.62 x 6.50 ) in - 'COMMENV_N8' => array( 278.640, 540.000), // = ( 98 x 191 ) mm = ( 3.87 x 7.50 ) in - 'COMMENV_N9' => array( 278.640, 638.640), // = ( 98 x 225 ) mm = ( 3.87 x 8.87 ) in - 'COMMENV_N10' => array( 296.640, 684.000), // = ( 105 x 241 ) mm = ( 4.12 x 9.50 ) in - 'COMMENV_N11' => array( 324.000, 746.640), // = ( 114 x 263 ) mm = ( 4.50 x 10.37 ) in - 'COMMENV_N12' => array( 342.000, 792.000), // = ( 121 x 279 ) mm = ( 4.75 x 11.00 ) in - 'COMMENV_N14' => array( 360.000, 828.000), // = ( 127 x 292 ) mm = ( 5.00 x 11.50 ) in - // - Catalogue Envelopes - 'CATENV_N1' => array( 432.000, 648.000), // = ( 152 x 229 ) mm = ( 6.00 x 9.00 ) in - 'CATENV_N1_3/4' => array( 468.000, 684.000), // = ( 165 x 241 ) mm = ( 6.50 x 9.50 ) in - 'CATENV_N2' => array( 468.000, 720.000), // = ( 165 x 254 ) mm = ( 6.50 x 10.00 ) in - 'CATENV_N3' => array( 504.000, 720.000), // = ( 178 x 254 ) mm = ( 7.00 x 10.00 ) in - 'CATENV_N6' => array( 540.000, 756.000), // = ( 191 x 267 ) mm = ( 7.50 x 10.50 ) in - 'CATENV_N7' => array( 576.000, 792.000), // = ( 203 x 279 ) mm = ( 8.00 x 11.00 ) in - 'CATENV_N8' => array( 594.000, 810.000), // = ( 210 x 286 ) mm = ( 8.25 x 11.25 ) in - 'CATENV_N9_1/2' => array( 612.000, 756.000), // = ( 216 x 267 ) mm = ( 8.50 x 10.50 ) in - 'CATENV_N9_3/4' => array( 630.000, 810.000), // = ( 222 x 286 ) mm = ( 8.75 x 11.25 ) in - 'CATENV_N10_1/2' => array( 648.000, 864.000), // = ( 229 x 305 ) mm = ( 9.00 x 12.00 ) in - 'CATENV_N12_1/2' => array( 684.000, 900.000), // = ( 241 x 318 ) mm = ( 9.50 x 12.50 ) in - 'CATENV_N13_1/2' => array( 720.000, 936.000), // = ( 254 x 330 ) mm = ( 10.00 x 13.00 ) in - 'CATENV_N14_1/4' => array( 810.000, 882.000), // = ( 286 x 311 ) mm = ( 11.25 x 12.25 ) in - 'CATENV_N14_1/2' => array( 828.000, 1044.000), // = ( 292 x 368 ) mm = ( 11.50 x 14.50 ) in - // Japanese (JIS P 0138-61) Standard B-Series - 'JIS_B0' => array( 2919.685, 4127.244), // = ( 1030 x 1456 ) mm = ( 40.55 x 57.32 ) in - 'JIS_B1' => array( 2063.622, 2919.685), // = ( 728 x 1030 ) mm = ( 28.66 x 40.55 ) in - 'JIS_B2' => array( 1459.843, 2063.622), // = ( 515 x 728 ) mm = ( 20.28 x 28.66 ) in - 'JIS_B3' => array( 1031.811, 1459.843), // = ( 364 x 515 ) mm = ( 14.33 x 20.28 ) in - 'JIS_B4' => array( 728.504, 1031.811), // = ( 257 x 364 ) mm = ( 10.12 x 14.33 ) in - 'JIS_B5' => array( 515.906, 728.504), // = ( 182 x 257 ) mm = ( 7.17 x 10.12 ) in - 'JIS_B6' => array( 362.835, 515.906), // = ( 128 x 182 ) mm = ( 5.04 x 7.17 ) in - 'JIS_B7' => array( 257.953, 362.835), // = ( 91 x 128 ) mm = ( 3.58 x 5.04 ) in - 'JIS_B8' => array( 181.417, 257.953), // = ( 64 x 91 ) mm = ( 2.52 x 3.58 ) in - 'JIS_B9' => array( 127.559, 181.417), // = ( 45 x 64 ) mm = ( 1.77 x 2.52 ) in - 'JIS_B10' => array( 90.709, 127.559), // = ( 32 x 45 ) mm = ( 1.26 x 1.77 ) in - 'JIS_B11' => array( 62.362, 90.709), // = ( 22 x 32 ) mm = ( 0.87 x 1.26 ) in - 'JIS_B12' => array( 45.354, 62.362), // = ( 16 x 22 ) mm = ( 0.63 x 0.87 ) in - // PA Series - 'PA0' => array( 2381.102, 3174.803), // = ( 840 x 1120 ) mm = ( 33.07 x 44.09 ) in - 'PA1' => array( 1587.402, 2381.102), // = ( 560 x 840 ) mm = ( 22.05 x 33.07 ) in - 'PA2' => array( 1190.551, 1587.402), // = ( 420 x 560 ) mm = ( 16.54 x 22.05 ) in - 'PA3' => array( 793.701, 1190.551), // = ( 280 x 420 ) mm = ( 11.02 x 16.54 ) in - 'PA4' => array( 595.276, 793.701), // = ( 210 x 280 ) mm = ( 8.27 x 11.02 ) in - 'PA5' => array( 396.850, 595.276), // = ( 140 x 210 ) mm = ( 5.51 x 8.27 ) in - 'PA6' => array( 297.638, 396.850), // = ( 105 x 140 ) mm = ( 4.13 x 5.51 ) in - 'PA7' => array( 198.425, 297.638), // = ( 70 x 105 ) mm = ( 2.76 x 4.13 ) in - 'PA8' => array( 147.402, 198.425), // = ( 52 x 70 ) mm = ( 2.05 x 2.76 ) in - 'PA9' => array( 99.213, 147.402), // = ( 35 x 52 ) mm = ( 1.38 x 2.05 ) in - 'PA10' => array( 73.701, 99.213), // = ( 26 x 35 ) mm = ( 1.02 x 1.38 ) in - // Standard Photographic Print Sizes - 'PASSPORT_PHOTO' => array( 99.213, 127.559), // = ( 35 x 45 ) mm = ( 1.38 x 1.77 ) in - 'E' => array( 233.858, 340.157), // = ( 82 x 120 ) mm = ( 3.25 x 4.72 ) in - 'L' => array( 252.283, 360.000), // = ( 89 x 127 ) mm = ( 3.50 x 5.00 ) in - '3R' => array( 252.283, 360.000), // = ( 89 x 127 ) mm = ( 3.50 x 5.00 ) in - 'KG' => array( 289.134, 430.866), // = ( 102 x 152 ) mm = ( 4.02 x 5.98 ) in - '4R' => array( 289.134, 430.866), // = ( 102 x 152 ) mm = ( 4.02 x 5.98 ) in - '4D' => array( 340.157, 430.866), // = ( 120 x 152 ) mm = ( 4.72 x 5.98 ) in - '2L' => array( 360.000, 504.567), // = ( 127 x 178 ) mm = ( 5.00 x 7.01 ) in - '5R' => array( 360.000, 504.567), // = ( 127 x 178 ) mm = ( 5.00 x 7.01 ) in - '8P' => array( 430.866, 575.433), // = ( 152 x 203 ) mm = ( 5.98 x 7.99 ) in - '6R' => array( 430.866, 575.433), // = ( 152 x 203 ) mm = ( 5.98 x 7.99 ) in - '6P' => array( 575.433, 720.000), // = ( 203 x 254 ) mm = ( 7.99 x 10.00 ) in - '8R' => array( 575.433, 720.000), // = ( 203 x 254 ) mm = ( 7.99 x 10.00 ) in - '6PW' => array( 575.433, 864.567), // = ( 203 x 305 ) mm = ( 7.99 x 12.01 ) in - 'S8R' => array( 575.433, 864.567), // = ( 203 x 305 ) mm = ( 7.99 x 12.01 ) in - '4P' => array( 720.000, 864.567), // = ( 254 x 305 ) mm = ( 10.00 x 12.01 ) in - '10R' => array( 720.000, 864.567), // = ( 254 x 305 ) mm = ( 10.00 x 12.01 ) in - '4PW' => array( 720.000, 1080.000), // = ( 254 x 381 ) mm = ( 10.00 x 15.00 ) in - 'S10R' => array( 720.000, 1080.000), // = ( 254 x 381 ) mm = ( 10.00 x 15.00 ) in - '11R' => array( 790.866, 1009.134), // = ( 279 x 356 ) mm = ( 10.98 x 14.02 ) in - 'S11R' => array( 790.866, 1224.567), // = ( 279 x 432 ) mm = ( 10.98 x 17.01 ) in - '12R' => array( 864.567, 1080.000), // = ( 305 x 381 ) mm = ( 12.01 x 15.00 ) in - 'S12R' => array( 864.567, 1292.598), // = ( 305 x 456 ) mm = ( 12.01 x 17.95 ) in - // Common Newspaper Sizes - 'NEWSPAPER_BROADSHEET' => array( 2125.984, 1700.787), // = ( 750 x 600 ) mm = ( 29.53 x 23.62 ) in - 'NEWSPAPER_BERLINER' => array( 1332.283, 892.913), // = ( 470 x 315 ) mm = ( 18.50 x 12.40 ) in - 'NEWSPAPER_TABLOID' => array( 1218.898, 793.701), // = ( 430 x 280 ) mm = ( 16.93 x 11.02 ) in - 'NEWSPAPER_COMPACT' => array( 1218.898, 793.701), // = ( 430 x 280 ) mm = ( 16.93 x 11.02 ) in - // Business Cards - 'CREDIT_CARD' => array( 153.014, 242.646), // = ( 54 x 86 ) mm = ( 2.13 x 3.37 ) in - 'BUSINESS_CARD' => array( 153.014, 242.646), // = ( 54 x 86 ) mm = ( 2.13 x 3.37 ) in - 'BUSINESS_CARD_ISO7810' => array( 153.014, 242.646), // = ( 54 x 86 ) mm = ( 2.13 x 3.37 ) in - 'BUSINESS_CARD_ISO216' => array( 147.402, 209.764), // = ( 52 x 74 ) mm = ( 2.05 x 2.91 ) in - 'BUSINESS_CARD_IT' => array( 155.906, 240.945), // = ( 55 x 85 ) mm = ( 2.17 x 3.35 ) in - 'BUSINESS_CARD_UK' => array( 155.906, 240.945), // = ( 55 x 85 ) mm = ( 2.17 x 3.35 ) in - 'BUSINESS_CARD_FR' => array( 155.906, 240.945), // = ( 55 x 85 ) mm = ( 2.17 x 3.35 ) in - 'BUSINESS_CARD_DE' => array( 155.906, 240.945), // = ( 55 x 85 ) mm = ( 2.17 x 3.35 ) in - 'BUSINESS_CARD_ES' => array( 155.906, 240.945), // = ( 55 x 85 ) mm = ( 2.17 x 3.35 ) in - 'BUSINESS_CARD_CA' => array( 144.567, 252.283), // = ( 51 x 89 ) mm = ( 2.01 x 3.50 ) in - 'BUSINESS_CARD_US' => array( 144.567, 252.283), // = ( 51 x 89 ) mm = ( 2.01 x 3.50 ) in - 'BUSINESS_CARD_JP' => array( 155.906, 257.953), // = ( 55 x 91 ) mm = ( 2.17 x 3.58 ) in - 'BUSINESS_CARD_HK' => array( 153.071, 255.118), // = ( 54 x 90 ) mm = ( 2.13 x 3.54 ) in - 'BUSINESS_CARD_AU' => array( 155.906, 255.118), // = ( 55 x 90 ) mm = ( 2.17 x 3.54 ) in - 'BUSINESS_CARD_DK' => array( 155.906, 255.118), // = ( 55 x 90 ) mm = ( 2.17 x 3.54 ) in - 'BUSINESS_CARD_SE' => array( 155.906, 255.118), // = ( 55 x 90 ) mm = ( 2.17 x 3.54 ) in - 'BUSINESS_CARD_RU' => array( 141.732, 255.118), // = ( 50 x 90 ) mm = ( 1.97 x 3.54 ) in - 'BUSINESS_CARD_CZ' => array( 141.732, 255.118), // = ( 50 x 90 ) mm = ( 1.97 x 3.54 ) in - 'BUSINESS_CARD_FI' => array( 141.732, 255.118), // = ( 50 x 90 ) mm = ( 1.97 x 3.54 ) in - 'BUSINESS_CARD_HU' => array( 141.732, 255.118), // = ( 50 x 90 ) mm = ( 1.97 x 3.54 ) in - 'BUSINESS_CARD_IL' => array( 141.732, 255.118), // = ( 50 x 90 ) mm = ( 1.97 x 3.54 ) in - // Billboards - '4SHEET' => array( 2880.000, 4320.000), // = ( 1016 x 1524 ) mm = ( 40.00 x 60.00 ) in - '6SHEET' => array( 3401.575, 5102.362), // = ( 1200 x 1800 ) mm = ( 47.24 x 70.87 ) in - '12SHEET' => array( 8640.000, 4320.000), // = ( 3048 x 1524 ) mm = (120.00 x 60.00 ) in - '16SHEET' => array( 5760.000, 8640.000), // = ( 2032 x 3048 ) mm = ( 80.00 x 120.00) in - '32SHEET' => array(11520.000, 8640.000), // = ( 4064 x 3048 ) mm = (160.00 x 120.00) in - '48SHEET' => array(17280.000, 8640.000), // = ( 6096 x 3048 ) mm = (240.00 x 120.00) in - '64SHEET' => array(23040.000, 8640.000), // = ( 8128 x 3048 ) mm = (320.00 x 120.00) in - '96SHEET' => array(34560.000, 8640.000), // = (12192 x 3048 ) mm = (480.00 x 120.00) in - // -- Old European Sizes - // - Old Imperial English Sizes - 'EN_EMPEROR' => array( 3456.000, 5184.000), // = ( 1219 x 1829 ) mm = ( 48.00 x 72.00 ) in - 'EN_ANTIQUARIAN' => array( 2232.000, 3816.000), // = ( 787 x 1346 ) mm = ( 31.00 x 53.00 ) in - 'EN_GRAND_EAGLE' => array( 2070.000, 3024.000), // = ( 730 x 1067 ) mm = ( 28.75 x 42.00 ) in - 'EN_DOUBLE_ELEPHANT' => array( 1926.000, 2880.000), // = ( 679 x 1016 ) mm = ( 26.75 x 40.00 ) in - 'EN_ATLAS' => array( 1872.000, 2448.000), // = ( 660 x 864 ) mm = ( 26.00 x 34.00 ) in - 'EN_COLOMBIER' => array( 1692.000, 2484.000), // = ( 597 x 876 ) mm = ( 23.50 x 34.50 ) in - 'EN_ELEPHANT' => array( 1656.000, 2016.000), // = ( 584 x 711 ) mm = ( 23.00 x 28.00 ) in - 'EN_DOUBLE_DEMY' => array( 1620.000, 2556.000), // = ( 572 x 902 ) mm = ( 22.50 x 35.50 ) in - 'EN_IMPERIAL' => array( 1584.000, 2160.000), // = ( 559 x 762 ) mm = ( 22.00 x 30.00 ) in - 'EN_PRINCESS' => array( 1548.000, 2016.000), // = ( 546 x 711 ) mm = ( 21.50 x 28.00 ) in - 'EN_CARTRIDGE' => array( 1512.000, 1872.000), // = ( 533 x 660 ) mm = ( 21.00 x 26.00 ) in - 'EN_DOUBLE_LARGE_POST' => array( 1512.000, 2376.000), // = ( 533 x 838 ) mm = ( 21.00 x 33.00 ) in - 'EN_ROYAL' => array( 1440.000, 1800.000), // = ( 508 x 635 ) mm = ( 20.00 x 25.00 ) in - 'EN_SHEET' => array( 1404.000, 1692.000), // = ( 495 x 597 ) mm = ( 19.50 x 23.50 ) in - 'EN_HALF_POST' => array( 1404.000, 1692.000), // = ( 495 x 597 ) mm = ( 19.50 x 23.50 ) in - 'EN_SUPER_ROYAL' => array( 1368.000, 1944.000), // = ( 483 x 686 ) mm = ( 19.00 x 27.00 ) in - 'EN_DOUBLE_POST' => array( 1368.000, 2196.000), // = ( 483 x 775 ) mm = ( 19.00 x 30.50 ) in - 'EN_MEDIUM' => array( 1260.000, 1656.000), // = ( 445 x 584 ) mm = ( 17.50 x 23.00 ) in - 'EN_DEMY' => array( 1260.000, 1620.000), // = ( 445 x 572 ) mm = ( 17.50 x 22.50 ) in - 'EN_LARGE_POST' => array( 1188.000, 1512.000), // = ( 419 x 533 ) mm = ( 16.50 x 21.00 ) in - 'EN_COPY_DRAUGHT' => array( 1152.000, 1440.000), // = ( 406 x 508 ) mm = ( 16.00 x 20.00 ) in - 'EN_POST' => array( 1116.000, 1386.000), // = ( 394 x 489 ) mm = ( 15.50 x 19.25 ) in - 'EN_CROWN' => array( 1080.000, 1440.000), // = ( 381 x 508 ) mm = ( 15.00 x 20.00 ) in - 'EN_PINCHED_POST' => array( 1062.000, 1332.000), // = ( 375 x 470 ) mm = ( 14.75 x 18.50 ) in - 'EN_BRIEF' => array( 972.000, 1152.000), // = ( 343 x 406 ) mm = ( 13.50 x 16.00 ) in - 'EN_FOOLSCAP' => array( 972.000, 1224.000), // = ( 343 x 432 ) mm = ( 13.50 x 17.00 ) in - 'EN_SMALL_FOOLSCAP' => array( 954.000, 1188.000), // = ( 337 x 419 ) mm = ( 13.25 x 16.50 ) in - 'EN_POTT' => array( 900.000, 1080.000), // = ( 318 x 381 ) mm = ( 12.50 x 15.00 ) in - // - Old Imperial Belgian Sizes - 'BE_GRAND_AIGLE' => array( 1984.252, 2948.031), // = ( 700 x 1040 ) mm = ( 27.56 x 40.94 ) in - 'BE_COLOMBIER' => array( 1757.480, 2409.449), // = ( 620 x 850 ) mm = ( 24.41 x 33.46 ) in - 'BE_DOUBLE_CARRE' => array( 1757.480, 2607.874), // = ( 620 x 920 ) mm = ( 24.41 x 36.22 ) in - 'BE_ELEPHANT' => array( 1746.142, 2182.677), // = ( 616 x 770 ) mm = ( 24.25 x 30.31 ) in - 'BE_PETIT_AIGLE' => array( 1700.787, 2381.102), // = ( 600 x 840 ) mm = ( 23.62 x 33.07 ) in - 'BE_GRAND_JESUS' => array( 1559.055, 2069.291), // = ( 550 x 730 ) mm = ( 21.65 x 28.74 ) in - 'BE_JESUS' => array( 1530.709, 2069.291), // = ( 540 x 730 ) mm = ( 21.26 x 28.74 ) in - 'BE_RAISIN' => array( 1417.323, 1842.520), // = ( 500 x 650 ) mm = ( 19.69 x 25.59 ) in - 'BE_GRAND_MEDIAN' => array( 1303.937, 1714.961), // = ( 460 x 605 ) mm = ( 18.11 x 23.82 ) in - 'BE_DOUBLE_POSTE' => array( 1233.071, 1601.575), // = ( 435 x 565 ) mm = ( 17.13 x 22.24 ) in - 'BE_COQUILLE' => array( 1218.898, 1587.402), // = ( 430 x 560 ) mm = ( 16.93 x 22.05 ) in - 'BE_PETIT_MEDIAN' => array( 1176.378, 1502.362), // = ( 415 x 530 ) mm = ( 16.34 x 20.87 ) in - 'BE_RUCHE' => array( 1020.472, 1303.937), // = ( 360 x 460 ) mm = ( 14.17 x 18.11 ) in - 'BE_PROPATRIA' => array( 977.953, 1218.898), // = ( 345 x 430 ) mm = ( 13.58 x 16.93 ) in - 'BE_LYS' => array( 898.583, 1125.354), // = ( 317 x 397 ) mm = ( 12.48 x 15.63 ) in - 'BE_POT' => array( 870.236, 1088.504), // = ( 307 x 384 ) mm = ( 12.09 x 15.12 ) in - 'BE_ROSETTE' => array( 765.354, 983.622), // = ( 270 x 347 ) mm = ( 10.63 x 13.66 ) in - // - Old Imperial French Sizes - 'FR_UNIVERS' => array( 2834.646, 3685.039), // = ( 1000 x 1300 ) mm = ( 39.37 x 51.18 ) in - 'FR_DOUBLE_COLOMBIER' => array( 2551.181, 3571.654), // = ( 900 x 1260 ) mm = ( 35.43 x 49.61 ) in - 'FR_GRANDE_MONDE' => array( 2551.181, 3571.654), // = ( 900 x 1260 ) mm = ( 35.43 x 49.61 ) in - 'FR_DOUBLE_SOLEIL' => array( 2267.717, 3401.575), // = ( 800 x 1200 ) mm = ( 31.50 x 47.24 ) in - 'FR_DOUBLE_JESUS' => array( 2154.331, 3174.803), // = ( 760 x 1120 ) mm = ( 29.92 x 44.09 ) in - 'FR_GRAND_AIGLE' => array( 2125.984, 3004.724), // = ( 750 x 1060 ) mm = ( 29.53 x 41.73 ) in - 'FR_PETIT_AIGLE' => array( 1984.252, 2664.567), // = ( 700 x 940 ) mm = ( 27.56 x 37.01 ) in - 'FR_DOUBLE_RAISIN' => array( 1842.520, 2834.646), // = ( 650 x 1000 ) mm = ( 25.59 x 39.37 ) in - 'FR_JOURNAL' => array( 1842.520, 2664.567), // = ( 650 x 940 ) mm = ( 25.59 x 37.01 ) in - 'FR_COLOMBIER_AFFICHE' => array( 1785.827, 2551.181), // = ( 630 x 900 ) mm = ( 24.80 x 35.43 ) in - 'FR_DOUBLE_CAVALIER' => array( 1757.480, 2607.874), // = ( 620 x 920 ) mm = ( 24.41 x 36.22 ) in - 'FR_CLOCHE' => array( 1700.787, 2267.717), // = ( 600 x 800 ) mm = ( 23.62 x 31.50 ) in - 'FR_SOLEIL' => array( 1700.787, 2267.717), // = ( 600 x 800 ) mm = ( 23.62 x 31.50 ) in - 'FR_DOUBLE_CARRE' => array( 1587.402, 2551.181), // = ( 560 x 900 ) mm = ( 22.05 x 35.43 ) in - 'FR_DOUBLE_COQUILLE' => array( 1587.402, 2494.488), // = ( 560 x 880 ) mm = ( 22.05 x 34.65 ) in - 'FR_JESUS' => array( 1587.402, 2154.331), // = ( 560 x 760 ) mm = ( 22.05 x 29.92 ) in - 'FR_RAISIN' => array( 1417.323, 1842.520), // = ( 500 x 650 ) mm = ( 19.69 x 25.59 ) in - 'FR_CAVALIER' => array( 1303.937, 1757.480), // = ( 460 x 620 ) mm = ( 18.11 x 24.41 ) in - 'FR_DOUBLE_COURONNE' => array( 1303.937, 2040.945), // = ( 460 x 720 ) mm = ( 18.11 x 28.35 ) in - 'FR_CARRE' => array( 1275.591, 1587.402), // = ( 450 x 560 ) mm = ( 17.72 x 22.05 ) in - 'FR_COQUILLE' => array( 1247.244, 1587.402), // = ( 440 x 560 ) mm = ( 17.32 x 22.05 ) in - 'FR_DOUBLE_TELLIERE' => array( 1247.244, 1927.559), // = ( 440 x 680 ) mm = ( 17.32 x 26.77 ) in - 'FR_DOUBLE_CLOCHE' => array( 1133.858, 1700.787), // = ( 400 x 600 ) mm = ( 15.75 x 23.62 ) in - 'FR_DOUBLE_POT' => array( 1133.858, 1757.480), // = ( 400 x 620 ) mm = ( 15.75 x 24.41 ) in - 'FR_ECU' => array( 1133.858, 1474.016), // = ( 400 x 520 ) mm = ( 15.75 x 20.47 ) in - 'FR_COURONNE' => array( 1020.472, 1303.937), // = ( 360 x 460 ) mm = ( 14.17 x 18.11 ) in - 'FR_TELLIERE' => array( 963.780, 1247.244), // = ( 340 x 440 ) mm = ( 13.39 x 17.32 ) in - 'FR_POT' => array( 878.740, 1133.858), // = ( 310 x 400 ) mm = ( 12.20 x 15.75 ) in - ); - - - /** - * Get page dimensions from format name. - * @param mixed $format The format name @see self::$page_format<ul> - * @return array containing page width and height in points - * @since 5.0.010 (2010-05-17) - * @public static - */ - public static function getPageSizeFromFormat($format) { - if (isset(self::$page_formats[$format])) { - return self::$page_formats[$format]; - } - return self::$page_formats['A4']; - } - - /** - * Set page boundaries. - * @param int $page page number - * @param string $type valid values are: <ul><li>'MediaBox' : the boundaries of the physical medium on which the page shall be displayed or printed;</li><li>'CropBox' : the visible region of default user space;</li><li>'BleedBox' : the region to which the contents of the page shall be clipped when output in a production environment;</li><li>'TrimBox' : the intended dimensions of the finished page after trimming;</li><li>'ArtBox' : the page's meaningful content (including potential white space).</li></ul> - * @param float $llx lower-left x coordinate in user units. - * @param float $lly lower-left y coordinate in user units. - * @param float $urx upper-right x coordinate in user units. - * @param float $ury upper-right y coordinate in user units. - * @param boolean $points If true uses user units as unit of measure, otherwise uses PDF points. - * @param float $k Scale factor (number of points in user unit). - * @param array $pagedim Array of page dimensions. - * @return array pagedim array of page dimensions. - * @since 5.0.010 (2010-05-17) - * @public static - */ - public static function setPageBoxes($page, $type, $llx, $lly, $urx, $ury, $points, $k, $pagedim=array()) { - if (!isset($pagedim[$page])) { - // initialize array - $pagedim[$page] = array(); - } - if (!in_array($type, self::$pageboxes)) { - return; - } - if ($points) { - $k = 1; - } - $pagedim[$page][$type]['llx'] = ($llx * $k); - $pagedim[$page][$type]['lly'] = ($lly * $k); - $pagedim[$page][$type]['urx'] = ($urx * $k); - $pagedim[$page][$type]['ury'] = ($ury * $k); - return $pagedim; - } - - /** - * Swap X and Y coordinates of page boxes (change page boxes orientation). - * @param int $page page number - * @param array $pagedim Array of page dimensions. - * @return array pagedim array of page dimensions. - * @since 5.0.010 (2010-05-17) - * @public static - */ - public static function swapPageBoxCoordinates($page, $pagedim) { - foreach (self::$pageboxes as $type) { - // swap X and Y coordinates - if (isset($pagedim[$page][$type])) { - $tmp = $pagedim[$page][$type]['llx']; - $pagedim[$page][$type]['llx'] = $pagedim[$page][$type]['lly']; - $pagedim[$page][$type]['lly'] = $tmp; - $tmp = $pagedim[$page][$type]['urx']; - $pagedim[$page][$type]['urx'] = $pagedim[$page][$type]['ury']; - $pagedim[$page][$type]['ury'] = $tmp; - } - } - return $pagedim; - } - - /** - * Get the canonical page layout mode. - * @param string $layout The page layout. Possible values are:<ul><li>SinglePage Display one page at a time</li><li>OneColumn Display the pages in one column</li><li>TwoColumnLeft Display the pages in two columns, with odd-numbered pages on the left</li><li>TwoColumnRight Display the pages in two columns, with odd-numbered pages on the right</li><li>TwoPageLeft (PDF 1.5) Display the pages two at a time, with odd-numbered pages on the left</li><li>TwoPageRight (PDF 1.5) Display the pages two at a time, with odd-numbered pages on the right</li></ul> - * @return string Canonical page layout name. - * @public static - */ - public static function getPageLayoutMode($layout='SinglePage') { - switch ($layout) { - case 'default': - case 'single': - case 'SinglePage': { - $layout_mode = 'SinglePage'; - break; - } - case 'continuous': - case 'OneColumn': { - $layout_mode = 'OneColumn'; - break; - } - case 'two': - case 'TwoColumnLeft': { - $layout_mode = 'TwoColumnLeft'; - break; - } - case 'TwoColumnRight': { - $layout_mode = 'TwoColumnRight'; - break; - } - case 'TwoPageLeft': { - $layout_mode = 'TwoPageLeft'; - break; - } - case 'TwoPageRight': { - $layout_mode = 'TwoPageRight'; - break; - } - default: { - $layout_mode = 'SinglePage'; - } - } - return $layout_mode; - } - - /** - * Get the canonical page layout mode. - * @param string $mode A name object specifying how the document should be displayed when opened:<ul><li>UseNone Neither document outline nor thumbnail images visible</li><li>UseOutlines Document outline visible</li><li>UseThumbs Thumbnail images visible</li><li>FullScreen Full-screen mode, with no menu bar, window controls, or any other window visible</li><li>UseOC (PDF 1.5) Optional content group panel visible</li><li>UseAttachments (PDF 1.6) Attachments panel visible</li></ul> - * @return string Canonical page mode name. - * @public static - */ - public static function getPageMode($mode='UseNone') { - switch ($mode) { - case 'UseNone': { - $page_mode = 'UseNone'; - break; - } - case 'UseOutlines': { - $page_mode = 'UseOutlines'; - break; - } - case 'UseThumbs': { - $page_mode = 'UseThumbs'; - break; - } - case 'FullScreen': { - $page_mode = 'FullScreen'; - break; - } - case 'UseOC': { - $page_mode = 'UseOC'; - break; - } - case '': { - $page_mode = 'UseAttachments'; - break; - } - default: { - $page_mode = 'UseNone'; - } - } - return $page_mode; - } - - -} // END OF TCPDF_STATIC CLASS - -//============================================================+ -// END OF FILE -//============================================================+ diff --git a/lib/combodo/tcpdf/tcpdf.php b/lib/combodo/tcpdf/tcpdf.php deleted file mode 100644 index 400434730..000000000 --- a/lib/combodo/tcpdf/tcpdf.php +++ /dev/null @@ -1,24729 +0,0 @@ -<?php -//============================================================+ -// File name : tcpdf.php -// Version : 6.4.4 -// Begin : 2002-08-03 -// Last Update : 2021-12-31 -// Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com -// License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html) -// ------------------------------------------------------------------- -// Copyright (C) 2002-2021 Nicola Asuni - Tecnick.com LTD -// -// This file is part of TCPDF software library. -// -// TCPDF is free software: you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// TCPDF is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// -// You should have received a copy of the License -// along with TCPDF. If not, see -// <http://www.tecnick.com/pagefiles/tcpdf/LICENSE.TXT>. -// -// See LICENSE.TXT file for more information. -// ------------------------------------------------------------------- -// -// Description : -// This is a PHP class for generating PDF documents without requiring external extensions. -// -// NOTE: -// This class was originally derived in 2002 from the Public -// Domain FPDF class by Olivier Plathey (http://www.fpdf.org), -// but now is almost entirely rewritten and contains thousands of -// new lines of code and hundreds new features. -// -// Main features: -// * no external libraries are required for the basic functions; -// * all standard page formats, custom page formats, custom margins and units of measure; -// * UTF-8 Unicode and Right-To-Left languages; -// * TrueTypeUnicode, TrueType, Type1 and CID-0 fonts; -// * font subsetting; -// * methods to publish some XHTML + CSS code, Javascript and Forms; -// * images, graphic (geometric figures) and transformation methods; -// * supports JPEG, PNG and SVG images natively, all images supported by GD (GD, GD2, GD2PART, GIF, JPEG, PNG, BMP, XBM, XPM) and all images supported via ImageMagick (http://www.imagemagick.org/www/formats.html) -// * 1D and 2D barcodes: CODE 39, ANSI MH10.8M-1983, USD-3, 3 of 9, CODE 93, USS-93, Standard 2 of 5, Interleaved 2 of 5, CODE 128 A/B/C, 2 and 5 Digits UPC-Based Extension, EAN 8, EAN 13, UPC-A, UPC-E, MSI, POSTNET, PLANET, RMS4CC (Royal Mail 4-state Customer Code), CBC (Customer Bar Code), KIX (Klant index - Customer index), Intelligent Mail Barcode, Onecode, USPS-B-3200, CODABAR, CODE 11, PHARMACODE, PHARMACODE TWO-TRACKS, Datamatrix, QR-Code, PDF417; -// * JPEG and PNG ICC profiles, Grayscale, RGB, CMYK, Spot Colors and Transparencies; -// * automatic page header and footer management; -// * document encryption up to 256 bit and digital signature certifications; -// * transactions to UNDO commands; -// * PDF annotations, including links, text and file attachments; -// * text rendering modes (fill, stroke and clipping); -// * multiple columns mode; -// * no-write page regions; -// * bookmarks, named destinations and table of content; -// * text hyphenation; -// * text stretching and spacing (tracking); -// * automatic page break, line break and text alignments including justification; -// * automatic page numbering and page groups; -// * move and delete pages; -// * page compression (requires php-zlib extension); -// * XOBject Templates; -// * Layers and object visibility. -// * PDF/A-1b support -//============================================================+ - -/** - * @file - * This is a PHP class for generating PDF documents without requiring external extensions.<br> - * TCPDF project (http://www.tcpdf.org) was originally derived in 2002 from the Public Domain FPDF class by Olivier Plathey (http://www.fpdf.org), but now is almost entirely rewritten.<br> - * <h3>TCPDF main features are:</h3> - * <ul> - * <li>no external libraries are required for the basic functions;</li> - * <li>all standard page formats, custom page formats, custom margins and units of measure;</li> - * <li>UTF-8 Unicode and Right-To-Left languages;</li> - * <li>TrueTypeUnicode, TrueType, Type1 and CID-0 fonts;</li> - * <li>font subsetting;</li> - * <li>methods to publish some XHTML + CSS code, Javascript and Forms;</li> - * <li>images, graphic (geometric figures) and transformation methods; - * <li>supports JPEG, PNG and SVG images natively, all images supported by GD (GD, GD2, GD2PART, GIF, JPEG, PNG, BMP, XBM, XPM) and all images supported via ImageMagick (http://www.imagemagick.org/www/formats.html)</li> - * <li>1D and 2D barcodes: CODE 39, ANSI MH10.8M-1983, USD-3, 3 of 9, CODE 93, USS-93, Standard 2 of 5, Interleaved 2 of 5, CODE 128 A/B/C, 2 and 5 Digits UPC-Based Extension, EAN 8, EAN 13, UPC-A, UPC-E, MSI, POSTNET, PLANET, RMS4CC (Royal Mail 4-state Customer Code), CBC (Customer Bar Code), KIX (Klant index - Customer index), Intelligent Mail Barcode, Onecode, USPS-B-3200, CODABAR, CODE 11, PHARMACODE, PHARMACODE TWO-TRACKS, Datamatrix, QR-Code, PDF417;</li> - * <li>JPEG and PNG ICC profiles, Grayscale, RGB, CMYK, Spot Colors and Transparencies;</li> - * <li>automatic page header and footer management;</li> - * <li>document encryption up to 256 bit and digital signature certifications;</li> - * <li>transactions to UNDO commands;</li> - * <li>PDF annotations, including links, text and file attachments;</li> - * <li>text rendering modes (fill, stroke and clipping);</li> - * <li>multiple columns mode;</li> - * <li>no-write page regions;</li> - * <li>bookmarks, named destinations and table of content;</li> - * <li>text hyphenation;</li> - * <li>text stretching and spacing (tracking);</li> - * <li>automatic page break, line break and text alignments including justification;</li> - * <li>automatic page numbering and page groups;</li> - * <li>move and delete pages;</li> - * <li>page compression (requires php-zlib extension);</li> - * <li>XOBject Templates;</li> - * <li>Layers and object visibility;</li> - * <li>PDF/A-1b support.</li> - * </ul> - * Tools to encode your unicode fonts are on fonts/utils directory.</p> - * @package com.tecnick.tcpdf - * @author Nicola Asuni - * @version 6.3.2 - */ - -// TCPDF configuration -require_once(dirname(__FILE__).'/tcpdf_autoconfig.php'); -// TCPDF static font methods and data -require_once(dirname(__FILE__).'/include/tcpdf_font_data.php'); -// TCPDF static font methods and data -require_once(dirname(__FILE__).'/include/tcpdf_fonts.php'); -// TCPDF static color methods and data -require_once(dirname(__FILE__).'/include/tcpdf_colors.php'); -// TCPDF static image methods and data -require_once(dirname(__FILE__).'/include/tcpdf_images.php'); -// TCPDF static methods and data -require_once(dirname(__FILE__).'/include/tcpdf_static.php'); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/** - * @class TCPDF - * PHP class for generating PDF documents without requiring external extensions. - * TCPDF project (http://www.tcpdf.org) has been originally derived in 2002 from the Public Domain FPDF class by Olivier Plathey (http://www.fpdf.org), but now is almost entirely rewritten.<br> - * @package com.tecnick.tcpdf - * @brief PHP class for generating PDF documents without requiring external extensions. - * @version 6.3.2 - * @author Nicola Asuni - info@tecnick.com - * @IgnoreAnnotation("protected") - * @IgnoreAnnotation("public") - * @IgnoreAnnotation("pre") - */ -class TCPDF { - - // Protected properties - - /** - * Current page number. - * @protected - */ - protected $page; - - /** - * Current object number. - * @protected - */ - protected $n; - - /** - * Array of object offsets. - * @protected - */ - protected $offsets = array(); - - /** - * Array of object IDs for each page. - * @protected - */ - protected $pageobjects = array(); - - /** - * Buffer holding in-memory PDF. - * @protected - */ - protected $buffer; - - /** - * Array containing pages. - * @protected - */ - protected $pages = array(); - - /** - * Current document state. - * @protected - */ - protected $state; - - /** - * Compression flag. - * @protected - */ - protected $compress; - - /** - * Current page orientation (P = Portrait, L = Landscape). - * @protected - */ - protected $CurOrientation; - - /** - * Page dimensions. - * @protected - */ - protected $pagedim = array(); - - /** - * Scale factor (number of points in user unit). - * @protected - */ - protected $k; - - /** - * Width of page format in points. - * @protected - */ - protected $fwPt; - - /** - * Height of page format in points. - * @protected - */ - protected $fhPt; - - /** - * Current width of page in points. - * @protected - */ - protected $wPt; - - /** - * Current height of page in points. - * @protected - */ - protected $hPt; - - /** - * Current width of page in user unit. - * @protected - */ - protected $w; - - /** - * Current height of page in user unit. - * @protected - */ - protected $h; - - /** - * Left margin. - * @protected - */ - protected $lMargin; - - /** - * Right margin. - * @protected - */ - protected $rMargin; - - /** - * Cell left margin (used by regions). - * @protected - */ - protected $clMargin; - - /** - * Cell right margin (used by regions). - * @protected - */ - protected $crMargin; - - /** - * Top margin. - * @protected - */ - protected $tMargin; - - /** - * Page break margin. - * @protected - */ - protected $bMargin; - - /** - * Array of cell internal paddings ('T' => top, 'R' => right, 'B' => bottom, 'L' => left). - * @since 5.9.000 (2010-10-03) - * @protected - */ - protected $cell_padding = array('T' => 0, 'R' => 0, 'B' => 0, 'L' => 0); - - /** - * Array of cell margins ('T' => top, 'R' => right, 'B' => bottom, 'L' => left). - * @since 5.9.000 (2010-10-04) - * @protected - */ - protected $cell_margin = array('T' => 0, 'R' => 0, 'B' => 0, 'L' => 0); - - /** - * Current horizontal position in user unit for cell positioning. - * @protected - */ - protected $x; - - /** - * Current vertical position in user unit for cell positioning. - * @protected - */ - protected $y; - - /** - * Height of last cell printed. - * @protected - */ - protected $lasth; - - /** - * Line width in user unit. - * @protected - */ - protected $LineWidth; - - /** - * Array of standard font names. - * @protected - */ - protected $CoreFonts; - - /** - * Array of used fonts. - * @protected - */ - protected $fonts = array(); - - /** - * Array of font files. - * @protected - */ - protected $FontFiles = array(); - - /** - * Array of encoding differences. - * @protected - */ - protected $diffs = array(); - - /** - * Array of used images. - * @protected - */ - protected $images = array(); - - /** - * Depth of the svg tag, to keep track if the svg tag is a subtag or the root tag. - * @protected - */ - protected $svg_tag_depth = 0; - - /** - * Array of Annotations in pages. - * @protected - */ - protected $PageAnnots = array(); - - /** - * Array of internal links. - * @protected - */ - protected $links = array(); - - /** - * Current font family. - * @protected - */ - protected $FontFamily; - - /** - * Current font style. - * @protected - */ - protected $FontStyle; - - /** - * Current font ascent (distance between font top and baseline). - * @protected - * @since 2.8.000 (2007-03-29) - */ - protected $FontAscent; - - /** - * Current font descent (distance between font bottom and baseline). - * @protected - * @since 2.8.000 (2007-03-29) - */ - protected $FontDescent; - - /** - * Underlining flag. - * @protected - */ - protected $underline; - - /** - * Overlining flag. - * @protected - */ - protected $overline; - - /** - * Current font info. - * @protected - */ - protected $CurrentFont; - - /** - * Current font size in points. - * @protected - */ - protected $FontSizePt; - - /** - * Current font size in user unit. - * @protected - */ - protected $FontSize; - - /** - * Commands for drawing color. - * @protected - */ - protected $DrawColor; - - /** - * Commands for filling color. - * @protected - */ - protected $FillColor; - - /** - * Commands for text color. - * @protected - */ - protected $TextColor; - - /** - * Indicates whether fill and text colors are different. - * @protected - */ - protected $ColorFlag; - - /** - * Automatic page breaking. - * @protected - */ - protected $AutoPageBreak; - - /** - * Threshold used to trigger page breaks. - * @protected - */ - protected $PageBreakTrigger; - - /** - * Flag set when processing page header. - * @protected - */ - protected $InHeader = false; - - /** - * Flag set when processing page footer. - * @protected - */ - protected $InFooter = false; - - /** - * Zoom display mode. - * @protected - */ - protected $ZoomMode; - - /** - * Layout display mode. - * @protected - */ - protected $LayoutMode; - - /** - * If true set the document information dictionary in Unicode. - * @protected - */ - protected $docinfounicode = true; - - /** - * Document title. - * @protected - */ - protected $title = ''; - - /** - * Document subject. - * @protected - */ - protected $subject = ''; - - /** - * Document author. - * @protected - */ - protected $author = ''; - - /** - * Document keywords. - * @protected - */ - protected $keywords = ''; - - /** - * Document creator. - * @protected - */ - protected $creator = ''; - - /** - * Starting page number. - * @protected - */ - protected $starting_page_number = 1; - - /** - * The right-bottom (or left-bottom for RTL) corner X coordinate of last inserted image. - * @since 2002-07-31 - * @author Nicola Asuni - * @protected - */ - protected $img_rb_x; - - /** - * The right-bottom corner Y coordinate of last inserted image. - * @since 2002-07-31 - * @author Nicola Asuni - * @protected - */ - protected $img_rb_y; - - /** - * Adjusting factor to convert pixels to user units. - * @since 2004-06-14 - * @author Nicola Asuni - * @protected - */ - protected $imgscale = 1; - - /** - * Boolean flag set to true when the input text is unicode (require unicode fonts). - * @since 2005-01-02 - * @author Nicola Asuni - * @protected - */ - protected $isunicode = false; - - /** - * PDF version. - * @since 1.5.3 - * @protected - */ - protected $PDFVersion = '1.7'; - - /** - * ID of the stored default header template (-1 = not set). - * @protected - */ - protected $header_xobjid = false; - - /** - * If true reset the Header Xobject template at each page - * @protected - */ - protected $header_xobj_autoreset = false; - - /** - * Minimum distance between header and top page margin. - * @protected - */ - protected $header_margin; - - /** - * Minimum distance between footer and bottom page margin. - * @protected - */ - protected $footer_margin; - - /** - * Original left margin value. - * @protected - * @since 1.53.0.TC013 - */ - protected $original_lMargin; - - /** - * Original right margin value. - * @protected - * @since 1.53.0.TC013 - */ - protected $original_rMargin; - - /** - * Default font used on page header. - * @protected - * @var array<int,string|float|null> - * @phpstan-var array{0: string, 1: string, 2: float|null} - */ - protected $header_font; - - /** - * Default font used on page footer. - * @protected - * @var array<int,string|float|null> - * @phpstan-var array{0: string, 1: string, 2: float|null} - */ - protected $footer_font; - - /** - * Language templates. - * @protected - */ - protected $l; - - /** - * Barcode to print on page footer (only if set). - * @protected - */ - protected $barcode = false; - - /** - * Boolean flag to print/hide page header. - * @protected - */ - protected $print_header = true; - - /** - * Boolean flag to print/hide page footer. - * @protected - */ - protected $print_footer = true; - - /** - * Header image logo. - * @protected - */ - protected $header_logo = ''; - - /** - * Width of header image logo in user units. - * @protected - */ - protected $header_logo_width = 30; - - /** - * Title to be printed on default page header. - * @protected - */ - protected $header_title = ''; - - /** - * String to print on page header after title. - * @protected - */ - protected $header_string = ''; - - /** - * Color for header text (RGB array). - * @since 5.9.174 (2012-07-25) - * @protected - * @var int[] - * @phpstan-var array{0: int, 1: int, 2: int} - */ - protected $header_text_color = array(0,0,0); - - /** - * Color for header line (RGB array). - * @since 5.9.174 (2012-07-25) - * @protected - * @var int[] - * @phpstan-var array{0: int, 1: int, 2: int} - */ - protected $header_line_color = array(0,0,0); - - /** - * Color for footer text (RGB array). - * @since 5.9.174 (2012-07-25) - * @protected - * @var int[] - * @phpstan-var array{0: int, 1: int, 2: int} - */ - protected $footer_text_color = array(0,0,0); - - /** - * Color for footer line (RGB array). - * @since 5.9.174 (2012-07-25) - * @protected - * @var int[] - * @phpstan-var array{0: int, 1: int, 2: int} - */ - protected $footer_line_color = array(0,0,0); - - /** - * Text shadow data array. - * @since 5.9.174 (2012-07-25) - * @protected - */ - protected $txtshadow = array('enabled'=>false, 'depth_w'=>0, 'depth_h'=>0, 'color'=>false, 'opacity'=>1, 'blend_mode'=>'Normal'); - - /** - * Default number of columns for html table. - * @protected - */ - protected $default_table_columns = 4; - - // variables for html parser - - /** - * HTML PARSER: array to store current link and rendering styles. - * @protected - */ - protected $HREF = array(); - - /** - * List of available fonts on filesystem. - * @protected - */ - protected $fontlist = array(); - - /** - * Current foreground color. - * @protected - */ - protected $fgcolor; - - /** - * HTML PARSER: array of boolean values, true in case of ordered list (OL), false otherwise. - * @protected - */ - protected $listordered = array(); - - /** - * HTML PARSER: array count list items on nested lists. - * @protected - */ - protected $listcount = array(); - - /** - * HTML PARSER: current list nesting level. - * @protected - */ - protected $listnum = 0; - - /** - * HTML PARSER: indent amount for lists. - * @protected - */ - protected $listindent = 0; - - /** - * HTML PARSER: current list indententation level. - * @protected - */ - protected $listindentlevel = 0; - - /** - * Current background color. - * @protected - */ - protected $bgcolor; - - /** - * Temporary font size in points. - * @protected - */ - protected $tempfontsize = 10; - - /** - * Spacer string for LI tags. - * @protected - */ - protected $lispacer = ''; - - /** - * Default encoding. - * @protected - * @since 1.53.0.TC010 - */ - protected $encoding = 'UTF-8'; - - /** - * Boolean flag to indicate if the document language is Right-To-Left. - * @protected - * @since 2.0.000 - */ - protected $rtl = false; - - /** - * Boolean flag used to force RTL or LTR string direction. - * @protected - * @since 2.0.000 - */ - protected $tmprtl = false; - - // --- Variables used for document encryption: - - /** - * IBoolean flag indicating whether document is protected. - * @protected - * @since 2.0.000 (2008-01-02) - */ - protected $encrypted; - - /** - * Array containing encryption settings. - * @protected - * @since 5.0.005 (2010-05-11) - */ - protected $encryptdata = array(); - - /** - * Last RC4 key encrypted (cached for optimisation). - * @protected - * @since 2.0.000 (2008-01-02) - */ - protected $last_enc_key; - - /** - * Last RC4 computed key. - * @protected - * @since 2.0.000 (2008-01-02) - */ - protected $last_enc_key_c; - - /** - * File ID (used on document trailer). - * @protected - * @since 5.0.005 (2010-05-12) - */ - protected $file_id; - - // --- bookmark --- - - /** - * Outlines for bookmark. - * @protected - * @since 2.1.002 (2008-02-12) - */ - protected $outlines = array(); - - /** - * Outline root for bookmark. - * @protected - * @since 2.1.002 (2008-02-12) - */ - protected $OutlineRoot; - - // --- javascript and form --- - - /** - * Javascript code. - * @protected - * @since 2.1.002 (2008-02-12) - */ - protected $javascript = ''; - - /** - * Javascript counter. - * @protected - * @since 2.1.002 (2008-02-12) - */ - protected $n_js; - - /** - * line through state - * @protected - * @since 2.8.000 (2008-03-19) - */ - protected $linethrough; - - /** - * Array with additional document-wide usage rights for the document. - * @protected - * @since 5.8.014 (2010-08-23) - */ - protected $ur = array(); - - /** - * DPI (Dot Per Inch) Document Resolution (do not change). - * @protected - * @since 3.0.000 (2008-03-27) - */ - protected $dpi = 72; - - /** - * Array of page numbers were a new page group was started (the page numbers are the keys of the array). - * @protected - * @since 3.0.000 (2008-03-27) - */ - protected $newpagegroup = array(); - - /** - * Array that contains the number of pages in each page group. - * @protected - * @since 3.0.000 (2008-03-27) - */ - protected $pagegroups = array(); - - /** - * Current page group number. - * @protected - * @since 3.0.000 (2008-03-27) - */ - protected $currpagegroup = 0; - - /** - * Array of transparency objects and parameters. - * @protected - * @since 3.0.000 (2008-03-27) - */ - protected $extgstates; - - /** - * Set the default JPEG compression quality (1-100). - * @protected - * @since 3.0.000 (2008-03-27) - */ - protected $jpeg_quality; - - /** - * Default cell height ratio. - * @protected - * @since 3.0.014 (2008-05-23) - * @var float - */ - protected $cell_height_ratio = K_CELL_HEIGHT_RATIO; - - /** - * PDF viewer preferences. - * @protected - * @since 3.1.000 (2008-06-09) - */ - protected $viewer_preferences; - - /** - * A name object specifying how the document should be displayed when opened. - * @protected - * @since 3.1.000 (2008-06-09) - */ - protected $PageMode; - - /** - * Array for storing gradient information. - * @protected - * @since 3.1.000 (2008-06-09) - */ - protected $gradients = array(); - - /** - * Array used to store positions inside the pages buffer (keys are the page numbers). - * @protected - * @since 3.2.000 (2008-06-26) - */ - protected $intmrk = array(); - - /** - * Array used to store positions inside the pages buffer (keys are the page numbers). - * @protected - * @since 5.7.000 (2010-08-03) - */ - protected $bordermrk = array(); - - /** - * Array used to store page positions to track empty pages (keys are the page numbers). - * @protected - * @since 5.8.007 (2010-08-18) - */ - protected $emptypagemrk = array(); - - /** - * Array used to store content positions inside the pages buffer (keys are the page numbers). - * @protected - * @since 4.6.021 (2009-07-20) - */ - protected $cntmrk = array(); - - /** - * Array used to store footer positions of each page. - * @protected - * @since 3.2.000 (2008-07-01) - */ - protected $footerpos = array(); - - /** - * Array used to store footer length of each page. - * @protected - * @since 4.0.014 (2008-07-29) - */ - protected $footerlen = array(); - - /** - * Boolean flag to indicate if a new line is created. - * @protected - * @since 3.2.000 (2008-07-01) - */ - protected $newline = true; - - /** - * End position of the latest inserted line. - * @protected - * @since 3.2.000 (2008-07-01) - */ - protected $endlinex = 0; - - /** - * PDF string for width value of the last line. - * @protected - * @since 4.0.006 (2008-07-16) - */ - protected $linestyleWidth = ''; - - /** - * PDF string for CAP value of the last line. - * @protected - * @since 4.0.006 (2008-07-16) - */ - protected $linestyleCap = '0 J'; - - /** - * PDF string for join value of the last line. - * @protected - * @since 4.0.006 (2008-07-16) - */ - protected $linestyleJoin = '0 j'; - - /** - * PDF string for dash value of the last line. - * @protected - * @since 4.0.006 (2008-07-16) - */ - protected $linestyleDash = '[] 0 d'; - - /** - * Boolean flag to indicate if marked-content sequence is open. - * @protected - * @since 4.0.013 (2008-07-28) - */ - protected $openMarkedContent = false; - - /** - * Count the latest inserted vertical spaces on HTML. - * @protected - * @since 4.0.021 (2008-08-24) - */ - protected $htmlvspace = 0; - - /** - * Array of Spot colors. - * @protected - * @since 4.0.024 (2008-09-12) - */ - protected $spot_colors = array(); - - /** - * Symbol used for HTML unordered list items. - * @protected - * @since 4.0.028 (2008-09-26) - */ - protected $lisymbol = ''; - - /** - * String used to mark the beginning and end of EPS image blocks. - * @protected - * @since 4.1.000 (2008-10-18) - */ - protected $epsmarker = 'x#!#EPS#!#x'; - - /** - * Array of transformation matrix. - * @protected - * @since 4.2.000 (2008-10-29) - */ - protected $transfmatrix = array(); - - /** - * Current key for transformation matrix. - * @protected - * @since 4.8.005 (2009-09-17) - */ - protected $transfmatrix_key = 0; - - /** - * Booklet mode for double-sided pages. - * @protected - * @since 4.2.000 (2008-10-29) - */ - protected $booklet = false; - - /** - * Epsilon value used for float calculations. - * @protected - * @since 4.2.000 (2008-10-29) - */ - protected $feps = 0.005; - - /** - * Array used for custom vertical spaces for HTML tags. - * @protected - * @since 4.2.001 (2008-10-30) - */ - protected $tagvspaces = array(); - - /** - * HTML PARSER: custom indent amount for lists. Negative value means disabled. - * @protected - * @since 4.2.007 (2008-11-12) - */ - protected $customlistindent = -1; - - /** - * Boolean flag to indicate if the border of the cell sides that cross the page should be removed. - * @protected - * @since 4.2.010 (2008-11-14) - */ - protected $opencell = true; - - /** - * Array of files to embedd. - * @protected - * @since 4.4.000 (2008-12-07) - */ - protected $embeddedfiles = array(); - - /** - * Boolean flag to indicate if we are inside a PRE tag. - * @protected - * @since 4.4.001 (2008-12-08) - */ - protected $premode = false; - - /** - * Array used to store positions of graphics transformation blocks inside the page buffer. - * keys are the page numbers - * @protected - * @since 4.4.002 (2008-12-09) - */ - protected $transfmrk = array(); - - /** - * Default color for html links. - * @protected - * @since 4.4.003 (2008-12-09) - */ - protected $htmlLinkColorArray = array(0, 0, 255); - - /** - * Default font style to add to html links. - * @protected - * @since 4.4.003 (2008-12-09) - */ - protected $htmlLinkFontStyle = 'U'; - - /** - * Counts the number of pages. - * @protected - * @since 4.5.000 (2008-12-31) - */ - protected $numpages = 0; - - /** - * Array containing page lengths in bytes. - * @protected - * @since 4.5.000 (2008-12-31) - */ - protected $pagelen = array(); - - /** - * Counts the number of pages. - * @protected - * @since 4.5.000 (2008-12-31) - */ - protected $numimages = 0; - - /** - * Store the image keys. - * @protected - * @since 4.5.000 (2008-12-31) - */ - protected $imagekeys = array(); - - /** - * Length of the buffer in bytes. - * @protected - * @since 4.5.000 (2008-12-31) - */ - protected $bufferlen = 0; - - /** - * Counts the number of fonts. - * @protected - * @since 4.5.000 (2009-01-02) - */ - protected $numfonts = 0; - - /** - * Store the font keys. - * @protected - * @since 4.5.000 (2009-01-02) - */ - protected $fontkeys = array(); - - /** - * Store the font object IDs. - * @protected - * @since 4.8.001 (2009-09-09) - */ - protected $font_obj_ids = array(); - - /** - * Store the fage status (true when opened, false when closed). - * @protected - * @since 4.5.000 (2009-01-02) - */ - protected $pageopen = array(); - - /** - * Default monospace font. - * @protected - * @since 4.5.025 (2009-03-10) - */ - protected $default_monospaced_font = 'courier'; - - /** - * Cloned copy of the current class object. - * @protected - * @since 4.5.029 (2009-03-19) - */ - protected $objcopy; - - /** - * Array used to store the lengths of cache files. - * @protected - * @since 4.5.029 (2009-03-19) - */ - protected $cache_file_length = array(); - - /** - * Table header content to be repeated on each new page. - * @protected - * @since 4.5.030 (2009-03-20) - */ - protected $thead = ''; - - /** - * Margins used for table header. - * @protected - * @since 4.5.030 (2009-03-20) - */ - protected $theadMargins = array(); - - /** - * Boolean flag to enable document digital signature. - * @protected - * @since 4.6.005 (2009-04-24) - */ - protected $sign = false; - - /** - * Digital signature data. - * @protected - * @since 4.6.005 (2009-04-24) - */ - protected $signature_data = array(); - - /** - * Digital signature max length. - * @protected - * @since 4.6.005 (2009-04-24) - */ - protected $signature_max_length = 11742; - - /** - * Data for digital signature appearance. - * @protected - * @since 5.3.011 (2010-06-16) - */ - protected $signature_appearance = array('page' => 1, 'rect' => '0 0 0 0'); - - /** - * Array of empty digital signature appearances. - * @protected - * @since 5.9.101 (2011-07-06) - */ - protected $empty_signature_appearance = array(); - - /** - * Boolean flag to enable document timestamping with TSA. - * @protected - * @since 6.0.085 (2014-06-19) - */ - protected $tsa_timestamp = false; - - /** - * Timestamping data. - * @protected - * @since 6.0.085 (2014-06-19) - */ - protected $tsa_data = array(); - - /** - * Regular expression used to find blank characters (required for word-wrapping). - * @protected - * @since 4.6.006 (2009-04-28) - */ - protected $re_spaces = '/[^\S\xa0]/'; - - /** - * Array of $re_spaces parts. - * @protected - * @since 5.5.011 (2010-07-09) - */ - protected $re_space = array('p' => '[^\S\xa0]', 'm' => ''); - - /** - * Digital signature object ID. - * @protected - * @since 4.6.022 (2009-06-23) - */ - protected $sig_obj_id = 0; - - /** - * ID of page objects. - * @protected - * @since 4.7.000 (2009-08-29) - */ - protected $page_obj_id = array(); - - /** - * List of form annotations IDs. - * @protected - * @since 4.8.000 (2009-09-07) - */ - protected $form_obj_id = array(); - - /** - * Deafult Javascript field properties. Possible values are described on official Javascript for Acrobat API reference. Annotation options can be directly specified using the 'aopt' entry. - * @protected - * @since 4.8.000 (2009-09-07) - */ - protected $default_form_prop = array('lineWidth'=>1, 'borderStyle'=>'solid', 'fillColor'=>array(255, 255, 255), 'strokeColor'=>array(128, 128, 128)); - - /** - * Javascript objects array. - * @protected - * @since 4.8.000 (2009-09-07) - */ - protected $js_objects = array(); - - /** - * Current form action (used during XHTML rendering). - * @protected - * @since 4.8.000 (2009-09-07) - */ - protected $form_action = ''; - - /** - * Current form encryption type (used during XHTML rendering). - * @protected - * @since 4.8.000 (2009-09-07) - */ - protected $form_enctype = 'application/x-www-form-urlencoded'; - - /** - * Current method to submit forms. - * @protected - * @since 4.8.000 (2009-09-07) - */ - protected $form_mode = 'post'; - - /** - * List of fonts used on form fields (fontname => fontkey). - * @protected - * @since 4.8.001 (2009-09-09) - */ - protected $annotation_fonts = array(); - - /** - * List of radio buttons parent objects. - * @protected - * @since 4.8.001 (2009-09-09) - */ - protected $radiobutton_groups = array(); - - /** - * List of radio group objects IDs. - * @protected - * @since 4.8.001 (2009-09-09) - */ - protected $radio_groups = array(); - - /** - * Text indentation value (used for text-indent CSS attribute). - * @protected - * @since 4.8.006 (2009-09-23) - */ - protected $textindent = 0; - - /** - * Store page number when startTransaction() is called. - * @protected - * @since 4.8.006 (2009-09-23) - */ - protected $start_transaction_page = 0; - - /** - * Store Y position when startTransaction() is called. - * @protected - * @since 4.9.001 (2010-03-28) - */ - protected $start_transaction_y = 0; - - /** - * True when we are printing the thead section on a new page. - * @protected - * @since 4.8.027 (2010-01-25) - */ - protected $inthead = false; - - /** - * Array of column measures (width, space, starting Y position). - * @protected - * @since 4.9.001 (2010-03-28) - */ - protected $columns = array(); - - /** - * Number of colums. - * @protected - * @since 4.9.001 (2010-03-28) - */ - protected $num_columns = 1; - - /** - * Current column number. - * @protected - * @since 4.9.001 (2010-03-28) - */ - protected $current_column = 0; - - /** - * Starting page for columns. - * @protected - * @since 4.9.001 (2010-03-28) - */ - protected $column_start_page = 0; - - /** - * Maximum page and column selected. - * @protected - * @since 5.8.000 (2010-08-11) - */ - protected $maxselcol = array('page' => 0, 'column' => 0); - - /** - * Array of: X difference between table cell x start and starting page margin, cellspacing, cellpadding. - * @protected - * @since 5.8.000 (2010-08-11) - */ - protected $colxshift = array('x' => 0, 's' => array('H' => 0, 'V' => 0), 'p' => array('L' => 0, 'T' => 0, 'R' => 0, 'B' => 0)); - - /** - * Text rendering mode: 0 = Fill text; 1 = Stroke text; 2 = Fill, then stroke text; 3 = Neither fill nor stroke text (invisible); 4 = Fill text and add to path for clipping; 5 = Stroke text and add to path for clipping; 6 = Fill, then stroke text and add to path for clipping; 7 = Add text to path for clipping. - * @protected - * @since 4.9.008 (2010-04-03) - */ - protected $textrendermode = 0; - - /** - * Text stroke width in doc units. - * @protected - * @since 4.9.008 (2010-04-03) - */ - protected $textstrokewidth = 0; - - /** - * Current stroke color. - * @protected - * @since 4.9.008 (2010-04-03) - */ - protected $strokecolor; - - /** - * Default unit of measure for document. - * @protected - * @since 5.0.000 (2010-04-22) - */ - protected $pdfunit = 'mm'; - - /** - * Boolean flag true when we are on TOC (Table Of Content) page. - * @protected - */ - protected $tocpage = false; - - /** - * Boolean flag: if true convert vector images (SVG, EPS) to raster image using GD or ImageMagick library. - * @protected - * @since 5.0.000 (2010-04-26) - */ - protected $rasterize_vector_images = false; - - /** - * Boolean flag: if true enables font subsetting by default. - * @protected - * @since 5.3.002 (2010-06-07) - */ - protected $font_subsetting = true; - - /** - * Array of default graphic settings. - * @protected - * @since 5.5.008 (2010-07-02) - */ - protected $default_graphic_vars = array(); - - /** - * Array of XObjects. - * @protected - * @since 5.8.014 (2010-08-23) - */ - protected $xobjects = array(); - - /** - * Boolean value true when we are inside an XObject. - * @protected - * @since 5.8.017 (2010-08-24) - */ - protected $inxobj = false; - - /** - * Current XObject ID. - * @protected - * @since 5.8.017 (2010-08-24) - */ - protected $xobjid = ''; - - /** - * Percentage of character stretching. - * @protected - * @since 5.9.000 (2010-09-29) - */ - protected $font_stretching = 100; - - /** - * Increases or decreases the space between characters in a text by the specified amount (tracking). - * @protected - * @since 5.9.000 (2010-09-29) - */ - protected $font_spacing = 0; - - /** - * Array of no-write regions. - * ('page' => page number or empy for current page, 'xt' => X top, 'yt' => Y top, 'xb' => X bottom, 'yb' => Y bottom, 'side' => page side 'L' = left or 'R' = right) - * @protected - * @since 5.9.003 (2010-10-14) - */ - protected $page_regions = array(); - - /** - * Boolean value true when page region check is active. - * @protected - */ - protected $check_page_regions = true; - - /** - * Array of PDF layers data. - * @protected - * @since 5.9.102 (2011-07-13) - */ - protected $pdflayers = array(); - - /** - * A dictionary of names and corresponding destinations (Dests key on document Catalog). - * @protected - * @since 5.9.097 (2011-06-23) - */ - protected $dests = array(); - - /** - * Object ID for Named Destinations - * @protected - * @since 5.9.097 (2011-06-23) - */ - protected $n_dests; - - /** - * Embedded Files Names - * @protected - * @since 5.9.204 (2013-01-23) - */ - protected $efnames = array(); - - /** - * Directory used for the last SVG image. - * @protected - * @since 5.0.000 (2010-05-05) - */ - protected $svgdir = ''; - - /** - * Deafult unit of measure for SVG. - * @protected - * @since 5.0.000 (2010-05-02) - */ - protected $svgunit = 'px'; - - /** - * Array of SVG gradients. - * @protected - * @since 5.0.000 (2010-05-02) - */ - protected $svggradients = array(); - - /** - * ID of last SVG gradient. - * @protected - * @since 5.0.000 (2010-05-02) - */ - protected $svggradientid = 0; - - /** - * Boolean value true when in SVG defs group. - * @protected - * @since 5.0.000 (2010-05-02) - */ - protected $svgdefsmode = false; - - /** - * Array of SVG defs. - * @protected - * @since 5.0.000 (2010-05-02) - */ - protected $svgdefs = array(); - - /** - * Boolean value true when in SVG clipPath tag. - * @protected - * @since 5.0.000 (2010-04-26) - */ - protected $svgclipmode = false; - - /** - * Array of SVG clipPath commands. - * @protected - * @since 5.0.000 (2010-05-02) - */ - protected $svgclippaths = array(); - - /** - * Array of SVG clipPath tranformation matrix. - * @protected - * @since 5.8.022 (2010-08-31) - */ - protected $svgcliptm = array(); - - /** - * ID of last SVG clipPath. - * @protected - * @since 5.0.000 (2010-05-02) - */ - protected $svgclipid = 0; - - /** - * SVG text. - * @protected - * @since 5.0.000 (2010-05-02) - */ - protected $svgtext = ''; - - /** - * SVG text properties. - * @protected - * @since 5.8.013 (2010-08-23) - */ - protected $svgtextmode = array(); - - /** - * Array of SVG properties. - * @protected - * @since 5.0.000 (2010-05-02) - */ - protected $svgstyles = array(array( - 'alignment-baseline' => 'auto', - 'baseline-shift' => 'baseline', - 'clip' => 'auto', - 'clip-path' => 'none', - 'clip-rule' => 'nonzero', - 'color' => 'black', - 'color-interpolation' => 'sRGB', - 'color-interpolation-filters' => 'linearRGB', - 'color-profile' => 'auto', - 'color-rendering' => 'auto', - 'cursor' => 'auto', - 'direction' => 'ltr', - 'display' => 'inline', - 'dominant-baseline' => 'auto', - 'enable-background' => 'accumulate', - 'fill' => 'black', - 'fill-opacity' => 1, - 'fill-rule' => 'nonzero', - 'filter' => 'none', - 'flood-color' => 'black', - 'flood-opacity' => 1, - 'font' => '', - 'font-family' => 'helvetica', - 'font-size' => 'medium', - 'font-size-adjust' => 'none', - 'font-stretch' => 'normal', - 'font-style' => 'normal', - 'font-variant' => 'normal', - 'font-weight' => 'normal', - 'glyph-orientation-horizontal' => '0deg', - 'glyph-orientation-vertical' => 'auto', - 'image-rendering' => 'auto', - 'kerning' => 'auto', - 'letter-spacing' => 'normal', - 'lighting-color' => 'white', - 'marker' => '', - 'marker-end' => 'none', - 'marker-mid' => 'none', - 'marker-start' => 'none', - 'mask' => 'none', - 'opacity' => 1, - 'overflow' => 'auto', - 'pointer-events' => 'visiblePainted', - 'shape-rendering' => 'auto', - 'stop-color' => 'black', - 'stop-opacity' => 1, - 'stroke' => 'none', - 'stroke-dasharray' => 'none', - 'stroke-dashoffset' => 0, - 'stroke-linecap' => 'butt', - 'stroke-linejoin' => 'miter', - 'stroke-miterlimit' => 4, - 'stroke-opacity' => 1, - 'stroke-width' => 1, - 'text-anchor' => 'start', - 'text-decoration' => 'none', - 'text-rendering' => 'auto', - 'unicode-bidi' => 'normal', - 'visibility' => 'visible', - 'word-spacing' => 'normal', - 'writing-mode' => 'lr-tb', - 'text-color' => 'black', - 'transfmatrix' => array(1, 0, 0, 1, 0, 0) - )); - - /** - * If true force sRGB color profile for all document. - * @protected - * @since 5.9.121 (2011-09-28) - */ - protected $force_srgb = false; - - /** - * If true set the document to PDF/A mode. - * @protected - * @since 5.9.121 (2011-09-27) - */ - protected $pdfa_mode = false; - - /** - * version of PDF/A mode (1 - 3). - * @protected - * @since 6.2.26 (2019-03-12) - */ - protected $pdfa_version = 1; - - /** - * Document creation date-time - * @protected - * @since 5.9.152 (2012-03-22) - */ - protected $doc_creation_timestamp; - - /** - * Document modification date-time - * @protected - * @since 5.9.152 (2012-03-22) - */ - protected $doc_modification_timestamp; - - /** - * Custom XMP data. - * @protected - * @since 5.9.128 (2011-10-06) - */ - protected $custom_xmp = ''; - - /** - * Custom XMP RDF data. - * @protected - * @since 6.3.0 (2019-09-19) - */ - protected $custom_xmp_rdf = ''; - - /** - * Overprint mode array. - * (Check the "Entries in a Graphics State Parameter Dictionary" on PDF 32000-1:2008). - * @protected - * @since 5.9.152 (2012-03-23) - * @var array<string,bool|int> - */ - protected $overprint = array('OP' => false, 'op' => false, 'OPM' => 0); - - /** - * Alpha mode array. - * (Check the "Entries in a Graphics State Parameter Dictionary" on PDF 32000-1:2008). - * @protected - * @since 5.9.152 (2012-03-23) - */ - protected $alpha = array('CA' => 1, 'ca' => 1, 'BM' => '/Normal', 'AIS' => false); - - /** - * Define the page boundaries boxes to be set on document. - * @protected - * @since 5.9.152 (2012-03-23) - */ - protected $page_boxes = array('MediaBox', 'CropBox', 'BleedBox', 'TrimBox', 'ArtBox'); - - /** - * If true print TCPDF meta link. - * @protected - * @since 5.9.152 (2012-03-23) - */ - protected $tcpdflink = true; - - /** - * Cache array for computed GD gamma values. - * @protected - * @since 5.9.1632 (2012-06-05) - */ - protected $gdgammacache = array(); - - /** - * Cache array for file content - * @protected - * @var array - * @since 6.3.5 (2020-09-28) - */ - protected $fileContentCache = array(); - - /** - * Whether to allow local file path in image html tags, when prefixed with file:// - * - * @var bool - * @protected - * @since 6.4 (2020-07-23) - */ - protected $allowLocalFiles = false; - - //------------------------------------------------------------ - // METHODS - //------------------------------------------------------------ - - /** - * This is the class constructor. - * It allows to set up the page format, the orientation and the measure unit used in all the methods (except for the font sizes). - * - * @param string $orientation page orientation. Possible values are (case insensitive):<ul><li>P or Portrait (default)</li><li>L or Landscape</li><li>'' (empty string) for automatic orientation</li></ul> - * @param string $unit User measure unit. Possible values are:<ul><li>pt: point</li><li>mm: millimeter (default)</li><li>cm: centimeter</li><li>in: inch</li></ul><br />A point equals 1/72 of inch, that is to say about 0.35 mm (an inch being 2.54 cm). This is a very common unit in typography; font sizes are expressed in that unit. - * @param mixed $format The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() or an array of parameters specified at setPageFormat(). - * @param boolean $unicode TRUE means that the input text is unicode (default = true) - * @param string $encoding Charset encoding (used only when converting back html entities); default is UTF-8. - * @param boolean $diskcache DEPRECATED FEATURE - * @param false|integer $pdfa If not false, set the document to PDF/A mode and the good version (1 or 3). - * @public - * @see getPageSizeFromFormat(), setPageFormat() - */ - public function __construct($orientation='P', $unit='mm', $format='A4', $unicode=true, $encoding='UTF-8', $diskcache=false, $pdfa=false) { - // set file ID for trailer - $serformat = (is_array($format) ? json_encode($format) : $format); - $this->file_id = md5(TCPDF_STATIC::getRandomSeed('TCPDF'.$orientation.$unit.$serformat.$encoding)); - $this->font_obj_ids = array(); - $this->page_obj_id = array(); - $this->form_obj_id = array(); - - // set pdf/a mode - if ($pdfa != false) { - $this->pdfa_mode = true; - $this->pdfa_version = $pdfa; // 1 or 3 - } else - $this->pdfa_mode = false; - - $this->force_srgb = false; - // set language direction - $this->rtl = false; - $this->tmprtl = false; - // some checks - $this->_dochecks(); - // initialization of properties - $this->isunicode = $unicode; - $this->page = 0; - $this->transfmrk[0] = array(); - $this->pagedim = array(); - $this->n = 2; - $this->buffer = ''; - $this->pages = array(); - $this->state = 0; - $this->fonts = array(); - $this->FontFiles = array(); - $this->diffs = array(); - $this->images = array(); - $this->links = array(); - $this->gradients = array(); - $this->InFooter = false; - $this->lasth = 0; - $this->FontFamily = defined('PDF_FONT_NAME_MAIN')?PDF_FONT_NAME_MAIN:'helvetica'; - $this->FontStyle = ''; - $this->FontSizePt = 12; - $this->underline = false; - $this->overline = false; - $this->linethrough = false; - $this->DrawColor = '0 G'; - $this->FillColor = '0 g'; - $this->TextColor = '0 g'; - $this->ColorFlag = false; - $this->pdflayers = array(); - // encryption values - $this->encrypted = false; - $this->last_enc_key = ''; - // standard Unicode fonts - $this->CoreFonts = array( - 'courier'=>'Courier', - 'courierB'=>'Courier-Bold', - 'courierI'=>'Courier-Oblique', - 'courierBI'=>'Courier-BoldOblique', - 'helvetica'=>'Helvetica', - 'helveticaB'=>'Helvetica-Bold', - 'helveticaI'=>'Helvetica-Oblique', - 'helveticaBI'=>'Helvetica-BoldOblique', - 'times'=>'Times-Roman', - 'timesB'=>'Times-Bold', - 'timesI'=>'Times-Italic', - 'timesBI'=>'Times-BoldItalic', - 'symbol'=>'Symbol', - 'zapfdingbats'=>'ZapfDingbats' - ); - // set scale factor - $this->setPageUnit($unit); - // set page format and orientation - $this->setPageFormat($format, $orientation); - // page margins (1 cm) - $margin = 28.35 / $this->k; - $this->setMargins($margin, $margin); - $this->clMargin = $this->lMargin; - $this->crMargin = $this->rMargin; - // internal cell padding - $cpadding = $margin / 10; - $this->setCellPaddings($cpadding, 0, $cpadding, 0); - // cell margins - $this->setCellMargins(0, 0, 0, 0); - // line width (0.2 mm) - $this->LineWidth = 0.57 / $this->k; - $this->linestyleWidth = sprintf('%F w', ($this->LineWidth * $this->k)); - $this->linestyleCap = '0 J'; - $this->linestyleJoin = '0 j'; - $this->linestyleDash = '[] 0 d'; - // automatic page break - $this->setAutoPageBreak(true, (2 * $margin)); - // full width display mode - $this->setDisplayMode('fullwidth'); - // compression - $this->setCompression(); - // set default PDF version number - $this->setPDFVersion(); - $this->tcpdflink = true; - $this->encoding = $encoding; - $this->HREF = array(); - $this->getFontsList(); - $this->fgcolor = array('R' => 0, 'G' => 0, 'B' => 0); - $this->strokecolor = array('R' => 0, 'G' => 0, 'B' => 0); - $this->bgcolor = array('R' => 255, 'G' => 255, 'B' => 255); - $this->extgstates = array(); - $this->setTextShadow(); - // signature - $this->sign = false; - $this->tsa_timestamp = false; - $this->tsa_data = array(); - $this->signature_appearance = array('page' => 1, 'rect' => '0 0 0 0', 'name' => 'Signature'); - $this->empty_signature_appearance = array(); - // user's rights - $this->ur['enabled'] = false; - $this->ur['document'] = '/FullSave'; - $this->ur['annots'] = '/Create/Delete/Modify/Copy/Import/Export'; - $this->ur['form'] = '/Add/Delete/FillIn/Import/Export/SubmitStandalone/SpawnTemplate'; - $this->ur['signature'] = '/Modify'; - $this->ur['ef'] = '/Create/Delete/Modify/Import'; - $this->ur['formex'] = ''; - // set default JPEG quality - $this->jpeg_quality = 75; - // initialize some settings - TCPDF_FONTS::utf8Bidi(array(), '', false, $this->isunicode, $this->CurrentFont); - // set default font - $this->setFont($this->FontFamily, $this->FontStyle, $this->FontSizePt); - $this->setHeaderFont(array($this->FontFamily, $this->FontStyle, $this->FontSizePt)); - $this->setFooterFont(array($this->FontFamily, $this->FontStyle, $this->FontSizePt)); - // check if PCRE Unicode support is enabled - if ($this->isunicode AND (@preg_match('/\pL/u', 'a') == 1)) { - // PCRE unicode support is turned ON - // \s : any whitespace character - // \p{Z} : any separator - // \p{Lo} : Unicode letter or ideograph that does not have lowercase and uppercase variants. Is used to chunk chinese words. - // \xa0 : Unicode Character 'NO-BREAK SPACE' (U+00A0) - //$this->setSpacesRE('/(?!\xa0)[\s\p{Z}\p{Lo}]/u'); - $this->setSpacesRE('/(?!\xa0)[\s\p{Z}]/u'); - } else { - // PCRE unicode support is turned OFF - $this->setSpacesRE('/[^\S\xa0]/'); - } - $this->default_form_prop = array('lineWidth'=>1, 'borderStyle'=>'solid', 'fillColor'=>array(255, 255, 255), 'strokeColor'=>array(128, 128, 128)); - // set document creation and modification timestamp - $this->doc_creation_timestamp = time(); - $this->doc_modification_timestamp = $this->doc_creation_timestamp; - // get default graphic vars - $this->default_graphic_vars = $this->getGraphicVars(); - $this->header_xobj_autoreset = false; - $this->custom_xmp = ''; - $this->custom_xmp_rdf = ''; - // Call cleanup method after script execution finishes or exit() is called. - // NOTE: This will not be executed if the process is killed with a SIGTERM or SIGKILL signal. - register_shutdown_function(array($this, '_destroy'), true); - } - - /** - * Default destructor. - * @public - * @since 1.53.0.TC016 - */ - public function __destruct() { - // cleanup - $this->_destroy(true); - } - - /** - * Set the units of measure for the document. - * @param string $unit User measure unit. Possible values are:<ul><li>pt: point</li><li>mm: millimeter (default)</li><li>cm: centimeter</li><li>in: inch</li></ul><br />A point equals 1/72 of inch, that is to say about 0.35 mm (an inch being 2.54 cm). This is a very common unit in typography; font sizes are expressed in that unit. - * @public - * @since 3.0.015 (2008-06-06) - */ - public function setPageUnit($unit) { - $unit = strtolower($unit); - //Set scale factor - switch ($unit) { - // points - case 'px': - case 'pt': { - $this->k = 1; - break; - } - // millimeters - case 'mm': { - $this->k = $this->dpi / 25.4; - break; - } - // centimeters - case 'cm': { - $this->k = $this->dpi / 2.54; - break; - } - // inches - case 'in': { - $this->k = $this->dpi; - break; - } - // unsupported unit - default : { - $this->Error('Incorrect unit: '.$unit); - break; - } - } - $this->pdfunit = $unit; - if (isset($this->CurOrientation)) { - $this->setPageOrientation($this->CurOrientation); - } - } - - /** - * Change the format of the current page - * @param mixed $format The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() documentation or an array of two numbers (width, height) or an array containing the following measures and options:<ul> - * <li>['format'] = page format name (one of the above);</li> - * <li>['Rotate'] : The number of degrees by which the page shall be rotated clockwise when displayed or printed. The value shall be a multiple of 90.</li> - * <li>['PZ'] : The page's preferred zoom (magnification) factor.</li> - * <li>['MediaBox'] : the boundaries of the physical medium on which the page shall be displayed or printed:</li> - * <li>['MediaBox']['llx'] : lower-left x coordinate</li> - * <li>['MediaBox']['lly'] : lower-left y coordinate</li> - * <li>['MediaBox']['urx'] : upper-right x coordinate</li> - * <li>['MediaBox']['ury'] : upper-right y coordinate</li> - * <li>['CropBox'] : the visible region of default user space:</li> - * <li>['CropBox']['llx'] : lower-left x coordinate</li> - * <li>['CropBox']['lly'] : lower-left y coordinate</li> - * <li>['CropBox']['urx'] : upper-right x coordinate</li> - * <li>['CropBox']['ury'] : upper-right y coordinate</li> - * <li>['BleedBox'] : the region to which the contents of the page shall be clipped when output in a production environment:</li> - * <li>['BleedBox']['llx'] : lower-left x coordinate</li> - * <li>['BleedBox']['lly'] : lower-left y coordinate</li> - * <li>['BleedBox']['urx'] : upper-right x coordinate</li> - * <li>['BleedBox']['ury'] : upper-right y coordinate</li> - * <li>['TrimBox'] : the intended dimensions of the finished page after trimming:</li> - * <li>['TrimBox']['llx'] : lower-left x coordinate</li> - * <li>['TrimBox']['lly'] : lower-left y coordinate</li> - * <li>['TrimBox']['urx'] : upper-right x coordinate</li> - * <li>['TrimBox']['ury'] : upper-right y coordinate</li> - * <li>['ArtBox'] : the extent of the page's meaningful content:</li> - * <li>['ArtBox']['llx'] : lower-left x coordinate</li> - * <li>['ArtBox']['lly'] : lower-left y coordinate</li> - * <li>['ArtBox']['urx'] : upper-right x coordinate</li> - * <li>['ArtBox']['ury'] : upper-right y coordinate</li> - * <li>['BoxColorInfo'] :specify the colours and other visual characteristics that should be used in displaying guidelines on the screen for each of the possible page boundaries other than the MediaBox:</li> - * <li>['BoxColorInfo'][BOXTYPE]['C'] : an array of three numbers in the range 0-255, representing the components in the DeviceRGB colour space.</li> - * <li>['BoxColorInfo'][BOXTYPE]['W'] : the guideline width in default user units</li> - * <li>['BoxColorInfo'][BOXTYPE]['S'] : the guideline style: S = Solid; D = Dashed</li> - * <li>['BoxColorInfo'][BOXTYPE]['D'] : dash array defining a pattern of dashes and gaps to be used in drawing dashed guidelines</li> - * <li>['trans'] : the style and duration of the visual transition to use when moving from another page to the given page during a presentation</li> - * <li>['trans']['Dur'] : The page's display duration (also called its advance timing): the maximum length of time, in seconds, that the page shall be displayed during presentations before the viewer application shall automatically advance to the next page.</li> - * <li>['trans']['S'] : transition style : Split, Blinds, Box, Wipe, Dissolve, Glitter, R, Fly, Push, Cover, Uncover, Fade</li> - * <li>['trans']['D'] : The duration of the transition effect, in seconds.</li> - * <li>['trans']['Dm'] : (Split and Blinds transition styles only) The dimension in which the specified transition effect shall occur: H = Horizontal, V = Vertical. Default value: H.</li> - * <li>['trans']['M'] : (Split, Box and Fly transition styles only) The direction of motion for the specified transition effect: I = Inward from the edges of the page, O = Outward from the center of the pageDefault value: I.</li> - * <li>['trans']['Di'] : (Wipe, Glitter, Fly, Cover, Uncover and Push transition styles only) The direction in which the specified transition effect shall moves, expressed in degrees counterclockwise starting from a left-to-right direction. If the value is a number, it shall be one of: 0 = Left to right, 90 = Bottom to top (Wipe only), 180 = Right to left (Wipe only), 270 = Top to bottom, 315 = Top-left to bottom-right (Glitter only). If the value is a name, it shall be None, which is relevant only for the Fly transition when the value of SS is not 1.0. Default value: 0.</li> - * <li>['trans']['SS'] : (Fly transition style only) The starting or ending scale at which the changes shall be drawn. If M specifies an inward transition, the scale of the changes drawn shall progress from SS to 1.0 over the course of the transition. If M specifies an outward transition, the scale of the changes drawn shall progress from 1.0 to SS over the course of the transition. Default: 1.0.</li> - * <li>['trans']['B'] : (Fly transition style only) If true, the area that shall be flown in is rectangular and opaque. Default: false.</li> - * </ul> - * @param string $orientation page orientation. Possible values are (case insensitive):<ul> - * <li>P or Portrait (default)</li> - * <li>L or Landscape</li> - * <li>'' (empty string) for automatic orientation</li> - * </ul> - * @protected - * @since 3.0.015 (2008-06-06) - * @see getPageSizeFromFormat() - */ - protected function setPageFormat($format, $orientation='P') { - if (!empty($format) AND isset($this->pagedim[$this->page])) { - // remove inherited values - unset($this->pagedim[$this->page]); - } - if (is_string($format)) { - // get page measures from format name - $pf = TCPDF_STATIC::getPageSizeFromFormat($format); - $this->fwPt = $pf[0]; - $this->fhPt = $pf[1]; - } else { - // the boundaries of the physical medium on which the page shall be displayed or printed - if (isset($format['MediaBox'])) { - $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'MediaBox', $format['MediaBox']['llx'], $format['MediaBox']['lly'], $format['MediaBox']['urx'], $format['MediaBox']['ury'], false, $this->k, $this->pagedim); - $this->fwPt = (($format['MediaBox']['urx'] - $format['MediaBox']['llx']) * $this->k); - $this->fhPt = (($format['MediaBox']['ury'] - $format['MediaBox']['lly']) * $this->k); - } else { - if (isset($format[0]) AND is_numeric($format[0]) AND isset($format[1]) AND is_numeric($format[1])) { - $pf = array(($format[0] * $this->k), ($format[1] * $this->k)); - } else { - if (!isset($format['format'])) { - // default value - $format['format'] = 'A4'; - } - $pf = TCPDF_STATIC::getPageSizeFromFormat($format['format']); - } - $this->fwPt = $pf[0]; - $this->fhPt = $pf[1]; - $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'MediaBox', 0, 0, $this->fwPt, $this->fhPt, true, $this->k, $this->pagedim); - } - // the visible region of default user space - if (isset($format['CropBox'])) { - $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'CropBox', $format['CropBox']['llx'], $format['CropBox']['lly'], $format['CropBox']['urx'], $format['CropBox']['ury'], false, $this->k, $this->pagedim); - } - // the region to which the contents of the page shall be clipped when output in a production environment - if (isset($format['BleedBox'])) { - $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'BleedBox', $format['BleedBox']['llx'], $format['BleedBox']['lly'], $format['BleedBox']['urx'], $format['BleedBox']['ury'], false, $this->k, $this->pagedim); - } - // the intended dimensions of the finished page after trimming - if (isset($format['TrimBox'])) { - $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'TrimBox', $format['TrimBox']['llx'], $format['TrimBox']['lly'], $format['TrimBox']['urx'], $format['TrimBox']['ury'], false, $this->k, $this->pagedim); - } - // the page's meaningful content (including potential white space) - if (isset($format['ArtBox'])) { - $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'ArtBox', $format['ArtBox']['llx'], $format['ArtBox']['lly'], $format['ArtBox']['urx'], $format['ArtBox']['ury'], false, $this->k, $this->pagedim); - } - // specify the colours and other visual characteristics that should be used in displaying guidelines on the screen for the various page boundaries - if (isset($format['BoxColorInfo'])) { - $this->pagedim[$this->page]['BoxColorInfo'] = $format['BoxColorInfo']; - } - if (isset($format['Rotate']) AND (($format['Rotate'] % 90) == 0)) { - // The number of degrees by which the page shall be rotated clockwise when displayed or printed. The value shall be a multiple of 90. - $this->pagedim[$this->page]['Rotate'] = intval($format['Rotate']); - } - if (isset($format['PZ'])) { - // The page's preferred zoom (magnification) factor - $this->pagedim[$this->page]['PZ'] = floatval($format['PZ']); - } - if (isset($format['trans'])) { - // The style and duration of the visual transition to use when moving from another page to the given page during a presentation - if (isset($format['trans']['Dur'])) { - // The page's display duration - $this->pagedim[$this->page]['trans']['Dur'] = floatval($format['trans']['Dur']); - } - $stansition_styles = array('Split', 'Blinds', 'Box', 'Wipe', 'Dissolve', 'Glitter', 'R', 'Fly', 'Push', 'Cover', 'Uncover', 'Fade'); - if (isset($format['trans']['S']) AND in_array($format['trans']['S'], $stansition_styles)) { - // The transition style that shall be used when moving to this page from another during a presentation - $this->pagedim[$this->page]['trans']['S'] = $format['trans']['S']; - $valid_effect = array('Split', 'Blinds'); - $valid_vals = array('H', 'V'); - if (isset($format['trans']['Dm']) AND in_array($format['trans']['S'], $valid_effect) AND in_array($format['trans']['Dm'], $valid_vals)) { - $this->pagedim[$this->page]['trans']['Dm'] = $format['trans']['Dm']; - } - $valid_effect = array('Split', 'Box', 'Fly'); - $valid_vals = array('I', 'O'); - if (isset($format['trans']['M']) AND in_array($format['trans']['S'], $valid_effect) AND in_array($format['trans']['M'], $valid_vals)) { - $this->pagedim[$this->page]['trans']['M'] = $format['trans']['M']; - } - $valid_effect = array('Wipe', 'Glitter', 'Fly', 'Cover', 'Uncover', 'Push'); - if (isset($format['trans']['Di']) AND in_array($format['trans']['S'], $valid_effect)) { - if (((($format['trans']['Di'] == 90) OR ($format['trans']['Di'] == 180)) AND ($format['trans']['S'] == 'Wipe')) - OR (($format['trans']['Di'] == 315) AND ($format['trans']['S'] == 'Glitter')) - OR (($format['trans']['Di'] == 0) OR ($format['trans']['Di'] == 270))) { - $this->pagedim[$this->page]['trans']['Di'] = intval($format['trans']['Di']); - } - } - if (isset($format['trans']['SS']) AND ($format['trans']['S'] == 'Fly')) { - $this->pagedim[$this->page]['trans']['SS'] = floatval($format['trans']['SS']); - } - if (isset($format['trans']['B']) AND ($format['trans']['B'] === true) AND ($format['trans']['S'] == 'Fly')) { - $this->pagedim[$this->page]['trans']['B'] = 'true'; - } - } else { - $this->pagedim[$this->page]['trans']['S'] = 'R'; - } - if (isset($format['trans']['D'])) { - // The duration of the transition effect, in seconds - $this->pagedim[$this->page]['trans']['D'] = floatval($format['trans']['D']); - } else { - $this->pagedim[$this->page]['trans']['D'] = 1; - } - } - } - $this->setPageOrientation($orientation); - } - - /** - * Set page orientation. - * @param string $orientation page orientation. Possible values are (case insensitive):<ul><li>P or Portrait (default)</li><li>L or Landscape</li><li>'' (empty string) for automatic orientation</li></ul> - * @param boolean|null $autopagebreak Boolean indicating if auto-page-break mode should be on or off. - * @param float|null $bottommargin bottom margin of the page. - * @public - * @since 3.0.015 (2008-06-06) - */ - public function setPageOrientation($orientation, $autopagebreak=null, $bottommargin=null) { - if (!isset($this->pagedim[$this->page]['MediaBox'])) { - // the boundaries of the physical medium on which the page shall be displayed or printed - $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'MediaBox', 0, 0, $this->fwPt, $this->fhPt, true, $this->k, $this->pagedim); - } - if (!isset($this->pagedim[$this->page]['CropBox'])) { - // the visible region of default user space - $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'CropBox', $this->pagedim[$this->page]['MediaBox']['llx'], $this->pagedim[$this->page]['MediaBox']['lly'], $this->pagedim[$this->page]['MediaBox']['urx'], $this->pagedim[$this->page]['MediaBox']['ury'], true, $this->k, $this->pagedim); - } - if (!isset($this->pagedim[$this->page]['BleedBox'])) { - // the region to which the contents of the page shall be clipped when output in a production environment - $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'BleedBox', $this->pagedim[$this->page]['CropBox']['llx'], $this->pagedim[$this->page]['CropBox']['lly'], $this->pagedim[$this->page]['CropBox']['urx'], $this->pagedim[$this->page]['CropBox']['ury'], true, $this->k, $this->pagedim); - } - if (!isset($this->pagedim[$this->page]['TrimBox'])) { - // the intended dimensions of the finished page after trimming - $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'TrimBox', $this->pagedim[$this->page]['CropBox']['llx'], $this->pagedim[$this->page]['CropBox']['lly'], $this->pagedim[$this->page]['CropBox']['urx'], $this->pagedim[$this->page]['CropBox']['ury'], true, $this->k, $this->pagedim); - } - if (!isset($this->pagedim[$this->page]['ArtBox'])) { - // the page's meaningful content (including potential white space) - $this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'ArtBox', $this->pagedim[$this->page]['CropBox']['llx'], $this->pagedim[$this->page]['CropBox']['lly'], $this->pagedim[$this->page]['CropBox']['urx'], $this->pagedim[$this->page]['CropBox']['ury'], true, $this->k, $this->pagedim); - } - if (!isset($this->pagedim[$this->page]['Rotate'])) { - // The number of degrees by which the page shall be rotated clockwise when displayed or printed. The value shall be a multiple of 90. - $this->pagedim[$this->page]['Rotate'] = 0; - } - if (!isset($this->pagedim[$this->page]['PZ'])) { - // The page's preferred zoom (magnification) factor - $this->pagedim[$this->page]['PZ'] = 1; - } - if ($this->fwPt > $this->fhPt) { - // landscape - $default_orientation = 'L'; - } else { - // portrait - $default_orientation = 'P'; - } - $valid_orientations = array('P', 'L'); - if (empty($orientation)) { - $orientation = $default_orientation; - } else { - $orientation = strtoupper($orientation[0]); - } - if (in_array($orientation, $valid_orientations) AND ($orientation != $default_orientation)) { - $this->CurOrientation = $orientation; - $this->wPt = $this->fhPt; - $this->hPt = $this->fwPt; - } else { - $this->CurOrientation = $default_orientation; - $this->wPt = $this->fwPt; - $this->hPt = $this->fhPt; - } - if ((abs($this->pagedim[$this->page]['MediaBox']['urx'] - $this->hPt) < $this->feps) AND (abs($this->pagedim[$this->page]['MediaBox']['ury'] - $this->wPt) < $this->feps)){ - // swap X and Y coordinates (change page orientation) - $this->pagedim = TCPDF_STATIC::swapPageBoxCoordinates($this->page, $this->pagedim); - } - $this->w = ($this->wPt / $this->k); - $this->h = ($this->hPt / $this->k); - if (TCPDF_STATIC::empty_string($autopagebreak)) { - if (isset($this->AutoPageBreak)) { - $autopagebreak = $this->AutoPageBreak; - } else { - $autopagebreak = true; - } - } - if (TCPDF_STATIC::empty_string($bottommargin)) { - if (isset($this->bMargin)) { - $bottommargin = $this->bMargin; - } else { - // default value = 2 cm - $bottommargin = 2 * 28.35 / $this->k; - } - } - $this->setAutoPageBreak($autopagebreak, $bottommargin); - // store page dimensions - $this->pagedim[$this->page]['w'] = $this->wPt; - $this->pagedim[$this->page]['h'] = $this->hPt; - $this->pagedim[$this->page]['wk'] = $this->w; - $this->pagedim[$this->page]['hk'] = $this->h; - $this->pagedim[$this->page]['tm'] = $this->tMargin; - $this->pagedim[$this->page]['bm'] = $bottommargin; - $this->pagedim[$this->page]['lm'] = $this->lMargin; - $this->pagedim[$this->page]['rm'] = $this->rMargin; - $this->pagedim[$this->page]['pb'] = $autopagebreak; - $this->pagedim[$this->page]['or'] = $this->CurOrientation; - $this->pagedim[$this->page]['olm'] = $this->original_lMargin; - $this->pagedim[$this->page]['orm'] = $this->original_rMargin; - } - - /** - * Set regular expression to detect withespaces or word separators. - * The pattern delimiter must be the forward-slash character "/". - * Some example patterns are: - * <pre> - * Non-Unicode or missing PCRE unicode support: "/[^\S\xa0]/" - * Unicode and PCRE unicode support: "/(?!\xa0)[\s\p{Z}]/u" - * Unicode and PCRE unicode support in Chinese mode: "/(?!\xa0)[\s\p{Z}\p{Lo}]/u" - * if PCRE unicode support is turned ON ("\P" is the negate class of "\p"): - * \s : any whitespace character - * \p{Z} : any separator - * \p{Lo} : Unicode letter or ideograph that does not have lowercase and uppercase variants. Is used to chunk chinese words. - * \xa0 : Unicode Character 'NO-BREAK SPACE' (U+00A0) - * </pre> - * @param string $re regular expression (leave empty for default). - * @public - * @since 4.6.016 (2009-06-15) - */ - public function setSpacesRE($re='/[^\S\xa0]/') { - $this->re_spaces = $re; - $re_parts = explode('/', $re); - // get pattern parts - $this->re_space = array(); - if (isset($re_parts[1]) AND !empty($re_parts[1])) { - $this->re_space['p'] = $re_parts[1]; - } else { - $this->re_space['p'] = '[\s]'; - } - // set pattern modifiers - if (isset($re_parts[2]) AND !empty($re_parts[2])) { - $this->re_space['m'] = $re_parts[2]; - } else { - $this->re_space['m'] = ''; - } - } - - /** - * Enable or disable Right-To-Left language mode - * @param boolean $enable if true enable Right-To-Left language mode. - * @param boolean $resetx if true reset the X position on direction change. - * @public - * @since 2.0.000 (2008-01-03) - */ - public function setRTL($enable, $resetx=true) { - $enable = $enable ? true : false; - $resetx = ($resetx AND ($enable != $this->rtl)); - $this->rtl = $enable; - $this->tmprtl = false; - if ($resetx) { - $this->Ln(0); - } - } - - /** - * Return the RTL status - * @return bool - * @public - * @since 4.0.012 (2008-07-24) - */ - public function getRTL() { - return $this->rtl; - } - - /** - * Force temporary RTL language direction - * @param false|string $mode can be false, 'L' for LTR or 'R' for RTL - * @public - * @since 2.1.000 (2008-01-09) - */ - public function setTempRTL($mode) { - $newmode = false; - switch (strtoupper($mode)) { - case 'LTR': - case 'L': { - if ($this->rtl) { - $newmode = 'L'; - } - break; - } - case 'RTL': - case 'R': { - if (!$this->rtl) { - $newmode = 'R'; - } - break; - } - case false: - default: { - $newmode = false; - break; - } - } - $this->tmprtl = $newmode; - } - - /** - * Return the current temporary RTL status - * @return bool - * @public - * @since 4.8.014 (2009-11-04) - */ - public function isRTLTextDir() { - return ($this->rtl OR ($this->tmprtl == 'R')); - } - - /** - * Set the last cell height. - * @param float $h cell height. - * @author Nicola Asuni - * @public - * @since 1.53.0.TC034 - */ - public function setLastH($h) { - $this->lasth = $h; - } - - /** - * Return the cell height - * @param int $fontsize Font size in internal units - * @param boolean $padding If true add cell padding - * @public - * @return float - */ - public function getCellHeight($fontsize, $padding=TRUE) { - $height = ($fontsize * $this->cell_height_ratio); - if ($padding) { - $height += ($this->cell_padding['T'] + $this->cell_padding['B']); - } - return round($height, 6); - } - - /** - * Reset the last cell height. - * @public - * @since 5.9.000 (2010-10-03) - */ - public function resetLastH() { - $this->lasth = $this->getCellHeight($this->FontSize); - } - - /** - * Get the last cell height. - * @return float last cell height - * @public - * @since 4.0.017 (2008-08-05) - */ - public function getLastH() { - return $this->lasth; - } - - /** - * Set the adjusting factor to convert pixels to user units. - * @param float $scale adjusting factor to convert pixels to user units. - * @author Nicola Asuni - * @public - * @since 1.5.2 - */ - public function setImageScale($scale) { - $this->imgscale = $scale; - } - - /** - * Returns the adjusting factor to convert pixels to user units. - * @return float adjusting factor to convert pixels to user units. - * @author Nicola Asuni - * @public - * @since 1.5.2 - */ - public function getImageScale() { - return $this->imgscale; - } - - /** - * Returns an array of page dimensions: - * <ul><li>$this->pagedim[$this->page]['w'] = page width in points</li><li>$this->pagedim[$this->page]['h'] = height in points</li><li>$this->pagedim[$this->page]['wk'] = page width in user units</li><li>$this->pagedim[$this->page]['hk'] = page height in user units</li><li>$this->pagedim[$this->page]['tm'] = top margin</li><li>$this->pagedim[$this->page]['bm'] = bottom margin</li><li>$this->pagedim[$this->page]['lm'] = left margin</li><li>$this->pagedim[$this->page]['rm'] = right margin</li><li>$this->pagedim[$this->page]['pb'] = auto page break</li><li>$this->pagedim[$this->page]['or'] = page orientation</li><li>$this->pagedim[$this->page]['olm'] = original left margin</li><li>$this->pagedim[$this->page]['orm'] = original right margin</li><li>$this->pagedim[$this->page]['Rotate'] = The number of degrees by which the page shall be rotated clockwise when displayed or printed. The value shall be a multiple of 90.</li><li>$this->pagedim[$this->page]['PZ'] = The page's preferred zoom (magnification) factor.</li><li>$this->pagedim[$this->page]['trans'] : the style and duration of the visual transition to use when moving from another page to the given page during a presentation<ul><li>$this->pagedim[$this->page]['trans']['Dur'] = The page's display duration (also called its advance timing): the maximum length of time, in seconds, that the page shall be displayed during presentations before the viewer application shall automatically advance to the next page.</li><li>$this->pagedim[$this->page]['trans']['S'] = transition style : Split, Blinds, Box, Wipe, Dissolve, Glitter, R, Fly, Push, Cover, Uncover, Fade</li><li>$this->pagedim[$this->page]['trans']['D'] = The duration of the transition effect, in seconds.</li><li>$this->pagedim[$this->page]['trans']['Dm'] = (Split and Blinds transition styles only) The dimension in which the specified transition effect shall occur: H = Horizontal, V = Vertical. Default value: H.</li><li>$this->pagedim[$this->page]['trans']['M'] = (Split, Box and Fly transition styles only) The direction of motion for the specified transition effect: I = Inward from the edges of the page, O = Outward from the center of the pageDefault value: I.</li><li>$this->pagedim[$this->page]['trans']['Di'] = (Wipe, Glitter, Fly, Cover, Uncover and Push transition styles only) The direction in which the specified transition effect shall moves, expressed in degrees counterclockwise starting from a left-to-right direction. If the value is a number, it shall be one of: 0 = Left to right, 90 = Bottom to top (Wipe only), 180 = Right to left (Wipe only), 270 = Top to bottom, 315 = Top-left to bottom-right (Glitter only). If the value is a name, it shall be None, which is relevant only for the Fly transition when the value of SS is not 1.0. Default value: 0.</li><li>$this->pagedim[$this->page]['trans']['SS'] = (Fly transition style only) The starting or ending scale at which the changes shall be drawn. If M specifies an inward transition, the scale of the changes drawn shall progress from SS to 1.0 over the course of the transition. If M specifies an outward transition, the scale of the changes drawn shall progress from 1.0 to SS over the course of the transition. Default: 1.0. </li><li>$this->pagedim[$this->page]['trans']['B'] = (Fly transition style only) If true, the area that shall be flown in is rectangular and opaque. Default: false.</li></ul></li><li>$this->pagedim[$this->page]['MediaBox'] : the boundaries of the physical medium on which the page shall be displayed or printed<ul><li>$this->pagedim[$this->page]['MediaBox']['llx'] = lower-left x coordinate in points</li><li>$this->pagedim[$this->page]['MediaBox']['lly'] = lower-left y coordinate in points</li><li>$this->pagedim[$this->page]['MediaBox']['urx'] = upper-right x coordinate in points</li><li>$this->pagedim[$this->page]['MediaBox']['ury'] = upper-right y coordinate in points</li></ul></li><li>$this->pagedim[$this->page]['CropBox'] : the visible region of default user space<ul><li>$this->pagedim[$this->page]['CropBox']['llx'] = lower-left x coordinate in points</li><li>$this->pagedim[$this->page]['CropBox']['lly'] = lower-left y coordinate in points</li><li>$this->pagedim[$this->page]['CropBox']['urx'] = upper-right x coordinate in points</li><li>$this->pagedim[$this->page]['CropBox']['ury'] = upper-right y coordinate in points</li></ul></li><li>$this->pagedim[$this->page]['BleedBox'] : the region to which the contents of the page shall be clipped when output in a production environment<ul><li>$this->pagedim[$this->page]['BleedBox']['llx'] = lower-left x coordinate in points</li><li>$this->pagedim[$this->page]['BleedBox']['lly'] = lower-left y coordinate in points</li><li>$this->pagedim[$this->page]['BleedBox']['urx'] = upper-right x coordinate in points</li><li>$this->pagedim[$this->page]['BleedBox']['ury'] = upper-right y coordinate in points</li></ul></li><li>$this->pagedim[$this->page]['TrimBox'] : the intended dimensions of the finished page after trimming<ul><li>$this->pagedim[$this->page]['TrimBox']['llx'] = lower-left x coordinate in points</li><li>$this->pagedim[$this->page]['TrimBox']['lly'] = lower-left y coordinate in points</li><li>$this->pagedim[$this->page]['TrimBox']['urx'] = upper-right x coordinate in points</li><li>$this->pagedim[$this->page]['TrimBox']['ury'] = upper-right y coordinate in points</li></ul></li><li>$this->pagedim[$this->page]['ArtBox'] : the extent of the page's meaningful content<ul><li>$this->pagedim[$this->page]['ArtBox']['llx'] = lower-left x coordinate in points</li><li>$this->pagedim[$this->page]['ArtBox']['lly'] = lower-left y coordinate in points</li><li>$this->pagedim[$this->page]['ArtBox']['urx'] = upper-right x coordinate in points</li><li>$this->pagedim[$this->page]['ArtBox']['ury'] = upper-right y coordinate in points</li></ul></li></ul> - * @param int|null $pagenum page number (empty = current page) - * @return array of page dimensions. - * @author Nicola Asuni - * @public - * @since 4.5.027 (2009-03-16) - */ - public function getPageDimensions($pagenum=null) { - if (empty($pagenum)) { - $pagenum = $this->page; - } - return $this->pagedim[$pagenum]; - } - - /** - * Returns the page width in units. - * @param int|null $pagenum page number (empty = current page) - * @return int page width. - * @author Nicola Asuni - * @public - * @since 1.5.2 - * @see getPageDimensions() - */ - public function getPageWidth($pagenum=null) { - if (empty($pagenum)) { - return $this->w; - } - return $this->pagedim[$pagenum]['w']; - } - - /** - * Returns the page height in units. - * @param int|null $pagenum page number (empty = current page) - * @return int page height. - * @author Nicola Asuni - * @public - * @since 1.5.2 - * @see getPageDimensions() - */ - public function getPageHeight($pagenum=null) { - if (empty($pagenum)) { - return $this->h; - } - return $this->pagedim[$pagenum]['h']; - } - - /** - * Returns the page break margin. - * @param int|null $pagenum page number (empty = current page) - * @return int page break margin. - * @author Nicola Asuni - * @public - * @since 1.5.2 - * @see getPageDimensions() - */ - public function getBreakMargin($pagenum=null) { - if (empty($pagenum)) { - return $this->bMargin; - } - return $this->pagedim[$pagenum]['bm']; - } - - /** - * Returns the scale factor (number of points in user unit). - * @return int scale factor. - * @author Nicola Asuni - * @public - * @since 1.5.2 - */ - public function getScaleFactor() { - return $this->k; - } - - /** - * Defines the left, top and right margins. - * @param float $left Left margin. - * @param float $top Top margin. - * @param float $right Right margin. Default value is the left one. - * @param boolean $keepmargins if true overwrites the default page margins - * @public - * @since 1.0 - * @see SetLeftMargin(), SetTopMargin(), SetRightMargin(), SetAutoPageBreak() - */ - public function setMargins($left, $top, $right=null, $keepmargins=false) { - //Set left, top and right margins - $this->lMargin = $left; - $this->tMargin = $top; - if ($right == -1 OR $right === null) { - $right = $left; - } - $this->rMargin = $right; - if ($keepmargins) { - // overwrite original values - $this->original_lMargin = $this->lMargin; - $this->original_rMargin = $this->rMargin; - } - } - - /** - * Defines the left margin. The method can be called before creating the first page. If the current abscissa gets out of page, it is brought back to the margin. - * @param float $margin The margin. - * @public - * @since 1.4 - * @see SetTopMargin(), SetRightMargin(), SetAutoPageBreak(), SetMargins() - */ - public function setLeftMargin($margin) { - //Set left margin - $this->lMargin = $margin; - if (($this->page > 0) AND ($this->x < $margin)) { - $this->x = $margin; - } - } - - /** - * Defines the top margin. The method can be called before creating the first page. - * @param float $margin The margin. - * @public - * @since 1.5 - * @see SetLeftMargin(), SetRightMargin(), SetAutoPageBreak(), SetMargins() - */ - public function setTopMargin($margin) { - //Set top margin - $this->tMargin = $margin; - if (($this->page > 0) AND ($this->y < $margin)) { - $this->y = $margin; - } - } - - /** - * Defines the right margin. The method can be called before creating the first page. - * @param float $margin The margin. - * @public - * @since 1.5 - * @see SetLeftMargin(), SetTopMargin(), SetAutoPageBreak(), SetMargins() - */ - public function setRightMargin($margin) { - $this->rMargin = $margin; - if (($this->page > 0) AND ($this->x > ($this->w - $margin))) { - $this->x = $this->w - $margin; - } - } - - /** - * Set the same internal Cell padding for top, right, bottom, left- - * @param float $pad internal padding. - * @public - * @since 2.1.000 (2008-01-09) - * @see getCellPaddings(), setCellPaddings() - */ - public function setCellPadding($pad) { - if ($pad >= 0) { - $this->cell_padding['L'] = $pad; - $this->cell_padding['T'] = $pad; - $this->cell_padding['R'] = $pad; - $this->cell_padding['B'] = $pad; - } - } - - /** - * Set the internal Cell paddings. - * @param float|null $left left padding - * @param float|null $top top padding - * @param float|null $right right padding - * @param float|null $bottom bottom padding - * @public - * @since 5.9.000 (2010-10-03) - * @see getCellPaddings(), SetCellPadding() - */ - public function setCellPaddings($left=null, $top=null, $right=null, $bottom=null) { - if (!TCPDF_STATIC::empty_string($left) AND ($left >= 0)) { - $this->cell_padding['L'] = $left; - } - if (!TCPDF_STATIC::empty_string($top) AND ($top >= 0)) { - $this->cell_padding['T'] = $top; - } - if (!TCPDF_STATIC::empty_string($right) AND ($right >= 0)) { - $this->cell_padding['R'] = $right; - } - if (!TCPDF_STATIC::empty_string($bottom) AND ($bottom >= 0)) { - $this->cell_padding['B'] = $bottom; - } - } - - /** - * Get the internal Cell padding array. - * @return array of padding values - * @public - * @since 5.9.000 (2010-10-03) - * @see setCellPaddings(), SetCellPadding() - */ - public function getCellPaddings() { - return $this->cell_padding; - } - - /** - * Set the internal Cell margins. - * @param float|null $left left margin - * @param float|null $top top margin - * @param float|null $right right margin - * @param float|null $bottom bottom margin - * @public - * @since 5.9.000 (2010-10-03) - * @see getCellMargins() - */ - public function setCellMargins($left=null, $top=null, $right=null, $bottom=null) { - if (!TCPDF_STATIC::empty_string($left) AND ($left >= 0)) { - $this->cell_margin['L'] = $left; - } - if (!TCPDF_STATIC::empty_string($top) AND ($top >= 0)) { - $this->cell_margin['T'] = $top; - } - if (!TCPDF_STATIC::empty_string($right) AND ($right >= 0)) { - $this->cell_margin['R'] = $right; - } - if (!TCPDF_STATIC::empty_string($bottom) AND ($bottom >= 0)) { - $this->cell_margin['B'] = $bottom; - } - } - - /** - * Get the internal Cell margin array. - * @return array of margin values - * @public - * @since 5.9.000 (2010-10-03) - * @see setCellMargins() - */ - public function getCellMargins() { - return $this->cell_margin; - } - - /** - * Adjust the internal Cell padding array to take account of the line width. - * @param string|array|int $brd Indicates if borders must be drawn around the cell. The value can be a number:<ul><li>0: no border (default)</li><li>1: frame</li></ul> or a string containing some or all of the following characters (in any order):<ul><li>L: left</li><li>T: top</li><li>R: right</li><li>B: bottom</li></ul> or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - * @return void|array array of adjustments - * @public - * @since 5.9.000 (2010-10-03) - */ - protected function adjustCellPadding($brd=0) { - if (empty($brd)) { - return; - } - if (is_string($brd)) { - // convert string to array - $slen = strlen($brd); - $newbrd = array(); - for ($i = 0; $i < $slen; ++$i) { - $newbrd[$brd[$i]] = true; - } - $brd = $newbrd; - } elseif ( - ($brd === 1) - || ($brd === true) - || (is_numeric($brd) && ((int)$brd > 0)) - ) { - $brd = array('LRTB' => true); - } - if (!is_array($brd)) { - return; - } - // store current cell padding - $cp = $this->cell_padding; - // select border mode - if (isset($brd['mode'])) { - $mode = $brd['mode']; - unset($brd['mode']); - } else { - $mode = 'normal'; - } - // process borders - foreach ($brd as $border => $style) { - $line_width = $this->LineWidth; - if (is_array($style) && isset($style['width'])) { - // get border width - $line_width = $style['width']; - } - $adj = 0; // line width inside the cell - switch ($mode) { - case 'ext': { - $adj = 0; - break; - } - case 'int': { - $adj = $line_width; - break; - } - case 'normal': - default: { - $adj = ($line_width / 2); - break; - } - } - // correct internal cell padding if required to avoid overlap between text and lines - if ( - is_numeric($this->cell_padding['T']) - && ($this->cell_padding['T'] < $adj) - && (strpos($border, 'T') !== false) - ) { - $this->cell_padding['T'] = $adj; - } - if ( - is_numeric($this->cell_padding['R']) - && ($this->cell_padding['R'] < $adj) - && (strpos($border, 'R') !== false) - ) { - $this->cell_padding['R'] = $adj; - } - if ( - is_numeric($this->cell_padding['B']) - && ($this->cell_padding['B'] < $adj) - && (strpos($border, 'B') !== false) - ) { - $this->cell_padding['B'] = $adj; - } - if ( - is_numeric($this->cell_padding['L']) - && ($this->cell_padding['L'] < $adj) - && (strpos($border, 'L') !== false) - ) { - $this->cell_padding['L'] = $adj; - } - - } - - return array( - 'T' => ($this->cell_padding['T'] - $cp['T']), - 'R' => ($this->cell_padding['R'] - $cp['R']), - 'B' => ($this->cell_padding['B'] - $cp['B']), - 'L' => ($this->cell_padding['L'] - $cp['L']), - ); - } - - /** - * Enables or disables the automatic page breaking mode. When enabling, the second parameter is the distance from the bottom of the page that defines the triggering limit. By default, the mode is on and the margin is 2 cm. - * @param boolean $auto Boolean indicating if mode should be on or off. - * @param float $margin Distance from the bottom of the page. - * @public - * @since 1.0 - * @see Cell(), MultiCell(), AcceptPageBreak() - */ - public function setAutoPageBreak($auto, $margin=0) { - $this->AutoPageBreak = $auto ? true : false; - $this->bMargin = $margin; - $this->PageBreakTrigger = $this->h - $margin; - } - - /** - * Return the auto-page-break mode (true or false). - * @return bool auto-page-break mode - * @public - * @since 5.9.088 - */ - public function getAutoPageBreak() { - return $this->AutoPageBreak; - } - - /** - * Defines the way the document is to be displayed by the viewer. - * @param mixed $zoom The zoom to use. It can be one of the following string values or a number indicating the zooming factor to use. <ul><li>fullpage: displays the entire page on screen </li><li>fullwidth: uses maximum width of window</li><li>real: uses real size (equivalent to 100% zoom)</li><li>default: uses viewer default mode</li></ul> - * @param string $layout The page layout. Possible values are:<ul><li>SinglePage Display one page at a time</li><li>OneColumn Display the pages in one column</li><li>TwoColumnLeft Display the pages in two columns, with odd-numbered pages on the left</li><li>TwoColumnRight Display the pages in two columns, with odd-numbered pages on the right</li><li>TwoPageLeft (PDF 1.5) Display the pages two at a time, with odd-numbered pages on the left</li><li>TwoPageRight (PDF 1.5) Display the pages two at a time, with odd-numbered pages on the right</li></ul> - * @param string $mode A name object specifying how the document should be displayed when opened:<ul><li>UseNone Neither document outline nor thumbnail images visible</li><li>UseOutlines Document outline visible</li><li>UseThumbs Thumbnail images visible</li><li>FullScreen Full-screen mode, with no menu bar, window controls, or any other window visible</li><li>UseOC (PDF 1.5) Optional content group panel visible</li><li>UseAttachments (PDF 1.6) Attachments panel visible</li></ul> - * @public - * @since 1.2 - */ - public function setDisplayMode($zoom, $layout='SinglePage', $mode='UseNone') { - if (($zoom == 'fullpage') OR ($zoom == 'fullwidth') OR ($zoom == 'real') OR ($zoom == 'default') OR (!is_string($zoom))) { - $this->ZoomMode = $zoom; - } else { - $this->Error('Incorrect zoom display mode: '.$zoom); - } - $this->LayoutMode = TCPDF_STATIC::getPageLayoutMode($layout); - $this->PageMode = TCPDF_STATIC::getPageMode($mode); - } - - /** - * Activates or deactivates page compression. When activated, the internal representation of each page is compressed, which leads to a compression ratio of about 2 for the resulting document. Compression is on by default. - * Note: the Zlib extension is required for this feature. If not present, compression will be turned off. - * @param boolean $compress Boolean indicating if compression must be enabled. - * @public - * @since 1.4 - */ - public function setCompression($compress=true) { - $this->compress = false; - if (function_exists('gzcompress')) { - if ($compress) { - if ( !$this->pdfa_mode) { - $this->compress = true; - } - } - } - } - - /** - * Set flag to force sRGB_IEC61966-2.1 black scaled ICC color profile for the whole document. - * @param boolean $mode If true force sRGB output intent. - * @public - * @since 5.9.121 (2011-09-28) - */ - public function setSRGBmode($mode=false) { - $this->force_srgb = $mode ? true : false; - } - - /** - * Turn on/off Unicode mode for document information dictionary (meta tags). - * This has effect only when unicode mode is set to false. - * @param boolean $unicode if true set the meta information in Unicode - * @since 5.9.027 (2010-12-01) - * @public - */ - public function setDocInfoUnicode($unicode=true) { - $this->docinfounicode = $unicode ? true : false; - } - - /** - * Defines the title of the document. - * @param string $title The title. - * @public - * @since 1.2 - * @see SetAuthor(), SetCreator(), SetKeywords(), SetSubject() - */ - public function setTitle($title) { - $this->title = $title; - } - - /** - * Defines the subject of the document. - * @param string $subject The subject. - * @public - * @since 1.2 - * @see SetAuthor(), SetCreator(), SetKeywords(), SetTitle() - */ - public function setSubject($subject) { - $this->subject = $subject; - } - - /** - * Defines the author of the document. - * @param string $author The name of the author. - * @public - * @since 1.2 - * @see SetCreator(), SetKeywords(), SetSubject(), SetTitle() - */ - public function setAuthor($author) { - $this->author = $author; - } - - /** - * Associates keywords with the document, generally in the form 'keyword1 keyword2 ...'. - * @param string $keywords The list of keywords. - * @public - * @since 1.2 - * @see SetAuthor(), SetCreator(), SetSubject(), SetTitle() - */ - public function setKeywords($keywords) { - $this->keywords = $keywords; - } - - /** - * Defines the creator of the document. This is typically the name of the application that generates the PDF. - * @param string $creator The name of the creator. - * @public - * @since 1.2 - * @see SetAuthor(), SetKeywords(), SetSubject(), SetTitle() - */ - public function setCreator($creator) { - $this->creator = $creator; - } - - /** - * Whether to allow local file path in image html tags, when prefixed with file:// - * - * @param bool $allowLocalFiles true, when local files should be allowed. Otherwise false. - * @public - * @since 6.4 - */ - public function setAllowLocalFiles($allowLocalFiles) { - $this->allowLocalFiles = (bool) $allowLocalFiles; - } - - - /** - * Throw an exception or print an error message and die if the K_TCPDF_PARSER_THROW_EXCEPTION_ERROR constant is set to true. - * @param string $msg The error message - * @public - * @since 1.0 - */ - public function Error($msg) { - // unset all class variables - $this->_destroy(true); - if (defined('K_TCPDF_THROW_EXCEPTION_ERROR') AND !K_TCPDF_THROW_EXCEPTION_ERROR) { - die('<strong>TCPDF ERROR: </strong>'.$msg); - } else { - throw new Exception('TCPDF ERROR: '.$msg); - } - } - - /** - * This method begins the generation of the PDF document. - * It is not necessary to call it explicitly because AddPage() does it automatically. - * Note: no page is created by this method - * @public - * @since 1.0 - * @see AddPage(), Close() - */ - public function Open() { - $this->state = 1; - } - - /** - * Terminates the PDF document. - * It is not necessary to call this method explicitly because Output() does it automatically. - * If the document contains no page, AddPage() is called to prevent from getting an invalid document. - * @public - * @since 1.0 - * @see Open(), Output() - */ - public function Close() { - if ($this->state == 3) { - return; - } - if ($this->page == 0) { - $this->AddPage(); - } - $this->endLayer(); - if ($this->tcpdflink) { - // save current graphic settings - $gvars = $this->getGraphicVars(); - $this->setEqualColumns(); - $this->lastpage(true); - $this->setAutoPageBreak(false); - $this->x = 0; - $this->y = $this->h - (1 / $this->k); - $this->lMargin = 0; - $this->_outSaveGraphicsState(); - $font = defined('PDF_FONT_NAME_MAIN')?PDF_FONT_NAME_MAIN:'helvetica'; - $this->setFont($font, '', 1); - $this->setTextRenderingMode(0, false, false); - $msg = "\x50\x6f\x77\x65\x72\x65\x64\x20\x62\x79\x20\x54\x43\x50\x44\x46\x20\x28\x77\x77\x77\x2e\x74\x63\x70\x64\x66\x2e\x6f\x72\x67\x29"; - $lnk = "\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x74\x63\x70\x64\x66\x2e\x6f\x72\x67"; - $this->Cell(0, 0, $msg, 0, 0, 'L', 0, $lnk, 0, false, 'D', 'B'); - $this->_outRestoreGraphicsState(); - // restore graphic settings - $this->setGraphicVars($gvars); - } - // close page - $this->endPage(); - // close document - $this->_enddoc(); - // unset all class variables (except critical ones) - $this->_destroy(false); - } - - /** - * Move pointer at the specified document page and update page dimensions. - * @param int $pnum page number (1 ... numpages) - * @param boolean $resetmargins if true reset left, right, top margins and Y position. - * @public - * @since 2.1.000 (2008-01-07) - * @see getPage(), lastpage(), getNumPages() - */ - public function setPage($pnum, $resetmargins=false) { - if (($pnum == $this->page) AND ($this->state == 2)) { - return; - } - if (($pnum > 0) AND ($pnum <= $this->numpages)) { - $this->state = 2; - // save current graphic settings - //$gvars = $this->getGraphicVars(); - $oldpage = $this->page; - $this->page = $pnum; - $this->wPt = $this->pagedim[$this->page]['w']; - $this->hPt = $this->pagedim[$this->page]['h']; - $this->w = $this->pagedim[$this->page]['wk']; - $this->h = $this->pagedim[$this->page]['hk']; - $this->tMargin = $this->pagedim[$this->page]['tm']; - $this->bMargin = $this->pagedim[$this->page]['bm']; - $this->original_lMargin = $this->pagedim[$this->page]['olm']; - $this->original_rMargin = $this->pagedim[$this->page]['orm']; - $this->AutoPageBreak = $this->pagedim[$this->page]['pb']; - $this->CurOrientation = $this->pagedim[$this->page]['or']; - $this->setAutoPageBreak($this->AutoPageBreak, $this->bMargin); - // restore graphic settings - //$this->setGraphicVars($gvars); - if ($resetmargins) { - $this->lMargin = $this->pagedim[$this->page]['olm']; - $this->rMargin = $this->pagedim[$this->page]['orm']; - $this->setY($this->tMargin); - } else { - // account for booklet mode - if ($this->pagedim[$this->page]['olm'] != $this->pagedim[$oldpage]['olm']) { - $deltam = $this->pagedim[$this->page]['olm'] - $this->pagedim[$this->page]['orm']; - $this->lMargin += $deltam; - $this->rMargin -= $deltam; - } - } - } else { - $this->Error('Wrong page number on setPage() function: '.$pnum); - } - } - - /** - * Reset pointer to the last document page. - * @param boolean $resetmargins if true reset left, right, top margins and Y position. - * @public - * @since 2.0.000 (2008-01-04) - * @see setPage(), getPage(), getNumPages() - */ - public function lastPage($resetmargins=false) { - $this->setPage($this->getNumPages(), $resetmargins); - } - - /** - * Get current document page number. - * @return int page number - * @public - * @since 2.1.000 (2008-01-07) - * @see setPage(), lastpage(), getNumPages() - */ - public function getPage() { - return $this->page; - } - - /** - * Get the total number of insered pages. - * @return int number of pages - * @public - * @since 2.1.000 (2008-01-07) - * @see setPage(), getPage(), lastpage() - */ - public function getNumPages() { - return $this->numpages; - } - - /** - * Adds a new TOC (Table Of Content) page to the document. - * @param string $orientation page orientation. - * @param mixed $format The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() or an array of parameters specified at setPageFormat(). - * @param boolean $keepmargins if true overwrites the default page margins with the current margins - * @public - * @since 5.0.001 (2010-05-06) - * @see AddPage(), startPage(), endPage(), endTOCPage() - */ - public function addTOCPage($orientation='', $format='', $keepmargins=false) { - $this->AddPage($orientation, $format, $keepmargins, true); - } - - /** - * Terminate the current TOC (Table Of Content) page - * @public - * @since 5.0.001 (2010-05-06) - * @see AddPage(), startPage(), endPage(), addTOCPage() - */ - public function endTOCPage() { - $this->endPage(true); - } - - /** - * Adds a new page to the document. If a page is already present, the Footer() method is called first to output the footer (if enabled). Then the page is added, the current position set to the top-left corner according to the left and top margins (or top-right if in RTL mode), and Header() is called to display the header (if enabled). - * The origin of the coordinate system is at the top-left corner (or top-right for RTL) and increasing ordinates go downwards. - * @param string $orientation page orientation. Possible values are (case insensitive):<ul><li>P or PORTRAIT (default)</li><li>L or LANDSCAPE</li></ul> - * @param mixed $format The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() or an array of parameters specified at setPageFormat(). - * @param boolean $keepmargins if true overwrites the default page margins with the current margins - * @param boolean $tocpage if true set the tocpage state to true (the added page will be used to display Table Of Content). - * @public - * @since 1.0 - * @see startPage(), endPage(), addTOCPage(), endTOCPage(), getPageSizeFromFormat(), setPageFormat() - */ - public function AddPage($orientation='', $format='', $keepmargins=false, $tocpage=false) { - if ($this->inxobj) { - // we are inside an XObject template - return; - } - if (!isset($this->original_lMargin) OR $keepmargins) { - $this->original_lMargin = $this->lMargin; - } - if (!isset($this->original_rMargin) OR $keepmargins) { - $this->original_rMargin = $this->rMargin; - } - // terminate previous page - $this->endPage(); - // start new page - $this->startPage($orientation, $format, $tocpage); - } - - /** - * Terminate the current page - * @param boolean $tocpage if true set the tocpage state to false (end the page used to display Table Of Content). - * @public - * @since 4.2.010 (2008-11-14) - * @see AddPage(), startPage(), addTOCPage(), endTOCPage() - */ - public function endPage($tocpage=false) { - // check if page is already closed - if (($this->page == 0) OR ($this->numpages > $this->page) OR (!$this->pageopen[$this->page])) { - return; - } - // print page footer - $this->setFooter(); - // close page - $this->_endpage(); - // mark page as closed - $this->pageopen[$this->page] = false; - if ($tocpage) { - $this->tocpage = false; - } - } - - /** - * Starts a new page to the document. The page must be closed using the endPage() function. - * The origin of the coordinate system is at the top-left corner and increasing ordinates go downwards. - * @param string $orientation page orientation. Possible values are (case insensitive):<ul><li>P or PORTRAIT (default)</li><li>L or LANDSCAPE</li></ul> - * @param mixed $format The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() or an array of parameters specified at setPageFormat(). - * @param boolean $tocpage if true the page is designated to contain the Table-Of-Content. - * @since 4.2.010 (2008-11-14) - * @see AddPage(), endPage(), addTOCPage(), endTOCPage(), getPageSizeFromFormat(), setPageFormat() - * @public - */ - public function startPage($orientation='', $format='', $tocpage=false) { - if ($tocpage) { - $this->tocpage = true; - } - // move page numbers of documents to be attached - if ($this->tocpage) { - // move reference to unexistent pages (used for page attachments) - // adjust outlines - $tmpoutlines = $this->outlines; - foreach ($tmpoutlines as $key => $outline) { - if (!$outline['f'] AND ($outline['p'] > $this->numpages)) { - $this->outlines[$key]['p'] = ($outline['p'] + 1); - } - } - // adjust dests - $tmpdests = $this->dests; - foreach ($tmpdests as $key => $dest) { - if (!$dest['f'] AND ($dest['p'] > $this->numpages)) { - $this->dests[$key]['p'] = ($dest['p'] + 1); - } - } - // adjust links - $tmplinks = $this->links; - foreach ($tmplinks as $key => $link) { - if (!$link['f'] AND ($link['p'] > $this->numpages)) { - $this->links[$key]['p'] = ($link['p'] + 1); - } - } - } - if ($this->numpages > $this->page) { - // this page has been already added - $this->setPage($this->page + 1); - $this->setY($this->tMargin); - return; - } - // start a new page - if ($this->state == 0) { - $this->Open(); - } - ++$this->numpages; - $this->swapMargins($this->booklet); - // save current graphic settings - $gvars = $this->getGraphicVars(); - // start new page - $this->_beginpage($orientation, $format); - // mark page as open - $this->pageopen[$this->page] = true; - // restore graphic settings - $this->setGraphicVars($gvars); - // mark this point - $this->setPageMark(); - // print page header - $this->setHeader(); - // restore graphic settings - $this->setGraphicVars($gvars); - // mark this point - $this->setPageMark(); - // print table header (if any) - $this->setTableHeader(); - // set mark for empty page check - $this->emptypagemrk[$this->page]= $this->pagelen[$this->page]; - } - - /** - * Set start-writing mark on current page stream used to put borders and fills. - * Borders and fills are always created after content and inserted on the position marked by this method. - * This function must be called after calling Image() function for a background image. - * Background images must be always inserted before calling Multicell() or WriteHTMLCell() or WriteHTML() functions. - * @public - * @since 4.0.016 (2008-07-30) - */ - public function setPageMark() { - $this->intmrk[$this->page] = $this->pagelen[$this->page]; - $this->bordermrk[$this->page] = $this->intmrk[$this->page]; - $this->setContentMark(); - } - - /** - * Set start-writing mark on selected page. - * Borders and fills are always created after content and inserted on the position marked by this method. - * @param int $page page number (default is the current page) - * @protected - * @since 4.6.021 (2009-07-20) - */ - protected function setContentMark($page=0) { - if ($page <= 0) { - $page = $this->page; - } - if (isset($this->footerlen[$page])) { - $this->cntmrk[$page] = $this->pagelen[$page] - $this->footerlen[$page]; - } else { - $this->cntmrk[$page] = $this->pagelen[$page]; - } - } - - /** - * Set header data. - * @param string $ln header image logo - * @param int $lw header image logo width in mm - * @param string $ht string to print as title on document header - * @param string $hs string to print on document header - * @param int[] $tc RGB array color for text. - * @param int[] $lc RGB array color for line. - * @public - */ - public function setHeaderData($ln='', $lw=0, $ht='', $hs='', $tc=array(0,0,0), $lc=array(0,0,0)) { - $this->header_logo = $ln; - $this->header_logo_width = $lw; - $this->header_title = $ht; - $this->header_string = $hs; - $this->header_text_color = $tc; - $this->header_line_color = $lc; - } - - /** - * Set footer data. - * @param int[] $tc RGB array color for text. - * @param int[] $lc RGB array color for line. - * @public - */ - public function setFooterData($tc=array(0,0,0), $lc=array(0,0,0)) { - $this->footer_text_color = $tc; - $this->footer_line_color = $lc; - } - - /** - * Returns header data: - * <ul><li>$ret['logo'] = logo image</li><li>$ret['logo_width'] = width of the image logo in user units</li><li>$ret['title'] = header title</li><li>$ret['string'] = header description string</li></ul> - * @return array<string,mixed> - * @public - * @since 4.0.012 (2008-07-24) - */ - public function getHeaderData() { - $ret = array(); - $ret['logo'] = $this->header_logo; - $ret['logo_width'] = $this->header_logo_width; - $ret['title'] = $this->header_title; - $ret['string'] = $this->header_string; - $ret['text_color'] = $this->header_text_color; - $ret['line_color'] = $this->header_line_color; - return $ret; - } - - /** - * Set header margin. - * (minimum distance between header and top page margin) - * @param int $hm distance in user units - * @public - */ - public function setHeaderMargin($hm=10) { - $this->header_margin = $hm; - } - - /** - * Returns header margin in user units. - * @return float - * @since 4.0.012 (2008-07-24) - * @public - */ - public function getHeaderMargin() { - return $this->header_margin; - } - - /** - * Set footer margin. - * (minimum distance between footer and bottom page margin) - * @param int $fm distance in user units - * @public - */ - public function setFooterMargin($fm=10) { - $this->footer_margin = $fm; - } - - /** - * Returns footer margin in user units. - * @return float - * @since 4.0.012 (2008-07-24) - * @public - */ - public function getFooterMargin() { - return $this->footer_margin; - } - /** - * Set a flag to print page header. - * @param boolean $val set to true to print the page header (default), false otherwise. - * @public - */ - public function setPrintHeader($val=true) { - $this->print_header = $val ? true : false; - } - - /** - * Set a flag to print page footer. - * @param boolean $val set to true to print the page footer (default), false otherwise. - * @public - */ - public function setPrintFooter($val=true) { - $this->print_footer = $val ? true : false; - } - - /** - * Return the right-bottom (or left-bottom for RTL) corner X coordinate of last inserted image - * @return float - * @public - */ - public function getImageRBX() { - return $this->img_rb_x; - } - - /** - * Return the right-bottom (or left-bottom for RTL) corner Y coordinate of last inserted image - * @return float - * @public - */ - public function getImageRBY() { - return $this->img_rb_y; - } - - /** - * Reset the xobject template used by Header() method. - * @public - */ - public function resetHeaderTemplate() { - $this->header_xobjid = false; - } - - /** - * Set a flag to automatically reset the xobject template used by Header() method at each page. - * @param boolean $val set to true to reset Header xobject template at each page, false otherwise. - * @public - */ - public function setHeaderTemplateAutoreset($val=true) { - $this->header_xobj_autoreset = $val ? true : false; - } - - /** - * This method is used to render the page header. - * It is automatically called by AddPage() and could be overwritten in your own inherited class. - * @public - */ - public function Header() { - if ($this->header_xobjid === false) { - // start a new XObject Template - $this->header_xobjid = $this->startTemplate($this->w, $this->tMargin); - $headerfont = $this->getHeaderFont(); - $headerdata = $this->getHeaderData(); - $this->y = $this->header_margin; - if ($this->rtl) { - $this->x = $this->w - $this->original_rMargin; - } else { - $this->x = $this->original_lMargin; - } - if (($headerdata['logo']) AND ($headerdata['logo'] != K_BLANK_IMAGE)) { - $imgtype = TCPDF_IMAGES::getImageFileType(K_PATH_IMAGES.$headerdata['logo']); - if (($imgtype == 'eps') OR ($imgtype == 'ai')) { - $this->ImageEps(K_PATH_IMAGES.$headerdata['logo'], '', '', $headerdata['logo_width']); - } elseif ($imgtype == 'svg') { - $this->ImageSVG(K_PATH_IMAGES.$headerdata['logo'], '', '', $headerdata['logo_width']); - } else { - $this->Image(K_PATH_IMAGES.$headerdata['logo'], '', '', $headerdata['logo_width']); - } - $imgy = $this->getImageRBY(); - } else { - $imgy = $this->y; - } - $cell_height = $this->getCellHeight($headerfont[2] / $this->k); - // set starting margin for text data cell - if ($this->getRTL()) { - $header_x = $this->original_rMargin + ($headerdata['logo_width'] * 1.1); - } else { - $header_x = $this->original_lMargin + ($headerdata['logo_width'] * 1.1); - } - $cw = $this->w - $this->original_lMargin - $this->original_rMargin - ($headerdata['logo_width'] * 1.1); - $this->setTextColorArray($this->header_text_color); - // header title - $this->setFont($headerfont[0], 'B', $headerfont[2] + 1); - $this->setX($header_x); - $this->Cell($cw, $cell_height, $headerdata['title'], 0, 1, '', 0, '', 0); - // header string - $this->setFont($headerfont[0], $headerfont[1], $headerfont[2]); - $this->setX($header_x); - $this->MultiCell($cw, $cell_height, $headerdata['string'], 0, '', 0, 1, '', '', true, 0, false, true, 0, 'T', false); - // print an ending header line - $this->setLineStyle(array('width' => 0.85 / $this->k, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => $headerdata['line_color'])); - $this->setY((2.835 / $this->k) + max($imgy, $this->y)); - if ($this->rtl) { - $this->setX($this->original_rMargin); - } else { - $this->setX($this->original_lMargin); - } - $this->Cell(($this->w - $this->original_lMargin - $this->original_rMargin), 0, '', 'T', 0, 'C'); - $this->endTemplate(); - } - // print header template - $x = 0; - $dx = 0; - if (!$this->header_xobj_autoreset AND $this->booklet AND (($this->page % 2) == 0)) { - // adjust margins for booklet mode - $dx = ($this->original_lMargin - $this->original_rMargin); - } - if ($this->rtl) { - $x = $this->w + $dx; - } else { - $x = 0 + $dx; - } - $this->printTemplate($this->header_xobjid, $x, 0, 0, 0, '', '', false); - if ($this->header_xobj_autoreset) { - // reset header xobject template at each page - $this->header_xobjid = false; - } - } - - /** - * This method is used to render the page footer. - * It is automatically called by AddPage() and could be overwritten in your own inherited class. - * @public - */ - public function Footer() { - $cur_y = $this->y; - $this->setTextColorArray($this->footer_text_color); - //set style for cell border - $line_width = (0.85 / $this->k); - $this->setLineStyle(array('width' => $line_width, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => $this->footer_line_color)); - //print document barcode - $barcode = $this->getBarcode(); - if (!empty($barcode)) { - $this->Ln($line_width); - $barcode_width = round(($this->w - $this->original_lMargin - $this->original_rMargin) / 3); - $style = array( - 'position' => $this->rtl?'R':'L', - 'align' => $this->rtl?'R':'L', - 'stretch' => false, - 'fitwidth' => true, - 'cellfitalign' => '', - 'border' => false, - 'padding' => 0, - 'fgcolor' => array(0,0,0), - 'bgcolor' => false, - 'text' => false - ); - $this->write1DBarcode($barcode, 'C128', '', $cur_y + $line_width, '', (($this->footer_margin / 3) - $line_width), 0.3, $style, ''); - } - $w_page = isset($this->l['w_page']) ? $this->l['w_page'].' ' : ''; - if (empty($this->pagegroups)) { - $pagenumtxt = $w_page.$this->getAliasNumPage().' / '.$this->getAliasNbPages(); - } else { - $pagenumtxt = $w_page.$this->getPageNumGroupAlias().' / '.$this->getPageGroupAlias(); - } - $this->setY($cur_y); - //Print page number - if ($this->getRTL()) { - $this->setX($this->original_rMargin); - $this->Cell(0, 0, $pagenumtxt, 'T', 0, 'L'); - } else { - $this->setX($this->original_lMargin); - $this->Cell(0, 0, $this->getAliasRightShift().$pagenumtxt, 'T', 0, 'R'); - } - } - - /** - * This method is used to render the page header. - * @protected - * @since 4.0.012 (2008-07-24) - */ - protected function setHeader() { - if (!$this->print_header OR ($this->state != 2)) { - return; - } - $this->InHeader = true; - $this->setGraphicVars($this->default_graphic_vars); - $temp_thead = $this->thead; - $temp_theadMargins = $this->theadMargins; - $lasth = $this->lasth; - $newline = $this->newline; - $this->_outSaveGraphicsState(); - $this->rMargin = $this->original_rMargin; - $this->lMargin = $this->original_lMargin; - $this->setCellPadding(0); - //set current position - if ($this->rtl) { - $this->setXY($this->original_rMargin, $this->header_margin); - } else { - $this->setXY($this->original_lMargin, $this->header_margin); - } - $this->setFont($this->header_font[0], $this->header_font[1], $this->header_font[2]); - $this->Header(); - //restore position - if ($this->rtl) { - $this->setXY($this->original_rMargin, $this->tMargin); - } else { - $this->setXY($this->original_lMargin, $this->tMargin); - } - $this->_outRestoreGraphicsState(); - $this->lasth = $lasth; - $this->thead = $temp_thead; - $this->theadMargins = $temp_theadMargins; - $this->newline = $newline; - $this->InHeader = false; - } - - /** - * This method is used to render the page footer. - * @protected - * @since 4.0.012 (2008-07-24) - */ - protected function setFooter() { - if ($this->state != 2) { - return; - } - $this->InFooter = true; - // save current graphic settings - $gvars = $this->getGraphicVars(); - // mark this point - $this->footerpos[$this->page] = $this->pagelen[$this->page]; - $this->_out("\n"); - if ($this->print_footer) { - $this->setGraphicVars($this->default_graphic_vars); - $this->current_column = 0; - $this->num_columns = 1; - $temp_thead = $this->thead; - $temp_theadMargins = $this->theadMargins; - $lasth = $this->lasth; - $this->_outSaveGraphicsState(); - $this->rMargin = $this->original_rMargin; - $this->lMargin = $this->original_lMargin; - $this->setCellPadding(0); - //set current position - $footer_y = $this->h - $this->footer_margin; - if ($this->rtl) { - $this->setXY($this->original_rMargin, $footer_y); - } else { - $this->setXY($this->original_lMargin, $footer_y); - } - $this->setFont($this->footer_font[0], $this->footer_font[1], $this->footer_font[2]); - $this->Footer(); - //restore position - if ($this->rtl) { - $this->setXY($this->original_rMargin, $this->tMargin); - } else { - $this->setXY($this->original_lMargin, $this->tMargin); - } - $this->_outRestoreGraphicsState(); - $this->lasth = $lasth; - $this->thead = $temp_thead; - $this->theadMargins = $temp_theadMargins; - } - // restore graphic settings - $this->setGraphicVars($gvars); - $this->current_column = $gvars['current_column']; - $this->num_columns = $gvars['num_columns']; - // calculate footer length - $this->footerlen[$this->page] = $this->pagelen[$this->page] - $this->footerpos[$this->page] + 1; - $this->InFooter = false; - } - - /** - * Check if we are on the page body (excluding page header and footer). - * @return bool true if we are not in page header nor in page footer, false otherwise. - * @protected - * @since 5.9.091 (2011-06-15) - */ - protected function inPageBody() { - return (($this->InHeader === false) AND ($this->InFooter === false)); - } - - /** - * This method is used to render the table header on new page (if any). - * @protected - * @since 4.5.030 (2009-03-25) - */ - protected function setTableHeader() { - if ($this->num_columns > 1) { - // multi column mode - return; - } - if (isset($this->theadMargins['top'])) { - // restore the original top-margin - $this->tMargin = $this->theadMargins['top']; - $this->pagedim[$this->page]['tm'] = $this->tMargin; - $this->y = $this->tMargin; - } - if (!TCPDF_STATIC::empty_string($this->thead) AND (!$this->inthead)) { - // set margins - $prev_lMargin = $this->lMargin; - $prev_rMargin = $this->rMargin; - $prev_cell_padding = $this->cell_padding; - $this->lMargin = $this->theadMargins['lmargin'] + ($this->pagedim[$this->page]['olm'] - $this->pagedim[$this->theadMargins['page']]['olm']); - $this->rMargin = $this->theadMargins['rmargin'] + ($this->pagedim[$this->page]['orm'] - $this->pagedim[$this->theadMargins['page']]['orm']); - $this->cell_padding = $this->theadMargins['cell_padding']; - if ($this->rtl) { - $this->x = $this->w - $this->rMargin; - } else { - $this->x = $this->lMargin; - } - // account for special "cell" mode - if ($this->theadMargins['cell']) { - if ($this->rtl) { - $this->x -= $this->cell_padding['R']; - } else { - $this->x += $this->cell_padding['L']; - } - } - $gvars = $this->getGraphicVars(); - if (!empty($this->theadMargins['gvars'])) { - // set the correct graphic style - $this->setGraphicVars($this->theadMargins['gvars']); - $this->rMargin = $gvars['rMargin']; - $this->lMargin = $gvars['lMargin']; - } - // print table header - $this->writeHTML($this->thead, false, false, false, false, ''); - $this->setGraphicVars($gvars); - // set new top margin to skip the table headers - if (!isset($this->theadMargins['top'])) { - $this->theadMargins['top'] = $this->tMargin; - } - // store end of header position - if (!isset($this->columns[0]['th'])) { - $this->columns[0]['th'] = array(); - } - $this->columns[0]['th']['\''.$this->page.'\''] = $this->y; - $this->tMargin = $this->y; - $this->pagedim[$this->page]['tm'] = $this->tMargin; - $this->lasth = 0; - $this->lMargin = $prev_lMargin; - $this->rMargin = $prev_rMargin; - $this->cell_padding = $prev_cell_padding; - } - } - - /** - * Returns the current page number. - * @return int page number - * @public - * @since 1.0 - * @see getAliasNbPages() - */ - public function PageNo() { - return $this->page; - } - - /** - * Returns the array of spot colors. - * @return array Spot colors array. - * @public - * @since 6.0.038 (2013-09-30) - */ - public function getAllSpotColors() { - return $this->spot_colors; - } - - /** - * Defines a new spot color. - * It can be expressed in RGB components or gray scale. - * The method can be called before the first page is created and the value is retained from page to page. - * @param string $name Full name of the spot color. - * @param float $c Cyan color for CMYK. Value between 0 and 100. - * @param float $m Magenta color for CMYK. Value between 0 and 100. - * @param float $y Yellow color for CMYK. Value between 0 and 100. - * @param float $k Key (Black) color for CMYK. Value between 0 and 100. - * @public - * @since 4.0.024 (2008-09-12) - * @see SetDrawSpotColor(), SetFillSpotColor(), SetTextSpotColor() - */ - public function AddSpotColor($name, $c, $m, $y, $k) { - if (!isset($this->spot_colors[$name])) { - $i = (1 + count($this->spot_colors)); - $this->spot_colors[$name] = array('C' => $c, 'M' => $m, 'Y' => $y, 'K' => $k, 'name' => $name, 'i' => $i); - } - } - - /** - * Set the spot color for the specified type ('draw', 'fill', 'text'). - * @param string $type Type of object affected by this color: ('draw', 'fill', 'text'). - * @param string $name Name of the spot color. - * @param float $tint Intensity of the color (from 0 to 100 ; 100 = full intensity by default). - * @return string PDF color command. - * @public - * @since 5.9.125 (2011-10-03) - */ - public function setSpotColor($type, $name, $tint=100) { - $spotcolor = TCPDF_COLORS::getSpotColor($name, $this->spot_colors); - if ($spotcolor === false) { - $this->Error('Undefined spot color: '.$name.', you must add it using the AddSpotColor() method.'); - } - $tint = (max(0, min(100, $tint)) / 100); - $pdfcolor = sprintf('/CS%d ', $this->spot_colors[$name]['i']); - switch ($type) { - case 'draw': { - $pdfcolor .= sprintf('CS %F SCN', $tint); - $this->DrawColor = $pdfcolor; - $this->strokecolor = $spotcolor; - break; - } - case 'fill': { - $pdfcolor .= sprintf('cs %F scn', $tint); - $this->FillColor = $pdfcolor; - $this->bgcolor = $spotcolor; - break; - } - case 'text': { - $pdfcolor .= sprintf('cs %F scn', $tint); - $this->TextColor = $pdfcolor; - $this->fgcolor = $spotcolor; - break; - } - } - $this->ColorFlag = ($this->FillColor != $this->TextColor); - if ($this->state == 2) { - $this->_out($pdfcolor); - } - if ($this->inxobj) { - // we are inside an XObject template - $this->xobjects[$this->xobjid]['spot_colors'][$name] = $this->spot_colors[$name]; - } - return $pdfcolor; - } - - /** - * Defines the spot color used for all drawing operations (lines, rectangles and cell borders). - * @param string $name Name of the spot color. - * @param float $tint Intensity of the color (from 0 to 100 ; 100 = full intensity by default). - * @public - * @since 4.0.024 (2008-09-12) - * @see AddSpotColor(), SetFillSpotColor(), SetTextSpotColor() - */ - public function setDrawSpotColor($name, $tint=100) { - $this->setSpotColor('draw', $name, $tint); - } - - /** - * Defines the spot color used for all filling operations (filled rectangles and cell backgrounds). - * @param string $name Name of the spot color. - * @param float $tint Intensity of the color (from 0 to 100 ; 100 = full intensity by default). - * @public - * @since 4.0.024 (2008-09-12) - * @see AddSpotColor(), SetDrawSpotColor(), SetTextSpotColor() - */ - public function setFillSpotColor($name, $tint=100) { - $this->setSpotColor('fill', $name, $tint); - } - - /** - * Defines the spot color used for text. - * @param string $name Name of the spot color. - * @param int $tint Intensity of the color (from 0 to 100 ; 100 = full intensity by default). - * @public - * @since 4.0.024 (2008-09-12) - * @see AddSpotColor(), SetDrawSpotColor(), SetFillSpotColor() - */ - public function setTextSpotColor($name, $tint=100) { - $this->setSpotColor('text', $name, $tint); - } - - /** - * Set the color array for the specified type ('draw', 'fill', 'text'). - * It can be expressed in RGB, CMYK or GRAY SCALE components. - * The method can be called before the first page is created and the value is retained from page to page. - * @param string $type Type of object affected by this color: ('draw', 'fill', 'text'). - * @param array $color Array of colors (1=gray, 3=RGB, 4=CMYK or 5=spotcolor=CMYK+name values). - * @param boolean $ret If true do not send the PDF command. - * @return string The PDF command or empty string. - * @public - * @since 3.1.000 (2008-06-11) - */ - public function setColorArray($type, $color, $ret=false) { - if (is_array($color)) { - $color = array_values($color); - // component: grey, RGB red or CMYK cyan - $c = isset($color[0]) ? $color[0] : -1; - // component: RGB green or CMYK magenta - $m = isset($color[1]) ? $color[1] : -1; - // component: RGB blue or CMYK yellow - $y = isset($color[2]) ? $color[2] : -1; - // component: CMYK black - $k = isset($color[3]) ? $color[3] : -1; - // color name - $name = isset($color[4]) ? $color[4] : ''; - if ($c >= 0) { - return $this->setColor($type, $c, $m, $y, $k, $ret, $name); - } - } - return ''; - } - - /** - * Defines the color used for all drawing operations (lines, rectangles and cell borders). - * It can be expressed in RGB, CMYK or GRAY SCALE components. - * The method can be called before the first page is created and the value is retained from page to page. - * @param array $color Array of colors (1, 3 or 4 values). - * @param boolean $ret If true do not send the PDF command. - * @return string the PDF command - * @public - * @since 3.1.000 (2008-06-11) - * @see SetDrawColor() - */ - public function setDrawColorArray($color, $ret=false) { - return $this->setColorArray('draw', $color, $ret); - } - - /** - * Defines the color used for all filling operations (filled rectangles and cell backgrounds). - * It can be expressed in RGB, CMYK or GRAY SCALE components. - * The method can be called before the first page is created and the value is retained from page to page. - * @param array $color Array of colors (1, 3 or 4 values). - * @param boolean $ret If true do not send the PDF command. - * @public - * @since 3.1.000 (2008-6-11) - * @see SetFillColor() - */ - public function setFillColorArray($color, $ret=false) { - return $this->setColorArray('fill', $color, $ret); - } - - /** - * Defines the color used for text. It can be expressed in RGB components or gray scale. - * The method can be called before the first page is created and the value is retained from page to page. - * @param array $color Array of colors (1, 3 or 4 values). - * @param boolean $ret If true do not send the PDF command. - * @public - * @since 3.1.000 (2008-6-11) - * @see SetFillColor() - */ - public function setTextColorArray($color, $ret=false) { - return $this->setColorArray('text', $color, $ret); - } - - /** - * Defines the color used by the specified type ('draw', 'fill', 'text'). - * @param string $type Type of object affected by this color: ('draw', 'fill', 'text'). - * @param float $col1 GRAY level for single color, or Red color for RGB (0-255), or CYAN color for CMYK (0-100). - * @param float $col2 GREEN color for RGB (0-255), or MAGENTA color for CMYK (0-100). - * @param float $col3 BLUE color for RGB (0-255), or YELLOW color for CMYK (0-100). - * @param float $col4 KEY (BLACK) color for CMYK (0-100). - * @param boolean $ret If true do not send the command. - * @param string $name spot color name (if any) - * @return string The PDF command or empty string. - * @public - * @since 5.9.125 (2011-10-03) - */ - public function setColor($type, $col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') { - // set default values - if (!is_numeric($col1)) { - $col1 = 0; - } - if (!is_numeric($col2)) { - $col2 = -1; - } - if (!is_numeric($col3)) { - $col3 = -1; - } - if (!is_numeric($col4)) { - $col4 = -1; - } - // set color by case - $suffix = ''; - if (($col2 == -1) AND ($col3 == -1) AND ($col4 == -1)) { - // Grey scale - $col1 = max(0, min(255, $col1)); - $intcolor = array('G' => $col1); - $pdfcolor = sprintf('%F ', ($col1 / 255)); - $suffix = 'g'; - } elseif ($col4 == -1) { - // RGB - $col1 = max(0, min(255, $col1)); - $col2 = max(0, min(255, $col2)); - $col3 = max(0, min(255, $col3)); - $intcolor = array('R' => $col1, 'G' => $col2, 'B' => $col3); - $pdfcolor = sprintf('%F %F %F ', ($col1 / 255), ($col2 / 255), ($col3 / 255)); - $suffix = 'rg'; - } else { - $col1 = max(0, min(100, $col1)); - $col2 = max(0, min(100, $col2)); - $col3 = max(0, min(100, $col3)); - $col4 = max(0, min(100, $col4)); - if (empty($name)) { - // CMYK - $intcolor = array('C' => $col1, 'M' => $col2, 'Y' => $col3, 'K' => $col4); - $pdfcolor = sprintf('%F %F %F %F ', ($col1 / 100), ($col2 / 100), ($col3 / 100), ($col4 / 100)); - $suffix = 'k'; - } else { - // SPOT COLOR - $intcolor = array('C' => $col1, 'M' => $col2, 'Y' => $col3, 'K' => $col4, 'name' => $name); - $this->AddSpotColor($name, $col1, $col2, $col3, $col4); - $pdfcolor = $this->setSpotColor($type, $name, 100); - } - } - switch ($type) { - case 'draw': { - $pdfcolor .= strtoupper($suffix); - $this->DrawColor = $pdfcolor; - $this->strokecolor = $intcolor; - break; - } - case 'fill': { - $pdfcolor .= $suffix; - $this->FillColor = $pdfcolor; - $this->bgcolor = $intcolor; - break; - } - case 'text': { - $pdfcolor .= $suffix; - $this->TextColor = $pdfcolor; - $this->fgcolor = $intcolor; - break; - } - } - $this->ColorFlag = ($this->FillColor != $this->TextColor); - if (($type != 'text') AND ($this->state == 2) AND $type !== 0) { - if (!$ret) { - $this->_out($pdfcolor); - } - return $pdfcolor; - } - return ''; - } - - /** - * Defines the color used for all drawing operations (lines, rectangles and cell borders). It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page. - * @param float $col1 GRAY level for single color, or Red color for RGB (0-255), or CYAN color for CMYK (0-100). - * @param float $col2 GREEN color for RGB (0-255), or MAGENTA color for CMYK (0-100). - * @param float $col3 BLUE color for RGB (0-255), or YELLOW color for CMYK (0-100). - * @param float $col4 KEY (BLACK) color for CMYK (0-100). - * @param boolean $ret If true do not send the command. - * @param string $name spot color name (if any) - * @return string the PDF command - * @public - * @since 1.3 - * @see SetDrawColorArray(), SetFillColor(), SetTextColor(), Line(), Rect(), Cell(), MultiCell() - */ - public function setDrawColor($col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') { - return $this->setColor('draw', $col1, $col2, $col3, $col4, $ret, $name); - } - - /** - * Defines the color used for all filling operations (filled rectangles and cell backgrounds). It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page. - * @param float $col1 GRAY level for single color, or Red color for RGB (0-255), or CYAN color for CMYK (0-100). - * @param float $col2 GREEN color for RGB (0-255), or MAGENTA color for CMYK (0-100). - * @param float $col3 BLUE color for RGB (0-255), or YELLOW color for CMYK (0-100). - * @param float $col4 KEY (BLACK) color for CMYK (0-100). - * @param boolean $ret If true do not send the command. - * @param string $name Spot color name (if any). - * @return string The PDF command. - * @public - * @since 1.3 - * @see SetFillColorArray(), SetDrawColor(), SetTextColor(), Rect(), Cell(), MultiCell() - */ - public function setFillColor($col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') { - return $this->setColor('fill', $col1, $col2, $col3, $col4, $ret, $name); - } - - /** - * Defines the color used for text. It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page. - * @param float $col1 GRAY level for single color, or Red color for RGB (0-255), or CYAN color for CMYK (0-100). - * @param float $col2 GREEN color for RGB (0-255), or MAGENTA color for CMYK (0-100). - * @param float $col3 BLUE color for RGB (0-255), or YELLOW color for CMYK (0-100). - * @param float $col4 KEY (BLACK) color for CMYK (0-100). - * @param boolean $ret If true do not send the command. - * @param string $name Spot color name (if any). - * @return string Empty string. - * @public - * @since 1.3 - * @see SetTextColorArray(), SetDrawColor(), SetFillColor(), Text(), Cell(), MultiCell() - */ - public function setTextColor($col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') { - return $this->setColor('text', $col1, $col2, $col3, $col4, $ret, $name); - } - - /** - * Returns the length of a string in user unit. A font must be selected.<br> - * @param string $s The string whose length is to be computed - * @param string $fontname Family font. It can be either a name defined by AddFont() or one of the standard families. It is also possible to pass an empty string, in that case, the current family is retained. - * @param string $fontstyle Font style. Possible values are (case insensitive):<ul><li>empty string: regular</li><li>B: bold</li><li>I: italic</li><li>U: underline</li><li>D: line-through</li><li>O: overline</li></ul> or any combination. The default value is regular. - * @param float $fontsize Font size in points. The default value is the current size. - * @param boolean $getarray if true returns an array of characters widths, if false returns the total length. - * @return float[]|float total string length or array of characted widths - * @author Nicola Asuni - * @public - * @since 1.2 - */ - public function GetStringWidth($s, $fontname='', $fontstyle='', $fontsize=0, $getarray=false) { - return $this->GetArrStringWidth(TCPDF_FONTS::utf8Bidi(TCPDF_FONTS::UTF8StringToArray($s, $this->isunicode, $this->CurrentFont), $s, $this->tmprtl, $this->isunicode, $this->CurrentFont), $fontname, $fontstyle, $fontsize, $getarray); - } - - /** - * Returns the string length of an array of chars in user unit or an array of characters widths. A font must be selected.<br> - * @param array $sa The array of chars whose total length is to be computed - * @param string $fontname Family font. It can be either a name defined by AddFont() or one of the standard families. It is also possible to pass an empty string, in that case, the current family is retained. - * @param string $fontstyle Font style. Possible values are (case insensitive):<ul><li>empty string: regular</li><li>B: bold</li><li>I: italic</li><li>U: underline</li><li>D: line through</li><li>O: overline</li></ul> or any combination. The default value is regular. - * @param float $fontsize Font size in points. The default value is the current size. - * @param boolean $getarray if true returns an array of characters widths, if false returns the total length. - * @return float[]|float total string length or array of characted widths - * @author Nicola Asuni - * @public - * @since 2.4.000 (2008-03-06) - */ - public function GetArrStringWidth($sa, $fontname='', $fontstyle='', $fontsize=0, $getarray=false) { - // store current values - if (!TCPDF_STATIC::empty_string($fontname)) { - $prev_FontFamily = $this->FontFamily; - $prev_FontStyle = $this->FontStyle; - $prev_FontSizePt = $this->FontSizePt; - $this->setFont($fontname, $fontstyle, $fontsize, '', 'default', false); - } - // convert UTF-8 array to Latin1 if required - if ($this->isunicode AND (!$this->isUnicodeFont())) { - $sa = TCPDF_FONTS::UTF8ArrToLatin1Arr($sa); - } - $w = 0; // total width - $wa = array(); // array of characters widths - foreach ($sa as $ck => $char) { - // character width - $cw = $this->GetCharWidth($char, isset($sa[($ck + 1)])); - $wa[] = $cw; - $w += $cw; - } - // restore previous values - if (!TCPDF_STATIC::empty_string($fontname)) { - $this->setFont($prev_FontFamily, $prev_FontStyle, $prev_FontSizePt, '', 'default', false); - } - if ($getarray) { - return $wa; - } - return $w; - } - - /** - * Returns the length of the char in user unit for the current font considering current stretching and spacing (tracking). - * @param int $char The char code whose length is to be returned - * @param boolean $notlast If false ignore the font-spacing. - * @return float char width - * @author Nicola Asuni - * @public - * @since 2.4.000 (2008-03-06) - */ - public function GetCharWidth($char, $notlast=true) { - // get raw width - $chw = $this->getRawCharWidth($char); - if (($this->font_spacing < 0) OR (($this->font_spacing > 0) AND $notlast)) { - // increase/decrease font spacing - $chw += $this->font_spacing; - } - if ($this->font_stretching != 100) { - // fixed stretching mode - $chw *= ($this->font_stretching / 100); - } - return $chw; - } - - /** - * Returns the length of the char in user unit for the current font. - * @param int $char The char code whose length is to be returned - * @return float char width - * @author Nicola Asuni - * @public - * @since 5.9.000 (2010-09-28) - */ - public function getRawCharWidth($char) { - if ($char == 173) { - // SHY character will not be printed - return (0); - } - if (isset($this->CurrentFont['cw'][intval($char)])) { - $w = $this->CurrentFont['cw'][intval($char)]; - } elseif (isset($this->CurrentFont['dw'])) { - // default width - $w = $this->CurrentFont['dw']; - } elseif (isset($this->CurrentFont['cw'][32])) { - // default width - $w = $this->CurrentFont['cw'][32]; - } else { - $w = 600; - } - return $this->getAbsFontMeasure($w); - } - - /** - * Returns the numbero of characters in a string. - * @param string $s The input string. - * @return int number of characters - * @public - * @since 2.0.0001 (2008-01-07) - */ - public function GetNumChars($s) { - if ($this->isUnicodeFont()) { - return count(TCPDF_FONTS::UTF8StringToArray($s, $this->isunicode, $this->CurrentFont)); - } - return strlen($s); - } - - /** - * Fill the list of available fonts ($this->fontlist). - * @protected - * @since 4.0.013 (2008-07-28) - */ - protected function getFontsList() { - if (($fontsdir = opendir(TCPDF_FONTS::_getfontpath())) !== false) { - while (($file = readdir($fontsdir)) !== false) { - if (substr($file, -4) == '.php') { - array_push($this->fontlist, strtolower(basename($file, '.php'))); - } - } - closedir($fontsdir); - } - } - - /** - * Imports a TrueType, Type1, core, or CID0 font and makes it available. - * It is necessary to generate a font definition file first (read /fonts/utils/README.TXT). - * The definition file (and the font file itself when embedding) must be present either in the current directory or in the one indicated by K_PATH_FONTS if the constant is defined. If it could not be found, the error "Could not include font definition file" is generated. - * @param string $family Font family. The name can be chosen arbitrarily. If it is a standard family name, it will override the corresponding font. - * @param string $style Font style. Possible values are (case insensitive):<ul><li>empty string: regular (default)</li><li>B: bold</li><li>I: italic</li><li>BI or IB: bold italic</li></ul> - * @param string $fontfile The font definition file. By default, the name is built from the family and style, in lower case with no spaces. - * @return array|false array containing the font data, or false in case of error. - * @param mixed $subset if true embedd only a subset of the font (stores only the information related to the used characters); if false embedd full font; if 'default' uses the default value set using setFontSubsetting(). This option is valid only for TrueTypeUnicode fonts. If you want to enable users to change the document, set this parameter to false. If you subset the font, the person who receives your PDF would need to have your same font in order to make changes to your PDF. The file size of the PDF would also be smaller because you are embedding only part of a font. - * @public - * @since 1.5 - * @see SetFont(), setFontSubsetting() - */ - public function AddFont($family, $style='', $fontfile='', $subset='default') { - if ($subset === 'default') { - $subset = $this->font_subsetting; - } - if ($this->pdfa_mode) { - $subset = false; - } - if (TCPDF_STATIC::empty_string($family)) { - if (!TCPDF_STATIC::empty_string($this->FontFamily)) { - $family = $this->FontFamily; - } else { - $this->Error('Empty font family'); - } - } - // move embedded styles on $style - if (substr($family, -1) == 'I') { - $style .= 'I'; - $family = substr($family, 0, -1); - } - if (substr($family, -1) == 'B') { - $style .= 'B'; - $family = substr($family, 0, -1); - } - // normalize family name - $family = strtolower($family); - if ((!$this->isunicode) AND ($family == 'arial')) { - $family = 'helvetica'; - } - if (($family == 'symbol') OR ($family == 'zapfdingbats')) { - $style = ''; - } - if ($this->pdfa_mode AND (isset($this->CoreFonts[$family]))) { - // all fonts must be embedded - $family = 'pdfa'.$family; - } - $tempstyle = strtoupper($style); - $style = ''; - // underline - if (strpos($tempstyle, 'U') !== false) { - $this->underline = true; - } else { - $this->underline = false; - } - // line-through (deleted) - if (strpos($tempstyle, 'D') !== false) { - $this->linethrough = true; - } else { - $this->linethrough = false; - } - // overline - if (strpos($tempstyle, 'O') !== false) { - $this->overline = true; - } else { - $this->overline = false; - } - // bold - if (strpos($tempstyle, 'B') !== false) { - $style .= 'B'; - } - // oblique - if (strpos($tempstyle, 'I') !== false) { - $style .= 'I'; - } - $bistyle = $style; - $fontkey = $family.$style; - $font_style = $style.($this->underline ? 'U' : '').($this->linethrough ? 'D' : '').($this->overline ? 'O' : ''); - $fontdata = array('fontkey' => $fontkey, 'family' => $family, 'style' => $font_style); - // check if the font has been already added - $fb = $this->getFontBuffer($fontkey); - if ($fb !== false) { - if ($this->inxobj) { - // we are inside an XObject template - $this->xobjects[$this->xobjid]['fonts'][$fontkey] = $fb['i']; - } - return $fontdata; - } - // get specified font directory (if any) - $fontdir = false; - if (!TCPDF_STATIC::empty_string($fontfile)) { - $fontdir = dirname($fontfile); - if (TCPDF_STATIC::empty_string($fontdir) OR ($fontdir == '.')) { - $fontdir = ''; - } else { - $fontdir .= '/'; - } - } - // true when the font style variation is missing - $missing_style = false; - // search and include font file - if (TCPDF_STATIC::empty_string($fontfile) OR (!@TCPDF_STATIC::file_exists($fontfile))) { - // build a standard filenames for specified font - $tmp_fontfile = str_replace(' ', '', $family).strtolower($style).'.php'; - $fontfile = TCPDF_FONTS::getFontFullPath($tmp_fontfile, $fontdir); - if (TCPDF_STATIC::empty_string($fontfile)) { - $missing_style = true; - // try to remove the style part - $tmp_fontfile = str_replace(' ', '', $family).'.php'; - $fontfile = TCPDF_FONTS::getFontFullPath($tmp_fontfile, $fontdir); - } - } - // include font file - if (!TCPDF_STATIC::empty_string($fontfile) AND (@TCPDF_STATIC::file_exists($fontfile))) { - include($fontfile); - } else { - $this->Error('Could not include font definition file: '.$family.''); - } - // check font parameters - if ((!isset($type)) OR (!isset($cw))) { - $this->Error('The font definition file has a bad format: '.$fontfile.''); - } - // SET default parameters - if (!isset($file) OR TCPDF_STATIC::empty_string($file)) { - $file = ''; - } - if (!isset($enc) OR TCPDF_STATIC::empty_string($enc)) { - $enc = ''; - } - if (!isset($cidinfo) OR TCPDF_STATIC::empty_string($cidinfo)) { - $cidinfo = array('Registry'=>'Adobe', 'Ordering'=>'Identity', 'Supplement'=>0); - $cidinfo['uni2cid'] = array(); - } - if (!isset($ctg) OR TCPDF_STATIC::empty_string($ctg)) { - $ctg = ''; - } - if (!isset($desc) OR TCPDF_STATIC::empty_string($desc)) { - $desc = array(); - } - if (!isset($up) OR TCPDF_STATIC::empty_string($up)) { - $up = -100; - } - if (!isset($ut) OR TCPDF_STATIC::empty_string($ut)) { - $ut = 50; - } - if (!isset($cw) OR TCPDF_STATIC::empty_string($cw)) { - $cw = array(); - } - if (!isset($dw) OR TCPDF_STATIC::empty_string($dw)) { - // set default width - if (isset($desc['MissingWidth']) AND ($desc['MissingWidth'] > 0)) { - $dw = $desc['MissingWidth']; - } elseif (isset($cw[32])) { - $dw = $cw[32]; - } else { - $dw = 600; - } - } - ++$this->numfonts; - if ($type == 'core') { - $name = $this->CoreFonts[$fontkey]; - $subset = false; - } elseif (($type == 'TrueType') OR ($type == 'Type1')) { - $subset = false; - } elseif ($type == 'TrueTypeUnicode') { - $enc = 'Identity-H'; - } elseif ($type == 'cidfont0') { - if ($this->pdfa_mode) { - $this->Error('All fonts must be embedded in PDF/A mode!'); - } - } else { - $this->Error('Unknow font type: '.$type.''); - } - // set name if unset - if (!isset($name) OR empty($name)) { - $name = $fontkey; - } - // create artificial font style variations if missing (only works with non-embedded fonts) - if (($type != 'core') AND $missing_style) { - // style variations - $styles = array('' => '', 'B' => ',Bold', 'I' => ',Italic', 'BI' => ',BoldItalic'); - $name .= $styles[$bistyle]; - // artificial bold - if (strpos($bistyle, 'B') !== false) { - if (isset($desc['StemV'])) { - // from normal to bold - $desc['StemV'] = round($desc['StemV'] * 1.75); - } else { - // bold - $desc['StemV'] = 123; - } - } - // artificial italic - if (strpos($bistyle, 'I') !== false) { - if (isset($desc['ItalicAngle'])) { - $desc['ItalicAngle'] -= 11; - } else { - $desc['ItalicAngle'] = -11; - } - if (isset($desc['Flags'])) { - $desc['Flags'] |= 64; //bit 7 - } else { - $desc['Flags'] = 64; - } - } - } - // check if the array of characters bounding boxes is defined - if (!isset($cbbox)) { - $cbbox = array(); - } - // initialize subsetchars - $subsetchars = array_fill(0, 255, true); - $this->setFontBuffer($fontkey, array('fontkey' => $fontkey, 'i' => $this->numfonts, 'type' => $type, 'name' => $name, 'desc' => $desc, 'up' => $up, 'ut' => $ut, 'cw' => $cw, 'cbbox' => $cbbox, 'dw' => $dw, 'enc' => $enc, 'cidinfo' => $cidinfo, 'file' => $file, 'ctg' => $ctg, 'subset' => $subset, 'subsetchars' => $subsetchars)); - if ($this->inxobj) { - // we are inside an XObject template - $this->xobjects[$this->xobjid]['fonts'][$fontkey] = $this->numfonts; - } - if (isset($diff) AND (!empty($diff))) { - //Search existing encodings - $d = 0; - $nb = count($this->diffs); - for ($i=1; $i <= $nb; ++$i) { - if ($this->diffs[$i] == $diff) { - $d = $i; - break; - } - } - if ($d == 0) { - $d = $nb + 1; - $this->diffs[$d] = $diff; - } - $this->setFontSubBuffer($fontkey, 'diff', $d); - } - if (!TCPDF_STATIC::empty_string($file)) { - if (!isset($this->FontFiles[$file])) { - if ((strcasecmp($type,'TrueType') == 0) OR (strcasecmp($type, 'TrueTypeUnicode') == 0)) { - $this->FontFiles[$file] = array('length1' => $originalsize, 'fontdir' => $fontdir, 'subset' => $subset, 'fontkeys' => array($fontkey)); - } elseif ($type != 'core') { - $this->FontFiles[$file] = array('length1' => $size1, 'length2' => $size2, 'fontdir' => $fontdir, 'subset' => $subset, 'fontkeys' => array($fontkey)); - } - } else { - // update fontkeys that are sharing this font file - $this->FontFiles[$file]['subset'] = ($this->FontFiles[$file]['subset'] AND $subset); - if (!in_array($fontkey, $this->FontFiles[$file]['fontkeys'])) { - $this->FontFiles[$file]['fontkeys'][] = $fontkey; - } - } - } - return $fontdata; - } - - /** - * Sets the font used to print character strings. - * The font can be either a standard one or a font added via the AddFont() method. Standard fonts use Windows encoding cp1252 (Western Europe). - * The method can be called before the first page is created and the font is retained from page to page. - * If you just wish to change the current font size, it is simpler to call SetFontSize(). - * Note: for the standard fonts, the font metric files must be accessible. There are three possibilities for this:<ul><li>They are in the current directory (the one where the running script lies)</li><li>They are in one of the directories defined by the include_path parameter</li><li>They are in the directory defined by the K_PATH_FONTS constant</li></ul><br /> - * @param string $family Family font. It can be either a name defined by AddFont() or one of the standard Type1 families (case insensitive):<ul><li>times (Times-Roman)</li><li>timesb (Times-Bold)</li><li>timesi (Times-Italic)</li><li>timesbi (Times-BoldItalic)</li><li>helvetica (Helvetica)</li><li>helveticab (Helvetica-Bold)</li><li>helveticai (Helvetica-Oblique)</li><li>helveticabi (Helvetica-BoldOblique)</li><li>courier (Courier)</li><li>courierb (Courier-Bold)</li><li>courieri (Courier-Oblique)</li><li>courierbi (Courier-BoldOblique)</li><li>symbol (Symbol)</li><li>zapfdingbats (ZapfDingbats)</li></ul> It is also possible to pass an empty string. In that case, the current family is retained. - * @param string $style Font style. Possible values are (case insensitive):<ul><li>empty string: regular</li><li>B: bold</li><li>I: italic</li><li>U: underline</li><li>D: line through</li><li>O: overline</li></ul> or any combination. The default value is regular. Bold and italic styles do not apply to Symbol and ZapfDingbats basic fonts or other fonts when not defined. - * @param float|null $size Font size in points. The default value is the current size. If no size has been specified since the beginning of the document, the value taken is 12 - * @param string $fontfile The font definition file. By default, the name is built from the family and style, in lower case with no spaces. - * @param mixed $subset if true embedd only a subset of the font (stores only the information related to the used characters); if false embedd full font; if 'default' uses the default value set using setFontSubsetting(). This option is valid only for TrueTypeUnicode fonts. If you want to enable users to change the document, set this parameter to false. If you subset the font, the person who receives your PDF would need to have your same font in order to make changes to your PDF. The file size of the PDF would also be smaller because you are embedding only part of a font. - * @param boolean $out if true output the font size command, otherwise only set the font properties. - * @author Nicola Asuni - * @public - * @since 1.0 - * @see AddFont(), SetFontSize() - */ - public function setFont($family, $style='', $size=null, $fontfile='', $subset='default', $out=true) { - //Select a font; size given in points - if ($size === null) { - $size = $this->FontSizePt; - } - if ($size < 0) { - $size = 0; - } - // try to add font (if not already added) - $fontdata = $this->AddFont($family, $style, $fontfile, $subset); - $this->FontFamily = $fontdata['family']; - $this->FontStyle = $fontdata['style']; - if (isset($this->CurrentFont['fontkey']) AND isset($this->CurrentFont['subsetchars'])) { - // save subset chars of the previous font - $this->setFontSubBuffer($this->CurrentFont['fontkey'], 'subsetchars', $this->CurrentFont['subsetchars']); - } - $this->CurrentFont = $this->getFontBuffer($fontdata['fontkey']); - $this->setFontSize($size, $out); - } - - /** - * Defines the size of the current font. - * @param float $size The font size in points. - * @param boolean $out if true output the font size command, otherwise only set the font properties. - * @public - * @since 1.0 - * @see SetFont() - */ - public function setFontSize($size, $out=true) { - $size = (float)$size; - // font size in points - $this->FontSizePt = $size; - // font size in user units - $this->FontSize = $size / $this->k; - // calculate some font metrics - if (isset($this->CurrentFont['desc']['FontBBox'])) { - $bbox = explode(' ', substr($this->CurrentFont['desc']['FontBBox'], 1, -1)); - $font_height = ((intval($bbox[3]) - intval($bbox[1])) * $size / 1000); - } else { - $font_height = $size * 1.219; - } - if (isset($this->CurrentFont['desc']['Ascent']) AND ($this->CurrentFont['desc']['Ascent'] > 0)) { - $font_ascent = ($this->CurrentFont['desc']['Ascent'] * $size / 1000); - } - if (isset($this->CurrentFont['desc']['Descent']) AND ($this->CurrentFont['desc']['Descent'] <= 0)) { - $font_descent = (- $this->CurrentFont['desc']['Descent'] * $size / 1000); - } - if (!isset($font_ascent) AND !isset($font_descent)) { - // core font - $font_ascent = 0.76 * $font_height; - $font_descent = $font_height - $font_ascent; - } elseif (!isset($font_descent)) { - $font_descent = $font_height - $font_ascent; - } elseif (!isset($font_ascent)) { - $font_ascent = $font_height - $font_descent; - } - $this->FontAscent = ($font_ascent / $this->k); - $this->FontDescent = ($font_descent / $this->k); - if ($out AND ($this->page > 0) AND (isset($this->CurrentFont['i'])) AND ($this->state == 2)) { - $this->_out(sprintf('BT /F%d %F Tf ET', $this->CurrentFont['i'], $this->FontSizePt)); - } - } - - /** - * Returns the bounding box of the current font in user units. - * @return array - * @public - * @since 5.9.152 (2012-03-23) - */ - public function getFontBBox() { - $fbbox = array(); - if (isset($this->CurrentFont['desc']['FontBBox'])) { - $tmpbbox = explode(' ', substr($this->CurrentFont['desc']['FontBBox'], 1, -1)); - $fbbox = array_map(array($this,'getAbsFontMeasure'), $tmpbbox); - } else { - // Find max width - if (isset($this->CurrentFont['desc']['MaxWidth'])) { - $maxw = $this->getAbsFontMeasure(intval($this->CurrentFont['desc']['MaxWidth'])); - } else { - $maxw = 0; - if (isset($this->CurrentFont['desc']['MissingWidth'])) { - $maxw = max($maxw, $this->CurrentFont['desc']['MissingWidth']); - } - if (isset($this->CurrentFont['desc']['AvgWidth'])) { - $maxw = max($maxw, $this->CurrentFont['desc']['AvgWidth']); - } - if (isset($this->CurrentFont['dw'])) { - $maxw = max($maxw, $this->CurrentFont['dw']); - } - foreach ($this->CurrentFont['cw'] as $char => $w) { - $maxw = max($maxw, $w); - } - if ($maxw == 0) { - $maxw = 600; - } - $maxw = $this->getAbsFontMeasure($maxw); - } - $fbbox = array(0, (0 - $this->FontDescent), $maxw, $this->FontAscent); - } - return $fbbox; - } - - /** - * Convert a relative font measure into absolute value. - * @param int $s Font measure. - * @return float Absolute measure. - * @since 5.9.186 (2012-09-13) - */ - public function getAbsFontMeasure($s) { - return ($s * $this->FontSize / 1000); - } - - /** - * Returns the glyph bounding box of the specified character in the current font in user units. - * @param int $char Input character code. - * @return false|array array(xMin, yMin, xMax, yMax) or FALSE if not defined. - * @since 5.9.186 (2012-09-13) - */ - public function getCharBBox($char) { - $c = intval($char); - if (isset($this->CurrentFont['cw'][$c])) { - // glyph is defined ... use zero width & height for glyphs without outlines - $result = array(0,0,0,0); - if (isset($this->CurrentFont['cbbox'][$c])) { - $result = $this->CurrentFont['cbbox'][$c]; - } - return array_map(array($this,'getAbsFontMeasure'), $result); - } - return false; - } - - /** - * Return the font descent value - * @param string $font font name - * @param string $style font style - * @param float $size The size (in points) - * @return int font descent - * @public - * @author Nicola Asuni - * @since 4.9.003 (2010-03-30) - */ - public function getFontDescent($font, $style='', $size=0) { - $fontdata = $this->AddFont($font, $style); - $fontinfo = $this->getFontBuffer($fontdata['fontkey']); - if (isset($fontinfo['desc']['Descent']) AND ($fontinfo['desc']['Descent'] <= 0)) { - $descent = (- $fontinfo['desc']['Descent'] * $size / 1000); - } else { - $descent = (1.219 * 0.24 * $size); - } - return ($descent / $this->k); - } - - /** - * Return the font ascent value. - * @param string $font font name - * @param string $style font style - * @param float $size The size (in points) - * @return int font ascent - * @public - * @author Nicola Asuni - * @since 4.9.003 (2010-03-30) - */ - public function getFontAscent($font, $style='', $size=0) { - $fontdata = $this->AddFont($font, $style); - $fontinfo = $this->getFontBuffer($fontdata['fontkey']); - if (isset($fontinfo['desc']['Ascent']) AND ($fontinfo['desc']['Ascent'] > 0)) { - $ascent = ($fontinfo['desc']['Ascent'] * $size / 1000); - } else { - $ascent = 1.219 * 0.76 * $size; - } - return ($ascent / $this->k); - } - - /** - * Return true in the character is present in the specified font. - * @param mixed $char Character to check (integer value or string) - * @param string $font Font name (family name). - * @param string $style Font style. - * @return bool true if the char is defined, false otherwise. - * @public - * @since 5.9.153 (2012-03-28) - */ - public function isCharDefined($char, $font='', $style='') { - if (is_string($char)) { - // get character code - $char = TCPDF_FONTS::UTF8StringToArray($char, $this->isunicode, $this->CurrentFont); - $char = $char[0]; - } - if (TCPDF_STATIC::empty_string($font)) { - if (TCPDF_STATIC::empty_string($style)) { - return (isset($this->CurrentFont['cw'][intval($char)])); - } - $font = $this->FontFamily; - } - $fontdata = $this->AddFont($font, $style); - $fontinfo = $this->getFontBuffer($fontdata['fontkey']); - return (isset($fontinfo['cw'][intval($char)])); - } - - /** - * Replace missing font characters on selected font with specified substitutions. - * @param string $text Text to process. - * @param string $font Font name (family name). - * @param string $style Font style. - * @param array $subs Array of possible character substitutions. The key is the character to check (integer value) and the value is a single intege value or an array of possible substitutes. - * @return string Processed text. - * @public - * @since 5.9.153 (2012-03-28) - */ - public function replaceMissingChars($text, $font='', $style='', $subs=array()) { - if (empty($subs)) { - return $text; - } - if (TCPDF_STATIC::empty_string($font)) { - $font = $this->FontFamily; - } - $fontdata = $this->AddFont($font, $style); - $fontinfo = $this->getFontBuffer($fontdata['fontkey']); - $uniarr = TCPDF_FONTS::UTF8StringToArray($text, $this->isunicode, $this->CurrentFont); - foreach ($uniarr as $k => $chr) { - if (!isset($fontinfo['cw'][$chr])) { - // this character is missing on the selected font - if (isset($subs[$chr])) { - // we have available substitutions - if (is_array($subs[$chr])) { - foreach($subs[$chr] as $s) { - if (isset($fontinfo['cw'][$s])) { - $uniarr[$k] = $s; - break; - } - } - } elseif (isset($fontinfo['cw'][$subs[$chr]])) { - $uniarr[$k] = $subs[$chr]; - } - } - } - } - return TCPDF_FONTS::UniArrSubString(TCPDF_FONTS::UTF8ArrayToUniArray($uniarr, $this->isunicode)); - } - - /** - * Defines the default monospaced font. - * @param string $font Font name. - * @public - * @since 4.5.025 - */ - public function setDefaultMonospacedFont($font) { - $this->default_monospaced_font = $font; - } - - /** - * Creates a new internal link and returns its identifier. An internal link is a clickable area which directs to another place within the document.<br /> - * The identifier can then be passed to Cell(), Write(), Image() or Link(). The destination is defined with SetLink(). - * @public - * @since 1.5 - * @see Cell(), Write(), Image(), Link(), SetLink() - */ - public function AddLink() { - // create a new internal link - $n = count($this->links) + 1; - $this->links[$n] = array('p' => 0, 'y' => 0, 'f' => false); - return $n; - } - - /** - * Defines the page and position a link points to. - * @param int $link The link identifier returned by AddLink() - * @param float $y Ordinate of target position; -1 indicates the current position. The default value is 0 (top of page) - * @param int|string $page Number of target page; -1 indicates the current page (default value). If you prefix a page number with the * character, then this page will not be changed when adding/deleting/moving pages. - * @public - * @since 1.5 - * @see AddLink() - */ - public function setLink($link, $y=0, $page=-1) { - $fixed = false; - if (!empty($page) AND (substr($page, 0, 1) == '*')) { - $page = intval(substr($page, 1)); - // this page number will not be changed when moving/add/deleting pages - $fixed = true; - } - if ($page < 0) { - $page = $this->page; - } - if ($y == -1) { - $y = $this->y; - } - $this->links[$link] = array('p' => $page, 'y' => $y, 'f' => $fixed); - } - - /** - * Puts a link on a rectangular area of the page. - * Text or image links are generally put via Cell(), Write() or Image(), but this method can be useful for instance to define a clickable area inside an image. - * @param float $x Abscissa of the upper-left corner of the rectangle - * @param float $y Ordinate of the upper-left corner of the rectangle - * @param float $w Width of the rectangle - * @param float $h Height of the rectangle - * @param mixed $link URL or identifier returned by AddLink() - * @param int $spaces number of spaces on the text to link - * @public - * @since 1.5 - * @see AddLink(), Annotation(), Cell(), Write(), Image() - */ - public function Link($x, $y, $w, $h, $link, $spaces=0) { - $this->Annotation($x, $y, $w, $h, $link, array('Subtype'=>'Link'), $spaces); - } - - /** - * Puts a markup annotation on a rectangular area of the page. - * !!!!THE ANNOTATION SUPPORT IS NOT YET FULLY IMPLEMENTED !!!! - * @param float $x Abscissa of the upper-left corner of the rectangle - * @param float $y Ordinate of the upper-left corner of the rectangle - * @param float $w Width of the rectangle - * @param float $h Height of the rectangle - * @param string $text annotation text or alternate content - * @param array $opt array of options (see section 8.4 of PDF reference 1.7). - * @param int $spaces number of spaces on the text to link - * @public - * @since 4.0.018 (2008-08-06) - */ - public function Annotation($x, $y, $w, $h, $text, $opt=array('Subtype'=>'Text'), $spaces=0) { - if ($this->inxobj) { - // store parameters for later use on template - $this->xobjects[$this->xobjid]['annotations'][] = array('x' => $x, 'y' => $y, 'w' => $w, 'h' => $h, 'text' => $text, 'opt' => $opt, 'spaces' => $spaces); - return; - } - if ($x === '') { - $x = $this->x; - } - if ($y === '') { - $y = $this->y; - } - // check page for no-write regions and adapt page margins if necessary - list($x, $y) = $this->checkPageRegions($h, $x, $y); - // recalculate coordinates to account for graphic transformations - if (isset($this->transfmatrix) AND !empty($this->transfmatrix)) { - for ($i=$this->transfmatrix_key; $i > 0; --$i) { - $maxid = count($this->transfmatrix[$i]) - 1; - for ($j=$maxid; $j >= 0; --$j) { - $ctm = $this->transfmatrix[$i][$j]; - if (isset($ctm['a'])) { - $x = $x * $this->k; - $y = ($this->h - $y) * $this->k; - $w = $w * $this->k; - $h = $h * $this->k; - // top left - $xt = $x; - $yt = $y; - $x1 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e']; - $y1 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f']; - // top right - $xt = $x + $w; - $yt = $y; - $x2 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e']; - $y2 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f']; - // bottom left - $xt = $x; - $yt = $y - $h; - $x3 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e']; - $y3 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f']; - // bottom right - $xt = $x + $w; - $yt = $y - $h; - $x4 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e']; - $y4 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f']; - // new coordinates (rectangle area) - $x = min($x1, $x2, $x3, $x4); - $y = max($y1, $y2, $y3, $y4); - $w = (max($x1, $x2, $x3, $x4) - $x) / $this->k; - $h = ($y - min($y1, $y2, $y3, $y4)) / $this->k; - $x = $x / $this->k; - $y = $this->h - ($y / $this->k); - } - } - } - } - if ($this->page <= 0) { - $page = 1; - } else { - $page = $this->page; - } - if (!isset($this->PageAnnots[$page])) { - $this->PageAnnots[$page] = array(); - } - $this->PageAnnots[$page][] = array('n' => ++$this->n, 'x' => $x, 'y' => $y, 'w' => $w, 'h' => $h, 'txt' => $text, 'opt' => $opt, 'numspaces' => $spaces); - if (!$this->pdfa_mode || ($this->pdfa_mode && $this->pdfa_version == 3)) { - if ((($opt['Subtype'] == 'FileAttachment') OR ($opt['Subtype'] == 'Sound')) AND (!TCPDF_STATIC::empty_string($opt['FS'])) - AND (@TCPDF_STATIC::file_exists($opt['FS']) OR TCPDF_STATIC::isValidURL($opt['FS'])) - AND (!isset($this->embeddedfiles[basename($opt['FS'])]))) { - $this->embeddedfiles[basename($opt['FS'])] = array('f' => ++$this->n, 'n' => ++$this->n, 'file' => $opt['FS']); - } - } - // Add widgets annotation's icons - if (isset($opt['mk']['i']) AND @TCPDF_STATIC::file_exists($opt['mk']['i'])) { - $this->Image($opt['mk']['i'], '', '', 10, 10, '', '', '', false, 300, '', false, false, 0, false, true); - } - if (isset($opt['mk']['ri']) AND @TCPDF_STATIC::file_exists($opt['mk']['ri'])) { - $this->Image($opt['mk']['ri'], '', '', 0, 0, '', '', '', false, 300, '', false, false, 0, false, true); - } - if (isset($opt['mk']['ix']) AND @TCPDF_STATIC::file_exists($opt['mk']['ix'])) { - $this->Image($opt['mk']['ix'], '', '', 0, 0, '', '', '', false, 300, '', false, false, 0, false, true); - } - } - - /** - * Embedd the attached files. - * @since 4.4.000 (2008-12-07) - * @protected - * @see Annotation() - */ - protected function _putEmbeddedFiles() { - if ($this->pdfa_mode && $this->pdfa_version != 3) { - // embedded files are not allowed in PDF/A mode version 1 and 2 - return; - } - reset($this->embeddedfiles); - foreach ($this->embeddedfiles as $filename => $filedata) { - $data = $this->getCachedFileContents($filedata['file']); - if ($data !== FALSE) { - $rawsize = strlen($data); - if ($rawsize > 0) { - // update name tree - $this->efnames[$filename] = $filedata['f'].' 0 R'; - // embedded file specification object - $out = $this->_getobj($filedata['f'])."\n"; - $out .= '<</Type /Filespec /F '.$this->_datastring($filename, $filedata['f']); - $out .= ' /UF '.$this->_datastring($filename, $filedata['f']); - $out .= ' /AFRelationship /Source'; - $out .= ' /EF <</F '.$filedata['n'].' 0 R>> >>'; - $out .= "\n".'endobj'; - $this->_out($out); - // embedded file object - $filter = ''; - if ($this->compress) { - $data = gzcompress($data); - $filter = ' /Filter /FlateDecode'; - } - - if ($this->pdfa_version == 3) { - $filter = ' /Subtype /text#2Fxml'; - } - - $stream = $this->_getrawstream($data, $filedata['n']); - $out = $this->_getobj($filedata['n'])."\n"; - $out .= '<< /Type /EmbeddedFile'.$filter.' /Length '.strlen($stream).' /Params <</Size '.$rawsize.'>> >>'; - $out .= ' stream'."\n".$stream."\n".'endstream'; - $out .= "\n".'endobj'; - $this->_out($out); - } - } - } - } - - /** - * Prints a text cell at the specified position. - * This method allows to place a string precisely on the page. - * @param float $x Abscissa of the cell origin - * @param float $y Ordinate of the cell origin - * @param string $txt String to print - * @param int $fstroke outline size in user units (0 = disable) - * @param boolean $fclip if true activate clipping mode (you must call StartTransform() before this function and StopTransform() to stop the clipping tranformation). - * @param boolean $ffill if true fills the text - * @param mixed $border Indicates if borders must be drawn around the cell. The value can be a number:<ul><li>0: no border (default)</li><li>1: frame</li></ul> or a string containing some or all of the following characters (in any order):<ul><li>L: left</li><li>T: top</li><li>R: right</li><li>B: bottom</li></ul> or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - * @param int $ln Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right (or left for RTL languages)</li><li>1: to the beginning of the next line</li><li>2: below</li></ul>Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0. - * @param string $align Allows to center or align the text. Possible values are:<ul><li>L or empty string: left align (default value)</li><li>C: center</li><li>R: right align</li><li>J: justify</li></ul> - * @param boolean $fill Indicates if the cell background must be painted (true) or transparent (false). - * @param mixed $link URL or identifier returned by AddLink(). - * @param int $stretch font stretch mode: <ul><li>0 = disabled</li><li>1 = horizontal scaling only if text is larger than cell width</li><li>2 = forced horizontal scaling to fit cell width</li><li>3 = character spacing only if text is larger than cell width</li><li>4 = forced character spacing to fit cell width</li></ul> General font stretching and scaling values will be preserved when possible. - * @param boolean $ignore_min_height if true ignore automatic minimum height value. - * @param string $calign cell vertical alignment relative to the specified Y value. Possible values are:<ul><li>T : cell top</li><li>A : font top</li><li>L : font baseline</li><li>D : font bottom</li><li>B : cell bottom</li></ul> - * @param string $valign text vertical alignment inside the cell. Possible values are:<ul><li>T : top</li><li>C : center</li><li>B : bottom</li></ul> - * @param boolean $rtloff if true uses the page top-left corner as origin of axis for $x and $y initial position. - * @public - * @since 1.0 - * @see Cell(), Write(), MultiCell(), WriteHTML(), WriteHTMLCell() - */ - public function Text($x, $y, $txt, $fstroke=0, $fclip=false, $ffill=true, $border=0, $ln=0, $align='', $fill=false, $link='', $stretch=0, $ignore_min_height=false, $calign='T', $valign='M', $rtloff=false) { - $textrendermode = $this->textrendermode; - $textstrokewidth = $this->textstrokewidth; - $this->setTextRenderingMode($fstroke, $ffill, $fclip); - $this->setXY($x, $y, $rtloff); - $this->Cell(0, 0, $txt, $border, $ln, $align, $fill, $link, $stretch, $ignore_min_height, $calign, $valign); - // restore previous rendering mode - $this->textrendermode = $textrendermode; - $this->textstrokewidth = $textstrokewidth; - } - - /** - * Whenever a page break condition is met, the method is called, and the break is issued or not depending on the returned value. - * The default implementation returns a value according to the mode selected by SetAutoPageBreak().<br /> - * This method is called automatically and should not be called directly by the application. - * @return bool - * @public - * @since 1.4 - * @see SetAutoPageBreak() - */ - public function AcceptPageBreak() { - if ($this->num_columns > 1) { - // multi column mode - if ($this->current_column < ($this->num_columns - 1)) { - // go to next column - $this->selectColumn($this->current_column + 1); - } elseif ($this->AutoPageBreak) { - // add a new page - $this->AddPage(); - // set first column - $this->selectColumn(0); - } - // avoid page breaking from checkPageBreak() - return false; - } - return $this->AutoPageBreak; - } - - /** - * Add page if needed. - * @param float $h Cell height. Default value: 0. - * @param float|null $y starting y position, leave empty for current position. - * @param bool $addpage if true add a page, otherwise only return the true/false state - * @return bool true in case of page break, false otherwise. - * @since 3.2.000 (2008-07-01) - * @protected - */ - protected function checkPageBreak($h=0, $y=null, $addpage=true) { - if (TCPDF_STATIC::empty_string($y)) { - $y = $this->y; - } - $current_page = $this->page; - if ((($y + $h) > $this->PageBreakTrigger) AND ($this->inPageBody()) AND ($this->AcceptPageBreak())) { - if ($addpage) { - //Automatic page break - $x = $this->x; - $this->AddPage($this->CurOrientation); - $this->y = $this->tMargin; - $oldpage = $this->page - 1; - if ($this->rtl) { - if ($this->pagedim[$this->page]['orm'] != $this->pagedim[$oldpage]['orm']) { - $this->x = $x - ($this->pagedim[$this->page]['orm'] - $this->pagedim[$oldpage]['orm']); - } else { - $this->x = $x; - } - } else { - if ($this->pagedim[$this->page]['olm'] != $this->pagedim[$oldpage]['olm']) { - $this->x = $x + ($this->pagedim[$this->page]['olm'] - $this->pagedim[$oldpage]['olm']); - } else { - $this->x = $x; - } - } - } - return true; - } - if ($current_page != $this->page) { - // account for columns mode - return true; - } - return false; - } - - /** - * Prints a cell (rectangular area) with optional borders, background color and character string. The upper-left corner of the cell corresponds to the current position. The text can be aligned or centered. After the call, the current position moves to the right or to the next line. It is possible to put a link on the text.<br /> - * If automatic page breaking is enabled and the cell goes beyond the limit, a page break is done before outputting. - * @param float $w Cell width. If 0, the cell extends up to the right margin. - * @param float $h Cell height. Default value: 0. - * @param string $txt String to print. Default value: empty string. - * @param mixed $border Indicates if borders must be drawn around the cell. The value can be a number:<ul><li>0: no border (default)</li><li>1: frame</li></ul> or a string containing some or all of the following characters (in any order):<ul><li>L: left</li><li>T: top</li><li>R: right</li><li>B: bottom</li></ul> or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - * @param int $ln Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right (or left for RTL languages)</li><li>1: to the beginning of the next line</li><li>2: below</li></ul> Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0. - * @param string $align Allows to center or align the text. Possible values are:<ul><li>L or empty string: left align (default value)</li><li>C: center</li><li>R: right align</li><li>J: justify</li></ul> - * @param boolean $fill Indicates if the cell background must be painted (true) or transparent (false). - * @param mixed $link URL or identifier returned by AddLink(). - * @param int $stretch font stretch mode: <ul><li>0 = disabled</li><li>1 = horizontal scaling only if text is larger than cell width</li><li>2 = forced horizontal scaling to fit cell width</li><li>3 = character spacing only if text is larger than cell width</li><li>4 = forced character spacing to fit cell width</li></ul> General font stretching and scaling values will be preserved when possible. - * @param boolean $ignore_min_height if true ignore automatic minimum height value. - * @param string $calign cell vertical alignment relative to the specified Y value. Possible values are:<ul><li>T : cell top</li><li>C : center</li><li>B : cell bottom</li><li>A : font top</li><li>L : font baseline</li><li>D : font bottom</li></ul> - * @param string $valign text vertical alignment inside the cell. Possible values are:<ul><li>T : top</li><li>C : center</li><li>B : bottom</li></ul> - * @public - * @since 1.0 - * @see SetFont(), SetDrawColor(), SetFillColor(), SetTextColor(), SetLineWidth(), AddLink(), Ln(), MultiCell(), Write(), SetAutoPageBreak() - */ - public function Cell($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='', $stretch=0, $ignore_min_height=false, $calign='T', $valign='M') { - $prev_cell_margin = $this->cell_margin; - $prev_cell_padding = $this->cell_padding; - $this->adjustCellPadding($border); - if (!$ignore_min_height) { - $min_cell_height = $this->getCellHeight($this->FontSize); - if ($h < $min_cell_height) { - $h = $min_cell_height; - } - } - $this->checkPageBreak($h + $this->cell_margin['T'] + $this->cell_margin['B']); - // apply text shadow if enabled - if ($this->txtshadow['enabled']) { - // save data - $x = $this->x; - $y = $this->y; - $bc = $this->bgcolor; - $fc = $this->fgcolor; - $sc = $this->strokecolor; - $alpha = $this->alpha; - // print shadow - $this->x += $this->txtshadow['depth_w']; - $this->y += $this->txtshadow['depth_h']; - $this->setFillColorArray($this->txtshadow['color']); - $this->setTextColorArray($this->txtshadow['color']); - $this->setDrawColorArray($this->txtshadow['color']); - if ($this->txtshadow['opacity'] != $alpha['CA']) { - $this->setAlpha($this->txtshadow['opacity'], $this->txtshadow['blend_mode']); - } - if ($this->state == 2) { - $this->_out($this->getCellCode($w, $h, $txt, $border, $ln, $align, $fill, $link, $stretch, true, $calign, $valign)); - } - //restore data - $this->x = $x; - $this->y = $y; - $this->setFillColorArray($bc); - $this->setTextColorArray($fc); - $this->setDrawColorArray($sc); - if ($this->txtshadow['opacity'] != $alpha['CA']) { - $this->setAlpha($alpha['CA'], $alpha['BM'], $alpha['ca'], $alpha['AIS']); - } - } - if ($this->state == 2) { - $this->_out($this->getCellCode($w, $h, $txt, $border, $ln, $align, $fill, $link, $stretch, true, $calign, $valign)); - } - $this->cell_padding = $prev_cell_padding; - $this->cell_margin = $prev_cell_margin; - } - - /** - * Returns the PDF string code to print a cell (rectangular area) with optional borders, background color and character string. The upper-left corner of the cell corresponds to the current position. The text can be aligned or centered. After the call, the current position moves to the right or to the next line. It is possible to put a link on the text.<br /> - * If automatic page breaking is enabled and the cell goes beyond the limit, a page break is done before outputting. - * @param float $w Cell width. If 0, the cell extends up to the right margin. - * @param float $h Cell height. Default value: 0. - * @param string $txt String to print. Default value: empty string. - * @param mixed $border Indicates if borders must be drawn around the cell. The value can be a number:<ul><li>0: no border (default)</li><li>1: frame</li></ul> or a string containing some or all of the following characters (in any order):<ul><li>L: left</li><li>T: top</li><li>R: right</li><li>B: bottom</li></ul> or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - * @param int $ln Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right (or left for RTL languages)</li><li>1: to the beginning of the next line</li><li>2: below</li></ul>Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0. - * @param string $align Allows to center or align the text. Possible values are:<ul><li>L or empty string: left align (default value)</li><li>C: center</li><li>R: right align</li><li>J: justify</li></ul> - * @param boolean $fill Indicates if the cell background must be painted (true) or transparent (false). - * @param mixed $link URL or identifier returned by AddLink(). - * @param int $stretch font stretch mode: <ul><li>0 = disabled</li><li>1 = horizontal scaling only if text is larger than cell width</li><li>2 = forced horizontal scaling to fit cell width</li><li>3 = character spacing only if text is larger than cell width</li><li>4 = forced character spacing to fit cell width</li></ul> General font stretching and scaling values will be preserved when possible. - * @param boolean $ignore_min_height if true ignore automatic minimum height value. - * @param string $calign cell vertical alignment relative to the specified Y value. Possible values are:<ul><li>T : cell top</li><li>C : center</li><li>B : cell bottom</li><li>A : font top</li><li>L : font baseline</li><li>D : font bottom</li></ul> - * @param string $valign text vertical alignment inside the cell. Possible values are:<ul><li>T : top</li><li>M : middle</li><li>B : bottom</li></ul> - * @return string containing cell code - * @protected - * @since 1.0 - * @see Cell() - */ - protected function getCellCode($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='', $stretch=0, $ignore_min_height=false, $calign='T', $valign='M') { - // replace 'NO-BREAK SPACE' (U+00A0) character with a simple space - $txt = str_replace(TCPDF_FONTS::unichr(160, $this->isunicode), ' ', $txt); - $prev_cell_margin = $this->cell_margin; - $prev_cell_padding = $this->cell_padding; - $txt = TCPDF_STATIC::removeSHY($txt, $this->isunicode); - $rs = ''; //string to be returned - $this->adjustCellPadding($border); - if (!$ignore_min_height) { - $min_cell_height = $this->getCellHeight($this->FontSize); - if ($h < $min_cell_height) { - $h = $min_cell_height; - } - } - $k = $this->k; - // check page for no-write regions and adapt page margins if necessary - list($this->x, $this->y) = $this->checkPageRegions($h, $this->x, $this->y); - if ($this->rtl) { - $x = $this->x - $this->cell_margin['R']; - } else { - $x = $this->x + $this->cell_margin['L']; - } - $y = $this->y + $this->cell_margin['T']; - $prev_font_stretching = $this->font_stretching; - $prev_font_spacing = $this->font_spacing; - // cell vertical alignment - switch ($calign) { - case 'A': { - // font top - switch ($valign) { - case 'T': { - // top - $y -= $this->cell_padding['T']; - break; - } - case 'B': { - // bottom - $y -= ($h - $this->cell_padding['B'] - $this->FontAscent - $this->FontDescent); - break; - } - default: - case 'C': - case 'M': { - // center - $y -= (($h - $this->FontAscent - $this->FontDescent) / 2); - break; - } - } - break; - } - case 'L': { - // font baseline - switch ($valign) { - case 'T': { - // top - $y -= ($this->cell_padding['T'] + $this->FontAscent); - break; - } - case 'B': { - // bottom - $y -= ($h - $this->cell_padding['B'] - $this->FontDescent); - break; - } - default: - case 'C': - case 'M': { - // center - $y -= (($h + $this->FontAscent - $this->FontDescent) / 2); - break; - } - } - break; - } - case 'D': { - // font bottom - switch ($valign) { - case 'T': { - // top - $y -= ($this->cell_padding['T'] + $this->FontAscent + $this->FontDescent); - break; - } - case 'B': { - // bottom - $y -= ($h - $this->cell_padding['B']); - break; - } - default: - case 'C': - case 'M': { - // center - $y -= (($h + $this->FontAscent + $this->FontDescent) / 2); - break; - } - } - break; - } - case 'B': { - // cell bottom - $y -= $h; - break; - } - case 'C': - case 'M': { - // cell center - $y -= ($h / 2); - break; - } - default: - case 'T': { - // cell top - break; - } - } - // text vertical alignment - switch ($valign) { - case 'T': { - // top - $yt = $y + $this->cell_padding['T']; - break; - } - case 'B': { - // bottom - $yt = $y + $h - $this->cell_padding['B'] - $this->FontAscent - $this->FontDescent; - break; - } - default: - case 'C': - case 'M': { - // center - $yt = $y + (($h - $this->FontAscent - $this->FontDescent) / 2); - break; - } - } - $basefonty = $yt + $this->FontAscent; - if (TCPDF_STATIC::empty_string($w) OR ($w <= 0)) { - if ($this->rtl) { - $w = $x - $this->lMargin; - } else { - $w = $this->w - $this->rMargin - $x; - } - } - $s = ''; - // fill and borders - if (is_string($border) AND (strlen($border) == 4)) { - // full border - $border = 1; - } - if ($fill OR ($border == 1)) { - if ($fill) { - $op = ($border == 1) ? 'B' : 'f'; - } else { - $op = 'S'; - } - if ($this->rtl) { - $xk = (($x - $w) * $k); - } else { - $xk = ($x * $k); - } - $s .= sprintf('%F %F %F %F re %s ', $xk, (($this->h - $y) * $k), ($w * $k), (-$h * $k), $op); - } - // draw borders - $s .= $this->getCellBorder($x, $y, $w, $h, $border); - if ($txt != '') { - $txt2 = $txt; - if ($this->isunicode) { - if (($this->CurrentFont['type'] == 'core') OR ($this->CurrentFont['type'] == 'TrueType') OR ($this->CurrentFont['type'] == 'Type1')) { - $txt2 = TCPDF_FONTS::UTF8ToLatin1($txt2, $this->isunicode, $this->CurrentFont); - } else { - $unicode = TCPDF_FONTS::UTF8StringToArray($txt, $this->isunicode, $this->CurrentFont); // array of UTF-8 unicode values - $unicode = TCPDF_FONTS::utf8Bidi($unicode, '', $this->tmprtl, $this->isunicode, $this->CurrentFont); - // replace thai chars (if any) - if (defined('K_THAI_TOPCHARS') AND (K_THAI_TOPCHARS == true)) { - // number of chars - $numchars = count($unicode); - // po pla, for far, for fan - $longtail = array(0x0e1b, 0x0e1d, 0x0e1f); - // do chada, to patak - $lowtail = array(0x0e0e, 0x0e0f); - // mai hun arkad, sara i, sara ii, sara ue, sara uee - $upvowel = array(0x0e31, 0x0e34, 0x0e35, 0x0e36, 0x0e37); - // mai ek, mai tho, mai tri, mai chattawa, karan - $tonemark = array(0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c); - // sara u, sara uu, pinthu - $lowvowel = array(0x0e38, 0x0e39, 0x0e3a); - $output = array(); - for ($i = 0; $i < $numchars; $i++) { - if (($unicode[$i] >= 0x0e00) && ($unicode[$i] <= 0x0e5b)) { - $ch0 = $unicode[$i]; - $ch1 = ($i > 0) ? $unicode[($i - 1)] : 0; - $ch2 = ($i > 1) ? $unicode[($i - 2)] : 0; - $chn = ($i < ($numchars - 1)) ? $unicode[($i + 1)] : 0; - if (in_array($ch0, $tonemark)) { - if ($chn == 0x0e33) { - // sara um - if (in_array($ch1, $longtail)) { - // tonemark at upper left - $output[] = $this->replaceChar($ch0, (0xf713 + $ch0 - 0x0e48)); - } else { - // tonemark at upper right (normal position) - $output[] = $ch0; - } - } elseif (in_array($ch1, $longtail) OR (in_array($ch2, $longtail) AND in_array($ch1, $lowvowel))) { - // tonemark at lower left - $output[] = $this->replaceChar($ch0, (0xf705 + $ch0 - 0x0e48)); - } elseif (in_array($ch1, $upvowel)) { - if (in_array($ch2, $longtail)) { - // tonemark at upper left - $output[] = $this->replaceChar($ch0, (0xf713 + $ch0 - 0x0e48)); - } else { - // tonemark at upper right (normal position) - $output[] = $ch0; - } - } else { - // tonemark at lower right - $output[] = $this->replaceChar($ch0, (0xf70a + $ch0 - 0x0e48)); - } - } elseif (($ch0 == 0x0e33) AND (in_array($ch1, $longtail) OR (in_array($ch2, $longtail) AND in_array($ch1, $tonemark)))) { - // add lower left nikhahit and sara aa - if ($this->isCharDefined(0xf711) AND $this->isCharDefined(0x0e32)) { - $output[] = 0xf711; - $this->CurrentFont['subsetchars'][0xf711] = true; - $output[] = 0x0e32; - $this->CurrentFont['subsetchars'][0x0e32] = true; - } else { - $output[] = $ch0; - } - } elseif (in_array($ch1, $longtail)) { - if ($ch0 == 0x0e31) { - // lower left mai hun arkad - $output[] = $this->replaceChar($ch0, 0xf710); - } elseif (in_array($ch0, $upvowel)) { - // lower left - $output[] = $this->replaceChar($ch0, (0xf701 + $ch0 - 0x0e34)); - } elseif ($ch0 == 0x0e47) { - // lower left mai tai koo - $output[] = $this->replaceChar($ch0, 0xf712); - } else { - // normal character - $output[] = $ch0; - } - } elseif (in_array($ch1, $lowtail) AND in_array($ch0, $lowvowel)) { - // lower vowel - $output[] = $this->replaceChar($ch0, (0xf718 + $ch0 - 0x0e38)); - } elseif (($ch0 == 0x0e0d) AND in_array($chn, $lowvowel)) { - // yo ying without lower part - $output[] = $this->replaceChar($ch0, 0xf70f); - } elseif (($ch0 == 0x0e10) AND in_array($chn, $lowvowel)) { - // tho santan without lower part - $output[] = $this->replaceChar($ch0, 0xf700); - } else { - $output[] = $ch0; - } - } else { - // non-thai character - $output[] = $unicode[$i]; - } - } - $unicode = $output; - // update font subsetchars - $this->setFontSubBuffer($this->CurrentFont['fontkey'], 'subsetchars', $this->CurrentFont['subsetchars']); - } // end of K_THAI_TOPCHARS - $txt2 = TCPDF_FONTS::arrUTF8ToUTF16BE($unicode, false); - } - } - $txt2 = TCPDF_STATIC::_escape($txt2); - // get current text width (considering general font stretching and spacing) - $txwidth = $this->GetStringWidth($txt); - $width = $txwidth; - // check for stretch mode - if ($stretch > 0) { - // calculate ratio between cell width and text width - if ($width <= 0) { - $ratio = 1; - } else { - $ratio = (($w - $this->cell_padding['L'] - $this->cell_padding['R']) / $width); - } - // check if stretching is required - if (($ratio < 1) OR (($ratio > 1) AND (($stretch % 2) == 0))) { - // the text will be stretched to fit cell width - if ($stretch > 2) { - // set new character spacing - $this->font_spacing += ($w - $this->cell_padding['L'] - $this->cell_padding['R'] - $width) / (max(($this->GetNumChars($txt) - 1), 1) * ($this->font_stretching / 100)); - } else { - // set new horizontal stretching - $this->font_stretching *= $ratio; - } - // recalculate text width (the text fills the entire cell) - $width = $w - $this->cell_padding['L'] - $this->cell_padding['R']; - // reset alignment - $align = ''; - } - } - if ($this->font_stretching != 100) { - // apply font stretching - $rs .= sprintf('BT %F Tz ET ', $this->font_stretching); - } - if ($this->font_spacing != 0) { - // increase/decrease font spacing - $rs .= sprintf('BT %F Tc ET ', ($this->font_spacing * $this->k)); - } - if ($this->ColorFlag AND ($this->textrendermode < 4)) { - $s .= 'q '.$this->TextColor.' '; - } - // rendering mode - $s .= sprintf('BT %d Tr %F w ET ', $this->textrendermode, ($this->textstrokewidth * $this->k)); - // count number of spaces - $ns = substr_count($txt, chr(32)); - // Justification - $spacewidth = 0; - if (($align == 'J') AND ($ns > 0)) { - if ($this->isUnicodeFont()) { - // get string width without spaces - $width = $this->GetStringWidth(str_replace(' ', '', $txt)); - // calculate average space width - $spacewidth = -1000 * ($w - $width - $this->cell_padding['L'] - $this->cell_padding['R']) / ($ns?$ns:1) / ($this->FontSize?$this->FontSize:1); - if ($this->font_stretching != 100) { - // word spacing is affected by stretching - $spacewidth /= ($this->font_stretching / 100); - } - // set word position to be used with TJ operator - $txt2 = str_replace(chr(0).chr(32), ') '.sprintf('%F', $spacewidth).' (', $txt2); - $unicode_justification = true; - } else { - // get string width - $width = $txwidth; - // new space width - $spacewidth = (($w - $width - $this->cell_padding['L'] - $this->cell_padding['R']) / ($ns?$ns:1)) * $this->k; - if ($this->font_stretching != 100) { - // word spacing (Tw) is affected by stretching - $spacewidth /= ($this->font_stretching / 100); - } - // set word spacing - $rs .= sprintf('BT %F Tw ET ', $spacewidth); - } - $width = $w - $this->cell_padding['L'] - $this->cell_padding['R']; - } - // replace carriage return characters - $txt2 = str_replace("\r", ' ', $txt2); - switch ($align) { - case 'C': { - $dx = ($w - $width) / 2; - break; - } - case 'R': { - if ($this->rtl) { - $dx = $this->cell_padding['R']; - } else { - $dx = $w - $width - $this->cell_padding['R']; - } - break; - } - case 'L': { - if ($this->rtl) { - $dx = $w - $width - $this->cell_padding['L']; - } else { - $dx = $this->cell_padding['L']; - } - break; - } - case 'J': - default: { - if ($this->rtl) { - $dx = $this->cell_padding['R']; - } else { - $dx = $this->cell_padding['L']; - } - break; - } - } - if ($this->rtl) { - $xdx = $x - $dx - $width; - } else { - $xdx = $x + $dx; - } - $xdk = $xdx * $k; - // print text - $s .= sprintf('BT %F %F Td [(%s)] TJ ET', $xdk, (($this->h - $basefonty) * $k), $txt2); - if (isset($uniblock)) { - // print overlapping characters as separate string - $xshift = 0; // horizontal shift - $ty = (($this->h - $basefonty + (0.2 * $this->FontSize)) * $k); - $spw = (($w - $txwidth - $this->cell_padding['L'] - $this->cell_padding['R']) / ($ns?$ns:1)); - foreach ($uniblock as $uk => $uniarr) { - if (($uk % 2) == 0) { - // x space to skip - if ($spacewidth != 0) { - // justification shift - $xshift += (count(array_keys($uniarr, 32)) * $spw); - } - $xshift += $this->GetArrStringWidth($uniarr); // + shift justification - } else { - // character to print - $topchr = TCPDF_FONTS::arrUTF8ToUTF16BE($uniarr, false); - $topchr = TCPDF_STATIC::_escape($topchr); - $s .= sprintf(' BT %F %F Td [(%s)] TJ ET', ($xdk + ($xshift * $k)), $ty, $topchr); - } - } - } - if ($this->underline) { - $s .= ' '.$this->_dounderlinew($xdx, $basefonty, $width); - } - if ($this->linethrough) { - $s .= ' '.$this->_dolinethroughw($xdx, $basefonty, $width); - } - if ($this->overline) { - $s .= ' '.$this->_dooverlinew($xdx, $basefonty, $width); - } - if ($this->ColorFlag AND ($this->textrendermode < 4)) { - $s .= ' Q'; - } - if ($link) { - $this->Link($xdx, $yt, $width, ($this->FontAscent + $this->FontDescent), $link, $ns); - } - } - // output cell - if ($s) { - // output cell - $rs .= $s; - if ($this->font_spacing != 0) { - // reset font spacing mode - $rs .= ' BT 0 Tc ET'; - } - if ($this->font_stretching != 100) { - // reset font stretching mode - $rs .= ' BT 100 Tz ET'; - } - } - // reset word spacing - if (!$this->isUnicodeFont() AND ($align == 'J')) { - $rs .= ' BT 0 Tw ET'; - } - // reset stretching and spacing - $this->font_stretching = $prev_font_stretching; - $this->font_spacing = $prev_font_spacing; - $this->lasth = $h; - if ($ln > 0) { - //Go to the beginning of the next line - $this->y = $y + $h + $this->cell_margin['B']; - if ($ln == 1) { - if ($this->rtl) { - $this->x = $this->w - $this->rMargin; - } else { - $this->x = $this->lMargin; - } - } - } else { - // go left or right by case - if ($this->rtl) { - $this->x = $x - $w - $this->cell_margin['L']; - } else { - $this->x = $x + $w + $this->cell_margin['R']; - } - } - $gstyles = ''.$this->linestyleWidth.' '.$this->linestyleCap.' '.$this->linestyleJoin.' '.$this->linestyleDash.' '.$this->DrawColor.' '.$this->FillColor."\n"; - $rs = $gstyles.$rs; - $this->cell_padding = $prev_cell_padding; - $this->cell_margin = $prev_cell_margin; - return $rs; - } - - /** - * Replace a char if is defined on the current font. - * @param int $oldchar Integer code (unicode) of the character to replace. - * @param int $newchar Integer code (unicode) of the new character. - * @return int the replaced char or the old char in case the new char i not defined - * @protected - * @since 5.9.167 (2012-06-22) - */ - protected function replaceChar($oldchar, $newchar) { - if ($this->isCharDefined($newchar)) { - // add the new char on the subset list - $this->CurrentFont['subsetchars'][$newchar] = true; - // return the new character - return $newchar; - } - // return the old char - return $oldchar; - } - - /** - * Returns the code to draw the cell border - * @param float $x X coordinate. - * @param float $y Y coordinate. - * @param float $w Cell width. - * @param float $h Cell height. - * @param string|array|int $brd Indicates if borders must be drawn around the cell. The value can be a number:<ul><li>0: no border (default)</li><li>1: frame</li></ul> or a string containing some or all of the following characters (in any order):<ul><li>L: left</li><li>T: top</li><li>R: right</li><li>B: bottom</li></ul> or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - * @return string containing cell border code - * @protected - * @see SetLineStyle() - * @since 5.7.000 (2010-08-02) - */ - protected function getCellBorder($x, $y, $w, $h, $brd) { - $s = ''; // string to be returned - if (empty($brd)) { - return $s; - } - if ($brd == 1) { - $brd = array('LRTB' => true); - } - // calculate coordinates for border - $k = $this->k; - if ($this->rtl) { - $xeL = ($x - $w) * $k; - $xeR = $x * $k; - } else { - $xeL = $x * $k; - $xeR = ($x + $w) * $k; - } - $yeL = (($this->h - ($y + $h)) * $k); - $yeT = (($this->h - $y) * $k); - $xeT = $xeL; - $xeB = $xeR; - $yeR = $yeT; - $yeB = $yeL; - if (is_string($brd)) { - // convert string to array - $slen = strlen($brd); - $newbrd = array(); - for ($i = 0; $i < $slen; ++$i) { - $newbrd[$brd[$i]] = array('cap' => 'square', 'join' => 'miter'); - } - $brd = $newbrd; - } - if (isset($brd['mode'])) { - $mode = $brd['mode']; - unset($brd['mode']); - } else { - $mode = 'normal'; - } - foreach ($brd as $border => $style) { - if (is_array($style) AND !empty($style)) { - // apply border style - $prev_style = $this->linestyleWidth.' '.$this->linestyleCap.' '.$this->linestyleJoin.' '.$this->linestyleDash.' '.$this->DrawColor.' '; - $s .= $this->setLineStyle($style, true)."\n"; - } - switch ($mode) { - case 'ext': { - $off = (($this->LineWidth / 2) * $k); - $xL = $xeL - $off; - $xR = $xeR + $off; - $yT = $yeT + $off; - $yL = $yeL - $off; - $xT = $xL; - $xB = $xR; - $yR = $yT; - $yB = $yL; - $w += $this->LineWidth; - $h += $this->LineWidth; - break; - } - case 'int': { - $off = ($this->LineWidth / 2) * $k; - $xL = $xeL + $off; - $xR = $xeR - $off; - $yT = $yeT - $off; - $yL = $yeL + $off; - $xT = $xL; - $xB = $xR; - $yR = $yT; - $yB = $yL; - $w -= $this->LineWidth; - $h -= $this->LineWidth; - break; - } - case 'normal': - default: { - $xL = $xeL; - $xT = $xeT; - $xB = $xeB; - $xR = $xeR; - $yL = $yeL; - $yT = $yeT; - $yB = $yeB; - $yR = $yeR; - break; - } - } - // draw borders by case - if (strlen($border) == 4) { - $s .= sprintf('%F %F %F %F re S ', $xT, $yT, ($w * $k), (-$h * $k)); - } elseif (strlen($border) == 3) { - if (strpos($border,'B') === false) { // LTR - $s .= sprintf('%F %F m ', $xL, $yL); - $s .= sprintf('%F %F l ', $xT, $yT); - $s .= sprintf('%F %F l ', $xR, $yR); - $s .= sprintf('%F %F l ', $xB, $yB); - $s .= 'S '; - } elseif (strpos($border,'L') === false) { // TRB - $s .= sprintf('%F %F m ', $xT, $yT); - $s .= sprintf('%F %F l ', $xR, $yR); - $s .= sprintf('%F %F l ', $xB, $yB); - $s .= sprintf('%F %F l ', $xL, $yL); - $s .= 'S '; - } elseif (strpos($border,'T') === false) { // RBL - $s .= sprintf('%F %F m ', $xR, $yR); - $s .= sprintf('%F %F l ', $xB, $yB); - $s .= sprintf('%F %F l ', $xL, $yL); - $s .= sprintf('%F %F l ', $xT, $yT); - $s .= 'S '; - } elseif (strpos($border,'R') === false) { // BLT - $s .= sprintf('%F %F m ', $xB, $yB); - $s .= sprintf('%F %F l ', $xL, $yL); - $s .= sprintf('%F %F l ', $xT, $yT); - $s .= sprintf('%F %F l ', $xR, $yR); - $s .= 'S '; - } - } elseif (strlen($border) == 2) { - if ((strpos($border,'L') !== false) AND (strpos($border,'T') !== false)) { // LT - $s .= sprintf('%F %F m ', $xL, $yL); - $s .= sprintf('%F %F l ', $xT, $yT); - $s .= sprintf('%F %F l ', $xR, $yR); - $s .= 'S '; - } elseif ((strpos($border,'T') !== false) AND (strpos($border,'R') !== false)) { // TR - $s .= sprintf('%F %F m ', $xT, $yT); - $s .= sprintf('%F %F l ', $xR, $yR); - $s .= sprintf('%F %F l ', $xB, $yB); - $s .= 'S '; - } elseif ((strpos($border,'R') !== false) AND (strpos($border,'B') !== false)) { // RB - $s .= sprintf('%F %F m ', $xR, $yR); - $s .= sprintf('%F %F l ', $xB, $yB); - $s .= sprintf('%F %F l ', $xL, $yL); - $s .= 'S '; - } elseif ((strpos($border,'B') !== false) AND (strpos($border,'L') !== false)) { // BL - $s .= sprintf('%F %F m ', $xB, $yB); - $s .= sprintf('%F %F l ', $xL, $yL); - $s .= sprintf('%F %F l ', $xT, $yT); - $s .= 'S '; - } elseif ((strpos($border,'L') !== false) AND (strpos($border,'R') !== false)) { // LR - $s .= sprintf('%F %F m ', $xL, $yL); - $s .= sprintf('%F %F l ', $xT, $yT); - $s .= 'S '; - $s .= sprintf('%F %F m ', $xR, $yR); - $s .= sprintf('%F %F l ', $xB, $yB); - $s .= 'S '; - } elseif ((strpos($border,'T') !== false) AND (strpos($border,'B') !== false)) { // TB - $s .= sprintf('%F %F m ', $xT, $yT); - $s .= sprintf('%F %F l ', $xR, $yR); - $s .= 'S '; - $s .= sprintf('%F %F m ', $xB, $yB); - $s .= sprintf('%F %F l ', $xL, $yL); - $s .= 'S '; - } - } else { // strlen($border) == 1 - if (strpos($border,'L') !== false) { // L - $s .= sprintf('%F %F m ', $xL, $yL); - $s .= sprintf('%F %F l ', $xT, $yT); - $s .= 'S '; - } elseif (strpos($border,'T') !== false) { // T - $s .= sprintf('%F %F m ', $xT, $yT); - $s .= sprintf('%F %F l ', $xR, $yR); - $s .= 'S '; - } elseif (strpos($border,'R') !== false) { // R - $s .= sprintf('%F %F m ', $xR, $yR); - $s .= sprintf('%F %F l ', $xB, $yB); - $s .= 'S '; - } elseif (strpos($border,'B') !== false) { // B - $s .= sprintf('%F %F m ', $xB, $yB); - $s .= sprintf('%F %F l ', $xL, $yL); - $s .= 'S '; - } - } - if (is_array($style) AND !empty($style)) { - // reset border style to previous value - $s .= "\n".$this->linestyleWidth.' '.$this->linestyleCap.' '.$this->linestyleJoin.' '.$this->linestyleDash.' '.$this->DrawColor."\n"; - } - } - return $s; - } - - /** - * This method allows printing text with line breaks. - * They can be automatic (as soon as the text reaches the right border of the cell) or explicit (via the \n character). As many cells as necessary are output, one below the other.<br /> - * Text can be aligned, centered or justified. The cell block can be framed and the background painted. - * @param float $w Width of cells. If 0, they extend up to the right margin of the page. - * @param float $h Cell minimum height. The cell extends automatically if needed. - * @param string $txt String to print - * @param mixed $border Indicates if borders must be drawn around the cell. The value can be a number:<ul><li>0: no border (default)</li><li>1: frame</li></ul> or a string containing some or all of the following characters (in any order):<ul><li>L: left</li><li>T: top</li><li>R: right</li><li>B: bottom</li></ul> or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - * @param string $align Allows to center or align the text. Possible values are:<ul><li>L or empty string: left align</li><li>C: center</li><li>R: right align</li><li>J: justification (default value when $ishtml=false)</li></ul> - * @param boolean $fill Indicates if the cell background must be painted (true) or transparent (false). - * @param int $ln Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right</li><li>1: to the beginning of the next line [DEFAULT]</li><li>2: below</li></ul> - * @param float|null $x x position in user units - * @param float|null $y y position in user units - * @param boolean $reseth if true reset the last cell height (default true). - * @param int $stretch font stretch mode: <ul><li>0 = disabled</li><li>1 = horizontal scaling only if text is larger than cell width</li><li>2 = forced horizontal scaling to fit cell width</li><li>3 = character spacing only if text is larger than cell width</li><li>4 = forced character spacing to fit cell width</li></ul> General font stretching and scaling values will be preserved when possible. - * @param boolean $ishtml INTERNAL USE ONLY -- set to true if $txt is HTML content (default = false). Never set this parameter to true, use instead writeHTMLCell() or writeHTML() methods. - * @param boolean $autopadding if true, uses internal padding and automatically adjust it to account for line width. - * @param float $maxh maximum height. It should be >= $h and less then remaining space to the bottom of the page, or 0 for disable this feature. This feature works only when $ishtml=false. - * @param string $valign Vertical alignment of text (requires $maxh = $h > 0). Possible values are:<ul><li>T: TOP</li><li>M: middle</li><li>B: bottom</li></ul>. This feature works only when $ishtml=false and the cell must fit in a single page. - * @param boolean $fitcell if true attempt to fit all the text within the cell by reducing the font size (do not work in HTML mode). $maxh must be greater than 0 and equal to $h. - * @return int Return the number of cells or 1 for html mode. - * @public - * @since 1.3 - * @see SetFont(), SetDrawColor(), SetFillColor(), SetTextColor(), SetLineWidth(), Cell(), Write(), SetAutoPageBreak() - */ - public function MultiCell($w, $h, $txt, $border=0, $align='J', $fill=false, $ln=1, $x=null, $y=null, $reseth=true, $stretch=0, $ishtml=false, $autopadding=true, $maxh=0, $valign='T', $fitcell=false) { - $prev_cell_margin = $this->cell_margin; - $prev_cell_padding = $this->cell_padding; - // adjust internal padding - $this->adjustCellPadding($border); - $mc_padding = $this->cell_padding; - $mc_margin = $this->cell_margin; - $this->cell_padding['T'] = 0; - $this->cell_padding['B'] = 0; - $this->setCellMargins(0, 0, 0, 0); - if (TCPDF_STATIC::empty_string($this->lasth) OR $reseth) { - // reset row height - $this->resetLastH(); - } - if (!TCPDF_STATIC::empty_string($y)) { - $this->setY($y); // set y in order to convert negative y values to positive ones - } - $y = $this->GetY(); - $resth = 0; - if (($h > 0) AND $this->inPageBody() AND (($y + $h + $mc_margin['T'] + $mc_margin['B']) > $this->PageBreakTrigger)) { - // spit cell in more pages/columns - $newh = ($this->PageBreakTrigger - $y); - $resth = ($h - $newh); // cell to be printed on the next page/column - $h = $newh; - } - // get current page number - $startpage = $this->page; - // get current column - $startcolumn = $this->current_column; - if (!TCPDF_STATIC::empty_string($x)) { - $this->setX($x); - } else { - $x = $this->GetX(); - } - // check page for no-write regions and adapt page margins if necessary - list($x, $y) = $this->checkPageRegions(0, $x, $y); - // apply margins - $oy = $y + $mc_margin['T']; - if ($this->rtl) { - $ox = ($this->w - $x - $mc_margin['R']); - } else { - $ox = ($x + $mc_margin['L']); - } - $this->x = $ox; - $this->y = $oy; - // set width - if (TCPDF_STATIC::empty_string($w) OR ($w <= 0)) { - if ($this->rtl) { - $w = ($this->x - $this->lMargin - $mc_margin['L']); - } else { - $w = ($this->w - $this->x - $this->rMargin - $mc_margin['R']); - } - } - // store original margin values - $lMargin = $this->lMargin; - $rMargin = $this->rMargin; - if ($this->rtl) { - $this->rMargin = ($this->w - $this->x); - $this->lMargin = ($this->x - $w); - } else { - $this->lMargin = ($this->x); - $this->rMargin = ($this->w - $this->x - $w); - } - $this->clMargin = $this->lMargin; - $this->crMargin = $this->rMargin; - if ($autopadding) { - // add top padding - $this->y += $mc_padding['T']; - } - if ($ishtml) { // ******* Write HTML text - $this->writeHTML($txt, true, false, $reseth, true, $align); - $nl = 1; - } else { // ******* Write simple text - $prev_FontSizePt = $this->FontSizePt; - if ($fitcell) { - // ajust height values - $tobottom = ($this->h - $this->y - $this->bMargin - $this->cell_padding['T'] - $this->cell_padding['B']); - $h = $maxh = max(min($h, $tobottom), min($maxh, $tobottom)); - } - // vertical alignment - if ($maxh > 0) { - // get text height - $text_height = $this->getStringHeight($w, $txt, $reseth, $autopadding, $mc_padding, $border); - if ($fitcell AND ($text_height > $maxh) AND ($this->FontSizePt > 1)) { - // try to reduce font size to fit text on cell (use a quick search algorithm) - $fmin = 1; - $fmax = $this->FontSizePt; - $diff_epsilon = (1 / $this->k); // one point (min resolution) - $maxit = (2 * min(100, max(10, intval($fmax)))); // max number of iterations - while ($maxit >= 0) { - $fmid = (($fmax + $fmin) / 2); - $this->setFontSize($fmid, false); - $this->resetLastH(); - $text_height = $this->getStringHeight($w, $txt, $reseth, $autopadding, $mc_padding, $border); - $diff = ($maxh - $text_height); - if ($diff >= 0) { - if ($diff <= $diff_epsilon) { - break; - } - $fmin = $fmid; - } else { - $fmax = $fmid; - } - --$maxit; - } - if ($maxit < 0) { - // premature exit, we get the minimum font value to fit the cell - $this->setFontSize($fmin); - $this->resetLastH(); - $text_height = $this->getStringHeight($w, $txt, $reseth, $autopadding, $mc_padding, $border); - } else { - $this->setFontSize($fmid); - $this->resetLastH(); - } - } - if ($text_height < $maxh) { - if ($valign == 'M') { - // text vertically centered - $this->y += (($maxh - $text_height) / 2); - } elseif ($valign == 'B') { - // text vertically aligned on bottom - $this->y += ($maxh - $text_height); - } - } - } - $nl = $this->Write($this->lasth, $txt, '', 0, $align, true, $stretch, false, true, $maxh, 0, $mc_margin); - if ($fitcell) { - // restore font size - $this->setFontSize($prev_FontSizePt); - } - } - if ($autopadding) { - // add bottom padding - $this->y += $mc_padding['B']; - } - // Get end-of-text Y position - $currentY = $this->y; - // get latest page number - $endpage = $this->page; - if ($resth > 0) { - $skip = ($endpage - $startpage); - $tmpresth = $resth; - while ($tmpresth > 0) { - if ($skip <= 0) { - // add a page (or trig AcceptPageBreak() for multicolumn mode) - $this->checkPageBreak($this->PageBreakTrigger + 1); - } - if ($this->num_columns > 1) { - $tmpresth -= ($this->h - $this->y - $this->bMargin); - } else { - $tmpresth -= ($this->h - $this->tMargin - $this->bMargin); - } - --$skip; - } - $currentY = $this->y; - $endpage = $this->page; - } - // get latest column - $endcolumn = $this->current_column; - if ($this->num_columns == 0) { - $this->num_columns = 1; - } - // disable page regions check - $check_page_regions = $this->check_page_regions; - $this->check_page_regions = false; - // get border modes - $border_start = TCPDF_STATIC::getBorderMode($border, $position='start', $this->opencell); - $border_end = TCPDF_STATIC::getBorderMode($border, $position='end', $this->opencell); - $border_middle = TCPDF_STATIC::getBorderMode($border, $position='middle', $this->opencell); - // design borders around HTML cells. - for ($page = $startpage; $page <= $endpage; ++$page) { // for each page - $ccode = ''; - $this->setPage($page); - if ($this->num_columns < 2) { - // single-column mode - $this->setX($x); - $this->y = $this->tMargin; - } - // account for margin changes - if ($page > $startpage) { - if (($this->rtl) AND ($this->pagedim[$page]['orm'] != $this->pagedim[$startpage]['orm'])) { - $this->x -= ($this->pagedim[$page]['orm'] - $this->pagedim[$startpage]['orm']); - } elseif ((!$this->rtl) AND ($this->pagedim[$page]['olm'] != $this->pagedim[$startpage]['olm'])) { - $this->x += ($this->pagedim[$page]['olm'] - $this->pagedim[$startpage]['olm']); - } - } - if ($startpage == $endpage) { - // single page - for ($column = $startcolumn; $column <= $endcolumn; ++$column) { // for each column - if ($column != $this->current_column) { - $this->selectColumn($column); - } - if ($this->rtl) { - $this->x -= $mc_margin['R']; - } else { - $this->x += $mc_margin['L']; - } - if ($startcolumn == $endcolumn) { // single column - $cborder = $border; - $h = max($h, ($currentY - $oy)); - $this->y = $oy; - } elseif ($column == $startcolumn) { // first column - $cborder = $border_start; - $this->y = $oy; - $h = $this->h - $this->y - $this->bMargin; - } elseif ($column == $endcolumn) { // end column - $cborder = $border_end; - $h = $currentY - $this->y; - if ($resth > $h) { - $h = $resth; - } - } else { // middle column - $cborder = $border_middle; - $h = $this->h - $this->y - $this->bMargin; - $resth -= $h; - } - $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n"; - } // end for each column - } elseif ($page == $startpage) { // first page - for ($column = $startcolumn; $column < $this->num_columns; ++$column) { // for each column - if ($column != $this->current_column) { - $this->selectColumn($column); - } - if ($this->rtl) { - $this->x -= $mc_margin['R']; - } else { - $this->x += $mc_margin['L']; - } - if ($column == $startcolumn) { // first column - $cborder = $border_start; - $this->y = $oy; - $h = $this->h - $this->y - $this->bMargin; - } else { // middle column - $cborder = $border_middle; - $h = $this->h - $this->y - $this->bMargin; - $resth -= $h; - } - $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n"; - } // end for each column - } elseif ($page == $endpage) { // last page - for ($column = 0; $column <= $endcolumn; ++$column) { // for each column - if ($column != $this->current_column) { - $this->selectColumn($column); - } - if ($this->rtl) { - $this->x -= $mc_margin['R']; - } else { - $this->x += $mc_margin['L']; - } - if ($column == $endcolumn) { - // end column - $cborder = $border_end; - $h = $currentY - $this->y; - if ($resth > $h) { - $h = $resth; - } - } else { - // middle column - $cborder = $border_middle; - $h = $this->h - $this->y - $this->bMargin; - $resth -= $h; - } - $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n"; - } // end for each column - } else { // middle page - for ($column = 0; $column < $this->num_columns; ++$column) { // for each column - $this->selectColumn($column); - if ($this->rtl) { - $this->x -= $mc_margin['R']; - } else { - $this->x += $mc_margin['L']; - } - $cborder = $border_middle; - $h = $this->h - $this->y - $this->bMargin; - $resth -= $h; - $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n"; - } // end for each column - } - if ($cborder OR $fill) { - $offsetlen = strlen($ccode); - // draw border and fill - if ($this->inxobj) { - // we are inside an XObject template - if (end($this->xobjects[$this->xobjid]['transfmrk']) !== false) { - $pagemarkkey = key($this->xobjects[$this->xobjid]['transfmrk']); - $pagemark = $this->xobjects[$this->xobjid]['transfmrk'][$pagemarkkey]; - $this->xobjects[$this->xobjid]['transfmrk'][$pagemarkkey] += $offsetlen; - } else { - $pagemark = $this->xobjects[$this->xobjid]['intmrk']; - $this->xobjects[$this->xobjid]['intmrk'] += $offsetlen; - } - $pagebuff = $this->xobjects[$this->xobjid]['outdata']; - $pstart = substr($pagebuff, 0, $pagemark); - $pend = substr($pagebuff, $pagemark); - $this->xobjects[$this->xobjid]['outdata'] = $pstart.$ccode.$pend; - } else { - if (end($this->transfmrk[$this->page]) !== false) { - $pagemarkkey = key($this->transfmrk[$this->page]); - $pagemark = $this->transfmrk[$this->page][$pagemarkkey]; - $this->transfmrk[$this->page][$pagemarkkey] += $offsetlen; - } elseif ($this->InFooter) { - $pagemark = $this->footerpos[$this->page]; - $this->footerpos[$this->page] += $offsetlen; - } else { - $pagemark = $this->intmrk[$this->page]; - $this->intmrk[$this->page] += $offsetlen; - } - $pagebuff = $this->getPageBuffer($this->page); - $pstart = substr($pagebuff, 0, $pagemark); - $pend = substr($pagebuff, $pagemark); - $this->setPageBuffer($this->page, $pstart.$ccode.$pend); - } - } - } // end for each page - // restore page regions check - $this->check_page_regions = $check_page_regions; - // Get end-of-cell Y position - $currentY = $this->GetY(); - // restore previous values - if ($this->num_columns > 1) { - $this->selectColumn(); - } else { - // restore original margins - $this->lMargin = $lMargin; - $this->rMargin = $rMargin; - if ($this->page > $startpage) { - // check for margin variations between pages (i.e. booklet mode) - $dl = ($this->pagedim[$this->page]['olm'] - $this->pagedim[$startpage]['olm']); - $dr = ($this->pagedim[$this->page]['orm'] - $this->pagedim[$startpage]['orm']); - if (($dl != 0) OR ($dr != 0)) { - $this->lMargin += $dl; - $this->rMargin += $dr; - } - } - } - if ($ln > 0) { - //Go to the beginning of the next line - $this->setY($currentY + $mc_margin['B']); - if ($ln == 2) { - $this->setX($x + $w + $mc_margin['L'] + $mc_margin['R']); - } - } else { - // go left or right by case - $this->setPage($startpage); - $this->y = $y; - $this->setX($x + $w + $mc_margin['L'] + $mc_margin['R']); - } - $this->setContentMark(); - $this->cell_padding = $prev_cell_padding; - $this->cell_margin = $prev_cell_margin; - $this->clMargin = $this->lMargin; - $this->crMargin = $this->rMargin; - return $nl; - } - - /** - * This method return the estimated number of lines for print a simple text string using Multicell() method. - * @param string $txt String for calculating his height - * @param float $w Width of cells. If 0, they extend up to the right margin of the page. - * @param boolean $reseth if true reset the last cell height (default false). - * @param boolean $autopadding if true, uses internal padding and automatically adjust it to account for line width (default true). - * @param array|null $cellpadding Internal cell padding, if empty uses default cell padding. - * @param mixed $border Indicates if borders must be drawn around the cell. The value can be a number:<ul><li>0: no border (default)</li><li>1: frame</li></ul> or a string containing some or all of the following characters (in any order):<ul><li>L: left</li><li>T: top</li><li>R: right</li><li>B: bottom</li></ul> or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - * @return float Return the minimal height needed for multicell method for printing the $txt param. - * @author Alexander Escalona Fern\E1ndez, Nicola Asuni - * @public - * @since 4.5.011 - */ - public function getNumLines($txt, $w=0, $reseth=false, $autopadding=true, $cellpadding=null, $border=0) { - if ($txt === NULL) { - return 0; - } - if ($txt === '') { - // empty string - return 1; - } - // adjust internal padding - $prev_cell_padding = $this->cell_padding; - $prev_lasth = $this->lasth; - if (is_array($cellpadding)) { - $this->cell_padding = $cellpadding; - } - $this->adjustCellPadding($border); - if (TCPDF_STATIC::empty_string($w) OR ($w <= 0)) { - if ($this->rtl) { - $w = $this->x - $this->lMargin; - } else { - $w = $this->w - $this->rMargin - $this->x; - } - } - $wmax = $w - $this->cell_padding['L'] - $this->cell_padding['R']; - if ($reseth) { - // reset row height - $this->resetLastH(); - } - $lines = 1; - $sum = 0; - $chars = TCPDF_FONTS::utf8Bidi(TCPDF_FONTS::UTF8StringToArray($txt, $this->isunicode, $this->CurrentFont), $txt, $this->tmprtl, $this->isunicode, $this->CurrentFont); - $charsWidth = $this->GetArrStringWidth($chars, '', '', 0, true); - $length = count($chars); - $lastSeparator = -1; - for ($i = 0; $i < $length; ++$i) { - $c = $chars[$i]; - $charWidth = $charsWidth[$i]; - if (($c != 160) - AND (($c == 173) - OR preg_match($this->re_spaces, TCPDF_FONTS::unichr($c, $this->isunicode)) - OR (($c == 45) - AND ($i > 0) AND ($i < ($length - 1)) - AND @preg_match('/[\p{L}]/'.$this->re_space['m'], TCPDF_FONTS::unichr($chars[($i - 1)], $this->isunicode)) - AND @preg_match('/[\p{L}]/'.$this->re_space['m'], TCPDF_FONTS::unichr($chars[($i + 1)], $this->isunicode)) - ) - ) - ) { - $lastSeparator = $i; - } - if ((($sum + $charWidth) > $wmax) OR ($c == 10)) { - ++$lines; - if ($c == 10) { - $lastSeparator = -1; - $sum = 0; - } elseif ($lastSeparator != -1) { - $i = $lastSeparator; - $lastSeparator = -1; - $sum = 0; - } else { - $sum = $charWidth; - } - } else { - $sum += $charWidth; - } - } - if ($chars[($length - 1)] == 10) { - --$lines; - } - $this->cell_padding = $prev_cell_padding; - $this->lasth = $prev_lasth; - return $lines; - } - - /** - * This method return the estimated height needed for printing a simple text string using the Multicell() method. - * Generally, if you want to know the exact height for a block of content you can use the following alternative technique: - * @pre - * // store current object - * $pdf->startTransaction(); - * // store starting values - * $start_y = $pdf->GetY(); - * $start_page = $pdf->getPage(); - * // call your printing functions with your parameters - * // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * $pdf->MultiCell($w=0, $h=0, $txt, $border=1, $align='L', $fill=false, $ln=1, $x=null, $y=null, $reseth=true, $stretch=0, $ishtml=false, $autopadding=true, $maxh=0); - * // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * // get the new Y - * $end_y = $pdf->GetY(); - * $end_page = $pdf->getPage(); - * // calculate height - * $height = 0; - * if ($end_page == $start_page) { - * $height = $end_y - $start_y; - * } else { - * for ($page=$start_page; $page <= $end_page; ++$page) { - * $this->setPage($page); - * if ($page == $start_page) { - * // first page - * $height += $this->h - $start_y - $this->bMargin; - * } elseif ($page == $end_page) { - * // last page - * $height += $end_y - $this->tMargin; - * } else { - * $height += $this->h - $this->tMargin - $this->bMargin; - * } - * } - * } - * // restore previous object - * $pdf = $pdf->rollbackTransaction(); - * - * @param float $w Width of cells. If 0, they extend up to the right margin of the page. - * @param string $txt String for calculating his height - * @param boolean $reseth if true reset the last cell height (default false). - * @param boolean $autopadding if true, uses internal padding and automatically adjust it to account for line width (default true). - * @param array|null $cellpadding Internal cell padding, if empty uses default cell padding. - * @param mixed $border Indicates if borders must be drawn around the cell. The value can be a number:<ul><li>0: no border (default)</li><li>1: frame</li></ul> or a string containing some or all of the following characters (in any order):<ul><li>L: left</li><li>T: top</li><li>R: right</li><li>B: bottom</li></ul> or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - * @return float Return the minimal height needed for multicell method for printing the $txt param. - * @author Nicola Asuni, Alexander Escalona Fern\E1ndez - * @public - */ - public function getStringHeight($w, $txt, $reseth=false, $autopadding=true, $cellpadding=null, $border=0) { - // adjust internal padding - $prev_cell_padding = $this->cell_padding; - $prev_lasth = $this->lasth; - if (is_array($cellpadding)) { - $this->cell_padding = $cellpadding; - } - $this->adjustCellPadding($border); - $lines = $this->getNumLines($txt, $w, $reseth, $autopadding, $cellpadding, $border); - $height = $this->getCellHeight(($lines * $this->FontSize), $autopadding); - $this->cell_padding = $prev_cell_padding; - $this->lasth = $prev_lasth; - return $height; - } - - /** - * This method prints text from the current position.<br /> - * @param float $h Line height - * @param string $txt String to print - * @param mixed $link URL or identifier returned by AddLink() - * @param boolean $fill Indicates if the cell background must be painted (true) or transparent (false). - * @param string $align Allows to center or align the text. Possible values are:<ul><li>L or empty string: left align (default value)</li><li>C: center</li><li>R: right align</li><li>J: justify</li></ul> - * @param boolean $ln if true set cursor at the bottom of the line, otherwise set cursor at the top of the line. - * @param int $stretch font stretch mode: <ul><li>0 = disabled</li><li>1 = horizontal scaling only if text is larger than cell width</li><li>2 = forced horizontal scaling to fit cell width</li><li>3 = character spacing only if text is larger than cell width</li><li>4 = forced character spacing to fit cell width</li></ul> General font stretching and scaling values will be preserved when possible. - * @param boolean $firstline if true prints only the first line and return the remaining string. - * @param boolean $firstblock if true the string is the starting of a line. - * @param float $maxh maximum height. It should be >= $h and less then remaining space to the bottom of the page, or 0 for disable this feature. - * @param float $wadj first line width will be reduced by this amount (used in HTML mode). - * @param array|null $margin margin array of the parent container - * @return mixed Return the number of cells or the remaining string if $firstline = true. - * @public - * @since 1.5 - */ - public function Write($h, $txt, $link='', $fill=false, $align='', $ln=false, $stretch=0, $firstline=false, $firstblock=false, $maxh=0, $wadj=0, $margin=null) { - // check page for no-write regions and adapt page margins if necessary - list($this->x, $this->y) = $this->checkPageRegions($h, $this->x, $this->y); - if (strlen($txt) == 0) { - // fix empty text - $txt = ' '; - } - if (!is_array($margin)) { - // set default margins - $margin = $this->cell_margin; - } - // remove carriage returns - $s = str_replace("\r", '', $txt); - // check if string contains arabic text - if (preg_match(TCPDF_FONT_DATA::$uni_RE_PATTERN_ARABIC, $s)) { - $arabic = true; - } else { - $arabic = false; - } - // check if string contains RTL text - if ($arabic OR ($this->tmprtl == 'R') OR preg_match(TCPDF_FONT_DATA::$uni_RE_PATTERN_RTL, $s)) { - $rtlmode = true; - } else { - $rtlmode = false; - } - // get a char width - $chrwidth = $this->GetCharWidth(46); // dot character - // get array of unicode values - $chars = TCPDF_FONTS::UTF8StringToArray($s, $this->isunicode, $this->CurrentFont); - // calculate maximum width for a single character on string - $chrw = $this->GetArrStringWidth($chars, '', '', 0, true); - array_walk($chrw, array($this, 'getRawCharWidth')); - $maxchwidth = max($chrw); - // get array of chars - $uchars = TCPDF_FONTS::UTF8ArrayToUniArray($chars, $this->isunicode); - // get the number of characters - $nb = count($chars); - // replacement for SHY character (minus symbol) - $shy_replacement = 45; - $shy_replacement_char = TCPDF_FONTS::unichr($shy_replacement, $this->isunicode); - // widht for SHY replacement - $shy_replacement_width = $this->GetCharWidth($shy_replacement); - // page width - $pw = $w = $this->w - $this->lMargin - $this->rMargin; - // calculate remaining line width ($w) - if ($this->rtl) { - $w = $this->x - $this->lMargin; - } else { - $w = $this->w - $this->rMargin - $this->x; - } - // max column width - $wmax = ($w - $wadj); - if (!$firstline) { - $wmax -= ($this->cell_padding['L'] + $this->cell_padding['R']); - } - if ((!$firstline) AND (($chrwidth > $wmax) OR ($maxchwidth > $wmax))) { - // the maximum width character do not fit on column - return ''; - } - // minimum row height - $row_height = max($h, $this->getCellHeight($this->FontSize)); - // max Y - $maxy = $this->y + $maxh - max($row_height, $h); - $start_page = $this->page; - $i = 0; // character position - $j = 0; // current starting position - $sep = -1; // position of the last blank space - $prevsep = $sep; // previous separator - $shy = false; // true if the last blank is a soft hypen (SHY) - $prevshy = $shy; // previous shy mode - $l = 0; // current string length - $nl = 0; //number of lines - $linebreak = false; - $pc = 0; // previous character - // for each character - while ($i < $nb) { - if (($maxh > 0) AND ($this->y > $maxy) ) { - break; - } - //Get the current character - $c = $chars[$i]; - if ($c == 10) { // 10 = "\n" = new line - //Explicit line break - if ($align == 'J') { - if ($this->rtl) { - $talign = 'R'; - } else { - $talign = 'L'; - } - } else { - $talign = $align; - } - $tmpstr = TCPDF_FONTS::UniArrSubString($uchars, $j, $i); - if ($firstline) { - $startx = $this->x; - $tmparr = array_slice($chars, $j, ($i - $j)); - if ($rtlmode) { - $tmparr = TCPDF_FONTS::utf8Bidi($tmparr, $tmpstr, $this->tmprtl, $this->isunicode, $this->CurrentFont); - } - $linew = $this->GetArrStringWidth($tmparr); - unset($tmparr); - if ($this->rtl) { - $this->endlinex = $startx - $linew; - } else { - $this->endlinex = $startx + $linew; - } - $w = $linew; - $tmpcellpadding = $this->cell_padding; - if ($maxh == 0) { - $this->setCellPadding(0); - } - } - if ($firstblock AND $this->isRTLTextDir()) { - $tmpstr = $this->stringRightTrim($tmpstr); - } - // Skip newlines at the beginning of a page or column - if (!empty($tmpstr) OR ($this->y < ($this->PageBreakTrigger - $row_height))) { - $this->Cell($w, $h, $tmpstr, 0, 1, $talign, $fill, $link, $stretch); - } - unset($tmpstr); - if ($firstline) { - $this->cell_padding = $tmpcellpadding; - return (TCPDF_FONTS::UniArrSubString($uchars, $i)); - } - ++$nl; - $j = $i + 1; - $l = 0; - $sep = -1; - $prevsep = $sep; - $shy = false; - // account for margin changes - if ((($this->y + $this->lasth) > $this->PageBreakTrigger) AND ($this->inPageBody())) { - $this->AcceptPageBreak(); - if ($this->rtl) { - $this->x -= $margin['R']; - } else { - $this->x += $margin['L']; - } - $this->lMargin += $margin['L']; - $this->rMargin += $margin['R']; - } - $w = $this->getRemainingWidth(); - $wmax = ($w - $this->cell_padding['L'] - $this->cell_padding['R']); - } else { - // 160 is the non-breaking space. - // 173 is SHY (Soft Hypen). - // \p{Z} or \p{Separator}: any kind of Unicode whitespace or invisible separator. - // \p{Lo} or \p{Other_Letter}: a Unicode letter or ideograph that does not have lowercase and uppercase variants. - // \p{Lo} is needed because Chinese characters are packed next to each other without spaces in between. - if (($c != 160) - AND (($c == 173) - OR preg_match($this->re_spaces, TCPDF_FONTS::unichr($c, $this->isunicode)) - OR (($c == 45) - AND ($i < ($nb - 1)) - AND @preg_match('/[\p{L}]/'.$this->re_space['m'], TCPDF_FONTS::unichr($pc, $this->isunicode)) - AND @preg_match('/[\p{L}]/'.$this->re_space['m'], TCPDF_FONTS::unichr($chars[($i + 1)], $this->isunicode)) - ) - ) - ) { - // update last blank space position - $prevsep = $sep; - $sep = $i; - // check if is a SHY - if (($c == 173) OR ($c == 45)) { - $prevshy = $shy; - $shy = true; - if ($pc == 45) { - $tmp_shy_replacement_width = 0; - $tmp_shy_replacement_char = ''; - } else { - $tmp_shy_replacement_width = $shy_replacement_width; - $tmp_shy_replacement_char = $shy_replacement_char; - } - } else { - $shy = false; - } - } - // update string length - if ($this->isUnicodeFont() AND ($arabic)) { - // with bidirectional algorithm some chars may be changed affecting the line length - // *** very slow *** - $l = $this->GetArrStringWidth(TCPDF_FONTS::utf8Bidi(array_slice($chars, $j, ($i - $j)), '', $this->tmprtl, $this->isunicode, $this->CurrentFont)); - } else { - $l += $this->GetCharWidth($c, ($i+1 < $nb)); - } - if (($l > $wmax) OR (($c == 173) AND (($l + $tmp_shy_replacement_width) >= $wmax))) { - if (($c == 173) AND (($l + $tmp_shy_replacement_width) > $wmax)) { - $sep = $prevsep; - $shy = $prevshy; - } - // we have reached the end of column - if ($sep == -1) { - // check if the line was already started - if (($this->rtl AND ($this->x <= ($this->w - $this->rMargin - $this->cell_padding['R'] - $margin['R'] - $chrwidth))) - OR ((!$this->rtl) AND ($this->x >= ($this->lMargin + $this->cell_padding['L'] + $margin['L'] + $chrwidth)))) { - // print a void cell and go to next line - $this->Cell($w, $h, '', 0, 1); - $linebreak = true; - if ($firstline) { - return (TCPDF_FONTS::UniArrSubString($uchars, $j)); - } - } else { - // truncate the word because do not fit on column - $tmpstr = TCPDF_FONTS::UniArrSubString($uchars, $j, $i); - if ($firstline) { - $startx = $this->x; - $tmparr = array_slice($chars, $j, ($i - $j)); - if ($rtlmode) { - $tmparr = TCPDF_FONTS::utf8Bidi($tmparr, $tmpstr, $this->tmprtl, $this->isunicode, $this->CurrentFont); - } - $linew = $this->GetArrStringWidth($tmparr); - unset($tmparr); - if ($this->rtl) { - $this->endlinex = $startx - $linew; - } else { - $this->endlinex = $startx + $linew; - } - $w = $linew; - $tmpcellpadding = $this->cell_padding; - if ($maxh == 0) { - $this->setCellPadding(0); - } - } - if ($firstblock AND $this->isRTLTextDir()) { - $tmpstr = $this->stringRightTrim($tmpstr); - } - $this->Cell($w, $h, $tmpstr, 0, 1, $align, $fill, $link, $stretch); - unset($tmpstr); - if ($firstline) { - $this->cell_padding = $tmpcellpadding; - return (TCPDF_FONTS::UniArrSubString($uchars, $i)); - } - $j = $i; - --$i; - } - } else { - // word wrapping - if ($this->rtl AND (!$firstblock) AND ($sep < $i)) { - $endspace = 1; - } else { - $endspace = 0; - } - // check the length of the next string - $strrest = TCPDF_FONTS::UniArrSubString($uchars, ($sep + $endspace)); - $nextstr = TCPDF_STATIC::pregSplit('/'.$this->re_space['p'].'/', $this->re_space['m'], $this->stringTrim($strrest)); - if (isset($nextstr[0]) AND ($this->GetStringWidth($nextstr[0]) > $pw)) { - // truncate the word because do not fit on a full page width - $tmpstr = TCPDF_FONTS::UniArrSubString($uchars, $j, $i); - if ($firstline) { - $startx = $this->x; - $tmparr = array_slice($chars, $j, ($i - $j)); - if ($rtlmode) { - $tmparr = TCPDF_FONTS::utf8Bidi($tmparr, $tmpstr, $this->tmprtl, $this->isunicode, $this->CurrentFont); - } - $linew = $this->GetArrStringWidth($tmparr); - unset($tmparr); - if ($this->rtl) { - $this->endlinex = ($startx - $linew); - } else { - $this->endlinex = ($startx + $linew); - } - $w = $linew; - $tmpcellpadding = $this->cell_padding; - if ($maxh == 0) { - $this->setCellPadding(0); - } - } - if ($firstblock AND $this->isRTLTextDir()) { - $tmpstr = $this->stringRightTrim($tmpstr); - } - $this->Cell($w, $h, $tmpstr, 0, 1, $align, $fill, $link, $stretch); - unset($tmpstr); - if ($firstline) { - $this->cell_padding = $tmpcellpadding; - return (TCPDF_FONTS::UniArrSubString($uchars, $i)); - } - $j = $i; - --$i; - } else { - // word wrapping - if ($shy) { - // add hypen (minus symbol) at the end of the line - $shy_width = $tmp_shy_replacement_width; - if ($this->rtl) { - $shy_char_left = $tmp_shy_replacement_char; - $shy_char_right = ''; - } else { - $shy_char_left = ''; - $shy_char_right = $tmp_shy_replacement_char; - } - } else { - $shy_width = 0; - $shy_char_left = ''; - $shy_char_right = ''; - } - $tmpstr = TCPDF_FONTS::UniArrSubString($uchars, $j, ($sep + $endspace)); - if ($firstline) { - $startx = $this->x; - $tmparr = array_slice($chars, $j, (($sep + $endspace) - $j)); - if ($rtlmode) { - $tmparr = TCPDF_FONTS::utf8Bidi($tmparr, $tmpstr, $this->tmprtl, $this->isunicode, $this->CurrentFont); - } - $linew = $this->GetArrStringWidth($tmparr); - unset($tmparr); - if ($this->rtl) { - $this->endlinex = $startx - $linew - $shy_width; - } else { - $this->endlinex = $startx + $linew + $shy_width; - } - $w = $linew; - $tmpcellpadding = $this->cell_padding; - if ($maxh == 0) { - $this->setCellPadding(0); - } - } - // print the line - if ($firstblock AND $this->isRTLTextDir()) { - $tmpstr = $this->stringRightTrim($tmpstr); - } - $this->Cell($w, $h, $shy_char_left.$tmpstr.$shy_char_right, 0, 1, $align, $fill, $link, $stretch); - unset($tmpstr); - if ($firstline) { - if ($chars[$sep] == 45) { - $endspace += 1; - } - // return the remaining text - $this->cell_padding = $tmpcellpadding; - return (TCPDF_FONTS::UniArrSubString($uchars, ($sep + $endspace))); - } - $i = $sep; - $sep = -1; - $shy = false; - $j = ($i + 1); - } - } - // account for margin changes - if ((($this->y + $this->lasth) > $this->PageBreakTrigger) AND ($this->inPageBody())) { - $this->AcceptPageBreak(); - if ($this->rtl) { - $this->x -= $margin['R']; - } else { - $this->x += $margin['L']; - } - $this->lMargin += $margin['L']; - $this->rMargin += $margin['R']; - } - $w = $this->getRemainingWidth(); - $wmax = $w - $this->cell_padding['L'] - $this->cell_padding['R']; - if ($linebreak) { - $linebreak = false; - } else { - ++$nl; - $l = 0; - } - } - } - // save last character - $pc = $c; - ++$i; - } // end while i < nb - // print last substring (if any) - if ($l > 0) { - switch ($align) { - case 'J': - case 'C': { - break; - } - case 'L': { - if (!$this->rtl) { - $w = $l; - } - break; - } - case 'R': { - if ($this->rtl) { - $w = $l; - } - break; - } - default: { - $w = $l; - break; - } - } - $tmpstr = TCPDF_FONTS::UniArrSubString($uchars, $j, $nb); - if ($firstline) { - $startx = $this->x; - $tmparr = array_slice($chars, $j, ($nb - $j)); - if ($rtlmode) { - $tmparr = TCPDF_FONTS::utf8Bidi($tmparr, $tmpstr, $this->tmprtl, $this->isunicode, $this->CurrentFont); - } - $linew = $this->GetArrStringWidth($tmparr); - unset($tmparr); - if ($this->rtl) { - $this->endlinex = $startx - $linew; - } else { - $this->endlinex = $startx + $linew; - } - $w = $linew; - $tmpcellpadding = $this->cell_padding; - if ($maxh == 0) { - $this->setCellPadding(0); - } - } - if ($firstblock AND $this->isRTLTextDir()) { - $tmpstr = $this->stringRightTrim($tmpstr); - } - $this->Cell($w, $h, $tmpstr, 0, $ln, $align, $fill, $link, $stretch); - unset($tmpstr); - if ($firstline) { - $this->cell_padding = $tmpcellpadding; - return (TCPDF_FONTS::UniArrSubString($uchars, $nb)); - } - ++$nl; - } - if ($firstline) { - return ''; - } - return $nl; - } - - /** - * Returns the remaining width between the current position and margins. - * @return float Return the remaining width - * @protected - */ - protected function getRemainingWidth() { - list($this->x, $this->y) = $this->checkPageRegions(0, $this->x, $this->y); - if ($this->rtl) { - return ($this->x - $this->lMargin); - } else { - return ($this->w - $this->rMargin - $this->x); - } - } - - /** - * Set the block dimensions accounting for page breaks and page/column fitting - * @param float $w width - * @param float $h height - * @param float $x X coordinate - * @param float $y Y coodiante - * @param boolean $fitonpage if true the block is resized to not exceed page dimensions. - * @return array array($w, $h, $x, $y) - * @protected - * @since 5.5.009 (2010-07-05) - */ - protected function fitBlock($w, $h, $x, $y, $fitonpage=false) { - if ($w <= 0) { - // set maximum width - $w = ($this->w - $this->lMargin - $this->rMargin); - if ($w <= 0) { - $w = 1; - } - } - if ($h <= 0) { - // set maximum height - $h = ($this->PageBreakTrigger - $this->tMargin); - if ($h <= 0) { - $h = 1; - } - } - // resize the block to be vertically contained on a single page or single column - if ($fitonpage OR $this->AutoPageBreak) { - $ratio_wh = ($w / $h); - if ($h > ($this->PageBreakTrigger - $this->tMargin)) { - $h = $this->PageBreakTrigger - $this->tMargin; - $w = ($h * $ratio_wh); - } - // resize the block to be horizontally contained on a single page or single column - if ($fitonpage) { - $maxw = ($this->w - $this->lMargin - $this->rMargin); - if ($w > $maxw) { - $w = $maxw; - $h = ($w / $ratio_wh); - } - } - } - // Check whether we need a new page or new column first as this does not fit - $prev_x = $this->x; - $prev_y = $this->y; - if ($this->checkPageBreak($h, $y) OR ($this->y < $prev_y)) { - $y = $this->y; - if ($this->rtl) { - $x += ($prev_x - $this->x); - } else { - $x += ($this->x - $prev_x); - } - $this->newline = true; - } - // resize the block to be contained on the remaining available page or column space - if ($fitonpage) { - $ratio_wh = ($w / $h); - if (($y + $h) > $this->PageBreakTrigger) { - $h = $this->PageBreakTrigger - $y; - $w = ($h * $ratio_wh); - } - if ((!$this->rtl) AND (($x + $w) > ($this->w - $this->rMargin))) { - $w = $this->w - $this->rMargin - $x; - $h = ($w / $ratio_wh); - } elseif (($this->rtl) AND (($x - $w) < ($this->lMargin))) { - $w = $x - $this->lMargin; - $h = ($w / $ratio_wh); - } - } - return array($w, $h, $x, $y); - } - - /** - * Puts an image in the page. - * The upper-left corner must be given. - * The dimensions can be specified in different ways:<ul> - * <li>explicit width and height (expressed in user unit)</li> - * <li>one explicit dimension, the other being calculated automatically in order to keep the original proportions</li> - * <li>no explicit dimension, in which case the image is put at 72 dpi</li></ul> - * Supported formats are JPEG and PNG images whitout GD library and all images supported by GD: GD, GD2, GD2PART, GIF, JPEG, PNG, BMP, XBM, XPM; - * The format can be specified explicitly or inferred from the file extension.<br /> - * It is possible to put a link on the image.<br /> - * Remark: if an image is used several times, only one copy will be embedded in the file.<br /> - * @param string $file Name of the file containing the image or a '@' character followed by the image data string. To link an image without embedding it on the document, set an asterisk character before the URL (i.e.: '*http://www.example.com/image.jpg'). - * @param float|null $x Abscissa of the upper-left corner (LTR) or upper-right corner (RTL). - * @param float|null $y Ordinate of the upper-left corner (LTR) or upper-right corner (RTL). - * @param float $w Width of the image in the page. If not specified or equal to zero, it is automatically calculated. - * @param float $h Height of the image in the page. If not specified or equal to zero, it is automatically calculated. - * @param string $type Image format. Possible values are (case insensitive): JPEG and PNG (whitout GD library) and all images supported by GD: GD, GD2, GD2PART, GIF, JPEG, PNG, BMP, XBM, XPM;. If not specified, the type is inferred from the file extension. - * @param mixed $link URL or identifier returned by AddLink(). - * @param string $align Indicates the alignment of the pointer next to image insertion relative to image height. The value can be:<ul><li>T: top-right for LTR or top-left for RTL</li><li>M: middle-right for LTR or middle-left for RTL</li><li>B: bottom-right for LTR or bottom-left for RTL</li><li>N: next line</li></ul> - * @param mixed $resize If true resize (reduce) the image to fit $w and $h (requires GD or ImageMagick library); if false do not resize; if 2 force resize in all cases (upscaling and downscaling). - * @param int $dpi dot-per-inch resolution used on resize - * @param string $palign Allows to center or align the image on the current line. Possible values are:<ul><li>L : left align</li><li>C : center</li><li>R : right align</li><li>'' : empty string : left for LTR or right for RTL</li></ul> - * @param boolean $ismask true if this image is a mask, false otherwise - * @param mixed $imgmask image object returned by this function or false - * @param mixed $border Indicates if borders must be drawn around the cell. The value can be a number:<ul><li>0: no border (default)</li><li>1: frame</li></ul> or a string containing some or all of the following characters (in any order):<ul><li>L: left</li><li>T: top</li><li>R: right</li><li>B: bottom</li></ul> or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - * @param mixed $fitbox If not false scale image dimensions proportionally to fit within the ($w, $h) box. $fitbox can be true or a 2 characters string indicating the image alignment inside the box. The first character indicate the horizontal alignment (L = left, C = center, R = right) the second character indicate the vertical algnment (T = top, M = middle, B = bottom). - * @param boolean $hidden If true do not display the image. - * @param boolean $fitonpage If true the image is resized to not exceed page dimensions. - * @param boolean $alt If true the image will be added as alternative and not directly printed (the ID of the image will be returned). - * @param array $altimgs Array of alternate images IDs. Each alternative image must be an array with two values: an integer representing the image ID (the value returned by the Image method) and a boolean value to indicate if the image is the default for printing. - * @return mixed|false image information - * @public - * @since 1.1 - */ - public function Image($file, $x=null, $y=null, $w=0, $h=0, $type='', $link='', $align='', $resize=false, $dpi=300, $palign='', $ismask=false, $imgmask=false, $border=0, $fitbox=false, $hidden=false, $fitonpage=false, $alt=false, $altimgs=array()) { - if ($this->state != 2) { - return false; - } - if (TCPDF_STATIC::empty_string($x)) { - $x = $this->x; - } - if (TCPDF_STATIC::empty_string($y)) { - $y = $this->y; - } - // check page for no-write regions and adapt page margins if necessary - list($x, $y) = $this->checkPageRegions($h, $x, $y); - $exurl = ''; // external streams - $imsize = FALSE; - - // Make sure the file variable is not empty or null because accessing $file[0] later - // results in error when running PHP 7.4 - if (empty($file)) { - return false; - } - // check if we are passing an image as file or string - if ($file[0] === '@') { - // image from string - $imgdata = substr($file, 1); - } else { // image file - if ($file[0] === '*') { - // image as external stream - $file = substr($file, 1); - $exurl = $file; - } - // check if file exist and it is valid - if (!@$this->fileExists($file)) { - return false; - } - if (false !== $info = $this->getImageBuffer($file)) { - $imsize = array($info['w'], $info['h']); - } elseif (($imsize = @getimagesize($file)) === FALSE && strpos($file, '__tcpdf_'.$this->file_id.'_img') === FALSE){ - $imgdata = $this->getCachedFileContents($file); - } - } - if (!empty($imgdata)) { - // copy image to cache - $original_file = $file; - $file = TCPDF_STATIC::getObjFilename('img', $this->file_id); - $fp = TCPDF_STATIC::fopenLocal($file, 'w'); - if (!$fp) { - $this->Error('Unable to write file: '.$file); - } - fwrite($fp, $imgdata); - fclose($fp); - unset($imgdata); - $imsize = @getimagesize($file); - if ($imsize === FALSE) { - unlink($file); - $file = $original_file; - } - } - if ($imsize === FALSE) { - if (($w > 0) AND ($h > 0)) { - // get measures from specified data - $pw = $this->getHTMLUnitToUnits($w, 0, $this->pdfunit, true) * $this->imgscale * $this->k; - $ph = $this->getHTMLUnitToUnits($h, 0, $this->pdfunit, true) * $this->imgscale * $this->k; - $imsize = array($pw, $ph); - } else { - $this->Error('[Image] Unable to get the size of the image: '.$file); - } - } - // file hash - $filehash = md5($file); - // get original image width and height in pixels - list($pixw, $pixh) = $imsize; - // calculate image width and height on document - if (($w <= 0) AND ($h <= 0)) { - // convert image size to document unit - $w = $this->pixelsToUnits($pixw); - $h = $this->pixelsToUnits($pixh); - } elseif ($w <= 0) { - $w = $h * $pixw / $pixh; - } elseif ($h <= 0) { - $h = $w * $pixh / $pixw; - } elseif (($fitbox !== false) AND ($w > 0) AND ($h > 0)) { - if (strlen($fitbox) !== 2) { - // set default alignment - $fitbox = '--'; - } - // scale image dimensions proportionally to fit within the ($w, $h) box - if ((($w * $pixh) / ($h * $pixw)) < 1) { - // store current height - $oldh = $h; - // calculate new height - $h = $w * $pixh / $pixw; - // height difference - $hdiff = ($oldh - $h); - // vertical alignment - switch (strtoupper($fitbox[1])) { - case 'T': { - break; - } - case 'M': { - $y += ($hdiff / 2); - break; - } - case 'B': { - $y += $hdiff; - break; - } - } - } else { - // store current width - $oldw = $w; - // calculate new width - $w = $h * $pixw / $pixh; - // width difference - $wdiff = ($oldw - $w); - // horizontal alignment - switch (strtoupper($fitbox[0])) { - case 'L': { - if ($this->rtl) { - $x -= $wdiff; - } - break; - } - case 'C': { - if ($this->rtl) { - $x -= ($wdiff / 2); - } else { - $x += ($wdiff / 2); - } - break; - } - case 'R': { - if (!$this->rtl) { - $x += $wdiff; - } - break; - } - } - } - } - // fit the image on available space - list($w, $h, $x, $y) = $this->fitBlock($w, $h, $x, $y, $fitonpage); - // calculate new minimum dimensions in pixels - $neww = round($w * $this->k * $dpi / $this->dpi); - $newh = round($h * $this->k * $dpi / $this->dpi); - // check if resize is necessary (resize is used only to reduce the image) - $newsize = ($neww * $newh); - $pixsize = ($pixw * $pixh); - if (intval($resize) == 2) { - $resize = true; - } elseif ($newsize >= $pixsize) { - $resize = false; - } - // check if image has been already added on document - $newimage = true; - if (in_array($file, $this->imagekeys)) { - $newimage = false; - // get existing image data - $info = $this->getImageBuffer($file); - if (strpos($file, '__tcpdf_'.$this->file_id.'_imgmask_') === FALSE) { - // check if the newer image is larger - $oldsize = ($info['w'] * $info['h']); - if ((($oldsize < $newsize) AND ($resize)) OR (($oldsize < $pixsize) AND (!$resize))) { - $newimage = true; - } - } - } elseif (($ismask === false) AND ($imgmask === false) AND (strpos($file, '__tcpdf_'.$this->file_id.'_imgmask_') === FALSE)) { - // create temp image file (without alpha channel) - $tempfile_plain = K_PATH_CACHE.'__tcpdf_'.$this->file_id.'_imgmask_plain_'.$filehash; - // create temp alpha file - $tempfile_alpha = K_PATH_CACHE.'__tcpdf_'.$this->file_id.'_imgmask_alpha_'.$filehash; - // check for cached images - if (in_array($tempfile_plain, $this->imagekeys)) { - // get existing image data - $info = $this->getImageBuffer($tempfile_plain); - // check if the newer image is larger - $oldsize = ($info['w'] * $info['h']); - if ((($oldsize < $newsize) AND ($resize)) OR (($oldsize < $pixsize) AND (!$resize))) { - $newimage = true; - } else { - $newimage = false; - // embed mask image - $imgmask = $this->Image($tempfile_alpha, $x, $y, $w, $h, 'PNG', '', '', $resize, $dpi, '', true, false); - // embed image, masked with previously embedded mask - return $this->Image($tempfile_plain, $x, $y, $w, $h, $type, $link, $align, $resize, $dpi, $palign, false, $imgmask); - } - } - } - if ($newimage) { - //First use of image, get info - $type = strtolower($type); - if ($type == '') { - $type = TCPDF_IMAGES::getImageFileType($file, $imsize); - } elseif ($type == 'jpg') { - $type = 'jpeg'; - } - $mqr = TCPDF_STATIC::get_mqr(); - TCPDF_STATIC::set_mqr(false); - // Specific image handlers (defined on TCPDF_IMAGES CLASS) - $mtd = '_parse'.$type; - // GD image handler function - $gdfunction = 'imagecreatefrom'.$type; - $info = false; - if ((method_exists('TCPDF_IMAGES', $mtd)) AND (!($resize AND (function_exists($gdfunction) OR extension_loaded('imagick'))))) { - // TCPDF image functions - $info = TCPDF_IMAGES::$mtd($file); - if (($ismask === false) AND ($imgmask === false) AND (strpos($file, '__tcpdf_'.$this->file_id.'_imgmask_') === FALSE) - AND (($info === 'pngalpha') OR (isset($info['trns']) AND !empty($info['trns'])))) { - return $this->ImagePngAlpha($file, $x, $y, $pixw, $pixh, $w, $h, 'PNG', $link, $align, $resize, $dpi, $palign, $filehash); - } - } - if (($info === false) AND function_exists($gdfunction)) { - try { - // GD library - $img = $gdfunction($file); - if ($img !== false) { - if ($resize) { - $imgr = imagecreatetruecolor($neww, $newh); - if (($type == 'gif') OR ($type == 'png')) { - $imgr = TCPDF_IMAGES::setGDImageTransparency($imgr, $img); - } - imagecopyresampled($imgr, $img, 0, 0, 0, 0, $neww, $newh, $pixw, $pixh); - $img = $imgr; - } - if (($type == 'gif') OR ($type == 'png')) { - $info = TCPDF_IMAGES::_toPNG($img, TCPDF_STATIC::getObjFilename('img', $this->file_id)); - } else { - $info = TCPDF_IMAGES::_toJPEG($img, $this->jpeg_quality, TCPDF_STATIC::getObjFilename('img', $this->file_id)); - } - } - } catch(Exception $e) { - $info = false; - } - } - if (($info === false) AND extension_loaded('imagick')) { - try { - // ImageMagick library - $img = new Imagick(); - if ($type == 'svg') { - if ($file[0] === '@') { - // image from string - $svgimg = substr($file, 1); - } else { - // get SVG file content - $svgimg = $this->getCachedFileContents($file); - } - if ($svgimg !== FALSE) { - // get width and height - $regs = array(); - if (preg_match('/<svg([^\>]*)>/si', $svgimg, $regs)) { - $svgtag = $regs[1]; - $tmp = array(); - if (preg_match('/[\s]+width[\s]*=[\s]*"([^"]*)"/si', $svgtag, $tmp)) { - $ow = $this->getHTMLUnitToUnits($tmp[1], 1, $this->svgunit, false); - $owu = sprintf('%F', ($ow * $dpi / 72)).$this->pdfunit; - $svgtag = preg_replace('/[\s]+width[\s]*=[\s]*"[^"]*"/si', ' width="'.$owu.'"', $svgtag, 1); - } else { - $ow = $w; - } - $tmp = array(); - if (preg_match('/[\s]+height[\s]*=[\s]*"([^"]*)"/si', $svgtag, $tmp)) { - $oh = $this->getHTMLUnitToUnits($tmp[1], 1, $this->svgunit, false); - $ohu = sprintf('%F', ($oh * $dpi / 72)).$this->pdfunit; - $svgtag = preg_replace('/[\s]+height[\s]*=[\s]*"[^"]*"/si', ' height="'.$ohu.'"', $svgtag, 1); - } else { - $oh = $h; - } - $tmp = array(); - if (!preg_match('/[\s]+viewBox[\s]*=[\s]*"[\s]*([0-9\.]+)[\s]+([0-9\.]+)[\s]+([0-9\.]+)[\s]+([0-9\.]+)[\s]*"/si', $svgtag, $tmp)) { - $vbw = ($ow * $this->imgscale * $this->k); - $vbh = ($oh * $this->imgscale * $this->k); - $vbox = sprintf(' viewBox="0 0 %F %F" ', $vbw, $vbh); - $svgtag = $vbox.$svgtag; - } - $svgimg = preg_replace('/<svg([^\>]*)>/si', '<svg'.$svgtag.'>', $svgimg, 1); - } - $img->readImageBlob($svgimg); - } - } else { - $img->readImage($file); - } - if ($resize) { - $img->resizeImage($neww, $newh, 10, 1, false); - } - $img->setCompressionQuality($this->jpeg_quality); - $img->setImageFormat('jpeg'); - $tempname = TCPDF_STATIC::getObjFilename('img', $this->file_id); - $img->writeImage($tempname); - $info = TCPDF_IMAGES::_parsejpeg($tempname); - unlink($tempname); - $img->destroy(); - } catch(Exception $e) { - $info = false; - } - } - if ($info === false) { - // unable to process image - return false; - } - TCPDF_STATIC::set_mqr($mqr); - if ($ismask) { - // force grayscale - $info['cs'] = 'DeviceGray'; - } - if ($imgmask !== false) { - $info['masked'] = $imgmask; - } - if (!empty($exurl)) { - $info['exurl'] = $exurl; - } - // array of alternative images - $info['altimgs'] = $altimgs; - // add image to document - $info['i'] = $this->setImageBuffer($file, $info); - } - // set alignment - $this->img_rb_x = $x + $w; - $this->img_rb_y = $y + $h; - - // set alignment - if ($palign == 'L') { - $ximg = $this->lMargin; - } elseif ($palign == 'C') { - $ximg = ($this->w + $this->lMargin - $this->rMargin - $w) / 2; - } elseif ($palign == 'R') { - $ximg = $this->w - $this->rMargin - $w; - } else { - $ximg = $x; - } - - if ($ismask OR $hidden) { - // image is not displayed - return $info['i']; - } - $xkimg = $ximg * $this->k; - if (!$alt) { - // only non-alternative immages will be set - $this->_out(sprintf('q %F 0 0 %F %F %F cm /I%u Do Q', ($w * $this->k), ($h * $this->k), $xkimg, (($this->h - ($y + $h)) * $this->k), $info['i'])); - } - if (!empty($border)) { - $bx = $this->x; - $by = $this->y; - $this->x = $ximg; - if ($this->rtl) { - $this->x += $w; - } - $this->y = $y; - $this->Cell($w, $h, '', $border, 0, '', 0, '', 0, true); - $this->x = $bx; - $this->y = $by; - } - if ($link) { - $this->Link($ximg, $y, $w, $h, $link, 0); - } - // set pointer to align the next text/objects - switch($align) { - case 'T': { - $this->y = $y; - $this->x = $this->img_rb_x; - break; - } - case 'M': { - $this->y = $y + round($h/2); - $this->x = $this->img_rb_x; - break; - } - case 'B': { - $this->y = $this->img_rb_y; - $this->x = $this->img_rb_x; - break; - } - case 'N': { - $this->setY($this->img_rb_y); - break; - } - default:{ - break; - } - } - $this->endlinex = $this->img_rb_x; - if ($this->inxobj) { - // we are inside an XObject template - $this->xobjects[$this->xobjid]['images'][] = $info['i']; - } - return $info['i']; - } - - /** - * Extract info from a PNG image with alpha channel using the Imagick or GD library. - * @param string $file Name of the file containing the image. - * @param float $x Abscissa of the upper-left corner. - * @param float $y Ordinate of the upper-left corner. - * @param float $wpx Original width of the image in pixels. - * @param float $hpx original height of the image in pixels. - * @param float $w Width of the image in the page. If not specified or equal to zero, it is automatically calculated. - * @param float $h Height of the image in the page. If not specified or equal to zero, it is automatically calculated. - * @param string $type Image format. Possible values are (case insensitive): JPEG and PNG (whitout GD library) and all images supported by GD: GD, GD2, GD2PART, GIF, JPEG, PNG, BMP, XBM, XPM;. If not specified, the type is inferred from the file extension. - * @param mixed $link URL or identifier returned by AddLink(). - * @param string $align Indicates the alignment of the pointer next to image insertion relative to image height. The value can be:<ul><li>T: top-right for LTR or top-left for RTL</li><li>M: middle-right for LTR or middle-left for RTL</li><li>B: bottom-right for LTR or bottom-left for RTL</li><li>N: next line</li></ul> - * @param boolean $resize If true resize (reduce) the image to fit $w and $h (requires GD library). - * @param int $dpi dot-per-inch resolution used on resize - * @param string $palign Allows to center or align the image on the current line. Possible values are:<ul><li>L : left align</li><li>C : center</li><li>R : right align</li><li>'' : empty string : left for LTR or right for RTL</li></ul> - * @param string $filehash File hash used to build unique file names. - * @author Nicola Asuni - * @protected - * @since 4.3.007 (2008-12-04) - * @see Image() - */ - protected function ImagePngAlpha($file, $x, $y, $wpx, $hpx, $w, $h, $type, $link, $align, $resize, $dpi, $palign, $filehash='') { - // create temp images - if (empty($filehash)) { - $filehash = md5($file); - } - // create temp image file (without alpha channel) - $tempfile_plain = K_PATH_CACHE.'__tcpdf_'.$this->file_id.'_imgmask_plain_'.$filehash; - // create temp alpha file - $tempfile_alpha = K_PATH_CACHE.'__tcpdf_'.$this->file_id.'_imgmask_alpha_'.$filehash; - $parsed = false; - $parse_error = ''; - // ImageMagick extension - if (($parsed === false) AND extension_loaded('imagick')) { - try { - // ImageMagick library - $img = new Imagick(); - $img->readImage($file); - // clone image object - $imga = TCPDF_STATIC::objclone($img); - // extract alpha channel - if (method_exists($img, 'setImageAlphaChannel') AND defined('Imagick::ALPHACHANNEL_EXTRACT')) { - $img->setImageAlphaChannel(Imagick::ALPHACHANNEL_EXTRACT); - } else { - $img->separateImageChannel(8); // 8 = (imagick::CHANNEL_ALPHA | imagick::CHANNEL_OPACITY | imagick::CHANNEL_MATTE); - $img->negateImage(true); - } - $img->setImageFormat('png'); - $img->writeImage($tempfile_alpha); - // remove alpha channel - if (method_exists($imga, 'setImageMatte')) { - $imga->setImageMatte(false); - } else { - $imga->separateImageChannel(39); // 39 = (imagick::CHANNEL_ALL & ~(imagick::CHANNEL_ALPHA | imagick::CHANNEL_OPACITY | imagick::CHANNEL_MATTE)); - } - $imga->setImageFormat('png'); - $imga->writeImage($tempfile_plain); - $parsed = true; - } catch (Exception $e) { - // Imagemagick fails, try with GD - $parse_error = 'Imagick library error: '.$e->getMessage(); - } - } - // GD extension - if (($parsed === false) AND function_exists('imagecreatefrompng')) { - try { - // generate images - $img = imagecreatefrompng($file); - $imgalpha = imagecreate($wpx, $hpx); - // generate gray scale palette (0 -> 255) - for ($c = 0; $c < 256; ++$c) { - ImageColorAllocate($imgalpha, $c, $c, $c); - } - // extract alpha channel - for ($xpx = 0; $xpx < $wpx; ++$xpx) { - for ($ypx = 0; $ypx < $hpx; ++$ypx) { - $color = imagecolorat($img, $xpx, $ypx); - // get and correct gamma color - $alpha = $this->getGDgamma($img, $color); - imagesetpixel($imgalpha, (int) $xpx, (int) $ypx, (int) $alpha); - } - } - imagepng($imgalpha, $tempfile_alpha); - imagedestroy($imgalpha); - // extract image without alpha channel - $imgplain = imagecreatetruecolor($wpx, $hpx); - imagecopy($imgplain, $img, 0, 0, 0, 0, $wpx, $hpx); - imagepng($imgplain, $tempfile_plain); - imagedestroy($imgplain); - $parsed = true; - } catch (Exception $e) { - // GD fails - $parse_error = 'GD library error: '.$e->getMessage(); - } - } - if ($parsed === false) { - if (empty($parse_error)) { - $this->Error('TCPDF requires the Imagick or GD extension to handle PNG images with alpha channel.'); - } else { - $this->Error($parse_error); - } - } - // embed mask image - $imgmask = $this->Image($tempfile_alpha, $x, $y, $w, $h, 'PNG', '', '', $resize, $dpi, '', true, false); - // embed image, masked with previously embedded mask - $this->Image($tempfile_plain, $x, $y, $w, $h, $type, $link, $align, $resize, $dpi, $palign, false, $imgmask); - } - - /** - * Get the GD-corrected PNG gamma value from alpha color - * @param resource $img GD image Resource ID. - * @param int $c alpha color - * @protected - * @since 4.3.007 (2008-12-04) - */ - protected function getGDgamma($img, $c) { - if (!isset($this->gdgammacache['#'.$c])) { - $colors = imagecolorsforindex($img, $c); - // GD alpha is only 7 bit (0 -> 127) - $this->gdgammacache['#'.$c] = (int) (((127 - $colors['alpha']) / 127) * 255); - // correct gamma - $this->gdgammacache['#'.$c] = (int) (pow(($this->gdgammacache['#'.$c] / 255), 2.2) * 255); - // store the latest values on cache to improve performances - if (count($this->gdgammacache) > 8) { - // remove one element from the cache array - array_shift($this->gdgammacache); - } - } - return $this->gdgammacache['#'.$c]; - } - - /** - * Performs a line break. - * The current abscissa goes back to the left margin and the ordinate increases by the amount passed in parameter. - * @param float|null $h The height of the break. By default, the value equals the height of the last printed cell. - * @param boolean $cell if true add the current left (or right o for RTL) padding to the X coordinate - * @public - * @since 1.0 - * @see Cell() - */ - public function Ln($h=null, $cell=false) { - if (($this->num_columns > 1) AND ($this->y == $this->columns[$this->current_column]['y']) AND isset($this->columns[$this->current_column]['x']) AND ($this->x == $this->columns[$this->current_column]['x'])) { - // revove vertical space from the top of the column - return; - } - if ($cell) { - if ($this->rtl) { - $cellpadding = $this->cell_padding['R']; - } else { - $cellpadding = $this->cell_padding['L']; - } - } else { - $cellpadding = 0; - } - if ($this->rtl) { - $this->x = $this->w - $this->rMargin - $cellpadding; - } else { - $this->x = $this->lMargin + $cellpadding; - } - if (TCPDF_STATIC::empty_string($h)) { - $h = $this->lasth; - } - $this->y += $h; - $this->newline = true; - } - - /** - * Returns the relative X value of current position. - * The value is relative to the left border for LTR languages and to the right border for RTL languages. - * @return float - * @public - * @since 1.2 - * @see SetX(), GetY(), SetY() - */ - public function GetX() { - //Get x position - if ($this->rtl) { - return ($this->w - $this->x); - } else { - return $this->x; - } - } - - /** - * Returns the absolute X value of current position. - * @return float - * @public - * @since 1.2 - * @see SetX(), GetY(), SetY() - */ - public function GetAbsX() { - return $this->x; - } - - /** - * Returns the ordinate of the current position. - * @return float - * @public - * @since 1.0 - * @see SetY(), GetX(), SetX() - */ - public function GetY() { - return $this->y; - } - - /** - * Defines the abscissa of the current position. - * If the passed value is negative, it is relative to the right of the page (or left if language is RTL). - * @param float $x The value of the abscissa in user units. - * @param boolean $rtloff if true always uses the page top-left corner as origin of axis. - * @public - * @since 1.2 - * @see GetX(), GetY(), SetY(), SetXY() - */ - public function setX($x, $rtloff=false) { - $x = floatval($x); - if (!$rtloff AND $this->rtl) { - if ($x >= 0) { - $this->x = $this->w - $x; - } else { - $this->x = abs($x); - } - } else { - if ($x >= 0) { - $this->x = $x; - } else { - $this->x = $this->w + $x; - } - } - if ($this->x < 0) { - $this->x = 0; - } - if ($this->x > $this->w) { - $this->x = $this->w; - } - } - - /** - * Moves the current abscissa back to the left margin and sets the ordinate. - * If the passed value is negative, it is relative to the bottom of the page. - * @param float $y The value of the ordinate in user units. - * @param bool $resetx if true (default) reset the X position. - * @param boolean $rtloff if true always uses the page top-left corner as origin of axis. - * @public - * @since 1.0 - * @see GetX(), GetY(), SetY(), SetXY() - */ - public function setY($y, $resetx=true, $rtloff=false) { - $y = floatval($y); - if ($resetx) { - //reset x - if (!$rtloff AND $this->rtl) { - $this->x = $this->w - $this->rMargin; - } else { - $this->x = $this->lMargin; - } - } - if ($y >= 0) { - $this->y = $y; - } else { - $this->y = $this->h + $y; - } - if ($this->y < 0) { - $this->y = 0; - } - if ($this->y > $this->h) { - $this->y = $this->h; - } - } - - /** - * Defines the abscissa and ordinate of the current position. - * If the passed values are negative, they are relative respectively to the right and bottom of the page. - * @param float $x The value of the abscissa. - * @param float $y The value of the ordinate. - * @param boolean $rtloff if true always uses the page top-left corner as origin of axis. - * @public - * @since 1.2 - * @see SetX(), SetY() - */ - public function setXY($x, $y, $rtloff=false) { - $this->setY($y, false, $rtloff); - $this->setX($x, $rtloff); - } - - /** - * Set the absolute X coordinate of the current pointer. - * @param float $x The value of the abscissa in user units. - * @public - * @since 5.9.186 (2012-09-13) - * @see setAbsX(), setAbsY(), SetAbsXY() - */ - public function setAbsX($x) { - $this->x = floatval($x); - } - - /** - * Set the absolute Y coordinate of the current pointer. - * @param float $y (float) The value of the ordinate in user units. - * @public - * @since 5.9.186 (2012-09-13) - * @see setAbsX(), setAbsY(), SetAbsXY() - */ - public function setAbsY($y) { - $this->y = floatval($y); - } - - /** - * Set the absolute X and Y coordinates of the current pointer. - * @param float $x The value of the abscissa in user units. - * @param float $y (float) The value of the ordinate in user units. - * @public - * @since 5.9.186 (2012-09-13) - * @see setAbsX(), setAbsY(), SetAbsXY() - */ - public function setAbsXY($x, $y) { - $this->setAbsX($x); - $this->setAbsY($y); - } - - /** - * Send the document to a given destination: string, local file or browser. - * In the last case, the plug-in may be used (if present) or a download ("Save as" dialog box) may be forced.<br /> - * The method first calls Close() if necessary to terminate the document. - * @param string $name The name of the file when saved. Note that special characters are removed and blanks characters are replaced with the underscore character. - * @param string $dest Destination where to send the document. It can take one of the following values:<ul><li>I: send the file inline to the browser (default). The plug-in is used if available. The name given by name is used when one selects the "Save as" option on the link generating the PDF.</li><li>D: send to the browser and force a file download with the name given by name.</li><li>F: save to a local server file with the name given by name.</li><li>S: return the document as a string (name is ignored).</li><li>FI: equivalent to F + I option</li><li>FD: equivalent to F + D option</li><li>E: return the document as base64 mime multi-part email attachment (RFC 2045)</li></ul> - * @return string - * @public - * @since 1.0 - * @see Close() - */ - public function Output($name='doc.pdf', $dest='I') { - //Output PDF to some destination - //Finish document if necessary - if ($this->state < 3) { - $this->Close(); - } - //Normalize parameters - if (is_bool($dest)) { - $dest = $dest ? 'D' : 'F'; - } - $dest = strtoupper($dest); - if ($dest[0] != 'F') { - $name = preg_replace('/[\s]+/', '_', $name); - $name = preg_replace('/[^a-zA-Z0-9_\.-]/', '', $name); - } - if ($this->sign) { - // *** apply digital signature to the document *** - // get the document content - $pdfdoc = $this->getBuffer(); - // remove last newline - $pdfdoc = substr($pdfdoc, 0, -1); - // remove filler space - $byterange_string_len = strlen(TCPDF_STATIC::$byterange_string); - // define the ByteRange - $byte_range = array(); - $byte_range[0] = 0; - $byte_range[1] = strpos($pdfdoc, TCPDF_STATIC::$byterange_string) + $byterange_string_len + 10; - $byte_range[2] = $byte_range[1] + $this->signature_max_length + 2; - $byte_range[3] = strlen($pdfdoc) - $byte_range[2]; - $pdfdoc = substr($pdfdoc, 0, $byte_range[1]).substr($pdfdoc, $byte_range[2]); - // replace the ByteRange - $byterange = sprintf('/ByteRange[0 %u %u %u]', $byte_range[1], $byte_range[2], $byte_range[3]); - $byterange .= str_repeat(' ', ($byterange_string_len - strlen($byterange))); - $pdfdoc = str_replace(TCPDF_STATIC::$byterange_string, $byterange, $pdfdoc); - // write the document to a temporary folder - $tempdoc = TCPDF_STATIC::getObjFilename('doc', $this->file_id); - $f = TCPDF_STATIC::fopenLocal($tempdoc, 'wb'); - if (!$f) { - $this->Error('Unable to create temporary file: '.$tempdoc); - } - $pdfdoc_length = strlen($pdfdoc); - fwrite($f, $pdfdoc, $pdfdoc_length); - fclose($f); - // get digital signature via openssl library - $tempsign = TCPDF_STATIC::getObjFilename('sig', $this->file_id); - if (empty($this->signature_data['extracerts'])) { - openssl_pkcs7_sign($tempdoc, $tempsign, $this->signature_data['signcert'], array($this->signature_data['privkey'], $this->signature_data['password']), array(), PKCS7_BINARY | PKCS7_DETACHED); - } else { - openssl_pkcs7_sign($tempdoc, $tempsign, $this->signature_data['signcert'], array($this->signature_data['privkey'], $this->signature_data['password']), array(), PKCS7_BINARY | PKCS7_DETACHED, $this->signature_data['extracerts']); - } - // read signature - $signature = file_get_contents($tempsign); - // extract signature - $signature = substr($signature, $pdfdoc_length); - $signature = substr($signature, (strpos($signature, "%%EOF\n\n------") + 13)); - $tmparr = explode("\n\n", $signature); - $signature = $tmparr[1]; - // decode signature - $signature = base64_decode(trim($signature)); - // add TSA timestamp to signature - $signature = $this->applyTSA($signature); - // convert signature to hex - $signature = current(unpack('H*', $signature)); - $signature = str_pad($signature, $this->signature_max_length, '0'); - // Add signature to the document - $this->buffer = substr($pdfdoc, 0, $byte_range[1]).'<'.$signature.'>'.substr($pdfdoc, $byte_range[1]); - $this->bufferlen = strlen($this->buffer); - } - switch($dest) { - case 'I': { - // Send PDF to the standard output - if (ob_get_contents()) { - $this->Error('Some data has already been output, can\'t send PDF file'); - } - if (php_sapi_name() != 'cli') { - // send output to a browser - header('Content-Type: application/pdf'); - if (headers_sent()) { - $this->Error('Some data has already been output to browser, can\'t send PDF file'); - } - header('Cache-Control: private, must-revalidate, post-check=0, pre-check=0, max-age=1'); - //header('Cache-Control: public, must-revalidate, max-age=0'); // HTTP/1.1 - header('Pragma: public'); - header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past - header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); - header('Content-Disposition: inline; filename="'.basename($name).'"'); - TCPDF_STATIC::sendOutputData($this->getBuffer(), $this->bufferlen); - } else { - echo $this->getBuffer(); - } - break; - } - case 'D': { - // download PDF as file - if (ob_get_contents()) { - $this->Error('Some data has already been output, can\'t send PDF file'); - } - header('Content-Description: File Transfer'); - if (headers_sent()) { - $this->Error('Some data has already been output to browser, can\'t send PDF file'); - } - header('Cache-Control: private, must-revalidate, post-check=0, pre-check=0, max-age=1'); - //header('Cache-Control: public, must-revalidate, max-age=0'); // HTTP/1.1 - header('Pragma: public'); - header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past - header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); - // force download dialog - if (strpos(php_sapi_name(), 'cgi') === false) { - header('Content-Type: application/force-download'); - header('Content-Type: application/octet-stream', false); - header('Content-Type: application/download', false); - header('Content-Type: application/pdf', false); - } else { - header('Content-Type: application/pdf'); - } - // use the Content-Disposition header to supply a recommended filename - header('Content-Disposition: attachment; filename="'.basename($name).'"'); - header('Content-Transfer-Encoding: binary'); - TCPDF_STATIC::sendOutputData($this->getBuffer(), $this->bufferlen); - break; - } - case 'F': - case 'FI': - case 'FD': { - // save PDF to a local file - $f = TCPDF_STATIC::fopenLocal($name, 'wb'); - if (!$f) { - $this->Error('Unable to create output file: '.$name); - } - fwrite($f, $this->getBuffer(), $this->bufferlen); - fclose($f); - if ($dest == 'FI') { - // send headers to browser - header('Content-Type: application/pdf'); - header('Cache-Control: private, must-revalidate, post-check=0, pre-check=0, max-age=1'); - //header('Cache-Control: public, must-revalidate, max-age=0'); // HTTP/1.1 - header('Pragma: public'); - header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past - header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); - header('Content-Disposition: inline; filename="'.basename($name).'"'); - TCPDF_STATIC::sendOutputData(file_get_contents($name), filesize($name)); - } elseif ($dest == 'FD') { - // send headers to browser - if (ob_get_contents()) { - $this->Error('Some data has already been output, can\'t send PDF file'); - } - header('Content-Description: File Transfer'); - if (headers_sent()) { - $this->Error('Some data has already been output to browser, can\'t send PDF file'); - } - header('Cache-Control: private, must-revalidate, post-check=0, pre-check=0, max-age=1'); - header('Pragma: public'); - header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past - header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); - // force download dialog - if (strpos(php_sapi_name(), 'cgi') === false) { - header('Content-Type: application/force-download'); - header('Content-Type: application/octet-stream', false); - header('Content-Type: application/download', false); - header('Content-Type: application/pdf', false); - } else { - header('Content-Type: application/pdf'); - } - // use the Content-Disposition header to supply a recommended filename - header('Content-Disposition: attachment; filename="'.basename($name).'"'); - header('Content-Transfer-Encoding: binary'); - TCPDF_STATIC::sendOutputData(file_get_contents($name), filesize($name)); - } - break; - } - case 'E': { - // return PDF as base64 mime multi-part email attachment (RFC 2045) - $retval = 'Content-Type: application/pdf;'."\r\n"; - $retval .= ' name="'.$name.'"'."\r\n"; - $retval .= 'Content-Transfer-Encoding: base64'."\r\n"; - $retval .= 'Content-Disposition: attachment;'."\r\n"; - $retval .= ' filename="'.$name.'"'."\r\n\r\n"; - $retval .= chunk_split(base64_encode($this->getBuffer()), 76, "\r\n"); - return $retval; - } - case 'S': { - // returns PDF as a string - return $this->getBuffer(); - } - default: { - $this->Error('Incorrect output destination: '.$dest); - } - } - return ''; - } - - protected static $cleaned_ids = array(); - /** - * Unset all class variables except the following critical variables. - * @param boolean $destroyall if true destroys all class variables, otherwise preserves critical variables. - * @param boolean $preserve_objcopy if true preserves the objcopy variable - * @public - * @since 4.5.016 (2009-02-24) - */ - public function _destroy($destroyall=false, $preserve_objcopy=false) { - if (isset(self::$cleaned_ids[$this->file_id])) { - $destroyall = false; - } - if ($destroyall AND !$preserve_objcopy && isset($this->file_id)) { - self::$cleaned_ids[$this->file_id] = true; - // remove all temporary files - if ($handle = @opendir(K_PATH_CACHE)) { - while ( false !== ( $file_name = readdir( $handle ) ) ) { - if (strpos($file_name, '__tcpdf_'.$this->file_id.'_') === 0) { - unlink(K_PATH_CACHE.$file_name); - } - } - closedir($handle); - } - if (isset($this->imagekeys)) { - foreach($this->imagekeys as $file) { - if (strpos($file, K_PATH_CACHE) === 0 && TCPDF_STATIC::file_exists($file)) { - @unlink($file); - } - } - } - } - $preserve = array( - 'file_id', - 'state', - 'bufferlen', - 'buffer', - 'cached_files', - 'imagekeys', - 'sign', - 'signature_data', - 'signature_max_length', - 'byterange_string', - 'tsa_timestamp', - 'tsa_data' - ); - foreach (array_keys(get_object_vars($this)) as $val) { - if ($destroyall OR !in_array($val, $preserve)) { - if ((!$preserve_objcopy OR ($val != 'objcopy')) AND ($val != 'file_id') AND isset($this->$val)) { - unset($this->$val); - } - } - } - } - - /** - * Check for locale-related bug - * @protected - */ - protected function _dochecks() { - //Check for locale-related bug - if (1.1 == 1) { - $this->Error('Don\'t alter the locale before including class file'); - } - //Check for decimal separator - if (sprintf('%.1F', 1.0) != '1.0') { - setlocale(LC_NUMERIC, 'C'); - } - } - - /** - * Return an array containing variations for the basic page number alias. - * @param string $a Base alias. - * @return array of page number aliases - * @protected - */ - protected function getInternalPageNumberAliases($a= '') { - $alias = array(); - // build array of Unicode + ASCII variants (the order is important) - $alias = array('u' => array(), 'a' => array()); - $u = '{'.$a.'}'; - $alias['u'][] = TCPDF_STATIC::_escape($u); - if ($this->isunicode) { - $alias['u'][] = TCPDF_STATIC::_escape(TCPDF_FONTS::UTF8ToLatin1($u, $this->isunicode, $this->CurrentFont)); - $alias['u'][] = TCPDF_STATIC::_escape(TCPDF_FONTS::utf8StrRev($u, false, $this->tmprtl, $this->isunicode, $this->CurrentFont)); - $alias['a'][] = TCPDF_STATIC::_escape(TCPDF_FONTS::UTF8ToLatin1($a, $this->isunicode, $this->CurrentFont)); - $alias['a'][] = TCPDF_STATIC::_escape(TCPDF_FONTS::utf8StrRev($a, false, $this->tmprtl, $this->isunicode, $this->CurrentFont)); - } - $alias['a'][] = TCPDF_STATIC::_escape($a); - return $alias; - } - - /** - * Return an array containing all internal page aliases. - * @return array of page number aliases - * @protected - */ - protected function getAllInternalPageNumberAliases() { - $basic_alias = array(TCPDF_STATIC::$alias_tot_pages, TCPDF_STATIC::$alias_num_page, TCPDF_STATIC::$alias_group_tot_pages, TCPDF_STATIC::$alias_group_num_page, TCPDF_STATIC::$alias_right_shift); - $pnalias = array(); - foreach($basic_alias as $k => $a) { - $pnalias[$k] = $this->getInternalPageNumberAliases($a); - } - return $pnalias; - } - - /** - * Replace right shift page number aliases with spaces to correct right alignment. - * This works perfectly only when using monospaced fonts. - * @param string $page Page content. - * @param array $aliases Array of page aliases. - * @param int $diff initial difference to add. - * @return string replaced page content. - * @protected - */ - protected function replaceRightShiftPageNumAliases($page, $aliases, $diff) { - foreach ($aliases as $type => $alias) { - foreach ($alias as $a) { - // find position of compensation factor - $startnum = (strpos($a, ':') + 1); - $a = substr($a, 0, $startnum); - if (($pos = strpos($page, $a)) !== false) { - // end of alias - $endnum = strpos($page, '}', $pos); - // string to be replaced - $aa = substr($page, $pos, ($endnum - $pos + 1)); - // get compensation factor - $ratio = substr($page, ($pos + $startnum), ($endnum - $pos - $startnum)); - $ratio = preg_replace('/[^0-9\.]/', '', $ratio); - $ratio = floatval($ratio); - if ($type == 'u') { - $chrdiff = floor(($diff + 12) * $ratio); - $shift = str_repeat(' ', $chrdiff); - $shift = TCPDF_FONTS::UTF8ToUTF16BE($shift, false, $this->isunicode, $this->CurrentFont); - } else { - $chrdiff = floor(($diff + 11) * $ratio); - $shift = str_repeat(' ', $chrdiff); - } - $page = str_replace($aa, $shift, $page); - } - } - } - return $page; - } - - /** - * Set page boxes to be included on page descriptions. - * @param array $boxes Array of page boxes to set on document: ('MediaBox', 'CropBox', 'BleedBox', 'TrimBox', 'ArtBox'). - * @protected - */ - protected function setPageBoxTypes($boxes) { - $this->page_boxes = array(); - foreach ($boxes as $box) { - if (in_array($box, TCPDF_STATIC::$pageboxes)) { - $this->page_boxes[] = $box; - } - } - } - - /** - * Output pages (and replace page number aliases). - * @protected - */ - protected function _putpages() { - $filter = ($this->compress) ? '/Filter /FlateDecode ' : ''; - // get internal aliases for page numbers - $pnalias = $this->getAllInternalPageNumberAliases(); - $num_pages = $this->numpages; - $ptpa = TCPDF_STATIC::formatPageNumber(($this->starting_page_number + $num_pages - 1)); - $ptpu = TCPDF_FONTS::UTF8ToUTF16BE($ptpa, false, $this->isunicode, $this->CurrentFont); - $ptp_num_chars = $this->GetNumChars($ptpa); - $pagegroupnum = 0; - $groupnum = 0; - $ptgu = 1; - $ptga = 1; - $ptg_num_chars = 1; - for ($n = 1; $n <= $num_pages; ++$n) { - // get current page - $temppage = $this->getPageBuffer($n); - $pagelen = strlen($temppage); - // set replacements for total pages number - $pnpa = TCPDF_STATIC::formatPageNumber(($this->starting_page_number + $n - 1)); - $pnpu = TCPDF_FONTS::UTF8ToUTF16BE($pnpa, false, $this->isunicode, $this->CurrentFont); - $pnp_num_chars = $this->GetNumChars($pnpa); - $pdiff = 0; // difference used for right shift alignment of page numbers - $gdiff = 0; // difference used for right shift alignment of page group numbers - if (!empty($this->pagegroups)) { - if (isset($this->newpagegroup[$n])) { - $pagegroupnum = 0; - ++$groupnum; - $ptga = TCPDF_STATIC::formatPageNumber($this->pagegroups[$groupnum]); - $ptgu = TCPDF_FONTS::UTF8ToUTF16BE($ptga, false, $this->isunicode, $this->CurrentFont); - $ptg_num_chars = $this->GetNumChars($ptga); - } - ++$pagegroupnum; - $pnga = TCPDF_STATIC::formatPageNumber($pagegroupnum); - $pngu = TCPDF_FONTS::UTF8ToUTF16BE($pnga, false, $this->isunicode, $this->CurrentFont); - $png_num_chars = $this->GetNumChars($pnga); - // replace page numbers - $replace = array(); - $replace[] = array($ptgu, $ptg_num_chars, 9, $pnalias[2]['u']); - $replace[] = array($ptga, $ptg_num_chars, 7, $pnalias[2]['a']); - $replace[] = array($pngu, $png_num_chars, 9, $pnalias[3]['u']); - $replace[] = array($pnga, $png_num_chars, 7, $pnalias[3]['a']); - list($temppage, $gdiff) = TCPDF_STATIC::replacePageNumAliases($temppage, $replace, $gdiff); - } - // replace page numbers - $replace = array(); - $replace[] = array($ptpu, $ptp_num_chars, 9, $pnalias[0]['u']); - $replace[] = array($ptpa, $ptp_num_chars, 7, $pnalias[0]['a']); - $replace[] = array($pnpu, $pnp_num_chars, 9, $pnalias[1]['u']); - $replace[] = array($pnpa, $pnp_num_chars, 7, $pnalias[1]['a']); - list($temppage, $pdiff) = TCPDF_STATIC::replacePageNumAliases($temppage, $replace, $pdiff); - // replace right shift alias - $temppage = $this->replaceRightShiftPageNumAliases($temppage, $pnalias[4], max($pdiff, $gdiff)); - // replace EPS marker - $temppage = str_replace($this->epsmarker, '', $temppage); - //Page - $this->page_obj_id[$n] = $this->_newobj(); - $out = '<<'; - $out .= ' /Type /Page'; - $out .= ' /Parent 1 0 R'; - if (empty($this->signature_data['approval']) OR ($this->signature_data['approval'] != 'A')) { - $out .= ' /LastModified '.$this->_datestring(0, $this->doc_modification_timestamp); - } - $out .= ' /Resources 2 0 R'; - foreach ($this->page_boxes as $box) { - $out .= ' /'.$box; - $out .= sprintf(' [%F %F %F %F]', $this->pagedim[$n][$box]['llx'], $this->pagedim[$n][$box]['lly'], $this->pagedim[$n][$box]['urx'], $this->pagedim[$n][$box]['ury']); - } - if (isset($this->pagedim[$n]['BoxColorInfo']) AND !empty($this->pagedim[$n]['BoxColorInfo'])) { - $out .= ' /BoxColorInfo <<'; - foreach ($this->page_boxes as $box) { - if (isset($this->pagedim[$n]['BoxColorInfo'][$box])) { - $out .= ' /'.$box.' <<'; - if (isset($this->pagedim[$n]['BoxColorInfo'][$box]['C'])) { - $color = $this->pagedim[$n]['BoxColorInfo'][$box]['C']; - $out .= ' /C ['; - $out .= sprintf(' %F %F %F', ($color[0] / 255), ($color[1] / 255), ($color[2] / 255)); - $out .= ' ]'; - } - if (isset($this->pagedim[$n]['BoxColorInfo'][$box]['W'])) { - $out .= ' /W '.($this->pagedim[$n]['BoxColorInfo'][$box]['W'] * $this->k); - } - if (isset($this->pagedim[$n]['BoxColorInfo'][$box]['S'])) { - $out .= ' /S /'.$this->pagedim[$n]['BoxColorInfo'][$box]['S']; - } - if (isset($this->pagedim[$n]['BoxColorInfo'][$box]['D'])) { - $dashes = $this->pagedim[$n]['BoxColorInfo'][$box]['D']; - $out .= ' /D ['; - foreach ($dashes as $dash) { - $out .= sprintf(' %F', ($dash * $this->k)); - } - $out .= ' ]'; - } - $out .= ' >>'; - } - } - $out .= ' >>'; - } - $out .= ' /Contents '.($this->n + 1).' 0 R'; - $out .= ' /Rotate '.$this->pagedim[$n]['Rotate']; - if (!$this->pdfa_mode || $this->pdfa_version >= 2) { - $out .= ' /Group << /Type /Group /S /Transparency /CS /DeviceRGB >>'; - } - if (isset($this->pagedim[$n]['trans']) AND !empty($this->pagedim[$n]['trans'])) { - // page transitions - if (isset($this->pagedim[$n]['trans']['Dur'])) { - $out .= ' /Dur '.$this->pagedim[$n]['trans']['Dur']; - } - $out .= ' /Trans <<'; - $out .= ' /Type /Trans'; - if (isset($this->pagedim[$n]['trans']['S'])) { - $out .= ' /S /'.$this->pagedim[$n]['trans']['S']; - } - if (isset($this->pagedim[$n]['trans']['D'])) { - $out .= ' /D '.$this->pagedim[$n]['trans']['D']; - } - if (isset($this->pagedim[$n]['trans']['Dm'])) { - $out .= ' /Dm /'.$this->pagedim[$n]['trans']['Dm']; - } - if (isset($this->pagedim[$n]['trans']['M'])) { - $out .= ' /M /'.$this->pagedim[$n]['trans']['M']; - } - if (isset($this->pagedim[$n]['trans']['Di'])) { - $out .= ' /Di '.$this->pagedim[$n]['trans']['Di']; - } - if (isset($this->pagedim[$n]['trans']['SS'])) { - $out .= ' /SS '.$this->pagedim[$n]['trans']['SS']; - } - if (isset($this->pagedim[$n]['trans']['B'])) { - $out .= ' /B '.$this->pagedim[$n]['trans']['B']; - } - $out .= ' >>'; - } - $out .= $this->_getannotsrefs($n); - $out .= ' /PZ '.$this->pagedim[$n]['PZ']; - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - //Page content - $p = ($this->compress) ? gzcompress($temppage) : $temppage; - $this->_newobj(); - $p = $this->_getrawstream($p); - $this->_out('<<'.$filter.'/Length '.strlen($p).'>> stream'."\n".$p."\n".'endstream'."\n".'endobj'); - } - //Pages root - $out = $this->_getobj(1)."\n"; - $out .= '<< /Type /Pages /Kids ['; - foreach($this->page_obj_id as $page_obj) { - $out .= ' '.$page_obj.' 0 R'; - } - $out .= ' ] /Count '.$num_pages.' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - } - - /** - * Get references to page annotations. - * @param int $n page number - * @return string - * @protected - * @author Nicola Asuni - * @since 5.0.010 (2010-05-17) - */ - protected function _getannotsrefs($n) { - if (!(isset($this->PageAnnots[$n]) OR ($this->sign AND isset($this->signature_data['cert_type'])))) { - return ''; - } - $out = ' /Annots ['; - if (isset($this->PageAnnots[$n])) { - foreach ($this->PageAnnots[$n] as $key => $val) { - if (!in_array($val['n'], $this->radio_groups)) { - $out .= ' '.$val['n'].' 0 R'; - } - } - // add radiobutton groups - if (isset($this->radiobutton_groups[$n])) { - foreach ($this->radiobutton_groups[$n] as $key => $data) { - if (isset($data['n'])) { - $out .= ' '.$data['n'].' 0 R'; - } - } - } - } - if ($this->sign AND ($n == $this->signature_appearance['page']) AND isset($this->signature_data['cert_type'])) { - // set reference for signature object - $out .= ' '.$this->sig_obj_id.' 0 R'; - } - if (!empty($this->empty_signature_appearance)) { - foreach ($this->empty_signature_appearance as $esa) { - if ($esa['page'] == $n) { - // set reference for empty signature objects - $out .= ' '.$esa['objid'].' 0 R'; - } - } - } - $out .= ' ]'; - return $out; - } - - /** - * Output annotations objects for all pages. - * !!! THIS METHOD IS NOT YET COMPLETED !!! - * See section 12.5 of PDF 32000_2008 reference. - * @protected - * @author Nicola Asuni - * @since 4.0.018 (2008-08-06) - */ - protected function _putannotsobjs() { - // reset object counter - for ($n=1; $n <= $this->numpages; ++$n) { - if (isset($this->PageAnnots[$n])) { - // set page annotations - foreach ($this->PageAnnots[$n] as $key => $pl) { - $annot_obj_id = $this->PageAnnots[$n][$key]['n']; - // create annotation object for grouping radiobuttons - if (isset($this->radiobutton_groups[$n][$pl['txt']]) AND is_array($this->radiobutton_groups[$n][$pl['txt']])) { - $radio_button_obj_id = $this->radiobutton_groups[$n][$pl['txt']]['n']; - $annots = '<<'; - $annots .= ' /Type /Annot'; - $annots .= ' /Subtype /Widget'; - $annots .= ' /Rect [0 0 0 0]'; - if ($this->radiobutton_groups[$n][$pl['txt']]['#readonly#']) { - // read only - $annots .= ' /F 68'; - $annots .= ' /Ff 49153'; - } else { - $annots .= ' /F 4'; // default print for PDF/A - $annots .= ' /Ff 49152'; - } - $annots .= ' /T '.$this->_datastring($pl['txt'], $radio_button_obj_id); - if (isset($pl['opt']['tu']) AND is_string($pl['opt']['tu'])) { - $annots .= ' /TU '.$this->_datastring($pl['opt']['tu'], $radio_button_obj_id); - } - $annots .= ' /FT /Btn'; - $annots .= ' /Kids ['; - $defval = ''; - foreach ($this->radiobutton_groups[$n][$pl['txt']] as $key => $data) { - if (isset($data['kid'])) { - $annots .= ' '.$data['kid'].' 0 R'; - if ($data['def'] !== 'Off') { - $defval = $data['def']; - } - } - } - $annots .= ' ]'; - if (!empty($defval)) { - $annots .= ' /V /'.$defval; - } - $annots .= ' >>'; - $this->_out($this->_getobj($radio_button_obj_id)."\n".$annots."\n".'endobj'); - $this->form_obj_id[] = $radio_button_obj_id; - // store object id to be used on Parent entry of Kids - $this->radiobutton_groups[$n][$pl['txt']] = $radio_button_obj_id; - } - $formfield = false; - $pl['opt'] = array_change_key_case($pl['opt'], CASE_LOWER); - $a = $pl['x'] * $this->k; - $b = $this->pagedim[$n]['h'] - (($pl['y'] + $pl['h']) * $this->k); - $c = $pl['w'] * $this->k; - $d = $pl['h'] * $this->k; - $rect = sprintf('%F %F %F %F', $a, $b, $a+$c, $b+$d); - // create new annotation object - $annots = '<</Type /Annot'; - $annots .= ' /Subtype /'.$pl['opt']['subtype']; - $annots .= ' /Rect ['.$rect.']'; - $ft = array('Btn', 'Tx', 'Ch', 'Sig'); - if (isset($pl['opt']['ft']) AND in_array($pl['opt']['ft'], $ft)) { - $annots .= ' /FT /'.$pl['opt']['ft']; - $formfield = true; - } - if ($pl['opt']['subtype'] !== 'Link') { - $annots .= ' /Contents '.$this->_textstring($pl['txt'], $annot_obj_id); - } - $annots .= ' /P '.$this->page_obj_id[$n].' 0 R'; - $annots .= ' /NM '.$this->_datastring(sprintf('%04u-%04u', $n, $key), $annot_obj_id); - $annots .= ' /M '.$this->_datestring($annot_obj_id, $this->doc_modification_timestamp); - if (isset($pl['opt']['f'])) { - $fval = 0; - if (is_array($pl['opt']['f'])) { - foreach ($pl['opt']['f'] as $f) { - switch (strtolower($f)) { - case 'invisible': { - $fval += 1 << 0; - break; - } - case 'hidden': { - $fval += 1 << 1; - break; - } - case 'print': { - $fval += 1 << 2; - break; - } - case 'nozoom': { - $fval += 1 << 3; - break; - } - case 'norotate': { - $fval += 1 << 4; - break; - } - case 'noview': { - $fval += 1 << 5; - break; - } - case 'readonly': { - $fval += 1 << 6; - break; - } - case 'locked': { - $fval += 1 << 8; - break; - } - case 'togglenoview': { - $fval += 1 << 9; - break; - } - case 'lockedcontents': { - $fval += 1 << 10; - break; - } - default: { - break; - } - } - } - } else { - $fval = intval($pl['opt']['f']); - } - } else { - $fval = 4; - } - if ($this->pdfa_mode) { - // force print flag for PDF/A mode - $fval |= 4; - } - $annots .= ' /F '.intval($fval); - if (isset($pl['opt']['as']) AND is_string($pl['opt']['as'])) { - $annots .= ' /AS /'.$pl['opt']['as']; - } - if (isset($pl['opt']['ap'])) { - // appearance stream - $annots .= ' /AP <<'; - if (is_array($pl['opt']['ap'])) { - foreach ($pl['opt']['ap'] as $apmode => $apdef) { - // $apmode can be: n = normal; r = rollover; d = down; - $annots .= ' /'.strtoupper($apmode); - if (is_array($apdef)) { - $annots .= ' <<'; - foreach ($apdef as $apstate => $stream) { - // reference to XObject that define the appearance for this mode-state - $apsobjid = $this->_putAPXObject($c, $d, $stream); - $annots .= ' /'.$apstate.' '.$apsobjid.' 0 R'; - } - $annots .= ' >>'; - } else { - // reference to XObject that define the appearance for this mode - $apsobjid = $this->_putAPXObject($c, $d, $apdef); - $annots .= ' '.$apsobjid.' 0 R'; - } - } - } else { - $annots .= $pl['opt']['ap']; - } - $annots .= ' >>'; - } - if (isset($pl['opt']['bs']) AND (is_array($pl['opt']['bs']))) { - $annots .= ' /BS <<'; - $annots .= ' /Type /Border'; - if (isset($pl['opt']['bs']['w'])) { - $annots .= ' /W '.intval($pl['opt']['bs']['w']); - } - $bstyles = array('S', 'D', 'B', 'I', 'U'); - if (isset($pl['opt']['bs']['s']) AND in_array($pl['opt']['bs']['s'], $bstyles)) { - $annots .= ' /S /'.$pl['opt']['bs']['s']; - } - if (isset($pl['opt']['bs']['d']) AND (is_array($pl['opt']['bs']['d']))) { - $annots .= ' /D ['; - foreach ($pl['opt']['bs']['d'] as $cord) { - $annots .= ' '.intval($cord); - } - $annots .= ']'; - } - $annots .= ' >>'; - } else { - $annots .= ' /Border ['; - if (isset($pl['opt']['border']) AND (count($pl['opt']['border']) >= 3)) { - $annots .= intval($pl['opt']['border'][0]).' '; - $annots .= intval($pl['opt']['border'][1]).' '; - $annots .= intval($pl['opt']['border'][2]); - if (isset($pl['opt']['border'][3]) AND is_array($pl['opt']['border'][3])) { - $annots .= ' ['; - foreach ($pl['opt']['border'][3] as $dash) { - $annots .= intval($dash).' '; - } - $annots .= ']'; - } - } else { - $annots .= '0 0 0'; - } - $annots .= ']'; - } - if (isset($pl['opt']['be']) AND (is_array($pl['opt']['be']))) { - $annots .= ' /BE <<'; - $bstyles = array('S', 'C'); - if (isset($pl['opt']['be']['s']) AND in_array($pl['opt']['be']['s'], $bstyles)) { - $annots .= ' /S /'.$pl['opt']['bs']['s']; - } else { - $annots .= ' /S /S'; - } - if (isset($pl['opt']['be']['i']) AND ($pl['opt']['be']['i'] >= 0) AND ($pl['opt']['be']['i'] <= 2)) { - $annots .= ' /I '.sprintf(' %F', $pl['opt']['be']['i']); - } - $annots .= '>>'; - } - if (isset($pl['opt']['c']) AND (is_array($pl['opt']['c'])) AND !empty($pl['opt']['c'])) { - $annots .= ' /C '.TCPDF_COLORS::getColorStringFromArray($pl['opt']['c']); - } - //$annots .= ' /StructParent '; - //$annots .= ' /OC '; - $markups = array('text', 'freetext', 'line', 'square', 'circle', 'polygon', 'polyline', 'highlight', 'underline', 'squiggly', 'strikeout', 'stamp', 'caret', 'ink', 'fileattachment', 'sound'); - if (in_array(strtolower($pl['opt']['subtype']), $markups)) { - // this is a markup type - if (isset($pl['opt']['t']) AND is_string($pl['opt']['t'])) { - $annots .= ' /T '.$this->_textstring($pl['opt']['t'], $annot_obj_id); - } - //$annots .= ' /Popup '; - if (isset($pl['opt']['ca'])) { - $annots .= ' /CA '.sprintf('%F', floatval($pl['opt']['ca'])); - } - if (isset($pl['opt']['rc'])) { - $annots .= ' /RC '.$this->_textstring($pl['opt']['rc'], $annot_obj_id); - } - $annots .= ' /CreationDate '.$this->_datestring($annot_obj_id, $this->doc_creation_timestamp); - //$annots .= ' /IRT '; - if (isset($pl['opt']['subj'])) { - $annots .= ' /Subj '.$this->_textstring($pl['opt']['subj'], $annot_obj_id); - } - //$annots .= ' /RT '; - //$annots .= ' /IT '; - //$annots .= ' /ExData '; - } - $lineendings = array('Square', 'Circle', 'Diamond', 'OpenArrow', 'ClosedArrow', 'None', 'Butt', 'ROpenArrow', 'RClosedArrow', 'Slash'); - // Annotation types - switch (strtolower($pl['opt']['subtype'])) { - case 'text': { - if (isset($pl['opt']['open'])) { - $annots .= ' /Open '. (strtolower($pl['opt']['open']) == 'true' ? 'true' : 'false'); - } - $iconsapp = array('Comment', 'Help', 'Insert', 'Key', 'NewParagraph', 'Note', 'Paragraph'); - if (isset($pl['opt']['name']) AND in_array($pl['opt']['name'], $iconsapp)) { - $annots .= ' /Name /'.$pl['opt']['name']; - } else { - $annots .= ' /Name /Note'; - } - $hasStateModel = isset($pl['opt']['statemodel']); - $hasState = isset($pl['opt']['state']); - $statemodels = array('Marked', 'Review'); - if (!$hasStateModel && !$hasState) { - break; - } - if ($hasStateModel AND in_array($pl['opt']['statemodel'], $statemodels)) { - $annots .= ' /StateModel /'.$pl['opt']['statemodel']; - } else { - $pl['opt']['statemodel'] = 'Marked'; - $annots .= ' /StateModel /'.$pl['opt']['statemodel']; - } - if ($pl['opt']['statemodel'] == 'Marked') { - $states = array('Accepted', 'Unmarked'); - } else { - $states = array('Accepted', 'Rejected', 'Cancelled', 'Completed', 'None'); - } - if ($hasState AND in_array($pl['opt']['state'], $states)) { - $annots .= ' /State /'.$pl['opt']['state']; - } else { - if ($pl['opt']['statemodel'] == 'Marked') { - $annots .= ' /State /Unmarked'; - } else { - $annots .= ' /State /None'; - } - } - break; - } - case 'link': { - if (is_string($pl['txt']) && !empty($pl['txt'])) { - if ($pl['txt'][0] == '#') { - // internal destination - $annots .= ' /A <</S /GoTo /D /'.TCPDF_STATIC::encodeNameObject(substr($pl['txt'], 1)).'>>'; - } elseif ($pl['txt'][0] == '%') { - // embedded PDF file - $filename = basename(substr($pl['txt'], 1)); - $annots .= ' /A << /S /GoToE /D [0 /Fit] /NewWindow true /T << /R /C /P '.($n - 1).' /A '.$this->embeddedfiles[$filename]['a'].' >> >>'; - } elseif ($pl['txt'][0] == '*') { - // embedded generic file - $filename = basename(substr($pl['txt'], 1)); - $jsa = 'var D=event.target.doc;var MyData=D.dataObjects;for (var i in MyData) if (MyData[i].path=="'.$filename.'") D.exportDataObject( { cName : MyData[i].name, nLaunch : 2});'; - $annots .= ' /A << /S /JavaScript /JS '.$this->_textstring($jsa, $annot_obj_id).'>>'; - } else { - $parsedUrl = parse_url($pl['txt']); - if (empty($parsedUrl['scheme']) AND (!empty($parsedUrl['path']) && strtolower(substr($parsedUrl['path'], -4)) == '.pdf')) { - // relative link to a PDF file - $dest = '[0 /Fit]'; // default page 0 - if (!empty($parsedUrl['fragment'])) { - // check for named destination - $tmp = explode('=', $parsedUrl['fragment']); - $dest = '('.((count($tmp) == 2) ? $tmp[1] : $tmp[0]).')'; - } - $annots .= ' /A <</S /GoToR /D '.$dest.' /F '.$this->_datastring($this->unhtmlentities($parsedUrl['path']), $annot_obj_id).' /NewWindow true>>'; - } else { - // external URI link - $annots .= ' /A <</S /URI /URI '.$this->_datastring($this->unhtmlentities($pl['txt']), $annot_obj_id).'>>'; - } - } - } elseif (isset($this->links[$pl['txt']])) { - // internal link ID - $l = $this->links[$pl['txt']]; - if (isset($this->page_obj_id[($l['p'])])) { - $annots .= sprintf(' /Dest [%u 0 R /XYZ 0 %F null]', $this->page_obj_id[($l['p'])], ($this->pagedim[$l['p']]['h'] - ($l['y'] * $this->k))); - } - } - $hmodes = array('N', 'I', 'O', 'P'); - if (isset($pl['opt']['h']) AND in_array($pl['opt']['h'], $hmodes)) { - $annots .= ' /H /'.$pl['opt']['h']; - } else { - $annots .= ' /H /I'; - } - //$annots .= ' /PA '; - //$annots .= ' /Quadpoints '; - break; - } - case 'freetext': { - if (isset($pl['opt']['da']) AND !empty($pl['opt']['da'])) { - $annots .= ' /DA ('.$pl['opt']['da'].')'; - } - if (isset($pl['opt']['q']) AND ($pl['opt']['q'] >= 0) AND ($pl['opt']['q'] <= 2)) { - $annots .= ' /Q '.intval($pl['opt']['q']); - } - if (isset($pl['opt']['rc'])) { - $annots .= ' /RC '.$this->_textstring($pl['opt']['rc'], $annot_obj_id); - } - if (isset($pl['opt']['ds'])) { - $annots .= ' /DS '.$this->_textstring($pl['opt']['ds'], $annot_obj_id); - } - if (isset($pl['opt']['cl']) AND is_array($pl['opt']['cl'])) { - $annots .= ' /CL ['; - foreach ($pl['opt']['cl'] as $cl) { - $annots .= sprintf('%F ', $cl * $this->k); - } - $annots .= ']'; - } - $tfit = array('FreeText', 'FreeTextCallout', 'FreeTextTypeWriter'); - if (isset($pl['opt']['it']) AND in_array($pl['opt']['it'], $tfit)) { - $annots .= ' /IT /'.$pl['opt']['it']; - } - if (isset($pl['opt']['rd']) AND is_array($pl['opt']['rd'])) { - $l = $pl['opt']['rd'][0] * $this->k; - $r = $pl['opt']['rd'][1] * $this->k; - $t = $pl['opt']['rd'][2] * $this->k; - $b = $pl['opt']['rd'][3] * $this->k; - $annots .= ' /RD ['.sprintf('%F %F %F %F', $l, $r, $t, $b).']'; - } - if (isset($pl['opt']['le']) AND in_array($pl['opt']['le'], $lineendings)) { - $annots .= ' /LE /'.$pl['opt']['le']; - } - break; - } - case 'line': { - break; - } - case 'square': { - break; - } - case 'circle': { - break; - } - case 'polygon': { - break; - } - case 'polyline': { - break; - } - case 'highlight': { - break; - } - case 'underline': { - break; - } - case 'squiggly': { - break; - } - case 'strikeout': { - break; - } - case 'stamp': { - break; - } - case 'caret': { - break; - } - case 'ink': { - break; - } - case 'popup': { - break; - } - case 'fileattachment': { - if ($this->pdfa_mode && $this->pdfa_version != 3) { - // embedded files are not allowed in PDF/A mode version 1 and 2 - break; - } - if (!isset($pl['opt']['fs'])) { - break; - } - $filename = basename($pl['opt']['fs']); - if (isset($this->embeddedfiles[$filename]['f'])) { - $annots .= ' /FS '.$this->embeddedfiles[$filename]['f'].' 0 R'; - $iconsapp = array('Graph', 'Paperclip', 'PushPin', 'Tag'); - if (isset($pl['opt']['name']) AND in_array($pl['opt']['name'], $iconsapp)) { - $annots .= ' /Name /'.$pl['opt']['name']; - } else { - $annots .= ' /Name /PushPin'; - } - // index (zero-based) of the annotation in the Annots array of this page - $this->embeddedfiles[$filename]['a'] = $key; - } - break; - } - case 'sound': { - if (!isset($pl['opt']['fs'])) { - break; - } - $filename = basename($pl['opt']['fs']); - if (isset($this->embeddedfiles[$filename]['f'])) { - // ... TO BE COMPLETED ... - // /R /C /B /E /CO /CP - $annots .= ' /Sound '.$this->embeddedfiles[$filename]['f'].' 0 R'; - $iconsapp = array('Speaker', 'Mic'); - if (isset($pl['opt']['name']) AND in_array($pl['opt']['name'], $iconsapp)) { - $annots .= ' /Name /'.$pl['opt']['name']; - } else { - $annots .= ' /Name /Speaker'; - } - } - break; - } - case 'movie': { - break; - } - case 'widget': { - $hmode = array('N', 'I', 'O', 'P', 'T'); - if (isset($pl['opt']['h']) AND in_array($pl['opt']['h'], $hmode)) { - $annots .= ' /H /'.$pl['opt']['h']; - } - if (isset($pl['opt']['mk']) AND (is_array($pl['opt']['mk'])) AND !empty($pl['opt']['mk'])) { - $annots .= ' /MK <<'; - if (isset($pl['opt']['mk']['r'])) { - $annots .= ' /R '.$pl['opt']['mk']['r']; - } - if (isset($pl['opt']['mk']['bc']) AND (is_array($pl['opt']['mk']['bc']))) { - $annots .= ' /BC '.TCPDF_COLORS::getColorStringFromArray($pl['opt']['mk']['bc']); - } - if (isset($pl['opt']['mk']['bg']) AND (is_array($pl['opt']['mk']['bg']))) { - $annots .= ' /BG '.TCPDF_COLORS::getColorStringFromArray($pl['opt']['mk']['bg']); - } - if (isset($pl['opt']['mk']['ca'])) { - $annots .= ' /CA '.$pl['opt']['mk']['ca']; - } - if (isset($pl['opt']['mk']['rc'])) { - $annots .= ' /RC '.$pl['opt']['mk']['rc']; - } - if (isset($pl['opt']['mk']['ac'])) { - $annots .= ' /AC '.$pl['opt']['mk']['ac']; - } - if (isset($pl['opt']['mk']['i'])) { - $info = $this->getImageBuffer($pl['opt']['mk']['i']); - if ($info !== false) { - $annots .= ' /I '.$info['n'].' 0 R'; - } - } - if (isset($pl['opt']['mk']['ri'])) { - $info = $this->getImageBuffer($pl['opt']['mk']['ri']); - if ($info !== false) { - $annots .= ' /RI '.$info['n'].' 0 R'; - } - } - if (isset($pl['opt']['mk']['ix'])) { - $info = $this->getImageBuffer($pl['opt']['mk']['ix']); - if ($info !== false) { - $annots .= ' /IX '.$info['n'].' 0 R'; - } - } - if (isset($pl['opt']['mk']['if']) AND (is_array($pl['opt']['mk']['if'])) AND !empty($pl['opt']['mk']['if'])) { - $annots .= ' /IF <<'; - $if_sw = array('A', 'B', 'S', 'N'); - if (isset($pl['opt']['mk']['if']['sw']) AND in_array($pl['opt']['mk']['if']['sw'], $if_sw)) { - $annots .= ' /SW /'.$pl['opt']['mk']['if']['sw']; - } - $if_s = array('A', 'P'); - if (isset($pl['opt']['mk']['if']['s']) AND in_array($pl['opt']['mk']['if']['s'], $if_s)) { - $annots .= ' /S /'.$pl['opt']['mk']['if']['s']; - } - if (isset($pl['opt']['mk']['if']['a']) AND (is_array($pl['opt']['mk']['if']['a'])) AND !empty($pl['opt']['mk']['if']['a'])) { - $annots .= sprintf(' /A [%F %F]', $pl['opt']['mk']['if']['a'][0], $pl['opt']['mk']['if']['a'][1]); - } - if (isset($pl['opt']['mk']['if']['fb']) AND ($pl['opt']['mk']['if']['fb'])) { - $annots .= ' /FB true'; - } - $annots .= '>>'; - } - if (isset($pl['opt']['mk']['tp']) AND ($pl['opt']['mk']['tp'] >= 0) AND ($pl['opt']['mk']['tp'] <= 6)) { - $annots .= ' /TP '.intval($pl['opt']['mk']['tp']); - } - $annots .= '>>'; - } // end MK - // --- Entries for field dictionaries --- - if (isset($this->radiobutton_groups[$n][$pl['txt']])) { - // set parent - $annots .= ' /Parent '.$this->radiobutton_groups[$n][$pl['txt']].' 0 R'; - } - if (isset($pl['opt']['t']) AND is_string($pl['opt']['t'])) { - $annots .= ' /T '.$this->_datastring($pl['opt']['t'], $annot_obj_id); - } - if (isset($pl['opt']['tu']) AND is_string($pl['opt']['tu'])) { - $annots .= ' /TU '.$this->_datastring($pl['opt']['tu'], $annot_obj_id); - } - if (isset($pl['opt']['tm']) AND is_string($pl['opt']['tm'])) { - $annots .= ' /TM '.$this->_datastring($pl['opt']['tm'], $annot_obj_id); - } - if (isset($pl['opt']['ff'])) { - if (is_array($pl['opt']['ff'])) { - // array of bit settings - $flag = 0; - foreach($pl['opt']['ff'] as $val) { - $flag += 1 << ($val - 1); - } - } else { - $flag = intval($pl['opt']['ff']); - } - $annots .= ' /Ff '.$flag; - } - if (isset($pl['opt']['maxlen'])) { - $annots .= ' /MaxLen '.intval($pl['opt']['maxlen']); - } - if (isset($pl['opt']['v'])) { - $annots .= ' /V'; - if (is_array($pl['opt']['v'])) { - foreach ($pl['opt']['v'] AS $optval) { - if (is_float($optval)) { - $optval = sprintf('%F', $optval); - } - $annots .= ' '.$optval; - } - } else { - $annots .= ' '.$this->_textstring($pl['opt']['v'], $annot_obj_id); - } - } - if (isset($pl['opt']['dv'])) { - $annots .= ' /DV'; - if (is_array($pl['opt']['dv'])) { - foreach ($pl['opt']['dv'] AS $optval) { - if (is_float($optval)) { - $optval = sprintf('%F', $optval); - } - $annots .= ' '.$optval; - } - } else { - $annots .= ' '.$this->_textstring($pl['opt']['dv'], $annot_obj_id); - } - } - if (isset($pl['opt']['rv'])) { - $annots .= ' /RV'; - if (is_array($pl['opt']['rv'])) { - foreach ($pl['opt']['rv'] AS $optval) { - if (is_float($optval)) { - $optval = sprintf('%F', $optval); - } - $annots .= ' '.$optval; - } - } else { - $annots .= ' '.$this->_textstring($pl['opt']['rv'], $annot_obj_id); - } - } - if (isset($pl['opt']['a']) AND !empty($pl['opt']['a'])) { - $annots .= ' /A << '.$pl['opt']['a'].' >>'; - } - if (isset($pl['opt']['aa']) AND !empty($pl['opt']['aa'])) { - $annots .= ' /AA << '.$pl['opt']['aa'].' >>'; - } - if (isset($pl['opt']['da']) AND !empty($pl['opt']['da'])) { - $annots .= ' /DA ('.$pl['opt']['da'].')'; - } - if (isset($pl['opt']['q']) AND ($pl['opt']['q'] >= 0) AND ($pl['opt']['q'] <= 2)) { - $annots .= ' /Q '.intval($pl['opt']['q']); - } - if (isset($pl['opt']['opt']) AND (is_array($pl['opt']['opt'])) AND !empty($pl['opt']['opt'])) { - $annots .= ' /Opt ['; - foreach($pl['opt']['opt'] AS $copt) { - if (is_array($copt)) { - $annots .= ' ['.$this->_textstring($copt[0], $annot_obj_id).' '.$this->_textstring($copt[1], $annot_obj_id).']'; - } else { - $annots .= ' '.$this->_textstring($copt, $annot_obj_id); - } - } - $annots .= ']'; - } - if (isset($pl['opt']['ti'])) { - $annots .= ' /TI '.intval($pl['opt']['ti']); - } - if (isset($pl['opt']['i']) AND (is_array($pl['opt']['i'])) AND !empty($pl['opt']['i'])) { - $annots .= ' /I ['; - foreach($pl['opt']['i'] AS $copt) { - $annots .= intval($copt).' '; - } - $annots .= ']'; - } - break; - } - case 'screen': { - break; - } - case 'printermark': { - break; - } - case 'trapnet': { - break; - } - case 'watermark': { - break; - } - case '3d': { - break; - } - default: { - break; - } - } - $annots .= '>>'; - // create new annotation object - $this->_out($this->_getobj($annot_obj_id)."\n".$annots."\n".'endobj'); - if ($formfield AND !isset($this->radiobutton_groups[$n][$pl['txt']])) { - // store reference of form object - $this->form_obj_id[] = $annot_obj_id; - } - } - } - } // end for each page - } - - /** - * Put appearance streams XObject used to define annotation's appearance states. - * @param int $w annotation width - * @param int $h annotation height - * @param string $stream appearance stream - * @return int object ID - * @protected - * @since 4.8.001 (2009-09-09) - */ - protected function _putAPXObject($w=0, $h=0, $stream='') { - $stream = trim($stream); - $out = $this->_getobj()."\n"; - $this->xobjects['AX'.$this->n] = array('n' => $this->n); - $out .= '<<'; - $out .= ' /Type /XObject'; - $out .= ' /Subtype /Form'; - $out .= ' /FormType 1'; - if ($this->compress) { - $stream = gzcompress($stream); - $out .= ' /Filter /FlateDecode'; - } - $rect = sprintf('%F %F', $w, $h); - $out .= ' /BBox [0 0 '.$rect.']'; - $out .= ' /Matrix [1 0 0 1 0 0]'; - $out .= ' /Resources 2 0 R'; - $stream = $this->_getrawstream($stream); - $out .= ' /Length '.strlen($stream); - $out .= ' >>'; - $out .= ' stream'."\n".$stream."\n".'endstream'; - $out .= "\n".'endobj'; - $this->_out($out); - return $this->n; - } - - /** - * Output fonts. - * @author Nicola Asuni - * @protected - */ - protected function _putfonts() { - $nf = $this->n; - foreach ($this->diffs as $diff) { - //Encodings - $this->_newobj(); - $this->_out('<< /Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences ['.$diff.'] >>'."\n".'endobj'); - } - $mqr = TCPDF_STATIC::get_mqr(); - TCPDF_STATIC::set_mqr(false); - foreach ($this->FontFiles as $file => $info) { - // search and get font file to embedd - $fontfile = TCPDF_FONTS::getFontFullPath($file, $info['fontdir']); - if (!TCPDF_STATIC::empty_string($fontfile)) { - $font = file_get_contents($fontfile); - $compressed = (substr($file, -2) == '.z'); - if ((!$compressed) AND (isset($info['length2']))) { - $header = (ord($font[0]) == 128); - if ($header) { - // strip first binary header - $font = substr($font, 6); - } - if ($header AND (ord($font[$info['length1']]) == 128)) { - // strip second binary header - $font = substr($font, 0, $info['length1']).substr($font, ($info['length1'] + 6)); - } - } elseif ($info['subset'] AND ((!$compressed) OR ($compressed AND function_exists('gzcompress')))) { - if ($compressed) { - // uncompress font - $font = gzuncompress($font); - } - // merge subset characters - $subsetchars = array(); // used chars - foreach ($info['fontkeys'] as $fontkey) { - $fontinfo = $this->getFontBuffer($fontkey); - $subsetchars += $fontinfo['subsetchars']; - } - // rebuild a font subset - $font = TCPDF_FONTS::_getTrueTypeFontSubset($font, $subsetchars); - // calculate new font length - $info['length1'] = strlen($font); - if ($compressed) { - // recompress font - $font = gzcompress($font); - } - } - $this->_newobj(); - $this->FontFiles[$file]['n'] = $this->n; - $stream = $this->_getrawstream($font); - $out = '<< /Length '.strlen($stream); - if ($compressed) { - $out .= ' /Filter /FlateDecode'; - } - $out .= ' /Length1 '.$info['length1']; - if (isset($info['length2'])) { - $out .= ' /Length2 '.$info['length2'].' /Length3 0'; - } - $out .= ' >>'; - $out .= ' stream'."\n".$stream."\n".'endstream'; - $out .= "\n".'endobj'; - $this->_out($out); - } - } - TCPDF_STATIC::set_mqr($mqr); - foreach ($this->fontkeys as $k) { - //Font objects - $font = $this->getFontBuffer($k); - $type = $font['type']; - $name = $font['name']; - if ($type == 'core') { - // standard core font - $out = $this->_getobj($this->font_obj_ids[$k])."\n"; - $out .= '<</Type /Font'; - $out .= ' /Subtype /Type1'; - $out .= ' /BaseFont /'.$name; - $out .= ' /Name /F'.$font['i']; - if ((strtolower($name) != 'symbol') AND (strtolower($name) != 'zapfdingbats')) { - $out .= ' /Encoding /WinAnsiEncoding'; - } - if ($k == 'helvetica') { - // add default font for annotations - $this->annotation_fonts[$k] = $font['i']; - } - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - } elseif (($type == 'Type1') OR ($type == 'TrueType')) { - // additional Type1 or TrueType font - $out = $this->_getobj($this->font_obj_ids[$k])."\n"; - $out .= '<</Type /Font'; - $out .= ' /Subtype /'.$type; - $out .= ' /BaseFont /'.$name; - $out .= ' /Name /F'.$font['i']; - $out .= ' /FirstChar 32 /LastChar 255'; - $out .= ' /Widths '.($this->n + 1).' 0 R'; - $out .= ' /FontDescriptor '.($this->n + 2).' 0 R'; - if ($font['enc']) { - if (isset($font['diff'])) { - $out .= ' /Encoding '.($nf + $font['diff']).' 0 R'; - } else { - $out .= ' /Encoding /WinAnsiEncoding'; - } - } - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - // Widths - $this->_newobj(); - $s = '['; - for ($i = 32; $i < 256; ++$i) { - if (isset($font['cw'][$i])) { - $s .= $font['cw'][$i].' '; - } else { - $s .= $font['dw'].' '; - } - } - $s .= ']'; - $s .= "\n".'endobj'; - $this->_out($s); - //Descriptor - $this->_newobj(); - $s = '<</Type /FontDescriptor /FontName /'.$name; - foreach ($font['desc'] as $fdk => $fdv) { - if (is_float($fdv)) { - $fdv = sprintf('%F', $fdv); - } - $s .= ' /'.$fdk.' '.$fdv.''; - } - if (!TCPDF_STATIC::empty_string($font['file'])) { - $s .= ' /FontFile'.($type == 'Type1' ? '' : '2').' '.$this->FontFiles[$font['file']]['n'].' 0 R'; - } - $s .= '>>'; - $s .= "\n".'endobj'; - $this->_out($s); - } else { - // additional types - $mtd = '_put'.strtolower($type); - if (!method_exists($this, $mtd)) { - $this->Error('Unsupported font type: '.$type); - } - $this->$mtd($font); - } - } - } - - /** - * Adds unicode fonts.<br> - * Based on PDF Reference 1.3 (section 5) - * @param array $font font data - * @protected - * @author Nicola Asuni - * @since 1.52.0.TC005 (2005-01-05) - */ - protected function _puttruetypeunicode($font) { - $fontname = ''; - if ($font['subset']) { - // change name for font subsetting - $subtag = sprintf('%06u', $font['i']); - $subtag = strtr($subtag, '0123456789', 'ABCDEFGHIJ'); - $fontname .= $subtag.'+'; - } - $fontname .= $font['name']; - // Type0 Font - // A composite font composed of other fonts, organized hierarchically - $out = $this->_getobj($this->font_obj_ids[$font['fontkey']])."\n"; - $out .= '<< /Type /Font'; - $out .= ' /Subtype /Type0'; - $out .= ' /BaseFont /'.$fontname; - $out .= ' /Name /F'.$font['i']; - $out .= ' /Encoding /'.$font['enc']; - $out .= ' /ToUnicode '.($this->n + 1).' 0 R'; - $out .= ' /DescendantFonts ['.($this->n + 2).' 0 R]'; - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - // ToUnicode map for Identity-H - $stream = TCPDF_FONT_DATA::$uni_identity_h; - // ToUnicode Object - $this->_newobj(); - $stream = ($this->compress) ? gzcompress($stream) : $stream; - $filter = ($this->compress) ? '/Filter /FlateDecode ' : ''; - $stream = $this->_getrawstream($stream); - $this->_out('<<'.$filter.'/Length '.strlen($stream).'>> stream'."\n".$stream."\n".'endstream'."\n".'endobj'); - // CIDFontType2 - // A CIDFont whose glyph descriptions are based on TrueType font technology - $oid = $this->_newobj(); - $out = '<< /Type /Font'; - $out .= ' /Subtype /CIDFontType2'; - $out .= ' /BaseFont /'.$fontname; - // A dictionary containing entries that define the character collection of the CIDFont. - $cidinfo = '/Registry '.$this->_datastring($font['cidinfo']['Registry'], $oid); - $cidinfo .= ' /Ordering '.$this->_datastring($font['cidinfo']['Ordering'], $oid); - $cidinfo .= ' /Supplement '.$font['cidinfo']['Supplement']; - $out .= ' /CIDSystemInfo << '.$cidinfo.' >>'; - $out .= ' /FontDescriptor '.($this->n + 1).' 0 R'; - $out .= ' /DW '.$font['dw']; // default width - $out .= "\n".TCPDF_FONTS::_putfontwidths($font, 0); - if (isset($font['ctg']) AND (!TCPDF_STATIC::empty_string($font['ctg']))) { - $out .= "\n".'/CIDToGIDMap '.($this->n + 2).' 0 R'; - } - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - // Font descriptor - // A font descriptor describing the CIDFont default metrics other than its glyph widths - $this->_newobj(); - $out = '<< /Type /FontDescriptor'; - $out .= ' /FontName /'.$fontname; - foreach ($font['desc'] as $key => $value) { - if (is_float($value)) { - $value = sprintf('%F', $value); - } - $out .= ' /'.$key.' '.$value; - } - $fontdir = false; - if (!TCPDF_STATIC::empty_string($font['file'])) { - // A stream containing a TrueType font - $out .= ' /FontFile2 '.$this->FontFiles[$font['file']]['n'].' 0 R'; - $fontdir = $this->FontFiles[$font['file']]['fontdir']; - } - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - if (isset($font['ctg']) AND (!TCPDF_STATIC::empty_string($font['ctg']))) { - $this->_newobj(); - // Embed CIDToGIDMap - // A specification of the mapping from CIDs to glyph indices - // search and get CTG font file to embedd - $ctgfile = strtolower($font['ctg']); - // search and get ctg font file to embedd - $fontfile = TCPDF_FONTS::getFontFullPath($ctgfile, $fontdir); - if (TCPDF_STATIC::empty_string($fontfile)) { - $this->Error('Font file not found: '.$ctgfile); - } - $stream = $this->_getrawstream(file_get_contents($fontfile)); - $out = '<< /Length '.strlen($stream).''; - if (substr($fontfile, -2) == '.z') { // check file extension - // Decompresses data encoded using the public-domain - // zlib/deflate compression method, reproducing the - // original text or binary data - $out .= ' /Filter /FlateDecode'; - } - $out .= ' >>'; - $out .= ' stream'."\n".$stream."\n".'endstream'; - $out .= "\n".'endobj'; - $this->_out($out); - } - } - - /** - * Output CID-0 fonts. - * A Type 0 CIDFont contains glyph descriptions based on the Adobe Type 1 font format - * @param array $font font data - * @protected - * @author Andrew Whitehead, Nicola Asuni, Yukihiro Nakadaira - * @since 3.2.000 (2008-06-23) - */ - protected function _putcidfont0($font) { - $cidoffset = 0; - if (!isset($font['cw'][1])) { - $cidoffset = 31; - } - if (isset($font['cidinfo']['uni2cid'])) { - // convert unicode to cid. - $uni2cid = $font['cidinfo']['uni2cid']; - $cw = array(); - foreach ($font['cw'] as $uni => $width) { - if (isset($uni2cid[$uni])) { - $cw[($uni2cid[$uni] + $cidoffset)] = $width; - } elseif ($uni < 256) { - $cw[$uni] = $width; - } // else unknown character - } - $font = array_merge($font, array('cw' => $cw)); - } - $name = $font['name']; - $enc = $font['enc']; - if ($enc) { - $longname = $name.'-'.$enc; - } else { - $longname = $name; - } - $out = $this->_getobj($this->font_obj_ids[$font['fontkey']])."\n"; - $out .= '<</Type /Font'; - $out .= ' /Subtype /Type0'; - $out .= ' /BaseFont /'.$longname; - $out .= ' /Name /F'.$font['i']; - if ($enc) { - $out .= ' /Encoding /'.$enc; - } - $out .= ' /DescendantFonts ['.($this->n + 1).' 0 R]'; - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - $oid = $this->_newobj(); - $out = '<</Type /Font'; - $out .= ' /Subtype /CIDFontType0'; - $out .= ' /BaseFont /'.$name; - $cidinfo = '/Registry '.$this->_datastring($font['cidinfo']['Registry'], $oid); - $cidinfo .= ' /Ordering '.$this->_datastring($font['cidinfo']['Ordering'], $oid); - $cidinfo .= ' /Supplement '.$font['cidinfo']['Supplement']; - $out .= ' /CIDSystemInfo <<'.$cidinfo.'>>'; - $out .= ' /FontDescriptor '.($this->n + 1).' 0 R'; - $out .= ' /DW '.$font['dw']; - $out .= "\n".TCPDF_FONTS::_putfontwidths($font, $cidoffset); - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - $this->_newobj(); - $s = '<</Type /FontDescriptor /FontName /'.$name; - foreach ($font['desc'] as $k => $v) { - if ($k != 'Style') { - if (is_float($v)) { - $v = sprintf('%F', $v); - } - $s .= ' /'.$k.' '.$v.''; - } - } - $s .= '>>'; - $s .= "\n".'endobj'; - $this->_out($s); - } - - /** - * Output images. - * @protected - */ - protected function _putimages() { - $filter = ($this->compress) ? '/Filter /FlateDecode ' : ''; - foreach ($this->imagekeys as $file) { - $info = $this->getImageBuffer($file); - // set object for alternate images array - if ((!$this->pdfa_mode) AND isset($info['altimgs']) AND !empty($info['altimgs'])) { - $altoid = $this->_newobj(); - $out = '['; - foreach ($info['altimgs'] as $altimage) { - if (isset($this->xobjects['I'.$altimage[0]]['n'])) { - $out .= ' << /Image '.$this->xobjects['I'.$altimage[0]]['n'].' 0 R'; - $out .= ' /DefaultForPrinting'; - if ($altimage[1] === true) { - $out .= ' true'; - } else { - $out .= ' false'; - } - $out .= ' >>'; - } - } - $out .= ' ]'; - $out .= "\n".'endobj'; - $this->_out($out); - } - // set image object - $oid = $this->_newobj(); - $this->xobjects['I'.$info['i']] = array('n' => $oid); - $this->setImageSubBuffer($file, 'n', $this->n); - $out = '<</Type /XObject'; - $out .= ' /Subtype /Image'; - $out .= ' /Width '.$info['w']; - $out .= ' /Height '.$info['h']; - if (array_key_exists('masked', $info)) { - $out .= ' /SMask '.($this->n - 1).' 0 R'; - } - // set color space - $icc = false; - if (isset($info['icc']) AND ($info['icc'] !== false)) { - // ICC Colour Space - $icc = true; - $out .= ' /ColorSpace [/ICCBased '.($this->n + 1).' 0 R]'; - } elseif ($info['cs'] == 'Indexed') { - // Indexed Colour Space - $out .= ' /ColorSpace [/Indexed /DeviceRGB '.((strlen($info['pal']) / 3) - 1).' '.($this->n + 1).' 0 R]'; - } else { - // Device Colour Space - $out .= ' /ColorSpace /'.$info['cs']; - } - if ($info['cs'] == 'DeviceCMYK') { - $out .= ' /Decode [1 0 1 0 1 0 1 0]'; - } - $out .= ' /BitsPerComponent '.$info['bpc']; - if (isset($altoid) AND ($altoid > 0)) { - // reference to alternate images dictionary - $out .= ' /Alternates '.$altoid.' 0 R'; - } - if (isset($info['exurl']) AND !empty($info['exurl'])) { - // external stream - $out .= ' /Length 0'; - $out .= ' /F << /FS /URL /F '.$this->_datastring($info['exurl'], $oid).' >>'; - if (isset($info['f'])) { - $out .= ' /FFilter /'.$info['f']; - } - $out .= ' >>'; - $out .= ' stream'."\n".'endstream'; - } else { - if (isset($info['f'])) { - $out .= ' /Filter /'.$info['f']; - } - if (isset($info['parms'])) { - $out .= ' '.$info['parms']; - } - if (isset($info['trns']) AND is_array($info['trns'])) { - $trns = ''; - $count_info = count($info['trns']); - if ($info['cs'] == 'Indexed') { - $maxval =(pow(2, $info['bpc']) - 1); - for ($i = 0; $i < $count_info; ++$i) { - if (($info['trns'][$i] != 0) AND ($info['trns'][$i] != $maxval)) { - // this is not a binary type mask @TODO: create a SMask - $trns = ''; - break; - } elseif (empty($trns) AND ($info['trns'][$i] == 0)) { - // store the first fully transparent value - $trns .= $i.' '.$i.' '; - } - } - } else { - // grayscale or RGB - for ($i = 0; $i < $count_info; ++$i) { - if ($info['trns'][$i] == 0) { - $trns .= $info['trns'][$i].' '.$info['trns'][$i].' '; - } - } - } - // Colour Key Masking - if (!empty($trns)) { - $out .= ' /Mask ['.$trns.']'; - } - } - $stream = $this->_getrawstream($info['data']); - $out .= ' /Length '.strlen($stream).' >>'; - $out .= ' stream'."\n".$stream."\n".'endstream'; - } - $out .= "\n".'endobj'; - $this->_out($out); - if ($icc) { - // ICC colour profile - $this->_newobj(); - $icc = ($this->compress) ? gzcompress($info['icc']) : $info['icc']; - $icc = $this->_getrawstream($icc); - $this->_out('<</N '.$info['ch'].' /Alternate /'.$info['cs'].' '.$filter.'/Length '.strlen($icc).'>> stream'."\n".$icc."\n".'endstream'."\n".'endobj'); - } elseif ($info['cs'] == 'Indexed') { - // colour palette - $this->_newobj(); - $pal = ($this->compress) ? gzcompress($info['pal']) : $info['pal']; - $pal = $this->_getrawstream($pal); - $this->_out('<<'.$filter.'/Length '.strlen($pal).'>> stream'."\n".$pal."\n".'endstream'."\n".'endobj'); - } - } - } - - /** - * Output Form XObjects Templates. - * @author Nicola Asuni - * @since 5.8.017 (2010-08-24) - * @protected - * @see startTemplate(), endTemplate(), printTemplate() - */ - protected function _putxobjects() { - foreach ($this->xobjects as $key => $data) { - if (isset($data['outdata'])) { - $stream = str_replace($this->epsmarker, '', trim($data['outdata'])); - $out = $this->_getobj($data['n'])."\n"; - $out .= '<<'; - $out .= ' /Type /XObject'; - $out .= ' /Subtype /Form'; - $out .= ' /FormType 1'; - if ($this->compress) { - $stream = gzcompress($stream); - $out .= ' /Filter /FlateDecode'; - } - $out .= sprintf(' /BBox [%F %F %F %F]', ($data['x'] * $this->k), (-$data['y'] * $this->k), (($data['w'] + $data['x']) * $this->k), (($data['h'] - $data['y']) * $this->k)); - $out .= ' /Matrix [1 0 0 1 0 0]'; - $out .= ' /Resources <<'; - $out .= ' /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]'; - if (!$this->pdfa_mode || $this->pdfa_version >= 2) { - // transparency - if (isset($data['extgstates']) AND !empty($data['extgstates'])) { - $out .= ' /ExtGState <<'; - foreach ($data['extgstates'] as $k => $extgstate) { - if (isset($this->extgstates[$k]['name'])) { - $out .= ' /'.$this->extgstates[$k]['name']; - } else { - $out .= ' /GS'.$k; - } - $out .= ' '.$this->extgstates[$k]['n'].' 0 R'; - } - $out .= ' >>'; - } - if (isset($data['gradients']) AND !empty($data['gradients'])) { - $gp = ''; - $gs = ''; - foreach ($data['gradients'] as $id => $grad) { - // gradient patterns - $gp .= ' /p'.$id.' '.$this->gradients[$id]['pattern'].' 0 R'; - // gradient shadings - $gs .= ' /Sh'.$id.' '.$this->gradients[$id]['id'].' 0 R'; - } - $out .= ' /Pattern <<'.$gp.' >>'; - $out .= ' /Shading <<'.$gs.' >>'; - } - } - // spot colors - if (isset($data['spot_colors']) AND !empty($data['spot_colors'])) { - $out .= ' /ColorSpace <<'; - foreach ($data['spot_colors'] as $name => $color) { - $out .= ' /CS'.$color['i'].' '.$this->spot_colors[$name]['n'].' 0 R'; - } - $out .= ' >>'; - } - // fonts - if (!empty($data['fonts'])) { - $out .= ' /Font <<'; - foreach ($data['fonts'] as $fontkey => $fontid) { - $out .= ' /F'.$fontid.' '.$this->font_obj_ids[$fontkey].' 0 R'; - } - $out .= ' >>'; - } - // images or nested xobjects - if (!empty($data['images']) OR !empty($data['xobjects'])) { - $out .= ' /XObject <<'; - foreach ($data['images'] as $imgid) { - $out .= ' /I'.$imgid.' '.$this->xobjects['I'.$imgid]['n'].' 0 R'; - } - foreach ($data['xobjects'] as $sub_id => $sub_objid) { - $out .= ' /'.$sub_id.' '.$sub_objid['n'].' 0 R'; - } - $out .= ' >>'; - } - $out .= ' >>'; //end resources - if (isset($data['group']) AND ($data['group'] !== false)) { - // set transparency group - $out .= ' /Group << /Type /Group /S /Transparency'; - if (is_array($data['group'])) { - if (isset($data['group']['CS']) AND !empty($data['group']['CS'])) { - $out .= ' /CS /'.$data['group']['CS']; - } - if (isset($data['group']['I'])) { - $out .= ' /I /'.($data['group']['I']===true?'true':'false'); - } - if (isset($data['group']['K'])) { - $out .= ' /K /'.($data['group']['K']===true?'true':'false'); - } - } - $out .= ' >>'; - } - $stream = $this->_getrawstream($stream, $data['n']); - $out .= ' /Length '.strlen($stream); - $out .= ' >>'; - $out .= ' stream'."\n".$stream."\n".'endstream'; - $out .= "\n".'endobj'; - $this->_out($out); - } - } - } - - /** - * Output Spot Colors Resources. - * @protected - * @since 4.0.024 (2008-09-12) - */ - protected function _putspotcolors() { - foreach ($this->spot_colors as $name => $color) { - $this->_newobj(); - $this->spot_colors[$name]['n'] = $this->n; - $out = '[/Separation /'.str_replace(' ', '#20', $name); - $out .= ' /DeviceCMYK <<'; - $out .= ' /Range [0 1 0 1 0 1 0 1] /C0 [0 0 0 0]'; - $out .= ' '.sprintf('/C1 [%F %F %F %F] ', ($color['C'] / 100), ($color['M'] / 100), ($color['Y'] / 100), ($color['K'] / 100)); - $out .= ' /FunctionType 2 /Domain [0 1] /N 1>>]'; - $out .= "\n".'endobj'; - $this->_out($out); - } - } - - /** - * Return XObjects Dictionary. - * @return string XObjects dictionary - * @protected - * @since 5.8.014 (2010-08-23) - */ - protected function _getxobjectdict() { - $out = ''; - foreach ($this->xobjects as $id => $objid) { - $out .= ' /'.$id.' '.$objid['n'].' 0 R'; - } - return $out; - } - - /** - * Output Resources Dictionary. - * @protected - */ - protected function _putresourcedict() { - $out = $this->_getobj(2)."\n"; - $out .= '<< /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]'; - $out .= ' /Font <<'; - foreach ($this->fontkeys as $fontkey) { - $font = $this->getFontBuffer($fontkey); - $out .= ' /F'.$font['i'].' '.$font['n'].' 0 R'; - } - $out .= ' >>'; - $out .= ' /XObject <<'; - $out .= $this->_getxobjectdict(); - $out .= ' >>'; - // layers - if (!empty($this->pdflayers)) { - $out .= ' /Properties <<'; - foreach ($this->pdflayers as $layer) { - $out .= ' /'.$layer['layer'].' '.$layer['objid'].' 0 R'; - } - $out .= ' >>'; - } - if (!$this->pdfa_mode || $this->pdfa_version >= 2) { - // transparency - if (isset($this->extgstates) AND !empty($this->extgstates)) { - $out .= ' /ExtGState <<'; - foreach ($this->extgstates as $k => $extgstate) { - if (isset($extgstate['name'])) { - $out .= ' /'.$extgstate['name']; - } else { - $out .= ' /GS'.$k; - } - $out .= ' '.$extgstate['n'].' 0 R'; - } - $out .= ' >>'; - } - if (isset($this->gradients) AND !empty($this->gradients)) { - $gp = ''; - $gs = ''; - foreach ($this->gradients as $id => $grad) { - // gradient patterns - $gp .= ' /p'.$id.' '.$grad['pattern'].' 0 R'; - // gradient shadings - $gs .= ' /Sh'.$id.' '.$grad['id'].' 0 R'; - } - $out .= ' /Pattern <<'.$gp.' >>'; - $out .= ' /Shading <<'.$gs.' >>'; - } - } - // spot colors - if (isset($this->spot_colors) AND !empty($this->spot_colors)) { - $out .= ' /ColorSpace <<'; - foreach ($this->spot_colors as $color) { - $out .= ' /CS'.$color['i'].' '.$color['n'].' 0 R'; - } - $out .= ' >>'; - } - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - } - - /** - * Output Resources. - * @protected - */ - protected function _putresources() { - $this->_putextgstates(); - $this->_putocg(); - $this->_putfonts(); - $this->_putimages(); - $this->_putspotcolors(); - $this->_putshaders(); - $this->_putxobjects(); - $this->_putresourcedict(); - $this->_putdests(); - $this->_putEmbeddedFiles(); - $this->_putannotsobjs(); - $this->_putjavascript(); - $this->_putbookmarks(); - $this->_putencryption(); - } - - /** - * Adds some Metadata information (Document Information Dictionary) - * (see Chapter 14.3.3 Document Information Dictionary of PDF32000_2008.pdf Reference) - * @return int object id - * @protected - */ - protected function _putinfo() { - $oid = $this->_newobj(); - $out = '<<'; - // store current isunicode value - $prev_isunicode = $this->isunicode; - if ($this->docinfounicode) { - $this->isunicode = true; - } - if (!TCPDF_STATIC::empty_string($this->title)) { - // The document's title. - $out .= ' /Title '.$this->_textstring($this->title, $oid); - } - if (!TCPDF_STATIC::empty_string($this->author)) { - // The name of the person who created the document. - $out .= ' /Author '.$this->_textstring($this->author, $oid); - } - if (!TCPDF_STATIC::empty_string($this->subject)) { - // The subject of the document. - $out .= ' /Subject '.$this->_textstring($this->subject, $oid); - } - if (!TCPDF_STATIC::empty_string($this->keywords)) { - // Keywords associated with the document. - $out .= ' /Keywords '.$this->_textstring($this->keywords, $oid); - } - if (!TCPDF_STATIC::empty_string($this->creator)) { - // If the document was converted to PDF from another format, the name of the conforming product that created the original document from which it was converted. - $out .= ' /Creator '.$this->_textstring($this->creator, $oid); - } - // restore previous isunicode value - $this->isunicode = $prev_isunicode; - // default producer - $out .= ' /Producer '.$this->_textstring(TCPDF_STATIC::getTCPDFProducer(), $oid); - // The date and time the document was created, in human-readable form - $out .= ' /CreationDate '.$this->_datestring(0, $this->doc_creation_timestamp); - // The date and time the document was most recently modified, in human-readable form - $out .= ' /ModDate '.$this->_datestring(0, $this->doc_modification_timestamp); - // A name object indicating whether the document has been modified to include trapping information - $out .= ' /Trapped /False'; - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - return $oid; - } - - /** - * Set additional XMP data to be added on the default XMP data just before the end of "x:xmpmeta" tag. - * IMPORTANT: This data is added as-is without controls, so you have to validate your data before using this method! - * @param string $xmp Custom XMP data. - * @since 5.9.128 (2011-10-06) - * @public - */ - public function setExtraXMP($xmp) { - $this->custom_xmp = $xmp; - } - - /** - * Set additional XMP data to be added on the default XMP data just before the end of "rdf:RDF" tag. - * IMPORTANT: This data is added as-is without controls, so you have to validate your data before using this method! - * @param string $xmp Custom XMP RDF data. - * @since 6.3.0 (2019-09-19) - * @public - */ - public function setExtraXMPRDF($xmp) { - $this->custom_xmp_rdf = $xmp; - } - - /** - * Put XMP data object and return ID. - * @return int The object ID. - * @since 5.9.121 (2011-09-28) - * @protected - */ - protected function _putXMP() { - $oid = $this->_newobj(); - // store current isunicode value - $prev_isunicode = $this->isunicode; - $this->isunicode = true; - $prev_encrypted = $this->encrypted; - $this->encrypted = false; - // set XMP data - $xmp = '<?xpacket begin="'.TCPDF_FONTS::unichr(0xfeff, $this->isunicode).'" id="W5M0MpCehiHzreSzNTczkc9d"?>'."\n"; - $xmp .= '<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2.1-c043 52.372728, 2009/01/18-15:08:04">'."\n"; - $xmp .= "\t".'<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">'."\n"; - $xmp .= "\t\t".'<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/">'."\n"; - $xmp .= "\t\t\t".'<dc:format>application/pdf</dc:format>'."\n"; - $xmp .= "\t\t\t".'<dc:title>'."\n"; - $xmp .= "\t\t\t\t".'<rdf:Alt>'."\n"; - $xmp .= "\t\t\t\t\t".'<rdf:li xml:lang="x-default">'.TCPDF_STATIC::_escapeXML($this->title).'</rdf:li>'."\n"; - $xmp .= "\t\t\t\t".'</rdf:Alt>'."\n"; - $xmp .= "\t\t\t".'</dc:title>'."\n"; - $xmp .= "\t\t\t".'<dc:creator>'."\n"; - $xmp .= "\t\t\t\t".'<rdf:Seq>'."\n"; - $xmp .= "\t\t\t\t\t".'<rdf:li>'.TCPDF_STATIC::_escapeXML($this->author).'</rdf:li>'."\n"; - $xmp .= "\t\t\t\t".'</rdf:Seq>'."\n"; - $xmp .= "\t\t\t".'</dc:creator>'."\n"; - $xmp .= "\t\t\t".'<dc:description>'."\n"; - $xmp .= "\t\t\t\t".'<rdf:Alt>'."\n"; - $xmp .= "\t\t\t\t\t".'<rdf:li xml:lang="x-default">'.TCPDF_STATIC::_escapeXML($this->subject).'</rdf:li>'."\n"; - $xmp .= "\t\t\t\t".'</rdf:Alt>'."\n"; - $xmp .= "\t\t\t".'</dc:description>'."\n"; - $xmp .= "\t\t\t".'<dc:subject>'."\n"; - $xmp .= "\t\t\t\t".'<rdf:Bag>'."\n"; - $xmp .= "\t\t\t\t\t".'<rdf:li>'.TCPDF_STATIC::_escapeXML($this->keywords).'</rdf:li>'."\n"; - $xmp .= "\t\t\t\t".'</rdf:Bag>'."\n"; - $xmp .= "\t\t\t".'</dc:subject>'."\n"; - $xmp .= "\t\t".'</rdf:Description>'."\n"; - // convert doc creation date format - $dcdate = TCPDF_STATIC::getFormattedDate($this->doc_creation_timestamp); - $doccreationdate = substr($dcdate, 0, 4).'-'.substr($dcdate, 4, 2).'-'.substr($dcdate, 6, 2); - $doccreationdate .= 'T'.substr($dcdate, 8, 2).':'.substr($dcdate, 10, 2).':'.substr($dcdate, 12, 2); - $doccreationdate .= substr($dcdate, 14, 3).':'.substr($dcdate, 18, 2); - $doccreationdate = TCPDF_STATIC::_escapeXML($doccreationdate); - // convert doc modification date format - $dmdate = TCPDF_STATIC::getFormattedDate($this->doc_modification_timestamp); - $docmoddate = substr($dmdate, 0, 4).'-'.substr($dmdate, 4, 2).'-'.substr($dmdate, 6, 2); - $docmoddate .= 'T'.substr($dmdate, 8, 2).':'.substr($dmdate, 10, 2).':'.substr($dmdate, 12, 2); - $docmoddate .= substr($dmdate, 14, 3).':'.substr($dmdate, 18, 2); - $docmoddate = TCPDF_STATIC::_escapeXML($docmoddate); - $xmp .= "\t\t".'<rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/">'."\n"; - $xmp .= "\t\t\t".'<xmp:CreateDate>'.$doccreationdate.'</xmp:CreateDate>'."\n"; - $xmp .= "\t\t\t".'<xmp:CreatorTool>'.$this->creator.'</xmp:CreatorTool>'."\n"; - $xmp .= "\t\t\t".'<xmp:ModifyDate>'.$docmoddate.'</xmp:ModifyDate>'."\n"; - $xmp .= "\t\t\t".'<xmp:MetadataDate>'.$doccreationdate.'</xmp:MetadataDate>'."\n"; - $xmp .= "\t\t".'</rdf:Description>'."\n"; - $xmp .= "\t\t".'<rdf:Description rdf:about="" xmlns:pdf="http://ns.adobe.com/pdf/1.3/">'."\n"; - $xmp .= "\t\t\t".'<pdf:Keywords>'.TCPDF_STATIC::_escapeXML($this->keywords).'</pdf:Keywords>'."\n"; - $xmp .= "\t\t\t".'<pdf:Producer>'.TCPDF_STATIC::_escapeXML(TCPDF_STATIC::getTCPDFProducer()).'</pdf:Producer>'."\n"; - $xmp .= "\t\t".'</rdf:Description>'."\n"; - $xmp .= "\t\t".'<rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/">'."\n"; - $uuid = 'uuid:'.substr($this->file_id, 0, 8).'-'.substr($this->file_id, 8, 4).'-'.substr($this->file_id, 12, 4).'-'.substr($this->file_id, 16, 4).'-'.substr($this->file_id, 20, 12); - $xmp .= "\t\t\t".'<xmpMM:DocumentID>'.$uuid.'</xmpMM:DocumentID>'."\n"; - $xmp .= "\t\t\t".'<xmpMM:InstanceID>'.$uuid.'</xmpMM:InstanceID>'."\n"; - $xmp .= "\t\t".'</rdf:Description>'."\n"; - if ($this->pdfa_mode) { - $xmp .= "\t\t".'<rdf:Description rdf:about="" xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/">'."\n"; - $xmp .= "\t\t\t".'<pdfaid:part>'.$this->pdfa_version.'</pdfaid:part>'."\n"; - $xmp .= "\t\t\t".'<pdfaid:conformance>B</pdfaid:conformance>'."\n"; - $xmp .= "\t\t".'</rdf:Description>'."\n"; - } - // XMP extension schemas - $xmp .= "\t\t".'<rdf:Description rdf:about="" xmlns:pdfaExtension="http://www.aiim.org/pdfa/ns/extension/" xmlns:pdfaSchema="http://www.aiim.org/pdfa/ns/schema#" xmlns:pdfaProperty="http://www.aiim.org/pdfa/ns/property#">'."\n"; - $xmp .= "\t\t\t".'<pdfaExtension:schemas>'."\n"; - $xmp .= "\t\t\t\t".'<rdf:Bag>'."\n"; - $xmp .= "\t\t\t\t\t".'<rdf:li rdf:parseType="Resource">'."\n"; - $xmp .= "\t\t\t\t\t\t".'<pdfaSchema:namespaceURI>http://ns.adobe.com/pdf/1.3/</pdfaSchema:namespaceURI>'."\n"; - $xmp .= "\t\t\t\t\t\t".'<pdfaSchema:prefix>pdf</pdfaSchema:prefix>'."\n"; - $xmp .= "\t\t\t\t\t\t".'<pdfaSchema:schema>Adobe PDF Schema</pdfaSchema:schema>'."\n"; - $xmp .= "\t\t\t\t\t\t".'<pdfaSchema:property>'."\n"; - $xmp .= "\t\t\t\t\t\t\t".'<rdf:Seq>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t".'<rdf:li rdf:parseType="Resource">'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:category>internal</pdfaProperty:category>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:description>Adobe PDF Schema</pdfaProperty:description>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:name>InstanceID</pdfaProperty:name>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:valueType>URI</pdfaProperty:valueType>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t".'</rdf:li>'."\n"; - $xmp .= "\t\t\t\t\t\t\t".'</rdf:Seq>'."\n"; - $xmp .= "\t\t\t\t\t\t".'</pdfaSchema:property>'."\n"; - $xmp .= "\t\t\t\t\t".'</rdf:li>'."\n"; - $xmp .= "\t\t\t\t\t".'<rdf:li rdf:parseType="Resource">'."\n"; - $xmp .= "\t\t\t\t\t\t".'<pdfaSchema:namespaceURI>http://ns.adobe.com/xap/1.0/mm/</pdfaSchema:namespaceURI>'."\n"; - $xmp .= "\t\t\t\t\t\t".'<pdfaSchema:prefix>xmpMM</pdfaSchema:prefix>'."\n"; - $xmp .= "\t\t\t\t\t\t".'<pdfaSchema:schema>XMP Media Management Schema</pdfaSchema:schema>'."\n"; - $xmp .= "\t\t\t\t\t\t".'<pdfaSchema:property>'."\n"; - $xmp .= "\t\t\t\t\t\t\t".'<rdf:Seq>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t".'<rdf:li rdf:parseType="Resource">'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:category>internal</pdfaProperty:category>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:description>UUID based identifier for specific incarnation of a document</pdfaProperty:description>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:name>InstanceID</pdfaProperty:name>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:valueType>URI</pdfaProperty:valueType>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t".'</rdf:li>'."\n"; - $xmp .= "\t\t\t\t\t\t\t".'</rdf:Seq>'."\n"; - $xmp .= "\t\t\t\t\t\t".'</pdfaSchema:property>'."\n"; - $xmp .= "\t\t\t\t\t".'</rdf:li>'."\n"; - $xmp .= "\t\t\t\t\t".'<rdf:li rdf:parseType="Resource">'."\n"; - $xmp .= "\t\t\t\t\t\t".'<pdfaSchema:namespaceURI>http://www.aiim.org/pdfa/ns/id/</pdfaSchema:namespaceURI>'."\n"; - $xmp .= "\t\t\t\t\t\t".'<pdfaSchema:prefix>pdfaid</pdfaSchema:prefix>'."\n"; - $xmp .= "\t\t\t\t\t\t".'<pdfaSchema:schema>PDF/A ID Schema</pdfaSchema:schema>'."\n"; - $xmp .= "\t\t\t\t\t\t".'<pdfaSchema:property>'."\n"; - $xmp .= "\t\t\t\t\t\t\t".'<rdf:Seq>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t".'<rdf:li rdf:parseType="Resource">'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:category>internal</pdfaProperty:category>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:description>Part of PDF/A standard</pdfaProperty:description>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:name>part</pdfaProperty:name>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:valueType>Integer</pdfaProperty:valueType>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t".'</rdf:li>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t".'<rdf:li rdf:parseType="Resource">'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:category>internal</pdfaProperty:category>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:description>Amendment of PDF/A standard</pdfaProperty:description>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:name>amd</pdfaProperty:name>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:valueType>Text</pdfaProperty:valueType>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t".'</rdf:li>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t".'<rdf:li rdf:parseType="Resource">'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:category>internal</pdfaProperty:category>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:description>Conformance level of PDF/A standard</pdfaProperty:description>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:name>conformance</pdfaProperty:name>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:valueType>Text</pdfaProperty:valueType>'."\n"; - $xmp .= "\t\t\t\t\t\t\t\t".'</rdf:li>'."\n"; - $xmp .= "\t\t\t\t\t\t\t".'</rdf:Seq>'."\n"; - $xmp .= "\t\t\t\t\t\t".'</pdfaSchema:property>'."\n"; - $xmp .= "\t\t\t\t\t".'</rdf:li>'."\n"; - $xmp .= "\t\t\t\t".'</rdf:Bag>'."\n"; - $xmp .= "\t\t\t".'</pdfaExtension:schemas>'."\n"; - $xmp .= "\t\t".'</rdf:Description>'."\n"; - $xmp .= $this->custom_xmp_rdf; - $xmp .= "\t".'</rdf:RDF>'."\n"; - $xmp .= $this->custom_xmp; - $xmp .= '</x:xmpmeta>'."\n"; - $xmp .= '<?xpacket end="w"?>'; - $out = '<< /Type /Metadata /Subtype /XML /Length '.strlen($xmp).' >> stream'."\n".$xmp."\n".'endstream'."\n".'endobj'; - // restore previous isunicode value - $this->isunicode = $prev_isunicode; - $this->encrypted = $prev_encrypted; - $this->_out($out); - return $oid; - } - - /** - * Output Catalog. - * @return int object id - * @protected - */ - protected function _putcatalog() { - // put XMP - $xmpobj = $this->_putXMP(); - // if required, add standard sRGB ICC colour profile - if ($this->pdfa_mode OR $this->force_srgb) { - $iccobj = $this->_newobj(); - $icc = file_get_contents(dirname(__FILE__).'/include/sRGB.icc'); - $filter = ''; - if ($this->compress) { - $filter = ' /Filter /FlateDecode'; - $icc = gzcompress($icc); - } - $icc = $this->_getrawstream($icc); - $this->_out('<</N 3 '.$filter.'/Length '.strlen($icc).'>> stream'."\n".$icc."\n".'endstream'."\n".'endobj'); - } - // start catalog - $oid = $this->_newobj(); - $out = '<< /Type /Catalog'; - $out .= ' /Version /'.$this->PDFVersion; - //$out .= ' /Extensions <<>>'; - $out .= ' /Pages 1 0 R'; - //$out .= ' /PageLabels ' //...; - $out .= ' /Names <<'; - if ((!$this->pdfa_mode) AND !empty($this->n_js)) { - $out .= ' /JavaScript '.$this->n_js; - } - if (!empty($this->efnames)) { - $out .= ' /EmbeddedFiles <</Names ['; - foreach ($this->efnames AS $fn => $fref) { - $out .= ' '.$this->_datastring($fn).' '.$fref; - } - $out .= ' ]>>'; - } - $out .= ' >>'; - if (!empty($this->dests)) { - $out .= ' /Dests '.($this->n_dests).' 0 R'; - } - $out .= $this->_putviewerpreferences(); - if (isset($this->LayoutMode) AND (!TCPDF_STATIC::empty_string($this->LayoutMode))) { - $out .= ' /PageLayout /'.$this->LayoutMode; - } - if (isset($this->PageMode) AND (!TCPDF_STATIC::empty_string($this->PageMode))) { - $out .= ' /PageMode /'.$this->PageMode; - } - if (count($this->outlines) > 0) { - $out .= ' /Outlines '.$this->OutlineRoot.' 0 R'; - $out .= ' /PageMode /UseOutlines'; - } - //$out .= ' /Threads []'; - if ($this->ZoomMode == 'fullpage') { - $out .= ' /OpenAction ['.$this->page_obj_id[1].' 0 R /Fit]'; - } elseif ($this->ZoomMode == 'fullwidth') { - $out .= ' /OpenAction ['.$this->page_obj_id[1].' 0 R /FitH null]'; - } elseif ($this->ZoomMode == 'real') { - $out .= ' /OpenAction ['.$this->page_obj_id[1].' 0 R /XYZ null null 1]'; - } elseif (!is_string($this->ZoomMode)) { - $out .= sprintf(' /OpenAction ['.$this->page_obj_id[1].' 0 R /XYZ null null %F]', ($this->ZoomMode / 100)); - } - //$out .= ' /AA <<>>'; - //$out .= ' /URI <<>>'; - $out .= ' /Metadata '.$xmpobj.' 0 R'; - //$out .= ' /StructTreeRoot <<>>'; - //$out .= ' /MarkInfo <<>>'; - if (isset($this->l['a_meta_language'])) { - $out .= ' /Lang '.$this->_textstring($this->l['a_meta_language'], $oid); - } - //$out .= ' /SpiderInfo <<>>'; - // set OutputIntent to sRGB IEC61966-2.1 if required - if ($this->pdfa_mode OR $this->force_srgb) { - $out .= ' /OutputIntents [<<'; - $out .= ' /Type /OutputIntent'; - $out .= ' /S /GTS_PDFA1'; - $out .= ' /OutputCondition '.$this->_textstring('sRGB IEC61966-2.1', $oid); - $out .= ' /OutputConditionIdentifier '.$this->_textstring('sRGB IEC61966-2.1', $oid); - $out .= ' /RegistryName '.$this->_textstring('http://www.color.org', $oid); - $out .= ' /Info '.$this->_textstring('sRGB IEC61966-2.1', $oid); - $out .= ' /DestOutputProfile '.$iccobj.' 0 R'; - $out .= ' >>]'; - } - //$out .= ' /PieceInfo <<>>'; - if (!empty($this->pdflayers)) { - $lyrobjs = ''; - $lyrobjs_off = ''; - $lyrobjs_lock = ''; - foreach ($this->pdflayers as $layer) { - $layer_obj_ref = ' '.$layer['objid'].' 0 R'; - $lyrobjs .= $layer_obj_ref; - if ($layer['view'] === false) { - $lyrobjs_off .= $layer_obj_ref; - } - if ($layer['lock']) { - $lyrobjs_lock .= $layer_obj_ref; - } - } - $out .= ' /OCProperties << /OCGs ['.$lyrobjs.']'; - $out .= ' /D <<'; - $out .= ' /Name '.$this->_textstring('Layers', $oid); - $out .= ' /Creator '.$this->_textstring('TCPDF', $oid); - $out .= ' /BaseState /ON'; - $out .= ' /OFF ['.$lyrobjs_off.']'; - $out .= ' /Locked ['.$lyrobjs_lock.']'; - $out .= ' /Intent /View'; - $out .= ' /AS ['; - $out .= ' << /Event /Print /OCGs ['.$lyrobjs.'] /Category [/Print] >>'; - $out .= ' << /Event /View /OCGs ['.$lyrobjs.'] /Category [/View] >>'; - $out .= ' ]'; - $out .= ' /Order ['.$lyrobjs.']'; - $out .= ' /ListMode /AllPages'; - //$out .= ' /RBGroups ['..']'; - //$out .= ' /Locked ['..']'; - $out .= ' >>'; - $out .= ' >>'; - } - // AcroForm - if (!empty($this->form_obj_id) - OR ($this->sign AND isset($this->signature_data['cert_type'])) - OR !empty($this->empty_signature_appearance)) { - $out .= ' /AcroForm <<'; - $objrefs = ''; - if ($this->sign AND isset($this->signature_data['cert_type'])) { - // set reference for signature object - $objrefs .= $this->sig_obj_id.' 0 R'; - } - if (!empty($this->empty_signature_appearance)) { - foreach ($this->empty_signature_appearance as $esa) { - // set reference for empty signature objects - $objrefs .= ' '.$esa['objid'].' 0 R'; - } - } - if (!empty($this->form_obj_id)) { - foreach($this->form_obj_id as $objid) { - $objrefs .= ' '.$objid.' 0 R'; - } - } - $out .= ' /Fields ['.$objrefs.']'; - // It's better to turn off this value and set the appearance stream for each annotation (/AP) to avoid conflicts with signature fields. - if (empty($this->signature_data['approval']) OR ($this->signature_data['approval'] != 'A')) { - $out .= ' /NeedAppearances false'; - } - if ($this->sign AND isset($this->signature_data['cert_type'])) { - if ($this->signature_data['cert_type'] > 0) { - $out .= ' /SigFlags 3'; - } else { - $out .= ' /SigFlags 1'; - } - } - //$out .= ' /CO '; - if (isset($this->annotation_fonts) AND !empty($this->annotation_fonts)) { - $out .= ' /DR <<'; - $out .= ' /Font <<'; - foreach ($this->annotation_fonts as $fontkey => $fontid) { - $out .= ' /F'.$fontid.' '.$this->font_obj_ids[$fontkey].' 0 R'; - } - $out .= ' >> >>'; - } - $font = $this->getFontBuffer('helvetica'); - $out .= ' /DA (/F'.$font['i'].' 0 Tf 0 g)'; - $out .= ' /Q '.(($this->rtl)?'2':'0'); - //$out .= ' /XFA '; - $out .= ' >>'; - // signatures - if ($this->sign AND isset($this->signature_data['cert_type']) - AND (empty($this->signature_data['approval']) OR ($this->signature_data['approval'] != 'A'))) { - if ($this->signature_data['cert_type'] > 0) { - $out .= ' /Perms << /DocMDP '.($this->sig_obj_id + 1).' 0 R >>'; - } else { - $out .= ' /Perms << /UR3 '.($this->sig_obj_id + 1).' 0 R >>'; - } - } - } - //$out .= ' /Legal <<>>'; - //$out .= ' /Requirements []'; - //$out .= ' /Collection <<>>'; - //$out .= ' /NeedsRendering true'; - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - return $oid; - } - - /** - * Output viewer preferences. - * @return string for viewer preferences - * @author Nicola asuni - * @since 3.1.000 (2008-06-09) - * @protected - */ - protected function _putviewerpreferences() { - $vp = $this->viewer_preferences; - $out = ' /ViewerPreferences <<'; - if ($this->rtl) { - $out .= ' /Direction /R2L'; - } else { - $out .= ' /Direction /L2R'; - } - if (isset($vp['HideToolbar']) AND ($vp['HideToolbar'])) { - $out .= ' /HideToolbar true'; - } - if (isset($vp['HideMenubar']) AND ($vp['HideMenubar'])) { - $out .= ' /HideMenubar true'; - } - if (isset($vp['HideWindowUI']) AND ($vp['HideWindowUI'])) { - $out .= ' /HideWindowUI true'; - } - if (isset($vp['FitWindow']) AND ($vp['FitWindow'])) { - $out .= ' /FitWindow true'; - } - if (isset($vp['CenterWindow']) AND ($vp['CenterWindow'])) { - $out .= ' /CenterWindow true'; - } - if (isset($vp['DisplayDocTitle']) AND ($vp['DisplayDocTitle'])) { - $out .= ' /DisplayDocTitle true'; - } - if (isset($vp['NonFullScreenPageMode'])) { - $out .= ' /NonFullScreenPageMode /'.$vp['NonFullScreenPageMode']; - } - if (isset($vp['ViewArea'])) { - $out .= ' /ViewArea /'.$vp['ViewArea']; - } - if (isset($vp['ViewClip'])) { - $out .= ' /ViewClip /'.$vp['ViewClip']; - } - if (isset($vp['PrintArea'])) { - $out .= ' /PrintArea /'.$vp['PrintArea']; - } - if (isset($vp['PrintClip'])) { - $out .= ' /PrintClip /'.$vp['PrintClip']; - } - if (isset($vp['PrintScaling'])) { - $out .= ' /PrintScaling /'.$vp['PrintScaling']; - } - if (isset($vp['Duplex']) AND (!TCPDF_STATIC::empty_string($vp['Duplex']))) { - $out .= ' /Duplex /'.$vp['Duplex']; - } - if (isset($vp['PickTrayByPDFSize'])) { - if ($vp['PickTrayByPDFSize']) { - $out .= ' /PickTrayByPDFSize true'; - } else { - $out .= ' /PickTrayByPDFSize false'; - } - } - if (isset($vp['PrintPageRange'])) { - $PrintPageRangeNum = ''; - foreach ($vp['PrintPageRange'] as $k => $v) { - $PrintPageRangeNum .= ' '.($v - 1).''; - } - $out .= ' /PrintPageRange ['.substr($PrintPageRangeNum,1).']'; - } - if (isset($vp['NumCopies'])) { - $out .= ' /NumCopies '.intval($vp['NumCopies']); - } - $out .= ' >>'; - return $out; - } - - /** - * Output PDF File Header (7.5.2). - * @protected - */ - protected function _putheader() { - $this->_out('%PDF-'.$this->PDFVersion); - $this->_out('%'.chr(0xe2).chr(0xe3).chr(0xcf).chr(0xd3)); - } - - /** - * Output end of document (EOF). - * @protected - */ - protected function _enddoc() { - if (isset($this->CurrentFont['fontkey']) AND isset($this->CurrentFont['subsetchars'])) { - // save subset chars of the previous font - $this->setFontSubBuffer($this->CurrentFont['fontkey'], 'subsetchars', $this->CurrentFont['subsetchars']); - } - $this->state = 1; - $this->_putheader(); - $this->_putpages(); - $this->_putresources(); - // empty signature fields - if (!empty($this->empty_signature_appearance)) { - foreach ($this->empty_signature_appearance as $key => $esa) { - // widget annotation for empty signature - $out = $this->_getobj($esa['objid'])."\n"; - $out .= '<< /Type /Annot'; - $out .= ' /Subtype /Widget'; - $out .= ' /Rect ['.$esa['rect'].']'; - $out .= ' /P '.$this->page_obj_id[($esa['page'])].' 0 R'; // link to signature appearance page - $out .= ' /F 4'; - $out .= ' /FT /Sig'; - $signame = $esa['name'].sprintf(' [%03d]', ($key + 1)); - $out .= ' /T '.$this->_textstring($signame, $esa['objid']); - $out .= ' /Ff 0'; - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - } - } - // Signature - if ($this->sign AND isset($this->signature_data['cert_type'])) { - // widget annotation for signature - $out = $this->_getobj($this->sig_obj_id)."\n"; - $out .= '<< /Type /Annot'; - $out .= ' /Subtype /Widget'; - $out .= ' /Rect ['.$this->signature_appearance['rect'].']'; - $out .= ' /P '.$this->page_obj_id[($this->signature_appearance['page'])].' 0 R'; // link to signature appearance page - $out .= ' /F 4'; - $out .= ' /FT /Sig'; - $out .= ' /T '.$this->_textstring($this->signature_appearance['name'], $this->sig_obj_id); - $out .= ' /Ff 0'; - $out .= ' /V '.($this->sig_obj_id + 1).' 0 R'; - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - // signature - $this->_putsignature(); - } - // Info - $objid_info = $this->_putinfo(); - // Catalog - $objid_catalog = $this->_putcatalog(); - // Cross-ref - $o = $this->bufferlen; - // XREF section - $this->_out('xref'); - $this->_out('0 '.($this->n + 1)); - $this->_out('0000000000 65535 f '); - $freegen = ($this->n + 2); - for ($i=1; $i <= $this->n; ++$i) { - if (!isset($this->offsets[$i]) AND ($i > 1)) { - $this->_out(sprintf('0000000000 %05d f ', $freegen)); - ++$freegen; - } else { - $this->_out(sprintf('%010d 00000 n ', $this->offsets[$i])); - } - } - // TRAILER - $out = 'trailer'."\n"; - $out .= '<<'; - $out .= ' /Size '.($this->n + 1); - $out .= ' /Root '.$objid_catalog.' 0 R'; - $out .= ' /Info '.$objid_info.' 0 R'; - if ($this->encrypted) { - $out .= ' /Encrypt '.$this->encryptdata['objid'].' 0 R'; - } - $out .= ' /ID [ <'.$this->file_id.'> <'.$this->file_id.'> ]'; - $out .= ' >>'; - $this->_out($out); - $this->_out('startxref'); - $this->_out($o); - $this->_out('%%EOF'); - $this->state = 3; // end-of-doc - } - - /** - * Initialize a new page. - * @param string $orientation page orientation. Possible values are (case insensitive):<ul><li>P or PORTRAIT (default)</li><li>L or LANDSCAPE</li></ul> - * @param mixed $format The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() or an array of parameters specified at setPageFormat(). - * @protected - * @see getPageSizeFromFormat(), setPageFormat() - */ - protected function _beginpage($orientation='', $format='') { - ++$this->page; - $this->pageobjects[$this->page] = array(); - $this->setPageBuffer($this->page, ''); - // initialize array for graphics tranformation positions inside a page buffer - $this->transfmrk[$this->page] = array(); - $this->state = 2; - if (TCPDF_STATIC::empty_string($orientation)) { - if (isset($this->CurOrientation)) { - $orientation = $this->CurOrientation; - } elseif ($this->fwPt > $this->fhPt) { - // landscape - $orientation = 'L'; - } else { - // portrait - $orientation = 'P'; - } - } - if (TCPDF_STATIC::empty_string($format)) { - $this->pagedim[$this->page] = $this->pagedim[($this->page - 1)]; - $this->setPageOrientation($orientation); - } else { - $this->setPageFormat($format, $orientation); - } - if ($this->rtl) { - $this->x = $this->w - $this->rMargin; - } else { - $this->x = $this->lMargin; - } - $this->y = $this->tMargin; - if (isset($this->newpagegroup[$this->page])) { - // start a new group - $this->currpagegroup = $this->newpagegroup[$this->page]; - $this->pagegroups[$this->currpagegroup] = 1; - } elseif (isset($this->currpagegroup) AND ($this->currpagegroup > 0)) { - ++$this->pagegroups[$this->currpagegroup]; - } - } - - /** - * Mark end of page. - * @protected - */ - protected function _endpage() { - $this->setVisibility('all'); - $this->state = 1; - } - - /** - * Begin a new object and return the object number. - * @return int object number - * @protected - */ - protected function _newobj() { - $this->_out($this->_getobj()); - return $this->n; - } - - /** - * Return the starting object string for the selected object ID. - * @param int|null $objid Object ID (leave empty to get a new ID). - * @return string the starting object string - * @protected - * @since 5.8.009 (2010-08-20) - */ - protected function _getobj($objid=null) { - if (TCPDF_STATIC::empty_string($objid)) { - ++$this->n; - $objid = $this->n; - } - $this->offsets[$objid] = $this->bufferlen; - $this->pageobjects[$this->page][] = $objid; - return $objid.' 0 obj'; - } - - /** - * Underline text. - * @param int $x X coordinate - * @param int $y Y coordinate - * @param string $txt text to underline - * @protected - */ - protected function _dounderline($x, $y, $txt) { - $w = $this->GetStringWidth($txt); - return $this->_dounderlinew($x, $y, $w); - } - - /** - * Underline for rectangular text area. - * @param int $x X coordinate - * @param int $y Y coordinate - * @param int $w width to underline - * @protected - * @since 4.8.008 (2009-09-29) - */ - protected function _dounderlinew($x, $y, $w) { - $linew = - $this->CurrentFont['ut'] / 1000 * $this->FontSizePt; - return sprintf('%F %F %F %F re f', $x * $this->k, ((($this->h - $y) * $this->k) + $linew), $w * $this->k, $linew); - } - - /** - * Line through text. - * @param int $x X coordinate - * @param int $y Y coordinate - * @param string $txt text to linethrough - * @protected - */ - protected function _dolinethrough($x, $y, $txt) { - $w = $this->GetStringWidth($txt); - return $this->_dolinethroughw($x, $y, $w); - } - - /** - * Line through for rectangular text area. - * @param int $x X coordinate - * @param int $y Y coordinate - * @param int $w line length (width) - * @protected - * @since 4.9.008 (2009-09-29) - */ - protected function _dolinethroughw($x, $y, $w) { - $linew = - $this->CurrentFont['ut'] / 1000 * $this->FontSizePt; - return sprintf('%F %F %F %F re f', $x * $this->k, ((($this->h - $y) * $this->k) + $linew + ($this->FontSizePt / 3)), $w * $this->k, $linew); - } - - /** - * Overline text. - * @param int $x X coordinate - * @param int $y Y coordinate - * @param string $txt text to overline - * @protected - * @since 4.9.015 (2010-04-19) - */ - protected function _dooverline($x, $y, $txt) { - $w = $this->GetStringWidth($txt); - return $this->_dooverlinew($x, $y, $w); - } - - /** - * Overline for rectangular text area. - * @param int $x X coordinate - * @param int $y Y coordinate - * @param int $w width to overline - * @protected - * @since 4.9.015 (2010-04-19) - */ - protected function _dooverlinew($x, $y, $w) { - $linew = - $this->CurrentFont['ut'] / 1000 * $this->FontSizePt; - return sprintf('%F %F %F %F re f', $x * $this->k, (($this->h - $y + $this->FontAscent) * $this->k) - $linew, $w * $this->k, $linew); - - } - - /** - * Format a data string for meta information - * @param string $s data string to escape. - * @param int $n object ID - * @return string escaped string. - * @protected - */ - protected function _datastring($s, $n=0) { - if ($n == 0) { - $n = $this->n; - } - $s = $this->_encrypt_data($n, $s); - return '('. TCPDF_STATIC::_escape($s).')'; - } - - /** - * Set the document creation timestamp - * @param mixed $time Document creation timestamp in seconds or date-time string. - * @public - * @since 5.9.152 (2012-03-23) - */ - public function setDocCreationTimestamp($time) { - if (is_string($time)) { - $time = TCPDF_STATIC::getTimestamp($time); - } - $this->doc_creation_timestamp = intval($time); - } - - /** - * Set the document modification timestamp - * @param mixed $time Document modification timestamp in seconds or date-time string. - * @public - * @since 5.9.152 (2012-03-23) - */ - public function setDocModificationTimestamp($time) { - if (is_string($time)) { - $time = TCPDF_STATIC::getTimestamp($time); - } - $this->doc_modification_timestamp = intval($time); - } - - /** - * Returns document creation timestamp in seconds. - * @return int Creation timestamp in seconds. - * @public - * @since 5.9.152 (2012-03-23) - */ - public function getDocCreationTimestamp() { - return $this->doc_creation_timestamp; - } - - /** - * Returns document modification timestamp in seconds. - * @return int Modfication timestamp in seconds. - * @public - * @since 5.9.152 (2012-03-23) - */ - public function getDocModificationTimestamp() { - return $this->doc_modification_timestamp; - } - - /** - * Returns a formatted date for meta information - * @param int $n Object ID. - * @param int $timestamp Timestamp to convert. - * @return string escaped date string. - * @protected - * @since 4.6.028 (2009-08-25) - */ - protected function _datestring($n=0, $timestamp=0) { - if ((empty($timestamp)) OR ($timestamp < 0)) { - $timestamp = $this->doc_creation_timestamp; - } - return $this->_datastring('D:'.TCPDF_STATIC::getFormattedDate($timestamp), $n); - } - - /** - * Format a text string for meta information - * @param string $s string to escape. - * @param int $n object ID - * @return string escaped string. - * @protected - */ - protected function _textstring($s, $n=0) { - if ($this->isunicode) { - //Convert string to UTF-16BE - $s = TCPDF_FONTS::UTF8ToUTF16BE($s, true, $this->isunicode, $this->CurrentFont); - } - return $this->_datastring($s, $n); - } - - /** - * get raw output stream. - * @param string $s string to output. - * @param int $n object reference for encryption mode - * @protected - * @author Nicola Asuni - * @since 5.5.000 (2010-06-22) - */ - protected function _getrawstream($s, $n=0) { - if ($n <= 0) { - // default to current object - $n = $this->n; - } - return $this->_encrypt_data($n, $s); - } - - /** - * Output a string to the document. - * @param string $s string to output. - * @protected - */ - protected function _out($s) { - if ($this->state == 2) { - if ($this->inxobj) { - // we are inside an XObject template - $this->xobjects[$this->xobjid]['outdata'] .= $s."\n"; - } elseif ((!$this->InFooter) AND isset($this->footerlen[$this->page]) AND ($this->footerlen[$this->page] > 0)) { - // puts data before page footer - $pagebuff = $this->getPageBuffer($this->page); - $page = substr($pagebuff, 0, -$this->footerlen[$this->page]); - $footer = substr($pagebuff, -$this->footerlen[$this->page]); - $this->setPageBuffer($this->page, $page.$s."\n".$footer); - // update footer position - $this->footerpos[$this->page] += strlen($s."\n"); - } else { - // set page data - $this->setPageBuffer($this->page, $s."\n", true); - } - } elseif ($this->state > 0) { - // set general data - $this->setBuffer($s."\n"); - } - } - - /** - * Set header font. - * @param array<int,string|float|null> $font Array describing the basic font parameters: (family, style, size). - * @phpstan-param array{0: string, 1: string, 2: float|null} $font - * @public - * @since 1.1 - */ - public function setHeaderFont($font) { - $this->header_font = $font; - } - - /** - * Get header font. - * @return array<int,string|float|null> Array describing the basic font parameters: (family, style, size). - * @phpstan-return array{0: string, 1: string, 2: float|null} - * @public - * @since 4.0.012 (2008-07-24) - */ - public function getHeaderFont() { - return $this->header_font; - } - - /** - * Set footer font. - * @param array<int,string|float|null> $font Array describing the basic font parameters: (family, style, size). - * @phpstan-param array{0: string, 1: string, 2: float|null} $font - * @public - * @since 1.1 - */ - public function setFooterFont($font) { - $this->footer_font = $font; - } - - /** - * Get Footer font. - * @return array<int,string|float|null> Array describing the basic font parameters: (family, style, size). - * @phpstan-return array{0: string, 1: string, 2: float|null} $font - * @public - * @since 4.0.012 (2008-07-24) - */ - public function getFooterFont() { - return $this->footer_font; - } - - /** - * Set language array. - * @param array $language - * @public - * @since 1.1 - */ - public function setLanguageArray($language) { - $this->l = $language; - if (isset($this->l['a_meta_dir'])) { - $this->rtl = $this->l['a_meta_dir']=='rtl' ? true : false; - } else { - $this->rtl = false; - } - } - - /** - * Returns the PDF data. - * @public - */ - public function getPDFData() { - if ($this->state < 3) { - $this->Close(); - } - return $this->buffer; - } - - /** - * Output anchor link. - * @param string $url link URL or internal link (i.e.: &lt;a href="#23,4.5"&gt;link to page 23 at 4.5 Y position&lt;/a&gt;) - * @param string $name link name - * @param boolean $fill Indicates if the cell background must be painted (true) or transparent (false). - * @param boolean $firstline if true prints only the first line and return the remaining string. - * @param array|null $color array of RGB text color - * @param string $style font style (U, D, B, I) - * @param boolean $firstblock if true the string is the starting of a line. - * @return int the number of cells used or the remaining text if $firstline = true; - * @public - */ - public function addHtmlLink($url, $name, $fill=false, $firstline=false, $color=null, $style=-1, $firstblock=false) { - if (isset($url[1]) AND ($url[0] == '#') AND is_numeric($url[1])) { - // convert url to internal link - $lnkdata = explode(',', $url); - if (isset($lnkdata[0]) ) { - $page = substr($lnkdata[0], 1); - if (isset($lnkdata[1]) AND (strlen($lnkdata[1]) > 0)) { - $lnky = floatval($lnkdata[1]); - } else { - $lnky = 0; - } - $url = $this->AddLink(); - $this->setLink($url, $lnky, $page); - } - } - // store current settings - $prevcolor = $this->fgcolor; - $prevstyle = $this->FontStyle; - if (empty($color)) { - $this->setTextColorArray($this->htmlLinkColorArray); - } else { - $this->setTextColorArray($color); - } - if ($style == -1) { - $this->setFont('', $this->FontStyle.$this->htmlLinkFontStyle); - } else { - $this->setFont('', $this->FontStyle.$style); - } - $ret = $this->Write($this->lasth, $name, $url, $fill, '', false, 0, $firstline, $firstblock, 0); - // restore settings - $this->setFont('', $prevstyle); - $this->setTextColorArray($prevcolor); - return $ret; - } - - /** - * Converts pixels to User's Units. - * @param int $px pixels - * @return float value in user's unit - * @public - * @see setImageScale(), getImageScale() - */ - public function pixelsToUnits($px) { - return ($px / ($this->imgscale * $this->k)); - } - - /** - * Reverse function for htmlentities. - * Convert entities in UTF-8. - * @param string $text_to_convert Text to convert. - * @return string converted text string - * @public - */ - public function unhtmlentities($text_to_convert) { - return @html_entity_decode($text_to_convert, ENT_QUOTES, $this->encoding); - } - - // ENCRYPTION METHODS ---------------------------------- - - /** - * Compute encryption key depending on object number where the encrypted data is stored. - * This is used for all strings and streams without crypt filter specifier. - * @param int $n object number - * @return int object key - * @protected - * @author Nicola Asuni - * @since 2.0.000 (2008-01-02) - */ - protected function _objectkey($n) { - $objkey = $this->encryptdata['key'].pack('VXxx', $n); - if ($this->encryptdata['mode'] == 2) { // AES-128 - // AES padding - $objkey .= "\x73\x41\x6C\x54"; // sAlT - } - $objkey = substr(TCPDF_STATIC::_md5_16($objkey), 0, (($this->encryptdata['Length'] / 8) + 5)); - $objkey = substr($objkey, 0, 16); - return $objkey; - } - - /** - * Encrypt the input string. - * @param int $n object number - * @param string $s data string to encrypt - * @return string encrypted string - * @protected - * @author Nicola Asuni - * @since 5.0.005 (2010-05-11) - */ - protected function _encrypt_data($n, $s) { - if (!$this->encrypted) { - return $s; - } - switch ($this->encryptdata['mode']) { - case 0: // RC4-40 - case 1: { // RC4-128 - $s = TCPDF_STATIC::_RC4($this->_objectkey($n), $s, $this->last_enc_key, $this->last_enc_key_c); - break; - } - case 2: { // AES-128 - $s = TCPDF_STATIC::_AES($this->_objectkey($n), $s); - break; - } - case 3: { // AES-256 - $s = TCPDF_STATIC::_AES($this->encryptdata['key'], $s); - break; - } - } - return $s; - } - - /** - * Put encryption on PDF document. - * @protected - * @author Nicola Asuni - * @since 2.0.000 (2008-01-02) - */ - protected function _putencryption() { - if (!$this->encrypted) { - return; - } - $this->encryptdata['objid'] = $this->_newobj(); - $out = '<<'; - if (!isset($this->encryptdata['Filter']) OR empty($this->encryptdata['Filter'])) { - $this->encryptdata['Filter'] = 'Standard'; - } - $out .= ' /Filter /'.$this->encryptdata['Filter']; - if (isset($this->encryptdata['SubFilter']) AND !empty($this->encryptdata['SubFilter'])) { - $out .= ' /SubFilter /'.$this->encryptdata['SubFilter']; - } - if (!isset($this->encryptdata['V']) OR empty($this->encryptdata['V'])) { - $this->encryptdata['V'] = 1; - } - // V is a code specifying the algorithm to be used in encrypting and decrypting the document - $out .= ' /V '.$this->encryptdata['V']; - if (isset($this->encryptdata['Length']) AND !empty($this->encryptdata['Length'])) { - // The length of the encryption key, in bits. The value shall be a multiple of 8, in the range 40 to 256 - $out .= ' /Length '.$this->encryptdata['Length']; - } else { - $out .= ' /Length 40'; - } - if ($this->encryptdata['V'] >= 4) { - if (!isset($this->encryptdata['StmF']) OR empty($this->encryptdata['StmF'])) { - $this->encryptdata['StmF'] = 'Identity'; - } - if (!isset($this->encryptdata['StrF']) OR empty($this->encryptdata['StrF'])) { - // The name of the crypt filter that shall be used when decrypting all strings in the document. - $this->encryptdata['StrF'] = 'Identity'; - } - // A dictionary whose keys shall be crypt filter names and whose values shall be the corresponding crypt filter dictionaries. - if (isset($this->encryptdata['CF']) AND !empty($this->encryptdata['CF'])) { - $out .= ' /CF <<'; - $out .= ' /'.$this->encryptdata['StmF'].' <<'; - $out .= ' /Type /CryptFilter'; - if (isset($this->encryptdata['CF']['CFM']) AND !empty($this->encryptdata['CF']['CFM'])) { - // The method used - $out .= ' /CFM /'.$this->encryptdata['CF']['CFM']; - if ($this->encryptdata['pubkey']) { - $out .= ' /Recipients ['; - foreach ($this->encryptdata['Recipients'] as $rec) { - $out .= ' <'.$rec.'>'; - } - $out .= ' ]'; - if (isset($this->encryptdata['CF']['EncryptMetadata']) AND (!$this->encryptdata['CF']['EncryptMetadata'])) { - $out .= ' /EncryptMetadata false'; - } else { - $out .= ' /EncryptMetadata true'; - } - } - } else { - $out .= ' /CFM /None'; - } - if (isset($this->encryptdata['CF']['AuthEvent']) AND !empty($this->encryptdata['CF']['AuthEvent'])) { - // The event to be used to trigger the authorization that is required to access encryption keys used by this filter. - $out .= ' /AuthEvent /'.$this->encryptdata['CF']['AuthEvent']; - } else { - $out .= ' /AuthEvent /DocOpen'; - } - if (isset($this->encryptdata['CF']['Length']) AND !empty($this->encryptdata['CF']['Length'])) { - // The bit length of the encryption key. - $out .= ' /Length '.$this->encryptdata['CF']['Length']; - } - $out .= ' >> >>'; - } - // The name of the crypt filter that shall be used by default when decrypting streams. - $out .= ' /StmF /'.$this->encryptdata['StmF']; - // The name of the crypt filter that shall be used when decrypting all strings in the document. - $out .= ' /StrF /'.$this->encryptdata['StrF']; - if (isset($this->encryptdata['EFF']) AND !empty($this->encryptdata['EFF'])) { - // The name of the crypt filter that shall be used when encrypting embedded file streams that do not have their own crypt filter specifier. - $out .= ' /EFF /'.$this->encryptdata['']; - } - } - // Additional encryption dictionary entries for the standard security handler - if ($this->encryptdata['pubkey']) { - if (($this->encryptdata['V'] < 4) AND isset($this->encryptdata['Recipients']) AND !empty($this->encryptdata['Recipients'])) { - $out .= ' /Recipients ['; - foreach ($this->encryptdata['Recipients'] as $rec) { - $out .= ' <'.$rec.'>'; - } - $out .= ' ]'; - } - } else { - $out .= ' /R'; - if ($this->encryptdata['V'] == 5) { // AES-256 - $out .= ' 5'; - $out .= ' /OE ('.TCPDF_STATIC::_escape($this->encryptdata['OE']).')'; - $out .= ' /UE ('.TCPDF_STATIC::_escape($this->encryptdata['UE']).')'; - $out .= ' /Perms ('.TCPDF_STATIC::_escape($this->encryptdata['perms']).')'; - } elseif ($this->encryptdata['V'] == 4) { // AES-128 - $out .= ' 4'; - } elseif ($this->encryptdata['V'] < 2) { // RC-40 - $out .= ' 2'; - } else { // RC-128 - $out .= ' 3'; - } - $out .= ' /O ('.TCPDF_STATIC::_escape($this->encryptdata['O']).')'; - $out .= ' /U ('.TCPDF_STATIC::_escape($this->encryptdata['U']).')'; - $out .= ' /P '.$this->encryptdata['P']; - if (isset($this->encryptdata['EncryptMetadata']) AND (!$this->encryptdata['EncryptMetadata'])) { - $out .= ' /EncryptMetadata false'; - } else { - $out .= ' /EncryptMetadata true'; - } - } - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - } - - /** - * Compute U value (used for encryption) - * @return string U value - * @protected - * @since 2.0.000 (2008-01-02) - * @author Nicola Asuni - */ - protected function _Uvalue() { - if ($this->encryptdata['mode'] == 0) { // RC4-40 - return TCPDF_STATIC::_RC4($this->encryptdata['key'], TCPDF_STATIC::$enc_padding, $this->last_enc_key, $this->last_enc_key_c); - } elseif ($this->encryptdata['mode'] < 3) { // RC4-128, AES-128 - $tmp = TCPDF_STATIC::_md5_16(TCPDF_STATIC::$enc_padding.$this->encryptdata['fileid']); - $enc = TCPDF_STATIC::_RC4($this->encryptdata['key'], $tmp, $this->last_enc_key, $this->last_enc_key_c); - $len = strlen($tmp); - for ($i = 1; $i <= 19; ++$i) { - $ek = ''; - for ($j = 0; $j < $len; ++$j) { - $ek .= chr(ord($this->encryptdata['key'][$j]) ^ $i); - } - $enc = TCPDF_STATIC::_RC4($ek, $enc, $this->last_enc_key, $this->last_enc_key_c); - } - $enc .= str_repeat("\x00", 16); - return substr($enc, 0, 32); - } elseif ($this->encryptdata['mode'] == 3) { // AES-256 - $seed = TCPDF_STATIC::_md5_16(TCPDF_STATIC::getRandomSeed()); - // User Validation Salt - $this->encryptdata['UVS'] = substr($seed, 0, 8); - // User Key Salt - $this->encryptdata['UKS'] = substr($seed, 8, 16); - return hash('sha256', $this->encryptdata['user_password'].$this->encryptdata['UVS'], true).$this->encryptdata['UVS'].$this->encryptdata['UKS']; - } - } - - /** - * Compute UE value (used for encryption) - * @return string UE value - * @protected - * @since 5.9.006 (2010-10-19) - * @author Nicola Asuni - */ - protected function _UEvalue() { - $hashkey = hash('sha256', $this->encryptdata['user_password'].$this->encryptdata['UKS'], true); - return TCPDF_STATIC::_AESnopad($hashkey, $this->encryptdata['key']); - } - - /** - * Compute O value (used for encryption) - * @return string O value - * @protected - * @since 2.0.000 (2008-01-02) - * @author Nicola Asuni - */ - protected function _Ovalue() { - if ($this->encryptdata['mode'] < 3) { // RC4-40, RC4-128, AES-128 - $tmp = TCPDF_STATIC::_md5_16($this->encryptdata['owner_password']); - if ($this->encryptdata['mode'] > 0) { - for ($i = 0; $i < 50; ++$i) { - $tmp = TCPDF_STATIC::_md5_16($tmp); - } - } - $owner_key = substr($tmp, 0, ($this->encryptdata['Length'] / 8)); - $enc = TCPDF_STATIC::_RC4($owner_key, $this->encryptdata['user_password'], $this->last_enc_key, $this->last_enc_key_c); - if ($this->encryptdata['mode'] > 0) { - $len = strlen($owner_key); - for ($i = 1; $i <= 19; ++$i) { - $ek = ''; - for ($j = 0; $j < $len; ++$j) { - $ek .= chr(ord($owner_key[$j]) ^ $i); - } - $enc = TCPDF_STATIC::_RC4($ek, $enc, $this->last_enc_key, $this->last_enc_key_c); - } - } - return $enc; - } elseif ($this->encryptdata['mode'] == 3) { // AES-256 - $seed = TCPDF_STATIC::_md5_16(TCPDF_STATIC::getRandomSeed()); - // Owner Validation Salt - $this->encryptdata['OVS'] = substr($seed, 0, 8); - // Owner Key Salt - $this->encryptdata['OKS'] = substr($seed, 8, 16); - return hash('sha256', $this->encryptdata['owner_password'].$this->encryptdata['OVS'].$this->encryptdata['U'], true).$this->encryptdata['OVS'].$this->encryptdata['OKS']; - } - } - - /** - * Compute OE value (used for encryption) - * @return string OE value - * @protected - * @since 5.9.006 (2010-10-19) - * @author Nicola Asuni - */ - protected function _OEvalue() { - $hashkey = hash('sha256', $this->encryptdata['owner_password'].$this->encryptdata['OKS'].$this->encryptdata['U'], true); - return TCPDF_STATIC::_AESnopad($hashkey, $this->encryptdata['key']); - } - - /** - * Convert password for AES-256 encryption mode - * @param string $password password - * @return string password - * @protected - * @since 5.9.006 (2010-10-19) - * @author Nicola Asuni - */ - protected function _fixAES256Password($password) { - $psw = ''; // password to be returned - $psw_array = TCPDF_FONTS::utf8Bidi(TCPDF_FONTS::UTF8StringToArray($password, $this->isunicode, $this->CurrentFont), $password, $this->rtl, $this->isunicode, $this->CurrentFont); - foreach ($psw_array as $c) { - $psw .= TCPDF_FONTS::unichr($c, $this->isunicode); - } - return substr($psw, 0, 127); - } - - /** - * Compute encryption key - * @protected - * @since 2.0.000 (2008-01-02) - * @author Nicola Asuni - */ - protected function _generateencryptionkey() { - $keybytelen = ($this->encryptdata['Length'] / 8); - if (!$this->encryptdata['pubkey']) { // standard mode - if ($this->encryptdata['mode'] == 3) { // AES-256 - // generate 256 bit random key - $this->encryptdata['key'] = substr(hash('sha256', TCPDF_STATIC::getRandomSeed(), true), 0, $keybytelen); - // truncate passwords - $this->encryptdata['user_password'] = $this->_fixAES256Password($this->encryptdata['user_password']); - $this->encryptdata['owner_password'] = $this->_fixAES256Password($this->encryptdata['owner_password']); - // Compute U value - $this->encryptdata['U'] = $this->_Uvalue(); - // Compute UE value - $this->encryptdata['UE'] = $this->_UEvalue(); - // Compute O value - $this->encryptdata['O'] = $this->_Ovalue(); - // Compute OE value - $this->encryptdata['OE'] = $this->_OEvalue(); - // Compute P value - $this->encryptdata['P'] = $this->encryptdata['protection']; - // Computing the encryption dictionary's Perms (permissions) value - $perms = TCPDF_STATIC::getEncPermissionsString($this->encryptdata['protection']); // bytes 0-3 - $perms .= chr(255).chr(255).chr(255).chr(255); // bytes 4-7 - if (isset($this->encryptdata['CF']['EncryptMetadata']) AND (!$this->encryptdata['CF']['EncryptMetadata'])) { // byte 8 - $perms .= 'F'; - } else { - $perms .= 'T'; - } - $perms .= 'adb'; // bytes 9-11 - $perms .= 'nick'; // bytes 12-15 - $this->encryptdata['perms'] = TCPDF_STATIC::_AESnopad($this->encryptdata['key'], $perms); - } else { // RC4-40, RC4-128, AES-128 - // Pad passwords - $this->encryptdata['user_password'] = substr($this->encryptdata['user_password'].TCPDF_STATIC::$enc_padding, 0, 32); - $this->encryptdata['owner_password'] = substr($this->encryptdata['owner_password'].TCPDF_STATIC::$enc_padding, 0, 32); - // Compute O value - $this->encryptdata['O'] = $this->_Ovalue(); - // get default permissions (reverse byte order) - $permissions = TCPDF_STATIC::getEncPermissionsString($this->encryptdata['protection']); - // Compute encryption key - $tmp = TCPDF_STATIC::_md5_16($this->encryptdata['user_password'].$this->encryptdata['O'].$permissions.$this->encryptdata['fileid']); - if ($this->encryptdata['mode'] > 0) { - for ($i = 0; $i < 50; ++$i) { - $tmp = TCPDF_STATIC::_md5_16(substr($tmp, 0, $keybytelen)); - } - } - $this->encryptdata['key'] = substr($tmp, 0, $keybytelen); - // Compute U value - $this->encryptdata['U'] = $this->_Uvalue(); - // Compute P value - $this->encryptdata['P'] = $this->encryptdata['protection']; - } - } else { // Public-Key mode - // random 20-byte seed - $seed = sha1(TCPDF_STATIC::getRandomSeed(), true); - $recipient_bytes = ''; - foreach ($this->encryptdata['pubkeys'] as $pubkey) { - // for each public certificate - if (isset($pubkey['p'])) { - $pkprotection = TCPDF_STATIC::getUserPermissionCode($pubkey['p'], $this->encryptdata['mode']); - } else { - $pkprotection = $this->encryptdata['protection']; - } - // get default permissions (reverse byte order) - $pkpermissions = TCPDF_STATIC::getEncPermissionsString($pkprotection); - // envelope data - $envelope = $seed.$pkpermissions; - // write the envelope data to a temporary file - $tempkeyfile = TCPDF_STATIC::getObjFilename('key', $this->file_id); - $f = TCPDF_STATIC::fopenLocal($tempkeyfile, 'wb'); - if (!$f) { - $this->Error('Unable to create temporary key file: '.$tempkeyfile); - } - $envelope_length = strlen($envelope); - fwrite($f, $envelope, $envelope_length); - fclose($f); - $tempencfile = TCPDF_STATIC::getObjFilename('enc', $this->file_id); - if (!openssl_pkcs7_encrypt($tempkeyfile, $tempencfile, $pubkey['c'], array(), PKCS7_BINARY | PKCS7_DETACHED)) { - $this->Error('Unable to encrypt the file: '.$tempkeyfile); - } - // read encryption signature - $signature = file_get_contents($tempencfile, false, null, $envelope_length); - // extract signature - $signature = substr($signature, strpos($signature, 'Content-Disposition')); - $tmparr = explode("\n\n", $signature); - $signature = trim($tmparr[1]); - unset($tmparr); - // decode signature - $signature = base64_decode($signature); - // convert signature to hex - $hexsignature = current(unpack('H*', $signature)); - // store signature on recipients array - $this->encryptdata['Recipients'][] = $hexsignature; - // The bytes of each item in the Recipients array of PKCS#7 objects in the order in which they appear in the array - $recipient_bytes .= $signature; - } - // calculate encryption key - if ($this->encryptdata['mode'] == 3) { // AES-256 - $this->encryptdata['key'] = substr(hash('sha256', $seed.$recipient_bytes, true), 0, $keybytelen); - } else { // RC4-40, RC4-128, AES-128 - $this->encryptdata['key'] = substr(sha1($seed.$recipient_bytes, true), 0, $keybytelen); - } - } - } - - /** - * Set document protection - * Remark: the protection against modification is for people who have the full Acrobat product. - * If you don't set any password, the document will open as usual. If you set a user password, the PDF viewer will ask for it before displaying the document. The master password, if different from the user one, can be used to get full access. - * Note: protecting a document requires to encrypt it, which increases the processing time a lot. This can cause a PHP time-out in some cases, especially if the document contains images or fonts. - * @param array $permissions the set of permissions (specify the ones you want to block):<ul><li>print : Print the document;</li><li>modify : Modify the contents of the document by operations other than those controlled by 'fill-forms', 'extract' and 'assemble';</li><li>copy : Copy or otherwise extract text and graphics from the document;</li><li>annot-forms : Add or modify text annotations, fill in interactive form fields, and, if 'modify' is also set, create or modify interactive form fields (including signature fields);</li><li>fill-forms : Fill in existing interactive form fields (including signature fields), even if 'annot-forms' is not specified;</li><li>extract : Extract text and graphics (in support of accessibility to users with disabilities or for other purposes);</li><li>assemble : Assemble the document (insert, rotate, or delete pages and create bookmarks or thumbnail images), even if 'modify' is not set;</li><li>print-high : Print the document to a representation from which a faithful digital copy of the PDF content could be generated. When this is not set, printing is limited to a low-level representation of the appearance, possibly of degraded quality.</li><li>owner : (inverted logic - only for public-key) when set permits change of encryption and enables all other permissions.</li></ul> - * @param string $user_pass user password. Empty by default. - * @param string|null $owner_pass owner password. If not specified, a random value is used. - * @param int $mode encryption strength: 0 = RC4 40 bit; 1 = RC4 128 bit; 2 = AES 128 bit; 3 = AES 256 bit. - * @param array|null $pubkeys array of recipients containing public-key certificates ('c') and permissions ('p'). For example: array(array('c' => 'file://../examples/data/cert/tcpdf.crt', 'p' => array('print'))) - * @public - * @since 2.0.000 (2008-01-02) - * @author Nicola Asuni - */ - public function setProtection($permissions=array('print', 'modify', 'copy', 'annot-forms', 'fill-forms', 'extract', 'assemble', 'print-high'), $user_pass='', $owner_pass=null, $mode=0, $pubkeys=null) { - if ($this->pdfa_mode) { - // encryption is not allowed in PDF/A mode - return; - } - $this->encryptdata['protection'] = TCPDF_STATIC::getUserPermissionCode($permissions, $mode); - if (($pubkeys !== null) AND (is_array($pubkeys))) { - // public-key mode - $this->encryptdata['pubkeys'] = $pubkeys; - if ($mode == 0) { - // public-Key Security requires at least 128 bit - $mode = 1; - } - if (!function_exists('openssl_pkcs7_encrypt')) { - $this->Error('Public-Key Security requires openssl library.'); - } - // Set Public-Key filter (available are: Entrust.PPKEF, Adobe.PPKLite, Adobe.PubSec) - $this->encryptdata['pubkey'] = true; - $this->encryptdata['Filter'] = 'Adobe.PubSec'; - $this->encryptdata['StmF'] = 'DefaultCryptFilter'; - $this->encryptdata['StrF'] = 'DefaultCryptFilter'; - } else { - // standard mode (password mode) - $this->encryptdata['pubkey'] = false; - $this->encryptdata['Filter'] = 'Standard'; - $this->encryptdata['StmF'] = 'StdCF'; - $this->encryptdata['StrF'] = 'StdCF'; - } - if ($mode > 1) { // AES - if (!extension_loaded('openssl') && !extension_loaded('mcrypt')) { - $this->Error('AES encryption requires openssl or mcrypt extension (http://www.php.net/manual/en/mcrypt.requirements.php).'); - } - if (extension_loaded('openssl') && !in_array('aes-256-cbc', openssl_get_cipher_methods())) { - $this->Error('AES encryption requires openssl/aes-256-cbc cypher.'); - } - if (extension_loaded('mcrypt') && mcrypt_get_cipher_name(MCRYPT_RIJNDAEL_128) === false) { - $this->Error('AES encryption requires MCRYPT_RIJNDAEL_128 cypher.'); - } - if (($mode == 3) AND !function_exists('hash')) { - // the Hash extension requires no external libraries and is enabled by default as of PHP 5.1.2. - $this->Error('AES 256 encryption requires HASH Message Digest Framework (http://www.php.net/manual/en/book.hash.php).'); - } - } - if ($owner_pass === null) { - $owner_pass = md5(TCPDF_STATIC::getRandomSeed()); - } - $this->encryptdata['user_password'] = $user_pass; - $this->encryptdata['owner_password'] = $owner_pass; - $this->encryptdata['mode'] = $mode; - switch ($mode) { - case 0: { // RC4 40 bit - $this->encryptdata['V'] = 1; - $this->encryptdata['Length'] = 40; - $this->encryptdata['CF']['CFM'] = 'V2'; - break; - } - case 1: { // RC4 128 bit - $this->encryptdata['V'] = 2; - $this->encryptdata['Length'] = 128; - $this->encryptdata['CF']['CFM'] = 'V2'; - if ($this->encryptdata['pubkey']) { - $this->encryptdata['SubFilter'] = 'adbe.pkcs7.s4'; - $this->encryptdata['Recipients'] = array(); - } - break; - } - case 2: { // AES 128 bit - $this->encryptdata['V'] = 4; - $this->encryptdata['Length'] = 128; - $this->encryptdata['CF']['CFM'] = 'AESV2'; - $this->encryptdata['CF']['Length'] = 128; - if ($this->encryptdata['pubkey']) { - $this->encryptdata['SubFilter'] = 'adbe.pkcs7.s5'; - $this->encryptdata['Recipients'] = array(); - } - break; - } - case 3: { // AES 256 bit - $this->encryptdata['V'] = 5; - $this->encryptdata['Length'] = 256; - $this->encryptdata['CF']['CFM'] = 'AESV3'; - $this->encryptdata['CF']['Length'] = 256; - if ($this->encryptdata['pubkey']) { - $this->encryptdata['SubFilter'] = 'adbe.pkcs7.s5'; - $this->encryptdata['Recipients'] = array(); - } - break; - } - } - $this->encrypted = true; - $this->encryptdata['fileid'] = TCPDF_STATIC::convertHexStringToString($this->file_id); - $this->_generateencryptionkey(); - } - - // END OF ENCRYPTION FUNCTIONS ------------------------- - - // START TRANSFORMATIONS SECTION ----------------------- - - /** - * Starts a 2D tranformation saving current graphic state. - * This function must be called before scaling, mirroring, translation, rotation and skewing. - * Use StartTransform() before, and StopTransform() after the transformations to restore the normal behavior. - * @public - * @since 2.1.000 (2008-01-07) - * @see StartTransform(), StopTransform() - */ - public function StartTransform() { - if ($this->state != 2) { - return; - } - $this->_outSaveGraphicsState(); - if ($this->inxobj) { - // we are inside an XObject template - $this->xobjects[$this->xobjid]['transfmrk'][] = strlen($this->xobjects[$this->xobjid]['outdata']); - } else { - $this->transfmrk[$this->page][] = $this->pagelen[$this->page]; - } - ++$this->transfmatrix_key; - $this->transfmatrix[$this->transfmatrix_key] = array(); - } - - /** - * Stops a 2D tranformation restoring previous graphic state. - * This function must be called after scaling, mirroring, translation, rotation and skewing. - * Use StartTransform() before, and StopTransform() after the transformations to restore the normal behavior. - * @public - * @since 2.1.000 (2008-01-07) - * @see StartTransform(), StopTransform() - */ - public function StopTransform() { - if ($this->state != 2) { - return; - } - $this->_outRestoreGraphicsState(); - if (isset($this->transfmatrix[$this->transfmatrix_key])) { - array_pop($this->transfmatrix[$this->transfmatrix_key]); - --$this->transfmatrix_key; - } - if ($this->inxobj) { - // we are inside an XObject template - array_pop($this->xobjects[$this->xobjid]['transfmrk']); - } else { - array_pop($this->transfmrk[$this->page]); - } - } - /** - * Horizontal Scaling. - * @param float $s_x scaling factor for width as percent. 0 is not allowed. - * @param int $x abscissa of the scaling center. Default is current x position - * @param int $y ordinate of the scaling center. Default is current y position - * @public - * @since 2.1.000 (2008-01-07) - * @see StartTransform(), StopTransform() - */ - public function ScaleX($s_x, $x='', $y='') { - $this->Scale($s_x, 100, $x, $y); - } - - /** - * Vertical Scaling. - * @param float $s_y scaling factor for height as percent. 0 is not allowed. - * @param int $x abscissa of the scaling center. Default is current x position - * @param int $y ordinate of the scaling center. Default is current y position - * @public - * @since 2.1.000 (2008-01-07) - * @see StartTransform(), StopTransform() - */ - public function ScaleY($s_y, $x='', $y='') { - $this->Scale(100, $s_y, $x, $y); - } - - /** - * Vertical and horizontal proportional Scaling. - * @param float $s scaling factor for width and height as percent. 0 is not allowed. - * @param int $x abscissa of the scaling center. Default is current x position - * @param int $y ordinate of the scaling center. Default is current y position - * @public - * @since 2.1.000 (2008-01-07) - * @see StartTransform(), StopTransform() - */ - public function ScaleXY($s, $x='', $y='') { - $this->Scale($s, $s, $x, $y); - } - - /** - * Vertical and horizontal non-proportional Scaling. - * @param float $s_x scaling factor for width as percent. 0 is not allowed. - * @param float $s_y scaling factor for height as percent. 0 is not allowed. - * @param float|null $x abscissa of the scaling center. Default is current x position - * @param float|null $y ordinate of the scaling center. Default is current y position - * @public - * @since 2.1.000 (2008-01-07) - * @see StartTransform(), StopTransform() - */ - public function Scale($s_x, $s_y, $x=null, $y=null) { - if (TCPDF_STATIC::empty_string($x)) { - $x = $this->x; - } - if (TCPDF_STATIC::empty_string($y)) { - $y = $this->y; - } - if (($s_x == 0) OR ($s_y == 0)) { - $this->Error('Please do not use values equal to zero for scaling'); - } - $y = ($this->h - $y) * $this->k; - $x *= $this->k; - //calculate elements of transformation matrix - $s_x /= 100; - $s_y /= 100; - $tm = array(); - $tm[0] = $s_x; - $tm[1] = 0; - $tm[2] = 0; - $tm[3] = $s_y; - $tm[4] = $x * (1 - $s_x); - $tm[5] = $y * (1 - $s_y); - //scale the coordinate system - $this->Transform($tm); - } - - /** - * Horizontal Mirroring. - * @param float|null $x abscissa of the point. Default is current x position - * @public - * @since 2.1.000 (2008-01-07) - * @see StartTransform(), StopTransform() - */ - public function MirrorH($x=null) { - $this->Scale(-100, 100, $x); - } - - /** - * Verical Mirroring. - * @param float|null $y ordinate of the point. Default is current y position - * @public - * @since 2.1.000 (2008-01-07) - * @see StartTransform(), StopTransform() - */ - public function MirrorV($y=null) { - $this->Scale(100, -100, null, $y); - } - - /** - * Point reflection mirroring. - * @param float|null $x abscissa of the point. Default is current x position - * @param float|null $y ordinate of the point. Default is current y position - * @public - * @since 2.1.000 (2008-01-07) - * @see StartTransform(), StopTransform() - */ - public function MirrorP($x=null,$y=null) { - $this->Scale(-100, -100, $x, $y); - } - - /** - * Reflection against a straight line through point (x, y) with the gradient angle (angle). - * @param float $angle gradient angle of the straight line. Default is 0 (horizontal line). - * @param float|null $x abscissa of the point. Default is current x position - * @param float|null $y ordinate of the point. Default is current y position - * @public - * @since 2.1.000 (2008-01-07) - * @see StartTransform(), StopTransform() - */ - public function MirrorL($angle=0, $x=null,$y=null) { - $this->Scale(-100, 100, $x, $y); - $this->Rotate(-2*($angle-90), $x, $y); - } - - /** - * Translate graphic object horizontally. - * @param int $t_x movement to the right (or left for RTL) - * @public - * @since 2.1.000 (2008-01-07) - * @see StartTransform(), StopTransform() - */ - public function TranslateX($t_x) { - $this->Translate($t_x, 0); - } - - /** - * Translate graphic object vertically. - * @param int $t_y movement to the bottom - * @public - * @since 2.1.000 (2008-01-07) - * @see StartTransform(), StopTransform() - */ - public function TranslateY($t_y) { - $this->Translate(0, $t_y); - } - - /** - * Translate graphic object horizontally and vertically. - * @param int $t_x movement to the right - * @param int $t_y movement to the bottom - * @public - * @since 2.1.000 (2008-01-07) - * @see StartTransform(), StopTransform() - */ - public function Translate($t_x, $t_y) { - //calculate elements of transformation matrix - $tm = array(); - $tm[0] = 1; - $tm[1] = 0; - $tm[2] = 0; - $tm[3] = 1; - $tm[4] = $t_x * $this->k; - $tm[5] = -$t_y * $this->k; - //translate the coordinate system - $this->Transform($tm); - } - - /** - * Rotate object. - * @param float $angle angle in degrees for counter-clockwise rotation - * @param float|null $x abscissa of the rotation center. Default is current x position - * @param float|null $y ordinate of the rotation center. Default is current y position - * @public - * @since 2.1.000 (2008-01-07) - * @see StartTransform(), StopTransform() - */ - public function Rotate($angle, $x=null, $y=null) { - if (TCPDF_STATIC::empty_string($x)) { - $x = $this->x; - } - if (TCPDF_STATIC::empty_string($y)) { - $y = $this->y; - } - $y = ($this->h - $y) * $this->k; - $x *= $this->k; - //calculate elements of transformation matrix - $tm = array(); - $tm[0] = cos(deg2rad($angle)); - $tm[1] = sin(deg2rad($angle)); - $tm[2] = -$tm[1]; - $tm[3] = $tm[0]; - $tm[4] = $x + ($tm[1] * $y) - ($tm[0] * $x); - $tm[5] = $y - ($tm[0] * $y) - ($tm[1] * $x); - //rotate the coordinate system around ($x,$y) - $this->Transform($tm); - } - - /** - * Skew horizontally. - * @param float $angle_x angle in degrees between -90 (skew to the left) and 90 (skew to the right) - * @param float|null $x abscissa of the skewing center. default is current x position - * @param float|null $y ordinate of the skewing center. default is current y position - * @public - * @since 2.1.000 (2008-01-07) - * @see StartTransform(), StopTransform() - */ - public function SkewX($angle_x, $x=null, $y=null) { - $this->Skew($angle_x, 0, $x, $y); - } - - /** - * Skew vertically. - * @param float $angle_y angle in degrees between -90 (skew to the bottom) and 90 (skew to the top) - * @param float|null $x abscissa of the skewing center. default is current x position - * @param float|null $y ordinate of the skewing center. default is current y position - * @public - * @since 2.1.000 (2008-01-07) - * @see StartTransform(), StopTransform() - */ - public function SkewY($angle_y, $x=null, $y=null) { - $this->Skew(0, $angle_y, $x, $y); - } - - /** - * Skew. - * @param float $angle_x angle in degrees between -90 (skew to the left) and 90 (skew to the right) - * @param float $angle_y angle in degrees between -90 (skew to the bottom) and 90 (skew to the top) - * @param float|null $x abscissa of the skewing center. default is current x position - * @param float|null $y ordinate of the skewing center. default is current y position - * @public - * @since 2.1.000 (2008-01-07) - * @see StartTransform(), StopTransform() - */ - public function Skew($angle_x, $angle_y, $x=null, $y=null) { - if (TCPDF_STATIC::empty_string($x)) { - $x = $this->x; - } - if (TCPDF_STATIC::empty_string($y)) { - $y = $this->y; - } - if (($angle_x <= -90) OR ($angle_x >= 90) OR ($angle_y <= -90) OR ($angle_y >= 90)) { - $this->Error('Please use values between -90 and +90 degrees for Skewing.'); - } - $x *= $this->k; - $y = ($this->h - $y) * $this->k; - //calculate elements of transformation matrix - $tm = array(); - $tm[0] = 1; - $tm[1] = tan(deg2rad($angle_y)); - $tm[2] = tan(deg2rad($angle_x)); - $tm[3] = 1; - $tm[4] = -$tm[2] * $y; - $tm[5] = -$tm[1] * $x; - //skew the coordinate system - $this->Transform($tm); - } - - /** - * Apply graphic transformations. - * @param array $tm transformation matrix - * @protected - * @since 2.1.000 (2008-01-07) - * @see StartTransform(), StopTransform() - */ - protected function Transform($tm) { - if ($this->state != 2) { - return; - } - $this->_out(sprintf('%F %F %F %F %F %F cm', $tm[0], $tm[1], $tm[2], $tm[3], $tm[4], $tm[5])); - // add tranformation matrix - $this->transfmatrix[$this->transfmatrix_key][] = array('a' => $tm[0], 'b' => $tm[1], 'c' => $tm[2], 'd' => $tm[3], 'e' => $tm[4], 'f' => $tm[5]); - // update transformation mark - if ($this->inxobj) { - // we are inside an XObject template - if (end($this->xobjects[$this->xobjid]['transfmrk']) !== false) { - $key = key($this->xobjects[$this->xobjid]['transfmrk']); - $this->xobjects[$this->xobjid]['transfmrk'][$key] = strlen($this->xobjects[$this->xobjid]['outdata']); - } - } elseif (end($this->transfmrk[$this->page]) !== false) { - $key = key($this->transfmrk[$this->page]); - $this->transfmrk[$this->page][$key] = $this->pagelen[$this->page]; - } - } - - // END TRANSFORMATIONS SECTION ------------------------- - - // START GRAPHIC FUNCTIONS SECTION --------------------- - // The following section is based on the code provided by David Hernandez Sanz - - /** - * Defines the line width. By default, the value equals 0.2 mm. The method can be called before the first page is created and the value is retained from page to page. - * @param float $width The width. - * @public - * @since 1.0 - * @see Line(), Rect(), Cell(), MultiCell() - */ - public function setLineWidth($width) { - //Set line width - $this->LineWidth = $width; - $this->linestyleWidth = sprintf('%F w', ($width * $this->k)); - if ($this->state == 2) { - $this->_out($this->linestyleWidth); - } - } - - /** - * Returns the current the line width. - * @return int Line width - * @public - * @since 2.1.000 (2008-01-07) - * @see Line(), SetLineWidth() - */ - public function GetLineWidth() { - return $this->LineWidth; - } - - /** - * Set line style. - * @param array $style Line style. Array with keys among the following: - * <ul> - * <li>width (float): Width of the line in user units.</li> - * <li>cap (string): Type of cap to put on the line. Possible values are: - * butt, round, square. The difference between "square" and "butt" is that - * "square" projects a flat end past the end of the line.</li> - * <li>join (string): Type of join. Possible values are: miter, round, - * bevel.</li> - * <li>dash (mixed): Dash pattern. Is 0 (without dash) or string with - * series of length values, which are the lengths of the on and off dashes. - * For example: "2" represents 2 on, 2 off, 2 on, 2 off, ...; "2,1" is 2 on, - * 1 off, 2 on, 1 off, ...</li> - * <li>phase (integer): Modifier on the dash pattern which is used to shift - * the point at which the pattern starts.</li> - * <li>color (array): Draw color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName).</li> - * </ul> - * @param boolean $ret if true do not send the command. - * @return string the PDF command - * @public - * @since 2.1.000 (2008-01-08) - */ - public function setLineStyle($style, $ret=false) { - $s = ''; // string to be returned - if (!is_array($style)) { - return $s; - } - if (isset($style['width'])) { - $this->LineWidth = $style['width']; - $this->linestyleWidth = sprintf('%F w', ($style['width'] * $this->k)); - $s .= $this->linestyleWidth.' '; - } - if (isset($style['cap'])) { - $ca = array('butt' => 0, 'round'=> 1, 'square' => 2); - if (isset($ca[$style['cap']])) { - $this->linestyleCap = $ca[$style['cap']].' J'; - $s .= $this->linestyleCap.' '; - } - } - if (isset($style['join'])) { - $ja = array('miter' => 0, 'round' => 1, 'bevel' => 2); - if (isset($ja[$style['join']])) { - $this->linestyleJoin = $ja[$style['join']].' j'; - $s .= $this->linestyleJoin.' '; - } - } - if (isset($style['dash'])) { - $dash_string = ''; - if ($style['dash']) { - if (preg_match('/^.+,/', $style['dash']) > 0) { - $tab = explode(',', $style['dash']); - } else { - $tab = array($style['dash']); - } - $dash_string = ''; - foreach ($tab as $i => $v) { - if ($i) { - $dash_string .= ' '; - } - $dash_string .= sprintf('%F', $v); - } - } - if (!isset($style['phase']) OR !$style['dash']) { - $style['phase'] = 0; - } - $this->linestyleDash = sprintf('[%s] %F d', $dash_string, $style['phase']); - $s .= $this->linestyleDash.' '; - } - if (isset($style['color'])) { - $s .= $this->setDrawColorArray($style['color'], true).' '; - } - if (!$ret AND ($this->state == 2)) { - $this->_out($s); - } - return $s; - } - - /** - * Begin a new subpath by moving the current point to coordinates (x, y), omitting any connecting line segment. - * @param float $x Abscissa of point. - * @param float $y Ordinate of point. - * @protected - * @since 2.1.000 (2008-01-08) - */ - protected function _outPoint($x, $y) { - if ($this->state == 2) { - $this->_out(sprintf('%F %F m', ($x * $this->k), (($this->h - $y) * $this->k))); - } - } - - /** - * Append a straight line segment from the current point to the point (x, y). - * The new current point shall be (x, y). - * @param float $x Abscissa of end point. - * @param float $y Ordinate of end point. - * @protected - * @since 2.1.000 (2008-01-08) - */ - protected function _outLine($x, $y) { - if ($this->state == 2) { - $this->_out(sprintf('%F %F l', ($x * $this->k), (($this->h - $y) * $this->k))); - } - } - - /** - * Append a rectangle to the current path as a complete subpath, with lower-left corner (x, y) and dimensions widthand height in user space. - * @param float $x Abscissa of upper-left corner. - * @param float $y Ordinate of upper-left corner. - * @param float $w Width. - * @param float $h Height. - * @param string $op options - * @protected - * @since 2.1.000 (2008-01-08) - */ - protected function _outRect($x, $y, $w, $h, $op) { - if ($this->state == 2) { - $this->_out(sprintf('%F %F %F %F re %s', ($x * $this->k), (($this->h - $y) * $this->k), ($w * $this->k), (-$h * $this->k), $op)); - } - } - - /** - * Append a cubic Bezier curve to the current path. The curve shall extend from the current point to the point (x3, y3), using (x1, y1) and (x2, y2) as the Bezier control points. - * The new current point shall be (x3, y3). - * @param float $x1 Abscissa of control point 1. - * @param float $y1 Ordinate of control point 1. - * @param float $x2 Abscissa of control point 2. - * @param float $y2 Ordinate of control point 2. - * @param float $x3 Abscissa of end point. - * @param float $y3 Ordinate of end point. - * @protected - * @since 2.1.000 (2008-01-08) - */ - protected function _outCurve($x1, $y1, $x2, $y2, $x3, $y3) { - if ($this->state == 2) { - $this->_out(sprintf('%F %F %F %F %F %F c', ($x1 * $this->k), (($this->h - $y1) * $this->k), ($x2 * $this->k), (($this->h - $y2) * $this->k), ($x3 * $this->k), (($this->h - $y3) * $this->k))); - } - } - - /** - * Append a cubic Bezier curve to the current path. The curve shall extend from the current point to the point (x3, y3), using the current point and (x2, y2) as the Bezier control points. - * The new current point shall be (x3, y3). - * @param float $x2 Abscissa of control point 2. - * @param float $y2 Ordinate of control point 2. - * @param float $x3 Abscissa of end point. - * @param float $y3 Ordinate of end point. - * @protected - * @since 4.9.019 (2010-04-26) - */ - protected function _outCurveV($x2, $y2, $x3, $y3) { - if ($this->state == 2) { - $this->_out(sprintf('%F %F %F %F v', ($x2 * $this->k), (($this->h - $y2) * $this->k), ($x3 * $this->k), (($this->h - $y3) * $this->k))); - } - } - - /** - * Append a cubic Bezier curve to the current path. The curve shall extend from the current point to the point (x3, y3), using (x1, y1) and (x3, y3) as the Bezier control points. - * The new current point shall be (x3, y3). - * @param float $x1 Abscissa of control point 1. - * @param float $y1 Ordinate of control point 1. - * @param float $x3 Abscissa of end point. - * @param float $y3 Ordinate of end point. - * @protected - * @since 2.1.000 (2008-01-08) - */ - protected function _outCurveY($x1, $y1, $x3, $y3) { - if ($this->state == 2) { - $this->_out(sprintf('%F %F %F %F y', ($x1 * $this->k), (($this->h - $y1) * $this->k), ($x3 * $this->k), (($this->h - $y3) * $this->k))); - } - } - - /** - * Draws a line between two points. - * @param float $x1 Abscissa of first point. - * @param float $y1 Ordinate of first point. - * @param float $x2 Abscissa of second point. - * @param float $y2 Ordinate of second point. - * @param array $style Line style. Array like for SetLineStyle(). Default value: default line style (empty array). - * @public - * @since 1.0 - * @see SetLineWidth(), SetDrawColor(), SetLineStyle() - */ - public function Line($x1, $y1, $x2, $y2, $style=array()) { - if ($this->state != 2) { - return; - } - if (is_array($style)) { - $this->setLineStyle($style); - } - $this->_outPoint($x1, $y1); - $this->_outLine($x2, $y2); - $this->_out('S'); - } - - /** - * Draws a rectangle. - * @param float $x Abscissa of upper-left corner. - * @param float $y Ordinate of upper-left corner. - * @param float $w Width. - * @param float $h Height. - * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. - * @param array $border_style Border style of rectangle. Array with keys among the following: - * <ul> - * <li>all: Line style of all borders. Array like for SetLineStyle().</li> - * <li>L, T, R, B or combinations: Line style of left, top, right or bottom border. Array like for SetLineStyle().</li> - * </ul> - * If a key is not present or is null, the correspondent border is not drawn. Default value: default line style (empty array). - * @param array $fill_color Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName). Default value: default color (empty array). - * @public - * @since 1.0 - * @see SetLineStyle() - */ - public function Rect($x, $y, $w, $h, $style='', $border_style=array(), $fill_color=array()) { - if ($this->state != 2) { - return; - } - if (empty($style)) { - $style = 'S'; - } - if (!(strpos($style, 'F') === false) AND !empty($fill_color)) { - // set background color - $this->setFillColorArray($fill_color); - } - if (!empty($border_style)) { - if (isset($border_style['all']) AND !empty($border_style['all'])) { - //set global style for border - $this->setLineStyle($border_style['all']); - $border_style = array(); - } else { - // remove stroke operator from style - $opnostroke = array('S' => '', 'D' => '', 's' => '', 'd' => '', 'B' => 'F', 'FD' => 'F', 'DF' => 'F', 'B*' => 'F*', 'F*D' => 'F*', 'DF*' => 'F*', 'b' => 'f', 'fd' => 'f', 'df' => 'f', 'b*' => 'f*', 'f*d' => 'f*', 'df*' => 'f*' ); - if (isset($opnostroke[$style])) { - $style = $opnostroke[$style]; - } - } - } - if (!empty($style)) { - $op = TCPDF_STATIC::getPathPaintOperator($style); - $this->_outRect($x, $y, $w, $h, $op); - } - if (!empty($border_style)) { - $border_style2 = array(); - foreach ($border_style as $line => $value) { - $length = strlen($line); - for ($i = 0; $i < $length; ++$i) { - $border_style2[$line[$i]] = $value; - } - } - $border_style = $border_style2; - if (isset($border_style['L']) AND $border_style['L']) { - $this->Line($x, $y, $x, $y + $h, $border_style['L']); - } - if (isset($border_style['T']) AND $border_style['T']) { - $this->Line($x, $y, $x + $w, $y, $border_style['T']); - } - if (isset($border_style['R']) AND $border_style['R']) { - $this->Line($x + $w, $y, $x + $w, $y + $h, $border_style['R']); - } - if (isset($border_style['B']) AND $border_style['B']) { - $this->Line($x, $y + $h, $x + $w, $y + $h, $border_style['B']); - } - } - } - - /** - * Draws a Bezier curve. - * The Bezier curve is a tangent to the line between the control points at - * either end of the curve. - * @param float $x0 Abscissa of start point. - * @param float $y0 Ordinate of start point. - * @param float $x1 Abscissa of control point 1. - * @param float $y1 Ordinate of control point 1. - * @param float $x2 Abscissa of control point 2. - * @param float $y2 Ordinate of control point 2. - * @param float $x3 Abscissa of end point. - * @param float $y3 Ordinate of end point. - * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. - * @param array $line_style Line style of curve. Array like for SetLineStyle(). Default value: default line style (empty array). - * @param array $fill_color Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName). Default value: default color (empty array). - * @public - * @see SetLineStyle() - * @since 2.1.000 (2008-01-08) - */ - public function Curve($x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3, $style='', $line_style=array(), $fill_color=array()) { - if ($this->state != 2) { - return; - } - if (!(false === strpos($style, 'F')) AND isset($fill_color)) { - $this->setFillColorArray($fill_color); - } - $op = TCPDF_STATIC::getPathPaintOperator($style); - if ($line_style) { - $this->setLineStyle($line_style); - } - $this->_outPoint($x0, $y0); - $this->_outCurve($x1, $y1, $x2, $y2, $x3, $y3); - $this->_out($op); - } - - /** - * Draws a poly-Bezier curve. - * Each Bezier curve segment is a tangent to the line between the control points at - * either end of the curve. - * @param float $x0 Abscissa of start point. - * @param float $y0 Ordinate of start point. - * @param float[] $segments An array of bezier descriptions. Format: array(x1, y1, x2, y2, x3, y3). - * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. - * @param array $line_style Line style of curve. Array like for SetLineStyle(). Default value: default line style (empty array). - * @param array $fill_color Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName). Default value: default color (empty array). - * @public - * @see SetLineStyle() - * @since 3.0008 (2008-05-12) - */ - public function Polycurve($x0, $y0, $segments, $style='', $line_style=array(), $fill_color=array()) { - if ($this->state != 2) { - return; - } - if (!(false === strpos($style, 'F')) AND isset($fill_color)) { - $this->setFillColorArray($fill_color); - } - $op = TCPDF_STATIC::getPathPaintOperator($style); - if ($op == 'f') { - $line_style = array(); - } - if ($line_style) { - $this->setLineStyle($line_style); - } - $this->_outPoint($x0, $y0); - foreach ($segments as $segment) { - list($x1, $y1, $x2, $y2, $x3, $y3) = $segment; - $this->_outCurve($x1, $y1, $x2, $y2, $x3, $y3); - } - $this->_out($op); - } - - /** - * Draws an ellipse. - * An ellipse is formed from n Bezier curves. - * @param float $x0 Abscissa of center point. - * @param float $y0 Ordinate of center point. - * @param float $rx Horizontal radius. - * @param float $ry Vertical radius (if ry = 0 then is a circle, see Circle()). Default value: 0. - * @param float $angle Angle oriented (anti-clockwise). Default value: 0. - * @param float $astart Angle start of draw line. Default value: 0. - * @param float $afinish Angle finish of draw line. Default value: 360. - * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. - * @param array $line_style Line style of ellipse. Array like for SetLineStyle(). Default value: default line style (empty array). - * @param array $fill_color Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName). Default value: default color (empty array). - * @param integer $nc Number of curves used to draw a 90 degrees portion of ellipse. - * @author Nicola Asuni - * @public - * @since 2.1.000 (2008-01-08) - */ - public function Ellipse($x0, $y0, $rx, $ry=0, $angle=0, $astart=0, $afinish=360, $style='', $line_style=array(), $fill_color=array(), $nc=2) { - if ($this->state != 2) { - return; - } - if (TCPDF_STATIC::empty_string($ry) OR ($ry == 0)) { - $ry = $rx; - } - if (!(false === strpos($style, 'F')) AND isset($fill_color)) { - $this->setFillColorArray($fill_color); - } - $op = TCPDF_STATIC::getPathPaintOperator($style); - if ($op == 'f') { - $line_style = array(); - } - if ($line_style) { - $this->setLineStyle($line_style); - } - $this->_outellipticalarc($x0, $y0, $rx, $ry, $angle, $astart, $afinish, false, $nc, true, true, false); - $this->_out($op); - } - - /** - * Append an elliptical arc to the current path. - * An ellipse is formed from n Bezier curves. - * @param float $xc Abscissa of center point. - * @param float $yc Ordinate of center point. - * @param float $rx Horizontal radius. - * @param float $ry Vertical radius (if ry = 0 then is a circle, see Circle()). Default value: 0. - * @param float $xang Angle between the X-axis and the major axis of the ellipse. Default value: 0. - * @param float $angs Angle start of draw line. Default value: 0. - * @param float $angf Angle finish of draw line. Default value: 360. - * @param boolean $pie if true do not mark the border point (used to draw pie sectors). - * @param integer $nc Number of curves used to draw a 90 degrees portion of ellipse. - * @param boolean $startpoint if true output a starting point. - * @param boolean $ccw if true draws in counter-clockwise. - * @param boolean $svg if true the angles are in svg mode (already calculated). - * @return array bounding box coordinates (x min, y min, x max, y max) - * @author Nicola Asuni - * @protected - * @since 4.9.019 (2010-04-26) - */ - protected function _outellipticalarc($xc, $yc, $rx, $ry, $xang=0, $angs=0, $angf=360, $pie=false, $nc=2, $startpoint=true, $ccw=true, $svg=false) { - if (($rx <= 0) OR ($ry < 0)) { - return; - } - $k = $this->k; - if ($nc < 2) { - $nc = 2; - } - $xmin = 2147483647; - $ymin = 2147483647; - $xmax = 0; - $ymax = 0; - if ($pie) { - // center of the arc - $this->_outPoint($xc, $yc); - } - $xang = deg2rad((float) $xang); - $angs = deg2rad((float) $angs); - $angf = deg2rad((float) $angf); - if ($svg) { - $as = $angs; - $af = $angf; - } else { - $as = atan2((sin($angs) / $ry), (cos($angs) / $rx)); - $af = atan2((sin($angf) / $ry), (cos($angf) / $rx)); - } - if ($as < 0) { - $as += (2 * M_PI); - } - if ($af < 0) { - $af += (2 * M_PI); - } - if ($ccw AND ($as > $af)) { - // reverse rotation - $as -= (2 * M_PI); - } elseif (!$ccw AND ($as < $af)) { - // reverse rotation - $af -= (2 * M_PI); - } - $total_angle = ($af - $as); - if ($nc < 2) { - $nc = 2; - } - // total arcs to draw - $nc *= (2 * abs($total_angle) / M_PI); - $nc = round($nc) + 1; - // angle of each arc - $arcang = ($total_angle / $nc); - // center point in PDF coordinates - $x0 = $xc; - $y0 = ($this->h - $yc); - // starting angle - $ang = $as; - $alpha = sin($arcang) * ((sqrt(4 + (3 * pow(tan(($arcang) / 2), 2))) - 1) / 3); - $cos_xang = cos($xang); - $sin_xang = sin($xang); - $cos_ang = cos($ang); - $sin_ang = sin($ang); - // first arc point - $px1 = $x0 + ($rx * $cos_xang * $cos_ang) - ($ry * $sin_xang * $sin_ang); - $py1 = $y0 + ($rx * $sin_xang * $cos_ang) + ($ry * $cos_xang * $sin_ang); - // first Bezier control point - $qx1 = ($alpha * ((-$rx * $cos_xang * $sin_ang) - ($ry * $sin_xang * $cos_ang))); - $qy1 = ($alpha * ((-$rx * $sin_xang * $sin_ang) + ($ry * $cos_xang * $cos_ang))); - if ($pie) { - // line from center to arc starting point - $this->_outLine($px1, $this->h - $py1); - } elseif ($startpoint) { - // arc starting point - $this->_outPoint($px1, $this->h - $py1); - } - // draw arcs - for ($i = 1; $i <= $nc; ++$i) { - // starting angle - $ang = $as + ($i * $arcang); - if ($i == $nc) { - $ang = $af; - } - $cos_ang = cos($ang); - $sin_ang = sin($ang); - // second arc point - $px2 = $x0 + ($rx * $cos_xang * $cos_ang) - ($ry * $sin_xang * $sin_ang); - $py2 = $y0 + ($rx * $sin_xang * $cos_ang) + ($ry * $cos_xang * $sin_ang); - // second Bezier control point - $qx2 = ($alpha * ((-$rx * $cos_xang * $sin_ang) - ($ry * $sin_xang * $cos_ang))); - $qy2 = ($alpha * ((-$rx * $sin_xang * $sin_ang) + ($ry * $cos_xang * $cos_ang))); - // draw arc - $cx1 = ($px1 + $qx1); - $cy1 = ($this->h - ($py1 + $qy1)); - $cx2 = ($px2 - $qx2); - $cy2 = ($this->h - ($py2 - $qy2)); - $cx3 = $px2; - $cy3 = ($this->h - $py2); - $this->_outCurve($cx1, $cy1, $cx2, $cy2, $cx3, $cy3); - // get bounding box coordinates - $xmin = min($xmin, $cx1, $cx2, $cx3); - $ymin = min($ymin, $cy1, $cy2, $cy3); - $xmax = max($xmax, $cx1, $cx2, $cx3); - $ymax = max($ymax, $cy1, $cy2, $cy3); - // move to next point - $px1 = $px2; - $py1 = $py2; - $qx1 = $qx2; - $qy1 = $qy2; - } - if ($pie) { - $this->_outLine($xc, $yc); - // get bounding box coordinates - $xmin = min($xmin, $xc); - $ymin = min($ymin, $yc); - $xmax = max($xmax, $xc); - $ymax = max($ymax, $yc); - } - return array($xmin, $ymin, $xmax, $ymax); - } - - /** - * Draws a circle. - * A circle is formed from n Bezier curves. - * @param float $x0 Abscissa of center point. - * @param float $y0 Ordinate of center point. - * @param float $r Radius. - * @param float $angstr Angle start of draw line. Default value: 0. - * @param float $angend Angle finish of draw line. Default value: 360. - * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. - * @param array $line_style Line style of circle. Array like for SetLineStyle(). Default value: default line style (empty array). - * @param array $fill_color Fill color. Format: array(red, green, blue). Default value: default color (empty array). - * @param integer $nc Number of curves used to draw a 90 degrees portion of circle. - * @public - * @since 2.1.000 (2008-01-08) - */ - public function Circle($x0, $y0, $r, $angstr=0, $angend=360, $style='', $line_style=array(), $fill_color=array(), $nc=2) { - $this->Ellipse($x0, $y0, $r, $r, 0, $angstr, $angend, $style, $line_style, $fill_color, $nc); - } - - /** - * Draws a polygonal line - * @param array $p Points 0 to ($np - 1). Array with values (x0, y0, x1, y1,..., x(np-1), y(np - 1)) - * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. - * @param array $line_style Line style of polygon. Array with keys among the following: - * <ul> - * <li>all: Line style of all lines. Array like for SetLineStyle().</li> - * <li>0 to ($np - 1): Line style of each line. Array like for SetLineStyle().</li> - * </ul> - * If a key is not present or is null, not draws the line. Default value is default line style (empty array). - * @param array $fill_color Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName). Default value: default color (empty array). - * @since 4.8.003 (2009-09-15) - * @public - */ - public function PolyLine($p, $style='', $line_style=array(), $fill_color=array()) { - $this->Polygon($p, $style, $line_style, $fill_color, false); - } - - /** - * Draws a polygon. - * @param array $p Points 0 to ($np - 1). Array with values (x0, y0, x1, y1,..., x(np-1), y(np - 1)) - * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. - * @param array $line_style Line style of polygon. Array with keys among the following: - * <ul> - * <li>all: Line style of all lines. Array like for SetLineStyle().</li> - * <li>0 to ($np - 1): Line style of each line. Array like for SetLineStyle().</li> - * </ul> - * If a key is not present or is null, not draws the line. Default value is default line style (empty array). - * @param array $fill_color Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName). Default value: default color (empty array). - * @param boolean $closed if true the polygon is closes, otherwise will remain open - * @public - * @since 2.1.000 (2008-01-08) - */ - public function Polygon($p, $style='', $line_style=array(), $fill_color=array(), $closed=true) { - if ($this->state != 2) { - return; - } - $nc = count($p); // number of coordinates - $np = $nc / 2; // number of points - if ($closed) { - // close polygon by adding the first 2 points at the end (one line) - for ($i = 0; $i < 4; ++$i) { - $p[$nc + $i] = $p[$i]; - } - // copy style for the last added line - if (isset($line_style[0])) { - $line_style[$np] = $line_style[0]; - } - $nc += 4; - } - if (!(false === strpos($style, 'F')) AND isset($fill_color)) { - $this->setFillColorArray($fill_color); - } - $op = TCPDF_STATIC::getPathPaintOperator($style); - if ($op == 'f') { - $line_style = array(); - } - $draw = true; - if ($line_style) { - if (isset($line_style['all'])) { - $this->setLineStyle($line_style['all']); - } else { - $draw = false; - if ($op == 'B') { - // draw fill - $op = 'f'; - $this->_outPoint($p[0], $p[1]); - for ($i = 2; $i < $nc; $i = $i + 2) { - $this->_outLine($p[$i], $p[$i + 1]); - } - $this->_out($op); - } - // draw outline - $this->_outPoint($p[0], $p[1]); - for ($i = 2; $i < $nc; $i = $i + 2) { - $line_num = ($i / 2) - 1; - if (isset($line_style[$line_num])) { - if ($line_style[$line_num] != 0) { - if (is_array($line_style[$line_num])) { - $this->_out('S'); - $this->setLineStyle($line_style[$line_num]); - $this->_outPoint($p[$i - 2], $p[$i - 1]); - $this->_outLine($p[$i], $p[$i + 1]); - $this->_out('S'); - $this->_outPoint($p[$i], $p[$i + 1]); - } else { - $this->_outLine($p[$i], $p[$i + 1]); - } - } - } else { - $this->_outLine($p[$i], $p[$i + 1]); - } - } - $this->_out($op); - } - } - if ($draw) { - $this->_outPoint($p[0], $p[1]); - for ($i = 2; $i < $nc; $i = $i + 2) { - $this->_outLine($p[$i], $p[$i + 1]); - } - $this->_out($op); - } - } - - /** - * Draws a regular polygon. - * @param float $x0 Abscissa of center point. - * @param float $y0 Ordinate of center point. - * @param float $r Radius of inscribed circle. - * @param integer $ns Number of sides. - * @param float $angle Angle oriented (anti-clockwise). Default value: 0. - * @param boolean $draw_circle Draw inscribed circle or not. Default value: false. - * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. - * @param array $line_style Line style of polygon sides. Array with keys among the following: - * <ul> - * <li>all: Line style of all sides. Array like for SetLineStyle().</li> - * <li>0 to ($ns - 1): Line style of each side. Array like for SetLineStyle().</li> - * </ul> - * If a key is not present or is null, not draws the side. Default value is default line style (empty array). - * @param array $fill_color Fill color. Format: array(red, green, blue). Default value: default color (empty array). - * @param string $circle_style Style of rendering of inscribed circle (if draws). Possible values are: - * <ul> - * <li>D or empty string: Draw (default).</li> - * <li>F: Fill.</li> - * <li>DF or FD: Draw and fill.</li> - * <li>CNZ: Clipping mode (using the even-odd rule to determine which regions lie inside the clipping path).</li> - * <li>CEO: Clipping mode (using the nonzero winding number rule to determine which regions lie inside the clipping path).</li> - * </ul> - * @param array $circle_outLine_style Line style of inscribed circle (if draws). Array like for SetLineStyle(). Default value: default line style (empty array). - * @param array $circle_fill_color Fill color of inscribed circle (if draws). Format: array(red, green, blue). Default value: default color (empty array). - * @public - * @since 2.1.000 (2008-01-08) - */ - public function RegularPolygon($x0, $y0, $r, $ns, $angle=0, $draw_circle=false, $style='', $line_style=array(), $fill_color=array(), $circle_style='', $circle_outLine_style=array(), $circle_fill_color=array()) { - if (3 > $ns) { - $ns = 3; - } - if ($draw_circle) { - $this->Circle($x0, $y0, $r, 0, 360, $circle_style, $circle_outLine_style, $circle_fill_color); - } - $p = array(); - for ($i = 0; $i < $ns; ++$i) { - $a = $angle + ($i * 360 / $ns); - $a_rad = deg2rad((float) $a); - $p[] = $x0 + ($r * sin($a_rad)); - $p[] = $y0 + ($r * cos($a_rad)); - } - $this->Polygon($p, $style, $line_style, $fill_color); - } - - /** - * Draws a star polygon - * @param float $x0 Abscissa of center point. - * @param float $y0 Ordinate of center point. - * @param float $r Radius of inscribed circle. - * @param integer $nv Number of vertices. - * @param integer $ng Number of gap (if ($ng % $nv = 1) then is a regular polygon). - * @param float $angle Angle oriented (anti-clockwise). Default value: 0. - * @param boolean $draw_circle Draw inscribed circle or not. Default value is false. - * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. - * @param array $line_style Line style of polygon sides. Array with keys among the following: - * <ul> - * <li>all: Line style of all sides. Array like for - * SetLineStyle().</li> - * <li>0 to (n - 1): Line style of each side. Array like for SetLineStyle().</li> - * </ul> - * If a key is not present or is null, not draws the side. Default value is default line style (empty array). - * @param array $fill_color Fill color. Format: array(red, green, blue). Default value: default color (empty array). - * @param string $circle_style Style of rendering of inscribed circle (if draws). Possible values are: - * <ul> - * <li>D or empty string: Draw (default).</li> - * <li>F: Fill.</li> - * <li>DF or FD: Draw and fill.</li> - * <li>CNZ: Clipping mode (using the even-odd rule to determine which regions lie inside the clipping path).</li> - * <li>CEO: Clipping mode (using the nonzero winding number rule to determine which regions lie inside the clipping path).</li> - * </ul> - * @param array $circle_outLine_style Line style of inscribed circle (if draws). Array like for SetLineStyle(). Default value: default line style (empty array). - * @param array $circle_fill_color Fill color of inscribed circle (if draws). Format: array(red, green, blue). Default value: default color (empty array). - * @public - * @since 2.1.000 (2008-01-08) - */ - public function StarPolygon($x0, $y0, $r, $nv, $ng, $angle=0, $draw_circle=false, $style='', $line_style=array(), $fill_color=array(), $circle_style='', $circle_outLine_style=array(), $circle_fill_color=array()) { - if ($nv < 2) { - $nv = 2; - } - if ($draw_circle) { - $this->Circle($x0, $y0, $r, 0, 360, $circle_style, $circle_outLine_style, $circle_fill_color); - } - $p2 = array(); - $visited = array(); - for ($i = 0; $i < $nv; ++$i) { - $a = $angle + ($i * 360 / $nv); - $a_rad = deg2rad((float) $a); - $p2[] = $x0 + ($r * sin($a_rad)); - $p2[] = $y0 + ($r * cos($a_rad)); - $visited[] = false; - } - $p = array(); - $i = 0; - do { - $p[] = $p2[$i * 2]; - $p[] = $p2[($i * 2) + 1]; - $visited[$i] = true; - $i += $ng; - $i %= $nv; - } while (!$visited[$i]); - $this->Polygon($p, $style, $line_style, $fill_color); - } - - /** - * Draws a rounded rectangle. - * @param float $x Abscissa of upper-left corner. - * @param float $y Ordinate of upper-left corner. - * @param float $w Width. - * @param float $h Height. - * @param float $r the radius of the circle used to round off the corners of the rectangle. - * @param string $round_corner Draws rounded corner or not. String with a 0 (not rounded i-corner) or 1 (rounded i-corner) in i-position. Positions are, in order and begin to 0: top right, bottom right, bottom left and top left. Default value: all rounded corner ("1111"). - * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. - * @param array $border_style Border style of rectangle. Array like for SetLineStyle(). Default value: default line style (empty array). - * @param array $fill_color Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName). Default value: default color (empty array). - * @public - * @since 2.1.000 (2008-01-08) - */ - public function RoundedRect($x, $y, $w, $h, $r, $round_corner='1111', $style='', $border_style=array(), $fill_color=array()) { - $this->RoundedRectXY($x, $y, $w, $h, $r, $r, $round_corner, $style, $border_style, $fill_color); - } - - /** - * Draws a rounded rectangle. - * @param float $x Abscissa of upper-left corner. - * @param float $y Ordinate of upper-left corner. - * @param float $w Width. - * @param float $h Height. - * @param float $rx the x-axis radius of the ellipse used to round off the corners of the rectangle. - * @param float $ry the y-axis radius of the ellipse used to round off the corners of the rectangle. - * @param string $round_corner Draws rounded corner or not. String with a 0 (not rounded i-corner) or 1 (rounded i-corner) in i-position. Positions are, in order and begin to 0: top right, bottom right, bottom left and top left. Default value: all rounded corner ("1111"). - * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. - * @param array $border_style Border style of rectangle. Array like for SetLineStyle(). Default value: default line style (empty array). - * @param array $fill_color Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K) or array(C,M,Y,K,SpotColorName). Default value: default color (empty array). - * @public - * @since 4.9.019 (2010-04-22) - */ - public function RoundedRectXY($x, $y, $w, $h, $rx, $ry, $round_corner='1111', $style='', $border_style=array(), $fill_color=array()) { - if ($this->state != 2) { - return; - } - if (($round_corner == '0000') OR (($rx == $ry) AND ($rx == 0))) { - // Not rounded - $this->Rect($x, $y, $w, $h, $style, $border_style, $fill_color); - return; - } - // Rounded - if (!(false === strpos($style, 'F')) AND isset($fill_color)) { - $this->setFillColorArray($fill_color); - } - $op = TCPDF_STATIC::getPathPaintOperator($style); - if ($op == 'f') { - $border_style = array(); - } - if ($border_style) { - $this->setLineStyle($border_style); - } - $MyArc = 4 / 3 * (sqrt(2) - 1); - $this->_outPoint($x + $rx, $y); - $xc = $x + $w - $rx; - $yc = $y + $ry; - $this->_outLine($xc, $y); - if ($round_corner[0]) { - $this->_outCurve($xc + ($rx * $MyArc), $yc - $ry, $xc + $rx, $yc - ($ry * $MyArc), $xc + $rx, $yc); - } else { - $this->_outLine($x + $w, $y); - } - $xc = $x + $w - $rx; - $yc = $y + $h - $ry; - $this->_outLine($x + $w, $yc); - if ($round_corner[1]) { - $this->_outCurve($xc + $rx, $yc + ($ry * $MyArc), $xc + ($rx * $MyArc), $yc + $ry, $xc, $yc + $ry); - } else { - $this->_outLine($x + $w, $y + $h); - } - $xc = $x + $rx; - $yc = $y + $h - $ry; - $this->_outLine($xc, $y + $h); - if ($round_corner[2]) { - $this->_outCurve($xc - ($rx * $MyArc), $yc + $ry, $xc - $rx, $yc + ($ry * $MyArc), $xc - $rx, $yc); - } else { - $this->_outLine($x, $y + $h); - } - $xc = $x + $rx; - $yc = $y + $ry; - $this->_outLine($x, $yc); - if ($round_corner[3]) { - $this->_outCurve($xc - $rx, $yc - ($ry * $MyArc), $xc - ($rx * $MyArc), $yc - $ry, $xc, $yc - $ry); - } else { - $this->_outLine($x, $y); - $this->_outLine($x + $rx, $y); - } - $this->_out($op); - } - - /** - * Draws a grahic arrow. - * @param float $x0 Abscissa of first point. - * @param float $y0 Ordinate of first point. - * @param float $x1 Abscissa of second point. - * @param float $y1 Ordinate of second point. - * @param int $head_style (0 = draw only arrowhead arms, 1 = draw closed arrowhead, but no fill, 2 = closed and filled arrowhead, 3 = filled arrowhead) - * @param float $arm_size length of arrowhead arms - * @param int $arm_angle angle between an arm and the shaft - * @author Piotr Galecki, Nicola Asuni, Andy Meier - * @since 4.6.018 (2009-07-10) - */ - public function Arrow($x0, $y0, $x1, $y1, $head_style=0, $arm_size=5, $arm_angle=15) { - // getting arrow direction angle - // 0 deg angle is when both arms go along X axis. angle grows clockwise. - $dir_angle = atan2(($y0 - $y1), ($x0 - $x1)); - if ($dir_angle < 0) { - $dir_angle += (2 * M_PI); - } - $arm_angle = deg2rad($arm_angle); - $sx1 = $x1; - $sy1 = $y1; - if ($head_style > 0) { - // calculate the stopping point for the arrow shaft - $sx1 = $x1 + (($arm_size - $this->LineWidth) * cos($dir_angle)); - $sy1 = $y1 + (($arm_size - $this->LineWidth) * sin($dir_angle)); - } - // main arrow line / shaft - $this->Line($x0, $y0, $sx1, $sy1); - // left arrowhead arm tip - $x2L = $x1 + ($arm_size * cos($dir_angle + $arm_angle)); - $y2L = $y1 + ($arm_size * sin($dir_angle + $arm_angle)); - // right arrowhead arm tip - $x2R = $x1 + ($arm_size * cos($dir_angle - $arm_angle)); - $y2R = $y1 + ($arm_size * sin($dir_angle - $arm_angle)); - $mode = 'D'; - $style = array(); - switch ($head_style) { - case 0: { - // draw only arrowhead arms - $mode = 'D'; - $style = array(1, 1, 0); - break; - } - case 1: { - // draw closed arrowhead, but no fill - $mode = 'D'; - break; - } - case 2: { - // closed and filled arrowhead - $mode = 'DF'; - break; - } - case 3: { - // filled arrowhead - $mode = 'F'; - break; - } - } - $this->Polygon(array($x2L, $y2L, $x1, $y1, $x2R, $y2R), $mode, $style, array()); - } - - // END GRAPHIC FUNCTIONS SECTION ----------------------- - - /** - * Add a Named Destination. - * NOTE: destination names are unique, so only last entry will be saved. - * @param string $name Destination name. - * @param float $y Y position in user units of the destiantion on the selected page (default = -1 = current position; 0 = page start;). - * @param int|string $page Target page number (leave empty for current page). If you prefix a page number with the * character, then this page will not be changed when adding/deleting/moving pages. - * @param float $x X position in user units of the destiantion on the selected page (default = -1 = current position;). - * @return string|false Stripped named destination identifier or false in case of error. - * @public - * @author Christian Deligant, Nicola Asuni - * @since 5.9.097 (2011-06-23) - */ - public function setDestination($name, $y=-1, $page='', $x=-1) { - // remove unsupported characters - $name = TCPDF_STATIC::encodeNameObject($name); - if (TCPDF_STATIC::empty_string($name)) { - return false; - } - if ($y == -1) { - $y = $this->GetY(); - } elseif ($y < 0) { - $y = 0; - } elseif ($y > $this->h) { - $y = $this->h; - } - if ($x == -1) { - $x = $this->GetX(); - } elseif ($x < 0) { - $x = 0; - } elseif ($x > $this->w) { - $x = $this->w; - } - $fixed = false; - if (!empty($page) AND (substr($page, 0, 1) == '*')) { - $page = intval(substr($page, 1)); - // this page number will not be changed when moving/add/deleting pages - $fixed = true; - } - if (empty($page)) { - $page = $this->PageNo(); - if (empty($page)) { - return; - } - } - $this->dests[$name] = array('x' => $x, 'y' => $y, 'p' => $page, 'f' => $fixed); - return $name; - } - - /** - * Return the Named Destination array. - * @return array Named Destination array. - * @public - * @author Nicola Asuni - * @since 5.9.097 (2011-06-23) - */ - public function getDestination() { - return $this->dests; - } - - /** - * Insert Named Destinations. - * @protected - * @author Johannes G\FCntert, Nicola Asuni - * @since 5.9.098 (2011-06-23) - */ - protected function _putdests() { - if (empty($this->dests)) { - return; - } - $this->n_dests = $this->_newobj(); - $out = ' <<'; - foreach($this->dests as $name => $o) { - $out .= ' /'.$name.' '.sprintf('[%u 0 R /XYZ %F %F null]', $this->page_obj_id[($o['p'])], ($o['x'] * $this->k), ($this->pagedim[$o['p']]['h'] - ($o['y'] * $this->k))); - } - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - } - - /** - * Adds a bookmark - alias for Bookmark(). - * @param string $txt Bookmark description. - * @param int $level Bookmark level (minimum value is 0). - * @param float $y Y position in user units of the bookmark on the selected page (default = -1 = current position; 0 = page start;). - * @param int|string $page Target page number (leave empty for current page). If you prefix a page number with the * character, then this page will not be changed when adding/deleting/moving pages. - * @param string $style Font style: B = Bold, I = Italic, BI = Bold + Italic. - * @param array $color RGB color array (values from 0 to 255). - * @param float $x X position in user units of the bookmark on the selected page (default = -1 = current position;). - * @param mixed $link URL, or numerical link ID, or named destination (# character followed by the destination name), or embedded file (* character followed by the file name). - * @public - */ - public function setBookmark($txt, $level=0, $y=-1, $page='', $style='', $color=array(0,0,0), $x=-1, $link='') { - $this->Bookmark($txt, $level, $y, $page, $style, $color, $x, $link); - } - - /** - * Adds a bookmark. - * @param string $txt Bookmark description. - * @param int $level Bookmark level (minimum value is 0). - * @param float $y Y position in user units of the bookmark on the selected page (default = -1 = current position; 0 = page start;). - * @param int|string $page Target page number (leave empty for current page). If you prefix a page number with the * character, then this page will not be changed when adding/deleting/moving pages. - * @param string $style Font style: B = Bold, I = Italic, BI = Bold + Italic. - * @param array $color RGB color array (values from 0 to 255). - * @param float $x X position in user units of the bookmark on the selected page (default = -1 = current position;). - * @param mixed $link URL, or numerical link ID, or named destination (# character followed by the destination name), or embedded file (* character followed by the file name). - * @public - * @since 2.1.002 (2008-02-12) - */ - public function Bookmark($txt, $level=0, $y=-1, $page='', $style='', $color=array(0,0,0), $x=-1, $link='') { - if ($level < 0) { - $level = 0; - } - if (isset($this->outlines[0])) { - $lastoutline = end($this->outlines); - $maxlevel = $lastoutline['l'] + 1; - } else { - $maxlevel = 0; - } - if ($level > $maxlevel) { - $level = $maxlevel; - } - if ($y == -1) { - $y = $this->GetY(); - } elseif ($y < 0) { - $y = 0; - } elseif ($y > $this->h) { - $y = $this->h; - } - if ($x == -1) { - $x = $this->GetX(); - } elseif ($x < 0) { - $x = 0; - } elseif ($x > $this->w) { - $x = $this->w; - } - $fixed = false; - $pageAsString = (string) $page; - if ($pageAsString && $pageAsString[0] == '*') { - $page = intval(substr($page, 1)); - // this page number will not be changed when moving/add/deleting pages - $fixed = true; - } - if (empty($page)) { - $page = $this->PageNo(); - if (empty($page)) { - return; - } - } - $this->outlines[] = array('t' => $txt, 'l' => $level, 'x' => $x, 'y' => $y, 'p' => $page, 'f' => $fixed, 's' => strtoupper($style), 'c' => $color, 'u' => $link); - } - - /** - * Sort bookmarks for page and key. - * @protected - * @since 5.9.119 (2011-09-19) - */ - protected function sortBookmarks() { - // get sorting columns - $outline_p = array(); - $outline_y = array(); - foreach ($this->outlines as $key => $row) { - $outline_p[$key] = $row['p']; - $outline_k[$key] = $key; - } - // sort outlines by page and original position - array_multisort($outline_p, SORT_NUMERIC, SORT_ASC, $outline_k, SORT_NUMERIC, SORT_ASC, $this->outlines); - } - - /** - * Create a bookmark PDF string. - * @protected - * @author Olivier Plathey, Nicola Asuni - * @since 2.1.002 (2008-02-12) - */ - protected function _putbookmarks() { - $nb = count($this->outlines); - if ($nb == 0) { - return; - } - // sort bookmarks - $this->sortBookmarks(); - $lru = array(); - $level = 0; - foreach ($this->outlines as $i => $o) { - if ($o['l'] > 0) { - $parent = $lru[($o['l'] - 1)]; - //Set parent and last pointers - $this->outlines[$i]['parent'] = $parent; - $this->outlines[$parent]['last'] = $i; - if ($o['l'] > $level) { - //Level increasing: set first pointer - $this->outlines[$parent]['first'] = $i; - } - } else { - $this->outlines[$i]['parent'] = $nb; - } - if (($o['l'] <= $level) AND ($i > 0)) { - //Set prev and next pointers - $prev = $lru[$o['l']]; - $this->outlines[$prev]['next'] = $i; - $this->outlines[$i]['prev'] = $prev; - } - $lru[$o['l']] = $i; - $level = $o['l']; - } - //Outline items - $n = $this->n + 1; - $nltags = '/<br[\s]?\/>|<\/(blockquote|dd|dl|div|dt|h1|h2|h3|h4|h5|h6|hr|li|ol|p|pre|ul|tcpdf|table|tr|td)>/si'; - foreach ($this->outlines as $i => $o) { - $oid = $this->_newobj(); - // covert HTML title to string - $title = preg_replace($nltags, "\n", $o['t']); - $title = preg_replace("/[\r]+/si", '', $title); - $title = preg_replace("/[\n]+/si", "\n", $title); - $title = strip_tags($title); - $title = $this->stringTrim($title); - $out = '<</Title '.$this->_textstring($title, $oid); - $out .= ' /Parent '.($n + $o['parent']).' 0 R'; - if (isset($o['prev'])) { - $out .= ' /Prev '.($n + $o['prev']).' 0 R'; - } - if (isset($o['next'])) { - $out .= ' /Next '.($n + $o['next']).' 0 R'; - } - if (isset($o['first'])) { - $out .= ' /First '.($n + $o['first']).' 0 R'; - } - if (isset($o['last'])) { - $out .= ' /Last '.($n + $o['last']).' 0 R'; - } - if (isset($o['u']) AND !empty($o['u'])) { - // link - if (is_string($o['u'])) { - if ($o['u'][0] == '#') { - // internal destination - $out .= ' /Dest /'.TCPDF_STATIC::encodeNameObject(substr($o['u'], 1)); - } elseif ($o['u'][0] == '%') { - // embedded PDF file - $filename = basename(substr($o['u'], 1)); - $out .= ' /A <</S /GoToE /D [0 /Fit] /NewWindow true /T << /R /C /P '.($o['p'] - 1).' /A '.$this->embeddedfiles[$filename]['a'].' >> >>'; - } elseif ($o['u'][0] == '*') { - // embedded generic file - $filename = basename(substr($o['u'], 1)); - $jsa = 'var D=event.target.doc;var MyData=D.dataObjects;for (var i in MyData) if (MyData[i].path=="'.$filename.'") D.exportDataObject( { cName : MyData[i].name, nLaunch : 2});'; - $out .= ' /A <</S /JavaScript /JS '.$this->_textstring($jsa, $oid).'>>'; - } else { - // external URI link - $out .= ' /A <</S /URI /URI '.$this->_datastring($this->unhtmlentities($o['u']), $oid).'>>'; - } - } elseif (isset($this->links[$o['u']])) { - // internal link ID - $l = $this->links[$o['u']]; - if (isset($this->page_obj_id[($l['p'])])) { - $out .= sprintf(' /Dest [%u 0 R /XYZ 0 %F null]', $this->page_obj_id[($l['p'])], ($this->pagedim[$l['p']]['h'] - ($l['y'] * $this->k))); - } - } - } elseif (isset($this->page_obj_id[($o['p'])])) { - // link to a page - $out .= ' '.sprintf('/Dest [%u 0 R /XYZ %F %F null]', $this->page_obj_id[($o['p'])], ($o['x'] * $this->k), ($this->pagedim[$o['p']]['h'] - ($o['y'] * $this->k))); - } - // set font style - $style = 0; - if (!empty($o['s'])) { - // bold - if (strpos($o['s'], 'B') !== false) { - $style |= 2; - } - // oblique - if (strpos($o['s'], 'I') !== false) { - $style |= 1; - } - } - $out .= sprintf(' /F %d', $style); - // set bookmark color - if (isset($o['c']) AND is_array($o['c']) AND (count($o['c']) == 3)) { - $color = array_values($o['c']); - $out .= sprintf(' /C [%F %F %F]', ($color[0] / 255), ($color[1] / 255), ($color[2] / 255)); - } else { - // black - $out .= ' /C [0.0 0.0 0.0]'; - } - $out .= ' /Count 0'; // normally closed item - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - } - //Outline root - $this->OutlineRoot = $this->_newobj(); - $this->_out('<< /Type /Outlines /First '.$n.' 0 R /Last '.($n + $lru[0]).' 0 R >>'."\n".'endobj'); - } - - // --- JAVASCRIPT ------------------------------------------------------ - - /** - * Adds a javascript - * @param string $script Javascript code - * @public - * @author Johannes G\FCntert, Nicola Asuni - * @since 2.1.002 (2008-02-12) - */ - public function IncludeJS($script) { - $this->javascript .= $script; - } - - /** - * Adds a javascript object and return object ID - * @param string $script Javascript code - * @param boolean $onload if true executes this object when opening the document - * @return int internal object ID - * @public - * @author Nicola Asuni - * @since 4.8.000 (2009-09-07) - */ - public function addJavascriptObject($script, $onload=false) { - if ($this->pdfa_mode) { - // javascript is not allowed in PDF/A mode - return false; - } - ++$this->n; - $this->js_objects[$this->n] = array('n' => $this->n, 'js' => $script, 'onload' => $onload); - return $this->n; - } - - /** - * Create a javascript PDF string. - * @protected - * @author Johannes G\FCntert, Nicola Asuni - * @since 2.1.002 (2008-02-12) - */ - protected function _putjavascript() { - if ($this->pdfa_mode OR (empty($this->javascript) AND empty($this->js_objects))) { - return; - } - if (strpos($this->javascript, 'this.addField') > 0) { - if (!$this->ur['enabled']) { - //$this->setUserRights(); - } - // the following two lines are used to avoid form fields duplication after saving - // The addField method only works when releasing user rights (UR3) - $jsa = sprintf("ftcpdfdocsaved=this.addField('%s','%s',%d,[%F,%F,%F,%F]);", 'tcpdfdocsaved', 'text', 0, 0, 1, 0, 1); - $jsb = "getField('tcpdfdocsaved').value='saved';"; - $this->javascript = $jsa."\n".$this->javascript."\n".$jsb; - } - // name tree for javascript - $this->n_js = '<< /Names ['; - if (!empty($this->javascript)) { - $this->n_js .= ' (EmbeddedJS) '.($this->n + 1).' 0 R'; - } - if (!empty($this->js_objects)) { - foreach ($this->js_objects as $key => $val) { - if ($val['onload']) { - $this->n_js .= ' (JS'.$key.') '.$key.' 0 R'; - } - } - } - $this->n_js .= ' ] >>'; - // default Javascript object - if (!empty($this->javascript)) { - $obj_id = $this->_newobj(); - $out = '<< /S /JavaScript'; - $out .= ' /JS '.$this->_textstring($this->javascript, $obj_id); - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - } - // additional Javascript objects - if (!empty($this->js_objects)) { - foreach ($this->js_objects as $key => $val) { - $out = $this->_getobj($key)."\n".' << /S /JavaScript /JS '.$this->_textstring($val['js'], $key).' >>'."\n".'endobj'; - $this->_out($out); - } - } - } - - /** - * Adds a javascript form field. - * @param string $type field type - * @param string $name field name - * @param int $x horizontal position - * @param int $y vertical position - * @param int $w width - * @param int $h height - * @param array $prop javascript field properties. Possible values are described on official Javascript for Acrobat API reference. - * @protected - * @author Denis Van Nuffelen, Nicola Asuni - * @since 2.1.002 (2008-02-12) - */ - protected function _addfield($type, $name, $x, $y, $w, $h, $prop) { - if ($this->rtl) { - $x = $x - $w; - } - // the followind avoid fields duplication after saving the document - $this->javascript .= "if (getField('tcpdfdocsaved').value != 'saved') {"; - $k = $this->k; - $this->javascript .= sprintf("f".$name."=this.addField('%s','%s',%u,[%F,%F,%F,%F]);", $name, $type, $this->PageNo()-1, $x*$k, ($this->h-$y)*$k+1, ($x+$w)*$k, ($this->h-$y-$h)*$k+1)."\n"; - $this->javascript .= 'f'.$name.'.textSize='.$this->FontSizePt.";\n"; - foreach($prop as $key => $val) { - if (strcmp(substr($key, -5), 'Color') == 0) { - $val = TCPDF_COLORS::_JScolor($val); - } else { - $val = "'".$val."'"; - } - $this->javascript .= 'f'.$name.'.'.$key.'='.$val.";\n"; - } - if ($this->rtl) { - $this->x -= $w; - } else { - $this->x += $w; - } - $this->javascript .= '}'; - } - - // --- FORM FIELDS ----------------------------------------------------- - - - - /** - * Set default properties for form fields. - * @param array $prop javascript field properties. Possible values are described on official Javascript for Acrobat API reference. - * @public - * @author Nicola Asuni - * @since 4.8.000 (2009-09-06) - */ - public function setFormDefaultProp($prop=array()) { - $this->default_form_prop = $prop; - } - - /** - * Return the default properties for form fields. - * @return array $prop javascript field properties. Possible values are described on official Javascript for Acrobat API reference. - * @public - * @author Nicola Asuni - * @since 4.8.000 (2009-09-06) - */ - public function getFormDefaultProp() { - return $this->default_form_prop; - } - - /** - * Creates a text field - * @param string $name field name - * @param float $w Width of the rectangle - * @param float $h Height of the rectangle - * @param array $prop javascript field properties. Possible values are described on official Javascript for Acrobat API reference. - * @param array $opt annotation parameters. Possible values are described on official PDF32000_2008 reference. - * @param float|null $x Abscissa of the upper-left corner of the rectangle - * @param float|null $y Ordinate of the upper-left corner of the rectangle - * @param boolean $js if true put the field using JavaScript (requires Acrobat Writer to be rendered). - * @public - * @author Nicola Asuni - * @since 4.8.000 (2009-09-07) - */ - public function TextField($name, $w, $h, $prop=array(), $opt=array(), $x=null, $y=null, $js=false) { - if (TCPDF_STATIC::empty_string($x)) { - $x = $this->x; - } - if (TCPDF_STATIC::empty_string($y)) { - $y = $this->y; - } - // check page for no-write regions and adapt page margins if necessary - list($x, $y) = $this->checkPageRegions($h, $x, $y); - if ($js) { - $this->_addfield('text', $name, $x, $y, $w, $h, $prop); - return; - } - // get default style - $prop = array_merge($this->getFormDefaultProp(), $prop); - // get annotation data - $popt = TCPDF_STATIC::getAnnotOptFromJSProp($prop, $this->spot_colors, $this->rtl); - // set default appearance stream - $this->annotation_fonts[$this->CurrentFont['fontkey']] = $this->CurrentFont['i']; - $fontstyle = sprintf('/F%d %F Tf %s', $this->CurrentFont['i'], $this->FontSizePt, $this->TextColor); - $popt['da'] = $fontstyle; - // build appearance stream - $popt['ap'] = array(); - $popt['ap']['n'] = '/Tx BMC q '.$fontstyle.' '; - $text = ''; - if (isset($prop['value']) AND !empty($prop['value'])) { - $text = $prop['value']; - } elseif (isset($opt['v']) AND !empty($opt['v'])) { - $text = $opt['v']; - } - $tmpid = $this->startTemplate($w, $h, false); - $align = ''; - if (isset($popt['q'])) { - switch ($popt['q']) { - case 0: { - $align = 'L'; - break; - } - case 1: { - $align = 'C'; - break; - } - case 2: { - $align = 'R'; - break; - } - default: { - $align = ''; - break; - } - } - } - $this->MultiCell($w, $h, $text, 0, $align, false, 0, 0, 0, true, 0, false, true, 0, 'T', false); - $this->endTemplate(); - --$this->n; - $popt['ap']['n'] .= $this->xobjects[$tmpid]['outdata']; - unset($this->xobjects[$tmpid]); - $popt['ap']['n'] .= 'Q EMC'; - // merge options - $opt = array_merge($popt, $opt); - // remove some conflicting options - unset($opt['bs']); - // set remaining annotation data - $opt['Subtype'] = 'Widget'; - $opt['ft'] = 'Tx'; - $opt['t'] = $name; - // Additional annotation's parameters (check _putannotsobj() method): - //$opt['f'] - //$opt['as'] - //$opt['bs'] - //$opt['be'] - //$opt['c'] - //$opt['border'] - //$opt['h'] - //$opt['mk']; - //$opt['mk']['r'] - //$opt['mk']['bc']; - //$opt['mk']['bg']; - unset($opt['mk']['ca']); - unset($opt['mk']['rc']); - unset($opt['mk']['ac']); - unset($opt['mk']['i']); - unset($opt['mk']['ri']); - unset($opt['mk']['ix']); - unset($opt['mk']['if']); - //$opt['mk']['if']['sw']; - //$opt['mk']['if']['s']; - //$opt['mk']['if']['a']; - //$opt['mk']['if']['fb']; - unset($opt['mk']['tp']); - //$opt['tu'] - //$opt['tm'] - //$opt['ff'] - //$opt['v'] - //$opt['dv'] - //$opt['a'] - //$opt['aa'] - //$opt['q'] - $this->Annotation($x, $y, $w, $h, $name, $opt, 0); - if ($this->rtl) { - $this->x -= $w; - } else { - $this->x += $w; - } - } - - /** - * Creates a RadioButton field. - * @param string $name Field name. - * @param int $w Width of the radio button. - * @param array $prop Javascript field properties. Possible values are described on official Javascript for Acrobat API reference. - * @param array $opt Annotation parameters. Possible values are described on official PDF32000_2008 reference. - * @param string $onvalue Value to be returned if selected. - * @param boolean $checked Define the initial state. - * @param float|null $x Abscissa of the upper-left corner of the rectangle - * @param float|null $y Ordinate of the upper-left corner of the rectangle - * @param boolean $js If true put the field using JavaScript (requires Acrobat Writer to be rendered). - * @public - * @author Nicola Asuni - * @since 4.8.000 (2009-09-07) - */ - public function RadioButton($name, $w, $prop=array(), $opt=array(), $onvalue='On', $checked=false, $x=null, $y=null, $js=false) { - if (TCPDF_STATIC::empty_string($x)) { - $x = $this->x; - } - if (TCPDF_STATIC::empty_string($y)) { - $y = $this->y; - } - // check page for no-write regions and adapt page margins if necessary - list($x, $y) = $this->checkPageRegions($w, $x, $y); - if ($js) { - $this->_addfield('radiobutton', $name, $x, $y, $w, $w, $prop); - return; - } - if (TCPDF_STATIC::empty_string($onvalue)) { - $onvalue = 'On'; - } - if ($checked) { - $defval = $onvalue; - } else { - $defval = 'Off'; - } - // set font - $font = 'zapfdingbats'; - if ($this->pdfa_mode) { - // all fonts must be embedded - $font = 'pdfa'.$font; - } - $this->AddFont($font); - $tmpfont = $this->getFontBuffer($font); - // set data for parent group - if (!isset($this->radiobutton_groups[$this->page])) { - $this->radiobutton_groups[$this->page] = array(); - } - if (!isset($this->radiobutton_groups[$this->page][$name])) { - $this->radiobutton_groups[$this->page][$name] = array(); - ++$this->n; - $this->radiobutton_groups[$this->page][$name]['n'] = $this->n; - $this->radio_groups[] = $this->n; - } - $kid = ($this->n + 1); - // save object ID to be added on Kids entry on parent object - $this->radiobutton_groups[$this->page][$name][] = array('kid' => $kid, 'def' => $defval); - // get default style - $prop = array_merge($this->getFormDefaultProp(), $prop); - $prop['NoToggleToOff'] = 'true'; - $prop['Radio'] = 'true'; - $prop['borderStyle'] = 'inset'; - // get annotation data - $popt = TCPDF_STATIC::getAnnotOptFromJSProp($prop, $this->spot_colors, $this->rtl); - // set additional default options - $this->annotation_fonts[$tmpfont['fontkey']] = $tmpfont['i']; - $fontstyle = sprintf('/F%d %F Tf %s', $tmpfont['i'], $this->FontSizePt, $this->TextColor); - $popt['da'] = $fontstyle; - // build appearance stream - $popt['ap'] = array(); - $popt['ap']['n'] = array(); - $fx = ((($w - $this->getAbsFontMeasure($tmpfont['cw'][108])) / 2) * $this->k); - $fy = (($w - ((($tmpfont['desc']['Ascent'] - $tmpfont['desc']['Descent']) * $this->FontSizePt / 1000) / $this->k)) * $this->k); - $popt['ap']['n'][$onvalue] = sprintf('q %s BT /F%d %F Tf %F %F Td ('.chr(108).') Tj ET Q', $this->TextColor, $tmpfont['i'], $this->FontSizePt, $fx, $fy); - $popt['ap']['n']['Off'] = sprintf('q %s BT /F%d %F Tf %F %F Td ('.chr(109).') Tj ET Q', $this->TextColor, $tmpfont['i'], $this->FontSizePt, $fx, $fy); - if (!isset($popt['mk'])) { - $popt['mk'] = array(); - } - $popt['mk']['ca'] = '(l)'; - // merge options - $opt = array_merge($popt, $opt); - // set remaining annotation data - $opt['Subtype'] = 'Widget'; - $opt['ft'] = 'Btn'; - if ($checked) { - $opt['v'] = array('/'.$onvalue); - $opt['as'] = $onvalue; - } else { - $opt['as'] = 'Off'; - } - // store readonly flag - if (!isset($this->radiobutton_groups[$this->page][$name]['#readonly#'])) { - $this->radiobutton_groups[$this->page][$name]['#readonly#'] = false; - } - $this->radiobutton_groups[$this->page][$name]['#readonly#'] |= ($opt['f'] & 64); - $this->Annotation($x, $y, $w, $w, $name, $opt, 0); - if ($this->rtl) { - $this->x -= $w; - } else { - $this->x += $w; - } - } - - /** - * Creates a List-box field - * @param string $name field name - * @param int $w width - * @param int $h height - * @param array $values array containing the list of values. - * @param array $prop javascript field properties. Possible values are described on official Javascript for Acrobat API reference. - * @param array $opt annotation parameters. Possible values are described on official PDF32000_2008 reference. - * @param float|null $x Abscissa of the upper-left corner of the rectangle - * @param float|null $y Ordinate of the upper-left corner of the rectangle - * @param boolean $js if true put the field using JavaScript (requires Acrobat Writer to be rendered). - * @public - * @author Nicola Asuni - * @since 4.8.000 (2009-09-07) - */ - public function ListBox($name, $w, $h, $values, $prop=array(), $opt=array(), $x=null, $y=null, $js=false) { - if (TCPDF_STATIC::empty_string($x)) { - $x = $this->x; - } - if (TCPDF_STATIC::empty_string($y)) { - $y = $this->y; - } - // check page for no-write regions and adapt page margins if necessary - list($x, $y) = $this->checkPageRegions($h, $x, $y); - if ($js) { - $this->_addfield('listbox', $name, $x, $y, $w, $h, $prop); - $s = ''; - foreach ($values as $value) { - if (is_array($value)) { - $s .= ',[\''.addslashes($value[1]).'\',\''.addslashes($value[0]).'\']'; - } else { - $s .= ',[\''.addslashes($value).'\',\''.addslashes($value).'\']'; - } - } - $this->javascript .= 'f'.$name.'.setItems('.substr($s, 1).');'."\n"; - return; - } - // get default style - $prop = array_merge($this->getFormDefaultProp(), $prop); - // get annotation data - $popt = TCPDF_STATIC::getAnnotOptFromJSProp($prop, $this->spot_colors, $this->rtl); - // set additional default values - $this->annotation_fonts[$this->CurrentFont['fontkey']] = $this->CurrentFont['i']; - $fontstyle = sprintf('/F%d %F Tf %s', $this->CurrentFont['i'], $this->FontSizePt, $this->TextColor); - $popt['da'] = $fontstyle; - // build appearance stream - $popt['ap'] = array(); - $popt['ap']['n'] = '/Tx BMC q '.$fontstyle.' '; - $text = ''; - foreach($values as $item) { - if (is_array($item)) { - $text .= $item[1]."\n"; - } else { - $text .= $item."\n"; - } - } - $tmpid = $this->startTemplate($w, $h, false); - $this->MultiCell($w, $h, $text, 0, '', false, 0, 0, 0, true, 0, false, true, 0, 'T', false); - $this->endTemplate(); - --$this->n; - $popt['ap']['n'] .= $this->xobjects[$tmpid]['outdata']; - unset($this->xobjects[$tmpid]); - $popt['ap']['n'] .= 'Q EMC'; - // merge options - $opt = array_merge($popt, $opt); - // set remaining annotation data - $opt['Subtype'] = 'Widget'; - $opt['ft'] = 'Ch'; - $opt['t'] = $name; - $opt['opt'] = $values; - unset($opt['mk']['ca']); - unset($opt['mk']['rc']); - unset($opt['mk']['ac']); - unset($opt['mk']['i']); - unset($opt['mk']['ri']); - unset($opt['mk']['ix']); - unset($opt['mk']['if']); - unset($opt['mk']['tp']); - $this->Annotation($x, $y, $w, $h, $name, $opt, 0); - if ($this->rtl) { - $this->x -= $w; - } else { - $this->x += $w; - } - } - - /** - * Creates a Combo-box field - * @param string $name field name - * @param int $w width - * @param int $h height - * @param array $values array containing the list of values. - * @param array $prop javascript field properties. Possible values are described on official Javascript for Acrobat API reference. - * @param array $opt annotation parameters. Possible values are described on official PDF32000_2008 reference. - * @param float|null $x Abscissa of the upper-left corner of the rectangle - * @param float|null $y Ordinate of the upper-left corner of the rectangle - * @param boolean $js if true put the field using JavaScript (requires Acrobat Writer to be rendered). - * @public - * @author Nicola Asuni - * @since 4.8.000 (2009-09-07) - */ - public function ComboBox($name, $w, $h, $values, $prop=array(), $opt=array(), $x=null, $y=null, $js=false) { - if (TCPDF_STATIC::empty_string($x)) { - $x = $this->x; - } - if (TCPDF_STATIC::empty_string($y)) { - $y = $this->y; - } - // check page for no-write regions and adapt page margins if necessary - list($x, $y) = $this->checkPageRegions($h, $x, $y); - if ($js) { - $this->_addfield('combobox', $name, $x, $y, $w, $h, $prop); - $s = ''; - foreach ($values as $value) { - if (is_array($value)) { - $s .= ',[\''.addslashes($value[1]).'\',\''.addslashes($value[0]).'\']'; - } else { - $s .= ',[\''.addslashes($value).'\',\''.addslashes($value).'\']'; - } - } - $this->javascript .= 'f'.$name.'.setItems('.substr($s, 1).');'."\n"; - return; - } - // get default style - $prop = array_merge($this->getFormDefaultProp(), $prop); - $prop['Combo'] = true; - // get annotation data - $popt = TCPDF_STATIC::getAnnotOptFromJSProp($prop, $this->spot_colors, $this->rtl); - // set additional default options - $this->annotation_fonts[$this->CurrentFont['fontkey']] = $this->CurrentFont['i']; - $fontstyle = sprintf('/F%d %F Tf %s', $this->CurrentFont['i'], $this->FontSizePt, $this->TextColor); - $popt['da'] = $fontstyle; - // build appearance stream - $popt['ap'] = array(); - $popt['ap']['n'] = '/Tx BMC q '.$fontstyle.' '; - $text = ''; - foreach($values as $item) { - if (is_array($item)) { - $text .= $item[1]."\n"; - } else { - $text .= $item."\n"; - } - } - $tmpid = $this->startTemplate($w, $h, false); - $this->MultiCell($w, $h, $text, 0, '', false, 0, 0, 0, true, 0, false, true, 0, 'T', false); - $this->endTemplate(); - --$this->n; - $popt['ap']['n'] .= $this->xobjects[$tmpid]['outdata']; - unset($this->xobjects[$tmpid]); - $popt['ap']['n'] .= 'Q EMC'; - // merge options - $opt = array_merge($popt, $opt); - // set remaining annotation data - $opt['Subtype'] = 'Widget'; - $opt['ft'] = 'Ch'; - $opt['t'] = $name; - $opt['opt'] = $values; - unset($opt['mk']['ca']); - unset($opt['mk']['rc']); - unset($opt['mk']['ac']); - unset($opt['mk']['i']); - unset($opt['mk']['ri']); - unset($opt['mk']['ix']); - unset($opt['mk']['if']); - unset($opt['mk']['tp']); - $this->Annotation($x, $y, $w, $h, $name, $opt, 0); - if ($this->rtl) { - $this->x -= $w; - } else { - $this->x += $w; - } - } - - /** - * Creates a CheckBox field - * @param string $name field name - * @param int $w width - * @param boolean $checked define the initial state. - * @param array $prop javascript field properties. Possible values are described on official Javascript for Acrobat API reference. - * @param array $opt annotation parameters. Possible values are described on official PDF32000_2008 reference. - * @param string $onvalue value to be returned if selected. - * @param float|null $x Abscissa of the upper-left corner of the rectangle - * @param float|null $y Ordinate of the upper-left corner of the rectangle - * @param boolean $js if true put the field using JavaScript (requires Acrobat Writer to be rendered). - * @public - * @author Nicola Asuni - * @since 4.8.000 (2009-09-07) - */ - public function CheckBox($name, $w, $checked=false, $prop=array(), $opt=array(), $onvalue='Yes', $x=null, $y=null, $js=false) { - if (TCPDF_STATIC::empty_string($x)) { - $x = $this->x; - } - if (TCPDF_STATIC::empty_string($y)) { - $y = $this->y; - } - // check page for no-write regions and adapt page margins if necessary - list($x, $y) = $this->checkPageRegions($w, $x, $y); - if ($js) { - $this->_addfield('checkbox', $name, $x, $y, $w, $w, $prop); - return; - } - if (!isset($prop['value'])) { - $prop['value'] = array('Yes'); - } - // get default style - $prop = array_merge($this->getFormDefaultProp(), $prop); - $prop['borderStyle'] = 'inset'; - // get annotation data - $popt = TCPDF_STATIC::getAnnotOptFromJSProp($prop, $this->spot_colors, $this->rtl); - // set additional default options - $font = 'zapfdingbats'; - if ($this->pdfa_mode) { - // all fonts must be embedded - $font = 'pdfa'.$font; - } - $this->AddFont($font); - $tmpfont = $this->getFontBuffer($font); - $this->annotation_fonts[$tmpfont['fontkey']] = $tmpfont['i']; - $fontstyle = sprintf('/F%d %F Tf %s', $tmpfont['i'], $this->FontSizePt, $this->TextColor); - $popt['da'] = $fontstyle; - // build appearance stream - $popt['ap'] = array(); - $popt['ap']['n'] = array(); - $fx = ((($w - $this->getAbsFontMeasure($tmpfont['cw'][110])) / 2) * $this->k); - $fy = (($w - ((($tmpfont['desc']['Ascent'] - $tmpfont['desc']['Descent']) * $this->FontSizePt / 1000) / $this->k)) * $this->k); - $popt['ap']['n']['Yes'] = sprintf('q %s BT /F%d %F Tf %F %F Td ('.chr(110).') Tj ET Q', $this->TextColor, $tmpfont['i'], $this->FontSizePt, $fx, $fy); - $popt['ap']['n']['Off'] = sprintf('q %s BT /F%d %F Tf %F %F Td ('.chr(111).') Tj ET Q', $this->TextColor, $tmpfont['i'], $this->FontSizePt, $fx, $fy); - // merge options - $opt = array_merge($popt, $opt); - // set remaining annotation data - $opt['Subtype'] = 'Widget'; - $opt['ft'] = 'Btn'; - $opt['t'] = $name; - if (TCPDF_STATIC::empty_string($onvalue)) { - $onvalue = 'Yes'; - } - $opt['opt'] = array($onvalue); - if ($checked) { - $opt['v'] = array('/Yes'); - $opt['as'] = 'Yes'; - } else { - $opt['v'] = array('/Off'); - $opt['as'] = 'Off'; - } - $this->Annotation($x, $y, $w, $w, $name, $opt, 0); - if ($this->rtl) { - $this->x -= $w; - } else { - $this->x += $w; - } - } - - /** - * Creates a button field - * @param string $name field name - * @param int $w width - * @param int $h height - * @param string $caption caption. - * @param mixed $action action triggered by pressing the button. Use a string to specify a javascript action. Use an array to specify a form action options as on section 12.7.5 of PDF32000_2008. - * @param array $prop javascript field properties. Possible values are described on official Javascript for Acrobat API reference. - * @param array $opt annotation parameters. Possible values are described on official PDF32000_2008 reference. - * @param float|null $x Abscissa of the upper-left corner of the rectangle - * @param float|null $y Ordinate of the upper-left corner of the rectangle - * @param boolean $js if true put the field using JavaScript (requires Acrobat Writer to be rendered). - * @public - * @author Nicola Asuni - * @since 4.8.000 (2009-09-07) - */ - public function Button($name, $w, $h, $caption, $action, $prop=array(), $opt=array(), $x=null, $y=null, $js=false) { - if (TCPDF_STATIC::empty_string($x)) { - $x = $this->x; - } - if (TCPDF_STATIC::empty_string($y)) { - $y = $this->y; - } - // check page for no-write regions and adapt page margins if necessary - list($x, $y) = $this->checkPageRegions($h, $x, $y); - if ($js) { - $this->_addfield('button', $name, $this->x, $this->y, $w, $h, $prop); - $this->javascript .= 'f'.$name.".buttonSetCaption('".addslashes($caption)."');\n"; - $this->javascript .= 'f'.$name.".setAction('MouseUp','".addslashes($action)."');\n"; - $this->javascript .= 'f'.$name.".highlight='push';\n"; - $this->javascript .= 'f'.$name.".print=false;\n"; - return; - } - // get default style - $prop = array_merge($this->getFormDefaultProp(), $prop); - $prop['Pushbutton'] = 'true'; - $prop['highlight'] = 'push'; - $prop['display'] = 'display.noPrint'; - // get annotation data - $popt = TCPDF_STATIC::getAnnotOptFromJSProp($prop, $this->spot_colors, $this->rtl); - $this->annotation_fonts[$this->CurrentFont['fontkey']] = $this->CurrentFont['i']; - $fontstyle = sprintf('/F%d %F Tf %s', $this->CurrentFont['i'], $this->FontSizePt, $this->TextColor); - $popt['da'] = $fontstyle; - // build appearance stream - $popt['ap'] = array(); - $popt['ap']['n'] = '/Tx BMC q '.$fontstyle.' '; - $tmpid = $this->startTemplate($w, $h, false); - $bw = (2 / $this->k); // border width - $border = array( - 'L' => array('width' => $bw, 'cap' => 'square', 'join' => 'miter', 'dash' => 0, 'color' => array(231)), - 'R' => array('width' => $bw, 'cap' => 'square', 'join' => 'miter', 'dash' => 0, 'color' => array(51)), - 'T' => array('width' => $bw, 'cap' => 'square', 'join' => 'miter', 'dash' => 0, 'color' => array(231)), - 'B' => array('width' => $bw, 'cap' => 'square', 'join' => 'miter', 'dash' => 0, 'color' => array(51))); - $this->setFillColor(204); - $this->Cell($w, $h, $caption, $border, 0, 'C', true, '', 1, false, 'T', 'M'); - $this->endTemplate(); - --$this->n; - $popt['ap']['n'] .= $this->xobjects[$tmpid]['outdata']; - unset($this->xobjects[$tmpid]); - $popt['ap']['n'] .= 'Q EMC'; - // set additional default options - if (!isset($popt['mk'])) { - $popt['mk'] = array(); - } - $ann_obj_id = ($this->n + 1); - if (!empty($action) AND !is_array($action)) { - $ann_obj_id = ($this->n + 2); - } - $popt['mk']['ca'] = $this->_textstring($caption, $ann_obj_id); - $popt['mk']['rc'] = $this->_textstring($caption, $ann_obj_id); - $popt['mk']['ac'] = $this->_textstring($caption, $ann_obj_id); - // merge options - $opt = array_merge($popt, $opt); - // set remaining annotation data - $opt['Subtype'] = 'Widget'; - $opt['ft'] = 'Btn'; - $opt['t'] = $caption; - $opt['v'] = $name; - if (!empty($action)) { - if (is_array($action)) { - // form action options as on section 12.7.5 of PDF32000_2008. - $opt['aa'] = '/D <<'; - $bmode = array('SubmitForm', 'ResetForm', 'ImportData'); - foreach ($action AS $key => $val) { - if (($key == 'S') AND in_array($val, $bmode)) { - $opt['aa'] .= ' /S /'.$val; - } elseif (($key == 'F') AND (!empty($val))) { - $opt['aa'] .= ' /F '.$this->_datastring($val, $ann_obj_id); - } elseif (($key == 'Fields') AND is_array($val) AND !empty($val)) { - $opt['aa'] .= ' /Fields ['; - foreach ($val AS $field) { - $opt['aa'] .= ' '.$this->_textstring($field, $ann_obj_id); - } - $opt['aa'] .= ']'; - } elseif (($key == 'Flags')) { - $ff = 0; - if (is_array($val)) { - foreach ($val AS $flag) { - switch ($flag) { - case 'Include/Exclude': { - $ff += 1 << 0; - break; - } - case 'IncludeNoValueFields': { - $ff += 1 << 1; - break; - } - case 'ExportFormat': { - $ff += 1 << 2; - break; - } - case 'GetMethod': { - $ff += 1 << 3; - break; - } - case 'SubmitCoordinates': { - $ff += 1 << 4; - break; - } - case 'XFDF': { - $ff += 1 << 5; - break; - } - case 'IncludeAppendSaves': { - $ff += 1 << 6; - break; - } - case 'IncludeAnnotations': { - $ff += 1 << 7; - break; - } - case 'SubmitPDF': { - $ff += 1 << 8; - break; - } - case 'CanonicalFormat': { - $ff += 1 << 9; - break; - } - case 'ExclNonUserAnnots': { - $ff += 1 << 10; - break; - } - case 'ExclFKey': { - $ff += 1 << 11; - break; - } - case 'EmbedForm': { - $ff += 1 << 13; - break; - } - } - } - } else { - $ff = intval($val); - } - $opt['aa'] .= ' /Flags '.$ff; - } - } - $opt['aa'] .= ' >>'; - } else { - // Javascript action or raw action command - $js_obj_id = $this->addJavascriptObject($action); - $opt['aa'] = '/D '.$js_obj_id.' 0 R'; - } - } - $this->Annotation($x, $y, $w, $h, $name, $opt, 0); - if ($this->rtl) { - $this->x -= $w; - } else { - $this->x += $w; - } - } - - // --- END FORMS FIELDS ------------------------------------------------ - - /** - * Add certification signature (DocMDP or UR3) - * You can set only one signature type - * @protected - * @author Nicola Asuni - * @since 4.6.008 (2009-05-07) - */ - protected function _putsignature() { - if ((!$this->sign) OR (!isset($this->signature_data['cert_type']))) { - return; - } - $sigobjid = ($this->sig_obj_id + 1); - $out = $this->_getobj($sigobjid)."\n"; - $out .= '<< /Type /Sig'; - $out .= ' /Filter /Adobe.PPKLite'; - $out .= ' /SubFilter /adbe.pkcs7.detached'; - $out .= ' '.TCPDF_STATIC::$byterange_string; - $out .= ' /Contents<'.str_repeat('0', $this->signature_max_length).'>'; - if (empty($this->signature_data['approval']) OR ($this->signature_data['approval'] != 'A')) { - $out .= ' /Reference ['; // array of signature reference dictionaries - $out .= ' << /Type /SigRef'; - if ($this->signature_data['cert_type'] > 0) { - $out .= ' /TransformMethod /DocMDP'; - $out .= ' /TransformParams <<'; - $out .= ' /Type /TransformParams'; - $out .= ' /P '.$this->signature_data['cert_type']; - $out .= ' /V /1.2'; - } else { - $out .= ' /TransformMethod /UR3'; - $out .= ' /TransformParams <<'; - $out .= ' /Type /TransformParams'; - $out .= ' /V /2.2'; - if (!TCPDF_STATIC::empty_string($this->ur['document'])) { - $out .= ' /Document['.$this->ur['document'].']'; - } - if (!TCPDF_STATIC::empty_string($this->ur['form'])) { - $out .= ' /Form['.$this->ur['form'].']'; - } - if (!TCPDF_STATIC::empty_string($this->ur['signature'])) { - $out .= ' /Signature['.$this->ur['signature'].']'; - } - if (!TCPDF_STATIC::empty_string($this->ur['annots'])) { - $out .= ' /Annots['.$this->ur['annots'].']'; - } - if (!TCPDF_STATIC::empty_string($this->ur['ef'])) { - $out .= ' /EF['.$this->ur['ef'].']'; - } - if (!TCPDF_STATIC::empty_string($this->ur['formex'])) { - $out .= ' /FormEX['.$this->ur['formex'].']'; - } - } - $out .= ' >>'; // close TransformParams - // optional digest data (values must be calculated and replaced later) - //$out .= ' /Data ********** 0 R'; - //$out .= ' /DigestMethod/MD5'; - //$out .= ' /DigestLocation[********** 34]'; - //$out .= ' /DigestValue<********************************>'; - $out .= ' >>'; - $out .= ' ]'; // end of reference - } - if (isset($this->signature_data['info']['Name']) AND !TCPDF_STATIC::empty_string($this->signature_data['info']['Name'])) { - $out .= ' /Name '.$this->_textstring($this->signature_data['info']['Name'], $sigobjid); - } - if (isset($this->signature_data['info']['Location']) AND !TCPDF_STATIC::empty_string($this->signature_data['info']['Location'])) { - $out .= ' /Location '.$this->_textstring($this->signature_data['info']['Location'], $sigobjid); - } - if (isset($this->signature_data['info']['Reason']) AND !TCPDF_STATIC::empty_string($this->signature_data['info']['Reason'])) { - $out .= ' /Reason '.$this->_textstring($this->signature_data['info']['Reason'], $sigobjid); - } - if (isset($this->signature_data['info']['ContactInfo']) AND !TCPDF_STATIC::empty_string($this->signature_data['info']['ContactInfo'])) { - $out .= ' /ContactInfo '.$this->_textstring($this->signature_data['info']['ContactInfo'], $sigobjid); - } - $out .= ' /M '.$this->_datestring($sigobjid, $this->doc_modification_timestamp); - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - } - - /** - * Set User's Rights for PDF Reader - * WARNING: This is experimental and currently do not work. - * Check the PDF Reference 8.7.1 Transform Methods, - * Table 8.105 Entries in the UR transform parameters dictionary - * @param boolean $enable if true enable user's rights on PDF reader - * @param string $document Names specifying additional document-wide usage rights for the document. The only defined value is "/FullSave", which permits a user to save the document along with modified form and/or annotation data. - * @param string $annots Names specifying additional annotation-related usage rights for the document. Valid names in PDF 1.5 and later are /Create/Delete/Modify/Copy/Import/Export, which permit the user to perform the named operation on annotations. - * @param string $form Names specifying additional form-field-related usage rights for the document. Valid names are: /Add/Delete/FillIn/Import/Export/SubmitStandalone/SpawnTemplate - * @param string $signature Names specifying additional signature-related usage rights for the document. The only defined value is /Modify, which permits a user to apply a digital signature to an existing signature form field or clear a signed signature form field. - * @param string $ef Names specifying additional usage rights for named embedded files in the document. Valid names are /Create/Delete/Modify/Import, which permit the user to perform the named operation on named embedded files - Names specifying additional embedded-files-related usage rights for the document. - * @param string $formex Names specifying additional form-field-related usage rights. The only valid name is BarcodePlaintext, which permits text form field data to be encoded as a plaintext two-dimensional barcode. - * @public - * @author Nicola Asuni - * @since 2.9.000 (2008-03-26) - */ - public function setUserRights( - $enable=true, - $document='/FullSave', - $annots='/Create/Delete/Modify/Copy/Import/Export', - $form='/Add/Delete/FillIn/Import/Export/SubmitStandalone/SpawnTemplate', - $signature='/Modify', - $ef='/Create/Delete/Modify/Import', - $formex='') { - $this->ur['enabled'] = $enable; - $this->ur['document'] = $document; - $this->ur['annots'] = $annots; - $this->ur['form'] = $form; - $this->ur['signature'] = $signature; - $this->ur['ef'] = $ef; - $this->ur['formex'] = $formex; - if (!$this->sign) { - $this->setSignature('', '', '', '', 0, array()); - } - } - - /** - * Enable document signature (requires the OpenSSL Library). - * The digital signature improve document authenticity and integrity and allows o enable extra features on Acrobat Reader. - * To create self-signed signature: openssl req -x509 -nodes -days 365000 -newkey rsa:1024 -keyout tcpdf.crt -out tcpdf.crt - * To export crt to p12: openssl pkcs12 -export -in tcpdf.crt -out tcpdf.p12 - * To convert pfx certificate to pem: openssl pkcs12 -in tcpdf.pfx -out tcpdf.crt -nodes - * @param mixed $signing_cert signing certificate (string or filename prefixed with 'file://') - * @param mixed $private_key private key (string or filename prefixed with 'file://') - * @param string $private_key_password password - * @param string $extracerts specifies the name of a file containing a bunch of extra certificates to include in the signature which can for example be used to help the recipient to verify the certificate that you used. - * @param int $cert_type The access permissions granted for this document. Valid values shall be: 1 = No changes to the document shall be permitted; any change to the document shall invalidate the signature; 2 = Permitted changes shall be filling in forms, instantiating page templates, and signing; other changes shall invalidate the signature; 3 = Permitted changes shall be the same as for 2, as well as annotation creation, deletion, and modification; other changes shall invalidate the signature. - * @param array $info array of option information: Name, Location, Reason, ContactInfo. - * @param string $approval Enable approval signature eg. for PDF incremental update - * @public - * @author Nicola Asuni - * @since 4.6.005 (2009-04-24) - */ - public function setSignature($signing_cert='', $private_key='', $private_key_password='', $extracerts='', $cert_type=2, $info=array(), $approval='') { - // to create self-signed signature: openssl req -x509 -nodes -days 365000 -newkey rsa:1024 -keyout tcpdf.crt -out tcpdf.crt - // to export crt to p12: openssl pkcs12 -export -in tcpdf.crt -out tcpdf.p12 - // to convert pfx certificate to pem: openssl - // OpenSSL> pkcs12 -in <cert.pfx> -out <cert.crt> -nodes - $this->sign = true; - ++$this->n; - $this->sig_obj_id = $this->n; // signature widget - ++$this->n; // signature object ($this->sig_obj_id + 1) - $this->signature_data = array(); - if (strlen($signing_cert) == 0) { - $this->Error('Please provide a certificate file and password!'); - } - if (strlen($private_key) == 0) { - $private_key = $signing_cert; - } - $this->signature_data['signcert'] = $signing_cert; - $this->signature_data['privkey'] = $private_key; - $this->signature_data['password'] = $private_key_password; - $this->signature_data['extracerts'] = $extracerts; - $this->signature_data['cert_type'] = $cert_type; - $this->signature_data['info'] = $info; - $this->signature_data['approval'] = $approval; - } - - /** - * Set the digital signature appearance (a cliccable rectangle area to get signature properties) - * @param float $x Abscissa of the upper-left corner. - * @param float $y Ordinate of the upper-left corner. - * @param float $w Width of the signature area. - * @param float $h Height of the signature area. - * @param int $page option page number (if < 0 the current page is used). - * @param string $name Name of the signature. - * @public - * @author Nicola Asuni - * @since 5.3.011 (2010-06-17) - */ - public function setSignatureAppearance($x=0, $y=0, $w=0, $h=0, $page=-1, $name='') { - $this->signature_appearance = $this->getSignatureAppearanceArray($x, $y, $w, $h, $page, $name); - } - - /** - * Add an empty digital signature appearance (a cliccable rectangle area to get signature properties) - * @param float $x Abscissa of the upper-left corner. - * @param float $y Ordinate of the upper-left corner. - * @param float $w Width of the signature area. - * @param float $h Height of the signature area. - * @param int $page option page number (if < 0 the current page is used). - * @param string $name Name of the signature. - * @public - * @author Nicola Asuni - * @since 5.9.101 (2011-07-06) - */ - public function addEmptySignatureAppearance($x=0, $y=0, $w=0, $h=0, $page=-1, $name='') { - ++$this->n; - $this->empty_signature_appearance[] = array('objid' => $this->n) + $this->getSignatureAppearanceArray($x, $y, $w, $h, $page, $name); - } - - /** - * Get the array that defines the signature appearance (page and rectangle coordinates). - * @param float $x Abscissa of the upper-left corner. - * @param float $y Ordinate of the upper-left corner. - * @param float $w Width of the signature area. - * @param float $h Height of the signature area. - * @param int $page option page number (if < 0 the current page is used). - * @param string $name Name of the signature. - * @return array Array defining page and rectangle coordinates of signature appearance. - * @protected - * @author Nicola Asuni - * @since 5.9.101 (2011-07-06) - */ - protected function getSignatureAppearanceArray($x=0, $y=0, $w=0, $h=0, $page=-1, $name='') { - $sigapp = array(); - if (($page < 1) OR ($page > $this->numpages)) { - $sigapp['page'] = $this->page; - } else { - $sigapp['page'] = intval($page); - } - if (empty($name)) { - $sigapp['name'] = 'Signature'; - } else { - $sigapp['name'] = $name; - } - $a = $x * $this->k; - $b = $this->pagedim[($sigapp['page'])]['h'] - (($y + $h) * $this->k); - $c = $w * $this->k; - $d = $h * $this->k; - $sigapp['rect'] = sprintf('%F %F %F %F', $a, $b, ($a + $c), ($b + $d)); - return $sigapp; - } - - /** - * Enable document timestamping (requires the OpenSSL Library). - * The trusted timestamping improve document security that means that no one should be able to change the document once it has been recorded. - * Use with digital signature only! - * @param string $tsa_host Time Stamping Authority (TSA) server (prefixed with 'https://') - * @param string $tsa_username Specifies the username for TSA authorization (optional) OR specifies the TSA authorization PEM file (see: example_66.php, optional) - * @param string $tsa_password Specifies the password for TSA authorization (optional) - * @param string $tsa_cert Specifies the location of TSA certificate for authorization (optional for cURL) - * @public - * @author Richard Stockinger - * @since 6.0.090 (2014-06-16) - */ - public function setTimeStamp($tsa_host='', $tsa_username='', $tsa_password='', $tsa_cert='') { - $this->tsa_data = array(); - if (!function_exists('curl_init')) { - $this->Error('Please enable cURL PHP extension!'); - } - if (strlen($tsa_host) == 0) { - $this->Error('Please specify the host of Time Stamping Authority (TSA)!'); - } - $this->tsa_data['tsa_host'] = $tsa_host; - if (is_file($tsa_username)) { - $this->tsa_data['tsa_auth'] = $tsa_username; - } else { - $this->tsa_data['tsa_username'] = $tsa_username; - } - $this->tsa_data['tsa_password'] = $tsa_password; - $this->tsa_data['tsa_cert'] = $tsa_cert; - $this->tsa_timestamp = true; - } - - /** - * NOT YET IMPLEMENTED - * Request TSA for a timestamp - * @param string $signature Digital signature as binary string - * @return string Timestamped digital signature - * @protected - * @author Richard Stockinger - * @since 6.0.090 (2014-06-16) - */ - protected function applyTSA($signature) { - if (!$this->tsa_timestamp) { - return $signature; - } - //@TODO: implement this feature - return $signature; - } - - /** - * Create a new page group. - * NOTE: call this function before calling AddPage() - * @param int|null $page starting group page (leave empty for next page). - * @public - * @since 3.0.000 (2008-03-27) - */ - public function startPageGroup($page=null) { - if (empty($page)) { - $page = $this->page + 1; - } - $this->newpagegroup[$page] = sizeof($this->newpagegroup) + 1; - } - - /** - * Set the starting page number. - * @param int $num Starting page number. - * @since 5.9.093 (2011-06-16) - * @public - */ - public function setStartingPageNumber($num=1) { - $this->starting_page_number = max(0, intval($num)); - } - - /** - * Returns the string alias used right align page numbers. - * If the current font is unicode type, the returned string wil contain an additional open curly brace. - * @return string - * @since 5.9.099 (2011-06-27) - * @public - */ - public function getAliasRightShift() { - // calculate aproximatively the ratio between widths of aliases and replacements. - $ref = '{'.TCPDF_STATIC::$alias_right_shift.'}{'.TCPDF_STATIC::$alias_tot_pages.'}{'.TCPDF_STATIC::$alias_num_page.'}'; - $rep = str_repeat(' ', $this->GetNumChars($ref)); - $wrep = $this->GetStringWidth($rep); - if ($wrep > 0) { - $wdiff = max(1, ($this->GetStringWidth($ref) / $wrep)); - } else { - $wdiff = 1; - } - $sdiff = sprintf('%F', $wdiff); - $alias = TCPDF_STATIC::$alias_right_shift.$sdiff.'}'; - if ($this->isUnicodeFont()) { - $alias = '{'.$alias; - } - return $alias; - } - - /** - * Returns the string alias used for the total number of pages. - * If the current font is unicode type, the returned string is surrounded by additional curly braces. - * This alias will be replaced by the total number of pages in the document. - * @return string - * @since 4.0.018 (2008-08-08) - * @public - */ - public function getAliasNbPages() { - if ($this->isUnicodeFont()) { - return '{'.TCPDF_STATIC::$alias_tot_pages.'}'; - } - return TCPDF_STATIC::$alias_tot_pages; - } - - /** - * Returns the string alias used for the page number. - * If the current font is unicode type, the returned string is surrounded by additional curly braces. - * This alias will be replaced by the page number. - * @return string - * @since 4.5.000 (2009-01-02) - * @public - */ - public function getAliasNumPage() { - if ($this->isUnicodeFont()) { - return '{'.TCPDF_STATIC::$alias_num_page.'}'; - } - return TCPDF_STATIC::$alias_num_page; - } - - /** - * Return the alias for the total number of pages in the current page group. - * If the current font is unicode type, the returned string is surrounded by additional curly braces. - * This alias will be replaced by the total number of pages in this group. - * @return string alias of the current page group - * @public - * @since 3.0.000 (2008-03-27) - */ - public function getPageGroupAlias() { - if ($this->isUnicodeFont()) { - return '{'.TCPDF_STATIC::$alias_group_tot_pages.'}'; - } - return TCPDF_STATIC::$alias_group_tot_pages; - } - - /** - * Return the alias for the page number on the current page group. - * If the current font is unicode type, the returned string is surrounded by additional curly braces. - * This alias will be replaced by the page number (relative to the belonging group). - * @return string alias of the current page group - * @public - * @since 4.5.000 (2009-01-02) - */ - public function getPageNumGroupAlias() { - if ($this->isUnicodeFont()) { - return '{'.TCPDF_STATIC::$alias_group_num_page.'}'; - } - return TCPDF_STATIC::$alias_group_num_page; - } - - /** - * Return the current page in the group. - * @return int current page in the group - * @public - * @since 3.0.000 (2008-03-27) - */ - public function getGroupPageNo() { - return $this->pagegroups[$this->currpagegroup]; - } - - /** - * Returns the current group page number formatted as a string. - * @public - * @since 4.3.003 (2008-11-18) - * @see PaneNo(), formatPageNumber() - */ - public function getGroupPageNoFormatted() { - return TCPDF_STATIC::formatPageNumber($this->getGroupPageNo()); - } - - /** - * Returns the current page number formatted as a string. - * @public - * @since 4.2.005 (2008-11-06) - * @see PaneNo(), formatPageNumber() - */ - public function PageNoFormatted() { - return TCPDF_STATIC::formatPageNumber($this->PageNo()); - } - - /** - * Put pdf layers. - * @protected - * @since 3.0.000 (2008-03-27) - */ - protected function _putocg() { - if (empty($this->pdflayers)) { - return; - } - foreach ($this->pdflayers as $key => $layer) { - $this->pdflayers[$key]['objid'] = $this->_newobj(); - $out = '<< /Type /OCG'; - $out .= ' /Name '.$this->_textstring($layer['name'], $this->pdflayers[$key]['objid']); - $out .= ' /Usage <<'; - if (isset($layer['print']) AND ($layer['print'] !== NULL)) { - $out .= ' /Print <</PrintState /'.($layer['print']?'ON':'OFF').'>>'; - } - $out .= ' /View <</ViewState /'.($layer['view']?'ON':'OFF').'>>'; - $out .= ' >> >>'; - $out .= "\n".'endobj'; - $this->_out($out); - } - } - - /** - * Start a new pdf layer. - * @param string $name Layer name (only a-z letters and numbers). Leave empty for automatic name. - * @param boolean|null $print Set to TRUE to print this layer, FALSE to not print and NULL to not set this option - * @param boolean $view Set to true to view this layer. - * @param boolean $lock If true lock the layer - * @public - * @since 5.9.102 (2011-07-13) - */ - public function startLayer($name='', $print=true, $view=true, $lock=true) { - if ($this->state != 2) { - return; - } - $layer = sprintf('LYR%03d', (count($this->pdflayers) + 1)); - if (empty($name)) { - $name = $layer; - } else { - $name = preg_replace('/[^a-zA-Z0-9_\-]/', '', $name); - } - $this->pdflayers[] = array('layer' => $layer, 'name' => $name, 'print' => $print, 'view' => $view, 'lock' => $lock); - $this->openMarkedContent = true; - $this->_out('/OC /'.$layer.' BDC'); - } - - /** - * End the current PDF layer. - * @public - * @since 5.9.102 (2011-07-13) - */ - public function endLayer() { - if ($this->state != 2) { - return; - } - if ($this->openMarkedContent) { - // close existing open marked-content layer - $this->_out('EMC'); - $this->openMarkedContent = false; - } - } - - /** - * Set the visibility of the successive elements. - * This can be useful, for instance, to put a background - * image or color that will show on screen but won't print. - * @param string $v visibility mode. Legal values are: all, print, screen or view. - * @public - * @since 3.0.000 (2008-03-27) - */ - public function setVisibility($v) { - if ($this->state != 2) { - return; - } - $this->endLayer(); - switch($v) { - case 'print': { - $this->startLayer('Print', true, false); - break; - } - case 'view': - case 'screen': { - $this->startLayer('View', false, true); - break; - } - case 'all': { - $this->_out(''); - break; - } - default: { - $this->Error('Incorrect visibility: '.$v); - break; - } - } - } - - /** - * Add transparency parameters to the current extgstate - * @param array $parms parameters - * @return int|void the number of extgstates - * @protected - * @since 3.0.000 (2008-03-27) - */ - protected function addExtGState($parms) { - if ($this->pdfa_mode || $this->pdfa_version >= 2) { - // transparencies are not allowed in PDF/A mode - return; - } - // check if this ExtGState already exist - foreach ($this->extgstates as $i => $ext) { - if ($ext['parms'] == $parms) { - if ($this->inxobj) { - // we are inside an XObject template - $this->xobjects[$this->xobjid]['extgstates'][$i] = $ext; - } - // return reference to existing ExtGState - return $i; - } - } - $n = (count($this->extgstates) + 1); - $this->extgstates[$n] = array('parms' => $parms); - if ($this->inxobj) { - // we are inside an XObject template - $this->xobjects[$this->xobjid]['extgstates'][$n] = $this->extgstates[$n]; - } - return $n; - } - - /** - * Add an extgstate - * @param int $gs extgstate - * @protected - * @since 3.0.000 (2008-03-27) - */ - protected function setExtGState($gs) { - if (($this->pdfa_mode && $this->pdfa_version < 2) OR ($this->state != 2)) { - // transparency is not allowed in PDF/A-1 mode - return; - } - $this->_out(sprintf('/GS%d gs', $gs)); - } - - /** - * Put extgstates for object transparency - * @protected - * @since 3.0.000 (2008-03-27) - */ - protected function _putextgstates() { - foreach ($this->extgstates as $i => $ext) { - $this->extgstates[$i]['n'] = $this->_newobj(); - $out = '<< /Type /ExtGState'; - foreach ($ext['parms'] as $k => $v) { - if (is_float($v)) { - $v = sprintf('%F', $v); - } elseif ($v === true) { - $v = 'true'; - } elseif ($v === false) { - $v = 'false'; - } - $out .= ' /'.$k.' '.$v; - } - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - } - } - - /** - * Set overprint mode for stroking (OP) and non-stroking (op) painting operations. - * (Check the "Entries in a Graphics State Parameter Dictionary" on PDF 32000-1:2008). - * @param boolean $stroking If true apply overprint for stroking operations. - * @param boolean|null $nonstroking If true apply overprint for painting operations other than stroking. - * @param integer $mode Overprint mode: (0 = each source colour component value replaces the value previously painted for the corresponding device colorant; 1 = a tint value of 0.0 for a source colour component shall leave the corresponding component of the previously painted colour unchanged). - * @public - * @since 5.9.152 (2012-03-23) - */ - public function setOverprint($stroking=true, $nonstroking=null, $mode=0) { - if ($this->state != 2) { - return; - } - $stroking = $stroking ? true : false; - if (TCPDF_STATIC::empty_string($nonstroking)) { - // default value if not set - $nonstroking = $stroking; - } else { - $nonstroking = $nonstroking ? true : false; - } - if (($mode != 0) AND ($mode != 1)) { - $mode = 0; - } - $this->overprint = array('OP' => $stroking, 'op' => $nonstroking, 'OPM' => $mode); - $gs = $this->addExtGState($this->overprint); - $this->setExtGState($gs); - } - - /** - * Get the overprint mode array (OP, op, OPM). - * (Check the "Entries in a Graphics State Parameter Dictionary" on PDF 32000-1:2008). - * @return array<string,bool|int> - * @public - * @since 5.9.152 (2012-03-23) - */ - public function getOverprint() { - return $this->overprint; - } - - /** - * Set alpha for stroking (CA) and non-stroking (ca) operations. - * @param float $stroking Alpha value for stroking operations: real value from 0 (transparent) to 1 (opaque). - * @param string $bm blend mode, one of the following: Normal, Multiply, Screen, Overlay, Darken, Lighten, ColorDodge, ColorBurn, HardLight, SoftLight, Difference, Exclusion, Hue, Saturation, Color, Luminosity - * @param float|null $nonstroking Alpha value for non-stroking operations: real value from 0 (transparent) to 1 (opaque). - * @param boolean $ais - * @public - * @since 3.0.000 (2008-03-27) - */ - public function setAlpha($stroking=1, $bm='Normal', $nonstroking=null, $ais=false) { - if ($this->pdfa_mode && $this->pdfa_version < 2) { - // transparency is not allowed in PDF/A-1 mode - return; - } - $stroking = floatval($stroking); - if (TCPDF_STATIC::empty_string($nonstroking)) { - // default value if not set - $nonstroking = $stroking; - } else { - $nonstroking = floatval($nonstroking); - } - if ($bm[0] == '/') { - // remove trailing slash - $bm = substr($bm, 1); - } - if (!in_array($bm, array('Normal', 'Multiply', 'Screen', 'Overlay', 'Darken', 'Lighten', 'ColorDodge', 'ColorBurn', 'HardLight', 'SoftLight', 'Difference', 'Exclusion', 'Hue', 'Saturation', 'Color', 'Luminosity'))) { - $bm = 'Normal'; - } - $ais = $ais ? true : false; - $this->alpha = array('CA' => $stroking, 'ca' => $nonstroking, 'BM' => '/'.$bm, 'AIS' => $ais); - $gs = $this->addExtGState($this->alpha); - $this->setExtGState($gs); - } - - /** - * Get the alpha mode array (CA, ca, BM, AIS). - * (Check the "Entries in a Graphics State Parameter Dictionary" on PDF 32000-1:2008). - * @return array<string,bool|string> - * @public - * @since 5.9.152 (2012-03-23) - */ - public function getAlpha() { - return $this->alpha; - } - - /** - * Set the default JPEG compression quality (1-100) - * @param int $quality JPEG quality, integer between 1 and 100 - * @public - * @since 3.0.000 (2008-03-27) - */ - public function setJPEGQuality($quality) { - if (($quality < 1) OR ($quality > 100)) { - $quality = 75; - } - $this->jpeg_quality = intval($quality); - } - - /** - * Set the default number of columns in a row for HTML tables. - * @param int $cols number of columns - * @public - * @since 3.0.014 (2008-06-04) - */ - public function setDefaultTableColumns($cols=4) { - $this->default_table_columns = intval($cols); - } - - /** - * Set the height of the cell (line height) respect the font height. - * @param float $h cell proportion respect font height (typical value = 1.25). - * @public - * @since 3.0.014 (2008-06-04) - */ - public function setCellHeightRatio($h) { - $this->cell_height_ratio = $h; - } - - /** - * return the height of cell repect font height. - * @public - * @return float - * @since 4.0.012 (2008-07-24) - */ - public function getCellHeightRatio() { - return $this->cell_height_ratio; - } - - /** - * Set the PDF version (check PDF reference for valid values). - * @param string $version PDF document version. - * @public - * @since 3.1.000 (2008-06-09) - */ - public function setPDFVersion($version='1.7') { - if ($this->pdfa_mode && $this->pdfa_version == 1 ) { - // PDF/A-1 mode - $this->PDFVersion = '1.4'; - } elseif ($this->pdfa_mode && $this->pdfa_version >= 2 ) { - // PDF/A-2 mode - $this->PDFVersion = '1.7'; - } else { - $this->PDFVersion = $version; - } - } - - /** - * Set the viewer preferences dictionary controlling the way the document is to be presented on the screen or in print. - * (see Section 8.1 of PDF reference, "Viewer Preferences"). - * <ul><li>HideToolbar boolean (Optional) A flag specifying whether to hide the viewer application's tool bars when the document is active. Default value: false.</li><li>HideMenubar boolean (Optional) A flag specifying whether to hide the viewer application's menu bar when the document is active. Default value: false.</li><li>HideWindowUI boolean (Optional) A flag specifying whether to hide user interface elements in the document's window (such as scroll bars and navigation controls), leaving only the document's contents displayed. Default value: false.</li><li>FitWindow boolean (Optional) A flag specifying whether to resize the document's window to fit the size of the first displayed page. Default value: false.</li><li>CenterWindow boolean (Optional) A flag specifying whether to position the document's window in the center of the screen. Default value: false.</li><li>DisplayDocTitle boolean (Optional; PDF 1.4) A flag specifying whether the window's title bar should display the document title taken from the Title entry of the document information dictionary (see Section 10.2.1, "Document Information Dictionary"). If false, the title bar should instead display the name of the PDF file containing the document. Default value: false.</li><li>NonFullScreenPageMode name (Optional) The document's page mode, specifying how to display the document on exiting full-screen mode:<ul><li>UseNone Neither document outline nor thumbnail images visible</li><li>UseOutlines Document outline visible</li><li>UseThumbs Thumbnail images visible</li><li>UseOC Optional content group panel visible</li></ul>This entry is meaningful only if the value of the PageMode entry in the catalog dictionary (see Section 3.6.1, "Document Catalog") is FullScreen; it is ignored otherwise. Default value: UseNone.</li><li>ViewArea name (Optional; PDF 1.4) The name of the page boundary representing the area of a page to be displayed when viewing the document on the screen. Valid values are (see Section 10.10.1, "Page Boundaries").:<ul><li>MediaBox</li><li>CropBox (default)</li><li>BleedBox</li><li>TrimBox</li><li>ArtBox</li></ul></li><li>ViewClip name (Optional; PDF 1.4) The name of the page boundary to which the contents of a page are to be clipped when viewing the document on the screen. Valid values are (see Section 10.10.1, "Page Boundaries").:<ul><li>MediaBox</li><li>CropBox (default)</li><li>BleedBox</li><li>TrimBox</li><li>ArtBox</li></ul></li><li>PrintArea name (Optional; PDF 1.4) The name of the page boundary representing the area of a page to be rendered when printing the document. Valid values are (see Section 10.10.1, "Page Boundaries").:<ul><li>MediaBox</li><li>CropBox (default)</li><li>BleedBox</li><li>TrimBox</li><li>ArtBox</li></ul></li><li>PrintClip name (Optional; PDF 1.4) The name of the page boundary to which the contents of a page are to be clipped when printing the document. Valid values are (see Section 10.10.1, "Page Boundaries").:<ul><li>MediaBox</li><li>CropBox (default)</li><li>BleedBox</li><li>TrimBox</li><li>ArtBox</li></ul></li><li>PrintScaling name (Optional; PDF 1.6) The page scaling option to be selected when a print dialog is displayed for this document. Valid values are: <ul><li>None, which indicates that the print dialog should reflect no page scaling</li><li>AppDefault (default), which indicates that applications should use the current print scaling</li></ul></li><li>Duplex name (Optional; PDF 1.7) The paper handling option to use when printing the file from the print dialog. The following values are valid:<ul><li>Simplex - Print single-sided</li><li>DuplexFlipShortEdge - Duplex and flip on the short edge of the sheet</li><li>DuplexFlipLongEdge - Duplex and flip on the long edge of the sheet</li></ul>Default value: none</li><li>PickTrayByPDFSize boolean (Optional; PDF 1.7) A flag specifying whether the PDF page size is used to select the input paper tray. This setting influences only the preset values used to populate the print dialog presented by a PDF viewer application. If PickTrayByPDFSize is true, the check box in the print dialog associated with input paper tray is checked. Note: This setting has no effect on Mac OS systems, which do not provide the ability to pick the input tray by size.</li><li>PrintPageRange array (Optional; PDF 1.7) The page numbers used to initialize the print dialog box when the file is printed. The first page of the PDF file is denoted by 1. Each pair consists of the first and last pages in the sub-range. An odd number of integers causes this entry to be ignored. Negative numbers cause the entire array to be ignored. Default value: as defined by PDF viewer application</li><li>NumCopies integer (Optional; PDF 1.7) The number of copies to be printed when the print dialog is opened for this file. Supported values are the integers 2 through 5. Values outside this range are ignored. Default value: as defined by PDF viewer application, but typically 1</li></ul> - * @param array $preferences array of options. - * @author Nicola Asuni - * @public - * @since 3.1.000 (2008-06-09) - */ - public function setViewerPreferences($preferences) { - $this->viewer_preferences = $preferences; - } - - /** - * Paints color transition registration bars - * @param float $x abscissa of the top left corner of the rectangle. - * @param float $y ordinate of the top left corner of the rectangle. - * @param float $w width of the rectangle. - * @param float $h height of the rectangle. - * @param boolean $transition if true prints tcolor transitions to white. - * @param boolean $vertical if true prints bar vertically. - * @param string $colors colors to print separated by comma. Valid values are: A,W,R,G,B,C,M,Y,K,RGB,CMYK,ALL,ALLSPOT,<SPOT_COLOR_NAME>. Where: A = grayscale black, W = grayscale white, R = RGB red, G RGB green, B RGB blue, C = CMYK cyan, M = CMYK magenta, Y = CMYK yellow, K = CMYK key/black, RGB = RGB registration color, CMYK = CMYK registration color, ALL = Spot registration color, ALLSPOT = print all defined spot colors, <SPOT_COLOR_NAME> = name of the spot color to print. - * @author Nicola Asuni - * @since 4.9.000 (2010-03-26) - * @public - */ - public function colorRegistrationBar($x, $y, $w, $h, $transition=true, $vertical=false, $colors='A,R,G,B,C,M,Y,K') { - if (strpos($colors, 'ALLSPOT') !== false) { - // expand spot colors - $spot_colors = ''; - foreach ($this->spot_colors as $spot_color_name => $v) { - $spot_colors .= ','.$spot_color_name; - } - if (!empty($spot_colors)) { - $spot_colors = substr($spot_colors, 1); - $colors = str_replace('ALLSPOT', $spot_colors, $colors); - } else { - $colors = str_replace('ALLSPOT', 'NONE', $colors); - } - } - $bars = explode(',', $colors); - $numbars = count($bars); // number of bars to print - if ($numbars <= 0) { - return; - } - // set bar measures - if ($vertical) { - $coords = array(0, 0, 0, 1); - $wb = $w / $numbars; // bar width - $hb = $h; // bar height - $xd = $wb; // delta x - $yd = 0; // delta y - } else { - $coords = array(1, 0, 0, 0); - $wb = $w; // bar width - $hb = $h / $numbars; // bar height - $xd = 0; // delta x - $yd = $hb; // delta y - } - $xb = $x; - $yb = $y; - foreach ($bars as $col) { - switch ($col) { - // set transition colors - case 'A': { // BLACK (GRAYSCALE) - $col_a = array(255); - $col_b = array(0); - break; - } - case 'W': { // WHITE (GRAYSCALE) - $col_a = array(0); - $col_b = array(255); - break; - } - case 'R': { // RED (RGB) - $col_a = array(255,255,255); - $col_b = array(255,0,0); - break; - } - case 'G': { // GREEN (RGB) - $col_a = array(255,255,255); - $col_b = array(0,255,0); - break; - } - case 'B': { // BLUE (RGB) - $col_a = array(255,255,255); - $col_b = array(0,0,255); - break; - } - case 'C': { // CYAN (CMYK) - $col_a = array(0,0,0,0); - $col_b = array(100,0,0,0); - break; - } - case 'M': { // MAGENTA (CMYK) - $col_a = array(0,0,0,0); - $col_b = array(0,100,0,0); - break; - } - case 'Y': { // YELLOW (CMYK) - $col_a = array(0,0,0,0); - $col_b = array(0,0,100,0); - break; - } - case 'K': { // KEY - BLACK (CMYK) - $col_a = array(0,0,0,0); - $col_b = array(0,0,0,100); - break; - } - case 'RGB': { // BLACK REGISTRATION (RGB) - $col_a = array(255,255,255); - $col_b = array(0,0,0); - break; - } - case 'CMYK': { // BLACK REGISTRATION (CMYK) - $col_a = array(0,0,0,0); - $col_b = array(100,100,100,100); - break; - } - case 'ALL': { // SPOT COLOR REGISTRATION - $col_a = array(0,0,0,0,'None'); - $col_b = array(100,100,100,100,'All'); - break; - } - case 'NONE': { // SKIP THIS COLOR - $col_a = array(0,0,0,0,'None'); - $col_b = array(0,0,0,0,'None'); - break; - } - default: { // SPECIFIC SPOT COLOR NAME - $col_a = array(0,0,0,0,'None'); - $col_b = TCPDF_COLORS::getSpotColor($col, $this->spot_colors); - if ($col_b === false) { - // in case of error defaults to the registration color - $col_b = array(100,100,100,100,'All'); - } - break; - } - } - if ($col != 'NONE') { - if ($transition) { - // color gradient - $this->LinearGradient($xb, $yb, $wb, $hb, $col_a, $col_b, $coords); - } else { - $this->setFillColorArray($col_b); - // colored rectangle - $this->Rect($xb, $yb, $wb, $hb, 'F', array()); - } - $xb += $xd; - $yb += $yd; - } - } - } - - /** - * Paints crop marks. - * @param float $x abscissa of the crop mark center. - * @param float $y ordinate of the crop mark center. - * @param float $w width of the crop mark. - * @param float $h height of the crop mark. - * @param string $type type of crop mark, one symbol per type separated by comma: T = TOP, F = BOTTOM, L = LEFT, R = RIGHT, TL = A = TOP-LEFT, TR = B = TOP-RIGHT, BL = C = BOTTOM-LEFT, BR = D = BOTTOM-RIGHT. - * @param array $color crop mark color (default spot registration color). - * @author Nicola Asuni - * @since 4.9.000 (2010-03-26) - * @public - */ - public function cropMark($x, $y, $w, $h, $type='T,R,B,L', $color=array(100,100,100,100,'All')) { - $this->setLineStyle(array('width' => (0.5 / $this->k), 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => $color)); - $type = strtoupper($type); - $type = preg_replace('/[^A-Z\-\,]*/', '', $type); - // split type in single components - $type = str_replace('-', ',', $type); - $type = str_replace('TL', 'T,L', $type); - $type = str_replace('TR', 'T,R', $type); - $type = str_replace('BL', 'F,L', $type); - $type = str_replace('BR', 'F,R', $type); - $type = str_replace('A', 'T,L', $type); - $type = str_replace('B', 'T,R', $type); - $type = str_replace('T,RO', 'BO', $type); - $type = str_replace('C', 'F,L', $type); - $type = str_replace('D', 'F,R', $type); - $crops = explode(',', strtoupper($type)); - // remove duplicates - $crops = array_unique($crops); - $dw = ($w / 4); // horizontal space to leave before the intersection point - $dh = ($h / 4); // vertical space to leave before the intersection point - foreach ($crops as $crop) { - switch ($crop) { - case 'T': - case 'TOP': { - $x1 = $x; - $y1 = ($y - $h); - $x2 = $x; - $y2 = ($y - $dh); - break; - } - case 'F': - case 'BOTTOM': { - $x1 = $x; - $y1 = ($y + $dh); - $x2 = $x; - $y2 = ($y + $h); - break; - } - case 'L': - case 'LEFT': { - $x1 = ($x - $w); - $y1 = $y; - $x2 = ($x - $dw); - $y2 = $y; - break; - } - case 'R': - case 'RIGHT': { - $x1 = ($x + $dw); - $y1 = $y; - $x2 = ($x + $w); - $y2 = $y; - break; - } - } - $this->Line($x1, $y1, $x2, $y2); - } - } - - /** - * Paints a registration mark - * @param float $x abscissa of the registration mark center. - * @param float $y ordinate of the registration mark center. - * @param float $r radius of the crop mark. - * @param boolean $double if true print two concentric crop marks. - * @param array $cola crop mark color (default spot registration color 'All'). - * @param array $colb second crop mark color (default spot registration color 'None'). - * @author Nicola Asuni - * @since 4.9.000 (2010-03-26) - * @public - */ - public function registrationMark($x, $y, $r, $double=false, $cola=array(100,100,100,100,'All'), $colb=array(0,0,0,0,'None')) { - $line_style = array('width' => max((0.5 / $this->k),($r / 30)), 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => $cola); - $this->setFillColorArray($cola); - $this->PieSector($x, $y, $r, 90, 180, 'F'); - $this->PieSector($x, $y, $r, 270, 360, 'F'); - $this->Circle($x, $y, $r, 0, 360, 'C', $line_style, array(), 8); - if ($double) { - $ri = $r * 0.5; - $this->setFillColorArray($colb); - $this->PieSector($x, $y, $ri, 90, 180, 'F'); - $this->PieSector($x, $y, $ri, 270, 360, 'F'); - $this->setFillColorArray($cola); - $this->PieSector($x, $y, $ri, 0, 90, 'F'); - $this->PieSector($x, $y, $ri, 180, 270, 'F'); - $this->Circle($x, $y, $ri, 0, 360, 'C', $line_style, array(), 8); - } - } - - /** - * Paints a CMYK registration mark - * @param float $x abscissa of the registration mark center. - * @param float $y ordinate of the registration mark center. - * @param float $r radius of the crop mark. - * @author Nicola Asuni - * @since 6.0.038 (2013-09-30) - * @public - */ - public function registrationMarkCMYK($x, $y, $r) { - // line width - $lw = max((0.5 / $this->k),($r / 8)); - // internal radius - $ri = ($r * 0.6); - // external radius - $re = ($r * 1.3); - // Cyan - $this->setFillColorArray(array(100,0,0,0)); - $this->PieSector($x, $y, $ri, 270, 360, 'F'); - // Magenta - $this->setFillColorArray(array(0,100,0,0)); - $this->PieSector($x, $y, $ri, 0, 90, 'F'); - // Yellow - $this->setFillColorArray(array(0,0,100,0)); - $this->PieSector($x, $y, $ri, 90, 180, 'F'); - // Key - black - $this->setFillColorArray(array(0,0,0,100)); - $this->PieSector($x, $y, $ri, 180, 270, 'F'); - // registration color - $line_style = array('width' => $lw, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(100,100,100,100,'All')); - $this->setFillColorArray(array(100,100,100,100,'All')); - // external circle - $this->Circle($x, $y, $r, 0, 360, 'C', $line_style, array(), 8); - // cross lines - $this->Line($x, ($y - $re), $x, ($y - $ri)); - $this->Line($x, ($y + $ri), $x, ($y + $re)); - $this->Line(($x - $re), $y, ($x - $ri), $y); - $this->Line(($x + $ri), $y, ($x + $re), $y); - } - - /** - * Paints a linear colour gradient. - * @param float $x abscissa of the top left corner of the rectangle. - * @param float $y ordinate of the top left corner of the rectangle. - * @param float $w width of the rectangle. - * @param float $h height of the rectangle. - * @param array $col1 first color (Grayscale, RGB or CMYK components). - * @param array $col2 second color (Grayscale, RGB or CMYK components). - * @param array $coords array of the form (x1, y1, x2, y2) which defines the gradient vector (see linear_gradient_coords.jpg). The default value is from left to right (x1=0, y1=0, x2=1, y2=0). - * @author Andreas W\FCrmser, Nicola Asuni - * @since 3.1.000 (2008-06-09) - * @public - */ - public function LinearGradient($x, $y, $w, $h, $col1=array(), $col2=array(), $coords=array(0,0,1,0)) { - $this->Clip($x, $y, $w, $h); - $this->Gradient(2, $coords, array(array('color' => $col1, 'offset' => 0, 'exponent' => 1), array('color' => $col2, 'offset' => 1, 'exponent' => 1)), array(), false); - } - - /** - * Paints a radial colour gradient. - * @param float $x abscissa of the top left corner of the rectangle. - * @param float $y ordinate of the top left corner of the rectangle. - * @param float $w width of the rectangle. - * @param float $h height of the rectangle. - * @param array $col1 first color (Grayscale, RGB or CMYK components). - * @param array $col2 second color (Grayscale, RGB or CMYK components). - * @param array $coords array of the form (fx, fy, cx, cy, r) where (fx, fy) is the starting point of the gradient with color1, (cx, cy) is the center of the circle with color2, and r is the radius of the circle (see radial_gradient_coords.jpg). (fx, fy) should be inside the circle, otherwise some areas will not be defined. - * @author Andreas W\FCrmser, Nicola Asuni - * @since 3.1.000 (2008-06-09) - * @public - */ - public function RadialGradient($x, $y, $w, $h, $col1=array(), $col2=array(), $coords=array(0.5,0.5,0.5,0.5,1)) { - $this->Clip($x, $y, $w, $h); - $this->Gradient(3, $coords, array(array('color' => $col1, 'offset' => 0, 'exponent' => 1), array('color' => $col2, 'offset' => 1, 'exponent' => 1)), array(), false); - } - - /** - * Paints a coons patch mesh. - * @param float $x abscissa of the top left corner of the rectangle. - * @param float $y ordinate of the top left corner of the rectangle. - * @param float $w width of the rectangle. - * @param float $h height of the rectangle. - * @param array $col1 first color (lower left corner) (RGB components). - * @param array $col2 second color (lower right corner) (RGB components). - * @param array $col3 third color (upper right corner) (RGB components). - * @param array $col4 fourth color (upper left corner) (RGB components). - * @param array $coords <ul><li>for one patch mesh: array(float x1, float y1, .... float x12, float y12): 12 pairs of coordinates (normally from 0 to 1) which specify the Bezier control points that define the patch. First pair is the lower left edge point, next is its right control point (control point 2). Then the other points are defined in the order: control point 1, edge point, control point 2 going counter-clockwise around the patch. Last (x12, y12) is the first edge point's left control point (control point 1).</li><li>for two or more patch meshes: array[number of patches]: arrays with the following keys for each patch: f: where to put that patch (0 = first patch, 1, 2, 3 = right, top and left of precedent patch - I didn't figure this out completely - just try and error ;-) points: 12 pairs of coordinates of the Bezier control points as above for the first patch, 8 pairs of coordinates for the following patches, ignoring the coordinates already defined by the precedent patch (I also didn't figure out the order of these - also: try and see what's happening) colors: must be 4 colors for the first patch, 2 colors for the following patches</li></ul> - * @param array $coords_min minimum value used by the coordinates. If a coordinate's value is smaller than this it will be cut to coords_min. default: 0 - * @param array $coords_max maximum value used by the coordinates. If a coordinate's value is greater than this it will be cut to coords_max. default: 1 - * @param boolean $antialias A flag indicating whether to filter the shading function to prevent aliasing artifacts. - * @author Andreas W\FCrmser, Nicola Asuni - * @since 3.1.000 (2008-06-09) - * @public - */ - public function CoonsPatchMesh($x, $y, $w, $h, $col1=array(), $col2=array(), $col3=array(), $col4=array(), $coords=array(0.00,0.0,0.33,0.00,0.67,0.00,1.00,0.00,1.00,0.33,1.00,0.67,1.00,1.00,0.67,1.00,0.33,1.00,0.00,1.00,0.00,0.67,0.00,0.33), $coords_min=0, $coords_max=1, $antialias=false) { - if (($this->pdfa_mode && $this->pdfa_version < 2) OR ($this->state != 2)) { - return; - } - $this->Clip($x, $y, $w, $h); - $n = count($this->gradients) + 1; - $this->gradients[$n] = array(); - $this->gradients[$n]['type'] = 6; //coons patch mesh - $this->gradients[$n]['coords'] = array(); - $this->gradients[$n]['antialias'] = $antialias; - $this->gradients[$n]['colors'] = array(); - $this->gradients[$n]['transparency'] = false; - //check the coords array if it is the simple array or the multi patch array - if (!isset($coords[0]['f'])) { - //simple array -> convert to multi patch array - if (!isset($col1[1])) { - $col1[1] = $col1[2] = $col1[0]; - } - if (!isset($col2[1])) { - $col2[1] = $col2[2] = $col2[0]; - } - if (!isset($col3[1])) { - $col3[1] = $col3[2] = $col3[0]; - } - if (!isset($col4[1])) { - $col4[1] = $col4[2] = $col4[0]; - } - $patch_array[0]['f'] = 0; - $patch_array[0]['points'] = $coords; - $patch_array[0]['colors'][0]['r'] = $col1[0]; - $patch_array[0]['colors'][0]['g'] = $col1[1]; - $patch_array[0]['colors'][0]['b'] = $col1[2]; - $patch_array[0]['colors'][1]['r'] = $col2[0]; - $patch_array[0]['colors'][1]['g'] = $col2[1]; - $patch_array[0]['colors'][1]['b'] = $col2[2]; - $patch_array[0]['colors'][2]['r'] = $col3[0]; - $patch_array[0]['colors'][2]['g'] = $col3[1]; - $patch_array[0]['colors'][2]['b'] = $col3[2]; - $patch_array[0]['colors'][3]['r'] = $col4[0]; - $patch_array[0]['colors'][3]['g'] = $col4[1]; - $patch_array[0]['colors'][3]['b'] = $col4[2]; - } else { - //multi patch array - $patch_array = $coords; - } - $bpcd = 65535; //16 bits per coordinate - //build the data stream - $this->gradients[$n]['stream'] = ''; - $count_patch = count($patch_array); - for ($i=0; $i < $count_patch; ++$i) { - $this->gradients[$n]['stream'] .= chr($patch_array[$i]['f']); //start with the edge flag as 8 bit - $count_points = count($patch_array[$i]['points']); - for ($j=0; $j < $count_points; ++$j) { - //each point as 16 bit - $patch_array[$i]['points'][$j] = (($patch_array[$i]['points'][$j] - $coords_min) / ($coords_max - $coords_min)) * $bpcd; - if ($patch_array[$i]['points'][$j] < 0) { - $patch_array[$i]['points'][$j] = 0; - } - if ($patch_array[$i]['points'][$j] > $bpcd) { - $patch_array[$i]['points'][$j] = $bpcd; - } - $this->gradients[$n]['stream'] .= chr((int) floor($patch_array[$i]['points'][$j] / 256)); - $this->gradients[$n]['stream'] .= chr((int) floor(intval($patch_array[$i]['points'][$j]) % 256)); - } - $count_cols = count($patch_array[$i]['colors']); - for ($j=0; $j < $count_cols; ++$j) { - //each color component as 8 bit - $this->gradients[$n]['stream'] .= chr($patch_array[$i]['colors'][$j]['r']); - $this->gradients[$n]['stream'] .= chr($patch_array[$i]['colors'][$j]['g']); - $this->gradients[$n]['stream'] .= chr($patch_array[$i]['colors'][$j]['b']); - } - } - //paint the gradient - $this->_out('/Sh'.$n.' sh'); - //restore previous Graphic State - $this->_outRestoreGraphicsState(); - if ($this->inxobj) { - // we are inside an XObject template - $this->xobjects[$this->xobjid]['gradients'][$n] = $this->gradients[$n]; - } - } - - /** - * Set a rectangular clipping area. - * @param float $x abscissa of the top left corner of the rectangle (or top right corner for RTL mode). - * @param float $y ordinate of the top left corner of the rectangle. - * @param float $w width of the rectangle. - * @param float $h height of the rectangle. - * @author Andreas W\FCrmser, Nicola Asuni - * @since 3.1.000 (2008-06-09) - * @protected - */ - protected function Clip($x, $y, $w, $h) { - if ($this->state != 2) { - return; - } - if ($this->rtl) { - $x = $this->w - $x - $w; - } - //save current Graphic State - $s = 'q'; - //set clipping area - $s .= sprintf(' %F %F %F %F re W n', $x*$this->k, ($this->h-$y)*$this->k, $w*$this->k, -$h*$this->k); - //set up transformation matrix for gradient - $s .= sprintf(' %F 0 0 %F %F %F cm', $w*$this->k, $h*$this->k, $x*$this->k, ($this->h-($y+$h))*$this->k); - $this->_out($s); - } - - /** - * Output gradient. - * @param int $type type of gradient (1 Function-based shading; 2 Axial shading; 3 Radial shading; 4 Free-form Gouraud-shaded triangle mesh; 5 Lattice-form Gouraud-shaded triangle mesh; 6 Coons patch mesh; 7 Tensor-product patch mesh). (Not all types are currently supported) - * @param array $coords array of coordinates. - * @param array $stops array gradient color components: color = array of GRAY, RGB or CMYK color components; offset = (0 to 1) represents a location along the gradient vector; exponent = exponent of the exponential interpolation function (default = 1). - * @param array $background An array of colour components appropriate to the colour space, specifying a single background colour value. - * @param boolean $antialias A flag indicating whether to filter the shading function to prevent aliasing artifacts. - * @author Nicola Asuni - * @since 3.1.000 (2008-06-09) - * @public - */ - public function Gradient($type, $coords, $stops, $background=array(), $antialias=false) { - if (($this->pdfa_mode && $this->pdfa_version < 2) OR ($this->state != 2)) { - return; - } - $n = count($this->gradients) + 1; - $this->gradients[$n] = array(); - $this->gradients[$n]['type'] = $type; - $this->gradients[$n]['coords'] = $coords; - $this->gradients[$n]['antialias'] = $antialias; - $this->gradients[$n]['colors'] = array(); - $this->gradients[$n]['transparency'] = false; - // color space - $numcolspace = count($stops[0]['color']); - $bcolor = array_values($background); - switch($numcolspace) { - case 5: // SPOT - case 4: { // CMYK - $this->gradients[$n]['colspace'] = 'DeviceCMYK'; - if (!empty($background)) { - $this->gradients[$n]['background'] = sprintf('%F %F %F %F', $bcolor[0]/100, $bcolor[1]/100, $bcolor[2]/100, $bcolor[3]/100); - } - break; - } - case 3: { // RGB - $this->gradients[$n]['colspace'] = 'DeviceRGB'; - if (!empty($background)) { - $this->gradients[$n]['background'] = sprintf('%F %F %F', $bcolor[0]/255, $bcolor[1]/255, $bcolor[2]/255); - } - break; - } - case 1: { // GRAY SCALE - $this->gradients[$n]['colspace'] = 'DeviceGray'; - if (!empty($background)) { - $this->gradients[$n]['background'] = sprintf('%F', $bcolor[0]/255); - } - break; - } - } - $num_stops = count($stops); - $last_stop_id = $num_stops - 1; - foreach ($stops as $key => $stop) { - $this->gradients[$n]['colors'][$key] = array(); - // offset represents a location along the gradient vector - if (isset($stop['offset'])) { - $this->gradients[$n]['colors'][$key]['offset'] = $stop['offset']; - } else { - if ($key == 0) { - $this->gradients[$n]['colors'][$key]['offset'] = 0; - } elseif ($key == $last_stop_id) { - $this->gradients[$n]['colors'][$key]['offset'] = 1; - } else { - $offsetstep = (1 - $this->gradients[$n]['colors'][($key - 1)]['offset']) / ($num_stops - $key); - $this->gradients[$n]['colors'][$key]['offset'] = $this->gradients[$n]['colors'][($key - 1)]['offset'] + $offsetstep; - } - } - if (isset($stop['opacity'])) { - $this->gradients[$n]['colors'][$key]['opacity'] = $stop['opacity']; - if ((!($this->pdfa_mode && $this->pdfa_version < 2)) AND ($stop['opacity'] < 1)) { - $this->gradients[$n]['transparency'] = true; - } - } else { - $this->gradients[$n]['colors'][$key]['opacity'] = 1; - } - // exponent for the exponential interpolation function - if (isset($stop['exponent'])) { - $this->gradients[$n]['colors'][$key]['exponent'] = $stop['exponent']; - } else { - $this->gradients[$n]['colors'][$key]['exponent'] = 1; - } - // set colors - $color = array_values($stop['color']); - switch($numcolspace) { - case 5: // SPOT - case 4: { // CMYK - $this->gradients[$n]['colors'][$key]['color'] = sprintf('%F %F %F %F', $color[0]/100, $color[1]/100, $color[2]/100, $color[3]/100); - break; - } - case 3: { // RGB - $this->gradients[$n]['colors'][$key]['color'] = sprintf('%F %F %F', $color[0]/255, $color[1]/255, $color[2]/255); - break; - } - case 1: { // GRAY SCALE - $this->gradients[$n]['colors'][$key]['color'] = sprintf('%F', $color[0]/255); - break; - } - } - } - if ($this->gradients[$n]['transparency']) { - // paint luminosity gradient - $this->_out('/TGS'.$n.' gs'); - } - //paint the gradient - $this->_out('/Sh'.$n.' sh'); - //restore previous Graphic State - $this->_outRestoreGraphicsState(); - if ($this->inxobj) { - // we are inside an XObject template - $this->xobjects[$this->xobjid]['gradients'][$n] = $this->gradients[$n]; - } - } - - /** - * Output gradient shaders. - * @author Nicola Asuni - * @since 3.1.000 (2008-06-09) - * @protected - */ - function _putshaders() { - if ($this->pdfa_mode && $this->pdfa_version < 2) { - return; - } - $idt = count($this->gradients); //index for transparency gradients - foreach ($this->gradients as $id => $grad) { - if (($grad['type'] == 2) OR ($grad['type'] == 3)) { - $fc = $this->_newobj(); - $out = '<<'; - $out .= ' /FunctionType 3'; - $out .= ' /Domain [0 1]'; - $functions = ''; - $bounds = ''; - $encode = ''; - $i = 1; - $num_cols = count($grad['colors']); - $lastcols = $num_cols - 1; - for ($i = 1; $i < $num_cols; ++$i) { - $functions .= ($fc + $i).' 0 R '; - if ($i < $lastcols) { - $bounds .= sprintf('%F ', $grad['colors'][$i]['offset']); - } - $encode .= '0 1 '; - } - $out .= ' /Functions ['.trim($functions).']'; - $out .= ' /Bounds ['.trim($bounds).']'; - $out .= ' /Encode ['.trim($encode).']'; - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - for ($i = 1; $i < $num_cols; ++$i) { - $this->_newobj(); - $out = '<<'; - $out .= ' /FunctionType 2'; - $out .= ' /Domain [0 1]'; - $out .= ' /C0 ['.$grad['colors'][($i - 1)]['color'].']'; - $out .= ' /C1 ['.$grad['colors'][$i]['color'].']'; - $out .= ' /N '.$grad['colors'][$i]['exponent']; - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - } - // set transparency functions - if ($grad['transparency']) { - $ft = $this->_newobj(); - $out = '<<'; - $out .= ' /FunctionType 3'; - $out .= ' /Domain [0 1]'; - $functions = ''; - $i = 1; - $num_cols = count($grad['colors']); - for ($i = 1; $i < $num_cols; ++$i) { - $functions .= ($ft + $i).' 0 R '; - } - $out .= ' /Functions ['.trim($functions).']'; - $out .= ' /Bounds ['.trim($bounds).']'; - $out .= ' /Encode ['.trim($encode).']'; - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - for ($i = 1; $i < $num_cols; ++$i) { - $this->_newobj(); - $out = '<<'; - $out .= ' /FunctionType 2'; - $out .= ' /Domain [0 1]'; - $out .= ' /C0 ['.$grad['colors'][($i - 1)]['opacity'].']'; - $out .= ' /C1 ['.$grad['colors'][$i]['opacity'].']'; - $out .= ' /N '.$grad['colors'][$i]['exponent']; - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - } - } - } - // set shading object - $this->_newobj(); - $out = '<< /ShadingType '.$grad['type']; - if (isset($grad['colspace'])) { - $out .= ' /ColorSpace /'.$grad['colspace']; - } else { - $out .= ' /ColorSpace /DeviceRGB'; - } - if (isset($grad['background']) AND !empty($grad['background'])) { - $out .= ' /Background ['.$grad['background'].']'; - } - if (isset($grad['antialias']) AND ($grad['antialias'] === true)) { - $out .= ' /AntiAlias true'; - } - if ($grad['type'] == 2) { - $out .= ' '.sprintf('/Coords [%F %F %F %F]', $grad['coords'][0], $grad['coords'][1], $grad['coords'][2], $grad['coords'][3]); - $out .= ' /Domain [0 1]'; - $out .= ' /Function '.$fc.' 0 R'; - $out .= ' /Extend [true true]'; - $out .= ' >>'; - } elseif ($grad['type'] == 3) { - //x0, y0, r0, x1, y1, r1 - //at this this time radius of inner circle is 0 - $out .= ' '.sprintf('/Coords [%F %F 0 %F %F %F]', $grad['coords'][0], $grad['coords'][1], $grad['coords'][2], $grad['coords'][3], $grad['coords'][4]); - $out .= ' /Domain [0 1]'; - $out .= ' /Function '.$fc.' 0 R'; - $out .= ' /Extend [true true]'; - $out .= ' >>'; - } elseif ($grad['type'] == 6) { - $out .= ' /BitsPerCoordinate 16'; - $out .= ' /BitsPerComponent 8'; - $out .= ' /Decode[0 1 0 1 0 1 0 1 0 1]'; - $out .= ' /BitsPerFlag 8'; - $stream = $this->_getrawstream($grad['stream']); - $out .= ' /Length '.strlen($stream); - $out .= ' >>'; - $out .= ' stream'."\n".$stream."\n".'endstream'; - } - $out .= "\n".'endobj'; - $this->_out($out); - if ($grad['transparency']) { - $shading_transparency = preg_replace('/\/ColorSpace \/[^\s]+/si', '/ColorSpace /DeviceGray', $out); - $shading_transparency = preg_replace('/\/Function [0-9]+ /si', '/Function '.$ft.' ', $shading_transparency); - } - $this->gradients[$id]['id'] = $this->n; - // set pattern object - $this->_newobj(); - $out = '<< /Type /Pattern /PatternType 2'; - $out .= ' /Shading '.$this->gradients[$id]['id'].' 0 R'; - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - $this->gradients[$id]['pattern'] = $this->n; - // set shading and pattern for transparency mask - if ($grad['transparency']) { - // luminosity pattern - $idgs = $id + $idt; - $this->_newobj(); - $this->_out($shading_transparency); - $this->gradients[$idgs]['id'] = $this->n; - $this->_newobj(); - $out = '<< /Type /Pattern /PatternType 2'; - $out .= ' /Shading '.$this->gradients[$idgs]['id'].' 0 R'; - $out .= ' >>'; - $out .= "\n".'endobj'; - $this->_out($out); - $this->gradients[$idgs]['pattern'] = $this->n; - // luminosity XObject - $oid = $this->_newobj(); - $this->xobjects['LX'.$oid] = array('n' => $oid); - $filter = ''; - $stream = 'q /a0 gs /Pattern cs /p'.$idgs.' scn 0 0 '.$this->wPt.' '.$this->hPt.' re f Q'; - if ($this->compress) { - $filter = ' /Filter /FlateDecode'; - $stream = gzcompress($stream); - } - $stream = $this->_getrawstream($stream); - $out = '<< /Type /XObject /Subtype /Form /FormType 1'.$filter; - $out .= ' /Length '.strlen($stream); - $rect = sprintf('%F %F', $this->wPt, $this->hPt); - $out .= ' /BBox [0 0 '.$rect.']'; - $out .= ' /Group << /Type /Group /S /Transparency /CS /DeviceGray >>'; - $out .= ' /Resources <<'; - $out .= ' /ExtGState << /a0 << /ca 1 /CA 1 >> >>'; - $out .= ' /Pattern << /p'.$idgs.' '.$this->gradients[$idgs]['pattern'].' 0 R >>'; - $out .= ' >>'; - $out .= ' >> '; - $out .= ' stream'."\n".$stream."\n".'endstream'; - $out .= "\n".'endobj'; - $this->_out($out); - // SMask - $this->_newobj(); - $out = '<< /Type /Mask /S /Luminosity /G '.($this->n - 1).' 0 R >>'."\n".'endobj'; - $this->_out($out); - // ExtGState - $this->_newobj(); - $out = '<< /Type /ExtGState /SMask '.($this->n - 1).' 0 R /AIS false >>'."\n".'endobj'; - $this->_out($out); - $this->extgstates[] = array('n' => $this->n, 'name' => 'TGS'.$id); - } - } - } - - /** - * Draw the sector of a circle. - * It can be used for instance to render pie charts. - * @param float $xc abscissa of the center. - * @param float $yc ordinate of the center. - * @param float $r radius. - * @param float $a start angle (in degrees). - * @param float $b end angle (in degrees). - * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. - * @param float $cw indicates whether to go clockwise (default: true). - * @param float $o origin of angles (0 for 3 o'clock, 90 for noon, 180 for 9 o'clock, 270 for 6 o'clock). Default: 90. - * @author Maxime Delorme, Nicola Asuni - * @since 3.1.000 (2008-06-09) - * @public - */ - public function PieSector($xc, $yc, $r, $a, $b, $style='FD', $cw=true, $o=90) { - $this->PieSectorXY($xc, $yc, $r, $r, $a, $b, $style, $cw, $o); - } - - /** - * Draw the sector of an ellipse. - * It can be used for instance to render pie charts. - * @param float $xc abscissa of the center. - * @param float $yc ordinate of the center. - * @param float $rx the x-axis radius. - * @param float $ry the y-axis radius. - * @param float $a start angle (in degrees). - * @param float $b end angle (in degrees). - * @param string $style Style of rendering. See the getPathPaintOperator() function for more information. - * @param float $cw indicates whether to go clockwise. - * @param float $o origin of angles (0 for 3 o'clock, 90 for noon, 180 for 9 o'clock, 270 for 6 o'clock). - * @param integer $nc Number of curves used to draw a 90 degrees portion of arc. - * @author Maxime Delorme, Nicola Asuni - * @since 3.1.000 (2008-06-09) - * @public - */ - public function PieSectorXY($xc, $yc, $rx, $ry, $a, $b, $style='FD', $cw=false, $o=0, $nc=2) { - if ($this->state != 2) { - return; - } - if ($this->rtl) { - $xc = ($this->w - $xc); - } - $op = TCPDF_STATIC::getPathPaintOperator($style); - if ($op == 'f') { - $line_style = array(); - } - if ($cw) { - $d = $b; - $b = (360 - $a + $o); - $a = (360 - $d + $o); - } else { - $b += $o; - $a += $o; - } - $this->_outellipticalarc($xc, $yc, $rx, $ry, 0, $a, $b, true, $nc); - $this->_out($op); - } - - /** - * Embed vector-based Adobe Illustrator (AI) or AI-compatible EPS files. - * NOTE: EPS is not yet fully implemented, use the setRasterizeVectorImages() method to enable/disable rasterization of vector images using ImageMagick library. - * Only vector drawing is supported, not text or bitmap. - * Although the script was successfully tested with various AI format versions, best results are probably achieved with files that were exported in the AI3 format (tested with Illustrator CS2, Freehand MX and Photoshop CS2). - * @param string $file Name of the file containing the image or a '@' character followed by the EPS/AI data string. - * @param float|null $x Abscissa of the upper-left corner. - * @param float|null $y Ordinate of the upper-left corner. - * @param float $w Width of the image in the page. If not specified or equal to zero, it is automatically calculated. - * @param float $h Height of the image in the page. If not specified or equal to zero, it is automatically calculated. - * @param mixed $link URL or identifier returned by AddLink(). - * @param boolean $useBoundingBox specifies whether to position the bounding box (true) or the complete canvas (false) at location (x,y). Default value is true. - * @param string $align Indicates the alignment of the pointer next to image insertion relative to image height. The value can be:<ul><li>T: top-right for LTR or top-left for RTL</li><li>M: middle-right for LTR or middle-left for RTL</li><li>B: bottom-right for LTR or bottom-left for RTL</li><li>N: next line</li></ul> - * @param string $palign Allows to center or align the image on the current line. Possible values are:<ul><li>L : left align</li><li>C : center</li><li>R : right align</li><li>'' : empty string : left for LTR or right for RTL</li></ul> - * @param mixed $border Indicates if borders must be drawn around the cell. The value can be a number:<ul><li>0: no border (default)</li><li>1: frame</li></ul> or a string containing some or all of the following characters (in any order):<ul><li>L: left</li><li>T: top</li><li>R: right</li><li>B: bottom</li></ul> or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - * @param boolean $fitonpage if true the image is resized to not exceed page dimensions. - * @param boolean $fixoutvals if true remove values outside the bounding box. - * @author Valentin Schmidt, Nicola Asuni - * @since 3.1.000 (2008-06-09) - * @public - */ - public function ImageEps($file, $x=null, $y=null, $w=0, $h=0, $link='', $useBoundingBox=true, $align='', $palign='', $border=0, $fitonpage=false, $fixoutvals=false) { - if ($this->state != 2) { - return; - } - if ($this->rasterize_vector_images AND ($w > 0) AND ($h > 0)) { - // convert EPS to raster image using GD or ImageMagick libraries - return $this->Image($file, $x, $y, $w, $h, 'EPS', $link, $align, true, 300, $palign, false, false, $border, false, false, $fitonpage); - } - if (TCPDF_STATIC::empty_string($x)) { - $x = $this->x; - } - if (TCPDF_STATIC::empty_string($y)) { - $y = $this->y; - } - // check page for no-write regions and adapt page margins if necessary - list($x, $y) = $this->checkPageRegions($h, $x, $y); - $k = $this->k; - if ($file[0] === '@') { // image from string - $data = substr($file, 1); - } else { // EPS/AI file - $data = $this->getCachedFileContents($file); - } - if ($data === FALSE) { - $this->Error('EPS file not found: '.$file); - } - $regs = array(); - // EPS/AI compatibility check (only checks files created by Adobe Illustrator!) - preg_match("/%%Creator:([^\r\n]+)/", $data, $regs); # find Creator - if (count($regs) > 1) { - $version_str = trim($regs[1]); # e.g. "Adobe Illustrator(R) 8.0" - if (strpos($version_str, 'Adobe Illustrator') !== false) { - $versexp = explode(' ', $version_str); - $version = (float)array_pop($versexp); - if ($version >= 9) { - $this->Error('This version of Adobe Illustrator file is not supported: '.$file); - } - } - } - // strip binary bytes in front of PS-header - $start = strpos($data, '%!PS-Adobe'); - if ($start > 0) { - $data = substr($data, $start); - } - // find BoundingBox params - preg_match("/%%BoundingBox:([^\r\n]+)/", $data, $regs); - if (count($regs) > 1) { - list($x1, $y1, $x2, $y2) = explode(' ', trim($regs[1])); - } else { - $this->Error('No BoundingBox found in EPS/AI file: '.$file); - } - $start = strpos($data, '%%EndSetup'); - if ($start === false) { - $start = strpos($data, '%%EndProlog'); - } - if ($start === false) { - $start = strpos($data, '%%BoundingBox'); - } - $data = substr($data, $start); - $end = strpos($data, '%%PageTrailer'); - if ($end===false) { - $end = strpos($data, 'showpage'); - } - if ($end) { - $data = substr($data, 0, $end); - } - // calculate image width and height on document - if (($w <= 0) AND ($h <= 0)) { - $w = ($x2 - $x1) / $k; - $h = ($y2 - $y1) / $k; - } elseif ($w <= 0) { - $w = ($x2-$x1) / $k * ($h / (($y2 - $y1) / $k)); - } elseif ($h <= 0) { - $h = ($y2 - $y1) / $k * ($w / (($x2 - $x1) / $k)); - } - // fit the image on available space - list($w, $h, $x, $y) = $this->fitBlock($w, $h, $x, $y, $fitonpage); - if ($this->rasterize_vector_images) { - // convert EPS to raster image using GD or ImageMagick libraries - return $this->Image($file, $x, $y, $w, $h, 'EPS', $link, $align, true, 300, $palign, false, false, $border, false, false, $fitonpage); - } - // set scaling factors - $scale_x = $w / (($x2 - $x1) / $k); - $scale_y = $h / (($y2 - $y1) / $k); - // set alignment - $this->img_rb_y = $y + $h; - // set alignment - if ($this->rtl) { - if ($palign == 'L') { - $ximg = $this->lMargin; - } elseif ($palign == 'C') { - $ximg = ($this->w + $this->lMargin - $this->rMargin - $w) / 2; - } elseif ($palign == 'R') { - $ximg = $this->w - $this->rMargin - $w; - } else { - $ximg = $x - $w; - } - $this->img_rb_x = $ximg; - } else { - if ($palign == 'L') { - $ximg = $this->lMargin; - } elseif ($palign == 'C') { - $ximg = ($this->w + $this->lMargin - $this->rMargin - $w) / 2; - } elseif ($palign == 'R') { - $ximg = $this->w - $this->rMargin - $w; - } else { - $ximg = $x; - } - $this->img_rb_x = $ximg + $w; - } - if ($useBoundingBox) { - $dx = $ximg * $k - $x1; - $dy = $y * $k - $y1; - } else { - $dx = $ximg * $k; - $dy = $y * $k; - } - // save the current graphic state - $this->_out('q'.$this->epsmarker); - // translate - $this->_out(sprintf('%F %F %F %F %F %F cm', 1, 0, 0, 1, $dx, $dy + ($this->hPt - (2 * $y * $k) - ($y2 - $y1)))); - // scale - if (isset($scale_x)) { - $this->_out(sprintf('%F %F %F %F %F %F cm', $scale_x, 0, 0, $scale_y, $x1 * (1 - $scale_x), $y2 * (1 - $scale_y))); - } - // handle pc/unix/mac line endings - $lines = preg_split('/[\r\n]+/si', $data, -1, PREG_SPLIT_NO_EMPTY); - $u=0; - $cnt = count($lines); - for ($i=0; $i < $cnt; ++$i) { - $line = $lines[$i]; - if (($line == '') OR ($line[0] == '%')) { - continue; - } - $len = strlen($line); - // check for spot color names - $color_name = ''; - if (strcasecmp('x', substr(trim($line), -1)) == 0) { - if (preg_match('/\([^\)]*\)/', $line, $matches) > 0) { - // extract spot color name - $color_name = $matches[0]; - // remove color name from string - $line = str_replace(' '.$color_name, '', $line); - // remove pharentesis from color name - $color_name = substr($color_name, 1, -1); - } - } - $chunks = explode(' ', $line); - $cmd = trim(array_pop($chunks)); - // RGB - if (($cmd == 'Xa') OR ($cmd == 'XA')) { - $b = array_pop($chunks); - $g = array_pop($chunks); - $r = array_pop($chunks); - $this->_out(''.$r.' '.$g.' '.$b.' '.($cmd=='Xa'?'rg':'RG')); //substr($line, 0, -2).'rg' -> in EPS (AI8): c m y k r g b rg! - continue; - } - $skip = false; - if ($fixoutvals) { - // check for values outside the bounding box - switch ($cmd) { - case 'm': - case 'l': - case 'L': { - // skip values outside bounding box - foreach ($chunks as $key => $val) { - if ((($key % 2) == 0) AND (($val < $x1) OR ($val > $x2))) { - $skip = true; - } elseif ((($key % 2) != 0) AND (($val < $y1) OR ($val > $y2))) { - $skip = true; - } - } - } - } - } - switch ($cmd) { - case 'm': - case 'l': - case 'v': - case 'y': - case 'c': - case 'k': - case 'K': - case 'g': - case 'G': - case 's': - case 'S': - case 'J': - case 'j': - case 'w': - case 'M': - case 'd': - case 'n': { - if ($skip) { - break; - } - $this->_out($line); - break; - } - case 'x': {// custom fill color - if (empty($color_name)) { - // CMYK color - list($col_c, $col_m, $col_y, $col_k) = $chunks; - $this->_out(''.$col_c.' '.$col_m.' '.$col_y.' '.$col_k.' k'); - } else { - // Spot Color (CMYK + tint) - list($col_c, $col_m, $col_y, $col_k, $col_t) = $chunks; - $this->AddSpotColor($color_name, ($col_c * 100), ($col_m * 100), ($col_y * 100), ($col_k * 100)); - $color_cmd = sprintf('/CS%d cs %F scn', $this->spot_colors[$color_name]['i'], (1 - $col_t)); - $this->_out($color_cmd); - } - break; - } - case 'X': { // custom stroke color - if (empty($color_name)) { - // CMYK color - list($col_c, $col_m, $col_y, $col_k) = $chunks; - $this->_out(''.$col_c.' '.$col_m.' '.$col_y.' '.$col_k.' K'); - } else { - // Spot Color (CMYK + tint) - list($col_c, $col_m, $col_y, $col_k, $col_t) = $chunks; - $this->AddSpotColor($color_name, ($col_c * 100), ($col_m * 100), ($col_y * 100), ($col_k * 100)); - $color_cmd = sprintf('/CS%d CS %F SCN', $this->spot_colors[$color_name]['i'], (1 - $col_t)); - $this->_out($color_cmd); - } - break; - } - case 'Y': - case 'N': - case 'V': - case 'L': - case 'C': { - if ($skip) { - break; - } - $line[($len - 1)] = strtolower($cmd); - $this->_out($line); - break; - } - case 'b': - case 'B': { - $this->_out($cmd . '*'); - break; - } - case 'f': - case 'F': { - if ($u > 0) { - $isU = false; - $max = min(($i + 5), $cnt); - for ($j = ($i + 1); $j < $max; ++$j) { - $isU = ($isU OR (($lines[$j] == 'U') OR ($lines[$j] == '*U'))); - } - if ($isU) { - $this->_out('f*'); - } - } else { - $this->_out('f*'); - } - break; - } - case '*u': { - ++$u; - break; - } - case '*U': { - --$u; - break; - } - } - } - // restore previous graphic state - $this->_out($this->epsmarker.'Q'); - if (!empty($border)) { - $bx = $this->x; - $by = $this->y; - $this->x = $ximg; - if ($this->rtl) { - $this->x += $w; - } - $this->y = $y; - $this->Cell($w, $h, '', $border, 0, '', 0, '', 0, true); - $this->x = $bx; - $this->y = $by; - } - if ($link) { - $this->Link($ximg, $y, $w, $h, $link, 0); - } - // set pointer to align the next text/objects - switch($align) { - case 'T':{ - $this->y = $y; - $this->x = $this->img_rb_x; - break; - } - case 'M':{ - $this->y = $y + round($h/2); - $this->x = $this->img_rb_x; - break; - } - case 'B':{ - $this->y = $this->img_rb_y; - $this->x = $this->img_rb_x; - break; - } - case 'N':{ - $this->setY($this->img_rb_y); - break; - } - default:{ - break; - } - } - $this->endlinex = $this->img_rb_x; - } - - /** - * Set document barcode. - * @param string $bc barcode - * @public - */ - public function setBarcode($bc='') { - $this->barcode = $bc; - } - - /** - * Get current barcode. - * @return string - * @public - * @since 4.0.012 (2008-07-24) - */ - public function getBarcode() { - return $this->barcode; - } - - /** - * Print a Linear Barcode. - * @param string $code code to print - * @param string $type type of barcode (see tcpdf_barcodes_1d.php for supported formats). - * @param float|null $x x position in user units (null = current x position) - * @param float|null $y y position in user units (null = current y position) - * @param float|null $w width in user units (null = remaining page width) - * @param float|null $h height in user units (null = remaining page height) - * @param float|null $xres width of the smallest bar in user units (null = default value = 0.4mm) - * @param array $style array of options:<ul> - * <li>boolean $style['border'] if true prints a border</li> - * <li>int $style['padding'] padding to leave around the barcode in user units (set to 'auto' for automatic padding)</li> - * <li>int $style['hpadding'] horizontal padding in user units (set to 'auto' for automatic padding)</li> - * <li>int $style['vpadding'] vertical padding in user units (set to 'auto' for automatic padding)</li> - * <li>array $style['fgcolor'] color array for bars and text</li> - * <li>mixed $style['bgcolor'] color array for background (set to false for transparent)</li> - * <li>boolean $style['text'] if true prints text below the barcode</li> - * <li>string $style['label'] override default label</li> - * <li>string $style['font'] font name for text</li><li>int $style['fontsize'] font size for text</li> - * <li>int $style['stretchtext']: 0 = disabled; 1 = horizontal scaling only if necessary; 2 = forced horizontal scaling; 3 = character spacing only if necessary; 4 = forced character spacing.</li> - * <li>string $style['position'] horizontal position of the containing barcode cell on the page: L = left margin; C = center; R = right margin.</li> - * <li>string $style['align'] horizontal position of the barcode on the containing rectangle: L = left; C = center; R = right.</li> - * <li>string $style['stretch'] if true stretch the barcode to best fit the available width, otherwise uses $xres resolution for a single bar.</li> - * <li>string $style['fitwidth'] if true reduce the width to fit the barcode width + padding. When this option is enabled the 'stretch' option is automatically disabled.</li> - * <li>string $style['cellfitalign'] this option works only when 'fitwidth' is true and 'position' is unset or empty. Set the horizontal position of the containing barcode cell inside the specified rectangle: L = left; C = center; R = right.</li></ul> - * @param string $align Indicates the alignment of the pointer next to barcode insertion relative to barcode height. The value can be:<ul><li>T: top-right for LTR or top-left for RTL</li><li>M: middle-right for LTR or middle-left for RTL</li><li>B: bottom-right for LTR or bottom-left for RTL</li><li>N: next line</li></ul> - * @author Nicola Asuni - * @since 3.1.000 (2008-06-09) - * @public - */ - public function write1DBarcode($code, $type, $x=null, $y=null, $w=null, $h=null, $xres=null, $style=array(), $align='') { - if (TCPDF_STATIC::empty_string(trim($code))) { - return; - } - require_once(dirname(__FILE__).'/tcpdf_barcodes_1d.php'); - // save current graphic settings - $gvars = $this->getGraphicVars(); - // create new barcode object - $barcodeobj = new TCPDFBarcode($code, $type); - $arrcode = $barcodeobj->getBarcodeArray(); - if (empty($arrcode) OR ($arrcode['maxw'] <= 0)) { - $this->Error('Error in 1D barcode string'); - } - if ($arrcode['maxh'] <= 0) { - $arrcode['maxh'] = 1; - } - // set default values - if (!isset($style['position'])) { - $style['position'] = ''; - } elseif ($style['position'] == 'S') { - // keep this for backward compatibility - $style['position'] = ''; - $style['stretch'] = true; - } - if (!isset($style['fitwidth'])) { - if (!isset($style['stretch'])) { - $style['fitwidth'] = true; - } else { - $style['fitwidth'] = false; - } - } - if ($style['fitwidth']) { - // disable stretch - $style['stretch'] = false; - } - if (!isset($style['stretch'])) { - if (($w === '') OR ($w <= 0)) { - $style['stretch'] = false; - } else { - $style['stretch'] = true; - } - } - if (!isset($style['fgcolor'])) { - $style['fgcolor'] = array(0,0,0); // default black - } - if (!isset($style['bgcolor'])) { - $style['bgcolor'] = false; // default transparent - } - if (!isset($style['border'])) { - $style['border'] = false; - } - $fontsize = 0; - if (!isset($style['text'])) { - $style['text'] = false; - } - if ($style['text'] AND isset($style['font'])) { - if (isset($style['fontsize'])) { - $fontsize = $style['fontsize']; - } - $this->setFont($style['font'], '', $fontsize); - } - if (!isset($style['stretchtext'])) { - $style['stretchtext'] = 4; - } - if (TCPDF_STATIC::empty_string($x)) { - $x = $this->x; - } - if (TCPDF_STATIC::empty_string($y)) { - $y = $this->y; - } - // check page for no-write regions and adapt page margins if necessary - list($x, $y) = $this->checkPageRegions($h, $x, $y); - if (TCPDF_STATIC::empty_string($w) OR ($w <= 0)) { - if ($this->rtl) { - $w = $x - $this->lMargin; - } else { - $w = $this->w - $this->rMargin - $x; - } - } - // padding - if (!isset($style['padding'])) { - $padding = 0; - } elseif ($style['padding'] === 'auto') { - $padding = 10 * ($w / ($arrcode['maxw'] + 20)); - } else { - $padding = floatval($style['padding']); - } - // horizontal padding - if (!isset($style['hpadding'])) { - $hpadding = $padding; - } elseif ($style['hpadding'] === 'auto') { - $hpadding = 10 * ($w / ($arrcode['maxw'] + 20)); - } else { - $hpadding = floatval($style['hpadding']); - } - // vertical padding - if (!isset($style['vpadding'])) { - $vpadding = $padding; - } elseif ($style['vpadding'] === 'auto') { - $vpadding = ($hpadding / 2); - } else { - $vpadding = floatval($style['vpadding']); - } - // calculate xres (single bar width) - $max_xres = ($w - (2 * $hpadding)) / $arrcode['maxw']; - if ($style['stretch']) { - $xres = $max_xres; - } else { - if (TCPDF_STATIC::empty_string($xres)) { - $xres = (0.141 * $this->k); // default bar width = 0.4 mm - } - if ($xres > $max_xres) { - // correct xres to fit on $w - $xres = $max_xres; - } - if ((isset($style['padding']) AND ($style['padding'] === 'auto')) - OR (isset($style['hpadding']) AND ($style['hpadding'] === 'auto'))) { - $hpadding = 10 * $xres; - if (isset($style['vpadding']) AND ($style['vpadding'] === 'auto')) { - $vpadding = ($hpadding / 2); - } - } - } - if ($style['fitwidth']) { - $wold = $w; - $w = (($arrcode['maxw'] * $xres) + (2 * $hpadding)); - if (isset($style['cellfitalign'])) { - switch ($style['cellfitalign']) { - case 'L': { - if ($this->rtl) { - $x -= ($wold - $w); - } - break; - } - case 'R': { - if (!$this->rtl) { - $x += ($wold - $w); - } - break; - } - case 'C': { - if ($this->rtl) { - $x -= (($wold - $w) / 2); - } else { - $x += (($wold - $w) / 2); - } - break; - } - default : { - break; - } - } - } - } - $text_height = $this->getCellHeight($fontsize / $this->k); - // height - if (TCPDF_STATIC::empty_string($h) OR ($h <= 0)) { - // set default height - $h = (($arrcode['maxw'] * $xres) / 3) + (2 * $vpadding) + $text_height; - } - $barh = $h - $text_height - (2 * $vpadding); - if ($barh <=0) { - // try to reduce font or padding to fit barcode on available height - if ($text_height > $h) { - $fontsize = (($h * $this->k) / (4 * $this->cell_height_ratio)); - $text_height = $this->getCellHeight($fontsize / $this->k); - $this->setFont($style['font'], '', $fontsize); - } - if ($vpadding > 0) { - $vpadding = (($h - $text_height) / 4); - } - $barh = $h - $text_height - (2 * $vpadding); - } - // fit the barcode on available space - list($w, $h, $x, $y) = $this->fitBlock($w, $h, $x, $y, false); - // set alignment - $this->img_rb_y = $y + $h; - // set alignment - if ($this->rtl) { - if ($style['position'] == 'L') { - $xpos = $this->lMargin; - } elseif ($style['position'] == 'C') { - $xpos = ($this->w + $this->lMargin - $this->rMargin - $w) / 2; - } elseif ($style['position'] == 'R') { - $xpos = $this->w - $this->rMargin - $w; - } else { - $xpos = $x - $w; - } - $this->img_rb_x = $xpos; - } else { - if ($style['position'] == 'L') { - $xpos = $this->lMargin; - } elseif ($style['position'] == 'C') { - $xpos = ($this->w + $this->lMargin - $this->rMargin - $w) / 2; - } elseif ($style['position'] == 'R') { - $xpos = $this->w - $this->rMargin - $w; - } else { - $xpos = $x; - } - $this->img_rb_x = $xpos + $w; - } - $xpos_rect = $xpos; - if (!isset($style['align'])) { - $style['align'] = 'C'; - } - switch ($style['align']) { - case 'L': { - $xpos = $xpos_rect + $hpadding; - break; - } - case 'R': { - $xpos = $xpos_rect + ($w - ($arrcode['maxw'] * $xres)) - $hpadding; - break; - } - case 'C': - default : { - $xpos = $xpos_rect + (($w - ($arrcode['maxw'] * $xres)) / 2); - break; - } - } - $xpos_text = $xpos; - // barcode is always printed in LTR direction - $tempRTL = $this->rtl; - $this->rtl = false; - // print background color - if ($style['bgcolor']) { - $this->Rect($xpos_rect, $y, $w, $h, $style['border'] ? 'DF' : 'F', '', $style['bgcolor']); - } elseif ($style['border']) { - $this->Rect($xpos_rect, $y, $w, $h, 'D'); - } - // set foreground color - $this->setDrawColorArray($style['fgcolor']); - $this->setTextColorArray($style['fgcolor']); - // print bars - foreach ($arrcode['bcode'] as $k => $v) { - $bw = ($v['w'] * $xres); - if ($v['t']) { - // draw a vertical bar - $ypos = $y + $vpadding + ($v['p'] * $barh / $arrcode['maxh']); - $this->Rect($xpos, $ypos, $bw, ($v['h'] * $barh / $arrcode['maxh']), 'F', array(), $style['fgcolor']); - } - $xpos += $bw; - } - // print text - if ($style['text']) { - if (isset($style['label']) AND !TCPDF_STATIC::empty_string($style['label'])) { - $label = $style['label']; - } else { - $label = $code; - } - $txtwidth = ($arrcode['maxw'] * $xres); - if ($this->GetStringWidth($label) > $txtwidth) { - $style['stretchtext'] = 2; - } - // print text - $this->x = $xpos_text; - $this->y = $y + $vpadding + $barh; - $cellpadding = $this->cell_padding; - $this->setCellPadding(0); - $this->Cell($txtwidth, 0, $label, 0, 0, 'C', false, '', $style['stretchtext'], false, 'T', 'T'); - $this->cell_padding = $cellpadding; - } - // restore original direction - $this->rtl = $tempRTL; - // restore previous settings - $this->setGraphicVars($gvars); - // set pointer to align the next text/objects - switch($align) { - case 'T':{ - $this->y = $y; - $this->x = $this->img_rb_x; - break; - } - case 'M':{ - $this->y = $y + round($h / 2); - $this->x = $this->img_rb_x; - break; - } - case 'B':{ - $this->y = $this->img_rb_y; - $this->x = $this->img_rb_x; - break; - } - case 'N':{ - $this->setY($this->img_rb_y); - break; - } - default:{ - break; - } - } - $this->endlinex = $this->img_rb_x; - } - - /** - * Print 2D Barcode. - * @param string $code code to print - * @param string $type type of barcode (see tcpdf_barcodes_2d.php for supported formats). - * @param float|null $x x position in user units - * @param float|null $y y position in user units - * @param float|null $w width in user units - * @param float|null $h height in user units - * @param array $style array of options:<ul> - * <li>boolean $style['border'] if true prints a border around the barcode</li> - * <li>int $style['padding'] padding to leave around the barcode in barcode units (set to 'auto' for automatic padding)</li> - * <li>int $style['hpadding'] horizontal padding in barcode units (set to 'auto' for automatic padding)</li> - * <li>int $style['vpadding'] vertical padding in barcode units (set to 'auto' for automatic padding)</li> - * <li>int $style['module_width'] width of a single module in points</li> - * <li>int $style['module_height'] height of a single module in points</li> - * <li>array $style['fgcolor'] color array for bars and text</li> - * <li>mixed $style['bgcolor'] color array for background or false for transparent</li> - * <li>string $style['position'] barcode position on the page: L = left margin; C = center; R = right margin; S = stretch</li> - * @param string $align Indicates the alignment of the pointer next to barcode insertion relative to barcode height. The value can be:<ul><li>T: top-right for LTR or top-left for RTL</li><li>M: middle-right for LTR or middle-left for RTL</li><li>B: bottom-right for LTR or bottom-left for RTL</li><li>N: next line</li></ul> - * @param boolean $distort if true distort the barcode to fit width and height, otherwise preserve aspect ratio - * @author Nicola Asuni - * @since 4.5.037 (2009-04-07) - * @public - */ - public function write2DBarcode($code, $type, $x=null, $y=null, $w=null, $h=null, $style=array(), $align='', $distort=false) { - if (TCPDF_STATIC::empty_string(trim($code))) { - return; - } - require_once(dirname(__FILE__).'/tcpdf_barcodes_2d.php'); - // save current graphic settings - $gvars = $this->getGraphicVars(); - // create new barcode object - $barcodeobj = new TCPDF2DBarcode($code, $type); - $arrcode = $barcodeobj->getBarcodeArray(); - if (empty($arrcode) OR !isset($arrcode['num_rows']) OR ($arrcode['num_rows'] == 0) OR !isset($arrcode['num_cols']) OR ($arrcode['num_cols'] == 0)) { - $this->Error('Error in 2D barcode string'); - } - // set default values - if (!isset($style['position'])) { - $style['position'] = ''; - } - if (!isset($style['fgcolor'])) { - $style['fgcolor'] = array(0,0,0); // default black - } - if (!isset($style['bgcolor'])) { - $style['bgcolor'] = false; // default transparent - } - if (!isset($style['border'])) { - $style['border'] = false; - } - // padding - if (!isset($style['padding'])) { - $style['padding'] = 0; - } elseif ($style['padding'] === 'auto') { - $style['padding'] = 4; - } - if (!isset($style['hpadding'])) { - $style['hpadding'] = $style['padding']; - } elseif ($style['hpadding'] === 'auto') { - $style['hpadding'] = 4; - } - if (!isset($style['vpadding'])) { - $style['vpadding'] = $style['padding']; - } elseif ($style['vpadding'] === 'auto') { - $style['vpadding'] = 4; - } - $hpad = (2 * $style['hpadding']); - $vpad = (2 * $style['vpadding']); - // cell (module) dimension - if (!isset($style['module_width'])) { - $style['module_width'] = 1; // width of a single module in points - } - if (!isset($style['module_height'])) { - $style['module_height'] = 1; // height of a single module in points - } - if (TCPDF_STATIC::empty_string($x)) { - $x = $this->x; - } - if (TCPDF_STATIC::empty_string($y)) { - $y = $this->y; - } - // check page for no-write regions and adapt page margins if necessary - list($x, $y) = $this->checkPageRegions($h, $x, $y); - // number of barcode columns and rows - $rows = $arrcode['num_rows']; - $cols = $arrcode['num_cols']; - if (($rows <= 0) || ($cols <= 0)){ - $this->Error('Error in 2D barcode string'); - } - // module width and height - $mw = $style['module_width']; - $mh = $style['module_height']; - if (($mw <= 0) OR ($mh <= 0)) { - $this->Error('Error in 2D barcode string'); - } - // get max dimensions - if ($this->rtl) { - $maxw = $x - $this->lMargin; - } else { - $maxw = $this->w - $this->rMargin - $x; - } - $maxh = ($this->h - $this->tMargin - $this->bMargin); - $ratioHW = ((($rows * $mh) + $hpad) / (($cols * $mw) + $vpad)); - $ratioWH = ((($cols * $mw) + $vpad) / (($rows * $mh) + $hpad)); - if (!$distort) { - if (($maxw * $ratioHW) > $maxh) { - $maxw = $maxh * $ratioWH; - } - if (($maxh * $ratioWH) > $maxw) { - $maxh = $maxw * $ratioHW; - } - } - // set maximum dimensions - if ($w > $maxw) { - $w = $maxw; - } - if ($h > $maxh) { - $h = $maxh; - } - // set dimensions - if ((TCPDF_STATIC::empty_string($w) OR ($w <= 0)) AND (TCPDF_STATIC::empty_string($h) OR ($h <= 0))) { - $w = ($cols + $hpad) * ($mw / $this->k); - $h = ($rows + $vpad) * ($mh / $this->k); - } elseif (($w === '') OR ($w <= 0)) { - $w = $h * $ratioWH; - } elseif (($h === '') OR ($h <= 0)) { - $h = $w * $ratioHW; - } - // barcode size (excluding padding) - $bw = ($w * $cols) / ($cols + $hpad); - $bh = ($h * $rows) / ($rows + $vpad); - // dimension of single barcode cell unit - $cw = $bw / $cols; - $ch = $bh / $rows; - if (!$distort) { - if (($cw / $ch) > ($mw / $mh)) { - // correct horizontal distortion - $cw = $ch * $mw / $mh; - $bw = $cw * $cols; - $style['hpadding'] = ($w - $bw) / (2 * $cw); - } else { - // correct vertical distortion - $ch = $cw * $mh / $mw; - $bh = $ch * $rows; - $style['vpadding'] = ($h - $bh) / (2 * $ch); - } - } - // fit the barcode on available space - list($w, $h, $x, $y) = $this->fitBlock($w, $h, $x, $y, false); - // set alignment - $this->img_rb_y = $y + $h; - // set alignment - if ($this->rtl) { - if ($style['position'] == 'L') { - $xpos = $this->lMargin; - } elseif ($style['position'] == 'C') { - $xpos = ($this->w + $this->lMargin - $this->rMargin - $w) / 2; - } elseif ($style['position'] == 'R') { - $xpos = $this->w - $this->rMargin - $w; - } else { - $xpos = $x - $w; - } - $this->img_rb_x = $xpos; - } else { - if ($style['position'] == 'L') { - $xpos = $this->lMargin; - } elseif ($style['position'] == 'C') { - $xpos = ($this->w + $this->lMargin - $this->rMargin - $w) / 2; - } elseif ($style['position'] == 'R') { - $xpos = $this->w - $this->rMargin - $w; - } else { - $xpos = $x; - } - $this->img_rb_x = $xpos + $w; - } - $xstart = $xpos + ($style['hpadding'] * $cw); - $ystart = $y + ($style['vpadding'] * $ch); - // barcode is always printed in LTR direction - $tempRTL = $this->rtl; - $this->rtl = false; - // print background color - if ($style['bgcolor']) { - $this->Rect($xpos, $y, $w, $h, $style['border'] ? 'DF' : 'F', '', $style['bgcolor']); - } elseif ($style['border']) { - $this->Rect($xpos, $y, $w, $h, 'D'); - } - // set foreground color - $this->setDrawColorArray($style['fgcolor']); - // print barcode cells - // for each row - for ($r = 0; $r < $rows; ++$r) { - $xr = $xstart; - // for each column - for ($c = 0; $c < $cols; ++$c) { - if ($arrcode['bcode'][$r][$c] == 1) { - // draw a single barcode cell - $this->Rect($xr, $ystart, $cw, $ch, 'F', array(), $style['fgcolor']); - } - $xr += $cw; - } - $ystart += $ch; - } - // restore original direction - $this->rtl = $tempRTL; - // restore previous settings - $this->setGraphicVars($gvars); - // set pointer to align the next text/objects - switch($align) { - case 'T':{ - $this->y = $y; - $this->x = $this->img_rb_x; - break; - } - case 'M':{ - $this->y = $y + round($h/2); - $this->x = $this->img_rb_x; - break; - } - case 'B':{ - $this->y = $this->img_rb_y; - $this->x = $this->img_rb_x; - break; - } - case 'N':{ - $this->setY($this->img_rb_y); - break; - } - default:{ - break; - } - } - $this->endlinex = $this->img_rb_x; - } - - /** - * Returns an array containing current margins: - * <ul> - <li>$ret['left'] = left margin</li> - <li>$ret['right'] = right margin</li> - <li>$ret['top'] = top margin</li> - <li>$ret['bottom'] = bottom margin</li> - <li>$ret['header'] = header margin</li> - <li>$ret['footer'] = footer margin</li> - <li>$ret['cell'] = cell padding array</li> - <li>$ret['padding_left'] = cell left padding</li> - <li>$ret['padding_top'] = cell top padding</li> - <li>$ret['padding_right'] = cell right padding</li> - <li>$ret['padding_bottom'] = cell bottom padding</li> - * </ul> - * @return array containing all margins measures - * @public - * @since 3.2.000 (2008-06-23) - */ - public function getMargins() { - $ret = array( - 'left' => $this->lMargin, - 'right' => $this->rMargin, - 'top' => $this->tMargin, - 'bottom' => $this->bMargin, - 'header' => $this->header_margin, - 'footer' => $this->footer_margin, - 'cell' => $this->cell_padding, - 'padding_left' => $this->cell_padding['L'], - 'padding_top' => $this->cell_padding['T'], - 'padding_right' => $this->cell_padding['R'], - 'padding_bottom' => $this->cell_padding['B'] - ); - return $ret; - } - - /** - * Returns an array containing original margins: - * <ul> - <li>$ret['left'] = left margin</li> - <li>$ret['right'] = right margin</li> - * </ul> - * @return array containing all margins measures - * @public - * @since 4.0.012 (2008-07-24) - */ - public function getOriginalMargins() { - $ret = array( - 'left' => $this->original_lMargin, - 'right' => $this->original_rMargin - ); - return $ret; - } - - /** - * Returns the current font size. - * @return float current font size - * @public - * @since 3.2.000 (2008-06-23) - */ - public function getFontSize() { - return $this->FontSize; - } - - /** - * Returns the current font size in points unit. - * @return int current font size in points unit - * @public - * @since 3.2.000 (2008-06-23) - */ - public function getFontSizePt() { - return $this->FontSizePt; - } - - /** - * Returns the current font family name. - * @return string current font family name - * @public - * @since 4.3.008 (2008-12-05) - */ - public function getFontFamily() { - return $this->FontFamily; - } - - /** - * Returns the current font style. - * @return string current font style - * @public - * @since 4.3.008 (2008-12-05) - */ - public function getFontStyle() { - return $this->FontStyle; - } - - /** - * Cleanup HTML code (requires HTML Tidy library). - * @param string $html htmlcode to fix - * @param string $default_css CSS commands to add - * @param array|null $tagvs parameters for setHtmlVSpace method - * @param array|null $tidy_options options for tidy_parse_string function - * @return string XHTML code cleaned up - * @author Nicola Asuni - * @public - * @since 5.9.017 (2010-11-16) - * @see setHtmlVSpace() - */ - public function fixHTMLCode($html, $default_css='', $tagvs=null, $tidy_options=null) { - return TCPDF_STATIC::fixHTMLCode($html, $default_css, $tagvs, $tidy_options, $this->tagvspaces); - } - - /** - * Returns the border width from CSS property - * @param string $width border width - * @return int with in user units - * @protected - * @since 5.7.000 (2010-08-02) - */ - protected function getCSSBorderWidth($width) { - if ($width == 'thin') { - $width = (2 / $this->k); - } elseif ($width == 'medium') { - $width = (4 / $this->k); - } elseif ($width == 'thick') { - $width = (6 / $this->k); - } else { - $width = $this->getHTMLUnitToUnits($width, 1, 'px', false); - } - return $width; - } - - /** - * Returns the border dash style from CSS property - * @param string $style border style to convert - * @return int sash style (return -1 in case of none or hidden border) - * @protected - * @since 5.7.000 (2010-08-02) - */ - protected function getCSSBorderDashStyle($style) { - switch (strtolower($style)) { - case 'none': - case 'hidden': { - $dash = -1; - break; - } - case 'dotted': { - $dash = 1; - break; - } - case 'dashed': { - $dash = 3; - break; - } - case 'double': - case 'groove': - case 'ridge': - case 'inset': - case 'outset': - case 'solid': - default: { - $dash = 0; - break; - } - } - return $dash; - } - - /** - * Returns the border style array from CSS border properties - * @param string $cssborder border properties - * @return array containing border properties - * @protected - * @since 5.7.000 (2010-08-02) - */ - protected function getCSSBorderStyle($cssborder) { - $bprop = preg_split('/[\s]+/', trim($cssborder)); - $border = array(); // value to be returned - switch (count($bprop)) { - case 3: { - $width = $bprop[0]; - $style = $bprop[1]; - $color = $bprop[2]; - break; - } - case 2: { - $width = 'medium'; - $style = $bprop[0]; - $color = $bprop[1]; - break; - } - case 1: { - $width = 'medium'; - $style = $bprop[0]; - $color = 'black'; - break; - } - default: { - $width = 'medium'; - $style = 'solid'; - $color = 'black'; - break; - } - } - if ($style == 'none') { - return array(); - } - $border['cap'] = 'square'; - $border['join'] = 'miter'; - $border['dash'] = $this->getCSSBorderDashStyle($style); - if ($border['dash'] < 0) { - return array(); - } - $border['width'] = $this->getCSSBorderWidth($width); - $border['color'] = TCPDF_COLORS::convertHTMLColorToDec($color, $this->spot_colors); - return $border; - } - - /** - * Get the internal Cell padding from CSS attribute. - * @param string $csspadding padding properties - * @param float $width width of the containing element - * @return array of cell paddings - * @public - * @since 5.9.000 (2010-10-04) - */ - public function getCSSPadding($csspadding, $width=0) { - $padding = preg_split('/[\s]+/', trim($csspadding)); - $cell_padding = array(); // value to be returned - switch (count($padding)) { - case 4: { - $cell_padding['T'] = $padding[0]; - $cell_padding['R'] = $padding[1]; - $cell_padding['B'] = $padding[2]; - $cell_padding['L'] = $padding[3]; - break; - } - case 3: { - $cell_padding['T'] = $padding[0]; - $cell_padding['R'] = $padding[1]; - $cell_padding['B'] = $padding[2]; - $cell_padding['L'] = $padding[1]; - break; - } - case 2: { - $cell_padding['T'] = $padding[0]; - $cell_padding['R'] = $padding[1]; - $cell_padding['B'] = $padding[0]; - $cell_padding['L'] = $padding[1]; - break; - } - case 1: { - $cell_padding['T'] = $padding[0]; - $cell_padding['R'] = $padding[0]; - $cell_padding['B'] = $padding[0]; - $cell_padding['L'] = $padding[0]; - break; - } - default: { - return $this->cell_padding; - } - } - if ($width == 0) { - $width = $this->w - $this->lMargin - $this->rMargin; - } - $cell_padding['T'] = $this->getHTMLUnitToUnits($cell_padding['T'], $width, 'px', false); - $cell_padding['R'] = $this->getHTMLUnitToUnits($cell_padding['R'], $width, 'px', false); - $cell_padding['B'] = $this->getHTMLUnitToUnits($cell_padding['B'], $width, 'px', false); - $cell_padding['L'] = $this->getHTMLUnitToUnits($cell_padding['L'], $width, 'px', false); - return $cell_padding; - } - - /** - * Get the internal Cell margin from CSS attribute. - * @param string $cssmargin margin properties - * @param float $width width of the containing element - * @return array of cell margins - * @public - * @since 5.9.000 (2010-10-04) - */ - public function getCSSMargin($cssmargin, $width=0) { - $margin = preg_split('/[\s]+/', trim($cssmargin)); - $cell_margin = array(); // value to be returned - switch (count($margin)) { - case 4: { - $cell_margin['T'] = $margin[0]; - $cell_margin['R'] = $margin[1]; - $cell_margin['B'] = $margin[2]; - $cell_margin['L'] = $margin[3]; - break; - } - case 3: { - $cell_margin['T'] = $margin[0]; - $cell_margin['R'] = $margin[1]; - $cell_margin['B'] = $margin[2]; - $cell_margin['L'] = $margin[1]; - break; - } - case 2: { - $cell_margin['T'] = $margin[0]; - $cell_margin['R'] = $margin[1]; - $cell_margin['B'] = $margin[0]; - $cell_margin['L'] = $margin[1]; - break; - } - case 1: { - $cell_margin['T'] = $margin[0]; - $cell_margin['R'] = $margin[0]; - $cell_margin['B'] = $margin[0]; - $cell_margin['L'] = $margin[0]; - break; - } - default: { - return $this->cell_margin; - } - } - if ($width == 0) { - $width = $this->w - $this->lMargin - $this->rMargin; - } - $cell_margin['T'] = $this->getHTMLUnitToUnits(str_replace('auto', '0', $cell_margin['T']), $width, 'px', false); - $cell_margin['R'] = $this->getHTMLUnitToUnits(str_replace('auto', '0', $cell_margin['R']), $width, 'px', false); - $cell_margin['B'] = $this->getHTMLUnitToUnits(str_replace('auto', '0', $cell_margin['B']), $width, 'px', false); - $cell_margin['L'] = $this->getHTMLUnitToUnits(str_replace('auto', '0', $cell_margin['L']), $width, 'px', false); - return $cell_margin; - } - - /** - * Get the border-spacing from CSS attribute. - * @param string $cssbspace border-spacing CSS properties - * @param float $width width of the containing element - * @return array of border spacings - * @public - * @since 5.9.010 (2010-10-27) - */ - public function getCSSBorderMargin($cssbspace, $width=0) { - $space = preg_split('/[\s]+/', trim($cssbspace)); - $border_spacing = array(); // value to be returned - switch (count($space)) { - case 2: { - $border_spacing['H'] = $space[0]; - $border_spacing['V'] = $space[1]; - break; - } - case 1: { - $border_spacing['H'] = $space[0]; - $border_spacing['V'] = $space[0]; - break; - } - default: { - return array('H' => 0, 'V' => 0); - } - } - if ($width == 0) { - $width = $this->w - $this->lMargin - $this->rMargin; - } - $border_spacing['H'] = $this->getHTMLUnitToUnits($border_spacing['H'], $width, 'px', false); - $border_spacing['V'] = $this->getHTMLUnitToUnits($border_spacing['V'], $width, 'px', false); - return $border_spacing; - } - - /** - * Returns the letter-spacing value from CSS value - * @param string $spacing letter-spacing value - * @param float $parent font spacing (tracking) value of the parent element - * @return float quantity to increases or decreases the space between characters in a text. - * @protected - * @since 5.9.000 (2010-10-02) - */ - protected function getCSSFontSpacing($spacing, $parent=0) { - $val = 0; // value to be returned - $spacing = trim($spacing); - switch ($spacing) { - case 'normal': { - $val = 0; - break; - } - case 'inherit': { - if ($parent == 'normal') { - $val = 0; - } else { - $val = $parent; - } - break; - } - default: { - $val = $this->getHTMLUnitToUnits($spacing, 0, 'px', false); - } - } - return $val; - } - - /** - * Returns the percentage of font stretching from CSS value - * @param string $stretch stretch mode - * @param float $parent stretch value of the parent element - * @return float font stretching percentage - * @protected - * @since 5.9.000 (2010-10-02) - */ - protected function getCSSFontStretching($stretch, $parent=100) { - $val = 100; // value to be returned - $stretch = trim($stretch); - switch ($stretch) { - case 'ultra-condensed': { - $val = 40; - break; - } - case 'extra-condensed': { - $val = 55; - break; - } - case 'condensed': { - $val = 70; - break; - } - case 'semi-condensed': { - $val = 85; - break; - } - case 'normal': { - $val = 100; - break; - } - case 'semi-expanded': { - $val = 115; - break; - } - case 'expanded': { - $val = 130; - break; - } - case 'extra-expanded': { - $val = 145; - break; - } - case 'ultra-expanded': { - $val = 160; - break; - } - case 'wider': { - $val = ($parent + 10); - break; - } - case 'narrower': { - $val = ($parent - 10); - break; - } - case 'inherit': { - if ($parent == 'normal') { - $val = 100; - } else { - $val = $parent; - } - break; - } - default: { - $val = $this->getHTMLUnitToUnits($stretch, 100, '%', false); - } - } - return $val; - } - - /** - * Convert HTML string containing font size value to points - * @param string $val String containing font size value and unit. - * @param float $refsize Reference font size in points. - * @param float $parent_size Parent font size in points. - * @param string $defaultunit Default unit (can be one of the following: %, em, ex, px, in, mm, pc, pt). - * @return float value in points - * @public - */ - public function getHTMLFontUnits($val, $refsize=12, $parent_size=12, $defaultunit='pt') { - $refsize = TCPDF_FONTS::getFontRefSize($refsize); - $parent_size = TCPDF_FONTS::getFontRefSize($parent_size, $refsize); - switch ($val) { - case 'xx-small': { - $size = ($refsize - 4); - break; - } - case 'x-small': { - $size = ($refsize - 3); - break; - } - case 'small': { - $size = ($refsize - 2); - break; - } - case 'medium': { - $size = $refsize; - break; - } - case 'large': { - $size = ($refsize + 2); - break; - } - case 'x-large': { - $size = ($refsize + 4); - break; - } - case 'xx-large': { - $size = ($refsize + 6); - break; - } - case 'smaller': { - $size = ($parent_size - 3); - break; - } - case 'larger': { - $size = ($parent_size + 3); - break; - } - default: { - $size = $this->getHTMLUnitToUnits($val, $parent_size, $defaultunit, true); - } - } - return $size; - } - - /** - * Returns the HTML DOM array. - * @param string $html html code - * @return array - * @protected - * @since 3.2.000 (2008-06-20) - */ - protected function getHtmlDomArray($html) { - // array of CSS styles ( selector => properties). - $css = array(); - // get CSS array defined at previous call - $matches = array(); - if (preg_match_all('/<cssarray>([^\<]*?)<\/cssarray>/is', $html, $matches) > 0) { - if (isset($matches[1][0])) { - $css = array_merge($css, json_decode($this->unhtmlentities($matches[1][0]), true)); - } - $html = preg_replace('/<cssarray>(.*?)<\/cssarray>/is', '', $html); - } - // extract external CSS files - $matches = array(); - if (preg_match_all('/<link([^\>]*?)>/is', $html, $matches) > 0) { - foreach ($matches[1] as $key => $link) { - $type = array(); - if (preg_match('/type[\s]*=[\s]*"text\/css"/', $link, $type)) { - $type = array(); - preg_match('/media[\s]*=[\s]*"([^"]*)"/', $link, $type); - // get 'all' and 'print' media, other media types are discarded - // (all, braille, embossed, handheld, print, projection, screen, speech, tty, tv) - if (empty($type) OR (isset($type[1]) AND (($type[1] == 'all') OR ($type[1] == 'print')))) { - $type = array(); - if (preg_match('/href[\s]*=[\s]*"([^"]*)"/', $link, $type) > 0) { - // read CSS data file - $cssdata = $this->getCachedFileContents(trim($type[1])); - if (($cssdata !== FALSE) AND (strlen($cssdata) > 0)) { - $css = array_merge($css, TCPDF_STATIC::extractCSSproperties($cssdata)); - } - } - } - } - } - } - // extract style tags - $matches = array(); - if (preg_match_all('/<style([^\>]*?)>([^\<]*?)<\/style>/is', $html, $matches) > 0) { - foreach ($matches[1] as $key => $media) { - $type = array(); - preg_match('/media[\s]*=[\s]*"([^"]*)"/', $media, $type); - // get 'all' and 'print' media, other media types are discarded - // (all, braille, embossed, handheld, print, projection, screen, speech, tty, tv) - if (empty($type) OR (isset($type[1]) AND (($type[1] == 'all') OR ($type[1] == 'print')))) { - $cssdata = $matches[2][$key]; - $css = array_merge($css, TCPDF_STATIC::extractCSSproperties($cssdata)); - } - } - } - // create a special tag to contain the CSS array (used for table content) - $csstagarray = '<cssarray>'.htmlentities(json_encode($css)).'</cssarray>'; - // remove head and style blocks - $html = preg_replace('/<head([^\>]*?)>(.*?)<\/head>/is', '', $html); - $html = preg_replace('/<style([^\>]*?)>([^\<]*?)<\/style>/is', '', $html); - // define block tags - $blocktags = array('blockquote','br','dd','dl','div','dt','h1','h2','h3','h4','h5','h6','hr','li','ol','p','pre','ul','tcpdf','table','tr','td'); - // define self-closing tags - $selfclosingtags = array('area','base','basefont','br','hr','input','img','link','meta'); - // remove all unsupported tags (the line below lists all supported tags) - $html = strip_tags($html, '<marker/><a><b><blockquote><body><br><br/><dd><del><div><dl><dt><em><font><form><h1><h2><h3><h4><h5><h6><hr><hr/><i><img><input><label><li><ol><option><p><pre><s><select><small><span><strike><strong><sub><sup><table><tablehead><tcpdf><td><textarea><th><thead><tr><tt><u><ul>'); - //replace some blank characters - $html = preg_replace('/<pre/', '<xre', $html); // preserve pre tag - $html = preg_replace('/<(table|tr|td|th|tcpdf|blockquote|dd|div|dl|dt|form|h1|h2|h3|h4|h5|h6|br|hr|li|ol|ul|p)([^\>]*)>[\n\r\t]+/', '<\\1\\2>', $html); - $html = preg_replace('@(\r\n|\r)@', "\n", $html); - $repTable = array("\t" => ' ', "\0" => ' ', "\x0B" => ' ', "\\" => "\\\\"); - $html = strtr($html, $repTable); - $offset = 0; - while (($offset < strlen($html)) AND ($pos = strpos($html, '</pre>', $offset)) !== false) { - $html_a = substr($html, 0, $offset); - $html_b = substr($html, $offset, ($pos - $offset + 6)); - while (preg_match("'<xre([^\>]*)>(.*?)\n(.*?)</pre>'si", $html_b)) { - // preserve newlines on <pre> tag - $html_b = preg_replace("'<xre([^\>]*)>(.*?)\n(.*?)</pre>'si", "<xre\\1>\\2<br />\\3</pre>", $html_b); - } - while (preg_match("'<xre([^\>]*)>(.*?)".$this->re_space['p']."(.*?)</pre>'".$this->re_space['m'], $html_b)) { - // preserve spaces on <pre> tag - $html_b = preg_replace("'<xre([^\>]*)>(.*?)".$this->re_space['p']."(.*?)</pre>'".$this->re_space['m'], "<xre\\1>\\2&nbsp;\\3</pre>", $html_b); - } - $html = $html_a.$html_b.substr($html, $pos + 6); - $offset = strlen($html_a.$html_b); - } - $offset = 0; - while (($offset < strlen($html)) AND ($pos = strpos($html, '</textarea>', $offset)) !== false) { - $html_a = substr($html, 0, $offset); - $html_b = substr($html, $offset, ($pos - $offset + 11)); - while (preg_match("'<textarea([^\>]*)>(.*?)\n(.*?)</textarea>'si", $html_b)) { - // preserve newlines on <textarea> tag - $html_b = preg_replace("'<textarea([^\>]*)>(.*?)\n(.*?)</textarea>'si", "<textarea\\1>\\2<TBR>\\3</textarea>", $html_b); - $html_b = preg_replace("'<textarea([^\>]*)>(.*?)[\"](.*?)</textarea>'si", "<textarea\\1>\\2''\\3</textarea>", $html_b); - } - $html = $html_a.$html_b.substr($html, $pos + 11); - $offset = strlen($html_a.$html_b); - } - $html = preg_replace('/([\s]*)<option/si', '<option', $html); - $html = preg_replace('/<\/option>([\s]*)/si', '</option>', $html); - $offset = 0; - while (($offset < strlen($html)) AND ($pos = strpos($html, '</option>', $offset)) !== false) { - $html_a = substr($html, 0, $offset); - $html_b = substr($html, $offset, ($pos - $offset + 9)); - while (preg_match("'<option([^\>]*)>(.*?)</option>'si", $html_b)) { - $html_b = preg_replace("'<option([\s]+)value=\"([^\"]*)\"([^\>]*)>(.*?)</option>'si", "\\2#!TaB!#\\4#!NwL!#", $html_b); - $html_b = preg_replace("'<option([^\>]*)>(.*?)</option>'si", "\\2#!NwL!#", $html_b); - } - $html = $html_a.$html_b.substr($html, $pos + 9); - $offset = strlen($html_a.$html_b); - } - if (preg_match("'</select'si", $html)) { - $html = preg_replace("'<select([^\>]*)>'si", "<select\\1 opt=\"", $html); - $html = preg_replace("'#!NwL!#</select>'si", "\" />", $html); - } - $html = str_replace("\n", ' ', $html); - // restore textarea newlines - $html = str_replace('<TBR>', "\n", $html); - // remove extra spaces from code - $html = preg_replace('/[\s]+<\/(table|tr|ul|ol|dl)>/', '</\\1>', $html); - $html = preg_replace('/'.$this->re_space['p'].'+<\/(td|th|li|dt|dd)>/'.$this->re_space['m'], '</\\1>', $html); - $html = preg_replace('/[\s]+<(tr|td|th|li|dt|dd)/', '<\\1', $html); - $html = preg_replace('/'.$this->re_space['p'].'+<(ul|ol|dl|br)/'.$this->re_space['m'], '<\\1', $html); - $html = preg_replace('/<\/(table|tr|td|th|blockquote|dd|dt|dl|div|dt|h1|h2|h3|h4|h5|h6|hr|li|ol|ul|p)>[\s]+</', '</\\1><', $html); - $html = preg_replace('/<\/(td|th)>/', '<marker style="font-size:0"/></\\1>', $html); - $html = preg_replace('/<\/table>([\s]*)<marker style="font-size:0"\/>/', '</table>', $html); - $html = preg_replace('/'.$this->re_space['p'].'+<img/'.$this->re_space['m'], chr(32).'<img', $html); - $html = preg_replace('/<img([^\>]*)>[\s]+([^\<])/xi', '<img\\1>&nbsp;\\2', $html); - $html = preg_replace('/<img([^\>]*)>/xi', '<img\\1><span><marker style="font-size:0"/></span>', $html); - $html = preg_replace('/<xre/', '<pre', $html); // restore pre tag - $html = preg_replace('/<textarea([^\>]*)>([^\<]*)<\/textarea>/xi', '<textarea\\1 value="\\2" />', $html); - $html = preg_replace('/<li([^\>]*)><\/li>/', '<li\\1>&nbsp;</li>', $html); - $html = preg_replace('/<li([^\>]*)>'.$this->re_space['p'].'*<img/'.$this->re_space['m'], '<li\\1><font size="1">&nbsp;</font><img', $html); - $html = preg_replace('/<([^\>\/]*)>[\s]/', '<\\1>&nbsp;', $html); // preserve some spaces - $html = preg_replace('/[\s]<\/([^\>]*)>/', '&nbsp;</\\1>', $html); // preserve some spaces - $html = preg_replace('/<su([bp])/', '<zws/><su\\1', $html); // fix sub/sup alignment - $html = preg_replace('/<\/su([bp])>/', '</su\\1><zws/>', $html); // fix sub/sup alignment - $html = preg_replace('/'.$this->re_space['p'].'+/'.$this->re_space['m'], chr(32), $html); // replace multiple spaces with a single space - // trim string - $html = $this->stringTrim($html); - // fix br tag after li - $html = preg_replace('/<li><br([^\>]*)>/', '<li> <br\\1>', $html); - // fix first image tag alignment - $html = preg_replace('/^<img/', '<span style="font-size:0"><br /></span> <img', $html, 1); - // pattern for generic tag - $tagpattern = '/(<[^>]+>)/'; - // explodes the string - $a = preg_split($tagpattern, $html, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); - // count elements - $maxel = count($a); - $elkey = 0; - $key = 0; - // create an array of elements - $dom = array(); - $dom[$key] = array(); - // set inheritable properties fot the first void element - // possible inheritable properties are: azimuth, border-collapse, border-spacing, caption-side, color, cursor, direction, empty-cells, font, font-family, font-stretch, font-size, font-size-adjust, font-style, font-variant, font-weight, letter-spacing, line-height, list-style, list-style-image, list-style-position, list-style-type, orphans, page, page-break-inside, quotes, speak, speak-header, text-align, text-indent, text-transform, volume, white-space, widows, word-spacing - $dom[$key]['tag'] = false; - $dom[$key]['block'] = false; - $dom[$key]['value'] = ''; - $dom[$key]['parent'] = 0; - $dom[$key]['hide'] = false; - $dom[$key]['fontname'] = $this->FontFamily; - $dom[$key]['fontstyle'] = $this->FontStyle; - $dom[$key]['fontsize'] = $this->FontSizePt; - $dom[$key]['font-stretch'] = $this->font_stretching; - $dom[$key]['letter-spacing'] = $this->font_spacing; - $dom[$key]['stroke'] = $this->textstrokewidth; - $dom[$key]['fill'] = (($this->textrendermode % 2) == 0); - $dom[$key]['clip'] = ($this->textrendermode > 3); - $dom[$key]['line-height'] = $this->cell_height_ratio; - $dom[$key]['bgcolor'] = false; - $dom[$key]['fgcolor'] = $this->fgcolor; // color - $dom[$key]['strokecolor'] = $this->strokecolor; - $dom[$key]['align'] = ''; - $dom[$key]['listtype'] = ''; - $dom[$key]['text-indent'] = 0; - $dom[$key]['text-transform'] = ''; - $dom[$key]['border'] = array(); - $dom[$key]['dir'] = $this->rtl?'rtl':'ltr'; - $thead = false; // true when we are inside the THEAD tag - ++$key; - $level = array(); - array_push($level, 0); // root - while ($elkey < $maxel) { - $dom[$key] = array(); - $element = $a[$elkey]; - $dom[$key]['elkey'] = $elkey; - if (preg_match($tagpattern, $element)) { - // html tag - $element = substr($element, 1, -1); - // get tag name - preg_match('/[\/]?([a-zA-Z0-9]*)/', $element, $tag); - $tagname = strtolower($tag[1]); - // check if we are inside a table header - if ($tagname == 'thead') { - if ($element[0] == '/') { - $thead = false; - } else { - $thead = true; - } - ++$elkey; - continue; - } - $dom[$key]['tag'] = true; - $dom[$key]['value'] = $tagname; - if (in_array($dom[$key]['value'], $blocktags)) { - $dom[$key]['block'] = true; - } else { - $dom[$key]['block'] = false; - } - if ($element[0] == '/') { - // *** closing html tag - $dom[$key]['opening'] = false; - $dom[$key]['parent'] = end($level); - array_pop($level); - $dom[$key]['hide'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['hide']; - $dom[$key]['fontname'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['fontname']; - $dom[$key]['fontstyle'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['fontstyle']; - $dom[$key]['fontsize'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['fontsize']; - $dom[$key]['font-stretch'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['font-stretch']; - $dom[$key]['letter-spacing'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['letter-spacing']; - $dom[$key]['stroke'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['stroke']; - $dom[$key]['fill'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['fill']; - $dom[$key]['clip'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['clip']; - $dom[$key]['line-height'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['line-height']; - $dom[$key]['bgcolor'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['bgcolor']; - $dom[$key]['fgcolor'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['fgcolor']; - $dom[$key]['strokecolor'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['strokecolor']; - $dom[$key]['align'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['align']; - $dom[$key]['text-transform'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['text-transform']; - $dom[$key]['dir'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['dir']; - if (isset($dom[($dom[($dom[$key]['parent'])]['parent'])]['listtype'])) { - $dom[$key]['listtype'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['listtype']; - } - // set the number of columns in table tag - if (($dom[$key]['value'] == 'tr') AND (!isset($dom[($dom[($dom[$key]['parent'])]['parent'])]['cols']))) { - $dom[($dom[($dom[$key]['parent'])]['parent'])]['cols'] = $dom[($dom[$key]['parent'])]['cols']; - } - if (($dom[$key]['value'] == 'td') OR ($dom[$key]['value'] == 'th')) { - $dom[($dom[$key]['parent'])]['content'] = $csstagarray; - for ($i = ($dom[$key]['parent'] + 1); $i < $key; ++$i) { - $dom[($dom[$key]['parent'])]['content'] .= stripslashes($a[$dom[$i]['elkey']]); - } - $key = $i; - // mark nested tables - $dom[($dom[$key]['parent'])]['content'] = str_replace('<table', '<table nested="true"', $dom[($dom[$key]['parent'])]['content']); - // remove thead sections from nested tables - $dom[($dom[$key]['parent'])]['content'] = str_replace('<thead>', '', $dom[($dom[$key]['parent'])]['content']); - $dom[($dom[$key]['parent'])]['content'] = str_replace('</thead>', '', $dom[($dom[$key]['parent'])]['content']); - } - // store header rows on a new table - if ( - ($dom[$key]['value'] === 'tr') - && !empty($dom[($dom[$key]['parent'])]['thead']) - && ($dom[($dom[$key]['parent'])]['thead'] === true) - ) { - if (TCPDF_STATIC::empty_string($dom[($dom[($dom[$key]['parent'])]['parent'])]['thead'])) { - $dom[($dom[($dom[$key]['parent'])]['parent'])]['thead'] = $csstagarray.$a[$dom[($dom[($dom[$key]['parent'])]['parent'])]['elkey']]; - } - for ($i = $dom[$key]['parent']; $i <= $key; ++$i) { - $dom[($dom[($dom[$key]['parent'])]['parent'])]['thead'] .= $a[$dom[$i]['elkey']]; - } - if (!isset($dom[($dom[$key]['parent'])]['attribute'])) { - $dom[($dom[$key]['parent'])]['attribute'] = array(); - } - // header elements must be always contained in a single page - $dom[($dom[$key]['parent'])]['attribute']['nobr'] = 'true'; - } - if (($dom[$key]['value'] == 'table') AND (!TCPDF_STATIC::empty_string($dom[($dom[$key]['parent'])]['thead']))) { - // remove the nobr attributes from the table header - $dom[($dom[$key]['parent'])]['thead'] = str_replace(' nobr="true"', '', $dom[($dom[$key]['parent'])]['thead']); - $dom[($dom[$key]['parent'])]['thead'] .= '</tablehead>'; - } - } else { - // *** opening or self-closing html tag - $dom[$key]['opening'] = true; - $dom[$key]['parent'] = end($level); - if ((substr($element, -1, 1) == '/') OR (in_array($dom[$key]['value'], $selfclosingtags))) { - // self-closing tag - $dom[$key]['self'] = true; - } else { - // opening tag - array_push($level, $key); - $dom[$key]['self'] = false; - } - // copy some values from parent - $parentkey = 0; - if ($key > 0) { - $parentkey = $dom[$key]['parent']; - $dom[$key]['hide'] = $dom[$parentkey]['hide']; - $dom[$key]['fontname'] = $dom[$parentkey]['fontname']; - $dom[$key]['fontstyle'] = $dom[$parentkey]['fontstyle']; - $dom[$key]['fontsize'] = $dom[$parentkey]['fontsize']; - $dom[$key]['font-stretch'] = $dom[$parentkey]['font-stretch']; - $dom[$key]['letter-spacing'] = $dom[$parentkey]['letter-spacing']; - $dom[$key]['stroke'] = $dom[$parentkey]['stroke']; - $dom[$key]['fill'] = $dom[$parentkey]['fill']; - $dom[$key]['clip'] = $dom[$parentkey]['clip']; - $dom[$key]['line-height'] = $dom[$parentkey]['line-height']; - $dom[$key]['bgcolor'] = $dom[$parentkey]['bgcolor']; - $dom[$key]['fgcolor'] = $dom[$parentkey]['fgcolor']; - $dom[$key]['strokecolor'] = $dom[$parentkey]['strokecolor']; - $dom[$key]['align'] = $dom[$parentkey]['align']; - $dom[$key]['listtype'] = $dom[$parentkey]['listtype']; - $dom[$key]['text-indent'] = $dom[$parentkey]['text-indent']; - $dom[$key]['text-transform'] = $dom[$parentkey]['text-transform']; - $dom[$key]['border'] = array(); - $dom[$key]['dir'] = $dom[$parentkey]['dir']; - } - // get attributes - preg_match_all('/([^=\s]*)[\s]*=[\s]*"([^"]*)"/', $element, $attr_array, PREG_PATTERN_ORDER); - $dom[$key]['attribute'] = array(); // reset attribute array - foreach($attr_array[1] as $id => $name) { - $dom[$key]['attribute'][strtolower($name)] = $attr_array[2][$id]; - } - if (!empty($css)) { - // merge CSS style to current style - list($dom[$key]['csssel'], $dom[$key]['cssdata']) = TCPDF_STATIC::getCSSdataArray($dom, $key, $css); - $dom[$key]['attribute']['style'] = TCPDF_STATIC::getTagStyleFromCSSarray($dom[$key]['cssdata']); - } - // split style attributes - if (isset($dom[$key]['attribute']['style']) AND !empty($dom[$key]['attribute']['style'])) { - // get style attributes - preg_match_all('/([^;:\s]*):([^;]*)/', $dom[$key]['attribute']['style'], $style_array, PREG_PATTERN_ORDER); - $dom[$key]['style'] = array(); // reset style attribute array - foreach($style_array[1] as $id => $name) { - // in case of duplicate attribute the last replace the previous - $dom[$key]['style'][strtolower($name)] = trim($style_array[2][$id]); - } - // --- get some style attributes --- - // text direction - if (isset($dom[$key]['style']['direction'])) { - $dom[$key]['dir'] = $dom[$key]['style']['direction']; - } - // display - if (isset($dom[$key]['style']['display'])) { - $dom[$key]['hide'] = (trim(strtolower($dom[$key]['style']['display'])) == 'none'); - } - // font family - if (isset($dom[$key]['style']['font-family'])) { - $dom[$key]['fontname'] = $this->getFontFamilyName($dom[$key]['style']['font-family']); - } - // list-style-type - if (isset($dom[$key]['style']['list-style-type'])) { - $dom[$key]['listtype'] = trim(strtolower($dom[$key]['style']['list-style-type'])); - if ($dom[$key]['listtype'] == 'inherit') { - $dom[$key]['listtype'] = $dom[$parentkey]['listtype']; - } - } - // text-indent - if (isset($dom[$key]['style']['text-indent'])) { - $dom[$key]['text-indent'] = $this->getHTMLUnitToUnits($dom[$key]['style']['text-indent']); - if ($dom[$key]['text-indent'] == 'inherit') { - $dom[$key]['text-indent'] = $dom[$parentkey]['text-indent']; - } - } - // text-transform - if (isset($dom[$key]['style']['text-transform'])) { - $dom[$key]['text-transform'] = $dom[$key]['style']['text-transform']; - } - // font size - if (isset($dom[$key]['style']['font-size'])) { - $fsize = trim($dom[$key]['style']['font-size']); - $dom[$key]['fontsize'] = $this->getHTMLFontUnits($fsize, $dom[0]['fontsize'], $dom[$parentkey]['fontsize'], 'pt'); - } - // font-stretch - if (isset($dom[$key]['style']['font-stretch'])) { - $dom[$key]['font-stretch'] = $this->getCSSFontStretching($dom[$key]['style']['font-stretch'], $dom[$parentkey]['font-stretch']); - } - // letter-spacing - if (isset($dom[$key]['style']['letter-spacing'])) { - $dom[$key]['letter-spacing'] = $this->getCSSFontSpacing($dom[$key]['style']['letter-spacing'], $dom[$parentkey]['letter-spacing']); - } - // line-height (internally is the cell height ratio) - if (isset($dom[$key]['style']['line-height'])) { - $lineheight = trim($dom[$key]['style']['line-height']); - switch ($lineheight) { - // A normal line height. This is default - case 'normal': { - $dom[$key]['line-height'] = $dom[0]['line-height']; - break; - } - case 'inherit': { - $dom[$key]['line-height'] = $dom[$parentkey]['line-height']; - } - default: { - if (is_numeric($lineheight)) { - // convert to percentage of font height - $lineheight = ($lineheight * 100).'%'; - } - $dom[$key]['line-height'] = $this->getHTMLUnitToUnits($lineheight, 1, '%', true); - if (substr($lineheight, -1) !== '%') { - if ($dom[$key]['fontsize'] <= 0) { - $dom[$key]['line-height'] = 1; - } else { - $dom[$key]['line-height'] = (($dom[$key]['line-height'] - $this->cell_padding['T'] - $this->cell_padding['B']) / $dom[$key]['fontsize']); - } - } - } - } - } - // font style - if (isset($dom[$key]['style']['font-weight'])) { - if (strtolower($dom[$key]['style']['font-weight'][0]) == 'n') { - if (strpos($dom[$key]['fontstyle'], 'B') !== false) { - $dom[$key]['fontstyle'] = str_replace('B', '', $dom[$key]['fontstyle']); - } - } elseif (strtolower($dom[$key]['style']['font-weight'][0]) == 'b') { - $dom[$key]['fontstyle'] .= 'B'; - } - } - if (isset($dom[$key]['style']['font-style']) AND (strtolower($dom[$key]['style']['font-style'][0]) == 'i')) { - $dom[$key]['fontstyle'] .= 'I'; - } - // font color - if (isset($dom[$key]['style']['color']) AND (!TCPDF_STATIC::empty_string($dom[$key]['style']['color']))) { - $dom[$key]['fgcolor'] = TCPDF_COLORS::convertHTMLColorToDec($dom[$key]['style']['color'], $this->spot_colors); - } elseif ($dom[$key]['value'] == 'a') { - $dom[$key]['fgcolor'] = $this->htmlLinkColorArray; - } - // background color - if (isset($dom[$key]['style']['background-color']) AND (!TCPDF_STATIC::empty_string($dom[$key]['style']['background-color']))) { - $dom[$key]['bgcolor'] = TCPDF_COLORS::convertHTMLColorToDec($dom[$key]['style']['background-color'], $this->spot_colors); - } - // text-decoration - if (isset($dom[$key]['style']['text-decoration'])) { - $decors = explode(' ', strtolower($dom[$key]['style']['text-decoration'])); - foreach ($decors as $dec) { - $dec = trim($dec); - if (!TCPDF_STATIC::empty_string($dec)) { - if ($dec[0] == 'u') { - // underline - $dom[$key]['fontstyle'] .= 'U'; - } elseif ($dec[0] == 'l') { - // line-through - $dom[$key]['fontstyle'] .= 'D'; - } elseif ($dec[0] == 'o') { - // overline - $dom[$key]['fontstyle'] .= 'O'; - } - } - } - } elseif ($dom[$key]['value'] == 'a') { - $dom[$key]['fontstyle'] = $this->htmlLinkFontStyle; - } - // check for width attribute - if (isset($dom[$key]['style']['width'])) { - $dom[$key]['width'] = $dom[$key]['style']['width']; - } - // check for height attribute - if (isset($dom[$key]['style']['height'])) { - $dom[$key]['height'] = $dom[$key]['style']['height']; - } - // check for text alignment - if (isset($dom[$key]['style']['text-align'])) { - $dom[$key]['align'] = strtoupper($dom[$key]['style']['text-align'][0]); - } - // check for CSS border properties - if (isset($dom[$key]['style']['border'])) { - $borderstyle = $this->getCSSBorderStyle($dom[$key]['style']['border']); - if (!empty($borderstyle)) { - $dom[$key]['border']['LTRB'] = $borderstyle; - } - } - if (isset($dom[$key]['style']['border-color'])) { - $brd_colors = preg_split('/[\s]+/', trim($dom[$key]['style']['border-color'])); - if (isset($brd_colors[3])) { - $dom[$key]['border']['L']['color'] = TCPDF_COLORS::convertHTMLColorToDec($brd_colors[3], $this->spot_colors); - } - if (isset($brd_colors[1])) { - $dom[$key]['border']['R']['color'] = TCPDF_COLORS::convertHTMLColorToDec($brd_colors[1], $this->spot_colors); - } - if (isset($brd_colors[0])) { - $dom[$key]['border']['T']['color'] = TCPDF_COLORS::convertHTMLColorToDec($brd_colors[0], $this->spot_colors); - } - if (isset($brd_colors[2])) { - $dom[$key]['border']['B']['color'] = TCPDF_COLORS::convertHTMLColorToDec($brd_colors[2], $this->spot_colors); - } - } - if (isset($dom[$key]['style']['border-width'])) { - $brd_widths = preg_split('/[\s]+/', trim($dom[$key]['style']['border-width'])); - if (isset($brd_widths[3])) { - $dom[$key]['border']['L']['width'] = $this->getCSSBorderWidth($brd_widths[3]); - } - if (isset($brd_widths[1])) { - $dom[$key]['border']['R']['width'] = $this->getCSSBorderWidth($brd_widths[1]); - } - if (isset($brd_widths[0])) { - $dom[$key]['border']['T']['width'] = $this->getCSSBorderWidth($brd_widths[0]); - } - if (isset($brd_widths[2])) { - $dom[$key]['border']['B']['width'] = $this->getCSSBorderWidth($brd_widths[2]); - } - } - if (isset($dom[$key]['style']['border-style'])) { - $brd_styles = preg_split('/[\s]+/', trim($dom[$key]['style']['border-style'])); - if (isset($brd_styles[3]) AND ($brd_styles[3]!='none')) { - $dom[$key]['border']['L']['cap'] = 'square'; - $dom[$key]['border']['L']['join'] = 'miter'; - $dom[$key]['border']['L']['dash'] = $this->getCSSBorderDashStyle($brd_styles[3]); - if ($dom[$key]['border']['L']['dash'] < 0) { - $dom[$key]['border']['L'] = array(); - } - } - if (isset($brd_styles[1])) { - $dom[$key]['border']['R']['cap'] = 'square'; - $dom[$key]['border']['R']['join'] = 'miter'; - $dom[$key]['border']['R']['dash'] = $this->getCSSBorderDashStyle($brd_styles[1]); - if ($dom[$key]['border']['R']['dash'] < 0) { - $dom[$key]['border']['R'] = array(); - } - } - if (isset($brd_styles[0])) { - $dom[$key]['border']['T']['cap'] = 'square'; - $dom[$key]['border']['T']['join'] = 'miter'; - $dom[$key]['border']['T']['dash'] = $this->getCSSBorderDashStyle($brd_styles[0]); - if ($dom[$key]['border']['T']['dash'] < 0) { - $dom[$key]['border']['T'] = array(); - } - } - if (isset($brd_styles[2])) { - $dom[$key]['border']['B']['cap'] = 'square'; - $dom[$key]['border']['B']['join'] = 'miter'; - $dom[$key]['border']['B']['dash'] = $this->getCSSBorderDashStyle($brd_styles[2]); - if ($dom[$key]['border']['B']['dash'] < 0) { - $dom[$key]['border']['B'] = array(); - } - } - } - $cellside = array('L' => 'left', 'R' => 'right', 'T' => 'top', 'B' => 'bottom'); - foreach ($cellside as $bsk => $bsv) { - if (isset($dom[$key]['style']['border-'.$bsv])) { - $borderstyle = $this->getCSSBorderStyle($dom[$key]['style']['border-'.$bsv]); - if (!empty($borderstyle)) { - $dom[$key]['border'][$bsk] = $borderstyle; - } - } - if (isset($dom[$key]['style']['border-'.$bsv.'-color'])) { - $dom[$key]['border'][$bsk]['color'] = TCPDF_COLORS::convertHTMLColorToDec($dom[$key]['style']['border-'.$bsv.'-color'], $this->spot_colors); - } - if (isset($dom[$key]['style']['border-'.$bsv.'-width'])) { - $dom[$key]['border'][$bsk]['width'] = $this->getCSSBorderWidth($dom[$key]['style']['border-'.$bsv.'-width']); - } - if (isset($dom[$key]['style']['border-'.$bsv.'-style'])) { - $dom[$key]['border'][$bsk]['dash'] = $this->getCSSBorderDashStyle($dom[$key]['style']['border-'.$bsv.'-style']); - if ($dom[$key]['border'][$bsk]['dash'] < 0) { - $dom[$key]['border'][$bsk] = array(); - } - } - } - // check for CSS padding properties - if (isset($dom[$key]['style']['padding'])) { - $dom[$key]['padding'] = $this->getCSSPadding($dom[$key]['style']['padding']); - } else { - $dom[$key]['padding'] = $this->cell_padding; - } - foreach ($cellside as $psk => $psv) { - if (isset($dom[$key]['style']['padding-'.$psv])) { - $dom[$key]['padding'][$psk] = $this->getHTMLUnitToUnits($dom[$key]['style']['padding-'.$psv], 0, 'px', false); - } - } - // check for CSS margin properties - if (isset($dom[$key]['style']['margin'])) { - $dom[$key]['margin'] = $this->getCSSMargin($dom[$key]['style']['margin']); - } else { - $dom[$key]['margin'] = $this->cell_margin; - } - foreach ($cellside as $psk => $psv) { - if (isset($dom[$key]['style']['margin-'.$psv])) { - $dom[$key]['margin'][$psk] = $this->getHTMLUnitToUnits(str_replace('auto', '0', $dom[$key]['style']['margin-'.$psv]), 0, 'px', false); - } - } - // check for CSS border-spacing properties - if (isset($dom[$key]['style']['border-spacing'])) { - $dom[$key]['border-spacing'] = $this->getCSSBorderMargin($dom[$key]['style']['border-spacing']); - } - // page-break-inside - if (isset($dom[$key]['style']['page-break-inside']) AND ($dom[$key]['style']['page-break-inside'] == 'avoid')) { - $dom[$key]['attribute']['nobr'] = 'true'; - } - // page-break-before - if (isset($dom[$key]['style']['page-break-before'])) { - if ($dom[$key]['style']['page-break-before'] == 'always') { - $dom[$key]['attribute']['pagebreak'] = 'true'; - } elseif ($dom[$key]['style']['page-break-before'] == 'left') { - $dom[$key]['attribute']['pagebreak'] = 'left'; - } elseif ($dom[$key]['style']['page-break-before'] == 'right') { - $dom[$key]['attribute']['pagebreak'] = 'right'; - } - } - // page-break-after - if (isset($dom[$key]['style']['page-break-after'])) { - if ($dom[$key]['style']['page-break-after'] == 'always') { - $dom[$key]['attribute']['pagebreakafter'] = 'true'; - } elseif ($dom[$key]['style']['page-break-after'] == 'left') { - $dom[$key]['attribute']['pagebreakafter'] = 'left'; - } elseif ($dom[$key]['style']['page-break-after'] == 'right') { - $dom[$key]['attribute']['pagebreakafter'] = 'right'; - } - } - } - if (isset($dom[$key]['attribute']['display'])) { - $dom[$key]['hide'] = (trim(strtolower($dom[$key]['attribute']['display'])) == 'none'); - } - if (isset($dom[$key]['attribute']['border']) AND ($dom[$key]['attribute']['border'] != 0)) { - $borderstyle = $this->getCSSBorderStyle($dom[$key]['attribute']['border'].' solid black'); - if (!empty($borderstyle)) { - $dom[$key]['border']['LTRB'] = $borderstyle; - } - } - // check for font tag - if ($dom[$key]['value'] == 'font') { - // font family - if (isset($dom[$key]['attribute']['face'])) { - $dom[$key]['fontname'] = $this->getFontFamilyName($dom[$key]['attribute']['face']); - } - // font size - if (isset($dom[$key]['attribute']['size'])) { - if ($key > 0) { - if ($dom[$key]['attribute']['size'][0] == '+') { - $dom[$key]['fontsize'] = $dom[($dom[$key]['parent'])]['fontsize'] + intval(substr($dom[$key]['attribute']['size'], 1)); - } elseif ($dom[$key]['attribute']['size'][0] == '-') { - $dom[$key]['fontsize'] = $dom[($dom[$key]['parent'])]['fontsize'] - intval(substr($dom[$key]['attribute']['size'], 1)); - } else { - $dom[$key]['fontsize'] = intval($dom[$key]['attribute']['size']); - } - } else { - $dom[$key]['fontsize'] = intval($dom[$key]['attribute']['size']); - } - } - } - // force natural alignment for lists - if ((($dom[$key]['value'] == 'ul') OR ($dom[$key]['value'] == 'ol') OR ($dom[$key]['value'] == 'dl')) - AND (!isset($dom[$key]['align']) OR TCPDF_STATIC::empty_string($dom[$key]['align']) OR ($dom[$key]['align'] != 'J'))) { - if ($this->rtl) { - $dom[$key]['align'] = 'R'; - } else { - $dom[$key]['align'] = 'L'; - } - } - if (($dom[$key]['value'] == 'small') OR ($dom[$key]['value'] == 'sup') OR ($dom[$key]['value'] == 'sub')) { - if (!isset($dom[$key]['attribute']['size']) AND !isset($dom[$key]['style']['font-size'])) { - $dom[$key]['fontsize'] = $dom[$key]['fontsize'] * K_SMALL_RATIO; - } - } - if (($dom[$key]['value'] == 'strong') OR ($dom[$key]['value'] == 'b')) { - $dom[$key]['fontstyle'] .= 'B'; - } - if (($dom[$key]['value'] == 'em') OR ($dom[$key]['value'] == 'i')) { - $dom[$key]['fontstyle'] .= 'I'; - } - if ($dom[$key]['value'] == 'u') { - $dom[$key]['fontstyle'] .= 'U'; - } - if (($dom[$key]['value'] == 'del') OR ($dom[$key]['value'] == 's') OR ($dom[$key]['value'] == 'strike')) { - $dom[$key]['fontstyle'] .= 'D'; - } - if (!isset($dom[$key]['style']['text-decoration']) AND ($dom[$key]['value'] == 'a')) { - $dom[$key]['fontstyle'] = $this->htmlLinkFontStyle; - } - if (($dom[$key]['value'] == 'pre') OR ($dom[$key]['value'] == 'tt')) { - $dom[$key]['fontname'] = $this->default_monospaced_font; - } - if (!empty($dom[$key]['value']) AND ($dom[$key]['value'][0] == 'h') AND (intval($dom[$key]['value'][1]) > 0) AND (intval($dom[$key]['value'][1]) < 7)) { - // headings h1, h2, h3, h4, h5, h6 - if (!isset($dom[$key]['attribute']['size']) AND !isset($dom[$key]['style']['font-size'])) { - $headsize = (4 - intval($dom[$key]['value'][1])) * 2; - $dom[$key]['fontsize'] = $dom[0]['fontsize'] + $headsize; - } - if (!isset($dom[$key]['style']['font-weight'])) { - $dom[$key]['fontstyle'] .= 'B'; - } - } - if (($dom[$key]['value'] == 'table')) { - $dom[$key]['rows'] = 0; // number of rows - $dom[$key]['trids'] = array(); // IDs of TR elements - $dom[$key]['thead'] = ''; // table header rows - } - if (($dom[$key]['value'] == 'tr')) { - $dom[$key]['cols'] = 0; - if ($thead) { - $dom[$key]['thead'] = true; - // rows on thead block are printed as a separate table - } else { - $dom[$key]['thead'] = false; - $parent = $dom[$key]['parent']; - - if (!isset($dom[$parent]['rows'])) { - $dom[$parent]['rows'] = 0; - } - // store the number of rows on table element - ++$dom[$parent]['rows']; - - if (!isset($dom[$parent]['trids'])) { - $dom[$parent]['trids'] = array(); - } - - // store the TR elements IDs on table element - array_push($dom[$parent]['trids'], $key); - } - } - if (($dom[$key]['value'] == 'th') OR ($dom[$key]['value'] == 'td')) { - if (isset($dom[$key]['attribute']['colspan'])) { - $colspan = intval($dom[$key]['attribute']['colspan']); - } else { - $colspan = 1; - } - $dom[$key]['attribute']['colspan'] = $colspan; - $dom[($dom[$key]['parent'])]['cols'] += $colspan; - } - // text direction - if (isset($dom[$key]['attribute']['dir'])) { - $dom[$key]['dir'] = $dom[$key]['attribute']['dir']; - } - // set foreground color attribute - if (isset($dom[$key]['attribute']['color']) AND (!TCPDF_STATIC::empty_string($dom[$key]['attribute']['color']))) { - $dom[$key]['fgcolor'] = TCPDF_COLORS::convertHTMLColorToDec($dom[$key]['attribute']['color'], $this->spot_colors); - } elseif (!isset($dom[$key]['style']['color']) AND ($dom[$key]['value'] == 'a')) { - $dom[$key]['fgcolor'] = $this->htmlLinkColorArray; - } - // set background color attribute - if (isset($dom[$key]['attribute']['bgcolor']) AND (!TCPDF_STATIC::empty_string($dom[$key]['attribute']['bgcolor']))) { - $dom[$key]['bgcolor'] = TCPDF_COLORS::convertHTMLColorToDec($dom[$key]['attribute']['bgcolor'], $this->spot_colors); - } - // set stroke color attribute - if (isset($dom[$key]['attribute']['strokecolor']) AND (!TCPDF_STATIC::empty_string($dom[$key]['attribute']['strokecolor']))) { - $dom[$key]['strokecolor'] = TCPDF_COLORS::convertHTMLColorToDec($dom[$key]['attribute']['strokecolor'], $this->spot_colors); - } - // check for width attribute - if (isset($dom[$key]['attribute']['width'])) { - $dom[$key]['width'] = $dom[$key]['attribute']['width']; - } - // check for height attribute - if (isset($dom[$key]['attribute']['height'])) { - $dom[$key]['height'] = $dom[$key]['attribute']['height']; - } - // check for text alignment - if (isset($dom[$key]['attribute']['align']) AND (!TCPDF_STATIC::empty_string($dom[$key]['attribute']['align'])) AND ($dom[$key]['value'] !== 'img')) { - $dom[$key]['align'] = strtoupper($dom[$key]['attribute']['align'][0]); - } - // check for text rendering mode (the following attributes do not exist in HTML) - if (isset($dom[$key]['attribute']['stroke'])) { - // font stroke width - $dom[$key]['stroke'] = $this->getHTMLUnitToUnits($dom[$key]['attribute']['stroke'], $dom[$key]['fontsize'], 'pt', true); - } - if (isset($dom[$key]['attribute']['fill'])) { - // font fill - if ($dom[$key]['attribute']['fill'] == 'true') { - $dom[$key]['fill'] = true; - } else { - $dom[$key]['fill'] = false; - } - } - if (isset($dom[$key]['attribute']['clip'])) { - // clipping mode - if ($dom[$key]['attribute']['clip'] == 'true') { - $dom[$key]['clip'] = true; - } else { - $dom[$key]['clip'] = false; - } - } - } // end opening tag - } else { - // text - $dom[$key]['tag'] = false; - $dom[$key]['block'] = false; - $dom[$key]['parent'] = end($level); - $dom[$key]['dir'] = $dom[$dom[$key]['parent']]['dir']; - if (!empty($dom[$dom[$key]['parent']]['text-transform'])) { - // text-transform for unicode requires mb_convert_case (Multibyte String Functions) - if (function_exists('mb_convert_case')) { - $ttm = array('capitalize' => MB_CASE_TITLE, 'uppercase' => MB_CASE_UPPER, 'lowercase' => MB_CASE_LOWER); - if (isset($ttm[$dom[$dom[$key]['parent']]['text-transform']])) { - $element = mb_convert_case($element, $ttm[$dom[$dom[$key]['parent']]['text-transform']], $this->encoding); - } - } elseif (!$this->isunicode) { - switch ($dom[$dom[$key]['parent']]['text-transform']) { - case 'capitalize': { - $element = ucwords(strtolower($element)); - break; - } - case 'uppercase': { - $element = strtoupper($element); - break; - } - case 'lowercase': { - $element = strtolower($element); - break; - } - } - } - $element = preg_replace("/&NBSP;/i", "&nbsp;", $element); - } - $dom[$key]['value'] = stripslashes($this->unhtmlentities($element)); - } - ++$elkey; - ++$key; - } - return $dom; - } - - /** - * Returns the string used to find spaces - * @return string - * @protected - * @author Nicola Asuni - * @since 4.8.024 (2010-01-15) - */ - protected function getSpaceString() { - $spacestr = chr(32); - if ($this->isUnicodeFont()) { - $spacestr = chr(0).chr(32); - } - return $spacestr; - } - - /** - * Return an hash code used to ensure that the serialized data has been generated by this TCPDF instance. - * @param string $data serialized data - * @return string - * @public static - */ - protected function getHashForTCPDFtagParams($data) { - return md5(strlen($data).$this->file_id.$data); - } - - /** - * Serialize an array of parameters to be used with TCPDF tag in HTML code. - * @param array $data parameters array - * @return string containing serialized data - * @public static - */ - public function serializeTCPDFtagParameters($data) { - $encoded = urlencode(json_encode($data)); - return $this->getHashForTCPDFtagParams($encoded).$encoded; - } - - /** - * Unserialize parameters to be used with TCPDF tag in HTML code. - * @param string $data serialized data - * @return array containing unserialized data - * @protected static - */ - protected function unserializeTCPDFtagParameters($data) { - $hash = substr($data, 0, 32); - $encoded = substr($data, 32); - if ($hash != $this->getHashForTCPDFtagParams($encoded)) { - $this->Error('Invalid parameters'); - } - return json_decode(urldecode($encoded), true); - } - - /** - * Prints a cell (rectangular area) with optional borders, background color and html text string. - * The upper-left corner of the cell corresponds to the current position. After the call, the current position moves to the right or to the next line.<br /> - * If automatic page breaking is enabled and the cell goes beyond the limit, a page break is done before outputting. - * IMPORTANT: The HTML must be well formatted - try to clean-up it using an application like HTML-Tidy before submitting. - * Supported tags are: a, b, blockquote, br, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, img, li, ol, p, pre, small, span, strong, sub, sup, table, tcpdf, td, th, thead, tr, tt, u, ul - * NOTE: all the HTML attributes must be enclosed in double-quote. - * @param float $w Cell width. If 0, the cell extends up to the right margin. - * @param float $h Cell minimum height. The cell extends automatically if needed. - * @param float|null $x upper-left corner X coordinate - * @param float|null $y upper-left corner Y coordinate - * @param string $html html text to print. Default value: empty string. - * @param mixed $border Indicates if borders must be drawn around the cell. The value can be a number:<ul><li>0: no border (default)</li><li>1: frame</li></ul> or a string containing some or all of the following characters (in any order):<ul><li>L: left</li><li>T: top</li><li>R: right</li><li>B: bottom</li></ul> or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - * @param int $ln Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right (or left for RTL language)</li><li>1: to the beginning of the next line</li><li>2: below</li></ul> -Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0. - * @param boolean $fill Indicates if the cell background must be painted (true) or transparent (false). - * @param boolean $reseth if true reset the last cell height (default true). - * @param string $align Allows to center or align the text. Possible values are:<ul><li>L : left align</li><li>C : center</li><li>R : right align</li><li>'' : empty string : left for LTR or right for RTL</li></ul> - * @param boolean $autopadding if true, uses internal padding and automatically adjust it to account for line width. - * @see Multicell(), writeHTML() - * @public - */ - public function writeHTMLCell($w, $h, $x, $y, $html='', $border=0, $ln=0, $fill=false, $reseth=true, $align='', $autopadding=true) { - return $this->MultiCell($w, $h, $html, $border, $align, $fill, $ln, $x, $y, $reseth, 0, true, $autopadding, 0, 'T', false); - } - - /** - * Allows to preserve some HTML formatting (limited support).<br /> - * IMPORTANT: The HTML must be well formatted - try to clean-up it using an application like HTML-Tidy before submitting. - * Supported tags are: a, b, blockquote, br, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, img, li, ol, p, pre, small, span, strong, sub, sup, table, tcpdf, td, th, thead, tr, tt, u, ul - * NOTE: all the HTML attributes must be enclosed in double-quote. - * @param string $html text to display - * @param boolean $ln if true add a new line after text (default = true) - * @param boolean $fill Indicates if the background must be painted (true) or transparent (false). - * @param boolean $reseth if true reset the last cell height (default false). - * @param boolean $cell if true add the current left (or right for RTL) padding to each Write (default false). - * @param string $align Allows to center or align the text. Possible values are:<ul><li>L : left align</li><li>C : center</li><li>R : right align</li><li>'' : empty string : left for LTR or right for RTL</li></ul> - * @public - */ - public function writeHTML($html, $ln=true, $fill=false, $reseth=false, $cell=false, $align='') { - $gvars = $this->getGraphicVars(); - // store current values - $prev_cell_margin = $this->cell_margin; - $prev_cell_padding = $this->cell_padding; - $prevPage = $this->page; - $prevlMargin = $this->lMargin; - $prevrMargin = $this->rMargin; - $curfontname = $this->FontFamily; - $curfontstyle = $this->FontStyle; - $curfontsize = $this->FontSizePt; - $curfontascent = $this->getFontAscent($curfontname, $curfontstyle, $curfontsize); - $curfontdescent = $this->getFontDescent($curfontname, $curfontstyle, $curfontsize); - $curfontstretcing = $this->font_stretching; - $curfonttracking = $this->font_spacing; - $this->newline = true; - $newline = true; - $startlinepage = $this->page; - $minstartliney = $this->y; - $maxbottomliney = 0; - $startlinex = $this->x; - $startliney = $this->y; - $yshift = 0; - $loop = 0; - $curpos = 0; - $this_method_vars = array(); - $undo = false; - $fontaligned = false; - $reverse_dir = false; // true when the text direction is reversed - $this->premode = false; - if ($this->inxobj) { - // we are inside an XObject template - $pask = count($this->xobjects[$this->xobjid]['annotations']); - } elseif (isset($this->PageAnnots[$this->page])) { - $pask = count($this->PageAnnots[$this->page]); - } else { - $pask = 0; - } - if ($this->inxobj) { - // we are inside an XObject template - $startlinepos = strlen($this->xobjects[$this->xobjid]['outdata']); - } elseif (!$this->InFooter) { - if (isset($this->footerlen[$this->page])) { - $this->footerpos[$this->page] = $this->pagelen[$this->page] - $this->footerlen[$this->page]; - } else { - $this->footerpos[$this->page] = $this->pagelen[$this->page]; - } - $startlinepos = $this->footerpos[$this->page]; - } else { - // we are inside the footer - $startlinepos = $this->pagelen[$this->page]; - } - $lalign = $align; - $plalign = $align; - if ($this->rtl) { - $w = $this->x - $this->lMargin; - } else { - $w = $this->w - $this->rMargin - $this->x; - } - $w -= ($this->cell_padding['L'] + $this->cell_padding['R']); - if ($cell) { - if ($this->rtl) { - $this->x -= $this->cell_padding['R']; - $this->lMargin += $this->cell_padding['L']; - } else { - $this->x += $this->cell_padding['L']; - $this->rMargin += $this->cell_padding['R']; - } - } - if ($this->customlistindent >= 0) { - $this->listindent = $this->customlistindent; - } else { - $this->listindent = $this->GetStringWidth('000000'); - } - $this->listindentlevel = 0; - // save previous states - $prev_cell_height_ratio = $this->cell_height_ratio; - $prev_listnum = $this->listnum; - $prev_listordered = $this->listordered; - $prev_listcount = $this->listcount; - $prev_lispacer = $this->lispacer; - $this->listnum = 0; - $this->listordered = array(); - $this->listcount = array(); - $this->lispacer = ''; - if ((TCPDF_STATIC::empty_string($this->lasth)) OR ($reseth)) { - // reset row height - $this->resetLastH(); - } - $dom = $this->getHtmlDomArray($html); - $maxel = count($dom); - $key = 0; - while ($key < $maxel) { - if ($dom[$key]['tag'] AND $dom[$key]['opening'] AND $dom[$key]['hide']) { - // store the node key - $hidden_node_key = $key; - if ($dom[$key]['self']) { - // skip just this self-closing tag - ++$key; - } else { - // skip this and all children tags - while (($key < $maxel) AND (!$dom[$key]['tag'] OR $dom[$key]['opening'] OR ($dom[$key]['parent'] != $hidden_node_key))) { - // skip hidden objects - ++$key; - } - ++$key; - } - } - if ($dom[$key]['tag'] AND isset($dom[$key]['attribute']['pagebreak'])) { - // check for pagebreak - if (($dom[$key]['attribute']['pagebreak'] == 'true') OR ($dom[$key]['attribute']['pagebreak'] == 'left') OR ($dom[$key]['attribute']['pagebreak'] == 'right')) { - // add a page (or trig AcceptPageBreak() for multicolumn mode) - $this->checkPageBreak($this->PageBreakTrigger + 1); - $this->htmlvspace = ($this->PageBreakTrigger + 1); - } - if ((($dom[$key]['attribute']['pagebreak'] == 'left') AND (((!$this->rtl) AND (($this->page % 2) == 0)) OR (($this->rtl) AND (($this->page % 2) != 0)))) - OR (($dom[$key]['attribute']['pagebreak'] == 'right') AND (((!$this->rtl) AND (($this->page % 2) != 0)) OR (($this->rtl) AND (($this->page % 2) == 0))))) { - // add a page (or trig AcceptPageBreak() for multicolumn mode) - $this->checkPageBreak($this->PageBreakTrigger + 1); - $this->htmlvspace = ($this->PageBreakTrigger + 1); - } - } - if ($dom[$key]['tag'] AND $dom[$key]['opening'] AND isset($dom[$key]['attribute']['nobr']) AND ($dom[$key]['attribute']['nobr'] == 'true')) { - if (isset($dom[($dom[$key]['parent'])]['attribute']['nobr']) AND ($dom[($dom[$key]['parent'])]['attribute']['nobr'] == 'true')) { - $dom[$key]['attribute']['nobr'] = false; - } else { - // store current object - $this->startTransaction(); - // save this method vars - $this_method_vars['html'] = $html; - $this_method_vars['ln'] = $ln; - $this_method_vars['fill'] = $fill; - $this_method_vars['reseth'] = $reseth; - $this_method_vars['cell'] = $cell; - $this_method_vars['align'] = $align; - $this_method_vars['gvars'] = $gvars; - $this_method_vars['prevPage'] = $prevPage; - $this_method_vars['prev_cell_margin'] = $prev_cell_margin; - $this_method_vars['prev_cell_padding'] = $prev_cell_padding; - $this_method_vars['prevlMargin'] = $prevlMargin; - $this_method_vars['prevrMargin'] = $prevrMargin; - $this_method_vars['curfontname'] = $curfontname; - $this_method_vars['curfontstyle'] = $curfontstyle; - $this_method_vars['curfontsize'] = $curfontsize; - $this_method_vars['curfontascent'] = $curfontascent; - $this_method_vars['curfontdescent'] = $curfontdescent; - $this_method_vars['curfontstretcing'] = $curfontstretcing; - $this_method_vars['curfonttracking'] = $curfonttracking; - $this_method_vars['minstartliney'] = $minstartliney; - $this_method_vars['maxbottomliney'] = $maxbottomliney; - $this_method_vars['yshift'] = $yshift; - $this_method_vars['startlinepage'] = $startlinepage; - $this_method_vars['startlinepos'] = $startlinepos; - $this_method_vars['startlinex'] = $startlinex; - $this_method_vars['startliney'] = $startliney; - $this_method_vars['newline'] = $newline; - $this_method_vars['loop'] = $loop; - $this_method_vars['curpos'] = $curpos; - $this_method_vars['pask'] = $pask; - $this_method_vars['lalign'] = $lalign; - $this_method_vars['plalign'] = $plalign; - $this_method_vars['w'] = $w; - $this_method_vars['prev_cell_height_ratio'] = $prev_cell_height_ratio; - $this_method_vars['prev_listnum'] = $prev_listnum; - $this_method_vars['prev_listordered'] = $prev_listordered; - $this_method_vars['prev_listcount'] = $prev_listcount; - $this_method_vars['prev_lispacer'] = $prev_lispacer; - $this_method_vars['fontaligned'] = $fontaligned; - $this_method_vars['key'] = $key; - $this_method_vars['dom'] = $dom; - } - } - // print THEAD block - if (($dom[$key]['value'] == 'tr') AND isset($dom[$key]['thead']) AND $dom[$key]['thead']) { - if (isset($dom[$key]['parent']) AND isset($dom[$dom[$key]['parent']]['thead']) AND !TCPDF_STATIC::empty_string($dom[$dom[$key]['parent']]['thead'])) { - $this->inthead = true; - // print table header (thead) - $this->writeHTML($this->thead, false, false, false, false, ''); - // check if we are on a new page or on a new column - if (($this->y < $this->start_transaction_y) OR ($this->checkPageBreak($this->lasth, '', false))) { - // we are on a new page or on a new column and the total object height is less than the available vertical space. - // restore previous object - $this->rollbackTransaction(true); - // restore previous values - foreach ($this_method_vars as $vkey => $vval) { - $$vkey = $vval; - } - // disable table header - $tmp_thead = $this->thead; - $this->thead = ''; - // add a page (or trig AcceptPageBreak() for multicolumn mode) - $pre_y = $this->y; - if ((!$this->checkPageBreak($this->PageBreakTrigger + 1)) AND ($this->y < $pre_y)) { - // fix for multicolumn mode - $startliney = $this->y; - } - $this->start_transaction_page = $this->page; - $this->start_transaction_y = $this->y; - // restore table header - $this->thead = $tmp_thead; - // fix table border properties - if (isset($dom[$dom[$key]['parent']]['attribute']['cellspacing'])) { - $tmp_cellspacing = $this->getHTMLUnitToUnits($dom[$dom[$key]['parent']]['attribute']['cellspacing'], 1, 'px'); - } elseif (isset($dom[$dom[$key]['parent']]['border-spacing'])) { - $tmp_cellspacing = $dom[$dom[$key]['parent']]['border-spacing']['V']; - } else { - $tmp_cellspacing = 0; - } - $dom[$dom[$key]['parent']]['borderposition']['page'] = $this->page; - $dom[$dom[$key]['parent']]['borderposition']['column'] = $this->current_column; - $dom[$dom[$key]['parent']]['borderposition']['y'] = $this->y + $tmp_cellspacing; - $xoffset = ($this->x - $dom[$dom[$key]['parent']]['borderposition']['x']); - $dom[$dom[$key]['parent']]['borderposition']['x'] += $xoffset; - $dom[$dom[$key]['parent']]['borderposition']['xmax'] += $xoffset; - // print table header (thead) - $this->writeHTML($this->thead, false, false, false, false, ''); - } - } - // move $key index forward to skip THEAD block - while ( ($key < $maxel) AND (!( - ($dom[$key]['tag'] AND $dom[$key]['opening'] AND ($dom[$key]['value'] == 'tr') AND (!isset($dom[$key]['thead']) OR !$dom[$key]['thead'])) - OR ($dom[$key]['tag'] AND (!$dom[$key]['opening']) AND ($dom[$key]['value'] == 'table'))) )) { - ++$key; - } - } - if ($dom[$key]['tag'] OR ($key == 0)) { - if ((($dom[$key]['value'] == 'table') OR ($dom[$key]['value'] == 'tr')) AND (isset($dom[$key]['align']))) { - $dom[$key]['align'] = ($this->rtl) ? 'R' : 'L'; - } - // vertically align image in line - if ((!$this->newline) AND ($dom[$key]['value'] == 'img') AND (isset($dom[$key]['height'])) AND ($dom[$key]['height'] > 0)) { - // get image height - $imgh = $this->getHTMLUnitToUnits($dom[$key]['height'], ($dom[$key]['fontsize'] / $this->k), 'px'); - $autolinebreak = false; - if (!empty($dom[$key]['width'])) { - $imgw = $this->getHTMLUnitToUnits($dom[$key]['width'], ($dom[$key]['fontsize'] / $this->k), 'px', false); - if (($imgw <= ($this->w - $this->lMargin - $this->rMargin - $this->cell_padding['L'] - $this->cell_padding['R'])) - AND ((($this->rtl) AND (($this->x - $imgw) < ($this->lMargin + $this->cell_padding['L']))) - OR ((!$this->rtl) AND (($this->x + $imgw) > ($this->w - $this->rMargin - $this->cell_padding['R']))))) { - // add automatic line break - $autolinebreak = true; - $this->Ln('', $cell); - if ((!$dom[($key-1)]['tag']) AND ($dom[($key-1)]['value'] == ' ')) { - // go back to evaluate this line break - --$key; - } - } - } - if (!$autolinebreak) { - if ($this->inPageBody()) { - $pre_y = $this->y; - // check for page break - if ((!$this->checkPageBreak($imgh)) AND ($this->y < $pre_y)) { - // fix for multicolumn mode - $startliney = $this->y; - } - } - if ($this->page > $startlinepage) { - // fix line splitted over two pages - if (isset($this->footerlen[$startlinepage])) { - $curpos = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage]; - } - // line to be moved one page forward - $pagebuff = $this->getPageBuffer($startlinepage); - $linebeg = substr($pagebuff, $startlinepos, ($curpos - $startlinepos)); - $tstart = substr($pagebuff, 0, $startlinepos); - $tend = substr($this->getPageBuffer($startlinepage), $curpos); - // remove line from previous page - $this->setPageBuffer($startlinepage, $tstart.''.$tend); - $pagebuff = $this->getPageBuffer($this->page); - $tstart = substr($pagebuff, 0, $this->cntmrk[$this->page]); - $tend = substr($pagebuff, $this->cntmrk[$this->page]); - // add line start to current page - $yshift = ($minstartliney - $this->y); - if ($fontaligned) { - $yshift += ($curfontsize / $this->k); - } - $try = sprintf('1 0 0 1 0 %F cm', ($yshift * $this->k)); - $this->setPageBuffer($this->page, $tstart."\nq\n".$try."\n".$linebeg."\nQ\n".$tend); - // shift the annotations and links - if (isset($this->PageAnnots[$this->page])) { - $next_pask = count($this->PageAnnots[$this->page]); - } else { - $next_pask = 0; - } - if (isset($this->PageAnnots[$startlinepage])) { - foreach ($this->PageAnnots[$startlinepage] as $pak => $pac) { - if ($pak >= $pask) { - $this->PageAnnots[$this->page][] = $pac; - unset($this->PageAnnots[$startlinepage][$pak]); - $npak = count($this->PageAnnots[$this->page]) - 1; - $this->PageAnnots[$this->page][$npak]['y'] -= $yshift; - } - } - } - $pask = $next_pask; - $startlinepos = $this->cntmrk[$this->page]; - $startlinepage = $this->page; - $startliney = $this->y; - $this->newline = false; - } - $this->y += ($this->getCellHeight($curfontsize / $this->k) - ($curfontdescent * $this->cell_height_ratio) - $imgh); - $minstartliney = min($this->y, $minstartliney); - $maxbottomliney = ($startliney + $this->getCellHeight($curfontsize / $this->k)); - } - } elseif (isset($dom[$key]['fontname']) OR isset($dom[$key]['fontstyle']) OR isset($dom[$key]['fontsize']) OR isset($dom[$key]['line-height'])) { - // account for different font size - $pfontname = $curfontname; - $pfontstyle = $curfontstyle; - $pfontsize = $curfontsize; - $fontname = (isset($dom[$key]['fontname']) ? $dom[$key]['fontname'] : $curfontname); - $fontstyle = (isset($dom[$key]['fontstyle']) ? $dom[$key]['fontstyle'] : $curfontstyle); - $fontsize = (isset($dom[$key]['fontsize']) ? $dom[$key]['fontsize'] : $curfontsize); - $fontascent = $this->getFontAscent($fontname, $fontstyle, $fontsize); - $fontdescent = $this->getFontDescent($fontname, $fontstyle, $fontsize); - if (($fontname != $curfontname) OR ($fontstyle != $curfontstyle) OR ($fontsize != $curfontsize) - OR ($this->cell_height_ratio != $dom[$key]['line-height']) - OR ($dom[$key]['tag'] AND $dom[$key]['opening'] AND ($dom[$key]['value'] == 'li')) ) { - if (($key < ($maxel - 1)) AND ( - ($dom[$key]['tag'] AND $dom[$key]['opening'] AND ($dom[$key]['value'] == 'li')) - OR ($this->cell_height_ratio != $dom[$key]['line-height']) - OR (!$this->newline AND is_numeric($fontsize) AND is_numeric($curfontsize) - AND ($fontsize >= 0) AND ($curfontsize >= 0) - AND (($fontsize != $curfontsize) OR ($fontstyle != $curfontstyle) OR ($fontname != $curfontname))) - )) { - if ($this->page > $startlinepage) { - // fix lines splitted over two pages - if (isset($this->footerlen[$startlinepage])) { - $curpos = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage]; - } - // line to be moved one page forward - $pagebuff = $this->getPageBuffer($startlinepage); - $linebeg = substr($pagebuff, $startlinepos, ($curpos - $startlinepos)); - $tstart = substr($pagebuff, 0, $startlinepos); - $tend = substr($this->getPageBuffer($startlinepage), $curpos); - // remove line start from previous page - $this->setPageBuffer($startlinepage, $tstart.''.$tend); - $pagebuff = $this->getPageBuffer($this->page); - $tstart = substr($pagebuff, 0, $this->cntmrk[$this->page]); - $tend = substr($pagebuff, $this->cntmrk[$this->page]); - // add line start to current page - $yshift = ($minstartliney - $this->y); - $try = sprintf('1 0 0 1 0 %F cm', ($yshift * $this->k)); - $this->setPageBuffer($this->page, $tstart."\nq\n".$try."\n".$linebeg."\nQ\n".$tend); - // shift the annotations and links - if (isset($this->PageAnnots[$this->page])) { - $next_pask = count($this->PageAnnots[$this->page]); - } else { - $next_pask = 0; - } - if (isset($this->PageAnnots[$startlinepage])) { - foreach ($this->PageAnnots[$startlinepage] as $pak => $pac) { - if ($pak >= $pask) { - $this->PageAnnots[$this->page][] = $pac; - unset($this->PageAnnots[$startlinepage][$pak]); - $npak = count($this->PageAnnots[$this->page]) - 1; - $this->PageAnnots[$this->page][$npak]['y'] -= $yshift; - } - } - } - $pask = $next_pask; - $startlinepos = $this->cntmrk[$this->page]; - $startlinepage = $this->page; - $startliney = $this->y; - } - if (!isset($dom[$key]['line-height'])) { - $dom[$key]['line-height'] = $this->cell_height_ratio; - } - if (!$dom[$key]['block']) { - if (!(isset($dom[($key + 1)]) AND $dom[($key + 1)]['tag'] AND (!$dom[($key + 1)]['opening']) AND ($dom[($key + 1)]['value'] != 'li') AND $dom[$key]['tag'] AND (!$dom[$key]['opening']))) { - $this->y += (((($curfontsize * $this->cell_height_ratio) - ($fontsize * $dom[$key]['line-height'])) / $this->k) + $curfontascent - $fontascent - $curfontdescent + $fontdescent) / 2; - } - if (($dom[$key]['value'] != 'sup') AND ($dom[$key]['value'] != 'sub')) { - $current_line_align_data = array($key, $minstartliney, $maxbottomliney); - if (isset($line_align_data) AND (($line_align_data[0] == ($key - 1)) OR (($line_align_data[0] == ($key - 2)) AND (isset($dom[($key - 1)])) AND (preg_match('/^([\s]+)$/', $dom[($key - 1)]['value']) > 0)))) { - $minstartliney = min($this->y, $line_align_data[1]); - $maxbottomliney = max(($this->y + $this->getCellHeight($fontsize / $this->k)), $line_align_data[2]); - } else { - $minstartliney = min($this->y, $minstartliney); - $maxbottomliney = max(($this->y + $this->getCellHeight($fontsize / $this->k)), $maxbottomliney); - } - $line_align_data = $current_line_align_data; - } - } - $this->cell_height_ratio = $dom[$key]['line-height']; - $fontaligned = true; - } - $this->setFont($fontname, $fontstyle, $fontsize); - // reset row height - $this->resetLastH(); - $curfontname = $fontname; - $curfontstyle = $fontstyle; - $curfontsize = $fontsize; - $curfontascent = $fontascent; - $curfontdescent = $fontdescent; - } - } - // set text rendering mode - $textstroke = isset($dom[$key]['stroke']) ? $dom[$key]['stroke'] : $this->textstrokewidth; - $textfill = isset($dom[$key]['fill']) ? $dom[$key]['fill'] : (($this->textrendermode % 2) == 0); - $textclip = isset($dom[$key]['clip']) ? $dom[$key]['clip'] : ($this->textrendermode > 3); - $this->setTextRenderingMode($textstroke, $textfill, $textclip); - if (isset($dom[$key]['font-stretch']) AND ($dom[$key]['font-stretch'] !== false)) { - $this->setFontStretching($dom[$key]['font-stretch']); - } - if (isset($dom[$key]['letter-spacing']) AND ($dom[$key]['letter-spacing'] !== false)) { - $this->setFontSpacing($dom[$key]['letter-spacing']); - } - if (($plalign == 'J') AND $dom[$key]['block']) { - $plalign = ''; - } - // get current position on page buffer - $curpos = $this->pagelen[$startlinepage]; - if (isset($dom[$key]['bgcolor']) AND ($dom[$key]['bgcolor'] !== false)) { - $this->setFillColorArray($dom[$key]['bgcolor']); - $wfill = true; - } else { - $wfill = $fill | false; - } - if (isset($dom[$key]['fgcolor']) AND ($dom[$key]['fgcolor'] !== false)) { - $this->setTextColorArray($dom[$key]['fgcolor']); - } - if (isset($dom[$key]['strokecolor']) AND ($dom[$key]['strokecolor'] !== false)) { - $this->setDrawColorArray($dom[$key]['strokecolor']); - } - if (isset($dom[$key]['align'])) { - $lalign = $dom[$key]['align']; - } - if (TCPDF_STATIC::empty_string($lalign)) { - $lalign = $align; - } - } - // align lines - if ($this->newline AND (strlen($dom[$key]['value']) > 0) AND ($dom[$key]['value'] != 'td') AND ($dom[$key]['value'] != 'th')) { - $newline = true; - $fontaligned = false; - // we are at the beginning of a new line - if (isset($startlinex)) { - $yshift = ($minstartliney - $startliney); - if (($yshift > 0) OR ($this->page > $startlinepage)) { - $yshift = 0; - } - $t_x = 0; - // the last line must be shifted to be aligned as requested - $linew = abs($this->endlinex - $startlinex); - if ($this->inxobj) { - // we are inside an XObject template - $pstart = substr($this->xobjects[$this->xobjid]['outdata'], 0, $startlinepos); - if (isset($opentagpos)) { - $midpos = $opentagpos; - } else { - $midpos = 0; - } - if ($midpos > 0) { - $pmid = substr($this->xobjects[$this->xobjid]['outdata'], $startlinepos, ($midpos - $startlinepos)); - $pend = substr($this->xobjects[$this->xobjid]['outdata'], $midpos); - } else { - $pmid = substr($this->xobjects[$this->xobjid]['outdata'], $startlinepos); - $pend = ''; - } - } else { - $pstart = substr($this->getPageBuffer($startlinepage), 0, $startlinepos); - if (isset($opentagpos) AND isset($this->footerlen[$startlinepage]) AND (!$this->InFooter)) { - $this->footerpos[$startlinepage] = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage]; - $midpos = min($opentagpos, $this->footerpos[$startlinepage]); - } elseif (isset($opentagpos)) { - $midpos = $opentagpos; - } elseif (isset($this->footerlen[$startlinepage]) AND (!$this->InFooter)) { - $this->footerpos[$startlinepage] = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage]; - $midpos = $this->footerpos[$startlinepage]; - } else { - $midpos = 0; - } - if ($midpos > 0) { - $pmid = substr($this->getPageBuffer($startlinepage), $startlinepos, ($midpos - $startlinepos)); - $pend = substr($this->getPageBuffer($startlinepage), $midpos); - } else { - $pmid = substr($this->getPageBuffer($startlinepage), $startlinepos); - $pend = ''; - } - } - if ((isset($plalign) AND ((($plalign == 'C') OR ($plalign == 'J') OR (($plalign == 'R') AND (!$this->rtl)) OR (($plalign == 'L') AND ($this->rtl)))))) { - // calculate shifting amount - $tw = $w; - if (($plalign == 'J') AND $this->isRTLTextDir() AND ($this->num_columns > 1)) { - $tw += $this->cell_padding['R']; - } - if ($this->lMargin != $prevlMargin) { - $tw += ($prevlMargin - $this->lMargin); - } - if ($this->rMargin != $prevrMargin) { - $tw += ($prevrMargin - $this->rMargin); - } - $one_space_width = $this->GetStringWidth(chr(32)); - $no = 0; // number of spaces on a line contained on a single block - if ($this->isRTLTextDir()) { // RTL - // remove left space if exist - $pos1 = TCPDF_STATIC::revstrpos($pmid, '[('); - if ($pos1 > 0) { - $pos1 = intval($pos1); - if ($this->isUnicodeFont()) { - $pos2 = intval(TCPDF_STATIC::revstrpos($pmid, '[('.chr(0).chr(32))); - $spacelen = 2; - } else { - $pos2 = intval(TCPDF_STATIC::revstrpos($pmid, '[('.chr(32))); - $spacelen = 1; - } - if ($pos1 == $pos2) { - $pmid = substr($pmid, 0, ($pos1 + 2)).substr($pmid, ($pos1 + 2 + $spacelen)); - if (substr($pmid, $pos1, 4) == '[()]') { - $linew -= $one_space_width; - } elseif ($pos1 == strpos($pmid, '[(')) { - $no = 1; - } - } - } - } else { // LTR - // remove right space if exist - $pos1 = TCPDF_STATIC::revstrpos($pmid, ')]'); - if ($pos1 > 0) { - $pos1 = intval($pos1); - if ($this->isUnicodeFont()) { - $pos2 = intval(TCPDF_STATIC::revstrpos($pmid, chr(0).chr(32).')]')) + 2; - $spacelen = 2; - } else { - $pos2 = intval(TCPDF_STATIC::revstrpos($pmid, chr(32).')]')) + 1; - $spacelen = 1; - } - if ($pos1 == $pos2) { - $pmid = substr($pmid, 0, ($pos1 - $spacelen)).substr($pmid, $pos1); - $linew -= $one_space_width; - } - } - } - $mdiff = ($tw - $linew); - if ($plalign == 'C') { - if ($this->rtl) { - $t_x = -($mdiff / 2); - } else { - $t_x = ($mdiff / 2); - } - } elseif ($plalign == 'R') { - // right alignment on LTR document - $t_x = $mdiff; - } elseif ($plalign == 'L') { - // left alignment on RTL document - $t_x = -$mdiff; - } elseif (($plalign == 'J') AND ($plalign == $lalign)) { - // Justification - if ($this->isRTLTextDir()) { - // align text on the left - $t_x = -$mdiff; - } - $ns = 0; // number of spaces - $pmidtemp = $pmid; - // escape special characters - $pmidtemp = preg_replace('/[\\\][\(]/x', '\\#!#OP#!#', $pmidtemp); - $pmidtemp = preg_replace('/[\\\][\)]/x', '\\#!#CP#!#', $pmidtemp); - // search spaces - if (preg_match_all('/\[\(([^\)]*)\)\]/x', $pmidtemp, $lnstring, PREG_PATTERN_ORDER)) { - $spacestr = $this->getSpaceString(); - $maxkk = count($lnstring[1]) - 1; - for ($kk=0; $kk <= $maxkk; ++$kk) { - // restore special characters - $lnstring[1][$kk] = str_replace('#!#OP#!#', '(', $lnstring[1][$kk]); - $lnstring[1][$kk] = str_replace('#!#CP#!#', ')', $lnstring[1][$kk]); - // store number of spaces on the strings - $lnstring[2][$kk] = substr_count($lnstring[1][$kk], $spacestr); - // count total spaces on line - $ns += $lnstring[2][$kk]; - $lnstring[3][$kk] = $ns; - } - if ($ns == 0) { - $ns = 1; - } - // calculate additional space to add to each existing space - $spacewidth = ($mdiff / ($ns - $no)) * $this->k; - if ($this->FontSize <= 0) { - $this->FontSize = 1; - } - $spacewidthu = -1000 * ($mdiff + (($ns + $no) * $one_space_width)) / $ns / $this->FontSize; - if ($this->font_spacing != 0) { - // fixed spacing mode - $osw = -1000 * $this->font_spacing / $this->FontSize; - $spacewidthu += $osw; - } - $nsmax = $ns; - $ns = 0; - reset($lnstring); - $offset = 0; - $strcount = 0; - $prev_epsposbeg = 0; - $textpos = 0; - if ($this->isRTLTextDir()) { - $textpos = $this->wPt; - } - while (preg_match('/([0-9\.\+\-]*)[\s](Td|cm|m|l|c|re)[\s]/x', $pmid, $strpiece, PREG_OFFSET_CAPTURE, $offset) == 1) { - // check if we are inside a string section '[( ... )]' - $stroffset = strpos($pmid, '[(', $offset); - if (($stroffset !== false) AND ($stroffset <= $strpiece[2][1])) { - // set offset to the end of string section - $offset = strpos($pmid, ')]', $stroffset); - while (($offset !== false) AND ($pmid[($offset - 1)] == '\\')) { - $offset = strpos($pmid, ')]', ($offset + 1)); - } - if ($offset === false) { - $this->Error('HTML Justification: malformed PDF code.'); - } - continue; - } - if ($this->isRTLTextDir()) { - $spacew = ($spacewidth * ($nsmax - $ns)); - } else { - $spacew = ($spacewidth * $ns); - } - $offset = $strpiece[2][1] + strlen($strpiece[2][0]); - $epsposend = strpos($pmid, $this->epsmarker.'Q', $offset); - if ($epsposend !== null) { - $epsposend += strlen($this->epsmarker.'Q'); - $epsposbeg = strpos($pmid, 'q'.$this->epsmarker, $offset); - if ($epsposbeg === null) { - $epsposbeg = strpos($pmid, 'q'.$this->epsmarker, ($prev_epsposbeg - 6)); - $prev_epsposbeg = $epsposbeg; - } - if (($epsposbeg > 0) AND ($epsposend > 0) AND ($offset > $epsposbeg) AND ($offset < $epsposend)) { - // shift EPS images - $trx = sprintf('1 0 0 1 %F 0 cm', $spacew); - $pmid_b = substr($pmid, 0, $epsposbeg); - $pmid_m = substr($pmid, $epsposbeg, ($epsposend - $epsposbeg)); - $pmid_e = substr($pmid, $epsposend); - $pmid = $pmid_b."\nq\n".$trx."\n".$pmid_m."\nQ\n".$pmid_e; - $offset = $epsposend; - continue; - } - } - $currentxpos = 0; - // shift blocks of code - switch ($strpiece[2][0]) { - case 'Td': - case 'cm': - case 'm': - case 'l': { - // get current X position - preg_match('/([0-9\.\+\-]*)[\s]('.$strpiece[1][0].')[\s]('.$strpiece[2][0].')([\s]*)/x', $pmid, $xmatches); - if (!isset($xmatches[1])) { - break; - } - $currentxpos = $xmatches[1]; - $textpos = $currentxpos; - if (($strcount <= $maxkk) AND ($strpiece[2][0] == 'Td')) { - $ns = $lnstring[3][$strcount]; - if ($this->isRTLTextDir()) { - $spacew = ($spacewidth * ($nsmax - $ns)); - } - ++$strcount; - } - // justify block - if (preg_match('/([0-9\.\+\-]*)[\s]('.$strpiece[1][0].')[\s]('.$strpiece[2][0].')([\s]*)/x', $pmid, $pmatch) == 1) { - $newpmid = sprintf('%F',(floatval($pmatch[1]) + $spacew)).' '.$pmatch[2].' x*#!#*x'.$pmatch[3].$pmatch[4]; - $pmid = str_replace($pmatch[0], $newpmid, $pmid); - unset($pmatch, $newpmid); - } - break; - } - case 're': { - // justify block - if (!TCPDF_STATIC::empty_string($this->lispacer)) { - $this->lispacer = ''; - break; - } - preg_match('/([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]('.$strpiece[1][0].')[\s](re)([\s]*)/x', $pmid, $xmatches); - if (!isset($xmatches[1])) { - break; - } - $currentxpos = $xmatches[1]; - $x_diff = 0; - $w_diff = 0; - if ($this->isRTLTextDir()) { // RTL - if ($currentxpos < $textpos) { - $x_diff = ($spacewidth * ($nsmax - $lnstring[3][$strcount])); - $w_diff = ($spacewidth * $lnstring[2][$strcount]); - } else { - if ($strcount > 0) { - $x_diff = ($spacewidth * ($nsmax - $lnstring[3][($strcount - 1)])); - $w_diff = ($spacewidth * $lnstring[2][($strcount - 1)]); - } - } - } else { // LTR - if ($currentxpos > $textpos) { - if ($strcount > 0) { - $x_diff = ($spacewidth * $lnstring[3][($strcount - 1)]); - } - $w_diff = ($spacewidth * $lnstring[2][$strcount]); - } else { - if ($strcount > 1) { - $x_diff = ($spacewidth * $lnstring[3][($strcount - 2)]); - } - if ($strcount > 0) { - $w_diff = ($spacewidth * $lnstring[2][($strcount - 1)]); - } - } - } - if (preg_match('/('.$xmatches[1].')[\s]('.$xmatches[2].')[\s]('.$xmatches[3].')[\s]('.$strpiece[1][0].')[\s](re)([\s]*)/x', $pmid, $pmatch) == 1) { - $newx = sprintf('%F',(floatval($pmatch[1]) + $x_diff)); - $neww = sprintf('%F',(floatval($pmatch[3]) + $w_diff)); - $newpmid = $newx.' '.$pmatch[2].' '.$neww.' '.$pmatch[4].' x*#!#*x'.$pmatch[5].$pmatch[6]; - $pmid = str_replace($pmatch[0], $newpmid, $pmid); - unset($pmatch, $newpmid, $newx, $neww); - } - break; - } - case 'c': { - // get current X position - preg_match('/([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]('.$strpiece[1][0].')[\s](c)([\s]*)/x', $pmid, $xmatches); - if (!isset($xmatches[1])) { - break; - } - $currentxpos = $xmatches[1]; - // justify block - if (preg_match('/('.$xmatches[1].')[\s]('.$xmatches[2].')[\s]('.$xmatches[3].')[\s]('.$xmatches[4].')[\s]('.$xmatches[5].')[\s]('.$strpiece[1][0].')[\s](c)([\s]*)/x', $pmid, $pmatch) == 1) { - $newx1 = sprintf('%F',(floatval($pmatch[1]) + $spacew)); - $newx2 = sprintf('%F',(floatval($pmatch[3]) + $spacew)); - $newx3 = sprintf('%F',(floatval($pmatch[5]) + $spacew)); - $newpmid = $newx1.' '.$pmatch[2].' '.$newx2.' '.$pmatch[4].' '.$newx3.' '.$pmatch[6].' x*#!#*x'.$pmatch[7].$pmatch[8]; - $pmid = str_replace($pmatch[0], $newpmid, $pmid); - unset($pmatch, $newpmid, $newx1, $newx2, $newx3); - } - break; - } - } - // shift the annotations and links - $cxpos = ($currentxpos / $this->k); - $lmpos = ($this->lMargin + $this->cell_padding['L'] + $this->feps); - if ($this->inxobj) { - // we are inside an XObject template - foreach ($this->xobjects[$this->xobjid]['annotations'] as $pak => $pac) { - if (($pac['y'] >= $minstartliney) AND (($pac['x'] * $this->k) >= ($currentxpos - $this->feps)) AND (($pac['x'] * $this->k) <= ($currentxpos + $this->feps))) { - if ($cxpos > $lmpos) { - $this->xobjects[$this->xobjid]['annotations'][$pak]['x'] += ($spacew / $this->k); - $this->xobjects[$this->xobjid]['annotations'][$pak]['w'] += (($spacewidth * $pac['numspaces']) / $this->k); - } else { - $this->xobjects[$this->xobjid]['annotations'][$pak]['w'] += (($spacewidth * $pac['numspaces']) / $this->k); - } - break; - } - } - } elseif (isset($this->PageAnnots[$this->page])) { - foreach ($this->PageAnnots[$this->page] as $pak => $pac) { - if (($pac['y'] >= $minstartliney) AND (($pac['x'] * $this->k) >= ($currentxpos - $this->feps)) AND (($pac['x'] * $this->k) <= ($currentxpos + $this->feps))) { - if ($cxpos > $lmpos) { - $this->PageAnnots[$this->page][$pak]['x'] += ($spacew / $this->k); - $this->PageAnnots[$this->page][$pak]['w'] += (($spacewidth * $pac['numspaces']) / $this->k); - } else { - $this->PageAnnots[$this->page][$pak]['w'] += (($spacewidth * $pac['numspaces']) / $this->k); - } - break; - } - } - } - } // end of while - // remove markers - $pmid = str_replace('x*#!#*x', '', $pmid); - if ($this->isUnicodeFont()) { - // multibyte characters - $spacew = $spacewidthu; - if ($this->font_stretching != 100) { - // word spacing is affected by stretching - $spacew /= ($this->font_stretching / 100); - } - // escape special characters - $pos = 0; - $pmid = preg_replace('/[\\\][\(]/x', '\\#!#OP#!#', $pmid); - $pmid = preg_replace('/[\\\][\)]/x', '\\#!#CP#!#', $pmid); - if (preg_match_all('/\[\(([^\)]*)\)\]/x', $pmid, $pamatch) > 0) { - foreach($pamatch[0] as $pk => $pmatch) { - $replace = $pamatch[1][$pk]; - $replace = str_replace('#!#OP#!#', '(', $replace); - $replace = str_replace('#!#CP#!#', ')', $replace); - $newpmid = '[('.str_replace(chr(0).chr(32), ') '.sprintf('%F', $spacew).' (', $replace).')]'; - $pos = strpos($pmid, $pmatch, $pos); - if ($pos !== FALSE) { - $pmid = substr_replace($pmid, $newpmid, $pos, strlen($pmatch)); - } - ++$pos; - } - unset($pamatch); - } - if ($this->inxobj) { - // we are inside an XObject template - $this->xobjects[$this->xobjid]['outdata'] = $pstart."\n".$pmid."\n".$pend; - } else { - $this->setPageBuffer($startlinepage, $pstart."\n".$pmid."\n".$pend); - } - $endlinepos = strlen($pstart."\n".$pmid."\n"); - } else { - // non-unicode (single-byte characters) - if ($this->font_stretching != 100) { - // word spacing (Tw) is affected by stretching - $spacewidth /= ($this->font_stretching / 100); - } - $rs = sprintf('%F Tw', $spacewidth); - $pmid = preg_replace("/\[\(/x", $rs.' [(', $pmid); - if ($this->inxobj) { - // we are inside an XObject template - $this->xobjects[$this->xobjid]['outdata'] = $pstart."\n".$pmid."\nBT 0 Tw ET\n".$pend; - } else { - $this->setPageBuffer($startlinepage, $pstart."\n".$pmid."\nBT 0 Tw ET\n".$pend); - } - $endlinepos = strlen($pstart."\n".$pmid."\nBT 0 Tw ET\n"); - } - } - } // end of J - } // end if $startlinex - if (($t_x != 0) OR ($yshift < 0)) { - // shift the line - $trx = sprintf('1 0 0 1 %F %F cm', ($t_x * $this->k), ($yshift * $this->k)); - $pstart .= "\nq\n".$trx."\n".$pmid."\nQ\n"; - $endlinepos = strlen($pstart); - if ($this->inxobj) { - // we are inside an XObject template - $this->xobjects[$this->xobjid]['outdata'] = $pstart.$pend; - foreach ($this->xobjects[$this->xobjid]['annotations'] as $pak => $pac) { - if ($pak >= $pask) { - $this->xobjects[$this->xobjid]['annotations'][$pak]['x'] += $t_x; - $this->xobjects[$this->xobjid]['annotations'][$pak]['y'] -= $yshift; - } - } - } else { - $this->setPageBuffer($startlinepage, $pstart.$pend); - // shift the annotations and links - if (isset($this->PageAnnots[$this->page])) { - foreach ($this->PageAnnots[$this->page] as $pak => $pac) { - if ($pak >= $pask) { - $this->PageAnnots[$this->page][$pak]['x'] += $t_x; - $this->PageAnnots[$this->page][$pak]['y'] -= $yshift; - } - } - } - } - $this->y -= $yshift; - } - } - $pbrk = $this->checkPageBreak($this->lasth); - $this->newline = false; - $startlinex = $this->x; - $startliney = $this->y; - if ($dom[$dom[$key]['parent']]['value'] == 'sup') { - $startliney -= ((0.3 * $this->FontSizePt) / $this->k); - } elseif ($dom[$dom[$key]['parent']]['value'] == 'sub') { - $startliney -= (($this->FontSizePt / 0.7) / $this->k); - } else { - $minstartliney = $startliney; - $maxbottomliney = ($this->y + $this->getCellHeight($fontsize / $this->k)); - } - $startlinepage = $this->page; - if (isset($endlinepos) AND (!$pbrk)) { - $startlinepos = $endlinepos; - } else { - if ($this->inxobj) { - // we are inside an XObject template - $startlinepos = strlen($this->xobjects[$this->xobjid]['outdata']); - } elseif (!$this->InFooter) { - if (isset($this->footerlen[$this->page])) { - $this->footerpos[$this->page] = $this->pagelen[$this->page] - $this->footerlen[$this->page]; - } else { - $this->footerpos[$this->page] = $this->pagelen[$this->page]; - } - $startlinepos = $this->footerpos[$this->page]; - } else { - $startlinepos = $this->pagelen[$this->page]; - } - } - unset($endlinepos); - $plalign = $lalign; - if (isset($this->PageAnnots[$this->page])) { - $pask = count($this->PageAnnots[$this->page]); - } else { - $pask = 0; - } - if (!($dom[$key]['tag'] AND !$dom[$key]['opening'] AND ($dom[$key]['value'] == 'table') - AND (isset($this->emptypagemrk[$this->page])) - AND ($this->emptypagemrk[$this->page] == $this->pagelen[$this->page]))) { - $this->setFont($fontname, $fontstyle, $fontsize); - if ($wfill) { - $this->setFillColorArray($this->bgcolor); - } - } - } // end newline - if (isset($opentagpos)) { - unset($opentagpos); - } - if ($dom[$key]['tag']) { - if ($dom[$key]['opening']) { - // get text indentation (if any) - if (isset($dom[$key]['text-indent']) AND $dom[$key]['block']) { - $this->textindent = $dom[$key]['text-indent']; - $this->newline = true; - } - // table - if (($dom[$key]['value'] == 'table') AND isset($dom[$key]['cols']) AND ($dom[$key]['cols'] > 0)) { - // available page width - if ($this->rtl) { - $wtmp = $this->x - $this->lMargin; - } else { - $wtmp = $this->w - $this->rMargin - $this->x; - } - // get cell spacing - if (isset($dom[$key]['attribute']['cellspacing'])) { - $clsp = $this->getHTMLUnitToUnits($dom[$key]['attribute']['cellspacing'], 1, 'px'); - $cellspacing = array('H' => $clsp, 'V' => $clsp); - } elseif (isset($dom[$key]['border-spacing'])) { - $cellspacing = $dom[$key]['border-spacing']; - } else { - $cellspacing = array('H' => 0, 'V' => 0); - } - // table width - if (isset($dom[$key]['width'])) { - $table_width = $this->getHTMLUnitToUnits($dom[$key]['width'], $wtmp, 'px'); - } else { - $table_width = $wtmp; - } - $table_width -= (2 * $cellspacing['H']); - if (!$this->inthead) { - $this->y += $cellspacing['V']; - } - if ($this->rtl) { - $cellspacingx = -$cellspacing['H']; - } else { - $cellspacingx = $cellspacing['H']; - } - // total table width without cellspaces - $table_columns_width = ($table_width - ($cellspacing['H'] * ($dom[$key]['cols'] - 1))); - // minimum column width - $table_min_column_width = ($table_columns_width / $dom[$key]['cols']); - // array of custom column widths - $table_colwidths = array_fill(0, $dom[$key]['cols'], $table_min_column_width); - } - // table row - if ($dom[$key]['value'] == 'tr') { - // reset column counter - $colid = 0; - } - // table cell - if (($dom[$key]['value'] == 'td') OR ($dom[$key]['value'] == 'th')) { - $trid = $dom[$key]['parent']; - $table_el = $dom[$trid]['parent']; - if (!isset($dom[$table_el]['cols'])) { - $dom[$table_el]['cols'] = $dom[$trid]['cols']; - } - // store border info - $tdborder = 0; - if (isset($dom[$key]['border']) AND !empty($dom[$key]['border'])) { - $tdborder = $dom[$key]['border']; - } - $colspan = intval($dom[$key]['attribute']['colspan']); - if ($colspan <= 0) { - $colspan = 1; - } - $old_cell_padding = $this->cell_padding; - if (isset($dom[($dom[$trid]['parent'])]['attribute']['cellpadding'])) { - $crclpd = $this->getHTMLUnitToUnits($dom[($dom[$trid]['parent'])]['attribute']['cellpadding'], 1, 'px'); - $current_cell_padding = array('L' => $crclpd, 'T' => $crclpd, 'R' => $crclpd, 'B' => $crclpd); - } elseif (isset($dom[($dom[$trid]['parent'])]['padding'])) { - $current_cell_padding = $dom[($dom[$trid]['parent'])]['padding']; - } else { - $current_cell_padding = array('L' => 0, 'T' => 0, 'R' => 0, 'B' => 0); - } - $this->cell_padding = $current_cell_padding; - if (isset($dom[$key]['height'])) { - // minimum cell height - $cellh = $this->getHTMLUnitToUnits($dom[$key]['height'], 0, 'px'); - } else { - $cellh = 0; - } - if (isset($dom[$key]['content'])) { - $cell_content = $dom[$key]['content']; - } else { - $cell_content = '&nbsp;'; - } - $tagtype = $dom[$key]['value']; - $parentid = $key; - while (($key < $maxel) AND (!(($dom[$key]['tag']) AND (!$dom[$key]['opening']) AND ($dom[$key]['value'] == $tagtype) AND ($dom[$key]['parent'] == $parentid)))) { - // move $key index forward - ++$key; - } - if (!isset($dom[$trid]['startpage'])) { - $dom[$trid]['startpage'] = $this->page; - } else { - $this->setPage($dom[$trid]['startpage']); - } - if (!isset($dom[$trid]['startcolumn'])) { - $dom[$trid]['startcolumn'] = $this->current_column; - } elseif ($this->current_column != $dom[$trid]['startcolumn']) { - $tmpx = $this->x; - $this->selectColumn($dom[$trid]['startcolumn']); - $this->x = $tmpx; - } - if (!isset($dom[$trid]['starty'])) { - $dom[$trid]['starty'] = $this->y; - } else { - $this->y = $dom[$trid]['starty']; - } - if (!isset($dom[$trid]['startx'])) { - $dom[$trid]['startx'] = $this->x; - $this->x += $cellspacingx; - } else { - $this->x += ($cellspacingx / 2); - } - if (isset($dom[$parentid]['attribute']['rowspan'])) { - $rowspan = intval($dom[$parentid]['attribute']['rowspan']); - } else { - $rowspan = 1; - } - // skip row-spanned cells started on the previous rows - if (isset($dom[$table_el]['rowspans'])) { - $rsk = 0; - $rskmax = count($dom[$table_el]['rowspans']); - while ($rsk < $rskmax) { - $trwsp = $dom[$table_el]['rowspans'][$rsk]; - $rsstartx = $trwsp['startx']; - $rsendx = $trwsp['endx']; - // account for margin changes - if ($trwsp['startpage'] < $this->page) { - if (($this->rtl) AND ($this->pagedim[$this->page]['orm'] != $this->pagedim[$trwsp['startpage']]['orm'])) { - $dl = ($this->pagedim[$this->page]['orm'] - $this->pagedim[$trwsp['startpage']]['orm']); - $rsstartx -= $dl; - $rsendx -= $dl; - } elseif ((!$this->rtl) AND ($this->pagedim[$this->page]['olm'] != $this->pagedim[$trwsp['startpage']]['olm'])) { - $dl = ($this->pagedim[$this->page]['olm'] - $this->pagedim[$trwsp['startpage']]['olm']); - $rsstartx += $dl; - $rsendx += $dl; - } - } - if (($trwsp['rowspan'] > 0) - AND ($rsstartx > ($this->x - $cellspacing['H'] - $current_cell_padding['L'] - $this->feps)) - AND ($rsstartx < ($this->x + $cellspacing['H'] + $current_cell_padding['R'] + $this->feps)) - AND (($trwsp['starty'] < ($this->y - $this->feps)) OR ($trwsp['startpage'] < $this->page) OR ($trwsp['startcolumn'] < $this->current_column))) { - // set the starting X position of the current cell - $this->x = $rsendx + $cellspacingx; - // increment column indicator - $colid += $trwsp['colspan']; - if (($trwsp['rowspan'] == 1) - AND (isset($dom[$trid]['endy'])) - AND (isset($dom[$trid]['endpage'])) - AND (isset($dom[$trid]['endcolumn'])) - AND ($trwsp['endpage'] == $dom[$trid]['endpage']) - AND ($trwsp['endcolumn'] == $dom[$trid]['endcolumn'])) { - // set ending Y position for row - $dom[$table_el]['rowspans'][$rsk]['endy'] = max($dom[$trid]['endy'], $trwsp['endy']); - $dom[$trid]['endy'] = $dom[$table_el]['rowspans'][$rsk]['endy']; - } - $rsk = 0; - } else { - ++$rsk; - } - } - } - if (isset($dom[$parentid]['width'])) { - // user specified width - $cellw = $this->getHTMLUnitToUnits($dom[$parentid]['width'], $table_columns_width, 'px'); - $tmpcw = ($cellw / $colspan); - for ($i = 0; $i < $colspan; ++$i) { - $table_colwidths[($colid + $i)] = $tmpcw; - } - } else { - // inherit column width - $cellw = 0; - for ($i = 0; $i < $colspan; ++$i) { - $cellw += (isset($table_colwidths[($colid + $i)]) ? $table_colwidths[($colid + $i)] : 0); - } - } - $cellw += (($colspan - 1) * $cellspacing['H']); - // increment column indicator - $colid += $colspan; - // add rowspan information to table element - if ($rowspan > 1) { - $trsid = array_push($dom[$table_el]['rowspans'], array('trid' => $trid, 'rowspan' => $rowspan, 'mrowspan' => $rowspan, 'colspan' => $colspan, 'startpage' => $this->page, 'startcolumn' => $this->current_column, 'startx' => $this->x, 'starty' => $this->y)); - } - $cellid = array_push($dom[$trid]['cellpos'], array('startx' => $this->x)); - if ($rowspan > 1) { - $dom[$trid]['cellpos'][($cellid - 1)]['rowspanid'] = ($trsid - 1); - } - // push background colors - if (isset($dom[$parentid]['bgcolor']) AND ($dom[$parentid]['bgcolor'] !== false)) { - $dom[$trid]['cellpos'][($cellid - 1)]['bgcolor'] = $dom[$parentid]['bgcolor']; - } - // store border info - if (isset($tdborder) AND !empty($tdborder)) { - $dom[$trid]['cellpos'][($cellid - 1)]['border'] = $tdborder; - } - $prevLastH = $this->lasth; - // store some info for multicolumn mode - if ($this->rtl) { - $this->colxshift['x'] = $this->w - $this->x - $this->rMargin; - } else { - $this->colxshift['x'] = $this->x - $this->lMargin; - } - $this->colxshift['s'] = $cellspacing; - $this->colxshift['p'] = $current_cell_padding; - // ****** write the cell content ****** - $this->MultiCell($cellw, $cellh, $cell_content, false, $lalign, false, 2, '', '', true, 0, true, true, 0, 'T', false); - // restore some values - $this->colxshift = array('x' => 0, 's' => array('H' => 0, 'V' => 0), 'p' => array('L' => 0, 'T' => 0, 'R' => 0, 'B' => 0)); - $this->lasth = $prevLastH; - $this->cell_padding = $old_cell_padding; - $dom[$trid]['cellpos'][($cellid - 1)]['endx'] = $this->x; - // update the end of row position - if ($rowspan <= 1) { - if (isset($dom[$trid]['endy'])) { - if (($this->page == $dom[$trid]['endpage']) AND ($this->current_column == $dom[$trid]['endcolumn'])) { - $dom[$trid]['endy'] = max($this->y, $dom[$trid]['endy']); - } elseif (($this->page > $dom[$trid]['endpage']) OR ($this->current_column > $dom[$trid]['endcolumn'])) { - $dom[$trid]['endy'] = $this->y; - } - } else { - $dom[$trid]['endy'] = $this->y; - } - if (isset($dom[$trid]['endpage'])) { - $dom[$trid]['endpage'] = max($this->page, $dom[$trid]['endpage']); - } else { - $dom[$trid]['endpage'] = $this->page; - } - if (isset($dom[$trid]['endcolumn'])) { - $dom[$trid]['endcolumn'] = max($this->current_column, $dom[$trid]['endcolumn']); - } else { - $dom[$trid]['endcolumn'] = $this->current_column; - } - } else { - // account for row-spanned cells - $dom[$table_el]['rowspans'][($trsid - 1)]['endx'] = $this->x; - $dom[$table_el]['rowspans'][($trsid - 1)]['endy'] = $this->y; - $dom[$table_el]['rowspans'][($trsid - 1)]['endpage'] = $this->page; - $dom[$table_el]['rowspans'][($trsid - 1)]['endcolumn'] = $this->current_column; - } - if (isset($dom[$table_el]['rowspans'])) { - // update endy and endpage on rowspanned cells - foreach ($dom[$table_el]['rowspans'] as $k => $trwsp) { - if ($trwsp['rowspan'] > 0) { - if (isset($dom[$trid]['endpage'])) { - if (($trwsp['endpage'] == $dom[$trid]['endpage']) AND ($trwsp['endcolumn'] == $dom[$trid]['endcolumn'])) { - $dom[$table_el]['rowspans'][$k]['endy'] = max($dom[$trid]['endy'], $trwsp['endy']); - } elseif (($trwsp['endpage'] < $dom[$trid]['endpage']) OR ($trwsp['endcolumn'] < $dom[$trid]['endcolumn'])) { - $dom[$table_el]['rowspans'][$k]['endy'] = $dom[$trid]['endy']; - $dom[$table_el]['rowspans'][$k]['endpage'] = $dom[$trid]['endpage']; - $dom[$table_el]['rowspans'][$k]['endcolumn'] = $dom[$trid]['endcolumn']; - } else { - $dom[$trid]['endy'] = $this->pagedim[$dom[$trid]['endpage']]['hk'] - $this->pagedim[$dom[$trid]['endpage']]['bm']; - } - } - } - } - } - $this->x += ($cellspacingx / 2); - } else { - // opening tag (or self-closing tag) - if (!isset($opentagpos)) { - if ($this->inxobj) { - // we are inside an XObject template - $opentagpos = strlen($this->xobjects[$this->xobjid]['outdata']); - } elseif (!$this->InFooter) { - if (isset($this->footerlen[$this->page])) { - $this->footerpos[$this->page] = $this->pagelen[$this->page] - $this->footerlen[$this->page]; - } else { - $this->footerpos[$this->page] = $this->pagelen[$this->page]; - } - $opentagpos = $this->footerpos[$this->page]; - } - } - $dom = $this->openHTMLTagHandler($dom, $key, $cell); - } - } else { // closing tag - $prev_numpages = $this->numpages; - $old_bordermrk = $this->bordermrk[$this->page]; - $dom = $this->closeHTMLTagHandler($dom, $key, $cell, $maxbottomliney); - if ($this->bordermrk[$this->page] > $old_bordermrk) { - $startlinepos += ($this->bordermrk[$this->page] - $old_bordermrk); - } - if ($prev_numpages > $this->numpages) { - $startlinepage = $this->page; - } - } - } elseif (strlen($dom[$key]['value']) > 0) { - // print list-item - if (!TCPDF_STATIC::empty_string($this->lispacer) AND ($this->lispacer != '^')) { - $this->setFont($pfontname, $pfontstyle, $pfontsize); - $this->resetLastH(); - $minstartliney = $this->y; - $maxbottomliney = ($startliney + $this->getCellHeight($this->FontSize)); - if (is_numeric($pfontsize) AND ($pfontsize > 0)) { - $this->putHtmlListBullet($this->listnum, $this->lispacer, $pfontsize); - } - $this->setFont($curfontname, $curfontstyle, $curfontsize); - $this->resetLastH(); - if (is_numeric($pfontsize) AND ($pfontsize > 0) AND is_numeric($curfontsize) AND ($curfontsize > 0) AND ($pfontsize != $curfontsize)) { - $pfontascent = $this->getFontAscent($pfontname, $pfontstyle, $pfontsize); - $pfontdescent = $this->getFontDescent($pfontname, $pfontstyle, $pfontsize); - $this->y += ($this->getCellHeight(($pfontsize - $curfontsize) / $this->k) + $pfontascent - $curfontascent - $pfontdescent + $curfontdescent) / 2; - $minstartliney = min($this->y, $minstartliney); - $maxbottomliney = max(($this->y + $this->getCellHeight($pfontsize / $this->k)), $maxbottomliney); - } - } - // text - $this->htmlvspace = 0; - $isRTLString = preg_match(TCPDF_FONT_DATA::$uni_RE_PATTERN_RTL, $dom[$key]['value']) || preg_match(TCPDF_FONT_DATA::$uni_RE_PATTERN_ARABIC, $dom[$key]['value']); - if ((!$this->premode) AND $this->isRTLTextDir() AND !$isRTLString) { - // reverse spaces order - $lsp = ''; // left spaces - $rsp = ''; // right spaces - if (preg_match('/^('.$this->re_space['p'].'+)/'.$this->re_space['m'], $dom[$key]['value'], $matches)) { - $lsp = $matches[1]; - } - if (preg_match('/('.$this->re_space['p'].'+)$/'.$this->re_space['m'], $dom[$key]['value'], $matches)) { - $rsp = $matches[1]; - } - $dom[$key]['value'] = $rsp.$this->stringTrim($dom[$key]['value']).$lsp; - } - if ($newline) { - if (!$this->premode) { - $prelen = strlen($dom[$key]['value']); - if ($this->isRTLTextDir() AND !$isRTLString) { - // right trim except non-breaking space - $dom[$key]['value'] = $this->stringRightTrim($dom[$key]['value']); - } else { - // left trim except non-breaking space - $dom[$key]['value'] = $this->stringLeftTrim($dom[$key]['value']); - } - $postlen = strlen($dom[$key]['value']); - if (($postlen == 0) AND ($prelen > 0)) { - $dom[$key]['trimmed_space'] = true; - } - } - $newline = false; - $firstblock = true; - } else { - $firstblock = false; - // replace empty multiple spaces string with a single space - $dom[$key]['value'] = preg_replace('/^'.$this->re_space['p'].'+$/'.$this->re_space['m'], chr(32), $dom[$key]['value']); - } - $strrest = ''; - if ($this->rtl) { - $this->x -= $this->textindent; - } else { - $this->x += $this->textindent; - } - if (!isset($dom[$key]['trimmed_space']) OR !$dom[$key]['trimmed_space']) { - $strlinelen = $this->GetStringWidth($dom[$key]['value']); - if (!empty($this->HREF) AND (isset($this->HREF['url']))) { - // HTML <a> Link - $hrefcolor = ''; - if (isset($dom[($dom[$key]['parent'])]['fgcolor']) AND ($dom[($dom[$key]['parent'])]['fgcolor'] !== false)) { - $hrefcolor = $dom[($dom[$key]['parent'])]['fgcolor']; - } - $hrefstyle = -1; - if (isset($dom[($dom[$key]['parent'])]['fontstyle']) AND ($dom[($dom[$key]['parent'])]['fontstyle'] !== false)) { - $hrefstyle = $dom[($dom[$key]['parent'])]['fontstyle']; - } - $strrest = $this->addHtmlLink($this->HREF['url'], $dom[$key]['value'], $wfill, true, $hrefcolor, $hrefstyle, true); - } else { - $wadj = 0; // space to leave for block continuity - if ($this->rtl) { - $cwa = ($this->x - $this->lMargin); - } else { - $cwa = ($this->w - $this->rMargin - $this->x); - } - if (($strlinelen < $cwa) AND (isset($dom[($key + 1)])) AND ($dom[($key + 1)]['tag']) AND (!$dom[($key + 1)]['block'])) { - // check the next text blocks for continuity - $nkey = ($key + 1); - $write_block = true; - $same_textdir = true; - $tmp_fontname = $this->FontFamily; - $tmp_fontstyle = $this->FontStyle; - $tmp_fontsize = $this->FontSizePt; - while ($write_block AND isset($dom[$nkey])) { - if ($dom[$nkey]['tag']) { - if ($dom[$nkey]['block']) { - // end of block - $write_block = false; - } - $tmp_fontname = isset($dom[$nkey]['fontname']) ? $dom[$nkey]['fontname'] : $this->FontFamily; - $tmp_fontstyle = isset($dom[$nkey]['fontstyle']) ? $dom[$nkey]['fontstyle'] : $this->FontStyle; - $tmp_fontsize = isset($dom[$nkey]['fontsize']) ? $dom[$nkey]['fontsize'] : $this->FontSizePt; - $same_textdir = ($dom[$nkey]['dir'] == $dom[$key]['dir']); - } else { - $nextstr = TCPDF_STATIC::pregSplit('/'.$this->re_space['p'].'+/', $this->re_space['m'], $dom[$nkey]['value']); - if (isset($nextstr[0]) AND $same_textdir) { - $wadj += $this->GetStringWidth($nextstr[0], $tmp_fontname, $tmp_fontstyle, $tmp_fontsize); - if (isset($nextstr[1])) { - $write_block = false; - } - } - } - ++$nkey; - } - } - if (($wadj > 0) AND (($strlinelen + $wadj) >= $cwa)) { - $wadj = 0; - $nextstr = TCPDF_STATIC::pregSplit('/'.$this->re_space['p'].'/', $this->re_space['m'], $dom[$key]['value']); - $numblks = count($nextstr); - if ($numblks > 1) { - // try to split on blank spaces - $wadj = ($cwa - $strlinelen + $this->GetStringWidth($nextstr[($numblks - 1)])); - } else { - // set the entire block on new line - $wadj = $this->GetStringWidth($nextstr[0]); - } - } - // check for reversed text direction - if (($wadj > 0) AND (($this->rtl AND ($this->tmprtl === 'L')) OR (!$this->rtl AND ($this->tmprtl === 'R')))) { - // LTR text on RTL direction or RTL text on LTR direction - $reverse_dir = true; - $this->rtl = !$this->rtl; - $revshift = ($strlinelen + $wadj + 0.000001); // add little quantity for rounding problems - if ($this->rtl) { - $this->x += $revshift; - } else { - $this->x -= $revshift; - } - $xws = $this->x; - } - // ****** write only until the end of the line and get the rest ****** - $strrest = $this->Write($this->lasth, $dom[$key]['value'], '', $wfill, '', false, 0, true, $firstblock, 0, $wadj); - // restore default direction - if ($reverse_dir AND ($wadj == 0)) { - $this->x = $xws; - $this->rtl = !$this->rtl; - $reverse_dir = false; - } - } - } - $this->textindent = 0; - if (strlen($strrest) > 0) { - // store the remaining string on the previous $key position - $this->newline = true; - if ($strrest == $dom[$key]['value']) { - // used to avoid infinite loop - ++$loop; - } else { - $loop = 0; - } - $dom[$key]['value'] = $strrest; - if ($cell) { - if ($this->rtl) { - $this->x -= $this->cell_padding['R']; - } else { - $this->x += $this->cell_padding['L']; - } - } - if ($loop < 3) { - --$key; - } - } else { - $loop = 0; - // add the positive font spacing of the last character (if any) - if ($this->font_spacing > 0) { - if ($this->rtl) { - $this->x -= $this->font_spacing; - } else { - $this->x += $this->font_spacing; - } - } - } - } - ++$key; - if (isset($dom[$key]['tag']) AND $dom[$key]['tag'] AND (!isset($dom[$key]['opening']) OR !$dom[$key]['opening']) AND isset($dom[($dom[$key]['parent'])]['attribute']['nobr']) AND ($dom[($dom[$key]['parent'])]['attribute']['nobr'] == 'true')) { - // check if we are on a new page or on a new column - if ((!$undo) AND (($this->y < $this->start_transaction_y) OR (($dom[$key]['value'] == 'tr') AND ($dom[($dom[$key]['parent'])]['endy'] < $this->start_transaction_y)))) { - // we are on a new page or on a new column and the total object height is less than the available vertical space. - // restore previous object - $this->rollbackTransaction(true); - // restore previous values - foreach ($this_method_vars as $vkey => $vval) { - $$vkey = $vval; - } - if (!empty($dom[$key]['thead'])) { - $this->inthead = true; - } - // add a page (or trig AcceptPageBreak() for multicolumn mode) - $pre_y = $this->y; - if ((!$this->checkPageBreak($this->PageBreakTrigger + 1)) AND ($this->y < $pre_y)) { - $startliney = $this->y; - } - $undo = true; // avoid infinite loop - } else { - $undo = false; - } - } - } // end for each $key - // align the last line - if (isset($startlinex)) { - $yshift = ($minstartliney - $startliney); - if (($yshift > 0) OR ($this->page > $startlinepage)) { - $yshift = 0; - } - $t_x = 0; - // the last line must be shifted to be aligned as requested - $linew = abs($this->endlinex - $startlinex); - if ($this->inxobj) { - // we are inside an XObject template - $pstart = substr($this->xobjects[$this->xobjid]['outdata'], 0, $startlinepos); - if (isset($opentagpos)) { - $midpos = $opentagpos; - } else { - $midpos = 0; - } - if ($midpos > 0) { - $pmid = substr($this->xobjects[$this->xobjid]['outdata'], $startlinepos, ($midpos - $startlinepos)); - $pend = substr($this->xobjects[$this->xobjid]['outdata'], $midpos); - } else { - $pmid = substr($this->xobjects[$this->xobjid]['outdata'], $startlinepos); - $pend = ''; - } - } else { - $pstart = substr($this->getPageBuffer($startlinepage), 0, $startlinepos); - if (isset($opentagpos) AND isset($this->footerlen[$startlinepage]) AND (!$this->InFooter)) { - $this->footerpos[$startlinepage] = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage]; - $midpos = min($opentagpos, $this->footerpos[$startlinepage]); - } elseif (isset($opentagpos)) { - $midpos = $opentagpos; - } elseif (isset($this->footerlen[$startlinepage]) AND (!$this->InFooter)) { - $this->footerpos[$startlinepage] = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage]; - $midpos = $this->footerpos[$startlinepage]; - } else { - $midpos = 0; - } - if ($midpos > 0) { - $pmid = substr($this->getPageBuffer($startlinepage), $startlinepos, ($midpos - $startlinepos)); - $pend = substr($this->getPageBuffer($startlinepage), $midpos); - } else { - $pmid = substr($this->getPageBuffer($startlinepage), $startlinepos); - $pend = ''; - } - } - if ((isset($plalign) AND ((($plalign == 'C') OR (($plalign == 'R') AND (!$this->rtl)) OR (($plalign == 'L') AND ($this->rtl)))))) { - // calculate shifting amount - $tw = $w; - if ($this->lMargin != $prevlMargin) { - $tw += ($prevlMargin - $this->lMargin); - } - if ($this->rMargin != $prevrMargin) { - $tw += ($prevrMargin - $this->rMargin); - } - $one_space_width = $this->GetStringWidth(chr(32)); - $no = 0; // number of spaces on a line contained on a single block - if ($this->isRTLTextDir()) { // RTL - // remove left space if exist - $pos1 = TCPDF_STATIC::revstrpos($pmid, '[('); - if ($pos1 > 0) { - $pos1 = intval($pos1); - if ($this->isUnicodeFont()) { - $pos2 = intval(TCPDF_STATIC::revstrpos($pmid, '[('.chr(0).chr(32))); - $spacelen = 2; - } else { - $pos2 = intval(TCPDF_STATIC::revstrpos($pmid, '[('.chr(32))); - $spacelen = 1; - } - if ($pos1 == $pos2) { - $pmid = substr($pmid, 0, ($pos1 + 2)).substr($pmid, ($pos1 + 2 + $spacelen)); - if (substr($pmid, $pos1, 4) == '[()]') { - $linew -= $one_space_width; - } elseif ($pos1 == strpos($pmid, '[(')) { - $no = 1; - } - } - } - } else { // LTR - // remove right space if exist - $pos1 = TCPDF_STATIC::revstrpos($pmid, ')]'); - if ($pos1 > 0) { - $pos1 = intval($pos1); - if ($this->isUnicodeFont()) { - $pos2 = intval(TCPDF_STATIC::revstrpos($pmid, chr(0).chr(32).')]')) + 2; - $spacelen = 2; - } else { - $pos2 = intval(TCPDF_STATIC::revstrpos($pmid, chr(32).')]')) + 1; - $spacelen = 1; - } - if ($pos1 == $pos2) { - $pmid = substr($pmid, 0, ($pos1 - $spacelen)).substr($pmid, $pos1); - $linew -= $one_space_width; - } - } - } - $mdiff = ($tw - $linew); - if ($plalign == 'C') { - if ($this->rtl) { - $t_x = -($mdiff / 2); - } else { - $t_x = ($mdiff / 2); - } - } elseif ($plalign == 'R') { - // right alignment on LTR document - $t_x = $mdiff; - } elseif ($plalign == 'L') { - // left alignment on RTL document - $t_x = -$mdiff; - } - } // end if startlinex - if (($t_x != 0) OR ($yshift < 0)) { - // shift the line - $trx = sprintf('1 0 0 1 %F %F cm', ($t_x * $this->k), ($yshift * $this->k)); - $pstart .= "\nq\n".$trx."\n".$pmid."\nQ\n"; - $endlinepos = strlen($pstart); - if ($this->inxobj) { - // we are inside an XObject template - $this->xobjects[$this->xobjid]['outdata'] = $pstart.$pend; - foreach ($this->xobjects[$this->xobjid]['annotations'] as $pak => $pac) { - if ($pak >= $pask) { - $this->xobjects[$this->xobjid]['annotations'][$pak]['x'] += $t_x; - $this->xobjects[$this->xobjid]['annotations'][$pak]['y'] -= $yshift; - } - } - } else { - $this->setPageBuffer($startlinepage, $pstart.$pend); - // shift the annotations and links - if (isset($this->PageAnnots[$this->page])) { - foreach ($this->PageAnnots[$this->page] as $pak => $pac) { - if ($pak >= $pask) { - $this->PageAnnots[$this->page][$pak]['x'] += $t_x; - $this->PageAnnots[$this->page][$pak]['y'] -= $yshift; - } - } - } - } - $this->y -= $yshift; - $yshift = 0; - } - } - // restore previous values - $this->setGraphicVars($gvars); - if ($this->num_columns > 1) { - $this->selectColumn(); - } elseif ($this->page > $prevPage) { - $this->lMargin = $this->pagedim[$this->page]['olm']; - $this->rMargin = $this->pagedim[$this->page]['orm']; - } - // restore previous list state - $this->cell_height_ratio = $prev_cell_height_ratio; - $this->listnum = $prev_listnum; - $this->listordered = $prev_listordered; - $this->listcount = $prev_listcount; - $this->lispacer = $prev_lispacer; - if ($ln AND (!($cell AND ($dom[$key-1]['value'] == 'table')))) { - $this->Ln($this->lasth); - if (($this->y < $maxbottomliney) AND ($startlinepage == $this->page)) { - $this->y = $maxbottomliney; - } - } - unset($dom); - } - - /** - * Process opening tags. - * @param array $dom html dom array - * @param int $key current element id - * @param boolean $cell if true add the default left (or right if RTL) padding to each new line (default false). - * @return array $dom - * @protected - */ - protected function openHTMLTagHandler($dom, $key, $cell) { - $tag = $dom[$key]; - $parent = $dom[($dom[$key]['parent'])]; - $firsttag = ($key == 1); - // check for text direction attribute - if (isset($tag['dir'])) { - $this->setTempRTL($tag['dir']); - } else { - $this->tmprtl = false; - } - if ($tag['block']) { - $hbz = 0; // distance from y to line bottom - $hb = 0; // vertical space between block tags - // calculate vertical space for block tags - if (isset($this->tagvspaces[$tag['value']][0]['h']) && !empty($this->tagvspaces[$tag['value']][0]['h']) && ($this->tagvspaces[$tag['value']][0]['h'] >= 0)) { - $cur_h = $this->tagvspaces[$tag['value']][0]['h']; - } elseif (isset($tag['fontsize'])) { - $cur_h = $this->getCellHeight($tag['fontsize'] / $this->k); - } else { - $cur_h = $this->getCellHeight($this->FontSize); - } - if (isset($this->tagvspaces[$tag['value']][0]['n'])) { - $on = $this->tagvspaces[$tag['value']][0]['n']; - } elseif (preg_match('/[h][0-9]/', $tag['value']) > 0) { - $on = 0.6; - } else { - $on = 1; - } - if ((!isset($this->tagvspaces[$tag['value']])) AND (in_array($tag['value'], array('div', 'dt', 'dd', 'li', 'br', 'hr')))) { - $hb = 0; - } else { - $hb = ($on * $cur_h); - } - if (($this->htmlvspace <= 0) AND ($on > 0)) { - if (isset($parent['fontsize'])) { - $hbz = (($parent['fontsize'] / $this->k) * $this->cell_height_ratio); - } else { - $hbz = $this->getCellHeight($this->FontSize); - } - } - if (isset($dom[($key - 1)]) AND ($dom[($key - 1)]['value'] == 'table')) { - // fix vertical space after table - $hbz = 0; - } - // closing vertical space - $hbc = 0; - if (isset($this->tagvspaces[$tag['value']][1]['h']) && !empty($this->tagvspaces[$tag['value']][1]['h']) && ($this->tagvspaces[$tag['value']][1]['h'] >= 0)) { - $pre_h = $this->tagvspaces[$tag['value']][1]['h']; - } elseif (isset($parent['fontsize'])) { - $pre_h = $this->getCellHeight($parent['fontsize'] / $this->k); - } else { - $pre_h = $this->getCellHeight($this->FontSize); - } - if (isset($this->tagvspaces[$tag['value']][1]['n'])) { - $cn = $this->tagvspaces[$tag['value']][1]['n']; - } elseif (preg_match('/[h][0-9]/', $tag['value']) > 0) { - $cn = 0.6; - } else { - $cn = 1; - } - if (isset($this->tagvspaces[$tag['value']][1])) { - $hbc = ($cn * $pre_h); - } - } - // Opening tag - switch($tag['value']) { - case 'table': { - $cp = 0; - $cs = 0; - $dom[$key]['rowspans'] = array(); - if (!isset($dom[$key]['attribute']['nested']) OR ($dom[$key]['attribute']['nested'] != 'true')) { - $this->htmlvspace = 0; - // set table header - if (!TCPDF_STATIC::empty_string($dom[$key]['thead'])) { - // set table header - $this->thead = $dom[$key]['thead']; - if (!isset($this->theadMargins) OR (empty($this->theadMargins))) { - $this->theadMargins = array(); - $this->theadMargins['cell_padding'] = $this->cell_padding; - $this->theadMargins['lmargin'] = $this->lMargin; - $this->theadMargins['rmargin'] = $this->rMargin; - $this->theadMargins['page'] = $this->page; - $this->theadMargins['cell'] = $cell; - $this->theadMargins['gvars'] = $this->getGraphicVars(); - } - } - } - // store current margins and page - $dom[$key]['old_cell_padding'] = $this->cell_padding; - if (isset($tag['attribute']['cellpadding'])) { - $pad = $this->getHTMLUnitToUnits($tag['attribute']['cellpadding'], 1, 'px'); - $this->setCellPadding($pad); - } elseif (isset($tag['padding'])) { - $this->cell_padding = $tag['padding']; - } - if (isset($tag['attribute']['cellspacing'])) { - $cs = $this->getHTMLUnitToUnits($tag['attribute']['cellspacing'], 1, 'px'); - } elseif (isset($tag['border-spacing'])) { - $cs = $tag['border-spacing']['V']; - } - $prev_y = $this->y; - if ($this->checkPageBreak(((2 * $cp) + (2 * $cs) + $this->lasth), '', false) OR ($this->y < $prev_y)) { - $this->inthead = true; - // add a page (or trig AcceptPageBreak() for multicolumn mode) - $this->checkPageBreak($this->PageBreakTrigger + 1); - } - break; - } - case 'tr': { - // array of columns positions - $dom[$key]['cellpos'] = array(); - break; - } - case 'hr': { - if ((isset($tag['height'])) AND ($tag['height'] != '')) { - $hrHeight = $this->getHTMLUnitToUnits($tag['height'], 1, 'px'); - } else { - $hrHeight = $this->GetLineWidth(); - } - $this->addHTMLVertSpace($hbz, max($hb, ($hrHeight / 2)), $cell, $firsttag); - $x = $this->GetX(); - $y = $this->GetY(); - $wtmp = $this->w - $this->lMargin - $this->rMargin; - if ($cell) { - $wtmp -= ($this->cell_padding['L'] + $this->cell_padding['R']); - } - if ((isset($tag['width'])) AND ($tag['width'] != '')) { - $hrWidth = $this->getHTMLUnitToUnits($tag['width'], $wtmp, 'px'); - } else { - $hrWidth = $wtmp; - } - $prevlinewidth = $this->GetLineWidth(); - $this->setLineWidth($hrHeight); - - $lineStyle = array(); - if (isset($tag['fgcolor'])) { - $lineStyle['color'] = $tag['fgcolor']; - } - - if (isset($tag['fgcolor'])) { - $lineStyle['color'] = $tag['fgcolor']; - } - - if (isset($tag['style']['cap'])) { - $lineStyle['cap'] = $tag['style']['cap']; - } - - if (isset($tag['style']['join'])) { - $lineStyle['join'] = $tag['style']['join']; - } - - if (isset($tag['style']['dash'])) { - $lineStyle['dash'] = $tag['style']['dash']; - } - - if (isset($tag['style']['phase'])) { - $lineStyle['phase'] = $tag['style']['phase']; - } - - $lineStyle = array_filter($lineStyle); - - $this->Line($x, $y, $x + $hrWidth, $y, $lineStyle); - $this->setLineWidth($prevlinewidth); - $this->addHTMLVertSpace(max($hbc, ($hrHeight / 2)), 0, $cell, !isset($dom[($key + 1)])); - break; - } - case 'a': { - if (array_key_exists('href', $tag['attribute'])) { - $this->HREF['url'] = $tag['attribute']['href']; - } - break; - } - case 'img': { - if (empty($tag['attribute']['src'])) { - break; - } - $imgsrc = $tag['attribute']['src']; - if ($imgsrc[0] === '@') { - // data stream - $imgsrc = '@'.base64_decode(substr($imgsrc, 1)); - $type = ''; - } elseif ( $this->allowLocalFiles && substr($imgsrc, 0, 7) === 'file://') { - // get image type from a local file path - $imgsrc = substr($imgsrc, 7); - $type = TCPDF_IMAGES::getImageFileType($imgsrc); - } else { - if (($imgsrc[0] === '/') AND !empty($_SERVER['DOCUMENT_ROOT']) AND ($_SERVER['DOCUMENT_ROOT'] != '/')) { - // fix image path - $findroot = strpos($imgsrc, $_SERVER['DOCUMENT_ROOT']); - if (($findroot === false) OR ($findroot > 1)) { - if (substr($_SERVER['DOCUMENT_ROOT'], -1) == '/') { - $imgsrc = substr($_SERVER['DOCUMENT_ROOT'], 0, -1).$imgsrc; - } else { - $imgsrc = $_SERVER['DOCUMENT_ROOT'].$imgsrc; - } - } - $imgsrc = urldecode($imgsrc); - $testscrtype = @parse_url($imgsrc); - if (empty($testscrtype['query'])) { - // convert URL to server path - $imgsrc = str_replace(K_PATH_URL, K_PATH_MAIN, $imgsrc); - } elseif (preg_match('|^https?://|', $imgsrc) !== 1) { - // convert URL to server path - $imgsrc = str_replace(K_PATH_MAIN, K_PATH_URL, $imgsrc); - } - } - // get image type - $type = TCPDF_IMAGES::getImageFileType($imgsrc); - } - if (!isset($tag['width'])) { - $tag['width'] = 0; - } - if (!isset($tag['height'])) { - $tag['height'] = 0; - } - //if (!isset($tag['attribute']['align'])) { - // the only alignment supported is "bottom" - // further development is required for other modes. - $tag['attribute']['align'] = 'bottom'; - //} - switch($tag['attribute']['align']) { - case 'top': { - $align = 'T'; - break; - } - case 'middle': { - $align = 'M'; - break; - } - case 'bottom': { - $align = 'B'; - break; - } - default: { - $align = 'B'; - break; - } - } - $prevy = $this->y; - $xpos = $this->x; - $imglink = ''; - if (isset($this->HREF['url']) AND !TCPDF_STATIC::empty_string($this->HREF['url'])) { - $imglink = $this->HREF['url']; - if ($imglink[0] == '#') { - // convert url to internal link - $lnkdata = explode(',', $imglink); - if (isset($lnkdata[0])) { - $page = intval(substr($lnkdata[0], 1)); - if (empty($page) OR ($page <= 0)) { - $page = $this->page; - } - if (isset($lnkdata[1]) AND (strlen($lnkdata[1]) > 0)) { - $lnky = floatval($lnkdata[1]); - } else { - $lnky = 0; - } - $imglink = $this->AddLink(); - $this->setLink($imglink, $lnky, $page); - } - } - } - $border = 0; - if (isset($tag['border']) AND !empty($tag['border'])) { - // currently only support 1 (frame) or a combination of 'LTRB' - $border = $tag['border']; - } - $iw = ''; - if (isset($tag['width'])) { - $iw = $this->getHTMLUnitToUnits($tag['width'], ($tag['fontsize'] / $this->k), 'px', false); - } - $ih = ''; - if (isset($tag['height'])) { - $ih = $this->getHTMLUnitToUnits($tag['height'], ($tag['fontsize'] / $this->k), 'px', false); - } - if (($type == 'eps') OR ($type == 'ai')) { - $this->ImageEps($imgsrc, $xpos, $this->y, $iw, $ih, $imglink, true, $align, '', $border, true); - } elseif ($type == 'svg') { - $this->ImageSVG($imgsrc, $xpos, $this->y, $iw, $ih, $imglink, $align, '', $border, true); - } else { - $this->Image($imgsrc, $xpos, $this->y, $iw, $ih, '', $imglink, $align, false, 300, '', false, false, $border, false, false, true); - } - switch($align) { - case 'T': { - $this->y = $prevy; - break; - } - case 'M': { - $this->y = (($this->img_rb_y + $prevy - ($this->getCellHeight($tag['fontsize'] / $this->k))) / 2); - break; - } - case 'B': { - $this->y = $this->img_rb_y - ($this->getCellHeight($tag['fontsize'] / $this->k) - ($this->getFontDescent($tag['fontname'], $tag['fontstyle'], $tag['fontsize']) * $this->cell_height_ratio)); - break; - } - } - break; - } - case 'dl': { - ++$this->listnum; - if ($this->listnum == 1) { - $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag); - } else { - $this->addHTMLVertSpace(0, 0, $cell, $firsttag); - } - break; - } - case 'dt': { - $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag); - break; - } - case 'dd': { - if ($this->rtl) { - $this->rMargin += $this->listindent; - } else { - $this->lMargin += $this->listindent; - } - ++$this->listindentlevel; - $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag); - break; - } - case 'ul': - case 'ol': { - ++$this->listnum; - if ($tag['value'] == 'ol') { - $this->listordered[$this->listnum] = true; - } else { - $this->listordered[$this->listnum] = false; - } - if (isset($tag['attribute']['start'])) { - $this->listcount[$this->listnum] = intval($tag['attribute']['start']) - 1; - } else { - $this->listcount[$this->listnum] = 0; - } - if ($this->rtl) { - $this->rMargin += $this->listindent; - $this->x -= $this->listindent; - } else { - $this->lMargin += $this->listindent; - $this->x += $this->listindent; - } - ++$this->listindentlevel; - if ($this->listnum == 1) { - if ($key > 1) { - $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag); - } - } else { - $this->addHTMLVertSpace(0, 0, $cell, $firsttag); - } - break; - } - case 'li': { - if ($key > 2) { - $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag); - } - if ($this->listordered[$this->listnum]) { - // ordered item - if (isset($parent['attribute']['type']) AND !TCPDF_STATIC::empty_string($parent['attribute']['type'])) { - $this->lispacer = $parent['attribute']['type']; - } elseif (isset($parent['listtype']) AND !TCPDF_STATIC::empty_string($parent['listtype'])) { - $this->lispacer = $parent['listtype']; - } elseif (isset($this->lisymbol) AND !TCPDF_STATIC::empty_string($this->lisymbol)) { - $this->lispacer = $this->lisymbol; - } else { - $this->lispacer = '#'; - } - ++$this->listcount[$this->listnum]; - if (isset($tag['attribute']['value'])) { - $this->listcount[$this->listnum] = intval($tag['attribute']['value']); - } - } else { - // unordered item - if (isset($parent['attribute']['type']) AND !TCPDF_STATIC::empty_string($parent['attribute']['type'])) { - $this->lispacer = $parent['attribute']['type']; - } elseif (isset($parent['listtype']) AND !TCPDF_STATIC::empty_string($parent['listtype'])) { - $this->lispacer = $parent['listtype']; - } elseif (isset($this->lisymbol) AND !TCPDF_STATIC::empty_string($this->lisymbol)) { - $this->lispacer = $this->lisymbol; - } else { - $this->lispacer = '!'; - } - } - break; - } - case 'blockquote': { - if ($this->rtl) { - $this->rMargin += $this->listindent; - } else { - $this->lMargin += $this->listindent; - } - ++$this->listindentlevel; - $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag); - break; - } - case 'br': { - $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag); - break; - } - case 'div': { - $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag); - break; - } - case 'p': { - $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag); - break; - } - case 'pre': { - $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag); - $this->premode = true; - break; - } - case 'sup': { - $this->setXY($this->GetX(), $this->GetY() - ((0.7 * $this->FontSizePt) / $this->k)); - break; - } - case 'sub': { - $this->setXY($this->GetX(), $this->GetY() + ((0.3 * $this->FontSizePt) / $this->k)); - break; - } - case 'h1': - case 'h2': - case 'h3': - case 'h4': - case 'h5': - case 'h6': { - $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag); - break; - } - // Form fields (since 4.8.000 - 2009-09-07) - case 'form': { - if (isset($tag['attribute']['action'])) { - $this->form_action = $tag['attribute']['action']; - } else { - $this->Error('Please explicitly set action attribute path!'); - } - if (isset($tag['attribute']['enctype'])) { - $this->form_enctype = $tag['attribute']['enctype']; - } else { - $this->form_enctype = 'application/x-www-form-urlencoded'; - } - if (isset($tag['attribute']['method'])) { - $this->form_mode = $tag['attribute']['method']; - } else { - $this->form_mode = 'post'; - } - break; - } - case 'input': { - if (isset($tag['attribute']['name']) AND !TCPDF_STATIC::empty_string($tag['attribute']['name'])) { - $name = $tag['attribute']['name']; - } else { - break; - } - $prop = array(); - $opt = array(); - if (isset($tag['attribute']['readonly']) AND !TCPDF_STATIC::empty_string($tag['attribute']['readonly'])) { - $prop['readonly'] = true; - } - if (isset($tag['attribute']['value']) AND !TCPDF_STATIC::empty_string($tag['attribute']['value'])) { - $value = $tag['attribute']['value']; - } - if (isset($tag['attribute']['maxlength']) AND !TCPDF_STATIC::empty_string($tag['attribute']['maxlength'])) { - $opt['maxlen'] = intval($tag['attribute']['maxlength']); - } - $h = $this->getCellHeight($this->FontSize); - if (isset($tag['attribute']['size']) AND !TCPDF_STATIC::empty_string($tag['attribute']['size'])) { - $w = intval($tag['attribute']['size']) * $this->GetStringWidth(chr(32)) * 2; - } else { - $w = $h; - } - if (isset($tag['attribute']['checked']) AND (($tag['attribute']['checked'] == 'checked') OR ($tag['attribute']['checked'] == 'true'))) { - $checked = true; - } else { - $checked = false; - } - if (isset($tag['align'])) { - switch ($tag['align']) { - case 'C': { - $opt['q'] = 1; - break; - } - case 'R': { - $opt['q'] = 2; - break; - } - case 'L': - default: { - break; - } - } - } - switch ($tag['attribute']['type']) { - case 'text': { - if (isset($value)) { - $opt['v'] = $value; - } - $this->TextField($name, $w, $h, $prop, $opt, '', '', false); - break; - } - case 'password': { - if (isset($value)) { - $opt['v'] = $value; - } - $prop['password'] = 'true'; - $this->TextField($name, $w, $h, $prop, $opt, '', '', false); - break; - } - case 'checkbox': { - if (!isset($value)) { - break; - } - $this->CheckBox($name, $w, $checked, $prop, $opt, $value, '', '', false); - break; - } - case 'radio': { - if (!isset($value)) { - break; - } - $this->RadioButton($name, $w, $prop, $opt, $value, $checked, '', '', false); - break; - } - case 'submit': { - if (!isset($value)) { - $value = 'submit'; - } - $w = $this->GetStringWidth($value) * 1.5; - $h *= 1.6; - $prop = array('lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>array(196, 196, 196), 'strokeColor'=>array(255, 255, 255)); - $action = array(); - $action['S'] = 'SubmitForm'; - $action['F'] = $this->form_action; - if ($this->form_enctype != 'FDF') { - $action['Flags'] = array('ExportFormat'); - } - if ($this->form_mode == 'get') { - $action['Flags'] = array('GetMethod'); - } - $this->Button($name, $w, $h, $value, $action, $prop, $opt, '', '', false); - break; - } - case 'reset': { - if (!isset($value)) { - $value = 'reset'; - } - $w = $this->GetStringWidth($value) * 1.5; - $h *= 1.6; - $prop = array('lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>array(196, 196, 196), 'strokeColor'=>array(255, 255, 255)); - $this->Button($name, $w, $h, $value, array('S'=>'ResetForm'), $prop, $opt, '', '', false); - break; - } - case 'file': { - $prop['fileSelect'] = 'true'; - $this->TextField($name, $w, $h, $prop, $opt, '', '', false); - if (!isset($value)) { - $value = '*'; - } - $w = $this->GetStringWidth($value) * 2; - $h *= 1.2; - $prop = array('lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>array(196, 196, 196), 'strokeColor'=>array(255, 255, 255)); - $jsaction = 'var f=this.getField(\''.$name.'\'); f.browseForFileToSubmit();'; - $this->Button('FB_'.$name, $w, $h, $value, $jsaction, $prop, $opt, '', '', false); - break; - } - case 'hidden': { - if (isset($value)) { - $opt['v'] = $value; - } - $opt['f'] = array('invisible', 'hidden'); - $this->TextField($name, 0, 0, $prop, $opt, '', '', false); - break; - } - case 'image': { - // THIS TYPE MUST BE FIXED - if (isset($tag['attribute']['src']) AND !TCPDF_STATIC::empty_string($tag['attribute']['src'])) { - $img = $tag['attribute']['src']; - } else { - break; - } - $value = 'img'; - //$opt['mk'] = array('i'=>$img, 'tp'=>1, 'if'=>array('sw'=>'A', 's'=>'A', 'fb'=>false)); - if (isset($tag['attribute']['onclick']) AND !empty($tag['attribute']['onclick'])) { - $jsaction = $tag['attribute']['onclick']; - } else { - $jsaction = ''; - } - $this->Button($name, $w, $h, $value, $jsaction, $prop, $opt, '', '', false); - break; - } - case 'button': { - if (!isset($value)) { - $value = ' '; - } - $w = $this->GetStringWidth($value) * 1.5; - $h *= 1.6; - $prop = array('lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>array(196, 196, 196), 'strokeColor'=>array(255, 255, 255)); - if (isset($tag['attribute']['onclick']) AND !empty($tag['attribute']['onclick'])) { - $jsaction = $tag['attribute']['onclick']; - } else { - $jsaction = ''; - } - $this->Button($name, $w, $h, $value, $jsaction, $prop, $opt, '', '', false); - break; - } - } - break; - } - case 'textarea': { - $prop = array(); - $opt = array(); - if (isset($tag['attribute']['readonly']) AND !TCPDF_STATIC::empty_string($tag['attribute']['readonly'])) { - $prop['readonly'] = true; - } - if (isset($tag['attribute']['name']) AND !TCPDF_STATIC::empty_string($tag['attribute']['name'])) { - $name = $tag['attribute']['name']; - } else { - break; - } - if (isset($tag['attribute']['value']) AND !TCPDF_STATIC::empty_string($tag['attribute']['value'])) { - $opt['v'] = $tag['attribute']['value']; - } - if (isset($tag['attribute']['cols']) AND !TCPDF_STATIC::empty_string($tag['attribute']['cols'])) { - $w = intval($tag['attribute']['cols']) * $this->GetStringWidth(chr(32)) * 2; - } else { - $w = 40; - } - if (isset($tag['attribute']['rows']) AND !TCPDF_STATIC::empty_string($tag['attribute']['rows'])) { - $h = intval($tag['attribute']['rows']) * $this->getCellHeight($this->FontSize); - } else { - $h = 10; - } - $prop['multiline'] = 'true'; - $this->TextField($name, $w, $h, $prop, $opt, '', '', false); - break; - } - case 'select': { - $h = $this->getCellHeight($this->FontSize); - if (isset($tag['attribute']['size']) AND !TCPDF_STATIC::empty_string($tag['attribute']['size'])) { - $h *= ($tag['attribute']['size'] + 1); - } - $prop = array(); - $opt = array(); - if (isset($tag['attribute']['name']) AND !TCPDF_STATIC::empty_string($tag['attribute']['name'])) { - $name = $tag['attribute']['name']; - } else { - break; - } - $w = 0; - if (isset($tag['attribute']['opt']) AND !TCPDF_STATIC::empty_string($tag['attribute']['opt'])) { - $options = explode('#!NwL!#', $tag['attribute']['opt']); - $values = array(); - foreach ($options as $val) { - if (strpos($val, '#!TaB!#') !== false) { - $opts = explode('#!TaB!#', $val); - $values[] = $opts; - $w = max($w, $this->GetStringWidth($opts[1])); - } else { - $values[] = $val; - $w = max($w, $this->GetStringWidth($val)); - } - } - } else { - break; - } - $w *= 2; - if (isset($tag['attribute']['multiple']) AND ($tag['attribute']['multiple']='multiple')) { - $prop['multipleSelection'] = 'true'; - $this->ListBox($name, $w, $h, $values, $prop, $opt, '', '', false); - } else { - $this->ComboBox($name, $w, $h, $values, $prop, $opt, '', '', false); - } - break; - } - case 'tcpdf': { - if (defined('K_TCPDF_CALLS_IN_HTML') AND (K_TCPDF_CALLS_IN_HTML === true)) { - // Special tag used to call TCPDF methods - if (isset($tag['attribute']['method'])) { - $tcpdf_method = $tag['attribute']['method']; - if (method_exists($this, $tcpdf_method)) { - if (isset($tag['attribute']['params']) AND (!empty($tag['attribute']['params']))) { - $params = $this->unserializeTCPDFtagParameters($tag['attribute']['params']); - call_user_func_array(array($this, $tcpdf_method), $params); - } else { - $this->$tcpdf_method(); - } - $this->newline = true; - } - } - } - break; - } - default: { - break; - } - } - // define tags that support borders and background colors - $bordertags = array('blockquote','br','dd','dl','div','dt','h1','h2','h3','h4','h5','h6','hr','li','ol','p','pre','ul','tcpdf','table'); - if (in_array($tag['value'], $bordertags)) { - // set border - $dom[$key]['borderposition'] = $this->getBorderStartPosition(); - } - if ($dom[$key]['self'] AND isset($dom[$key]['attribute']['pagebreakafter'])) { - $pba = $dom[$key]['attribute']['pagebreakafter']; - // check for pagebreak - if (($pba == 'true') OR ($pba == 'left') OR ($pba == 'right')) { - // add a page (or trig AcceptPageBreak() for multicolumn mode) - $this->checkPageBreak($this->PageBreakTrigger + 1); - } - if ((($pba == 'left') AND (((!$this->rtl) AND (($this->page % 2) == 0)) OR (($this->rtl) AND (($this->page % 2) != 0)))) - OR (($pba == 'right') AND (((!$this->rtl) AND (($this->page % 2) != 0)) OR (($this->rtl) AND (($this->page % 2) == 0))))) { - // add a page (or trig AcceptPageBreak() for multicolumn mode) - $this->checkPageBreak($this->PageBreakTrigger + 1); - } - } - return $dom; - } - - /** - * Process closing tags. - * @param array $dom html dom array - * @param int $key current element id - * @param boolean $cell if true add the default left (or right if RTL) padding to each new line (default false). - * @param int $maxbottomliney maximum y value of current line - * @return array $dom - * @protected - */ - protected function closeHTMLTagHandler($dom, $key, $cell, $maxbottomliney=0) { - $tag = $dom[$key]; - $parent = $dom[($dom[$key]['parent'])]; - $lasttag = ((!isset($dom[($key + 1)])) OR ((!isset($dom[($key + 2)])) AND ($dom[($key + 1)]['value'] == 'marker'))); - $in_table_head = false; - // maximum x position (used to draw borders) - if ($this->rtl) { - $xmax = $this->w; - } else { - $xmax = 0; - } - if ($tag['block']) { - $hbz = 0; // distance from y to line bottom - $hb = 0; // vertical space between block tags - // calculate vertical space for block tags - if (isset($this->tagvspaces[$tag['value']][1]['h']) && !empty($this->tagvspaces[$tag['value']][1]['h']) && ($this->tagvspaces[$tag['value']][1]['h'] >= 0)) { - $pre_h = $this->tagvspaces[$tag['value']][1]['h']; - } elseif (isset($parent['fontsize'])) { - $pre_h = $this->getCellHeight($parent['fontsize'] / $this->k); - } else { - $pre_h = $this->getCellHeight($this->FontSize); - } - if (isset($this->tagvspaces[$tag['value']][1]['n'])) { - $cn = $this->tagvspaces[$tag['value']][1]['n']; - } elseif (preg_match('/[h][0-9]/', $tag['value']) > 0) { - $cn = 0.6; - } else { - $cn = 1; - } - if ((!isset($this->tagvspaces[$tag['value']])) AND ($tag['value'] == 'div')) { - $hb = 0; - } else { - $hb = ($cn * $pre_h); - } - if ($maxbottomliney > $this->PageBreakTrigger) { - $hbz = $this->getCellHeight($this->FontSize); - } elseif ($this->y < $maxbottomliney) { - $hbz = ($maxbottomliney - $this->y); - } - } - // Closing tag - switch($tag['value']) { - case 'tr': { - $table_el = $dom[($dom[$key]['parent'])]['parent']; - if (!isset($parent['endy'])) { - $dom[($dom[$key]['parent'])]['endy'] = $this->y; - $parent['endy'] = $this->y; - } - if (!isset($parent['endpage'])) { - $dom[($dom[$key]['parent'])]['endpage'] = $this->page; - $parent['endpage'] = $this->page; - } - if (!isset($parent['endcolumn'])) { - $dom[($dom[$key]['parent'])]['endcolumn'] = $this->current_column; - $parent['endcolumn'] = $this->current_column; - } - // update row-spanned cells - if (isset($dom[$table_el]['rowspans'])) { - foreach ($dom[$table_el]['rowspans'] as $k => $trwsp) { - $dom[$table_el]['rowspans'][$k]['rowspan'] -= 1; - if ($dom[$table_el]['rowspans'][$k]['rowspan'] == 0) { - if (($dom[$table_el]['rowspans'][$k]['endpage'] == $parent['endpage']) AND ($dom[$table_el]['rowspans'][$k]['endcolumn'] == $parent['endcolumn'])) { - $dom[($dom[$key]['parent'])]['endy'] = max($dom[$table_el]['rowspans'][$k]['endy'], $parent['endy']); - } elseif (($dom[$table_el]['rowspans'][$k]['endpage'] > $parent['endpage']) OR ($dom[$table_el]['rowspans'][$k]['endcolumn'] > $parent['endcolumn'])) { - $dom[($dom[$key]['parent'])]['endy'] = $dom[$table_el]['rowspans'][$k]['endy']; - $dom[($dom[$key]['parent'])]['endpage'] = $dom[$table_el]['rowspans'][$k]['endpage']; - $dom[($dom[$key]['parent'])]['endcolumn'] = $dom[$table_el]['rowspans'][$k]['endcolumn']; - } - } - } - // report new endy and endpage to the rowspanned cells - foreach ($dom[$table_el]['rowspans'] as $k => $trwsp) { - if ($dom[$table_el]['rowspans'][$k]['rowspan'] == 0) { - $dom[$table_el]['rowspans'][$k]['endpage'] = max($dom[$table_el]['rowspans'][$k]['endpage'], $dom[($dom[$key]['parent'])]['endpage']); - $dom[($dom[$key]['parent'])]['endpage'] = $dom[$table_el]['rowspans'][$k]['endpage']; - $dom[$table_el]['rowspans'][$k]['endcolumn'] = max($dom[$table_el]['rowspans'][$k]['endcolumn'], $dom[($dom[$key]['parent'])]['endcolumn']); - $dom[($dom[$key]['parent'])]['endcolumn'] = $dom[$table_el]['rowspans'][$k]['endcolumn']; - $dom[$table_el]['rowspans'][$k]['endy'] = max($dom[$table_el]['rowspans'][$k]['endy'], $dom[($dom[$key]['parent'])]['endy']); - $dom[($dom[$key]['parent'])]['endy'] = $dom[$table_el]['rowspans'][$k]['endy']; - } - } - // update remaining rowspanned cells - foreach ($dom[$table_el]['rowspans'] as $k => $trwsp) { - if ($dom[$table_el]['rowspans'][$k]['rowspan'] == 0) { - $dom[$table_el]['rowspans'][$k]['endpage'] = $dom[($dom[$key]['parent'])]['endpage']; - $dom[$table_el]['rowspans'][$k]['endcolumn'] = $dom[($dom[$key]['parent'])]['endcolumn']; - $dom[$table_el]['rowspans'][$k]['endy'] = $dom[($dom[$key]['parent'])]['endy']; - } - } - } - $prev_page = $this->page; - $this->setPage($dom[($dom[$key]['parent'])]['endpage']); - if ($this->num_columns > 1) { - if (($prev_page < $this->page) - AND ((($this->current_column == 0) AND ($dom[($dom[$key]['parent'])]['endcolumn'] == ($this->num_columns - 1))) - OR ($this->current_column == $dom[($dom[$key]['parent'])]['endcolumn']))) { - // page jump - $this->selectColumn(0); - $dom[($dom[$key]['parent'])]['endcolumn'] = 0; - $dom[($dom[$key]['parent'])]['endy'] = $this->y; - } else { - $this->selectColumn($dom[($dom[$key]['parent'])]['endcolumn']); - $this->y = $dom[($dom[$key]['parent'])]['endy']; - } - } else { - $this->y = $dom[($dom[$key]['parent'])]['endy']; - } - if (isset($dom[$table_el]['attribute']['cellspacing'])) { - $this->y += $this->getHTMLUnitToUnits($dom[$table_el]['attribute']['cellspacing'], 1, 'px'); - } elseif (isset($dom[$table_el]['border-spacing'])) { - $this->y += $dom[$table_el]['border-spacing']['V']; - } - $this->Ln(0, $cell); - if ($this->current_column == $parent['startcolumn']) { - $this->x = $parent['startx']; - } - // account for booklet mode - if ($this->page > $parent['startpage']) { - if (($this->rtl) AND ($this->pagedim[$this->page]['orm'] != $this->pagedim[$parent['startpage']]['orm'])) { - $this->x -= ($this->pagedim[$this->page]['orm'] - $this->pagedim[$parent['startpage']]['orm']); - } elseif ((!$this->rtl) AND ($this->pagedim[$this->page]['olm'] != $this->pagedim[$parent['startpage']]['olm'])) { - $this->x += ($this->pagedim[$this->page]['olm'] - $this->pagedim[$parent['startpage']]['olm']); - } - } - break; - } - case 'tablehead': - // closing tag used for the thead part - $in_table_head = true; - $this->inthead = false; - case 'table': { - $table_el = $parent; - // set default border - if (isset($table_el['attribute']['border']) AND ($table_el['attribute']['border'] > 0)) { - // set default border - $border = array('LTRB' => array('width' => $this->getCSSBorderWidth($table_el['attribute']['border']), 'cap'=>'square', 'join'=>'miter', 'dash'=> 0, 'color'=>array(0,0,0))); - } else { - $border = 0; - } - $default_border = $border; - // fix bottom line alignment of last line before page break - foreach ($dom[($dom[$key]['parent'])]['trids'] as $j => $trkey) { - // update row-spanned cells - if (isset($dom[($dom[$key]['parent'])]['rowspans'])) { - foreach ($dom[($dom[$key]['parent'])]['rowspans'] as $k => $trwsp) { - if (isset($prevtrkey) AND ($trwsp['trid'] == $prevtrkey) AND ($trwsp['mrowspan'] > 0)) { - $dom[($dom[$key]['parent'])]['rowspans'][$k]['trid'] = $trkey; - } - if ($dom[($dom[$key]['parent'])]['rowspans'][$k]['trid'] == $trkey) { - $dom[($dom[$key]['parent'])]['rowspans'][$k]['mrowspan'] -= 1; - } - } - } - if (isset($prevtrkey) AND ($dom[$trkey]['startpage'] > $dom[$prevtrkey]['endpage'])) { - $pgendy = $this->pagedim[$dom[$prevtrkey]['endpage']]['hk'] - $this->pagedim[$dom[$prevtrkey]['endpage']]['bm']; - $dom[$prevtrkey]['endy'] = $pgendy; - // update row-spanned cells - if (isset($dom[($dom[$key]['parent'])]['rowspans'])) { - foreach ($dom[($dom[$key]['parent'])]['rowspans'] as $k => $trwsp) { - if (($trwsp['trid'] == $prevtrkey) AND ($trwsp['mrowspan'] >= 0) AND ($trwsp['endpage'] == $dom[$prevtrkey]['endpage'])) { - $dom[($dom[$key]['parent'])]['rowspans'][$k]['endy'] = $pgendy; - $dom[($dom[$key]['parent'])]['rowspans'][$k]['mrowspan'] = -1; - } - } - } - } - $prevtrkey = $trkey; - $table_el = $dom[($dom[$key]['parent'])]; - } - // for each row - if (count($table_el['trids']) > 0) { - unset($xmax); - } - foreach ($table_el['trids'] as $j => $trkey) { - $parent = $dom[$trkey]; - if (!isset($xmax)) { - $xmax = $parent['cellpos'][(count($parent['cellpos']) - 1)]['endx']; - } - // for each cell on the row - foreach ($parent['cellpos'] as $k => $cellpos) { - if (isset($cellpos['rowspanid']) AND ($cellpos['rowspanid'] >= 0)) { - $cellpos['startx'] = $table_el['rowspans'][($cellpos['rowspanid'])]['startx']; - $cellpos['endx'] = $table_el['rowspans'][($cellpos['rowspanid'])]['endx']; - $endy = $table_el['rowspans'][($cellpos['rowspanid'])]['endy']; - $startpage = $table_el['rowspans'][($cellpos['rowspanid'])]['startpage']; - $endpage = $table_el['rowspans'][($cellpos['rowspanid'])]['endpage']; - $startcolumn = $table_el['rowspans'][($cellpos['rowspanid'])]['startcolumn']; - $endcolumn = $table_el['rowspans'][($cellpos['rowspanid'])]['endcolumn']; - } else { - $endy = $parent['endy']; - $startpage = $parent['startpage']; - $endpage = $parent['endpage']; - $startcolumn = $parent['startcolumn']; - $endcolumn = $parent['endcolumn']; - } - if ($this->num_columns == 0) { - $this->num_columns = 1; - } - if (isset($cellpos['border'])) { - $border = $cellpos['border']; - } - if (isset($cellpos['bgcolor']) AND ($cellpos['bgcolor']) !== false) { - $this->setFillColorArray($cellpos['bgcolor']); - $fill = true; - } else { - $fill = false; - } - $x = $cellpos['startx']; - $y = $parent['starty']; - $starty = $y; - $w = abs($cellpos['endx'] - $cellpos['startx']); - // get border modes - $border_start = TCPDF_STATIC::getBorderMode($border, $position='start', $this->opencell); - $border_end = TCPDF_STATIC::getBorderMode($border, $position='end', $this->opencell); - $border_middle = TCPDF_STATIC::getBorderMode($border, $position='middle', $this->opencell); - // design borders around HTML cells. - for ($page = $startpage; $page <= $endpage; ++$page) { // for each page - $ccode = ''; - $this->setPage($page); - if ($this->num_columns < 2) { - // single-column mode - $this->x = $x; - $this->y = $this->tMargin; - } - // account for margin changes - if ($page > $startpage) { - if (($this->rtl) AND ($this->pagedim[$page]['orm'] != $this->pagedim[$startpage]['orm'])) { - $this->x -= ($this->pagedim[$page]['orm'] - $this->pagedim[$startpage]['orm']); - } elseif ((!$this->rtl) AND ($this->pagedim[$page]['olm'] != $this->pagedim[$startpage]['olm'])) { - $this->x += ($this->pagedim[$page]['olm'] - $this->pagedim[$startpage]['olm']); - } - } - if ($startpage == $endpage) { // single page - $deltacol = 0; - $deltath = 0; - for ($column = $startcolumn; $column <= $endcolumn; ++$column) { // for each column - $this->selectColumn($column); - if ($startcolumn == $endcolumn) { // single column - $cborder = $border; - $h = $endy - $parent['starty']; - $this->y = $y; - $this->x = $x; - } elseif ($column == $startcolumn) { // first column - $cborder = $border_start; - $this->y = $starty; - $this->x = $x; - $h = $this->h - $this->y - $this->bMargin; - if ($this->rtl) { - $deltacol = $this->x + $this->rMargin - $this->w; - } else { - $deltacol = $this->x - $this->lMargin; - } - } elseif ($column == $endcolumn) { // end column - $cborder = $border_end; - if (isset($this->columns[$column]['th']['\''.$page.'\''])) { - $this->y = $this->columns[$column]['th']['\''.$page.'\'']; - } - $this->x += $deltacol; - $h = $endy - $this->y; - } else { // middle column - $cborder = $border_middle; - if (isset($this->columns[$column]['th']['\''.$page.'\''])) { - $this->y = $this->columns[$column]['th']['\''.$page.'\'']; - } - $this->x += $deltacol; - $h = $this->h - $this->y - $this->bMargin; - } - $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n"; - } // end for each column - } elseif ($page == $startpage) { // first page - $deltacol = 0; - $deltath = 0; - for ($column = $startcolumn; $column < $this->num_columns; ++$column) { // for each column - $this->selectColumn($column); - if ($column == $startcolumn) { // first column - $cborder = $border_start; - $this->y = $starty; - $this->x = $x; - $h = $this->h - $this->y - $this->bMargin; - if ($this->rtl) { - $deltacol = $this->x + $this->rMargin - $this->w; - } else { - $deltacol = $this->x - $this->lMargin; - } - } else { // middle column - $cborder = $border_middle; - if (isset($this->columns[$column]['th']['\''.$page.'\''])) { - $this->y = $this->columns[$column]['th']['\''.$page.'\'']; - } - $this->x += $deltacol; - $h = $this->h - $this->y - $this->bMargin; - } - $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n"; - } // end for each column - } elseif ($page == $endpage) { // last page - $deltacol = 0; - $deltath = 0; - for ($column = 0; $column <= $endcolumn; ++$column) { // for each column - $this->selectColumn($column); - if ($column == $endcolumn) { // end column - $cborder = $border_end; - if (isset($this->columns[$column]['th']['\''.$page.'\''])) { - $this->y = $this->columns[$column]['th']['\''.$page.'\'']; - } - $this->x += $deltacol; - $h = $endy - $this->y; - } else { // middle column - $cborder = $border_middle; - if (isset($this->columns[$column]['th']['\''.$page.'\''])) { - $this->y = $this->columns[$column]['th']['\''.$page.'\'']; - } - $this->x += $deltacol; - $h = $this->h - $this->y - $this->bMargin; - } - $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n"; - } // end for each column - } else { // middle page - $deltacol = 0; - $deltath = 0; - for ($column = 0; $column < $this->num_columns; ++$column) { // for each column - $this->selectColumn($column); - $cborder = $border_middle; - if (isset($this->columns[$column]['th']['\''.$page.'\''])) { - $this->y = $this->columns[$column]['th']['\''.$page.'\'']; - } - $this->x += $deltacol; - $h = $this->h - $this->y - $this->bMargin; - $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n"; - } // end for each column - } - if (!empty($cborder) OR !empty($fill)) { - $offsetlen = strlen($ccode); - // draw border and fill - if ($this->inxobj) { - // we are inside an XObject template - if (end($this->xobjects[$this->xobjid]['transfmrk']) !== false) { - $pagemarkkey = key($this->xobjects[$this->xobjid]['transfmrk']); - $pagemark = $this->xobjects[$this->xobjid]['transfmrk'][$pagemarkkey]; - $this->xobjects[$this->xobjid]['transfmrk'][$pagemarkkey] += $offsetlen; - } else { - $pagemark = $this->xobjects[$this->xobjid]['intmrk']; - $this->xobjects[$this->xobjid]['intmrk'] += $offsetlen; - } - $pagebuff = $this->xobjects[$this->xobjid]['outdata']; - $pstart = substr($pagebuff, 0, $pagemark); - $pend = substr($pagebuff, $pagemark); - $this->xobjects[$this->xobjid]['outdata'] = $pstart.$ccode.$pend; - } else { - // draw border and fill - if (end($this->transfmrk[$this->page]) !== false) { - $pagemarkkey = key($this->transfmrk[$this->page]); - $pagemark = $this->transfmrk[$this->page][$pagemarkkey]; - } elseif ($this->InFooter) { - $pagemark = $this->footerpos[$this->page]; - } else { - $pagemark = $this->intmrk[$this->page]; - } - $pagebuff = $this->getPageBuffer($this->page); - $pstart = substr($pagebuff, 0, $pagemark); - $pend = substr($pagebuff, $pagemark); - $this->setPageBuffer($this->page, $pstart.$ccode.$pend); - } - } - } // end for each page - // restore default border - $border = $default_border; - } // end for each cell on the row - if (isset($table_el['attribute']['cellspacing'])) { - $this->y += $this->getHTMLUnitToUnits($table_el['attribute']['cellspacing'], 1, 'px'); - } elseif (isset($table_el['border-spacing'])) { - $this->y += $table_el['border-spacing']['V']; - } - $this->Ln(0, $cell); - $this->x = $parent['startx']; - if ($endpage > $startpage) { - if (($this->rtl) AND ($this->pagedim[$endpage]['orm'] != $this->pagedim[$startpage]['orm'])) { - $this->x += ($this->pagedim[$endpage]['orm'] - $this->pagedim[$startpage]['orm']); - } elseif ((!$this->rtl) AND ($this->pagedim[$endpage]['olm'] != $this->pagedim[$startpage]['olm'])) { - $this->x += ($this->pagedim[$endpage]['olm'] - $this->pagedim[$startpage]['olm']); - } - } - } - if (!$in_table_head) { // we are not inside a thead section - $this->cell_padding = isset($table_el['old_cell_padding']) ? $table_el['old_cell_padding'] : null; - // reset row height - $this->resetLastH(); - if (($this->page == ($this->numpages - 1)) AND ($this->pageopen[$this->numpages])) { - $plendiff = ($this->pagelen[$this->numpages] - $this->emptypagemrk[$this->numpages]); - if (($plendiff > 0) AND ($plendiff < 60)) { - $pagediff = substr($this->getPageBuffer($this->numpages), $this->emptypagemrk[$this->numpages], $plendiff); - if (substr($pagediff, 0, 5) == 'BT /F') { - // the difference is only a font setting - $plendiff = 0; - } - } - if ($plendiff == 0) { - // remove last blank page - $this->deletePage($this->numpages); - } - } - if (isset($this->theadMargins['top'])) { - // restore top margin - $this->tMargin = $this->theadMargins['top']; - } - if (!isset($table_el['attribute']['nested']) OR ($table_el['attribute']['nested'] != 'true')) { - // reset main table header - $this->thead = ''; - $this->theadMargins = array(); - $this->pagedim[$this->page]['tm'] = $this->tMargin; - } - } - $parent = $table_el; - break; - } - case 'a': { - $this->HREF = array(); - break; - } - case 'sup': { - $this->setXY($this->GetX(), $this->GetY() + ((0.7 * $parent['fontsize']) / $this->k)); - break; - } - case 'sub': { - $this->setXY($this->GetX(), $this->GetY() - ((0.3 * $parent['fontsize']) / $this->k)); - break; - } - case 'div': { - $this->addHTMLVertSpace($hbz, $hb, $cell, false, $lasttag); - break; - } - case 'blockquote': { - if ($this->rtl) { - $this->rMargin -= $this->listindent; - } else { - $this->lMargin -= $this->listindent; - } - --$this->listindentlevel; - $this->addHTMLVertSpace($hbz, $hb, $cell, false, $lasttag); - break; - } - case 'p': { - $this->addHTMLVertSpace($hbz, $hb, $cell, false, $lasttag); - break; - } - case 'pre': { - $this->addHTMLVertSpace($hbz, $hb, $cell, false, $lasttag); - $this->premode = false; - break; - } - case 'dl': { - --$this->listnum; - if ($this->listnum <= 0) { - $this->listnum = 0; - $this->addHTMLVertSpace($hbz, $hb, $cell, false, $lasttag); - } else { - $this->addHTMLVertSpace(0, 0, $cell, false, $lasttag); - } - $this->resetLastH(); - break; - } - case 'dt': { - $this->lispacer = ''; - $this->addHTMLVertSpace(0, 0, $cell, false, $lasttag); - break; - } - case 'dd': { - $this->lispacer = ''; - if ($this->rtl) { - $this->rMargin -= $this->listindent; - } else { - $this->lMargin -= $this->listindent; - } - --$this->listindentlevel; - $this->addHTMLVertSpace(0, 0, $cell, false, $lasttag); - break; - } - case 'ul': - case 'ol': { - --$this->listnum; - $this->lispacer = ''; - if ($this->rtl) { - $this->rMargin -= $this->listindent; - } else { - $this->lMargin -= $this->listindent; - } - --$this->listindentlevel; - if ($this->listnum <= 0) { - $this->listnum = 0; - $this->addHTMLVertSpace($hbz, $hb, $cell, false, $lasttag); - } else { - $this->addHTMLVertSpace(0, 0, $cell, false, $lasttag); - } - $this->resetLastH(); - break; - } - case 'li': { - $this->lispacer = ''; - $this->addHTMLVertSpace(0, 0, $cell, false, $lasttag); - break; - } - case 'h1': - case 'h2': - case 'h3': - case 'h4': - case 'h5': - case 'h6': { - $this->addHTMLVertSpace($hbz, $hb, $cell, false, $lasttag); - break; - } - // Form fields (since 4.8.000 - 2009-09-07) - case 'form': { - $this->form_action = ''; - $this->form_enctype = 'application/x-www-form-urlencoded'; - break; - } - default : { - break; - } - } - // draw border and background (if any) - $this->drawHTMLTagBorder($parent, $xmax); - if (isset($dom[($dom[$key]['parent'])]['attribute']['pagebreakafter'])) { - $pba = $dom[($dom[$key]['parent'])]['attribute']['pagebreakafter']; - // check for pagebreak - if (($pba == 'true') OR ($pba == 'left') OR ($pba == 'right')) { - // add a page (or trig AcceptPageBreak() for multicolumn mode) - $this->checkPageBreak($this->PageBreakTrigger + 1); - } - if ((($pba == 'left') AND (((!$this->rtl) AND (($this->page % 2) == 0)) OR (($this->rtl) AND (($this->page % 2) != 0)))) - OR (($pba == 'right') AND (((!$this->rtl) AND (($this->page % 2) != 0)) OR (($this->rtl) AND (($this->page % 2) == 0))))) { - // add a page (or trig AcceptPageBreak() for multicolumn mode) - $this->checkPageBreak($this->PageBreakTrigger + 1); - } - } - $this->tmprtl = false; - return $dom; - } - - /** - * Add vertical spaces if needed. - * @param string $hbz Distance between current y and line bottom. - * @param string $hb The height of the break. - * @param boolean $cell if true add the default left (or right if RTL) padding to each new line (default false). - * @param boolean $firsttag set to true when the tag is the first. - * @param boolean $lasttag set to true when the tag is the last. - * @protected - */ - protected function addHTMLVertSpace($hbz=0, $hb=0, $cell=false, $firsttag=false, $lasttag=false) { - if ($firsttag) { - $this->Ln(0, $cell); - $this->htmlvspace = 0; - return; - } - if ($lasttag) { - $this->Ln($hbz, $cell); - $this->htmlvspace = 0; - return; - } - if ($hb < $this->htmlvspace) { - $hd = 0; - } else { - $hd = $hb - $this->htmlvspace; - $this->htmlvspace = $hb; - } - $this->Ln(($hbz + $hd), $cell); - } - - /** - * Return the starting coordinates to draw an html border - * @return array containing top-left border coordinates - * @protected - * @since 5.7.000 (2010-08-03) - */ - protected function getBorderStartPosition() { - if ($this->rtl) { - $xmax = $this->lMargin; - } else { - $xmax = $this->w - $this->rMargin; - } - return array('page' => $this->page, 'column' => $this->current_column, 'x' => $this->x, 'y' => $this->y, 'xmax' => $xmax); - } - - /** - * Draw an HTML block border and fill - * @param array $tag array of tag properties. - * @param int $xmax end X coordinate for border. - * @protected - * @since 5.7.000 (2010-08-03) - */ - protected function drawHTMLTagBorder($tag, $xmax) { - if (!isset($tag['borderposition'])) { - // nothing to draw - return; - } - $prev_x = $this->x; - $prev_y = $this->y; - $prev_lasth = $this->lasth; - $border = 0; - $fill = false; - $this->lasth = 0; - if (isset($tag['border']) AND !empty($tag['border'])) { - // get border style - $border = $tag['border']; - if (!TCPDF_STATIC::empty_string($this->thead) AND (!$this->inthead)) { - // border for table header - $border = TCPDF_STATIC::getBorderMode($border, $position='middle', $this->opencell); - } - } - if (isset($tag['bgcolor']) AND ($tag['bgcolor'] !== false)) { - // get background color - $old_bgcolor = $this->bgcolor; - $this->setFillColorArray($tag['bgcolor']); - $fill = true; - } - if (!$border AND !$fill) { - // nothing to draw - return; - } - if (isset($tag['attribute']['cellspacing'])) { - $clsp = $this->getHTMLUnitToUnits($tag['attribute']['cellspacing'], 1, 'px'); - $cellspacing = array('H' => $clsp, 'V' => $clsp); - } elseif (isset($tag['border-spacing'])) { - $cellspacing = $tag['border-spacing']; - } else { - $cellspacing = array('H' => 0, 'V' => 0); - } - if (($tag['value'] != 'table') AND (is_array($border)) AND (!empty($border))) { - // draw the border externally respect the sqare edge. - $border['mode'] = 'ext'; - } - if ($this->rtl) { - if ($xmax >= $tag['borderposition']['x']) { - $xmax = $tag['borderposition']['xmax']; - } - $w = ($tag['borderposition']['x'] - $xmax); - } else { - if ($xmax <= $tag['borderposition']['x']) { - $xmax = $tag['borderposition']['xmax']; - } - $w = ($xmax - $tag['borderposition']['x']); - } - if ($w <= 0) { - return; - } - $w += $cellspacing['H']; - $startpage = $tag['borderposition']['page']; - $startcolumn = $tag['borderposition']['column']; - $x = $tag['borderposition']['x']; - $y = $tag['borderposition']['y']; - $endpage = $this->page; - $starty = $tag['borderposition']['y'] - $cellspacing['V']; - $currentY = $this->y; - $this->x = $x; - // get latest column - $endcolumn = $this->current_column; - if ($this->num_columns == 0) { - $this->num_columns = 1; - } - // get border modes - $border_start = TCPDF_STATIC::getBorderMode($border, $position='start', $this->opencell); - $border_end = TCPDF_STATIC::getBorderMode($border, $position='end', $this->opencell); - $border_middle = TCPDF_STATIC::getBorderMode($border, $position='middle', $this->opencell); - // temporary disable page regions - $temp_page_regions = $this->page_regions; - $this->page_regions = array(); - // design borders around HTML cells. - for ($page = $startpage; $page <= $endpage; ++$page) { // for each page - $ccode = ''; - $this->setPage($page); - if ($this->num_columns < 2) { - // single-column mode - $this->x = $x; - $this->y = $this->tMargin; - } - // account for margin changes - if ($page > $startpage) { - if (($this->rtl) AND ($this->pagedim[$page]['orm'] != $this->pagedim[$startpage]['orm'])) { - $this->x -= ($this->pagedim[$page]['orm'] - $this->pagedim[$startpage]['orm']); - } elseif ((!$this->rtl) AND ($this->pagedim[$page]['olm'] != $this->pagedim[$startpage]['olm'])) { - $this->x += ($this->pagedim[$page]['olm'] - $this->pagedim[$startpage]['olm']); - } - } - if ($startpage == $endpage) { - // single page - for ($column = $startcolumn; $column <= $endcolumn; ++$column) { // for each column - $this->selectColumn($column); - if ($startcolumn == $endcolumn) { // single column - $cborder = $border; - $h = ($currentY - $y) + $cellspacing['V']; - $this->y = $starty; - } elseif ($column == $startcolumn) { // first column - $cborder = $border_start; - $this->y = $starty; - $h = $this->h - $this->y - $this->bMargin; - } elseif ($column == $endcolumn) { // end column - $cborder = $border_end; - $h = $currentY - $this->y; - } else { // middle column - $cborder = $border_middle; - $h = $this->h - $this->y - $this->bMargin; - } - $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n"; - } // end for each column - } elseif ($page == $startpage) { // first page - for ($column = $startcolumn; $column < $this->num_columns; ++$column) { // for each column - $this->selectColumn($column); - if ($column == $startcolumn) { // first column - $cborder = $border_start; - $this->y = $starty; - $h = $this->h - $this->y - $this->bMargin; - } else { // middle column - $cborder = $border_middle; - $h = $this->h - $this->y - $this->bMargin; - } - $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n"; - } // end for each column - } elseif ($page == $endpage) { // last page - for ($column = 0; $column <= $endcolumn; ++$column) { // for each column - $this->selectColumn($column); - if ($column == $endcolumn) { - // end column - $cborder = $border_end; - $h = $currentY - $this->y; - } else { - // middle column - $cborder = $border_middle; - $h = $this->h - $this->y - $this->bMargin; - } - $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n"; - } // end for each column - } else { // middle page - for ($column = 0; $column < $this->num_columns; ++$column) { // for each column - $this->selectColumn($column); - $cborder = $border_middle; - $h = $this->h - $this->y - $this->bMargin; - $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n"; - } // end for each column - } - if ($cborder OR $fill) { - $offsetlen = strlen($ccode); - // draw border and fill - if ($this->inxobj) { - // we are inside an XObject template - if (end($this->xobjects[$this->xobjid]['transfmrk']) !== false) { - $pagemarkkey = key($this->xobjects[$this->xobjid]['transfmrk']); - $pagemark = $this->xobjects[$this->xobjid]['transfmrk'][$pagemarkkey]; - $this->xobjects[$this->xobjid]['transfmrk'][$pagemarkkey] += $offsetlen; - } else { - $pagemark = $this->xobjects[$this->xobjid]['intmrk']; - $this->xobjects[$this->xobjid]['intmrk'] += $offsetlen; - } - $pagebuff = $this->xobjects[$this->xobjid]['outdata']; - $pstart = substr($pagebuff, 0, $pagemark); - $pend = substr($pagebuff, $pagemark); - $this->xobjects[$this->xobjid]['outdata'] = $pstart.$ccode.$pend; - } else { - if (end($this->transfmrk[$this->page]) !== false) { - $pagemarkkey = key($this->transfmrk[$this->page]); - $pagemark = $this->transfmrk[$this->page][$pagemarkkey]; - } elseif ($this->InFooter) { - $pagemark = $this->footerpos[$this->page]; - } else { - $pagemark = $this->intmrk[$this->page]; - } - $pagebuff = $this->getPageBuffer($this->page); - $pstart = substr($pagebuff, 0, $pagemark); - $pend = substr($pagebuff, $pagemark); - $this->setPageBuffer($this->page, $pstart.$ccode.$pend); - $this->bordermrk[$this->page] += $offsetlen; - $this->cntmrk[$this->page] += $offsetlen; - } - } - } // end for each page - // restore page regions - $this->page_regions = $temp_page_regions; - if (isset($old_bgcolor)) { - // restore background color - $this->setFillColorArray($old_bgcolor); - } - // restore pointer position - $this->x = $prev_x; - $this->y = $prev_y; - $this->lasth = $prev_lasth; - } - - /** - * Set the default bullet to be used as LI bullet symbol - * @param string $symbol character or string to be used (legal values are: '' = automatic, '!' = auto bullet, '#' = auto numbering, 'disc', 'disc', 'circle', 'square', '1', 'decimal', 'decimal-leading-zero', 'i', 'lower-roman', 'I', 'upper-roman', 'a', 'lower-alpha', 'lower-latin', 'A', 'upper-alpha', 'upper-latin', 'lower-greek', 'img|type|width|height|image.ext') - * @public - * @since 4.0.028 (2008-09-26) - */ - public function setLIsymbol($symbol='!') { - // check for custom image symbol - if (substr($symbol, 0, 4) == 'img|') { - $this->lisymbol = $symbol; - return; - } - $symbol = strtolower($symbol); - $valid_symbols = array('!', '#', 'disc', 'circle', 'square', '1', 'decimal', 'decimal-leading-zero', 'i', 'lower-roman', 'I', 'upper-roman', 'a', 'lower-alpha', 'lower-latin', 'A', 'upper-alpha', 'upper-latin', 'lower-greek'); - if (in_array($symbol, $valid_symbols)) { - $this->lisymbol = $symbol; - } else { - $this->lisymbol = ''; - } - } - - /** - * Set the booklet mode for double-sided pages. - * @param boolean $booklet true set the booklet mode on, false otherwise. - * @param float $inner Inner page margin. - * @param float $outer Outer page margin. - * @public - * @since 4.2.000 (2008-10-29) - */ - public function setBooklet($booklet=true, $inner=-1, $outer=-1) { - $this->booklet = $booklet; - if ($inner >= 0) { - $this->lMargin = $inner; - } - if ($outer >= 0) { - $this->rMargin = $outer; - } - } - - /** - * Swap the left and right margins. - * @param boolean $reverse if true swap left and right margins. - * @protected - * @since 4.2.000 (2008-10-29) - */ - protected function swapMargins($reverse=true) { - if ($reverse) { - // swap left and right margins - $mtemp = $this->original_lMargin; - $this->original_lMargin = $this->original_rMargin; - $this->original_rMargin = $mtemp; - $deltam = $this->original_lMargin - $this->original_rMargin; - $this->lMargin += $deltam; - $this->rMargin -= $deltam; - } - } - - /** - * Set the vertical spaces for HTML tags. - * The array must have the following structure (example): - * $tagvs = array('h1' => array(0 => array('h' => '', 'n' => 2), 1 => array('h' => 1.3, 'n' => 1))); - * The first array level contains the tag names, - * the second level contains 0 for opening tags or 1 for closing tags, - * the third level contains the vertical space unit (h) and the number spaces to add (n). - * If the h parameter is not specified, default values are used. - * @param array $tagvs array of tags and relative vertical spaces. - * @public - * @since 4.2.001 (2008-10-30) - */ - public function setHtmlVSpace($tagvs) { - $this->tagvspaces = $tagvs; - } - - /** - * Set custom width for list indentation. - * @param float $width width of the indentation. Use negative value to disable it. - * @public - * @since 4.2.007 (2008-11-12) - */ - public function setListIndentWidth($width) { - return $this->customlistindent = floatval($width); - } - - /** - * Set the top/bottom cell sides to be open or closed when the cell cross the page. - * @param boolean $isopen if true keeps the top/bottom border open for the cell sides that cross the page. - * @public - * @since 4.2.010 (2008-11-14) - */ - public function setOpenCell($isopen) { - $this->opencell = $isopen; - } - - /** - * Set the color and font style for HTML links. - * @param array $color RGB array of colors - * @param string $fontstyle additional font styles to add - * @public - * @since 4.4.003 (2008-12-09) - */ - public function setHtmlLinksStyle($color=array(0,0,255), $fontstyle='U') { - $this->htmlLinkColorArray = $color; - $this->htmlLinkFontStyle = $fontstyle; - } - - /** - * Convert HTML string containing value and unit of measure to user's units or points. - * @param string $htmlval String containing values and unit. - * @param string $refsize Reference value in points. - * @param string $defaultunit Default unit (can be one of the following: %, em, ex, px, in, mm, pc, pt). - * @param boolean $points If true returns points, otherwise returns value in user's units. - * @return float value in user's unit or point if $points=true - * @public - * @since 4.4.004 (2008-12-10) - */ - public function getHTMLUnitToUnits($htmlval, $refsize=1, $defaultunit='px', $points=false) { - $supportedunits = array('%', 'em', 'ex', 'px', 'in', 'cm', 'mm', 'pc', 'pt'); - $retval = 0; - $value = 0; - $unit = 'px'; - if ($points) { - $k = 1; - } else { - $k = $this->k; - } - if (in_array($defaultunit, $supportedunits)) { - $unit = $defaultunit; - } - if (is_numeric($htmlval)) { - $value = floatval($htmlval); - } elseif (preg_match('/([0-9\.\-\+]+)/', $htmlval, $mnum)) { - $value = floatval($mnum[1]); - if (preg_match('/([a-z%]+)/', $htmlval, $munit)) { - if (in_array($munit[1], $supportedunits)) { - $unit = $munit[1]; - } - } - } - switch ($unit) { - // percentage - case '%': { - $retval = (($value * $refsize) / 100); - break; - } - // relative-size - case 'em': { - $retval = ($value * $refsize); - break; - } - // height of lower case 'x' (about half the font-size) - case 'ex': { - $retval = ($value * ($refsize / 2)); - break; - } - // absolute-size - case 'in': { - $retval = (($value * $this->dpi) / $k); - break; - } - // centimeters - case 'cm': { - $retval = (($value / 2.54 * $this->dpi) / $k); - break; - } - // millimeters - case 'mm': { - $retval = (($value / 25.4 * $this->dpi) / $k); - break; - } - // one pica is 12 points - case 'pc': { - $retval = (($value * 12) / $k); - break; - } - // points - case 'pt': { - $retval = ($value / $k); - break; - } - // pixels - case 'px': { - $retval = $this->pixelsToUnits($value); - if ($points) { - $retval *= $this->k; - } - break; - } - } - return $retval; - } - - /** - * Output an HTML list bullet or ordered item symbol - * @param int $listdepth list nesting level - * @param string $listtype type of list - * @param float $size current font size - * @protected - * @since 4.4.004 (2008-12-10) - */ - protected function putHtmlListBullet($listdepth, $listtype='', $size=10) { - if ($this->state != 2) { - return; - } - $size /= $this->k; - $fill = ''; - $bgcolor = $this->bgcolor; - $color = $this->fgcolor; - $strokecolor = $this->strokecolor; - $width = 0; - $textitem = ''; - $tmpx = $this->x; - $lspace = $this->GetStringWidth(' '); - if ($listtype == '^') { - // special symbol used for avoid justification of rect bullet - $this->lispacer = ''; - return; - } elseif ($listtype == '!') { - // set default list type for unordered list - $deftypes = array('disc', 'circle', 'square'); - $listtype = $deftypes[($listdepth - 1) % 3]; - } elseif ($listtype == '#') { - // set default list type for ordered list - $listtype = 'decimal'; - } elseif (substr($listtype, 0, 4) == 'img|') { - // custom image type ('img|type|width|height|image.ext') - $img = explode('|', $listtype); - $listtype = 'img'; - } - switch ($listtype) { - // unordered types - case 'none': { - break; - } - case 'disc': { - $r = $size / 6; - $lspace += (2 * $r); - if ($this->rtl) { - $this->x += $lspace; - } else { - $this->x -= $lspace; - } - $this->Circle(($this->x + $r), ($this->y + ($this->lasth / 2)), $r, 0, 360, 'F', array(), $color, 8); - break; - } - case 'circle': { - $r = $size / 6; - $lspace += (2 * $r); - if ($this->rtl) { - $this->x += $lspace; - } else { - $this->x -= $lspace; - } - $prev_line_style = $this->linestyleWidth.' '.$this->linestyleCap.' '.$this->linestyleJoin.' '.$this->linestyleDash.' '.$this->DrawColor; - $new_line_style = array('width' => ($r / 3), 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'phase' => 0, 'color'=>$color); - $this->Circle(($this->x + $r), ($this->y + ($this->lasth / 2)), ($r * (1 - (1/6))), 0, 360, 'D', $new_line_style, array(), 8); - $this->_out($prev_line_style); // restore line settings - break; - } - case 'square': { - $l = $size / 3; - $lspace += $l; - if ($this->rtl) {; - $this->x += $lspace; - } else { - $this->x -= $lspace; - } - $this->Rect($this->x, ($this->y + (($this->lasth - $l) / 2)), $l, $l, 'F', array(), $color); - break; - } - case 'img': { - // 1=>type, 2=>width, 3=>height, 4=>image.ext - $lspace += $img[2]; - if ($this->rtl) {; - $this->x += $lspace; - } else { - $this->x -= $lspace; - } - $imgtype = strtolower($img[1]); - $prev_y = $this->y; - switch ($imgtype) { - case 'svg': { - $this->ImageSVG($img[4], $this->x, ($this->y + (($this->lasth - $img[3]) / 2)), $img[2], $img[3], '', 'T', '', 0, false); - break; - } - case 'ai': - case 'eps': { - $this->ImageEps($img[4], $this->x, ($this->y + (($this->lasth - $img[3]) / 2)), $img[2], $img[3], '', true, 'T', '', 0, false); - break; - } - default: { - $this->Image($img[4], $this->x, ($this->y + (($this->lasth - $img[3]) / 2)), $img[2], $img[3], $img[1], '', 'T', false, 300, '', false, false, 0, false, false, false); - break; - } - } - $this->y = $prev_y; - break; - } - // ordered types - // $this->listcount[$this->listnum]; - // $textitem - case '1': - case 'decimal': { - $textitem = $this->listcount[$this->listnum]; - break; - } - case 'decimal-leading-zero': { - $textitem = sprintf('%02d', $this->listcount[$this->listnum]); - break; - } - case 'i': - case 'lower-roman': { - $textitem = strtolower(TCPDF_STATIC::intToRoman($this->listcount[$this->listnum])); - break; - } - case 'I': - case 'upper-roman': { - $textitem = TCPDF_STATIC::intToRoman($this->listcount[$this->listnum]); - break; - } - case 'a': - case 'lower-alpha': - case 'lower-latin': { - $textitem = chr(97 + $this->listcount[$this->listnum] - 1); - break; - } - case 'A': - case 'upper-alpha': - case 'upper-latin': { - $textitem = chr(65 + $this->listcount[$this->listnum] - 1); - break; - } - case 'lower-greek': { - $textitem = TCPDF_FONTS::unichr((945 + $this->listcount[$this->listnum] - 1), $this->isunicode); - break; - } - /* - // Types to be implemented (special handling) - case 'hebrew': { - break; - } - case 'armenian': { - break; - } - case 'georgian': { - break; - } - case 'cjk-ideographic': { - break; - } - case 'hiragana': { - break; - } - case 'katakana': { - break; - } - case 'hiragana-iroha': { - break; - } - case 'katakana-iroha': { - break; - } - */ - default: { - $textitem = $this->listcount[$this->listnum]; - } - } - if (!TCPDF_STATIC::empty_string($textitem)) { - // Check whether we need a new page or new column - $prev_y = $this->y; - $h = $this->getCellHeight($this->FontSize); - if ($this->checkPageBreak($h) OR ($this->y < $prev_y)) { - $tmpx = $this->x; - } - // print ordered item - if ($this->rtl) { - $textitem = '.'.$textitem; - } else { - $textitem = $textitem.'.'; - } - $lspace += $this->GetStringWidth($textitem); - if ($this->rtl) { - $this->x += $lspace; - } else { - $this->x -= $lspace; - } - $this->Write($this->lasth, $textitem, '', false, '', false, 0, false); - } - $this->x = $tmpx; - $this->lispacer = '^'; - // restore colors - $this->setFillColorArray($bgcolor); - $this->setDrawColorArray($strokecolor); - $this->settextColorArray($color); - } - - /** - * Returns current graphic variables as array. - * @return array of graphic variables - * @protected - * @since 4.2.010 (2008-11-14) - */ - protected function getGraphicVars() { - $grapvars = array( - 'FontFamily' => $this->FontFamily, - 'FontStyle' => $this->FontStyle, - 'FontSizePt' => $this->FontSizePt, - 'rMargin' => $this->rMargin, - 'lMargin' => $this->lMargin, - 'cell_padding' => $this->cell_padding, - 'cell_margin' => $this->cell_margin, - 'LineWidth' => $this->LineWidth, - 'linestyleWidth' => $this->linestyleWidth, - 'linestyleCap' => $this->linestyleCap, - 'linestyleJoin' => $this->linestyleJoin, - 'linestyleDash' => $this->linestyleDash, - 'textrendermode' => $this->textrendermode, - 'textstrokewidth' => $this->textstrokewidth, - 'DrawColor' => $this->DrawColor, - 'FillColor' => $this->FillColor, - 'TextColor' => $this->TextColor, - 'ColorFlag' => $this->ColorFlag, - 'bgcolor' => $this->bgcolor, - 'fgcolor' => $this->fgcolor, - 'htmlvspace' => $this->htmlvspace, - 'listindent' => $this->listindent, - 'listindentlevel' => $this->listindentlevel, - 'listnum' => $this->listnum, - 'listordered' => $this->listordered, - 'listcount' => $this->listcount, - 'lispacer' => $this->lispacer, - 'cell_height_ratio' => $this->cell_height_ratio, - 'font_stretching' => $this->font_stretching, - 'font_spacing' => $this->font_spacing, - 'alpha' => $this->alpha, - // extended - 'lasth' => $this->lasth, - 'tMargin' => $this->tMargin, - 'bMargin' => $this->bMargin, - 'AutoPageBreak' => $this->AutoPageBreak, - 'PageBreakTrigger' => $this->PageBreakTrigger, - 'x' => $this->x, - 'y' => $this->y, - 'w' => $this->w, - 'h' => $this->h, - 'wPt' => $this->wPt, - 'hPt' => $this->hPt, - 'fwPt' => $this->fwPt, - 'fhPt' => $this->fhPt, - 'page' => $this->page, - 'current_column' => $this->current_column, - 'num_columns' => $this->num_columns - ); - return $grapvars; - } - - /** - * Set graphic variables. - * @param array $gvars array of graphic variablesto restore - * @param boolean $extended if true restore extended graphic variables - * @protected - * @since 4.2.010 (2008-11-14) - */ - protected function setGraphicVars($gvars, $extended=false) { - if ($this->state != 2) { - return; - } - $this->FontFamily = $gvars['FontFamily']; - $this->FontStyle = $gvars['FontStyle']; - $this->FontSizePt = $gvars['FontSizePt']; - $this->rMargin = $gvars['rMargin']; - $this->lMargin = $gvars['lMargin']; - $this->cell_padding = $gvars['cell_padding']; - $this->cell_margin = $gvars['cell_margin']; - $this->LineWidth = $gvars['LineWidth']; - $this->linestyleWidth = $gvars['linestyleWidth']; - $this->linestyleCap = $gvars['linestyleCap']; - $this->linestyleJoin = $gvars['linestyleJoin']; - $this->linestyleDash = $gvars['linestyleDash']; - $this->textrendermode = $gvars['textrendermode']; - $this->textstrokewidth = $gvars['textstrokewidth']; - $this->DrawColor = $gvars['DrawColor']; - $this->FillColor = $gvars['FillColor']; - $this->TextColor = $gvars['TextColor']; - $this->ColorFlag = $gvars['ColorFlag']; - $this->bgcolor = $gvars['bgcolor']; - $this->fgcolor = $gvars['fgcolor']; - $this->htmlvspace = $gvars['htmlvspace']; - $this->listindent = $gvars['listindent']; - $this->listindentlevel = $gvars['listindentlevel']; - $this->listnum = $gvars['listnum']; - $this->listordered = $gvars['listordered']; - $this->listcount = $gvars['listcount']; - $this->lispacer = $gvars['lispacer']; - $this->cell_height_ratio = $gvars['cell_height_ratio']; - $this->font_stretching = $gvars['font_stretching']; - $this->font_spacing = $gvars['font_spacing']; - $this->alpha = $gvars['alpha']; - if ($extended) { - // restore extended values - $this->lasth = $gvars['lasth']; - $this->tMargin = $gvars['tMargin']; - $this->bMargin = $gvars['bMargin']; - $this->AutoPageBreak = $gvars['AutoPageBreak']; - $this->PageBreakTrigger = $gvars['PageBreakTrigger']; - $this->x = $gvars['x']; - $this->y = $gvars['y']; - $this->w = $gvars['w']; - $this->h = $gvars['h']; - $this->wPt = $gvars['wPt']; - $this->hPt = $gvars['hPt']; - $this->fwPt = $gvars['fwPt']; - $this->fhPt = $gvars['fhPt']; - $this->page = $gvars['page']; - $this->current_column = $gvars['current_column']; - $this->num_columns = $gvars['num_columns']; - } - $this->_out(''.$this->linestyleWidth.' '.$this->linestyleCap.' '.$this->linestyleJoin.' '.$this->linestyleDash.' '.$this->DrawColor.' '.$this->FillColor.''); - if (!TCPDF_STATIC::empty_string($this->FontFamily)) { - $this->setFont($this->FontFamily, $this->FontStyle, $this->FontSizePt); - } - } - - /** - * Outputs the "save graphics state" operator 'q' - * @protected - */ - protected function _outSaveGraphicsState() { - $this->_out('q'); - } - - /** - * Outputs the "restore graphics state" operator 'Q' - * @protected - */ - protected function _outRestoreGraphicsState() { - $this->_out('Q'); - } - - /** - * Set buffer content (always append data). - * @param string $data data - * @protected - * @since 4.5.000 (2009-01-02) - */ - protected function setBuffer($data) { - $this->bufferlen += strlen($data); - $this->buffer .= $data; - } - - /** - * Replace the buffer content - * @param string $data data - * @protected - * @since 5.5.000 (2010-06-22) - */ - protected function replaceBuffer($data) { - $this->bufferlen = strlen($data); - $this->buffer = $data; - } - - /** - * Get buffer content. - * @return string buffer content - * @protected - * @since 4.5.000 (2009-01-02) - */ - protected function getBuffer() { - return $this->buffer; - } - - /** - * Set page buffer content. - * @param int $page page number - * @param string $data page data - * @param boolean $append if true append data, false replace. - * @protected - * @since 4.5.000 (2008-12-31) - */ - protected function setPageBuffer($page, $data, $append=false) { - if ($append) { - $this->pages[$page] .= $data; - } else { - $this->pages[$page] = $data; - } - if ($append AND isset($this->pagelen[$page])) { - $this->pagelen[$page] += strlen($data); - } else { - $this->pagelen[$page] = strlen($data); - } - } - - /** - * Get page buffer content. - * @param int $page page number - * @return string page buffer content or false in case of error - * @protected - * @since 4.5.000 (2008-12-31) - */ - protected function getPageBuffer($page) { - if (isset($this->pages[$page])) { - return $this->pages[$page]; - } - return false; - } - - /** - * Set image buffer content. - * @param string $image image key - * @param array $data image data - * @return int image index number - * @protected - * @since 4.5.000 (2008-12-31) - */ - protected function setImageBuffer($image, $data) { - if (($data['i'] = array_search($image, $this->imagekeys)) === FALSE) { - $this->imagekeys[$this->numimages] = $image; - $data['i'] = $this->numimages; - ++$this->numimages; - } - $this->images[$image] = $data; - return $data['i']; - } - - /** - * Set image buffer content for a specified sub-key. - * @param string $image image key - * @param string $key image sub-key - * @param array $data image data - * @protected - * @since 4.5.000 (2008-12-31) - */ - protected function setImageSubBuffer($image, $key, $data) { - if (!isset($this->images[$image])) { - $this->setImageBuffer($image, array()); - } - $this->images[$image][$key] = $data; - } - - /** - * Get image buffer content. - * @param string $image image key - * @return string|false image buffer content or false in case of error - * @protected - * @since 4.5.000 (2008-12-31) - */ - protected function getImageBuffer($image) { - if (isset($this->images[$image])) { - return $this->images[$image]; - } - return false; - } - - /** - * Set font buffer content. - * @param string $font font key - * @param array $data font data - * @protected - * @since 4.5.000 (2009-01-02) - */ - protected function setFontBuffer($font, $data) { - $this->fonts[$font] = $data; - if (!in_array($font, $this->fontkeys)) { - $this->fontkeys[] = $font; - // store object ID for current font - ++$this->n; - $this->font_obj_ids[$font] = $this->n; - $this->setFontSubBuffer($font, 'n', $this->n); - } - } - - /** - * Set font buffer content. - * @param string $font font key - * @param string $key font sub-key - * @param mixed $data font data - * @protected - * @since 4.5.000 (2009-01-02) - */ - protected function setFontSubBuffer($font, $key, $data) { - if (!isset($this->fonts[$font])) { - $this->setFontBuffer($font, array()); - } - $this->fonts[$font][$key] = $data; - } - - /** - * Get font buffer content. - * @param string $font font key - * @return string|false font buffer content or false in case of error - * @protected - * @since 4.5.000 (2009-01-02) - */ - protected function getFontBuffer($font) { - if (isset($this->fonts[$font])) { - return $this->fonts[$font]; - } - return false; - } - - /** - * Move a page to a previous position. - * @param int $frompage number of the source page - * @param int $topage number of the destination page (must be less than $frompage) - * @return bool true in case of success, false in case of error. - * @public - * @since 4.5.000 (2009-01-02) - */ - public function movePage($frompage, $topage) { - if (($frompage > $this->numpages) OR ($frompage <= $topage)) { - return false; - } - if ($frompage == $this->page) { - // close the page before moving it - $this->endPage(); - } - // move all page-related states - $tmppage = $this->getPageBuffer($frompage); - $tmppagedim = $this->pagedim[$frompage]; - $tmppagelen = $this->pagelen[$frompage]; - $tmpintmrk = $this->intmrk[$frompage]; - $tmpbordermrk = $this->bordermrk[$frompage]; - $tmpcntmrk = $this->cntmrk[$frompage]; - $tmppageobjects = $this->pageobjects[$frompage]; - if (isset($this->footerpos[$frompage])) { - $tmpfooterpos = $this->footerpos[$frompage]; - } - if (isset($this->footerlen[$frompage])) { - $tmpfooterlen = $this->footerlen[$frompage]; - } - if (isset($this->transfmrk[$frompage])) { - $tmptransfmrk = $this->transfmrk[$frompage]; - } - if (isset($this->PageAnnots[$frompage])) { - $tmpannots = $this->PageAnnots[$frompage]; - } - if (isset($this->newpagegroup) AND !empty($this->newpagegroup)) { - for ($i = $frompage; $i > $topage; --$i) { - if (isset($this->newpagegroup[$i]) AND (($i + $this->pagegroups[$this->newpagegroup[$i]]) > $frompage)) { - --$this->pagegroups[$this->newpagegroup[$i]]; - break; - } - } - for ($i = $topage; $i > 0; --$i) { - if (isset($this->newpagegroup[$i]) AND (($i + $this->pagegroups[$this->newpagegroup[$i]]) > $topage)) { - ++$this->pagegroups[$this->newpagegroup[$i]]; - break; - } - } - } - for ($i = $frompage; $i > $topage; --$i) { - $j = $i - 1; - // shift pages down - $this->setPageBuffer($i, $this->getPageBuffer($j)); - $this->pagedim[$i] = $this->pagedim[$j]; - $this->pagelen[$i] = $this->pagelen[$j]; - $this->intmrk[$i] = $this->intmrk[$j]; - $this->bordermrk[$i] = $this->bordermrk[$j]; - $this->cntmrk[$i] = $this->cntmrk[$j]; - $this->pageobjects[$i] = $this->pageobjects[$j]; - if (isset($this->footerpos[$j])) { - $this->footerpos[$i] = $this->footerpos[$j]; - } elseif (isset($this->footerpos[$i])) { - unset($this->footerpos[$i]); - } - if (isset($this->footerlen[$j])) { - $this->footerlen[$i] = $this->footerlen[$j]; - } elseif (isset($this->footerlen[$i])) { - unset($this->footerlen[$i]); - } - if (isset($this->transfmrk[$j])) { - $this->transfmrk[$i] = $this->transfmrk[$j]; - } elseif (isset($this->transfmrk[$i])) { - unset($this->transfmrk[$i]); - } - if (isset($this->PageAnnots[$j])) { - $this->PageAnnots[$i] = $this->PageAnnots[$j]; - } elseif (isset($this->PageAnnots[$i])) { - unset($this->PageAnnots[$i]); - } - if (isset($this->newpagegroup[$j])) { - $this->newpagegroup[$i] = $this->newpagegroup[$j]; - unset($this->newpagegroup[$j]); - } - if ($this->currpagegroup == $j) { - $this->currpagegroup = $i; - } - } - $this->setPageBuffer($topage, $tmppage); - $this->pagedim[$topage] = $tmppagedim; - $this->pagelen[$topage] = $tmppagelen; - $this->intmrk[$topage] = $tmpintmrk; - $this->bordermrk[$topage] = $tmpbordermrk; - $this->cntmrk[$topage] = $tmpcntmrk; - $this->pageobjects[$topage] = $tmppageobjects; - if (isset($tmpfooterpos)) { - $this->footerpos[$topage] = $tmpfooterpos; - } elseif (isset($this->footerpos[$topage])) { - unset($this->footerpos[$topage]); - } - if (isset($tmpfooterlen)) { - $this->footerlen[$topage] = $tmpfooterlen; - } elseif (isset($this->footerlen[$topage])) { - unset($this->footerlen[$topage]); - } - if (isset($tmptransfmrk)) { - $this->transfmrk[$topage] = $tmptransfmrk; - } elseif (isset($this->transfmrk[$topage])) { - unset($this->transfmrk[$topage]); - } - if (isset($tmpannots)) { - $this->PageAnnots[$topage] = $tmpannots; - } elseif (isset($this->PageAnnots[$topage])) { - unset($this->PageAnnots[$topage]); - } - // adjust outlines - $tmpoutlines = $this->outlines; - foreach ($tmpoutlines as $key => $outline) { - if (!$outline['f']) { - if (($outline['p'] >= $topage) AND ($outline['p'] < $frompage)) { - $this->outlines[$key]['p'] = ($outline['p'] + 1); - } elseif ($outline['p'] == $frompage) { - $this->outlines[$key]['p'] = $topage; - } - } - } - // adjust dests - $tmpdests = $this->dests; - foreach ($tmpdests as $key => $dest) { - if (!$dest['f']) { - if (($dest['p'] >= $topage) AND ($dest['p'] < $frompage)) { - $this->dests[$key]['p'] = ($dest['p'] + 1); - } elseif ($dest['p'] == $frompage) { - $this->dests[$key]['p'] = $topage; - } - } - } - // adjust links - $tmplinks = $this->links; - foreach ($tmplinks as $key => $link) { - if (!$link['f']) { - if (($link['p'] >= $topage) AND ($link['p'] < $frompage)) { - $this->links[$key]['p'] = ($link['p'] + 1); - } elseif ($link['p'] == $frompage) { - $this->links[$key]['p'] = $topage; - } - } - } - // adjust javascript - $jfrompage = $frompage; - $jtopage = $topage; - if (preg_match_all('/this\.addField\(\'([^\']*)\',\'([^\']*)\',([0-9]+)/', $this->javascript, $pamatch) > 0) { - foreach($pamatch[0] as $pk => $pmatch) { - $pagenum = intval($pamatch[3][$pk]) + 1; - if (($pagenum >= $jtopage) AND ($pagenum < $jfrompage)) { - $newpage = ($pagenum + 1); - } elseif ($pagenum == $jfrompage) { - $newpage = $jtopage; - } else { - $newpage = $pagenum; - } - --$newpage; - $newjs = "this.addField(\'".$pamatch[1][$pk]."\',\'".$pamatch[2][$pk]."\',".$newpage; - $this->javascript = str_replace($pmatch, $newjs, $this->javascript); - } - unset($pamatch); - } - // return to last page - $this->lastPage(true); - return true; - } - - /** - * Remove the specified page. - * @param int $page page to remove - * @return bool true in case of success, false in case of error. - * @public - * @since 4.6.004 (2009-04-23) - */ - public function deletePage($page) { - if (($page < 1) OR ($page > $this->numpages)) { - return false; - } - // delete current page - unset($this->pages[$page]); - unset($this->pagedim[$page]); - unset($this->pagelen[$page]); - unset($this->intmrk[$page]); - unset($this->bordermrk[$page]); - unset($this->cntmrk[$page]); - foreach ($this->pageobjects[$page] as $oid) { - if (isset($this->offsets[$oid])){ - unset($this->offsets[$oid]); - } - } - unset($this->pageobjects[$page]); - if (isset($this->footerpos[$page])) { - unset($this->footerpos[$page]); - } - if (isset($this->footerlen[$page])) { - unset($this->footerlen[$page]); - } - if (isset($this->transfmrk[$page])) { - unset($this->transfmrk[$page]); - } - if (isset($this->PageAnnots[$page])) { - unset($this->PageAnnots[$page]); - } - if (isset($this->newpagegroup) AND !empty($this->newpagegroup)) { - for ($i = $page; $i > 0; --$i) { - if (isset($this->newpagegroup[$i]) AND (($i + $this->pagegroups[$this->newpagegroup[$i]]) > $page)) { - --$this->pagegroups[$this->newpagegroup[$i]]; - break; - } - } - } - if (isset($this->pageopen[$page])) { - unset($this->pageopen[$page]); - } - if ($page < $this->numpages) { - // update remaining pages - for ($i = $page; $i < $this->numpages; ++$i) { - $j = $i + 1; - // shift pages - $this->setPageBuffer($i, $this->getPageBuffer($j)); - $this->pagedim[$i] = $this->pagedim[$j]; - $this->pagelen[$i] = $this->pagelen[$j]; - $this->intmrk[$i] = $this->intmrk[$j]; - $this->bordermrk[$i] = $this->bordermrk[$j]; - $this->cntmrk[$i] = $this->cntmrk[$j]; - $this->pageobjects[$i] = $this->pageobjects[$j]; - if (isset($this->footerpos[$j])) { - $this->footerpos[$i] = $this->footerpos[$j]; - } elseif (isset($this->footerpos[$i])) { - unset($this->footerpos[$i]); - } - if (isset($this->footerlen[$j])) { - $this->footerlen[$i] = $this->footerlen[$j]; - } elseif (isset($this->footerlen[$i])) { - unset($this->footerlen[$i]); - } - if (isset($this->transfmrk[$j])) { - $this->transfmrk[$i] = $this->transfmrk[$j]; - } elseif (isset($this->transfmrk[$i])) { - unset($this->transfmrk[$i]); - } - if (isset($this->PageAnnots[$j])) { - $this->PageAnnots[$i] = $this->PageAnnots[$j]; - } elseif (isset($this->PageAnnots[$i])) { - unset($this->PageAnnots[$i]); - } - if (isset($this->newpagegroup[$j])) { - $this->newpagegroup[$i] = $this->newpagegroup[$j]; - unset($this->newpagegroup[$j]); - } - if ($this->currpagegroup == $j) { - $this->currpagegroup = $i; - } - if (isset($this->pageopen[$j])) { - $this->pageopen[$i] = $this->pageopen[$j]; - } elseif (isset($this->pageopen[$i])) { - unset($this->pageopen[$i]); - } - } - // remove last page - unset($this->pages[$this->numpages]); - unset($this->pagedim[$this->numpages]); - unset($this->pagelen[$this->numpages]); - unset($this->intmrk[$this->numpages]); - unset($this->bordermrk[$this->numpages]); - unset($this->cntmrk[$this->numpages]); - foreach ($this->pageobjects[$this->numpages] as $oid) { - if (isset($this->offsets[$oid])){ - unset($this->offsets[$oid]); - } - } - unset($this->pageobjects[$this->numpages]); - if (isset($this->footerpos[$this->numpages])) { - unset($this->footerpos[$this->numpages]); - } - if (isset($this->footerlen[$this->numpages])) { - unset($this->footerlen[$this->numpages]); - } - if (isset($this->transfmrk[$this->numpages])) { - unset($this->transfmrk[$this->numpages]); - } - if (isset($this->PageAnnots[$this->numpages])) { - unset($this->PageAnnots[$this->numpages]); - } - if (isset($this->newpagegroup[$this->numpages])) { - unset($this->newpagegroup[$this->numpages]); - } - if ($this->currpagegroup == $this->numpages) { - $this->currpagegroup = ($this->numpages - 1); - } - if (isset($this->pagegroups[$this->numpages])) { - unset($this->pagegroups[$this->numpages]); - } - if (isset($this->pageopen[$this->numpages])) { - unset($this->pageopen[$this->numpages]); - } - } - --$this->numpages; - $this->page = $this->numpages; - // adjust outlines - $tmpoutlines = $this->outlines; - foreach ($tmpoutlines as $key => $outline) { - if (!$outline['f']) { - if ($outline['p'] > $page) { - $this->outlines[$key]['p'] = $outline['p'] - 1; - } elseif ($outline['p'] == $page) { - unset($this->outlines[$key]); - } - } - } - // adjust dests - $tmpdests = $this->dests; - foreach ($tmpdests as $key => $dest) { - if (!$dest['f']) { - if ($dest['p'] > $page) { - $this->dests[$key]['p'] = $dest['p'] - 1; - } elseif ($dest['p'] == $page) { - unset($this->dests[$key]); - } - } - } - // adjust links - $tmplinks = $this->links; - foreach ($tmplinks as $key => $link) { - if (!$link['f']) { - if ($link['p'] > $page) { - $this->links[$key]['p'] = $link['p'] - 1; - } elseif ($link['p'] == $page) { - unset($this->links[$key]); - } - } - } - // adjust javascript - $jpage = $page; - if (preg_match_all('/this\.addField\(\'([^\']*)\',\'([^\']*)\',([0-9]+)/', $this->javascript, $pamatch) > 0) { - foreach($pamatch[0] as $pk => $pmatch) { - $pagenum = intval($pamatch[3][$pk]) + 1; - if ($pagenum >= $jpage) { - $newpage = ($pagenum - 1); - } elseif ($pagenum == $jpage) { - $newpage = 1; - } else { - $newpage = $pagenum; - } - --$newpage; - $newjs = "this.addField(\'".$pamatch[1][$pk]."\',\'".$pamatch[2][$pk]."\',".$newpage; - $this->javascript = str_replace($pmatch, $newjs, $this->javascript); - } - unset($pamatch); - } - // return to last page - if ($this->numpages > 0) { - $this->lastPage(true); - } - return true; - } - - /** - * Clone the specified page to a new page. - * @param int $page number of page to copy (0 = current page) - * @return bool true in case of success, false in case of error. - * @public - * @since 4.9.015 (2010-04-20) - */ - public function copyPage($page=0) { - if ($page == 0) { - // default value - $page = $this->page; - } - if (($page < 1) OR ($page > $this->numpages)) { - return false; - } - // close the last page - $this->endPage(); - // copy all page-related states - ++$this->numpages; - $this->page = $this->numpages; - $this->setPageBuffer($this->page, $this->getPageBuffer($page)); - $this->pagedim[$this->page] = $this->pagedim[$page]; - $this->pagelen[$this->page] = $this->pagelen[$page]; - $this->intmrk[$this->page] = $this->intmrk[$page]; - $this->bordermrk[$this->page] = $this->bordermrk[$page]; - $this->cntmrk[$this->page] = $this->cntmrk[$page]; - $this->pageobjects[$this->page] = $this->pageobjects[$page]; - $this->pageopen[$this->page] = false; - if (isset($this->footerpos[$page])) { - $this->footerpos[$this->page] = $this->footerpos[$page]; - } - if (isset($this->footerlen[$page])) { - $this->footerlen[$this->page] = $this->footerlen[$page]; - } - if (isset($this->transfmrk[$page])) { - $this->transfmrk[$this->page] = $this->transfmrk[$page]; - } - if (isset($this->PageAnnots[$page])) { - $this->PageAnnots[$this->page] = $this->PageAnnots[$page]; - } - if (isset($this->newpagegroup[$page])) { - // start a new group - $this->newpagegroup[$this->page] = sizeof($this->newpagegroup) + 1; - $this->currpagegroup = $this->newpagegroup[$this->page]; - $this->pagegroups[$this->currpagegroup] = 1; - } elseif (isset($this->currpagegroup) AND ($this->currpagegroup > 0)) { - ++$this->pagegroups[$this->currpagegroup]; - } - // copy outlines - $tmpoutlines = $this->outlines; - foreach ($tmpoutlines as $key => $outline) { - if ($outline['p'] == $page) { - $this->outlines[] = array('t' => $outline['t'], 'l' => $outline['l'], 'x' => $outline['x'], 'y' => $outline['y'], 'p' => $this->page, 'f' => $outline['f'], 's' => $outline['s'], 'c' => $outline['c']); - } - } - // copy links - $tmplinks = $this->links; - foreach ($tmplinks as $key => $link) { - if ($link['p'] == $page) { - $this->links[] = array('p' => $this->page, 'y' => $link['y'], 'f' => $link['f']); - } - } - // return to last page - $this->lastPage(true); - return true; - } - - /** - * Output a Table of Content Index (TOC). - * This method must be called after all Bookmarks were set. - * Before calling this method you have to open the page using the addTOCPage() method. - * After calling this method you have to call endTOCPage() to close the TOC page. - * You can override this method to achieve different styles. - * @param int|null $page page number where this TOC should be inserted (leave empty for current page). - * @param string $numbersfont set the font for page numbers (please use monospaced font for better alignment). - * @param string $filler string used to fill the space between text and page number. - * @param string $toc_name name to use for TOC bookmark. - * @param string $style Font style for title: B = Bold, I = Italic, BI = Bold + Italic. - * @param array $color RGB color array for bookmark title (values from 0 to 255). - * @public - * @author Nicola Asuni - * @since 4.5.000 (2009-01-02) - * @see addTOCPage(), endTOCPage(), addHTMLTOC() - */ - public function addTOC($page=null, $numbersfont='', $filler='.', $toc_name='TOC', $style='', $color=array(0,0,0)) { - $fontsize = $this->FontSizePt; - $fontfamily = $this->FontFamily; - $fontstyle = $this->FontStyle; - $w = $this->w - $this->lMargin - $this->rMargin; - $spacer = $this->GetStringWidth(chr(32)) * 4; - $lmargin = $this->lMargin; - $rmargin = $this->rMargin; - $x_start = $this->GetX(); - $page_first = $this->page; - $current_page = $this->page; - $page_fill_start = false; - $page_fill_end = false; - $current_column = $this->current_column; - if (TCPDF_STATIC::empty_string($numbersfont)) { - $numbersfont = $this->default_monospaced_font; - } - if (TCPDF_STATIC::empty_string($filler)) { - $filler = ' '; - } - if (TCPDF_STATIC::empty_string($page)) { - $gap = ' '; - } else { - $gap = ''; - if ($page < 1) { - $page = 1; - } - } - $this->setFont($numbersfont, $fontstyle, $fontsize); - $numwidth = $this->GetStringWidth('00000'); - $maxpage = 0; //used for pages on attached documents - foreach ($this->outlines as $key => $outline) { - // check for extra pages (used for attachments) - if (($this->page > $page_first) AND ($outline['p'] >= $this->numpages)) { - $outline['p'] += ($this->page - $page_first); - } - if ($this->rtl) { - $aligntext = 'R'; - $alignnum = 'L'; - } else { - $aligntext = 'L'; - $alignnum = 'R'; - } - if ($outline['l'] == 0) { - $this->setFont($fontfamily, $outline['s'].'B', $fontsize); - } else { - $this->setFont($fontfamily, $outline['s'], $fontsize - $outline['l']); - } - $this->setTextColorArray($outline['c']); - // check for page break - $this->checkPageBreak(2 * $this->getCellHeight($this->FontSize)); - // set margins and X position - if (($this->page == $current_page) AND ($this->current_column == $current_column)) { - $this->lMargin = $lmargin; - $this->rMargin = $rmargin; - } else { - if ($this->current_column != $current_column) { - if ($this->rtl) { - $x_start = $this->w - $this->columns[$this->current_column]['x']; - } else { - $x_start = $this->columns[$this->current_column]['x']; - } - } - $lmargin = $this->lMargin; - $rmargin = $this->rMargin; - $current_page = $this->page; - $current_column = $this->current_column; - } - $this->setX($x_start); - $indent = ($spacer * $outline['l']); - if ($this->rtl) { - $this->x -= $indent; - $this->rMargin = $this->w - $this->x; - } else { - $this->x += $indent; - $this->lMargin = $this->x; - } - $link = $this->AddLink(); - $this->setLink($link, $outline['y'], $outline['p']); - // write the text - if ($this->rtl) { - $txt = ' '.$outline['t']; - } else { - $txt = $outline['t'].' '; - } - $this->Write(0, $txt, $link, false, $aligntext, false, 0, false, false, 0, $numwidth, ''); - if ($this->rtl) { - $tw = $this->x - $this->lMargin; - } else { - $tw = $this->w - $this->rMargin - $this->x; - } - $this->setFont($numbersfont, $fontstyle, $fontsize); - if (TCPDF_STATIC::empty_string($page)) { - $pagenum = $outline['p']; - } else { - // placemark to be replaced with the correct number - $pagenum = '{#'.($outline['p']).'}'; - if ($this->isUnicodeFont()) { - $pagenum = '{'.$pagenum.'}'; - } - $maxpage = max($maxpage, $outline['p']); - } - $fw = ($tw - $this->GetStringWidth($pagenum.$filler)); - $wfiller = $this->GetStringWidth($filler); - if ($wfiller > 0) { - $numfills = floor($fw / $wfiller); - } else { - $numfills = 0; - } - if ($numfills > 0) { - $rowfill = str_repeat($filler, $numfills); - } else { - $rowfill = ''; - } - if ($this->rtl) { - $pagenum = $pagenum.$gap.$rowfill; - } else { - $pagenum = $rowfill.$gap.$pagenum; - } - // write the number - $this->Cell($tw, 0, $pagenum, 0, 1, $alignnum, 0, $link, 0); - } - $page_last = $this->getPage(); - $numpages = ($page_last - $page_first + 1); - // account for booklet mode - if ($this->booklet) { - // check if a blank page is required before TOC - $page_fill_start = ((($page_first % 2) == 0) XOR (($page % 2) == 0)); - $page_fill_end = (!((($numpages % 2) == 0) XOR ($page_fill_start))); - if ($page_fill_start) { - // add a page at the end (to be moved before TOC) - $this->addPage(); - ++$page_last; - ++$numpages; - } - if ($page_fill_end) { - // add a page at the end - $this->addPage(); - ++$page_last; - ++$numpages; - } - } - $maxpage = max($maxpage, $page_last); - if (!TCPDF_STATIC::empty_string($page)) { - for ($p = $page_first; $p <= $page_last; ++$p) { - // get page data - $temppage = $this->getPageBuffer($p); - for ($n = 1; $n <= $maxpage; ++$n) { - // update page numbers - $a = '{#'.$n.'}'; - // get page number aliases - $pnalias = $this->getInternalPageNumberAliases($a); - // calculate replacement number - if (($n >= $page) AND ($n <= $this->numpages)) { - $np = $n + $numpages; - } else { - $np = $n; - } - $na = TCPDF_STATIC::formatTOCPageNumber(($this->starting_page_number + $np - 1)); - $nu = TCPDF_FONTS::UTF8ToUTF16BE($na, false, $this->isunicode, $this->CurrentFont); - // replace aliases with numbers - foreach ($pnalias['u'] as $u) { - $sfill = str_repeat($filler, max(0, (strlen($u) - strlen($nu.' ')))); - if ($this->rtl) { - $nr = $nu.TCPDF_FONTS::UTF8ToUTF16BE(' '.$sfill, false, $this->isunicode, $this->CurrentFont); - } else { - $nr = TCPDF_FONTS::UTF8ToUTF16BE($sfill.' ', false, $this->isunicode, $this->CurrentFont).$nu; - } - $temppage = str_replace($u, $nr, $temppage); - } - foreach ($pnalias['a'] as $a) { - $sfill = str_repeat($filler, max(0, (strlen($a) - strlen($na.' ')))); - if ($this->rtl) { - $nr = $na.' '.$sfill; - } else { - $nr = $sfill.' '.$na; - } - $temppage = str_replace($a, $nr, $temppage); - } - } - // save changes - $this->setPageBuffer($p, $temppage); - } - // move pages - $this->Bookmark($toc_name, 0, 0, $page_first, $style, $color); - if ($page_fill_start) { - $this->movePage($page_last, $page_first); - } - for ($i = 0; $i < $numpages; ++$i) { - $this->movePage($page_last, $page); - } - } - } - - /** - * Output a Table Of Content Index (TOC) using HTML templates. - * This method must be called after all Bookmarks were set. - * Before calling this method you have to open the page using the addTOCPage() method. - * After calling this method you have to call endTOCPage() to close the TOC page. - * @param int|null $page page number where this TOC should be inserted (leave empty for current page). - * @param string $toc_name name to use for TOC bookmark. - * @param array $templates array of html templates. Use: "#TOC_DESCRIPTION#" for bookmark title, "#TOC_PAGE_NUMBER#" for page number. - * @param boolean $correct_align if true correct the number alignment (numbers must be in monospaced font like courier and right aligned on LTR, or left aligned on RTL) - * @param string $style Font style for title: B = Bold, I = Italic, BI = Bold + Italic. - * @param array $color RGB color array for title (values from 0 to 255). - * @public - * @author Nicola Asuni - * @since 5.0.001 (2010-05-06) - * @see addTOCPage(), endTOCPage(), addTOC() - */ - public function addHTMLTOC($page=null, $toc_name='TOC', $templates=array(), $correct_align=true, $style='', $color=array(0,0,0)) { - $filler = ' '; - $prev_htmlLinkColorArray = $this->htmlLinkColorArray; - $prev_htmlLinkFontStyle = $this->htmlLinkFontStyle; - // set new style for link - $this->htmlLinkColorArray = array(); - $this->htmlLinkFontStyle = ''; - $page_first = $this->getPage(); - $page_fill_start = false; - $page_fill_end = false; - // get the font type used for numbers in each template - $current_font = $this->FontFamily; - foreach ($templates as $level => $html) { - $dom = $this->getHtmlDomArray($html); - foreach ($dom as $key => $value) { - if ($value['value'] == '#TOC_PAGE_NUMBER#') { - $this->setFont($dom[($key - 1)]['fontname']); - $templates['F'.$level] = $this->isUnicodeFont(); - } - } - } - $this->setFont($current_font); - $maxpage = 0; //used for pages on attached documents - foreach ($this->outlines as $key => $outline) { - // get HTML template - $row = $templates[$outline['l']]; - if (TCPDF_STATIC::empty_string($page)) { - $pagenum = $outline['p']; - } else { - // placemark to be replaced with the correct number - $pagenum = '{#'.($outline['p']).'}'; - if (isset($templates['F'.$outline['l']]) && $templates['F'.$outline['l']]) { - $pagenum = '{'.$pagenum.'}'; - } - $maxpage = max($maxpage, $outline['p']); - } - // replace templates with current values - $row = str_replace('#TOC_DESCRIPTION#', $outline['t'], $row); - $row = str_replace('#TOC_PAGE_NUMBER#', $pagenum, $row); - // add link to page - $row = '<a href="#'.$outline['p'].','.$outline['y'].'">'.$row.'</a>'; - // write bookmark entry - $this->writeHTML($row, false, false, true, false, ''); - } - // restore link styles - $this->htmlLinkColorArray = $prev_htmlLinkColorArray; - $this->htmlLinkFontStyle = $prev_htmlLinkFontStyle; - // move TOC page and replace numbers - $page_last = $this->getPage(); - $numpages = ($page_last - $page_first + 1); - // account for booklet mode - if ($this->booklet) { - // check if a blank page is required before TOC - $page_fill_start = ((($page_first % 2) == 0) XOR (($page % 2) == 0)); - $page_fill_end = (!((($numpages % 2) == 0) XOR ($page_fill_start))); - if ($page_fill_start) { - // add a page at the end (to be moved before TOC) - $this->addPage(); - ++$page_last; - ++$numpages; - } - if ($page_fill_end) { - // add a page at the end - $this->addPage(); - ++$page_last; - ++$numpages; - } - } - $maxpage = max($maxpage, $page_last); - if (!TCPDF_STATIC::empty_string($page)) { - for ($p = $page_first; $p <= $page_last; ++$p) { - // get page data - $temppage = $this->getPageBuffer($p); - for ($n = 1; $n <= $maxpage; ++$n) { - // update page numbers - $a = '{#'.$n.'}'; - // get page number aliases - $pnalias = $this->getInternalPageNumberAliases($a); - // calculate replacement number - if ($n >= $page) { - $np = $n + $numpages; - } else { - $np = $n; - } - $na = TCPDF_STATIC::formatTOCPageNumber(($this->starting_page_number + $np - 1)); - $nu = TCPDF_FONTS::UTF8ToUTF16BE($na, false, $this->isunicode, $this->CurrentFont); - // replace aliases with numbers - foreach ($pnalias['u'] as $u) { - if ($correct_align) { - $sfill = str_repeat($filler, (strlen($u) - strlen($nu.' '))); - if ($this->rtl) { - $nr = $nu.TCPDF_FONTS::UTF8ToUTF16BE(' '.$sfill, false, $this->isunicode, $this->CurrentFont); - } else { - $nr = TCPDF_FONTS::UTF8ToUTF16BE($sfill.' ', false, $this->isunicode, $this->CurrentFont).$nu; - } - } else { - $nr = $nu; - } - $temppage = str_replace($u, $nr, $temppage); - } - foreach ($pnalias['a'] as $a) { - if ($correct_align) { - $sfill = str_repeat($filler, (strlen($a) - strlen($na.' '))); - if ($this->rtl) { - $nr = $na.' '.$sfill; - } else { - $nr = $sfill.' '.$na; - } - } else { - $nr = $na; - } - $temppage = str_replace($a, $nr, $temppage); - } - } - // save changes - $this->setPageBuffer($p, $temppage); - } - // move pages - $this->Bookmark($toc_name, 0, 0, $page_first, $style, $color); - if ($page_fill_start) { - $this->movePage($page_last, $page_first); - } - for ($i = 0; $i < $numpages; ++$i) { - $this->movePage($page_last, $page); - } - } - } - - /** - * Stores a copy of the current TCPDF object used for undo operation. - * @public - * @since 4.5.029 (2009-03-19) - */ - public function startTransaction() { - if (isset($this->objcopy)) { - // remove previous copy - $this->commitTransaction(); - } - // record current page number and Y position - $this->start_transaction_page = $this->page; - $this->start_transaction_y = $this->y; - // clone current object - $this->objcopy = TCPDF_STATIC::objclone($this); - } - - /** - * Delete the copy of the current TCPDF object used for undo operation. - * @public - * @since 4.5.029 (2009-03-19) - */ - public function commitTransaction() { - if (isset($this->objcopy)) { - $this->objcopy->_destroy(true, true); - /* The unique file_id should not be used during cleanup again */ - $this->objcopy->file_id = NULL; - unset($this->objcopy); - } - } - - /** - * This method allows to undo the latest transaction by returning the latest saved TCPDF object with startTransaction(). - * @param boolean $self if true restores current class object to previous state without the need of reassignment via the returned value. - * @return TCPDF object. - * @public - * @since 4.5.029 (2009-03-19) - */ - public function rollbackTransaction($self=false) { - if (isset($this->objcopy)) { - $objcopy = $this->objcopy; - $this->_destroy(true, true); - if ($self) { - $objvars = get_object_vars($objcopy); - foreach ($objvars as $key => $value) { - $this->$key = $value; - } - $objcopy->_destroy(true, true); - /* The unique file_id should not be used during cleanup again */ - $objcopy->file_id = NULL; - unset($objcopy); - return $this; - } - /* The unique file_id should not be used during cleanup again */ - $this->file_id = NULL; - return $objcopy; - } - return $this; - } - - // --- MULTI COLUMNS METHODS ----------------------- - - /** - * Set multiple columns of the same size - * @param int $numcols number of columns (set to zero to disable columns mode) - * @param int $width column width - * @param int|null $y column starting Y position (leave empty for current Y position) - * @public - * @since 4.9.001 (2010-03-28) - */ - public function setEqualColumns($numcols=0, $width=0, $y=null) { - $this->columns = array(); - if ($numcols < 2) { - $numcols = 0; - $this->columns = array(); - } else { - // maximum column width - $maxwidth = ($this->w - $this->original_lMargin - $this->original_rMargin) / $numcols; - if (($width == 0) OR ($width > $maxwidth)) { - $width = $maxwidth; - } - if (TCPDF_STATIC::empty_string($y)) { - $y = $this->y; - } - // space between columns - $space = (($this->w - $this->original_lMargin - $this->original_rMargin - ($numcols * $width)) / ($numcols - 1)); - // fill the columns array (with, space, starting Y position) - for ($i = 0; $i < $numcols; ++$i) { - $this->columns[$i] = array('w' => $width, 's' => $space, 'y' => $y); - } - } - $this->num_columns = $numcols; - $this->current_column = 0; - $this->column_start_page = $this->page; - $this->selectColumn(0); - } - - /** - * Remove columns and reset page margins. - * @public - * @since 5.9.072 (2011-04-26) - */ - public function resetColumns() { - $this->lMargin = $this->original_lMargin; - $this->rMargin = $this->original_rMargin; - $this->setEqualColumns(); - } - - /** - * Set columns array. - * Each column is represented by an array of arrays with the following keys: (w = width, s = space between columns, y = column top position). - * @param array $columns - * @public - * @since 4.9.001 (2010-03-28) - */ - public function setColumnsArray($columns) { - $this->columns = $columns; - $this->num_columns = count($columns); - $this->current_column = 0; - $this->column_start_page = $this->page; - $this->selectColumn(0); - } - - /** - * Set position at a given column - * @param int|null $col column number (from 0 to getNumberOfColumns()-1); empty string = current column. - * @public - * @since 4.9.001 (2010-03-28) - */ - public function selectColumn($col=null) { - if (TCPDF_STATIC::empty_string($col)) { - $col = $this->current_column; - } elseif ($col >= $this->num_columns) { - $col = 0; - } - $xshift = array('x' => 0, 's' => array('H' => 0, 'V' => 0), 'p' => array('L' => 0, 'T' => 0, 'R' => 0, 'B' => 0)); - $enable_thead = false; - if ($this->num_columns > 1) { - if ($col != $this->current_column) { - // move Y pointer at the top of the column - if ($this->column_start_page == $this->page) { - $this->y = $this->columns[$col]['y']; - } else { - $this->y = $this->tMargin; - } - // Avoid to write table headers more than once - if (($this->page > $this->maxselcol['page']) OR (($this->page == $this->maxselcol['page']) AND ($col > $this->maxselcol['column']))) { - $enable_thead = true; - $this->maxselcol['page'] = $this->page; - $this->maxselcol['column'] = $col; - } - } - $xshift = $this->colxshift; - // set X position of the current column by case - $listindent = ($this->listindentlevel * $this->listindent); - // calculate column X position - $colpos = 0; - for ($i = 0; $i < $col; ++$i) { - $colpos += ($this->columns[$i]['w'] + $this->columns[$i]['s']); - } - if ($this->rtl) { - $x = $this->w - $this->original_rMargin - $colpos; - $this->rMargin = ($this->w - $x + $listindent); - $this->lMargin = ($x - $this->columns[$col]['w']); - $this->x = $x - $listindent; - } else { - $x = $this->original_lMargin + $colpos; - $this->lMargin = ($x + $listindent); - $this->rMargin = ($this->w - $x - $this->columns[$col]['w']); - $this->x = $x + $listindent; - } - $this->columns[$col]['x'] = $x; - } - $this->current_column = $col; - // fix for HTML mode - $this->newline = true; - // print HTML table header (if any) - if ((!TCPDF_STATIC::empty_string($this->thead)) AND (!$this->inthead)) { - if ($enable_thead) { - // print table header - $this->writeHTML($this->thead, false, false, false, false, ''); - $this->y += $xshift['s']['V']; - // store end of header position - if (!isset($this->columns[$col]['th'])) { - $this->columns[$col]['th'] = array(); - } - $this->columns[$col]['th']['\''.$this->page.'\''] = $this->y; - $this->lasth = 0; - } elseif (isset($this->columns[$col]['th']['\''.$this->page.'\''])) { - $this->y = $this->columns[$col]['th']['\''.$this->page.'\'']; - } - } - // account for an html table cell over multiple columns - if ($this->rtl) { - $this->rMargin += $xshift['x']; - $this->x -= ($xshift['x'] + $xshift['p']['R']); - } else { - $this->lMargin += $xshift['x']; - $this->x += $xshift['x'] + $xshift['p']['L']; - } - } - - /** - * Return the current column number - * @return int current column number - * @public - * @since 5.5.011 (2010-07-08) - */ - public function getColumn() { - return $this->current_column; - } - - /** - * Return the current number of columns. - * @return int number of columns - * @public - * @since 5.8.018 (2010-08-25) - */ - public function getNumberOfColumns() { - return $this->num_columns; - } - - /** - * Set Text rendering mode. - * @param int $stroke outline size in user units (0 = disable). - * @param boolean $fill if true fills the text (default). - * @param boolean $clip if true activate clipping mode - * @public - * @since 4.9.008 (2009-04-02) - */ - public function setTextRenderingMode($stroke=0, $fill=true, $clip=false) { - // Ref.: PDF 32000-1:2008 - 9.3.6 Text Rendering Mode - // convert text rendering parameters - if ($stroke < 0) { - $stroke = 0; - } - if ($fill === true) { - if ($stroke > 0) { - if ($clip === true) { - // Fill, then stroke text and add to path for clipping - $textrendermode = 6; - } else { - // Fill, then stroke text - $textrendermode = 2; - } - $textstrokewidth = $stroke; - } else { - if ($clip === true) { - // Fill text and add to path for clipping - $textrendermode = 4; - } else { - // Fill text - $textrendermode = 0; - } - } - } else { - if ($stroke > 0) { - if ($clip === true) { - // Stroke text and add to path for clipping - $textrendermode = 5; - } else { - // Stroke text - $textrendermode = 1; - } - $textstrokewidth = $stroke; - } else { - if ($clip === true) { - // Add text to path for clipping - $textrendermode = 7; - } else { - // Neither fill nor stroke text (invisible) - $textrendermode = 3; - } - } - } - $this->textrendermode = $textrendermode; - $this->textstrokewidth = $stroke; - } - - /** - * Set parameters for drop shadow effect for text. - * @param array $params Array of parameters: enabled (boolean) set to true to enable shadow; depth_w (float) shadow width in user units; depth_h (float) shadow height in user units; color (array) shadow color or false to use the stroke color; opacity (float) Alpha value: real value from 0 (transparent) to 1 (opaque); blend_mode (string) blend mode, one of the following: Normal, Multiply, Screen, Overlay, Darken, Lighten, ColorDodge, ColorBurn, HardLight, SoftLight, Difference, Exclusion, Hue, Saturation, Color, Luminosity. - * @since 5.9.174 (2012-07-25) - * @public - */ - public function setTextShadow($params=array('enabled'=>false, 'depth_w'=>0, 'depth_h'=>0, 'color'=>false, 'opacity'=>1, 'blend_mode'=>'Normal')) { - if (isset($params['enabled'])) { - $this->txtshadow['enabled'] = $params['enabled']?true:false; - } else { - $this->txtshadow['enabled'] = false; - } - if (isset($params['depth_w'])) { - $this->txtshadow['depth_w'] = floatval($params['depth_w']); - } else { - $this->txtshadow['depth_w'] = 0; - } - if (isset($params['depth_h'])) { - $this->txtshadow['depth_h'] = floatval($params['depth_h']); - } else { - $this->txtshadow['depth_h'] = 0; - } - if (isset($params['color']) AND ($params['color'] !== false) AND is_array($params['color'])) { - $this->txtshadow['color'] = $params['color']; - } else { - $this->txtshadow['color'] = $this->strokecolor; - } - if (isset($params['opacity'])) { - $this->txtshadow['opacity'] = min(1, max(0, floatval($params['opacity']))); - } else { - $this->txtshadow['opacity'] = 1; - } - if (isset($params['blend_mode']) AND in_array($params['blend_mode'], array('Normal', 'Multiply', 'Screen', 'Overlay', 'Darken', 'Lighten', 'ColorDodge', 'ColorBurn', 'HardLight', 'SoftLight', 'Difference', 'Exclusion', 'Hue', 'Saturation', 'Color', 'Luminosity'))) { - $this->txtshadow['blend_mode'] = $params['blend_mode']; - } else { - $this->txtshadow['blend_mode'] = 'Normal'; - } - if ((($this->txtshadow['depth_w'] == 0) AND ($this->txtshadow['depth_h'] == 0)) OR ($this->txtshadow['opacity'] == 0)) { - $this->txtshadow['enabled'] = false; - } - } - - /** - * Return the text shadow parameters array. - * @return array array of parameters. - * @since 5.9.174 (2012-07-25) - * @public - */ - public function getTextShadow() { - return $this->txtshadow; - } - - /** - * Returns an array of chars containing soft hyphens. - * @param array $word array of chars - * @param array $patterns Array of hypenation patterns. - * @param array $dictionary Array of words to be returned without applying the hyphenation algorithm. - * @param int $leftmin Minimum number of character to leave on the left of the word without applying the hyphens. - * @param int $rightmin Minimum number of character to leave on the right of the word without applying the hyphens. - * @param int $charmin Minimum word length to apply the hyphenation algorithm. - * @param int $charmax Maximum length of broken piece of word. - * @return array text with soft hyphens - * @author Nicola Asuni - * @since 4.9.012 (2010-04-12) - * @protected - */ - protected function hyphenateWord($word, $patterns, $dictionary=array(), $leftmin=1, $rightmin=2, $charmin=1, $charmax=8) { - $hyphenword = array(); // hyphens positions - $numchars = count($word); - if ($numchars <= $charmin) { - return $word; - } - $word_string = TCPDF_FONTS::UTF8ArrSubString($word, '', '', $this->isunicode); - // some words will be returned as-is - $pattern = '/^([a-zA-Z0-9_\.\-]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/'; - if (preg_match($pattern, $word_string) > 0) { - // email - return $word; - } - $pattern = '/(([a-zA-Z0-9\-]+\.)?)((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/'; - if (preg_match($pattern, $word_string) > 0) { - // URL - return $word; - } - if (isset($dictionary[$word_string])) { - return TCPDF_FONTS::UTF8StringToArray($dictionary[$word_string], $this->isunicode, $this->CurrentFont); - } - // surround word with '_' characters - $tmpword = array_merge(array(46), $word, array(46)); - $tmpnumchars = $numchars + 2; - $maxpos = $tmpnumchars - 1; - for ($pos = 0; $pos < $maxpos; ++$pos) { - $imax = min(($tmpnumchars - $pos), $charmax); - for ($i = 1; $i <= $imax; ++$i) { - $subword = strtolower(TCPDF_FONTS::UTF8ArrSubString($tmpword, $pos, ($pos + $i), $this->isunicode)); - if (isset($patterns[$subword])) { - $pattern = TCPDF_FONTS::UTF8StringToArray($patterns[$subword], $this->isunicode, $this->CurrentFont); - $pattern_length = count($pattern); - $digits = 1; - for ($j = 0; $j < $pattern_length; ++$j) { - // check if $pattern[$j] is a number = hyphenation level (only numbers from 1 to 5 are valid) - if (($pattern[$j] >= 48) AND ($pattern[$j] <= 57)) { - if ($j == 0) { - $zero = $pos - 1; - } else { - $zero = $pos + $j - $digits; - } - // get hyphenation level - $level = ($pattern[$j] - 48); - // if two levels from two different patterns match at the same point, the higher one is selected. - if (!isset($hyphenword[$zero]) OR ($hyphenword[$zero] < $level)) { - $hyphenword[$zero] = $level; - } - ++$digits; - } - } - } - } - } - $inserted = 0; - $maxpos = $numchars - $rightmin; - for ($i = $leftmin; $i <= $maxpos; ++$i) { - // only odd levels indicate allowed hyphenation points - if (isset($hyphenword[$i]) AND (($hyphenword[$i] % 2) != 0)) { - // 173 = soft hyphen character - array_splice($word, $i + $inserted, 0, 173); - ++$inserted; - } - } - return $word; - } - - /** - * Returns text with soft hyphens. - * @param string $text text to process - * @param mixed $patterns Array of hypenation patterns or a TEX file containing hypenation patterns. TEX patterns can be downloaded from http://www.ctan.org/tex-archive/language/hyph-utf8/tex/generic/hyph-utf8/patterns/ - * @param array $dictionary Array of words to be returned without applying the hyphenation algorithm. - * @param int $leftmin Minimum number of character to leave on the left of the word without applying the hyphens. - * @param int $rightmin Minimum number of character to leave on the right of the word without applying the hyphens. - * @param int $charmin Minimum word length to apply the hyphenation algorithm. - * @param int $charmax Maximum length of broken piece of word. - * @return string text with soft hyphens - * @author Nicola Asuni - * @since 4.9.012 (2010-04-12) - * @public - */ - public function hyphenateText($text, $patterns, $dictionary=array(), $leftmin=1, $rightmin=2, $charmin=1, $charmax=8) { - $text = $this->unhtmlentities($text); - $word = array(); // last word - $txtarr = array(); // text to be returned - $intag = false; // true if we are inside an HTML tag - $skip = false; // true to skip hyphenation - if (!is_array($patterns)) { - $patterns = TCPDF_STATIC::getHyphenPatternsFromTEX($patterns); - } - // get array of characters - $unichars = TCPDF_FONTS::UTF8StringToArray($text, $this->isunicode, $this->CurrentFont); - // for each char - foreach ($unichars as $char) { - if ((!$intag) AND (!$skip) AND TCPDF_FONT_DATA::$uni_type[$char] == 'L') { - // letter character - $word[] = $char; - } else { - // other type of character - if (!TCPDF_STATIC::empty_string($word)) { - // hypenate the word - $txtarr = array_merge($txtarr, $this->hyphenateWord($word, $patterns, $dictionary, $leftmin, $rightmin, $charmin, $charmax)); - $word = array(); - } - $txtarr[] = $char; - if (chr($char) == '<') { - // we are inside an HTML tag - $intag = true; - } elseif ($intag AND (chr($char) == '>')) { - // end of HTML tag - $intag = false; - // check for style tag - $expected = array(115, 116, 121, 108, 101); // = 'style' - $current = array_slice($txtarr, -6, 5); // last 5 chars - $compare = array_diff($expected, $current); - if (empty($compare)) { - // check if it is a closing tag - $expected = array(47); // = '/' - $current = array_slice($txtarr, -7, 1); - $compare = array_diff($expected, $current); - if (empty($compare)) { - // closing style tag - $skip = false; - } else { - // opening style tag - $skip = true; - } - } - } - } - } - if (!TCPDF_STATIC::empty_string($word)) { - // hypenate the word - $txtarr = array_merge($txtarr, $this->hyphenateWord($word, $patterns, $dictionary, $leftmin, $rightmin, $charmin, $charmax)); - } - // convert char array to string and return - return TCPDF_FONTS::UTF8ArrSubString($txtarr, '', '', $this->isunicode); - } - - /** - * Enable/disable rasterization of vector images using ImageMagick library. - * @param boolean $mode if true enable rasterization, false otherwise. - * @public - * @since 5.0.000 (2010-04-27) - */ - public function setRasterizeVectorImages($mode) { - $this->rasterize_vector_images = $mode; - } - - /** - * Enable or disable default option for font subsetting. - * @param boolean $enable if true enable font subsetting by default. - * @author Nicola Asuni - * @public - * @since 5.3.002 (2010-06-07) - */ - public function setFontSubsetting($enable=true) { - if ($this->pdfa_mode) { - $this->font_subsetting = false; - } else { - $this->font_subsetting = $enable ? true : false; - } - } - - /** - * Return the default option for font subsetting. - * @return bool default font subsetting state. - * @author Nicola Asuni - * @public - * @since 5.3.002 (2010-06-07) - */ - public function getFontSubsetting() { - return $this->font_subsetting; - } - - /** - * Left trim the input string - * @param string $str string to trim - * @param string $replace string that replace spaces. - * @return string left trimmed string - * @author Nicola Asuni - * @public - * @since 5.8.000 (2010-08-11) - */ - public function stringLeftTrim($str, $replace='') { - return preg_replace('/^'.$this->re_space['p'].'+/'.$this->re_space['m'], $replace, $str); - } - - /** - * Right trim the input string - * @param string $str string to trim - * @param string $replace string that replace spaces. - * @return string right trimmed string - * @author Nicola Asuni - * @public - * @since 5.8.000 (2010-08-11) - */ - public function stringRightTrim($str, $replace='') { - return preg_replace('/'.$this->re_space['p'].'+$/'.$this->re_space['m'], $replace, $str); - } - - /** - * Trim the input string - * @param string $str string to trim - * @param string $replace string that replace spaces. - * @return string trimmed string - * @author Nicola Asuni - * @public - * @since 5.8.000 (2010-08-11) - */ - public function stringTrim($str, $replace='') { - $str = $this->stringLeftTrim($str, $replace); - $str = $this->stringRightTrim($str, $replace); - return $str; - } - - /** - * Return true if the current font is unicode type. - * @return bool true for unicode font, false otherwise. - * @author Nicola Asuni - * @public - * @since 5.8.002 (2010-08-14) - */ - public function isUnicodeFont() { - return (($this->CurrentFont['type'] == 'TrueTypeUnicode') OR ($this->CurrentFont['type'] == 'cidfont0')); - } - - /** - * Return normalized font name - * @param string $fontfamily property string containing font family names - * @return string normalized font name - * @author Nicola Asuni - * @public - * @since 5.8.004 (2010-08-17) - */ - public function getFontFamilyName($fontfamily) { - // remove spaces and symbols - $fontfamily = preg_replace('/[^a-z0-9_\,]/', '', strtolower($fontfamily)); - // extract all font names - $fontslist = preg_split('/[,]/', $fontfamily); - // find first valid font name - foreach ($fontslist as $font) { - // replace font variations - $font = preg_replace('/regular$/', '', $font); - $font = preg_replace('/italic$/', 'I', $font); - $font = preg_replace('/oblique$/', 'I', $font); - $font = preg_replace('/bold([I]?)$/', 'B\\1', $font); - // replace common family names and core fonts - $pattern = array(); - $replacement = array(); - $pattern[] = '/^serif|^cursive|^fantasy|^timesnewroman/'; - $replacement[] = 'times'; - $pattern[] = '/^sansserif/'; - $replacement[] = 'helvetica'; - $pattern[] = '/^monospace/'; - $replacement[] = 'courier'; - $font = preg_replace($pattern, $replacement, $font); - if (in_array(strtolower($font), $this->fontlist) OR in_array($font, $this->fontkeys)) { - return $font; - } - } - // return current font as default - return $this->CurrentFont['fontkey']; - } - - /** - * Start a new XObject Template. - * An XObject Template is a PDF block that is a self-contained description of any sequence of graphics objects (including path objects, text objects, and sampled images). - * An XObject Template may be painted multiple times, either on several pages or at several locations on the same page and produces the same results each time, subject only to the graphics state at the time it is invoked. - * Note: X,Y coordinates will be reset to 0,0. - * @param int $w Template width in user units (empty string or zero = page width less margins). - * @param int $h Template height in user units (empty string or zero = page height less margins). - * @param mixed $group Set transparency group. Can be a boolean value or an array specifying optional parameters: 'CS' (solour space name), 'I' (boolean flag to indicate isolated group) and 'K' (boolean flag to indicate knockout group). - * @return string|false the XObject Template ID in case of success or false in case of error. - * @author Nicola Asuni - * @public - * @since 5.8.017 (2010-08-24) - * @see endTemplate(), printTemplate() - */ - public function startTemplate($w=0, $h=0, $group=false) { - if ($this->inxobj) { - // we are already inside an XObject template - return false; - } - $this->inxobj = true; - ++$this->n; - // XObject ID - $this->xobjid = 'XT'.$this->n; - // object ID - $this->xobjects[$this->xobjid] = array('n' => $this->n); - // store current graphic state - $this->xobjects[$this->xobjid]['gvars'] = $this->getGraphicVars(); - // initialize data - $this->xobjects[$this->xobjid]['intmrk'] = 0; - $this->xobjects[$this->xobjid]['transfmrk'] = array(); - $this->xobjects[$this->xobjid]['outdata'] = ''; - $this->xobjects[$this->xobjid]['xobjects'] = array(); - $this->xobjects[$this->xobjid]['images'] = array(); - $this->xobjects[$this->xobjid]['fonts'] = array(); - $this->xobjects[$this->xobjid]['annotations'] = array(); - $this->xobjects[$this->xobjid]['extgstates'] = array(); - $this->xobjects[$this->xobjid]['gradients'] = array(); - $this->xobjects[$this->xobjid]['spot_colors'] = array(); - // set new environment - $this->num_columns = 1; - $this->current_column = 0; - $this->setAutoPageBreak(false); - if (($w === '') OR ($w <= 0)) { - $w = $this->w - $this->lMargin - $this->rMargin; - } - if (($h === '') OR ($h <= 0)) { - $h = $this->h - $this->tMargin - $this->bMargin; - } - $this->xobjects[$this->xobjid]['x'] = 0; - $this->xobjects[$this->xobjid]['y'] = 0; - $this->xobjects[$this->xobjid]['w'] = $w; - $this->xobjects[$this->xobjid]['h'] = $h; - $this->w = $w; - $this->h = $h; - $this->wPt = $this->w * $this->k; - $this->hPt = $this->h * $this->k; - $this->fwPt = $this->wPt; - $this->fhPt = $this->hPt; - $this->x = 0; - $this->y = 0; - $this->lMargin = 0; - $this->rMargin = 0; - $this->tMargin = 0; - $this->bMargin = 0; - // set group mode - $this->xobjects[$this->xobjid]['group'] = $group; - return $this->xobjid; - } - - /** - * End the current XObject Template started with startTemplate() and restore the previous graphic state. - * An XObject Template is a PDF block that is a self-contained description of any sequence of graphics objects (including path objects, text objects, and sampled images). - * An XObject Template may be painted multiple times, either on several pages or at several locations on the same page and produces the same results each time, subject only to the graphics state at the time it is invoked. - * @return string|false the XObject Template ID in case of success or false in case of error. - * @author Nicola Asuni - * @public - * @since 5.8.017 (2010-08-24) - * @see startTemplate(), printTemplate() - */ - public function endTemplate() { - if (!$this->inxobj) { - // we are not inside a template - return false; - } - $this->inxobj = false; - // restore previous graphic state - $this->setGraphicVars($this->xobjects[$this->xobjid]['gvars'], true); - return $this->xobjid; - } - - /** - * Print an XObject Template. - * You can print an XObject Template inside the currently opened Template. - * An XObject Template is a PDF block that is a self-contained description of any sequence of graphics objects (including path objects, text objects, and sampled images). - * An XObject Template may be painted multiple times, either on several pages or at several locations on the same page and produces the same results each time, subject only to the graphics state at the time it is invoked. - * @param string $id The ID of XObject Template to print. - * @param float|null $x X position in user units (empty string = current x position) - * @param float|null $y Y position in user units (empty string = current y position) - * @param float $w Width in user units (zero = remaining page width) - * @param float $h Height in user units (zero = remaining page height) - * @param string $align Indicates the alignment of the pointer next to template insertion relative to template height. The value can be:<ul><li>T: top-right for LTR or top-left for RTL</li><li>M: middle-right for LTR or middle-left for RTL</li><li>B: bottom-right for LTR or bottom-left for RTL</li><li>N: next line</li></ul> - * @param string $palign Allows to center or align the template on the current line. Possible values are:<ul><li>L : left align</li><li>C : center</li><li>R : right align</li><li>'' : empty string : left for LTR or right for RTL</li></ul> - * @param boolean $fitonpage If true the template is resized to not exceed page dimensions. - * @author Nicola Asuni - * @public - * @since 5.8.017 (2010-08-24) - * @see startTemplate(), endTemplate() - */ - public function printTemplate($id, $x=null, $y=null, $w=0, $h=0, $align='', $palign='', $fitonpage=false) { - if ($this->state != 2) { - return; - } - if (!isset($this->xobjects[$id])) { - $this->Error('The XObject Template \''.$id.'\' doesn\'t exist!'); - } - if ($this->inxobj) { - if ($id == $this->xobjid) { - // close current template - $this->endTemplate(); - } else { - // use the template as resource for the template currently opened - $this->xobjects[$this->xobjid]['xobjects'][$id] = $this->xobjects[$id]; - } - } - // set default values - if (TCPDF_STATIC::empty_string($x)) { - $x = $this->x; - } - if (TCPDF_STATIC::empty_string($y)) { - $y = $this->y; - } - // check page for no-write regions and adapt page margins if necessary - list($x, $y) = $this->checkPageRegions($h, $x, $y); - $ow = $this->xobjects[$id]['w']; - if ($ow <= 0) { - $ow = 1; - } - $oh = $this->xobjects[$id]['h']; - if ($oh <= 0) { - $oh = 1; - } - // calculate template width and height on document - if (($w <= 0) AND ($h <= 0)) { - $w = $ow; - $h = $oh; - } elseif ($w <= 0) { - $w = $h * $ow / $oh; - } elseif ($h <= 0) { - $h = $w * $oh / $ow; - } - // fit the template on available space - list($w, $h, $x, $y) = $this->fitBlock($w, $h, $x, $y, $fitonpage); - // set page alignment - $rb_y = $y + $h; - // set alignment - if ($this->rtl) { - if ($palign == 'L') { - $xt = $this->lMargin; - } elseif ($palign == 'C') { - $xt = ($this->w + $this->lMargin - $this->rMargin - $w) / 2; - } elseif ($palign == 'R') { - $xt = $this->w - $this->rMargin - $w; - } else { - $xt = $x - $w; - } - $rb_x = $xt; - } else { - if ($palign == 'L') { - $xt = $this->lMargin; - } elseif ($palign == 'C') { - $xt = ($this->w + $this->lMargin - $this->rMargin - $w) / 2; - } elseif ($palign == 'R') { - $xt = $this->w - $this->rMargin - $w; - } else { - $xt = $x; - } - $rb_x = $xt + $w; - } - // print XObject Template + Transformation matrix - $this->StartTransform(); - // translate and scale - $sx = ($w / $ow); - $sy = ($h / $oh); - $tm = array(); - $tm[0] = $sx; - $tm[1] = 0; - $tm[2] = 0; - $tm[3] = $sy; - $tm[4] = $xt * $this->k; - $tm[5] = ($this->h - $h - $y) * $this->k; - $this->Transform($tm); - // set object - $this->_out('/'.$id.' Do'); - $this->StopTransform(); - // add annotations - if (!empty($this->xobjects[$id]['annotations'])) { - foreach ($this->xobjects[$id]['annotations'] as $annot) { - // transform original coordinates - $coordlt = TCPDF_STATIC::getTransformationMatrixProduct($tm, array(1, 0, 0, 1, ($annot['x'] * $this->k), (-$annot['y'] * $this->k))); - $ax = ($coordlt[4] / $this->k); - $ay = ($this->h - $h - ($coordlt[5] / $this->k)); - $coordrb = TCPDF_STATIC::getTransformationMatrixProduct($tm, array(1, 0, 0, 1, (($annot['x'] + $annot['w']) * $this->k), ((-$annot['y'] - $annot['h']) * $this->k))); - $aw = ($coordrb[4] / $this->k) - $ax; - $ah = ($this->h - $h - ($coordrb[5] / $this->k)) - $ay; - $this->Annotation($ax, $ay, $aw, $ah, $annot['text'], $annot['opt'], $annot['spaces']); - } - } - // set pointer to align the next text/objects - switch($align) { - case 'T': { - $this->y = $y; - $this->x = $rb_x; - break; - } - case 'M': { - $this->y = $y + round($h/2); - $this->x = $rb_x; - break; - } - case 'B': { - $this->y = $rb_y; - $this->x = $rb_x; - break; - } - case 'N': { - $this->setY($rb_y); - break; - } - default:{ - break; - } - } - } - - /** - * Set the percentage of character stretching. - * @param int $perc percentage of stretching (100 = no stretching) - * @author Nicola Asuni - * @public - * @since 5.9.000 (2010-09-29) - */ - public function setFontStretching($perc=100) { - $this->font_stretching = $perc; - } - - /** - * Get the percentage of character stretching. - * @return float stretching value - * @author Nicola Asuni - * @public - * @since 5.9.000 (2010-09-29) - */ - public function getFontStretching() { - return $this->font_stretching; - } - - /** - * Set the amount to increase or decrease the space between characters in a text. - * @param float $spacing amount to increase or decrease the space between characters in a text (0 = default spacing) - * @author Nicola Asuni - * @public - * @since 5.9.000 (2010-09-29) - */ - public function setFontSpacing($spacing=0) { - $this->font_spacing = $spacing; - } - - /** - * Get the amount to increase or decrease the space between characters in a text. - * @return int font spacing (tracking) value - * @author Nicola Asuni - * @public - * @since 5.9.000 (2010-09-29) - */ - public function getFontSpacing() { - return $this->font_spacing; - } - - /** - * Return an array of no-write page regions - * @return array of no-write page regions - * @author Nicola Asuni - * @public - * @since 5.9.003 (2010-10-13) - * @see setPageRegions(), addPageRegion() - */ - public function getPageRegions() { - return $this->page_regions; - } - - /** - * Set no-write regions on page. - * A no-write region is a portion of the page with a rectangular or trapezium shape that will not be covered when writing text or html code. - * A region is always aligned on the left or right side of the page ad is defined using a vertical segment. - * You can set multiple regions for the same page. - * @param array $regions array of no-write regions. For each region you can define an array as follow: ('page' => page number or empy for current page, 'xt' => X top, 'yt' => Y top, 'xb' => X bottom, 'yb' => Y bottom, 'side' => page side 'L' = left or 'R' = right). Omit this parameter to remove all regions. - * @author Nicola Asuni - * @public - * @since 5.9.003 (2010-10-13) - * @see addPageRegion(), getPageRegions() - */ - public function setPageRegions($regions=array()) { - // empty current regions array - $this->page_regions = array(); - // add regions - foreach ($regions as $data) { - $this->addPageRegion($data); - } - } - - /** - * Add a single no-write region on selected page. - * A no-write region is a portion of the page with a rectangular or trapezium shape that will not be covered when writing text or html code. - * A region is always aligned on the left or right side of the page ad is defined using a vertical segment. - * You can set multiple regions for the same page. - * @param array $region array of a single no-write region array: ('page' => page number or empy for current page, 'xt' => X top, 'yt' => Y top, 'xb' => X bottom, 'yb' => Y bottom, 'side' => page side 'L' = left or 'R' = right). - * @author Nicola Asuni - * @public - * @since 5.9.003 (2010-10-13) - * @see setPageRegions(), getPageRegions() - */ - public function addPageRegion($region) { - if (!isset($region['page']) OR empty($region['page'])) { - $region['page'] = $this->page; - } - if (isset($region['xt']) AND isset($region['xb']) AND ($region['xt'] > 0) AND ($region['xb'] > 0) - AND isset($region['yt']) AND isset($region['yb']) AND ($region['yt'] >= 0) AND ($region['yt'] < $region['yb']) - AND isset($region['side']) AND (($region['side'] == 'L') OR ($region['side'] == 'R'))) { - $this->page_regions[] = $region; - } - } - - /** - * Remove a single no-write region. - * @param int $key region key - * @author Nicola Asuni - * @public - * @since 5.9.003 (2010-10-13) - * @see setPageRegions(), getPageRegions() - */ - public function removePageRegion($key) { - if (isset($this->page_regions[$key])) { - unset($this->page_regions[$key]); - } - } - - /** - * Check page for no-write regions and adapt current coordinates and page margins if necessary. - * A no-write region is a portion of the page with a rectangular or trapezium shape that will not be covered when writing text or html code. - * A region is always aligned on the left or right side of the page ad is defined using a vertical segment. - * @param float $h height of the text/image/object to print in user units - * @param float $x current X coordinate in user units - * @param float $y current Y coordinate in user units - * @return float[] array($x, $y) - * @author Nicola Asuni - * @protected - * @since 5.9.003 (2010-10-13) - */ - protected function checkPageRegions($h, $x, $y) { - // set default values - if ($x === '') { - $x = $this->x; - } - if ($y === '') { - $y = $this->y; - } - if (!$this->check_page_regions OR empty($this->page_regions)) { - // no page regions defined - return array($x, $y); - } - if (empty($h)) { - $h = $this->getCellHeight($this->FontSize); - } - // check for page break - if ($this->checkPageBreak($h, $y)) { - // the content will be printed on a new page - $x = $this->x; - $y = $this->y; - } - if ($this->num_columns > 1) { - if ($this->rtl) { - $this->lMargin = ($this->columns[$this->current_column]['x'] - $this->columns[$this->current_column]['w']); - } else { - $this->rMargin = ($this->w - $this->columns[$this->current_column]['x'] - $this->columns[$this->current_column]['w']); - } - } else { - if ($this->rtl) { - $this->lMargin = max($this->clMargin, $this->original_lMargin); - } else { - $this->rMargin = max($this->crMargin, $this->original_rMargin); - } - } - // adjust coordinates and page margins - foreach ($this->page_regions as $regid => $regdata) { - if ($regdata['page'] == $this->page) { - // check region boundaries - if (($y > ($regdata['yt'] - $h)) AND ($y <= $regdata['yb'])) { - // Y is inside the region - $minv = ($regdata['xb'] - $regdata['xt']) / ($regdata['yb'] - $regdata['yt']); // inverse of angular coefficient - $yt = max($y, $regdata['yt']); - $yb = min(($yt + $h), $regdata['yb']); - $xt = (($yt - $regdata['yt']) * $minv) + $regdata['xt']; - $xb = (($yb - $regdata['yt']) * $minv) + $regdata['xt']; - if ($regdata['side'] == 'L') { // left side - $new_margin = max($xt, $xb); - if ($this->lMargin < $new_margin) { - if ($this->rtl) { - // adjust left page margin - $this->lMargin = max(0, $new_margin); - } - if ($x < $new_margin) { - // adjust x position - $x = $new_margin; - if ($new_margin > ($this->w - $this->rMargin)) { - // adjust y position - $y = $regdata['yb'] - $h; - } - } - } - } elseif ($regdata['side'] == 'R') { // right side - $new_margin = min($xt, $xb); - if (($this->w - $this->rMargin) > $new_margin) { - if (!$this->rtl) { - // adjust right page margin - $this->rMargin = max(0, ($this->w - $new_margin)); - } - if ($x > $new_margin) { - // adjust x position - $x = $new_margin; - if ($new_margin > $this->lMargin) { - // adjust y position - $y = $regdata['yb'] - $h; - } - } - } - } - } - } - } - return array($x, $y); - } - - // --- SVG METHODS --------------------------------------------------------- - - /** - * Embedd a Scalable Vector Graphics (SVG) image. - * NOTE: SVG standard is not yet fully implemented, use the setRasterizeVectorImages() method to enable/disable rasterization of vector images using ImageMagick library. - * @param string $file Name of the SVG file or a '@' character followed by the SVG data string. - * @param float|null $x Abscissa of the upper-left corner. - * @param float|null $y Ordinate of the upper-left corner. - * @param float $w Width of the image in the page. If not specified or equal to zero, it is automatically calculated. - * @param float $h Height of the image in the page. If not specified or equal to zero, it is automatically calculated. - * @param mixed $link URL or identifier returned by AddLink(). - * @param string $align Indicates the alignment of the pointer next to image insertion relative to image height. The value can be:<ul><li>T: top-right for LTR or top-left for RTL</li><li>M: middle-right for LTR or middle-left for RTL</li><li>B: bottom-right for LTR or bottom-left for RTL</li><li>N: next line</li></ul> If the alignment is an empty string, then the pointer will be restored on the starting SVG position. - * @param string $palign Allows to center or align the image on the current line. Possible values are:<ul><li>L : left align</li><li>C : center</li><li>R : right align</li><li>'' : empty string : left for LTR or right for RTL</li></ul> - * @param mixed $border Indicates if borders must be drawn around the cell. The value can be a number:<ul><li>0: no border (default)</li><li>1: frame</li></ul> or a string containing some or all of the following characters (in any order):<ul><li>L: left</li><li>T: top</li><li>R: right</li><li>B: bottom</li></ul> or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - * @param boolean $fitonpage if true the image is resized to not exceed page dimensions. - * @author Nicola Asuni - * @since 5.0.000 (2010-05-02) - * @public - */ - public function ImageSVG($file, $x=null, $y=null, $w=0, $h=0, $link='', $align='', $palign='', $border=0, $fitonpage=false) { - if ($this->state != 2) { - return; - } - // reset SVG vars - $this->svggradients = array(); - $this->svggradientid = 0; - $this->svgdefsmode = false; - $this->svgdefs = array(); - $this->svgclipmode = false; - $this->svgclippaths = array(); - $this->svgcliptm = array(); - $this->svgclipid = 0; - $this->svgtext = ''; - $this->svgtextmode = array(); - if ($this->rasterize_vector_images AND ($w > 0) AND ($h > 0)) { - // convert SVG to raster image using GD or ImageMagick libraries - return $this->Image($file, $x, $y, $w, $h, 'SVG', $link, $align, true, 300, $palign, false, false, $border, false, false, false); - } - if ($file[0] === '@') { // image from string - $this->svgdir = ''; - $svgdata = substr($file, 1); - } else { // SVG file - $this->svgdir = dirname($file); - $svgdata = $this->getCachedFileContents($file); - } - if ($svgdata === FALSE) { - $this->Error('SVG file not found: '.$file); - } - if (TCPDF_STATIC::empty_string($x)) { - $x = $this->x; - } - if (TCPDF_STATIC::empty_string($y)) { - $y = $this->y; - } - // check page for no-write regions and adapt page margins if necessary - list($x, $y) = $this->checkPageRegions($h, $x, $y); - $k = $this->k; - $ox = 0; - $oy = 0; - $ow = $w; - $oh = $h; - $aspect_ratio_align = 'xMidYMid'; - $aspect_ratio_ms = 'meet'; - $regs = array(); - // get original image width and height - preg_match('/<svg([^\>]*)>/si', $svgdata, $regs); - if (isset($regs[1]) AND !empty($regs[1])) { - $tmp = array(); - if (preg_match('/[\s]+x[\s]*=[\s]*"([^"]*)"/si', $regs[1], $tmp)) { - $ox = $this->getHTMLUnitToUnits($tmp[1], 0, $this->svgunit, false); - } - $tmp = array(); - if (preg_match('/[\s]+y[\s]*=[\s]*"([^"]*)"/si', $regs[1], $tmp)) { - $oy = $this->getHTMLUnitToUnits($tmp[1], 0, $this->svgunit, false); - } - $tmp = array(); - if (preg_match('/[\s]+width[\s]*=[\s]*"([^"]*)"/si', $regs[1], $tmp)) { - $ow = $this->getHTMLUnitToUnits($tmp[1], 1, $this->svgunit, false); - } - $tmp = array(); - if (preg_match('/[\s]+height[\s]*=[\s]*"([^"]*)"/si', $regs[1], $tmp)) { - $oh = $this->getHTMLUnitToUnits($tmp[1], 1, $this->svgunit, false); - } - $tmp = array(); - $view_box = array(); - if (preg_match('/[\s]+viewBox[\s]*=[\s]*"[\s]*([0-9\.\-]+)[\s]+([0-9\.\-]+)[\s]+([0-9\.]+)[\s]+([0-9\.]+)[\s]*"/si', $regs[1], $tmp)) { - if (count($tmp) == 5) { - array_shift($tmp); - foreach ($tmp as $key => $val) { - $view_box[$key] = $this->getHTMLUnitToUnits($val, 0, $this->svgunit, false); - } - $ox = $view_box[0]; - $oy = $view_box[1]; - } - // get aspect ratio - $tmp = array(); - if (preg_match('/[\s]+preserveAspectRatio[\s]*=[\s]*"([^"]*)"/si', $regs[1], $tmp)) { - $aspect_ratio = preg_split('/[\s]+/si', $tmp[1]); - switch (count($aspect_ratio)) { - case 3: { - $aspect_ratio_align = $aspect_ratio[1]; - $aspect_ratio_ms = $aspect_ratio[2]; - break; - } - case 2: { - $aspect_ratio_align = $aspect_ratio[0]; - $aspect_ratio_ms = $aspect_ratio[1]; - break; - } - case 1: { - $aspect_ratio_align = $aspect_ratio[0]; - $aspect_ratio_ms = 'meet'; - break; - } - } - } - } - } - if ($ow <= 0) { - $ow = 1; - } - if ($oh <= 0) { - $oh = 1; - } - // calculate image width and height on document - if (($w <= 0) AND ($h <= 0)) { - // convert image size to document unit - $w = $ow; - $h = $oh; - } elseif ($w <= 0) { - $w = $h * $ow / $oh; - } elseif ($h <= 0) { - $h = $w * $oh / $ow; - } - // fit the image on available space - list($w, $h, $x, $y) = $this->fitBlock($w, $h, $x, $y, $fitonpage); - if ($this->rasterize_vector_images) { - // convert SVG to raster image using GD or ImageMagick libraries - return $this->Image($file, $x, $y, $w, $h, 'SVG', $link, $align, true, 300, $palign, false, false, $border, false, false, false); - } - // set alignment - $this->img_rb_y = $y + $h; - // set alignment - if ($this->rtl) { - if ($palign == 'L') { - $ximg = $this->lMargin; - } elseif ($palign == 'C') { - $ximg = ($this->w + $this->lMargin - $this->rMargin - $w) / 2; - } elseif ($palign == 'R') { - $ximg = $this->w - $this->rMargin - $w; - } else { - $ximg = $x - $w; - } - $this->img_rb_x = $ximg; - } else { - if ($palign == 'L') { - $ximg = $this->lMargin; - } elseif ($palign == 'C') { - $ximg = ($this->w + $this->lMargin - $this->rMargin - $w) / 2; - } elseif ($palign == 'R') { - $ximg = $this->w - $this->rMargin - $w; - } else { - $ximg = $x; - } - $this->img_rb_x = $ximg + $w; - } - // store current graphic vars - $gvars = $this->getGraphicVars(); - // store SVG position and scale factors - $svgoffset_x = ($ximg - $ox) * $this->k; - $svgoffset_y = -($y - $oy) * $this->k; - if (isset($view_box[2]) AND ($view_box[2] > 0) AND ($view_box[3] > 0)) { - $ow = $view_box[2]; - $oh = $view_box[3]; - } else { - if ($ow <= 0) { - $ow = $w; - } - if ($oh <= 0) { - $oh = $h; - } - } - $svgscale_x = $w / $ow; - $svgscale_y = $h / $oh; - // scaling and alignment - if ($aspect_ratio_align != 'none') { - // store current scaling values - $svgscale_old_x = $svgscale_x; - $svgscale_old_y = $svgscale_y; - // force uniform scaling - if ($aspect_ratio_ms == 'slice') { - // the entire viewport is covered by the viewBox - if ($svgscale_x > $svgscale_y) { - $svgscale_y = $svgscale_x; - } elseif ($svgscale_x < $svgscale_y) { - $svgscale_x = $svgscale_y; - } - } else { // meet - // the entire viewBox is visible within the viewport - if ($svgscale_x < $svgscale_y) { - $svgscale_y = $svgscale_x; - } elseif ($svgscale_x > $svgscale_y) { - $svgscale_x = $svgscale_y; - } - } - // correct X alignment - switch (substr($aspect_ratio_align, 1, 3)) { - case 'Min': { - // do nothing - break; - } - case 'Max': { - $svgoffset_x += (($w * $this->k) - ($ow * $this->k * $svgscale_x)); - break; - } - default: - case 'Mid': { - $svgoffset_x += ((($w * $this->k) - ($ow * $this->k * $svgscale_x)) / 2); - break; - } - } - // correct Y alignment - switch (substr($aspect_ratio_align, 5)) { - case 'Min': { - // do nothing - break; - } - case 'Max': { - $svgoffset_y -= (($h * $this->k) - ($oh * $this->k * $svgscale_y)); - break; - } - default: - case 'Mid': { - $svgoffset_y -= ((($h * $this->k) - ($oh * $this->k * $svgscale_y)) / 2); - break; - } - } - } - // store current page break mode - $page_break_mode = $this->AutoPageBreak; - $page_break_margin = $this->getBreakMargin(); - $cell_padding = $this->cell_padding; - $this->setCellPadding(0); - $this->setAutoPageBreak(false); - // save the current graphic state - $this->_out('q'.$this->epsmarker); - // set initial clipping mask - $this->Rect($ximg, $y, $w, $h, 'CNZ', array(), array()); - // scale and translate - $e = $ox * $this->k * (1 - $svgscale_x); - $f = ($this->h - $oy) * $this->k * (1 - $svgscale_y); - $this->_out(sprintf('%F %F %F %F %F %F cm', $svgscale_x, 0, 0, $svgscale_y, ($e + $svgoffset_x), ($f + $svgoffset_y))); - // creates a new XML parser to be used by the other XML functions - $parser = xml_parser_create('UTF-8'); - // the following function allows to use parser inside object - xml_set_object($parser, $this); - // disable case-folding for this XML parser - xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); - // sets the element handler functions for the XML parser - xml_set_element_handler($parser, 'startSVGElementHandler', 'endSVGElementHandler'); - // sets the character data handler function for the XML parser - xml_set_character_data_handler($parser, 'segSVGContentHandler'); - // start parsing an XML document - if (!xml_parse($parser, $svgdata)) { - $error_message = sprintf('SVG Error: %s at line %d', xml_error_string(xml_get_error_code($parser)), xml_get_current_line_number($parser)); - $this->Error($error_message); - } - // free this XML parser - xml_parser_free($parser); - - // >= PHP 7.0.0 "explicitly unset the reference to parser to avoid memory leaks" - unset($parser); - - // restore previous graphic state - $this->_out($this->epsmarker.'Q'); - // restore graphic vars - $this->setGraphicVars($gvars); - $this->lasth = $gvars['lasth']; - if (!empty($border)) { - $bx = $this->x; - $by = $this->y; - $this->x = $ximg; - if ($this->rtl) { - $this->x += $w; - } - $this->y = $y; - $this->Cell($w, $h, '', $border, 0, '', 0, '', 0, true); - $this->x = $bx; - $this->y = $by; - } - if ($link) { - $this->Link($ximg, $y, $w, $h, $link, 0); - } - // set pointer to align the next text/objects - switch($align) { - case 'T':{ - $this->y = $y; - $this->x = $this->img_rb_x; - break; - } - case 'M':{ - $this->y = $y + round($h/2); - $this->x = $this->img_rb_x; - break; - } - case 'B':{ - $this->y = $this->img_rb_y; - $this->x = $this->img_rb_x; - break; - } - case 'N':{ - $this->setY($this->img_rb_y); - break; - } - default:{ - // restore pointer to starting position - $this->x = $gvars['x']; - $this->y = $gvars['y']; - $this->page = $gvars['page']; - $this->current_column = $gvars['current_column']; - $this->tMargin = $gvars['tMargin']; - $this->bMargin = $gvars['bMargin']; - $this->w = $gvars['w']; - $this->h = $gvars['h']; - $this->wPt = $gvars['wPt']; - $this->hPt = $gvars['hPt']; - $this->fwPt = $gvars['fwPt']; - $this->fhPt = $gvars['fhPt']; - break; - } - } - $this->endlinex = $this->img_rb_x; - // restore page break - $this->setAutoPageBreak($page_break_mode, $page_break_margin); - $this->cell_padding = $cell_padding; - } - - /** - * Convert SVG transformation matrix to PDF. - * @param array $tm original SVG transformation matrix - * @return array transformation matrix - * @protected - * @since 5.0.000 (2010-05-02) - */ - protected function convertSVGtMatrix($tm) { - $a = $tm[0]; - $b = -$tm[1]; - $c = -$tm[2]; - $d = $tm[3]; - $e = $this->getHTMLUnitToUnits($tm[4], 1, $this->svgunit, false) * $this->k; - $f = -$this->getHTMLUnitToUnits($tm[5], 1, $this->svgunit, false) * $this->k; - $x = 0; - $y = $this->h * $this->k; - $e = ($x * (1 - $a)) - ($y * $c) + $e; - $f = ($y * (1 - $d)) - ($x * $b) + $f; - return array($a, $b, $c, $d, $e, $f); - } - - /** - * Apply SVG graphic transformation matrix. - * @param array $tm original SVG transformation matrix - * @protected - * @since 5.0.000 (2010-05-02) - */ - protected function SVGTransform($tm) { - $this->Transform($this->convertSVGtMatrix($tm)); - } - - /** - * Apply the requested SVG styles (*** TO BE COMPLETED ***) - * @param array $svgstyle array of SVG styles to apply - * @param array $prevsvgstyle array of previous SVG style - * @param int $x X origin of the bounding box - * @param int $y Y origin of the bounding box - * @param int $w width of the bounding box - * @param int $h height of the bounding box - * @param string $clip_function clip function - * @param array $clip_params array of parameters for clipping function - * @return string style - * @author Nicola Asuni - * @since 5.0.000 (2010-05-02) - * @protected - */ - protected function setSVGStyles($svgstyle, $prevsvgstyle, $x=0, $y=0, $w=1, $h=1, $clip_function='', $clip_params=array()) { - if ($this->state != 2) { - return; - } - $objstyle = ''; - $minlen = (0.01 / $this->k); // minimum acceptable length - if (!isset($svgstyle['opacity'])) { - return $objstyle; - } - // clip-path - $regs = array(); - if (preg_match('/url\([\s]*\#([^\)]*)\)/si', $svgstyle['clip-path'], $regs)) { - $clip_path = $this->svgclippaths[$regs[1]]; - foreach ($clip_path as $cp) { - $this->startSVGElementHandler('clip-path', $cp['name'], $cp['attribs'], $cp['tm']); - } - } - // opacity - if ($svgstyle['opacity'] != 1) { - $this->setAlpha($svgstyle['opacity'], 'Normal', $svgstyle['opacity'], false); - } - // color - $fill_color = TCPDF_COLORS::convertHTMLColorToDec($svgstyle['color'], $this->spot_colors); - $this->setFillColorArray($fill_color); - // text color - $text_color = TCPDF_COLORS::convertHTMLColorToDec($svgstyle['text-color'], $this->spot_colors); - $this->setTextColorArray($text_color); - // clip - if (preg_match('/rect\(([a-z0-9\-\.]*)[\s]*([a-z0-9\-\.]*)[\s]*([a-z0-9\-\.]*)[\s]*([a-z0-9\-\.]*)\)/si', $svgstyle['clip'], $regs)) { - $top = (isset($regs[1])?$this->getHTMLUnitToUnits($regs[1], 0, $this->svgunit, false):0); - $right = (isset($regs[2])?$this->getHTMLUnitToUnits($regs[2], 0, $this->svgunit, false):0); - $bottom = (isset($regs[3])?$this->getHTMLUnitToUnits($regs[3], 0, $this->svgunit, false):0); - $left = (isset($regs[4])?$this->getHTMLUnitToUnits($regs[4], 0, $this->svgunit, false):0); - $cx = $x + $left; - $cy = $y + $top; - $cw = $w - $left - $right; - $ch = $h - $top - $bottom; - if ($svgstyle['clip-rule'] == 'evenodd') { - $clip_rule = 'CNZ'; - } else { - $clip_rule = 'CEO'; - } - $this->Rect($cx, $cy, $cw, $ch, $clip_rule, array(), array()); - } - // fill - $regs = array(); - if (preg_match('/url\([\s]*\#([^\)]*)\)/si', $svgstyle['fill'], $regs)) { - // gradient - $gradient = $this->svggradients[$regs[1]]; - if (isset($gradient['xref'])) { - // reference to another gradient definition - $newgradient = $this->svggradients[$gradient['xref']]; - $newgradient['coords'] = $gradient['coords']; - $newgradient['mode'] = $gradient['mode']; - $newgradient['type'] = $gradient['type']; - $newgradient['gradientUnits'] = $gradient['gradientUnits']; - if (isset($gradient['gradientTransform'])) { - $newgradient['gradientTransform'] = $gradient['gradientTransform']; - } - $gradient = $newgradient; - } - //save current Graphic State - $this->_outSaveGraphicsState(); - //set clipping area - if (!empty($clip_function) AND method_exists($this, $clip_function)) { - $bbox = call_user_func_array(array($this, $clip_function), $clip_params); - if ((!isset($gradient['type']) OR ($gradient['type'] != 3)) AND is_array($bbox) AND (count($bbox) == 4)) { - list($x, $y, $w, $h) = $bbox; - } - } - if ($gradient['mode'] == 'measure') { - if (!isset($gradient['coords'][4])) { - $gradient['coords'][4] = 0.5; - } - if (isset($gradient['gradientTransform']) AND !empty($gradient['gradientTransform'])) { - $gtm = $gradient['gradientTransform']; - // apply transformation matrix - $xa = ($gtm[0] * $gradient['coords'][0]) + ($gtm[2] * $gradient['coords'][1]) + $gtm[4]; - $ya = ($gtm[1] * $gradient['coords'][0]) + ($gtm[3] * $gradient['coords'][1]) + $gtm[5]; - $xb = ($gtm[0] * $gradient['coords'][2]) + ($gtm[2] * $gradient['coords'][3]) + $gtm[4]; - $yb = ($gtm[1] * $gradient['coords'][2]) + ($gtm[3] * $gradient['coords'][3]) + $gtm[5]; - $r = sqrt(pow(($gtm[0] * $gradient['coords'][4]), 2) + pow(($gtm[1] * $gradient['coords'][4]), 2)); - $gradient['coords'][0] = $xa; - $gradient['coords'][1] = $ya; - $gradient['coords'][2] = $xb; - $gradient['coords'][3] = $yb; - $gradient['coords'][4] = $r; - } - // convert SVG coordinates to user units - $gradient['coords'][0] = $this->getHTMLUnitToUnits($gradient['coords'][0], 0, $this->svgunit, false); - $gradient['coords'][1] = $this->getHTMLUnitToUnits($gradient['coords'][1], 0, $this->svgunit, false); - $gradient['coords'][2] = $this->getHTMLUnitToUnits($gradient['coords'][2], 0, $this->svgunit, false); - $gradient['coords'][3] = $this->getHTMLUnitToUnits($gradient['coords'][3], 0, $this->svgunit, false); - $gradient['coords'][4] = $this->getHTMLUnitToUnits($gradient['coords'][4], 0, $this->svgunit, false); - if ($w <= $minlen) { - $w = $minlen; - } - if ($h <= $minlen) { - $h = $minlen; - } - // shift units - if ($gradient['gradientUnits'] == 'objectBoundingBox') { - // convert to SVG coordinate system - $gradient['coords'][0] += $x; - $gradient['coords'][1] += $y; - $gradient['coords'][2] += $x; - $gradient['coords'][3] += $y; - } - // calculate percentages - $gradient['coords'][0] = (($gradient['coords'][0] - $x) / $w); - $gradient['coords'][1] = (($gradient['coords'][1] - $y) / $h); - $gradient['coords'][2] = (($gradient['coords'][2] - $x) / $w); - $gradient['coords'][3] = (($gradient['coords'][3] - $y) / $h); - $gradient['coords'][4] /= $w; - } elseif ($gradient['mode'] == 'percentage') { - foreach($gradient['coords'] as $key => $val) { - $gradient['coords'][$key] = (intval($val) / 100); - if ($val < 0) { - $gradient['coords'][$key] = 0; - } elseif ($val > 1) { - $gradient['coords'][$key] = 1; - } - } - } - if (($gradient['type'] == 2) AND ($gradient['coords'][0] == $gradient['coords'][2]) AND ($gradient['coords'][1] == $gradient['coords'][3])) { - // single color (no shading) - $gradient['coords'][0] = 1; - $gradient['coords'][1] = 0; - $gradient['coords'][2] = 0.999; - $gradient['coords'][3] = 0; - } - // swap Y coordinates - $tmp = $gradient['coords'][1]; - $gradient['coords'][1] = $gradient['coords'][3]; - $gradient['coords'][3] = $tmp; - // set transformation map for gradient - $cy = ($this->h - $y); - if ($gradient['type'] == 3) { - // circular gradient - $cy -= ($gradient['coords'][1] * ($w + $h)); - $h = $w = max($w, $h); - } else { - $cy -= $h; - } - $this->_out(sprintf('%F 0 0 %F %F %F cm', ($w * $this->k), ($h * $this->k), ($x * $this->k), ($cy * $this->k))); - if (count($gradient['stops']) > 1) { - $this->Gradient($gradient['type'], $gradient['coords'], $gradient['stops'], array(), false); - } - } elseif ($svgstyle['fill'] != 'none') { - $fill_color = TCPDF_COLORS::convertHTMLColorToDec($svgstyle['fill'], $this->spot_colors); - if ($svgstyle['fill-opacity'] != 1) { - $this->setAlpha($this->alpha['CA'], 'Normal', $svgstyle['fill-opacity'], false); - } - $this->setFillColorArray($fill_color); - if ($svgstyle['fill-rule'] == 'evenodd') { - $objstyle .= 'F*'; - } else { - $objstyle .= 'F'; - } - } - // stroke - if ($svgstyle['stroke'] != 'none') { - if ($svgstyle['stroke-opacity'] != 1) { - $this->setAlpha($svgstyle['stroke-opacity'], 'Normal', $this->alpha['ca'], false); - } elseif (preg_match('/rgba\(\d+%?,\s*\d+%?,\s*\d+%?,\s*(\d+(?:\.\d+)?)\)/i', $svgstyle['stroke'], $rgba_matches)) { - $this->setAlpha($rgba_matches[1], 'Normal', $this->alpha['ca'], false); - } - $stroke_style = array( - 'color' => TCPDF_COLORS::convertHTMLColorToDec($svgstyle['stroke'], $this->spot_colors), - 'width' => $this->getHTMLUnitToUnits($svgstyle['stroke-width'], 0, $this->svgunit, false), - 'cap' => $svgstyle['stroke-linecap'], - 'join' => $svgstyle['stroke-linejoin'] - ); - if (isset($svgstyle['stroke-dasharray']) AND !empty($svgstyle['stroke-dasharray']) AND ($svgstyle['stroke-dasharray'] != 'none')) { - $stroke_style['dash'] = $svgstyle['stroke-dasharray']; - } - $this->setLineStyle($stroke_style); - $objstyle .= 'D'; - } - // font - $regs = array(); - if (!empty($svgstyle['font'])) { - if (preg_match('/font-family[\s]*:[\s]*([^\;\"]*)/si', $svgstyle['font'], $regs)) { - $font_family = $this->getFontFamilyName($regs[1]); - } else { - $font_family = $svgstyle['font-family']; - } - if (preg_match('/font-size[\s]*:[\s]*([^\s\;\"]*)/si', $svgstyle['font'], $regs)) { - $font_size = trim($regs[1]); - } else { - $font_size = $svgstyle['font-size']; - } - if (preg_match('/font-style[\s]*:[\s]*([^\s\;\"]*)/si', $svgstyle['font'], $regs)) { - $font_style = trim($regs[1]); - } else { - $font_style = $svgstyle['font-style']; - } - if (preg_match('/font-weight[\s]*:[\s]*([^\s\;\"]*)/si', $svgstyle['font'], $regs)) { - $font_weight = trim($regs[1]); - } else { - $font_weight = $svgstyle['font-weight']; - } - if (preg_match('/font-stretch[\s]*:[\s]*([^\s\;\"]*)/si', $svgstyle['font'], $regs)) { - $font_stretch = trim($regs[1]); - } else { - $font_stretch = $svgstyle['font-stretch']; - } - if (preg_match('/letter-spacing[\s]*:[\s]*([^\s\;\"]*)/si', $svgstyle['font'], $regs)) { - $font_spacing = trim($regs[1]); - } else { - $font_spacing = $svgstyle['letter-spacing']; - } - } else { - $font_family = $this->getFontFamilyName($svgstyle['font-family']); - $font_size = $svgstyle['font-size']; - $font_style = $svgstyle['font-style']; - $font_weight = $svgstyle['font-weight']; - $font_stretch = $svgstyle['font-stretch']; - $font_spacing = $svgstyle['letter-spacing']; - } - $font_size = $this->getHTMLFontUnits($font_size, $this->svgstyles[0]['font-size'], $prevsvgstyle['font-size'], $this->svgunit); - $font_stretch = $this->getCSSFontStretching($font_stretch, $svgstyle['font-stretch']); - $font_spacing = $this->getCSSFontSpacing($font_spacing, $svgstyle['letter-spacing']); - switch ($font_style) { - case 'italic': { - $font_style = 'I'; - break; - } - case 'oblique': { - $font_style = 'I'; - break; - } - default: - case 'normal': { - $font_style = ''; - break; - } - } - switch ($font_weight) { - case 'bold': - case 'bolder': { - $font_style .= 'B'; - break; - } - case 'normal': { - if ((substr($font_family, -1) == 'I') AND (substr($font_family, -2, 1) == 'B')) { - $font_family = substr($font_family, 0, -2).'I'; - } elseif (substr($font_family, -1) == 'B') { - $font_family = substr($font_family, 0, -1); - } - break; - } - } - switch ($svgstyle['text-decoration']) { - case 'underline': { - $font_style .= 'U'; - break; - } - case 'overline': { - $font_style .= 'O'; - break; - } - case 'line-through': { - $font_style .= 'D'; - break; - } - default: - case 'none': { - break; - } - } - $this->setFont($font_family, $font_style, $font_size); - $this->setFontStretching($font_stretch); - $this->setFontSpacing($font_spacing); - return $objstyle; - } - - /** - * Draws an SVG path - * @param string $d attribute d of the path SVG element - * @param string $style Style of rendering. Possible values are: - * <ul> - * <li>D or empty string: Draw (default).</li> - * <li>F: Fill.</li> - * <li>F*: Fill using the even-odd rule to determine which regions lie inside the clipping path.</li> - * <li>DF or FD: Draw and fill.</li> - * <li>DF* or FD*: Draw and fill using the even-odd rule to determine which regions lie inside the clipping path.</li> - * <li>CNZ: Clipping mode (using the even-odd rule to determine which regions lie inside the clipping path).</li> - * <li>CEO: Clipping mode (using the nonzero winding number rule to determine which regions lie inside the clipping path).</li> - * </ul> - * @return array of container box measures (x, y, w, h) - * @author Nicola Asuni - * @since 5.0.000 (2010-05-02) - * @protected - */ - protected function SVGPath($d, $style='') { - if ($this->state != 2) { - return; - } - // set fill/stroke style - $op = TCPDF_STATIC::getPathPaintOperator($style, ''); - if (empty($op)) { - return; - } - $paths = array(); - $d = preg_replace('/([0-9ACHLMQSTVZ])([\-\+])/si', '\\1 \\2', $d); - $d = preg_replace('/(\.[0-9]+)(\.)/s', '\\1 \\2', $d); - preg_match_all('/([ACHLMQSTVZ])[\s]*([^ACHLMQSTVZ\"]*)/si', $d, $paths, PREG_SET_ORDER); - $x = 0; - $y = 0; - $x1 = 0; - $y1 = 0; - $x2 = 0; - $y2 = 0; - $xmin = 2147483647; - $xmax = 0; - $ymin = 2147483647; - $ymax = 0; - $xinitial = 0; - $yinitial = 0; - $relcoord = false; - $minlen = (0.01 / $this->k); // minimum acceptable length (3 point) - $firstcmd = true; // used to print first point - // draw curve pieces - foreach ($paths as $key => $val) { - // get curve type - $cmd = trim($val[1]); - if (strtolower($cmd) == $cmd) { - // use relative coordinated instead of absolute - $relcoord = true; - $xoffset = $x; - $yoffset = $y; - } else { - $relcoord = false; - $xoffset = 0; - $yoffset = 0; - } - $params = array(); - if (isset($val[2])) { - // get curve parameters - $rawparams = preg_split('/([\,\s]+)/si', trim($val[2])); - $params = array(); - foreach ($rawparams as $ck => $cp) { - $params[$ck] = $this->getHTMLUnitToUnits($cp, 0, $this->svgunit, false); - if (abs($params[$ck]) < $minlen) { - // approximate little values to zero - $params[$ck] = 0; - } - } - } - // store current origin point - $x0 = $x; - $y0 = $y; - switch (strtoupper($cmd)) { - case 'M': { // moveto - foreach ($params as $ck => $cp) { - if (($ck % 2) == 0) { - $x = $cp + $xoffset; - } else { - $y = $cp + $yoffset; - if ($firstcmd OR (abs($x0 - $x) >= $minlen) OR (abs($y0 - $y) >= $minlen)) { - if ($ck == 1) { - $this->_outPoint($x, $y); - $firstcmd = false; - $xinitial = $x; - $yinitial = $y; - } else { - $this->_outLine($x, $y); - } - $x0 = $x; - $y0 = $y; - } - $xmin = min($xmin, $x); - $ymin = min($ymin, $y); - $xmax = max($xmax, $x); - $ymax = max($ymax, $y); - if ($relcoord) { - $xoffset = $x; - $yoffset = $y; - } - } - } - break; - } - case 'L': { // lineto - foreach ($params as $ck => $cp) { - if (($ck % 2) == 0) { - $x = $cp + $xoffset; - } else { - $y = $cp + $yoffset; - if ((abs($x0 - $x) >= $minlen) OR (abs($y0 - $y) >= $minlen)) { - $this->_outLine($x, $y); - $x0 = $x; - $y0 = $y; - } - $xmin = min($xmin, $x); - $ymin = min($ymin, $y); - $xmax = max($xmax, $x); - $ymax = max($ymax, $y); - if ($relcoord) { - $xoffset = $x; - $yoffset = $y; - } - } - } - break; - } - case 'H': { // horizontal lineto - foreach ($params as $ck => $cp) { - $x = $cp + $xoffset; - if ((abs($x0 - $x) >= $minlen) OR (abs($y0 - $y) >= $minlen)) { - $this->_outLine($x, $y); - $x0 = $x; - $y0 = $y; - } - $xmin = min($xmin, $x); - $xmax = max($xmax, $x); - if ($relcoord) { - $xoffset = $x; - } - } - break; - } - case 'V': { // vertical lineto - foreach ($params as $ck => $cp) { - $y = $cp + $yoffset; - if ((abs($x0 - $x) >= $minlen) OR (abs($y0 - $y) >= $minlen)) { - $this->_outLine($x, $y); - $x0 = $x; - $y0 = $y; - } - $ymin = min($ymin, $y); - $ymax = max($ymax, $y); - if ($relcoord) { - $yoffset = $y; - } - } - break; - } - case 'C': { // curveto - foreach ($params as $ck => $cp) { - $params[$ck] = $cp; - if ((($ck + 1) % 6) == 0) { - $x1 = $params[($ck - 5)] + $xoffset; - $y1 = $params[($ck - 4)] + $yoffset; - $x2 = $params[($ck - 3)] + $xoffset; - $y2 = $params[($ck - 2)] + $yoffset; - $x = $params[($ck - 1)] + $xoffset; - $y = $params[($ck)] + $yoffset; - $this->_outCurve($x1, $y1, $x2, $y2, $x, $y); - $xmin = min($xmin, $x, $x1, $x2); - $ymin = min($ymin, $y, $y1, $y2); - $xmax = max($xmax, $x, $x1, $x2); - $ymax = max($ymax, $y, $y1, $y2); - if ($relcoord) { - $xoffset = $x; - $yoffset = $y; - } - } - } - break; - } - case 'S': { // shorthand/smooth curveto - foreach ($params as $ck => $cp) { - $params[$ck] = $cp; - if ((($ck + 1) % 4) == 0) { - if (($key > 0) AND ((strtoupper($paths[($key - 1)][1]) == 'C') OR (strtoupper($paths[($key - 1)][1]) == 'S'))) { - $x1 = (2 * $x) - $x2; - $y1 = (2 * $y) - $y2; - } else { - $x1 = $x; - $y1 = $y; - } - $x2 = $params[($ck - 3)] + $xoffset; - $y2 = $params[($ck - 2)] + $yoffset; - $x = $params[($ck - 1)] + $xoffset; - $y = $params[($ck)] + $yoffset; - $this->_outCurve($x1, $y1, $x2, $y2, $x, $y); - $xmin = min($xmin, $x, $x1, $x2); - $ymin = min($ymin, $y, $y1, $y2); - $xmax = max($xmax, $x, $x1, $x2); - $ymax = max($ymax, $y, $y1, $y2); - if ($relcoord) { - $xoffset = $x; - $yoffset = $y; - } - } - } - break; - } - case 'Q': { // quadratic Bezier curveto - foreach ($params as $ck => $cp) { - $params[$ck] = $cp; - if ((($ck + 1) % 4) == 0) { - // convert quadratic points to cubic points - $x1 = $params[($ck - 3)] + $xoffset; - $y1 = $params[($ck - 2)] + $yoffset; - $xa = ($x + (2 * $x1)) / 3; - $ya = ($y + (2 * $y1)) / 3; - $x = $params[($ck - 1)] + $xoffset; - $y = $params[($ck)] + $yoffset; - $xb = ($x + (2 * $x1)) / 3; - $yb = ($y + (2 * $y1)) / 3; - $this->_outCurve($xa, $ya, $xb, $yb, $x, $y); - $xmin = min($xmin, $x, $xa, $xb); - $ymin = min($ymin, $y, $ya, $yb); - $xmax = max($xmax, $x, $xa, $xb); - $ymax = max($ymax, $y, $ya, $yb); - if ($relcoord) { - $xoffset = $x; - $yoffset = $y; - } - } - } - break; - } - case 'T': { // shorthand/smooth quadratic Bezier curveto - foreach ($params as $ck => $cp) { - $params[$ck] = $cp; - if (($ck % 2) != 0) { - if (($key > 0) AND ((strtoupper($paths[($key - 1)][1]) == 'Q') OR (strtoupper($paths[($key - 1)][1]) == 'T'))) { - $x1 = (2 * $x) - $x1; - $y1 = (2 * $y) - $y1; - } else { - $x1 = $x; - $y1 = $y; - } - // convert quadratic points to cubic points - $xa = ($x + (2 * $x1)) / 3; - $ya = ($y + (2 * $y1)) / 3; - $x = $params[($ck - 1)] + $xoffset; - $y = $params[($ck)] + $yoffset; - $xb = ($x + (2 * $x1)) / 3; - $yb = ($y + (2 * $y1)) / 3; - $this->_outCurve($xa, $ya, $xb, $yb, $x, $y); - $xmin = min($xmin, $x, $xa, $xb); - $ymin = min($ymin, $y, $ya, $yb); - $xmax = max($xmax, $x, $xa, $xb); - $ymax = max($ymax, $y, $ya, $yb); - if ($relcoord) { - $xoffset = $x; - $yoffset = $y; - } - } - } - break; - } - case 'A': { // elliptical arc - foreach ($params as $ck => $cp) { - $params[$ck] = $cp; - if ((($ck + 1) % 7) == 0) { - $x0 = $x; - $y0 = $y; - $rx = max(abs($params[($ck - 6)]), .000000001); - $ry = max(abs($params[($ck - 5)]), .000000001); - $ang = -$rawparams[($ck - 4)]; - $angle = deg2rad($ang); - $fa = $rawparams[($ck - 3)]; // large-arc-flag - $fs = $rawparams[($ck - 2)]; // sweep-flag - $x = $params[($ck - 1)] + $xoffset; - $y = $params[$ck] + $yoffset; - if ((abs($x0 - $x) < $minlen) AND (abs($y0 - $y) < $minlen)) { - // endpoints are almost identical - $xmin = min($xmin, $x); - $ymin = min($ymin, $y); - $xmax = max($xmax, $x); - $ymax = max($ymax, $y); - } else { - $cos_ang = cos($angle); - $sin_ang = sin($angle); - $a = (($x0 - $x) / 2); - $b = (($y0 - $y) / 2); - $xa = ($a * $cos_ang) - ($b * $sin_ang); - $ya = ($a * $sin_ang) + ($b * $cos_ang); - $rx2 = $rx * $rx; - $ry2 = $ry * $ry; - $xa2 = $xa * $xa; - $ya2 = $ya * $ya; - $delta = ($xa2 / $rx2) + ($ya2 / $ry2); - if ($delta > 1) { - $rx *= sqrt($delta); - $ry *= sqrt($delta); - $rx2 = $rx * $rx; - $ry2 = $ry * $ry; - } - $numerator = (($rx2 * $ry2) - ($rx2 * $ya2) - ($ry2 * $xa2)); - if ($numerator < 0) { - $root = 0; - } else { - $root = sqrt($numerator / (($rx2 * $ya2) + ($ry2 * $xa2))); - } - if ($fa == $fs){ - $root *= -1; - } - $cax = $root * (($rx * $ya) / $ry); - $cay = -$root * (($ry * $xa) / $rx); - // coordinates of ellipse center - $cx = ($cax * $cos_ang) - ($cay * $sin_ang) + (($x0 + $x) / 2); - $cy = ($cax * $sin_ang) + ($cay * $cos_ang) + (($y0 + $y) / 2); - // get angles - $angs = TCPDF_STATIC::getVectorsAngle(1, 0, (($xa - $cax) / $rx), (($cay - $ya) / $ry)); - $dang = TCPDF_STATIC::getVectorsAngle((($xa - $cax) / $rx), (($ya - $cay) / $ry), ((-$xa - $cax) / $rx), ((-$ya - $cay) / $ry)); - if (($fs == 0) AND ($dang > 0)) { - $dang -= (2 * M_PI); - } elseif (($fs == 1) AND ($dang < 0)) { - $dang += (2 * M_PI); - } - $angf = $angs - $dang; - if ((($fs == 0) AND ($angs > $angf)) OR (($fs == 1) AND ($angs < $angf))) { - // reverse angles - $tmp = $angs; - $angs = $angf; - $angf = $tmp; - } - $angs = round(rad2deg($angs), 6); - $angf = round(rad2deg($angf), 6); - // covent angles to positive values - if (($angs < 0) AND ($angf < 0)) { - $angs += 360; - $angf += 360; - } - $pie = false; - if (($key == 0) AND (isset($paths[($key + 1)][1])) AND (trim($paths[($key + 1)][1]) == 'z')) { - $pie = true; - } - list($axmin, $aymin, $axmax, $aymax) = $this->_outellipticalarc($cx, $cy, $rx, $ry, $ang, $angs, $angf, $pie, 2, false, ($fs == 0), true); - $xmin = min($xmin, $x, $axmin); - $ymin = min($ymin, $y, $aymin); - $xmax = max($xmax, $x, $axmax); - $ymax = max($ymax, $y, $aymax); - } - if ($relcoord) { - $xoffset = $x; - $yoffset = $y; - } - } - } - break; - } - case 'Z': { - $this->_out('h'); - $x = $x0 = $xinitial; - $y = $y0 = $yinitial; - break; - } - } - $firstcmd = false; - } // end foreach - if (!empty($op)) { - $this->_out($op); - } - return array($xmin, $ymin, ($xmax - $xmin), ($ymax - $ymin)); - } - - /** - * Return the tag name without the namespace - * @param string $name Tag name - * @protected - */ - protected function removeTagNamespace($name) { - if(strpos($name, ':') !== false) { - $parts = explode(':', $name); - return $parts[(sizeof($parts) - 1)]; - } - return $name; - } - - /** - * Sets the opening SVG element handler function for the XML parser. (*** TO BE COMPLETED ***) - * @param resource|string $parser The first parameter, parser, is a reference to the XML parser calling the handler. - * @param string $name The second parameter, name, contains the name of the element for which this handler is called. If case-folding is in effect for this parser, the element name will be in uppercase letters. - * @param array $attribs The third parameter, attribs, contains an associative array with the element's attributes (if any). The keys of this array are the attribute names, the values are the attribute values. Attribute names are case-folded on the same criteria as element names. Attribute values are not case-folded. The original order of the attributes can be retrieved by walking through attribs the normal way, using each(). The first key in the array was the first attribute, and so on. - * @param array $ctm tranformation matrix for clipping mode (starting transformation matrix). - * @author Nicola Asuni - * @since 5.0.000 (2010-05-02) - * @protected - */ - protected function startSVGElementHandler($parser, $name, $attribs, $ctm=array()) { - $name = $this->removeTagNamespace($name); - // check if we are in clip mode - if ($this->svgclipmode) { - $this->svgclippaths[$this->svgclipid][] = array('name' => $name, 'attribs' => $attribs, 'tm' => $this->svgcliptm[$this->svgclipid]); - return; - } - if ($this->svgdefsmode AND !in_array($name, array('clipPath', 'linearGradient', 'radialGradient', 'stop'))) { - if (isset($attribs['id'])) { - $attribs['child_elements'] = array(); - $this->svgdefs[$attribs['id']] = array('name' => $name, 'attribs' => $attribs); - return; - } - if (end($this->svgdefs) !== FALSE) { - $last_svgdefs_id = key($this->svgdefs); - if (isset($this->svgdefs[$last_svgdefs_id]['attribs']['child_elements'])) { - $attribs['id'] = 'DF_'.(count($this->svgdefs[$last_svgdefs_id]['attribs']['child_elements']) + 1); - $this->svgdefs[$last_svgdefs_id]['attribs']['child_elements'][$attribs['id']] = array('name' => $name, 'attribs' => $attribs); - return; - } - } - return; - } - $clipping = false; - if ($parser == 'clip-path') { - // set clipping mode - $clipping = true; - } - // get styling properties - $prev_svgstyle = $this->svgstyles[max(0,(count($this->svgstyles) - 1))]; // previous style - $svgstyle = $this->svgstyles[0]; // set default style - if ($clipping AND !isset($attribs['fill']) AND (!isset($attribs['style']) OR (!preg_match('/[;\"\s]{1}fill[\s]*:[\s]*([^;\"]*)/si', $attribs['style'], $attrval)))) { - // default fill attribute for clipping - $attribs['fill'] = 'none'; - } - if (isset($attribs['style']) AND !TCPDF_STATIC::empty_string($attribs['style']) AND ($attribs['style'][0] != ';')) { - // fix style for regular expression - $attribs['style'] = ';'.$attribs['style']; - } - foreach ($prev_svgstyle as $key => $val) { - if (in_array($key, TCPDF_IMAGES::$svginheritprop)) { - // inherit previous value - $svgstyle[$key] = $val; - } - if (isset($attribs[$key]) AND !TCPDF_STATIC::empty_string($attribs[$key])) { - // specific attribute settings - if ($attribs[$key] == 'inherit') { - $svgstyle[$key] = $val; - } else { - $svgstyle[$key] = $attribs[$key]; - } - } elseif (isset($attribs['style']) AND !TCPDF_STATIC::empty_string($attribs['style'])) { - // CSS style syntax - $attrval = array(); - if (preg_match('/[;\"\s]{1}'.$key.'[\s]*:[\s]*([^;\"]*)/si', $attribs['style'], $attrval) AND isset($attrval[1])) { - if ($attrval[1] == 'inherit') { - $svgstyle[$key] = $val; - } else { - $svgstyle[$key] = $attrval[1]; - } - } - } - } - // transformation matrix - if (!empty($ctm)) { - $tm = $ctm; - } else { - $tm = array(1,0,0,1,0,0); - } - if (isset($attribs['transform']) AND !empty($attribs['transform'])) { - $tm = TCPDF_STATIC::getTransformationMatrixProduct($tm, TCPDF_STATIC::getSVGTransformMatrix($attribs['transform'])); - } - $svgstyle['transfmatrix'] = $tm; - $invisible = false; - if (($svgstyle['visibility'] == 'hidden') OR ($svgstyle['visibility'] == 'collapse') OR ($svgstyle['display'] == 'none')) { - // the current graphics element is invisible (nothing is painted) - $invisible = true; - } - // process tag - switch($name) { - case 'defs': { - $this->svgdefsmode = true; - break; - } - // clipPath - case 'clipPath': { - if ($invisible) { - break; - } - $this->svgclipmode = true; - if (!isset($attribs['id'])) { - $attribs['id'] = 'CP_'.(count($this->svgcliptm) + 1); - } - $this->svgclipid = $attribs['id']; - $this->svgclippaths[$this->svgclipid] = array(); - $this->svgcliptm[$this->svgclipid] = $tm; - break; - } - case 'svg': { - // start of SVG object - if(++$this->svg_tag_depth <= 1) { - break; - } - // inner SVG - array_push($this->svgstyles, $svgstyle); - $this->StartTransform(); - $svgX = (isset($attribs['x'])?$attribs['x']:0); - $svgY = (isset($attribs['y'])?$attribs['y']:0); - $svgW = (isset($attribs['width'])?$attribs['width']:0); - $svgH = (isset($attribs['height'])?$attribs['height']:0); - // set x, y position using transform matrix - $tm = TCPDF_STATIC::getTransformationMatrixProduct($tm, array( 1, 0, 0, 1, $svgX, $svgY)); - $this->SVGTransform($tm); - // set clipping for width and height - $x = 0; - $y = 0; - $w = (isset($attribs['width'])?$this->getHTMLUnitToUnits($attribs['width'], 0, $this->svgunit, false):$this->w); - $h = (isset($attribs['height'])?$this->getHTMLUnitToUnits($attribs['height'], 0, $this->svgunit, false):$this->h); - // draw clipping rect - $this->Rect($x, $y, $w, $h, 'CNZ', array(), array()); - // parse viewbox, calculate extra transformation matrix - if (isset($attribs['viewBox'])) { - $tmp = array(); - preg_match_all("/[0-9]+/", $attribs['viewBox'], $tmp); - $tmp = $tmp[0]; - if (sizeof($tmp) == 4) { - $vx = $tmp[0]; - $vy = $tmp[1]; - $vw = $tmp[2]; - $vh = $tmp[3]; - // get aspect ratio - $tmp = array(); - $aspectX = 'xMid'; - $aspectY = 'YMid'; - $fit = 'meet'; - if (isset($attribs['preserveAspectRatio'])) { - if($attribs['preserveAspectRatio'] == 'none') { - $fit = 'none'; - } else { - preg_match_all('/[a-zA-Z]+/', $attribs['preserveAspectRatio'], $tmp); - $tmp = $tmp[0]; - if ((sizeof($tmp) == 2) AND (strlen($tmp[0]) == 8) AND (in_array($tmp[1], array('meet', 'slice', 'none')))) { - $aspectX = substr($tmp[0], 0, 4); - $aspectY = substr($tmp[0], 4, 4); - $fit = $tmp[1]; - } - } - } - $wr = ($svgW / $vw); - $hr = ($svgH / $vh); - $ax = $ay = 0; - if ((($fit == 'meet') AND ($hr < $wr)) OR (($fit == 'slice') AND ($hr > $wr))) { - if ($aspectX == 'xMax') { - $ax = (($vw * ($wr / $hr)) - $vw); - } - if ($aspectX == 'xMid') { - $ax = ((($vw * ($wr / $hr)) - $vw) / 2); - } - $wr = $hr; - } elseif ((($fit == 'meet') AND ($hr > $wr)) OR (($fit == 'slice') AND ($hr < $wr))) { - if ($aspectY == 'YMax') { - $ay = (($vh * ($hr / $wr)) - $vh); - } - if ($aspectY == 'YMid') { - $ay = ((($vh * ($hr / $wr)) - $vh) / 2); - } - $hr = $wr; - } - $newtm = array($wr, 0, 0, $hr, (($wr * ($ax - $vx)) - $svgX), (($hr * ($ay - $vy)) - $svgY)); - $tm = TCPDF_STATIC::getTransformationMatrixProduct($tm, $newtm); - $this->SVGTransform($tm); - } - } - $this->setSVGStyles($svgstyle, $prev_svgstyle); - break; - } - case 'g': { - // group together related graphics elements - array_push($this->svgstyles, $svgstyle); - $this->StartTransform(); - $x = (isset($attribs['x'])?$attribs['x']:0); - $y = (isset($attribs['y'])?$attribs['y']:0); - $w = 1;//(isset($attribs['width'])?$attribs['width']:1); - $h = 1;//(isset($attribs['height'])?$attribs['height']:1); - $tm = TCPDF_STATIC::getTransformationMatrixProduct($tm, array($w, 0, 0, $h, $x, $y)); - $this->SVGTransform($tm); - $this->setSVGStyles($svgstyle, $prev_svgstyle); - break; - } - case 'linearGradient': { - if ($this->pdfa_mode && $this->pdfa_version < 2) { - break; - } - if (!isset($attribs['id'])) { - $attribs['id'] = 'GR_'.(count($this->svggradients) + 1); - } - $this->svggradientid = $attribs['id']; - $this->svggradients[$this->svggradientid] = array(); - $this->svggradients[$this->svggradientid]['type'] = 2; - $this->svggradients[$this->svggradientid]['stops'] = array(); - if (isset($attribs['gradientUnits'])) { - $this->svggradients[$this->svggradientid]['gradientUnits'] = $attribs['gradientUnits']; - } else { - $this->svggradients[$this->svggradientid]['gradientUnits'] = 'objectBoundingBox'; - } - //$attribs['spreadMethod'] - if (((!isset($attribs['x1'])) AND (!isset($attribs['y1'])) AND (!isset($attribs['x2'])) AND (!isset($attribs['y2']))) - OR ((isset($attribs['x1']) AND (substr($attribs['x1'], -1) == '%')) - OR (isset($attribs['y1']) AND (substr($attribs['y1'], -1) == '%')) - OR (isset($attribs['x2']) AND (substr($attribs['x2'], -1) == '%')) - OR (isset($attribs['y2']) AND (substr($attribs['y2'], -1) == '%')))) { - $this->svggradients[$this->svggradientid]['mode'] = 'percentage'; - } else { - $this->svggradients[$this->svggradientid]['mode'] = 'measure'; - } - $x1 = (isset($attribs['x1'])?$attribs['x1']:'0'); - $y1 = (isset($attribs['y1'])?$attribs['y1']:'0'); - $x2 = (isset($attribs['x2'])?$attribs['x2']:'100'); - $y2 = (isset($attribs['y2'])?$attribs['y2']:'0'); - if (isset($attribs['gradientTransform'])) { - $this->svggradients[$this->svggradientid]['gradientTransform'] = TCPDF_STATIC::getSVGTransformMatrix($attribs['gradientTransform']); - } - $this->svggradients[$this->svggradientid]['coords'] = array($x1, $y1, $x2, $y2); - if (isset($attribs['xlink:href']) AND !empty($attribs['xlink:href'])) { - // gradient is defined on another place - $this->svggradients[$this->svggradientid]['xref'] = substr($attribs['xlink:href'], 1); - } - break; - } - case 'radialGradient': { - if ($this->pdfa_mode && $this->pdfa_version < 2) { - break; - } - if (!isset($attribs['id'])) { - $attribs['id'] = 'GR_'.(count($this->svggradients) + 1); - } - $this->svggradientid = $attribs['id']; - $this->svggradients[$this->svggradientid] = array(); - $this->svggradients[$this->svggradientid]['type'] = 3; - $this->svggradients[$this->svggradientid]['stops'] = array(); - if (isset($attribs['gradientUnits'])) { - $this->svggradients[$this->svggradientid]['gradientUnits'] = $attribs['gradientUnits']; - } else { - $this->svggradients[$this->svggradientid]['gradientUnits'] = 'objectBoundingBox'; - } - //$attribs['spreadMethod'] - if (((!isset($attribs['cx'])) AND (!isset($attribs['cy']))) - OR ((isset($attribs['cx']) AND (substr($attribs['cx'], -1) == '%')) - OR (isset($attribs['cy']) AND (substr($attribs['cy'], -1) == '%')))) { - $this->svggradients[$this->svggradientid]['mode'] = 'percentage'; - } elseif (isset($attribs['r']) AND is_numeric($attribs['r']) AND ($attribs['r']) <= 1) { - $this->svggradients[$this->svggradientid]['mode'] = 'ratio'; - } else { - $this->svggradients[$this->svggradientid]['mode'] = 'measure'; - } - $cx = (isset($attribs['cx']) ? $attribs['cx'] : 0.5); - $cy = (isset($attribs['cy']) ? $attribs['cy'] : 0.5); - $fx = (isset($attribs['fx']) ? $attribs['fx'] : $cx); - $fy = (isset($attribs['fy']) ? $attribs['fy'] : $cy); - $r = (isset($attribs['r']) ? $attribs['r'] : 0.5); - if (isset($attribs['gradientTransform'])) { - $this->svggradients[$this->svggradientid]['gradientTransform'] = TCPDF_STATIC::getSVGTransformMatrix($attribs['gradientTransform']); - } - $this->svggradients[$this->svggradientid]['coords'] = array($cx, $cy, $fx, $fy, $r); - if (isset($attribs['xlink:href']) AND !empty($attribs['xlink:href'])) { - // gradient is defined on another place - $this->svggradients[$this->svggradientid]['xref'] = substr($attribs['xlink:href'], 1); - } - break; - } - case 'stop': { - // gradient stops - if (substr($attribs['offset'], -1) == '%') { - $offset = floatval(substr($attribs['offset'], 0, -1)) / 100; - } else { - $offset = floatval($attribs['offset']); - if ($offset > 1) { - $offset /= 100; - } - } - $stop_color = isset($svgstyle['stop-color'])?TCPDF_COLORS::convertHTMLColorToDec($svgstyle['stop-color'], $this->spot_colors):'black'; - $opacity = isset($svgstyle['stop-opacity'])?$svgstyle['stop-opacity']:1; - $this->svggradients[$this->svggradientid]['stops'][] = array('offset' => $offset, 'color' => $stop_color, 'opacity' => $opacity); - break; - } - // paths - case 'path': { - if ($invisible) { - break; - } - if (isset($attribs['d'])) { - $d = trim($attribs['d']); - if (!empty($d)) { - $x = (isset($attribs['x'])?$attribs['x']:0); - $y = (isset($attribs['y'])?$attribs['y']:0); - $w = (isset($attribs['width'])?$attribs['width']:1); - $h = (isset($attribs['height'])?$attribs['height']:1); - $tm = TCPDF_STATIC::getTransformationMatrixProduct($tm, array($w, 0, 0, $h, $x, $y)); - if ($clipping) { - $this->SVGTransform($tm); - $this->SVGPath($d, 'CNZ'); - } else { - $this->StartTransform(); - $this->SVGTransform($tm); - $obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, $w, $h, 'SVGPath', array($d, 'CNZ')); - if (!empty($obstyle)) { - $this->SVGPath($d, $obstyle); - } - $this->StopTransform(); - } - } - } - break; - } - // shapes - case 'rect': { - if ($invisible) { - break; - } - $x = (isset($attribs['x'])?$this->getHTMLUnitToUnits($attribs['x'], 0, $this->svgunit, false):0); - $y = (isset($attribs['y'])?$this->getHTMLUnitToUnits($attribs['y'], 0, $this->svgunit, false):0); - $w = (isset($attribs['width'])?$this->getHTMLUnitToUnits($attribs['width'], 0, $this->svgunit, false):0); - $h = (isset($attribs['height'])?$this->getHTMLUnitToUnits($attribs['height'], 0, $this->svgunit, false):0); - $rx = (isset($attribs['rx'])?$this->getHTMLUnitToUnits($attribs['rx'], 0, $this->svgunit, false):0); - $ry = (isset($attribs['ry'])?$this->getHTMLUnitToUnits($attribs['ry'], 0, $this->svgunit, false):$rx); - if ($clipping) { - $this->SVGTransform($tm); - $this->RoundedRectXY($x, $y, $w, $h, $rx, $ry, '1111', 'CNZ', array(), array()); - } else { - $this->StartTransform(); - $this->SVGTransform($tm); - $obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, $w, $h, 'RoundedRectXY', array($x, $y, $w, $h, $rx, $ry, '1111', 'CNZ')); - if (!empty($obstyle)) { - $this->RoundedRectXY($x, $y, $w, $h, $rx, $ry, '1111', $obstyle, array(), array()); - } - $this->StopTransform(); - } - break; - } - case 'circle': { - if ($invisible) { - break; - } - $r = (isset($attribs['r']) ? $this->getHTMLUnitToUnits($attribs['r'], 0, $this->svgunit, false) : 0); - $cx = (isset($attribs['cx']) ? $this->getHTMLUnitToUnits($attribs['cx'], 0, $this->svgunit, false) : (isset($attribs['x']) ? $this->getHTMLUnitToUnits($attribs['x'], 0, $this->svgunit, false) : 0)); - $cy = (isset($attribs['cy']) ? $this->getHTMLUnitToUnits($attribs['cy'], 0, $this->svgunit, false) : (isset($attribs['y']) ? $this->getHTMLUnitToUnits($attribs['y'], 0, $this->svgunit, false) : 0)); - $x = ($cx - $r); - $y = ($cy - $r); - $w = (2 * $r); - $h = $w; - if ($clipping) { - $this->SVGTransform($tm); - $this->Circle($cx, $cy, $r, 0, 360, 'CNZ', array(), array(), 8); - } else { - $this->StartTransform(); - $this->SVGTransform($tm); - $obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, $w, $h, 'Circle', array($cx, $cy, $r, 0, 360, 'CNZ')); - if (!empty($obstyle)) { - $this->Circle($cx, $cy, $r, 0, 360, $obstyle, array(), array(), 8); - } - $this->StopTransform(); - } - break; - } - case 'ellipse': { - if ($invisible) { - break; - } - $rx = (isset($attribs['rx']) ? $this->getHTMLUnitToUnits($attribs['rx'], 0, $this->svgunit, false) : 0); - $ry = (isset($attribs['ry']) ? $this->getHTMLUnitToUnits($attribs['ry'], 0, $this->svgunit, false) : 0); - $cx = (isset($attribs['cx']) ? $this->getHTMLUnitToUnits($attribs['cx'], 0, $this->svgunit, false) : (isset($attribs['x']) ? $this->getHTMLUnitToUnits($attribs['x'], 0, $this->svgunit, false) : 0)); - $cy = (isset($attribs['cy']) ? $this->getHTMLUnitToUnits($attribs['cy'], 0, $this->svgunit, false) : (isset($attribs['y']) ? $this->getHTMLUnitToUnits($attribs['y'], 0, $this->svgunit, false) : 0)); - $x = ($cx - $rx); - $y = ($cy - $ry); - $w = (2 * $rx); - $h = (2 * $ry); - if ($clipping) { - $this->SVGTransform($tm); - $this->Ellipse($cx, $cy, $rx, $ry, 0, 0, 360, 'CNZ', array(), array(), 8); - } else { - $this->StartTransform(); - $this->SVGTransform($tm); - $obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, $w, $h, 'Ellipse', array($cx, $cy, $rx, $ry, 0, 0, 360, 'CNZ')); - if (!empty($obstyle)) { - $this->Ellipse($cx, $cy, $rx, $ry, 0, 0, 360, $obstyle, array(), array(), 8); - } - $this->StopTransform(); - } - break; - } - case 'line': { - if ($invisible) { - break; - } - $x1 = (isset($attribs['x1'])?$this->getHTMLUnitToUnits($attribs['x1'], 0, $this->svgunit, false):0); - $y1 = (isset($attribs['y1'])?$this->getHTMLUnitToUnits($attribs['y1'], 0, $this->svgunit, false):0); - $x2 = (isset($attribs['x2'])?$this->getHTMLUnitToUnits($attribs['x2'], 0, $this->svgunit, false):0); - $y2 = (isset($attribs['y2'])?$this->getHTMLUnitToUnits($attribs['y2'], 0, $this->svgunit, false):0); - $x = $x1; - $y = $y1; - $w = abs($x2 - $x1); - $h = abs($y2 - $y1); - if (!$clipping) { - $this->StartTransform(); - $this->SVGTransform($tm); - $obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, $w, $h, 'Line', array($x1, $y1, $x2, $y2)); - $this->Line($x1, $y1, $x2, $y2); - $this->StopTransform(); - } - break; - } - case 'polyline': - case 'polygon': { - if ($invisible) { - break; - } - $points = (isset($attribs['points'])?$attribs['points']:'0 0'); - $points = trim($points); - // note that point may use a complex syntax not covered here - $points = preg_split('/[\,\s]+/si', $points); - if (count($points) < 4) { - break; - } - $p = array(); - $xmin = 2147483647; - $xmax = 0; - $ymin = 2147483647; - $ymax = 0; - foreach ($points as $key => $val) { - $p[$key] = $this->getHTMLUnitToUnits($val, 0, $this->svgunit, false); - if (($key % 2) == 0) { - // X coordinate - $xmin = min($xmin, $p[$key]); - $xmax = max($xmax, $p[$key]); - } else { - // Y coordinate - $ymin = min($ymin, $p[$key]); - $ymax = max($ymax, $p[$key]); - } - } - $x = $xmin; - $y = $ymin; - $w = ($xmax - $xmin); - $h = ($ymax - $ymin); - if ($name == 'polyline') { - $this->StartTransform(); - $this->SVGTransform($tm); - $obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, $w, $h, 'PolyLine', array($p, 'CNZ')); - if (!empty($obstyle)) { - $this->PolyLine($p, $obstyle, array(), array()); - } - $this->StopTransform(); - } else { // polygon - if ($clipping) { - $this->SVGTransform($tm); - $this->Polygon($p, 'CNZ', array(), array(), true); - } else { - $this->StartTransform(); - $this->SVGTransform($tm); - $obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, $w, $h, 'Polygon', array($p, 'CNZ')); - if (!empty($obstyle)) { - $this->Polygon($p, $obstyle, array(), array(), true); - } - $this->StopTransform(); - } - } - break; - } - // image - case 'image': { - if ($invisible) { - break; - } - if (!isset($attribs['xlink:href']) OR empty($attribs['xlink:href'])) { - break; - } - $x = (isset($attribs['x'])?$this->getHTMLUnitToUnits($attribs['x'], 0, $this->svgunit, false):0); - $y = (isset($attribs['y'])?$this->getHTMLUnitToUnits($attribs['y'], 0, $this->svgunit, false):0); - $w = (isset($attribs['width'])?$this->getHTMLUnitToUnits($attribs['width'], 0, $this->svgunit, false):0); - $h = (isset($attribs['height'])?$this->getHTMLUnitToUnits($attribs['height'], 0, $this->svgunit, false):0); - $img = $attribs['xlink:href']; - if (!$clipping) { - $this->StartTransform(); - $this->SVGTransform($tm); - $obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, $w, $h); - if (preg_match('/^data:image\/[^;]+;base64,/', $img, $m) > 0) { - // embedded image encoded as base64 - $img = '@'.base64_decode(substr($img, strlen($m[0]))); - } else { - // fix image path - if (!TCPDF_STATIC::empty_string($this->svgdir) AND (($img[0] == '.') OR (basename($img) == $img))) { - // replace relative path with full server path - $img = $this->svgdir.'/'.$img; - } - if (($img[0] == '/') AND !empty($_SERVER['DOCUMENT_ROOT']) AND ($_SERVER['DOCUMENT_ROOT'] != '/')) { - $findroot = strpos($img, $_SERVER['DOCUMENT_ROOT']); - if (($findroot === false) OR ($findroot > 1)) { - if (substr($_SERVER['DOCUMENT_ROOT'], -1) == '/') { - $img = substr($_SERVER['DOCUMENT_ROOT'], 0, -1).$img; - } else { - $img = $_SERVER['DOCUMENT_ROOT'].$img; - } - } - } - $img = urldecode($img); - $testscrtype = @parse_url($img); - if (empty($testscrtype['query'])) { - // convert URL to server path - $img = str_replace(K_PATH_URL, K_PATH_MAIN, $img); - } elseif (preg_match('|^https?://|', $img) !== 1) { - // convert server path to URL - $img = str_replace(K_PATH_MAIN, K_PATH_URL, $img); - } - } - // get image type - $imgtype = TCPDF_IMAGES::getImageFileType($img); - if (($imgtype == 'eps') OR ($imgtype == 'ai')) { - $this->ImageEps($img, $x, $y, $w, $h); - } elseif ($imgtype == 'svg') { - // store SVG vars - $svggradients = $this->svggradients; - $svggradientid = $this->svggradientid; - $svgdefsmode = $this->svgdefsmode; - $svgdefs = $this->svgdefs; - $svgclipmode = $this->svgclipmode; - $svgclippaths = $this->svgclippaths; - $svgcliptm = $this->svgcliptm; - $svgclipid = $this->svgclipid; - $svgtext = $this->svgtext; - $svgtextmode = $this->svgtextmode; - $this->ImageSVG($img, $x, $y, $w, $h); - // restore SVG vars - $this->svggradients = $svggradients; - $this->svggradientid = $svggradientid; - $this->svgdefsmode = $svgdefsmode; - $this->svgdefs = $svgdefs; - $this->svgclipmode = $svgclipmode; - $this->svgclippaths = $svgclippaths; - $this->svgcliptm = $svgcliptm; - $this->svgclipid = $svgclipid; - $this->svgtext = $svgtext; - $this->svgtextmode = $svgtextmode; - } else { - $this->Image($img, $x, $y, $w, $h); - } - $this->StopTransform(); - } - break; - } - // text - case 'text': - case 'tspan': { - if (isset($this->svgtextmode['text-anchor']) AND !empty($this->svgtext)) { - // @TODO: unsupported feature - } - // only basic support - advanced features must be implemented - $this->svgtextmode['invisible'] = $invisible; - if ($invisible) { - break; - } - array_push($this->svgstyles, $svgstyle); - if (isset($attribs['x'])) { - $x = $this->getHTMLUnitToUnits($attribs['x'], 0, $this->svgunit, false); - } elseif ($name == 'tspan') { - $x = $this->x; - } else { - $x = 0; - } - if (isset($attribs['dx'])) { - $x += $this->getHTMLUnitToUnits($attribs['dx'], 0, $this->svgunit, false); - } - if (isset($attribs['y'])) { - $y = $this->getHTMLUnitToUnits($attribs['y'], 0, $this->svgunit, false); - } elseif ($name == 'tspan') { - $y = $this->y; - } else { - $y = 0; - } - if (isset($attribs['dy'])) { - $y += $this->getHTMLUnitToUnits($attribs['dy'], 0, $this->svgunit, false); - } - $svgstyle['text-color'] = $svgstyle['fill']; - $this->svgtext = ''; - if (isset($svgstyle['text-anchor'])) { - $this->svgtextmode['text-anchor'] = $svgstyle['text-anchor']; - } else { - $this->svgtextmode['text-anchor'] = 'start'; - } - if (isset($svgstyle['direction'])) { - if ($svgstyle['direction'] == 'rtl') { - $this->svgtextmode['rtl'] = true; - } else { - $this->svgtextmode['rtl'] = false; - } - } else { - $this->svgtextmode['rtl'] = false; - } - if (isset($svgstyle['stroke']) AND ($svgstyle['stroke'] != 'none') AND isset($svgstyle['stroke-width']) AND ($svgstyle['stroke-width'] > 0)) { - $this->svgtextmode['stroke'] = $this->getHTMLUnitToUnits($svgstyle['stroke-width'], 0, $this->svgunit, false); - } else { - $this->svgtextmode['stroke'] = false; - } - $this->StartTransform(); - $this->SVGTransform($tm); - $obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, 1, 1); - $this->x = $x; - $this->y = $y; - break; - } - // use - case 'use': { - if (isset($attribs['xlink:href']) AND !empty($attribs['xlink:href'])) { - $svgdefid = substr($attribs['xlink:href'], 1); - if (isset($this->svgdefs[$svgdefid])) { - $use = $this->svgdefs[$svgdefid]; - if (isset($attribs['xlink:href'])) { - unset($attribs['xlink:href']); - } - if (isset($attribs['id'])) { - unset($attribs['id']); - } - if (isset($use['attribs']['x']) AND isset($attribs['x'])) { - $attribs['x'] += $use['attribs']['x']; - } - if (isset($use['attribs']['y']) AND isset($attribs['y'])) { - $attribs['y'] += $use['attribs']['y']; - } - if (empty($attribs['style'])) { - $attribs['style'] = ''; - } - if (!empty($use['attribs']['style'])) { - // merge styles - $attribs['style'] = str_replace(';;',';',';'.$use['attribs']['style'].$attribs['style']); - } - $attribs = array_merge($use['attribs'], $attribs); - $this->startSVGElementHandler($parser, $use['name'], $attribs); - return; - } - } - break; - } - default: { - break; - } - } // end of switch - // process child elements - if (!empty($attribs['child_elements'])) { - $child_elements = $attribs['child_elements']; - unset($attribs['child_elements']); - foreach($child_elements as $child_element) { - if (empty($child_element['attribs']['closing_tag'])) { - $this->startSVGElementHandler('child-tag', $child_element['name'], $child_element['attribs']); - } else { - if (isset($child_element['attribs']['content'])) { - $this->svgtext = $child_element['attribs']['content']; - } - $this->endSVGElementHandler('child-tag', $child_element['name']); - } - } - } - } - - /** - * Sets the closing SVG element handler function for the XML parser. - * @param resource|string $parser The first parameter, parser, is a reference to the XML parser calling the handler. - * @param string $name The second parameter, name, contains the name of the element for which this handler is called. If case-folding is in effect for this parser, the element name will be in uppercase letters. - * @author Nicola Asuni - * @since 5.0.000 (2010-05-02) - * @protected - */ - protected function endSVGElementHandler($parser, $name) { - $name = $this->removeTagNamespace($name); - if ($this->svgdefsmode AND !in_array($name, array('defs', 'clipPath', 'linearGradient', 'radialGradient', 'stop'))) {; - if (end($this->svgdefs) !== FALSE) { - $last_svgdefs_id = key($this->svgdefs); - if (isset($this->svgdefs[$last_svgdefs_id]['attribs']['child_elements'])) { - foreach($this->svgdefs[$last_svgdefs_id]['attribs']['child_elements'] as $child_element) { - if (isset($child_element['attribs']['id']) AND ($child_element['name'] == $name)) { - $this->svgdefs[$last_svgdefs_id]['attribs']['child_elements'][$child_element['attribs']['id'].'_CLOSE'] = array('name' => $name, 'attribs' => array('closing_tag' => TRUE, 'content' => $this->svgtext)); - return; - } - } - if ($this->svgdefs[$last_svgdefs_id]['name'] == $name) { - $this->svgdefs[$last_svgdefs_id]['attribs']['child_elements'][$last_svgdefs_id.'_CLOSE'] = array('name' => $name, 'attribs' => array('closing_tag' => TRUE, 'content' => $this->svgtext)); - return; - } - } - } - return; - } - switch($name) { - case 'defs': { - $this->svgdefsmode = false; - break; - } - // clipPath - case 'clipPath': { - $this->svgclipmode = false; - break; - } - case 'svg': { - if (--$this->svg_tag_depth <= 0) { - break; - } - } - case 'g': { - // ungroup: remove last style from array - array_pop($this->svgstyles); - $this->StopTransform(); - break; - } - case 'text': - case 'tspan': { - if ($this->svgtextmode['invisible']) { - // This implementation must be fixed to following the rule: - // If the 'visibility' property is set to hidden on a 'tspan', 'tref' or 'altGlyph' element, then the text is invisible but still takes up space in text layout calculations. - break; - } - // print text - $text = $this->svgtext; - //$text = $this->stringTrim($text); - $textlen = $this->GetStringWidth($text); - if ($this->svgtextmode['text-anchor'] != 'start') { - // check if string is RTL text - if ($this->svgtextmode['text-anchor'] == 'end') { - if ($this->svgtextmode['rtl']) { - $this->x += $textlen; - } else { - $this->x -= $textlen; - } - } elseif ($this->svgtextmode['text-anchor'] == 'middle') { - if ($this->svgtextmode['rtl']) { - $this->x += ($textlen / 2); - } else { - $this->x -= ($textlen / 2); - } - } - } - $textrendermode = $this->textrendermode; - $textstrokewidth = $this->textstrokewidth; - $this->setTextRenderingMode($this->svgtextmode['stroke'], true, false); - if ($name == 'text') { - // store current coordinates - $tmpx = $this->x; - $tmpy = $this->y; - } - // print the text - $this->Cell($textlen, 0, $text, 0, 0, '', false, '', 0, false, 'L', 'T'); - if ($name == 'text') { - // restore coordinates - $this->x = $tmpx; - $this->y = $tmpy; - } - // restore previous rendering mode - $this->textrendermode = $textrendermode; - $this->textstrokewidth = $textstrokewidth; - $this->svgtext = ''; - $this->StopTransform(); - if (!$this->svgdefsmode) { - array_pop($this->svgstyles); - } - break; - } - default: { - break; - } - } - } - - /** - * Sets the character data handler function for the XML parser. - * @param resource $parser The first parameter, parser, is a reference to the XML parser calling the handler. - * @param string $data The second parameter, data, contains the character data as a string. - * @author Nicola Asuni - * @since 5.0.000 (2010-05-02) - * @protected - */ - protected function segSVGContentHandler($parser, $data) { - $this->svgtext .= $data; - } - - // --- END SVG METHODS ----------------------------------------------------- - - /** - * Keeps files in memory, so it doesn't need to downloaded everytime in a loop - * @param string $file - * @return string - */ - protected function getCachedFileContents($file) - { - if (!isset($this->fileContentCache[$file])) { - $this->fileContentCache[$file] = TCPDF_STATIC::fileGetContents($file); - } - return $this->fileContentCache[$file]; - } - - /** - * Avoid multiple calls to an external server to see if a file exists - * @param string $file - * @return bool - */ - protected function fileExists($file) - { - if (isset($this->fileContentCache[$file]) || false !== $this->getImageBuffer($file)) { - return true; - } - - return TCPDF_STATIC::file_exists($file); - } - -} // END OF TCPDF CLASS - -//============================================================+ -// END OF FILE -//============================================================+ diff --git a/lib/combodo/tcpdf/tcpdf_autoconfig.php b/lib/combodo/tcpdf/tcpdf_autoconfig.php deleted file mode 100644 index 6ec9ce83b..000000000 --- a/lib/combodo/tcpdf/tcpdf_autoconfig.php +++ /dev/null @@ -1,241 +0,0 @@ -<?php -//============================================================+ -// File name : tcpdf_autoconfig.php -// Version : 1.1.1 -// Begin : 2013-05-16 -// Last Update : 2014-12-18 -// Authors : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com -// License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html) -// ------------------------------------------------------------------- -// Copyright (C) 2011-2014 Nicola Asuni - Tecnick.com LTD -// -// This file is part of TCPDF software library. -// -// TCPDF is free software: you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// TCPDF is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// -// You should have received a copy of the License -// along with TCPDF. If not, see -// <http://www.tecnick.com/pagefiles/tcpdf/LICENSE.TXT>. -// -// See LICENSE.TXT file for more information. -// ------------------------------------------------------------------- -// -// Description : Try to automatically configure some TCPDF -// constants if not defined. -// -//============================================================+ - -/** - * @file - * Try to automatically configure some TCPDF constants if not defined. - * @package com.tecnick.tcpdf - * @version 1.1.1 - */ - -// DOCUMENT_ROOT fix for IIS Webserver -if ((!isset($_SERVER['DOCUMENT_ROOT'])) OR (empty($_SERVER['DOCUMENT_ROOT']))) { - if(isset($_SERVER['SCRIPT_FILENAME'])) { - $_SERVER['DOCUMENT_ROOT'] = str_replace( '\\', '/', substr($_SERVER['SCRIPT_FILENAME'], 0, 0-strlen($_SERVER['PHP_SELF']))); - } elseif(isset($_SERVER['PATH_TRANSLATED'])) { - $_SERVER['DOCUMENT_ROOT'] = str_replace( '\\', '/', substr(str_replace('\\\\', '\\', $_SERVER['PATH_TRANSLATED']), 0, 0-strlen($_SERVER['PHP_SELF']))); - } else { - // define here your DOCUMENT_ROOT path if the previous fails (e.g. '/var/www') - $_SERVER['DOCUMENT_ROOT'] = '/'; - } -} -$_SERVER['DOCUMENT_ROOT'] = str_replace('//', '/', $_SERVER['DOCUMENT_ROOT']); -if (substr($_SERVER['DOCUMENT_ROOT'], -1) != '/') { - $_SERVER['DOCUMENT_ROOT'] .= '/'; -} - -// Load main configuration file only if the K_TCPDF_EXTERNAL_CONFIG constant is set to false. -if (!defined('K_TCPDF_EXTERNAL_CONFIG') OR !K_TCPDF_EXTERNAL_CONFIG) { - // define a list of default config files in order of priority - $tcpdf_config_files = array(dirname(__FILE__).'/config/tcpdf_config.php', '/etc/php-tcpdf/tcpdf_config.php', '/etc/tcpdf/tcpdf_config.php', '/etc/tcpdf_config.php'); - foreach ($tcpdf_config_files as $tcpdf_config) { - if (@file_exists($tcpdf_config) AND is_readable($tcpdf_config)) { - require_once($tcpdf_config); - break; - } - } -} - -if (!defined('K_PATH_MAIN')) { - define ('K_PATH_MAIN', dirname(__FILE__).'/'); -} - -if (!defined('K_PATH_FONTS')) { - define ('K_PATH_FONTS', K_PATH_MAIN.'fonts/'); -} - -if (!defined('K_PATH_URL')) { - $k_path_url = K_PATH_MAIN; // default value for console mode - if (isset($_SERVER['HTTP_HOST']) AND (!empty($_SERVER['HTTP_HOST']))) { - if(isset($_SERVER['HTTPS']) AND (!empty($_SERVER['HTTPS'])) AND (strtolower($_SERVER['HTTPS']) != 'off')) { - $k_path_url = 'https://'; - } else { - $k_path_url = 'http://'; - } - $k_path_url .= $_SERVER['HTTP_HOST']; - $k_path_url .= str_replace( '\\', '/', substr(K_PATH_MAIN, (strlen($_SERVER['DOCUMENT_ROOT']) - 1))); - } - define ('K_PATH_URL', $k_path_url); -} - -if (!defined('K_PATH_IMAGES')) { - $tcpdf_images_dirs = array(K_PATH_MAIN.'examples/images/', K_PATH_MAIN.'images/', '/usr/share/doc/php-tcpdf/examples/images/', '/usr/share/doc/tcpdf/examples/images/', '/usr/share/doc/php/tcpdf/examples/images/', '/var/www/tcpdf/images/', '/var/www/html/tcpdf/images/', '/usr/local/apache2/htdocs/tcpdf/images/', K_PATH_MAIN); - foreach ($tcpdf_images_dirs as $tcpdf_images_path) { - if (@file_exists($tcpdf_images_path)) { - define ('K_PATH_IMAGES', $tcpdf_images_path); - break; - } - } -} - -if (!defined('PDF_HEADER_LOGO')) { - $tcpdf_header_logo = ''; - if (@file_exists(K_PATH_IMAGES.'tcpdf_logo.jpg')) { - $tcpdf_header_logo = 'tcpdf_logo.jpg'; - } - define ('PDF_HEADER_LOGO', $tcpdf_header_logo); -} - -if (!defined('PDF_HEADER_LOGO_WIDTH')) { - if (!empty($tcpdf_header_logo)) { - define ('PDF_HEADER_LOGO_WIDTH', 30); - } else { - define ('PDF_HEADER_LOGO_WIDTH', 0); - } -} - -if (!defined('K_PATH_CACHE')) { - $K_PATH_CACHE = ini_get('upload_tmp_dir') ? ini_get('upload_tmp_dir') : sys_get_temp_dir(); - if (substr($K_PATH_CACHE, -1) != '/') { - $K_PATH_CACHE .= '/'; - } - define ('K_PATH_CACHE', $K_PATH_CACHE); -} - -if (!defined('K_BLANK_IMAGE')) { - define ('K_BLANK_IMAGE', '_blank.png'); -} - -if (!defined('PDF_PAGE_FORMAT')) { - define ('PDF_PAGE_FORMAT', 'A4'); -} - -if (!defined('PDF_PAGE_ORIENTATION')) { - define ('PDF_PAGE_ORIENTATION', 'P'); -} - -if (!defined('PDF_CREATOR')) { - define ('PDF_CREATOR', 'TCPDF'); -} - -if (!defined('PDF_AUTHOR')) { - define ('PDF_AUTHOR', 'TCPDF'); -} - -if (!defined('PDF_HEADER_TITLE')) { - define ('PDF_HEADER_TITLE', 'TCPDF Example'); -} - -if (!defined('PDF_HEADER_STRING')) { - define ('PDF_HEADER_STRING', "by Nicola Asuni - Tecnick.com\nwww.tcpdf.org"); -} - -if (!defined('PDF_UNIT')) { - define ('PDF_UNIT', 'mm'); -} - -if (!defined('PDF_MARGIN_HEADER')) { - define ('PDF_MARGIN_HEADER', 5); -} - -if (!defined('PDF_MARGIN_FOOTER')) { - define ('PDF_MARGIN_FOOTER', 10); -} - -if (!defined('PDF_MARGIN_TOP')) { - define ('PDF_MARGIN_TOP', 27); -} - -if (!defined('PDF_MARGIN_BOTTOM')) { - define ('PDF_MARGIN_BOTTOM', 25); -} - -if (!defined('PDF_MARGIN_LEFT')) { - define ('PDF_MARGIN_LEFT', 15); -} - -if (!defined('PDF_MARGIN_RIGHT')) { - define ('PDF_MARGIN_RIGHT', 15); -} - -if (!defined('PDF_FONT_NAME_MAIN')) { - define ('PDF_FONT_NAME_MAIN', 'helvetica'); -} - -if (!defined('PDF_FONT_SIZE_MAIN')) { - define ('PDF_FONT_SIZE_MAIN', 10); -} - -if (!defined('PDF_FONT_NAME_DATA')) { - define ('PDF_FONT_NAME_DATA', 'helvetica'); -} - -if (!defined('PDF_FONT_SIZE_DATA')) { - define ('PDF_FONT_SIZE_DATA', 8); -} - -if (!defined('PDF_FONT_MONOSPACED')) { - define ('PDF_FONT_MONOSPACED', 'courier'); -} - -if (!defined('PDF_IMAGE_SCALE_RATIO')) { - define ('PDF_IMAGE_SCALE_RATIO', 1.25); -} - -if (!defined('HEAD_MAGNIFICATION')) { - define('HEAD_MAGNIFICATION', 1.1); -} - -if (!defined('K_CELL_HEIGHT_RATIO')) { - define('K_CELL_HEIGHT_RATIO', 1.25); -} - -if (!defined('K_TITLE_MAGNIFICATION')) { - define('K_TITLE_MAGNIFICATION', 1.3); -} - -if (!defined('K_SMALL_RATIO')) { - define('K_SMALL_RATIO', 2/3); -} - -if (!defined('K_THAI_TOPCHARS')) { - define('K_THAI_TOPCHARS', true); -} - -if (!defined('K_TCPDF_CALLS_IN_HTML')) { - define('K_TCPDF_CALLS_IN_HTML', false); -} - -if (!defined('K_TCPDF_THROW_EXCEPTION_ERROR')) { - define('K_TCPDF_THROW_EXCEPTION_ERROR', false); -} - -if (!defined('K_TIMEZONE')) { - define('K_TIMEZONE', @date_default_timezone_get()); -} - -//============================================================+ -// END OF FILE -//============================================================+ diff --git a/lib/combodo/tcpdf/tcpdf_barcodes_1d.php b/lib/combodo/tcpdf/tcpdf_barcodes_1d.php deleted file mode 100644 index 10a79a72e..000000000 --- a/lib/combodo/tcpdf/tcpdf_barcodes_1d.php +++ /dev/null @@ -1,2356 +0,0 @@ -<?php -//============================================================+ -// File name : tcpdf_barcodes_1d.php -// Version : 1.0.027 -// Begin : 2008-06-09 -// Last Update : 2014-10-20 -// Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com -// License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html) -// ------------------------------------------------------------------- -// Copyright (C) 2008-2014 Nicola Asuni - Tecnick.com LTD -// -// This file is part of TCPDF software library. -// -// TCPDF is free software: you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// TCPDF is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with TCPDF. If not, see <http://www.gnu.org/licenses/>. -// -// See LICENSE.TXT file for more information. -// ------------------------------------------------------------------- -// -// Description : PHP class to creates array representations for -// common 1D barcodes to be used with TCPDF. -// -//============================================================+ - -/** - * @file - * PHP class to creates array representations for common 1D barcodes to be used with TCPDF. - * @package com.tecnick.tcpdf - * @author Nicola Asuni - * @version 1.0.027 - */ - -/** - * @class TCPDFBarcode - * PHP class to creates array representations for common 1D barcodes to be used with TCPDF (http://www.tcpdf.org).<br> - * @package com.tecnick.tcpdf - * @version 1.0.027 - * @author Nicola Asuni - */ -class TCPDFBarcode { - - /** - * Array representation of barcode. - * @protected - */ - protected $barcode_array = array(); - - /** - * This is the class constructor. - * Return an array representations for common 1D barcodes:<ul> - * <li>$arrcode['code'] code to be printed on text label</li> - * <li>$arrcode['maxh'] max barcode height</li> - * <li>$arrcode['maxw'] max barcode width</li> - * <li>$arrcode['bcode'][$k] single bar or space in $k position</li> - * <li>$arrcode['bcode'][$k]['t'] bar type: true = bar, false = space.</li> - * <li>$arrcode['bcode'][$k]['w'] bar width in units.</li> - * <li>$arrcode['bcode'][$k]['h'] bar height in units.</li> - * <li>$arrcode['bcode'][$k]['p'] bar top position (0 = top, 1 = middle)</li></ul> - * @param string $code code to print - * @param string $type type of barcode: <ul><li>C39 : CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.</li><li>C39+ : CODE 39 with checksum</li><li>C39E : CODE 39 EXTENDED</li><li>C39E+ : CODE 39 EXTENDED + CHECKSUM</li><li>C93 : CODE 93 - USS-93</li><li>S25 : Standard 2 of 5</li><li>S25+ : Standard 2 of 5 + CHECKSUM</li><li>I25 : Interleaved 2 of 5</li><li>I25+ : Interleaved 2 of 5 + CHECKSUM</li><li>C128 : CODE 128</li><li>C128A : CODE 128 A</li><li>C128B : CODE 128 B</li><li>C128C : CODE 128 C</li><li>EAN2 : 2-Digits UPC-Based Extension</li><li>EAN5 : 5-Digits UPC-Based Extension</li><li>EAN8 : EAN 8</li><li>EAN13 : EAN 13</li><li>UPCA : UPC-A</li><li>UPCE : UPC-E</li><li>MSI : MSI (Variation of Plessey code)</li><li>MSI+ : MSI + CHECKSUM (modulo 11)</li><li>POSTNET : POSTNET</li><li>PLANET : PLANET</li><li>RMS4CC : RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code)</li><li>KIX : KIX (Klant index - Customer index)</li><li>IMB: Intelligent Mail Barcode - Onecode - USPS-B-3200</li><li>CODABAR : CODABAR</li><li>CODE11 : CODE 11</li><li>PHARMA : PHARMACODE</li><li>PHARMA2T : PHARMACODE TWO-TRACKS</li></ul> - * @public - */ - public function __construct($code, $type) { - $this->setBarcode($code, $type); - } - - /** - * Return an array representations of barcode. - * @return array - * @public - */ - public function getBarcodeArray() { - return $this->barcode_array; - } - - /** - * Send barcode as SVG image object to the standard output. - * @param int $w Minimum width of a single bar in user units. - * @param int $h Height of barcode in user units. - * @param string $color Foreground color (in SVG format) for bar elements (background is transparent). - * @public - */ - public function getBarcodeSVG($w=2, $h=30, $color='black') { - // send headers - $code = $this->getBarcodeSVGcode($w, $h, $color); - header('Content-Type: application/svg+xml'); - header('Cache-Control: public, must-revalidate, max-age=0'); // HTTP/1.1 - header('Pragma: public'); - header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past - header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); - header('Content-Disposition: inline; filename="'.md5($code).'.svg";'); - //header('Content-Length: '.strlen($code)); - echo $code; - } - - /** - * Return a SVG string representation of barcode. - * @param int $w Minimum width of a single bar in user units. - * @param int $h Height of barcode in user units. - * @param string $color Foreground color (in SVG format) for bar elements (background is transparent). - * @return string SVG code. - * @public - */ - public function getBarcodeSVGcode($w=2, $h=30, $color='black') { - // replace table for special characters - $repstr = array("\0" => '', '&' => '&amp;', '<' => '&lt;', '>' => '&gt;'); - $svg = '<'.'?'.'xml version="1.0" standalone="no"'.'?'.'>'."\n"; - $svg .= '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'."\n"; - $svg .= '<svg width="'.round(($this->barcode_array['maxw'] * $w), 3).'" height="'.$h.'" version="1.1" xmlns="http://www.w3.org/2000/svg">'."\n"; - $svg .= "\t".'<desc>'.strtr($this->barcode_array['code'], $repstr).'</desc>'."\n"; - $svg .= "\t".'<g id="bars" fill="'.$color.'" stroke="none">'."\n"; - // print bars - $x = 0; - foreach ($this->barcode_array['bcode'] as $k => $v) { - $bw = round(($v['w'] * $w), 3); - $bh = round(($v['h'] * $h / $this->barcode_array['maxh']), 3); - if ($v['t']) { - $y = round(($v['p'] * $h / $this->barcode_array['maxh']), 3); - // draw a vertical bar - $svg .= "\t\t".'<rect x="'.$x.'" y="'.$y.'" width="'.$bw.'" height="'.$bh.'" />'."\n"; - } - $x += $bw; - } - $svg .= "\t".'</g>'."\n"; - $svg .= '</svg>'."\n"; - return $svg; - } - - /** - * Return an HTML representation of barcode. - * @param int $w Width of a single bar element in pixels. - * @param int $h Height of a single bar element in pixels. - * @param string $color Foreground color for bar elements (background is transparent). - * @return string HTML code. - * @public - */ - public function getBarcodeHTML($w=2, $h=30, $color='black') { - $html = '<div style="font-size:0;position:relative;width:'.($this->barcode_array['maxw'] * $w).'px;height:'.($h).'px;">'."\n"; - // print bars - $x = 0; - foreach ($this->barcode_array['bcode'] as $k => $v) { - $bw = round(($v['w'] * $w), 3); - $bh = round(($v['h'] * $h / $this->barcode_array['maxh']), 3); - if ($v['t']) { - $y = round(($v['p'] * $h / $this->barcode_array['maxh']), 3); - // draw a vertical bar - $html .= '<div style="background-color:'.$color.';width:'.$bw.'px;height:'.$bh.'px;position:absolute;left:'.$x.'px;top:'.$y.'px;">&nbsp;</div>'."\n"; - } - $x += $bw; - } - $html .= '</div>'."\n"; - return $html; - } - - /** - * Send a PNG image representation of barcode (requires GD or Imagick library). - * @param int $w Width of a single bar element in pixels. - * @param int $h Height of a single bar element in pixels. - * @param array $color RGB (0-255) foreground color for bar elements (background is transparent). - * @public - */ - public function getBarcodePNG($w=2, $h=30, $color=array(0,0,0)) { - $data = $this->getBarcodePngData($w, $h, $color); - // send headers - header('Content-Type: image/png'); - header('Cache-Control: public, must-revalidate, max-age=0'); // HTTP/1.1 - header('Pragma: public'); - header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past - header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); - //header('Content-Length: '.strlen($data)); - echo $data; - } - - /** - * Return a PNG image representation of barcode (requires GD or Imagick library). - * @param int $w Width of a single bar element in pixels. - * @param int $h Height of a single bar element in pixels. - * @param array $color RGB (0-255) foreground color for bar elements (background is transparent). - * @return string|Imagick|false image or false in case of error. - * @public - */ - public function getBarcodePngData($w=2, $h=30, $color=array(0,0,0)) { - // calculate image size - $width = ($this->barcode_array['maxw'] * $w); - $height = $h; - if (function_exists('imagecreate')) { - // GD library - $imagick = false; - $png = imagecreate($width, $height); - $bgcol = imagecolorallocate($png, 255, 255, 255); - imagecolortransparent($png, $bgcol); - $fgcol = imagecolorallocate($png, $color[0], $color[1], $color[2]); - } elseif (extension_loaded('imagick')) { - $imagick = true; - $bgcol = new imagickpixel('rgb(255,255,255'); - $fgcol = new imagickpixel('rgb('.$color[0].','.$color[1].','.$color[2].')'); - $png = new Imagick(); - $png->newImage($width, $height, 'none', 'png'); - $bar = new imagickdraw(); - $bar->setfillcolor($fgcol); - } else { - return false; - } - // print bars - $x = 0; - foreach ($this->barcode_array['bcode'] as $k => $v) { - $bw = round(($v['w'] * $w), 3); - $bh = round(($v['h'] * $h / $this->barcode_array['maxh']), 3); - if ($v['t']) { - $y = round(($v['p'] * $h / $this->barcode_array['maxh']), 3); - // draw a vertical bar - if ($imagick) { - $bar->rectangle($x, $y, ($x + $bw - 1), ($y + $bh - 1)); - } else { - imagefilledrectangle($png, $x, $y, ($x + $bw - 1), ($y + $bh - 1), $fgcol); - } - } - $x += $bw; - } - if ($imagick) { - $png->drawimage($bar); - return $png; - } else { - ob_start(); - imagepng($png); - $imagedata = ob_get_clean(); - imagedestroy($png); - return $imagedata; - } - } - - /** - * Set the barcode. - * @param string $code code to print - * @param string $type type of barcode: <ul><li>C39 : CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.</li><li>C39+ : CODE 39 with checksum</li><li>C39E : CODE 39 EXTENDED</li><li>C39E+ : CODE 39 EXTENDED + CHECKSUM</li><li>C93 : CODE 93 - USS-93</li><li>S25 : Standard 2 of 5</li><li>S25+ : Standard 2 of 5 + CHECKSUM</li><li>I25 : Interleaved 2 of 5</li><li>I25+ : Interleaved 2 of 5 + CHECKSUM</li><li>C128 : CODE 128</li><li>C128A : CODE 128 A</li><li>C128B : CODE 128 B</li><li>C128C : CODE 128 C</li><li>EAN2 : 2-Digits UPC-Based Extension</li><li>EAN5 : 5-Digits UPC-Based Extension</li><li>EAN8 : EAN 8</li><li>EAN13 : EAN 13</li><li>UPCA : UPC-A</li><li>UPCE : UPC-E</li><li>MSI : MSI (Variation of Plessey code)</li><li>MSI+ : MSI + CHECKSUM (modulo 11)</li><li>POSTNET : POSTNET</li><li>PLANET : PLANET</li><li>RMS4CC : RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code)</li><li>KIX : KIX (Klant index - Customer index)</li><li>IMB: Intelligent Mail Barcode - Onecode - USPS-B-3200</li><li>IMBPRE: Pre-processed Intelligent Mail Barcode - Onecode - USPS-B-3200, using only F,A,D,T letters</li><li>CODABAR : CODABAR</li><li>CODE11 : CODE 11</li><li>PHARMA : PHARMACODE</li><li>PHARMA2T : PHARMACODE TWO-TRACKS</li></ul> - * @return void - * @public - */ - public function setBarcode($code, $type) { - switch (strtoupper($type)) { - case 'C39': { // CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9. - $arrcode = $this->barcode_code39($code, false, false); - break; - } - case 'C39+': { // CODE 39 with checksum - $arrcode = $this->barcode_code39($code, false, true); - break; - } - case 'C39E': { // CODE 39 EXTENDED - $arrcode = $this->barcode_code39($code, true, false); - break; - } - case 'C39E+': { // CODE 39 EXTENDED + CHECKSUM - $arrcode = $this->barcode_code39($code, true, true); - break; - } - case 'C93': { // CODE 93 - USS-93 - $arrcode = $this->barcode_code93($code); - break; - } - case 'S25': { // Standard 2 of 5 - $arrcode = $this->barcode_s25($code, false); - break; - } - case 'S25+': { // Standard 2 of 5 + CHECKSUM - $arrcode = $this->barcode_s25($code, true); - break; - } - case 'I25': { // Interleaved 2 of 5 - $arrcode = $this->barcode_i25($code, false); - break; - } - case 'I25+': { // Interleaved 2 of 5 + CHECKSUM - $arrcode = $this->barcode_i25($code, true); - break; - } - case 'C128': { // CODE 128 - $arrcode = $this->barcode_c128($code, ''); - break; - } - case 'C128A': { // CODE 128 A - $arrcode = $this->barcode_c128($code, 'A'); - break; - } - case 'C128B': { // CODE 128 B - $arrcode = $this->barcode_c128($code, 'B'); - break; - } - case 'C128C': { // CODE 128 C - $arrcode = $this->barcode_c128($code, 'C'); - break; - } - case 'EAN2': { // 2-Digits UPC-Based Extension - $arrcode = $this->barcode_eanext($code, 2); - break; - } - case 'EAN5': { // 5-Digits UPC-Based Extension - $arrcode = $this->barcode_eanext($code, 5); - break; - } - case 'EAN8': { // EAN 8 - $arrcode = $this->barcode_eanupc($code, 8); - break; - } - case 'EAN13': { // EAN 13 - $arrcode = $this->barcode_eanupc($code, 13); - break; - } - case 'UPCA': { // UPC-A - $arrcode = $this->barcode_eanupc($code, 12); - break; - } - case 'UPCE': { // UPC-E - $arrcode = $this->barcode_eanupc($code, 6); - break; - } - case 'MSI': { // MSI (Variation of Plessey code) - $arrcode = $this->barcode_msi($code, false); - break; - } - case 'MSI+': { // MSI + CHECKSUM (modulo 11) - $arrcode = $this->barcode_msi($code, true); - break; - } - case 'POSTNET': { // POSTNET - $arrcode = $this->barcode_postnet($code, false); - break; - } - case 'PLANET': { // PLANET - $arrcode = $this->barcode_postnet($code, true); - break; - } - case 'RMS4CC': { // RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code) - $arrcode = $this->barcode_rms4cc($code, false); - break; - } - case 'KIX': { // KIX (Klant index - Customer index) - $arrcode = $this->barcode_rms4cc($code, true); - break; - } - case 'IMB': { // IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200 - $arrcode = $this->barcode_imb($code); - break; - } - case 'IMBPRE': { // IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200- pre-processed - $arrcode = $this->barcode_imb_pre($code); - break; - } - case 'CODABAR': { // CODABAR - $arrcode = $this->barcode_codabar($code); - break; - } - case 'CODE11': { // CODE 11 - $arrcode = $this->barcode_code11($code); - break; - } - case 'PHARMA': { // PHARMACODE - $arrcode = $this->barcode_pharmacode($code); - break; - } - case 'PHARMA2T': { // PHARMACODE TWO-TRACKS - $arrcode = $this->barcode_pharmacode2t($code); - break; - } - default: { - $this->barcode_array = array(); - $arrcode = false; - break; - } - } - $this->barcode_array = $arrcode; - } - - /** - * CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9. - * General-purpose code in very wide use world-wide - * @param string $code code to represent. - * @param boolean $extended if true uses the extended mode. - * @param boolean $checksum if true add a checksum to the code. - * @return array barcode representation. - * @protected - */ - protected function barcode_code39($code, $extended=false, $checksum=false) { - $chr['0'] = '111331311'; - $chr['1'] = '311311113'; - $chr['2'] = '113311113'; - $chr['3'] = '313311111'; - $chr['4'] = '111331113'; - $chr['5'] = '311331111'; - $chr['6'] = '113331111'; - $chr['7'] = '111311313'; - $chr['8'] = '311311311'; - $chr['9'] = '113311311'; - $chr['A'] = '311113113'; - $chr['B'] = '113113113'; - $chr['C'] = '313113111'; - $chr['D'] = '111133113'; - $chr['E'] = '311133111'; - $chr['F'] = '113133111'; - $chr['G'] = '111113313'; - $chr['H'] = '311113311'; - $chr['I'] = '113113311'; - $chr['J'] = '111133311'; - $chr['K'] = '311111133'; - $chr['L'] = '113111133'; - $chr['M'] = '313111131'; - $chr['N'] = '111131133'; - $chr['O'] = '311131131'; - $chr['P'] = '113131131'; - $chr['Q'] = '111111333'; - $chr['R'] = '311111331'; - $chr['S'] = '113111331'; - $chr['T'] = '111131331'; - $chr['U'] = '331111113'; - $chr['V'] = '133111113'; - $chr['W'] = '333111111'; - $chr['X'] = '131131113'; - $chr['Y'] = '331131111'; - $chr['Z'] = '133131111'; - $chr['-'] = '131111313'; - $chr['.'] = '331111311'; - $chr[' '] = '133111311'; - $chr['$'] = '131313111'; - $chr['/'] = '131311131'; - $chr['+'] = '131113131'; - $chr['%'] = '111313131'; - $chr['*'] = '131131311'; - $code = strtoupper($code); - if ($extended) { - // extended mode - $code = $this->encode_code39_ext($code); - } - if ($code === false) { - return false; - } - if ($checksum) { - // checksum - $code .= $this->checksum_code39($code); - } - // add start and stop codes - $code = '*'.$code.'*'; - $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); - $k = 0; - $clen = strlen($code); - for ($i = 0; $i < $clen; ++$i) { - $char = $code[$i]; - if(!isset($chr[$char])) { - // invalid character - return false; - } - for ($j = 0; $j < 9; ++$j) { - if (($j % 2) == 0) { - $t = true; // bar - } else { - $t = false; // space - } - $w = $chr[$char][$j]; - $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); - $bararray['maxw'] += $w; - ++$k; - } - // intercharacter gap - $bararray['bcode'][$k] = array('t' => false, 'w' => 1, 'h' => 1, 'p' => 0); - $bararray['maxw'] += 1; - ++$k; - } - return $bararray; - } - - /** - * Encode a string to be used for CODE 39 Extended mode. - * @param string $code code to represent. - * @return string encoded string. - * @protected - */ - protected function encode_code39_ext($code) { - $encode = array( - chr(0) => '%U', chr(1) => '$A', chr(2) => '$B', chr(3) => '$C', - chr(4) => '$D', chr(5) => '$E', chr(6) => '$F', chr(7) => '$G', - chr(8) => '$H', chr(9) => '$I', chr(10) => '$J', chr(11) => '£K', - chr(12) => '$L', chr(13) => '$M', chr(14) => '$N', chr(15) => '$O', - chr(16) => '$P', chr(17) => '$Q', chr(18) => '$R', chr(19) => '$S', - chr(20) => '$T', chr(21) => '$U', chr(22) => '$V', chr(23) => '$W', - chr(24) => '$X', chr(25) => '$Y', chr(26) => '$Z', chr(27) => '%A', - chr(28) => '%B', chr(29) => '%C', chr(30) => '%D', chr(31) => '%E', - chr(32) => ' ', chr(33) => '/A', chr(34) => '/B', chr(35) => '/C', - chr(36) => '/D', chr(37) => '/E', chr(38) => '/F', chr(39) => '/G', - chr(40) => '/H', chr(41) => '/I', chr(42) => '/J', chr(43) => '/K', - chr(44) => '/L', chr(45) => '-', chr(46) => '.', chr(47) => '/O', - chr(48) => '0', chr(49) => '1', chr(50) => '2', chr(51) => '3', - chr(52) => '4', chr(53) => '5', chr(54) => '6', chr(55) => '7', - chr(56) => '8', chr(57) => '9', chr(58) => '/Z', chr(59) => '%F', - chr(60) => '%G', chr(61) => '%H', chr(62) => '%I', chr(63) => '%J', - chr(64) => '%V', chr(65) => 'A', chr(66) => 'B', chr(67) => 'C', - chr(68) => 'D', chr(69) => 'E', chr(70) => 'F', chr(71) => 'G', - chr(72) => 'H', chr(73) => 'I', chr(74) => 'J', chr(75) => 'K', - chr(76) => 'L', chr(77) => 'M', chr(78) => 'N', chr(79) => 'O', - chr(80) => 'P', chr(81) => 'Q', chr(82) => 'R', chr(83) => 'S', - chr(84) => 'T', chr(85) => 'U', chr(86) => 'V', chr(87) => 'W', - chr(88) => 'X', chr(89) => 'Y', chr(90) => 'Z', chr(91) => '%K', - chr(92) => '%L', chr(93) => '%M', chr(94) => '%N', chr(95) => '%O', - chr(96) => '%W', chr(97) => '+A', chr(98) => '+B', chr(99) => '+C', - chr(100) => '+D', chr(101) => '+E', chr(102) => '+F', chr(103) => '+G', - chr(104) => '+H', chr(105) => '+I', chr(106) => '+J', chr(107) => '+K', - chr(108) => '+L', chr(109) => '+M', chr(110) => '+N', chr(111) => '+O', - chr(112) => '+P', chr(113) => '+Q', chr(114) => '+R', chr(115) => '+S', - chr(116) => '+T', chr(117) => '+U', chr(118) => '+V', chr(119) => '+W', - chr(120) => '+X', chr(121) => '+Y', chr(122) => '+Z', chr(123) => '%P', - chr(124) => '%Q', chr(125) => '%R', chr(126) => '%S', chr(127) => '%T'); - $code_ext = ''; - $clen = strlen($code); - for ($i = 0 ; $i < $clen; ++$i) { - if (ord($code[$i]) > 127) { - return false; - } - $code_ext .= $encode[$code[$i]]; - } - return $code_ext; - } - - /** - * Calculate CODE 39 checksum (modulo 43). - * @param string $code code to represent. - * @return string char checksum. - * @protected - */ - protected function checksum_code39($code) { - $chars = array( - '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', '-', '.', ' ', '$', '/', '+', '%'); - $sum = 0; - $clen = strlen($code); - for ($i = 0 ; $i < $clen; ++$i) { - $k = array_keys($chars, $code[$i]); - $sum += $k[0]; - } - $j = ($sum % 43); - return $chars[$j]; - } - - /** - * CODE 93 - USS-93 - * Compact code similar to Code 39 - * @param string $code code to represent. - * @return array barcode representation. - * @protected - */ - protected function barcode_code93($code) { - $chr[48] = '131112'; // 0 - $chr[49] = '111213'; // 1 - $chr[50] = '111312'; // 2 - $chr[51] = '111411'; // 3 - $chr[52] = '121113'; // 4 - $chr[53] = '121212'; // 5 - $chr[54] = '121311'; // 6 - $chr[55] = '111114'; // 7 - $chr[56] = '131211'; // 8 - $chr[57] = '141111'; // 9 - $chr[65] = '211113'; // A - $chr[66] = '211212'; // B - $chr[67] = '211311'; // C - $chr[68] = '221112'; // D - $chr[69] = '221211'; // E - $chr[70] = '231111'; // F - $chr[71] = '112113'; // G - $chr[72] = '112212'; // H - $chr[73] = '112311'; // I - $chr[74] = '122112'; // J - $chr[75] = '132111'; // K - $chr[76] = '111123'; // L - $chr[77] = '111222'; // M - $chr[78] = '111321'; // N - $chr[79] = '121122'; // O - $chr[80] = '131121'; // P - $chr[81] = '212112'; // Q - $chr[82] = '212211'; // R - $chr[83] = '211122'; // S - $chr[84] = '211221'; // T - $chr[85] = '221121'; // U - $chr[86] = '222111'; // V - $chr[87] = '112122'; // W - $chr[88] = '112221'; // X - $chr[89] = '122121'; // Y - $chr[90] = '123111'; // Z - $chr[45] = '121131'; // - - $chr[46] = '311112'; // . - $chr[32] = '311211'; // - $chr[36] = '321111'; // $ - $chr[47] = '112131'; // / - $chr[43] = '113121'; // + - $chr[37] = '211131'; // % - $chr[128] = '121221'; // ($) - $chr[129] = '311121'; // (/) - $chr[130] = '122211'; // (+) - $chr[131] = '312111'; // (%) - $chr[42] = '111141'; // start-stop - $code = strtoupper($code); - $encode = array( - chr(0) => chr(131).'U', chr(1) => chr(128).'A', chr(2) => chr(128).'B', chr(3) => chr(128).'C', - chr(4) => chr(128).'D', chr(5) => chr(128).'E', chr(6) => chr(128).'F', chr(7) => chr(128).'G', - chr(8) => chr(128).'H', chr(9) => chr(128).'I', chr(10) => chr(128).'J', chr(11) => '£K', - chr(12) => chr(128).'L', chr(13) => chr(128).'M', chr(14) => chr(128).'N', chr(15) => chr(128).'O', - chr(16) => chr(128).'P', chr(17) => chr(128).'Q', chr(18) => chr(128).'R', chr(19) => chr(128).'S', - chr(20) => chr(128).'T', chr(21) => chr(128).'U', chr(22) => chr(128).'V', chr(23) => chr(128).'W', - chr(24) => chr(128).'X', chr(25) => chr(128).'Y', chr(26) => chr(128).'Z', chr(27) => chr(131).'A', - chr(28) => chr(131).'B', chr(29) => chr(131).'C', chr(30) => chr(131).'D', chr(31) => chr(131).'E', - chr(32) => ' ', chr(33) => chr(129).'A', chr(34) => chr(129).'B', chr(35) => chr(129).'C', - chr(36) => chr(129).'D', chr(37) => chr(129).'E', chr(38) => chr(129).'F', chr(39) => chr(129).'G', - chr(40) => chr(129).'H', chr(41) => chr(129).'I', chr(42) => chr(129).'J', chr(43) => chr(129).'K', - chr(44) => chr(129).'L', chr(45) => '-', chr(46) => '.', chr(47) => chr(129).'O', - chr(48) => '0', chr(49) => '1', chr(50) => '2', chr(51) => '3', - chr(52) => '4', chr(53) => '5', chr(54) => '6', chr(55) => '7', - chr(56) => '8', chr(57) => '9', chr(58) => chr(129).'Z', chr(59) => chr(131).'F', - chr(60) => chr(131).'G', chr(61) => chr(131).'H', chr(62) => chr(131).'I', chr(63) => chr(131).'J', - chr(64) => chr(131).'V', chr(65) => 'A', chr(66) => 'B', chr(67) => 'C', - chr(68) => 'D', chr(69) => 'E', chr(70) => 'F', chr(71) => 'G', - chr(72) => 'H', chr(73) => 'I', chr(74) => 'J', chr(75) => 'K', - chr(76) => 'L', chr(77) => 'M', chr(78) => 'N', chr(79) => 'O', - chr(80) => 'P', chr(81) => 'Q', chr(82) => 'R', chr(83) => 'S', - chr(84) => 'T', chr(85) => 'U', chr(86) => 'V', chr(87) => 'W', - chr(88) => 'X', chr(89) => 'Y', chr(90) => 'Z', chr(91) => chr(131).'K', - chr(92) => chr(131).'L', chr(93) => chr(131).'M', chr(94) => chr(131).'N', chr(95) => chr(131).'O', - chr(96) => chr(131).'W', chr(97) => chr(130).'A', chr(98) => chr(130).'B', chr(99) => chr(130).'C', - chr(100) => chr(130).'D', chr(101) => chr(130).'E', chr(102) => chr(130).'F', chr(103) => chr(130).'G', - chr(104) => chr(130).'H', chr(105) => chr(130).'I', chr(106) => chr(130).'J', chr(107) => chr(130).'K', - chr(108) => chr(130).'L', chr(109) => chr(130).'M', chr(110) => chr(130).'N', chr(111) => chr(130).'O', - chr(112) => chr(130).'P', chr(113) => chr(130).'Q', chr(114) => chr(130).'R', chr(115) => chr(130).'S', - chr(116) => chr(130).'T', chr(117) => chr(130).'U', chr(118) => chr(130).'V', chr(119) => chr(130).'W', - chr(120) => chr(130).'X', chr(121) => chr(130).'Y', chr(122) => chr(130).'Z', chr(123) => chr(131).'P', - chr(124) => chr(131).'Q', chr(125) => chr(131).'R', chr(126) => chr(131).'S', chr(127) => chr(131).'T'); - $code_ext = ''; - $clen = strlen($code); - for ($i = 0 ; $i < $clen; ++$i) { - if (ord($code[$i]) > 127) { - return false; - } - $code_ext .= $encode[$code[$i]]; - } - // checksum - $code_ext .= $this->checksum_code93($code_ext); - // add start and stop codes - $code = '*'.$code_ext.'*'; - $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); - $k = 0; - $clen = strlen($code); - for ($i = 0; $i < $clen; ++$i) { - $char = ord($code[$i]); - if(!isset($chr[$char])) { - // invalid character - return false; - } - for ($j = 0; $j < 6; ++$j) { - if (($j % 2) == 0) { - $t = true; // bar - } else { - $t = false; // space - } - $w = $chr[$char][$j]; - $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); - $bararray['maxw'] += $w; - ++$k; - } - } - $bararray['bcode'][$k] = array('t' => true, 'w' => 1, 'h' => 1, 'p' => 0); - $bararray['maxw'] += 1; - ++$k; - return $bararray; - } - - /** - * Calculate CODE 93 checksum (modulo 47). - * @param string $code code to represent. - * @return string checksum code. - * @protected - */ - protected function checksum_code93($code) { - $chars = array( - '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', '-', '.', ' ', '$', '/', '+', '%', - '<', '=', '>', '?'); - // translate special characters - $code = strtr($code, chr(128).chr(131).chr(129).chr(130), '<=>?'); - $len = strlen($code); - // calculate check digit C - $p = 1; - $check = 0; - for ($i = ($len - 1); $i >= 0; --$i) { - $k = array_keys($chars, $code[$i]); - $check += ($k[0] * $p); - ++$p; - if ($p > 20) { - $p = 1; - } - } - $check %= 47; - $c = $chars[$check]; - $code .= $c; - // calculate check digit K - $p = 1; - $check = 0; - for ($i = $len; $i >= 0; --$i) { - $k = array_keys($chars, $code[$i]); - $check += ($k[0] * $p); - ++$p; - if ($p > 15) { - $p = 1; - } - } - $check %= 47; - $k = $chars[$check]; - $checksum = $c.$k; - // resto respecial characters - $checksum = strtr($checksum, '<=>?', chr(128).chr(131).chr(129).chr(130)); - return $checksum; - } - - /** - * Checksum for standard 2 of 5 barcodes. - * @param string $code code to process. - * @return int checksum. - * @protected - */ - protected function checksum_s25($code) { - $len = strlen($code); - $sum = 0; - for ($i = 0; $i < $len; $i+=2) { - $sum += $code[$i]; - } - $sum *= 3; - for ($i = 1; $i < $len; $i+=2) { - $sum += ($code[$i]); - } - $r = $sum % 10; - if($r > 0) { - $r = (10 - $r); - } - return $r; - } - - /** - * MSI. - * Variation of Plessey code, with similar applications - * Contains digits (0 to 9) and encodes the data only in the width of bars. - * @param string $code code to represent. - * @param boolean $checksum if true add a checksum to the code (modulo 11) - * @return array barcode representation. - * @protected - */ - protected function barcode_msi($code, $checksum=false) { - $chr['0'] = '100100100100'; - $chr['1'] = '100100100110'; - $chr['2'] = '100100110100'; - $chr['3'] = '100100110110'; - $chr['4'] = '100110100100'; - $chr['5'] = '100110100110'; - $chr['6'] = '100110110100'; - $chr['7'] = '100110110110'; - $chr['8'] = '110100100100'; - $chr['9'] = '110100100110'; - $chr['A'] = '110100110100'; - $chr['B'] = '110100110110'; - $chr['C'] = '110110100100'; - $chr['D'] = '110110100110'; - $chr['E'] = '110110110100'; - $chr['F'] = '110110110110'; - if ($checksum) { - // add checksum - $clen = strlen($code); - $p = 2; - $check = 0; - for ($i = ($clen - 1); $i >= 0; --$i) { - $check += (hexdec($code[$i]) * $p); - ++$p; - if ($p > 7) { - $p = 2; - } - } - $check %= 11; - if ($check > 0) { - $check = 11 - $check; - } - $code .= $check; - } - $seq = '110'; // left guard - $clen = strlen($code); - for ($i = 0; $i < $clen; ++$i) { - $digit = $code[$i]; - if (!isset($chr[$digit])) { - // invalid character - return false; - } - $seq .= $chr[$digit]; - } - $seq .= '1001'; // right guard - $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); - return $this->binseq_to_array($seq, $bararray); - } - - /** - * Standard 2 of 5 barcodes. - * Used in airline ticket marking, photofinishing - * Contains digits (0 to 9) and encodes the data only in the width of bars. - * @param string $code code to represent. - * @param boolean $checksum if true add a checksum to the code - * @return array barcode representation. - * @protected - */ - protected function barcode_s25($code, $checksum=false) { - $chr['0'] = '10101110111010'; - $chr['1'] = '11101010101110'; - $chr['2'] = '10111010101110'; - $chr['3'] = '11101110101010'; - $chr['4'] = '10101110101110'; - $chr['5'] = '11101011101010'; - $chr['6'] = '10111011101010'; - $chr['7'] = '10101011101110'; - $chr['8'] = '10101110111010'; - $chr['9'] = '10111010111010'; - if ($checksum) { - // add checksum - $code .= $this->checksum_s25($code); - } - if((strlen($code) % 2) != 0) { - // add leading zero if code-length is odd - $code = '0'.$code; - } - $seq = '11011010'; - $clen = strlen($code); - for ($i = 0; $i < $clen; ++$i) { - $digit = $code[$i]; - if (!isset($chr[$digit])) { - // invalid character - return false; - } - $seq .= $chr[$digit]; - } - $seq .= '1101011'; - $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); - return $this->binseq_to_array($seq, $bararray); - } - - /** - * Convert binary barcode sequence to WarnockPDF barcode array. - * @param string $seq barcode as binary sequence. - * @param array $bararray barcode array to fill up - * @return array barcode representation. - * @protected - */ - protected function binseq_to_array($seq, $bararray) { - $len = strlen($seq); - $w = 0; - $k = 0; - for ($i = 0; $i < $len; ++$i) { - $w += 1; - if (($i == ($len - 1)) OR (($i < ($len - 1)) AND ($seq[$i] != $seq[($i+1)]))) { - if ($seq[$i] == '1') { - $t = true; // bar - } else { - $t = false; // space - } - $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); - $bararray['maxw'] += $w; - ++$k; - $w = 0; - } - } - return $bararray; - } - - /** - * Interleaved 2 of 5 barcodes. - * Compact numeric code, widely used in industry, air cargo - * Contains digits (0 to 9) and encodes the data in the width of both bars and spaces. - * @param string $code code to represent. - * @param boolean $checksum if true add a checksum to the code - * @return array barcode representation. - * @protected - */ - protected function barcode_i25($code, $checksum=false) { - $chr['0'] = '11221'; - $chr['1'] = '21112'; - $chr['2'] = '12112'; - $chr['3'] = '22111'; - $chr['4'] = '11212'; - $chr['5'] = '21211'; - $chr['6'] = '12211'; - $chr['7'] = '11122'; - $chr['8'] = '21121'; - $chr['9'] = '12121'; - $chr['A'] = '11'; - $chr['Z'] = '21'; - if ($checksum) { - // add checksum - $code .= $this->checksum_s25($code); - } - if((strlen($code) % 2) != 0) { - // add leading zero if code-length is odd - $code = '0'.$code; - } - // add start and stop codes - $code = 'AA'.strtolower($code).'ZA'; - - $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); - $k = 0; - $clen = strlen($code); - for ($i = 0; $i < $clen; $i = ($i + 2)) { - $char_bar = $code[$i]; - $char_space = $code[$i+1]; - if((!isset($chr[$char_bar])) OR (!isset($chr[$char_space]))) { - // invalid character - return false; - } - // create a bar-space sequence - $seq = ''; - $chrlen = strlen($chr[$char_bar]); - for ($s = 0; $s < $chrlen; $s++){ - $seq .= $chr[$char_bar][$s] . $chr[$char_space][$s]; - } - $seqlen = strlen($seq); - for ($j = 0; $j < $seqlen; ++$j) { - if (($j % 2) == 0) { - $t = true; // bar - } else { - $t = false; // space - } - $w = (float)$seq[$j]; - $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); - $bararray['maxw'] += $w; - ++$k; - } - } - return $bararray; - } - - /** - * C128 barcodes. - * Very capable code, excellent density, high reliability; in very wide use world-wide - * @param string $code code to represent. - * @param string $type barcode type: A, B, C or empty for automatic switch (AUTO mode) - * @return array barcode representation. - * @protected - */ - protected function barcode_c128($code, $type='') { - $chr = array( - '212222', /* 00 */ - '222122', /* 01 */ - '222221', /* 02 */ - '121223', /* 03 */ - '121322', /* 04 */ - '131222', /* 05 */ - '122213', /* 06 */ - '122312', /* 07 */ - '132212', /* 08 */ - '221213', /* 09 */ - '221312', /* 10 */ - '231212', /* 11 */ - '112232', /* 12 */ - '122132', /* 13 */ - '122231', /* 14 */ - '113222', /* 15 */ - '123122', /* 16 */ - '123221', /* 17 */ - '223211', /* 18 */ - '221132', /* 19 */ - '221231', /* 20 */ - '213212', /* 21 */ - '223112', /* 22 */ - '312131', /* 23 */ - '311222', /* 24 */ - '321122', /* 25 */ - '321221', /* 26 */ - '312212', /* 27 */ - '322112', /* 28 */ - '322211', /* 29 */ - '212123', /* 30 */ - '212321', /* 31 */ - '232121', /* 32 */ - '111323', /* 33 */ - '131123', /* 34 */ - '131321', /* 35 */ - '112313', /* 36 */ - '132113', /* 37 */ - '132311', /* 38 */ - '211313', /* 39 */ - '231113', /* 40 */ - '231311', /* 41 */ - '112133', /* 42 */ - '112331', /* 43 */ - '132131', /* 44 */ - '113123', /* 45 */ - '113321', /* 46 */ - '133121', /* 47 */ - '313121', /* 48 */ - '211331', /* 49 */ - '231131', /* 50 */ - '213113', /* 51 */ - '213311', /* 52 */ - '213131', /* 53 */ - '311123', /* 54 */ - '311321', /* 55 */ - '331121', /* 56 */ - '312113', /* 57 */ - '312311', /* 58 */ - '332111', /* 59 */ - '314111', /* 60 */ - '221411', /* 61 */ - '431111', /* 62 */ - '111224', /* 63 */ - '111422', /* 64 */ - '121124', /* 65 */ - '121421', /* 66 */ - '141122', /* 67 */ - '141221', /* 68 */ - '112214', /* 69 */ - '112412', /* 70 */ - '122114', /* 71 */ - '122411', /* 72 */ - '142112', /* 73 */ - '142211', /* 74 */ - '241211', /* 75 */ - '221114', /* 76 */ - '413111', /* 77 */ - '241112', /* 78 */ - '134111', /* 79 */ - '111242', /* 80 */ - '121142', /* 81 */ - '121241', /* 82 */ - '114212', /* 83 */ - '124112', /* 84 */ - '124211', /* 85 */ - '411212', /* 86 */ - '421112', /* 87 */ - '421211', /* 88 */ - '212141', /* 89 */ - '214121', /* 90 */ - '412121', /* 91 */ - '111143', /* 92 */ - '111341', /* 93 */ - '131141', /* 94 */ - '114113', /* 95 */ - '114311', /* 96 */ - '411113', /* 97 */ - '411311', /* 98 */ - '113141', /* 99 */ - '114131', /* 100 */ - '311141', /* 101 */ - '411131', /* 102 */ - '211412', /* 103 START A */ - '211214', /* 104 START B */ - '211232', /* 105 START C */ - '233111', /* STOP */ - '200000' /* END */ - ); - // ASCII characters for code A (ASCII 00 - 95) - $keys_a = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_'; - $keys_a .= chr(0).chr(1).chr(2).chr(3).chr(4).chr(5).chr(6).chr(7).chr(8).chr(9); - $keys_a .= chr(10).chr(11).chr(12).chr(13).chr(14).chr(15).chr(16).chr(17).chr(18).chr(19); - $keys_a .= chr(20).chr(21).chr(22).chr(23).chr(24).chr(25).chr(26).chr(27).chr(28).chr(29); - $keys_a .= chr(30).chr(31); - // ASCII characters for code B (ASCII 32 - 127) - $keys_b = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'.chr(127); - // special codes - $fnc_a = array(241 => 102, 242 => 97, 243 => 96, 244 => 101); - $fnc_b = array(241 => 102, 242 => 97, 243 => 96, 244 => 100); - // array of symbols - $code_data = array(); - // length of the code - $len = strlen($code); - switch(strtoupper($type)) { - case 'A': { // MODE A - $startid = 103; - for ($i = 0; $i < $len; ++$i) { - $char = $code[$i]; - $char_id = ord($char); - if (($char_id >= 241) AND ($char_id <= 244)) { - $code_data[] = $fnc_a[$char_id]; - } elseif (($char_id >= 0) AND ($char_id <= 95)) { - $code_data[] = strpos($keys_a, $char); - } else { - return false; - } - } - break; - } - case 'B': { // MODE B - $startid = 104; - for ($i = 0; $i < $len; ++$i) { - $char = $code[$i]; - $char_id = ord($char); - if (($char_id >= 241) AND ($char_id <= 244)) { - $code_data[] = $fnc_b[$char_id]; - } elseif (($char_id >= 32) AND ($char_id <= 127)) { - $code_data[] = strpos($keys_b, $char); - } else { - return false; - } - } - break; - } - case 'C': { // MODE C - $startid = 105; - if (ord($code[0]) == 241) { - $code_data[] = 102; - $code = substr($code, 1); - --$len; - } - if (($len % 2) != 0) { - // the length must be even - return false; - } - for ($i = 0; $i < $len; $i+=2) { - $chrnum = $code[$i].$code[$i+1]; - if (preg_match('/([0-9]{2})/', $chrnum) > 0) { - $code_data[] = intval($chrnum); - } else { - return false; - } - } - break; - } - default: { // MODE AUTO - // split code into sequences - $sequence = array(); - // get numeric sequences (if any) - $numseq = array(); - preg_match_all('/([0-9]{4,})/', $code, $numseq, PREG_OFFSET_CAPTURE); - if (isset($numseq[1]) AND !empty($numseq[1])) { - $end_offset = 0; - foreach ($numseq[1] as $val) { - $offset = $val[1]; - if ($offset > $end_offset) { - // non numeric sequence - $sequence = array_merge($sequence, $this->get128ABsequence(substr($code, $end_offset, ($offset - $end_offset)))); - } - // numeric sequence - $slen = strlen($val[0]); - if (($slen % 2) != 0) { - // the length must be even - --$slen; - } - $sequence[] = array('C', substr($code, $offset, $slen), $slen); - $end_offset = $offset + $slen; - } - if ($end_offset < $len) { - $sequence = array_merge($sequence, $this->get128ABsequence(substr($code, $end_offset))); - } - } else { - // text code (non C mode) - $sequence = array_merge($sequence, $this->get128ABsequence($code)); - } - // process the sequence - foreach ($sequence as $key => $seq) { - switch($seq[0]) { - case 'A': { - if ($key == 0) { - $startid = 103; - } elseif ($sequence[($key - 1)][0] != 'A') { - if (($seq[2] == 1) AND ($key > 0) AND ($sequence[($key - 1)][0] == 'B') AND (!isset($sequence[($key - 1)][3]))) { - // single character shift - $code_data[] = 98; - // mark shift - $sequence[$key][3] = true; - } elseif (!isset($sequence[($key - 1)][3])) { - $code_data[] = 101; - } - } - for ($i = 0; $i < $seq[2]; ++$i) { - $char = $seq[1][$i]; - $char_id = ord($char); - if (($char_id >= 241) AND ($char_id <= 244)) { - $code_data[] = $fnc_a[$char_id]; - } else { - $code_data[] = strpos($keys_a, $char); - } - } - break; - } - case 'B': { - if ($key == 0) { - $tmpchr = ord($seq[1][0]); - if (($seq[2] == 1) AND ($tmpchr >= 241) AND ($tmpchr <= 244) AND isset($sequence[($key + 1)]) AND ($sequence[($key + 1)][0] != 'B')) { - switch ($sequence[($key + 1)][0]) { - case 'A': { - $startid = 103; - $sequence[$key][0] = 'A'; - $code_data[] = $fnc_a[$tmpchr]; - break; - } - case 'C': { - $startid = 105; - $sequence[$key][0] = 'C'; - $code_data[] = $fnc_a[$tmpchr]; - break; - } - } - break; - } else { - $startid = 104; - } - } elseif ($sequence[($key - 1)][0] != 'B') { - if (($seq[2] == 1) AND ($key > 0) AND ($sequence[($key - 1)][0] == 'A') AND (!isset($sequence[($key - 1)][3]))) { - // single character shift - $code_data[] = 98; - // mark shift - $sequence[$key][3] = true; - } elseif (!isset($sequence[($key - 1)][3])) { - $code_data[] = 100; - } - } - for ($i = 0; $i < $seq[2]; ++$i) { - $char = $seq[1][$i]; - $char_id = ord($char); - if (($char_id >= 241) AND ($char_id <= 244)) { - $code_data[] = $fnc_b[$char_id]; - } else { - $code_data[] = strpos($keys_b, $char); - } - } - break; - } - case 'C': { - if ($key == 0) { - $startid = 105; - } elseif ($sequence[($key - 1)][0] != 'C') { - $code_data[] = 99; - } - for ($i = 0; $i < $seq[2]; $i+=2) { - $chrnum = $seq[1][$i].$seq[1][$i+1]; - $code_data[] = intval($chrnum); - } - break; - } - } - } - } - } - // calculate check character - $sum = $startid; - foreach ($code_data as $key => $val) { - $sum += ($val * ($key + 1)); - } - // add check character - $code_data[] = ($sum % 103); - // add stop sequence - $code_data[] = 106; - $code_data[] = 107; - // add start code at the beginning - array_unshift($code_data, $startid); - // build barcode array - $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); - foreach ($code_data as $val) { - $seq = $chr[$val]; - for ($j = 0; $j < 6; ++$j) { - if (($j % 2) == 0) { - $t = true; // bar - } else { - $t = false; // space - } - $w = (float)$seq[$j]; - $bararray['bcode'][] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); - $bararray['maxw'] += $w; - } - } - return $bararray; - } - - /** - * Split text code in A/B sequence for 128 code - * @param string $code code to split. - * @return array sequence - * @protected - */ - protected function get128ABsequence($code) { - $len = strlen($code); - $sequence = array(); - // get A sequences (if any) - $numseq = array(); - preg_match_all('/([\0-\31])/', $code, $numseq, PREG_OFFSET_CAPTURE); - if (isset($numseq[1]) AND !empty($numseq[1])) { - $end_offset = 0; - foreach ($numseq[1] as $val) { - $offset = $val[1]; - if ($offset > $end_offset) { - // B sequence - $sequence[] = array('B', substr($code, $end_offset, ($offset - $end_offset)), ($offset - $end_offset)); - } - // A sequence - $slen = strlen($val[0]); - $sequence[] = array('A', substr($code, $offset, $slen), $slen); - $end_offset = $offset + $slen; - } - if ($end_offset < $len) { - $sequence[] = array('B', substr($code, $end_offset), ($len - $end_offset)); - } - } else { - // only B sequence - $sequence[] = array('B', $code, $len); - } - return $sequence; - } - - /** - * EAN13 and UPC-A barcodes. - * EAN13: European Article Numbering international retail product code - * UPC-A: Universal product code seen on almost all retail products in the USA and Canada - * UPC-E: Short version of UPC symbol - * @param string $code code to represent. - * @param string $len barcode type: 6 = UPC-E, 8 = EAN8, 13 = EAN13, 12 = UPC-A - * @return array barcode representation. - * @protected - */ - protected function barcode_eanupc($code, $len=13) { - $upce = false; - if ($len == 6) { - $len = 12; // UPC-A - $upce = true; // UPC-E mode - } - $data_len = $len - 1; - //Padding - $code = str_pad($code, $data_len, '0', STR_PAD_LEFT); - $code_len = strlen($code); - // calculate check digit - $sum_a = 0; - for ($i = 1; $i < $data_len; $i+=2) { - $sum_a += $code[$i]; - } - if ($len > 12) { - $sum_a *= 3; - } - $sum_b = 0; - for ($i = 0; $i < $data_len; $i+=2) { - $sum_b += ($code[$i]); - } - if ($len < 13) { - $sum_b *= 3; - } - $r = ($sum_a + $sum_b) % 10; - if($r > 0) { - $r = (10 - $r); - } - if ($code_len == $data_len) { - // add check digit - $code .= $r; - } elseif ($r !== intval($code[$data_len])) { - // wrong checkdigit - return false; - } - if ($len == 12) { - // UPC-A - $code = '0'.$code; - ++$len; - } - if ($upce) { - // convert UPC-A to UPC-E - $tmp = substr($code, 4, 3); - if (($tmp == '000') OR ($tmp == '100') OR ($tmp == '200')) { - // manufacturer code ends in 000, 100, or 200 - $upce_code = substr($code, 2, 2).substr($code, 9, 3).substr($code, 4, 1); - } else { - $tmp = substr($code, 5, 2); - if ($tmp == '00') { - // manufacturer code ends in 00 - $upce_code = substr($code, 2, 3).substr($code, 10, 2).'3'; - } else { - $tmp = substr($code, 6, 1); - if ($tmp == '0') { - // manufacturer code ends in 0 - $upce_code = substr($code, 2, 4).substr($code, 11, 1).'4'; - } else { - // manufacturer code does not end in zero - $upce_code = substr($code, 2, 5).substr($code, 11, 1); - } - } - } - } - //Convert digits to bars - $codes = array( - 'A'=>array( // left odd parity - '0'=>'0001101', - '1'=>'0011001', - '2'=>'0010011', - '3'=>'0111101', - '4'=>'0100011', - '5'=>'0110001', - '6'=>'0101111', - '7'=>'0111011', - '8'=>'0110111', - '9'=>'0001011'), - 'B'=>array( // left even parity - '0'=>'0100111', - '1'=>'0110011', - '2'=>'0011011', - '3'=>'0100001', - '4'=>'0011101', - '5'=>'0111001', - '6'=>'0000101', - '7'=>'0010001', - '8'=>'0001001', - '9'=>'0010111'), - 'C'=>array( // right - '0'=>'1110010', - '1'=>'1100110', - '2'=>'1101100', - '3'=>'1000010', - '4'=>'1011100', - '5'=>'1001110', - '6'=>'1010000', - '7'=>'1000100', - '8'=>'1001000', - '9'=>'1110100') - ); - $parities = array( - '0'=>array('A','A','A','A','A','A'), - '1'=>array('A','A','B','A','B','B'), - '2'=>array('A','A','B','B','A','B'), - '3'=>array('A','A','B','B','B','A'), - '4'=>array('A','B','A','A','B','B'), - '5'=>array('A','B','B','A','A','B'), - '6'=>array('A','B','B','B','A','A'), - '7'=>array('A','B','A','B','A','B'), - '8'=>array('A','B','A','B','B','A'), - '9'=>array('A','B','B','A','B','A') - ); - $upce_parities = array(); - $upce_parities[0] = array( - '0'=>array('B','B','B','A','A','A'), - '1'=>array('B','B','A','B','A','A'), - '2'=>array('B','B','A','A','B','A'), - '3'=>array('B','B','A','A','A','B'), - '4'=>array('B','A','B','B','A','A'), - '5'=>array('B','A','A','B','B','A'), - '6'=>array('B','A','A','A','B','B'), - '7'=>array('B','A','B','A','B','A'), - '8'=>array('B','A','B','A','A','B'), - '9'=>array('B','A','A','B','A','B') - ); - $upce_parities[1] = array( - '0'=>array('A','A','A','B','B','B'), - '1'=>array('A','A','B','A','B','B'), - '2'=>array('A','A','B','B','A','B'), - '3'=>array('A','A','B','B','B','A'), - '4'=>array('A','B','A','A','B','B'), - '5'=>array('A','B','B','A','A','B'), - '6'=>array('A','B','B','B','A','A'), - '7'=>array('A','B','A','B','A','B'), - '8'=>array('A','B','A','B','B','A'), - '9'=>array('A','B','B','A','B','A') - ); - $k = 0; - $seq = '101'; // left guard bar - if ($upce) { - $bararray = array('code' => $upce_code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); - $p = $upce_parities[$code[1]][$r]; - for ($i = 0; $i < 6; ++$i) { - $seq .= $codes[$p[$i]][$upce_code[$i]]; - } - $seq .= '010101'; // right guard bar - } else { - $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); - $half_len = intval(ceil($len / 2)); - if ($len == 8) { - for ($i = 0; $i < $half_len; ++$i) { - $seq .= $codes['A'][$code[$i]]; - } - } else { - $p = $parities[$code[0]]; - for ($i = 1; $i < $half_len; ++$i) { - $seq .= $codes[$p[$i-1]][$code[$i]]; - } - } - $seq .= '01010'; // center guard bar - for ($i = $half_len; $i < $len; ++$i) { - $seq .= $codes['C'][$code[$i]]; - } - $seq .= '101'; // right guard bar - } - $clen = strlen($seq); - $w = 0; - for ($i = 0; $i < $clen; ++$i) { - $w += 1; - if (($i == ($clen - 1)) OR (($i < ($clen - 1)) AND ($seq[$i] != $seq[$i+1]))) { - if ($seq[$i] == '1') { - $t = true; // bar - } else { - $t = false; // space - } - $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); - $bararray['maxw'] += $w; - ++$k; - $w = 0; - } - } - return $bararray; - } - - /** - * UPC-Based Extensions - * 2-Digit Ext.: Used to indicate magazines and newspaper issue numbers - * 5-Digit Ext.: Used to mark suggested retail price of books - * @param string $code code to represent. - * @param string $len barcode type: 2 = 2-Digit, 5 = 5-Digit - * @return array barcode representation. - * @protected - */ - protected function barcode_eanext($code, $len=5) { - //Padding - $code = str_pad($code, $len, '0', STR_PAD_LEFT); - // calculate check digit - if ($len == 2) { - $r = $code % 4; - } elseif ($len == 5) { - $r = (3 * ($code[0] + $code[2] + $code[4])) + (9 * ($code[1] + $code[3])); - $r %= 10; - } else { - return false; - } - //Convert digits to bars - $codes = array( - 'A'=>array( // left odd parity - '0'=>'0001101', - '1'=>'0011001', - '2'=>'0010011', - '3'=>'0111101', - '4'=>'0100011', - '5'=>'0110001', - '6'=>'0101111', - '7'=>'0111011', - '8'=>'0110111', - '9'=>'0001011'), - 'B'=>array( // left even parity - '0'=>'0100111', - '1'=>'0110011', - '2'=>'0011011', - '3'=>'0100001', - '4'=>'0011101', - '5'=>'0111001', - '6'=>'0000101', - '7'=>'0010001', - '8'=>'0001001', - '9'=>'0010111') - ); - $parities = array(); - $parities[2] = array( - '0'=>array('A','A'), - '1'=>array('A','B'), - '2'=>array('B','A'), - '3'=>array('B','B') - ); - $parities[5] = array( - '0'=>array('B','B','A','A','A'), - '1'=>array('B','A','B','A','A'), - '2'=>array('B','A','A','B','A'), - '3'=>array('B','A','A','A','B'), - '4'=>array('A','B','B','A','A'), - '5'=>array('A','A','B','B','A'), - '6'=>array('A','A','A','B','B'), - '7'=>array('A','B','A','B','A'), - '8'=>array('A','B','A','A','B'), - '9'=>array('A','A','B','A','B') - ); - $p = $parities[$len][$r]; - $seq = '1011'; // left guard bar - $seq .= $codes[$p[0]][$code[0]]; - for ($i = 1; $i < $len; ++$i) { - $seq .= '01'; // separator - $seq .= $codes[$p[$i]][$code[$i]]; - } - $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); - return $this->binseq_to_array($seq, $bararray); - } - - /** - * POSTNET and PLANET barcodes. - * Used by U.S. Postal Service for automated mail sorting - * @param string $code zip code to represent. Must be a string containing a zip code of the form DDDDD or DDDDD-DDDD. - * @param boolean $planet if true print the PLANET barcode, otherwise print POSTNET - * @return array barcode representation. - * @protected - */ - protected function barcode_postnet($code, $planet=false) { - // bar length - if ($planet) { - $barlen = Array( - 0 => Array(1,1,2,2,2), - 1 => Array(2,2,2,1,1), - 2 => Array(2,2,1,2,1), - 3 => Array(2,2,1,1,2), - 4 => Array(2,1,2,2,1), - 5 => Array(2,1,2,1,2), - 6 => Array(2,1,1,2,2), - 7 => Array(1,2,2,2,1), - 8 => Array(1,2,2,1,2), - 9 => Array(1,2,1,2,2) - ); - } else { - $barlen = Array( - 0 => Array(2,2,1,1,1), - 1 => Array(1,1,1,2,2), - 2 => Array(1,1,2,1,2), - 3 => Array(1,1,2,2,1), - 4 => Array(1,2,1,1,2), - 5 => Array(1,2,1,2,1), - 6 => Array(1,2,2,1,1), - 7 => Array(2,1,1,1,2), - 8 => Array(2,1,1,2,1), - 9 => Array(2,1,2,1,1) - ); - } - $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 2, 'bcode' => array()); - $k = 0; - $code = str_replace('-', '', $code); - $code = str_replace(' ', '', $code); - $len = strlen($code); - // calculate checksum - $sum = 0; - for ($i = 0; $i < $len; ++$i) { - $sum += intval($code[$i]); - } - $chkd = ($sum % 10); - if($chkd > 0) { - $chkd = (10 - $chkd); - } - $code .= $chkd; - $len = strlen($code); - // start bar - $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0); - $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0); - $bararray['maxw'] += 2; - for ($i = 0; $i < $len; ++$i) { - for ($j = 0; $j < 5; ++$j) { - $h = $barlen[$code[$i]][$j]; - $p = floor(1 / $h); - $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p); - $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0); - $bararray['maxw'] += 2; - } - } - // end bar - $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0); - $bararray['maxw'] += 1; - return $bararray; - } - - /** - * RMS4CC - CBC - KIX - * RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code) - KIX (Klant index - Customer index) - * RM4SCC is the name of the barcode symbology used by the Royal Mail for its Cleanmail service. - * @param string $code code to print - * @param boolean $kix if true prints the KIX variation (doesn't use the start and end symbols, and the checksum) - in this case the house number must be sufficed with an X and placed at the end of the code. - * @return array barcode representation. - * @protected - */ - protected function barcode_rms4cc($code, $kix=false) { - $notkix = !$kix; - // bar mode - // 1 = pos 1, length 2 - // 2 = pos 1, length 3 - // 3 = pos 2, length 1 - // 4 = pos 2, length 2 - $barmode = array( - '0' => array(3,3,2,2), - '1' => array(3,4,1,2), - '2' => array(3,4,2,1), - '3' => array(4,3,1,2), - '4' => array(4,3,2,1), - '5' => array(4,4,1,1), - '6' => array(3,1,4,2), - '7' => array(3,2,3,2), - '8' => array(3,2,4,1), - '9' => array(4,1,3,2), - 'A' => array(4,1,4,1), - 'B' => array(4,2,3,1), - 'C' => array(3,1,2,4), - 'D' => array(3,2,1,4), - 'E' => array(3,2,2,3), - 'F' => array(4,1,1,4), - 'G' => array(4,1,2,3), - 'H' => array(4,2,1,3), - 'I' => array(1,3,4,2), - 'J' => array(1,4,3,2), - 'K' => array(1,4,4,1), - 'L' => array(2,3,3,2), - 'M' => array(2,3,4,1), - 'N' => array(2,4,3,1), - 'O' => array(1,3,2,4), - 'P' => array(1,4,1,4), - 'Q' => array(1,4,2,3), - 'R' => array(2,3,1,4), - 'S' => array(2,3,2,3), - 'T' => array(2,4,1,3), - 'U' => array(1,1,4,4), - 'V' => array(1,2,3,4), - 'W' => array(1,2,4,3), - 'X' => array(2,1,3,4), - 'Y' => array(2,1,4,3), - 'Z' => array(2,2,3,3) - ); - $code = strtoupper($code); - $len = strlen($code); - $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 3, 'bcode' => array()); - if ($notkix) { - // table for checksum calculation (row,col) - $checktable = array( - '0' => array(1,1), - '1' => array(1,2), - '2' => array(1,3), - '3' => array(1,4), - '4' => array(1,5), - '5' => array(1,0), - '6' => array(2,1), - '7' => array(2,2), - '8' => array(2,3), - '9' => array(2,4), - 'A' => array(2,5), - 'B' => array(2,0), - 'C' => array(3,1), - 'D' => array(3,2), - 'E' => array(3,3), - 'F' => array(3,4), - 'G' => array(3,5), - 'H' => array(3,0), - 'I' => array(4,1), - 'J' => array(4,2), - 'K' => array(4,3), - 'L' => array(4,4), - 'M' => array(4,5), - 'N' => array(4,0), - 'O' => array(5,1), - 'P' => array(5,2), - 'Q' => array(5,3), - 'R' => array(5,4), - 'S' => array(5,5), - 'T' => array(5,0), - 'U' => array(0,1), - 'V' => array(0,2), - 'W' => array(0,3), - 'X' => array(0,4), - 'Y' => array(0,5), - 'Z' => array(0,0) - ); - $row = 0; - $col = 0; - for ($i = 0; $i < $len; ++$i) { - $row += $checktable[$code[$i]][0]; - $col += $checktable[$code[$i]][1]; - } - $row %= 6; - $col %= 6; - $chk = array_keys($checktable, array($row,$col)); - $code .= $chk[0]; - ++$len; - } - $k = 0; - if ($notkix) { - // start bar - $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0); - $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0); - $bararray['maxw'] += 2; - } - for ($i = 0; $i < $len; ++$i) { - for ($j = 0; $j < 4; ++$j) { - switch ($barmode[$code[$i]][$j]) { - case 1: { - $p = 0; - $h = 2; - break; - } - case 2: { - $p = 0; - $h = 3; - break; - } - case 3: { - $p = 1; - $h = 1; - break; - } - case 4: { - $p = 1; - $h = 2; - break; - } - } - $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p); - $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0); - $bararray['maxw'] += 2; - } - } - if ($notkix) { - // stop bar - $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 3, 'p' => 0); - $bararray['maxw'] += 1; - } - return $bararray; - } - - /** - * CODABAR barcodes. - * Older code often used in library systems, sometimes in blood banks - * @param string $code code to represent. - * @return array barcode representation. - * @protected - */ - protected function barcode_codabar($code) { - $chr = array( - '0' => '11111221', - '1' => '11112211', - '2' => '11121121', - '3' => '22111111', - '4' => '11211211', - '5' => '21111211', - '6' => '12111121', - '7' => '12112111', - '8' => '12211111', - '9' => '21121111', - '-' => '11122111', - '$' => '11221111', - ':' => '21112121', - '/' => '21211121', - '.' => '21212111', - '+' => '11222221', - 'A' => '11221211', - 'B' => '12121121', - 'C' => '11121221', - 'D' => '11122211' - ); - $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); - $k = 0; - $w = 0; - $seq = ''; - $code = 'A'.strtoupper($code).'A'; - $len = strlen($code); - for ($i = 0; $i < $len; ++$i) { - if (!isset($chr[$code[$i]])) { - return false; - } - $seq = $chr[$code[$i]]; - for ($j = 0; $j < 8; ++$j) { - if (($j % 2) == 0) { - $t = true; // bar - } else { - $t = false; // space - } - $w = (float)$seq[$j]; - $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); - $bararray['maxw'] += $w; - ++$k; - } - } - return $bararray; - } - - /** - * CODE11 barcodes. - * Used primarily for labeling telecommunications equipment - * @param string $code code to represent. - * @return array barcode representation. - * @protected - */ - protected function barcode_code11($code) { - $chr = array( - '0' => '111121', - '1' => '211121', - '2' => '121121', - '3' => '221111', - '4' => '112121', - '5' => '212111', - '6' => '122111', - '7' => '111221', - '8' => '211211', - '9' => '211111', - '-' => '112111', - 'S' => '112211' - ); - $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); - $k = 0; - $w = 0; - $seq = ''; - $len = strlen($code); - // calculate check digit C - $p = 1; - $check = 0; - for ($i = ($len - 1); $i >= 0; --$i) { - $digit = $code[$i]; - if ($digit == '-') { - $dval = 10; - } else { - $dval = intval($digit); - } - $check += ($dval * $p); - ++$p; - if ($p > 10) { - $p = 1; - } - } - $check %= 11; - if ($check == 10) { - $check = '-'; - } - $code .= $check; - if ($len > 10) { - // calculate check digit K - $p = 1; - $check = 0; - for ($i = $len; $i >= 0; --$i) { - $digit = $code[$i]; - if ($digit == '-') { - $dval = 10; - } else { - $dval = intval($digit); - } - $check += ($dval * $p); - ++$p; - if ($p > 9) { - $p = 1; - } - } - $check %= 11; - $code .= $check; - ++$len; - } - $code = 'S'.$code.'S'; - $len += 3; - for ($i = 0; $i < $len; ++$i) { - if (!isset($chr[$code[$i]])) { - return false; - } - $seq = $chr[$code[$i]]; - for ($j = 0; $j < 6; ++$j) { - if (($j % 2) == 0) { - $t = true; // bar - } else { - $t = false; // space - } - $w = (float)$seq[$j]; - $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); - $bararray['maxw'] += $w; - ++$k; - } - } - return $bararray; - } - - /** - * Pharmacode - * Contains digits (0 to 9) - * @param string $code code to represent. - * @return array barcode representation. - * @protected - */ - protected function barcode_pharmacode($code) { - $seq = ''; - $code = intval($code); - while ($code > 0) { - if (($code % 2) == 0) { - $seq .= '11100'; - $code -= 2; - } else { - $seq .= '100'; - $code -= 1; - } - $code /= 2; - } - $seq = substr($seq, 0, -2); - $seq = strrev($seq); - $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); - return $this->binseq_to_array($seq, $bararray); - } - - /** - * Pharmacode two-track - * Contains digits (0 to 9) - * @param string $code code to represent. - * @return array barcode representation. - * @protected - */ - protected function barcode_pharmacode2t($code) { - $seq = ''; - $code = intval($code); - do { - switch ($code % 3) { - case 0: { - $seq .= '3'; - $code = ($code - 3) / 3; - break; - } - case 1: { - $seq .= '1'; - $code = ($code - 1) / 3; - break; - } - case 2: { - $seq .= '2'; - $code = ($code - 2) / 3; - break; - } - } - } while($code != 0); - $seq = strrev($seq); - $k = 0; - $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 2, 'bcode' => array()); - $len = strlen($seq); - for ($i = 0; $i < $len; ++$i) { - switch ($seq[$i]) { - case '1': { - $p = 1; - $h = 1; - break; - } - case '2': { - $p = 0; - $h = 1; - break; - } - case '3': { - $p = 0; - $h = 2; - break; - } - } - $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p); - $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0); - $bararray['maxw'] += 2; - } - unset($bararray['bcode'][($k - 1)]); - --$bararray['maxw']; - return $bararray; - } - - /** - * IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200 - * (requires PHP bcmath extension) - * Intelligent Mail barcode is a 65-bar code for use on mail in the United States. - * The fields are described as follows:<ul><li>The Barcode Identifier shall be assigned by USPS to encode the presort identification that is currently printed in human readable form on the optional endorsement line (OEL) as well as for future USPS use. This shall be two digits, with the second digit in the range of 0–4. The allowable encoding ranges shall be 00–04, 10–14, 20–24, 30–34, 40–44, 50–54, 60–64, 70–74, 80–84, and 90–94.</li><li>The Service Type Identifier shall be assigned by USPS for any combination of services requested on the mailpiece. The allowable encoding range shall be 000http://it2.php.net/manual/en/function.dechex.php–999. Each 3-digit value shall correspond to a particular mail class with a particular combination of service(s). Each service program, such as OneCode Confirm and OneCode ACS, shall provide the list of Service Type Identifier values.</li><li>The Mailer or Customer Identifier shall be assigned by USPS as a unique, 6 or 9 digit number that identifies a business entity. The allowable encoding range for the 6 digit Mailer ID shall be 000000- 899999, while the allowable encoding range for the 9 digit Mailer ID shall be 900000000-999999999.</li><li>The Serial or Sequence Number shall be assigned by the mailer for uniquely identifying and tracking mailpieces. The allowable encoding range shall be 000000000–999999999 when used with a 6 digit Mailer ID and 000000-999999 when used with a 9 digit Mailer ID. e. The Delivery Point ZIP Code shall be assigned by the mailer for routing the mailpiece. This shall replace POSTNET for routing the mailpiece to its final delivery point. The length may be 0, 5, 9, or 11 digits. The allowable encoding ranges shall be no ZIP Code, 00000–99999, 000000000–999999999, and 00000000000–99999999999.</li></ul> - * @param string $code code to print, separate the ZIP (routing code) from the rest using a minus char '-' (BarcodeID_ServiceTypeID_MailerID_SerialNumber-RoutingCode) - * @return array barcode representation. - * @protected - */ - protected function barcode_imb($code) { - $asc_chr = array(4,0,2,6,3,5,1,9,8,7,1,2,0,6,4,8,2,9,5,3,0,1,3,7,4,6,8,9,2,0,5,1,9,4,3,8,6,7,1,2,4,3,9,5,7,8,3,0,2,1,4,0,9,1,7,0,2,4,6,3,7,1,9,5,8); - $dsc_chr = array(7,1,9,5,8,0,2,4,6,3,5,8,9,7,3,0,6,1,7,4,6,8,9,2,5,1,7,5,4,3,8,7,6,0,2,5,4,9,3,0,1,6,8,2,0,4,5,9,6,7,5,2,6,3,8,5,1,9,8,7,4,0,2,6,3); - $asc_pos = array(3,0,8,11,1,12,8,11,10,6,4,12,2,7,9,6,7,9,2,8,4,0,12,7,10,9,0,7,10,5,7,9,6,8,2,12,1,4,2,0,1,5,4,6,12,1,0,9,4,7,5,10,2,6,9,11,2,12,6,7,5,11,0,3,2); - $dsc_pos = array(2,10,12,5,9,1,5,4,3,9,11,5,10,1,6,3,4,1,10,0,2,11,8,6,1,12,3,8,6,4,4,11,0,6,1,9,11,5,3,7,3,10,7,11,8,2,10,3,5,8,0,3,12,11,8,4,5,1,3,0,7,12,9,8,10); - $code_arr = explode('-', $code); - $tracking_number = $code_arr[0]; - if (isset($code_arr[1])) { - $routing_code = $code_arr[1]; - } else { - $routing_code = ''; - } - // Conversion of Routing Code - switch (strlen($routing_code)) { - case 0: { - $binary_code = 0; - break; - } - case 5: { - $binary_code = bcadd($routing_code, '1'); - break; - } - case 9: { - $binary_code = bcadd($routing_code, '100001'); - break; - } - case 11: { - $binary_code = bcadd($routing_code, '1000100001'); - break; - } - default: { - return false; - break; - } - } - $binary_code = bcmul($binary_code, 10); - $binary_code = bcadd($binary_code, $tracking_number[0]); - $binary_code = bcmul($binary_code, 5); - $binary_code = bcadd($binary_code, $tracking_number[1]); - $binary_code .= substr($tracking_number, 2, 18); - // convert to hexadecimal - $binary_code = $this->dec_to_hex($binary_code); - // pad to get 13 bytes - $binary_code = str_pad($binary_code, 26, '0', STR_PAD_LEFT); - // convert string to array of bytes - $binary_code_arr = chunk_split($binary_code, 2, "\r"); - $binary_code_arr = substr($binary_code_arr, 0, -1); - $binary_code_arr = explode("\r", $binary_code_arr); - // calculate frame check sequence - $fcs = $this->imb_crc11fcs($binary_code_arr); - // exclude first 2 bits from first byte - $first_byte = sprintf('%2s', dechex((hexdec($binary_code_arr[0]) << 2) >> 2)); - $binary_code_102bit = $first_byte.substr($binary_code, 2); - // convert binary data to codewords - $codewords = array(); - $data = $this->hex_to_dec($binary_code_102bit); - $codewords[0] = bcmod($data, 636) * 2; - $data = bcdiv($data, 636); - for ($i = 1; $i < 9; ++$i) { - $codewords[$i] = bcmod($data, 1365); - $data = bcdiv($data, 1365); - } - $codewords[9] = $data; - if (($fcs >> 10) == 1) { - $codewords[9] += 659; - } - // generate lookup tables - $table2of13 = $this->imb_tables(2, 78); - $table5of13 = $this->imb_tables(5, 1287); - // convert codewords to characters - $characters = array(); - $bitmask = 512; - foreach($codewords as $k => $val) { - if ($val <= 1286) { - $chrcode = $table5of13[$val]; - } else { - $chrcode = $table2of13[($val - 1287)]; - } - if (($fcs & $bitmask) > 0) { - // bitwise invert - $chrcode = ((~$chrcode) & 8191); - } - $characters[] = $chrcode; - $bitmask /= 2; - } - $characters = array_reverse($characters); - // build bars - $k = 0; - $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 3, 'bcode' => array()); - for ($i = 0; $i < 65; ++$i) { - $asc = (($characters[$asc_chr[$i]] & pow(2, $asc_pos[$i])) > 0); - $dsc = (($characters[$dsc_chr[$i]] & pow(2, $dsc_pos[$i])) > 0); - if ($asc AND $dsc) { - // full bar (F) - $p = 0; - $h = 3; - } elseif ($asc) { - // ascender (A) - $p = 0; - $h = 2; - } elseif ($dsc) { - // descender (D) - $p = 1; - $h = 2; - } else { - // tracker (T) - $p = 1; - $h = 1; - } - $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p); - $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0); - $bararray['maxw'] += 2; - } - unset($bararray['bcode'][($k - 1)]); - --$bararray['maxw']; - return $bararray; - } - - /** - * IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200 - * - * @param string $code pre-formatted IMB barcode (65 chars "FADT") - * @return array barcode representation. - * @protected - */ - protected function barcode_imb_pre($code) { - if (!preg_match('/^[fadtFADT]{65}$/', $code) == 1) { - return false; - } - $characters = str_split(strtolower($code), 1); - // build bars - $k = 0; - $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 3, 'bcode' => array()); - for ($i = 0; $i < 65; ++$i) { - switch($characters[$i]) { - case 'f': { - // full bar - $p = 0; - $h = 3; - break; - } - case 'a': { - // ascender - $p = 0; - $h = 2; - break; - } - case 'd': { - // descender - $p = 1; - $h = 2; - break; - } - case 't': { - // tracker (short) - $p = 1; - $h = 1; - break; - } - } - $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p); - $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0); - $bararray['maxw'] += 2; - } - unset($bararray['bcode'][($k - 1)]); - --$bararray['maxw']; - return $bararray; - } - - /** - * Convert large integer number to hexadecimal representation. - * (requires PHP bcmath extension) - * @param string $number number to convert specified as a string - * @return string hexadecimal representation - */ - public function dec_to_hex($number) { - $i = 0; - $hex = array(); - if($number == 0) { - return '00'; - } - while($number > 0) { - if($number == 0) { - array_push($hex, '0'); - } else { - array_push($hex, strtoupper(dechex(bcmod($number, '16')))); - $number = bcdiv($number, '16', 0); - } - } - $hex = array_reverse($hex); - return implode($hex); - } - - /** - * Convert large hexadecimal number to decimal representation (string). - * (requires PHP bcmath extension) - * @param string $hex hexadecimal number to convert specified as a string - * @return string hexadecimal representation - */ - public function hex_to_dec($hex) { - $dec = 0; - $bitval = 1; - $len = strlen($hex); - for($pos = ($len - 1); $pos >= 0; --$pos) { - $dec = bcadd($dec, bcmul(hexdec($hex[$pos]), $bitval)); - $bitval = bcmul($bitval, 16); - } - return $dec; - } - - /** - * Intelligent Mail Barcode calculation of Frame Check Sequence - * @param string $code_arr array of hexadecimal values (13 bytes holding 102 bits right justified). - * @return int 11 bit Frame Check Sequence as integer (decimal base) - * @protected - */ - protected function imb_crc11fcs($code_arr) { - $genpoly = 0x0F35; // generator polynomial - $fcs = 0x07FF; // Frame Check Sequence - // do most significant byte skipping the 2 most significant bits - $data = hexdec($code_arr[0]) << 5; - for ($bit = 2; $bit < 8; ++$bit) { - if (($fcs ^ $data) & 0x400) { - $fcs = ($fcs << 1) ^ $genpoly; - } else { - $fcs = ($fcs << 1); - } - $fcs &= 0x7FF; - $data <<= 1; - } - // do rest of bytes - for ($byte = 1; $byte < 13; ++$byte) { - $data = hexdec($code_arr[$byte]) << 3; - for ($bit = 0; $bit < 8; ++$bit) { - if (($fcs ^ $data) & 0x400) { - $fcs = ($fcs << 1) ^ $genpoly; - } else { - $fcs = ($fcs << 1); - } - $fcs &= 0x7FF; - $data <<= 1; - } - } - return $fcs; - } - - /** - * Reverse unsigned short value - * @param int $num value to reversr - * @return int reversed value - * @protected - */ - protected function imb_reverse_us($num) { - $rev = 0; - for ($i = 0; $i < 16; ++$i) { - $rev <<= 1; - $rev |= ($num & 1); - $num >>= 1; - } - return $rev; - } - - /** - * generate Nof13 tables used for Intelligent Mail Barcode - * @param int $n is the type of table: 2 for 2of13 table, 5 for 5of13table - * @param int $size size of table (78 for n=2 and 1287 for n=5) - * @return array requested table - * @protected - */ - protected function imb_tables($n, $size) { - $table = array(); - $lli = 0; // LUT lower index - $lui = $size - 1; // LUT upper index - for ($count = 0; $count < 8192; ++$count) { - $bit_count = 0; - for ($bit_index = 0; $bit_index < 13; ++$bit_index) { - $bit_count += intval(($count & (1 << $bit_index)) != 0); - } - // if we don't have the right number of bits on, go on to the next value - if ($bit_count == $n) { - $reverse = ($this->imb_reverse_us($count) >> 3); - // if the reverse is less than count, we have already visited this pair before - if ($reverse >= $count) { - // If count is symmetric, place it at the first free slot from the end of the list. - // Otherwise, place it at the first free slot from the beginning of the list AND place $reverse ath the next free slot from the beginning of the list - if ($reverse == $count) { - $table[$lui] = $count; - --$lui; - } else { - $table[$lli] = $count; - ++$lli; - $table[$lli] = $reverse; - ++$lli; - } - } - } - } - return $table; - } - -} // end of class -//============================================================+ -// END OF FILE -//============================================================+ diff --git a/lib/combodo/tcpdf/tcpdf_barcodes_2d.php b/lib/combodo/tcpdf/tcpdf_barcodes_2d.php deleted file mode 100644 index 730361bd8..000000000 --- a/lib/combodo/tcpdf/tcpdf_barcodes_2d.php +++ /dev/null @@ -1,349 +0,0 @@ -<?php -//============================================================+ -// File name : tcpdf_barcodes_2d.php -// Version : 1.0.015 -// Begin : 2009-04-07 -// Last Update : 2014-05-20 -// Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com -// License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html) -// ------------------------------------------------------------------- -// Copyright (C) 2009-2014 Nicola Asuni - Tecnick.com LTD -// -// This file is part of TCPDF software library. -// -// TCPDF is free software: you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// TCPDF is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with TCPDF. If not, see <http://www.gnu.org/licenses/>. -// -// See LICENSE.TXT file for more information. -// ------------------------------------------------------------------- -// -// Description : PHP class to creates array representations for -// 2D barcodes to be used with TCPDF. -// -//============================================================+ - -/** - * @file - * PHP class to creates array representations for 2D barcodes to be used with TCPDF. - * @package com.tecnick.tcpdf - * @author Nicola Asuni - * @version 1.0.015 - */ - -/** - * @class TCPDF2DBarcode - * PHP class to creates array representations for 2D barcodes to be used with TCPDF (http://www.tcpdf.org). - * @package com.tecnick.tcpdf - * @version 1.0.015 - * @author Nicola Asuni - */ -class TCPDF2DBarcode { - - /** - * Array representation of barcode. - * @protected - */ - protected $barcode_array = array(); - - /** - * This is the class constructor. - * Return an array representations for 2D barcodes:<ul> - * <li>$arrcode['code'] code to be printed on text label</li> - * <li>$arrcode['num_rows'] required number of rows</li> - * <li>$arrcode['num_cols'] required number of columns</li> - * <li>$arrcode['bcode'][$r][$c] value of the cell is $r row and $c column (0 = transparent, 1 = black)</li></ul> - * @param string $code code to print - * @param string $type type of barcode: <ul><li>DATAMATRIX : Datamatrix (ISO/IEC 16022)</li><li>PDF417 : PDF417 (ISO/IEC 15438:2006)</li><li>PDF417,a,e,t,s,f,o0,o1,o2,o3,o4,o5,o6 : PDF417 with parameters: a = aspect ratio (width/height); e = error correction level (0-8); t = total number of macro segments; s = macro segment index (0-99998); f = file ID; o0 = File Name (text); o1 = Segment Count (numeric); o2 = Time Stamp (numeric); o3 = Sender (text); o4 = Addressee (text); o5 = File Size (numeric); o6 = Checksum (numeric). NOTES: Parameters t, s and f are required for a Macro Control Block, all other parameters are optional. To use a comma character ',' on text options, replace it with the character 255: "\xff".</li><li>QRCODE : QRcode Low error correction</li><li>QRCODE,L : QRcode Low error correction</li><li>QRCODE,M : QRcode Medium error correction</li><li>QRCODE,Q : QRcode Better error correction</li><li>QRCODE,H : QR-CODE Best error correction</li><li>RAW: raw mode - comma-separad list of array rows</li><li>RAW2: raw mode - array rows are surrounded by square parenthesis.</li><li>TEST : Test matrix</li></ul> - */ - public function __construct($code, $type) { - $this->setBarcode($code, $type); - } - - /** - * Return an array representations of barcode. - * @return array - */ - public function getBarcodeArray() { - return $this->barcode_array; - } - - /** - * Send barcode as SVG image object to the standard output. - * @param int $w Width of a single rectangle element in user units. - * @param int $h Height of a single rectangle element in user units. - * @param string $color Foreground color (in SVG format) for bar elements (background is transparent). - * @public - */ - public function getBarcodeSVG($w=3, $h=3, $color='black') { - // send headers - $code = $this->getBarcodeSVGcode($w, $h, $color); - header('Content-Type: application/svg+xml'); - header('Cache-Control: public, must-revalidate, max-age=0'); // HTTP/1.1 - header('Pragma: public'); - header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past - header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); - header('Content-Disposition: inline; filename="'.md5($code).'.svg";'); - //header('Content-Length: '.strlen($code)); - echo $code; - } - - /** - * Return a SVG string representation of barcode. - * @param int $w Width of a single rectangle element in user units. - * @param int $h Height of a single rectangle element in user units. - * @param string $color Foreground color (in SVG format) for bar elements (background is transparent). - * @return string SVG code. - * @public - */ - public function getBarcodeSVGcode($w=3, $h=3, $color='black') { - // replace table for special characters - $repstr = array("\0" => '', '&' => '&amp;', '<' => '&lt;', '>' => '&gt;'); - $svg = '<'.'?'.'xml version="1.0" standalone="no"'.'?'.'>'."\n"; - $svg .= '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'."\n"; - $svg .= '<svg width="'.round(($this->barcode_array['num_cols'] * $w), 3).'" height="'.round(($this->barcode_array['num_rows'] * $h), 3).'" version="1.1" xmlns="http://www.w3.org/2000/svg">'."\n"; - $svg .= "\t".'<desc>'.strtr($this->barcode_array['code'], $repstr).'</desc>'."\n"; - $svg .= "\t".'<g id="elements" fill="'.$color.'" stroke="none">'."\n"; - // print barcode elements - $y = 0; - // for each row - for ($r = 0; $r < $this->barcode_array['num_rows']; ++$r) { - $x = 0; - // for each column - for ($c = 0; $c < $this->barcode_array['num_cols']; ++$c) { - if ($this->barcode_array['bcode'][$r][$c] == 1) { - // draw a single barcode cell - $svg .= "\t\t".'<rect x="'.$x.'" y="'.$y.'" width="'.$w.'" height="'.$h.'" />'."\n"; - } - $x += $w; - } - $y += $h; - } - $svg .= "\t".'</g>'."\n"; - $svg .= '</svg>'."\n"; - return $svg; - } - - /** - * Return an HTML representation of barcode. - * @param int $w Width of a single rectangle element in pixels. - * @param int $h Height of a single rectangle element in pixels. - * @param string $color Foreground color for bar elements (background is transparent). - * @return string HTML code. - * @public - */ - public function getBarcodeHTML($w=10, $h=10, $color='black') { - $html = '<div style="font-size:0;position:relative;width:'.($w * $this->barcode_array['num_cols']).'px;height:'.($h * $this->barcode_array['num_rows']).'px;">'."\n"; - // print barcode elements - $y = 0; - // for each row - for ($r = 0; $r < $this->barcode_array['num_rows']; ++$r) { - $x = 0; - // for each column - for ($c = 0; $c < $this->barcode_array['num_cols']; ++$c) { - if ($this->barcode_array['bcode'][$r][$c] == 1) { - // draw a single barcode cell - $html .= '<div style="background-color:'.$color.';width:'.$w.'px;height:'.$h.'px;position:absolute;left:'.$x.'px;top:'.$y.'px;">&nbsp;</div>'."\n"; - } - $x += $w; - } - $y += $h; - } - $html .= '</div>'."\n"; - return $html; - } - - /** - * Send a PNG image representation of barcode (requires GD or Imagick library). - * @param int $w Width of a single rectangle element in pixels. - * @param int $h Height of a single rectangle element in pixels. - * @param array $color RGB (0-255) foreground color for bar elements (background is transparent). - * @public - */ - public function getBarcodePNG($w=3, $h=3, $color=array(0,0,0)) { - $data = $this->getBarcodePngData($w, $h, $color); - // send headers - header('Content-Type: image/png'); - header('Cache-Control: public, must-revalidate, max-age=0'); // HTTP/1.1 - header('Pragma: public'); - header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past - header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); - //header('Content-Length: '.strlen($data)); - echo $data; - - } - - /** - * Return a PNG image representation of barcode (requires GD or Imagick library). - * @param int $w Width of a single rectangle element in pixels. - * @param int $h Height of a single rectangle element in pixels. - * @param array $color RGB (0-255) foreground color for bar elements (background is transparent). - * @return string|Imagick|false image or false in case of error. - * @public - */ - public function getBarcodePngData($w=3, $h=3, $color=array(0,0,0)) { - // calculate image size - $width = ($this->barcode_array['num_cols'] * $w); - $height = ($this->barcode_array['num_rows'] * $h); - if (function_exists('imagecreate')) { - // GD library - $imagick = false; - $png = imagecreate($width, $height); - $bgcol = imagecolorallocate($png, 255, 255, 255); - imagecolortransparent($png, $bgcol); - $fgcol = imagecolorallocate($png, $color[0], $color[1], $color[2]); - } elseif (extension_loaded('imagick')) { - $imagick = true; - $bgcol = new imagickpixel('rgb(255,255,255'); - $fgcol = new imagickpixel('rgb('.$color[0].','.$color[1].','.$color[2].')'); - $png = new Imagick(); - $png->newImage($width, $height, 'none', 'png'); - $bar = new imagickdraw(); - $bar->setfillcolor($fgcol); - } else { - return false; - } - // print barcode elements - $y = 0; - // for each row - for ($r = 0; $r < $this->barcode_array['num_rows']; ++$r) { - $x = 0; - // for each column - for ($c = 0; $c < $this->barcode_array['num_cols']; ++$c) { - if ($this->barcode_array['bcode'][$r][$c] == 1) { - // draw a single barcode cell - if ($imagick) { - $bar->rectangle($x, $y, ($x + $w - 1), ($y + $h - 1)); - } else { - imagefilledrectangle($png, $x, $y, ($x + $w - 1), ($y + $h - 1), $fgcol); - } - } - $x += $w; - } - $y += $h; - } - if ($imagick) { - $png->drawimage($bar); - return $png; - } else { - ob_start(); - imagepng($png); - $imagedata = ob_get_clean(); - imagedestroy($png); - return $imagedata; - } - } - - /** - * Set the barcode. - * @param string $code code to print - * @param string $type type of barcode: <ul><li>DATAMATRIX : Datamatrix (ISO/IEC 16022)</li><li>PDF417 : PDF417 (ISO/IEC 15438:2006)</li><li>PDF417,a,e,t,s,f,o0,o1,o2,o3,o4,o5,o6 : PDF417 with parameters: a = aspect ratio (width/height); e = error correction level (0-8); t = total number of macro segments; s = macro segment index (0-99998); f = file ID; o0 = File Name (text); o1 = Segment Count (numeric); o2 = Time Stamp (numeric); o3 = Sender (text); o4 = Addressee (text); o5 = File Size (numeric); o6 = Checksum (numeric). NOTES: Parameters t, s and f are required for a Macro Control Block, all other parameters are optional. To use a comma character ',' on text options, replace it with the character 255: "\xff".</li><li>QRCODE : QRcode Low error correction</li><li>QRCODE,L : QRcode Low error correction</li><li>QRCODE,M : QRcode Medium error correction</li><li>QRCODE,Q : QRcode Better error correction</li><li>QRCODE,H : QR-CODE Best error correction</li><li>RAW: raw mode - comma-separad list of array rows</li><li>RAW2: raw mode - array rows are surrounded by square parenthesis.</li><li>TEST : Test matrix</li></ul> - * @return void - */ - public function setBarcode($code, $type) { - $mode = explode(',', $type); - $qrtype = strtoupper($mode[0]); - switch ($qrtype) { - case 'DATAMATRIX': { // DATAMATRIX (ISO/IEC 16022) - require_once(dirname(__FILE__).'/include/barcodes/datamatrix.php'); - $qrcode = new Datamatrix($code); - $this->barcode_array = $qrcode->getBarcodeArray(); - $this->barcode_array['code'] = $code; - break; - } - case 'PDF417': { // PDF417 (ISO/IEC 15438:2006) - require_once(dirname(__FILE__).'/include/barcodes/pdf417.php'); - if (!isset($mode[1]) OR ($mode[1] === '')) { - $aspectratio = 2; // default aspect ratio (width / height) - } else { - $aspectratio = floatval($mode[1]); - } - if (!isset($mode[2]) OR ($mode[2] === '')) { - $ecl = -1; // default error correction level (auto) - } else { - $ecl = intval($mode[2]); - } - // set macro block - $macro = array(); - if (isset($mode[3]) AND ($mode[3] !== '') AND isset($mode[4]) AND ($mode[4] !== '') AND isset($mode[5]) AND ($mode[5] !== '')) { - $macro['segment_total'] = intval($mode[3]); - $macro['segment_index'] = intval($mode[4]); - $macro['file_id'] = strtr($mode[5], "\xff", ','); - for ($i = 0; $i < 7; ++$i) { - $o = $i + 6; - if (isset($mode[$o]) AND ($mode[$o] !== '')) { - // add option - $macro['option_'.$i] = strtr($mode[$o], "\xff", ','); - } - } - } - $qrcode = new PDF417($code, $ecl, $aspectratio, $macro); - $this->barcode_array = $qrcode->getBarcodeArray(); - $this->barcode_array['code'] = $code; - break; - } - case 'QRCODE': { // QR-CODE - require_once(dirname(__FILE__).'/include/barcodes/qrcode.php'); - if (!isset($mode[1]) OR (!in_array($mode[1],array('L','M','Q','H')))) { - $mode[1] = 'L'; // Ddefault: Low error correction - } - $qrcode = new QRcode($code, strtoupper($mode[1])); - $this->barcode_array = $qrcode->getBarcodeArray(); - $this->barcode_array['code'] = $code; - break; - } - case 'RAW': - case 'RAW2': { // RAW MODE - // remove spaces - $code = preg_replace('/[\s]*/si', '', $code); - if (strlen($code) < 3) { - break; - } - if ($qrtype == 'RAW') { - // comma-separated rows - $rows = explode(',', $code); - } else { // RAW2 - // rows enclosed in square parentheses - $code = substr($code, 1, -1); - $rows = explode('][', $code); - } - $this->barcode_array['num_rows'] = count($rows); - $this->barcode_array['num_cols'] = strlen($rows[0]); - $this->barcode_array['bcode'] = array(); - foreach ($rows as $r) { - $this->barcode_array['bcode'][] = str_split($r, 1); - } - $this->barcode_array['code'] = $code; - break; - } - case 'TEST': { // TEST MODE - $this->barcode_array['num_rows'] = 5; - $this->barcode_array['num_cols'] = 15; - $this->barcode_array['bcode'] = array( - array(1,1,1,0,1,1,1,0,1,1,1,0,1,1,1), - array(0,1,0,0,1,0,0,0,1,0,0,0,0,1,0), - array(0,1,0,0,1,1,0,0,1,1,1,0,0,1,0), - array(0,1,0,0,1,0,0,0,0,0,1,0,0,1,0), - array(0,1,0,0,1,1,1,0,1,1,1,0,0,1,0)); - $this->barcode_array['code'] = $code; - break; - } - default: { - $this->barcode_array = array(); - } - } - } -} // end of class - -//============================================================+ -// END OF FILE -//============================================================+ diff --git a/lib/combodo/tcpdf/tcpdf_import.php b/lib/combodo/tcpdf/tcpdf_import.php deleted file mode 100644 index cc6fda780..000000000 --- a/lib/combodo/tcpdf/tcpdf_import.php +++ /dev/null @@ -1,104 +0,0 @@ -<?php -//============================================================+ -// File name : tcpdf_import.php -// Version : 1.0.001 -// Begin : 2011-05-23 -// Last Update : 2013-09-17 -// Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com -// License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html) -// ------------------------------------------------------------------- -// Copyright (C) 2011-2013 Nicola Asuni - Tecnick.com LTD -// -// This file is part of TCPDF software library. -// -// TCPDF is free software: you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// TCPDF is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// -// You should have received a copy of the License -// along with TCPDF. If not, see -// <http://www.tecnick.com/pagefiles/tcpdf/LICENSE.TXT>. -// -// See LICENSE.TXT file for more information. -// ------------------------------------------------------------------- -// -// Description : This is a PHP class extension of the TCPDF library to -// import existing PDF documents. -// -//============================================================+ - -/** - * @file - * !!! THIS CLASS IS UNDER DEVELOPMENT !!! - * This is a PHP class extension of the TCPDF (http://www.tcpdf.org) library to import existing PDF documents.<br> - * @package com.tecnick.tcpdf - * @author Nicola Asuni - * @version 1.0.001 - */ - -// include the TCPDF class -require_once(dirname(__FILE__).'/tcpdf.php'); -// include PDF parser class -require_once(dirname(__FILE__).'/tcpdf_parser.php'); - -/** - * @class TCPDF_IMPORT - * !!! THIS CLASS IS UNDER DEVELOPMENT !!! - * PHP class extension of the TCPDF (http://www.tcpdf.org) library to import existing PDF documents.<br> - * @package com.tecnick.tcpdf - * @brief PHP class extension of the TCPDF library to import existing PDF documents. - * @version 1.0.001 - * @author Nicola Asuni - info@tecnick.com - */ -class TCPDF_IMPORT extends TCPDF { - - /** - * Import an existing PDF document - * @param string $filename Filename of the PDF document to import. - * @return true in case of success, false otherwise - * @public - * @since 1.0.000 (2011-05-24) - */ - public function importPDF($filename) { - // load document - $rawdata = file_get_contents($filename); - if ($rawdata === false) { - $this->Error('Unable to get the content of the file: '.$filename); - } - // configuration parameters for parser - $cfg = array( - 'die_for_errors' => false, - 'ignore_filter_decoding_errors' => true, - 'ignore_missing_filter_decoders' => true, - ); - try { - // parse PDF data - $pdf = new TCPDF_PARSER($rawdata, $cfg); - } catch (Exception $e) { - die($e->getMessage()); - } - // get the parsed data - $data = $pdf->getParsedData(); - // release some memory - unset($rawdata); - - // ... - - - print_r($data); // DEBUG - - - unset($pdf); - } - -} // END OF CLASS - -//============================================================+ -// END OF FILE -//============================================================+ diff --git a/lib/combodo/tcpdf/tcpdf_parser.php b/lib/combodo/tcpdf/tcpdf_parser.php deleted file mode 100644 index 4156230a3..000000000 --- a/lib/combodo/tcpdf/tcpdf_parser.php +++ /dev/null @@ -1,815 +0,0 @@ -<?php -//============================================================+ -// File name : tcpdf_parser.php -// Version : 1.0.16 -// Begin : 2011-05-23 -// Last Update : 2015-04-28 -// Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com -// License : http://www.tecnick.com/pagefiles/tcpdf/LICENSE.TXT GNU-LGPLv3 -// ------------------------------------------------------------------- -// Copyright (C) 2011-2015 Nicola Asuni - Tecnick.com LTD -// -// This file is part of TCPDF software library. -// -// TCPDF is free software: you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// TCPDF is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// -// You should have received a copy of the License -// along with TCPDF. If not, see -// <http://www.tecnick.com/pagefiles/tcpdf/LICENSE.TXT>. -// -// See LICENSE.TXT file for more information. -// ------------------------------------------------------------------- -// -// Description : This is a PHP class for parsing PDF documents. -// -//============================================================+ - -/** - * @file - * This is a PHP class for parsing PDF documents.<br> - * @package com.tecnick.tcpdf - * @author Nicola Asuni - * @version 1.0.15 - */ - -// include class for decoding filters -require_once(dirname(__FILE__).'/include/tcpdf_filters.php'); - -/** - * @class TCPDF_PARSER - * This is a PHP class for parsing PDF documents.<br> - * @package com.tecnick.tcpdf - * @brief This is a PHP class for parsing PDF documents.. - * @version 1.0.15 - * @author Nicola Asuni - info@tecnick.com - */ -class TCPDF_PARSER { - - /** - * Raw content of the PDF document. - * @private - */ - private $pdfdata = ''; - - /** - * XREF data. - * @protected - */ - protected $xref = array(); - - /** - * Array of PDF objects. - * @protected - */ - protected $objects = array(); - - /** - * Class object for decoding filters. - * @private - */ - private $FilterDecoders; - - /** - * Array of configuration parameters. - * @private - */ - private $cfg = array( - 'die_for_errors' => false, - 'ignore_filter_decoding_errors' => true, - 'ignore_missing_filter_decoders' => true, - ); - -// ----------------------------------------------------------------------------- - - /** - * Parse a PDF document an return an array of objects. - * @param string $data PDF data to parse. - * @param array $cfg Array of configuration parameters: - * 'die_for_errors' : if true termitate the program execution in case of error, otherwise thows an exception; - * 'ignore_filter_decoding_errors' : if true ignore filter decoding errors; - * 'ignore_missing_filter_decoders' : if true ignore missing filter decoding errors. - * @public - * @since 1.0.000 (2011-05-24) - */ - public function __construct($data, $cfg=array()) { - if (empty($data)) { - $this->Error('Empty PDF data.'); - } - // find the pdf header starting position - if (($trimpos = strpos($data, '%PDF-')) === FALSE) { - $this->Error('Invalid PDF data: missing %PDF header.'); - } - // get PDF content string - $this->pdfdata = substr($data, $trimpos); - // get length - $pdflen = strlen($this->pdfdata); - // set configuration parameters - $this->setConfig($cfg); - // get xref and trailer data - $this->xref = $this->getXrefData(); - // parse all document objects - $this->objects = array(); - foreach ($this->xref['xref'] as $obj => $offset) { - if (!isset($this->objects[$obj]) AND ($offset > 0)) { - // decode objects with positive offset - $this->objects[$obj] = $this->getIndirectObject($obj, $offset, true); - } - } - // release some memory - unset($this->pdfdata); - $this->pdfdata = ''; - } - - /** - * Set the configuration parameters. - * @param array $cfg Array of configuration parameters: - * 'die_for_errors' : if true termitate the program execution in case of error, otherwise thows an exception; - * 'ignore_filter_decoding_errors' : if true ignore filter decoding errors; - * 'ignore_missing_filter_decoders' : if true ignore missing filter decoding errors. - * @public - */ - protected function setConfig($cfg) { - if (isset($cfg['die_for_errors'])) { - $this->cfg['die_for_errors'] = !!$cfg['die_for_errors']; - } - if (isset($cfg['ignore_filter_decoding_errors'])) { - $this->cfg['ignore_filter_decoding_errors'] = !!$cfg['ignore_filter_decoding_errors']; - } - if (isset($cfg['ignore_missing_filter_decoders'])) { - $this->cfg['ignore_missing_filter_decoders'] = !!$cfg['ignore_missing_filter_decoders']; - } - } - - /** - * Return an array of parsed PDF document objects. - * @return array Array of parsed PDF document objects. - * @public - * @since 1.0.000 (2011-06-26) - */ - public function getParsedData() { - return array($this->xref, $this->objects); - } - - /** - * Get Cross-Reference (xref) table and trailer data from PDF document data. - * @param int $offset xref offset (if know). - * @param array $xref previous xref array (if any). - * @return array containing xref and trailer data. - * @protected - * @since 1.0.000 (2011-05-24) - */ - protected function getXrefData($offset=0, $xref=array()) { - if ($offset == 0) { - // find last startxref - if (preg_match_all('/[\r\n]startxref[\s]*[\r\n]+([0-9]+)[\s]*[\r\n]+%%EOF/i', $this->pdfdata, $matches, PREG_SET_ORDER, $offset) == 0) { - $this->Error('Unable to find startxref'); - } - $matches = array_pop($matches); - $startxref = $matches[1]; - } elseif (strpos($this->pdfdata, 'xref', $offset) == $offset) { - // Already pointing at the xref table - $startxref = $offset; - } elseif (preg_match('/([0-9]+[\s][0-9]+[\s]obj)/i', $this->pdfdata, $matches, PREG_OFFSET_CAPTURE, $offset)) { - // Cross-Reference Stream object - $startxref = $offset; - } elseif (preg_match('/[\r\n]startxref[\s]*[\r\n]+([0-9]+)[\s]*[\r\n]+%%EOF/i', $this->pdfdata, $matches, PREG_OFFSET_CAPTURE, $offset)) { - // startxref found - $startxref = $matches[1][0]; - } else { - $this->Error('Unable to find startxref'); - } - // check xref position - if (strpos($this->pdfdata, 'xref', $startxref) == $startxref) { - // Cross-Reference - $xref = $this->decodeXref($startxref, $xref); - } else { - // Cross-Reference Stream - $xref = $this->decodeXrefStream($startxref, $xref); - } - if (empty($xref)) { - $this->Error('Unable to find xref'); - } - return $xref; - } - - /** - * Decode the Cross-Reference section - * @param int $startxref Offset at which the xref section starts (position of the 'xref' keyword). - * @param array $xref Previous xref array (if any). - * @return array containing xref and trailer data. - * @protected - * @since 1.0.000 (2011-06-20) - */ - protected function decodeXref($startxref, $xref=array()) { - $startxref += 4; // 4 is the length of the word 'xref' - // skip initial white space chars: \x00 null (NUL), \x09 horizontal tab (HT), \x0A line feed (LF), \x0C form feed (FF), \x0D carriage return (CR), \x20 space (SP) - $offset = $startxref + strspn($this->pdfdata, "\x00\x09\x0a\x0c\x0d\x20", $startxref); - // initialize object number - $obj_num = 0; - // search for cross-reference entries or subsection - while (preg_match('/([0-9]+)[\x20]([0-9]+)[\x20]?([nf]?)(\r\n|[\x20]?[\r\n])/', $this->pdfdata, $matches, PREG_OFFSET_CAPTURE, $offset) > 0) { - if ($matches[0][1] != $offset) { - // we are on another section - break; - } - $offset += strlen($matches[0][0]); - if ($matches[3][0] == 'n') { - // create unique object index: [object number]_[generation number] - $index = $obj_num.'_'.intval($matches[2][0]); - // check if object already exist - if (!isset($xref['xref'][$index])) { - // store object offset position - $xref['xref'][$index] = intval($matches[1][0]); - } - ++$obj_num; - } elseif ($matches[3][0] == 'f') { - ++$obj_num; - } else { - // object number (index) - $obj_num = intval($matches[1][0]); - } - } - // get trailer data - if (preg_match('/trailer[\s]*<<(.*)>>/isU', $this->pdfdata, $matches, PREG_OFFSET_CAPTURE, $offset) > 0) { - $trailer_data = $matches[1][0]; - if (!isset($xref['trailer']) OR empty($xref['trailer'])) { - // get only the last updated version - $xref['trailer'] = array(); - // parse trailer_data - if (preg_match('/Size[\s]+([0-9]+)/i', $trailer_data, $matches) > 0) { - $xref['trailer']['size'] = intval($matches[1]); - } - if (preg_match('/Root[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailer_data, $matches) > 0) { - $xref['trailer']['root'] = intval($matches[1]).'_'.intval($matches[2]); - } - if (preg_match('/Encrypt[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailer_data, $matches) > 0) { - $xref['trailer']['encrypt'] = intval($matches[1]).'_'.intval($matches[2]); - } - if (preg_match('/Info[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailer_data, $matches) > 0) { - $xref['trailer']['info'] = intval($matches[1]).'_'.intval($matches[2]); - } - if (preg_match('/ID[\s]*[\[][\s]*[<]([^>]*)[>][\s]*[<]([^>]*)[>]/i', $trailer_data, $matches) > 0) { - $xref['trailer']['id'] = array(); - $xref['trailer']['id'][0] = $matches[1]; - $xref['trailer']['id'][1] = $matches[2]; - } - } - if (preg_match('/Prev[\s]+([0-9]+)/i', $trailer_data, $matches) > 0) { - // get previous xref - $xref = $this->getXrefData(intval($matches[1]), $xref); - } - } else { - $this->Error('Unable to find trailer'); - } - return $xref; - } - - /** - * Decode the Cross-Reference Stream section - * @param int $startxref Offset at which the xref section starts. - * @param array $xref Previous xref array (if any). - * @return array containing xref and trailer data. - * @protected - * @since 1.0.003 (2013-03-16) - */ - protected function decodeXrefStream($startxref, $xref=array()) { - // try to read Cross-Reference Stream - $xrefobj = $this->getRawObject($startxref); - $xrefcrs = $this->getIndirectObject($xrefobj[1], $startxref, true); - if (!isset($xref['trailer']) OR empty($xref['trailer'])) { - // get only the last updated version - $xref['trailer'] = array(); - $filltrailer = true; - } else { - $filltrailer = false; - } - if (!isset($xref['xref'])) { - $xref['xref'] = array(); - } - $valid_crs = false; - $columns = 0; - $sarr = $xrefcrs[0][1]; - if (!is_array($sarr)) { - $sarr = array(); - } - foreach ($sarr as $k => $v) { - if (($v[0] == '/') AND ($v[1] == 'Type') AND (isset($sarr[($k +1)]) AND ($sarr[($k +1)][0] == '/') AND ($sarr[($k +1)][1] == 'XRef'))) { - $valid_crs = true; - } elseif (($v[0] == '/') AND ($v[1] == 'Index') AND (isset($sarr[($k +1)]))) { - // first object number in the subsection - $index_first = intval($sarr[($k +1)][1][0][1]); - // number of entries in the subsection - $index_entries = intval($sarr[($k +1)][1][1][1]); - } elseif (($v[0] == '/') AND ($v[1] == 'Prev') AND (isset($sarr[($k +1)]) AND ($sarr[($k +1)][0] == 'numeric'))) { - // get previous xref offset - $prevxref = intval($sarr[($k +1)][1]); - } elseif (($v[0] == '/') AND ($v[1] == 'W') AND (isset($sarr[($k +1)]))) { - // number of bytes (in the decoded stream) of the corresponding field - $wb = array(); - $wb[0] = intval($sarr[($k +1)][1][0][1]); - $wb[1] = intval($sarr[($k +1)][1][1][1]); - $wb[2] = intval($sarr[($k +1)][1][2][1]); - } elseif (($v[0] == '/') AND ($v[1] == 'DecodeParms') AND (isset($sarr[($k +1)][1]))) { - $decpar = $sarr[($k +1)][1]; - foreach ($decpar as $kdc => $vdc) { - if (($vdc[0] == '/') AND ($vdc[1] == 'Columns') AND (isset($decpar[($kdc +1)]) AND ($decpar[($kdc +1)][0] == 'numeric'))) { - $columns = intval($decpar[($kdc +1)][1]); - } elseif (($vdc[0] == '/') AND ($vdc[1] == 'Predictor') AND (isset($decpar[($kdc +1)]) AND ($decpar[($kdc +1)][0] == 'numeric'))) { - $predictor = intval($decpar[($kdc +1)][1]); - } - } - } elseif ($filltrailer) { - if (($v[0] == '/') AND ($v[1] == 'Size') AND (isset($sarr[($k +1)]) AND ($sarr[($k +1)][0] == 'numeric'))) { - $xref['trailer']['size'] = $sarr[($k +1)][1]; - } elseif (($v[0] == '/') AND ($v[1] == 'Root') AND (isset($sarr[($k +1)]) AND ($sarr[($k +1)][0] == 'objref'))) { - $xref['trailer']['root'] = $sarr[($k +1)][1]; - } elseif (($v[0] == '/') AND ($v[1] == 'Info') AND (isset($sarr[($k +1)]) AND ($sarr[($k +1)][0] == 'objref'))) { - $xref['trailer']['info'] = $sarr[($k +1)][1]; - } elseif (($v[0] == '/') AND ($v[1] == 'Encrypt') AND (isset($sarr[($k +1)]) AND ($sarr[($k +1)][0] == 'objref'))) { - $xref['trailer']['encrypt'] = $sarr[($k +1)][1]; - } elseif (($v[0] == '/') AND ($v[1] == 'ID') AND (isset($sarr[($k +1)]))) { - $xref['trailer']['id'] = array(); - $xref['trailer']['id'][0] = $sarr[($k +1)][1][0][1]; - $xref['trailer']['id'][1] = $sarr[($k +1)][1][1][1]; - } - } - } - // decode data - if ($valid_crs AND isset($xrefcrs[1][3][0])) { - // number of bytes in a row - $rowlen = ($columns + 1); - // convert the stream into an array of integers - $sdata = unpack('C*', $xrefcrs[1][3][0]); - // split the rows - $sdata = array_chunk($sdata, $rowlen); - // initialize decoded array - $ddata = array(); - // initialize first row with zeros - $prev_row = array_fill (0, $rowlen, 0); - // for each row apply PNG unpredictor - foreach ($sdata as $k => $row) { - // initialize new row - $ddata[$k] = array(); - // get PNG predictor value - $predictor = (10 + $row[0]); - // for each byte on the row - for ($i=1; $i<=$columns; ++$i) { - // new index - $j = ($i - 1); - $row_up = $prev_row[$j]; - if ($i == 1) { - $row_left = 0; - $row_upleft = 0; - } else { - $row_left = $row[($i - 1)]; - $row_upleft = $prev_row[($j - 1)]; - } - switch ($predictor) { - case 10: { // PNG prediction (on encoding, PNG None on all rows) - $ddata[$k][$j] = $row[$i]; - break; - } - case 11: { // PNG prediction (on encoding, PNG Sub on all rows) - $ddata[$k][$j] = (($row[$i] + $row_left) & 0xff); - break; - } - case 12: { // PNG prediction (on encoding, PNG Up on all rows) - $ddata[$k][$j] = (($row[$i] + $row_up) & 0xff); - break; - } - case 13: { // PNG prediction (on encoding, PNG Average on all rows) - $ddata[$k][$j] = (($row[$i] + (($row_left + $row_up) / 2)) & 0xff); - break; - } - case 14: { // PNG prediction (on encoding, PNG Paeth on all rows) - // initial estimate - $p = ($row_left + $row_up - $row_upleft); - // distances - $pa = abs($p - $row_left); - $pb = abs($p - $row_up); - $pc = abs($p - $row_upleft); - $pmin = min($pa, $pb, $pc); - // return minimum distance - switch ($pmin) { - case $pa: { - $ddata[$k][$j] = (($row[$i] + $row_left) & 0xff); - break; - } - case $pb: { - $ddata[$k][$j] = (($row[$i] + $row_up) & 0xff); - break; - } - case $pc: { - $ddata[$k][$j] = (($row[$i] + $row_upleft) & 0xff); - break; - } - } - break; - } - default: { // PNG prediction (on encoding, PNG optimum) - $this->Error('Unknown PNG predictor'); - break; - } - } - } - $prev_row = $ddata[$k]; - } // end for each row - // complete decoding - $sdata = array(); - // for every row - foreach ($ddata as $k => $row) { - // initialize new row - $sdata[$k] = array(0, 0, 0); - if ($wb[0] == 0) { - // default type field - $sdata[$k][0] = 1; - } - $i = 0; // count bytes in the row - // for every column - for ($c = 0; $c < 3; ++$c) { - // for every byte on the column - for ($b = 0; $b < $wb[$c]; ++$b) { - if (isset($row[$i])) { - $sdata[$k][$c] += ($row[$i] << (($wb[$c] - 1 - $b) * 8)); - } - ++$i; - } - } - } - $ddata = array(); - // fill xref - if (isset($index_first)) { - $obj_num = $index_first; - } else { - $obj_num = 0; - } - foreach ($sdata as $k => $row) { - switch ($row[0]) { - case 0: { // (f) linked list of free objects - break; - } - case 1: { // (n) objects that are in use but are not compressed - // create unique object index: [object number]_[generation number] - $index = $obj_num.'_'.$row[2]; - // check if object already exist - if (!isset($xref['xref'][$index])) { - // store object offset position - $xref['xref'][$index] = $row[1]; - } - break; - } - case 2: { // compressed objects - // $row[1] = object number of the object stream in which this object is stored - // $row[2] = index of this object within the object stream - $index = $row[1].'_0_'.$row[2]; - $xref['xref'][$index] = -1; - break; - } - default: { // null objects - break; - } - } - ++$obj_num; - } - } // end decoding data - if (isset($prevxref)) { - // get previous xref - $xref = $this->getXrefData($prevxref, $xref); - } - return $xref; - } - - /** - * Get object type, raw value and offset to next object - * @param int $offset Object offset. - * @return array containing object type, raw value and offset to next object - * @protected - * @since 1.0.000 (2011-06-20) - */ - protected function getRawObject($offset=0) { - $objtype = ''; // object type to be returned - $objval = ''; // object value to be returned - // skip initial white space chars: \x00 null (NUL), \x09 horizontal tab (HT), \x0A line feed (LF), \x0C form feed (FF), \x0D carriage return (CR), \x20 space (SP) - $offset += strspn($this->pdfdata, "\x00\x09\x0a\x0c\x0d\x20", $offset); - // get first char - $char = $this->pdfdata[$offset]; - // get object type - switch ($char) { - case '%': { // \x25 PERCENT SIGN - // skip comment and search for next token - $next = strcspn($this->pdfdata, "\r\n", $offset); - if ($next > 0) { - $offset += $next; - return $this->getRawObject($offset); - } - break; - } - case '/': { // \x2F SOLIDUS - // name object - $objtype = $char; - ++$offset; - if (preg_match('/^([^\x00\x09\x0a\x0c\x0d\x20\s\x28\x29\x3c\x3e\x5b\x5d\x7b\x7d\x2f\x25]+)/', substr($this->pdfdata, $offset, 256), $matches) == 1) { - $objval = $matches[1]; // unescaped value - $offset += strlen($objval); - } - break; - } - case '(': // \x28 LEFT PARENTHESIS - case ')': { // \x29 RIGHT PARENTHESIS - // literal string object - $objtype = $char; - ++$offset; - $strpos = $offset; - if ($char == '(') { - $open_bracket = 1; - while ($open_bracket > 0) { - if (!isset($this->pdfdata[$strpos])) { - break; - } - $ch = $this->pdfdata[$strpos]; - switch ($ch) { - case '\\': { // REVERSE SOLIDUS (5Ch) (Backslash) - // skip next character - ++$strpos; - break; - } - case '(': { // LEFT PARENHESIS (28h) - ++$open_bracket; - break; - } - case ')': { // RIGHT PARENTHESIS (29h) - --$open_bracket; - break; - } - } - ++$strpos; - } - $objval = substr($this->pdfdata, $offset, ($strpos - $offset - 1)); - $offset = $strpos; - } - break; - } - case '[': // \x5B LEFT SQUARE BRACKET - case ']': { // \x5D RIGHT SQUARE BRACKET - // array object - $objtype = $char; - ++$offset; - if ($char == '[') { - // get array content - $objval = array(); - do { - // get element - $element = $this->getRawObject($offset); - $offset = $element[2]; - $objval[] = $element; - } while ($element[0] != ']'); - // remove closing delimiter - array_pop($objval); - } - break; - } - case '<': // \x3C LESS-THAN SIGN - case '>': { // \x3E GREATER-THAN SIGN - if (isset($this->pdfdata[($offset + 1)]) AND ($this->pdfdata[($offset + 1)] == $char)) { - // dictionary object - $objtype = $char.$char; - $offset += 2; - if ($char == '<') { - // get array content - $objval = array(); - do { - // get element - $element = $this->getRawObject($offset); - $offset = $element[2]; - $objval[] = $element; - } while ($element[0] != '>>'); - // remove closing delimiter - array_pop($objval); - } - } else { - // hexadecimal string object - $objtype = $char; - ++$offset; - if (($char == '<') AND (preg_match('/^([0-9A-Fa-f\x09\x0a\x0c\x0d\x20]+)>/iU', substr($this->pdfdata, $offset), $matches) == 1)) { - // remove white space characters - $objval = strtr($matches[1], "\x09\x0a\x0c\x0d\x20", ''); - $offset += strlen($matches[0]); - } elseif (($endpos = strpos($this->pdfdata, '>', $offset)) !== FALSE) { - $offset = $endpos + 1; - } - } - break; - } - default: { - if (substr($this->pdfdata, $offset, 6) == 'endobj') { - // indirect object - $objtype = 'endobj'; - $offset += 6; - } elseif (substr($this->pdfdata, $offset, 4) == 'null') { - // null object - $objtype = 'null'; - $offset += 4; - $objval = 'null'; - } elseif (substr($this->pdfdata, $offset, 4) == 'true') { - // boolean true object - $objtype = 'boolean'; - $offset += 4; - $objval = 'true'; - } elseif (substr($this->pdfdata, $offset, 5) == 'false') { - // boolean false object - $objtype = 'boolean'; - $offset += 5; - $objval = 'false'; - } elseif (substr($this->pdfdata, $offset, 6) == 'stream') { - // start stream object - $objtype = 'stream'; - $offset += 6; - if (preg_match('/^([\r]?[\n])/isU', substr($this->pdfdata, $offset), $matches) == 1) { - $offset += strlen($matches[0]); - if (preg_match('/(endstream)[\x09\x0a\x0c\x0d\x20]/isU', substr($this->pdfdata, $offset), $matches, PREG_OFFSET_CAPTURE) == 1) { - $objval = substr($this->pdfdata, $offset, $matches[0][1]); - $offset += $matches[1][1]; - } - } - } elseif (substr($this->pdfdata, $offset, 9) == 'endstream') { - // end stream object - $objtype = 'endstream'; - $offset += 9; - } elseif (preg_match('/^([0-9]+)[\s]+([0-9]+)[\s]+R/iU', substr($this->pdfdata, $offset, 33), $matches) == 1) { - // indirect object reference - $objtype = 'objref'; - $offset += strlen($matches[0]); - $objval = intval($matches[1]).'_'.intval($matches[2]); - } elseif (preg_match('/^([0-9]+)[\s]+([0-9]+)[\s]+obj/iU', substr($this->pdfdata, $offset, 33), $matches) == 1) { - // object start - $objtype = 'obj'; - $objval = intval($matches[1]).'_'.intval($matches[2]); - $offset += strlen ($matches[0]); - } elseif (($numlen = strspn($this->pdfdata, '+-.0123456789', $offset)) > 0) { - // numeric object - $objtype = 'numeric'; - $objval = substr($this->pdfdata, $offset, $numlen); - $offset += $numlen; - } - break; - } - } - return array($objtype, $objval, $offset); - } - - /** - * Get content of indirect object. - * @param string $obj_ref Object number and generation number separated by underscore character. - * @param int $offset Object offset. - * @param boolean $decoding If true decode streams. - * @return array containing object data. - * @protected - * @since 1.0.000 (2011-05-24) - */ - protected function getIndirectObject($obj_ref, $offset=0, $decoding=true) { - $obj = explode('_', $obj_ref); - if (($obj === false) OR (count($obj) != 2)) { - $this->Error('Invalid object reference: '.$obj); - return; - } - $objref = $obj[0].' '.$obj[1].' obj'; - // ignore leading zeros - $offset += strspn($this->pdfdata, '0', $offset); - if (strpos($this->pdfdata, $objref, $offset) != $offset) { - // an indirect reference to an undefined object shall be considered a reference to the null object - return array('null', 'null', $offset); - } - // starting position of object content - $offset += strlen($objref); - // get array of object content - $objdata = array(); - $i = 0; // object main index - do { - $oldoffset = $offset; - // get element - $element = $this->getRawObject($offset); - $offset = $element[2]; - // decode stream using stream's dictionary information - if ($decoding AND ($element[0] == 'stream') AND (isset($objdata[($i - 1)][0])) AND ($objdata[($i - 1)][0] == '<<')) { - $element[3] = $this->decodeStream($objdata[($i - 1)][1], $element[1]); - } - $objdata[$i] = $element; - ++$i; - } while (($element[0] != 'endobj') AND ($offset != $oldoffset)); - // remove closing delimiter - array_pop($objdata); - // return raw object content - return $objdata; - } - - /** - * Get the content of object, resolving indect object reference if necessary. - * @param string $obj Object value. - * @return array containing object data. - * @protected - * @since 1.0.000 (2011-06-26) - */ - protected function getObjectVal($obj) { - if ($obj[0] == 'objref') { - // reference to indirect object - if (isset($this->objects[$obj[1]])) { - // this object has been already parsed - return $this->objects[$obj[1]]; - } elseif (isset($this->xref[$obj[1]])) { - // parse new object - $this->objects[$obj[1]] = $this->getIndirectObject($obj[1], $this->xref[$obj[1]], false); - return $this->objects[$obj[1]]; - } - } - return $obj; - } - - /** - * Decode the specified stream. - * @param array $sdic Stream's dictionary array. - * @param string $stream Stream to decode. - * @return array containing decoded stream data and remaining filters. - * @protected - * @since 1.0.000 (2011-06-22) - */ - protected function decodeStream($sdic, $stream) { - // get stream length and filters - $slength = strlen($stream); - if ($slength <= 0) { - return array('', array()); - } - $filters = array(); - foreach ($sdic as $k => $v) { - if ($v[0] == '/') { - if (($v[1] == 'Length') AND (isset($sdic[($k + 1)])) AND ($sdic[($k + 1)][0] == 'numeric')) { - // get declared stream length - $declength = intval($sdic[($k + 1)][1]); - if ($declength < $slength) { - $stream = substr($stream, 0, $declength); - $slength = $declength; - } - } elseif (($v[1] == 'Filter') AND (isset($sdic[($k + 1)]))) { - // resolve indirect object - $objval = $this->getObjectVal($sdic[($k + 1)]); - if ($objval[0] == '/') { - // single filter - $filters[] = $objval[1]; - } elseif ($objval[0] == '[') { - // array of filters - foreach ($objval[1] as $flt) { - if ($flt[0] == '/') { - $filters[] = $flt[1]; - } - } - } - } - } - } - // decode the stream - $remaining_filters = array(); - foreach ($filters as $filter) { - if (in_array($filter, TCPDF_FILTERS::getAvailableFilters())) { - try { - $stream = TCPDF_FILTERS::decodeFilter($filter, $stream); - } catch (Exception $e) { - $emsg = $e->getMessage(); - if ((($emsg[0] == '~') AND !$this->cfg['ignore_missing_filter_decoders']) - OR (($emsg[0] != '~') AND !$this->cfg['ignore_filter_decoding_errors'])) { - $this->Error($e->getMessage()); - } - } - } else { - // add missing filter to array - $remaining_filters[] = $filter; - } - } - return array($stream, $remaining_filters); - } - - /** - * Throw an exception or print an error message and die if the K_TCPDF_PARSER_THROW_EXCEPTION_ERROR constant is set to true. - * @param string $msg The error message - * @public - * @since 1.0.000 (2011-05-23) - */ - public function Error($msg) { - if ($this->cfg['die_for_errors']) { - die('<strong>TCPDF_PARSER ERROR: </strong>'.$msg); - } else { - throw new Exception('TCPDF_PARSER ERROR: '.$msg); - } - } - -} // END OF TCPDF_PARSER CLASS - -//============================================================+ -// END OF FILE -//============================================================+ diff --git a/lib/composer/ClassLoader.php b/lib/composer/ClassLoader.php deleted file mode 100644 index 0cd6055d1..000000000 --- a/lib/composer/ClassLoader.php +++ /dev/null @@ -1,572 +0,0 @@ -<?php - -/* - * This file is part of Composer. - * - * (c) Nils Adermann <naderman@naderman.de> - * Jordi Boggiano <j.boggiano@seld.be> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Composer\Autoload; - -/** - * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. - * - * $loader = new \Composer\Autoload\ClassLoader(); - * - * // register classes with namespaces - * $loader->add('Symfony\Component', __DIR__.'/component'); - * $loader->add('Symfony', __DIR__.'/framework'); - * - * // activate the autoloader - * $loader->register(); - * - * // to enable searching the include path (eg. for PEAR packages) - * $loader->setUseIncludePath(true); - * - * In this example, if you try to use a class in the Symfony\Component - * namespace or one of its children (Symfony\Component\Console for instance), - * the autoloader will first look for the class under the component/ - * directory, and it will then fallback to the framework/ directory if not - * found before giving up. - * - * This class is loosely based on the Symfony UniversalClassLoader. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Jordi Boggiano <j.boggiano@seld.be> - * @see https://www.php-fig.org/psr/psr-0/ - * @see https://www.php-fig.org/psr/psr-4/ - */ -class ClassLoader -{ - /** @var ?string */ - private $vendorDir; - - // PSR-4 - /** - * @var array[] - * @psalm-var array<string, array<string, int>> - */ - private $prefixLengthsPsr4 = array(); - /** - * @var array[] - * @psalm-var array<string, array<int, string>> - */ - private $prefixDirsPsr4 = array(); - /** - * @var array[] - * @psalm-var array<string, string> - */ - private $fallbackDirsPsr4 = array(); - - // PSR-0 - /** - * @var array[] - * @psalm-var array<string, array<string, string[]>> - */ - private $prefixesPsr0 = array(); - /** - * @var array[] - * @psalm-var array<string, string> - */ - private $fallbackDirsPsr0 = array(); - - /** @var bool */ - private $useIncludePath = false; - - /** - * @var string[] - * @psalm-var array<string, string> - */ - private $classMap = array(); - - /** @var bool */ - private $classMapAuthoritative = false; - - /** - * @var bool[] - * @psalm-var array<string, bool> - */ - private $missingClasses = array(); - - /** @var ?string */ - private $apcuPrefix; - - /** - * @var self[] - */ - private static $registeredLoaders = array(); - - /** - * @param ?string $vendorDir - */ - public function __construct($vendorDir = null) - { - $this->vendorDir = $vendorDir; - } - - /** - * @return string[] - */ - public function getPrefixes() - { - if (!empty($this->prefixesPsr0)) { - return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); - } - - return array(); - } - - /** - * @return array[] - * @psalm-return array<string, array<int, string>> - */ - public function getPrefixesPsr4() - { - return $this->prefixDirsPsr4; - } - - /** - * @return array[] - * @psalm-return array<string, string> - */ - public function getFallbackDirs() - { - return $this->fallbackDirsPsr0; - } - - /** - * @return array[] - * @psalm-return array<string, string> - */ - public function getFallbackDirsPsr4() - { - return $this->fallbackDirsPsr4; - } - - /** - * @return string[] Array of classname => path - * @psalm-var array<string, string> - */ - public function getClassMap() - { - return $this->classMap; - } - - /** - * @param string[] $classMap Class to filename map - * @psalm-param array<string, string> $classMap - * - * @return void - */ - public function addClassMap(array $classMap) - { - if ($this->classMap) { - $this->classMap = array_merge($this->classMap, $classMap); - } else { - $this->classMap = $classMap; - } - } - - /** - * Registers a set of PSR-0 directories for a given prefix, either - * appending or prepending to the ones previously set for this prefix. - * - * @param string $prefix The prefix - * @param string[]|string $paths The PSR-0 root directories - * @param bool $prepend Whether to prepend the directories - * - * @return void - */ - public function add($prefix, $paths, $prepend = false) - { - if (!$prefix) { - if ($prepend) { - $this->fallbackDirsPsr0 = array_merge( - (array) $paths, - $this->fallbackDirsPsr0 - ); - } else { - $this->fallbackDirsPsr0 = array_merge( - $this->fallbackDirsPsr0, - (array) $paths - ); - } - - return; - } - - $first = $prefix[0]; - if (!isset($this->prefixesPsr0[$first][$prefix])) { - $this->prefixesPsr0[$first][$prefix] = (array) $paths; - - return; - } - if ($prepend) { - $this->prefixesPsr0[$first][$prefix] = array_merge( - (array) $paths, - $this->prefixesPsr0[$first][$prefix] - ); - } else { - $this->prefixesPsr0[$first][$prefix] = array_merge( - $this->prefixesPsr0[$first][$prefix], - (array) $paths - ); - } - } - - /** - * Registers a set of PSR-4 directories for a given namespace, either - * appending or prepending to the ones previously set for this namespace. - * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param string[]|string $paths The PSR-4 base directories - * @param bool $prepend Whether to prepend the directories - * - * @throws \InvalidArgumentException - * - * @return void - */ - public function addPsr4($prefix, $paths, $prepend = false) - { - if (!$prefix) { - // Register directories for the root namespace. - if ($prepend) { - $this->fallbackDirsPsr4 = array_merge( - (array) $paths, - $this->fallbackDirsPsr4 - ); - } else { - $this->fallbackDirsPsr4 = array_merge( - $this->fallbackDirsPsr4, - (array) $paths - ); - } - } elseif (!isset($this->prefixDirsPsr4[$prefix])) { - // Register directories for a new namespace. - $length = strlen($prefix); - if ('\\' !== $prefix[$length - 1]) { - throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); - } - $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; - $this->prefixDirsPsr4[$prefix] = (array) $paths; - } elseif ($prepend) { - // Prepend directories for an already registered namespace. - $this->prefixDirsPsr4[$prefix] = array_merge( - (array) $paths, - $this->prefixDirsPsr4[$prefix] - ); - } else { - // Append directories for an already registered namespace. - $this->prefixDirsPsr4[$prefix] = array_merge( - $this->prefixDirsPsr4[$prefix], - (array) $paths - ); - } - } - - /** - * Registers a set of PSR-0 directories for a given prefix, - * replacing any others previously set for this prefix. - * - * @param string $prefix The prefix - * @param string[]|string $paths The PSR-0 base directories - * - * @return void - */ - public function set($prefix, $paths) - { - if (!$prefix) { - $this->fallbackDirsPsr0 = (array) $paths; - } else { - $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; - } - } - - /** - * Registers a set of PSR-4 directories for a given namespace, - * replacing any others previously set for this namespace. - * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param string[]|string $paths The PSR-4 base directories - * - * @throws \InvalidArgumentException - * - * @return void - */ - public function setPsr4($prefix, $paths) - { - if (!$prefix) { - $this->fallbackDirsPsr4 = (array) $paths; - } else { - $length = strlen($prefix); - if ('\\' !== $prefix[$length - 1]) { - throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); - } - $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; - $this->prefixDirsPsr4[$prefix] = (array) $paths; - } - } - - /** - * Turns on searching the include path for class files. - * - * @param bool $useIncludePath - * - * @return void - */ - public function setUseIncludePath($useIncludePath) - { - $this->useIncludePath = $useIncludePath; - } - - /** - * Can be used to check if the autoloader uses the include path to check - * for classes. - * - * @return bool - */ - public function getUseIncludePath() - { - return $this->useIncludePath; - } - - /** - * Turns off searching the prefix and fallback directories for classes - * that have not been registered with the class map. - * - * @param bool $classMapAuthoritative - * - * @return void - */ - public function setClassMapAuthoritative($classMapAuthoritative) - { - $this->classMapAuthoritative = $classMapAuthoritative; - } - - /** - * Should class lookup fail if not found in the current class map? - * - * @return bool - */ - public function isClassMapAuthoritative() - { - return $this->classMapAuthoritative; - } - - /** - * APCu prefix to use to cache found/not-found classes, if the extension is enabled. - * - * @param string|null $apcuPrefix - * - * @return void - */ - public function setApcuPrefix($apcuPrefix) - { - $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; - } - - /** - * The APCu prefix in use, or null if APCu caching is not enabled. - * - * @return string|null - */ - public function getApcuPrefix() - { - return $this->apcuPrefix; - } - - /** - * Registers this instance as an autoloader. - * - * @param bool $prepend Whether to prepend the autoloader or not - * - * @return void - */ - public function register($prepend = false) - { - spl_autoload_register(array($this, 'loadClass'), true, $prepend); - - if (null === $this->vendorDir) { - return; - } - - if ($prepend) { - self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders; - } else { - unset(self::$registeredLoaders[$this->vendorDir]); - self::$registeredLoaders[$this->vendorDir] = $this; - } - } - - /** - * Unregisters this instance as an autoloader. - * - * @return void - */ - public function unregister() - { - spl_autoload_unregister(array($this, 'loadClass')); - - if (null !== $this->vendorDir) { - unset(self::$registeredLoaders[$this->vendorDir]); - } - } - - /** - * Loads the given class or interface. - * - * @param string $class The name of the class - * @return true|null True if loaded, null otherwise - */ - public function loadClass($class) - { - if ($file = $this->findFile($class)) { - includeFile($file); - - return true; - } - - return null; - } - - /** - * Finds the path to the file where the class is defined. - * - * @param string $class The name of the class - * - * @return string|false The path if found, false otherwise - */ - public function findFile($class) - { - // class map lookup - if (isset($this->classMap[$class])) { - return $this->classMap[$class]; - } - if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { - return false; - } - if (null !== $this->apcuPrefix) { - $file = apcu_fetch($this->apcuPrefix.$class, $hit); - if ($hit) { - return $file; - } - } - - $file = $this->findFileWithExtension($class, '.php'); - - // Search for Hack files if we are running on HHVM - if (false === $file && defined('HHVM_VERSION')) { - $file = $this->findFileWithExtension($class, '.hh'); - } - - if (null !== $this->apcuPrefix) { - apcu_add($this->apcuPrefix.$class, $file); - } - - if (false === $file) { - // Remember that this class does not exist. - $this->missingClasses[$class] = true; - } - - return $file; - } - - /** - * Returns the currently registered loaders indexed by their corresponding vendor directories. - * - * @return self[] - */ - public static function getRegisteredLoaders() - { - return self::$registeredLoaders; - } - - /** - * @param string $class - * @param string $ext - * @return string|false - */ - private function findFileWithExtension($class, $ext) - { - // PSR-4 lookup - $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; - - $first = $class[0]; - if (isset($this->prefixLengthsPsr4[$first])) { - $subPath = $class; - while (false !== $lastPos = strrpos($subPath, '\\')) { - $subPath = substr($subPath, 0, $lastPos); - $search = $subPath . '\\'; - if (isset($this->prefixDirsPsr4[$search])) { - $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); - foreach ($this->prefixDirsPsr4[$search] as $dir) { - if (file_exists($file = $dir . $pathEnd)) { - return $file; - } - } - } - } - } - - // PSR-4 fallback dirs - foreach ($this->fallbackDirsPsr4 as $dir) { - if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { - return $file; - } - } - - // PSR-0 lookup - if (false !== $pos = strrpos($class, '\\')) { - // namespaced class name - $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) - . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); - } else { - // PEAR-like class name - $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; - } - - if (isset($this->prefixesPsr0[$first])) { - foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { - if (0 === strpos($class, $prefix)) { - foreach ($dirs as $dir) { - if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { - return $file; - } - } - } - } - } - - // PSR-0 fallback dirs - foreach ($this->fallbackDirsPsr0 as $dir) { - if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { - return $file; - } - } - - // PSR-0 include paths. - if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { - return $file; - } - - return false; - } -} - -/** - * Scope isolated include. - * - * Prevents access to $this/self from included files. - * - * @param string $file - * @return void - * @private - */ -function includeFile($file) -{ - include $file; -} diff --git a/lib/composer/InstalledVersions.php b/lib/composer/InstalledVersions.php deleted file mode 100644 index d50e0c9fc..000000000 --- a/lib/composer/InstalledVersions.php +++ /dev/null @@ -1,350 +0,0 @@ -<?php - -/* - * This file is part of Composer. - * - * (c) Nils Adermann <naderman@naderman.de> - * Jordi Boggiano <j.boggiano@seld.be> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Composer; - -use Composer\Autoload\ClassLoader; -use Composer\Semver\VersionParser; - -/** - * This class is copied in every Composer installed project and available to all - * - * See also https://getcomposer.org/doc/07-runtime.md#installed-versions - * - * To require its presence, you can require `composer-runtime-api ^2.0` - */ -class InstalledVersions -{ - /** - * @var mixed[]|null - * @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}|array{}|null - */ - private static $installed; - - /** - * @var bool|null - */ - private static $canGetVendors; - - /** - * @var array[] - * @psalm-var array<string, array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}> - */ - private static $installedByVendor = array(); - - /** - * Returns a list of all package names which are present, either by being installed, replaced or provided - * - * @return string[] - * @psalm-return list<string> - */ - public static function getInstalledPackages() - { - $packages = array(); - foreach (self::getInstalled() as $installed) { - $packages[] = array_keys($installed['versions']); - } - - if (1 === \count($packages)) { - return $packages[0]; - } - - return array_keys(array_flip(\call_user_func_array('array_merge', $packages))); - } - - /** - * Returns a list of all package names with a specific type e.g. 'library' - * - * @param string $type - * @return string[] - * @psalm-return list<string> - */ - public static function getInstalledPackagesByType($type) - { - $packagesByType = array(); - - foreach (self::getInstalled() as $installed) { - foreach ($installed['versions'] as $name => $package) { - if (isset($package['type']) && $package['type'] === $type) { - $packagesByType[] = $name; - } - } - } - - return $packagesByType; - } - - /** - * Checks whether the given package is installed - * - * This also returns true if the package name is provided or replaced by another package - * - * @param string $packageName - * @param bool $includeDevRequirements - * @return bool - */ - public static function isInstalled($packageName, $includeDevRequirements = true) - { - foreach (self::getInstalled() as $installed) { - if (isset($installed['versions'][$packageName])) { - return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']); - } - } - - return false; - } - - /** - * Checks whether the given package satisfies a version constraint - * - * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call: - * - * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3') - * - * @param VersionParser $parser Install composer/semver to have access to this class and functionality - * @param string $packageName - * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package - * @return bool - */ - public static function satisfies(VersionParser $parser, $packageName, $constraint) - { - $constraint = $parser->parseConstraints($constraint); - $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); - - return $provided->matches($constraint); - } - - /** - * Returns a version constraint representing all the range(s) which are installed for a given package - * - * It is easier to use this via isInstalled() with the $constraint argument if you need to check - * whether a given version of a package is installed, and not just whether it exists - * - * @param string $packageName - * @return string Version constraint usable with composer/semver - */ - public static function getVersionRanges($packageName) - { - foreach (self::getInstalled() as $installed) { - if (!isset($installed['versions'][$packageName])) { - continue; - } - - $ranges = array(); - if (isset($installed['versions'][$packageName]['pretty_version'])) { - $ranges[] = $installed['versions'][$packageName]['pretty_version']; - } - if (array_key_exists('aliases', $installed['versions'][$packageName])) { - $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']); - } - if (array_key_exists('replaced', $installed['versions'][$packageName])) { - $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']); - } - if (array_key_exists('provided', $installed['versions'][$packageName])) { - $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']); - } - - return implode(' || ', $ranges); - } - - throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); - } - - /** - * @param string $packageName - * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present - */ - public static function getVersion($packageName) - { - foreach (self::getInstalled() as $installed) { - if (!isset($installed['versions'][$packageName])) { - continue; - } - - if (!isset($installed['versions'][$packageName]['version'])) { - return null; - } - - return $installed['versions'][$packageName]['version']; - } - - throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); - } - - /** - * @param string $packageName - * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present - */ - public static function getPrettyVersion($packageName) - { - foreach (self::getInstalled() as $installed) { - if (!isset($installed['versions'][$packageName])) { - continue; - } - - if (!isset($installed['versions'][$packageName]['pretty_version'])) { - return null; - } - - return $installed['versions'][$packageName]['pretty_version']; - } - - throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); - } - - /** - * @param string $packageName - * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference - */ - public static function getReference($packageName) - { - foreach (self::getInstalled() as $installed) { - if (!isset($installed['versions'][$packageName])) { - continue; - } - - if (!isset($installed['versions'][$packageName]['reference'])) { - return null; - } - - return $installed['versions'][$packageName]['reference']; - } - - throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); - } - - /** - * @param string $packageName - * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path. - */ - public static function getInstallPath($packageName) - { - foreach (self::getInstalled() as $installed) { - if (!isset($installed['versions'][$packageName])) { - continue; - } - - return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null; - } - - throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); - } - - /** - * @return array - * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string} - */ - public static function getRootPackage() - { - $installed = self::getInstalled(); - - return $installed[0]['root']; - } - - /** - * Returns the raw installed.php data for custom implementations - * - * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. - * @return array[] - * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} - */ - public static function getRawData() - { - @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED); - - if (null === self::$installed) { - // only require the installed.php file if this file is loaded from its dumped location, - // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 - if (substr(__DIR__, -8, 1) !== 'C') { - self::$installed = include __DIR__ . '/installed.php'; - } else { - self::$installed = array(); - } - } - - return self::$installed; - } - - /** - * Returns the raw data of all installed.php which are currently loaded for custom implementations - * - * @return array[] - * @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}> - */ - public static function getAllRawData() - { - return self::getInstalled(); - } - - /** - * Lets you reload the static array from another file - * - * This is only useful for complex integrations in which a project needs to use - * this class but then also needs to execute another project's autoloader in process, - * and wants to ensure both projects have access to their version of installed.php. - * - * A typical case would be PHPUnit, where it would need to make sure it reads all - * the data it needs from this class, then call reload() with - * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure - * the project in which it runs can then also use this class safely, without - * interference between PHPUnit's dependencies and the project's dependencies. - * - * @param array[] $data A vendor/composer/installed.php data set - * @return void - * - * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} $data - */ - public static function reload($data) - { - self::$installed = $data; - self::$installedByVendor = array(); - } - - /** - * @return array[] - * @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}> - */ - private static function getInstalled() - { - if (null === self::$canGetVendors) { - self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders'); - } - - $installed = array(); - - if (self::$canGetVendors) { - foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { - if (isset(self::$installedByVendor[$vendorDir])) { - $installed[] = self::$installedByVendor[$vendorDir]; - } elseif (is_file($vendorDir.'/composer/installed.php')) { - $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php'; - if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { - self::$installed = $installed[count($installed) - 1]; - } - } - } - } - - if (null === self::$installed) { - // only require the installed.php file if this file is loaded from its dumped location, - // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 - if (substr(__DIR__, -8, 1) !== 'C') { - self::$installed = require __DIR__ . '/installed.php'; - } else { - self::$installed = array(); - } - } - $installed[] = self::$installed; - - return $installed; - } -} diff --git a/lib/composer/LICENSE b/lib/composer/LICENSE deleted file mode 100644 index f27399a04..000000000 --- a/lib/composer/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ - -Copyright (c) Nils Adermann, Jordi Boggiano - -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/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php deleted file mode 100644 index 4027b2b92..000000000 --- a/lib/composer/autoload_classmap.php +++ /dev/null @@ -1,3378 +0,0 @@ -<?php - -// autoload_classmap.php @generated by Composer - -$vendorDir = dirname(dirname(__FILE__)); -$baseDir = dirname($vendorDir); - -return array( - 'AbstractApplicationObjectExtension' => $baseDir . '/application/applicationextension.inc.php', - 'AbstractApplicationUIExtension' => $baseDir . '/application/applicationextension.inc.php', - 'AbstractLoginFSMExtension' => $baseDir . '/application/applicationextension.inc.php', - 'AbstractPageUIBlockExtension' => $baseDir . '/application/applicationextension.inc.php', - 'AbstractPageUIExtension' => $baseDir . '/application/applicationextension.inc.php', - 'AbstractPortalUIExtension' => $baseDir . '/application/applicationextension.inc.php', - 'AbstractPreferencesExtension' => $baseDir . '/application/applicationextension.inc.php', - 'AbstractWeeklyScheduledProcess' => $baseDir . '/core/backgroundprocess.inc.php', - 'Action' => $baseDir . '/core/action.class.inc.php', - 'ActionChecker' => $baseDir . '/core/userrights.class.inc.php', - 'ActionEmail' => $baseDir . '/core/action.class.inc.php', - 'ActionNotification' => $baseDir . '/core/action.class.inc.php', - 'AjaxPage' => $baseDir . '/sources/Application/WebPage/AjaxPage.php', - 'ApcService' => $baseDir . '/core/apc-service.class.inc.php', - 'ApplicationContext' => $baseDir . '/application/applicationcontext.class.inc.php', - 'ApplicationException' => $baseDir . '/application/exceptions/ApplicationException.php', - 'ApplicationMenu' => $baseDir . '/application/menunode.class.inc.php', - 'ApplicationPopupMenuItem' => $baseDir . '/application/applicationextension.inc.php', - 'Archive_Tar' => $vendorDir . '/pear/archive_tar/Archive/Tar.php', - 'ArchivedObjectException' => $baseDir . '/application/exceptions/ArchivedObjectException.php', - 'AsyncSendEmail' => $baseDir . '/core/asynctask.class.inc.php', - 'AsyncTask' => $baseDir . '/core/asynctask.class.inc.php', - 'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', - 'AttributeApplicationLanguage' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeArchiveDate' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeArchiveFlag' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeBlob' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeBoolean' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeCaseLog' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeClass' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeClassAttCodeSet' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeClassState' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeCustomFields' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeDBField' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeDBFieldVoid' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeDashboard' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeDate' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeDateTime' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeDeadline' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeDecimal' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeDefinition' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeDuration' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeEmailAddress' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeEncryptedString' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeEnum' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeEnumSet' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeExternalField' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeExternalKey' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeFinalClass' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeFriendlyName' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeHTML' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeHierarchicalKey' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeIPAddress' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeImage' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeInteger' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeLinkedSet' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeLinkedSetIndirect' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeLongText' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeMetaEnum' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeOQL' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeObjectKey' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeObsolescenceDate' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeObsolescenceFlag' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeOneWayPassword' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributePassword' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributePercentage' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributePhoneNumber' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributePropertySet' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeQueryAttCodeSet' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeRedundancySettings' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeSet' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeStopWatch' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeString' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeSubItem' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeTable' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeTagSet' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeTemplateHTML' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeTemplateString' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeTemplateText' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeText' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeURL' => $baseDir . '/core/attributedef.class.inc.php', - 'AuditCategory' => $baseDir . '/application/audit.category.class.inc.php', - 'AuditDomain' => $baseDir . '/application/audit.domain.class.inc.php', - 'AuditRule' => $baseDir . '/application/audit.rule.class.inc.php', - 'BackgroundTask' => $baseDir . '/core/backgroundtask.class.inc.php', - 'BinaryExpression' => $baseDir . '/core/oql/expression.class.inc.php', - 'BinaryOqlExpression' => $baseDir . '/core/oql/oqlquery.class.inc.php', - 'BulkChange' => $baseDir . '/core/bulkchange.class.inc.php', - 'BulkChangeException' => $baseDir . '/application/exceptions/BulkChangeException.php', - 'BulkExport' => $baseDir . '/core/bulkexport.class.inc.php', - 'BulkExportException' => $baseDir . '/core/bulkexport.class.inc.php', - 'BulkExportMissingParameterException' => $baseDir . '/core/bulkexport.class.inc.php', - 'BulkExportResult' => $baseDir . '/core/bulkexport.class.inc.php', - 'BulkExportResultGC' => $baseDir . '/core/bulkexport.class.inc.php', - 'CAS_AuthenticationException' => $vendorDir . '/apereo/phpcas/source/CAS/AuthenticationException.php', - 'CAS_Client' => $vendorDir . '/apereo/phpcas/source/CAS/Client.php', - 'CAS_CookieJar' => $vendorDir . '/apereo/phpcas/source/CAS/CookieJar.php', - 'CAS_Exception' => $vendorDir . '/apereo/phpcas/source/CAS/Exception.php', - 'CAS_GracefullTerminationException' => $vendorDir . '/apereo/phpcas/source/CAS/GracefullTerminationException.php', - 'CAS_InvalidArgumentException' => $vendorDir . '/apereo/phpcas/source/CAS/InvalidArgumentException.php', - 'CAS_Languages_Catalan' => $vendorDir . '/apereo/phpcas/source/CAS/Languages/Catalan.php', - 'CAS_Languages_ChineseSimplified' => $vendorDir . '/apereo/phpcas/source/CAS/Languages/ChineseSimplified.php', - 'CAS_Languages_English' => $vendorDir . '/apereo/phpcas/source/CAS/Languages/English.php', - 'CAS_Languages_French' => $vendorDir . '/apereo/phpcas/source/CAS/Languages/French.php', - 'CAS_Languages_Galego' => $vendorDir . '/apereo/phpcas/source/CAS/Languages/Galego.php', - 'CAS_Languages_German' => $vendorDir . '/apereo/phpcas/source/CAS/Languages/German.php', - 'CAS_Languages_Greek' => $vendorDir . '/apereo/phpcas/source/CAS/Languages/Greek.php', - 'CAS_Languages_Japanese' => $vendorDir . '/apereo/phpcas/source/CAS/Languages/Japanese.php', - 'CAS_Languages_LanguageInterface' => $vendorDir . '/apereo/phpcas/source/CAS/Languages/LanguageInterface.php', - 'CAS_Languages_Portuguese' => $vendorDir . '/apereo/phpcas/source/CAS/Languages/Portuguese.php', - 'CAS_Languages_Spanish' => $vendorDir . '/apereo/phpcas/source/CAS/Languages/Spanish.php', - 'CAS_OutOfSequenceBeforeAuthenticationCallException' => $vendorDir . '/apereo/phpcas/source/CAS/OutOfSequenceBeforeAuthenticationCallException.php', - 'CAS_OutOfSequenceBeforeClientException' => $vendorDir . '/apereo/phpcas/source/CAS/OutOfSequenceBeforeClientException.php', - 'CAS_OutOfSequenceBeforeProxyException' => $vendorDir . '/apereo/phpcas/source/CAS/OutOfSequenceBeforeProxyException.php', - 'CAS_OutOfSequenceException' => $vendorDir . '/apereo/phpcas/source/CAS/OutOfSequenceException.php', - 'CAS_PGTStorage_AbstractStorage' => $vendorDir . '/apereo/phpcas/source/CAS/PGTStorage/AbstractStorage.php', - 'CAS_PGTStorage_Db' => $vendorDir . '/apereo/phpcas/source/CAS/PGTStorage/Db.php', - 'CAS_PGTStorage_File' => $vendorDir . '/apereo/phpcas/source/CAS/PGTStorage/File.php', - 'CAS_ProxiedService' => $vendorDir . '/apereo/phpcas/source/CAS/ProxiedService.php', - 'CAS_ProxiedService_Abstract' => $vendorDir . '/apereo/phpcas/source/CAS/ProxiedService/Abstract.php', - 'CAS_ProxiedService_Exception' => $vendorDir . '/apereo/phpcas/source/CAS/ProxiedService/Exception.php', - 'CAS_ProxiedService_Http' => $vendorDir . '/apereo/phpcas/source/CAS/ProxiedService/Http.php', - 'CAS_ProxiedService_Http_Abstract' => $vendorDir . '/apereo/phpcas/source/CAS/ProxiedService/Http/Abstract.php', - 'CAS_ProxiedService_Http_Get' => $vendorDir . '/apereo/phpcas/source/CAS/ProxiedService/Http/Get.php', - 'CAS_ProxiedService_Http_Post' => $vendorDir . '/apereo/phpcas/source/CAS/ProxiedService/Http/Post.php', - 'CAS_ProxiedService_Imap' => $vendorDir . '/apereo/phpcas/source/CAS/ProxiedService/Imap.php', - 'CAS_ProxiedService_Testable' => $vendorDir . '/apereo/phpcas/source/CAS/ProxiedService/Testable.php', - 'CAS_ProxyChain' => $vendorDir . '/apereo/phpcas/source/CAS/ProxyChain.php', - 'CAS_ProxyChain_AllowedList' => $vendorDir . '/apereo/phpcas/source/CAS/ProxyChain/AllowedList.php', - 'CAS_ProxyChain_Any' => $vendorDir . '/apereo/phpcas/source/CAS/ProxyChain/Any.php', - 'CAS_ProxyChain_Interface' => $vendorDir . '/apereo/phpcas/source/CAS/ProxyChain/Interface.php', - 'CAS_ProxyChain_Trusted' => $vendorDir . '/apereo/phpcas/source/CAS/ProxyChain/Trusted.php', - 'CAS_ProxyTicketException' => $vendorDir . '/apereo/phpcas/source/CAS/ProxyTicketException.php', - 'CAS_Request_AbstractRequest' => $vendorDir . '/apereo/phpcas/source/CAS/Request/AbstractRequest.php', - 'CAS_Request_CurlMultiRequest' => $vendorDir . '/apereo/phpcas/source/CAS/Request/CurlMultiRequest.php', - 'CAS_Request_CurlRequest' => $vendorDir . '/apereo/phpcas/source/CAS/Request/CurlRequest.php', - 'CAS_Request_Exception' => $vendorDir . '/apereo/phpcas/source/CAS/Request/Exception.php', - 'CAS_Request_MultiRequestInterface' => $vendorDir . '/apereo/phpcas/source/CAS/Request/MultiRequestInterface.php', - 'CAS_Request_RequestInterface' => $vendorDir . '/apereo/phpcas/source/CAS/Request/RequestInterface.php', - 'CAS_Session_PhpSession' => $vendorDir . '/apereo/phpcas/source/CAS/Session/PhpSession.php', - 'CAS_TypeMismatchException' => $vendorDir . '/apereo/phpcas/source/CAS/TypeMismatchException.php', - 'CLILikeWebPage' => $baseDir . '/sources/Application/WebPage/CLILikeWebPage.php', - 'CLIPage' => $baseDir . '/sources/Application/WebPage/CLIPage.php', - 'CMDBChange' => $baseDir . '/core/cmdbchange.class.inc.php', - 'CMDBChangeOp' => $baseDir . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpCreate' => $baseDir . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpDelete' => $baseDir . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpPlugin' => $baseDir . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttribute' => $baseDir . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeBlob' => $baseDir . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeCaseLog' => $baseDir . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeCustomFields' => $baseDir . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeEncrypted' => $baseDir . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeHTML' => $baseDir . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeLinks' => $baseDir . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeLinksAddRemove' => $baseDir . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeLinksTune' => $baseDir . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeLongText' => $baseDir . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeOneWayPassword' => $baseDir . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeScalar' => $baseDir . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeTagSet' => $baseDir . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeText' => $baseDir . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeURL' => $baseDir . '/core/cmdbchangeop.class.inc.php', - 'CMDBObject' => $baseDir . '/core/cmdbobject.class.inc.php', - 'CMDBObjectSet' => $baseDir . '/core/cmdbobject.class.inc.php', - 'CMDBSource' => $baseDir . '/core/cmdbsource.class.inc.php', - 'CSVBulkExport' => $baseDir . '/core/csvbulkexport.class.inc.php', - 'CSVPage' => $baseDir . '/sources/Application/WebPage/CSVPage.php', - 'CSVParser' => $baseDir . '/core/csvparser.class.inc.php', - 'CSVParserException' => $baseDir . '/application/exceptions/CSVParserException.php', - 'CaptureWebPage' => $baseDir . '/sources/Application/WebPage/CaptureWebPage.php', - 'CellChangeSpec' => $baseDir . '/core/bulkchange.class.inc.php', - 'CellStatus_Ambiguous' => $baseDir . '/core/bulkchange.class.inc.php', - 'CellStatus_Issue' => $baseDir . '/core/bulkchange.class.inc.php', - 'CellStatus_Modify' => $baseDir . '/core/bulkchange.class.inc.php', - 'CellStatus_NullIssue' => $baseDir . '/core/bulkchange.class.inc.php', - 'CellStatus_SearchIssue' => $baseDir . '/core/bulkchange.class.inc.php', - 'CellStatus_Void' => $baseDir . '/core/bulkchange.class.inc.php', - 'CharConcatExpression' => $baseDir . '/core/oql/expression.class.inc.php', - 'CharConcatWSExpression' => $baseDir . '/core/oql/expression.class.inc.php', - 'CheckStopWatchThresholds' => $baseDir . '/core/ormstopwatch.class.inc.php', - 'CheckableExpression' => $baseDir . '/core/oql/oqlquery.class.inc.php', - 'Collator' => $vendorDir . '/symfony/polyfill-intl-icu/Resources/stubs/Collator.php', - 'Combodo\\iTop\\Application\\Branding' => $baseDir . '/sources/Application/Branding.php', - 'Combodo\\iTop\\Application\\EventRegister\\ApplicationEvents' => $baseDir . '/sources/Application/EventRegister/ApplicationEvents.php', - 'Combodo\\iTop\\Application\\Helper\\FormHelper' => $baseDir . '/sources/Application/Helper/FormHelper.php', - 'Combodo\\iTop\\Application\\Helper\\Session' => $baseDir . '/sources/Application/Helper/Session.php', - 'Combodo\\iTop\\Application\\Helper\\WebResourcesHelper' => $baseDir . '/sources/Application/Helper/WebResourcesHelper.php', - 'Combodo\\iTop\\Application\\Search\\AjaxSearchException' => $baseDir . '/sources/Application/Search/ajaxsearchexception.class.inc.php', - 'Combodo\\iTop\\Application\\Search\\CriterionConversionAbstract' => $baseDir . '/sources/Application/Search/criterionconversionabstract.class.inc.php', - 'Combodo\\iTop\\Application\\Search\\CriterionConversion\\CriterionToOQL' => $baseDir . '/sources/Application/Search/CriterionConversion/criteriontooql.class.inc.php', - 'Combodo\\iTop\\Application\\Search\\CriterionConversion\\CriterionToSearchForm' => $baseDir . '/sources/Application/Search/CriterionConversion/criteriontosearchform.class.inc.php', - 'Combodo\\iTop\\Application\\Search\\CriterionParser' => $baseDir . '/sources/Application/Search/criterionparser.class.inc.php', - 'Combodo\\iTop\\Application\\Search\\SearchForm' => $baseDir . '/sources/Application/Search/searchform.class.inc.php', - 'Combodo\\iTop\\Application\\Status\\Status' => $baseDir . '/sources/Application/Status/Status.php', - 'Combodo\\iTop\\Application\\TwigBase\\Controller\\Controller' => $baseDir . '/sources/Application/TwigBase/Controller/Controller.php', - 'Combodo\\iTop\\Application\\TwigBase\\Controller\\PageNotFoundException' => $baseDir . '/application/exceptions/PageNotFoundException.php', - 'Combodo\\iTop\\Application\\TwigBase\\Twig\\Extension' => $baseDir . '/sources/Application/TwigBase/Twig/Extension.php', - 'Combodo\\iTop\\Application\\TwigBase\\Twig\\TwigHelper' => $baseDir . '/sources/Application/TwigBase/Twig/TwigHelper.php', - 'Combodo\\iTop\\Application\\TwigBase\\UI\\UIBlockExtension' => $baseDir . '/sources/Application/TwigBase/UI/UIBlockExtension.php', - 'Combodo\\iTop\\Application\\TwigBase\\UI\\UIBlockNode' => $baseDir . '/sources/Application/TwigBase/UI/UIBlockNode.php', - 'Combodo\\iTop\\Application\\TwigBase\\UI\\UIBlockParser' => $baseDir . '/sources/Application/TwigBase/UI/UIBlockParser.php', - 'Combodo\\iTop\\Application\\UI\\Base\\AbstractUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/AbstractUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Alert\\Alert' => $baseDir . '/sources/Application/UI/Base/Component/Alert/Alert.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Alert\\AlertUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/Alert/AlertUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Breadcrumbs\\Breadcrumbs' => $baseDir . '/sources/Application/UI/Base/Component/Breadcrumbs/Breadcrumbs.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\ButtonGroup\\ButtonGroup' => $baseDir . '/sources/Application/UI/Base/Component/ButtonGroup/ButtonGroup.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\ButtonGroup\\ButtonGroupUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/ButtonGroup/ButtonGroupUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Button\\Button' => $baseDir . '/sources/Application/UI/Base/Component/Button/Button.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Button\\ButtonJS' => $baseDir . '/sources/Application/UI/Base/Component/Button/ButtonJS.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Button\\ButtonUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/Button/ButtonUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Button\\ButtonURL' => $baseDir . '/sources/Application/UI/Base/Component/Button/ButtonURL.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\CollapsibleSection\\CollapsibleSection' => $baseDir . '/sources/Application/UI/Base/Component/CollapsibleSection/CollapsibleSection.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\CollapsibleSection\\CollapsibleSectionUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/CollapsibleSection/CollapsibleSectionUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Dashlet\\DashletBadge' => $baseDir . '/sources/Application/UI/Base/Component/Dashlet/DashletBadge.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Dashlet\\DashletContainer' => $baseDir . '/sources/Application/UI/Base/Component/Dashlet/DashletContainer.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Dashlet\\DashletFactory' => $baseDir . '/sources/Application/UI/Base/Component/Dashlet/DashletFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Dashlet\\DashletHeaderStatic' => $baseDir . '/sources/Application/UI/Base/Component/Dashlet/DashletHeaderStatic.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Dashlet\\DashletPlainText' => $baseDir . '/sources/Application/UI/Base/Component/Dashlet/DashletPlainText.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\DataTable\\DataTable' => $baseDir . '/sources/Application/UI/Base/Component/DataTable/DataTable.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\DataTable\\DataTableSettings' => $baseDir . '/sources/Application/UI/Base/Component/DataTable/DataTableSettings.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\DataTable\\DataTableUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/DataTable/DataTableUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\DataTable\\StaticTable\\FormTableRow\\FormTableRow' => $baseDir . '/sources/Application/UI/Base/Component/DataTable/StaticTable/FormTableRow/FormTableRow.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\DataTable\\StaticTable\\FormTable\\FormTable' => $baseDir . '/sources/Application/UI/Base/Component/DataTable/StaticTable/FormTable/FormTable.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\DataTable\\StaticTable\\StaticTable' => $baseDir . '/sources/Application/UI/Base/Component/DataTable/StaticTable/StaticTable.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\DataTable\\tTableRowActions' => $baseDir . '/sources/Application/UI/Base/Component/DataTable/tTableRowActions.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\FieldBadge\\FieldBadge' => $baseDir . '/sources/Application/UI/Base/Component/FieldBadge/FieldBadge.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\FieldBadge\\FieldBadgeUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/FieldBadge/FieldBadgeUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\FieldSet\\FieldSet' => $baseDir . '/sources/Application/UI/Base/Component/FieldSet/FieldSet.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\FieldSet\\FieldSetUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/FieldSet/FieldSetUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Field\\Field' => $baseDir . '/sources/Application/UI/Base/Component/Field/Field.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Field\\FieldUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/Field/FieldUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Form\\Form' => $baseDir . '/sources/Application/UI/Base/Component/Form/Form.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Form\\FormUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/Form/FormUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\GlobalSearch\\GlobalSearch' => $baseDir . '/sources/Application/UI/Base/Component/GlobalSearch/GlobalSearch.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\GlobalSearch\\GlobalSearchFactory' => $baseDir . '/sources/Application/UI/Base/Component/GlobalSearch/GlobalSearchFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\GlobalSearch\\GlobalSearchHelper' => $baseDir . '/sources/Application/UI/Base/Component/GlobalSearch/GlobalSearchHelper.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Html\\Html' => $baseDir . '/sources/Application/UI/Base/Component/Html/Html.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Html\\HtmlFactory' => $baseDir . '/sources/Application/UI/Base/Component/Html/HtmlFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\AbstractInput' => $baseDir . '/sources/Application/UI/Base/Component/Input/AbstractInput.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\FileSelect\\FileSelect' => $baseDir . '/sources/Application/UI/Base/Component/Input/FileSelect/FileSelect.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\FileSelect\\FileSelectUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/Input/FileSelect/FileSelectUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\Input' => $baseDir . '/sources/Application/UI/Base/Component/Input/Input.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\InputUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/Input/InputUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\InputWithLabel' => $baseDir . '/sources/Application/UI/Base/Component/Input/InputWithLabel.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\RichText\\RichText' => $baseDir . '/sources/Application/UI/Base/Component/Input/RichText/RichText.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\SelectUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/Input/Select/SelectUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\Select\\Select' => $baseDir . '/sources/Application/UI/Base/Component/Input/Select/Select.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\Select\\SelectOption' => $baseDir . '/sources/Application/UI/Base/Component/Input/Select/SelectOption.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\Select\\SelectOptionUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/Input/Select/SelectOptionUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\Set\\DataProvider\\AbstractDataProvider' => $baseDir . '/sources/Application/UI/Base/Component/Input/Set/DataProvider/AbstractDataProvider.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\Set\\DataProvider\\AjaxDataProvider' => $baseDir . '/sources/Application/UI/Base/Component/Input/Set/DataProvider/AjaxDataProvider.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\Set\\DataProvider\\AjaxDataProviderForOQL' => $baseDir . '/sources/Application/UI/Base/Component/Input/Set/DataProvider/AjaxDataProviderForOql.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\Set\\DataProvider\\SimpleDataProvider' => $baseDir . '/sources/Application/UI/Base/Component/Input/Set/DataProvider/SimpleDataProvider.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\Set\\DataProvider\\iDataProvider' => $baseDir . '/sources/Application/UI/Base/Component/Input/Set/DataProvider/iDataProvider.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\Set\\Set' => $baseDir . '/sources/Application/UI/Base/Component/Input/Set/Set.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\Set\\SetUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/Input/Set/SetUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\TextArea' => $baseDir . '/sources/Application/UI/Base/Component/Input/TextArea.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\tInputLabel' => $baseDir . '/sources/Application/UI/Base/Component/Input/tInputLabel.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\MedallionIcon\\MedallionIcon' => $baseDir . '/sources/Application/UI/Base/Component/MedallionIcon/MedallionIcon.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Modal\\DoNotShowAgainOptionBlock' => $baseDir . '/sources/Application/UI/Base/Component/Modal/DoNotShowAgainOptionBlock.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Panel\\Panel' => $baseDir . '/sources/Application/UI/Base/Component/Panel/Panel.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Panel\\PanelUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/Panel/PanelUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Pill\\Pill' => $baseDir . '/sources/Application/UI/Base/Component/Pill/Pill.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Pill\\PillFactory' => $baseDir . '/sources/Application/UI/Base/Component/Pill/PillFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\PopoverMenu\\NewsroomMenu\\NewsroomMenu' => $baseDir . '/sources/Application/UI/Base/Component/PopoverMenu/NewsroomMenu/NewsroomMenu.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\PopoverMenu\\NewsroomMenu\\NewsroomMenuFactory' => $baseDir . '/sources/Application/UI/Base/Component/PopoverMenu/NewsroomMenu/NewsroomMenuFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\PopoverMenu\\PopoverMenu' => $baseDir . '/sources/Application/UI/Base/Component/PopoverMenu/PopoverMenu.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\PopoverMenu\\PopoverMenuFactory' => $baseDir . '/sources/Application/UI/Base/Component/PopoverMenu/PopoverMenuFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\PopoverMenu\\PopoverMenuItem\\JsPopoverMenuItem' => $baseDir . '/sources/Application/UI/Base/Component/PopoverMenu/PopoverMenuItem/JsPopoverMenuItem.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\PopoverMenu\\PopoverMenuItem\\PopoverMenuItem' => $baseDir . '/sources/Application/UI/Base/Component/PopoverMenu/PopoverMenuItem/PopoverMenuItem.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\PopoverMenu\\PopoverMenuItem\\PopoverMenuItemFactory' => $baseDir . '/sources/Application/UI/Base/Component/PopoverMenu/PopoverMenuItem/PopoverMenuItemFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\PopoverMenu\\PopoverMenuItem\\SeparatorPopoverMenuItem' => $baseDir . '/sources/Application/UI/Base/Component/PopoverMenu/PopoverMenuItem/SeparatorPopoverMenuItem.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\PopoverMenu\\PopoverMenuItem\\UrlPopoverMenuItem' => $baseDir . '/sources/Application/UI/Base/Component/PopoverMenu/PopoverMenuItem/UrlPopoverMenuItem.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\QuickCreate\\QuickCreate' => $baseDir . '/sources/Application/UI/Base/Component/QuickCreate/QuickCreate.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\QuickCreate\\QuickCreateFactory' => $baseDir . '/sources/Application/UI/Base/Component/QuickCreate/QuickCreateFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\QuickCreate\\QuickCreateHelper' => $baseDir . '/sources/Application/UI/Base/Component/QuickCreate/QuickCreateHelper.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Spinner\\Spinner' => $baseDir . '/sources/Application/UI/Base/Component/Spinner/Spinner.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Spinner\\SpinnerUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/Spinner/SpinnerUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Template\\Template' => $baseDir . '/sources/Application/UI/Base/Component/Template/Template.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Template\\TemplateUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/Template/TemplateUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Text\\Text' => $baseDir . '/sources/Application/UI/Base/Component/Text/Text.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Title\\Title' => $baseDir . '/sources/Application/UI/Base/Component/Title/Title.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Title\\TitleUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/Title/TitleUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Toolbar\\Separator\\AbstractSeparator' => $baseDir . '/sources/Application/UI/Base/Component/Toolbar/Separator/AbstractSeparator.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Toolbar\\Separator\\ToolbarSeparatorUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/Toolbar/Separator/ToolbarSeparatorUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Toolbar\\Separator\\VerticalSeparator' => $baseDir . '/sources/Application/UI/Base/Component/Toolbar/Separator/VerticalSeparator.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Toolbar\\Toolbar' => $baseDir . '/sources/Application/UI/Base/Component/Toolbar/Toolbar.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Toolbar\\ToolbarSpacer\\ToolbarSpacer' => $baseDir . '/sources/Application/UI/Base/Component/Toolbar/ToolbarSpacer/ToolbarSpacer.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Toolbar\\ToolbarSpacer\\ToolbarSpacerUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/Toolbar/ToolbarSpacer/ToolbarSpacerUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Toolbar\\ToolbarUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/Toolbar/ToolbarUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\ActivityEntry' => $baseDir . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/ActivityEntry.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\ActivityEntryFactory' => $baseDir . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/ActivityEntryFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\CMDBChangeOp\\CMDBChangeOpAttachmentAddedFactory' => $baseDir . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/CMDBChangeOp/CMDBChangeOpAttachmentAddedFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\CMDBChangeOp\\CMDBChangeOpAttachmentRemovedFactory' => $baseDir . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/CMDBChangeOp/CMDBChangeOpAttachmentRemovedFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\CMDBChangeOp\\CMDBChangeOpCreateFactory' => $baseDir . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/CMDBChangeOp/CMDBChangeOpCreateFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\CMDBChangeOp\\CMDBChangeOpDeleteFactory' => $baseDir . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/CMDBChangeOp/CMDBChangeOpDeleteFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\CMDBChangeOp\\CMDBChangeOpFactory' => $baseDir . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/CMDBChangeOp/CMDBChangeOpFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\CMDBChangeOp\\CMDBChangeOpSetAttributeFactory' => $baseDir . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/CMDBChangeOp/CMDBChangeOpSetAttributeFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\CMDBChangeOp\\CMDBChangeOpSetAttributeScalarFactory' => $baseDir . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/CMDBChangeOp/CMDBChangeOpSetAttributeScalarFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\CaseLogEntry' => $baseDir . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/CaseLogEntry.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\EditsEntry' => $baseDir . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/EditsEntry.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\EventNotification\\EventNotificationEmailFactory' => $baseDir . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/EventNotification/EventNotificationEmailFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\EventNotification\\EventNotificationFactory' => $baseDir . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/EventNotification/EventNotificationFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\NotificationEntry' => $baseDir . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/NotificationEntry.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\TransitionEntry' => $baseDir . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/TransitionEntry.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityPanel' => $baseDir . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanel.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityPanelFactory' => $baseDir . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanelFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityPanelHelper' => $baseDir . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanelHelper.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityPanelPrint' => $baseDir . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanelPrint.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\CaseLogEntryFormFactory\\CaseLogEntryFormFactory' => $baseDir . '/sources/Application/UI/Base/Layout/ActivityPanel/CaseLogEntryForm/CaseLogEntryFormFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\CaseLogEntryForm\\CaseLogEntryForm' => $baseDir . '/sources/Application/UI/Base/Layout/ActivityPanel/CaseLogEntryForm/CaseLogEntryForm.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\Dashboard\\DashboardColumn' => $baseDir . '/sources/Application/UI/Base/Layout/Dashboard/DashboardColumn.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\Dashboard\\DashboardLayout' => $baseDir . '/sources/Application/UI/Base/Layout/Dashboard/DashboardLayout.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\Dashboard\\DashboardRow' => $baseDir . '/sources/Application/UI/Base/Layout/Dashboard/DashboardRow.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\MultiColumn\\Column\\Column' => $baseDir . '/sources/Application/UI/Base/Layout/MultiColumn/Column/Column.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\MultiColumn\\Column\\ColumnUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Layout/MultiColumn/Column/ColumnUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\MultiColumn\\MultiColumn' => $baseDir . '/sources/Application/UI/Base/Layout/MultiColumn/MultiColumn.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\MultiColumn\\MultiColumnUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Layout/MultiColumn/MultiColumnUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\NavigationMenu\\NavigationMenu' => $baseDir . '/sources/Application/UI/Base/Layout/NavigationMenu/NavigationMenu.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\NavigationMenu\\NavigationMenuFactory' => $baseDir . '/sources/Application/UI/Base/Layout/NavigationMenu/NavigationMenuFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\Object\\ObjectDetails' => $baseDir . '/sources/Application/UI/Base/Layout/Object/ObjectDetails.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\Object\\ObjectFactory' => $baseDir . '/sources/Application/UI/Base/Layout/Object/ObjectFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\Object\\ObjectSummary' => $baseDir . '/sources/Application/UI/Base/Layout/Object/ObjectSummary.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\PageContent\\PageContent' => $baseDir . '/sources/Application/UI/Base/Layout/PageContent/PageContent.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\PageContent\\PageContentFactory' => $baseDir . '/sources/Application/UI/Base/Layout/PageContent/PageContentFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\PageContent\\PageContentWithSideContent' => $baseDir . '/sources/Application/UI/Base/Layout/PageContent/PageContentWithSideContent.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\TabContainer\\TabContainer' => $baseDir . '/sources/Application/UI/Base/Layout/TabContainer/TabContainer.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\TabContainer\\Tab\\AjaxTab' => $baseDir . '/sources/Application/UI/Base/Layout/TabContainer/Tab/AjaxTab.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\TabContainer\\Tab\\Tab' => $baseDir . '/sources/Application/UI/Base/Layout/TabContainer/Tab/Tab.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\TopBar\\TopBar' => $baseDir . '/sources/Application/UI/Base/Layout/TopBar/TopBar.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\TopBar\\TopBarFactory' => $baseDir . '/sources/Application/UI/Base/Layout/TopBar/TopBarFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\UIContentBlock' => $baseDir . '/sources/Application/UI/Base/Layout/UIContentBlock.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\UIContentBlockUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Layout/UIContentBlockUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\UIContentBlockWithJSRefreshCallback' => $baseDir . '/sources/Application/UI/Base/Layout/UIContentBlockWithJSRefreshCallback .php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\iUIContentBlock' => $baseDir . '/sources/Application/UI/Base/Layout/iUIContentBlock.php', - 'Combodo\\iTop\\Application\\UI\\Base\\UIBlock' => $baseDir . '/sources/Application/UI/Base/UIBlock.php', - 'Combodo\\iTop\\Application\\UI\\Base\\UIException' => $baseDir . '/sources/Application/UI/Base/UIException.php', - 'Combodo\\iTop\\Application\\UI\\Base\\iUIBlock' => $baseDir . '/sources/Application/UI/Base/iUIBlock.php', - 'Combodo\\iTop\\Application\\UI\\Base\\iUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/iUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\tJSRefreshCallback' => $baseDir . '/sources/Application/UI/Base/tJSRefreshCallback.php', - 'Combodo\\iTop\\Application\\UI\\Base\\tUIContentAreas' => $baseDir . '/sources/Application/UI/Base/tUIContentAreas.php', - 'Combodo\\iTop\\Application\\UI\\DisplayBlock\\BlockChartAjaxBars\\BlockChartAjaxBars' => $baseDir . '/sources/Application/UI/DisplayBlock/BlockChartAjaxBars/BlockChartAjaxBars.php', - 'Combodo\\iTop\\Application\\UI\\DisplayBlock\\BlockChartAjaxPie\\BlockChartAjaxPie' => $baseDir . '/sources/Application/UI/DisplayBlock/BlockChartAjaxPie/BlockChartAjaxPie.php', - 'Combodo\\iTop\\Application\\UI\\DisplayBlock\\BlockChart\\BlockChart' => $baseDir . '/sources/Application/UI/DisplayBlock/BlockChart/BlockChart.php', - 'Combodo\\iTop\\Application\\UI\\DisplayBlock\\BlockCsv\\BlockCsv' => $baseDir . '/sources/Application/UI/DisplayBlock/BlockCsv/BlockCsv.php', - 'Combodo\\iTop\\Application\\UI\\DisplayBlock\\BlockList\\BlockList' => $baseDir . '/sources/Application/UI/DisplayBlock/BlockList/BlockList.php', - 'Combodo\\iTop\\Application\\UI\\Helper\\UIHelper' => $baseDir . '/sources/Application/UI/Helper/UIHelper.php', - 'Combodo\\iTop\\Application\\UI\\Links\\AbstractBlockLinkSetViewTable' => $baseDir . '/sources/Application/UI/Links/AbstractBlockLinkSetViewTable.php', - 'Combodo\\iTop\\Application\\UI\\Links\\Direct\\BlockDirectLinkSetEditTable' => $baseDir . '/sources/Application/UI/Links/Direct/BlockDirectLinkSetEditTable.php', - 'Combodo\\iTop\\Application\\UI\\Links\\Direct\\BlockDirectLinkSetViewTable' => $baseDir . '/sources/Application/UI/Links/Direct/BlockDirectLinkSetViewTable.php', - 'Combodo\\iTop\\Application\\UI\\Links\\Indirect\\BlockIndirectLinkSetEditTable' => $baseDir . '/sources/Application/UI/Links/Indirect/BlockIndirectLinkSetEditTable.php', - 'Combodo\\iTop\\Application\\UI\\Links\\Indirect\\BlockIndirectLinkSetViewTable' => $baseDir . '/sources/Application/UI/Links/Indirect/BlockIndirectLinkSetViewTable.php', - 'Combodo\\iTop\\Application\\UI\\Links\\Indirect\\BlockObjectPickerDialog' => $baseDir . '/sources/Application/UI/Links/Indirect/BlockObjectPickerDialog.php', - 'Combodo\\iTop\\Application\\UI\\Links\\Set\\BlockLinkSetDisplayAsProperty' => $baseDir . '/sources/Application/UI/Links/Set/BlockLinksSetDisplayAsProperty.php', - 'Combodo\\iTop\\Application\\UI\\Links\\Set\\LinkSetUIBlockFactory' => $baseDir . '/sources/Application/UI/Links/Set/LinksSetUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Preferences\\BlockShortcuts\\BlockShortcuts' => $baseDir . '/sources/Application/UI/Preferences/BlockShortcuts/BlockShortcuts.php', - 'Combodo\\iTop\\Application\\UI\\Printable\\BlockPrintHeader\\BlockPrintHeader' => $baseDir . '/sources/Application/UI/Printable/BlockPrintHeader/BlockPrintHeader.php', - 'Combodo\\iTop\\Composer\\iTopComposer' => $baseDir . '/sources/Composer/iTopComposer.php', - 'Combodo\\iTop\\Controller\\AbstractController' => $baseDir . '/sources/Controller/AbstractController.php', - 'Combodo\\iTop\\Controller\\AjaxRenderController' => $baseDir . '/sources/Controller/AjaxRenderController.php', - 'Combodo\\iTop\\Controller\\Base\\Layout\\ActivityPanelController' => $baseDir . '/sources/Controller/Base/Layout/ActivityPanelController.php', - 'Combodo\\iTop\\Controller\\Base\\Layout\\ObjectController' => $baseDir . '/sources/Controller/Base/Layout/ObjectController.php', - 'Combodo\\iTop\\Controller\\Links\\LinkSetController' => $baseDir . '/sources/Controller/Links/LinkSetController.php', - 'Combodo\\iTop\\Controller\\OAuth\\OAuthLandingController' => $baseDir . '/sources/Controller/OAuth/OAuthLandingController.php', - 'Combodo\\iTop\\Controller\\PreferencesController' => $baseDir . '/sources/Controller/PreferencesController.php', - 'Combodo\\iTop\\Controller\\TemporaryObjects\\TemporaryObjectController' => $baseDir . '/sources/Controller/TemporaryObjects/TemporaryObjectController.php', - 'Combodo\\iTop\\Controller\\iController' => $baseDir . '/sources/Controller/iController.php', - 'Combodo\\iTop\\Core\\Authentication\\Client\\OAuth\\IOAuthClientProvider' => $baseDir . '/sources/Core/Authentication/Client/OAuth/IOAuthClientProvider.php', - 'Combodo\\iTop\\Core\\Authentication\\Client\\OAuth\\OAuthClientProviderAbstract' => $baseDir . '/sources/Core/Authentication/Client/OAuth/OAuthClientProviderAbstract.php', - 'Combodo\\iTop\\Core\\Authentication\\Client\\OAuth\\OAuthClientProviderAzure' => $baseDir . '/sources/Core/Authentication/Client/OAuth/OAuthClientProviderAzure.php', - 'Combodo\\iTop\\Core\\Authentication\\Client\\OAuth\\OAuthClientProviderFactory' => $baseDir . '/sources/Core/Authentication/Client/OAuth/OAuthClientProviderFactory.php', - 'Combodo\\iTop\\Core\\Authentication\\Client\\OAuth\\OAuthClientProviderGoogle' => $baseDir . '/sources/Core/Authentication/Client/OAuth/OAuthClientProviderGoogle.php', - 'Combodo\\iTop\\Core\\CMDBChange\\CMDBChangeOrigin' => $baseDir . '/sources/Core/CMDBChange/CMDBChangeOrigin.php', - 'Combodo\\iTop\\Core\\DbConnectionWrapper' => $baseDir . '/core/DbConnectionWrapper.php', - 'Combodo\\iTop\\Core\\Email\\EmailFactory' => $baseDir . '/sources/Core/Email/EmailFactory.php', - 'Combodo\\iTop\\Core\\Email\\iEMail' => $baseDir . '/sources/Core/Email/iEMail.php', - 'Combodo\\iTop\\Core\\EventListener\\AttributeBlobEventListener' => $baseDir . '/sources/Core/EventListener/AttributeBlobEventListener.php', - 'Combodo\\iTop\\Core\\Kpi\\KpiLogData' => $baseDir . '/sources/Core/Kpi/KpiLogData.php', - 'Combodo\\iTop\\Core\\MetaModel\\FriendlyNameType' => $baseDir . '/sources/Core/MetaModel/FriendlyNameType.php', - 'Combodo\\iTop\\Core\\MetaModel\\HierarchicalKey' => $baseDir . '/sources/Core/MetaModel/HierarchicalKey.php', - 'Combodo\\iTop\\DI\\Controller\\Controller' => $baseDir . '/sources/DI/Controller/Controller.php', - 'Combodo\\iTop\\DI\\Form\\Listener\\IFormTypeOptionModifier' => $baseDir . '/sources/DI/Form/Listener/IFormTypeOptionModifier.php', - 'Combodo\\iTop\\DI\\Form\\Listener\\ObjectFormListener' => $baseDir . '/sources/DI/Form/Listener/ObjectFormListener.php', - 'Combodo\\iTop\\DI\\Form\\Type\\ConfigurationType' => $baseDir . '/sources/DI/Form/Type/ConfigurationType.php', - 'Combodo\\iTop\\DI\\Form\\Type\\Layout\\AbstractContainerType' => $baseDir . '/sources/DI/Form/Type/Layout/AbstractContainerType.php', - 'Combodo\\iTop\\DI\\Form\\Type\\Layout\\ColumnType' => $baseDir . '/sources/DI/Form/Type/Layout/ColumnType.php', - 'Combodo\\iTop\\DI\\Form\\Type\\Layout\\FieldSetType' => $baseDir . '/sources/DI/Form/Type/Layout/FieldSetType.php', - 'Combodo\\iTop\\DI\\Form\\Type\\Layout\\RowType' => $baseDir . '/sources/DI/Form/Type/Layout/RowType.php', - 'Combodo\\iTop\\DI\\Form\\Type\\ObjectSingleAttributeType' => $baseDir . '/sources/DI/Form/Type/ObjectSingleAttributeType.php', - 'Combodo\\iTop\\DI\\Form\\Type\\ObjectType' => $baseDir . '/sources/DI/Form/Type/ObjectType.php', - 'Combodo\\iTop\\DI\\Form\\Type\\Simple\\DocumentType' => $baseDir . '/sources/DI/Form/Type/Simple/DocumentType.php', - 'Combodo\\iTop\\DI\\Form\\Type\\Simple\\ExternalKeyType' => $baseDir . '/sources/DI/Form/Type/Simple/ExternalKeyType.php', - 'Combodo\\iTop\\DI\\Form\\Type\\Simple\\LinkSetType' => $baseDir . '/sources/DI/Form/Type/Simple/LinkSetType.php', - 'Combodo\\iTop\\DI\\ITopKernel' => $baseDir . '/sources/DI/ITopKernel.php', - 'Combodo\\iTop\\DI\\Services\\ObjectPresentationService' => $baseDir . '/sources/DI/Services/ObjectPresentationService.php', - 'Combodo\\iTop\\DI\\Services\\ObjectService' => $baseDir . '/sources/DI/Services/ObjectService.php', - 'Combodo\\iTop\\DI\\Services\\TwigHelper' => $baseDir . '/sources/DI/Services/TwigHelper.php', - 'Combodo\\iTop\\DesignDocument' => $baseDir . '/core/designdocument.class.inc.php', - 'Combodo\\iTop\\DesignElement' => $baseDir . '/core/designdocument.class.inc.php', - 'Combodo\\iTop\\Form\\Field\\AbstractSimpleField' => $baseDir . '/sources/Form/Field/AbstractSimpleField.php', - 'Combodo\\iTop\\Form\\Field\\BlobField' => $baseDir . '/sources/Form/Field/BlobField.php', - 'Combodo\\iTop\\Form\\Field\\CaseLogField' => $baseDir . '/sources/Form/Field/CaseLogField.php', - 'Combodo\\iTop\\Form\\Field\\CheckboxField' => $baseDir . '/sources/Form/Field/CheckboxField.php', - 'Combodo\\iTop\\Form\\Field\\DateField' => $baseDir . '/sources/Form/Field/DateField.php', - 'Combodo\\iTop\\Form\\Field\\DateTimeField' => $baseDir . '/sources/Form/Field/DateTimeField.php', - 'Combodo\\iTop\\Form\\Field\\DurationField' => $baseDir . '/sources/Form/Field/DurationField.php', - 'Combodo\\iTop\\Form\\Field\\EmailField' => $baseDir . '/sources/Form/Field/EmailField.php', - 'Combodo\\iTop\\Form\\Field\\Field' => $baseDir . '/sources/Form/Field/Field.php', - 'Combodo\\iTop\\Form\\Field\\FileUploadField' => $baseDir . '/sources/Form/Field/FileUploadField.php', - 'Combodo\\iTop\\Form\\Field\\HiddenField' => $baseDir . '/sources/Form/Field/HiddenField.php', - 'Combodo\\iTop\\Form\\Field\\ImageField' => $baseDir . '/sources/Form/Field/ImageField.php', - 'Combodo\\iTop\\Form\\Field\\LabelField' => $baseDir . '/sources/Form/Field/LabelField.php', - 'Combodo\\iTop\\Form\\Field\\LinkedSetField' => $baseDir . '/sources/Form/Field/LinkedSetField.php', - 'Combodo\\iTop\\Form\\Field\\MultipleChoicesField' => $baseDir . '/sources/Form/Field/MultipleChoicesField.php', - 'Combodo\\iTop\\Form\\Field\\MultipleSelectField' => $baseDir . '/sources/Form/Field/MultipleSelectField.php', - 'Combodo\\iTop\\Form\\Field\\PasswordField' => $baseDir . '/sources/Form/Field/PasswordField.php', - 'Combodo\\iTop\\Form\\Field\\PhoneField' => $baseDir . '/sources/Form/Field/PhoneField.php', - 'Combodo\\iTop\\Form\\Field\\RadioField' => $baseDir . '/sources/Form/Field/RadioField.php', - 'Combodo\\iTop\\Form\\Field\\SelectField' => $baseDir . '/sources/Form/Field/SelectField.php', - 'Combodo\\iTop\\Form\\Field\\SelectObjectField' => $baseDir . '/sources/Form/Field/SelectObjectField.php', - 'Combodo\\iTop\\Form\\Field\\SetField' => $baseDir . '/sources/Form/Field/SetField.php', - 'Combodo\\iTop\\Form\\Field\\StringField' => $baseDir . '/sources/Form/Field/StringField.php', - 'Combodo\\iTop\\Form\\Field\\SubFormField' => $baseDir . '/sources/Form/Field/SubFormField.php', - 'Combodo\\iTop\\Form\\Field\\TagSetField' => $baseDir . '/sources/Form/Field/TagSetField.php', - 'Combodo\\iTop\\Form\\Field\\TextAreaField' => $baseDir . '/sources/Form/Field/TextAreaField.php', - 'Combodo\\iTop\\Form\\Field\\TextField' => $baseDir . '/sources/Form/Field/TextField.php', - 'Combodo\\iTop\\Form\\Field\\UrlField' => $baseDir . '/sources/Form/Field/UrlField.php', - 'Combodo\\iTop\\Form\\Form' => $baseDir . '/sources/Form/Form.php', - 'Combodo\\iTop\\Form\\FormManager' => $baseDir . '/sources/Form/FormManager.php', - 'Combodo\\iTop\\Form\\Helper\\FieldHelper' => $baseDir . '/sources/Form/Helper/FieldHelper.php', - 'Combodo\\iTop\\Form\\Validator\\AbstractRegexpValidator' => $baseDir . '/sources/Form/Validator/AbstractRegexpValidator.php', - 'Combodo\\iTop\\Form\\Validator\\AbstractValidator' => $baseDir . '/sources/Form/Validator/AbstractValidator.php', - 'Combodo\\iTop\\Form\\Validator\\CustomRegexpValidator' => $baseDir . '/sources/Form/Validator/CustomRegexpValidator.php', - 'Combodo\\iTop\\Form\\Validator\\IntegerValidator' => $baseDir . '/sources/Form/Validator/IntegerValidator.php', - 'Combodo\\iTop\\Form\\Validator\\LinkedSetValidator' => $baseDir . '/sources/Form/Validator/LinkedSetValidator.php', - 'Combodo\\iTop\\Form\\Validator\\MandatoryValidator' => $baseDir . '/sources/Form/Validator/MandatoryValidator.php', - 'Combodo\\iTop\\Form\\Validator\\MultipleChoicesValidator' => $baseDir . '/sources/Form/Validator/MultipleChoicesValidator.php', - 'Combodo\\iTop\\Form\\Validator\\NotEmptyExtKeyValidator' => $baseDir . '/sources/Form/Validator/NotEmptyExtKeyValidator.php', - 'Combodo\\iTop\\Form\\Validator\\SelectObjectValidator' => $baseDir . '/sources/Form/Validator/SelectObjectValidator.php', - 'Combodo\\iTop\\Form\\Validator\\Validator' => $baseDir . '/sources/Form/Validator/Validator.php', - 'Combodo\\iTop\\Renderer\\BlockRenderer' => $baseDir . '/sources/Renderer/BlockRenderer.php', - 'Combodo\\iTop\\Renderer\\Bootstrap\\BsFieldRendererMappings' => $baseDir . '/sources/Renderer/Bootstrap/BsFieldRendererMappings.php', - 'Combodo\\iTop\\Renderer\\Bootstrap\\BsFormRenderer' => $baseDir . '/sources/Renderer/Bootstrap/BsFormRenderer.php', - 'Combodo\\iTop\\Renderer\\Bootstrap\\FieldRenderer\\BsFieldRenderer' => $baseDir . '/sources/Renderer/Bootstrap/FieldRenderer/BsFieldRenderer.php', - 'Combodo\\iTop\\Renderer\\Bootstrap\\FieldRenderer\\BsFileUploadFieldRenderer' => $baseDir . '/sources/Renderer/Bootstrap/FieldRenderer/BsFileUploadFieldRenderer.php', - 'Combodo\\iTop\\Renderer\\Bootstrap\\FieldRenderer\\BsLinkedSetFieldRenderer' => $baseDir . '/sources/Renderer/Bootstrap/FieldRenderer/BsLinkedSetFieldRenderer.php', - 'Combodo\\iTop\\Renderer\\Bootstrap\\FieldRenderer\\BsSelectObjectFieldRenderer' => $baseDir . '/sources/Renderer/Bootstrap/FieldRenderer/BsSelectObjectFieldRenderer.php', - 'Combodo\\iTop\\Renderer\\Bootstrap\\FieldRenderer\\BsSetFieldRenderer' => $baseDir . '/sources/Renderer/Bootstrap/FieldRenderer/BsSetFieldRenderer.php', - 'Combodo\\iTop\\Renderer\\Bootstrap\\FieldRenderer\\BsSimpleFieldRenderer' => $baseDir . '/sources/Renderer/Bootstrap/FieldRenderer/BsSimpleFieldRenderer.php', - 'Combodo\\iTop\\Renderer\\Bootstrap\\FieldRenderer\\BsSubFormFieldRenderer' => $baseDir . '/sources/Renderer/Bootstrap/FieldRenderer/BsSubFormFieldRenderer.php', - 'Combodo\\iTop\\Renderer\\Console\\ConsoleBlockRenderer' => $baseDir . '/sources/Renderer/Console/ConsoleBlockRenderer.php', - 'Combodo\\iTop\\Renderer\\Console\\ConsoleFieldRendererMappings' => $baseDir . '/sources/Renderer/Console/ConsoleFieldRendererMappings.php', - 'Combodo\\iTop\\Renderer\\Console\\ConsoleFormRenderer' => $baseDir . '/sources/Renderer/Console/ConsoleFormRenderer.php', - 'Combodo\\iTop\\Renderer\\Console\\FieldRenderer\\ConsoleSelectObjectFieldRenderer' => $baseDir . '/sources/Renderer/Console/FieldRenderer/ConsoleSelectObjectFieldRenderer.php', - 'Combodo\\iTop\\Renderer\\Console\\FieldRenderer\\ConsoleSimpleFieldRenderer' => $baseDir . '/sources/Renderer/Console/FieldRenderer/ConsoleSimpleFieldRenderer.php', - 'Combodo\\iTop\\Renderer\\Console\\FieldRenderer\\ConsoleSubFormFieldRenderer' => $baseDir . '/sources/Renderer/Console/FieldRenderer/ConsoleSubFormFieldRenderer.php', - 'Combodo\\iTop\\Renderer\\FieldRenderer' => $baseDir . '/sources/Renderer/FieldRenderer.php', - 'Combodo\\iTop\\Renderer\\FormRenderer' => $baseDir . '/sources/Renderer/FormRenderer.php', - 'Combodo\\iTop\\Renderer\\RenderingOutput' => $baseDir . '/sources/Renderer/RenderingOutput.php', - 'Combodo\\iTop\\Service\\Base\\ObjectRepository' => $baseDir . '/sources/Service/Base/ObjectRepository.php', - 'Combodo\\iTop\\Service\\Base\\iDataPostProcessor' => $baseDir . '/sources/Service/Base/iDataPostProcessor.php', - 'Combodo\\iTop\\Service\\Events\\Description\\EventDataDescription' => $baseDir . '/sources/Service/Events/Description/EventDataDescription.php', - 'Combodo\\iTop\\Service\\Events\\Description\\EventDescription' => $baseDir . '/sources/Service/Events/Description/EventDescription.php', - 'Combodo\\iTop\\Service\\Events\\EventData' => $baseDir . '/sources/Service/Events/EventData.php', - 'Combodo\\iTop\\Service\\Events\\EventException' => $baseDir . '/sources/Service/Events/EventException.php', - 'Combodo\\iTop\\Service\\Events\\EventHelper' => $baseDir . '/sources/Service/Events/EventHelper.php', - 'Combodo\\iTop\\Service\\Events\\EventService' => $baseDir . '/sources/Service/Events/EventService.php', - 'Combodo\\iTop\\Service\\Events\\EventServiceLog' => $baseDir . '/sources/Service/Events/EventServiceLog.php', - 'Combodo\\iTop\\Service\\Events\\iEventServiceSetup' => $baseDir . '/sources/Service/Events/iEventServiceSetup.php', - 'Combodo\\iTop\\Service\\Links\\LinkSetDataTransformer' => $baseDir . '/sources/Service/Links/LinkSetDataTransformer.php', - 'Combodo\\iTop\\Service\\Links\\LinkSetModel' => $baseDir . '/sources/Service/Links/LinkSetModel.php', - 'Combodo\\iTop\\Service\\Links\\LinkSetRepository' => $baseDir . '/sources/Service/Links/LinkSetRepository.php', - 'Combodo\\iTop\\Service\\Links\\LinksBulkDataPostProcessor' => $baseDir . '/sources/Service/Links/LinksBulkDataPostProcessor.php', - 'Combodo\\iTop\\Service\\Module\\ModuleService' => $baseDir . '/sources/Service/Module/ModuleService.php', - 'Combodo\\iTop\\Service\\Router\\Exception\\RouteNotFoundException' => $baseDir . '/sources/Service/Router/Exception/RouteNotFoundException.php', - 'Combodo\\iTop\\Service\\Router\\Exception\\RouterException' => $baseDir . '/sources/Service/Router/Exception/RouterException.php', - 'Combodo\\iTop\\Service\\Router\\Router' => $baseDir . '/sources/Service/Router/Router.php', - 'Combodo\\iTop\\Service\\TemporaryObjects\\TemporaryObjectConfig' => $baseDir . '/sources/Service/TemporaryObjects/TemporaryObjectConfig.php', - 'Combodo\\iTop\\Service\\TemporaryObjects\\TemporaryObjectGC' => $baseDir . '/sources/Service/TemporaryObjects/TemporaryObjectGC.php', - 'Combodo\\iTop\\Service\\TemporaryObjects\\TemporaryObjectHelper' => $baseDir . '/sources/Service/TemporaryObjects/TemporaryObjectHelper.php', - 'Combodo\\iTop\\Service\\TemporaryObjects\\TemporaryObjectManager' => $baseDir . '/sources/Service/TemporaryObjects/TemporaryObjectManager.php', - 'Combodo\\iTop\\Service\\TemporaryObjects\\TemporaryObjectRepository' => $baseDir . '/sources/Service/TemporaryObjects/TemporaryObjectRepository.php', - 'Combodo\\iTop\\Service\\TemporaryObjects\\TemporaryObjectsEvents' => $baseDir . '/sources/Service/TemporaryObjects/TemporaryObjectsEvents.php', - 'CompileCSSService' => $baseDir . '/application/compilecssservice.class.inc.php', - 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', - 'Config' => $baseDir . '/core/config.class.inc.php', - 'ConfigException' => $baseDir . '/application/exceptions/ConfigException.php', - 'ConfigPlaceholdersResolver' => $baseDir . '/core/config.class.inc.php', - 'Console_Getopt' => $vendorDir . '/pear/console_getopt/Console/Getopt.php', - 'ContextTag' => $baseDir . '/core/contexttag.class.inc.php', - 'CoreCannotSaveObjectException' => $baseDir . '/application/exceptions/CoreCannotSaveObjectException.php', - 'CoreException' => $baseDir . '/application/exceptions/CoreException.php', - 'CoreOqlException' => $baseDir . '/application/exceptions/oql/CoreOqlException.php', - 'CoreOqlMultipleResultsForbiddenException' => $baseDir . '/application/exceptions/oql/CoreOqlMultipleResultsForbiddenException.php', - 'CorePortalInvalidActionRuleException' => $baseDir . '/application/exceptions/CorePortalInvalidActionRuleException.php', - 'CoreServices' => $baseDir . '/core/restservices.class.inc.php', - 'CoreTemplateException' => $baseDir . '/application/exceptions/CoreTemplateException.php', - 'CoreUnexpectedValue' => $baseDir . '/application/exceptions/CoreUnexpectedValue.php', - 'CoreWarning' => $baseDir . '/application/exceptions/CoreWarning.php', - 'CryptEngine' => $baseDir . '/core/simplecrypt.class.inc.php', - 'CustomFieldsHandler' => $baseDir . '/core/customfieldshandler.class.inc.php', - 'DBObject' => $baseDir . '/core/dbobject.class.php', - 'DBObjectSearch' => $baseDir . '/core/dbobjectsearch.class.php', - 'DBObjectSet' => $baseDir . '/core/dbobjectset.class.php', - 'DBObjectSetComparator' => $baseDir . '/core/dbobjectset.class.php', - 'DBProperty' => $baseDir . '/core/dbproperty.class.inc.php', - 'DBSearch' => $baseDir . '/core/dbsearch.class.php', - 'DBSearchHelper' => $baseDir . '/application/DBSearchHelper.php', - 'DBUnionSearch' => $baseDir . '/core/dbunionsearch.class.php', - 'DOMSanitizer' => $baseDir . '/core/htmlsanitizer.class.inc.php', - 'DailyRotatingLogFileNameBuilder' => $baseDir . '/core/log.class.inc.php', - 'Dashboard' => $baseDir . '/application/dashboard.class.inc.php', - 'DashboardLayout' => $baseDir . '/application/dashboardlayout.class.inc.php', - 'DashboardLayoutMultiCol' => $baseDir . '/application/dashboardlayout.class.inc.php', - 'DashboardLayoutOneCol' => $baseDir . '/application/dashboardlayout.class.inc.php', - 'DashboardLayoutThreeCols' => $baseDir . '/application/dashboardlayout.class.inc.php', - 'DashboardLayoutTwoCols' => $baseDir . '/application/dashboardlayout.class.inc.php', - 'DashboardMenuNode' => $baseDir . '/application/menunode.class.inc.php', - 'Dashlet' => $baseDir . '/application/dashlet.class.inc.php', - 'DashletBadge' => $baseDir . '/application/dashlet.class.inc.php', - 'DashletEmptyCell' => $baseDir . '/application/dashlet.class.inc.php', - 'DashletGroupBy' => $baseDir . '/application/dashlet.class.inc.php', - 'DashletGroupByBars' => $baseDir . '/application/dashlet.class.inc.php', - 'DashletGroupByPie' => $baseDir . '/application/dashlet.class.inc.php', - 'DashletGroupByTable' => $baseDir . '/application/dashlet.class.inc.php', - 'DashletHeaderDynamic' => $baseDir . '/application/dashlet.class.inc.php', - 'DashletHeaderStatic' => $baseDir . '/application/dashlet.class.inc.php', - 'DashletObjectList' => $baseDir . '/application/dashlet.class.inc.php', - 'DashletPlainText' => $baseDir . '/application/dashlet.class.inc.php', - 'DashletProxy' => $baseDir . '/application/dashlet.class.inc.php', - 'DashletUnknown' => $baseDir . '/application/dashlet.class.inc.php', - 'DataTable' => $baseDir . '/application/datatable.class.inc.php', - 'DataTableConfig' => $baseDir . '/sources/Application/UI/Base/Component/DataTable/DataTableConfig/DataTableConfig.php', - 'Datamatrix' => $vendorDir . '/combodo/tcpdf/include/barcodes/datamatrix.php', - 'DateTimeFormat' => $baseDir . '/core/datetimeformat.class.inc.php', - 'DeadLockLog' => $baseDir . '/core/log.class.inc.php', - 'DefaultLogFileNameBuilder' => $baseDir . '/core/log.class.inc.php', - 'DefaultMetricComputer' => $baseDir . '/core/computing.inc.php', - 'DefaultWorkingTimeComputer' => $baseDir . '/core/computing.inc.php', - 'DeleteException' => $baseDir . '/application/exceptions/DeleteException.php', - 'DeletionPlan' => $baseDir . '/core/deletionplan.class.inc.php', - 'DeprecatedCallsLog' => $baseDir . '/core/log.class.inc.php', - 'DesignerBooleanField' => $baseDir . '/application/forms.class.inc.php', - 'DesignerComboField' => $baseDir . '/application/forms.class.inc.php', - 'DesignerForm' => $baseDir . '/application/forms.class.inc.php', - 'DesignerFormField' => $baseDir . '/application/forms.class.inc.php', - 'DesignerFormSelectorField' => $baseDir . '/application/forms.class.inc.php', - 'DesignerHiddenField' => $baseDir . '/application/forms.class.inc.php', - 'DesignerIconSelectionField' => $baseDir . '/application/forms.class.inc.php', - 'DesignerIntegerField' => $baseDir . '/application/forms.class.inc.php', - 'DesignerLabelField' => $baseDir . '/application/forms.class.inc.php', - 'DesignerLongTextField' => $baseDir . '/application/forms.class.inc.php', - 'DesignerSortableField' => $baseDir . '/application/forms.class.inc.php', - 'DesignerStaticTextField' => $baseDir . '/application/forms.class.inc.php', - 'DesignerSubFormField' => $baseDir . '/application/forms.class.inc.php', - 'DesignerTabularForm' => $baseDir . '/application/forms.class.inc.php', - 'DesignerTextField' => $baseDir . '/application/forms.class.inc.php', - 'DesignerXMLField' => $baseDir . '/application/forms.class.inc.php', - 'Dict' => $baseDir . '/core/dict.class.inc.php', - 'DictException' => $baseDir . '/application/exceptions/dict/DictException.php', - 'DictExceptionMissingString' => $baseDir . '/application/exceptions/dict/DictExceptionMissingString.php', - 'DictExceptionUnknownLanguage' => $baseDir . '/application/exceptions/dict/DictExceptionUnknownLanguage.php', - 'DisplayBlock' => $baseDir . '/application/displayblock.class.inc.php', - 'DisplayTemplate' => $baseDir . '/application/template.class.inc.php', - 'DisplayableEdge' => $baseDir . '/core/displayablegraph.class.inc.php', - 'DisplayableGraph' => $baseDir . '/core/displayablegraph.class.inc.php', - 'DisplayableGroupNode' => $baseDir . '/core/displayablegraph.class.inc.php', - 'DisplayableNode' => $baseDir . '/core/displayablegraph.class.inc.php', - 'DisplayableRedundancyNode' => $baseDir . '/core/displayablegraph.class.inc.php', - 'Doctrine\\Common\\Annotations\\Annotation' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php', - 'Doctrine\\Common\\Annotations\\AnnotationException' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php', - 'Doctrine\\Common\\Annotations\\AnnotationReader' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php', - 'Doctrine\\Common\\Annotations\\AnnotationRegistry' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php', - 'Doctrine\\Common\\Annotations\\Annotation\\Attribute' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php', - 'Doctrine\\Common\\Annotations\\Annotation\\Attributes' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attributes.php', - 'Doctrine\\Common\\Annotations\\Annotation\\Enum' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php', - 'Doctrine\\Common\\Annotations\\Annotation\\IgnoreAnnotation' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php', - 'Doctrine\\Common\\Annotations\\Annotation\\NamedArgumentConstructor' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/NamedArgumentConstructor.php', - 'Doctrine\\Common\\Annotations\\Annotation\\Required' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Required.php', - 'Doctrine\\Common\\Annotations\\Annotation\\Target' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Target.php', - 'Doctrine\\Common\\Annotations\\DocLexer' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php', - 'Doctrine\\Common\\Annotations\\DocParser' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php', - 'Doctrine\\Common\\Annotations\\ImplicitlyIgnoredAnnotationNames' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/ImplicitlyIgnoredAnnotationNames.php', - 'Doctrine\\Common\\Annotations\\IndexedReader' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php', - 'Doctrine\\Common\\Annotations\\PhpParser' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/PhpParser.php', - 'Doctrine\\Common\\Annotations\\PsrCachedReader' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/PsrCachedReader.php', - 'Doctrine\\Common\\Annotations\\Reader' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php', - 'Doctrine\\Common\\Annotations\\TokenParser' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php', - 'Doctrine\\Common\\Cache\\Cache' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/Cache.php', - 'Doctrine\\Common\\Cache\\CacheProvider' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/CacheProvider.php', - 'Doctrine\\Common\\Cache\\ClearableCache' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/ClearableCache.php', - 'Doctrine\\Common\\Cache\\FlushableCache' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/FlushableCache.php', - 'Doctrine\\Common\\Cache\\MultiDeleteCache' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/MultiDeleteCache.php', - 'Doctrine\\Common\\Cache\\MultiGetCache' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/MultiGetCache.php', - 'Doctrine\\Common\\Cache\\MultiOperationCache' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/MultiOperationCache.php', - 'Doctrine\\Common\\Cache\\MultiPutCache' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/MultiPutCache.php', - 'Doctrine\\Common\\Cache\\Psr6\\CacheAdapter' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/CacheAdapter.php', - 'Doctrine\\Common\\Cache\\Psr6\\CacheItem' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/CacheItem.php', - 'Doctrine\\Common\\Cache\\Psr6\\DoctrineProvider' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/DoctrineProvider.php', - 'Doctrine\\Common\\Cache\\Psr6\\InvalidArgument' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/InvalidArgument.php', - 'Doctrine\\Common\\Cache\\Psr6\\TypedCacheItem' => $vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/TypedCacheItem.php', - 'Doctrine\\Common\\Lexer\\AbstractLexer' => $vendorDir . '/doctrine/lexer/src/AbstractLexer.php', - 'Doctrine\\Common\\Lexer\\Token' => $vendorDir . '/doctrine/lexer/src/Token.php', - 'Doctrine\\Deprecations\\Deprecation' => $vendorDir . '/doctrine/deprecations/lib/Doctrine/Deprecations/Deprecation.php', - 'Doctrine\\Deprecations\\PHPUnit\\VerifyDeprecations' => $vendorDir . '/doctrine/deprecations/lib/Doctrine/Deprecations/PHPUnit/VerifyDeprecations.php', - 'DownloadPage' => $baseDir . '/sources/Application/WebPage/DownloadPage.php', - 'EMail' => $baseDir . '/core/email.class.inc.php', - 'EMailLaminas' => $baseDir . '/sources/Core/Email/EmailLaminas.php', - 'ErrorPage' => $baseDir . '/sources/Application/WebPage/ErrorPage.php', - 'Event' => $baseDir . '/core/event.class.inc.php', - 'EventIssue' => $baseDir . '/core/event.class.inc.php', - 'EventLoginUsage' => $baseDir . '/core/event.class.inc.php', - 'EventNotification' => $baseDir . '/core/event.class.inc.php', - 'EventNotificationEmail' => $baseDir . '/core/event.class.inc.php', - 'EventOnObject' => $baseDir . '/core/event.class.inc.php', - 'EventRestService' => $baseDir . '/core/event.class.inc.php', - 'EventWebService' => $baseDir . '/core/event.class.inc.php', - 'ExcelBulkExport' => $baseDir . '/core/excelbulkexport.class.inc.php', - 'ExcelExporter' => $baseDir . '/application/excelexporter.class.inc.php', - 'ExceptionLog' => $baseDir . '/core/log.class.inc.php', - 'ExecAsyncTask' => $baseDir . '/core/asynctask.class.inc.php', - 'ExecutionKPI' => $baseDir . '/core/kpi.class.inc.php', - 'Expression' => $baseDir . '/core/oql/expression.class.inc.php', - 'ExpressionCache' => $baseDir . '/core/expressioncache.class.inc.php', - 'ExpressionHelper' => $baseDir . '/core/oql/expression.class.inc.php', - 'FalseExpression' => $baseDir . '/core/oql/expression.class.inc.php', - 'FieldExpression' => $baseDir . '/core/oql/expression.class.inc.php', - 'FieldExpressionResolved' => $baseDir . '/core/oql/expression.class.inc.php', - 'FieldOqlExpression' => $baseDir . '/core/oql/oqlquery.class.inc.php', - 'FileLog' => $baseDir . '/core/log.class.inc.php', - 'FileUploadException' => $baseDir . '/application/utils.inc.php', - 'FilterDefinition' => $baseDir . '/core/filterdef.class.inc.php', - 'FilterFromAttribute' => $baseDir . '/core/filterdef.class.inc.php', - 'FilterPrivateKey' => $baseDir . '/core/filterdef.class.inc.php', - 'FindStylesheetObject' => $baseDir . '/application/findstylesheetobject.class.inc.php', - 'Firebase\\JWT\\BeforeValidException' => $vendorDir . '/firebase/php-jwt/src/BeforeValidException.php', - 'Firebase\\JWT\\CachedKeySet' => $vendorDir . '/firebase/php-jwt/src/CachedKeySet.php', - 'Firebase\\JWT\\ExpiredException' => $vendorDir . '/firebase/php-jwt/src/ExpiredException.php', - 'Firebase\\JWT\\JWK' => $vendorDir . '/firebase/php-jwt/src/JWK.php', - 'Firebase\\JWT\\JWT' => $vendorDir . '/firebase/php-jwt/src/JWT.php', - 'Firebase\\JWT\\Key' => $vendorDir . '/firebase/php-jwt/src/Key.php', - 'Firebase\\JWT\\SignatureInvalidException' => $vendorDir . '/firebase/php-jwt/src/SignatureInvalidException.php', - 'FunctionExpression' => $baseDir . '/core/oql/expression.class.inc.php', - 'FunctionOqlExpression' => $baseDir . '/core/oql/oqlquery.class.inc.php', - 'GraphEdge' => $baseDir . '/core/simplegraph.class.inc.php', - 'GraphElement' => $baseDir . '/core/simplegraph.class.inc.php', - 'GraphNode' => $baseDir . '/core/simplegraph.class.inc.php', - 'GuzzleHttp\\BodySummarizer' => $vendorDir . '/guzzlehttp/guzzle/src/BodySummarizer.php', - 'GuzzleHttp\\BodySummarizerInterface' => $vendorDir . '/guzzlehttp/guzzle/src/BodySummarizerInterface.php', - 'GuzzleHttp\\Client' => $vendorDir . '/guzzlehttp/guzzle/src/Client.php', - 'GuzzleHttp\\ClientInterface' => $vendorDir . '/guzzlehttp/guzzle/src/ClientInterface.php', - 'GuzzleHttp\\ClientTrait' => $vendorDir . '/guzzlehttp/guzzle/src/ClientTrait.php', - 'GuzzleHttp\\Cookie\\CookieJar' => $vendorDir . '/guzzlehttp/guzzle/src/Cookie/CookieJar.php', - 'GuzzleHttp\\Cookie\\CookieJarInterface' => $vendorDir . '/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php', - 'GuzzleHttp\\Cookie\\FileCookieJar' => $vendorDir . '/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php', - 'GuzzleHttp\\Cookie\\SessionCookieJar' => $vendorDir . '/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php', - 'GuzzleHttp\\Cookie\\SetCookie' => $vendorDir . '/guzzlehttp/guzzle/src/Cookie/SetCookie.php', - 'GuzzleHttp\\Exception\\BadResponseException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/BadResponseException.php', - 'GuzzleHttp\\Exception\\ClientException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/ClientException.php', - 'GuzzleHttp\\Exception\\ConnectException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/ConnectException.php', - 'GuzzleHttp\\Exception\\GuzzleException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/GuzzleException.php', - 'GuzzleHttp\\Exception\\InvalidArgumentException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/InvalidArgumentException.php', - 'GuzzleHttp\\Exception\\RequestException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/RequestException.php', - 'GuzzleHttp\\Exception\\ServerException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/ServerException.php', - 'GuzzleHttp\\Exception\\TooManyRedirectsException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php', - 'GuzzleHttp\\Exception\\TransferException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/TransferException.php', - 'GuzzleHttp\\HandlerStack' => $vendorDir . '/guzzlehttp/guzzle/src/HandlerStack.php', - 'GuzzleHttp\\Handler\\CurlFactory' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/CurlFactory.php', - 'GuzzleHttp\\Handler\\CurlFactoryInterface' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php', - 'GuzzleHttp\\Handler\\CurlHandler' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/CurlHandler.php', - 'GuzzleHttp\\Handler\\CurlMultiHandler' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php', - 'GuzzleHttp\\Handler\\EasyHandle' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/EasyHandle.php', - 'GuzzleHttp\\Handler\\HeaderProcessor' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/HeaderProcessor.php', - 'GuzzleHttp\\Handler\\MockHandler' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/MockHandler.php', - 'GuzzleHttp\\Handler\\Proxy' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/Proxy.php', - 'GuzzleHttp\\Handler\\StreamHandler' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/StreamHandler.php', - 'GuzzleHttp\\MessageFormatter' => $vendorDir . '/guzzlehttp/guzzle/src/MessageFormatter.php', - 'GuzzleHttp\\MessageFormatterInterface' => $vendorDir . '/guzzlehttp/guzzle/src/MessageFormatterInterface.php', - 'GuzzleHttp\\Middleware' => $vendorDir . '/guzzlehttp/guzzle/src/Middleware.php', - 'GuzzleHttp\\Pool' => $vendorDir . '/guzzlehttp/guzzle/src/Pool.php', - 'GuzzleHttp\\PrepareBodyMiddleware' => $vendorDir . '/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php', - 'GuzzleHttp\\Promise\\AggregateException' => $vendorDir . '/guzzlehttp/promises/src/AggregateException.php', - 'GuzzleHttp\\Promise\\CancellationException' => $vendorDir . '/guzzlehttp/promises/src/CancellationException.php', - 'GuzzleHttp\\Promise\\Coroutine' => $vendorDir . '/guzzlehttp/promises/src/Coroutine.php', - 'GuzzleHttp\\Promise\\Create' => $vendorDir . '/guzzlehttp/promises/src/Create.php', - 'GuzzleHttp\\Promise\\Each' => $vendorDir . '/guzzlehttp/promises/src/Each.php', - 'GuzzleHttp\\Promise\\EachPromise' => $vendorDir . '/guzzlehttp/promises/src/EachPromise.php', - 'GuzzleHttp\\Promise\\FulfilledPromise' => $vendorDir . '/guzzlehttp/promises/src/FulfilledPromise.php', - 'GuzzleHttp\\Promise\\Is' => $vendorDir . '/guzzlehttp/promises/src/Is.php', - 'GuzzleHttp\\Promise\\Promise' => $vendorDir . '/guzzlehttp/promises/src/Promise.php', - 'GuzzleHttp\\Promise\\PromiseInterface' => $vendorDir . '/guzzlehttp/promises/src/PromiseInterface.php', - 'GuzzleHttp\\Promise\\PromisorInterface' => $vendorDir . '/guzzlehttp/promises/src/PromisorInterface.php', - 'GuzzleHttp\\Promise\\RejectedPromise' => $vendorDir . '/guzzlehttp/promises/src/RejectedPromise.php', - 'GuzzleHttp\\Promise\\RejectionException' => $vendorDir . '/guzzlehttp/promises/src/RejectionException.php', - 'GuzzleHttp\\Promise\\TaskQueue' => $vendorDir . '/guzzlehttp/promises/src/TaskQueue.php', - 'GuzzleHttp\\Promise\\TaskQueueInterface' => $vendorDir . '/guzzlehttp/promises/src/TaskQueueInterface.php', - 'GuzzleHttp\\Promise\\Utils' => $vendorDir . '/guzzlehttp/promises/src/Utils.php', - 'GuzzleHttp\\Psr7\\AppendStream' => $vendorDir . '/guzzlehttp/psr7/src/AppendStream.php', - 'GuzzleHttp\\Psr7\\BufferStream' => $vendorDir . '/guzzlehttp/psr7/src/BufferStream.php', - 'GuzzleHttp\\Psr7\\CachingStream' => $vendorDir . '/guzzlehttp/psr7/src/CachingStream.php', - 'GuzzleHttp\\Psr7\\DroppingStream' => $vendorDir . '/guzzlehttp/psr7/src/DroppingStream.php', - 'GuzzleHttp\\Psr7\\Exception\\MalformedUriException' => $vendorDir . '/guzzlehttp/psr7/src/Exception/MalformedUriException.php', - 'GuzzleHttp\\Psr7\\FnStream' => $vendorDir . '/guzzlehttp/psr7/src/FnStream.php', - 'GuzzleHttp\\Psr7\\Header' => $vendorDir . '/guzzlehttp/psr7/src/Header.php', - 'GuzzleHttp\\Psr7\\HttpFactory' => $vendorDir . '/guzzlehttp/psr7/src/HttpFactory.php', - 'GuzzleHttp\\Psr7\\InflateStream' => $vendorDir . '/guzzlehttp/psr7/src/InflateStream.php', - 'GuzzleHttp\\Psr7\\LazyOpenStream' => $vendorDir . '/guzzlehttp/psr7/src/LazyOpenStream.php', - 'GuzzleHttp\\Psr7\\LimitStream' => $vendorDir . '/guzzlehttp/psr7/src/LimitStream.php', - 'GuzzleHttp\\Psr7\\Message' => $vendorDir . '/guzzlehttp/psr7/src/Message.php', - 'GuzzleHttp\\Psr7\\MessageTrait' => $vendorDir . '/guzzlehttp/psr7/src/MessageTrait.php', - 'GuzzleHttp\\Psr7\\MimeType' => $vendorDir . '/guzzlehttp/psr7/src/MimeType.php', - 'GuzzleHttp\\Psr7\\MultipartStream' => $vendorDir . '/guzzlehttp/psr7/src/MultipartStream.php', - 'GuzzleHttp\\Psr7\\NoSeekStream' => $vendorDir . '/guzzlehttp/psr7/src/NoSeekStream.php', - 'GuzzleHttp\\Psr7\\PumpStream' => $vendorDir . '/guzzlehttp/psr7/src/PumpStream.php', - 'GuzzleHttp\\Psr7\\Query' => $vendorDir . '/guzzlehttp/psr7/src/Query.php', - 'GuzzleHttp\\Psr7\\Request' => $vendorDir . '/guzzlehttp/psr7/src/Request.php', - 'GuzzleHttp\\Psr7\\Response' => $vendorDir . '/guzzlehttp/psr7/src/Response.php', - 'GuzzleHttp\\Psr7\\Rfc7230' => $vendorDir . '/guzzlehttp/psr7/src/Rfc7230.php', - 'GuzzleHttp\\Psr7\\ServerRequest' => $vendorDir . '/guzzlehttp/psr7/src/ServerRequest.php', - 'GuzzleHttp\\Psr7\\Stream' => $vendorDir . '/guzzlehttp/psr7/src/Stream.php', - 'GuzzleHttp\\Psr7\\StreamDecoratorTrait' => $vendorDir . '/guzzlehttp/psr7/src/StreamDecoratorTrait.php', - 'GuzzleHttp\\Psr7\\StreamWrapper' => $vendorDir . '/guzzlehttp/psr7/src/StreamWrapper.php', - 'GuzzleHttp\\Psr7\\UploadedFile' => $vendorDir . '/guzzlehttp/psr7/src/UploadedFile.php', - 'GuzzleHttp\\Psr7\\Uri' => $vendorDir . '/guzzlehttp/psr7/src/Uri.php', - 'GuzzleHttp\\Psr7\\UriComparator' => $vendorDir . '/guzzlehttp/psr7/src/UriComparator.php', - 'GuzzleHttp\\Psr7\\UriNormalizer' => $vendorDir . '/guzzlehttp/psr7/src/UriNormalizer.php', - 'GuzzleHttp\\Psr7\\UriResolver' => $vendorDir . '/guzzlehttp/psr7/src/UriResolver.php', - 'GuzzleHttp\\Psr7\\Utils' => $vendorDir . '/guzzlehttp/psr7/src/Utils.php', - 'GuzzleHttp\\RedirectMiddleware' => $vendorDir . '/guzzlehttp/guzzle/src/RedirectMiddleware.php', - 'GuzzleHttp\\RequestOptions' => $vendorDir . '/guzzlehttp/guzzle/src/RequestOptions.php', - 'GuzzleHttp\\RetryMiddleware' => $vendorDir . '/guzzlehttp/guzzle/src/RetryMiddleware.php', - 'GuzzleHttp\\TransferStats' => $vendorDir . '/guzzlehttp/guzzle/src/TransferStats.php', - 'GuzzleHttp\\Utils' => $vendorDir . '/guzzlehttp/guzzle/src/Utils.php', - 'HTMLBulkExport' => $baseDir . '/core/htmlbulkexport.class.inc.php', - 'HTMLDOMSanitizer' => $baseDir . '/core/htmlsanitizer.class.inc.php', - 'HTMLNullSanitizer' => $baseDir . '/core/htmlsanitizer.class.inc.php', - 'HTMLSanitizer' => $baseDir . '/core/htmlsanitizer.class.inc.php', - 'Html2Text\\Html2Text' => $baseDir . '/application/Html2Text.php', - 'Html2Text\\Html2TextException' => $baseDir . '/application/Html2TextException.php', - 'ITopArchiveTar' => $baseDir . '/core/tar-itop.class.inc.php', - 'InlineImage' => $baseDir . '/core/inlineimage.class.inc.php', - 'InlineImageGC' => $baseDir . '/core/inlineimage.class.inc.php', - 'InputOutputTask' => $baseDir . '/application/iotask.class.inc.php', - 'IntervalExpression' => $baseDir . '/core/oql/expression.class.inc.php', - 'IntervalOqlExpression' => $baseDir . '/core/oql/oqlquery.class.inc.php', - 'IntlDateFormatter' => $vendorDir . '/symfony/polyfill-intl-icu/Resources/stubs/IntlDateFormatter.php', - 'Introspection' => $baseDir . '/core/introspection.class.inc.php', - 'InvalidConfigParamException' => $baseDir . '/application/exceptions/InvalidConfigParamException.php', - 'InvalidPasswordAttributeOneWayPassword' => $baseDir . '/application/exceptions/InvalidPasswordAttributeOneWayPassword.php', - 'IssueLog' => $baseDir . '/core/log.class.inc.php', - 'ItopCounter' => $baseDir . '/core/counter.class.inc.php', - 'JSButtonItem' => $baseDir . '/application/applicationextension.inc.php', - 'JSPopupMenuItem' => $baseDir . '/application/applicationextension.inc.php', - 'JsonException' => $vendorDir . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', - 'JsonPPage' => $baseDir . '/sources/Application/WebPage/JsonPPage.php', - 'JsonPage' => $baseDir . '/sources/Application/WebPage/JsonPage.php', - 'KeyValueStore' => $baseDir . '/core/counter.class.inc.php', - 'Laminas\\Loader\\AutoloaderFactory' => $vendorDir . '/laminas/laminas-loader/src/AutoloaderFactory.php', - 'Laminas\\Loader\\ClassMapAutoloader' => $vendorDir . '/laminas/laminas-loader/src/ClassMapAutoloader.php', - 'Laminas\\Loader\\Exception\\BadMethodCallException' => $vendorDir . '/laminas/laminas-loader/src/Exception/BadMethodCallException.php', - 'Laminas\\Loader\\Exception\\DomainException' => $vendorDir . '/laminas/laminas-loader/src/Exception/DomainException.php', - 'Laminas\\Loader\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-loader/src/Exception/ExceptionInterface.php', - 'Laminas\\Loader\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-loader/src/Exception/InvalidArgumentException.php', - 'Laminas\\Loader\\Exception\\InvalidPathException' => $vendorDir . '/laminas/laminas-loader/src/Exception/InvalidPathException.php', - 'Laminas\\Loader\\Exception\\MissingResourceNamespaceException' => $vendorDir . '/laminas/laminas-loader/src/Exception/MissingResourceNamespaceException.php', - 'Laminas\\Loader\\Exception\\PluginLoaderException' => $vendorDir . '/laminas/laminas-loader/src/Exception/PluginLoaderException.php', - 'Laminas\\Loader\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-loader/src/Exception/RuntimeException.php', - 'Laminas\\Loader\\Exception\\SecurityException' => $vendorDir . '/laminas/laminas-loader/src/Exception/SecurityException.php', - 'Laminas\\Loader\\ModuleAutoloader' => $vendorDir . '/laminas/laminas-loader/src/ModuleAutoloader.php', - 'Laminas\\Loader\\PluginClassLoader' => $vendorDir . '/laminas/laminas-loader/src/PluginClassLoader.php', - 'Laminas\\Loader\\PluginClassLocator' => $vendorDir . '/laminas/laminas-loader/src/PluginClassLocator.php', - 'Laminas\\Loader\\ShortNameLocator' => $vendorDir . '/laminas/laminas-loader/src/ShortNameLocator.php', - 'Laminas\\Loader\\SplAutoloader' => $vendorDir . '/laminas/laminas-loader/src/SplAutoloader.php', - 'Laminas\\Loader\\StandardAutoloader' => $vendorDir . '/laminas/laminas-loader/src/StandardAutoloader.php', - 'Laminas\\Mail\\Address' => $vendorDir . '/laminas/laminas-mail/src/Address.php', - 'Laminas\\Mail\\AddressList' => $vendorDir . '/laminas/laminas-mail/src/AddressList.php', - 'Laminas\\Mail\\Address\\AddressInterface' => $vendorDir . '/laminas/laminas-mail/src/Address/AddressInterface.php', - 'Laminas\\Mail\\ConfigProvider' => $vendorDir . '/laminas/laminas-mail/src/ConfigProvider.php', - 'Laminas\\Mail\\Exception\\BadMethodCallException' => $vendorDir . '/laminas/laminas-mail/src/Exception/BadMethodCallException.php', - 'Laminas\\Mail\\Exception\\DomainException' => $vendorDir . '/laminas/laminas-mail/src/Exception/DomainException.php', - 'Laminas\\Mail\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-mail/src/Exception/ExceptionInterface.php', - 'Laminas\\Mail\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-mail/src/Exception/InvalidArgumentException.php', - 'Laminas\\Mail\\Exception\\OutOfBoundsException' => $vendorDir . '/laminas/laminas-mail/src/Exception/OutOfBoundsException.php', - 'Laminas\\Mail\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-mail/src/Exception/RuntimeException.php', - 'Laminas\\Mail\\Header\\AbstractAddressList' => $vendorDir . '/laminas/laminas-mail/src/Header/AbstractAddressList.php', - 'Laminas\\Mail\\Header\\Bcc' => $vendorDir . '/laminas/laminas-mail/src/Header/Bcc.php', - 'Laminas\\Mail\\Header\\Cc' => $vendorDir . '/laminas/laminas-mail/src/Header/Cc.php', - 'Laminas\\Mail\\Header\\ContentDisposition' => $vendorDir . '/laminas/laminas-mail/src/Header/ContentDisposition.php', - 'Laminas\\Mail\\Header\\ContentTransferEncoding' => $vendorDir . '/laminas/laminas-mail/src/Header/ContentTransferEncoding.php', - 'Laminas\\Mail\\Header\\ContentType' => $vendorDir . '/laminas/laminas-mail/src/Header/ContentType.php', - 'Laminas\\Mail\\Header\\Date' => $vendorDir . '/laminas/laminas-mail/src/Header/Date.php', - 'Laminas\\Mail\\Header\\Exception\\BadMethodCallException' => $vendorDir . '/laminas/laminas-mail/src/Header/Exception/BadMethodCallException.php', - 'Laminas\\Mail\\Header\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-mail/src/Header/Exception/ExceptionInterface.php', - 'Laminas\\Mail\\Header\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-mail/src/Header/Exception/InvalidArgumentException.php', - 'Laminas\\Mail\\Header\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-mail/src/Header/Exception/RuntimeException.php', - 'Laminas\\Mail\\Header\\From' => $vendorDir . '/laminas/laminas-mail/src/Header/From.php', - 'Laminas\\Mail\\Header\\GenericHeader' => $vendorDir . '/laminas/laminas-mail/src/Header/GenericHeader.php', - 'Laminas\\Mail\\Header\\GenericMultiHeader' => $vendorDir . '/laminas/laminas-mail/src/Header/GenericMultiHeader.php', - 'Laminas\\Mail\\Header\\HeaderInterface' => $vendorDir . '/laminas/laminas-mail/src/Header/HeaderInterface.php', - 'Laminas\\Mail\\Header\\HeaderLoader' => $vendorDir . '/laminas/laminas-mail/src/Header/HeaderLoader.php', - 'Laminas\\Mail\\Header\\HeaderLocator' => $vendorDir . '/laminas/laminas-mail/src/Header/HeaderLocator.php', - 'Laminas\\Mail\\Header\\HeaderLocatorInterface' => $vendorDir . '/laminas/laminas-mail/src/Header/HeaderLocatorInterface.php', - 'Laminas\\Mail\\Header\\HeaderName' => $vendorDir . '/laminas/laminas-mail/src/Header/HeaderName.php', - 'Laminas\\Mail\\Header\\HeaderValue' => $vendorDir . '/laminas/laminas-mail/src/Header/HeaderValue.php', - 'Laminas\\Mail\\Header\\HeaderWrap' => $vendorDir . '/laminas/laminas-mail/src/Header/HeaderWrap.php', - 'Laminas\\Mail\\Header\\IdentificationField' => $vendorDir . '/laminas/laminas-mail/src/Header/IdentificationField.php', - 'Laminas\\Mail\\Header\\InReplyTo' => $vendorDir . '/laminas/laminas-mail/src/Header/InReplyTo.php', - 'Laminas\\Mail\\Header\\ListParser' => $vendorDir . '/laminas/laminas-mail/src/Header/ListParser.php', - 'Laminas\\Mail\\Header\\MessageId' => $vendorDir . '/laminas/laminas-mail/src/Header/MessageId.php', - 'Laminas\\Mail\\Header\\MimeVersion' => $vendorDir . '/laminas/laminas-mail/src/Header/MimeVersion.php', - 'Laminas\\Mail\\Header\\MultipleHeadersInterface' => $vendorDir . '/laminas/laminas-mail/src/Header/MultipleHeadersInterface.php', - 'Laminas\\Mail\\Header\\Received' => $vendorDir . '/laminas/laminas-mail/src/Header/Received.php', - 'Laminas\\Mail\\Header\\References' => $vendorDir . '/laminas/laminas-mail/src/Header/References.php', - 'Laminas\\Mail\\Header\\ReplyTo' => $vendorDir . '/laminas/laminas-mail/src/Header/ReplyTo.php', - 'Laminas\\Mail\\Header\\Sender' => $vendorDir . '/laminas/laminas-mail/src/Header/Sender.php', - 'Laminas\\Mail\\Header\\StructuredInterface' => $vendorDir . '/laminas/laminas-mail/src/Header/StructuredInterface.php', - 'Laminas\\Mail\\Header\\Subject' => $vendorDir . '/laminas/laminas-mail/src/Header/Subject.php', - 'Laminas\\Mail\\Header\\To' => $vendorDir . '/laminas/laminas-mail/src/Header/To.php', - 'Laminas\\Mail\\Header\\UnstructuredInterface' => $vendorDir . '/laminas/laminas-mail/src/Header/UnstructuredInterface.php', - 'Laminas\\Mail\\Headers' => $vendorDir . '/laminas/laminas-mail/src/Headers.php', - 'Laminas\\Mail\\Message' => $vendorDir . '/laminas/laminas-mail/src/Message.php', - 'Laminas\\Mail\\MessageFactory' => $vendorDir . '/laminas/laminas-mail/src/MessageFactory.php', - 'Laminas\\Mail\\Module' => $vendorDir . '/laminas/laminas-mail/src/Module.php', - 'Laminas\\Mail\\Protocol\\AbstractProtocol' => $vendorDir . '/laminas/laminas-mail/src/Protocol/AbstractProtocol.php', - 'Laminas\\Mail\\Protocol\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-mail/src/Protocol/Exception/ExceptionInterface.php', - 'Laminas\\Mail\\Protocol\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-mail/src/Protocol/Exception/InvalidArgumentException.php', - 'Laminas\\Mail\\Protocol\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-mail/src/Protocol/Exception/RuntimeException.php', - 'Laminas\\Mail\\Protocol\\Imap' => $vendorDir . '/laminas/laminas-mail/src/Protocol/Imap.php', - 'Laminas\\Mail\\Protocol\\Pop3' => $vendorDir . '/laminas/laminas-mail/src/Protocol/Pop3.php', - 'Laminas\\Mail\\Protocol\\ProtocolTrait' => $vendorDir . '/laminas/laminas-mail/src/Protocol/ProtocolTrait.php', - 'Laminas\\Mail\\Protocol\\Smtp' => $vendorDir . '/laminas/laminas-mail/src/Protocol/Smtp.php', - 'Laminas\\Mail\\Protocol\\SmtpPluginManager' => $vendorDir . '/laminas/laminas-mail/src/Protocol/SmtpPluginManager.php', - 'Laminas\\Mail\\Protocol\\SmtpPluginManagerFactory' => $vendorDir . '/laminas/laminas-mail/src/Protocol/SmtpPluginManagerFactory.php', - 'Laminas\\Mail\\Protocol\\Smtp\\Auth\\Crammd5' => $vendorDir . '/laminas/laminas-mail/src/Protocol/Smtp/Auth/Crammd5.php', - 'Laminas\\Mail\\Protocol\\Smtp\\Auth\\Login' => $vendorDir . '/laminas/laminas-mail/src/Protocol/Smtp/Auth/Login.php', - 'Laminas\\Mail\\Protocol\\Smtp\\Auth\\Oauth' => $baseDir . '/sources/Core/Authentication/Client/Smtp/SmtpOAuthLogin.php', - 'Laminas\\Mail\\Protocol\\Smtp\\Auth\\Plain' => $vendorDir . '/laminas/laminas-mail/src/Protocol/Smtp/Auth/Plain.php', - 'Laminas\\Mail\\Storage' => $vendorDir . '/laminas/laminas-mail/src/Storage.php', - 'Laminas\\Mail\\Storage\\AbstractStorage' => $vendorDir . '/laminas/laminas-mail/src/Storage/AbstractStorage.php', - 'Laminas\\Mail\\Storage\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-mail/src/Storage/Exception/ExceptionInterface.php', - 'Laminas\\Mail\\Storage\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-mail/src/Storage/Exception/InvalidArgumentException.php', - 'Laminas\\Mail\\Storage\\Exception\\OutOfBoundsException' => $vendorDir . '/laminas/laminas-mail/src/Storage/Exception/OutOfBoundsException.php', - 'Laminas\\Mail\\Storage\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-mail/src/Storage/Exception/RuntimeException.php', - 'Laminas\\Mail\\Storage\\Folder' => $vendorDir . '/laminas/laminas-mail/src/Storage/Folder.php', - 'Laminas\\Mail\\Storage\\Folder\\FolderInterface' => $vendorDir . '/laminas/laminas-mail/src/Storage/Folder/FolderInterface.php', - 'Laminas\\Mail\\Storage\\Folder\\Maildir' => $vendorDir . '/laminas/laminas-mail/src/Storage/Folder/Maildir.php', - 'Laminas\\Mail\\Storage\\Folder\\Mbox' => $vendorDir . '/laminas/laminas-mail/src/Storage/Folder/Mbox.php', - 'Laminas\\Mail\\Storage\\Imap' => $vendorDir . '/laminas/laminas-mail/src/Storage/Imap.php', - 'Laminas\\Mail\\Storage\\Maildir' => $vendorDir . '/laminas/laminas-mail/src/Storage/Maildir.php', - 'Laminas\\Mail\\Storage\\Mbox' => $vendorDir . '/laminas/laminas-mail/src/Storage/Mbox.php', - 'Laminas\\Mail\\Storage\\Message' => $vendorDir . '/laminas/laminas-mail/src/Storage/Message.php', - 'Laminas\\Mail\\Storage\\Message\\File' => $vendorDir . '/laminas/laminas-mail/src/Storage/Message/File.php', - 'Laminas\\Mail\\Storage\\Message\\MessageInterface' => $vendorDir . '/laminas/laminas-mail/src/Storage/Message/MessageInterface.php', - 'Laminas\\Mail\\Storage\\ParamsNormalizer' => $vendorDir . '/laminas/laminas-mail/src/Storage/ParamsNormalizer.php', - 'Laminas\\Mail\\Storage\\Part' => $vendorDir . '/laminas/laminas-mail/src/Storage/Part.php', - 'Laminas\\Mail\\Storage\\Part\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-mail/src/Storage/Part/Exception/ExceptionInterface.php', - 'Laminas\\Mail\\Storage\\Part\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-mail/src/Storage/Part/Exception/InvalidArgumentException.php', - 'Laminas\\Mail\\Storage\\Part\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-mail/src/Storage/Part/Exception/RuntimeException.php', - 'Laminas\\Mail\\Storage\\Part\\File' => $vendorDir . '/laminas/laminas-mail/src/Storage/Part/File.php', - 'Laminas\\Mail\\Storage\\Part\\PartInterface' => $vendorDir . '/laminas/laminas-mail/src/Storage/Part/PartInterface.php', - 'Laminas\\Mail\\Storage\\Pop3' => $vendorDir . '/laminas/laminas-mail/src/Storage/Pop3.php', - 'Laminas\\Mail\\Storage\\Writable\\Maildir' => $vendorDir . '/laminas/laminas-mail/src/Storage/Writable/Maildir.php', - 'Laminas\\Mail\\Storage\\Writable\\WritableInterface' => $vendorDir . '/laminas/laminas-mail/src/Storage/Writable/WritableInterface.php', - 'Laminas\\Mail\\Transport\\Envelope' => $vendorDir . '/laminas/laminas-mail/src/Transport/Envelope.php', - 'Laminas\\Mail\\Transport\\Exception\\DomainException' => $vendorDir . '/laminas/laminas-mail/src/Transport/Exception/DomainException.php', - 'Laminas\\Mail\\Transport\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-mail/src/Transport/Exception/ExceptionInterface.php', - 'Laminas\\Mail\\Transport\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-mail/src/Transport/Exception/InvalidArgumentException.php', - 'Laminas\\Mail\\Transport\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-mail/src/Transport/Exception/RuntimeException.php', - 'Laminas\\Mail\\Transport\\Factory' => $vendorDir . '/laminas/laminas-mail/src/Transport/Factory.php', - 'Laminas\\Mail\\Transport\\File' => $vendorDir . '/laminas/laminas-mail/src/Transport/File.php', - 'Laminas\\Mail\\Transport\\FileOptions' => $vendorDir . '/laminas/laminas-mail/src/Transport/FileOptions.php', - 'Laminas\\Mail\\Transport\\InMemory' => $vendorDir . '/laminas/laminas-mail/src/Transport/InMemory.php', - 'Laminas\\Mail\\Transport\\Sendmail' => $vendorDir . '/laminas/laminas-mail/src/Transport/Sendmail.php', - 'Laminas\\Mail\\Transport\\Smtp' => $vendorDir . '/laminas/laminas-mail/src/Transport/Smtp.php', - 'Laminas\\Mail\\Transport\\SmtpOptions' => $vendorDir . '/laminas/laminas-mail/src/Transport/SmtpOptions.php', - 'Laminas\\Mail\\Transport\\TransportInterface' => $vendorDir . '/laminas/laminas-mail/src/Transport/TransportInterface.php', - 'Laminas\\Mime\\Decode' => $vendorDir . '/laminas/laminas-mime/src/Decode.php', - 'Laminas\\Mime\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-mime/src/Exception/ExceptionInterface.php', - 'Laminas\\Mime\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-mime/src/Exception/InvalidArgumentException.php', - 'Laminas\\Mime\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-mime/src/Exception/RuntimeException.php', - 'Laminas\\Mime\\Message' => $vendorDir . '/laminas/laminas-mime/src/Message.php', - 'Laminas\\Mime\\Mime' => $vendorDir . '/laminas/laminas-mime/src/Mime.php', - 'Laminas\\Mime\\Part' => $vendorDir . '/laminas/laminas-mime/src/Part.php', - 'Laminas\\ServiceManager\\AbstractFactoryInterface' => $vendorDir . '/laminas/laminas-servicemanager/src/AbstractFactoryInterface.php', - 'Laminas\\ServiceManager\\AbstractFactory\\ConfigAbstractFactory' => $vendorDir . '/laminas/laminas-servicemanager/src/AbstractFactory/ConfigAbstractFactory.php', - 'Laminas\\ServiceManager\\AbstractFactory\\ReflectionBasedAbstractFactory' => $vendorDir . '/laminas/laminas-servicemanager/src/AbstractFactory/ReflectionBasedAbstractFactory.php', - 'Laminas\\ServiceManager\\AbstractPluginManager' => $vendorDir . '/laminas/laminas-servicemanager/src/AbstractPluginManager.php', - 'Laminas\\ServiceManager\\Config' => $vendorDir . '/laminas/laminas-servicemanager/src/Config.php', - 'Laminas\\ServiceManager\\ConfigInterface' => $vendorDir . '/laminas/laminas-servicemanager/src/ConfigInterface.php', - 'Laminas\\ServiceManager\\DelegatorFactoryInterface' => $vendorDir . '/laminas/laminas-servicemanager/src/DelegatorFactoryInterface.php', - 'Laminas\\ServiceManager\\Exception\\ContainerModificationsNotAllowedException' => $vendorDir . '/laminas/laminas-servicemanager/src/Exception/ContainerModificationsNotAllowedException.php', - 'Laminas\\ServiceManager\\Exception\\CyclicAliasException' => $vendorDir . '/laminas/laminas-servicemanager/src/Exception/CyclicAliasException.php', - 'Laminas\\ServiceManager\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-servicemanager/src/Exception/ExceptionInterface.php', - 'Laminas\\ServiceManager\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-servicemanager/src/Exception/InvalidArgumentException.php', - 'Laminas\\ServiceManager\\Exception\\InvalidServiceException' => $vendorDir . '/laminas/laminas-servicemanager/src/Exception/InvalidServiceException.php', - 'Laminas\\ServiceManager\\Exception\\ServiceNotCreatedException' => $vendorDir . '/laminas/laminas-servicemanager/src/Exception/ServiceNotCreatedException.php', - 'Laminas\\ServiceManager\\Exception\\ServiceNotFoundException' => $vendorDir . '/laminas/laminas-servicemanager/src/Exception/ServiceNotFoundException.php', - 'Laminas\\ServiceManager\\FactoryInterface' => $vendorDir . '/laminas/laminas-servicemanager/src/FactoryInterface.php', - 'Laminas\\ServiceManager\\Factory\\AbstractFactoryInterface' => $vendorDir . '/laminas/laminas-servicemanager/src/Factory/AbstractFactoryInterface.php', - 'Laminas\\ServiceManager\\Factory\\DelegatorFactoryInterface' => $vendorDir . '/laminas/laminas-servicemanager/src/Factory/DelegatorFactoryInterface.php', - 'Laminas\\ServiceManager\\Factory\\FactoryInterface' => $vendorDir . '/laminas/laminas-servicemanager/src/Factory/FactoryInterface.php', - 'Laminas\\ServiceManager\\Factory\\InvokableFactory' => $vendorDir . '/laminas/laminas-servicemanager/src/Factory/InvokableFactory.php', - 'Laminas\\ServiceManager\\InitializerInterface' => $vendorDir . '/laminas/laminas-servicemanager/src/InitializerInterface.php', - 'Laminas\\ServiceManager\\Initializer\\InitializerInterface' => $vendorDir . '/laminas/laminas-servicemanager/src/Initializer/InitializerInterface.php', - 'Laminas\\ServiceManager\\PluginManagerInterface' => $vendorDir . '/laminas/laminas-servicemanager/src/PluginManagerInterface.php', - 'Laminas\\ServiceManager\\Proxy\\LazyServiceFactory' => $vendorDir . '/laminas/laminas-servicemanager/src/Proxy/LazyServiceFactory.php', - 'Laminas\\ServiceManager\\ServiceLocatorInterface' => $vendorDir . '/laminas/laminas-servicemanager/src/ServiceLocatorInterface.php', - 'Laminas\\ServiceManager\\ServiceManager' => $vendorDir . '/laminas/laminas-servicemanager/src/ServiceManager.php', - 'Laminas\\ServiceManager\\Tool\\ConfigDumper' => $vendorDir . '/laminas/laminas-servicemanager/src/Tool/ConfigDumper.php', - 'Laminas\\ServiceManager\\Tool\\ConfigDumperCommand' => $vendorDir . '/laminas/laminas-servicemanager/src/Tool/ConfigDumperCommand.php', - 'Laminas\\ServiceManager\\Tool\\FactoryCreator' => $vendorDir . '/laminas/laminas-servicemanager/src/Tool/FactoryCreator.php', - 'Laminas\\ServiceManager\\Tool\\FactoryCreatorCommand' => $vendorDir . '/laminas/laminas-servicemanager/src/Tool/FactoryCreatorCommand.php', - 'Laminas\\Stdlib\\AbstractOptions' => $vendorDir . '/laminas/laminas-stdlib/src/AbstractOptions.php', - 'Laminas\\Stdlib\\ArrayObject' => $vendorDir . '/laminas/laminas-stdlib/src/ArrayObject.php', - 'Laminas\\Stdlib\\ArraySerializableInterface' => $vendorDir . '/laminas/laminas-stdlib/src/ArraySerializableInterface.php', - 'Laminas\\Stdlib\\ArrayStack' => $vendorDir . '/laminas/laminas-stdlib/src/ArrayStack.php', - 'Laminas\\Stdlib\\ArrayUtils' => $vendorDir . '/laminas/laminas-stdlib/src/ArrayUtils.php', - 'Laminas\\Stdlib\\ArrayUtils\\MergeRemoveKey' => $vendorDir . '/laminas/laminas-stdlib/src/ArrayUtils/MergeRemoveKey.php', - 'Laminas\\Stdlib\\ArrayUtils\\MergeReplaceKey' => $vendorDir . '/laminas/laminas-stdlib/src/ArrayUtils/MergeReplaceKey.php', - 'Laminas\\Stdlib\\ArrayUtils\\MergeReplaceKeyInterface' => $vendorDir . '/laminas/laminas-stdlib/src/ArrayUtils/MergeReplaceKeyInterface.php', - 'Laminas\\Stdlib\\ConsoleHelper' => $vendorDir . '/laminas/laminas-stdlib/src/ConsoleHelper.php', - 'Laminas\\Stdlib\\DispatchableInterface' => $vendorDir . '/laminas/laminas-stdlib/src/DispatchableInterface.php', - 'Laminas\\Stdlib\\ErrorHandler' => $vendorDir . '/laminas/laminas-stdlib/src/ErrorHandler.php', - 'Laminas\\Stdlib\\Exception\\BadMethodCallException' => $vendorDir . '/laminas/laminas-stdlib/src/Exception/BadMethodCallException.php', - 'Laminas\\Stdlib\\Exception\\DomainException' => $vendorDir . '/laminas/laminas-stdlib/src/Exception/DomainException.php', - 'Laminas\\Stdlib\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-stdlib/src/Exception/ExceptionInterface.php', - 'Laminas\\Stdlib\\Exception\\ExtensionNotLoadedException' => $vendorDir . '/laminas/laminas-stdlib/src/Exception/ExtensionNotLoadedException.php', - 'Laminas\\Stdlib\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-stdlib/src/Exception/InvalidArgumentException.php', - 'Laminas\\Stdlib\\Exception\\LogicException' => $vendorDir . '/laminas/laminas-stdlib/src/Exception/LogicException.php', - 'Laminas\\Stdlib\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-stdlib/src/Exception/RuntimeException.php', - 'Laminas\\Stdlib\\FastPriorityQueue' => $vendorDir . '/laminas/laminas-stdlib/src/FastPriorityQueue.php', - 'Laminas\\Stdlib\\Glob' => $vendorDir . '/laminas/laminas-stdlib/src/Glob.php', - 'Laminas\\Stdlib\\Guard\\AllGuardsTrait' => $vendorDir . '/laminas/laminas-stdlib/src/Guard/AllGuardsTrait.php', - 'Laminas\\Stdlib\\Guard\\ArrayOrTraversableGuardTrait' => $vendorDir . '/laminas/laminas-stdlib/src/Guard/ArrayOrTraversableGuardTrait.php', - 'Laminas\\Stdlib\\Guard\\EmptyGuardTrait' => $vendorDir . '/laminas/laminas-stdlib/src/Guard/EmptyGuardTrait.php', - 'Laminas\\Stdlib\\Guard\\NullGuardTrait' => $vendorDir . '/laminas/laminas-stdlib/src/Guard/NullGuardTrait.php', - 'Laminas\\Stdlib\\InitializableInterface' => $vendorDir . '/laminas/laminas-stdlib/src/InitializableInterface.php', - 'Laminas\\Stdlib\\JsonSerializable' => $vendorDir . '/laminas/laminas-stdlib/src/JsonSerializable.php', - 'Laminas\\Stdlib\\Message' => $vendorDir . '/laminas/laminas-stdlib/src/Message.php', - 'Laminas\\Stdlib\\MessageInterface' => $vendorDir . '/laminas/laminas-stdlib/src/MessageInterface.php', - 'Laminas\\Stdlib\\ParameterObjectInterface' => $vendorDir . '/laminas/laminas-stdlib/src/ParameterObjectInterface.php', - 'Laminas\\Stdlib\\Parameters' => $vendorDir . '/laminas/laminas-stdlib/src/Parameters.php', - 'Laminas\\Stdlib\\ParametersInterface' => $vendorDir . '/laminas/laminas-stdlib/src/ParametersInterface.php', - 'Laminas\\Stdlib\\PriorityList' => $vendorDir . '/laminas/laminas-stdlib/src/PriorityList.php', - 'Laminas\\Stdlib\\PriorityQueue' => $vendorDir . '/laminas/laminas-stdlib/src/PriorityQueue.php', - 'Laminas\\Stdlib\\Request' => $vendorDir . '/laminas/laminas-stdlib/src/Request.php', - 'Laminas\\Stdlib\\RequestInterface' => $vendorDir . '/laminas/laminas-stdlib/src/RequestInterface.php', - 'Laminas\\Stdlib\\Response' => $vendorDir . '/laminas/laminas-stdlib/src/Response.php', - 'Laminas\\Stdlib\\ResponseInterface' => $vendorDir . '/laminas/laminas-stdlib/src/ResponseInterface.php', - 'Laminas\\Stdlib\\SplPriorityQueue' => $vendorDir . '/laminas/laminas-stdlib/src/SplPriorityQueue.php', - 'Laminas\\Stdlib\\SplQueue' => $vendorDir . '/laminas/laminas-stdlib/src/SplQueue.php', - 'Laminas\\Stdlib\\SplStack' => $vendorDir . '/laminas/laminas-stdlib/src/SplStack.php', - 'Laminas\\Stdlib\\StringUtils' => $vendorDir . '/laminas/laminas-stdlib/src/StringUtils.php', - 'Laminas\\Stdlib\\StringWrapper\\AbstractStringWrapper' => $vendorDir . '/laminas/laminas-stdlib/src/StringWrapper/AbstractStringWrapper.php', - 'Laminas\\Stdlib\\StringWrapper\\Iconv' => $vendorDir . '/laminas/laminas-stdlib/src/StringWrapper/Iconv.php', - 'Laminas\\Stdlib\\StringWrapper\\Intl' => $vendorDir . '/laminas/laminas-stdlib/src/StringWrapper/Intl.php', - 'Laminas\\Stdlib\\StringWrapper\\MbString' => $vendorDir . '/laminas/laminas-stdlib/src/StringWrapper/MbString.php', - 'Laminas\\Stdlib\\StringWrapper\\Native' => $vendorDir . '/laminas/laminas-stdlib/src/StringWrapper/Native.php', - 'Laminas\\Stdlib\\StringWrapper\\StringWrapperInterface' => $vendorDir . '/laminas/laminas-stdlib/src/StringWrapper/StringWrapperInterface.php', - 'Laminas\\Validator\\AbstractValidator' => $vendorDir . '/laminas/laminas-validator/src/AbstractValidator.php', - 'Laminas\\Validator\\Barcode' => $vendorDir . '/laminas/laminas-validator/src/Barcode.php', - 'Laminas\\Validator\\Barcode\\AbstractAdapter' => $vendorDir . '/laminas/laminas-validator/src/Barcode/AbstractAdapter.php', - 'Laminas\\Validator\\Barcode\\AdapterInterface' => $vendorDir . '/laminas/laminas-validator/src/Barcode/AdapterInterface.php', - 'Laminas\\Validator\\Barcode\\Codabar' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Codabar.php', - 'Laminas\\Validator\\Barcode\\Code128' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Code128.php', - 'Laminas\\Validator\\Barcode\\Code25' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Code25.php', - 'Laminas\\Validator\\Barcode\\Code25interleaved' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Code25interleaved.php', - 'Laminas\\Validator\\Barcode\\Code39' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Code39.php', - 'Laminas\\Validator\\Barcode\\Code39ext' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Code39ext.php', - 'Laminas\\Validator\\Barcode\\Code93' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Code93.php', - 'Laminas\\Validator\\Barcode\\Code93ext' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Code93ext.php', - 'Laminas\\Validator\\Barcode\\Ean12' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Ean12.php', - 'Laminas\\Validator\\Barcode\\Ean13' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Ean13.php', - 'Laminas\\Validator\\Barcode\\Ean14' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Ean14.php', - 'Laminas\\Validator\\Barcode\\Ean18' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Ean18.php', - 'Laminas\\Validator\\Barcode\\Ean2' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Ean2.php', - 'Laminas\\Validator\\Barcode\\Ean5' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Ean5.php', - 'Laminas\\Validator\\Barcode\\Ean8' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Ean8.php', - 'Laminas\\Validator\\Barcode\\Gtin12' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Gtin12.php', - 'Laminas\\Validator\\Barcode\\Gtin13' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Gtin13.php', - 'Laminas\\Validator\\Barcode\\Gtin14' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Gtin14.php', - 'Laminas\\Validator\\Barcode\\Identcode' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Identcode.php', - 'Laminas\\Validator\\Barcode\\Intelligentmail' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Intelligentmail.php', - 'Laminas\\Validator\\Barcode\\Issn' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Issn.php', - 'Laminas\\Validator\\Barcode\\Itf14' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Itf14.php', - 'Laminas\\Validator\\Barcode\\Leitcode' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Leitcode.php', - 'Laminas\\Validator\\Barcode\\Planet' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Planet.php', - 'Laminas\\Validator\\Barcode\\Postnet' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Postnet.php', - 'Laminas\\Validator\\Barcode\\Royalmail' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Royalmail.php', - 'Laminas\\Validator\\Barcode\\Sscc' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Sscc.php', - 'Laminas\\Validator\\Barcode\\Upca' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Upca.php', - 'Laminas\\Validator\\Barcode\\Upce' => $vendorDir . '/laminas/laminas-validator/src/Barcode/Upce.php', - 'Laminas\\Validator\\Between' => $vendorDir . '/laminas/laminas-validator/src/Between.php', - 'Laminas\\Validator\\Bitwise' => $vendorDir . '/laminas/laminas-validator/src/Bitwise.php', - 'Laminas\\Validator\\BusinessIdentifierCode' => $vendorDir . '/laminas/laminas-validator/src/BusinessIdentifierCode.php', - 'Laminas\\Validator\\Callback' => $vendorDir . '/laminas/laminas-validator/src/Callback.php', - 'Laminas\\Validator\\ConfigProvider' => $vendorDir . '/laminas/laminas-validator/src/ConfigProvider.php', - 'Laminas\\Validator\\CreditCard' => $vendorDir . '/laminas/laminas-validator/src/CreditCard.php', - 'Laminas\\Validator\\Csrf' => $vendorDir . '/laminas/laminas-validator/src/Csrf.php', - 'Laminas\\Validator\\Date' => $vendorDir . '/laminas/laminas-validator/src/Date.php', - 'Laminas\\Validator\\DateStep' => $vendorDir . '/laminas/laminas-validator/src/DateStep.php', - 'Laminas\\Validator\\Db\\AbstractDb' => $vendorDir . '/laminas/laminas-validator/src/Db/AbstractDb.php', - 'Laminas\\Validator\\Db\\NoRecordExists' => $vendorDir . '/laminas/laminas-validator/src/Db/NoRecordExists.php', - 'Laminas\\Validator\\Db\\RecordExists' => $vendorDir . '/laminas/laminas-validator/src/Db/RecordExists.php', - 'Laminas\\Validator\\Digits' => $vendorDir . '/laminas/laminas-validator/src/Digits.php', - 'Laminas\\Validator\\EmailAddress' => $vendorDir . '/laminas/laminas-validator/src/EmailAddress.php', - 'Laminas\\Validator\\Exception\\BadMethodCallException' => $vendorDir . '/laminas/laminas-validator/src/Exception/BadMethodCallException.php', - 'Laminas\\Validator\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-validator/src/Exception/ExceptionInterface.php', - 'Laminas\\Validator\\Exception\\ExtensionNotLoadedException' => $vendorDir . '/laminas/laminas-validator/src/Exception/ExtensionNotLoadedException.php', - 'Laminas\\Validator\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-validator/src/Exception/InvalidArgumentException.php', - 'Laminas\\Validator\\Exception\\InvalidMagicMimeFileException' => $vendorDir . '/laminas/laminas-validator/src/Exception/InvalidMagicMimeFileException.php', - 'Laminas\\Validator\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-validator/src/Exception/RuntimeException.php', - 'Laminas\\Validator\\Explode' => $vendorDir . '/laminas/laminas-validator/src/Explode.php', - 'Laminas\\Validator\\File\\Count' => $vendorDir . '/laminas/laminas-validator/src/File/Count.php', - 'Laminas\\Validator\\File\\Crc32' => $vendorDir . '/laminas/laminas-validator/src/File/Crc32.php', - 'Laminas\\Validator\\File\\ExcludeExtension' => $vendorDir . '/laminas/laminas-validator/src/File/ExcludeExtension.php', - 'Laminas\\Validator\\File\\ExcludeMimeType' => $vendorDir . '/laminas/laminas-validator/src/File/ExcludeMimeType.php', - 'Laminas\\Validator\\File\\Exists' => $vendorDir . '/laminas/laminas-validator/src/File/Exists.php', - 'Laminas\\Validator\\File\\Extension' => $vendorDir . '/laminas/laminas-validator/src/File/Extension.php', - 'Laminas\\Validator\\File\\FileInformationTrait' => $vendorDir . '/laminas/laminas-validator/src/File/FileInformationTrait.php', - 'Laminas\\Validator\\File\\FilesSize' => $vendorDir . '/laminas/laminas-validator/src/File/FilesSize.php', - 'Laminas\\Validator\\File\\Hash' => $vendorDir . '/laminas/laminas-validator/src/File/Hash.php', - 'Laminas\\Validator\\File\\ImageSize' => $vendorDir . '/laminas/laminas-validator/src/File/ImageSize.php', - 'Laminas\\Validator\\File\\IsCompressed' => $vendorDir . '/laminas/laminas-validator/src/File/IsCompressed.php', - 'Laminas\\Validator\\File\\IsImage' => $vendorDir . '/laminas/laminas-validator/src/File/IsImage.php', - 'Laminas\\Validator\\File\\Md5' => $vendorDir . '/laminas/laminas-validator/src/File/Md5.php', - 'Laminas\\Validator\\File\\MimeType' => $vendorDir . '/laminas/laminas-validator/src/File/MimeType.php', - 'Laminas\\Validator\\File\\NotExists' => $vendorDir . '/laminas/laminas-validator/src/File/NotExists.php', - 'Laminas\\Validator\\File\\Sha1' => $vendorDir . '/laminas/laminas-validator/src/File/Sha1.php', - 'Laminas\\Validator\\File\\Size' => $vendorDir . '/laminas/laminas-validator/src/File/Size.php', - 'Laminas\\Validator\\File\\Upload' => $vendorDir . '/laminas/laminas-validator/src/File/Upload.php', - 'Laminas\\Validator\\File\\UploadFile' => $vendorDir . '/laminas/laminas-validator/src/File/UploadFile.php', - 'Laminas\\Validator\\File\\WordCount' => $vendorDir . '/laminas/laminas-validator/src/File/WordCount.php', - 'Laminas\\Validator\\GpsPoint' => $vendorDir . '/laminas/laminas-validator/src/GpsPoint.php', - 'Laminas\\Validator\\GreaterThan' => $vendorDir . '/laminas/laminas-validator/src/GreaterThan.php', - 'Laminas\\Validator\\Hex' => $vendorDir . '/laminas/laminas-validator/src/Hex.php', - 'Laminas\\Validator\\Hostname' => $vendorDir . '/laminas/laminas-validator/src/Hostname.php', - 'Laminas\\Validator\\Iban' => $vendorDir . '/laminas/laminas-validator/src/Iban.php', - 'Laminas\\Validator\\Identical' => $vendorDir . '/laminas/laminas-validator/src/Identical.php', - 'Laminas\\Validator\\InArray' => $vendorDir . '/laminas/laminas-validator/src/InArray.php', - 'Laminas\\Validator\\Ip' => $vendorDir . '/laminas/laminas-validator/src/Ip.php', - 'Laminas\\Validator\\IsCountable' => $vendorDir . '/laminas/laminas-validator/src/IsCountable.php', - 'Laminas\\Validator\\IsInstanceOf' => $vendorDir . '/laminas/laminas-validator/src/IsInstanceOf.php', - 'Laminas\\Validator\\Isbn' => $vendorDir . '/laminas/laminas-validator/src/Isbn.php', - 'Laminas\\Validator\\Isbn\\Isbn10' => $vendorDir . '/laminas/laminas-validator/src/Isbn/Isbn10.php', - 'Laminas\\Validator\\Isbn\\Isbn13' => $vendorDir . '/laminas/laminas-validator/src/Isbn/Isbn13.php', - 'Laminas\\Validator\\LessThan' => $vendorDir . '/laminas/laminas-validator/src/LessThan.php', - 'Laminas\\Validator\\Module' => $vendorDir . '/laminas/laminas-validator/src/Module.php', - 'Laminas\\Validator\\NotEmpty' => $vendorDir . '/laminas/laminas-validator/src/NotEmpty.php', - 'Laminas\\Validator\\Regex' => $vendorDir . '/laminas/laminas-validator/src/Regex.php', - 'Laminas\\Validator\\Sitemap\\Changefreq' => $vendorDir . '/laminas/laminas-validator/src/Sitemap/Changefreq.php', - 'Laminas\\Validator\\Sitemap\\Lastmod' => $vendorDir . '/laminas/laminas-validator/src/Sitemap/Lastmod.php', - 'Laminas\\Validator\\Sitemap\\Loc' => $vendorDir . '/laminas/laminas-validator/src/Sitemap/Loc.php', - 'Laminas\\Validator\\Sitemap\\Priority' => $vendorDir . '/laminas/laminas-validator/src/Sitemap/Priority.php', - 'Laminas\\Validator\\StaticValidator' => $vendorDir . '/laminas/laminas-validator/src/StaticValidator.php', - 'Laminas\\Validator\\Step' => $vendorDir . '/laminas/laminas-validator/src/Step.php', - 'Laminas\\Validator\\StringLength' => $vendorDir . '/laminas/laminas-validator/src/StringLength.php', - 'Laminas\\Validator\\Timezone' => $vendorDir . '/laminas/laminas-validator/src/Timezone.php', - 'Laminas\\Validator\\Translator\\TranslatorAwareInterface' => $vendorDir . '/laminas/laminas-validator/src/Translator/TranslatorAwareInterface.php', - 'Laminas\\Validator\\Translator\\TranslatorInterface' => $vendorDir . '/laminas/laminas-validator/src/Translator/TranslatorInterface.php', - 'Laminas\\Validator\\UndisclosedPassword' => $vendorDir . '/laminas/laminas-validator/src/UndisclosedPassword.php', - 'Laminas\\Validator\\Uri' => $vendorDir . '/laminas/laminas-validator/src/Uri.php', - 'Laminas\\Validator\\Uuid' => $vendorDir . '/laminas/laminas-validator/src/Uuid.php', - 'Laminas\\Validator\\ValidatorChain' => $vendorDir . '/laminas/laminas-validator/src/ValidatorChain.php', - 'Laminas\\Validator\\ValidatorInterface' => $vendorDir . '/laminas/laminas-validator/src/ValidatorInterface.php', - 'Laminas\\Validator\\ValidatorPluginManager' => $vendorDir . '/laminas/laminas-validator/src/ValidatorPluginManager.php', - 'Laminas\\Validator\\ValidatorPluginManagerAwareInterface' => $vendorDir . '/laminas/laminas-validator/src/ValidatorPluginManagerAwareInterface.php', - 'Laminas\\Validator\\ValidatorPluginManagerFactory' => $vendorDir . '/laminas/laminas-validator/src/ValidatorPluginManagerFactory.php', - 'Laminas\\Validator\\ValidatorProviderInterface' => $vendorDir . '/laminas/laminas-validator/src/ValidatorProviderInterface.php', - 'League\\OAuth2\\Client\\Exception\\HostedDomainException' => $vendorDir . '/league/oauth2-google/src/Exception/HostedDomainException.php', - 'League\\OAuth2\\Client\\Grant\\AbstractGrant' => $vendorDir . '/league/oauth2-client/src/Grant/AbstractGrant.php', - 'League\\OAuth2\\Client\\Grant\\AuthorizationCode' => $vendorDir . '/league/oauth2-client/src/Grant/AuthorizationCode.php', - 'League\\OAuth2\\Client\\Grant\\ClientCredentials' => $vendorDir . '/league/oauth2-client/src/Grant/ClientCredentials.php', - 'League\\OAuth2\\Client\\Grant\\Exception\\InvalidGrantException' => $vendorDir . '/league/oauth2-client/src/Grant/Exception/InvalidGrantException.php', - 'League\\OAuth2\\Client\\Grant\\GrantFactory' => $vendorDir . '/league/oauth2-client/src/Grant/GrantFactory.php', - 'League\\OAuth2\\Client\\Grant\\Password' => $vendorDir . '/league/oauth2-client/src/Grant/Password.php', - 'League\\OAuth2\\Client\\Grant\\RefreshToken' => $vendorDir . '/league/oauth2-client/src/Grant/RefreshToken.php', - 'League\\OAuth2\\Client\\OptionProvider\\HttpBasicAuthOptionProvider' => $vendorDir . '/league/oauth2-client/src/OptionProvider/HttpBasicAuthOptionProvider.php', - 'League\\OAuth2\\Client\\OptionProvider\\OptionProviderInterface' => $vendorDir . '/league/oauth2-client/src/OptionProvider/OptionProviderInterface.php', - 'League\\OAuth2\\Client\\OptionProvider\\PostAuthOptionProvider' => $vendorDir . '/league/oauth2-client/src/OptionProvider/PostAuthOptionProvider.php', - 'League\\OAuth2\\Client\\Provider\\AbstractProvider' => $vendorDir . '/league/oauth2-client/src/Provider/AbstractProvider.php', - 'League\\OAuth2\\Client\\Provider\\Exception\\IdentityProviderException' => $vendorDir . '/league/oauth2-client/src/Provider/Exception/IdentityProviderException.php', - 'League\\OAuth2\\Client\\Provider\\GenericProvider' => $vendorDir . '/league/oauth2-client/src/Provider/GenericProvider.php', - 'League\\OAuth2\\Client\\Provider\\GenericResourceOwner' => $vendorDir . '/league/oauth2-client/src/Provider/GenericResourceOwner.php', - 'League\\OAuth2\\Client\\Provider\\Google' => $vendorDir . '/league/oauth2-google/src/Provider/Google.php', - 'League\\OAuth2\\Client\\Provider\\GoogleUser' => $vendorDir . '/league/oauth2-google/src/Provider/GoogleUser.php', - 'League\\OAuth2\\Client\\Provider\\ResourceOwnerInterface' => $vendorDir . '/league/oauth2-client/src/Provider/ResourceOwnerInterface.php', - 'League\\OAuth2\\Client\\Token\\AccessToken' => $vendorDir . '/league/oauth2-client/src/Token/AccessToken.php', - 'League\\OAuth2\\Client\\Token\\AccessTokenInterface' => $vendorDir . '/league/oauth2-client/src/Token/AccessTokenInterface.php', - 'League\\OAuth2\\Client\\Token\\ResourceOwnerAccessTokenInterface' => $vendorDir . '/league/oauth2-client/src/Token/ResourceOwnerAccessTokenInterface.php', - 'League\\OAuth2\\Client\\Tool\\ArrayAccessorTrait' => $vendorDir . '/league/oauth2-client/src/Tool/ArrayAccessorTrait.php', - 'League\\OAuth2\\Client\\Tool\\BearerAuthorizationTrait' => $vendorDir . '/league/oauth2-client/src/Tool/BearerAuthorizationTrait.php', - 'League\\OAuth2\\Client\\Tool\\GuardedPropertyTrait' => $vendorDir . '/league/oauth2-client/src/Tool/GuardedPropertyTrait.php', - 'League\\OAuth2\\Client\\Tool\\MacAuthorizationTrait' => $vendorDir . '/league/oauth2-client/src/Tool/MacAuthorizationTrait.php', - 'League\\OAuth2\\Client\\Tool\\ProviderRedirectTrait' => $vendorDir . '/league/oauth2-client/src/Tool/ProviderRedirectTrait.php', - 'League\\OAuth2\\Client\\Tool\\QueryBuilderTrait' => $vendorDir . '/league/oauth2-client/src/Tool/QueryBuilderTrait.php', - 'League\\OAuth2\\Client\\Tool\\RequestFactory' => $vendorDir . '/league/oauth2-client/src/Tool/RequestFactory.php', - 'League\\OAuth2\\Client\\Tool\\RequiredParameterTrait' => $vendorDir . '/league/oauth2-client/src/Tool/RequiredParameterTrait.php', - 'ListExpression' => $baseDir . '/core/oql/expression.class.inc.php', - 'ListOqlExpression' => $baseDir . '/core/oql/oqlquery.class.inc.php', - 'Locale' => $vendorDir . '/symfony/polyfill-intl-icu/Resources/stubs/Locale.php', - 'LogAPI' => $baseDir . '/core/log.class.inc.php', - 'LogChannels' => $baseDir . '/core/log.class.inc.php', - 'LogFileNameBuilderFactory' => $baseDir . '/core/log.class.inc.php', - 'LogFileRotationProcess' => $baseDir . '/core/log.class.inc.php', - 'LoginBlockExtension' => $baseDir . '/application/logintwig.class.inc.php', - 'LoginTwigContext' => $baseDir . '/application/logintwig.class.inc.php', - 'LoginTwigRenderer' => $baseDir . '/application/logintwig.class.inc.php', - 'LoginWebPage' => $baseDir . '/application/loginwebpage.class.inc.php', - 'MatchExpression' => $baseDir . '/core/oql/expression.class.inc.php', - 'MatchOqlExpression' => $baseDir . '/core/oql/oqlquery.class.inc.php', - 'MenuBlock' => $baseDir . '/application/displayblock.class.inc.php', - 'MenuGroup' => $baseDir . '/application/menunode.class.inc.php', - 'MenuNode' => $baseDir . '/application/menunode.class.inc.php', - 'MetaModel' => $baseDir . '/core/metamodel.class.php', - 'MissingColumnException' => $baseDir . '/core/attributedef.class.inc.php', - 'MissingQueryArgument' => $baseDir . '/core/oql/expression.class.inc.php', - 'ModelReflection' => $baseDir . '/core/modelreflection.class.inc.php', - 'ModelReflectionRuntime' => $baseDir . '/core/modelreflection.class.inc.php', - 'ModuleDesign' => $baseDir . '/core/moduledesign.class.inc.php', - 'ModuleHandlerAPI' => $baseDir . '/core/modulehandler.class.inc.php', - 'ModuleHandlerApiInterface' => $baseDir . '/core/modulehandler.class.inc.php', - 'MonthlyRotatingLogFileNameBuilder' => $baseDir . '/core/log.class.inc.php', - 'MyHelpers' => $baseDir . '/core/MyHelpers.class.inc.php', - 'MySQLException' => $baseDir . '/application/exceptions/mysql/MySQLException.php', - 'MySQLHasGoneAwayException' => $baseDir . '/application/exceptions/mysql/MySQLHasGoneAwayException.php', - 'MySQLNoTransactionException' => $baseDir . '/application/exceptions/mysql/MySQLNoTransactionException.php', - 'MySQLQueryHasNoResultException' => $baseDir . '/application/exceptions/mysql/MySQLQueryHasNoResultException.php', - 'MySQLTransactionNotClosedException' => $baseDir . '/application/exceptions/mysql/MySQLTransactionNotClosedException.php', - 'NestedQueryExpression' => $baseDir . '/core/oql/expression.class.inc.php', - 'NestedQueryOqlExpression' => $baseDir . '/core/oql/oqlquery.class.inc.php', - 'NewObjectMenuNode' => $baseDir . '/application/menunode.class.inc.php', - 'NewsroomProviderBase' => $baseDir . '/application/newsroomprovider.class.inc.php', - 'NiceWebPage' => $baseDir . '/sources/Application/WebPage/NiceWebPage.php', - 'Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php', - 'NotYetEvaluatedExpression' => $baseDir . '/core/oql/expression.class.inc.php', - 'NumberFormatter' => $vendorDir . '/symfony/polyfill-intl-icu/Resources/stubs/NumberFormatter.php', - 'OQLActualClassTreeResolver' => $baseDir . '/core/oqlactualclasstreeresolver.class.inc.php', - 'OQLClassNode' => $baseDir . '/core/oqlclassnode.class.inc.php', - 'OQLClassTreeBuilder' => $baseDir . '/core/oqlclasstreebuilder.class.inc.php', - 'OQLClassTreeOptimizer' => $baseDir . '/core/oqlclasstreeoptimizer.class.inc.php', - 'OQLException' => $baseDir . '/core/oql/oqlexception.class.inc.php', - 'OQLJoin' => $baseDir . '/core/oqlclassnode.class.inc.php', - 'OQLLexer' => $baseDir . '/core/oql/oql-lexer.php', - 'OQLLexerException' => $baseDir . '/core/oql/oql-lexer.php', - 'OQLLexerRaw' => $baseDir . '/core/oql/oql-lexer.php', - 'OQLMenuNode' => $baseDir . '/application/menunode.class.inc.php', - 'OQLParser' => $baseDir . '/core/oql/oql-parser.php', - 'OQLParserException' => $baseDir . '/core/oql/oql-parser.php', - 'OQLParserParseFailureException' => $baseDir . '/core/oql/oql-parser.php', - 'OQLParserRaw' => $baseDir . '/core/oql/oql-parser.php', - 'OQLParserStackOverFlowException' => $baseDir . '/core/oql/oql-parser.php', - 'OQLParserSyntaxErrorException' => $baseDir . '/core/oql/oql-parser.php', - 'OQLParser_yyStackEntry' => $baseDir . '/core/oql/oql-parser.php', - 'OQLParser_yyToken' => $baseDir . '/core/oql/oql-parser.php', - 'OS_Guess' => $vendorDir . '/pear/pear-core-minimal/src/OS/Guess.php', - 'ObjectDetailsTemplate' => $baseDir . '/application/template.class.inc.php', - 'ObjectResult' => $baseDir . '/core/restservices.class.inc.php', - 'ObjectStimulus' => $baseDir . '/core/stimulus.class.inc.php', - 'ObsolescenceDateUpdater' => $baseDir . '/core/background.inc.php', - 'OqlHexValue' => $baseDir . '/core/oql/oqlquery.class.inc.php', - 'OqlInterpreter' => $baseDir . '/core/oql/oqlinterpreter.class.inc.php', - 'OqlInterpreterException' => $baseDir . '/core/oql/oqlinterpreter.class.inc.php', - 'OqlJoinSpec' => $baseDir . '/core/oql/oqlquery.class.inc.php', - 'OqlName' => $baseDir . '/core/oql/oqlquery.class.inc.php', - 'OqlNormalizeException' => $baseDir . '/core/oql/oqlinterpreter.class.inc.php', - 'OqlObjectQuery' => $baseDir . '/core/oql/oqlquery.class.inc.php', - 'OqlQuery' => $baseDir . '/core/oql/oqlquery.class.inc.php', - 'OqlUnionQuery' => $baseDir . '/core/oql/oqlquery.class.inc.php', - 'PDF417' => $vendorDir . '/combodo/tcpdf/include/barcodes/pdf417.php', - 'PDFBulkExport' => $baseDir . '/core/pdfbulkexport.class.inc.php', - 'PDFPage' => $baseDir . '/sources/Application/WebPage/PDFPage.php', - 'PEAR' => $vendorDir . '/pear/pear-core-minimal/src/PEAR.php', - 'PEAR_ErrorStack' => $vendorDir . '/pear/pear-core-minimal/src/PEAR/ErrorStack.php', - 'PEAR_Exception' => $vendorDir . '/pear/pear_exception/PEAR/Exception.php', - 'Page' => $baseDir . '/sources/Application/WebPage/Page.php', - 'Pelago\\Emogrifier\\Caching\\SimpleStringCache' => $vendorDir . '/pelago/emogrifier/src/Caching/SimpleStringCache.php', - 'Pelago\\Emogrifier\\CssInliner' => $vendorDir . '/pelago/emogrifier/src/CssInliner.php', - 'Pelago\\Emogrifier\\Css\\CssDocument' => $vendorDir . '/pelago/emogrifier/src/Css/CssDocument.php', - 'Pelago\\Emogrifier\\Css\\StyleRule' => $vendorDir . '/pelago/emogrifier/src/Css/StyleRule.php', - 'Pelago\\Emogrifier\\HtmlProcessor\\AbstractHtmlProcessor' => $vendorDir . '/pelago/emogrifier/src/HtmlProcessor/AbstractHtmlProcessor.php', - 'Pelago\\Emogrifier\\HtmlProcessor\\CssToAttributeConverter' => $vendorDir . '/pelago/emogrifier/src/HtmlProcessor/CssToAttributeConverter.php', - 'Pelago\\Emogrifier\\HtmlProcessor\\HtmlNormalizer' => $vendorDir . '/pelago/emogrifier/src/HtmlProcessor/HtmlNormalizer.php', - 'Pelago\\Emogrifier\\HtmlProcessor\\HtmlPruner' => $vendorDir . '/pelago/emogrifier/src/HtmlProcessor/HtmlPruner.php', - 'Pelago\\Emogrifier\\Utilities\\ArrayIntersector' => $vendorDir . '/pelago/emogrifier/src/Utilities/ArrayIntersector.php', - 'Pelago\\Emogrifier\\Utilities\\CssConcatenator' => $vendorDir . '/pelago/emogrifier/src/Utilities/CssConcatenator.php', - 'PhpParser\\Builder' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder.php', - 'PhpParser\\BuilderFactory' => $vendorDir . '/nikic/php-parser/lib/PhpParser/BuilderFactory.php', - 'PhpParser\\BuilderHelpers' => $vendorDir . '/nikic/php-parser/lib/PhpParser/BuilderHelpers.php', - 'PhpParser\\Builder\\ClassConst' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/ClassConst.php', - 'PhpParser\\Builder\\Class_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Class_.php', - 'PhpParser\\Builder\\Declaration' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Declaration.php', - 'PhpParser\\Builder\\EnumCase' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/EnumCase.php', - 'PhpParser\\Builder\\Enum_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Enum_.php', - 'PhpParser\\Builder\\FunctionLike' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php', - 'PhpParser\\Builder\\Function_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Function_.php', - 'PhpParser\\Builder\\Interface_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Interface_.php', - 'PhpParser\\Builder\\Method' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Method.php', - 'PhpParser\\Builder\\Namespace_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php', - 'PhpParser\\Builder\\Param' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Param.php', - 'PhpParser\\Builder\\Property' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Property.php', - 'PhpParser\\Builder\\TraitUse' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/TraitUse.php', - 'PhpParser\\Builder\\TraitUseAdaptation' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.php', - 'PhpParser\\Builder\\Trait_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Trait_.php', - 'PhpParser\\Builder\\Use_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Use_.php', - 'PhpParser\\Comment' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Comment.php', - 'PhpParser\\Comment\\Doc' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Comment/Doc.php', - 'PhpParser\\ConstExprEvaluationException' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ConstExprEvaluationException.php', - 'PhpParser\\ConstExprEvaluator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.php', - 'PhpParser\\Error' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Error.php', - 'PhpParser\\ErrorHandler' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ErrorHandler.php', - 'PhpParser\\ErrorHandler\\Collecting' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ErrorHandler/Collecting.php', - 'PhpParser\\ErrorHandler\\Throwing' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php', - 'PhpParser\\Internal\\DiffElem' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Internal/DiffElem.php', - 'PhpParser\\Internal\\Differ' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Internal/Differ.php', - 'PhpParser\\Internal\\PrintableNewAnonClassNode' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php', - 'PhpParser\\Internal\\TokenStream' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php', - 'PhpParser\\JsonDecoder' => $vendorDir . '/nikic/php-parser/lib/PhpParser/JsonDecoder.php', - 'PhpParser\\Lexer' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer.php', - 'PhpParser\\Lexer\\Emulative' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php', - 'PhpParser\\Lexer\\TokenEmulator\\AttributeEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php', - 'PhpParser\\Lexer\\TokenEmulator\\CoaleseEqualTokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/CoaleseEqualTokenEmulator.php', - 'PhpParser\\Lexer\\TokenEmulator\\EnumTokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/EnumTokenEmulator.php', - 'PhpParser\\Lexer\\TokenEmulator\\ExplicitOctalEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ExplicitOctalEmulator.php', - 'PhpParser\\Lexer\\TokenEmulator\\FlexibleDocStringEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php', - 'PhpParser\\Lexer\\TokenEmulator\\FnTokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php', - 'PhpParser\\Lexer\\TokenEmulator\\KeywordEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php', - 'PhpParser\\Lexer\\TokenEmulator\\MatchTokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php', - 'PhpParser\\Lexer\\TokenEmulator\\NullsafeTokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php', - 'PhpParser\\Lexer\\TokenEmulator\\NumericLiteralSeparatorEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php', - 'PhpParser\\Lexer\\TokenEmulator\\ReadonlyTokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyTokenEmulator.php', - 'PhpParser\\Lexer\\TokenEmulator\\ReverseEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.php', - 'PhpParser\\Lexer\\TokenEmulator\\TokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php', - 'PhpParser\\NameContext' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NameContext.php', - 'PhpParser\\Node' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node.php', - 'PhpParser\\NodeAbstract' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeAbstract.php', - 'PhpParser\\NodeDumper' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeDumper.php', - 'PhpParser\\NodeFinder' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeFinder.php', - 'PhpParser\\NodeTraverser' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeTraverser.php', - 'PhpParser\\NodeTraverserInterface' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php', - 'PhpParser\\NodeVisitor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitor.php', - 'PhpParser\\NodeVisitorAbstract' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php', - 'PhpParser\\NodeVisitor\\CloningVisitor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php', - 'PhpParser\\NodeVisitor\\FindingVisitor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php', - 'PhpParser\\NodeVisitor\\FirstFindingVisitor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.php', - 'PhpParser\\NodeVisitor\\NameResolver' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php', - 'PhpParser\\NodeVisitor\\NodeConnectingVisitor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php', - 'PhpParser\\NodeVisitor\\ParentConnectingVisitor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php', - 'PhpParser\\Node\\Arg' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Arg.php', - 'PhpParser\\Node\\Attribute' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Attribute.php', - 'PhpParser\\Node\\AttributeGroup' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php', - 'PhpParser\\Node\\ComplexType' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/ComplexType.php', - 'PhpParser\\Node\\Const_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Const_.php', - 'PhpParser\\Node\\Expr' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr.php', - 'PhpParser\\Node\\Expr\\ArrayDimFetch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php', - 'PhpParser\\Node\\Expr\\ArrayItem' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php', - 'PhpParser\\Node\\Expr\\Array_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php', - 'PhpParser\\Node\\Expr\\ArrowFunction' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php', - 'PhpParser\\Node\\Expr\\Assign' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php', - 'PhpParser\\Node\\Expr\\AssignOp' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php', - 'PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php', - 'PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php', - 'PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php', - 'PhpParser\\Node\\Expr\\AssignOp\\Coalesce' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Coalesce.php', - 'PhpParser\\Node\\Expr\\AssignOp\\Concat' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.php', - 'PhpParser\\Node\\Expr\\AssignOp\\Div' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.php', - 'PhpParser\\Node\\Expr\\AssignOp\\Minus' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.php', - 'PhpParser\\Node\\Expr\\AssignOp\\Mod' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.php', - 'PhpParser\\Node\\Expr\\AssignOp\\Mul' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.php', - 'PhpParser\\Node\\Expr\\AssignOp\\Plus' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.php', - 'PhpParser\\Node\\Expr\\AssignOp\\Pow' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.php', - 'PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php', - 'PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php', - 'PhpParser\\Node\\Expr\\AssignRef' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignRef.php', - 'PhpParser\\Node\\Expr\\BinaryOp' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Coalesce' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Concat' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Div' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Equal' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Greater' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Identical' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Minus' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Mod' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Mul' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Plus' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Pow' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Spaceship' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php', - 'PhpParser\\Node\\Expr\\BitwiseNot' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php', - 'PhpParser\\Node\\Expr\\BooleanNot' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php', - 'PhpParser\\Node\\Expr\\CallLike' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/CallLike.php', - 'PhpParser\\Node\\Expr\\Cast' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php', - 'PhpParser\\Node\\Expr\\Cast\\Array_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php', - 'PhpParser\\Node\\Expr\\Cast\\Bool_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php', - 'PhpParser\\Node\\Expr\\Cast\\Double' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Double.php', - 'PhpParser\\Node\\Expr\\Cast\\Int_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.php', - 'PhpParser\\Node\\Expr\\Cast\\Object_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.php', - 'PhpParser\\Node\\Expr\\Cast\\String_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/String_.php', - 'PhpParser\\Node\\Expr\\Cast\\Unset_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.php', - 'PhpParser\\Node\\Expr\\ClassConstFetch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php', - 'PhpParser\\Node\\Expr\\Clone_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php', - 'PhpParser\\Node\\Expr\\Closure' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php', - 'PhpParser\\Node\\Expr\\ClosureUse' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php', - 'PhpParser\\Node\\Expr\\ConstFetch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php', - 'PhpParser\\Node\\Expr\\Empty_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php', - 'PhpParser\\Node\\Expr\\Error' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php', - 'PhpParser\\Node\\Expr\\ErrorSuppress' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php', - 'PhpParser\\Node\\Expr\\Eval_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php', - 'PhpParser\\Node\\Expr\\Exit_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php', - 'PhpParser\\Node\\Expr\\FuncCall' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php', - 'PhpParser\\Node\\Expr\\Include_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php', - 'PhpParser\\Node\\Expr\\Instanceof_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php', - 'PhpParser\\Node\\Expr\\Isset_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php', - 'PhpParser\\Node\\Expr\\List_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php', - 'PhpParser\\Node\\Expr\\Match_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.php', - 'PhpParser\\Node\\Expr\\MethodCall' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php', - 'PhpParser\\Node\\Expr\\New_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php', - 'PhpParser\\Node\\Expr\\NullsafeMethodCall' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php', - 'PhpParser\\Node\\Expr\\NullsafePropertyFetch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php', - 'PhpParser\\Node\\Expr\\PostDec' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php', - 'PhpParser\\Node\\Expr\\PostInc' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php', - 'PhpParser\\Node\\Expr\\PreDec' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php', - 'PhpParser\\Node\\Expr\\PreInc' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php', - 'PhpParser\\Node\\Expr\\Print_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php', - 'PhpParser\\Node\\Expr\\PropertyFetch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php', - 'PhpParser\\Node\\Expr\\ShellExec' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php', - 'PhpParser\\Node\\Expr\\StaticCall' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php', - 'PhpParser\\Node\\Expr\\StaticPropertyFetch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php', - 'PhpParser\\Node\\Expr\\Ternary' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php', - 'PhpParser\\Node\\Expr\\Throw_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.php', - 'PhpParser\\Node\\Expr\\UnaryMinus' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php', - 'PhpParser\\Node\\Expr\\UnaryPlus' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php', - 'PhpParser\\Node\\Expr\\Variable' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php', - 'PhpParser\\Node\\Expr\\YieldFrom' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php', - 'PhpParser\\Node\\Expr\\Yield_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php', - 'PhpParser\\Node\\FunctionLike' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php', - 'PhpParser\\Node\\Identifier' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Identifier.php', - 'PhpParser\\Node\\IntersectionType' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/IntersectionType.php', - 'PhpParser\\Node\\MatchArm' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/MatchArm.php', - 'PhpParser\\Node\\Name' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Name.php', - 'PhpParser\\Node\\Name\\FullyQualified' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php', - 'PhpParser\\Node\\Name\\Relative' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php', - 'PhpParser\\Node\\NullableType' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/NullableType.php', - 'PhpParser\\Node\\Param' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Param.php', - 'PhpParser\\Node\\Scalar' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar.php', - 'PhpParser\\Node\\Scalar\\DNumber' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/DNumber.php', - 'PhpParser\\Node\\Scalar\\Encapsed' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php', - 'PhpParser\\Node\\Scalar\\EncapsedStringPart' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php', - 'PhpParser\\Node\\Scalar\\LNumber' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php', - 'PhpParser\\Node\\Scalar\\MagicConst' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php', - 'PhpParser\\Node\\Scalar\\MagicConst\\Class_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php', - 'PhpParser\\Node\\Scalar\\MagicConst\\Dir' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php', - 'PhpParser\\Node\\Scalar\\MagicConst\\File' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php', - 'PhpParser\\Node\\Scalar\\MagicConst\\Function_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.php', - 'PhpParser\\Node\\Scalar\\MagicConst\\Line' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php', - 'PhpParser\\Node\\Scalar\\MagicConst\\Method' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.php', - 'PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php', - 'PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.php', - 'PhpParser\\Node\\Scalar\\String_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/String_.php', - 'PhpParser\\Node\\Stmt' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt.php', - 'PhpParser\\Node\\Stmt\\Break_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Break_.php', - 'PhpParser\\Node\\Stmt\\Case_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php', - 'PhpParser\\Node\\Stmt\\Catch_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php', - 'PhpParser\\Node\\Stmt\\ClassConst' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php', - 'PhpParser\\Node\\Stmt\\ClassLike' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php', - 'PhpParser\\Node\\Stmt\\ClassMethod' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php', - 'PhpParser\\Node\\Stmt\\Class_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php', - 'PhpParser\\Node\\Stmt\\Const_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php', - 'PhpParser\\Node\\Stmt\\Continue_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php', - 'PhpParser\\Node\\Stmt\\DeclareDeclare' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php', - 'PhpParser\\Node\\Stmt\\Declare_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php', - 'PhpParser\\Node\\Stmt\\Do_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php', - 'PhpParser\\Node\\Stmt\\Echo_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php', - 'PhpParser\\Node\\Stmt\\ElseIf_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php', - 'PhpParser\\Node\\Stmt\\Else_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php', - 'PhpParser\\Node\\Stmt\\EnumCase' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/EnumCase.php', - 'PhpParser\\Node\\Stmt\\Enum_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Enum_.php', - 'PhpParser\\Node\\Stmt\\Expression' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.php', - 'PhpParser\\Node\\Stmt\\Finally_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php', - 'PhpParser\\Node\\Stmt\\For_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php', - 'PhpParser\\Node\\Stmt\\Foreach_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php', - 'PhpParser\\Node\\Stmt\\Function_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php', - 'PhpParser\\Node\\Stmt\\Global_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php', - 'PhpParser\\Node\\Stmt\\Goto_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php', - 'PhpParser\\Node\\Stmt\\GroupUse' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php', - 'PhpParser\\Node\\Stmt\\HaltCompiler' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php', - 'PhpParser\\Node\\Stmt\\If_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php', - 'PhpParser\\Node\\Stmt\\InlineHTML' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php', - 'PhpParser\\Node\\Stmt\\Interface_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php', - 'PhpParser\\Node\\Stmt\\Label' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php', - 'PhpParser\\Node\\Stmt\\Namespace_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php', - 'PhpParser\\Node\\Stmt\\Nop' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php', - 'PhpParser\\Node\\Stmt\\Property' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php', - 'PhpParser\\Node\\Stmt\\PropertyProperty' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php', - 'PhpParser\\Node\\Stmt\\Return_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php', - 'PhpParser\\Node\\Stmt\\StaticVar' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php', - 'PhpParser\\Node\\Stmt\\Static_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php', - 'PhpParser\\Node\\Stmt\\Switch_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php', - 'PhpParser\\Node\\Stmt\\Throw_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php', - 'PhpParser\\Node\\Stmt\\TraitUse' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php', - 'PhpParser\\Node\\Stmt\\TraitUseAdaptation' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php', - 'PhpParser\\Node\\Stmt\\TraitUseAdaptation\\Alias' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php', - 'PhpParser\\Node\\Stmt\\TraitUseAdaptation\\Precedence' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php', - 'PhpParser\\Node\\Stmt\\Trait_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php', - 'PhpParser\\Node\\Stmt\\TryCatch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php', - 'PhpParser\\Node\\Stmt\\Unset_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php', - 'PhpParser\\Node\\Stmt\\UseUse' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php', - 'PhpParser\\Node\\Stmt\\Use_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php', - 'PhpParser\\Node\\Stmt\\While_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php', - 'PhpParser\\Node\\UnionType' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/UnionType.php', - 'PhpParser\\Node\\VarLikeIdentifier' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php', - 'PhpParser\\Node\\VariadicPlaceholder' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/VariadicPlaceholder.php', - 'PhpParser\\Parser' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Parser.php', - 'PhpParser\\ParserAbstract' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ParserAbstract.php', - 'PhpParser\\ParserFactory' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ParserFactory.php', - 'PhpParser\\Parser\\Multiple' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Parser/Multiple.php', - 'PhpParser\\Parser\\Php5' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Parser/Php5.php', - 'PhpParser\\Parser\\Php7' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Parser/Php7.php', - 'PhpParser\\Parser\\Tokens' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Parser/Tokens.php', - 'PhpParser\\PrettyPrinterAbstract' => $vendorDir . '/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php', - 'PhpParser\\PrettyPrinter\\Standard' => $vendorDir . '/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php', - 'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', - 'PluginInstanciationManager' => $baseDir . '/core/plugininstanciationmanager.class.inc.php', - 'PluginManager' => $baseDir . '/core/pluginmanager.class.inc.php', - 'PortalDispatcher' => $baseDir . '/application/portaldispatcher.class.inc.php', - 'PortalURLMaker' => $baseDir . '/application/applicationcontext.class.inc.php', - 'PrintableDataTable' => $baseDir . '/application/datatable.class.inc.php', - 'ProcessException' => $baseDir . '/application/exceptions/process/ProcessException.php', - 'ProcessFatalException' => $baseDir . '/application/exceptions/process/ProcessFatalException.php', - 'ProcessInvalidConfigException' => $baseDir . '/application/exceptions/process/ProcessInvalidConfigException.php', - 'Psr\\Cache\\CacheException' => $vendorDir . '/psr/cache/src/CacheException.php', - 'Psr\\Cache\\CacheItemInterface' => $vendorDir . '/psr/cache/src/CacheItemInterface.php', - 'Psr\\Cache\\CacheItemPoolInterface' => $vendorDir . '/psr/cache/src/CacheItemPoolInterface.php', - 'Psr\\Cache\\InvalidArgumentException' => $vendorDir . '/psr/cache/src/InvalidArgumentException.php', - 'Psr\\Container\\ContainerExceptionInterface' => $vendorDir . '/psr/container/src/ContainerExceptionInterface.php', - 'Psr\\Container\\ContainerInterface' => $vendorDir . '/psr/container/src/ContainerInterface.php', - 'Psr\\Container\\NotFoundExceptionInterface' => $vendorDir . '/psr/container/src/NotFoundExceptionInterface.php', - 'Psr\\EventDispatcher\\EventDispatcherInterface' => $vendorDir . '/psr/event-dispatcher/src/EventDispatcherInterface.php', - 'Psr\\EventDispatcher\\ListenerProviderInterface' => $vendorDir . '/psr/event-dispatcher/src/ListenerProviderInterface.php', - 'Psr\\EventDispatcher\\StoppableEventInterface' => $vendorDir . '/psr/event-dispatcher/src/StoppableEventInterface.php', - 'Psr\\Http\\Client\\ClientExceptionInterface' => $vendorDir . '/psr/http-client/src/ClientExceptionInterface.php', - 'Psr\\Http\\Client\\ClientInterface' => $vendorDir . '/psr/http-client/src/ClientInterface.php', - 'Psr\\Http\\Client\\NetworkExceptionInterface' => $vendorDir . '/psr/http-client/src/NetworkExceptionInterface.php', - 'Psr\\Http\\Client\\RequestExceptionInterface' => $vendorDir . '/psr/http-client/src/RequestExceptionInterface.php', - 'Psr\\Http\\Message\\MessageInterface' => $vendorDir . '/psr/http-message/src/MessageInterface.php', - 'Psr\\Http\\Message\\RequestFactoryInterface' => $vendorDir . '/psr/http-factory/src/RequestFactoryInterface.php', - 'Psr\\Http\\Message\\RequestInterface' => $vendorDir . '/psr/http-message/src/RequestInterface.php', - 'Psr\\Http\\Message\\ResponseFactoryInterface' => $vendorDir . '/psr/http-factory/src/ResponseFactoryInterface.php', - 'Psr\\Http\\Message\\ResponseInterface' => $vendorDir . '/psr/http-message/src/ResponseInterface.php', - 'Psr\\Http\\Message\\ServerRequestFactoryInterface' => $vendorDir . '/psr/http-factory/src/ServerRequestFactoryInterface.php', - 'Psr\\Http\\Message\\ServerRequestInterface' => $vendorDir . '/psr/http-message/src/ServerRequestInterface.php', - 'Psr\\Http\\Message\\StreamFactoryInterface' => $vendorDir . '/psr/http-factory/src/StreamFactoryInterface.php', - 'Psr\\Http\\Message\\StreamInterface' => $vendorDir . '/psr/http-message/src/StreamInterface.php', - 'Psr\\Http\\Message\\UploadedFileFactoryInterface' => $vendorDir . '/psr/http-factory/src/UploadedFileFactoryInterface.php', - 'Psr\\Http\\Message\\UploadedFileInterface' => $vendorDir . '/psr/http-message/src/UploadedFileInterface.php', - 'Psr\\Http\\Message\\UriFactoryInterface' => $vendorDir . '/psr/http-factory/src/UriFactoryInterface.php', - 'Psr\\Http\\Message\\UriInterface' => $vendorDir . '/psr/http-message/src/UriInterface.php', - 'Psr\\Log\\AbstractLogger' => $vendorDir . '/psr/log/Psr/Log/AbstractLogger.php', - 'Psr\\Log\\InvalidArgumentException' => $vendorDir . '/psr/log/Psr/Log/InvalidArgumentException.php', - 'Psr\\Log\\LogLevel' => $vendorDir . '/psr/log/Psr/Log/LogLevel.php', - 'Psr\\Log\\LoggerAwareInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerAwareInterface.php', - 'Psr\\Log\\LoggerAwareTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerAwareTrait.php', - 'Psr\\Log\\LoggerInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerInterface.php', - 'Psr\\Log\\LoggerTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerTrait.php', - 'Psr\\Log\\NullLogger' => $vendorDir . '/psr/log/Psr/Log/NullLogger.php', - 'QRcode' => $vendorDir . '/combodo/tcpdf/include/barcodes/qrcode.php', - 'Query' => $baseDir . '/application/query.class.inc.php', - 'QueryBuilderContext' => $baseDir . '/core/querybuildercontext.class.inc.php', - 'QueryBuilderExpressions' => $baseDir . '/core/querybuilderexpressions.class.inc.php', - 'QueryOQL' => $baseDir . '/application/query.class.inc.php', - 'QueryReflection' => $baseDir . '/core/modelreflection.class.inc.php', - 'QueryReflectionRuntime' => $baseDir . '/core/modelreflection.class.inc.php', - 'RelationEdge' => $baseDir . '/core/relationgraph.class.inc.php', - 'RelationGraph' => $baseDir . '/core/relationgraph.class.inc.php', - 'RelationObjectNode' => $baseDir . '/core/relationgraph.class.inc.php', - 'RelationRedundancyNode' => $baseDir . '/core/relationgraph.class.inc.php', - 'RelationTypeIterator' => $baseDir . '/core/simplegraph.class.inc.php', - 'RestDelete' => $baseDir . '/core/restservices.class.inc.php', - 'RestResult' => $baseDir . '/application/applicationextension.inc.php', - 'RestResultWithObjects' => $baseDir . '/core/restservices.class.inc.php', - 'RestResultWithRelations' => $baseDir . '/core/restservices.class.inc.php', - 'RestUtils' => $baseDir . '/application/applicationextension.inc.php', - 'ReturnTypeWillChange' => $vendorDir . '/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php', - 'RotatingLogFileNameBuilder' => $baseDir . '/core/log.class.inc.php', - 'RowStatus' => $baseDir . '/core/bulkchange.class.inc.php', - 'RowStatus_Disappeared' => $baseDir . '/core/bulkchange.class.inc.php', - 'RowStatus_Error' => $baseDir . '/core/bulkchange.class.inc.php', - 'RowStatus_Issue' => $baseDir . '/core/bulkchange.class.inc.php', - 'RowStatus_Modify' => $baseDir . '/core/bulkchange.class.inc.php', - 'RowStatus_NewObj' => $baseDir . '/core/bulkchange.class.inc.php', - 'RowStatus_NoChange' => $baseDir . '/core/bulkchange.class.inc.php', - 'RunTimeIconSelectionField' => $baseDir . '/application/forms.class.inc.php', - 'RuntimeDashboard' => $baseDir . '/application/dashboard.class.inc.php', - 'SQLExpression' => $baseDir . '/core/oql/expression.class.inc.php', - 'SQLObjectQuery' => $baseDir . '/core/sqlobjectquery.class.inc.php', - 'SQLObjectQueryBuilder' => $baseDir . '/core/sqlobjectquerybuilder.class.inc.php', - 'SQLQuery' => $baseDir . '/core/sqlquery.class.inc.php', - 'SQLUnionQuery' => $baseDir . '/core/sqlunionquery.class.inc.php', - 'SVGDOMSanitizer' => $baseDir . '/core/htmlsanitizer.class.inc.php', - 'Sabberworm\\CSS\\CSSList\\AtRuleBlockList' => $vendorDir . '/sabberworm/php-css-parser/src/CSSList/AtRuleBlockList.php', - 'Sabberworm\\CSS\\CSSList\\CSSBlockList' => $vendorDir . '/sabberworm/php-css-parser/src/CSSList/CSSBlockList.php', - 'Sabberworm\\CSS\\CSSList\\CSSList' => $vendorDir . '/sabberworm/php-css-parser/src/CSSList/CSSList.php', - 'Sabberworm\\CSS\\CSSList\\Document' => $vendorDir . '/sabberworm/php-css-parser/src/CSSList/Document.php', - 'Sabberworm\\CSS\\CSSList\\KeyFrame' => $vendorDir . '/sabberworm/php-css-parser/src/CSSList/KeyFrame.php', - 'Sabberworm\\CSS\\Comment\\Comment' => $vendorDir . '/sabberworm/php-css-parser/src/Comment/Comment.php', - 'Sabberworm\\CSS\\Comment\\Commentable' => $vendorDir . '/sabberworm/php-css-parser/src/Comment/Commentable.php', - 'Sabberworm\\CSS\\OutputFormat' => $vendorDir . '/sabberworm/php-css-parser/src/OutputFormat.php', - 'Sabberworm\\CSS\\OutputFormatter' => $vendorDir . '/sabberworm/php-css-parser/src/OutputFormatter.php', - 'Sabberworm\\CSS\\Parser' => $vendorDir . '/sabberworm/php-css-parser/src/Parser.php', - 'Sabberworm\\CSS\\Parsing\\OutputException' => $vendorDir . '/sabberworm/php-css-parser/src/Parsing/OutputException.php', - 'Sabberworm\\CSS\\Parsing\\ParserState' => $vendorDir . '/sabberworm/php-css-parser/src/Parsing/ParserState.php', - 'Sabberworm\\CSS\\Parsing\\SourceException' => $vendorDir . '/sabberworm/php-css-parser/src/Parsing/SourceException.php', - 'Sabberworm\\CSS\\Parsing\\UnexpectedEOFException' => $vendorDir . '/sabberworm/php-css-parser/src/Parsing/UnexpectedEOFException.php', - 'Sabberworm\\CSS\\Parsing\\UnexpectedTokenException' => $vendorDir . '/sabberworm/php-css-parser/src/Parsing/UnexpectedTokenException.php', - 'Sabberworm\\CSS\\Property\\AtRule' => $vendorDir . '/sabberworm/php-css-parser/src/Property/AtRule.php', - 'Sabberworm\\CSS\\Property\\CSSNamespace' => $vendorDir . '/sabberworm/php-css-parser/src/Property/CSSNamespace.php', - 'Sabberworm\\CSS\\Property\\Charset' => $vendorDir . '/sabberworm/php-css-parser/src/Property/Charset.php', - 'Sabberworm\\CSS\\Property\\Import' => $vendorDir . '/sabberworm/php-css-parser/src/Property/Import.php', - 'Sabberworm\\CSS\\Property\\KeyframeSelector' => $vendorDir . '/sabberworm/php-css-parser/src/Property/KeyframeSelector.php', - 'Sabberworm\\CSS\\Property\\Selector' => $vendorDir . '/sabberworm/php-css-parser/src/Property/Selector.php', - 'Sabberworm\\CSS\\Renderable' => $vendorDir . '/sabberworm/php-css-parser/src/Renderable.php', - 'Sabberworm\\CSS\\RuleSet\\AtRuleSet' => $vendorDir . '/sabberworm/php-css-parser/src/RuleSet/AtRuleSet.php', - 'Sabberworm\\CSS\\RuleSet\\DeclarationBlock' => $vendorDir . '/sabberworm/php-css-parser/src/RuleSet/DeclarationBlock.php', - 'Sabberworm\\CSS\\RuleSet\\RuleSet' => $vendorDir . '/sabberworm/php-css-parser/src/RuleSet/RuleSet.php', - 'Sabberworm\\CSS\\Rule\\Rule' => $vendorDir . '/sabberworm/php-css-parser/src/Rule/Rule.php', - 'Sabberworm\\CSS\\Settings' => $vendorDir . '/sabberworm/php-css-parser/src/Settings.php', - 'Sabberworm\\CSS\\Value\\CSSFunction' => $vendorDir . '/sabberworm/php-css-parser/src/Value/CSSFunction.php', - 'Sabberworm\\CSS\\Value\\CSSString' => $vendorDir . '/sabberworm/php-css-parser/src/Value/CSSString.php', - 'Sabberworm\\CSS\\Value\\CalcFunction' => $vendorDir . '/sabberworm/php-css-parser/src/Value/CalcFunction.php', - 'Sabberworm\\CSS\\Value\\CalcRuleValueList' => $vendorDir . '/sabberworm/php-css-parser/src/Value/CalcRuleValueList.php', - 'Sabberworm\\CSS\\Value\\Color' => $vendorDir . '/sabberworm/php-css-parser/src/Value/Color.php', - 'Sabberworm\\CSS\\Value\\LineName' => $vendorDir . '/sabberworm/php-css-parser/src/Value/LineName.php', - 'Sabberworm\\CSS\\Value\\PrimitiveValue' => $vendorDir . '/sabberworm/php-css-parser/src/Value/PrimitiveValue.php', - 'Sabberworm\\CSS\\Value\\RuleValueList' => $vendorDir . '/sabberworm/php-css-parser/src/Value/RuleValueList.php', - 'Sabberworm\\CSS\\Value\\Size' => $vendorDir . '/sabberworm/php-css-parser/src/Value/Size.php', - 'Sabberworm\\CSS\\Value\\URL' => $vendorDir . '/sabberworm/php-css-parser/src/Value/URL.php', - 'Sabberworm\\CSS\\Value\\Value' => $vendorDir . '/sabberworm/php-css-parser/src/Value/Value.php', - 'Sabberworm\\CSS\\Value\\ValueList' => $vendorDir . '/sabberworm/php-css-parser/src/Value/ValueList.php', - 'ScalarExpression' => $baseDir . '/core/oql/expression.class.inc.php', - 'ScalarOqlExpression' => $baseDir . '/core/oql/oqlquery.class.inc.php', - 'ScssPhp\\ScssPhp\\Base\\Range' => $vendorDir . '/scssphp/scssphp/src/Base/Range.php', - 'ScssPhp\\ScssPhp\\Block' => $vendorDir . '/scssphp/scssphp/src/Block.php', - 'ScssPhp\\ScssPhp\\Block\\AtRootBlock' => $vendorDir . '/scssphp/scssphp/src/Block/AtRootBlock.php', - 'ScssPhp\\ScssPhp\\Block\\CallableBlock' => $vendorDir . '/scssphp/scssphp/src/Block/CallableBlock.php', - 'ScssPhp\\ScssPhp\\Block\\ContentBlock' => $vendorDir . '/scssphp/scssphp/src/Block/ContentBlock.php', - 'ScssPhp\\ScssPhp\\Block\\DirectiveBlock' => $vendorDir . '/scssphp/scssphp/src/Block/DirectiveBlock.php', - 'ScssPhp\\ScssPhp\\Block\\EachBlock' => $vendorDir . '/scssphp/scssphp/src/Block/EachBlock.php', - 'ScssPhp\\ScssPhp\\Block\\ElseBlock' => $vendorDir . '/scssphp/scssphp/src/Block/ElseBlock.php', - 'ScssPhp\\ScssPhp\\Block\\ElseifBlock' => $vendorDir . '/scssphp/scssphp/src/Block/ElseifBlock.php', - 'ScssPhp\\ScssPhp\\Block\\ForBlock' => $vendorDir . '/scssphp/scssphp/src/Block/ForBlock.php', - 'ScssPhp\\ScssPhp\\Block\\IfBlock' => $vendorDir . '/scssphp/scssphp/src/Block/IfBlock.php', - 'ScssPhp\\ScssPhp\\Block\\MediaBlock' => $vendorDir . '/scssphp/scssphp/src/Block/MediaBlock.php', - 'ScssPhp\\ScssPhp\\Block\\NestedPropertyBlock' => $vendorDir . '/scssphp/scssphp/src/Block/NestedPropertyBlock.php', - 'ScssPhp\\ScssPhp\\Block\\WhileBlock' => $vendorDir . '/scssphp/scssphp/src/Block/WhileBlock.php', - 'ScssPhp\\ScssPhp\\Cache' => $vendorDir . '/scssphp/scssphp/src/Cache.php', - 'ScssPhp\\ScssPhp\\Colors' => $vendorDir . '/scssphp/scssphp/src/Colors.php', - 'ScssPhp\\ScssPhp\\CompilationResult' => $vendorDir . '/scssphp/scssphp/src/CompilationResult.php', - 'ScssPhp\\ScssPhp\\Compiler' => $vendorDir . '/scssphp/scssphp/src/Compiler.php', - 'ScssPhp\\ScssPhp\\Compiler\\CachedResult' => $vendorDir . '/scssphp/scssphp/src/Compiler/CachedResult.php', - 'ScssPhp\\ScssPhp\\Compiler\\Environment' => $vendorDir . '/scssphp/scssphp/src/Compiler/Environment.php', - 'ScssPhp\\ScssPhp\\Exception\\CompilerException' => $vendorDir . '/scssphp/scssphp/src/Exception/CompilerException.php', - 'ScssPhp\\ScssPhp\\Exception\\ParserException' => $vendorDir . '/scssphp/scssphp/src/Exception/ParserException.php', - 'ScssPhp\\ScssPhp\\Exception\\RangeException' => $vendorDir . '/scssphp/scssphp/src/Exception/RangeException.php', - 'ScssPhp\\ScssPhp\\Exception\\SassException' => $vendorDir . '/scssphp/scssphp/src/Exception/SassException.php', - 'ScssPhp\\ScssPhp\\Exception\\SassScriptException' => $vendorDir . '/scssphp/scssphp/src/Exception/SassScriptException.php', - 'ScssPhp\\ScssPhp\\Exception\\ServerException' => $vendorDir . '/scssphp/scssphp/src/Exception/ServerException.php', - 'ScssPhp\\ScssPhp\\Formatter' => $vendorDir . '/scssphp/scssphp/src/Formatter.php', - 'ScssPhp\\ScssPhp\\Formatter\\Compact' => $vendorDir . '/scssphp/scssphp/src/Formatter/Compact.php', - 'ScssPhp\\ScssPhp\\Formatter\\Compressed' => $vendorDir . '/scssphp/scssphp/src/Formatter/Compressed.php', - 'ScssPhp\\ScssPhp\\Formatter\\Crunched' => $vendorDir . '/scssphp/scssphp/src/Formatter/Crunched.php', - 'ScssPhp\\ScssPhp\\Formatter\\Debug' => $vendorDir . '/scssphp/scssphp/src/Formatter/Debug.php', - 'ScssPhp\\ScssPhp\\Formatter\\Expanded' => $vendorDir . '/scssphp/scssphp/src/Formatter/Expanded.php', - 'ScssPhp\\ScssPhp\\Formatter\\Nested' => $vendorDir . '/scssphp/scssphp/src/Formatter/Nested.php', - 'ScssPhp\\ScssPhp\\Formatter\\OutputBlock' => $vendorDir . '/scssphp/scssphp/src/Formatter/OutputBlock.php', - 'ScssPhp\\ScssPhp\\Logger\\LoggerInterface' => $vendorDir . '/scssphp/scssphp/src/Logger/LoggerInterface.php', - 'ScssPhp\\ScssPhp\\Logger\\QuietLogger' => $vendorDir . '/scssphp/scssphp/src/Logger/QuietLogger.php', - 'ScssPhp\\ScssPhp\\Logger\\StreamLogger' => $vendorDir . '/scssphp/scssphp/src/Logger/StreamLogger.php', - 'ScssPhp\\ScssPhp\\Node' => $vendorDir . '/scssphp/scssphp/src/Node.php', - 'ScssPhp\\ScssPhp\\Node\\Number' => $vendorDir . '/scssphp/scssphp/src/Node/Number.php', - 'ScssPhp\\ScssPhp\\OutputStyle' => $vendorDir . '/scssphp/scssphp/src/OutputStyle.php', - 'ScssPhp\\ScssPhp\\Parser' => $vendorDir . '/scssphp/scssphp/src/Parser.php', - 'ScssPhp\\ScssPhp\\SourceMap\\Base64' => $vendorDir . '/scssphp/scssphp/src/SourceMap/Base64.php', - 'ScssPhp\\ScssPhp\\SourceMap\\Base64VLQ' => $vendorDir . '/scssphp/scssphp/src/SourceMap/Base64VLQ.php', - 'ScssPhp\\ScssPhp\\SourceMap\\SourceMapGenerator' => $vendorDir . '/scssphp/scssphp/src/SourceMap/SourceMapGenerator.php', - 'ScssPhp\\ScssPhp\\Type' => $vendorDir . '/scssphp/scssphp/src/Type.php', - 'ScssPhp\\ScssPhp\\Util' => $vendorDir . '/scssphp/scssphp/src/Util.php', - 'ScssPhp\\ScssPhp\\Util\\Path' => $vendorDir . '/scssphp/scssphp/src/Util/Path.php', - 'ScssPhp\\ScssPhp\\ValueConverter' => $vendorDir . '/scssphp/scssphp/src/ValueConverter.php', - 'ScssPhp\\ScssPhp\\Version' => $vendorDir . '/scssphp/scssphp/src/Version.php', - 'ScssPhp\\ScssPhp\\Warn' => $vendorDir . '/scssphp/scssphp/src/Warn.php', - 'SearchMenuNode' => $baseDir . '/application/menunode.class.inc.php', - 'SecurityException' => $baseDir . '/application/exceptions/SecurityException.php', - 'SeparatorPopupMenuItem' => $baseDir . '/application/applicationextension.inc.php', - 'SetupLog' => $baseDir . '/core/log.class.inc.php', - 'Shortcut' => $baseDir . '/application/shortcut.class.inc.php', - 'ShortcutContainerMenuNode' => $baseDir . '/application/menunode.class.inc.php', - 'ShortcutMenuNode' => $baseDir . '/application/menunode.class.inc.php', - 'ShortcutOQL' => $baseDir . '/application/shortcut.class.inc.php', - 'SimpleCrypt' => $baseDir . '/core/simplecrypt.class.inc.php', - 'SimpleCryptMcryptEngine' => $baseDir . '/core/simplecrypt.class.inc.php', - 'SimpleCryptOpenSSLEngine' => $baseDir . '/core/simplecrypt.class.inc.php', - 'SimpleCryptOpenSSLMcryptCompatibilityEngine' => $baseDir . '/core/simplecrypt.class.inc.php', - 'SimpleCryptSimpleEngine' => $baseDir . '/core/simplecrypt.class.inc.php', - 'SimpleCryptSodiumEngine' => $baseDir . '/core/simplecrypt.class.inc.php', - 'SimpleGraph' => $baseDir . '/core/simplegraph.class.inc.php', - 'SimpleGraphException' => $baseDir . '/core/simplegraph.class.inc.php', - 'SpreadsheetBulkExport' => $baseDir . '/core/spreadsheetbulkexport.class.inc.php', - 'StimulusChecker' => $baseDir . '/core/userrights.class.inc.php', - 'StimulusInternal' => $baseDir . '/core/stimulus.class.inc.php', - 'StimulusUserAction' => $baseDir . '/core/stimulus.class.inc.php', - 'Str' => $baseDir . '/core/MyHelpers.class.inc.php', - 'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', - 'SummaryCardService' => $baseDir . '/sources/Service/SummaryCard/SummaryCardService.php', - 'Symfony\\Bridge\\Twig\\AppVariable' => $vendorDir . '/symfony/twig-bridge/AppVariable.php', - 'Symfony\\Bridge\\Twig\\Command\\DebugCommand' => $vendorDir . '/symfony/twig-bridge/Command/DebugCommand.php', - 'Symfony\\Bridge\\Twig\\Command\\LintCommand' => $vendorDir . '/symfony/twig-bridge/Command/LintCommand.php', - 'Symfony\\Bridge\\Twig\\DataCollector\\TwigDataCollector' => $vendorDir . '/symfony/twig-bridge/DataCollector/TwigDataCollector.php', - 'Symfony\\Bridge\\Twig\\ErrorRenderer\\TwigErrorRenderer' => $vendorDir . '/symfony/twig-bridge/ErrorRenderer/TwigErrorRenderer.php', - 'Symfony\\Bridge\\Twig\\Extension\\AssetExtension' => $vendorDir . '/symfony/twig-bridge/Extension/AssetExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\CodeExtension' => $vendorDir . '/symfony/twig-bridge/Extension/CodeExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\CsrfExtension' => $vendorDir . '/symfony/twig-bridge/Extension/CsrfExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\CsrfRuntime' => $vendorDir . '/symfony/twig-bridge/Extension/CsrfRuntime.php', - 'Symfony\\Bridge\\Twig\\Extension\\DumpExtension' => $vendorDir . '/symfony/twig-bridge/Extension/DumpExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\ExpressionExtension' => $vendorDir . '/symfony/twig-bridge/Extension/ExpressionExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\FormExtension' => $vendorDir . '/symfony/twig-bridge/Extension/FormExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\HttpFoundationExtension' => $vendorDir . '/symfony/twig-bridge/Extension/HttpFoundationExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\HttpKernelExtension' => $vendorDir . '/symfony/twig-bridge/Extension/HttpKernelExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\HttpKernelRuntime' => $vendorDir . '/symfony/twig-bridge/Extension/HttpKernelRuntime.php', - 'Symfony\\Bridge\\Twig\\Extension\\LogoutUrlExtension' => $vendorDir . '/symfony/twig-bridge/Extension/LogoutUrlExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension' => $vendorDir . '/symfony/twig-bridge/Extension/ProfilerExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\RoutingExtension' => $vendorDir . '/symfony/twig-bridge/Extension/RoutingExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\SecurityExtension' => $vendorDir . '/symfony/twig-bridge/Extension/SecurityExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\SerializerExtension' => $vendorDir . '/symfony/twig-bridge/Extension/SerializerExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\SerializerRuntime' => $vendorDir . '/symfony/twig-bridge/Extension/SerializerRuntime.php', - 'Symfony\\Bridge\\Twig\\Extension\\StopwatchExtension' => $vendorDir . '/symfony/twig-bridge/Extension/StopwatchExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\TranslationExtension' => $vendorDir . '/symfony/twig-bridge/Extension/TranslationExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\WebLinkExtension' => $vendorDir . '/symfony/twig-bridge/Extension/WebLinkExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\WorkflowExtension' => $vendorDir . '/symfony/twig-bridge/Extension/WorkflowExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\YamlExtension' => $vendorDir . '/symfony/twig-bridge/Extension/YamlExtension.php', - 'Symfony\\Bridge\\Twig\\Form\\TwigRendererEngine' => $vendorDir . '/symfony/twig-bridge/Form/TwigRendererEngine.php', - 'Symfony\\Bridge\\Twig\\Mime\\BodyRenderer' => $vendorDir . '/symfony/twig-bridge/Mime/BodyRenderer.php', - 'Symfony\\Bridge\\Twig\\Mime\\NotificationEmail' => $vendorDir . '/symfony/twig-bridge/Mime/NotificationEmail.php', - 'Symfony\\Bridge\\Twig\\Mime\\TemplatedEmail' => $vendorDir . '/symfony/twig-bridge/Mime/TemplatedEmail.php', - 'Symfony\\Bridge\\Twig\\Mime\\WrappedTemplatedEmail' => $vendorDir . '/symfony/twig-bridge/Mime/WrappedTemplatedEmail.php', - 'Symfony\\Bridge\\Twig\\NodeVisitor\\Scope' => $vendorDir . '/symfony/twig-bridge/NodeVisitor/Scope.php', - 'Symfony\\Bridge\\Twig\\NodeVisitor\\TranslationDefaultDomainNodeVisitor' => $vendorDir . '/symfony/twig-bridge/NodeVisitor/TranslationDefaultDomainNodeVisitor.php', - 'Symfony\\Bridge\\Twig\\NodeVisitor\\TranslationNodeVisitor' => $vendorDir . '/symfony/twig-bridge/NodeVisitor/TranslationNodeVisitor.php', - 'Symfony\\Bridge\\Twig\\Node\\DumpNode' => $vendorDir . '/symfony/twig-bridge/Node/DumpNode.php', - 'Symfony\\Bridge\\Twig\\Node\\FormThemeNode' => $vendorDir . '/symfony/twig-bridge/Node/FormThemeNode.php', - 'Symfony\\Bridge\\Twig\\Node\\RenderBlockNode' => $vendorDir . '/symfony/twig-bridge/Node/RenderBlockNode.php', - 'Symfony\\Bridge\\Twig\\Node\\SearchAndRenderBlockNode' => $vendorDir . '/symfony/twig-bridge/Node/SearchAndRenderBlockNode.php', - 'Symfony\\Bridge\\Twig\\Node\\StopwatchNode' => $vendorDir . '/symfony/twig-bridge/Node/StopwatchNode.php', - 'Symfony\\Bridge\\Twig\\Node\\TransDefaultDomainNode' => $vendorDir . '/symfony/twig-bridge/Node/TransDefaultDomainNode.php', - 'Symfony\\Bridge\\Twig\\Node\\TransNode' => $vendorDir . '/symfony/twig-bridge/Node/TransNode.php', - 'Symfony\\Bridge\\Twig\\TokenParser\\DumpTokenParser' => $vendorDir . '/symfony/twig-bridge/TokenParser/DumpTokenParser.php', - 'Symfony\\Bridge\\Twig\\TokenParser\\FormThemeTokenParser' => $vendorDir . '/symfony/twig-bridge/TokenParser/FormThemeTokenParser.php', - 'Symfony\\Bridge\\Twig\\TokenParser\\StopwatchTokenParser' => $vendorDir . '/symfony/twig-bridge/TokenParser/StopwatchTokenParser.php', - 'Symfony\\Bridge\\Twig\\TokenParser\\TransDefaultDomainTokenParser' => $vendorDir . '/symfony/twig-bridge/TokenParser/TransDefaultDomainTokenParser.php', - 'Symfony\\Bridge\\Twig\\TokenParser\\TransTokenParser' => $vendorDir . '/symfony/twig-bridge/TokenParser/TransTokenParser.php', - 'Symfony\\Bridge\\Twig\\Translation\\TwigExtractor' => $vendorDir . '/symfony/twig-bridge/Translation/TwigExtractor.php', - 'Symfony\\Bridge\\Twig\\UndefinedCallableHandler' => $vendorDir . '/symfony/twig-bridge/UndefinedCallableHandler.php', - 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\AbstractPhpFileCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/AbstractPhpFileCacheWarmer.php', - 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\AnnotationsCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/AnnotationsCacheWarmer.php', - 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\CachePoolClearerCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/CachePoolClearerCacheWarmer.php', - 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\ConfigBuilderCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/ConfigBuilderCacheWarmer.php', - 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\RouterCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/RouterCacheWarmer.php', - 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\SerializerCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/SerializerCacheWarmer.php', - 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\TranslationsCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/TranslationsCacheWarmer.php', - 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\ValidatorCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/ValidatorCacheWarmer.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\AboutCommand' => $vendorDir . '/symfony/framework-bundle/Command/AboutCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\AbstractConfigCommand' => $vendorDir . '/symfony/framework-bundle/Command/AbstractConfigCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\AssetsInstallCommand' => $vendorDir . '/symfony/framework-bundle/Command/AssetsInstallCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\BuildDebugContainerTrait' => $vendorDir . '/symfony/framework-bundle/Command/BuildDebugContainerTrait.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\CacheClearCommand' => $vendorDir . '/symfony/framework-bundle/Command/CacheClearCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolClearCommand' => $vendorDir . '/symfony/framework-bundle/Command/CachePoolClearCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolDeleteCommand' => $vendorDir . '/symfony/framework-bundle/Command/CachePoolDeleteCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolListCommand' => $vendorDir . '/symfony/framework-bundle/Command/CachePoolListCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolPruneCommand' => $vendorDir . '/symfony/framework-bundle/Command/CachePoolPruneCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\CacheWarmupCommand' => $vendorDir . '/symfony/framework-bundle/Command/CacheWarmupCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\ConfigDebugCommand' => $vendorDir . '/symfony/framework-bundle/Command/ConfigDebugCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\ConfigDumpReferenceCommand' => $vendorDir . '/symfony/framework-bundle/Command/ConfigDumpReferenceCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\ContainerDebugCommand' => $vendorDir . '/symfony/framework-bundle/Command/ContainerDebugCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\ContainerLintCommand' => $vendorDir . '/symfony/framework-bundle/Command/ContainerLintCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\DebugAutowiringCommand' => $vendorDir . '/symfony/framework-bundle/Command/DebugAutowiringCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\EventDispatcherDebugCommand' => $vendorDir . '/symfony/framework-bundle/Command/EventDispatcherDebugCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\RouterDebugCommand' => $vendorDir . '/symfony/framework-bundle/Command/RouterDebugCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\RouterMatchCommand' => $vendorDir . '/symfony/framework-bundle/Command/RouterMatchCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsDecryptToLocalCommand' => $vendorDir . '/symfony/framework-bundle/Command/SecretsDecryptToLocalCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsEncryptFromLocalCommand' => $vendorDir . '/symfony/framework-bundle/Command/SecretsEncryptFromLocalCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsGenerateKeysCommand' => $vendorDir . '/symfony/framework-bundle/Command/SecretsGenerateKeysCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsListCommand' => $vendorDir . '/symfony/framework-bundle/Command/SecretsListCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsRemoveCommand' => $vendorDir . '/symfony/framework-bundle/Command/SecretsRemoveCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsSetCommand' => $vendorDir . '/symfony/framework-bundle/Command/SecretsSetCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\TranslationDebugCommand' => $vendorDir . '/symfony/framework-bundle/Command/TranslationDebugCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\TranslationUpdateCommand' => $vendorDir . '/symfony/framework-bundle/Command/TranslationUpdateCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\WorkflowDumpCommand' => $vendorDir . '/symfony/framework-bundle/Command/WorkflowDumpCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\XliffLintCommand' => $vendorDir . '/symfony/framework-bundle/Command/XliffLintCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\YamlLintCommand' => $vendorDir . '/symfony/framework-bundle/Command/YamlLintCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Console\\Application' => $vendorDir . '/symfony/framework-bundle/Console/Application.php', - 'Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\Descriptor' => $vendorDir . '/symfony/framework-bundle/Console/Descriptor/Descriptor.php', - 'Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\JsonDescriptor' => $vendorDir . '/symfony/framework-bundle/Console/Descriptor/JsonDescriptor.php', - 'Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\MarkdownDescriptor' => $vendorDir . '/symfony/framework-bundle/Console/Descriptor/MarkdownDescriptor.php', - 'Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\TextDescriptor' => $vendorDir . '/symfony/framework-bundle/Console/Descriptor/TextDescriptor.php', - 'Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\XmlDescriptor' => $vendorDir . '/symfony/framework-bundle/Console/Descriptor/XmlDescriptor.php', - 'Symfony\\Bundle\\FrameworkBundle\\Console\\Helper\\DescriptorHelper' => $vendorDir . '/symfony/framework-bundle/Console/Helper/DescriptorHelper.php', - 'Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController' => $vendorDir . '/symfony/framework-bundle/Controller/AbstractController.php', - 'Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerResolver' => $vendorDir . '/symfony/framework-bundle/Controller/ControllerResolver.php', - 'Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController' => $vendorDir . '/symfony/framework-bundle/Controller/RedirectController.php', - 'Symfony\\Bundle\\FrameworkBundle\\Controller\\TemplateController' => $vendorDir . '/symfony/framework-bundle/Controller/TemplateController.php', - 'Symfony\\Bundle\\FrameworkBundle\\DataCollector\\AbstractDataCollector' => $vendorDir . '/symfony/framework-bundle/DataCollector/AbstractDataCollector.php', - 'Symfony\\Bundle\\FrameworkBundle\\DataCollector\\RouterDataCollector' => $vendorDir . '/symfony/framework-bundle/DataCollector/RouterDataCollector.php', - 'Symfony\\Bundle\\FrameworkBundle\\DataCollector\\TemplateAwareDataCollectorInterface' => $vendorDir . '/symfony/framework-bundle/DataCollector/TemplateAwareDataCollectorInterface.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\AddAnnotationsCachedReaderPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\AddDebugLogProcessorPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/AddDebugLogProcessorPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\AddExpressionLanguageProvidersPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\AssetsContextPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/AssetsContextPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\ContainerBuilderDebugDumpPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\DataCollectorTranslatorPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\LoggingTranslatorPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/LoggingTranslatorPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\ProfilerPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/ProfilerPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\RemoveUnusedSessionMarshallingHandlerPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/RemoveUnusedSessionMarshallingHandlerPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\SessionPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/SessionPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\TestServiceContainerRealRefPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\TestServiceContainerWeakRefPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\UnusedTagsPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/UnusedTagsPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\WorkflowGuardListenerPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Configuration' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Configuration.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\FrameworkExtension' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php', - 'Symfony\\Bundle\\FrameworkBundle\\EventListener\\SuggestMissingPackageSubscriber' => $vendorDir . '/symfony/framework-bundle/EventListener/SuggestMissingPackageSubscriber.php', - 'Symfony\\Bundle\\FrameworkBundle\\FrameworkBundle' => $vendorDir . '/symfony/framework-bundle/FrameworkBundle.php', - 'Symfony\\Bundle\\FrameworkBundle\\HttpCache\\HttpCache' => $vendorDir . '/symfony/framework-bundle/HttpCache/HttpCache.php', - 'Symfony\\Bundle\\FrameworkBundle\\KernelBrowser' => $vendorDir . '/symfony/framework-bundle/KernelBrowser.php', - 'Symfony\\Bundle\\FrameworkBundle\\Kernel\\MicroKernelTrait' => $vendorDir . '/symfony/framework-bundle/Kernel/MicroKernelTrait.php', - 'Symfony\\Bundle\\FrameworkBundle\\Routing\\AnnotatedRouteControllerLoader' => $vendorDir . '/symfony/framework-bundle/Routing/AnnotatedRouteControllerLoader.php', - 'Symfony\\Bundle\\FrameworkBundle\\Routing\\DelegatingLoader' => $vendorDir . '/symfony/framework-bundle/Routing/DelegatingLoader.php', - 'Symfony\\Bundle\\FrameworkBundle\\Routing\\RedirectableCompiledUrlMatcher' => $vendorDir . '/symfony/framework-bundle/Routing/RedirectableCompiledUrlMatcher.php', - 'Symfony\\Bundle\\FrameworkBundle\\Routing\\RouteLoaderInterface' => $vendorDir . '/symfony/framework-bundle/Routing/RouteLoaderInterface.php', - 'Symfony\\Bundle\\FrameworkBundle\\Routing\\Router' => $vendorDir . '/symfony/framework-bundle/Routing/Router.php', - 'Symfony\\Bundle\\FrameworkBundle\\Secrets\\AbstractVault' => $vendorDir . '/symfony/framework-bundle/Secrets/AbstractVault.php', - 'Symfony\\Bundle\\FrameworkBundle\\Secrets\\DotenvVault' => $vendorDir . '/symfony/framework-bundle/Secrets/DotenvVault.php', - 'Symfony\\Bundle\\FrameworkBundle\\Secrets\\SodiumVault' => $vendorDir . '/symfony/framework-bundle/Secrets/SodiumVault.php', - 'Symfony\\Bundle\\FrameworkBundle\\Session\\DeprecatedSessionFactory' => $vendorDir . '/symfony/framework-bundle/Session/DeprecatedSessionFactory.php', - 'Symfony\\Bundle\\FrameworkBundle\\Session\\ServiceSessionFactory' => $vendorDir . '/symfony/framework-bundle/Session/ServiceSessionFactory.php', - 'Symfony\\Bundle\\FrameworkBundle\\Translation\\Translator' => $vendorDir . '/symfony/framework-bundle/Translation/Translator.php', - 'Symfony\\Bundle\\TwigBundle\\CacheWarmer\\TemplateCacheWarmer' => $vendorDir . '/symfony/twig-bundle/CacheWarmer/TemplateCacheWarmer.php', - 'Symfony\\Bundle\\TwigBundle\\Command\\LintCommand' => $vendorDir . '/symfony/twig-bundle/Command/LintCommand.php', - 'Symfony\\Bundle\\TwigBundle\\DependencyInjection\\Compiler\\ExtensionPass' => $vendorDir . '/symfony/twig-bundle/DependencyInjection/Compiler/ExtensionPass.php', - 'Symfony\\Bundle\\TwigBundle\\DependencyInjection\\Compiler\\RuntimeLoaderPass' => $vendorDir . '/symfony/twig-bundle/DependencyInjection/Compiler/RuntimeLoaderPass.php', - 'Symfony\\Bundle\\TwigBundle\\DependencyInjection\\Compiler\\TwigEnvironmentPass' => $vendorDir . '/symfony/twig-bundle/DependencyInjection/Compiler/TwigEnvironmentPass.php', - 'Symfony\\Bundle\\TwigBundle\\DependencyInjection\\Compiler\\TwigLoaderPass' => $vendorDir . '/symfony/twig-bundle/DependencyInjection/Compiler/TwigLoaderPass.php', - 'Symfony\\Bundle\\TwigBundle\\DependencyInjection\\Configuration' => $vendorDir . '/symfony/twig-bundle/DependencyInjection/Configuration.php', - 'Symfony\\Bundle\\TwigBundle\\DependencyInjection\\Configurator\\EnvironmentConfigurator' => $vendorDir . '/symfony/twig-bundle/DependencyInjection/Configurator/EnvironmentConfigurator.php', - 'Symfony\\Bundle\\TwigBundle\\DependencyInjection\\TwigExtension' => $vendorDir . '/symfony/twig-bundle/DependencyInjection/TwigExtension.php', - 'Symfony\\Bundle\\TwigBundle\\TemplateIterator' => $vendorDir . '/symfony/twig-bundle/TemplateIterator.php', - 'Symfony\\Bundle\\TwigBundle\\TwigBundle' => $vendorDir . '/symfony/twig-bundle/TwigBundle.php', - 'Symfony\\Bundle\\WebProfilerBundle\\Controller\\ExceptionPanelController' => $vendorDir . '/symfony/web-profiler-bundle/Controller/ExceptionPanelController.php', - 'Symfony\\Bundle\\WebProfilerBundle\\Controller\\ProfilerController' => $vendorDir . '/symfony/web-profiler-bundle/Controller/ProfilerController.php', - 'Symfony\\Bundle\\WebProfilerBundle\\Controller\\RouterController' => $vendorDir . '/symfony/web-profiler-bundle/Controller/RouterController.php', - 'Symfony\\Bundle\\WebProfilerBundle\\Csp\\ContentSecurityPolicyHandler' => $vendorDir . '/symfony/web-profiler-bundle/Csp/ContentSecurityPolicyHandler.php', - 'Symfony\\Bundle\\WebProfilerBundle\\Csp\\NonceGenerator' => $vendorDir . '/symfony/web-profiler-bundle/Csp/NonceGenerator.php', - 'Symfony\\Bundle\\WebProfilerBundle\\DependencyInjection\\Configuration' => $vendorDir . '/symfony/web-profiler-bundle/DependencyInjection/Configuration.php', - 'Symfony\\Bundle\\WebProfilerBundle\\DependencyInjection\\WebProfilerExtension' => $vendorDir . '/symfony/web-profiler-bundle/DependencyInjection/WebProfilerExtension.php', - 'Symfony\\Bundle\\WebProfilerBundle\\EventListener\\WebDebugToolbarListener' => $vendorDir . '/symfony/web-profiler-bundle/EventListener/WebDebugToolbarListener.php', - 'Symfony\\Bundle\\WebProfilerBundle\\Profiler\\TemplateManager' => $vendorDir . '/symfony/web-profiler-bundle/Profiler/TemplateManager.php', - 'Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension' => $vendorDir . '/symfony/web-profiler-bundle/Twig/WebProfilerExtension.php', - 'Symfony\\Bundle\\WebProfilerBundle\\WebProfilerBundle' => $vendorDir . '/symfony/web-profiler-bundle/WebProfilerBundle.php', - 'Symfony\\Component\\Cache\\Adapter\\AbstractAdapter' => $vendorDir . '/symfony/cache/Adapter/AbstractAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\AbstractTagAwareAdapter' => $vendorDir . '/symfony/cache/Adapter/AbstractTagAwareAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\AdapterInterface' => $vendorDir . '/symfony/cache/Adapter/AdapterInterface.php', - 'Symfony\\Component\\Cache\\Adapter\\ApcuAdapter' => $vendorDir . '/symfony/cache/Adapter/ApcuAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\ArrayAdapter' => $vendorDir . '/symfony/cache/Adapter/ArrayAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\ChainAdapter' => $vendorDir . '/symfony/cache/Adapter/ChainAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\CouchbaseBucketAdapter' => $vendorDir . '/symfony/cache/Adapter/CouchbaseBucketAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\CouchbaseCollectionAdapter' => $vendorDir . '/symfony/cache/Adapter/CouchbaseCollectionAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\DoctrineAdapter' => $vendorDir . '/symfony/cache/Adapter/DoctrineAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\DoctrineDbalAdapter' => $vendorDir . '/symfony/cache/Adapter/DoctrineDbalAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\FilesystemAdapter' => $vendorDir . '/symfony/cache/Adapter/FilesystemAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\FilesystemTagAwareAdapter' => $vendorDir . '/symfony/cache/Adapter/FilesystemTagAwareAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\MemcachedAdapter' => $vendorDir . '/symfony/cache/Adapter/MemcachedAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\NullAdapter' => $vendorDir . '/symfony/cache/Adapter/NullAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\ParameterNormalizer' => $vendorDir . '/symfony/cache/Adapter/ParameterNormalizer.php', - 'Symfony\\Component\\Cache\\Adapter\\PdoAdapter' => $vendorDir . '/symfony/cache/Adapter/PdoAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\PhpArrayAdapter' => $vendorDir . '/symfony/cache/Adapter/PhpArrayAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\PhpFilesAdapter' => $vendorDir . '/symfony/cache/Adapter/PhpFilesAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\ProxyAdapter' => $vendorDir . '/symfony/cache/Adapter/ProxyAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\Psr16Adapter' => $vendorDir . '/symfony/cache/Adapter/Psr16Adapter.php', - 'Symfony\\Component\\Cache\\Adapter\\RedisAdapter' => $vendorDir . '/symfony/cache/Adapter/RedisAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\RedisTagAwareAdapter' => $vendorDir . '/symfony/cache/Adapter/RedisTagAwareAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\TagAwareAdapter' => $vendorDir . '/symfony/cache/Adapter/TagAwareAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\TagAwareAdapterInterface' => $vendorDir . '/symfony/cache/Adapter/TagAwareAdapterInterface.php', - 'Symfony\\Component\\Cache\\Adapter\\TraceableAdapter' => $vendorDir . '/symfony/cache/Adapter/TraceableAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\TraceableTagAwareAdapter' => $vendorDir . '/symfony/cache/Adapter/TraceableTagAwareAdapter.php', - 'Symfony\\Component\\Cache\\CacheItem' => $vendorDir . '/symfony/cache/CacheItem.php', - 'Symfony\\Component\\Cache\\DataCollector\\CacheDataCollector' => $vendorDir . '/symfony/cache/DataCollector/CacheDataCollector.php', - 'Symfony\\Component\\Cache\\DependencyInjection\\CacheCollectorPass' => $vendorDir . '/symfony/cache/DependencyInjection/CacheCollectorPass.php', - 'Symfony\\Component\\Cache\\DependencyInjection\\CachePoolClearerPass' => $vendorDir . '/symfony/cache/DependencyInjection/CachePoolClearerPass.php', - 'Symfony\\Component\\Cache\\DependencyInjection\\CachePoolPass' => $vendorDir . '/symfony/cache/DependencyInjection/CachePoolPass.php', - 'Symfony\\Component\\Cache\\DependencyInjection\\CachePoolPrunerPass' => $vendorDir . '/symfony/cache/DependencyInjection/CachePoolPrunerPass.php', - 'Symfony\\Component\\Cache\\DoctrineProvider' => $vendorDir . '/symfony/cache/DoctrineProvider.php', - 'Symfony\\Component\\Cache\\Exception\\CacheException' => $vendorDir . '/symfony/cache/Exception/CacheException.php', - 'Symfony\\Component\\Cache\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/cache/Exception/InvalidArgumentException.php', - 'Symfony\\Component\\Cache\\Exception\\LogicException' => $vendorDir . '/symfony/cache/Exception/LogicException.php', - 'Symfony\\Component\\Cache\\LockRegistry' => $vendorDir . '/symfony/cache/LockRegistry.php', - 'Symfony\\Component\\Cache\\Marshaller\\DefaultMarshaller' => $vendorDir . '/symfony/cache/Marshaller/DefaultMarshaller.php', - 'Symfony\\Component\\Cache\\Marshaller\\DeflateMarshaller' => $vendorDir . '/symfony/cache/Marshaller/DeflateMarshaller.php', - 'Symfony\\Component\\Cache\\Marshaller\\MarshallerInterface' => $vendorDir . '/symfony/cache/Marshaller/MarshallerInterface.php', - 'Symfony\\Component\\Cache\\Marshaller\\SodiumMarshaller' => $vendorDir . '/symfony/cache/Marshaller/SodiumMarshaller.php', - 'Symfony\\Component\\Cache\\Marshaller\\TagAwareMarshaller' => $vendorDir . '/symfony/cache/Marshaller/TagAwareMarshaller.php', - 'Symfony\\Component\\Cache\\Messenger\\EarlyExpirationDispatcher' => $vendorDir . '/symfony/cache/Messenger/EarlyExpirationDispatcher.php', - 'Symfony\\Component\\Cache\\Messenger\\EarlyExpirationHandler' => $vendorDir . '/symfony/cache/Messenger/EarlyExpirationHandler.php', - 'Symfony\\Component\\Cache\\Messenger\\EarlyExpirationMessage' => $vendorDir . '/symfony/cache/Messenger/EarlyExpirationMessage.php', - 'Symfony\\Component\\Cache\\PruneableInterface' => $vendorDir . '/symfony/cache/PruneableInterface.php', - 'Symfony\\Component\\Cache\\Psr16Cache' => $vendorDir . '/symfony/cache/Psr16Cache.php', - 'Symfony\\Component\\Cache\\ResettableInterface' => $vendorDir . '/symfony/cache/ResettableInterface.php', - 'Symfony\\Component\\Cache\\Traits\\AbstractAdapterTrait' => $vendorDir . '/symfony/cache/Traits/AbstractAdapterTrait.php', - 'Symfony\\Component\\Cache\\Traits\\ContractsTrait' => $vendorDir . '/symfony/cache/Traits/ContractsTrait.php', - 'Symfony\\Component\\Cache\\Traits\\FilesystemCommonTrait' => $vendorDir . '/symfony/cache/Traits/FilesystemCommonTrait.php', - 'Symfony\\Component\\Cache\\Traits\\FilesystemTrait' => $vendorDir . '/symfony/cache/Traits/FilesystemTrait.php', - 'Symfony\\Component\\Cache\\Traits\\ProxyTrait' => $vendorDir . '/symfony/cache/Traits/ProxyTrait.php', - 'Symfony\\Component\\Cache\\Traits\\RedisClusterNodeProxy' => $vendorDir . '/symfony/cache/Traits/RedisClusterNodeProxy.php', - 'Symfony\\Component\\Cache\\Traits\\RedisClusterProxy' => $vendorDir . '/symfony/cache/Traits/RedisClusterProxy.php', - 'Symfony\\Component\\Cache\\Traits\\RedisProxy' => $vendorDir . '/symfony/cache/Traits/RedisProxy.php', - 'Symfony\\Component\\Cache\\Traits\\RedisTrait' => $vendorDir . '/symfony/cache/Traits/RedisTrait.php', - 'Symfony\\Component\\Config\\Builder\\ClassBuilder' => $vendorDir . '/symfony/config/Builder/ClassBuilder.php', - 'Symfony\\Component\\Config\\Builder\\ConfigBuilderGenerator' => $vendorDir . '/symfony/config/Builder/ConfigBuilderGenerator.php', - 'Symfony\\Component\\Config\\Builder\\ConfigBuilderGeneratorInterface' => $vendorDir . '/symfony/config/Builder/ConfigBuilderGeneratorInterface.php', - 'Symfony\\Component\\Config\\Builder\\ConfigBuilderInterface' => $vendorDir . '/symfony/config/Builder/ConfigBuilderInterface.php', - 'Symfony\\Component\\Config\\Builder\\Method' => $vendorDir . '/symfony/config/Builder/Method.php', - 'Symfony\\Component\\Config\\Builder\\Property' => $vendorDir . '/symfony/config/Builder/Property.php', - 'Symfony\\Component\\Config\\ConfigCache' => $vendorDir . '/symfony/config/ConfigCache.php', - 'Symfony\\Component\\Config\\ConfigCacheFactory' => $vendorDir . '/symfony/config/ConfigCacheFactory.php', - 'Symfony\\Component\\Config\\ConfigCacheFactoryInterface' => $vendorDir . '/symfony/config/ConfigCacheFactoryInterface.php', - 'Symfony\\Component\\Config\\ConfigCacheInterface' => $vendorDir . '/symfony/config/ConfigCacheInterface.php', - 'Symfony\\Component\\Config\\Definition\\ArrayNode' => $vendorDir . '/symfony/config/Definition/ArrayNode.php', - 'Symfony\\Component\\Config\\Definition\\BaseNode' => $vendorDir . '/symfony/config/Definition/BaseNode.php', - 'Symfony\\Component\\Config\\Definition\\BooleanNode' => $vendorDir . '/symfony/config/Definition/BooleanNode.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\ArrayNodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/ArrayNodeDefinition.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\BooleanNodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/BooleanNodeDefinition.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\BuilderAwareInterface' => $vendorDir . '/symfony/config/Definition/Builder/BuilderAwareInterface.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\EnumNodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/EnumNodeDefinition.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\ExprBuilder' => $vendorDir . '/symfony/config/Definition/Builder/ExprBuilder.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\FloatNodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/FloatNodeDefinition.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\IntegerNodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/IntegerNodeDefinition.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\MergeBuilder' => $vendorDir . '/symfony/config/Definition/Builder/MergeBuilder.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\NodeBuilder' => $vendorDir . '/symfony/config/Definition/Builder/NodeBuilder.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\NodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/NodeDefinition.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\NodeParentInterface' => $vendorDir . '/symfony/config/Definition/Builder/NodeParentInterface.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\NormalizationBuilder' => $vendorDir . '/symfony/config/Definition/Builder/NormalizationBuilder.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\NumericNodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/NumericNodeDefinition.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\ParentNodeDefinitionInterface' => $vendorDir . '/symfony/config/Definition/Builder/ParentNodeDefinitionInterface.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\ScalarNodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/ScalarNodeDefinition.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\TreeBuilder' => $vendorDir . '/symfony/config/Definition/Builder/TreeBuilder.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\ValidationBuilder' => $vendorDir . '/symfony/config/Definition/Builder/ValidationBuilder.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\VariableNodeDefinition' => $vendorDir . '/symfony/config/Definition/Builder/VariableNodeDefinition.php', - 'Symfony\\Component\\Config\\Definition\\ConfigurationInterface' => $vendorDir . '/symfony/config/Definition/ConfigurationInterface.php', - 'Symfony\\Component\\Config\\Definition\\Dumper\\XmlReferenceDumper' => $vendorDir . '/symfony/config/Definition/Dumper/XmlReferenceDumper.php', - 'Symfony\\Component\\Config\\Definition\\Dumper\\YamlReferenceDumper' => $vendorDir . '/symfony/config/Definition/Dumper/YamlReferenceDumper.php', - 'Symfony\\Component\\Config\\Definition\\EnumNode' => $vendorDir . '/symfony/config/Definition/EnumNode.php', - 'Symfony\\Component\\Config\\Definition\\Exception\\DuplicateKeyException' => $vendorDir . '/symfony/config/Definition/Exception/DuplicateKeyException.php', - 'Symfony\\Component\\Config\\Definition\\Exception\\Exception' => $vendorDir . '/symfony/config/Definition/Exception/Exception.php', - 'Symfony\\Component\\Config\\Definition\\Exception\\ForbiddenOverwriteException' => $vendorDir . '/symfony/config/Definition/Exception/ForbiddenOverwriteException.php', - 'Symfony\\Component\\Config\\Definition\\Exception\\InvalidConfigurationException' => $vendorDir . '/symfony/config/Definition/Exception/InvalidConfigurationException.php', - 'Symfony\\Component\\Config\\Definition\\Exception\\InvalidDefinitionException' => $vendorDir . '/symfony/config/Definition/Exception/InvalidDefinitionException.php', - 'Symfony\\Component\\Config\\Definition\\Exception\\InvalidTypeException' => $vendorDir . '/symfony/config/Definition/Exception/InvalidTypeException.php', - 'Symfony\\Component\\Config\\Definition\\Exception\\UnsetKeyException' => $vendorDir . '/symfony/config/Definition/Exception/UnsetKeyException.php', - 'Symfony\\Component\\Config\\Definition\\FloatNode' => $vendorDir . '/symfony/config/Definition/FloatNode.php', - 'Symfony\\Component\\Config\\Definition\\IntegerNode' => $vendorDir . '/symfony/config/Definition/IntegerNode.php', - 'Symfony\\Component\\Config\\Definition\\NodeInterface' => $vendorDir . '/symfony/config/Definition/NodeInterface.php', - 'Symfony\\Component\\Config\\Definition\\NumericNode' => $vendorDir . '/symfony/config/Definition/NumericNode.php', - 'Symfony\\Component\\Config\\Definition\\Processor' => $vendorDir . '/symfony/config/Definition/Processor.php', - 'Symfony\\Component\\Config\\Definition\\PrototypeNodeInterface' => $vendorDir . '/symfony/config/Definition/PrototypeNodeInterface.php', - 'Symfony\\Component\\Config\\Definition\\PrototypedArrayNode' => $vendorDir . '/symfony/config/Definition/PrototypedArrayNode.php', - 'Symfony\\Component\\Config\\Definition\\ScalarNode' => $vendorDir . '/symfony/config/Definition/ScalarNode.php', - 'Symfony\\Component\\Config\\Definition\\VariableNode' => $vendorDir . '/symfony/config/Definition/VariableNode.php', - 'Symfony\\Component\\Config\\Exception\\FileLoaderImportCircularReferenceException' => $vendorDir . '/symfony/config/Exception/FileLoaderImportCircularReferenceException.php', - 'Symfony\\Component\\Config\\Exception\\FileLocatorFileNotFoundException' => $vendorDir . '/symfony/config/Exception/FileLocatorFileNotFoundException.php', - 'Symfony\\Component\\Config\\Exception\\LoaderLoadException' => $vendorDir . '/symfony/config/Exception/LoaderLoadException.php', - 'Symfony\\Component\\Config\\FileLocator' => $vendorDir . '/symfony/config/FileLocator.php', - 'Symfony\\Component\\Config\\FileLocatorInterface' => $vendorDir . '/symfony/config/FileLocatorInterface.php', - 'Symfony\\Component\\Config\\Loader\\DelegatingLoader' => $vendorDir . '/symfony/config/Loader/DelegatingLoader.php', - 'Symfony\\Component\\Config\\Loader\\FileLoader' => $vendorDir . '/symfony/config/Loader/FileLoader.php', - 'Symfony\\Component\\Config\\Loader\\GlobFileLoader' => $vendorDir . '/symfony/config/Loader/GlobFileLoader.php', - 'Symfony\\Component\\Config\\Loader\\Loader' => $vendorDir . '/symfony/config/Loader/Loader.php', - 'Symfony\\Component\\Config\\Loader\\LoaderInterface' => $vendorDir . '/symfony/config/Loader/LoaderInterface.php', - 'Symfony\\Component\\Config\\Loader\\LoaderResolver' => $vendorDir . '/symfony/config/Loader/LoaderResolver.php', - 'Symfony\\Component\\Config\\Loader\\LoaderResolverInterface' => $vendorDir . '/symfony/config/Loader/LoaderResolverInterface.php', - 'Symfony\\Component\\Config\\Loader\\ParamConfigurator' => $vendorDir . '/symfony/config/Loader/ParamConfigurator.php', - 'Symfony\\Component\\Config\\ResourceCheckerConfigCache' => $vendorDir . '/symfony/config/ResourceCheckerConfigCache.php', - 'Symfony\\Component\\Config\\ResourceCheckerConfigCacheFactory' => $vendorDir . '/symfony/config/ResourceCheckerConfigCacheFactory.php', - 'Symfony\\Component\\Config\\ResourceCheckerInterface' => $vendorDir . '/symfony/config/ResourceCheckerInterface.php', - 'Symfony\\Component\\Config\\Resource\\ClassExistenceResource' => $vendorDir . '/symfony/config/Resource/ClassExistenceResource.php', - 'Symfony\\Component\\Config\\Resource\\ComposerResource' => $vendorDir . '/symfony/config/Resource/ComposerResource.php', - 'Symfony\\Component\\Config\\Resource\\DirectoryResource' => $vendorDir . '/symfony/config/Resource/DirectoryResource.php', - 'Symfony\\Component\\Config\\Resource\\FileExistenceResource' => $vendorDir . '/symfony/config/Resource/FileExistenceResource.php', - 'Symfony\\Component\\Config\\Resource\\FileResource' => $vendorDir . '/symfony/config/Resource/FileResource.php', - 'Symfony\\Component\\Config\\Resource\\GlobResource' => $vendorDir . '/symfony/config/Resource/GlobResource.php', - 'Symfony\\Component\\Config\\Resource\\ReflectionClassResource' => $vendorDir . '/symfony/config/Resource/ReflectionClassResource.php', - 'Symfony\\Component\\Config\\Resource\\ResourceInterface' => $vendorDir . '/symfony/config/Resource/ResourceInterface.php', - 'Symfony\\Component\\Config\\Resource\\SelfCheckingResourceChecker' => $vendorDir . '/symfony/config/Resource/SelfCheckingResourceChecker.php', - 'Symfony\\Component\\Config\\Resource\\SelfCheckingResourceInterface' => $vendorDir . '/symfony/config/Resource/SelfCheckingResourceInterface.php', - 'Symfony\\Component\\Config\\Util\\Exception\\InvalidXmlException' => $vendorDir . '/symfony/config/Util/Exception/InvalidXmlException.php', - 'Symfony\\Component\\Config\\Util\\Exception\\XmlParsingException' => $vendorDir . '/symfony/config/Util/Exception/XmlParsingException.php', - 'Symfony\\Component\\Config\\Util\\XmlUtils' => $vendorDir . '/symfony/config/Util/XmlUtils.php', - 'Symfony\\Component\\Console\\Application' => $vendorDir . '/symfony/console/Application.php', - 'Symfony\\Component\\Console\\Attribute\\AsCommand' => $vendorDir . '/symfony/console/Attribute/AsCommand.php', - 'Symfony\\Component\\Console\\CI\\GithubActionReporter' => $vendorDir . '/symfony/console/CI/GithubActionReporter.php', - 'Symfony\\Component\\Console\\Color' => $vendorDir . '/symfony/console/Color.php', - 'Symfony\\Component\\Console\\CommandLoader\\CommandLoaderInterface' => $vendorDir . '/symfony/console/CommandLoader/CommandLoaderInterface.php', - 'Symfony\\Component\\Console\\CommandLoader\\ContainerCommandLoader' => $vendorDir . '/symfony/console/CommandLoader/ContainerCommandLoader.php', - 'Symfony\\Component\\Console\\CommandLoader\\FactoryCommandLoader' => $vendorDir . '/symfony/console/CommandLoader/FactoryCommandLoader.php', - 'Symfony\\Component\\Console\\Command\\Command' => $vendorDir . '/symfony/console/Command/Command.php', - 'Symfony\\Component\\Console\\Command\\CompleteCommand' => $vendorDir . '/symfony/console/Command/CompleteCommand.php', - 'Symfony\\Component\\Console\\Command\\DumpCompletionCommand' => $vendorDir . '/symfony/console/Command/DumpCompletionCommand.php', - 'Symfony\\Component\\Console\\Command\\HelpCommand' => $vendorDir . '/symfony/console/Command/HelpCommand.php', - 'Symfony\\Component\\Console\\Command\\LazyCommand' => $vendorDir . '/symfony/console/Command/LazyCommand.php', - 'Symfony\\Component\\Console\\Command\\ListCommand' => $vendorDir . '/symfony/console/Command/ListCommand.php', - 'Symfony\\Component\\Console\\Command\\LockableTrait' => $vendorDir . '/symfony/console/Command/LockableTrait.php', - 'Symfony\\Component\\Console\\Command\\SignalableCommandInterface' => $vendorDir . '/symfony/console/Command/SignalableCommandInterface.php', - 'Symfony\\Component\\Console\\Completion\\CompletionInput' => $vendorDir . '/symfony/console/Completion/CompletionInput.php', - 'Symfony\\Component\\Console\\Completion\\CompletionSuggestions' => $vendorDir . '/symfony/console/Completion/CompletionSuggestions.php', - 'Symfony\\Component\\Console\\Completion\\Output\\BashCompletionOutput' => $vendorDir . '/symfony/console/Completion/Output/BashCompletionOutput.php', - 'Symfony\\Component\\Console\\Completion\\Output\\CompletionOutputInterface' => $vendorDir . '/symfony/console/Completion/Output/CompletionOutputInterface.php', - 'Symfony\\Component\\Console\\Completion\\Suggestion' => $vendorDir . '/symfony/console/Completion/Suggestion.php', - 'Symfony\\Component\\Console\\ConsoleEvents' => $vendorDir . '/symfony/console/ConsoleEvents.php', - 'Symfony\\Component\\Console\\Cursor' => $vendorDir . '/symfony/console/Cursor.php', - 'Symfony\\Component\\Console\\DependencyInjection\\AddConsoleCommandPass' => $vendorDir . '/symfony/console/DependencyInjection/AddConsoleCommandPass.php', - 'Symfony\\Component\\Console\\Descriptor\\ApplicationDescription' => $vendorDir . '/symfony/console/Descriptor/ApplicationDescription.php', - 'Symfony\\Component\\Console\\Descriptor\\Descriptor' => $vendorDir . '/symfony/console/Descriptor/Descriptor.php', - 'Symfony\\Component\\Console\\Descriptor\\DescriptorInterface' => $vendorDir . '/symfony/console/Descriptor/DescriptorInterface.php', - 'Symfony\\Component\\Console\\Descriptor\\JsonDescriptor' => $vendorDir . '/symfony/console/Descriptor/JsonDescriptor.php', - 'Symfony\\Component\\Console\\Descriptor\\MarkdownDescriptor' => $vendorDir . '/symfony/console/Descriptor/MarkdownDescriptor.php', - 'Symfony\\Component\\Console\\Descriptor\\TextDescriptor' => $vendorDir . '/symfony/console/Descriptor/TextDescriptor.php', - 'Symfony\\Component\\Console\\Descriptor\\XmlDescriptor' => $vendorDir . '/symfony/console/Descriptor/XmlDescriptor.php', - 'Symfony\\Component\\Console\\EventListener\\ErrorListener' => $vendorDir . '/symfony/console/EventListener/ErrorListener.php', - 'Symfony\\Component\\Console\\Event\\ConsoleCommandEvent' => $vendorDir . '/symfony/console/Event/ConsoleCommandEvent.php', - 'Symfony\\Component\\Console\\Event\\ConsoleErrorEvent' => $vendorDir . '/symfony/console/Event/ConsoleErrorEvent.php', - 'Symfony\\Component\\Console\\Event\\ConsoleEvent' => $vendorDir . '/symfony/console/Event/ConsoleEvent.php', - 'Symfony\\Component\\Console\\Event\\ConsoleSignalEvent' => $vendorDir . '/symfony/console/Event/ConsoleSignalEvent.php', - 'Symfony\\Component\\Console\\Event\\ConsoleTerminateEvent' => $vendorDir . '/symfony/console/Event/ConsoleTerminateEvent.php', - 'Symfony\\Component\\Console\\Exception\\CommandNotFoundException' => $vendorDir . '/symfony/console/Exception/CommandNotFoundException.php', - 'Symfony\\Component\\Console\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/console/Exception/ExceptionInterface.php', - 'Symfony\\Component\\Console\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/console/Exception/InvalidArgumentException.php', - 'Symfony\\Component\\Console\\Exception\\InvalidOptionException' => $vendorDir . '/symfony/console/Exception/InvalidOptionException.php', - 'Symfony\\Component\\Console\\Exception\\LogicException' => $vendorDir . '/symfony/console/Exception/LogicException.php', - 'Symfony\\Component\\Console\\Exception\\MissingInputException' => $vendorDir . '/symfony/console/Exception/MissingInputException.php', - 'Symfony\\Component\\Console\\Exception\\NamespaceNotFoundException' => $vendorDir . '/symfony/console/Exception/NamespaceNotFoundException.php', - 'Symfony\\Component\\Console\\Exception\\RuntimeException' => $vendorDir . '/symfony/console/Exception/RuntimeException.php', - 'Symfony\\Component\\Console\\Formatter\\NullOutputFormatter' => $vendorDir . '/symfony/console/Formatter/NullOutputFormatter.php', - 'Symfony\\Component\\Console\\Formatter\\NullOutputFormatterStyle' => $vendorDir . '/symfony/console/Formatter/NullOutputFormatterStyle.php', - 'Symfony\\Component\\Console\\Formatter\\OutputFormatter' => $vendorDir . '/symfony/console/Formatter/OutputFormatter.php', - 'Symfony\\Component\\Console\\Formatter\\OutputFormatterInterface' => $vendorDir . '/symfony/console/Formatter/OutputFormatterInterface.php', - 'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyle' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyle.php', - 'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleInterface' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyleInterface.php', - 'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleStack' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyleStack.php', - 'Symfony\\Component\\Console\\Formatter\\WrappableOutputFormatterInterface' => $vendorDir . '/symfony/console/Formatter/WrappableOutputFormatterInterface.php', - 'Symfony\\Component\\Console\\Helper\\DebugFormatterHelper' => $vendorDir . '/symfony/console/Helper/DebugFormatterHelper.php', - 'Symfony\\Component\\Console\\Helper\\DescriptorHelper' => $vendorDir . '/symfony/console/Helper/DescriptorHelper.php', - 'Symfony\\Component\\Console\\Helper\\Dumper' => $vendorDir . '/symfony/console/Helper/Dumper.php', - 'Symfony\\Component\\Console\\Helper\\FormatterHelper' => $vendorDir . '/symfony/console/Helper/FormatterHelper.php', - 'Symfony\\Component\\Console\\Helper\\Helper' => $vendorDir . '/symfony/console/Helper/Helper.php', - 'Symfony\\Component\\Console\\Helper\\HelperInterface' => $vendorDir . '/symfony/console/Helper/HelperInterface.php', - 'Symfony\\Component\\Console\\Helper\\HelperSet' => $vendorDir . '/symfony/console/Helper/HelperSet.php', - 'Symfony\\Component\\Console\\Helper\\InputAwareHelper' => $vendorDir . '/symfony/console/Helper/InputAwareHelper.php', - 'Symfony\\Component\\Console\\Helper\\ProcessHelper' => $vendorDir . '/symfony/console/Helper/ProcessHelper.php', - 'Symfony\\Component\\Console\\Helper\\ProgressBar' => $vendorDir . '/symfony/console/Helper/ProgressBar.php', - 'Symfony\\Component\\Console\\Helper\\ProgressIndicator' => $vendorDir . '/symfony/console/Helper/ProgressIndicator.php', - 'Symfony\\Component\\Console\\Helper\\QuestionHelper' => $vendorDir . '/symfony/console/Helper/QuestionHelper.php', - 'Symfony\\Component\\Console\\Helper\\SymfonyQuestionHelper' => $vendorDir . '/symfony/console/Helper/SymfonyQuestionHelper.php', - 'Symfony\\Component\\Console\\Helper\\Table' => $vendorDir . '/symfony/console/Helper/Table.php', - 'Symfony\\Component\\Console\\Helper\\TableCell' => $vendorDir . '/symfony/console/Helper/TableCell.php', - 'Symfony\\Component\\Console\\Helper\\TableCellStyle' => $vendorDir . '/symfony/console/Helper/TableCellStyle.php', - 'Symfony\\Component\\Console\\Helper\\TableRows' => $vendorDir . '/symfony/console/Helper/TableRows.php', - 'Symfony\\Component\\Console\\Helper\\TableSeparator' => $vendorDir . '/symfony/console/Helper/TableSeparator.php', - 'Symfony\\Component\\Console\\Helper\\TableStyle' => $vendorDir . '/symfony/console/Helper/TableStyle.php', - 'Symfony\\Component\\Console\\Input\\ArgvInput' => $vendorDir . '/symfony/console/Input/ArgvInput.php', - 'Symfony\\Component\\Console\\Input\\ArrayInput' => $vendorDir . '/symfony/console/Input/ArrayInput.php', - 'Symfony\\Component\\Console\\Input\\Input' => $vendorDir . '/symfony/console/Input/Input.php', - 'Symfony\\Component\\Console\\Input\\InputArgument' => $vendorDir . '/symfony/console/Input/InputArgument.php', - 'Symfony\\Component\\Console\\Input\\InputAwareInterface' => $vendorDir . '/symfony/console/Input/InputAwareInterface.php', - 'Symfony\\Component\\Console\\Input\\InputDefinition' => $vendorDir . '/symfony/console/Input/InputDefinition.php', - 'Symfony\\Component\\Console\\Input\\InputInterface' => $vendorDir . '/symfony/console/Input/InputInterface.php', - 'Symfony\\Component\\Console\\Input\\InputOption' => $vendorDir . '/symfony/console/Input/InputOption.php', - 'Symfony\\Component\\Console\\Input\\StreamableInputInterface' => $vendorDir . '/symfony/console/Input/StreamableInputInterface.php', - 'Symfony\\Component\\Console\\Input\\StringInput' => $vendorDir . '/symfony/console/Input/StringInput.php', - 'Symfony\\Component\\Console\\Logger\\ConsoleLogger' => $vendorDir . '/symfony/console/Logger/ConsoleLogger.php', - 'Symfony\\Component\\Console\\Output\\BufferedOutput' => $vendorDir . '/symfony/console/Output/BufferedOutput.php', - 'Symfony\\Component\\Console\\Output\\ConsoleOutput' => $vendorDir . '/symfony/console/Output/ConsoleOutput.php', - 'Symfony\\Component\\Console\\Output\\ConsoleOutputInterface' => $vendorDir . '/symfony/console/Output/ConsoleOutputInterface.php', - 'Symfony\\Component\\Console\\Output\\ConsoleSectionOutput' => $vendorDir . '/symfony/console/Output/ConsoleSectionOutput.php', - 'Symfony\\Component\\Console\\Output\\NullOutput' => $vendorDir . '/symfony/console/Output/NullOutput.php', - 'Symfony\\Component\\Console\\Output\\Output' => $vendorDir . '/symfony/console/Output/Output.php', - 'Symfony\\Component\\Console\\Output\\OutputInterface' => $vendorDir . '/symfony/console/Output/OutputInterface.php', - 'Symfony\\Component\\Console\\Output\\StreamOutput' => $vendorDir . '/symfony/console/Output/StreamOutput.php', - 'Symfony\\Component\\Console\\Output\\TrimmedBufferOutput' => $vendorDir . '/symfony/console/Output/TrimmedBufferOutput.php', - 'Symfony\\Component\\Console\\Question\\ChoiceQuestion' => $vendorDir . '/symfony/console/Question/ChoiceQuestion.php', - 'Symfony\\Component\\Console\\Question\\ConfirmationQuestion' => $vendorDir . '/symfony/console/Question/ConfirmationQuestion.php', - 'Symfony\\Component\\Console\\Question\\Question' => $vendorDir . '/symfony/console/Question/Question.php', - 'Symfony\\Component\\Console\\SignalRegistry\\SignalRegistry' => $vendorDir . '/symfony/console/SignalRegistry/SignalRegistry.php', - 'Symfony\\Component\\Console\\SingleCommandApplication' => $vendorDir . '/symfony/console/SingleCommandApplication.php', - 'Symfony\\Component\\Console\\Style\\OutputStyle' => $vendorDir . '/symfony/console/Style/OutputStyle.php', - 'Symfony\\Component\\Console\\Style\\StyleInterface' => $vendorDir . '/symfony/console/Style/StyleInterface.php', - 'Symfony\\Component\\Console\\Style\\SymfonyStyle' => $vendorDir . '/symfony/console/Style/SymfonyStyle.php', - 'Symfony\\Component\\Console\\Terminal' => $vendorDir . '/symfony/console/Terminal.php', - 'Symfony\\Component\\Console\\Tester\\ApplicationTester' => $vendorDir . '/symfony/console/Tester/ApplicationTester.php', - 'Symfony\\Component\\Console\\Tester\\CommandCompletionTester' => $vendorDir . '/symfony/console/Tester/CommandCompletionTester.php', - 'Symfony\\Component\\Console\\Tester\\CommandTester' => $vendorDir . '/symfony/console/Tester/CommandTester.php', - 'Symfony\\Component\\Console\\Tester\\Constraint\\CommandIsSuccessful' => $vendorDir . '/symfony/console/Tester/Constraint/CommandIsSuccessful.php', - 'Symfony\\Component\\Console\\Tester\\TesterTrait' => $vendorDir . '/symfony/console/Tester/TesterTrait.php', - 'Symfony\\Component\\CssSelector\\CssSelectorConverter' => $vendorDir . '/symfony/css-selector/CssSelectorConverter.php', - 'Symfony\\Component\\CssSelector\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/css-selector/Exception/ExceptionInterface.php', - 'Symfony\\Component\\CssSelector\\Exception\\ExpressionErrorException' => $vendorDir . '/symfony/css-selector/Exception/ExpressionErrorException.php', - 'Symfony\\Component\\CssSelector\\Exception\\InternalErrorException' => $vendorDir . '/symfony/css-selector/Exception/InternalErrorException.php', - 'Symfony\\Component\\CssSelector\\Exception\\ParseException' => $vendorDir . '/symfony/css-selector/Exception/ParseException.php', - 'Symfony\\Component\\CssSelector\\Exception\\SyntaxErrorException' => $vendorDir . '/symfony/css-selector/Exception/SyntaxErrorException.php', - 'Symfony\\Component\\CssSelector\\Node\\AbstractNode' => $vendorDir . '/symfony/css-selector/Node/AbstractNode.php', - 'Symfony\\Component\\CssSelector\\Node\\AttributeNode' => $vendorDir . '/symfony/css-selector/Node/AttributeNode.php', - 'Symfony\\Component\\CssSelector\\Node\\ClassNode' => $vendorDir . '/symfony/css-selector/Node/ClassNode.php', - 'Symfony\\Component\\CssSelector\\Node\\CombinedSelectorNode' => $vendorDir . '/symfony/css-selector/Node/CombinedSelectorNode.php', - 'Symfony\\Component\\CssSelector\\Node\\ElementNode' => $vendorDir . '/symfony/css-selector/Node/ElementNode.php', - 'Symfony\\Component\\CssSelector\\Node\\FunctionNode' => $vendorDir . '/symfony/css-selector/Node/FunctionNode.php', - 'Symfony\\Component\\CssSelector\\Node\\HashNode' => $vendorDir . '/symfony/css-selector/Node/HashNode.php', - 'Symfony\\Component\\CssSelector\\Node\\NegationNode' => $vendorDir . '/symfony/css-selector/Node/NegationNode.php', - 'Symfony\\Component\\CssSelector\\Node\\NodeInterface' => $vendorDir . '/symfony/css-selector/Node/NodeInterface.php', - 'Symfony\\Component\\CssSelector\\Node\\PseudoNode' => $vendorDir . '/symfony/css-selector/Node/PseudoNode.php', - 'Symfony\\Component\\CssSelector\\Node\\SelectorNode' => $vendorDir . '/symfony/css-selector/Node/SelectorNode.php', - 'Symfony\\Component\\CssSelector\\Node\\Specificity' => $vendorDir . '/symfony/css-selector/Node/Specificity.php', - 'Symfony\\Component\\CssSelector\\Parser\\Handler\\CommentHandler' => $vendorDir . '/symfony/css-selector/Parser/Handler/CommentHandler.php', - 'Symfony\\Component\\CssSelector\\Parser\\Handler\\HandlerInterface' => $vendorDir . '/symfony/css-selector/Parser/Handler/HandlerInterface.php', - 'Symfony\\Component\\CssSelector\\Parser\\Handler\\HashHandler' => $vendorDir . '/symfony/css-selector/Parser/Handler/HashHandler.php', - 'Symfony\\Component\\CssSelector\\Parser\\Handler\\IdentifierHandler' => $vendorDir . '/symfony/css-selector/Parser/Handler/IdentifierHandler.php', - 'Symfony\\Component\\CssSelector\\Parser\\Handler\\NumberHandler' => $vendorDir . '/symfony/css-selector/Parser/Handler/NumberHandler.php', - 'Symfony\\Component\\CssSelector\\Parser\\Handler\\StringHandler' => $vendorDir . '/symfony/css-selector/Parser/Handler/StringHandler.php', - 'Symfony\\Component\\CssSelector\\Parser\\Handler\\WhitespaceHandler' => $vendorDir . '/symfony/css-selector/Parser/Handler/WhitespaceHandler.php', - 'Symfony\\Component\\CssSelector\\Parser\\Parser' => $vendorDir . '/symfony/css-selector/Parser/Parser.php', - 'Symfony\\Component\\CssSelector\\Parser\\ParserInterface' => $vendorDir . '/symfony/css-selector/Parser/ParserInterface.php', - 'Symfony\\Component\\CssSelector\\Parser\\Reader' => $vendorDir . '/symfony/css-selector/Parser/Reader.php', - 'Symfony\\Component\\CssSelector\\Parser\\Shortcut\\ClassParser' => $vendorDir . '/symfony/css-selector/Parser/Shortcut/ClassParser.php', - 'Symfony\\Component\\CssSelector\\Parser\\Shortcut\\ElementParser' => $vendorDir . '/symfony/css-selector/Parser/Shortcut/ElementParser.php', - 'Symfony\\Component\\CssSelector\\Parser\\Shortcut\\EmptyStringParser' => $vendorDir . '/symfony/css-selector/Parser/Shortcut/EmptyStringParser.php', - 'Symfony\\Component\\CssSelector\\Parser\\Shortcut\\HashParser' => $vendorDir . '/symfony/css-selector/Parser/Shortcut/HashParser.php', - 'Symfony\\Component\\CssSelector\\Parser\\Token' => $vendorDir . '/symfony/css-selector/Parser/Token.php', - 'Symfony\\Component\\CssSelector\\Parser\\TokenStream' => $vendorDir . '/symfony/css-selector/Parser/TokenStream.php', - 'Symfony\\Component\\CssSelector\\Parser\\Tokenizer\\Tokenizer' => $vendorDir . '/symfony/css-selector/Parser/Tokenizer/Tokenizer.php', - 'Symfony\\Component\\CssSelector\\Parser\\Tokenizer\\TokenizerEscaping' => $vendorDir . '/symfony/css-selector/Parser/Tokenizer/TokenizerEscaping.php', - 'Symfony\\Component\\CssSelector\\Parser\\Tokenizer\\TokenizerPatterns' => $vendorDir . '/symfony/css-selector/Parser/Tokenizer/TokenizerPatterns.php', - 'Symfony\\Component\\CssSelector\\XPath\\Extension\\AbstractExtension' => $vendorDir . '/symfony/css-selector/XPath/Extension/AbstractExtension.php', - 'Symfony\\Component\\CssSelector\\XPath\\Extension\\AttributeMatchingExtension' => $vendorDir . '/symfony/css-selector/XPath/Extension/AttributeMatchingExtension.php', - 'Symfony\\Component\\CssSelector\\XPath\\Extension\\CombinationExtension' => $vendorDir . '/symfony/css-selector/XPath/Extension/CombinationExtension.php', - 'Symfony\\Component\\CssSelector\\XPath\\Extension\\ExtensionInterface' => $vendorDir . '/symfony/css-selector/XPath/Extension/ExtensionInterface.php', - 'Symfony\\Component\\CssSelector\\XPath\\Extension\\FunctionExtension' => $vendorDir . '/symfony/css-selector/XPath/Extension/FunctionExtension.php', - 'Symfony\\Component\\CssSelector\\XPath\\Extension\\HtmlExtension' => $vendorDir . '/symfony/css-selector/XPath/Extension/HtmlExtension.php', - 'Symfony\\Component\\CssSelector\\XPath\\Extension\\NodeExtension' => $vendorDir . '/symfony/css-selector/XPath/Extension/NodeExtension.php', - 'Symfony\\Component\\CssSelector\\XPath\\Extension\\PseudoClassExtension' => $vendorDir . '/symfony/css-selector/XPath/Extension/PseudoClassExtension.php', - 'Symfony\\Component\\CssSelector\\XPath\\Translator' => $vendorDir . '/symfony/css-selector/XPath/Translator.php', - 'Symfony\\Component\\CssSelector\\XPath\\TranslatorInterface' => $vendorDir . '/symfony/css-selector/XPath/TranslatorInterface.php', - 'Symfony\\Component\\CssSelector\\XPath\\XPathExpr' => $vendorDir . '/symfony/css-selector/XPath/XPathExpr.php', - 'Symfony\\Component\\DependencyInjection\\Alias' => $vendorDir . '/symfony/dependency-injection/Alias.php', - 'Symfony\\Component\\DependencyInjection\\Argument\\AbstractArgument' => $vendorDir . '/symfony/dependency-injection/Argument/AbstractArgument.php', - 'Symfony\\Component\\DependencyInjection\\Argument\\ArgumentInterface' => $vendorDir . '/symfony/dependency-injection/Argument/ArgumentInterface.php', - 'Symfony\\Component\\DependencyInjection\\Argument\\BoundArgument' => $vendorDir . '/symfony/dependency-injection/Argument/BoundArgument.php', - 'Symfony\\Component\\DependencyInjection\\Argument\\IteratorArgument' => $vendorDir . '/symfony/dependency-injection/Argument/IteratorArgument.php', - 'Symfony\\Component\\DependencyInjection\\Argument\\ReferenceSetArgumentTrait' => $vendorDir . '/symfony/dependency-injection/Argument/ReferenceSetArgumentTrait.php', - 'Symfony\\Component\\DependencyInjection\\Argument\\RewindableGenerator' => $vendorDir . '/symfony/dependency-injection/Argument/RewindableGenerator.php', - 'Symfony\\Component\\DependencyInjection\\Argument\\ServiceClosureArgument' => $vendorDir . '/symfony/dependency-injection/Argument/ServiceClosureArgument.php', - 'Symfony\\Component\\DependencyInjection\\Argument\\ServiceLocator' => $vendorDir . '/symfony/dependency-injection/Argument/ServiceLocator.php', - 'Symfony\\Component\\DependencyInjection\\Argument\\ServiceLocatorArgument' => $vendorDir . '/symfony/dependency-injection/Argument/ServiceLocatorArgument.php', - 'Symfony\\Component\\DependencyInjection\\Argument\\TaggedIteratorArgument' => $vendorDir . '/symfony/dependency-injection/Argument/TaggedIteratorArgument.php', - 'Symfony\\Component\\DependencyInjection\\Attribute\\AsTaggedItem' => $vendorDir . '/symfony/dependency-injection/Attribute/AsTaggedItem.php', - 'Symfony\\Component\\DependencyInjection\\Attribute\\Autoconfigure' => $vendorDir . '/symfony/dependency-injection/Attribute/Autoconfigure.php', - 'Symfony\\Component\\DependencyInjection\\Attribute\\AutoconfigureTag' => $vendorDir . '/symfony/dependency-injection/Attribute/AutoconfigureTag.php', - 'Symfony\\Component\\DependencyInjection\\Attribute\\TaggedIterator' => $vendorDir . '/symfony/dependency-injection/Attribute/TaggedIterator.php', - 'Symfony\\Component\\DependencyInjection\\Attribute\\TaggedLocator' => $vendorDir . '/symfony/dependency-injection/Attribute/TaggedLocator.php', - 'Symfony\\Component\\DependencyInjection\\Attribute\\Target' => $vendorDir . '/symfony/dependency-injection/Attribute/Target.php', - 'Symfony\\Component\\DependencyInjection\\Attribute\\When' => $vendorDir . '/symfony/dependency-injection/Attribute/When.php', - 'Symfony\\Component\\DependencyInjection\\ChildDefinition' => $vendorDir . '/symfony/dependency-injection/ChildDefinition.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\AbstractRecursivePass' => $vendorDir . '/symfony/dependency-injection/Compiler/AbstractRecursivePass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\AliasDeprecatedPublicServicesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/AliasDeprecatedPublicServicesPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\AnalyzeServiceReferencesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\AttributeAutoconfigurationPass' => $vendorDir . '/symfony/dependency-injection/Compiler/AttributeAutoconfigurationPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\AutoAliasServicePass' => $vendorDir . '/symfony/dependency-injection/Compiler/AutoAliasServicePass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\AutowirePass' => $vendorDir . '/symfony/dependency-injection/Compiler/AutowirePass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\AutowireRequiredMethodsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\AutowireRequiredPropertiesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/AutowireRequiredPropertiesPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\CheckArgumentsValidityPass' => $vendorDir . '/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\CheckCircularReferencesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\CheckDefinitionValidityPass' => $vendorDir . '/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\CheckExceptionOnInvalidReferenceBehaviorPass' => $vendorDir . '/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\CheckReferenceValidityPass' => $vendorDir . '/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\CheckTypeDeclarationsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\Compiler' => $vendorDir . '/symfony/dependency-injection/Compiler/Compiler.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\CompilerPassInterface' => $vendorDir . '/symfony/dependency-injection/Compiler/CompilerPassInterface.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\DecoratorServicePass' => $vendorDir . '/symfony/dependency-injection/Compiler/DecoratorServicePass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\DefinitionErrorExceptionPass' => $vendorDir . '/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ExtensionCompilerPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ExtensionCompilerPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\InlineServiceDefinitionsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\MergeExtensionConfigurationPass' => $vendorDir . '/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\PassConfig' => $vendorDir . '/symfony/dependency-injection/Compiler/PassConfig.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\PriorityTaggedServiceTrait' => $vendorDir . '/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\RegisterAutoconfigureAttributesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RegisterAutoconfigureAttributesPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\RegisterEnvVarProcessorsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\RegisterReverseContainerPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RegisterReverseContainerPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\RegisterServiceSubscribersPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\RemoveAbstractDefinitionsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\RemovePrivateAliasesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\RemoveUnusedDefinitionsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ReplaceAliasByActualDefinitionPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveBindingsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveBindingsPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveChildDefinitionsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveClassPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveClassPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveDecoratorStackPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveDecoratorStackPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveEnvPlaceholdersPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveFactoryClassPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveHotPathPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveHotPathPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveInstanceofConditionalsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveInvalidReferencesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveNamedArgumentsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveNoPreloadPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveNoPreloadPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveParameterPlaceHoldersPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolvePrivatesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolvePrivatesPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveReferencesToAliasesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveServiceSubscribersPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveTaggedIteratorArgumentPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ServiceLocatorTagPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ServiceReferenceGraph' => $vendorDir . '/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ServiceReferenceGraphEdge' => $vendorDir . '/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ServiceReferenceGraphNode' => $vendorDir . '/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ValidateEnvPlaceholdersPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php', - 'Symfony\\Component\\DependencyInjection\\Config\\ContainerParametersResource' => $vendorDir . '/symfony/dependency-injection/Config/ContainerParametersResource.php', - 'Symfony\\Component\\DependencyInjection\\Config\\ContainerParametersResourceChecker' => $vendorDir . '/symfony/dependency-injection/Config/ContainerParametersResourceChecker.php', - 'Symfony\\Component\\DependencyInjection\\Container' => $vendorDir . '/symfony/dependency-injection/Container.php', - 'Symfony\\Component\\DependencyInjection\\ContainerAwareInterface' => $vendorDir . '/symfony/dependency-injection/ContainerAwareInterface.php', - 'Symfony\\Component\\DependencyInjection\\ContainerAwareTrait' => $vendorDir . '/symfony/dependency-injection/ContainerAwareTrait.php', - 'Symfony\\Component\\DependencyInjection\\ContainerBuilder' => $vendorDir . '/symfony/dependency-injection/ContainerBuilder.php', - 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => $vendorDir . '/symfony/dependency-injection/ContainerInterface.php', - 'Symfony\\Component\\DependencyInjection\\Definition' => $vendorDir . '/symfony/dependency-injection/Definition.php', - 'Symfony\\Component\\DependencyInjection\\Dumper\\Dumper' => $vendorDir . '/symfony/dependency-injection/Dumper/Dumper.php', - 'Symfony\\Component\\DependencyInjection\\Dumper\\DumperInterface' => $vendorDir . '/symfony/dependency-injection/Dumper/DumperInterface.php', - 'Symfony\\Component\\DependencyInjection\\Dumper\\GraphvizDumper' => $vendorDir . '/symfony/dependency-injection/Dumper/GraphvizDumper.php', - 'Symfony\\Component\\DependencyInjection\\Dumper\\PhpDumper' => $vendorDir . '/symfony/dependency-injection/Dumper/PhpDumper.php', - 'Symfony\\Component\\DependencyInjection\\Dumper\\Preloader' => $vendorDir . '/symfony/dependency-injection/Dumper/Preloader.php', - 'Symfony\\Component\\DependencyInjection\\Dumper\\XmlDumper' => $vendorDir . '/symfony/dependency-injection/Dumper/XmlDumper.php', - 'Symfony\\Component\\DependencyInjection\\Dumper\\YamlDumper' => $vendorDir . '/symfony/dependency-injection/Dumper/YamlDumper.php', - 'Symfony\\Component\\DependencyInjection\\EnvVarLoaderInterface' => $vendorDir . '/symfony/dependency-injection/EnvVarLoaderInterface.php', - 'Symfony\\Component\\DependencyInjection\\EnvVarProcessor' => $vendorDir . '/symfony/dependency-injection/EnvVarProcessor.php', - 'Symfony\\Component\\DependencyInjection\\EnvVarProcessorInterface' => $vendorDir . '/symfony/dependency-injection/EnvVarProcessorInterface.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\AutowiringFailedException' => $vendorDir . '/symfony/dependency-injection/Exception/AutowiringFailedException.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\BadMethodCallException' => $vendorDir . '/symfony/dependency-injection/Exception/BadMethodCallException.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\EnvNotFoundException' => $vendorDir . '/symfony/dependency-injection/Exception/EnvNotFoundException.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\EnvParameterException' => $vendorDir . '/symfony/dependency-injection/Exception/EnvParameterException.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/dependency-injection/Exception/ExceptionInterface.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/dependency-injection/Exception/InvalidArgumentException.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\InvalidParameterTypeException' => $vendorDir . '/symfony/dependency-injection/Exception/InvalidParameterTypeException.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\LogicException' => $vendorDir . '/symfony/dependency-injection/Exception/LogicException.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\OutOfBoundsException' => $vendorDir . '/symfony/dependency-injection/Exception/OutOfBoundsException.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\ParameterCircularReferenceException' => $vendorDir . '/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\ParameterNotFoundException' => $vendorDir . '/symfony/dependency-injection/Exception/ParameterNotFoundException.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\RuntimeException' => $vendorDir . '/symfony/dependency-injection/Exception/RuntimeException.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\ServiceCircularReferenceException' => $vendorDir . '/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\ServiceNotFoundException' => $vendorDir . '/symfony/dependency-injection/Exception/ServiceNotFoundException.php', - 'Symfony\\Component\\DependencyInjection\\ExpressionLanguage' => $vendorDir . '/symfony/dependency-injection/ExpressionLanguage.php', - 'Symfony\\Component\\DependencyInjection\\ExpressionLanguageProvider' => $vendorDir . '/symfony/dependency-injection/ExpressionLanguageProvider.php', - 'Symfony\\Component\\DependencyInjection\\Extension\\ConfigurationExtensionInterface' => $vendorDir . '/symfony/dependency-injection/Extension/ConfigurationExtensionInterface.php', - 'Symfony\\Component\\DependencyInjection\\Extension\\Extension' => $vendorDir . '/symfony/dependency-injection/Extension/Extension.php', - 'Symfony\\Component\\DependencyInjection\\Extension\\ExtensionInterface' => $vendorDir . '/symfony/dependency-injection/Extension/ExtensionInterface.php', - 'Symfony\\Component\\DependencyInjection\\Extension\\PrependExtensionInterface' => $vendorDir . '/symfony/dependency-injection/Extension/PrependExtensionInterface.php', - 'Symfony\\Component\\DependencyInjection\\LazyProxy\\Instantiator\\InstantiatorInterface' => $vendorDir . '/symfony/dependency-injection/LazyProxy/Instantiator/InstantiatorInterface.php', - 'Symfony\\Component\\DependencyInjection\\LazyProxy\\Instantiator\\RealServiceInstantiator' => $vendorDir . '/symfony/dependency-injection/LazyProxy/Instantiator/RealServiceInstantiator.php', - 'Symfony\\Component\\DependencyInjection\\LazyProxy\\PhpDumper\\DumperInterface' => $vendorDir . '/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php', - 'Symfony\\Component\\DependencyInjection\\LazyProxy\\PhpDumper\\NullDumper' => $vendorDir . '/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php', - 'Symfony\\Component\\DependencyInjection\\LazyProxy\\ProxyHelper' => $vendorDir . '/symfony/dependency-injection/LazyProxy/ProxyHelper.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\ClosureLoader' => $vendorDir . '/symfony/dependency-injection/Loader/ClosureLoader.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\AbstractConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\AbstractServiceConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\AliasConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/AliasConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ClosureReferenceConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/ClosureReferenceConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ContainerConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\DefaultsConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\EnvConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/EnvConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\InlineServiceConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/InlineServiceConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\InstanceofConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ParametersConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/ParametersConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\PrototypeConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ReferenceConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/ReferenceConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ServiceConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ServicesConfigurator' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\AbstractTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/AbstractTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ArgumentTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/ArgumentTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\AutoconfigureTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/AutoconfigureTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\AutowireTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/AutowireTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\BindTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/BindTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\CallTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/CallTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ClassTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/ClassTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ConfiguratorTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/ConfiguratorTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\DecorateTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\DeprecateTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/DeprecateTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\FactoryTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/FactoryTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\FileTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/FileTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\LazyTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/LazyTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ParentTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/ParentTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\PropertyTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/PropertyTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\PublicTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/PublicTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ShareTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/ShareTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\SyntheticTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/SyntheticTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\TagTrait' => $vendorDir . '/symfony/dependency-injection/Loader/Configurator/Traits/TagTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\DirectoryLoader' => $vendorDir . '/symfony/dependency-injection/Loader/DirectoryLoader.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\FileLoader' => $vendorDir . '/symfony/dependency-injection/Loader/FileLoader.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\GlobFileLoader' => $vendorDir . '/symfony/dependency-injection/Loader/GlobFileLoader.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\IniFileLoader' => $vendorDir . '/symfony/dependency-injection/Loader/IniFileLoader.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\PhpFileLoader' => $vendorDir . '/symfony/dependency-injection/Loader/PhpFileLoader.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\XmlFileLoader' => $vendorDir . '/symfony/dependency-injection/Loader/XmlFileLoader.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\YamlFileLoader' => $vendorDir . '/symfony/dependency-injection/Loader/YamlFileLoader.php', - 'Symfony\\Component\\DependencyInjection\\Parameter' => $vendorDir . '/symfony/dependency-injection/Parameter.php', - 'Symfony\\Component\\DependencyInjection\\ParameterBag\\ContainerBag' => $vendorDir . '/symfony/dependency-injection/ParameterBag/ContainerBag.php', - 'Symfony\\Component\\DependencyInjection\\ParameterBag\\ContainerBagInterface' => $vendorDir . '/symfony/dependency-injection/ParameterBag/ContainerBagInterface.php', - 'Symfony\\Component\\DependencyInjection\\ParameterBag\\EnvPlaceholderParameterBag' => $vendorDir . '/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php', - 'Symfony\\Component\\DependencyInjection\\ParameterBag\\FrozenParameterBag' => $vendorDir . '/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php', - 'Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBag' => $vendorDir . '/symfony/dependency-injection/ParameterBag/ParameterBag.php', - 'Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBagInterface' => $vendorDir . '/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php', - 'Symfony\\Component\\DependencyInjection\\Reference' => $vendorDir . '/symfony/dependency-injection/Reference.php', - 'Symfony\\Component\\DependencyInjection\\ReverseContainer' => $vendorDir . '/symfony/dependency-injection/ReverseContainer.php', - 'Symfony\\Component\\DependencyInjection\\ServiceLocator' => $vendorDir . '/symfony/dependency-injection/ServiceLocator.php', - 'Symfony\\Component\\DependencyInjection\\TaggedContainerInterface' => $vendorDir . '/symfony/dependency-injection/TaggedContainerInterface.php', - 'Symfony\\Component\\DependencyInjection\\TypedReference' => $vendorDir . '/symfony/dependency-injection/TypedReference.php', - 'Symfony\\Component\\DependencyInjection\\Variable' => $vendorDir . '/symfony/dependency-injection/Variable.php', - 'Symfony\\Component\\Dotenv\\Command\\DebugCommand' => $vendorDir . '/symfony/dotenv/Command/DebugCommand.php', - 'Symfony\\Component\\Dotenv\\Command\\DotenvDumpCommand' => $vendorDir . '/symfony/dotenv/Command/DotenvDumpCommand.php', - 'Symfony\\Component\\Dotenv\\Dotenv' => $vendorDir . '/symfony/dotenv/Dotenv.php', - 'Symfony\\Component\\Dotenv\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/dotenv/Exception/ExceptionInterface.php', - 'Symfony\\Component\\Dotenv\\Exception\\FormatException' => $vendorDir . '/symfony/dotenv/Exception/FormatException.php', - 'Symfony\\Component\\Dotenv\\Exception\\FormatExceptionContext' => $vendorDir . '/symfony/dotenv/Exception/FormatExceptionContext.php', - 'Symfony\\Component\\Dotenv\\Exception\\PathException' => $vendorDir . '/symfony/dotenv/Exception/PathException.php', - 'Symfony\\Component\\ErrorHandler\\BufferingLogger' => $vendorDir . '/symfony/error-handler/BufferingLogger.php', - 'Symfony\\Component\\ErrorHandler\\Debug' => $vendorDir . '/symfony/error-handler/Debug.php', - 'Symfony\\Component\\ErrorHandler\\DebugClassLoader' => $vendorDir . '/symfony/error-handler/DebugClassLoader.php', - 'Symfony\\Component\\ErrorHandler\\ErrorEnhancer\\ClassNotFoundErrorEnhancer' => $vendorDir . '/symfony/error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php', - 'Symfony\\Component\\ErrorHandler\\ErrorEnhancer\\ErrorEnhancerInterface' => $vendorDir . '/symfony/error-handler/ErrorEnhancer/ErrorEnhancerInterface.php', - 'Symfony\\Component\\ErrorHandler\\ErrorEnhancer\\UndefinedFunctionErrorEnhancer' => $vendorDir . '/symfony/error-handler/ErrorEnhancer/UndefinedFunctionErrorEnhancer.php', - 'Symfony\\Component\\ErrorHandler\\ErrorEnhancer\\UndefinedMethodErrorEnhancer' => $vendorDir . '/symfony/error-handler/ErrorEnhancer/UndefinedMethodErrorEnhancer.php', - 'Symfony\\Component\\ErrorHandler\\ErrorHandler' => $vendorDir . '/symfony/error-handler/ErrorHandler.php', - 'Symfony\\Component\\ErrorHandler\\ErrorRenderer\\CliErrorRenderer' => $vendorDir . '/symfony/error-handler/ErrorRenderer/CliErrorRenderer.php', - 'Symfony\\Component\\ErrorHandler\\ErrorRenderer\\ErrorRendererInterface' => $vendorDir . '/symfony/error-handler/ErrorRenderer/ErrorRendererInterface.php', - 'Symfony\\Component\\ErrorHandler\\ErrorRenderer\\HtmlErrorRenderer' => $vendorDir . '/symfony/error-handler/ErrorRenderer/HtmlErrorRenderer.php', - 'Symfony\\Component\\ErrorHandler\\ErrorRenderer\\SerializerErrorRenderer' => $vendorDir . '/symfony/error-handler/ErrorRenderer/SerializerErrorRenderer.php', - 'Symfony\\Component\\ErrorHandler\\Error\\ClassNotFoundError' => $vendorDir . '/symfony/error-handler/Error/ClassNotFoundError.php', - 'Symfony\\Component\\ErrorHandler\\Error\\FatalError' => $vendorDir . '/symfony/error-handler/Error/FatalError.php', - 'Symfony\\Component\\ErrorHandler\\Error\\OutOfMemoryError' => $vendorDir . '/symfony/error-handler/Error/OutOfMemoryError.php', - 'Symfony\\Component\\ErrorHandler\\Error\\UndefinedFunctionError' => $vendorDir . '/symfony/error-handler/Error/UndefinedFunctionError.php', - 'Symfony\\Component\\ErrorHandler\\Error\\UndefinedMethodError' => $vendorDir . '/symfony/error-handler/Error/UndefinedMethodError.php', - 'Symfony\\Component\\ErrorHandler\\Exception\\FlattenException' => $vendorDir . '/symfony/error-handler/Exception/FlattenException.php', - 'Symfony\\Component\\ErrorHandler\\Exception\\SilencedErrorContext' => $vendorDir . '/symfony/error-handler/Exception/SilencedErrorContext.php', - 'Symfony\\Component\\ErrorHandler\\Internal\\TentativeTypes' => $vendorDir . '/symfony/error-handler/Internal/TentativeTypes.php', - 'Symfony\\Component\\ErrorHandler\\ThrowableUtils' => $vendorDir . '/symfony/error-handler/ThrowableUtils.php', - 'Symfony\\Component\\EventDispatcher\\Attribute\\AsEventListener' => $vendorDir . '/symfony/event-dispatcher/Attribute/AsEventListener.php', - 'Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcher' => $vendorDir . '/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php', - 'Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener' => $vendorDir . '/symfony/event-dispatcher/Debug/WrappedListener.php', - 'Symfony\\Component\\EventDispatcher\\DependencyInjection\\AddEventAliasesPass' => $vendorDir . '/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php', - 'Symfony\\Component\\EventDispatcher\\DependencyInjection\\RegisterListenersPass' => $vendorDir . '/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php', - 'Symfony\\Component\\EventDispatcher\\EventDispatcher' => $vendorDir . '/symfony/event-dispatcher/EventDispatcher.php', - 'Symfony\\Component\\EventDispatcher\\EventDispatcherInterface' => $vendorDir . '/symfony/event-dispatcher/EventDispatcherInterface.php', - 'Symfony\\Component\\EventDispatcher\\EventSubscriberInterface' => $vendorDir . '/symfony/event-dispatcher/EventSubscriberInterface.php', - 'Symfony\\Component\\EventDispatcher\\GenericEvent' => $vendorDir . '/symfony/event-dispatcher/GenericEvent.php', - 'Symfony\\Component\\EventDispatcher\\ImmutableEventDispatcher' => $vendorDir . '/symfony/event-dispatcher/ImmutableEventDispatcher.php', - 'Symfony\\Component\\EventDispatcher\\LegacyEventDispatcherProxy' => $vendorDir . '/symfony/event-dispatcher/LegacyEventDispatcherProxy.php', - 'Symfony\\Component\\Filesystem\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/filesystem/Exception/ExceptionInterface.php', - 'Symfony\\Component\\Filesystem\\Exception\\FileNotFoundException' => $vendorDir . '/symfony/filesystem/Exception/FileNotFoundException.php', - 'Symfony\\Component\\Filesystem\\Exception\\IOException' => $vendorDir . '/symfony/filesystem/Exception/IOException.php', - 'Symfony\\Component\\Filesystem\\Exception\\IOExceptionInterface' => $vendorDir . '/symfony/filesystem/Exception/IOExceptionInterface.php', - 'Symfony\\Component\\Filesystem\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/filesystem/Exception/InvalidArgumentException.php', - 'Symfony\\Component\\Filesystem\\Exception\\RuntimeException' => $vendorDir . '/symfony/filesystem/Exception/RuntimeException.php', - 'Symfony\\Component\\Filesystem\\Filesystem' => $vendorDir . '/symfony/filesystem/Filesystem.php', - 'Symfony\\Component\\Filesystem\\Path' => $vendorDir . '/symfony/filesystem/Path.php', - 'Symfony\\Component\\Finder\\Comparator\\Comparator' => $vendorDir . '/symfony/finder/Comparator/Comparator.php', - 'Symfony\\Component\\Finder\\Comparator\\DateComparator' => $vendorDir . '/symfony/finder/Comparator/DateComparator.php', - 'Symfony\\Component\\Finder\\Comparator\\NumberComparator' => $vendorDir . '/symfony/finder/Comparator/NumberComparator.php', - 'Symfony\\Component\\Finder\\Exception\\AccessDeniedException' => $vendorDir . '/symfony/finder/Exception/AccessDeniedException.php', - 'Symfony\\Component\\Finder\\Exception\\DirectoryNotFoundException' => $vendorDir . '/symfony/finder/Exception/DirectoryNotFoundException.php', - 'Symfony\\Component\\Finder\\Finder' => $vendorDir . '/symfony/finder/Finder.php', - 'Symfony\\Component\\Finder\\Gitignore' => $vendorDir . '/symfony/finder/Gitignore.php', - 'Symfony\\Component\\Finder\\Glob' => $vendorDir . '/symfony/finder/Glob.php', - 'Symfony\\Component\\Finder\\Iterator\\CustomFilterIterator' => $vendorDir . '/symfony/finder/Iterator/CustomFilterIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\DateRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/DateRangeFilterIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\DepthRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/DepthRangeFilterIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\ExcludeDirectoryFilterIterator' => $vendorDir . '/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\FileTypeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FileTypeFilterIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\FilecontentFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FilecontentFilterIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\FilenameFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FilenameFilterIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\LazyIterator' => $vendorDir . '/symfony/finder/Iterator/LazyIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\MultiplePcreFilterIterator' => $vendorDir . '/symfony/finder/Iterator/MultiplePcreFilterIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\PathFilterIterator' => $vendorDir . '/symfony/finder/Iterator/PathFilterIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\RecursiveDirectoryIterator' => $vendorDir . '/symfony/finder/Iterator/RecursiveDirectoryIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\SizeRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/SizeRangeFilterIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\SortableIterator' => $vendorDir . '/symfony/finder/Iterator/SortableIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\VcsIgnoredFilterIterator' => $vendorDir . '/symfony/finder/Iterator/VcsIgnoredFilterIterator.php', - 'Symfony\\Component\\Finder\\SplFileInfo' => $vendorDir . '/symfony/finder/SplFileInfo.php', - 'Symfony\\Component\\Form\\AbstractExtension' => $vendorDir . '/symfony/form/AbstractExtension.php', - 'Symfony\\Component\\Form\\AbstractRendererEngine' => $vendorDir . '/symfony/form/AbstractRendererEngine.php', - 'Symfony\\Component\\Form\\AbstractType' => $vendorDir . '/symfony/form/AbstractType.php', - 'Symfony\\Component\\Form\\AbstractTypeExtension' => $vendorDir . '/symfony/form/AbstractTypeExtension.php', - 'Symfony\\Component\\Form\\Button' => $vendorDir . '/symfony/form/Button.php', - 'Symfony\\Component\\Form\\ButtonBuilder' => $vendorDir . '/symfony/form/ButtonBuilder.php', - 'Symfony\\Component\\Form\\ButtonTypeInterface' => $vendorDir . '/symfony/form/ButtonTypeInterface.php', - 'Symfony\\Component\\Form\\CallbackTransformer' => $vendorDir . '/symfony/form/CallbackTransformer.php', - 'Symfony\\Component\\Form\\ChoiceList\\ArrayChoiceList' => $vendorDir . '/symfony/form/ChoiceList/ArrayChoiceList.php', - 'Symfony\\Component\\Form\\ChoiceList\\ChoiceList' => $vendorDir . '/symfony/form/ChoiceList/ChoiceList.php', - 'Symfony\\Component\\Form\\ChoiceList\\ChoiceListInterface' => $vendorDir . '/symfony/form/ChoiceList/ChoiceListInterface.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\Cache\\AbstractStaticOption' => $vendorDir . '/symfony/form/ChoiceList/Factory/Cache/AbstractStaticOption.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\Cache\\ChoiceAttr' => $vendorDir . '/symfony/form/ChoiceList/Factory/Cache/ChoiceAttr.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\Cache\\ChoiceFieldName' => $vendorDir . '/symfony/form/ChoiceList/Factory/Cache/ChoiceFieldName.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\Cache\\ChoiceFilter' => $vendorDir . '/symfony/form/ChoiceList/Factory/Cache/ChoiceFilter.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\Cache\\ChoiceLabel' => $vendorDir . '/symfony/form/ChoiceList/Factory/Cache/ChoiceLabel.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\Cache\\ChoiceLoader' => $vendorDir . '/symfony/form/ChoiceList/Factory/Cache/ChoiceLoader.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\Cache\\ChoiceTranslationParameters' => $vendorDir . '/symfony/form/ChoiceList/Factory/Cache/ChoiceTranslationParameters.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\Cache\\ChoiceValue' => $vendorDir . '/symfony/form/ChoiceList/Factory/Cache/ChoiceValue.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\Cache\\GroupBy' => $vendorDir . '/symfony/form/ChoiceList/Factory/Cache/GroupBy.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\Cache\\PreferredChoice' => $vendorDir . '/symfony/form/ChoiceList/Factory/Cache/PreferredChoice.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\CachingFactoryDecorator' => $vendorDir . '/symfony/form/ChoiceList/Factory/CachingFactoryDecorator.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\ChoiceListFactoryInterface' => $vendorDir . '/symfony/form/ChoiceList/Factory/ChoiceListFactoryInterface.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\DefaultChoiceListFactory' => $vendorDir . '/symfony/form/ChoiceList/Factory/DefaultChoiceListFactory.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\PropertyAccessDecorator' => $vendorDir . '/symfony/form/ChoiceList/Factory/PropertyAccessDecorator.php', - 'Symfony\\Component\\Form\\ChoiceList\\LazyChoiceList' => $vendorDir . '/symfony/form/ChoiceList/LazyChoiceList.php', - 'Symfony\\Component\\Form\\ChoiceList\\Loader\\AbstractChoiceLoader' => $vendorDir . '/symfony/form/ChoiceList/Loader/AbstractChoiceLoader.php', - 'Symfony\\Component\\Form\\ChoiceList\\Loader\\CallbackChoiceLoader' => $vendorDir . '/symfony/form/ChoiceList/Loader/CallbackChoiceLoader.php', - 'Symfony\\Component\\Form\\ChoiceList\\Loader\\ChoiceLoaderInterface' => $vendorDir . '/symfony/form/ChoiceList/Loader/ChoiceLoaderInterface.php', - 'Symfony\\Component\\Form\\ChoiceList\\Loader\\FilterChoiceLoaderDecorator' => $vendorDir . '/symfony/form/ChoiceList/Loader/FilterChoiceLoaderDecorator.php', - 'Symfony\\Component\\Form\\ChoiceList\\Loader\\IntlCallbackChoiceLoader' => $vendorDir . '/symfony/form/ChoiceList/Loader/IntlCallbackChoiceLoader.php', - 'Symfony\\Component\\Form\\ChoiceList\\View\\ChoiceGroupView' => $vendorDir . '/symfony/form/ChoiceList/View/ChoiceGroupView.php', - 'Symfony\\Component\\Form\\ChoiceList\\View\\ChoiceListView' => $vendorDir . '/symfony/form/ChoiceList/View/ChoiceListView.php', - 'Symfony\\Component\\Form\\ChoiceList\\View\\ChoiceView' => $vendorDir . '/symfony/form/ChoiceList/View/ChoiceView.php', - 'Symfony\\Component\\Form\\ClearableErrorsInterface' => $vendorDir . '/symfony/form/ClearableErrorsInterface.php', - 'Symfony\\Component\\Form\\ClickableInterface' => $vendorDir . '/symfony/form/ClickableInterface.php', - 'Symfony\\Component\\Form\\Command\\DebugCommand' => $vendorDir . '/symfony/form/Command/DebugCommand.php', - 'Symfony\\Component\\Form\\Console\\Descriptor\\Descriptor' => $vendorDir . '/symfony/form/Console/Descriptor/Descriptor.php', - 'Symfony\\Component\\Form\\Console\\Descriptor\\JsonDescriptor' => $vendorDir . '/symfony/form/Console/Descriptor/JsonDescriptor.php', - 'Symfony\\Component\\Form\\Console\\Descriptor\\TextDescriptor' => $vendorDir . '/symfony/form/Console/Descriptor/TextDescriptor.php', - 'Symfony\\Component\\Form\\Console\\Helper\\DescriptorHelper' => $vendorDir . '/symfony/form/Console/Helper/DescriptorHelper.php', - 'Symfony\\Component\\Form\\DataAccessorInterface' => $vendorDir . '/symfony/form/DataAccessorInterface.php', - 'Symfony\\Component\\Form\\DataMapperInterface' => $vendorDir . '/symfony/form/DataMapperInterface.php', - 'Symfony\\Component\\Form\\DataTransformerInterface' => $vendorDir . '/symfony/form/DataTransformerInterface.php', - 'Symfony\\Component\\Form\\DependencyInjection\\FormPass' => $vendorDir . '/symfony/form/DependencyInjection/FormPass.php', - 'Symfony\\Component\\Form\\Event\\PostSetDataEvent' => $vendorDir . '/symfony/form/Event/PostSetDataEvent.php', - 'Symfony\\Component\\Form\\Event\\PostSubmitEvent' => $vendorDir . '/symfony/form/Event/PostSubmitEvent.php', - 'Symfony\\Component\\Form\\Event\\PreSetDataEvent' => $vendorDir . '/symfony/form/Event/PreSetDataEvent.php', - 'Symfony\\Component\\Form\\Event\\PreSubmitEvent' => $vendorDir . '/symfony/form/Event/PreSubmitEvent.php', - 'Symfony\\Component\\Form\\Event\\SubmitEvent' => $vendorDir . '/symfony/form/Event/SubmitEvent.php', - 'Symfony\\Component\\Form\\Exception\\AccessException' => $vendorDir . '/symfony/form/Exception/AccessException.php', - 'Symfony\\Component\\Form\\Exception\\AlreadySubmittedException' => $vendorDir . '/symfony/form/Exception/AlreadySubmittedException.php', - 'Symfony\\Component\\Form\\Exception\\BadMethodCallException' => $vendorDir . '/symfony/form/Exception/BadMethodCallException.php', - 'Symfony\\Component\\Form\\Exception\\ErrorMappingException' => $vendorDir . '/symfony/form/Exception/ErrorMappingException.php', - 'Symfony\\Component\\Form\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/form/Exception/ExceptionInterface.php', - 'Symfony\\Component\\Form\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/form/Exception/InvalidArgumentException.php', - 'Symfony\\Component\\Form\\Exception\\InvalidConfigurationException' => $vendorDir . '/symfony/form/Exception/InvalidConfigurationException.php', - 'Symfony\\Component\\Form\\Exception\\LogicException' => $vendorDir . '/symfony/form/Exception/LogicException.php', - 'Symfony\\Component\\Form\\Exception\\OutOfBoundsException' => $vendorDir . '/symfony/form/Exception/OutOfBoundsException.php', - 'Symfony\\Component\\Form\\Exception\\RuntimeException' => $vendorDir . '/symfony/form/Exception/RuntimeException.php', - 'Symfony\\Component\\Form\\Exception\\StringCastException' => $vendorDir . '/symfony/form/Exception/StringCastException.php', - 'Symfony\\Component\\Form\\Exception\\TransformationFailedException' => $vendorDir . '/symfony/form/Exception/TransformationFailedException.php', - 'Symfony\\Component\\Form\\Exception\\UnexpectedTypeException' => $vendorDir . '/symfony/form/Exception/UnexpectedTypeException.php', - 'Symfony\\Component\\Form\\Extension\\Core\\CoreExtension' => $vendorDir . '/symfony/form/Extension/Core/CoreExtension.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataAccessor\\CallbackAccessor' => $vendorDir . '/symfony/form/Extension/Core/DataAccessor/CallbackAccessor.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataAccessor\\ChainAccessor' => $vendorDir . '/symfony/form/Extension/Core/DataAccessor/ChainAccessor.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataAccessor\\PropertyPathAccessor' => $vendorDir . '/symfony/form/Extension/Core/DataAccessor/PropertyPathAccessor.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataMapper\\CheckboxListMapper' => $vendorDir . '/symfony/form/Extension/Core/DataMapper/CheckboxListMapper.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataMapper\\DataMapper' => $vendorDir . '/symfony/form/Extension/Core/DataMapper/DataMapper.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataMapper\\PropertyPathMapper' => $vendorDir . '/symfony/form/Extension/Core/DataMapper/PropertyPathMapper.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataMapper\\RadioListMapper' => $vendorDir . '/symfony/form/Extension/Core/DataMapper/RadioListMapper.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\ArrayToPartsTransformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/ArrayToPartsTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\BaseDateTimeTransformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/BaseDateTimeTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\BooleanToStringTransformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/BooleanToStringTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\ChoiceToValueTransformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\ChoicesToValuesTransformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\DataTransformerChain' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/DataTransformerChain.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\DateIntervalToArrayTransformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/DateIntervalToArrayTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\DateIntervalToStringTransformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/DateIntervalToStringTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\DateTimeImmutableToDateTimeTransformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/DateTimeImmutableToDateTimeTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\DateTimeToArrayTransformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\DateTimeToHtml5LocalDateTimeTransformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/DateTimeToHtml5LocalDateTimeTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\DateTimeToLocalizedStringTransformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\DateTimeToRfc3339Transformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\DateTimeToStringTransformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\DateTimeToTimestampTransformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\DateTimeZoneToStringTransformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/DateTimeZoneToStringTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\IntegerToLocalizedStringTransformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\IntlTimeZoneToStringTransformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/IntlTimeZoneToStringTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\MoneyToLocalizedStringTransformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\NumberToLocalizedStringTransformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\PercentToLocalizedStringTransformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\StringToFloatTransformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/StringToFloatTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\UlidToStringTransformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/UlidToStringTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\UuidToStringTransformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/UuidToStringTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\ValueToDuplicatesTransformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\WeekToArrayTransformer' => $vendorDir . '/symfony/form/Extension/Core/DataTransformer/WeekToArrayTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\EventListener\\FixUrlProtocolListener' => $vendorDir . '/symfony/form/Extension/Core/EventListener/FixUrlProtocolListener.php', - 'Symfony\\Component\\Form\\Extension\\Core\\EventListener\\MergeCollectionListener' => $vendorDir . '/symfony/form/Extension/Core/EventListener/MergeCollectionListener.php', - 'Symfony\\Component\\Form\\Extension\\Core\\EventListener\\ResizeFormListener' => $vendorDir . '/symfony/form/Extension/Core/EventListener/ResizeFormListener.php', - 'Symfony\\Component\\Form\\Extension\\Core\\EventListener\\TransformationFailureListener' => $vendorDir . '/symfony/form/Extension/Core/EventListener/TransformationFailureListener.php', - 'Symfony\\Component\\Form\\Extension\\Core\\EventListener\\TrimListener' => $vendorDir . '/symfony/form/Extension/Core/EventListener/TrimListener.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\BaseType' => $vendorDir . '/symfony/form/Extension/Core/Type/BaseType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\BirthdayType' => $vendorDir . '/symfony/form/Extension/Core/Type/BirthdayType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\ButtonType' => $vendorDir . '/symfony/form/Extension/Core/Type/ButtonType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\CheckboxType' => $vendorDir . '/symfony/form/Extension/Core/Type/CheckboxType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\ChoiceType' => $vendorDir . '/symfony/form/Extension/Core/Type/ChoiceType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\CollectionType' => $vendorDir . '/symfony/form/Extension/Core/Type/CollectionType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\ColorType' => $vendorDir . '/symfony/form/Extension/Core/Type/ColorType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\CountryType' => $vendorDir . '/symfony/form/Extension/Core/Type/CountryType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\CurrencyType' => $vendorDir . '/symfony/form/Extension/Core/Type/CurrencyType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\DateIntervalType' => $vendorDir . '/symfony/form/Extension/Core/Type/DateIntervalType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\DateTimeType' => $vendorDir . '/symfony/form/Extension/Core/Type/DateTimeType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\DateType' => $vendorDir . '/symfony/form/Extension/Core/Type/DateType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\EmailType' => $vendorDir . '/symfony/form/Extension/Core/Type/EmailType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\EnumType' => $vendorDir . '/symfony/form/Extension/Core/Type/EnumType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\FileType' => $vendorDir . '/symfony/form/Extension/Core/Type/FileType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\FormType' => $vendorDir . '/symfony/form/Extension/Core/Type/FormType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\HiddenType' => $vendorDir . '/symfony/form/Extension/Core/Type/HiddenType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\IntegerType' => $vendorDir . '/symfony/form/Extension/Core/Type/IntegerType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\LanguageType' => $vendorDir . '/symfony/form/Extension/Core/Type/LanguageType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\LocaleType' => $vendorDir . '/symfony/form/Extension/Core/Type/LocaleType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\MoneyType' => $vendorDir . '/symfony/form/Extension/Core/Type/MoneyType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\NumberType' => $vendorDir . '/symfony/form/Extension/Core/Type/NumberType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\PasswordType' => $vendorDir . '/symfony/form/Extension/Core/Type/PasswordType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\PercentType' => $vendorDir . '/symfony/form/Extension/Core/Type/PercentType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\RadioType' => $vendorDir . '/symfony/form/Extension/Core/Type/RadioType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\RangeType' => $vendorDir . '/symfony/form/Extension/Core/Type/RangeType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\RepeatedType' => $vendorDir . '/symfony/form/Extension/Core/Type/RepeatedType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\ResetType' => $vendorDir . '/symfony/form/Extension/Core/Type/ResetType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\SearchType' => $vendorDir . '/symfony/form/Extension/Core/Type/SearchType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\SubmitType' => $vendorDir . '/symfony/form/Extension/Core/Type/SubmitType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\TelType' => $vendorDir . '/symfony/form/Extension/Core/Type/TelType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\TextType' => $vendorDir . '/symfony/form/Extension/Core/Type/TextType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\TextareaType' => $vendorDir . '/symfony/form/Extension/Core/Type/TextareaType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\TimeType' => $vendorDir . '/symfony/form/Extension/Core/Type/TimeType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\TimezoneType' => $vendorDir . '/symfony/form/Extension/Core/Type/TimezoneType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\TransformationFailureExtension' => $vendorDir . '/symfony/form/Extension/Core/Type/TransformationFailureExtension.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\UlidType' => $vendorDir . '/symfony/form/Extension/Core/Type/UlidType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\UrlType' => $vendorDir . '/symfony/form/Extension/Core/Type/UrlType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\UuidType' => $vendorDir . '/symfony/form/Extension/Core/Type/UuidType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\WeekType' => $vendorDir . '/symfony/form/Extension/Core/Type/WeekType.php', - 'Symfony\\Component\\Form\\Extension\\Csrf\\CsrfExtension' => $vendorDir . '/symfony/form/Extension/Csrf/CsrfExtension.php', - 'Symfony\\Component\\Form\\Extension\\Csrf\\EventListener\\CsrfValidationListener' => $vendorDir . '/symfony/form/Extension/Csrf/EventListener/CsrfValidationListener.php', - 'Symfony\\Component\\Form\\Extension\\Csrf\\Type\\FormTypeCsrfExtension' => $vendorDir . '/symfony/form/Extension/Csrf/Type/FormTypeCsrfExtension.php', - 'Symfony\\Component\\Form\\Extension\\DataCollector\\DataCollectorExtension' => $vendorDir . '/symfony/form/Extension/DataCollector/DataCollectorExtension.php', - 'Symfony\\Component\\Form\\Extension\\DataCollector\\EventListener\\DataCollectorListener' => $vendorDir . '/symfony/form/Extension/DataCollector/EventListener/DataCollectorListener.php', - 'Symfony\\Component\\Form\\Extension\\DataCollector\\FormDataCollector' => $vendorDir . '/symfony/form/Extension/DataCollector/FormDataCollector.php', - 'Symfony\\Component\\Form\\Extension\\DataCollector\\FormDataCollectorInterface' => $vendorDir . '/symfony/form/Extension/DataCollector/FormDataCollectorInterface.php', - 'Symfony\\Component\\Form\\Extension\\DataCollector\\FormDataExtractor' => $vendorDir . '/symfony/form/Extension/DataCollector/FormDataExtractor.php', - 'Symfony\\Component\\Form\\Extension\\DataCollector\\FormDataExtractorInterface' => $vendorDir . '/symfony/form/Extension/DataCollector/FormDataExtractorInterface.php', - 'Symfony\\Component\\Form\\Extension\\DataCollector\\Proxy\\ResolvedTypeDataCollectorProxy' => $vendorDir . '/symfony/form/Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.php', - 'Symfony\\Component\\Form\\Extension\\DataCollector\\Proxy\\ResolvedTypeFactoryDataCollectorProxy' => $vendorDir . '/symfony/form/Extension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.php', - 'Symfony\\Component\\Form\\Extension\\DataCollector\\Type\\DataCollectorTypeExtension' => $vendorDir . '/symfony/form/Extension/DataCollector/Type/DataCollectorTypeExtension.php', - 'Symfony\\Component\\Form\\Extension\\DependencyInjection\\DependencyInjectionExtension' => $vendorDir . '/symfony/form/Extension/DependencyInjection/DependencyInjectionExtension.php', - 'Symfony\\Component\\Form\\Extension\\HttpFoundation\\HttpFoundationExtension' => $vendorDir . '/symfony/form/Extension/HttpFoundation/HttpFoundationExtension.php', - 'Symfony\\Component\\Form\\Extension\\HttpFoundation\\HttpFoundationRequestHandler' => $vendorDir . '/symfony/form/Extension/HttpFoundation/HttpFoundationRequestHandler.php', - 'Symfony\\Component\\Form\\Extension\\HttpFoundation\\Type\\FormTypeHttpFoundationExtension' => $vendorDir . '/symfony/form/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\Constraints\\Form' => $vendorDir . '/symfony/form/Extension/Validator/Constraints/Form.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\Constraints\\FormValidator' => $vendorDir . '/symfony/form/Extension/Validator/Constraints/FormValidator.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\EventListener\\ValidationListener' => $vendorDir . '/symfony/form/Extension/Validator/EventListener/ValidationListener.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\Type\\BaseValidatorExtension' => $vendorDir . '/symfony/form/Extension/Validator/Type/BaseValidatorExtension.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\Type\\FormTypeValidatorExtension' => $vendorDir . '/symfony/form/Extension/Validator/Type/FormTypeValidatorExtension.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\Type\\RepeatedTypeValidatorExtension' => $vendorDir . '/symfony/form/Extension/Validator/Type/RepeatedTypeValidatorExtension.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\Type\\SubmitTypeValidatorExtension' => $vendorDir . '/symfony/form/Extension/Validator/Type/SubmitTypeValidatorExtension.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\Type\\UploadValidatorExtension' => $vendorDir . '/symfony/form/Extension/Validator/Type/UploadValidatorExtension.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\Util\\ServerParams' => $vendorDir . '/symfony/form/Extension/Validator/Util/ServerParams.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\ValidatorExtension' => $vendorDir . '/symfony/form/Extension/Validator/ValidatorExtension.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\ValidatorTypeGuesser' => $vendorDir . '/symfony/form/Extension/Validator/ValidatorTypeGuesser.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\ViolationMapper\\MappingRule' => $vendorDir . '/symfony/form/Extension/Validator/ViolationMapper/MappingRule.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\ViolationMapper\\RelativePath' => $vendorDir . '/symfony/form/Extension/Validator/ViolationMapper/RelativePath.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\ViolationMapper\\ViolationMapper' => $vendorDir . '/symfony/form/Extension/Validator/ViolationMapper/ViolationMapper.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\ViolationMapper\\ViolationMapperInterface' => $vendorDir . '/symfony/form/Extension/Validator/ViolationMapper/ViolationMapperInterface.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\ViolationMapper\\ViolationPath' => $vendorDir . '/symfony/form/Extension/Validator/ViolationMapper/ViolationPath.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\ViolationMapper\\ViolationPathIterator' => $vendorDir . '/symfony/form/Extension/Validator/ViolationMapper/ViolationPathIterator.php', - 'Symfony\\Component\\Form\\FileUploadError' => $vendorDir . '/symfony/form/FileUploadError.php', - 'Symfony\\Component\\Form\\Form' => $vendorDir . '/symfony/form/Form.php', - 'Symfony\\Component\\Form\\FormBuilder' => $vendorDir . '/symfony/form/FormBuilder.php', - 'Symfony\\Component\\Form\\FormBuilderInterface' => $vendorDir . '/symfony/form/FormBuilderInterface.php', - 'Symfony\\Component\\Form\\FormConfigBuilder' => $vendorDir . '/symfony/form/FormConfigBuilder.php', - 'Symfony\\Component\\Form\\FormConfigBuilderInterface' => $vendorDir . '/symfony/form/FormConfigBuilderInterface.php', - 'Symfony\\Component\\Form\\FormConfigInterface' => $vendorDir . '/symfony/form/FormConfigInterface.php', - 'Symfony\\Component\\Form\\FormError' => $vendorDir . '/symfony/form/FormError.php', - 'Symfony\\Component\\Form\\FormErrorIterator' => $vendorDir . '/symfony/form/FormErrorIterator.php', - 'Symfony\\Component\\Form\\FormEvent' => $vendorDir . '/symfony/form/FormEvent.php', - 'Symfony\\Component\\Form\\FormEvents' => $vendorDir . '/symfony/form/FormEvents.php', - 'Symfony\\Component\\Form\\FormExtensionInterface' => $vendorDir . '/symfony/form/FormExtensionInterface.php', - 'Symfony\\Component\\Form\\FormFactory' => $vendorDir . '/symfony/form/FormFactory.php', - 'Symfony\\Component\\Form\\FormFactoryBuilder' => $vendorDir . '/symfony/form/FormFactoryBuilder.php', - 'Symfony\\Component\\Form\\FormFactoryBuilderInterface' => $vendorDir . '/symfony/form/FormFactoryBuilderInterface.php', - 'Symfony\\Component\\Form\\FormFactoryInterface' => $vendorDir . '/symfony/form/FormFactoryInterface.php', - 'Symfony\\Component\\Form\\FormInterface' => $vendorDir . '/symfony/form/FormInterface.php', - 'Symfony\\Component\\Form\\FormRegistry' => $vendorDir . '/symfony/form/FormRegistry.php', - 'Symfony\\Component\\Form\\FormRegistryInterface' => $vendorDir . '/symfony/form/FormRegistryInterface.php', - 'Symfony\\Component\\Form\\FormRenderer' => $vendorDir . '/symfony/form/FormRenderer.php', - 'Symfony\\Component\\Form\\FormRendererEngineInterface' => $vendorDir . '/symfony/form/FormRendererEngineInterface.php', - 'Symfony\\Component\\Form\\FormRendererInterface' => $vendorDir . '/symfony/form/FormRendererInterface.php', - 'Symfony\\Component\\Form\\FormTypeExtensionInterface' => $vendorDir . '/symfony/form/FormTypeExtensionInterface.php', - 'Symfony\\Component\\Form\\FormTypeGuesserChain' => $vendorDir . '/symfony/form/FormTypeGuesserChain.php', - 'Symfony\\Component\\Form\\FormTypeGuesserInterface' => $vendorDir . '/symfony/form/FormTypeGuesserInterface.php', - 'Symfony\\Component\\Form\\FormTypeInterface' => $vendorDir . '/symfony/form/FormTypeInterface.php', - 'Symfony\\Component\\Form\\FormView' => $vendorDir . '/symfony/form/FormView.php', - 'Symfony\\Component\\Form\\Forms' => $vendorDir . '/symfony/form/Forms.php', - 'Symfony\\Component\\Form\\Guess\\Guess' => $vendorDir . '/symfony/form/Guess/Guess.php', - 'Symfony\\Component\\Form\\Guess\\TypeGuess' => $vendorDir . '/symfony/form/Guess/TypeGuess.php', - 'Symfony\\Component\\Form\\Guess\\ValueGuess' => $vendorDir . '/symfony/form/Guess/ValueGuess.php', - 'Symfony\\Component\\Form\\NativeRequestHandler' => $vendorDir . '/symfony/form/NativeRequestHandler.php', - 'Symfony\\Component\\Form\\PreloadedExtension' => $vendorDir . '/symfony/form/PreloadedExtension.php', - 'Symfony\\Component\\Form\\RequestHandlerInterface' => $vendorDir . '/symfony/form/RequestHandlerInterface.php', - 'Symfony\\Component\\Form\\ResolvedFormType' => $vendorDir . '/symfony/form/ResolvedFormType.php', - 'Symfony\\Component\\Form\\ResolvedFormTypeFactory' => $vendorDir . '/symfony/form/ResolvedFormTypeFactory.php', - 'Symfony\\Component\\Form\\ResolvedFormTypeFactoryInterface' => $vendorDir . '/symfony/form/ResolvedFormTypeFactoryInterface.php', - 'Symfony\\Component\\Form\\ResolvedFormTypeInterface' => $vendorDir . '/symfony/form/ResolvedFormTypeInterface.php', - 'Symfony\\Component\\Form\\ReversedTransformer' => $vendorDir . '/symfony/form/ReversedTransformer.php', - 'Symfony\\Component\\Form\\SubmitButton' => $vendorDir . '/symfony/form/SubmitButton.php', - 'Symfony\\Component\\Form\\SubmitButtonBuilder' => $vendorDir . '/symfony/form/SubmitButtonBuilder.php', - 'Symfony\\Component\\Form\\SubmitButtonTypeInterface' => $vendorDir . '/symfony/form/SubmitButtonTypeInterface.php', - 'Symfony\\Component\\Form\\Test\\FormBuilderInterface' => $vendorDir . '/symfony/form/Test/FormBuilderInterface.php', - 'Symfony\\Component\\Form\\Test\\FormIntegrationTestCase' => $vendorDir . '/symfony/form/Test/FormIntegrationTestCase.php', - 'Symfony\\Component\\Form\\Test\\FormInterface' => $vendorDir . '/symfony/form/Test/FormInterface.php', - 'Symfony\\Component\\Form\\Test\\FormPerformanceTestCase' => $vendorDir . '/symfony/form/Test/FormPerformanceTestCase.php', - 'Symfony\\Component\\Form\\Test\\Traits\\ValidatorExtensionTrait' => $vendorDir . '/symfony/form/Test/Traits/ValidatorExtensionTrait.php', - 'Symfony\\Component\\Form\\Test\\TypeTestCase' => $vendorDir . '/symfony/form/Test/TypeTestCase.php', - 'Symfony\\Component\\Form\\Util\\FormUtil' => $vendorDir . '/symfony/form/Util/FormUtil.php', - 'Symfony\\Component\\Form\\Util\\InheritDataAwareIterator' => $vendorDir . '/symfony/form/Util/InheritDataAwareIterator.php', - 'Symfony\\Component\\Form\\Util\\OptionsResolverWrapper' => $vendorDir . '/symfony/form/Util/OptionsResolverWrapper.php', - 'Symfony\\Component\\Form\\Util\\OrderedHashMap' => $vendorDir . '/symfony/form/Util/OrderedHashMap.php', - 'Symfony\\Component\\Form\\Util\\OrderedHashMapIterator' => $vendorDir . '/symfony/form/Util/OrderedHashMapIterator.php', - 'Symfony\\Component\\Form\\Util\\ServerParams' => $vendorDir . '/symfony/form/Util/ServerParams.php', - 'Symfony\\Component\\Form\\Util\\StringUtil' => $vendorDir . '/symfony/form/Util/StringUtil.php', - 'Symfony\\Component\\HttpFoundation\\AcceptHeader' => $vendorDir . '/symfony/http-foundation/AcceptHeader.php', - 'Symfony\\Component\\HttpFoundation\\AcceptHeaderItem' => $vendorDir . '/symfony/http-foundation/AcceptHeaderItem.php', - 'Symfony\\Component\\HttpFoundation\\BinaryFileResponse' => $vendorDir . '/symfony/http-foundation/BinaryFileResponse.php', - 'Symfony\\Component\\HttpFoundation\\Cookie' => $vendorDir . '/symfony/http-foundation/Cookie.php', - 'Symfony\\Component\\HttpFoundation\\Exception\\BadRequestException' => $vendorDir . '/symfony/http-foundation/Exception/BadRequestException.php', - 'Symfony\\Component\\HttpFoundation\\Exception\\ConflictingHeadersException' => $vendorDir . '/symfony/http-foundation/Exception/ConflictingHeadersException.php', - 'Symfony\\Component\\HttpFoundation\\Exception\\JsonException' => $vendorDir . '/symfony/http-foundation/Exception/JsonException.php', - 'Symfony\\Component\\HttpFoundation\\Exception\\RequestExceptionInterface' => $vendorDir . '/symfony/http-foundation/Exception/RequestExceptionInterface.php', - 'Symfony\\Component\\HttpFoundation\\Exception\\SessionNotFoundException' => $vendorDir . '/symfony/http-foundation/Exception/SessionNotFoundException.php', - 'Symfony\\Component\\HttpFoundation\\Exception\\SuspiciousOperationException' => $vendorDir . '/symfony/http-foundation/Exception/SuspiciousOperationException.php', - 'Symfony\\Component\\HttpFoundation\\ExpressionRequestMatcher' => $vendorDir . '/symfony/http-foundation/ExpressionRequestMatcher.php', - 'Symfony\\Component\\HttpFoundation\\FileBag' => $vendorDir . '/symfony/http-foundation/FileBag.php', - 'Symfony\\Component\\HttpFoundation\\File\\Exception\\AccessDeniedException' => $vendorDir . '/symfony/http-foundation/File/Exception/AccessDeniedException.php', - 'Symfony\\Component\\HttpFoundation\\File\\Exception\\CannotWriteFileException' => $vendorDir . '/symfony/http-foundation/File/Exception/CannotWriteFileException.php', - 'Symfony\\Component\\HttpFoundation\\File\\Exception\\ExtensionFileException' => $vendorDir . '/symfony/http-foundation/File/Exception/ExtensionFileException.php', - 'Symfony\\Component\\HttpFoundation\\File\\Exception\\FileException' => $vendorDir . '/symfony/http-foundation/File/Exception/FileException.php', - 'Symfony\\Component\\HttpFoundation\\File\\Exception\\FileNotFoundException' => $vendorDir . '/symfony/http-foundation/File/Exception/FileNotFoundException.php', - 'Symfony\\Component\\HttpFoundation\\File\\Exception\\FormSizeFileException' => $vendorDir . '/symfony/http-foundation/File/Exception/FormSizeFileException.php', - 'Symfony\\Component\\HttpFoundation\\File\\Exception\\IniSizeFileException' => $vendorDir . '/symfony/http-foundation/File/Exception/IniSizeFileException.php', - 'Symfony\\Component\\HttpFoundation\\File\\Exception\\NoFileException' => $vendorDir . '/symfony/http-foundation/File/Exception/NoFileException.php', - 'Symfony\\Component\\HttpFoundation\\File\\Exception\\NoTmpDirFileException' => $vendorDir . '/symfony/http-foundation/File/Exception/NoTmpDirFileException.php', - 'Symfony\\Component\\HttpFoundation\\File\\Exception\\PartialFileException' => $vendorDir . '/symfony/http-foundation/File/Exception/PartialFileException.php', - 'Symfony\\Component\\HttpFoundation\\File\\Exception\\UnexpectedTypeException' => $vendorDir . '/symfony/http-foundation/File/Exception/UnexpectedTypeException.php', - 'Symfony\\Component\\HttpFoundation\\File\\Exception\\UploadException' => $vendorDir . '/symfony/http-foundation/File/Exception/UploadException.php', - 'Symfony\\Component\\HttpFoundation\\File\\File' => $vendorDir . '/symfony/http-foundation/File/File.php', - 'Symfony\\Component\\HttpFoundation\\File\\Stream' => $vendorDir . '/symfony/http-foundation/File/Stream.php', - 'Symfony\\Component\\HttpFoundation\\File\\UploadedFile' => $vendorDir . '/symfony/http-foundation/File/UploadedFile.php', - 'Symfony\\Component\\HttpFoundation\\HeaderBag' => $vendorDir . '/symfony/http-foundation/HeaderBag.php', - 'Symfony\\Component\\HttpFoundation\\HeaderUtils' => $vendorDir . '/symfony/http-foundation/HeaderUtils.php', - 'Symfony\\Component\\HttpFoundation\\InputBag' => $vendorDir . '/symfony/http-foundation/InputBag.php', - 'Symfony\\Component\\HttpFoundation\\IpUtils' => $vendorDir . '/symfony/http-foundation/IpUtils.php', - 'Symfony\\Component\\HttpFoundation\\JsonResponse' => $vendorDir . '/symfony/http-foundation/JsonResponse.php', - 'Symfony\\Component\\HttpFoundation\\ParameterBag' => $vendorDir . '/symfony/http-foundation/ParameterBag.php', - 'Symfony\\Component\\HttpFoundation\\RateLimiter\\AbstractRequestRateLimiter' => $vendorDir . '/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php', - 'Symfony\\Component\\HttpFoundation\\RateLimiter\\RequestRateLimiterInterface' => $vendorDir . '/symfony/http-foundation/RateLimiter/RequestRateLimiterInterface.php', - 'Symfony\\Component\\HttpFoundation\\RedirectResponse' => $vendorDir . '/symfony/http-foundation/RedirectResponse.php', - 'Symfony\\Component\\HttpFoundation\\Request' => $vendorDir . '/symfony/http-foundation/Request.php', - 'Symfony\\Component\\HttpFoundation\\RequestMatcher' => $vendorDir . '/symfony/http-foundation/RequestMatcher.php', - 'Symfony\\Component\\HttpFoundation\\RequestMatcherInterface' => $vendorDir . '/symfony/http-foundation/RequestMatcherInterface.php', - 'Symfony\\Component\\HttpFoundation\\RequestStack' => $vendorDir . '/symfony/http-foundation/RequestStack.php', - 'Symfony\\Component\\HttpFoundation\\Response' => $vendorDir . '/symfony/http-foundation/Response.php', - 'Symfony\\Component\\HttpFoundation\\ResponseHeaderBag' => $vendorDir . '/symfony/http-foundation/ResponseHeaderBag.php', - 'Symfony\\Component\\HttpFoundation\\ServerBag' => $vendorDir . '/symfony/http-foundation/ServerBag.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBag' => $vendorDir . '/symfony/http-foundation/Session/Attribute/AttributeBag.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBagInterface' => $vendorDir . '/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Attribute\\NamespacedAttributeBag' => $vendorDir . '/symfony/http-foundation/Session/Attribute/NamespacedAttributeBag.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Flash\\AutoExpireFlashBag' => $vendorDir . '/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Flash\\FlashBag' => $vendorDir . '/symfony/http-foundation/Session/Flash/FlashBag.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Flash\\FlashBagInterface' => $vendorDir . '/symfony/http-foundation/Session/Flash/FlashBagInterface.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Session' => $vendorDir . '/symfony/http-foundation/Session/Session.php', - 'Symfony\\Component\\HttpFoundation\\Session\\SessionBagInterface' => $vendorDir . '/symfony/http-foundation/Session/SessionBagInterface.php', - 'Symfony\\Component\\HttpFoundation\\Session\\SessionBagProxy' => $vendorDir . '/symfony/http-foundation/Session/SessionBagProxy.php', - 'Symfony\\Component\\HttpFoundation\\Session\\SessionFactory' => $vendorDir . '/symfony/http-foundation/Session/SessionFactory.php', - 'Symfony\\Component\\HttpFoundation\\Session\\SessionFactoryInterface' => $vendorDir . '/symfony/http-foundation/Session/SessionFactoryInterface.php', - 'Symfony\\Component\\HttpFoundation\\Session\\SessionInterface' => $vendorDir . '/symfony/http-foundation/Session/SessionInterface.php', - 'Symfony\\Component\\HttpFoundation\\Session\\SessionUtils' => $vendorDir . '/symfony/http-foundation/Session/SessionUtils.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\AbstractSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\IdentityMarshaller' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/IdentityMarshaller.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MarshallingSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MemcachedSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MigratingSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MongoDbSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NativeFileSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NullSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\PdoSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\RedisSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\SessionHandlerFactory' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\StrictSessionHandler' => $vendorDir . '/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\MetadataBag' => $vendorDir . '/symfony/http-foundation/Session/Storage/MetadataBag.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\MockArraySessionStorage' => $vendorDir . '/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\MockFileSessionStorage' => $vendorDir . '/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\MockFileSessionStorageFactory' => $vendorDir . '/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorage' => $vendorDir . '/symfony/http-foundation/Session/Storage/NativeSessionStorage.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorageFactory' => $vendorDir . '/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\PhpBridgeSessionStorage' => $vendorDir . '/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\PhpBridgeSessionStorageFactory' => $vendorDir . '/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\AbstractProxy' => $vendorDir . '/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\SessionHandlerProxy' => $vendorDir . '/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\ServiceSessionFactory' => $vendorDir . '/symfony/http-foundation/Session/Storage/ServiceSessionFactory.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\SessionStorageFactoryInterface' => $vendorDir . '/symfony/http-foundation/Session/Storage/SessionStorageFactoryInterface.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\SessionStorageInterface' => $vendorDir . '/symfony/http-foundation/Session/Storage/SessionStorageInterface.php', - 'Symfony\\Component\\HttpFoundation\\StreamedResponse' => $vendorDir . '/symfony/http-foundation/StreamedResponse.php', - 'Symfony\\Component\\HttpFoundation\\UrlHelper' => $vendorDir . '/symfony/http-foundation/UrlHelper.php', - 'Symfony\\Component\\HttpKernel\\Attribute\\ArgumentInterface' => $vendorDir . '/symfony/http-kernel/Attribute/ArgumentInterface.php', - 'Symfony\\Component\\HttpKernel\\Attribute\\AsController' => $vendorDir . '/symfony/http-kernel/Attribute/AsController.php', - 'Symfony\\Component\\HttpKernel\\Bundle\\Bundle' => $vendorDir . '/symfony/http-kernel/Bundle/Bundle.php', - 'Symfony\\Component\\HttpKernel\\Bundle\\BundleInterface' => $vendorDir . '/symfony/http-kernel/Bundle/BundleInterface.php', - 'Symfony\\Component\\HttpKernel\\CacheClearer\\CacheClearerInterface' => $vendorDir . '/symfony/http-kernel/CacheClearer/CacheClearerInterface.php', - 'Symfony\\Component\\HttpKernel\\CacheClearer\\ChainCacheClearer' => $vendorDir . '/symfony/http-kernel/CacheClearer/ChainCacheClearer.php', - 'Symfony\\Component\\HttpKernel\\CacheClearer\\Psr6CacheClearer' => $vendorDir . '/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php', - 'Symfony\\Component\\HttpKernel\\CacheWarmer\\CacheWarmer' => $vendorDir . '/symfony/http-kernel/CacheWarmer/CacheWarmer.php', - 'Symfony\\Component\\HttpKernel\\CacheWarmer\\CacheWarmerAggregate' => $vendorDir . '/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php', - 'Symfony\\Component\\HttpKernel\\CacheWarmer\\CacheWarmerInterface' => $vendorDir . '/symfony/http-kernel/CacheWarmer/CacheWarmerInterface.php', - 'Symfony\\Component\\HttpKernel\\CacheWarmer\\WarmableInterface' => $vendorDir . '/symfony/http-kernel/CacheWarmer/WarmableInterface.php', - 'Symfony\\Component\\HttpKernel\\Config\\FileLocator' => $vendorDir . '/symfony/http-kernel/Config/FileLocator.php', - 'Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadata' => $vendorDir . '/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php', - 'Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadataFactory' => $vendorDir . '/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php', - 'Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadataFactoryInterface' => $vendorDir . '/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolverInterface' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolverInterface.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\DefaultValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\NotTaggedControllerValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestAttributeValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\ServiceValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\SessionValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\TraceableValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\VariadicValueResolver' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentValueResolverInterface' => $vendorDir . '/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ContainerControllerResolver' => $vendorDir . '/symfony/http-kernel/Controller/ContainerControllerResolver.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ControllerReference' => $vendorDir . '/symfony/http-kernel/Controller/ControllerReference.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver' => $vendorDir . '/symfony/http-kernel/Controller/ControllerResolver.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface' => $vendorDir . '/symfony/http-kernel/Controller/ControllerResolverInterface.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ErrorController' => $vendorDir . '/symfony/http-kernel/Controller/ErrorController.php', - 'Symfony\\Component\\HttpKernel\\Controller\\TraceableArgumentResolver' => $vendorDir . '/symfony/http-kernel/Controller/TraceableArgumentResolver.php', - 'Symfony\\Component\\HttpKernel\\Controller\\TraceableControllerResolver' => $vendorDir . '/symfony/http-kernel/Controller/TraceableControllerResolver.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\AjaxDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/AjaxDataCollector.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\ConfigDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/ConfigDataCollector.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\DataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/DataCollector.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\DataCollectorInterface' => $vendorDir . '/symfony/http-kernel/DataCollector/DataCollectorInterface.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\DumpDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/DumpDataCollector.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\EventDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/EventDataCollector.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\ExceptionDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/ExceptionDataCollector.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\LateDataCollectorInterface' => $vendorDir . '/symfony/http-kernel/DataCollector/LateDataCollectorInterface.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\LoggerDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/LoggerDataCollector.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\MemoryDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/MemoryDataCollector.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\RequestDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/RequestDataCollector.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\RouterDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/RouterDataCollector.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\TimeDataCollector' => $vendorDir . '/symfony/http-kernel/DataCollector/TimeDataCollector.php', - 'Symfony\\Component\\HttpKernel\\Debug\\FileLinkFormatter' => $vendorDir . '/symfony/http-kernel/Debug/FileLinkFormatter.php', - 'Symfony\\Component\\HttpKernel\\Debug\\TraceableEventDispatcher' => $vendorDir . '/symfony/http-kernel/Debug/TraceableEventDispatcher.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\AddAnnotatedClassesToCachePass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\ConfigurableExtension' => $vendorDir . '/symfony/http-kernel/DependencyInjection/ConfigurableExtension.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\ControllerArgumentValueResolverPass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\Extension' => $vendorDir . '/symfony/http-kernel/DependencyInjection/Extension.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\FragmentRendererPass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\LazyLoadingFragmentHandler' => $vendorDir . '/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\LoggerPass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/LoggerPass.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\MergeExtensionConfigurationPass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\RegisterControllerArgumentLocatorsPass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\RegisterLocaleAwareServicesPass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/RegisterLocaleAwareServicesPass.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\RemoveEmptyControllerArgumentLocatorsPass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\ResettableServicePass' => $vendorDir . '/symfony/http-kernel/DependencyInjection/ResettableServicePass.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\ServicesResetter' => $vendorDir . '/symfony/http-kernel/DependencyInjection/ServicesResetter.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\AbstractSessionListener' => $vendorDir . '/symfony/http-kernel/EventListener/AbstractSessionListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\AbstractTestSessionListener' => $vendorDir . '/symfony/http-kernel/EventListener/AbstractTestSessionListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\AddRequestFormatsListener' => $vendorDir . '/symfony/http-kernel/EventListener/AddRequestFormatsListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\DebugHandlersListener' => $vendorDir . '/symfony/http-kernel/EventListener/DebugHandlersListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\DisallowRobotsIndexingListener' => $vendorDir . '/symfony/http-kernel/EventListener/DisallowRobotsIndexingListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\DumpListener' => $vendorDir . '/symfony/http-kernel/EventListener/DumpListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\ErrorListener' => $vendorDir . '/symfony/http-kernel/EventListener/ErrorListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\FragmentListener' => $vendorDir . '/symfony/http-kernel/EventListener/FragmentListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\LocaleAwareListener' => $vendorDir . '/symfony/http-kernel/EventListener/LocaleAwareListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\LocaleListener' => $vendorDir . '/symfony/http-kernel/EventListener/LocaleListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\ProfilerListener' => $vendorDir . '/symfony/http-kernel/EventListener/ProfilerListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\ResponseListener' => $vendorDir . '/symfony/http-kernel/EventListener/ResponseListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\RouterListener' => $vendorDir . '/symfony/http-kernel/EventListener/RouterListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\SessionListener' => $vendorDir . '/symfony/http-kernel/EventListener/SessionListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\StreamedResponseListener' => $vendorDir . '/symfony/http-kernel/EventListener/StreamedResponseListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\SurrogateListener' => $vendorDir . '/symfony/http-kernel/EventListener/SurrogateListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\TestSessionListener' => $vendorDir . '/symfony/http-kernel/EventListener/TestSessionListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\ValidateRequestListener' => $vendorDir . '/symfony/http-kernel/EventListener/ValidateRequestListener.php', - 'Symfony\\Component\\HttpKernel\\Event\\ControllerArgumentsEvent' => $vendorDir . '/symfony/http-kernel/Event/ControllerArgumentsEvent.php', - 'Symfony\\Component\\HttpKernel\\Event\\ControllerEvent' => $vendorDir . '/symfony/http-kernel/Event/ControllerEvent.php', - 'Symfony\\Component\\HttpKernel\\Event\\ExceptionEvent' => $vendorDir . '/symfony/http-kernel/Event/ExceptionEvent.php', - 'Symfony\\Component\\HttpKernel\\Event\\FinishRequestEvent' => $vendorDir . '/symfony/http-kernel/Event/FinishRequestEvent.php', - 'Symfony\\Component\\HttpKernel\\Event\\KernelEvent' => $vendorDir . '/symfony/http-kernel/Event/KernelEvent.php', - 'Symfony\\Component\\HttpKernel\\Event\\RequestEvent' => $vendorDir . '/symfony/http-kernel/Event/RequestEvent.php', - 'Symfony\\Component\\HttpKernel\\Event\\ResponseEvent' => $vendorDir . '/symfony/http-kernel/Event/ResponseEvent.php', - 'Symfony\\Component\\HttpKernel\\Event\\TerminateEvent' => $vendorDir . '/symfony/http-kernel/Event/TerminateEvent.php', - 'Symfony\\Component\\HttpKernel\\Event\\ViewEvent' => $vendorDir . '/symfony/http-kernel/Event/ViewEvent.php', - 'Symfony\\Component\\HttpKernel\\Exception\\AccessDeniedHttpException' => $vendorDir . '/symfony/http-kernel/Exception/AccessDeniedHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\BadRequestHttpException' => $vendorDir . '/symfony/http-kernel/Exception/BadRequestHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\ConflictHttpException' => $vendorDir . '/symfony/http-kernel/Exception/ConflictHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\ControllerDoesNotReturnResponseException' => $vendorDir . '/symfony/http-kernel/Exception/ControllerDoesNotReturnResponseException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\GoneHttpException' => $vendorDir . '/symfony/http-kernel/Exception/GoneHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\HttpException' => $vendorDir . '/symfony/http-kernel/Exception/HttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\HttpExceptionInterface' => $vendorDir . '/symfony/http-kernel/Exception/HttpExceptionInterface.php', - 'Symfony\\Component\\HttpKernel\\Exception\\InvalidMetadataException' => $vendorDir . '/symfony/http-kernel/Exception/InvalidMetadataException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\LengthRequiredHttpException' => $vendorDir . '/symfony/http-kernel/Exception/LengthRequiredHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\MethodNotAllowedHttpException' => $vendorDir . '/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\NotAcceptableHttpException' => $vendorDir . '/symfony/http-kernel/Exception/NotAcceptableHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException' => $vendorDir . '/symfony/http-kernel/Exception/NotFoundHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\PreconditionFailedHttpException' => $vendorDir . '/symfony/http-kernel/Exception/PreconditionFailedHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\PreconditionRequiredHttpException' => $vendorDir . '/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\ServiceUnavailableHttpException' => $vendorDir . '/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\TooManyRequestsHttpException' => $vendorDir . '/symfony/http-kernel/Exception/TooManyRequestsHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException' => $vendorDir . '/symfony/http-kernel/Exception/UnauthorizedHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\UnexpectedSessionUsageException' => $vendorDir . '/symfony/http-kernel/Exception/UnexpectedSessionUsageException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\UnprocessableEntityHttpException' => $vendorDir . '/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\UnsupportedMediaTypeHttpException' => $vendorDir . '/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php', - 'Symfony\\Component\\HttpKernel\\Fragment\\AbstractSurrogateFragmentRenderer' => $vendorDir . '/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php', - 'Symfony\\Component\\HttpKernel\\Fragment\\EsiFragmentRenderer' => $vendorDir . '/symfony/http-kernel/Fragment/EsiFragmentRenderer.php', - 'Symfony\\Component\\HttpKernel\\Fragment\\FragmentHandler' => $vendorDir . '/symfony/http-kernel/Fragment/FragmentHandler.php', - 'Symfony\\Component\\HttpKernel\\Fragment\\FragmentRendererInterface' => $vendorDir . '/symfony/http-kernel/Fragment/FragmentRendererInterface.php', - 'Symfony\\Component\\HttpKernel\\Fragment\\FragmentUriGenerator' => $vendorDir . '/symfony/http-kernel/Fragment/FragmentUriGenerator.php', - 'Symfony\\Component\\HttpKernel\\Fragment\\FragmentUriGeneratorInterface' => $vendorDir . '/symfony/http-kernel/Fragment/FragmentUriGeneratorInterface.php', - 'Symfony\\Component\\HttpKernel\\Fragment\\HIncludeFragmentRenderer' => $vendorDir . '/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php', - 'Symfony\\Component\\HttpKernel\\Fragment\\InlineFragmentRenderer' => $vendorDir . '/symfony/http-kernel/Fragment/InlineFragmentRenderer.php', - 'Symfony\\Component\\HttpKernel\\Fragment\\RoutableFragmentRenderer' => $vendorDir . '/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php', - 'Symfony\\Component\\HttpKernel\\Fragment\\SsiFragmentRenderer' => $vendorDir . '/symfony/http-kernel/Fragment/SsiFragmentRenderer.php', - 'Symfony\\Component\\HttpKernel\\HttpCache\\AbstractSurrogate' => $vendorDir . '/symfony/http-kernel/HttpCache/AbstractSurrogate.php', - 'Symfony\\Component\\HttpKernel\\HttpCache\\Esi' => $vendorDir . '/symfony/http-kernel/HttpCache/Esi.php', - 'Symfony\\Component\\HttpKernel\\HttpCache\\HttpCache' => $vendorDir . '/symfony/http-kernel/HttpCache/HttpCache.php', - 'Symfony\\Component\\HttpKernel\\HttpCache\\ResponseCacheStrategy' => $vendorDir . '/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php', - 'Symfony\\Component\\HttpKernel\\HttpCache\\ResponseCacheStrategyInterface' => $vendorDir . '/symfony/http-kernel/HttpCache/ResponseCacheStrategyInterface.php', - 'Symfony\\Component\\HttpKernel\\HttpCache\\Ssi' => $vendorDir . '/symfony/http-kernel/HttpCache/Ssi.php', - 'Symfony\\Component\\HttpKernel\\HttpCache\\Store' => $vendorDir . '/symfony/http-kernel/HttpCache/Store.php', - 'Symfony\\Component\\HttpKernel\\HttpCache\\StoreInterface' => $vendorDir . '/symfony/http-kernel/HttpCache/StoreInterface.php', - 'Symfony\\Component\\HttpKernel\\HttpCache\\SubRequestHandler' => $vendorDir . '/symfony/http-kernel/HttpCache/SubRequestHandler.php', - 'Symfony\\Component\\HttpKernel\\HttpCache\\SurrogateInterface' => $vendorDir . '/symfony/http-kernel/HttpCache/SurrogateInterface.php', - 'Symfony\\Component\\HttpKernel\\HttpClientKernel' => $vendorDir . '/symfony/http-kernel/HttpClientKernel.php', - 'Symfony\\Component\\HttpKernel\\HttpKernel' => $vendorDir . '/symfony/http-kernel/HttpKernel.php', - 'Symfony\\Component\\HttpKernel\\HttpKernelBrowser' => $vendorDir . '/symfony/http-kernel/HttpKernelBrowser.php', - 'Symfony\\Component\\HttpKernel\\HttpKernelInterface' => $vendorDir . '/symfony/http-kernel/HttpKernelInterface.php', - 'Symfony\\Component\\HttpKernel\\Kernel' => $vendorDir . '/symfony/http-kernel/Kernel.php', - 'Symfony\\Component\\HttpKernel\\KernelEvents' => $vendorDir . '/symfony/http-kernel/KernelEvents.php', - 'Symfony\\Component\\HttpKernel\\KernelInterface' => $vendorDir . '/symfony/http-kernel/KernelInterface.php', - 'Symfony\\Component\\HttpKernel\\Log\\DebugLoggerInterface' => $vendorDir . '/symfony/http-kernel/Log/DebugLoggerInterface.php', - 'Symfony\\Component\\HttpKernel\\Log\\Logger' => $vendorDir . '/symfony/http-kernel/Log/Logger.php', - 'Symfony\\Component\\HttpKernel\\Profiler\\FileProfilerStorage' => $vendorDir . '/symfony/http-kernel/Profiler/FileProfilerStorage.php', - 'Symfony\\Component\\HttpKernel\\Profiler\\Profile' => $vendorDir . '/symfony/http-kernel/Profiler/Profile.php', - 'Symfony\\Component\\HttpKernel\\Profiler\\Profiler' => $vendorDir . '/symfony/http-kernel/Profiler/Profiler.php', - 'Symfony\\Component\\HttpKernel\\Profiler\\ProfilerStorageInterface' => $vendorDir . '/symfony/http-kernel/Profiler/ProfilerStorageInterface.php', - 'Symfony\\Component\\HttpKernel\\RebootableInterface' => $vendorDir . '/symfony/http-kernel/RebootableInterface.php', - 'Symfony\\Component\\HttpKernel\\TerminableInterface' => $vendorDir . '/symfony/http-kernel/TerminableInterface.php', - 'Symfony\\Component\\HttpKernel\\UriSigner' => $vendorDir . '/symfony/http-kernel/UriSigner.php', - 'Symfony\\Component\\OptionsResolver\\Debug\\OptionsResolverIntrospector' => $vendorDir . '/symfony/options-resolver/Debug/OptionsResolverIntrospector.php', - 'Symfony\\Component\\OptionsResolver\\Exception\\AccessException' => $vendorDir . '/symfony/options-resolver/Exception/AccessException.php', - 'Symfony\\Component\\OptionsResolver\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/options-resolver/Exception/ExceptionInterface.php', - 'Symfony\\Component\\OptionsResolver\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/options-resolver/Exception/InvalidArgumentException.php', - 'Symfony\\Component\\OptionsResolver\\Exception\\InvalidOptionsException' => $vendorDir . '/symfony/options-resolver/Exception/InvalidOptionsException.php', - 'Symfony\\Component\\OptionsResolver\\Exception\\MissingOptionsException' => $vendorDir . '/symfony/options-resolver/Exception/MissingOptionsException.php', - 'Symfony\\Component\\OptionsResolver\\Exception\\NoConfigurationException' => $vendorDir . '/symfony/options-resolver/Exception/NoConfigurationException.php', - 'Symfony\\Component\\OptionsResolver\\Exception\\NoSuchOptionException' => $vendorDir . '/symfony/options-resolver/Exception/NoSuchOptionException.php', - 'Symfony\\Component\\OptionsResolver\\Exception\\OptionDefinitionException' => $vendorDir . '/symfony/options-resolver/Exception/OptionDefinitionException.php', - 'Symfony\\Component\\OptionsResolver\\Exception\\UndefinedOptionsException' => $vendorDir . '/symfony/options-resolver/Exception/UndefinedOptionsException.php', - 'Symfony\\Component\\OptionsResolver\\OptionConfigurator' => $vendorDir . '/symfony/options-resolver/OptionConfigurator.php', - 'Symfony\\Component\\OptionsResolver\\Options' => $vendorDir . '/symfony/options-resolver/Options.php', - 'Symfony\\Component\\OptionsResolver\\OptionsResolver' => $vendorDir . '/symfony/options-resolver/OptionsResolver.php', - 'Symfony\\Component\\PropertyAccess\\Exception\\AccessException' => $vendorDir . '/symfony/property-access/Exception/AccessException.php', - 'Symfony\\Component\\PropertyAccess\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/property-access/Exception/ExceptionInterface.php', - 'Symfony\\Component\\PropertyAccess\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/property-access/Exception/InvalidArgumentException.php', - 'Symfony\\Component\\PropertyAccess\\Exception\\InvalidPropertyPathException' => $vendorDir . '/symfony/property-access/Exception/InvalidPropertyPathException.php', - 'Symfony\\Component\\PropertyAccess\\Exception\\NoSuchIndexException' => $vendorDir . '/symfony/property-access/Exception/NoSuchIndexException.php', - 'Symfony\\Component\\PropertyAccess\\Exception\\NoSuchPropertyException' => $vendorDir . '/symfony/property-access/Exception/NoSuchPropertyException.php', - 'Symfony\\Component\\PropertyAccess\\Exception\\OutOfBoundsException' => $vendorDir . '/symfony/property-access/Exception/OutOfBoundsException.php', - 'Symfony\\Component\\PropertyAccess\\Exception\\RuntimeException' => $vendorDir . '/symfony/property-access/Exception/RuntimeException.php', - 'Symfony\\Component\\PropertyAccess\\Exception\\UnexpectedTypeException' => $vendorDir . '/symfony/property-access/Exception/UnexpectedTypeException.php', - 'Symfony\\Component\\PropertyAccess\\Exception\\UninitializedPropertyException' => $vendorDir . '/symfony/property-access/Exception/UninitializedPropertyException.php', - 'Symfony\\Component\\PropertyAccess\\PropertyAccess' => $vendorDir . '/symfony/property-access/PropertyAccess.php', - 'Symfony\\Component\\PropertyAccess\\PropertyAccessor' => $vendorDir . '/symfony/property-access/PropertyAccessor.php', - 'Symfony\\Component\\PropertyAccess\\PropertyAccessorBuilder' => $vendorDir . '/symfony/property-access/PropertyAccessorBuilder.php', - 'Symfony\\Component\\PropertyAccess\\PropertyAccessorInterface' => $vendorDir . '/symfony/property-access/PropertyAccessorInterface.php', - 'Symfony\\Component\\PropertyAccess\\PropertyPath' => $vendorDir . '/symfony/property-access/PropertyPath.php', - 'Symfony\\Component\\PropertyAccess\\PropertyPathBuilder' => $vendorDir . '/symfony/property-access/PropertyPathBuilder.php', - 'Symfony\\Component\\PropertyAccess\\PropertyPathInterface' => $vendorDir . '/symfony/property-access/PropertyPathInterface.php', - 'Symfony\\Component\\PropertyAccess\\PropertyPathIterator' => $vendorDir . '/symfony/property-access/PropertyPathIterator.php', - 'Symfony\\Component\\PropertyAccess\\PropertyPathIteratorInterface' => $vendorDir . '/symfony/property-access/PropertyPathIteratorInterface.php', - 'Symfony\\Component\\PropertyInfo\\DependencyInjection\\PropertyInfoConstructorPass' => $vendorDir . '/symfony/property-info/DependencyInjection/PropertyInfoConstructorPass.php', - 'Symfony\\Component\\PropertyInfo\\DependencyInjection\\PropertyInfoPass' => $vendorDir . '/symfony/property-info/DependencyInjection/PropertyInfoPass.php', - 'Symfony\\Component\\PropertyInfo\\Extractor\\ConstructorArgumentTypeExtractorInterface' => $vendorDir . '/symfony/property-info/Extractor/ConstructorArgumentTypeExtractorInterface.php', - 'Symfony\\Component\\PropertyInfo\\Extractor\\ConstructorExtractor' => $vendorDir . '/symfony/property-info/Extractor/ConstructorExtractor.php', - 'Symfony\\Component\\PropertyInfo\\Extractor\\PhpDocExtractor' => $vendorDir . '/symfony/property-info/Extractor/PhpDocExtractor.php', - 'Symfony\\Component\\PropertyInfo\\Extractor\\PhpStanExtractor' => $vendorDir . '/symfony/property-info/Extractor/PhpStanExtractor.php', - 'Symfony\\Component\\PropertyInfo\\Extractor\\ReflectionExtractor' => $vendorDir . '/symfony/property-info/Extractor/ReflectionExtractor.php', - 'Symfony\\Component\\PropertyInfo\\Extractor\\SerializerExtractor' => $vendorDir . '/symfony/property-info/Extractor/SerializerExtractor.php', - 'Symfony\\Component\\PropertyInfo\\PhpStan\\NameScope' => $vendorDir . '/symfony/property-info/PhpStan/NameScope.php', - 'Symfony\\Component\\PropertyInfo\\PhpStan\\NameScopeFactory' => $vendorDir . '/symfony/property-info/PhpStan/NameScopeFactory.php', - 'Symfony\\Component\\PropertyInfo\\PropertyAccessExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyAccessExtractorInterface.php', - 'Symfony\\Component\\PropertyInfo\\PropertyDescriptionExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyDescriptionExtractorInterface.php', - 'Symfony\\Component\\PropertyInfo\\PropertyInfoCacheExtractor' => $vendorDir . '/symfony/property-info/PropertyInfoCacheExtractor.php', - 'Symfony\\Component\\PropertyInfo\\PropertyInfoExtractor' => $vendorDir . '/symfony/property-info/PropertyInfoExtractor.php', - 'Symfony\\Component\\PropertyInfo\\PropertyInfoExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyInfoExtractorInterface.php', - 'Symfony\\Component\\PropertyInfo\\PropertyInitializableExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyInitializableExtractorInterface.php', - 'Symfony\\Component\\PropertyInfo\\PropertyListExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyListExtractorInterface.php', - 'Symfony\\Component\\PropertyInfo\\PropertyReadInfo' => $vendorDir . '/symfony/property-info/PropertyReadInfo.php', - 'Symfony\\Component\\PropertyInfo\\PropertyReadInfoExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyReadInfoExtractorInterface.php', - 'Symfony\\Component\\PropertyInfo\\PropertyTypeExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyTypeExtractorInterface.php', - 'Symfony\\Component\\PropertyInfo\\PropertyWriteInfo' => $vendorDir . '/symfony/property-info/PropertyWriteInfo.php', - 'Symfony\\Component\\PropertyInfo\\PropertyWriteInfoExtractorInterface' => $vendorDir . '/symfony/property-info/PropertyWriteInfoExtractorInterface.php', - 'Symfony\\Component\\PropertyInfo\\Type' => $vendorDir . '/symfony/property-info/Type.php', - 'Symfony\\Component\\PropertyInfo\\Util\\PhpDocTypeHelper' => $vendorDir . '/symfony/property-info/Util/PhpDocTypeHelper.php', - 'Symfony\\Component\\PropertyInfo\\Util\\PhpStanTypeHelper' => $vendorDir . '/symfony/property-info/Util/PhpStanTypeHelper.php', - 'Symfony\\Component\\Routing\\Alias' => $vendorDir . '/symfony/routing/Alias.php', - 'Symfony\\Component\\Routing\\Annotation\\Route' => $vendorDir . '/symfony/routing/Annotation/Route.php', - 'Symfony\\Component\\Routing\\CompiledRoute' => $vendorDir . '/symfony/routing/CompiledRoute.php', - 'Symfony\\Component\\Routing\\DependencyInjection\\RoutingResolverPass' => $vendorDir . '/symfony/routing/DependencyInjection/RoutingResolverPass.php', - 'Symfony\\Component\\Routing\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/routing/Exception/ExceptionInterface.php', - 'Symfony\\Component\\Routing\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/routing/Exception/InvalidArgumentException.php', - 'Symfony\\Component\\Routing\\Exception\\InvalidParameterException' => $vendorDir . '/symfony/routing/Exception/InvalidParameterException.php', - 'Symfony\\Component\\Routing\\Exception\\MethodNotAllowedException' => $vendorDir . '/symfony/routing/Exception/MethodNotAllowedException.php', - 'Symfony\\Component\\Routing\\Exception\\MissingMandatoryParametersException' => $vendorDir . '/symfony/routing/Exception/MissingMandatoryParametersException.php', - 'Symfony\\Component\\Routing\\Exception\\NoConfigurationException' => $vendorDir . '/symfony/routing/Exception/NoConfigurationException.php', - 'Symfony\\Component\\Routing\\Exception\\ResourceNotFoundException' => $vendorDir . '/symfony/routing/Exception/ResourceNotFoundException.php', - 'Symfony\\Component\\Routing\\Exception\\RouteCircularReferenceException' => $vendorDir . '/symfony/routing/Exception/RouteCircularReferenceException.php', - 'Symfony\\Component\\Routing\\Exception\\RouteNotFoundException' => $vendorDir . '/symfony/routing/Exception/RouteNotFoundException.php', - 'Symfony\\Component\\Routing\\Exception\\RuntimeException' => $vendorDir . '/symfony/routing/Exception/RuntimeException.php', - 'Symfony\\Component\\Routing\\Generator\\CompiledUrlGenerator' => $vendorDir . '/symfony/routing/Generator/CompiledUrlGenerator.php', - 'Symfony\\Component\\Routing\\Generator\\ConfigurableRequirementsInterface' => $vendorDir . '/symfony/routing/Generator/ConfigurableRequirementsInterface.php', - 'Symfony\\Component\\Routing\\Generator\\Dumper\\CompiledUrlGeneratorDumper' => $vendorDir . '/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php', - 'Symfony\\Component\\Routing\\Generator\\Dumper\\GeneratorDumper' => $vendorDir . '/symfony/routing/Generator/Dumper/GeneratorDumper.php', - 'Symfony\\Component\\Routing\\Generator\\Dumper\\GeneratorDumperInterface' => $vendorDir . '/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php', - 'Symfony\\Component\\Routing\\Generator\\UrlGenerator' => $vendorDir . '/symfony/routing/Generator/UrlGenerator.php', - 'Symfony\\Component\\Routing\\Generator\\UrlGeneratorInterface' => $vendorDir . '/symfony/routing/Generator/UrlGeneratorInterface.php', - 'Symfony\\Component\\Routing\\Loader\\AnnotationClassLoader' => $vendorDir . '/symfony/routing/Loader/AnnotationClassLoader.php', - 'Symfony\\Component\\Routing\\Loader\\AnnotationDirectoryLoader' => $vendorDir . '/symfony/routing/Loader/AnnotationDirectoryLoader.php', - 'Symfony\\Component\\Routing\\Loader\\AnnotationFileLoader' => $vendorDir . '/symfony/routing/Loader/AnnotationFileLoader.php', - 'Symfony\\Component\\Routing\\Loader\\ClosureLoader' => $vendorDir . '/symfony/routing/Loader/ClosureLoader.php', - 'Symfony\\Component\\Routing\\Loader\\Configurator\\AliasConfigurator' => $vendorDir . '/symfony/routing/Loader/Configurator/AliasConfigurator.php', - 'Symfony\\Component\\Routing\\Loader\\Configurator\\CollectionConfigurator' => $vendorDir . '/symfony/routing/Loader/Configurator/CollectionConfigurator.php', - 'Symfony\\Component\\Routing\\Loader\\Configurator\\ImportConfigurator' => $vendorDir . '/symfony/routing/Loader/Configurator/ImportConfigurator.php', - 'Symfony\\Component\\Routing\\Loader\\Configurator\\RouteConfigurator' => $vendorDir . '/symfony/routing/Loader/Configurator/RouteConfigurator.php', - 'Symfony\\Component\\Routing\\Loader\\Configurator\\RoutingConfigurator' => $vendorDir . '/symfony/routing/Loader/Configurator/RoutingConfigurator.php', - 'Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\AddTrait' => $vendorDir . '/symfony/routing/Loader/Configurator/Traits/AddTrait.php', - 'Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\HostTrait' => $vendorDir . '/symfony/routing/Loader/Configurator/Traits/HostTrait.php', - 'Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\LocalizedRouteTrait' => $vendorDir . '/symfony/routing/Loader/Configurator/Traits/LocalizedRouteTrait.php', - 'Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\PrefixTrait' => $vendorDir . '/symfony/routing/Loader/Configurator/Traits/PrefixTrait.php', - 'Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\RouteTrait' => $vendorDir . '/symfony/routing/Loader/Configurator/Traits/RouteTrait.php', - 'Symfony\\Component\\Routing\\Loader\\ContainerLoader' => $vendorDir . '/symfony/routing/Loader/ContainerLoader.php', - 'Symfony\\Component\\Routing\\Loader\\DirectoryLoader' => $vendorDir . '/symfony/routing/Loader/DirectoryLoader.php', - 'Symfony\\Component\\Routing\\Loader\\GlobFileLoader' => $vendorDir . '/symfony/routing/Loader/GlobFileLoader.php', - 'Symfony\\Component\\Routing\\Loader\\ObjectLoader' => $vendorDir . '/symfony/routing/Loader/ObjectLoader.php', - 'Symfony\\Component\\Routing\\Loader\\PhpFileLoader' => $vendorDir . '/symfony/routing/Loader/PhpFileLoader.php', - 'Symfony\\Component\\Routing\\Loader\\XmlFileLoader' => $vendorDir . '/symfony/routing/Loader/XmlFileLoader.php', - 'Symfony\\Component\\Routing\\Loader\\YamlFileLoader' => $vendorDir . '/symfony/routing/Loader/YamlFileLoader.php', - 'Symfony\\Component\\Routing\\Matcher\\CompiledUrlMatcher' => $vendorDir . '/symfony/routing/Matcher/CompiledUrlMatcher.php', - 'Symfony\\Component\\Routing\\Matcher\\Dumper\\CompiledUrlMatcherDumper' => $vendorDir . '/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php', - 'Symfony\\Component\\Routing\\Matcher\\Dumper\\CompiledUrlMatcherTrait' => $vendorDir . '/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php', - 'Symfony\\Component\\Routing\\Matcher\\Dumper\\MatcherDumper' => $vendorDir . '/symfony/routing/Matcher/Dumper/MatcherDumper.php', - 'Symfony\\Component\\Routing\\Matcher\\Dumper\\MatcherDumperInterface' => $vendorDir . '/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php', - 'Symfony\\Component\\Routing\\Matcher\\Dumper\\StaticPrefixCollection' => $vendorDir . '/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php', - 'Symfony\\Component\\Routing\\Matcher\\ExpressionLanguageProvider' => $vendorDir . '/symfony/routing/Matcher/ExpressionLanguageProvider.php', - 'Symfony\\Component\\Routing\\Matcher\\RedirectableUrlMatcher' => $vendorDir . '/symfony/routing/Matcher/RedirectableUrlMatcher.php', - 'Symfony\\Component\\Routing\\Matcher\\RedirectableUrlMatcherInterface' => $vendorDir . '/symfony/routing/Matcher/RedirectableUrlMatcherInterface.php', - 'Symfony\\Component\\Routing\\Matcher\\RequestMatcherInterface' => $vendorDir . '/symfony/routing/Matcher/RequestMatcherInterface.php', - 'Symfony\\Component\\Routing\\Matcher\\TraceableUrlMatcher' => $vendorDir . '/symfony/routing/Matcher/TraceableUrlMatcher.php', - 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher' => $vendorDir . '/symfony/routing/Matcher/UrlMatcher.php', - 'Symfony\\Component\\Routing\\Matcher\\UrlMatcherInterface' => $vendorDir . '/symfony/routing/Matcher/UrlMatcherInterface.php', - 'Symfony\\Component\\Routing\\RequestContext' => $vendorDir . '/symfony/routing/RequestContext.php', - 'Symfony\\Component\\Routing\\RequestContextAwareInterface' => $vendorDir . '/symfony/routing/RequestContextAwareInterface.php', - 'Symfony\\Component\\Routing\\Route' => $vendorDir . '/symfony/routing/Route.php', - 'Symfony\\Component\\Routing\\RouteCollection' => $vendorDir . '/symfony/routing/RouteCollection.php', - 'Symfony\\Component\\Routing\\RouteCollectionBuilder' => $vendorDir . '/symfony/routing/RouteCollectionBuilder.php', - 'Symfony\\Component\\Routing\\RouteCompiler' => $vendorDir . '/symfony/routing/RouteCompiler.php', - 'Symfony\\Component\\Routing\\RouteCompilerInterface' => $vendorDir . '/symfony/routing/RouteCompilerInterface.php', - 'Symfony\\Component\\Routing\\Router' => $vendorDir . '/symfony/routing/Router.php', - 'Symfony\\Component\\Routing\\RouterInterface' => $vendorDir . '/symfony/routing/RouterInterface.php', - 'Symfony\\Component\\Stopwatch\\Section' => $vendorDir . '/symfony/stopwatch/Section.php', - 'Symfony\\Component\\Stopwatch\\Stopwatch' => $vendorDir . '/symfony/stopwatch/Stopwatch.php', - 'Symfony\\Component\\Stopwatch\\StopwatchEvent' => $vendorDir . '/symfony/stopwatch/StopwatchEvent.php', - 'Symfony\\Component\\Stopwatch\\StopwatchPeriod' => $vendorDir . '/symfony/stopwatch/StopwatchPeriod.php', - 'Symfony\\Component\\String\\AbstractString' => $vendorDir . '/symfony/string/AbstractString.php', - 'Symfony\\Component\\String\\AbstractUnicodeString' => $vendorDir . '/symfony/string/AbstractUnicodeString.php', - 'Symfony\\Component\\String\\ByteString' => $vendorDir . '/symfony/string/ByteString.php', - 'Symfony\\Component\\String\\CodePointString' => $vendorDir . '/symfony/string/CodePointString.php', - 'Symfony\\Component\\String\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/string/Exception/ExceptionInterface.php', - 'Symfony\\Component\\String\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/string/Exception/InvalidArgumentException.php', - 'Symfony\\Component\\String\\Exception\\RuntimeException' => $vendorDir . '/symfony/string/Exception/RuntimeException.php', - 'Symfony\\Component\\String\\Inflector\\EnglishInflector' => $vendorDir . '/symfony/string/Inflector/EnglishInflector.php', - 'Symfony\\Component\\String\\Inflector\\FrenchInflector' => $vendorDir . '/symfony/string/Inflector/FrenchInflector.php', - 'Symfony\\Component\\String\\Inflector\\InflectorInterface' => $vendorDir . '/symfony/string/Inflector/InflectorInterface.php', - 'Symfony\\Component\\String\\LazyString' => $vendorDir . '/symfony/string/LazyString.php', - 'Symfony\\Component\\String\\Slugger\\AsciiSlugger' => $vendorDir . '/symfony/string/Slugger/AsciiSlugger.php', - 'Symfony\\Component\\String\\Slugger\\SluggerInterface' => $vendorDir . '/symfony/string/Slugger/SluggerInterface.php', - 'Symfony\\Component\\String\\UnicodeString' => $vendorDir . '/symfony/string/UnicodeString.php', - 'Symfony\\Component\\VarDumper\\Caster\\AmqpCaster' => $vendorDir . '/symfony/var-dumper/Caster/AmqpCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\ArgsStub' => $vendorDir . '/symfony/var-dumper/Caster/ArgsStub.php', - 'Symfony\\Component\\VarDumper\\Caster\\Caster' => $vendorDir . '/symfony/var-dumper/Caster/Caster.php', - 'Symfony\\Component\\VarDumper\\Caster\\ClassStub' => $vendorDir . '/symfony/var-dumper/Caster/ClassStub.php', - 'Symfony\\Component\\VarDumper\\Caster\\ConstStub' => $vendorDir . '/symfony/var-dumper/Caster/ConstStub.php', - 'Symfony\\Component\\VarDumper\\Caster\\CutArrayStub' => $vendorDir . '/symfony/var-dumper/Caster/CutArrayStub.php', - 'Symfony\\Component\\VarDumper\\Caster\\CutStub' => $vendorDir . '/symfony/var-dumper/Caster/CutStub.php', - 'Symfony\\Component\\VarDumper\\Caster\\DOMCaster' => $vendorDir . '/symfony/var-dumper/Caster/DOMCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\DateCaster' => $vendorDir . '/symfony/var-dumper/Caster/DateCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\DoctrineCaster' => $vendorDir . '/symfony/var-dumper/Caster/DoctrineCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\DsCaster' => $vendorDir . '/symfony/var-dumper/Caster/DsCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\DsPairStub' => $vendorDir . '/symfony/var-dumper/Caster/DsPairStub.php', - 'Symfony\\Component\\VarDumper\\Caster\\EnumStub' => $vendorDir . '/symfony/var-dumper/Caster/EnumStub.php', - 'Symfony\\Component\\VarDumper\\Caster\\ExceptionCaster' => $vendorDir . '/symfony/var-dumper/Caster/ExceptionCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\FiberCaster' => $vendorDir . '/symfony/var-dumper/Caster/FiberCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\FrameStub' => $vendorDir . '/symfony/var-dumper/Caster/FrameStub.php', - 'Symfony\\Component\\VarDumper\\Caster\\GmpCaster' => $vendorDir . '/symfony/var-dumper/Caster/GmpCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\ImagineCaster' => $vendorDir . '/symfony/var-dumper/Caster/ImagineCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\ImgStub' => $vendorDir . '/symfony/var-dumper/Caster/ImgStub.php', - 'Symfony\\Component\\VarDumper\\Caster\\IntlCaster' => $vendorDir . '/symfony/var-dumper/Caster/IntlCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\LinkStub' => $vendorDir . '/symfony/var-dumper/Caster/LinkStub.php', - 'Symfony\\Component\\VarDumper\\Caster\\MemcachedCaster' => $vendorDir . '/symfony/var-dumper/Caster/MemcachedCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\MysqliCaster' => $vendorDir . '/symfony/var-dumper/Caster/MysqliCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\PdoCaster' => $vendorDir . '/symfony/var-dumper/Caster/PdoCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\PgSqlCaster' => $vendorDir . '/symfony/var-dumper/Caster/PgSqlCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\ProxyManagerCaster' => $vendorDir . '/symfony/var-dumper/Caster/ProxyManagerCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster' => $vendorDir . '/symfony/var-dumper/Caster/RdKafkaCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\RedisCaster' => $vendorDir . '/symfony/var-dumper/Caster/RedisCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster' => $vendorDir . '/symfony/var-dumper/Caster/ReflectionCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\ResourceCaster' => $vendorDir . '/symfony/var-dumper/Caster/ResourceCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\SplCaster' => $vendorDir . '/symfony/var-dumper/Caster/SplCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\StubCaster' => $vendorDir . '/symfony/var-dumper/Caster/StubCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster' => $vendorDir . '/symfony/var-dumper/Caster/SymfonyCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\TraceStub' => $vendorDir . '/symfony/var-dumper/Caster/TraceStub.php', - 'Symfony\\Component\\VarDumper\\Caster\\UuidCaster' => $vendorDir . '/symfony/var-dumper/Caster/UuidCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\XmlReaderCaster' => $vendorDir . '/symfony/var-dumper/Caster/XmlReaderCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\XmlResourceCaster' => $vendorDir . '/symfony/var-dumper/Caster/XmlResourceCaster.php', - 'Symfony\\Component\\VarDumper\\Cloner\\AbstractCloner' => $vendorDir . '/symfony/var-dumper/Cloner/AbstractCloner.php', - 'Symfony\\Component\\VarDumper\\Cloner\\ClonerInterface' => $vendorDir . '/symfony/var-dumper/Cloner/ClonerInterface.php', - 'Symfony\\Component\\VarDumper\\Cloner\\Cursor' => $vendorDir . '/symfony/var-dumper/Cloner/Cursor.php', - 'Symfony\\Component\\VarDumper\\Cloner\\Data' => $vendorDir . '/symfony/var-dumper/Cloner/Data.php', - 'Symfony\\Component\\VarDumper\\Cloner\\DumperInterface' => $vendorDir . '/symfony/var-dumper/Cloner/DumperInterface.php', - 'Symfony\\Component\\VarDumper\\Cloner\\Stub' => $vendorDir . '/symfony/var-dumper/Cloner/Stub.php', - 'Symfony\\Component\\VarDumper\\Cloner\\VarCloner' => $vendorDir . '/symfony/var-dumper/Cloner/VarCloner.php', - 'Symfony\\Component\\VarDumper\\Command\\Descriptor\\CliDescriptor' => $vendorDir . '/symfony/var-dumper/Command/Descriptor/CliDescriptor.php', - 'Symfony\\Component\\VarDumper\\Command\\Descriptor\\DumpDescriptorInterface' => $vendorDir . '/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php', - 'Symfony\\Component\\VarDumper\\Command\\Descriptor\\HtmlDescriptor' => $vendorDir . '/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php', - 'Symfony\\Component\\VarDumper\\Command\\ServerDumpCommand' => $vendorDir . '/symfony/var-dumper/Command/ServerDumpCommand.php', - 'Symfony\\Component\\VarDumper\\Dumper\\AbstractDumper' => $vendorDir . '/symfony/var-dumper/Dumper/AbstractDumper.php', - 'Symfony\\Component\\VarDumper\\Dumper\\CliDumper' => $vendorDir . '/symfony/var-dumper/Dumper/CliDumper.php', - 'Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\CliContextProvider' => $vendorDir . '/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php', - 'Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\ContextProviderInterface' => $vendorDir . '/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php', - 'Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\RequestContextProvider' => $vendorDir . '/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php', - 'Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\SourceContextProvider' => $vendorDir . '/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php', - 'Symfony\\Component\\VarDumper\\Dumper\\ContextualizedDumper' => $vendorDir . '/symfony/var-dumper/Dumper/ContextualizedDumper.php', - 'Symfony\\Component\\VarDumper\\Dumper\\DataDumperInterface' => $vendorDir . '/symfony/var-dumper/Dumper/DataDumperInterface.php', - 'Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper' => $vendorDir . '/symfony/var-dumper/Dumper/HtmlDumper.php', - 'Symfony\\Component\\VarDumper\\Dumper\\ServerDumper' => $vendorDir . '/symfony/var-dumper/Dumper/ServerDumper.php', - 'Symfony\\Component\\VarDumper\\Exception\\ThrowingCasterException' => $vendorDir . '/symfony/var-dumper/Exception/ThrowingCasterException.php', - 'Symfony\\Component\\VarDumper\\Server\\Connection' => $vendorDir . '/symfony/var-dumper/Server/Connection.php', - 'Symfony\\Component\\VarDumper\\Server\\DumpServer' => $vendorDir . '/symfony/var-dumper/Server/DumpServer.php', - 'Symfony\\Component\\VarDumper\\VarDumper' => $vendorDir . '/symfony/var-dumper/VarDumper.php', - 'Symfony\\Component\\VarExporter\\Exception\\ClassNotFoundException' => $vendorDir . '/symfony/var-exporter/Exception/ClassNotFoundException.php', - 'Symfony\\Component\\VarExporter\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/var-exporter/Exception/ExceptionInterface.php', - 'Symfony\\Component\\VarExporter\\Exception\\NotInstantiableTypeException' => $vendorDir . '/symfony/var-exporter/Exception/NotInstantiableTypeException.php', - 'Symfony\\Component\\VarExporter\\Instantiator' => $vendorDir . '/symfony/var-exporter/Instantiator.php', - 'Symfony\\Component\\VarExporter\\Internal\\Exporter' => $vendorDir . '/symfony/var-exporter/Internal/Exporter.php', - 'Symfony\\Component\\VarExporter\\Internal\\Hydrator' => $vendorDir . '/symfony/var-exporter/Internal/Hydrator.php', - 'Symfony\\Component\\VarExporter\\Internal\\Reference' => $vendorDir . '/symfony/var-exporter/Internal/Reference.php', - 'Symfony\\Component\\VarExporter\\Internal\\Registry' => $vendorDir . '/symfony/var-exporter/Internal/Registry.php', - 'Symfony\\Component\\VarExporter\\Internal\\Values' => $vendorDir . '/symfony/var-exporter/Internal/Values.php', - 'Symfony\\Component\\VarExporter\\VarExporter' => $vendorDir . '/symfony/var-exporter/VarExporter.php', - 'Symfony\\Component\\Yaml\\Command\\LintCommand' => $vendorDir . '/symfony/yaml/Command/LintCommand.php', - 'Symfony\\Component\\Yaml\\Dumper' => $vendorDir . '/symfony/yaml/Dumper.php', - 'Symfony\\Component\\Yaml\\Escaper' => $vendorDir . '/symfony/yaml/Escaper.php', - 'Symfony\\Component\\Yaml\\Exception\\DumpException' => $vendorDir . '/symfony/yaml/Exception/DumpException.php', - 'Symfony\\Component\\Yaml\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/yaml/Exception/ExceptionInterface.php', - 'Symfony\\Component\\Yaml\\Exception\\ParseException' => $vendorDir . '/symfony/yaml/Exception/ParseException.php', - 'Symfony\\Component\\Yaml\\Exception\\RuntimeException' => $vendorDir . '/symfony/yaml/Exception/RuntimeException.php', - 'Symfony\\Component\\Yaml\\Inline' => $vendorDir . '/symfony/yaml/Inline.php', - 'Symfony\\Component\\Yaml\\Parser' => $vendorDir . '/symfony/yaml/Parser.php', - 'Symfony\\Component\\Yaml\\Tag\\TaggedValue' => $vendorDir . '/symfony/yaml/Tag/TaggedValue.php', - 'Symfony\\Component\\Yaml\\Unescaper' => $vendorDir . '/symfony/yaml/Unescaper.php', - 'Symfony\\Component\\Yaml\\Yaml' => $vendorDir . '/symfony/yaml/Yaml.php', - 'Symfony\\Contracts\\Cache\\CacheInterface' => $vendorDir . '/symfony/cache-contracts/CacheInterface.php', - 'Symfony\\Contracts\\Cache\\CacheTrait' => $vendorDir . '/symfony/cache-contracts/CacheTrait.php', - 'Symfony\\Contracts\\Cache\\CallbackInterface' => $vendorDir . '/symfony/cache-contracts/CallbackInterface.php', - 'Symfony\\Contracts\\Cache\\ItemInterface' => $vendorDir . '/symfony/cache-contracts/ItemInterface.php', - 'Symfony\\Contracts\\Cache\\TagAwareCacheInterface' => $vendorDir . '/symfony/cache-contracts/TagAwareCacheInterface.php', - 'Symfony\\Contracts\\EventDispatcher\\Event' => $vendorDir . '/symfony/event-dispatcher-contracts/Event.php', - 'Symfony\\Contracts\\EventDispatcher\\EventDispatcherInterface' => $vendorDir . '/symfony/event-dispatcher-contracts/EventDispatcherInterface.php', - 'Symfony\\Contracts\\Service\\Attribute\\Required' => $vendorDir . '/symfony/service-contracts/Attribute/Required.php', - 'Symfony\\Contracts\\Service\\Attribute\\SubscribedService' => $vendorDir . '/symfony/service-contracts/Attribute/SubscribedService.php', - 'Symfony\\Contracts\\Service\\ResetInterface' => $vendorDir . '/symfony/service-contracts/ResetInterface.php', - 'Symfony\\Contracts\\Service\\ServiceLocatorTrait' => $vendorDir . '/symfony/service-contracts/ServiceLocatorTrait.php', - 'Symfony\\Contracts\\Service\\ServiceProviderInterface' => $vendorDir . '/symfony/service-contracts/ServiceProviderInterface.php', - 'Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => $vendorDir . '/symfony/service-contracts/ServiceSubscriberInterface.php', - 'Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => $vendorDir . '/symfony/service-contracts/ServiceSubscriberTrait.php', - 'Symfony\\Contracts\\Translation\\LocaleAwareInterface' => $vendorDir . '/symfony/translation-contracts/LocaleAwareInterface.php', - 'Symfony\\Contracts\\Translation\\TranslatableInterface' => $vendorDir . '/symfony/translation-contracts/TranslatableInterface.php', - 'Symfony\\Contracts\\Translation\\TranslatorInterface' => $vendorDir . '/symfony/translation-contracts/TranslatorInterface.php', - 'Symfony\\Contracts\\Translation\\TranslatorTrait' => $vendorDir . '/symfony/translation-contracts/TranslatorTrait.php', - 'Symfony\\Polyfill\\Ctype\\Ctype' => $vendorDir . '/symfony/polyfill-ctype/Ctype.php', - 'Symfony\\Polyfill\\Intl\\Grapheme\\Grapheme' => $vendorDir . '/symfony/polyfill-intl-grapheme/Grapheme.php', - 'Symfony\\Polyfill\\Intl\\Icu\\Collator' => $vendorDir . '/symfony/polyfill-intl-icu/Collator.php', - 'Symfony\\Polyfill\\Intl\\Icu\\Currencies' => $vendorDir . '/symfony/polyfill-intl-icu/Currencies.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\AmPmTransformer' => $vendorDir . '/symfony/polyfill-intl-icu/DateFormat/AmPmTransformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\DayOfWeekTransformer' => $vendorDir . '/symfony/polyfill-intl-icu/DateFormat/DayOfWeekTransformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\DayOfYearTransformer' => $vendorDir . '/symfony/polyfill-intl-icu/DateFormat/DayOfYearTransformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\DayTransformer' => $vendorDir . '/symfony/polyfill-intl-icu/DateFormat/DayTransformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\FullTransformer' => $vendorDir . '/symfony/polyfill-intl-icu/DateFormat/FullTransformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\Hour1200Transformer' => $vendorDir . '/symfony/polyfill-intl-icu/DateFormat/Hour1200Transformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\Hour1201Transformer' => $vendorDir . '/symfony/polyfill-intl-icu/DateFormat/Hour1201Transformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\Hour2400Transformer' => $vendorDir . '/symfony/polyfill-intl-icu/DateFormat/Hour2400Transformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\Hour2401Transformer' => $vendorDir . '/symfony/polyfill-intl-icu/DateFormat/Hour2401Transformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\HourTransformer' => $vendorDir . '/symfony/polyfill-intl-icu/DateFormat/HourTransformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\MinuteTransformer' => $vendorDir . '/symfony/polyfill-intl-icu/DateFormat/MinuteTransformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\MonthTransformer' => $vendorDir . '/symfony/polyfill-intl-icu/DateFormat/MonthTransformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\QuarterTransformer' => $vendorDir . '/symfony/polyfill-intl-icu/DateFormat/QuarterTransformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\SecondTransformer' => $vendorDir . '/symfony/polyfill-intl-icu/DateFormat/SecondTransformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\TimezoneTransformer' => $vendorDir . '/symfony/polyfill-intl-icu/DateFormat/TimezoneTransformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\Transformer' => $vendorDir . '/symfony/polyfill-intl-icu/DateFormat/Transformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\YearTransformer' => $vendorDir . '/symfony/polyfill-intl-icu/DateFormat/YearTransformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/polyfill-intl-icu/Exception/ExceptionInterface.php', - 'Symfony\\Polyfill\\Intl\\Icu\\Exception\\MethodArgumentNotImplementedException' => $vendorDir . '/symfony/polyfill-intl-icu/Exception/MethodArgumentNotImplementedException.php', - 'Symfony\\Polyfill\\Intl\\Icu\\Exception\\MethodArgumentValueNotImplementedException' => $vendorDir . '/symfony/polyfill-intl-icu/Exception/MethodArgumentValueNotImplementedException.php', - 'Symfony\\Polyfill\\Intl\\Icu\\Exception\\MethodNotImplementedException' => $vendorDir . '/symfony/polyfill-intl-icu/Exception/MethodNotImplementedException.php', - 'Symfony\\Polyfill\\Intl\\Icu\\Exception\\NotImplementedException' => $vendorDir . '/symfony/polyfill-intl-icu/Exception/NotImplementedException.php', - 'Symfony\\Polyfill\\Intl\\Icu\\Exception\\RuntimeException' => $vendorDir . '/symfony/polyfill-intl-icu/Exception/RuntimeException.php', - 'Symfony\\Polyfill\\Intl\\Icu\\Icu' => $vendorDir . '/symfony/polyfill-intl-icu/Icu.php', - 'Symfony\\Polyfill\\Intl\\Icu\\IntlDateFormatter' => $vendorDir . '/symfony/polyfill-intl-icu/IntlDateFormatter.php', - 'Symfony\\Polyfill\\Intl\\Icu\\Locale' => $vendorDir . '/symfony/polyfill-intl-icu/Locale.php', - 'Symfony\\Polyfill\\Intl\\Icu\\NumberFormatter' => $vendorDir . '/symfony/polyfill-intl-icu/NumberFormatter.php', - 'Symfony\\Polyfill\\Intl\\Idn\\Idn' => $vendorDir . '/symfony/polyfill-intl-idn/Idn.php', - 'Symfony\\Polyfill\\Intl\\Idn\\Info' => $vendorDir . '/symfony/polyfill-intl-idn/Info.php', - 'Symfony\\Polyfill\\Intl\\Idn\\Resources\\unidata\\DisallowedRanges' => $vendorDir . '/symfony/polyfill-intl-idn/Resources/unidata/DisallowedRanges.php', - 'Symfony\\Polyfill\\Intl\\Idn\\Resources\\unidata\\Regex' => $vendorDir . '/symfony/polyfill-intl-idn/Resources/unidata/Regex.php', - 'Symfony\\Polyfill\\Intl\\Normalizer\\Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Normalizer.php', - 'Symfony\\Polyfill\\Mbstring\\Mbstring' => $vendorDir . '/symfony/polyfill-mbstring/Mbstring.php', - 'Symfony\\Polyfill\\Php72\\Php72' => $vendorDir . '/symfony/polyfill-php72/Php72.php', - 'Symfony\\Polyfill\\Php73\\Php73' => $vendorDir . '/symfony/polyfill-php73/Php73.php', - 'Symfony\\Polyfill\\Php80\\Php80' => $vendorDir . '/symfony/polyfill-php80/Php80.php', - 'Symfony\\Polyfill\\Php80\\PhpToken' => $vendorDir . '/symfony/polyfill-php80/PhpToken.php', - 'Symfony\\Polyfill\\Php81\\Php81' => $vendorDir . '/symfony/polyfill-php81/Php81.php', - 'SynchroExceptionNotStarted' => $baseDir . '/application/exceptions/SynchroExceptionNotStarted.php', - 'System' => $vendorDir . '/pear/pear-core-minimal/src/System.php', - 'TCPDF' => $vendorDir . '/combodo/tcpdf/tcpdf.php', - 'TCPDF2DBarcode' => $vendorDir . '/combodo/tcpdf/tcpdf_barcodes_2d.php', - 'TCPDFBarcode' => $vendorDir . '/combodo/tcpdf/tcpdf_barcodes_1d.php', - 'TCPDF_COLORS' => $vendorDir . '/combodo/tcpdf/include/tcpdf_colors.php', - 'TCPDF_FILTERS' => $vendorDir . '/combodo/tcpdf/include/tcpdf_filters.php', - 'TCPDF_FONTS' => $vendorDir . '/combodo/tcpdf/include/tcpdf_fonts.php', - 'TCPDF_FONT_DATA' => $vendorDir . '/combodo/tcpdf/include/tcpdf_font_data.php', - 'TCPDF_IMAGES' => $vendorDir . '/combodo/tcpdf/include/tcpdf_images.php', - 'TCPDF_IMPORT' => $vendorDir . '/combodo/tcpdf/tcpdf_import.php', - 'TCPDF_PARSER' => $vendorDir . '/combodo/tcpdf/tcpdf_parser.php', - 'TCPDF_STATIC' => $vendorDir . '/combodo/tcpdf/include/tcpdf_static.php', - 'TabManager' => $baseDir . '/sources/Application/WebPage/TabManager.php', - 'TabularBulkExport' => $baseDir . '/core/tabularbulkexport.class.inc.php', - 'TagSetFieldData' => $baseDir . '/core/tagsetfield.class.inc.php', - 'TemplateMenuNode' => $baseDir . '/application/menunode.class.inc.php', - 'TemplateString' => $baseDir . '/core/templatestring.class.inc.php', - 'TemplateStringPlaceholder' => $baseDir . '/core/templatestring.class.inc.php', - 'TemporaryObjectDescriptor' => $baseDir . '/core/TemporaryObjectDescriptor.php', - 'TheNetworg\\OAuth2\\Client\\Grant\\JwtBearer' => $vendorDir . '/thenetworg/oauth2-azure/src/Grant/JwtBearer.php', - 'TheNetworg\\OAuth2\\Client\\Provider\\Azure' => $vendorDir . '/thenetworg/oauth2-azure/src/Provider/Azure.php', - 'TheNetworg\\OAuth2\\Client\\Provider\\AzureResourceOwner' => $vendorDir . '/thenetworg/oauth2-azure/src/Provider/AzureResourceOwner.php', - 'TheNetworg\\OAuth2\\Client\\Token\\AccessToken' => $vendorDir . '/thenetworg/oauth2-azure/src/Token/AccessToken.php', - 'ThemeHandler' => $baseDir . '/application/themehandler.class.inc.php', - 'ThemeHandlerService' => $baseDir . '/application/themehandlerservice.class.inc.php', - 'ToolsLog' => $baseDir . '/core/log.class.inc.php', - 'Trigger' => $baseDir . '/core/trigger.class.inc.php', - 'TriggerOnAttributeBlobDownload' => $baseDir . '/core/trigger.class.inc.php', - 'TriggerOnObject' => $baseDir . '/core/trigger.class.inc.php', - 'TriggerOnObjectCreate' => $baseDir . '/core/trigger.class.inc.php', - 'TriggerOnObjectDelete' => $baseDir . '/core/trigger.class.inc.php', - 'TriggerOnObjectMention' => $baseDir . '/core/trigger.class.inc.php', - 'TriggerOnObjectUpdate' => $baseDir . '/core/trigger.class.inc.php', - 'TriggerOnPortalUpdate' => $baseDir . '/core/trigger.class.inc.php', - 'TriggerOnStateChange' => $baseDir . '/core/trigger.class.inc.php', - 'TriggerOnStateEnter' => $baseDir . '/core/trigger.class.inc.php', - 'TriggerOnStateLeave' => $baseDir . '/core/trigger.class.inc.php', - 'TriggerOnThresholdReached' => $baseDir . '/core/trigger.class.inc.php', - 'TrueExpression' => $baseDir . '/core/oql/expression.class.inc.php', - 'Twig\\Cache\\CacheInterface' => $vendorDir . '/twig/twig/src/Cache/CacheInterface.php', - 'Twig\\Cache\\FilesystemCache' => $vendorDir . '/twig/twig/src/Cache/FilesystemCache.php', - 'Twig\\Cache\\NullCache' => $vendorDir . '/twig/twig/src/Cache/NullCache.php', - 'Twig\\Compiler' => $vendorDir . '/twig/twig/src/Compiler.php', - 'Twig\\Environment' => $vendorDir . '/twig/twig/src/Environment.php', - 'Twig\\Error\\Error' => $vendorDir . '/twig/twig/src/Error/Error.php', - 'Twig\\Error\\LoaderError' => $vendorDir . '/twig/twig/src/Error/LoaderError.php', - 'Twig\\Error\\RuntimeError' => $vendorDir . '/twig/twig/src/Error/RuntimeError.php', - 'Twig\\Error\\SyntaxError' => $vendorDir . '/twig/twig/src/Error/SyntaxError.php', - 'Twig\\ExpressionParser' => $vendorDir . '/twig/twig/src/ExpressionParser.php', - 'Twig\\ExtensionSet' => $vendorDir . '/twig/twig/src/ExtensionSet.php', - 'Twig\\Extension\\AbstractExtension' => $vendorDir . '/twig/twig/src/Extension/AbstractExtension.php', - 'Twig\\Extension\\CoreExtension' => $vendorDir . '/twig/twig/src/Extension/CoreExtension.php', - 'Twig\\Extension\\DebugExtension' => $vendorDir . '/twig/twig/src/Extension/DebugExtension.php', - 'Twig\\Extension\\EscaperExtension' => $vendorDir . '/twig/twig/src/Extension/EscaperExtension.php', - 'Twig\\Extension\\ExtensionInterface' => $vendorDir . '/twig/twig/src/Extension/ExtensionInterface.php', - 'Twig\\Extension\\GlobalsInterface' => $vendorDir . '/twig/twig/src/Extension/GlobalsInterface.php', - 'Twig\\Extension\\OptimizerExtension' => $vendorDir . '/twig/twig/src/Extension/OptimizerExtension.php', - 'Twig\\Extension\\ProfilerExtension' => $vendorDir . '/twig/twig/src/Extension/ProfilerExtension.php', - 'Twig\\Extension\\RuntimeExtensionInterface' => $vendorDir . '/twig/twig/src/Extension/RuntimeExtensionInterface.php', - 'Twig\\Extension\\SandboxExtension' => $vendorDir . '/twig/twig/src/Extension/SandboxExtension.php', - 'Twig\\Extension\\StagingExtension' => $vendorDir . '/twig/twig/src/Extension/StagingExtension.php', - 'Twig\\Extension\\StringLoaderExtension' => $vendorDir . '/twig/twig/src/Extension/StringLoaderExtension.php', - 'Twig\\FileExtensionEscapingStrategy' => $vendorDir . '/twig/twig/src/FileExtensionEscapingStrategy.php', - 'Twig\\Lexer' => $vendorDir . '/twig/twig/src/Lexer.php', - 'Twig\\Loader\\ArrayLoader' => $vendorDir . '/twig/twig/src/Loader/ArrayLoader.php', - 'Twig\\Loader\\ChainLoader' => $vendorDir . '/twig/twig/src/Loader/ChainLoader.php', - 'Twig\\Loader\\FilesystemLoader' => $vendorDir . '/twig/twig/src/Loader/FilesystemLoader.php', - 'Twig\\Loader\\LoaderInterface' => $vendorDir . '/twig/twig/src/Loader/LoaderInterface.php', - 'Twig\\Markup' => $vendorDir . '/twig/twig/src/Markup.php', - 'Twig\\NodeTraverser' => $vendorDir . '/twig/twig/src/NodeTraverser.php', - 'Twig\\NodeVisitor\\AbstractNodeVisitor' => $vendorDir . '/twig/twig/src/NodeVisitor/AbstractNodeVisitor.php', - 'Twig\\NodeVisitor\\EscaperNodeVisitor' => $vendorDir . '/twig/twig/src/NodeVisitor/EscaperNodeVisitor.php', - 'Twig\\NodeVisitor\\MacroAutoImportNodeVisitor' => $vendorDir . '/twig/twig/src/NodeVisitor/MacroAutoImportNodeVisitor.php', - 'Twig\\NodeVisitor\\NodeVisitorInterface' => $vendorDir . '/twig/twig/src/NodeVisitor/NodeVisitorInterface.php', - 'Twig\\NodeVisitor\\OptimizerNodeVisitor' => $vendorDir . '/twig/twig/src/NodeVisitor/OptimizerNodeVisitor.php', - 'Twig\\NodeVisitor\\SafeAnalysisNodeVisitor' => $vendorDir . '/twig/twig/src/NodeVisitor/SafeAnalysisNodeVisitor.php', - 'Twig\\NodeVisitor\\SandboxNodeVisitor' => $vendorDir . '/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php', - 'Twig\\Node\\AutoEscapeNode' => $vendorDir . '/twig/twig/src/Node/AutoEscapeNode.php', - 'Twig\\Node\\BlockNode' => $vendorDir . '/twig/twig/src/Node/BlockNode.php', - 'Twig\\Node\\BlockReferenceNode' => $vendorDir . '/twig/twig/src/Node/BlockReferenceNode.php', - 'Twig\\Node\\BodyNode' => $vendorDir . '/twig/twig/src/Node/BodyNode.php', - 'Twig\\Node\\CheckSecurityCallNode' => $vendorDir . '/twig/twig/src/Node/CheckSecurityCallNode.php', - 'Twig\\Node\\CheckSecurityNode' => $vendorDir . '/twig/twig/src/Node/CheckSecurityNode.php', - 'Twig\\Node\\CheckToStringNode' => $vendorDir . '/twig/twig/src/Node/CheckToStringNode.php', - 'Twig\\Node\\DeprecatedNode' => $vendorDir . '/twig/twig/src/Node/DeprecatedNode.php', - 'Twig\\Node\\DoNode' => $vendorDir . '/twig/twig/src/Node/DoNode.php', - 'Twig\\Node\\EmbedNode' => $vendorDir . '/twig/twig/src/Node/EmbedNode.php', - 'Twig\\Node\\Expression\\AbstractExpression' => $vendorDir . '/twig/twig/src/Node/Expression/AbstractExpression.php', - 'Twig\\Node\\Expression\\ArrayExpression' => $vendorDir . '/twig/twig/src/Node/Expression/ArrayExpression.php', - 'Twig\\Node\\Expression\\ArrowFunctionExpression' => $vendorDir . '/twig/twig/src/Node/Expression/ArrowFunctionExpression.php', - 'Twig\\Node\\Expression\\AssignNameExpression' => $vendorDir . '/twig/twig/src/Node/Expression/AssignNameExpression.php', - 'Twig\\Node\\Expression\\Binary\\AbstractBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/AbstractBinary.php', - 'Twig\\Node\\Expression\\Binary\\AddBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/AddBinary.php', - 'Twig\\Node\\Expression\\Binary\\AndBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/AndBinary.php', - 'Twig\\Node\\Expression\\Binary\\BitwiseAndBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/BitwiseAndBinary.php', - 'Twig\\Node\\Expression\\Binary\\BitwiseOrBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/BitwiseOrBinary.php', - 'Twig\\Node\\Expression\\Binary\\BitwiseXorBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/BitwiseXorBinary.php', - 'Twig\\Node\\Expression\\Binary\\ConcatBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/ConcatBinary.php', - 'Twig\\Node\\Expression\\Binary\\DivBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/DivBinary.php', - 'Twig\\Node\\Expression\\Binary\\EndsWithBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/EndsWithBinary.php', - 'Twig\\Node\\Expression\\Binary\\EqualBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/EqualBinary.php', - 'Twig\\Node\\Expression\\Binary\\FloorDivBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/FloorDivBinary.php', - 'Twig\\Node\\Expression\\Binary\\GreaterBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/GreaterBinary.php', - 'Twig\\Node\\Expression\\Binary\\GreaterEqualBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/GreaterEqualBinary.php', - 'Twig\\Node\\Expression\\Binary\\InBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/InBinary.php', - 'Twig\\Node\\Expression\\Binary\\LessBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/LessBinary.php', - 'Twig\\Node\\Expression\\Binary\\LessEqualBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/LessEqualBinary.php', - 'Twig\\Node\\Expression\\Binary\\MatchesBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/MatchesBinary.php', - 'Twig\\Node\\Expression\\Binary\\ModBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/ModBinary.php', - 'Twig\\Node\\Expression\\Binary\\MulBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/MulBinary.php', - 'Twig\\Node\\Expression\\Binary\\NotEqualBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/NotEqualBinary.php', - 'Twig\\Node\\Expression\\Binary\\NotInBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/NotInBinary.php', - 'Twig\\Node\\Expression\\Binary\\OrBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/OrBinary.php', - 'Twig\\Node\\Expression\\Binary\\PowerBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/PowerBinary.php', - 'Twig\\Node\\Expression\\Binary\\RangeBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/RangeBinary.php', - 'Twig\\Node\\Expression\\Binary\\SpaceshipBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/SpaceshipBinary.php', - 'Twig\\Node\\Expression\\Binary\\StartsWithBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/StartsWithBinary.php', - 'Twig\\Node\\Expression\\Binary\\SubBinary' => $vendorDir . '/twig/twig/src/Node/Expression/Binary/SubBinary.php', - 'Twig\\Node\\Expression\\BlockReferenceExpression' => $vendorDir . '/twig/twig/src/Node/Expression/BlockReferenceExpression.php', - 'Twig\\Node\\Expression\\CallExpression' => $vendorDir . '/twig/twig/src/Node/Expression/CallExpression.php', - 'Twig\\Node\\Expression\\ConditionalExpression' => $vendorDir . '/twig/twig/src/Node/Expression/ConditionalExpression.php', - 'Twig\\Node\\Expression\\ConstantExpression' => $vendorDir . '/twig/twig/src/Node/Expression/ConstantExpression.php', - 'Twig\\Node\\Expression\\FilterExpression' => $vendorDir . '/twig/twig/src/Node/Expression/FilterExpression.php', - 'Twig\\Node\\Expression\\Filter\\DefaultFilter' => $vendorDir . '/twig/twig/src/Node/Expression/Filter/DefaultFilter.php', - 'Twig\\Node\\Expression\\FunctionExpression' => $vendorDir . '/twig/twig/src/Node/Expression/FunctionExpression.php', - 'Twig\\Node\\Expression\\GetAttrExpression' => $vendorDir . '/twig/twig/src/Node/Expression/GetAttrExpression.php', - 'Twig\\Node\\Expression\\InlinePrint' => $vendorDir . '/twig/twig/src/Node/Expression/InlinePrint.php', - 'Twig\\Node\\Expression\\MethodCallExpression' => $vendorDir . '/twig/twig/src/Node/Expression/MethodCallExpression.php', - 'Twig\\Node\\Expression\\NameExpression' => $vendorDir . '/twig/twig/src/Node/Expression/NameExpression.php', - 'Twig\\Node\\Expression\\NullCoalesceExpression' => $vendorDir . '/twig/twig/src/Node/Expression/NullCoalesceExpression.php', - 'Twig\\Node\\Expression\\ParentExpression' => $vendorDir . '/twig/twig/src/Node/Expression/ParentExpression.php', - 'Twig\\Node\\Expression\\TempNameExpression' => $vendorDir . '/twig/twig/src/Node/Expression/TempNameExpression.php', - 'Twig\\Node\\Expression\\TestExpression' => $vendorDir . '/twig/twig/src/Node/Expression/TestExpression.php', - 'Twig\\Node\\Expression\\Test\\ConstantTest' => $vendorDir . '/twig/twig/src/Node/Expression/Test/ConstantTest.php', - 'Twig\\Node\\Expression\\Test\\DefinedTest' => $vendorDir . '/twig/twig/src/Node/Expression/Test/DefinedTest.php', - 'Twig\\Node\\Expression\\Test\\DivisiblebyTest' => $vendorDir . '/twig/twig/src/Node/Expression/Test/DivisiblebyTest.php', - 'Twig\\Node\\Expression\\Test\\EvenTest' => $vendorDir . '/twig/twig/src/Node/Expression/Test/EvenTest.php', - 'Twig\\Node\\Expression\\Test\\NullTest' => $vendorDir . '/twig/twig/src/Node/Expression/Test/NullTest.php', - 'Twig\\Node\\Expression\\Test\\OddTest' => $vendorDir . '/twig/twig/src/Node/Expression/Test/OddTest.php', - 'Twig\\Node\\Expression\\Test\\SameasTest' => $vendorDir . '/twig/twig/src/Node/Expression/Test/SameasTest.php', - 'Twig\\Node\\Expression\\Unary\\AbstractUnary' => $vendorDir . '/twig/twig/src/Node/Expression/Unary/AbstractUnary.php', - 'Twig\\Node\\Expression\\Unary\\NegUnary' => $vendorDir . '/twig/twig/src/Node/Expression/Unary/NegUnary.php', - 'Twig\\Node\\Expression\\Unary\\NotUnary' => $vendorDir . '/twig/twig/src/Node/Expression/Unary/NotUnary.php', - 'Twig\\Node\\Expression\\Unary\\PosUnary' => $vendorDir . '/twig/twig/src/Node/Expression/Unary/PosUnary.php', - 'Twig\\Node\\Expression\\VariadicExpression' => $vendorDir . '/twig/twig/src/Node/Expression/VariadicExpression.php', - 'Twig\\Node\\FlushNode' => $vendorDir . '/twig/twig/src/Node/FlushNode.php', - 'Twig\\Node\\ForLoopNode' => $vendorDir . '/twig/twig/src/Node/ForLoopNode.php', - 'Twig\\Node\\ForNode' => $vendorDir . '/twig/twig/src/Node/ForNode.php', - 'Twig\\Node\\IfNode' => $vendorDir . '/twig/twig/src/Node/IfNode.php', - 'Twig\\Node\\ImportNode' => $vendorDir . '/twig/twig/src/Node/ImportNode.php', - 'Twig\\Node\\IncludeNode' => $vendorDir . '/twig/twig/src/Node/IncludeNode.php', - 'Twig\\Node\\MacroNode' => $vendorDir . '/twig/twig/src/Node/MacroNode.php', - 'Twig\\Node\\ModuleNode' => $vendorDir . '/twig/twig/src/Node/ModuleNode.php', - 'Twig\\Node\\Node' => $vendorDir . '/twig/twig/src/Node/Node.php', - 'Twig\\Node\\NodeCaptureInterface' => $vendorDir . '/twig/twig/src/Node/NodeCaptureInterface.php', - 'Twig\\Node\\NodeOutputInterface' => $vendorDir . '/twig/twig/src/Node/NodeOutputInterface.php', - 'Twig\\Node\\PrintNode' => $vendorDir . '/twig/twig/src/Node/PrintNode.php', - 'Twig\\Node\\SandboxNode' => $vendorDir . '/twig/twig/src/Node/SandboxNode.php', - 'Twig\\Node\\SetNode' => $vendorDir . '/twig/twig/src/Node/SetNode.php', - 'Twig\\Node\\TextNode' => $vendorDir . '/twig/twig/src/Node/TextNode.php', - 'Twig\\Node\\WithNode' => $vendorDir . '/twig/twig/src/Node/WithNode.php', - 'Twig\\Parser' => $vendorDir . '/twig/twig/src/Parser.php', - 'Twig\\Profiler\\Dumper\\BaseDumper' => $vendorDir . '/twig/twig/src/Profiler/Dumper/BaseDumper.php', - 'Twig\\Profiler\\Dumper\\BlackfireDumper' => $vendorDir . '/twig/twig/src/Profiler/Dumper/BlackfireDumper.php', - 'Twig\\Profiler\\Dumper\\HtmlDumper' => $vendorDir . '/twig/twig/src/Profiler/Dumper/HtmlDumper.php', - 'Twig\\Profiler\\Dumper\\TextDumper' => $vendorDir . '/twig/twig/src/Profiler/Dumper/TextDumper.php', - 'Twig\\Profiler\\NodeVisitor\\ProfilerNodeVisitor' => $vendorDir . '/twig/twig/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php', - 'Twig\\Profiler\\Node\\EnterProfileNode' => $vendorDir . '/twig/twig/src/Profiler/Node/EnterProfileNode.php', - 'Twig\\Profiler\\Node\\LeaveProfileNode' => $vendorDir . '/twig/twig/src/Profiler/Node/LeaveProfileNode.php', - 'Twig\\Profiler\\Profile' => $vendorDir . '/twig/twig/src/Profiler/Profile.php', - 'Twig\\RuntimeLoader\\ContainerRuntimeLoader' => $vendorDir . '/twig/twig/src/RuntimeLoader/ContainerRuntimeLoader.php', - 'Twig\\RuntimeLoader\\FactoryRuntimeLoader' => $vendorDir . '/twig/twig/src/RuntimeLoader/FactoryRuntimeLoader.php', - 'Twig\\RuntimeLoader\\RuntimeLoaderInterface' => $vendorDir . '/twig/twig/src/RuntimeLoader/RuntimeLoaderInterface.php', - 'Twig\\Sandbox\\SecurityError' => $vendorDir . '/twig/twig/src/Sandbox/SecurityError.php', - 'Twig\\Sandbox\\SecurityNotAllowedFilterError' => $vendorDir . '/twig/twig/src/Sandbox/SecurityNotAllowedFilterError.php', - 'Twig\\Sandbox\\SecurityNotAllowedFunctionError' => $vendorDir . '/twig/twig/src/Sandbox/SecurityNotAllowedFunctionError.php', - 'Twig\\Sandbox\\SecurityNotAllowedMethodError' => $vendorDir . '/twig/twig/src/Sandbox/SecurityNotAllowedMethodError.php', - 'Twig\\Sandbox\\SecurityNotAllowedPropertyError' => $vendorDir . '/twig/twig/src/Sandbox/SecurityNotAllowedPropertyError.php', - 'Twig\\Sandbox\\SecurityNotAllowedTagError' => $vendorDir . '/twig/twig/src/Sandbox/SecurityNotAllowedTagError.php', - 'Twig\\Sandbox\\SecurityPolicy' => $vendorDir . '/twig/twig/src/Sandbox/SecurityPolicy.php', - 'Twig\\Sandbox\\SecurityPolicyInterface' => $vendorDir . '/twig/twig/src/Sandbox/SecurityPolicyInterface.php', - 'Twig\\Source' => $vendorDir . '/twig/twig/src/Source.php', - 'Twig\\Template' => $vendorDir . '/twig/twig/src/Template.php', - 'Twig\\TemplateWrapper' => $vendorDir . '/twig/twig/src/TemplateWrapper.php', - 'Twig\\Token' => $vendorDir . '/twig/twig/src/Token.php', - 'Twig\\TokenParser\\AbstractTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/AbstractTokenParser.php', - 'Twig\\TokenParser\\ApplyTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/ApplyTokenParser.php', - 'Twig\\TokenParser\\AutoEscapeTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/AutoEscapeTokenParser.php', - 'Twig\\TokenParser\\BlockTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/BlockTokenParser.php', - 'Twig\\TokenParser\\DeprecatedTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/DeprecatedTokenParser.php', - 'Twig\\TokenParser\\DoTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/DoTokenParser.php', - 'Twig\\TokenParser\\EmbedTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/EmbedTokenParser.php', - 'Twig\\TokenParser\\ExtendsTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/ExtendsTokenParser.php', - 'Twig\\TokenParser\\FlushTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/FlushTokenParser.php', - 'Twig\\TokenParser\\ForTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/ForTokenParser.php', - 'Twig\\TokenParser\\FromTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/FromTokenParser.php', - 'Twig\\TokenParser\\IfTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/IfTokenParser.php', - 'Twig\\TokenParser\\ImportTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/ImportTokenParser.php', - 'Twig\\TokenParser\\IncludeTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/IncludeTokenParser.php', - 'Twig\\TokenParser\\MacroTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/MacroTokenParser.php', - 'Twig\\TokenParser\\SandboxTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/SandboxTokenParser.php', - 'Twig\\TokenParser\\SetTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/SetTokenParser.php', - 'Twig\\TokenParser\\TokenParserInterface' => $vendorDir . '/twig/twig/src/TokenParser/TokenParserInterface.php', - 'Twig\\TokenParser\\UseTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/UseTokenParser.php', - 'Twig\\TokenParser\\WithTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/WithTokenParser.php', - 'Twig\\TokenStream' => $vendorDir . '/twig/twig/src/TokenStream.php', - 'Twig\\TwigFilter' => $vendorDir . '/twig/twig/src/TwigFilter.php', - 'Twig\\TwigFunction' => $vendorDir . '/twig/twig/src/TwigFunction.php', - 'Twig\\TwigTest' => $vendorDir . '/twig/twig/src/TwigTest.php', - 'Twig\\Util\\DeprecationCollector' => $vendorDir . '/twig/twig/src/Util/DeprecationCollector.php', - 'Twig\\Util\\TemplateDirIterator' => $vendorDir . '/twig/twig/src/Util/TemplateDirIterator.php', - 'UIExtKeyWidget' => $baseDir . '/application/ui.extkeywidget.class.inc.php', - 'UIHTMLEditorWidget' => $baseDir . '/application/ui.htmleditorwidget.class.inc.php', - 'UILinksWidget' => $baseDir . '/application/ui.linkswidget.class.inc.php', - 'UILinksWidgetDirect' => $baseDir . '/application/ui.linksdirectwidget.class.inc.php', - 'UIPasswordWidget' => $baseDir . '/application/ui.passwordwidget.class.inc.php', - 'UISearchFormForeignKeys' => $baseDir . '/application/ui.searchformforeignkeys.class.inc.php', - 'UIWizard' => $baseDir . '/application/uiwizard.class.inc.php', - 'URLButtonItem' => $baseDir . '/application/applicationextension.inc.php', - 'URLPopupMenuItem' => $baseDir . '/application/applicationextension.inc.php', - 'UnaryExpression' => $baseDir . '/core/oql/expression.class.inc.php', - 'UnauthenticatedWebPage' => $baseDir . '/sources/Application/WebPage/UnauthenticatedWebPage.php', - 'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', - 'UnknownClassOqlException' => $baseDir . '/core/oql/oqlinterpreter.class.inc.php', - 'User' => $baseDir . '/core/userrights.class.inc.php', - 'UserDashboard' => $baseDir . '/application/user.dashboard.class.inc.php', - 'UserInternal' => $baseDir . '/core/userrights.class.inc.php', - 'UserRightException' => $baseDir . '/application/exceptions/UserRightException.php', - 'UserRights' => $baseDir . '/core/userrights.class.inc.php', - 'UserRightsAddOnAPI' => $baseDir . '/core/userrights.class.inc.php', - 'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', - 'ValueSetDefinition' => $baseDir . '/core/valuesetdef.class.inc.php', - 'ValueSetEnum' => $baseDir . '/core/valuesetdef.class.inc.php', - 'ValueSetEnumClasses' => $baseDir . '/core/valuesetdef.class.inc.php', - 'ValueSetEnumPadded' => $baseDir . '/core/valuesetdef.class.inc.php', - 'ValueSetObjects' => $baseDir . '/core/valuesetdef.class.inc.php', - 'ValueSetRange' => $baseDir . '/core/valuesetdef.class.inc.php', - 'VariableExpression' => $baseDir . '/core/oql/expression.class.inc.php', - 'VariableOqlExpression' => $baseDir . '/core/oql/oqlquery.class.inc.php', - 'WebPage' => $baseDir . '/sources/Application/WebPage/WebPage.php', - 'WebPageMenuNode' => $baseDir . '/application/menunode.class.inc.php', - 'Webmozart\\Assert\\Assert' => $vendorDir . '/webmozart/assert/src/Assert.php', - 'Webmozart\\Assert\\InvalidArgumentException' => $vendorDir . '/webmozart/assert/src/InvalidArgumentException.php', - 'Webmozart\\Assert\\Mixin' => $vendorDir . '/webmozart/assert/src/Mixin.php', - 'WeeklyRotatingLogFileNameBuilder' => $baseDir . '/core/log.class.inc.php', - 'WizardHelper' => $baseDir . '/application/wizardhelper.class.inc.php', - 'XLSXWriter' => $baseDir . '/application/xlsxwriter.class.php', - 'XMLBulkExport' => $baseDir . '/core/xmlbulkexport.class.inc.php', - 'XMLPage' => $baseDir . '/sources/Application/WebPage/XMLPage.php', - 'ajax_page' => $baseDir . '/application/ajaxwebpage.class.inc.php', - 'appUserPreferences' => $baseDir . '/application/user.preferences.class.inc.php', - 'cmdbAbstractObject' => $baseDir . '/application/cmdbabstract.class.inc.php', - 'cmdbDataGenerator' => $baseDir . '/core/data.generator.class.inc.php', - 'iApplicationObjectExtension' => $baseDir . '/application/applicationextension.inc.php', - 'iApplicationUIExtension' => $baseDir . '/application/applicationextension.inc.php', - 'iAttributeNoGroupBy' => $baseDir . '/core/attributedef.class.inc.php', - 'iBackgroundProcess' => $baseDir . '/core/backgroundprocess.inc.php', - 'iBackofficeDictEntriesExtension' => $baseDir . '/application/applicationextension.inc.php', - 'iBackofficeDictEntriesPrefixesExtension' => $baseDir . '/application/applicationextension.inc.php', - 'iBackofficeEarlyScriptExtension' => $baseDir . '/application/applicationextension.inc.php', - 'iBackofficeInitScriptExtension' => $baseDir . '/application/applicationextension.inc.php', - 'iBackofficeLinkedScriptsExtension' => $baseDir . '/application/applicationextension.inc.php', - 'iBackofficeLinkedStylesheetsExtension' => $baseDir . '/application/applicationextension.inc.php', - 'iBackofficeReadyScriptExtension' => $baseDir . '/application/applicationextension.inc.php', - 'iBackofficeScriptExtension' => $baseDir . '/application/applicationextension.inc.php', - 'iBackofficeStyleExtension' => $baseDir . '/application/applicationextension.inc.php', - 'iCMDBChangeOp' => $baseDir . '/core/cmdbchangeop.class.inc.php', - 'iDBObjectSetIterator' => $baseDir . '/core/dbobjectiterator.php', - 'iDBObjectURLMaker' => $baseDir . '/application/applicationcontext.class.inc.php', - 'iDisplay' => $baseDir . '/core/dbobject.class.php', - 'iFieldRendererMappingsExtension' => $baseDir . '/application/applicationextension.inc.php', - 'iKPILoggerExtension' => $baseDir . '/application/applicationextension.inc.php', - 'iKeyboardShortcut' => $baseDir . '/sources/Application/UI/Hook/iKeyboardShortcut.php', - 'iLogFileNameBuilder' => $baseDir . '/core/log.class.inc.php', - 'iLoginExtension' => $baseDir . '/application/applicationextension.inc.php', - 'iLoginFSMExtension' => $baseDir . '/application/applicationextension.inc.php', - 'iLoginUIExtension' => $baseDir . '/application/applicationextension.inc.php', - 'iLogoutExtension' => $baseDir . '/application/applicationextension.inc.php', - 'iMetricComputer' => $baseDir . '/core/computing.inc.php', - 'iModuleExtension' => $baseDir . '/application/applicationextension.inc.php', - 'iNewsroomProvider' => $baseDir . '/application/newsroomprovider.class.inc.php', - 'iOnClassInitialization' => $baseDir . '/core/metamodelmodifier.inc.php', - 'iPageUIBlockExtension' => $baseDir . '/application/applicationextension.inc.php', - 'iPageUIExtension' => $baseDir . '/application/applicationextension.inc.php', - 'iPopupMenuExtension' => $baseDir . '/application/applicationextension.inc.php', - 'iPortalUIExtension' => $baseDir . '/application/applicationextension.inc.php', - 'iPreferencesExtension' => $baseDir . '/application/applicationextension.inc.php', - 'iProcess' => $baseDir . '/core/backgroundprocess.inc.php', - 'iQueryModifier' => $baseDir . '/core/querymodifier.class.inc.php', - 'iRestServiceProvider' => $baseDir . '/application/applicationextension.inc.php', - 'iScheduledProcess' => $baseDir . '/core/backgroundprocess.inc.php', - 'iSelfRegister' => $baseDir . '/core/userrights.class.inc.php', - 'iTabbedPage' => $baseDir . '/sources/Application/WebPage/iTabbedPage.php', - 'iTopConfigParser' => $baseDir . '/core/iTopConfigParser.php', - 'iTopMutex' => $baseDir . '/core/mutex.class.inc.php', - 'iTopOwnershipLock' => $baseDir . '/core/ownershiplock.class.inc.php', - 'iTopOwnershipToken' => $baseDir . '/core/ownershiplock.class.inc.php', - 'iTopPDF' => $baseDir . '/sources/Application/WebPage/iTopPDF.php', - 'iTopStandardURLMaker' => $baseDir . '/application/applicationcontext.class.inc.php', - 'iTopWebPage' => $baseDir . '/sources/Application/WebPage/iTopWebPage.php', - 'iTopWizardWebPage' => $baseDir . '/sources/Application/WebPage/iTopWizardWebPage.php', - 'iTopXmlException' => $baseDir . '/application/exceptions/iTopXmlException.php', - 'iWorkingTimeComputer' => $baseDir . '/core/computing.inc.php', - 'lnkAuditCategoryToAuditDomain' => $baseDir . '/application/audit.domain.class.inc.php', - 'lnkTriggerAction' => $baseDir . '/core/trigger.class.inc.php', - 'ormCaseLog' => $baseDir . '/core/ormcaselog.class.inc.php', - 'ormCustomFieldsValue' => $baseDir . '/core/ormcustomfieldsvalue.class.inc.php', - 'ormDocument' => $baseDir . '/core/ormdocument.class.inc.php', - 'ormLinkSet' => $baseDir . '/core/ormlinkset.class.inc.php', - 'ormPassword' => $baseDir . '/core/ormpassword.class.inc.php', - 'ormSet' => $baseDir . '/core/ormset.class.inc.php', - 'ormStopWatch' => $baseDir . '/core/ormstopwatch.class.inc.php', - 'ormStyle' => $baseDir . '/core/ormStyle.class.inc.php', - 'ormTagSet' => $baseDir . '/core/ormtagset.class.inc.php', - 'phpCAS' => $vendorDir . '/apereo/phpcas/source/CAS.php', - 'privUITransaction' => $baseDir . '/application/transaction.class.inc.php', - 'privUITransactionFile' => $baseDir . '/application/transaction.class.inc.php', - 'privUITransactionSession' => $baseDir . '/application/transaction.class.inc.php', - 'utils' => $baseDir . '/application/utils.inc.php', -); diff --git a/lib/composer/autoload_files.php b/lib/composer/autoload_files.php deleted file mode 100644 index c561b4630..000000000 --- a/lib/composer/autoload_files.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -// autoload_files.php @generated by Composer - -$vendorDir = dirname(dirname(__FILE__)); -$baseDir = dirname($vendorDir); - -return array( - '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php', - 'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php', - '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php', - '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', - '0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php', - '23c18046f52bef3eea034657bafda50f' => $vendorDir . '/symfony/polyfill-php81/bootstrap.php', - '667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php', - 'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php', - '8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php', - 'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php', - '6a47392539ca2329373e0d33e1dba053' => $vendorDir . '/symfony/polyfill-intl-icu/bootstrap.php', - 'c9d07b32a2e02bc0fc582d4f0c1b56cc' => $vendorDir . '/laminas/laminas-servicemanager/src/autoload.php', - '7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php', - '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php', - '25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php', - 'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php', -); diff --git a/lib/composer/autoload_namespaces.php b/lib/composer/autoload_namespaces.php deleted file mode 100644 index 1db5bf646..000000000 --- a/lib/composer/autoload_namespaces.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -// autoload_namespaces.php @generated by Composer - -$vendorDir = dirname(dirname(__FILE__)); -$baseDir = dirname($vendorDir); - -return array( - 'Console' => array($vendorDir . '/pear/console_getopt'), - 'Archive_Tar' => array($vendorDir . '/pear/archive_tar'), - '' => array($vendorDir . '/pear/pear-core-minimal/src'), -); diff --git a/lib/composer/autoload_psr4.php b/lib/composer/autoload_psr4.php deleted file mode 100644 index 577d0ac10..000000000 --- a/lib/composer/autoload_psr4.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php - -// autoload_psr4.php @generated by Composer - -$vendorDir = dirname(dirname(__FILE__)); -$baseDir = dirname($vendorDir); - -return array( - 'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'), - 'Twig\\' => array($vendorDir . '/twig/twig/src'), - 'TheNetworg\\OAuth2\\Client\\' => array($vendorDir . '/thenetworg/oauth2-azure/src'), - 'Symfony\\Polyfill\\Php81\\' => array($vendorDir . '/symfony/polyfill-php81'), - 'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'), - 'Symfony\\Polyfill\\Php73\\' => array($vendorDir . '/symfony/polyfill-php73'), - 'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'), - 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'), - 'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'), - 'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'), - 'Symfony\\Polyfill\\Intl\\Icu\\' => array($vendorDir . '/symfony/polyfill-intl-icu'), - 'Symfony\\Polyfill\\Intl\\Grapheme\\' => array($vendorDir . '/symfony/polyfill-intl-grapheme'), - 'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'), - 'Symfony\\Contracts\\Translation\\' => array($vendorDir . '/symfony/translation-contracts'), - 'Symfony\\Contracts\\Service\\' => array($vendorDir . '/symfony/service-contracts'), - 'Symfony\\Contracts\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher-contracts'), - 'Symfony\\Contracts\\Cache\\' => array($vendorDir . '/symfony/cache-contracts'), - 'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'), - 'Symfony\\Component\\VarExporter\\' => array($vendorDir . '/symfony/var-exporter'), - 'Symfony\\Component\\VarDumper\\' => array($vendorDir . '/symfony/var-dumper'), - 'Symfony\\Component\\String\\' => array($vendorDir . '/symfony/string'), - 'Symfony\\Component\\Stopwatch\\' => array($vendorDir . '/symfony/stopwatch'), - 'Symfony\\Component\\Routing\\' => array($vendorDir . '/symfony/routing'), - 'Symfony\\Component\\PropertyInfo\\' => array($vendorDir . '/symfony/property-info'), - 'Symfony\\Component\\PropertyAccess\\' => array($vendorDir . '/symfony/property-access'), - 'Symfony\\Component\\OptionsResolver\\' => array($vendorDir . '/symfony/options-resolver'), - 'Symfony\\Component\\HttpKernel\\' => array($vendorDir . '/symfony/http-kernel'), - 'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'), - 'Symfony\\Component\\Form\\' => array($vendorDir . '/symfony/form'), - 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'), - 'Symfony\\Component\\Filesystem\\' => array($vendorDir . '/symfony/filesystem'), - 'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'), - 'Symfony\\Component\\ErrorHandler\\' => array($vendorDir . '/symfony/error-handler'), - 'Symfony\\Component\\Dotenv\\' => array($vendorDir . '/symfony/dotenv'), - 'Symfony\\Component\\DependencyInjection\\' => array($vendorDir . '/symfony/dependency-injection'), - 'Symfony\\Component\\CssSelector\\' => array($vendorDir . '/symfony/css-selector'), - 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'), - 'Symfony\\Component\\Config\\' => array($vendorDir . '/symfony/config'), - 'Symfony\\Component\\Cache\\' => array($vendorDir . '/symfony/cache'), - 'Symfony\\Bundle\\WebProfilerBundle\\' => array($vendorDir . '/symfony/web-profiler-bundle'), - 'Symfony\\Bundle\\TwigBundle\\' => array($vendorDir . '/symfony/twig-bundle'), - 'Symfony\\Bundle\\FrameworkBundle\\' => array($vendorDir . '/symfony/framework-bundle'), - 'Symfony\\Bridge\\Twig\\' => array($vendorDir . '/symfony/twig-bridge'), - 'ScssPhp\\ScssPhp\\' => array($vendorDir . '/scssphp/scssphp/src'), - 'Sabberworm\\CSS\\' => array($vendorDir . '/sabberworm/php-css-parser/src'), - 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), - 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'), - 'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'), - 'Psr\\EventDispatcher\\' => array($vendorDir . '/psr/event-dispatcher/src'), - 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'), - 'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'), - 'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'), - 'Pelago\\Emogrifier\\' => array($vendorDir . '/pelago/emogrifier/src'), - 'League\\OAuth2\\Client\\' => array($vendorDir . '/league/oauth2-client/src', $vendorDir . '/league/oauth2-google/src'), - 'Laminas\\Validator\\' => array($vendorDir . '/laminas/laminas-validator/src'), - 'Laminas\\Stdlib\\' => array($vendorDir . '/laminas/laminas-stdlib/src'), - 'Laminas\\ServiceManager\\' => array($vendorDir . '/laminas/laminas-servicemanager/src'), - 'Laminas\\Mime\\' => array($vendorDir . '/laminas/laminas-mime/src'), - 'Laminas\\Mail\\' => array($vendorDir . '/laminas/laminas-mail/src'), - 'Laminas\\Loader\\' => array($vendorDir . '/laminas/laminas-loader/src'), - 'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'), - 'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'), - 'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'), - 'Firebase\\JWT\\' => array($vendorDir . '/firebase/php-jwt/src'), - 'Doctrine\\Deprecations\\' => array($vendorDir . '/doctrine/deprecations/lib/Doctrine/Deprecations'), - 'Doctrine\\Common\\Lexer\\' => array($vendorDir . '/doctrine/lexer/src'), - 'Doctrine\\Common\\Cache\\' => array($vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache'), - 'Doctrine\\Common\\Annotations\\' => array($vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations'), -); diff --git a/lib/composer/autoload_real.php b/lib/composer/autoload_real.php deleted file mode 100644 index cc554d8d1..000000000 --- a/lib/composer/autoload_real.php +++ /dev/null @@ -1,70 +0,0 @@ -<?php - -// autoload_real.php @generated by Composer - -class ComposerAutoloaderInit7f81b4a2a468a061c306af5e447a9a9f -{ - private static $loader; - - public static function loadClassLoader($class) - { - if ('Composer\Autoload\ClassLoader' === $class) { - require __DIR__ . '/ClassLoader.php'; - } - } - - /** - * @return \Composer\Autoload\ClassLoader - */ - public static function getLoader() - { - if (null !== self::$loader) { - return self::$loader; - } - - require __DIR__ . '/platform_check.php'; - - spl_autoload_register(array('ComposerAutoloaderInit7f81b4a2a468a061c306af5e447a9a9f', 'loadClassLoader'), true, true); - self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__))); - spl_autoload_unregister(array('ComposerAutoloaderInit7f81b4a2a468a061c306af5e447a9a9f', 'loadClassLoader')); - - $includePaths = require __DIR__ . '/include_paths.php'; - $includePaths[] = get_include_path(); - set_include_path(implode(PATH_SEPARATOR, $includePaths)); - - $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); - if ($useStaticLoader) { - require __DIR__ . '/autoload_static.php'; - - call_user_func(\Composer\Autoload\ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f::getInitializer($loader)); - } else { - $classMap = require __DIR__ . '/autoload_classmap.php'; - if ($classMap) { - $loader->addClassMap($classMap); - } - } - - $loader->setClassMapAuthoritative(true); - $loader->register(true); - - if ($useStaticLoader) { - $includeFiles = Composer\Autoload\ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f::$files; - } else { - $includeFiles = require __DIR__ . '/autoload_files.php'; - } - foreach ($includeFiles as $fileIdentifier => $file) { - composerRequire7f81b4a2a468a061c306af5e447a9a9f($fileIdentifier, $file); - } - - return $loader; - } -} - -function composerRequire7f81b4a2a468a061c306af5e447a9a9f($fileIdentifier, $file) -{ - if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { - require $file; - - $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; - } -} diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php deleted file mode 100644 index 566579a38..000000000 --- a/lib/composer/autoload_static.php +++ /dev/null @@ -1,3804 +0,0 @@ -<?php - -// autoload_static.php @generated by Composer - -namespace Composer\Autoload; - -class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f -{ - public static $files = array ( - '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php', - 'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php', - '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php', - '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', - '0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php', - '23c18046f52bef3eea034657bafda50f' => __DIR__ . '/..' . '/symfony/polyfill-php81/bootstrap.php', - '667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php', - 'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php', - '8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php', - 'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php', - '6a47392539ca2329373e0d33e1dba053' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/bootstrap.php', - 'c9d07b32a2e02bc0fc582d4f0c1b56cc' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/autoload.php', - '7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php', - '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php', - '25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php', - 'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php', - ); - - public static $prefixLengthsPsr4 = array ( - 'W' => - array ( - 'Webmozart\\Assert\\' => 17, - ), - 'T' => - array ( - 'Twig\\' => 5, - 'TheNetworg\\OAuth2\\Client\\' => 25, - ), - 'S' => - array ( - 'Symfony\\Polyfill\\Php81\\' => 23, - 'Symfony\\Polyfill\\Php80\\' => 23, - 'Symfony\\Polyfill\\Php73\\' => 23, - 'Symfony\\Polyfill\\Php72\\' => 23, - 'Symfony\\Polyfill\\Mbstring\\' => 26, - 'Symfony\\Polyfill\\Intl\\Normalizer\\' => 33, - 'Symfony\\Polyfill\\Intl\\Idn\\' => 26, - 'Symfony\\Polyfill\\Intl\\Icu\\' => 26, - 'Symfony\\Polyfill\\Intl\\Grapheme\\' => 31, - 'Symfony\\Polyfill\\Ctype\\' => 23, - 'Symfony\\Contracts\\Translation\\' => 30, - 'Symfony\\Contracts\\Service\\' => 26, - 'Symfony\\Contracts\\EventDispatcher\\' => 34, - 'Symfony\\Contracts\\Cache\\' => 24, - 'Symfony\\Component\\Yaml\\' => 23, - 'Symfony\\Component\\VarExporter\\' => 30, - 'Symfony\\Component\\VarDumper\\' => 28, - 'Symfony\\Component\\String\\' => 25, - 'Symfony\\Component\\Stopwatch\\' => 28, - 'Symfony\\Component\\Routing\\' => 26, - 'Symfony\\Component\\PropertyInfo\\' => 31, - 'Symfony\\Component\\PropertyAccess\\' => 33, - 'Symfony\\Component\\OptionsResolver\\' => 34, - 'Symfony\\Component\\HttpKernel\\' => 29, - 'Symfony\\Component\\HttpFoundation\\' => 33, - 'Symfony\\Component\\Form\\' => 23, - 'Symfony\\Component\\Finder\\' => 25, - 'Symfony\\Component\\Filesystem\\' => 29, - 'Symfony\\Component\\EventDispatcher\\' => 34, - 'Symfony\\Component\\ErrorHandler\\' => 31, - 'Symfony\\Component\\Dotenv\\' => 25, - 'Symfony\\Component\\DependencyInjection\\' => 38, - 'Symfony\\Component\\CssSelector\\' => 30, - 'Symfony\\Component\\Console\\' => 26, - 'Symfony\\Component\\Config\\' => 25, - 'Symfony\\Component\\Cache\\' => 24, - 'Symfony\\Bundle\\WebProfilerBundle\\' => 33, - 'Symfony\\Bundle\\TwigBundle\\' => 26, - 'Symfony\\Bundle\\FrameworkBundle\\' => 31, - 'Symfony\\Bridge\\Twig\\' => 20, - 'ScssPhp\\ScssPhp\\' => 16, - 'Sabberworm\\CSS\\' => 15, - ), - 'P' => - array ( - 'Psr\\Log\\' => 8, - 'Psr\\Http\\Message\\' => 17, - 'Psr\\Http\\Client\\' => 16, - 'Psr\\EventDispatcher\\' => 20, - 'Psr\\Container\\' => 14, - 'Psr\\Cache\\' => 10, - 'PhpParser\\' => 10, - 'Pelago\\Emogrifier\\' => 18, - ), - 'L' => - array ( - 'League\\OAuth2\\Client\\' => 21, - 'Laminas\\Validator\\' => 18, - 'Laminas\\Stdlib\\' => 15, - 'Laminas\\ServiceManager\\' => 23, - 'Laminas\\Mime\\' => 13, - 'Laminas\\Mail\\' => 13, - 'Laminas\\Loader\\' => 15, - ), - 'G' => - array ( - 'GuzzleHttp\\Psr7\\' => 16, - 'GuzzleHttp\\Promise\\' => 19, - 'GuzzleHttp\\' => 11, - ), - 'F' => - array ( - 'Firebase\\JWT\\' => 13, - ), - 'D' => - array ( - 'Doctrine\\Deprecations\\' => 22, - 'Doctrine\\Common\\Lexer\\' => 22, - 'Doctrine\\Common\\Cache\\' => 22, - 'Doctrine\\Common\\Annotations\\' => 28, - ), - ); - - public static $prefixDirsPsr4 = array ( - 'Webmozart\\Assert\\' => - array ( - 0 => __DIR__ . '/..' . '/webmozart/assert/src', - ), - 'Twig\\' => - array ( - 0 => __DIR__ . '/..' . '/twig/twig/src', - ), - 'TheNetworg\\OAuth2\\Client\\' => - array ( - 0 => __DIR__ . '/..' . '/thenetworg/oauth2-azure/src', - ), - 'Symfony\\Polyfill\\Php81\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/polyfill-php81', - ), - 'Symfony\\Polyfill\\Php80\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/polyfill-php80', - ), - 'Symfony\\Polyfill\\Php73\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/polyfill-php73', - ), - 'Symfony\\Polyfill\\Php72\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/polyfill-php72', - ), - 'Symfony\\Polyfill\\Mbstring\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring', - ), - 'Symfony\\Polyfill\\Intl\\Normalizer\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer', - ), - 'Symfony\\Polyfill\\Intl\\Idn\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-idn', - ), - 'Symfony\\Polyfill\\Intl\\Icu\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-icu', - ), - 'Symfony\\Polyfill\\Intl\\Grapheme\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme', - ), - 'Symfony\\Polyfill\\Ctype\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype', - ), - 'Symfony\\Contracts\\Translation\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/translation-contracts', - ), - 'Symfony\\Contracts\\Service\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/service-contracts', - ), - 'Symfony\\Contracts\\EventDispatcher\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts', - ), - 'Symfony\\Contracts\\Cache\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/cache-contracts', - ), - 'Symfony\\Component\\Yaml\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/yaml', - ), - 'Symfony\\Component\\VarExporter\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/var-exporter', - ), - 'Symfony\\Component\\VarDumper\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/var-dumper', - ), - 'Symfony\\Component\\String\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/string', - ), - 'Symfony\\Component\\Stopwatch\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/stopwatch', - ), - 'Symfony\\Component\\Routing\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/routing', - ), - 'Symfony\\Component\\PropertyInfo\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/property-info', - ), - 'Symfony\\Component\\PropertyAccess\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/property-access', - ), - 'Symfony\\Component\\OptionsResolver\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/options-resolver', - ), - 'Symfony\\Component\\HttpKernel\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/http-kernel', - ), - 'Symfony\\Component\\HttpFoundation\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/http-foundation', - ), - 'Symfony\\Component\\Form\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/form', - ), - 'Symfony\\Component\\Finder\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/finder', - ), - 'Symfony\\Component\\Filesystem\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/filesystem', - ), - 'Symfony\\Component\\EventDispatcher\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/event-dispatcher', - ), - 'Symfony\\Component\\ErrorHandler\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/error-handler', - ), - 'Symfony\\Component\\Dotenv\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/dotenv', - ), - 'Symfony\\Component\\DependencyInjection\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/dependency-injection', - ), - 'Symfony\\Component\\CssSelector\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/css-selector', - ), - 'Symfony\\Component\\Console\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/console', - ), - 'Symfony\\Component\\Config\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/config', - ), - 'Symfony\\Component\\Cache\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/cache', - ), - 'Symfony\\Bundle\\WebProfilerBundle\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/web-profiler-bundle', - ), - 'Symfony\\Bundle\\TwigBundle\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/twig-bundle', - ), - 'Symfony\\Bundle\\FrameworkBundle\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/framework-bundle', - ), - 'Symfony\\Bridge\\Twig\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/twig-bridge', - ), - 'ScssPhp\\ScssPhp\\' => - array ( - 0 => __DIR__ . '/..' . '/scssphp/scssphp/src', - ), - 'Sabberworm\\CSS\\' => - array ( - 0 => __DIR__ . '/..' . '/sabberworm/php-css-parser/src', - ), - 'Psr\\Log\\' => - array ( - 0 => __DIR__ . '/..' . '/psr/log/Psr/Log', - ), - 'Psr\\Http\\Message\\' => - array ( - 0 => __DIR__ . '/..' . '/psr/http-factory/src', - 1 => __DIR__ . '/..' . '/psr/http-message/src', - ), - 'Psr\\Http\\Client\\' => - array ( - 0 => __DIR__ . '/..' . '/psr/http-client/src', - ), - 'Psr\\EventDispatcher\\' => - array ( - 0 => __DIR__ . '/..' . '/psr/event-dispatcher/src', - ), - 'Psr\\Container\\' => - array ( - 0 => __DIR__ . '/..' . '/psr/container/src', - ), - 'Psr\\Cache\\' => - array ( - 0 => __DIR__ . '/..' . '/psr/cache/src', - ), - 'PhpParser\\' => - array ( - 0 => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser', - ), - 'Pelago\\Emogrifier\\' => - array ( - 0 => __DIR__ . '/..' . '/pelago/emogrifier/src', - ), - 'League\\OAuth2\\Client\\' => - array ( - 0 => __DIR__ . '/..' . '/league/oauth2-client/src', - 1 => __DIR__ . '/..' . '/league/oauth2-google/src', - ), - 'Laminas\\Validator\\' => - array ( - 0 => __DIR__ . '/..' . '/laminas/laminas-validator/src', - ), - 'Laminas\\Stdlib\\' => - array ( - 0 => __DIR__ . '/..' . '/laminas/laminas-stdlib/src', - ), - 'Laminas\\ServiceManager\\' => - array ( - 0 => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src', - ), - 'Laminas\\Mime\\' => - array ( - 0 => __DIR__ . '/..' . '/laminas/laminas-mime/src', - ), - 'Laminas\\Mail\\' => - array ( - 0 => __DIR__ . '/..' . '/laminas/laminas-mail/src', - ), - 'Laminas\\Loader\\' => - array ( - 0 => __DIR__ . '/..' . '/laminas/laminas-loader/src', - ), - 'GuzzleHttp\\Psr7\\' => - array ( - 0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src', - ), - 'GuzzleHttp\\Promise\\' => - array ( - 0 => __DIR__ . '/..' . '/guzzlehttp/promises/src', - ), - 'GuzzleHttp\\' => - array ( - 0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src', - ), - 'Firebase\\JWT\\' => - array ( - 0 => __DIR__ . '/..' . '/firebase/php-jwt/src', - ), - 'Doctrine\\Deprecations\\' => - array ( - 0 => __DIR__ . '/..' . '/doctrine/deprecations/lib/Doctrine/Deprecations', - ), - 'Doctrine\\Common\\Lexer\\' => - array ( - 0 => __DIR__ . '/..' . '/doctrine/lexer/src', - ), - 'Doctrine\\Common\\Cache\\' => - array ( - 0 => __DIR__ . '/..' . '/doctrine/cache/lib/Doctrine/Common/Cache', - ), - 'Doctrine\\Common\\Annotations\\' => - array ( - 0 => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations', - ), - ); - - public static $prefixesPsr0 = array ( - 'C' => - array ( - 'Console' => - array ( - 0 => __DIR__ . '/..' . '/pear/console_getopt', - ), - ), - 'A' => - array ( - 'Archive_Tar' => - array ( - 0 => __DIR__ . '/..' . '/pear/archive_tar', - ), - ), - ); - - public static $fallbackDirsPsr0 = array ( - 0 => __DIR__ . '/..' . '/pear/pear-core-minimal/src', - ); - - public static $classMap = array ( - 'AbstractApplicationObjectExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'AbstractApplicationUIExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'AbstractLoginFSMExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'AbstractPageUIBlockExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'AbstractPageUIExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'AbstractPortalUIExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'AbstractPreferencesExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'AbstractWeeklyScheduledProcess' => __DIR__ . '/../..' . '/core/backgroundprocess.inc.php', - 'Action' => __DIR__ . '/../..' . '/core/action.class.inc.php', - 'ActionChecker' => __DIR__ . '/../..' . '/core/userrights.class.inc.php', - 'ActionEmail' => __DIR__ . '/../..' . '/core/action.class.inc.php', - 'ActionNotification' => __DIR__ . '/../..' . '/core/action.class.inc.php', - 'AjaxPage' => __DIR__ . '/../..' . '/sources/Application/WebPage/AjaxPage.php', - 'ApcService' => __DIR__ . '/../..' . '/core/apc-service.class.inc.php', - 'ApplicationContext' => __DIR__ . '/../..' . '/application/applicationcontext.class.inc.php', - 'ApplicationException' => __DIR__ . '/../..' . '/application/exceptions/ApplicationException.php', - 'ApplicationMenu' => __DIR__ . '/../..' . '/application/menunode.class.inc.php', - 'ApplicationPopupMenuItem' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'Archive_Tar' => __DIR__ . '/..' . '/pear/archive_tar/Archive/Tar.php', - 'ArchivedObjectException' => __DIR__ . '/../..' . '/application/exceptions/ArchivedObjectException.php', - 'AsyncSendEmail' => __DIR__ . '/../..' . '/core/asynctask.class.inc.php', - 'AsyncTask' => __DIR__ . '/../..' . '/core/asynctask.class.inc.php', - 'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', - 'AttributeApplicationLanguage' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeArchiveDate' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeArchiveFlag' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeBlob' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeBoolean' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeCaseLog' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeClass' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeClassAttCodeSet' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeClassState' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeCustomFields' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeDBField' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeDBFieldVoid' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeDashboard' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeDate' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeDateTime' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeDeadline' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeDecimal' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeDefinition' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeDuration' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeEmailAddress' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeEncryptedString' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeEnum' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeEnumSet' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeExternalField' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeExternalKey' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeFinalClass' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeFriendlyName' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeHTML' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeHierarchicalKey' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeIPAddress' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeImage' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeInteger' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeLinkedSet' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeLinkedSetIndirect' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeLongText' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeMetaEnum' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeOQL' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeObjectKey' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeObsolescenceDate' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeObsolescenceFlag' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeOneWayPassword' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributePassword' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributePercentage' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributePhoneNumber' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributePropertySet' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeQueryAttCodeSet' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeRedundancySettings' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeSet' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeStopWatch' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeString' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeSubItem' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeTable' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeTagSet' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeTemplateHTML' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeTemplateString' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeTemplateText' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeText' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeURL' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AuditCategory' => __DIR__ . '/../..' . '/application/audit.category.class.inc.php', - 'AuditDomain' => __DIR__ . '/../..' . '/application/audit.domain.class.inc.php', - 'AuditRule' => __DIR__ . '/../..' . '/application/audit.rule.class.inc.php', - 'BackgroundTask' => __DIR__ . '/../..' . '/core/backgroundtask.class.inc.php', - 'BinaryExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', - 'BinaryOqlExpression' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php', - 'BulkChange' => __DIR__ . '/../..' . '/core/bulkchange.class.inc.php', - 'BulkChangeException' => __DIR__ . '/../..' . '/application/exceptions/BulkChangeException.php', - 'BulkExport' => __DIR__ . '/../..' . '/core/bulkexport.class.inc.php', - 'BulkExportException' => __DIR__ . '/../..' . '/core/bulkexport.class.inc.php', - 'BulkExportMissingParameterException' => __DIR__ . '/../..' . '/core/bulkexport.class.inc.php', - 'BulkExportResult' => __DIR__ . '/../..' . '/core/bulkexport.class.inc.php', - 'BulkExportResultGC' => __DIR__ . '/../..' . '/core/bulkexport.class.inc.php', - 'CAS_AuthenticationException' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/AuthenticationException.php', - 'CAS_Client' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Client.php', - 'CAS_CookieJar' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/CookieJar.php', - 'CAS_Exception' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Exception.php', - 'CAS_GracefullTerminationException' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/GracefullTerminationException.php', - 'CAS_InvalidArgumentException' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/InvalidArgumentException.php', - 'CAS_Languages_Catalan' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Languages/Catalan.php', - 'CAS_Languages_ChineseSimplified' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Languages/ChineseSimplified.php', - 'CAS_Languages_English' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Languages/English.php', - 'CAS_Languages_French' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Languages/French.php', - 'CAS_Languages_Galego' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Languages/Galego.php', - 'CAS_Languages_German' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Languages/German.php', - 'CAS_Languages_Greek' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Languages/Greek.php', - 'CAS_Languages_Japanese' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Languages/Japanese.php', - 'CAS_Languages_LanguageInterface' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Languages/LanguageInterface.php', - 'CAS_Languages_Portuguese' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Languages/Portuguese.php', - 'CAS_Languages_Spanish' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Languages/Spanish.php', - 'CAS_OutOfSequenceBeforeAuthenticationCallException' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/OutOfSequenceBeforeAuthenticationCallException.php', - 'CAS_OutOfSequenceBeforeClientException' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/OutOfSequenceBeforeClientException.php', - 'CAS_OutOfSequenceBeforeProxyException' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/OutOfSequenceBeforeProxyException.php', - 'CAS_OutOfSequenceException' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/OutOfSequenceException.php', - 'CAS_PGTStorage_AbstractStorage' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/PGTStorage/AbstractStorage.php', - 'CAS_PGTStorage_Db' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/PGTStorage/Db.php', - 'CAS_PGTStorage_File' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/PGTStorage/File.php', - 'CAS_ProxiedService' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxiedService.php', - 'CAS_ProxiedService_Abstract' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxiedService/Abstract.php', - 'CAS_ProxiedService_Exception' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxiedService/Exception.php', - 'CAS_ProxiedService_Http' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxiedService/Http.php', - 'CAS_ProxiedService_Http_Abstract' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxiedService/Http/Abstract.php', - 'CAS_ProxiedService_Http_Get' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxiedService/Http/Get.php', - 'CAS_ProxiedService_Http_Post' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxiedService/Http/Post.php', - 'CAS_ProxiedService_Imap' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxiedService/Imap.php', - 'CAS_ProxiedService_Testable' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxiedService/Testable.php', - 'CAS_ProxyChain' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxyChain.php', - 'CAS_ProxyChain_AllowedList' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxyChain/AllowedList.php', - 'CAS_ProxyChain_Any' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxyChain/Any.php', - 'CAS_ProxyChain_Interface' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxyChain/Interface.php', - 'CAS_ProxyChain_Trusted' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxyChain/Trusted.php', - 'CAS_ProxyTicketException' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ProxyTicketException.php', - 'CAS_Request_AbstractRequest' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Request/AbstractRequest.php', - 'CAS_Request_CurlMultiRequest' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Request/CurlMultiRequest.php', - 'CAS_Request_CurlRequest' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Request/CurlRequest.php', - 'CAS_Request_Exception' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Request/Exception.php', - 'CAS_Request_MultiRequestInterface' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Request/MultiRequestInterface.php', - 'CAS_Request_RequestInterface' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Request/RequestInterface.php', - 'CAS_Session_PhpSession' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Session/PhpSession.php', - 'CAS_TypeMismatchException' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/TypeMismatchException.php', - 'CLILikeWebPage' => __DIR__ . '/../..' . '/sources/Application/WebPage/CLILikeWebPage.php', - 'CLIPage' => __DIR__ . '/../..' . '/sources/Application/WebPage/CLIPage.php', - 'CMDBChange' => __DIR__ . '/../..' . '/core/cmdbchange.class.inc.php', - 'CMDBChangeOp' => __DIR__ . '/../..' . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpCreate' => __DIR__ . '/../..' . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpDelete' => __DIR__ . '/../..' . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpPlugin' => __DIR__ . '/../..' . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttribute' => __DIR__ . '/../..' . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeBlob' => __DIR__ . '/../..' . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeCaseLog' => __DIR__ . '/../..' . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeCustomFields' => __DIR__ . '/../..' . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeEncrypted' => __DIR__ . '/../..' . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeHTML' => __DIR__ . '/../..' . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeLinks' => __DIR__ . '/../..' . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeLinksAddRemove' => __DIR__ . '/../..' . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeLinksTune' => __DIR__ . '/../..' . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeLongText' => __DIR__ . '/../..' . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeOneWayPassword' => __DIR__ . '/../..' . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeScalar' => __DIR__ . '/../..' . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeTagSet' => __DIR__ . '/../..' . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeText' => __DIR__ . '/../..' . '/core/cmdbchangeop.class.inc.php', - 'CMDBChangeOpSetAttributeURL' => __DIR__ . '/../..' . '/core/cmdbchangeop.class.inc.php', - 'CMDBObject' => __DIR__ . '/../..' . '/core/cmdbobject.class.inc.php', - 'CMDBObjectSet' => __DIR__ . '/../..' . '/core/cmdbobject.class.inc.php', - 'CMDBSource' => __DIR__ . '/../..' . '/core/cmdbsource.class.inc.php', - 'CSVBulkExport' => __DIR__ . '/../..' . '/core/csvbulkexport.class.inc.php', - 'CSVPage' => __DIR__ . '/../..' . '/sources/Application/WebPage/CSVPage.php', - 'CSVParser' => __DIR__ . '/../..' . '/core/csvparser.class.inc.php', - 'CSVParserException' => __DIR__ . '/../..' . '/application/exceptions/CSVParserException.php', - 'CaptureWebPage' => __DIR__ . '/../..' . '/sources/Application/WebPage/CaptureWebPage.php', - 'CellChangeSpec' => __DIR__ . '/../..' . '/core/bulkchange.class.inc.php', - 'CellStatus_Ambiguous' => __DIR__ . '/../..' . '/core/bulkchange.class.inc.php', - 'CellStatus_Issue' => __DIR__ . '/../..' . '/core/bulkchange.class.inc.php', - 'CellStatus_Modify' => __DIR__ . '/../..' . '/core/bulkchange.class.inc.php', - 'CellStatus_NullIssue' => __DIR__ . '/../..' . '/core/bulkchange.class.inc.php', - 'CellStatus_SearchIssue' => __DIR__ . '/../..' . '/core/bulkchange.class.inc.php', - 'CellStatus_Void' => __DIR__ . '/../..' . '/core/bulkchange.class.inc.php', - 'CharConcatExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', - 'CharConcatWSExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', - 'CheckStopWatchThresholds' => __DIR__ . '/../..' . '/core/ormstopwatch.class.inc.php', - 'CheckableExpression' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php', - 'Collator' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/Resources/stubs/Collator.php', - 'Combodo\\iTop\\Application\\Branding' => __DIR__ . '/../..' . '/sources/Application/Branding.php', - 'Combodo\\iTop\\Application\\EventRegister\\ApplicationEvents' => __DIR__ . '/../..' . '/sources/Application/EventRegister/ApplicationEvents.php', - 'Combodo\\iTop\\Application\\Helper\\FormHelper' => __DIR__ . '/../..' . '/sources/Application/Helper/FormHelper.php', - 'Combodo\\iTop\\Application\\Helper\\Session' => __DIR__ . '/../..' . '/sources/Application/Helper/Session.php', - 'Combodo\\iTop\\Application\\Helper\\WebResourcesHelper' => __DIR__ . '/../..' . '/sources/Application/Helper/WebResourcesHelper.php', - 'Combodo\\iTop\\Application\\Search\\AjaxSearchException' => __DIR__ . '/../..' . '/sources/Application/Search/ajaxsearchexception.class.inc.php', - 'Combodo\\iTop\\Application\\Search\\CriterionConversionAbstract' => __DIR__ . '/../..' . '/sources/Application/Search/criterionconversionabstract.class.inc.php', - 'Combodo\\iTop\\Application\\Search\\CriterionConversion\\CriterionToOQL' => __DIR__ . '/../..' . '/sources/Application/Search/CriterionConversion/criteriontooql.class.inc.php', - 'Combodo\\iTop\\Application\\Search\\CriterionConversion\\CriterionToSearchForm' => __DIR__ . '/../..' . '/sources/Application/Search/CriterionConversion/criteriontosearchform.class.inc.php', - 'Combodo\\iTop\\Application\\Search\\CriterionParser' => __DIR__ . '/../..' . '/sources/Application/Search/criterionparser.class.inc.php', - 'Combodo\\iTop\\Application\\Search\\SearchForm' => __DIR__ . '/../..' . '/sources/Application/Search/searchform.class.inc.php', - 'Combodo\\iTop\\Application\\Status\\Status' => __DIR__ . '/../..' . '/sources/Application/Status/Status.php', - 'Combodo\\iTop\\Application\\TwigBase\\Controller\\Controller' => __DIR__ . '/../..' . '/sources/Application/TwigBase/Controller/Controller.php', - 'Combodo\\iTop\\Application\\TwigBase\\Controller\\PageNotFoundException' => __DIR__ . '/../..' . '/application/exceptions/PageNotFoundException.php', - 'Combodo\\iTop\\Application\\TwigBase\\Twig\\Extension' => __DIR__ . '/../..' . '/sources/Application/TwigBase/Twig/Extension.php', - 'Combodo\\iTop\\Application\\TwigBase\\Twig\\TwigHelper' => __DIR__ . '/../..' . '/sources/Application/TwigBase/Twig/TwigHelper.php', - 'Combodo\\iTop\\Application\\TwigBase\\UI\\UIBlockExtension' => __DIR__ . '/../..' . '/sources/Application/TwigBase/UI/UIBlockExtension.php', - 'Combodo\\iTop\\Application\\TwigBase\\UI\\UIBlockNode' => __DIR__ . '/../..' . '/sources/Application/TwigBase/UI/UIBlockNode.php', - 'Combodo\\iTop\\Application\\TwigBase\\UI\\UIBlockParser' => __DIR__ . '/../..' . '/sources/Application/TwigBase/UI/UIBlockParser.php', - 'Combodo\\iTop\\Application\\UI\\Base\\AbstractUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/AbstractUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Alert\\Alert' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Alert/Alert.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Alert\\AlertUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Alert/AlertUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Breadcrumbs\\Breadcrumbs' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Breadcrumbs/Breadcrumbs.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\ButtonGroup\\ButtonGroup' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/ButtonGroup/ButtonGroup.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\ButtonGroup\\ButtonGroupUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/ButtonGroup/ButtonGroupUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Button\\Button' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Button/Button.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Button\\ButtonJS' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Button/ButtonJS.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Button\\ButtonUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Button/ButtonUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Button\\ButtonURL' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Button/ButtonURL.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\CollapsibleSection\\CollapsibleSection' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/CollapsibleSection/CollapsibleSection.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\CollapsibleSection\\CollapsibleSectionUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/CollapsibleSection/CollapsibleSectionUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Dashlet\\DashletBadge' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Dashlet/DashletBadge.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Dashlet\\DashletContainer' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Dashlet/DashletContainer.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Dashlet\\DashletFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Dashlet/DashletFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Dashlet\\DashletHeaderStatic' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Dashlet/DashletHeaderStatic.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Dashlet\\DashletPlainText' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Dashlet/DashletPlainText.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\DataTable\\DataTable' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/DataTable/DataTable.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\DataTable\\DataTableSettings' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/DataTable/DataTableSettings.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\DataTable\\DataTableUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/DataTable/DataTableUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\DataTable\\StaticTable\\FormTableRow\\FormTableRow' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/DataTable/StaticTable/FormTableRow/FormTableRow.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\DataTable\\StaticTable\\FormTable\\FormTable' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/DataTable/StaticTable/FormTable/FormTable.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\DataTable\\StaticTable\\StaticTable' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/DataTable/StaticTable/StaticTable.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\DataTable\\tTableRowActions' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/DataTable/tTableRowActions.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\FieldBadge\\FieldBadge' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/FieldBadge/FieldBadge.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\FieldBadge\\FieldBadgeUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/FieldBadge/FieldBadgeUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\FieldSet\\FieldSet' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/FieldSet/FieldSet.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\FieldSet\\FieldSetUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/FieldSet/FieldSetUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Field\\Field' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Field/Field.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Field\\FieldUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Field/FieldUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Form\\Form' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Form/Form.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Form\\FormUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Form/FormUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\GlobalSearch\\GlobalSearch' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/GlobalSearch/GlobalSearch.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\GlobalSearch\\GlobalSearchFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/GlobalSearch/GlobalSearchFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\GlobalSearch\\GlobalSearchHelper' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/GlobalSearch/GlobalSearchHelper.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Html\\Html' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Html/Html.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Html\\HtmlFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Html/HtmlFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\AbstractInput' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Input/AbstractInput.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\FileSelect\\FileSelect' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Input/FileSelect/FileSelect.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\FileSelect\\FileSelectUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Input/FileSelect/FileSelectUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\Input' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Input/Input.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\InputUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Input/InputUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\InputWithLabel' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Input/InputWithLabel.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\RichText\\RichText' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Input/RichText/RichText.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\SelectUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Input/Select/SelectUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\Select\\Select' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Input/Select/Select.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\Select\\SelectOption' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Input/Select/SelectOption.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\Select\\SelectOptionUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Input/Select/SelectOptionUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\Set\\DataProvider\\AbstractDataProvider' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Input/Set/DataProvider/AbstractDataProvider.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\Set\\DataProvider\\AjaxDataProvider' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Input/Set/DataProvider/AjaxDataProvider.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\Set\\DataProvider\\AjaxDataProviderForOQL' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Input/Set/DataProvider/AjaxDataProviderForOql.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\Set\\DataProvider\\SimpleDataProvider' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Input/Set/DataProvider/SimpleDataProvider.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\Set\\DataProvider\\iDataProvider' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Input/Set/DataProvider/iDataProvider.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\Set\\Set' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Input/Set/Set.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\Set\\SetUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Input/Set/SetUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\TextArea' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Input/TextArea.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\tInputLabel' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Input/tInputLabel.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\MedallionIcon\\MedallionIcon' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/MedallionIcon/MedallionIcon.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Modal\\DoNotShowAgainOptionBlock' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Modal/DoNotShowAgainOptionBlock.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Panel\\Panel' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Panel/Panel.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Panel\\PanelUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Panel/PanelUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Pill\\Pill' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Pill/Pill.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Pill\\PillFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Pill/PillFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\PopoverMenu\\NewsroomMenu\\NewsroomMenu' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/PopoverMenu/NewsroomMenu/NewsroomMenu.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\PopoverMenu\\NewsroomMenu\\NewsroomMenuFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/PopoverMenu/NewsroomMenu/NewsroomMenuFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\PopoverMenu\\PopoverMenu' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/PopoverMenu/PopoverMenu.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\PopoverMenu\\PopoverMenuFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/PopoverMenu/PopoverMenuFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\PopoverMenu\\PopoverMenuItem\\JsPopoverMenuItem' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/PopoverMenu/PopoverMenuItem/JsPopoverMenuItem.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\PopoverMenu\\PopoverMenuItem\\PopoverMenuItem' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/PopoverMenu/PopoverMenuItem/PopoverMenuItem.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\PopoverMenu\\PopoverMenuItem\\PopoverMenuItemFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/PopoverMenu/PopoverMenuItem/PopoverMenuItemFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\PopoverMenu\\PopoverMenuItem\\SeparatorPopoverMenuItem' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/PopoverMenu/PopoverMenuItem/SeparatorPopoverMenuItem.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\PopoverMenu\\PopoverMenuItem\\UrlPopoverMenuItem' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/PopoverMenu/PopoverMenuItem/UrlPopoverMenuItem.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\QuickCreate\\QuickCreate' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/QuickCreate/QuickCreate.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\QuickCreate\\QuickCreateFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/QuickCreate/QuickCreateFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\QuickCreate\\QuickCreateHelper' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/QuickCreate/QuickCreateHelper.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Spinner\\Spinner' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Spinner/Spinner.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Spinner\\SpinnerUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Spinner/SpinnerUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Template\\Template' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Template/Template.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Template\\TemplateUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Template/TemplateUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Text\\Text' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Text/Text.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Title\\Title' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Title/Title.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Title\\TitleUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Title/TitleUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Toolbar\\Separator\\AbstractSeparator' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Toolbar/Separator/AbstractSeparator.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Toolbar\\Separator\\ToolbarSeparatorUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Toolbar/Separator/ToolbarSeparatorUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Toolbar\\Separator\\VerticalSeparator' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Toolbar/Separator/VerticalSeparator.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Toolbar\\Toolbar' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Toolbar/Toolbar.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Toolbar\\ToolbarSpacer\\ToolbarSpacer' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Toolbar/ToolbarSpacer/ToolbarSpacer.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Toolbar\\ToolbarSpacer\\ToolbarSpacerUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Toolbar/ToolbarSpacer/ToolbarSpacerUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Toolbar\\ToolbarUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Toolbar/ToolbarUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\ActivityEntry' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/ActivityEntry.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\ActivityEntryFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/ActivityEntryFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\CMDBChangeOp\\CMDBChangeOpAttachmentAddedFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/CMDBChangeOp/CMDBChangeOpAttachmentAddedFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\CMDBChangeOp\\CMDBChangeOpAttachmentRemovedFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/CMDBChangeOp/CMDBChangeOpAttachmentRemovedFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\CMDBChangeOp\\CMDBChangeOpCreateFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/CMDBChangeOp/CMDBChangeOpCreateFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\CMDBChangeOp\\CMDBChangeOpDeleteFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/CMDBChangeOp/CMDBChangeOpDeleteFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\CMDBChangeOp\\CMDBChangeOpFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/CMDBChangeOp/CMDBChangeOpFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\CMDBChangeOp\\CMDBChangeOpSetAttributeFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/CMDBChangeOp/CMDBChangeOpSetAttributeFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\CMDBChangeOp\\CMDBChangeOpSetAttributeScalarFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/CMDBChangeOp/CMDBChangeOpSetAttributeScalarFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\CaseLogEntry' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/CaseLogEntry.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\EditsEntry' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/EditsEntry.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\EventNotification\\EventNotificationEmailFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/EventNotification/EventNotificationEmailFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\EventNotification\\EventNotificationFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/EventNotification/EventNotificationFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\NotificationEntry' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/NotificationEntry.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityEntry\\TransitionEntry' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityEntry/TransitionEntry.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityPanel' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanel.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityPanelFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanelFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityPanelHelper' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanelHelper.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\ActivityPanelPrint' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanelPrint.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\CaseLogEntryFormFactory\\CaseLogEntryFormFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/ActivityPanel/CaseLogEntryForm/CaseLogEntryFormFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\ActivityPanel\\CaseLogEntryForm\\CaseLogEntryForm' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/ActivityPanel/CaseLogEntryForm/CaseLogEntryForm.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\Dashboard\\DashboardColumn' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/Dashboard/DashboardColumn.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\Dashboard\\DashboardLayout' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/Dashboard/DashboardLayout.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\Dashboard\\DashboardRow' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/Dashboard/DashboardRow.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\MultiColumn\\Column\\Column' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/MultiColumn/Column/Column.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\MultiColumn\\Column\\ColumnUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/MultiColumn/Column/ColumnUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\MultiColumn\\MultiColumn' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/MultiColumn/MultiColumn.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\MultiColumn\\MultiColumnUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/MultiColumn/MultiColumnUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\NavigationMenu\\NavigationMenu' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/NavigationMenu/NavigationMenu.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\NavigationMenu\\NavigationMenuFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/NavigationMenu/NavigationMenuFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\Object\\ObjectDetails' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/Object/ObjectDetails.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\Object\\ObjectFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/Object/ObjectFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\Object\\ObjectSummary' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/Object/ObjectSummary.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\PageContent\\PageContent' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/PageContent/PageContent.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\PageContent\\PageContentFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/PageContent/PageContentFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\PageContent\\PageContentWithSideContent' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/PageContent/PageContentWithSideContent.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\TabContainer\\TabContainer' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/TabContainer/TabContainer.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\TabContainer\\Tab\\AjaxTab' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/TabContainer/Tab/AjaxTab.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\TabContainer\\Tab\\Tab' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/TabContainer/Tab/Tab.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\TopBar\\TopBar' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/TopBar/TopBar.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\TopBar\\TopBarFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/TopBar/TopBarFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\UIContentBlock' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/UIContentBlock.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\UIContentBlockUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/UIContentBlockUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\UIContentBlockWithJSRefreshCallback' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/UIContentBlockWithJSRefreshCallback .php', - 'Combodo\\iTop\\Application\\UI\\Base\\Layout\\iUIContentBlock' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Layout/iUIContentBlock.php', - 'Combodo\\iTop\\Application\\UI\\Base\\UIBlock' => __DIR__ . '/../..' . '/sources/Application/UI/Base/UIBlock.php', - 'Combodo\\iTop\\Application\\UI\\Base\\UIException' => __DIR__ . '/../..' . '/sources/Application/UI/Base/UIException.php', - 'Combodo\\iTop\\Application\\UI\\Base\\iUIBlock' => __DIR__ . '/../..' . '/sources/Application/UI/Base/iUIBlock.php', - 'Combodo\\iTop\\Application\\UI\\Base\\iUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/iUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Base\\tJSRefreshCallback' => __DIR__ . '/../..' . '/sources/Application/UI/Base/tJSRefreshCallback.php', - 'Combodo\\iTop\\Application\\UI\\Base\\tUIContentAreas' => __DIR__ . '/../..' . '/sources/Application/UI/Base/tUIContentAreas.php', - 'Combodo\\iTop\\Application\\UI\\DisplayBlock\\BlockChartAjaxBars\\BlockChartAjaxBars' => __DIR__ . '/../..' . '/sources/Application/UI/DisplayBlock/BlockChartAjaxBars/BlockChartAjaxBars.php', - 'Combodo\\iTop\\Application\\UI\\DisplayBlock\\BlockChartAjaxPie\\BlockChartAjaxPie' => __DIR__ . '/../..' . '/sources/Application/UI/DisplayBlock/BlockChartAjaxPie/BlockChartAjaxPie.php', - 'Combodo\\iTop\\Application\\UI\\DisplayBlock\\BlockChart\\BlockChart' => __DIR__ . '/../..' . '/sources/Application/UI/DisplayBlock/BlockChart/BlockChart.php', - 'Combodo\\iTop\\Application\\UI\\DisplayBlock\\BlockCsv\\BlockCsv' => __DIR__ . '/../..' . '/sources/Application/UI/DisplayBlock/BlockCsv/BlockCsv.php', - 'Combodo\\iTop\\Application\\UI\\DisplayBlock\\BlockList\\BlockList' => __DIR__ . '/../..' . '/sources/Application/UI/DisplayBlock/BlockList/BlockList.php', - 'Combodo\\iTop\\Application\\UI\\Helper\\UIHelper' => __DIR__ . '/../..' . '/sources/Application/UI/Helper/UIHelper.php', - 'Combodo\\iTop\\Application\\UI\\Links\\AbstractBlockLinkSetViewTable' => __DIR__ . '/../..' . '/sources/Application/UI/Links/AbstractBlockLinkSetViewTable.php', - 'Combodo\\iTop\\Application\\UI\\Links\\Direct\\BlockDirectLinkSetEditTable' => __DIR__ . '/../..' . '/sources/Application/UI/Links/Direct/BlockDirectLinkSetEditTable.php', - 'Combodo\\iTop\\Application\\UI\\Links\\Direct\\BlockDirectLinkSetViewTable' => __DIR__ . '/../..' . '/sources/Application/UI/Links/Direct/BlockDirectLinkSetViewTable.php', - 'Combodo\\iTop\\Application\\UI\\Links\\Indirect\\BlockIndirectLinkSetEditTable' => __DIR__ . '/../..' . '/sources/Application/UI/Links/Indirect/BlockIndirectLinkSetEditTable.php', - 'Combodo\\iTop\\Application\\UI\\Links\\Indirect\\BlockIndirectLinkSetViewTable' => __DIR__ . '/../..' . '/sources/Application/UI/Links/Indirect/BlockIndirectLinkSetViewTable.php', - 'Combodo\\iTop\\Application\\UI\\Links\\Indirect\\BlockObjectPickerDialog' => __DIR__ . '/../..' . '/sources/Application/UI/Links/Indirect/BlockObjectPickerDialog.php', - 'Combodo\\iTop\\Application\\UI\\Links\\Set\\BlockLinkSetDisplayAsProperty' => __DIR__ . '/../..' . '/sources/Application/UI/Links/Set/BlockLinksSetDisplayAsProperty.php', - 'Combodo\\iTop\\Application\\UI\\Links\\Set\\LinkSetUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Links/Set/LinksSetUIBlockFactory.php', - 'Combodo\\iTop\\Application\\UI\\Preferences\\BlockShortcuts\\BlockShortcuts' => __DIR__ . '/../..' . '/sources/Application/UI/Preferences/BlockShortcuts/BlockShortcuts.php', - 'Combodo\\iTop\\Application\\UI\\Printable\\BlockPrintHeader\\BlockPrintHeader' => __DIR__ . '/../..' . '/sources/Application/UI/Printable/BlockPrintHeader/BlockPrintHeader.php', - 'Combodo\\iTop\\Composer\\iTopComposer' => __DIR__ . '/../..' . '/sources/Composer/iTopComposer.php', - 'Combodo\\iTop\\Controller\\AbstractController' => __DIR__ . '/../..' . '/sources/Controller/AbstractController.php', - 'Combodo\\iTop\\Controller\\AjaxRenderController' => __DIR__ . '/../..' . '/sources/Controller/AjaxRenderController.php', - 'Combodo\\iTop\\Controller\\Base\\Layout\\ActivityPanelController' => __DIR__ . '/../..' . '/sources/Controller/Base/Layout/ActivityPanelController.php', - 'Combodo\\iTop\\Controller\\Base\\Layout\\ObjectController' => __DIR__ . '/../..' . '/sources/Controller/Base/Layout/ObjectController.php', - 'Combodo\\iTop\\Controller\\Links\\LinkSetController' => __DIR__ . '/../..' . '/sources/Controller/Links/LinkSetController.php', - 'Combodo\\iTop\\Controller\\OAuth\\OAuthLandingController' => __DIR__ . '/../..' . '/sources/Controller/OAuth/OAuthLandingController.php', - 'Combodo\\iTop\\Controller\\PreferencesController' => __DIR__ . '/../..' . '/sources/Controller/PreferencesController.php', - 'Combodo\\iTop\\Controller\\TemporaryObjects\\TemporaryObjectController' => __DIR__ . '/../..' . '/sources/Controller/TemporaryObjects/TemporaryObjectController.php', - 'Combodo\\iTop\\Controller\\iController' => __DIR__ . '/../..' . '/sources/Controller/iController.php', - 'Combodo\\iTop\\Core\\Authentication\\Client\\OAuth\\IOAuthClientProvider' => __DIR__ . '/../..' . '/sources/Core/Authentication/Client/OAuth/IOAuthClientProvider.php', - 'Combodo\\iTop\\Core\\Authentication\\Client\\OAuth\\OAuthClientProviderAbstract' => __DIR__ . '/../..' . '/sources/Core/Authentication/Client/OAuth/OAuthClientProviderAbstract.php', - 'Combodo\\iTop\\Core\\Authentication\\Client\\OAuth\\OAuthClientProviderAzure' => __DIR__ . '/../..' . '/sources/Core/Authentication/Client/OAuth/OAuthClientProviderAzure.php', - 'Combodo\\iTop\\Core\\Authentication\\Client\\OAuth\\OAuthClientProviderFactory' => __DIR__ . '/../..' . '/sources/Core/Authentication/Client/OAuth/OAuthClientProviderFactory.php', - 'Combodo\\iTop\\Core\\Authentication\\Client\\OAuth\\OAuthClientProviderGoogle' => __DIR__ . '/../..' . '/sources/Core/Authentication/Client/OAuth/OAuthClientProviderGoogle.php', - 'Combodo\\iTop\\Core\\CMDBChange\\CMDBChangeOrigin' => __DIR__ . '/../..' . '/sources/Core/CMDBChange/CMDBChangeOrigin.php', - 'Combodo\\iTop\\Core\\DbConnectionWrapper' => __DIR__ . '/../..' . '/core/DbConnectionWrapper.php', - 'Combodo\\iTop\\Core\\Email\\EmailFactory' => __DIR__ . '/../..' . '/sources/Core/Email/EmailFactory.php', - 'Combodo\\iTop\\Core\\Email\\iEMail' => __DIR__ . '/../..' . '/sources/Core/Email/iEMail.php', - 'Combodo\\iTop\\Core\\EventListener\\AttributeBlobEventListener' => __DIR__ . '/../..' . '/sources/Core/EventListener/AttributeBlobEventListener.php', - 'Combodo\\iTop\\Core\\Kpi\\KpiLogData' => __DIR__ . '/../..' . '/sources/Core/Kpi/KpiLogData.php', - 'Combodo\\iTop\\Core\\MetaModel\\FriendlyNameType' => __DIR__ . '/../..' . '/sources/Core/MetaModel/FriendlyNameType.php', - 'Combodo\\iTop\\Core\\MetaModel\\HierarchicalKey' => __DIR__ . '/../..' . '/sources/Core/MetaModel/HierarchicalKey.php', - 'Combodo\\iTop\\DI\\Controller\\Controller' => __DIR__ . '/../..' . '/sources/DI/Controller/Controller.php', - 'Combodo\\iTop\\DI\\Form\\Listener\\IFormTypeOptionModifier' => __DIR__ . '/../..' . '/sources/DI/Form/Listener/IFormTypeOptionModifier.php', - 'Combodo\\iTop\\DI\\Form\\Listener\\ObjectFormListener' => __DIR__ . '/../..' . '/sources/DI/Form/Listener/ObjectFormListener.php', - 'Combodo\\iTop\\DI\\Form\\Type\\ConfigurationType' => __DIR__ . '/../..' . '/sources/DI/Form/Type/ConfigurationType.php', - 'Combodo\\iTop\\DI\\Form\\Type\\Layout\\AbstractContainerType' => __DIR__ . '/../..' . '/sources/DI/Form/Type/Layout/AbstractContainerType.php', - 'Combodo\\iTop\\DI\\Form\\Type\\Layout\\ColumnType' => __DIR__ . '/../..' . '/sources/DI/Form/Type/Layout/ColumnType.php', - 'Combodo\\iTop\\DI\\Form\\Type\\Layout\\FieldSetType' => __DIR__ . '/../..' . '/sources/DI/Form/Type/Layout/FieldSetType.php', - 'Combodo\\iTop\\DI\\Form\\Type\\Layout\\RowType' => __DIR__ . '/../..' . '/sources/DI/Form/Type/Layout/RowType.php', - 'Combodo\\iTop\\DI\\Form\\Type\\ObjectSingleAttributeType' => __DIR__ . '/../..' . '/sources/DI/Form/Type/ObjectSingleAttributeType.php', - 'Combodo\\iTop\\DI\\Form\\Type\\ObjectType' => __DIR__ . '/../..' . '/sources/DI/Form/Type/ObjectType.php', - 'Combodo\\iTop\\DI\\Form\\Type\\Simple\\DocumentType' => __DIR__ . '/../..' . '/sources/DI/Form/Type/Simple/DocumentType.php', - 'Combodo\\iTop\\DI\\Form\\Type\\Simple\\ExternalKeyType' => __DIR__ . '/../..' . '/sources/DI/Form/Type/Simple/ExternalKeyType.php', - 'Combodo\\iTop\\DI\\Form\\Type\\Simple\\LinkSetType' => __DIR__ . '/../..' . '/sources/DI/Form/Type/Simple/LinkSetType.php', - 'Combodo\\iTop\\DI\\ITopKernel' => __DIR__ . '/../..' . '/sources/DI/ITopKernel.php', - 'Combodo\\iTop\\DI\\Services\\ObjectPresentationService' => __DIR__ . '/../..' . '/sources/DI/Services/ObjectPresentationService.php', - 'Combodo\\iTop\\DI\\Services\\ObjectService' => __DIR__ . '/../..' . '/sources/DI/Services/ObjectService.php', - 'Combodo\\iTop\\DI\\Services\\TwigHelper' => __DIR__ . '/../..' . '/sources/DI/Services/TwigHelper.php', - 'Combodo\\iTop\\DesignDocument' => __DIR__ . '/../..' . '/core/designdocument.class.inc.php', - 'Combodo\\iTop\\DesignElement' => __DIR__ . '/../..' . '/core/designdocument.class.inc.php', - 'Combodo\\iTop\\Form\\Field\\AbstractSimpleField' => __DIR__ . '/../..' . '/sources/Form/Field/AbstractSimpleField.php', - 'Combodo\\iTop\\Form\\Field\\BlobField' => __DIR__ . '/../..' . '/sources/Form/Field/BlobField.php', - 'Combodo\\iTop\\Form\\Field\\CaseLogField' => __DIR__ . '/../..' . '/sources/Form/Field/CaseLogField.php', - 'Combodo\\iTop\\Form\\Field\\CheckboxField' => __DIR__ . '/../..' . '/sources/Form/Field/CheckboxField.php', - 'Combodo\\iTop\\Form\\Field\\DateField' => __DIR__ . '/../..' . '/sources/Form/Field/DateField.php', - 'Combodo\\iTop\\Form\\Field\\DateTimeField' => __DIR__ . '/../..' . '/sources/Form/Field/DateTimeField.php', - 'Combodo\\iTop\\Form\\Field\\DurationField' => __DIR__ . '/../..' . '/sources/Form/Field/DurationField.php', - 'Combodo\\iTop\\Form\\Field\\EmailField' => __DIR__ . '/../..' . '/sources/Form/Field/EmailField.php', - 'Combodo\\iTop\\Form\\Field\\Field' => __DIR__ . '/../..' . '/sources/Form/Field/Field.php', - 'Combodo\\iTop\\Form\\Field\\FileUploadField' => __DIR__ . '/../..' . '/sources/Form/Field/FileUploadField.php', - 'Combodo\\iTop\\Form\\Field\\HiddenField' => __DIR__ . '/../..' . '/sources/Form/Field/HiddenField.php', - 'Combodo\\iTop\\Form\\Field\\ImageField' => __DIR__ . '/../..' . '/sources/Form/Field/ImageField.php', - 'Combodo\\iTop\\Form\\Field\\LabelField' => __DIR__ . '/../..' . '/sources/Form/Field/LabelField.php', - 'Combodo\\iTop\\Form\\Field\\LinkedSetField' => __DIR__ . '/../..' . '/sources/Form/Field/LinkedSetField.php', - 'Combodo\\iTop\\Form\\Field\\MultipleChoicesField' => __DIR__ . '/../..' . '/sources/Form/Field/MultipleChoicesField.php', - 'Combodo\\iTop\\Form\\Field\\MultipleSelectField' => __DIR__ . '/../..' . '/sources/Form/Field/MultipleSelectField.php', - 'Combodo\\iTop\\Form\\Field\\PasswordField' => __DIR__ . '/../..' . '/sources/Form/Field/PasswordField.php', - 'Combodo\\iTop\\Form\\Field\\PhoneField' => __DIR__ . '/../..' . '/sources/Form/Field/PhoneField.php', - 'Combodo\\iTop\\Form\\Field\\RadioField' => __DIR__ . '/../..' . '/sources/Form/Field/RadioField.php', - 'Combodo\\iTop\\Form\\Field\\SelectField' => __DIR__ . '/../..' . '/sources/Form/Field/SelectField.php', - 'Combodo\\iTop\\Form\\Field\\SelectObjectField' => __DIR__ . '/../..' . '/sources/Form/Field/SelectObjectField.php', - 'Combodo\\iTop\\Form\\Field\\SetField' => __DIR__ . '/../..' . '/sources/Form/Field/SetField.php', - 'Combodo\\iTop\\Form\\Field\\StringField' => __DIR__ . '/../..' . '/sources/Form/Field/StringField.php', - 'Combodo\\iTop\\Form\\Field\\SubFormField' => __DIR__ . '/../..' . '/sources/Form/Field/SubFormField.php', - 'Combodo\\iTop\\Form\\Field\\TagSetField' => __DIR__ . '/../..' . '/sources/Form/Field/TagSetField.php', - 'Combodo\\iTop\\Form\\Field\\TextAreaField' => __DIR__ . '/../..' . '/sources/Form/Field/TextAreaField.php', - 'Combodo\\iTop\\Form\\Field\\TextField' => __DIR__ . '/../..' . '/sources/Form/Field/TextField.php', - 'Combodo\\iTop\\Form\\Field\\UrlField' => __DIR__ . '/../..' . '/sources/Form/Field/UrlField.php', - 'Combodo\\iTop\\Form\\Form' => __DIR__ . '/../..' . '/sources/Form/Form.php', - 'Combodo\\iTop\\Form\\FormManager' => __DIR__ . '/../..' . '/sources/Form/FormManager.php', - 'Combodo\\iTop\\Form\\Helper\\FieldHelper' => __DIR__ . '/../..' . '/sources/Form/Helper/FieldHelper.php', - 'Combodo\\iTop\\Form\\Validator\\AbstractRegexpValidator' => __DIR__ . '/../..' . '/sources/Form/Validator/AbstractRegexpValidator.php', - 'Combodo\\iTop\\Form\\Validator\\AbstractValidator' => __DIR__ . '/../..' . '/sources/Form/Validator/AbstractValidator.php', - 'Combodo\\iTop\\Form\\Validator\\CustomRegexpValidator' => __DIR__ . '/../..' . '/sources/Form/Validator/CustomRegexpValidator.php', - 'Combodo\\iTop\\Form\\Validator\\IntegerValidator' => __DIR__ . '/../..' . '/sources/Form/Validator/IntegerValidator.php', - 'Combodo\\iTop\\Form\\Validator\\LinkedSetValidator' => __DIR__ . '/../..' . '/sources/Form/Validator/LinkedSetValidator.php', - 'Combodo\\iTop\\Form\\Validator\\MandatoryValidator' => __DIR__ . '/../..' . '/sources/Form/Validator/MandatoryValidator.php', - 'Combodo\\iTop\\Form\\Validator\\MultipleChoicesValidator' => __DIR__ . '/../..' . '/sources/Form/Validator/MultipleChoicesValidator.php', - 'Combodo\\iTop\\Form\\Validator\\NotEmptyExtKeyValidator' => __DIR__ . '/../..' . '/sources/Form/Validator/NotEmptyExtKeyValidator.php', - 'Combodo\\iTop\\Form\\Validator\\SelectObjectValidator' => __DIR__ . '/../..' . '/sources/Form/Validator/SelectObjectValidator.php', - 'Combodo\\iTop\\Form\\Validator\\Validator' => __DIR__ . '/../..' . '/sources/Form/Validator/Validator.php', - 'Combodo\\iTop\\Renderer\\BlockRenderer' => __DIR__ . '/../..' . '/sources/Renderer/BlockRenderer.php', - 'Combodo\\iTop\\Renderer\\Bootstrap\\BsFieldRendererMappings' => __DIR__ . '/../..' . '/sources/Renderer/Bootstrap/BsFieldRendererMappings.php', - 'Combodo\\iTop\\Renderer\\Bootstrap\\BsFormRenderer' => __DIR__ . '/../..' . '/sources/Renderer/Bootstrap/BsFormRenderer.php', - 'Combodo\\iTop\\Renderer\\Bootstrap\\FieldRenderer\\BsFieldRenderer' => __DIR__ . '/../..' . '/sources/Renderer/Bootstrap/FieldRenderer/BsFieldRenderer.php', - 'Combodo\\iTop\\Renderer\\Bootstrap\\FieldRenderer\\BsFileUploadFieldRenderer' => __DIR__ . '/../..' . '/sources/Renderer/Bootstrap/FieldRenderer/BsFileUploadFieldRenderer.php', - 'Combodo\\iTop\\Renderer\\Bootstrap\\FieldRenderer\\BsLinkedSetFieldRenderer' => __DIR__ . '/../..' . '/sources/Renderer/Bootstrap/FieldRenderer/BsLinkedSetFieldRenderer.php', - 'Combodo\\iTop\\Renderer\\Bootstrap\\FieldRenderer\\BsSelectObjectFieldRenderer' => __DIR__ . '/../..' . '/sources/Renderer/Bootstrap/FieldRenderer/BsSelectObjectFieldRenderer.php', - 'Combodo\\iTop\\Renderer\\Bootstrap\\FieldRenderer\\BsSetFieldRenderer' => __DIR__ . '/../..' . '/sources/Renderer/Bootstrap/FieldRenderer/BsSetFieldRenderer.php', - 'Combodo\\iTop\\Renderer\\Bootstrap\\FieldRenderer\\BsSimpleFieldRenderer' => __DIR__ . '/../..' . '/sources/Renderer/Bootstrap/FieldRenderer/BsSimpleFieldRenderer.php', - 'Combodo\\iTop\\Renderer\\Bootstrap\\FieldRenderer\\BsSubFormFieldRenderer' => __DIR__ . '/../..' . '/sources/Renderer/Bootstrap/FieldRenderer/BsSubFormFieldRenderer.php', - 'Combodo\\iTop\\Renderer\\Console\\ConsoleBlockRenderer' => __DIR__ . '/../..' . '/sources/Renderer/Console/ConsoleBlockRenderer.php', - 'Combodo\\iTop\\Renderer\\Console\\ConsoleFieldRendererMappings' => __DIR__ . '/../..' . '/sources/Renderer/Console/ConsoleFieldRendererMappings.php', - 'Combodo\\iTop\\Renderer\\Console\\ConsoleFormRenderer' => __DIR__ . '/../..' . '/sources/Renderer/Console/ConsoleFormRenderer.php', - 'Combodo\\iTop\\Renderer\\Console\\FieldRenderer\\ConsoleSelectObjectFieldRenderer' => __DIR__ . '/../..' . '/sources/Renderer/Console/FieldRenderer/ConsoleSelectObjectFieldRenderer.php', - 'Combodo\\iTop\\Renderer\\Console\\FieldRenderer\\ConsoleSimpleFieldRenderer' => __DIR__ . '/../..' . '/sources/Renderer/Console/FieldRenderer/ConsoleSimpleFieldRenderer.php', - 'Combodo\\iTop\\Renderer\\Console\\FieldRenderer\\ConsoleSubFormFieldRenderer' => __DIR__ . '/../..' . '/sources/Renderer/Console/FieldRenderer/ConsoleSubFormFieldRenderer.php', - 'Combodo\\iTop\\Renderer\\FieldRenderer' => __DIR__ . '/../..' . '/sources/Renderer/FieldRenderer.php', - 'Combodo\\iTop\\Renderer\\FormRenderer' => __DIR__ . '/../..' . '/sources/Renderer/FormRenderer.php', - 'Combodo\\iTop\\Renderer\\RenderingOutput' => __DIR__ . '/../..' . '/sources/Renderer/RenderingOutput.php', - 'Combodo\\iTop\\Service\\Base\\ObjectRepository' => __DIR__ . '/../..' . '/sources/Service/Base/ObjectRepository.php', - 'Combodo\\iTop\\Service\\Base\\iDataPostProcessor' => __DIR__ . '/../..' . '/sources/Service/Base/iDataPostProcessor.php', - 'Combodo\\iTop\\Service\\Events\\Description\\EventDataDescription' => __DIR__ . '/../..' . '/sources/Service/Events/Description/EventDataDescription.php', - 'Combodo\\iTop\\Service\\Events\\Description\\EventDescription' => __DIR__ . '/../..' . '/sources/Service/Events/Description/EventDescription.php', - 'Combodo\\iTop\\Service\\Events\\EventData' => __DIR__ . '/../..' . '/sources/Service/Events/EventData.php', - 'Combodo\\iTop\\Service\\Events\\EventException' => __DIR__ . '/../..' . '/sources/Service/Events/EventException.php', - 'Combodo\\iTop\\Service\\Events\\EventHelper' => __DIR__ . '/../..' . '/sources/Service/Events/EventHelper.php', - 'Combodo\\iTop\\Service\\Events\\EventService' => __DIR__ . '/../..' . '/sources/Service/Events/EventService.php', - 'Combodo\\iTop\\Service\\Events\\EventServiceLog' => __DIR__ . '/../..' . '/sources/Service/Events/EventServiceLog.php', - 'Combodo\\iTop\\Service\\Events\\iEventServiceSetup' => __DIR__ . '/../..' . '/sources/Service/Events/iEventServiceSetup.php', - 'Combodo\\iTop\\Service\\Links\\LinkSetDataTransformer' => __DIR__ . '/../..' . '/sources/Service/Links/LinkSetDataTransformer.php', - 'Combodo\\iTop\\Service\\Links\\LinkSetModel' => __DIR__ . '/../..' . '/sources/Service/Links/LinkSetModel.php', - 'Combodo\\iTop\\Service\\Links\\LinkSetRepository' => __DIR__ . '/../..' . '/sources/Service/Links/LinkSetRepository.php', - 'Combodo\\iTop\\Service\\Links\\LinksBulkDataPostProcessor' => __DIR__ . '/../..' . '/sources/Service/Links/LinksBulkDataPostProcessor.php', - 'Combodo\\iTop\\Service\\Module\\ModuleService' => __DIR__ . '/../..' . '/sources/Service/Module/ModuleService.php', - 'Combodo\\iTop\\Service\\Router\\Exception\\RouteNotFoundException' => __DIR__ . '/../..' . '/sources/Service/Router/Exception/RouteNotFoundException.php', - 'Combodo\\iTop\\Service\\Router\\Exception\\RouterException' => __DIR__ . '/../..' . '/sources/Service/Router/Exception/RouterException.php', - 'Combodo\\iTop\\Service\\Router\\Router' => __DIR__ . '/../..' . '/sources/Service/Router/Router.php', - 'Combodo\\iTop\\Service\\TemporaryObjects\\TemporaryObjectConfig' => __DIR__ . '/../..' . '/sources/Service/TemporaryObjects/TemporaryObjectConfig.php', - 'Combodo\\iTop\\Service\\TemporaryObjects\\TemporaryObjectGC' => __DIR__ . '/../..' . '/sources/Service/TemporaryObjects/TemporaryObjectGC.php', - 'Combodo\\iTop\\Service\\TemporaryObjects\\TemporaryObjectHelper' => __DIR__ . '/../..' . '/sources/Service/TemporaryObjects/TemporaryObjectHelper.php', - 'Combodo\\iTop\\Service\\TemporaryObjects\\TemporaryObjectManager' => __DIR__ . '/../..' . '/sources/Service/TemporaryObjects/TemporaryObjectManager.php', - 'Combodo\\iTop\\Service\\TemporaryObjects\\TemporaryObjectRepository' => __DIR__ . '/../..' . '/sources/Service/TemporaryObjects/TemporaryObjectRepository.php', - 'Combodo\\iTop\\Service\\TemporaryObjects\\TemporaryObjectsEvents' => __DIR__ . '/../..' . '/sources/Service/TemporaryObjects/TemporaryObjectsEvents.php', - 'CompileCSSService' => __DIR__ . '/../..' . '/application/compilecssservice.class.inc.php', - 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', - 'Config' => __DIR__ . '/../..' . '/core/config.class.inc.php', - 'ConfigException' => __DIR__ . '/../..' . '/application/exceptions/ConfigException.php', - 'ConfigPlaceholdersResolver' => __DIR__ . '/../..' . '/core/config.class.inc.php', - 'Console_Getopt' => __DIR__ . '/..' . '/pear/console_getopt/Console/Getopt.php', - 'ContextTag' => __DIR__ . '/../..' . '/core/contexttag.class.inc.php', - 'CoreCannotSaveObjectException' => __DIR__ . '/../..' . '/application/exceptions/CoreCannotSaveObjectException.php', - 'CoreException' => __DIR__ . '/../..' . '/application/exceptions/CoreException.php', - 'CoreOqlException' => __DIR__ . '/../..' . '/application/exceptions/oql/CoreOqlException.php', - 'CoreOqlMultipleResultsForbiddenException' => __DIR__ . '/../..' . '/application/exceptions/oql/CoreOqlMultipleResultsForbiddenException.php', - 'CorePortalInvalidActionRuleException' => __DIR__ . '/../..' . '/application/exceptions/CorePortalInvalidActionRuleException.php', - 'CoreServices' => __DIR__ . '/../..' . '/core/restservices.class.inc.php', - 'CoreTemplateException' => __DIR__ . '/../..' . '/application/exceptions/CoreTemplateException.php', - 'CoreUnexpectedValue' => __DIR__ . '/../..' . '/application/exceptions/CoreUnexpectedValue.php', - 'CoreWarning' => __DIR__ . '/../..' . '/application/exceptions/CoreWarning.php', - 'CryptEngine' => __DIR__ . '/../..' . '/core/simplecrypt.class.inc.php', - 'CustomFieldsHandler' => __DIR__ . '/../..' . '/core/customfieldshandler.class.inc.php', - 'DBObject' => __DIR__ . '/../..' . '/core/dbobject.class.php', - 'DBObjectSearch' => __DIR__ . '/../..' . '/core/dbobjectsearch.class.php', - 'DBObjectSet' => __DIR__ . '/../..' . '/core/dbobjectset.class.php', - 'DBObjectSetComparator' => __DIR__ . '/../..' . '/core/dbobjectset.class.php', - 'DBProperty' => __DIR__ . '/../..' . '/core/dbproperty.class.inc.php', - 'DBSearch' => __DIR__ . '/../..' . '/core/dbsearch.class.php', - 'DBSearchHelper' => __DIR__ . '/../..' . '/application/DBSearchHelper.php', - 'DBUnionSearch' => __DIR__ . '/../..' . '/core/dbunionsearch.class.php', - 'DOMSanitizer' => __DIR__ . '/../..' . '/core/htmlsanitizer.class.inc.php', - 'DailyRotatingLogFileNameBuilder' => __DIR__ . '/../..' . '/core/log.class.inc.php', - 'Dashboard' => __DIR__ . '/../..' . '/application/dashboard.class.inc.php', - 'DashboardLayout' => __DIR__ . '/../..' . '/application/dashboardlayout.class.inc.php', - 'DashboardLayoutMultiCol' => __DIR__ . '/../..' . '/application/dashboardlayout.class.inc.php', - 'DashboardLayoutOneCol' => __DIR__ . '/../..' . '/application/dashboardlayout.class.inc.php', - 'DashboardLayoutThreeCols' => __DIR__ . '/../..' . '/application/dashboardlayout.class.inc.php', - 'DashboardLayoutTwoCols' => __DIR__ . '/../..' . '/application/dashboardlayout.class.inc.php', - 'DashboardMenuNode' => __DIR__ . '/../..' . '/application/menunode.class.inc.php', - 'Dashlet' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php', - 'DashletBadge' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php', - 'DashletEmptyCell' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php', - 'DashletGroupBy' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php', - 'DashletGroupByBars' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php', - 'DashletGroupByPie' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php', - 'DashletGroupByTable' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php', - 'DashletHeaderDynamic' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php', - 'DashletHeaderStatic' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php', - 'DashletObjectList' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php', - 'DashletPlainText' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php', - 'DashletProxy' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php', - 'DashletUnknown' => __DIR__ . '/../..' . '/application/dashlet.class.inc.php', - 'DataTable' => __DIR__ . '/../..' . '/application/datatable.class.inc.php', - 'DataTableConfig' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/DataTable/DataTableConfig/DataTableConfig.php', - 'Datamatrix' => __DIR__ . '/..' . '/combodo/tcpdf/include/barcodes/datamatrix.php', - 'DateTimeFormat' => __DIR__ . '/../..' . '/core/datetimeformat.class.inc.php', - 'DeadLockLog' => __DIR__ . '/../..' . '/core/log.class.inc.php', - 'DefaultLogFileNameBuilder' => __DIR__ . '/../..' . '/core/log.class.inc.php', - 'DefaultMetricComputer' => __DIR__ . '/../..' . '/core/computing.inc.php', - 'DefaultWorkingTimeComputer' => __DIR__ . '/../..' . '/core/computing.inc.php', - 'DeleteException' => __DIR__ . '/../..' . '/application/exceptions/DeleteException.php', - 'DeletionPlan' => __DIR__ . '/../..' . '/core/deletionplan.class.inc.php', - 'DeprecatedCallsLog' => __DIR__ . '/../..' . '/core/log.class.inc.php', - 'DesignerBooleanField' => __DIR__ . '/../..' . '/application/forms.class.inc.php', - 'DesignerComboField' => __DIR__ . '/../..' . '/application/forms.class.inc.php', - 'DesignerForm' => __DIR__ . '/../..' . '/application/forms.class.inc.php', - 'DesignerFormField' => __DIR__ . '/../..' . '/application/forms.class.inc.php', - 'DesignerFormSelectorField' => __DIR__ . '/../..' . '/application/forms.class.inc.php', - 'DesignerHiddenField' => __DIR__ . '/../..' . '/application/forms.class.inc.php', - 'DesignerIconSelectionField' => __DIR__ . '/../..' . '/application/forms.class.inc.php', - 'DesignerIntegerField' => __DIR__ . '/../..' . '/application/forms.class.inc.php', - 'DesignerLabelField' => __DIR__ . '/../..' . '/application/forms.class.inc.php', - 'DesignerLongTextField' => __DIR__ . '/../..' . '/application/forms.class.inc.php', - 'DesignerSortableField' => __DIR__ . '/../..' . '/application/forms.class.inc.php', - 'DesignerStaticTextField' => __DIR__ . '/../..' . '/application/forms.class.inc.php', - 'DesignerSubFormField' => __DIR__ . '/../..' . '/application/forms.class.inc.php', - 'DesignerTabularForm' => __DIR__ . '/../..' . '/application/forms.class.inc.php', - 'DesignerTextField' => __DIR__ . '/../..' . '/application/forms.class.inc.php', - 'DesignerXMLField' => __DIR__ . '/../..' . '/application/forms.class.inc.php', - 'Dict' => __DIR__ . '/../..' . '/core/dict.class.inc.php', - 'DictException' => __DIR__ . '/../..' . '/application/exceptions/dict/DictException.php', - 'DictExceptionMissingString' => __DIR__ . '/../..' . '/application/exceptions/dict/DictExceptionMissingString.php', - 'DictExceptionUnknownLanguage' => __DIR__ . '/../..' . '/application/exceptions/dict/DictExceptionUnknownLanguage.php', - 'DisplayBlock' => __DIR__ . '/../..' . '/application/displayblock.class.inc.php', - 'DisplayTemplate' => __DIR__ . '/../..' . '/application/template.class.inc.php', - 'DisplayableEdge' => __DIR__ . '/../..' . '/core/displayablegraph.class.inc.php', - 'DisplayableGraph' => __DIR__ . '/../..' . '/core/displayablegraph.class.inc.php', - 'DisplayableGroupNode' => __DIR__ . '/../..' . '/core/displayablegraph.class.inc.php', - 'DisplayableNode' => __DIR__ . '/../..' . '/core/displayablegraph.class.inc.php', - 'DisplayableRedundancyNode' => __DIR__ . '/../..' . '/core/displayablegraph.class.inc.php', - 'Doctrine\\Common\\Annotations\\Annotation' => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php', - 'Doctrine\\Common\\Annotations\\AnnotationException' => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php', - 'Doctrine\\Common\\Annotations\\AnnotationReader' => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php', - 'Doctrine\\Common\\Annotations\\AnnotationRegistry' => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php', - 'Doctrine\\Common\\Annotations\\Annotation\\Attribute' => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php', - 'Doctrine\\Common\\Annotations\\Annotation\\Attributes' => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attributes.php', - 'Doctrine\\Common\\Annotations\\Annotation\\Enum' => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php', - 'Doctrine\\Common\\Annotations\\Annotation\\IgnoreAnnotation' => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php', - 'Doctrine\\Common\\Annotations\\Annotation\\NamedArgumentConstructor' => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/NamedArgumentConstructor.php', - 'Doctrine\\Common\\Annotations\\Annotation\\Required' => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Required.php', - 'Doctrine\\Common\\Annotations\\Annotation\\Target' => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Target.php', - 'Doctrine\\Common\\Annotations\\DocLexer' => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php', - 'Doctrine\\Common\\Annotations\\DocParser' => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php', - 'Doctrine\\Common\\Annotations\\ImplicitlyIgnoredAnnotationNames' => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations/ImplicitlyIgnoredAnnotationNames.php', - 'Doctrine\\Common\\Annotations\\IndexedReader' => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php', - 'Doctrine\\Common\\Annotations\\PhpParser' => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations/PhpParser.php', - 'Doctrine\\Common\\Annotations\\PsrCachedReader' => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations/PsrCachedReader.php', - 'Doctrine\\Common\\Annotations\\Reader' => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php', - 'Doctrine\\Common\\Annotations\\TokenParser' => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php', - 'Doctrine\\Common\\Cache\\Cache' => __DIR__ . '/..' . '/doctrine/cache/lib/Doctrine/Common/Cache/Cache.php', - 'Doctrine\\Common\\Cache\\CacheProvider' => __DIR__ . '/..' . '/doctrine/cache/lib/Doctrine/Common/Cache/CacheProvider.php', - 'Doctrine\\Common\\Cache\\ClearableCache' => __DIR__ . '/..' . '/doctrine/cache/lib/Doctrine/Common/Cache/ClearableCache.php', - 'Doctrine\\Common\\Cache\\FlushableCache' => __DIR__ . '/..' . '/doctrine/cache/lib/Doctrine/Common/Cache/FlushableCache.php', - 'Doctrine\\Common\\Cache\\MultiDeleteCache' => __DIR__ . '/..' . '/doctrine/cache/lib/Doctrine/Common/Cache/MultiDeleteCache.php', - 'Doctrine\\Common\\Cache\\MultiGetCache' => __DIR__ . '/..' . '/doctrine/cache/lib/Doctrine/Common/Cache/MultiGetCache.php', - 'Doctrine\\Common\\Cache\\MultiOperationCache' => __DIR__ . '/..' . '/doctrine/cache/lib/Doctrine/Common/Cache/MultiOperationCache.php', - 'Doctrine\\Common\\Cache\\MultiPutCache' => __DIR__ . '/..' . '/doctrine/cache/lib/Doctrine/Common/Cache/MultiPutCache.php', - 'Doctrine\\Common\\Cache\\Psr6\\CacheAdapter' => __DIR__ . '/..' . '/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/CacheAdapter.php', - 'Doctrine\\Common\\Cache\\Psr6\\CacheItem' => __DIR__ . '/..' . '/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/CacheItem.php', - 'Doctrine\\Common\\Cache\\Psr6\\DoctrineProvider' => __DIR__ . '/..' . '/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/DoctrineProvider.php', - 'Doctrine\\Common\\Cache\\Psr6\\InvalidArgument' => __DIR__ . '/..' . '/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/InvalidArgument.php', - 'Doctrine\\Common\\Cache\\Psr6\\TypedCacheItem' => __DIR__ . '/..' . '/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/TypedCacheItem.php', - 'Doctrine\\Common\\Lexer\\AbstractLexer' => __DIR__ . '/..' . '/doctrine/lexer/src/AbstractLexer.php', - 'Doctrine\\Common\\Lexer\\Token' => __DIR__ . '/..' . '/doctrine/lexer/src/Token.php', - 'Doctrine\\Deprecations\\Deprecation' => __DIR__ . '/..' . '/doctrine/deprecations/lib/Doctrine/Deprecations/Deprecation.php', - 'Doctrine\\Deprecations\\PHPUnit\\VerifyDeprecations' => __DIR__ . '/..' . '/doctrine/deprecations/lib/Doctrine/Deprecations/PHPUnit/VerifyDeprecations.php', - 'DownloadPage' => __DIR__ . '/../..' . '/sources/Application/WebPage/DownloadPage.php', - 'EMail' => __DIR__ . '/../..' . '/core/email.class.inc.php', - 'EMailLaminas' => __DIR__ . '/../..' . '/sources/Core/Email/EmailLaminas.php', - 'ErrorPage' => __DIR__ . '/../..' . '/sources/Application/WebPage/ErrorPage.php', - 'Event' => __DIR__ . '/../..' . '/core/event.class.inc.php', - 'EventIssue' => __DIR__ . '/../..' . '/core/event.class.inc.php', - 'EventLoginUsage' => __DIR__ . '/../..' . '/core/event.class.inc.php', - 'EventNotification' => __DIR__ . '/../..' . '/core/event.class.inc.php', - 'EventNotificationEmail' => __DIR__ . '/../..' . '/core/event.class.inc.php', - 'EventOnObject' => __DIR__ . '/../..' . '/core/event.class.inc.php', - 'EventRestService' => __DIR__ . '/../..' . '/core/event.class.inc.php', - 'EventWebService' => __DIR__ . '/../..' . '/core/event.class.inc.php', - 'ExcelBulkExport' => __DIR__ . '/../..' . '/core/excelbulkexport.class.inc.php', - 'ExcelExporter' => __DIR__ . '/../..' . '/application/excelexporter.class.inc.php', - 'ExceptionLog' => __DIR__ . '/../..' . '/core/log.class.inc.php', - 'ExecAsyncTask' => __DIR__ . '/../..' . '/core/asynctask.class.inc.php', - 'ExecutionKPI' => __DIR__ . '/../..' . '/core/kpi.class.inc.php', - 'Expression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', - 'ExpressionCache' => __DIR__ . '/../..' . '/core/expressioncache.class.inc.php', - 'ExpressionHelper' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', - 'FalseExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', - 'FieldExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', - 'FieldExpressionResolved' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', - 'FieldOqlExpression' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php', - 'FileLog' => __DIR__ . '/../..' . '/core/log.class.inc.php', - 'FileUploadException' => __DIR__ . '/../..' . '/application/utils.inc.php', - 'FilterDefinition' => __DIR__ . '/../..' . '/core/filterdef.class.inc.php', - 'FilterFromAttribute' => __DIR__ . '/../..' . '/core/filterdef.class.inc.php', - 'FilterPrivateKey' => __DIR__ . '/../..' . '/core/filterdef.class.inc.php', - 'FindStylesheetObject' => __DIR__ . '/../..' . '/application/findstylesheetobject.class.inc.php', - 'Firebase\\JWT\\BeforeValidException' => __DIR__ . '/..' . '/firebase/php-jwt/src/BeforeValidException.php', - 'Firebase\\JWT\\CachedKeySet' => __DIR__ . '/..' . '/firebase/php-jwt/src/CachedKeySet.php', - 'Firebase\\JWT\\ExpiredException' => __DIR__ . '/..' . '/firebase/php-jwt/src/ExpiredException.php', - 'Firebase\\JWT\\JWK' => __DIR__ . '/..' . '/firebase/php-jwt/src/JWK.php', - 'Firebase\\JWT\\JWT' => __DIR__ . '/..' . '/firebase/php-jwt/src/JWT.php', - 'Firebase\\JWT\\Key' => __DIR__ . '/..' . '/firebase/php-jwt/src/Key.php', - 'Firebase\\JWT\\SignatureInvalidException' => __DIR__ . '/..' . '/firebase/php-jwt/src/SignatureInvalidException.php', - 'FunctionExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', - 'FunctionOqlExpression' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php', - 'GraphEdge' => __DIR__ . '/../..' . '/core/simplegraph.class.inc.php', - 'GraphElement' => __DIR__ . '/../..' . '/core/simplegraph.class.inc.php', - 'GraphNode' => __DIR__ . '/../..' . '/core/simplegraph.class.inc.php', - 'GuzzleHttp\\BodySummarizer' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/BodySummarizer.php', - 'GuzzleHttp\\BodySummarizerInterface' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/BodySummarizerInterface.php', - 'GuzzleHttp\\Client' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Client.php', - 'GuzzleHttp\\ClientInterface' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/ClientInterface.php', - 'GuzzleHttp\\ClientTrait' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/ClientTrait.php', - 'GuzzleHttp\\Cookie\\CookieJar' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Cookie/CookieJar.php', - 'GuzzleHttp\\Cookie\\CookieJarInterface' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php', - 'GuzzleHttp\\Cookie\\FileCookieJar' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php', - 'GuzzleHttp\\Cookie\\SessionCookieJar' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php', - 'GuzzleHttp\\Cookie\\SetCookie' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Cookie/SetCookie.php', - 'GuzzleHttp\\Exception\\BadResponseException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/BadResponseException.php', - 'GuzzleHttp\\Exception\\ClientException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/ClientException.php', - 'GuzzleHttp\\Exception\\ConnectException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/ConnectException.php', - 'GuzzleHttp\\Exception\\GuzzleException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/GuzzleException.php', - 'GuzzleHttp\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/InvalidArgumentException.php', - 'GuzzleHttp\\Exception\\RequestException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/RequestException.php', - 'GuzzleHttp\\Exception\\ServerException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/ServerException.php', - 'GuzzleHttp\\Exception\\TooManyRedirectsException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php', - 'GuzzleHttp\\Exception\\TransferException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/TransferException.php', - 'GuzzleHttp\\HandlerStack' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/HandlerStack.php', - 'GuzzleHttp\\Handler\\CurlFactory' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/CurlFactory.php', - 'GuzzleHttp\\Handler\\CurlFactoryInterface' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php', - 'GuzzleHttp\\Handler\\CurlHandler' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/CurlHandler.php', - 'GuzzleHttp\\Handler\\CurlMultiHandler' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php', - 'GuzzleHttp\\Handler\\EasyHandle' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/EasyHandle.php', - 'GuzzleHttp\\Handler\\HeaderProcessor' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/HeaderProcessor.php', - 'GuzzleHttp\\Handler\\MockHandler' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/MockHandler.php', - 'GuzzleHttp\\Handler\\Proxy' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/Proxy.php', - 'GuzzleHttp\\Handler\\StreamHandler' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/StreamHandler.php', - 'GuzzleHttp\\MessageFormatter' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/MessageFormatter.php', - 'GuzzleHttp\\MessageFormatterInterface' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/MessageFormatterInterface.php', - 'GuzzleHttp\\Middleware' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Middleware.php', - 'GuzzleHttp\\Pool' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Pool.php', - 'GuzzleHttp\\PrepareBodyMiddleware' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php', - 'GuzzleHttp\\Promise\\AggregateException' => __DIR__ . '/..' . '/guzzlehttp/promises/src/AggregateException.php', - 'GuzzleHttp\\Promise\\CancellationException' => __DIR__ . '/..' . '/guzzlehttp/promises/src/CancellationException.php', - 'GuzzleHttp\\Promise\\Coroutine' => __DIR__ . '/..' . '/guzzlehttp/promises/src/Coroutine.php', - 'GuzzleHttp\\Promise\\Create' => __DIR__ . '/..' . '/guzzlehttp/promises/src/Create.php', - 'GuzzleHttp\\Promise\\Each' => __DIR__ . '/..' . '/guzzlehttp/promises/src/Each.php', - 'GuzzleHttp\\Promise\\EachPromise' => __DIR__ . '/..' . '/guzzlehttp/promises/src/EachPromise.php', - 'GuzzleHttp\\Promise\\FulfilledPromise' => __DIR__ . '/..' . '/guzzlehttp/promises/src/FulfilledPromise.php', - 'GuzzleHttp\\Promise\\Is' => __DIR__ . '/..' . '/guzzlehttp/promises/src/Is.php', - 'GuzzleHttp\\Promise\\Promise' => __DIR__ . '/..' . '/guzzlehttp/promises/src/Promise.php', - 'GuzzleHttp\\Promise\\PromiseInterface' => __DIR__ . '/..' . '/guzzlehttp/promises/src/PromiseInterface.php', - 'GuzzleHttp\\Promise\\PromisorInterface' => __DIR__ . '/..' . '/guzzlehttp/promises/src/PromisorInterface.php', - 'GuzzleHttp\\Promise\\RejectedPromise' => __DIR__ . '/..' . '/guzzlehttp/promises/src/RejectedPromise.php', - 'GuzzleHttp\\Promise\\RejectionException' => __DIR__ . '/..' . '/guzzlehttp/promises/src/RejectionException.php', - 'GuzzleHttp\\Promise\\TaskQueue' => __DIR__ . '/..' . '/guzzlehttp/promises/src/TaskQueue.php', - 'GuzzleHttp\\Promise\\TaskQueueInterface' => __DIR__ . '/..' . '/guzzlehttp/promises/src/TaskQueueInterface.php', - 'GuzzleHttp\\Promise\\Utils' => __DIR__ . '/..' . '/guzzlehttp/promises/src/Utils.php', - 'GuzzleHttp\\Psr7\\AppendStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/AppendStream.php', - 'GuzzleHttp\\Psr7\\BufferStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/BufferStream.php', - 'GuzzleHttp\\Psr7\\CachingStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/CachingStream.php', - 'GuzzleHttp\\Psr7\\DroppingStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/DroppingStream.php', - 'GuzzleHttp\\Psr7\\Exception\\MalformedUriException' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Exception/MalformedUriException.php', - 'GuzzleHttp\\Psr7\\FnStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/FnStream.php', - 'GuzzleHttp\\Psr7\\Header' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Header.php', - 'GuzzleHttp\\Psr7\\HttpFactory' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/HttpFactory.php', - 'GuzzleHttp\\Psr7\\InflateStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/InflateStream.php', - 'GuzzleHttp\\Psr7\\LazyOpenStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/LazyOpenStream.php', - 'GuzzleHttp\\Psr7\\LimitStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/LimitStream.php', - 'GuzzleHttp\\Psr7\\Message' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Message.php', - 'GuzzleHttp\\Psr7\\MessageTrait' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/MessageTrait.php', - 'GuzzleHttp\\Psr7\\MimeType' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/MimeType.php', - 'GuzzleHttp\\Psr7\\MultipartStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/MultipartStream.php', - 'GuzzleHttp\\Psr7\\NoSeekStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/NoSeekStream.php', - 'GuzzleHttp\\Psr7\\PumpStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/PumpStream.php', - 'GuzzleHttp\\Psr7\\Query' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Query.php', - 'GuzzleHttp\\Psr7\\Request' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Request.php', - 'GuzzleHttp\\Psr7\\Response' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Response.php', - 'GuzzleHttp\\Psr7\\Rfc7230' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Rfc7230.php', - 'GuzzleHttp\\Psr7\\ServerRequest' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/ServerRequest.php', - 'GuzzleHttp\\Psr7\\Stream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Stream.php', - 'GuzzleHttp\\Psr7\\StreamDecoratorTrait' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/StreamDecoratorTrait.php', - 'GuzzleHttp\\Psr7\\StreamWrapper' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/StreamWrapper.php', - 'GuzzleHttp\\Psr7\\UploadedFile' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/UploadedFile.php', - 'GuzzleHttp\\Psr7\\Uri' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Uri.php', - 'GuzzleHttp\\Psr7\\UriComparator' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/UriComparator.php', - 'GuzzleHttp\\Psr7\\UriNormalizer' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/UriNormalizer.php', - 'GuzzleHttp\\Psr7\\UriResolver' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/UriResolver.php', - 'GuzzleHttp\\Psr7\\Utils' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Utils.php', - 'GuzzleHttp\\RedirectMiddleware' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/RedirectMiddleware.php', - 'GuzzleHttp\\RequestOptions' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/RequestOptions.php', - 'GuzzleHttp\\RetryMiddleware' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/RetryMiddleware.php', - 'GuzzleHttp\\TransferStats' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/TransferStats.php', - 'GuzzleHttp\\Utils' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Utils.php', - 'HTMLBulkExport' => __DIR__ . '/../..' . '/core/htmlbulkexport.class.inc.php', - 'HTMLDOMSanitizer' => __DIR__ . '/../..' . '/core/htmlsanitizer.class.inc.php', - 'HTMLNullSanitizer' => __DIR__ . '/../..' . '/core/htmlsanitizer.class.inc.php', - 'HTMLSanitizer' => __DIR__ . '/../..' . '/core/htmlsanitizer.class.inc.php', - 'Html2Text\\Html2Text' => __DIR__ . '/../..' . '/application/Html2Text.php', - 'Html2Text\\Html2TextException' => __DIR__ . '/../..' . '/application/Html2TextException.php', - 'ITopArchiveTar' => __DIR__ . '/../..' . '/core/tar-itop.class.inc.php', - 'InlineImage' => __DIR__ . '/../..' . '/core/inlineimage.class.inc.php', - 'InlineImageGC' => __DIR__ . '/../..' . '/core/inlineimage.class.inc.php', - 'InputOutputTask' => __DIR__ . '/../..' . '/application/iotask.class.inc.php', - 'IntervalExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', - 'IntervalOqlExpression' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php', - 'IntlDateFormatter' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/Resources/stubs/IntlDateFormatter.php', - 'Introspection' => __DIR__ . '/../..' . '/core/introspection.class.inc.php', - 'InvalidConfigParamException' => __DIR__ . '/../..' . '/application/exceptions/InvalidConfigParamException.php', - 'InvalidPasswordAttributeOneWayPassword' => __DIR__ . '/../..' . '/application/exceptions/InvalidPasswordAttributeOneWayPassword.php', - 'IssueLog' => __DIR__ . '/../..' . '/core/log.class.inc.php', - 'ItopCounter' => __DIR__ . '/../..' . '/core/counter.class.inc.php', - 'JSButtonItem' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'JSPopupMenuItem' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'JsonException' => __DIR__ . '/..' . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', - 'JsonPPage' => __DIR__ . '/../..' . '/sources/Application/WebPage/JsonPPage.php', - 'JsonPage' => __DIR__ . '/../..' . '/sources/Application/WebPage/JsonPage.php', - 'KeyValueStore' => __DIR__ . '/../..' . '/core/counter.class.inc.php', - 'Laminas\\Loader\\AutoloaderFactory' => __DIR__ . '/..' . '/laminas/laminas-loader/src/AutoloaderFactory.php', - 'Laminas\\Loader\\ClassMapAutoloader' => __DIR__ . '/..' . '/laminas/laminas-loader/src/ClassMapAutoloader.php', - 'Laminas\\Loader\\Exception\\BadMethodCallException' => __DIR__ . '/..' . '/laminas/laminas-loader/src/Exception/BadMethodCallException.php', - 'Laminas\\Loader\\Exception\\DomainException' => __DIR__ . '/..' . '/laminas/laminas-loader/src/Exception/DomainException.php', - 'Laminas\\Loader\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-loader/src/Exception/ExceptionInterface.php', - 'Laminas\\Loader\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-loader/src/Exception/InvalidArgumentException.php', - 'Laminas\\Loader\\Exception\\InvalidPathException' => __DIR__ . '/..' . '/laminas/laminas-loader/src/Exception/InvalidPathException.php', - 'Laminas\\Loader\\Exception\\MissingResourceNamespaceException' => __DIR__ . '/..' . '/laminas/laminas-loader/src/Exception/MissingResourceNamespaceException.php', - 'Laminas\\Loader\\Exception\\PluginLoaderException' => __DIR__ . '/..' . '/laminas/laminas-loader/src/Exception/PluginLoaderException.php', - 'Laminas\\Loader\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-loader/src/Exception/RuntimeException.php', - 'Laminas\\Loader\\Exception\\SecurityException' => __DIR__ . '/..' . '/laminas/laminas-loader/src/Exception/SecurityException.php', - 'Laminas\\Loader\\ModuleAutoloader' => __DIR__ . '/..' . '/laminas/laminas-loader/src/ModuleAutoloader.php', - 'Laminas\\Loader\\PluginClassLoader' => __DIR__ . '/..' . '/laminas/laminas-loader/src/PluginClassLoader.php', - 'Laminas\\Loader\\PluginClassLocator' => __DIR__ . '/..' . '/laminas/laminas-loader/src/PluginClassLocator.php', - 'Laminas\\Loader\\ShortNameLocator' => __DIR__ . '/..' . '/laminas/laminas-loader/src/ShortNameLocator.php', - 'Laminas\\Loader\\SplAutoloader' => __DIR__ . '/..' . '/laminas/laminas-loader/src/SplAutoloader.php', - 'Laminas\\Loader\\StandardAutoloader' => __DIR__ . '/..' . '/laminas/laminas-loader/src/StandardAutoloader.php', - 'Laminas\\Mail\\Address' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Address.php', - 'Laminas\\Mail\\AddressList' => __DIR__ . '/..' . '/laminas/laminas-mail/src/AddressList.php', - 'Laminas\\Mail\\Address\\AddressInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Address/AddressInterface.php', - 'Laminas\\Mail\\ConfigProvider' => __DIR__ . '/..' . '/laminas/laminas-mail/src/ConfigProvider.php', - 'Laminas\\Mail\\Exception\\BadMethodCallException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Exception/BadMethodCallException.php', - 'Laminas\\Mail\\Exception\\DomainException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Exception/DomainException.php', - 'Laminas\\Mail\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Exception/ExceptionInterface.php', - 'Laminas\\Mail\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Exception/InvalidArgumentException.php', - 'Laminas\\Mail\\Exception\\OutOfBoundsException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Exception/OutOfBoundsException.php', - 'Laminas\\Mail\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Exception/RuntimeException.php', - 'Laminas\\Mail\\Header\\AbstractAddressList' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/AbstractAddressList.php', - 'Laminas\\Mail\\Header\\Bcc' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/Bcc.php', - 'Laminas\\Mail\\Header\\Cc' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/Cc.php', - 'Laminas\\Mail\\Header\\ContentDisposition' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/ContentDisposition.php', - 'Laminas\\Mail\\Header\\ContentTransferEncoding' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/ContentTransferEncoding.php', - 'Laminas\\Mail\\Header\\ContentType' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/ContentType.php', - 'Laminas\\Mail\\Header\\Date' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/Date.php', - 'Laminas\\Mail\\Header\\Exception\\BadMethodCallException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/Exception/BadMethodCallException.php', - 'Laminas\\Mail\\Header\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/Exception/ExceptionInterface.php', - 'Laminas\\Mail\\Header\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/Exception/InvalidArgumentException.php', - 'Laminas\\Mail\\Header\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/Exception/RuntimeException.php', - 'Laminas\\Mail\\Header\\From' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/From.php', - 'Laminas\\Mail\\Header\\GenericHeader' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/GenericHeader.php', - 'Laminas\\Mail\\Header\\GenericMultiHeader' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/GenericMultiHeader.php', - 'Laminas\\Mail\\Header\\HeaderInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/HeaderInterface.php', - 'Laminas\\Mail\\Header\\HeaderLoader' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/HeaderLoader.php', - 'Laminas\\Mail\\Header\\HeaderLocator' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/HeaderLocator.php', - 'Laminas\\Mail\\Header\\HeaderLocatorInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/HeaderLocatorInterface.php', - 'Laminas\\Mail\\Header\\HeaderName' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/HeaderName.php', - 'Laminas\\Mail\\Header\\HeaderValue' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/HeaderValue.php', - 'Laminas\\Mail\\Header\\HeaderWrap' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/HeaderWrap.php', - 'Laminas\\Mail\\Header\\IdentificationField' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/IdentificationField.php', - 'Laminas\\Mail\\Header\\InReplyTo' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/InReplyTo.php', - 'Laminas\\Mail\\Header\\ListParser' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/ListParser.php', - 'Laminas\\Mail\\Header\\MessageId' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/MessageId.php', - 'Laminas\\Mail\\Header\\MimeVersion' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/MimeVersion.php', - 'Laminas\\Mail\\Header\\MultipleHeadersInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/MultipleHeadersInterface.php', - 'Laminas\\Mail\\Header\\Received' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/Received.php', - 'Laminas\\Mail\\Header\\References' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/References.php', - 'Laminas\\Mail\\Header\\ReplyTo' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/ReplyTo.php', - 'Laminas\\Mail\\Header\\Sender' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/Sender.php', - 'Laminas\\Mail\\Header\\StructuredInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/StructuredInterface.php', - 'Laminas\\Mail\\Header\\Subject' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/Subject.php', - 'Laminas\\Mail\\Header\\To' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/To.php', - 'Laminas\\Mail\\Header\\UnstructuredInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Header/UnstructuredInterface.php', - 'Laminas\\Mail\\Headers' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Headers.php', - 'Laminas\\Mail\\Message' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Message.php', - 'Laminas\\Mail\\MessageFactory' => __DIR__ . '/..' . '/laminas/laminas-mail/src/MessageFactory.php', - 'Laminas\\Mail\\Module' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Module.php', - 'Laminas\\Mail\\Protocol\\AbstractProtocol' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/AbstractProtocol.php', - 'Laminas\\Mail\\Protocol\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/Exception/ExceptionInterface.php', - 'Laminas\\Mail\\Protocol\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/Exception/InvalidArgumentException.php', - 'Laminas\\Mail\\Protocol\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/Exception/RuntimeException.php', - 'Laminas\\Mail\\Protocol\\Imap' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/Imap.php', - 'Laminas\\Mail\\Protocol\\Pop3' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/Pop3.php', - 'Laminas\\Mail\\Protocol\\ProtocolTrait' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/ProtocolTrait.php', - 'Laminas\\Mail\\Protocol\\Smtp' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/Smtp.php', - 'Laminas\\Mail\\Protocol\\SmtpPluginManager' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/SmtpPluginManager.php', - 'Laminas\\Mail\\Protocol\\SmtpPluginManagerFactory' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/SmtpPluginManagerFactory.php', - 'Laminas\\Mail\\Protocol\\Smtp\\Auth\\Crammd5' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/Smtp/Auth/Crammd5.php', - 'Laminas\\Mail\\Protocol\\Smtp\\Auth\\Login' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/Smtp/Auth/Login.php', - 'Laminas\\Mail\\Protocol\\Smtp\\Auth\\Oauth' => __DIR__ . '/../..' . '/sources/Core/Authentication/Client/Smtp/SmtpOAuthLogin.php', - 'Laminas\\Mail\\Protocol\\Smtp\\Auth\\Plain' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Protocol/Smtp/Auth/Plain.php', - 'Laminas\\Mail\\Storage' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage.php', - 'Laminas\\Mail\\Storage\\AbstractStorage' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/AbstractStorage.php', - 'Laminas\\Mail\\Storage\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Exception/ExceptionInterface.php', - 'Laminas\\Mail\\Storage\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Exception/InvalidArgumentException.php', - 'Laminas\\Mail\\Storage\\Exception\\OutOfBoundsException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Exception/OutOfBoundsException.php', - 'Laminas\\Mail\\Storage\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Exception/RuntimeException.php', - 'Laminas\\Mail\\Storage\\Folder' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Folder.php', - 'Laminas\\Mail\\Storage\\Folder\\FolderInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Folder/FolderInterface.php', - 'Laminas\\Mail\\Storage\\Folder\\Maildir' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Folder/Maildir.php', - 'Laminas\\Mail\\Storage\\Folder\\Mbox' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Folder/Mbox.php', - 'Laminas\\Mail\\Storage\\Imap' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Imap.php', - 'Laminas\\Mail\\Storage\\Maildir' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Maildir.php', - 'Laminas\\Mail\\Storage\\Mbox' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Mbox.php', - 'Laminas\\Mail\\Storage\\Message' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Message.php', - 'Laminas\\Mail\\Storage\\Message\\File' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Message/File.php', - 'Laminas\\Mail\\Storage\\Message\\MessageInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Message/MessageInterface.php', - 'Laminas\\Mail\\Storage\\ParamsNormalizer' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/ParamsNormalizer.php', - 'Laminas\\Mail\\Storage\\Part' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Part.php', - 'Laminas\\Mail\\Storage\\Part\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Part/Exception/ExceptionInterface.php', - 'Laminas\\Mail\\Storage\\Part\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Part/Exception/InvalidArgumentException.php', - 'Laminas\\Mail\\Storage\\Part\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Part/Exception/RuntimeException.php', - 'Laminas\\Mail\\Storage\\Part\\File' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Part/File.php', - 'Laminas\\Mail\\Storage\\Part\\PartInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Part/PartInterface.php', - 'Laminas\\Mail\\Storage\\Pop3' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Pop3.php', - 'Laminas\\Mail\\Storage\\Writable\\Maildir' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Writable/Maildir.php', - 'Laminas\\Mail\\Storage\\Writable\\WritableInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Storage/Writable/WritableInterface.php', - 'Laminas\\Mail\\Transport\\Envelope' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/Envelope.php', - 'Laminas\\Mail\\Transport\\Exception\\DomainException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/Exception/DomainException.php', - 'Laminas\\Mail\\Transport\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/Exception/ExceptionInterface.php', - 'Laminas\\Mail\\Transport\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/Exception/InvalidArgumentException.php', - 'Laminas\\Mail\\Transport\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/Exception/RuntimeException.php', - 'Laminas\\Mail\\Transport\\Factory' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/Factory.php', - 'Laminas\\Mail\\Transport\\File' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/File.php', - 'Laminas\\Mail\\Transport\\FileOptions' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/FileOptions.php', - 'Laminas\\Mail\\Transport\\InMemory' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/InMemory.php', - 'Laminas\\Mail\\Transport\\Sendmail' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/Sendmail.php', - 'Laminas\\Mail\\Transport\\Smtp' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/Smtp.php', - 'Laminas\\Mail\\Transport\\SmtpOptions' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/SmtpOptions.php', - 'Laminas\\Mail\\Transport\\TransportInterface' => __DIR__ . '/..' . '/laminas/laminas-mail/src/Transport/TransportInterface.php', - 'Laminas\\Mime\\Decode' => __DIR__ . '/..' . '/laminas/laminas-mime/src/Decode.php', - 'Laminas\\Mime\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-mime/src/Exception/ExceptionInterface.php', - 'Laminas\\Mime\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-mime/src/Exception/InvalidArgumentException.php', - 'Laminas\\Mime\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-mime/src/Exception/RuntimeException.php', - 'Laminas\\Mime\\Message' => __DIR__ . '/..' . '/laminas/laminas-mime/src/Message.php', - 'Laminas\\Mime\\Mime' => __DIR__ . '/..' . '/laminas/laminas-mime/src/Mime.php', - 'Laminas\\Mime\\Part' => __DIR__ . '/..' . '/laminas/laminas-mime/src/Part.php', - 'Laminas\\ServiceManager\\AbstractFactoryInterface' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/AbstractFactoryInterface.php', - 'Laminas\\ServiceManager\\AbstractFactory\\ConfigAbstractFactory' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/AbstractFactory/ConfigAbstractFactory.php', - 'Laminas\\ServiceManager\\AbstractFactory\\ReflectionBasedAbstractFactory' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/AbstractFactory/ReflectionBasedAbstractFactory.php', - 'Laminas\\ServiceManager\\AbstractPluginManager' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/AbstractPluginManager.php', - 'Laminas\\ServiceManager\\Config' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Config.php', - 'Laminas\\ServiceManager\\ConfigInterface' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/ConfigInterface.php', - 'Laminas\\ServiceManager\\DelegatorFactoryInterface' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/DelegatorFactoryInterface.php', - 'Laminas\\ServiceManager\\Exception\\ContainerModificationsNotAllowedException' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Exception/ContainerModificationsNotAllowedException.php', - 'Laminas\\ServiceManager\\Exception\\CyclicAliasException' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Exception/CyclicAliasException.php', - 'Laminas\\ServiceManager\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Exception/ExceptionInterface.php', - 'Laminas\\ServiceManager\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Exception/InvalidArgumentException.php', - 'Laminas\\ServiceManager\\Exception\\InvalidServiceException' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Exception/InvalidServiceException.php', - 'Laminas\\ServiceManager\\Exception\\ServiceNotCreatedException' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Exception/ServiceNotCreatedException.php', - 'Laminas\\ServiceManager\\Exception\\ServiceNotFoundException' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Exception/ServiceNotFoundException.php', - 'Laminas\\ServiceManager\\FactoryInterface' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/FactoryInterface.php', - 'Laminas\\ServiceManager\\Factory\\AbstractFactoryInterface' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Factory/AbstractFactoryInterface.php', - 'Laminas\\ServiceManager\\Factory\\DelegatorFactoryInterface' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Factory/DelegatorFactoryInterface.php', - 'Laminas\\ServiceManager\\Factory\\FactoryInterface' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Factory/FactoryInterface.php', - 'Laminas\\ServiceManager\\Factory\\InvokableFactory' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Factory/InvokableFactory.php', - 'Laminas\\ServiceManager\\InitializerInterface' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/InitializerInterface.php', - 'Laminas\\ServiceManager\\Initializer\\InitializerInterface' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Initializer/InitializerInterface.php', - 'Laminas\\ServiceManager\\PluginManagerInterface' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/PluginManagerInterface.php', - 'Laminas\\ServiceManager\\Proxy\\LazyServiceFactory' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Proxy/LazyServiceFactory.php', - 'Laminas\\ServiceManager\\ServiceLocatorInterface' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/ServiceLocatorInterface.php', - 'Laminas\\ServiceManager\\ServiceManager' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/ServiceManager.php', - 'Laminas\\ServiceManager\\Tool\\ConfigDumper' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Tool/ConfigDumper.php', - 'Laminas\\ServiceManager\\Tool\\ConfigDumperCommand' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Tool/ConfigDumperCommand.php', - 'Laminas\\ServiceManager\\Tool\\FactoryCreator' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Tool/FactoryCreator.php', - 'Laminas\\ServiceManager\\Tool\\FactoryCreatorCommand' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/Tool/FactoryCreatorCommand.php', - 'Laminas\\Stdlib\\AbstractOptions' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/AbstractOptions.php', - 'Laminas\\Stdlib\\ArrayObject' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ArrayObject.php', - 'Laminas\\Stdlib\\ArraySerializableInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ArraySerializableInterface.php', - 'Laminas\\Stdlib\\ArrayStack' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ArrayStack.php', - 'Laminas\\Stdlib\\ArrayUtils' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ArrayUtils.php', - 'Laminas\\Stdlib\\ArrayUtils\\MergeRemoveKey' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ArrayUtils/MergeRemoveKey.php', - 'Laminas\\Stdlib\\ArrayUtils\\MergeReplaceKey' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ArrayUtils/MergeReplaceKey.php', - 'Laminas\\Stdlib\\ArrayUtils\\MergeReplaceKeyInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ArrayUtils/MergeReplaceKeyInterface.php', - 'Laminas\\Stdlib\\ConsoleHelper' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ConsoleHelper.php', - 'Laminas\\Stdlib\\DispatchableInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/DispatchableInterface.php', - 'Laminas\\Stdlib\\ErrorHandler' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ErrorHandler.php', - 'Laminas\\Stdlib\\Exception\\BadMethodCallException' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Exception/BadMethodCallException.php', - 'Laminas\\Stdlib\\Exception\\DomainException' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Exception/DomainException.php', - 'Laminas\\Stdlib\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Exception/ExceptionInterface.php', - 'Laminas\\Stdlib\\Exception\\ExtensionNotLoadedException' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Exception/ExtensionNotLoadedException.php', - 'Laminas\\Stdlib\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Exception/InvalidArgumentException.php', - 'Laminas\\Stdlib\\Exception\\LogicException' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Exception/LogicException.php', - 'Laminas\\Stdlib\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Exception/RuntimeException.php', - 'Laminas\\Stdlib\\FastPriorityQueue' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/FastPriorityQueue.php', - 'Laminas\\Stdlib\\Glob' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Glob.php', - 'Laminas\\Stdlib\\Guard\\AllGuardsTrait' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Guard/AllGuardsTrait.php', - 'Laminas\\Stdlib\\Guard\\ArrayOrTraversableGuardTrait' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Guard/ArrayOrTraversableGuardTrait.php', - 'Laminas\\Stdlib\\Guard\\EmptyGuardTrait' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Guard/EmptyGuardTrait.php', - 'Laminas\\Stdlib\\Guard\\NullGuardTrait' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Guard/NullGuardTrait.php', - 'Laminas\\Stdlib\\InitializableInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/InitializableInterface.php', - 'Laminas\\Stdlib\\JsonSerializable' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/JsonSerializable.php', - 'Laminas\\Stdlib\\Message' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Message.php', - 'Laminas\\Stdlib\\MessageInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/MessageInterface.php', - 'Laminas\\Stdlib\\ParameterObjectInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ParameterObjectInterface.php', - 'Laminas\\Stdlib\\Parameters' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Parameters.php', - 'Laminas\\Stdlib\\ParametersInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ParametersInterface.php', - 'Laminas\\Stdlib\\PriorityList' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/PriorityList.php', - 'Laminas\\Stdlib\\PriorityQueue' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/PriorityQueue.php', - 'Laminas\\Stdlib\\Request' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Request.php', - 'Laminas\\Stdlib\\RequestInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/RequestInterface.php', - 'Laminas\\Stdlib\\Response' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Response.php', - 'Laminas\\Stdlib\\ResponseInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ResponseInterface.php', - 'Laminas\\Stdlib\\SplPriorityQueue' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/SplPriorityQueue.php', - 'Laminas\\Stdlib\\SplQueue' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/SplQueue.php', - 'Laminas\\Stdlib\\SplStack' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/SplStack.php', - 'Laminas\\Stdlib\\StringUtils' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/StringUtils.php', - 'Laminas\\Stdlib\\StringWrapper\\AbstractStringWrapper' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/StringWrapper/AbstractStringWrapper.php', - 'Laminas\\Stdlib\\StringWrapper\\Iconv' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/StringWrapper/Iconv.php', - 'Laminas\\Stdlib\\StringWrapper\\Intl' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/StringWrapper/Intl.php', - 'Laminas\\Stdlib\\StringWrapper\\MbString' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/StringWrapper/MbString.php', - 'Laminas\\Stdlib\\StringWrapper\\Native' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/StringWrapper/Native.php', - 'Laminas\\Stdlib\\StringWrapper\\StringWrapperInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/StringWrapper/StringWrapperInterface.php', - 'Laminas\\Validator\\AbstractValidator' => __DIR__ . '/..' . '/laminas/laminas-validator/src/AbstractValidator.php', - 'Laminas\\Validator\\Barcode' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode.php', - 'Laminas\\Validator\\Barcode\\AbstractAdapter' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/AbstractAdapter.php', - 'Laminas\\Validator\\Barcode\\AdapterInterface' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/AdapterInterface.php', - 'Laminas\\Validator\\Barcode\\Codabar' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Codabar.php', - 'Laminas\\Validator\\Barcode\\Code128' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Code128.php', - 'Laminas\\Validator\\Barcode\\Code25' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Code25.php', - 'Laminas\\Validator\\Barcode\\Code25interleaved' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Code25interleaved.php', - 'Laminas\\Validator\\Barcode\\Code39' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Code39.php', - 'Laminas\\Validator\\Barcode\\Code39ext' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Code39ext.php', - 'Laminas\\Validator\\Barcode\\Code93' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Code93.php', - 'Laminas\\Validator\\Barcode\\Code93ext' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Code93ext.php', - 'Laminas\\Validator\\Barcode\\Ean12' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Ean12.php', - 'Laminas\\Validator\\Barcode\\Ean13' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Ean13.php', - 'Laminas\\Validator\\Barcode\\Ean14' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Ean14.php', - 'Laminas\\Validator\\Barcode\\Ean18' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Ean18.php', - 'Laminas\\Validator\\Barcode\\Ean2' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Ean2.php', - 'Laminas\\Validator\\Barcode\\Ean5' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Ean5.php', - 'Laminas\\Validator\\Barcode\\Ean8' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Ean8.php', - 'Laminas\\Validator\\Barcode\\Gtin12' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Gtin12.php', - 'Laminas\\Validator\\Barcode\\Gtin13' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Gtin13.php', - 'Laminas\\Validator\\Barcode\\Gtin14' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Gtin14.php', - 'Laminas\\Validator\\Barcode\\Identcode' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Identcode.php', - 'Laminas\\Validator\\Barcode\\Intelligentmail' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Intelligentmail.php', - 'Laminas\\Validator\\Barcode\\Issn' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Issn.php', - 'Laminas\\Validator\\Barcode\\Itf14' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Itf14.php', - 'Laminas\\Validator\\Barcode\\Leitcode' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Leitcode.php', - 'Laminas\\Validator\\Barcode\\Planet' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Planet.php', - 'Laminas\\Validator\\Barcode\\Postnet' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Postnet.php', - 'Laminas\\Validator\\Barcode\\Royalmail' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Royalmail.php', - 'Laminas\\Validator\\Barcode\\Sscc' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Sscc.php', - 'Laminas\\Validator\\Barcode\\Upca' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Upca.php', - 'Laminas\\Validator\\Barcode\\Upce' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Barcode/Upce.php', - 'Laminas\\Validator\\Between' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Between.php', - 'Laminas\\Validator\\Bitwise' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Bitwise.php', - 'Laminas\\Validator\\BusinessIdentifierCode' => __DIR__ . '/..' . '/laminas/laminas-validator/src/BusinessIdentifierCode.php', - 'Laminas\\Validator\\Callback' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Callback.php', - 'Laminas\\Validator\\ConfigProvider' => __DIR__ . '/..' . '/laminas/laminas-validator/src/ConfigProvider.php', - 'Laminas\\Validator\\CreditCard' => __DIR__ . '/..' . '/laminas/laminas-validator/src/CreditCard.php', - 'Laminas\\Validator\\Csrf' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Csrf.php', - 'Laminas\\Validator\\Date' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Date.php', - 'Laminas\\Validator\\DateStep' => __DIR__ . '/..' . '/laminas/laminas-validator/src/DateStep.php', - 'Laminas\\Validator\\Db\\AbstractDb' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Db/AbstractDb.php', - 'Laminas\\Validator\\Db\\NoRecordExists' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Db/NoRecordExists.php', - 'Laminas\\Validator\\Db\\RecordExists' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Db/RecordExists.php', - 'Laminas\\Validator\\Digits' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Digits.php', - 'Laminas\\Validator\\EmailAddress' => __DIR__ . '/..' . '/laminas/laminas-validator/src/EmailAddress.php', - 'Laminas\\Validator\\Exception\\BadMethodCallException' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Exception/BadMethodCallException.php', - 'Laminas\\Validator\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Exception/ExceptionInterface.php', - 'Laminas\\Validator\\Exception\\ExtensionNotLoadedException' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Exception/ExtensionNotLoadedException.php', - 'Laminas\\Validator\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Exception/InvalidArgumentException.php', - 'Laminas\\Validator\\Exception\\InvalidMagicMimeFileException' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Exception/InvalidMagicMimeFileException.php', - 'Laminas\\Validator\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Exception/RuntimeException.php', - 'Laminas\\Validator\\Explode' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Explode.php', - 'Laminas\\Validator\\File\\Count' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/Count.php', - 'Laminas\\Validator\\File\\Crc32' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/Crc32.php', - 'Laminas\\Validator\\File\\ExcludeExtension' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/ExcludeExtension.php', - 'Laminas\\Validator\\File\\ExcludeMimeType' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/ExcludeMimeType.php', - 'Laminas\\Validator\\File\\Exists' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/Exists.php', - 'Laminas\\Validator\\File\\Extension' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/Extension.php', - 'Laminas\\Validator\\File\\FileInformationTrait' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/FileInformationTrait.php', - 'Laminas\\Validator\\File\\FilesSize' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/FilesSize.php', - 'Laminas\\Validator\\File\\Hash' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/Hash.php', - 'Laminas\\Validator\\File\\ImageSize' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/ImageSize.php', - 'Laminas\\Validator\\File\\IsCompressed' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/IsCompressed.php', - 'Laminas\\Validator\\File\\IsImage' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/IsImage.php', - 'Laminas\\Validator\\File\\Md5' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/Md5.php', - 'Laminas\\Validator\\File\\MimeType' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/MimeType.php', - 'Laminas\\Validator\\File\\NotExists' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/NotExists.php', - 'Laminas\\Validator\\File\\Sha1' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/Sha1.php', - 'Laminas\\Validator\\File\\Size' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/Size.php', - 'Laminas\\Validator\\File\\Upload' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/Upload.php', - 'Laminas\\Validator\\File\\UploadFile' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/UploadFile.php', - 'Laminas\\Validator\\File\\WordCount' => __DIR__ . '/..' . '/laminas/laminas-validator/src/File/WordCount.php', - 'Laminas\\Validator\\GpsPoint' => __DIR__ . '/..' . '/laminas/laminas-validator/src/GpsPoint.php', - 'Laminas\\Validator\\GreaterThan' => __DIR__ . '/..' . '/laminas/laminas-validator/src/GreaterThan.php', - 'Laminas\\Validator\\Hex' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Hex.php', - 'Laminas\\Validator\\Hostname' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Hostname.php', - 'Laminas\\Validator\\Iban' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Iban.php', - 'Laminas\\Validator\\Identical' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Identical.php', - 'Laminas\\Validator\\InArray' => __DIR__ . '/..' . '/laminas/laminas-validator/src/InArray.php', - 'Laminas\\Validator\\Ip' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Ip.php', - 'Laminas\\Validator\\IsCountable' => __DIR__ . '/..' . '/laminas/laminas-validator/src/IsCountable.php', - 'Laminas\\Validator\\IsInstanceOf' => __DIR__ . '/..' . '/laminas/laminas-validator/src/IsInstanceOf.php', - 'Laminas\\Validator\\Isbn' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Isbn.php', - 'Laminas\\Validator\\Isbn\\Isbn10' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Isbn/Isbn10.php', - 'Laminas\\Validator\\Isbn\\Isbn13' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Isbn/Isbn13.php', - 'Laminas\\Validator\\LessThan' => __DIR__ . '/..' . '/laminas/laminas-validator/src/LessThan.php', - 'Laminas\\Validator\\Module' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Module.php', - 'Laminas\\Validator\\NotEmpty' => __DIR__ . '/..' . '/laminas/laminas-validator/src/NotEmpty.php', - 'Laminas\\Validator\\Regex' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Regex.php', - 'Laminas\\Validator\\Sitemap\\Changefreq' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Sitemap/Changefreq.php', - 'Laminas\\Validator\\Sitemap\\Lastmod' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Sitemap/Lastmod.php', - 'Laminas\\Validator\\Sitemap\\Loc' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Sitemap/Loc.php', - 'Laminas\\Validator\\Sitemap\\Priority' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Sitemap/Priority.php', - 'Laminas\\Validator\\StaticValidator' => __DIR__ . '/..' . '/laminas/laminas-validator/src/StaticValidator.php', - 'Laminas\\Validator\\Step' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Step.php', - 'Laminas\\Validator\\StringLength' => __DIR__ . '/..' . '/laminas/laminas-validator/src/StringLength.php', - 'Laminas\\Validator\\Timezone' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Timezone.php', - 'Laminas\\Validator\\Translator\\TranslatorAwareInterface' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Translator/TranslatorAwareInterface.php', - 'Laminas\\Validator\\Translator\\TranslatorInterface' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Translator/TranslatorInterface.php', - 'Laminas\\Validator\\UndisclosedPassword' => __DIR__ . '/..' . '/laminas/laminas-validator/src/UndisclosedPassword.php', - 'Laminas\\Validator\\Uri' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Uri.php', - 'Laminas\\Validator\\Uuid' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Uuid.php', - 'Laminas\\Validator\\ValidatorChain' => __DIR__ . '/..' . '/laminas/laminas-validator/src/ValidatorChain.php', - 'Laminas\\Validator\\ValidatorInterface' => __DIR__ . '/..' . '/laminas/laminas-validator/src/ValidatorInterface.php', - 'Laminas\\Validator\\ValidatorPluginManager' => __DIR__ . '/..' . '/laminas/laminas-validator/src/ValidatorPluginManager.php', - 'Laminas\\Validator\\ValidatorPluginManagerAwareInterface' => __DIR__ . '/..' . '/laminas/laminas-validator/src/ValidatorPluginManagerAwareInterface.php', - 'Laminas\\Validator\\ValidatorPluginManagerFactory' => __DIR__ . '/..' . '/laminas/laminas-validator/src/ValidatorPluginManagerFactory.php', - 'Laminas\\Validator\\ValidatorProviderInterface' => __DIR__ . '/..' . '/laminas/laminas-validator/src/ValidatorProviderInterface.php', - 'League\\OAuth2\\Client\\Exception\\HostedDomainException' => __DIR__ . '/..' . '/league/oauth2-google/src/Exception/HostedDomainException.php', - 'League\\OAuth2\\Client\\Grant\\AbstractGrant' => __DIR__ . '/..' . '/league/oauth2-client/src/Grant/AbstractGrant.php', - 'League\\OAuth2\\Client\\Grant\\AuthorizationCode' => __DIR__ . '/..' . '/league/oauth2-client/src/Grant/AuthorizationCode.php', - 'League\\OAuth2\\Client\\Grant\\ClientCredentials' => __DIR__ . '/..' . '/league/oauth2-client/src/Grant/ClientCredentials.php', - 'League\\OAuth2\\Client\\Grant\\Exception\\InvalidGrantException' => __DIR__ . '/..' . '/league/oauth2-client/src/Grant/Exception/InvalidGrantException.php', - 'League\\OAuth2\\Client\\Grant\\GrantFactory' => __DIR__ . '/..' . '/league/oauth2-client/src/Grant/GrantFactory.php', - 'League\\OAuth2\\Client\\Grant\\Password' => __DIR__ . '/..' . '/league/oauth2-client/src/Grant/Password.php', - 'League\\OAuth2\\Client\\Grant\\RefreshToken' => __DIR__ . '/..' . '/league/oauth2-client/src/Grant/RefreshToken.php', - 'League\\OAuth2\\Client\\OptionProvider\\HttpBasicAuthOptionProvider' => __DIR__ . '/..' . '/league/oauth2-client/src/OptionProvider/HttpBasicAuthOptionProvider.php', - 'League\\OAuth2\\Client\\OptionProvider\\OptionProviderInterface' => __DIR__ . '/..' . '/league/oauth2-client/src/OptionProvider/OptionProviderInterface.php', - 'League\\OAuth2\\Client\\OptionProvider\\PostAuthOptionProvider' => __DIR__ . '/..' . '/league/oauth2-client/src/OptionProvider/PostAuthOptionProvider.php', - 'League\\OAuth2\\Client\\Provider\\AbstractProvider' => __DIR__ . '/..' . '/league/oauth2-client/src/Provider/AbstractProvider.php', - 'League\\OAuth2\\Client\\Provider\\Exception\\IdentityProviderException' => __DIR__ . '/..' . '/league/oauth2-client/src/Provider/Exception/IdentityProviderException.php', - 'League\\OAuth2\\Client\\Provider\\GenericProvider' => __DIR__ . '/..' . '/league/oauth2-client/src/Provider/GenericProvider.php', - 'League\\OAuth2\\Client\\Provider\\GenericResourceOwner' => __DIR__ . '/..' . '/league/oauth2-client/src/Provider/GenericResourceOwner.php', - 'League\\OAuth2\\Client\\Provider\\Google' => __DIR__ . '/..' . '/league/oauth2-google/src/Provider/Google.php', - 'League\\OAuth2\\Client\\Provider\\GoogleUser' => __DIR__ . '/..' . '/league/oauth2-google/src/Provider/GoogleUser.php', - 'League\\OAuth2\\Client\\Provider\\ResourceOwnerInterface' => __DIR__ . '/..' . '/league/oauth2-client/src/Provider/ResourceOwnerInterface.php', - 'League\\OAuth2\\Client\\Token\\AccessToken' => __DIR__ . '/..' . '/league/oauth2-client/src/Token/AccessToken.php', - 'League\\OAuth2\\Client\\Token\\AccessTokenInterface' => __DIR__ . '/..' . '/league/oauth2-client/src/Token/AccessTokenInterface.php', - 'League\\OAuth2\\Client\\Token\\ResourceOwnerAccessTokenInterface' => __DIR__ . '/..' . '/league/oauth2-client/src/Token/ResourceOwnerAccessTokenInterface.php', - 'League\\OAuth2\\Client\\Tool\\ArrayAccessorTrait' => __DIR__ . '/..' . '/league/oauth2-client/src/Tool/ArrayAccessorTrait.php', - 'League\\OAuth2\\Client\\Tool\\BearerAuthorizationTrait' => __DIR__ . '/..' . '/league/oauth2-client/src/Tool/BearerAuthorizationTrait.php', - 'League\\OAuth2\\Client\\Tool\\GuardedPropertyTrait' => __DIR__ . '/..' . '/league/oauth2-client/src/Tool/GuardedPropertyTrait.php', - 'League\\OAuth2\\Client\\Tool\\MacAuthorizationTrait' => __DIR__ . '/..' . '/league/oauth2-client/src/Tool/MacAuthorizationTrait.php', - 'League\\OAuth2\\Client\\Tool\\ProviderRedirectTrait' => __DIR__ . '/..' . '/league/oauth2-client/src/Tool/ProviderRedirectTrait.php', - 'League\\OAuth2\\Client\\Tool\\QueryBuilderTrait' => __DIR__ . '/..' . '/league/oauth2-client/src/Tool/QueryBuilderTrait.php', - 'League\\OAuth2\\Client\\Tool\\RequestFactory' => __DIR__ . '/..' . '/league/oauth2-client/src/Tool/RequestFactory.php', - 'League\\OAuth2\\Client\\Tool\\RequiredParameterTrait' => __DIR__ . '/..' . '/league/oauth2-client/src/Tool/RequiredParameterTrait.php', - 'ListExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', - 'ListOqlExpression' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php', - 'Locale' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/Resources/stubs/Locale.php', - 'LogAPI' => __DIR__ . '/../..' . '/core/log.class.inc.php', - 'LogChannels' => __DIR__ . '/../..' . '/core/log.class.inc.php', - 'LogFileNameBuilderFactory' => __DIR__ . '/../..' . '/core/log.class.inc.php', - 'LogFileRotationProcess' => __DIR__ . '/../..' . '/core/log.class.inc.php', - 'LoginBlockExtension' => __DIR__ . '/../..' . '/application/logintwig.class.inc.php', - 'LoginTwigContext' => __DIR__ . '/../..' . '/application/logintwig.class.inc.php', - 'LoginTwigRenderer' => __DIR__ . '/../..' . '/application/logintwig.class.inc.php', - 'LoginWebPage' => __DIR__ . '/../..' . '/application/loginwebpage.class.inc.php', - 'MatchExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', - 'MatchOqlExpression' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php', - 'MenuBlock' => __DIR__ . '/../..' . '/application/displayblock.class.inc.php', - 'MenuGroup' => __DIR__ . '/../..' . '/application/menunode.class.inc.php', - 'MenuNode' => __DIR__ . '/../..' . '/application/menunode.class.inc.php', - 'MetaModel' => __DIR__ . '/../..' . '/core/metamodel.class.php', - 'MissingColumnException' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'MissingQueryArgument' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', - 'ModelReflection' => __DIR__ . '/../..' . '/core/modelreflection.class.inc.php', - 'ModelReflectionRuntime' => __DIR__ . '/../..' . '/core/modelreflection.class.inc.php', - 'ModuleDesign' => __DIR__ . '/../..' . '/core/moduledesign.class.inc.php', - 'ModuleHandlerAPI' => __DIR__ . '/../..' . '/core/modulehandler.class.inc.php', - 'ModuleHandlerApiInterface' => __DIR__ . '/../..' . '/core/modulehandler.class.inc.php', - 'MonthlyRotatingLogFileNameBuilder' => __DIR__ . '/../..' . '/core/log.class.inc.php', - 'MyHelpers' => __DIR__ . '/../..' . '/core/MyHelpers.class.inc.php', - 'MySQLException' => __DIR__ . '/../..' . '/application/exceptions/mysql/MySQLException.php', - 'MySQLHasGoneAwayException' => __DIR__ . '/../..' . '/application/exceptions/mysql/MySQLHasGoneAwayException.php', - 'MySQLNoTransactionException' => __DIR__ . '/../..' . '/application/exceptions/mysql/MySQLNoTransactionException.php', - 'MySQLQueryHasNoResultException' => __DIR__ . '/../..' . '/application/exceptions/mysql/MySQLQueryHasNoResultException.php', - 'MySQLTransactionNotClosedException' => __DIR__ . '/../..' . '/application/exceptions/mysql/MySQLTransactionNotClosedException.php', - 'NestedQueryExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', - 'NestedQueryOqlExpression' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php', - 'NewObjectMenuNode' => __DIR__ . '/../..' . '/application/menunode.class.inc.php', - 'NewsroomProviderBase' => __DIR__ . '/../..' . '/application/newsroomprovider.class.inc.php', - 'NiceWebPage' => __DIR__ . '/../..' . '/sources/Application/WebPage/NiceWebPage.php', - 'Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php', - 'NotYetEvaluatedExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', - 'NumberFormatter' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/Resources/stubs/NumberFormatter.php', - 'OQLActualClassTreeResolver' => __DIR__ . '/../..' . '/core/oqlactualclasstreeresolver.class.inc.php', - 'OQLClassNode' => __DIR__ . '/../..' . '/core/oqlclassnode.class.inc.php', - 'OQLClassTreeBuilder' => __DIR__ . '/../..' . '/core/oqlclasstreebuilder.class.inc.php', - 'OQLClassTreeOptimizer' => __DIR__ . '/../..' . '/core/oqlclasstreeoptimizer.class.inc.php', - 'OQLException' => __DIR__ . '/../..' . '/core/oql/oqlexception.class.inc.php', - 'OQLJoin' => __DIR__ . '/../..' . '/core/oqlclassnode.class.inc.php', - 'OQLLexer' => __DIR__ . '/../..' . '/core/oql/oql-lexer.php', - 'OQLLexerException' => __DIR__ . '/../..' . '/core/oql/oql-lexer.php', - 'OQLLexerRaw' => __DIR__ . '/../..' . '/core/oql/oql-lexer.php', - 'OQLMenuNode' => __DIR__ . '/../..' . '/application/menunode.class.inc.php', - 'OQLParser' => __DIR__ . '/../..' . '/core/oql/oql-parser.php', - 'OQLParserException' => __DIR__ . '/../..' . '/core/oql/oql-parser.php', - 'OQLParserParseFailureException' => __DIR__ . '/../..' . '/core/oql/oql-parser.php', - 'OQLParserRaw' => __DIR__ . '/../..' . '/core/oql/oql-parser.php', - 'OQLParserStackOverFlowException' => __DIR__ . '/../..' . '/core/oql/oql-parser.php', - 'OQLParserSyntaxErrorException' => __DIR__ . '/../..' . '/core/oql/oql-parser.php', - 'OQLParser_yyStackEntry' => __DIR__ . '/../..' . '/core/oql/oql-parser.php', - 'OQLParser_yyToken' => __DIR__ . '/../..' . '/core/oql/oql-parser.php', - 'OS_Guess' => __DIR__ . '/..' . '/pear/pear-core-minimal/src/OS/Guess.php', - 'ObjectDetailsTemplate' => __DIR__ . '/../..' . '/application/template.class.inc.php', - 'ObjectResult' => __DIR__ . '/../..' . '/core/restservices.class.inc.php', - 'ObjectStimulus' => __DIR__ . '/../..' . '/core/stimulus.class.inc.php', - 'ObsolescenceDateUpdater' => __DIR__ . '/../..' . '/core/background.inc.php', - 'OqlHexValue' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php', - 'OqlInterpreter' => __DIR__ . '/../..' . '/core/oql/oqlinterpreter.class.inc.php', - 'OqlInterpreterException' => __DIR__ . '/../..' . '/core/oql/oqlinterpreter.class.inc.php', - 'OqlJoinSpec' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php', - 'OqlName' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php', - 'OqlNormalizeException' => __DIR__ . '/../..' . '/core/oql/oqlinterpreter.class.inc.php', - 'OqlObjectQuery' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php', - 'OqlQuery' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php', - 'OqlUnionQuery' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php', - 'PDF417' => __DIR__ . '/..' . '/combodo/tcpdf/include/barcodes/pdf417.php', - 'PDFBulkExport' => __DIR__ . '/../..' . '/core/pdfbulkexport.class.inc.php', - 'PDFPage' => __DIR__ . '/../..' . '/sources/Application/WebPage/PDFPage.php', - 'PEAR' => __DIR__ . '/..' . '/pear/pear-core-minimal/src/PEAR.php', - 'PEAR_ErrorStack' => __DIR__ . '/..' . '/pear/pear-core-minimal/src/PEAR/ErrorStack.php', - 'PEAR_Exception' => __DIR__ . '/..' . '/pear/pear_exception/PEAR/Exception.php', - 'Page' => __DIR__ . '/../..' . '/sources/Application/WebPage/Page.php', - 'Pelago\\Emogrifier\\Caching\\SimpleStringCache' => __DIR__ . '/..' . '/pelago/emogrifier/src/Caching/SimpleStringCache.php', - 'Pelago\\Emogrifier\\CssInliner' => __DIR__ . '/..' . '/pelago/emogrifier/src/CssInliner.php', - 'Pelago\\Emogrifier\\Css\\CssDocument' => __DIR__ . '/..' . '/pelago/emogrifier/src/Css/CssDocument.php', - 'Pelago\\Emogrifier\\Css\\StyleRule' => __DIR__ . '/..' . '/pelago/emogrifier/src/Css/StyleRule.php', - 'Pelago\\Emogrifier\\HtmlProcessor\\AbstractHtmlProcessor' => __DIR__ . '/..' . '/pelago/emogrifier/src/HtmlProcessor/AbstractHtmlProcessor.php', - 'Pelago\\Emogrifier\\HtmlProcessor\\CssToAttributeConverter' => __DIR__ . '/..' . '/pelago/emogrifier/src/HtmlProcessor/CssToAttributeConverter.php', - 'Pelago\\Emogrifier\\HtmlProcessor\\HtmlNormalizer' => __DIR__ . '/..' . '/pelago/emogrifier/src/HtmlProcessor/HtmlNormalizer.php', - 'Pelago\\Emogrifier\\HtmlProcessor\\HtmlPruner' => __DIR__ . '/..' . '/pelago/emogrifier/src/HtmlProcessor/HtmlPruner.php', - 'Pelago\\Emogrifier\\Utilities\\ArrayIntersector' => __DIR__ . '/..' . '/pelago/emogrifier/src/Utilities/ArrayIntersector.php', - 'Pelago\\Emogrifier\\Utilities\\CssConcatenator' => __DIR__ . '/..' . '/pelago/emogrifier/src/Utilities/CssConcatenator.php', - 'PhpParser\\Builder' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder.php', - 'PhpParser\\BuilderFactory' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/BuilderFactory.php', - 'PhpParser\\BuilderHelpers' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/BuilderHelpers.php', - 'PhpParser\\Builder\\ClassConst' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/ClassConst.php', - 'PhpParser\\Builder\\Class_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Class_.php', - 'PhpParser\\Builder\\Declaration' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Declaration.php', - 'PhpParser\\Builder\\EnumCase' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/EnumCase.php', - 'PhpParser\\Builder\\Enum_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Enum_.php', - 'PhpParser\\Builder\\FunctionLike' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php', - 'PhpParser\\Builder\\Function_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Function_.php', - 'PhpParser\\Builder\\Interface_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Interface_.php', - 'PhpParser\\Builder\\Method' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Method.php', - 'PhpParser\\Builder\\Namespace_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php', - 'PhpParser\\Builder\\Param' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Param.php', - 'PhpParser\\Builder\\Property' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Property.php', - 'PhpParser\\Builder\\TraitUse' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/TraitUse.php', - 'PhpParser\\Builder\\TraitUseAdaptation' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.php', - 'PhpParser\\Builder\\Trait_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Trait_.php', - 'PhpParser\\Builder\\Use_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Use_.php', - 'PhpParser\\Comment' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Comment.php', - 'PhpParser\\Comment\\Doc' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Comment/Doc.php', - 'PhpParser\\ConstExprEvaluationException' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ConstExprEvaluationException.php', - 'PhpParser\\ConstExprEvaluator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.php', - 'PhpParser\\Error' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Error.php', - 'PhpParser\\ErrorHandler' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ErrorHandler.php', - 'PhpParser\\ErrorHandler\\Collecting' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ErrorHandler/Collecting.php', - 'PhpParser\\ErrorHandler\\Throwing' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php', - 'PhpParser\\Internal\\DiffElem' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Internal/DiffElem.php', - 'PhpParser\\Internal\\Differ' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Internal/Differ.php', - 'PhpParser\\Internal\\PrintableNewAnonClassNode' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php', - 'PhpParser\\Internal\\TokenStream' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php', - 'PhpParser\\JsonDecoder' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/JsonDecoder.php', - 'PhpParser\\Lexer' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer.php', - 'PhpParser\\Lexer\\Emulative' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php', - 'PhpParser\\Lexer\\TokenEmulator\\AttributeEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php', - 'PhpParser\\Lexer\\TokenEmulator\\CoaleseEqualTokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/CoaleseEqualTokenEmulator.php', - 'PhpParser\\Lexer\\TokenEmulator\\EnumTokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/EnumTokenEmulator.php', - 'PhpParser\\Lexer\\TokenEmulator\\ExplicitOctalEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ExplicitOctalEmulator.php', - 'PhpParser\\Lexer\\TokenEmulator\\FlexibleDocStringEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php', - 'PhpParser\\Lexer\\TokenEmulator\\FnTokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php', - 'PhpParser\\Lexer\\TokenEmulator\\KeywordEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php', - 'PhpParser\\Lexer\\TokenEmulator\\MatchTokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php', - 'PhpParser\\Lexer\\TokenEmulator\\NullsafeTokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php', - 'PhpParser\\Lexer\\TokenEmulator\\NumericLiteralSeparatorEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php', - 'PhpParser\\Lexer\\TokenEmulator\\ReadonlyTokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyTokenEmulator.php', - 'PhpParser\\Lexer\\TokenEmulator\\ReverseEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.php', - 'PhpParser\\Lexer\\TokenEmulator\\TokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php', - 'PhpParser\\NameContext' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NameContext.php', - 'PhpParser\\Node' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node.php', - 'PhpParser\\NodeAbstract' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeAbstract.php', - 'PhpParser\\NodeDumper' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeDumper.php', - 'PhpParser\\NodeFinder' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeFinder.php', - 'PhpParser\\NodeTraverser' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeTraverser.php', - 'PhpParser\\NodeTraverserInterface' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php', - 'PhpParser\\NodeVisitor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitor.php', - 'PhpParser\\NodeVisitorAbstract' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php', - 'PhpParser\\NodeVisitor\\CloningVisitor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php', - 'PhpParser\\NodeVisitor\\FindingVisitor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php', - 'PhpParser\\NodeVisitor\\FirstFindingVisitor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.php', - 'PhpParser\\NodeVisitor\\NameResolver' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php', - 'PhpParser\\NodeVisitor\\NodeConnectingVisitor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php', - 'PhpParser\\NodeVisitor\\ParentConnectingVisitor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php', - 'PhpParser\\Node\\Arg' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Arg.php', - 'PhpParser\\Node\\Attribute' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Attribute.php', - 'PhpParser\\Node\\AttributeGroup' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php', - 'PhpParser\\Node\\ComplexType' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/ComplexType.php', - 'PhpParser\\Node\\Const_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Const_.php', - 'PhpParser\\Node\\Expr' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr.php', - 'PhpParser\\Node\\Expr\\ArrayDimFetch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php', - 'PhpParser\\Node\\Expr\\ArrayItem' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php', - 'PhpParser\\Node\\Expr\\Array_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php', - 'PhpParser\\Node\\Expr\\ArrowFunction' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php', - 'PhpParser\\Node\\Expr\\Assign' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php', - 'PhpParser\\Node\\Expr\\AssignOp' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php', - 'PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php', - 'PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php', - 'PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php', - 'PhpParser\\Node\\Expr\\AssignOp\\Coalesce' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Coalesce.php', - 'PhpParser\\Node\\Expr\\AssignOp\\Concat' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.php', - 'PhpParser\\Node\\Expr\\AssignOp\\Div' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.php', - 'PhpParser\\Node\\Expr\\AssignOp\\Minus' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.php', - 'PhpParser\\Node\\Expr\\AssignOp\\Mod' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.php', - 'PhpParser\\Node\\Expr\\AssignOp\\Mul' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.php', - 'PhpParser\\Node\\Expr\\AssignOp\\Plus' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.php', - 'PhpParser\\Node\\Expr\\AssignOp\\Pow' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.php', - 'PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php', - 'PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php', - 'PhpParser\\Node\\Expr\\AssignRef' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignRef.php', - 'PhpParser\\Node\\Expr\\BinaryOp' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Coalesce' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Concat' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Div' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Equal' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Greater' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Identical' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Minus' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Mod' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Mul' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Plus' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Pow' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php', - 'PhpParser\\Node\\Expr\\BinaryOp\\Spaceship' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php', - 'PhpParser\\Node\\Expr\\BitwiseNot' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php', - 'PhpParser\\Node\\Expr\\BooleanNot' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php', - 'PhpParser\\Node\\Expr\\CallLike' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/CallLike.php', - 'PhpParser\\Node\\Expr\\Cast' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php', - 'PhpParser\\Node\\Expr\\Cast\\Array_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php', - 'PhpParser\\Node\\Expr\\Cast\\Bool_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php', - 'PhpParser\\Node\\Expr\\Cast\\Double' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Double.php', - 'PhpParser\\Node\\Expr\\Cast\\Int_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.php', - 'PhpParser\\Node\\Expr\\Cast\\Object_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.php', - 'PhpParser\\Node\\Expr\\Cast\\String_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/String_.php', - 'PhpParser\\Node\\Expr\\Cast\\Unset_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.php', - 'PhpParser\\Node\\Expr\\ClassConstFetch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php', - 'PhpParser\\Node\\Expr\\Clone_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php', - 'PhpParser\\Node\\Expr\\Closure' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php', - 'PhpParser\\Node\\Expr\\ClosureUse' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php', - 'PhpParser\\Node\\Expr\\ConstFetch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php', - 'PhpParser\\Node\\Expr\\Empty_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php', - 'PhpParser\\Node\\Expr\\Error' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php', - 'PhpParser\\Node\\Expr\\ErrorSuppress' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php', - 'PhpParser\\Node\\Expr\\Eval_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php', - 'PhpParser\\Node\\Expr\\Exit_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php', - 'PhpParser\\Node\\Expr\\FuncCall' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php', - 'PhpParser\\Node\\Expr\\Include_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php', - 'PhpParser\\Node\\Expr\\Instanceof_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php', - 'PhpParser\\Node\\Expr\\Isset_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php', - 'PhpParser\\Node\\Expr\\List_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php', - 'PhpParser\\Node\\Expr\\Match_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.php', - 'PhpParser\\Node\\Expr\\MethodCall' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php', - 'PhpParser\\Node\\Expr\\New_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php', - 'PhpParser\\Node\\Expr\\NullsafeMethodCall' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php', - 'PhpParser\\Node\\Expr\\NullsafePropertyFetch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php', - 'PhpParser\\Node\\Expr\\PostDec' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php', - 'PhpParser\\Node\\Expr\\PostInc' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php', - 'PhpParser\\Node\\Expr\\PreDec' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php', - 'PhpParser\\Node\\Expr\\PreInc' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php', - 'PhpParser\\Node\\Expr\\Print_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php', - 'PhpParser\\Node\\Expr\\PropertyFetch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php', - 'PhpParser\\Node\\Expr\\ShellExec' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php', - 'PhpParser\\Node\\Expr\\StaticCall' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php', - 'PhpParser\\Node\\Expr\\StaticPropertyFetch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php', - 'PhpParser\\Node\\Expr\\Ternary' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php', - 'PhpParser\\Node\\Expr\\Throw_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.php', - 'PhpParser\\Node\\Expr\\UnaryMinus' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php', - 'PhpParser\\Node\\Expr\\UnaryPlus' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php', - 'PhpParser\\Node\\Expr\\Variable' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php', - 'PhpParser\\Node\\Expr\\YieldFrom' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php', - 'PhpParser\\Node\\Expr\\Yield_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php', - 'PhpParser\\Node\\FunctionLike' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php', - 'PhpParser\\Node\\Identifier' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Identifier.php', - 'PhpParser\\Node\\IntersectionType' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/IntersectionType.php', - 'PhpParser\\Node\\MatchArm' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/MatchArm.php', - 'PhpParser\\Node\\Name' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Name.php', - 'PhpParser\\Node\\Name\\FullyQualified' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php', - 'PhpParser\\Node\\Name\\Relative' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php', - 'PhpParser\\Node\\NullableType' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/NullableType.php', - 'PhpParser\\Node\\Param' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Param.php', - 'PhpParser\\Node\\Scalar' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar.php', - 'PhpParser\\Node\\Scalar\\DNumber' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/DNumber.php', - 'PhpParser\\Node\\Scalar\\Encapsed' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php', - 'PhpParser\\Node\\Scalar\\EncapsedStringPart' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php', - 'PhpParser\\Node\\Scalar\\LNumber' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php', - 'PhpParser\\Node\\Scalar\\MagicConst' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php', - 'PhpParser\\Node\\Scalar\\MagicConst\\Class_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php', - 'PhpParser\\Node\\Scalar\\MagicConst\\Dir' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php', - 'PhpParser\\Node\\Scalar\\MagicConst\\File' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php', - 'PhpParser\\Node\\Scalar\\MagicConst\\Function_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.php', - 'PhpParser\\Node\\Scalar\\MagicConst\\Line' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php', - 'PhpParser\\Node\\Scalar\\MagicConst\\Method' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.php', - 'PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php', - 'PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.php', - 'PhpParser\\Node\\Scalar\\String_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/String_.php', - 'PhpParser\\Node\\Stmt' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt.php', - 'PhpParser\\Node\\Stmt\\Break_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Break_.php', - 'PhpParser\\Node\\Stmt\\Case_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php', - 'PhpParser\\Node\\Stmt\\Catch_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php', - 'PhpParser\\Node\\Stmt\\ClassConst' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php', - 'PhpParser\\Node\\Stmt\\ClassLike' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php', - 'PhpParser\\Node\\Stmt\\ClassMethod' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php', - 'PhpParser\\Node\\Stmt\\Class_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php', - 'PhpParser\\Node\\Stmt\\Const_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php', - 'PhpParser\\Node\\Stmt\\Continue_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php', - 'PhpParser\\Node\\Stmt\\DeclareDeclare' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php', - 'PhpParser\\Node\\Stmt\\Declare_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php', - 'PhpParser\\Node\\Stmt\\Do_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php', - 'PhpParser\\Node\\Stmt\\Echo_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php', - 'PhpParser\\Node\\Stmt\\ElseIf_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php', - 'PhpParser\\Node\\Stmt\\Else_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php', - 'PhpParser\\Node\\Stmt\\EnumCase' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/EnumCase.php', - 'PhpParser\\Node\\Stmt\\Enum_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Enum_.php', - 'PhpParser\\Node\\Stmt\\Expression' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.php', - 'PhpParser\\Node\\Stmt\\Finally_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php', - 'PhpParser\\Node\\Stmt\\For_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php', - 'PhpParser\\Node\\Stmt\\Foreach_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php', - 'PhpParser\\Node\\Stmt\\Function_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php', - 'PhpParser\\Node\\Stmt\\Global_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php', - 'PhpParser\\Node\\Stmt\\Goto_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php', - 'PhpParser\\Node\\Stmt\\GroupUse' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php', - 'PhpParser\\Node\\Stmt\\HaltCompiler' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php', - 'PhpParser\\Node\\Stmt\\If_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php', - 'PhpParser\\Node\\Stmt\\InlineHTML' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php', - 'PhpParser\\Node\\Stmt\\Interface_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php', - 'PhpParser\\Node\\Stmt\\Label' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php', - 'PhpParser\\Node\\Stmt\\Namespace_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php', - 'PhpParser\\Node\\Stmt\\Nop' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php', - 'PhpParser\\Node\\Stmt\\Property' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php', - 'PhpParser\\Node\\Stmt\\PropertyProperty' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php', - 'PhpParser\\Node\\Stmt\\Return_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php', - 'PhpParser\\Node\\Stmt\\StaticVar' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php', - 'PhpParser\\Node\\Stmt\\Static_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php', - 'PhpParser\\Node\\Stmt\\Switch_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php', - 'PhpParser\\Node\\Stmt\\Throw_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php', - 'PhpParser\\Node\\Stmt\\TraitUse' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php', - 'PhpParser\\Node\\Stmt\\TraitUseAdaptation' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php', - 'PhpParser\\Node\\Stmt\\TraitUseAdaptation\\Alias' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php', - 'PhpParser\\Node\\Stmt\\TraitUseAdaptation\\Precedence' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php', - 'PhpParser\\Node\\Stmt\\Trait_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php', - 'PhpParser\\Node\\Stmt\\TryCatch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php', - 'PhpParser\\Node\\Stmt\\Unset_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php', - 'PhpParser\\Node\\Stmt\\UseUse' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php', - 'PhpParser\\Node\\Stmt\\Use_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php', - 'PhpParser\\Node\\Stmt\\While_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php', - 'PhpParser\\Node\\UnionType' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/UnionType.php', - 'PhpParser\\Node\\VarLikeIdentifier' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php', - 'PhpParser\\Node\\VariadicPlaceholder' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/VariadicPlaceholder.php', - 'PhpParser\\Parser' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Parser.php', - 'PhpParser\\ParserAbstract' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ParserAbstract.php', - 'PhpParser\\ParserFactory' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ParserFactory.php', - 'PhpParser\\Parser\\Multiple' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Parser/Multiple.php', - 'PhpParser\\Parser\\Php5' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Parser/Php5.php', - 'PhpParser\\Parser\\Php7' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Parser/Php7.php', - 'PhpParser\\Parser\\Tokens' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Parser/Tokens.php', - 'PhpParser\\PrettyPrinterAbstract' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php', - 'PhpParser\\PrettyPrinter\\Standard' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php', - 'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', - 'PluginInstanciationManager' => __DIR__ . '/../..' . '/core/plugininstanciationmanager.class.inc.php', - 'PluginManager' => __DIR__ . '/../..' . '/core/pluginmanager.class.inc.php', - 'PortalDispatcher' => __DIR__ . '/../..' . '/application/portaldispatcher.class.inc.php', - 'PortalURLMaker' => __DIR__ . '/../..' . '/application/applicationcontext.class.inc.php', - 'PrintableDataTable' => __DIR__ . '/../..' . '/application/datatable.class.inc.php', - 'ProcessException' => __DIR__ . '/../..' . '/application/exceptions/process/ProcessException.php', - 'ProcessFatalException' => __DIR__ . '/../..' . '/application/exceptions/process/ProcessFatalException.php', - 'ProcessInvalidConfigException' => __DIR__ . '/../..' . '/application/exceptions/process/ProcessInvalidConfigException.php', - 'Psr\\Cache\\CacheException' => __DIR__ . '/..' . '/psr/cache/src/CacheException.php', - 'Psr\\Cache\\CacheItemInterface' => __DIR__ . '/..' . '/psr/cache/src/CacheItemInterface.php', - 'Psr\\Cache\\CacheItemPoolInterface' => __DIR__ . '/..' . '/psr/cache/src/CacheItemPoolInterface.php', - 'Psr\\Cache\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/cache/src/InvalidArgumentException.php', - 'Psr\\Container\\ContainerExceptionInterface' => __DIR__ . '/..' . '/psr/container/src/ContainerExceptionInterface.php', - 'Psr\\Container\\ContainerInterface' => __DIR__ . '/..' . '/psr/container/src/ContainerInterface.php', - 'Psr\\Container\\NotFoundExceptionInterface' => __DIR__ . '/..' . '/psr/container/src/NotFoundExceptionInterface.php', - 'Psr\\EventDispatcher\\EventDispatcherInterface' => __DIR__ . '/..' . '/psr/event-dispatcher/src/EventDispatcherInterface.php', - 'Psr\\EventDispatcher\\ListenerProviderInterface' => __DIR__ . '/..' . '/psr/event-dispatcher/src/ListenerProviderInterface.php', - 'Psr\\EventDispatcher\\StoppableEventInterface' => __DIR__ . '/..' . '/psr/event-dispatcher/src/StoppableEventInterface.php', - 'Psr\\Http\\Client\\ClientExceptionInterface' => __DIR__ . '/..' . '/psr/http-client/src/ClientExceptionInterface.php', - 'Psr\\Http\\Client\\ClientInterface' => __DIR__ . '/..' . '/psr/http-client/src/ClientInterface.php', - 'Psr\\Http\\Client\\NetworkExceptionInterface' => __DIR__ . '/..' . '/psr/http-client/src/NetworkExceptionInterface.php', - 'Psr\\Http\\Client\\RequestExceptionInterface' => __DIR__ . '/..' . '/psr/http-client/src/RequestExceptionInterface.php', - 'Psr\\Http\\Message\\MessageInterface' => __DIR__ . '/..' . '/psr/http-message/src/MessageInterface.php', - 'Psr\\Http\\Message\\RequestFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/RequestFactoryInterface.php', - 'Psr\\Http\\Message\\RequestInterface' => __DIR__ . '/..' . '/psr/http-message/src/RequestInterface.php', - 'Psr\\Http\\Message\\ResponseFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/ResponseFactoryInterface.php', - 'Psr\\Http\\Message\\ResponseInterface' => __DIR__ . '/..' . '/psr/http-message/src/ResponseInterface.php', - 'Psr\\Http\\Message\\ServerRequestFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/ServerRequestFactoryInterface.php', - 'Psr\\Http\\Message\\ServerRequestInterface' => __DIR__ . '/..' . '/psr/http-message/src/ServerRequestInterface.php', - 'Psr\\Http\\Message\\StreamFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/StreamFactoryInterface.php', - 'Psr\\Http\\Message\\StreamInterface' => __DIR__ . '/..' . '/psr/http-message/src/StreamInterface.php', - 'Psr\\Http\\Message\\UploadedFileFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/UploadedFileFactoryInterface.php', - 'Psr\\Http\\Message\\UploadedFileInterface' => __DIR__ . '/..' . '/psr/http-message/src/UploadedFileInterface.php', - 'Psr\\Http\\Message\\UriFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/UriFactoryInterface.php', - 'Psr\\Http\\Message\\UriInterface' => __DIR__ . '/..' . '/psr/http-message/src/UriInterface.php', - 'Psr\\Log\\AbstractLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/AbstractLogger.php', - 'Psr\\Log\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/log/Psr/Log/InvalidArgumentException.php', - 'Psr\\Log\\LogLevel' => __DIR__ . '/..' . '/psr/log/Psr/Log/LogLevel.php', - 'Psr\\Log\\LoggerAwareInterface' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerAwareInterface.php', - 'Psr\\Log\\LoggerAwareTrait' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerAwareTrait.php', - 'Psr\\Log\\LoggerInterface' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerInterface.php', - 'Psr\\Log\\LoggerTrait' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerTrait.php', - 'Psr\\Log\\NullLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/NullLogger.php', - 'QRcode' => __DIR__ . '/..' . '/combodo/tcpdf/include/barcodes/qrcode.php', - 'Query' => __DIR__ . '/../..' . '/application/query.class.inc.php', - 'QueryBuilderContext' => __DIR__ . '/../..' . '/core/querybuildercontext.class.inc.php', - 'QueryBuilderExpressions' => __DIR__ . '/../..' . '/core/querybuilderexpressions.class.inc.php', - 'QueryOQL' => __DIR__ . '/../..' . '/application/query.class.inc.php', - 'QueryReflection' => __DIR__ . '/../..' . '/core/modelreflection.class.inc.php', - 'QueryReflectionRuntime' => __DIR__ . '/../..' . '/core/modelreflection.class.inc.php', - 'RelationEdge' => __DIR__ . '/../..' . '/core/relationgraph.class.inc.php', - 'RelationGraph' => __DIR__ . '/../..' . '/core/relationgraph.class.inc.php', - 'RelationObjectNode' => __DIR__ . '/../..' . '/core/relationgraph.class.inc.php', - 'RelationRedundancyNode' => __DIR__ . '/../..' . '/core/relationgraph.class.inc.php', - 'RelationTypeIterator' => __DIR__ . '/../..' . '/core/simplegraph.class.inc.php', - 'RestDelete' => __DIR__ . '/../..' . '/core/restservices.class.inc.php', - 'RestResult' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'RestResultWithObjects' => __DIR__ . '/../..' . '/core/restservices.class.inc.php', - 'RestResultWithRelations' => __DIR__ . '/../..' . '/core/restservices.class.inc.php', - 'RestUtils' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'ReturnTypeWillChange' => __DIR__ . '/..' . '/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php', - 'RotatingLogFileNameBuilder' => __DIR__ . '/../..' . '/core/log.class.inc.php', - 'RowStatus' => __DIR__ . '/../..' . '/core/bulkchange.class.inc.php', - 'RowStatus_Disappeared' => __DIR__ . '/../..' . '/core/bulkchange.class.inc.php', - 'RowStatus_Error' => __DIR__ . '/../..' . '/core/bulkchange.class.inc.php', - 'RowStatus_Issue' => __DIR__ . '/../..' . '/core/bulkchange.class.inc.php', - 'RowStatus_Modify' => __DIR__ . '/../..' . '/core/bulkchange.class.inc.php', - 'RowStatus_NewObj' => __DIR__ . '/../..' . '/core/bulkchange.class.inc.php', - 'RowStatus_NoChange' => __DIR__ . '/../..' . '/core/bulkchange.class.inc.php', - 'RunTimeIconSelectionField' => __DIR__ . '/../..' . '/application/forms.class.inc.php', - 'RuntimeDashboard' => __DIR__ . '/../..' . '/application/dashboard.class.inc.php', - 'SQLExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', - 'SQLObjectQuery' => __DIR__ . '/../..' . '/core/sqlobjectquery.class.inc.php', - 'SQLObjectQueryBuilder' => __DIR__ . '/../..' . '/core/sqlobjectquerybuilder.class.inc.php', - 'SQLQuery' => __DIR__ . '/../..' . '/core/sqlquery.class.inc.php', - 'SQLUnionQuery' => __DIR__ . '/../..' . '/core/sqlunionquery.class.inc.php', - 'SVGDOMSanitizer' => __DIR__ . '/../..' . '/core/htmlsanitizer.class.inc.php', - 'Sabberworm\\CSS\\CSSList\\AtRuleBlockList' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/CSSList/AtRuleBlockList.php', - 'Sabberworm\\CSS\\CSSList\\CSSBlockList' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/CSSList/CSSBlockList.php', - 'Sabberworm\\CSS\\CSSList\\CSSList' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/CSSList/CSSList.php', - 'Sabberworm\\CSS\\CSSList\\Document' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/CSSList/Document.php', - 'Sabberworm\\CSS\\CSSList\\KeyFrame' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/CSSList/KeyFrame.php', - 'Sabberworm\\CSS\\Comment\\Comment' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Comment/Comment.php', - 'Sabberworm\\CSS\\Comment\\Commentable' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Comment/Commentable.php', - 'Sabberworm\\CSS\\OutputFormat' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/OutputFormat.php', - 'Sabberworm\\CSS\\OutputFormatter' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/OutputFormatter.php', - 'Sabberworm\\CSS\\Parser' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Parser.php', - 'Sabberworm\\CSS\\Parsing\\OutputException' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Parsing/OutputException.php', - 'Sabberworm\\CSS\\Parsing\\ParserState' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Parsing/ParserState.php', - 'Sabberworm\\CSS\\Parsing\\SourceException' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Parsing/SourceException.php', - 'Sabberworm\\CSS\\Parsing\\UnexpectedEOFException' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Parsing/UnexpectedEOFException.php', - 'Sabberworm\\CSS\\Parsing\\UnexpectedTokenException' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Parsing/UnexpectedTokenException.php', - 'Sabberworm\\CSS\\Property\\AtRule' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Property/AtRule.php', - 'Sabberworm\\CSS\\Property\\CSSNamespace' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Property/CSSNamespace.php', - 'Sabberworm\\CSS\\Property\\Charset' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Property/Charset.php', - 'Sabberworm\\CSS\\Property\\Import' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Property/Import.php', - 'Sabberworm\\CSS\\Property\\KeyframeSelector' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Property/KeyframeSelector.php', - 'Sabberworm\\CSS\\Property\\Selector' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Property/Selector.php', - 'Sabberworm\\CSS\\Renderable' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Renderable.php', - 'Sabberworm\\CSS\\RuleSet\\AtRuleSet' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/RuleSet/AtRuleSet.php', - 'Sabberworm\\CSS\\RuleSet\\DeclarationBlock' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/RuleSet/DeclarationBlock.php', - 'Sabberworm\\CSS\\RuleSet\\RuleSet' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/RuleSet/RuleSet.php', - 'Sabberworm\\CSS\\Rule\\Rule' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Rule/Rule.php', - 'Sabberworm\\CSS\\Settings' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Settings.php', - 'Sabberworm\\CSS\\Value\\CSSFunction' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Value/CSSFunction.php', - 'Sabberworm\\CSS\\Value\\CSSString' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Value/CSSString.php', - 'Sabberworm\\CSS\\Value\\CalcFunction' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Value/CalcFunction.php', - 'Sabberworm\\CSS\\Value\\CalcRuleValueList' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Value/CalcRuleValueList.php', - 'Sabberworm\\CSS\\Value\\Color' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Value/Color.php', - 'Sabberworm\\CSS\\Value\\LineName' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Value/LineName.php', - 'Sabberworm\\CSS\\Value\\PrimitiveValue' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Value/PrimitiveValue.php', - 'Sabberworm\\CSS\\Value\\RuleValueList' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Value/RuleValueList.php', - 'Sabberworm\\CSS\\Value\\Size' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Value/Size.php', - 'Sabberworm\\CSS\\Value\\URL' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Value/URL.php', - 'Sabberworm\\CSS\\Value\\Value' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Value/Value.php', - 'Sabberworm\\CSS\\Value\\ValueList' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Value/ValueList.php', - 'ScalarExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', - 'ScalarOqlExpression' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php', - 'ScssPhp\\ScssPhp\\Base\\Range' => __DIR__ . '/..' . '/scssphp/scssphp/src/Base/Range.php', - 'ScssPhp\\ScssPhp\\Block' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block.php', - 'ScssPhp\\ScssPhp\\Block\\AtRootBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block/AtRootBlock.php', - 'ScssPhp\\ScssPhp\\Block\\CallableBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block/CallableBlock.php', - 'ScssPhp\\ScssPhp\\Block\\ContentBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block/ContentBlock.php', - 'ScssPhp\\ScssPhp\\Block\\DirectiveBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block/DirectiveBlock.php', - 'ScssPhp\\ScssPhp\\Block\\EachBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block/EachBlock.php', - 'ScssPhp\\ScssPhp\\Block\\ElseBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block/ElseBlock.php', - 'ScssPhp\\ScssPhp\\Block\\ElseifBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block/ElseifBlock.php', - 'ScssPhp\\ScssPhp\\Block\\ForBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block/ForBlock.php', - 'ScssPhp\\ScssPhp\\Block\\IfBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block/IfBlock.php', - 'ScssPhp\\ScssPhp\\Block\\MediaBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block/MediaBlock.php', - 'ScssPhp\\ScssPhp\\Block\\NestedPropertyBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block/NestedPropertyBlock.php', - 'ScssPhp\\ScssPhp\\Block\\WhileBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Block/WhileBlock.php', - 'ScssPhp\\ScssPhp\\Cache' => __DIR__ . '/..' . '/scssphp/scssphp/src/Cache.php', - 'ScssPhp\\ScssPhp\\Colors' => __DIR__ . '/..' . '/scssphp/scssphp/src/Colors.php', - 'ScssPhp\\ScssPhp\\CompilationResult' => __DIR__ . '/..' . '/scssphp/scssphp/src/CompilationResult.php', - 'ScssPhp\\ScssPhp\\Compiler' => __DIR__ . '/..' . '/scssphp/scssphp/src/Compiler.php', - 'ScssPhp\\ScssPhp\\Compiler\\CachedResult' => __DIR__ . '/..' . '/scssphp/scssphp/src/Compiler/CachedResult.php', - 'ScssPhp\\ScssPhp\\Compiler\\Environment' => __DIR__ . '/..' . '/scssphp/scssphp/src/Compiler/Environment.php', - 'ScssPhp\\ScssPhp\\Exception\\CompilerException' => __DIR__ . '/..' . '/scssphp/scssphp/src/Exception/CompilerException.php', - 'ScssPhp\\ScssPhp\\Exception\\ParserException' => __DIR__ . '/..' . '/scssphp/scssphp/src/Exception/ParserException.php', - 'ScssPhp\\ScssPhp\\Exception\\RangeException' => __DIR__ . '/..' . '/scssphp/scssphp/src/Exception/RangeException.php', - 'ScssPhp\\ScssPhp\\Exception\\SassException' => __DIR__ . '/..' . '/scssphp/scssphp/src/Exception/SassException.php', - 'ScssPhp\\ScssPhp\\Exception\\SassScriptException' => __DIR__ . '/..' . '/scssphp/scssphp/src/Exception/SassScriptException.php', - 'ScssPhp\\ScssPhp\\Exception\\ServerException' => __DIR__ . '/..' . '/scssphp/scssphp/src/Exception/ServerException.php', - 'ScssPhp\\ScssPhp\\Formatter' => __DIR__ . '/..' . '/scssphp/scssphp/src/Formatter.php', - 'ScssPhp\\ScssPhp\\Formatter\\Compact' => __DIR__ . '/..' . '/scssphp/scssphp/src/Formatter/Compact.php', - 'ScssPhp\\ScssPhp\\Formatter\\Compressed' => __DIR__ . '/..' . '/scssphp/scssphp/src/Formatter/Compressed.php', - 'ScssPhp\\ScssPhp\\Formatter\\Crunched' => __DIR__ . '/..' . '/scssphp/scssphp/src/Formatter/Crunched.php', - 'ScssPhp\\ScssPhp\\Formatter\\Debug' => __DIR__ . '/..' . '/scssphp/scssphp/src/Formatter/Debug.php', - 'ScssPhp\\ScssPhp\\Formatter\\Expanded' => __DIR__ . '/..' . '/scssphp/scssphp/src/Formatter/Expanded.php', - 'ScssPhp\\ScssPhp\\Formatter\\Nested' => __DIR__ . '/..' . '/scssphp/scssphp/src/Formatter/Nested.php', - 'ScssPhp\\ScssPhp\\Formatter\\OutputBlock' => __DIR__ . '/..' . '/scssphp/scssphp/src/Formatter/OutputBlock.php', - 'ScssPhp\\ScssPhp\\Logger\\LoggerInterface' => __DIR__ . '/..' . '/scssphp/scssphp/src/Logger/LoggerInterface.php', - 'ScssPhp\\ScssPhp\\Logger\\QuietLogger' => __DIR__ . '/..' . '/scssphp/scssphp/src/Logger/QuietLogger.php', - 'ScssPhp\\ScssPhp\\Logger\\StreamLogger' => __DIR__ . '/..' . '/scssphp/scssphp/src/Logger/StreamLogger.php', - 'ScssPhp\\ScssPhp\\Node' => __DIR__ . '/..' . '/scssphp/scssphp/src/Node.php', - 'ScssPhp\\ScssPhp\\Node\\Number' => __DIR__ . '/..' . '/scssphp/scssphp/src/Node/Number.php', - 'ScssPhp\\ScssPhp\\OutputStyle' => __DIR__ . '/..' . '/scssphp/scssphp/src/OutputStyle.php', - 'ScssPhp\\ScssPhp\\Parser' => __DIR__ . '/..' . '/scssphp/scssphp/src/Parser.php', - 'ScssPhp\\ScssPhp\\SourceMap\\Base64' => __DIR__ . '/..' . '/scssphp/scssphp/src/SourceMap/Base64.php', - 'ScssPhp\\ScssPhp\\SourceMap\\Base64VLQ' => __DIR__ . '/..' . '/scssphp/scssphp/src/SourceMap/Base64VLQ.php', - 'ScssPhp\\ScssPhp\\SourceMap\\SourceMapGenerator' => __DIR__ . '/..' . '/scssphp/scssphp/src/SourceMap/SourceMapGenerator.php', - 'ScssPhp\\ScssPhp\\Type' => __DIR__ . '/..' . '/scssphp/scssphp/src/Type.php', - 'ScssPhp\\ScssPhp\\Util' => __DIR__ . '/..' . '/scssphp/scssphp/src/Util.php', - 'ScssPhp\\ScssPhp\\Util\\Path' => __DIR__ . '/..' . '/scssphp/scssphp/src/Util/Path.php', - 'ScssPhp\\ScssPhp\\ValueConverter' => __DIR__ . '/..' . '/scssphp/scssphp/src/ValueConverter.php', - 'ScssPhp\\ScssPhp\\Version' => __DIR__ . '/..' . '/scssphp/scssphp/src/Version.php', - 'ScssPhp\\ScssPhp\\Warn' => __DIR__ . '/..' . '/scssphp/scssphp/src/Warn.php', - 'SearchMenuNode' => __DIR__ . '/../..' . '/application/menunode.class.inc.php', - 'SecurityException' => __DIR__ . '/../..' . '/application/exceptions/SecurityException.php', - 'SeparatorPopupMenuItem' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'SetupLog' => __DIR__ . '/../..' . '/core/log.class.inc.php', - 'Shortcut' => __DIR__ . '/../..' . '/application/shortcut.class.inc.php', - 'ShortcutContainerMenuNode' => __DIR__ . '/../..' . '/application/menunode.class.inc.php', - 'ShortcutMenuNode' => __DIR__ . '/../..' . '/application/menunode.class.inc.php', - 'ShortcutOQL' => __DIR__ . '/../..' . '/application/shortcut.class.inc.php', - 'SimpleCrypt' => __DIR__ . '/../..' . '/core/simplecrypt.class.inc.php', - 'SimpleCryptMcryptEngine' => __DIR__ . '/../..' . '/core/simplecrypt.class.inc.php', - 'SimpleCryptOpenSSLEngine' => __DIR__ . '/../..' . '/core/simplecrypt.class.inc.php', - 'SimpleCryptOpenSSLMcryptCompatibilityEngine' => __DIR__ . '/../..' . '/core/simplecrypt.class.inc.php', - 'SimpleCryptSimpleEngine' => __DIR__ . '/../..' . '/core/simplecrypt.class.inc.php', - 'SimpleCryptSodiumEngine' => __DIR__ . '/../..' . '/core/simplecrypt.class.inc.php', - 'SimpleGraph' => __DIR__ . '/../..' . '/core/simplegraph.class.inc.php', - 'SimpleGraphException' => __DIR__ . '/../..' . '/core/simplegraph.class.inc.php', - 'SpreadsheetBulkExport' => __DIR__ . '/../..' . '/core/spreadsheetbulkexport.class.inc.php', - 'StimulusChecker' => __DIR__ . '/../..' . '/core/userrights.class.inc.php', - 'StimulusInternal' => __DIR__ . '/../..' . '/core/stimulus.class.inc.php', - 'StimulusUserAction' => __DIR__ . '/../..' . '/core/stimulus.class.inc.php', - 'Str' => __DIR__ . '/../..' . '/core/MyHelpers.class.inc.php', - 'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', - 'SummaryCardService' => __DIR__ . '/../..' . '/sources/Service/SummaryCard/SummaryCardService.php', - 'Symfony\\Bridge\\Twig\\AppVariable' => __DIR__ . '/..' . '/symfony/twig-bridge/AppVariable.php', - 'Symfony\\Bridge\\Twig\\Command\\DebugCommand' => __DIR__ . '/..' . '/symfony/twig-bridge/Command/DebugCommand.php', - 'Symfony\\Bridge\\Twig\\Command\\LintCommand' => __DIR__ . '/..' . '/symfony/twig-bridge/Command/LintCommand.php', - 'Symfony\\Bridge\\Twig\\DataCollector\\TwigDataCollector' => __DIR__ . '/..' . '/symfony/twig-bridge/DataCollector/TwigDataCollector.php', - 'Symfony\\Bridge\\Twig\\ErrorRenderer\\TwigErrorRenderer' => __DIR__ . '/..' . '/symfony/twig-bridge/ErrorRenderer/TwigErrorRenderer.php', - 'Symfony\\Bridge\\Twig\\Extension\\AssetExtension' => __DIR__ . '/..' . '/symfony/twig-bridge/Extension/AssetExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\CodeExtension' => __DIR__ . '/..' . '/symfony/twig-bridge/Extension/CodeExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\CsrfExtension' => __DIR__ . '/..' . '/symfony/twig-bridge/Extension/CsrfExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\CsrfRuntime' => __DIR__ . '/..' . '/symfony/twig-bridge/Extension/CsrfRuntime.php', - 'Symfony\\Bridge\\Twig\\Extension\\DumpExtension' => __DIR__ . '/..' . '/symfony/twig-bridge/Extension/DumpExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\ExpressionExtension' => __DIR__ . '/..' . '/symfony/twig-bridge/Extension/ExpressionExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\FormExtension' => __DIR__ . '/..' . '/symfony/twig-bridge/Extension/FormExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\HttpFoundationExtension' => __DIR__ . '/..' . '/symfony/twig-bridge/Extension/HttpFoundationExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\HttpKernelExtension' => __DIR__ . '/..' . '/symfony/twig-bridge/Extension/HttpKernelExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\HttpKernelRuntime' => __DIR__ . '/..' . '/symfony/twig-bridge/Extension/HttpKernelRuntime.php', - 'Symfony\\Bridge\\Twig\\Extension\\LogoutUrlExtension' => __DIR__ . '/..' . '/symfony/twig-bridge/Extension/LogoutUrlExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension' => __DIR__ . '/..' . '/symfony/twig-bridge/Extension/ProfilerExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\RoutingExtension' => __DIR__ . '/..' . '/symfony/twig-bridge/Extension/RoutingExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\SecurityExtension' => __DIR__ . '/..' . '/symfony/twig-bridge/Extension/SecurityExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\SerializerExtension' => __DIR__ . '/..' . '/symfony/twig-bridge/Extension/SerializerExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\SerializerRuntime' => __DIR__ . '/..' . '/symfony/twig-bridge/Extension/SerializerRuntime.php', - 'Symfony\\Bridge\\Twig\\Extension\\StopwatchExtension' => __DIR__ . '/..' . '/symfony/twig-bridge/Extension/StopwatchExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\TranslationExtension' => __DIR__ . '/..' . '/symfony/twig-bridge/Extension/TranslationExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\WebLinkExtension' => __DIR__ . '/..' . '/symfony/twig-bridge/Extension/WebLinkExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\WorkflowExtension' => __DIR__ . '/..' . '/symfony/twig-bridge/Extension/WorkflowExtension.php', - 'Symfony\\Bridge\\Twig\\Extension\\YamlExtension' => __DIR__ . '/..' . '/symfony/twig-bridge/Extension/YamlExtension.php', - 'Symfony\\Bridge\\Twig\\Form\\TwigRendererEngine' => __DIR__ . '/..' . '/symfony/twig-bridge/Form/TwigRendererEngine.php', - 'Symfony\\Bridge\\Twig\\Mime\\BodyRenderer' => __DIR__ . '/..' . '/symfony/twig-bridge/Mime/BodyRenderer.php', - 'Symfony\\Bridge\\Twig\\Mime\\NotificationEmail' => __DIR__ . '/..' . '/symfony/twig-bridge/Mime/NotificationEmail.php', - 'Symfony\\Bridge\\Twig\\Mime\\TemplatedEmail' => __DIR__ . '/..' . '/symfony/twig-bridge/Mime/TemplatedEmail.php', - 'Symfony\\Bridge\\Twig\\Mime\\WrappedTemplatedEmail' => __DIR__ . '/..' . '/symfony/twig-bridge/Mime/WrappedTemplatedEmail.php', - 'Symfony\\Bridge\\Twig\\NodeVisitor\\Scope' => __DIR__ . '/..' . '/symfony/twig-bridge/NodeVisitor/Scope.php', - 'Symfony\\Bridge\\Twig\\NodeVisitor\\TranslationDefaultDomainNodeVisitor' => __DIR__ . '/..' . '/symfony/twig-bridge/NodeVisitor/TranslationDefaultDomainNodeVisitor.php', - 'Symfony\\Bridge\\Twig\\NodeVisitor\\TranslationNodeVisitor' => __DIR__ . '/..' . '/symfony/twig-bridge/NodeVisitor/TranslationNodeVisitor.php', - 'Symfony\\Bridge\\Twig\\Node\\DumpNode' => __DIR__ . '/..' . '/symfony/twig-bridge/Node/DumpNode.php', - 'Symfony\\Bridge\\Twig\\Node\\FormThemeNode' => __DIR__ . '/..' . '/symfony/twig-bridge/Node/FormThemeNode.php', - 'Symfony\\Bridge\\Twig\\Node\\RenderBlockNode' => __DIR__ . '/..' . '/symfony/twig-bridge/Node/RenderBlockNode.php', - 'Symfony\\Bridge\\Twig\\Node\\SearchAndRenderBlockNode' => __DIR__ . '/..' . '/symfony/twig-bridge/Node/SearchAndRenderBlockNode.php', - 'Symfony\\Bridge\\Twig\\Node\\StopwatchNode' => __DIR__ . '/..' . '/symfony/twig-bridge/Node/StopwatchNode.php', - 'Symfony\\Bridge\\Twig\\Node\\TransDefaultDomainNode' => __DIR__ . '/..' . '/symfony/twig-bridge/Node/TransDefaultDomainNode.php', - 'Symfony\\Bridge\\Twig\\Node\\TransNode' => __DIR__ . '/..' . '/symfony/twig-bridge/Node/TransNode.php', - 'Symfony\\Bridge\\Twig\\TokenParser\\DumpTokenParser' => __DIR__ . '/..' . '/symfony/twig-bridge/TokenParser/DumpTokenParser.php', - 'Symfony\\Bridge\\Twig\\TokenParser\\FormThemeTokenParser' => __DIR__ . '/..' . '/symfony/twig-bridge/TokenParser/FormThemeTokenParser.php', - 'Symfony\\Bridge\\Twig\\TokenParser\\StopwatchTokenParser' => __DIR__ . '/..' . '/symfony/twig-bridge/TokenParser/StopwatchTokenParser.php', - 'Symfony\\Bridge\\Twig\\TokenParser\\TransDefaultDomainTokenParser' => __DIR__ . '/..' . '/symfony/twig-bridge/TokenParser/TransDefaultDomainTokenParser.php', - 'Symfony\\Bridge\\Twig\\TokenParser\\TransTokenParser' => __DIR__ . '/..' . '/symfony/twig-bridge/TokenParser/TransTokenParser.php', - 'Symfony\\Bridge\\Twig\\Translation\\TwigExtractor' => __DIR__ . '/..' . '/symfony/twig-bridge/Translation/TwigExtractor.php', - 'Symfony\\Bridge\\Twig\\UndefinedCallableHandler' => __DIR__ . '/..' . '/symfony/twig-bridge/UndefinedCallableHandler.php', - 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\AbstractPhpFileCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/AbstractPhpFileCacheWarmer.php', - 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\AnnotationsCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/AnnotationsCacheWarmer.php', - 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\CachePoolClearerCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/CachePoolClearerCacheWarmer.php', - 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\ConfigBuilderCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/ConfigBuilderCacheWarmer.php', - 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\RouterCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/RouterCacheWarmer.php', - 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\SerializerCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/SerializerCacheWarmer.php', - 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\TranslationsCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/TranslationsCacheWarmer.php', - 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\ValidatorCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/ValidatorCacheWarmer.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\AboutCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/AboutCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\AbstractConfigCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/AbstractConfigCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\AssetsInstallCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/AssetsInstallCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\BuildDebugContainerTrait' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/BuildDebugContainerTrait.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\CacheClearCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/CacheClearCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolClearCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/CachePoolClearCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolDeleteCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/CachePoolDeleteCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolListCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/CachePoolListCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\CachePoolPruneCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/CachePoolPruneCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\CacheWarmupCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/CacheWarmupCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\ConfigDebugCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/ConfigDebugCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\ConfigDumpReferenceCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/ConfigDumpReferenceCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\ContainerDebugCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/ContainerDebugCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\ContainerLintCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/ContainerLintCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\DebugAutowiringCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/DebugAutowiringCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\EventDispatcherDebugCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/EventDispatcherDebugCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\RouterDebugCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/RouterDebugCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\RouterMatchCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/RouterMatchCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsDecryptToLocalCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/SecretsDecryptToLocalCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsEncryptFromLocalCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/SecretsEncryptFromLocalCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsGenerateKeysCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/SecretsGenerateKeysCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsListCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/SecretsListCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsRemoveCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/SecretsRemoveCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\SecretsSetCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/SecretsSetCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\TranslationDebugCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/TranslationDebugCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\TranslationUpdateCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/TranslationUpdateCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\WorkflowDumpCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/WorkflowDumpCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\XliffLintCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/XliffLintCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Command\\YamlLintCommand' => __DIR__ . '/..' . '/symfony/framework-bundle/Command/YamlLintCommand.php', - 'Symfony\\Bundle\\FrameworkBundle\\Console\\Application' => __DIR__ . '/..' . '/symfony/framework-bundle/Console/Application.php', - 'Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\Descriptor' => __DIR__ . '/..' . '/symfony/framework-bundle/Console/Descriptor/Descriptor.php', - 'Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\JsonDescriptor' => __DIR__ . '/..' . '/symfony/framework-bundle/Console/Descriptor/JsonDescriptor.php', - 'Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\MarkdownDescriptor' => __DIR__ . '/..' . '/symfony/framework-bundle/Console/Descriptor/MarkdownDescriptor.php', - 'Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\TextDescriptor' => __DIR__ . '/..' . '/symfony/framework-bundle/Console/Descriptor/TextDescriptor.php', - 'Symfony\\Bundle\\FrameworkBundle\\Console\\Descriptor\\XmlDescriptor' => __DIR__ . '/..' . '/symfony/framework-bundle/Console/Descriptor/XmlDescriptor.php', - 'Symfony\\Bundle\\FrameworkBundle\\Console\\Helper\\DescriptorHelper' => __DIR__ . '/..' . '/symfony/framework-bundle/Console/Helper/DescriptorHelper.php', - 'Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController' => __DIR__ . '/..' . '/symfony/framework-bundle/Controller/AbstractController.php', - 'Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerResolver' => __DIR__ . '/..' . '/symfony/framework-bundle/Controller/ControllerResolver.php', - 'Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController' => __DIR__ . '/..' . '/symfony/framework-bundle/Controller/RedirectController.php', - 'Symfony\\Bundle\\FrameworkBundle\\Controller\\TemplateController' => __DIR__ . '/..' . '/symfony/framework-bundle/Controller/TemplateController.php', - 'Symfony\\Bundle\\FrameworkBundle\\DataCollector\\AbstractDataCollector' => __DIR__ . '/..' . '/symfony/framework-bundle/DataCollector/AbstractDataCollector.php', - 'Symfony\\Bundle\\FrameworkBundle\\DataCollector\\RouterDataCollector' => __DIR__ . '/..' . '/symfony/framework-bundle/DataCollector/RouterDataCollector.php', - 'Symfony\\Bundle\\FrameworkBundle\\DataCollector\\TemplateAwareDataCollectorInterface' => __DIR__ . '/..' . '/symfony/framework-bundle/DataCollector/TemplateAwareDataCollectorInterface.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\AddAnnotationsCachedReaderPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\AddDebugLogProcessorPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/AddDebugLogProcessorPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\AddExpressionLanguageProvidersPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\AssetsContextPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/AssetsContextPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\ContainerBuilderDebugDumpPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\DataCollectorTranslatorPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\LoggingTranslatorPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/LoggingTranslatorPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\ProfilerPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/ProfilerPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\RemoveUnusedSessionMarshallingHandlerPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/RemoveUnusedSessionMarshallingHandlerPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\SessionPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/SessionPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\TestServiceContainerRealRefPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\TestServiceContainerWeakRefPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\UnusedTagsPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/UnusedTagsPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\WorkflowGuardListenerPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Configuration' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Configuration.php', - 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\FrameworkExtension' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php', - 'Symfony\\Bundle\\FrameworkBundle\\EventListener\\SuggestMissingPackageSubscriber' => __DIR__ . '/..' . '/symfony/framework-bundle/EventListener/SuggestMissingPackageSubscriber.php', - 'Symfony\\Bundle\\FrameworkBundle\\FrameworkBundle' => __DIR__ . '/..' . '/symfony/framework-bundle/FrameworkBundle.php', - 'Symfony\\Bundle\\FrameworkBundle\\HttpCache\\HttpCache' => __DIR__ . '/..' . '/symfony/framework-bundle/HttpCache/HttpCache.php', - 'Symfony\\Bundle\\FrameworkBundle\\KernelBrowser' => __DIR__ . '/..' . '/symfony/framework-bundle/KernelBrowser.php', - 'Symfony\\Bundle\\FrameworkBundle\\Kernel\\MicroKernelTrait' => __DIR__ . '/..' . '/symfony/framework-bundle/Kernel/MicroKernelTrait.php', - 'Symfony\\Bundle\\FrameworkBundle\\Routing\\AnnotatedRouteControllerLoader' => __DIR__ . '/..' . '/symfony/framework-bundle/Routing/AnnotatedRouteControllerLoader.php', - 'Symfony\\Bundle\\FrameworkBundle\\Routing\\DelegatingLoader' => __DIR__ . '/..' . '/symfony/framework-bundle/Routing/DelegatingLoader.php', - 'Symfony\\Bundle\\FrameworkBundle\\Routing\\RedirectableCompiledUrlMatcher' => __DIR__ . '/..' . '/symfony/framework-bundle/Routing/RedirectableCompiledUrlMatcher.php', - 'Symfony\\Bundle\\FrameworkBundle\\Routing\\RouteLoaderInterface' => __DIR__ . '/..' . '/symfony/framework-bundle/Routing/RouteLoaderInterface.php', - 'Symfony\\Bundle\\FrameworkBundle\\Routing\\Router' => __DIR__ . '/..' . '/symfony/framework-bundle/Routing/Router.php', - 'Symfony\\Bundle\\FrameworkBundle\\Secrets\\AbstractVault' => __DIR__ . '/..' . '/symfony/framework-bundle/Secrets/AbstractVault.php', - 'Symfony\\Bundle\\FrameworkBundle\\Secrets\\DotenvVault' => __DIR__ . '/..' . '/symfony/framework-bundle/Secrets/DotenvVault.php', - 'Symfony\\Bundle\\FrameworkBundle\\Secrets\\SodiumVault' => __DIR__ . '/..' . '/symfony/framework-bundle/Secrets/SodiumVault.php', - 'Symfony\\Bundle\\FrameworkBundle\\Session\\DeprecatedSessionFactory' => __DIR__ . '/..' . '/symfony/framework-bundle/Session/DeprecatedSessionFactory.php', - 'Symfony\\Bundle\\FrameworkBundle\\Session\\ServiceSessionFactory' => __DIR__ . '/..' . '/symfony/framework-bundle/Session/ServiceSessionFactory.php', - 'Symfony\\Bundle\\FrameworkBundle\\Translation\\Translator' => __DIR__ . '/..' . '/symfony/framework-bundle/Translation/Translator.php', - 'Symfony\\Bundle\\TwigBundle\\CacheWarmer\\TemplateCacheWarmer' => __DIR__ . '/..' . '/symfony/twig-bundle/CacheWarmer/TemplateCacheWarmer.php', - 'Symfony\\Bundle\\TwigBundle\\Command\\LintCommand' => __DIR__ . '/..' . '/symfony/twig-bundle/Command/LintCommand.php', - 'Symfony\\Bundle\\TwigBundle\\DependencyInjection\\Compiler\\ExtensionPass' => __DIR__ . '/..' . '/symfony/twig-bundle/DependencyInjection/Compiler/ExtensionPass.php', - 'Symfony\\Bundle\\TwigBundle\\DependencyInjection\\Compiler\\RuntimeLoaderPass' => __DIR__ . '/..' . '/symfony/twig-bundle/DependencyInjection/Compiler/RuntimeLoaderPass.php', - 'Symfony\\Bundle\\TwigBundle\\DependencyInjection\\Compiler\\TwigEnvironmentPass' => __DIR__ . '/..' . '/symfony/twig-bundle/DependencyInjection/Compiler/TwigEnvironmentPass.php', - 'Symfony\\Bundle\\TwigBundle\\DependencyInjection\\Compiler\\TwigLoaderPass' => __DIR__ . '/..' . '/symfony/twig-bundle/DependencyInjection/Compiler/TwigLoaderPass.php', - 'Symfony\\Bundle\\TwigBundle\\DependencyInjection\\Configuration' => __DIR__ . '/..' . '/symfony/twig-bundle/DependencyInjection/Configuration.php', - 'Symfony\\Bundle\\TwigBundle\\DependencyInjection\\Configurator\\EnvironmentConfigurator' => __DIR__ . '/..' . '/symfony/twig-bundle/DependencyInjection/Configurator/EnvironmentConfigurator.php', - 'Symfony\\Bundle\\TwigBundle\\DependencyInjection\\TwigExtension' => __DIR__ . '/..' . '/symfony/twig-bundle/DependencyInjection/TwigExtension.php', - 'Symfony\\Bundle\\TwigBundle\\TemplateIterator' => __DIR__ . '/..' . '/symfony/twig-bundle/TemplateIterator.php', - 'Symfony\\Bundle\\TwigBundle\\TwigBundle' => __DIR__ . '/..' . '/symfony/twig-bundle/TwigBundle.php', - 'Symfony\\Bundle\\WebProfilerBundle\\Controller\\ExceptionPanelController' => __DIR__ . '/..' . '/symfony/web-profiler-bundle/Controller/ExceptionPanelController.php', - 'Symfony\\Bundle\\WebProfilerBundle\\Controller\\ProfilerController' => __DIR__ . '/..' . '/symfony/web-profiler-bundle/Controller/ProfilerController.php', - 'Symfony\\Bundle\\WebProfilerBundle\\Controller\\RouterController' => __DIR__ . '/..' . '/symfony/web-profiler-bundle/Controller/RouterController.php', - 'Symfony\\Bundle\\WebProfilerBundle\\Csp\\ContentSecurityPolicyHandler' => __DIR__ . '/..' . '/symfony/web-profiler-bundle/Csp/ContentSecurityPolicyHandler.php', - 'Symfony\\Bundle\\WebProfilerBundle\\Csp\\NonceGenerator' => __DIR__ . '/..' . '/symfony/web-profiler-bundle/Csp/NonceGenerator.php', - 'Symfony\\Bundle\\WebProfilerBundle\\DependencyInjection\\Configuration' => __DIR__ . '/..' . '/symfony/web-profiler-bundle/DependencyInjection/Configuration.php', - 'Symfony\\Bundle\\WebProfilerBundle\\DependencyInjection\\WebProfilerExtension' => __DIR__ . '/..' . '/symfony/web-profiler-bundle/DependencyInjection/WebProfilerExtension.php', - 'Symfony\\Bundle\\WebProfilerBundle\\EventListener\\WebDebugToolbarListener' => __DIR__ . '/..' . '/symfony/web-profiler-bundle/EventListener/WebDebugToolbarListener.php', - 'Symfony\\Bundle\\WebProfilerBundle\\Profiler\\TemplateManager' => __DIR__ . '/..' . '/symfony/web-profiler-bundle/Profiler/TemplateManager.php', - 'Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension' => __DIR__ . '/..' . '/symfony/web-profiler-bundle/Twig/WebProfilerExtension.php', - 'Symfony\\Bundle\\WebProfilerBundle\\WebProfilerBundle' => __DIR__ . '/..' . '/symfony/web-profiler-bundle/WebProfilerBundle.php', - 'Symfony\\Component\\Cache\\Adapter\\AbstractAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/AbstractAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\AbstractTagAwareAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/AbstractTagAwareAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\AdapterInterface' => __DIR__ . '/..' . '/symfony/cache/Adapter/AdapterInterface.php', - 'Symfony\\Component\\Cache\\Adapter\\ApcuAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/ApcuAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\ArrayAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/ArrayAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\ChainAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/ChainAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\CouchbaseBucketAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/CouchbaseBucketAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\CouchbaseCollectionAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/CouchbaseCollectionAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\DoctrineAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/DoctrineAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\DoctrineDbalAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/DoctrineDbalAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\FilesystemAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/FilesystemAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\FilesystemTagAwareAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/FilesystemTagAwareAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\MemcachedAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/MemcachedAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\NullAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/NullAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\ParameterNormalizer' => __DIR__ . '/..' . '/symfony/cache/Adapter/ParameterNormalizer.php', - 'Symfony\\Component\\Cache\\Adapter\\PdoAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/PdoAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\PhpArrayAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/PhpArrayAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\PhpFilesAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/PhpFilesAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\ProxyAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/ProxyAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\Psr16Adapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/Psr16Adapter.php', - 'Symfony\\Component\\Cache\\Adapter\\RedisAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/RedisAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\RedisTagAwareAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/RedisTagAwareAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\TagAwareAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/TagAwareAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\TagAwareAdapterInterface' => __DIR__ . '/..' . '/symfony/cache/Adapter/TagAwareAdapterInterface.php', - 'Symfony\\Component\\Cache\\Adapter\\TraceableAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/TraceableAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\TraceableTagAwareAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/TraceableTagAwareAdapter.php', - 'Symfony\\Component\\Cache\\CacheItem' => __DIR__ . '/..' . '/symfony/cache/CacheItem.php', - 'Symfony\\Component\\Cache\\DataCollector\\CacheDataCollector' => __DIR__ . '/..' . '/symfony/cache/DataCollector/CacheDataCollector.php', - 'Symfony\\Component\\Cache\\DependencyInjection\\CacheCollectorPass' => __DIR__ . '/..' . '/symfony/cache/DependencyInjection/CacheCollectorPass.php', - 'Symfony\\Component\\Cache\\DependencyInjection\\CachePoolClearerPass' => __DIR__ . '/..' . '/symfony/cache/DependencyInjection/CachePoolClearerPass.php', - 'Symfony\\Component\\Cache\\DependencyInjection\\CachePoolPass' => __DIR__ . '/..' . '/symfony/cache/DependencyInjection/CachePoolPass.php', - 'Symfony\\Component\\Cache\\DependencyInjection\\CachePoolPrunerPass' => __DIR__ . '/..' . '/symfony/cache/DependencyInjection/CachePoolPrunerPass.php', - 'Symfony\\Component\\Cache\\DoctrineProvider' => __DIR__ . '/..' . '/symfony/cache/DoctrineProvider.php', - 'Symfony\\Component\\Cache\\Exception\\CacheException' => __DIR__ . '/..' . '/symfony/cache/Exception/CacheException.php', - 'Symfony\\Component\\Cache\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/cache/Exception/InvalidArgumentException.php', - 'Symfony\\Component\\Cache\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/cache/Exception/LogicException.php', - 'Symfony\\Component\\Cache\\LockRegistry' => __DIR__ . '/..' . '/symfony/cache/LockRegistry.php', - 'Symfony\\Component\\Cache\\Marshaller\\DefaultMarshaller' => __DIR__ . '/..' . '/symfony/cache/Marshaller/DefaultMarshaller.php', - 'Symfony\\Component\\Cache\\Marshaller\\DeflateMarshaller' => __DIR__ . '/..' . '/symfony/cache/Marshaller/DeflateMarshaller.php', - 'Symfony\\Component\\Cache\\Marshaller\\MarshallerInterface' => __DIR__ . '/..' . '/symfony/cache/Marshaller/MarshallerInterface.php', - 'Symfony\\Component\\Cache\\Marshaller\\SodiumMarshaller' => __DIR__ . '/..' . '/symfony/cache/Marshaller/SodiumMarshaller.php', - 'Symfony\\Component\\Cache\\Marshaller\\TagAwareMarshaller' => __DIR__ . '/..' . '/symfony/cache/Marshaller/TagAwareMarshaller.php', - 'Symfony\\Component\\Cache\\Messenger\\EarlyExpirationDispatcher' => __DIR__ . '/..' . '/symfony/cache/Messenger/EarlyExpirationDispatcher.php', - 'Symfony\\Component\\Cache\\Messenger\\EarlyExpirationHandler' => __DIR__ . '/..' . '/symfony/cache/Messenger/EarlyExpirationHandler.php', - 'Symfony\\Component\\Cache\\Messenger\\EarlyExpirationMessage' => __DIR__ . '/..' . '/symfony/cache/Messenger/EarlyExpirationMessage.php', - 'Symfony\\Component\\Cache\\PruneableInterface' => __DIR__ . '/..' . '/symfony/cache/PruneableInterface.php', - 'Symfony\\Component\\Cache\\Psr16Cache' => __DIR__ . '/..' . '/symfony/cache/Psr16Cache.php', - 'Symfony\\Component\\Cache\\ResettableInterface' => __DIR__ . '/..' . '/symfony/cache/ResettableInterface.php', - 'Symfony\\Component\\Cache\\Traits\\AbstractAdapterTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/AbstractAdapterTrait.php', - 'Symfony\\Component\\Cache\\Traits\\ContractsTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/ContractsTrait.php', - 'Symfony\\Component\\Cache\\Traits\\FilesystemCommonTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/FilesystemCommonTrait.php', - 'Symfony\\Component\\Cache\\Traits\\FilesystemTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/FilesystemTrait.php', - 'Symfony\\Component\\Cache\\Traits\\ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/ProxyTrait.php', - 'Symfony\\Component\\Cache\\Traits\\RedisClusterNodeProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisClusterNodeProxy.php', - 'Symfony\\Component\\Cache\\Traits\\RedisClusterProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisClusterProxy.php', - 'Symfony\\Component\\Cache\\Traits\\RedisProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisProxy.php', - 'Symfony\\Component\\Cache\\Traits\\RedisTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisTrait.php', - 'Symfony\\Component\\Config\\Builder\\ClassBuilder' => __DIR__ . '/..' . '/symfony/config/Builder/ClassBuilder.php', - 'Symfony\\Component\\Config\\Builder\\ConfigBuilderGenerator' => __DIR__ . '/..' . '/symfony/config/Builder/ConfigBuilderGenerator.php', - 'Symfony\\Component\\Config\\Builder\\ConfigBuilderGeneratorInterface' => __DIR__ . '/..' . '/symfony/config/Builder/ConfigBuilderGeneratorInterface.php', - 'Symfony\\Component\\Config\\Builder\\ConfigBuilderInterface' => __DIR__ . '/..' . '/symfony/config/Builder/ConfigBuilderInterface.php', - 'Symfony\\Component\\Config\\Builder\\Method' => __DIR__ . '/..' . '/symfony/config/Builder/Method.php', - 'Symfony\\Component\\Config\\Builder\\Property' => __DIR__ . '/..' . '/symfony/config/Builder/Property.php', - 'Symfony\\Component\\Config\\ConfigCache' => __DIR__ . '/..' . '/symfony/config/ConfigCache.php', - 'Symfony\\Component\\Config\\ConfigCacheFactory' => __DIR__ . '/..' . '/symfony/config/ConfigCacheFactory.php', - 'Symfony\\Component\\Config\\ConfigCacheFactoryInterface' => __DIR__ . '/..' . '/symfony/config/ConfigCacheFactoryInterface.php', - 'Symfony\\Component\\Config\\ConfigCacheInterface' => __DIR__ . '/..' . '/symfony/config/ConfigCacheInterface.php', - 'Symfony\\Component\\Config\\Definition\\ArrayNode' => __DIR__ . '/..' . '/symfony/config/Definition/ArrayNode.php', - 'Symfony\\Component\\Config\\Definition\\BaseNode' => __DIR__ . '/..' . '/symfony/config/Definition/BaseNode.php', - 'Symfony\\Component\\Config\\Definition\\BooleanNode' => __DIR__ . '/..' . '/symfony/config/Definition/BooleanNode.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\ArrayNodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/ArrayNodeDefinition.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\BooleanNodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/BooleanNodeDefinition.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\BuilderAwareInterface' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/BuilderAwareInterface.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\EnumNodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/EnumNodeDefinition.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\ExprBuilder' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/ExprBuilder.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\FloatNodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/FloatNodeDefinition.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\IntegerNodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/IntegerNodeDefinition.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\MergeBuilder' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/MergeBuilder.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\NodeBuilder' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/NodeBuilder.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\NodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/NodeDefinition.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\NodeParentInterface' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/NodeParentInterface.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\NormalizationBuilder' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/NormalizationBuilder.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\NumericNodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/NumericNodeDefinition.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\ParentNodeDefinitionInterface' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/ParentNodeDefinitionInterface.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\ScalarNodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/ScalarNodeDefinition.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\TreeBuilder' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/TreeBuilder.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\ValidationBuilder' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/ValidationBuilder.php', - 'Symfony\\Component\\Config\\Definition\\Builder\\VariableNodeDefinition' => __DIR__ . '/..' . '/symfony/config/Definition/Builder/VariableNodeDefinition.php', - 'Symfony\\Component\\Config\\Definition\\ConfigurationInterface' => __DIR__ . '/..' . '/symfony/config/Definition/ConfigurationInterface.php', - 'Symfony\\Component\\Config\\Definition\\Dumper\\XmlReferenceDumper' => __DIR__ . '/..' . '/symfony/config/Definition/Dumper/XmlReferenceDumper.php', - 'Symfony\\Component\\Config\\Definition\\Dumper\\YamlReferenceDumper' => __DIR__ . '/..' . '/symfony/config/Definition/Dumper/YamlReferenceDumper.php', - 'Symfony\\Component\\Config\\Definition\\EnumNode' => __DIR__ . '/..' . '/symfony/config/Definition/EnumNode.php', - 'Symfony\\Component\\Config\\Definition\\Exception\\DuplicateKeyException' => __DIR__ . '/..' . '/symfony/config/Definition/Exception/DuplicateKeyException.php', - 'Symfony\\Component\\Config\\Definition\\Exception\\Exception' => __DIR__ . '/..' . '/symfony/config/Definition/Exception/Exception.php', - 'Symfony\\Component\\Config\\Definition\\Exception\\ForbiddenOverwriteException' => __DIR__ . '/..' . '/symfony/config/Definition/Exception/ForbiddenOverwriteException.php', - 'Symfony\\Component\\Config\\Definition\\Exception\\InvalidConfigurationException' => __DIR__ . '/..' . '/symfony/config/Definition/Exception/InvalidConfigurationException.php', - 'Symfony\\Component\\Config\\Definition\\Exception\\InvalidDefinitionException' => __DIR__ . '/..' . '/symfony/config/Definition/Exception/InvalidDefinitionException.php', - 'Symfony\\Component\\Config\\Definition\\Exception\\InvalidTypeException' => __DIR__ . '/..' . '/symfony/config/Definition/Exception/InvalidTypeException.php', - 'Symfony\\Component\\Config\\Definition\\Exception\\UnsetKeyException' => __DIR__ . '/..' . '/symfony/config/Definition/Exception/UnsetKeyException.php', - 'Symfony\\Component\\Config\\Definition\\FloatNode' => __DIR__ . '/..' . '/symfony/config/Definition/FloatNode.php', - 'Symfony\\Component\\Config\\Definition\\IntegerNode' => __DIR__ . '/..' . '/symfony/config/Definition/IntegerNode.php', - 'Symfony\\Component\\Config\\Definition\\NodeInterface' => __DIR__ . '/..' . '/symfony/config/Definition/NodeInterface.php', - 'Symfony\\Component\\Config\\Definition\\NumericNode' => __DIR__ . '/..' . '/symfony/config/Definition/NumericNode.php', - 'Symfony\\Component\\Config\\Definition\\Processor' => __DIR__ . '/..' . '/symfony/config/Definition/Processor.php', - 'Symfony\\Component\\Config\\Definition\\PrototypeNodeInterface' => __DIR__ . '/..' . '/symfony/config/Definition/PrototypeNodeInterface.php', - 'Symfony\\Component\\Config\\Definition\\PrototypedArrayNode' => __DIR__ . '/..' . '/symfony/config/Definition/PrototypedArrayNode.php', - 'Symfony\\Component\\Config\\Definition\\ScalarNode' => __DIR__ . '/..' . '/symfony/config/Definition/ScalarNode.php', - 'Symfony\\Component\\Config\\Definition\\VariableNode' => __DIR__ . '/..' . '/symfony/config/Definition/VariableNode.php', - 'Symfony\\Component\\Config\\Exception\\FileLoaderImportCircularReferenceException' => __DIR__ . '/..' . '/symfony/config/Exception/FileLoaderImportCircularReferenceException.php', - 'Symfony\\Component\\Config\\Exception\\FileLocatorFileNotFoundException' => __DIR__ . '/..' . '/symfony/config/Exception/FileLocatorFileNotFoundException.php', - 'Symfony\\Component\\Config\\Exception\\LoaderLoadException' => __DIR__ . '/..' . '/symfony/config/Exception/LoaderLoadException.php', - 'Symfony\\Component\\Config\\FileLocator' => __DIR__ . '/..' . '/symfony/config/FileLocator.php', - 'Symfony\\Component\\Config\\FileLocatorInterface' => __DIR__ . '/..' . '/symfony/config/FileLocatorInterface.php', - 'Symfony\\Component\\Config\\Loader\\DelegatingLoader' => __DIR__ . '/..' . '/symfony/config/Loader/DelegatingLoader.php', - 'Symfony\\Component\\Config\\Loader\\FileLoader' => __DIR__ . '/..' . '/symfony/config/Loader/FileLoader.php', - 'Symfony\\Component\\Config\\Loader\\GlobFileLoader' => __DIR__ . '/..' . '/symfony/config/Loader/GlobFileLoader.php', - 'Symfony\\Component\\Config\\Loader\\Loader' => __DIR__ . '/..' . '/symfony/config/Loader/Loader.php', - 'Symfony\\Component\\Config\\Loader\\LoaderInterface' => __DIR__ . '/..' . '/symfony/config/Loader/LoaderInterface.php', - 'Symfony\\Component\\Config\\Loader\\LoaderResolver' => __DIR__ . '/..' . '/symfony/config/Loader/LoaderResolver.php', - 'Symfony\\Component\\Config\\Loader\\LoaderResolverInterface' => __DIR__ . '/..' . '/symfony/config/Loader/LoaderResolverInterface.php', - 'Symfony\\Component\\Config\\Loader\\ParamConfigurator' => __DIR__ . '/..' . '/symfony/config/Loader/ParamConfigurator.php', - 'Symfony\\Component\\Config\\ResourceCheckerConfigCache' => __DIR__ . '/..' . '/symfony/config/ResourceCheckerConfigCache.php', - 'Symfony\\Component\\Config\\ResourceCheckerConfigCacheFactory' => __DIR__ . '/..' . '/symfony/config/ResourceCheckerConfigCacheFactory.php', - 'Symfony\\Component\\Config\\ResourceCheckerInterface' => __DIR__ . '/..' . '/symfony/config/ResourceCheckerInterface.php', - 'Symfony\\Component\\Config\\Resource\\ClassExistenceResource' => __DIR__ . '/..' . '/symfony/config/Resource/ClassExistenceResource.php', - 'Symfony\\Component\\Config\\Resource\\ComposerResource' => __DIR__ . '/..' . '/symfony/config/Resource/ComposerResource.php', - 'Symfony\\Component\\Config\\Resource\\DirectoryResource' => __DIR__ . '/..' . '/symfony/config/Resource/DirectoryResource.php', - 'Symfony\\Component\\Config\\Resource\\FileExistenceResource' => __DIR__ . '/..' . '/symfony/config/Resource/FileExistenceResource.php', - 'Symfony\\Component\\Config\\Resource\\FileResource' => __DIR__ . '/..' . '/symfony/config/Resource/FileResource.php', - 'Symfony\\Component\\Config\\Resource\\GlobResource' => __DIR__ . '/..' . '/symfony/config/Resource/GlobResource.php', - 'Symfony\\Component\\Config\\Resource\\ReflectionClassResource' => __DIR__ . '/..' . '/symfony/config/Resource/ReflectionClassResource.php', - 'Symfony\\Component\\Config\\Resource\\ResourceInterface' => __DIR__ . '/..' . '/symfony/config/Resource/ResourceInterface.php', - 'Symfony\\Component\\Config\\Resource\\SelfCheckingResourceChecker' => __DIR__ . '/..' . '/symfony/config/Resource/SelfCheckingResourceChecker.php', - 'Symfony\\Component\\Config\\Resource\\SelfCheckingResourceInterface' => __DIR__ . '/..' . '/symfony/config/Resource/SelfCheckingResourceInterface.php', - 'Symfony\\Component\\Config\\Util\\Exception\\InvalidXmlException' => __DIR__ . '/..' . '/symfony/config/Util/Exception/InvalidXmlException.php', - 'Symfony\\Component\\Config\\Util\\Exception\\XmlParsingException' => __DIR__ . '/..' . '/symfony/config/Util/Exception/XmlParsingException.php', - 'Symfony\\Component\\Config\\Util\\XmlUtils' => __DIR__ . '/..' . '/symfony/config/Util/XmlUtils.php', - 'Symfony\\Component\\Console\\Application' => __DIR__ . '/..' . '/symfony/console/Application.php', - 'Symfony\\Component\\Console\\Attribute\\AsCommand' => __DIR__ . '/..' . '/symfony/console/Attribute/AsCommand.php', - 'Symfony\\Component\\Console\\CI\\GithubActionReporter' => __DIR__ . '/..' . '/symfony/console/CI/GithubActionReporter.php', - 'Symfony\\Component\\Console\\Color' => __DIR__ . '/..' . '/symfony/console/Color.php', - 'Symfony\\Component\\Console\\CommandLoader\\CommandLoaderInterface' => __DIR__ . '/..' . '/symfony/console/CommandLoader/CommandLoaderInterface.php', - 'Symfony\\Component\\Console\\CommandLoader\\ContainerCommandLoader' => __DIR__ . '/..' . '/symfony/console/CommandLoader/ContainerCommandLoader.php', - 'Symfony\\Component\\Console\\CommandLoader\\FactoryCommandLoader' => __DIR__ . '/..' . '/symfony/console/CommandLoader/FactoryCommandLoader.php', - 'Symfony\\Component\\Console\\Command\\Command' => __DIR__ . '/..' . '/symfony/console/Command/Command.php', - 'Symfony\\Component\\Console\\Command\\CompleteCommand' => __DIR__ . '/..' . '/symfony/console/Command/CompleteCommand.php', - 'Symfony\\Component\\Console\\Command\\DumpCompletionCommand' => __DIR__ . '/..' . '/symfony/console/Command/DumpCompletionCommand.php', - 'Symfony\\Component\\Console\\Command\\HelpCommand' => __DIR__ . '/..' . '/symfony/console/Command/HelpCommand.php', - 'Symfony\\Component\\Console\\Command\\LazyCommand' => __DIR__ . '/..' . '/symfony/console/Command/LazyCommand.php', - 'Symfony\\Component\\Console\\Command\\ListCommand' => __DIR__ . '/..' . '/symfony/console/Command/ListCommand.php', - 'Symfony\\Component\\Console\\Command\\LockableTrait' => __DIR__ . '/..' . '/symfony/console/Command/LockableTrait.php', - 'Symfony\\Component\\Console\\Command\\SignalableCommandInterface' => __DIR__ . '/..' . '/symfony/console/Command/SignalableCommandInterface.php', - 'Symfony\\Component\\Console\\Completion\\CompletionInput' => __DIR__ . '/..' . '/symfony/console/Completion/CompletionInput.php', - 'Symfony\\Component\\Console\\Completion\\CompletionSuggestions' => __DIR__ . '/..' . '/symfony/console/Completion/CompletionSuggestions.php', - 'Symfony\\Component\\Console\\Completion\\Output\\BashCompletionOutput' => __DIR__ . '/..' . '/symfony/console/Completion/Output/BashCompletionOutput.php', - 'Symfony\\Component\\Console\\Completion\\Output\\CompletionOutputInterface' => __DIR__ . '/..' . '/symfony/console/Completion/Output/CompletionOutputInterface.php', - 'Symfony\\Component\\Console\\Completion\\Suggestion' => __DIR__ . '/..' . '/symfony/console/Completion/Suggestion.php', - 'Symfony\\Component\\Console\\ConsoleEvents' => __DIR__ . '/..' . '/symfony/console/ConsoleEvents.php', - 'Symfony\\Component\\Console\\Cursor' => __DIR__ . '/..' . '/symfony/console/Cursor.php', - 'Symfony\\Component\\Console\\DependencyInjection\\AddConsoleCommandPass' => __DIR__ . '/..' . '/symfony/console/DependencyInjection/AddConsoleCommandPass.php', - 'Symfony\\Component\\Console\\Descriptor\\ApplicationDescription' => __DIR__ . '/..' . '/symfony/console/Descriptor/ApplicationDescription.php', - 'Symfony\\Component\\Console\\Descriptor\\Descriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/Descriptor.php', - 'Symfony\\Component\\Console\\Descriptor\\DescriptorInterface' => __DIR__ . '/..' . '/symfony/console/Descriptor/DescriptorInterface.php', - 'Symfony\\Component\\Console\\Descriptor\\JsonDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/JsonDescriptor.php', - 'Symfony\\Component\\Console\\Descriptor\\MarkdownDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/MarkdownDescriptor.php', - 'Symfony\\Component\\Console\\Descriptor\\TextDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/TextDescriptor.php', - 'Symfony\\Component\\Console\\Descriptor\\XmlDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/XmlDescriptor.php', - 'Symfony\\Component\\Console\\EventListener\\ErrorListener' => __DIR__ . '/..' . '/symfony/console/EventListener/ErrorListener.php', - 'Symfony\\Component\\Console\\Event\\ConsoleCommandEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleCommandEvent.php', - 'Symfony\\Component\\Console\\Event\\ConsoleErrorEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleErrorEvent.php', - 'Symfony\\Component\\Console\\Event\\ConsoleEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleEvent.php', - 'Symfony\\Component\\Console\\Event\\ConsoleSignalEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleSignalEvent.php', - 'Symfony\\Component\\Console\\Event\\ConsoleTerminateEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleTerminateEvent.php', - 'Symfony\\Component\\Console\\Exception\\CommandNotFoundException' => __DIR__ . '/..' . '/symfony/console/Exception/CommandNotFoundException.php', - 'Symfony\\Component\\Console\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/console/Exception/ExceptionInterface.php', - 'Symfony\\Component\\Console\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/console/Exception/InvalidArgumentException.php', - 'Symfony\\Component\\Console\\Exception\\InvalidOptionException' => __DIR__ . '/..' . '/symfony/console/Exception/InvalidOptionException.php', - 'Symfony\\Component\\Console\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/console/Exception/LogicException.php', - 'Symfony\\Component\\Console\\Exception\\MissingInputException' => __DIR__ . '/..' . '/symfony/console/Exception/MissingInputException.php', - 'Symfony\\Component\\Console\\Exception\\NamespaceNotFoundException' => __DIR__ . '/..' . '/symfony/console/Exception/NamespaceNotFoundException.php', - 'Symfony\\Component\\Console\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/console/Exception/RuntimeException.php', - 'Symfony\\Component\\Console\\Formatter\\NullOutputFormatter' => __DIR__ . '/..' . '/symfony/console/Formatter/NullOutputFormatter.php', - 'Symfony\\Component\\Console\\Formatter\\NullOutputFormatterStyle' => __DIR__ . '/..' . '/symfony/console/Formatter/NullOutputFormatterStyle.php', - 'Symfony\\Component\\Console\\Formatter\\OutputFormatter' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatter.php', - 'Symfony\\Component\\Console\\Formatter\\OutputFormatterInterface' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterInterface.php', - 'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyle' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyle.php', - 'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleInterface' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyleInterface.php', - 'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleStack' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyleStack.php', - 'Symfony\\Component\\Console\\Formatter\\WrappableOutputFormatterInterface' => __DIR__ . '/..' . '/symfony/console/Formatter/WrappableOutputFormatterInterface.php', - 'Symfony\\Component\\Console\\Helper\\DebugFormatterHelper' => __DIR__ . '/..' . '/symfony/console/Helper/DebugFormatterHelper.php', - 'Symfony\\Component\\Console\\Helper\\DescriptorHelper' => __DIR__ . '/..' . '/symfony/console/Helper/DescriptorHelper.php', - 'Symfony\\Component\\Console\\Helper\\Dumper' => __DIR__ . '/..' . '/symfony/console/Helper/Dumper.php', - 'Symfony\\Component\\Console\\Helper\\FormatterHelper' => __DIR__ . '/..' . '/symfony/console/Helper/FormatterHelper.php', - 'Symfony\\Component\\Console\\Helper\\Helper' => __DIR__ . '/..' . '/symfony/console/Helper/Helper.php', - 'Symfony\\Component\\Console\\Helper\\HelperInterface' => __DIR__ . '/..' . '/symfony/console/Helper/HelperInterface.php', - 'Symfony\\Component\\Console\\Helper\\HelperSet' => __DIR__ . '/..' . '/symfony/console/Helper/HelperSet.php', - 'Symfony\\Component\\Console\\Helper\\InputAwareHelper' => __DIR__ . '/..' . '/symfony/console/Helper/InputAwareHelper.php', - 'Symfony\\Component\\Console\\Helper\\ProcessHelper' => __DIR__ . '/..' . '/symfony/console/Helper/ProcessHelper.php', - 'Symfony\\Component\\Console\\Helper\\ProgressBar' => __DIR__ . '/..' . '/symfony/console/Helper/ProgressBar.php', - 'Symfony\\Component\\Console\\Helper\\ProgressIndicator' => __DIR__ . '/..' . '/symfony/console/Helper/ProgressIndicator.php', - 'Symfony\\Component\\Console\\Helper\\QuestionHelper' => __DIR__ . '/..' . '/symfony/console/Helper/QuestionHelper.php', - 'Symfony\\Component\\Console\\Helper\\SymfonyQuestionHelper' => __DIR__ . '/..' . '/symfony/console/Helper/SymfonyQuestionHelper.php', - 'Symfony\\Component\\Console\\Helper\\Table' => __DIR__ . '/..' . '/symfony/console/Helper/Table.php', - 'Symfony\\Component\\Console\\Helper\\TableCell' => __DIR__ . '/..' . '/symfony/console/Helper/TableCell.php', - 'Symfony\\Component\\Console\\Helper\\TableCellStyle' => __DIR__ . '/..' . '/symfony/console/Helper/TableCellStyle.php', - 'Symfony\\Component\\Console\\Helper\\TableRows' => __DIR__ . '/..' . '/symfony/console/Helper/TableRows.php', - 'Symfony\\Component\\Console\\Helper\\TableSeparator' => __DIR__ . '/..' . '/symfony/console/Helper/TableSeparator.php', - 'Symfony\\Component\\Console\\Helper\\TableStyle' => __DIR__ . '/..' . '/symfony/console/Helper/TableStyle.php', - 'Symfony\\Component\\Console\\Input\\ArgvInput' => __DIR__ . '/..' . '/symfony/console/Input/ArgvInput.php', - 'Symfony\\Component\\Console\\Input\\ArrayInput' => __DIR__ . '/..' . '/symfony/console/Input/ArrayInput.php', - 'Symfony\\Component\\Console\\Input\\Input' => __DIR__ . '/..' . '/symfony/console/Input/Input.php', - 'Symfony\\Component\\Console\\Input\\InputArgument' => __DIR__ . '/..' . '/symfony/console/Input/InputArgument.php', - 'Symfony\\Component\\Console\\Input\\InputAwareInterface' => __DIR__ . '/..' . '/symfony/console/Input/InputAwareInterface.php', - 'Symfony\\Component\\Console\\Input\\InputDefinition' => __DIR__ . '/..' . '/symfony/console/Input/InputDefinition.php', - 'Symfony\\Component\\Console\\Input\\InputInterface' => __DIR__ . '/..' . '/symfony/console/Input/InputInterface.php', - 'Symfony\\Component\\Console\\Input\\InputOption' => __DIR__ . '/..' . '/symfony/console/Input/InputOption.php', - 'Symfony\\Component\\Console\\Input\\StreamableInputInterface' => __DIR__ . '/..' . '/symfony/console/Input/StreamableInputInterface.php', - 'Symfony\\Component\\Console\\Input\\StringInput' => __DIR__ . '/..' . '/symfony/console/Input/StringInput.php', - 'Symfony\\Component\\Console\\Logger\\ConsoleLogger' => __DIR__ . '/..' . '/symfony/console/Logger/ConsoleLogger.php', - 'Symfony\\Component\\Console\\Output\\BufferedOutput' => __DIR__ . '/..' . '/symfony/console/Output/BufferedOutput.php', - 'Symfony\\Component\\Console\\Output\\ConsoleOutput' => __DIR__ . '/..' . '/symfony/console/Output/ConsoleOutput.php', - 'Symfony\\Component\\Console\\Output\\ConsoleOutputInterface' => __DIR__ . '/..' . '/symfony/console/Output/ConsoleOutputInterface.php', - 'Symfony\\Component\\Console\\Output\\ConsoleSectionOutput' => __DIR__ . '/..' . '/symfony/console/Output/ConsoleSectionOutput.php', - 'Symfony\\Component\\Console\\Output\\NullOutput' => __DIR__ . '/..' . '/symfony/console/Output/NullOutput.php', - 'Symfony\\Component\\Console\\Output\\Output' => __DIR__ . '/..' . '/symfony/console/Output/Output.php', - 'Symfony\\Component\\Console\\Output\\OutputInterface' => __DIR__ . '/..' . '/symfony/console/Output/OutputInterface.php', - 'Symfony\\Component\\Console\\Output\\StreamOutput' => __DIR__ . '/..' . '/symfony/console/Output/StreamOutput.php', - 'Symfony\\Component\\Console\\Output\\TrimmedBufferOutput' => __DIR__ . '/..' . '/symfony/console/Output/TrimmedBufferOutput.php', - 'Symfony\\Component\\Console\\Question\\ChoiceQuestion' => __DIR__ . '/..' . '/symfony/console/Question/ChoiceQuestion.php', - 'Symfony\\Component\\Console\\Question\\ConfirmationQuestion' => __DIR__ . '/..' . '/symfony/console/Question/ConfirmationQuestion.php', - 'Symfony\\Component\\Console\\Question\\Question' => __DIR__ . '/..' . '/symfony/console/Question/Question.php', - 'Symfony\\Component\\Console\\SignalRegistry\\SignalRegistry' => __DIR__ . '/..' . '/symfony/console/SignalRegistry/SignalRegistry.php', - 'Symfony\\Component\\Console\\SingleCommandApplication' => __DIR__ . '/..' . '/symfony/console/SingleCommandApplication.php', - 'Symfony\\Component\\Console\\Style\\OutputStyle' => __DIR__ . '/..' . '/symfony/console/Style/OutputStyle.php', - 'Symfony\\Component\\Console\\Style\\StyleInterface' => __DIR__ . '/..' . '/symfony/console/Style/StyleInterface.php', - 'Symfony\\Component\\Console\\Style\\SymfonyStyle' => __DIR__ . '/..' . '/symfony/console/Style/SymfonyStyle.php', - 'Symfony\\Component\\Console\\Terminal' => __DIR__ . '/..' . '/symfony/console/Terminal.php', - 'Symfony\\Component\\Console\\Tester\\ApplicationTester' => __DIR__ . '/..' . '/symfony/console/Tester/ApplicationTester.php', - 'Symfony\\Component\\Console\\Tester\\CommandCompletionTester' => __DIR__ . '/..' . '/symfony/console/Tester/CommandCompletionTester.php', - 'Symfony\\Component\\Console\\Tester\\CommandTester' => __DIR__ . '/..' . '/symfony/console/Tester/CommandTester.php', - 'Symfony\\Component\\Console\\Tester\\Constraint\\CommandIsSuccessful' => __DIR__ . '/..' . '/symfony/console/Tester/Constraint/CommandIsSuccessful.php', - 'Symfony\\Component\\Console\\Tester\\TesterTrait' => __DIR__ . '/..' . '/symfony/console/Tester/TesterTrait.php', - 'Symfony\\Component\\CssSelector\\CssSelectorConverter' => __DIR__ . '/..' . '/symfony/css-selector/CssSelectorConverter.php', - 'Symfony\\Component\\CssSelector\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/css-selector/Exception/ExceptionInterface.php', - 'Symfony\\Component\\CssSelector\\Exception\\ExpressionErrorException' => __DIR__ . '/..' . '/symfony/css-selector/Exception/ExpressionErrorException.php', - 'Symfony\\Component\\CssSelector\\Exception\\InternalErrorException' => __DIR__ . '/..' . '/symfony/css-selector/Exception/InternalErrorException.php', - 'Symfony\\Component\\CssSelector\\Exception\\ParseException' => __DIR__ . '/..' . '/symfony/css-selector/Exception/ParseException.php', - 'Symfony\\Component\\CssSelector\\Exception\\SyntaxErrorException' => __DIR__ . '/..' . '/symfony/css-selector/Exception/SyntaxErrorException.php', - 'Symfony\\Component\\CssSelector\\Node\\AbstractNode' => __DIR__ . '/..' . '/symfony/css-selector/Node/AbstractNode.php', - 'Symfony\\Component\\CssSelector\\Node\\AttributeNode' => __DIR__ . '/..' . '/symfony/css-selector/Node/AttributeNode.php', - 'Symfony\\Component\\CssSelector\\Node\\ClassNode' => __DIR__ . '/..' . '/symfony/css-selector/Node/ClassNode.php', - 'Symfony\\Component\\CssSelector\\Node\\CombinedSelectorNode' => __DIR__ . '/..' . '/symfony/css-selector/Node/CombinedSelectorNode.php', - 'Symfony\\Component\\CssSelector\\Node\\ElementNode' => __DIR__ . '/..' . '/symfony/css-selector/Node/ElementNode.php', - 'Symfony\\Component\\CssSelector\\Node\\FunctionNode' => __DIR__ . '/..' . '/symfony/css-selector/Node/FunctionNode.php', - 'Symfony\\Component\\CssSelector\\Node\\HashNode' => __DIR__ . '/..' . '/symfony/css-selector/Node/HashNode.php', - 'Symfony\\Component\\CssSelector\\Node\\NegationNode' => __DIR__ . '/..' . '/symfony/css-selector/Node/NegationNode.php', - 'Symfony\\Component\\CssSelector\\Node\\NodeInterface' => __DIR__ . '/..' . '/symfony/css-selector/Node/NodeInterface.php', - 'Symfony\\Component\\CssSelector\\Node\\PseudoNode' => __DIR__ . '/..' . '/symfony/css-selector/Node/PseudoNode.php', - 'Symfony\\Component\\CssSelector\\Node\\SelectorNode' => __DIR__ . '/..' . '/symfony/css-selector/Node/SelectorNode.php', - 'Symfony\\Component\\CssSelector\\Node\\Specificity' => __DIR__ . '/..' . '/symfony/css-selector/Node/Specificity.php', - 'Symfony\\Component\\CssSelector\\Parser\\Handler\\CommentHandler' => __DIR__ . '/..' . '/symfony/css-selector/Parser/Handler/CommentHandler.php', - 'Symfony\\Component\\CssSelector\\Parser\\Handler\\HandlerInterface' => __DIR__ . '/..' . '/symfony/css-selector/Parser/Handler/HandlerInterface.php', - 'Symfony\\Component\\CssSelector\\Parser\\Handler\\HashHandler' => __DIR__ . '/..' . '/symfony/css-selector/Parser/Handler/HashHandler.php', - 'Symfony\\Component\\CssSelector\\Parser\\Handler\\IdentifierHandler' => __DIR__ . '/..' . '/symfony/css-selector/Parser/Handler/IdentifierHandler.php', - 'Symfony\\Component\\CssSelector\\Parser\\Handler\\NumberHandler' => __DIR__ . '/..' . '/symfony/css-selector/Parser/Handler/NumberHandler.php', - 'Symfony\\Component\\CssSelector\\Parser\\Handler\\StringHandler' => __DIR__ . '/..' . '/symfony/css-selector/Parser/Handler/StringHandler.php', - 'Symfony\\Component\\CssSelector\\Parser\\Handler\\WhitespaceHandler' => __DIR__ . '/..' . '/symfony/css-selector/Parser/Handler/WhitespaceHandler.php', - 'Symfony\\Component\\CssSelector\\Parser\\Parser' => __DIR__ . '/..' . '/symfony/css-selector/Parser/Parser.php', - 'Symfony\\Component\\CssSelector\\Parser\\ParserInterface' => __DIR__ . '/..' . '/symfony/css-selector/Parser/ParserInterface.php', - 'Symfony\\Component\\CssSelector\\Parser\\Reader' => __DIR__ . '/..' . '/symfony/css-selector/Parser/Reader.php', - 'Symfony\\Component\\CssSelector\\Parser\\Shortcut\\ClassParser' => __DIR__ . '/..' . '/symfony/css-selector/Parser/Shortcut/ClassParser.php', - 'Symfony\\Component\\CssSelector\\Parser\\Shortcut\\ElementParser' => __DIR__ . '/..' . '/symfony/css-selector/Parser/Shortcut/ElementParser.php', - 'Symfony\\Component\\CssSelector\\Parser\\Shortcut\\EmptyStringParser' => __DIR__ . '/..' . '/symfony/css-selector/Parser/Shortcut/EmptyStringParser.php', - 'Symfony\\Component\\CssSelector\\Parser\\Shortcut\\HashParser' => __DIR__ . '/..' . '/symfony/css-selector/Parser/Shortcut/HashParser.php', - 'Symfony\\Component\\CssSelector\\Parser\\Token' => __DIR__ . '/..' . '/symfony/css-selector/Parser/Token.php', - 'Symfony\\Component\\CssSelector\\Parser\\TokenStream' => __DIR__ . '/..' . '/symfony/css-selector/Parser/TokenStream.php', - 'Symfony\\Component\\CssSelector\\Parser\\Tokenizer\\Tokenizer' => __DIR__ . '/..' . '/symfony/css-selector/Parser/Tokenizer/Tokenizer.php', - 'Symfony\\Component\\CssSelector\\Parser\\Tokenizer\\TokenizerEscaping' => __DIR__ . '/..' . '/symfony/css-selector/Parser/Tokenizer/TokenizerEscaping.php', - 'Symfony\\Component\\CssSelector\\Parser\\Tokenizer\\TokenizerPatterns' => __DIR__ . '/..' . '/symfony/css-selector/Parser/Tokenizer/TokenizerPatterns.php', - 'Symfony\\Component\\CssSelector\\XPath\\Extension\\AbstractExtension' => __DIR__ . '/..' . '/symfony/css-selector/XPath/Extension/AbstractExtension.php', - 'Symfony\\Component\\CssSelector\\XPath\\Extension\\AttributeMatchingExtension' => __DIR__ . '/..' . '/symfony/css-selector/XPath/Extension/AttributeMatchingExtension.php', - 'Symfony\\Component\\CssSelector\\XPath\\Extension\\CombinationExtension' => __DIR__ . '/..' . '/symfony/css-selector/XPath/Extension/CombinationExtension.php', - 'Symfony\\Component\\CssSelector\\XPath\\Extension\\ExtensionInterface' => __DIR__ . '/..' . '/symfony/css-selector/XPath/Extension/ExtensionInterface.php', - 'Symfony\\Component\\CssSelector\\XPath\\Extension\\FunctionExtension' => __DIR__ . '/..' . '/symfony/css-selector/XPath/Extension/FunctionExtension.php', - 'Symfony\\Component\\CssSelector\\XPath\\Extension\\HtmlExtension' => __DIR__ . '/..' . '/symfony/css-selector/XPath/Extension/HtmlExtension.php', - 'Symfony\\Component\\CssSelector\\XPath\\Extension\\NodeExtension' => __DIR__ . '/..' . '/symfony/css-selector/XPath/Extension/NodeExtension.php', - 'Symfony\\Component\\CssSelector\\XPath\\Extension\\PseudoClassExtension' => __DIR__ . '/..' . '/symfony/css-selector/XPath/Extension/PseudoClassExtension.php', - 'Symfony\\Component\\CssSelector\\XPath\\Translator' => __DIR__ . '/..' . '/symfony/css-selector/XPath/Translator.php', - 'Symfony\\Component\\CssSelector\\XPath\\TranslatorInterface' => __DIR__ . '/..' . '/symfony/css-selector/XPath/TranslatorInterface.php', - 'Symfony\\Component\\CssSelector\\XPath\\XPathExpr' => __DIR__ . '/..' . '/symfony/css-selector/XPath/XPathExpr.php', - 'Symfony\\Component\\DependencyInjection\\Alias' => __DIR__ . '/..' . '/symfony/dependency-injection/Alias.php', - 'Symfony\\Component\\DependencyInjection\\Argument\\AbstractArgument' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/AbstractArgument.php', - 'Symfony\\Component\\DependencyInjection\\Argument\\ArgumentInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/ArgumentInterface.php', - 'Symfony\\Component\\DependencyInjection\\Argument\\BoundArgument' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/BoundArgument.php', - 'Symfony\\Component\\DependencyInjection\\Argument\\IteratorArgument' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/IteratorArgument.php', - 'Symfony\\Component\\DependencyInjection\\Argument\\ReferenceSetArgumentTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/ReferenceSetArgumentTrait.php', - 'Symfony\\Component\\DependencyInjection\\Argument\\RewindableGenerator' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/RewindableGenerator.php', - 'Symfony\\Component\\DependencyInjection\\Argument\\ServiceClosureArgument' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/ServiceClosureArgument.php', - 'Symfony\\Component\\DependencyInjection\\Argument\\ServiceLocator' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/ServiceLocator.php', - 'Symfony\\Component\\DependencyInjection\\Argument\\ServiceLocatorArgument' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/ServiceLocatorArgument.php', - 'Symfony\\Component\\DependencyInjection\\Argument\\TaggedIteratorArgument' => __DIR__ . '/..' . '/symfony/dependency-injection/Argument/TaggedIteratorArgument.php', - 'Symfony\\Component\\DependencyInjection\\Attribute\\AsTaggedItem' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AsTaggedItem.php', - 'Symfony\\Component\\DependencyInjection\\Attribute\\Autoconfigure' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/Autoconfigure.php', - 'Symfony\\Component\\DependencyInjection\\Attribute\\AutoconfigureTag' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AutoconfigureTag.php', - 'Symfony\\Component\\DependencyInjection\\Attribute\\TaggedIterator' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/TaggedIterator.php', - 'Symfony\\Component\\DependencyInjection\\Attribute\\TaggedLocator' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/TaggedLocator.php', - 'Symfony\\Component\\DependencyInjection\\Attribute\\Target' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/Target.php', - 'Symfony\\Component\\DependencyInjection\\Attribute\\When' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/When.php', - 'Symfony\\Component\\DependencyInjection\\ChildDefinition' => __DIR__ . '/..' . '/symfony/dependency-injection/ChildDefinition.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\AbstractRecursivePass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AbstractRecursivePass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\AliasDeprecatedPublicServicesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AliasDeprecatedPublicServicesPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\AnalyzeServiceReferencesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\AttributeAutoconfigurationPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AttributeAutoconfigurationPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\AutoAliasServicePass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AutoAliasServicePass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\AutowirePass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AutowirePass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\AutowireRequiredMethodsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\AutowireRequiredPropertiesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AutowireRequiredPropertiesPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\CheckArgumentsValidityPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\CheckCircularReferencesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\CheckDefinitionValidityPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\CheckExceptionOnInvalidReferenceBehaviorPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\CheckReferenceValidityPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\CheckTypeDeclarationsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\Compiler' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/Compiler.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\CompilerPassInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CompilerPassInterface.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\DecoratorServicePass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/DecoratorServicePass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\DefinitionErrorExceptionPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ExtensionCompilerPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ExtensionCompilerPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\InlineServiceDefinitionsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\MergeExtensionConfigurationPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\PassConfig' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/PassConfig.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\PriorityTaggedServiceTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\RegisterAutoconfigureAttributesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RegisterAutoconfigureAttributesPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\RegisterEnvVarProcessorsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\RegisterReverseContainerPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RegisterReverseContainerPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\RegisterServiceSubscribersPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\RemoveAbstractDefinitionsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\RemovePrivateAliasesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\RemoveUnusedDefinitionsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ReplaceAliasByActualDefinitionPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveBindingsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveBindingsPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveChildDefinitionsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveClassPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveClassPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveDecoratorStackPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveDecoratorStackPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveEnvPlaceholdersPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveFactoryClassPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveHotPathPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveHotPathPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveInstanceofConditionalsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveInvalidReferencesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveNamedArgumentsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveNoPreloadPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveNoPreloadPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveParameterPlaceHoldersPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolvePrivatesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolvePrivatesPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveReferencesToAliasesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveServiceSubscribersPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveTaggedIteratorArgumentPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ServiceLocatorTagPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ServiceReferenceGraph' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ServiceReferenceGraphEdge' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ServiceReferenceGraphNode' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php', - 'Symfony\\Component\\DependencyInjection\\Compiler\\ValidateEnvPlaceholdersPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php', - 'Symfony\\Component\\DependencyInjection\\Config\\ContainerParametersResource' => __DIR__ . '/..' . '/symfony/dependency-injection/Config/ContainerParametersResource.php', - 'Symfony\\Component\\DependencyInjection\\Config\\ContainerParametersResourceChecker' => __DIR__ . '/..' . '/symfony/dependency-injection/Config/ContainerParametersResourceChecker.php', - 'Symfony\\Component\\DependencyInjection\\Container' => __DIR__ . '/..' . '/symfony/dependency-injection/Container.php', - 'Symfony\\Component\\DependencyInjection\\ContainerAwareInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/ContainerAwareInterface.php', - 'Symfony\\Component\\DependencyInjection\\ContainerAwareTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/ContainerAwareTrait.php', - 'Symfony\\Component\\DependencyInjection\\ContainerBuilder' => __DIR__ . '/..' . '/symfony/dependency-injection/ContainerBuilder.php', - 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/ContainerInterface.php', - 'Symfony\\Component\\DependencyInjection\\Definition' => __DIR__ . '/..' . '/symfony/dependency-injection/Definition.php', - 'Symfony\\Component\\DependencyInjection\\Dumper\\Dumper' => __DIR__ . '/..' . '/symfony/dependency-injection/Dumper/Dumper.php', - 'Symfony\\Component\\DependencyInjection\\Dumper\\DumperInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/Dumper/DumperInterface.php', - 'Symfony\\Component\\DependencyInjection\\Dumper\\GraphvizDumper' => __DIR__ . '/..' . '/symfony/dependency-injection/Dumper/GraphvizDumper.php', - 'Symfony\\Component\\DependencyInjection\\Dumper\\PhpDumper' => __DIR__ . '/..' . '/symfony/dependency-injection/Dumper/PhpDumper.php', - 'Symfony\\Component\\DependencyInjection\\Dumper\\Preloader' => __DIR__ . '/..' . '/symfony/dependency-injection/Dumper/Preloader.php', - 'Symfony\\Component\\DependencyInjection\\Dumper\\XmlDumper' => __DIR__ . '/..' . '/symfony/dependency-injection/Dumper/XmlDumper.php', - 'Symfony\\Component\\DependencyInjection\\Dumper\\YamlDumper' => __DIR__ . '/..' . '/symfony/dependency-injection/Dumper/YamlDumper.php', - 'Symfony\\Component\\DependencyInjection\\EnvVarLoaderInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/EnvVarLoaderInterface.php', - 'Symfony\\Component\\DependencyInjection\\EnvVarProcessor' => __DIR__ . '/..' . '/symfony/dependency-injection/EnvVarProcessor.php', - 'Symfony\\Component\\DependencyInjection\\EnvVarProcessorInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/EnvVarProcessorInterface.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\AutowiringFailedException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/AutowiringFailedException.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\BadMethodCallException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/BadMethodCallException.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\EnvNotFoundException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/EnvNotFoundException.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\EnvParameterException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/EnvParameterException.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/ExceptionInterface.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/InvalidArgumentException.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\InvalidParameterTypeException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/InvalidParameterTypeException.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/LogicException.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\OutOfBoundsException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/OutOfBoundsException.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\ParameterCircularReferenceException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\ParameterNotFoundException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/ParameterNotFoundException.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/RuntimeException.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\ServiceCircularReferenceException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php', - 'Symfony\\Component\\DependencyInjection\\Exception\\ServiceNotFoundException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/ServiceNotFoundException.php', - 'Symfony\\Component\\DependencyInjection\\ExpressionLanguage' => __DIR__ . '/..' . '/symfony/dependency-injection/ExpressionLanguage.php', - 'Symfony\\Component\\DependencyInjection\\ExpressionLanguageProvider' => __DIR__ . '/..' . '/symfony/dependency-injection/ExpressionLanguageProvider.php', - 'Symfony\\Component\\DependencyInjection\\Extension\\ConfigurationExtensionInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/Extension/ConfigurationExtensionInterface.php', - 'Symfony\\Component\\DependencyInjection\\Extension\\Extension' => __DIR__ . '/..' . '/symfony/dependency-injection/Extension/Extension.php', - 'Symfony\\Component\\DependencyInjection\\Extension\\ExtensionInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/Extension/ExtensionInterface.php', - 'Symfony\\Component\\DependencyInjection\\Extension\\PrependExtensionInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/Extension/PrependExtensionInterface.php', - 'Symfony\\Component\\DependencyInjection\\LazyProxy\\Instantiator\\InstantiatorInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/LazyProxy/Instantiator/InstantiatorInterface.php', - 'Symfony\\Component\\DependencyInjection\\LazyProxy\\Instantiator\\RealServiceInstantiator' => __DIR__ . '/..' . '/symfony/dependency-injection/LazyProxy/Instantiator/RealServiceInstantiator.php', - 'Symfony\\Component\\DependencyInjection\\LazyProxy\\PhpDumper\\DumperInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php', - 'Symfony\\Component\\DependencyInjection\\LazyProxy\\PhpDumper\\NullDumper' => __DIR__ . '/..' . '/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php', - 'Symfony\\Component\\DependencyInjection\\LazyProxy\\ProxyHelper' => __DIR__ . '/..' . '/symfony/dependency-injection/LazyProxy/ProxyHelper.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\ClosureLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/ClosureLoader.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\AbstractConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\AbstractServiceConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\AliasConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/AliasConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ClosureReferenceConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/ClosureReferenceConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ContainerConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\DefaultsConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\EnvConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/EnvConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\InlineServiceConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/InlineServiceConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\InstanceofConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ParametersConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/ParametersConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\PrototypeConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ReferenceConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/ReferenceConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ServiceConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ServicesConfigurator' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\AbstractTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/AbstractTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ArgumentTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/ArgumentTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\AutoconfigureTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/AutoconfigureTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\AutowireTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/AutowireTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\BindTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/BindTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\CallTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/CallTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ClassTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/ClassTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ConfiguratorTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/ConfiguratorTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\DecorateTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\DeprecateTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/DeprecateTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\FactoryTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/FactoryTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\FileTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/FileTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\LazyTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/LazyTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ParentTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/ParentTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\PropertyTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/PropertyTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\PublicTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/PublicTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\ShareTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/ShareTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\SyntheticTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/SyntheticTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\Traits\\TagTrait' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/Configurator/Traits/TagTrait.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\DirectoryLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/DirectoryLoader.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\FileLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/FileLoader.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\GlobFileLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/GlobFileLoader.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\IniFileLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/IniFileLoader.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\PhpFileLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/PhpFileLoader.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\XmlFileLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/XmlFileLoader.php', - 'Symfony\\Component\\DependencyInjection\\Loader\\YamlFileLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/YamlFileLoader.php', - 'Symfony\\Component\\DependencyInjection\\Parameter' => __DIR__ . '/..' . '/symfony/dependency-injection/Parameter.php', - 'Symfony\\Component\\DependencyInjection\\ParameterBag\\ContainerBag' => __DIR__ . '/..' . '/symfony/dependency-injection/ParameterBag/ContainerBag.php', - 'Symfony\\Component\\DependencyInjection\\ParameterBag\\ContainerBagInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/ParameterBag/ContainerBagInterface.php', - 'Symfony\\Component\\DependencyInjection\\ParameterBag\\EnvPlaceholderParameterBag' => __DIR__ . '/..' . '/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php', - 'Symfony\\Component\\DependencyInjection\\ParameterBag\\FrozenParameterBag' => __DIR__ . '/..' . '/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php', - 'Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBag' => __DIR__ . '/..' . '/symfony/dependency-injection/ParameterBag/ParameterBag.php', - 'Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBagInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php', - 'Symfony\\Component\\DependencyInjection\\Reference' => __DIR__ . '/..' . '/symfony/dependency-injection/Reference.php', - 'Symfony\\Component\\DependencyInjection\\ReverseContainer' => __DIR__ . '/..' . '/symfony/dependency-injection/ReverseContainer.php', - 'Symfony\\Component\\DependencyInjection\\ServiceLocator' => __DIR__ . '/..' . '/symfony/dependency-injection/ServiceLocator.php', - 'Symfony\\Component\\DependencyInjection\\TaggedContainerInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/TaggedContainerInterface.php', - 'Symfony\\Component\\DependencyInjection\\TypedReference' => __DIR__ . '/..' . '/symfony/dependency-injection/TypedReference.php', - 'Symfony\\Component\\DependencyInjection\\Variable' => __DIR__ . '/..' . '/symfony/dependency-injection/Variable.php', - 'Symfony\\Component\\Dotenv\\Command\\DebugCommand' => __DIR__ . '/..' . '/symfony/dotenv/Command/DebugCommand.php', - 'Symfony\\Component\\Dotenv\\Command\\DotenvDumpCommand' => __DIR__ . '/..' . '/symfony/dotenv/Command/DotenvDumpCommand.php', - 'Symfony\\Component\\Dotenv\\Dotenv' => __DIR__ . '/..' . '/symfony/dotenv/Dotenv.php', - 'Symfony\\Component\\Dotenv\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/dotenv/Exception/ExceptionInterface.php', - 'Symfony\\Component\\Dotenv\\Exception\\FormatException' => __DIR__ . '/..' . '/symfony/dotenv/Exception/FormatException.php', - 'Symfony\\Component\\Dotenv\\Exception\\FormatExceptionContext' => __DIR__ . '/..' . '/symfony/dotenv/Exception/FormatExceptionContext.php', - 'Symfony\\Component\\Dotenv\\Exception\\PathException' => __DIR__ . '/..' . '/symfony/dotenv/Exception/PathException.php', - 'Symfony\\Component\\ErrorHandler\\BufferingLogger' => __DIR__ . '/..' . '/symfony/error-handler/BufferingLogger.php', - 'Symfony\\Component\\ErrorHandler\\Debug' => __DIR__ . '/..' . '/symfony/error-handler/Debug.php', - 'Symfony\\Component\\ErrorHandler\\DebugClassLoader' => __DIR__ . '/..' . '/symfony/error-handler/DebugClassLoader.php', - 'Symfony\\Component\\ErrorHandler\\ErrorEnhancer\\ClassNotFoundErrorEnhancer' => __DIR__ . '/..' . '/symfony/error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php', - 'Symfony\\Component\\ErrorHandler\\ErrorEnhancer\\ErrorEnhancerInterface' => __DIR__ . '/..' . '/symfony/error-handler/ErrorEnhancer/ErrorEnhancerInterface.php', - 'Symfony\\Component\\ErrorHandler\\ErrorEnhancer\\UndefinedFunctionErrorEnhancer' => __DIR__ . '/..' . '/symfony/error-handler/ErrorEnhancer/UndefinedFunctionErrorEnhancer.php', - 'Symfony\\Component\\ErrorHandler\\ErrorEnhancer\\UndefinedMethodErrorEnhancer' => __DIR__ . '/..' . '/symfony/error-handler/ErrorEnhancer/UndefinedMethodErrorEnhancer.php', - 'Symfony\\Component\\ErrorHandler\\ErrorHandler' => __DIR__ . '/..' . '/symfony/error-handler/ErrorHandler.php', - 'Symfony\\Component\\ErrorHandler\\ErrorRenderer\\CliErrorRenderer' => __DIR__ . '/..' . '/symfony/error-handler/ErrorRenderer/CliErrorRenderer.php', - 'Symfony\\Component\\ErrorHandler\\ErrorRenderer\\ErrorRendererInterface' => __DIR__ . '/..' . '/symfony/error-handler/ErrorRenderer/ErrorRendererInterface.php', - 'Symfony\\Component\\ErrorHandler\\ErrorRenderer\\HtmlErrorRenderer' => __DIR__ . '/..' . '/symfony/error-handler/ErrorRenderer/HtmlErrorRenderer.php', - 'Symfony\\Component\\ErrorHandler\\ErrorRenderer\\SerializerErrorRenderer' => __DIR__ . '/..' . '/symfony/error-handler/ErrorRenderer/SerializerErrorRenderer.php', - 'Symfony\\Component\\ErrorHandler\\Error\\ClassNotFoundError' => __DIR__ . '/..' . '/symfony/error-handler/Error/ClassNotFoundError.php', - 'Symfony\\Component\\ErrorHandler\\Error\\FatalError' => __DIR__ . '/..' . '/symfony/error-handler/Error/FatalError.php', - 'Symfony\\Component\\ErrorHandler\\Error\\OutOfMemoryError' => __DIR__ . '/..' . '/symfony/error-handler/Error/OutOfMemoryError.php', - 'Symfony\\Component\\ErrorHandler\\Error\\UndefinedFunctionError' => __DIR__ . '/..' . '/symfony/error-handler/Error/UndefinedFunctionError.php', - 'Symfony\\Component\\ErrorHandler\\Error\\UndefinedMethodError' => __DIR__ . '/..' . '/symfony/error-handler/Error/UndefinedMethodError.php', - 'Symfony\\Component\\ErrorHandler\\Exception\\FlattenException' => __DIR__ . '/..' . '/symfony/error-handler/Exception/FlattenException.php', - 'Symfony\\Component\\ErrorHandler\\Exception\\SilencedErrorContext' => __DIR__ . '/..' . '/symfony/error-handler/Exception/SilencedErrorContext.php', - 'Symfony\\Component\\ErrorHandler\\Internal\\TentativeTypes' => __DIR__ . '/..' . '/symfony/error-handler/Internal/TentativeTypes.php', - 'Symfony\\Component\\ErrorHandler\\ThrowableUtils' => __DIR__ . '/..' . '/symfony/error-handler/ThrowableUtils.php', - 'Symfony\\Component\\EventDispatcher\\Attribute\\AsEventListener' => __DIR__ . '/..' . '/symfony/event-dispatcher/Attribute/AsEventListener.php', - 'Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcher' => __DIR__ . '/..' . '/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php', - 'Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener' => __DIR__ . '/..' . '/symfony/event-dispatcher/Debug/WrappedListener.php', - 'Symfony\\Component\\EventDispatcher\\DependencyInjection\\AddEventAliasesPass' => __DIR__ . '/..' . '/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php', - 'Symfony\\Component\\EventDispatcher\\DependencyInjection\\RegisterListenersPass' => __DIR__ . '/..' . '/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php', - 'Symfony\\Component\\EventDispatcher\\EventDispatcher' => __DIR__ . '/..' . '/symfony/event-dispatcher/EventDispatcher.php', - 'Symfony\\Component\\EventDispatcher\\EventDispatcherInterface' => __DIR__ . '/..' . '/symfony/event-dispatcher/EventDispatcherInterface.php', - 'Symfony\\Component\\EventDispatcher\\EventSubscriberInterface' => __DIR__ . '/..' . '/symfony/event-dispatcher/EventSubscriberInterface.php', - 'Symfony\\Component\\EventDispatcher\\GenericEvent' => __DIR__ . '/..' . '/symfony/event-dispatcher/GenericEvent.php', - 'Symfony\\Component\\EventDispatcher\\ImmutableEventDispatcher' => __DIR__ . '/..' . '/symfony/event-dispatcher/ImmutableEventDispatcher.php', - 'Symfony\\Component\\EventDispatcher\\LegacyEventDispatcherProxy' => __DIR__ . '/..' . '/symfony/event-dispatcher/LegacyEventDispatcherProxy.php', - 'Symfony\\Component\\Filesystem\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/filesystem/Exception/ExceptionInterface.php', - 'Symfony\\Component\\Filesystem\\Exception\\FileNotFoundException' => __DIR__ . '/..' . '/symfony/filesystem/Exception/FileNotFoundException.php', - 'Symfony\\Component\\Filesystem\\Exception\\IOException' => __DIR__ . '/..' . '/symfony/filesystem/Exception/IOException.php', - 'Symfony\\Component\\Filesystem\\Exception\\IOExceptionInterface' => __DIR__ . '/..' . '/symfony/filesystem/Exception/IOExceptionInterface.php', - 'Symfony\\Component\\Filesystem\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/filesystem/Exception/InvalidArgumentException.php', - 'Symfony\\Component\\Filesystem\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/filesystem/Exception/RuntimeException.php', - 'Symfony\\Component\\Filesystem\\Filesystem' => __DIR__ . '/..' . '/symfony/filesystem/Filesystem.php', - 'Symfony\\Component\\Filesystem\\Path' => __DIR__ . '/..' . '/symfony/filesystem/Path.php', - 'Symfony\\Component\\Finder\\Comparator\\Comparator' => __DIR__ . '/..' . '/symfony/finder/Comparator/Comparator.php', - 'Symfony\\Component\\Finder\\Comparator\\DateComparator' => __DIR__ . '/..' . '/symfony/finder/Comparator/DateComparator.php', - 'Symfony\\Component\\Finder\\Comparator\\NumberComparator' => __DIR__ . '/..' . '/symfony/finder/Comparator/NumberComparator.php', - 'Symfony\\Component\\Finder\\Exception\\AccessDeniedException' => __DIR__ . '/..' . '/symfony/finder/Exception/AccessDeniedException.php', - 'Symfony\\Component\\Finder\\Exception\\DirectoryNotFoundException' => __DIR__ . '/..' . '/symfony/finder/Exception/DirectoryNotFoundException.php', - 'Symfony\\Component\\Finder\\Finder' => __DIR__ . '/..' . '/symfony/finder/Finder.php', - 'Symfony\\Component\\Finder\\Gitignore' => __DIR__ . '/..' . '/symfony/finder/Gitignore.php', - 'Symfony\\Component\\Finder\\Glob' => __DIR__ . '/..' . '/symfony/finder/Glob.php', - 'Symfony\\Component\\Finder\\Iterator\\CustomFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/CustomFilterIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\DateRangeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/DateRangeFilterIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\DepthRangeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/DepthRangeFilterIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\ExcludeDirectoryFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\FileTypeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FileTypeFilterIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\FilecontentFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FilecontentFilterIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\FilenameFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FilenameFilterIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\LazyIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/LazyIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\MultiplePcreFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/MultiplePcreFilterIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\PathFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/PathFilterIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\RecursiveDirectoryIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/RecursiveDirectoryIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\SizeRangeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/SizeRangeFilterIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\SortableIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/SortableIterator.php', - 'Symfony\\Component\\Finder\\Iterator\\VcsIgnoredFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/VcsIgnoredFilterIterator.php', - 'Symfony\\Component\\Finder\\SplFileInfo' => __DIR__ . '/..' . '/symfony/finder/SplFileInfo.php', - 'Symfony\\Component\\Form\\AbstractExtension' => __DIR__ . '/..' . '/symfony/form/AbstractExtension.php', - 'Symfony\\Component\\Form\\AbstractRendererEngine' => __DIR__ . '/..' . '/symfony/form/AbstractRendererEngine.php', - 'Symfony\\Component\\Form\\AbstractType' => __DIR__ . '/..' . '/symfony/form/AbstractType.php', - 'Symfony\\Component\\Form\\AbstractTypeExtension' => __DIR__ . '/..' . '/symfony/form/AbstractTypeExtension.php', - 'Symfony\\Component\\Form\\Button' => __DIR__ . '/..' . '/symfony/form/Button.php', - 'Symfony\\Component\\Form\\ButtonBuilder' => __DIR__ . '/..' . '/symfony/form/ButtonBuilder.php', - 'Symfony\\Component\\Form\\ButtonTypeInterface' => __DIR__ . '/..' . '/symfony/form/ButtonTypeInterface.php', - 'Symfony\\Component\\Form\\CallbackTransformer' => __DIR__ . '/..' . '/symfony/form/CallbackTransformer.php', - 'Symfony\\Component\\Form\\ChoiceList\\ArrayChoiceList' => __DIR__ . '/..' . '/symfony/form/ChoiceList/ArrayChoiceList.php', - 'Symfony\\Component\\Form\\ChoiceList\\ChoiceList' => __DIR__ . '/..' . '/symfony/form/ChoiceList/ChoiceList.php', - 'Symfony\\Component\\Form\\ChoiceList\\ChoiceListInterface' => __DIR__ . '/..' . '/symfony/form/ChoiceList/ChoiceListInterface.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\Cache\\AbstractStaticOption' => __DIR__ . '/..' . '/symfony/form/ChoiceList/Factory/Cache/AbstractStaticOption.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\Cache\\ChoiceAttr' => __DIR__ . '/..' . '/symfony/form/ChoiceList/Factory/Cache/ChoiceAttr.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\Cache\\ChoiceFieldName' => __DIR__ . '/..' . '/symfony/form/ChoiceList/Factory/Cache/ChoiceFieldName.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\Cache\\ChoiceFilter' => __DIR__ . '/..' . '/symfony/form/ChoiceList/Factory/Cache/ChoiceFilter.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\Cache\\ChoiceLabel' => __DIR__ . '/..' . '/symfony/form/ChoiceList/Factory/Cache/ChoiceLabel.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\Cache\\ChoiceLoader' => __DIR__ . '/..' . '/symfony/form/ChoiceList/Factory/Cache/ChoiceLoader.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\Cache\\ChoiceTranslationParameters' => __DIR__ . '/..' . '/symfony/form/ChoiceList/Factory/Cache/ChoiceTranslationParameters.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\Cache\\ChoiceValue' => __DIR__ . '/..' . '/symfony/form/ChoiceList/Factory/Cache/ChoiceValue.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\Cache\\GroupBy' => __DIR__ . '/..' . '/symfony/form/ChoiceList/Factory/Cache/GroupBy.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\Cache\\PreferredChoice' => __DIR__ . '/..' . '/symfony/form/ChoiceList/Factory/Cache/PreferredChoice.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\CachingFactoryDecorator' => __DIR__ . '/..' . '/symfony/form/ChoiceList/Factory/CachingFactoryDecorator.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\ChoiceListFactoryInterface' => __DIR__ . '/..' . '/symfony/form/ChoiceList/Factory/ChoiceListFactoryInterface.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\DefaultChoiceListFactory' => __DIR__ . '/..' . '/symfony/form/ChoiceList/Factory/DefaultChoiceListFactory.php', - 'Symfony\\Component\\Form\\ChoiceList\\Factory\\PropertyAccessDecorator' => __DIR__ . '/..' . '/symfony/form/ChoiceList/Factory/PropertyAccessDecorator.php', - 'Symfony\\Component\\Form\\ChoiceList\\LazyChoiceList' => __DIR__ . '/..' . '/symfony/form/ChoiceList/LazyChoiceList.php', - 'Symfony\\Component\\Form\\ChoiceList\\Loader\\AbstractChoiceLoader' => __DIR__ . '/..' . '/symfony/form/ChoiceList/Loader/AbstractChoiceLoader.php', - 'Symfony\\Component\\Form\\ChoiceList\\Loader\\CallbackChoiceLoader' => __DIR__ . '/..' . '/symfony/form/ChoiceList/Loader/CallbackChoiceLoader.php', - 'Symfony\\Component\\Form\\ChoiceList\\Loader\\ChoiceLoaderInterface' => __DIR__ . '/..' . '/symfony/form/ChoiceList/Loader/ChoiceLoaderInterface.php', - 'Symfony\\Component\\Form\\ChoiceList\\Loader\\FilterChoiceLoaderDecorator' => __DIR__ . '/..' . '/symfony/form/ChoiceList/Loader/FilterChoiceLoaderDecorator.php', - 'Symfony\\Component\\Form\\ChoiceList\\Loader\\IntlCallbackChoiceLoader' => __DIR__ . '/..' . '/symfony/form/ChoiceList/Loader/IntlCallbackChoiceLoader.php', - 'Symfony\\Component\\Form\\ChoiceList\\View\\ChoiceGroupView' => __DIR__ . '/..' . '/symfony/form/ChoiceList/View/ChoiceGroupView.php', - 'Symfony\\Component\\Form\\ChoiceList\\View\\ChoiceListView' => __DIR__ . '/..' . '/symfony/form/ChoiceList/View/ChoiceListView.php', - 'Symfony\\Component\\Form\\ChoiceList\\View\\ChoiceView' => __DIR__ . '/..' . '/symfony/form/ChoiceList/View/ChoiceView.php', - 'Symfony\\Component\\Form\\ClearableErrorsInterface' => __DIR__ . '/..' . '/symfony/form/ClearableErrorsInterface.php', - 'Symfony\\Component\\Form\\ClickableInterface' => __DIR__ . '/..' . '/symfony/form/ClickableInterface.php', - 'Symfony\\Component\\Form\\Command\\DebugCommand' => __DIR__ . '/..' . '/symfony/form/Command/DebugCommand.php', - 'Symfony\\Component\\Form\\Console\\Descriptor\\Descriptor' => __DIR__ . '/..' . '/symfony/form/Console/Descriptor/Descriptor.php', - 'Symfony\\Component\\Form\\Console\\Descriptor\\JsonDescriptor' => __DIR__ . '/..' . '/symfony/form/Console/Descriptor/JsonDescriptor.php', - 'Symfony\\Component\\Form\\Console\\Descriptor\\TextDescriptor' => __DIR__ . '/..' . '/symfony/form/Console/Descriptor/TextDescriptor.php', - 'Symfony\\Component\\Form\\Console\\Helper\\DescriptorHelper' => __DIR__ . '/..' . '/symfony/form/Console/Helper/DescriptorHelper.php', - 'Symfony\\Component\\Form\\DataAccessorInterface' => __DIR__ . '/..' . '/symfony/form/DataAccessorInterface.php', - 'Symfony\\Component\\Form\\DataMapperInterface' => __DIR__ . '/..' . '/symfony/form/DataMapperInterface.php', - 'Symfony\\Component\\Form\\DataTransformerInterface' => __DIR__ . '/..' . '/symfony/form/DataTransformerInterface.php', - 'Symfony\\Component\\Form\\DependencyInjection\\FormPass' => __DIR__ . '/..' . '/symfony/form/DependencyInjection/FormPass.php', - 'Symfony\\Component\\Form\\Event\\PostSetDataEvent' => __DIR__ . '/..' . '/symfony/form/Event/PostSetDataEvent.php', - 'Symfony\\Component\\Form\\Event\\PostSubmitEvent' => __DIR__ . '/..' . '/symfony/form/Event/PostSubmitEvent.php', - 'Symfony\\Component\\Form\\Event\\PreSetDataEvent' => __DIR__ . '/..' . '/symfony/form/Event/PreSetDataEvent.php', - 'Symfony\\Component\\Form\\Event\\PreSubmitEvent' => __DIR__ . '/..' . '/symfony/form/Event/PreSubmitEvent.php', - 'Symfony\\Component\\Form\\Event\\SubmitEvent' => __DIR__ . '/..' . '/symfony/form/Event/SubmitEvent.php', - 'Symfony\\Component\\Form\\Exception\\AccessException' => __DIR__ . '/..' . '/symfony/form/Exception/AccessException.php', - 'Symfony\\Component\\Form\\Exception\\AlreadySubmittedException' => __DIR__ . '/..' . '/symfony/form/Exception/AlreadySubmittedException.php', - 'Symfony\\Component\\Form\\Exception\\BadMethodCallException' => __DIR__ . '/..' . '/symfony/form/Exception/BadMethodCallException.php', - 'Symfony\\Component\\Form\\Exception\\ErrorMappingException' => __DIR__ . '/..' . '/symfony/form/Exception/ErrorMappingException.php', - 'Symfony\\Component\\Form\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/form/Exception/ExceptionInterface.php', - 'Symfony\\Component\\Form\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/form/Exception/InvalidArgumentException.php', - 'Symfony\\Component\\Form\\Exception\\InvalidConfigurationException' => __DIR__ . '/..' . '/symfony/form/Exception/InvalidConfigurationException.php', - 'Symfony\\Component\\Form\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/form/Exception/LogicException.php', - 'Symfony\\Component\\Form\\Exception\\OutOfBoundsException' => __DIR__ . '/..' . '/symfony/form/Exception/OutOfBoundsException.php', - 'Symfony\\Component\\Form\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/form/Exception/RuntimeException.php', - 'Symfony\\Component\\Form\\Exception\\StringCastException' => __DIR__ . '/..' . '/symfony/form/Exception/StringCastException.php', - 'Symfony\\Component\\Form\\Exception\\TransformationFailedException' => __DIR__ . '/..' . '/symfony/form/Exception/TransformationFailedException.php', - 'Symfony\\Component\\Form\\Exception\\UnexpectedTypeException' => __DIR__ . '/..' . '/symfony/form/Exception/UnexpectedTypeException.php', - 'Symfony\\Component\\Form\\Extension\\Core\\CoreExtension' => __DIR__ . '/..' . '/symfony/form/Extension/Core/CoreExtension.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataAccessor\\CallbackAccessor' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataAccessor/CallbackAccessor.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataAccessor\\ChainAccessor' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataAccessor/ChainAccessor.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataAccessor\\PropertyPathAccessor' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataAccessor/PropertyPathAccessor.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataMapper\\CheckboxListMapper' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataMapper/CheckboxListMapper.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataMapper\\DataMapper' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataMapper/DataMapper.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataMapper\\PropertyPathMapper' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataMapper/PropertyPathMapper.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataMapper\\RadioListMapper' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataMapper/RadioListMapper.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\ArrayToPartsTransformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/ArrayToPartsTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\BaseDateTimeTransformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/BaseDateTimeTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\BooleanToStringTransformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/BooleanToStringTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\ChoiceToValueTransformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\ChoicesToValuesTransformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\DataTransformerChain' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/DataTransformerChain.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\DateIntervalToArrayTransformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/DateIntervalToArrayTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\DateIntervalToStringTransformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/DateIntervalToStringTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\DateTimeImmutableToDateTimeTransformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/DateTimeImmutableToDateTimeTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\DateTimeToArrayTransformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\DateTimeToHtml5LocalDateTimeTransformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/DateTimeToHtml5LocalDateTimeTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\DateTimeToLocalizedStringTransformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\DateTimeToRfc3339Transformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\DateTimeToStringTransformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\DateTimeToTimestampTransformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\DateTimeZoneToStringTransformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/DateTimeZoneToStringTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\IntegerToLocalizedStringTransformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\IntlTimeZoneToStringTransformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/IntlTimeZoneToStringTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\MoneyToLocalizedStringTransformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\NumberToLocalizedStringTransformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\PercentToLocalizedStringTransformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\StringToFloatTransformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/StringToFloatTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\UlidToStringTransformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/UlidToStringTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\UuidToStringTransformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/UuidToStringTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\ValueToDuplicatesTransformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\WeekToArrayTransformer' => __DIR__ . '/..' . '/symfony/form/Extension/Core/DataTransformer/WeekToArrayTransformer.php', - 'Symfony\\Component\\Form\\Extension\\Core\\EventListener\\FixUrlProtocolListener' => __DIR__ . '/..' . '/symfony/form/Extension/Core/EventListener/FixUrlProtocolListener.php', - 'Symfony\\Component\\Form\\Extension\\Core\\EventListener\\MergeCollectionListener' => __DIR__ . '/..' . '/symfony/form/Extension/Core/EventListener/MergeCollectionListener.php', - 'Symfony\\Component\\Form\\Extension\\Core\\EventListener\\ResizeFormListener' => __DIR__ . '/..' . '/symfony/form/Extension/Core/EventListener/ResizeFormListener.php', - 'Symfony\\Component\\Form\\Extension\\Core\\EventListener\\TransformationFailureListener' => __DIR__ . '/..' . '/symfony/form/Extension/Core/EventListener/TransformationFailureListener.php', - 'Symfony\\Component\\Form\\Extension\\Core\\EventListener\\TrimListener' => __DIR__ . '/..' . '/symfony/form/Extension/Core/EventListener/TrimListener.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\BaseType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/BaseType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\BirthdayType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/BirthdayType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\ButtonType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/ButtonType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\CheckboxType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/CheckboxType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\ChoiceType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/ChoiceType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\CollectionType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/CollectionType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\ColorType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/ColorType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\CountryType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/CountryType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\CurrencyType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/CurrencyType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\DateIntervalType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/DateIntervalType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\DateTimeType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/DateTimeType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\DateType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/DateType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\EmailType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/EmailType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\EnumType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/EnumType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\FileType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/FileType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\FormType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/FormType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\HiddenType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/HiddenType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\IntegerType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/IntegerType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\LanguageType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/LanguageType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\LocaleType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/LocaleType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\MoneyType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/MoneyType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\NumberType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/NumberType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\PasswordType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/PasswordType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\PercentType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/PercentType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\RadioType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/RadioType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\RangeType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/RangeType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\RepeatedType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/RepeatedType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\ResetType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/ResetType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\SearchType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/SearchType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\SubmitType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/SubmitType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\TelType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/TelType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\TextType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/TextType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\TextareaType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/TextareaType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\TimeType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/TimeType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\TimezoneType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/TimezoneType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\TransformationFailureExtension' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/TransformationFailureExtension.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\UlidType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/UlidType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\UrlType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/UrlType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\UuidType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/UuidType.php', - 'Symfony\\Component\\Form\\Extension\\Core\\Type\\WeekType' => __DIR__ . '/..' . '/symfony/form/Extension/Core/Type/WeekType.php', - 'Symfony\\Component\\Form\\Extension\\Csrf\\CsrfExtension' => __DIR__ . '/..' . '/symfony/form/Extension/Csrf/CsrfExtension.php', - 'Symfony\\Component\\Form\\Extension\\Csrf\\EventListener\\CsrfValidationListener' => __DIR__ . '/..' . '/symfony/form/Extension/Csrf/EventListener/CsrfValidationListener.php', - 'Symfony\\Component\\Form\\Extension\\Csrf\\Type\\FormTypeCsrfExtension' => __DIR__ . '/..' . '/symfony/form/Extension/Csrf/Type/FormTypeCsrfExtension.php', - 'Symfony\\Component\\Form\\Extension\\DataCollector\\DataCollectorExtension' => __DIR__ . '/..' . '/symfony/form/Extension/DataCollector/DataCollectorExtension.php', - 'Symfony\\Component\\Form\\Extension\\DataCollector\\EventListener\\DataCollectorListener' => __DIR__ . '/..' . '/symfony/form/Extension/DataCollector/EventListener/DataCollectorListener.php', - 'Symfony\\Component\\Form\\Extension\\DataCollector\\FormDataCollector' => __DIR__ . '/..' . '/symfony/form/Extension/DataCollector/FormDataCollector.php', - 'Symfony\\Component\\Form\\Extension\\DataCollector\\FormDataCollectorInterface' => __DIR__ . '/..' . '/symfony/form/Extension/DataCollector/FormDataCollectorInterface.php', - 'Symfony\\Component\\Form\\Extension\\DataCollector\\FormDataExtractor' => __DIR__ . '/..' . '/symfony/form/Extension/DataCollector/FormDataExtractor.php', - 'Symfony\\Component\\Form\\Extension\\DataCollector\\FormDataExtractorInterface' => __DIR__ . '/..' . '/symfony/form/Extension/DataCollector/FormDataExtractorInterface.php', - 'Symfony\\Component\\Form\\Extension\\DataCollector\\Proxy\\ResolvedTypeDataCollectorProxy' => __DIR__ . '/..' . '/symfony/form/Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.php', - 'Symfony\\Component\\Form\\Extension\\DataCollector\\Proxy\\ResolvedTypeFactoryDataCollectorProxy' => __DIR__ . '/..' . '/symfony/form/Extension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.php', - 'Symfony\\Component\\Form\\Extension\\DataCollector\\Type\\DataCollectorTypeExtension' => __DIR__ . '/..' . '/symfony/form/Extension/DataCollector/Type/DataCollectorTypeExtension.php', - 'Symfony\\Component\\Form\\Extension\\DependencyInjection\\DependencyInjectionExtension' => __DIR__ . '/..' . '/symfony/form/Extension/DependencyInjection/DependencyInjectionExtension.php', - 'Symfony\\Component\\Form\\Extension\\HttpFoundation\\HttpFoundationExtension' => __DIR__ . '/..' . '/symfony/form/Extension/HttpFoundation/HttpFoundationExtension.php', - 'Symfony\\Component\\Form\\Extension\\HttpFoundation\\HttpFoundationRequestHandler' => __DIR__ . '/..' . '/symfony/form/Extension/HttpFoundation/HttpFoundationRequestHandler.php', - 'Symfony\\Component\\Form\\Extension\\HttpFoundation\\Type\\FormTypeHttpFoundationExtension' => __DIR__ . '/..' . '/symfony/form/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\Constraints\\Form' => __DIR__ . '/..' . '/symfony/form/Extension/Validator/Constraints/Form.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\Constraints\\FormValidator' => __DIR__ . '/..' . '/symfony/form/Extension/Validator/Constraints/FormValidator.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\EventListener\\ValidationListener' => __DIR__ . '/..' . '/symfony/form/Extension/Validator/EventListener/ValidationListener.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\Type\\BaseValidatorExtension' => __DIR__ . '/..' . '/symfony/form/Extension/Validator/Type/BaseValidatorExtension.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\Type\\FormTypeValidatorExtension' => __DIR__ . '/..' . '/symfony/form/Extension/Validator/Type/FormTypeValidatorExtension.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\Type\\RepeatedTypeValidatorExtension' => __DIR__ . '/..' . '/symfony/form/Extension/Validator/Type/RepeatedTypeValidatorExtension.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\Type\\SubmitTypeValidatorExtension' => __DIR__ . '/..' . '/symfony/form/Extension/Validator/Type/SubmitTypeValidatorExtension.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\Type\\UploadValidatorExtension' => __DIR__ . '/..' . '/symfony/form/Extension/Validator/Type/UploadValidatorExtension.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\Util\\ServerParams' => __DIR__ . '/..' . '/symfony/form/Extension/Validator/Util/ServerParams.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\ValidatorExtension' => __DIR__ . '/..' . '/symfony/form/Extension/Validator/ValidatorExtension.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\ValidatorTypeGuesser' => __DIR__ . '/..' . '/symfony/form/Extension/Validator/ValidatorTypeGuesser.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\ViolationMapper\\MappingRule' => __DIR__ . '/..' . '/symfony/form/Extension/Validator/ViolationMapper/MappingRule.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\ViolationMapper\\RelativePath' => __DIR__ . '/..' . '/symfony/form/Extension/Validator/ViolationMapper/RelativePath.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\ViolationMapper\\ViolationMapper' => __DIR__ . '/..' . '/symfony/form/Extension/Validator/ViolationMapper/ViolationMapper.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\ViolationMapper\\ViolationMapperInterface' => __DIR__ . '/..' . '/symfony/form/Extension/Validator/ViolationMapper/ViolationMapperInterface.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\ViolationMapper\\ViolationPath' => __DIR__ . '/..' . '/symfony/form/Extension/Validator/ViolationMapper/ViolationPath.php', - 'Symfony\\Component\\Form\\Extension\\Validator\\ViolationMapper\\ViolationPathIterator' => __DIR__ . '/..' . '/symfony/form/Extension/Validator/ViolationMapper/ViolationPathIterator.php', - 'Symfony\\Component\\Form\\FileUploadError' => __DIR__ . '/..' . '/symfony/form/FileUploadError.php', - 'Symfony\\Component\\Form\\Form' => __DIR__ . '/..' . '/symfony/form/Form.php', - 'Symfony\\Component\\Form\\FormBuilder' => __DIR__ . '/..' . '/symfony/form/FormBuilder.php', - 'Symfony\\Component\\Form\\FormBuilderInterface' => __DIR__ . '/..' . '/symfony/form/FormBuilderInterface.php', - 'Symfony\\Component\\Form\\FormConfigBuilder' => __DIR__ . '/..' . '/symfony/form/FormConfigBuilder.php', - 'Symfony\\Component\\Form\\FormConfigBuilderInterface' => __DIR__ . '/..' . '/symfony/form/FormConfigBuilderInterface.php', - 'Symfony\\Component\\Form\\FormConfigInterface' => __DIR__ . '/..' . '/symfony/form/FormConfigInterface.php', - 'Symfony\\Component\\Form\\FormError' => __DIR__ . '/..' . '/symfony/form/FormError.php', - 'Symfony\\Component\\Form\\FormErrorIterator' => __DIR__ . '/..' . '/symfony/form/FormErrorIterator.php', - 'Symfony\\Component\\Form\\FormEvent' => __DIR__ . '/..' . '/symfony/form/FormEvent.php', - 'Symfony\\Component\\Form\\FormEvents' => __DIR__ . '/..' . '/symfony/form/FormEvents.php', - 'Symfony\\Component\\Form\\FormExtensionInterface' => __DIR__ . '/..' . '/symfony/form/FormExtensionInterface.php', - 'Symfony\\Component\\Form\\FormFactory' => __DIR__ . '/..' . '/symfony/form/FormFactory.php', - 'Symfony\\Component\\Form\\FormFactoryBuilder' => __DIR__ . '/..' . '/symfony/form/FormFactoryBuilder.php', - 'Symfony\\Component\\Form\\FormFactoryBuilderInterface' => __DIR__ . '/..' . '/symfony/form/FormFactoryBuilderInterface.php', - 'Symfony\\Component\\Form\\FormFactoryInterface' => __DIR__ . '/..' . '/symfony/form/FormFactoryInterface.php', - 'Symfony\\Component\\Form\\FormInterface' => __DIR__ . '/..' . '/symfony/form/FormInterface.php', - 'Symfony\\Component\\Form\\FormRegistry' => __DIR__ . '/..' . '/symfony/form/FormRegistry.php', - 'Symfony\\Component\\Form\\FormRegistryInterface' => __DIR__ . '/..' . '/symfony/form/FormRegistryInterface.php', - 'Symfony\\Component\\Form\\FormRenderer' => __DIR__ . '/..' . '/symfony/form/FormRenderer.php', - 'Symfony\\Component\\Form\\FormRendererEngineInterface' => __DIR__ . '/..' . '/symfony/form/FormRendererEngineInterface.php', - 'Symfony\\Component\\Form\\FormRendererInterface' => __DIR__ . '/..' . '/symfony/form/FormRendererInterface.php', - 'Symfony\\Component\\Form\\FormTypeExtensionInterface' => __DIR__ . '/..' . '/symfony/form/FormTypeExtensionInterface.php', - 'Symfony\\Component\\Form\\FormTypeGuesserChain' => __DIR__ . '/..' . '/symfony/form/FormTypeGuesserChain.php', - 'Symfony\\Component\\Form\\FormTypeGuesserInterface' => __DIR__ . '/..' . '/symfony/form/FormTypeGuesserInterface.php', - 'Symfony\\Component\\Form\\FormTypeInterface' => __DIR__ . '/..' . '/symfony/form/FormTypeInterface.php', - 'Symfony\\Component\\Form\\FormView' => __DIR__ . '/..' . '/symfony/form/FormView.php', - 'Symfony\\Component\\Form\\Forms' => __DIR__ . '/..' . '/symfony/form/Forms.php', - 'Symfony\\Component\\Form\\Guess\\Guess' => __DIR__ . '/..' . '/symfony/form/Guess/Guess.php', - 'Symfony\\Component\\Form\\Guess\\TypeGuess' => __DIR__ . '/..' . '/symfony/form/Guess/TypeGuess.php', - 'Symfony\\Component\\Form\\Guess\\ValueGuess' => __DIR__ . '/..' . '/symfony/form/Guess/ValueGuess.php', - 'Symfony\\Component\\Form\\NativeRequestHandler' => __DIR__ . '/..' . '/symfony/form/NativeRequestHandler.php', - 'Symfony\\Component\\Form\\PreloadedExtension' => __DIR__ . '/..' . '/symfony/form/PreloadedExtension.php', - 'Symfony\\Component\\Form\\RequestHandlerInterface' => __DIR__ . '/..' . '/symfony/form/RequestHandlerInterface.php', - 'Symfony\\Component\\Form\\ResolvedFormType' => __DIR__ . '/..' . '/symfony/form/ResolvedFormType.php', - 'Symfony\\Component\\Form\\ResolvedFormTypeFactory' => __DIR__ . '/..' . '/symfony/form/ResolvedFormTypeFactory.php', - 'Symfony\\Component\\Form\\ResolvedFormTypeFactoryInterface' => __DIR__ . '/..' . '/symfony/form/ResolvedFormTypeFactoryInterface.php', - 'Symfony\\Component\\Form\\ResolvedFormTypeInterface' => __DIR__ . '/..' . '/symfony/form/ResolvedFormTypeInterface.php', - 'Symfony\\Component\\Form\\ReversedTransformer' => __DIR__ . '/..' . '/symfony/form/ReversedTransformer.php', - 'Symfony\\Component\\Form\\SubmitButton' => __DIR__ . '/..' . '/symfony/form/SubmitButton.php', - 'Symfony\\Component\\Form\\SubmitButtonBuilder' => __DIR__ . '/..' . '/symfony/form/SubmitButtonBuilder.php', - 'Symfony\\Component\\Form\\SubmitButtonTypeInterface' => __DIR__ . '/..' . '/symfony/form/SubmitButtonTypeInterface.php', - 'Symfony\\Component\\Form\\Test\\FormBuilderInterface' => __DIR__ . '/..' . '/symfony/form/Test/FormBuilderInterface.php', - 'Symfony\\Component\\Form\\Test\\FormIntegrationTestCase' => __DIR__ . '/..' . '/symfony/form/Test/FormIntegrationTestCase.php', - 'Symfony\\Component\\Form\\Test\\FormInterface' => __DIR__ . '/..' . '/symfony/form/Test/FormInterface.php', - 'Symfony\\Component\\Form\\Test\\FormPerformanceTestCase' => __DIR__ . '/..' . '/symfony/form/Test/FormPerformanceTestCase.php', - 'Symfony\\Component\\Form\\Test\\Traits\\ValidatorExtensionTrait' => __DIR__ . '/..' . '/symfony/form/Test/Traits/ValidatorExtensionTrait.php', - 'Symfony\\Component\\Form\\Test\\TypeTestCase' => __DIR__ . '/..' . '/symfony/form/Test/TypeTestCase.php', - 'Symfony\\Component\\Form\\Util\\FormUtil' => __DIR__ . '/..' . '/symfony/form/Util/FormUtil.php', - 'Symfony\\Component\\Form\\Util\\InheritDataAwareIterator' => __DIR__ . '/..' . '/symfony/form/Util/InheritDataAwareIterator.php', - 'Symfony\\Component\\Form\\Util\\OptionsResolverWrapper' => __DIR__ . '/..' . '/symfony/form/Util/OptionsResolverWrapper.php', - 'Symfony\\Component\\Form\\Util\\OrderedHashMap' => __DIR__ . '/..' . '/symfony/form/Util/OrderedHashMap.php', - 'Symfony\\Component\\Form\\Util\\OrderedHashMapIterator' => __DIR__ . '/..' . '/symfony/form/Util/OrderedHashMapIterator.php', - 'Symfony\\Component\\Form\\Util\\ServerParams' => __DIR__ . '/..' . '/symfony/form/Util/ServerParams.php', - 'Symfony\\Component\\Form\\Util\\StringUtil' => __DIR__ . '/..' . '/symfony/form/Util/StringUtil.php', - 'Symfony\\Component\\HttpFoundation\\AcceptHeader' => __DIR__ . '/..' . '/symfony/http-foundation/AcceptHeader.php', - 'Symfony\\Component\\HttpFoundation\\AcceptHeaderItem' => __DIR__ . '/..' . '/symfony/http-foundation/AcceptHeaderItem.php', - 'Symfony\\Component\\HttpFoundation\\BinaryFileResponse' => __DIR__ . '/..' . '/symfony/http-foundation/BinaryFileResponse.php', - 'Symfony\\Component\\HttpFoundation\\Cookie' => __DIR__ . '/..' . '/symfony/http-foundation/Cookie.php', - 'Symfony\\Component\\HttpFoundation\\Exception\\BadRequestException' => __DIR__ . '/..' . '/symfony/http-foundation/Exception/BadRequestException.php', - 'Symfony\\Component\\HttpFoundation\\Exception\\ConflictingHeadersException' => __DIR__ . '/..' . '/symfony/http-foundation/Exception/ConflictingHeadersException.php', - 'Symfony\\Component\\HttpFoundation\\Exception\\JsonException' => __DIR__ . '/..' . '/symfony/http-foundation/Exception/JsonException.php', - 'Symfony\\Component\\HttpFoundation\\Exception\\RequestExceptionInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Exception/RequestExceptionInterface.php', - 'Symfony\\Component\\HttpFoundation\\Exception\\SessionNotFoundException' => __DIR__ . '/..' . '/symfony/http-foundation/Exception/SessionNotFoundException.php', - 'Symfony\\Component\\HttpFoundation\\Exception\\SuspiciousOperationException' => __DIR__ . '/..' . '/symfony/http-foundation/Exception/SuspiciousOperationException.php', - 'Symfony\\Component\\HttpFoundation\\ExpressionRequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/ExpressionRequestMatcher.php', - 'Symfony\\Component\\HttpFoundation\\FileBag' => __DIR__ . '/..' . '/symfony/http-foundation/FileBag.php', - 'Symfony\\Component\\HttpFoundation\\File\\Exception\\AccessDeniedException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/AccessDeniedException.php', - 'Symfony\\Component\\HttpFoundation\\File\\Exception\\CannotWriteFileException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/CannotWriteFileException.php', - 'Symfony\\Component\\HttpFoundation\\File\\Exception\\ExtensionFileException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/ExtensionFileException.php', - 'Symfony\\Component\\HttpFoundation\\File\\Exception\\FileException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/FileException.php', - 'Symfony\\Component\\HttpFoundation\\File\\Exception\\FileNotFoundException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/FileNotFoundException.php', - 'Symfony\\Component\\HttpFoundation\\File\\Exception\\FormSizeFileException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/FormSizeFileException.php', - 'Symfony\\Component\\HttpFoundation\\File\\Exception\\IniSizeFileException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/IniSizeFileException.php', - 'Symfony\\Component\\HttpFoundation\\File\\Exception\\NoFileException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/NoFileException.php', - 'Symfony\\Component\\HttpFoundation\\File\\Exception\\NoTmpDirFileException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/NoTmpDirFileException.php', - 'Symfony\\Component\\HttpFoundation\\File\\Exception\\PartialFileException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/PartialFileException.php', - 'Symfony\\Component\\HttpFoundation\\File\\Exception\\UnexpectedTypeException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/UnexpectedTypeException.php', - 'Symfony\\Component\\HttpFoundation\\File\\Exception\\UploadException' => __DIR__ . '/..' . '/symfony/http-foundation/File/Exception/UploadException.php', - 'Symfony\\Component\\HttpFoundation\\File\\File' => __DIR__ . '/..' . '/symfony/http-foundation/File/File.php', - 'Symfony\\Component\\HttpFoundation\\File\\Stream' => __DIR__ . '/..' . '/symfony/http-foundation/File/Stream.php', - 'Symfony\\Component\\HttpFoundation\\File\\UploadedFile' => __DIR__ . '/..' . '/symfony/http-foundation/File/UploadedFile.php', - 'Symfony\\Component\\HttpFoundation\\HeaderBag' => __DIR__ . '/..' . '/symfony/http-foundation/HeaderBag.php', - 'Symfony\\Component\\HttpFoundation\\HeaderUtils' => __DIR__ . '/..' . '/symfony/http-foundation/HeaderUtils.php', - 'Symfony\\Component\\HttpFoundation\\InputBag' => __DIR__ . '/..' . '/symfony/http-foundation/InputBag.php', - 'Symfony\\Component\\HttpFoundation\\IpUtils' => __DIR__ . '/..' . '/symfony/http-foundation/IpUtils.php', - 'Symfony\\Component\\HttpFoundation\\JsonResponse' => __DIR__ . '/..' . '/symfony/http-foundation/JsonResponse.php', - 'Symfony\\Component\\HttpFoundation\\ParameterBag' => __DIR__ . '/..' . '/symfony/http-foundation/ParameterBag.php', - 'Symfony\\Component\\HttpFoundation\\RateLimiter\\AbstractRequestRateLimiter' => __DIR__ . '/..' . '/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php', - 'Symfony\\Component\\HttpFoundation\\RateLimiter\\RequestRateLimiterInterface' => __DIR__ . '/..' . '/symfony/http-foundation/RateLimiter/RequestRateLimiterInterface.php', - 'Symfony\\Component\\HttpFoundation\\RedirectResponse' => __DIR__ . '/..' . '/symfony/http-foundation/RedirectResponse.php', - 'Symfony\\Component\\HttpFoundation\\Request' => __DIR__ . '/..' . '/symfony/http-foundation/Request.php', - 'Symfony\\Component\\HttpFoundation\\RequestMatcher' => __DIR__ . '/..' . '/symfony/http-foundation/RequestMatcher.php', - 'Symfony\\Component\\HttpFoundation\\RequestMatcherInterface' => __DIR__ . '/..' . '/symfony/http-foundation/RequestMatcherInterface.php', - 'Symfony\\Component\\HttpFoundation\\RequestStack' => __DIR__ . '/..' . '/symfony/http-foundation/RequestStack.php', - 'Symfony\\Component\\HttpFoundation\\Response' => __DIR__ . '/..' . '/symfony/http-foundation/Response.php', - 'Symfony\\Component\\HttpFoundation\\ResponseHeaderBag' => __DIR__ . '/..' . '/symfony/http-foundation/ResponseHeaderBag.php', - 'Symfony\\Component\\HttpFoundation\\ServerBag' => __DIR__ . '/..' . '/symfony/http-foundation/ServerBag.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBag' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Attribute/AttributeBag.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBagInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Attribute\\NamespacedAttributeBag' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Attribute/NamespacedAttributeBag.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Flash\\AutoExpireFlashBag' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Flash\\FlashBag' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Flash/FlashBag.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Flash\\FlashBagInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Flash/FlashBagInterface.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Session' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Session.php', - 'Symfony\\Component\\HttpFoundation\\Session\\SessionBagInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Session/SessionBagInterface.php', - 'Symfony\\Component\\HttpFoundation\\Session\\SessionBagProxy' => __DIR__ . '/..' . '/symfony/http-foundation/Session/SessionBagProxy.php', - 'Symfony\\Component\\HttpFoundation\\Session\\SessionFactory' => __DIR__ . '/..' . '/symfony/http-foundation/Session/SessionFactory.php', - 'Symfony\\Component\\HttpFoundation\\Session\\SessionFactoryInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Session/SessionFactoryInterface.php', - 'Symfony\\Component\\HttpFoundation\\Session\\SessionInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Session/SessionInterface.php', - 'Symfony\\Component\\HttpFoundation\\Session\\SessionUtils' => __DIR__ . '/..' . '/symfony/http-foundation/Session/SessionUtils.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\AbstractSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\IdentityMarshaller' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/IdentityMarshaller.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MarshallingSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MemcachedSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MigratingSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\MongoDbSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NativeFileSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NullSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\PdoSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\RedisSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\SessionHandlerFactory' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\StrictSessionHandler' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\MetadataBag' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/MetadataBag.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\MockArraySessionStorage' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\MockFileSessionStorage' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\MockFileSessionStorageFactory' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorage' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/NativeSessionStorage.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorageFactory' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\PhpBridgeSessionStorage' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\PhpBridgeSessionStorageFactory' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\AbstractProxy' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\SessionHandlerProxy' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\ServiceSessionFactory' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/ServiceSessionFactory.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\SessionStorageFactoryInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/SessionStorageFactoryInterface.php', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\SessionStorageInterface' => __DIR__ . '/..' . '/symfony/http-foundation/Session/Storage/SessionStorageInterface.php', - 'Symfony\\Component\\HttpFoundation\\StreamedResponse' => __DIR__ . '/..' . '/symfony/http-foundation/StreamedResponse.php', - 'Symfony\\Component\\HttpFoundation\\UrlHelper' => __DIR__ . '/..' . '/symfony/http-foundation/UrlHelper.php', - 'Symfony\\Component\\HttpKernel\\Attribute\\ArgumentInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Attribute/ArgumentInterface.php', - 'Symfony\\Component\\HttpKernel\\Attribute\\AsController' => __DIR__ . '/..' . '/symfony/http-kernel/Attribute/AsController.php', - 'Symfony\\Component\\HttpKernel\\Bundle\\Bundle' => __DIR__ . '/..' . '/symfony/http-kernel/Bundle/Bundle.php', - 'Symfony\\Component\\HttpKernel\\Bundle\\BundleInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Bundle/BundleInterface.php', - 'Symfony\\Component\\HttpKernel\\CacheClearer\\CacheClearerInterface' => __DIR__ . '/..' . '/symfony/http-kernel/CacheClearer/CacheClearerInterface.php', - 'Symfony\\Component\\HttpKernel\\CacheClearer\\ChainCacheClearer' => __DIR__ . '/..' . '/symfony/http-kernel/CacheClearer/ChainCacheClearer.php', - 'Symfony\\Component\\HttpKernel\\CacheClearer\\Psr6CacheClearer' => __DIR__ . '/..' . '/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php', - 'Symfony\\Component\\HttpKernel\\CacheWarmer\\CacheWarmer' => __DIR__ . '/..' . '/symfony/http-kernel/CacheWarmer/CacheWarmer.php', - 'Symfony\\Component\\HttpKernel\\CacheWarmer\\CacheWarmerAggregate' => __DIR__ . '/..' . '/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php', - 'Symfony\\Component\\HttpKernel\\CacheWarmer\\CacheWarmerInterface' => __DIR__ . '/..' . '/symfony/http-kernel/CacheWarmer/CacheWarmerInterface.php', - 'Symfony\\Component\\HttpKernel\\CacheWarmer\\WarmableInterface' => __DIR__ . '/..' . '/symfony/http-kernel/CacheWarmer/WarmableInterface.php', - 'Symfony\\Component\\HttpKernel\\Config\\FileLocator' => __DIR__ . '/..' . '/symfony/http-kernel/Config/FileLocator.php', - 'Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadata' => __DIR__ . '/..' . '/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php', - 'Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadataFactory' => __DIR__ . '/..' . '/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php', - 'Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadataFactoryInterface' => __DIR__ . '/..' . '/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolverInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolverInterface.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\DefaultValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\NotTaggedControllerValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestAttributeValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\ServiceValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\SessionValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\TraceableValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\VariadicValueResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentValueResolverInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ContainerControllerResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ContainerControllerResolver.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ControllerReference' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ControllerReference.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ControllerResolver.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ControllerResolverInterface.php', - 'Symfony\\Component\\HttpKernel\\Controller\\ErrorController' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/ErrorController.php', - 'Symfony\\Component\\HttpKernel\\Controller\\TraceableArgumentResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/TraceableArgumentResolver.php', - 'Symfony\\Component\\HttpKernel\\Controller\\TraceableControllerResolver' => __DIR__ . '/..' . '/symfony/http-kernel/Controller/TraceableControllerResolver.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\AjaxDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/AjaxDataCollector.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\ConfigDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/ConfigDataCollector.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\DataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/DataCollector.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\DataCollectorInterface' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/DataCollectorInterface.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\DumpDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/DumpDataCollector.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\EventDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/EventDataCollector.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\ExceptionDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/ExceptionDataCollector.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\LateDataCollectorInterface' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/LateDataCollectorInterface.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\LoggerDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/LoggerDataCollector.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\MemoryDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/MemoryDataCollector.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\RequestDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/RequestDataCollector.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\RouterDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/RouterDataCollector.php', - 'Symfony\\Component\\HttpKernel\\DataCollector\\TimeDataCollector' => __DIR__ . '/..' . '/symfony/http-kernel/DataCollector/TimeDataCollector.php', - 'Symfony\\Component\\HttpKernel\\Debug\\FileLinkFormatter' => __DIR__ . '/..' . '/symfony/http-kernel/Debug/FileLinkFormatter.php', - 'Symfony\\Component\\HttpKernel\\Debug\\TraceableEventDispatcher' => __DIR__ . '/..' . '/symfony/http-kernel/Debug/TraceableEventDispatcher.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\AddAnnotatedClassesToCachePass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\ConfigurableExtension' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/ConfigurableExtension.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\ControllerArgumentValueResolverPass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\Extension' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/Extension.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\FragmentRendererPass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\LazyLoadingFragmentHandler' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\LoggerPass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/LoggerPass.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\MergeExtensionConfigurationPass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\RegisterControllerArgumentLocatorsPass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\RegisterLocaleAwareServicesPass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/RegisterLocaleAwareServicesPass.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\RemoveEmptyControllerArgumentLocatorsPass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\ResettableServicePass' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/ResettableServicePass.php', - 'Symfony\\Component\\HttpKernel\\DependencyInjection\\ServicesResetter' => __DIR__ . '/..' . '/symfony/http-kernel/DependencyInjection/ServicesResetter.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\AbstractSessionListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/AbstractSessionListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\AbstractTestSessionListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/AbstractTestSessionListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\AddRequestFormatsListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/AddRequestFormatsListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\DebugHandlersListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/DebugHandlersListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\DisallowRobotsIndexingListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/DisallowRobotsIndexingListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\DumpListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/DumpListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\ErrorListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/ErrorListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\FragmentListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/FragmentListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\LocaleAwareListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/LocaleAwareListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\LocaleListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/LocaleListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\ProfilerListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/ProfilerListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\ResponseListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/ResponseListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\RouterListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/RouterListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\SessionListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/SessionListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\StreamedResponseListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/StreamedResponseListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\SurrogateListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/SurrogateListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\TestSessionListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/TestSessionListener.php', - 'Symfony\\Component\\HttpKernel\\EventListener\\ValidateRequestListener' => __DIR__ . '/..' . '/symfony/http-kernel/EventListener/ValidateRequestListener.php', - 'Symfony\\Component\\HttpKernel\\Event\\ControllerArgumentsEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/ControllerArgumentsEvent.php', - 'Symfony\\Component\\HttpKernel\\Event\\ControllerEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/ControllerEvent.php', - 'Symfony\\Component\\HttpKernel\\Event\\ExceptionEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/ExceptionEvent.php', - 'Symfony\\Component\\HttpKernel\\Event\\FinishRequestEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/FinishRequestEvent.php', - 'Symfony\\Component\\HttpKernel\\Event\\KernelEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/KernelEvent.php', - 'Symfony\\Component\\HttpKernel\\Event\\RequestEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/RequestEvent.php', - 'Symfony\\Component\\HttpKernel\\Event\\ResponseEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/ResponseEvent.php', - 'Symfony\\Component\\HttpKernel\\Event\\TerminateEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/TerminateEvent.php', - 'Symfony\\Component\\HttpKernel\\Event\\ViewEvent' => __DIR__ . '/..' . '/symfony/http-kernel/Event/ViewEvent.php', - 'Symfony\\Component\\HttpKernel\\Exception\\AccessDeniedHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/AccessDeniedHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\BadRequestHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/BadRequestHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\ConflictHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/ConflictHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\ControllerDoesNotReturnResponseException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/ControllerDoesNotReturnResponseException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\GoneHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/GoneHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\HttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/HttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\HttpExceptionInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/HttpExceptionInterface.php', - 'Symfony\\Component\\HttpKernel\\Exception\\InvalidMetadataException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/InvalidMetadataException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\LengthRequiredHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/LengthRequiredHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\MethodNotAllowedHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\NotAcceptableHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/NotAcceptableHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/NotFoundHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\PreconditionFailedHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/PreconditionFailedHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\PreconditionRequiredHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\ServiceUnavailableHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\TooManyRequestsHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/TooManyRequestsHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/UnauthorizedHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\UnexpectedSessionUsageException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/UnexpectedSessionUsageException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\UnprocessableEntityHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php', - 'Symfony\\Component\\HttpKernel\\Exception\\UnsupportedMediaTypeHttpException' => __DIR__ . '/..' . '/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php', - 'Symfony\\Component\\HttpKernel\\Fragment\\AbstractSurrogateFragmentRenderer' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php', - 'Symfony\\Component\\HttpKernel\\Fragment\\EsiFragmentRenderer' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/EsiFragmentRenderer.php', - 'Symfony\\Component\\HttpKernel\\Fragment\\FragmentHandler' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/FragmentHandler.php', - 'Symfony\\Component\\HttpKernel\\Fragment\\FragmentRendererInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/FragmentRendererInterface.php', - 'Symfony\\Component\\HttpKernel\\Fragment\\FragmentUriGenerator' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/FragmentUriGenerator.php', - 'Symfony\\Component\\HttpKernel\\Fragment\\FragmentUriGeneratorInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/FragmentUriGeneratorInterface.php', - 'Symfony\\Component\\HttpKernel\\Fragment\\HIncludeFragmentRenderer' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php', - 'Symfony\\Component\\HttpKernel\\Fragment\\InlineFragmentRenderer' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/InlineFragmentRenderer.php', - 'Symfony\\Component\\HttpKernel\\Fragment\\RoutableFragmentRenderer' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php', - 'Symfony\\Component\\HttpKernel\\Fragment\\SsiFragmentRenderer' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/SsiFragmentRenderer.php', - 'Symfony\\Component\\HttpKernel\\HttpCache\\AbstractSurrogate' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/AbstractSurrogate.php', - 'Symfony\\Component\\HttpKernel\\HttpCache\\Esi' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/Esi.php', - 'Symfony\\Component\\HttpKernel\\HttpCache\\HttpCache' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/HttpCache.php', - 'Symfony\\Component\\HttpKernel\\HttpCache\\ResponseCacheStrategy' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php', - 'Symfony\\Component\\HttpKernel\\HttpCache\\ResponseCacheStrategyInterface' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/ResponseCacheStrategyInterface.php', - 'Symfony\\Component\\HttpKernel\\HttpCache\\Ssi' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/Ssi.php', - 'Symfony\\Component\\HttpKernel\\HttpCache\\Store' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/Store.php', - 'Symfony\\Component\\HttpKernel\\HttpCache\\StoreInterface' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/StoreInterface.php', - 'Symfony\\Component\\HttpKernel\\HttpCache\\SubRequestHandler' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/SubRequestHandler.php', - 'Symfony\\Component\\HttpKernel\\HttpCache\\SurrogateInterface' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/SurrogateInterface.php', - 'Symfony\\Component\\HttpKernel\\HttpClientKernel' => __DIR__ . '/..' . '/symfony/http-kernel/HttpClientKernel.php', - 'Symfony\\Component\\HttpKernel\\HttpKernel' => __DIR__ . '/..' . '/symfony/http-kernel/HttpKernel.php', - 'Symfony\\Component\\HttpKernel\\HttpKernelBrowser' => __DIR__ . '/..' . '/symfony/http-kernel/HttpKernelBrowser.php', - 'Symfony\\Component\\HttpKernel\\HttpKernelInterface' => __DIR__ . '/..' . '/symfony/http-kernel/HttpKernelInterface.php', - 'Symfony\\Component\\HttpKernel\\Kernel' => __DIR__ . '/..' . '/symfony/http-kernel/Kernel.php', - 'Symfony\\Component\\HttpKernel\\KernelEvents' => __DIR__ . '/..' . '/symfony/http-kernel/KernelEvents.php', - 'Symfony\\Component\\HttpKernel\\KernelInterface' => __DIR__ . '/..' . '/symfony/http-kernel/KernelInterface.php', - 'Symfony\\Component\\HttpKernel\\Log\\DebugLoggerInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Log/DebugLoggerInterface.php', - 'Symfony\\Component\\HttpKernel\\Log\\Logger' => __DIR__ . '/..' . '/symfony/http-kernel/Log/Logger.php', - 'Symfony\\Component\\HttpKernel\\Profiler\\FileProfilerStorage' => __DIR__ . '/..' . '/symfony/http-kernel/Profiler/FileProfilerStorage.php', - 'Symfony\\Component\\HttpKernel\\Profiler\\Profile' => __DIR__ . '/..' . '/symfony/http-kernel/Profiler/Profile.php', - 'Symfony\\Component\\HttpKernel\\Profiler\\Profiler' => __DIR__ . '/..' . '/symfony/http-kernel/Profiler/Profiler.php', - 'Symfony\\Component\\HttpKernel\\Profiler\\ProfilerStorageInterface' => __DIR__ . '/..' . '/symfony/http-kernel/Profiler/ProfilerStorageInterface.php', - 'Symfony\\Component\\HttpKernel\\RebootableInterface' => __DIR__ . '/..' . '/symfony/http-kernel/RebootableInterface.php', - 'Symfony\\Component\\HttpKernel\\TerminableInterface' => __DIR__ . '/..' . '/symfony/http-kernel/TerminableInterface.php', - 'Symfony\\Component\\HttpKernel\\UriSigner' => __DIR__ . '/..' . '/symfony/http-kernel/UriSigner.php', - 'Symfony\\Component\\OptionsResolver\\Debug\\OptionsResolverIntrospector' => __DIR__ . '/..' . '/symfony/options-resolver/Debug/OptionsResolverIntrospector.php', - 'Symfony\\Component\\OptionsResolver\\Exception\\AccessException' => __DIR__ . '/..' . '/symfony/options-resolver/Exception/AccessException.php', - 'Symfony\\Component\\OptionsResolver\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/options-resolver/Exception/ExceptionInterface.php', - 'Symfony\\Component\\OptionsResolver\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/options-resolver/Exception/InvalidArgumentException.php', - 'Symfony\\Component\\OptionsResolver\\Exception\\InvalidOptionsException' => __DIR__ . '/..' . '/symfony/options-resolver/Exception/InvalidOptionsException.php', - 'Symfony\\Component\\OptionsResolver\\Exception\\MissingOptionsException' => __DIR__ . '/..' . '/symfony/options-resolver/Exception/MissingOptionsException.php', - 'Symfony\\Component\\OptionsResolver\\Exception\\NoConfigurationException' => __DIR__ . '/..' . '/symfony/options-resolver/Exception/NoConfigurationException.php', - 'Symfony\\Component\\OptionsResolver\\Exception\\NoSuchOptionException' => __DIR__ . '/..' . '/symfony/options-resolver/Exception/NoSuchOptionException.php', - 'Symfony\\Component\\OptionsResolver\\Exception\\OptionDefinitionException' => __DIR__ . '/..' . '/symfony/options-resolver/Exception/OptionDefinitionException.php', - 'Symfony\\Component\\OptionsResolver\\Exception\\UndefinedOptionsException' => __DIR__ . '/..' . '/symfony/options-resolver/Exception/UndefinedOptionsException.php', - 'Symfony\\Component\\OptionsResolver\\OptionConfigurator' => __DIR__ . '/..' . '/symfony/options-resolver/OptionConfigurator.php', - 'Symfony\\Component\\OptionsResolver\\Options' => __DIR__ . '/..' . '/symfony/options-resolver/Options.php', - 'Symfony\\Component\\OptionsResolver\\OptionsResolver' => __DIR__ . '/..' . '/symfony/options-resolver/OptionsResolver.php', - 'Symfony\\Component\\PropertyAccess\\Exception\\AccessException' => __DIR__ . '/..' . '/symfony/property-access/Exception/AccessException.php', - 'Symfony\\Component\\PropertyAccess\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/property-access/Exception/ExceptionInterface.php', - 'Symfony\\Component\\PropertyAccess\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/property-access/Exception/InvalidArgumentException.php', - 'Symfony\\Component\\PropertyAccess\\Exception\\InvalidPropertyPathException' => __DIR__ . '/..' . '/symfony/property-access/Exception/InvalidPropertyPathException.php', - 'Symfony\\Component\\PropertyAccess\\Exception\\NoSuchIndexException' => __DIR__ . '/..' . '/symfony/property-access/Exception/NoSuchIndexException.php', - 'Symfony\\Component\\PropertyAccess\\Exception\\NoSuchPropertyException' => __DIR__ . '/..' . '/symfony/property-access/Exception/NoSuchPropertyException.php', - 'Symfony\\Component\\PropertyAccess\\Exception\\OutOfBoundsException' => __DIR__ . '/..' . '/symfony/property-access/Exception/OutOfBoundsException.php', - 'Symfony\\Component\\PropertyAccess\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/property-access/Exception/RuntimeException.php', - 'Symfony\\Component\\PropertyAccess\\Exception\\UnexpectedTypeException' => __DIR__ . '/..' . '/symfony/property-access/Exception/UnexpectedTypeException.php', - 'Symfony\\Component\\PropertyAccess\\Exception\\UninitializedPropertyException' => __DIR__ . '/..' . '/symfony/property-access/Exception/UninitializedPropertyException.php', - 'Symfony\\Component\\PropertyAccess\\PropertyAccess' => __DIR__ . '/..' . '/symfony/property-access/PropertyAccess.php', - 'Symfony\\Component\\PropertyAccess\\PropertyAccessor' => __DIR__ . '/..' . '/symfony/property-access/PropertyAccessor.php', - 'Symfony\\Component\\PropertyAccess\\PropertyAccessorBuilder' => __DIR__ . '/..' . '/symfony/property-access/PropertyAccessorBuilder.php', - 'Symfony\\Component\\PropertyAccess\\PropertyAccessorInterface' => __DIR__ . '/..' . '/symfony/property-access/PropertyAccessorInterface.php', - 'Symfony\\Component\\PropertyAccess\\PropertyPath' => __DIR__ . '/..' . '/symfony/property-access/PropertyPath.php', - 'Symfony\\Component\\PropertyAccess\\PropertyPathBuilder' => __DIR__ . '/..' . '/symfony/property-access/PropertyPathBuilder.php', - 'Symfony\\Component\\PropertyAccess\\PropertyPathInterface' => __DIR__ . '/..' . '/symfony/property-access/PropertyPathInterface.php', - 'Symfony\\Component\\PropertyAccess\\PropertyPathIterator' => __DIR__ . '/..' . '/symfony/property-access/PropertyPathIterator.php', - 'Symfony\\Component\\PropertyAccess\\PropertyPathIteratorInterface' => __DIR__ . '/..' . '/symfony/property-access/PropertyPathIteratorInterface.php', - 'Symfony\\Component\\PropertyInfo\\DependencyInjection\\PropertyInfoConstructorPass' => __DIR__ . '/..' . '/symfony/property-info/DependencyInjection/PropertyInfoConstructorPass.php', - 'Symfony\\Component\\PropertyInfo\\DependencyInjection\\PropertyInfoPass' => __DIR__ . '/..' . '/symfony/property-info/DependencyInjection/PropertyInfoPass.php', - 'Symfony\\Component\\PropertyInfo\\Extractor\\ConstructorArgumentTypeExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/Extractor/ConstructorArgumentTypeExtractorInterface.php', - 'Symfony\\Component\\PropertyInfo\\Extractor\\ConstructorExtractor' => __DIR__ . '/..' . '/symfony/property-info/Extractor/ConstructorExtractor.php', - 'Symfony\\Component\\PropertyInfo\\Extractor\\PhpDocExtractor' => __DIR__ . '/..' . '/symfony/property-info/Extractor/PhpDocExtractor.php', - 'Symfony\\Component\\PropertyInfo\\Extractor\\PhpStanExtractor' => __DIR__ . '/..' . '/symfony/property-info/Extractor/PhpStanExtractor.php', - 'Symfony\\Component\\PropertyInfo\\Extractor\\ReflectionExtractor' => __DIR__ . '/..' . '/symfony/property-info/Extractor/ReflectionExtractor.php', - 'Symfony\\Component\\PropertyInfo\\Extractor\\SerializerExtractor' => __DIR__ . '/..' . '/symfony/property-info/Extractor/SerializerExtractor.php', - 'Symfony\\Component\\PropertyInfo\\PhpStan\\NameScope' => __DIR__ . '/..' . '/symfony/property-info/PhpStan/NameScope.php', - 'Symfony\\Component\\PropertyInfo\\PhpStan\\NameScopeFactory' => __DIR__ . '/..' . '/symfony/property-info/PhpStan/NameScopeFactory.php', - 'Symfony\\Component\\PropertyInfo\\PropertyAccessExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyAccessExtractorInterface.php', - 'Symfony\\Component\\PropertyInfo\\PropertyDescriptionExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyDescriptionExtractorInterface.php', - 'Symfony\\Component\\PropertyInfo\\PropertyInfoCacheExtractor' => __DIR__ . '/..' . '/symfony/property-info/PropertyInfoCacheExtractor.php', - 'Symfony\\Component\\PropertyInfo\\PropertyInfoExtractor' => __DIR__ . '/..' . '/symfony/property-info/PropertyInfoExtractor.php', - 'Symfony\\Component\\PropertyInfo\\PropertyInfoExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyInfoExtractorInterface.php', - 'Symfony\\Component\\PropertyInfo\\PropertyInitializableExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyInitializableExtractorInterface.php', - 'Symfony\\Component\\PropertyInfo\\PropertyListExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyListExtractorInterface.php', - 'Symfony\\Component\\PropertyInfo\\PropertyReadInfo' => __DIR__ . '/..' . '/symfony/property-info/PropertyReadInfo.php', - 'Symfony\\Component\\PropertyInfo\\PropertyReadInfoExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyReadInfoExtractorInterface.php', - 'Symfony\\Component\\PropertyInfo\\PropertyTypeExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyTypeExtractorInterface.php', - 'Symfony\\Component\\PropertyInfo\\PropertyWriteInfo' => __DIR__ . '/..' . '/symfony/property-info/PropertyWriteInfo.php', - 'Symfony\\Component\\PropertyInfo\\PropertyWriteInfoExtractorInterface' => __DIR__ . '/..' . '/symfony/property-info/PropertyWriteInfoExtractorInterface.php', - 'Symfony\\Component\\PropertyInfo\\Type' => __DIR__ . '/..' . '/symfony/property-info/Type.php', - 'Symfony\\Component\\PropertyInfo\\Util\\PhpDocTypeHelper' => __DIR__ . '/..' . '/symfony/property-info/Util/PhpDocTypeHelper.php', - 'Symfony\\Component\\PropertyInfo\\Util\\PhpStanTypeHelper' => __DIR__ . '/..' . '/symfony/property-info/Util/PhpStanTypeHelper.php', - 'Symfony\\Component\\Routing\\Alias' => __DIR__ . '/..' . '/symfony/routing/Alias.php', - 'Symfony\\Component\\Routing\\Annotation\\Route' => __DIR__ . '/..' . '/symfony/routing/Annotation/Route.php', - 'Symfony\\Component\\Routing\\CompiledRoute' => __DIR__ . '/..' . '/symfony/routing/CompiledRoute.php', - 'Symfony\\Component\\Routing\\DependencyInjection\\RoutingResolverPass' => __DIR__ . '/..' . '/symfony/routing/DependencyInjection/RoutingResolverPass.php', - 'Symfony\\Component\\Routing\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/routing/Exception/ExceptionInterface.php', - 'Symfony\\Component\\Routing\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/routing/Exception/InvalidArgumentException.php', - 'Symfony\\Component\\Routing\\Exception\\InvalidParameterException' => __DIR__ . '/..' . '/symfony/routing/Exception/InvalidParameterException.php', - 'Symfony\\Component\\Routing\\Exception\\MethodNotAllowedException' => __DIR__ . '/..' . '/symfony/routing/Exception/MethodNotAllowedException.php', - 'Symfony\\Component\\Routing\\Exception\\MissingMandatoryParametersException' => __DIR__ . '/..' . '/symfony/routing/Exception/MissingMandatoryParametersException.php', - 'Symfony\\Component\\Routing\\Exception\\NoConfigurationException' => __DIR__ . '/..' . '/symfony/routing/Exception/NoConfigurationException.php', - 'Symfony\\Component\\Routing\\Exception\\ResourceNotFoundException' => __DIR__ . '/..' . '/symfony/routing/Exception/ResourceNotFoundException.php', - 'Symfony\\Component\\Routing\\Exception\\RouteCircularReferenceException' => __DIR__ . '/..' . '/symfony/routing/Exception/RouteCircularReferenceException.php', - 'Symfony\\Component\\Routing\\Exception\\RouteNotFoundException' => __DIR__ . '/..' . '/symfony/routing/Exception/RouteNotFoundException.php', - 'Symfony\\Component\\Routing\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/routing/Exception/RuntimeException.php', - 'Symfony\\Component\\Routing\\Generator\\CompiledUrlGenerator' => __DIR__ . '/..' . '/symfony/routing/Generator/CompiledUrlGenerator.php', - 'Symfony\\Component\\Routing\\Generator\\ConfigurableRequirementsInterface' => __DIR__ . '/..' . '/symfony/routing/Generator/ConfigurableRequirementsInterface.php', - 'Symfony\\Component\\Routing\\Generator\\Dumper\\CompiledUrlGeneratorDumper' => __DIR__ . '/..' . '/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php', - 'Symfony\\Component\\Routing\\Generator\\Dumper\\GeneratorDumper' => __DIR__ . '/..' . '/symfony/routing/Generator/Dumper/GeneratorDumper.php', - 'Symfony\\Component\\Routing\\Generator\\Dumper\\GeneratorDumperInterface' => __DIR__ . '/..' . '/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php', - 'Symfony\\Component\\Routing\\Generator\\UrlGenerator' => __DIR__ . '/..' . '/symfony/routing/Generator/UrlGenerator.php', - 'Symfony\\Component\\Routing\\Generator\\UrlGeneratorInterface' => __DIR__ . '/..' . '/symfony/routing/Generator/UrlGeneratorInterface.php', - 'Symfony\\Component\\Routing\\Loader\\AnnotationClassLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/AnnotationClassLoader.php', - 'Symfony\\Component\\Routing\\Loader\\AnnotationDirectoryLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/AnnotationDirectoryLoader.php', - 'Symfony\\Component\\Routing\\Loader\\AnnotationFileLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/AnnotationFileLoader.php', - 'Symfony\\Component\\Routing\\Loader\\ClosureLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/ClosureLoader.php', - 'Symfony\\Component\\Routing\\Loader\\Configurator\\AliasConfigurator' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/AliasConfigurator.php', - 'Symfony\\Component\\Routing\\Loader\\Configurator\\CollectionConfigurator' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/CollectionConfigurator.php', - 'Symfony\\Component\\Routing\\Loader\\Configurator\\ImportConfigurator' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/ImportConfigurator.php', - 'Symfony\\Component\\Routing\\Loader\\Configurator\\RouteConfigurator' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/RouteConfigurator.php', - 'Symfony\\Component\\Routing\\Loader\\Configurator\\RoutingConfigurator' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/RoutingConfigurator.php', - 'Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\AddTrait' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/Traits/AddTrait.php', - 'Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\HostTrait' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/Traits/HostTrait.php', - 'Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\LocalizedRouteTrait' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/Traits/LocalizedRouteTrait.php', - 'Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\PrefixTrait' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/Traits/PrefixTrait.php', - 'Symfony\\Component\\Routing\\Loader\\Configurator\\Traits\\RouteTrait' => __DIR__ . '/..' . '/symfony/routing/Loader/Configurator/Traits/RouteTrait.php', - 'Symfony\\Component\\Routing\\Loader\\ContainerLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/ContainerLoader.php', - 'Symfony\\Component\\Routing\\Loader\\DirectoryLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/DirectoryLoader.php', - 'Symfony\\Component\\Routing\\Loader\\GlobFileLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/GlobFileLoader.php', - 'Symfony\\Component\\Routing\\Loader\\ObjectLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/ObjectLoader.php', - 'Symfony\\Component\\Routing\\Loader\\PhpFileLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/PhpFileLoader.php', - 'Symfony\\Component\\Routing\\Loader\\XmlFileLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/XmlFileLoader.php', - 'Symfony\\Component\\Routing\\Loader\\YamlFileLoader' => __DIR__ . '/..' . '/symfony/routing/Loader/YamlFileLoader.php', - 'Symfony\\Component\\Routing\\Matcher\\CompiledUrlMatcher' => __DIR__ . '/..' . '/symfony/routing/Matcher/CompiledUrlMatcher.php', - 'Symfony\\Component\\Routing\\Matcher\\Dumper\\CompiledUrlMatcherDumper' => __DIR__ . '/..' . '/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php', - 'Symfony\\Component\\Routing\\Matcher\\Dumper\\CompiledUrlMatcherTrait' => __DIR__ . '/..' . '/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php', - 'Symfony\\Component\\Routing\\Matcher\\Dumper\\MatcherDumper' => __DIR__ . '/..' . '/symfony/routing/Matcher/Dumper/MatcherDumper.php', - 'Symfony\\Component\\Routing\\Matcher\\Dumper\\MatcherDumperInterface' => __DIR__ . '/..' . '/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php', - 'Symfony\\Component\\Routing\\Matcher\\Dumper\\StaticPrefixCollection' => __DIR__ . '/..' . '/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php', - 'Symfony\\Component\\Routing\\Matcher\\ExpressionLanguageProvider' => __DIR__ . '/..' . '/symfony/routing/Matcher/ExpressionLanguageProvider.php', - 'Symfony\\Component\\Routing\\Matcher\\RedirectableUrlMatcher' => __DIR__ . '/..' . '/symfony/routing/Matcher/RedirectableUrlMatcher.php', - 'Symfony\\Component\\Routing\\Matcher\\RedirectableUrlMatcherInterface' => __DIR__ . '/..' . '/symfony/routing/Matcher/RedirectableUrlMatcherInterface.php', - 'Symfony\\Component\\Routing\\Matcher\\RequestMatcherInterface' => __DIR__ . '/..' . '/symfony/routing/Matcher/RequestMatcherInterface.php', - 'Symfony\\Component\\Routing\\Matcher\\TraceableUrlMatcher' => __DIR__ . '/..' . '/symfony/routing/Matcher/TraceableUrlMatcher.php', - 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher' => __DIR__ . '/..' . '/symfony/routing/Matcher/UrlMatcher.php', - 'Symfony\\Component\\Routing\\Matcher\\UrlMatcherInterface' => __DIR__ . '/..' . '/symfony/routing/Matcher/UrlMatcherInterface.php', - 'Symfony\\Component\\Routing\\RequestContext' => __DIR__ . '/..' . '/symfony/routing/RequestContext.php', - 'Symfony\\Component\\Routing\\RequestContextAwareInterface' => __DIR__ . '/..' . '/symfony/routing/RequestContextAwareInterface.php', - 'Symfony\\Component\\Routing\\Route' => __DIR__ . '/..' . '/symfony/routing/Route.php', - 'Symfony\\Component\\Routing\\RouteCollection' => __DIR__ . '/..' . '/symfony/routing/RouteCollection.php', - 'Symfony\\Component\\Routing\\RouteCollectionBuilder' => __DIR__ . '/..' . '/symfony/routing/RouteCollectionBuilder.php', - 'Symfony\\Component\\Routing\\RouteCompiler' => __DIR__ . '/..' . '/symfony/routing/RouteCompiler.php', - 'Symfony\\Component\\Routing\\RouteCompilerInterface' => __DIR__ . '/..' . '/symfony/routing/RouteCompilerInterface.php', - 'Symfony\\Component\\Routing\\Router' => __DIR__ . '/..' . '/symfony/routing/Router.php', - 'Symfony\\Component\\Routing\\RouterInterface' => __DIR__ . '/..' . '/symfony/routing/RouterInterface.php', - 'Symfony\\Component\\Stopwatch\\Section' => __DIR__ . '/..' . '/symfony/stopwatch/Section.php', - 'Symfony\\Component\\Stopwatch\\Stopwatch' => __DIR__ . '/..' . '/symfony/stopwatch/Stopwatch.php', - 'Symfony\\Component\\Stopwatch\\StopwatchEvent' => __DIR__ . '/..' . '/symfony/stopwatch/StopwatchEvent.php', - 'Symfony\\Component\\Stopwatch\\StopwatchPeriod' => __DIR__ . '/..' . '/symfony/stopwatch/StopwatchPeriod.php', - 'Symfony\\Component\\String\\AbstractString' => __DIR__ . '/..' . '/symfony/string/AbstractString.php', - 'Symfony\\Component\\String\\AbstractUnicodeString' => __DIR__ . '/..' . '/symfony/string/AbstractUnicodeString.php', - 'Symfony\\Component\\String\\ByteString' => __DIR__ . '/..' . '/symfony/string/ByteString.php', - 'Symfony\\Component\\String\\CodePointString' => __DIR__ . '/..' . '/symfony/string/CodePointString.php', - 'Symfony\\Component\\String\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/string/Exception/ExceptionInterface.php', - 'Symfony\\Component\\String\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/string/Exception/InvalidArgumentException.php', - 'Symfony\\Component\\String\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/string/Exception/RuntimeException.php', - 'Symfony\\Component\\String\\Inflector\\EnglishInflector' => __DIR__ . '/..' . '/symfony/string/Inflector/EnglishInflector.php', - 'Symfony\\Component\\String\\Inflector\\FrenchInflector' => __DIR__ . '/..' . '/symfony/string/Inflector/FrenchInflector.php', - 'Symfony\\Component\\String\\Inflector\\InflectorInterface' => __DIR__ . '/..' . '/symfony/string/Inflector/InflectorInterface.php', - 'Symfony\\Component\\String\\LazyString' => __DIR__ . '/..' . '/symfony/string/LazyString.php', - 'Symfony\\Component\\String\\Slugger\\AsciiSlugger' => __DIR__ . '/..' . '/symfony/string/Slugger/AsciiSlugger.php', - 'Symfony\\Component\\String\\Slugger\\SluggerInterface' => __DIR__ . '/..' . '/symfony/string/Slugger/SluggerInterface.php', - 'Symfony\\Component\\String\\UnicodeString' => __DIR__ . '/..' . '/symfony/string/UnicodeString.php', - 'Symfony\\Component\\VarDumper\\Caster\\AmqpCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/AmqpCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\ArgsStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ArgsStub.php', - 'Symfony\\Component\\VarDumper\\Caster\\Caster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/Caster.php', - 'Symfony\\Component\\VarDumper\\Caster\\ClassStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ClassStub.php', - 'Symfony\\Component\\VarDumper\\Caster\\ConstStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ConstStub.php', - 'Symfony\\Component\\VarDumper\\Caster\\CutArrayStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/CutArrayStub.php', - 'Symfony\\Component\\VarDumper\\Caster\\CutStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/CutStub.php', - 'Symfony\\Component\\VarDumper\\Caster\\DOMCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/DOMCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\DateCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/DateCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\DoctrineCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/DoctrineCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\DsCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/DsCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\DsPairStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/DsPairStub.php', - 'Symfony\\Component\\VarDumper\\Caster\\EnumStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/EnumStub.php', - 'Symfony\\Component\\VarDumper\\Caster\\ExceptionCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ExceptionCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\FiberCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/FiberCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\FrameStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/FrameStub.php', - 'Symfony\\Component\\VarDumper\\Caster\\GmpCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/GmpCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\ImagineCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ImagineCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\ImgStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ImgStub.php', - 'Symfony\\Component\\VarDumper\\Caster\\IntlCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/IntlCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\LinkStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/LinkStub.php', - 'Symfony\\Component\\VarDumper\\Caster\\MemcachedCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/MemcachedCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\MysqliCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/MysqliCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\PdoCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/PdoCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\PgSqlCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/PgSqlCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\ProxyManagerCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ProxyManagerCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\RdKafkaCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/RdKafkaCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\RedisCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/RedisCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\ReflectionCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ReflectionCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\ResourceCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/ResourceCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\SplCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/SplCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\StubCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/StubCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\SymfonyCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/SymfonyCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\TraceStub' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/TraceStub.php', - 'Symfony\\Component\\VarDumper\\Caster\\UuidCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/UuidCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\XmlReaderCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/XmlReaderCaster.php', - 'Symfony\\Component\\VarDumper\\Caster\\XmlResourceCaster' => __DIR__ . '/..' . '/symfony/var-dumper/Caster/XmlResourceCaster.php', - 'Symfony\\Component\\VarDumper\\Cloner\\AbstractCloner' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/AbstractCloner.php', - 'Symfony\\Component\\VarDumper\\Cloner\\ClonerInterface' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/ClonerInterface.php', - 'Symfony\\Component\\VarDumper\\Cloner\\Cursor' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Cursor.php', - 'Symfony\\Component\\VarDumper\\Cloner\\Data' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Data.php', - 'Symfony\\Component\\VarDumper\\Cloner\\DumperInterface' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/DumperInterface.php', - 'Symfony\\Component\\VarDumper\\Cloner\\Stub' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Stub.php', - 'Symfony\\Component\\VarDumper\\Cloner\\VarCloner' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/VarCloner.php', - 'Symfony\\Component\\VarDumper\\Command\\Descriptor\\CliDescriptor' => __DIR__ . '/..' . '/symfony/var-dumper/Command/Descriptor/CliDescriptor.php', - 'Symfony\\Component\\VarDumper\\Command\\Descriptor\\DumpDescriptorInterface' => __DIR__ . '/..' . '/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php', - 'Symfony\\Component\\VarDumper\\Command\\Descriptor\\HtmlDescriptor' => __DIR__ . '/..' . '/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php', - 'Symfony\\Component\\VarDumper\\Command\\ServerDumpCommand' => __DIR__ . '/..' . '/symfony/var-dumper/Command/ServerDumpCommand.php', - 'Symfony\\Component\\VarDumper\\Dumper\\AbstractDumper' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/AbstractDumper.php', - 'Symfony\\Component\\VarDumper\\Dumper\\CliDumper' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/CliDumper.php', - 'Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\CliContextProvider' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php', - 'Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\ContextProviderInterface' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php', - 'Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\RequestContextProvider' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php', - 'Symfony\\Component\\VarDumper\\Dumper\\ContextProvider\\SourceContextProvider' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php', - 'Symfony\\Component\\VarDumper\\Dumper\\ContextualizedDumper' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/ContextualizedDumper.php', - 'Symfony\\Component\\VarDumper\\Dumper\\DataDumperInterface' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/DataDumperInterface.php', - 'Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/HtmlDumper.php', - 'Symfony\\Component\\VarDumper\\Dumper\\ServerDumper' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/ServerDumper.php', - 'Symfony\\Component\\VarDumper\\Exception\\ThrowingCasterException' => __DIR__ . '/..' . '/symfony/var-dumper/Exception/ThrowingCasterException.php', - 'Symfony\\Component\\VarDumper\\Server\\Connection' => __DIR__ . '/..' . '/symfony/var-dumper/Server/Connection.php', - 'Symfony\\Component\\VarDumper\\Server\\DumpServer' => __DIR__ . '/..' . '/symfony/var-dumper/Server/DumpServer.php', - 'Symfony\\Component\\VarDumper\\VarDumper' => __DIR__ . '/..' . '/symfony/var-dumper/VarDumper.php', - 'Symfony\\Component\\VarExporter\\Exception\\ClassNotFoundException' => __DIR__ . '/..' . '/symfony/var-exporter/Exception/ClassNotFoundException.php', - 'Symfony\\Component\\VarExporter\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/var-exporter/Exception/ExceptionInterface.php', - 'Symfony\\Component\\VarExporter\\Exception\\NotInstantiableTypeException' => __DIR__ . '/..' . '/symfony/var-exporter/Exception/NotInstantiableTypeException.php', - 'Symfony\\Component\\VarExporter\\Instantiator' => __DIR__ . '/..' . '/symfony/var-exporter/Instantiator.php', - 'Symfony\\Component\\VarExporter\\Internal\\Exporter' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/Exporter.php', - 'Symfony\\Component\\VarExporter\\Internal\\Hydrator' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/Hydrator.php', - 'Symfony\\Component\\VarExporter\\Internal\\Reference' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/Reference.php', - 'Symfony\\Component\\VarExporter\\Internal\\Registry' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/Registry.php', - 'Symfony\\Component\\VarExporter\\Internal\\Values' => __DIR__ . '/..' . '/symfony/var-exporter/Internal/Values.php', - 'Symfony\\Component\\VarExporter\\VarExporter' => __DIR__ . '/..' . '/symfony/var-exporter/VarExporter.php', - 'Symfony\\Component\\Yaml\\Command\\LintCommand' => __DIR__ . '/..' . '/symfony/yaml/Command/LintCommand.php', - 'Symfony\\Component\\Yaml\\Dumper' => __DIR__ . '/..' . '/symfony/yaml/Dumper.php', - 'Symfony\\Component\\Yaml\\Escaper' => __DIR__ . '/..' . '/symfony/yaml/Escaper.php', - 'Symfony\\Component\\Yaml\\Exception\\DumpException' => __DIR__ . '/..' . '/symfony/yaml/Exception/DumpException.php', - 'Symfony\\Component\\Yaml\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/yaml/Exception/ExceptionInterface.php', - 'Symfony\\Component\\Yaml\\Exception\\ParseException' => __DIR__ . '/..' . '/symfony/yaml/Exception/ParseException.php', - 'Symfony\\Component\\Yaml\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/yaml/Exception/RuntimeException.php', - 'Symfony\\Component\\Yaml\\Inline' => __DIR__ . '/..' . '/symfony/yaml/Inline.php', - 'Symfony\\Component\\Yaml\\Parser' => __DIR__ . '/..' . '/symfony/yaml/Parser.php', - 'Symfony\\Component\\Yaml\\Tag\\TaggedValue' => __DIR__ . '/..' . '/symfony/yaml/Tag/TaggedValue.php', - 'Symfony\\Component\\Yaml\\Unescaper' => __DIR__ . '/..' . '/symfony/yaml/Unescaper.php', - 'Symfony\\Component\\Yaml\\Yaml' => __DIR__ . '/..' . '/symfony/yaml/Yaml.php', - 'Symfony\\Contracts\\Cache\\CacheInterface' => __DIR__ . '/..' . '/symfony/cache-contracts/CacheInterface.php', - 'Symfony\\Contracts\\Cache\\CacheTrait' => __DIR__ . '/..' . '/symfony/cache-contracts/CacheTrait.php', - 'Symfony\\Contracts\\Cache\\CallbackInterface' => __DIR__ . '/..' . '/symfony/cache-contracts/CallbackInterface.php', - 'Symfony\\Contracts\\Cache\\ItemInterface' => __DIR__ . '/..' . '/symfony/cache-contracts/ItemInterface.php', - 'Symfony\\Contracts\\Cache\\TagAwareCacheInterface' => __DIR__ . '/..' . '/symfony/cache-contracts/TagAwareCacheInterface.php', - 'Symfony\\Contracts\\EventDispatcher\\Event' => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts/Event.php', - 'Symfony\\Contracts\\EventDispatcher\\EventDispatcherInterface' => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts/EventDispatcherInterface.php', - 'Symfony\\Contracts\\Service\\Attribute\\Required' => __DIR__ . '/..' . '/symfony/service-contracts/Attribute/Required.php', - 'Symfony\\Contracts\\Service\\Attribute\\SubscribedService' => __DIR__ . '/..' . '/symfony/service-contracts/Attribute/SubscribedService.php', - 'Symfony\\Contracts\\Service\\ResetInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ResetInterface.php', - 'Symfony\\Contracts\\Service\\ServiceLocatorTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceLocatorTrait.php', - 'Symfony\\Contracts\\Service\\ServiceProviderInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceProviderInterface.php', - 'Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceSubscriberInterface.php', - 'Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceSubscriberTrait.php', - 'Symfony\\Contracts\\Translation\\LocaleAwareInterface' => __DIR__ . '/..' . '/symfony/translation-contracts/LocaleAwareInterface.php', - 'Symfony\\Contracts\\Translation\\TranslatableInterface' => __DIR__ . '/..' . '/symfony/translation-contracts/TranslatableInterface.php', - 'Symfony\\Contracts\\Translation\\TranslatorInterface' => __DIR__ . '/..' . '/symfony/translation-contracts/TranslatorInterface.php', - 'Symfony\\Contracts\\Translation\\TranslatorTrait' => __DIR__ . '/..' . '/symfony/translation-contracts/TranslatorTrait.php', - 'Symfony\\Polyfill\\Ctype\\Ctype' => __DIR__ . '/..' . '/symfony/polyfill-ctype/Ctype.php', - 'Symfony\\Polyfill\\Intl\\Grapheme\\Grapheme' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/Grapheme.php', - 'Symfony\\Polyfill\\Intl\\Icu\\Collator' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/Collator.php', - 'Symfony\\Polyfill\\Intl\\Icu\\Currencies' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/Currencies.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\AmPmTransformer' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/DateFormat/AmPmTransformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\DayOfWeekTransformer' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/DateFormat/DayOfWeekTransformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\DayOfYearTransformer' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/DateFormat/DayOfYearTransformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\DayTransformer' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/DateFormat/DayTransformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\FullTransformer' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/DateFormat/FullTransformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\Hour1200Transformer' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/DateFormat/Hour1200Transformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\Hour1201Transformer' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/DateFormat/Hour1201Transformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\Hour2400Transformer' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/DateFormat/Hour2400Transformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\Hour2401Transformer' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/DateFormat/Hour2401Transformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\HourTransformer' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/DateFormat/HourTransformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\MinuteTransformer' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/DateFormat/MinuteTransformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\MonthTransformer' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/DateFormat/MonthTransformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\QuarterTransformer' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/DateFormat/QuarterTransformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\SecondTransformer' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/DateFormat/SecondTransformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\TimezoneTransformer' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/DateFormat/TimezoneTransformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\Transformer' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/DateFormat/Transformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\DateFormat\\YearTransformer' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/DateFormat/YearTransformer.php', - 'Symfony\\Polyfill\\Intl\\Icu\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/Exception/ExceptionInterface.php', - 'Symfony\\Polyfill\\Intl\\Icu\\Exception\\MethodArgumentNotImplementedException' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/Exception/MethodArgumentNotImplementedException.php', - 'Symfony\\Polyfill\\Intl\\Icu\\Exception\\MethodArgumentValueNotImplementedException' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/Exception/MethodArgumentValueNotImplementedException.php', - 'Symfony\\Polyfill\\Intl\\Icu\\Exception\\MethodNotImplementedException' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/Exception/MethodNotImplementedException.php', - 'Symfony\\Polyfill\\Intl\\Icu\\Exception\\NotImplementedException' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/Exception/NotImplementedException.php', - 'Symfony\\Polyfill\\Intl\\Icu\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/Exception/RuntimeException.php', - 'Symfony\\Polyfill\\Intl\\Icu\\Icu' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/Icu.php', - 'Symfony\\Polyfill\\Intl\\Icu\\IntlDateFormatter' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/IntlDateFormatter.php', - 'Symfony\\Polyfill\\Intl\\Icu\\Locale' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/Locale.php', - 'Symfony\\Polyfill\\Intl\\Icu\\NumberFormatter' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/NumberFormatter.php', - 'Symfony\\Polyfill\\Intl\\Idn\\Idn' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/Idn.php', - 'Symfony\\Polyfill\\Intl\\Idn\\Info' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/Info.php', - 'Symfony\\Polyfill\\Intl\\Idn\\Resources\\unidata\\DisallowedRanges' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/Resources/unidata/DisallowedRanges.php', - 'Symfony\\Polyfill\\Intl\\Idn\\Resources\\unidata\\Regex' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/Resources/unidata/Regex.php', - 'Symfony\\Polyfill\\Intl\\Normalizer\\Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Normalizer.php', - 'Symfony\\Polyfill\\Mbstring\\Mbstring' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/Mbstring.php', - 'Symfony\\Polyfill\\Php72\\Php72' => __DIR__ . '/..' . '/symfony/polyfill-php72/Php72.php', - 'Symfony\\Polyfill\\Php73\\Php73' => __DIR__ . '/..' . '/symfony/polyfill-php73/Php73.php', - 'Symfony\\Polyfill\\Php80\\Php80' => __DIR__ . '/..' . '/symfony/polyfill-php80/Php80.php', - 'Symfony\\Polyfill\\Php80\\PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/PhpToken.php', - 'Symfony\\Polyfill\\Php81\\Php81' => __DIR__ . '/..' . '/symfony/polyfill-php81/Php81.php', - 'SynchroExceptionNotStarted' => __DIR__ . '/../..' . '/application/exceptions/SynchroExceptionNotStarted.php', - 'System' => __DIR__ . '/..' . '/pear/pear-core-minimal/src/System.php', - 'TCPDF' => __DIR__ . '/..' . '/combodo/tcpdf/tcpdf.php', - 'TCPDF2DBarcode' => __DIR__ . '/..' . '/combodo/tcpdf/tcpdf_barcodes_2d.php', - 'TCPDFBarcode' => __DIR__ . '/..' . '/combodo/tcpdf/tcpdf_barcodes_1d.php', - 'TCPDF_COLORS' => __DIR__ . '/..' . '/combodo/tcpdf/include/tcpdf_colors.php', - 'TCPDF_FILTERS' => __DIR__ . '/..' . '/combodo/tcpdf/include/tcpdf_filters.php', - 'TCPDF_FONTS' => __DIR__ . '/..' . '/combodo/tcpdf/include/tcpdf_fonts.php', - 'TCPDF_FONT_DATA' => __DIR__ . '/..' . '/combodo/tcpdf/include/tcpdf_font_data.php', - 'TCPDF_IMAGES' => __DIR__ . '/..' . '/combodo/tcpdf/include/tcpdf_images.php', - 'TCPDF_IMPORT' => __DIR__ . '/..' . '/combodo/tcpdf/tcpdf_import.php', - 'TCPDF_PARSER' => __DIR__ . '/..' . '/combodo/tcpdf/tcpdf_parser.php', - 'TCPDF_STATIC' => __DIR__ . '/..' . '/combodo/tcpdf/include/tcpdf_static.php', - 'TabManager' => __DIR__ . '/../..' . '/sources/Application/WebPage/TabManager.php', - 'TabularBulkExport' => __DIR__ . '/../..' . '/core/tabularbulkexport.class.inc.php', - 'TagSetFieldData' => __DIR__ . '/../..' . '/core/tagsetfield.class.inc.php', - 'TemplateMenuNode' => __DIR__ . '/../..' . '/application/menunode.class.inc.php', - 'TemplateString' => __DIR__ . '/../..' . '/core/templatestring.class.inc.php', - 'TemplateStringPlaceholder' => __DIR__ . '/../..' . '/core/templatestring.class.inc.php', - 'TemporaryObjectDescriptor' => __DIR__ . '/../..' . '/core/TemporaryObjectDescriptor.php', - 'TheNetworg\\OAuth2\\Client\\Grant\\JwtBearer' => __DIR__ . '/..' . '/thenetworg/oauth2-azure/src/Grant/JwtBearer.php', - 'TheNetworg\\OAuth2\\Client\\Provider\\Azure' => __DIR__ . '/..' . '/thenetworg/oauth2-azure/src/Provider/Azure.php', - 'TheNetworg\\OAuth2\\Client\\Provider\\AzureResourceOwner' => __DIR__ . '/..' . '/thenetworg/oauth2-azure/src/Provider/AzureResourceOwner.php', - 'TheNetworg\\OAuth2\\Client\\Token\\AccessToken' => __DIR__ . '/..' . '/thenetworg/oauth2-azure/src/Token/AccessToken.php', - 'ThemeHandler' => __DIR__ . '/../..' . '/application/themehandler.class.inc.php', - 'ThemeHandlerService' => __DIR__ . '/../..' . '/application/themehandlerservice.class.inc.php', - 'ToolsLog' => __DIR__ . '/../..' . '/core/log.class.inc.php', - 'Trigger' => __DIR__ . '/../..' . '/core/trigger.class.inc.php', - 'TriggerOnAttributeBlobDownload' => __DIR__ . '/../..' . '/core/trigger.class.inc.php', - 'TriggerOnObject' => __DIR__ . '/../..' . '/core/trigger.class.inc.php', - 'TriggerOnObjectCreate' => __DIR__ . '/../..' . '/core/trigger.class.inc.php', - 'TriggerOnObjectDelete' => __DIR__ . '/../..' . '/core/trigger.class.inc.php', - 'TriggerOnObjectMention' => __DIR__ . '/../..' . '/core/trigger.class.inc.php', - 'TriggerOnObjectUpdate' => __DIR__ . '/../..' . '/core/trigger.class.inc.php', - 'TriggerOnPortalUpdate' => __DIR__ . '/../..' . '/core/trigger.class.inc.php', - 'TriggerOnStateChange' => __DIR__ . '/../..' . '/core/trigger.class.inc.php', - 'TriggerOnStateEnter' => __DIR__ . '/../..' . '/core/trigger.class.inc.php', - 'TriggerOnStateLeave' => __DIR__ . '/../..' . '/core/trigger.class.inc.php', - 'TriggerOnThresholdReached' => __DIR__ . '/../..' . '/core/trigger.class.inc.php', - 'TrueExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', - 'Twig\\Cache\\CacheInterface' => __DIR__ . '/..' . '/twig/twig/src/Cache/CacheInterface.php', - 'Twig\\Cache\\FilesystemCache' => __DIR__ . '/..' . '/twig/twig/src/Cache/FilesystemCache.php', - 'Twig\\Cache\\NullCache' => __DIR__ . '/..' . '/twig/twig/src/Cache/NullCache.php', - 'Twig\\Compiler' => __DIR__ . '/..' . '/twig/twig/src/Compiler.php', - 'Twig\\Environment' => __DIR__ . '/..' . '/twig/twig/src/Environment.php', - 'Twig\\Error\\Error' => __DIR__ . '/..' . '/twig/twig/src/Error/Error.php', - 'Twig\\Error\\LoaderError' => __DIR__ . '/..' . '/twig/twig/src/Error/LoaderError.php', - 'Twig\\Error\\RuntimeError' => __DIR__ . '/..' . '/twig/twig/src/Error/RuntimeError.php', - 'Twig\\Error\\SyntaxError' => __DIR__ . '/..' . '/twig/twig/src/Error/SyntaxError.php', - 'Twig\\ExpressionParser' => __DIR__ . '/..' . '/twig/twig/src/ExpressionParser.php', - 'Twig\\ExtensionSet' => __DIR__ . '/..' . '/twig/twig/src/ExtensionSet.php', - 'Twig\\Extension\\AbstractExtension' => __DIR__ . '/..' . '/twig/twig/src/Extension/AbstractExtension.php', - 'Twig\\Extension\\CoreExtension' => __DIR__ . '/..' . '/twig/twig/src/Extension/CoreExtension.php', - 'Twig\\Extension\\DebugExtension' => __DIR__ . '/..' . '/twig/twig/src/Extension/DebugExtension.php', - 'Twig\\Extension\\EscaperExtension' => __DIR__ . '/..' . '/twig/twig/src/Extension/EscaperExtension.php', - 'Twig\\Extension\\ExtensionInterface' => __DIR__ . '/..' . '/twig/twig/src/Extension/ExtensionInterface.php', - 'Twig\\Extension\\GlobalsInterface' => __DIR__ . '/..' . '/twig/twig/src/Extension/GlobalsInterface.php', - 'Twig\\Extension\\OptimizerExtension' => __DIR__ . '/..' . '/twig/twig/src/Extension/OptimizerExtension.php', - 'Twig\\Extension\\ProfilerExtension' => __DIR__ . '/..' . '/twig/twig/src/Extension/ProfilerExtension.php', - 'Twig\\Extension\\RuntimeExtensionInterface' => __DIR__ . '/..' . '/twig/twig/src/Extension/RuntimeExtensionInterface.php', - 'Twig\\Extension\\SandboxExtension' => __DIR__ . '/..' . '/twig/twig/src/Extension/SandboxExtension.php', - 'Twig\\Extension\\StagingExtension' => __DIR__ . '/..' . '/twig/twig/src/Extension/StagingExtension.php', - 'Twig\\Extension\\StringLoaderExtension' => __DIR__ . '/..' . '/twig/twig/src/Extension/StringLoaderExtension.php', - 'Twig\\FileExtensionEscapingStrategy' => __DIR__ . '/..' . '/twig/twig/src/FileExtensionEscapingStrategy.php', - 'Twig\\Lexer' => __DIR__ . '/..' . '/twig/twig/src/Lexer.php', - 'Twig\\Loader\\ArrayLoader' => __DIR__ . '/..' . '/twig/twig/src/Loader/ArrayLoader.php', - 'Twig\\Loader\\ChainLoader' => __DIR__ . '/..' . '/twig/twig/src/Loader/ChainLoader.php', - 'Twig\\Loader\\FilesystemLoader' => __DIR__ . '/..' . '/twig/twig/src/Loader/FilesystemLoader.php', - 'Twig\\Loader\\LoaderInterface' => __DIR__ . '/..' . '/twig/twig/src/Loader/LoaderInterface.php', - 'Twig\\Markup' => __DIR__ . '/..' . '/twig/twig/src/Markup.php', - 'Twig\\NodeTraverser' => __DIR__ . '/..' . '/twig/twig/src/NodeTraverser.php', - 'Twig\\NodeVisitor\\AbstractNodeVisitor' => __DIR__ . '/..' . '/twig/twig/src/NodeVisitor/AbstractNodeVisitor.php', - 'Twig\\NodeVisitor\\EscaperNodeVisitor' => __DIR__ . '/..' . '/twig/twig/src/NodeVisitor/EscaperNodeVisitor.php', - 'Twig\\NodeVisitor\\MacroAutoImportNodeVisitor' => __DIR__ . '/..' . '/twig/twig/src/NodeVisitor/MacroAutoImportNodeVisitor.php', - 'Twig\\NodeVisitor\\NodeVisitorInterface' => __DIR__ . '/..' . '/twig/twig/src/NodeVisitor/NodeVisitorInterface.php', - 'Twig\\NodeVisitor\\OptimizerNodeVisitor' => __DIR__ . '/..' . '/twig/twig/src/NodeVisitor/OptimizerNodeVisitor.php', - 'Twig\\NodeVisitor\\SafeAnalysisNodeVisitor' => __DIR__ . '/..' . '/twig/twig/src/NodeVisitor/SafeAnalysisNodeVisitor.php', - 'Twig\\NodeVisitor\\SandboxNodeVisitor' => __DIR__ . '/..' . '/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php', - 'Twig\\Node\\AutoEscapeNode' => __DIR__ . '/..' . '/twig/twig/src/Node/AutoEscapeNode.php', - 'Twig\\Node\\BlockNode' => __DIR__ . '/..' . '/twig/twig/src/Node/BlockNode.php', - 'Twig\\Node\\BlockReferenceNode' => __DIR__ . '/..' . '/twig/twig/src/Node/BlockReferenceNode.php', - 'Twig\\Node\\BodyNode' => __DIR__ . '/..' . '/twig/twig/src/Node/BodyNode.php', - 'Twig\\Node\\CheckSecurityCallNode' => __DIR__ . '/..' . '/twig/twig/src/Node/CheckSecurityCallNode.php', - 'Twig\\Node\\CheckSecurityNode' => __DIR__ . '/..' . '/twig/twig/src/Node/CheckSecurityNode.php', - 'Twig\\Node\\CheckToStringNode' => __DIR__ . '/..' . '/twig/twig/src/Node/CheckToStringNode.php', - 'Twig\\Node\\DeprecatedNode' => __DIR__ . '/..' . '/twig/twig/src/Node/DeprecatedNode.php', - 'Twig\\Node\\DoNode' => __DIR__ . '/..' . '/twig/twig/src/Node/DoNode.php', - 'Twig\\Node\\EmbedNode' => __DIR__ . '/..' . '/twig/twig/src/Node/EmbedNode.php', - 'Twig\\Node\\Expression\\AbstractExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/AbstractExpression.php', - 'Twig\\Node\\Expression\\ArrayExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/ArrayExpression.php', - 'Twig\\Node\\Expression\\ArrowFunctionExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/ArrowFunctionExpression.php', - 'Twig\\Node\\Expression\\AssignNameExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/AssignNameExpression.php', - 'Twig\\Node\\Expression\\Binary\\AbstractBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/AbstractBinary.php', - 'Twig\\Node\\Expression\\Binary\\AddBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/AddBinary.php', - 'Twig\\Node\\Expression\\Binary\\AndBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/AndBinary.php', - 'Twig\\Node\\Expression\\Binary\\BitwiseAndBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/BitwiseAndBinary.php', - 'Twig\\Node\\Expression\\Binary\\BitwiseOrBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/BitwiseOrBinary.php', - 'Twig\\Node\\Expression\\Binary\\BitwiseXorBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/BitwiseXorBinary.php', - 'Twig\\Node\\Expression\\Binary\\ConcatBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/ConcatBinary.php', - 'Twig\\Node\\Expression\\Binary\\DivBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/DivBinary.php', - 'Twig\\Node\\Expression\\Binary\\EndsWithBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/EndsWithBinary.php', - 'Twig\\Node\\Expression\\Binary\\EqualBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/EqualBinary.php', - 'Twig\\Node\\Expression\\Binary\\FloorDivBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/FloorDivBinary.php', - 'Twig\\Node\\Expression\\Binary\\GreaterBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/GreaterBinary.php', - 'Twig\\Node\\Expression\\Binary\\GreaterEqualBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/GreaterEqualBinary.php', - 'Twig\\Node\\Expression\\Binary\\InBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/InBinary.php', - 'Twig\\Node\\Expression\\Binary\\LessBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/LessBinary.php', - 'Twig\\Node\\Expression\\Binary\\LessEqualBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/LessEqualBinary.php', - 'Twig\\Node\\Expression\\Binary\\MatchesBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/MatchesBinary.php', - 'Twig\\Node\\Expression\\Binary\\ModBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/ModBinary.php', - 'Twig\\Node\\Expression\\Binary\\MulBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/MulBinary.php', - 'Twig\\Node\\Expression\\Binary\\NotEqualBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/NotEqualBinary.php', - 'Twig\\Node\\Expression\\Binary\\NotInBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/NotInBinary.php', - 'Twig\\Node\\Expression\\Binary\\OrBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/OrBinary.php', - 'Twig\\Node\\Expression\\Binary\\PowerBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/PowerBinary.php', - 'Twig\\Node\\Expression\\Binary\\RangeBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/RangeBinary.php', - 'Twig\\Node\\Expression\\Binary\\SpaceshipBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/SpaceshipBinary.php', - 'Twig\\Node\\Expression\\Binary\\StartsWithBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/StartsWithBinary.php', - 'Twig\\Node\\Expression\\Binary\\SubBinary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Binary/SubBinary.php', - 'Twig\\Node\\Expression\\BlockReferenceExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/BlockReferenceExpression.php', - 'Twig\\Node\\Expression\\CallExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/CallExpression.php', - 'Twig\\Node\\Expression\\ConditionalExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/ConditionalExpression.php', - 'Twig\\Node\\Expression\\ConstantExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/ConstantExpression.php', - 'Twig\\Node\\Expression\\FilterExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/FilterExpression.php', - 'Twig\\Node\\Expression\\Filter\\DefaultFilter' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Filter/DefaultFilter.php', - 'Twig\\Node\\Expression\\FunctionExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/FunctionExpression.php', - 'Twig\\Node\\Expression\\GetAttrExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/GetAttrExpression.php', - 'Twig\\Node\\Expression\\InlinePrint' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/InlinePrint.php', - 'Twig\\Node\\Expression\\MethodCallExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/MethodCallExpression.php', - 'Twig\\Node\\Expression\\NameExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/NameExpression.php', - 'Twig\\Node\\Expression\\NullCoalesceExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/NullCoalesceExpression.php', - 'Twig\\Node\\Expression\\ParentExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/ParentExpression.php', - 'Twig\\Node\\Expression\\TempNameExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/TempNameExpression.php', - 'Twig\\Node\\Expression\\TestExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/TestExpression.php', - 'Twig\\Node\\Expression\\Test\\ConstantTest' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Test/ConstantTest.php', - 'Twig\\Node\\Expression\\Test\\DefinedTest' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Test/DefinedTest.php', - 'Twig\\Node\\Expression\\Test\\DivisiblebyTest' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Test/DivisiblebyTest.php', - 'Twig\\Node\\Expression\\Test\\EvenTest' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Test/EvenTest.php', - 'Twig\\Node\\Expression\\Test\\NullTest' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Test/NullTest.php', - 'Twig\\Node\\Expression\\Test\\OddTest' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Test/OddTest.php', - 'Twig\\Node\\Expression\\Test\\SameasTest' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Test/SameasTest.php', - 'Twig\\Node\\Expression\\Unary\\AbstractUnary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Unary/AbstractUnary.php', - 'Twig\\Node\\Expression\\Unary\\NegUnary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Unary/NegUnary.php', - 'Twig\\Node\\Expression\\Unary\\NotUnary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Unary/NotUnary.php', - 'Twig\\Node\\Expression\\Unary\\PosUnary' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/Unary/PosUnary.php', - 'Twig\\Node\\Expression\\VariadicExpression' => __DIR__ . '/..' . '/twig/twig/src/Node/Expression/VariadicExpression.php', - 'Twig\\Node\\FlushNode' => __DIR__ . '/..' . '/twig/twig/src/Node/FlushNode.php', - 'Twig\\Node\\ForLoopNode' => __DIR__ . '/..' . '/twig/twig/src/Node/ForLoopNode.php', - 'Twig\\Node\\ForNode' => __DIR__ . '/..' . '/twig/twig/src/Node/ForNode.php', - 'Twig\\Node\\IfNode' => __DIR__ . '/..' . '/twig/twig/src/Node/IfNode.php', - 'Twig\\Node\\ImportNode' => __DIR__ . '/..' . '/twig/twig/src/Node/ImportNode.php', - 'Twig\\Node\\IncludeNode' => __DIR__ . '/..' . '/twig/twig/src/Node/IncludeNode.php', - 'Twig\\Node\\MacroNode' => __DIR__ . '/..' . '/twig/twig/src/Node/MacroNode.php', - 'Twig\\Node\\ModuleNode' => __DIR__ . '/..' . '/twig/twig/src/Node/ModuleNode.php', - 'Twig\\Node\\Node' => __DIR__ . '/..' . '/twig/twig/src/Node/Node.php', - 'Twig\\Node\\NodeCaptureInterface' => __DIR__ . '/..' . '/twig/twig/src/Node/NodeCaptureInterface.php', - 'Twig\\Node\\NodeOutputInterface' => __DIR__ . '/..' . '/twig/twig/src/Node/NodeOutputInterface.php', - 'Twig\\Node\\PrintNode' => __DIR__ . '/..' . '/twig/twig/src/Node/PrintNode.php', - 'Twig\\Node\\SandboxNode' => __DIR__ . '/..' . '/twig/twig/src/Node/SandboxNode.php', - 'Twig\\Node\\SetNode' => __DIR__ . '/..' . '/twig/twig/src/Node/SetNode.php', - 'Twig\\Node\\TextNode' => __DIR__ . '/..' . '/twig/twig/src/Node/TextNode.php', - 'Twig\\Node\\WithNode' => __DIR__ . '/..' . '/twig/twig/src/Node/WithNode.php', - 'Twig\\Parser' => __DIR__ . '/..' . '/twig/twig/src/Parser.php', - 'Twig\\Profiler\\Dumper\\BaseDumper' => __DIR__ . '/..' . '/twig/twig/src/Profiler/Dumper/BaseDumper.php', - 'Twig\\Profiler\\Dumper\\BlackfireDumper' => __DIR__ . '/..' . '/twig/twig/src/Profiler/Dumper/BlackfireDumper.php', - 'Twig\\Profiler\\Dumper\\HtmlDumper' => __DIR__ . '/..' . '/twig/twig/src/Profiler/Dumper/HtmlDumper.php', - 'Twig\\Profiler\\Dumper\\TextDumper' => __DIR__ . '/..' . '/twig/twig/src/Profiler/Dumper/TextDumper.php', - 'Twig\\Profiler\\NodeVisitor\\ProfilerNodeVisitor' => __DIR__ . '/..' . '/twig/twig/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php', - 'Twig\\Profiler\\Node\\EnterProfileNode' => __DIR__ . '/..' . '/twig/twig/src/Profiler/Node/EnterProfileNode.php', - 'Twig\\Profiler\\Node\\LeaveProfileNode' => __DIR__ . '/..' . '/twig/twig/src/Profiler/Node/LeaveProfileNode.php', - 'Twig\\Profiler\\Profile' => __DIR__ . '/..' . '/twig/twig/src/Profiler/Profile.php', - 'Twig\\RuntimeLoader\\ContainerRuntimeLoader' => __DIR__ . '/..' . '/twig/twig/src/RuntimeLoader/ContainerRuntimeLoader.php', - 'Twig\\RuntimeLoader\\FactoryRuntimeLoader' => __DIR__ . '/..' . '/twig/twig/src/RuntimeLoader/FactoryRuntimeLoader.php', - 'Twig\\RuntimeLoader\\RuntimeLoaderInterface' => __DIR__ . '/..' . '/twig/twig/src/RuntimeLoader/RuntimeLoaderInterface.php', - 'Twig\\Sandbox\\SecurityError' => __DIR__ . '/..' . '/twig/twig/src/Sandbox/SecurityError.php', - 'Twig\\Sandbox\\SecurityNotAllowedFilterError' => __DIR__ . '/..' . '/twig/twig/src/Sandbox/SecurityNotAllowedFilterError.php', - 'Twig\\Sandbox\\SecurityNotAllowedFunctionError' => __DIR__ . '/..' . '/twig/twig/src/Sandbox/SecurityNotAllowedFunctionError.php', - 'Twig\\Sandbox\\SecurityNotAllowedMethodError' => __DIR__ . '/..' . '/twig/twig/src/Sandbox/SecurityNotAllowedMethodError.php', - 'Twig\\Sandbox\\SecurityNotAllowedPropertyError' => __DIR__ . '/..' . '/twig/twig/src/Sandbox/SecurityNotAllowedPropertyError.php', - 'Twig\\Sandbox\\SecurityNotAllowedTagError' => __DIR__ . '/..' . '/twig/twig/src/Sandbox/SecurityNotAllowedTagError.php', - 'Twig\\Sandbox\\SecurityPolicy' => __DIR__ . '/..' . '/twig/twig/src/Sandbox/SecurityPolicy.php', - 'Twig\\Sandbox\\SecurityPolicyInterface' => __DIR__ . '/..' . '/twig/twig/src/Sandbox/SecurityPolicyInterface.php', - 'Twig\\Source' => __DIR__ . '/..' . '/twig/twig/src/Source.php', - 'Twig\\Template' => __DIR__ . '/..' . '/twig/twig/src/Template.php', - 'Twig\\TemplateWrapper' => __DIR__ . '/..' . '/twig/twig/src/TemplateWrapper.php', - 'Twig\\Token' => __DIR__ . '/..' . '/twig/twig/src/Token.php', - 'Twig\\TokenParser\\AbstractTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/AbstractTokenParser.php', - 'Twig\\TokenParser\\ApplyTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/ApplyTokenParser.php', - 'Twig\\TokenParser\\AutoEscapeTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/AutoEscapeTokenParser.php', - 'Twig\\TokenParser\\BlockTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/BlockTokenParser.php', - 'Twig\\TokenParser\\DeprecatedTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/DeprecatedTokenParser.php', - 'Twig\\TokenParser\\DoTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/DoTokenParser.php', - 'Twig\\TokenParser\\EmbedTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/EmbedTokenParser.php', - 'Twig\\TokenParser\\ExtendsTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/ExtendsTokenParser.php', - 'Twig\\TokenParser\\FlushTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/FlushTokenParser.php', - 'Twig\\TokenParser\\ForTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/ForTokenParser.php', - 'Twig\\TokenParser\\FromTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/FromTokenParser.php', - 'Twig\\TokenParser\\IfTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/IfTokenParser.php', - 'Twig\\TokenParser\\ImportTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/ImportTokenParser.php', - 'Twig\\TokenParser\\IncludeTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/IncludeTokenParser.php', - 'Twig\\TokenParser\\MacroTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/MacroTokenParser.php', - 'Twig\\TokenParser\\SandboxTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/SandboxTokenParser.php', - 'Twig\\TokenParser\\SetTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/SetTokenParser.php', - 'Twig\\TokenParser\\TokenParserInterface' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/TokenParserInterface.php', - 'Twig\\TokenParser\\UseTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/UseTokenParser.php', - 'Twig\\TokenParser\\WithTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/WithTokenParser.php', - 'Twig\\TokenStream' => __DIR__ . '/..' . '/twig/twig/src/TokenStream.php', - 'Twig\\TwigFilter' => __DIR__ . '/..' . '/twig/twig/src/TwigFilter.php', - 'Twig\\TwigFunction' => __DIR__ . '/..' . '/twig/twig/src/TwigFunction.php', - 'Twig\\TwigTest' => __DIR__ . '/..' . '/twig/twig/src/TwigTest.php', - 'Twig\\Util\\DeprecationCollector' => __DIR__ . '/..' . '/twig/twig/src/Util/DeprecationCollector.php', - 'Twig\\Util\\TemplateDirIterator' => __DIR__ . '/..' . '/twig/twig/src/Util/TemplateDirIterator.php', - 'UIExtKeyWidget' => __DIR__ . '/../..' . '/application/ui.extkeywidget.class.inc.php', - 'UIHTMLEditorWidget' => __DIR__ . '/../..' . '/application/ui.htmleditorwidget.class.inc.php', - 'UILinksWidget' => __DIR__ . '/../..' . '/application/ui.linkswidget.class.inc.php', - 'UILinksWidgetDirect' => __DIR__ . '/../..' . '/application/ui.linksdirectwidget.class.inc.php', - 'UIPasswordWidget' => __DIR__ . '/../..' . '/application/ui.passwordwidget.class.inc.php', - 'UISearchFormForeignKeys' => __DIR__ . '/../..' . '/application/ui.searchformforeignkeys.class.inc.php', - 'UIWizard' => __DIR__ . '/../..' . '/application/uiwizard.class.inc.php', - 'URLButtonItem' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'URLPopupMenuItem' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'UnaryExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', - 'UnauthenticatedWebPage' => __DIR__ . '/../..' . '/sources/Application/WebPage/UnauthenticatedWebPage.php', - 'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', - 'UnknownClassOqlException' => __DIR__ . '/../..' . '/core/oql/oqlinterpreter.class.inc.php', - 'User' => __DIR__ . '/../..' . '/core/userrights.class.inc.php', - 'UserDashboard' => __DIR__ . '/../..' . '/application/user.dashboard.class.inc.php', - 'UserInternal' => __DIR__ . '/../..' . '/core/userrights.class.inc.php', - 'UserRightException' => __DIR__ . '/../..' . '/application/exceptions/UserRightException.php', - 'UserRights' => __DIR__ . '/../..' . '/core/userrights.class.inc.php', - 'UserRightsAddOnAPI' => __DIR__ . '/../..' . '/core/userrights.class.inc.php', - 'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', - 'ValueSetDefinition' => __DIR__ . '/../..' . '/core/valuesetdef.class.inc.php', - 'ValueSetEnum' => __DIR__ . '/../..' . '/core/valuesetdef.class.inc.php', - 'ValueSetEnumClasses' => __DIR__ . '/../..' . '/core/valuesetdef.class.inc.php', - 'ValueSetEnumPadded' => __DIR__ . '/../..' . '/core/valuesetdef.class.inc.php', - 'ValueSetObjects' => __DIR__ . '/../..' . '/core/valuesetdef.class.inc.php', - 'ValueSetRange' => __DIR__ . '/../..' . '/core/valuesetdef.class.inc.php', - 'VariableExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', - 'VariableOqlExpression' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php', - 'WebPage' => __DIR__ . '/../..' . '/sources/Application/WebPage/WebPage.php', - 'WebPageMenuNode' => __DIR__ . '/../..' . '/application/menunode.class.inc.php', - 'Webmozart\\Assert\\Assert' => __DIR__ . '/..' . '/webmozart/assert/src/Assert.php', - 'Webmozart\\Assert\\InvalidArgumentException' => __DIR__ . '/..' . '/webmozart/assert/src/InvalidArgumentException.php', - 'Webmozart\\Assert\\Mixin' => __DIR__ . '/..' . '/webmozart/assert/src/Mixin.php', - 'WeeklyRotatingLogFileNameBuilder' => __DIR__ . '/../..' . '/core/log.class.inc.php', - 'WizardHelper' => __DIR__ . '/../..' . '/application/wizardhelper.class.inc.php', - 'XLSXWriter' => __DIR__ . '/../..' . '/application/xlsxwriter.class.php', - 'XMLBulkExport' => __DIR__ . '/../..' . '/core/xmlbulkexport.class.inc.php', - 'XMLPage' => __DIR__ . '/../..' . '/sources/Application/WebPage/XMLPage.php', - 'ajax_page' => __DIR__ . '/../..' . '/application/ajaxwebpage.class.inc.php', - 'appUserPreferences' => __DIR__ . '/../..' . '/application/user.preferences.class.inc.php', - 'cmdbAbstractObject' => __DIR__ . '/../..' . '/application/cmdbabstract.class.inc.php', - 'cmdbDataGenerator' => __DIR__ . '/../..' . '/core/data.generator.class.inc.php', - 'iApplicationObjectExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'iApplicationUIExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'iAttributeNoGroupBy' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'iBackgroundProcess' => __DIR__ . '/../..' . '/core/backgroundprocess.inc.php', - 'iBackofficeDictEntriesExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'iBackofficeDictEntriesPrefixesExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'iBackofficeEarlyScriptExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'iBackofficeInitScriptExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'iBackofficeLinkedScriptsExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'iBackofficeLinkedStylesheetsExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'iBackofficeReadyScriptExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'iBackofficeScriptExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'iBackofficeStyleExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'iCMDBChangeOp' => __DIR__ . '/../..' . '/core/cmdbchangeop.class.inc.php', - 'iDBObjectSetIterator' => __DIR__ . '/../..' . '/core/dbobjectiterator.php', - 'iDBObjectURLMaker' => __DIR__ . '/../..' . '/application/applicationcontext.class.inc.php', - 'iDisplay' => __DIR__ . '/../..' . '/core/dbobject.class.php', - 'iFieldRendererMappingsExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'iKPILoggerExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'iKeyboardShortcut' => __DIR__ . '/../..' . '/sources/Application/UI/Hook/iKeyboardShortcut.php', - 'iLogFileNameBuilder' => __DIR__ . '/../..' . '/core/log.class.inc.php', - 'iLoginExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'iLoginFSMExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'iLoginUIExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'iLogoutExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'iMetricComputer' => __DIR__ . '/../..' . '/core/computing.inc.php', - 'iModuleExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'iNewsroomProvider' => __DIR__ . '/../..' . '/application/newsroomprovider.class.inc.php', - 'iOnClassInitialization' => __DIR__ . '/../..' . '/core/metamodelmodifier.inc.php', - 'iPageUIBlockExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'iPageUIExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'iPopupMenuExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'iPortalUIExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'iPreferencesExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'iProcess' => __DIR__ . '/../..' . '/core/backgroundprocess.inc.php', - 'iQueryModifier' => __DIR__ . '/../..' . '/core/querymodifier.class.inc.php', - 'iRestServiceProvider' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', - 'iScheduledProcess' => __DIR__ . '/../..' . '/core/backgroundprocess.inc.php', - 'iSelfRegister' => __DIR__ . '/../..' . '/core/userrights.class.inc.php', - 'iTabbedPage' => __DIR__ . '/../..' . '/sources/Application/WebPage/iTabbedPage.php', - 'iTopConfigParser' => __DIR__ . '/../..' . '/core/iTopConfigParser.php', - 'iTopMutex' => __DIR__ . '/../..' . '/core/mutex.class.inc.php', - 'iTopOwnershipLock' => __DIR__ . '/../..' . '/core/ownershiplock.class.inc.php', - 'iTopOwnershipToken' => __DIR__ . '/../..' . '/core/ownershiplock.class.inc.php', - 'iTopPDF' => __DIR__ . '/../..' . '/sources/Application/WebPage/iTopPDF.php', - 'iTopStandardURLMaker' => __DIR__ . '/../..' . '/application/applicationcontext.class.inc.php', - 'iTopWebPage' => __DIR__ . '/../..' . '/sources/Application/WebPage/iTopWebPage.php', - 'iTopWizardWebPage' => __DIR__ . '/../..' . '/sources/Application/WebPage/iTopWizardWebPage.php', - 'iTopXmlException' => __DIR__ . '/../..' . '/application/exceptions/iTopXmlException.php', - 'iWorkingTimeComputer' => __DIR__ . '/../..' . '/core/computing.inc.php', - 'lnkAuditCategoryToAuditDomain' => __DIR__ . '/../..' . '/application/audit.domain.class.inc.php', - 'lnkTriggerAction' => __DIR__ . '/../..' . '/core/trigger.class.inc.php', - 'ormCaseLog' => __DIR__ . '/../..' . '/core/ormcaselog.class.inc.php', - 'ormCustomFieldsValue' => __DIR__ . '/../..' . '/core/ormcustomfieldsvalue.class.inc.php', - 'ormDocument' => __DIR__ . '/../..' . '/core/ormdocument.class.inc.php', - 'ormLinkSet' => __DIR__ . '/../..' . '/core/ormlinkset.class.inc.php', - 'ormPassword' => __DIR__ . '/../..' . '/core/ormpassword.class.inc.php', - 'ormSet' => __DIR__ . '/../..' . '/core/ormset.class.inc.php', - 'ormStopWatch' => __DIR__ . '/../..' . '/core/ormstopwatch.class.inc.php', - 'ormStyle' => __DIR__ . '/../..' . '/core/ormStyle.class.inc.php', - 'ormTagSet' => __DIR__ . '/../..' . '/core/ormtagset.class.inc.php', - 'phpCAS' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS.php', - 'privUITransaction' => __DIR__ . '/../..' . '/application/transaction.class.inc.php', - 'privUITransactionFile' => __DIR__ . '/../..' . '/application/transaction.class.inc.php', - 'privUITransactionSession' => __DIR__ . '/../..' . '/application/transaction.class.inc.php', - 'utils' => __DIR__ . '/../..' . '/application/utils.inc.php', - ); - - public static function getInitializer(ClassLoader $loader) - { - return \Closure::bind(function () use ($loader) { - $loader->prefixLengthsPsr4 = ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f::$prefixLengthsPsr4; - $loader->prefixDirsPsr4 = ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f::$prefixDirsPsr4; - $loader->prefixesPsr0 = ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f::$prefixesPsr0; - $loader->fallbackDirsPsr0 = ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f::$fallbackDirsPsr0; - $loader->classMap = ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f::$classMap; - - }, null, ClassLoader::class); - } -} diff --git a/lib/composer/include_paths.php b/lib/composer/include_paths.php deleted file mode 100644 index d4fb96718..000000000 --- a/lib/composer/include_paths.php +++ /dev/null @@ -1,13 +0,0 @@ -<?php - -// include_paths.php @generated by Composer - -$vendorDir = dirname(dirname(__FILE__)); -$baseDir = dirname($vendorDir); - -return array( - $vendorDir . '/pear/archive_tar', - $vendorDir . '/pear/console_getopt', - $vendorDir . '/pear/pear-core-minimal/src', - $vendorDir . '/pear/pear_exception', -); diff --git a/lib/composer/installed.json b/lib/composer/installed.json deleted file mode 100644 index 4c0402db3..000000000 --- a/lib/composer/installed.json +++ /dev/null @@ -1,6216 +0,0 @@ -{ - "packages": [ - { - "name": "apereo/phpcas", - "version": "1.6.0", - "version_normalized": "1.6.0.0", - "source": { - "type": "git", - "url": "https://github.com/apereo/phpCAS.git", - "reference": "f817c72a961484afef95ac64a9257c8e31f063b9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/apereo/phpCAS/zipball/f817c72a961484afef95ac64a9257c8e31f063b9", - "reference": "f817c72a961484afef95ac64a9257c8e31f063b9", - "shasum": "" - }, - "require": { - "ext-curl": "*", - "ext-dom": "*", - "php": ">=7.1.0", - "psr/log": "^1.0 || ^2.0 || ^3.0" - }, - "require-dev": { - "monolog/monolog": "^1.0.0 || ^2.0.0", - "phpstan/phpstan": "^1.5", - "phpunit/phpunit": ">=7.5" - }, - "time": "2022-10-31T20:39:27+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "source/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Joachim Fritschi", - "email": "jfritschi@freenet.de", - "homepage": "https://github.com/jfritschi" - }, - { - "name": "Adam Franco", - "homepage": "https://github.com/adamfranco" - }, - { - "name": "Henry Pan", - "homepage": "https://github.com/phy25" - } - ], - "description": "Provides a simple API for authenticating users against a CAS server", - "homepage": "https://wiki.jasig.org/display/CASC/phpCAS", - "keywords": [ - "apereo", - "cas", - "jasig" - ], - "support": { - "issues": "https://github.com/apereo/phpCAS/issues", - "source": "https://github.com/apereo/phpCAS/tree/1.6.0" - }, - "install-path": "../apereo/phpcas" - }, - { - "name": "combodo/tcpdf", - "version": "6.4.4", - "version_normalized": "6.4.4.0", - "source": { - "type": "git", - "url": "https://github.com/combodo-itop-libs/TCPDF.git", - "reference": "0e31c013ccd000aa6762e9186778aa6e259ac8e8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/combodo-itop-libs/TCPDF/zipball/0e31c013ccd000aa6762e9186778aa6e259ac8e8", - "reference": "0e31c013ccd000aa6762e9186778aa6e259ac8e8", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "replace": { - "tecnickcom/tcpdf": "self.version" - }, - "time": "2022-03-10T14:36:39+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "classmap": [ - "config", - "include", - "tcpdf.php", - "tcpdf_parser.php", - "tcpdf_import.php", - "tcpdf_barcodes_1d.php", - "tcpdf_barcodes_2d.php", - "include/tcpdf_colors.php", - "include/tcpdf_filters.php", - "include/tcpdf_font_data.php", - "include/tcpdf_fonts.php", - "include/tcpdf_images.php", - "include/tcpdf_static.php", - "include/barcodes/datamatrix.php", - "include/barcodes/pdf417.php", - "include/barcodes/qrcode.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-3.0-only" - ], - "authors": [ - { - "name": "Nicola Asuni", - "email": "info@tecnick.com", - "role": "lead" - }, - { - "name": "Combodo", - "email": "contact@combodo.com" - } - ], - "description": "TCPDF is a PHP class for generating PDF documents and barcodes.", - "homepage": "https://github.com/combodo-itop-libs/TCPDF", - "keywords": [ - "PDFD32000-2008", - "TCPDF", - "barcodes", - "datamatrix", - "pdf", - "pdf417", - "qrcode" - ], - "support": { - "source": "https://github.com/combodo-itop-libs/TCPDF/tree/6.4.4" - }, - "funding": [ - { - "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_donations&currency_code=GBP&business=paypal@tecnick.com&item_name=donation%20for%20tcpdf%20project", - "type": "custom" - } - ], - "install-path": "../combodo/tcpdf" - }, - { - "name": "doctrine/annotations", - "version": "2.0.1", - "version_normalized": "2.0.1.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f", - "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f", - "shasum": "" - }, - "require": { - "doctrine/lexer": "^2 || ^3", - "ext-tokenizer": "*", - "php": "^7.2 || ^8.0", - "psr/cache": "^1 || ^2 || ^3" - }, - "require-dev": { - "doctrine/cache": "^2.0", - "doctrine/coding-standard": "^10", - "phpstan/phpstan": "^1.8.0", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "symfony/cache": "^5.4 || ^6", - "vimeo/psalm": "^4.10" - }, - "suggest": { - "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" - }, - "time": "2023-02-02T22:02:53+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Docblock Annotations Parser", - "homepage": "https://www.doctrine-project.org/projects/annotations.html", - "keywords": [ - "annotations", - "docblock", - "parser" - ], - "support": { - "issues": "https://github.com/doctrine/annotations/issues", - "source": "https://github.com/doctrine/annotations/tree/2.0.1" - }, - "install-path": "../doctrine/annotations" - }, - { - "name": "doctrine/cache", - "version": "2.2.0", - "version_normalized": "2.2.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/cache.git", - "reference": "1ca8f21980e770095a31456042471a57bc4c68fb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/1ca8f21980e770095a31456042471a57bc4c68fb", - "reference": "1ca8f21980e770095a31456042471a57bc4c68fb", - "shasum": "" - }, - "require": { - "php": "~7.1 || ^8.0" - }, - "conflict": { - "doctrine/common": ">2.2,<2.4" - }, - "require-dev": { - "cache/integration-tests": "dev-master", - "doctrine/coding-standard": "^9", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "psr/cache": "^1.0 || ^2.0 || ^3.0", - "symfony/cache": "^4.4 || ^5.4 || ^6", - "symfony/var-exporter": "^4.4 || ^5.4 || ^6" - }, - "time": "2022-05-20T20:07:39+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" - } - }, - "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 Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", - "homepage": "https://www.doctrine-project.org/projects/cache.html", - "keywords": [ - "abstraction", - "apcu", - "cache", - "caching", - "couchdb", - "memcached", - "php", - "redis", - "xcache" - ], - "support": { - "issues": "https://github.com/doctrine/cache/issues", - "source": "https://github.com/doctrine/cache/tree/2.2.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcache", - "type": "tidelift" - } - ], - "install-path": "../doctrine/cache" - }, - { - "name": "doctrine/deprecations", - "version": "v1.1.1", - "version_normalized": "1.1.1.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/deprecations.git", - "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", - "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9", - "phpstan/phpstan": "1.4.10 || 1.10.15", - "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "psalm/plugin-phpunit": "0.18.4", - "psr/log": "^1 || ^2 || ^3", - "vimeo/psalm": "4.30.0 || 5.12.0" - }, - "suggest": { - "psr/log": "Allows logging deprecations via PSR-3 logger implementation" - }, - "time": "2023-06-03T09:27:29+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", - "homepage": "https://www.doctrine-project.org/", - "support": { - "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/v1.1.1" - }, - "install-path": "../doctrine/deprecations" - }, - { - "name": "doctrine/lexer", - "version": "2.1.0", - "version_normalized": "2.1.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", - "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", - "shasum": "" - }, - "require": { - "doctrine/deprecations": "^1.0", - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9 || ^10", - "phpstan/phpstan": "^1.3", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "psalm/plugin-phpunit": "^0.18.3", - "vimeo/psalm": "^4.11 || ^5.0" - }, - "time": "2022-12-14T08:49:07+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Lexer\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "https://www.doctrine-project.org/projects/lexer.html", - "keywords": [ - "annotations", - "docblock", - "lexer", - "parser", - "php" - ], - "support": { - "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/2.1.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", - "type": "tidelift" - } - ], - "install-path": "../doctrine/lexer" - }, - { - "name": "firebase/php-jwt", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", - "source": { - "type": "git", - "url": "https://github.com/firebase/php-jwt.git", - "reference": "4dd1e007f22a927ac77da5a3fbb067b42d3bc224" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/4dd1e007f22a927ac77da5a3fbb067b42d3bc224", - "reference": "4dd1e007f22a927ac77da5a3fbb067b42d3bc224", - "shasum": "" - }, - "require": { - "php": "^7.1||^8.0" - }, - "require-dev": { - "guzzlehttp/guzzle": "^6.5||^7.4", - "phpspec/prophecy-phpunit": "^1.1", - "phpunit/phpunit": "^7.5||^9.5", - "psr/cache": "^1.0||^2.0", - "psr/http-client": "^1.0", - "psr/http-factory": "^1.0" - }, - "suggest": { - "ext-sodium": "Support EdDSA (Ed25519) signatures", - "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" - }, - "time": "2023-02-09T21:01:23+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Firebase\\JWT\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Neuman Vong", - "email": "neuman+pear@twilio.com", - "role": "Developer" - }, - { - "name": "Anant Narayanan", - "email": "anant@php.net", - "role": "Developer" - } - ], - "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", - "homepage": "https://github.com/firebase/php-jwt", - "keywords": [ - "jwt", - "php" - ], - "support": { - "issues": "https://github.com/firebase/php-jwt/issues", - "source": "https://github.com/firebase/php-jwt/tree/v6.4.0" - }, - "install-path": "../firebase/php-jwt" - }, - { - "name": "guzzlehttp/guzzle", - "version": "7.7.0", - "version_normalized": "7.7.0.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/fb7566caccf22d74d1ab270de3551f72a58399f5", - "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5", - "shasum": "" - }, - "require": { - "ext-json": "*", - "guzzlehttp/promises": "^1.5.3 || ^2.0", - "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", - "php": "^7.2.5 || ^8.0", - "psr/http-client": "^1.0", - "symfony/deprecation-contracts": "^2.2 || ^3.0" - }, - "provide": { - "psr/http-client-implementation": "1.0" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", - "ext-curl": "*", - "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", - "php-http/message-factory": "^1.1", - "phpunit/phpunit": "^8.5.29 || ^9.5.23", - "psr/log": "^1.1 || ^2.0 || ^3.0" - }, - "suggest": { - "ext-curl": "Required for CURL handler support", - "ext-intl": "Required for Internationalized Domain Name (IDN) support", - "psr/log": "Required for using the Log middleware" - }, - "time": "2023-05-21T14:04:53+00:00", - "type": "library", - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "GuzzleHttp\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - }, - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Jeremy Lindblom", - "email": "jeremeamia@gmail.com", - "homepage": "https://github.com/jeremeamia" - }, - { - "name": "George Mponos", - "email": "gmponos@gmail.com", - "homepage": "https://github.com/gmponos" - }, - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/Nyholm" - }, - { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com", - "homepage": "https://github.com/sagikazarmark" - }, - { - "name": "Tobias Schultze", - "email": "webmaster@tubo-world.de", - "homepage": "https://github.com/Tobion" - } - ], - "description": "Guzzle is a PHP HTTP client library", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "psr-18", - "psr-7", - "rest", - "web service" - ], - "support": { - "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.7.0" - }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://github.com/Nyholm", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", - "type": "tidelift" - } - ], - "install-path": "../guzzlehttp/guzzle" - }, - { - "name": "guzzlehttp/promises", - "version": "2.0.0", - "version_normalized": "2.0.0.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/promises.git", - "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/3a494dc7dc1d7d12e511890177ae2d0e6c107da6", - "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6", - "shasum": "" - }, - "require": { - "php": "^7.2.5 || ^8.0" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", - "phpunit/phpunit": "^8.5.29 || ^9.5.23" - }, - "time": "2023-05-21T13:50:22+00:00", - "type": "library", - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "GuzzleHttp\\Promise\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - }, - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/Nyholm" - }, - { - "name": "Tobias Schultze", - "email": "webmaster@tubo-world.de", - "homepage": "https://github.com/Tobion" - } - ], - "description": "Guzzle promises library", - "keywords": [ - "promise" - ], - "support": { - "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.0.0" - }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://github.com/Nyholm", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", - "type": "tidelift" - } - ], - "install-path": "../guzzlehttp/promises" - }, - { - "name": "guzzlehttp/psr7", - "version": "2.5.0", - "version_normalized": "2.5.0.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/psr7.git", - "reference": "b635f279edd83fc275f822a1188157ffea568ff6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/b635f279edd83fc275f822a1188157ffea568ff6", - "reference": "b635f279edd83fc275f822a1188157ffea568ff6", - "shasum": "" - }, - "require": { - "php": "^7.2.5 || ^8.0", - "psr/http-factory": "^1.0", - "psr/http-message": "^1.1 || ^2.0", - "ralouphie/getallheaders": "^3.0" - }, - "provide": { - "psr/http-factory-implementation": "1.0", - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", - "http-interop/http-factory-tests": "^0.9", - "phpunit/phpunit": "^8.5.29 || ^9.5.23" - }, - "suggest": { - "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" - }, - "time": "2023-04-17T16:11:26+00:00", - "type": "library", - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "GuzzleHttp\\Psr7\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - }, - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "George Mponos", - "email": "gmponos@gmail.com", - "homepage": "https://github.com/gmponos" - }, - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/Nyholm" - }, - { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com", - "homepage": "https://github.com/sagikazarmark" - }, - { - "name": "Tobias Schultze", - "email": "webmaster@tubo-world.de", - "homepage": "https://github.com/Tobion" - }, - { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com", - "homepage": "https://sagikazarmark.hu" - } - ], - "description": "PSR-7 message implementation that also provides common utility methods", - "keywords": [ - "http", - "message", - "psr-7", - "request", - "response", - "stream", - "uri", - "url" - ], - "support": { - "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.5.0" - }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://github.com/Nyholm", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", - "type": "tidelift" - } - ], - "install-path": "../guzzlehttp/psr7" - }, - { - "name": "laminas/laminas-loader", - "version": "2.8.0", - "version_normalized": "2.8.0.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-loader.git", - "reference": "d0589ec9dd48365fd95ad10d1c906efd7711c16b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-loader/zipball/d0589ec9dd48365fd95ad10d1c906efd7711c16b", - "reference": "d0589ec9dd48365fd95ad10d1c906efd7711c16b", - "shasum": "" - }, - "require": { - "php": "^7.3 || ~8.0.0 || ~8.1.0" - }, - "conflict": { - "zendframework/zend-loader": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~2.2.1", - "phpunit/phpunit": "^9.3" - }, - "time": "2021-09-02T18:30:53+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Laminas\\Loader\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Autoloading and plugin loading strategies", - "homepage": "https://laminas.dev", - "keywords": [ - "laminas", - "loader" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-loader/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-loader/issues", - "rss": "https://github.com/laminas/laminas-loader/releases.atom", - "source": "https://github.com/laminas/laminas-loader" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "install-path": "../laminas/laminas-loader" - }, - { - "name": "laminas/laminas-mail", - "version": "2.16.0", - "version_normalized": "2.16.0.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-mail.git", - "reference": "1ee1a384b96c8af29ecad9b3a7adc27a150ebc49" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-mail/zipball/1ee1a384b96c8af29ecad9b3a7adc27a150ebc49", - "reference": "1ee1a384b96c8af29ecad9b3a7adc27a150ebc49", - "shasum": "" - }, - "require": { - "ext-iconv": "*", - "laminas/laminas-loader": "^2.8", - "laminas/laminas-mime": "^2.9.1", - "laminas/laminas-stdlib": "^3.6", - "laminas/laminas-validator": "^2.15", - "php": "^7.3 || ~8.0.0 || ~8.1.0", - "symfony/polyfill-intl-idn": "^1.24.0", - "symfony/polyfill-mbstring": "^1.12.0", - "webmozart/assert": "^1.10" - }, - "conflict": { - "zendframework/zend-mail": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~1.0.0", - "laminas/laminas-crypt": "^2.6 || ^3.4", - "laminas/laminas-db": "^2.13.3", - "laminas/laminas-servicemanager": "^3.7", - "phpunit/phpunit": "^9.5.5", - "psalm/plugin-phpunit": "^0.15.1", - "symfony/process": "^5.3.7", - "vimeo/psalm": "^4.7" - }, - "suggest": { - "laminas/laminas-crypt": "Crammd5 support in SMTP Auth", - "laminas/laminas-servicemanager": "^2.7.10 || ^3.3.1 when using SMTP to deliver messages" - }, - "time": "2022-02-23T21:08:17+00:00", - "type": "library", - "extra": { - "laminas": { - "component": "Laminas\\Mail", - "config-provider": "Laminas\\Mail\\ConfigProvider" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Laminas\\Mail\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Provides generalized functionality to compose and send both text and MIME-compliant multipart e-mail messages", - "homepage": "https://laminas.dev", - "keywords": [ - "laminas", - "mail" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-mail/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-mail/issues", - "rss": "https://github.com/laminas/laminas-mail/releases.atom", - "source": "https://github.com/laminas/laminas-mail" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "install-path": "../laminas/laminas-mail" - }, - { - "name": "laminas/laminas-mime", - "version": "2.9.1", - "version_normalized": "2.9.1.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-mime.git", - "reference": "72d21a1b4bb7086d4a4d7058c0abca180b209184" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-mime/zipball/72d21a1b4bb7086d4a4d7058c0abca180b209184", - "reference": "72d21a1b4bb7086d4a4d7058c0abca180b209184", - "shasum": "" - }, - "require": { - "laminas/laminas-stdlib": "^2.7 || ^3.0", - "php": "^7.3 || ~8.0.0 || ~8.1.0" - }, - "conflict": { - "zendframework/zend-mime": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~2.2.1", - "laminas/laminas-mail": "^2.12", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "laminas/laminas-mail": "Laminas\\Mail component" - }, - "time": "2021-09-20T21:19:24+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Laminas\\Mime\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Create and parse MIME messages and parts", - "homepage": "https://laminas.dev", - "keywords": [ - "laminas", - "mime" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-mime/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-mime/issues", - "rss": "https://github.com/laminas/laminas-mime/releases.atom", - "source": "https://github.com/laminas/laminas-mime" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "install-path": "../laminas/laminas-mime" - }, - { - "name": "laminas/laminas-servicemanager", - "version": "3.16.0", - "version_normalized": "3.16.0.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-servicemanager.git", - "reference": "863c66733740cd36ebf5e700f4258ef2c68a2a24" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-servicemanager/zipball/863c66733740cd36ebf5e700f4258ef2c68a2a24", - "reference": "863c66733740cd36ebf5e700f4258ef2c68a2a24", - "shasum": "" - }, - "require": { - "laminas/laminas-stdlib": "^3.2.1", - "php": "~7.4.0 || ~8.0.0 || ~8.1.0", - "psr/container": "^1.0" - }, - "conflict": { - "ext-psr": "*", - "laminas/laminas-code": "<3.3.1", - "zendframework/zend-code": "<3.3.1", - "zendframework/zend-servicemanager": "*" - }, - "provide": { - "psr/container-implementation": "^1.0" - }, - "replace": { - "container-interop/container-interop": "^1.2.0" - }, - "require-dev": { - "composer/package-versions-deprecated": "^1.0", - "laminas/laminas-coding-standard": "~2.3.0", - "laminas/laminas-container-config-test": "^0.7", - "laminas/laminas-dependency-plugin": "^2.1.2", - "mikey179/vfsstream": "^1.6.10@alpha", - "ocramius/proxy-manager": "^2.11", - "phpbench/phpbench": "^1.1", - "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^9.5.5", - "psalm/plugin-phpunit": "^0.17.0", - "vimeo/psalm": "^4.8" - }, - "suggest": { - "ocramius/proxy-manager": "ProxyManager ^2.1.1 to handle lazy initialization of services" - }, - "time": "2022-07-27T14:58:17+00:00", - "bin": [ - "bin/generate-deps-for-config-factory", - "bin/generate-factory-for-class" - ], - "type": "library", - "installation-source": "dist", - "autoload": { - "files": [ - "src/autoload.php" - ], - "psr-4": { - "Laminas\\ServiceManager\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Factory-Driven Dependency Injection Container", - "homepage": "https://laminas.dev", - "keywords": [ - "PSR-11", - "dependency-injection", - "di", - "dic", - "laminas", - "service-manager", - "servicemanager" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-servicemanager/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-servicemanager/issues", - "rss": "https://github.com/laminas/laminas-servicemanager/releases.atom", - "source": "https://github.com/laminas/laminas-servicemanager" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "install-path": "../laminas/laminas-servicemanager" - }, - { - "name": "laminas/laminas-stdlib", - "version": "3.12.0", - "version_normalized": "3.12.0.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-stdlib.git", - "reference": "c5aed3c798018e31fbb7b1e421b8d96bf2cda453" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/c5aed3c798018e31fbb7b1e421b8d96bf2cda453", - "reference": "c5aed3c798018e31fbb7b1e421b8d96bf2cda453", - "shasum": "" - }, - "require": { - "php": "^7.4 || ~8.0.0 || ~8.1.0" - }, - "conflict": { - "zendframework/zend-stdlib": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~2.3.0", - "phpbench/phpbench": "^1.2.6", - "phpstan/phpdoc-parser": "^0.5.4", - "phpunit/phpunit": "^9.5.23", - "psalm/plugin-phpunit": "^0.17.0", - "vimeo/psalm": "^4.26" - }, - "time": "2022-08-22T22:55:58+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Laminas\\Stdlib\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "SPL extensions, array utilities, error handlers, and more", - "homepage": "https://laminas.dev", - "keywords": [ - "laminas", - "stdlib" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-stdlib/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-stdlib/issues", - "rss": "https://github.com/laminas/laminas-stdlib/releases.atom", - "source": "https://github.com/laminas/laminas-stdlib" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "install-path": "../laminas/laminas-stdlib" - }, - { - "name": "laminas/laminas-validator", - "version": "2.23.0", - "version_normalized": "2.23.0.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-validator.git", - "reference": "6d61b6cc3b222f13807a18d9247cdfb084958b03" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-validator/zipball/6d61b6cc3b222f13807a18d9247cdfb084958b03", - "reference": "6d61b6cc3b222f13807a18d9247cdfb084958b03", - "shasum": "" - }, - "require": { - "laminas/laminas-servicemanager": "^3.12.0", - "laminas/laminas-stdlib": "^3.10", - "php": "^7.4 || ~8.0.0 || ~8.1.0" - }, - "conflict": { - "zendframework/zend-validator": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~2.3.0", - "laminas/laminas-db": "^2.7", - "laminas/laminas-filter": "^2.14.0", - "laminas/laminas-http": "^2.14.2", - "laminas/laminas-i18n": "^2.15.0", - "laminas/laminas-session": "^2.12.1", - "laminas/laminas-uri": "^2.9.1", - "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^9.5.21", - "psalm/plugin-phpunit": "^0.17.0", - "psr/http-client": "^1.0", - "psr/http-factory": "^1.0", - "psr/http-message": "^1.0", - "vimeo/psalm": "^4.24.0" - }, - "suggest": { - "laminas/laminas-db": "Laminas\\Db component, required by the (No)RecordExists validator", - "laminas/laminas-filter": "Laminas\\Filter component, required by the Digits validator", - "laminas/laminas-i18n": "Laminas\\I18n component to allow translation of validation error messages", - "laminas/laminas-i18n-resources": "Translations of validator messages", - "laminas/laminas-servicemanager": "Laminas\\ServiceManager component to allow using the ValidatorPluginManager and validator chains", - "laminas/laminas-session": "Laminas\\Session component, ^2.8; required by the Csrf validator", - "laminas/laminas-uri": "Laminas\\Uri component, required by the Uri and Sitemap\\Loc validators", - "psr/http-message": "psr/http-message, required when validating PSR-7 UploadedFileInterface instances via the Upload and UploadFile validators" - }, - "time": "2022-07-27T19:17:59+00:00", - "type": "library", - "extra": { - "laminas": { - "component": "Laminas\\Validator", - "config-provider": "Laminas\\Validator\\ConfigProvider" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Laminas\\Validator\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Validation classes for a wide range of domains, and the ability to chain validators to create complex validation criteria", - "homepage": "https://laminas.dev", - "keywords": [ - "laminas", - "validator" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-validator/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-validator/issues", - "rss": "https://github.com/laminas/laminas-validator/releases.atom", - "source": "https://github.com/laminas/laminas-validator" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "install-path": "../laminas/laminas-validator" - }, - { - "name": "league/oauth2-client", - "version": "2.6.1", - "version_normalized": "2.6.1.0", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/oauth2-client.git", - "reference": "2334c249907190c132364f5dae0287ab8666aa19" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/oauth2-client/zipball/2334c249907190c132364f5dae0287ab8666aa19", - "reference": "2334c249907190c132364f5dae0287ab8666aa19", - "shasum": "" - }, - "require": { - "guzzlehttp/guzzle": "^6.0 || ^7.0", - "paragonie/random_compat": "^1 || ^2 || ^9.99", - "php": "^5.6 || ^7.0 || ^8.0" - }, - "require-dev": { - "mockery/mockery": "^1.3.5", - "php-parallel-lint/php-parallel-lint": "^1.3.1", - "phpunit/phpunit": "^5.7 || ^6.0 || ^9.5", - "squizlabs/php_codesniffer": "^2.3 || ^3.0" - }, - "time": "2021-12-22T16:42:49+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "League\\OAuth2\\Client\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Alex Bilbie", - "email": "hello@alexbilbie.com", - "homepage": "http://www.alexbilbie.com", - "role": "Developer" - }, - { - "name": "Woody Gilk", - "homepage": "https://github.com/shadowhand", - "role": "Contributor" - } - ], - "description": "OAuth 2.0 Client Library", - "keywords": [ - "Authentication", - "SSO", - "authorization", - "identity", - "idp", - "oauth", - "oauth2", - "single sign on" - ], - "support": { - "issues": "https://github.com/thephpleague/oauth2-client/issues", - "source": "https://github.com/thephpleague/oauth2-client/tree/2.6.1" - }, - "install-path": "../league/oauth2-client" - }, - { - "name": "league/oauth2-google", - "version": "3.0.4", - "version_normalized": "3.0.4.0", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/oauth2-google.git", - "reference": "6b79441f244040760bed5fdcd092a2bda7cf34c6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/oauth2-google/zipball/6b79441f244040760bed5fdcd092a2bda7cf34c6", - "reference": "6b79441f244040760bed5fdcd092a2bda7cf34c6", - "shasum": "" - }, - "require": { - "league/oauth2-client": "^2.0" - }, - "require-dev": { - "eloquent/phony-phpunit": "^2.0", - "php-coveralls/php-coveralls": "^2.1", - "phpunit/phpunit": "^6.0", - "squizlabs/php_codesniffer": "^2.0" - }, - "time": "2021-01-27T16:09:03+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "League\\OAuth2\\Client\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Woody Gilk", - "email": "woody.gilk@gmail.com", - "homepage": "http://shadowhand.me" - } - ], - "description": "Google OAuth 2.0 Client Provider for The PHP League OAuth2-Client", - "keywords": [ - "Authentication", - "authorization", - "client", - "google", - "oauth", - "oauth2" - ], - "support": { - "issues": "https://github.com/thephpleague/oauth2-google/issues", - "source": "https://github.com/thephpleague/oauth2-google/tree/3.0.4" - }, - "install-path": "../league/oauth2-google" - }, - { - "name": "nikic/php-parser", - "version": "v4.14.0", - "version_normalized": "4.14.0.0", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/34bea19b6e03d8153165d8f30bba4c3be86184c1", - "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=7.0" - }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" - }, - "time": "2022-05-31T20:59:12+00:00", - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.9-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.14.0" - }, - "install-path": "../nikic/php-parser" - }, - { - "name": "paragonie/random_compat", - "version": "v9.99.100", - "version_normalized": "9.99.100.0", - "source": { - "type": "git", - "url": "https://github.com/paragonie/random_compat.git", - "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a", - "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a", - "shasum": "" - }, - "require": { - "php": ">= 7" - }, - "require-dev": { - "phpunit/phpunit": "4.*|5.*", - "vimeo/psalm": "^1" - }, - "suggest": { - "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." - }, - "time": "2020-10-15T08:29:30+00:00", - "type": "library", - "installation-source": "dist", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com", - "homepage": "https://paragonie.com" - } - ], - "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", - "keywords": [ - "csprng", - "polyfill", - "pseudorandom", - "random" - ], - "support": { - "email": "info@paragonie.com", - "issues": "https://github.com/paragonie/random_compat/issues", - "source": "https://github.com/paragonie/random_compat" - }, - "install-path": "../paragonie/random_compat" - }, - { - "name": "pear/archive_tar", - "version": "1.4.14", - "version_normalized": "1.4.14.0", - "source": { - "type": "git", - "url": "https://github.com/pear/Archive_Tar.git", - "reference": "4d761c5334c790e45ef3245f0864b8955c562caa" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/pear/Archive_Tar/zipball/4d761c5334c790e45ef3245f0864b8955c562caa", - "reference": "4d761c5334c790e45ef3245f0864b8955c562caa", - "shasum": "" - }, - "require": { - "pear/pear-core-minimal": "^1.10.0alpha2", - "php": ">=5.2.0" - }, - "require-dev": { - "phpunit/phpunit": "*" - }, - "suggest": { - "ext-bz2": "Bz2 compression support.", - "ext-xz": "Lzma2 compression support.", - "ext-zlib": "Gzip compression support." - }, - "time": "2021-07-20T13:53:39+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-0": { - "Archive_Tar": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "./" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Vincent Blavet", - "email": "vincent@phpconcept.net" - }, - { - "name": "Greg Beaver", - "email": "greg@chiaraquartet.net" - }, - { - "name": "Michiel Rook", - "email": "mrook@php.net" - } - ], - "description": "Tar file management class with compression support (gzip, bzip2, lzma2)", - "homepage": "https://github.com/pear/Archive_Tar", - "keywords": [ - "archive", - "tar" - ], - "support": { - "issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=Archive_Tar", - "source": "https://github.com/pear/Archive_Tar" - }, - "funding": [ - { - "url": "https://github.com/mrook", - "type": "github" - }, - { - "url": "https://www.patreon.com/michielrook", - "type": "patreon" - } - ], - "install-path": "../pear/archive_tar" - }, - { - "name": "pear/console_getopt", - "version": "v1.4.3", - "version_normalized": "1.4.3.0", - "source": { - "type": "git", - "url": "https://github.com/pear/Console_Getopt.git", - "reference": "a41f8d3e668987609178c7c4a9fe48fecac53fa0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/pear/Console_Getopt/zipball/a41f8d3e668987609178c7c4a9fe48fecac53fa0", - "reference": "a41f8d3e668987609178c7c4a9fe48fecac53fa0", - "shasum": "" - }, - "time": "2019-11-20T18:27:48+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-0": { - "Console": "./" - } - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "./" - ], - "license": [ - "BSD-2-Clause" - ], - "authors": [ - { - "name": "Andrei Zmievski", - "email": "andrei@php.net", - "role": "Lead" - }, - { - "name": "Stig Bakken", - "email": "stig@php.net", - "role": "Developer" - }, - { - "name": "Greg Beaver", - "email": "cellog@php.net", - "role": "Helper" - } - ], - "description": "More info available on: http://pear.php.net/package/Console_Getopt", - "support": { - "issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=Console_Getopt", - "source": "https://github.com/pear/Console_Getopt" - }, - "install-path": "../pear/console_getopt" - }, - { - "name": "pear/pear-core-minimal", - "version": "v1.10.11", - "version_normalized": "1.10.11.0", - "source": { - "type": "git", - "url": "https://github.com/pear/pear-core-minimal.git", - "reference": "68d0d32ada737153b7e93b8d3c710ebe70ac867d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/pear/pear-core-minimal/zipball/68d0d32ada737153b7e93b8d3c710ebe70ac867d", - "reference": "68d0d32ada737153b7e93b8d3c710ebe70ac867d", - "shasum": "" - }, - "require": { - "pear/console_getopt": "~1.4", - "pear/pear_exception": "~1.0" - }, - "replace": { - "rsky/pear-core-min": "self.version" - }, - "time": "2021-08-10T22:31:03+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-0": { - "": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "src/" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Christian Weiske", - "email": "cweiske@php.net", - "role": "Lead" - } - ], - "description": "Minimal set of PEAR core files to be used as composer dependency", - "support": { - "issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=PEAR", - "source": "https://github.com/pear/pear-core-minimal" - }, - "install-path": "../pear/pear-core-minimal" - }, - { - "name": "pear/pear_exception", - "version": "v1.0.2", - "version_normalized": "1.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/pear/PEAR_Exception.git", - "reference": "b14fbe2ddb0b9f94f5b24cf08783d599f776fff0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/pear/PEAR_Exception/zipball/b14fbe2ddb0b9f94f5b24cf08783d599f776fff0", - "reference": "b14fbe2ddb0b9f94f5b24cf08783d599f776fff0", - "shasum": "" - }, - "require": { - "php": ">=5.2.0" - }, - "require-dev": { - "phpunit/phpunit": "<9" - }, - "time": "2021-03-21T15:43:46+00:00", - "type": "class", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "PEAR/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "." - ], - "license": [ - "BSD-2-Clause" - ], - "authors": [ - { - "name": "Helgi Thormar", - "email": "dufuz@php.net" - }, - { - "name": "Greg Beaver", - "email": "cellog@php.net" - } - ], - "description": "The PEAR Exception base class.", - "homepage": "https://github.com/pear/PEAR_Exception", - "keywords": [ - "exception" - ], - "support": { - "issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=PEAR_Exception", - "source": "https://github.com/pear/PEAR_Exception" - }, - "install-path": "../pear/pear_exception" - }, - { - "name": "pelago/emogrifier", - "version": "v6.0.0", - "version_normalized": "6.0.0.0", - "source": { - "type": "git", - "url": "https://github.com/MyIntervals/emogrifier.git", - "reference": "aa72d5407efac118f3896bcb995a2cba793df0ae" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/MyIntervals/emogrifier/zipball/aa72d5407efac118f3896bcb995a2cba793df0ae", - "reference": "aa72d5407efac118f3896bcb995a2cba793df0ae", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "php": "~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0", - "sabberworm/php-css-parser": "^8.3.1", - "symfony/css-selector": "^3.4.32 || ^4.4 || ^5.3 || ^6.0" - }, - "require-dev": { - "php-parallel-lint/php-parallel-lint": "^1.3.0", - "phpunit/phpunit": "^8.5.16", - "rawr/cross-data-providers": "^2.3.0" - }, - "time": "2021-09-16T16:22:04+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "7.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Pelago\\Emogrifier\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Oliver Klee", - "email": "github@oliverklee.de" - }, - { - "name": "Zoli Szabó", - "email": "zoli.szabo+github@gmail.com" - }, - { - "name": "John Reeve", - "email": "jreeve@pelagodesign.com" - }, - { - "name": "Jake Hotson", - "email": "jake@qzdesign.co.uk" - }, - { - "name": "Cameron Brooks" - }, - { - "name": "Jaime Prado" - } - ], - "description": "Converts CSS styles into inline style attributes in your HTML code", - "homepage": "https://www.myintervals.com/emogrifier.php", - "keywords": [ - "css", - "email", - "pre-processing" - ], - "support": { - "issues": "https://github.com/MyIntervals/emogrifier/issues", - "source": "https://github.com/MyIntervals/emogrifier" - }, - "install-path": "../pelago/emogrifier" - }, - { - "name": "psr/cache", - "version": "1.0.1", - "version_normalized": "1.0.1.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "time": "2016-08-06T20:24:11+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Cache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for caching libraries", - "keywords": [ - "cache", - "psr", - "psr-6" - ], - "install-path": "../psr/cache" - }, - { - "name": "psr/container", - "version": "1.1.2", - "version_normalized": "1.1.2.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "time": "2021-11-05T16:50:12+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.2" - }, - "install-path": "../psr/container" - }, - { - "name": "psr/event-dispatcher", - "version": "1.0.0", - "version_normalized": "1.0.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/event-dispatcher.git", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", - "shasum": "" - }, - "require": { - "php": ">=7.2.0" - }, - "time": "2019-01-08T18:20:26+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\EventDispatcher\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Standard interfaces for event handling.", - "keywords": [ - "events", - "psr", - "psr-14" - ], - "support": { - "issues": "https://github.com/php-fig/event-dispatcher/issues", - "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" - }, - "install-path": "../psr/event-dispatcher" - }, - { - "name": "psr/http-client", - "version": "1.0.2", - "version_normalized": "1.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-client.git", - "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/0955afe48220520692d2d09f7ab7e0f93ffd6a31", - "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31", - "shasum": "" - }, - "require": { - "php": "^7.0 || ^8.0", - "psr/http-message": "^1.0 || ^2.0" - }, - "time": "2023-04-10T20:12:12+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Http\\Client\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP clients", - "homepage": "https://github.com/php-fig/http-client", - "keywords": [ - "http", - "http-client", - "psr", - "psr-18" - ], - "support": { - "source": "https://github.com/php-fig/http-client/tree/1.0.2" - }, - "install-path": "../psr/http-client" - }, - { - "name": "psr/http-factory", - "version": "1.0.2", - "version_normalized": "1.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-factory.git", - "reference": "e616d01114759c4c489f93b099585439f795fe35" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", - "reference": "e616d01114759c4c489f93b099585439f795fe35", - "shasum": "" - }, - "require": { - "php": ">=7.0.0", - "psr/http-message": "^1.0 || ^2.0" - }, - "time": "2023-04-10T20:10:41+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interfaces for PSR-7 HTTP message factories", - "keywords": [ - "factory", - "http", - "message", - "psr", - "psr-17", - "psr-7", - "request", - "response" - ], - "support": { - "source": "https://github.com/php-fig/http-factory/tree/1.0.2" - }, - "install-path": "../psr/http-factory" - }, - { - "name": "psr/http-message", - "version": "2.0", - "version_normalized": "2.0.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "time": "2023-04-04T09:54:51+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "support": { - "source": "https://github.com/php-fig/http-message/tree/2.0" - }, - "install-path": "../psr/http-message" - }, - { - "name": "psr/log", - "version": "1.1.4", - "version_normalized": "1.1.4.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "time": "2021-05-03T11:20:27+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "support": { - "source": "https://github.com/php-fig/log/tree/1.1.4" - }, - "install-path": "../psr/log" - }, - { - "name": "ralouphie/getallheaders", - "version": "3.0.3", - "version_normalized": "3.0.3.0", - "source": { - "type": "git", - "url": "https://github.com/ralouphie/getallheaders.git", - "reference": "120b605dfeb996808c31b6477290a714d356e822" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", - "reference": "120b605dfeb996808c31b6477290a714d356e822", - "shasum": "" - }, - "require": { - "php": ">=5.6" - }, - "require-dev": { - "php-coveralls/php-coveralls": "^2.1", - "phpunit/phpunit": "^5 || ^6.5" - }, - "time": "2019-03-08T08:55:37+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "files": [ - "src/getallheaders.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ralph Khattar", - "email": "ralph.khattar@gmail.com" - } - ], - "description": "A polyfill for getallheaders.", - "support": { - "issues": "https://github.com/ralouphie/getallheaders/issues", - "source": "https://github.com/ralouphie/getallheaders/tree/develop" - }, - "install-path": "../ralouphie/getallheaders" - }, - { - "name": "sabberworm/php-css-parser", - "version": "8.4.0", - "version_normalized": "8.4.0.0", - "source": { - "type": "git", - "url": "https://github.com/sabberworm/PHP-CSS-Parser.git", - "reference": "e41d2140031d533348b2192a83f02d8dd8a71d30" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sabberworm/PHP-CSS-Parser/zipball/e41d2140031d533348b2192a83f02d8dd8a71d30", - "reference": "e41d2140031d533348b2192a83f02d8dd8a71d30", - "shasum": "" - }, - "require": { - "ext-iconv": "*", - "php": ">=5.6.20" - }, - "require-dev": { - "codacy/coverage": "^1.4", - "phpunit/phpunit": "^4.8.36" - }, - "suggest": { - "ext-mbstring": "for parsing UTF-8 CSS" - }, - "time": "2021-12-11T13:40:54+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Sabberworm\\CSS\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Raphael Schweikert" - } - ], - "description": "Parser for CSS Files written in PHP", - "homepage": "https://www.sabberworm.com/blog/2010/6/10/php-css-parser", - "keywords": [ - "css", - "parser", - "stylesheet" - ], - "support": { - "issues": "https://github.com/sabberworm/PHP-CSS-Parser/issues", - "source": "https://github.com/sabberworm/PHP-CSS-Parser/tree/8.4.0" - }, - "install-path": "../sabberworm/php-css-parser" - }, - { - "name": "scssphp/scssphp", - "version": "v1.10.5", - "version_normalized": "1.10.5.0", - "source": { - "type": "git", - "url": "https://github.com/scssphp/scssphp.git", - "reference": "6d44282ccf283e133ab70b6282f8e068ff2f9bf9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/scssphp/scssphp/zipball/6d44282ccf283e133ab70b6282f8e068ff2f9bf9", - "reference": "6d44282ccf283e133ab70b6282f8e068ff2f9bf9", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "ext-json": "*", - "php": ">=5.6.0" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.4", - "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.3 || ^9.4", - "sass/sass-spec": "*", - "squizlabs/php_codesniffer": "~3.5", - "symfony/phpunit-bridge": "^5.1", - "thoughtbot/bourbon": "^7.0", - "twbs/bootstrap": "~5.0", - "twbs/bootstrap4": "4.6.1", - "zurb/foundation": "~6.5" - }, - "suggest": { - "ext-iconv": "Can be used as fallback when ext-mbstring is not available", - "ext-mbstring": "For best performance, mbstring should be installed as it is faster than ext-iconv" - }, - "time": "2022-07-27T15:52:39+00:00", - "bin": [ - "bin/pscss" - ], - "type": "library", - "extra": { - "bamarni-bin": { - "forward-command": false, - "bin-links": false - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "ScssPhp\\ScssPhp\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Anthon Pang", - "email": "apang@softwaredevelopment.ca", - "homepage": "https://github.com/robocoder" - }, - { - "name": "Cédric Morin", - "email": "cedric@yterium.com", - "homepage": "https://github.com/Cerdic" - } - ], - "description": "scssphp is a compiler for SCSS written in PHP.", - "homepage": "http://scssphp.github.io/scssphp/", - "keywords": [ - "css", - "less", - "sass", - "scss", - "stylesheet" - ], - "support": { - "issues": "https://github.com/scssphp/scssphp/issues", - "source": "https://github.com/scssphp/scssphp/tree/v1.10.5" - }, - "install-path": "../scssphp/scssphp" - }, - { - "name": "symfony/cache", - "version": "v5.4.11", - "version_normalized": "5.4.11.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/cache.git", - "reference": "5a0fff46df349f0db3fe242263451fddf5277362" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/5a0fff46df349f0db3fe242263451fddf5277362", - "reference": "5a0fff46df349f0db3fe242263451fddf5277362", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/cache": "^1.0|^2.0", - "psr/log": "^1.1|^2|^3", - "symfony/cache-contracts": "^1.1.7|^2", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/var-exporter": "^4.4|^5.0|^6.0" - }, - "conflict": { - "doctrine/dbal": "<2.13.1", - "symfony/dependency-injection": "<4.4", - "symfony/http-kernel": "<4.4", - "symfony/var-dumper": "<4.4" - }, - "provide": { - "psr/cache-implementation": "1.0|2.0", - "psr/simple-cache-implementation": "1.0|2.0", - "symfony/cache-implementation": "1.0|2.0" - }, - "require-dev": { - "cache/integration-tests": "dev-master", - "doctrine/cache": "^1.6|^2.0", - "doctrine/dbal": "^2.13.1|^3.0", - "predis/predis": "^1.1", - "psr/simple-cache": "^1.0|^2.0", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/filesystem": "^4.4|^5.0|^6.0", - "symfony/http-kernel": "^4.4|^5.0|^6.0", - "symfony/messenger": "^4.4|^5.0|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0" - }, - "time": "2022-07-28T15:25:17+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Cache\\": "" - }, - "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 extended PSR-6, PSR-16 (and tags) implementation", - "homepage": "https://symfony.com", - "keywords": [ - "caching", - "psr6" - ], - "support": { - "source": "https://github.com/symfony/cache/tree/v5.4.11" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/cache" - }, - { - "name": "symfony/cache-contracts", - "version": "v2.5.2", - "version_normalized": "2.5.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/cache-contracts.git", - "reference": "64be4a7acb83b6f2bf6de9a02cee6dad41277ebc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/64be4a7acb83b6f2bf6de9a02cee6dad41277ebc", - "reference": "64be4a7acb83b6f2bf6de9a02cee6dad41277ebc", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/cache": "^1.0|^2.0|^3.0" - }, - "suggest": { - "symfony/cache-implementation": "" - }, - "time": "2022-01-02T09:53:40+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Cache\\": "" - } - }, - "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 caching", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/cache-contracts/tree/v2.5.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/cache-contracts" - }, - { - "name": "symfony/config", - "version": "v5.4.11", - "version_normalized": "5.4.11.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/config.git", - "reference": "ec79e03125c1d2477e43dde8528535d90cc78379" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/ec79e03125c1d2477e43dde8528535d90cc78379", - "reference": "ec79e03125c1d2477e43dde8528535d90cc78379", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/filesystem": "^4.4|^5.0|^6.0", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-php80": "^1.16", - "symfony/polyfill-php81": "^1.22" - }, - "conflict": { - "symfony/finder": "<4.4" - }, - "require-dev": { - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/finder": "^4.4|^5.0|^6.0", - "symfony/messenger": "^4.4|^5.0|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/yaml": "^4.4|^5.0|^6.0" - }, - "suggest": { - "symfony/yaml": "To use the yaml reference dumper" - }, - "time": "2022-07-20T13:00:38+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Config\\": "" - }, - "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": "Helps you find, load, combine, autofill and validate configuration values of any kind", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/config/tree/v5.4.11" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/config" - }, - { - "name": "symfony/console", - "version": "v5.4.19", - "version_normalized": "5.4.19.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "dccb8d251a9017d5994c988b034d3e18aaabf740" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/dccb8d251a9017d5994c988b034d3e18aaabf740", - "reference": "dccb8d251a9017d5994c988b034d3e18aaabf740", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.1|^6.0" - }, - "conflict": { - "psr/log": ">=3", - "symfony/dependency-injection": "<4.4", - "symfony/dotenv": "<5.1", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" - }, - "provide": { - "psr/log-implementation": "1.0|2.0" - }, - "require-dev": { - "psr/log": "^1|^2", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/lock": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, - "time": "2023-01-01T08:32:19+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Eases the creation of beautiful and testable command line interfaces", - "homepage": "https://symfony.com", - "keywords": [ - "cli", - "command line", - "console", - "terminal" - ], - "support": { - "source": "https://github.com/symfony/console/tree/v5.4.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" - } - ], - "install-path": "../symfony/console" - }, - { - "name": "symfony/css-selector", - "version": "v5.4.11", - "version_normalized": "5.4.11.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/css-selector.git", - "reference": "c1681789f059ab756001052164726ae88512ae3d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/c1681789f059ab756001052164726ae88512ae3d", - "reference": "c1681789f059ab756001052164726ae88512ae3d", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" - }, - "time": "2022-06-27T16:58:25+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\CssSelector\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Jean-François Simon", - "email": "jeanfrancois.simon@sensiolabs.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Converts CSS selectors to XPath expressions", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/css-selector/tree/v5.4.11" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/css-selector" - }, - { - "name": "symfony/dependency-injection", - "version": "v5.4.11", - "version_normalized": "5.4.11.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/dependency-injection.git", - "reference": "a8b9251016e9476db73e25fa836904bc0bf74c62" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/a8b9251016e9476db73e25fa836904bc0bf74c62", - "reference": "a8b9251016e9476db73e25fa836904bc0bf74c62", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/container": "^1.1.1", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16", - "symfony/polyfill-php81": "^1.22", - "symfony/service-contracts": "^1.1.6|^2" - }, - "conflict": { - "ext-psr": "<1.1|>=2", - "symfony/config": "<5.3", - "symfony/finder": "<4.4", - "symfony/proxy-manager-bridge": "<4.4", - "symfony/yaml": "<4.4.26" - }, - "provide": { - "psr/container-implementation": "1.0", - "symfony/service-implementation": "1.0|2.0" - }, - "require-dev": { - "symfony/config": "^5.3|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/yaml": "^4.4.26|^5.0|^6.0" - }, - "suggest": { - "symfony/config": "", - "symfony/expression-language": "For using expressions in service container configuration", - "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", - "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", - "symfony/yaml": "" - }, - "time": "2022-07-20T13:00:38+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\DependencyInjection\\": "" - }, - "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": "Allows you to standardize and centralize the way objects are constructed in your application", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v5.4.11" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/dependency-injection" - }, - { - "name": "symfony/deprecation-contracts", - "version": "v2.5.2", - "version_normalized": "2.5.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "time": "2022-01-02T09:53:40+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "function.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/deprecation-contracts" - }, - { - "name": "symfony/dotenv", - "version": "v5.4.19", - "version_normalized": "5.4.19.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/dotenv.git", - "reference": "38190ba62566afa26ca723a795d0a004e061bd2a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/38190ba62566afa26ca723a795d0a004e061bd2a", - "reference": "38190ba62566afa26ca723a795d0a004e061bd2a", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3" - }, - "require-dev": { - "symfony/console": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0" - }, - "time": "2023-01-01T08:32:19+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Dotenv\\": "" - }, - "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": "Registers environment variables from a .env file", - "homepage": "https://symfony.com", - "keywords": [ - "dotenv", - "env", - "environment" - ], - "support": { - "source": "https://github.com/symfony/dotenv/tree/v5.4.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" - } - ], - "install-path": "../symfony/dotenv" - }, - { - "name": "symfony/error-handler", - "version": "v5.4.11", - "version_normalized": "5.4.11.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/error-handler.git", - "reference": "f75d17cb4769eb38cd5fccbda95cd80a054d35c8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/f75d17cb4769eb38cd5fccbda95cd80a054d35c8", - "reference": "f75d17cb4769eb38cd5fccbda95cd80a054d35c8", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^4.4|^5.0|^6.0" - }, - "require-dev": { - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/http-kernel": "^4.4|^5.0|^6.0", - "symfony/serializer": "^4.4|^5.0|^6.0" - }, - "time": "2022-07-29T07:37:50+00:00", - "bin": [ - "Resources/bin/patch-type-declarations" - ], - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\ErrorHandler\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides tools to manage errors and ease debugging PHP code", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/error-handler/tree/v5.4.11" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/error-handler" - }, - { - "name": "symfony/event-dispatcher", - "version": "v5.4.9", - "version_normalized": "5.4.9.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "8e6ce1cc0279e3ff3c8ff0f43813bc88d21ca1bc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/8e6ce1cc0279e3ff3c8ff0f43813bc88d21ca1bc", - "reference": "8e6ce1cc0279e3ff3c8ff0f43813bc88d21ca1bc", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/event-dispatcher-contracts": "^2|^3", - "symfony/polyfill-php80": "^1.16" - }, - "conflict": { - "symfony/dependency-injection": "<4.4" - }, - "provide": { - "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/stopwatch": "^4.4|^5.0|^6.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "time": "2022-05-05T16:45:39+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.9" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/event-dispatcher" - }, - { - "name": "symfony/event-dispatcher-contracts", - "version": "v2.5.2", - "version_normalized": "2.5.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/f98b54df6ad059855739db6fcbc2d36995283fe1", - "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/event-dispatcher": "^1" - }, - "suggest": { - "symfony/event-dispatcher-implementation": "" - }, - "time": "2022-01-02T09:53:40+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Contracts\\EventDispatcher\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to dispatching event", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/event-dispatcher-contracts" - }, - { - "name": "symfony/filesystem", - "version": "v5.4.11", - "version_normalized": "5.4.11.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "6699fb0228d1bc35b12aed6dd5e7455457609ddd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/6699fb0228d1bc35b12aed6dd5e7455457609ddd", - "reference": "6699fb0228d1bc35b12aed6dd5e7455457609ddd", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8", - "symfony/polyfill-php80": "^1.16" - }, - "time": "2022-07-20T13:00:38+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides basic utilities for the filesystem", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.4.11" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/filesystem" - }, - { - "name": "symfony/finder", - "version": "v5.4.11", - "version_normalized": "5.4.11.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "7872a66f57caffa2916a584db1aa7f12adc76f8c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/7872a66f57caffa2916a584db1aa7f12adc76f8c", - "reference": "7872a66f57caffa2916a584db1aa7f12adc76f8c", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16" - }, - "time": "2022-07-29T07:37:50+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Finds files and directories via an intuitive fluent interface", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/finder/tree/v5.4.11" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/finder" - }, - { - "name": "symfony/form", - "version": "v5.4.19", - "version_normalized": "5.4.19.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/form.git", - "reference": "c29e6cccee469ca93db2dbc02a39c29312c5e362" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/form/zipball/c29e6cccee469ca93db2dbc02a39c29312c5e362", - "reference": "c29e6cccee469ca93db2dbc02a39c29312c5e362", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/options-resolver": "^5.1|^6.0", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-icu": "^1.21", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "^1.16", - "symfony/polyfill-php81": "^1.23", - "symfony/property-access": "^5.0.8|^6.0", - "symfony/service-contracts": "^1.1|^2|^3" - }, - "conflict": { - "phpunit/phpunit": "<5.4.3", - "symfony/console": "<4.4", - "symfony/dependency-injection": "<4.4", - "symfony/doctrine-bridge": "<4.4", - "symfony/error-handler": "<4.4.5", - "symfony/framework-bundle": "<4.4", - "symfony/http-kernel": "<4.4", - "symfony/translation": "<4.4", - "symfony/translation-contracts": "<1.1.7", - "symfony/twig-bridge": "<4.4" - }, - "require-dev": { - "doctrine/collections": "^1.0|^2.0", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/console": "^5.4|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", - "symfony/http-kernel": "^4.4|^5.0|^6.0", - "symfony/intl": "^4.4|^5.0|^6.0", - "symfony/security-csrf": "^4.4|^5.0|^6.0", - "symfony/translation": "^4.4|^5.0|^6.0", - "symfony/uid": "^5.1|^6.0", - "symfony/validator": "^4.4.17|^5.1.9|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0" - }, - "suggest": { - "symfony/security-csrf": "For protecting forms against CSRF attacks.", - "symfony/twig-bridge": "For templating with Twig.", - "symfony/validator": "For form validation." - }, - "time": "2023-01-01T08:32:19+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Form\\": "" - }, - "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": "Allows to easily create, process and reuse HTML forms", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/form/tree/v5.4.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" - } - ], - "install-path": "../symfony/form" - }, - { - "name": "symfony/framework-bundle", - "version": "v5.4.19", - "version_normalized": "5.4.19.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/framework-bundle.git", - "reference": "a208ee578000f9dedcb50a9784ec7ff8706a7bf1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/a208ee578000f9dedcb50a9784ec7ff8706a7bf1", - "reference": "a208ee578000f9dedcb50a9784ec7ff8706a7bf1", - "shasum": "" - }, - "require": { - "ext-xml": "*", - "php": ">=7.2.5", - "symfony/cache": "^5.2|^6.0", - "symfony/config": "^5.3|^6.0", - "symfony/dependency-injection": "^5.4.5|^6.0.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/error-handler": "^4.4.1|^5.0.1|^6.0", - "symfony/event-dispatcher": "^5.1|^6.0", - "symfony/filesystem": "^4.4|^5.0|^6.0", - "symfony/finder": "^4.4|^5.0|^6.0", - "symfony/http-foundation": "^5.3|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "^1.16", - "symfony/polyfill-php81": "^1.22", - "symfony/routing": "^5.3|^6.0" - }, - "conflict": { - "doctrine/annotations": "<1.13.1", - "doctrine/cache": "<1.11", - "doctrine/persistence": "<1.3", - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", - "phpunit/phpunit": "<5.4.3", - "symfony/asset": "<5.3", - "symfony/console": "<5.2.5", - "symfony/dom-crawler": "<4.4", - "symfony/dotenv": "<5.1", - "symfony/form": "<5.2", - "symfony/http-client": "<4.4", - "symfony/lock": "<4.4", - "symfony/mailer": "<5.2", - "symfony/messenger": "<5.4", - "symfony/mime": "<4.4", - "symfony/property-access": "<5.3", - "symfony/property-info": "<4.4", - "symfony/security-csrf": "<5.3", - "symfony/serializer": "<5.2", - "symfony/service-contracts": ">=3.0", - "symfony/stopwatch": "<4.4", - "symfony/translation": "<5.3", - "symfony/twig-bridge": "<4.4", - "symfony/twig-bundle": "<4.4", - "symfony/validator": "<5.2", - "symfony/web-profiler-bundle": "<4.4", - "symfony/workflow": "<5.2" - }, - "require-dev": { - "doctrine/annotations": "^1.13.1|^2", - "doctrine/cache": "^1.11|^2.0", - "doctrine/persistence": "^1.3|^2|^3", - "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/asset": "^5.3|^6.0", - "symfony/browser-kit": "^5.4|^6.0", - "symfony/console": "^5.4.9|^6.0.9", - "symfony/css-selector": "^4.4|^5.0|^6.0", - "symfony/dom-crawler": "^4.4.30|^5.3.7|^6.0", - "symfony/dotenv": "^5.1|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/form": "^5.2|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/lock": "^4.4|^5.0|^6.0", - "symfony/mailer": "^5.2|^6.0", - "symfony/messenger": "^5.4|^6.0", - "symfony/mime": "^4.4|^5.0|^6.0", - "symfony/notifier": "^5.4|^6.0", - "symfony/polyfill-intl-icu": "~1.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/property-info": "^4.4|^5.0|^6.0", - "symfony/rate-limiter": "^5.2|^6.0", - "symfony/security-bundle": "^5.4|^6.0", - "symfony/serializer": "^5.4|^6.0", - "symfony/stopwatch": "^4.4|^5.0|^6.0", - "symfony/string": "^5.0|^6.0", - "symfony/translation": "^5.3|^6.0", - "symfony/twig-bundle": "^4.4|^5.0|^6.0", - "symfony/validator": "^5.2|^6.0", - "symfony/web-link": "^4.4|^5.0|^6.0", - "symfony/workflow": "^5.2|^6.0", - "symfony/yaml": "^4.4|^5.0|^6.0", - "twig/twig": "^2.10|^3.0" - }, - "suggest": { - "ext-apcu": "For best performance of the system caches", - "symfony/console": "For using the console commands", - "symfony/form": "For using forms", - "symfony/property-info": "For using the property_info service", - "symfony/serializer": "For using the serializer service", - "symfony/validator": "For using validation", - "symfony/web-link": "For using web links, features such as preloading, prefetching or prerendering", - "symfony/yaml": "For using the debug:config and lint:yaml commands" - }, - "time": "2023-01-10T17:40:25+00:00", - "type": "symfony-bundle", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Bundle\\FrameworkBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/framework-bundle/tree/v5.4.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" - } - ], - "install-path": "../symfony/framework-bundle" - }, - { - "name": "symfony/http-foundation", - "version": "v5.4.20", - "version_normalized": "5.4.20.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-foundation.git", - "reference": "d0435363362a47c14e9cf50663cb8ffbf491875a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/d0435363362a47c14e9cf50663cb8ffbf491875a", - "reference": "d0435363362a47c14e9cf50663cb8ffbf491875a", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-mbstring": "~1.1", - "symfony/polyfill-php80": "^1.16" - }, - "require-dev": { - "predis/predis": "~1.0", - "symfony/cache": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4", - "symfony/mime": "^4.4|^5.0|^6.0", - "symfony/rate-limiter": "^5.2|^6.0" - }, - "suggest": { - "symfony/mime": "To use the file extension guesser" - }, - "time": "2023-01-29T11:11:52+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpFoundation\\": "" - }, - "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": "Defines an object-oriented layer for the HTTP specification", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/http-foundation/tree/v5.4.20" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/http-foundation" - }, - { - "name": "symfony/http-kernel", - "version": "v5.4.20", - "version_normalized": "5.4.20.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-kernel.git", - "reference": "aaeec341582d3c160cc9ecfa8b2419ba6c69954e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/aaeec341582d3c160cc9ecfa8b2419ba6c69954e", - "reference": "aaeec341582d3c160cc9ecfa8b2419ba6c69954e", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/log": "^1|^2", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/event-dispatcher": "^5.0|^6.0", - "symfony/http-foundation": "^5.3.7|^6.0", - "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16" - }, - "conflict": { - "symfony/browser-kit": "<5.4", - "symfony/cache": "<5.0", - "symfony/config": "<5.0", - "symfony/console": "<4.4", - "symfony/dependency-injection": "<5.3", - "symfony/doctrine-bridge": "<5.0", - "symfony/form": "<5.0", - "symfony/http-client": "<5.0", - "symfony/mailer": "<5.0", - "symfony/messenger": "<5.0", - "symfony/translation": "<5.0", - "symfony/twig-bridge": "<5.0", - "symfony/validator": "<5.0", - "twig/twig": "<2.13" - }, - "provide": { - "psr/log-implementation": "1.0|2.0" - }, - "require-dev": { - "psr/cache": "^1.0|^2.0|^3.0", - "symfony/browser-kit": "^5.4|^6.0", - "symfony/config": "^5.0|^6.0", - "symfony/console": "^4.4|^5.0|^6.0", - "symfony/css-selector": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^5.3|^6.0", - "symfony/dom-crawler": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/finder": "^4.4|^5.0|^6.0", - "symfony/http-client-contracts": "^1.1|^2|^3", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/routing": "^4.4|^5.0|^6.0", - "symfony/stopwatch": "^4.4|^5.0|^6.0", - "symfony/translation": "^4.4|^5.0|^6.0", - "symfony/translation-contracts": "^1.1|^2|^3", - "twig/twig": "^2.13|^3.0.4" - }, - "suggest": { - "symfony/browser-kit": "", - "symfony/config": "", - "symfony/console": "", - "symfony/dependency-injection": "" - }, - "time": "2023-02-01T08:18:48+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpKernel\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a structured process for converting a Request into a Response", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/http-kernel/tree/v5.4.20" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/http-kernel" - }, - { - "name": "symfony/options-resolver", - "version": "v5.4.21", - "version_normalized": "5.4.21.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/options-resolver.git", - "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", - "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php73": "~1.0", - "symfony/polyfill-php80": "^1.16" - }, - "time": "2023-02-14T08:03:56+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\OptionsResolver\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an improved replacement for the array_replace PHP function", - "homepage": "https://symfony.com", - "keywords": [ - "config", - "configuration", - "options" - ], - "support": { - "source": "https://github.com/symfony/options-resolver/tree/v5.4.21" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/options-resolver" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.26.0", - "version_normalized": "1.26.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", - "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-ctype": "*" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "time": "2022-05-24T11:49:31+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/polyfill-ctype" - }, - { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.26.0", - "version_normalized": "1.26.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "433d05519ce6990bf3530fba6957499d327395c2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2", - "reference": "433d05519ce6990bf3530fba6957499d327395c2", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "time": "2022-05-24T11:49:31+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's grapheme_* functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "grapheme", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/polyfill-intl-grapheme" - }, - { - "name": "symfony/polyfill-intl-icu", - "version": "v1.27.0", - "version_normalized": "1.27.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-icu.git", - "reference": "a3d9148e2c363588e05abbdd4ee4f971f0a5330c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/a3d9148e2c363588e05abbdd4ee4f971f0a5330c", - "reference": "a3d9148e2c363588e05abbdd4ee4f971f0a5330c", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance and support of other locales than \"en\"" - }, - "time": "2022-11-03T14:55:06+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Icu\\": "" - }, - "classmap": [ - "Resources/stubs" - ], - "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": "Symfony polyfill for intl's ICU-related data and classes", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "icu", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.27.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/polyfill-intl-icu" - }, - { - "name": "symfony/polyfill-intl-idn", - "version": "v1.26.0", - "version_normalized": "1.26.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/59a8d271f00dd0e4c2e518104cc7963f655a1aa8", - "reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8", - "shasum": "" - }, - "require": { - "php": ">=7.1", - "symfony/polyfill-intl-normalizer": "^1.10", - "symfony/polyfill-php72": "^1.10" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "time": "2022-05-24T11:49:31+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Idn\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Laurent Bassin", - "email": "laurent@bassin.info" - }, - { - "name": "Trevor Rowbotham", - "email": "trevor.rowbotham@pm.me" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "idn", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/polyfill-intl-idn" - }, - { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.26.0", - "version_normalized": "1.26.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "219aa369ceff116e673852dce47c3a41794c14bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd", - "reference": "219aa369ceff116e673852dce47c3a41794c14bd", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "time": "2022-05-24T11:49:31+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "intl", - "normalizer", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/polyfill-intl-normalizer" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.26.0", - "version_normalized": "1.26.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", - "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "time": "2022-05-24T11:49:31+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/polyfill-mbstring" - }, - { - "name": "symfony/polyfill-php72", - "version": "v1.26.0", - "version_normalized": "1.26.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/bf44a9fd41feaac72b074de600314a93e2ae78e2", - "reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "time": "2022-05-24T11:49:31+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php72\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/polyfill-php72" - }, - { - "name": "symfony/polyfill-php73", - "version": "v1.26.0", - "version_normalized": "1.26.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/e440d35fa0286f77fb45b79a03fedbeda9307e85", - "reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "time": "2022-05-24T11:49:31+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/polyfill-php73" - }, - { - "name": "symfony/polyfill-php80", - "version": "v1.26.0", - "version_normalized": "1.26.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace", - "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "time": "2022-05-10T07:21:04+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/polyfill-php80" - }, - { - "name": "symfony/polyfill-php81", - "version": "v1.26.0", - "version_normalized": "1.26.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/13f6d1271c663dc5ae9fb843a8f16521db7687a1", - "reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "time": "2022-05-24T11:49:31+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php81\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/polyfill-php81" - }, - { - "name": "symfony/property-access", - "version": "v5.4.22", - "version_normalized": "5.4.22.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/property-access.git", - "reference": "ffee082889586b5718347b291e04071f4d07b38f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/property-access/zipball/ffee082889586b5718347b291e04071f4d07b38f", - "reference": "ffee082889586b5718347b291e04071f4d07b38f", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16", - "symfony/property-info": "^5.2|^6.0" - }, - "require-dev": { - "symfony/cache": "^4.4|^5.0|^6.0" - }, - "suggest": { - "psr/cache-implementation": "To cache access methods." - }, - "time": "2023-03-14T14:59:20+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\PropertyAccess\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides functions to read and write from/to an object or array using a simple string notation", - "homepage": "https://symfony.com", - "keywords": [ - "access", - "array", - "extraction", - "index", - "injection", - "object", - "property", - "property-path", - "reflection" - ], - "support": { - "source": "https://github.com/symfony/property-access/tree/v5.4.22" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/property-access" - }, - { - "name": "symfony/property-info", - "version": "v5.4.24", - "version_normalized": "5.4.24.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/property-info.git", - "reference": "d43b85b00699b4484964c297575b5c6f9dc5f6e1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/d43b85b00699b4484964c297575b5c6f9dc5f6e1", - "reference": "d43b85b00699b4484964c297575b5c6f9dc5f6e1", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16", - "symfony/string": "^5.1|^6.0" - }, - "conflict": { - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", - "symfony/dependency-injection": "<4.4" - }, - "require-dev": { - "doctrine/annotations": "^1.10.4|^2", - "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "phpstan/phpdoc-parser": "^1.0", - "symfony/cache": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/serializer": "^4.4|^5.0|^6.0" - }, - "suggest": { - "phpdocumentor/reflection-docblock": "To use the PHPDoc", - "psr/cache-implementation": "To cache results", - "symfony/doctrine-bridge": "To use Doctrine metadata", - "symfony/serializer": "To use Serializer metadata" - }, - "time": "2023-05-15T20:11:03+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\PropertyInfo\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Kévin Dunglas", - "email": "dunglas@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Extracts information about PHP class' properties using metadata of popular sources", - "homepage": "https://symfony.com", - "keywords": [ - "doctrine", - "phpdoc", - "property", - "symfony", - "type", - "validator" - ], - "support": { - "source": "https://github.com/symfony/property-info/tree/v5.4.24" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/property-info" - }, - { - "name": "symfony/routing", - "version": "v5.4.11", - "version_normalized": "5.4.11.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/routing.git", - "reference": "3e01ccd9b2a3a4167ba2b3c53612762300300226" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/3e01ccd9b2a3a4167ba2b3c53612762300300226", - "reference": "3e01ccd9b2a3a4167ba2b3c53612762300300226", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16" - }, - "conflict": { - "doctrine/annotations": "<1.12", - "symfony/config": "<5.3", - "symfony/dependency-injection": "<4.4", - "symfony/yaml": "<4.4" - }, - "require-dev": { - "doctrine/annotations": "^1.12", - "psr/log": "^1|^2|^3", - "symfony/config": "^5.3|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", - "symfony/yaml": "^4.4|^5.0|^6.0" - }, - "suggest": { - "symfony/config": "For using the all-in-one router or any loader", - "symfony/expression-language": "For using expression matching", - "symfony/http-foundation": "For using a Symfony Request object", - "symfony/yaml": "For using the YAML loader" - }, - "time": "2022-07-20T13:00:38+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Routing\\": "" - }, - "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": "Maps an HTTP request to a set of configuration variables", - "homepage": "https://symfony.com", - "keywords": [ - "router", - "routing", - "uri", - "url" - ], - "support": { - "source": "https://github.com/symfony/routing/tree/v5.4.11" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/routing" - }, - { - "name": "symfony/service-contracts", - "version": "v2.5.2", - "version_normalized": "2.5.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1|^3" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "suggest": { - "symfony/service-implementation": "" - }, - "time": "2022-05-30T19:17:29+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/service-contracts" - }, - { - "name": "symfony/stopwatch", - "version": "v5.4.19", - "version_normalized": "5.4.19.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/stopwatch.git", - "reference": "bd2b066090fd6a67039371098fa25a84cb2679ec" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/bd2b066090fd6a67039371098fa25a84cb2679ec", - "reference": "bd2b066090fd6a67039371098fa25a84cb2679ec", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/service-contracts": "^1|^2|^3" - }, - "time": "2023-01-01T08:32:19+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Stopwatch\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a way to profile code", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/stopwatch/tree/v5.4.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" - } - ], - "install-path": "../symfony/stopwatch" - }, - { - "name": "symfony/string", - "version": "v5.4.11", - "version_normalized": "5.4.11.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "5eb661e49ad389e4ae2b6e4df8d783a8a6548322" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/5eb661e49ad389e4ae2b6e4df8d783a8a6548322", - "reference": "5eb661e49ad389e4ae2b6e4df8d783a8a6548322", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "~1.15" - }, - "conflict": { - "symfony/translation-contracts": ">=3.0" - }, - "require-dev": { - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/translation-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0|^6.0" - }, - "time": "2022-07-24T16:15:25+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "files": [ - "Resources/functions.php" - ], - "psr-4": { - "Symfony\\Component\\String\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", - "homepage": "https://symfony.com", - "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" - ], - "support": { - "source": "https://github.com/symfony/string/tree/v5.4.11" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/string" - }, - { - "name": "symfony/translation-contracts", - "version": "v2.5.2", - "version_normalized": "2.5.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/translation-contracts.git", - "reference": "136b19dd05cdf0709db6537d058bcab6dd6e2dbe" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/136b19dd05cdf0709db6537d058bcab6dd6e2dbe", - "reference": "136b19dd05cdf0709db6537d058bcab6dd6e2dbe", - "shasum": "" - }, - "require": { - "php": ">=7.2.5" - }, - "suggest": { - "symfony/translation-implementation": "" - }, - "time": "2022-06-27T16:58:25+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Translation\\": "" - } - }, - "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 translation", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v2.5.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/translation-contracts" - }, - { - "name": "symfony/twig-bridge", - "version": "v5.4.11", - "version_normalized": "5.4.11.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/twig-bridge.git", - "reference": "63b8a50d48c9fe3d04e77307d4f1771dd848baa8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/63b8a50d48c9fe3d04e77307d4f1771dd848baa8", - "reference": "63b8a50d48c9fe3d04e77307d4f1771dd848baa8", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16", - "symfony/translation-contracts": "^1.1|^2|^3", - "twig/twig": "^2.13|^3.0.4" - }, - "conflict": { - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", - "symfony/console": "<5.3", - "symfony/form": "<5.3", - "symfony/http-foundation": "<5.3", - "symfony/http-kernel": "<4.4", - "symfony/translation": "<5.2", - "symfony/workflow": "<5.2" - }, - "require-dev": { - "doctrine/annotations": "^1.12", - "egulias/email-validator": "^2.1.10|^3", - "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/asset": "^4.4|^5.0|^6.0", - "symfony/console": "^5.3|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/finder": "^4.4|^5.0|^6.0", - "symfony/form": "^5.3|^6.0", - "symfony/http-foundation": "^5.3|^6.0", - "symfony/http-kernel": "^4.4|^5.0|^6.0", - "symfony/intl": "^4.4|^5.0|^6.0", - "symfony/mime": "^5.2|^6.0", - "symfony/polyfill-intl-icu": "~1.0", - "symfony/property-info": "^4.4|^5.1|^6.0", - "symfony/routing": "^4.4|^5.0|^6.0", - "symfony/security-acl": "^2.8|^3.0", - "symfony/security-core": "^4.4|^5.0|^6.0", - "symfony/security-csrf": "^4.4|^5.0|^6.0", - "symfony/security-http": "^4.4|^5.0|^6.0", - "symfony/serializer": "^5.2|^6.0", - "symfony/stopwatch": "^4.4|^5.0|^6.0", - "symfony/translation": "^5.2|^6.0", - "symfony/web-link": "^4.4|^5.0|^6.0", - "symfony/workflow": "^5.2|^6.0", - "symfony/yaml": "^4.4|^5.0|^6.0", - "twig/cssinliner-extra": "^2.12|^3", - "twig/inky-extra": "^2.12|^3", - "twig/markdown-extra": "^2.12|^3" - }, - "suggest": { - "symfony/asset": "For using the AssetExtension", - "symfony/expression-language": "For using the ExpressionExtension", - "symfony/finder": "", - "symfony/form": "For using the FormExtension", - "symfony/http-kernel": "For using the HttpKernelExtension", - "symfony/routing": "For using the RoutingExtension", - "symfony/security-core": "For using the SecurityExtension", - "symfony/security-csrf": "For using the CsrfExtension", - "symfony/security-http": "For using the LogoutUrlExtension", - "symfony/stopwatch": "For using the StopwatchExtension", - "symfony/translation": "For using the TranslationExtension", - "symfony/var-dumper": "For using the DumpExtension", - "symfony/web-link": "For using the WebLinkExtension", - "symfony/yaml": "For using the YamlExtension" - }, - "time": "2022-07-20T13:00:38+00:00", - "type": "symfony-bridge", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Bridge\\Twig\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides integration for Twig with various Symfony components", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/twig-bridge/tree/v5.4.11" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/twig-bridge" - }, - { - "name": "symfony/twig-bundle", - "version": "v5.4.19", - "version_normalized": "5.4.19.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/twig-bundle.git", - "reference": "286bd9e38b9bcb142f1eda0a75b0bbeb49ff34bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/286bd9e38b9bcb142f1eda0a75b0bbeb49ff34bd", - "reference": "286bd9e38b9bcb142f1eda0a75b0bbeb49ff34bd", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", - "symfony/http-kernel": "^5.0|^6.0", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-php80": "^1.16", - "symfony/twig-bridge": "^5.3|^6.0", - "twig/twig": "^2.13|^3.0.4" - }, - "conflict": { - "symfony/dependency-injection": "<5.3", - "symfony/framework-bundle": "<5.0", - "symfony/service-contracts": ">=3.0", - "symfony/translation": "<5.0" - }, - "require-dev": { - "doctrine/annotations": "^1.10.4|^2", - "doctrine/cache": "^1.0|^2.0", - "symfony/asset": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^5.3|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/finder": "^4.4|^5.0|^6.0", - "symfony/form": "^4.4|^5.0|^6.0", - "symfony/framework-bundle": "^5.0|^6.0", - "symfony/routing": "^4.4|^5.0|^6.0", - "symfony/stopwatch": "^4.4|^5.0|^6.0", - "symfony/translation": "^5.0|^6.0", - "symfony/web-link": "^4.4|^5.0|^6.0", - "symfony/yaml": "^4.4|^5.0|^6.0" - }, - "time": "2023-01-01T08:32:19+00:00", - "type": "symfony-bundle", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Bundle\\TwigBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a tight integration of Twig into the Symfony full-stack framework", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/twig-bundle/tree/v5.4.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" - } - ], - "install-path": "../symfony/twig-bundle" - }, - { - "name": "symfony/var-dumper", - "version": "v5.4.11", - "version_normalized": "5.4.11.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/var-dumper.git", - "reference": "b8f306d7b8ef34fb3db3305be97ba8e088fb4861" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/b8f306d7b8ef34fb3db3305be97ba8e088fb4861", - "reference": "b8f306d7b8ef34fb3db3305be97ba8e088fb4861", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "^1.16" - }, - "conflict": { - "phpunit/phpunit": "<5.4.3", - "symfony/console": "<4.4" - }, - "require-dev": { - "ext-iconv": "*", - "symfony/console": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/uid": "^5.1|^6.0", - "twig/twig": "^2.13|^3.0.4" - }, - "suggest": { - "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", - "ext-intl": "To show region name in time zone dump", - "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" - }, - "time": "2022-07-20T13:00:38+00:00", - "bin": [ - "Resources/bin/var-dump-server" - ], - "type": "library", - "installation-source": "dist", - "autoload": { - "files": [ - "Resources/functions/dump.php" - ], - "psr-4": { - "Symfony\\Component\\VarDumper\\": "" - }, - "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 mechanisms for walking through any arbitrary PHP variable", - "homepage": "https://symfony.com", - "keywords": [ - "debug", - "dump" - ], - "support": { - "source": "https://github.com/symfony/var-dumper/tree/v5.4.11" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/var-dumper" - }, - { - "name": "symfony/var-exporter", - "version": "v5.4.10", - "version_normalized": "5.4.10.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/var-exporter.git", - "reference": "8fc03ee75eeece3d9be1ef47d26d79bea1afb340" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/8fc03ee75eeece3d9be1ef47d26d79bea1afb340", - "reference": "8fc03ee75eeece3d9be1ef47d26d79bea1afb340", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" - }, - "require-dev": { - "symfony/var-dumper": "^4.4.9|^5.0.9|^6.0" - }, - "time": "2022-05-27T12:56:18+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\VarExporter\\": "" - }, - "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": "Allows exporting any serializable PHP data structure to plain PHP code", - "homepage": "https://symfony.com", - "keywords": [ - "clone", - "construct", - "export", - "hydrate", - "instantiate", - "serialize" - ], - "support": { - "source": "https://github.com/symfony/var-exporter/tree/v5.4.10" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/var-exporter" - }, - { - "name": "symfony/web-profiler-bundle", - "version": "v5.4.19", - "version_normalized": "5.4.19.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "cd83822071f2bc05583af1e53c1bc46be625a56d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/cd83822071f2bc05583af1e53c1bc46be625a56d", - "reference": "cd83822071f2bc05583af1e53c1bc46be625a56d", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/framework-bundle": "^5.3|^6.0", - "symfony/http-kernel": "^5.3|^6.0", - "symfony/polyfill-php80": "^1.16", - "symfony/routing": "^4.4|^5.0|^6.0", - "symfony/twig-bundle": "^4.4|^5.0|^6.0", - "twig/twig": "^2.13|^3.0.4" - }, - "conflict": { - "symfony/dependency-injection": "<5.2", - "symfony/form": "<4.4", - "symfony/mailer": "<5.4", - "symfony/messenger": "<4.4" - }, - "require-dev": { - "symfony/browser-kit": "^4.4|^5.0|^6.0", - "symfony/console": "^4.4|^5.0|^6.0", - "symfony/css-selector": "^4.4|^5.0|^6.0", - "symfony/stopwatch": "^4.4|^5.0|^6.0" - }, - "time": "2023-01-01T08:32:19+00:00", - "type": "symfony-bundle", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Bundle\\WebProfilerBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a development tool that gives detailed information about the execution of any request", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v5.4.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" - } - ], - "install-path": "../symfony/web-profiler-bundle" - }, - { - "name": "symfony/yaml", - "version": "v5.4.19", - "version_normalized": "5.4.19.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "71c05db20cb9b54d381a28255f17580e2b7e36a5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/71c05db20cb9b54d381a28255f17580e2b7e36a5", - "reference": "71c05db20cb9b54d381a28255f17580e2b7e36a5", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "symfony/console": "<5.3" - }, - "require-dev": { - "symfony/console": "^5.3|^6.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" - }, - "time": "2023-01-10T18:51:14+00:00", - "bin": [ - "Resources/bin/yaml-lint" - ], - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Loads and dumps YAML files", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/yaml/tree/v5.4.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" - } - ], - "install-path": "../symfony/yaml" - }, - { - "name": "thenetworg/oauth2-azure", - "version": "v2.1.1", - "version_normalized": "2.1.1.0", - "source": { - "type": "git", - "url": "https://github.com/TheNetworg/oauth2-azure.git", - "reference": "06fb2d620fb6e6c934f632c7ec7c5ea2e978a844" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/TheNetworg/oauth2-azure/zipball/06fb2d620fb6e6c934f632c7ec7c5ea2e978a844", - "reference": "06fb2d620fb6e6c934f632c7ec7c5ea2e978a844", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-openssl": "*", - "firebase/php-jwt": "~3.0||~4.0||~5.0||~6.0", - "league/oauth2-client": "~2.0", - "php": "^7.1|^8.0" - }, - "time": "2022-06-23T10:35:36+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "TheNetworg\\OAuth2\\Client\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jan Hajek", - "email": "jan.hajek@thenetw.org", - "homepage": "https://thenetw.org" - } - ], - "description": "Azure Active Directory OAuth 2.0 Client Provider for The PHP League OAuth2-Client", - "keywords": [ - "SSO", - "aad", - "authorization", - "azure", - "azure active directory", - "client", - "microsoft", - "oauth", - "oauth2", - "windows azure" - ], - "support": { - "issues": "https://github.com/TheNetworg/oauth2-azure/issues", - "source": "https://github.com/TheNetworg/oauth2-azure/tree/v2.1.1" - }, - "install-path": "../thenetworg/oauth2-azure" - }, - { - "name": "twig/twig", - "version": "v3.4.3", - "version_normalized": "3.4.3.0", - "source": { - "type": "git", - "url": "https://github.com/twigphp/Twig.git", - "reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/c38fd6b0b7f370c198db91ffd02e23b517426b58", - "reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-mbstring": "^1.3" - }, - "require-dev": { - "psr/container": "^1.0", - "symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0" - }, - "time": "2022-09-28T08:42:51+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Twig\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, - { - "name": "Twig Team", - "role": "Contributors" - }, - { - "name": "Armin Ronacher", - "email": "armin.ronacher@active-4.com", - "role": "Project Founder" - } - ], - "description": "Twig, the flexible, fast, and secure template language for PHP", - "homepage": "https://twig.symfony.com", - "keywords": [ - "templating" - ], - "support": { - "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.4.3" - }, - "funding": [ - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/twig/twig", - "type": "tidelift" - } - ], - "install-path": "../twig/twig" - }, - { - "name": "webmozart/assert", - "version": "1.11.0", - "version_normalized": "1.11.0.0", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "php": "^7.2 || ^8.0" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" - }, - "time": "2022-06-03T18:03:27+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.11.0" - }, - "install-path": "../webmozart/assert" - } - ], - "dev": true, - "dev-package-names": [ - "symfony/stopwatch", - "symfony/web-profiler-bundle" - ] -} diff --git a/lib/composer/installed.php b/lib/composer/installed.php deleted file mode 100644 index 75145242e..000000000 --- a/lib/composer/installed.php +++ /dev/null @@ -1,819 +0,0 @@ -<?php return array( - 'root' => array( - 'pretty_version' => 'dev-develop', - 'version' => 'dev-develop', - 'type' => 'project', - 'install_path' => __DIR__ . '/../../', - 'aliases' => array(), - 'reference' => '960ce4efcd62c8ca3378b81414b33742bde1d568', - 'name' => 'combodo/itop', - 'dev' => true, - ), - 'versions' => array( - 'apereo/phpcas' => array( - 'pretty_version' => '1.6.0', - 'version' => '1.6.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../apereo/phpcas', - 'aliases' => array(), - 'reference' => 'f817c72a961484afef95ac64a9257c8e31f063b9', - 'dev_requirement' => false, - ), - 'combodo/itop' => array( - 'pretty_version' => 'dev-develop', - 'version' => 'dev-develop', - 'type' => 'project', - 'install_path' => __DIR__ . '/../../', - 'aliases' => array(), - 'reference' => '960ce4efcd62c8ca3378b81414b33742bde1d568', - 'dev_requirement' => false, - ), - 'combodo/tcpdf' => array( - 'pretty_version' => '6.4.4', - 'version' => '6.4.4.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../combodo/tcpdf', - 'aliases' => array(), - 'reference' => '0e31c013ccd000aa6762e9186778aa6e259ac8e8', - 'dev_requirement' => false, - ), - 'container-interop/container-interop' => array( - 'dev_requirement' => false, - 'replaced' => array( - 0 => '^1.2.0', - ), - ), - 'doctrine/annotations' => array( - 'pretty_version' => '2.0.1', - 'version' => '2.0.1.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../doctrine/annotations', - 'aliases' => array(), - 'reference' => 'e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f', - 'dev_requirement' => false, - ), - 'doctrine/cache' => array( - 'pretty_version' => '2.2.0', - 'version' => '2.2.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../doctrine/cache', - 'aliases' => array(), - 'reference' => '1ca8f21980e770095a31456042471a57bc4c68fb', - 'dev_requirement' => false, - ), - 'doctrine/deprecations' => array( - 'pretty_version' => 'v1.1.1', - 'version' => '1.1.1.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../doctrine/deprecations', - 'aliases' => array(), - 'reference' => '612a3ee5ab0d5dd97b7cf3874a6efe24325efac3', - 'dev_requirement' => false, - ), - 'doctrine/lexer' => array( - 'pretty_version' => '2.1.0', - 'version' => '2.1.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../doctrine/lexer', - 'aliases' => array(), - 'reference' => '39ab8fcf5a51ce4b85ca97c7a7d033eb12831124', - 'dev_requirement' => false, - ), - 'firebase/php-jwt' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../firebase/php-jwt', - 'aliases' => array(), - 'reference' => '4dd1e007f22a927ac77da5a3fbb067b42d3bc224', - 'dev_requirement' => false, - ), - 'guzzlehttp/guzzle' => array( - 'pretty_version' => '7.7.0', - 'version' => '7.7.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../guzzlehttp/guzzle', - 'aliases' => array(), - 'reference' => 'fb7566caccf22d74d1ab270de3551f72a58399f5', - 'dev_requirement' => false, - ), - 'guzzlehttp/promises' => array( - 'pretty_version' => '2.0.0', - 'version' => '2.0.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../guzzlehttp/promises', - 'aliases' => array(), - 'reference' => '3a494dc7dc1d7d12e511890177ae2d0e6c107da6', - 'dev_requirement' => false, - ), - 'guzzlehttp/psr7' => array( - 'pretty_version' => '2.5.0', - 'version' => '2.5.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../guzzlehttp/psr7', - 'aliases' => array(), - 'reference' => 'b635f279edd83fc275f822a1188157ffea568ff6', - 'dev_requirement' => false, - ), - 'laminas/laminas-loader' => array( - 'pretty_version' => '2.8.0', - 'version' => '2.8.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../laminas/laminas-loader', - 'aliases' => array(), - 'reference' => 'd0589ec9dd48365fd95ad10d1c906efd7711c16b', - 'dev_requirement' => false, - ), - 'laminas/laminas-mail' => array( - 'pretty_version' => '2.16.0', - 'version' => '2.16.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../laminas/laminas-mail', - 'aliases' => array(), - 'reference' => '1ee1a384b96c8af29ecad9b3a7adc27a150ebc49', - 'dev_requirement' => false, - ), - 'laminas/laminas-mime' => array( - 'pretty_version' => '2.9.1', - 'version' => '2.9.1.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../laminas/laminas-mime', - 'aliases' => array(), - 'reference' => '72d21a1b4bb7086d4a4d7058c0abca180b209184', - 'dev_requirement' => false, - ), - 'laminas/laminas-servicemanager' => array( - 'pretty_version' => '3.16.0', - 'version' => '3.16.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../laminas/laminas-servicemanager', - 'aliases' => array(), - 'reference' => '863c66733740cd36ebf5e700f4258ef2c68a2a24', - 'dev_requirement' => false, - ), - 'laminas/laminas-stdlib' => array( - 'pretty_version' => '3.12.0', - 'version' => '3.12.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../laminas/laminas-stdlib', - 'aliases' => array(), - 'reference' => 'c5aed3c798018e31fbb7b1e421b8d96bf2cda453', - 'dev_requirement' => false, - ), - 'laminas/laminas-validator' => array( - 'pretty_version' => '2.23.0', - 'version' => '2.23.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../laminas/laminas-validator', - 'aliases' => array(), - 'reference' => '6d61b6cc3b222f13807a18d9247cdfb084958b03', - 'dev_requirement' => false, - ), - 'league/oauth2-client' => array( - 'pretty_version' => '2.6.1', - 'version' => '2.6.1.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../league/oauth2-client', - 'aliases' => array(), - 'reference' => '2334c249907190c132364f5dae0287ab8666aa19', - 'dev_requirement' => false, - ), - 'league/oauth2-google' => array( - 'pretty_version' => '3.0.4', - 'version' => '3.0.4.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../league/oauth2-google', - 'aliases' => array(), - 'reference' => '6b79441f244040760bed5fdcd092a2bda7cf34c6', - 'dev_requirement' => false, - ), - 'nikic/php-parser' => array( - 'pretty_version' => 'v4.14.0', - 'version' => '4.14.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../nikic/php-parser', - 'aliases' => array(), - 'reference' => '34bea19b6e03d8153165d8f30bba4c3be86184c1', - 'dev_requirement' => false, - ), - 'paragonie/random_compat' => array( - 'pretty_version' => 'v9.99.100', - 'version' => '9.99.100.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../paragonie/random_compat', - 'aliases' => array(), - 'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a', - 'dev_requirement' => false, - ), - 'pear/archive_tar' => array( - 'pretty_version' => '1.4.14', - 'version' => '1.4.14.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../pear/archive_tar', - 'aliases' => array(), - 'reference' => '4d761c5334c790e45ef3245f0864b8955c562caa', - 'dev_requirement' => false, - ), - 'pear/console_getopt' => array( - 'pretty_version' => 'v1.4.3', - 'version' => '1.4.3.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../pear/console_getopt', - 'aliases' => array(), - 'reference' => 'a41f8d3e668987609178c7c4a9fe48fecac53fa0', - 'dev_requirement' => false, - ), - 'pear/pear-core-minimal' => array( - 'pretty_version' => 'v1.10.11', - 'version' => '1.10.11.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../pear/pear-core-minimal', - 'aliases' => array(), - 'reference' => '68d0d32ada737153b7e93b8d3c710ebe70ac867d', - 'dev_requirement' => false, - ), - 'pear/pear_exception' => array( - 'pretty_version' => 'v1.0.2', - 'version' => '1.0.2.0', - 'type' => 'class', - 'install_path' => __DIR__ . '/../pear/pear_exception', - 'aliases' => array(), - 'reference' => 'b14fbe2ddb0b9f94f5b24cf08783d599f776fff0', - 'dev_requirement' => false, - ), - 'pelago/emogrifier' => array( - 'pretty_version' => 'v6.0.0', - 'version' => '6.0.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../pelago/emogrifier', - 'aliases' => array(), - 'reference' => 'aa72d5407efac118f3896bcb995a2cba793df0ae', - 'dev_requirement' => false, - ), - 'psr/cache' => array( - 'pretty_version' => '1.0.1', - 'version' => '1.0.1.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../psr/cache', - 'aliases' => array(), - 'reference' => 'd11b50ad223250cf17b86e38383413f5a6764bf8', - 'dev_requirement' => false, - ), - 'psr/cache-implementation' => array( - 'dev_requirement' => false, - 'provided' => array( - 0 => '1.0|2.0', - ), - ), - 'psr/container' => array( - 'pretty_version' => '1.1.2', - 'version' => '1.1.2.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../psr/container', - 'aliases' => array(), - 'reference' => '513e0666f7216c7459170d56df27dfcefe1689ea', - 'dev_requirement' => false, - ), - 'psr/container-implementation' => array( - 'dev_requirement' => false, - 'provided' => array( - 0 => '^1.0', - 1 => '1.0', - ), - ), - 'psr/event-dispatcher' => array( - 'pretty_version' => '1.0.0', - 'version' => '1.0.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../psr/event-dispatcher', - 'aliases' => array(), - 'reference' => 'dbefd12671e8a14ec7f180cab83036ed26714bb0', - 'dev_requirement' => false, - ), - 'psr/event-dispatcher-implementation' => array( - 'dev_requirement' => false, - 'provided' => array( - 0 => '1.0', - ), - ), - 'psr/http-client' => array( - 'pretty_version' => '1.0.2', - 'version' => '1.0.2.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../psr/http-client', - 'aliases' => array(), - 'reference' => '0955afe48220520692d2d09f7ab7e0f93ffd6a31', - 'dev_requirement' => false, - ), - 'psr/http-client-implementation' => array( - 'dev_requirement' => false, - 'provided' => array( - 0 => '1.0', - ), - ), - 'psr/http-factory' => array( - 'pretty_version' => '1.0.2', - 'version' => '1.0.2.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../psr/http-factory', - 'aliases' => array(), - 'reference' => 'e616d01114759c4c489f93b099585439f795fe35', - 'dev_requirement' => false, - ), - 'psr/http-factory-implementation' => array( - 'dev_requirement' => false, - 'provided' => array( - 0 => '1.0', - ), - ), - 'psr/http-message' => array( - 'pretty_version' => '2.0', - 'version' => '2.0.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../psr/http-message', - 'aliases' => array(), - 'reference' => '402d35bcb92c70c026d1a6a9883f06b2ead23d71', - 'dev_requirement' => false, - ), - 'psr/http-message-implementation' => array( - 'dev_requirement' => false, - 'provided' => array( - 0 => '1.0', - ), - ), - 'psr/log' => array( - 'pretty_version' => '1.1.4', - 'version' => '1.1.4.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../psr/log', - 'aliases' => array(), - 'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11', - 'dev_requirement' => false, - ), - 'psr/log-implementation' => array( - 'dev_requirement' => false, - 'provided' => array( - 0 => '1.0|2.0', - ), - ), - 'psr/simple-cache-implementation' => array( - 'dev_requirement' => false, - 'provided' => array( - 0 => '1.0|2.0', - ), - ), - 'ralouphie/getallheaders' => array( - 'pretty_version' => '3.0.3', - 'version' => '3.0.3.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../ralouphie/getallheaders', - 'aliases' => array(), - 'reference' => '120b605dfeb996808c31b6477290a714d356e822', - 'dev_requirement' => false, - ), - 'rsky/pear-core-min' => array( - 'dev_requirement' => false, - 'replaced' => array( - 0 => 'v1.10.11', - ), - ), - 'sabberworm/php-css-parser' => array( - 'pretty_version' => '8.4.0', - 'version' => '8.4.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../sabberworm/php-css-parser', - 'aliases' => array(), - 'reference' => 'e41d2140031d533348b2192a83f02d8dd8a71d30', - 'dev_requirement' => false, - ), - 'scssphp/scssphp' => array( - 'pretty_version' => 'v1.10.5', - 'version' => '1.10.5.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../scssphp/scssphp', - 'aliases' => array(), - 'reference' => '6d44282ccf283e133ab70b6282f8e068ff2f9bf9', - 'dev_requirement' => false, - ), - 'symfony/cache' => array( - 'pretty_version' => 'v5.4.11', - 'version' => '5.4.11.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/cache', - 'aliases' => array(), - 'reference' => '5a0fff46df349f0db3fe242263451fddf5277362', - 'dev_requirement' => false, - ), - 'symfony/cache-contracts' => array( - 'pretty_version' => 'v2.5.2', - 'version' => '2.5.2.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/cache-contracts', - 'aliases' => array(), - 'reference' => '64be4a7acb83b6f2bf6de9a02cee6dad41277ebc', - 'dev_requirement' => false, - ), - 'symfony/cache-implementation' => array( - 'dev_requirement' => false, - 'provided' => array( - 0 => '1.0|2.0', - ), - ), - 'symfony/config' => array( - 'pretty_version' => 'v5.4.11', - 'version' => '5.4.11.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/config', - 'aliases' => array(), - 'reference' => 'ec79e03125c1d2477e43dde8528535d90cc78379', - 'dev_requirement' => false, - ), - 'symfony/console' => array( - 'pretty_version' => 'v5.4.19', - 'version' => '5.4.19.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/console', - 'aliases' => array(), - 'reference' => 'dccb8d251a9017d5994c988b034d3e18aaabf740', - 'dev_requirement' => false, - ), - 'symfony/css-selector' => array( - 'pretty_version' => 'v5.4.11', - 'version' => '5.4.11.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/css-selector', - 'aliases' => array(), - 'reference' => 'c1681789f059ab756001052164726ae88512ae3d', - 'dev_requirement' => false, - ), - 'symfony/dependency-injection' => array( - 'pretty_version' => 'v5.4.11', - 'version' => '5.4.11.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/dependency-injection', - 'aliases' => array(), - 'reference' => 'a8b9251016e9476db73e25fa836904bc0bf74c62', - 'dev_requirement' => false, - ), - 'symfony/deprecation-contracts' => array( - 'pretty_version' => 'v2.5.2', - 'version' => '2.5.2.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', - 'aliases' => array(), - 'reference' => 'e8b495ea28c1d97b5e0c121748d6f9b53d075c66', - 'dev_requirement' => false, - ), - 'symfony/dotenv' => array( - 'pretty_version' => 'v5.4.19', - 'version' => '5.4.19.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/dotenv', - 'aliases' => array(), - 'reference' => '38190ba62566afa26ca723a795d0a004e061bd2a', - 'dev_requirement' => false, - ), - 'symfony/error-handler' => array( - 'pretty_version' => 'v5.4.11', - 'version' => '5.4.11.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/error-handler', - 'aliases' => array(), - 'reference' => 'f75d17cb4769eb38cd5fccbda95cd80a054d35c8', - 'dev_requirement' => false, - ), - 'symfony/event-dispatcher' => array( - 'pretty_version' => 'v5.4.9', - 'version' => '5.4.9.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/event-dispatcher', - 'aliases' => array(), - 'reference' => '8e6ce1cc0279e3ff3c8ff0f43813bc88d21ca1bc', - 'dev_requirement' => false, - ), - 'symfony/event-dispatcher-contracts' => array( - 'pretty_version' => 'v2.5.2', - 'version' => '2.5.2.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/event-dispatcher-contracts', - 'aliases' => array(), - 'reference' => 'f98b54df6ad059855739db6fcbc2d36995283fe1', - 'dev_requirement' => false, - ), - 'symfony/event-dispatcher-implementation' => array( - 'dev_requirement' => false, - 'provided' => array( - 0 => '2.0', - ), - ), - 'symfony/filesystem' => array( - 'pretty_version' => 'v5.4.11', - 'version' => '5.4.11.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/filesystem', - 'aliases' => array(), - 'reference' => '6699fb0228d1bc35b12aed6dd5e7455457609ddd', - 'dev_requirement' => false, - ), - 'symfony/finder' => array( - 'pretty_version' => 'v5.4.11', - 'version' => '5.4.11.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/finder', - 'aliases' => array(), - 'reference' => '7872a66f57caffa2916a584db1aa7f12adc76f8c', - 'dev_requirement' => false, - ), - 'symfony/form' => array( - 'pretty_version' => 'v5.4.19', - 'version' => '5.4.19.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/form', - 'aliases' => array(), - 'reference' => 'c29e6cccee469ca93db2dbc02a39c29312c5e362', - 'dev_requirement' => false, - ), - 'symfony/framework-bundle' => array( - 'pretty_version' => 'v5.4.19', - 'version' => '5.4.19.0', - 'type' => 'symfony-bundle', - 'install_path' => __DIR__ . '/../symfony/framework-bundle', - 'aliases' => array(), - 'reference' => 'a208ee578000f9dedcb50a9784ec7ff8706a7bf1', - 'dev_requirement' => false, - ), - 'symfony/http-foundation' => array( - 'pretty_version' => 'v5.4.20', - 'version' => '5.4.20.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/http-foundation', - 'aliases' => array(), - 'reference' => 'd0435363362a47c14e9cf50663cb8ffbf491875a', - 'dev_requirement' => false, - ), - 'symfony/http-kernel' => array( - 'pretty_version' => 'v5.4.20', - 'version' => '5.4.20.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/http-kernel', - 'aliases' => array(), - 'reference' => 'aaeec341582d3c160cc9ecfa8b2419ba6c69954e', - 'dev_requirement' => false, - ), - 'symfony/options-resolver' => array( - 'pretty_version' => 'v5.4.21', - 'version' => '5.4.21.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/options-resolver', - 'aliases' => array(), - 'reference' => '4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9', - 'dev_requirement' => false, - ), - 'symfony/polyfill-ctype' => array( - 'pretty_version' => 'v1.26.0', - 'version' => '1.26.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/polyfill-ctype', - 'aliases' => array(), - 'reference' => '6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4', - 'dev_requirement' => false, - ), - 'symfony/polyfill-intl-grapheme' => array( - 'pretty_version' => 'v1.26.0', - 'version' => '1.26.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/polyfill-intl-grapheme', - 'aliases' => array(), - 'reference' => '433d05519ce6990bf3530fba6957499d327395c2', - 'dev_requirement' => false, - ), - 'symfony/polyfill-intl-icu' => array( - 'pretty_version' => 'v1.27.0', - 'version' => '1.27.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/polyfill-intl-icu', - 'aliases' => array(), - 'reference' => 'a3d9148e2c363588e05abbdd4ee4f971f0a5330c', - 'dev_requirement' => false, - ), - 'symfony/polyfill-intl-idn' => array( - 'pretty_version' => 'v1.26.0', - 'version' => '1.26.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/polyfill-intl-idn', - 'aliases' => array(), - 'reference' => '59a8d271f00dd0e4c2e518104cc7963f655a1aa8', - 'dev_requirement' => false, - ), - 'symfony/polyfill-intl-normalizer' => array( - 'pretty_version' => 'v1.26.0', - 'version' => '1.26.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer', - 'aliases' => array(), - 'reference' => '219aa369ceff116e673852dce47c3a41794c14bd', - 'dev_requirement' => false, - ), - 'symfony/polyfill-mbstring' => array( - 'pretty_version' => 'v1.26.0', - 'version' => '1.26.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring', - 'aliases' => array(), - 'reference' => '9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e', - 'dev_requirement' => false, - ), - 'symfony/polyfill-php72' => array( - 'pretty_version' => 'v1.26.0', - 'version' => '1.26.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/polyfill-php72', - 'aliases' => array(), - 'reference' => 'bf44a9fd41feaac72b074de600314a93e2ae78e2', - 'dev_requirement' => false, - ), - 'symfony/polyfill-php73' => array( - 'pretty_version' => 'v1.26.0', - 'version' => '1.26.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/polyfill-php73', - 'aliases' => array(), - 'reference' => 'e440d35fa0286f77fb45b79a03fedbeda9307e85', - 'dev_requirement' => false, - ), - 'symfony/polyfill-php80' => array( - 'pretty_version' => 'v1.26.0', - 'version' => '1.26.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/polyfill-php80', - 'aliases' => array(), - 'reference' => 'cfa0ae98841b9e461207c13ab093d76b0fa7bace', - 'dev_requirement' => false, - ), - 'symfony/polyfill-php81' => array( - 'pretty_version' => 'v1.26.0', - 'version' => '1.26.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/polyfill-php81', - 'aliases' => array(), - 'reference' => '13f6d1271c663dc5ae9fb843a8f16521db7687a1', - 'dev_requirement' => false, - ), - 'symfony/property-access' => array( - 'pretty_version' => 'v5.4.22', - 'version' => '5.4.22.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/property-access', - 'aliases' => array(), - 'reference' => 'ffee082889586b5718347b291e04071f4d07b38f', - 'dev_requirement' => false, - ), - 'symfony/property-info' => array( - 'pretty_version' => 'v5.4.24', - 'version' => '5.4.24.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/property-info', - 'aliases' => array(), - 'reference' => 'd43b85b00699b4484964c297575b5c6f9dc5f6e1', - 'dev_requirement' => false, - ), - 'symfony/routing' => array( - 'pretty_version' => 'v5.4.11', - 'version' => '5.4.11.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/routing', - 'aliases' => array(), - 'reference' => '3e01ccd9b2a3a4167ba2b3c53612762300300226', - 'dev_requirement' => false, - ), - 'symfony/service-contracts' => array( - 'pretty_version' => 'v2.5.2', - 'version' => '2.5.2.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/service-contracts', - 'aliases' => array(), - 'reference' => '4b426aac47d6427cc1a1d0f7e2ac724627f5966c', - 'dev_requirement' => false, - ), - 'symfony/service-implementation' => array( - 'dev_requirement' => false, - 'provided' => array( - 0 => '1.0|2.0', - ), - ), - 'symfony/stopwatch' => array( - 'pretty_version' => 'v5.4.19', - 'version' => '5.4.19.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/stopwatch', - 'aliases' => array(), - 'reference' => 'bd2b066090fd6a67039371098fa25a84cb2679ec', - 'dev_requirement' => true, - ), - 'symfony/string' => array( - 'pretty_version' => 'v5.4.11', - 'version' => '5.4.11.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/string', - 'aliases' => array(), - 'reference' => '5eb661e49ad389e4ae2b6e4df8d783a8a6548322', - 'dev_requirement' => false, - ), - 'symfony/translation-contracts' => array( - 'pretty_version' => 'v2.5.2', - 'version' => '2.5.2.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/translation-contracts', - 'aliases' => array(), - 'reference' => '136b19dd05cdf0709db6537d058bcab6dd6e2dbe', - 'dev_requirement' => false, - ), - 'symfony/twig-bridge' => array( - 'pretty_version' => 'v5.4.11', - 'version' => '5.4.11.0', - 'type' => 'symfony-bridge', - 'install_path' => __DIR__ . '/../symfony/twig-bridge', - 'aliases' => array(), - 'reference' => '63b8a50d48c9fe3d04e77307d4f1771dd848baa8', - 'dev_requirement' => false, - ), - 'symfony/twig-bundle' => array( - 'pretty_version' => 'v5.4.19', - 'version' => '5.4.19.0', - 'type' => 'symfony-bundle', - 'install_path' => __DIR__ . '/../symfony/twig-bundle', - 'aliases' => array(), - 'reference' => '286bd9e38b9bcb142f1eda0a75b0bbeb49ff34bd', - 'dev_requirement' => false, - ), - 'symfony/var-dumper' => array( - 'pretty_version' => 'v5.4.11', - 'version' => '5.4.11.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/var-dumper', - 'aliases' => array(), - 'reference' => 'b8f306d7b8ef34fb3db3305be97ba8e088fb4861', - 'dev_requirement' => false, - ), - 'symfony/var-exporter' => array( - 'pretty_version' => 'v5.4.10', - 'version' => '5.4.10.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/var-exporter', - 'aliases' => array(), - 'reference' => '8fc03ee75eeece3d9be1ef47d26d79bea1afb340', - 'dev_requirement' => false, - ), - 'symfony/web-profiler-bundle' => array( - 'pretty_version' => 'v5.4.19', - 'version' => '5.4.19.0', - 'type' => 'symfony-bundle', - 'install_path' => __DIR__ . '/../symfony/web-profiler-bundle', - 'aliases' => array(), - 'reference' => 'cd83822071f2bc05583af1e53c1bc46be625a56d', - 'dev_requirement' => true, - ), - 'symfony/yaml' => array( - 'pretty_version' => 'v5.4.19', - 'version' => '5.4.19.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/yaml', - 'aliases' => array(), - 'reference' => '71c05db20cb9b54d381a28255f17580e2b7e36a5', - 'dev_requirement' => false, - ), - 'tecnickcom/tcpdf' => array( - 'dev_requirement' => false, - 'replaced' => array( - 0 => '6.4.4', - ), - ), - 'thenetworg/oauth2-azure' => array( - 'pretty_version' => 'v2.1.1', - 'version' => '2.1.1.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../thenetworg/oauth2-azure', - 'aliases' => array(), - 'reference' => '06fb2d620fb6e6c934f632c7ec7c5ea2e978a844', - 'dev_requirement' => false, - ), - 'twig/twig' => array( - 'pretty_version' => 'v3.4.3', - 'version' => '3.4.3.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../twig/twig', - 'aliases' => array(), - 'reference' => 'c38fd6b0b7f370c198db91ffd02e23b517426b58', - 'dev_requirement' => false, - ), - 'webmozart/assert' => array( - 'pretty_version' => '1.11.0', - 'version' => '1.11.0.0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../webmozart/assert', - 'aliases' => array(), - 'reference' => '11cb2199493b2f8a3b53e7f19068fc6aac760991', - 'dev_requirement' => false, - ), - ), -); diff --git a/lib/composer/platform_check.php b/lib/composer/platform_check.php deleted file mode 100644 index 2e6a23f9c..000000000 --- a/lib/composer/platform_check.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -// platform_check.php @generated by Composer - -$issues = array(); - -if (!(PHP_VERSION_ID >= 70400)) { - $issues[] = 'Your Composer dependencies require a PHP version ">= 7.4.0". You are running ' . PHP_VERSION . '.'; -} - -$missingExtensions = array(); -extension_loaded('curl') || $missingExtensions[] = 'curl'; -extension_loaded('dom') || $missingExtensions[] = 'dom'; -extension_loaded('gd') || $missingExtensions[] = 'gd'; -extension_loaded('iconv') || $missingExtensions[] = 'iconv'; -extension_loaded('json') || $missingExtensions[] = 'json'; -extension_loaded('libxml') || $missingExtensions[] = 'libxml'; -extension_loaded('mysqli') || $missingExtensions[] = 'mysqli'; -extension_loaded('openssl') || $missingExtensions[] = 'openssl'; -extension_loaded('soap') || $missingExtensions[] = 'soap'; -extension_loaded('tokenizer') || $missingExtensions[] = 'tokenizer'; -extension_loaded('xml') || $missingExtensions[] = 'xml'; - -if ($missingExtensions) { - $issues[] = 'Your Composer dependencies require the following PHP extensions to be installed: ' . implode(', ', $missingExtensions) . '.'; -} - -if ($issues) { - if (!headers_sent()) { - header('HTTP/1.1 500 Internal Server Error'); - } - if (!ini_get('display_errors')) { - if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { - fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL); - } elseif (!headers_sent()) { - echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL; - } - } - trigger_error( - 'Composer detected issues in your platform: ' . implode(' ', $issues), - E_USER_ERROR - ); -} diff --git a/lib/doctrine/annotations/LICENSE b/lib/doctrine/annotations/LICENSE deleted file mode 100644 index 5e781fce4..000000000 --- a/lib/doctrine/annotations/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2006-2013 Doctrine Project - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/lib/doctrine/annotations/README.md b/lib/doctrine/annotations/README.md deleted file mode 100644 index 6b8c0359b..000000000 --- a/lib/doctrine/annotations/README.md +++ /dev/null @@ -1,24 +0,0 @@ -⚠️ PHP 8 introduced -[attributes](https://www.php.net/manual/en/language.attributes.overview.php), -which are a native replacement for annotations. As such, this library is -considered feature complete, and should receive exclusively bugfixes and -security fixes. - -# Doctrine Annotations - -[![Build Status](https://github.com/doctrine/annotations/workflows/Continuous%20Integration/badge.svg?label=build)](https://github.com/doctrine/persistence/actions) -[![Dependency Status](https://www.versioneye.com/package/php--doctrine--annotations/badge.png)](https://www.versioneye.com/package/php--doctrine--annotations) -[![Reference Status](https://www.versioneye.com/php/doctrine:annotations/reference_badge.svg)](https://www.versioneye.com/php/doctrine:annotations/references) -[![Total Downloads](https://poser.pugx.org/doctrine/annotations/downloads.png)](https://packagist.org/packages/doctrine/annotations) -[![Latest Stable Version](https://img.shields.io/packagist/v/doctrine/annotations.svg?label=stable)](https://packagist.org/packages/doctrine/annotations) - -Docblock Annotations Parser library (extracted from [Doctrine Common](https://github.com/doctrine/common)). - -## Documentation - -See the [doctrine-project website](https://www.doctrine-project.org/projects/doctrine-annotations/en/latest/index.html). - -## Contributing - -When making a pull request, make sure your changes follow the -[Coding Standard Guidelines](https://www.doctrine-project.org/projects/doctrine-coding-standard/en/current/reference/index.html#introduction). diff --git a/lib/doctrine/annotations/UPGRADE.md b/lib/doctrine/annotations/UPGRADE.md deleted file mode 100644 index 4172708f0..000000000 --- a/lib/doctrine/annotations/UPGRADE.md +++ /dev/null @@ -1,18 +0,0 @@ -# Upgrade from 1.0.x to 2.0.x - -- The `NamedArgumentConstructorAnnotation` has been removed. Use the `@NamedArgumentConstructor` - annotation instead. -- `SimpleAnnotationReader` has been removed. -- `DocLexer::peek()` and `DocLexer::glimpse` now return -`Doctrine\Common\Lexer\Token` objects. When using `doctrine/lexer` 2, these -implement `ArrayAccess` as a way for you to still be able to treat them as -arrays in some ways. -- `CachedReader` and `FileCacheReader` have been removed. -- `AnnotationRegistry` methods related to registering annotations instead of - using autoloading have been removed. -- Parameter type declarations have been added to all methods of all classes. If -you have classes inheriting from classes inside this package, you should add -parameter and return type declarations. -- Support for PHP < 7.2 has been removed -- `PhpParser::parseClass()` has been removed. Use - `PhpParser::parseUseStatements()` instead. diff --git a/lib/doctrine/annotations/composer.json b/lib/doctrine/annotations/composer.json deleted file mode 100644 index d1d3d8db1..000000000 --- a/lib/doctrine/annotations/composer.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "name": "doctrine/annotations", - "description": "Docblock Annotations Parser", - "license": "MIT", - "type": "library", - "keywords": [ - "annotations", - "docblock", - "parser" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "homepage": "https://www.doctrine-project.org/projects/annotations.html", - "require": { - "php": "^7.2 || ^8.0", - "ext-tokenizer": "*", - "doctrine/lexer": "^2 || ^3", - "psr/cache": "^1 || ^2 || ^3" - }, - "require-dev": { - "doctrine/cache": "^2.0", - "doctrine/coding-standard": "^10", - "phpstan/phpstan": "^1.8.0", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "symfony/cache": "^5.4 || ^6", - "vimeo/psalm": "^4.10" - }, - "suggest": { - "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" - } - }, - "autoload-dev": { - "psr-4": { - "Doctrine\\Performance\\Common\\Annotations\\": "tests/Doctrine/Performance/Common/Annotations", - "Doctrine\\Tests\\Common\\Annotations\\": "tests/Doctrine/Tests/Common/Annotations" - }, - "files": [ - "tests/Doctrine/Tests/Common/Annotations/Fixtures/functions.php", - "tests/Doctrine/Tests/Common/Annotations/Fixtures/SingleClassLOC1000.php" - ] - }, - "config": { - "allow-plugins": { - "dealerdirect/phpcodesniffer-composer-installer": true - }, - "sort-packages": true - } -} diff --git a/lib/doctrine/annotations/docs/en/annotations.rst b/lib/doctrine/annotations/docs/en/annotations.rst deleted file mode 100644 index d32b15d12..000000000 --- a/lib/doctrine/annotations/docs/en/annotations.rst +++ /dev/null @@ -1,189 +0,0 @@ -Handling Annotations -==================== - -There are several different approaches to handling annotations in PHP. -Doctrine Annotations maps docblock annotations to PHP classes. Because -not all docblock annotations are used for metadata purposes a filter is -applied to ignore or skip classes that are not Doctrine annotations. - -Take a look at the following code snippet: - -.. code-block:: php - - namespace MyProject\Entities; - - use Doctrine\ORM\Mapping AS ORM; - use Symfony\Component\Validator\Constraints AS Assert; - - /** - * @author Benjamin Eberlei - * @ORM\Entity - * @MyProject\Annotations\Foobarable - */ - class User - { - /** - * @ORM\Id @ORM\Column @ORM\GeneratedValue - * @dummy - * @var int - */ - private $id; - - /** - * @ORM\Column(type="string") - * @Assert\NotEmpty - * @Assert\Email - * @var string - */ - private $email; - } - -In this snippet you can see a variety of different docblock annotations: - -- Documentation annotations such as ``@var`` and ``@author``. These - annotations are ignored and never considered for throwing an - exception due to wrongly used annotations. -- Annotations imported through use statements. The statement ``use - Doctrine\ORM\Mapping AS ORM`` makes all classes under that namespace - available as ``@ORM\ClassName``. Same goes for the import of - ``@Assert``. -- The ``@dummy`` annotation. It is not a documentation annotation and - not ignored. For Doctrine Annotations it is not entirely clear how - to handle this annotation. Depending on the configuration an exception - (unknown annotation) will be thrown when parsing this annotation. -- The fully qualified annotation ``@MyProject\Annotations\Foobarable``. - This is transformed directly into the given class name. - -How are these annotations loaded? From looking at the code you could -guess that the ORM Mapping, Assert Validation and the fully qualified -annotation can just be loaded using -the defined PHP autoloaders. This is not the case however: For error -handling reasons every check for class existence inside the -``AnnotationReader`` sets the second parameter $autoload -of ``class_exists($name, $autoload)`` to false. To work flawlessly the -``AnnotationReader`` requires silent autoloaders which many autoloaders are -not. Silent autoloading is NOT part of the `PSR-0 specification -<https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md>`_ -for autoloading. - -This is why Doctrine Annotations uses its own autoloading mechanism -through a global registry. If you are wondering about the annotation -registry being global, there is no other way to solve the architectural -problems of autoloading annotation classes in a straightforward fashion. -Additionally if you think about PHP autoloading then you recognize it is -a global as well. - -To anticipate the configuration section, making the above PHP class work -with Doctrine Annotations requires this setup: - -.. code-block:: php - - use Doctrine\Common\Annotations\AnnotationReader; - - $reader = new AnnotationReader(); - AnnotationReader::addGlobalIgnoredName('dummy'); - -We create the actual ``AnnotationReader`` instance. -Note that we also add ``dummy`` to the global list of ignored -annotations for which we do not throw exceptions. Setting this is -necessary in our example case, otherwise ``@dummy`` would trigger an -exception to be thrown during the parsing of the docblock of -``MyProject\Entities\User#id``. - -Setup and Configuration ------------------------ - -To use the annotations library is simple, you just need to create a new -``AnnotationReader`` instance: - -.. code-block:: php - - $reader = new \Doctrine\Common\Annotations\AnnotationReader(); - -This creates a simple annotation reader with no caching other than in -memory (in php arrays). Since parsing docblocks can be expensive you -should cache this process by using a caching reader. - -To cache annotations, you can create a ``Doctrine\Common\Annotations\PsrCachedReader``. -This reader decorates the original reader and stores all annotations in a PSR-6 -cache: - -.. code-block:: php - - use Doctrine\Common\Annotations\AnnotationReader; - use Doctrine\Common\Annotations\PsrCachedReader; - - $cache = ... // instantiate a PSR-6 Cache pool - - $reader = new PsrCachedReader( - new AnnotationReader(), - $cache, - $debug = true - ); - -The ``debug`` flag is used here as well to invalidate the cache files -when the PHP class with annotations changed and should be used during -development. - -.. warning :: - - The ``AnnotationReader`` works and caches under the - assumption that all annotations of a doc-block are processed at - once. That means that annotation classes that do not exist and - aren't loaded and cannot be autoloaded (using the - AnnotationRegistry) would never be visible and not accessible if a - cache is used unless the cache is cleared and the annotations - requested again, this time with all annotations defined. - -By default the annotation reader returns a list of annotations with -numeric indexes. If you want your annotations to be indexed by their -class name you can wrap the reader in an ``IndexedReader``: - -.. code-block:: php - - use Doctrine\Common\Annotations\AnnotationReader; - use Doctrine\Common\Annotations\IndexedReader; - - $reader = new IndexedReader(new AnnotationReader()); - -.. warning:: - - You should never wrap the indexed reader inside a cached reader, - only the other way around. This way you can re-use the cache with - indexed or numeric keys, otherwise your code may experience failures - due to caching in a numerical or indexed format. - -Ignoring missing exceptions -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -By default an exception is thrown from the ``AnnotationReader`` if an -annotation was found that: - -- is not part of the list of ignored "documentation annotations"; -- was not imported through a use statement; -- is not a fully qualified class that exists. - -You can disable this behavior for specific names if your docblocks do -not follow strict requirements: - -.. code-block:: php - - $reader = new \Doctrine\Common\Annotations\AnnotationReader(); - AnnotationReader::addGlobalIgnoredName('foo'); - -PHP Imports -~~~~~~~~~~~ - -By default the annotation reader parses the use-statement of a php file -to gain access to the import rules and register them for the annotation -processing. Only if you are using PHP Imports can you validate the -correct usage of annotations and throw exceptions if you misspelled an -annotation. This mechanism is enabled by default. - -To ease the upgrade path, we still allow you to disable this mechanism. -Note however that we will remove this in future versions: - -.. code-block:: php - - $reader = new \Doctrine\Common\Annotations\AnnotationReader(); - $reader->setEnabledPhpImports(false); diff --git a/lib/doctrine/annotations/docs/en/custom.rst b/lib/doctrine/annotations/docs/en/custom.rst deleted file mode 100644 index 300516625..000000000 --- a/lib/doctrine/annotations/docs/en/custom.rst +++ /dev/null @@ -1,443 +0,0 @@ -Custom Annotation Classes -========================= - -If you want to define your own annotations, you just have to group them -in a namespace. -Annotation classes have to contain a class-level docblock with the text -``@Annotation``: - -.. code-block:: php - - namespace MyCompany\Annotations; - - /** @Annotation */ - class Bar - { - // some code - } - -Inject annotation values ------------------------- - -The annotation parser checks if the annotation constructor has arguments, -if so then it will pass the value array, otherwise it will try to inject -values into public properties directly: - - -.. code-block:: php - - namespace MyCompany\Annotations; - - /** - * @Annotation - * - * Some Annotation using a constructor - */ - class Bar - { - private $foo; - - public function __construct(array $values) - { - $this->foo = $values['foo']; - } - } - - /** - * @Annotation - * - * Some Annotation without a constructor - */ - class Foo - { - public $bar; - } - -Optional: Constructors with Named Parameters --------------------------------------------- - -Starting with Annotations v1.11 a new annotation instantiation strategy -is available that aims at compatibility of Annotation classes with the PHP 8 -attribute feature. You need to declare a constructor with regular parameter -names that match the named arguments in the annotation syntax. - -To enable this feature, you can tag your annotation class with -``@NamedArgumentConstructor`` (available from v1.12) or implement the -``Doctrine\Common\Annotations\NamedArgumentConstructorAnnotation`` interface -(available from v1.11 and deprecated as of v1.12). -When using the ``@NamedArgumentConstructor`` tag, the first argument of the -constructor is considered as the default one. - - -Usage with the ``@NamedArgumentConstructor`` tag - -.. code-block:: php - - namespace MyCompany\Annotations; - - /** - * @Annotation - * @NamedArgumentConstructor - */ - class Bar implements NamedArgumentConstructorAnnotation - { - private $foo; - - public function __construct(string $foo) - { - $this->foo = $foo; - } - } - - /** Usable with @Bar(foo="baz") */ - /** Usable with @Bar("baz") */ - -In combination with PHP 8's constructor property promotion feature -you can simplify this to: - -.. code-block:: php - - namespace MyCompany\Annotations; - - /** - * @Annotation - * @NamedArgumentConstructor - */ - class Bar implements NamedArgumentConstructorAnnotation - { - public function __construct(private string $foo) {} - } - - -Usage with the -``Doctrine\Common\Annotations\NamedArgumentConstructorAnnotation`` -interface (v1.11, deprecated as of v1.12): -.. code-block:: php - - namespace MyCompany\Annotations; - - use Doctrine\Common\Annotations\NamedArgumentConstructorAnnotation; - - /** @Annotation */ - class Bar implements NamedArgumentConstructorAnnotation - { - private $foo; - - public function __construct(private string $foo) {} - } - - /** Usable with @Bar(foo="baz") */ - -Annotation Target ------------------ - -``@Target`` indicates the kinds of class elements to which an annotation -type is applicable. Then you could define one or more targets: - -- ``CLASS`` Allowed in class docblocks -- ``PROPERTY`` Allowed in property docblocks -- ``METHOD`` Allowed in the method docblocks -- ``FUNCTION`` Allowed in function dockblocks -- ``ALL`` Allowed in class, property, method and function docblocks -- ``ANNOTATION`` Allowed inside other annotations - -If the annotations is not allowed in the current context, an -``AnnotationException`` is thrown. - -.. code-block:: php - - namespace MyCompany\Annotations; - - /** - * @Annotation - * @Target({"METHOD","PROPERTY"}) - */ - class Bar - { - // some code - } - - /** - * @Annotation - * @Target("CLASS") - */ - class Foo - { - // some code - } - -Attribute types ---------------- - -The annotation parser checks the given parameters using the phpdoc -annotation ``@var``, The data type could be validated using the ``@var`` -annotation on the annotation properties or using the ``@Attributes`` and -``@Attribute`` annotations. - -If the data type does not match you get an ``AnnotationException`` - -.. code-block:: php - - namespace MyCompany\Annotations; - - /** - * @Annotation - * @Target({"METHOD","PROPERTY"}) - */ - class Bar - { - /** @var mixed */ - public $mixed; - - /** @var boolean */ - public $boolean; - - /** @var bool */ - public $bool; - - /** @var float */ - public $float; - - /** @var string */ - public $string; - - /** @var integer */ - public $integer; - - /** @var array */ - public $array; - - /** @var SomeAnnotationClass */ - public $annotation; - - /** @var array<integer> */ - public $arrayOfIntegers; - - /** @var array<SomeAnnotationClass> */ - public $arrayOfAnnotations; - } - - /** - * @Annotation - * @Target({"METHOD","PROPERTY"}) - * @Attributes({ - * @Attribute("stringProperty", type = "string"), - * @Attribute("annotProperty", type = "SomeAnnotationClass"), - * }) - */ - class Foo - { - public function __construct(array $values) - { - $this->stringProperty = $values['stringProperty']; - $this->annotProperty = $values['annotProperty']; - } - - // some code - } - -Annotation Required -------------------- - -``@Required`` indicates that the field must be specified when the -annotation is used. If it is not used you get an ``AnnotationException`` -stating that this value can not be null. - -Declaring a required field: - -.. code-block:: php - - /** - * @Annotation - * @Target("ALL") - */ - class Foo - { - /** @Required */ - public $requiredField; - } - -Usage: - -.. code-block:: php - - /** @Foo(requiredField="value") */ - public $direction; // Valid - - /** @Foo */ - public $direction; // Required field missing, throws an AnnotationException - - -Enumerated values ------------------ - -- An annotation property marked with ``@Enum`` is a field that accepts a - fixed set of scalar values. -- You should use ``@Enum`` fields any time you need to represent fixed - values. -- The annotation parser checks the given value and throws an - ``AnnotationException`` if the value does not match. - - -Declaring an enumerated property: - -.. code-block:: php - - /** - * @Annotation - * @Target("ALL") - */ - class Direction - { - /** - * @Enum({"NORTH", "SOUTH", "EAST", "WEST"}) - */ - public $value; - } - -Annotation usage: - -.. code-block:: php - - /** @Direction("NORTH") */ - public $direction; // Valid value - - /** @Direction("NORTHEAST") */ - public $direction; // Invalid value, throws an AnnotationException - - -Constants ---------- - -The use of constants and class constants is available on the annotations -parser. - -The following usages are allowed: - -.. code-block:: php - - namespace MyCompany\Entity; - - use MyCompany\Annotations\Foo; - use MyCompany\Annotations\Bar; - use MyCompany\Entity\SomeClass; - - /** - * @Foo(PHP_EOL) - * @Bar(Bar::FOO) - * @Foo({SomeClass::FOO, SomeClass::BAR}) - * @Bar({SomeClass::FOO_KEY = SomeClass::BAR_VALUE}) - */ - class User - { - } - - -Be careful with constants and the cache ! - -.. note:: - - The cached reader will not re-evaluate each time an annotation is - loaded from cache. When a constant is changed the cache must be - cleaned. - - -Usage ------ - -Using the library API is simple. Using the annotations described in the -previous section, you can now annotate other classes with your -annotations: - -.. code-block:: php - - namespace MyCompany\Entity; - - use MyCompany\Annotations\Foo; - use MyCompany\Annotations\Bar; - - /** - * @Foo(bar="foo") - * @Bar(foo="bar") - */ - class User - { - } - -Now we can write a script to get the annotations above: - -.. code-block:: php - - $reflClass = new ReflectionClass('MyCompany\Entity\User'); - $classAnnotations = $reader->getClassAnnotations($reflClass); - - foreach ($classAnnotations AS $annot) { - if ($annot instanceof \MyCompany\Annotations\Foo) { - echo $annot->bar; // prints "foo"; - } else if ($annot instanceof \MyCompany\Annotations\Bar) { - echo $annot->foo; // prints "bar"; - } - } - -You have a complete API for retrieving annotation class instances from a -class, property or method docblock: - - -Reader API -~~~~~~~~~~ - -Access all annotations of a class -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: php - - public function getClassAnnotations(\ReflectionClass $class); - -Access one annotation of a class -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: php - - public function getClassAnnotation(\ReflectionClass $class, $annotationName); - -Access all annotations of a method -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: php - - public function getMethodAnnotations(\ReflectionMethod $method); - -Access one annotation of a method -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: php - - public function getMethodAnnotation(\ReflectionMethod $method, $annotationName); - -Access all annotations of a property -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: php - - public function getPropertyAnnotations(\ReflectionProperty $property); - -Access one annotation of a property -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: php - - public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName); - -Access all annotations of a function -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: php - - public function getFunctionAnnotations(\ReflectionFunction $property); - -Access one annotation of a function -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: php - - public function getFunctionAnnotation(\ReflectionFunction $property, $annotationName); diff --git a/lib/doctrine/annotations/docs/en/index.rst b/lib/doctrine/annotations/docs/en/index.rst deleted file mode 100644 index a6e338333..000000000 --- a/lib/doctrine/annotations/docs/en/index.rst +++ /dev/null @@ -1,102 +0,0 @@ -Deprecation notice -================== - -PHP 8 introduced `attributes -<https://www.php.net/manual/en/language.attributes.overview.php>`_, -which are a native replacement for annotations. As such, this library is -considered feature complete, and should receive exclusively bugfixes and -security fixes. - -Introduction -============ - -Doctrine Annotations allows to implement custom annotation -functionality for PHP classes and functions. - -.. code-block:: php - - class Foo - { - /** - * @MyAnnotation(myProperty="value") - */ - private $bar; - } - -Annotations aren't implemented in PHP itself which is why this component -offers a way to use the PHP doc-blocks as a place for the well known -annotation syntax using the ``@`` char. - -Annotations in Doctrine are used for the ORM configuration to build the -class mapping, but it can be used in other projects for other purposes -too. - -Installation -============ - -You can install the Annotation component with composer: - -.. code-block:: - -   $ composer require doctrine/annotations - -Create an annotation class -========================== - -An annotation class is a representation of the later used annotation -configuration in classes. The annotation class of the previous example -looks like this: - -.. code-block:: php - - /** - * @Annotation - */ - final class MyAnnotation - { - public $myProperty; - } - -The annotation class is declared as an annotation by ``@Annotation``. - -:ref:`Read more about custom annotations. <custom>` - -Reading annotations -=================== - -The access to the annotations happens by reflection of the class or function -containing them. There are multiple reader-classes implementing the -``Doctrine\Common\Annotations\Reader`` interface, that can access the -annotations of a class. A common one is -``Doctrine\Common\Annotations\AnnotationReader``: - -.. code-block:: php - - use Doctrine\Common\Annotations\AnnotationReader; - - $reflectionClass = new ReflectionClass(Foo::class); - $property = $reflectionClass->getProperty('bar'); - - $reader = new AnnotationReader(); - $myAnnotation = $reader->getPropertyAnnotation( - $property, - MyAnnotation::class - ); - - echo $myAnnotation->myProperty; // result: "value" - -A reader has multiple methods to access the annotations of a class or -function. - -:ref:`Read more about handling annotations. <annotations>` - -IDE Support ------------ - -Some IDEs already provide support for annotations: - -- Eclipse via the `Symfony2 Plugin <https://github.com/pulse00/Symfony-2-Eclipse-Plugin>`_ -- PhpStorm via the `PHP Annotations Plugin <https://plugins.jetbrains.com/plugin/7320-php-annotations>`_ or the `Symfony Plugin <https://plugins.jetbrains.com/plugin/7219-symfony-support>`_ - -.. _Read more about handling annotations.: annotations -.. _Read more about custom annotations.: custom diff --git a/lib/doctrine/annotations/docs/en/sidebar.rst b/lib/doctrine/annotations/docs/en/sidebar.rst deleted file mode 100644 index 6f5d13c46..000000000 --- a/lib/doctrine/annotations/docs/en/sidebar.rst +++ /dev/null @@ -1,6 +0,0 @@ -.. toctree:: - :depth: 3 - - index - annotations - custom diff --git a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php b/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php deleted file mode 100644 index fba23e9f1..000000000 --- a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php - -namespace Doctrine\Common\Annotations; - -use BadMethodCallException; - -use function sprintf; - -/** - * Annotations class. - */ -class Annotation -{ - /** - * Value property. Common among all derived classes. - * - * @var mixed - */ - public $value; - - /** @param array<string, mixed> $data Key-value for properties to be defined in this class. */ - final public function __construct(array $data) - { - foreach ($data as $key => $value) { - $this->$key = $value; - } - } - - /** - * Error handler for unknown property accessor in Annotation class. - * - * @throws BadMethodCallException - */ - public function __get(string $name) - { - throw new BadMethodCallException( - sprintf("Unknown property '%s' on annotation '%s'.", $name, static::class) - ); - } - - /** - * Error handler for unknown property mutator in Annotation class. - * - * @param mixed $value Property value. - * - * @throws BadMethodCallException - */ - public function __set(string $name, $value) - { - throw new BadMethodCallException( - sprintf("Unknown property '%s' on annotation '%s'.", $name, static::class) - ); - } -} diff --git a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php b/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php deleted file mode 100644 index b1f851400..000000000 --- a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -namespace Doctrine\Common\Annotations\Annotation; - -/** - * Annotation that can be used to signal to the parser - * to check the attribute type during the parsing process. - * - * @Annotation - */ -final class Attribute -{ - /** @var string */ - public $name; - - /** @var string */ - public $type; - - /** @var bool */ - public $required = false; -} diff --git a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attributes.php b/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attributes.php deleted file mode 100644 index 8f758f3f7..000000000 --- a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attributes.php +++ /dev/null @@ -1,15 +0,0 @@ -<?php - -namespace Doctrine\Common\Annotations\Annotation; - -/** - * Annotation that can be used to signal to the parser - * to check the types of all declared attributes during the parsing process. - * - * @Annotation - */ -final class Attributes -{ - /** @var array<Attribute> */ - public $value; -} diff --git a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php b/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php deleted file mode 100644 index 6f24d9f1b..000000000 --- a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php - -namespace Doctrine\Common\Annotations\Annotation; - -use InvalidArgumentException; - -use function get_class; -use function gettype; -use function in_array; -use function is_object; -use function is_scalar; -use function sprintf; - -/** - * Annotation that can be used to signal to the parser - * to check the available values during the parsing process. - * - * @Annotation - * @Attributes({ - * @Attribute("value", required = true, type = "array"), - * @Attribute("literal", required = false, type = "array") - * }) - */ -final class Enum -{ - /** @phpstan-var list<scalar> */ - public $value; - - /** - * Literal target declaration. - * - * @var mixed[] - */ - public $literal; - - /** - * @phpstan-param array{literal?: mixed[], value: list<scalar>} $values - * - * @throws InvalidArgumentException - */ - public function __construct(array $values) - { - if (! isset($values['literal'])) { - $values['literal'] = []; - } - - foreach ($values['value'] as $var) { - if (! is_scalar($var)) { - throw new InvalidArgumentException(sprintf( - '@Enum supports only scalar values "%s" given.', - is_object($var) ? get_class($var) : gettype($var) - )); - } - } - - foreach ($values['literal'] as $key => $var) { - if (! in_array($key, $values['value'])) { - throw new InvalidArgumentException(sprintf( - 'Undefined enumerator value "%s" for literal "%s".', - $key, - $var - )); - } - } - - $this->value = $values['value']; - $this->literal = $values['literal']; - } -} diff --git a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php b/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php deleted file mode 100644 index 97a15c257..000000000 --- a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -namespace Doctrine\Common\Annotations\Annotation; - -use RuntimeException; - -use function is_array; -use function is_string; -use function json_encode; -use function sprintf; - -/** - * Annotation that can be used to signal to the parser to ignore specific - * annotations during the parsing process. - * - * @Annotation - */ -final class IgnoreAnnotation -{ - /** @phpstan-var list<string> */ - public $names; - - /** - * @phpstan-param array{value: string|list<string>} $values - * - * @throws RuntimeException - */ - public function __construct(array $values) - { - if (is_string($values['value'])) { - $values['value'] = [$values['value']]; - } - - if (! is_array($values['value'])) { - throw new RuntimeException(sprintf( - '@IgnoreAnnotation expects either a string name, or an array of strings, but got %s.', - json_encode($values['value']) - )); - } - - $this->names = $values['value']; - } -} diff --git a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/NamedArgumentConstructor.php b/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/NamedArgumentConstructor.php deleted file mode 100644 index 169060103..000000000 --- a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/NamedArgumentConstructor.php +++ /dev/null @@ -1,13 +0,0 @@ -<?php - -namespace Doctrine\Common\Annotations\Annotation; - -/** - * Annotation that indicates that the annotated class should be constructed with a named argument call. - * - * @Annotation - * @Target("CLASS") - */ -final class NamedArgumentConstructor -{ -} diff --git a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Required.php b/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Required.php deleted file mode 100644 index dee585755..000000000 --- a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Required.php +++ /dev/null @@ -1,13 +0,0 @@ -<?php - -namespace Doctrine\Common\Annotations\Annotation; - -/** - * Annotation that can be used to signal to the parser - * to check if that attribute is required during the parsing process. - * - * @Annotation - */ -final class Required -{ -} diff --git a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Target.php b/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Target.php deleted file mode 100644 index ba1d489ac..000000000 --- a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Target.php +++ /dev/null @@ -1,101 +0,0 @@ -<?php - -namespace Doctrine\Common\Annotations\Annotation; - -use InvalidArgumentException; - -use function array_keys; -use function get_class; -use function gettype; -use function implode; -use function is_array; -use function is_object; -use function is_string; -use function sprintf; - -/** - * Annotation that can be used to signal to the parser - * to check the annotation target during the parsing process. - * - * @Annotation - */ -final class Target -{ - public const TARGET_CLASS = 1; - public const TARGET_METHOD = 2; - public const TARGET_PROPERTY = 4; - public const TARGET_ANNOTATION = 8; - public const TARGET_FUNCTION = 16; - public const TARGET_ALL = 31; - - /** @var array<string, int> */ - private static $map = [ - 'ALL' => self::TARGET_ALL, - 'CLASS' => self::TARGET_CLASS, - 'METHOD' => self::TARGET_METHOD, - 'PROPERTY' => self::TARGET_PROPERTY, - 'FUNCTION' => self::TARGET_FUNCTION, - 'ANNOTATION' => self::TARGET_ANNOTATION, - ]; - - /** @phpstan-var list<string> */ - public $value; - - /** - * Targets as bitmask. - * - * @var int - */ - public $targets; - - /** - * Literal target declaration. - * - * @var string - */ - public $literal; - - /** - * @phpstan-param array{value?: string|list<string>} $values - * - * @throws InvalidArgumentException - */ - public function __construct(array $values) - { - if (! isset($values['value'])) { - $values['value'] = null; - } - - if (is_string($values['value'])) { - $values['value'] = [$values['value']]; - } - - if (! is_array($values['value'])) { - throw new InvalidArgumentException( - sprintf( - '@Target expects either a string value, or an array of strings, "%s" given.', - is_object($values['value']) ? get_class($values['value']) : gettype($values['value']) - ) - ); - } - - $bitmask = 0; - foreach ($values['value'] as $literal) { - if (! isset(self::$map[$literal])) { - throw new InvalidArgumentException( - sprintf( - 'Invalid Target "%s". Available targets: [%s]', - $literal, - implode(', ', array_keys(self::$map)) - ) - ); - } - - $bitmask |= self::$map[$literal]; - } - - $this->targets = $bitmask; - $this->value = $values['value']; - $this->literal = implode(', ', $this->value); - } -} diff --git a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php b/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php deleted file mode 100644 index 002ee0491..000000000 --- a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php +++ /dev/null @@ -1,158 +0,0 @@ -<?php - -namespace Doctrine\Common\Annotations; - -use Exception; -use Throwable; - -use function get_class; -use function gettype; -use function implode; -use function is_object; -use function sprintf; - -/** - * Description of AnnotationException - */ -class AnnotationException extends Exception -{ - /** - * Creates a new AnnotationException describing a Syntax error. - * - * @return AnnotationException - */ - public static function syntaxError(string $message) - { - return new self('[Syntax Error] ' . $message); - } - - /** - * Creates a new AnnotationException describing a Semantical error. - * - * @return AnnotationException - */ - public static function semanticalError(string $message) - { - return new self('[Semantical Error] ' . $message); - } - - /** - * Creates a new AnnotationException describing an error which occurred during - * the creation of the annotation. - * - * @return AnnotationException - */ - public static function creationError(string $message, ?Throwable $previous = null) - { - return new self('[Creation Error] ' . $message, 0, $previous); - } - - /** - * Creates a new AnnotationException describing a type error. - * - * @return AnnotationException - */ - public static function typeError(string $message) - { - return new self('[Type Error] ' . $message); - } - - /** - * Creates a new AnnotationException describing a constant semantical error. - * - * @return AnnotationException - */ - public static function semanticalErrorConstants(string $identifier, ?string $context = null) - { - return self::semanticalError(sprintf( - "Couldn't find constant %s%s.", - $identifier, - $context ? ', ' . $context : '' - )); - } - - /** - * Creates a new AnnotationException describing an type error of an attribute. - * - * @param mixed $actual - * - * @return AnnotationException - */ - public static function attributeTypeError( - string $attributeName, - string $annotationName, - string $context, - string $expected, - $actual - ) { - return self::typeError(sprintf( - 'Attribute "%s" of @%s declared on %s expects %s, but got %s.', - $attributeName, - $annotationName, - $context, - $expected, - is_object($actual) ? 'an instance of ' . get_class($actual) : gettype($actual) - )); - } - - /** - * Creates a new AnnotationException describing an required error of an attribute. - * - * @return AnnotationException - */ - public static function requiredError( - string $attributeName, - string $annotationName, - string $context, - string $expected - ) { - return self::typeError(sprintf( - 'Attribute "%s" of @%s declared on %s expects %s. This value should not be null.', - $attributeName, - $annotationName, - $context, - $expected - )); - } - - /** - * Creates a new AnnotationException describing a invalid enummerator. - * - * @param mixed $given - * @phpstan-param list<string> $available - * - * @return AnnotationException - */ - public static function enumeratorError( - string $attributeName, - string $annotationName, - string $context, - array $available, - $given - ) { - return new self(sprintf( - '[Enum Error] Attribute "%s" of @%s declared on %s accepts only [%s], but got %s.', - $attributeName, - $annotationName, - $context, - implode(', ', $available), - is_object($given) ? get_class($given) : $given - )); - } - - /** @return AnnotationException */ - public static function optimizerPlusSaveComments() - { - return new self( - 'You have to enable opcache.save_comments=1 or zend_optimizerplus.save_comments=1.' - ); - } - - /** @return AnnotationException */ - public static function optimizerPlusLoadComments() - { - return new self( - 'You have to enable opcache.load_comments=1 or zend_optimizerplus.load_comments=1.' - ); - } -} diff --git a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php b/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php deleted file mode 100644 index 31f3777a8..000000000 --- a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php +++ /dev/null @@ -1,385 +0,0 @@ -<?php - -namespace Doctrine\Common\Annotations; - -use Doctrine\Common\Annotations\Annotation\IgnoreAnnotation; -use Doctrine\Common\Annotations\Annotation\Target; -use ReflectionClass; -use ReflectionFunction; -use ReflectionMethod; -use ReflectionProperty; - -use function array_merge; -use function class_exists; -use function extension_loaded; -use function ini_get; - -/** - * A reader for docblock annotations. - */ -class AnnotationReader implements Reader -{ - /** - * Global map for imports. - * - * @var array<string, class-string> - */ - private static $globalImports = [ - 'ignoreannotation' => Annotation\IgnoreAnnotation::class, - ]; - - /** - * A list with annotations that are not causing exceptions when not resolved to an annotation class. - * - * The names are case sensitive. - * - * @var array<string, true> - */ - private static $globalIgnoredNames = ImplicitlyIgnoredAnnotationNames::LIST; - - /** - * A list with annotations that are not causing exceptions when not resolved to an annotation class. - * - * The names are case sensitive. - * - * @var array<string, true> - */ - private static $globalIgnoredNamespaces = []; - - /** - * Add a new annotation to the globally ignored annotation names with regard to exception handling. - */ - public static function addGlobalIgnoredName(string $name) - { - self::$globalIgnoredNames[$name] = true; - } - - /** - * Add a new annotation to the globally ignored annotation namespaces with regard to exception handling. - */ - public static function addGlobalIgnoredNamespace(string $namespace) - { - self::$globalIgnoredNamespaces[$namespace] = true; - } - - /** - * Annotations parser. - * - * @var DocParser - */ - private $parser; - - /** - * Annotations parser used to collect parsing metadata. - * - * @var DocParser - */ - private $preParser; - - /** - * PHP parser used to collect imports. - * - * @var PhpParser - */ - private $phpParser; - - /** - * In-memory cache mechanism to store imported annotations per class. - * - * @psalm-var array<'class'|'function', array<string, array<string, class-string>>> - */ - private $imports = []; - - /** - * In-memory cache mechanism to store ignored annotations per class. - * - * @psalm-var array<'class'|'function', array<string, array<string, true>>> - */ - private $ignoredAnnotationNames = []; - - /** - * Initializes a new AnnotationReader. - * - * @throws AnnotationException - */ - public function __construct(?DocParser $parser = null) - { - if ( - extension_loaded('Zend Optimizer+') && (ini_get('zend_optimizerplus.save_comments') === '0' || - ini_get('opcache.save_comments') === '0') - ) { - throw AnnotationException::optimizerPlusSaveComments(); - } - - if (extension_loaded('Zend OPcache') && ini_get('opcache.save_comments') === 0) { - throw AnnotationException::optimizerPlusSaveComments(); - } - - // Make sure that the IgnoreAnnotation annotation is loaded - class_exists(IgnoreAnnotation::class); - - $this->parser = $parser ?: new DocParser(); - - $this->preParser = new DocParser(); - - $this->preParser->setImports(self::$globalImports); - $this->preParser->setIgnoreNotImportedAnnotations(true); - $this->preParser->setIgnoredAnnotationNames(self::$globalIgnoredNames); - - $this->phpParser = new PhpParser(); - } - - /** - * {@inheritDoc} - */ - public function getClassAnnotations(ReflectionClass $class) - { - $this->parser->setTarget(Target::TARGET_CLASS); - $this->parser->setImports($this->getImports($class)); - $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class)); - $this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces); - - return $this->parser->parse($class->getDocComment(), 'class ' . $class->getName()); - } - - /** - * {@inheritDoc} - */ - public function getClassAnnotation(ReflectionClass $class, $annotationName) - { - $annotations = $this->getClassAnnotations($class); - - foreach ($annotations as $annotation) { - if ($annotation instanceof $annotationName) { - return $annotation; - } - } - - return null; - } - - /** - * {@inheritDoc} - */ - public function getPropertyAnnotations(ReflectionProperty $property) - { - $class = $property->getDeclaringClass(); - $context = 'property ' . $class->getName() . '::$' . $property->getName(); - - $this->parser->setTarget(Target::TARGET_PROPERTY); - $this->parser->setImports($this->getPropertyImports($property)); - $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class)); - $this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces); - - return $this->parser->parse($property->getDocComment(), $context); - } - - /** - * {@inheritDoc} - */ - public function getPropertyAnnotation(ReflectionProperty $property, $annotationName) - { - $annotations = $this->getPropertyAnnotations($property); - - foreach ($annotations as $annotation) { - if ($annotation instanceof $annotationName) { - return $annotation; - } - } - - return null; - } - - /** - * {@inheritDoc} - */ - public function getMethodAnnotations(ReflectionMethod $method) - { - $class = $method->getDeclaringClass(); - $context = 'method ' . $class->getName() . '::' . $method->getName() . '()'; - - $this->parser->setTarget(Target::TARGET_METHOD); - $this->parser->setImports($this->getMethodImports($method)); - $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class)); - $this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces); - - return $this->parser->parse($method->getDocComment(), $context); - } - - /** - * {@inheritDoc} - */ - public function getMethodAnnotation(ReflectionMethod $method, $annotationName) - { - $annotations = $this->getMethodAnnotations($method); - - foreach ($annotations as $annotation) { - if ($annotation instanceof $annotationName) { - return $annotation; - } - } - - return null; - } - - /** - * Gets the annotations applied to a function. - * - * @phpstan-return list<object> An array of Annotations. - */ - public function getFunctionAnnotations(ReflectionFunction $function): array - { - $context = 'function ' . $function->getName(); - - $this->parser->setTarget(Target::TARGET_FUNCTION); - $this->parser->setImports($this->getImports($function)); - $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($function)); - $this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces); - - return $this->parser->parse($function->getDocComment(), $context); - } - - /** - * Gets a function annotation. - * - * @return object|null The Annotation or NULL, if the requested annotation does not exist. - */ - public function getFunctionAnnotation(ReflectionFunction $function, string $annotationName) - { - $annotations = $this->getFunctionAnnotations($function); - - foreach ($annotations as $annotation) { - if ($annotation instanceof $annotationName) { - return $annotation; - } - } - - return null; - } - - /** - * Returns the ignored annotations for the given class or function. - * - * @param ReflectionClass|ReflectionFunction $reflection - * - * @return array<string, true> - */ - private function getIgnoredAnnotationNames($reflection): array - { - $type = $reflection instanceof ReflectionClass ? 'class' : 'function'; - $name = $reflection->getName(); - - if (isset($this->ignoredAnnotationNames[$type][$name])) { - return $this->ignoredAnnotationNames[$type][$name]; - } - - $this->collectParsingMetadata($reflection); - - return $this->ignoredAnnotationNames[$type][$name]; - } - - /** - * Retrieves imports for a class or a function. - * - * @param ReflectionClass|ReflectionFunction $reflection - * - * @return array<string, class-string> - */ - private function getImports($reflection): array - { - $type = $reflection instanceof ReflectionClass ? 'class' : 'function'; - $name = $reflection->getName(); - - if (isset($this->imports[$type][$name])) { - return $this->imports[$type][$name]; - } - - $this->collectParsingMetadata($reflection); - - return $this->imports[$type][$name]; - } - - /** - * Retrieves imports for methods. - * - * @return array<string, class-string> - */ - private function getMethodImports(ReflectionMethod $method) - { - $class = $method->getDeclaringClass(); - $classImports = $this->getImports($class); - - $traitImports = []; - - foreach ($class->getTraits() as $trait) { - if ( - ! $trait->hasMethod($method->getName()) - || $trait->getFileName() !== $method->getFileName() - ) { - continue; - } - - $traitImports = array_merge($traitImports, $this->phpParser->parseUseStatements($trait)); - } - - return array_merge($classImports, $traitImports); - } - - /** - * Retrieves imports for properties. - * - * @return array<string, class-string> - */ - private function getPropertyImports(ReflectionProperty $property) - { - $class = $property->getDeclaringClass(); - $classImports = $this->getImports($class); - - $traitImports = []; - - foreach ($class->getTraits() as $trait) { - if (! $trait->hasProperty($property->getName())) { - continue; - } - - $traitImports = array_merge($traitImports, $this->phpParser->parseUseStatements($trait)); - } - - return array_merge($classImports, $traitImports); - } - - /** - * Collects parsing metadata for a given class or function. - * - * @param ReflectionClass|ReflectionFunction $reflection - */ - private function collectParsingMetadata($reflection): void - { - $type = $reflection instanceof ReflectionClass ? 'class' : 'function'; - $name = $reflection->getName(); - - $ignoredAnnotationNames = self::$globalIgnoredNames; - $annotations = $this->preParser->parse($reflection->getDocComment(), $type . ' ' . $name); - - foreach ($annotations as $annotation) { - if (! ($annotation instanceof IgnoreAnnotation)) { - continue; - } - - foreach ($annotation->names as $annot) { - $ignoredAnnotationNames[$annot] = true; - } - } - - $this->imports[$type][$name] = array_merge( - self::$globalImports, - $this->phpParser->parseUseStatements($reflection), - [ - '__NAMESPACE__' => $reflection->getNamespaceName(), - 'self' => $name, - ] - ); - - $this->ignoredAnnotationNames[$type][$name] = $ignoredAnnotationNames; - } -} diff --git a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php b/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php deleted file mode 100644 index 290e60aba..000000000 --- a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -namespace Doctrine\Common\Annotations; - -use function array_key_exists; -use function class_exists; - -final class AnnotationRegistry -{ - /** - * An array of classes which cannot be found - * - * @var null[] indexed by class name - */ - private static $failedToAutoload = []; - - public static function reset(): void - { - self::$failedToAutoload = []; - } - - /** - * Autoloads an annotation class silently. - */ - public static function loadAnnotationClass(string $class): bool - { - if (class_exists($class, false)) { - return true; - } - - if (array_key_exists($class, self::$failedToAutoload)) { - return false; - } - - if (class_exists($class)) { - return true; - } - - self::$failedToAutoload[$class] = null; - - return false; - } -} diff --git a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php b/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php deleted file mode 100644 index cbb86a708..000000000 --- a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php +++ /dev/null @@ -1,131 +0,0 @@ -<?php - -namespace Doctrine\Common\Annotations; - -use Doctrine\Common\Lexer\AbstractLexer; - -use function ctype_alpha; -use function is_numeric; -use function str_replace; -use function stripos; -use function strlen; -use function strpos; -use function strtolower; -use function substr; - -/** - * Simple lexer for docblock annotations. - * - * @template-extends AbstractLexer<DocLexer::T_*, string> - */ -final class DocLexer extends AbstractLexer -{ - public const T_NONE = 1; - public const T_INTEGER = 2; - public const T_STRING = 3; - public const T_FLOAT = 4; - - // All tokens that are also identifiers should be >= 100 - public const T_IDENTIFIER = 100; - public const T_AT = 101; - public const T_CLOSE_CURLY_BRACES = 102; - public const T_CLOSE_PARENTHESIS = 103; - public const T_COMMA = 104; - public const T_EQUALS = 105; - public const T_FALSE = 106; - public const T_NAMESPACE_SEPARATOR = 107; - public const T_OPEN_CURLY_BRACES = 108; - public const T_OPEN_PARENTHESIS = 109; - public const T_TRUE = 110; - public const T_NULL = 111; - public const T_COLON = 112; - public const T_MINUS = 113; - - /** @var array<string, self::T*> */ - protected $noCase = [ - '@' => self::T_AT, - ',' => self::T_COMMA, - '(' => self::T_OPEN_PARENTHESIS, - ')' => self::T_CLOSE_PARENTHESIS, - '{' => self::T_OPEN_CURLY_BRACES, - '}' => self::T_CLOSE_CURLY_BRACES, - '=' => self::T_EQUALS, - ':' => self::T_COLON, - '-' => self::T_MINUS, - '\\' => self::T_NAMESPACE_SEPARATOR, - ]; - - /** @var array<string, self::T*> */ - protected $withCase = [ - 'true' => self::T_TRUE, - 'false' => self::T_FALSE, - 'null' => self::T_NULL, - ]; - - /** - * Whether the next token starts immediately, or if there were - * non-captured symbols before that - */ - public function nextTokenIsAdjacent(): bool - { - return $this->token === null - || ($this->lookahead !== null - && ($this->lookahead->position - $this->token->position) === strlen($this->token->value)); - } - - /** - * {@inheritdoc} - */ - protected function getCatchablePatterns() - { - return [ - '[a-z_\\\][a-z0-9_\:\\\]*[a-z_][a-z0-9_]*', - '(?:[+-]?[0-9]+(?:[\.][0-9]+)*)(?:[eE][+-]?[0-9]+)?', - '"(?:""|[^"])*+"', - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNonCatchablePatterns() - { - return ['\s+', '\*+', '(.)']; - } - - /** - * {@inheritdoc} - */ - protected function getType(&$value) - { - $type = self::T_NONE; - - if ($value[0] === '"') { - $value = str_replace('""', '"', substr($value, 1, strlen($value) - 2)); - - return self::T_STRING; - } - - if (isset($this->noCase[$value])) { - return $this->noCase[$value]; - } - - if ($value[0] === '_' || $value[0] === '\\' || ctype_alpha($value[0])) { - return self::T_IDENTIFIER; - } - - $lowerValue = strtolower($value); - - if (isset($this->withCase[$lowerValue])) { - return $this->withCase[$lowerValue]; - } - - // Checking numeric value - if (is_numeric($value)) { - return strpos($value, '.') !== false || stripos($value, 'e') !== false - ? self::T_FLOAT : self::T_INTEGER; - } - - return $type; - } -} diff --git a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php b/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php deleted file mode 100644 index a12c15e74..000000000 --- a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php +++ /dev/null @@ -1,1494 +0,0 @@ -<?php - -namespace Doctrine\Common\Annotations; - -use Doctrine\Common\Annotations\Annotation\Attribute; -use Doctrine\Common\Annotations\Annotation\Attributes; -use Doctrine\Common\Annotations\Annotation\Enum; -use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor; -use Doctrine\Common\Annotations\Annotation\Target; -use ReflectionClass; -use ReflectionException; -use ReflectionProperty; -use RuntimeException; -use stdClass; -use Throwable; - -use function array_keys; -use function array_map; -use function array_pop; -use function array_values; -use function class_exists; -use function constant; -use function count; -use function defined; -use function explode; -use function gettype; -use function implode; -use function in_array; -use function interface_exists; -use function is_array; -use function is_object; -use function json_encode; -use function ltrim; -use function preg_match; -use function reset; -use function rtrim; -use function sprintf; -use function stripos; -use function strlen; -use function strpos; -use function strrpos; -use function strtolower; -use function substr; -use function trim; - -use const PHP_VERSION_ID; - -/** - * A parser for docblock annotations. - * - * It is strongly discouraged to change the default annotation parsing process. - */ -final class DocParser -{ - /** - * An array of all valid tokens for a class name. - * - * @phpstan-var list<int> - */ - private static $classIdentifiers = [ - DocLexer::T_IDENTIFIER, - DocLexer::T_TRUE, - DocLexer::T_FALSE, - DocLexer::T_NULL, - ]; - - /** - * The lexer. - * - * @var DocLexer - */ - private $lexer; - - /** - * Current target context. - * - * @var int - */ - private $target; - - /** - * Doc parser used to collect annotation target. - * - * @var DocParser - */ - private static $metadataParser; - - /** - * Flag to control if the current annotation is nested or not. - * - * @var bool - */ - private $isNestedAnnotation = false; - - /** - * Hashmap containing all use-statements that are to be used when parsing - * the given doc block. - * - * @var array<string, class-string> - */ - private $imports = []; - - /** - * This hashmap is used internally to cache results of class_exists() - * look-ups. - * - * @var array<class-string, bool> - */ - private $classExists = []; - - /** - * Whether annotations that have not been imported should be ignored. - * - * @var bool - */ - private $ignoreNotImportedAnnotations = false; - - /** - * An array of default namespaces if operating in simple mode. - * - * @var string[] - */ - private $namespaces = []; - - /** - * A list with annotations that are not causing exceptions when not resolved to an annotation class. - * - * The names must be the raw names as used in the class, not the fully qualified - * - * @var bool[] indexed by annotation name - */ - private $ignoredAnnotationNames = []; - - /** - * A list with annotations in namespaced format - * that are not causing exceptions when not resolved to an annotation class. - * - * @var bool[] indexed by namespace name - */ - private $ignoredAnnotationNamespaces = []; - - /** @var string */ - private $context = ''; - - /** - * Hash-map for caching annotation metadata. - * - * @var array<class-string, mixed[]> - */ - private static $annotationMetadata = [ - Annotation\Target::class => [ - 'is_annotation' => true, - 'has_constructor' => true, - 'has_named_argument_constructor' => false, - 'properties' => [], - 'targets_literal' => 'ANNOTATION_CLASS', - 'targets' => Target::TARGET_CLASS, - 'default_property' => 'value', - 'attribute_types' => [ - 'value' => [ - 'required' => false, - 'type' => 'array', - 'array_type' => 'string', - 'value' => 'array<string>', - ], - ], - ], - Annotation\Attribute::class => [ - 'is_annotation' => true, - 'has_constructor' => false, - 'has_named_argument_constructor' => false, - 'targets_literal' => 'ANNOTATION_ANNOTATION', - 'targets' => Target::TARGET_ANNOTATION, - 'default_property' => 'name', - 'properties' => [ - 'name' => 'name', - 'type' => 'type', - 'required' => 'required', - ], - 'attribute_types' => [ - 'value' => [ - 'required' => true, - 'type' => 'string', - 'value' => 'string', - ], - 'type' => [ - 'required' => true, - 'type' => 'string', - 'value' => 'string', - ], - 'required' => [ - 'required' => false, - 'type' => 'boolean', - 'value' => 'boolean', - ], - ], - ], - Annotation\Attributes::class => [ - 'is_annotation' => true, - 'has_constructor' => false, - 'has_named_argument_constructor' => false, - 'targets_literal' => 'ANNOTATION_CLASS', - 'targets' => Target::TARGET_CLASS, - 'default_property' => 'value', - 'properties' => ['value' => 'value'], - 'attribute_types' => [ - 'value' => [ - 'type' => 'array', - 'required' => true, - 'array_type' => Annotation\Attribute::class, - 'value' => 'array<' . Annotation\Attribute::class . '>', - ], - ], - ], - Annotation\Enum::class => [ - 'is_annotation' => true, - 'has_constructor' => true, - 'has_named_argument_constructor' => false, - 'targets_literal' => 'ANNOTATION_PROPERTY', - 'targets' => Target::TARGET_PROPERTY, - 'default_property' => 'value', - 'properties' => ['value' => 'value'], - 'attribute_types' => [ - 'value' => [ - 'type' => 'array', - 'required' => true, - ], - 'literal' => [ - 'type' => 'array', - 'required' => false, - ], - ], - ], - Annotation\NamedArgumentConstructor::class => [ - 'is_annotation' => true, - 'has_constructor' => false, - 'has_named_argument_constructor' => false, - 'targets_literal' => 'ANNOTATION_CLASS', - 'targets' => Target::TARGET_CLASS, - 'default_property' => null, - 'properties' => [], - 'attribute_types' => [], - ], - ]; - - /** - * Hash-map for handle types declaration. - * - * @var array<string, string> - */ - private static $typeMap = [ - 'float' => 'double', - 'bool' => 'boolean', - // allow uppercase Boolean in honor of George Boole - 'Boolean' => 'boolean', - 'int' => 'integer', - ]; - - /** - * Constructs a new DocParser. - */ - public function __construct() - { - $this->lexer = new DocLexer(); - } - - /** - * Sets the annotation names that are ignored during the parsing process. - * - * The names are supposed to be the raw names as used in the class, not the - * fully qualified class names. - * - * @param bool[] $names indexed by annotation name - * - * @return void - */ - public function setIgnoredAnnotationNames(array $names) - { - $this->ignoredAnnotationNames = $names; - } - - /** - * Sets the annotation namespaces that are ignored during the parsing process. - * - * @param bool[] $ignoredAnnotationNamespaces indexed by annotation namespace name - * - * @return void - */ - public function setIgnoredAnnotationNamespaces(array $ignoredAnnotationNamespaces) - { - $this->ignoredAnnotationNamespaces = $ignoredAnnotationNamespaces; - } - - /** - * Sets ignore on not-imported annotations. - * - * @return void - */ - public function setIgnoreNotImportedAnnotations(bool $bool) - { - $this->ignoreNotImportedAnnotations = $bool; - } - - /** - * Sets the default namespaces. - * - * @return void - * - * @throws RuntimeException - */ - public function addNamespace(string $namespace) - { - if ($this->imports) { - throw new RuntimeException('You must either use addNamespace(), or setImports(), but not both.'); - } - - $this->namespaces[] = $namespace; - } - - /** - * Sets the imports. - * - * @param array<string, class-string> $imports - * - * @return void - * - * @throws RuntimeException - */ - public function setImports(array $imports) - { - if ($this->namespaces) { - throw new RuntimeException('You must either use addNamespace(), or setImports(), but not both.'); - } - - $this->imports = $imports; - } - - /** - * Sets current target context as bitmask. - * - * @return void - */ - public function setTarget(int $target) - { - $this->target = $target; - } - - /** - * Parses the given docblock string for annotations. - * - * @phpstan-return list<object> Array of annotations. If no annotations are found, an empty array is returned. - * - * @throws AnnotationException - * @throws ReflectionException - */ - public function parse(string $input, string $context = '') - { - $pos = $this->findInitialTokenPosition($input); - if ($pos === null) { - return []; - } - - $this->context = $context; - - $this->lexer->setInput(trim(substr($input, $pos), '* /')); - $this->lexer->moveNext(); - - return $this->Annotations(); - } - - /** - * Finds the first valid annotation - */ - private function findInitialTokenPosition(string $input): ?int - { - $pos = 0; - - // search for first valid annotation - while (($pos = strpos($input, '@', $pos)) !== false) { - $preceding = substr($input, $pos - 1, 1); - - // if the @ is preceded by a space, a tab or * it is valid - if ($pos === 0 || $preceding === ' ' || $preceding === '*' || $preceding === "\t") { - return $pos; - } - - $pos++; - } - - return null; - } - - /** - * Attempts to match the given token with the current lookahead token. - * If they match, updates the lookahead token; otherwise raises a syntax error. - * - * @param int $token Type of token. - * - * @return bool True if tokens match; false otherwise. - * - * @throws AnnotationException - */ - private function match(int $token): bool - { - if (! $this->lexer->isNextToken($token)) { - throw $this->syntaxError($this->lexer->getLiteral($token)); - } - - return $this->lexer->moveNext(); - } - - /** - * Attempts to match the current lookahead token with any of the given tokens. - * - * If any of them matches, this method updates the lookahead token; otherwise - * a syntax error is raised. - * - * @phpstan-param list<mixed[]> $tokens - * - * @throws AnnotationException - */ - private function matchAny(array $tokens): bool - { - if (! $this->lexer->isNextTokenAny($tokens)) { - throw $this->syntaxError(implode(' or ', array_map([$this->lexer, 'getLiteral'], $tokens))); - } - - return $this->lexer->moveNext(); - } - - /** - * Generates a new syntax error. - * - * @param string $expected Expected string. - * @param mixed[]|null $token Optional token. - */ - private function syntaxError(string $expected, ?array $token = null): AnnotationException - { - if ($token === null) { - $token = $this->lexer->lookahead; - } - - $message = sprintf('Expected %s, got ', $expected); - $message .= $this->lexer->lookahead === null - ? 'end of string' - : sprintf("'%s' at position %s", $token->value, $token->position); - - if (strlen($this->context)) { - $message .= ' in ' . $this->context; - } - - $message .= '.'; - - return AnnotationException::syntaxError($message); - } - - /** - * Attempts to check if a class exists or not. This never goes through the PHP autoloading mechanism - * but uses the {@link AnnotationRegistry} to load classes. - * - * @param class-string $fqcn - */ - private function classExists(string $fqcn): bool - { - if (isset($this->classExists[$fqcn])) { - return $this->classExists[$fqcn]; - } - - // first check if the class already exists, maybe loaded through another AnnotationReader - if (class_exists($fqcn, false)) { - return $this->classExists[$fqcn] = true; - } - - // final check, does this class exist? - return $this->classExists[$fqcn] = AnnotationRegistry::loadAnnotationClass($fqcn); - } - - /** - * Collects parsing metadata for a given annotation class - * - * @param class-string $name The annotation name - * - * @throws AnnotationException - * @throws ReflectionException - */ - private function collectAnnotationMetadata(string $name): void - { - if (self::$metadataParser === null) { - self::$metadataParser = new self(); - - self::$metadataParser->setIgnoreNotImportedAnnotations(true); - self::$metadataParser->setIgnoredAnnotationNames($this->ignoredAnnotationNames); - self::$metadataParser->setImports([ - 'enum' => Enum::class, - 'target' => Target::class, - 'attribute' => Attribute::class, - 'attributes' => Attributes::class, - 'namedargumentconstructor' => NamedArgumentConstructor::class, - ]); - - // Make sure that annotations from metadata are loaded - class_exists(Enum::class); - class_exists(Target::class); - class_exists(Attribute::class); - class_exists(Attributes::class); - class_exists(NamedArgumentConstructor::class); - } - - $class = new ReflectionClass($name); - $docComment = $class->getDocComment(); - - // Sets default values for annotation metadata - $constructor = $class->getConstructor(); - $metadata = [ - 'default_property' => null, - 'has_constructor' => $constructor !== null && $constructor->getNumberOfParameters() > 0, - 'constructor_args' => [], - 'properties' => [], - 'property_types' => [], - 'attribute_types' => [], - 'targets_literal' => null, - 'targets' => Target::TARGET_ALL, - 'is_annotation' => strpos($docComment, '@Annotation') !== false, - ]; - - $metadata['has_named_argument_constructor'] = false; - - // verify that the class is really meant to be an annotation - if ($metadata['is_annotation']) { - self::$metadataParser->setTarget(Target::TARGET_CLASS); - - foreach (self::$metadataParser->parse($docComment, 'class @' . $name) as $annotation) { - if ($annotation instanceof Target) { - $metadata['targets'] = $annotation->targets; - $metadata['targets_literal'] = $annotation->literal; - - continue; - } - - if ($annotation instanceof NamedArgumentConstructor) { - $metadata['has_named_argument_constructor'] = $metadata['has_constructor']; - if ($metadata['has_named_argument_constructor']) { - // choose the first argument as the default property - $metadata['default_property'] = $constructor->getParameters()[0]->getName(); - } - } - - if (! ($annotation instanceof Attributes)) { - continue; - } - - foreach ($annotation->value as $attribute) { - $this->collectAttributeTypeMetadata($metadata, $attribute); - } - } - - // if not has a constructor will inject values into public properties - if ($metadata['has_constructor'] === false) { - // collect all public properties - foreach ($class->getProperties(ReflectionProperty::IS_PUBLIC) as $property) { - $metadata['properties'][$property->name] = $property->name; - - $propertyComment = $property->getDocComment(); - if ($propertyComment === false) { - continue; - } - - $attribute = new Attribute(); - - $attribute->required = (strpos($propertyComment, '@Required') !== false); - $attribute->name = $property->name; - $attribute->type = (strpos($propertyComment, '@var') !== false && - preg_match('/@var\s+([^\s]+)/', $propertyComment, $matches)) - ? $matches[1] - : 'mixed'; - - $this->collectAttributeTypeMetadata($metadata, $attribute); - - // checks if the property has @Enum - if (strpos($propertyComment, '@Enum') === false) { - continue; - } - - $context = 'property ' . $class->name . '::$' . $property->name; - - self::$metadataParser->setTarget(Target::TARGET_PROPERTY); - - foreach (self::$metadataParser->parse($propertyComment, $context) as $annotation) { - if (! $annotation instanceof Enum) { - continue; - } - - $metadata['enum'][$property->name]['value'] = $annotation->value; - $metadata['enum'][$property->name]['literal'] = (! empty($annotation->literal)) - ? $annotation->literal - : $annotation->value; - } - } - - // choose the first property as default property - $metadata['default_property'] = reset($metadata['properties']); - } elseif ($metadata['has_named_argument_constructor']) { - foreach ($constructor->getParameters() as $parameter) { - if ($parameter->isVariadic()) { - break; - } - - $metadata['constructor_args'][$parameter->getName()] = [ - 'position' => $parameter->getPosition(), - 'default' => $parameter->isOptional() ? $parameter->getDefaultValue() : null, - ]; - } - } - } - - self::$annotationMetadata[$name] = $metadata; - } - - /** - * Collects parsing metadata for a given attribute. - * - * @param mixed[] $metadata - */ - private function collectAttributeTypeMetadata(array &$metadata, Attribute $attribute): void - { - // handle internal type declaration - $type = self::$typeMap[$attribute->type] ?? $attribute->type; - - // handle the case if the property type is mixed - if ($type === 'mixed') { - return; - } - - // Evaluate type - $pos = strpos($type, '<'); - if ($pos !== false) { - // Checks if the property has array<type> - $arrayType = substr($type, $pos + 1, -1); - $type = 'array'; - - if (isset(self::$typeMap[$arrayType])) { - $arrayType = self::$typeMap[$arrayType]; - } - - $metadata['attribute_types'][$attribute->name]['array_type'] = $arrayType; - } else { - // Checks if the property has type[] - $pos = strrpos($type, '['); - if ($pos !== false) { - $arrayType = substr($type, 0, $pos); - $type = 'array'; - - if (isset(self::$typeMap[$arrayType])) { - $arrayType = self::$typeMap[$arrayType]; - } - - $metadata['attribute_types'][$attribute->name]['array_type'] = $arrayType; - } - } - - $metadata['attribute_types'][$attribute->name]['type'] = $type; - $metadata['attribute_types'][$attribute->name]['value'] = $attribute->type; - $metadata['attribute_types'][$attribute->name]['required'] = $attribute->required; - } - - /** - * Annotations ::= Annotation {[ "*" ]* [Annotation]}* - * - * @phpstan-return list<object> - * - * @throws AnnotationException - * @throws ReflectionException - */ - private function Annotations(): array - { - $annotations = []; - - while ($this->lexer->lookahead !== null) { - if ($this->lexer->lookahead->type !== DocLexer::T_AT) { - $this->lexer->moveNext(); - continue; - } - - // make sure the @ is preceded by non-catchable pattern - if ( - $this->lexer->token !== null && - $this->lexer->lookahead->position === $this->lexer->token->position + strlen( - $this->lexer->token->value - ) - ) { - $this->lexer->moveNext(); - continue; - } - - // make sure the @ is followed by either a namespace separator, or - // an identifier token - $peek = $this->lexer->glimpse(); - if ( - ($peek === null) - || ($peek->type !== DocLexer::T_NAMESPACE_SEPARATOR && ! in_array( - $peek->type, - self::$classIdentifiers, - true - )) - || $peek->position !== $this->lexer->lookahead->position + 1 - ) { - $this->lexer->moveNext(); - continue; - } - - $this->isNestedAnnotation = false; - $annot = $this->Annotation(); - if ($annot === false) { - continue; - } - - $annotations[] = $annot; - } - - return $annotations; - } - - /** - * Annotation ::= "@" AnnotationName MethodCall - * AnnotationName ::= QualifiedName | SimpleName - * QualifiedName ::= NameSpacePart "\" {NameSpacePart "\"}* SimpleName - * NameSpacePart ::= identifier | null | false | true - * SimpleName ::= identifier | null | false | true - * - * @return object|false False if it is not a valid annotation. - * - * @throws AnnotationException - * @throws ReflectionException - */ - private function Annotation() - { - $this->match(DocLexer::T_AT); - - // check if we have an annotation - $name = $this->Identifier(); - - if ( - $this->lexer->isNextToken(DocLexer::T_MINUS) - && $this->lexer->nextTokenIsAdjacent() - ) { - // Annotations with dashes, such as "@foo-" or "@foo-bar", are to be discarded - return false; - } - - // only process names which are not fully qualified, yet - // fully qualified names must start with a \ - $originalName = $name; - - if ($name[0] !== '\\') { - $pos = strpos($name, '\\'); - $alias = ($pos === false) ? $name : substr($name, 0, $pos); - $found = false; - $loweredAlias = strtolower($alias); - - if ($this->namespaces) { - foreach ($this->namespaces as $namespace) { - if ($this->classExists($namespace . '\\' . $name)) { - $name = $namespace . '\\' . $name; - $found = true; - break; - } - } - } elseif (isset($this->imports[$loweredAlias])) { - $namespace = ltrim($this->imports[$loweredAlias], '\\'); - $name = ($pos !== false) - ? $namespace . substr($name, $pos) - : $namespace; - $found = $this->classExists($name); - } elseif ( - ! isset($this->ignoredAnnotationNames[$name]) - && isset($this->imports['__NAMESPACE__']) - && $this->classExists($this->imports['__NAMESPACE__'] . '\\' . $name) - ) { - $name = $this->imports['__NAMESPACE__'] . '\\' . $name; - $found = true; - } elseif (! isset($this->ignoredAnnotationNames[$name]) && $this->classExists($name)) { - $found = true; - } - - if (! $found) { - if ($this->isIgnoredAnnotation($name)) { - return false; - } - - throw AnnotationException::semanticalError(sprintf( - <<<'EXCEPTION' -The annotation "@%s" in %s was never imported. Did you maybe forget to add a "use" statement for this annotation? -EXCEPTION - , - $name, - $this->context - )); - } - } - - $name = ltrim($name, '\\'); - - if (! $this->classExists($name)) { - throw AnnotationException::semanticalError(sprintf( - 'The annotation "@%s" in %s does not exist, or could not be auto-loaded.', - $name, - $this->context - )); - } - - // at this point, $name contains the fully qualified class name of the - // annotation, and it is also guaranteed that this class exists, and - // that it is loaded - - // collects the metadata annotation only if there is not yet - if (! isset(self::$annotationMetadata[$name])) { - $this->collectAnnotationMetadata($name); - } - - // verify that the class is really meant to be an annotation and not just any ordinary class - if (self::$annotationMetadata[$name]['is_annotation'] === false) { - if ($this->isIgnoredAnnotation($originalName) || $this->isIgnoredAnnotation($name)) { - return false; - } - - throw AnnotationException::semanticalError(sprintf( - <<<'EXCEPTION' -The class "%s" is not annotated with @Annotation. -Are you sure this class can be used as annotation? -If so, then you need to add @Annotation to the _class_ doc comment of "%s". -If it is indeed no annotation, then you need to add @IgnoreAnnotation("%s") to the _class_ doc comment of %s. -EXCEPTION - , - $name, - $name, - $originalName, - $this->context - )); - } - - //if target is nested annotation - $target = $this->isNestedAnnotation ? Target::TARGET_ANNOTATION : $this->target; - - // Next will be nested - $this->isNestedAnnotation = true; - - //if annotation does not support current target - if ((self::$annotationMetadata[$name]['targets'] & $target) === 0 && $target) { - throw AnnotationException::semanticalError( - sprintf( - <<<'EXCEPTION' -Annotation @%s is not allowed to be declared on %s. You may only use this annotation on these code elements: %s. -EXCEPTION - , - $originalName, - $this->context, - self::$annotationMetadata[$name]['targets_literal'] - ) - ); - } - - $arguments = $this->MethodCall(); - $values = $this->resolvePositionalValues($arguments, $name); - - if (isset(self::$annotationMetadata[$name]['enum'])) { - // checks all declared attributes - foreach (self::$annotationMetadata[$name]['enum'] as $property => $enum) { - // checks if the attribute is a valid enumerator - if (isset($values[$property]) && ! in_array($values[$property], $enum['value'])) { - throw AnnotationException::enumeratorError( - $property, - $name, - $this->context, - $enum['literal'], - $values[$property] - ); - } - } - } - - // checks all declared attributes - foreach (self::$annotationMetadata[$name]['attribute_types'] as $property => $type) { - if ( - $property === self::$annotationMetadata[$name]['default_property'] - && ! isset($values[$property]) && isset($values['value']) - ) { - $property = 'value'; - } - - // handle a not given attribute or null value - if (! isset($values[$property])) { - if ($type['required']) { - throw AnnotationException::requiredError( - $property, - $originalName, - $this->context, - 'a(n) ' . $type['value'] - ); - } - - continue; - } - - if ($type['type'] === 'array') { - // handle the case of a single value - if (! is_array($values[$property])) { - $values[$property] = [$values[$property]]; - } - - // checks if the attribute has array type declaration, such as "array<string>" - if (isset($type['array_type'])) { - foreach ($values[$property] as $item) { - if (gettype($item) !== $type['array_type'] && ! $item instanceof $type['array_type']) { - throw AnnotationException::attributeTypeError( - $property, - $originalName, - $this->context, - 'either a(n) ' . $type['array_type'] . ', or an array of ' . $type['array_type'] . 's', - $item - ); - } - } - } - } elseif (gettype($values[$property]) !== $type['type'] && ! $values[$property] instanceof $type['type']) { - throw AnnotationException::attributeTypeError( - $property, - $originalName, - $this->context, - 'a(n) ' . $type['value'], - $values[$property] - ); - } - } - - if (self::$annotationMetadata[$name]['has_named_argument_constructor']) { - if (PHP_VERSION_ID >= 80000) { - foreach ($values as $property => $value) { - if (! isset(self::$annotationMetadata[$name]['constructor_args'][$property])) { - throw AnnotationException::creationError(sprintf( - <<<'EXCEPTION' -The annotation @%s declared on %s does not have a property named "%s" -that can be set through its named arguments constructor. -Available named arguments: %s -EXCEPTION - , - $originalName, - $this->context, - $property, - implode(', ', array_keys(self::$annotationMetadata[$name]['constructor_args'])) - )); - } - } - - return $this->instantiateAnnotiation($originalName, $this->context, $name, $values); - } - - $positionalValues = []; - foreach (self::$annotationMetadata[$name]['constructor_args'] as $property => $parameter) { - $positionalValues[$parameter['position']] = $parameter['default']; - } - - foreach ($values as $property => $value) { - if (! isset(self::$annotationMetadata[$name]['constructor_args'][$property])) { - throw AnnotationException::creationError(sprintf( - <<<'EXCEPTION' -The annotation @%s declared on %s does not have a property named "%s" -that can be set through its named arguments constructor. -Available named arguments: %s -EXCEPTION - , - $originalName, - $this->context, - $property, - implode(', ', array_keys(self::$annotationMetadata[$name]['constructor_args'])) - )); - } - - $positionalValues[self::$annotationMetadata[$name]['constructor_args'][$property]['position']] = $value; - } - - return $this->instantiateAnnotiation($originalName, $this->context, $name, $positionalValues); - } - - // check if the annotation expects values via the constructor, - // or directly injected into public properties - if (self::$annotationMetadata[$name]['has_constructor'] === true) { - return $this->instantiateAnnotiation($originalName, $this->context, $name, [$values]); - } - - $instance = $this->instantiateAnnotiation($originalName, $this->context, $name, []); - - foreach ($values as $property => $value) { - if (! isset(self::$annotationMetadata[$name]['properties'][$property])) { - if ($property !== 'value') { - throw AnnotationException::creationError(sprintf( - <<<'EXCEPTION' -The annotation @%s declared on %s does not have a property named "%s". -Available properties: %s -EXCEPTION - , - $originalName, - $this->context, - $property, - implode(', ', self::$annotationMetadata[$name]['properties']) - )); - } - - // handle the case if the property has no annotations - $property = self::$annotationMetadata[$name]['default_property']; - if (! $property) { - throw AnnotationException::creationError(sprintf( - 'The annotation @%s declared on %s does not accept any values, but got %s.', - $originalName, - $this->context, - json_encode($values) - )); - } - } - - $instance->{$property} = $value; - } - - return $instance; - } - - /** - * MethodCall ::= ["(" [Values] ")"] - * - * @return mixed[] - * - * @throws AnnotationException - * @throws ReflectionException - */ - private function MethodCall(): array - { - $values = []; - - if (! $this->lexer->isNextToken(DocLexer::T_OPEN_PARENTHESIS)) { - return $values; - } - - $this->match(DocLexer::T_OPEN_PARENTHESIS); - - if (! $this->lexer->isNextToken(DocLexer::T_CLOSE_PARENTHESIS)) { - $values = $this->Values(); - } - - $this->match(DocLexer::T_CLOSE_PARENTHESIS); - - return $values; - } - - /** - * Values ::= Array | Value {"," Value}* [","] - * - * @return mixed[] - * - * @throws AnnotationException - * @throws ReflectionException - */ - private function Values(): array - { - $values = [$this->Value()]; - - while ($this->lexer->isNextToken(DocLexer::T_COMMA)) { - $this->match(DocLexer::T_COMMA); - - if ($this->lexer->isNextToken(DocLexer::T_CLOSE_PARENTHESIS)) { - break; - } - - $token = $this->lexer->lookahead; - $value = $this->Value(); - - $values[] = $value; - } - - $namedArguments = []; - $positionalArguments = []; - foreach ($values as $k => $value) { - if (is_object($value) && $value instanceof stdClass) { - $namedArguments[$value->name] = $value->value; - } else { - $positionalArguments[$k] = $value; - } - } - - return ['named_arguments' => $namedArguments, 'positional_arguments' => $positionalArguments]; - } - - /** - * Constant ::= integer | string | float | boolean - * - * @return mixed - * - * @throws AnnotationException - */ - private function Constant() - { - $identifier = $this->Identifier(); - - if (! defined($identifier) && strpos($identifier, '::') !== false && $identifier[0] !== '\\') { - [$className, $const] = explode('::', $identifier); - - $pos = strpos($className, '\\'); - $alias = ($pos === false) ? $className : substr($className, 0, $pos); - $found = false; - $loweredAlias = strtolower($alias); - - switch (true) { - case ! empty($this->namespaces): - foreach ($this->namespaces as $ns) { - if (class_exists($ns . '\\' . $className) || interface_exists($ns . '\\' . $className)) { - $className = $ns . '\\' . $className; - $found = true; - break; - } - } - - break; - - case isset($this->imports[$loweredAlias]): - $found = true; - $className = ($pos !== false) - ? $this->imports[$loweredAlias] . substr($className, $pos) - : $this->imports[$loweredAlias]; - break; - - default: - if (isset($this->imports['__NAMESPACE__'])) { - $ns = $this->imports['__NAMESPACE__']; - - if (class_exists($ns . '\\' . $className) || interface_exists($ns . '\\' . $className)) { - $className = $ns . '\\' . $className; - $found = true; - } - } - - break; - } - - if ($found) { - $identifier = $className . '::' . $const; - } - } - - /** - * Checks if identifier ends with ::class and remove the leading backslash if it exists. - */ - if ( - $this->identifierEndsWithClassConstant($identifier) && - ! $this->identifierStartsWithBackslash($identifier) - ) { - return substr($identifier, 0, $this->getClassConstantPositionInIdentifier($identifier)); - } - - if ($this->identifierEndsWithClassConstant($identifier) && $this->identifierStartsWithBackslash($identifier)) { - return substr($identifier, 1, $this->getClassConstantPositionInIdentifier($identifier) - 1); - } - - if (! defined($identifier)) { - throw AnnotationException::semanticalErrorConstants($identifier, $this->context); - } - - return constant($identifier); - } - - private function identifierStartsWithBackslash(string $identifier): bool - { - return $identifier[0] === '\\'; - } - - private function identifierEndsWithClassConstant(string $identifier): bool - { - return $this->getClassConstantPositionInIdentifier($identifier) === strlen($identifier) - strlen('::class'); - } - - /** @return int|false */ - private function getClassConstantPositionInIdentifier(string $identifier) - { - return stripos($identifier, '::class'); - } - - /** - * Identifier ::= string - * - * @throws AnnotationException - */ - private function Identifier(): string - { - // check if we have an annotation - if (! $this->lexer->isNextTokenAny(self::$classIdentifiers)) { - throw $this->syntaxError('namespace separator or identifier'); - } - - $this->lexer->moveNext(); - - $className = $this->lexer->token->value; - - while ( - $this->lexer->lookahead !== null && - $this->lexer->lookahead->position === ($this->lexer->token->position + - strlen($this->lexer->token->value)) && - $this->lexer->isNextToken(DocLexer::T_NAMESPACE_SEPARATOR) - ) { - $this->match(DocLexer::T_NAMESPACE_SEPARATOR); - $this->matchAny(self::$classIdentifiers); - - $className .= '\\' . $this->lexer->token->value; - } - - return $className; - } - - /** - * Value ::= PlainValue | FieldAssignment - * - * @return mixed - * - * @throws AnnotationException - * @throws ReflectionException - */ - private function Value() - { - $peek = $this->lexer->glimpse(); - - if ($peek->type === DocLexer::T_EQUALS) { - return $this->FieldAssignment(); - } - - return $this->PlainValue(); - } - - /** - * PlainValue ::= integer | string | float | boolean | Array | Annotation - * - * @return mixed - * - * @throws AnnotationException - * @throws ReflectionException - */ - private function PlainValue() - { - if ($this->lexer->isNextToken(DocLexer::T_OPEN_CURLY_BRACES)) { - return $this->Arrayx(); - } - - if ($this->lexer->isNextToken(DocLexer::T_AT)) { - return $this->Annotation(); - } - - if ($this->lexer->isNextToken(DocLexer::T_IDENTIFIER)) { - return $this->Constant(); - } - - switch ($this->lexer->lookahead->type) { - case DocLexer::T_STRING: - $this->match(DocLexer::T_STRING); - - return $this->lexer->token->value; - - case DocLexer::T_INTEGER: - $this->match(DocLexer::T_INTEGER); - - return (int) $this->lexer->token->value; - - case DocLexer::T_FLOAT: - $this->match(DocLexer::T_FLOAT); - - return (float) $this->lexer->token->value; - - case DocLexer::T_TRUE: - $this->match(DocLexer::T_TRUE); - - return true; - - case DocLexer::T_FALSE: - $this->match(DocLexer::T_FALSE); - - return false; - - case DocLexer::T_NULL: - $this->match(DocLexer::T_NULL); - - return null; - - default: - throw $this->syntaxError('PlainValue'); - } - } - - /** - * FieldAssignment ::= FieldName "=" PlainValue - * FieldName ::= identifier - * - * @throws AnnotationException - * @throws ReflectionException - */ - private function FieldAssignment(): stdClass - { - $this->match(DocLexer::T_IDENTIFIER); - $fieldName = $this->lexer->token->value; - - $this->match(DocLexer::T_EQUALS); - - $item = new stdClass(); - $item->name = $fieldName; - $item->value = $this->PlainValue(); - - return $item; - } - - /** - * Array ::= "{" ArrayEntry {"," ArrayEntry}* [","] "}" - * - * @return mixed[] - * - * @throws AnnotationException - * @throws ReflectionException - */ - private function Arrayx(): array - { - $array = $values = []; - - $this->match(DocLexer::T_OPEN_CURLY_BRACES); - - // If the array is empty, stop parsing and return. - if ($this->lexer->isNextToken(DocLexer::T_CLOSE_CURLY_BRACES)) { - $this->match(DocLexer::T_CLOSE_CURLY_BRACES); - - return $array; - } - - $values[] = $this->ArrayEntry(); - - while ($this->lexer->isNextToken(DocLexer::T_COMMA)) { - $this->match(DocLexer::T_COMMA); - - // optional trailing comma - if ($this->lexer->isNextToken(DocLexer::T_CLOSE_CURLY_BRACES)) { - break; - } - - $values[] = $this->ArrayEntry(); - } - - $this->match(DocLexer::T_CLOSE_CURLY_BRACES); - - foreach ($values as $value) { - [$key, $val] = $value; - - if ($key !== null) { - $array[$key] = $val; - } else { - $array[] = $val; - } - } - - return $array; - } - - /** - * ArrayEntry ::= Value | KeyValuePair - * KeyValuePair ::= Key ("=" | ":") PlainValue | Constant - * Key ::= string | integer | Constant - * - * @phpstan-return array{mixed, mixed} - * - * @throws AnnotationException - * @throws ReflectionException - */ - private function ArrayEntry(): array - { - $peek = $this->lexer->glimpse(); - - if ( - $peek->type === DocLexer::T_EQUALS - || $peek->type === DocLexer::T_COLON - ) { - if ($this->lexer->isNextToken(DocLexer::T_IDENTIFIER)) { - $key = $this->Constant(); - } else { - $this->matchAny([DocLexer::T_INTEGER, DocLexer::T_STRING]); - $key = $this->lexer->token->value; - } - - $this->matchAny([DocLexer::T_EQUALS, DocLexer::T_COLON]); - - return [$key, $this->PlainValue()]; - } - - return [null, $this->Value()]; - } - - /** - * Checks whether the given $name matches any ignored annotation name or namespace - */ - private function isIgnoredAnnotation(string $name): bool - { - if ($this->ignoreNotImportedAnnotations || isset($this->ignoredAnnotationNames[$name])) { - return true; - } - - foreach (array_keys($this->ignoredAnnotationNamespaces) as $ignoredAnnotationNamespace) { - $ignoredAnnotationNamespace = rtrim($ignoredAnnotationNamespace, '\\') . '\\'; - - if (stripos(rtrim($name, '\\') . '\\', $ignoredAnnotationNamespace) === 0) { - return true; - } - } - - return false; - } - - /** - * Resolve positional arguments (without name) to named ones - * - * @param array<string,mixed> $arguments - * - * @return array<string,mixed> - */ - private function resolvePositionalValues(array $arguments, string $name): array - { - $positionalArguments = $arguments['positional_arguments'] ?? []; - $values = $arguments['named_arguments'] ?? []; - - if ( - self::$annotationMetadata[$name]['has_named_argument_constructor'] - && self::$annotationMetadata[$name]['default_property'] !== null - ) { - // We must ensure that we don't have positional arguments after named ones - $positions = array_keys($positionalArguments); - $lastPosition = null; - foreach ($positions as $position) { - if ( - ($lastPosition === null && $position !== 0) || - ($lastPosition !== null && $position !== $lastPosition + 1) - ) { - throw $this->syntaxError('Positional arguments after named arguments is not allowed'); - } - - $lastPosition = $position; - } - - foreach (self::$annotationMetadata[$name]['constructor_args'] as $property => $parameter) { - $position = $parameter['position']; - if (isset($values[$property]) || ! isset($positionalArguments[$position])) { - continue; - } - - $values[$property] = $positionalArguments[$position]; - } - } else { - if (count($positionalArguments) > 0 && ! isset($values['value'])) { - if (count($positionalArguments) === 1) { - $value = array_pop($positionalArguments); - } else { - $value = array_values($positionalArguments); - } - - $values['value'] = $value; - } - } - - return $values; - } - - /** - * Try to instantiate the annotation and catch and process any exceptions related to failure - * - * @param class-string $name - * @param array<string,mixed> $arguments - * - * @return object - * - * @throws AnnotationException - */ - private function instantiateAnnotiation(string $originalName, string $context, string $name, array $arguments) - { - try { - return new $name(...$arguments); - } catch (Throwable $exception) { - throw AnnotationException::creationError( - sprintf( - 'An error occurred while instantiating the annotation @%s declared on %s: "%s".', - $originalName, - $context, - $exception->getMessage() - ), - $exception - ); - } - } -} diff --git a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/ImplicitlyIgnoredAnnotationNames.php b/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/ImplicitlyIgnoredAnnotationNames.php deleted file mode 100644 index ab27f8a5c..000000000 --- a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/ImplicitlyIgnoredAnnotationNames.php +++ /dev/null @@ -1,178 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Doctrine\Common\Annotations; - -/** - * A list of annotations that are implicitly ignored during the parsing process. - * - * All names are case sensitive. - */ -final class ImplicitlyIgnoredAnnotationNames -{ - private const Reserved = [ - 'Annotation' => true, - 'Attribute' => true, - 'Attributes' => true, - /* Can we enable this? 'Enum' => true, */ - 'Required' => true, - 'Target' => true, - 'NamedArgumentConstructor' => true, - ]; - - private const WidelyUsedNonStandard = [ - 'fix' => true, - 'fixme' => true, - 'override' => true, - ]; - - private const PhpDocumentor1 = [ - 'abstract' => true, - 'access' => true, - 'code' => true, - 'deprec' => true, - 'endcode' => true, - 'exception' => true, - 'final' => true, - 'ingroup' => true, - 'inheritdoc' => true, - 'inheritDoc' => true, - 'magic' => true, - 'name' => true, - 'private' => true, - 'static' => true, - 'staticvar' => true, - 'staticVar' => true, - 'toc' => true, - 'tutorial' => true, - 'throw' => true, - ]; - - private const PhpDocumentor2 = [ - 'api' => true, - 'author' => true, - 'category' => true, - 'copyright' => true, - 'deprecated' => true, - 'example' => true, - 'filesource' => true, - 'global' => true, - 'ignore' => true, - /* Can we enable this? 'index' => true, */ - 'internal' => true, - 'license' => true, - 'link' => true, - 'method' => true, - 'package' => true, - 'param' => true, - 'property' => true, - 'property-read' => true, - 'property-write' => true, - 'return' => true, - 'see' => true, - 'since' => true, - 'source' => true, - 'subpackage' => true, - 'throws' => true, - 'todo' => true, - 'TODO' => true, - 'usedby' => true, - 'uses' => true, - 'var' => true, - 'version' => true, - ]; - - private const PHPUnit = [ - 'author' => true, - 'after' => true, - 'afterClass' => true, - 'backupGlobals' => true, - 'backupStaticAttributes' => true, - 'before' => true, - 'beforeClass' => true, - 'codeCoverageIgnore' => true, - 'codeCoverageIgnoreStart' => true, - 'codeCoverageIgnoreEnd' => true, - 'covers' => true, - 'coversDefaultClass' => true, - 'coversNothing' => true, - 'dataProvider' => true, - 'depends' => true, - 'doesNotPerformAssertions' => true, - 'expectedException' => true, - 'expectedExceptionCode' => true, - 'expectedExceptionMessage' => true, - 'expectedExceptionMessageRegExp' => true, - 'group' => true, - 'large' => true, - 'medium' => true, - 'preserveGlobalState' => true, - 'requires' => true, - 'runTestsInSeparateProcesses' => true, - 'runInSeparateProcess' => true, - 'small' => true, - 'test' => true, - 'testdox' => true, - 'testWith' => true, - 'ticket' => true, - 'uses' => true, - ]; - - private const PhpCheckStyle = ['SuppressWarnings' => true]; - - private const PhpStorm = ['noinspection' => true]; - - private const PEAR = ['package_version' => true]; - - private const PlainUML = [ - 'startuml' => true, - 'enduml' => true, - ]; - - private const Symfony = ['experimental' => true]; - - private const PhpCodeSniffer = [ - 'codingStandardsIgnoreStart' => true, - 'codingStandardsIgnoreEnd' => true, - ]; - - private const SlevomatCodingStandard = ['phpcsSuppress' => true]; - - private const Phan = ['suppress' => true]; - - private const Rector = ['noRector' => true]; - - private const StaticAnalysis = [ - // PHPStan, Psalm - 'extends' => true, - 'implements' => true, - 'readonly' => true, - 'template' => true, - 'use' => true, - - // Psalm - 'pure' => true, - 'immutable' => true, - ]; - - public const LIST = self::Reserved - + self::WidelyUsedNonStandard - + self::PhpDocumentor1 - + self::PhpDocumentor2 - + self::PHPUnit - + self::PhpCheckStyle - + self::PhpStorm - + self::PEAR - + self::PlainUML - + self::Symfony - + self::SlevomatCodingStandard - + self::PhpCodeSniffer - + self::Phan - + self::Rector - + self::StaticAnalysis; - - private function __construct() - { - } -} diff --git a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php b/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php deleted file mode 100644 index 77b5b9cb2..000000000 --- a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php +++ /dev/null @@ -1,99 +0,0 @@ -<?php - -namespace Doctrine\Common\Annotations; - -use ReflectionClass; -use ReflectionMethod; -use ReflectionProperty; - -use function call_user_func_array; -use function get_class; - -/** - * Allows the reader to be used in-place of Doctrine's reader. - */ -class IndexedReader implements Reader -{ - /** @var Reader */ - private $delegate; - - public function __construct(Reader $reader) - { - $this->delegate = $reader; - } - - /** - * {@inheritDoc} - */ - public function getClassAnnotations(ReflectionClass $class) - { - $annotations = []; - foreach ($this->delegate->getClassAnnotations($class) as $annot) { - $annotations[get_class($annot)] = $annot; - } - - return $annotations; - } - - /** - * {@inheritDoc} - */ - public function getClassAnnotation(ReflectionClass $class, $annotationName) - { - return $this->delegate->getClassAnnotation($class, $annotationName); - } - - /** - * {@inheritDoc} - */ - public function getMethodAnnotations(ReflectionMethod $method) - { - $annotations = []; - foreach ($this->delegate->getMethodAnnotations($method) as $annot) { - $annotations[get_class($annot)] = $annot; - } - - return $annotations; - } - - /** - * {@inheritDoc} - */ - public function getMethodAnnotation(ReflectionMethod $method, $annotationName) - { - return $this->delegate->getMethodAnnotation($method, $annotationName); - } - - /** - * {@inheritDoc} - */ - public function getPropertyAnnotations(ReflectionProperty $property) - { - $annotations = []; - foreach ($this->delegate->getPropertyAnnotations($property) as $annot) { - $annotations[get_class($annot)] = $annot; - } - - return $annotations; - } - - /** - * {@inheritDoc} - */ - public function getPropertyAnnotation(ReflectionProperty $property, $annotationName) - { - return $this->delegate->getPropertyAnnotation($property, $annotationName); - } - - /** - * Proxies all methods to the delegate. - * - * @param mixed[] $args - * - * @return mixed - */ - public function __call(string $method, array $args) - { - return call_user_func_array([$this->delegate, $method], $args); - } -} diff --git a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/PhpParser.php b/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/PhpParser.php deleted file mode 100644 index 312a2ab1f..000000000 --- a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/PhpParser.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php - -namespace Doctrine\Common\Annotations; - -use ReflectionClass; -use ReflectionFunction; -use SplFileObject; - -use function is_file; -use function method_exists; -use function preg_quote; -use function preg_replace; - -/** - * Parses a file for namespaces/use/class declarations. - */ -final class PhpParser -{ - /** - * Parse a class or function for use statements. - * - * @param ReflectionClass|ReflectionFunction $reflection - * - * @psalm-return array<string, string> a list with use statements in the form (Alias => FQN). - */ - public function parseUseStatements($reflection): array - { - if (method_exists($reflection, 'getUseStatements')) { - return $reflection->getUseStatements(); - } - - $filename = $reflection->getFileName(); - - if ($filename === false) { - return []; - } - - $content = $this->getFileContent($filename, $reflection->getStartLine()); - - if ($content === null) { - return []; - } - - $namespace = preg_quote($reflection->getNamespaceName()); - $content = preg_replace('/^.*?(\bnamespace\s+' . $namespace . '\s*[;{].*)$/s', '\\1', $content); - $tokenizer = new TokenParser('<?php ' . $content); - - return $tokenizer->parseUseStatements($reflection->getNamespaceName()); - } - - /** - * Gets the content of the file right up to the given line number. - * - * @param string $filename The name of the file to load. - * @param int $lineNumber The number of lines to read from file. - * - * @return string|null The content of the file or null if the file does not exist. - */ - private function getFileContent(string $filename, $lineNumber) - { - if (! is_file($filename)) { - return null; - } - - $content = ''; - $lineCnt = 0; - $file = new SplFileObject($filename); - while (! $file->eof()) { - if ($lineCnt++ === $lineNumber) { - break; - } - - $content .= $file->fgets(); - } - - return $content; - } -} diff --git a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/PsrCachedReader.php b/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/PsrCachedReader.php deleted file mode 100644 index a7099d579..000000000 --- a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/PsrCachedReader.php +++ /dev/null @@ -1,232 +0,0 @@ -<?php - -namespace Doctrine\Common\Annotations; - -use Psr\Cache\CacheItemPoolInterface; -use ReflectionClass; -use ReflectionMethod; -use ReflectionProperty; -use Reflector; - -use function array_map; -use function array_merge; -use function assert; -use function filemtime; -use function max; -use function rawurlencode; -use function time; - -/** - * A cache aware annotation reader. - */ -final class PsrCachedReader implements Reader -{ - /** @var Reader */ - private $delegate; - - /** @var CacheItemPoolInterface */ - private $cache; - - /** @var bool */ - private $debug; - - /** @var array<string, array<object>> */ - private $loadedAnnotations = []; - - /** @var int[] */ - private $loadedFilemtimes = []; - - public function __construct(Reader $reader, CacheItemPoolInterface $cache, bool $debug = false) - { - $this->delegate = $reader; - $this->cache = $cache; - $this->debug = (bool) $debug; - } - - /** - * {@inheritDoc} - */ - public function getClassAnnotations(ReflectionClass $class) - { - $cacheKey = $class->getName(); - - if (isset($this->loadedAnnotations[$cacheKey])) { - return $this->loadedAnnotations[$cacheKey]; - } - - $annots = $this->fetchFromCache($cacheKey, $class, 'getClassAnnotations', $class); - - return $this->loadedAnnotations[$cacheKey] = $annots; - } - - /** - * {@inheritDoc} - */ - public function getClassAnnotation(ReflectionClass $class, $annotationName) - { - foreach ($this->getClassAnnotations($class) as $annot) { - if ($annot instanceof $annotationName) { - return $annot; - } - } - - return null; - } - - /** - * {@inheritDoc} - */ - public function getPropertyAnnotations(ReflectionProperty $property) - { - $class = $property->getDeclaringClass(); - $cacheKey = $class->getName() . '$' . $property->getName(); - - if (isset($this->loadedAnnotations[$cacheKey])) { - return $this->loadedAnnotations[$cacheKey]; - } - - $annots = $this->fetchFromCache($cacheKey, $class, 'getPropertyAnnotations', $property); - - return $this->loadedAnnotations[$cacheKey] = $annots; - } - - /** - * {@inheritDoc} - */ - public function getPropertyAnnotation(ReflectionProperty $property, $annotationName) - { - foreach ($this->getPropertyAnnotations($property) as $annot) { - if ($annot instanceof $annotationName) { - return $annot; - } - } - - return null; - } - - /** - * {@inheritDoc} - */ - public function getMethodAnnotations(ReflectionMethod $method) - { - $class = $method->getDeclaringClass(); - $cacheKey = $class->getName() . '#' . $method->getName(); - - if (isset($this->loadedAnnotations[$cacheKey])) { - return $this->loadedAnnotations[$cacheKey]; - } - - $annots = $this->fetchFromCache($cacheKey, $class, 'getMethodAnnotations', $method); - - return $this->loadedAnnotations[$cacheKey] = $annots; - } - - /** - * {@inheritDoc} - */ - public function getMethodAnnotation(ReflectionMethod $method, $annotationName) - { - foreach ($this->getMethodAnnotations($method) as $annot) { - if ($annot instanceof $annotationName) { - return $annot; - } - } - - return null; - } - - public function clearLoadedAnnotations(): void - { - $this->loadedAnnotations = []; - $this->loadedFilemtimes = []; - } - - /** @return mixed[] */ - private function fetchFromCache( - string $cacheKey, - ReflectionClass $class, - string $method, - Reflector $reflector - ): array { - $cacheKey = rawurlencode($cacheKey); - - $item = $this->cache->getItem($cacheKey); - if (($this->debug && ! $this->refresh($cacheKey, $class)) || ! $item->isHit()) { - $this->cache->save($item->set($this->delegate->{$method}($reflector))); - } - - return $item->get(); - } - - /** - * Used in debug mode to check if the cache is fresh. - * - * @return bool Returns true if the cache was fresh, or false if the class - * being read was modified since writing to the cache. - */ - private function refresh(string $cacheKey, ReflectionClass $class): bool - { - $lastModification = $this->getLastModification($class); - if ($lastModification === 0) { - return true; - } - - $item = $this->cache->getItem('[C]' . $cacheKey); - if ($item->isHit() && $item->get() >= $lastModification) { - return true; - } - - $this->cache->save($item->set(time())); - - return false; - } - - /** - * Returns the time the class was last modified, testing traits and parents - */ - private function getLastModification(ReflectionClass $class): int - { - $filename = $class->getFileName(); - - if (isset($this->loadedFilemtimes[$filename])) { - return $this->loadedFilemtimes[$filename]; - } - - $parent = $class->getParentClass(); - - $lastModification = max(array_merge( - [$filename ? filemtime($filename) : 0], - array_map(function (ReflectionClass $reflectionTrait): int { - return $this->getTraitLastModificationTime($reflectionTrait); - }, $class->getTraits()), - array_map(function (ReflectionClass $class): int { - return $this->getLastModification($class); - }, $class->getInterfaces()), - $parent ? [$this->getLastModification($parent)] : [] - )); - - assert($lastModification !== false); - - return $this->loadedFilemtimes[$filename] = $lastModification; - } - - private function getTraitLastModificationTime(ReflectionClass $reflectionTrait): int - { - $fileName = $reflectionTrait->getFileName(); - - if (isset($this->loadedFilemtimes[$fileName])) { - return $this->loadedFilemtimes[$fileName]; - } - - $lastModificationTime = max(array_merge( - [$fileName ? filemtime($fileName) : 0], - array_map(function (ReflectionClass $reflectionTrait): int { - return $this->getTraitLastModificationTime($reflectionTrait); - }, $reflectionTrait->getTraits()) - )); - - assert($lastModificationTime !== false); - - return $this->loadedFilemtimes[$fileName] = $lastModificationTime; - } -} diff --git a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php b/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php deleted file mode 100644 index 0663ffda0..000000000 --- a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php - -namespace Doctrine\Common\Annotations; - -use ReflectionClass; -use ReflectionMethod; -use ReflectionProperty; - -/** - * Interface for annotation readers. - */ -interface Reader -{ - /** - * Gets the annotations applied to a class. - * - * @param ReflectionClass $class The ReflectionClass of the class from which - * the class annotations should be read. - * - * @return array<object> An array of Annotations. - */ - public function getClassAnnotations(ReflectionClass $class); - - /** - * Gets a class annotation. - * - * @param ReflectionClass $class The ReflectionClass of the class from which - * the class annotations should be read. - * @param class-string<T> $annotationName The name of the annotation. - * - * @return T|null The Annotation or NULL, if the requested annotation does not exist. - * - * @template T - */ - public function getClassAnnotation(ReflectionClass $class, $annotationName); - - /** - * Gets the annotations applied to a method. - * - * @param ReflectionMethod $method The ReflectionMethod of the method from which - * the annotations should be read. - * - * @return array<object> An array of Annotations. - */ - public function getMethodAnnotations(ReflectionMethod $method); - - /** - * Gets a method annotation. - * - * @param ReflectionMethod $method The ReflectionMethod to read the annotations from. - * @param class-string<T> $annotationName The name of the annotation. - * - * @return T|null The Annotation or NULL, if the requested annotation does not exist. - * - * @template T - */ - public function getMethodAnnotation(ReflectionMethod $method, $annotationName); - - /** - * Gets the annotations applied to a property. - * - * @param ReflectionProperty $property The ReflectionProperty of the property - * from which the annotations should be read. - * - * @return array<object> An array of Annotations. - */ - public function getPropertyAnnotations(ReflectionProperty $property); - - /** - * Gets a property annotation. - * - * @param ReflectionProperty $property The ReflectionProperty to read the annotations from. - * @param class-string<T> $annotationName The name of the annotation. - * - * @return T|null The Annotation or NULL, if the requested annotation does not exist. - * - * @template T - */ - public function getPropertyAnnotation(ReflectionProperty $property, $annotationName); -} diff --git a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php b/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php deleted file mode 100644 index 0534fd17c..000000000 --- a/lib/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php +++ /dev/null @@ -1,205 +0,0 @@ -<?php - -namespace Doctrine\Common\Annotations; - -use function array_merge; -use function count; -use function explode; -use function strtolower; -use function token_get_all; - -use const PHP_VERSION_ID; -use const T_AS; -use const T_COMMENT; -use const T_DOC_COMMENT; -use const T_NAME_FULLY_QUALIFIED; -use const T_NAME_QUALIFIED; -use const T_NAMESPACE; -use const T_NS_SEPARATOR; -use const T_STRING; -use const T_USE; -use const T_WHITESPACE; - -/** - * Parses a file for namespaces/use/class declarations. - */ -class TokenParser -{ - /** - * The token list. - * - * @phpstan-var list<mixed[]> - */ - private $tokens; - - /** - * The number of tokens. - * - * @var int - */ - private $numTokens; - - /** - * The current array pointer. - * - * @var int - */ - private $pointer = 0; - - public function __construct(string $contents) - { - $this->tokens = token_get_all($contents); - - // The PHP parser sets internal compiler globals for certain things. Annoyingly, the last docblock comment it - // saw gets stored in doc_comment. When it comes to compile the next thing to be include()d this stored - // doc_comment becomes owned by the first thing the compiler sees in the file that it considers might have a - // docblock. If the first thing in the file is a class without a doc block this would cause calls to - // getDocBlock() on said class to return our long lost doc_comment. Argh. - // To workaround, cause the parser to parse an empty docblock. Sure getDocBlock() will return this, but at least - // it's harmless to us. - token_get_all("<?php\n/**\n *\n */"); - - $this->numTokens = count($this->tokens); - } - - /** - * Gets the next non whitespace and non comment token. - * - * @param bool $docCommentIsComment If TRUE then a doc comment is considered a comment and skipped. - * If FALSE then only whitespace and normal comments are skipped. - * - * @return mixed[]|string|null The token if exists, null otherwise. - */ - public function next(bool $docCommentIsComment = true) - { - for ($i = $this->pointer; $i < $this->numTokens; $i++) { - $this->pointer++; - if ( - $this->tokens[$i][0] === T_WHITESPACE || - $this->tokens[$i][0] === T_COMMENT || - ($docCommentIsComment && $this->tokens[$i][0] === T_DOC_COMMENT) - ) { - continue; - } - - return $this->tokens[$i]; - } - - return null; - } - - /** - * Parses a single use statement. - * - * @return array<string, string> A list with all found class names for a use statement. - */ - public function parseUseStatement() - { - $groupRoot = ''; - $class = ''; - $alias = ''; - $statements = []; - $explicitAlias = false; - while (($token = $this->next())) { - if (! $explicitAlias && $token[0] === T_STRING) { - $class .= $token[1]; - $alias = $token[1]; - } elseif ($explicitAlias && $token[0] === T_STRING) { - $alias = $token[1]; - } elseif ( - PHP_VERSION_ID >= 80000 && - ($token[0] === T_NAME_QUALIFIED || $token[0] === T_NAME_FULLY_QUALIFIED) - ) { - $class .= $token[1]; - - $classSplit = explode('\\', $token[1]); - $alias = $classSplit[count($classSplit) - 1]; - } elseif ($token[0] === T_NS_SEPARATOR) { - $class .= '\\'; - $alias = ''; - } elseif ($token[0] === T_AS) { - $explicitAlias = true; - $alias = ''; - } elseif ($token === ',') { - $statements[strtolower($alias)] = $groupRoot . $class; - $class = ''; - $alias = ''; - $explicitAlias = false; - } elseif ($token === ';') { - $statements[strtolower($alias)] = $groupRoot . $class; - break; - } elseif ($token === '{') { - $groupRoot = $class; - $class = ''; - } elseif ($token === '}') { - continue; - } else { - break; - } - } - - return $statements; - } - - /** - * Gets all use statements. - * - * @param string $namespaceName The namespace name of the reflected class. - * - * @return array<string, string> A list with all found use statements. - */ - public function parseUseStatements(string $namespaceName) - { - $statements = []; - while (($token = $this->next())) { - if ($token[0] === T_USE) { - $statements = array_merge($statements, $this->parseUseStatement()); - continue; - } - - if ($token[0] !== T_NAMESPACE || $this->parseNamespace() !== $namespaceName) { - continue; - } - - // Get fresh array for new namespace. This is to prevent the parser to collect the use statements - // for a previous namespace with the same name. This is the case if a namespace is defined twice - // or if a namespace with the same name is commented out. - $statements = []; - } - - return $statements; - } - - /** - * Gets the namespace. - * - * @return string The found namespace. - */ - public function parseNamespace() - { - $name = ''; - while ( - ($token = $this->next()) && ($token[0] === T_STRING || $token[0] === T_NS_SEPARATOR || ( - PHP_VERSION_ID >= 80000 && - ($token[0] === T_NAME_QUALIFIED || $token[0] === T_NAME_FULLY_QUALIFIED) - )) - ) { - $name .= $token[1]; - } - - return $name; - } - - /** - * Gets the class name. - * - * @return string The found class name. - */ - public function parseClass() - { - // Namespaces and class names are tokenized the same: T_STRINGs - // separated by T_NS_SEPARATOR so we can use one function to provide - // both. - return $this->parseNamespace(); - } -} diff --git a/lib/doctrine/annotations/psalm.xml b/lib/doctrine/annotations/psalm.xml deleted file mode 100644 index e6af38923..000000000 --- a/lib/doctrine/annotations/psalm.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0"?> -<psalm - errorLevel="7" - resolveFromConfigFile="true" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns="https://getpsalm.org/schema/config" - xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd" -> - <projectFiles> - <directory name="lib/Doctrine/Common/Annotations" /> - <ignoreFiles> - <directory name="vendor" /> - </ignoreFiles> - </projectFiles> -</psalm> diff --git a/lib/doctrine/cache/LICENSE b/lib/doctrine/cache/LICENSE deleted file mode 100644 index 8c38cc1bc..000000000 --- a/lib/doctrine/cache/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2006-2015 Doctrine Project - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/lib/doctrine/cache/README.md b/lib/doctrine/cache/README.md deleted file mode 100644 index a13196d15..000000000 --- a/lib/doctrine/cache/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Doctrine Cache - -[![Build Status](https://github.com/doctrine/cache/workflows/Continuous%20Integration/badge.svg)](https://github.com/doctrine/cache/actions) -[![Code Coverage](https://codecov.io/gh/doctrine/cache/branch/1.10.x/graph/badge.svg)](https://codecov.io/gh/doctrine/cache/branch/1.10.x) - -[![Latest Stable Version](https://img.shields.io/packagist/v/doctrine/cache.svg?style=flat-square)](https://packagist.org/packages/doctrine/cache) -[![Total Downloads](https://img.shields.io/packagist/dt/doctrine/cache.svg?style=flat-square)](https://packagist.org/packages/doctrine/cache) - -Cache component extracted from the Doctrine Common project. [Documentation](https://www.doctrine-project.org/projects/doctrine-cache/en/current/index.html) - -This library is deprecated and will no longer receive bug fixes from the -Doctrine Project. Please use a different cache library, preferably PSR-6 or -PSR-16 instead. diff --git a/lib/doctrine/cache/UPGRADE-1.11.md b/lib/doctrine/cache/UPGRADE-1.11.md deleted file mode 100644 index 6c5ddb559..000000000 --- a/lib/doctrine/cache/UPGRADE-1.11.md +++ /dev/null @@ -1,27 +0,0 @@ -# Upgrade to 1.11 - -doctrine/cache will no longer be maintained and all cache implementations have -been marked as deprecated. These implementations will be removed in 2.0, which -will only contain interfaces to provide a lightweight package for backward -compatibility. - -There are two new classes to use in the `Doctrine\Common\Cache\Psr6` namespace: -* The `CacheAdapter` class allows using any Doctrine Cache as PSR-6 cache. This - is useful to provide a forward compatibility layer in libraries that accept - Doctrine cache implementations and switch to PSR-6. -* The `DoctrineProvider` class allows using any PSR-6 cache as Doctrine cache. - This implementation is designed for libraries that leak the cache and want to - switch to allowing PSR-6 implementations. This class is design to be used - during the transition phase of sunsetting doctrine/cache support. - -A full example to setup a filesystem based PSR-6 cache with symfony/cache -using the `DoctrineProvider` to convert back to Doctrine's `Cache` interface: - -```php -use Doctrine\Common\Cache\Psr6\DoctrineProvider; -use Symfony\Component\Cache\Adapter\FilesystemAdapter; - -$cachePool = new FilesystemAdapter(); -$cache = DoctrineProvider::wrap($cachePool); -// $cache instanceof \Doctrine\Common\Cache\Cache -``` diff --git a/lib/doctrine/cache/UPGRADE-1.4.md b/lib/doctrine/cache/UPGRADE-1.4.md deleted file mode 100644 index e1f8a503e..000000000 --- a/lib/doctrine/cache/UPGRADE-1.4.md +++ /dev/null @@ -1,16 +0,0 @@ -# Upgrade to 1.4 - -## Minor BC Break: `Doctrine\Common\Cache\FileCache#$extension` is now `private`. - -If you need to override the value of `Doctrine\Common\Cache\FileCache#$extension`, then use the -second parameter of `Doctrine\Common\Cache\FileCache#__construct()` instead of overriding -the property in your own implementation. - -## Minor BC Break: file based caches paths changed - -`Doctrine\Common\Cache\FileCache`, `Doctrine\Common\Cache\PhpFileCache` and -`Doctrine\Common\Cache\FilesystemCache` are using a different cache paths structure. - -If you rely on warmed up caches for deployments, consider that caches generated -with `doctrine/cache` `<1.4` are not compatible with the new directory structure, -and will be ignored. diff --git a/lib/doctrine/cache/composer.json b/lib/doctrine/cache/composer.json deleted file mode 100644 index 3c8ca971e..000000000 --- a/lib/doctrine/cache/composer.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "name": "doctrine/cache", - "type": "library", - "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", - "keywords": [ - "php", - "cache", - "caching", - "abstraction", - "redis", - "memcached", - "couchdb", - "xcache", - "apcu" - ], - "homepage": "https://www.doctrine-project.org/projects/cache.html", - "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"} - ], - "require": { - "php": "~7.1 || ^8.0" - }, - "require-dev": { - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "doctrine/coding-standard": "^9", - "psr/cache": "^1.0 || ^2.0 || ^3.0", - "cache/integration-tests": "dev-master", - "symfony/cache": "^4.4 || ^5.4 || ^6", - "symfony/var-exporter": "^4.4 || ^5.4 || ^6" - }, - "conflict": { - "doctrine/common": ">2.2,<2.4" - }, - "autoload": { - "psr-4": { "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" } - }, - "autoload-dev": { - "psr-4": { "Doctrine\\Tests\\": "tests/Doctrine/Tests" } - }, - "config": { - "allow-plugins": { - "dealerdirect/phpcodesniffer-composer-installer": true - } - } -} diff --git a/lib/doctrine/cache/lib/Doctrine/Common/Cache/Cache.php b/lib/doctrine/cache/lib/Doctrine/Common/Cache/Cache.php deleted file mode 100644 index 4cfab6c0f..000000000 --- a/lib/doctrine/cache/lib/Doctrine/Common/Cache/Cache.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php - -namespace Doctrine\Common\Cache; - -/** - * Interface for cache drivers. - * - * @link www.doctrine-project.org - */ -interface Cache -{ - public const STATS_HITS = 'hits'; - public const STATS_MISSES = 'misses'; - public const STATS_UPTIME = 'uptime'; - public const STATS_MEMORY_USAGE = 'memory_usage'; - public const STATS_MEMORY_AVAILABLE = 'memory_available'; - /** - * Only for backward compatibility (may be removed in next major release) - * - * @deprecated - */ - public const STATS_MEMORY_AVAILIABLE = 'memory_available'; - - /** - * Fetches an entry from the cache. - * - * @param string $id The id of the cache entry to fetch. - * - * @return mixed The cached data or FALSE, if no cache entry exists for the given id. - */ - public function fetch($id); - - /** - * Tests if an entry exists in the cache. - * - * @param string $id The cache id of the entry to check for. - * - * @return bool TRUE if a cache entry exists for the given cache id, FALSE otherwise. - */ - public function contains($id); - - /** - * Puts data into the cache. - * - * If a cache entry with the given id already exists, its data will be replaced. - * - * @param string $id The cache id. - * @param mixed $data The cache entry/data. - * @param int $lifeTime The lifetime in number of seconds for this cache entry. - * If zero (the default), the entry never expires (although it may be deleted from the cache - * to make place for other entries). - * - * @return bool TRUE if the entry was successfully stored in the cache, FALSE otherwise. - */ - public function save($id, $data, $lifeTime = 0); - - /** - * Deletes a cache entry. - * - * @param string $id The cache id. - * - * @return bool TRUE if the cache entry was successfully deleted, FALSE otherwise. - * Deleting a non-existing entry is considered successful. - */ - public function delete($id); - - /** - * Retrieves cached information from the data store. - * - * The server's statistics array has the following values: - * - * - <b>hits</b> - * Number of keys that have been requested and found present. - * - * - <b>misses</b> - * Number of items that have been requested and not found. - * - * - <b>uptime</b> - * Time that the server is running. - * - * - <b>memory_usage</b> - * Memory used by this server to store items. - * - * - <b>memory_available</b> - * Memory allowed to use for storage. - * - * @return mixed[]|null An associative array with server's statistics if available, NULL otherwise. - */ - public function getStats(); -} diff --git a/lib/doctrine/cache/lib/Doctrine/Common/Cache/CacheProvider.php b/lib/doctrine/cache/lib/Doctrine/Common/Cache/CacheProvider.php deleted file mode 100644 index 180482a7b..000000000 --- a/lib/doctrine/cache/lib/Doctrine/Common/Cache/CacheProvider.php +++ /dev/null @@ -1,325 +0,0 @@ -<?php - -namespace Doctrine\Common\Cache; - -use function array_combine; -use function array_key_exists; -use function array_map; -use function sprintf; - -/** - * Base class for cache provider implementations. - */ -abstract class CacheProvider implements Cache, FlushableCache, ClearableCache, MultiOperationCache -{ - public const DOCTRINE_NAMESPACE_CACHEKEY = 'DoctrineNamespaceCacheKey[%s]'; - - /** - * The namespace to prefix all cache ids with. - * - * @var string - */ - private $namespace = ''; - - /** - * The namespace version. - * - * @var int|null - */ - private $namespaceVersion; - - /** - * Sets the namespace to prefix all cache ids with. - * - * @param string $namespace - * - * @return void - */ - public function setNamespace($namespace) - { - $this->namespace = (string) $namespace; - $this->namespaceVersion = null; - } - - /** - * Retrieves the namespace that prefixes all cache ids. - * - * @return string - */ - public function getNamespace() - { - return $this->namespace; - } - - /** - * {@inheritdoc} - */ - public function fetch($id) - { - return $this->doFetch($this->getNamespacedId($id)); - } - - /** - * {@inheritdoc} - */ - public function fetchMultiple(array $keys) - { - if (empty($keys)) { - return []; - } - - // note: the array_combine() is in place to keep an association between our $keys and the $namespacedKeys - $namespacedKeys = array_combine($keys, array_map([$this, 'getNamespacedId'], $keys)); - $items = $this->doFetchMultiple($namespacedKeys); - $foundItems = []; - - // no internal array function supports this sort of mapping: needs to be iterative - // this filters and combines keys in one pass - foreach ($namespacedKeys as $requestedKey => $namespacedKey) { - if (! isset($items[$namespacedKey]) && ! array_key_exists($namespacedKey, $items)) { - continue; - } - - $foundItems[$requestedKey] = $items[$namespacedKey]; - } - - return $foundItems; - } - - /** - * {@inheritdoc} - */ - public function saveMultiple(array $keysAndValues, $lifetime = 0) - { - $namespacedKeysAndValues = []; - foreach ($keysAndValues as $key => $value) { - $namespacedKeysAndValues[$this->getNamespacedId($key)] = $value; - } - - return $this->doSaveMultiple($namespacedKeysAndValues, $lifetime); - } - - /** - * {@inheritdoc} - */ - public function contains($id) - { - return $this->doContains($this->getNamespacedId($id)); - } - - /** - * {@inheritdoc} - */ - public function save($id, $data, $lifeTime = 0) - { - return $this->doSave($this->getNamespacedId($id), $data, $lifeTime); - } - - /** - * {@inheritdoc} - */ - public function deleteMultiple(array $keys) - { - return $this->doDeleteMultiple(array_map([$this, 'getNamespacedId'], $keys)); - } - - /** - * {@inheritdoc} - */ - public function delete($id) - { - return $this->doDelete($this->getNamespacedId($id)); - } - - /** - * {@inheritdoc} - */ - public function getStats() - { - return $this->doGetStats(); - } - - /** - * {@inheritDoc} - */ - public function flushAll() - { - return $this->doFlush(); - } - - /** - * {@inheritDoc} - */ - public function deleteAll() - { - $namespaceCacheKey = $this->getNamespaceCacheKey(); - $namespaceVersion = $this->getNamespaceVersion() + 1; - - if ($this->doSave($namespaceCacheKey, $namespaceVersion)) { - $this->namespaceVersion = $namespaceVersion; - - return true; - } - - return false; - } - - /** - * Prefixes the passed id with the configured namespace value. - * - * @param string $id The id to namespace. - * - * @return string The namespaced id. - */ - private function getNamespacedId(string $id): string - { - $namespaceVersion = $this->getNamespaceVersion(); - - return sprintf('%s[%s][%s]', $this->namespace, $id, $namespaceVersion); - } - - /** - * Returns the namespace cache key. - */ - private function getNamespaceCacheKey(): string - { - return sprintf(self::DOCTRINE_NAMESPACE_CACHEKEY, $this->namespace); - } - - /** - * Returns the namespace version. - */ - private function getNamespaceVersion(): int - { - if ($this->namespaceVersion !== null) { - return $this->namespaceVersion; - } - - $namespaceCacheKey = $this->getNamespaceCacheKey(); - $this->namespaceVersion = (int) $this->doFetch($namespaceCacheKey) ?: 1; - - return $this->namespaceVersion; - } - - /** - * Default implementation of doFetchMultiple. Each driver that supports multi-get should owerwrite it. - * - * @param string[] $keys Array of keys to retrieve from cache - * - * @return mixed[] Array of values retrieved for the given keys. - */ - protected function doFetchMultiple(array $keys) - { - $returnValues = []; - - foreach ($keys as $key) { - $item = $this->doFetch($key); - if ($item === false && ! $this->doContains($key)) { - continue; - } - - $returnValues[$key] = $item; - } - - return $returnValues; - } - - /** - * Fetches an entry from the cache. - * - * @param string $id The id of the cache entry to fetch. - * - * @return mixed|false The cached data or FALSE, if no cache entry exists for the given id. - */ - abstract protected function doFetch($id); - - /** - * Tests if an entry exists in the cache. - * - * @param string $id The cache id of the entry to check for. - * - * @return bool TRUE if a cache entry exists for the given cache id, FALSE otherwise. - */ - abstract protected function doContains($id); - - /** - * Default implementation of doSaveMultiple. Each driver that supports multi-put should override it. - * - * @param mixed[] $keysAndValues Array of keys and values to save in cache - * @param int $lifetime The lifetime. If != 0, sets a specific lifetime for these - * cache entries (0 => infinite lifeTime). - * - * @return bool TRUE if the operation was successful, FALSE if it wasn't. - */ - protected function doSaveMultiple(array $keysAndValues, $lifetime = 0) - { - $success = true; - - foreach ($keysAndValues as $key => $value) { - if ($this->doSave($key, $value, $lifetime)) { - continue; - } - - $success = false; - } - - return $success; - } - - /** - * Puts data into the cache. - * - * @param string $id The cache id. - * @param string $data The cache entry/data. - * @param int $lifeTime The lifetime. If != 0, sets a specific lifetime for this - * cache entry (0 => infinite lifeTime). - * - * @return bool TRUE if the entry was successfully stored in the cache, FALSE otherwise. - */ - abstract protected function doSave($id, $data, $lifeTime = 0); - - /** - * Default implementation of doDeleteMultiple. Each driver that supports multi-delete should override it. - * - * @param string[] $keys Array of keys to delete from cache - * - * @return bool TRUE if the operation was successful, FALSE if it wasn't - */ - protected function doDeleteMultiple(array $keys) - { - $success = true; - - foreach ($keys as $key) { - if ($this->doDelete($key)) { - continue; - } - - $success = false; - } - - return $success; - } - - /** - * Deletes a cache entry. - * - * @param string $id The cache id. - * - * @return bool TRUE if the cache entry was successfully deleted, FALSE otherwise. - */ - abstract protected function doDelete($id); - - /** - * Flushes all cache entries. - * - * @return bool TRUE if the cache entries were successfully flushed, FALSE otherwise. - */ - abstract protected function doFlush(); - - /** - * Retrieves cached information from the data store. - * - * @return mixed[]|null An associative array with server's statistics if available, NULL otherwise. - */ - abstract protected function doGetStats(); -} diff --git a/lib/doctrine/cache/lib/Doctrine/Common/Cache/ClearableCache.php b/lib/doctrine/cache/lib/Doctrine/Common/Cache/ClearableCache.php deleted file mode 100644 index b94618e46..000000000 --- a/lib/doctrine/cache/lib/Doctrine/Common/Cache/ClearableCache.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -namespace Doctrine\Common\Cache; - -/** - * Interface for cache that can be flushed. - * - * Intended to be used for partial clearing of a cache namespace. For a more - * global "flushing", see {@see FlushableCache}. - * - * @link www.doctrine-project.org - */ -interface ClearableCache -{ - /** - * Deletes all cache entries in the current cache namespace. - * - * @return bool TRUE if the cache entries were successfully deleted, FALSE otherwise. - */ - public function deleteAll(); -} diff --git a/lib/doctrine/cache/lib/Doctrine/Common/Cache/FlushableCache.php b/lib/doctrine/cache/lib/Doctrine/Common/Cache/FlushableCache.php deleted file mode 100644 index ee7ce984e..000000000 --- a/lib/doctrine/cache/lib/Doctrine/Common/Cache/FlushableCache.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php - -namespace Doctrine\Common\Cache; - -/** - * Interface for cache that can be flushed. - * - * @link www.doctrine-project.org - */ -interface FlushableCache -{ - /** - * Flushes all cache entries, globally. - * - * @return bool TRUE if the cache entries were successfully flushed, FALSE otherwise. - */ - public function flushAll(); -} diff --git a/lib/doctrine/cache/lib/Doctrine/Common/Cache/MultiDeleteCache.php b/lib/doctrine/cache/lib/Doctrine/Common/Cache/MultiDeleteCache.php deleted file mode 100644 index d099d47b8..000000000 --- a/lib/doctrine/cache/lib/Doctrine/Common/Cache/MultiDeleteCache.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -namespace Doctrine\Common\Cache; - -/** - * Interface for cache drivers that allows to put many items at once. - * - * @deprecated - * - * @link www.doctrine-project.org - */ -interface MultiDeleteCache -{ - /** - * Deletes several cache entries. - * - * @param string[] $keys Array of keys to delete from cache - * - * @return bool TRUE if the operation was successful, FALSE if it wasn't. - */ - public function deleteMultiple(array $keys); -} diff --git a/lib/doctrine/cache/lib/Doctrine/Common/Cache/MultiGetCache.php b/lib/doctrine/cache/lib/Doctrine/Common/Cache/MultiGetCache.php deleted file mode 100644 index e75d6b1c9..000000000 --- a/lib/doctrine/cache/lib/Doctrine/Common/Cache/MultiGetCache.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -namespace Doctrine\Common\Cache; - -/** - * Interface for cache drivers that allows to get many items at once. - * - * @deprecated - * - * @link www.doctrine-project.org - */ -interface MultiGetCache -{ - /** - * Returns an associative array of values for keys is found in cache. - * - * @param string[] $keys Array of keys to retrieve from cache - * - * @return mixed[] Array of retrieved values, indexed by the specified keys. - * Values that couldn't be retrieved are not contained in this array. - */ - public function fetchMultiple(array $keys); -} diff --git a/lib/doctrine/cache/lib/Doctrine/Common/Cache/MultiOperationCache.php b/lib/doctrine/cache/lib/Doctrine/Common/Cache/MultiOperationCache.php deleted file mode 100644 index f182d984d..000000000 --- a/lib/doctrine/cache/lib/Doctrine/Common/Cache/MultiOperationCache.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -namespace Doctrine\Common\Cache; - -/** - * Interface for cache drivers that supports multiple items manipulation. - * - * @link www.doctrine-project.org - */ -interface MultiOperationCache extends MultiGetCache, MultiDeleteCache, MultiPutCache -{ -} diff --git a/lib/doctrine/cache/lib/Doctrine/Common/Cache/MultiPutCache.php b/lib/doctrine/cache/lib/Doctrine/Common/Cache/MultiPutCache.php deleted file mode 100644 index b7c06d396..000000000 --- a/lib/doctrine/cache/lib/Doctrine/Common/Cache/MultiPutCache.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -namespace Doctrine\Common\Cache; - -/** - * Interface for cache drivers that allows to put many items at once. - * - * @deprecated - * - * @link www.doctrine-project.org - */ -interface MultiPutCache -{ - /** - * Returns a boolean value indicating if the operation succeeded. - * - * @param mixed[] $keysAndValues Array of keys and values to save in cache - * @param int $lifetime The lifetime. If != 0, sets a specific lifetime for these - * cache entries (0 => infinite lifeTime). - * - * @return bool TRUE if the operation was successful, FALSE if it wasn't. - */ - public function saveMultiple(array $keysAndValues, $lifetime = 0); -} diff --git a/lib/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/CacheAdapter.php b/lib/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/CacheAdapter.php deleted file mode 100644 index d3693b7c6..000000000 --- a/lib/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/CacheAdapter.php +++ /dev/null @@ -1,340 +0,0 @@ -<?php - -namespace Doctrine\Common\Cache\Psr6; - -use Doctrine\Common\Cache\Cache; -use Doctrine\Common\Cache\ClearableCache; -use Doctrine\Common\Cache\MultiDeleteCache; -use Doctrine\Common\Cache\MultiGetCache; -use Doctrine\Common\Cache\MultiPutCache; -use Psr\Cache\CacheItemInterface; -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Cache\DoctrineProvider as SymfonyDoctrineProvider; - -use function array_key_exists; -use function assert; -use function count; -use function current; -use function get_class; -use function gettype; -use function is_object; -use function is_string; -use function microtime; -use function sprintf; -use function strpbrk; - -use const PHP_VERSION_ID; - -final class CacheAdapter implements CacheItemPoolInterface -{ - private const RESERVED_CHARACTERS = '{}()/\@:'; - - /** @var Cache */ - private $cache; - - /** @var array<CacheItem|TypedCacheItem> */ - private $deferredItems = []; - - public static function wrap(Cache $cache): CacheItemPoolInterface - { - if ($cache instanceof DoctrineProvider && ! $cache->getNamespace()) { - return $cache->getPool(); - } - - if ($cache instanceof SymfonyDoctrineProvider && ! $cache->getNamespace()) { - $getPool = function () { - // phpcs:ignore Squiz.Scope.StaticThisUsage.Found - return $this->pool; - }; - - return $getPool->bindTo($cache, SymfonyDoctrineProvider::class)(); - } - - return new self($cache); - } - - private function __construct(Cache $cache) - { - $this->cache = $cache; - } - - /** @internal */ - public function getCache(): Cache - { - return $this->cache; - } - - /** - * {@inheritDoc} - */ - public function getItem($key): CacheItemInterface - { - assert(self::validKey($key)); - - if (isset($this->deferredItems[$key])) { - $this->commit(); - } - - $value = $this->cache->fetch($key); - - if (PHP_VERSION_ID >= 80000) { - if ($value !== false) { - return new TypedCacheItem($key, $value, true); - } - - return new TypedCacheItem($key, null, false); - } - - if ($value !== false) { - return new CacheItem($key, $value, true); - } - - return new CacheItem($key, null, false); - } - - /** - * {@inheritDoc} - */ - public function getItems(array $keys = []): array - { - if ($this->deferredItems) { - $this->commit(); - } - - assert(self::validKeys($keys)); - - $values = $this->doFetchMultiple($keys); - $items = []; - - if (PHP_VERSION_ID >= 80000) { - foreach ($keys as $key) { - if (array_key_exists($key, $values)) { - $items[$key] = new TypedCacheItem($key, $values[$key], true); - } else { - $items[$key] = new TypedCacheItem($key, null, false); - } - } - - return $items; - } - - foreach ($keys as $key) { - if (array_key_exists($key, $values)) { - $items[$key] = new CacheItem($key, $values[$key], true); - } else { - $items[$key] = new CacheItem($key, null, false); - } - } - - return $items; - } - - /** - * {@inheritDoc} - */ - public function hasItem($key): bool - { - assert(self::validKey($key)); - - if (isset($this->deferredItems[$key])) { - $this->commit(); - } - - return $this->cache->contains($key); - } - - public function clear(): bool - { - $this->deferredItems = []; - - if (! $this->cache instanceof ClearableCache) { - return false; - } - - return $this->cache->deleteAll(); - } - - /** - * {@inheritDoc} - */ - public function deleteItem($key): bool - { - assert(self::validKey($key)); - unset($this->deferredItems[$key]); - - return $this->cache->delete($key); - } - - /** - * {@inheritDoc} - */ - public function deleteItems(array $keys): bool - { - foreach ($keys as $key) { - assert(self::validKey($key)); - unset($this->deferredItems[$key]); - } - - return $this->doDeleteMultiple($keys); - } - - public function save(CacheItemInterface $item): bool - { - return $this->saveDeferred($item) && $this->commit(); - } - - public function saveDeferred(CacheItemInterface $item): bool - { - if (! $item instanceof CacheItem && ! $item instanceof TypedCacheItem) { - return false; - } - - $this->deferredItems[$item->getKey()] = $item; - - return true; - } - - public function commit(): bool - { - if (! $this->deferredItems) { - return true; - } - - $now = microtime(true); - $itemsCount = 0; - $byLifetime = []; - $expiredKeys = []; - - foreach ($this->deferredItems as $key => $item) { - $lifetime = ($item->getExpiry() ?? $now) - $now; - - if ($lifetime < 0) { - $expiredKeys[] = $key; - - continue; - } - - ++$itemsCount; - $byLifetime[(int) $lifetime][$key] = $item->get(); - } - - $this->deferredItems = []; - - switch (count($expiredKeys)) { - case 0: - break; - case 1: - $this->cache->delete(current($expiredKeys)); - break; - default: - $this->doDeleteMultiple($expiredKeys); - break; - } - - if ($itemsCount === 1) { - return $this->cache->save($key, $item->get(), (int) $lifetime); - } - - $success = true; - foreach ($byLifetime as $lifetime => $values) { - $success = $this->doSaveMultiple($values, $lifetime) && $success; - } - - return $success; - } - - public function __destruct() - { - $this->commit(); - } - - /** - * @param mixed $key - */ - private static function validKey($key): bool - { - if (! is_string($key)) { - throw new InvalidArgument(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); - } - - if ($key === '') { - throw new InvalidArgument('Cache key length must be greater than zero.'); - } - - if (strpbrk($key, self::RESERVED_CHARACTERS) !== false) { - throw new InvalidArgument(sprintf('Cache key "%s" contains reserved characters "%s".', $key, self::RESERVED_CHARACTERS)); - } - - return true; - } - - /** - * @param mixed[] $keys - */ - private static function validKeys(array $keys): bool - { - foreach ($keys as $key) { - self::validKey($key); - } - - return true; - } - - /** - * @param mixed[] $keys - */ - private function doDeleteMultiple(array $keys): bool - { - if ($this->cache instanceof MultiDeleteCache) { - return $this->cache->deleteMultiple($keys); - } - - $success = true; - foreach ($keys as $key) { - $success = $this->cache->delete($key) && $success; - } - - return $success; - } - - /** - * @param mixed[] $keys - * - * @return mixed[] - */ - private function doFetchMultiple(array $keys): array - { - if ($this->cache instanceof MultiGetCache) { - return $this->cache->fetchMultiple($keys); - } - - $values = []; - foreach ($keys as $key) { - $value = $this->cache->fetch($key); - if (! $value) { - continue; - } - - $values[$key] = $value; - } - - return $values; - } - - /** - * @param mixed[] $keysAndValues - */ - private function doSaveMultiple(array $keysAndValues, int $lifetime = 0): bool - { - if ($this->cache instanceof MultiPutCache) { - return $this->cache->saveMultiple($keysAndValues, $lifetime); - } - - $success = true; - foreach ($keysAndValues as $key => $value) { - $success = $this->cache->save($key, $value, $lifetime) && $success; - } - - return $success; - } -} diff --git a/lib/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/CacheItem.php b/lib/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/CacheItem.php deleted file mode 100644 index 0b6f0a28d..000000000 --- a/lib/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/CacheItem.php +++ /dev/null @@ -1,118 +0,0 @@ -<?php - -namespace Doctrine\Common\Cache\Psr6; - -use DateInterval; -use DateTime; -use DateTimeInterface; -use Psr\Cache\CacheItemInterface; -use TypeError; - -use function get_class; -use function gettype; -use function is_int; -use function is_object; -use function microtime; -use function sprintf; - -final class CacheItem implements CacheItemInterface -{ - /** @var string */ - private $key; - /** @var mixed */ - private $value; - /** @var bool */ - private $isHit; - /** @var float|null */ - private $expiry; - - /** - * @internal - * - * @param mixed $data - */ - public function __construct(string $key, $data, bool $isHit) - { - $this->key = $key; - $this->value = $data; - $this->isHit = $isHit; - } - - public function getKey(): string - { - return $this->key; - } - - /** - * {@inheritDoc} - * - * @return mixed - */ - public function get() - { - return $this->value; - } - - public function isHit(): bool - { - return $this->isHit; - } - - /** - * {@inheritDoc} - */ - public function set($value): self - { - $this->value = $value; - - return $this; - } - - /** - * {@inheritDoc} - */ - public function expiresAt($expiration): self - { - if ($expiration === null) { - $this->expiry = null; - } elseif ($expiration instanceof DateTimeInterface) { - $this->expiry = (float) $expiration->format('U.u'); - } else { - throw new TypeError(sprintf( - 'Expected $expiration to be an instance of DateTimeInterface or null, got %s', - is_object($expiration) ? get_class($expiration) : gettype($expiration) - )); - } - - return $this; - } - - /** - * {@inheritDoc} - */ - public function expiresAfter($time): self - { - if ($time === null) { - $this->expiry = null; - } elseif ($time instanceof DateInterval) { - $this->expiry = microtime(true) + DateTime::createFromFormat('U', 0)->add($time)->format('U.u'); - } elseif (is_int($time)) { - $this->expiry = $time + microtime(true); - } else { - throw new TypeError(sprintf( - 'Expected $time to be either an integer, an instance of DateInterval or null, got %s', - is_object($time) ? get_class($time) : gettype($time) - )); - } - - return $this; - } - - /** - * @internal - */ - public function getExpiry(): ?float - { - return $this->expiry; - } -} diff --git a/lib/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/DoctrineProvider.php b/lib/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/DoctrineProvider.php deleted file mode 100644 index 3b0f416c1..000000000 --- a/lib/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/DoctrineProvider.php +++ /dev/null @@ -1,135 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Doctrine\Common\Cache\Psr6; - -use Doctrine\Common\Cache\Cache; -use Doctrine\Common\Cache\CacheProvider; -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Cache\Adapter\DoctrineAdapter as SymfonyDoctrineAdapter; -use Symfony\Contracts\Service\ResetInterface; - -use function rawurlencode; - -/** - * This class was copied from the Symfony Framework, see the original copyright - * notice above. The code is distributed subject to the license terms in - * https://github.com/symfony/symfony/blob/ff0cf61278982539c49e467db9ab13cbd342f76d/LICENSE - */ -final class DoctrineProvider extends CacheProvider -{ - /** @var CacheItemPoolInterface */ - private $pool; - - public static function wrap(CacheItemPoolInterface $pool): Cache - { - if ($pool instanceof CacheAdapter) { - return $pool->getCache(); - } - - if ($pool instanceof SymfonyDoctrineAdapter) { - $getCache = function () { - // phpcs:ignore Squiz.Scope.StaticThisUsage.Found - return $this->provider; - }; - - return $getCache->bindTo($pool, SymfonyDoctrineAdapter::class)(); - } - - return new self($pool); - } - - private function __construct(CacheItemPoolInterface $pool) - { - $this->pool = $pool; - } - - /** @internal */ - public function getPool(): CacheItemPoolInterface - { - return $this->pool; - } - - public function reset(): void - { - if ($this->pool instanceof ResetInterface) { - $this->pool->reset(); - } - - $this->setNamespace($this->getNamespace()); - } - - /** - * {@inheritdoc} - */ - protected function doFetch($id) - { - $item = $this->pool->getItem(rawurlencode($id)); - - return $item->isHit() ? $item->get() : false; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - protected function doContains($id) - { - return $this->pool->hasItem(rawurlencode($id)); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - protected function doSave($id, $data, $lifeTime = 0) - { - $item = $this->pool->getItem(rawurlencode($id)); - - if (0 < $lifeTime) { - $item->expiresAfter($lifeTime); - } - - return $this->pool->save($item->set($data)); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - protected function doDelete($id) - { - return $this->pool->deleteItem(rawurlencode($id)); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - protected function doFlush() - { - return $this->pool->clear(); - } - - /** - * {@inheritdoc} - * - * @return array|null - */ - protected function doGetStats() - { - return null; - } -} diff --git a/lib/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/InvalidArgument.php b/lib/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/InvalidArgument.php deleted file mode 100644 index 196f1bca9..000000000 --- a/lib/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/InvalidArgument.php +++ /dev/null @@ -1,13 +0,0 @@ -<?php - -namespace Doctrine\Common\Cache\Psr6; - -use InvalidArgumentException; -use Psr\Cache\InvalidArgumentException as PsrInvalidArgumentException; - -/** - * @internal - */ -final class InvalidArgument extends InvalidArgumentException implements PsrInvalidArgumentException -{ -} diff --git a/lib/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/TypedCacheItem.php b/lib/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/TypedCacheItem.php deleted file mode 100644 index 60f379674..000000000 --- a/lib/doctrine/cache/lib/Doctrine/Common/Cache/Psr6/TypedCacheItem.php +++ /dev/null @@ -1,99 +0,0 @@ -<?php - -namespace Doctrine\Common\Cache\Psr6; - -use DateInterval; -use DateTime; -use DateTimeInterface; -use Psr\Cache\CacheItemInterface; -use TypeError; - -use function get_debug_type; -use function is_int; -use function microtime; -use function sprintf; - -final class TypedCacheItem implements CacheItemInterface -{ - private ?float $expiry = null; - - /** - * @internal - */ - public function __construct( - private string $key, - private mixed $value, - private bool $isHit, - ) { - } - - public function getKey(): string - { - return $this->key; - } - - public function get(): mixed - { - return $this->value; - } - - public function isHit(): bool - { - return $this->isHit; - } - - public function set(mixed $value): static - { - $this->value = $value; - - return $this; - } - - /** - * {@inheritDoc} - */ - public function expiresAt($expiration): static - { - if ($expiration === null) { - $this->expiry = null; - } elseif ($expiration instanceof DateTimeInterface) { - $this->expiry = (float) $expiration->format('U.u'); - } else { - throw new TypeError(sprintf( - 'Expected $expiration to be an instance of DateTimeInterface or null, got %s', - get_debug_type($expiration) - )); - } - - return $this; - } - - /** - * {@inheritDoc} - */ - public function expiresAfter($time): static - { - if ($time === null) { - $this->expiry = null; - } elseif ($time instanceof DateInterval) { - $this->expiry = microtime(true) + DateTime::createFromFormat('U', 0)->add($time)->format('U.u'); - } elseif (is_int($time)) { - $this->expiry = $time + microtime(true); - } else { - throw new TypeError(sprintf( - 'Expected $time to be either an integer, an instance of DateInterval or null, got %s', - get_debug_type($time) - )); - } - - return $this; - } - - /** - * @internal - */ - public function getExpiry(): ?float - { - return $this->expiry; - } -} diff --git a/lib/doctrine/deprecations/LICENSE b/lib/doctrine/deprecations/LICENSE deleted file mode 100644 index 156905cdd..000000000 --- a/lib/doctrine/deprecations/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2020-2021 Doctrine Project - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/lib/doctrine/deprecations/README.md b/lib/doctrine/deprecations/README.md deleted file mode 100644 index 93caf83f8..000000000 --- a/lib/doctrine/deprecations/README.md +++ /dev/null @@ -1,157 +0,0 @@ -# Doctrine Deprecations - -A small (side-effect free by default) layer on top of -`trigger_error(E_USER_DEPRECATED)` or PSR-3 logging. - -- no side-effects by default, making it a perfect fit for libraries that don't know how the error handler works they operate under -- options to avoid having to rely on error handlers global state by using PSR-3 logging -- deduplicate deprecation messages to avoid excessive triggering and reduce overhead - -We recommend to collect Deprecations using a PSR logger instead of relying on -the global error handler. - -## Usage from consumer perspective: - -Enable Doctrine deprecations to be sent to a PSR3 logger: - -```php -\Doctrine\Deprecations\Deprecation::enableWithPsrLogger($logger); -``` - -Enable Doctrine deprecations to be sent as `@trigger_error($message, E_USER_DEPRECATED)` -messages by setting the `DOCTRINE_DEPRECATIONS` environment variable to `trigger`. -Alternatively, call: - -```php -\Doctrine\Deprecations\Deprecation::enableWithTriggerError(); -``` - -If you only want to enable deprecation tracking, without logging or calling `trigger_error` -then set the `DOCTRINE_DEPRECATIONS` environment variable to `track`. -Alternatively, call: - -```php -\Doctrine\Deprecations\Deprecation::enableTrackingDeprecations(); -``` - -Tracking is enabled with all three modes and provides access to all triggered -deprecations and their individual count: - -```php -$deprecations = \Doctrine\Deprecations\Deprecation::getTriggeredDeprecations(); - -foreach ($deprecations as $identifier => $count) { - echo $identifier . " was triggered " . $count . " times\n"; -} -``` - -### Suppressing Specific Deprecations - -Disable triggering about specific deprecations: - -```php -\Doctrine\Deprecations\Deprecation::ignoreDeprecations("https://link/to/deprecations-description-identifier"); -``` - -Disable all deprecations from a package - -```php -\Doctrine\Deprecations\Deprecation::ignorePackage("doctrine/orm"); -``` - -### Other Operations - -When used within PHPUnit or other tools that could collect multiple instances of the same deprecations -the deduplication can be disabled: - -```php -\Doctrine\Deprecations\Deprecation::withoutDeduplication(); -``` - -Disable deprecation tracking again: - -```php -\Doctrine\Deprecations\Deprecation::disable(); -``` - -## Usage from a library/producer perspective: - -When you want to unconditionally trigger a deprecation even when called -from the library itself then the `trigger` method is the way to go: - -```php -\Doctrine\Deprecations\Deprecation::trigger( - "doctrine/orm", - "https://link/to/deprecations-description", - "message" -); -``` - -If variable arguments are provided at the end, they are used with `sprintf` on -the message. - -```php -\Doctrine\Deprecations\Deprecation::trigger( - "doctrine/orm", - "https://github.com/doctrine/orm/issue/1234", - "message %s %d", - "foo", - 1234 -); -``` - -When you want to trigger a deprecation only when it is called by a function -outside of the current package, but not trigger when the package itself is the cause, -then use: - -```php -\Doctrine\Deprecations\Deprecation::triggerIfCalledFromOutside( - "doctrine/orm", - "https://link/to/deprecations-description", - "message" -); -``` - -Based on the issue link each deprecation message is only triggered once per -request. - -A limited stacktrace is included in the deprecation message to find the -offending location. - -Note: A producer/library should never call `Deprecation::enableWith` methods -and leave the decision how to handle deprecations to application and -frameworks. - -## Usage in PHPUnit tests - -There is a `VerifyDeprecations` trait that you can use to make assertions on -the occurrence of deprecations within a test. - -```php -use Doctrine\Deprecations\PHPUnit\VerifyDeprecations; - -class MyTest extends TestCase -{ - use VerifyDeprecations; - - public function testSomethingDeprecation() - { - $this->expectDeprecationWithIdentifier('https://github.com/doctrine/orm/issue/1234'); - - triggerTheCodeWithDeprecation(); - } - - public function testSomethingDeprecationFixed() - { - $this->expectNoDeprecationWithIdentifier('https://github.com/doctrine/orm/issue/1234'); - - triggerTheCodeWithoutDeprecation(); - } -} -``` - -## What is a deprecation identifier? - -An identifier for deprecations is just a link to any resource, most often a -Github Issue or Pull Request explaining the deprecation and potentially its -alternative. diff --git a/lib/doctrine/deprecations/composer.json b/lib/doctrine/deprecations/composer.json deleted file mode 100644 index f8319f9a2..000000000 --- a/lib/doctrine/deprecations/composer.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "doctrine/deprecations", - "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", - "license": "MIT", - "type": "library", - "homepage": "https://www.doctrine-project.org/", - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9", - "phpstan/phpstan": "1.4.10 || 1.10.15", - "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "psalm/plugin-phpunit": "0.18.4", - "psr/log": "^1 || ^2 || ^3", - "vimeo/psalm": "4.30.0 || 5.12.0" - }, - "suggest": { - "psr/log": "Allows logging deprecations via PSR-3 logger implementation" - }, - "autoload": { - "psr-4": { - "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" - } - }, - "autoload-dev": { - "psr-4": { - "DeprecationTests\\": "test_fixtures/src", - "Doctrine\\Foo\\": "test_fixtures/vendor/doctrine/foo" - } - }, - "config": { - "allow-plugins": { - "dealerdirect/phpcodesniffer-composer-installer": true - } - } -} diff --git a/lib/doctrine/deprecations/lib/Doctrine/Deprecations/Deprecation.php b/lib/doctrine/deprecations/lib/Doctrine/Deprecations/Deprecation.php deleted file mode 100644 index 07cb43b6c..000000000 --- a/lib/doctrine/deprecations/lib/Doctrine/Deprecations/Deprecation.php +++ /dev/null @@ -1,312 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Doctrine\Deprecations; - -use Psr\Log\LoggerInterface; - -use function array_key_exists; -use function array_reduce; -use function assert; -use function debug_backtrace; -use function sprintf; -use function strpos; -use function strrpos; -use function substr; -use function trigger_error; - -use const DEBUG_BACKTRACE_IGNORE_ARGS; -use const DIRECTORY_SEPARATOR; -use const E_USER_DEPRECATED; - -/** - * Manages Deprecation logging in different ways. - * - * By default triggered exceptions are not logged. - * - * To enable different deprecation logging mechanisms you can call the - * following methods: - * - * - Minimal collection of deprecations via getTriggeredDeprecations() - * \Doctrine\Deprecations\Deprecation::enableTrackingDeprecations(); - * - * - Uses @trigger_error with E_USER_DEPRECATED - * \Doctrine\Deprecations\Deprecation::enableWithTriggerError(); - * - * - Sends deprecation messages via a PSR-3 logger - * \Doctrine\Deprecations\Deprecation::enableWithPsrLogger($logger); - * - * Packages that trigger deprecations should use the `trigger()` or - * `triggerIfCalledFromOutside()` methods. - */ -class Deprecation -{ - private const TYPE_NONE = 0; - private const TYPE_TRACK_DEPRECATIONS = 1; - private const TYPE_TRIGGER_ERROR = 2; - private const TYPE_PSR_LOGGER = 4; - - /** @var int-mask-of<self::TYPE_*>|null */ - private static $type; - - /** @var LoggerInterface|null */ - private static $logger; - - /** @var array<string,bool> */ - private static $ignoredPackages = []; - - /** @var array<string,int> */ - private static $triggeredDeprecations = []; - - /** @var array<string,bool> */ - private static $ignoredLinks = []; - - /** @var bool */ - private static $deduplication = true; - - /** - * Trigger a deprecation for the given package and identfier. - * - * The link should point to a Github issue or Wiki entry detailing the - * deprecation. It is additionally used to de-duplicate the trigger of the - * same deprecation during a request. - * - * @param float|int|string $args - */ - public static function trigger(string $package, string $link, string $message, ...$args): void - { - $type = self::$type ?? self::getTypeFromEnv(); - - if ($type === self::TYPE_NONE) { - return; - } - - if (isset(self::$ignoredLinks[$link])) { - return; - } - - if (array_key_exists($link, self::$triggeredDeprecations)) { - self::$triggeredDeprecations[$link]++; - } else { - self::$triggeredDeprecations[$link] = 1; - } - - if (self::$deduplication === true && self::$triggeredDeprecations[$link] > 1) { - return; - } - - if (isset(self::$ignoredPackages[$package])) { - return; - } - - $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); - - $message = sprintf($message, ...$args); - - self::delegateTriggerToBackend($message, $backtrace, $link, $package); - } - - /** - * Trigger a deprecation for the given package and identifier when called from outside. - * - * "Outside" means we assume that $package is currently installed as a - * dependency and the caller is not a file in that package. When $package - * is installed as a root package then deprecations triggered from the - * tests folder are also considered "outside". - * - * This deprecation method assumes that you are using Composer to install - * the dependency and are using the default /vendor/ folder and not a - * Composer plugin to change the install location. The assumption is also - * that $package is the exact composer packge name. - * - * Compared to {@link trigger()} this method causes some overhead when - * deprecation tracking is enabled even during deduplication, because it - * needs to call {@link debug_backtrace()} - * - * @param float|int|string $args - */ - public static function triggerIfCalledFromOutside(string $package, string $link, string $message, ...$args): void - { - $type = self::$type ?? self::getTypeFromEnv(); - - if ($type === self::TYPE_NONE) { - return; - } - - $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); - - // first check that the caller is not from a tests folder, in which case we always let deprecations pass - if (isset($backtrace[1]['file'], $backtrace[0]['file']) && strpos($backtrace[1]['file'], DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR) === false) { - $path = DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . $package . DIRECTORY_SEPARATOR; - - if (strpos($backtrace[0]['file'], $path) === false) { - return; - } - - if (strpos($backtrace[1]['file'], $path) !== false) { - return; - } - } - - if (isset(self::$ignoredLinks[$link])) { - return; - } - - if (array_key_exists($link, self::$triggeredDeprecations)) { - self::$triggeredDeprecations[$link]++; - } else { - self::$triggeredDeprecations[$link] = 1; - } - - if (self::$deduplication === true && self::$triggeredDeprecations[$link] > 1) { - return; - } - - if (isset(self::$ignoredPackages[$package])) { - return; - } - - $message = sprintf($message, ...$args); - - self::delegateTriggerToBackend($message, $backtrace, $link, $package); - } - - /** - * @param list<array{function: string, line?: int, file?: string, class?: class-string, type?: string, args?: mixed[], object?: object}> $backtrace - */ - private static function delegateTriggerToBackend(string $message, array $backtrace, string $link, string $package): void - { - $type = self::$type ?? self::getTypeFromEnv(); - - if (($type & self::TYPE_PSR_LOGGER) > 0) { - $context = [ - 'file' => $backtrace[0]['file'] ?? null, - 'line' => $backtrace[0]['line'] ?? null, - 'package' => $package, - 'link' => $link, - ]; - - assert(self::$logger !== null); - - self::$logger->notice($message, $context); - } - - if (! (($type & self::TYPE_TRIGGER_ERROR) > 0)) { - return; - } - - $message .= sprintf( - ' (%s:%d called by %s:%d, %s, package %s)', - self::basename($backtrace[0]['file'] ?? 'native code'), - $backtrace[0]['line'] ?? 0, - self::basename($backtrace[1]['file'] ?? 'native code'), - $backtrace[1]['line'] ?? 0, - $link, - $package - ); - - @trigger_error($message, E_USER_DEPRECATED); - } - - /** - * A non-local-aware version of PHPs basename function. - */ - private static function basename(string $filename): string - { - $pos = strrpos($filename, DIRECTORY_SEPARATOR); - - if ($pos === false) { - return $filename; - } - - return substr($filename, $pos + 1); - } - - public static function enableTrackingDeprecations(): void - { - self::$type = self::$type ?? 0; - self::$type |= self::TYPE_TRACK_DEPRECATIONS; - } - - public static function enableWithTriggerError(): void - { - self::$type = self::$type ?? 0; - self::$type |= self::TYPE_TRIGGER_ERROR; - } - - public static function enableWithPsrLogger(LoggerInterface $logger): void - { - self::$type = self::$type ?? 0; - self::$type |= self::TYPE_PSR_LOGGER; - self::$logger = $logger; - } - - public static function withoutDeduplication(): void - { - self::$deduplication = false; - } - - public static function disable(): void - { - self::$type = self::TYPE_NONE; - self::$logger = null; - self::$deduplication = true; - self::$ignoredLinks = []; - - foreach (self::$triggeredDeprecations as $link => $count) { - self::$triggeredDeprecations[$link] = 0; - } - } - - public static function ignorePackage(string $packageName): void - { - self::$ignoredPackages[$packageName] = true; - } - - public static function ignoreDeprecations(string ...$links): void - { - foreach ($links as $link) { - self::$ignoredLinks[$link] = true; - } - } - - public static function getUniqueTriggeredDeprecationsCount(): int - { - return array_reduce(self::$triggeredDeprecations, static function (int $carry, int $count) { - return $carry + $count; - }, 0); - } - - /** - * Returns each triggered deprecation link identifier and the amount of occurrences. - * - * @return array<string,int> - */ - public static function getTriggeredDeprecations(): array - { - return self::$triggeredDeprecations; - } - - /** - * @return int-mask-of<self::TYPE_*> - */ - private static function getTypeFromEnv(): int - { - switch ($_SERVER['DOCTRINE_DEPRECATIONS'] ?? $_ENV['DOCTRINE_DEPRECATIONS'] ?? null) { - case 'trigger': - self::$type = self::TYPE_TRIGGER_ERROR; - break; - - case 'track': - self::$type = self::TYPE_TRACK_DEPRECATIONS; - break; - - default: - self::$type = self::TYPE_NONE; - break; - } - - return self::$type; - } -} diff --git a/lib/doctrine/deprecations/lib/Doctrine/Deprecations/PHPUnit/VerifyDeprecations.php b/lib/doctrine/deprecations/lib/Doctrine/Deprecations/PHPUnit/VerifyDeprecations.php deleted file mode 100644 index 4c3366a97..000000000 --- a/lib/doctrine/deprecations/lib/Doctrine/Deprecations/PHPUnit/VerifyDeprecations.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Doctrine\Deprecations\PHPUnit; - -use Doctrine\Deprecations\Deprecation; - -use function sprintf; - -trait VerifyDeprecations -{ - /** @var array<string,int> */ - private $doctrineDeprecationsExpectations = []; - - /** @var array<string,int> */ - private $doctrineNoDeprecationsExpectations = []; - - public function expectDeprecationWithIdentifier(string $identifier): void - { - $this->doctrineDeprecationsExpectations[$identifier] = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0; - } - - public function expectNoDeprecationWithIdentifier(string $identifier): void - { - $this->doctrineNoDeprecationsExpectations[$identifier] = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0; - } - - /** - * @before - */ - public function enableDeprecationTracking(): void - { - Deprecation::enableTrackingDeprecations(); - } - - /** - * @after - */ - public function verifyDeprecationsAreTriggered(): void - { - foreach ($this->doctrineDeprecationsExpectations as $identifier => $expectation) { - $actualCount = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0; - - $this->assertTrue( - $actualCount > $expectation, - sprintf( - "Expected deprecation with identifier '%s' was not triggered by code executed in test.", - $identifier - ) - ); - } - - foreach ($this->doctrineNoDeprecationsExpectations as $identifier => $expectation) { - $actualCount = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0; - - $this->assertTrue( - $actualCount === $expectation, - sprintf( - "Expected deprecation with identifier '%s' was triggered by code executed in test, but expected not to.", - $identifier - ) - ); - } - } -} diff --git a/lib/doctrine/deprecations/phpcs.xml b/lib/doctrine/deprecations/phpcs.xml deleted file mode 100644 index f115e43dd..000000000 --- a/lib/doctrine/deprecations/phpcs.xml +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0"?> -<ruleset> - <arg name="basepath" value="."/> - <arg name="extensions" value="php"/> - <arg name="parallel" value="80"/> - <arg name="cache" value=".phpcs-cache"/> - <arg name="colors"/> - - <!-- Ignore warnings, show progress of the run and show sniff names --> - <arg value="nps"/> - - <config name="php_version" value="70100"/> - - <!-- Directories to be checked --> - <file>lib</file> - <file>tests</file> - - <!-- Include full Doctrine Coding Standard --> - <rule ref="Doctrine"> - <exclude name="SlevomatCodingStandard.TypeHints.PropertyTypeHint.MissingNativeTypeHint" /> - </rule> -</ruleset> diff --git a/lib/doctrine/deprecations/phpstan.neon b/lib/doctrine/deprecations/phpstan.neon deleted file mode 100644 index 4ee286b8a..000000000 --- a/lib/doctrine/deprecations/phpstan.neon +++ /dev/null @@ -1,9 +0,0 @@ -parameters: - level: 6 - paths: - - lib - - tests - -includes: - - vendor/phpstan/phpstan-phpunit/extension.neon - - vendor/phpstan/phpstan-phpunit/rules.neon diff --git a/lib/doctrine/deprecations/psalm.xml b/lib/doctrine/deprecations/psalm.xml deleted file mode 100644 index ad76e32e3..000000000 --- a/lib/doctrine/deprecations/psalm.xml +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0"?> -<psalm - errorLevel="1" - resolveFromConfigFile="true" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns="https://getpsalm.org/schema/config" - xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd" - findUnusedBaselineEntry="true" - findUnusedCode="false" -> - <projectFiles> - <directory name="lib/Doctrine/Deprecations" /> - <directory name="tests/Doctrine/Deprecations" /> - <ignoreFiles> - <directory name="vendor" /> - </ignoreFiles> - </projectFiles> - <plugins> - <pluginClass class="Psalm\PhpUnitPlugin\Plugin"/> - </plugins> - <issueHandlers> - <DeprecatedMethod> - <errorLevel type="suppress"> - <!-- Remove when dropping support for PHPUnit 9.6 --> - <referencedMethod name="PHPUnit\Framework\TestCase::expectDeprecation"/> - <referencedMethod name="PHPUnit\Framework\TestCase::expectDeprecationMessage"/> - </errorLevel> - </DeprecatedMethod> - </issueHandlers> -</psalm> diff --git a/lib/doctrine/lexer/LICENSE b/lib/doctrine/lexer/LICENSE deleted file mode 100644 index e8fdec4af..000000000 --- a/lib/doctrine/lexer/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2006-2018 Doctrine Project - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/lib/doctrine/lexer/README.md b/lib/doctrine/lexer/README.md deleted file mode 100644 index 784f2a271..000000000 --- a/lib/doctrine/lexer/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Doctrine Lexer - -[![Build Status](https://github.com/doctrine/lexer/workflows/Continuous%20Integration/badge.svg)](https://github.com/doctrine/lexer/actions) - -Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers. - -This lexer is used in Doctrine Annotations and in Doctrine ORM (DQL). - -https://www.doctrine-project.org/projects/lexer.html diff --git a/lib/doctrine/lexer/UPGRADE.md b/lib/doctrine/lexer/UPGRADE.md deleted file mode 100644 index 42b85b373..000000000 --- a/lib/doctrine/lexer/UPGRADE.md +++ /dev/null @@ -1,14 +0,0 @@ -Note about upgrading: Doctrine uses static and runtime mechanisms to raise -awareness about deprecated code. - -- Use of `@deprecated` docblock that is detected by IDEs (like PHPStorm) or - Static Analysis tools (like Psalm, phpstan) -- Use of our low-overhead runtime deprecation API, details: - https://github.com/doctrine/deprecations/ - -# Upgrade to 2.0.0 - -`AbstractLexer::glimpse()` and `AbstractLexer::peek()` now return -instances of `Doctrine\Common\Lexer\Token`, which is an array-like class -Using it as an array is deprecated in favor of using properties of that class. -Using `count()` on it is deprecated with no replacement. diff --git a/lib/doctrine/lexer/composer.json b/lib/doctrine/lexer/composer.json deleted file mode 100644 index be3013cff..000000000 --- a/lib/doctrine/lexer/composer.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "name": "doctrine/lexer", - "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", - "license": "MIT", - "type": "library", - "keywords": [ - "php", - "parser", - "lexer", - "annotations", - "docblock" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "homepage": "https://www.doctrine-project.org/projects/lexer.html", - "require": { - "php": "^7.1 || ^8.0", - "doctrine/deprecations": "^1.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9 || ^10", - "phpstan/phpstan": "^1.3", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "psalm/plugin-phpunit": "^0.18.3", - "vimeo/psalm": "^4.11 || ^5.0" - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\Lexer\\": "src" - } - }, - "autoload-dev": { - "psr-4": { - "Doctrine\\Tests\\Common\\Lexer\\": "tests" - } - }, - "config": { - "allow-plugins": { - "composer/package-versions-deprecated": true, - "dealerdirect/phpcodesniffer-composer-installer": true - }, - "sort-packages": true - } -} diff --git a/lib/doctrine/lexer/src/AbstractLexer.php b/lib/doctrine/lexer/src/AbstractLexer.php deleted file mode 100644 index eed4c5139..000000000 --- a/lib/doctrine/lexer/src/AbstractLexer.php +++ /dev/null @@ -1,346 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Doctrine\Common\Lexer; - -use ReflectionClass; -use UnitEnum; - -use function get_class; -use function implode; -use function preg_split; -use function sprintf; -use function substr; - -use const PREG_SPLIT_DELIM_CAPTURE; -use const PREG_SPLIT_NO_EMPTY; -use const PREG_SPLIT_OFFSET_CAPTURE; - -/** - * Base class for writing simple lexers, i.e. for creating small DSLs. - * - * @template T of UnitEnum|string|int - * @template V of string|int - */ -abstract class AbstractLexer -{ - /** - * Lexer original input string. - * - * @var string - */ - private $input; - - /** - * Array of scanned tokens. - * - * @var list<Token<T, V>> - */ - private $tokens = []; - - /** - * Current lexer position in input string. - * - * @var int - */ - private $position = 0; - - /** - * Current peek of current lexer position. - * - * @var int - */ - private $peek = 0; - - /** - * The next token in the input. - * - * @var mixed[]|null - * @psalm-var Token<T, V>|null - */ - public $lookahead; - - /** - * The last matched/seen token. - * - * @var mixed[]|null - * @psalm-var Token<T, V>|null - */ - public $token; - - /** - * Composed regex for input parsing. - * - * @var string|null - */ - private $regex; - - /** - * Sets the input data to be tokenized. - * - * The Lexer is immediately reset and the new input tokenized. - * Any unprocessed tokens from any previous input are lost. - * - * @param string $input The input to be tokenized. - * - * @return void - */ - public function setInput($input) - { - $this->input = $input; - $this->tokens = []; - - $this->reset(); - $this->scan($input); - } - - /** - * Resets the lexer. - * - * @return void - */ - public function reset() - { - $this->lookahead = null; - $this->token = null; - $this->peek = 0; - $this->position = 0; - } - - /** - * Resets the peek pointer to 0. - * - * @return void - */ - public function resetPeek() - { - $this->peek = 0; - } - - /** - * Resets the lexer position on the input to the given position. - * - * @param int $position Position to place the lexical scanner. - * - * @return void - */ - public function resetPosition($position = 0) - { - $this->position = $position; - } - - /** - * Retrieve the original lexer's input until a given position. - * - * @param int $position - * - * @return string - */ - public function getInputUntilPosition($position) - { - return substr($this->input, 0, $position); - } - - /** - * Checks whether a given token matches the current lookahead. - * - * @param T $type - * - * @return bool - * - * @psalm-assert-if-true !=null $this->lookahead - */ - public function isNextToken($type) - { - return $this->lookahead !== null && $this->lookahead->isA($type); - } - - /** - * Checks whether any of the given tokens matches the current lookahead. - * - * @param list<T> $types - * - * @return bool - * - * @psalm-assert-if-true !=null $this->lookahead - */ - public function isNextTokenAny(array $types) - { - return $this->lookahead !== null && $this->lookahead->isA(...$types); - } - - /** - * Moves to the next token in the input string. - * - * @return bool - * - * @psalm-assert-if-true !null $this->lookahead - */ - public function moveNext() - { - $this->peek = 0; - $this->token = $this->lookahead; - $this->lookahead = isset($this->tokens[$this->position]) - ? $this->tokens[$this->position++] : null; - - return $this->lookahead !== null; - } - - /** - * Tells the lexer to skip input tokens until it sees a token with the given value. - * - * @param T $type The token type to skip until. - * - * @return void - */ - public function skipUntil($type) - { - while ($this->lookahead !== null && ! $this->lookahead->isA($type)) { - $this->moveNext(); - } - } - - /** - * Checks if given value is identical to the given token. - * - * @param string $value - * @param int|string $token - * - * @return bool - */ - public function isA($value, $token) - { - return $this->getType($value) === $token; - } - - /** - * Moves the lookahead token forward. - * - * @return mixed[]|null The next token or NULL if there are no more tokens ahead. - * @psalm-return Token<T, V>|null - */ - public function peek() - { - if (isset($this->tokens[$this->position + $this->peek])) { - return $this->tokens[$this->position + $this->peek++]; - } - - return null; - } - - /** - * Peeks at the next token, returns it and immediately resets the peek. - * - * @return mixed[]|null The next token or NULL if there are no more tokens ahead. - * @psalm-return Token<T, V>|null - */ - public function glimpse() - { - $peek = $this->peek(); - $this->peek = 0; - - return $peek; - } - - /** - * Scans the input string for tokens. - * - * @param string $input A query string. - * - * @return void - */ - protected function scan($input) - { - if (! isset($this->regex)) { - $this->regex = sprintf( - '/(%s)|%s/%s', - implode(')|(', $this->getCatchablePatterns()), - implode('|', $this->getNonCatchablePatterns()), - $this->getModifiers() - ); - } - - $flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE; - $matches = preg_split($this->regex, $input, -1, $flags); - - if ($matches === false) { - // Work around https://bugs.php.net/78122 - $matches = [[$input, 0]]; - } - - foreach ($matches as $match) { - // Must remain before 'value' assignment since it can change content - $firstMatch = $match[0]; - $type = $this->getType($firstMatch); - - $this->tokens[] = new Token( - $firstMatch, - $type, - $match[1] - ); - } - } - - /** - * Gets the literal for a given token. - * - * @param T $token - * - * @return int|string - */ - public function getLiteral($token) - { - if ($token instanceof UnitEnum) { - return get_class($token) . '::' . $token->name; - } - - $className = static::class; - - $reflClass = new ReflectionClass($className); - $constants = $reflClass->getConstants(); - - foreach ($constants as $name => $value) { - if ($value === $token) { - return $className . '::' . $name; - } - } - - return $token; - } - - /** - * Regex modifiers - * - * @return string - */ - protected function getModifiers() - { - return 'iu'; - } - - /** - * Lexical catchable patterns. - * - * @return string[] - */ - abstract protected function getCatchablePatterns(); - - /** - * Lexical non-catchable patterns. - * - * @return string[] - */ - abstract protected function getNonCatchablePatterns(); - - /** - * Retrieve token type. Also processes the token value if necessary. - * - * @param string $value - * - * @return T|null - * - * @param-out V $value - */ - abstract protected function getType(&$value); -} diff --git a/lib/doctrine/lexer/src/Token.php b/lib/doctrine/lexer/src/Token.php deleted file mode 100644 index 4fbbf4e40..000000000 --- a/lib/doctrine/lexer/src/Token.php +++ /dev/null @@ -1,145 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Doctrine\Common\Lexer; - -use ArrayAccess; -use Doctrine\Deprecations\Deprecation; -use ReturnTypeWillChange; -use UnitEnum; - -use function in_array; - -/** - * @template T of UnitEnum|string|int - * @template V of string|int - * @implements ArrayAccess<string,mixed> - */ -final class Token implements ArrayAccess -{ - /** - * The string value of the token in the input string - * - * @readonly - * @var V - */ - public $value; - - /** - * The type of the token (identifier, numeric, string, input parameter, none) - * - * @readonly - * @var T|null - */ - public $type; - - /** - * The position of the token in the input string - * - * @readonly - * @var int - */ - public $position; - - /** - * @param V $value - * @param T|null $type - */ - public function __construct($value, $type, int $position) - { - $this->value = $value; - $this->type = $type; - $this->position = $position; - } - - /** @param T ...$types */ - public function isA(...$types): bool - { - return in_array($this->type, $types, true); - } - - /** - * @deprecated Use the value, type or position property instead - * {@inheritDoc} - */ - public function offsetExists($offset): bool - { - Deprecation::trigger( - 'doctrine/lexer', - 'https://github.com/doctrine/lexer/pull/79', - 'Accessing %s properties via ArrayAccess is deprecated, use the value, type or position property instead', - self::class - ); - - return in_array($offset, ['value', 'type', 'position'], true); - } - - /** - * @deprecated Use the value, type or position property instead - * {@inheritDoc} - * - * @param O $offset - * - * @return mixed - * @psalm-return ( - * O is 'value' - * ? V - * : ( - * O is 'type' - * ? T|null - * : ( - * O is 'position' - * ? int - * : mixed - * ) - * ) - * ) - * - * @template O of array-key - */ - #[ReturnTypeWillChange] - public function offsetGet($offset) - { - Deprecation::trigger( - 'doctrine/lexer', - 'https://github.com/doctrine/lexer/pull/79', - 'Accessing %s properties via ArrayAccess is deprecated, use the value, type or position property instead', - self::class - ); - - return $this->$offset; - } - - /** - * @deprecated no replacement planned - * {@inheritDoc} - */ - public function offsetSet($offset, $value): void - { - Deprecation::trigger( - 'doctrine/lexer', - 'https://github.com/doctrine/lexer/pull/79', - 'Setting %s properties via ArrayAccess is deprecated', - self::class - ); - - $this->$offset = $value; - } - - /** - * @deprecated no replacement planned - * {@inheritDoc} - */ - public function offsetUnset($offset): void - { - Deprecation::trigger( - 'doctrine/lexer', - 'https://github.com/doctrine/lexer/pull/79', - 'Setting %s properties via ArrayAccess is deprecated', - self::class - ); - - $this->$offset = null; - } -} diff --git a/lib/firebase/php-jwt/CHANGELOG.md b/lib/firebase/php-jwt/CHANGELOG.md deleted file mode 100644 index 9242bd30d..000000000 --- a/lib/firebase/php-jwt/CHANGELOG.md +++ /dev/null @@ -1,105 +0,0 @@ -# Changelog - -## [6.4.0](https://github.com/firebase/php-jwt/compare/v6.3.2...v6.4.0) (2023-02-08) - - -### Features - -* add support for W3C ES256K ([#462](https://github.com/firebase/php-jwt/issues/462)) ([213924f](https://github.com/firebase/php-jwt/commit/213924f51936291fbbca99158b11bd4ae56c2c95)) -* improve caching by only decoding jwks when necessary ([#486](https://github.com/firebase/php-jwt/issues/486)) ([78d3ed1](https://github.com/firebase/php-jwt/commit/78d3ed1073553f7d0bbffa6c2010009a0d483d5c)) - -## [6.3.2](https://github.com/firebase/php-jwt/compare/v6.3.1...v6.3.2) (2022-11-01) - - -### Bug Fixes - -* check kid before using as array index ([bad1b04](https://github.com/firebase/php-jwt/commit/bad1b040d0c736bbf86814c6b5ae614f517cf7bd)) - -## [6.3.1](https://github.com/firebase/php-jwt/compare/v6.3.0...v6.3.1) (2022-11-01) - - -### Bug Fixes - -* casing of GET for PSR compat ([#451](https://github.com/firebase/php-jwt/issues/451)) ([60b52b7](https://github.com/firebase/php-jwt/commit/60b52b71978790eafcf3b95cfbd83db0439e8d22)) -* string interpolation format for php 8.2 ([#446](https://github.com/firebase/php-jwt/issues/446)) ([2e07d8a](https://github.com/firebase/php-jwt/commit/2e07d8a1524d12b69b110ad649f17461d068b8f2)) - -## 6.3.0 / 2022-07-15 - - - Added ES256 support to JWK parsing ([#399](https://github.com/firebase/php-jwt/pull/399)) - - Fixed potential caching error in `CachedKeySet` by caching jwks as strings ([#435](https://github.com/firebase/php-jwt/pull/435)) - -## 6.2.0 / 2022-05-14 - - - Added `CachedKeySet` ([#397](https://github.com/firebase/php-jwt/pull/397)) - - Added `$defaultAlg` parameter to `JWT::parseKey` and `JWT::parseKeySet` ([#426](https://github.com/firebase/php-jwt/pull/426)). - -## 6.1.0 / 2022-03-23 - - - Drop support for PHP 5.3, 5.4, 5.5, 5.6, and 7.0 - - Add parameter typing and return types where possible - -## 6.0.0 / 2022-01-24 - - - **Backwards-Compatibility Breaking Changes**: See the [Release Notes](https://github.com/firebase/php-jwt/releases/tag/v6.0.0) for more information. - - New Key object to prevent key/algorithm type confusion (#365) - - Add JWK support (#273) - - Add ES256 support (#256) - - Add ES384 support (#324) - - Add Ed25519 support (#343) - -## 5.0.0 / 2017-06-26 -- Support RS384 and RS512. - See [#117](https://github.com/firebase/php-jwt/pull/117). Thanks [@joostfaassen](https://github.com/joostfaassen)! -- Add an example for RS256 openssl. - See [#125](https://github.com/firebase/php-jwt/pull/125). Thanks [@akeeman](https://github.com/akeeman)! -- Detect invalid Base64 encoding in signature. - See [#162](https://github.com/firebase/php-jwt/pull/162). Thanks [@psignoret](https://github.com/psignoret)! -- Update `JWT::verify` to handle OpenSSL errors. - See [#159](https://github.com/firebase/php-jwt/pull/159). Thanks [@bshaffer](https://github.com/bshaffer)! -- Add `array` type hinting to `decode` method - See [#101](https://github.com/firebase/php-jwt/pull/101). Thanks [@hywak](https://github.com/hywak)! -- Add all JSON error types. - See [#110](https://github.com/firebase/php-jwt/pull/110). Thanks [@gbalduzzi](https://github.com/gbalduzzi)! -- Bugfix 'kid' not in given key list. - See [#129](https://github.com/firebase/php-jwt/pull/129). Thanks [@stampycode](https://github.com/stampycode)! -- Miscellaneous cleanup, documentation and test fixes. - See [#107](https://github.com/firebase/php-jwt/pull/107), [#115](https://github.com/firebase/php-jwt/pull/115), - [#160](https://github.com/firebase/php-jwt/pull/160), [#161](https://github.com/firebase/php-jwt/pull/161), and - [#165](https://github.com/firebase/php-jwt/pull/165). Thanks [@akeeman](https://github.com/akeeman), - [@chinedufn](https://github.com/chinedufn), and [@bshaffer](https://github.com/bshaffer)! - -## 4.0.0 / 2016-07-17 -- Add support for late static binding. See [#88](https://github.com/firebase/php-jwt/pull/88) for details. Thanks to [@chappy84](https://github.com/chappy84)! -- Use static `$timestamp` instead of `time()` to improve unit testing. See [#93](https://github.com/firebase/php-jwt/pull/93) for details. Thanks to [@josephmcdermott](https://github.com/josephmcdermott)! -- Fixes to exceptions classes. See [#81](https://github.com/firebase/php-jwt/pull/81) for details. Thanks to [@Maks3w](https://github.com/Maks3w)! -- Fixes to PHPDoc. See [#76](https://github.com/firebase/php-jwt/pull/76) for details. Thanks to [@akeeman](https://github.com/akeeman)! - -## 3.0.0 / 2015-07-22 -- Minimum PHP version updated from `5.2.0` to `5.3.0`. -- Add `\Firebase\JWT` namespace. See -[#59](https://github.com/firebase/php-jwt/pull/59) for details. Thanks to -[@Dashron](https://github.com/Dashron)! -- Require a non-empty key to decode and verify a JWT. See -[#60](https://github.com/firebase/php-jwt/pull/60) for details. Thanks to -[@sjones608](https://github.com/sjones608)! -- Cleaner documentation blocks in the code. See -[#62](https://github.com/firebase/php-jwt/pull/62) for details. Thanks to -[@johanderuijter](https://github.com/johanderuijter)! - -## 2.2.0 / 2015-06-22 -- Add support for adding custom, optional JWT headers to `JWT::encode()`. See -[#53](https://github.com/firebase/php-jwt/pull/53/files) for details. Thanks to -[@mcocaro](https://github.com/mcocaro)! - -## 2.1.0 / 2015-05-20 -- Add support for adding a leeway to `JWT:decode()` that accounts for clock skew -between signing and verifying entities. Thanks to [@lcabral](https://github.com/lcabral)! -- Add support for passing an object implementing the `ArrayAccess` interface for -`$keys` argument in `JWT::decode()`. Thanks to [@aztech-dev](https://github.com/aztech-dev)! - -## 2.0.0 / 2015-04-01 -- **Note**: It is strongly recommended that you update to > v2.0.0 to address - known security vulnerabilities in prior versions when both symmetric and - asymmetric keys are used together. -- Update signature for `JWT::decode(...)` to require an array of supported - algorithms to use when verifying token signatures. diff --git a/lib/firebase/php-jwt/LICENSE b/lib/firebase/php-jwt/LICENSE deleted file mode 100644 index 11c014665..000000000 --- a/lib/firebase/php-jwt/LICENSE +++ /dev/null @@ -1,30 +0,0 @@ -Copyright (c) 2011, Neuman Vong - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - - * Neither the name of the copyright holder nor the names of other - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/lib/firebase/php-jwt/README.md b/lib/firebase/php-jwt/README.md deleted file mode 100644 index ae2b38956..000000000 --- a/lib/firebase/php-jwt/README.md +++ /dev/null @@ -1,332 +0,0 @@ -![Build Status](https://github.com/firebase/php-jwt/actions/workflows/tests.yml/badge.svg) -[![Latest Stable Version](https://poser.pugx.org/firebase/php-jwt/v/stable)](https://packagist.org/packages/firebase/php-jwt) -[![Total Downloads](https://poser.pugx.org/firebase/php-jwt/downloads)](https://packagist.org/packages/firebase/php-jwt) -[![License](https://poser.pugx.org/firebase/php-jwt/license)](https://packagist.org/packages/firebase/php-jwt) - -PHP-JWT -======= -A simple library to encode and decode JSON Web Tokens (JWT) in PHP, conforming to [RFC 7519](https://tools.ietf.org/html/rfc7519). - -Installation ------------- - -Use composer to manage your dependencies and download PHP-JWT: - -```bash -composer require firebase/php-jwt -``` - -Optionally, install the `paragonie/sodium_compat` package from composer if your -php is < 7.2 or does not have libsodium installed: - -```bash -composer require paragonie/sodium_compat -``` - -Example -------- -```php -use Firebase\JWT\JWT; -use Firebase\JWT\Key; - -$key = 'example_key'; -$payload = [ - 'iss' => 'http://example.org', - 'aud' => 'http://example.com', - 'iat' => 1356999524, - 'nbf' => 1357000000 -]; - -/** - * IMPORTANT: - * You must specify supported algorithms for your application. See - * https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40 - * for a list of spec-compliant algorithms. - */ -$jwt = JWT::encode($payload, $key, 'HS256'); -$decoded = JWT::decode($jwt, new Key($key, 'HS256')); - -print_r($decoded); - -/* - NOTE: This will now be an object instead of an associative array. To get - an associative array, you will need to cast it as such: -*/ - -$decoded_array = (array) $decoded; - -/** - * You can add a leeway to account for when there is a clock skew times between - * the signing and verifying servers. It is recommended that this leeway should - * not be bigger than a few minutes. - * - * Source: http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#nbfDef - */ -JWT::$leeway = 60; // $leeway in seconds -$decoded = JWT::decode($jwt, new Key($key, 'HS256')); -``` -Example with RS256 (openssl) ----------------------------- -```php -use Firebase\JWT\JWT; -use Firebase\JWT\Key; - -$privateKey = <<<EOD ------BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQC8kGa1pSjbSYZVebtTRBLxBz5H4i2p/llLCrEeQhta5kaQu/Rn -vuER4W8oDH3+3iuIYW4VQAzyqFpwuzjkDI+17t5t0tyazyZ8JXw+KgXTxldMPEL9 -5+qVhgXvwtihXC1c5oGbRlEDvDF6Sa53rcFVsYJ4ehde/zUxo6UvS7UrBQIDAQAB -AoGAb/MXV46XxCFRxNuB8LyAtmLDgi/xRnTAlMHjSACddwkyKem8//8eZtw9fzxz -bWZ/1/doQOuHBGYZU8aDzzj59FZ78dyzNFoF91hbvZKkg+6wGyd/LrGVEB+Xre0J -Nil0GReM2AHDNZUYRv+HYJPIOrB0CRczLQsgFJ8K6aAD6F0CQQDzbpjYdx10qgK1 -cP59UHiHjPZYC0loEsk7s+hUmT3QHerAQJMZWC11Qrn2N+ybwwNblDKv+s5qgMQ5 -5tNoQ9IfAkEAxkyffU6ythpg/H0Ixe1I2rd0GbF05biIzO/i77Det3n4YsJVlDck -ZkcvY3SK2iRIL4c9yY6hlIhs+K9wXTtGWwJBAO9Dskl48mO7woPR9uD22jDpNSwe -k90OMepTjzSvlhjbfuPN1IdhqvSJTDychRwn1kIJ7LQZgQ8fVz9OCFZ/6qMCQGOb -qaGwHmUK6xzpUbbacnYrIM6nLSkXgOAwv7XXCojvY614ILTK3iXiLBOxPu5Eu13k -eUz9sHyD6vkgZzjtxXECQAkp4Xerf5TGfQXGXhxIX52yH+N2LtujCdkQZjXAsGdm -B2zNzvrlgRmgBrklMTrMYgm1NPcW+bRLGcwgW2PTvNM= ------END RSA PRIVATE KEY----- -EOD; - -$publicKey = <<<EOD ------BEGIN PUBLIC KEY----- -MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8kGa1pSjbSYZVebtTRBLxBz5H -4i2p/llLCrEeQhta5kaQu/RnvuER4W8oDH3+3iuIYW4VQAzyqFpwuzjkDI+17t5t -0tyazyZ8JXw+KgXTxldMPEL95+qVhgXvwtihXC1c5oGbRlEDvDF6Sa53rcFVsYJ4 -ehde/zUxo6UvS7UrBQIDAQAB ------END PUBLIC KEY----- -EOD; - -$payload = [ - 'iss' => 'example.org', - 'aud' => 'example.com', - 'iat' => 1356999524, - 'nbf' => 1357000000 -]; - -$jwt = JWT::encode($payload, $privateKey, 'RS256'); -echo "Encode:\n" . print_r($jwt, true) . "\n"; - -$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); - -/* - NOTE: This will now be an object instead of an associative array. To get - an associative array, you will need to cast it as such: -*/ - -$decoded_array = (array) $decoded; -echo "Decode:\n" . print_r($decoded_array, true) . "\n"; -``` - -Example with a passphrase -------------------------- - -```php -use Firebase\JWT\JWT; -use Firebase\JWT\Key; - -// Your passphrase -$passphrase = '[YOUR_PASSPHRASE]'; - -// Your private key file with passphrase -// Can be generated with "ssh-keygen -t rsa -m pem" -$privateKeyFile = '/path/to/key-with-passphrase.pem'; - -// Create a private key of type "resource" -$privateKey = openssl_pkey_get_private( - file_get_contents($privateKeyFile), - $passphrase -); - -$payload = [ - 'iss' => 'example.org', - 'aud' => 'example.com', - 'iat' => 1356999524, - 'nbf' => 1357000000 -]; - -$jwt = JWT::encode($payload, $privateKey, 'RS256'); -echo "Encode:\n" . print_r($jwt, true) . "\n"; - -// Get public key from the private key, or pull from from a file. -$publicKey = openssl_pkey_get_details($privateKey)['key']; - -$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); -echo "Decode:\n" . print_r((array) $decoded, true) . "\n"; -``` - -Example with EdDSA (libsodium and Ed25519 signature) ----------------------------- -```php -use Firebase\JWT\JWT; -use Firebase\JWT\Key; - -// Public and private keys are expected to be Base64 encoded. The last -// non-empty line is used so that keys can be generated with -// sodium_crypto_sign_keypair(). The secret keys generated by other tools may -// need to be adjusted to match the input expected by libsodium. - -$keyPair = sodium_crypto_sign_keypair(); - -$privateKey = base64_encode(sodium_crypto_sign_secretkey($keyPair)); - -$publicKey = base64_encode(sodium_crypto_sign_publickey($keyPair)); - -$payload = [ - 'iss' => 'example.org', - 'aud' => 'example.com', - 'iat' => 1356999524, - 'nbf' => 1357000000 -]; - -$jwt = JWT::encode($payload, $privateKey, 'EdDSA'); -echo "Encode:\n" . print_r($jwt, true) . "\n"; - -$decoded = JWT::decode($jwt, new Key($publicKey, 'EdDSA')); -echo "Decode:\n" . print_r((array) $decoded, true) . "\n"; -```` - -Using JWKs ----------- - -```php -use Firebase\JWT\JWK; -use Firebase\JWT\JWT; - -// Set of keys. The "keys" key is required. For example, the JSON response to -// this endpoint: https://www.gstatic.com/iap/verify/public_key-jwk -$jwks = ['keys' => []]; - -// JWK::parseKeySet($jwks) returns an associative array of **kid** to Firebase\JWT\Key -// objects. Pass this as the second parameter to JWT::decode. -JWT::decode($payload, JWK::parseKeySet($jwks)); -``` - -Using Cached Key Sets ---------------------- - -The `CachedKeySet` class can be used to fetch and cache JWKS (JSON Web Key Sets) from a public URI. -This has the following advantages: - -1. The results are cached for performance. -2. If an unrecognized key is requested, the cache is refreshed, to accomodate for key rotation. -3. If rate limiting is enabled, the JWKS URI will not make more than 10 requests a second. - -```php -use Firebase\JWT\CachedKeySet; -use Firebase\JWT\JWT; - -// The URI for the JWKS you wish to cache the results from -$jwksUri = 'https://www.gstatic.com/iap/verify/public_key-jwk'; - -// Create an HTTP client (can be any PSR-7 compatible HTTP client) -$httpClient = new GuzzleHttp\Client(); - -// Create an HTTP request factory (can be any PSR-17 compatible HTTP request factory) -$httpFactory = new GuzzleHttp\Psr\HttpFactory(); - -// Create a cache item pool (can be any PSR-6 compatible cache item pool) -$cacheItemPool = Phpfastcache\CacheManager::getInstance('files'); - -$keySet = new CachedKeySet( - $jwksUri, - $httpClient, - $httpFactory, - $cacheItemPool, - null, // $expiresAfter int seconds to set the JWKS to expire - true // $rateLimit true to enable rate limit of 10 RPS on lookup of invalid keys -); - -$jwt = 'eyJhbGci...'; // Some JWT signed by a key from the $jwkUri above -$decoded = JWT::decode($jwt, $keySet); -``` - -Miscellaneous -------------- - -#### Exception Handling - -When a call to `JWT::decode` is invalid, it will throw one of the following exceptions: - -```php -use Firebase\JWT\JWT; -use Firebase\JWT\SignatureInvalidException; -use Firebase\JWT\BeforeValidException; -use Firebase\JWT\ExpiredException; -use DomainException; -use InvalidArgumentException; -use UnexpectedValueException; - -try { - $decoded = JWT::decode($payload, $keys); -} catch (InvalidArgumentException $e) { - // provided key/key-array is empty or malformed. -} catch (DomainException $e) { - // provided algorithm is unsupported OR - // provided key is invalid OR - // unknown error thrown in openSSL or libsodium OR - // libsodium is required but not available. -} catch (SignatureInvalidException $e) { - // provided JWT signature verification failed. -} catch (BeforeValidException $e) { - // provided JWT is trying to be used before "nbf" claim OR - // provided JWT is trying to be used before "iat" claim. -} catch (ExpiredException $e) { - // provided JWT is trying to be used after "exp" claim. -} catch (UnexpectedValueException $e) { - // provided JWT is malformed OR - // provided JWT is missing an algorithm / using an unsupported algorithm OR - // provided JWT algorithm does not match provided key OR - // provided key ID in key/key-array is empty or invalid. -} -``` - -All exceptions in the `Firebase\JWT` namespace extend `UnexpectedValueException`, and can be simplified -like this: - -```php -try { - $decoded = JWT::decode($payload, $keys); -} catch (LogicException $e) { - // errors having to do with environmental setup or malformed JWT Keys -} catch (UnexpectedValueException $e) { - // errors having to do with JWT signature and claims -} -``` - -#### Casting to array - -The return value of `JWT::decode` is the generic PHP object `stdClass`. If you'd like to handle with arrays -instead, you can do the following: - -```php -// return type is stdClass -$decoded = JWT::decode($payload, $keys); - -// cast to array -$decoded = json_decode(json_encode($decoded), true); -``` - -Tests ------ -Run the tests using phpunit: - -```bash -$ pear install PHPUnit -$ phpunit --configuration phpunit.xml.dist -PHPUnit 3.7.10 by Sebastian Bergmann. -..... -Time: 0 seconds, Memory: 2.50Mb -OK (5 tests, 5 assertions) -``` - -New Lines in private keys ------ - -If your private key contains `\n` characters, be sure to wrap it in double quotes `""` -and not single quotes `''` in order to properly interpret the escaped characters. - -License -------- -[3-Clause BSD](http://opensource.org/licenses/BSD-3-Clause). diff --git a/lib/firebase/php-jwt/composer.json b/lib/firebase/php-jwt/composer.json deleted file mode 100644 index c9aa3dbbc..000000000 --- a/lib/firebase/php-jwt/composer.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "firebase/php-jwt", - "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", - "homepage": "https://github.com/firebase/php-jwt", - "keywords": [ - "php", - "jwt" - ], - "authors": [ - { - "name": "Neuman Vong", - "email": "neuman+pear@twilio.com", - "role": "Developer" - }, - { - "name": "Anant Narayanan", - "email": "anant@php.net", - "role": "Developer" - } - ], - "license": "BSD-3-Clause", - "require": { - "php": "^7.1||^8.0" - }, - "suggest": { - "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present", - "ext-sodium": "Support EdDSA (Ed25519) signatures" - }, - "autoload": { - "psr-4": { - "Firebase\\JWT\\": "src" - } - }, - "require-dev": { - "guzzlehttp/guzzle": "^6.5||^7.4", - "phpspec/prophecy-phpunit": "^1.1", - "phpunit/phpunit": "^7.5||^9.5", - "psr/cache": "^1.0||^2.0", - "psr/http-client": "^1.0", - "psr/http-factory": "^1.0" - } -} diff --git a/lib/firebase/php-jwt/src/BeforeValidException.php b/lib/firebase/php-jwt/src/BeforeValidException.php deleted file mode 100644 index c147852b9..000000000 --- a/lib/firebase/php-jwt/src/BeforeValidException.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace Firebase\JWT; - -class BeforeValidException extends \UnexpectedValueException -{ -} diff --git a/lib/firebase/php-jwt/src/CachedKeySet.php b/lib/firebase/php-jwt/src/CachedKeySet.php deleted file mode 100644 index baf801f13..000000000 --- a/lib/firebase/php-jwt/src/CachedKeySet.php +++ /dev/null @@ -1,258 +0,0 @@ -<?php - -namespace Firebase\JWT; - -use ArrayAccess; -use InvalidArgumentException; -use LogicException; -use OutOfBoundsException; -use Psr\Cache\CacheItemInterface; -use Psr\Cache\CacheItemPoolInterface; -use Psr\Http\Client\ClientInterface; -use Psr\Http\Message\RequestFactoryInterface; -use RuntimeException; -use UnexpectedValueException; - -/** - * @implements ArrayAccess<string, Key> - */ -class CachedKeySet implements ArrayAccess -{ - /** - * @var string - */ - private $jwksUri; - /** - * @var ClientInterface - */ - private $httpClient; - /** - * @var RequestFactoryInterface - */ - private $httpFactory; - /** - * @var CacheItemPoolInterface - */ - private $cache; - /** - * @var ?int - */ - private $expiresAfter; - /** - * @var ?CacheItemInterface - */ - private $cacheItem; - /** - * @var array<string, array<mixed>> - */ - private $keySet; - /** - * @var string - */ - private $cacheKey; - /** - * @var string - */ - private $cacheKeyPrefix = 'jwks'; - /** - * @var int - */ - private $maxKeyLength = 64; - /** - * @var bool - */ - private $rateLimit; - /** - * @var string - */ - private $rateLimitCacheKey; - /** - * @var int - */ - private $maxCallsPerMinute = 10; - /** - * @var string|null - */ - private $defaultAlg; - - public function __construct( - string $jwksUri, - ClientInterface $httpClient, - RequestFactoryInterface $httpFactory, - CacheItemPoolInterface $cache, - int $expiresAfter = null, - bool $rateLimit = false, - string $defaultAlg = null - ) { - $this->jwksUri = $jwksUri; - $this->httpClient = $httpClient; - $this->httpFactory = $httpFactory; - $this->cache = $cache; - $this->expiresAfter = $expiresAfter; - $this->rateLimit = $rateLimit; - $this->defaultAlg = $defaultAlg; - $this->setCacheKeys(); - } - - /** - * @param string $keyId - * @return Key - */ - public function offsetGet($keyId): Key - { - if (!$this->keyIdExists($keyId)) { - throw new OutOfBoundsException('Key ID not found'); - } - return JWK::parseKey($this->keySet[$keyId], $this->defaultAlg); - } - - /** - * @param string $keyId - * @return bool - */ - public function offsetExists($keyId): bool - { - return $this->keyIdExists($keyId); - } - - /** - * @param string $offset - * @param Key $value - */ - public function offsetSet($offset, $value): void - { - throw new LogicException('Method not implemented'); - } - - /** - * @param string $offset - */ - public function offsetUnset($offset): void - { - throw new LogicException('Method not implemented'); - } - - /** - * @return array<mixed> - */ - private function formatJwksForCache(string $jwks): array - { - $jwks = json_decode($jwks, true); - - if (!isset($jwks['keys'])) { - throw new UnexpectedValueException('"keys" member must exist in the JWK Set'); - } - - if (empty($jwks['keys'])) { - throw new InvalidArgumentException('JWK Set did not contain any keys'); - } - - $keys = []; - foreach ($jwks['keys'] as $k => $v) { - $kid = isset($v['kid']) ? $v['kid'] : $k; - $keys[(string) $kid] = $v; - } - - return $keys; - } - - private function keyIdExists(string $keyId): bool - { - if (null === $this->keySet) { - $item = $this->getCacheItem(); - // Try to load keys from cache - if ($item->isHit()) { - // item found! retrieve it - $this->keySet = $item->get(); - // If the cached item is a string, the JWKS response was cached (previous behavior). - // Parse this into expected format array<kid, jwk> instead. - if (\is_string($this->keySet)) { - $this->keySet = $this->formatJwksForCache($this->keySet); - } - } - } - - if (!isset($this->keySet[$keyId])) { - if ($this->rateLimitExceeded()) { - return false; - } - $request = $this->httpFactory->createRequest('GET', $this->jwksUri); - $jwksResponse = $this->httpClient->sendRequest($request); - $this->keySet = $this->formatJwksForCache((string) $jwksResponse->getBody()); - - if (!isset($this->keySet[$keyId])) { - return false; - } - - $item = $this->getCacheItem(); - $item->set($this->keySet); - if ($this->expiresAfter) { - $item->expiresAfter($this->expiresAfter); - } - $this->cache->save($item); - } - - return true; - } - - private function rateLimitExceeded(): bool - { - if (!$this->rateLimit) { - return false; - } - - $cacheItem = $this->cache->getItem($this->rateLimitCacheKey); - if (!$cacheItem->isHit()) { - $cacheItem->expiresAfter(1); // # of calls are cached each minute - } - - $callsPerMinute = (int) $cacheItem->get(); - if (++$callsPerMinute > $this->maxCallsPerMinute) { - return true; - } - $cacheItem->set($callsPerMinute); - $this->cache->save($cacheItem); - return false; - } - - private function getCacheItem(): CacheItemInterface - { - if (\is_null($this->cacheItem)) { - $this->cacheItem = $this->cache->getItem($this->cacheKey); - } - - return $this->cacheItem; - } - - private function setCacheKeys(): void - { - if (empty($this->jwksUri)) { - throw new RuntimeException('JWKS URI is empty'); - } - - // ensure we do not have illegal characters - $key = preg_replace('|[^a-zA-Z0-9_\.!]|', '', $this->jwksUri); - - // add prefix - $key = $this->cacheKeyPrefix . $key; - - // Hash keys if they exceed $maxKeyLength of 64 - if (\strlen($key) > $this->maxKeyLength) { - $key = substr(hash('sha256', $key), 0, $this->maxKeyLength); - } - - $this->cacheKey = $key; - - if ($this->rateLimit) { - // add prefix - $rateLimitKey = $this->cacheKeyPrefix . 'ratelimit' . $key; - - // Hash keys if they exceed $maxKeyLength of 64 - if (\strlen($rateLimitKey) > $this->maxKeyLength) { - $rateLimitKey = substr(hash('sha256', $rateLimitKey), 0, $this->maxKeyLength); - } - - $this->rateLimitCacheKey = $rateLimitKey; - } - } -} diff --git a/lib/firebase/php-jwt/src/ExpiredException.php b/lib/firebase/php-jwt/src/ExpiredException.php deleted file mode 100644 index 81ba52d43..000000000 --- a/lib/firebase/php-jwt/src/ExpiredException.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace Firebase\JWT; - -class ExpiredException extends \UnexpectedValueException -{ -} diff --git a/lib/firebase/php-jwt/src/JWK.php b/lib/firebase/php-jwt/src/JWK.php deleted file mode 100644 index c7eff8ae4..000000000 --- a/lib/firebase/php-jwt/src/JWK.php +++ /dev/null @@ -1,323 +0,0 @@ -<?php - -namespace Firebase\JWT; - -use DomainException; -use InvalidArgumentException; -use UnexpectedValueException; - -/** - * JSON Web Key implementation, based on this spec: - * https://tools.ietf.org/html/draft-ietf-jose-json-web-key-41 - * - * PHP version 5 - * - * @category Authentication - * @package Authentication_JWT - * @author Bui Sy Nguyen <nguyenbs@gmail.com> - * @license http://opensource.org/licenses/BSD-3-Clause 3-clause BSD - * @link https://github.com/firebase/php-jwt - */ -class JWK -{ - private const OID = '1.2.840.10045.2.1'; - private const ASN1_OBJECT_IDENTIFIER = 0x06; - private const ASN1_SEQUENCE = 0x10; // also defined in JWT - private const ASN1_BIT_STRING = 0x03; - private const EC_CURVES = [ - 'P-256' => '1.2.840.10045.3.1.7', // Len: 64 - 'secp256k1' => '1.3.132.0.10', // Len: 64 - // 'P-384' => '1.3.132.0.34', // Len: 96 (not yet supported) - // 'P-521' => '1.3.132.0.35', // Len: 132 (not supported) - ]; - - /** - * Parse a set of JWK keys - * - * @param array<mixed> $jwks The JSON Web Key Set as an associative array - * @param string $defaultAlg The algorithm for the Key object if "alg" is not set in the - * JSON Web Key Set - * - * @return array<string, Key> An associative array of key IDs (kid) to Key objects - * - * @throws InvalidArgumentException Provided JWK Set is empty - * @throws UnexpectedValueException Provided JWK Set was invalid - * @throws DomainException OpenSSL failure - * - * @uses parseKey - */ - public static function parseKeySet(array $jwks, string $defaultAlg = null): array - { - $keys = []; - - if (!isset($jwks['keys'])) { - throw new UnexpectedValueException('"keys" member must exist in the JWK Set'); - } - - if (empty($jwks['keys'])) { - throw new InvalidArgumentException('JWK Set did not contain any keys'); - } - - foreach ($jwks['keys'] as $k => $v) { - $kid = isset($v['kid']) ? $v['kid'] : $k; - if ($key = self::parseKey($v, $defaultAlg)) { - $keys[(string) $kid] = $key; - } - } - - if (0 === \count($keys)) { - throw new UnexpectedValueException('No supported algorithms found in JWK Set'); - } - - return $keys; - } - - /** - * Parse a JWK key - * - * @param array<mixed> $jwk An individual JWK - * @param string $defaultAlg The algorithm for the Key object if "alg" is not set in the - * JSON Web Key Set - * - * @return Key The key object for the JWK - * - * @throws InvalidArgumentException Provided JWK is empty - * @throws UnexpectedValueException Provided JWK was invalid - * @throws DomainException OpenSSL failure - * - * @uses createPemFromModulusAndExponent - */ - public static function parseKey(array $jwk, string $defaultAlg = null): ?Key - { - if (empty($jwk)) { - throw new InvalidArgumentException('JWK must not be empty'); - } - - if (!isset($jwk['kty'])) { - throw new UnexpectedValueException('JWK must contain a "kty" parameter'); - } - - if (!isset($jwk['alg'])) { - if (\is_null($defaultAlg)) { - // The "alg" parameter is optional in a KTY, but an algorithm is required - // for parsing in this library. Use the $defaultAlg parameter when parsing the - // key set in order to prevent this error. - // @see https://datatracker.ietf.org/doc/html/rfc7517#section-4.4 - throw new UnexpectedValueException('JWK must contain an "alg" parameter'); - } - $jwk['alg'] = $defaultAlg; - } - - switch ($jwk['kty']) { - case 'RSA': - if (!empty($jwk['d'])) { - throw new UnexpectedValueException('RSA private keys are not supported'); - } - if (!isset($jwk['n']) || !isset($jwk['e'])) { - throw new UnexpectedValueException('RSA keys must contain values for both "n" and "e"'); - } - - $pem = self::createPemFromModulusAndExponent($jwk['n'], $jwk['e']); - $publicKey = \openssl_pkey_get_public($pem); - if (false === $publicKey) { - throw new DomainException( - 'OpenSSL error: ' . \openssl_error_string() - ); - } - return new Key($publicKey, $jwk['alg']); - case 'EC': - if (isset($jwk['d'])) { - // The key is actually a private key - throw new UnexpectedValueException('Key data must be for a public key'); - } - - if (empty($jwk['crv'])) { - throw new UnexpectedValueException('crv not set'); - } - - if (!isset(self::EC_CURVES[$jwk['crv']])) { - throw new DomainException('Unrecognised or unsupported EC curve'); - } - - if (empty($jwk['x']) || empty($jwk['y'])) { - throw new UnexpectedValueException('x and y not set'); - } - - $publicKey = self::createPemFromCrvAndXYCoordinates($jwk['crv'], $jwk['x'], $jwk['y']); - return new Key($publicKey, $jwk['alg']); - default: - // Currently only RSA is supported - break; - } - - return null; - } - - /** - * Converts the EC JWK values to pem format. - * - * @param string $crv The EC curve (only P-256 is supported) - * @param string $x The EC x-coordinate - * @param string $y The EC y-coordinate - * - * @return string - */ - private static function createPemFromCrvAndXYCoordinates(string $crv, string $x, string $y): string - { - $pem = - self::encodeDER( - self::ASN1_SEQUENCE, - self::encodeDER( - self::ASN1_SEQUENCE, - self::encodeDER( - self::ASN1_OBJECT_IDENTIFIER, - self::encodeOID(self::OID) - ) - . self::encodeDER( - self::ASN1_OBJECT_IDENTIFIER, - self::encodeOID(self::EC_CURVES[$crv]) - ) - ) . - self::encodeDER( - self::ASN1_BIT_STRING, - \chr(0x00) . \chr(0x04) - . JWT::urlsafeB64Decode($x) - . JWT::urlsafeB64Decode($y) - ) - ); - - return sprintf( - "-----BEGIN PUBLIC KEY-----\n%s\n-----END PUBLIC KEY-----\n", - wordwrap(base64_encode($pem), 64, "\n", true) - ); - } - - /** - * Create a public key represented in PEM format from RSA modulus and exponent information - * - * @param string $n The RSA modulus encoded in Base64 - * @param string $e The RSA exponent encoded in Base64 - * - * @return string The RSA public key represented in PEM format - * - * @uses encodeLength - */ - private static function createPemFromModulusAndExponent( - string $n, - string $e - ): string { - $mod = JWT::urlsafeB64Decode($n); - $exp = JWT::urlsafeB64Decode($e); - - $modulus = \pack('Ca*a*', 2, self::encodeLength(\strlen($mod)), $mod); - $publicExponent = \pack('Ca*a*', 2, self::encodeLength(\strlen($exp)), $exp); - - $rsaPublicKey = \pack( - 'Ca*a*a*', - 48, - self::encodeLength(\strlen($modulus) + \strlen($publicExponent)), - $modulus, - $publicExponent - ); - - // sequence(oid(1.2.840.113549.1.1.1), null)) = rsaEncryption. - $rsaOID = \pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA - $rsaPublicKey = \chr(0) . $rsaPublicKey; - $rsaPublicKey = \chr(3) . self::encodeLength(\strlen($rsaPublicKey)) . $rsaPublicKey; - - $rsaPublicKey = \pack( - 'Ca*a*', - 48, - self::encodeLength(\strlen($rsaOID . $rsaPublicKey)), - $rsaOID . $rsaPublicKey - ); - - return "-----BEGIN PUBLIC KEY-----\r\n" . - \chunk_split(\base64_encode($rsaPublicKey), 64) . - '-----END PUBLIC KEY-----'; - } - - /** - * DER-encode the length - * - * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See - * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information. - * - * @param int $length - * @return string - */ - private static function encodeLength(int $length): string - { - if ($length <= 0x7F) { - return \chr($length); - } - - $temp = \ltrim(\pack('N', $length), \chr(0)); - - return \pack('Ca*', 0x80 | \strlen($temp), $temp); - } - - /** - * Encodes a value into a DER object. - * Also defined in Firebase\JWT\JWT - * - * @param int $type DER tag - * @param string $value the value to encode - * @return string the encoded object - */ - private static function encodeDER(int $type, string $value): string - { - $tag_header = 0; - if ($type === self::ASN1_SEQUENCE) { - $tag_header |= 0x20; - } - - // Type - $der = \chr($tag_header | $type); - - // Length - $der .= \chr(\strlen($value)); - - return $der . $value; - } - - /** - * Encodes a string into a DER-encoded OID. - * - * @param string $oid the OID string - * @return string the binary DER-encoded OID - */ - private static function encodeOID(string $oid): string - { - $octets = explode('.', $oid); - - // Get the first octet - $first = (int) array_shift($octets); - $second = (int) array_shift($octets); - $oid = \chr($first * 40 + $second); - - // Iterate over subsequent octets - foreach ($octets as $octet) { - if ($octet == 0) { - $oid .= \chr(0x00); - continue; - } - $bin = ''; - - while ($octet) { - $bin .= \chr(0x80 | ($octet & 0x7f)); - $octet >>= 7; - } - $bin[0] = $bin[0] & \chr(0x7f); - - // Convert to big endian if necessary - if (pack('V', 65534) == pack('L', 65534)) { - $oid .= strrev($bin); - } else { - $oid .= $bin; - } - } - - return $oid; - } -} diff --git a/lib/firebase/php-jwt/src/JWT.php b/lib/firebase/php-jwt/src/JWT.php deleted file mode 100644 index 269e8caf0..000000000 --- a/lib/firebase/php-jwt/src/JWT.php +++ /dev/null @@ -1,638 +0,0 @@ -<?php - -namespace Firebase\JWT; - -use ArrayAccess; -use DateTime; -use DomainException; -use Exception; -use InvalidArgumentException; -use OpenSSLAsymmetricKey; -use OpenSSLCertificate; -use stdClass; -use UnexpectedValueException; - -/** - * JSON Web Token implementation, based on this spec: - * https://tools.ietf.org/html/rfc7519 - * - * PHP version 5 - * - * @category Authentication - * @package Authentication_JWT - * @author Neuman Vong <neuman@twilio.com> - * @author Anant Narayanan <anant@php.net> - * @license http://opensource.org/licenses/BSD-3-Clause 3-clause BSD - * @link https://github.com/firebase/php-jwt - */ -class JWT -{ - private const ASN1_INTEGER = 0x02; - private const ASN1_SEQUENCE = 0x10; - private const ASN1_BIT_STRING = 0x03; - - /** - * When checking nbf, iat or expiration times, - * we want to provide some extra leeway time to - * account for clock skew. - * - * @var int - */ - public static $leeway = 0; - - /** - * Allow the current timestamp to be specified. - * Useful for fixing a value within unit testing. - * Will default to PHP time() value if null. - * - * @var ?int - */ - public static $timestamp = null; - - /** - * @var array<string, string[]> - */ - public static $supported_algs = [ - 'ES384' => ['openssl', 'SHA384'], - 'ES256' => ['openssl', 'SHA256'], - 'ES256K' => ['openssl', 'SHA256'], - 'HS256' => ['hash_hmac', 'SHA256'], - 'HS384' => ['hash_hmac', 'SHA384'], - 'HS512' => ['hash_hmac', 'SHA512'], - 'RS256' => ['openssl', 'SHA256'], - 'RS384' => ['openssl', 'SHA384'], - 'RS512' => ['openssl', 'SHA512'], - 'EdDSA' => ['sodium_crypto', 'EdDSA'], - ]; - - /** - * Decodes a JWT string into a PHP object. - * - * @param string $jwt The JWT - * @param Key|array<string,Key> $keyOrKeyArray The Key or associative array of key IDs (kid) to Key objects. - * If the algorithm used is asymmetric, this is the public key - * Each Key object contains an algorithm and matching key. - * Supported algorithms are 'ES384','ES256', 'HS256', 'HS384', - * 'HS512', 'RS256', 'RS384', and 'RS512' - * - * @return stdClass The JWT's payload as a PHP object - * - * @throws InvalidArgumentException Provided key/key-array was empty or malformed - * @throws DomainException Provided JWT is malformed - * @throws UnexpectedValueException Provided JWT was invalid - * @throws SignatureInvalidException Provided JWT was invalid because the signature verification failed - * @throws BeforeValidException Provided JWT is trying to be used before it's eligible as defined by 'nbf' - * @throws BeforeValidException Provided JWT is trying to be used before it's been created as defined by 'iat' - * @throws ExpiredException Provided JWT has since expired, as defined by the 'exp' claim - * - * @uses jsonDecode - * @uses urlsafeB64Decode - */ - public static function decode( - string $jwt, - $keyOrKeyArray - ): stdClass { - // Validate JWT - $timestamp = \is_null(static::$timestamp) ? \time() : static::$timestamp; - - if (empty($keyOrKeyArray)) { - throw new InvalidArgumentException('Key may not be empty'); - } - $tks = \explode('.', $jwt); - if (\count($tks) !== 3) { - throw new UnexpectedValueException('Wrong number of segments'); - } - list($headb64, $bodyb64, $cryptob64) = $tks; - $headerRaw = static::urlsafeB64Decode($headb64); - if (null === ($header = static::jsonDecode($headerRaw))) { - throw new UnexpectedValueException('Invalid header encoding'); - } - $payloadRaw = static::urlsafeB64Decode($bodyb64); - if (null === ($payload = static::jsonDecode($payloadRaw))) { - throw new UnexpectedValueException('Invalid claims encoding'); - } - if (\is_array($payload)) { - // prevent PHP Fatal Error in edge-cases when payload is empty array - $payload = (object) $payload; - } - if (!$payload instanceof stdClass) { - throw new UnexpectedValueException('Payload must be a JSON object'); - } - $sig = static::urlsafeB64Decode($cryptob64); - if (empty($header->alg)) { - throw new UnexpectedValueException('Empty algorithm'); - } - if (empty(static::$supported_algs[$header->alg])) { - throw new UnexpectedValueException('Algorithm not supported'); - } - - $key = self::getKey($keyOrKeyArray, property_exists($header, 'kid') ? $header->kid : null); - - // Check the algorithm - if (!self::constantTimeEquals($key->getAlgorithm(), $header->alg)) { - // See issue #351 - throw new UnexpectedValueException('Incorrect key for this algorithm'); - } - if (\in_array($header->alg, ['ES256', 'ES256K', 'ES384'], true)) { - // OpenSSL expects an ASN.1 DER sequence for ES256/ES256K/ES384 signatures - $sig = self::signatureToDER($sig); - } - if (!self::verify("{$headb64}.{$bodyb64}", $sig, $key->getKeyMaterial(), $header->alg)) { - throw new SignatureInvalidException('Signature verification failed'); - } - - // Check the nbf if it is defined. This is the time that the - // token can actually be used. If it's not yet that time, abort. - if (isset($payload->nbf) && $payload->nbf > ($timestamp + static::$leeway)) { - throw new BeforeValidException( - 'Cannot handle token prior to ' . \date(DateTime::ISO8601, $payload->nbf) - ); - } - - // Check that this token has been created before 'now'. This prevents - // using tokens that have been created for later use (and haven't - // correctly used the nbf claim). - if (isset($payload->iat) && $payload->iat > ($timestamp + static::$leeway)) { - throw new BeforeValidException( - 'Cannot handle token prior to ' . \date(DateTime::ISO8601, $payload->iat) - ); - } - - // Check if this token has expired. - if (isset($payload->exp) && ($timestamp - static::$leeway) >= $payload->exp) { - throw new ExpiredException('Expired token'); - } - - return $payload; - } - - /** - * Converts and signs a PHP array into a JWT string. - * - * @param array<mixed> $payload PHP array - * @param string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate $key The secret key. - * @param string $alg Supported algorithms are 'ES384','ES256', 'ES256K', 'HS256', - * 'HS384', 'HS512', 'RS256', 'RS384', and 'RS512' - * @param string $keyId - * @param array<string, string> $head An array with header elements to attach - * - * @return string A signed JWT - * - * @uses jsonEncode - * @uses urlsafeB64Encode - */ - public static function encode( - array $payload, - $key, - string $alg, - string $keyId = null, - array $head = null - ): string { - $header = ['typ' => 'JWT', 'alg' => $alg]; - if ($keyId !== null) { - $header['kid'] = $keyId; - } - if (isset($head) && \is_array($head)) { - $header = \array_merge($head, $header); - } - $segments = []; - $segments[] = static::urlsafeB64Encode((string) static::jsonEncode($header)); - $segments[] = static::urlsafeB64Encode((string) static::jsonEncode($payload)); - $signing_input = \implode('.', $segments); - - $signature = static::sign($signing_input, $key, $alg); - $segments[] = static::urlsafeB64Encode($signature); - - return \implode('.', $segments); - } - - /** - * Sign a string with a given key and algorithm. - * - * @param string $msg The message to sign - * @param string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate $key The secret key. - * @param string $alg Supported algorithms are 'ES384','ES256', 'ES256K', 'HS256', - * 'HS384', 'HS512', 'RS256', 'RS384', and 'RS512' - * - * @return string An encrypted message - * - * @throws DomainException Unsupported algorithm or bad key was specified - */ - public static function sign( - string $msg, - $key, - string $alg - ): string { - if (empty(static::$supported_algs[$alg])) { - throw new DomainException('Algorithm not supported'); - } - list($function, $algorithm) = static::$supported_algs[$alg]; - switch ($function) { - case 'hash_hmac': - if (!\is_string($key)) { - throw new InvalidArgumentException('key must be a string when using hmac'); - } - return \hash_hmac($algorithm, $msg, $key, true); - case 'openssl': - $signature = ''; - $success = \openssl_sign($msg, $signature, $key, $algorithm); // @phpstan-ignore-line - if (!$success) { - throw new DomainException('OpenSSL unable to sign data'); - } - if ($alg === 'ES256' || $alg === 'ES256K') { - $signature = self::signatureFromDER($signature, 256); - } elseif ($alg === 'ES384') { - $signature = self::signatureFromDER($signature, 384); - } - return $signature; - case 'sodium_crypto': - if (!\function_exists('sodium_crypto_sign_detached')) { - throw new DomainException('libsodium is not available'); - } - if (!\is_string($key)) { - throw new InvalidArgumentException('key must be a string when using EdDSA'); - } - try { - // The last non-empty line is used as the key. - $lines = array_filter(explode("\n", $key)); - $key = base64_decode((string) end($lines)); - if (\strlen($key) === 0) { - throw new DomainException('Key cannot be empty string'); - } - return sodium_crypto_sign_detached($msg, $key); - } catch (Exception $e) { - throw new DomainException($e->getMessage(), 0, $e); - } - } - - throw new DomainException('Algorithm not supported'); - } - - /** - * Verify a signature with the message, key and method. Not all methods - * are symmetric, so we must have a separate verify and sign method. - * - * @param string $msg The original message (header and body) - * @param string $signature The original signature - * @param string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate $keyMaterial For HS*, a string key works. for RS*, must be an instance of OpenSSLAsymmetricKey - * @param string $alg The algorithm - * - * @return bool - * - * @throws DomainException Invalid Algorithm, bad key, or OpenSSL failure - */ - private static function verify( - string $msg, - string $signature, - $keyMaterial, - string $alg - ): bool { - if (empty(static::$supported_algs[$alg])) { - throw new DomainException('Algorithm not supported'); - } - - list($function, $algorithm) = static::$supported_algs[$alg]; - switch ($function) { - case 'openssl': - $success = \openssl_verify($msg, $signature, $keyMaterial, $algorithm); // @phpstan-ignore-line - if ($success === 1) { - return true; - } - if ($success === 0) { - return false; - } - // returns 1 on success, 0 on failure, -1 on error. - throw new DomainException( - 'OpenSSL error: ' . \openssl_error_string() - ); - case 'sodium_crypto': - if (!\function_exists('sodium_crypto_sign_verify_detached')) { - throw new DomainException('libsodium is not available'); - } - if (!\is_string($keyMaterial)) { - throw new InvalidArgumentException('key must be a string when using EdDSA'); - } - try { - // The last non-empty line is used as the key. - $lines = array_filter(explode("\n", $keyMaterial)); - $key = base64_decode((string) end($lines)); - if (\strlen($key) === 0) { - throw new DomainException('Key cannot be empty string'); - } - if (\strlen($signature) === 0) { - throw new DomainException('Signature cannot be empty string'); - } - return sodium_crypto_sign_verify_detached($signature, $msg, $key); - } catch (Exception $e) { - throw new DomainException($e->getMessage(), 0, $e); - } - case 'hash_hmac': - default: - if (!\is_string($keyMaterial)) { - throw new InvalidArgumentException('key must be a string when using hmac'); - } - $hash = \hash_hmac($algorithm, $msg, $keyMaterial, true); - return self::constantTimeEquals($hash, $signature); - } - } - - /** - * Decode a JSON string into a PHP object. - * - * @param string $input JSON string - * - * @return mixed The decoded JSON string - * - * @throws DomainException Provided string was invalid JSON - */ - public static function jsonDecode(string $input) - { - $obj = \json_decode($input, false, 512, JSON_BIGINT_AS_STRING); - - if ($errno = \json_last_error()) { - self::handleJsonError($errno); - } elseif ($obj === null && $input !== 'null') { - throw new DomainException('Null result with non-null input'); - } - return $obj; - } - - /** - * Encode a PHP array into a JSON string. - * - * @param array<mixed> $input A PHP array - * - * @return string JSON representation of the PHP array - * - * @throws DomainException Provided object could not be encoded to valid JSON - */ - public static function jsonEncode(array $input): string - { - if (PHP_VERSION_ID >= 50400) { - $json = \json_encode($input, \JSON_UNESCAPED_SLASHES); - } else { - // PHP 5.3 only - $json = \json_encode($input); - } - if ($errno = \json_last_error()) { - self::handleJsonError($errno); - } elseif ($json === 'null' && $input !== null) { - throw new DomainException('Null result with non-null input'); - } - if ($json === false) { - throw new DomainException('Provided object could not be encoded to valid JSON'); - } - return $json; - } - - /** - * Decode a string with URL-safe Base64. - * - * @param string $input A Base64 encoded string - * - * @return string A decoded string - * - * @throws InvalidArgumentException invalid base64 characters - */ - public static function urlsafeB64Decode(string $input): string - { - $remainder = \strlen($input) % 4; - if ($remainder) { - $padlen = 4 - $remainder; - $input .= \str_repeat('=', $padlen); - } - return \base64_decode(\strtr($input, '-_', '+/')); - } - - /** - * Encode a string with URL-safe Base64. - * - * @param string $input The string you want encoded - * - * @return string The base64 encode of what you passed in - */ - public static function urlsafeB64Encode(string $input): string - { - return \str_replace('=', '', \strtr(\base64_encode($input), '+/', '-_')); - } - - - /** - * Determine if an algorithm has been provided for each Key - * - * @param Key|ArrayAccess<string,Key>|array<string,Key> $keyOrKeyArray - * @param string|null $kid - * - * @throws UnexpectedValueException - * - * @return Key - */ - private static function getKey( - $keyOrKeyArray, - ?string $kid - ): Key { - if ($keyOrKeyArray instanceof Key) { - return $keyOrKeyArray; - } - - if (empty($kid)) { - throw new UnexpectedValueException('"kid" empty, unable to lookup correct key'); - } - - if ($keyOrKeyArray instanceof CachedKeySet) { - // Skip "isset" check, as this will automatically refresh if not set - return $keyOrKeyArray[$kid]; - } - - if (!isset($keyOrKeyArray[$kid])) { - throw new UnexpectedValueException('"kid" invalid, unable to lookup correct key'); - } - - return $keyOrKeyArray[$kid]; - } - - /** - * @param string $left The string of known length to compare against - * @param string $right The user-supplied string - * @return bool - */ - public static function constantTimeEquals(string $left, string $right): bool - { - if (\function_exists('hash_equals')) { - return \hash_equals($left, $right); - } - $len = \min(self::safeStrlen($left), self::safeStrlen($right)); - - $status = 0; - for ($i = 0; $i < $len; $i++) { - $status |= (\ord($left[$i]) ^ \ord($right[$i])); - } - $status |= (self::safeStrlen($left) ^ self::safeStrlen($right)); - - return ($status === 0); - } - - /** - * Helper method to create a JSON error. - * - * @param int $errno An error number from json_last_error() - * - * @throws DomainException - * - * @return void - */ - private static function handleJsonError(int $errno): void - { - $messages = [ - JSON_ERROR_DEPTH => 'Maximum stack depth exceeded', - JSON_ERROR_STATE_MISMATCH => 'Invalid or malformed JSON', - JSON_ERROR_CTRL_CHAR => 'Unexpected control character found', - JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON', - JSON_ERROR_UTF8 => 'Malformed UTF-8 characters' //PHP >= 5.3.3 - ]; - throw new DomainException( - isset($messages[$errno]) - ? $messages[$errno] - : 'Unknown JSON error: ' . $errno - ); - } - - /** - * Get the number of bytes in cryptographic strings. - * - * @param string $str - * - * @return int - */ - private static function safeStrlen(string $str): int - { - if (\function_exists('mb_strlen')) { - return \mb_strlen($str, '8bit'); - } - return \strlen($str); - } - - /** - * Convert an ECDSA signature to an ASN.1 DER sequence - * - * @param string $sig The ECDSA signature to convert - * @return string The encoded DER object - */ - private static function signatureToDER(string $sig): string - { - // Separate the signature into r-value and s-value - $length = max(1, (int) (\strlen($sig) / 2)); - list($r, $s) = \str_split($sig, $length); - - // Trim leading zeros - $r = \ltrim($r, "\x00"); - $s = \ltrim($s, "\x00"); - - // Convert r-value and s-value from unsigned big-endian integers to - // signed two's complement - if (\ord($r[0]) > 0x7f) { - $r = "\x00" . $r; - } - if (\ord($s[0]) > 0x7f) { - $s = "\x00" . $s; - } - - return self::encodeDER( - self::ASN1_SEQUENCE, - self::encodeDER(self::ASN1_INTEGER, $r) . - self::encodeDER(self::ASN1_INTEGER, $s) - ); - } - - /** - * Encodes a value into a DER object. - * - * @param int $type DER tag - * @param string $value the value to encode - * - * @return string the encoded object - */ - private static function encodeDER(int $type, string $value): string - { - $tag_header = 0; - if ($type === self::ASN1_SEQUENCE) { - $tag_header |= 0x20; - } - - // Type - $der = \chr($tag_header | $type); - - // Length - $der .= \chr(\strlen($value)); - - return $der . $value; - } - - /** - * Encodes signature from a DER object. - * - * @param string $der binary signature in DER format - * @param int $keySize the number of bits in the key - * - * @return string the signature - */ - private static function signatureFromDER(string $der, int $keySize): string - { - // OpenSSL returns the ECDSA signatures as a binary ASN.1 DER SEQUENCE - list($offset, $_) = self::readDER($der); - list($offset, $r) = self::readDER($der, $offset); - list($offset, $s) = self::readDER($der, $offset); - - // Convert r-value and s-value from signed two's compliment to unsigned - // big-endian integers - $r = \ltrim($r, "\x00"); - $s = \ltrim($s, "\x00"); - - // Pad out r and s so that they are $keySize bits long - $r = \str_pad($r, $keySize / 8, "\x00", STR_PAD_LEFT); - $s = \str_pad($s, $keySize / 8, "\x00", STR_PAD_LEFT); - - return $r . $s; - } - - /** - * Reads binary DER-encoded data and decodes into a single object - * - * @param string $der the binary data in DER format - * @param int $offset the offset of the data stream containing the object - * to decode - * - * @return array{int, string|null} the new offset and the decoded object - */ - private static function readDER(string $der, int $offset = 0): array - { - $pos = $offset; - $size = \strlen($der); - $constructed = (\ord($der[$pos]) >> 5) & 0x01; - $type = \ord($der[$pos++]) & 0x1f; - - // Length - $len = \ord($der[$pos++]); - if ($len & 0x80) { - $n = $len & 0x1f; - $len = 0; - while ($n-- && $pos < $size) { - $len = ($len << 8) | \ord($der[$pos++]); - } - } - - // Value - if ($type === self::ASN1_BIT_STRING) { - $pos++; // Skip the first contents octet (padding indicator) - $data = \substr($der, $pos, $len - 1); - $pos += $len - 1; - } elseif (!$constructed) { - $data = \substr($der, $pos, $len); - $pos += $len; - } else { - $data = null; - } - - return [$pos, $data]; - } -} diff --git a/lib/firebase/php-jwt/src/Key.php b/lib/firebase/php-jwt/src/Key.php deleted file mode 100644 index 00cf7f2ed..000000000 --- a/lib/firebase/php-jwt/src/Key.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -namespace Firebase\JWT; - -use InvalidArgumentException; -use OpenSSLAsymmetricKey; -use OpenSSLCertificate; -use TypeError; - -class Key -{ - /** @var string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate */ - private $keyMaterial; - /** @var string */ - private $algorithm; - - /** - * @param string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate $keyMaterial - * @param string $algorithm - */ - public function __construct( - $keyMaterial, - string $algorithm - ) { - if ( - !\is_string($keyMaterial) - && !$keyMaterial instanceof OpenSSLAsymmetricKey - && !$keyMaterial instanceof OpenSSLCertificate - && !\is_resource($keyMaterial) - ) { - throw new TypeError('Key material must be a string, resource, or OpenSSLAsymmetricKey'); - } - - if (empty($keyMaterial)) { - throw new InvalidArgumentException('Key material must not be empty'); - } - - if (empty($algorithm)) { - throw new InvalidArgumentException('Algorithm must not be empty'); - } - - // TODO: Remove in PHP 8.0 in favor of class constructor property promotion - $this->keyMaterial = $keyMaterial; - $this->algorithm = $algorithm; - } - - /** - * Return the algorithm valid for this key - * - * @return string - */ - public function getAlgorithm(): string - { - return $this->algorithm; - } - - /** - * @return string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate - */ - public function getKeyMaterial() - { - return $this->keyMaterial; - } -} diff --git a/lib/firebase/php-jwt/src/SignatureInvalidException.php b/lib/firebase/php-jwt/src/SignatureInvalidException.php deleted file mode 100644 index d35dee9f1..000000000 --- a/lib/firebase/php-jwt/src/SignatureInvalidException.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace Firebase\JWT; - -class SignatureInvalidException extends \UnexpectedValueException -{ -} diff --git a/lib/guzzlehttp/guzzle/CHANGELOG.md b/lib/guzzlehttp/guzzle/CHANGELOG.md deleted file mode 100644 index 1144eb763..000000000 --- a/lib/guzzlehttp/guzzle/CHANGELOG.md +++ /dev/null @@ -1,1609 +0,0 @@ -# Change Log - -Please refer to [UPGRADING](UPGRADING.md) guide for upgrading to a major version. - - -## 7.7.0 - 2023-05-21 - -### Added - -- Support `guzzlehttp/promises` v2 - - -## 7.6.1 - 2023-05-15 - -### Fixed - -- Fix `SetCookie::fromString` MaxAge deprecation warning and skip invalid MaxAge values - - -## 7.6.0 - 2023-05-14 - -### Added - -- Support for setting the minimum TLS version in a unified way -- Apply on request the version set in options parameters - - -## 7.5.2 - 2023-05-14 - -### Fixed - -- Fixed set cookie constructor validation -- Fixed handling of files with `'0'` body - -### Changed - -- Corrected docs and default connect timeout value to 300 seconds - - -## 7.5.1 - 2023-04-17 - -### Fixed - -- Fixed `NO_PROXY` settings so that setting the `proxy` option to `no` overrides the env variable - -### Changed - -- Adjusted `guzzlehttp/psr7` version constraint to `^1.9.1 || ^2.4.5` - - -## 7.5.0 - 2022-08-28 - -### Added - -- Support PHP 8.2 -- Add request to delay closure params - - -## 7.4.5 - 2022-06-20 - -### Fixed - -* Fix change in port should be considered a change in origin -* Fix `CURLOPT_HTTPAUTH` option not cleared on change of origin - - -## 7.4.4 - 2022-06-09 - -### Fixed - -* Fix failure to strip Authorization header on HTTP downgrade -* Fix failure to strip the Cookie header on change in host or HTTP downgrade - - -## 7.4.3 - 2022-05-25 - -### Fixed - -* Fix cross-domain cookie leakage - - -## 7.4.2 - 2022-03-20 - -### Fixed - -- Remove curl auth on cross-domain redirects to align with the Authorization HTTP header -- Reject non-HTTP schemes in StreamHandler -- Set a default ssl.peer_name context in StreamHandler to allow `force_ip_resolve` - - -## 7.4.1 - 2021-12-06 - -### Changed - -- Replaced implicit URI to string coercion [#2946](https://github.com/guzzle/guzzle/pull/2946) -- Allow `symfony/deprecation-contracts` version 3 [#2961](https://github.com/guzzle/guzzle/pull/2961) - -### Fixed - -- Only close curl handle if it's done [#2950](https://github.com/guzzle/guzzle/pull/2950) - - -## 7.4.0 - 2021-10-18 - -### Added - -- Support PHP 8.1 [#2929](https://github.com/guzzle/guzzle/pull/2929), [#2939](https://github.com/guzzle/guzzle/pull/2939) -- Support `psr/log` version 2 and 3 [#2943](https://github.com/guzzle/guzzle/pull/2943) - -### Fixed - -- Make sure we always call `restore_error_handler()` [#2915](https://github.com/guzzle/guzzle/pull/2915) -- Fix progress parameter type compatibility between the cURL and stream handlers [#2936](https://github.com/guzzle/guzzle/pull/2936) -- Throw `InvalidArgumentException` when an incorrect `headers` array is provided [#2916](https://github.com/guzzle/guzzle/pull/2916), [#2942](https://github.com/guzzle/guzzle/pull/2942) - -### Changed - -- Be more strict with types [#2914](https://github.com/guzzle/guzzle/pull/2914), [#2917](https://github.com/guzzle/guzzle/pull/2917), [#2919](https://github.com/guzzle/guzzle/pull/2919), [#2945](https://github.com/guzzle/guzzle/pull/2945) - - -## 7.3.0 - 2021-03-23 - -### Added - -- Support for DER and P12 certificates [#2413](https://github.com/guzzle/guzzle/pull/2413) -- Support the cURL (http://) scheme for StreamHandler proxies [#2850](https://github.com/guzzle/guzzle/pull/2850) -- Support for `guzzlehttp/psr7:^2.0` [#2878](https://github.com/guzzle/guzzle/pull/2878) - -### Fixed - -- Handle exceptions on invalid header consistently between PHP versions and handlers [#2872](https://github.com/guzzle/guzzle/pull/2872) - - -## 7.2.0 - 2020-10-10 - -### Added - -- Support for PHP 8 [#2712](https://github.com/guzzle/guzzle/pull/2712), [#2715](https://github.com/guzzle/guzzle/pull/2715), [#2789](https://github.com/guzzle/guzzle/pull/2789) -- Support passing a body summarizer to the http errors middleware [#2795](https://github.com/guzzle/guzzle/pull/2795) - -### Fixed - -- Handle exceptions during response creation [#2591](https://github.com/guzzle/guzzle/pull/2591) -- Fix CURLOPT_ENCODING not to be overwritten [#2595](https://github.com/guzzle/guzzle/pull/2595) -- Make sure the Request always has a body object [#2804](https://github.com/guzzle/guzzle/pull/2804) - -### Changed - -- The `TooManyRedirectsException` has a response [#2660](https://github.com/guzzle/guzzle/pull/2660) -- Avoid "functions" from dependencies [#2712](https://github.com/guzzle/guzzle/pull/2712) - -### Deprecated - -- Using environment variable GUZZLE_CURL_SELECT_TIMEOUT [#2786](https://github.com/guzzle/guzzle/pull/2786) - - -## 7.1.1 - 2020-09-30 - -### Fixed - -- Incorrect EOF detection for response body streams on Windows. - -### Changed - -- We dont connect curl `sink` on HEAD requests. -- Removed some PHP 5 workarounds - - -## 7.1.0 - 2020-09-22 - -### Added - -- `GuzzleHttp\MessageFormatterInterface` - -### Fixed - -- Fixed issue that caused cookies with no value not to be stored. -- On redirects, we allow all safe methods like GET, HEAD and OPTIONS. -- Fixed logging on empty responses. -- Make sure MessageFormatter::format returns string - -### Deprecated - -- All functions in `GuzzleHttp` has been deprecated. Use static methods on `Utils` instead. -- `ClientInterface::getConfig()` -- `Client::getConfig()` -- `Client::__call()` -- `Utils::defaultCaBundle()` -- `CurlFactory::LOW_CURL_VERSION_NUMBER` - - -## 7.0.1 - 2020-06-27 - -* Fix multiply defined functions fatal error [#2699](https://github.com/guzzle/guzzle/pull/2699) - - -## 7.0.0 - 2020-06-27 - -No changes since 7.0.0-rc1. - - -## 7.0.0-rc1 - 2020-06-15 - -### Changed - -* Use error level for logging errors in Middleware [#2629](https://github.com/guzzle/guzzle/pull/2629) -* Disabled IDN support by default and require ext-intl to use it [#2675](https://github.com/guzzle/guzzle/pull/2675) - - -## 7.0.0-beta2 - 2020-05-25 - -### Added - -* Using `Utils` class instead of functions in the `GuzzleHttp` namespace. [#2546](https://github.com/guzzle/guzzle/pull/2546) -* `ClientInterface::MAJOR_VERSION` [#2583](https://github.com/guzzle/guzzle/pull/2583) - -### Changed - -* Avoid the `getenv` function when unsafe [#2531](https://github.com/guzzle/guzzle/pull/2531) -* Added real client methods [#2529](https://github.com/guzzle/guzzle/pull/2529) -* Avoid functions due to global install conflicts [#2546](https://github.com/guzzle/guzzle/pull/2546) -* Use Symfony intl-idn polyfill [#2550](https://github.com/guzzle/guzzle/pull/2550) -* Adding methods for HTTP verbs like `Client::get()`, `Client::head()`, `Client::patch()` etc [#2529](https://github.com/guzzle/guzzle/pull/2529) -* `ConnectException` extends `TransferException` [#2541](https://github.com/guzzle/guzzle/pull/2541) -* Updated the default User Agent to "GuzzleHttp/7" [#2654](https://github.com/guzzle/guzzle/pull/2654) - -### Fixed - -* Various intl icu issues [#2626](https://github.com/guzzle/guzzle/pull/2626) - -### Removed - -* Pool option `pool_size` [#2528](https://github.com/guzzle/guzzle/pull/2528) - - -## 7.0.0-beta1 - 2019-12-30 - -The diff might look very big but 95% of Guzzle users will be able to upgrade without modification. -Please see [the upgrade document](UPGRADING.md) that describes all BC breaking changes. - -### Added - -* Implement PSR-18 and dropped PHP 5 support [#2421](https://github.com/guzzle/guzzle/pull/2421) [#2474](https://github.com/guzzle/guzzle/pull/2474) -* PHP 7 types [#2442](https://github.com/guzzle/guzzle/pull/2442) [#2449](https://github.com/guzzle/guzzle/pull/2449) [#2466](https://github.com/guzzle/guzzle/pull/2466) [#2497](https://github.com/guzzle/guzzle/pull/2497) [#2499](https://github.com/guzzle/guzzle/pull/2499) -* IDN support for redirects [2424](https://github.com/guzzle/guzzle/pull/2424) - -### Changed - -* Dont allow passing null as third argument to `BadResponseException::__construct()` [#2427](https://github.com/guzzle/guzzle/pull/2427) -* Use SAPI constant instead of method call [#2450](https://github.com/guzzle/guzzle/pull/2450) -* Use native function invocation [#2444](https://github.com/guzzle/guzzle/pull/2444) -* Better defaults for PHP installations with old ICU lib [2454](https://github.com/guzzle/guzzle/pull/2454) -* Added visibility to all constants [#2462](https://github.com/guzzle/guzzle/pull/2462) -* Dont allow passing `null` as URI to `Client::request()` and `Client::requestAsync()` [#2461](https://github.com/guzzle/guzzle/pull/2461) -* Widen the exception argument to throwable [#2495](https://github.com/guzzle/guzzle/pull/2495) - -### Fixed - -* Logging when Promise rejected with a string [#2311](https://github.com/guzzle/guzzle/pull/2311) - -### Removed - -* Class `SeekException` [#2162](https://github.com/guzzle/guzzle/pull/2162) -* `RequestException::getResponseBodySummary()` [#2425](https://github.com/guzzle/guzzle/pull/2425) -* `CookieJar::getCookieValue()` [#2433](https://github.com/guzzle/guzzle/pull/2433) -* `uri_template()` and `UriTemplate` [#2440](https://github.com/guzzle/guzzle/pull/2440) -* Request options `save_to` and `exceptions` [#2464](https://github.com/guzzle/guzzle/pull/2464) - - -## 6.5.2 - 2019-12-23 - -* idn_to_ascii() fix for old PHP versions [#2489](https://github.com/guzzle/guzzle/pull/2489) - - -## 6.5.1 - 2019-12-21 - -* Better defaults for PHP installations with old ICU lib [#2454](https://github.com/guzzle/guzzle/pull/2454) -* IDN support for redirects [#2424](https://github.com/guzzle/guzzle/pull/2424) - - -## 6.5.0 - 2019-12-07 - -* Improvement: Added support for reset internal queue in MockHandler. [#2143](https://github.com/guzzle/guzzle/pull/2143) -* Improvement: Added support to pass arbitrary options to `curl_multi_init`. [#2287](https://github.com/guzzle/guzzle/pull/2287) -* Fix: Gracefully handle passing `null` to the `header` option. [#2132](https://github.com/guzzle/guzzle/pull/2132) -* Fix: `RetryMiddleware` did not do exponential delay between retires due unit mismatch. [#2132](https://github.com/guzzle/guzzle/pull/2132) -* Fix: Prevent undefined offset when using array for ssl_key options. [#2348](https://github.com/guzzle/guzzle/pull/2348) -* Deprecated `ClientInterface::VERSION` - - -## 6.4.1 - 2019-10-23 - -* No `guzzle.phar` was created in 6.4.0 due expired API token. This release will fix that -* Added `parent::__construct()` to `FileCookieJar` and `SessionCookieJar` - - -## 6.4.0 - 2019-10-23 - -* Improvement: Improved error messages when using curl < 7.21.2 [#2108](https://github.com/guzzle/guzzle/pull/2108) -* Fix: Test if response is readable before returning a summary in `RequestException::getResponseBodySummary()` [#2081](https://github.com/guzzle/guzzle/pull/2081) -* Fix: Add support for GUZZLE_CURL_SELECT_TIMEOUT environment variable [#2161](https://github.com/guzzle/guzzle/pull/2161) -* Improvement: Added `GuzzleHttp\Exception\InvalidArgumentException` [#2163](https://github.com/guzzle/guzzle/pull/2163) -* Improvement: Added `GuzzleHttp\_current_time()` to use `hrtime()` if that function exists. [#2242](https://github.com/guzzle/guzzle/pull/2242) -* Improvement: Added curl's `appconnect_time` in `TransferStats` [#2284](https://github.com/guzzle/guzzle/pull/2284) -* Improvement: Make GuzzleException extend Throwable wherever it's available [#2273](https://github.com/guzzle/guzzle/pull/2273) -* Fix: Prevent concurrent writes to file when saving `CookieJar` [#2335](https://github.com/guzzle/guzzle/pull/2335) -* Improvement: Update `MockHandler` so we can test transfer time [#2362](https://github.com/guzzle/guzzle/pull/2362) - - -## 6.3.3 - 2018-04-22 - -* Fix: Default headers when decode_content is specified - - -## 6.3.2 - 2018-03-26 - -* Fix: Release process - - -## 6.3.1 - 2018-03-26 - -* Bug fix: Parsing 0 epoch expiry times in cookies [#2014](https://github.com/guzzle/guzzle/pull/2014) -* Improvement: Better ConnectException detection [#2012](https://github.com/guzzle/guzzle/pull/2012) -* Bug fix: Malformed domain that contains a "/" [#1999](https://github.com/guzzle/guzzle/pull/1999) -* Bug fix: Undefined offset when a cookie has no first key-value pair [#1998](https://github.com/guzzle/guzzle/pull/1998) -* Improvement: Support PHPUnit 6 [#1953](https://github.com/guzzle/guzzle/pull/1953) -* Bug fix: Support empty headers [#1915](https://github.com/guzzle/guzzle/pull/1915) -* Bug fix: Ignore case during header modifications [#1916](https://github.com/guzzle/guzzle/pull/1916) - -+ Minor code cleanups, documentation fixes and clarifications. - - -## 6.3.0 - 2017-06-22 - -* Feature: force IP resolution (ipv4 or ipv6) [#1608](https://github.com/guzzle/guzzle/pull/1608), [#1659](https://github.com/guzzle/guzzle/pull/1659) -* Improvement: Don't include summary in exception message when body is empty [#1621](https://github.com/guzzle/guzzle/pull/1621) -* Improvement: Handle `on_headers` option in MockHandler [#1580](https://github.com/guzzle/guzzle/pull/1580) -* Improvement: Added SUSE Linux CA path [#1609](https://github.com/guzzle/guzzle/issues/1609) -* Improvement: Use class reference for getting the name of the class instead of using hardcoded strings [#1641](https://github.com/guzzle/guzzle/pull/1641) -* Feature: Added `read_timeout` option [#1611](https://github.com/guzzle/guzzle/pull/1611) -* Bug fix: PHP 7.x fixes [#1685](https://github.com/guzzle/guzzle/pull/1685), [#1686](https://github.com/guzzle/guzzle/pull/1686), [#1811](https://github.com/guzzle/guzzle/pull/1811) -* Deprecation: BadResponseException instantiation without a response [#1642](https://github.com/guzzle/guzzle/pull/1642) -* Feature: Added NTLM auth [#1569](https://github.com/guzzle/guzzle/pull/1569) -* Feature: Track redirect HTTP status codes [#1711](https://github.com/guzzle/guzzle/pull/1711) -* Improvement: Check handler type during construction [#1745](https://github.com/guzzle/guzzle/pull/1745) -* Improvement: Always include the Content-Length if there's a body [#1721](https://github.com/guzzle/guzzle/pull/1721) -* Feature: Added convenience method to access a cookie by name [#1318](https://github.com/guzzle/guzzle/pull/1318) -* Bug fix: Fill `CURLOPT_CAPATH` and `CURLOPT_CAINFO` properly [#1684](https://github.com/guzzle/guzzle/pull/1684) -* Improvement: Use `\GuzzleHttp\Promise\rejection_for` function instead of object init [#1827](https://github.com/guzzle/guzzle/pull/1827) - -+ Minor code cleanups, documentation fixes and clarifications. - - -## 6.2.3 - 2017-02-28 - -* Fix deprecations with guzzle/psr7 version 1.4 - - -## 6.2.2 - 2016-10-08 - -* Allow to pass nullable Response to delay callable -* Only add scheme when host is present -* Fix drain case where content-length is the literal string zero -* Obfuscate in-URL credentials in exceptions - - -## 6.2.1 - 2016-07-18 - -* Address HTTP_PROXY security vulnerability, CVE-2016-5385: - https://httpoxy.org/ -* Fixing timeout bug with StreamHandler: - https://github.com/guzzle/guzzle/pull/1488 -* Only read up to `Content-Length` in PHP StreamHandler to avoid timeouts when - a server does not honor `Connection: close`. -* Ignore URI fragment when sending requests. - - -## 6.2.0 - 2016-03-21 - -* Feature: added `GuzzleHttp\json_encode` and `GuzzleHttp\json_decode`. - https://github.com/guzzle/guzzle/pull/1389 -* Bug fix: Fix sleep calculation when waiting for delayed requests. - https://github.com/guzzle/guzzle/pull/1324 -* Feature: More flexible history containers. - https://github.com/guzzle/guzzle/pull/1373 -* Bug fix: defer sink stream opening in StreamHandler. - https://github.com/guzzle/guzzle/pull/1377 -* Bug fix: do not attempt to escape cookie values. - https://github.com/guzzle/guzzle/pull/1406 -* Feature: report original content encoding and length on decoded responses. - https://github.com/guzzle/guzzle/pull/1409 -* Bug fix: rewind seekable request bodies before dispatching to cURL. - https://github.com/guzzle/guzzle/pull/1422 -* Bug fix: provide an empty string to `http_build_query` for HHVM workaround. - https://github.com/guzzle/guzzle/pull/1367 - - -## 6.1.1 - 2015-11-22 - -* Bug fix: Proxy::wrapSync() now correctly proxies to the appropriate handler - https://github.com/guzzle/guzzle/commit/911bcbc8b434adce64e223a6d1d14e9a8f63e4e4 -* Feature: HandlerStack is now more generic. - https://github.com/guzzle/guzzle/commit/f2102941331cda544745eedd97fc8fd46e1ee33e -* Bug fix: setting verify to false in the StreamHandler now disables peer - verification. https://github.com/guzzle/guzzle/issues/1256 -* Feature: Middleware now uses an exception factory, including more error - context. https://github.com/guzzle/guzzle/pull/1282 -* Feature: better support for disabled functions. - https://github.com/guzzle/guzzle/pull/1287 -* Bug fix: fixed regression where MockHandler was not using `sink`. - https://github.com/guzzle/guzzle/pull/1292 - - -## 6.1.0 - 2015-09-08 - -* Feature: Added the `on_stats` request option to provide access to transfer - statistics for requests. https://github.com/guzzle/guzzle/pull/1202 -* Feature: Added the ability to persist session cookies in CookieJars. - https://github.com/guzzle/guzzle/pull/1195 -* Feature: Some compatibility updates for Google APP Engine - https://github.com/guzzle/guzzle/pull/1216 -* Feature: Added support for NO_PROXY to prevent the use of a proxy based on - a simple set of rules. https://github.com/guzzle/guzzle/pull/1197 -* Feature: Cookies can now contain square brackets. - https://github.com/guzzle/guzzle/pull/1237 -* Bug fix: Now correctly parsing `=` inside of quotes in Cookies. - https://github.com/guzzle/guzzle/pull/1232 -* Bug fix: Cusotm cURL options now correctly override curl options of the - same name. https://github.com/guzzle/guzzle/pull/1221 -* Bug fix: Content-Type header is now added when using an explicitly provided - multipart body. https://github.com/guzzle/guzzle/pull/1218 -* Bug fix: Now ignoring Set-Cookie headers that have no name. -* Bug fix: Reason phrase is no longer cast to an int in some cases in the - cURL handler. https://github.com/guzzle/guzzle/pull/1187 -* Bug fix: Remove the Authorization header when redirecting if the Host - header changes. https://github.com/guzzle/guzzle/pull/1207 -* Bug fix: Cookie path matching fixes - https://github.com/guzzle/guzzle/issues/1129 -* Bug fix: Fixing the cURL `body_as_string` setting - https://github.com/guzzle/guzzle/pull/1201 -* Bug fix: quotes are no longer stripped when parsing cookies. - https://github.com/guzzle/guzzle/issues/1172 -* Bug fix: `form_params` and `query` now always uses the `&` separator. - https://github.com/guzzle/guzzle/pull/1163 -* Bug fix: Adding a Content-Length to PHP stream wrapper requests if not set. - https://github.com/guzzle/guzzle/pull/1189 - - -## 6.0.2 - 2015-07-04 - -* Fixed a memory leak in the curl handlers in which references to callbacks - were not being removed by `curl_reset`. -* Cookies are now extracted properly before redirects. -* Cookies now allow more character ranges. -* Decoded Content-Encoding responses are now modified to correctly reflect - their state if the encoding was automatically removed by a handler. This - means that the `Content-Encoding` header may be removed an the - `Content-Length` modified to reflect the message size after removing the - encoding. -* Added a more explicit error message when trying to use `form_params` and - `multipart` in the same request. -* Several fixes for HHVM support. -* Functions are now conditionally required using an additional level of - indirection to help with global Composer installations. - - -## 6.0.1 - 2015-05-27 - -* Fixed a bug with serializing the `query` request option where the `&` - separator was missing. -* Added a better error message for when `body` is provided as an array. Please - use `form_params` or `multipart` instead. -* Various doc fixes. - - -## 6.0.0 - 2015-05-26 - -* See the UPGRADING.md document for more information. -* Added `multipart` and `form_params` request options. -* Added `synchronous` request option. -* Added the `on_headers` request option. -* Fixed `expect` handling. -* No longer adding default middlewares in the client ctor. These need to be - present on the provided handler in order to work. -* Requests are no longer initiated when sending async requests with the - CurlMultiHandler. This prevents unexpected recursion from requests completing - while ticking the cURL loop. -* Removed the semantics of setting `default` to `true`. This is no longer - required now that the cURL loop is not ticked for async requests. -* Added request and response logging middleware. -* No longer allowing self signed certificates when using the StreamHandler. -* Ensuring that `sink` is valid if saving to a file. -* Request exceptions now include a "handler context" which provides handler - specific contextual information. -* Added `GuzzleHttp\RequestOptions` to allow request options to be applied - using constants. -* `$maxHandles` has been removed from CurlMultiHandler. -* `MultipartPostBody` is now part of the `guzzlehttp/psr7` package. - - -## 5.3.0 - 2015-05-19 - -* Mock now supports `save_to` -* Marked `AbstractRequestEvent::getTransaction()` as public. -* Fixed a bug in which multiple headers using different casing would overwrite - previous headers in the associative array. -* Added `Utils::getDefaultHandler()` -* Marked `GuzzleHttp\Client::getDefaultUserAgent` as deprecated. -* URL scheme is now always lowercased. - - -## 6.0.0-beta.1 - -* Requires PHP >= 5.5 -* Updated to use PSR-7 - * Requires immutable messages, which basically means an event based system - owned by a request instance is no longer possible. - * Utilizing the [Guzzle PSR-7 package](https://github.com/guzzle/psr7). - * Removed the dependency on `guzzlehttp/streams`. These stream abstractions - are available in the `guzzlehttp/psr7` package under the `GuzzleHttp\Psr7` - namespace. -* Added middleware and handler system - * Replaced the Guzzle event and subscriber system with a middleware system. - * No longer depends on RingPHP, but rather places the HTTP handlers directly - in Guzzle, operating on PSR-7 messages. - * Retry logic is now encapsulated in `GuzzleHttp\Middleware::retry`, which - means the `guzzlehttp/retry-subscriber` is now obsolete. - * Mocking responses is now handled using `GuzzleHttp\Handler\MockHandler`. -* Asynchronous responses - * No longer supports the `future` request option to send an async request. - Instead, use one of the `*Async` methods of a client (e.g., `requestAsync`, - `getAsync`, etc.). - * Utilizing `GuzzleHttp\Promise` instead of React's promise library to avoid - recursion required by chaining and forwarding react promises. See - https://github.com/guzzle/promises - * Added `requestAsync` and `sendAsync` to send request asynchronously. - * Added magic methods for `getAsync()`, `postAsync()`, etc. to send requests - asynchronously. -* Request options - * POST and form updates - * Added the `form_fields` and `form_files` request options. - * Removed the `GuzzleHttp\Post` namespace. - * The `body` request option no longer accepts an array for POST requests. - * The `exceptions` request option has been deprecated in favor of the - `http_errors` request options. - * The `save_to` request option has been deprecated in favor of `sink` request - option. -* Clients no longer accept an array of URI template string and variables for - URI variables. You will need to expand URI templates before passing them - into a client constructor or request method. -* Client methods `get()`, `post()`, `put()`, `patch()`, `options()`, etc. are - now magic methods that will send synchronous requests. -* Replaced `Utils.php` with plain functions in `functions.php`. -* Removed `GuzzleHttp\Collection`. -* Removed `GuzzleHttp\BatchResults`. Batched pool results are now returned as - an array. -* Removed `GuzzleHttp\Query`. Query string handling is now handled using an - associative array passed into the `query` request option. The query string - is serialized using PHP's `http_build_query`. If you need more control, you - can pass the query string in as a string. -* `GuzzleHttp\QueryParser` has been replaced with the - `GuzzleHttp\Psr7\parse_query`. - - -## 5.2.0 - 2015-01-27 - -* Added `AppliesHeadersInterface` to make applying headers to a request based - on the body more generic and not specific to `PostBodyInterface`. -* Reduced the number of stack frames needed to send requests. -* Nested futures are now resolved in the client rather than the RequestFsm -* Finishing state transitions is now handled in the RequestFsm rather than the - RingBridge. -* Added a guard in the Pool class to not use recursion for request retries. - - -## 5.1.0 - 2014-12-19 - -* Pool class no longer uses recursion when a request is intercepted. -* The size of a Pool can now be dynamically adjusted using a callback. - See https://github.com/guzzle/guzzle/pull/943. -* Setting a request option to `null` when creating a request with a client will - ensure that the option is not set. This allows you to overwrite default - request options on a per-request basis. - See https://github.com/guzzle/guzzle/pull/937. -* Added the ability to limit which protocols are allowed for redirects by - specifying a `protocols` array in the `allow_redirects` request option. -* Nested futures due to retries are now resolved when waiting for synchronous - responses. See https://github.com/guzzle/guzzle/pull/947. -* `"0"` is now an allowed URI path. See - https://github.com/guzzle/guzzle/pull/935. -* `Query` no longer typehints on the `$query` argument in the constructor, - allowing for strings and arrays. -* Exceptions thrown in the `end` event are now correctly wrapped with Guzzle - specific exceptions if necessary. - - -## 5.0.3 - 2014-11-03 - -This change updates query strings so that they are treated as un-encoded values -by default where the value represents an un-encoded value to send over the -wire. A Query object then encodes the value before sending over the wire. This -means that even value query string values (e.g., ":") are url encoded. This -makes the Query class match PHP's http_build_query function. However, if you -want to send requests over the wire using valid query string characters that do -not need to be encoded, then you can provide a string to Url::setQuery() and -pass true as the second argument to specify that the query string is a raw -string that should not be parsed or encoded (unless a call to getQuery() is -subsequently made, forcing the query-string to be converted into a Query -object). - - -## 5.0.2 - 2014-10-30 - -* Added a trailing `\r\n` to multipart/form-data payloads. See - https://github.com/guzzle/guzzle/pull/871 -* Added a `GuzzleHttp\Pool::send()` convenience method to match the docs. -* Status codes are now returned as integers. See - https://github.com/guzzle/guzzle/issues/881 -* No longer overwriting an existing `application/x-www-form-urlencoded` header - when sending POST requests, allowing for customized headers. See - https://github.com/guzzle/guzzle/issues/877 -* Improved path URL serialization. - - * No longer double percent-encoding characters in the path or query string if - they are already encoded. - * Now properly encoding the supplied path to a URL object, instead of only - encoding ' ' and '?'. - * Note: This has been changed in 5.0.3 to now encode query string values by - default unless the `rawString` argument is provided when setting the query - string on a URL: Now allowing many more characters to be present in the - query string without being percent encoded. See https://tools.ietf.org/html/rfc3986#appendix-A - - -## 5.0.1 - 2014-10-16 - -Bugfix release. - -* Fixed an issue where connection errors still returned response object in - error and end events event though the response is unusable. This has been - corrected so that a response is not returned in the `getResponse` method of - these events if the response did not complete. https://github.com/guzzle/guzzle/issues/867 -* Fixed an issue where transfer statistics were not being populated in the - RingBridge. https://github.com/guzzle/guzzle/issues/866 - - -## 5.0.0 - 2014-10-12 - -Adding support for non-blocking responses and some minor API cleanup. - -### New Features - -* Added support for non-blocking responses based on `guzzlehttp/guzzle-ring`. -* Added a public API for creating a default HTTP adapter. -* Updated the redirect plugin to be non-blocking so that redirects are sent - concurrently. Other plugins like this can now be updated to be non-blocking. -* Added a "progress" event so that you can get upload and download progress - events. -* Added `GuzzleHttp\Pool` which implements FutureInterface and transfers - requests concurrently using a capped pool size as efficiently as possible. -* Added `hasListeners()` to EmitterInterface. -* Removed `GuzzleHttp\ClientInterface::sendAll` and marked - `GuzzleHttp\Client::sendAll` as deprecated (it's still there, just not the - recommended way). - -### Breaking changes - -The breaking changes in this release are relatively minor. The biggest thing to -look out for is that request and response objects no longer implement fluent -interfaces. - -* Removed the fluent interfaces (i.e., `return $this`) from requests, - responses, `GuzzleHttp\Collection`, `GuzzleHttp\Url`, - `GuzzleHttp\Query`, `GuzzleHttp\Post\PostBody`, and - `GuzzleHttp\Cookie\SetCookie`. This blog post provides a good outline of - why I did this: https://ocramius.github.io/blog/fluent-interfaces-are-evil/. - This also makes the Guzzle message interfaces compatible with the current - PSR-7 message proposal. -* Removed "functions.php", so that Guzzle is truly PSR-4 compliant. Except - for the HTTP request functions from function.php, these functions are now - implemented in `GuzzleHttp\Utils` using camelCase. `GuzzleHttp\json_decode` - moved to `GuzzleHttp\Utils::jsonDecode`. `GuzzleHttp\get_path` moved to - `GuzzleHttp\Utils::getPath`. `GuzzleHttp\set_path` moved to - `GuzzleHttp\Utils::setPath`. `GuzzleHttp\batch` should now be - `GuzzleHttp\Pool::batch`, which returns an `objectStorage`. Using functions.php - caused problems for many users: they aren't PSR-4 compliant, require an - explicit include, and needed an if-guard to ensure that the functions are not - declared multiple times. -* Rewrote adapter layer. - * Removing all classes from `GuzzleHttp\Adapter`, these are now - implemented as callables that are stored in `GuzzleHttp\Ring\Client`. - * Removed the concept of "parallel adapters". Sending requests serially or - concurrently is now handled using a single adapter. - * Moved `GuzzleHttp\Adapter\Transaction` to `GuzzleHttp\Transaction`. The - Transaction object now exposes the request, response, and client as public - properties. The getters and setters have been removed. -* Removed the "headers" event. This event was only useful for changing the - body a response once the headers of the response were known. You can implement - a similar behavior in a number of ways. One example might be to use a - FnStream that has access to the transaction being sent. For example, when the - first byte is written, you could check if the response headers match your - expectations, and if so, change the actual stream body that is being - written to. -* Removed the `asArray` parameter from - `GuzzleHttp\Message\MessageInterface::getHeader`. If you want to get a header - value as an array, then use the newly added `getHeaderAsArray()` method of - `MessageInterface`. This change makes the Guzzle interfaces compatible with - the PSR-7 interfaces. -* `GuzzleHttp\Message\MessageFactory` no longer allows subclasses to add - custom request options using double-dispatch (this was an implementation - detail). Instead, you should now provide an associative array to the - constructor which is a mapping of the request option name mapping to a - function that applies the option value to a request. -* Removed the concept of "throwImmediately" from exceptions and error events. - This control mechanism was used to stop a transfer of concurrent requests - from completing. This can now be handled by throwing the exception or by - cancelling a pool of requests or each outstanding future request individually. -* Updated to "GuzzleHttp\Streams" 3.0. - * `GuzzleHttp\Stream\StreamInterface::getContents()` no longer accepts a - `maxLen` parameter. This update makes the Guzzle streams project - compatible with the current PSR-7 proposal. - * `GuzzleHttp\Stream\Stream::__construct`, - `GuzzleHttp\Stream\Stream::factory`, and - `GuzzleHttp\Stream\Utils::create` no longer accept a size in the second - argument. They now accept an associative array of options, including the - "size" key and "metadata" key which can be used to provide custom metadata. - - -## 4.2.2 - 2014-09-08 - -* Fixed a memory leak in the CurlAdapter when reusing cURL handles. -* No longer using `request_fulluri` in stream adapter proxies. -* Relative redirects are now based on the last response, not the first response. - -## 4.2.1 - 2014-08-19 - -* Ensuring that the StreamAdapter does not always add a Content-Type header -* Adding automated github releases with a phar and zip - -## 4.2.0 - 2014-08-17 - -* Now merging in default options using a case-insensitive comparison. - Closes https://github.com/guzzle/guzzle/issues/767 -* Added the ability to automatically decode `Content-Encoding` response bodies - using the `decode_content` request option. This is set to `true` by default - to decode the response body if it comes over the wire with a - `Content-Encoding`. Set this value to `false` to disable decoding the - response content, and pass a string to provide a request `Accept-Encoding` - header and turn on automatic response decoding. This feature now allows you - to pass an `Accept-Encoding` header in the headers of a request but still - disable automatic response decoding. - Closes https://github.com/guzzle/guzzle/issues/764 -* Added the ability to throw an exception immediately when transferring - requests in parallel. Closes https://github.com/guzzle/guzzle/issues/760 -* Updating guzzlehttp/streams dependency to ~2.1 -* No longer utilizing the now deprecated namespaced methods from the stream - package. - -## 4.1.8 - 2014-08-14 - -* Fixed an issue in the CurlFactory that caused setting the `stream=false` - request option to throw an exception. - See: https://github.com/guzzle/guzzle/issues/769 -* TransactionIterator now calls rewind on the inner iterator. - See: https://github.com/guzzle/guzzle/pull/765 -* You can now set the `Content-Type` header to `multipart/form-data` - when creating POST requests to force multipart bodies. - See https://github.com/guzzle/guzzle/issues/768 - -## 4.1.7 - 2014-08-07 - -* Fixed an error in the HistoryPlugin that caused the same request and response - to be logged multiple times when an HTTP protocol error occurs. -* Ensuring that cURL does not add a default Content-Type when no Content-Type - has been supplied by the user. This prevents the adapter layer from modifying - the request that is sent over the wire after any listeners may have already - put the request in a desired state (e.g., signed the request). -* Throwing an exception when you attempt to send requests that have the - "stream" set to true in parallel using the MultiAdapter. -* Only calling curl_multi_select when there are active cURL handles. This was - previously changed and caused performance problems on some systems due to PHP - always selecting until the maximum select timeout. -* Fixed a bug where multipart/form-data POST fields were not correctly - aggregated (e.g., values with "&"). - -## 4.1.6 - 2014-08-03 - -* Added helper methods to make it easier to represent messages as strings, - including getting the start line and getting headers as a string. - -## 4.1.5 - 2014-08-02 - -* Automatically retrying cURL "Connection died, retrying a fresh connect" - errors when possible. -* cURL implementation cleanup -* Allowing multiple event subscriber listeners to be registered per event by - passing an array of arrays of listener configuration. - -## 4.1.4 - 2014-07-22 - -* Fixed a bug that caused multi-part POST requests with more than one field to - serialize incorrectly. -* Paths can now be set to "0" -* `ResponseInterface::xml` now accepts a `libxml_options` option and added a - missing default argument that was required when parsing XML response bodies. -* A `save_to` stream is now created lazily, which means that files are not - created on disk unless a request succeeds. - -## 4.1.3 - 2014-07-15 - -* Various fixes to multipart/form-data POST uploads -* Wrapping function.php in an if-statement to ensure Guzzle can be used - globally and in a Composer install -* Fixed an issue with generating and merging in events to an event array -* POST headers are only applied before sending a request to allow you to change - the query aggregator used before uploading -* Added much more robust query string parsing -* Fixed various parsing and normalization issues with URLs -* Fixing an issue where multi-valued headers were not being utilized correctly - in the StreamAdapter - -## 4.1.2 - 2014-06-18 - -* Added support for sending payloads with GET requests - -## 4.1.1 - 2014-06-08 - -* Fixed an issue related to using custom message factory options in subclasses -* Fixed an issue with nested form fields in a multi-part POST -* Fixed an issue with using the `json` request option for POST requests -* Added `ToArrayInterface` to `GuzzleHttp\Cookie\CookieJar` - -## 4.1.0 - 2014-05-27 - -* Added a `json` request option to easily serialize JSON payloads. -* Added a `GuzzleHttp\json_decode()` wrapper to safely parse JSON. -* Added `setPort()` and `getPort()` to `GuzzleHttp\Message\RequestInterface`. -* Added the ability to provide an emitter to a client in the client constructor. -* Added the ability to persist a cookie session using $_SESSION. -* Added a trait that can be used to add event listeners to an iterator. -* Removed request method constants from RequestInterface. -* Fixed warning when invalid request start-lines are received. -* Updated MessageFactory to work with custom request option methods. -* Updated cacert bundle to latest build. - -4.0.2 (2014-04-16) ------------------- - -* Proxy requests using the StreamAdapter now properly use request_fulluri (#632) -* Added the ability to set scalars as POST fields (#628) - -## 4.0.1 - 2014-04-04 - -* The HTTP status code of a response is now set as the exception code of - RequestException objects. -* 303 redirects will now correctly switch from POST to GET requests. -* The default parallel adapter of a client now correctly uses the MultiAdapter. -* HasDataTrait now initializes the internal data array as an empty array so - that the toArray() method always returns an array. - -## 4.0.0 - 2014-03-29 - -* For information on changes and upgrading, see: - https://github.com/guzzle/guzzle/blob/master/UPGRADING.md#3x-to-40 -* Added `GuzzleHttp\batch()` as a convenience function for sending requests in - parallel without needing to write asynchronous code. -* Restructured how events are added to `GuzzleHttp\ClientInterface::sendAll()`. - You can now pass a callable or an array of associative arrays where each - associative array contains the "fn", "priority", and "once" keys. - -## 4.0.0.rc-2 - 2014-03-25 - -* Removed `getConfig()` and `setConfig()` from clients to avoid confusion - around whether things like base_url, message_factory, etc. should be able to - be retrieved or modified. -* Added `getDefaultOption()` and `setDefaultOption()` to ClientInterface -* functions.php functions were renamed using snake_case to match PHP idioms -* Added support for `HTTP_PROXY`, `HTTPS_PROXY`, and - `GUZZLE_CURL_SELECT_TIMEOUT` environment variables -* Added the ability to specify custom `sendAll()` event priorities -* Added the ability to specify custom stream context options to the stream - adapter. -* Added a functions.php function for `get_path()` and `set_path()` -* CurlAdapter and MultiAdapter now use a callable to generate curl resources -* MockAdapter now properly reads a body and emits a `headers` event -* Updated Url class to check if a scheme and host are set before adding ":" - and "//". This allows empty Url (e.g., "") to be serialized as "". -* Parsing invalid XML no longer emits warnings -* Curl classes now properly throw AdapterExceptions -* Various performance optimizations -* Streams are created with the faster `Stream\create()` function -* Marked deprecation_proxy() as internal -* Test server is now a collection of static methods on a class - -## 4.0.0-rc.1 - 2014-03-15 - -* See https://github.com/guzzle/guzzle/blob/master/UPGRADING.md#3x-to-40 - -## 3.8.1 - 2014-01-28 - -* Bug: Always using GET requests when redirecting from a 303 response -* Bug: CURLOPT_SSL_VERIFYHOST is now correctly set to false when setting `$certificateAuthority` to false in - `Guzzle\Http\ClientInterface::setSslVerification()` -* Bug: RedirectPlugin now uses strict RFC 3986 compliance when combining a base URL with a relative URL -* Bug: The body of a request can now be set to `"0"` -* Sending PHP stream requests no longer forces `HTTP/1.0` -* Adding more information to ExceptionCollection exceptions so that users have more context, including a stack trace of - each sub-exception -* Updated the `$ref` attribute in service descriptions to merge over any existing parameters of a schema (rather than - clobbering everything). -* Merging URLs will now use the query string object from the relative URL (thus allowing custom query aggregators) -* Query strings are now parsed in a way that they do no convert empty keys with no value to have a dangling `=`. - For example `foo&bar=baz` is now correctly parsed and recognized as `foo&bar=baz` rather than `foo=&bar=baz`. -* Now properly escaping the regular expression delimiter when matching Cookie domains. -* Network access is now disabled when loading XML documents - -## 3.8.0 - 2013-12-05 - -* Added the ability to define a POST name for a file -* JSON response parsing now properly walks additionalProperties -* cURL error code 18 is now retried automatically in the BackoffPlugin -* Fixed a cURL error when URLs contain fragments -* Fixed an issue in the BackoffPlugin retry event where it was trying to access all exceptions as if they were - CurlExceptions -* CURLOPT_PROGRESS function fix for PHP 5.5 (69fcc1e) -* Added the ability for Guzzle to work with older versions of cURL that do not support `CURLOPT_TIMEOUT_MS` -* Fixed a bug that was encountered when parsing empty header parameters -* UriTemplate now has a `setRegex()` method to match the docs -* The `debug` request parameter now checks if it is truthy rather than if it exists -* Setting the `debug` request parameter to true shows verbose cURL output instead of using the LogPlugin -* Added the ability to combine URLs using strict RFC 3986 compliance -* Command objects can now return the validation errors encountered by the command -* Various fixes to cache revalidation (#437 and 29797e5) -* Various fixes to the AsyncPlugin -* Cleaned up build scripts - -## 3.7.4 - 2013-10-02 - -* Bug fix: 0 is now an allowed value in a description parameter that has a default value (#430) -* Bug fix: SchemaFormatter now returns an integer when formatting to a Unix timestamp - (see https://github.com/aws/aws-sdk-php/issues/147) -* Bug fix: Cleaned up and fixed URL dot segment removal to properly resolve internal dots -* Minimum PHP version is now properly specified as 5.3.3 (up from 5.3.2) (#420) -* Updated the bundled cacert.pem (#419) -* OauthPlugin now supports adding authentication to headers or query string (#425) - -## 3.7.3 - 2013-09-08 - -* Added the ability to get the exception associated with a request/command when using `MultiTransferException` and - `CommandTransferException`. -* Setting `additionalParameters` of a response to false is now honored when parsing responses with a service description -* Schemas are only injected into response models when explicitly configured. -* No longer guessing Content-Type based on the path of a request. Content-Type is now only guessed based on the path of - an EntityBody. -* Bug fix: ChunkedIterator can now properly chunk a \Traversable as well as an \Iterator. -* Bug fix: FilterIterator now relies on `\Iterator` instead of `\Traversable`. -* Bug fix: Gracefully handling malformed responses in RequestMediator::writeResponseBody() -* Bug fix: Replaced call to canCache with canCacheRequest in the CallbackCanCacheStrategy of the CachePlugin -* Bug fix: Visiting XML attributes first before visiting XML children when serializing requests -* Bug fix: Properly parsing headers that contain commas contained in quotes -* Bug fix: mimetype guessing based on a filename is now case-insensitive - -## 3.7.2 - 2013-08-02 - -* Bug fix: Properly URL encoding paths when using the PHP-only version of the UriTemplate expander - See https://github.com/guzzle/guzzle/issues/371 -* Bug fix: Cookie domains are now matched correctly according to RFC 6265 - See https://github.com/guzzle/guzzle/issues/377 -* Bug fix: GET parameters are now used when calculating an OAuth signature -* Bug fix: Fixed an issue with cache revalidation where the If-None-Match header was being double quoted -* `Guzzle\Common\AbstractHasDispatcher::dispatch()` now returns the event that was dispatched -* `Guzzle\Http\QueryString::factory()` now guesses the most appropriate query aggregator to used based on the input. - See https://github.com/guzzle/guzzle/issues/379 -* Added a way to add custom domain objects to service description parsing using the `operation.parse_class` event. See - https://github.com/guzzle/guzzle/pull/380 -* cURL multi cleanup and optimizations - -## 3.7.1 - 2013-07-05 - -* Bug fix: Setting default options on a client now works -* Bug fix: Setting options on HEAD requests now works. See #352 -* Bug fix: Moving stream factory before send event to before building the stream. See #353 -* Bug fix: Cookies no longer match on IP addresses per RFC 6265 -* Bug fix: Correctly parsing header parameters that are in `<>` and quotes -* Added `cert` and `ssl_key` as request options -* `Host` header can now diverge from the host part of a URL if the header is set manually -* `Guzzle\Service\Command\LocationVisitor\Request\XmlVisitor` was rewritten to change from using SimpleXML to XMLWriter -* OAuth parameters are only added via the plugin if they aren't already set -* Exceptions are now thrown when a URL cannot be parsed -* Returning `false` if `Guzzle\Http\EntityBody::getContentMd5()` fails -* Not setting a `Content-MD5` on a command if calculating the Content-MD5 fails via the CommandContentMd5Plugin - -## 3.7.0 - 2013-06-10 - -* See UPGRADING.md for more information on how to upgrade. -* Requests now support the ability to specify an array of $options when creating a request to more easily modify a - request. You can pass a 'request.options' configuration setting to a client to apply default request options to - every request created by a client (e.g. default query string variables, headers, curl options, etc.). -* Added a static facade class that allows you to use Guzzle with static methods and mount the class to `\Guzzle`. - See `Guzzle\Http\StaticClient::mount`. -* Added `command.request_options` to `Guzzle\Service\Command\AbstractCommand` to pass request options to requests - created by a command (e.g. custom headers, query string variables, timeout settings, etc.). -* Stream size in `Guzzle\Stream\PhpStreamRequestFactory` will now be set if Content-Length is returned in the - headers of a response -* Added `Guzzle\Common\Collection::setPath($path, $value)` to set a value into an array using a nested key - (e.g. `$collection->setPath('foo/baz/bar', 'test'); echo $collection['foo']['bar']['bar'];`) -* ServiceBuilders now support storing and retrieving arbitrary data -* CachePlugin can now purge all resources for a given URI -* CachePlugin can automatically purge matching cached items when a non-idempotent request is sent to a resource -* CachePlugin now uses the Vary header to determine if a resource is a cache hit -* `Guzzle\Http\Message\Response` now implements `\Serializable` -* Added `Guzzle\Cache\CacheAdapterFactory::fromCache()` to more easily create cache adapters -* `Guzzle\Service\ClientInterface::execute()` now accepts an array, single command, or Traversable -* Fixed a bug in `Guzzle\Http\Message\Header\Link::addLink()` -* Better handling of calculating the size of a stream in `Guzzle\Stream\Stream` using fstat() and caching the size -* `Guzzle\Common\Exception\ExceptionCollection` now creates a more readable exception message -* Fixing BC break: Added back the MonologLogAdapter implementation rather than extending from PsrLog so that older - Symfony users can still use the old version of Monolog. -* Fixing BC break: Added the implementation back in for `Guzzle\Http\Message\AbstractMessage::getTokenizedHeader()`. - Now triggering an E_USER_DEPRECATED warning when used. Use `$message->getHeader()->parseParams()`. -* Several performance improvements to `Guzzle\Common\Collection` -* Added an `$options` argument to the end of the following methods of `Guzzle\Http\ClientInterface`: - createRequest, head, delete, put, patch, post, options, prepareRequest -* Added an `$options` argument to the end of `Guzzle\Http\Message\Request\RequestFactoryInterface::createRequest()` -* Added an `applyOptions()` method to `Guzzle\Http\Message\Request\RequestFactoryInterface` -* Changed `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $body = null)` to - `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $options = array())`. You can still pass in a - resource, string, or EntityBody into the $options parameter to specify the download location of the response. -* Changed `Guzzle\Common\Collection::__construct($data)` to no longer accepts a null value for `$data` but a - default `array()` -* Added `Guzzle\Stream\StreamInterface::isRepeatable` -* Removed `Guzzle\Http\ClientInterface::setDefaultHeaders(). Use - $client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`. or - $client->getConfig()->setPath('request.options/headers', array('header_name' => 'value'))`. -* Removed `Guzzle\Http\ClientInterface::getDefaultHeaders(). Use $client->getConfig()->getPath('request.options/headers')`. -* Removed `Guzzle\Http\ClientInterface::expandTemplate()` -* Removed `Guzzle\Http\ClientInterface::setRequestFactory()` -* Removed `Guzzle\Http\ClientInterface::getCurlMulti()` -* Removed `Guzzle\Http\Message\RequestInterface::canCache` -* Removed `Guzzle\Http\Message\RequestInterface::setIsRedirect` -* Removed `Guzzle\Http\Message\RequestInterface::isRedirect` -* Made `Guzzle\Http\Client::expandTemplate` and `getUriTemplate` protected methods. -* You can now enable E_USER_DEPRECATED warnings to see if you are using a deprecated method by setting - `Guzzle\Common\Version::$emitWarnings` to true. -* Marked `Guzzle\Http\Message\Request::isResponseBodyRepeatable()` as deprecated. Use - `$request->getResponseBody()->isRepeatable()` instead. -* Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use - `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead. -* Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use - `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead. -* Marked `Guzzle\Http\Message\Request::setIsRedirect()` as deprecated. Use the HistoryPlugin instead. -* Marked `Guzzle\Http\Message\Request::isRedirect()` as deprecated. Use the HistoryPlugin instead. -* Marked `Guzzle\Cache\CacheAdapterFactory::factory()` as deprecated -* Marked 'command.headers', 'command.response_body' and 'command.on_complete' as deprecated for AbstractCommand. - These will work through Guzzle 4.0 -* Marked 'request.params' for `Guzzle\Http\Client` as deprecated. Use [request.options][params]. -* Marked `Guzzle\Service\Client::enableMagicMethods()` as deprecated. Magic methods can no longer be disabled on a Guzzle\Service\Client. -* Marked `Guzzle\Service\Client::getDefaultHeaders()` as deprecated. Use $client->getConfig()->getPath('request.options/headers')`. -* Marked `Guzzle\Service\Client::setDefaultHeaders()` as deprecated. Use $client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`. -* Marked `Guzzle\Parser\Url\UrlParser` as deprecated. Just use PHP's `parse_url()` and percent encode your UTF-8. -* Marked `Guzzle\Common\Collection::inject()` as deprecated. -* Marked `Guzzle\Plugin\CurlAuth\CurlAuthPlugin` as deprecated. Use `$client->getConfig()->setPath('request.options/auth', array('user', 'pass', 'Basic|Digest');` -* CacheKeyProviderInterface and DefaultCacheKeyProvider are no longer used. All of this logic is handled in a - CacheStorageInterface. These two objects and interface will be removed in a future version. -* Always setting X-cache headers on cached responses -* Default cache TTLs are now handled by the CacheStorageInterface of a CachePlugin -* `CacheStorageInterface::cache($key, Response $response, $ttl = null)` has changed to `cache(RequestInterface - $request, Response $response);` -* `CacheStorageInterface::fetch($key)` has changed to `fetch(RequestInterface $request);` -* `CacheStorageInterface::delete($key)` has changed to `delete(RequestInterface $request);` -* Added `CacheStorageInterface::purge($url)` -* `DefaultRevalidation::__construct(CacheKeyProviderInterface $cacheKey, CacheStorageInterface $cache, CachePlugin - $plugin)` has changed to `DefaultRevalidation::__construct(CacheStorageInterface $cache, - CanCacheStrategyInterface $canCache = null)` -* Added `RevalidationInterface::shouldRevalidate(RequestInterface $request, Response $response)` - -## 3.6.0 - 2013-05-29 - -* ServiceDescription now implements ToArrayInterface -* Added command.hidden_params to blacklist certain headers from being treated as additionalParameters -* Guzzle can now correctly parse incomplete URLs -* Mixed casing of headers are now forced to be a single consistent casing across all values for that header. -* Messages internally use a HeaderCollection object to delegate handling case-insensitive header resolution -* Removed the whole changedHeader() function system of messages because all header changes now go through addHeader(). -* Specific header implementations can be created for complex headers. When a message creates a header, it uses a - HeaderFactory which can map specific headers to specific header classes. There is now a Link header and - CacheControl header implementation. -* Removed from interface: Guzzle\Http\ClientInterface::setUriTemplate -* Removed from interface: Guzzle\Http\ClientInterface::setCurlMulti() -* Removed Guzzle\Http\Message\Request::receivedRequestHeader() and implemented this functionality in - Guzzle\Http\Curl\RequestMediator -* Removed the optional $asString parameter from MessageInterface::getHeader(). Just cast the header to a string. -* Removed the optional $tryChunkedTransfer option from Guzzle\Http\Message\EntityEnclosingRequestInterface -* Removed the $asObjects argument from Guzzle\Http\Message\MessageInterface::getHeaders() -* Removed Guzzle\Parser\ParserRegister::get(). Use getParser() -* Removed Guzzle\Parser\ParserRegister::set(). Use registerParser(). -* All response header helper functions return a string rather than mixing Header objects and strings inconsistently -* Removed cURL blacklist support. This is no longer necessary now that Expect, Accept, etc. are managed by Guzzle - directly via interfaces -* Removed the injecting of a request object onto a response object. The methods to get and set a request still exist - but are a no-op until removed. -* Most classes that used to require a `Guzzle\Service\Command\CommandInterface` typehint now request a - `Guzzle\Service\Command\ArrayCommandInterface`. -* Added `Guzzle\Http\Message\RequestInterface::startResponse()` to the RequestInterface to handle injecting a response - on a request while the request is still being transferred -* The ability to case-insensitively search for header values -* Guzzle\Http\Message\Header::hasExactHeader -* Guzzle\Http\Message\Header::raw. Use getAll() -* Deprecated cache control specific methods on Guzzle\Http\Message\AbstractMessage. Use the CacheControl header object - instead. -* `Guzzle\Service\Command\CommandInterface` now extends from ToArrayInterface and ArrayAccess -* Added the ability to cast Model objects to a string to view debug information. - -## 3.5.0 - 2013-05-13 - -* Bug: Fixed a regression so that request responses are parsed only once per oncomplete event rather than multiple times -* Bug: Better cleanup of one-time events across the board (when an event is meant to fire once, it will now remove - itself from the EventDispatcher) -* Bug: `Guzzle\Log\MessageFormatter` now properly writes "total_time" and "connect_time" values -* Bug: Cloning an EntityEnclosingRequest now clones the EntityBody too -* Bug: Fixed an undefined index error when parsing nested JSON responses with a sentAs parameter that reference a - non-existent key -* Bug: All __call() method arguments are now required (helps with mocking frameworks) -* Deprecating Response::getRequest() and now using a shallow clone of a request object to remove a circular reference - to help with refcount based garbage collection of resources created by sending a request -* Deprecating ZF1 cache and log adapters. These will be removed in the next major version. -* Deprecating `Response::getPreviousResponse()` (method signature still exists, but it's deprecated). Use the - HistoryPlugin for a history. -* Added a `responseBody` alias for the `response_body` location -* Refactored internals to no longer rely on Response::getRequest() -* HistoryPlugin can now be cast to a string -* HistoryPlugin now logs transactions rather than requests and responses to more accurately keep track of the requests - and responses that are sent over the wire -* Added `getEffectiveUrl()` and `getRedirectCount()` to Response objects - -## 3.4.3 - 2013-04-30 - -* Bug fix: Fixing bug introduced in 3.4.2 where redirect responses are duplicated on the final redirected response -* Added a check to re-extract the temp cacert bundle from the phar before sending each request - -## 3.4.2 - 2013-04-29 - -* Bug fix: Stream objects now work correctly with "a" and "a+" modes -* Bug fix: Removing `Transfer-Encoding: chunked` header when a Content-Length is present -* Bug fix: AsyncPlugin no longer forces HEAD requests -* Bug fix: DateTime timezones are now properly handled when using the service description schema formatter -* Bug fix: CachePlugin now properly handles stale-if-error directives when a request to the origin server fails -* Setting a response on a request will write to the custom request body from the response body if one is specified -* LogPlugin now writes to php://output when STDERR is undefined -* Added the ability to set multiple POST files for the same key in a single call -* application/x-www-form-urlencoded POSTs now use the utf-8 charset by default -* Added the ability to queue CurlExceptions to the MockPlugin -* Cleaned up how manual responses are queued on requests (removed "queued_response" and now using request.before_send) -* Configuration loading now allows remote files - -## 3.4.1 - 2013-04-16 - -* Large refactoring to how CurlMulti handles work. There is now a proxy that sits in front of a pool of CurlMulti - handles. This greatly simplifies the implementation, fixes a couple bugs, and provides a small performance boost. -* Exceptions are now properly grouped when sending requests in parallel -* Redirects are now properly aggregated when a multi transaction fails -* Redirects now set the response on the original object even in the event of a failure -* Bug fix: Model names are now properly set even when using $refs -* Added support for PHP 5.5's CurlFile to prevent warnings with the deprecated @ syntax -* Added support for oauth_callback in OAuth signatures -* Added support for oauth_verifier in OAuth signatures -* Added support to attempt to retrieve a command first literally, then ucfirst, the with inflection - -## 3.4.0 - 2013-04-11 - -* Bug fix: URLs are now resolved correctly based on https://tools.ietf.org/html/rfc3986#section-5.2. #289 -* Bug fix: Absolute URLs with a path in a service description will now properly override the base URL. #289 -* Bug fix: Parsing a query string with a single PHP array value will now result in an array. #263 -* Bug fix: Better normalization of the User-Agent header to prevent duplicate headers. #264. -* Bug fix: Added `number` type to service descriptions. -* Bug fix: empty parameters are removed from an OAuth signature -* Bug fix: Revalidating a cache entry prefers the Last-Modified over the Date header -* Bug fix: Fixed "array to string" error when validating a union of types in a service description -* Bug fix: Removed code that attempted to determine the size of a stream when data is written to the stream -* Bug fix: Not including an `oauth_token` if the value is null in the OauthPlugin. -* Bug fix: Now correctly aggregating successful requests and failed requests in CurlMulti when a redirect occurs. -* The new default CURLOPT_TIMEOUT setting has been increased to 150 seconds so that Guzzle works on poor connections. -* Added a feature to EntityEnclosingRequest::setBody() that will automatically set the Content-Type of the request if - the Content-Type can be determined based on the entity body or the path of the request. -* Added the ability to overwrite configuration settings in a client when grabbing a throwaway client from a builder. -* Added support for a PSR-3 LogAdapter. -* Added a `command.after_prepare` event -* Added `oauth_callback` parameter to the OauthPlugin -* Added the ability to create a custom stream class when using a stream factory -* Added a CachingEntityBody decorator -* Added support for `additionalParameters` in service descriptions to define how custom parameters are serialized. -* The bundled SSL certificate is now provided in the phar file and extracted when running Guzzle from a phar. -* You can now send any EntityEnclosingRequest with POST fields or POST files and cURL will handle creating bodies -* POST requests using a custom entity body are now treated exactly like PUT requests but with a custom cURL method. This - means that the redirect behavior of POST requests with custom bodies will not be the same as POST requests that use - POST fields or files (the latter is only used when emulating a form POST in the browser). -* Lots of cleanup to CurlHandle::factory and RequestFactory::createRequest - -## 3.3.1 - 2013-03-10 - -* Added the ability to create PHP streaming responses from HTTP requests -* Bug fix: Running any filters when parsing response headers with service descriptions -* Bug fix: OauthPlugin fixes to allow for multi-dimensional array signing, and sorting parameters before signing -* Bug fix: Removed the adding of default empty arrays and false Booleans to responses in order to be consistent across - response location visitors. -* Bug fix: Removed the possibility of creating configuration files with circular dependencies -* RequestFactory::create() now uses the key of a POST file when setting the POST file name -* Added xmlAllowEmpty to serialize an XML body even if no XML specific parameters are set - -## 3.3.0 - 2013-03-03 - -* A large number of performance optimizations have been made -* Bug fix: Added 'wb' as a valid write mode for streams -* Bug fix: `Guzzle\Http\Message\Response::json()` now allows scalar values to be returned -* Bug fix: Fixed bug in `Guzzle\Http\Message\Response` where wrapping quotes were stripped from `getEtag()` -* BC: Removed `Guzzle\Http\Utils` class -* BC: Setting a service description on a client will no longer modify the client's command factories. -* BC: Emitting IO events from a RequestMediator is now a parameter that must be set in a request's curl options using - the 'emit_io' key. This was previously set under a request's parameters using 'curl.emit_io' -* BC: `Guzzle\Stream\Stream::getWrapper()` and `Guzzle\Stream\Stream::getSteamType()` are no longer converted to - lowercase -* Operation parameter objects are now lazy loaded internally -* Added ErrorResponsePlugin that can throw errors for responses defined in service description operations' errorResponses -* Added support for instantiating responseType=class responseClass classes. Classes must implement - `Guzzle\Service\Command\ResponseClassInterface` -* Added support for additionalProperties for top-level parameters in responseType=model responseClasses. These - additional properties also support locations and can be used to parse JSON responses where the outermost part of the - JSON is an array -* Added support for nested renaming of JSON models (rename sentAs to name) -* CachePlugin - * Added support for stale-if-error so that the CachePlugin can now serve stale content from the cache on error - * Debug headers can now added to cached response in the CachePlugin - -## 3.2.0 - 2013-02-14 - -* CurlMulti is no longer reused globally. A new multi object is created per-client. This helps to isolate clients. -* URLs with no path no longer contain a "/" by default -* Guzzle\Http\QueryString does no longer manages the leading "?". This is now handled in Guzzle\Http\Url. -* BadResponseException no longer includes the full request and response message -* Adding setData() to Guzzle\Service\Description\ServiceDescriptionInterface -* Adding getResponseBody() to Guzzle\Http\Message\RequestInterface -* Various updates to classes to use ServiceDescriptionInterface type hints rather than ServiceDescription -* Header values can now be normalized into distinct values when multiple headers are combined with a comma separated list -* xmlEncoding can now be customized for the XML declaration of a XML service description operation -* Guzzle\Http\QueryString now uses Guzzle\Http\QueryAggregator\QueryAggregatorInterface objects to add custom value - aggregation and no longer uses callbacks -* The URL encoding implementation of Guzzle\Http\QueryString can now be customized -* Bug fix: Filters were not always invoked for array service description parameters -* Bug fix: Redirects now use a target response body rather than a temporary response body -* Bug fix: The default exponential backoff BackoffPlugin was not giving when the request threshold was exceeded -* Bug fix: Guzzle now takes the first found value when grabbing Cache-Control directives - -## 3.1.2 - 2013-01-27 - -* Refactored how operation responses are parsed. Visitors now include a before() method responsible for parsing the - response body. For example, the XmlVisitor now parses the XML response into an array in the before() method. -* Fixed an issue where cURL would not automatically decompress responses when the Accept-Encoding header was sent -* CURLOPT_SSL_VERIFYHOST is never set to 1 because it is deprecated (see 5e0ff2ef20f839e19d1eeb298f90ba3598784444) -* Fixed a bug where redirect responses were not chained correctly using getPreviousResponse() -* Setting default headers on a client after setting the user-agent will not erase the user-agent setting - -## 3.1.1 - 2013-01-20 - -* Adding wildcard support to Guzzle\Common\Collection::getPath() -* Adding alias support to ServiceBuilder configs -* Adding Guzzle\Service\Resource\CompositeResourceIteratorFactory and cleaning up factory interface - -## 3.1.0 - 2013-01-12 - -* BC: CurlException now extends from RequestException rather than BadResponseException -* BC: Renamed Guzzle\Plugin\Cache\CanCacheStrategyInterface::canCache() to canCacheRequest() and added CanCacheResponse() -* Added getData to ServiceDescriptionInterface -* Added context array to RequestInterface::setState() -* Bug: Removing hard dependency on the BackoffPlugin from Guzzle\Http -* Bug: Adding required content-type when JSON request visitor adds JSON to a command -* Bug: Fixing the serialization of a service description with custom data -* Made it easier to deal with exceptions thrown when transferring commands or requests in parallel by providing - an array of successful and failed responses -* Moved getPath from Guzzle\Service\Resource\Model to Guzzle\Common\Collection -* Added Guzzle\Http\IoEmittingEntityBody -* Moved command filtration from validators to location visitors -* Added `extends` attributes to service description parameters -* Added getModels to ServiceDescriptionInterface - -## 3.0.7 - 2012-12-19 - -* Fixing phar detection when forcing a cacert to system if null or true -* Allowing filename to be passed to `Guzzle\Http\Message\Request::setResponseBody()` -* Cleaning up `Guzzle\Common\Collection::inject` method -* Adding a response_body location to service descriptions - -## 3.0.6 - 2012-12-09 - -* CurlMulti performance improvements -* Adding setErrorResponses() to Operation -* composer.json tweaks - -## 3.0.5 - 2012-11-18 - -* Bug: Fixing an infinite recursion bug caused from revalidating with the CachePlugin -* Bug: Response body can now be a string containing "0" -* Bug: Using Guzzle inside of a phar uses system by default but now allows for a custom cacert -* Bug: QueryString::fromString now properly parses query string parameters that contain equal signs -* Added support for XML attributes in service description responses -* DefaultRequestSerializer now supports array URI parameter values for URI template expansion -* Added better mimetype guessing to requests and post files - -## 3.0.4 - 2012-11-11 - -* Bug: Fixed a bug when adding multiple cookies to a request to use the correct glue value -* Bug: Cookies can now be added that have a name, domain, or value set to "0" -* Bug: Using the system cacert bundle when using the Phar -* Added json and xml methods to Response to make it easier to parse JSON and XML response data into data structures -* Enhanced cookie jar de-duplication -* Added the ability to enable strict cookie jars that throw exceptions when invalid cookies are added -* Added setStream to StreamInterface to actually make it possible to implement custom rewind behavior for entity bodies -* Added the ability to create any sort of hash for a stream rather than just an MD5 hash - -## 3.0.3 - 2012-11-04 - -* Implementing redirects in PHP rather than cURL -* Added PECL URI template extension and using as default parser if available -* Bug: Fixed Content-Length parsing of Response factory -* Adding rewind() method to entity bodies and streams. Allows for custom rewinding of non-repeatable streams. -* Adding ToArrayInterface throughout library -* Fixing OauthPlugin to create unique nonce values per request - -## 3.0.2 - 2012-10-25 - -* Magic methods are enabled by default on clients -* Magic methods return the result of a command -* Service clients no longer require a base_url option in the factory -* Bug: Fixed an issue with URI templates where null template variables were being expanded - -## 3.0.1 - 2012-10-22 - -* Models can now be used like regular collection objects by calling filter, map, etc. -* Models no longer require a Parameter structure or initial data in the constructor -* Added a custom AppendIterator to get around a PHP bug with the `\AppendIterator` - -## 3.0.0 - 2012-10-15 - -* Rewrote service description format to be based on Swagger - * Now based on JSON schema - * Added nested input structures and nested response models - * Support for JSON and XML input and output models - * Renamed `commands` to `operations` - * Removed dot class notation - * Removed custom types -* Broke the project into smaller top-level namespaces to be more component friendly -* Removed support for XML configs and descriptions. Use arrays or JSON files. -* Removed the Validation component and Inspector -* Moved all cookie code to Guzzle\Plugin\Cookie -* Magic methods on a Guzzle\Service\Client now return the command un-executed. -* Calling getResult() or getResponse() on a command will lazily execute the command if needed. -* Now shipping with cURL's CA certs and using it by default -* Added previousResponse() method to response objects -* No longer sending Accept and Accept-Encoding headers on every request -* Only sending an Expect header by default when a payload is greater than 1MB -* Added/moved client options: - * curl.blacklist to curl.option.blacklist - * Added ssl.certificate_authority -* Added a Guzzle\Iterator component -* Moved plugins from Guzzle\Http\Plugin to Guzzle\Plugin -* Added a more robust backoff retry strategy (replaced the ExponentialBackoffPlugin) -* Added a more robust caching plugin -* Added setBody to response objects -* Updating LogPlugin to use a more flexible MessageFormatter -* Added a completely revamped build process -* Cleaning up Collection class and removing default values from the get method -* Fixed ZF2 cache adapters - -## 2.8.8 - 2012-10-15 - -* Bug: Fixed a cookie issue that caused dot prefixed domains to not match where popular browsers did - -## 2.8.7 - 2012-09-30 - -* Bug: Fixed config file aliases for JSON includes -* Bug: Fixed cookie bug on a request object by using CookieParser to parse cookies on requests -* Bug: Removing the path to a file when sending a Content-Disposition header on a POST upload -* Bug: Hardening request and response parsing to account for missing parts -* Bug: Fixed PEAR packaging -* Bug: Fixed Request::getInfo -* Bug: Fixed cases where CURLM_CALL_MULTI_PERFORM return codes were causing curl transactions to fail -* Adding the ability for the namespace Iterator factory to look in multiple directories -* Added more getters/setters/removers from service descriptions -* Added the ability to remove POST fields from OAuth signatures -* OAuth plugin now supports 2-legged OAuth - -## 2.8.6 - 2012-09-05 - -* Added the ability to modify and build service descriptions -* Added the use of visitors to apply parameters to locations in service descriptions using the dynamic command -* Added a `json` parameter location -* Now allowing dot notation for classes in the CacheAdapterFactory -* Using the union of two arrays rather than an array_merge when extending service builder services and service params -* Ensuring that a service is a string before doing strpos() checks on it when substituting services for references - in service builder config files. -* Services defined in two different config files that include one another will by default replace the previously - defined service, but you can now create services that extend themselves and merge their settings over the previous -* The JsonLoader now supports aliasing filenames with different filenames. This allows you to alias something like - '_default' with a default JSON configuration file. - -## 2.8.5 - 2012-08-29 - -* Bug: Suppressed empty arrays from URI templates -* Bug: Added the missing $options argument from ServiceDescription::factory to enable caching -* Added support for HTTP responses that do not contain a reason phrase in the start-line -* AbstractCommand commands are now invokable -* Added a way to get the data used when signing an Oauth request before a request is sent - -## 2.8.4 - 2012-08-15 - -* Bug: Custom delay time calculations are no longer ignored in the ExponentialBackoffPlugin -* Added the ability to transfer entity bodies as a string rather than streamed. This gets around curl error 65. Set `body_as_string` in a request's curl options to enable. -* Added a StreamInterface, EntityBodyInterface, and added ftell() to Guzzle\Common\Stream -* Added an AbstractEntityBodyDecorator and a ReadLimitEntityBody decorator to transfer only a subset of a decorated stream -* Stream and EntityBody objects will now return the file position to the previous position after a read required operation (e.g. getContentMd5()) -* Added additional response status codes -* Removed SSL information from the default User-Agent header -* DELETE requests can now send an entity body -* Added an EventDispatcher to the ExponentialBackoffPlugin and added an ExponentialBackoffLogger to log backoff retries -* Added the ability of the MockPlugin to consume mocked request bodies -* LogPlugin now exposes request and response objects in the extras array - -## 2.8.3 - 2012-07-30 - -* Bug: Fixed a case where empty POST requests were sent as GET requests -* Bug: Fixed a bug in ExponentialBackoffPlugin that caused fatal errors when retrying an EntityEnclosingRequest that does not have a body -* Bug: Setting the response body of a request to null after completing a request, not when setting the state of a request to new -* Added multiple inheritance to service description commands -* Added an ApiCommandInterface and added `getParamNames()` and `hasParam()` -* Removed the default 2mb size cutoff from the Md5ValidatorPlugin so that it now defaults to validating everything -* Changed CurlMulti::perform to pass a smaller timeout to CurlMulti::executeHandles - -## 2.8.2 - 2012-07-24 - -* Bug: Query string values set to 0 are no longer dropped from the query string -* Bug: A Collection object is no longer created each time a call is made to `Guzzle\Service\Command\AbstractCommand::getRequestHeaders()` -* Bug: `+` is now treated as an encoded space when parsing query strings -* QueryString and Collection performance improvements -* Allowing dot notation for class paths in filters attribute of a service descriptions - -## 2.8.1 - 2012-07-16 - -* Loosening Event Dispatcher dependency -* POST redirects can now be customized using CURLOPT_POSTREDIR - -## 2.8.0 - 2012-07-15 - -* BC: Guzzle\Http\Query - * Query strings with empty variables will always show an equal sign unless the variable is set to QueryString::BLANK (e.g. ?acl= vs ?acl) - * Changed isEncodingValues() and isEncodingFields() to isUrlEncoding() - * Changed setEncodeValues(bool) and setEncodeFields(bool) to useUrlEncoding(bool) - * Changed the aggregation functions of QueryString to be static methods - * Can now use fromString() with querystrings that have a leading ? -* cURL configuration values can be specified in service descriptions using `curl.` prefixed parameters -* Content-Length is set to 0 before emitting the request.before_send event when sending an empty request body -* Cookies are no longer URL decoded by default -* Bug: URI template variables set to null are no longer expanded - -## 2.7.2 - 2012-07-02 - -* BC: Moving things to get ready for subtree splits. Moving Inflection into Common. Moving Guzzle\Http\Parser to Guzzle\Parser. -* BC: Removing Guzzle\Common\Batch\Batch::count() and replacing it with isEmpty() -* CachePlugin now allows for a custom request parameter function to check if a request can be cached -* Bug fix: CachePlugin now only caches GET and HEAD requests by default -* Bug fix: Using header glue when transferring headers over the wire -* Allowing deeply nested arrays for composite variables in URI templates -* Batch divisors can now return iterators or arrays - -## 2.7.1 - 2012-06-26 - -* Minor patch to update version number in UA string -* Updating build process - -## 2.7.0 - 2012-06-25 - -* BC: Inflection classes moved to Guzzle\Inflection. No longer static methods. Can now inject custom inflectors into classes. -* BC: Removed magic setX methods from commands -* BC: Magic methods mapped to service description commands are now inflected in the command factory rather than the client __call() method -* Verbose cURL options are no longer enabled by default. Set curl.debug to true on a client to enable. -* Bug: Now allowing colons in a response start-line (e.g. HTTP/1.1 503 Service Unavailable: Back-end server is at capacity) -* Guzzle\Service\Resource\ResourceIteratorApplyBatched now internally uses the Guzzle\Common\Batch namespace -* Added Guzzle\Service\Plugin namespace and a PluginCollectionPlugin -* Added the ability to set POST fields and files in a service description -* Guzzle\Http\EntityBody::factory() now accepts objects with a __toString() method -* Adding a command.before_prepare event to clients -* Added BatchClosureTransfer and BatchClosureDivisor -* BatchTransferException now includes references to the batch divisor and transfer strategies -* Fixed some tests so that they pass more reliably -* Added Guzzle\Common\Log\ArrayLogAdapter - -## 2.6.6 - 2012-06-10 - -* BC: Removing Guzzle\Http\Plugin\BatchQueuePlugin -* BC: Removing Guzzle\Service\Command\CommandSet -* Adding generic batching system (replaces the batch queue plugin and command set) -* Updating ZF cache and log adapters and now using ZF's composer repository -* Bug: Setting the name of each ApiParam when creating through an ApiCommand -* Adding result_type, result_doc, deprecated, and doc_url to service descriptions -* Bug: Changed the default cookie header casing back to 'Cookie' - -## 2.6.5 - 2012-06-03 - -* BC: Renaming Guzzle\Http\Message\RequestInterface::getResourceUri() to getResource() -* BC: Removing unused AUTH_BASIC and AUTH_DIGEST constants from -* BC: Guzzle\Http\Cookie is now used to manage Set-Cookie data, not Cookie data -* BC: Renaming methods in the CookieJarInterface -* Moving almost all cookie logic out of the CookiePlugin and into the Cookie or CookieJar implementations -* Making the default glue for HTTP headers ';' instead of ',' -* Adding a removeValue to Guzzle\Http\Message\Header -* Adding getCookies() to request interface. -* Making it easier to add event subscribers to HasDispatcherInterface classes. Can now directly call addSubscriber() - -## 2.6.4 - 2012-05-30 - -* BC: Cleaning up how POST files are stored in EntityEnclosingRequest objects. Adding PostFile class. -* BC: Moving ApiCommand specific functionality from the Inspector and on to the ApiCommand -* Bug: Fixing magic method command calls on clients -* Bug: Email constraint only validates strings -* Bug: Aggregate POST fields when POST files are present in curl handle -* Bug: Fixing default User-Agent header -* Bug: Only appending or prepending parameters in commands if they are specified -* Bug: Not requiring response reason phrases or status codes to match a predefined list of codes -* Allowing the use of dot notation for class namespaces when using instance_of constraint -* Added any_match validation constraint -* Added an AsyncPlugin -* Passing request object to the calculateWait method of the ExponentialBackoffPlugin -* Allowing the result of a command object to be changed -* Parsing location and type sub values when instantiating a service description rather than over and over at runtime - -## 2.6.3 - 2012-05-23 - -* [BC] Guzzle\Common\FromConfigInterface no longer requires any config options. -* [BC] Refactoring how POST files are stored on an EntityEnclosingRequest. They are now separate from POST fields. -* You can now use an array of data when creating PUT request bodies in the request factory. -* Removing the requirement that HTTPS requests needed a Cache-Control: public directive to be cacheable. -* [Http] Adding support for Content-Type in multipart POST uploads per upload -* [Http] Added support for uploading multiple files using the same name (foo[0], foo[1]) -* Adding more POST data operations for easier manipulation of POST data. -* You can now set empty POST fields. -* The body of a request is only shown on EntityEnclosingRequest objects that do not use POST files. -* Split the Guzzle\Service\Inspector::validateConfig method into two methods. One to initialize when a command is created, and one to validate. -* CS updates - -## 2.6.2 - 2012-05-19 - -* [Http] Better handling of nested scope requests in CurlMulti. Requests are now always prepares in the send() method rather than the addRequest() method. - -## 2.6.1 - 2012-05-19 - -* [BC] Removing 'path' support in service descriptions. Use 'uri'. -* [BC] Guzzle\Service\Inspector::parseDocBlock is now protected. Adding getApiParamsForClass() with cache. -* [BC] Removing Guzzle\Common\NullObject. Use https://github.com/mtdowling/NullObject if you need it. -* [BC] Removing Guzzle\Common\XmlElement. -* All commands, both dynamic and concrete, have ApiCommand objects. -* Adding a fix for CurlMulti so that if all of the connections encounter some sort of curl error, then the loop exits. -* Adding checks to EntityEnclosingRequest so that empty POST files and fields are ignored. -* Making the method signature of Guzzle\Service\Builder\ServiceBuilder::factory more flexible. - -## 2.6.0 - 2012-05-15 - -* [BC] Moving Guzzle\Service\Builder to Guzzle\Service\Builder\ServiceBuilder -* [BC] Executing a Command returns the result of the command rather than the command -* [BC] Moving all HTTP parsing logic to Guzzle\Http\Parsers. Allows for faster C implementations if needed. -* [BC] Changing the Guzzle\Http\Message\Response::setProtocol() method to accept a protocol and version in separate args. -* [BC] Moving ResourceIterator* to Guzzle\Service\Resource -* [BC] Completely refactored ResourceIterators to iterate over a cloned command object -* [BC] Moved Guzzle\Http\UriTemplate to Guzzle\Http\Parser\UriTemplate\UriTemplate -* [BC] Guzzle\Guzzle is now deprecated -* Moving Guzzle\Common\Guzzle::inject to Guzzle\Common\Collection::inject -* Adding Guzzle\Version class to give version information about Guzzle -* Adding Guzzle\Http\Utils class to provide getDefaultUserAgent() and getHttpDate() -* Adding Guzzle\Curl\CurlVersion to manage caching curl_version() data -* ServiceDescription and ServiceBuilder are now cacheable using similar configs -* Changing the format of XML and JSON service builder configs. Backwards compatible. -* Cleaned up Cookie parsing -* Trimming the default Guzzle User-Agent header -* Adding a setOnComplete() method to Commands that is called when a command completes -* Keeping track of requests that were mocked in the MockPlugin -* Fixed a caching bug in the CacheAdapterFactory -* Inspector objects can be injected into a Command object -* Refactoring a lot of code and tests to be case insensitive when dealing with headers -* Adding Guzzle\Http\Message\HeaderComparison for easy comparison of HTTP headers using a DSL -* Adding the ability to set global option overrides to service builder configs -* Adding the ability to include other service builder config files from within XML and JSON files -* Moving the parseQuery method out of Url and on to QueryString::fromString() as a static factory method. - -## 2.5.0 - 2012-05-08 - -* Major performance improvements -* [BC] Simplifying Guzzle\Common\Collection. Please check to see if you are using features that are now deprecated. -* [BC] Using a custom validation system that allows a flyweight implementation for much faster validation. No longer using Symfony2 Validation component. -* [BC] No longer supporting "{{ }}" for injecting into command or UriTemplates. Use "{}" -* Added the ability to passed parameters to all requests created by a client -* Added callback functionality to the ExponentialBackoffPlugin -* Using microtime in ExponentialBackoffPlugin to allow more granular backoff strategies. -* Rewinding request stream bodies when retrying requests -* Exception is thrown when JSON response body cannot be decoded -* Added configurable magic method calls to clients and commands. This is off by default. -* Fixed a defect that added a hash to every parsed URL part -* Fixed duplicate none generation for OauthPlugin. -* Emitting an event each time a client is generated by a ServiceBuilder -* Using an ApiParams object instead of a Collection for parameters of an ApiCommand -* cache.* request parameters should be renamed to params.cache.* -* Added the ability to set arbitrary curl options on requests (disable_wire, progress, etc.). See CurlHandle. -* Added the ability to disable type validation of service descriptions -* ServiceDescriptions and ServiceBuilders are now Serializable diff --git a/lib/guzzlehttp/guzzle/LICENSE b/lib/guzzlehttp/guzzle/LICENSE deleted file mode 100644 index fd2375d88..000000000 --- a/lib/guzzlehttp/guzzle/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2011 Michael Dowling <mtdowling@gmail.com> -Copyright (c) 2012 Jeremy Lindblom <jeremeamia@gmail.com> -Copyright (c) 2014 Graham Campbell <hello@gjcampbell.co.uk> -Copyright (c) 2015 Márk Sági-Kazár <mark.sagikazar@gmail.com> -Copyright (c) 2015 Tobias Schultze <webmaster@tubo-world.de> -Copyright (c) 2016 Tobias Nyholm <tobias.nyholm@gmail.com> -Copyright (c) 2016 George Mponos <gmponos@gmail.com> - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -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/lib/guzzlehttp/guzzle/README.md b/lib/guzzlehttp/guzzle/README.md deleted file mode 100644 index 0786462b3..000000000 --- a/lib/guzzlehttp/guzzle/README.md +++ /dev/null @@ -1,94 +0,0 @@ -![Guzzle](.github/logo.png?raw=true) - -# Guzzle, PHP HTTP client - -[![Latest Version](https://img.shields.io/github/release/guzzle/guzzle.svg?style=flat-square)](https://github.com/guzzle/guzzle/releases) -[![Build Status](https://img.shields.io/github/workflow/status/guzzle/guzzle/CI?label=ci%20build&style=flat-square)](https://github.com/guzzle/guzzle/actions?query=workflow%3ACI) -[![Total Downloads](https://img.shields.io/packagist/dt/guzzlehttp/guzzle.svg?style=flat-square)](https://packagist.org/packages/guzzlehttp/guzzle) - -Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and -trivial to integrate with web services. - -- Simple interface for building query strings, POST requests, streaming large - uploads, streaming large downloads, using HTTP cookies, uploading JSON data, - etc... -- Can send both synchronous and asynchronous requests using the same interface. -- Uses PSR-7 interfaces for requests, responses, and streams. This allows you - to utilize other PSR-7 compatible libraries with Guzzle. -- Supports PSR-18 allowing interoperability between other PSR-18 HTTP Clients. -- Abstracts away the underlying HTTP transport, allowing you to write - environment and transport agnostic code; i.e., no hard dependency on cURL, - PHP streams, sockets, or non-blocking event loops. -- Middleware system allows you to augment and compose client behavior. - -```php -$client = new \GuzzleHttp\Client(); -$response = $client->request('GET', 'https://api.github.com/repos/guzzle/guzzle'); - -echo $response->getStatusCode(); // 200 -echo $response->getHeaderLine('content-type'); // 'application/json; charset=utf8' -echo $response->getBody(); // '{"id": 1420053, "name": "guzzle", ...}' - -// Send an asynchronous request. -$request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org'); -$promise = $client->sendAsync($request)->then(function ($response) { - echo 'I completed! ' . $response->getBody(); -}); - -$promise->wait(); -``` - -## Help and docs - -We use GitHub issues only to discuss bugs and new features. For support please refer to: - -- [Documentation](https://docs.guzzlephp.org) -- [Stack Overflow](https://stackoverflow.com/questions/tagged/guzzle) -- [#guzzle](https://app.slack.com/client/T0D2S9JCT/CE6UAAKL4) channel on [PHP-HTTP Slack](https://slack.httplug.io/) -- [Gitter](https://gitter.im/guzzle/guzzle) - - -## Installing Guzzle - -The recommended way to install Guzzle is through -[Composer](https://getcomposer.org/). - -```bash -composer require guzzlehttp/guzzle -``` - - -## Version Guidance - -| Version | Status | Packagist | Namespace | Repo | Docs | PSR-7 | PHP Version | -|---------|---------------------|---------------------|--------------|---------------------|---------------------|-------|--------------| -| 3.x | EOL | `guzzle/guzzle` | `Guzzle` | [v3][guzzle-3-repo] | [v3][guzzle-3-docs] | No | >=5.3.3,<7.0 | -| 4.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | [v4][guzzle-4-repo] | N/A | No | >=5.4,<7.0 | -| 5.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | [v5][guzzle-5-repo] | [v5][guzzle-5-docs] | No | >=5.4,<7.4 | -| 6.x | Security fixes only | `guzzlehttp/guzzle` | `GuzzleHttp` | [v6][guzzle-6-repo] | [v6][guzzle-6-docs] | Yes | >=5.5,<8.0 | -| 7.x | Latest | `guzzlehttp/guzzle` | `GuzzleHttp` | [v7][guzzle-7-repo] | [v7][guzzle-7-docs] | Yes | >=7.2.5,<8.3 | - -[guzzle-3-repo]: https://github.com/guzzle/guzzle3 -[guzzle-4-repo]: https://github.com/guzzle/guzzle/tree/4.x -[guzzle-5-repo]: https://github.com/guzzle/guzzle/tree/5.3 -[guzzle-6-repo]: https://github.com/guzzle/guzzle/tree/6.5 -[guzzle-7-repo]: https://github.com/guzzle/guzzle -[guzzle-3-docs]: https://guzzle3.readthedocs.io/ -[guzzle-5-docs]: https://docs.guzzlephp.org/en/5.3/ -[guzzle-6-docs]: https://docs.guzzlephp.org/en/6.5/ -[guzzle-7-docs]: https://docs.guzzlephp.org/en/latest/ - - -## Security - -If you discover a security vulnerability within this package, please send an email to security@tidelift.com. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see [Security Policy](https://github.com/guzzle/guzzle/security/policy) for more information. - -## License - -Guzzle is made available under the MIT License (MIT). Please see [License File](LICENSE) for more information. - -## For Enterprise - -Available as part of the Tidelift Subscription - -The maintainers of Guzzle and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/packagist-guzzlehttp-guzzle?utm_source=packagist-guzzlehttp-guzzle&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) diff --git a/lib/guzzlehttp/guzzle/UPGRADING.md b/lib/guzzlehttp/guzzle/UPGRADING.md deleted file mode 100644 index 45417a7e1..000000000 --- a/lib/guzzlehttp/guzzle/UPGRADING.md +++ /dev/null @@ -1,1253 +0,0 @@ -Guzzle Upgrade Guide -==================== - -6.0 to 7.0 ----------- - -In order to take advantage of the new features of PHP, Guzzle dropped the support -of PHP 5. The minimum supported PHP version is now PHP 7.2. Type hints and return -types for functions and methods have been added wherever possible. - -Please make sure: -- You are calling a function or a method with the correct type. -- If you extend a class of Guzzle; update all signatures on methods you override. - -#### Other backwards compatibility breaking changes - -- Class `GuzzleHttp\UriTemplate` is removed. -- Class `GuzzleHttp\Exception\SeekException` is removed. -- Classes `GuzzleHttp\Exception\BadResponseException`, `GuzzleHttp\Exception\ClientException`, - `GuzzleHttp\Exception\ServerException` can no longer be initialized with an empty - Response as argument. -- Class `GuzzleHttp\Exception\ConnectException` now extends `GuzzleHttp\Exception\TransferException` - instead of `GuzzleHttp\Exception\RequestException`. -- Function `GuzzleHttp\Exception\ConnectException::getResponse()` is removed. -- Function `GuzzleHttp\Exception\ConnectException::hasResponse()` is removed. -- Constant `GuzzleHttp\ClientInterface::VERSION` is removed. Added `GuzzleHttp\ClientInterface::MAJOR_VERSION` instead. -- Function `GuzzleHttp\Exception\RequestException::getResponseBodySummary` is removed. - Use `\GuzzleHttp\Psr7\get_message_body_summary` as an alternative. -- Function `GuzzleHttp\Cookie\CookieJar::getCookieValue` is removed. -- Request option `exception` is removed. Please use `http_errors`. -- Request option `save_to` is removed. Please use `sink`. -- Pool option `pool_size` is removed. Please use `concurrency`. -- We now look for environment variables in the `$_SERVER` super global, due to thread safety issues with `getenv`. We continue to fallback to `getenv` in CLI environments, for maximum compatibility. -- The `get`, `head`, `put`, `post`, `patch`, `delete`, `getAsync`, `headAsync`, `putAsync`, `postAsync`, `patchAsync`, and `deleteAsync` methods are now implemented as genuine methods on `GuzzleHttp\Client`, with strong typing. The original `__call` implementation remains unchanged for now, for maximum backwards compatibility, but won't be invoked under normal operation. -- The `log` middleware will log the errors with level `error` instead of `notice` -- Support for international domain names (IDN) is now disabled by default, and enabling it requires installing ext-intl, linked against a modern version of the C library (ICU 4.6 or higher). - -#### Native functions calls - -All internal native functions calls of Guzzle are now prefixed with a slash. This -change makes it impossible for method overloading by other libraries or applications. -Example: - -```php -// Before: -curl_version(); - -// After: -\curl_version(); -``` - -For the full diff you can check [here](https://github.com/guzzle/guzzle/compare/6.5.4..master). - -5.0 to 6.0 ----------- - -Guzzle now uses [PSR-7](https://www.php-fig.org/psr/psr-7/) for HTTP messages. -Due to the fact that these messages are immutable, this prompted a refactoring -of Guzzle to use a middleware based system rather than an event system. Any -HTTP message interaction (e.g., `GuzzleHttp\Message\Request`) need to be -updated to work with the new immutable PSR-7 request and response objects. Any -event listeners or subscribers need to be updated to become middleware -functions that wrap handlers (or are injected into a -`GuzzleHttp\HandlerStack`). - -- Removed `GuzzleHttp\BatchResults` -- Removed `GuzzleHttp\Collection` -- Removed `GuzzleHttp\HasDataTrait` -- Removed `GuzzleHttp\ToArrayInterface` -- The `guzzlehttp/streams` dependency has been removed. Stream functionality - is now present in the `GuzzleHttp\Psr7` namespace provided by the - `guzzlehttp/psr7` package. -- Guzzle no longer uses ReactPHP promises and now uses the - `guzzlehttp/promises` library. We use a custom promise library for three - significant reasons: - 1. React promises (at the time of writing this) are recursive. Promise - chaining and promise resolution will eventually blow the stack. Guzzle - promises are not recursive as they use a sort of trampolining technique. - Note: there has been movement in the React project to modify promises to - no longer utilize recursion. - 2. Guzzle needs to have the ability to synchronously block on a promise to - wait for a result. Guzzle promises allows this functionality (and does - not require the use of recursion). - 3. Because we need to be able to wait on a result, doing so using React - promises requires wrapping react promises with RingPHP futures. This - overhead is no longer needed, reducing stack sizes, reducing complexity, - and improving performance. -- `GuzzleHttp\Mimetypes` has been moved to a function in - `GuzzleHttp\Psr7\mimetype_from_extension` and - `GuzzleHttp\Psr7\mimetype_from_filename`. -- `GuzzleHttp\Query` and `GuzzleHttp\QueryParser` have been removed. Query - strings must now be passed into request objects as strings, or provided to - the `query` request option when creating requests with clients. The `query` - option uses PHP's `http_build_query` to convert an array to a string. If you - need a different serialization technique, you will need to pass the query - string in as a string. There are a couple helper functions that will make - working with query strings easier: `GuzzleHttp\Psr7\parse_query` and - `GuzzleHttp\Psr7\build_query`. -- Guzzle no longer has a dependency on RingPHP. Due to the use of a middleware - system based on PSR-7, using RingPHP and it's middleware system as well adds - more complexity than the benefits it provides. All HTTP handlers that were - present in RingPHP have been modified to work directly with PSR-7 messages - and placed in the `GuzzleHttp\Handler` namespace. This significantly reduces - complexity in Guzzle, removes a dependency, and improves performance. RingPHP - will be maintained for Guzzle 5 support, but will no longer be a part of - Guzzle 6. -- As Guzzle now uses a middleware based systems the event system and RingPHP - integration has been removed. Note: while the event system has been removed, - it is possible to add your own type of event system that is powered by the - middleware system. - - Removed the `Event` namespace. - - Removed the `Subscriber` namespace. - - Removed `Transaction` class - - Removed `RequestFsm` - - Removed `RingBridge` - - `GuzzleHttp\Subscriber\Cookie` is now provided by - `GuzzleHttp\Middleware::cookies` - - `GuzzleHttp\Subscriber\HttpError` is now provided by - `GuzzleHttp\Middleware::httpError` - - `GuzzleHttp\Subscriber\History` is now provided by - `GuzzleHttp\Middleware::history` - - `GuzzleHttp\Subscriber\Mock` is now provided by - `GuzzleHttp\Handler\MockHandler` - - `GuzzleHttp\Subscriber\Prepare` is now provided by - `GuzzleHttp\PrepareBodyMiddleware` - - `GuzzleHttp\Subscriber\Redirect` is now provided by - `GuzzleHttp\RedirectMiddleware` -- Guzzle now uses `Psr\Http\Message\UriInterface` (implements in - `GuzzleHttp\Psr7\Uri`) for URI support. `GuzzleHttp\Url` is now gone. -- Static functions in `GuzzleHttp\Utils` have been moved to namespaced - functions under the `GuzzleHttp` namespace. This requires either a Composer - based autoloader or you to include functions.php. -- `GuzzleHttp\ClientInterface::getDefaultOption` has been renamed to - `GuzzleHttp\ClientInterface::getConfig`. -- `GuzzleHttp\ClientInterface::setDefaultOption` has been removed. -- The `json` and `xml` methods of response objects has been removed. With the - migration to strictly adhering to PSR-7 as the interface for Guzzle messages, - adding methods to message interfaces would actually require Guzzle messages - to extend from PSR-7 messages rather then work with them directly. - -## Migrating to middleware - -The change to PSR-7 unfortunately required significant refactoring to Guzzle -due to the fact that PSR-7 messages are immutable. Guzzle 5 relied on an event -system from plugins. The event system relied on mutability of HTTP messages and -side effects in order to work. With immutable messages, you have to change your -workflow to become more about either returning a value (e.g., functional -middlewares) or setting a value on an object. Guzzle v6 has chosen the -functional middleware approach. - -Instead of using the event system to listen for things like the `before` event, -you now create a stack based middleware function that intercepts a request on -the way in and the promise of the response on the way out. This is a much -simpler and more predictable approach than the event system and works nicely -with PSR-7 middleware. Due to the use of promises, the middleware system is -also asynchronous. - -v5: - -```php -use GuzzleHttp\Event\BeforeEvent; -$client = new GuzzleHttp\Client(); -// Get the emitter and listen to the before event. -$client->getEmitter()->on('before', function (BeforeEvent $e) { - // Guzzle v5 events relied on mutation - $e->getRequest()->setHeader('X-Foo', 'Bar'); -}); -``` - -v6: - -In v6, you can modify the request before it is sent using the `mapRequest` -middleware. The idiomatic way in v6 to modify the request/response lifecycle is -to setup a handler middleware stack up front and inject the handler into a -client. - -```php -use GuzzleHttp\Middleware; -// Create a handler stack that has all of the default middlewares attached -$handler = GuzzleHttp\HandlerStack::create(); -// Push the handler onto the handler stack -$handler->push(Middleware::mapRequest(function (RequestInterface $request) { - // Notice that we have to return a request object - return $request->withHeader('X-Foo', 'Bar'); -})); -// Inject the handler into the client -$client = new GuzzleHttp\Client(['handler' => $handler]); -``` - -## POST Requests - -This version added the [`form_params`](http://guzzle.readthedocs.org/en/latest/request-options.html#form_params) -and `multipart` request options. `form_params` is an associative array of -strings or array of strings and is used to serialize an -`application/x-www-form-urlencoded` POST request. The -[`multipart`](http://guzzle.readthedocs.org/en/latest/request-options.html#multipart) -option is now used to send a multipart/form-data POST request. - -`GuzzleHttp\Post\PostFile` has been removed. Use the `multipart` option to add -POST files to a multipart/form-data request. - -The `body` option no longer accepts an array to send POST requests. Please use -`multipart` or `form_params` instead. - -The `base_url` option has been renamed to `base_uri`. - -4.x to 5.0 ----------- - -## Rewritten Adapter Layer - -Guzzle now uses [RingPHP](http://ringphp.readthedocs.org/en/latest) to send -HTTP requests. The `adapter` option in a `GuzzleHttp\Client` constructor -is still supported, but it has now been renamed to `handler`. Instead of -passing a `GuzzleHttp\Adapter\AdapterInterface`, you must now pass a PHP -`callable` that follows the RingPHP specification. - -## Removed Fluent Interfaces - -[Fluent interfaces were removed](https://ocramius.github.io/blog/fluent-interfaces-are-evil/) -from the following classes: - -- `GuzzleHttp\Collection` -- `GuzzleHttp\Url` -- `GuzzleHttp\Query` -- `GuzzleHttp\Post\PostBody` -- `GuzzleHttp\Cookie\SetCookie` - -## Removed functions.php - -Removed "functions.php", so that Guzzle is truly PSR-4 compliant. The following -functions can be used as replacements. - -- `GuzzleHttp\json_decode` -> `GuzzleHttp\Utils::jsonDecode` -- `GuzzleHttp\get_path` -> `GuzzleHttp\Utils::getPath` -- `GuzzleHttp\Utils::setPath` -> `GuzzleHttp\set_path` -- `GuzzleHttp\Pool::batch` -> `GuzzleHttp\batch`. This function is, however, - deprecated in favor of using `GuzzleHttp\Pool::batch()`. - -The "procedural" global client has been removed with no replacement (e.g., -`GuzzleHttp\get()`, `GuzzleHttp\post()`, etc.). Use a `GuzzleHttp\Client` -object as a replacement. - -## `throwImmediately` has been removed - -The concept of "throwImmediately" has been removed from exceptions and error -events. This control mechanism was used to stop a transfer of concurrent -requests from completing. This can now be handled by throwing the exception or -by cancelling a pool of requests or each outstanding future request -individually. - -## headers event has been removed - -Removed the "headers" event. This event was only useful for changing the -body a response once the headers of the response were known. You can implement -a similar behavior in a number of ways. One example might be to use a -FnStream that has access to the transaction being sent. For example, when the -first byte is written, you could check if the response headers match your -expectations, and if so, change the actual stream body that is being -written to. - -## Updates to HTTP Messages - -Removed the `asArray` parameter from -`GuzzleHttp\Message\MessageInterface::getHeader`. If you want to get a header -value as an array, then use the newly added `getHeaderAsArray()` method of -`MessageInterface`. This change makes the Guzzle interfaces compatible with -the PSR-7 interfaces. - -3.x to 4.0 ----------- - -## Overarching changes: - -- Now requires PHP 5.4 or greater. -- No longer requires cURL to send requests. -- Guzzle no longer wraps every exception it throws. Only exceptions that are - recoverable are now wrapped by Guzzle. -- Various namespaces have been removed or renamed. -- No longer requiring the Symfony EventDispatcher. A custom event dispatcher - based on the Symfony EventDispatcher is - now utilized in `GuzzleHttp\Event\EmitterInterface` (resulting in significant - speed and functionality improvements). - -Changes per Guzzle 3.x namespace are described below. - -## Batch - -The `Guzzle\Batch` namespace has been removed. This is best left to -third-parties to implement on top of Guzzle's core HTTP library. - -## Cache - -The `Guzzle\Cache` namespace has been removed. (Todo: No suitable replacement -has been implemented yet, but hoping to utilize a PSR cache interface). - -## Common - -- Removed all of the wrapped exceptions. It's better to use the standard PHP - library for unrecoverable exceptions. -- `FromConfigInterface` has been removed. -- `Guzzle\Common\Version` has been removed. The VERSION constant can be found - at `GuzzleHttp\ClientInterface::VERSION`. - -### Collection - -- `getAll` has been removed. Use `toArray` to convert a collection to an array. -- `inject` has been removed. -- `keySearch` has been removed. -- `getPath` no longer supports wildcard expressions. Use something better like - JMESPath for this. -- `setPath` now supports appending to an existing array via the `[]` notation. - -### Events - -Guzzle no longer requires Symfony's EventDispatcher component. Guzzle now uses -`GuzzleHttp\Event\Emitter`. - -- `Symfony\Component\EventDispatcher\EventDispatcherInterface` is replaced by - `GuzzleHttp\Event\EmitterInterface`. -- `Symfony\Component\EventDispatcher\EventDispatcher` is replaced by - `GuzzleHttp\Event\Emitter`. -- `Symfony\Component\EventDispatcher\Event` is replaced by - `GuzzleHttp\Event\Event`, and Guzzle now has an EventInterface in - `GuzzleHttp\Event\EventInterface`. -- `AbstractHasDispatcher` has moved to a trait, `HasEmitterTrait`, and - `HasDispatcherInterface` has moved to `HasEmitterInterface`. Retrieving the - event emitter of a request, client, etc. now uses the `getEmitter` method - rather than the `getDispatcher` method. - -#### Emitter - -- Use the `once()` method to add a listener that automatically removes itself - the first time it is invoked. -- Use the `listeners()` method to retrieve a list of event listeners rather than - the `getListeners()` method. -- Use `emit()` instead of `dispatch()` to emit an event from an emitter. -- Use `attach()` instead of `addSubscriber()` and `detach()` instead of - `removeSubscriber()`. - -```php -$mock = new Mock(); -// 3.x -$request->getEventDispatcher()->addSubscriber($mock); -$request->getEventDispatcher()->removeSubscriber($mock); -// 4.x -$request->getEmitter()->attach($mock); -$request->getEmitter()->detach($mock); -``` - -Use the `on()` method to add a listener rather than the `addListener()` method. - -```php -// 3.x -$request->getEventDispatcher()->addListener('foo', function (Event $event) { /* ... */ } ); -// 4.x -$request->getEmitter()->on('foo', function (Event $event, $name) { /* ... */ } ); -``` - -## Http - -### General changes - -- The cacert.pem certificate has been moved to `src/cacert.pem`. -- Added the concept of adapters that are used to transfer requests over the - wire. -- Simplified the event system. -- Sending requests in parallel is still possible, but batching is no longer a - concept of the HTTP layer. Instead, you must use the `complete` and `error` - events to asynchronously manage parallel request transfers. -- `Guzzle\Http\Url` has moved to `GuzzleHttp\Url`. -- `Guzzle\Http\QueryString` has moved to `GuzzleHttp\Query`. -- QueryAggregators have been rewritten so that they are simply callable - functions. -- `GuzzleHttp\StaticClient` has been removed. Use the functions provided in - `functions.php` for an easy to use static client instance. -- Exceptions in `GuzzleHttp\Exception` have been updated to all extend from - `GuzzleHttp\Exception\TransferException`. - -### Client - -Calling methods like `get()`, `post()`, `head()`, etc. no longer create and -return a request, but rather creates a request, sends the request, and returns -the response. - -```php -// 3.0 -$request = $client->get('/'); -$response = $request->send(); - -// 4.0 -$response = $client->get('/'); - -// or, to mirror the previous behavior -$request = $client->createRequest('GET', '/'); -$response = $client->send($request); -``` - -`GuzzleHttp\ClientInterface` has changed. - -- The `send` method no longer accepts more than one request. Use `sendAll` to - send multiple requests in parallel. -- `setUserAgent()` has been removed. Use a default request option instead. You - could, for example, do something like: - `$client->setConfig('defaults/headers/User-Agent', 'Foo/Bar ' . $client::getDefaultUserAgent())`. -- `setSslVerification()` has been removed. Use default request options instead, - like `$client->setConfig('defaults/verify', true)`. - -`GuzzleHttp\Client` has changed. - -- The constructor now accepts only an associative array. You can include a - `base_url` string or array to use a URI template as the base URL of a client. - You can also specify a `defaults` key that is an associative array of default - request options. You can pass an `adapter` to use a custom adapter, - `batch_adapter` to use a custom adapter for sending requests in parallel, or - a `message_factory` to change the factory used to create HTTP requests and - responses. -- The client no longer emits a `client.create_request` event. -- Creating requests with a client no longer automatically utilize a URI - template. You must pass an array into a creational method (e.g., - `createRequest`, `get`, `put`, etc.) in order to expand a URI template. - -### Messages - -Messages no longer have references to their counterparts (i.e., a request no -longer has a reference to it's response, and a response no loger has a -reference to its request). This association is now managed through a -`GuzzleHttp\Adapter\TransactionInterface` object. You can get references to -these transaction objects using request events that are emitted over the -lifecycle of a request. - -#### Requests with a body - -- `GuzzleHttp\Message\EntityEnclosingRequest` and - `GuzzleHttp\Message\EntityEnclosingRequestInterface` have been removed. The - separation between requests that contain a body and requests that do not - contain a body has been removed, and now `GuzzleHttp\Message\RequestInterface` - handles both use cases. -- Any method that previously accepts a `GuzzleHttp\Response` object now accept a - `GuzzleHttp\Message\ResponseInterface`. -- `GuzzleHttp\Message\RequestFactoryInterface` has been renamed to - `GuzzleHttp\Message\MessageFactoryInterface`. This interface is used to create - both requests and responses and is implemented in - `GuzzleHttp\Message\MessageFactory`. -- POST field and file methods have been removed from the request object. You - must now use the methods made available to `GuzzleHttp\Post\PostBodyInterface` - to control the format of a POST body. Requests that are created using a - standard `GuzzleHttp\Message\MessageFactoryInterface` will automatically use - a `GuzzleHttp\Post\PostBody` body if the body was passed as an array or if - the method is POST and no body is provided. - -```php -$request = $client->createRequest('POST', '/'); -$request->getBody()->setField('foo', 'bar'); -$request->getBody()->addFile(new PostFile('file_key', fopen('/path/to/content', 'r'))); -``` - -#### Headers - -- `GuzzleHttp\Message\Header` has been removed. Header values are now simply - represented by an array of values or as a string. Header values are returned - as a string by default when retrieving a header value from a message. You can - pass an optional argument of `true` to retrieve a header value as an array - of strings instead of a single concatenated string. -- `GuzzleHttp\PostFile` and `GuzzleHttp\PostFileInterface` have been moved to - `GuzzleHttp\Post`. This interface has been simplified and now allows the - addition of arbitrary headers. -- Custom headers like `GuzzleHttp\Message\Header\Link` have been removed. Most - of the custom headers are now handled separately in specific - subscribers/plugins, and `GuzzleHttp\Message\HeaderValues::parseParams()` has - been updated to properly handle headers that contain parameters (like the - `Link` header). - -#### Responses - -- `GuzzleHttp\Message\Response::getInfo()` and - `GuzzleHttp\Message\Response::setInfo()` have been removed. Use the event - system to retrieve this type of information. -- `GuzzleHttp\Message\Response::getRawHeaders()` has been removed. -- `GuzzleHttp\Message\Response::getMessage()` has been removed. -- `GuzzleHttp\Message\Response::calculateAge()` and other cache specific - methods have moved to the CacheSubscriber. -- Header specific helper functions like `getContentMd5()` have been removed. - Just use `getHeader('Content-MD5')` instead. -- `GuzzleHttp\Message\Response::setRequest()` and - `GuzzleHttp\Message\Response::getRequest()` have been removed. Use the event - system to work with request and response objects as a transaction. -- `GuzzleHttp\Message\Response::getRedirectCount()` has been removed. Use the - Redirect subscriber instead. -- `GuzzleHttp\Message\Response::isSuccessful()` and other related methods have - been removed. Use `getStatusCode()` instead. - -#### Streaming responses - -Streaming requests can now be created by a client directly, returning a -`GuzzleHttp\Message\ResponseInterface` object that contains a body stream -referencing an open PHP HTTP stream. - -```php -// 3.0 -use Guzzle\Stream\PhpStreamRequestFactory; -$request = $client->get('/'); -$factory = new PhpStreamRequestFactory(); -$stream = $factory->fromRequest($request); -$data = $stream->read(1024); - -// 4.0 -$response = $client->get('/', ['stream' => true]); -// Read some data off of the stream in the response body -$data = $response->getBody()->read(1024); -``` - -#### Redirects - -The `configureRedirects()` method has been removed in favor of a -`allow_redirects` request option. - -```php -// Standard redirects with a default of a max of 5 redirects -$request = $client->createRequest('GET', '/', ['allow_redirects' => true]); - -// Strict redirects with a custom number of redirects -$request = $client->createRequest('GET', '/', [ - 'allow_redirects' => ['max' => 5, 'strict' => true] -]); -``` - -#### EntityBody - -EntityBody interfaces and classes have been removed or moved to -`GuzzleHttp\Stream`. All classes and interfaces that once required -`GuzzleHttp\EntityBodyInterface` now require -`GuzzleHttp\Stream\StreamInterface`. Creating a new body for a request no -longer uses `GuzzleHttp\EntityBody::factory` but now uses -`GuzzleHttp\Stream\Stream::factory` or even better: -`GuzzleHttp\Stream\create()`. - -- `Guzzle\Http\EntityBodyInterface` is now `GuzzleHttp\Stream\StreamInterface` -- `Guzzle\Http\EntityBody` is now `GuzzleHttp\Stream\Stream` -- `Guzzle\Http\CachingEntityBody` is now `GuzzleHttp\Stream\CachingStream` -- `Guzzle\Http\ReadLimitEntityBody` is now `GuzzleHttp\Stream\LimitStream` -- `Guzzle\Http\IoEmittyinEntityBody` has been removed. - -#### Request lifecycle events - -Requests previously submitted a large number of requests. The number of events -emitted over the lifecycle of a request has been significantly reduced to make -it easier to understand how to extend the behavior of a request. All events -emitted during the lifecycle of a request now emit a custom -`GuzzleHttp\Event\EventInterface` object that contains context providing -methods and a way in which to modify the transaction at that specific point in -time (e.g., intercept the request and set a response on the transaction). - -- `request.before_send` has been renamed to `before` and now emits a - `GuzzleHttp\Event\BeforeEvent` -- `request.complete` has been renamed to `complete` and now emits a - `GuzzleHttp\Event\CompleteEvent`. -- `request.sent` has been removed. Use `complete`. -- `request.success` has been removed. Use `complete`. -- `error` is now an event that emits a `GuzzleHttp\Event\ErrorEvent`. -- `request.exception` has been removed. Use `error`. -- `request.receive.status_line` has been removed. -- `curl.callback.progress` has been removed. Use a custom `StreamInterface` to - maintain a status update. -- `curl.callback.write` has been removed. Use a custom `StreamInterface` to - intercept writes. -- `curl.callback.read` has been removed. Use a custom `StreamInterface` to - intercept reads. - -`headers` is a new event that is emitted after the response headers of a -request have been received before the body of the response is downloaded. This -event emits a `GuzzleHttp\Event\HeadersEvent`. - -You can intercept a request and inject a response using the `intercept()` event -of a `GuzzleHttp\Event\BeforeEvent`, `GuzzleHttp\Event\CompleteEvent`, and -`GuzzleHttp\Event\ErrorEvent` event. - -See: http://docs.guzzlephp.org/en/latest/events.html - -## Inflection - -The `Guzzle\Inflection` namespace has been removed. This is not a core concern -of Guzzle. - -## Iterator - -The `Guzzle\Iterator` namespace has been removed. - -- `Guzzle\Iterator\AppendIterator`, `Guzzle\Iterator\ChunkedIterator`, and - `Guzzle\Iterator\MethodProxyIterator` are nice, but not a core requirement of - Guzzle itself. -- `Guzzle\Iterator\FilterIterator` is no longer needed because an equivalent - class is shipped with PHP 5.4. -- `Guzzle\Iterator\MapIterator` is not really needed when using PHP 5.5 because - it's easier to just wrap an iterator in a generator that maps values. - -For a replacement of these iterators, see https://github.com/nikic/iter - -## Log - -The LogPlugin has moved to https://github.com/guzzle/log-subscriber. The -`Guzzle\Log` namespace has been removed. Guzzle now relies on -`Psr\Log\LoggerInterface` for all logging. The MessageFormatter class has been -moved to `GuzzleHttp\Subscriber\Log\Formatter`. - -## Parser - -The `Guzzle\Parser` namespace has been removed. This was previously used to -make it possible to plug in custom parsers for cookies, messages, URI -templates, and URLs; however, this level of complexity is not needed in Guzzle -so it has been removed. - -- Cookie: Cookie parsing logic has been moved to - `GuzzleHttp\Cookie\SetCookie::fromString`. -- Message: Message parsing logic for both requests and responses has been moved - to `GuzzleHttp\Message\MessageFactory::fromMessage`. Message parsing is only - used in debugging or deserializing messages, so it doesn't make sense for - Guzzle as a library to add this level of complexity to parsing messages. -- UriTemplate: URI template parsing has been moved to - `GuzzleHttp\UriTemplate`. The Guzzle library will automatically use the PECL - URI template library if it is installed. -- Url: URL parsing is now performed in `GuzzleHttp\Url::fromString` (previously - it was `Guzzle\Http\Url::factory()`). If custom URL parsing is necessary, - then developers are free to subclass `GuzzleHttp\Url`. - -## Plugin - -The `Guzzle\Plugin` namespace has been renamed to `GuzzleHttp\Subscriber`. -Several plugins are shipping with the core Guzzle library under this namespace. - -- `GuzzleHttp\Subscriber\Cookie`: Replaces the old CookiePlugin. Cookie jar - code has moved to `GuzzleHttp\Cookie`. -- `GuzzleHttp\Subscriber\History`: Replaces the old HistoryPlugin. -- `GuzzleHttp\Subscriber\HttpError`: Throws errors when a bad HTTP response is - received. -- `GuzzleHttp\Subscriber\Mock`: Replaces the old MockPlugin. -- `GuzzleHttp\Subscriber\Prepare`: Prepares the body of a request just before - sending. This subscriber is attached to all requests by default. -- `GuzzleHttp\Subscriber\Redirect`: Replaces the RedirectPlugin. - -The following plugins have been removed (third-parties are free to re-implement -these if needed): - -- `GuzzleHttp\Plugin\Async` has been removed. -- `GuzzleHttp\Plugin\CurlAuth` has been removed. -- `GuzzleHttp\Plugin\ErrorResponse\ErrorResponsePlugin` has been removed. This - functionality should instead be implemented with event listeners that occur - after normal response parsing occurs in the guzzle/command package. - -The following plugins are not part of the core Guzzle package, but are provided -in separate repositories: - -- `Guzzle\Http\Plugin\BackoffPlugin` has been rewritten to be much simpler - to build custom retry policies using simple functions rather than various - chained classes. See: https://github.com/guzzle/retry-subscriber -- `Guzzle\Http\Plugin\Cache\CachePlugin` has moved to - https://github.com/guzzle/cache-subscriber -- `Guzzle\Http\Plugin\Log\LogPlugin` has moved to - https://github.com/guzzle/log-subscriber -- `Guzzle\Http\Plugin\Md5\Md5Plugin` has moved to - https://github.com/guzzle/message-integrity-subscriber -- `Guzzle\Http\Plugin\Mock\MockPlugin` has moved to - `GuzzleHttp\Subscriber\MockSubscriber`. -- `Guzzle\Http\Plugin\Oauth\OauthPlugin` has moved to - https://github.com/guzzle/oauth-subscriber - -## Service - -The service description layer of Guzzle has moved into two separate packages: - -- http://github.com/guzzle/command Provides a high level abstraction over web - services by representing web service operations using commands. -- http://github.com/guzzle/guzzle-services Provides an implementation of - guzzle/command that provides request serialization and response parsing using - Guzzle service descriptions. - -## Stream - -Stream have moved to a separate package available at -https://github.com/guzzle/streams. - -`Guzzle\Stream\StreamInterface` has been given a large update to cleanly take -on the responsibilities of `Guzzle\Http\EntityBody` and -`Guzzle\Http\EntityBodyInterface` now that they have been removed. The number -of methods implemented by the `StreamInterface` has been drastically reduced to -allow developers to more easily extend and decorate stream behavior. - -## Removed methods from StreamInterface - -- `getStream` and `setStream` have been removed to better encapsulate streams. -- `getMetadata` and `setMetadata` have been removed in favor of - `GuzzleHttp\Stream\MetadataStreamInterface`. -- `getWrapper`, `getWrapperData`, `getStreamType`, and `getUri` have all been - removed. This data is accessible when - using streams that implement `GuzzleHttp\Stream\MetadataStreamInterface`. -- `rewind` has been removed. Use `seek(0)` for a similar behavior. - -## Renamed methods - -- `detachStream` has been renamed to `detach`. -- `feof` has been renamed to `eof`. -- `ftell` has been renamed to `tell`. -- `readLine` has moved from an instance method to a static class method of - `GuzzleHttp\Stream\Stream`. - -## Metadata streams - -`GuzzleHttp\Stream\MetadataStreamInterface` has been added to denote streams -that contain additional metadata accessible via `getMetadata()`. -`GuzzleHttp\Stream\StreamInterface::getMetadata` and -`GuzzleHttp\Stream\StreamInterface::setMetadata` have been removed. - -## StreamRequestFactory - -The entire concept of the StreamRequestFactory has been removed. The way this -was used in Guzzle 3 broke the actual interface of sending streaming requests -(instead of getting back a Response, you got a StreamInterface). Streaming -PHP requests are now implemented through the `GuzzleHttp\Adapter\StreamAdapter`. - -3.6 to 3.7 ----------- - -### Deprecations - -- You can now enable E_USER_DEPRECATED warnings to see if you are using any deprecated methods.: - -```php -\Guzzle\Common\Version::$emitWarnings = true; -``` - -The following APIs and options have been marked as deprecated: - -- Marked `Guzzle\Http\Message\Request::isResponseBodyRepeatable()` as deprecated. Use `$request->getResponseBody()->isRepeatable()` instead. -- Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead. -- Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead. -- Marked `Guzzle\Http\Message\Request::setIsRedirect()` as deprecated. Use the HistoryPlugin instead. -- Marked `Guzzle\Http\Message\Request::isRedirect()` as deprecated. Use the HistoryPlugin instead. -- Marked `Guzzle\Cache\CacheAdapterFactory::factory()` as deprecated -- Marked `Guzzle\Service\Client::enableMagicMethods()` as deprecated. Magic methods can no longer be disabled on a Guzzle\Service\Client. -- Marked `Guzzle\Parser\Url\UrlParser` as deprecated. Just use PHP's `parse_url()` and percent encode your UTF-8. -- Marked `Guzzle\Common\Collection::inject()` as deprecated. -- Marked `Guzzle\Plugin\CurlAuth\CurlAuthPlugin` as deprecated. Use - `$client->getConfig()->setPath('request.options/auth', array('user', 'pass', 'Basic|Digest|NTLM|Any'));` or - `$client->setDefaultOption('auth', array('user', 'pass', 'Basic|Digest|NTLM|Any'));` - -3.7 introduces `request.options` as a parameter for a client configuration and as an optional argument to all creational -request methods. When paired with a client's configuration settings, these options allow you to specify default settings -for various aspects of a request. Because these options make other previous configuration options redundant, several -configuration options and methods of a client and AbstractCommand have been deprecated. - -- Marked `Guzzle\Service\Client::getDefaultHeaders()` as deprecated. Use `$client->getDefaultOption('headers')`. -- Marked `Guzzle\Service\Client::setDefaultHeaders()` as deprecated. Use `$client->setDefaultOption('headers/{header_name}', 'value')`. -- Marked 'request.params' for `Guzzle\Http\Client` as deprecated. Use `$client->setDefaultOption('params/{param_name}', 'value')` -- Marked 'command.headers', 'command.response_body' and 'command.on_complete' as deprecated for AbstractCommand. These will work through Guzzle 4.0 - - $command = $client->getCommand('foo', array( - 'command.headers' => array('Test' => '123'), - 'command.response_body' => '/path/to/file' - )); - - // Should be changed to: - - $command = $client->getCommand('foo', array( - 'command.request_options' => array( - 'headers' => array('Test' => '123'), - 'save_as' => '/path/to/file' - ) - )); - -### Interface changes - -Additions and changes (you will need to update any implementations or subclasses you may have created): - -- Added an `$options` argument to the end of the following methods of `Guzzle\Http\ClientInterface`: - createRequest, head, delete, put, patch, post, options, prepareRequest -- Added an `$options` argument to the end of `Guzzle\Http\Message\Request\RequestFactoryInterface::createRequest()` -- Added an `applyOptions()` method to `Guzzle\Http\Message\Request\RequestFactoryInterface` -- Changed `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $body = null)` to - `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $options = array())`. You can still pass in a - resource, string, or EntityBody into the $options parameter to specify the download location of the response. -- Changed `Guzzle\Common\Collection::__construct($data)` to no longer accepts a null value for `$data` but a - default `array()` -- Added `Guzzle\Stream\StreamInterface::isRepeatable` -- Made `Guzzle\Http\Client::expandTemplate` and `getUriTemplate` protected methods. - -The following methods were removed from interfaces. All of these methods are still available in the concrete classes -that implement them, but you should update your code to use alternative methods: - -- Removed `Guzzle\Http\ClientInterface::setDefaultHeaders(). Use - `$client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`. or - `$client->getConfig()->setPath('request.options/headers', array('header_name' => 'value'))` or - `$client->setDefaultOption('headers/{header_name}', 'value')`. or - `$client->setDefaultOption('headers', array('header_name' => 'value'))`. -- Removed `Guzzle\Http\ClientInterface::getDefaultHeaders(). Use `$client->getConfig()->getPath('request.options/headers')`. -- Removed `Guzzle\Http\ClientInterface::expandTemplate()`. This is an implementation detail. -- Removed `Guzzle\Http\ClientInterface::setRequestFactory()`. This is an implementation detail. -- Removed `Guzzle\Http\ClientInterface::getCurlMulti()`. This is a very specific implementation detail. -- Removed `Guzzle\Http\Message\RequestInterface::canCache`. Use the CachePlugin. -- Removed `Guzzle\Http\Message\RequestInterface::setIsRedirect`. Use the HistoryPlugin. -- Removed `Guzzle\Http\Message\RequestInterface::isRedirect`. Use the HistoryPlugin. - -### Cache plugin breaking changes - -- CacheKeyProviderInterface and DefaultCacheKeyProvider are no longer used. All of this logic is handled in a - CacheStorageInterface. These two objects and interface will be removed in a future version. -- Always setting X-cache headers on cached responses -- Default cache TTLs are now handled by the CacheStorageInterface of a CachePlugin -- `CacheStorageInterface::cache($key, Response $response, $ttl = null)` has changed to `cache(RequestInterface - $request, Response $response);` -- `CacheStorageInterface::fetch($key)` has changed to `fetch(RequestInterface $request);` -- `CacheStorageInterface::delete($key)` has changed to `delete(RequestInterface $request);` -- Added `CacheStorageInterface::purge($url)` -- `DefaultRevalidation::__construct(CacheKeyProviderInterface $cacheKey, CacheStorageInterface $cache, CachePlugin - $plugin)` has changed to `DefaultRevalidation::__construct(CacheStorageInterface $cache, - CanCacheStrategyInterface $canCache = null)` -- Added `RevalidationInterface::shouldRevalidate(RequestInterface $request, Response $response)` - -3.5 to 3.6 ----------- - -* Mixed casing of headers are now forced to be a single consistent casing across all values for that header. -* Messages internally use a HeaderCollection object to delegate handling case-insensitive header resolution -* Removed the whole changedHeader() function system of messages because all header changes now go through addHeader(). - For example, setHeader() first removes the header using unset on a HeaderCollection and then calls addHeader(). - Keeping the Host header and URL host in sync is now handled by overriding the addHeader method in Request. -* Specific header implementations can be created for complex headers. When a message creates a header, it uses a - HeaderFactory which can map specific headers to specific header classes. There is now a Link header and - CacheControl header implementation. -* Moved getLinks() from Response to just be used on a Link header object. - -If you previously relied on Guzzle\Http\Message\Header::raw(), then you will need to update your code to use the -HeaderInterface (e.g. toArray(), getAll(), etc.). - -### Interface changes - -* Removed from interface: Guzzle\Http\ClientInterface::setUriTemplate -* Removed from interface: Guzzle\Http\ClientInterface::setCurlMulti() -* Removed Guzzle\Http\Message\Request::receivedRequestHeader() and implemented this functionality in - Guzzle\Http\Curl\RequestMediator -* Removed the optional $asString parameter from MessageInterface::getHeader(). Just cast the header to a string. -* Removed the optional $tryChunkedTransfer option from Guzzle\Http\Message\EntityEnclosingRequestInterface -* Removed the $asObjects argument from Guzzle\Http\Message\MessageInterface::getHeaders() - -### Removed deprecated functions - -* Removed Guzzle\Parser\ParserRegister::get(). Use getParser() -* Removed Guzzle\Parser\ParserRegister::set(). Use registerParser(). - -### Deprecations - -* The ability to case-insensitively search for header values -* Guzzle\Http\Message\Header::hasExactHeader -* Guzzle\Http\Message\Header::raw. Use getAll() -* Deprecated cache control specific methods on Guzzle\Http\Message\AbstractMessage. Use the CacheControl header object - instead. - -### Other changes - -* All response header helper functions return a string rather than mixing Header objects and strings inconsistently -* Removed cURL blacklist support. This is no longer necessary now that Expect, Accept, etc. are managed by Guzzle - directly via interfaces -* Removed the injecting of a request object onto a response object. The methods to get and set a request still exist - but are a no-op until removed. -* Most classes that used to require a `Guzzle\Service\Command\CommandInterface` typehint now request a - `Guzzle\Service\Command\ArrayCommandInterface`. -* Added `Guzzle\Http\Message\RequestInterface::startResponse()` to the RequestInterface to handle injecting a response - on a request while the request is still being transferred -* `Guzzle\Service\Command\CommandInterface` now extends from ToArrayInterface and ArrayAccess - -3.3 to 3.4 ----------- - -Base URLs of a client now follow the rules of https://tools.ietf.org/html/rfc3986#section-5.2.2 when merging URLs. - -3.2 to 3.3 ----------- - -### Response::getEtag() quote stripping removed - -`Guzzle\Http\Message\Response::getEtag()` no longer strips quotes around the ETag response header - -### Removed `Guzzle\Http\Utils` - -The `Guzzle\Http\Utils` class was removed. This class was only used for testing. - -### Stream wrapper and type - -`Guzzle\Stream\Stream::getWrapper()` and `Guzzle\Stream\Stream::getStreamType()` are no longer converted to lowercase. - -### curl.emit_io became emit_io - -Emitting IO events from a RequestMediator is now a parameter that must be set in a request's curl options using the -'emit_io' key. This was previously set under a request's parameters using 'curl.emit_io' - -3.1 to 3.2 ----------- - -### CurlMulti is no longer reused globally - -Before 3.2, the same CurlMulti object was reused globally for each client. This can cause issue where plugins added -to a single client can pollute requests dispatched from other clients. - -If you still wish to reuse the same CurlMulti object with each client, then you can add a listener to the -ServiceBuilder's `service_builder.create_client` event to inject a custom CurlMulti object into each client as it is -created. - -```php -$multi = new Guzzle\Http\Curl\CurlMulti(); -$builder = Guzzle\Service\Builder\ServiceBuilder::factory('/path/to/config.json'); -$builder->addListener('service_builder.create_client', function ($event) use ($multi) { - $event['client']->setCurlMulti($multi); -} -}); -``` - -### No default path - -URLs no longer have a default path value of '/' if no path was specified. - -Before: - -```php -$request = $client->get('http://www.foo.com'); -echo $request->getUrl(); -// >> http://www.foo.com/ -``` - -After: - -```php -$request = $client->get('http://www.foo.com'); -echo $request->getUrl(); -// >> http://www.foo.com -``` - -### Less verbose BadResponseException - -The exception message for `Guzzle\Http\Exception\BadResponseException` no longer contains the full HTTP request and -response information. You can, however, get access to the request and response object by calling `getRequest()` or -`getResponse()` on the exception object. - -### Query parameter aggregation - -Multi-valued query parameters are no longer aggregated using a callback function. `Guzzle\Http\Query` now has a -setAggregator() method that accepts a `Guzzle\Http\QueryAggregator\QueryAggregatorInterface` object. This object is -responsible for handling the aggregation of multi-valued query string variables into a flattened hash. - -2.8 to 3.x ----------- - -### Guzzle\Service\Inspector - -Change `\Guzzle\Service\Inspector::fromConfig` to `\Guzzle\Common\Collection::fromConfig` - -**Before** - -```php -use Guzzle\Service\Inspector; - -class YourClient extends \Guzzle\Service\Client -{ - public static function factory($config = array()) - { - $default = array(); - $required = array('base_url', 'username', 'api_key'); - $config = Inspector::fromConfig($config, $default, $required); - - $client = new self( - $config->get('base_url'), - $config->get('username'), - $config->get('api_key') - ); - $client->setConfig($config); - - $client->setDescription(ServiceDescription::factory(__DIR__ . DIRECTORY_SEPARATOR . 'client.json')); - - return $client; - } -``` - -**After** - -```php -use Guzzle\Common\Collection; - -class YourClient extends \Guzzle\Service\Client -{ - public static function factory($config = array()) - { - $default = array(); - $required = array('base_url', 'username', 'api_key'); - $config = Collection::fromConfig($config, $default, $required); - - $client = new self( - $config->get('base_url'), - $config->get('username'), - $config->get('api_key') - ); - $client->setConfig($config); - - $client->setDescription(ServiceDescription::factory(__DIR__ . DIRECTORY_SEPARATOR . 'client.json')); - - return $client; - } -``` - -### Convert XML Service Descriptions to JSON - -**Before** - -```xml -<?xml version="1.0" encoding="UTF-8"?> -<client> - <commands> - <!-- Groups --> - <command name="list_groups" method="GET" uri="groups.json"> - <doc>Get a list of groups</doc> - </command> - <command name="search_groups" method="GET" uri='search.json?query="{{query}} type:group"'> - <doc>Uses a search query to get a list of groups</doc> - <param name="query" type="string" required="true" /> - </command> - <command name="create_group" method="POST" uri="groups.json"> - <doc>Create a group</doc> - <param name="data" type="array" location="body" filters="json_encode" doc="Group JSON"/> - <param name="Content-Type" location="header" static="application/json"/> - </command> - <command name="delete_group" method="DELETE" uri="groups/{{id}}.json"> - <doc>Delete a group by ID</doc> - <param name="id" type="integer" required="true"/> - </command> - <command name="get_group" method="GET" uri="groups/{{id}}.json"> - <param name="id" type="integer" required="true"/> - </command> - <command name="update_group" method="PUT" uri="groups/{{id}}.json"> - <doc>Update a group</doc> - <param name="id" type="integer" required="true"/> - <param name="data" type="array" location="body" filters="json_encode" doc="Group JSON"/> - <param name="Content-Type" location="header" static="application/json"/> - </command> - </commands> -</client> -``` - -**After** - -```json -{ - "name": "Zendesk REST API v2", - "apiVersion": "2012-12-31", - "description":"Provides access to Zendesk views, groups, tickets, ticket fields, and users", - "operations": { - "list_groups": { - "httpMethod":"GET", - "uri": "groups.json", - "summary": "Get a list of groups" - }, - "search_groups":{ - "httpMethod":"GET", - "uri": "search.json?query=\"{query} type:group\"", - "summary": "Uses a search query to get a list of groups", - "parameters":{ - "query":{ - "location": "uri", - "description":"Zendesk Search Query", - "type": "string", - "required": true - } - } - }, - "create_group": { - "httpMethod":"POST", - "uri": "groups.json", - "summary": "Create a group", - "parameters":{ - "data": { - "type": "array", - "location": "body", - "description":"Group JSON", - "filters": "json_encode", - "required": true - }, - "Content-Type":{ - "type": "string", - "location":"header", - "static": "application/json" - } - } - }, - "delete_group": { - "httpMethod":"DELETE", - "uri": "groups/{id}.json", - "summary": "Delete a group", - "parameters":{ - "id":{ - "location": "uri", - "description":"Group to delete by ID", - "type": "integer", - "required": true - } - } - }, - "get_group": { - "httpMethod":"GET", - "uri": "groups/{id}.json", - "summary": "Get a ticket", - "parameters":{ - "id":{ - "location": "uri", - "description":"Group to get by ID", - "type": "integer", - "required": true - } - } - }, - "update_group": { - "httpMethod":"PUT", - "uri": "groups/{id}.json", - "summary": "Update a group", - "parameters":{ - "id": { - "location": "uri", - "description":"Group to update by ID", - "type": "integer", - "required": true - }, - "data": { - "type": "array", - "location": "body", - "description":"Group JSON", - "filters": "json_encode", - "required": true - }, - "Content-Type":{ - "type": "string", - "location":"header", - "static": "application/json" - } - } - } -} -``` - -### Guzzle\Service\Description\ServiceDescription - -Commands are now called Operations - -**Before** - -```php -use Guzzle\Service\Description\ServiceDescription; - -$sd = new ServiceDescription(); -$sd->getCommands(); // @returns ApiCommandInterface[] -$sd->hasCommand($name); -$sd->getCommand($name); // @returns ApiCommandInterface|null -$sd->addCommand($command); // @param ApiCommandInterface $command -``` - -**After** - -```php -use Guzzle\Service\Description\ServiceDescription; - -$sd = new ServiceDescription(); -$sd->getOperations(); // @returns OperationInterface[] -$sd->hasOperation($name); -$sd->getOperation($name); // @returns OperationInterface|null -$sd->addOperation($operation); // @param OperationInterface $operation -``` - -### Guzzle\Common\Inflection\Inflector - -Namespace is now `Guzzle\Inflection\Inflector` - -### Guzzle\Http\Plugin - -Namespace is now `Guzzle\Plugin`. Many other changes occur within this namespace and are detailed in their own sections below. - -### Guzzle\Http\Plugin\LogPlugin and Guzzle\Common\Log - -Now `Guzzle\Plugin\Log\LogPlugin` and `Guzzle\Log` respectively. - -**Before** - -```php -use Guzzle\Common\Log\ClosureLogAdapter; -use Guzzle\Http\Plugin\LogPlugin; - -/** @var \Guzzle\Http\Client */ -$client; - -// $verbosity is an integer indicating desired message verbosity level -$client->addSubscriber(new LogPlugin(new ClosureLogAdapter(function($m) { echo $m; }, $verbosity = LogPlugin::LOG_VERBOSE); -``` - -**After** - -```php -use Guzzle\Log\ClosureLogAdapter; -use Guzzle\Log\MessageFormatter; -use Guzzle\Plugin\Log\LogPlugin; - -/** @var \Guzzle\Http\Client */ -$client; - -// $format is a string indicating desired message format -- @see MessageFormatter -$client->addSubscriber(new LogPlugin(new ClosureLogAdapter(function($m) { echo $m; }, $format = MessageFormatter::DEBUG_FORMAT); -``` - -### Guzzle\Http\Plugin\CurlAuthPlugin - -Now `Guzzle\Plugin\CurlAuth\CurlAuthPlugin`. - -### Guzzle\Http\Plugin\ExponentialBackoffPlugin - -Now `Guzzle\Plugin\Backoff\BackoffPlugin`, and other changes. - -**Before** - -```php -use Guzzle\Http\Plugin\ExponentialBackoffPlugin; - -$backoffPlugin = new ExponentialBackoffPlugin($maxRetries, array_merge( - ExponentialBackoffPlugin::getDefaultFailureCodes(), array(429) - )); - -$client->addSubscriber($backoffPlugin); -``` - -**After** - -```php -use Guzzle\Plugin\Backoff\BackoffPlugin; -use Guzzle\Plugin\Backoff\HttpBackoffStrategy; - -// Use convenient factory method instead -- see implementation for ideas of what -// you can do with chaining backoff strategies -$backoffPlugin = BackoffPlugin::getExponentialBackoff($maxRetries, array_merge( - HttpBackoffStrategy::getDefaultFailureCodes(), array(429) - )); -$client->addSubscriber($backoffPlugin); -``` - -### Known Issues - -#### [BUG] Accept-Encoding header behavior changed unintentionally. - -(See #217) (Fixed in 09daeb8c666fb44499a0646d655a8ae36456575e) - -In version 2.8 setting the `Accept-Encoding` header would set the CURLOPT_ENCODING option, which permitted cURL to -properly handle gzip/deflate compressed responses from the server. In versions affected by this bug this does not happen. -See issue #217 for a workaround, or use a version containing the fix. diff --git a/lib/guzzlehttp/guzzle/composer.json b/lib/guzzlehttp/guzzle/composer.json deleted file mode 100644 index 3207f8c3a..000000000 --- a/lib/guzzlehttp/guzzle/composer.json +++ /dev/null @@ -1,103 +0,0 @@ -{ - "name": "guzzlehttp/guzzle", - "description": "Guzzle is a PHP HTTP client library", - "keywords": [ - "framework", - "http", - "rest", - "web service", - "curl", - "client", - "HTTP client", - "PSR-7", - "PSR-18" - ], - "license": "MIT", - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - }, - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Jeremy Lindblom", - "email": "jeremeamia@gmail.com", - "homepage": "https://github.com/jeremeamia" - }, - { - "name": "George Mponos", - "email": "gmponos@gmail.com", - "homepage": "https://github.com/gmponos" - }, - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/Nyholm" - }, - { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com", - "homepage": "https://github.com/sagikazarmark" - }, - { - "name": "Tobias Schultze", - "email": "webmaster@tubo-world.de", - "homepage": "https://github.com/Tobion" - } - ], - "require": { - "php": "^7.2.5 || ^8.0", - "ext-json": "*", - "guzzlehttp/promises": "^1.5.3 || ^2.0", - "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", - "psr/http-client": "^1.0", - "symfony/deprecation-contracts": "^2.2 || ^3.0" - }, - "provide": { - "psr/http-client-implementation": "1.0" - }, - "require-dev": { - "ext-curl": "*", - "bamarni/composer-bin-plugin": "^1.8.1", - "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", - "php-http/message-factory": "^1.1", - "phpunit/phpunit": "^8.5.29 || ^9.5.23", - "psr/log": "^1.1 || ^2.0 || ^3.0" - }, - "suggest": { - "ext-curl": "Required for CURL handler support", - "ext-intl": "Required for Internationalized Domain Name (IDN) support", - "psr/log": "Required for using the Log middleware" - }, - "config": { - "allow-plugins": { - "bamarni/composer-bin-plugin": true - }, - "preferred-install": "dist", - "sort-packages": true - }, - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "autoload-dev": { - "psr-4": { - "GuzzleHttp\\Tests\\": "tests/" - } - } -} diff --git a/lib/guzzlehttp/guzzle/src/BodySummarizer.php b/lib/guzzlehttp/guzzle/src/BodySummarizer.php deleted file mode 100644 index 6eca94ef9..000000000 --- a/lib/guzzlehttp/guzzle/src/BodySummarizer.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php - -namespace GuzzleHttp; - -use Psr\Http\Message\MessageInterface; - -final class BodySummarizer implements BodySummarizerInterface -{ - /** - * @var int|null - */ - private $truncateAt; - - public function __construct(int $truncateAt = null) - { - $this->truncateAt = $truncateAt; - } - - /** - * Returns a summarized message body. - */ - public function summarize(MessageInterface $message): ?string - { - return $this->truncateAt === null - ? \GuzzleHttp\Psr7\Message::bodySummary($message) - : \GuzzleHttp\Psr7\Message::bodySummary($message, $this->truncateAt); - } -} diff --git a/lib/guzzlehttp/guzzle/src/BodySummarizerInterface.php b/lib/guzzlehttp/guzzle/src/BodySummarizerInterface.php deleted file mode 100644 index 3e02e036e..000000000 --- a/lib/guzzlehttp/guzzle/src/BodySummarizerInterface.php +++ /dev/null @@ -1,13 +0,0 @@ -<?php - -namespace GuzzleHttp; - -use Psr\Http\Message\MessageInterface; - -interface BodySummarizerInterface -{ - /** - * Returns a summarized message body. - */ - public function summarize(MessageInterface $message): ?string; -} diff --git a/lib/guzzlehttp/guzzle/src/Client.php b/lib/guzzlehttp/guzzle/src/Client.php deleted file mode 100644 index 9b0d71070..000000000 --- a/lib/guzzlehttp/guzzle/src/Client.php +++ /dev/null @@ -1,483 +0,0 @@ -<?php - -namespace GuzzleHttp; - -use GuzzleHttp\Cookie\CookieJar; -use GuzzleHttp\Exception\GuzzleException; -use GuzzleHttp\Exception\InvalidArgumentException; -use GuzzleHttp\Promise as P; -use GuzzleHttp\Promise\PromiseInterface; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\UriInterface; - -/** - * @final - */ -class Client implements ClientInterface, \Psr\Http\Client\ClientInterface -{ - use ClientTrait; - - /** - * @var array Default request options - */ - private $config; - - /** - * Clients accept an array of constructor parameters. - * - * Here's an example of creating a client using a base_uri and an array of - * default request options to apply to each request: - * - * $client = new Client([ - * 'base_uri' => 'http://www.foo.com/1.0/', - * 'timeout' => 0, - * 'allow_redirects' => false, - * 'proxy' => '192.168.16.1:10' - * ]); - * - * Client configuration settings include the following options: - * - * - handler: (callable) Function that transfers HTTP requests over the - * wire. The function is called with a Psr7\Http\Message\RequestInterface - * and array of transfer options, and must return a - * GuzzleHttp\Promise\PromiseInterface that is fulfilled with a - * Psr7\Http\Message\ResponseInterface on success. - * If no handler is provided, a default handler will be created - * that enables all of the request options below by attaching all of the - * default middleware to the handler. - * - base_uri: (string|UriInterface) Base URI of the client that is merged - * into relative URIs. Can be a string or instance of UriInterface. - * - **: any request option - * - * @param array $config Client configuration settings. - * - * @see \GuzzleHttp\RequestOptions for a list of available request options. - */ - public function __construct(array $config = []) - { - if (!isset($config['handler'])) { - $config['handler'] = HandlerStack::create(); - } elseif (!\is_callable($config['handler'])) { - throw new InvalidArgumentException('handler must be a callable'); - } - - // Convert the base_uri to a UriInterface - if (isset($config['base_uri'])) { - $config['base_uri'] = Psr7\Utils::uriFor($config['base_uri']); - } - - $this->configureDefaults($config); - } - - /** - * @param string $method - * @param array $args - * - * @return PromiseInterface|ResponseInterface - * - * @deprecated Client::__call will be removed in guzzlehttp/guzzle:8.0. - */ - public function __call($method, $args) - { - if (\count($args) < 1) { - throw new InvalidArgumentException('Magic request methods require a URI and optional options array'); - } - - $uri = $args[0]; - $opts = $args[1] ?? []; - - return \substr($method, -5) === 'Async' - ? $this->requestAsync(\substr($method, 0, -5), $uri, $opts) - : $this->request($method, $uri, $opts); - } - - /** - * Asynchronously send an HTTP request. - * - * @param array $options Request options to apply to the given - * request and to the transfer. See \GuzzleHttp\RequestOptions. - */ - public function sendAsync(RequestInterface $request, array $options = []): PromiseInterface - { - // Merge the base URI into the request URI if needed. - $options = $this->prepareDefaults($options); - - return $this->transfer( - $request->withUri($this->buildUri($request->getUri(), $options), $request->hasHeader('Host')), - $options - ); - } - - /** - * Send an HTTP request. - * - * @param array $options Request options to apply to the given - * request and to the transfer. See \GuzzleHttp\RequestOptions. - * - * @throws GuzzleException - */ - public function send(RequestInterface $request, array $options = []): ResponseInterface - { - $options[RequestOptions::SYNCHRONOUS] = true; - - return $this->sendAsync($request, $options)->wait(); - } - - /** - * The HttpClient PSR (PSR-18) specify this method. - * - * {@inheritDoc} - */ - public function sendRequest(RequestInterface $request): ResponseInterface - { - $options[RequestOptions::SYNCHRONOUS] = true; - $options[RequestOptions::ALLOW_REDIRECTS] = false; - $options[RequestOptions::HTTP_ERRORS] = false; - - return $this->sendAsync($request, $options)->wait(); - } - - /** - * Create and send an asynchronous HTTP request. - * - * Use an absolute path to override the base path of the client, or a - * relative path to append to the base path of the client. The URL can - * contain the query string as well. Use an array to provide a URL - * template and additional variables to use in the URL template expansion. - * - * @param string $method HTTP method - * @param string|UriInterface $uri URI object or string. - * @param array $options Request options to apply. See \GuzzleHttp\RequestOptions. - */ - public function requestAsync(string $method, $uri = '', array $options = []): PromiseInterface - { - $options = $this->prepareDefaults($options); - // Remove request modifying parameter because it can be done up-front. - $headers = $options['headers'] ?? []; - $body = $options['body'] ?? null; - $version = $options['version'] ?? '1.1'; - // Merge the URI into the base URI. - $uri = $this->buildUri(Psr7\Utils::uriFor($uri), $options); - if (\is_array($body)) { - throw $this->invalidBody(); - } - $request = new Psr7\Request($method, $uri, $headers, $body, $version); - // Remove the option so that they are not doubly-applied. - unset($options['headers'], $options['body'], $options['version']); - - return $this->transfer($request, $options); - } - - /** - * Create and send an HTTP request. - * - * Use an absolute path to override the base path of the client, or a - * relative path to append to the base path of the client. The URL can - * contain the query string as well. - * - * @param string $method HTTP method. - * @param string|UriInterface $uri URI object or string. - * @param array $options Request options to apply. See \GuzzleHttp\RequestOptions. - * - * @throws GuzzleException - */ - public function request(string $method, $uri = '', array $options = []): ResponseInterface - { - $options[RequestOptions::SYNCHRONOUS] = true; - - return $this->requestAsync($method, $uri, $options)->wait(); - } - - /** - * Get a client configuration option. - * - * These options include default request options of the client, a "handler" - * (if utilized by the concrete client), and a "base_uri" if utilized by - * the concrete client. - * - * @param string|null $option The config option to retrieve. - * - * @return mixed - * - * @deprecated Client::getConfig will be removed in guzzlehttp/guzzle:8.0. - */ - public function getConfig(?string $option = null) - { - return $option === null - ? $this->config - : ($this->config[$option] ?? null); - } - - private function buildUri(UriInterface $uri, array $config): UriInterface - { - if (isset($config['base_uri'])) { - $uri = Psr7\UriResolver::resolve(Psr7\Utils::uriFor($config['base_uri']), $uri); - } - - if (isset($config['idn_conversion']) && ($config['idn_conversion'] !== false)) { - $idnOptions = ($config['idn_conversion'] === true) ? \IDNA_DEFAULT : $config['idn_conversion']; - $uri = Utils::idnUriConvert($uri, $idnOptions); - } - - return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri; - } - - /** - * Configures the default options for a client. - */ - private function configureDefaults(array $config): void - { - $defaults = [ - 'allow_redirects' => RedirectMiddleware::$defaultSettings, - 'http_errors' => true, - 'decode_content' => true, - 'verify' => true, - 'cookies' => false, - 'idn_conversion' => false, - ]; - - // Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set. - - // We can only trust the HTTP_PROXY environment variable in a CLI - // process due to the fact that PHP has no reliable mechanism to - // get environment variables that start with "HTTP_". - if (\PHP_SAPI === 'cli' && ($proxy = Utils::getenv('HTTP_PROXY'))) { - $defaults['proxy']['http'] = $proxy; - } - - if ($proxy = Utils::getenv('HTTPS_PROXY')) { - $defaults['proxy']['https'] = $proxy; - } - - if ($noProxy = Utils::getenv('NO_PROXY')) { - $cleanedNoProxy = \str_replace(' ', '', $noProxy); - $defaults['proxy']['no'] = \explode(',', $cleanedNoProxy); - } - - $this->config = $config + $defaults; - - if (!empty($config['cookies']) && $config['cookies'] === true) { - $this->config['cookies'] = new CookieJar(); - } - - // Add the default user-agent header. - if (!isset($this->config['headers'])) { - $this->config['headers'] = ['User-Agent' => Utils::defaultUserAgent()]; - } else { - // Add the User-Agent header if one was not already set. - foreach (\array_keys($this->config['headers']) as $name) { - if (\strtolower($name) === 'user-agent') { - return; - } - } - $this->config['headers']['User-Agent'] = Utils::defaultUserAgent(); - } - } - - /** - * Merges default options into the array. - * - * @param array $options Options to modify by reference - */ - private function prepareDefaults(array $options): array - { - $defaults = $this->config; - - if (!empty($defaults['headers'])) { - // Default headers are only added if they are not present. - $defaults['_conditional'] = $defaults['headers']; - unset($defaults['headers']); - } - - // Special handling for headers is required as they are added as - // conditional headers and as headers passed to a request ctor. - if (\array_key_exists('headers', $options)) { - // Allows default headers to be unset. - if ($options['headers'] === null) { - $defaults['_conditional'] = []; - unset($options['headers']); - } elseif (!\is_array($options['headers'])) { - throw new InvalidArgumentException('headers must be an array'); - } - } - - // Shallow merge defaults underneath options. - $result = $options + $defaults; - - // Remove null values. - foreach ($result as $k => $v) { - if ($v === null) { - unset($result[$k]); - } - } - - return $result; - } - - /** - * Transfers the given request and applies request options. - * - * The URI of the request is not modified and the request options are used - * as-is without merging in default options. - * - * @param array $options See \GuzzleHttp\RequestOptions. - */ - private function transfer(RequestInterface $request, array $options): PromiseInterface - { - $request = $this->applyOptions($request, $options); - /** @var HandlerStack $handler */ - $handler = $options['handler']; - - try { - return P\Create::promiseFor($handler($request, $options)); - } catch (\Exception $e) { - return P\Create::rejectionFor($e); - } - } - - /** - * Applies the array of request options to a request. - */ - private function applyOptions(RequestInterface $request, array &$options): RequestInterface - { - $modify = [ - 'set_headers' => [], - ]; - - if (isset($options['headers'])) { - if (array_keys($options['headers']) === range(0, count($options['headers']) - 1)) { - throw new InvalidArgumentException('The headers array must have header name as keys.'); - } - $modify['set_headers'] = $options['headers']; - unset($options['headers']); - } - - if (isset($options['form_params'])) { - if (isset($options['multipart'])) { - throw new InvalidArgumentException('You cannot use ' - .'form_params and multipart at the same time. Use the ' - .'form_params option if you want to send application/' - .'x-www-form-urlencoded requests, and the multipart ' - .'option to send multipart/form-data requests.'); - } - $options['body'] = \http_build_query($options['form_params'], '', '&'); - unset($options['form_params']); - // Ensure that we don't have the header in different case and set the new value. - $options['_conditional'] = Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']); - $options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded'; - } - - if (isset($options['multipart'])) { - $options['body'] = new Psr7\MultipartStream($options['multipart']); - unset($options['multipart']); - } - - if (isset($options['json'])) { - $options['body'] = Utils::jsonEncode($options['json']); - unset($options['json']); - // Ensure that we don't have the header in different case and set the new value. - $options['_conditional'] = Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']); - $options['_conditional']['Content-Type'] = 'application/json'; - } - - if (!empty($options['decode_content']) - && $options['decode_content'] !== true - ) { - // Ensure that we don't have the header in different case and set the new value. - $options['_conditional'] = Psr7\Utils::caselessRemove(['Accept-Encoding'], $options['_conditional']); - $modify['set_headers']['Accept-Encoding'] = $options['decode_content']; - } - - if (isset($options['body'])) { - if (\is_array($options['body'])) { - throw $this->invalidBody(); - } - $modify['body'] = Psr7\Utils::streamFor($options['body']); - unset($options['body']); - } - - if (!empty($options['auth']) && \is_array($options['auth'])) { - $value = $options['auth']; - $type = isset($value[2]) ? \strtolower($value[2]) : 'basic'; - switch ($type) { - case 'basic': - // Ensure that we don't have the header in different case and set the new value. - $modify['set_headers'] = Psr7\Utils::caselessRemove(['Authorization'], $modify['set_headers']); - $modify['set_headers']['Authorization'] = 'Basic ' - .\base64_encode("$value[0]:$value[1]"); - break; - case 'digest': - // @todo: Do not rely on curl - $options['curl'][\CURLOPT_HTTPAUTH] = \CURLAUTH_DIGEST; - $options['curl'][\CURLOPT_USERPWD] = "$value[0]:$value[1]"; - break; - case 'ntlm': - $options['curl'][\CURLOPT_HTTPAUTH] = \CURLAUTH_NTLM; - $options['curl'][\CURLOPT_USERPWD] = "$value[0]:$value[1]"; - break; - } - } - - if (isset($options['query'])) { - $value = $options['query']; - if (\is_array($value)) { - $value = \http_build_query($value, '', '&', \PHP_QUERY_RFC3986); - } - if (!\is_string($value)) { - throw new InvalidArgumentException('query must be a string or array'); - } - $modify['query'] = $value; - unset($options['query']); - } - - // Ensure that sink is not an invalid value. - if (isset($options['sink'])) { - // TODO: Add more sink validation? - if (\is_bool($options['sink'])) { - throw new InvalidArgumentException('sink must not be a boolean'); - } - } - - if (isset($options['version'])) { - $modify['version'] = $options['version']; - } - - $request = Psr7\Utils::modifyRequest($request, $modify); - if ($request->getBody() instanceof Psr7\MultipartStream) { - // Use a multipart/form-data POST if a Content-Type is not set. - // Ensure that we don't have the header in different case and set the new value. - $options['_conditional'] = Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']); - $options['_conditional']['Content-Type'] = 'multipart/form-data; boundary=' - .$request->getBody()->getBoundary(); - } - - // Merge in conditional headers if they are not present. - if (isset($options['_conditional'])) { - // Build up the changes so it's in a single clone of the message. - $modify = []; - foreach ($options['_conditional'] as $k => $v) { - if (!$request->hasHeader($k)) { - $modify['set_headers'][$k] = $v; - } - } - $request = Psr7\Utils::modifyRequest($request, $modify); - // Don't pass this internal value along to middleware/handlers. - unset($options['_conditional']); - } - - return $request; - } - - /** - * Return an InvalidArgumentException with pre-set message. - */ - private function invalidBody(): InvalidArgumentException - { - return new InvalidArgumentException('Passing in the "body" request ' - .'option as an array to send a request is not supported. ' - .'Please use the "form_params" request option to send a ' - .'application/x-www-form-urlencoded request, or the "multipart" ' - .'request option to send a multipart/form-data request.'); - } -} diff --git a/lib/guzzlehttp/guzzle/src/ClientInterface.php b/lib/guzzlehttp/guzzle/src/ClientInterface.php deleted file mode 100644 index 6aaee61af..000000000 --- a/lib/guzzlehttp/guzzle/src/ClientInterface.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php - -namespace GuzzleHttp; - -use GuzzleHttp\Exception\GuzzleException; -use GuzzleHttp\Promise\PromiseInterface; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\UriInterface; - -/** - * Client interface for sending HTTP requests. - */ -interface ClientInterface -{ - /** - * The Guzzle major version. - */ - public const MAJOR_VERSION = 7; - - /** - * Send an HTTP request. - * - * @param RequestInterface $request Request to send - * @param array $options Request options to apply to the given - * request and to the transfer. - * - * @throws GuzzleException - */ - public function send(RequestInterface $request, array $options = []): ResponseInterface; - - /** - * Asynchronously send an HTTP request. - * - * @param RequestInterface $request Request to send - * @param array $options Request options to apply to the given - * request and to the transfer. - */ - public function sendAsync(RequestInterface $request, array $options = []): PromiseInterface; - - /** - * Create and send an HTTP request. - * - * Use an absolute path to override the base path of the client, or a - * relative path to append to the base path of the client. The URL can - * contain the query string as well. - * - * @param string $method HTTP method. - * @param string|UriInterface $uri URI object or string. - * @param array $options Request options to apply. - * - * @throws GuzzleException - */ - public function request(string $method, $uri, array $options = []): ResponseInterface; - - /** - * Create and send an asynchronous HTTP request. - * - * Use an absolute path to override the base path of the client, or a - * relative path to append to the base path of the client. The URL can - * contain the query string as well. Use an array to provide a URL - * template and additional variables to use in the URL template expansion. - * - * @param string $method HTTP method - * @param string|UriInterface $uri URI object or string. - * @param array $options Request options to apply. - */ - public function requestAsync(string $method, $uri, array $options = []): PromiseInterface; - - /** - * Get a client configuration option. - * - * These options include default request options of the client, a "handler" - * (if utilized by the concrete client), and a "base_uri" if utilized by - * the concrete client. - * - * @param string|null $option The config option to retrieve. - * - * @return mixed - * - * @deprecated ClientInterface::getConfig will be removed in guzzlehttp/guzzle:8.0. - */ - public function getConfig(?string $option = null); -} diff --git a/lib/guzzlehttp/guzzle/src/ClientTrait.php b/lib/guzzlehttp/guzzle/src/ClientTrait.php deleted file mode 100644 index c584c76cb..000000000 --- a/lib/guzzlehttp/guzzle/src/ClientTrait.php +++ /dev/null @@ -1,241 +0,0 @@ -<?php - -namespace GuzzleHttp; - -use GuzzleHttp\Exception\GuzzleException; -use GuzzleHttp\Promise\PromiseInterface; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\UriInterface; - -/** - * Client interface for sending HTTP requests. - */ -trait ClientTrait -{ - /** - * Create and send an HTTP request. - * - * Use an absolute path to override the base path of the client, or a - * relative path to append to the base path of the client. The URL can - * contain the query string as well. - * - * @param string $method HTTP method. - * @param string|UriInterface $uri URI object or string. - * @param array $options Request options to apply. - * - * @throws GuzzleException - */ - abstract public function request(string $method, $uri, array $options = []): ResponseInterface; - - /** - * Create and send an HTTP GET request. - * - * Use an absolute path to override the base path of the client, or a - * relative path to append to the base path of the client. The URL can - * contain the query string as well. - * - * @param string|UriInterface $uri URI object or string. - * @param array $options Request options to apply. - * - * @throws GuzzleException - */ - public function get($uri, array $options = []): ResponseInterface - { - return $this->request('GET', $uri, $options); - } - - /** - * Create and send an HTTP HEAD request. - * - * Use an absolute path to override the base path of the client, or a - * relative path to append to the base path of the client. The URL can - * contain the query string as well. - * - * @param string|UriInterface $uri URI object or string. - * @param array $options Request options to apply. - * - * @throws GuzzleException - */ - public function head($uri, array $options = []): ResponseInterface - { - return $this->request('HEAD', $uri, $options); - } - - /** - * Create and send an HTTP PUT request. - * - * Use an absolute path to override the base path of the client, or a - * relative path to append to the base path of the client. The URL can - * contain the query string as well. - * - * @param string|UriInterface $uri URI object or string. - * @param array $options Request options to apply. - * - * @throws GuzzleException - */ - public function put($uri, array $options = []): ResponseInterface - { - return $this->request('PUT', $uri, $options); - } - - /** - * Create and send an HTTP POST request. - * - * Use an absolute path to override the base path of the client, or a - * relative path to append to the base path of the client. The URL can - * contain the query string as well. - * - * @param string|UriInterface $uri URI object or string. - * @param array $options Request options to apply. - * - * @throws GuzzleException - */ - public function post($uri, array $options = []): ResponseInterface - { - return $this->request('POST', $uri, $options); - } - - /** - * Create and send an HTTP PATCH request. - * - * Use an absolute path to override the base path of the client, or a - * relative path to append to the base path of the client. The URL can - * contain the query string as well. - * - * @param string|UriInterface $uri URI object or string. - * @param array $options Request options to apply. - * - * @throws GuzzleException - */ - public function patch($uri, array $options = []): ResponseInterface - { - return $this->request('PATCH', $uri, $options); - } - - /** - * Create and send an HTTP DELETE request. - * - * Use an absolute path to override the base path of the client, or a - * relative path to append to the base path of the client. The URL can - * contain the query string as well. - * - * @param string|UriInterface $uri URI object or string. - * @param array $options Request options to apply. - * - * @throws GuzzleException - */ - public function delete($uri, array $options = []): ResponseInterface - { - return $this->request('DELETE', $uri, $options); - } - - /** - * Create and send an asynchronous HTTP request. - * - * Use an absolute path to override the base path of the client, or a - * relative path to append to the base path of the client. The URL can - * contain the query string as well. Use an array to provide a URL - * template and additional variables to use in the URL template expansion. - * - * @param string $method HTTP method - * @param string|UriInterface $uri URI object or string. - * @param array $options Request options to apply. - */ - abstract public function requestAsync(string $method, $uri, array $options = []): PromiseInterface; - - /** - * Create and send an asynchronous HTTP GET request. - * - * Use an absolute path to override the base path of the client, or a - * relative path to append to the base path of the client. The URL can - * contain the query string as well. Use an array to provide a URL - * template and additional variables to use in the URL template expansion. - * - * @param string|UriInterface $uri URI object or string. - * @param array $options Request options to apply. - */ - public function getAsync($uri, array $options = []): PromiseInterface - { - return $this->requestAsync('GET', $uri, $options); - } - - /** - * Create and send an asynchronous HTTP HEAD request. - * - * Use an absolute path to override the base path of the client, or a - * relative path to append to the base path of the client. The URL can - * contain the query string as well. Use an array to provide a URL - * template and additional variables to use in the URL template expansion. - * - * @param string|UriInterface $uri URI object or string. - * @param array $options Request options to apply. - */ - public function headAsync($uri, array $options = []): PromiseInterface - { - return $this->requestAsync('HEAD', $uri, $options); - } - - /** - * Create and send an asynchronous HTTP PUT request. - * - * Use an absolute path to override the base path of the client, or a - * relative path to append to the base path of the client. The URL can - * contain the query string as well. Use an array to provide a URL - * template and additional variables to use in the URL template expansion. - * - * @param string|UriInterface $uri URI object or string. - * @param array $options Request options to apply. - */ - public function putAsync($uri, array $options = []): PromiseInterface - { - return $this->requestAsync('PUT', $uri, $options); - } - - /** - * Create and send an asynchronous HTTP POST request. - * - * Use an absolute path to override the base path of the client, or a - * relative path to append to the base path of the client. The URL can - * contain the query string as well. Use an array to provide a URL - * template and additional variables to use in the URL template expansion. - * - * @param string|UriInterface $uri URI object or string. - * @param array $options Request options to apply. - */ - public function postAsync($uri, array $options = []): PromiseInterface - { - return $this->requestAsync('POST', $uri, $options); - } - - /** - * Create and send an asynchronous HTTP PATCH request. - * - * Use an absolute path to override the base path of the client, or a - * relative path to append to the base path of the client. The URL can - * contain the query string as well. Use an array to provide a URL - * template and additional variables to use in the URL template expansion. - * - * @param string|UriInterface $uri URI object or string. - * @param array $options Request options to apply. - */ - public function patchAsync($uri, array $options = []): PromiseInterface - { - return $this->requestAsync('PATCH', $uri, $options); - } - - /** - * Create and send an asynchronous HTTP DELETE request. - * - * Use an absolute path to override the base path of the client, or a - * relative path to append to the base path of the client. The URL can - * contain the query string as well. Use an array to provide a URL - * template and additional variables to use in the URL template expansion. - * - * @param string|UriInterface $uri URI object or string. - * @param array $options Request options to apply. - */ - public function deleteAsync($uri, array $options = []): PromiseInterface - { - return $this->requestAsync('DELETE', $uri, $options); - } -} diff --git a/lib/guzzlehttp/guzzle/src/Cookie/CookieJar.php b/lib/guzzlehttp/guzzle/src/Cookie/CookieJar.php deleted file mode 100644 index b4ced5a1a..000000000 --- a/lib/guzzlehttp/guzzle/src/Cookie/CookieJar.php +++ /dev/null @@ -1,319 +0,0 @@ -<?php - -namespace GuzzleHttp\Cookie; - -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; - -/** - * Cookie jar that stores cookies as an array - */ -class CookieJar implements CookieJarInterface -{ - /** - * @var SetCookie[] Loaded cookie data - */ - private $cookies = []; - - /** - * @var bool - */ - private $strictMode; - - /** - * @param bool $strictMode Set to true to throw exceptions when invalid - * cookies are added to the cookie jar. - * @param array $cookieArray Array of SetCookie objects or a hash of - * arrays that can be used with the SetCookie - * constructor - */ - public function __construct(bool $strictMode = false, array $cookieArray = []) - { - $this->strictMode = $strictMode; - - foreach ($cookieArray as $cookie) { - if (!($cookie instanceof SetCookie)) { - $cookie = new SetCookie($cookie); - } - $this->setCookie($cookie); - } - } - - /** - * Create a new Cookie jar from an associative array and domain. - * - * @param array $cookies Cookies to create the jar from - * @param string $domain Domain to set the cookies to - */ - public static function fromArray(array $cookies, string $domain): self - { - $cookieJar = new self(); - foreach ($cookies as $name => $value) { - $cookieJar->setCookie(new SetCookie([ - 'Domain' => $domain, - 'Name' => $name, - 'Value' => $value, - 'Discard' => true, - ])); - } - - return $cookieJar; - } - - /** - * Evaluate if this cookie should be persisted to storage - * that survives between requests. - * - * @param SetCookie $cookie Being evaluated. - * @param bool $allowSessionCookies If we should persist session cookies - */ - public static function shouldPersist(SetCookie $cookie, bool $allowSessionCookies = false): bool - { - if ($cookie->getExpires() || $allowSessionCookies) { - if (!$cookie->getDiscard()) { - return true; - } - } - - return false; - } - - /** - * Finds and returns the cookie based on the name - * - * @param string $name cookie name to search for - * - * @return SetCookie|null cookie that was found or null if not found - */ - public function getCookieByName(string $name): ?SetCookie - { - foreach ($this->cookies as $cookie) { - if ($cookie->getName() !== null && \strcasecmp($cookie->getName(), $name) === 0) { - return $cookie; - } - } - - return null; - } - - /** - * {@inheritDoc} - */ - public function toArray(): array - { - return \array_map(static function (SetCookie $cookie): array { - return $cookie->toArray(); - }, $this->getIterator()->getArrayCopy()); - } - - /** - * {@inheritDoc} - */ - public function clear(?string $domain = null, ?string $path = null, ?string $name = null): void - { - if (!$domain) { - $this->cookies = []; - - return; - } elseif (!$path) { - $this->cookies = \array_filter( - $this->cookies, - static function (SetCookie $cookie) use ($domain): bool { - return !$cookie->matchesDomain($domain); - } - ); - } elseif (!$name) { - $this->cookies = \array_filter( - $this->cookies, - static function (SetCookie $cookie) use ($path, $domain): bool { - return !($cookie->matchesPath($path) && - $cookie->matchesDomain($domain)); - } - ); - } else { - $this->cookies = \array_filter( - $this->cookies, - static function (SetCookie $cookie) use ($path, $domain, $name) { - return !($cookie->getName() == $name && - $cookie->matchesPath($path) && - $cookie->matchesDomain($domain)); - } - ); - } - } - - /** - * {@inheritDoc} - */ - public function clearSessionCookies(): void - { - $this->cookies = \array_filter( - $this->cookies, - static function (SetCookie $cookie): bool { - return !$cookie->getDiscard() && $cookie->getExpires(); - } - ); - } - - /** - * {@inheritDoc} - */ - public function setCookie(SetCookie $cookie): bool - { - // If the name string is empty (but not 0), ignore the set-cookie - // string entirely. - $name = $cookie->getName(); - if (!$name && $name !== '0') { - return false; - } - - // Only allow cookies with set and valid domain, name, value - $result = $cookie->validate(); - if ($result !== true) { - if ($this->strictMode) { - throw new \RuntimeException('Invalid cookie: '.$result); - } - $this->removeCookieIfEmpty($cookie); - - return false; - } - - // Resolve conflicts with previously set cookies - foreach ($this->cookies as $i => $c) { - // Two cookies are identical, when their path, and domain are - // identical. - if ($c->getPath() != $cookie->getPath() || - $c->getDomain() != $cookie->getDomain() || - $c->getName() != $cookie->getName() - ) { - continue; - } - - // The previously set cookie is a discard cookie and this one is - // not so allow the new cookie to be set - if (!$cookie->getDiscard() && $c->getDiscard()) { - unset($this->cookies[$i]); - continue; - } - - // If the new cookie's expiration is further into the future, then - // replace the old cookie - if ($cookie->getExpires() > $c->getExpires()) { - unset($this->cookies[$i]); - continue; - } - - // If the value has changed, we better change it - if ($cookie->getValue() !== $c->getValue()) { - unset($this->cookies[$i]); - continue; - } - - // The cookie exists, so no need to continue - return false; - } - - $this->cookies[] = $cookie; - - return true; - } - - public function count(): int - { - return \count($this->cookies); - } - - /** - * @return \ArrayIterator<int, SetCookie> - */ - public function getIterator(): \ArrayIterator - { - return new \ArrayIterator(\array_values($this->cookies)); - } - - public function extractCookies(RequestInterface $request, ResponseInterface $response): void - { - if ($cookieHeader = $response->getHeader('Set-Cookie')) { - foreach ($cookieHeader as $cookie) { - $sc = SetCookie::fromString($cookie); - if (!$sc->getDomain()) { - $sc->setDomain($request->getUri()->getHost()); - } - if (0 !== \strpos($sc->getPath(), '/')) { - $sc->setPath($this->getCookiePathFromRequest($request)); - } - if (!$sc->matchesDomain($request->getUri()->getHost())) { - continue; - } - // Note: At this point `$sc->getDomain()` being a public suffix should - // be rejected, but we don't want to pull in the full PSL dependency. - $this->setCookie($sc); - } - } - } - - /** - * Computes cookie path following RFC 6265 section 5.1.4 - * - * @see https://tools.ietf.org/html/rfc6265#section-5.1.4 - */ - private function getCookiePathFromRequest(RequestInterface $request): string - { - $uriPath = $request->getUri()->getPath(); - if ('' === $uriPath) { - return '/'; - } - if (0 !== \strpos($uriPath, '/')) { - return '/'; - } - if ('/' === $uriPath) { - return '/'; - } - $lastSlashPos = \strrpos($uriPath, '/'); - if (0 === $lastSlashPos || false === $lastSlashPos) { - return '/'; - } - - return \substr($uriPath, 0, $lastSlashPos); - } - - public function withCookieHeader(RequestInterface $request): RequestInterface - { - $values = []; - $uri = $request->getUri(); - $scheme = $uri->getScheme(); - $host = $uri->getHost(); - $path = $uri->getPath() ?: '/'; - - foreach ($this->cookies as $cookie) { - if ($cookie->matchesPath($path) && - $cookie->matchesDomain($host) && - !$cookie->isExpired() && - (!$cookie->getSecure() || $scheme === 'https') - ) { - $values[] = $cookie->getName().'=' - .$cookie->getValue(); - } - } - - return $values - ? $request->withHeader('Cookie', \implode('; ', $values)) - : $request; - } - - /** - * If a cookie already exists and the server asks to set it again with a - * null value, the cookie must be deleted. - */ - private function removeCookieIfEmpty(SetCookie $cookie): void - { - $cookieValue = $cookie->getValue(); - if ($cookieValue === null || $cookieValue === '') { - $this->clear( - $cookie->getDomain(), - $cookie->getPath(), - $cookie->getName() - ); - } - } -} diff --git a/lib/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php b/lib/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php deleted file mode 100644 index 50bc36398..000000000 --- a/lib/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php +++ /dev/null @@ -1,79 +0,0 @@ -<?php - -namespace GuzzleHttp\Cookie; - -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; - -/** - * Stores HTTP cookies. - * - * It extracts cookies from HTTP requests, and returns them in HTTP responses. - * CookieJarInterface instances automatically expire contained cookies when - * necessary. Subclasses are also responsible for storing and retrieving - * cookies from a file, database, etc. - * - * @see https://docs.python.org/2/library/cookielib.html Inspiration - * @extends \IteratorAggregate<SetCookie> - */ -interface CookieJarInterface extends \Countable, \IteratorAggregate -{ - /** - * Create a request with added cookie headers. - * - * If no matching cookies are found in the cookie jar, then no Cookie - * header is added to the request and the same request is returned. - * - * @param RequestInterface $request Request object to modify. - * - * @return RequestInterface returns the modified request. - */ - public function withCookieHeader(RequestInterface $request): RequestInterface; - - /** - * Extract cookies from an HTTP response and store them in the CookieJar. - * - * @param RequestInterface $request Request that was sent - * @param ResponseInterface $response Response that was received - */ - public function extractCookies(RequestInterface $request, ResponseInterface $response): void; - - /** - * Sets a cookie in the cookie jar. - * - * @param SetCookie $cookie Cookie to set. - * - * @return bool Returns true on success or false on failure - */ - public function setCookie(SetCookie $cookie): bool; - - /** - * Remove cookies currently held in the cookie jar. - * - * Invoking this method without arguments will empty the whole cookie jar. - * If given a $domain argument only cookies belonging to that domain will - * be removed. If given a $domain and $path argument, cookies belonging to - * the specified path within that domain are removed. If given all three - * arguments, then the cookie with the specified name, path and domain is - * removed. - * - * @param string|null $domain Clears cookies matching a domain - * @param string|null $path Clears cookies matching a domain and path - * @param string|null $name Clears cookies matching a domain, path, and name - */ - public function clear(?string $domain = null, ?string $path = null, ?string $name = null): void; - - /** - * Discard all sessions cookies. - * - * Removes cookies that don't have an expire field or a have a discard - * field set to true. To be called when the user agent shuts down according - * to RFC 2965. - */ - public function clearSessionCookies(): void; - - /** - * Converts the cookie jar to an array. - */ - public function toArray(): array; -} diff --git a/lib/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php b/lib/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php deleted file mode 100644 index 290236d54..000000000 --- a/lib/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php +++ /dev/null @@ -1,101 +0,0 @@ -<?php - -namespace GuzzleHttp\Cookie; - -use GuzzleHttp\Utils; - -/** - * Persists non-session cookies using a JSON formatted file - */ -class FileCookieJar extends CookieJar -{ - /** - * @var string filename - */ - private $filename; - - /** - * @var bool Control whether to persist session cookies or not. - */ - private $storeSessionCookies; - - /** - * Create a new FileCookieJar object - * - * @param string $cookieFile File to store the cookie data - * @param bool $storeSessionCookies Set to true to store session cookies - * in the cookie jar. - * - * @throws \RuntimeException if the file cannot be found or created - */ - public function __construct(string $cookieFile, bool $storeSessionCookies = false) - { - parent::__construct(); - $this->filename = $cookieFile; - $this->storeSessionCookies = $storeSessionCookies; - - if (\file_exists($cookieFile)) { - $this->load($cookieFile); - } - } - - /** - * Saves the file when shutting down - */ - public function __destruct() - { - $this->save($this->filename); - } - - /** - * Saves the cookies to a file. - * - * @param string $filename File to save - * - * @throws \RuntimeException if the file cannot be found or created - */ - public function save(string $filename): void - { - $json = []; - /** @var SetCookie $cookie */ - foreach ($this as $cookie) { - if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) { - $json[] = $cookie->toArray(); - } - } - - $jsonStr = Utils::jsonEncode($json); - if (false === \file_put_contents($filename, $jsonStr, \LOCK_EX)) { - throw new \RuntimeException("Unable to save file {$filename}"); - } - } - - /** - * Load cookies from a JSON formatted file. - * - * Old cookies are kept unless overwritten by newly loaded ones. - * - * @param string $filename Cookie file to load. - * - * @throws \RuntimeException if the file cannot be loaded. - */ - public function load(string $filename): void - { - $json = \file_get_contents($filename); - if (false === $json) { - throw new \RuntimeException("Unable to load file {$filename}"); - } - if ($json === '') { - return; - } - - $data = Utils::jsonDecode($json, true); - if (\is_array($data)) { - foreach ($data as $cookie) { - $this->setCookie(new SetCookie($cookie)); - } - } elseif (\is_scalar($data) && !empty($data)) { - throw new \RuntimeException("Invalid cookie file: {$filename}"); - } - } -} diff --git a/lib/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php b/lib/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php deleted file mode 100644 index cb3e67c6a..000000000 --- a/lib/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php - -namespace GuzzleHttp\Cookie; - -/** - * Persists cookies in the client session - */ -class SessionCookieJar extends CookieJar -{ - /** - * @var string session key - */ - private $sessionKey; - - /** - * @var bool Control whether to persist session cookies or not. - */ - private $storeSessionCookies; - - /** - * Create a new SessionCookieJar object - * - * @param string $sessionKey Session key name to store the cookie - * data in session - * @param bool $storeSessionCookies Set to true to store session cookies - * in the cookie jar. - */ - public function __construct(string $sessionKey, bool $storeSessionCookies = false) - { - parent::__construct(); - $this->sessionKey = $sessionKey; - $this->storeSessionCookies = $storeSessionCookies; - $this->load(); - } - - /** - * Saves cookies to session when shutting down - */ - public function __destruct() - { - $this->save(); - } - - /** - * Save cookies to the client session - */ - public function save(): void - { - $json = []; - /** @var SetCookie $cookie */ - foreach ($this as $cookie) { - if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) { - $json[] = $cookie->toArray(); - } - } - - $_SESSION[$this->sessionKey] = \json_encode($json); - } - - /** - * Load the contents of the client session into the data array - */ - protected function load(): void - { - if (!isset($_SESSION[$this->sessionKey])) { - return; - } - $data = \json_decode($_SESSION[$this->sessionKey], true); - if (\is_array($data)) { - foreach ($data as $cookie) { - $this->setCookie(new SetCookie($cookie)); - } - } elseif (\strlen($data)) { - throw new \RuntimeException('Invalid cookie data'); - } - } -} diff --git a/lib/guzzlehttp/guzzle/src/Cookie/SetCookie.php b/lib/guzzlehttp/guzzle/src/Cookie/SetCookie.php deleted file mode 100644 index d74915bed..000000000 --- a/lib/guzzlehttp/guzzle/src/Cookie/SetCookie.php +++ /dev/null @@ -1,488 +0,0 @@ -<?php - -namespace GuzzleHttp\Cookie; - -/** - * Set-Cookie object - */ -class SetCookie -{ - /** - * @var array - */ - private static $defaults = [ - 'Name' => null, - 'Value' => null, - 'Domain' => null, - 'Path' => '/', - 'Max-Age' => null, - 'Expires' => null, - 'Secure' => false, - 'Discard' => false, - 'HttpOnly' => false, - ]; - - /** - * @var array Cookie data - */ - private $data; - - /** - * Create a new SetCookie object from a string. - * - * @param string $cookie Set-Cookie header string - */ - public static function fromString(string $cookie): self - { - // Create the default return array - $data = self::$defaults; - // Explode the cookie string using a series of semicolons - $pieces = \array_filter(\array_map('trim', \explode(';', $cookie))); - // The name of the cookie (first kvp) must exist and include an equal sign. - if (!isset($pieces[0]) || \strpos($pieces[0], '=') === false) { - return new self($data); - } - - // Add the cookie pieces into the parsed data array - foreach ($pieces as $part) { - $cookieParts = \explode('=', $part, 2); - $key = \trim($cookieParts[0]); - $value = isset($cookieParts[1]) - ? \trim($cookieParts[1], " \n\r\t\0\x0B") - : true; - - // Only check for non-cookies when cookies have been found - if (!isset($data['Name'])) { - $data['Name'] = $key; - $data['Value'] = $value; - } else { - foreach (\array_keys(self::$defaults) as $search) { - if (!\strcasecmp($search, $key)) { - if ($search === 'Max-Age') { - if (is_numeric($value)) { - $data[$search] = (int) $value; - } - } else { - $data[$search] = $value; - } - continue 2; - } - } - $data[$key] = $value; - } - } - - return new self($data); - } - - /** - * @param array $data Array of cookie data provided by a Cookie parser - */ - public function __construct(array $data = []) - { - $this->data = self::$defaults; - - if (isset($data['Name'])) { - $this->setName($data['Name']); - } - - if (isset($data['Value'])) { - $this->setValue($data['Value']); - } - - if (isset($data['Domain'])) { - $this->setDomain($data['Domain']); - } - - if (isset($data['Path'])) { - $this->setPath($data['Path']); - } - - if (isset($data['Max-Age'])) { - $this->setMaxAge($data['Max-Age']); - } - - if (isset($data['Expires'])) { - $this->setExpires($data['Expires']); - } - - if (isset($data['Secure'])) { - $this->setSecure($data['Secure']); - } - - if (isset($data['Discard'])) { - $this->setDiscard($data['Discard']); - } - - if (isset($data['HttpOnly'])) { - $this->setHttpOnly($data['HttpOnly']); - } - - // Set the remaining values that don't have extra validation logic - foreach (array_diff(array_keys($data), array_keys(self::$defaults)) as $key) { - $this->data[$key] = $data[$key]; - } - - // Extract the Expires value and turn it into a UNIX timestamp if needed - if (!$this->getExpires() && $this->getMaxAge()) { - // Calculate the Expires date - $this->setExpires(\time() + $this->getMaxAge()); - } elseif (null !== ($expires = $this->getExpires()) && !\is_numeric($expires)) { - $this->setExpires($expires); - } - } - - public function __toString() - { - $str = $this->data['Name'].'='.($this->data['Value'] ?? '').'; '; - foreach ($this->data as $k => $v) { - if ($k !== 'Name' && $k !== 'Value' && $v !== null && $v !== false) { - if ($k === 'Expires') { - $str .= 'Expires='.\gmdate('D, d M Y H:i:s \G\M\T', $v).'; '; - } else { - $str .= ($v === true ? $k : "{$k}={$v}").'; '; - } - } - } - - return \rtrim($str, '; '); - } - - public function toArray(): array - { - return $this->data; - } - - /** - * Get the cookie name. - * - * @return string - */ - public function getName() - { - return $this->data['Name']; - } - - /** - * Set the cookie name. - * - * @param string $name Cookie name - */ - public function setName($name): void - { - if (!is_string($name)) { - trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); - } - - $this->data['Name'] = (string) $name; - } - - /** - * Get the cookie value. - * - * @return string|null - */ - public function getValue() - { - return $this->data['Value']; - } - - /** - * Set the cookie value. - * - * @param string $value Cookie value - */ - public function setValue($value): void - { - if (!is_string($value)) { - trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); - } - - $this->data['Value'] = (string) $value; - } - - /** - * Get the domain. - * - * @return string|null - */ - public function getDomain() - { - return $this->data['Domain']; - } - - /** - * Set the domain of the cookie. - * - * @param string|null $domain - */ - public function setDomain($domain): void - { - if (!is_string($domain) && null !== $domain) { - trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); - } - - $this->data['Domain'] = null === $domain ? null : (string) $domain; - } - - /** - * Get the path. - * - * @return string - */ - public function getPath() - { - return $this->data['Path']; - } - - /** - * Set the path of the cookie. - * - * @param string $path Path of the cookie - */ - public function setPath($path): void - { - if (!is_string($path)) { - trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); - } - - $this->data['Path'] = (string) $path; - } - - /** - * Maximum lifetime of the cookie in seconds. - * - * @return int|null - */ - public function getMaxAge() - { - return null === $this->data['Max-Age'] ? null : (int) $this->data['Max-Age']; - } - - /** - * Set the max-age of the cookie. - * - * @param int|null $maxAge Max age of the cookie in seconds - */ - public function setMaxAge($maxAge): void - { - if (!is_int($maxAge) && null !== $maxAge) { - trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an int or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); - } - - $this->data['Max-Age'] = $maxAge === null ? null : (int) $maxAge; - } - - /** - * The UNIX timestamp when the cookie Expires. - * - * @return string|int|null - */ - public function getExpires() - { - return $this->data['Expires']; - } - - /** - * Set the unix timestamp for which the cookie will expire. - * - * @param int|string|null $timestamp Unix timestamp or any English textual datetime description. - */ - public function setExpires($timestamp): void - { - if (!is_int($timestamp) && !is_string($timestamp) && null !== $timestamp) { - trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an int, string or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); - } - - $this->data['Expires'] = null === $timestamp ? null : (\is_numeric($timestamp) ? (int) $timestamp : \strtotime((string) $timestamp)); - } - - /** - * Get whether or not this is a secure cookie. - * - * @return bool - */ - public function getSecure() - { - return $this->data['Secure']; - } - - /** - * Set whether or not the cookie is secure. - * - * @param bool $secure Set to true or false if secure - */ - public function setSecure($secure): void - { - if (!is_bool($secure)) { - trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); - } - - $this->data['Secure'] = (bool) $secure; - } - - /** - * Get whether or not this is a session cookie. - * - * @return bool|null - */ - public function getDiscard() - { - return $this->data['Discard']; - } - - /** - * Set whether or not this is a session cookie. - * - * @param bool $discard Set to true or false if this is a session cookie - */ - public function setDiscard($discard): void - { - if (!is_bool($discard)) { - trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); - } - - $this->data['Discard'] = (bool) $discard; - } - - /** - * Get whether or not this is an HTTP only cookie. - * - * @return bool - */ - public function getHttpOnly() - { - return $this->data['HttpOnly']; - } - - /** - * Set whether or not this is an HTTP only cookie. - * - * @param bool $httpOnly Set to true or false if this is HTTP only - */ - public function setHttpOnly($httpOnly): void - { - if (!is_bool($httpOnly)) { - trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); - } - - $this->data['HttpOnly'] = (bool) $httpOnly; - } - - /** - * Check if the cookie matches a path value. - * - * A request-path path-matches a given cookie-path if at least one of - * the following conditions holds: - * - * - The cookie-path and the request-path are identical. - * - The cookie-path is a prefix of the request-path, and the last - * character of the cookie-path is %x2F ("/"). - * - The cookie-path is a prefix of the request-path, and the first - * character of the request-path that is not included in the cookie- - * path is a %x2F ("/") character. - * - * @param string $requestPath Path to check against - */ - public function matchesPath(string $requestPath): bool - { - $cookiePath = $this->getPath(); - - // Match on exact matches or when path is the default empty "/" - if ($cookiePath === '/' || $cookiePath == $requestPath) { - return true; - } - - // Ensure that the cookie-path is a prefix of the request path. - if (0 !== \strpos($requestPath, $cookiePath)) { - return false; - } - - // Match if the last character of the cookie-path is "/" - if (\substr($cookiePath, -1, 1) === '/') { - return true; - } - - // Match if the first character not included in cookie path is "/" - return \substr($requestPath, \strlen($cookiePath), 1) === '/'; - } - - /** - * Check if the cookie matches a domain value. - * - * @param string $domain Domain to check against - */ - public function matchesDomain(string $domain): bool - { - $cookieDomain = $this->getDomain(); - if (null === $cookieDomain) { - return true; - } - - // Remove the leading '.' as per spec in RFC 6265. - // https://tools.ietf.org/html/rfc6265#section-5.2.3 - $cookieDomain = \ltrim(\strtolower($cookieDomain), '.'); - - $domain = \strtolower($domain); - - // Domain not set or exact match. - if ('' === $cookieDomain || $domain === $cookieDomain) { - return true; - } - - // Matching the subdomain according to RFC 6265. - // https://tools.ietf.org/html/rfc6265#section-5.1.3 - if (\filter_var($domain, \FILTER_VALIDATE_IP)) { - return false; - } - - return (bool) \preg_match('/\.'.\preg_quote($cookieDomain, '/').'$/', $domain); - } - - /** - * Check if the cookie is expired. - */ - public function isExpired(): bool - { - return $this->getExpires() !== null && \time() > $this->getExpires(); - } - - /** - * Check if the cookie is valid according to RFC 6265. - * - * @return bool|string Returns true if valid or an error message if invalid - */ - public function validate() - { - $name = $this->getName(); - if ($name === '') { - return 'The cookie name must not be empty'; - } - - // Check if any of the invalid characters are present in the cookie name - if (\preg_match( - '/[\x00-\x20\x22\x28-\x29\x2c\x2f\x3a-\x40\x5c\x7b\x7d\x7f]/', - $name - )) { - return 'Cookie name must not contain invalid characters: ASCII ' - .'Control characters (0-31;127), space, tab and the ' - .'following characters: ()<>@,;:\"/?={}'; - } - - // Value must not be null. 0 and empty string are valid. Empty strings - // are technically against RFC 6265, but known to happen in the wild. - $value = $this->getValue(); - if ($value === null) { - return 'The cookie value must not be empty'; - } - - // Domains must not be empty, but can be 0. "0" is not a valid internet - // domain, but may be used as server name in a private network. - $domain = $this->getDomain(); - if ($domain === null || $domain === '') { - return 'The cookie domain must not be empty'; - } - - return true; - } -} diff --git a/lib/guzzlehttp/guzzle/src/Exception/BadResponseException.php b/lib/guzzlehttp/guzzle/src/Exception/BadResponseException.php deleted file mode 100644 index a80956c9d..000000000 --- a/lib/guzzlehttp/guzzle/src/Exception/BadResponseException.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -namespace GuzzleHttp\Exception; - -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; - -/** - * Exception when an HTTP error occurs (4xx or 5xx error) - */ -class BadResponseException extends RequestException -{ - public function __construct( - string $message, - RequestInterface $request, - ResponseInterface $response, - \Throwable $previous = null, - array $handlerContext = [] - ) { - parent::__construct($message, $request, $response, $previous, $handlerContext); - } - - /** - * Current exception and the ones that extend it will always have a response. - */ - public function hasResponse(): bool - { - return true; - } - - /** - * This function narrows the return type from the parent class and does not allow it to be nullable. - */ - public function getResponse(): ResponseInterface - { - /** @var ResponseInterface */ - return parent::getResponse(); - } -} diff --git a/lib/guzzlehttp/guzzle/src/Exception/ClientException.php b/lib/guzzlehttp/guzzle/src/Exception/ClientException.php deleted file mode 100644 index 12fa5e351..000000000 --- a/lib/guzzlehttp/guzzle/src/Exception/ClientException.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php - -namespace GuzzleHttp\Exception; - -/** - * Exception when a client error is encountered (4xx codes) - */ -class ClientException extends BadResponseException -{ -} diff --git a/lib/guzzlehttp/guzzle/src/Exception/ConnectException.php b/lib/guzzlehttp/guzzle/src/Exception/ConnectException.php deleted file mode 100644 index e1a31519c..000000000 --- a/lib/guzzlehttp/guzzle/src/Exception/ConnectException.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php - -namespace GuzzleHttp\Exception; - -use Psr\Http\Client\NetworkExceptionInterface; -use Psr\Http\Message\RequestInterface; - -/** - * Exception thrown when a connection cannot be established. - * - * Note that no response is present for a ConnectException - */ -class ConnectException extends TransferException implements NetworkExceptionInterface -{ - /** - * @var RequestInterface - */ - private $request; - - /** - * @var array - */ - private $handlerContext; - - public function __construct( - string $message, - RequestInterface $request, - \Throwable $previous = null, - array $handlerContext = [] - ) { - parent::__construct($message, 0, $previous); - $this->request = $request; - $this->handlerContext = $handlerContext; - } - - /** - * Get the request that caused the exception - */ - public function getRequest(): RequestInterface - { - return $this->request; - } - - /** - * Get contextual information about the error from the underlying handler. - * - * The contents of this array will vary depending on which handler you are - * using. It may also be just an empty array. Relying on this data will - * couple you to a specific handler, but can give more debug information - * when needed. - */ - public function getHandlerContext(): array - { - return $this->handlerContext; - } -} diff --git a/lib/guzzlehttp/guzzle/src/Exception/GuzzleException.php b/lib/guzzlehttp/guzzle/src/Exception/GuzzleException.php deleted file mode 100644 index fa3ed6998..000000000 --- a/lib/guzzlehttp/guzzle/src/Exception/GuzzleException.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -namespace GuzzleHttp\Exception; - -use Psr\Http\Client\ClientExceptionInterface; - -interface GuzzleException extends ClientExceptionInterface -{ -} diff --git a/lib/guzzlehttp/guzzle/src/Exception/InvalidArgumentException.php b/lib/guzzlehttp/guzzle/src/Exception/InvalidArgumentException.php deleted file mode 100644 index bfd20e232..000000000 --- a/lib/guzzlehttp/guzzle/src/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace GuzzleHttp\Exception; - -final class InvalidArgumentException extends \InvalidArgumentException implements GuzzleException -{ -} diff --git a/lib/guzzlehttp/guzzle/src/Exception/RequestException.php b/lib/guzzlehttp/guzzle/src/Exception/RequestException.php deleted file mode 100644 index c2d0a9ccc..000000000 --- a/lib/guzzlehttp/guzzle/src/Exception/RequestException.php +++ /dev/null @@ -1,166 +0,0 @@ -<?php - -namespace GuzzleHttp\Exception; - -use GuzzleHttp\BodySummarizer; -use GuzzleHttp\BodySummarizerInterface; -use Psr\Http\Client\RequestExceptionInterface; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\UriInterface; - -/** - * HTTP Request exception - */ -class RequestException extends TransferException implements RequestExceptionInterface -{ - /** - * @var RequestInterface - */ - private $request; - - /** - * @var ResponseInterface|null - */ - private $response; - - /** - * @var array - */ - private $handlerContext; - - public function __construct( - string $message, - RequestInterface $request, - ResponseInterface $response = null, - \Throwable $previous = null, - array $handlerContext = [] - ) { - // Set the code of the exception if the response is set and not future. - $code = $response ? $response->getStatusCode() : 0; - parent::__construct($message, $code, $previous); - $this->request = $request; - $this->response = $response; - $this->handlerContext = $handlerContext; - } - - /** - * Wrap non-RequestExceptions with a RequestException - */ - public static function wrapException(RequestInterface $request, \Throwable $e): RequestException - { - return $e instanceof RequestException ? $e : new RequestException($e->getMessage(), $request, null, $e); - } - - /** - * Factory method to create a new exception with a normalized error message - * - * @param RequestInterface $request Request sent - * @param ResponseInterface $response Response received - * @param \Throwable|null $previous Previous exception - * @param array $handlerContext Optional handler context - * @param BodySummarizerInterface|null $bodySummarizer Optional body summarizer - */ - public static function create( - RequestInterface $request, - ResponseInterface $response = null, - \Throwable $previous = null, - array $handlerContext = [], - BodySummarizerInterface $bodySummarizer = null - ): self { - if (!$response) { - return new self( - 'Error completing request', - $request, - null, - $previous, - $handlerContext - ); - } - - $level = (int) \floor($response->getStatusCode() / 100); - if ($level === 4) { - $label = 'Client error'; - $className = ClientException::class; - } elseif ($level === 5) { - $label = 'Server error'; - $className = ServerException::class; - } else { - $label = 'Unsuccessful request'; - $className = __CLASS__; - } - - $uri = $request->getUri(); - $uri = static::obfuscateUri($uri); - - // Client Error: `GET /` resulted in a `404 Not Found` response: - // <html> ... (truncated) - $message = \sprintf( - '%s: `%s %s` resulted in a `%s %s` response', - $label, - $request->getMethod(), - $uri->__toString(), - $response->getStatusCode(), - $response->getReasonPhrase() - ); - - $summary = ($bodySummarizer ?? new BodySummarizer())->summarize($response); - - if ($summary !== null) { - $message .= ":\n{$summary}\n"; - } - - return new $className($message, $request, $response, $previous, $handlerContext); - } - - /** - * Obfuscates URI if there is a username and a password present - */ - private static function obfuscateUri(UriInterface $uri): UriInterface - { - $userInfo = $uri->getUserInfo(); - - if (false !== ($pos = \strpos($userInfo, ':'))) { - return $uri->withUserInfo(\substr($userInfo, 0, $pos), '***'); - } - - return $uri; - } - - /** - * Get the request that caused the exception - */ - public function getRequest(): RequestInterface - { - return $this->request; - } - - /** - * Get the associated response - */ - public function getResponse(): ?ResponseInterface - { - return $this->response; - } - - /** - * Check if a response was received - */ - public function hasResponse(): bool - { - return $this->response !== null; - } - - /** - * Get contextual information about the error from the underlying handler. - * - * The contents of this array will vary depending on which handler you are - * using. It may also be just an empty array. Relying on this data will - * couple you to a specific handler, but can give more debug information - * when needed. - */ - public function getHandlerContext(): array - { - return $this->handlerContext; - } -} diff --git a/lib/guzzlehttp/guzzle/src/Exception/ServerException.php b/lib/guzzlehttp/guzzle/src/Exception/ServerException.php deleted file mode 100644 index 8055e067c..000000000 --- a/lib/guzzlehttp/guzzle/src/Exception/ServerException.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php - -namespace GuzzleHttp\Exception; - -/** - * Exception when a server error is encountered (5xx codes) - */ -class ServerException extends BadResponseException -{ -} diff --git a/lib/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php b/lib/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php deleted file mode 100644 index fad3a57cf..000000000 --- a/lib/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace GuzzleHttp\Exception; - -class TooManyRedirectsException extends RequestException -{ -} diff --git a/lib/guzzlehttp/guzzle/src/Exception/TransferException.php b/lib/guzzlehttp/guzzle/src/Exception/TransferException.php deleted file mode 100644 index 507633608..000000000 --- a/lib/guzzlehttp/guzzle/src/Exception/TransferException.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace GuzzleHttp\Exception; - -class TransferException extends \RuntimeException implements GuzzleException -{ -} diff --git a/lib/guzzlehttp/guzzle/src/Handler/CurlFactory.php b/lib/guzzlehttp/guzzle/src/Handler/CurlFactory.php deleted file mode 100644 index 3a6a8db26..000000000 --- a/lib/guzzlehttp/guzzle/src/Handler/CurlFactory.php +++ /dev/null @@ -1,630 +0,0 @@ -<?php - -namespace GuzzleHttp\Handler; - -use GuzzleHttp\Exception\ConnectException; -use GuzzleHttp\Exception\RequestException; -use GuzzleHttp\Promise as P; -use GuzzleHttp\Promise\FulfilledPromise; -use GuzzleHttp\Promise\PromiseInterface; -use GuzzleHttp\Psr7\LazyOpenStream; -use GuzzleHttp\TransferStats; -use GuzzleHttp\Utils; -use Psr\Http\Message\RequestInterface; - -/** - * Creates curl resources from a request - * - * @final - */ -class CurlFactory implements CurlFactoryInterface -{ - public const CURL_VERSION_STR = 'curl_version'; - - /** - * @deprecated - */ - public const LOW_CURL_VERSION_NUMBER = '7.21.2'; - - /** - * @var resource[]|\CurlHandle[] - */ - private $handles = []; - - /** - * @var int Total number of idle handles to keep in cache - */ - private $maxHandles; - - /** - * @param int $maxHandles Maximum number of idle handles. - */ - public function __construct(int $maxHandles) - { - $this->maxHandles = $maxHandles; - } - - public function create(RequestInterface $request, array $options): EasyHandle - { - if (isset($options['curl']['body_as_string'])) { - $options['_body_as_string'] = $options['curl']['body_as_string']; - unset($options['curl']['body_as_string']); - } - - $easy = new EasyHandle(); - $easy->request = $request; - $easy->options = $options; - $conf = $this->getDefaultConf($easy); - $this->applyMethod($easy, $conf); - $this->applyHandlerOptions($easy, $conf); - $this->applyHeaders($easy, $conf); - unset($conf['_headers']); - - // Add handler options from the request configuration options - if (isset($options['curl'])) { - $conf = \array_replace($conf, $options['curl']); - } - - $conf[\CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy); - $easy->handle = $this->handles ? \array_pop($this->handles) : \curl_init(); - curl_setopt_array($easy->handle, $conf); - - return $easy; - } - - public function release(EasyHandle $easy): void - { - $resource = $easy->handle; - unset($easy->handle); - - if (\count($this->handles) >= $this->maxHandles) { - \curl_close($resource); - } else { - // Remove all callback functions as they can hold onto references - // and are not cleaned up by curl_reset. Using curl_setopt_array - // does not work for some reason, so removing each one - // individually. - \curl_setopt($resource, \CURLOPT_HEADERFUNCTION, null); - \curl_setopt($resource, \CURLOPT_READFUNCTION, null); - \curl_setopt($resource, \CURLOPT_WRITEFUNCTION, null); - \curl_setopt($resource, \CURLOPT_PROGRESSFUNCTION, null); - \curl_reset($resource); - $this->handles[] = $resource; - } - } - - /** - * Completes a cURL transaction, either returning a response promise or a - * rejected promise. - * - * @param callable(RequestInterface, array): PromiseInterface $handler - * @param CurlFactoryInterface $factory Dictates how the handle is released - */ - public static function finish(callable $handler, EasyHandle $easy, CurlFactoryInterface $factory): PromiseInterface - { - if (isset($easy->options['on_stats'])) { - self::invokeStats($easy); - } - - if (!$easy->response || $easy->errno) { - return self::finishError($handler, $easy, $factory); - } - - // Return the response if it is present and there is no error. - $factory->release($easy); - - // Rewind the body of the response if possible. - $body = $easy->response->getBody(); - if ($body->isSeekable()) { - $body->rewind(); - } - - return new FulfilledPromise($easy->response); - } - - private static function invokeStats(EasyHandle $easy): void - { - $curlStats = \curl_getinfo($easy->handle); - $curlStats['appconnect_time'] = \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME); - $stats = new TransferStats( - $easy->request, - $easy->response, - $curlStats['total_time'], - $easy->errno, - $curlStats - ); - ($easy->options['on_stats'])($stats); - } - - /** - * @param callable(RequestInterface, array): PromiseInterface $handler - */ - private static function finishError(callable $handler, EasyHandle $easy, CurlFactoryInterface $factory): PromiseInterface - { - // Get error information and release the handle to the factory. - $ctx = [ - 'errno' => $easy->errno, - 'error' => \curl_error($easy->handle), - 'appconnect_time' => \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME), - ] + \curl_getinfo($easy->handle); - $ctx[self::CURL_VERSION_STR] = \curl_version()['version']; - $factory->release($easy); - - // Retry when nothing is present or when curl failed to rewind. - if (empty($easy->options['_err_message']) && (!$easy->errno || $easy->errno == 65)) { - return self::retryFailedRewind($handler, $easy, $ctx); - } - - return self::createRejection($easy, $ctx); - } - - private static function createRejection(EasyHandle $easy, array $ctx): PromiseInterface - { - static $connectionErrors = [ - \CURLE_OPERATION_TIMEOUTED => true, - \CURLE_COULDNT_RESOLVE_HOST => true, - \CURLE_COULDNT_CONNECT => true, - \CURLE_SSL_CONNECT_ERROR => true, - \CURLE_GOT_NOTHING => true, - ]; - - if ($easy->createResponseException) { - return P\Create::rejectionFor( - new RequestException( - 'An error was encountered while creating the response', - $easy->request, - $easy->response, - $easy->createResponseException, - $ctx - ) - ); - } - - // If an exception was encountered during the onHeaders event, then - // return a rejected promise that wraps that exception. - if ($easy->onHeadersException) { - return P\Create::rejectionFor( - new RequestException( - 'An error was encountered during the on_headers event', - $easy->request, - $easy->response, - $easy->onHeadersException, - $ctx - ) - ); - } - - $message = \sprintf( - 'cURL error %s: %s (%s)', - $ctx['errno'], - $ctx['error'], - 'see https://curl.haxx.se/libcurl/c/libcurl-errors.html' - ); - $uriString = (string) $easy->request->getUri(); - if ($uriString !== '' && false === \strpos($ctx['error'], $uriString)) { - $message .= \sprintf(' for %s', $uriString); - } - - // Create a connection exception if it was a specific error code. - $error = isset($connectionErrors[$easy->errno]) - ? new ConnectException($message, $easy->request, null, $ctx) - : new RequestException($message, $easy->request, $easy->response, null, $ctx); - - return P\Create::rejectionFor($error); - } - - /** - * @return array<int|string, mixed> - */ - private function getDefaultConf(EasyHandle $easy): array - { - $conf = [ - '_headers' => $easy->request->getHeaders(), - \CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(), - \CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''), - \CURLOPT_RETURNTRANSFER => false, - \CURLOPT_HEADER => false, - \CURLOPT_CONNECTTIMEOUT => 300, - ]; - - if (\defined('CURLOPT_PROTOCOLS')) { - $conf[\CURLOPT_PROTOCOLS] = \CURLPROTO_HTTP | \CURLPROTO_HTTPS; - } - - $version = $easy->request->getProtocolVersion(); - if ($version == 1.1) { - $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_1; - } elseif ($version == 2.0) { - $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_2_0; - } else { - $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_0; - } - - return $conf; - } - - private function applyMethod(EasyHandle $easy, array &$conf): void - { - $body = $easy->request->getBody(); - $size = $body->getSize(); - - if ($size === null || $size > 0) { - $this->applyBody($easy->request, $easy->options, $conf); - - return; - } - - $method = $easy->request->getMethod(); - if ($method === 'PUT' || $method === 'POST') { - // See https://tools.ietf.org/html/rfc7230#section-3.3.2 - if (!$easy->request->hasHeader('Content-Length')) { - $conf[\CURLOPT_HTTPHEADER][] = 'Content-Length: 0'; - } - } elseif ($method === 'HEAD') { - $conf[\CURLOPT_NOBODY] = true; - unset( - $conf[\CURLOPT_WRITEFUNCTION], - $conf[\CURLOPT_READFUNCTION], - $conf[\CURLOPT_FILE], - $conf[\CURLOPT_INFILE] - ); - } - } - - private function applyBody(RequestInterface $request, array $options, array &$conf): void - { - $size = $request->hasHeader('Content-Length') - ? (int) $request->getHeaderLine('Content-Length') - : null; - - // Send the body as a string if the size is less than 1MB OR if the - // [curl][body_as_string] request value is set. - if (($size !== null && $size < 1000000) || !empty($options['_body_as_string'])) { - $conf[\CURLOPT_POSTFIELDS] = (string) $request->getBody(); - // Don't duplicate the Content-Length header - $this->removeHeader('Content-Length', $conf); - $this->removeHeader('Transfer-Encoding', $conf); - } else { - $conf[\CURLOPT_UPLOAD] = true; - if ($size !== null) { - $conf[\CURLOPT_INFILESIZE] = $size; - $this->removeHeader('Content-Length', $conf); - } - $body = $request->getBody(); - if ($body->isSeekable()) { - $body->rewind(); - } - $conf[\CURLOPT_READFUNCTION] = static function ($ch, $fd, $length) use ($body) { - return $body->read($length); - }; - } - - // If the Expect header is not present, prevent curl from adding it - if (!$request->hasHeader('Expect')) { - $conf[\CURLOPT_HTTPHEADER][] = 'Expect:'; - } - - // cURL sometimes adds a content-type by default. Prevent this. - if (!$request->hasHeader('Content-Type')) { - $conf[\CURLOPT_HTTPHEADER][] = 'Content-Type:'; - } - } - - private function applyHeaders(EasyHandle $easy, array &$conf): void - { - foreach ($conf['_headers'] as $name => $values) { - foreach ($values as $value) { - $value = (string) $value; - if ($value === '') { - // cURL requires a special format for empty headers. - // See https://github.com/guzzle/guzzle/issues/1882 for more details. - $conf[\CURLOPT_HTTPHEADER][] = "$name;"; - } else { - $conf[\CURLOPT_HTTPHEADER][] = "$name: $value"; - } - } - } - - // Remove the Accept header if one was not set - if (!$easy->request->hasHeader('Accept')) { - $conf[\CURLOPT_HTTPHEADER][] = 'Accept:'; - } - } - - /** - * Remove a header from the options array. - * - * @param string $name Case-insensitive header to remove - * @param array $options Array of options to modify - */ - private function removeHeader(string $name, array &$options): void - { - foreach (\array_keys($options['_headers']) as $key) { - if (!\strcasecmp($key, $name)) { - unset($options['_headers'][$key]); - - return; - } - } - } - - private function applyHandlerOptions(EasyHandle $easy, array &$conf): void - { - $options = $easy->options; - if (isset($options['verify'])) { - if ($options['verify'] === false) { - unset($conf[\CURLOPT_CAINFO]); - $conf[\CURLOPT_SSL_VERIFYHOST] = 0; - $conf[\CURLOPT_SSL_VERIFYPEER] = false; - } else { - $conf[\CURLOPT_SSL_VERIFYHOST] = 2; - $conf[\CURLOPT_SSL_VERIFYPEER] = true; - if (\is_string($options['verify'])) { - // Throw an error if the file/folder/link path is not valid or doesn't exist. - if (!\file_exists($options['verify'])) { - throw new \InvalidArgumentException("SSL CA bundle not found: {$options['verify']}"); - } - // If it's a directory or a link to a directory use CURLOPT_CAPATH. - // If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO. - if ( - \is_dir($options['verify']) || - ( - \is_link($options['verify']) === true && - ($verifyLink = \readlink($options['verify'])) !== false && - \is_dir($verifyLink) - ) - ) { - $conf[\CURLOPT_CAPATH] = $options['verify']; - } else { - $conf[\CURLOPT_CAINFO] = $options['verify']; - } - } - } - } - - if (!isset($options['curl'][\CURLOPT_ENCODING]) && !empty($options['decode_content'])) { - $accept = $easy->request->getHeaderLine('Accept-Encoding'); - if ($accept) { - $conf[\CURLOPT_ENCODING] = $accept; - } else { - // The empty string enables all available decoders and implicitly - // sets a matching 'Accept-Encoding' header. - $conf[\CURLOPT_ENCODING] = ''; - // But as the user did not specify any acceptable encodings we need - // to overwrite this implicit header with an empty one. - $conf[\CURLOPT_HTTPHEADER][] = 'Accept-Encoding:'; - } - } - - if (!isset($options['sink'])) { - // Use a default temp stream if no sink was set. - $options['sink'] = \GuzzleHttp\Psr7\Utils::tryFopen('php://temp', 'w+'); - } - $sink = $options['sink']; - if (!\is_string($sink)) { - $sink = \GuzzleHttp\Psr7\Utils::streamFor($sink); - } elseif (!\is_dir(\dirname($sink))) { - // Ensure that the directory exists before failing in curl. - throw new \RuntimeException(\sprintf('Directory %s does not exist for sink value of %s', \dirname($sink), $sink)); - } else { - $sink = new LazyOpenStream($sink, 'w+'); - } - $easy->sink = $sink; - $conf[\CURLOPT_WRITEFUNCTION] = static function ($ch, $write) use ($sink): int { - return $sink->write($write); - }; - - $timeoutRequiresNoSignal = false; - if (isset($options['timeout'])) { - $timeoutRequiresNoSignal |= $options['timeout'] < 1; - $conf[\CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000; - } - - // CURL default value is CURL_IPRESOLVE_WHATEVER - if (isset($options['force_ip_resolve'])) { - if ('v4' === $options['force_ip_resolve']) { - $conf[\CURLOPT_IPRESOLVE] = \CURL_IPRESOLVE_V4; - } elseif ('v6' === $options['force_ip_resolve']) { - $conf[\CURLOPT_IPRESOLVE] = \CURL_IPRESOLVE_V6; - } - } - - if (isset($options['connect_timeout'])) { - $timeoutRequiresNoSignal |= $options['connect_timeout'] < 1; - $conf[\CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000; - } - - if ($timeoutRequiresNoSignal && \strtoupper(\substr(\PHP_OS, 0, 3)) !== 'WIN') { - $conf[\CURLOPT_NOSIGNAL] = true; - } - - if (isset($options['proxy'])) { - if (!\is_array($options['proxy'])) { - $conf[\CURLOPT_PROXY] = $options['proxy']; - } else { - $scheme = $easy->request->getUri()->getScheme(); - if (isset($options['proxy'][$scheme])) { - $host = $easy->request->getUri()->getHost(); - if (isset($options['proxy']['no']) && Utils::isHostInNoProxy($host, $options['proxy']['no'])) { - unset($conf[\CURLOPT_PROXY]); - } else { - $conf[\CURLOPT_PROXY] = $options['proxy'][$scheme]; - } - } - } - } - - if (isset($options['crypto_method'])) { - if (\STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT === $options['crypto_method']) { - if (!defined('CURL_SSLVERSION_TLSv1_0')) { - throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.0 not supported by your version of cURL'); - } - $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_0; - } elseif (\STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT === $options['crypto_method']) { - if (!defined('CURL_SSLVERSION_TLSv1_1')) { - throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.1 not supported by your version of cURL'); - } - $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_1; - } elseif (\STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT === $options['crypto_method']) { - if (!defined('CURL_SSLVERSION_TLSv1_2')) { - throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.2 not supported by your version of cURL'); - } - $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_2; - } elseif (defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT === $options['crypto_method']) { - if (!defined('CURL_SSLVERSION_TLSv1_3')) { - throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.3 not supported by your version of cURL'); - } - $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_3; - } else { - throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided'); - } - } - - if (isset($options['cert'])) { - $cert = $options['cert']; - if (\is_array($cert)) { - $conf[\CURLOPT_SSLCERTPASSWD] = $cert[1]; - $cert = $cert[0]; - } - if (!\file_exists($cert)) { - throw new \InvalidArgumentException("SSL certificate not found: {$cert}"); - } - // OpenSSL (versions 0.9.3 and later) also support "P12" for PKCS#12-encoded files. - // see https://curl.se/libcurl/c/CURLOPT_SSLCERTTYPE.html - $ext = pathinfo($cert, \PATHINFO_EXTENSION); - if (preg_match('#^(der|p12)$#i', $ext)) { - $conf[\CURLOPT_SSLCERTTYPE] = strtoupper($ext); - } - $conf[\CURLOPT_SSLCERT] = $cert; - } - - if (isset($options['ssl_key'])) { - if (\is_array($options['ssl_key'])) { - if (\count($options['ssl_key']) === 2) { - [$sslKey, $conf[\CURLOPT_SSLKEYPASSWD]] = $options['ssl_key']; - } else { - [$sslKey] = $options['ssl_key']; - } - } - - $sslKey = $sslKey ?? $options['ssl_key']; - - if (!\file_exists($sslKey)) { - throw new \InvalidArgumentException("SSL private key not found: {$sslKey}"); - } - $conf[\CURLOPT_SSLKEY] = $sslKey; - } - - if (isset($options['progress'])) { - $progress = $options['progress']; - if (!\is_callable($progress)) { - throw new \InvalidArgumentException('progress client option must be callable'); - } - $conf[\CURLOPT_NOPROGRESS] = false; - $conf[\CURLOPT_PROGRESSFUNCTION] = static function ($resource, int $downloadSize, int $downloaded, int $uploadSize, int $uploaded) use ($progress) { - $progress($downloadSize, $downloaded, $uploadSize, $uploaded); - }; - } - - if (!empty($options['debug'])) { - $conf[\CURLOPT_STDERR] = Utils::debugResource($options['debug']); - $conf[\CURLOPT_VERBOSE] = true; - } - } - - /** - * This function ensures that a response was set on a transaction. If one - * was not set, then the request is retried if possible. This error - * typically means you are sending a payload, curl encountered a - * "Connection died, retrying a fresh connect" error, tried to rewind the - * stream, and then encountered a "necessary data rewind wasn't possible" - * error, causing the request to be sent through curl_multi_info_read() - * without an error status. - * - * @param callable(RequestInterface, array): PromiseInterface $handler - */ - private static function retryFailedRewind(callable $handler, EasyHandle $easy, array $ctx): PromiseInterface - { - try { - // Only rewind if the body has been read from. - $body = $easy->request->getBody(); - if ($body->tell() > 0) { - $body->rewind(); - } - } catch (\RuntimeException $e) { - $ctx['error'] = 'The connection unexpectedly failed without ' - .'providing an error. The request would have been retried, ' - .'but attempting to rewind the request body failed. ' - .'Exception: '.$e; - - return self::createRejection($easy, $ctx); - } - - // Retry no more than 3 times before giving up. - if (!isset($easy->options['_curl_retries'])) { - $easy->options['_curl_retries'] = 1; - } elseif ($easy->options['_curl_retries'] == 2) { - $ctx['error'] = 'The cURL request was retried 3 times ' - .'and did not succeed. The most likely reason for the failure ' - .'is that cURL was unable to rewind the body of the request ' - .'and subsequent retries resulted in the same error. Turn on ' - .'the debug option to see what went wrong. See ' - .'https://bugs.php.net/bug.php?id=47204 for more information.'; - - return self::createRejection($easy, $ctx); - } else { - ++$easy->options['_curl_retries']; - } - - return $handler($easy->request, $easy->options); - } - - private function createHeaderFn(EasyHandle $easy): callable - { - if (isset($easy->options['on_headers'])) { - $onHeaders = $easy->options['on_headers']; - - if (!\is_callable($onHeaders)) { - throw new \InvalidArgumentException('on_headers must be callable'); - } - } else { - $onHeaders = null; - } - - return static function ($ch, $h) use ( - $onHeaders, - $easy, - &$startingResponse - ) { - $value = \trim($h); - if ($value === '') { - $startingResponse = true; - try { - $easy->createResponse(); - } catch (\Exception $e) { - $easy->createResponseException = $e; - - return -1; - } - if ($onHeaders !== null) { - try { - $onHeaders($easy->response); - } catch (\Exception $e) { - // Associate the exception with the handle and trigger - // a curl header write error by returning 0. - $easy->onHeadersException = $e; - - return -1; - } - } - } elseif ($startingResponse) { - $startingResponse = false; - $easy->headers = [$value]; - } else { - $easy->headers[] = $value; - } - - return \strlen($h); - }; - } -} diff --git a/lib/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php b/lib/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php deleted file mode 100644 index fe57ed5d5..000000000 --- a/lib/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -namespace GuzzleHttp\Handler; - -use Psr\Http\Message\RequestInterface; - -interface CurlFactoryInterface -{ - /** - * Creates a cURL handle resource. - * - * @param RequestInterface $request Request - * @param array $options Transfer options - * - * @throws \RuntimeException when an option cannot be applied - */ - public function create(RequestInterface $request, array $options): EasyHandle; - - /** - * Release an easy handle, allowing it to be reused or closed. - * - * This function must call unset on the easy handle's "handle" property. - */ - public function release(EasyHandle $easy): void; -} diff --git a/lib/guzzlehttp/guzzle/src/Handler/CurlHandler.php b/lib/guzzlehttp/guzzle/src/Handler/CurlHandler.php deleted file mode 100644 index 9ad10a9b0..000000000 --- a/lib/guzzlehttp/guzzle/src/Handler/CurlHandler.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -namespace GuzzleHttp\Handler; - -use GuzzleHttp\Promise\PromiseInterface; -use Psr\Http\Message\RequestInterface; - -/** - * HTTP handler that uses cURL easy handles as a transport layer. - * - * When using the CurlHandler, custom curl options can be specified as an - * associative array of curl option constants mapping to values in the - * **curl** key of the "client" key of the request. - * - * @final - */ -class CurlHandler -{ - /** - * @var CurlFactoryInterface - */ - private $factory; - - /** - * Accepts an associative array of options: - * - * - handle_factory: Optional curl factory used to create cURL handles. - * - * @param array{handle_factory?: ?CurlFactoryInterface} $options Array of options to use with the handler - */ - public function __construct(array $options = []) - { - $this->factory = $options['handle_factory'] - ?? new CurlFactory(3); - } - - public function __invoke(RequestInterface $request, array $options): PromiseInterface - { - if (isset($options['delay'])) { - \usleep($options['delay'] * 1000); - } - - $easy = $this->factory->create($request, $options); - \curl_exec($easy->handle); - $easy->errno = \curl_errno($easy->handle); - - return CurlFactory::finish($this, $easy, $this->factory); - } -} diff --git a/lib/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php b/lib/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php deleted file mode 100644 index f0acde145..000000000 --- a/lib/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php +++ /dev/null @@ -1,263 +0,0 @@ -<?php - -namespace GuzzleHttp\Handler; - -use GuzzleHttp\Promise as P; -use GuzzleHttp\Promise\Promise; -use GuzzleHttp\Promise\PromiseInterface; -use GuzzleHttp\Utils; -use Psr\Http\Message\RequestInterface; - -/** - * Returns an asynchronous response using curl_multi_* functions. - * - * When using the CurlMultiHandler, custom curl options can be specified as an - * associative array of curl option constants mapping to values in the - * **curl** key of the provided request options. - * - * @property resource|\CurlMultiHandle $_mh Internal use only. Lazy loaded multi-handle. - * - * @final - */ -#[\AllowDynamicProperties] -class CurlMultiHandler -{ - /** - * @var CurlFactoryInterface - */ - private $factory; - - /** - * @var int - */ - private $selectTimeout; - - /** - * @var int Will be higher than 0 when `curl_multi_exec` is still running. - */ - private $active = 0; - - /** - * @var array Request entry handles, indexed by handle id in `addRequest`. - * - * @see CurlMultiHandler::addRequest - */ - private $handles = []; - - /** - * @var array<int, float> An array of delay times, indexed by handle id in `addRequest`. - * - * @see CurlMultiHandler::addRequest - */ - private $delays = []; - - /** - * @var array<mixed> An associative array of CURLMOPT_* options and corresponding values for curl_multi_setopt() - */ - private $options = []; - - /** - * This handler accepts the following options: - * - * - handle_factory: An optional factory used to create curl handles - * - select_timeout: Optional timeout (in seconds) to block before timing - * out while selecting curl handles. Defaults to 1 second. - * - options: An associative array of CURLMOPT_* options and - * corresponding values for curl_multi_setopt() - */ - public function __construct(array $options = []) - { - $this->factory = $options['handle_factory'] ?? new CurlFactory(50); - - if (isset($options['select_timeout'])) { - $this->selectTimeout = $options['select_timeout']; - } elseif ($selectTimeout = Utils::getenv('GUZZLE_CURL_SELECT_TIMEOUT')) { - @trigger_error('Since guzzlehttp/guzzle 7.2.0: Using environment variable GUZZLE_CURL_SELECT_TIMEOUT is deprecated. Use option "select_timeout" instead.', \E_USER_DEPRECATED); - $this->selectTimeout = (int) $selectTimeout; - } else { - $this->selectTimeout = 1; - } - - $this->options = $options['options'] ?? []; - } - - /** - * @param string $name - * - * @return resource|\CurlMultiHandle - * - * @throws \BadMethodCallException when another field as `_mh` will be gotten - * @throws \RuntimeException when curl can not initialize a multi handle - */ - public function __get($name) - { - if ($name !== '_mh') { - throw new \BadMethodCallException("Can not get other property as '_mh'."); - } - - $multiHandle = \curl_multi_init(); - - if (false === $multiHandle) { - throw new \RuntimeException('Can not initialize curl multi handle.'); - } - - $this->_mh = $multiHandle; - - foreach ($this->options as $option => $value) { - // A warning is raised in case of a wrong option. - curl_multi_setopt($this->_mh, $option, $value); - } - - return $this->_mh; - } - - public function __destruct() - { - if (isset($this->_mh)) { - \curl_multi_close($this->_mh); - unset($this->_mh); - } - } - - public function __invoke(RequestInterface $request, array $options): PromiseInterface - { - $easy = $this->factory->create($request, $options); - $id = (int) $easy->handle; - - $promise = new Promise( - [$this, 'execute'], - function () use ($id) { - return $this->cancel($id); - } - ); - - $this->addRequest(['easy' => $easy, 'deferred' => $promise]); - - return $promise; - } - - /** - * Ticks the curl event loop. - */ - public function tick(): void - { - // Add any delayed handles if needed. - if ($this->delays) { - $currentTime = Utils::currentTime(); - foreach ($this->delays as $id => $delay) { - if ($currentTime >= $delay) { - unset($this->delays[$id]); - \curl_multi_add_handle( - $this->_mh, - $this->handles[$id]['easy']->handle - ); - } - } - } - - // Step through the task queue which may add additional requests. - P\Utils::queue()->run(); - - if ($this->active && \curl_multi_select($this->_mh, $this->selectTimeout) === -1) { - // Perform a usleep if a select returns -1. - // See: https://bugs.php.net/bug.php?id=61141 - \usleep(250); - } - - while (\curl_multi_exec($this->_mh, $this->active) === \CURLM_CALL_MULTI_PERFORM) { - } - - $this->processMessages(); - } - - /** - * Runs until all outstanding connections have completed. - */ - public function execute(): void - { - $queue = P\Utils::queue(); - - while ($this->handles || !$queue->isEmpty()) { - // If there are no transfers, then sleep for the next delay - if (!$this->active && $this->delays) { - \usleep($this->timeToNext()); - } - $this->tick(); - } - } - - private function addRequest(array $entry): void - { - $easy = $entry['easy']; - $id = (int) $easy->handle; - $this->handles[$id] = $entry; - if (empty($easy->options['delay'])) { - \curl_multi_add_handle($this->_mh, $easy->handle); - } else { - $this->delays[$id] = Utils::currentTime() + ($easy->options['delay'] / 1000); - } - } - - /** - * Cancels a handle from sending and removes references to it. - * - * @param int $id Handle ID to cancel and remove. - * - * @return bool True on success, false on failure. - */ - private function cancel($id): bool - { - if (!is_int($id)) { - trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an integer to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); - } - - // Cannot cancel if it has been processed. - if (!isset($this->handles[$id])) { - return false; - } - - $handle = $this->handles[$id]['easy']->handle; - unset($this->delays[$id], $this->handles[$id]); - \curl_multi_remove_handle($this->_mh, $handle); - \curl_close($handle); - - return true; - } - - private function processMessages(): void - { - while ($done = \curl_multi_info_read($this->_mh)) { - if ($done['msg'] !== \CURLMSG_DONE) { - // if it's not done, then it would be premature to remove the handle. ref https://github.com/guzzle/guzzle/pull/2892#issuecomment-945150216 - continue; - } - $id = (int) $done['handle']; - \curl_multi_remove_handle($this->_mh, $done['handle']); - - if (!isset($this->handles[$id])) { - // Probably was cancelled. - continue; - } - - $entry = $this->handles[$id]; - unset($this->handles[$id], $this->delays[$id]); - $entry['easy']->errno = $done['result']; - $entry['deferred']->resolve( - CurlFactory::finish($this, $entry['easy'], $this->factory) - ); - } - } - - private function timeToNext(): int - { - $currentTime = Utils::currentTime(); - $nextTime = \PHP_INT_MAX; - foreach ($this->delays as $time) { - if ($time < $nextTime) { - $nextTime = $time; - } - } - - return ((int) \max(0, $nextTime - $currentTime)) * 1000000; - } -} diff --git a/lib/guzzlehttp/guzzle/src/Handler/EasyHandle.php b/lib/guzzlehttp/guzzle/src/Handler/EasyHandle.php deleted file mode 100644 index 1bc39f4b4..000000000 --- a/lib/guzzlehttp/guzzle/src/Handler/EasyHandle.php +++ /dev/null @@ -1,112 +0,0 @@ -<?php - -namespace GuzzleHttp\Handler; - -use GuzzleHttp\Psr7\Response; -use GuzzleHttp\Utils; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\StreamInterface; - -/** - * Represents a cURL easy handle and the data it populates. - * - * @internal - */ -final class EasyHandle -{ - /** - * @var resource|\CurlHandle cURL resource - */ - public $handle; - - /** - * @var StreamInterface Where data is being written - */ - public $sink; - - /** - * @var array Received HTTP headers so far - */ - public $headers = []; - - /** - * @var ResponseInterface|null Received response (if any) - */ - public $response; - - /** - * @var RequestInterface Request being sent - */ - public $request; - - /** - * @var array Request options - */ - public $options = []; - - /** - * @var int cURL error number (if any) - */ - public $errno = 0; - - /** - * @var \Throwable|null Exception during on_headers (if any) - */ - public $onHeadersException; - - /** - * @var \Exception|null Exception during createResponse (if any) - */ - public $createResponseException; - - /** - * Attach a response to the easy handle based on the received headers. - * - * @throws \RuntimeException if no headers have been received or the first - * header line is invalid. - */ - public function createResponse(): void - { - [$ver, $status, $reason, $headers] = HeaderProcessor::parseHeaders($this->headers); - - $normalizedKeys = Utils::normalizeHeaderKeys($headers); - - if (!empty($this->options['decode_content']) && isset($normalizedKeys['content-encoding'])) { - $headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']]; - unset($headers[$normalizedKeys['content-encoding']]); - if (isset($normalizedKeys['content-length'])) { - $headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']]; - - $bodyLength = (int) $this->sink->getSize(); - if ($bodyLength) { - $headers[$normalizedKeys['content-length']] = $bodyLength; - } else { - unset($headers[$normalizedKeys['content-length']]); - } - } - } - - // Attach a response to the easy handle with the parsed headers. - $this->response = new Response( - $status, - $headers, - $this->sink, - $ver, - $reason - ); - } - - /** - * @param string $name - * - * @return void - * - * @throws \BadMethodCallException - */ - public function __get($name) - { - $msg = $name === 'handle' ? 'The EasyHandle has been released' : 'Invalid property: '.$name; - throw new \BadMethodCallException($msg); - } -} diff --git a/lib/guzzlehttp/guzzle/src/Handler/HeaderProcessor.php b/lib/guzzlehttp/guzzle/src/Handler/HeaderProcessor.php deleted file mode 100644 index 5554b8fa9..000000000 --- a/lib/guzzlehttp/guzzle/src/Handler/HeaderProcessor.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php - -namespace GuzzleHttp\Handler; - -use GuzzleHttp\Utils; - -/** - * @internal - */ -final class HeaderProcessor -{ - /** - * Returns the HTTP version, status code, reason phrase, and headers. - * - * @param string[] $headers - * - * @return array{0:string, 1:int, 2:?string, 3:array} - * - * @throws \RuntimeException - */ - public static function parseHeaders(array $headers): array - { - if ($headers === []) { - throw new \RuntimeException('Expected a non-empty array of header data'); - } - - $parts = \explode(' ', \array_shift($headers), 3); - $version = \explode('/', $parts[0])[1] ?? null; - - if ($version === null) { - throw new \RuntimeException('HTTP version missing from header data'); - } - - $status = $parts[1] ?? null; - - if ($status === null) { - throw new \RuntimeException('HTTP status code missing from header data'); - } - - return [$version, (int) $status, $parts[2] ?? null, Utils::headersFromLines($headers)]; - } -} diff --git a/lib/guzzlehttp/guzzle/src/Handler/MockHandler.php b/lib/guzzlehttp/guzzle/src/Handler/MockHandler.php deleted file mode 100644 index 77ffed521..000000000 --- a/lib/guzzlehttp/guzzle/src/Handler/MockHandler.php +++ /dev/null @@ -1,212 +0,0 @@ -<?php - -namespace GuzzleHttp\Handler; - -use GuzzleHttp\Exception\RequestException; -use GuzzleHttp\HandlerStack; -use GuzzleHttp\Promise as P; -use GuzzleHttp\Promise\PromiseInterface; -use GuzzleHttp\TransferStats; -use GuzzleHttp\Utils; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\StreamInterface; - -/** - * Handler that returns responses or throw exceptions from a queue. - * - * @final - */ -class MockHandler implements \Countable -{ - /** - * @var array - */ - private $queue = []; - - /** - * @var RequestInterface|null - */ - private $lastRequest; - - /** - * @var array - */ - private $lastOptions = []; - - /** - * @var callable|null - */ - private $onFulfilled; - - /** - * @var callable|null - */ - private $onRejected; - - /** - * Creates a new MockHandler that uses the default handler stack list of - * middlewares. - * - * @param array|null $queue Array of responses, callables, or exceptions. - * @param callable|null $onFulfilled Callback to invoke when the return value is fulfilled. - * @param callable|null $onRejected Callback to invoke when the return value is rejected. - */ - public static function createWithMiddleware(array $queue = null, callable $onFulfilled = null, callable $onRejected = null): HandlerStack - { - return HandlerStack::create(new self($queue, $onFulfilled, $onRejected)); - } - - /** - * The passed in value must be an array of - * {@see \Psr\Http\Message\ResponseInterface} objects, Exceptions, - * callables, or Promises. - * - * @param array<int, mixed>|null $queue The parameters to be passed to the append function, as an indexed array. - * @param callable|null $onFulfilled Callback to invoke when the return value is fulfilled. - * @param callable|null $onRejected Callback to invoke when the return value is rejected. - */ - public function __construct(array $queue = null, callable $onFulfilled = null, callable $onRejected = null) - { - $this->onFulfilled = $onFulfilled; - $this->onRejected = $onRejected; - - if ($queue) { - // array_values included for BC - $this->append(...array_values($queue)); - } - } - - public function __invoke(RequestInterface $request, array $options): PromiseInterface - { - if (!$this->queue) { - throw new \OutOfBoundsException('Mock queue is empty'); - } - - if (isset($options['delay']) && \is_numeric($options['delay'])) { - \usleep((int) $options['delay'] * 1000); - } - - $this->lastRequest = $request; - $this->lastOptions = $options; - $response = \array_shift($this->queue); - - if (isset($options['on_headers'])) { - if (!\is_callable($options['on_headers'])) { - throw new \InvalidArgumentException('on_headers must be callable'); - } - try { - $options['on_headers']($response); - } catch (\Exception $e) { - $msg = 'An error was encountered during the on_headers event'; - $response = new RequestException($msg, $request, $response, $e); - } - } - - if (\is_callable($response)) { - $response = $response($request, $options); - } - - $response = $response instanceof \Throwable - ? P\Create::rejectionFor($response) - : P\Create::promiseFor($response); - - return $response->then( - function (?ResponseInterface $value) use ($request, $options) { - $this->invokeStats($request, $options, $value); - if ($this->onFulfilled) { - ($this->onFulfilled)($value); - } - - if ($value !== null && isset($options['sink'])) { - $contents = (string) $value->getBody(); - $sink = $options['sink']; - - if (\is_resource($sink)) { - \fwrite($sink, $contents); - } elseif (\is_string($sink)) { - \file_put_contents($sink, $contents); - } elseif ($sink instanceof StreamInterface) { - $sink->write($contents); - } - } - - return $value; - }, - function ($reason) use ($request, $options) { - $this->invokeStats($request, $options, null, $reason); - if ($this->onRejected) { - ($this->onRejected)($reason); - } - - return P\Create::rejectionFor($reason); - } - ); - } - - /** - * Adds one or more variadic requests, exceptions, callables, or promises - * to the queue. - * - * @param mixed ...$values - */ - public function append(...$values): void - { - foreach ($values as $value) { - if ($value instanceof ResponseInterface - || $value instanceof \Throwable - || $value instanceof PromiseInterface - || \is_callable($value) - ) { - $this->queue[] = $value; - } else { - throw new \TypeError('Expected a Response, Promise, Throwable or callable. Found '.Utils::describeType($value)); - } - } - } - - /** - * Get the last received request. - */ - public function getLastRequest(): ?RequestInterface - { - return $this->lastRequest; - } - - /** - * Get the last received request options. - */ - public function getLastOptions(): array - { - return $this->lastOptions; - } - - /** - * Returns the number of remaining items in the queue. - */ - public function count(): int - { - return \count($this->queue); - } - - public function reset(): void - { - $this->queue = []; - } - - /** - * @param mixed $reason Promise or reason. - */ - private function invokeStats( - RequestInterface $request, - array $options, - ResponseInterface $response = null, - $reason = null - ): void { - if (isset($options['on_stats'])) { - $transferTime = $options['transfer_time'] ?? 0; - $stats = new TransferStats($request, $response, $transferTime, $reason); - ($options['on_stats'])($stats); - } - } -} diff --git a/lib/guzzlehttp/guzzle/src/Handler/Proxy.php b/lib/guzzlehttp/guzzle/src/Handler/Proxy.php deleted file mode 100644 index f045b526c..000000000 --- a/lib/guzzlehttp/guzzle/src/Handler/Proxy.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php - -namespace GuzzleHttp\Handler; - -use GuzzleHttp\Promise\PromiseInterface; -use GuzzleHttp\RequestOptions; -use Psr\Http\Message\RequestInterface; - -/** - * Provides basic proxies for handlers. - * - * @final - */ -class Proxy -{ - /** - * Sends synchronous requests to a specific handler while sending all other - * requests to another handler. - * - * @param callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface $default Handler used for normal responses - * @param callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface $sync Handler used for synchronous responses. - * - * @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the composed handler. - */ - public static function wrapSync(callable $default, callable $sync): callable - { - return static function (RequestInterface $request, array $options) use ($default, $sync): PromiseInterface { - return empty($options[RequestOptions::SYNCHRONOUS]) ? $default($request, $options) : $sync($request, $options); - }; - } - - /** - * Sends streaming requests to a streaming compatible handler while sending - * all other requests to a default handler. - * - * This, for example, could be useful for taking advantage of the - * performance benefits of curl while still supporting true streaming - * through the StreamHandler. - * - * @param callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface $default Handler used for non-streaming responses - * @param callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface $streaming Handler used for streaming responses - * - * @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the composed handler. - */ - public static function wrapStreaming(callable $default, callable $streaming): callable - { - return static function (RequestInterface $request, array $options) use ($default, $streaming): PromiseInterface { - return empty($options['stream']) ? $default($request, $options) : $streaming($request, $options); - }; - } -} diff --git a/lib/guzzlehttp/guzzle/src/Handler/StreamHandler.php b/lib/guzzlehttp/guzzle/src/Handler/StreamHandler.php deleted file mode 100644 index 61632f564..000000000 --- a/lib/guzzlehttp/guzzle/src/Handler/StreamHandler.php +++ /dev/null @@ -1,615 +0,0 @@ -<?php - -namespace GuzzleHttp\Handler; - -use GuzzleHttp\Exception\ConnectException; -use GuzzleHttp\Exception\RequestException; -use GuzzleHttp\Promise as P; -use GuzzleHttp\Promise\FulfilledPromise; -use GuzzleHttp\Promise\PromiseInterface; -use GuzzleHttp\Psr7; -use GuzzleHttp\TransferStats; -use GuzzleHttp\Utils; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\StreamInterface; -use Psr\Http\Message\UriInterface; - -/** - * HTTP handler that uses PHP's HTTP stream wrapper. - * - * @final - */ -class StreamHandler -{ - /** - * @var array - */ - private $lastHeaders = []; - - /** - * Sends an HTTP request. - * - * @param RequestInterface $request Request to send. - * @param array $options Request transfer options. - */ - public function __invoke(RequestInterface $request, array $options): PromiseInterface - { - // Sleep if there is a delay specified. - if (isset($options['delay'])) { - \usleep($options['delay'] * 1000); - } - - $startTime = isset($options['on_stats']) ? Utils::currentTime() : null; - - try { - // Does not support the expect header. - $request = $request->withoutHeader('Expect'); - - // Append a content-length header if body size is zero to match - // cURL's behavior. - if (0 === $request->getBody()->getSize()) { - $request = $request->withHeader('Content-Length', '0'); - } - - return $this->createResponse( - $request, - $options, - $this->createStream($request, $options), - $startTime - ); - } catch (\InvalidArgumentException $e) { - throw $e; - } catch (\Exception $e) { - // Determine if the error was a networking error. - $message = $e->getMessage(); - // This list can probably get more comprehensive. - if (false !== \strpos($message, 'getaddrinfo') // DNS lookup failed - || false !== \strpos($message, 'Connection refused') - || false !== \strpos($message, "couldn't connect to host") // error on HHVM - || false !== \strpos($message, 'connection attempt failed') - ) { - $e = new ConnectException($e->getMessage(), $request, $e); - } else { - $e = RequestException::wrapException($request, $e); - } - $this->invokeStats($options, $request, $startTime, null, $e); - - return P\Create::rejectionFor($e); - } - } - - private function invokeStats( - array $options, - RequestInterface $request, - ?float $startTime, - ResponseInterface $response = null, - \Throwable $error = null - ): void { - if (isset($options['on_stats'])) { - $stats = new TransferStats($request, $response, Utils::currentTime() - $startTime, $error, []); - ($options['on_stats'])($stats); - } - } - - /** - * @param resource $stream - */ - private function createResponse(RequestInterface $request, array $options, $stream, ?float $startTime): PromiseInterface - { - $hdrs = $this->lastHeaders; - $this->lastHeaders = []; - - try { - [$ver, $status, $reason, $headers] = HeaderProcessor::parseHeaders($hdrs); - } catch (\Exception $e) { - return P\Create::rejectionFor( - new RequestException('An error was encountered while creating the response', $request, null, $e) - ); - } - - [$stream, $headers] = $this->checkDecode($options, $headers, $stream); - $stream = Psr7\Utils::streamFor($stream); - $sink = $stream; - - if (\strcasecmp('HEAD', $request->getMethod())) { - $sink = $this->createSink($stream, $options); - } - - try { - $response = new Psr7\Response($status, $headers, $sink, $ver, $reason); - } catch (\Exception $e) { - return P\Create::rejectionFor( - new RequestException('An error was encountered while creating the response', $request, null, $e) - ); - } - - if (isset($options['on_headers'])) { - try { - $options['on_headers']($response); - } catch (\Exception $e) { - return P\Create::rejectionFor( - new RequestException('An error was encountered during the on_headers event', $request, $response, $e) - ); - } - } - - // Do not drain when the request is a HEAD request because they have - // no body. - if ($sink !== $stream) { - $this->drain($stream, $sink, $response->getHeaderLine('Content-Length')); - } - - $this->invokeStats($options, $request, $startTime, $response, null); - - return new FulfilledPromise($response); - } - - private function createSink(StreamInterface $stream, array $options): StreamInterface - { - if (!empty($options['stream'])) { - return $stream; - } - - $sink = $options['sink'] ?? Psr7\Utils::tryFopen('php://temp', 'r+'); - - return \is_string($sink) ? new Psr7\LazyOpenStream($sink, 'w+') : Psr7\Utils::streamFor($sink); - } - - /** - * @param resource $stream - */ - private function checkDecode(array $options, array $headers, $stream): array - { - // Automatically decode responses when instructed. - if (!empty($options['decode_content'])) { - $normalizedKeys = Utils::normalizeHeaderKeys($headers); - if (isset($normalizedKeys['content-encoding'])) { - $encoding = $headers[$normalizedKeys['content-encoding']]; - if ($encoding[0] === 'gzip' || $encoding[0] === 'deflate') { - $stream = new Psr7\InflateStream(Psr7\Utils::streamFor($stream)); - $headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']]; - - // Remove content-encoding header - unset($headers[$normalizedKeys['content-encoding']]); - - // Fix content-length header - if (isset($normalizedKeys['content-length'])) { - $headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']]; - $length = (int) $stream->getSize(); - if ($length === 0) { - unset($headers[$normalizedKeys['content-length']]); - } else { - $headers[$normalizedKeys['content-length']] = [$length]; - } - } - } - } - } - - return [$stream, $headers]; - } - - /** - * Drains the source stream into the "sink" client option. - * - * @param string $contentLength Header specifying the amount of - * data to read. - * - * @throws \RuntimeException when the sink option is invalid. - */ - private function drain(StreamInterface $source, StreamInterface $sink, string $contentLength): StreamInterface - { - // If a content-length header is provided, then stop reading once - // that number of bytes has been read. This can prevent infinitely - // reading from a stream when dealing with servers that do not honor - // Connection: Close headers. - Psr7\Utils::copyToStream( - $source, - $sink, - (\strlen($contentLength) > 0 && (int) $contentLength > 0) ? (int) $contentLength : -1 - ); - - $sink->seek(0); - $source->close(); - - return $sink; - } - - /** - * Create a resource and check to ensure it was created successfully - * - * @param callable $callback Callable that returns stream resource - * - * @return resource - * - * @throws \RuntimeException on error - */ - private function createResource(callable $callback) - { - $errors = []; - \set_error_handler(static function ($_, $msg, $file, $line) use (&$errors): bool { - $errors[] = [ - 'message' => $msg, - 'file' => $file, - 'line' => $line, - ]; - - return true; - }); - - try { - $resource = $callback(); - } finally { - \restore_error_handler(); - } - - if (!$resource) { - $message = 'Error creating resource: '; - foreach ($errors as $err) { - foreach ($err as $key => $value) { - $message .= "[$key] $value".\PHP_EOL; - } - } - throw new \RuntimeException(\trim($message)); - } - - return $resource; - } - - /** - * @return resource - */ - private function createStream(RequestInterface $request, array $options) - { - static $methods; - if (!$methods) { - $methods = \array_flip(\get_class_methods(__CLASS__)); - } - - if (!\in_array($request->getUri()->getScheme(), ['http', 'https'])) { - throw new RequestException(\sprintf("The scheme '%s' is not supported.", $request->getUri()->getScheme()), $request); - } - - // HTTP/1.1 streams using the PHP stream wrapper require a - // Connection: close header - if ($request->getProtocolVersion() == '1.1' - && !$request->hasHeader('Connection') - ) { - $request = $request->withHeader('Connection', 'close'); - } - - // Ensure SSL is verified by default - if (!isset($options['verify'])) { - $options['verify'] = true; - } - - $params = []; - $context = $this->getDefaultContext($request); - - if (isset($options['on_headers']) && !\is_callable($options['on_headers'])) { - throw new \InvalidArgumentException('on_headers must be callable'); - } - - if (!empty($options)) { - foreach ($options as $key => $value) { - $method = "add_{$key}"; - if (isset($methods[$method])) { - $this->{$method}($request, $context, $value, $params); - } - } - } - - if (isset($options['stream_context'])) { - if (!\is_array($options['stream_context'])) { - throw new \InvalidArgumentException('stream_context must be an array'); - } - $context = \array_replace_recursive($context, $options['stream_context']); - } - - // Microsoft NTLM authentication only supported with curl handler - if (isset($options['auth'][2]) && 'ntlm' === $options['auth'][2]) { - throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler'); - } - - $uri = $this->resolveHost($request, $options); - - $contextResource = $this->createResource( - static function () use ($context, $params) { - return \stream_context_create($context, $params); - } - ); - - return $this->createResource( - function () use ($uri, &$http_response_header, $contextResource, $context, $options, $request) { - $resource = @\fopen((string) $uri, 'r', false, $contextResource); - $this->lastHeaders = $http_response_header ?? []; - - if (false === $resource) { - throw new ConnectException(sprintf('Connection refused for URI %s', $uri), $request, null, $context); - } - - if (isset($options['read_timeout'])) { - $readTimeout = $options['read_timeout']; - $sec = (int) $readTimeout; - $usec = ($readTimeout - $sec) * 100000; - \stream_set_timeout($resource, $sec, $usec); - } - - return $resource; - } - ); - } - - private function resolveHost(RequestInterface $request, array $options): UriInterface - { - $uri = $request->getUri(); - - if (isset($options['force_ip_resolve']) && !\filter_var($uri->getHost(), \FILTER_VALIDATE_IP)) { - if ('v4' === $options['force_ip_resolve']) { - $records = \dns_get_record($uri->getHost(), \DNS_A); - if (false === $records || !isset($records[0]['ip'])) { - throw new ConnectException(\sprintf("Could not resolve IPv4 address for host '%s'", $uri->getHost()), $request); - } - - return $uri->withHost($records[0]['ip']); - } - if ('v6' === $options['force_ip_resolve']) { - $records = \dns_get_record($uri->getHost(), \DNS_AAAA); - if (false === $records || !isset($records[0]['ipv6'])) { - throw new ConnectException(\sprintf("Could not resolve IPv6 address for host '%s'", $uri->getHost()), $request); - } - - return $uri->withHost('['.$records[0]['ipv6'].']'); - } - } - - return $uri; - } - - private function getDefaultContext(RequestInterface $request): array - { - $headers = ''; - foreach ($request->getHeaders() as $name => $value) { - foreach ($value as $val) { - $headers .= "$name: $val\r\n"; - } - } - - $context = [ - 'http' => [ - 'method' => $request->getMethod(), - 'header' => $headers, - 'protocol_version' => $request->getProtocolVersion(), - 'ignore_errors' => true, - 'follow_location' => 0, - ], - 'ssl' => [ - 'peer_name' => $request->getUri()->getHost(), - ], - ]; - - $body = (string) $request->getBody(); - - if ('' !== $body) { - $context['http']['content'] = $body; - // Prevent the HTTP handler from adding a Content-Type header. - if (!$request->hasHeader('Content-Type')) { - $context['http']['header'] .= "Content-Type:\r\n"; - } - } - - $context['http']['header'] = \rtrim($context['http']['header']); - - return $context; - } - - /** - * @param mixed $value as passed via Request transfer options. - */ - private function add_proxy(RequestInterface $request, array &$options, $value, array &$params): void - { - $uri = null; - - if (!\is_array($value)) { - $uri = $value; - } else { - $scheme = $request->getUri()->getScheme(); - if (isset($value[$scheme])) { - if (!isset($value['no']) || !Utils::isHostInNoProxy($request->getUri()->getHost(), $value['no'])) { - $uri = $value[$scheme]; - } - } - } - - if (!$uri) { - return; - } - - $parsed = $this->parse_proxy($uri); - $options['http']['proxy'] = $parsed['proxy']; - - if ($parsed['auth']) { - if (!isset($options['http']['header'])) { - $options['http']['header'] = []; - } - $options['http']['header'] .= "\r\nProxy-Authorization: {$parsed['auth']}"; - } - } - - /** - * Parses the given proxy URL to make it compatible with the format PHP's stream context expects. - */ - private function parse_proxy(string $url): array - { - $parsed = \parse_url($url); - - if ($parsed !== false && isset($parsed['scheme']) && $parsed['scheme'] === 'http') { - if (isset($parsed['host']) && isset($parsed['port'])) { - $auth = null; - if (isset($parsed['user']) && isset($parsed['pass'])) { - $auth = \base64_encode("{$parsed['user']}:{$parsed['pass']}"); - } - - return [ - 'proxy' => "tcp://{$parsed['host']}:{$parsed['port']}", - 'auth' => $auth ? "Basic {$auth}" : null, - ]; - } - } - - // Return proxy as-is. - return [ - 'proxy' => $url, - 'auth' => null, - ]; - } - - /** - * @param mixed $value as passed via Request transfer options. - */ - private function add_timeout(RequestInterface $request, array &$options, $value, array &$params): void - { - if ($value > 0) { - $options['http']['timeout'] = $value; - } - } - - /** - * @param mixed $value as passed via Request transfer options. - */ - private function add_crypto_method(RequestInterface $request, array &$options, $value, array &$params): void - { - if ( - $value === \STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT - || $value === \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT - || $value === \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT - || (defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && $value === \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT) - ) { - $options['http']['crypto_method'] = $value; - - return; - } - - throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided'); - } - - /** - * @param mixed $value as passed via Request transfer options. - */ - private function add_verify(RequestInterface $request, array &$options, $value, array &$params): void - { - if ($value === false) { - $options['ssl']['verify_peer'] = false; - $options['ssl']['verify_peer_name'] = false; - - return; - } - - if (\is_string($value)) { - $options['ssl']['cafile'] = $value; - if (!\file_exists($value)) { - throw new \RuntimeException("SSL CA bundle not found: $value"); - } - } elseif ($value !== true) { - throw new \InvalidArgumentException('Invalid verify request option'); - } - - $options['ssl']['verify_peer'] = true; - $options['ssl']['verify_peer_name'] = true; - $options['ssl']['allow_self_signed'] = false; - } - - /** - * @param mixed $value as passed via Request transfer options. - */ - private function add_cert(RequestInterface $request, array &$options, $value, array &$params): void - { - if (\is_array($value)) { - $options['ssl']['passphrase'] = $value[1]; - $value = $value[0]; - } - - if (!\file_exists($value)) { - throw new \RuntimeException("SSL certificate not found: {$value}"); - } - - $options['ssl']['local_cert'] = $value; - } - - /** - * @param mixed $value as passed via Request transfer options. - */ - private function add_progress(RequestInterface $request, array &$options, $value, array &$params): void - { - self::addNotification( - $params, - static function ($code, $a, $b, $c, $transferred, $total) use ($value) { - if ($code == \STREAM_NOTIFY_PROGRESS) { - // The upload progress cannot be determined. Use 0 for cURL compatibility: - // https://curl.se/libcurl/c/CURLOPT_PROGRESSFUNCTION.html - $value($total, $transferred, 0, 0); - } - } - ); - } - - /** - * @param mixed $value as passed via Request transfer options. - */ - private function add_debug(RequestInterface $request, array &$options, $value, array &$params): void - { - if ($value === false) { - return; - } - - static $map = [ - \STREAM_NOTIFY_CONNECT => 'CONNECT', - \STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED', - \STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT', - \STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS', - \STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS', - \STREAM_NOTIFY_REDIRECTED => 'REDIRECTED', - \STREAM_NOTIFY_PROGRESS => 'PROGRESS', - \STREAM_NOTIFY_FAILURE => 'FAILURE', - \STREAM_NOTIFY_COMPLETED => 'COMPLETED', - \STREAM_NOTIFY_RESOLVE => 'RESOLVE', - ]; - static $args = ['severity', 'message', 'message_code', 'bytes_transferred', 'bytes_max']; - - $value = Utils::debugResource($value); - $ident = $request->getMethod().' '.$request->getUri()->withFragment(''); - self::addNotification( - $params, - static function (int $code, ...$passed) use ($ident, $value, $map, $args): void { - \fprintf($value, '<%s> [%s] ', $ident, $map[$code]); - foreach (\array_filter($passed) as $i => $v) { - \fwrite($value, $args[$i].': "'.$v.'" '); - } - \fwrite($value, "\n"); - } - ); - } - - private static function addNotification(array &$params, callable $notify): void - { - // Wrap the existing function if needed. - if (!isset($params['notification'])) { - $params['notification'] = $notify; - } else { - $params['notification'] = self::callArray([ - $params['notification'], - $notify, - ]); - } - } - - private static function callArray(array $functions): callable - { - return static function (...$args) use ($functions) { - foreach ($functions as $fn) { - $fn(...$args); - } - }; - } -} diff --git a/lib/guzzlehttp/guzzle/src/HandlerStack.php b/lib/guzzlehttp/guzzle/src/HandlerStack.php deleted file mode 100644 index 1ce9c4b19..000000000 --- a/lib/guzzlehttp/guzzle/src/HandlerStack.php +++ /dev/null @@ -1,275 +0,0 @@ -<?php - -namespace GuzzleHttp; - -use GuzzleHttp\Promise\PromiseInterface; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; - -/** - * Creates a composed Guzzle handler function by stacking middlewares on top of - * an HTTP handler function. - * - * @final - */ -class HandlerStack -{ - /** - * @var (callable(RequestInterface, array): PromiseInterface)|null - */ - private $handler; - - /** - * @var array{(callable(callable(RequestInterface, array): PromiseInterface): callable), (string|null)}[] - */ - private $stack = []; - - /** - * @var (callable(RequestInterface, array): PromiseInterface)|null - */ - private $cached; - - /** - * Creates a default handler stack that can be used by clients. - * - * The returned handler will wrap the provided handler or use the most - * appropriate default handler for your system. The returned HandlerStack has - * support for cookies, redirects, HTTP error exceptions, and preparing a body - * before sending. - * - * The returned handler stack can be passed to a client in the "handler" - * option. - * - * @param (callable(RequestInterface, array): PromiseInterface)|null $handler HTTP handler function to use with the stack. If no - * handler is provided, the best handler for your - * system will be utilized. - */ - public static function create(?callable $handler = null): self - { - $stack = new self($handler ?: Utils::chooseHandler()); - $stack->push(Middleware::httpErrors(), 'http_errors'); - $stack->push(Middleware::redirect(), 'allow_redirects'); - $stack->push(Middleware::cookies(), 'cookies'); - $stack->push(Middleware::prepareBody(), 'prepare_body'); - - return $stack; - } - - /** - * @param (callable(RequestInterface, array): PromiseInterface)|null $handler Underlying HTTP handler. - */ - public function __construct(callable $handler = null) - { - $this->handler = $handler; - } - - /** - * Invokes the handler stack as a composed handler - * - * @return ResponseInterface|PromiseInterface - */ - public function __invoke(RequestInterface $request, array $options) - { - $handler = $this->resolve(); - - return $handler($request, $options); - } - - /** - * Dumps a string representation of the stack. - * - * @return string - */ - public function __toString() - { - $depth = 0; - $stack = []; - - if ($this->handler !== null) { - $stack[] = '0) Handler: '.$this->debugCallable($this->handler); - } - - $result = ''; - foreach (\array_reverse($this->stack) as $tuple) { - ++$depth; - $str = "{$depth}) Name: '{$tuple[1]}', "; - $str .= 'Function: '.$this->debugCallable($tuple[0]); - $result = "> {$str}\n{$result}"; - $stack[] = $str; - } - - foreach (\array_keys($stack) as $k) { - $result .= "< {$stack[$k]}\n"; - } - - return $result; - } - - /** - * Set the HTTP handler that actually returns a promise. - * - * @param callable(RequestInterface, array): PromiseInterface $handler Accepts a request and array of options and - * returns a Promise. - */ - public function setHandler(callable $handler): void - { - $this->handler = $handler; - $this->cached = null; - } - - /** - * Returns true if the builder has a handler. - */ - public function hasHandler(): bool - { - return $this->handler !== null; - } - - /** - * Unshift a middleware to the bottom of the stack. - * - * @param callable(callable): callable $middleware Middleware function - * @param string $name Name to register for this middleware. - */ - public function unshift(callable $middleware, ?string $name = null): void - { - \array_unshift($this->stack, [$middleware, $name]); - $this->cached = null; - } - - /** - * Push a middleware to the top of the stack. - * - * @param callable(callable): callable $middleware Middleware function - * @param string $name Name to register for this middleware. - */ - public function push(callable $middleware, string $name = ''): void - { - $this->stack[] = [$middleware, $name]; - $this->cached = null; - } - - /** - * Add a middleware before another middleware by name. - * - * @param string $findName Middleware to find - * @param callable(callable): callable $middleware Middleware function - * @param string $withName Name to register for this middleware. - */ - public function before(string $findName, callable $middleware, string $withName = ''): void - { - $this->splice($findName, $withName, $middleware, true); - } - - /** - * Add a middleware after another middleware by name. - * - * @param string $findName Middleware to find - * @param callable(callable): callable $middleware Middleware function - * @param string $withName Name to register for this middleware. - */ - public function after(string $findName, callable $middleware, string $withName = ''): void - { - $this->splice($findName, $withName, $middleware, false); - } - - /** - * Remove a middleware by instance or name from the stack. - * - * @param callable|string $remove Middleware to remove by instance or name. - */ - public function remove($remove): void - { - if (!is_string($remove) && !is_callable($remove)) { - trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a callable or string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); - } - - $this->cached = null; - $idx = \is_callable($remove) ? 0 : 1; - $this->stack = \array_values(\array_filter( - $this->stack, - static function ($tuple) use ($idx, $remove) { - return $tuple[$idx] !== $remove; - } - )); - } - - /** - * Compose the middleware and handler into a single callable function. - * - * @return callable(RequestInterface, array): PromiseInterface - */ - public function resolve(): callable - { - if ($this->cached === null) { - if (($prev = $this->handler) === null) { - throw new \LogicException('No handler has been specified'); - } - - foreach (\array_reverse($this->stack) as $fn) { - /** @var callable(RequestInterface, array): PromiseInterface $prev */ - $prev = $fn[0]($prev); - } - - $this->cached = $prev; - } - - return $this->cached; - } - - private function findByName(string $name): int - { - foreach ($this->stack as $k => $v) { - if ($v[1] === $name) { - return $k; - } - } - - throw new \InvalidArgumentException("Middleware not found: $name"); - } - - /** - * Splices a function into the middleware list at a specific position. - */ - private function splice(string $findName, string $withName, callable $middleware, bool $before): void - { - $this->cached = null; - $idx = $this->findByName($findName); - $tuple = [$middleware, $withName]; - - if ($before) { - if ($idx === 0) { - \array_unshift($this->stack, $tuple); - } else { - $replacement = [$tuple, $this->stack[$idx]]; - \array_splice($this->stack, $idx, 1, $replacement); - } - } elseif ($idx === \count($this->stack) - 1) { - $this->stack[] = $tuple; - } else { - $replacement = [$this->stack[$idx], $tuple]; - \array_splice($this->stack, $idx, 1, $replacement); - } - } - - /** - * Provides a debug string for a given callable. - * - * @param callable|string $fn Function to write as a string. - */ - private function debugCallable($fn): string - { - if (\is_string($fn)) { - return "callable({$fn})"; - } - - if (\is_array($fn)) { - return \is_string($fn[0]) - ? "callable({$fn[0]}::{$fn[1]})" - : "callable(['".\get_class($fn[0])."', '{$fn[1]}'])"; - } - - /** @var object $fn */ - return 'callable('.\spl_object_hash($fn).')'; - } -} diff --git a/lib/guzzlehttp/guzzle/src/MessageFormatter.php b/lib/guzzlehttp/guzzle/src/MessageFormatter.php deleted file mode 100644 index 9b77eee83..000000000 --- a/lib/guzzlehttp/guzzle/src/MessageFormatter.php +++ /dev/null @@ -1,199 +0,0 @@ -<?php - -namespace GuzzleHttp; - -use Psr\Http\Message\MessageInterface; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; - -/** - * Formats log messages using variable substitutions for requests, responses, - * and other transactional data. - * - * The following variable substitutions are supported: - * - * - {request}: Full HTTP request message - * - {response}: Full HTTP response message - * - {ts}: ISO 8601 date in GMT - * - {date_iso_8601} ISO 8601 date in GMT - * - {date_common_log} Apache common log date using the configured timezone. - * - {host}: Host of the request - * - {method}: Method of the request - * - {uri}: URI of the request - * - {version}: Protocol version - * - {target}: Request target of the request (path + query + fragment) - * - {hostname}: Hostname of the machine that sent the request - * - {code}: Status code of the response (if available) - * - {phrase}: Reason phrase of the response (if available) - * - {error}: Any error messages (if available) - * - {req_header_*}: Replace `*` with the lowercased name of a request header to add to the message - * - {res_header_*}: Replace `*` with the lowercased name of a response header to add to the message - * - {req_headers}: Request headers - * - {res_headers}: Response headers - * - {req_body}: Request body - * - {res_body}: Response body - * - * @final - */ -class MessageFormatter implements MessageFormatterInterface -{ - /** - * Apache Common Log Format. - * - * @see https://httpd.apache.org/docs/2.4/logs.html#common - * - * @var string - */ - public const CLF = '{hostname} {req_header_User-Agent} - [{date_common_log}] "{method} {target} HTTP/{version}" {code} {res_header_Content-Length}'; - public const DEBUG = ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}"; - public const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}'; - - /** - * @var string Template used to format log messages - */ - private $template; - - /** - * @param string $template Log message template - */ - public function __construct(?string $template = self::CLF) - { - $this->template = $template ?: self::CLF; - } - - /** - * Returns a formatted message string. - * - * @param RequestInterface $request Request that was sent - * @param ResponseInterface|null $response Response that was received - * @param \Throwable|null $error Exception that was received - */ - public function format(RequestInterface $request, ?ResponseInterface $response = null, ?\Throwable $error = null): string - { - $cache = []; - - /** @var string */ - return \preg_replace_callback( - '/{\s*([A-Za-z_\-\.0-9]+)\s*}/', - function (array $matches) use ($request, $response, $error, &$cache) { - if (isset($cache[$matches[1]])) { - return $cache[$matches[1]]; - } - - $result = ''; - switch ($matches[1]) { - case 'request': - $result = Psr7\Message::toString($request); - break; - case 'response': - $result = $response ? Psr7\Message::toString($response) : ''; - break; - case 'req_headers': - $result = \trim($request->getMethod() - .' '.$request->getRequestTarget()) - .' HTTP/'.$request->getProtocolVersion()."\r\n" - .$this->headers($request); - break; - case 'res_headers': - $result = $response ? - \sprintf( - 'HTTP/%s %d %s', - $response->getProtocolVersion(), - $response->getStatusCode(), - $response->getReasonPhrase() - )."\r\n".$this->headers($response) - : 'NULL'; - break; - case 'req_body': - $result = $request->getBody()->__toString(); - break; - case 'res_body': - if (!$response instanceof ResponseInterface) { - $result = 'NULL'; - break; - } - - $body = $response->getBody(); - - if (!$body->isSeekable()) { - $result = 'RESPONSE_NOT_LOGGEABLE'; - break; - } - - $result = $response->getBody()->__toString(); - break; - case 'ts': - case 'date_iso_8601': - $result = \gmdate('c'); - break; - case 'date_common_log': - $result = \date('d/M/Y:H:i:s O'); - break; - case 'method': - $result = $request->getMethod(); - break; - case 'version': - $result = $request->getProtocolVersion(); - break; - case 'uri': - case 'url': - $result = $request->getUri()->__toString(); - break; - case 'target': - $result = $request->getRequestTarget(); - break; - case 'req_version': - $result = $request->getProtocolVersion(); - break; - case 'res_version': - $result = $response - ? $response->getProtocolVersion() - : 'NULL'; - break; - case 'host': - $result = $request->getHeaderLine('Host'); - break; - case 'hostname': - $result = \gethostname(); - break; - case 'code': - $result = $response ? $response->getStatusCode() : 'NULL'; - break; - case 'phrase': - $result = $response ? $response->getReasonPhrase() : 'NULL'; - break; - case 'error': - $result = $error ? $error->getMessage() : 'NULL'; - break; - default: - // handle prefixed dynamic headers - if (\strpos($matches[1], 'req_header_') === 0) { - $result = $request->getHeaderLine(\substr($matches[1], 11)); - } elseif (\strpos($matches[1], 'res_header_') === 0) { - $result = $response - ? $response->getHeaderLine(\substr($matches[1], 11)) - : 'NULL'; - } - } - - $cache[$matches[1]] = $result; - - return $result; - }, - $this->template - ); - } - - /** - * Get headers from message as string - */ - private function headers(MessageInterface $message): string - { - $result = ''; - foreach ($message->getHeaders() as $name => $values) { - $result .= $name.': '.\implode(', ', $values)."\r\n"; - } - - return \trim($result); - } -} diff --git a/lib/guzzlehttp/guzzle/src/MessageFormatterInterface.php b/lib/guzzlehttp/guzzle/src/MessageFormatterInterface.php deleted file mode 100644 index a39ac248e..000000000 --- a/lib/guzzlehttp/guzzle/src/MessageFormatterInterface.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php - -namespace GuzzleHttp; - -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; - -interface MessageFormatterInterface -{ - /** - * Returns a formatted message string. - * - * @param RequestInterface $request Request that was sent - * @param ResponseInterface|null $response Response that was received - * @param \Throwable|null $error Exception that was received - */ - public function format(RequestInterface $request, ?ResponseInterface $response = null, ?\Throwable $error = null): string; -} diff --git a/lib/guzzlehttp/guzzle/src/Middleware.php b/lib/guzzlehttp/guzzle/src/Middleware.php deleted file mode 100644 index 7e3eb6b3a..000000000 --- a/lib/guzzlehttp/guzzle/src/Middleware.php +++ /dev/null @@ -1,268 +0,0 @@ -<?php - -namespace GuzzleHttp; - -use GuzzleHttp\Cookie\CookieJarInterface; -use GuzzleHttp\Exception\RequestException; -use GuzzleHttp\Promise as P; -use GuzzleHttp\Promise\PromiseInterface; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; -use Psr\Log\LoggerInterface; - -/** - * Functions used to create and wrap handlers with handler middleware. - */ -final class Middleware -{ - /** - * Middleware that adds cookies to requests. - * - * The options array must be set to a CookieJarInterface in order to use - * cookies. This is typically handled for you by a client. - * - * @return callable Returns a function that accepts the next handler. - */ - public static function cookies(): callable - { - return static function (callable $handler): callable { - return static function ($request, array $options) use ($handler) { - if (empty($options['cookies'])) { - return $handler($request, $options); - } elseif (!($options['cookies'] instanceof CookieJarInterface)) { - throw new \InvalidArgumentException('cookies must be an instance of GuzzleHttp\Cookie\CookieJarInterface'); - } - $cookieJar = $options['cookies']; - $request = $cookieJar->withCookieHeader($request); - - return $handler($request, $options) - ->then( - static function (ResponseInterface $response) use ($cookieJar, $request): ResponseInterface { - $cookieJar->extractCookies($request, $response); - - return $response; - } - ); - }; - }; - } - - /** - * Middleware that throws exceptions for 4xx or 5xx responses when the - * "http_errors" request option is set to true. - * - * @param BodySummarizerInterface|null $bodySummarizer The body summarizer to use in exception messages. - * - * @return callable(callable): callable Returns a function that accepts the next handler. - */ - public static function httpErrors(BodySummarizerInterface $bodySummarizer = null): callable - { - return static function (callable $handler) use ($bodySummarizer): callable { - return static function ($request, array $options) use ($handler, $bodySummarizer) { - if (empty($options['http_errors'])) { - return $handler($request, $options); - } - - return $handler($request, $options)->then( - static function (ResponseInterface $response) use ($request, $bodySummarizer) { - $code = $response->getStatusCode(); - if ($code < 400) { - return $response; - } - throw RequestException::create($request, $response, null, [], $bodySummarizer); - } - ); - }; - }; - } - - /** - * Middleware that pushes history data to an ArrayAccess container. - * - * @param array|\ArrayAccess<int, array> $container Container to hold the history (by reference). - * - * @return callable(callable): callable Returns a function that accepts the next handler. - * - * @throws \InvalidArgumentException if container is not an array or ArrayAccess. - */ - public static function history(&$container): callable - { - if (!\is_array($container) && !$container instanceof \ArrayAccess) { - throw new \InvalidArgumentException('history container must be an array or object implementing ArrayAccess'); - } - - return static function (callable $handler) use (&$container): callable { - return static function (RequestInterface $request, array $options) use ($handler, &$container) { - return $handler($request, $options)->then( - static function ($value) use ($request, &$container, $options) { - $container[] = [ - 'request' => $request, - 'response' => $value, - 'error' => null, - 'options' => $options, - ]; - - return $value; - }, - static function ($reason) use ($request, &$container, $options) { - $container[] = [ - 'request' => $request, - 'response' => null, - 'error' => $reason, - 'options' => $options, - ]; - - return P\Create::rejectionFor($reason); - } - ); - }; - }; - } - - /** - * Middleware that invokes a callback before and after sending a request. - * - * The provided listener cannot modify or alter the response. It simply - * "taps" into the chain to be notified before returning the promise. The - * before listener accepts a request and options array, and the after - * listener accepts a request, options array, and response promise. - * - * @param callable $before Function to invoke before forwarding the request. - * @param callable $after Function invoked after forwarding. - * - * @return callable Returns a function that accepts the next handler. - */ - public static function tap(callable $before = null, callable $after = null): callable - { - return static function (callable $handler) use ($before, $after): callable { - return static function (RequestInterface $request, array $options) use ($handler, $before, $after) { - if ($before) { - $before($request, $options); - } - $response = $handler($request, $options); - if ($after) { - $after($request, $options, $response); - } - - return $response; - }; - }; - } - - /** - * Middleware that handles request redirects. - * - * @return callable Returns a function that accepts the next handler. - */ - public static function redirect(): callable - { - return static function (callable $handler): RedirectMiddleware { - return new RedirectMiddleware($handler); - }; - } - - /** - * Middleware that retries requests based on the boolean result of - * invoking the provided "decider" function. - * - * If no delay function is provided, a simple implementation of exponential - * backoff will be utilized. - * - * @param callable $decider Function that accepts the number of retries, - * a request, [response], and [exception] and - * returns true if the request is to be retried. - * @param callable $delay Function that accepts the number of retries and - * returns the number of milliseconds to delay. - * - * @return callable Returns a function that accepts the next handler. - */ - public static function retry(callable $decider, callable $delay = null): callable - { - return static function (callable $handler) use ($decider, $delay): RetryMiddleware { - return new RetryMiddleware($decider, $handler, $delay); - }; - } - - /** - * Middleware that logs requests, responses, and errors using a message - * formatter. - * - * @phpstan-param \Psr\Log\LogLevel::* $logLevel Level at which to log requests. - * - * @param LoggerInterface $logger Logs messages. - * @param MessageFormatterInterface|MessageFormatter $formatter Formatter used to create message strings. - * @param string $logLevel Level at which to log requests. - * - * @return callable Returns a function that accepts the next handler. - */ - public static function log(LoggerInterface $logger, $formatter, string $logLevel = 'info'): callable - { - // To be compatible with Guzzle 7.1.x we need to allow users to pass a MessageFormatter - if (!$formatter instanceof MessageFormatter && !$formatter instanceof MessageFormatterInterface) { - throw new \LogicException(sprintf('Argument 2 to %s::log() must be of type %s', self::class, MessageFormatterInterface::class)); - } - - return static function (callable $handler) use ($logger, $formatter, $logLevel): callable { - return static function (RequestInterface $request, array $options = []) use ($handler, $logger, $formatter, $logLevel) { - return $handler($request, $options)->then( - static function ($response) use ($logger, $request, $formatter, $logLevel): ResponseInterface { - $message = $formatter->format($request, $response); - $logger->log($logLevel, $message); - - return $response; - }, - static function ($reason) use ($logger, $request, $formatter): PromiseInterface { - $response = $reason instanceof RequestException ? $reason->getResponse() : null; - $message = $formatter->format($request, $response, P\Create::exceptionFor($reason)); - $logger->error($message); - - return P\Create::rejectionFor($reason); - } - ); - }; - }; - } - - /** - * This middleware adds a default content-type if possible, a default - * content-length or transfer-encoding header, and the expect header. - */ - public static function prepareBody(): callable - { - return static function (callable $handler): PrepareBodyMiddleware { - return new PrepareBodyMiddleware($handler); - }; - } - - /** - * Middleware that applies a map function to the request before passing to - * the next handler. - * - * @param callable $fn Function that accepts a RequestInterface and returns - * a RequestInterface. - */ - public static function mapRequest(callable $fn): callable - { - return static function (callable $handler) use ($fn): callable { - return static function (RequestInterface $request, array $options) use ($handler, $fn) { - return $handler($fn($request), $options); - }; - }; - } - - /** - * Middleware that applies a map function to the resolved promise's - * response. - * - * @param callable $fn Function that accepts a ResponseInterface and - * returns a ResponseInterface. - */ - public static function mapResponse(callable $fn): callable - { - return static function (callable $handler) use ($fn): callable { - return static function (RequestInterface $request, array $options) use ($handler, $fn) { - return $handler($request, $options)->then($fn); - }; - }; - } -} diff --git a/lib/guzzlehttp/guzzle/src/Pool.php b/lib/guzzlehttp/guzzle/src/Pool.php deleted file mode 100644 index 6277c61fb..000000000 --- a/lib/guzzlehttp/guzzle/src/Pool.php +++ /dev/null @@ -1,125 +0,0 @@ -<?php - -namespace GuzzleHttp; - -use GuzzleHttp\Promise as P; -use GuzzleHttp\Promise\EachPromise; -use GuzzleHttp\Promise\PromiseInterface; -use GuzzleHttp\Promise\PromisorInterface; -use Psr\Http\Message\RequestInterface; - -/** - * Sends an iterator of requests concurrently using a capped pool size. - * - * The pool will read from an iterator until it is cancelled or until the - * iterator is consumed. When a request is yielded, the request is sent after - * applying the "request_options" request options (if provided in the ctor). - * - * When a function is yielded by the iterator, the function is provided the - * "request_options" array that should be merged on top of any existing - * options, and the function MUST then return a wait-able promise. - * - * @final - */ -class Pool implements PromisorInterface -{ - /** - * @var EachPromise - */ - private $each; - - /** - * @param ClientInterface $client Client used to send the requests. - * @param array|\Iterator $requests Requests or functions that return - * requests to send concurrently. - * @param array $config Associative array of options - * - concurrency: (int) Maximum number of requests to send concurrently - * - options: Array of request options to apply to each request. - * - fulfilled: (callable) Function to invoke when a request completes. - * - rejected: (callable) Function to invoke when a request is rejected. - */ - public function __construct(ClientInterface $client, $requests, array $config = []) - { - if (!isset($config['concurrency'])) { - $config['concurrency'] = 25; - } - - if (isset($config['options'])) { - $opts = $config['options']; - unset($config['options']); - } else { - $opts = []; - } - - $iterable = P\Create::iterFor($requests); - $requests = static function () use ($iterable, $client, $opts) { - foreach ($iterable as $key => $rfn) { - if ($rfn instanceof RequestInterface) { - yield $key => $client->sendAsync($rfn, $opts); - } elseif (\is_callable($rfn)) { - yield $key => $rfn($opts); - } else { - throw new \InvalidArgumentException('Each value yielded by the iterator must be a Psr7\Http\Message\RequestInterface or a callable that returns a promise that fulfills with a Psr7\Message\Http\ResponseInterface object.'); - } - } - }; - - $this->each = new EachPromise($requests(), $config); - } - - /** - * Get promise - */ - public function promise(): PromiseInterface - { - return $this->each->promise(); - } - - /** - * Sends multiple requests concurrently and returns an array of responses - * and exceptions that uses the same ordering as the provided requests. - * - * IMPORTANT: This method keeps every request and response in memory, and - * as such, is NOT recommended when sending a large number or an - * indeterminate number of requests concurrently. - * - * @param ClientInterface $client Client used to send the requests - * @param array|\Iterator $requests Requests to send concurrently. - * @param array $options Passes through the options available in - * {@see \GuzzleHttp\Pool::__construct} - * - * @return array Returns an array containing the response or an exception - * in the same order that the requests were sent. - * - * @throws \InvalidArgumentException if the event format is incorrect. - */ - public static function batch(ClientInterface $client, $requests, array $options = []): array - { - $res = []; - self::cmpCallback($options, 'fulfilled', $res); - self::cmpCallback($options, 'rejected', $res); - $pool = new static($client, $requests, $options); - $pool->promise()->wait(); - \ksort($res); - - return $res; - } - - /** - * Execute callback(s) - */ - private static function cmpCallback(array &$options, string $name, array &$results): void - { - if (!isset($options[$name])) { - $options[$name] = static function ($v, $k) use (&$results) { - $results[$k] = $v; - }; - } else { - $currentFn = $options[$name]; - $options[$name] = static function ($v, $k) use (&$results, $currentFn) { - $currentFn($v, $k); - $results[$k] = $v; - }; - } - } -} diff --git a/lib/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php b/lib/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php deleted file mode 100644 index 0a8de8128..000000000 --- a/lib/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php +++ /dev/null @@ -1,105 +0,0 @@ -<?php - -namespace GuzzleHttp; - -use GuzzleHttp\Promise\PromiseInterface; -use Psr\Http\Message\RequestInterface; - -/** - * Prepares requests that contain a body, adding the Content-Length, - * Content-Type, and Expect headers. - * - * @final - */ -class PrepareBodyMiddleware -{ - /** - * @var callable(RequestInterface, array): PromiseInterface - */ - private $nextHandler; - - /** - * @param callable(RequestInterface, array): PromiseInterface $nextHandler Next handler to invoke. - */ - public function __construct(callable $nextHandler) - { - $this->nextHandler = $nextHandler; - } - - public function __invoke(RequestInterface $request, array $options): PromiseInterface - { - $fn = $this->nextHandler; - - // Don't do anything if the request has no body. - if ($request->getBody()->getSize() === 0) { - return $fn($request, $options); - } - - $modify = []; - - // Add a default content-type if possible. - if (!$request->hasHeader('Content-Type')) { - if ($uri = $request->getBody()->getMetadata('uri')) { - if (is_string($uri) && $type = Psr7\MimeType::fromFilename($uri)) { - $modify['set_headers']['Content-Type'] = $type; - } - } - } - - // Add a default content-length or transfer-encoding header. - if (!$request->hasHeader('Content-Length') - && !$request->hasHeader('Transfer-Encoding') - ) { - $size = $request->getBody()->getSize(); - if ($size !== null) { - $modify['set_headers']['Content-Length'] = $size; - } else { - $modify['set_headers']['Transfer-Encoding'] = 'chunked'; - } - } - - // Add the expect header if needed. - $this->addExpectHeader($request, $options, $modify); - - return $fn(Psr7\Utils::modifyRequest($request, $modify), $options); - } - - /** - * Add expect header - */ - private function addExpectHeader(RequestInterface $request, array $options, array &$modify): void - { - // Determine if the Expect header should be used - if ($request->hasHeader('Expect')) { - return; - } - - $expect = $options['expect'] ?? null; - - // Return if disabled or if you're not using HTTP/1.1 or HTTP/2.0 - if ($expect === false || $request->getProtocolVersion() < 1.1) { - return; - } - - // The expect header is unconditionally enabled - if ($expect === true) { - $modify['set_headers']['Expect'] = '100-Continue'; - - return; - } - - // By default, send the expect header when the payload is > 1mb - if ($expect === null) { - $expect = 1048576; - } - - // Always add if the body cannot be rewound, the size cannot be - // determined, or the size is greater than the cutoff threshold - $body = $request->getBody(); - $size = $body->getSize(); - - if ($size === null || $size >= (int) $expect || !$body->isSeekable()) { - $modify['set_headers']['Expect'] = '100-Continue'; - } - } -} diff --git a/lib/guzzlehttp/guzzle/src/RedirectMiddleware.php b/lib/guzzlehttp/guzzle/src/RedirectMiddleware.php deleted file mode 100644 index f32808a75..000000000 --- a/lib/guzzlehttp/guzzle/src/RedirectMiddleware.php +++ /dev/null @@ -1,228 +0,0 @@ -<?php - -namespace GuzzleHttp; - -use GuzzleHttp\Exception\BadResponseException; -use GuzzleHttp\Exception\TooManyRedirectsException; -use GuzzleHttp\Promise\PromiseInterface; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\UriInterface; - -/** - * Request redirect middleware. - * - * Apply this middleware like other middleware using - * {@see \GuzzleHttp\Middleware::redirect()}. - * - * @final - */ -class RedirectMiddleware -{ - public const HISTORY_HEADER = 'X-Guzzle-Redirect-History'; - - public const STATUS_HISTORY_HEADER = 'X-Guzzle-Redirect-Status-History'; - - /** - * @var array - */ - public static $defaultSettings = [ - 'max' => 5, - 'protocols' => ['http', 'https'], - 'strict' => false, - 'referer' => false, - 'track_redirects' => false, - ]; - - /** - * @var callable(RequestInterface, array): PromiseInterface - */ - private $nextHandler; - - /** - * @param callable(RequestInterface, array): PromiseInterface $nextHandler Next handler to invoke. - */ - public function __construct(callable $nextHandler) - { - $this->nextHandler = $nextHandler; - } - - public function __invoke(RequestInterface $request, array $options): PromiseInterface - { - $fn = $this->nextHandler; - - if (empty($options['allow_redirects'])) { - return $fn($request, $options); - } - - if ($options['allow_redirects'] === true) { - $options['allow_redirects'] = self::$defaultSettings; - } elseif (!\is_array($options['allow_redirects'])) { - throw new \InvalidArgumentException('allow_redirects must be true, false, or array'); - } else { - // Merge the default settings with the provided settings - $options['allow_redirects'] += self::$defaultSettings; - } - - if (empty($options['allow_redirects']['max'])) { - return $fn($request, $options); - } - - return $fn($request, $options) - ->then(function (ResponseInterface $response) use ($request, $options) { - return $this->checkRedirect($request, $options, $response); - }); - } - - /** - * @return ResponseInterface|PromiseInterface - */ - public function checkRedirect(RequestInterface $request, array $options, ResponseInterface $response) - { - if (\strpos((string) $response->getStatusCode(), '3') !== 0 - || !$response->hasHeader('Location') - ) { - return $response; - } - - $this->guardMax($request, $response, $options); - $nextRequest = $this->modifyRequest($request, $options, $response); - - // If authorization is handled by curl, unset it if URI is cross-origin. - if (Psr7\UriComparator::isCrossOrigin($request->getUri(), $nextRequest->getUri()) && defined('\CURLOPT_HTTPAUTH')) { - unset( - $options['curl'][\CURLOPT_HTTPAUTH], - $options['curl'][\CURLOPT_USERPWD] - ); - } - - if (isset($options['allow_redirects']['on_redirect'])) { - ($options['allow_redirects']['on_redirect'])( - $request, - $response, - $nextRequest->getUri() - ); - } - - $promise = $this($nextRequest, $options); - - // Add headers to be able to track history of redirects. - if (!empty($options['allow_redirects']['track_redirects'])) { - return $this->withTracking( - $promise, - (string) $nextRequest->getUri(), - $response->getStatusCode() - ); - } - - return $promise; - } - - /** - * Enable tracking on promise. - */ - private function withTracking(PromiseInterface $promise, string $uri, int $statusCode): PromiseInterface - { - return $promise->then( - static function (ResponseInterface $response) use ($uri, $statusCode) { - // Note that we are pushing to the front of the list as this - // would be an earlier response than what is currently present - // in the history header. - $historyHeader = $response->getHeader(self::HISTORY_HEADER); - $statusHeader = $response->getHeader(self::STATUS_HISTORY_HEADER); - \array_unshift($historyHeader, $uri); - \array_unshift($statusHeader, (string) $statusCode); - - return $response->withHeader(self::HISTORY_HEADER, $historyHeader) - ->withHeader(self::STATUS_HISTORY_HEADER, $statusHeader); - } - ); - } - - /** - * Check for too many redirects. - * - * @throws TooManyRedirectsException Too many redirects. - */ - private function guardMax(RequestInterface $request, ResponseInterface $response, array &$options): void - { - $current = $options['__redirect_count'] - ?? 0; - $options['__redirect_count'] = $current + 1; - $max = $options['allow_redirects']['max']; - - if ($options['__redirect_count'] > $max) { - throw new TooManyRedirectsException("Will not follow more than {$max} redirects", $request, $response); - } - } - - public function modifyRequest(RequestInterface $request, array $options, ResponseInterface $response): RequestInterface - { - // Request modifications to apply. - $modify = []; - $protocols = $options['allow_redirects']['protocols']; - - // Use a GET request if this is an entity enclosing request and we are - // not forcing RFC compliance, but rather emulating what all browsers - // would do. - $statusCode = $response->getStatusCode(); - if ($statusCode == 303 || - ($statusCode <= 302 && !$options['allow_redirects']['strict']) - ) { - $safeMethods = ['GET', 'HEAD', 'OPTIONS']; - $requestMethod = $request->getMethod(); - - $modify['method'] = in_array($requestMethod, $safeMethods) ? $requestMethod : 'GET'; - $modify['body'] = ''; - } - - $uri = self::redirectUri($request, $response, $protocols); - if (isset($options['idn_conversion']) && ($options['idn_conversion'] !== false)) { - $idnOptions = ($options['idn_conversion'] === true) ? \IDNA_DEFAULT : $options['idn_conversion']; - $uri = Utils::idnUriConvert($uri, $idnOptions); - } - - $modify['uri'] = $uri; - Psr7\Message::rewindBody($request); - - // Add the Referer header if it is told to do so and only - // add the header if we are not redirecting from https to http. - if ($options['allow_redirects']['referer'] - && $modify['uri']->getScheme() === $request->getUri()->getScheme() - ) { - $uri = $request->getUri()->withUserInfo(''); - $modify['set_headers']['Referer'] = (string) $uri; - } else { - $modify['remove_headers'][] = 'Referer'; - } - - // Remove Authorization and Cookie headers if URI is cross-origin. - if (Psr7\UriComparator::isCrossOrigin($request->getUri(), $modify['uri'])) { - $modify['remove_headers'][] = 'Authorization'; - $modify['remove_headers'][] = 'Cookie'; - } - - return Psr7\Utils::modifyRequest($request, $modify); - } - - /** - * Set the appropriate URL on the request based on the location header. - */ - private static function redirectUri( - RequestInterface $request, - ResponseInterface $response, - array $protocols - ): UriInterface { - $location = Psr7\UriResolver::resolve( - $request->getUri(), - new Psr7\Uri($response->getHeaderLine('Location')) - ); - - // Ensure that the redirect URI is allowed based on the protocols. - if (!\in_array($location->getScheme(), $protocols)) { - throw new BadResponseException(\sprintf('Redirect URI, %s, does not use one of the allowed redirect protocols: %s', $location, \implode(', ', $protocols)), $request, $response); - } - - return $location; - } -} diff --git a/lib/guzzlehttp/guzzle/src/RequestOptions.php b/lib/guzzlehttp/guzzle/src/RequestOptions.php deleted file mode 100644 index bf3b02b6b..000000000 --- a/lib/guzzlehttp/guzzle/src/RequestOptions.php +++ /dev/null @@ -1,276 +0,0 @@ -<?php - -namespace GuzzleHttp; - -/** - * This class contains a list of built-in Guzzle request options. - * - * More documentation for each option can be found at http://guzzlephp.org/. - * - * @see http://docs.guzzlephp.org/en/v6/request-options.html - */ -final class RequestOptions -{ - /** - * allow_redirects: (bool|array) Controls redirect behavior. Pass false - * to disable redirects, pass true to enable redirects, pass an - * associative to provide custom redirect settings. Defaults to "false". - * This option only works if your handler has the RedirectMiddleware. When - * passing an associative array, you can provide the following key value - * pairs: - * - * - max: (int, default=5) maximum number of allowed redirects. - * - strict: (bool, default=false) Set to true to use strict redirects - * meaning redirect POST requests with POST requests vs. doing what most - * browsers do which is redirect POST requests with GET requests - * - referer: (bool, default=false) Set to true to enable the Referer - * header. - * - protocols: (array, default=['http', 'https']) Allowed redirect - * protocols. - * - on_redirect: (callable) PHP callable that is invoked when a redirect - * is encountered. The callable is invoked with the request, the redirect - * response that was received, and the effective URI. Any return value - * from the on_redirect function is ignored. - */ - public const ALLOW_REDIRECTS = 'allow_redirects'; - - /** - * auth: (array) Pass an array of HTTP authentication parameters to use - * with the request. The array must contain the username in index [0], - * the password in index [1], and you can optionally provide a built-in - * authentication type in index [2]. Pass null to disable authentication - * for a request. - */ - public const AUTH = 'auth'; - - /** - * body: (resource|string|null|int|float|StreamInterface|callable|\Iterator) - * Body to send in the request. - */ - public const BODY = 'body'; - - /** - * cert: (string|array) Set to a string to specify the path to a file - * containing a PEM formatted SSL client side certificate. If a password - * is required, then set cert to an array containing the path to the PEM - * file in the first array element followed by the certificate password - * in the second array element. - */ - public const CERT = 'cert'; - - /** - * cookies: (bool|GuzzleHttp\Cookie\CookieJarInterface, default=false) - * Specifies whether or not cookies are used in a request or what cookie - * jar to use or what cookies to send. This option only works if your - * handler has the `cookie` middleware. Valid values are `false` and - * an instance of {@see \GuzzleHttp\Cookie\CookieJarInterface}. - */ - public const COOKIES = 'cookies'; - - /** - * connect_timeout: (float, default=0) Float describing the number of - * seconds to wait while trying to connect to a server. Use 0 to wait - * 300 seconds (the default behavior). - */ - public const CONNECT_TIMEOUT = 'connect_timeout'; - - /** - * crypto_method: (int) A value describing the minimum TLS protocol - * version to use. - * - * This setting must be set to one of the - * ``STREAM_CRYPTO_METHOD_TLS*_CLIENT`` constants. PHP 7.4 or higher is - * required in order to use TLS 1.3, and cURL 7.34.0 or higher is required - * in order to specify a crypto method, with cURL 7.52.0 or higher being - * required to use TLS 1.3. - */ - public const CRYPTO_METHOD = 'crypto_method'; - - /** - * debug: (bool|resource) Set to true or set to a PHP stream returned by - * fopen() enable debug output with the HTTP handler used to send a - * request. - */ - public const DEBUG = 'debug'; - - /** - * decode_content: (bool, default=true) Specify whether or not - * Content-Encoding responses (gzip, deflate, etc.) are automatically - * decoded. - */ - public const DECODE_CONTENT = 'decode_content'; - - /** - * delay: (int) The amount of time to delay before sending in milliseconds. - */ - public const DELAY = 'delay'; - - /** - * expect: (bool|integer) Controls the behavior of the - * "Expect: 100-Continue" header. - * - * Set to `true` to enable the "Expect: 100-Continue" header for all - * requests that sends a body. Set to `false` to disable the - * "Expect: 100-Continue" header for all requests. Set to a number so that - * the size of the payload must be greater than the number in order to send - * the Expect header. Setting to a number will send the Expect header for - * all requests in which the size of the payload cannot be determined or - * where the body is not rewindable. - * - * By default, Guzzle will add the "Expect: 100-Continue" header when the - * size of the body of a request is greater than 1 MB and a request is - * using HTTP/1.1. - */ - public const EXPECT = 'expect'; - - /** - * form_params: (array) Associative array of form field names to values - * where each value is a string or array of strings. Sets the Content-Type - * header to application/x-www-form-urlencoded when no Content-Type header - * is already present. - */ - public const FORM_PARAMS = 'form_params'; - - /** - * headers: (array) Associative array of HTTP headers. Each value MUST be - * a string or array of strings. - */ - public const HEADERS = 'headers'; - - /** - * http_errors: (bool, default=true) Set to false to disable exceptions - * when a non- successful HTTP response is received. By default, - * exceptions will be thrown for 4xx and 5xx responses. This option only - * works if your handler has the `httpErrors` middleware. - */ - public const HTTP_ERRORS = 'http_errors'; - - /** - * idn: (bool|int, default=true) A combination of IDNA_* constants for - * idn_to_ascii() PHP's function (see "options" parameter). Set to false to - * disable IDN support completely, or to true to use the default - * configuration (IDNA_DEFAULT constant). - */ - public const IDN_CONVERSION = 'idn_conversion'; - - /** - * json: (mixed) Adds JSON data to a request. The provided value is JSON - * encoded and a Content-Type header of application/json will be added to - * the request if no Content-Type header is already present. - */ - public const JSON = 'json'; - - /** - * multipart: (array) Array of associative arrays, each containing a - * required "name" key mapping to the form field, name, a required - * "contents" key mapping to a StreamInterface|resource|string, an - * optional "headers" associative array of custom headers, and an - * optional "filename" key mapping to a string to send as the filename in - * the part. If no "filename" key is present, then no "filename" attribute - * will be added to the part. - */ - public const MULTIPART = 'multipart'; - - /** - * on_headers: (callable) A callable that is invoked when the HTTP headers - * of the response have been received but the body has not yet begun to - * download. - */ - public const ON_HEADERS = 'on_headers'; - - /** - * on_stats: (callable) allows you to get access to transfer statistics of - * a request and access the lower level transfer details of the handler - * associated with your client. ``on_stats`` is a callable that is invoked - * when a handler has finished sending a request. The callback is invoked - * with transfer statistics about the request, the response received, or - * the error encountered. Included in the data is the total amount of time - * taken to send the request. - */ - public const ON_STATS = 'on_stats'; - - /** - * progress: (callable) Defines a function to invoke when transfer - * progress is made. The function accepts the following positional - * arguments: the total number of bytes expected to be downloaded, the - * number of bytes downloaded so far, the number of bytes expected to be - * uploaded, the number of bytes uploaded so far. - */ - public const PROGRESS = 'progress'; - - /** - * proxy: (string|array) Pass a string to specify an HTTP proxy, or an - * array to specify different proxies for different protocols (where the - * key is the protocol and the value is a proxy string). - */ - public const PROXY = 'proxy'; - - /** - * query: (array|string) Associative array of query string values to add - * to the request. This option uses PHP's http_build_query() to create - * the string representation. Pass a string value if you need more - * control than what this method provides - */ - public const QUERY = 'query'; - - /** - * sink: (resource|string|StreamInterface) Where the data of the - * response is written to. Defaults to a PHP temp stream. Providing a - * string will write data to a file by the given name. - */ - public const SINK = 'sink'; - - /** - * synchronous: (bool) Set to true to inform HTTP handlers that you intend - * on waiting on the response. This can be useful for optimizations. Note - * that a promise is still returned if you are using one of the async - * client methods. - */ - public const SYNCHRONOUS = 'synchronous'; - - /** - * ssl_key: (array|string) Specify the path to a file containing a private - * SSL key in PEM format. If a password is required, then set to an array - * containing the path to the SSL key in the first array element followed - * by the password required for the certificate in the second element. - */ - public const SSL_KEY = 'ssl_key'; - - /** - * stream: Set to true to attempt to stream a response rather than - * download it all up-front. - */ - public const STREAM = 'stream'; - - /** - * verify: (bool|string, default=true) Describes the SSL certificate - * verification behavior of a request. Set to true to enable SSL - * certificate verification using the system CA bundle when available - * (the default). Set to false to disable certificate verification (this - * is insecure!). Set to a string to provide the path to a CA bundle on - * disk to enable verification using a custom certificate. - */ - public const VERIFY = 'verify'; - - /** - * timeout: (float, default=0) Float describing the timeout of the - * request in seconds. Use 0 to wait indefinitely (the default behavior). - */ - public const TIMEOUT = 'timeout'; - - /** - * read_timeout: (float, default=default_socket_timeout ini setting) Float describing - * the body read timeout, for stream requests. - */ - public const READ_TIMEOUT = 'read_timeout'; - - /** - * version: (float) Specifies the HTTP protocol version to attempt to use. - */ - public const VERSION = 'version'; - - /** - * force_ip_resolve: (bool) Force client to use only ipv4 or ipv6 protocol - */ - public const FORCE_IP_RESOLVE = 'force_ip_resolve'; -} diff --git a/lib/guzzlehttp/guzzle/src/RetryMiddleware.php b/lib/guzzlehttp/guzzle/src/RetryMiddleware.php deleted file mode 100644 index 8f4d93ac4..000000000 --- a/lib/guzzlehttp/guzzle/src/RetryMiddleware.php +++ /dev/null @@ -1,119 +0,0 @@ -<?php - -namespace GuzzleHttp; - -use GuzzleHttp\Promise as P; -use GuzzleHttp\Promise\PromiseInterface; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; - -/** - * Middleware that retries requests based on the boolean result of - * invoking the provided "decider" function. - * - * @final - */ -class RetryMiddleware -{ - /** - * @var callable(RequestInterface, array): PromiseInterface - */ - private $nextHandler; - - /** - * @var callable - */ - private $decider; - - /** - * @var callable(int) - */ - private $delay; - - /** - * @param callable $decider Function that accepts the number of retries, - * a request, [response], and [exception] and - * returns true if the request is to be - * retried. - * @param callable(RequestInterface, array): PromiseInterface $nextHandler Next handler to invoke. - * @param (callable(int): int)|null $delay Function that accepts the number of retries - * and returns the number of - * milliseconds to delay. - */ - public function __construct(callable $decider, callable $nextHandler, callable $delay = null) - { - $this->decider = $decider; - $this->nextHandler = $nextHandler; - $this->delay = $delay ?: __CLASS__.'::exponentialDelay'; - } - - /** - * Default exponential backoff delay function. - * - * @return int milliseconds. - */ - public static function exponentialDelay(int $retries): int - { - return (int) 2 ** ($retries - 1) * 1000; - } - - public function __invoke(RequestInterface $request, array $options): PromiseInterface - { - if (!isset($options['retries'])) { - $options['retries'] = 0; - } - - $fn = $this->nextHandler; - - return $fn($request, $options) - ->then( - $this->onFulfilled($request, $options), - $this->onRejected($request, $options) - ); - } - - /** - * Execute fulfilled closure - */ - private function onFulfilled(RequestInterface $request, array $options): callable - { - return function ($value) use ($request, $options) { - if (!($this->decider)( - $options['retries'], - $request, - $value, - null - )) { - return $value; - } - - return $this->doRetry($request, $options, $value); - }; - } - - /** - * Execute rejected closure - */ - private function onRejected(RequestInterface $req, array $options): callable - { - return function ($reason) use ($req, $options) { - if (!($this->decider)( - $options['retries'], - $req, - null, - $reason - )) { - return P\Create::rejectionFor($reason); - } - - return $this->doRetry($req, $options); - }; - } - - private function doRetry(RequestInterface $request, array $options, ResponseInterface $response = null): PromiseInterface - { - $options['delay'] = ($this->delay)(++$options['retries'], $response, $request); - - return $this($request, $options); - } -} diff --git a/lib/guzzlehttp/guzzle/src/TransferStats.php b/lib/guzzlehttp/guzzle/src/TransferStats.php deleted file mode 100644 index 93fa334c8..000000000 --- a/lib/guzzlehttp/guzzle/src/TransferStats.php +++ /dev/null @@ -1,133 +0,0 @@ -<?php - -namespace GuzzleHttp; - -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\UriInterface; - -/** - * Represents data at the point after it was transferred either successfully - * or after a network error. - */ -final class TransferStats -{ - /** - * @var RequestInterface - */ - private $request; - - /** - * @var ResponseInterface|null - */ - private $response; - - /** - * @var float|null - */ - private $transferTime; - - /** - * @var array - */ - private $handlerStats; - - /** - * @var mixed|null - */ - private $handlerErrorData; - - /** - * @param RequestInterface $request Request that was sent. - * @param ResponseInterface|null $response Response received (if any) - * @param float|null $transferTime Total handler transfer time. - * @param mixed $handlerErrorData Handler error data. - * @param array $handlerStats Handler specific stats. - */ - public function __construct( - RequestInterface $request, - ?ResponseInterface $response = null, - ?float $transferTime = null, - $handlerErrorData = null, - array $handlerStats = [] - ) { - $this->request = $request; - $this->response = $response; - $this->transferTime = $transferTime; - $this->handlerErrorData = $handlerErrorData; - $this->handlerStats = $handlerStats; - } - - public function getRequest(): RequestInterface - { - return $this->request; - } - - /** - * Returns the response that was received (if any). - */ - public function getResponse(): ?ResponseInterface - { - return $this->response; - } - - /** - * Returns true if a response was received. - */ - public function hasResponse(): bool - { - return $this->response !== null; - } - - /** - * Gets handler specific error data. - * - * This might be an exception, a integer representing an error code, or - * anything else. Relying on this value assumes that you know what handler - * you are using. - * - * @return mixed - */ - public function getHandlerErrorData() - { - return $this->handlerErrorData; - } - - /** - * Get the effective URI the request was sent to. - */ - public function getEffectiveUri(): UriInterface - { - return $this->request->getUri(); - } - - /** - * Get the estimated time the request was being transferred by the handler. - * - * @return float|null Time in seconds. - */ - public function getTransferTime(): ?float - { - return $this->transferTime; - } - - /** - * Gets an array of all of the handler specific transfer data. - */ - public function getHandlerStats(): array - { - return $this->handlerStats; - } - - /** - * Get a specific handler statistic from the handler by name. - * - * @param string $stat Handler specific transfer stat to retrieve. - * - * @return mixed|null - */ - public function getHandlerStat(string $stat) - { - return $this->handlerStats[$stat] ?? null; - } -} diff --git a/lib/guzzlehttp/guzzle/src/Utils.php b/lib/guzzlehttp/guzzle/src/Utils.php deleted file mode 100644 index fcf571d6b..000000000 --- a/lib/guzzlehttp/guzzle/src/Utils.php +++ /dev/null @@ -1,385 +0,0 @@ -<?php - -namespace GuzzleHttp; - -use GuzzleHttp\Exception\InvalidArgumentException; -use GuzzleHttp\Handler\CurlHandler; -use GuzzleHttp\Handler\CurlMultiHandler; -use GuzzleHttp\Handler\Proxy; -use GuzzleHttp\Handler\StreamHandler; -use Psr\Http\Message\UriInterface; - -final class Utils -{ - /** - * Debug function used to describe the provided value type and class. - * - * @param mixed $input - * - * @return string Returns a string containing the type of the variable and - * if a class is provided, the class name. - */ - public static function describeType($input): string - { - switch (\gettype($input)) { - case 'object': - return 'object('.\get_class($input).')'; - case 'array': - return 'array('.\count($input).')'; - default: - \ob_start(); - \var_dump($input); - // normalize float vs double - /** @var string $varDumpContent */ - $varDumpContent = \ob_get_clean(); - - return \str_replace('double(', 'float(', \rtrim($varDumpContent)); - } - } - - /** - * Parses an array of header lines into an associative array of headers. - * - * @param iterable $lines Header lines array of strings in the following - * format: "Name: Value" - */ - public static function headersFromLines(iterable $lines): array - { - $headers = []; - - foreach ($lines as $line) { - $parts = \explode(':', $line, 2); - $headers[\trim($parts[0])][] = isset($parts[1]) ? \trim($parts[1]) : null; - } - - return $headers; - } - - /** - * Returns a debug stream based on the provided variable. - * - * @param mixed $value Optional value - * - * @return resource - */ - public static function debugResource($value = null) - { - if (\is_resource($value)) { - return $value; - } - if (\defined('STDOUT')) { - return \STDOUT; - } - - return \GuzzleHttp\Psr7\Utils::tryFopen('php://output', 'w'); - } - - /** - * Chooses and creates a default handler to use based on the environment. - * - * The returned handler is not wrapped by any default middlewares. - * - * @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the best handler for the given system. - * - * @throws \RuntimeException if no viable Handler is available. - */ - public static function chooseHandler(): callable - { - $handler = null; - - if (\defined('CURLOPT_CUSTOMREQUEST')) { - if (\function_exists('curl_multi_exec') && \function_exists('curl_exec')) { - $handler = Proxy::wrapSync(new CurlMultiHandler(), new CurlHandler()); - } elseif (\function_exists('curl_exec')) { - $handler = new CurlHandler(); - } elseif (\function_exists('curl_multi_exec')) { - $handler = new CurlMultiHandler(); - } - } - - if (\ini_get('allow_url_fopen')) { - $handler = $handler - ? Proxy::wrapStreaming($handler, new StreamHandler()) - : new StreamHandler(); - } elseif (!$handler) { - throw new \RuntimeException('GuzzleHttp requires cURL, the allow_url_fopen ini setting, or a custom HTTP handler.'); - } - - return $handler; - } - - /** - * Get the default User-Agent string to use with Guzzle. - */ - public static function defaultUserAgent(): string - { - return sprintf('GuzzleHttp/%d', ClientInterface::MAJOR_VERSION); - } - - /** - * Returns the default cacert bundle for the current system. - * - * First, the openssl.cafile and curl.cainfo php.ini settings are checked. - * If those settings are not configured, then the common locations for - * bundles found on Red Hat, CentOS, Fedora, Ubuntu, Debian, FreeBSD, OS X - * and Windows are checked. If any of these file locations are found on - * disk, they will be utilized. - * - * Note: the result of this function is cached for subsequent calls. - * - * @throws \RuntimeException if no bundle can be found. - * - * @deprecated Utils::defaultCaBundle will be removed in guzzlehttp/guzzle:8.0. This method is not needed in PHP 5.6+. - */ - public static function defaultCaBundle(): string - { - static $cached = null; - static $cafiles = [ - // Red Hat, CentOS, Fedora (provided by the ca-certificates package) - '/etc/pki/tls/certs/ca-bundle.crt', - // Ubuntu, Debian (provided by the ca-certificates package) - '/etc/ssl/certs/ca-certificates.crt', - // FreeBSD (provided by the ca_root_nss package) - '/usr/local/share/certs/ca-root-nss.crt', - // SLES 12 (provided by the ca-certificates package) - '/var/lib/ca-certificates/ca-bundle.pem', - // OS X provided by homebrew (using the default path) - '/usr/local/etc/openssl/cert.pem', - // Google app engine - '/etc/ca-certificates.crt', - // Windows? - 'C:\\windows\\system32\\curl-ca-bundle.crt', - 'C:\\windows\\curl-ca-bundle.crt', - ]; - - if ($cached) { - return $cached; - } - - if ($ca = \ini_get('openssl.cafile')) { - return $cached = $ca; - } - - if ($ca = \ini_get('curl.cainfo')) { - return $cached = $ca; - } - - foreach ($cafiles as $filename) { - if (\file_exists($filename)) { - return $cached = $filename; - } - } - - throw new \RuntimeException( - <<< EOT -No system CA bundle could be found in any of the the common system locations. -PHP versions earlier than 5.6 are not properly configured to use the system's -CA bundle by default. In order to verify peer certificates, you will need to -supply the path on disk to a certificate bundle to the 'verify' request -option: http://docs.guzzlephp.org/en/latest/clients.html#verify. If you do not -need a specific certificate bundle, then Mozilla provides a commonly used CA -bundle which can be downloaded here (provided by the maintainer of cURL): -https://curl.haxx.se/ca/cacert.pem. Once -you have a CA bundle available on disk, you can set the 'openssl.cafile' PHP -ini setting to point to the path to the file, allowing you to omit the 'verify' -request option. See https://curl.haxx.se/docs/sslcerts.html for more -information. -EOT - ); - } - - /** - * Creates an associative array of lowercase header names to the actual - * header casing. - */ - public static function normalizeHeaderKeys(array $headers): array - { - $result = []; - foreach (\array_keys($headers) as $key) { - $result[\strtolower($key)] = $key; - } - - return $result; - } - - /** - * Returns true if the provided host matches any of the no proxy areas. - * - * This method will strip a port from the host if it is present. Each pattern - * can be matched with an exact match (e.g., "foo.com" == "foo.com") or a - * partial match: (e.g., "foo.com" == "baz.foo.com" and ".foo.com" == - * "baz.foo.com", but ".foo.com" != "foo.com"). - * - * Areas are matched in the following cases: - * 1. "*" (without quotes) always matches any hosts. - * 2. An exact match. - * 3. The area starts with "." and the area is the last part of the host. e.g. - * '.mit.edu' will match any host that ends with '.mit.edu'. - * - * @param string $host Host to check against the patterns. - * @param string[] $noProxyArray An array of host patterns. - * - * @throws InvalidArgumentException - */ - public static function isHostInNoProxy(string $host, array $noProxyArray): bool - { - if (\strlen($host) === 0) { - throw new InvalidArgumentException('Empty host provided'); - } - - // Strip port if present. - [$host] = \explode(':', $host, 2); - - foreach ($noProxyArray as $area) { - // Always match on wildcards. - if ($area === '*') { - return true; - } - - if (empty($area)) { - // Don't match on empty values. - continue; - } - - if ($area === $host) { - // Exact matches. - return true; - } - // Special match if the area when prefixed with ".". Remove any - // existing leading "." and add a new leading ".". - $area = '.'.\ltrim($area, '.'); - if (\substr($host, -\strlen($area)) === $area) { - return true; - } - } - - return false; - } - - /** - * Wrapper for json_decode that throws when an error occurs. - * - * @param string $json JSON data to parse - * @param bool $assoc When true, returned objects will be converted - * into associative arrays. - * @param int $depth User specified recursion depth. - * @param int $options Bitmask of JSON decode options. - * - * @return object|array|string|int|float|bool|null - * - * @throws InvalidArgumentException if the JSON cannot be decoded. - * - * @see https://www.php.net/manual/en/function.json-decode.php - */ - public static function jsonDecode(string $json, bool $assoc = false, int $depth = 512, int $options = 0) - { - $data = \json_decode($json, $assoc, $depth, $options); - if (\JSON_ERROR_NONE !== \json_last_error()) { - throw new InvalidArgumentException('json_decode error: '.\json_last_error_msg()); - } - - return $data; - } - - /** - * Wrapper for JSON encoding that throws when an error occurs. - * - * @param mixed $value The value being encoded - * @param int $options JSON encode option bitmask - * @param int $depth Set the maximum depth. Must be greater than zero. - * - * @throws InvalidArgumentException if the JSON cannot be encoded. - * - * @see https://www.php.net/manual/en/function.json-encode.php - */ - public static function jsonEncode($value, int $options = 0, int $depth = 512): string - { - $json = \json_encode($value, $options, $depth); - if (\JSON_ERROR_NONE !== \json_last_error()) { - throw new InvalidArgumentException('json_encode error: '.\json_last_error_msg()); - } - - /** @var string */ - return $json; - } - - /** - * Wrapper for the hrtime() or microtime() functions - * (depending on the PHP version, one of the two is used) - * - * @return float UNIX timestamp - * - * @internal - */ - public static function currentTime(): float - { - return (float) \function_exists('hrtime') ? \hrtime(true) / 1e9 : \microtime(true); - } - - /** - * @throws InvalidArgumentException - * - * @internal - */ - public static function idnUriConvert(UriInterface $uri, int $options = 0): UriInterface - { - if ($uri->getHost()) { - $asciiHost = self::idnToAsci($uri->getHost(), $options, $info); - if ($asciiHost === false) { - $errorBitSet = $info['errors'] ?? 0; - - $errorConstants = array_filter(array_keys(get_defined_constants()), static function (string $name): bool { - return substr($name, 0, 11) === 'IDNA_ERROR_'; - }); - - $errors = []; - foreach ($errorConstants as $errorConstant) { - if ($errorBitSet & constant($errorConstant)) { - $errors[] = $errorConstant; - } - } - - $errorMessage = 'IDN conversion failed'; - if ($errors) { - $errorMessage .= ' (errors: '.implode(', ', $errors).')'; - } - - throw new InvalidArgumentException($errorMessage); - } - if ($uri->getHost() !== $asciiHost) { - // Replace URI only if the ASCII version is different - $uri = $uri->withHost($asciiHost); - } - } - - return $uri; - } - - /** - * @internal - */ - public static function getenv(string $name): ?string - { - if (isset($_SERVER[$name])) { - return (string) $_SERVER[$name]; - } - - if (\PHP_SAPI === 'cli' && ($value = \getenv($name)) !== false && $value !== null) { - return (string) $value; - } - - return null; - } - - /** - * @return string|false - */ - private static function idnToAsci(string $domain, int $options, ?array &$info = []) - { - if (\function_exists('idn_to_ascii') && \defined('INTL_IDNA_VARIANT_UTS46')) { - return \idn_to_ascii($domain, $options, \INTL_IDNA_VARIANT_UTS46, $info); - } - - throw new \Error('ext-idn or symfony/polyfill-intl-idn not loaded or too old'); - } -} diff --git a/lib/guzzlehttp/guzzle/src/functions.php b/lib/guzzlehttp/guzzle/src/functions.php deleted file mode 100644 index 5edc66ab1..000000000 --- a/lib/guzzlehttp/guzzle/src/functions.php +++ /dev/null @@ -1,167 +0,0 @@ -<?php - -namespace GuzzleHttp; - -/** - * Debug function used to describe the provided value type and class. - * - * @param mixed $input Any type of variable to describe the type of. This - * parameter misses a typehint because of that. - * - * @return string Returns a string containing the type of the variable and - * if a class is provided, the class name. - * - * @deprecated describe_type will be removed in guzzlehttp/guzzle:8.0. Use Utils::describeType instead. - */ -function describe_type($input): string -{ - return Utils::describeType($input); -} - -/** - * Parses an array of header lines into an associative array of headers. - * - * @param iterable $lines Header lines array of strings in the following - * format: "Name: Value" - * - * @deprecated headers_from_lines will be removed in guzzlehttp/guzzle:8.0. Use Utils::headersFromLines instead. - */ -function headers_from_lines(iterable $lines): array -{ - return Utils::headersFromLines($lines); -} - -/** - * Returns a debug stream based on the provided variable. - * - * @param mixed $value Optional value - * - * @return resource - * - * @deprecated debug_resource will be removed in guzzlehttp/guzzle:8.0. Use Utils::debugResource instead. - */ -function debug_resource($value = null) -{ - return Utils::debugResource($value); -} - -/** - * Chooses and creates a default handler to use based on the environment. - * - * The returned handler is not wrapped by any default middlewares. - * - * @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the best handler for the given system. - * - * @throws \RuntimeException if no viable Handler is available. - * - * @deprecated choose_handler will be removed in guzzlehttp/guzzle:8.0. Use Utils::chooseHandler instead. - */ -function choose_handler(): callable -{ - return Utils::chooseHandler(); -} - -/** - * Get the default User-Agent string to use with Guzzle. - * - * @deprecated default_user_agent will be removed in guzzlehttp/guzzle:8.0. Use Utils::defaultUserAgent instead. - */ -function default_user_agent(): string -{ - return Utils::defaultUserAgent(); -} - -/** - * Returns the default cacert bundle for the current system. - * - * First, the openssl.cafile and curl.cainfo php.ini settings are checked. - * If those settings are not configured, then the common locations for - * bundles found on Red Hat, CentOS, Fedora, Ubuntu, Debian, FreeBSD, OS X - * and Windows are checked. If any of these file locations are found on - * disk, they will be utilized. - * - * Note: the result of this function is cached for subsequent calls. - * - * @throws \RuntimeException if no bundle can be found. - * - * @deprecated default_ca_bundle will be removed in guzzlehttp/guzzle:8.0. This function is not needed in PHP 5.6+. - */ -function default_ca_bundle(): string -{ - return Utils::defaultCaBundle(); -} - -/** - * Creates an associative array of lowercase header names to the actual - * header casing. - * - * @deprecated normalize_header_keys will be removed in guzzlehttp/guzzle:8.0. Use Utils::normalizeHeaderKeys instead. - */ -function normalize_header_keys(array $headers): array -{ - return Utils::normalizeHeaderKeys($headers); -} - -/** - * Returns true if the provided host matches any of the no proxy areas. - * - * This method will strip a port from the host if it is present. Each pattern - * can be matched with an exact match (e.g., "foo.com" == "foo.com") or a - * partial match: (e.g., "foo.com" == "baz.foo.com" and ".foo.com" == - * "baz.foo.com", but ".foo.com" != "foo.com"). - * - * Areas are matched in the following cases: - * 1. "*" (without quotes) always matches any hosts. - * 2. An exact match. - * 3. The area starts with "." and the area is the last part of the host. e.g. - * '.mit.edu' will match any host that ends with '.mit.edu'. - * - * @param string $host Host to check against the patterns. - * @param string[] $noProxyArray An array of host patterns. - * - * @throws Exception\InvalidArgumentException - * - * @deprecated is_host_in_noproxy will be removed in guzzlehttp/guzzle:8.0. Use Utils::isHostInNoProxy instead. - */ -function is_host_in_noproxy(string $host, array $noProxyArray): bool -{ - return Utils::isHostInNoProxy($host, $noProxyArray); -} - -/** - * Wrapper for json_decode that throws when an error occurs. - * - * @param string $json JSON data to parse - * @param bool $assoc When true, returned objects will be converted - * into associative arrays. - * @param int $depth User specified recursion depth. - * @param int $options Bitmask of JSON decode options. - * - * @return object|array|string|int|float|bool|null - * - * @throws Exception\InvalidArgumentException if the JSON cannot be decoded. - * - * @see https://www.php.net/manual/en/function.json-decode.php - * @deprecated json_decode will be removed in guzzlehttp/guzzle:8.0. Use Utils::jsonDecode instead. - */ -function json_decode(string $json, bool $assoc = false, int $depth = 512, int $options = 0) -{ - return Utils::jsonDecode($json, $assoc, $depth, $options); -} - -/** - * Wrapper for JSON encoding that throws when an error occurs. - * - * @param mixed $value The value being encoded - * @param int $options JSON encode option bitmask - * @param int $depth Set the maximum depth. Must be greater than zero. - * - * @throws Exception\InvalidArgumentException if the JSON cannot be encoded. - * - * @see https://www.php.net/manual/en/function.json-encode.php - * @deprecated json_encode will be removed in guzzlehttp/guzzle:8.0. Use Utils::jsonEncode instead. - */ -function json_encode($value, int $options = 0, int $depth = 512): string -{ - return Utils::jsonEncode($value, $options, $depth); -} diff --git a/lib/guzzlehttp/guzzle/src/functions_include.php b/lib/guzzlehttp/guzzle/src/functions_include.php deleted file mode 100644 index 394f95347..000000000 --- a/lib/guzzlehttp/guzzle/src/functions_include.php +++ /dev/null @@ -1,6 +0,0 @@ -<?php - -// Don't redefine the functions if included multiple times. -if (!\function_exists('GuzzleHttp\describe_type')) { - require __DIR__.'/functions.php'; -} diff --git a/lib/guzzlehttp/promises/CHANGELOG.md b/lib/guzzlehttp/promises/CHANGELOG.md deleted file mode 100644 index ab173ad74..000000000 --- a/lib/guzzlehttp/promises/CHANGELOG.md +++ /dev/null @@ -1,138 +0,0 @@ -# CHANGELOG - - -## 2.0.0 - TBC - -### Added - -- Added PHP 7 type hints - -### Changed - -- All previously non-final non-exception classes have been marked as soft-final - -### Removed - -- Dropped PHP < 7.2 support -- All functions in the `GuzzleHttp\Promise` namespace - - -## 1.5.3 - 2023-05-21 - -### Changed - -- Removed remaining usage of deprecated functions - - -## 1.5.2 - 2022-08-07 - -### Changed - -- Officially support PHP 8.2 - - -## 1.5.1 - 2021-10-22 - -### Fixed - -- Revert "Call handler when waiting on fulfilled/rejected Promise" -- Fix pool memory leak when empty array of promises provided - - -## 1.5.0 - 2021-10-07 - -### Changed - -- Call handler when waiting on fulfilled/rejected Promise -- Officially support PHP 8.1 - -### Fixed - -- Fix manually settle promises generated with `Utils::task` - - -## 1.4.1 - 2021-02-18 - -### Fixed - -- Fixed `each_limit` skipping promises and failing - - -## 1.4.0 - 2020-09-30 - -### Added - -- Support for PHP 8 -- Optional `$recursive` flag to `all` -- Replaced functions by static methods - -### Fixed - -- Fix empty `each` processing -- Fix promise handling for Iterators of non-unique keys -- Fixed `method_exists` crashes on PHP 8 -- Memory leak on exceptions - - -## 1.3.1 - 2016-12-20 - -### Fixed - -- `wait()` foreign promise compatibility - - -## 1.3.0 - 2016-11-18 - -### Added - -- Adds support for custom task queues. - -### Fixed - -- Fixed coroutine promise memory leak. - - -## 1.2.0 - 2016-05-18 - -### Changed - -- Update to now catch `\Throwable` on PHP 7+ - - -## 1.1.0 - 2016-03-07 - -### Changed - -- Update EachPromise to prevent recurring on a iterator when advancing, as this - could trigger fatal generator errors. -- Update Promise to allow recursive waiting without unwrapping exceptions. - - -## 1.0.3 - 2015-10-15 - -### Changed - -- Update EachPromise to immediately resolve when the underlying promise iterator - is empty. Previously, such a promise would throw an exception when its `wait` - function was called. - - -## 1.0.2 - 2015-05-15 - -### Changed - -- Conditionally require functions.php. - - -## 1.0.1 - 2015-06-24 - -### Changed - -- Updating EachPromise to call next on the underlying promise iterator as late - as possible to ensure that generators that generate new requests based on - callbacks are not iterated until after callbacks are invoked. - - -## 1.0.0 - 2015-05-12 - -- Initial release diff --git a/lib/guzzlehttp/promises/LICENSE b/lib/guzzlehttp/promises/LICENSE deleted file mode 100644 index 9f0f943be..000000000 --- a/lib/guzzlehttp/promises/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Michael Dowling <mtdowling@gmail.com> -Copyright (c) 2015 Graham Campbell <hello@gjcampbell.co.uk> -Copyright (c) 2017 Tobias Schultze <webmaster@tubo-world.de> -Copyright (c) 2020 Tobias Nyholm <tobias.nyholm@gmail.com> - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -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/lib/guzzlehttp/promises/README.md b/lib/guzzlehttp/promises/README.md deleted file mode 100644 index 4dc7b6a1d..000000000 --- a/lib/guzzlehttp/promises/README.md +++ /dev/null @@ -1,559 +0,0 @@ -# Guzzle Promises - -[Promises/A+](https://promisesaplus.com/) implementation that handles promise -chaining and resolution iteratively, allowing for "infinite" promise chaining -while keeping the stack size constant. Read [this blog post](https://blog.domenic.me/youre-missing-the-point-of-promises/) -for a general introduction to promises. - -- [Features](#features) -- [Quick start](#quick-start) -- [Synchronous wait](#synchronous-wait) -- [Cancellation](#cancellation) -- [API](#api) - - [Promise](#promise) - - [FulfilledPromise](#fulfilledpromise) - - [RejectedPromise](#rejectedpromise) -- [Promise interop](#promise-interop) -- [Implementation notes](#implementation-notes) - - -## Features - -- [Promises/A+](https://promisesaplus.com/) implementation. -- Promise resolution and chaining is handled iteratively, allowing for - "infinite" promise chaining. -- Promises have a synchronous `wait` method. -- Promises can be cancelled. -- Works with any object that has a `then` function. -- C# style async/await coroutine promises using - `GuzzleHttp\Promise\Coroutine::of()`. - - -## Installation - -```shell -composer require guzzlehttp/promises -``` - - -## Version Guidance - -| Version | Status | PHP Version | -|---------|------------------------|--------------| -| 1.x | Bug and security fixes | >=5.5,<8.3 | -| 2.x | Latest | >=7.2.5,<8.3 | - - -## Quick Start - -A *promise* represents the eventual result of an asynchronous operation. The -primary way of interacting with a promise is through its `then` method, which -registers callbacks to receive either a promise's eventual value or the reason -why the promise cannot be fulfilled. - -### Callbacks - -Callbacks are registered with the `then` method by providing an optional -`$onFulfilled` followed by an optional `$onRejected` function. - - -```php -use GuzzleHttp\Promise\Promise; - -$promise = new Promise(); -$promise->then( - // $onFulfilled - function ($value) { - echo 'The promise was fulfilled.'; - }, - // $onRejected - function ($reason) { - echo 'The promise was rejected.'; - } -); -``` - -*Resolving* a promise means that you either fulfill a promise with a *value* or -reject a promise with a *reason*. Resolving a promise triggers callbacks -registered with the promise's `then` method. These callbacks are triggered -only once and in the order in which they were added. - -### Resolving a Promise - -Promises are fulfilled using the `resolve($value)` method. Resolving a promise -with any value other than a `GuzzleHttp\Promise\RejectedPromise` will trigger -all of the onFulfilled callbacks (resolving a promise with a rejected promise -will reject the promise and trigger the `$onRejected` callbacks). - -```php -use GuzzleHttp\Promise\Promise; - -$promise = new Promise(); -$promise - ->then(function ($value) { - // Return a value and don't break the chain - return "Hello, " . $value; - }) - // This then is executed after the first then and receives the value - // returned from the first then. - ->then(function ($value) { - echo $value; - }); - -// Resolving the promise triggers the $onFulfilled callbacks and outputs -// "Hello, reader." -$promise->resolve('reader.'); -``` - -### Promise Forwarding - -Promises can be chained one after the other. Each then in the chain is a new -promise. The return value of a promise is what's forwarded to the next -promise in the chain. Returning a promise in a `then` callback will cause the -subsequent promises in the chain to only be fulfilled when the returned promise -has been fulfilled. The next promise in the chain will be invoked with the -resolved value of the promise. - -```php -use GuzzleHttp\Promise\Promise; - -$promise = new Promise(); -$nextPromise = new Promise(); - -$promise - ->then(function ($value) use ($nextPromise) { - echo $value; - return $nextPromise; - }) - ->then(function ($value) { - echo $value; - }); - -// Triggers the first callback and outputs "A" -$promise->resolve('A'); -// Triggers the second callback and outputs "B" -$nextPromise->resolve('B'); -``` - -### Promise Rejection - -When a promise is rejected, the `$onRejected` callbacks are invoked with the -rejection reason. - -```php -use GuzzleHttp\Promise\Promise; - -$promise = new Promise(); -$promise->then(null, function ($reason) { - echo $reason; -}); - -$promise->reject('Error!'); -// Outputs "Error!" -``` - -### Rejection Forwarding - -If an exception is thrown in an `$onRejected` callback, subsequent -`$onRejected` callbacks are invoked with the thrown exception as the reason. - -```php -use GuzzleHttp\Promise\Promise; - -$promise = new Promise(); -$promise->then(null, function ($reason) { - throw new Exception($reason); -})->then(null, function ($reason) { - assert($reason->getMessage() === 'Error!'); -}); - -$promise->reject('Error!'); -``` - -You can also forward a rejection down the promise chain by returning a -`GuzzleHttp\Promise\RejectedPromise` in either an `$onFulfilled` or -`$onRejected` callback. - -```php -use GuzzleHttp\Promise\Promise; -use GuzzleHttp\Promise\RejectedPromise; - -$promise = new Promise(); -$promise->then(null, function ($reason) { - return new RejectedPromise($reason); -})->then(null, function ($reason) { - assert($reason === 'Error!'); -}); - -$promise->reject('Error!'); -``` - -If an exception is not thrown in a `$onRejected` callback and the callback -does not return a rejected promise, downstream `$onFulfilled` callbacks are -invoked using the value returned from the `$onRejected` callback. - -```php -use GuzzleHttp\Promise\Promise; - -$promise = new Promise(); -$promise - ->then(null, function ($reason) { - return "It's ok"; - }) - ->then(function ($value) { - assert($value === "It's ok"); - }); - -$promise->reject('Error!'); -``` - - -## Synchronous Wait - -You can synchronously force promises to complete using a promise's `wait` -method. When creating a promise, you can provide a wait function that is used -to synchronously force a promise to complete. When a wait function is invoked -it is expected to deliver a value to the promise or reject the promise. If the -wait function does not deliver a value, then an exception is thrown. The wait -function provided to a promise constructor is invoked when the `wait` function -of the promise is called. - -```php -$promise = new Promise(function () use (&$promise) { - $promise->resolve('foo'); -}); - -// Calling wait will return the value of the promise. -echo $promise->wait(); // outputs "foo" -``` - -If an exception is encountered while invoking the wait function of a promise, -the promise is rejected with the exception and the exception is thrown. - -```php -$promise = new Promise(function () use (&$promise) { - throw new Exception('foo'); -}); - -$promise->wait(); // throws the exception. -``` - -Calling `wait` on a promise that has been fulfilled will not trigger the wait -function. It will simply return the previously resolved value. - -```php -$promise = new Promise(function () { die('this is not called!'); }); -$promise->resolve('foo'); -echo $promise->wait(); // outputs "foo" -``` - -Calling `wait` on a promise that has been rejected will throw an exception. If -the rejection reason is an instance of `\Exception` the reason is thrown. -Otherwise, a `GuzzleHttp\Promise\RejectionException` is thrown and the reason -can be obtained by calling the `getReason` method of the exception. - -```php -$promise = new Promise(); -$promise->reject('foo'); -$promise->wait(); -``` - -> PHP Fatal error: Uncaught exception 'GuzzleHttp\Promise\RejectionException' with message 'The promise was rejected with value: foo' - -### Unwrapping a Promise - -When synchronously waiting on a promise, you are joining the state of the -promise into the current state of execution (i.e., return the value of the -promise if it was fulfilled or throw an exception if it was rejected). This is -called "unwrapping" the promise. Waiting on a promise will by default unwrap -the promise state. - -You can force a promise to resolve and *not* unwrap the state of the promise -by passing `false` to the first argument of the `wait` function: - -```php -$promise = new Promise(); -$promise->reject('foo'); -// This will not throw an exception. It simply ensures the promise has -// been resolved. -$promise->wait(false); -``` - -When unwrapping a promise, the resolved value of the promise will be waited -upon until the unwrapped value is not a promise. This means that if you resolve -promise A with a promise B and unwrap promise A, the value returned by the -wait function will be the value delivered to promise B. - -**Note**: when you do not unwrap the promise, no value is returned. - - -## Cancellation - -You can cancel a promise that has not yet been fulfilled using the `cancel()` -method of a promise. When creating a promise you can provide an optional -cancel function that when invoked cancels the action of computing a resolution -of the promise. - - -## API - -### Promise - -When creating a promise object, you can provide an optional `$waitFn` and -`$cancelFn`. `$waitFn` is a function that is invoked with no arguments and is -expected to resolve the promise. `$cancelFn` is a function with no arguments -that is expected to cancel the computation of a promise. It is invoked when the -`cancel()` method of a promise is called. - -```php -use GuzzleHttp\Promise\Promise; - -$promise = new Promise( - function () use (&$promise) { - $promise->resolve('waited'); - }, - function () { - // do something that will cancel the promise computation (e.g., close - // a socket, cancel a database query, etc...) - } -); - -assert('waited' === $promise->wait()); -``` - -A promise has the following methods: - -- `then(callable $onFulfilled, callable $onRejected) : PromiseInterface` - - Appends fulfillment and rejection handlers to the promise, and returns a new promise resolving to the return value of the called handler. - -- `otherwise(callable $onRejected) : PromiseInterface` - - Appends a rejection handler callback to the promise, and returns a new promise resolving to the return value of the callback if it is called, or to its original fulfillment value if the promise is instead fulfilled. - -- `wait($unwrap = true) : mixed` - - Synchronously waits on the promise to complete. - - `$unwrap` controls whether or not the value of the promise is returned for a - fulfilled promise or if an exception is thrown if the promise is rejected. - This is set to `true` by default. - -- `cancel()` - - Attempts to cancel the promise if possible. The promise being cancelled and - the parent most ancestor that has not yet been resolved will also be - cancelled. Any promises waiting on the cancelled promise to resolve will also - be cancelled. - -- `getState() : string` - - Returns the state of the promise. One of `pending`, `fulfilled`, or - `rejected`. - -- `resolve($value)` - - Fulfills the promise with the given `$value`. - -- `reject($reason)` - - Rejects the promise with the given `$reason`. - - -### FulfilledPromise - -A fulfilled promise can be created to represent a promise that has been -fulfilled. - -```php -use GuzzleHttp\Promise\FulfilledPromise; - -$promise = new FulfilledPromise('value'); - -// Fulfilled callbacks are immediately invoked. -$promise->then(function ($value) { - echo $value; -}); -``` - - -### RejectedPromise - -A rejected promise can be created to represent a promise that has been -rejected. - -```php -use GuzzleHttp\Promise\RejectedPromise; - -$promise = new RejectedPromise('Error'); - -// Rejected callbacks are immediately invoked. -$promise->then(null, function ($reason) { - echo $reason; -}); -``` - - -## Promise Interoperability - -This library works with foreign promises that have a `then` method. This means -you can use Guzzle promises with [React promises](https://github.com/reactphp/promise) -for example. When a foreign promise is returned inside of a then method -callback, promise resolution will occur recursively. - -```php -// Create a React promise -$deferred = new React\Promise\Deferred(); -$reactPromise = $deferred->promise(); - -// Create a Guzzle promise that is fulfilled with a React promise. -$guzzlePromise = new GuzzleHttp\Promise\Promise(); -$guzzlePromise->then(function ($value) use ($reactPromise) { - // Do something something with the value... - // Return the React promise - return $reactPromise; -}); -``` - -Please note that wait and cancel chaining is no longer possible when forwarding -a foreign promise. You will need to wrap a third-party promise with a Guzzle -promise in order to utilize wait and cancel functions with foreign promises. - - -### Event Loop Integration - -In order to keep the stack size constant, Guzzle promises are resolved -asynchronously using a task queue. When waiting on promises synchronously, the -task queue will be automatically run to ensure that the blocking promise and -any forwarded promises are resolved. When using promises asynchronously in an -event loop, you will need to run the task queue on each tick of the loop. If -you do not run the task queue, then promises will not be resolved. - -You can run the task queue using the `run()` method of the global task queue -instance. - -```php -// Get the global task queue -$queue = GuzzleHttp\Promise\Utils::queue(); -$queue->run(); -``` - -For example, you could use Guzzle promises with React using a periodic timer: - -```php -$loop = React\EventLoop\Factory::create(); -$loop->addPeriodicTimer(0, [$queue, 'run']); -``` - - -## Implementation Notes - -### Promise Resolution and Chaining is Handled Iteratively - -By shuffling pending handlers from one owner to another, promises are -resolved iteratively, allowing for "infinite" then chaining. - -```php -<?php -require 'vendor/autoload.php'; - -use GuzzleHttp\Promise\Promise; - -$parent = new Promise(); -$p = $parent; - -for ($i = 0; $i < 1000; $i++) { - $p = $p->then(function ($v) { - // The stack size remains constant (a good thing) - echo xdebug_get_stack_depth() . ', '; - return $v + 1; - }); -} - -$parent->resolve(0); -var_dump($p->wait()); // int(1000) - -``` - -When a promise is fulfilled or rejected with a non-promise value, the promise -then takes ownership of the handlers of each child promise and delivers values -down the chain without using recursion. - -When a promise is resolved with another promise, the original promise transfers -all of its pending handlers to the new promise. When the new promise is -eventually resolved, all of the pending handlers are delivered the forwarded -value. - -### A Promise is the Deferred - -Some promise libraries implement promises using a deferred object to represent -a computation and a promise object to represent the delivery of the result of -the computation. This is a nice separation of computation and delivery because -consumers of the promise cannot modify the value that will be eventually -delivered. - -One side effect of being able to implement promise resolution and chaining -iteratively is that you need to be able for one promise to reach into the state -of another promise to shuffle around ownership of handlers. In order to achieve -this without making the handlers of a promise publicly mutable, a promise is -also the deferred value, allowing promises of the same parent class to reach -into and modify the private properties of promises of the same type. While this -does allow consumers of the value to modify the resolution or rejection of the -deferred, it is a small price to pay for keeping the stack size constant. - -```php -$promise = new Promise(); -$promise->then(function ($value) { echo $value; }); -// The promise is the deferred value, so you can deliver a value to it. -$promise->resolve('foo'); -// prints "foo" -``` - - -## Upgrading from Function API - -A static API was first introduced in 1.4.0, in order to mitigate problems with -functions conflicting between global and local copies of the package. The -function API was removed in 2.0.0. A migration table has been provided here for -your convenience: - -| Original Function | Replacement Method | -|----------------|----------------| -| `queue` | `Utils::queue` | -| `task` | `Utils::task` | -| `promise_for` | `Create::promiseFor` | -| `rejection_for` | `Create::rejectionFor` | -| `exception_for` | `Create::exceptionFor` | -| `iter_for` | `Create::iterFor` | -| `inspect` | `Utils::inspect` | -| `inspect_all` | `Utils::inspectAll` | -| `unwrap` | `Utils::unwrap` | -| `all` | `Utils::all` | -| `some` | `Utils::some` | -| `any` | `Utils::any` | -| `settle` | `Utils::settle` | -| `each` | `Each::of` | -| `each_limit` | `Each::ofLimit` | -| `each_limit_all` | `Each::ofLimitAll` | -| `!is_fulfilled` | `Is::pending` | -| `is_fulfilled` | `Is::fulfilled` | -| `is_rejected` | `Is::rejected` | -| `is_settled` | `Is::settled` | -| `coroutine` | `Coroutine::of` | - - -## Security - -If you discover a security vulnerability within this package, please send an email to security@tidelift.com. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see [Security Policy](https://github.com/guzzle/promises/security/policy) for more information. - - -## License - -Guzzle is made available under the MIT License (MIT). Please see [License File](LICENSE) for more information. - - -## For Enterprise - -Available as part of the Tidelift Subscription - -The maintainers of Guzzle and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/packagist-guzzlehttp-promises?utm_source=packagist-guzzlehttp-promises&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) diff --git a/lib/guzzlehttp/promises/composer.json b/lib/guzzlehttp/promises/composer.json deleted file mode 100644 index fc1989ec1..000000000 --- a/lib/guzzlehttp/promises/composer.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "name": "guzzlehttp/promises", - "description": "Guzzle promises library", - "keywords": ["promise"], - "license": "MIT", - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - }, - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/Nyholm" - }, - { - "name": "Tobias Schultze", - "email": "webmaster@tubo-world.de", - "homepage": "https://github.com/Tobion" - } - ], - "require": { - "php": "^7.2.5 || ^8.0" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", - "phpunit/phpunit": "^8.5.29 || ^9.5.23" - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Promise\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "GuzzleHttp\\Promise\\Tests\\": "tests/" - } - }, - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - } - }, - "config": { - "allow-plugins": { - "bamarni/composer-bin-plugin": true - }, - "preferred-install": "dist", - "sort-packages": true - } -} diff --git a/lib/guzzlehttp/promises/src/AggregateException.php b/lib/guzzlehttp/promises/src/AggregateException.php deleted file mode 100644 index 40ffdbcf1..000000000 --- a/lib/guzzlehttp/promises/src/AggregateException.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Promise; - -/** - * Exception thrown when too many errors occur in the some() or any() methods. - */ -class AggregateException extends RejectionException -{ - public function __construct(string $msg, array $reasons) - { - parent::__construct( - $reasons, - sprintf('%s; %d rejected promises', $msg, count($reasons)) - ); - } -} diff --git a/lib/guzzlehttp/promises/src/CancellationException.php b/lib/guzzlehttp/promises/src/CancellationException.php deleted file mode 100644 index ad8f51d48..000000000 --- a/lib/guzzlehttp/promises/src/CancellationException.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Promise; - -/** - * Exception that is set as the reason for a promise that has been cancelled. - */ -class CancellationException extends RejectionException -{ -} diff --git a/lib/guzzlehttp/promises/src/Coroutine.php b/lib/guzzlehttp/promises/src/Coroutine.php deleted file mode 100644 index 0b5b9c0a4..000000000 --- a/lib/guzzlehttp/promises/src/Coroutine.php +++ /dev/null @@ -1,162 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Promise; - -use Generator; -use Throwable; - -/** - * Creates a promise that is resolved using a generator that yields values or - * promises (somewhat similar to C#'s async keyword). - * - * When called, the Coroutine::of method will start an instance of the generator - * and returns a promise that is fulfilled with its final yielded value. - * - * Control is returned back to the generator when the yielded promise settles. - * This can lead to less verbose code when doing lots of sequential async calls - * with minimal processing in between. - * - * use GuzzleHttp\Promise; - * - * function createPromise($value) { - * return new Promise\FulfilledPromise($value); - * } - * - * $promise = Promise\Coroutine::of(function () { - * $value = (yield createPromise('a')); - * try { - * $value = (yield createPromise($value . 'b')); - * } catch (\Throwable $e) { - * // The promise was rejected. - * } - * yield $value . 'c'; - * }); - * - * // Outputs "abc" - * $promise->then(function ($v) { echo $v; }); - * - * @param callable $generatorFn Generator function to wrap into a promise. - * - * @return Promise - * - * @see https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration - */ -final class Coroutine implements PromiseInterface -{ - /** - * @var PromiseInterface|null - */ - private $currentPromise; - - /** - * @var Generator - */ - private $generator; - - /** - * @var Promise - */ - private $result; - - public function __construct(callable $generatorFn) - { - $this->generator = $generatorFn(); - $this->result = new Promise(function (): void { - while (isset($this->currentPromise)) { - $this->currentPromise->wait(); - } - }); - try { - $this->nextCoroutine($this->generator->current()); - } catch (Throwable $throwable) { - $this->result->reject($throwable); - } - } - - /** - * Create a new coroutine. - */ - public static function of(callable $generatorFn): self - { - return new self($generatorFn); - } - - public function then( - callable $onFulfilled = null, - callable $onRejected = null - ): PromiseInterface { - return $this->result->then($onFulfilled, $onRejected); - } - - public function otherwise(callable $onRejected): PromiseInterface - { - return $this->result->otherwise($onRejected); - } - - public function wait(bool $unwrap = true) - { - return $this->result->wait($unwrap); - } - - public function getState(): string - { - return $this->result->getState(); - } - - public function resolve($value): void - { - $this->result->resolve($value); - } - - public function reject($reason): void - { - $this->result->reject($reason); - } - - public function cancel(): void - { - $this->currentPromise->cancel(); - $this->result->cancel(); - } - - private function nextCoroutine($yielded): void - { - $this->currentPromise = Create::promiseFor($yielded) - ->then([$this, '_handleSuccess'], [$this, '_handleFailure']); - } - - /** - * @internal - */ - public function _handleSuccess($value): void - { - unset($this->currentPromise); - try { - $next = $this->generator->send($value); - if ($this->generator->valid()) { - $this->nextCoroutine($next); - } else { - $this->result->resolve($value); - } - } catch (Throwable $throwable) { - $this->result->reject($throwable); - } - } - - /** - * @internal - */ - public function _handleFailure($reason): void - { - unset($this->currentPromise); - try { - $nextYield = $this->generator->throw(Create::exceptionFor($reason)); - // The throw was caught, so keep iterating on the coroutine - $this->nextCoroutine($nextYield); - } catch (Throwable $throwable) { - $this->result->reject($throwable); - } - } -} diff --git a/lib/guzzlehttp/promises/src/Create.php b/lib/guzzlehttp/promises/src/Create.php deleted file mode 100644 index 9d3fc4a1e..000000000 --- a/lib/guzzlehttp/promises/src/Create.php +++ /dev/null @@ -1,79 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Promise; - -final class Create -{ - /** - * Creates a promise for a value if the value is not a promise. - * - * @param mixed $value Promise or value. - */ - public static function promiseFor($value): PromiseInterface - { - if ($value instanceof PromiseInterface) { - return $value; - } - - // Return a Guzzle promise that shadows the given promise. - if (is_object($value) && method_exists($value, 'then')) { - $wfn = method_exists($value, 'wait') ? [$value, 'wait'] : null; - $cfn = method_exists($value, 'cancel') ? [$value, 'cancel'] : null; - $promise = new Promise($wfn, $cfn); - $value->then([$promise, 'resolve'], [$promise, 'reject']); - - return $promise; - } - - return new FulfilledPromise($value); - } - - /** - * Creates a rejected promise for a reason if the reason is not a promise. - * If the provided reason is a promise, then it is returned as-is. - * - * @param mixed $reason Promise or reason. - */ - public static function rejectionFor($reason): PromiseInterface - { - if ($reason instanceof PromiseInterface) { - return $reason; - } - - return new RejectedPromise($reason); - } - - /** - * Create an exception for a rejected promise value. - * - * @param mixed $reason - */ - public static function exceptionFor($reason): \Throwable - { - if ($reason instanceof \Throwable) { - return $reason; - } - - return new RejectionException($reason); - } - - /** - * Returns an iterator for the given value. - * - * @param mixed $value - */ - public static function iterFor($value): \Iterator - { - if ($value instanceof \Iterator) { - return $value; - } - - if (is_array($value)) { - return new \ArrayIterator($value); - } - - return new \ArrayIterator([$value]); - } -} diff --git a/lib/guzzlehttp/promises/src/Each.php b/lib/guzzlehttp/promises/src/Each.php deleted file mode 100644 index 1a7aa0fb6..000000000 --- a/lib/guzzlehttp/promises/src/Each.php +++ /dev/null @@ -1,86 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Promise; - -final class Each -{ - /** - * Given an iterator that yields promises or values, returns a promise that - * is fulfilled with a null value when the iterator has been consumed or - * the aggregate promise has been fulfilled or rejected. - * - * $onFulfilled is a function that accepts the fulfilled value, iterator - * index, and the aggregate promise. The callback can invoke any necessary - * side effects and choose to resolve or reject the aggregate if needed. - * - * $onRejected is a function that accepts the rejection reason, iterator - * index, and the aggregate promise. The callback can invoke any necessary - * side effects and choose to resolve or reject the aggregate if needed. - * - * @param mixed $iterable Iterator or array to iterate over. - * @param callable $onFulfilled - * @param callable $onRejected - */ - public static function of( - $iterable, - callable $onFulfilled = null, - callable $onRejected = null - ): PromiseInterface { - return (new EachPromise($iterable, [ - 'fulfilled' => $onFulfilled, - 'rejected' => $onRejected, - ]))->promise(); - } - - /** - * Like of, but only allows a certain number of outstanding promises at any - * given time. - * - * $concurrency may be an integer or a function that accepts the number of - * pending promises and returns a numeric concurrency limit value to allow - * for dynamic a concurrency size. - * - * @param mixed $iterable - * @param int|callable $concurrency - * @param callable $onFulfilled - * @param callable $onRejected - */ - public static function ofLimit( - $iterable, - $concurrency, - callable $onFulfilled = null, - callable $onRejected = null - ): PromiseInterface { - return (new EachPromise($iterable, [ - 'fulfilled' => $onFulfilled, - 'rejected' => $onRejected, - 'concurrency' => $concurrency, - ]))->promise(); - } - - /** - * Like limit, but ensures that no promise in the given $iterable argument - * is rejected. If any promise is rejected, then the aggregate promise is - * rejected with the encountered rejection. - * - * @param mixed $iterable - * @param int|callable $concurrency - * @param callable $onFulfilled - */ - public static function ofLimitAll( - $iterable, - $concurrency, - callable $onFulfilled = null - ): PromiseInterface { - return self::ofLimit( - $iterable, - $concurrency, - $onFulfilled, - function ($reason, $idx, PromiseInterface $aggregate): void { - $aggregate->reject($reason); - } - ); - } -} diff --git a/lib/guzzlehttp/promises/src/EachPromise.php b/lib/guzzlehttp/promises/src/EachPromise.php deleted file mode 100644 index 28dd9793a..000000000 --- a/lib/guzzlehttp/promises/src/EachPromise.php +++ /dev/null @@ -1,250 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Promise; - -/** - * Represents a promise that iterates over many promises and invokes - * side-effect functions in the process. - * - * @final - */ -class EachPromise implements PromisorInterface -{ - private $pending = []; - - private $nextPendingIndex = 0; - - /** @var \Iterator|null */ - private $iterable; - - /** @var callable|int|null */ - private $concurrency; - - /** @var callable|null */ - private $onFulfilled; - - /** @var callable|null */ - private $onRejected; - - /** @var Promise|null */ - private $aggregate; - - /** @var bool|null */ - private $mutex; - - /** - * Configuration hash can include the following key value pairs: - * - * - fulfilled: (callable) Invoked when a promise fulfills. The function - * is invoked with three arguments: the fulfillment value, the index - * position from the iterable list of the promise, and the aggregate - * promise that manages all of the promises. The aggregate promise may - * be resolved from within the callback to short-circuit the promise. - * - rejected: (callable) Invoked when a promise is rejected. The - * function is invoked with three arguments: the rejection reason, the - * index position from the iterable list of the promise, and the - * aggregate promise that manages all of the promises. The aggregate - * promise may be resolved from within the callback to short-circuit - * the promise. - * - concurrency: (integer) Pass this configuration option to limit the - * allowed number of outstanding concurrently executing promises, - * creating a capped pool of promises. There is no limit by default. - * - * @param mixed $iterable Promises or values to iterate. - * @param array $config Configuration options - */ - public function __construct($iterable, array $config = []) - { - $this->iterable = Create::iterFor($iterable); - - if (isset($config['concurrency'])) { - $this->concurrency = $config['concurrency']; - } - - if (isset($config['fulfilled'])) { - $this->onFulfilled = $config['fulfilled']; - } - - if (isset($config['rejected'])) { - $this->onRejected = $config['rejected']; - } - } - - /** @psalm-suppress InvalidNullableReturnType */ - public function promise(): PromiseInterface - { - if ($this->aggregate) { - return $this->aggregate; - } - - try { - $this->createPromise(); - /** @psalm-assert Promise $this->aggregate */ - $this->iterable->rewind(); - $this->refillPending(); - } catch (\Throwable $e) { - $this->aggregate->reject($e); - } - - /** - * @psalm-suppress NullableReturnStatement - */ - return $this->aggregate; - } - - private function createPromise(): void - { - $this->mutex = false; - $this->aggregate = new Promise(function (): void { - if ($this->checkIfFinished()) { - return; - } - reset($this->pending); - // Consume a potentially fluctuating list of promises while - // ensuring that indexes are maintained (precluding array_shift). - while ($promise = current($this->pending)) { - next($this->pending); - $promise->wait(); - if (Is::settled($this->aggregate)) { - return; - } - } - }); - - // Clear the references when the promise is resolved. - $clearFn = function (): void { - $this->iterable = $this->concurrency = $this->pending = null; - $this->onFulfilled = $this->onRejected = null; - $this->nextPendingIndex = 0; - }; - - $this->aggregate->then($clearFn, $clearFn); - } - - private function refillPending(): void - { - if (!$this->concurrency) { - // Add all pending promises. - while ($this->addPending() && $this->advanceIterator()) { - } - - return; - } - - // Add only up to N pending promises. - $concurrency = is_callable($this->concurrency) - ? call_user_func($this->concurrency, count($this->pending)) - : $this->concurrency; - $concurrency = max($concurrency - count($this->pending), 0); - // Concurrency may be set to 0 to disallow new promises. - if (!$concurrency) { - return; - } - // Add the first pending promise. - $this->addPending(); - // Note this is special handling for concurrency=1 so that we do - // not advance the iterator after adding the first promise. This - // helps work around issues with generators that might not have the - // next value to yield until promise callbacks are called. - while (--$concurrency - && $this->advanceIterator() - && $this->addPending()) { - } - } - - private function addPending(): bool - { - if (!$this->iterable || !$this->iterable->valid()) { - return false; - } - - $promise = Create::promiseFor($this->iterable->current()); - $key = $this->iterable->key(); - - // Iterable keys may not be unique, so we use a counter to - // guarantee uniqueness - $idx = $this->nextPendingIndex++; - - $this->pending[$idx] = $promise->then( - function ($value) use ($idx, $key): void { - if ($this->onFulfilled) { - call_user_func( - $this->onFulfilled, - $value, - $key, - $this->aggregate - ); - } - $this->step($idx); - }, - function ($reason) use ($idx, $key): void { - if ($this->onRejected) { - call_user_func( - $this->onRejected, - $reason, - $key, - $this->aggregate - ); - } - $this->step($idx); - } - ); - - return true; - } - - private function advanceIterator(): bool - { - // Place a lock on the iterator so that we ensure to not recurse, - // preventing fatal generator errors. - if ($this->mutex) { - return false; - } - - $this->mutex = true; - - try { - $this->iterable->next(); - $this->mutex = false; - - return true; - } catch (\Throwable $e) { - $this->aggregate->reject($e); - $this->mutex = false; - - return false; - } - } - - private function step(int $idx): void - { - // If the promise was already resolved, then ignore this step. - if (Is::settled($this->aggregate)) { - return; - } - - unset($this->pending[$idx]); - - // Only refill pending promises if we are not locked, preventing the - // EachPromise to recursively invoke the provided iterator, which - // cause a fatal error: "Cannot resume an already running generator" - if ($this->advanceIterator() && !$this->checkIfFinished()) { - // Add more pending promises if possible. - $this->refillPending(); - } - } - - private function checkIfFinished(): bool - { - if (!$this->pending && !$this->iterable->valid()) { - // Resolve the promise if there's nothing left to do. - $this->aggregate->resolve(null); - - return true; - } - - return false; - } -} diff --git a/lib/guzzlehttp/promises/src/FulfilledPromise.php b/lib/guzzlehttp/promises/src/FulfilledPromise.php deleted file mode 100644 index ab7129659..000000000 --- a/lib/guzzlehttp/promises/src/FulfilledPromise.php +++ /dev/null @@ -1,89 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Promise; - -/** - * A promise that has been fulfilled. - * - * Thenning off of this promise will invoke the onFulfilled callback - * immediately and ignore other callbacks. - * - * @final - */ -class FulfilledPromise implements PromiseInterface -{ - private $value; - - /** - * @param mixed $value - */ - public function __construct($value) - { - if (is_object($value) && method_exists($value, 'then')) { - throw new \InvalidArgumentException( - 'You cannot create a FulfilledPromise with a promise.' - ); - } - - $this->value = $value; - } - - public function then( - callable $onFulfilled = null, - callable $onRejected = null - ): PromiseInterface { - // Return itself if there is no onFulfilled function. - if (!$onFulfilled) { - return $this; - } - - $queue = Utils::queue(); - $p = new Promise([$queue, 'run']); - $value = $this->value; - $queue->add(static function () use ($p, $value, $onFulfilled): void { - if (Is::pending($p)) { - try { - $p->resolve($onFulfilled($value)); - } catch (\Throwable $e) { - $p->reject($e); - } - } - }); - - return $p; - } - - public function otherwise(callable $onRejected): PromiseInterface - { - return $this->then(null, $onRejected); - } - - public function wait(bool $unwrap = true) - { - return $unwrap ? $this->value : null; - } - - public function getState(): string - { - return self::FULFILLED; - } - - public function resolve($value): void - { - if ($value !== $this->value) { - throw new \LogicException('Cannot resolve a fulfilled promise'); - } - } - - public function reject($reason): void - { - throw new \LogicException('Cannot reject a fulfilled promise'); - } - - public function cancel(): void - { - // pass - } -} diff --git a/lib/guzzlehttp/promises/src/Is.php b/lib/guzzlehttp/promises/src/Is.php deleted file mode 100644 index f3f050384..000000000 --- a/lib/guzzlehttp/promises/src/Is.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Promise; - -final class Is -{ - /** - * Returns true if a promise is pending. - */ - public static function pending(PromiseInterface $promise): bool - { - return $promise->getState() === PromiseInterface::PENDING; - } - - /** - * Returns true if a promise is fulfilled or rejected. - */ - public static function settled(PromiseInterface $promise): bool - { - return $promise->getState() !== PromiseInterface::PENDING; - } - - /** - * Returns true if a promise is fulfilled. - */ - public static function fulfilled(PromiseInterface $promise): bool - { - return $promise->getState() === PromiseInterface::FULFILLED; - } - - /** - * Returns true if a promise is rejected. - */ - public static function rejected(PromiseInterface $promise): bool - { - return $promise->getState() === PromiseInterface::REJECTED; - } -} diff --git a/lib/guzzlehttp/promises/src/Promise.php b/lib/guzzlehttp/promises/src/Promise.php deleted file mode 100644 index 1b07bdc9a..000000000 --- a/lib/guzzlehttp/promises/src/Promise.php +++ /dev/null @@ -1,281 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Promise; - -/** - * Promises/A+ implementation that avoids recursion when possible. - * - * @see https://promisesaplus.com/ - * - * @final - */ -class Promise implements PromiseInterface -{ - private $state = self::PENDING; - private $result; - private $cancelFn; - private $waitFn; - private $waitList; - private $handlers = []; - - /** - * @param callable $waitFn Fn that when invoked resolves the promise. - * @param callable $cancelFn Fn that when invoked cancels the promise. - */ - public function __construct( - callable $waitFn = null, - callable $cancelFn = null - ) { - $this->waitFn = $waitFn; - $this->cancelFn = $cancelFn; - } - - public function then( - callable $onFulfilled = null, - callable $onRejected = null - ): PromiseInterface { - if ($this->state === self::PENDING) { - $p = new Promise(null, [$this, 'cancel']); - $this->handlers[] = [$p, $onFulfilled, $onRejected]; - $p->waitList = $this->waitList; - $p->waitList[] = $this; - - return $p; - } - - // Return a fulfilled promise and immediately invoke any callbacks. - if ($this->state === self::FULFILLED) { - $promise = Create::promiseFor($this->result); - - return $onFulfilled ? $promise->then($onFulfilled) : $promise; - } - - // It's either cancelled or rejected, so return a rejected promise - // and immediately invoke any callbacks. - $rejection = Create::rejectionFor($this->result); - - return $onRejected ? $rejection->then(null, $onRejected) : $rejection; - } - - public function otherwise(callable $onRejected): PromiseInterface - { - return $this->then(null, $onRejected); - } - - public function wait(bool $unwrap = true) - { - $this->waitIfPending(); - - if ($this->result instanceof PromiseInterface) { - return $this->result->wait($unwrap); - } - if ($unwrap) { - if ($this->state === self::FULFILLED) { - return $this->result; - } - // It's rejected so "unwrap" and throw an exception. - throw Create::exceptionFor($this->result); - } - } - - public function getState(): string - { - return $this->state; - } - - public function cancel(): void - { - if ($this->state !== self::PENDING) { - return; - } - - $this->waitFn = $this->waitList = null; - - if ($this->cancelFn) { - $fn = $this->cancelFn; - $this->cancelFn = null; - try { - $fn(); - } catch (\Throwable $e) { - $this->reject($e); - } - } - - // Reject the promise only if it wasn't rejected in a then callback. - /** @psalm-suppress RedundantCondition */ - if ($this->state === self::PENDING) { - $this->reject(new CancellationException('Promise has been cancelled')); - } - } - - public function resolve($value): void - { - $this->settle(self::FULFILLED, $value); - } - - public function reject($reason): void - { - $this->settle(self::REJECTED, $reason); - } - - private function settle(string $state, $value): void - { - if ($this->state !== self::PENDING) { - // Ignore calls with the same resolution. - if ($state === $this->state && $value === $this->result) { - return; - } - throw $this->state === $state - ? new \LogicException("The promise is already {$state}.") - : new \LogicException("Cannot change a {$this->state} promise to {$state}"); - } - - if ($value === $this) { - throw new \LogicException('Cannot fulfill or reject a promise with itself'); - } - - // Clear out the state of the promise but stash the handlers. - $this->state = $state; - $this->result = $value; - $handlers = $this->handlers; - $this->handlers = null; - $this->waitList = $this->waitFn = null; - $this->cancelFn = null; - - if (!$handlers) { - return; - } - - // If the value was not a settled promise or a thenable, then resolve - // it in the task queue using the correct ID. - if (!is_object($value) || !method_exists($value, 'then')) { - $id = $state === self::FULFILLED ? 1 : 2; - // It's a success, so resolve the handlers in the queue. - Utils::queue()->add(static function () use ($id, $value, $handlers): void { - foreach ($handlers as $handler) { - self::callHandler($id, $value, $handler); - } - }); - } elseif ($value instanceof Promise && Is::pending($value)) { - // We can just merge our handlers onto the next promise. - $value->handlers = array_merge($value->handlers, $handlers); - } else { - // Resolve the handlers when the forwarded promise is resolved. - $value->then( - static function ($value) use ($handlers): void { - foreach ($handlers as $handler) { - self::callHandler(1, $value, $handler); - } - }, - static function ($reason) use ($handlers): void { - foreach ($handlers as $handler) { - self::callHandler(2, $reason, $handler); - } - } - ); - } - } - - /** - * Call a stack of handlers using a specific callback index and value. - * - * @param int $index 1 (resolve) or 2 (reject). - * @param mixed $value Value to pass to the callback. - * @param array $handler Array of handler data (promise and callbacks). - */ - private static function callHandler(int $index, $value, array $handler): void - { - /** @var PromiseInterface $promise */ - $promise = $handler[0]; - - // The promise may have been cancelled or resolved before placing - // this thunk in the queue. - if (Is::settled($promise)) { - return; - } - - try { - if (isset($handler[$index])) { - /* - * If $f throws an exception, then $handler will be in the exception - * stack trace. Since $handler contains a reference to the callable - * itself we get a circular reference. We clear the $handler - * here to avoid that memory leak. - */ - $f = $handler[$index]; - unset($handler); - $promise->resolve($f($value)); - } elseif ($index === 1) { - // Forward resolution values as-is. - $promise->resolve($value); - } else { - // Forward rejections down the chain. - $promise->reject($value); - } - } catch (\Throwable $reason) { - $promise->reject($reason); - } - } - - private function waitIfPending(): void - { - if ($this->state !== self::PENDING) { - return; - } elseif ($this->waitFn) { - $this->invokeWaitFn(); - } elseif ($this->waitList) { - $this->invokeWaitList(); - } else { - // If there's no wait function, then reject the promise. - $this->reject('Cannot wait on a promise that has ' - .'no internal wait function. You must provide a wait ' - .'function when constructing the promise to be able to ' - .'wait on a promise.'); - } - - Utils::queue()->run(); - - /** @psalm-suppress RedundantCondition */ - if ($this->state === self::PENDING) { - $this->reject('Invoking the wait callback did not resolve the promise'); - } - } - - private function invokeWaitFn(): void - { - try { - $wfn = $this->waitFn; - $this->waitFn = null; - $wfn(true); - } catch (\Throwable $reason) { - if ($this->state === self::PENDING) { - // The promise has not been resolved yet, so reject the promise - // with the exception. - $this->reject($reason); - } else { - // The promise was already resolved, so there's a problem in - // the application. - throw $reason; - } - } - } - - private function invokeWaitList(): void - { - $waitList = $this->waitList; - $this->waitList = null; - - foreach ($waitList as $result) { - do { - $result->waitIfPending(); - $result = $result->result; - } while ($result instanceof Promise); - - if ($result instanceof PromiseInterface) { - $result->wait(false); - } - } - } -} diff --git a/lib/guzzlehttp/promises/src/PromiseInterface.php b/lib/guzzlehttp/promises/src/PromiseInterface.php deleted file mode 100644 index 2824802bb..000000000 --- a/lib/guzzlehttp/promises/src/PromiseInterface.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Promise; - -/** - * A promise represents the eventual result of an asynchronous operation. - * - * The primary way of interacting with a promise is through its then method, - * which registers callbacks to receive either a promise’s eventual value or - * the reason why the promise cannot be fulfilled. - * - * @see https://promisesaplus.com/ - */ -interface PromiseInterface -{ - public const PENDING = 'pending'; - public const FULFILLED = 'fulfilled'; - public const REJECTED = 'rejected'; - - /** - * Appends fulfillment and rejection handlers to the promise, and returns - * a new promise resolving to the return value of the called handler. - * - * @param callable $onFulfilled Invoked when the promise fulfills. - * @param callable $onRejected Invoked when the promise is rejected. - */ - public function then( - callable $onFulfilled = null, - callable $onRejected = null - ): PromiseInterface; - - /** - * Appends a rejection handler callback to the promise, and returns a new - * promise resolving to the return value of the callback if it is called, - * or to its original fulfillment value if the promise is instead - * fulfilled. - * - * @param callable $onRejected Invoked when the promise is rejected. - */ - public function otherwise(callable $onRejected): PromiseInterface; - - /** - * Get the state of the promise ("pending", "rejected", or "fulfilled"). - * - * The three states can be checked against the constants defined on - * PromiseInterface: PENDING, FULFILLED, and REJECTED. - */ - public function getState(): string; - - /** - * Resolve the promise with the given value. - * - * @param mixed $value - * - * @throws \RuntimeException if the promise is already resolved. - */ - public function resolve($value): void; - - /** - * Reject the promise with the given reason. - * - * @param mixed $reason - * - * @throws \RuntimeException if the promise is already resolved. - */ - public function reject($reason): void; - - /** - * Cancels the promise if possible. - * - * @see https://github.com/promises-aplus/cancellation-spec/issues/7 - */ - public function cancel(): void; - - /** - * Waits until the promise completes if possible. - * - * Pass $unwrap as true to unwrap the result of the promise, either - * returning the resolved value or throwing the rejected exception. - * - * If the promise cannot be waited on, then the promise will be rejected. - * - * @return mixed - * - * @throws \LogicException if the promise has no wait function or if the - * promise does not settle after waiting. - */ - public function wait(bool $unwrap = true); -} diff --git a/lib/guzzlehttp/promises/src/PromisorInterface.php b/lib/guzzlehttp/promises/src/PromisorInterface.php deleted file mode 100644 index 5e8c51264..000000000 --- a/lib/guzzlehttp/promises/src/PromisorInterface.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Promise; - -/** - * Interface used with classes that return a promise. - */ -interface PromisorInterface -{ - /** - * Returns a promise. - */ - public function promise(): PromiseInterface; -} diff --git a/lib/guzzlehttp/promises/src/RejectedPromise.php b/lib/guzzlehttp/promises/src/RejectedPromise.php deleted file mode 100644 index d947da1f5..000000000 --- a/lib/guzzlehttp/promises/src/RejectedPromise.php +++ /dev/null @@ -1,95 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Promise; - -/** - * A promise that has been rejected. - * - * Thenning off of this promise will invoke the onRejected callback - * immediately and ignore other callbacks. - * - * @final - */ -class RejectedPromise implements PromiseInterface -{ - private $reason; - - /** - * @param mixed $reason - */ - public function __construct($reason) - { - if (is_object($reason) && method_exists($reason, 'then')) { - throw new \InvalidArgumentException( - 'You cannot create a RejectedPromise with a promise.' - ); - } - - $this->reason = $reason; - } - - public function then( - callable $onFulfilled = null, - callable $onRejected = null - ): PromiseInterface { - // If there's no onRejected callback then just return self. - if (!$onRejected) { - return $this; - } - - $queue = Utils::queue(); - $reason = $this->reason; - $p = new Promise([$queue, 'run']); - $queue->add(static function () use ($p, $reason, $onRejected): void { - if (Is::pending($p)) { - try { - // Return a resolved promise if onRejected does not throw. - $p->resolve($onRejected($reason)); - } catch (\Throwable $e) { - // onRejected threw, so return a rejected promise. - $p->reject($e); - } - } - }); - - return $p; - } - - public function otherwise(callable $onRejected): PromiseInterface - { - return $this->then(null, $onRejected); - } - - public function wait(bool $unwrap = true) - { - if ($unwrap) { - throw Create::exceptionFor($this->reason); - } - - return null; - } - - public function getState(): string - { - return self::REJECTED; - } - - public function resolve($value): void - { - throw new \LogicException('Cannot resolve a rejected promise'); - } - - public function reject($reason): void - { - if ($reason !== $this->reason) { - throw new \LogicException('Cannot reject a rejected promise'); - } - } - - public function cancel(): void - { - // pass - } -} diff --git a/lib/guzzlehttp/promises/src/RejectionException.php b/lib/guzzlehttp/promises/src/RejectionException.php deleted file mode 100644 index 0db98ffb9..000000000 --- a/lib/guzzlehttp/promises/src/RejectionException.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Promise; - -/** - * A special exception that is thrown when waiting on a rejected promise. - * - * The reason value is available via the getReason() method. - */ -class RejectionException extends \RuntimeException -{ - /** @var mixed Rejection reason. */ - private $reason; - - /** - * @param mixed $reason Rejection reason. - * @param string|null $description Optional description. - */ - public function __construct($reason, $description = null) - { - $this->reason = $reason; - - $message = 'The promise was rejected'; - - if ($description) { - $message .= ' with reason: '.$description; - } elseif (is_string($reason) - || (is_object($reason) && method_exists($reason, '__toString')) - ) { - $message .= ' with reason: '.$this->reason; - } elseif ($reason instanceof \JsonSerializable) { - $message .= ' with reason: '.json_encode($this->reason, JSON_PRETTY_PRINT); - } - - parent::__construct($message); - } - - /** - * Returns the rejection reason. - * - * @return mixed - */ - public function getReason() - { - return $this->reason; - } -} diff --git a/lib/guzzlehttp/promises/src/TaskQueue.php b/lib/guzzlehttp/promises/src/TaskQueue.php deleted file mode 100644 index 503e0b2da..000000000 --- a/lib/guzzlehttp/promises/src/TaskQueue.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Promise; - -/** - * A task queue that executes tasks in a FIFO order. - * - * This task queue class is used to settle promises asynchronously and - * maintains a constant stack size. You can use the task queue asynchronously - * by calling the `run()` function of the global task queue in an event loop. - * - * GuzzleHttp\Promise\Utils::queue()->run(); - * - * @final - */ -class TaskQueue implements TaskQueueInterface -{ - private $enableShutdown = true; - private $queue = []; - - public function __construct(bool $withShutdown = true) - { - if ($withShutdown) { - register_shutdown_function(function (): void { - if ($this->enableShutdown) { - // Only run the tasks if an E_ERROR didn't occur. - $err = error_get_last(); - if (!$err || ($err['type'] ^ E_ERROR)) { - $this->run(); - } - } - }); - } - } - - public function isEmpty(): bool - { - return !$this->queue; - } - - public function add(callable $task): void - { - $this->queue[] = $task; - } - - public function run(): void - { - while ($task = array_shift($this->queue)) { - /** @var callable $task */ - $task(); - } - } - - /** - * The task queue will be run and exhausted by default when the process - * exits IFF the exit is not the result of a PHP E_ERROR error. - * - * You can disable running the automatic shutdown of the queue by calling - * this function. If you disable the task queue shutdown process, then you - * MUST either run the task queue (as a result of running your event loop - * or manually using the run() method) or wait on each outstanding promise. - * - * Note: This shutdown will occur before any destructors are triggered. - */ - public function disableShutdown(): void - { - $this->enableShutdown = false; - } -} diff --git a/lib/guzzlehttp/promises/src/TaskQueueInterface.php b/lib/guzzlehttp/promises/src/TaskQueueInterface.php deleted file mode 100644 index 34c561a48..000000000 --- a/lib/guzzlehttp/promises/src/TaskQueueInterface.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Promise; - -interface TaskQueueInterface -{ - /** - * Returns true if the queue is empty. - */ - public function isEmpty(): bool; - - /** - * Adds a task to the queue that will be executed the next time run is - * called. - */ - public function add(callable $task): void; - - /** - * Execute all of the pending task in the queue. - */ - public function run(): void; -} diff --git a/lib/guzzlehttp/promises/src/Utils.php b/lib/guzzlehttp/promises/src/Utils.php deleted file mode 100644 index e1570d727..000000000 --- a/lib/guzzlehttp/promises/src/Utils.php +++ /dev/null @@ -1,259 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Promise; - -final class Utils -{ - /** - * Get the global task queue used for promise resolution. - * - * This task queue MUST be run in an event loop in order for promises to be - * settled asynchronously. It will be automatically run when synchronously - * waiting on a promise. - * - * <code> - * while ($eventLoop->isRunning()) { - * GuzzleHttp\Promise\Utils::queue()->run(); - * } - * </code> - * - * @param TaskQueueInterface|null $assign Optionally specify a new queue instance. - */ - public static function queue(TaskQueueInterface $assign = null): TaskQueueInterface - { - static $queue; - - if ($assign) { - $queue = $assign; - } elseif (!$queue) { - $queue = new TaskQueue(); - } - - return $queue; - } - - /** - * Adds a function to run in the task queue when it is next `run()` and - * returns a promise that is fulfilled or rejected with the result. - * - * @param callable $task Task function to run. - */ - public static function task(callable $task): PromiseInterface - { - $queue = self::queue(); - $promise = new Promise([$queue, 'run']); - $queue->add(function () use ($task, $promise): void { - try { - if (Is::pending($promise)) { - $promise->resolve($task()); - } - } catch (\Throwable $e) { - $promise->reject($e); - } - }); - - return $promise; - } - - /** - * Synchronously waits on a promise to resolve and returns an inspection - * state array. - * - * Returns a state associative array containing a "state" key mapping to a - * valid promise state. If the state of the promise is "fulfilled", the - * array will contain a "value" key mapping to the fulfilled value of the - * promise. If the promise is rejected, the array will contain a "reason" - * key mapping to the rejection reason of the promise. - * - * @param PromiseInterface $promise Promise or value. - */ - public static function inspect(PromiseInterface $promise): array - { - try { - return [ - 'state' => PromiseInterface::FULFILLED, - 'value' => $promise->wait(), - ]; - } catch (RejectionException $e) { - return ['state' => PromiseInterface::REJECTED, 'reason' => $e->getReason()]; - } catch (\Throwable $e) { - return ['state' => PromiseInterface::REJECTED, 'reason' => $e]; - } - } - - /** - * Waits on all of the provided promises, but does not unwrap rejected - * promises as thrown exception. - * - * Returns an array of inspection state arrays. - * - * @see inspect for the inspection state array format. - * - * @param PromiseInterface[] $promises Traversable of promises to wait upon. - */ - public static function inspectAll($promises): array - { - $results = []; - foreach ($promises as $key => $promise) { - $results[$key] = self::inspect($promise); - } - - return $results; - } - - /** - * Waits on all of the provided promises and returns the fulfilled values. - * - * Returns an array that contains the value of each promise (in the same - * order the promises were provided). An exception is thrown if any of the - * promises are rejected. - * - * @param iterable<PromiseInterface> $promises Iterable of PromiseInterface objects to wait on. - * - * @throws \Throwable on error - */ - public static function unwrap($promises): array - { - $results = []; - foreach ($promises as $key => $promise) { - $results[$key] = $promise->wait(); - } - - return $results; - } - - /** - * Given an array of promises, return a promise that is fulfilled when all - * the items in the array are fulfilled. - * - * The promise's fulfillment value is an array with fulfillment values at - * respective positions to the original array. If any promise in the array - * rejects, the returned promise is rejected with the rejection reason. - * - * @param mixed $promises Promises or values. - * @param bool $recursive If true, resolves new promises that might have been added to the stack during its own resolution. - */ - public static function all($promises, bool $recursive = false): PromiseInterface - { - $results = []; - $promise = Each::of( - $promises, - function ($value, $idx) use (&$results): void { - $results[$idx] = $value; - }, - function ($reason, $idx, Promise $aggregate): void { - $aggregate->reject($reason); - } - )->then(function () use (&$results) { - ksort($results); - - return $results; - }); - - if (true === $recursive) { - $promise = $promise->then(function ($results) use ($recursive, &$promises) { - foreach ($promises as $promise) { - if (Is::pending($promise)) { - return self::all($promises, $recursive); - } - } - - return $results; - }); - } - - return $promise; - } - - /** - * Initiate a competitive race between multiple promises or values (values - * will become immediately fulfilled promises). - * - * When count amount of promises have been fulfilled, the returned promise - * is fulfilled with an array that contains the fulfillment values of the - * winners in order of resolution. - * - * This promise is rejected with a {@see AggregateException} if the number - * of fulfilled promises is less than the desired $count. - * - * @param int $count Total number of promises. - * @param mixed $promises Promises or values. - */ - public static function some(int $count, $promises): PromiseInterface - { - $results = []; - $rejections = []; - - return Each::of( - $promises, - function ($value, $idx, PromiseInterface $p) use (&$results, $count): void { - if (Is::settled($p)) { - return; - } - $results[$idx] = $value; - if (count($results) >= $count) { - $p->resolve(null); - } - }, - function ($reason) use (&$rejections): void { - $rejections[] = $reason; - } - )->then( - function () use (&$results, &$rejections, $count) { - if (count($results) !== $count) { - throw new AggregateException( - 'Not enough promises to fulfill count', - $rejections - ); - } - ksort($results); - - return array_values($results); - } - ); - } - - /** - * Like some(), with 1 as count. However, if the promise fulfills, the - * fulfillment value is not an array of 1 but the value directly. - * - * @param mixed $promises Promises or values. - */ - public static function any($promises): PromiseInterface - { - return self::some(1, $promises)->then(function ($values) { - return $values[0]; - }); - } - - /** - * Returns a promise that is fulfilled when all of the provided promises have - * been fulfilled or rejected. - * - * The returned promise is fulfilled with an array of inspection state arrays. - * - * @see inspect for the inspection state array format. - * - * @param mixed $promises Promises or values. - */ - public static function settle($promises): PromiseInterface - { - $results = []; - - return Each::of( - $promises, - function ($value, $idx) use (&$results): void { - $results[$idx] = ['state' => PromiseInterface::FULFILLED, 'value' => $value]; - }, - function ($reason, $idx) use (&$results): void { - $results[$idx] = ['state' => PromiseInterface::REJECTED, 'reason' => $reason]; - } - )->then(function () use (&$results) { - ksort($results); - - return $results; - }); - } -} diff --git a/lib/guzzlehttp/promises/vendor-bin/php-cs-fixer/composer.json b/lib/guzzlehttp/promises/vendor-bin/php-cs-fixer/composer.json deleted file mode 100644 index c9dd5ee42..000000000 --- a/lib/guzzlehttp/promises/vendor-bin/php-cs-fixer/composer.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "require": { - "php": "^7.4 || ^8.0", - "friendsofphp/php-cs-fixer": "3.16.0" - }, - "config": { - "preferred-install": "dist" - } -} diff --git a/lib/guzzlehttp/promises/vendor-bin/phpstan/composer.json b/lib/guzzlehttp/promises/vendor-bin/phpstan/composer.json deleted file mode 100644 index 711507cba..000000000 --- a/lib/guzzlehttp/promises/vendor-bin/phpstan/composer.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "require": { - "php": "^7.4 || ^8.0", - "phpstan/phpstan": "1.10.11", - "phpstan/phpstan-deprecation-rules": "1.1.3" - }, - "config": { - "preferred-install": "dist" - } -} diff --git a/lib/guzzlehttp/promises/vendor-bin/psalm/composer.json b/lib/guzzlehttp/promises/vendor-bin/psalm/composer.json deleted file mode 100644 index ab96f2caf..000000000 --- a/lib/guzzlehttp/promises/vendor-bin/psalm/composer.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "require": { - "php": "^7.4 || ^8.0", - "psalm/phar": "5.9.0" - }, - "config": { - "preferred-install": "dist" - } -} diff --git a/lib/guzzlehttp/psr7/CHANGELOG.md b/lib/guzzlehttp/psr7/CHANGELOG.md deleted file mode 100644 index fa716c094..000000000 --- a/lib/guzzlehttp/psr7/CHANGELOG.md +++ /dev/null @@ -1,416 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## Unreleased - -## 2.5.0 - 2023-04-17 - -### Changed - -- Adjusted `psr/http-message` version constraint to `^1.1 || ^2.0` - -## 2.4.5 - 2023-04-17 - -### Fixed - -- Prevent possible warnings on unset variables in `ServerRequest::normalizeNestedFileSpec` -- Fixed `Message::bodySummary` when `preg_match` fails -- Fixed header validation issue - -## 2.4.4 - 2023-03-09 - -### Changed - -- Removed the need for `AllowDynamicProperties` in `LazyOpenStream` - -## 2.4.3 - 2022-10-26 - -### Changed - -- Replaced `sha1(uniqid())` by `bin2hex(random_bytes(20))` - -## 2.4.2 - 2022-10-25 - -### Fixed - -- Fixed erroneous behaviour when combining host and relative path - -## 2.4.1 - 2022-08-28 - -### Fixed - -- Rewind body before reading in `Message::bodySummary` - -## 2.4.0 - 2022-06-20 - -### Added - -- Added provisional PHP 8.2 support -- Added `UriComparator::isCrossOrigin` method - -## 2.3.0 - 2022-06-09 - -### Fixed - -- Added `Header::splitList` method -- Added `Utils::tryGetContents` method -- Improved `Stream::getContents` method -- Updated mimetype mappings - -## 2.2.2 - 2022-06-08 - -### Fixed - -- Fix `Message::parseRequestUri` for numeric headers -- Re-wrap exceptions thrown in `fread` into runtime exceptions -- Throw an exception when multipart options is misformatted - -## 2.2.1 - 2022-03-20 - -### Fixed - -- Correct header value validation - -## 2.2.0 - 2022-03-20 - -### Added - -- A more compressive list of mime types -- Add JsonSerializable to Uri -- Missing return types - -### Fixed - -- Bug MultipartStream no `uri` metadata -- Bug MultipartStream with filename for `data://` streams -- Fixed new line handling in MultipartStream -- Reduced RAM usage when copying streams -- Updated parsing in `Header::normalize()` - -## 2.1.1 - 2022-03-20 - -### Fixed - -- Validate header values properly - -## 2.1.0 - 2021-10-06 - -### Changed - -- Attempting to create a `Uri` object from a malformed URI will no longer throw a generic - `InvalidArgumentException`, but rather a `MalformedUriException`, which inherits from the former - for backwards compatibility. Callers relying on the exception being thrown to detect invalid - URIs should catch the new exception. - -### Fixed - -- Return `null` in caching stream size if remote size is `null` - -## 2.0.0 - 2021-06-30 - -Identical to the RC release. - -## 2.0.0@RC-1 - 2021-04-29 - -### Fixed - -- Handle possibly unset `url` in `stream_get_meta_data` - -## 2.0.0@beta-1 - 2021-03-21 - -### Added - -- PSR-17 factories -- Made classes final -- PHP7 type hints - -### Changed - -- When building a query string, booleans are represented as 1 and 0. - -### Removed - -- PHP < 7.2 support -- All functions in the `GuzzleHttp\Psr7` namespace - -## 1.8.1 - 2021-03-21 - -### Fixed - -- Issue parsing IPv6 URLs -- Issue modifying ServerRequest lost all its attributes - -## 1.8.0 - 2021-03-21 - -### Added - -- Locale independent URL parsing -- Most classes got a `@final` annotation to prepare for 2.0 - -### Fixed - -- Issue when creating stream from `php://input` and curl-ext is not installed -- Broken `Utils::tryFopen()` on PHP 8 - -## 1.7.0 - 2020-09-30 - -### Added - -- Replaced functions by static methods - -### Fixed - -- Converting a non-seekable stream to a string -- Handle multiple Set-Cookie correctly -- Ignore array keys in header values when merging -- Allow multibyte characters to be parsed in `Message:bodySummary()` - -### Changed - -- Restored partial HHVM 3 support - - -## [1.6.1] - 2019-07-02 - -### Fixed - -- Accept null and bool header values again - - -## [1.6.0] - 2019-06-30 - -### Added - -- Allowed version `^3.0` of `ralouphie/getallheaders` dependency (#244) -- Added MIME type for WEBP image format (#246) -- Added more validation of values according to PSR-7 and RFC standards, e.g. status code range (#250, #272) - -### Changed - -- Tests don't pass with HHVM 4.0, so HHVM support got dropped. Other libraries like composer have done the same. (#262) -- Accept port number 0 to be valid (#270) - -### Fixed - -- Fixed subsequent reads from `php://input` in ServerRequest (#247) -- Fixed readable/writable detection for certain stream modes (#248) -- Fixed encoding of special characters in the `userInfo` component of an URI (#253) - - -## [1.5.2] - 2018-12-04 - -### Fixed - -- Check body size when getting the message summary - - -## [1.5.1] - 2018-12-04 - -### Fixed - -- Get the summary of a body only if it is readable - - -## [1.5.0] - 2018-12-03 - -### Added - -- Response first-line to response string exception (fixes #145) -- A test for #129 behavior -- `get_message_body_summary` function in order to get the message summary -- `3gp` and `mkv` mime types - -### Changed - -- Clarify exception message when stream is detached - -### Deprecated - -- Deprecated parsing folded header lines as per RFC 7230 - -### Fixed - -- Fix `AppendStream::detach` to not close streams -- `InflateStream` preserves `isSeekable` attribute of the underlying stream -- `ServerRequest::getUriFromGlobals` to support URLs in query parameters - - -Several other fixes and improvements. - - -## [1.4.2] - 2017-03-20 - -### Fixed - -- Reverted BC break to `Uri::resolve` and `Uri::removeDotSegments` by removing - calls to `trigger_error` when deprecated methods are invoked. - - -## [1.4.1] - 2017-02-27 - -### Added - -- Rriggering of silenced deprecation warnings. - -### Fixed - -- Reverted BC break by reintroducing behavior to automagically fix a URI with a - relative path and an authority by adding a leading slash to the path. It's only - deprecated now. - - -## [1.4.0] - 2017-02-21 - -### Added - -- Added common URI utility methods based on RFC 3986 (see documentation in the readme): - - `Uri::isDefaultPort` - - `Uri::isAbsolute` - - `Uri::isNetworkPathReference` - - `Uri::isAbsolutePathReference` - - `Uri::isRelativePathReference` - - `Uri::isSameDocumentReference` - - `Uri::composeComponents` - - `UriNormalizer::normalize` - - `UriNormalizer::isEquivalent` - - `UriResolver::relativize` - -### Changed - -- Ensure `ServerRequest::getUriFromGlobals` returns a URI in absolute form. -- Allow `parse_response` to parse a response without delimiting space and reason. -- Ensure each URI modification results in a valid URI according to PSR-7 discussions. - Invalid modifications will throw an exception instead of returning a wrong URI or - doing some magic. - - `(new Uri)->withPath('foo')->withHost('example.com')` will throw an exception - because the path of a URI with an authority must start with a slash "/" or be empty - - `(new Uri())->withScheme('http')` will return `'http://localhost'` - -### Deprecated - -- `Uri::resolve` in favor of `UriResolver::resolve` -- `Uri::removeDotSegments` in favor of `UriResolver::removeDotSegments` - -### Fixed - -- `Stream::read` when length parameter <= 0. -- `copy_to_stream` reads bytes in chunks instead of `maxLen` into memory. -- `ServerRequest::getUriFromGlobals` when `Host` header contains port. -- Compatibility of URIs with `file` scheme and empty host. - - -## [1.3.1] - 2016-06-25 - -### Fixed - -- `Uri::__toString` for network path references, e.g. `//example.org`. -- Missing lowercase normalization for host. -- Handling of URI components in case they are `'0'` in a lot of places, - e.g. as a user info password. -- `Uri::withAddedHeader` to correctly merge headers with different case. -- Trimming of header values in `Uri::withAddedHeader`. Header values may - be surrounded by whitespace which should be ignored according to RFC 7230 - Section 3.2.4. This does not apply to header names. -- `Uri::withAddedHeader` with an array of header values. -- `Uri::resolve` when base path has no slash and handling of fragment. -- Handling of encoding in `Uri::with(out)QueryValue` so one can pass the - key/value both in encoded as well as decoded form to those methods. This is - consistent with withPath, withQuery etc. -- `ServerRequest::withoutAttribute` when attribute value is null. - - -## [1.3.0] - 2016-04-13 - -### Added - -- Remaining interfaces needed for full PSR7 compatibility - (ServerRequestInterface, UploadedFileInterface, etc.). -- Support for stream_for from scalars. - -### Changed - -- Can now extend Uri. - -### Fixed -- A bug in validating request methods by making it more permissive. - - -## [1.2.3] - 2016-02-18 - -### Fixed - -- Support in `GuzzleHttp\Psr7\CachingStream` for seeking forward on remote - streams, which can sometimes return fewer bytes than requested with `fread`. -- Handling of gzipped responses with FNAME headers. - - -## [1.2.2] - 2016-01-22 - -### Added - -- Support for URIs without any authority. -- Support for HTTP 451 'Unavailable For Legal Reasons.' -- Support for using '0' as a filename. -- Support for including non-standard ports in Host headers. - - -## [1.2.1] - 2015-11-02 - -### Changes - -- Now supporting negative offsets when seeking to SEEK_END. - - -## [1.2.0] - 2015-08-15 - -### Changed - -- Body as `"0"` is now properly added to a response. -- Now allowing forward seeking in CachingStream. -- Now properly parsing HTTP requests that contain proxy targets in - `parse_request`. -- functions.php is now conditionally required. -- user-info is no longer dropped when resolving URIs. - - -## [1.1.0] - 2015-06-24 - -### Changed - -- URIs can now be relative. -- `multipart/form-data` headers are now overridden case-insensitively. -- URI paths no longer encode the following characters because they are allowed - in URIs: "(", ")", "*", "!", "'" -- A port is no longer added to a URI when the scheme is missing and no port is - present. - - -## 1.0.0 - 2015-05-19 - -Initial release. - -Currently unsupported: - -- `Psr\Http\Message\ServerRequestInterface` -- `Psr\Http\Message\UploadedFileInterface` - - - -[1.6.0]: https://github.com/guzzle/psr7/compare/1.5.2...1.6.0 -[1.5.2]: https://github.com/guzzle/psr7/compare/1.5.1...1.5.2 -[1.5.1]: https://github.com/guzzle/psr7/compare/1.5.0...1.5.1 -[1.5.0]: https://github.com/guzzle/psr7/compare/1.4.2...1.5.0 -[1.4.2]: https://github.com/guzzle/psr7/compare/1.4.1...1.4.2 -[1.4.1]: https://github.com/guzzle/psr7/compare/1.4.0...1.4.1 -[1.4.0]: https://github.com/guzzle/psr7/compare/1.3.1...1.4.0 -[1.3.1]: https://github.com/guzzle/psr7/compare/1.3.0...1.3.1 -[1.3.0]: https://github.com/guzzle/psr7/compare/1.2.3...1.3.0 -[1.2.3]: https://github.com/guzzle/psr7/compare/1.2.2...1.2.3 -[1.2.2]: https://github.com/guzzle/psr7/compare/1.2.1...1.2.2 -[1.2.1]: https://github.com/guzzle/psr7/compare/1.2.0...1.2.1 -[1.2.0]: https://github.com/guzzle/psr7/compare/1.1.0...1.2.0 -[1.1.0]: https://github.com/guzzle/psr7/compare/1.0.0...1.1.0 diff --git a/lib/guzzlehttp/psr7/LICENSE b/lib/guzzlehttp/psr7/LICENSE deleted file mode 100644 index 51c7ec81c..000000000 --- a/lib/guzzlehttp/psr7/LICENSE +++ /dev/null @@ -1,26 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Michael Dowling <mtdowling@gmail.com> -Copyright (c) 2015 Márk Sági-Kazár <mark.sagikazar@gmail.com> -Copyright (c) 2015 Graham Campbell <hello@gjcampbell.co.uk> -Copyright (c) 2016 Tobias Schultze <webmaster@tubo-world.de> -Copyright (c) 2016 George Mponos <gmponos@gmail.com> -Copyright (c) 2018 Tobias Nyholm <tobias.nyholm@gmail.com> - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -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/lib/guzzlehttp/psr7/README.md b/lib/guzzlehttp/psr7/README.md deleted file mode 100644 index 9566a7d47..000000000 --- a/lib/guzzlehttp/psr7/README.md +++ /dev/null @@ -1,880 +0,0 @@ -# PSR-7 Message Implementation - -This repository contains a full [PSR-7](https://www.php-fig.org/psr/psr-7/) -message implementation, several stream decorators, and some helpful -functionality like query string parsing. - -![CI](https://github.com/guzzle/psr7/workflows/CI/badge.svg) -![Static analysis](https://github.com/guzzle/psr7/workflows/Static%20analysis/badge.svg) - - -# Installation - -```shell -composer require guzzlehttp/psr7 -``` - -# Stream implementation - -This package comes with a number of stream implementations and stream -decorators. - - -## AppendStream - -`GuzzleHttp\Psr7\AppendStream` - -Reads from multiple streams, one after the other. - -```php -use GuzzleHttp\Psr7; - -$a = Psr7\Utils::streamFor('abc, '); -$b = Psr7\Utils::streamFor('123.'); -$composed = new Psr7\AppendStream([$a, $b]); - -$composed->addStream(Psr7\Utils::streamFor(' Above all listen to me')); - -echo $composed; // abc, 123. Above all listen to me. -``` - - -## BufferStream - -`GuzzleHttp\Psr7\BufferStream` - -Provides a buffer stream that can be written to fill a buffer, and read -from to remove bytes from the buffer. - -This stream returns a "hwm" metadata value that tells upstream consumers -what the configured high water mark of the stream is, or the maximum -preferred size of the buffer. - -```php -use GuzzleHttp\Psr7; - -// When more than 1024 bytes are in the buffer, it will begin returning -// false to writes. This is an indication that writers should slow down. -$buffer = new Psr7\BufferStream(1024); -``` - - -## CachingStream - -The CachingStream is used to allow seeking over previously read bytes on -non-seekable streams. This can be useful when transferring a non-seekable -entity body fails due to needing to rewind the stream (for example, resulting -from a redirect). Data that is read from the remote stream will be buffered in -a PHP temp stream so that previously read bytes are cached first in memory, -then on disk. - -```php -use GuzzleHttp\Psr7; - -$original = Psr7\Utils::streamFor(fopen('http://www.google.com', 'r')); -$stream = new Psr7\CachingStream($original); - -$stream->read(1024); -echo $stream->tell(); -// 1024 - -$stream->seek(0); -echo $stream->tell(); -// 0 -``` - - -## DroppingStream - -`GuzzleHttp\Psr7\DroppingStream` - -Stream decorator that begins dropping data once the size of the underlying -stream becomes too full. - -```php -use GuzzleHttp\Psr7; - -// Create an empty stream -$stream = Psr7\Utils::streamFor(); - -// Start dropping data when the stream has more than 10 bytes -$dropping = new Psr7\DroppingStream($stream, 10); - -$dropping->write('01234567890123456789'); -echo $stream; // 0123456789 -``` - - -## FnStream - -`GuzzleHttp\Psr7\FnStream` - -Compose stream implementations based on a hash of functions. - -Allows for easy testing and extension of a provided stream without needing -to create a concrete class for a simple extension point. - -```php - -use GuzzleHttp\Psr7; - -$stream = Psr7\Utils::streamFor('hi'); -$fnStream = Psr7\FnStream::decorate($stream, [ - 'rewind' => function () use ($stream) { - echo 'About to rewind - '; - $stream->rewind(); - echo 'rewound!'; - } -]); - -$fnStream->rewind(); -// Outputs: About to rewind - rewound! -``` - - -## InflateStream - -`GuzzleHttp\Psr7\InflateStream` - -Uses PHP's zlib.inflate filter to inflate zlib (HTTP deflate, RFC1950) or gzipped (RFC1952) content. - -This stream decorator converts the provided stream to a PHP stream resource, -then appends the zlib.inflate filter. The stream is then converted back -to a Guzzle stream resource to be used as a Guzzle stream. - - -## LazyOpenStream - -`GuzzleHttp\Psr7\LazyOpenStream` - -Lazily reads or writes to a file that is opened only after an IO operation -take place on the stream. - -```php -use GuzzleHttp\Psr7; - -$stream = new Psr7\LazyOpenStream('/path/to/file', 'r'); -// The file has not yet been opened... - -echo $stream->read(10); -// The file is opened and read from only when needed. -``` - - -## LimitStream - -`GuzzleHttp\Psr7\LimitStream` - -LimitStream can be used to read a subset or slice of an existing stream object. -This can be useful for breaking a large file into smaller pieces to be sent in -chunks (e.g. Amazon S3's multipart upload API). - -```php -use GuzzleHttp\Psr7; - -$original = Psr7\Utils::streamFor(fopen('/tmp/test.txt', 'r+')); -echo $original->getSize(); -// >>> 1048576 - -// Limit the size of the body to 1024 bytes and start reading from byte 2048 -$stream = new Psr7\LimitStream($original, 1024, 2048); -echo $stream->getSize(); -// >>> 1024 -echo $stream->tell(); -// >>> 0 -``` - - -## MultipartStream - -`GuzzleHttp\Psr7\MultipartStream` - -Stream that when read returns bytes for a streaming multipart or -multipart/form-data stream. - - -## NoSeekStream - -`GuzzleHttp\Psr7\NoSeekStream` - -NoSeekStream wraps a stream and does not allow seeking. - -```php -use GuzzleHttp\Psr7; - -$original = Psr7\Utils::streamFor('foo'); -$noSeek = new Psr7\NoSeekStream($original); - -echo $noSeek->read(3); -// foo -var_export($noSeek->isSeekable()); -// false -$noSeek->seek(0); -var_export($noSeek->read(3)); -// NULL -``` - - -## PumpStream - -`GuzzleHttp\Psr7\PumpStream` - -Provides a read only stream that pumps data from a PHP callable. - -When invoking the provided callable, the PumpStream will pass the amount of -data requested to read to the callable. The callable can choose to ignore -this value and return fewer or more bytes than requested. Any extra data -returned by the provided callable is buffered internally until drained using -the read() function of the PumpStream. The provided callable MUST return -false when there is no more data to read. - - -## Implementing stream decorators - -Creating a stream decorator is very easy thanks to the -`GuzzleHttp\Psr7\StreamDecoratorTrait`. This trait provides methods that -implement `Psr\Http\Message\StreamInterface` by proxying to an underlying -stream. Just `use` the `StreamDecoratorTrait` and implement your custom -methods. - -For example, let's say we wanted to call a specific function each time the last -byte is read from a stream. This could be implemented by overriding the -`read()` method. - -```php -use Psr\Http\Message\StreamInterface; -use GuzzleHttp\Psr7\StreamDecoratorTrait; - -class EofCallbackStream implements StreamInterface -{ - use StreamDecoratorTrait; - - private $callback; - - private $stream; - - public function __construct(StreamInterface $stream, callable $cb) - { - $this->stream = $stream; - $this->callback = $cb; - } - - public function read($length) - { - $result = $this->stream->read($length); - - // Invoke the callback when EOF is hit. - if ($this->eof()) { - call_user_func($this->callback); - } - - return $result; - } -} -``` - -This decorator could be added to any existing stream and used like so: - -```php -use GuzzleHttp\Psr7; - -$original = Psr7\Utils::streamFor('foo'); - -$eofStream = new EofCallbackStream($original, function () { - echo 'EOF!'; -}); - -$eofStream->read(2); -$eofStream->read(1); -// echoes "EOF!" -$eofStream->seek(0); -$eofStream->read(3); -// echoes "EOF!" -``` - - -## PHP StreamWrapper - -You can use the `GuzzleHttp\Psr7\StreamWrapper` class if you need to use a -PSR-7 stream as a PHP stream resource. - -Use the `GuzzleHttp\Psr7\StreamWrapper::getResource()` method to create a PHP -stream from a PSR-7 stream. - -```php -use GuzzleHttp\Psr7\StreamWrapper; - -$stream = GuzzleHttp\Psr7\Utils::streamFor('hello!'); -$resource = StreamWrapper::getResource($stream); -echo fread($resource, 6); // outputs hello! -``` - - -# Static API - -There are various static methods available under the `GuzzleHttp\Psr7` namespace. - - -## `GuzzleHttp\Psr7\Message::toString` - -`public static function toString(MessageInterface $message): string` - -Returns the string representation of an HTTP message. - -```php -$request = new GuzzleHttp\Psr7\Request('GET', 'http://example.com'); -echo GuzzleHttp\Psr7\Message::toString($request); -``` - - -## `GuzzleHttp\Psr7\Message::bodySummary` - -`public static function bodySummary(MessageInterface $message, int $truncateAt = 120): string|null` - -Get a short summary of the message body. - -Will return `null` if the response is not printable. - - -## `GuzzleHttp\Psr7\Message::rewindBody` - -`public static function rewindBody(MessageInterface $message): void` - -Attempts to rewind a message body and throws an exception on failure. - -The body of the message will only be rewound if a call to `tell()` -returns a value other than `0`. - - -## `GuzzleHttp\Psr7\Message::parseMessage` - -`public static function parseMessage(string $message): array` - -Parses an HTTP message into an associative array. - -The array contains the "start-line" key containing the start line of -the message, "headers" key containing an associative array of header -array values, and a "body" key containing the body of the message. - - -## `GuzzleHttp\Psr7\Message::parseRequestUri` - -`public static function parseRequestUri(string $path, array $headers): string` - -Constructs a URI for an HTTP request message. - - -## `GuzzleHttp\Psr7\Message::parseRequest` - -`public static function parseRequest(string $message): Request` - -Parses a request message string into a request object. - - -## `GuzzleHttp\Psr7\Message::parseResponse` - -`public static function parseResponse(string $message): Response` - -Parses a response message string into a response object. - - -## `GuzzleHttp\Psr7\Header::parse` - -`public static function parse(string|array $header): array` - -Parse an array of header values containing ";" separated data into an -array of associative arrays representing the header key value pair data -of the header. When a parameter does not contain a value, but just -contains a key, this function will inject a key with a '' string value. - - -## `GuzzleHttp\Psr7\Header::splitList` - -`public static function splitList(string|string[] $header): string[]` - -Splits a HTTP header defined to contain a comma-separated list into -each individual value: - -``` -$knownEtags = Header::splitList($request->getHeader('if-none-match')); -``` - -Example headers include `accept`, `cache-control` and `if-none-match`. - - -## `GuzzleHttp\Psr7\Header::normalize` (deprecated) - -`public static function normalize(string|array $header): array` - -`Header::normalize()` is deprecated in favor of [`Header::splitList()`](README.md#guzzlehttppsr7headersplitlist) -which performs the same operation with a cleaned up API and improved -documentation. - -Converts an array of header values that may contain comma separated -headers into an array of headers with no comma separated values. - - -## `GuzzleHttp\Psr7\Query::parse` - -`public static function parse(string $str, int|bool $urlEncoding = true): array` - -Parse a query string into an associative array. - -If multiple values are found for the same key, the value of that key -value pair will become an array. This function does not parse nested -PHP style arrays into an associative array (e.g., `foo[a]=1&foo[b]=2` -will be parsed into `['foo[a]' => '1', 'foo[b]' => '2'])`. - - -## `GuzzleHttp\Psr7\Query::build` - -`public static function build(array $params, int|false $encoding = PHP_QUERY_RFC3986): string` - -Build a query string from an array of key value pairs. - -This function can use the return value of `parse()` to build a query -string. This function does not modify the provided keys when an array is -encountered (like `http_build_query()` would). - - -## `GuzzleHttp\Psr7\Utils::caselessRemove` - -`public static function caselessRemove(iterable<string> $keys, $keys, array $data): array` - -Remove the items given by the keys, case insensitively from the data. - - -## `GuzzleHttp\Psr7\Utils::copyToStream` - -`public static function copyToStream(StreamInterface $source, StreamInterface $dest, int $maxLen = -1): void` - -Copy the contents of a stream into another stream until the given number -of bytes have been read. - - -## `GuzzleHttp\Psr7\Utils::copyToString` - -`public static function copyToString(StreamInterface $stream, int $maxLen = -1): string` - -Copy the contents of a stream into a string until the given number of -bytes have been read. - - -## `GuzzleHttp\Psr7\Utils::hash` - -`public static function hash(StreamInterface $stream, string $algo, bool $rawOutput = false): string` - -Calculate a hash of a stream. - -This method reads the entire stream to calculate a rolling hash, based on -PHP's `hash_init` functions. - - -## `GuzzleHttp\Psr7\Utils::modifyRequest` - -`public static function modifyRequest(RequestInterface $request, array $changes): RequestInterface` - -Clone and modify a request with the given changes. - -This method is useful for reducing the number of clones needed to mutate -a message. - -- method: (string) Changes the HTTP method. -- set_headers: (array) Sets the given headers. -- remove_headers: (array) Remove the given headers. -- body: (mixed) Sets the given body. -- uri: (UriInterface) Set the URI. -- query: (string) Set the query string value of the URI. -- version: (string) Set the protocol version. - - -## `GuzzleHttp\Psr7\Utils::readLine` - -`public static function readLine(StreamInterface $stream, int $maxLength = null): string` - -Read a line from the stream up to the maximum allowed buffer length. - - -## `GuzzleHttp\Psr7\Utils::streamFor` - -`public static function streamFor(resource|string|null|int|float|bool|StreamInterface|callable|\Iterator $resource = '', array $options = []): StreamInterface` - -Create a new stream based on the input type. - -Options is an associative array that can contain the following keys: - -- metadata: Array of custom metadata. -- size: Size of the stream. - -This method accepts the following `$resource` types: - -- `Psr\Http\Message\StreamInterface`: Returns the value as-is. -- `string`: Creates a stream object that uses the given string as the contents. -- `resource`: Creates a stream object that wraps the given PHP stream resource. -- `Iterator`: If the provided value implements `Iterator`, then a read-only - stream object will be created that wraps the given iterable. Each time the - stream is read from, data from the iterator will fill a buffer and will be - continuously called until the buffer is equal to the requested read size. - Subsequent read calls will first read from the buffer and then call `next` - on the underlying iterator until it is exhausted. -- `object` with `__toString()`: If the object has the `__toString()` method, - the object will be cast to a string and then a stream will be returned that - uses the string value. -- `NULL`: When `null` is passed, an empty stream object is returned. -- `callable` When a callable is passed, a read-only stream object will be - created that invokes the given callable. The callable is invoked with the - number of suggested bytes to read. The callable can return any number of - bytes, but MUST return `false` when there is no more data to return. The - stream object that wraps the callable will invoke the callable until the - number of requested bytes are available. Any additional bytes will be - buffered and used in subsequent reads. - -```php -$stream = GuzzleHttp\Psr7\Utils::streamFor('foo'); -$stream = GuzzleHttp\Psr7\Utils::streamFor(fopen('/path/to/file', 'r')); - -$generator = function ($bytes) { - for ($i = 0; $i < $bytes; $i++) { - yield ' '; - } -} - -$stream = GuzzleHttp\Psr7\Utils::streamFor($generator(100)); -``` - - -## `GuzzleHttp\Psr7\Utils::tryFopen` - -`public static function tryFopen(string $filename, string $mode): resource` - -Safely opens a PHP stream resource using a filename. - -When fopen fails, PHP normally raises a warning. This function adds an -error handler that checks for errors and throws an exception instead. - - -## `GuzzleHttp\Psr7\Utils::tryGetContents` - -`public static function tryGetContents(resource $stream): string` - -Safely gets the contents of a given stream. - -When stream_get_contents fails, PHP normally raises a warning. This -function adds an error handler that checks for errors and throws an -exception instead. - - -## `GuzzleHttp\Psr7\Utils::uriFor` - -`public static function uriFor(string|UriInterface $uri): UriInterface` - -Returns a UriInterface for the given value. - -This function accepts a string or UriInterface and returns a -UriInterface for the given value. If the value is already a -UriInterface, it is returned as-is. - - -## `GuzzleHttp\Psr7\MimeType::fromFilename` - -`public static function fromFilename(string $filename): string|null` - -Determines the mimetype of a file by looking at its extension. - - -## `GuzzleHttp\Psr7\MimeType::fromExtension` - -`public static function fromExtension(string $extension): string|null` - -Maps a file extensions to a mimetype. - - -## Upgrading from Function API - -The static API was first introduced in 1.7.0, in order to mitigate problems with functions conflicting between global and local copies of the package. The function API was removed in 2.0.0. A migration table has been provided here for your convenience: - -| Original Function | Replacement Method | -|----------------|----------------| -| `str` | `Message::toString` | -| `uri_for` | `Utils::uriFor` | -| `stream_for` | `Utils::streamFor` | -| `parse_header` | `Header::parse` | -| `normalize_header` | `Header::normalize` | -| `modify_request` | `Utils::modifyRequest` | -| `rewind_body` | `Message::rewindBody` | -| `try_fopen` | `Utils::tryFopen` | -| `copy_to_string` | `Utils::copyToString` | -| `copy_to_stream` | `Utils::copyToStream` | -| `hash` | `Utils::hash` | -| `readline` | `Utils::readLine` | -| `parse_request` | `Message::parseRequest` | -| `parse_response` | `Message::parseResponse` | -| `parse_query` | `Query::parse` | -| `build_query` | `Query::build` | -| `mimetype_from_filename` | `MimeType::fromFilename` | -| `mimetype_from_extension` | `MimeType::fromExtension` | -| `_parse_message` | `Message::parseMessage` | -| `_parse_request_uri` | `Message::parseRequestUri` | -| `get_message_body_summary` | `Message::bodySummary` | -| `_caseless_remove` | `Utils::caselessRemove` | - - -# Additional URI Methods - -Aside from the standard `Psr\Http\Message\UriInterface` implementation in form of the `GuzzleHttp\Psr7\Uri` class, -this library also provides additional functionality when working with URIs as static methods. - -## URI Types - -An instance of `Psr\Http\Message\UriInterface` can either be an absolute URI or a relative reference. -An absolute URI has a scheme. A relative reference is used to express a URI relative to another URI, -the base URI. Relative references can be divided into several forms according to -[RFC 3986 Section 4.2](https://tools.ietf.org/html/rfc3986#section-4.2): - -- network-path references, e.g. `//example.com/path` -- absolute-path references, e.g. `/path` -- relative-path references, e.g. `subpath` - -The following methods can be used to identify the type of the URI. - -### `GuzzleHttp\Psr7\Uri::isAbsolute` - -`public static function isAbsolute(UriInterface $uri): bool` - -Whether the URI is absolute, i.e. it has a scheme. - -### `GuzzleHttp\Psr7\Uri::isNetworkPathReference` - -`public static function isNetworkPathReference(UriInterface $uri): bool` - -Whether the URI is a network-path reference. A relative reference that begins with two slash characters is -termed an network-path reference. - -### `GuzzleHttp\Psr7\Uri::isAbsolutePathReference` - -`public static function isAbsolutePathReference(UriInterface $uri): bool` - -Whether the URI is a absolute-path reference. A relative reference that begins with a single slash character is -termed an absolute-path reference. - -### `GuzzleHttp\Psr7\Uri::isRelativePathReference` - -`public static function isRelativePathReference(UriInterface $uri): bool` - -Whether the URI is a relative-path reference. A relative reference that does not begin with a slash character is -termed a relative-path reference. - -### `GuzzleHttp\Psr7\Uri::isSameDocumentReference` - -`public static function isSameDocumentReference(UriInterface $uri, UriInterface $base = null): bool` - -Whether the URI is a same-document reference. A same-document reference refers to a URI that is, aside from its -fragment component, identical to the base URI. When no base URI is given, only an empty URI reference -(apart from its fragment) is considered a same-document reference. - -## URI Components - -Additional methods to work with URI components. - -### `GuzzleHttp\Psr7\Uri::isDefaultPort` - -`public static function isDefaultPort(UriInterface $uri): bool` - -Whether the URI has the default port of the current scheme. `Psr\Http\Message\UriInterface::getPort` may return null -or the standard port. This method can be used independently of the implementation. - -### `GuzzleHttp\Psr7\Uri::composeComponents` - -`public static function composeComponents($scheme, $authority, $path, $query, $fragment): string` - -Composes a URI reference string from its various components according to -[RFC 3986 Section 5.3](https://tools.ietf.org/html/rfc3986#section-5.3). Usually this method does not need to be called -manually but instead is used indirectly via `Psr\Http\Message\UriInterface::__toString`. - -### `GuzzleHttp\Psr7\Uri::fromParts` - -`public static function fromParts(array $parts): UriInterface` - -Creates a URI from a hash of [`parse_url`](https://www.php.net/manual/en/function.parse-url.php) components. - - -### `GuzzleHttp\Psr7\Uri::withQueryValue` - -`public static function withQueryValue(UriInterface $uri, $key, $value): UriInterface` - -Creates a new URI with a specific query string value. Any existing query string values that exactly match the -provided key are removed and replaced with the given key value pair. A value of null will set the query string -key without a value, e.g. "key" instead of "key=value". - -### `GuzzleHttp\Psr7\Uri::withQueryValues` - -`public static function withQueryValues(UriInterface $uri, array $keyValueArray): UriInterface` - -Creates a new URI with multiple query string values. It has the same behavior as `withQueryValue()` but for an -associative array of key => value. - -### `GuzzleHttp\Psr7\Uri::withoutQueryValue` - -`public static function withoutQueryValue(UriInterface $uri, $key): UriInterface` - -Creates a new URI with a specific query string value removed. Any existing query string values that exactly match the -provided key are removed. - -## Cross-Origin Detection - -`GuzzleHttp\Psr7\UriComparator` provides methods to determine if a modified URL should be considered cross-origin. - -### `GuzzleHttp\Psr7\UriComparator::isCrossOrigin` - -`public static function isCrossOrigin(UriInterface $original, UriInterface $modified): bool` - -Determines if a modified URL should be considered cross-origin with respect to an original URL. - -## Reference Resolution - -`GuzzleHttp\Psr7\UriResolver` provides methods to resolve a URI reference in the context of a base URI according -to [RFC 3986 Section 5](https://tools.ietf.org/html/rfc3986#section-5). This is for example also what web browsers -do when resolving a link in a website based on the current request URI. - -### `GuzzleHttp\Psr7\UriResolver::resolve` - -`public static function resolve(UriInterface $base, UriInterface $rel): UriInterface` - -Converts the relative URI into a new URI that is resolved against the base URI. - -### `GuzzleHttp\Psr7\UriResolver::removeDotSegments` - -`public static function removeDotSegments(string $path): string` - -Removes dot segments from a path and returns the new path according to -[RFC 3986 Section 5.2.4](https://tools.ietf.org/html/rfc3986#section-5.2.4). - -### `GuzzleHttp\Psr7\UriResolver::relativize` - -`public static function relativize(UriInterface $base, UriInterface $target): UriInterface` - -Returns the target URI as a relative reference from the base URI. This method is the counterpart to resolve(): - -```php -(string) $target === (string) UriResolver::resolve($base, UriResolver::relativize($base, $target)) -``` - -One use-case is to use the current request URI as base URI and then generate relative links in your documents -to reduce the document size or offer self-contained downloadable document archives. - -```php -$base = new Uri('http://example.com/a/b/'); -echo UriResolver::relativize($base, new Uri('http://example.com/a/b/c')); // prints 'c'. -echo UriResolver::relativize($base, new Uri('http://example.com/a/x/y')); // prints '../x/y'. -echo UriResolver::relativize($base, new Uri('http://example.com/a/b/?q')); // prints '?q'. -echo UriResolver::relativize($base, new Uri('http://example.org/a/b/')); // prints '//example.org/a/b/'. -``` - -## Normalization and Comparison - -`GuzzleHttp\Psr7\UriNormalizer` provides methods to normalize and compare URIs according to -[RFC 3986 Section 6](https://tools.ietf.org/html/rfc3986#section-6). - -### `GuzzleHttp\Psr7\UriNormalizer::normalize` - -`public static function normalize(UriInterface $uri, $flags = self::PRESERVING_NORMALIZATIONS): UriInterface` - -Returns a normalized URI. The scheme and host component are already normalized to lowercase per PSR-7 UriInterface. -This methods adds additional normalizations that can be configured with the `$flags` parameter which is a bitmask -of normalizations to apply. The following normalizations are available: - -- `UriNormalizer::PRESERVING_NORMALIZATIONS` - - Default normalizations which only include the ones that preserve semantics. - -- `UriNormalizer::CAPITALIZE_PERCENT_ENCODING` - - All letters within a percent-encoding triplet (e.g., "%3A") are case-insensitive, and should be capitalized. - - Example: `http://example.org/a%c2%b1b` → `http://example.org/a%C2%B1b` - -- `UriNormalizer::DECODE_UNRESERVED_CHARACTERS` - - Decodes percent-encoded octets of unreserved characters. For consistency, percent-encoded octets in the ranges of - ALPHA (%41–%5A and %61–%7A), DIGIT (%30–%39), hyphen (%2D), period (%2E), underscore (%5F), or tilde (%7E) should - not be created by URI producers and, when found in a URI, should be decoded to their corresponding unreserved - characters by URI normalizers. - - Example: `http://example.org/%7Eusern%61me/` → `http://example.org/~username/` - -- `UriNormalizer::CONVERT_EMPTY_PATH` - - Converts the empty path to "/" for http and https URIs. - - Example: `http://example.org` → `http://example.org/` - -- `UriNormalizer::REMOVE_DEFAULT_HOST` - - Removes the default host of the given URI scheme from the URI. Only the "file" scheme defines the default host - "localhost". All of `file:/myfile`, `file:///myfile`, and `file://localhost/myfile` are equivalent according to - RFC 3986. - - Example: `file://localhost/myfile` → `file:///myfile` - -- `UriNormalizer::REMOVE_DEFAULT_PORT` - - Removes the default port of the given URI scheme from the URI. - - Example: `http://example.org:80/` → `http://example.org/` - -- `UriNormalizer::REMOVE_DOT_SEGMENTS` - - Removes unnecessary dot-segments. Dot-segments in relative-path references are not removed as it would - change the semantics of the URI reference. - - Example: `http://example.org/../a/b/../c/./d.html` → `http://example.org/a/c/d.html` - -- `UriNormalizer::REMOVE_DUPLICATE_SLASHES` - - Paths which include two or more adjacent slashes are converted to one. Webservers usually ignore duplicate slashes - and treat those URIs equivalent. But in theory those URIs do not need to be equivalent. So this normalization - may change the semantics. Encoded slashes (%2F) are not removed. - - Example: `http://example.org//foo///bar.html` → `http://example.org/foo/bar.html` - -- `UriNormalizer::SORT_QUERY_PARAMETERS` - - Sort query parameters with their values in alphabetical order. However, the order of parameters in a URI may be - significant (this is not defined by the standard). So this normalization is not safe and may change the semantics - of the URI. - - Example: `?lang=en&article=fred` → `?article=fred&lang=en` - -### `GuzzleHttp\Psr7\UriNormalizer::isEquivalent` - -`public static function isEquivalent(UriInterface $uri1, UriInterface $uri2, $normalizations = self::PRESERVING_NORMALIZATIONS): bool` - -Whether two URIs can be considered equivalent. Both URIs are normalized automatically before comparison with the given -`$normalizations` bitmask. The method also accepts relative URI references and returns true when they are equivalent. -This of course assumes they will be resolved against the same base URI. If this is not the case, determination of -equivalence or difference of relative references does not mean anything. - - -## Version Guidance - -| Version | Status | PHP Version | -|---------|----------------|------------------| -| 1.x | Security fixes | >=5.4,<8.1 | -| 2.x | Latest | ^7.2.5 \|\| ^8.0 | - - -## Security - -If you discover a security vulnerability within this package, please send an email to security@tidelift.com. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see [Security Policy](https://github.com/guzzle/psr7/security/policy) for more information. - - -## License - -Guzzle is made available under the MIT License (MIT). Please see [License File](LICENSE) for more information. - - -## For Enterprise - -Available as part of the Tidelift Subscription - -The maintainers of Guzzle and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/packagist-guzzlehttp-psr7?utm_source=packagist-guzzlehttp-psr7&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) diff --git a/lib/guzzlehttp/psr7/composer.json b/lib/guzzlehttp/psr7/composer.json deleted file mode 100644 index d51dd622e..000000000 --- a/lib/guzzlehttp/psr7/composer.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "name": "guzzlehttp/psr7", - "description": "PSR-7 message implementation that also provides common utility methods", - "keywords": [ - "request", - "response", - "message", - "stream", - "http", - "uri", - "url", - "psr-7" - ], - "license": "MIT", - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - }, - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "George Mponos", - "email": "gmponos@gmail.com", - "homepage": "https://github.com/gmponos" - }, - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/Nyholm" - }, - { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com", - "homepage": "https://github.com/sagikazarmark" - }, - { - "name": "Tobias Schultze", - "email": "webmaster@tubo-world.de", - "homepage": "https://github.com/Tobion" - }, - { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com", - "homepage": "https://sagikazarmark.hu" - } - ], - "require": { - "php": "^7.2.5 || ^8.0", - "psr/http-factory": "^1.0", - "psr/http-message": "^1.1 || ^2.0", - "ralouphie/getallheaders": "^3.0" - }, - "provide": { - "psr/http-factory-implementation": "1.0", - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", - "http-interop/http-factory-tests": "^0.9", - "phpunit/phpunit": "^8.5.29 || ^9.5.23" - }, - "suggest": { - "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Psr7\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "GuzzleHttp\\Tests\\Psr7\\": "tests/" - } - }, - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - } - }, - "config": { - "allow-plugins": { - "bamarni/composer-bin-plugin": true - }, - "preferred-install": "dist", - "sort-packages": true - } -} diff --git a/lib/guzzlehttp/psr7/src/AppendStream.php b/lib/guzzlehttp/psr7/src/AppendStream.php deleted file mode 100644 index cbcfaee65..000000000 --- a/lib/guzzlehttp/psr7/src/AppendStream.php +++ /dev/null @@ -1,248 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use Psr\Http\Message\StreamInterface; - -/** - * Reads from multiple streams, one after the other. - * - * This is a read-only stream decorator. - */ -final class AppendStream implements StreamInterface -{ - /** @var StreamInterface[] Streams being decorated */ - private $streams = []; - - /** @var bool */ - private $seekable = true; - - /** @var int */ - private $current = 0; - - /** @var int */ - private $pos = 0; - - /** - * @param StreamInterface[] $streams Streams to decorate. Each stream must - * be readable. - */ - public function __construct(array $streams = []) - { - foreach ($streams as $stream) { - $this->addStream($stream); - } - } - - public function __toString(): string - { - try { - $this->rewind(); - return $this->getContents(); - } catch (\Throwable $e) { - if (\PHP_VERSION_ID >= 70400) { - throw $e; - } - trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR); - return ''; - } - } - - /** - * Add a stream to the AppendStream - * - * @param StreamInterface $stream Stream to append. Must be readable. - * - * @throws \InvalidArgumentException if the stream is not readable - */ - public function addStream(StreamInterface $stream): void - { - if (!$stream->isReadable()) { - throw new \InvalidArgumentException('Each stream must be readable'); - } - - // The stream is only seekable if all streams are seekable - if (!$stream->isSeekable()) { - $this->seekable = false; - } - - $this->streams[] = $stream; - } - - public function getContents(): string - { - return Utils::copyToString($this); - } - - /** - * Closes each attached stream. - */ - public function close(): void - { - $this->pos = $this->current = 0; - $this->seekable = true; - - foreach ($this->streams as $stream) { - $stream->close(); - } - - $this->streams = []; - } - - /** - * Detaches each attached stream. - * - * Returns null as it's not clear which underlying stream resource to return. - */ - public function detach() - { - $this->pos = $this->current = 0; - $this->seekable = true; - - foreach ($this->streams as $stream) { - $stream->detach(); - } - - $this->streams = []; - - return null; - } - - public function tell(): int - { - return $this->pos; - } - - /** - * Tries to calculate the size by adding the size of each stream. - * - * If any of the streams do not return a valid number, then the size of the - * append stream cannot be determined and null is returned. - */ - public function getSize(): ?int - { - $size = 0; - - foreach ($this->streams as $stream) { - $s = $stream->getSize(); - if ($s === null) { - return null; - } - $size += $s; - } - - return $size; - } - - public function eof(): bool - { - return !$this->streams || - ($this->current >= count($this->streams) - 1 && - $this->streams[$this->current]->eof()); - } - - public function rewind(): void - { - $this->seek(0); - } - - /** - * Attempts to seek to the given position. Only supports SEEK_SET. - */ - public function seek($offset, $whence = SEEK_SET): void - { - if (!$this->seekable) { - throw new \RuntimeException('This AppendStream is not seekable'); - } elseif ($whence !== SEEK_SET) { - throw new \RuntimeException('The AppendStream can only seek with SEEK_SET'); - } - - $this->pos = $this->current = 0; - - // Rewind each stream - foreach ($this->streams as $i => $stream) { - try { - $stream->rewind(); - } catch (\Exception $e) { - throw new \RuntimeException('Unable to seek stream ' - . $i . ' of the AppendStream', 0, $e); - } - } - - // Seek to the actual position by reading from each stream - while ($this->pos < $offset && !$this->eof()) { - $result = $this->read(min(8096, $offset - $this->pos)); - if ($result === '') { - break; - } - } - } - - /** - * Reads from all of the appended streams until the length is met or EOF. - */ - public function read($length): string - { - $buffer = ''; - $total = count($this->streams) - 1; - $remaining = $length; - $progressToNext = false; - - while ($remaining > 0) { - // Progress to the next stream if needed. - if ($progressToNext || $this->streams[$this->current]->eof()) { - $progressToNext = false; - if ($this->current === $total) { - break; - } - $this->current++; - } - - $result = $this->streams[$this->current]->read($remaining); - - if ($result === '') { - $progressToNext = true; - continue; - } - - $buffer .= $result; - $remaining = $length - strlen($buffer); - } - - $this->pos += strlen($buffer); - - return $buffer; - } - - public function isReadable(): bool - { - return true; - } - - public function isWritable(): bool - { - return false; - } - - public function isSeekable(): bool - { - return $this->seekable; - } - - public function write($string): int - { - throw new \RuntimeException('Cannot write to an AppendStream'); - } - - /** - * {@inheritdoc} - * - * @return mixed - */ - public function getMetadata($key = null) - { - return $key ? null : []; - } -} diff --git a/lib/guzzlehttp/psr7/src/BufferStream.php b/lib/guzzlehttp/psr7/src/BufferStream.php deleted file mode 100644 index 21be8c0a9..000000000 --- a/lib/guzzlehttp/psr7/src/BufferStream.php +++ /dev/null @@ -1,149 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use Psr\Http\Message\StreamInterface; - -/** - * Provides a buffer stream that can be written to to fill a buffer, and read - * from to remove bytes from the buffer. - * - * This stream returns a "hwm" metadata value that tells upstream consumers - * what the configured high water mark of the stream is, or the maximum - * preferred size of the buffer. - */ -final class BufferStream implements StreamInterface -{ - /** @var int */ - private $hwm; - - /** @var string */ - private $buffer = ''; - - /** - * @param int $hwm High water mark, representing the preferred maximum - * buffer size. If the size of the buffer exceeds the high - * water mark, then calls to write will continue to succeed - * but will return 0 to inform writers to slow down - * until the buffer has been drained by reading from it. - */ - public function __construct(int $hwm = 16384) - { - $this->hwm = $hwm; - } - - public function __toString(): string - { - return $this->getContents(); - } - - public function getContents(): string - { - $buffer = $this->buffer; - $this->buffer = ''; - - return $buffer; - } - - public function close(): void - { - $this->buffer = ''; - } - - public function detach() - { - $this->close(); - - return null; - } - - public function getSize(): ?int - { - return strlen($this->buffer); - } - - public function isReadable(): bool - { - return true; - } - - public function isWritable(): bool - { - return true; - } - - public function isSeekable(): bool - { - return false; - } - - public function rewind(): void - { - $this->seek(0); - } - - public function seek($offset, $whence = SEEK_SET): void - { - throw new \RuntimeException('Cannot seek a BufferStream'); - } - - public function eof(): bool - { - return strlen($this->buffer) === 0; - } - - public function tell(): int - { - throw new \RuntimeException('Cannot determine the position of a BufferStream'); - } - - /** - * Reads data from the buffer. - */ - public function read($length): string - { - $currentLength = strlen($this->buffer); - - if ($length >= $currentLength) { - // No need to slice the buffer because we don't have enough data. - $result = $this->buffer; - $this->buffer = ''; - } else { - // Slice up the result to provide a subset of the buffer. - $result = substr($this->buffer, 0, $length); - $this->buffer = substr($this->buffer, $length); - } - - return $result; - } - - /** - * Writes data to the buffer. - */ - public function write($string): int - { - $this->buffer .= $string; - - if (strlen($this->buffer) >= $this->hwm) { - return 0; - } - - return strlen($string); - } - - /** - * {@inheritdoc} - * - * @return mixed - */ - public function getMetadata($key = null) - { - if ($key === 'hwm') { - return $this->hwm; - } - - return $key ? null : []; - } -} diff --git a/lib/guzzlehttp/psr7/src/CachingStream.php b/lib/guzzlehttp/psr7/src/CachingStream.php deleted file mode 100644 index f34722cff..000000000 --- a/lib/guzzlehttp/psr7/src/CachingStream.php +++ /dev/null @@ -1,153 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use Psr\Http\Message\StreamInterface; - -/** - * Stream decorator that can cache previously read bytes from a sequentially - * read stream. - */ -final class CachingStream implements StreamInterface -{ - use StreamDecoratorTrait; - - /** @var StreamInterface Stream being wrapped */ - private $remoteStream; - - /** @var int Number of bytes to skip reading due to a write on the buffer */ - private $skipReadBytes = 0; - - /** - * @var StreamInterface - */ - private $stream; - - /** - * We will treat the buffer object as the body of the stream - * - * @param StreamInterface $stream Stream to cache. The cursor is assumed to be at the beginning of the stream. - * @param StreamInterface $target Optionally specify where data is cached - */ - public function __construct( - StreamInterface $stream, - StreamInterface $target = null - ) { - $this->remoteStream = $stream; - $this->stream = $target ?: new Stream(Utils::tryFopen('php://temp', 'r+')); - } - - public function getSize(): ?int - { - $remoteSize = $this->remoteStream->getSize(); - - if (null === $remoteSize) { - return null; - } - - return max($this->stream->getSize(), $remoteSize); - } - - public function rewind(): void - { - $this->seek(0); - } - - public function seek($offset, $whence = SEEK_SET): void - { - if ($whence === SEEK_SET) { - $byte = $offset; - } elseif ($whence === SEEK_CUR) { - $byte = $offset + $this->tell(); - } elseif ($whence === SEEK_END) { - $size = $this->remoteStream->getSize(); - if ($size === null) { - $size = $this->cacheEntireStream(); - } - $byte = $size + $offset; - } else { - throw new \InvalidArgumentException('Invalid whence'); - } - - $diff = $byte - $this->stream->getSize(); - - if ($diff > 0) { - // Read the remoteStream until we have read in at least the amount - // of bytes requested, or we reach the end of the file. - while ($diff > 0 && !$this->remoteStream->eof()) { - $this->read($diff); - $diff = $byte - $this->stream->getSize(); - } - } else { - // We can just do a normal seek since we've already seen this byte. - $this->stream->seek($byte); - } - } - - public function read($length): string - { - // Perform a regular read on any previously read data from the buffer - $data = $this->stream->read($length); - $remaining = $length - strlen($data); - - // More data was requested so read from the remote stream - if ($remaining) { - // If data was written to the buffer in a position that would have - // been filled from the remote stream, then we must skip bytes on - // the remote stream to emulate overwriting bytes from that - // position. This mimics the behavior of other PHP stream wrappers. - $remoteData = $this->remoteStream->read( - $remaining + $this->skipReadBytes - ); - - if ($this->skipReadBytes) { - $len = strlen($remoteData); - $remoteData = substr($remoteData, $this->skipReadBytes); - $this->skipReadBytes = max(0, $this->skipReadBytes - $len); - } - - $data .= $remoteData; - $this->stream->write($remoteData); - } - - return $data; - } - - public function write($string): int - { - // When appending to the end of the currently read stream, you'll want - // to skip bytes from being read from the remote stream to emulate - // other stream wrappers. Basically replacing bytes of data of a fixed - // length. - $overflow = (strlen($string) + $this->tell()) - $this->remoteStream->tell(); - if ($overflow > 0) { - $this->skipReadBytes += $overflow; - } - - return $this->stream->write($string); - } - - public function eof(): bool - { - return $this->stream->eof() && $this->remoteStream->eof(); - } - - /** - * Close both the remote stream and buffer stream - */ - public function close(): void - { - $this->remoteStream->close(); - $this->stream->close(); - } - - private function cacheEntireStream(): int - { - $target = new FnStream(['write' => 'strlen']); - Utils::copyToStream($this, $target); - - return $this->tell(); - } -} diff --git a/lib/guzzlehttp/psr7/src/DroppingStream.php b/lib/guzzlehttp/psr7/src/DroppingStream.php deleted file mode 100644 index 6e3d209d0..000000000 --- a/lib/guzzlehttp/psr7/src/DroppingStream.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use Psr\Http\Message\StreamInterface; - -/** - * Stream decorator that begins dropping data once the size of the underlying - * stream becomes too full. - */ -final class DroppingStream implements StreamInterface -{ - use StreamDecoratorTrait; - - /** @var int */ - private $maxLength; - - /** @var StreamInterface */ - private $stream; - - /** - * @param StreamInterface $stream Underlying stream to decorate. - * @param int $maxLength Maximum size before dropping data. - */ - public function __construct(StreamInterface $stream, int $maxLength) - { - $this->stream = $stream; - $this->maxLength = $maxLength; - } - - public function write($string): int - { - $diff = $this->maxLength - $this->stream->getSize(); - - // Begin returning 0 when the underlying stream is too large. - if ($diff <= 0) { - return 0; - } - - // Write the stream or a subset of the stream if needed. - if (strlen($string) < $diff) { - return $this->stream->write($string); - } - - return $this->stream->write(substr($string, 0, $diff)); - } -} diff --git a/lib/guzzlehttp/psr7/src/Exception/MalformedUriException.php b/lib/guzzlehttp/psr7/src/Exception/MalformedUriException.php deleted file mode 100644 index 3a084779a..000000000 --- a/lib/guzzlehttp/psr7/src/Exception/MalformedUriException.php +++ /dev/null @@ -1,14 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7\Exception; - -use InvalidArgumentException; - -/** - * Exception thrown if a URI cannot be parsed because it's malformed. - */ -class MalformedUriException extends InvalidArgumentException -{ -} diff --git a/lib/guzzlehttp/psr7/src/FnStream.php b/lib/guzzlehttp/psr7/src/FnStream.php deleted file mode 100644 index 3a1a9512e..000000000 --- a/lib/guzzlehttp/psr7/src/FnStream.php +++ /dev/null @@ -1,180 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use Psr\Http\Message\StreamInterface; - -/** - * Compose stream implementations based on a hash of functions. - * - * Allows for easy testing and extension of a provided stream without needing - * to create a concrete class for a simple extension point. - */ -#[\AllowDynamicProperties] -final class FnStream implements StreamInterface -{ - private const SLOTS = [ - '__toString', 'close', 'detach', 'rewind', - 'getSize', 'tell', 'eof', 'isSeekable', 'seek', 'isWritable', 'write', - 'isReadable', 'read', 'getContents', 'getMetadata' - ]; - - /** @var array<string, callable> */ - private $methods; - - /** - * @param array<string, callable> $methods Hash of method name to a callable. - */ - public function __construct(array $methods) - { - $this->methods = $methods; - - // Create the functions on the class - foreach ($methods as $name => $fn) { - $this->{'_fn_' . $name} = $fn; - } - } - - /** - * Lazily determine which methods are not implemented. - * - * @throws \BadMethodCallException - */ - public function __get(string $name): void - { - throw new \BadMethodCallException(str_replace('_fn_', '', $name) - . '() is not implemented in the FnStream'); - } - - /** - * The close method is called on the underlying stream only if possible. - */ - public function __destruct() - { - if (isset($this->_fn_close)) { - call_user_func($this->_fn_close); - } - } - - /** - * An unserialize would allow the __destruct to run when the unserialized value goes out of scope. - * - * @throws \LogicException - */ - public function __wakeup(): void - { - throw new \LogicException('FnStream should never be unserialized'); - } - - /** - * Adds custom functionality to an underlying stream by intercepting - * specific method calls. - * - * @param StreamInterface $stream Stream to decorate - * @param array<string, callable> $methods Hash of method name to a closure - * - * @return FnStream - */ - public static function decorate(StreamInterface $stream, array $methods) - { - // If any of the required methods were not provided, then simply - // proxy to the decorated stream. - foreach (array_diff(self::SLOTS, array_keys($methods)) as $diff) { - /** @var callable $callable */ - $callable = [$stream, $diff]; - $methods[$diff] = $callable; - } - - return new self($methods); - } - - public function __toString(): string - { - try { - return call_user_func($this->_fn___toString); - } catch (\Throwable $e) { - if (\PHP_VERSION_ID >= 70400) { - throw $e; - } - trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR); - return ''; - } - } - - public function close(): void - { - call_user_func($this->_fn_close); - } - - public function detach() - { - return call_user_func($this->_fn_detach); - } - - public function getSize(): ?int - { - return call_user_func($this->_fn_getSize); - } - - public function tell(): int - { - return call_user_func($this->_fn_tell); - } - - public function eof(): bool - { - return call_user_func($this->_fn_eof); - } - - public function isSeekable(): bool - { - return call_user_func($this->_fn_isSeekable); - } - - public function rewind(): void - { - call_user_func($this->_fn_rewind); - } - - public function seek($offset, $whence = SEEK_SET): void - { - call_user_func($this->_fn_seek, $offset, $whence); - } - - public function isWritable(): bool - { - return call_user_func($this->_fn_isWritable); - } - - public function write($string): int - { - return call_user_func($this->_fn_write, $string); - } - - public function isReadable(): bool - { - return call_user_func($this->_fn_isReadable); - } - - public function read($length): string - { - return call_user_func($this->_fn_read, $length); - } - - public function getContents(): string - { - return call_user_func($this->_fn_getContents); - } - - /** - * {@inheritdoc} - * - * @return mixed - */ - public function getMetadata($key = null) - { - return call_user_func($this->_fn_getMetadata, $key); - } -} diff --git a/lib/guzzlehttp/psr7/src/Header.php b/lib/guzzlehttp/psr7/src/Header.php deleted file mode 100644 index 4d7005b22..000000000 --- a/lib/guzzlehttp/psr7/src/Header.php +++ /dev/null @@ -1,134 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -final class Header -{ - /** - * Parse an array of header values containing ";" separated data into an - * array of associative arrays representing the header key value pair data - * of the header. When a parameter does not contain a value, but just - * contains a key, this function will inject a key with a '' string value. - * - * @param string|array $header Header to parse into components. - */ - public static function parse($header): array - { - static $trimmed = "\"' \n\t\r"; - $params = $matches = []; - - foreach ((array) $header as $value) { - foreach (self::splitList($value) as $val) { - $part = []; - foreach (preg_split('/;(?=([^"]*"[^"]*")*[^"]*$)/', $val) as $kvp) { - if (preg_match_all('/<[^>]+>|[^=]+/', $kvp, $matches)) { - $m = $matches[0]; - if (isset($m[1])) { - $part[trim($m[0], $trimmed)] = trim($m[1], $trimmed); - } else { - $part[] = trim($m[0], $trimmed); - } - } - } - if ($part) { - $params[] = $part; - } - } - } - - return $params; - } - - /** - * Converts an array of header values that may contain comma separated - * headers into an array of headers with no comma separated values. - * - * @param string|array $header Header to normalize. - * - * @deprecated Use self::splitList() instead. - */ - public static function normalize($header): array - { - $result = []; - foreach ((array) $header as $value) { - foreach (self::splitList($value) as $parsed) { - $result[] = $parsed; - } - } - - return $result; - } - - /** - * Splits a HTTP header defined to contain a comma-separated list into - * each individual value. Empty values will be removed. - * - * Example headers include 'accept', 'cache-control' and 'if-none-match'. - * - * This method must not be used to parse headers that are not defined as - * a list, such as 'user-agent' or 'set-cookie'. - * - * @param string|string[] $values Header value as returned by MessageInterface::getHeader() - * - * @return string[] - */ - public static function splitList($values): array - { - if (!\is_array($values)) { - $values = [$values]; - } - - $result = []; - foreach ($values as $value) { - if (!\is_string($value)) { - throw new \TypeError('$header must either be a string or an array containing strings.'); - } - - $v = ''; - $isQuoted = false; - $isEscaped = false; - for ($i = 0, $max = \strlen($value); $i < $max; $i++) { - if ($isEscaped) { - $v .= $value[$i]; - $isEscaped = false; - - continue; - } - - if (!$isQuoted && $value[$i] === ',') { - $v = \trim($v); - if ($v !== '') { - $result[] = $v; - } - - $v = ''; - continue; - } - - if ($isQuoted && $value[$i] === '\\') { - $isEscaped = true; - $v .= $value[$i]; - - continue; - } - if ($value[$i] === '"') { - $isQuoted = !$isQuoted; - $v .= $value[$i]; - - continue; - } - - $v .= $value[$i]; - } - - $v = \trim($v); - if ($v !== '') { - $result[] = $v; - } - } - - return $result; - } -} diff --git a/lib/guzzlehttp/psr7/src/HttpFactory.php b/lib/guzzlehttp/psr7/src/HttpFactory.php deleted file mode 100644 index 30be222fc..000000000 --- a/lib/guzzlehttp/psr7/src/HttpFactory.php +++ /dev/null @@ -1,100 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use Psr\Http\Message\RequestFactoryInterface; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseFactoryInterface; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestFactoryInterface; -use Psr\Http\Message\ServerRequestInterface; -use Psr\Http\Message\StreamFactoryInterface; -use Psr\Http\Message\StreamInterface; -use Psr\Http\Message\UploadedFileFactoryInterface; -use Psr\Http\Message\UploadedFileInterface; -use Psr\Http\Message\UriFactoryInterface; -use Psr\Http\Message\UriInterface; - -/** - * Implements all of the PSR-17 interfaces. - * - * Note: in consuming code it is recommended to require the implemented interfaces - * and inject the instance of this class multiple times. - */ -final class HttpFactory implements - RequestFactoryInterface, - ResponseFactoryInterface, - ServerRequestFactoryInterface, - StreamFactoryInterface, - UploadedFileFactoryInterface, - UriFactoryInterface -{ - public function createUploadedFile( - StreamInterface $stream, - int $size = null, - int $error = \UPLOAD_ERR_OK, - string $clientFilename = null, - string $clientMediaType = null - ): UploadedFileInterface { - if ($size === null) { - $size = $stream->getSize(); - } - - return new UploadedFile($stream, $size, $error, $clientFilename, $clientMediaType); - } - - public function createStream(string $content = ''): StreamInterface - { - return Utils::streamFor($content); - } - - public function createStreamFromFile(string $file, string $mode = 'r'): StreamInterface - { - try { - $resource = Utils::tryFopen($file, $mode); - } catch (\RuntimeException $e) { - if ('' === $mode || false === \in_array($mode[0], ['r', 'w', 'a', 'x', 'c'], true)) { - throw new \InvalidArgumentException(sprintf('Invalid file opening mode "%s"', $mode), 0, $e); - } - - throw $e; - } - - return Utils::streamFor($resource); - } - - public function createStreamFromResource($resource): StreamInterface - { - return Utils::streamFor($resource); - } - - public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface - { - if (empty($method)) { - if (!empty($serverParams['REQUEST_METHOD'])) { - $method = $serverParams['REQUEST_METHOD']; - } else { - throw new \InvalidArgumentException('Cannot determine HTTP method'); - } - } - - return new ServerRequest($method, $uri, [], null, '1.1', $serverParams); - } - - public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface - { - return new Response($code, [], null, '1.1', $reasonPhrase); - } - - public function createRequest(string $method, $uri): RequestInterface - { - return new Request($method, $uri); - } - - public function createUri(string $uri = ''): UriInterface - { - return new Uri($uri); - } -} diff --git a/lib/guzzlehttp/psr7/src/InflateStream.php b/lib/guzzlehttp/psr7/src/InflateStream.php deleted file mode 100644 index 8e00f1c32..000000000 --- a/lib/guzzlehttp/psr7/src/InflateStream.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use Psr\Http\Message\StreamInterface; - -/** - * Uses PHP's zlib.inflate filter to inflate zlib (HTTP deflate, RFC1950) or gzipped (RFC1952) content. - * - * This stream decorator converts the provided stream to a PHP stream resource, - * then appends the zlib.inflate filter. The stream is then converted back - * to a Guzzle stream resource to be used as a Guzzle stream. - * - * @link http://tools.ietf.org/html/rfc1950 - * @link http://tools.ietf.org/html/rfc1952 - * @link http://php.net/manual/en/filters.compression.php - */ -final class InflateStream implements StreamInterface -{ - use StreamDecoratorTrait; - - /** @var StreamInterface */ - private $stream; - - public function __construct(StreamInterface $stream) - { - $resource = StreamWrapper::getResource($stream); - // Specify window=15+32, so zlib will use header detection to both gzip (with header) and zlib data - // See http://www.zlib.net/manual.html#Advanced definition of inflateInit2 - // "Add 32 to windowBits to enable zlib and gzip decoding with automatic header detection" - // Default window size is 15. - stream_filter_append($resource, 'zlib.inflate', STREAM_FILTER_READ, ['window' => 15 + 32]); - $this->stream = $stream->isSeekable() ? new Stream($resource) : new NoSeekStream(new Stream($resource)); - } -} diff --git a/lib/guzzlehttp/psr7/src/LazyOpenStream.php b/lib/guzzlehttp/psr7/src/LazyOpenStream.php deleted file mode 100644 index f6c84904e..000000000 --- a/lib/guzzlehttp/psr7/src/LazyOpenStream.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use Psr\Http\Message\StreamInterface; - -/** - * Lazily reads or writes to a file that is opened only after an IO operation - * take place on the stream. - */ -final class LazyOpenStream implements StreamInterface -{ - use StreamDecoratorTrait; - - /** @var string */ - private $filename; - - /** @var string */ - private $mode; - - /** - * @var StreamInterface - */ - private $stream; - - /** - * @param string $filename File to lazily open - * @param string $mode fopen mode to use when opening the stream - */ - public function __construct(string $filename, string $mode) - { - $this->filename = $filename; - $this->mode = $mode; - - // unsetting the property forces the first access to go through - // __get(). - unset($this->stream); - } - - /** - * Creates the underlying stream lazily when required. - */ - protected function createStream(): StreamInterface - { - return Utils::streamFor(Utils::tryFopen($this->filename, $this->mode)); - } -} diff --git a/lib/guzzlehttp/psr7/src/LimitStream.php b/lib/guzzlehttp/psr7/src/LimitStream.php deleted file mode 100644 index fb2232557..000000000 --- a/lib/guzzlehttp/psr7/src/LimitStream.php +++ /dev/null @@ -1,157 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use Psr\Http\Message\StreamInterface; - -/** - * Decorator used to return only a subset of a stream. - */ -final class LimitStream implements StreamInterface -{ - use StreamDecoratorTrait; - - /** @var int Offset to start reading from */ - private $offset; - - /** @var int Limit the number of bytes that can be read */ - private $limit; - - /** @var StreamInterface */ - private $stream; - - /** - * @param StreamInterface $stream Stream to wrap - * @param int $limit Total number of bytes to allow to be read - * from the stream. Pass -1 for no limit. - * @param int $offset Position to seek to before reading (only - * works on seekable streams). - */ - public function __construct( - StreamInterface $stream, - int $limit = -1, - int $offset = 0 - ) { - $this->stream = $stream; - $this->setLimit($limit); - $this->setOffset($offset); - } - - public function eof(): bool - { - // Always return true if the underlying stream is EOF - if ($this->stream->eof()) { - return true; - } - - // No limit and the underlying stream is not at EOF - if ($this->limit === -1) { - return false; - } - - return $this->stream->tell() >= $this->offset + $this->limit; - } - - /** - * Returns the size of the limited subset of data - */ - public function getSize(): ?int - { - if (null === ($length = $this->stream->getSize())) { - return null; - } elseif ($this->limit === -1) { - return $length - $this->offset; - } else { - return min($this->limit, $length - $this->offset); - } - } - - /** - * Allow for a bounded seek on the read limited stream - */ - public function seek($offset, $whence = SEEK_SET): void - { - if ($whence !== SEEK_SET || $offset < 0) { - throw new \RuntimeException(sprintf( - 'Cannot seek to offset %s with whence %s', - $offset, - $whence - )); - } - - $offset += $this->offset; - - if ($this->limit !== -1) { - if ($offset > $this->offset + $this->limit) { - $offset = $this->offset + $this->limit; - } - } - - $this->stream->seek($offset); - } - - /** - * Give a relative tell() - */ - public function tell(): int - { - return $this->stream->tell() - $this->offset; - } - - /** - * Set the offset to start limiting from - * - * @param int $offset Offset to seek to and begin byte limiting from - * - * @throws \RuntimeException if the stream cannot be seeked. - */ - public function setOffset(int $offset): void - { - $current = $this->stream->tell(); - - if ($current !== $offset) { - // If the stream cannot seek to the offset position, then read to it - if ($this->stream->isSeekable()) { - $this->stream->seek($offset); - } elseif ($current > $offset) { - throw new \RuntimeException("Could not seek to stream offset $offset"); - } else { - $this->stream->read($offset - $current); - } - } - - $this->offset = $offset; - } - - /** - * Set the limit of bytes that the decorator allows to be read from the - * stream. - * - * @param int $limit Number of bytes to allow to be read from the stream. - * Use -1 for no limit. - */ - public function setLimit(int $limit): void - { - $this->limit = $limit; - } - - public function read($length): string - { - if ($this->limit === -1) { - return $this->stream->read($length); - } - - // Check if the current position is less than the total allowed - // bytes + original offset - $remaining = ($this->offset + $this->limit) - $this->stream->tell(); - if ($remaining > 0) { - // Only return the amount of requested data, ensuring that the byte - // limit is not exceeded - return $this->stream->read(min($remaining, $length)); - } - - return ''; - } -} diff --git a/lib/guzzlehttp/psr7/src/Message.php b/lib/guzzlehttp/psr7/src/Message.php deleted file mode 100644 index c1e15f826..000000000 --- a/lib/guzzlehttp/psr7/src/Message.php +++ /dev/null @@ -1,246 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use Psr\Http\Message\MessageInterface; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; - -final class Message -{ - /** - * Returns the string representation of an HTTP message. - * - * @param MessageInterface $message Message to convert to a string. - */ - public static function toString(MessageInterface $message): string - { - if ($message instanceof RequestInterface) { - $msg = trim($message->getMethod() . ' ' - . $message->getRequestTarget()) - . ' HTTP/' . $message->getProtocolVersion(); - if (!$message->hasHeader('host')) { - $msg .= "\r\nHost: " . $message->getUri()->getHost(); - } - } elseif ($message instanceof ResponseInterface) { - $msg = 'HTTP/' . $message->getProtocolVersion() . ' ' - . $message->getStatusCode() . ' ' - . $message->getReasonPhrase(); - } else { - throw new \InvalidArgumentException('Unknown message type'); - } - - foreach ($message->getHeaders() as $name => $values) { - if (strtolower($name) === 'set-cookie') { - foreach ($values as $value) { - $msg .= "\r\n{$name}: " . $value; - } - } else { - $msg .= "\r\n{$name}: " . implode(', ', $values); - } - } - - return "{$msg}\r\n\r\n" . $message->getBody(); - } - - /** - * Get a short summary of the message body. - * - * Will return `null` if the response is not printable. - * - * @param MessageInterface $message The message to get the body summary - * @param int $truncateAt The maximum allowed size of the summary - */ - public static function bodySummary(MessageInterface $message, int $truncateAt = 120): ?string - { - $body = $message->getBody(); - - if (!$body->isSeekable() || !$body->isReadable()) { - return null; - } - - $size = $body->getSize(); - - if ($size === 0) { - return null; - } - - $body->rewind(); - $summary = $body->read($truncateAt); - $body->rewind(); - - if ($size > $truncateAt) { - $summary .= ' (truncated...)'; - } - - // Matches any printable character, including unicode characters: - // letters, marks, numbers, punctuation, spacing, and separators. - if (preg_match('/[^\pL\pM\pN\pP\pS\pZ\n\r\t]/u', $summary) !== 0) { - return null; - } - - return $summary; - } - - /** - * Attempts to rewind a message body and throws an exception on failure. - * - * The body of the message will only be rewound if a call to `tell()` - * returns a value other than `0`. - * - * @param MessageInterface $message Message to rewind - * - * @throws \RuntimeException - */ - public static function rewindBody(MessageInterface $message): void - { - $body = $message->getBody(); - - if ($body->tell()) { - $body->rewind(); - } - } - - /** - * Parses an HTTP message into an associative array. - * - * The array contains the "start-line" key containing the start line of - * the message, "headers" key containing an associative array of header - * array values, and a "body" key containing the body of the message. - * - * @param string $message HTTP request or response to parse. - */ - public static function parseMessage(string $message): array - { - if (!$message) { - throw new \InvalidArgumentException('Invalid message'); - } - - $message = ltrim($message, "\r\n"); - - $messageParts = preg_split("/\r?\n\r?\n/", $message, 2); - - if ($messageParts === false || count($messageParts) !== 2) { - throw new \InvalidArgumentException('Invalid message: Missing header delimiter'); - } - - [$rawHeaders, $body] = $messageParts; - $rawHeaders .= "\r\n"; // Put back the delimiter we split previously - $headerParts = preg_split("/\r?\n/", $rawHeaders, 2); - - if ($headerParts === false || count($headerParts) !== 2) { - throw new \InvalidArgumentException('Invalid message: Missing status line'); - } - - [$startLine, $rawHeaders] = $headerParts; - - if (preg_match("/(?:^HTTP\/|^[A-Z]+ \S+ HTTP\/)(\d+(?:\.\d+)?)/i", $startLine, $matches) && $matches[1] === '1.0') { - // Header folding is deprecated for HTTP/1.1, but allowed in HTTP/1.0 - $rawHeaders = preg_replace(Rfc7230::HEADER_FOLD_REGEX, ' ', $rawHeaders); - } - - /** @var array[] $headerLines */ - $count = preg_match_all(Rfc7230::HEADER_REGEX, $rawHeaders, $headerLines, PREG_SET_ORDER); - - // If these aren't the same, then one line didn't match and there's an invalid header. - if ($count !== substr_count($rawHeaders, "\n")) { - // Folding is deprecated, see https://tools.ietf.org/html/rfc7230#section-3.2.4 - if (preg_match(Rfc7230::HEADER_FOLD_REGEX, $rawHeaders)) { - throw new \InvalidArgumentException('Invalid header syntax: Obsolete line folding'); - } - - throw new \InvalidArgumentException('Invalid header syntax'); - } - - $headers = []; - - foreach ($headerLines as $headerLine) { - $headers[$headerLine[1]][] = $headerLine[2]; - } - - return [ - 'start-line' => $startLine, - 'headers' => $headers, - 'body' => $body, - ]; - } - - /** - * Constructs a URI for an HTTP request message. - * - * @param string $path Path from the start-line - * @param array $headers Array of headers (each value an array). - */ - public static function parseRequestUri(string $path, array $headers): string - { - $hostKey = array_filter(array_keys($headers), function ($k) { - // Numeric array keys are converted to int by PHP. - $k = (string) $k; - - return strtolower($k) === 'host'; - }); - - // If no host is found, then a full URI cannot be constructed. - if (!$hostKey) { - return $path; - } - - $host = $headers[reset($hostKey)][0]; - $scheme = substr($host, -4) === ':443' ? 'https' : 'http'; - - return $scheme . '://' . $host . '/' . ltrim($path, '/'); - } - - /** - * Parses a request message string into a request object. - * - * @param string $message Request message string. - */ - public static function parseRequest(string $message): RequestInterface - { - $data = self::parseMessage($message); - $matches = []; - if (!preg_match('/^[\S]+\s+([a-zA-Z]+:\/\/|\/).*/', $data['start-line'], $matches)) { - throw new \InvalidArgumentException('Invalid request string'); - } - $parts = explode(' ', $data['start-line'], 3); - $version = isset($parts[2]) ? explode('/', $parts[2])[1] : '1.1'; - - $request = new Request( - $parts[0], - $matches[1] === '/' ? self::parseRequestUri($parts[1], $data['headers']) : $parts[1], - $data['headers'], - $data['body'], - $version - ); - - return $matches[1] === '/' ? $request : $request->withRequestTarget($parts[1]); - } - - /** - * Parses a response message string into a response object. - * - * @param string $message Response message string. - */ - public static function parseResponse(string $message): ResponseInterface - { - $data = self::parseMessage($message); - // According to https://tools.ietf.org/html/rfc7230#section-3.1.2 the space - // between status-code and reason-phrase is required. But browsers accept - // responses without space and reason as well. - if (!preg_match('/^HTTP\/.* [0-9]{3}( .*|$)/', $data['start-line'])) { - throw new \InvalidArgumentException('Invalid response string: ' . $data['start-line']); - } - $parts = explode(' ', $data['start-line'], 3); - - return new Response( - (int) $parts[1], - $data['headers'], - $data['body'], - explode('/', $parts[0])[1], - $parts[2] ?? null - ); - } -} diff --git a/lib/guzzlehttp/psr7/src/MessageTrait.php b/lib/guzzlehttp/psr7/src/MessageTrait.php deleted file mode 100644 index 464bdfaa4..000000000 --- a/lib/guzzlehttp/psr7/src/MessageTrait.php +++ /dev/null @@ -1,263 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use Psr\Http\Message\MessageInterface; -use Psr\Http\Message\StreamInterface; - -/** - * Trait implementing functionality common to requests and responses. - */ -trait MessageTrait -{ - /** @var array<string, string[]> Map of all registered headers, as original name => array of values */ - private $headers = []; - - /** @var array<string, string> Map of lowercase header name => original name at registration */ - private $headerNames = []; - - /** @var string */ - private $protocol = '1.1'; - - /** @var StreamInterface|null */ - private $stream; - - public function getProtocolVersion(): string - { - return $this->protocol; - } - - public function withProtocolVersion($version): MessageInterface - { - if ($this->protocol === $version) { - return $this; - } - - $new = clone $this; - $new->protocol = $version; - return $new; - } - - public function getHeaders(): array - { - return $this->headers; - } - - public function hasHeader($header): bool - { - return isset($this->headerNames[strtolower($header)]); - } - - public function getHeader($header): array - { - $header = strtolower($header); - - if (!isset($this->headerNames[$header])) { - return []; - } - - $header = $this->headerNames[$header]; - - return $this->headers[$header]; - } - - public function getHeaderLine($header): string - { - return implode(', ', $this->getHeader($header)); - } - - public function withHeader($header, $value): MessageInterface - { - $this->assertHeader($header); - $value = $this->normalizeHeaderValue($value); - $normalized = strtolower($header); - - $new = clone $this; - if (isset($new->headerNames[$normalized])) { - unset($new->headers[$new->headerNames[$normalized]]); - } - $new->headerNames[$normalized] = $header; - $new->headers[$header] = $value; - - return $new; - } - - public function withAddedHeader($header, $value): MessageInterface - { - $this->assertHeader($header); - $value = $this->normalizeHeaderValue($value); - $normalized = strtolower($header); - - $new = clone $this; - if (isset($new->headerNames[$normalized])) { - $header = $this->headerNames[$normalized]; - $new->headers[$header] = array_merge($this->headers[$header], $value); - } else { - $new->headerNames[$normalized] = $header; - $new->headers[$header] = $value; - } - - return $new; - } - - public function withoutHeader($header): MessageInterface - { - $normalized = strtolower($header); - - if (!isset($this->headerNames[$normalized])) { - return $this; - } - - $header = $this->headerNames[$normalized]; - - $new = clone $this; - unset($new->headers[$header], $new->headerNames[$normalized]); - - return $new; - } - - public function getBody(): StreamInterface - { - if (!$this->stream) { - $this->stream = Utils::streamFor(''); - } - - return $this->stream; - } - - public function withBody(StreamInterface $body): MessageInterface - { - if ($body === $this->stream) { - return $this; - } - - $new = clone $this; - $new->stream = $body; - return $new; - } - - /** - * @param array<string|int, string|string[]> $headers - */ - private function setHeaders(array $headers): void - { - $this->headerNames = $this->headers = []; - foreach ($headers as $header => $value) { - // Numeric array keys are converted to int by PHP. - $header = (string) $header; - - $this->assertHeader($header); - $value = $this->normalizeHeaderValue($value); - $normalized = strtolower($header); - if (isset($this->headerNames[$normalized])) { - $header = $this->headerNames[$normalized]; - $this->headers[$header] = array_merge($this->headers[$header], $value); - } else { - $this->headerNames[$normalized] = $header; - $this->headers[$header] = $value; - } - } - } - - /** - * @param mixed $value - * - * @return string[] - */ - private function normalizeHeaderValue($value): array - { - if (!is_array($value)) { - return $this->trimAndValidateHeaderValues([$value]); - } - - if (count($value) === 0) { - throw new \InvalidArgumentException('Header value can not be an empty array.'); - } - - return $this->trimAndValidateHeaderValues($value); - } - - /** - * Trims whitespace from the header values. - * - * Spaces and tabs ought to be excluded by parsers when extracting the field value from a header field. - * - * header-field = field-name ":" OWS field-value OWS - * OWS = *( SP / HTAB ) - * - * @param mixed[] $values Header values - * - * @return string[] Trimmed header values - * - * @see https://tools.ietf.org/html/rfc7230#section-3.2.4 - */ - private function trimAndValidateHeaderValues(array $values): array - { - return array_map(function ($value) { - if (!is_scalar($value) && null !== $value) { - throw new \InvalidArgumentException(sprintf( - 'Header value must be scalar or null but %s provided.', - is_object($value) ? get_class($value) : gettype($value) - )); - } - - $trimmed = trim((string) $value, " \t"); - $this->assertValue($trimmed); - - return $trimmed; - }, array_values($values)); - } - - /** - * @see https://tools.ietf.org/html/rfc7230#section-3.2 - * - * @param mixed $header - */ - private function assertHeader($header): void - { - if (!is_string($header)) { - throw new \InvalidArgumentException(sprintf( - 'Header name must be a string but %s provided.', - is_object($header) ? get_class($header) : gettype($header) - )); - } - - if (! preg_match('/^[a-zA-Z0-9\'`#$%&*+.^_|~!-]+$/D', $header)) { - throw new \InvalidArgumentException( - sprintf('"%s" is not valid header name.', $header) - ); - } - } - - /** - * @see https://tools.ietf.org/html/rfc7230#section-3.2 - * - * field-value = *( field-content / obs-fold ) - * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] - * field-vchar = VCHAR / obs-text - * VCHAR = %x21-7E - * obs-text = %x80-FF - * obs-fold = CRLF 1*( SP / HTAB ) - */ - private function assertValue(string $value): void - { - // The regular expression intentionally does not support the obs-fold production, because as - // per RFC 7230#3.2.4: - // - // A sender MUST NOT generate a message that includes - // line folding (i.e., that has any field-value that contains a match to - // the obs-fold rule) unless the message is intended for packaging - // within the message/http media type. - // - // Clients must not send a request with line folding and a server sending folded headers is - // likely very rare. Line folding is a fairly obscure feature of HTTP/1.1 and thus not accepting - // folding is not likely to break any legitimate use case. - if (! preg_match('/^[\x20\x09\x21-\x7E\x80-\xFF]*$/D', $value)) { - throw new \InvalidArgumentException( - sprintf('"%s" is not valid header value.', $value) - ); - } - } -} diff --git a/lib/guzzlehttp/psr7/src/MimeType.php b/lib/guzzlehttp/psr7/src/MimeType.php deleted file mode 100644 index 0debbd18c..000000000 --- a/lib/guzzlehttp/psr7/src/MimeType.php +++ /dev/null @@ -1,1237 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -final class MimeType -{ - private const MIME_TYPES = [ - '1km' => 'application/vnd.1000minds.decision-model+xml', - '3dml' => 'text/vnd.in3d.3dml', - '3ds' => 'image/x-3ds', - '3g2' => 'video/3gpp2', - '3gp' => 'video/3gp', - '3gpp' => 'video/3gpp', - '3mf' => 'model/3mf', - '7z' => 'application/x-7z-compressed', - '7zip' => 'application/x-7z-compressed', - '123' => 'application/vnd.lotus-1-2-3', - 'aab' => 'application/x-authorware-bin', - 'aac' => 'audio/x-acc', - 'aam' => 'application/x-authorware-map', - 'aas' => 'application/x-authorware-seg', - 'abw' => 'application/x-abiword', - 'ac' => 'application/vnd.nokia.n-gage.ac+xml', - 'ac3' => 'audio/ac3', - 'acc' => 'application/vnd.americandynamics.acc', - 'ace' => 'application/x-ace-compressed', - 'acu' => 'application/vnd.acucobol', - 'acutc' => 'application/vnd.acucorp', - 'adp' => 'audio/adpcm', - 'aep' => 'application/vnd.audiograph', - 'afm' => 'application/x-font-type1', - 'afp' => 'application/vnd.ibm.modcap', - 'age' => 'application/vnd.age', - 'ahead' => 'application/vnd.ahead.space', - 'ai' => 'application/pdf', - 'aif' => 'audio/x-aiff', - 'aifc' => 'audio/x-aiff', - 'aiff' => 'audio/x-aiff', - 'air' => 'application/vnd.adobe.air-application-installer-package+zip', - 'ait' => 'application/vnd.dvb.ait', - 'ami' => 'application/vnd.amiga.ami', - 'amr' => 'audio/amr', - 'apk' => 'application/vnd.android.package-archive', - 'apng' => 'image/apng', - 'appcache' => 'text/cache-manifest', - 'application' => 'application/x-ms-application', - 'apr' => 'application/vnd.lotus-approach', - 'arc' => 'application/x-freearc', - 'arj' => 'application/x-arj', - 'asc' => 'application/pgp-signature', - 'asf' => 'video/x-ms-asf', - 'asm' => 'text/x-asm', - 'aso' => 'application/vnd.accpac.simply.aso', - 'asx' => 'video/x-ms-asf', - 'atc' => 'application/vnd.acucorp', - 'atom' => 'application/atom+xml', - 'atomcat' => 'application/atomcat+xml', - 'atomdeleted' => 'application/atomdeleted+xml', - 'atomsvc' => 'application/atomsvc+xml', - 'atx' => 'application/vnd.antix.game-component', - 'au' => 'audio/x-au', - 'avci' => 'image/avci', - 'avcs' => 'image/avcs', - 'avi' => 'video/x-msvideo', - 'avif' => 'image/avif', - 'aw' => 'application/applixware', - 'azf' => 'application/vnd.airzip.filesecure.azf', - 'azs' => 'application/vnd.airzip.filesecure.azs', - 'azv' => 'image/vnd.airzip.accelerator.azv', - 'azw' => 'application/vnd.amazon.ebook', - 'b16' => 'image/vnd.pco.b16', - 'bat' => 'application/x-msdownload', - 'bcpio' => 'application/x-bcpio', - 'bdf' => 'application/x-font-bdf', - 'bdm' => 'application/vnd.syncml.dm+wbxml', - 'bdoc' => 'application/x-bdoc', - 'bed' => 'application/vnd.realvnc.bed', - 'bh2' => 'application/vnd.fujitsu.oasysprs', - 'bin' => 'application/octet-stream', - 'blb' => 'application/x-blorb', - 'blorb' => 'application/x-blorb', - 'bmi' => 'application/vnd.bmi', - 'bmml' => 'application/vnd.balsamiq.bmml+xml', - 'bmp' => 'image/bmp', - 'book' => 'application/vnd.framemaker', - 'box' => 'application/vnd.previewsystems.box', - 'boz' => 'application/x-bzip2', - 'bpk' => 'application/octet-stream', - 'bpmn' => 'application/octet-stream', - 'bsp' => 'model/vnd.valve.source.compiled-map', - 'btif' => 'image/prs.btif', - 'buffer' => 'application/octet-stream', - 'bz' => 'application/x-bzip', - 'bz2' => 'application/x-bzip2', - 'c' => 'text/x-c', - 'c4d' => 'application/vnd.clonk.c4group', - 'c4f' => 'application/vnd.clonk.c4group', - 'c4g' => 'application/vnd.clonk.c4group', - 'c4p' => 'application/vnd.clonk.c4group', - 'c4u' => 'application/vnd.clonk.c4group', - 'c11amc' => 'application/vnd.cluetrust.cartomobile-config', - 'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg', - 'cab' => 'application/vnd.ms-cab-compressed', - 'caf' => 'audio/x-caf', - 'cap' => 'application/vnd.tcpdump.pcap', - 'car' => 'application/vnd.curl.car', - 'cat' => 'application/vnd.ms-pki.seccat', - 'cb7' => 'application/x-cbr', - 'cba' => 'application/x-cbr', - 'cbr' => 'application/x-cbr', - 'cbt' => 'application/x-cbr', - 'cbz' => 'application/x-cbr', - 'cc' => 'text/x-c', - 'cco' => 'application/x-cocoa', - 'cct' => 'application/x-director', - 'ccxml' => 'application/ccxml+xml', - 'cdbcmsg' => 'application/vnd.contact.cmsg', - 'cdf' => 'application/x-netcdf', - 'cdfx' => 'application/cdfx+xml', - 'cdkey' => 'application/vnd.mediastation.cdkey', - 'cdmia' => 'application/cdmi-capability', - 'cdmic' => 'application/cdmi-container', - 'cdmid' => 'application/cdmi-domain', - 'cdmio' => 'application/cdmi-object', - 'cdmiq' => 'application/cdmi-queue', - 'cdr' => 'application/cdr', - 'cdx' => 'chemical/x-cdx', - 'cdxml' => 'application/vnd.chemdraw+xml', - 'cdy' => 'application/vnd.cinderella', - 'cer' => 'application/pkix-cert', - 'cfs' => 'application/x-cfs-compressed', - 'cgm' => 'image/cgm', - 'chat' => 'application/x-chat', - 'chm' => 'application/vnd.ms-htmlhelp', - 'chrt' => 'application/vnd.kde.kchart', - 'cif' => 'chemical/x-cif', - 'cii' => 'application/vnd.anser-web-certificate-issue-initiation', - 'cil' => 'application/vnd.ms-artgalry', - 'cjs' => 'application/node', - 'cla' => 'application/vnd.claymore', - 'class' => 'application/octet-stream', - 'clkk' => 'application/vnd.crick.clicker.keyboard', - 'clkp' => 'application/vnd.crick.clicker.palette', - 'clkt' => 'application/vnd.crick.clicker.template', - 'clkw' => 'application/vnd.crick.clicker.wordbank', - 'clkx' => 'application/vnd.crick.clicker', - 'clp' => 'application/x-msclip', - 'cmc' => 'application/vnd.cosmocaller', - 'cmdf' => 'chemical/x-cmdf', - 'cml' => 'chemical/x-cml', - 'cmp' => 'application/vnd.yellowriver-custom-menu', - 'cmx' => 'image/x-cmx', - 'cod' => 'application/vnd.rim.cod', - 'coffee' => 'text/coffeescript', - 'com' => 'application/x-msdownload', - 'conf' => 'text/plain', - 'cpio' => 'application/x-cpio', - 'cpl' => 'application/cpl+xml', - 'cpp' => 'text/x-c', - 'cpt' => 'application/mac-compactpro', - 'crd' => 'application/x-mscardfile', - 'crl' => 'application/pkix-crl', - 'crt' => 'application/x-x509-ca-cert', - 'crx' => 'application/x-chrome-extension', - 'cryptonote' => 'application/vnd.rig.cryptonote', - 'csh' => 'application/x-csh', - 'csl' => 'application/vnd.citationstyles.style+xml', - 'csml' => 'chemical/x-csml', - 'csp' => 'application/vnd.commonspace', - 'csr' => 'application/octet-stream', - 'css' => 'text/css', - 'cst' => 'application/x-director', - 'csv' => 'text/csv', - 'cu' => 'application/cu-seeme', - 'curl' => 'text/vnd.curl', - 'cww' => 'application/prs.cww', - 'cxt' => 'application/x-director', - 'cxx' => 'text/x-c', - 'dae' => 'model/vnd.collada+xml', - 'daf' => 'application/vnd.mobius.daf', - 'dart' => 'application/vnd.dart', - 'dataless' => 'application/vnd.fdsn.seed', - 'davmount' => 'application/davmount+xml', - 'dbf' => 'application/vnd.dbf', - 'dbk' => 'application/docbook+xml', - 'dcr' => 'application/x-director', - 'dcurl' => 'text/vnd.curl.dcurl', - 'dd2' => 'application/vnd.oma.dd2+xml', - 'ddd' => 'application/vnd.fujixerox.ddd', - 'ddf' => 'application/vnd.syncml.dmddf+xml', - 'dds' => 'image/vnd.ms-dds', - 'deb' => 'application/x-debian-package', - 'def' => 'text/plain', - 'deploy' => 'application/octet-stream', - 'der' => 'application/x-x509-ca-cert', - 'dfac' => 'application/vnd.dreamfactory', - 'dgc' => 'application/x-dgc-compressed', - 'dic' => 'text/x-c', - 'dir' => 'application/x-director', - 'dis' => 'application/vnd.mobius.dis', - 'disposition-notification' => 'message/disposition-notification', - 'dist' => 'application/octet-stream', - 'distz' => 'application/octet-stream', - 'djv' => 'image/vnd.djvu', - 'djvu' => 'image/vnd.djvu', - 'dll' => 'application/octet-stream', - 'dmg' => 'application/x-apple-diskimage', - 'dmn' => 'application/octet-stream', - 'dmp' => 'application/vnd.tcpdump.pcap', - 'dms' => 'application/octet-stream', - 'dna' => 'application/vnd.dna', - 'doc' => 'application/msword', - 'docm' => 'application/vnd.ms-word.template.macroEnabled.12', - 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - 'dot' => 'application/msword', - 'dotm' => 'application/vnd.ms-word.template.macroEnabled.12', - 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', - 'dp' => 'application/vnd.osgi.dp', - 'dpg' => 'application/vnd.dpgraph', - 'dra' => 'audio/vnd.dra', - 'drle' => 'image/dicom-rle', - 'dsc' => 'text/prs.lines.tag', - 'dssc' => 'application/dssc+der', - 'dtb' => 'application/x-dtbook+xml', - 'dtd' => 'application/xml-dtd', - 'dts' => 'audio/vnd.dts', - 'dtshd' => 'audio/vnd.dts.hd', - 'dump' => 'application/octet-stream', - 'dvb' => 'video/vnd.dvb.file', - 'dvi' => 'application/x-dvi', - 'dwd' => 'application/atsc-dwd+xml', - 'dwf' => 'model/vnd.dwf', - 'dwg' => 'image/vnd.dwg', - 'dxf' => 'image/vnd.dxf', - 'dxp' => 'application/vnd.spotfire.dxp', - 'dxr' => 'application/x-director', - 'ear' => 'application/java-archive', - 'ecelp4800' => 'audio/vnd.nuera.ecelp4800', - 'ecelp7470' => 'audio/vnd.nuera.ecelp7470', - 'ecelp9600' => 'audio/vnd.nuera.ecelp9600', - 'ecma' => 'application/ecmascript', - 'edm' => 'application/vnd.novadigm.edm', - 'edx' => 'application/vnd.novadigm.edx', - 'efif' => 'application/vnd.picsel', - 'ei6' => 'application/vnd.pg.osasli', - 'elc' => 'application/octet-stream', - 'emf' => 'image/emf', - 'eml' => 'message/rfc822', - 'emma' => 'application/emma+xml', - 'emotionml' => 'application/emotionml+xml', - 'emz' => 'application/x-msmetafile', - 'eol' => 'audio/vnd.digital-winds', - 'eot' => 'application/vnd.ms-fontobject', - 'eps' => 'application/postscript', - 'epub' => 'application/epub+zip', - 'es' => 'application/ecmascript', - 'es3' => 'application/vnd.eszigno3+xml', - 'esa' => 'application/vnd.osgi.subsystem', - 'esf' => 'application/vnd.epson.esf', - 'et3' => 'application/vnd.eszigno3+xml', - 'etx' => 'text/x-setext', - 'eva' => 'application/x-eva', - 'evy' => 'application/x-envoy', - 'exe' => 'application/octet-stream', - 'exi' => 'application/exi', - 'exp' => 'application/express', - 'exr' => 'image/aces', - 'ext' => 'application/vnd.novadigm.ext', - 'ez' => 'application/andrew-inset', - 'ez2' => 'application/vnd.ezpix-album', - 'ez3' => 'application/vnd.ezpix-package', - 'f' => 'text/x-fortran', - 'f4v' => 'video/mp4', - 'f77' => 'text/x-fortran', - 'f90' => 'text/x-fortran', - 'fbs' => 'image/vnd.fastbidsheet', - 'fcdt' => 'application/vnd.adobe.formscentral.fcdt', - 'fcs' => 'application/vnd.isac.fcs', - 'fdf' => 'application/vnd.fdf', - 'fdt' => 'application/fdt+xml', - 'fe_launch' => 'application/vnd.denovo.fcselayout-link', - 'fg5' => 'application/vnd.fujitsu.oasysgp', - 'fgd' => 'application/x-director', - 'fh' => 'image/x-freehand', - 'fh4' => 'image/x-freehand', - 'fh5' => 'image/x-freehand', - 'fh7' => 'image/x-freehand', - 'fhc' => 'image/x-freehand', - 'fig' => 'application/x-xfig', - 'fits' => 'image/fits', - 'flac' => 'audio/x-flac', - 'fli' => 'video/x-fli', - 'flo' => 'application/vnd.micrografx.flo', - 'flv' => 'video/x-flv', - 'flw' => 'application/vnd.kde.kivio', - 'flx' => 'text/vnd.fmi.flexstor', - 'fly' => 'text/vnd.fly', - 'fm' => 'application/vnd.framemaker', - 'fnc' => 'application/vnd.frogans.fnc', - 'fo' => 'application/vnd.software602.filler.form+xml', - 'for' => 'text/x-fortran', - 'fpx' => 'image/vnd.fpx', - 'frame' => 'application/vnd.framemaker', - 'fsc' => 'application/vnd.fsc.weblaunch', - 'fst' => 'image/vnd.fst', - 'ftc' => 'application/vnd.fluxtime.clip', - 'fti' => 'application/vnd.anser-web-funds-transfer-initiation', - 'fvt' => 'video/vnd.fvt', - 'fxp' => 'application/vnd.adobe.fxp', - 'fxpl' => 'application/vnd.adobe.fxp', - 'fzs' => 'application/vnd.fuzzysheet', - 'g2w' => 'application/vnd.geoplan', - 'g3' => 'image/g3fax', - 'g3w' => 'application/vnd.geospace', - 'gac' => 'application/vnd.groove-account', - 'gam' => 'application/x-tads', - 'gbr' => 'application/rpki-ghostbusters', - 'gca' => 'application/x-gca-compressed', - 'gdl' => 'model/vnd.gdl', - 'gdoc' => 'application/vnd.google-apps.document', - 'ged' => 'text/vnd.familysearch.gedcom', - 'geo' => 'application/vnd.dynageo', - 'geojson' => 'application/geo+json', - 'gex' => 'application/vnd.geometry-explorer', - 'ggb' => 'application/vnd.geogebra.file', - 'ggt' => 'application/vnd.geogebra.tool', - 'ghf' => 'application/vnd.groove-help', - 'gif' => 'image/gif', - 'gim' => 'application/vnd.groove-identity-message', - 'glb' => 'model/gltf-binary', - 'gltf' => 'model/gltf+json', - 'gml' => 'application/gml+xml', - 'gmx' => 'application/vnd.gmx', - 'gnumeric' => 'application/x-gnumeric', - 'gpg' => 'application/gpg-keys', - 'gph' => 'application/vnd.flographit', - 'gpx' => 'application/gpx+xml', - 'gqf' => 'application/vnd.grafeq', - 'gqs' => 'application/vnd.grafeq', - 'gram' => 'application/srgs', - 'gramps' => 'application/x-gramps-xml', - 'gre' => 'application/vnd.geometry-explorer', - 'grv' => 'application/vnd.groove-injector', - 'grxml' => 'application/srgs+xml', - 'gsf' => 'application/x-font-ghostscript', - 'gsheet' => 'application/vnd.google-apps.spreadsheet', - 'gslides' => 'application/vnd.google-apps.presentation', - 'gtar' => 'application/x-gtar', - 'gtm' => 'application/vnd.groove-tool-message', - 'gtw' => 'model/vnd.gtw', - 'gv' => 'text/vnd.graphviz', - 'gxf' => 'application/gxf', - 'gxt' => 'application/vnd.geonext', - 'gz' => 'application/gzip', - 'gzip' => 'application/gzip', - 'h' => 'text/x-c', - 'h261' => 'video/h261', - 'h263' => 'video/h263', - 'h264' => 'video/h264', - 'hal' => 'application/vnd.hal+xml', - 'hbci' => 'application/vnd.hbci', - 'hbs' => 'text/x-handlebars-template', - 'hdd' => 'application/x-virtualbox-hdd', - 'hdf' => 'application/x-hdf', - 'heic' => 'image/heic', - 'heics' => 'image/heic-sequence', - 'heif' => 'image/heif', - 'heifs' => 'image/heif-sequence', - 'hej2' => 'image/hej2k', - 'held' => 'application/atsc-held+xml', - 'hh' => 'text/x-c', - 'hjson' => 'application/hjson', - 'hlp' => 'application/winhlp', - 'hpgl' => 'application/vnd.hp-hpgl', - 'hpid' => 'application/vnd.hp-hpid', - 'hps' => 'application/vnd.hp-hps', - 'hqx' => 'application/mac-binhex40', - 'hsj2' => 'image/hsj2', - 'htc' => 'text/x-component', - 'htke' => 'application/vnd.kenameaapp', - 'htm' => 'text/html', - 'html' => 'text/html', - 'hvd' => 'application/vnd.yamaha.hv-dic', - 'hvp' => 'application/vnd.yamaha.hv-voice', - 'hvs' => 'application/vnd.yamaha.hv-script', - 'i2g' => 'application/vnd.intergeo', - 'icc' => 'application/vnd.iccprofile', - 'ice' => 'x-conference/x-cooltalk', - 'icm' => 'application/vnd.iccprofile', - 'ico' => 'image/x-icon', - 'ics' => 'text/calendar', - 'ief' => 'image/ief', - 'ifb' => 'text/calendar', - 'ifm' => 'application/vnd.shana.informed.formdata', - 'iges' => 'model/iges', - 'igl' => 'application/vnd.igloader', - 'igm' => 'application/vnd.insors.igm', - 'igs' => 'model/iges', - 'igx' => 'application/vnd.micrografx.igx', - 'iif' => 'application/vnd.shana.informed.interchange', - 'img' => 'application/octet-stream', - 'imp' => 'application/vnd.accpac.simply.imp', - 'ims' => 'application/vnd.ms-ims', - 'in' => 'text/plain', - 'ini' => 'text/plain', - 'ink' => 'application/inkml+xml', - 'inkml' => 'application/inkml+xml', - 'install' => 'application/x-install-instructions', - 'iota' => 'application/vnd.astraea-software.iota', - 'ipfix' => 'application/ipfix', - 'ipk' => 'application/vnd.shana.informed.package', - 'irm' => 'application/vnd.ibm.rights-management', - 'irp' => 'application/vnd.irepository.package+xml', - 'iso' => 'application/x-iso9660-image', - 'itp' => 'application/vnd.shana.informed.formtemplate', - 'its' => 'application/its+xml', - 'ivp' => 'application/vnd.immervision-ivp', - 'ivu' => 'application/vnd.immervision-ivu', - 'jad' => 'text/vnd.sun.j2me.app-descriptor', - 'jade' => 'text/jade', - 'jam' => 'application/vnd.jam', - 'jar' => 'application/java-archive', - 'jardiff' => 'application/x-java-archive-diff', - 'java' => 'text/x-java-source', - 'jhc' => 'image/jphc', - 'jisp' => 'application/vnd.jisp', - 'jls' => 'image/jls', - 'jlt' => 'application/vnd.hp-jlyt', - 'jng' => 'image/x-jng', - 'jnlp' => 'application/x-java-jnlp-file', - 'joda' => 'application/vnd.joost.joda-archive', - 'jp2' => 'image/jp2', - 'jpe' => 'image/jpeg', - 'jpeg' => 'image/jpeg', - 'jpf' => 'image/jpx', - 'jpg' => 'image/jpeg', - 'jpg2' => 'image/jp2', - 'jpgm' => 'video/jpm', - 'jpgv' => 'video/jpeg', - 'jph' => 'image/jph', - 'jpm' => 'video/jpm', - 'jpx' => 'image/jpx', - 'js' => 'application/javascript', - 'json' => 'application/json', - 'json5' => 'application/json5', - 'jsonld' => 'application/ld+json', - 'jsonml' => 'application/jsonml+json', - 'jsx' => 'text/jsx', - 'jxr' => 'image/jxr', - 'jxra' => 'image/jxra', - 'jxrs' => 'image/jxrs', - 'jxs' => 'image/jxs', - 'jxsc' => 'image/jxsc', - 'jxsi' => 'image/jxsi', - 'jxss' => 'image/jxss', - 'kar' => 'audio/midi', - 'karbon' => 'application/vnd.kde.karbon', - 'kdb' => 'application/octet-stream', - 'kdbx' => 'application/x-keepass2', - 'key' => 'application/x-iwork-keynote-sffkey', - 'kfo' => 'application/vnd.kde.kformula', - 'kia' => 'application/vnd.kidspiration', - 'kml' => 'application/vnd.google-earth.kml+xml', - 'kmz' => 'application/vnd.google-earth.kmz', - 'kne' => 'application/vnd.kinar', - 'knp' => 'application/vnd.kinar', - 'kon' => 'application/vnd.kde.kontour', - 'kpr' => 'application/vnd.kde.kpresenter', - 'kpt' => 'application/vnd.kde.kpresenter', - 'kpxx' => 'application/vnd.ds-keypoint', - 'ksp' => 'application/vnd.kde.kspread', - 'ktr' => 'application/vnd.kahootz', - 'ktx' => 'image/ktx', - 'ktx2' => 'image/ktx2', - 'ktz' => 'application/vnd.kahootz', - 'kwd' => 'application/vnd.kde.kword', - 'kwt' => 'application/vnd.kde.kword', - 'lasxml' => 'application/vnd.las.las+xml', - 'latex' => 'application/x-latex', - 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop', - 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml', - 'les' => 'application/vnd.hhe.lesson-player', - 'less' => 'text/less', - 'lgr' => 'application/lgr+xml', - 'lha' => 'application/octet-stream', - 'link66' => 'application/vnd.route66.link66+xml', - 'list' => 'text/plain', - 'list3820' => 'application/vnd.ibm.modcap', - 'listafp' => 'application/vnd.ibm.modcap', - 'litcoffee' => 'text/coffeescript', - 'lnk' => 'application/x-ms-shortcut', - 'log' => 'text/plain', - 'lostxml' => 'application/lost+xml', - 'lrf' => 'application/octet-stream', - 'lrm' => 'application/vnd.ms-lrm', - 'ltf' => 'application/vnd.frogans.ltf', - 'lua' => 'text/x-lua', - 'luac' => 'application/x-lua-bytecode', - 'lvp' => 'audio/vnd.lucent.voice', - 'lwp' => 'application/vnd.lotus-wordpro', - 'lzh' => 'application/octet-stream', - 'm1v' => 'video/mpeg', - 'm2a' => 'audio/mpeg', - 'm2v' => 'video/mpeg', - 'm3a' => 'audio/mpeg', - 'm3u' => 'text/plain', - 'm3u8' => 'application/vnd.apple.mpegurl', - 'm4a' => 'audio/x-m4a', - 'm4p' => 'application/mp4', - 'm4s' => 'video/iso.segment', - 'm4u' => 'application/vnd.mpegurl', - 'm4v' => 'video/x-m4v', - 'm13' => 'application/x-msmediaview', - 'm14' => 'application/x-msmediaview', - 'm21' => 'application/mp21', - 'ma' => 'application/mathematica', - 'mads' => 'application/mads+xml', - 'maei' => 'application/mmt-aei+xml', - 'mag' => 'application/vnd.ecowin.chart', - 'maker' => 'application/vnd.framemaker', - 'man' => 'text/troff', - 'manifest' => 'text/cache-manifest', - 'map' => 'application/json', - 'mar' => 'application/octet-stream', - 'markdown' => 'text/markdown', - 'mathml' => 'application/mathml+xml', - 'mb' => 'application/mathematica', - 'mbk' => 'application/vnd.mobius.mbk', - 'mbox' => 'application/mbox', - 'mc1' => 'application/vnd.medcalcdata', - 'mcd' => 'application/vnd.mcd', - 'mcurl' => 'text/vnd.curl.mcurl', - 'md' => 'text/markdown', - 'mdb' => 'application/x-msaccess', - 'mdi' => 'image/vnd.ms-modi', - 'mdx' => 'text/mdx', - 'me' => 'text/troff', - 'mesh' => 'model/mesh', - 'meta4' => 'application/metalink4+xml', - 'metalink' => 'application/metalink+xml', - 'mets' => 'application/mets+xml', - 'mfm' => 'application/vnd.mfmp', - 'mft' => 'application/rpki-manifest', - 'mgp' => 'application/vnd.osgeo.mapguide.package', - 'mgz' => 'application/vnd.proteus.magazine', - 'mid' => 'audio/midi', - 'midi' => 'audio/midi', - 'mie' => 'application/x-mie', - 'mif' => 'application/vnd.mif', - 'mime' => 'message/rfc822', - 'mj2' => 'video/mj2', - 'mjp2' => 'video/mj2', - 'mjs' => 'application/javascript', - 'mk3d' => 'video/x-matroska', - 'mka' => 'audio/x-matroska', - 'mkd' => 'text/x-markdown', - 'mks' => 'video/x-matroska', - 'mkv' => 'video/x-matroska', - 'mlp' => 'application/vnd.dolby.mlp', - 'mmd' => 'application/vnd.chipnuts.karaoke-mmd', - 'mmf' => 'application/vnd.smaf', - 'mml' => 'text/mathml', - 'mmr' => 'image/vnd.fujixerox.edmics-mmr', - 'mng' => 'video/x-mng', - 'mny' => 'application/x-msmoney', - 'mobi' => 'application/x-mobipocket-ebook', - 'mods' => 'application/mods+xml', - 'mov' => 'video/quicktime', - 'movie' => 'video/x-sgi-movie', - 'mp2' => 'audio/mpeg', - 'mp2a' => 'audio/mpeg', - 'mp3' => 'audio/mpeg', - 'mp4' => 'video/mp4', - 'mp4a' => 'audio/mp4', - 'mp4s' => 'application/mp4', - 'mp4v' => 'video/mp4', - 'mp21' => 'application/mp21', - 'mpc' => 'application/vnd.mophun.certificate', - 'mpd' => 'application/dash+xml', - 'mpe' => 'video/mpeg', - 'mpeg' => 'video/mpeg', - 'mpf' => 'application/media-policy-dataset+xml', - 'mpg' => 'video/mpeg', - 'mpg4' => 'video/mp4', - 'mpga' => 'audio/mpeg', - 'mpkg' => 'application/vnd.apple.installer+xml', - 'mpm' => 'application/vnd.blueice.multipass', - 'mpn' => 'application/vnd.mophun.application', - 'mpp' => 'application/vnd.ms-project', - 'mpt' => 'application/vnd.ms-project', - 'mpy' => 'application/vnd.ibm.minipay', - 'mqy' => 'application/vnd.mobius.mqy', - 'mrc' => 'application/marc', - 'mrcx' => 'application/marcxml+xml', - 'ms' => 'text/troff', - 'mscml' => 'application/mediaservercontrol+xml', - 'mseed' => 'application/vnd.fdsn.mseed', - 'mseq' => 'application/vnd.mseq', - 'msf' => 'application/vnd.epson.msf', - 'msg' => 'application/vnd.ms-outlook', - 'msh' => 'model/mesh', - 'msi' => 'application/x-msdownload', - 'msl' => 'application/vnd.mobius.msl', - 'msm' => 'application/octet-stream', - 'msp' => 'application/octet-stream', - 'msty' => 'application/vnd.muvee.style', - 'mtl' => 'model/mtl', - 'mts' => 'model/vnd.mts', - 'mus' => 'application/vnd.musician', - 'musd' => 'application/mmt-usd+xml', - 'musicxml' => 'application/vnd.recordare.musicxml+xml', - 'mvb' => 'application/x-msmediaview', - 'mvt' => 'application/vnd.mapbox-vector-tile', - 'mwf' => 'application/vnd.mfer', - 'mxf' => 'application/mxf', - 'mxl' => 'application/vnd.recordare.musicxml', - 'mxmf' => 'audio/mobile-xmf', - 'mxml' => 'application/xv+xml', - 'mxs' => 'application/vnd.triscape.mxs', - 'mxu' => 'video/vnd.mpegurl', - 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install', - 'n3' => 'text/n3', - 'nb' => 'application/mathematica', - 'nbp' => 'application/vnd.wolfram.player', - 'nc' => 'application/x-netcdf', - 'ncx' => 'application/x-dtbncx+xml', - 'nfo' => 'text/x-nfo', - 'ngdat' => 'application/vnd.nokia.n-gage.data', - 'nitf' => 'application/vnd.nitf', - 'nlu' => 'application/vnd.neurolanguage.nlu', - 'nml' => 'application/vnd.enliven', - 'nnd' => 'application/vnd.noblenet-directory', - 'nns' => 'application/vnd.noblenet-sealer', - 'nnw' => 'application/vnd.noblenet-web', - 'npx' => 'image/vnd.net-fpx', - 'nq' => 'application/n-quads', - 'nsc' => 'application/x-conference', - 'nsf' => 'application/vnd.lotus-notes', - 'nt' => 'application/n-triples', - 'ntf' => 'application/vnd.nitf', - 'numbers' => 'application/x-iwork-numbers-sffnumbers', - 'nzb' => 'application/x-nzb', - 'oa2' => 'application/vnd.fujitsu.oasys2', - 'oa3' => 'application/vnd.fujitsu.oasys3', - 'oas' => 'application/vnd.fujitsu.oasys', - 'obd' => 'application/x-msbinder', - 'obgx' => 'application/vnd.openblox.game+xml', - 'obj' => 'model/obj', - 'oda' => 'application/oda', - 'odb' => 'application/vnd.oasis.opendocument.database', - 'odc' => 'application/vnd.oasis.opendocument.chart', - 'odf' => 'application/vnd.oasis.opendocument.formula', - 'odft' => 'application/vnd.oasis.opendocument.formula-template', - 'odg' => 'application/vnd.oasis.opendocument.graphics', - 'odi' => 'application/vnd.oasis.opendocument.image', - 'odm' => 'application/vnd.oasis.opendocument.text-master', - 'odp' => 'application/vnd.oasis.opendocument.presentation', - 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', - 'odt' => 'application/vnd.oasis.opendocument.text', - 'oga' => 'audio/ogg', - 'ogex' => 'model/vnd.opengex', - 'ogg' => 'audio/ogg', - 'ogv' => 'video/ogg', - 'ogx' => 'application/ogg', - 'omdoc' => 'application/omdoc+xml', - 'onepkg' => 'application/onenote', - 'onetmp' => 'application/onenote', - 'onetoc' => 'application/onenote', - 'onetoc2' => 'application/onenote', - 'opf' => 'application/oebps-package+xml', - 'opml' => 'text/x-opml', - 'oprc' => 'application/vnd.palm', - 'opus' => 'audio/ogg', - 'org' => 'text/x-org', - 'osf' => 'application/vnd.yamaha.openscoreformat', - 'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml', - 'osm' => 'application/vnd.openstreetmap.data+xml', - 'otc' => 'application/vnd.oasis.opendocument.chart-template', - 'otf' => 'font/otf', - 'otg' => 'application/vnd.oasis.opendocument.graphics-template', - 'oth' => 'application/vnd.oasis.opendocument.text-web', - 'oti' => 'application/vnd.oasis.opendocument.image-template', - 'otp' => 'application/vnd.oasis.opendocument.presentation-template', - 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template', - 'ott' => 'application/vnd.oasis.opendocument.text-template', - 'ova' => 'application/x-virtualbox-ova', - 'ovf' => 'application/x-virtualbox-ovf', - 'owl' => 'application/rdf+xml', - 'oxps' => 'application/oxps', - 'oxt' => 'application/vnd.openofficeorg.extension', - 'p' => 'text/x-pascal', - 'p7a' => 'application/x-pkcs7-signature', - 'p7b' => 'application/x-pkcs7-certificates', - 'p7c' => 'application/pkcs7-mime', - 'p7m' => 'application/pkcs7-mime', - 'p7r' => 'application/x-pkcs7-certreqresp', - 'p7s' => 'application/pkcs7-signature', - 'p8' => 'application/pkcs8', - 'p10' => 'application/x-pkcs10', - 'p12' => 'application/x-pkcs12', - 'pac' => 'application/x-ns-proxy-autoconfig', - 'pages' => 'application/x-iwork-pages-sffpages', - 'pas' => 'text/x-pascal', - 'paw' => 'application/vnd.pawaafile', - 'pbd' => 'application/vnd.powerbuilder6', - 'pbm' => 'image/x-portable-bitmap', - 'pcap' => 'application/vnd.tcpdump.pcap', - 'pcf' => 'application/x-font-pcf', - 'pcl' => 'application/vnd.hp-pcl', - 'pclxl' => 'application/vnd.hp-pclxl', - 'pct' => 'image/x-pict', - 'pcurl' => 'application/vnd.curl.pcurl', - 'pcx' => 'image/x-pcx', - 'pdb' => 'application/x-pilot', - 'pde' => 'text/x-processing', - 'pdf' => 'application/pdf', - 'pem' => 'application/x-x509-user-cert', - 'pfa' => 'application/x-font-type1', - 'pfb' => 'application/x-font-type1', - 'pfm' => 'application/x-font-type1', - 'pfr' => 'application/font-tdpfr', - 'pfx' => 'application/x-pkcs12', - 'pgm' => 'image/x-portable-graymap', - 'pgn' => 'application/x-chess-pgn', - 'pgp' => 'application/pgp', - 'phar' => 'application/octet-stream', - 'php' => 'application/x-httpd-php', - 'php3' => 'application/x-httpd-php', - 'php4' => 'application/x-httpd-php', - 'phps' => 'application/x-httpd-php-source', - 'phtml' => 'application/x-httpd-php', - 'pic' => 'image/x-pict', - 'pkg' => 'application/octet-stream', - 'pki' => 'application/pkixcmp', - 'pkipath' => 'application/pkix-pkipath', - 'pkpass' => 'application/vnd.apple.pkpass', - 'pl' => 'application/x-perl', - 'plb' => 'application/vnd.3gpp.pic-bw-large', - 'plc' => 'application/vnd.mobius.plc', - 'plf' => 'application/vnd.pocketlearn', - 'pls' => 'application/pls+xml', - 'pm' => 'application/x-perl', - 'pml' => 'application/vnd.ctc-posml', - 'png' => 'image/png', - 'pnm' => 'image/x-portable-anymap', - 'portpkg' => 'application/vnd.macports.portpkg', - 'pot' => 'application/vnd.ms-powerpoint', - 'potm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', - 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', - 'ppa' => 'application/vnd.ms-powerpoint', - 'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12', - 'ppd' => 'application/vnd.cups-ppd', - 'ppm' => 'image/x-portable-pixmap', - 'pps' => 'application/vnd.ms-powerpoint', - 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12', - 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', - 'ppt' => 'application/powerpoint', - 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', - 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', - 'pqa' => 'application/vnd.palm', - 'prc' => 'model/prc', - 'pre' => 'application/vnd.lotus-freelance', - 'prf' => 'application/pics-rules', - 'provx' => 'application/provenance+xml', - 'ps' => 'application/postscript', - 'psb' => 'application/vnd.3gpp.pic-bw-small', - 'psd' => 'application/x-photoshop', - 'psf' => 'application/x-font-linux-psf', - 'pskcxml' => 'application/pskc+xml', - 'pti' => 'image/prs.pti', - 'ptid' => 'application/vnd.pvi.ptid1', - 'pub' => 'application/x-mspublisher', - 'pvb' => 'application/vnd.3gpp.pic-bw-var', - 'pwn' => 'application/vnd.3m.post-it-notes', - 'pya' => 'audio/vnd.ms-playready.media.pya', - 'pyv' => 'video/vnd.ms-playready.media.pyv', - 'qam' => 'application/vnd.epson.quickanime', - 'qbo' => 'application/vnd.intu.qbo', - 'qfx' => 'application/vnd.intu.qfx', - 'qps' => 'application/vnd.publishare-delta-tree', - 'qt' => 'video/quicktime', - 'qwd' => 'application/vnd.quark.quarkxpress', - 'qwt' => 'application/vnd.quark.quarkxpress', - 'qxb' => 'application/vnd.quark.quarkxpress', - 'qxd' => 'application/vnd.quark.quarkxpress', - 'qxl' => 'application/vnd.quark.quarkxpress', - 'qxt' => 'application/vnd.quark.quarkxpress', - 'ra' => 'audio/x-realaudio', - 'ram' => 'audio/x-pn-realaudio', - 'raml' => 'application/raml+yaml', - 'rapd' => 'application/route-apd+xml', - 'rar' => 'application/x-rar', - 'ras' => 'image/x-cmu-raster', - 'rcprofile' => 'application/vnd.ipunplugged.rcprofile', - 'rdf' => 'application/rdf+xml', - 'rdz' => 'application/vnd.data-vision.rdz', - 'relo' => 'application/p2p-overlay+xml', - 'rep' => 'application/vnd.businessobjects', - 'res' => 'application/x-dtbresource+xml', - 'rgb' => 'image/x-rgb', - 'rif' => 'application/reginfo+xml', - 'rip' => 'audio/vnd.rip', - 'ris' => 'application/x-research-info-systems', - 'rl' => 'application/resource-lists+xml', - 'rlc' => 'image/vnd.fujixerox.edmics-rlc', - 'rld' => 'application/resource-lists-diff+xml', - 'rm' => 'audio/x-pn-realaudio', - 'rmi' => 'audio/midi', - 'rmp' => 'audio/x-pn-realaudio-plugin', - 'rms' => 'application/vnd.jcp.javame.midlet-rms', - 'rmvb' => 'application/vnd.rn-realmedia-vbr', - 'rnc' => 'application/relax-ng-compact-syntax', - 'rng' => 'application/xml', - 'roa' => 'application/rpki-roa', - 'roff' => 'text/troff', - 'rp9' => 'application/vnd.cloanto.rp9', - 'rpm' => 'audio/x-pn-realaudio-plugin', - 'rpss' => 'application/vnd.nokia.radio-presets', - 'rpst' => 'application/vnd.nokia.radio-preset', - 'rq' => 'application/sparql-query', - 'rs' => 'application/rls-services+xml', - 'rsa' => 'application/x-pkcs7', - 'rsat' => 'application/atsc-rsat+xml', - 'rsd' => 'application/rsd+xml', - 'rsheet' => 'application/urc-ressheet+xml', - 'rss' => 'application/rss+xml', - 'rtf' => 'text/rtf', - 'rtx' => 'text/richtext', - 'run' => 'application/x-makeself', - 'rusd' => 'application/route-usd+xml', - 'rv' => 'video/vnd.rn-realvideo', - 's' => 'text/x-asm', - 's3m' => 'audio/s3m', - 'saf' => 'application/vnd.yamaha.smaf-audio', - 'sass' => 'text/x-sass', - 'sbml' => 'application/sbml+xml', - 'sc' => 'application/vnd.ibm.secure-container', - 'scd' => 'application/x-msschedule', - 'scm' => 'application/vnd.lotus-screencam', - 'scq' => 'application/scvp-cv-request', - 'scs' => 'application/scvp-cv-response', - 'scss' => 'text/x-scss', - 'scurl' => 'text/vnd.curl.scurl', - 'sda' => 'application/vnd.stardivision.draw', - 'sdc' => 'application/vnd.stardivision.calc', - 'sdd' => 'application/vnd.stardivision.impress', - 'sdkd' => 'application/vnd.solent.sdkm+xml', - 'sdkm' => 'application/vnd.solent.sdkm+xml', - 'sdp' => 'application/sdp', - 'sdw' => 'application/vnd.stardivision.writer', - 'sea' => 'application/octet-stream', - 'see' => 'application/vnd.seemail', - 'seed' => 'application/vnd.fdsn.seed', - 'sema' => 'application/vnd.sema', - 'semd' => 'application/vnd.semd', - 'semf' => 'application/vnd.semf', - 'senmlx' => 'application/senml+xml', - 'sensmlx' => 'application/sensml+xml', - 'ser' => 'application/java-serialized-object', - 'setpay' => 'application/set-payment-initiation', - 'setreg' => 'application/set-registration-initiation', - 'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data', - 'sfs' => 'application/vnd.spotfire.sfs', - 'sfv' => 'text/x-sfv', - 'sgi' => 'image/sgi', - 'sgl' => 'application/vnd.stardivision.writer-global', - 'sgm' => 'text/sgml', - 'sgml' => 'text/sgml', - 'sh' => 'application/x-sh', - 'shar' => 'application/x-shar', - 'shex' => 'text/shex', - 'shf' => 'application/shf+xml', - 'shtml' => 'text/html', - 'sid' => 'image/x-mrsid-image', - 'sieve' => 'application/sieve', - 'sig' => 'application/pgp-signature', - 'sil' => 'audio/silk', - 'silo' => 'model/mesh', - 'sis' => 'application/vnd.symbian.install', - 'sisx' => 'application/vnd.symbian.install', - 'sit' => 'application/x-stuffit', - 'sitx' => 'application/x-stuffitx', - 'siv' => 'application/sieve', - 'skd' => 'application/vnd.koan', - 'skm' => 'application/vnd.koan', - 'skp' => 'application/vnd.koan', - 'skt' => 'application/vnd.koan', - 'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12', - 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide', - 'slim' => 'text/slim', - 'slm' => 'text/slim', - 'sls' => 'application/route-s-tsid+xml', - 'slt' => 'application/vnd.epson.salt', - 'sm' => 'application/vnd.stepmania.stepchart', - 'smf' => 'application/vnd.stardivision.math', - 'smi' => 'application/smil', - 'smil' => 'application/smil', - 'smv' => 'video/x-smv', - 'smzip' => 'application/vnd.stepmania.package', - 'snd' => 'audio/basic', - 'snf' => 'application/x-font-snf', - 'so' => 'application/octet-stream', - 'spc' => 'application/x-pkcs7-certificates', - 'spdx' => 'text/spdx', - 'spf' => 'application/vnd.yamaha.smaf-phrase', - 'spl' => 'application/x-futuresplash', - 'spot' => 'text/vnd.in3d.spot', - 'spp' => 'application/scvp-vp-response', - 'spq' => 'application/scvp-vp-request', - 'spx' => 'audio/ogg', - 'sql' => 'application/x-sql', - 'src' => 'application/x-wais-source', - 'srt' => 'application/x-subrip', - 'sru' => 'application/sru+xml', - 'srx' => 'application/sparql-results+xml', - 'ssdl' => 'application/ssdl+xml', - 'sse' => 'application/vnd.kodak-descriptor', - 'ssf' => 'application/vnd.epson.ssf', - 'ssml' => 'application/ssml+xml', - 'sst' => 'application/octet-stream', - 'st' => 'application/vnd.sailingtracker.track', - 'stc' => 'application/vnd.sun.xml.calc.template', - 'std' => 'application/vnd.sun.xml.draw.template', - 'stf' => 'application/vnd.wt.stf', - 'sti' => 'application/vnd.sun.xml.impress.template', - 'stk' => 'application/hyperstudio', - 'stl' => 'model/stl', - 'stpx' => 'model/step+xml', - 'stpxz' => 'model/step-xml+zip', - 'stpz' => 'model/step+zip', - 'str' => 'application/vnd.pg.format', - 'stw' => 'application/vnd.sun.xml.writer.template', - 'styl' => 'text/stylus', - 'stylus' => 'text/stylus', - 'sub' => 'text/vnd.dvb.subtitle', - 'sus' => 'application/vnd.sus-calendar', - 'susp' => 'application/vnd.sus-calendar', - 'sv4cpio' => 'application/x-sv4cpio', - 'sv4crc' => 'application/x-sv4crc', - 'svc' => 'application/vnd.dvb.service', - 'svd' => 'application/vnd.svd', - 'svg' => 'image/svg+xml', - 'svgz' => 'image/svg+xml', - 'swa' => 'application/x-director', - 'swf' => 'application/x-shockwave-flash', - 'swi' => 'application/vnd.aristanetworks.swi', - 'swidtag' => 'application/swid+xml', - 'sxc' => 'application/vnd.sun.xml.calc', - 'sxd' => 'application/vnd.sun.xml.draw', - 'sxg' => 'application/vnd.sun.xml.writer.global', - 'sxi' => 'application/vnd.sun.xml.impress', - 'sxm' => 'application/vnd.sun.xml.math', - 'sxw' => 'application/vnd.sun.xml.writer', - 't' => 'text/troff', - 't3' => 'application/x-t3vm-image', - 't38' => 'image/t38', - 'taglet' => 'application/vnd.mynfc', - 'tao' => 'application/vnd.tao.intent-module-archive', - 'tap' => 'image/vnd.tencent.tap', - 'tar' => 'application/x-tar', - 'tcap' => 'application/vnd.3gpp2.tcap', - 'tcl' => 'application/x-tcl', - 'td' => 'application/urc-targetdesc+xml', - 'teacher' => 'application/vnd.smart.teacher', - 'tei' => 'application/tei+xml', - 'teicorpus' => 'application/tei+xml', - 'tex' => 'application/x-tex', - 'texi' => 'application/x-texinfo', - 'texinfo' => 'application/x-texinfo', - 'text' => 'text/plain', - 'tfi' => 'application/thraud+xml', - 'tfm' => 'application/x-tex-tfm', - 'tfx' => 'image/tiff-fx', - 'tga' => 'image/x-tga', - 'tgz' => 'application/x-tar', - 'thmx' => 'application/vnd.ms-officetheme', - 'tif' => 'image/tiff', - 'tiff' => 'image/tiff', - 'tk' => 'application/x-tcl', - 'tmo' => 'application/vnd.tmobile-livetv', - 'toml' => 'application/toml', - 'torrent' => 'application/x-bittorrent', - 'tpl' => 'application/vnd.groove-tool-template', - 'tpt' => 'application/vnd.trid.tpt', - 'tr' => 'text/troff', - 'tra' => 'application/vnd.trueapp', - 'trig' => 'application/trig', - 'trm' => 'application/x-msterminal', - 'ts' => 'video/mp2t', - 'tsd' => 'application/timestamped-data', - 'tsv' => 'text/tab-separated-values', - 'ttc' => 'font/collection', - 'ttf' => 'font/ttf', - 'ttl' => 'text/turtle', - 'ttml' => 'application/ttml+xml', - 'twd' => 'application/vnd.simtech-mindmapper', - 'twds' => 'application/vnd.simtech-mindmapper', - 'txd' => 'application/vnd.genomatix.tuxedo', - 'txf' => 'application/vnd.mobius.txf', - 'txt' => 'text/plain', - 'u3d' => 'model/u3d', - 'u8dsn' => 'message/global-delivery-status', - 'u8hdr' => 'message/global-headers', - 'u8mdn' => 'message/global-disposition-notification', - 'u8msg' => 'message/global', - 'u32' => 'application/x-authorware-bin', - 'ubj' => 'application/ubjson', - 'udeb' => 'application/x-debian-package', - 'ufd' => 'application/vnd.ufdl', - 'ufdl' => 'application/vnd.ufdl', - 'ulx' => 'application/x-glulx', - 'umj' => 'application/vnd.umajin', - 'unityweb' => 'application/vnd.unity', - 'uoml' => 'application/vnd.uoml+xml', - 'uri' => 'text/uri-list', - 'uris' => 'text/uri-list', - 'urls' => 'text/uri-list', - 'usdz' => 'model/vnd.usdz+zip', - 'ustar' => 'application/x-ustar', - 'utz' => 'application/vnd.uiq.theme', - 'uu' => 'text/x-uuencode', - 'uva' => 'audio/vnd.dece.audio', - 'uvd' => 'application/vnd.dece.data', - 'uvf' => 'application/vnd.dece.data', - 'uvg' => 'image/vnd.dece.graphic', - 'uvh' => 'video/vnd.dece.hd', - 'uvi' => 'image/vnd.dece.graphic', - 'uvm' => 'video/vnd.dece.mobile', - 'uvp' => 'video/vnd.dece.pd', - 'uvs' => 'video/vnd.dece.sd', - 'uvt' => 'application/vnd.dece.ttml+xml', - 'uvu' => 'video/vnd.uvvu.mp4', - 'uvv' => 'video/vnd.dece.video', - 'uvva' => 'audio/vnd.dece.audio', - 'uvvd' => 'application/vnd.dece.data', - 'uvvf' => 'application/vnd.dece.data', - 'uvvg' => 'image/vnd.dece.graphic', - 'uvvh' => 'video/vnd.dece.hd', - 'uvvi' => 'image/vnd.dece.graphic', - 'uvvm' => 'video/vnd.dece.mobile', - 'uvvp' => 'video/vnd.dece.pd', - 'uvvs' => 'video/vnd.dece.sd', - 'uvvt' => 'application/vnd.dece.ttml+xml', - 'uvvu' => 'video/vnd.uvvu.mp4', - 'uvvv' => 'video/vnd.dece.video', - 'uvvx' => 'application/vnd.dece.unspecified', - 'uvvz' => 'application/vnd.dece.zip', - 'uvx' => 'application/vnd.dece.unspecified', - 'uvz' => 'application/vnd.dece.zip', - 'vbox' => 'application/x-virtualbox-vbox', - 'vbox-extpack' => 'application/x-virtualbox-vbox-extpack', - 'vcard' => 'text/vcard', - 'vcd' => 'application/x-cdlink', - 'vcf' => 'text/x-vcard', - 'vcg' => 'application/vnd.groove-vcard', - 'vcs' => 'text/x-vcalendar', - 'vcx' => 'application/vnd.vcx', - 'vdi' => 'application/x-virtualbox-vdi', - 'vds' => 'model/vnd.sap.vds', - 'vhd' => 'application/x-virtualbox-vhd', - 'vis' => 'application/vnd.visionary', - 'viv' => 'video/vnd.vivo', - 'vlc' => 'application/videolan', - 'vmdk' => 'application/x-virtualbox-vmdk', - 'vob' => 'video/x-ms-vob', - 'vor' => 'application/vnd.stardivision.writer', - 'vox' => 'application/x-authorware-bin', - 'vrml' => 'model/vrml', - 'vsd' => 'application/vnd.visio', - 'vsf' => 'application/vnd.vsf', - 'vss' => 'application/vnd.visio', - 'vst' => 'application/vnd.visio', - 'vsw' => 'application/vnd.visio', - 'vtf' => 'image/vnd.valve.source.texture', - 'vtt' => 'text/vtt', - 'vtu' => 'model/vnd.vtu', - 'vxml' => 'application/voicexml+xml', - 'w3d' => 'application/x-director', - 'wad' => 'application/x-doom', - 'wadl' => 'application/vnd.sun.wadl+xml', - 'war' => 'application/java-archive', - 'wasm' => 'application/wasm', - 'wav' => 'audio/x-wav', - 'wax' => 'audio/x-ms-wax', - 'wbmp' => 'image/vnd.wap.wbmp', - 'wbs' => 'application/vnd.criticaltools.wbs+xml', - 'wbxml' => 'application/wbxml', - 'wcm' => 'application/vnd.ms-works', - 'wdb' => 'application/vnd.ms-works', - 'wdp' => 'image/vnd.ms-photo', - 'weba' => 'audio/webm', - 'webapp' => 'application/x-web-app-manifest+json', - 'webm' => 'video/webm', - 'webmanifest' => 'application/manifest+json', - 'webp' => 'image/webp', - 'wg' => 'application/vnd.pmi.widget', - 'wgt' => 'application/widget', - 'wif' => 'application/watcherinfo+xml', - 'wks' => 'application/vnd.ms-works', - 'wm' => 'video/x-ms-wm', - 'wma' => 'audio/x-ms-wma', - 'wmd' => 'application/x-ms-wmd', - 'wmf' => 'image/wmf', - 'wml' => 'text/vnd.wap.wml', - 'wmlc' => 'application/wmlc', - 'wmls' => 'text/vnd.wap.wmlscript', - 'wmlsc' => 'application/vnd.wap.wmlscriptc', - 'wmv' => 'video/x-ms-wmv', - 'wmx' => 'video/x-ms-wmx', - 'wmz' => 'application/x-msmetafile', - 'woff' => 'font/woff', - 'woff2' => 'font/woff2', - 'word' => 'application/msword', - 'wpd' => 'application/vnd.wordperfect', - 'wpl' => 'application/vnd.ms-wpl', - 'wps' => 'application/vnd.ms-works', - 'wqd' => 'application/vnd.wqd', - 'wri' => 'application/x-mswrite', - 'wrl' => 'model/vrml', - 'wsc' => 'message/vnd.wfa.wsc', - 'wsdl' => 'application/wsdl+xml', - 'wspolicy' => 'application/wspolicy+xml', - 'wtb' => 'application/vnd.webturbo', - 'wvx' => 'video/x-ms-wvx', - 'x3d' => 'model/x3d+xml', - 'x3db' => 'model/x3d+fastinfoset', - 'x3dbz' => 'model/x3d+binary', - 'x3dv' => 'model/x3d-vrml', - 'x3dvz' => 'model/x3d+vrml', - 'x3dz' => 'model/x3d+xml', - 'x32' => 'application/x-authorware-bin', - 'x_b' => 'model/vnd.parasolid.transmit.binary', - 'x_t' => 'model/vnd.parasolid.transmit.text', - 'xaml' => 'application/xaml+xml', - 'xap' => 'application/x-silverlight-app', - 'xar' => 'application/vnd.xara', - 'xav' => 'application/xcap-att+xml', - 'xbap' => 'application/x-ms-xbap', - 'xbd' => 'application/vnd.fujixerox.docuworks.binder', - 'xbm' => 'image/x-xbitmap', - 'xca' => 'application/xcap-caps+xml', - 'xcs' => 'application/calendar+xml', - 'xdf' => 'application/xcap-diff+xml', - 'xdm' => 'application/vnd.syncml.dm+xml', - 'xdp' => 'application/vnd.adobe.xdp+xml', - 'xdssc' => 'application/dssc+xml', - 'xdw' => 'application/vnd.fujixerox.docuworks', - 'xel' => 'application/xcap-el+xml', - 'xenc' => 'application/xenc+xml', - 'xer' => 'application/patch-ops-error+xml', - 'xfdf' => 'application/vnd.adobe.xfdf', - 'xfdl' => 'application/vnd.xfdl', - 'xht' => 'application/xhtml+xml', - 'xhtml' => 'application/xhtml+xml', - 'xhvml' => 'application/xv+xml', - 'xif' => 'image/vnd.xiff', - 'xl' => 'application/excel', - 'xla' => 'application/vnd.ms-excel', - 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12', - 'xlc' => 'application/vnd.ms-excel', - 'xlf' => 'application/xliff+xml', - 'xlm' => 'application/vnd.ms-excel', - 'xls' => 'application/vnd.ms-excel', - 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', - 'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12', - 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - 'xlt' => 'application/vnd.ms-excel', - 'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12', - 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', - 'xlw' => 'application/vnd.ms-excel', - 'xm' => 'audio/xm', - 'xml' => 'application/xml', - 'xns' => 'application/xcap-ns+xml', - 'xo' => 'application/vnd.olpc-sugar', - 'xop' => 'application/xop+xml', - 'xpi' => 'application/x-xpinstall', - 'xpl' => 'application/xproc+xml', - 'xpm' => 'image/x-xpixmap', - 'xpr' => 'application/vnd.is-xpr', - 'xps' => 'application/vnd.ms-xpsdocument', - 'xpw' => 'application/vnd.intercon.formnet', - 'xpx' => 'application/vnd.intercon.formnet', - 'xsd' => 'application/xml', - 'xsl' => 'application/xml', - 'xslt' => 'application/xslt+xml', - 'xsm' => 'application/vnd.syncml+xml', - 'xspf' => 'application/xspf+xml', - 'xul' => 'application/vnd.mozilla.xul+xml', - 'xvm' => 'application/xv+xml', - 'xvml' => 'application/xv+xml', - 'xwd' => 'image/x-xwindowdump', - 'xyz' => 'chemical/x-xyz', - 'xz' => 'application/x-xz', - 'yaml' => 'text/yaml', - 'yang' => 'application/yang', - 'yin' => 'application/yin+xml', - 'yml' => 'text/yaml', - 'ymp' => 'text/x-suse-ymp', - 'z' => 'application/x-compress', - 'z1' => 'application/x-zmachine', - 'z2' => 'application/x-zmachine', - 'z3' => 'application/x-zmachine', - 'z4' => 'application/x-zmachine', - 'z5' => 'application/x-zmachine', - 'z6' => 'application/x-zmachine', - 'z7' => 'application/x-zmachine', - 'z8' => 'application/x-zmachine', - 'zaz' => 'application/vnd.zzazz.deck+xml', - 'zip' => 'application/zip', - 'zir' => 'application/vnd.zul', - 'zirz' => 'application/vnd.zul', - 'zmm' => 'application/vnd.handheld-entertainment+xml', - 'zsh' => 'text/x-scriptzsh', - ]; - - /** - * Determines the mimetype of a file by looking at its extension. - * - * @link https://raw.githubusercontent.com/jshttp/mime-db/master/db.json - */ - public static function fromFilename(string $filename): ?string - { - return self::fromExtension(pathinfo($filename, PATHINFO_EXTENSION)); - } - - /** - * Maps a file extensions to a mimetype. - * - * @link https://raw.githubusercontent.com/jshttp/mime-db/master/db.json - */ - public static function fromExtension(string $extension): ?string - { - return self::MIME_TYPES[strtolower($extension)] ?? null; - } -} diff --git a/lib/guzzlehttp/psr7/src/MultipartStream.php b/lib/guzzlehttp/psr7/src/MultipartStream.php deleted file mode 100644 index 3e12b74d1..000000000 --- a/lib/guzzlehttp/psr7/src/MultipartStream.php +++ /dev/null @@ -1,159 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use Psr\Http\Message\StreamInterface; - -/** - * Stream that when read returns bytes for a streaming multipart or - * multipart/form-data stream. - */ -final class MultipartStream implements StreamInterface -{ - use StreamDecoratorTrait; - - /** @var string */ - private $boundary; - - /** @var StreamInterface */ - private $stream; - - /** - * @param array $elements Array of associative arrays, each containing a - * required "name" key mapping to the form field, - * name, a required "contents" key mapping to a - * StreamInterface/resource/string, an optional - * "headers" associative array of custom headers, - * and an optional "filename" key mapping to a - * string to send as the filename in the part. - * @param string $boundary You can optionally provide a specific boundary - * - * @throws \InvalidArgumentException - */ - public function __construct(array $elements = [], string $boundary = null) - { - $this->boundary = $boundary ?: bin2hex(random_bytes(20)); - $this->stream = $this->createStream($elements); - } - - public function getBoundary(): string - { - return $this->boundary; - } - - public function isWritable(): bool - { - return false; - } - - /** - * Get the headers needed before transferring the content of a POST file - * - * @param array<string, string> $headers - */ - private function getHeaders(array $headers): string - { - $str = ''; - foreach ($headers as $key => $value) { - $str .= "{$key}: {$value}\r\n"; - } - - return "--{$this->boundary}\r\n" . trim($str) . "\r\n\r\n"; - } - - /** - * Create the aggregate stream that will be used to upload the POST data - */ - protected function createStream(array $elements = []): StreamInterface - { - $stream = new AppendStream(); - - foreach ($elements as $element) { - if (!is_array($element)) { - throw new \UnexpectedValueException("An array is expected"); - } - $this->addElement($stream, $element); - } - - // Add the trailing boundary with CRLF - $stream->addStream(Utils::streamFor("--{$this->boundary}--\r\n")); - - return $stream; - } - - private function addElement(AppendStream $stream, array $element): void - { - foreach (['contents', 'name'] as $key) { - if (!array_key_exists($key, $element)) { - throw new \InvalidArgumentException("A '{$key}' key is required"); - } - } - - $element['contents'] = Utils::streamFor($element['contents']); - - if (empty($element['filename'])) { - $uri = $element['contents']->getMetadata('uri'); - if ($uri && \is_string($uri) && \substr($uri, 0, 6) !== 'php://' && \substr($uri, 0, 7) !== 'data://') { - $element['filename'] = $uri; - } - } - - [$body, $headers] = $this->createElement( - $element['name'], - $element['contents'], - $element['filename'] ?? null, - $element['headers'] ?? [] - ); - - $stream->addStream(Utils::streamFor($this->getHeaders($headers))); - $stream->addStream($body); - $stream->addStream(Utils::streamFor("\r\n")); - } - - private function createElement(string $name, StreamInterface $stream, ?string $filename, array $headers): array - { - // Set a default content-disposition header if one was no provided - $disposition = $this->getHeader($headers, 'content-disposition'); - if (!$disposition) { - $headers['Content-Disposition'] = ($filename === '0' || $filename) - ? sprintf( - 'form-data; name="%s"; filename="%s"', - $name, - basename($filename) - ) - : "form-data; name=\"{$name}\""; - } - - // Set a default content-length header if one was no provided - $length = $this->getHeader($headers, 'content-length'); - if (!$length) { - if ($length = $stream->getSize()) { - $headers['Content-Length'] = (string) $length; - } - } - - // Set a default Content-Type if one was not supplied - $type = $this->getHeader($headers, 'content-type'); - if (!$type && ($filename === '0' || $filename)) { - if ($type = MimeType::fromFilename($filename)) { - $headers['Content-Type'] = $type; - } - } - - return [$stream, $headers]; - } - - private function getHeader(array $headers, string $key) - { - $lowercaseHeader = strtolower($key); - foreach ($headers as $k => $v) { - if (strtolower($k) === $lowercaseHeader) { - return $v; - } - } - - return null; - } -} diff --git a/lib/guzzlehttp/psr7/src/NoSeekStream.php b/lib/guzzlehttp/psr7/src/NoSeekStream.php deleted file mode 100644 index 161a224f0..000000000 --- a/lib/guzzlehttp/psr7/src/NoSeekStream.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use Psr\Http\Message\StreamInterface; - -/** - * Stream decorator that prevents a stream from being seeked. - */ -final class NoSeekStream implements StreamInterface -{ - use StreamDecoratorTrait; - - /** @var StreamInterface */ - private $stream; - - public function seek($offset, $whence = SEEK_SET): void - { - throw new \RuntimeException('Cannot seek a NoSeekStream'); - } - - public function isSeekable(): bool - { - return false; - } -} diff --git a/lib/guzzlehttp/psr7/src/PumpStream.php b/lib/guzzlehttp/psr7/src/PumpStream.php deleted file mode 100644 index e90389c3b..000000000 --- a/lib/guzzlehttp/psr7/src/PumpStream.php +++ /dev/null @@ -1,179 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use Psr\Http\Message\StreamInterface; - -/** - * Provides a read only stream that pumps data from a PHP callable. - * - * When invoking the provided callable, the PumpStream will pass the amount of - * data requested to read to the callable. The callable can choose to ignore - * this value and return fewer or more bytes than requested. Any extra data - * returned by the provided callable is buffered internally until drained using - * the read() function of the PumpStream. The provided callable MUST return - * false when there is no more data to read. - */ -final class PumpStream implements StreamInterface -{ - /** @var callable|null */ - private $source; - - /** @var int|null */ - private $size; - - /** @var int */ - private $tellPos = 0; - - /** @var array */ - private $metadata; - - /** @var BufferStream */ - private $buffer; - - /** - * @param callable(int): (string|null|false) $source Source of the stream data. The callable MAY - * accept an integer argument used to control the - * amount of data to return. The callable MUST - * return a string when called, or false|null on error - * or EOF. - * @param array{size?: int, metadata?: array} $options Stream options: - * - metadata: Hash of metadata to use with stream. - * - size: Size of the stream, if known. - */ - public function __construct(callable $source, array $options = []) - { - $this->source = $source; - $this->size = $options['size'] ?? null; - $this->metadata = $options['metadata'] ?? []; - $this->buffer = new BufferStream(); - } - - public function __toString(): string - { - try { - return Utils::copyToString($this); - } catch (\Throwable $e) { - if (\PHP_VERSION_ID >= 70400) { - throw $e; - } - trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR); - return ''; - } - } - - public function close(): void - { - $this->detach(); - } - - public function detach() - { - $this->tellPos = 0; - $this->source = null; - - return null; - } - - public function getSize(): ?int - { - return $this->size; - } - - public function tell(): int - { - return $this->tellPos; - } - - public function eof(): bool - { - return $this->source === null; - } - - public function isSeekable(): bool - { - return false; - } - - public function rewind(): void - { - $this->seek(0); - } - - public function seek($offset, $whence = SEEK_SET): void - { - throw new \RuntimeException('Cannot seek a PumpStream'); - } - - public function isWritable(): bool - { - return false; - } - - public function write($string): int - { - throw new \RuntimeException('Cannot write to a PumpStream'); - } - - public function isReadable(): bool - { - return true; - } - - public function read($length): string - { - $data = $this->buffer->read($length); - $readLen = strlen($data); - $this->tellPos += $readLen; - $remaining = $length - $readLen; - - if ($remaining) { - $this->pump($remaining); - $data .= $this->buffer->read($remaining); - $this->tellPos += strlen($data) - $readLen; - } - - return $data; - } - - public function getContents(): string - { - $result = ''; - while (!$this->eof()) { - $result .= $this->read(1000000); - } - - return $result; - } - - /** - * {@inheritdoc} - * - * @return mixed - */ - public function getMetadata($key = null) - { - if (!$key) { - return $this->metadata; - } - - return $this->metadata[$key] ?? null; - } - - private function pump(int $length): void - { - if ($this->source) { - do { - $data = call_user_func($this->source, $length); - if ($data === false || $data === null) { - $this->source = null; - return; - } - $this->buffer->write($data); - $length -= strlen($data); - } while ($length > 0); - } - } -} diff --git a/lib/guzzlehttp/psr7/src/Query.php b/lib/guzzlehttp/psr7/src/Query.php deleted file mode 100644 index 2faab3a88..000000000 --- a/lib/guzzlehttp/psr7/src/Query.php +++ /dev/null @@ -1,113 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -final class Query -{ - /** - * Parse a query string into an associative array. - * - * If multiple values are found for the same key, the value of that key - * value pair will become an array. This function does not parse nested - * PHP style arrays into an associative array (e.g., `foo[a]=1&foo[b]=2` - * will be parsed into `['foo[a]' => '1', 'foo[b]' => '2'])`. - * - * @param string $str Query string to parse - * @param int|bool $urlEncoding How the query string is encoded - */ - public static function parse(string $str, $urlEncoding = true): array - { - $result = []; - - if ($str === '') { - return $result; - } - - if ($urlEncoding === true) { - $decoder = function ($value) { - return rawurldecode(str_replace('+', ' ', (string) $value)); - }; - } elseif ($urlEncoding === PHP_QUERY_RFC3986) { - $decoder = 'rawurldecode'; - } elseif ($urlEncoding === PHP_QUERY_RFC1738) { - $decoder = 'urldecode'; - } else { - $decoder = function ($str) { - return $str; - }; - } - - foreach (explode('&', $str) as $kvp) { - $parts = explode('=', $kvp, 2); - $key = $decoder($parts[0]); - $value = isset($parts[1]) ? $decoder($parts[1]) : null; - if (!array_key_exists($key, $result)) { - $result[$key] = $value; - } else { - if (!is_array($result[$key])) { - $result[$key] = [$result[$key]]; - } - $result[$key][] = $value; - } - } - - return $result; - } - - /** - * Build a query string from an array of key value pairs. - * - * This function can use the return value of `parse()` to build a query - * string. This function does not modify the provided keys when an array is - * encountered (like `http_build_query()` would). - * - * @param array $params Query string parameters. - * @param int|false $encoding Set to false to not encode, PHP_QUERY_RFC3986 - * to encode using RFC3986, or PHP_QUERY_RFC1738 - * to encode using RFC1738. - */ - public static function build(array $params, $encoding = PHP_QUERY_RFC3986): string - { - if (!$params) { - return ''; - } - - if ($encoding === false) { - $encoder = function (string $str): string { - return $str; - }; - } elseif ($encoding === PHP_QUERY_RFC3986) { - $encoder = 'rawurlencode'; - } elseif ($encoding === PHP_QUERY_RFC1738) { - $encoder = 'urlencode'; - } else { - throw new \InvalidArgumentException('Invalid type'); - } - - $qs = ''; - foreach ($params as $k => $v) { - $k = $encoder((string) $k); - if (!is_array($v)) { - $qs .= $k; - $v = is_bool($v) ? (int) $v : $v; - if ($v !== null) { - $qs .= '=' . $encoder((string) $v); - } - $qs .= '&'; - } else { - foreach ($v as $vv) { - $qs .= $k; - $vv = is_bool($vv) ? (int) $vv : $vv; - if ($vv !== null) { - $qs .= '=' . $encoder((string) $vv); - } - $qs .= '&'; - } - } - } - - return $qs ? (string) substr($qs, 0, -1) : ''; - } -} diff --git a/lib/guzzlehttp/psr7/src/Request.php b/lib/guzzlehttp/psr7/src/Request.php deleted file mode 100644 index b17af66a2..000000000 --- a/lib/guzzlehttp/psr7/src/Request.php +++ /dev/null @@ -1,157 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use InvalidArgumentException; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\StreamInterface; -use Psr\Http\Message\UriInterface; - -/** - * PSR-7 request implementation. - */ -class Request implements RequestInterface -{ - use MessageTrait; - - /** @var string */ - private $method; - - /** @var string|null */ - private $requestTarget; - - /** @var UriInterface */ - private $uri; - - /** - * @param string $method HTTP method - * @param string|UriInterface $uri URI - * @param array<string, string|string[]> $headers Request headers - * @param string|resource|StreamInterface|null $body Request body - * @param string $version Protocol version - */ - public function __construct( - string $method, - $uri, - array $headers = [], - $body = null, - string $version = '1.1' - ) { - $this->assertMethod($method); - if (!($uri instanceof UriInterface)) { - $uri = new Uri($uri); - } - - $this->method = strtoupper($method); - $this->uri = $uri; - $this->setHeaders($headers); - $this->protocol = $version; - - if (!isset($this->headerNames['host'])) { - $this->updateHostFromUri(); - } - - if ($body !== '' && $body !== null) { - $this->stream = Utils::streamFor($body); - } - } - - public function getRequestTarget(): string - { - if ($this->requestTarget !== null) { - return $this->requestTarget; - } - - $target = $this->uri->getPath(); - if ($target === '') { - $target = '/'; - } - if ($this->uri->getQuery() != '') { - $target .= '?' . $this->uri->getQuery(); - } - - return $target; - } - - public function withRequestTarget($requestTarget): RequestInterface - { - if (preg_match('#\s#', $requestTarget)) { - throw new InvalidArgumentException( - 'Invalid request target provided; cannot contain whitespace' - ); - } - - $new = clone $this; - $new->requestTarget = $requestTarget; - return $new; - } - - public function getMethod(): string - { - return $this->method; - } - - public function withMethod($method): RequestInterface - { - $this->assertMethod($method); - $new = clone $this; - $new->method = strtoupper($method); - return $new; - } - - public function getUri(): UriInterface - { - return $this->uri; - } - - public function withUri(UriInterface $uri, $preserveHost = false): RequestInterface - { - if ($uri === $this->uri) { - return $this; - } - - $new = clone $this; - $new->uri = $uri; - - if (!$preserveHost || !isset($this->headerNames['host'])) { - $new->updateHostFromUri(); - } - - return $new; - } - - private function updateHostFromUri(): void - { - $host = $this->uri->getHost(); - - if ($host == '') { - return; - } - - if (($port = $this->uri->getPort()) !== null) { - $host .= ':' . $port; - } - - if (isset($this->headerNames['host'])) { - $header = $this->headerNames['host']; - } else { - $header = 'Host'; - $this->headerNames['host'] = 'Host'; - } - // Ensure Host is the first header. - // See: http://tools.ietf.org/html/rfc7230#section-5.4 - $this->headers = [$header => [$host]] + $this->headers; - } - - /** - * @param mixed $method - */ - private function assertMethod($method): void - { - if (!is_string($method) || $method === '') { - throw new InvalidArgumentException('Method must be a non-empty string.'); - } - } -} diff --git a/lib/guzzlehttp/psr7/src/Response.php b/lib/guzzlehttp/psr7/src/Response.php deleted file mode 100644 index 4c6ee6f03..000000000 --- a/lib/guzzlehttp/psr7/src/Response.php +++ /dev/null @@ -1,160 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\StreamInterface; - -/** - * PSR-7 response implementation. - */ -class Response implements ResponseInterface -{ - use MessageTrait; - - /** Map of standard HTTP status code/reason phrases */ - private const PHRASES = [ - 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', - 308 => 'Permanent 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', - 510 => 'Not Extended', - 511 => 'Network Authentication Required', - ]; - - /** @var string */ - private $reasonPhrase; - - /** @var int */ - private $statusCode; - - /** - * @param int $status Status code - * @param array<string, string|string[]> $headers Response headers - * @param string|resource|StreamInterface|null $body Response body - * @param string $version Protocol version - * @param string|null $reason Reason phrase (when empty a default will be used based on the status code) - */ - public function __construct( - int $status = 200, - array $headers = [], - $body = null, - string $version = '1.1', - string $reason = null - ) { - $this->assertStatusCodeRange($status); - - $this->statusCode = $status; - - if ($body !== '' && $body !== null) { - $this->stream = Utils::streamFor($body); - } - - $this->setHeaders($headers); - if ($reason == '' && isset(self::PHRASES[$this->statusCode])) { - $this->reasonPhrase = self::PHRASES[$this->statusCode]; - } else { - $this->reasonPhrase = (string) $reason; - } - - $this->protocol = $version; - } - - public function getStatusCode(): int - { - return $this->statusCode; - } - - public function getReasonPhrase(): string - { - return $this->reasonPhrase; - } - - public function withStatus($code, $reasonPhrase = ''): ResponseInterface - { - $this->assertStatusCodeIsInteger($code); - $code = (int) $code; - $this->assertStatusCodeRange($code); - - $new = clone $this; - $new->statusCode = $code; - if ($reasonPhrase == '' && isset(self::PHRASES[$new->statusCode])) { - $reasonPhrase = self::PHRASES[$new->statusCode]; - } - $new->reasonPhrase = (string) $reasonPhrase; - return $new; - } - - /** - * @param mixed $statusCode - */ - private function assertStatusCodeIsInteger($statusCode): void - { - if (filter_var($statusCode, FILTER_VALIDATE_INT) === false) { - throw new \InvalidArgumentException('Status code must be an integer value.'); - } - } - - private function assertStatusCodeRange(int $statusCode): void - { - if ($statusCode < 100 || $statusCode >= 600) { - throw new \InvalidArgumentException('Status code must be an integer value between 1xx and 5xx.'); - } - } -} diff --git a/lib/guzzlehttp/psr7/src/Rfc7230.php b/lib/guzzlehttp/psr7/src/Rfc7230.php deleted file mode 100644 index 30224018d..000000000 --- a/lib/guzzlehttp/psr7/src/Rfc7230.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -/** - * @internal - */ -final class Rfc7230 -{ - /** - * Header related regular expressions (based on amphp/http package) - * - * Note: header delimiter (\r\n) is modified to \r?\n to accept line feed only delimiters for BC reasons. - * - * @link https://github.com/amphp/http/blob/v1.0.1/src/Rfc7230.php#L12-L15 - * - * @license https://github.com/amphp/http/blob/v1.0.1/LICENSE - */ - public const HEADER_REGEX = "(^([^()<>@,;:\\\"/[\]?={}\x01-\x20\x7F]++):[ \t]*+((?:[ \t]*+[\x21-\x7E\x80-\xFF]++)*+)[ \t]*+\r?\n)m"; - public const HEADER_FOLD_REGEX = "(\r?\n[ \t]++)"; -} diff --git a/lib/guzzlehttp/psr7/src/ServerRequest.php b/lib/guzzlehttp/psr7/src/ServerRequest.php deleted file mode 100644 index b2aa382da..000000000 --- a/lib/guzzlehttp/psr7/src/ServerRequest.php +++ /dev/null @@ -1,344 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use InvalidArgumentException; -use Psr\Http\Message\ServerRequestInterface; -use Psr\Http\Message\StreamInterface; -use Psr\Http\Message\UploadedFileInterface; -use Psr\Http\Message\UriInterface; - -/** - * Server-side HTTP request - * - * Extends the Request definition to add methods for accessing incoming data, - * specifically server parameters, cookies, matched path parameters, query - * string arguments, body parameters, and upload file information. - * - * "Attributes" are discovered via decomposing the request (and usually - * specifically the URI path), and typically will be injected by the application. - * - * Requests are considered immutable; all methods that might change state are - * implemented such that they retain the internal state of the current - * message and return a new instance that contains the changed state. - */ -class ServerRequest extends Request implements ServerRequestInterface -{ - /** - * @var array - */ - private $attributes = []; - - /** - * @var array - */ - private $cookieParams = []; - - /** - * @var array|object|null - */ - private $parsedBody; - - /** - * @var array - */ - private $queryParams = []; - - /** - * @var array - */ - private $serverParams; - - /** - * @var array - */ - private $uploadedFiles = []; - - /** - * @param string $method HTTP method - * @param string|UriInterface $uri URI - * @param array<string, string|string[]> $headers Request headers - * @param string|resource|StreamInterface|null $body Request body - * @param string $version Protocol version - * @param array $serverParams Typically the $_SERVER superglobal - */ - public function __construct( - string $method, - $uri, - array $headers = [], - $body = null, - string $version = '1.1', - array $serverParams = [] - ) { - $this->serverParams = $serverParams; - - parent::__construct($method, $uri, $headers, $body, $version); - } - - /** - * Return an UploadedFile instance array. - * - * @param array $files An array which respect $_FILES structure - * - * @throws InvalidArgumentException for unrecognized values - */ - public static function normalizeFiles(array $files): array - { - $normalized = []; - - foreach ($files as $key => $value) { - if ($value instanceof UploadedFileInterface) { - $normalized[$key] = $value; - } elseif (is_array($value) && isset($value['tmp_name'])) { - $normalized[$key] = self::createUploadedFileFromSpec($value); - } elseif (is_array($value)) { - $normalized[$key] = self::normalizeFiles($value); - continue; - } else { - throw new InvalidArgumentException('Invalid value in files specification'); - } - } - - return $normalized; - } - - /** - * Create and return an UploadedFile instance from a $_FILES specification. - * - * If the specification represents an array of values, this method will - * delegate to normalizeNestedFileSpec() and return that return value. - * - * @param array $value $_FILES struct - * - * @return UploadedFileInterface|UploadedFileInterface[] - */ - private static function createUploadedFileFromSpec(array $value) - { - if (is_array($value['tmp_name'])) { - return self::normalizeNestedFileSpec($value); - } - - return new UploadedFile( - $value['tmp_name'], - (int) $value['size'], - (int) $value['error'], - $value['name'], - $value['type'] - ); - } - - /** - * Normalize an array of file specifications. - * - * Loops through all nested files and returns a normalized array of - * UploadedFileInterface instances. - * - * @return UploadedFileInterface[] - */ - private static function normalizeNestedFileSpec(array $files = []): array - { - $normalizedFiles = []; - - foreach (array_keys($files['tmp_name']) as $key) { - $spec = [ - 'tmp_name' => $files['tmp_name'][$key], - 'size' => $files['size'][$key] ?? null, - 'error' => $files['error'][$key] ?? null, - 'name' => $files['name'][$key] ?? null, - 'type' => $files['type'][$key] ?? null, - ]; - $normalizedFiles[$key] = self::createUploadedFileFromSpec($spec); - } - - return $normalizedFiles; - } - - /** - * Return a ServerRequest populated with superglobals: - * $_GET - * $_POST - * $_COOKIE - * $_FILES - * $_SERVER - */ - public static function fromGlobals(): ServerRequestInterface - { - $method = $_SERVER['REQUEST_METHOD'] ?? 'GET'; - $headers = getallheaders(); - $uri = self::getUriFromGlobals(); - $body = new CachingStream(new LazyOpenStream('php://input', 'r+')); - $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? str_replace('HTTP/', '', $_SERVER['SERVER_PROTOCOL']) : '1.1'; - - $serverRequest = new ServerRequest($method, $uri, $headers, $body, $protocol, $_SERVER); - - return $serverRequest - ->withCookieParams($_COOKIE) - ->withQueryParams($_GET) - ->withParsedBody($_POST) - ->withUploadedFiles(self::normalizeFiles($_FILES)); - } - - private static function extractHostAndPortFromAuthority(string $authority): array - { - $uri = 'http://' . $authority; - $parts = parse_url($uri); - if (false === $parts) { - return [null, null]; - } - - $host = $parts['host'] ?? null; - $port = $parts['port'] ?? null; - - return [$host, $port]; - } - - /** - * Get a Uri populated with values from $_SERVER. - */ - public static function getUriFromGlobals(): UriInterface - { - $uri = new Uri(''); - - $uri = $uri->withScheme(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http'); - - $hasPort = false; - if (isset($_SERVER['HTTP_HOST'])) { - [$host, $port] = self::extractHostAndPortFromAuthority($_SERVER['HTTP_HOST']); - if ($host !== null) { - $uri = $uri->withHost($host); - } - - if ($port !== null) { - $hasPort = true; - $uri = $uri->withPort($port); - } - } elseif (isset($_SERVER['SERVER_NAME'])) { - $uri = $uri->withHost($_SERVER['SERVER_NAME']); - } elseif (isset($_SERVER['SERVER_ADDR'])) { - $uri = $uri->withHost($_SERVER['SERVER_ADDR']); - } - - if (!$hasPort && isset($_SERVER['SERVER_PORT'])) { - $uri = $uri->withPort($_SERVER['SERVER_PORT']); - } - - $hasQuery = false; - if (isset($_SERVER['REQUEST_URI'])) { - $requestUriParts = explode('?', $_SERVER['REQUEST_URI'], 2); - $uri = $uri->withPath($requestUriParts[0]); - if (isset($requestUriParts[1])) { - $hasQuery = true; - $uri = $uri->withQuery($requestUriParts[1]); - } - } - - if (!$hasQuery && isset($_SERVER['QUERY_STRING'])) { - $uri = $uri->withQuery($_SERVER['QUERY_STRING']); - } - - return $uri; - } - - public function getServerParams(): array - { - return $this->serverParams; - } - - public function getUploadedFiles(): array - { - return $this->uploadedFiles; - } - - public function withUploadedFiles(array $uploadedFiles): ServerRequestInterface - { - $new = clone $this; - $new->uploadedFiles = $uploadedFiles; - - return $new; - } - - public function getCookieParams(): array - { - return $this->cookieParams; - } - - public function withCookieParams(array $cookies): ServerRequestInterface - { - $new = clone $this; - $new->cookieParams = $cookies; - - return $new; - } - - public function getQueryParams(): array - { - return $this->queryParams; - } - - public function withQueryParams(array $query): ServerRequestInterface - { - $new = clone $this; - $new->queryParams = $query; - - return $new; - } - - /** - * {@inheritdoc} - * - * @return array|object|null - */ - public function getParsedBody() - { - return $this->parsedBody; - } - - public function withParsedBody($data): ServerRequestInterface - { - $new = clone $this; - $new->parsedBody = $data; - - return $new; - } - - public function getAttributes(): array - { - return $this->attributes; - } - - /** - * {@inheritdoc} - * - * @return mixed - */ - public function getAttribute($attribute, $default = null) - { - if (false === array_key_exists($attribute, $this->attributes)) { - return $default; - } - - return $this->attributes[$attribute]; - } - - public function withAttribute($attribute, $value): ServerRequestInterface - { - $new = clone $this; - $new->attributes[$attribute] = $value; - - return $new; - } - - public function withoutAttribute($attribute): ServerRequestInterface - { - if (false === array_key_exists($attribute, $this->attributes)) { - return $this; - } - - $new = clone $this; - unset($new->attributes[$attribute]); - - return $new; - } -} diff --git a/lib/guzzlehttp/psr7/src/Stream.php b/lib/guzzlehttp/psr7/src/Stream.php deleted file mode 100644 index ecd31861e..000000000 --- a/lib/guzzlehttp/psr7/src/Stream.php +++ /dev/null @@ -1,282 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use Psr\Http\Message\StreamInterface; - -/** - * PHP stream implementation. - */ -class Stream implements StreamInterface -{ - /** - * @see http://php.net/manual/function.fopen.php - * @see http://php.net/manual/en/function.gzopen.php - */ - private const READABLE_MODES = '/r|a\+|ab\+|w\+|wb\+|x\+|xb\+|c\+|cb\+/'; - private const WRITABLE_MODES = '/a|w|r\+|rb\+|rw|x|c/'; - - /** @var resource */ - private $stream; - /** @var int|null */ - private $size; - /** @var bool */ - private $seekable; - /** @var bool */ - private $readable; - /** @var bool */ - private $writable; - /** @var string|null */ - private $uri; - /** @var mixed[] */ - private $customMetadata; - - /** - * This constructor accepts an associative array of options. - * - * - size: (int) If a read stream would otherwise have an indeterminate - * size, but the size is known due to foreknowledge, then you can - * provide that size, in bytes. - * - metadata: (array) Any additional metadata to return when the metadata - * of the stream is accessed. - * - * @param resource $stream Stream resource to wrap. - * @param array{size?: int, metadata?: array} $options Associative array of options. - * - * @throws \InvalidArgumentException if the stream is not a stream resource - */ - public function __construct($stream, array $options = []) - { - if (!is_resource($stream)) { - throw new \InvalidArgumentException('Stream must be a resource'); - } - - if (isset($options['size'])) { - $this->size = $options['size']; - } - - $this->customMetadata = $options['metadata'] ?? []; - $this->stream = $stream; - $meta = stream_get_meta_data($this->stream); - $this->seekable = $meta['seekable']; - $this->readable = (bool)preg_match(self::READABLE_MODES, $meta['mode']); - $this->writable = (bool)preg_match(self::WRITABLE_MODES, $meta['mode']); - $this->uri = $this->getMetadata('uri'); - } - - /** - * Closes the stream when the destructed - */ - public function __destruct() - { - $this->close(); - } - - public function __toString(): string - { - try { - if ($this->isSeekable()) { - $this->seek(0); - } - return $this->getContents(); - } catch (\Throwable $e) { - if (\PHP_VERSION_ID >= 70400) { - throw $e; - } - trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR); - return ''; - } - } - - public function getContents(): string - { - if (!isset($this->stream)) { - throw new \RuntimeException('Stream is detached'); - } - - if (!$this->readable) { - throw new \RuntimeException('Cannot read from non-readable stream'); - } - - return Utils::tryGetContents($this->stream); - } - - public function close(): void - { - if (isset($this->stream)) { - if (is_resource($this->stream)) { - fclose($this->stream); - } - $this->detach(); - } - } - - public function detach() - { - if (!isset($this->stream)) { - return null; - } - - $result = $this->stream; - unset($this->stream); - $this->size = $this->uri = null; - $this->readable = $this->writable = $this->seekable = false; - - return $result; - } - - public function getSize(): ?int - { - if ($this->size !== null) { - return $this->size; - } - - if (!isset($this->stream)) { - return null; - } - - // Clear the stat cache if the stream has a URI - if ($this->uri) { - clearstatcache(true, $this->uri); - } - - $stats = fstat($this->stream); - if (is_array($stats) && isset($stats['size'])) { - $this->size = $stats['size']; - return $this->size; - } - - return null; - } - - public function isReadable(): bool - { - return $this->readable; - } - - public function isWritable(): bool - { - return $this->writable; - } - - public function isSeekable(): bool - { - return $this->seekable; - } - - public function eof(): bool - { - if (!isset($this->stream)) { - throw new \RuntimeException('Stream is detached'); - } - - return feof($this->stream); - } - - public function tell(): int - { - if (!isset($this->stream)) { - throw new \RuntimeException('Stream is detached'); - } - - $result = ftell($this->stream); - - if ($result === false) { - throw new \RuntimeException('Unable to determine stream position'); - } - - return $result; - } - - public function rewind(): void - { - $this->seek(0); - } - - public function seek($offset, $whence = SEEK_SET): void - { - $whence = (int) $whence; - - if (!isset($this->stream)) { - throw new \RuntimeException('Stream is detached'); - } - if (!$this->seekable) { - throw new \RuntimeException('Stream is not seekable'); - } - if (fseek($this->stream, $offset, $whence) === -1) { - throw new \RuntimeException('Unable to seek to stream position ' - . $offset . ' with whence ' . var_export($whence, true)); - } - } - - public function read($length): string - { - if (!isset($this->stream)) { - throw new \RuntimeException('Stream is detached'); - } - if (!$this->readable) { - throw new \RuntimeException('Cannot read from non-readable stream'); - } - if ($length < 0) { - throw new \RuntimeException('Length parameter cannot be negative'); - } - - if (0 === $length) { - return ''; - } - - try { - $string = fread($this->stream, $length); - } catch (\Exception $e) { - throw new \RuntimeException('Unable to read from stream', 0, $e); - } - - if (false === $string) { - throw new \RuntimeException('Unable to read from stream'); - } - - return $string; - } - - public function write($string): int - { - if (!isset($this->stream)) { - throw new \RuntimeException('Stream is detached'); - } - if (!$this->writable) { - throw new \RuntimeException('Cannot write to a non-writable stream'); - } - - // We can't know the size after writing anything - $this->size = null; - $result = fwrite($this->stream, $string); - - if ($result === false) { - throw new \RuntimeException('Unable to write to stream'); - } - - return $result; - } - - /** - * {@inheritdoc} - * - * @return mixed - */ - public function getMetadata($key = null) - { - if (!isset($this->stream)) { - return $key ? null : []; - } elseif (!$key) { - return $this->customMetadata + stream_get_meta_data($this->stream); - } elseif (isset($this->customMetadata[$key])) { - return $this->customMetadata[$key]; - } - - $meta = stream_get_meta_data($this->stream); - - return $meta[$key] ?? null; - } -} diff --git a/lib/guzzlehttp/psr7/src/StreamDecoratorTrait.php b/lib/guzzlehttp/psr7/src/StreamDecoratorTrait.php deleted file mode 100644 index 56d4104d4..000000000 --- a/lib/guzzlehttp/psr7/src/StreamDecoratorTrait.php +++ /dev/null @@ -1,155 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use Psr\Http\Message\StreamInterface; - -/** - * Stream decorator trait - * - * @property StreamInterface $stream - */ -trait StreamDecoratorTrait -{ - /** - * @param StreamInterface $stream Stream to decorate - */ - public function __construct(StreamInterface $stream) - { - $this->stream = $stream; - } - - /** - * Magic method used to create a new stream if streams are not added in - * the constructor of a decorator (e.g., LazyOpenStream). - * - * @return StreamInterface - */ - public function __get(string $name) - { - if ($name === 'stream') { - $this->stream = $this->createStream(); - return $this->stream; - } - - throw new \UnexpectedValueException("$name not found on class"); - } - - public function __toString(): string - { - try { - if ($this->isSeekable()) { - $this->seek(0); - } - return $this->getContents(); - } catch (\Throwable $e) { - if (\PHP_VERSION_ID >= 70400) { - throw $e; - } - trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR); - return ''; - } - } - - public function getContents(): string - { - return Utils::copyToString($this); - } - - /** - * Allow decorators to implement custom methods - * - * @return mixed - */ - public function __call(string $method, array $args) - { - /** @var callable $callable */ - $callable = [$this->stream, $method]; - $result = call_user_func_array($callable, $args); - - // Always return the wrapped object if the result is a return $this - return $result === $this->stream ? $this : $result; - } - - public function close(): void - { - $this->stream->close(); - } - - /** - * {@inheritdoc} - * - * @return mixed - */ - public function getMetadata($key = null) - { - return $this->stream->getMetadata($key); - } - - public function detach() - { - return $this->stream->detach(); - } - - public function getSize(): ?int - { - return $this->stream->getSize(); - } - - public function eof(): bool - { - return $this->stream->eof(); - } - - public function tell(): int - { - return $this->stream->tell(); - } - - public function isReadable(): bool - { - return $this->stream->isReadable(); - } - - public function isWritable(): bool - { - return $this->stream->isWritable(); - } - - public function isSeekable(): bool - { - return $this->stream->isSeekable(); - } - - public function rewind(): void - { - $this->seek(0); - } - - public function seek($offset, $whence = SEEK_SET): void - { - $this->stream->seek($offset, $whence); - } - - public function read($length): string - { - return $this->stream->read($length); - } - - public function write($string): int - { - return $this->stream->write($string); - } - - /** - * Implement in subclasses to dynamically create streams when requested. - * - * @throws \BadMethodCallException - */ - protected function createStream(): StreamInterface - { - throw new \BadMethodCallException('Not implemented'); - } -} diff --git a/lib/guzzlehttp/psr7/src/StreamWrapper.php b/lib/guzzlehttp/psr7/src/StreamWrapper.php deleted file mode 100644 index 2a9346403..000000000 --- a/lib/guzzlehttp/psr7/src/StreamWrapper.php +++ /dev/null @@ -1,175 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use Psr\Http\Message\StreamInterface; - -/** - * Converts Guzzle streams into PHP stream resources. - * - * @see https://www.php.net/streamwrapper - */ -final class StreamWrapper -{ - /** @var resource */ - public $context; - - /** @var StreamInterface */ - private $stream; - - /** @var string r, r+, or w */ - private $mode; - - /** - * Returns a resource representing the stream. - * - * @param StreamInterface $stream The stream to get a resource for - * - * @return resource - * - * @throws \InvalidArgumentException if stream is not readable or writable - */ - public static function getResource(StreamInterface $stream) - { - self::register(); - - if ($stream->isReadable()) { - $mode = $stream->isWritable() ? 'r+' : 'r'; - } elseif ($stream->isWritable()) { - $mode = 'w'; - } else { - throw new \InvalidArgumentException('The stream must be readable, ' - . 'writable, or both.'); - } - - return fopen('guzzle://stream', $mode, false, self::createStreamContext($stream)); - } - - /** - * Creates a stream context that can be used to open a stream as a php stream resource. - * - * @return resource - */ - public static function createStreamContext(StreamInterface $stream) - { - return stream_context_create([ - 'guzzle' => ['stream' => $stream] - ]); - } - - /** - * Registers the stream wrapper if needed - */ - public static function register(): void - { - if (!in_array('guzzle', stream_get_wrappers())) { - stream_wrapper_register('guzzle', __CLASS__); - } - } - - public function stream_open(string $path, string $mode, int $options, string &$opened_path = null): bool - { - $options = stream_context_get_options($this->context); - - if (!isset($options['guzzle']['stream'])) { - return false; - } - - $this->mode = $mode; - $this->stream = $options['guzzle']['stream']; - - return true; - } - - public function stream_read(int $count): string - { - return $this->stream->read($count); - } - - public function stream_write(string $data): int - { - return $this->stream->write($data); - } - - public function stream_tell(): int - { - return $this->stream->tell(); - } - - public function stream_eof(): bool - { - return $this->stream->eof(); - } - - public function stream_seek(int $offset, int $whence): bool - { - $this->stream->seek($offset, $whence); - - return true; - } - - /** - * @return resource|false - */ - public function stream_cast(int $cast_as) - { - $stream = clone($this->stream); - $resource = $stream->detach(); - - return $resource ?? false; - } - - /** - * @return array<int|string, int> - */ - public function stream_stat(): array - { - static $modeMap = [ - 'r' => 33060, - 'rb' => 33060, - 'r+' => 33206, - 'w' => 33188, - 'wb' => 33188 - ]; - - return [ - 'dev' => 0, - 'ino' => 0, - 'mode' => $modeMap[$this->mode], - 'nlink' => 0, - 'uid' => 0, - 'gid' => 0, - 'rdev' => 0, - 'size' => $this->stream->getSize() ?: 0, - 'atime' => 0, - 'mtime' => 0, - 'ctime' => 0, - 'blksize' => 0, - 'blocks' => 0 - ]; - } - - /** - * @return array<int|string, int> - */ - public function url_stat(string $path, int $flags): array - { - return [ - 'dev' => 0, - 'ino' => 0, - 'mode' => 0, - 'nlink' => 0, - 'uid' => 0, - 'gid' => 0, - 'rdev' => 0, - 'size' => 0, - 'atime' => 0, - 'mtime' => 0, - 'ctime' => 0, - 'blksize' => 0, - 'blocks' => 0 - ]; - } -} diff --git a/lib/guzzlehttp/psr7/src/UploadedFile.php b/lib/guzzlehttp/psr7/src/UploadedFile.php deleted file mode 100644 index b1521bcf8..000000000 --- a/lib/guzzlehttp/psr7/src/UploadedFile.php +++ /dev/null @@ -1,211 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use InvalidArgumentException; -use Psr\Http\Message\StreamInterface; -use Psr\Http\Message\UploadedFileInterface; -use RuntimeException; - -class UploadedFile implements UploadedFileInterface -{ - private const ERRORS = [ - UPLOAD_ERR_OK, - UPLOAD_ERR_INI_SIZE, - UPLOAD_ERR_FORM_SIZE, - UPLOAD_ERR_PARTIAL, - UPLOAD_ERR_NO_FILE, - UPLOAD_ERR_NO_TMP_DIR, - UPLOAD_ERR_CANT_WRITE, - UPLOAD_ERR_EXTENSION, - ]; - - /** - * @var string|null - */ - private $clientFilename; - - /** - * @var string|null - */ - private $clientMediaType; - - /** - * @var int - */ - private $error; - - /** - * @var string|null - */ - private $file; - - /** - * @var bool - */ - private $moved = false; - - /** - * @var int|null - */ - private $size; - - /** - * @var StreamInterface|null - */ - private $stream; - - /** - * @param StreamInterface|string|resource $streamOrFile - */ - public function __construct( - $streamOrFile, - ?int $size, - int $errorStatus, - string $clientFilename = null, - string $clientMediaType = null - ) { - $this->setError($errorStatus); - $this->size = $size; - $this->clientFilename = $clientFilename; - $this->clientMediaType = $clientMediaType; - - if ($this->isOk()) { - $this->setStreamOrFile($streamOrFile); - } - } - - /** - * Depending on the value set file or stream variable - * - * @param StreamInterface|string|resource $streamOrFile - * - * @throws InvalidArgumentException - */ - private function setStreamOrFile($streamOrFile): void - { - if (is_string($streamOrFile)) { - $this->file = $streamOrFile; - } elseif (is_resource($streamOrFile)) { - $this->stream = new Stream($streamOrFile); - } elseif ($streamOrFile instanceof StreamInterface) { - $this->stream = $streamOrFile; - } else { - throw new InvalidArgumentException( - 'Invalid stream or file provided for UploadedFile' - ); - } - } - - /** - * @throws InvalidArgumentException - */ - private function setError(int $error): void - { - if (false === in_array($error, UploadedFile::ERRORS, true)) { - throw new InvalidArgumentException( - 'Invalid error status for UploadedFile' - ); - } - - $this->error = $error; - } - - private function isStringNotEmpty($param): bool - { - return is_string($param) && false === empty($param); - } - - /** - * Return true if there is no upload error - */ - private function isOk(): bool - { - return $this->error === UPLOAD_ERR_OK; - } - - public function isMoved(): bool - { - return $this->moved; - } - - /** - * @throws RuntimeException if is moved or not ok - */ - private function validateActive(): void - { - if (false === $this->isOk()) { - throw new RuntimeException('Cannot retrieve stream due to upload error'); - } - - if ($this->isMoved()) { - throw new RuntimeException('Cannot retrieve stream after it has already been moved'); - } - } - - public function getStream(): StreamInterface - { - $this->validateActive(); - - if ($this->stream instanceof StreamInterface) { - return $this->stream; - } - - /** @var string $file */ - $file = $this->file; - - return new LazyOpenStream($file, 'r+'); - } - - public function moveTo($targetPath): void - { - $this->validateActive(); - - if (false === $this->isStringNotEmpty($targetPath)) { - throw new InvalidArgumentException( - 'Invalid path provided for move operation; must be a non-empty string' - ); - } - - if ($this->file) { - $this->moved = PHP_SAPI === 'cli' - ? rename($this->file, $targetPath) - : move_uploaded_file($this->file, $targetPath); - } else { - Utils::copyToStream( - $this->getStream(), - new LazyOpenStream($targetPath, 'w') - ); - - $this->moved = true; - } - - if (false === $this->moved) { - throw new RuntimeException( - sprintf('Uploaded file could not be moved to %s', $targetPath) - ); - } - } - - public function getSize(): ?int - { - return $this->size; - } - - public function getError(): int - { - return $this->error; - } - - public function getClientFilename(): ?string - { - return $this->clientFilename; - } - - public function getClientMediaType(): ?string - { - return $this->clientMediaType; - } -} diff --git a/lib/guzzlehttp/psr7/src/Uri.php b/lib/guzzlehttp/psr7/src/Uri.php deleted file mode 100644 index 09e878d3d..000000000 --- a/lib/guzzlehttp/psr7/src/Uri.php +++ /dev/null @@ -1,740 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use GuzzleHttp\Psr7\Exception\MalformedUriException; -use Psr\Http\Message\UriInterface; - -/** - * PSR-7 URI implementation. - * - * @author Michael Dowling - * @author Tobias Schultze - * @author Matthew Weier O'Phinney - */ -class Uri implements UriInterface, \JsonSerializable -{ - /** - * Absolute http and https URIs require a host per RFC 7230 Section 2.7 - * but in generic URIs the host can be empty. So for http(s) URIs - * we apply this default host when no host is given yet to form a - * valid URI. - */ - private const HTTP_DEFAULT_HOST = 'localhost'; - - private const DEFAULT_PORTS = [ - 'http' => 80, - 'https' => 443, - 'ftp' => 21, - 'gopher' => 70, - 'nntp' => 119, - 'news' => 119, - 'telnet' => 23, - 'tn3270' => 23, - 'imap' => 143, - 'pop' => 110, - 'ldap' => 389, - ]; - - /** - * Unreserved characters for use in a regex. - * - * @link https://tools.ietf.org/html/rfc3986#section-2.3 - */ - private const CHAR_UNRESERVED = 'a-zA-Z0-9_\-\.~'; - - /** - * Sub-delims for use in a regex. - * - * @link https://tools.ietf.org/html/rfc3986#section-2.2 - */ - private const CHAR_SUB_DELIMS = '!\$&\'\(\)\*\+,;='; - private const QUERY_SEPARATORS_REPLACEMENT = ['=' => '%3D', '&' => '%26']; - - /** @var string Uri scheme. */ - private $scheme = ''; - - /** @var string Uri user info. */ - private $userInfo = ''; - - /** @var string Uri host. */ - private $host = ''; - - /** @var int|null Uri port. */ - private $port; - - /** @var string Uri path. */ - private $path = ''; - - /** @var string Uri query string. */ - private $query = ''; - - /** @var string Uri fragment. */ - private $fragment = ''; - - /** @var string|null String representation */ - private $composedComponents; - - public function __construct(string $uri = '') - { - if ($uri !== '') { - $parts = self::parse($uri); - if ($parts === false) { - throw new MalformedUriException("Unable to parse URI: $uri"); - } - $this->applyParts($parts); - } - } - /** - * UTF-8 aware \parse_url() replacement. - * - * The internal function produces broken output for non ASCII domain names - * (IDN) when used with locales other than "C". - * - * On the other hand, cURL understands IDN correctly only when UTF-8 locale - * is configured ("C.UTF-8", "en_US.UTF-8", etc.). - * - * @see https://bugs.php.net/bug.php?id=52923 - * @see https://www.php.net/manual/en/function.parse-url.php#114817 - * @see https://curl.haxx.se/libcurl/c/CURLOPT_URL.html#ENCODING - * - * @return array|false - */ - private static function parse(string $url) - { - // If IPv6 - $prefix = ''; - if (preg_match('%^(.*://\[[0-9:a-f]+\])(.*?)$%', $url, $matches)) { - /** @var array{0:string, 1:string, 2:string} $matches */ - $prefix = $matches[1]; - $url = $matches[2]; - } - - /** @var string */ - $encodedUrl = preg_replace_callback( - '%[^:/@?&=#]+%usD', - static function ($matches) { - return urlencode($matches[0]); - }, - $url - ); - - $result = parse_url($prefix . $encodedUrl); - - if ($result === false) { - return false; - } - - return array_map('urldecode', $result); - } - - public function __toString(): string - { - if ($this->composedComponents === null) { - $this->composedComponents = self::composeComponents( - $this->scheme, - $this->getAuthority(), - $this->path, - $this->query, - $this->fragment - ); - } - - return $this->composedComponents; - } - - /** - * Composes a URI reference string from its various components. - * - * Usually this method does not need to be called manually but instead is used indirectly via - * `Psr\Http\Message\UriInterface::__toString`. - * - * PSR-7 UriInterface treats an empty component the same as a missing component as - * getQuery(), getFragment() etc. always return a string. This explains the slight - * difference to RFC 3986 Section 5.3. - * - * Another adjustment is that the authority separator is added even when the authority is missing/empty - * for the "file" scheme. This is because PHP stream functions like `file_get_contents` only work with - * `file:///myfile` but not with `file:/myfile` although they are equivalent according to RFC 3986. But - * `file:///` is the more common syntax for the file scheme anyway (Chrome for example redirects to - * that format). - * - * @link https://tools.ietf.org/html/rfc3986#section-5.3 - */ - public static function composeComponents(?string $scheme, ?string $authority, string $path, ?string $query, ?string $fragment): string - { - $uri = ''; - - // weak type checks to also accept null until we can add scalar type hints - if ($scheme != '') { - $uri .= $scheme . ':'; - } - - if ($authority != '' || $scheme === 'file') { - $uri .= '//' . $authority; - } - - if ($authority != '' && $path != '' && $path[0] != '/') { - $path = '/' . $path; - } - - $uri .= $path; - - if ($query != '') { - $uri .= '?' . $query; - } - - if ($fragment != '') { - $uri .= '#' . $fragment; - } - - return $uri; - } - - /** - * Whether the URI has the default port of the current scheme. - * - * `Psr\Http\Message\UriInterface::getPort` may return null or the standard port. This method can be used - * independently of the implementation. - */ - public static function isDefaultPort(UriInterface $uri): bool - { - return $uri->getPort() === null - || (isset(self::DEFAULT_PORTS[$uri->getScheme()]) && $uri->getPort() === self::DEFAULT_PORTS[$uri->getScheme()]); - } - - /** - * Whether the URI is absolute, i.e. it has a scheme. - * - * An instance of UriInterface can either be an absolute URI or a relative reference. This method returns true - * if it is the former. An absolute URI has a scheme. A relative reference is used to express a URI relative - * to another URI, the base URI. Relative references can be divided into several forms: - * - network-path references, e.g. '//example.com/path' - * - absolute-path references, e.g. '/path' - * - relative-path references, e.g. 'subpath' - * - * @see Uri::isNetworkPathReference - * @see Uri::isAbsolutePathReference - * @see Uri::isRelativePathReference - * @link https://tools.ietf.org/html/rfc3986#section-4 - */ - public static function isAbsolute(UriInterface $uri): bool - { - return $uri->getScheme() !== ''; - } - - /** - * Whether the URI is a network-path reference. - * - * A relative reference that begins with two slash characters is termed an network-path reference. - * - * @link https://tools.ietf.org/html/rfc3986#section-4.2 - */ - public static function isNetworkPathReference(UriInterface $uri): bool - { - return $uri->getScheme() === '' && $uri->getAuthority() !== ''; - } - - /** - * Whether the URI is a absolute-path reference. - * - * A relative reference that begins with a single slash character is termed an absolute-path reference. - * - * @link https://tools.ietf.org/html/rfc3986#section-4.2 - */ - public static function isAbsolutePathReference(UriInterface $uri): bool - { - return $uri->getScheme() === '' - && $uri->getAuthority() === '' - && isset($uri->getPath()[0]) - && $uri->getPath()[0] === '/'; - } - - /** - * Whether the URI is a relative-path reference. - * - * A relative reference that does not begin with a slash character is termed a relative-path reference. - * - * @link https://tools.ietf.org/html/rfc3986#section-4.2 - */ - public static function isRelativePathReference(UriInterface $uri): bool - { - return $uri->getScheme() === '' - && $uri->getAuthority() === '' - && (!isset($uri->getPath()[0]) || $uri->getPath()[0] !== '/'); - } - - /** - * Whether the URI is a same-document reference. - * - * A same-document reference refers to a URI that is, aside from its fragment - * component, identical to the base URI. When no base URI is given, only an empty - * URI reference (apart from its fragment) is considered a same-document reference. - * - * @param UriInterface $uri The URI to check - * @param UriInterface|null $base An optional base URI to compare against - * - * @link https://tools.ietf.org/html/rfc3986#section-4.4 - */ - public static function isSameDocumentReference(UriInterface $uri, UriInterface $base = null): bool - { - if ($base !== null) { - $uri = UriResolver::resolve($base, $uri); - - return ($uri->getScheme() === $base->getScheme()) - && ($uri->getAuthority() === $base->getAuthority()) - && ($uri->getPath() === $base->getPath()) - && ($uri->getQuery() === $base->getQuery()); - } - - return $uri->getScheme() === '' && $uri->getAuthority() === '' && $uri->getPath() === '' && $uri->getQuery() === ''; - } - - /** - * Creates a new URI with a specific query string value removed. - * - * Any existing query string values that exactly match the provided key are - * removed. - * - * @param UriInterface $uri URI to use as a base. - * @param string $key Query string key to remove. - */ - public static function withoutQueryValue(UriInterface $uri, string $key): UriInterface - { - $result = self::getFilteredQueryString($uri, [$key]); - - return $uri->withQuery(implode('&', $result)); - } - - /** - * Creates a new URI with a specific query string value. - * - * Any existing query string values that exactly match the provided key are - * removed and replaced with the given key value pair. - * - * A value of null will set the query string key without a value, e.g. "key" - * instead of "key=value". - * - * @param UriInterface $uri URI to use as a base. - * @param string $key Key to set. - * @param string|null $value Value to set - */ - public static function withQueryValue(UriInterface $uri, string $key, ?string $value): UriInterface - { - $result = self::getFilteredQueryString($uri, [$key]); - - $result[] = self::generateQueryString($key, $value); - - return $uri->withQuery(implode('&', $result)); - } - - /** - * Creates a new URI with multiple specific query string values. - * - * It has the same behavior as withQueryValue() but for an associative array of key => value. - * - * @param UriInterface $uri URI to use as a base. - * @param array<string, string|null> $keyValueArray Associative array of key and values - */ - public static function withQueryValues(UriInterface $uri, array $keyValueArray): UriInterface - { - $result = self::getFilteredQueryString($uri, array_keys($keyValueArray)); - - foreach ($keyValueArray as $key => $value) { - $result[] = self::generateQueryString((string) $key, $value !== null ? (string) $value : null); - } - - return $uri->withQuery(implode('&', $result)); - } - - /** - * Creates a URI from a hash of `parse_url` components. - * - * @link http://php.net/manual/en/function.parse-url.php - * - * @throws MalformedUriException If the components do not form a valid URI. - */ - public static function fromParts(array $parts): UriInterface - { - $uri = new self(); - $uri->applyParts($parts); - $uri->validateState(); - - return $uri; - } - - public function getScheme(): string - { - return $this->scheme; - } - - public function getAuthority(): string - { - $authority = $this->host; - if ($this->userInfo !== '') { - $authority = $this->userInfo . '@' . $authority; - } - - if ($this->port !== null) { - $authority .= ':' . $this->port; - } - - return $authority; - } - - public function getUserInfo(): string - { - return $this->userInfo; - } - - public function getHost(): string - { - return $this->host; - } - - public function getPort(): ?int - { - return $this->port; - } - - public function getPath(): string - { - return $this->path; - } - - public function getQuery(): string - { - return $this->query; - } - - public function getFragment(): string - { - return $this->fragment; - } - - public function withScheme($scheme): UriInterface - { - $scheme = $this->filterScheme($scheme); - - if ($this->scheme === $scheme) { - return $this; - } - - $new = clone $this; - $new->scheme = $scheme; - $new->composedComponents = null; - $new->removeDefaultPort(); - $new->validateState(); - - return $new; - } - - public function withUserInfo($user, $password = null): UriInterface - { - $info = $this->filterUserInfoComponent($user); - if ($password !== null) { - $info .= ':' . $this->filterUserInfoComponent($password); - } - - if ($this->userInfo === $info) { - return $this; - } - - $new = clone $this; - $new->userInfo = $info; - $new->composedComponents = null; - $new->validateState(); - - return $new; - } - - public function withHost($host): UriInterface - { - $host = $this->filterHost($host); - - if ($this->host === $host) { - return $this; - } - - $new = clone $this; - $new->host = $host; - $new->composedComponents = null; - $new->validateState(); - - return $new; - } - - public function withPort($port): UriInterface - { - $port = $this->filterPort($port); - - if ($this->port === $port) { - return $this; - } - - $new = clone $this; - $new->port = $port; - $new->composedComponents = null; - $new->removeDefaultPort(); - $new->validateState(); - - return $new; - } - - public function withPath($path): UriInterface - { - $path = $this->filterPath($path); - - if ($this->path === $path) { - return $this; - } - - $new = clone $this; - $new->path = $path; - $new->composedComponents = null; - $new->validateState(); - - return $new; - } - - public function withQuery($query): UriInterface - { - $query = $this->filterQueryAndFragment($query); - - if ($this->query === $query) { - return $this; - } - - $new = clone $this; - $new->query = $query; - $new->composedComponents = null; - - return $new; - } - - public function withFragment($fragment): UriInterface - { - $fragment = $this->filterQueryAndFragment($fragment); - - if ($this->fragment === $fragment) { - return $this; - } - - $new = clone $this; - $new->fragment = $fragment; - $new->composedComponents = null; - - return $new; - } - - public function jsonSerialize(): string - { - return $this->__toString(); - } - - /** - * Apply parse_url parts to a URI. - * - * @param array $parts Array of parse_url parts to apply. - */ - private function applyParts(array $parts): void - { - $this->scheme = isset($parts['scheme']) - ? $this->filterScheme($parts['scheme']) - : ''; - $this->userInfo = isset($parts['user']) - ? $this->filterUserInfoComponent($parts['user']) - : ''; - $this->host = isset($parts['host']) - ? $this->filterHost($parts['host']) - : ''; - $this->port = isset($parts['port']) - ? $this->filterPort($parts['port']) - : null; - $this->path = isset($parts['path']) - ? $this->filterPath($parts['path']) - : ''; - $this->query = isset($parts['query']) - ? $this->filterQueryAndFragment($parts['query']) - : ''; - $this->fragment = isset($parts['fragment']) - ? $this->filterQueryAndFragment($parts['fragment']) - : ''; - if (isset($parts['pass'])) { - $this->userInfo .= ':' . $this->filterUserInfoComponent($parts['pass']); - } - - $this->removeDefaultPort(); - } - - /** - * @param mixed $scheme - * - * @throws \InvalidArgumentException If the scheme is invalid. - */ - private function filterScheme($scheme): string - { - if (!is_string($scheme)) { - throw new \InvalidArgumentException('Scheme must be a string'); - } - - return \strtr($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); - } - - /** - * @param mixed $component - * - * @throws \InvalidArgumentException If the user info is invalid. - */ - private function filterUserInfoComponent($component): string - { - if (!is_string($component)) { - throw new \InvalidArgumentException('User info must be a string'); - } - - return preg_replace_callback( - '/(?:[^%' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . ']+|%(?![A-Fa-f0-9]{2}))/', - [$this, 'rawurlencodeMatchZero'], - $component - ); - } - - /** - * @param mixed $host - * - * @throws \InvalidArgumentException If the host is invalid. - */ - private function filterHost($host): string - { - if (!is_string($host)) { - throw new \InvalidArgumentException('Host must be a string'); - } - - return \strtr($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); - } - - /** - * @param mixed $port - * - * @throws \InvalidArgumentException If the port is invalid. - */ - private function filterPort($port): ?int - { - if ($port === null) { - return null; - } - - $port = (int) $port; - if (0 > $port || 0xffff < $port) { - throw new \InvalidArgumentException( - sprintf('Invalid port: %d. Must be between 0 and 65535', $port) - ); - } - - return $port; - } - - /** - * @param string[] $keys - * - * @return string[] - */ - private static function getFilteredQueryString(UriInterface $uri, array $keys): array - { - $current = $uri->getQuery(); - - if ($current === '') { - return []; - } - - $decodedKeys = array_map('rawurldecode', $keys); - - return array_filter(explode('&', $current), function ($part) use ($decodedKeys) { - return !in_array(rawurldecode(explode('=', $part)[0]), $decodedKeys, true); - }); - } - - private static function generateQueryString(string $key, ?string $value): string - { - // Query string separators ("=", "&") within the key or value need to be encoded - // (while preventing double-encoding) before setting the query string. All other - // chars that need percent-encoding will be encoded by withQuery(). - $queryString = strtr($key, self::QUERY_SEPARATORS_REPLACEMENT); - - if ($value !== null) { - $queryString .= '=' . strtr($value, self::QUERY_SEPARATORS_REPLACEMENT); - } - - return $queryString; - } - - private function removeDefaultPort(): void - { - if ($this->port !== null && self::isDefaultPort($this)) { - $this->port = null; - } - } - - /** - * Filters the path of a URI - * - * @param mixed $path - * - * @throws \InvalidArgumentException If the path is invalid. - */ - private function filterPath($path): string - { - if (!is_string($path)) { - throw new \InvalidArgumentException('Path must be a string'); - } - - return preg_replace_callback( - '/(?:[^' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . '%:@\/]++|%(?![A-Fa-f0-9]{2}))/', - [$this, 'rawurlencodeMatchZero'], - $path - ); - } - - /** - * Filters the query string or fragment of a URI. - * - * @param mixed $str - * - * @throws \InvalidArgumentException If the query or fragment is invalid. - */ - private function filterQueryAndFragment($str): string - { - if (!is_string($str)) { - throw new \InvalidArgumentException('Query and fragment must be a string'); - } - - return preg_replace_callback( - '/(?:[^' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . '%:@\/\?]++|%(?![A-Fa-f0-9]{2}))/', - [$this, 'rawurlencodeMatchZero'], - $str - ); - } - - private function rawurlencodeMatchZero(array $match): string - { - return rawurlencode($match[0]); - } - - private function validateState(): void - { - if ($this->host === '' && ($this->scheme === 'http' || $this->scheme === 'https')) { - $this->host = self::HTTP_DEFAULT_HOST; - } - - if ($this->getAuthority() === '') { - if (0 === strpos($this->path, '//')) { - throw new MalformedUriException('The path of a URI without an authority must not start with two slashes "//"'); - } - if ($this->scheme === '' && false !== strpos(explode('/', $this->path, 2)[0], ':')) { - throw new MalformedUriException('A relative URI must not have a path beginning with a segment containing a colon'); - } - } - } -} diff --git a/lib/guzzlehttp/psr7/src/UriComparator.php b/lib/guzzlehttp/psr7/src/UriComparator.php deleted file mode 100644 index 70c582aa0..000000000 --- a/lib/guzzlehttp/psr7/src/UriComparator.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use Psr\Http\Message\UriInterface; - -/** - * Provides methods to determine if a modified URL should be considered cross-origin. - * - * @author Graham Campbell - */ -final class UriComparator -{ - /** - * Determines if a modified URL should be considered cross-origin with - * respect to an original URL. - */ - public static function isCrossOrigin(UriInterface $original, UriInterface $modified): bool - { - if (\strcasecmp($original->getHost(), $modified->getHost()) !== 0) { - return true; - } - - if ($original->getScheme() !== $modified->getScheme()) { - return true; - } - - if (self::computePort($original) !== self::computePort($modified)) { - return true; - } - - return false; - } - - private static function computePort(UriInterface $uri): int - { - $port = $uri->getPort(); - - if (null !== $port) { - return $port; - } - - return 'https' === $uri->getScheme() ? 443 : 80; - } - - private function __construct() - { - // cannot be instantiated - } -} diff --git a/lib/guzzlehttp/psr7/src/UriNormalizer.php b/lib/guzzlehttp/psr7/src/UriNormalizer.php deleted file mode 100644 index e12971edd..000000000 --- a/lib/guzzlehttp/psr7/src/UriNormalizer.php +++ /dev/null @@ -1,220 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use Psr\Http\Message\UriInterface; - -/** - * Provides methods to normalize and compare URIs. - * - * @author Tobias Schultze - * - * @link https://tools.ietf.org/html/rfc3986#section-6 - */ -final class UriNormalizer -{ - /** - * Default normalizations which only include the ones that preserve semantics. - */ - public const PRESERVING_NORMALIZATIONS = - self::CAPITALIZE_PERCENT_ENCODING | - self::DECODE_UNRESERVED_CHARACTERS | - self::CONVERT_EMPTY_PATH | - self::REMOVE_DEFAULT_HOST | - self::REMOVE_DEFAULT_PORT | - self::REMOVE_DOT_SEGMENTS; - - /** - * All letters within a percent-encoding triplet (e.g., "%3A") are case-insensitive, and should be capitalized. - * - * Example: http://example.org/a%c2%b1b → http://example.org/a%C2%B1b - */ - public const CAPITALIZE_PERCENT_ENCODING = 1; - - /** - * Decodes percent-encoded octets of unreserved characters. - * - * For consistency, percent-encoded octets in the ranges of ALPHA (%41–%5A and %61–%7A), DIGIT (%30–%39), - * hyphen (%2D), period (%2E), underscore (%5F), or tilde (%7E) should not be created by URI producers and, - * when found in a URI, should be decoded to their corresponding unreserved characters by URI normalizers. - * - * Example: http://example.org/%7Eusern%61me/ → http://example.org/~username/ - */ - public const DECODE_UNRESERVED_CHARACTERS = 2; - - /** - * Converts the empty path to "/" for http and https URIs. - * - * Example: http://example.org → http://example.org/ - */ - public const CONVERT_EMPTY_PATH = 4; - - /** - * Removes the default host of the given URI scheme from the URI. - * - * Only the "file" scheme defines the default host "localhost". - * All of `file:/myfile`, `file:///myfile`, and `file://localhost/myfile` - * are equivalent according to RFC 3986. The first format is not accepted - * by PHPs stream functions and thus already normalized implicitly to the - * second format in the Uri class. See `GuzzleHttp\Psr7\Uri::composeComponents`. - * - * Example: file://localhost/myfile → file:///myfile - */ - public const REMOVE_DEFAULT_HOST = 8; - - /** - * Removes the default port of the given URI scheme from the URI. - * - * Example: http://example.org:80/ → http://example.org/ - */ - public const REMOVE_DEFAULT_PORT = 16; - - /** - * Removes unnecessary dot-segments. - * - * Dot-segments in relative-path references are not removed as it would - * change the semantics of the URI reference. - * - * Example: http://example.org/../a/b/../c/./d.html → http://example.org/a/c/d.html - */ - public const REMOVE_DOT_SEGMENTS = 32; - - /** - * Paths which include two or more adjacent slashes are converted to one. - * - * Webservers usually ignore duplicate slashes and treat those URIs equivalent. - * But in theory those URIs do not need to be equivalent. So this normalization - * may change the semantics. Encoded slashes (%2F) are not removed. - * - * Example: http://example.org//foo///bar.html → http://example.org/foo/bar.html - */ - public const REMOVE_DUPLICATE_SLASHES = 64; - - /** - * Sort query parameters with their values in alphabetical order. - * - * However, the order of parameters in a URI may be significant (this is not defined by the standard). - * So this normalization is not safe and may change the semantics of the URI. - * - * Example: ?lang=en&article=fred → ?article=fred&lang=en - * - * Note: The sorting is neither locale nor Unicode aware (the URI query does not get decoded at all) as the - * purpose is to be able to compare URIs in a reproducible way, not to have the params sorted perfectly. - */ - public const SORT_QUERY_PARAMETERS = 128; - - /** - * Returns a normalized URI. - * - * The scheme and host component are already normalized to lowercase per PSR-7 UriInterface. - * This methods adds additional normalizations that can be configured with the $flags parameter. - * - * PSR-7 UriInterface cannot distinguish between an empty component and a missing component as - * getQuery(), getFragment() etc. always return a string. This means the URIs "/?#" and "/" are - * treated equivalent which is not necessarily true according to RFC 3986. But that difference - * is highly uncommon in reality. So this potential normalization is implied in PSR-7 as well. - * - * @param UriInterface $uri The URI to normalize - * @param int $flags A bitmask of normalizations to apply, see constants - * - * @link https://tools.ietf.org/html/rfc3986#section-6.2 - */ - public static function normalize(UriInterface $uri, int $flags = self::PRESERVING_NORMALIZATIONS): UriInterface - { - if ($flags & self::CAPITALIZE_PERCENT_ENCODING) { - $uri = self::capitalizePercentEncoding($uri); - } - - if ($flags & self::DECODE_UNRESERVED_CHARACTERS) { - $uri = self::decodeUnreservedCharacters($uri); - } - - if ($flags & self::CONVERT_EMPTY_PATH && $uri->getPath() === '' && - ($uri->getScheme() === 'http' || $uri->getScheme() === 'https') - ) { - $uri = $uri->withPath('/'); - } - - if ($flags & self::REMOVE_DEFAULT_HOST && $uri->getScheme() === 'file' && $uri->getHost() === 'localhost') { - $uri = $uri->withHost(''); - } - - if ($flags & self::REMOVE_DEFAULT_PORT && $uri->getPort() !== null && Uri::isDefaultPort($uri)) { - $uri = $uri->withPort(null); - } - - if ($flags & self::REMOVE_DOT_SEGMENTS && !Uri::isRelativePathReference($uri)) { - $uri = $uri->withPath(UriResolver::removeDotSegments($uri->getPath())); - } - - if ($flags & self::REMOVE_DUPLICATE_SLASHES) { - $uri = $uri->withPath(preg_replace('#//++#', '/', $uri->getPath())); - } - - if ($flags & self::SORT_QUERY_PARAMETERS && $uri->getQuery() !== '') { - $queryKeyValues = explode('&', $uri->getQuery()); - sort($queryKeyValues); - $uri = $uri->withQuery(implode('&', $queryKeyValues)); - } - - return $uri; - } - - /** - * Whether two URIs can be considered equivalent. - * - * Both URIs are normalized automatically before comparison with the given $normalizations bitmask. The method also - * accepts relative URI references and returns true when they are equivalent. This of course assumes they will be - * resolved against the same base URI. If this is not the case, determination of equivalence or difference of - * relative references does not mean anything. - * - * @param UriInterface $uri1 An URI to compare - * @param UriInterface $uri2 An URI to compare - * @param int $normalizations A bitmask of normalizations to apply, see constants - * - * @link https://tools.ietf.org/html/rfc3986#section-6.1 - */ - public static function isEquivalent(UriInterface $uri1, UriInterface $uri2, int $normalizations = self::PRESERVING_NORMALIZATIONS): bool - { - return (string) self::normalize($uri1, $normalizations) === (string) self::normalize($uri2, $normalizations); - } - - private static function capitalizePercentEncoding(UriInterface $uri): UriInterface - { - $regex = '/(?:%[A-Fa-f0-9]{2})++/'; - - $callback = function (array $match) { - return strtoupper($match[0]); - }; - - return - $uri->withPath( - preg_replace_callback($regex, $callback, $uri->getPath()) - )->withQuery( - preg_replace_callback($regex, $callback, $uri->getQuery()) - ); - } - - private static function decodeUnreservedCharacters(UriInterface $uri): UriInterface - { - $regex = '/%(?:2D|2E|5F|7E|3[0-9]|[46][1-9A-F]|[57][0-9A])/i'; - - $callback = function (array $match) { - return rawurldecode($match[0]); - }; - - return - $uri->withPath( - preg_replace_callback($regex, $callback, $uri->getPath()) - )->withQuery( - preg_replace_callback($regex, $callback, $uri->getQuery()) - ); - } - - private function __construct() - { - // cannot be instantiated - } -} diff --git a/lib/guzzlehttp/psr7/src/UriResolver.php b/lib/guzzlehttp/psr7/src/UriResolver.php deleted file mode 100644 index 426e5c9ad..000000000 --- a/lib/guzzlehttp/psr7/src/UriResolver.php +++ /dev/null @@ -1,211 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use Psr\Http\Message\UriInterface; - -/** - * Resolves a URI reference in the context of a base URI and the opposite way. - * - * @author Tobias Schultze - * - * @link https://tools.ietf.org/html/rfc3986#section-5 - */ -final class UriResolver -{ - /** - * Removes dot segments from a path and returns the new path. - * - * @link http://tools.ietf.org/html/rfc3986#section-5.2.4 - */ - public static function removeDotSegments(string $path): string - { - if ($path === '' || $path === '/') { - return $path; - } - - $results = []; - $segments = explode('/', $path); - foreach ($segments as $segment) { - if ($segment === '..') { - array_pop($results); - } elseif ($segment !== '.') { - $results[] = $segment; - } - } - - $newPath = implode('/', $results); - - if ($path[0] === '/' && (!isset($newPath[0]) || $newPath[0] !== '/')) { - // Re-add the leading slash if necessary for cases like "/.." - $newPath = '/' . $newPath; - } elseif ($newPath !== '' && ($segment === '.' || $segment === '..')) { - // Add the trailing slash if necessary - // If newPath is not empty, then $segment must be set and is the last segment from the foreach - $newPath .= '/'; - } - - return $newPath; - } - - /** - * Converts the relative URI into a new URI that is resolved against the base URI. - * - * @link http://tools.ietf.org/html/rfc3986#section-5.2 - */ - public static function resolve(UriInterface $base, UriInterface $rel): UriInterface - { - if ((string) $rel === '') { - // we can simply return the same base URI instance for this same-document reference - return $base; - } - - if ($rel->getScheme() != '') { - return $rel->withPath(self::removeDotSegments($rel->getPath())); - } - - if ($rel->getAuthority() != '') { - $targetAuthority = $rel->getAuthority(); - $targetPath = self::removeDotSegments($rel->getPath()); - $targetQuery = $rel->getQuery(); - } else { - $targetAuthority = $base->getAuthority(); - if ($rel->getPath() === '') { - $targetPath = $base->getPath(); - $targetQuery = $rel->getQuery() != '' ? $rel->getQuery() : $base->getQuery(); - } else { - if ($rel->getPath()[0] === '/') { - $targetPath = $rel->getPath(); - } else { - if ($targetAuthority != '' && $base->getPath() === '') { - $targetPath = '/' . $rel->getPath(); - } else { - $lastSlashPos = strrpos($base->getPath(), '/'); - if ($lastSlashPos === false) { - $targetPath = $rel->getPath(); - } else { - $targetPath = substr($base->getPath(), 0, $lastSlashPos + 1) . $rel->getPath(); - } - } - } - $targetPath = self::removeDotSegments($targetPath); - $targetQuery = $rel->getQuery(); - } - } - - return new Uri(Uri::composeComponents( - $base->getScheme(), - $targetAuthority, - $targetPath, - $targetQuery, - $rel->getFragment() - )); - } - - /** - * Returns the target URI as a relative reference from the base URI. - * - * This method is the counterpart to resolve(): - * - * (string) $target === (string) UriResolver::resolve($base, UriResolver::relativize($base, $target)) - * - * One use-case is to use the current request URI as base URI and then generate relative links in your documents - * to reduce the document size or offer self-contained downloadable document archives. - * - * $base = new Uri('http://example.com/a/b/'); - * echo UriResolver::relativize($base, new Uri('http://example.com/a/b/c')); // prints 'c'. - * echo UriResolver::relativize($base, new Uri('http://example.com/a/x/y')); // prints '../x/y'. - * echo UriResolver::relativize($base, new Uri('http://example.com/a/b/?q')); // prints '?q'. - * echo UriResolver::relativize($base, new Uri('http://example.org/a/b/')); // prints '//example.org/a/b/'. - * - * This method also accepts a target that is already relative and will try to relativize it further. Only a - * relative-path reference will be returned as-is. - * - * echo UriResolver::relativize($base, new Uri('/a/b/c')); // prints 'c' as well - */ - public static function relativize(UriInterface $base, UriInterface $target): UriInterface - { - if ($target->getScheme() !== '' && - ($base->getScheme() !== $target->getScheme() || $target->getAuthority() === '' && $base->getAuthority() !== '') - ) { - return $target; - } - - if (Uri::isRelativePathReference($target)) { - // As the target is already highly relative we return it as-is. It would be possible to resolve - // the target with `$target = self::resolve($base, $target);` and then try make it more relative - // by removing a duplicate query. But let's not do that automatically. - return $target; - } - - if ($target->getAuthority() !== '' && $base->getAuthority() !== $target->getAuthority()) { - return $target->withScheme(''); - } - - // We must remove the path before removing the authority because if the path starts with two slashes, the URI - // would turn invalid. And we also cannot set a relative path before removing the authority, as that is also - // invalid. - $emptyPathUri = $target->withScheme('')->withPath('')->withUserInfo('')->withPort(null)->withHost(''); - - if ($base->getPath() !== $target->getPath()) { - return $emptyPathUri->withPath(self::getRelativePath($base, $target)); - } - - if ($base->getQuery() === $target->getQuery()) { - // Only the target fragment is left. And it must be returned even if base and target fragment are the same. - return $emptyPathUri->withQuery(''); - } - - // If the base URI has a query but the target has none, we cannot return an empty path reference as it would - // inherit the base query component when resolving. - if ($target->getQuery() === '') { - $segments = explode('/', $target->getPath()); - /** @var string $lastSegment */ - $lastSegment = end($segments); - - return $emptyPathUri->withPath($lastSegment === '' ? './' : $lastSegment); - } - - return $emptyPathUri; - } - - private static function getRelativePath(UriInterface $base, UriInterface $target): string - { - $sourceSegments = explode('/', $base->getPath()); - $targetSegments = explode('/', $target->getPath()); - array_pop($sourceSegments); - $targetLastSegment = array_pop($targetSegments); - foreach ($sourceSegments as $i => $segment) { - if (isset($targetSegments[$i]) && $segment === $targetSegments[$i]) { - unset($sourceSegments[$i], $targetSegments[$i]); - } else { - break; - } - } - $targetSegments[] = $targetLastSegment; - $relativePath = str_repeat('../', count($sourceSegments)) . implode('/', $targetSegments); - - // A reference to am empty last segment or an empty first sub-segment must be prefixed with "./". - // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used - // as the first segment of a relative-path reference, as it would be mistaken for a scheme name. - if ('' === $relativePath || false !== strpos(explode('/', $relativePath, 2)[0], ':')) { - $relativePath = "./$relativePath"; - } elseif ('/' === $relativePath[0]) { - if ($base->getAuthority() != '' && $base->getPath() === '') { - // In this case an extra slash is added by resolve() automatically. So we must not add one here. - $relativePath = ".$relativePath"; - } else { - $relativePath = "./$relativePath"; - } - } - - return $relativePath; - } - - private function __construct() - { - // cannot be instantiated - } -} diff --git a/lib/guzzlehttp/psr7/src/Utils.php b/lib/guzzlehttp/psr7/src/Utils.php deleted file mode 100644 index 3a4cf3946..000000000 --- a/lib/guzzlehttp/psr7/src/Utils.php +++ /dev/null @@ -1,459 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace GuzzleHttp\Psr7; - -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ServerRequestInterface; -use Psr\Http\Message\StreamInterface; -use Psr\Http\Message\UriInterface; - -final class Utils -{ - /** - * Remove the items given by the keys, case insensitively from the data. - * - * @param string[] $keys - */ - public static function caselessRemove(array $keys, array $data): array - { - $result = []; - - foreach ($keys as &$key) { - $key = strtolower($key); - } - - foreach ($data as $k => $v) { - if (!is_string($k) || !in_array(strtolower($k), $keys)) { - $result[$k] = $v; - } - } - - return $result; - } - - /** - * Copy the contents of a stream into another stream until the given number - * of bytes have been read. - * - * @param StreamInterface $source Stream to read from - * @param StreamInterface $dest Stream to write to - * @param int $maxLen Maximum number of bytes to read. Pass -1 - * to read the entire stream. - * - * @throws \RuntimeException on error. - */ - public static function copyToStream(StreamInterface $source, StreamInterface $dest, int $maxLen = -1): void - { - $bufferSize = 8192; - - if ($maxLen === -1) { - while (!$source->eof()) { - if (!$dest->write($source->read($bufferSize))) { - break; - } - } - } else { - $remaining = $maxLen; - while ($remaining > 0 && !$source->eof()) { - $buf = $source->read(min($bufferSize, $remaining)); - $len = strlen($buf); - if (!$len) { - break; - } - $remaining -= $len; - $dest->write($buf); - } - } - } - - /** - * Copy the contents of a stream into a string until the given number of - * bytes have been read. - * - * @param StreamInterface $stream Stream to read - * @param int $maxLen Maximum number of bytes to read. Pass -1 - * to read the entire stream. - * - * @throws \RuntimeException on error. - */ - public static function copyToString(StreamInterface $stream, int $maxLen = -1): string - { - $buffer = ''; - - if ($maxLen === -1) { - while (!$stream->eof()) { - $buf = $stream->read(1048576); - if ($buf === '') { - break; - } - $buffer .= $buf; - } - return $buffer; - } - - $len = 0; - while (!$stream->eof() && $len < $maxLen) { - $buf = $stream->read($maxLen - $len); - if ($buf === '') { - break; - } - $buffer .= $buf; - $len = strlen($buffer); - } - - return $buffer; - } - - /** - * Calculate a hash of a stream. - * - * This method reads the entire stream to calculate a rolling hash, based - * on PHP's `hash_init` functions. - * - * @param StreamInterface $stream Stream to calculate the hash for - * @param string $algo Hash algorithm (e.g. md5, crc32, etc) - * @param bool $rawOutput Whether or not to use raw output - * - * @throws \RuntimeException on error. - */ - public static function hash(StreamInterface $stream, string $algo, bool $rawOutput = false): string - { - $pos = $stream->tell(); - - if ($pos > 0) { - $stream->rewind(); - } - - $ctx = hash_init($algo); - while (!$stream->eof()) { - hash_update($ctx, $stream->read(1048576)); - } - - $out = hash_final($ctx, $rawOutput); - $stream->seek($pos); - - return $out; - } - - /** - * Clone and modify a request with the given changes. - * - * This method is useful for reducing the number of clones needed to mutate - * a message. - * - * The changes can be one of: - * - method: (string) Changes the HTTP method. - * - set_headers: (array) Sets the given headers. - * - remove_headers: (array) Remove the given headers. - * - body: (mixed) Sets the given body. - * - uri: (UriInterface) Set the URI. - * - query: (string) Set the query string value of the URI. - * - version: (string) Set the protocol version. - * - * @param RequestInterface $request Request to clone and modify. - * @param array $changes Changes to apply. - */ - public static function modifyRequest(RequestInterface $request, array $changes): RequestInterface - { - if (!$changes) { - return $request; - } - - $headers = $request->getHeaders(); - - if (!isset($changes['uri'])) { - $uri = $request->getUri(); - } else { - // Remove the host header if one is on the URI - if ($host = $changes['uri']->getHost()) { - $changes['set_headers']['Host'] = $host; - - if ($port = $changes['uri']->getPort()) { - $standardPorts = ['http' => 80, 'https' => 443]; - $scheme = $changes['uri']->getScheme(); - if (isset($standardPorts[$scheme]) && $port != $standardPorts[$scheme]) { - $changes['set_headers']['Host'] .= ':' . $port; - } - } - } - $uri = $changes['uri']; - } - - if (!empty($changes['remove_headers'])) { - $headers = self::caselessRemove($changes['remove_headers'], $headers); - } - - if (!empty($changes['set_headers'])) { - $headers = self::caselessRemove(array_keys($changes['set_headers']), $headers); - $headers = $changes['set_headers'] + $headers; - } - - if (isset($changes['query'])) { - $uri = $uri->withQuery($changes['query']); - } - - if ($request instanceof ServerRequestInterface) { - $new = (new ServerRequest( - $changes['method'] ?? $request->getMethod(), - $uri, - $headers, - $changes['body'] ?? $request->getBody(), - $changes['version'] ?? $request->getProtocolVersion(), - $request->getServerParams() - )) - ->withParsedBody($request->getParsedBody()) - ->withQueryParams($request->getQueryParams()) - ->withCookieParams($request->getCookieParams()) - ->withUploadedFiles($request->getUploadedFiles()); - - foreach ($request->getAttributes() as $key => $value) { - $new = $new->withAttribute($key, $value); - } - - return $new; - } - - return new Request( - $changes['method'] ?? $request->getMethod(), - $uri, - $headers, - $changes['body'] ?? $request->getBody(), - $changes['version'] ?? $request->getProtocolVersion() - ); - } - - /** - * Read a line from the stream up to the maximum allowed buffer length. - * - * @param StreamInterface $stream Stream to read from - * @param int|null $maxLength Maximum buffer length - */ - public static function readLine(StreamInterface $stream, ?int $maxLength = null): string - { - $buffer = ''; - $size = 0; - - while (!$stream->eof()) { - if ('' === ($byte = $stream->read(1))) { - return $buffer; - } - $buffer .= $byte; - // Break when a new line is found or the max length - 1 is reached - if ($byte === "\n" || ++$size === $maxLength - 1) { - break; - } - } - - return $buffer; - } - - /** - * Create a new stream based on the input type. - * - * Options is an associative array that can contain the following keys: - * - metadata: Array of custom metadata. - * - size: Size of the stream. - * - * This method accepts the following `$resource` types: - * - `Psr\Http\Message\StreamInterface`: Returns the value as-is. - * - `string`: Creates a stream object that uses the given string as the contents. - * - `resource`: Creates a stream object that wraps the given PHP stream resource. - * - `Iterator`: If the provided value implements `Iterator`, then a read-only - * stream object will be created that wraps the given iterable. Each time the - * stream is read from, data from the iterator will fill a buffer and will be - * continuously called until the buffer is equal to the requested read size. - * Subsequent read calls will first read from the buffer and then call `next` - * on the underlying iterator until it is exhausted. - * - `object` with `__toString()`: If the object has the `__toString()` method, - * the object will be cast to a string and then a stream will be returned that - * uses the string value. - * - `NULL`: When `null` is passed, an empty stream object is returned. - * - `callable` When a callable is passed, a read-only stream object will be - * created that invokes the given callable. The callable is invoked with the - * number of suggested bytes to read. The callable can return any number of - * bytes, but MUST return `false` when there is no more data to return. The - * stream object that wraps the callable will invoke the callable until the - * number of requested bytes are available. Any additional bytes will be - * buffered and used in subsequent reads. - * - * @param resource|string|int|float|bool|StreamInterface|callable|\Iterator|null $resource Entity body data - * @param array{size?: int, metadata?: array} $options Additional options - * - * @throws \InvalidArgumentException if the $resource arg is not valid. - */ - public static function streamFor($resource = '', array $options = []): StreamInterface - { - if (is_scalar($resource)) { - $stream = self::tryFopen('php://temp', 'r+'); - if ($resource !== '') { - fwrite($stream, (string) $resource); - fseek($stream, 0); - } - return new Stream($stream, $options); - } - - switch (gettype($resource)) { - case 'resource': - /* - * The 'php://input' is a special stream with quirks and inconsistencies. - * We avoid using that stream by reading it into php://temp - */ - - /** @var resource $resource */ - if ((\stream_get_meta_data($resource)['uri'] ?? '') === 'php://input') { - $stream = self::tryFopen('php://temp', 'w+'); - stream_copy_to_stream($resource, $stream); - fseek($stream, 0); - $resource = $stream; - } - return new Stream($resource, $options); - case 'object': - /** @var object $resource */ - if ($resource instanceof StreamInterface) { - return $resource; - } elseif ($resource instanceof \Iterator) { - return new PumpStream(function () use ($resource) { - if (!$resource->valid()) { - return false; - } - $result = $resource->current(); - $resource->next(); - return $result; - }, $options); - } elseif (method_exists($resource, '__toString')) { - return self::streamFor((string) $resource, $options); - } - break; - case 'NULL': - return new Stream(self::tryFopen('php://temp', 'r+'), $options); - } - - if (is_callable($resource)) { - return new PumpStream($resource, $options); - } - - throw new \InvalidArgumentException('Invalid resource type: ' . gettype($resource)); - } - - /** - * Safely opens a PHP stream resource using a filename. - * - * When fopen fails, PHP normally raises a warning. This function adds an - * error handler that checks for errors and throws an exception instead. - * - * @param string $filename File to open - * @param string $mode Mode used to open the file - * - * @return resource - * - * @throws \RuntimeException if the file cannot be opened - */ - public static function tryFopen(string $filename, string $mode) - { - $ex = null; - set_error_handler(static function (int $errno, string $errstr) use ($filename, $mode, &$ex): bool { - $ex = new \RuntimeException(sprintf( - 'Unable to open "%s" using mode "%s": %s', - $filename, - $mode, - $errstr - )); - - return true; - }); - - try { - /** @var resource $handle */ - $handle = fopen($filename, $mode); - } catch (\Throwable $e) { - $ex = new \RuntimeException(sprintf( - 'Unable to open "%s" using mode "%s": %s', - $filename, - $mode, - $e->getMessage() - ), 0, $e); - } - - restore_error_handler(); - - if ($ex) { - /** @var $ex \RuntimeException */ - throw $ex; - } - - return $handle; - } - - /** - * Safely gets the contents of a given stream. - * - * When stream_get_contents fails, PHP normally raises a warning. This - * function adds an error handler that checks for errors and throws an - * exception instead. - * - * @param resource $stream - * - * @throws \RuntimeException if the stream cannot be read - */ - public static function tryGetContents($stream): string - { - $ex = null; - set_error_handler(static function (int $errno, string $errstr) use (&$ex): bool { - $ex = new \RuntimeException(sprintf( - 'Unable to read stream contents: %s', - $errstr - )); - - return true; - }); - - try { - /** @var string|false $contents */ - $contents = stream_get_contents($stream); - - if ($contents === false) { - $ex = new \RuntimeException('Unable to read stream contents'); - } - } catch (\Throwable $e) { - $ex = new \RuntimeException(sprintf( - 'Unable to read stream contents: %s', - $e->getMessage() - ), 0, $e); - } - - restore_error_handler(); - - if ($ex) { - /** @var $ex \RuntimeException */ - throw $ex; - } - - return $contents; - } - - /** - * Returns a UriInterface for the given value. - * - * This function accepts a string or UriInterface and returns a - * UriInterface for the given value. If the value is already a - * UriInterface, it is returned as-is. - * - * @param string|UriInterface $uri - * - * @throws \InvalidArgumentException - */ - public static function uriFor($uri): UriInterface - { - if ($uri instanceof UriInterface) { - return $uri; - } - - if (is_string($uri)) { - return new Uri($uri); - } - - throw new \InvalidArgumentException('URI must be a string or UriInterface'); - } -} diff --git a/lib/laminas/laminas-loader/.laminas-ci.json b/lib/laminas/laminas-loader/.laminas-ci.json deleted file mode 100644 index bce3fa21b..000000000 --- a/lib/laminas/laminas-loader/.laminas-ci.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "ignore_php_platform_requirements": { - "8.1": true - } -} diff --git a/lib/laminas/laminas-loader/COPYRIGHT.md b/lib/laminas/laminas-loader/COPYRIGHT.md deleted file mode 100644 index 0a8cccc06..000000000 --- a/lib/laminas/laminas-loader/COPYRIGHT.md +++ /dev/null @@ -1 +0,0 @@ -Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/) diff --git a/lib/laminas/laminas-loader/LICENSE.md b/lib/laminas/laminas-loader/LICENSE.md deleted file mode 100644 index 10b40f142..000000000 --- a/lib/laminas/laminas-loader/LICENSE.md +++ /dev/null @@ -1,26 +0,0 @@ -Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -- Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -- Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -- Neither the name of Laminas Foundation nor the names of its contributors may - be used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/lib/laminas/laminas-loader/README.md b/lib/laminas/laminas-loader/README.md deleted file mode 100644 index 1c9911767..000000000 --- a/lib/laminas/laminas-loader/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# laminas-loader - -> This package is considered feature-complete, and is now in **security-only** maintenance mode, following a [decision by the Technical Steering Committee](https://github.com/laminas/technical-steering-committee/blob/2b55453e172a1b8c9c4c212be7cf7e7a58b9352c/meetings/minutes/2020-08-03-TSC-Minutes.md#vote-on-components-to-mark-as-security-only). -> If you have a security issue, please [follow our security reporting guidelines](https://getlaminas.org/security/). -> If you wish to take on the role of maintainer, please [nominate yourself](https://github.com/laminas/technical-steering-committee/issues/new?assignees=&labels=Nomination&template=Maintainer_Nomination.md&title=%5BNOMINATION%5D%5BMAINTAINER%5D%3A+%7Bname+of+person+being+nominated%7D) - - -[![Build Status](https://github.com/laminas/laminas-loader/workflows/Continuous%20Integration/badge.svg)](https://github.com/laminas/laminas-loader/actions?query=workflow%3A"Continuous+Integration") - -laminas-loader provides different strategies for autoloading PHP classes. - -- File issues at https://github.com/laminas/laminas-loader/issues -- Documentation is at https://docs.laminas.dev/laminas-loader/ diff --git a/lib/laminas/laminas-loader/composer.json b/lib/laminas/laminas-loader/composer.json deleted file mode 100644 index 8457d67ed..000000000 --- a/lib/laminas/laminas-loader/composer.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "laminas/laminas-loader", - "description": "Autoloading and plugin loading strategies", - "license": "BSD-3-Clause", - "keywords": [ - "laminas", - "loader" - ], - "homepage": "https://laminas.dev", - "support": { - "docs": "https://docs.laminas.dev/laminas-loader/", - "issues": "https://github.com/laminas/laminas-loader/issues", - "source": "https://github.com/laminas/laminas-loader", - "rss": "https://github.com/laminas/laminas-loader/releases.atom", - "chat": "https://laminas.dev/chat", - "forum": "https://discourse.laminas.dev" - }, - "config": { - "sort-packages": true - }, - "require": { - "php": "^7.3 || ~8.0.0 || ~8.1.0" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~2.2.1", - "phpunit/phpunit": "^9.3" - }, - "autoload": { - "psr-4": { - "Laminas\\Loader\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "LaminasTest\\Loader\\": "test/" - } - }, - "scripts": { - "check": [ - "@cs-check", - "@test" - ], - "cs-check": "phpcs", - "cs-fix": "phpcbf", - "test": "phpunit --colors=always", - "test-coverage": "phpunit --colors=always --coverage-clover clover.xml" - }, - "conflict": { - "zendframework/zend-loader": "*" - } -} diff --git a/lib/laminas/laminas-loader/composer.lock b/lib/laminas/laminas-loader/composer.lock deleted file mode 100644 index 19e27ed25..000000000 --- a/lib/laminas/laminas-loader/composer.lock +++ /dev/null @@ -1,2460 +0,0 @@ -{ - "_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": "04bc51f9c0a84aa54ea419f7c9fbee94", - "packages": [], - "packages-dev": [ - { - "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "v0.7.1", - "source": { - "type": "git", - "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", - "reference": "fe390591e0241955f22eb9ba327d137e501c771c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/fe390591e0241955f22eb9ba327d137e501c771c", - "reference": "fe390591e0241955f22eb9ba327d137e501c771c", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.0 || ^2.0", - "php": ">=5.3", - "squizlabs/php_codesniffer": "^2.0 || ^3.0 || ^4.0" - }, - "require-dev": { - "composer/composer": "*", - "phpcompatibility/php-compatibility": "^9.0", - "sensiolabs/security-checker": "^4.1.0" - }, - "type": "composer-plugin", - "extra": { - "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" - }, - "autoload": { - "psr-4": { - "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Franck Nijhof", - "email": "franck.nijhof@dealerdirect.com", - "homepage": "http://www.frenck.nl", - "role": "Developer / IT Manager" - } - ], - "description": "PHP_CodeSniffer Standards Composer Installer Plugin", - "homepage": "http://www.dealerdirect.com", - "keywords": [ - "PHPCodeSniffer", - "PHP_CodeSniffer", - "code quality", - "codesniffer", - "composer", - "installer", - "phpcs", - "plugin", - "qa", - "quality", - "standard", - "standards", - "style guide", - "stylecheck", - "tests" - ], - "support": { - "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues", - "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer" - }, - "time": "2020-12-07T18:04:37+00:00" - }, - { - "name": "doctrine/instantiator", - "version": "1.4.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b", - "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^8.0", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^0.13 || 1.0.0-alpha2", - "phpstan/phpstan": "^0.12", - "phpstan/phpstan-phpunit": "^0.12", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.4.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" - } - ], - "time": "2020-11-10T18:47:58+00:00" - }, - { - "name": "laminas/laminas-coding-standard", - "version": "2.2.1", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-coding-standard.git", - "reference": "c953ecb1d37034f4aa326046e2c24a10fe0a2845" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-coding-standard/zipball/c953ecb1d37034f4aa326046e2c24a10fe0a2845", - "reference": "c953ecb1d37034f4aa326046e2c24a10fe0a2845", - "shasum": "" - }, - "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7", - "php": "^7.3 || ~8.0.0", - "slevomat/coding-standard": "^6.4.1", - "squizlabs/php_codesniffer": "^3.5.8", - "webimpress/coding-standard": "^1.1.6" - }, - "type": "phpcodesniffer-standard", - "autoload": { - "psr-4": { - "LaminasCodingStandard\\": "src/LaminasCodingStandard/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Laminas Coding Standard", - "homepage": "https://laminas.dev", - "keywords": [ - "Coding Standard", - "laminas" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-coding-standard/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-coding-standard/issues", - "rss": "https://github.com/laminas/laminas-coding-standard/releases.atom", - "source": "https://github.com/laminas/laminas-coding-standard" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2021-05-17T17:39:41+00:00" - }, - { - "name": "myclabs/deep-copy", - "version": "1.10.2", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "replace": { - "myclabs/deep-copy": "self.version" - }, - "require-dev": { - "doctrine/collections": "^1.0", - "doctrine/common": "^2.6", - "phpunit/phpunit": "^7.1" - }, - "type": "library", - "autoload": { - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - }, - "files": [ - "src/DeepCopy/deep_copy.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.10.2" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2020-11-13T09:40:50+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v4.12.0", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "6608f01670c3cc5079e18c1dab1104e002579143" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/6608f01670c3cc5079e18c1dab1104e002579143", - "reference": "6608f01670c3cc5079e18c1dab1104e002579143", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=7.0" - }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.9-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.12.0" - }, - "time": "2021-07-21T10:44:31+00:00" - }, - { - "name": "phar-io/manifest", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.3" - }, - "time": "2021-07-20T11:28:43+00:00" - }, - { - "name": "phar-io/version", - "version": "3.1.0", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "bae7c545bef187884426f042434e561ab1ddb182" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/bae7c545bef187884426f042434e561ab1ddb182", - "reference": "bae7c545bef187884426f042434e561ab1ddb182", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.1.0" - }, - "time": "2021-02-23T14:00:09+00:00" - }, - { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" - }, - "time": "2020-06-27T09:03:43+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "5.2.2", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556", - "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556", - "shasum": "" - }, - "require": { - "ext-filter": "*", - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", - "webmozart/assert": "^1.9.1" - }, - "require-dev": { - "mockery/mockery": "~1.3.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - }, - { - "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/master" - }, - "time": "2020-09-03T19:13:55+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.4.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", - "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.0" - }, - "require-dev": { - "ext-tokenizer": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.4.0" - }, - "time": "2020-09-17T18:55:26+00:00" - }, - { - "name": "phpspec/prophecy", - "version": "1.13.0", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "be1996ed8adc35c3fd795488a653f4b518be70ea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/be1996ed8adc35c3fd795488a653f4b518be70ea", - "reference": "be1996ed8adc35c3fd795488a653f4b518be70ea", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.2", - "php": "^7.2 || ~8.0, <8.1", - "phpdocumentor/reflection-docblock": "^5.2", - "sebastian/comparator": "^3.0 || ^4.0", - "sebastian/recursion-context": "^3.0 || ^4.0" - }, - "require-dev": { - "phpspec/phpspec": "^6.0", - "phpunit/phpunit": "^8.0 || ^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.11.x-dev" - } - }, - "autoload": { - "psr-4": { - "Prophecy\\": "src/Prophecy" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" - } - ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "support": { - "issues": "https://github.com/phpspec/prophecy/issues", - "source": "https://github.com/phpspec/prophecy/tree/1.13.0" - }, - "time": "2021-03-17T13:42:18+00:00" - }, - { - "name": "phpstan/phpdoc-parser", - "version": "0.4.9", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "98a088b17966bdf6ee25c8a4b634df313d8aa531" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/98a088b17966bdf6ee25c8a4b634df313d8aa531", - "reference": "98a088b17966bdf6ee25c8a4b634df313d8aa531", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "consistence/coding-standard": "^3.5", - "ergebnis/composer-normalize": "^2.0.2", - "jakub-onderka/php-parallel-lint": "^0.9.2", - "phing/phing": "^2.16.0", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^0.12.26", - "phpstan/phpstan-strict-rules": "^0.12", - "phpunit/phpunit": "^6.3", - "slevomat/coding-standard": "^4.7.2", - "symfony/process": "^4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.4-dev" - } - }, - "autoload": { - "psr-4": { - "PHPStan\\PhpDocParser\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPDoc parser with support for nullable, intersection and generic types", - "support": { - "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/master" - }, - "time": "2020-08-03T20:32:43+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "9.2.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "f6293e1b30a2354e8428e004689671b83871edde" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f6293e1b30a2354e8428e004689671b83871edde", - "reference": "f6293e1b30a2354e8428e004689671b83871edde", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^4.10.2", - "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.3", - "phpunit/php-text-template": "^2.0.2", - "sebastian/code-unit-reverse-lookup": "^2.0.2", - "sebastian/complexity": "^2.0", - "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0.3", - "sebastian/version": "^3.0.1", - "theseer/tokenizer": "^1.2.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcov": "*", - "ext-xdebug": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-03-28T07:26:59+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "3.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/aa4be8575f26070b100fccb67faabb28f21f66f8", - "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:57:25+00:00" - }, - { - "name": "phpunit/php-invoker", - "version": "3.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:58:55+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T05:33:50+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "5.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:16:10+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "9.5.9", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "ea8c2dfb1065eb35a79b3681eee6e6fb0a6f273b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ea8c2dfb1065eb35a79b3681eee6e6fb0a6f273b", - "reference": "ea8c2dfb1065eb35a79b3681eee6e6fb0a6f273b", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.3.1", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", - "php": ">=7.3", - "phpspec/prophecy": "^1.12.1", - "phpunit/php-code-coverage": "^9.2.3", - "phpunit/php-file-iterator": "^3.0.5", - "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.5", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.3", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^2.3.4", - "sebastian/version": "^3.0.2" - }, - "require-dev": { - "ext-pdo": "*", - "phpspec/prophecy-phpunit": "^2.0.1" - }, - "suggest": { - "ext-soap": "*", - "ext-xdebug": "*" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.5-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ], - "files": [ - "src/Framework/Assert/Functions.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.9" - }, - "funding": [ - { - "url": "https://phpunit.de/donate.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-08-31T06:47:40+00:00" - }, - { - "name": "sebastian/cli-parser", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", - "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:08:49+00:00" - }, - { - "name": "sebastian/code-unit", - "version": "1.0.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:08:54+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:30:19+00:00" - }, - { - "name": "sebastian/comparator", - "version": "4.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T15:49:45+00:00" - }, - { - "name": "sebastian/complexity", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.7", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", - "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T15:52:27+00:00" - }, - { - "name": "sebastian/diff", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/process": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:10:38+00:00" - }, - { - "name": "sebastian/environment", - "version": "5.1.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "388b6ced16caa751030f6a69e588299fa09200ac" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/388b6ced16caa751030f6a69e588299fa09200ac", - "reference": "388b6ced16caa751030f6a69e588299fa09200ac", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-posix": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:52:38+00:00" - }, - { - "name": "sebastian/exporter", - "version": "4.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/d89cc98761b8cb5a1a235a6b703ae50d34080e65", - "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:24:23+00:00" - }, - { - "name": "sebastian/global-state", - "version": "5.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/23bd5951f7ff26f12d4e3242864df3e08dec4e49", - "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-06-11T13:31:12+00:00" - }, - { - "name": "sebastian/lines-of-code", - "version": "1.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.6", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", - "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-28T06:42:11+00:00" - }, - { - "name": "sebastian/object-enumerator", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:12:34+00:00" - }, - { - "name": "sebastian/object-reflector", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:14:26+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:17:30+00:00" - }, - { - "name": "sebastian/resource-operations", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:45:17+00:00" - }, - { - "name": "sebastian/type", - "version": "2.3.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b8cd8a1c753c90bc1a0f5372170e3e489136f914", - "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", - "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/2.3.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-06-15T12:49:02+00:00" - }, - { - "name": "sebastian/version", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:39:44+00:00" - }, - { - "name": "slevomat/coding-standard", - "version": "6.4.1", - "source": { - "type": "git", - "url": "https://github.com/slevomat/coding-standard.git", - "reference": "696dcca217d0c9da2c40d02731526c1e25b65346" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/696dcca217d0c9da2c40d02731526c1e25b65346", - "reference": "696dcca217d0c9da2c40d02731526c1e25b65346", - "shasum": "" - }, - "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7", - "php": "^7.1 || ^8.0", - "phpstan/phpdoc-parser": "0.4.5 - 0.4.9", - "squizlabs/php_codesniffer": "^3.5.6" - }, - "require-dev": { - "phing/phing": "2.16.3", - "php-parallel-lint/php-parallel-lint": "1.2.0", - "phpstan/phpstan": "0.12.48", - "phpstan/phpstan-deprecation-rules": "0.12.5", - "phpstan/phpstan-phpunit": "0.12.16", - "phpstan/phpstan-strict-rules": "0.12.5", - "phpunit/phpunit": "7.5.20|8.5.5|9.4.0" - }, - "type": "phpcodesniffer-standard", - "extra": { - "branch-alias": { - "dev-master": "6.x-dev" - } - }, - "autoload": { - "psr-4": { - "SlevomatCodingStandard\\": "SlevomatCodingStandard" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", - "support": { - "issues": "https://github.com/slevomat/coding-standard/issues", - "source": "https://github.com/slevomat/coding-standard/tree/6.4.1" - }, - "funding": [ - { - "url": "https://github.com/kukulich", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard", - "type": "tidelift" - } - ], - "time": "2020-10-05T12:39:37+00:00" - }, - { - "name": "squizlabs/php_codesniffer", - "version": "3.6.0", - "source": { - "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ffced0d2c8fa8e6cdc4d695a743271fab6c38625", - "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" - }, - "bin": [ - "bin/phpcs", - "bin/phpcbf" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Greg Sherwood", - "role": "lead" - } - ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", - "keywords": [ - "phpcs", - "standards" - ], - "support": { - "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", - "source": "https://github.com/squizlabs/PHP_CodeSniffer", - "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" - }, - "time": "2021-04-09T00:54:41+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.23.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce", - "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "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.23.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": "2021-02-19T12:13:01+00:00" - }, - { - "name": "theseer/tokenizer", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.1" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2021-07-28T10:34:58+00:00" - }, - { - "name": "webimpress/coding-standard", - "version": "1.2.2", - "source": { - "type": "git", - "url": "https://github.com/webimpress/coding-standard.git", - "reference": "8f4a220de33f471a8101836f7ec72b852c3f9f03" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webimpress/coding-standard/zipball/8f4a220de33f471a8101836f7ec72b852c3f9f03", - "reference": "8f4a220de33f471a8101836f7ec72b852c3f9f03", - "shasum": "" - }, - "require": { - "php": "^7.3 || ^8.0", - "squizlabs/php_codesniffer": "^3.6" - }, - "require-dev": { - "phpunit/phpunit": "^9.5.4" - }, - "type": "phpcodesniffer-standard", - "extra": { - "dev-master": "1.2.x-dev", - "dev-develop": "1.3.x-dev" - }, - "autoload": { - "psr-4": { - "WebimpressCodingStandard\\": "src/WebimpressCodingStandard/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "description": "Webimpress Coding Standard", - "keywords": [ - "Coding Standard", - "PSR-2", - "phpcs", - "psr-12", - "webimpress" - ], - "support": { - "issues": "https://github.com/webimpress/coding-standard/issues", - "source": "https://github.com/webimpress/coding-standard/tree/1.2.2" - }, - "funding": [ - { - "url": "https://github.com/michalbundyra", - "type": "github" - } - ], - "time": "2021-04-12T12:51:27+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.10.0", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25", - "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.10.0" - }, - "time": "2021-03-09T10:59:23+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": "^7.3 || ~8.0.0 || ~8.1.0" - }, - "platform-dev": [], - "plugin-api-version": "2.0.0" -} diff --git a/lib/laminas/laminas-loader/phpcs.xml.dist b/lib/laminas/laminas-loader/phpcs.xml.dist deleted file mode 100644 index 174a8d4c9..000000000 --- a/lib/laminas/laminas-loader/phpcs.xml.dist +++ /dev/null @@ -1,32 +0,0 @@ -<?xml version="1.0"?> -<ruleset - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="./vendor/squizlabs/php_codesniffer/phpcs.xsd"> - - <arg name="basepath" value="."/> - <arg name="cache" value=".phpcs-cache"/> - <arg name="colors"/> - <arg name="extensions" value="php"/> - <arg name="parallel" value="80"/> - - <!-- Show progress --> - <arg value="p"/> - - <!-- Paths to check --> - <file>src</file> - <file>test</file> - <exclude-pattern>*/TestAsset/*</exclude-pattern> - <exclude-pattern>*/_files/*</exclude-pattern> - - <!-- Include all rules from Laminas Coding Standard --> - <rule ref="LaminasCodingStandard"/> - - <rule ref="PSR1.Files.SideEffects"> - <exclude-pattern>/src/Exception/*</exclude-pattern> - <exclude-pattern>/src/SplAutoloader.php</exclude-pattern> - <exclude-pattern>/src/AutoloaderFactory.php</exclude-pattern> - <exclude-pattern>/src/ClassMapAutoloader.php</exclude-pattern> - <exclude-pattern>/src/ModuleAutoloader.php</exclude-pattern> - <exclude-pattern>/src/StandardAutoloader.php</exclude-pattern> - </rule> -</ruleset> diff --git a/lib/laminas/laminas-loader/src/AutoloaderFactory.php b/lib/laminas/laminas-loader/src/AutoloaderFactory.php deleted file mode 100644 index e1dabba1a..000000000 --- a/lib/laminas/laminas-loader/src/AutoloaderFactory.php +++ /dev/null @@ -1,212 +0,0 @@ -<?php - -namespace Laminas\Loader; - -use Laminas\Loader\SplAutoloader; -use Laminas\Loader\StandardAutoloader; -use Traversable; - -use function class_exists; -use function is_array; -use function is_subclass_of; -use function spl_autoload_unregister; -use function sprintf; -use function strrchr; -use function substr; - -if (class_exists(AutoloaderFactory::class)) { - return; -} - -// phpcs:ignore WebimpressCodingStandard.NamingConventions.AbstractClass.Prefix -abstract class AutoloaderFactory -{ - public const STANDARD_AUTOLOADER = StandardAutoloader::class; - - /** @var array All autoloaders registered using the factory */ - protected static $loaders = []; - - /** - * @var StandardAutoloader StandardAutoloader instance for resolving - * autoloader classes via the include_path - */ - protected static $standardAutoloader; - - /** - * Factory for autoloaders - * - * Options should be an array or Traversable object of the following structure: - * <code> - * array( - * '<autoloader class name>' => $autoloaderOptions, - * ) - * </code> - * - * The factory will then loop through and instantiate each autoloader with - * the specified options, and register each with the spl_autoloader. - * - * You may retrieve the concrete autoloader instances later using - * {@link getRegisteredAutoloaders()}. - * - * Note that the class names must be resolvable on the include_path or via - * the Laminas library, using PSR-0 rules (unless the class has already been - * loaded). - * - * @param array|Traversable $options (optional) options to use. Defaults to Laminas\Loader\StandardAutoloader - * @return void - * @throws Exception\InvalidArgumentException For invalid options. - * @throws Exception\InvalidArgumentException For unloadable autoloader classes. - * @throws Exception\DomainException For autoloader classes not implementing SplAutoloader. - */ - public static function factory($options = null) - { - if (null === $options) { - if (! isset(static::$loaders[static::STANDARD_AUTOLOADER])) { - $autoloader = static::getStandardAutoloader(); - $autoloader->register(); - static::$loaders[static::STANDARD_AUTOLOADER] = $autoloader; - } - - // Return so we don't hit the next check's exception (we're done here anyway) - return; - } - - if (! is_array($options) && ! $options instanceof Traversable) { - require_once __DIR__ . '/Exception/InvalidArgumentException.php'; - throw new Exception\InvalidArgumentException( - 'Options provided must be an array or Traversable' - ); - } - - foreach ($options as $class => $autoloaderOptions) { - if (! isset(static::$loaders[$class])) { - $autoloader = static::getStandardAutoloader(); - if (! class_exists($class) && ! $autoloader->autoload($class)) { - require_once 'Exception/InvalidArgumentException.php'; - throw new Exception\InvalidArgumentException( - sprintf('Autoloader class "%s" not loaded', $class) - ); - } - - if (! is_subclass_of($class, SplAutoloader::class)) { - require_once 'Exception/InvalidArgumentException.php'; - throw new Exception\InvalidArgumentException( - sprintf('Autoloader class %s must implement Laminas\\Loader\\SplAutoloader', $class) - ); - } - - if ($class === static::STANDARD_AUTOLOADER) { - $autoloader->setOptions($autoloaderOptions); - } else { - $autoloader = new $class($autoloaderOptions); - } - $autoloader->register(); - static::$loaders[$class] = $autoloader; - } else { - static::$loaders[$class]->setOptions($autoloaderOptions); - } - } - } - - /** - * Get a list of all autoloaders registered with the factory - * - * Returns an array of autoloader instances. - * - * @return array - */ - public static function getRegisteredAutoloaders() - { - return static::$loaders; - } - - /** - * Retrieves an autoloader by class name - * - * @param string $class - * @return SplAutoloader - * @throws Exception\InvalidArgumentException For non-registered class. - */ - public static function getRegisteredAutoloader($class) - { - if (! isset(static::$loaders[$class])) { - require_once 'Exception/InvalidArgumentException.php'; - throw new Exception\InvalidArgumentException(sprintf('Autoloader class "%s" not loaded', $class)); - } - return static::$loaders[$class]; - } - - /** - * Unregisters all autoloaders that have been registered via the factory. - * This will NOT unregister autoloaders registered outside of the fctory. - * - * @return void - */ - public static function unregisterAutoloaders() - { - foreach (static::getRegisteredAutoloaders() as $class => $autoloader) { - spl_autoload_unregister([$autoloader, 'autoload']); - unset(static::$loaders[$class]); - } - } - - /** - * Unregister a single autoloader by class name - * - * @param string $autoloaderClass - * @return bool - */ - public static function unregisterAutoloader($autoloaderClass) - { - if (! isset(static::$loaders[$autoloaderClass])) { - return false; - } - - $autoloader = static::$loaders[$autoloaderClass]; - spl_autoload_unregister([$autoloader, 'autoload']); - unset(static::$loaders[$autoloaderClass]); - return true; - } - - /** - * Get an instance of the standard autoloader - * - * Used to attempt to resolve autoloader classes, using the - * StandardAutoloader. The instance is marked as a fallback autoloader, to - * allow resolving autoloaders not under the "Laminas" namespace. - * - * @return SplAutoloader - */ - protected static function getStandardAutoloader() - { - if (null !== static::$standardAutoloader) { - return static::$standardAutoloader; - } - - if (! class_exists(static::STANDARD_AUTOLOADER)) { - // Extract the filename from the classname - $stdAutoloader = substr(strrchr(static::STANDARD_AUTOLOADER, '\\'), 1); - require_once __DIR__ . "/$stdAutoloader.php"; - } - $loader = new StandardAutoloader(); - static::$standardAutoloader = $loader; - return static::$standardAutoloader; - } - - /** - * Checks if the object has this class as one of its parents - * - * @deprecated since laminas 2.3 requires PHP >= 5.3.23 - * - * @see https://bugs.php.net/bug.php?id=53727 - * @see https://github.com/zendframework/zf2/pull/1807 - * - * @param string $className - * @param string $type - * @return bool - */ - protected static function isSubclassOf($className, $type) - { - return is_subclass_of($className, $type); - } -} diff --git a/lib/laminas/laminas-loader/src/ClassMapAutoloader.php b/lib/laminas/laminas-loader/src/ClassMapAutoloader.php deleted file mode 100644 index b8edf3e61..000000000 --- a/lib/laminas/laminas-loader/src/ClassMapAutoloader.php +++ /dev/null @@ -1,234 +0,0 @@ -<?php - -namespace Laminas\Loader; - -use Traversable; - -use function array_filter; -use function array_values; -use function array_walk; -use function explode; -use function file_exists; -use function gettype; -use function implode; -use function in_array; -use function is_array; -use function is_string; -use function preg_match; -use function realpath; -use function spl_autoload_register; -use function sprintf; -use function str_pad; -use function str_replace; -use function strlen; -use function substr; - -// Grab SplAutoloader interface -require_once __DIR__ . '/SplAutoloader.php'; - -/** - * Class-map autoloader - * - * Utilizes class-map files to lookup classfile locations. - */ -class ClassMapAutoloader implements SplAutoloader -{ - /** - * Registry of map files that have already been loaded - * - * @var array - */ - protected $mapsLoaded = []; - - /** - * Class name/filename map - * - * @var array - */ - protected $map = []; - - /** - * Constructor - * - * Create a new instance, and optionally configure the autoloader. - * - * @param null|array|Traversable $options - */ - public function __construct($options = null) - { - if (null !== $options) { - $this->setOptions($options); - } - } - - /** - * Configure the autoloader - * - * Proxies to {@link registerAutoloadMaps()}. - * - * @param array|Traversable $options - * @return ClassMapAutoloader - */ - public function setOptions($options) - { - $this->registerAutoloadMaps($options); - return $this; - } - - /** - * Register an autoload map - * - * An autoload map may be either an associative array, or a file returning - * an associative array. - * - * An autoload map should be an associative array containing - * classname/file pairs. - * - * @param string|array $map - * @throws Exception\InvalidArgumentException - * @return ClassMapAutoloader - */ - public function registerAutoloadMap($map) - { - if (is_string($map)) { - $location = $map; - if ($this === ($map = $this->loadMapFromFile($location))) { - return $this; - } - } - - if (! is_array($map)) { - require_once __DIR__ . '/Exception/InvalidArgumentException.php'; - throw new Exception\InvalidArgumentException(sprintf( - 'Map file provided does not return a map. Map file: "%s"', - isset($location) && is_string($location) ? $location : 'unexpected type: ' . gettype($map) - )); - } - - $this->map = $map + $this->map; - - if (isset($location)) { - $this->mapsLoaded[] = $location; - } - - return $this; - } - - /** - * Register many autoload maps at once - * - * @param array $locations - * @throws Exception\InvalidArgumentException - * @return ClassMapAutoloader - */ - public function registerAutoloadMaps($locations) - { - if (! is_array($locations) && ! $locations instanceof Traversable) { - require_once __DIR__ . '/Exception/InvalidArgumentException.php'; - throw new Exception\InvalidArgumentException('Map list must be an array or implement Traversable'); - } - foreach ($locations as $location) { - $this->registerAutoloadMap($location); - } - return $this; - } - - /** - * Retrieve current autoload map - * - * @return array - */ - public function getAutoloadMap() - { - return $this->map; - } - - /** - * {@inheritDoc} - */ - public function autoload($class) - { - if (isset($this->map[$class])) { - require_once $this->map[$class]; - - return $class; - } - - return false; - } - - /** - * Register the autoloader with spl_autoload registry - * - * @return void - */ - public function register() - { - spl_autoload_register([$this, 'autoload'], true, true); - } - - /** - * Load a map from a file - * - * If the map has been previously loaded, returns the current instance; - * otherwise, returns whatever was returned by calling include() on the - * location. - * - * @param string $location - * @return ClassMapAutoloader|mixed - * @throws Exception\InvalidArgumentException For nonexistent locations. - */ - protected function loadMapFromFile($location) - { - if (! file_exists($location)) { - require_once __DIR__ . '/Exception/InvalidArgumentException.php'; - throw new Exception\InvalidArgumentException(sprintf( - 'Map file provided does not exist. Map file: "%s"', - is_string($location) ? $location : 'unexpected type: ' . gettype($location) - )); - } - - if (! $path = static::realPharPath($location)) { - $path = realpath($location); - } - - if (in_array($path, $this->mapsLoaded)) { - // Already loaded this map - return $this; - } - - return include $path; - } - - /** - * Resolve the real_path() to a file within a phar. - * - * @see https://bugs.php.net/bug.php?id=52769 - * - * @param string $path - * @return string - */ - public static function realPharPath($path) - { - if (! preg_match('|^phar:(/{2,3})|', $path, $match)) { - return; - } - - $prefixLength = 5 + strlen($match[1]); - $parts = explode('/', str_replace(['/', '\\'], '/', substr($path, $prefixLength))); - $parts = array_values(array_filter($parts, function ($p) { - return $p !== '' && $p !== '.'; - })); - - array_walk($parts, function ($value, $key) use (&$parts) { - if ($value === '..') { - unset($parts[$key], $parts[$key - 1]); - $parts = array_values($parts); - } - }); - - if (file_exists($realPath = str_pad('phar:', $prefixLength, '/') . implode('/', $parts))) { - return $realPath; - } - } -} diff --git a/lib/laminas/laminas-loader/src/Exception/BadMethodCallException.php b/lib/laminas/laminas-loader/src/Exception/BadMethodCallException.php deleted file mode 100644 index 98f08aa7d..000000000 --- a/lib/laminas/laminas-loader/src/Exception/BadMethodCallException.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php - -namespace Laminas\Loader\Exception; - -require_once __DIR__ . '/ExceptionInterface.php'; - -class BadMethodCallException extends \BadMethodCallException implements - ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-loader/src/Exception/DomainException.php b/lib/laminas/laminas-loader/src/Exception/DomainException.php deleted file mode 100644 index fa72384f6..000000000 --- a/lib/laminas/laminas-loader/src/Exception/DomainException.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -namespace Laminas\Loader\Exception; - -require_once __DIR__ . '/ExceptionInterface.php'; - -class DomainException extends \DomainException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-loader/src/Exception/ExceptionInterface.php b/lib/laminas/laminas-loader/src/Exception/ExceptionInterface.php deleted file mode 100644 index 32d6d7289..000000000 --- a/lib/laminas/laminas-loader/src/Exception/ExceptionInterface.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace Laminas\Loader\Exception; - -interface ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-loader/src/Exception/InvalidArgumentException.php b/lib/laminas/laminas-loader/src/Exception/InvalidArgumentException.php deleted file mode 100644 index b2caabfb6..000000000 --- a/lib/laminas/laminas-loader/src/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -namespace Laminas\Loader\Exception; - -require_once __DIR__ . '/ExceptionInterface.php'; - -class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-loader/src/Exception/InvalidPathException.php b/lib/laminas/laminas-loader/src/Exception/InvalidPathException.php deleted file mode 100644 index 87123820b..000000000 --- a/lib/laminas/laminas-loader/src/Exception/InvalidPathException.php +++ /dev/null @@ -1,11 +0,0 @@ -<?php - -namespace Laminas\Loader\Exception; - -use Exception; - -require_once __DIR__ . '/ExceptionInterface.php'; - -class InvalidPathException extends Exception implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-loader/src/Exception/MissingResourceNamespaceException.php b/lib/laminas/laminas-loader/src/Exception/MissingResourceNamespaceException.php deleted file mode 100644 index 8f4f5041f..000000000 --- a/lib/laminas/laminas-loader/src/Exception/MissingResourceNamespaceException.php +++ /dev/null @@ -1,11 +0,0 @@ -<?php - -namespace Laminas\Loader\Exception; - -use Exception; - -require_once __DIR__ . '/ExceptionInterface.php'; - -class MissingResourceNamespaceException extends Exception implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-loader/src/Exception/PluginLoaderException.php b/lib/laminas/laminas-loader/src/Exception/PluginLoaderException.php deleted file mode 100644 index da6d652d1..000000000 --- a/lib/laminas/laminas-loader/src/Exception/PluginLoaderException.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -namespace Laminas\Loader\Exception; - -require_once __DIR__ . '/DomainException.php'; - -/** - * Plugin class loader exceptions - */ -class PluginLoaderException extends DomainException -{ -} diff --git a/lib/laminas/laminas-loader/src/Exception/RuntimeException.php b/lib/laminas/laminas-loader/src/Exception/RuntimeException.php deleted file mode 100644 index 4f542d327..000000000 --- a/lib/laminas/laminas-loader/src/Exception/RuntimeException.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -namespace Laminas\Loader\Exception; - -require_once __DIR__ . '/ExceptionInterface.php'; - -class RuntimeException extends \RuntimeException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-loader/src/Exception/SecurityException.php b/lib/laminas/laminas-loader/src/Exception/SecurityException.php deleted file mode 100644 index 9184c36df..000000000 --- a/lib/laminas/laminas-loader/src/Exception/SecurityException.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -namespace Laminas\Loader\Exception; - -require_once __DIR__ . '/DomainException.php'; - -class SecurityException extends DomainException -{ -} diff --git a/lib/laminas/laminas-loader/src/ModuleAutoloader.php b/lib/laminas/laminas-loader/src/ModuleAutoloader.php deleted file mode 100644 index d4dfef840..000000000 --- a/lib/laminas/laminas-loader/src/ModuleAutoloader.php +++ /dev/null @@ -1,445 +0,0 @@ -<?php - -namespace Laminas\Loader; - -// Grab SplAutoloader interface -require_once __DIR__ . '/SplAutoloader.php'; - -use GlobIterator; -use InvalidArgumentException; -use Phar; -use PharFileInfo; -use SplFileInfo; -use Traversable; -use function array_map; -use function class_exists; -use function count; -use function extension_loaded; -use function getcwd; -use function gettype; -use function implode; -use function in_array; -use function is_array; -use function is_string; -use function pathinfo; -use function preg_match; -use function realpath; -use function rtrim; -use function spl_autoload_register; -use function spl_autoload_unregister; -use function sprintf; -use function str_replace; -use function strpos; -use function substr; -use const DIRECTORY_SEPARATOR; - -class ModuleAutoloader implements SplAutoloader -{ - /** @var array An array of module paths to scan */ - protected $paths = []; - - /** @var array An array of modulename => path */ - protected $explicitPaths = []; - - /** @var array An array of namespaceName => namespacePath */ - protected $namespacedPaths = []; - - /** @var string Will contain the absolute phar:// path to the executable when packaged as phar file */ - protected $pharBasePath = ""; - - /** @var array An array of supported phar extensions (filled on constructor) */ - protected $pharExtensions = []; - - /** @var array An array of module classes to their containing files */ - protected $moduleClassMap = []; - - /** - * Constructor - * - * Allow configuration of the autoloader via the constructor. - * - * @param null|array|Traversable $options - */ - public function __construct($options = null) - { - if (extension_loaded('phar')) { - $this->pharBasePath = Phar::running(true); - $this->pharExtensions = [ - 'phar', - 'phar.tar', - 'tar', - ]; - - // ext/zlib enabled -> phar can read gzip & zip compressed files - if (extension_loaded('zlib')) { - $this->pharExtensions[] = 'phar.gz'; - $this->pharExtensions[] = 'phar.tar.gz'; - $this->pharExtensions[] = 'tar.gz'; - - $this->pharExtensions[] = 'phar.zip'; - $this->pharExtensions[] = 'zip'; - } - - // ext/bzip2 enabled -> phar can read bz2 compressed files - if (extension_loaded('bzip2')) { - $this->pharExtensions[] = 'phar.bz2'; - $this->pharExtensions[] = 'phar.tar.bz2'; - $this->pharExtensions[] = 'tar.bz2'; - } - } - - if (null !== $options) { - $this->setOptions($options); - } - } - - /** - * Configure the autoloader - * - * In most cases, $options should be either an associative array or - * Traversable object. - * - * @param array|Traversable $options - * @return ModuleAutoloader - */ - public function setOptions($options) - { - $this->registerPaths($options); - return $this; - } - - /** - * Retrieves the class map for all loaded modules. - * - * @return array - */ - public function getModuleClassMap() - { - return $this->moduleClassMap; - } - - /** - * Sets the class map used to speed up the module autoloading. - * - * @param array $classmap - * @return ModuleAutoloader - */ - public function setModuleClassMap(array $classmap) - { - $this->moduleClassMap = $classmap; - - return $this; - } - - /** - * Autoload a class - * - * @param string $class - * @return mixed - * False [if unable to load $class] - * get_class($class) [if $class is successfully loaded] - */ - public function autoload($class) - { - // Limit scope of this autoloader - if (substr($class, -7) !== '\Module') { - return false; - } - - if (isset($this->moduleClassMap[$class])) { - require_once $this->moduleClassMap[$class]; - return $class; - } - - $moduleName = substr($class, 0, -7); - if (isset($this->explicitPaths[$moduleName])) { - $classLoaded = $this->loadModuleFromDir($this->explicitPaths[$moduleName], $class); - if ($classLoaded) { - return $classLoaded; - } - - $classLoaded = $this->loadModuleFromPhar($this->explicitPaths[$moduleName], $class); - if ($classLoaded) { - return $classLoaded; - } - } - - if (count($this->namespacedPaths) >= 1) { - foreach ($this->namespacedPaths as $namespace => $path) { - if (false === strpos($moduleName, $namespace)) { - continue; - } - - $moduleNameBuffer = str_replace($namespace . "\\", "", $moduleName); - $path .= DIRECTORY_SEPARATOR . $moduleNameBuffer . DIRECTORY_SEPARATOR; - - $classLoaded = $this->loadModuleFromDir($path, $class); - if ($classLoaded) { - return $classLoaded; - } - - $classLoaded = $this->loadModuleFromPhar($path, $class); - if ($classLoaded) { - return $classLoaded; - } - } - } - - $moduleClassPath = str_replace('\\', DIRECTORY_SEPARATOR, $moduleName); - - $pharSuffixPattern = null; - if ($this->pharExtensions) { - $pharSuffixPattern = '(' . implode('|', array_map('preg_quote', $this->pharExtensions)) . ')'; - } - - foreach ($this->paths as $path) { - $path .= $moduleClassPath; - - if ($path === '.' || substr($path, 0, 2) === './' || substr($path, 0, 2) === '.\\') { - if (! $basePath = $this->pharBasePath) { - $basePath = realpath('.'); - } - - if (false === $basePath) { - $basePath = getcwd(); - } - - $path = rtrim($basePath, '\/\\') . substr($path, 1); - } - - $classLoaded = $this->loadModuleFromDir($path, $class); - if ($classLoaded) { - return $classLoaded; - } - - // No directory with Module.php, searching for phars - if ($pharSuffixPattern) { - foreach (new GlobIterator($path . '.*') as $entry) { - if ($entry->isDir()) { - continue; - } - - if (! preg_match('#.+\.' . $pharSuffixPattern . '$#', $entry->getPathname())) { - continue; - } - - $classLoaded = $this->loadModuleFromPhar($entry->getPathname(), $class); - if ($classLoaded) { - return $classLoaded; - } - } - } - } - - return false; - } - - /** - * loadModuleFromDir - * - * @param string $dirPath - * @param string $class - * @return mixed - * False [if unable to load $class] - * get_class($class) [if $class is successfully loaded] - */ - protected function loadModuleFromDir($dirPath, $class) - { - $modulePath = $dirPath . '/Module.php'; - if (substr($modulePath, 0, 7) === 'phar://') { - $file = new PharFileInfo($modulePath); - } else { - $file = new SplFileInfo($modulePath); - } - - if ($file->isReadable() && $file->isFile()) { - // Found directory with Module.php in it - $absModulePath = $this->pharBasePath ? (string) $file : $file->getRealPath(); - require_once $absModulePath; - if (class_exists($class)) { - $this->moduleClassMap[$class] = $absModulePath; - return $class; - } - } - return false; - } - - /** - * loadModuleFromPhar - * - * @param string $pharPath - * @param string $class - * @return mixed - * False [if unable to load $class] - * get_class($class) [if $class is successfully loaded] - */ - protected function loadModuleFromPhar($pharPath, $class) - { - $pharPath = static::normalizePath($pharPath, false); - $file = new SplFileInfo($pharPath); - if (! $file->isReadable() || ! $file->isFile()) { - return false; - } - - $fileRealPath = $file->getRealPath(); - - // Phase 0: Check for executable phar with Module class in stub - if (strpos($fileRealPath, '.phar') !== false) { - // First see if the stub makes the Module class available - require_once $fileRealPath; - if (class_exists($class)) { - $this->moduleClassMap[$class] = $fileRealPath; - return $class; - } - } - - // Phase 1: Not executable phar, no stub, or stub did not provide Module class; try Module.php directly - $moduleClassFile = 'phar://' . $fileRealPath . '/Module.php'; - $moduleFile = new SplFileInfo($moduleClassFile); - if ($moduleFile->isReadable() && $moduleFile->isFile()) { - require_once $moduleClassFile; - if (class_exists($class)) { - $this->moduleClassMap[$class] = $moduleClassFile; - return $class; - } - } - - // Phase 2: Check for nested module directory within archive - // Checks for /path/to/MyModule.tar/MyModule/Module.php - // (shell-integrated zip/tar utilities wrap directories like this) - $pharBaseName = $this->pharFileToModuleName($fileRealPath); - $moduleClassFile = 'phar://' . $fileRealPath . '/' . $pharBaseName . '/Module.php'; - $moduleFile = new SplFileInfo($moduleClassFile); - if ($moduleFile->isReadable() && $moduleFile->isFile()) { - require_once $moduleClassFile; - if (class_exists($class)) { - $this->moduleClassMap[$class] = $moduleClassFile; - return $class; - } - } - - return false; - } - - /** - * Register the autoloader with spl_autoload registry - * - * @return void - */ - public function register() - { - spl_autoload_register([$this, 'autoload']); - } - - /** - * Unregister the autoloader with spl_autoload registry - * - * @return void - */ - public function unregister() - { - spl_autoload_unregister([$this, 'autoload']); - } - - /** - * registerPaths - * - * @param array|Traversable $paths - * @throws InvalidArgumentException - * @return ModuleAutoloader - */ - public function registerPaths($paths) - { - if (! is_array($paths) && ! $paths instanceof Traversable) { - require_once __DIR__ . '/Exception/InvalidArgumentException.php'; - throw new Exception\InvalidArgumentException( - 'Parameter to \\Laminas\\Loader\\ModuleAutoloader\'s ' - . 'registerPaths method must be an array or ' - . 'implement the Traversable interface' - ); - } - - foreach ($paths as $module => $path) { - if (is_string($module)) { - $this->registerPath($path, $module); - } else { - $this->registerPath($path); - } - } - - return $this; - } - - /** - * registerPath - * - * @param string $path - * @param bool|string $moduleName - * @throws InvalidArgumentException - * @return ModuleAutoloader - */ - public function registerPath($path, $moduleName = false) - { - if (! is_string($path)) { - require_once __DIR__ . '/Exception/InvalidArgumentException.php'; - throw new Exception\InvalidArgumentException(sprintf( - 'Invalid path provided; must be a string, received %s', - gettype($path) - )); - } - if ($moduleName) { - if (in_array(substr($moduleName, -2), ['\\*', '\\%'])) { - $this->namespacedPaths[substr($moduleName, 0, -2)] = static::normalizePath($path); - } else { - $this->explicitPaths[$moduleName] = static::normalizePath($path); - } - } else { - $this->paths[] = static::normalizePath($path); - } - return $this; - } - - /** - * getPaths - * - * This is primarily for unit testing, but could have other uses. - * - * @return array - */ - public function getPaths() - { - return $this->paths; - } - - /** - * Returns the base module name from the path to a phar - * - * @param string $pharPath - * @return string - */ - protected function pharFileToModuleName($pharPath) - { - do { - $pathinfo = pathinfo($pharPath); - $pharPath = $pathinfo['filename']; - } while (isset($pathinfo['extension'])); - return $pathinfo['filename']; - } - - /** - * Normalize a path for insertion in the stack - * - * @param string $path - * @param bool $trailingSlash Whether trailing slash should be included - * @return string - */ - public static function normalizePath($path, $trailingSlash = true) - { - $path = rtrim($path, '/'); - $path = rtrim($path, '\\'); - if ($trailingSlash) { - $path .= DIRECTORY_SEPARATOR; - } - return $path; - } -} diff --git a/lib/laminas/laminas-loader/src/PluginClassLoader.php b/lib/laminas/laminas-loader/src/PluginClassLoader.php deleted file mode 100644 index 0743cc7ae..000000000 --- a/lib/laminas/laminas-loader/src/PluginClassLoader.php +++ /dev/null @@ -1,223 +0,0 @@ -<?php // phpcs:disable SlevomatCodingStandard.Namespaces.UnusedUses.UnusedUse - -namespace Laminas\Loader; - -use ArrayIterator; -use IteratorAggregate; -use ReturnTypeWillChange; -use Traversable; - -use function array_key_exists; -use function class_exists; -use function is_array; -use function is_int; -use function is_numeric; -use function is_object; -use function is_string; -use function strtolower; - -/** - * Plugin class locator interface - */ -class PluginClassLoader implements PluginClassLocator -{ - /** - * List of plugin name => class name pairs - * - * @var array - */ - protected $plugins = []; - - /** - * Static map allow global seeding of plugin loader - * - * @var array - */ - protected static $staticMap = []; - - /** - * Constructor - * - * @param null|array|Traversable $map If provided, seeds the loader with a map - */ - public function __construct($map = null) - { - // Merge in static overrides - if (! empty(static::$staticMap)) { - $this->registerPlugins(static::$staticMap); - } - - // Merge in constructor arguments - if ($map !== null) { - $this->registerPlugins($map); - } - } - - /** - * Add a static map of plugins - * - * A null value will clear the static map. - * - * @param null|array|Traversable $map - * @throws Exception\InvalidArgumentException - * @return void - */ - public static function addStaticMap($map) - { - if (null === $map) { - static::$staticMap = []; - return; - } - - if (! is_array($map) && ! $map instanceof Traversable) { - throw new Exception\InvalidArgumentException('Expects an array or Traversable object'); - } - foreach ($map as $key => $value) { - static::$staticMap[$key] = $value; - } - } - - /** - * Register a class to a given short name - * - * @param string $shortName - * @param string $className - * @return PluginClassLoader - */ - public function registerPlugin($shortName, $className) - { - $this->plugins[strtolower($shortName)] = $className; - return $this; - } - - /** - * Register many plugins at once - * - * If $map is a string, assumes that the map is the class name of a - * Traversable object (likely a ShortNameLocator); it will then instantiate - * this class and use it to register plugins. - * - * If $map is an array or Traversable object, it will iterate it to - * register plugin names/classes. - * - * For all other arguments, or if the string $map is not a class or not a - * Traversable class, an exception will be raised. - * - * @param string|array|Traversable $map - * @return PluginClassLoader - * @throws Exception\InvalidArgumentException - */ - public function registerPlugins($map) - { - if (is_string($map)) { - if (! class_exists($map)) { - throw new Exception\InvalidArgumentException('Map class provided is invalid'); - } - $map = new $map(); - } - if (is_array($map)) { - $map = new ArrayIterator($map); - } - if (! $map instanceof Traversable) { - throw new Exception\InvalidArgumentException('Map provided is invalid; must be traversable'); - } - - // iterator_apply doesn't work as expected with IteratorAggregate - if ($map instanceof IteratorAggregate) { - $map = $map->getIterator(); - } - - foreach ($map as $name => $class) { - if (is_int($name) || is_numeric($name)) { - if (! is_object($class) && class_exists($class)) { - $class = new $class(); - } - - if ($class instanceof Traversable) { - $this->registerPlugins($class); - continue; - } - } - - $this->registerPlugin($name, $class); - } - - return $this; - } - - /** - * Unregister a short name lookup - * - * @param mixed $shortName - * @return PluginClassLoader - */ - public function unregisterPlugin($shortName) - { - $lookup = strtolower($shortName); - if (array_key_exists($lookup, $this->plugins)) { - unset($this->plugins[$lookup]); - } - return $this; - } - - /** - * Get a list of all registered plugins - * - * @return array|Traversable - */ - public function getRegisteredPlugins() - { - return $this->plugins; - } - - /** - * Whether or not a plugin by a specific name has been registered - * - * @param string $name - * @return bool - */ - public function isLoaded($name) - { - $lookup = strtolower($name); - return isset($this->plugins[$lookup]); - } - - /** - * Return full class name for a named helper - * - * @param string $name - * @return string|false - */ - public function getClassName($name) - { - return $this->load($name); - } - - /** - * Load a helper via the name provided - * - * @param string $name - * @return string|false - */ - public function load($name) - { - if (! $this->isLoaded($name)) { - return false; - } - return $this->plugins[strtolower($name)]; - } - - /** - * Defined by IteratorAggregate - * - * Returns an instance of ArrayIterator, containing a map of - * all plugins - * - * @return ArrayIterator - */ - #[ReturnTypeWillChange] - public function getIterator() - { - return new ArrayIterator($this->plugins); - } -} diff --git a/lib/laminas/laminas-loader/src/PluginClassLocator.php b/lib/laminas/laminas-loader/src/PluginClassLocator.php deleted file mode 100644 index 181b88ef8..000000000 --- a/lib/laminas/laminas-loader/src/PluginClassLocator.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php // phpcs:disable WebimpressCodingStandard.NamingConventions.Interface.Suffix - -namespace Laminas\Loader; - -use IteratorAggregate; -use Traversable; - -/** - * Plugin class locator interface - */ -interface PluginClassLocator extends ShortNameLocator, IteratorAggregate -{ - /** - * Register a class to a given short name - * - * @param string $shortName - * @param string $className - * @return PluginClassLocator - */ - public function registerPlugin($shortName, $className); - - /** - * Unregister a short name lookup - * - * @param mixed $shortName - * @return void - */ - public function unregisterPlugin($shortName); - - /** - * Get a list of all registered plugins - * - * @return array|Traversable - */ - public function getRegisteredPlugins(); -} diff --git a/lib/laminas/laminas-loader/src/ShortNameLocator.php b/lib/laminas/laminas-loader/src/ShortNameLocator.php deleted file mode 100644 index 3c62f0384..000000000 --- a/lib/laminas/laminas-loader/src/ShortNameLocator.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php // phpcs:disable WebimpressCodingStandard.NamingConventions.Interface.Suffix - -namespace Laminas\Loader; - -/** - * Short name locator interface - */ -interface ShortNameLocator -{ - /** - * Whether or not a Helper by a specific name - * - * @param string $name - * @return bool - */ - public function isLoaded($name); - - /** - * Return full class name for a named helper - * - * @param string $name - * @return string - */ - public function getClassName($name); - - /** - * Load a helper via the name provided - * - * @param string $name - * @return string - */ - public function load($name); -} diff --git a/lib/laminas/laminas-loader/src/SplAutoloader.php b/lib/laminas/laminas-loader/src/SplAutoloader.php deleted file mode 100644 index 22ab87b35..000000000 --- a/lib/laminas/laminas-loader/src/SplAutoloader.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php // phpcs:disable WebimpressCodingStandard.NamingConventions.Interface.Suffix - -namespace Laminas\Loader; - -use Traversable; - -use function interface_exists; - -if (interface_exists(SplAutoloader::class)) { - return; -} - -/** - * Defines an interface for classes that may register with the spl_autoload - * registry - */ -interface SplAutoloader -{ - /** - * Constructor - * - * Allow configuration of the autoloader via the constructor. - * - * @param null|array|Traversable $options - */ - public function __construct($options = null); - - /** - * Configure the autoloader - * - * In most cases, $options should be either an associative array or - * Traversable object. - * - * @param array|Traversable $options - * @return SplAutoloader - */ - public function setOptions($options); - - /** - * Autoload a class - * - * @param string $class - * @return mixed - * False [if unable to load $class] - * get_class($class) [if $class is successfully loaded] - */ - public function autoload($class); - - /** - * Register the autoloader with spl_autoload registry - * - * Typically, the body of this will simply be: - * <code> - * spl_autoload_register(array($this, 'autoload')); - * </code> - * - * @return void - */ - public function register(); -} diff --git a/lib/laminas/laminas-loader/src/StandardAutoloader.php b/lib/laminas/laminas-loader/src/StandardAutoloader.php deleted file mode 100644 index 6d468187b..000000000 --- a/lib/laminas/laminas-loader/src/StandardAutoloader.php +++ /dev/null @@ -1,332 +0,0 @@ -<?php - -namespace Laminas\Loader; - -use Traversable; - -use function dirname; -use function file_exists; -use function in_array; -use function is_array; -use function preg_match; -use function rtrim; -use function spl_autoload_register; -use function str_replace; -use function stream_resolve_include_path; -use function strlen; -use function strpos; -use function substr; - -use const DIRECTORY_SEPARATOR; - -// Grab SplAutoloader interface -require_once __DIR__ . '/SplAutoloader.php'; - -/** - * PSR-0 compliant autoloader - * - * Allows autoloading both namespaced and vendor-prefixed classes. Class - * lookups are performed on the filesystem. If a class file for the referenced - * class is not found, a PHP warning will be raised by include(). - */ -class StandardAutoloader implements SplAutoloader -{ - public const NS_SEPARATOR = '\\'; - public const PREFIX_SEPARATOR = '_'; - public const LOAD_NS = 'namespaces'; - public const LOAD_PREFIX = 'prefixes'; - public const ACT_AS_FALLBACK = 'fallback_autoloader'; - /** @deprecated Use AUTOREGISTER_LAMINAS instead */ - public const AUTOREGISTER_ZF = 'autoregister_laminas'; - public const AUTOREGISTER_LAMINAS = 'autoregister_laminas'; - - /** @var array Namespace/directory pairs to search; Laminas library added by default */ - protected $namespaces = []; - - /** @var array Prefix/directory pairs to search */ - protected $prefixes = []; - - /** @var bool Whether or not the autoloader should also act as a fallback autoloader */ - protected $fallbackAutoloaderFlag = false; - - /** - * Constructor - * - * @param null|array|Traversable $options - */ - public function __construct($options = null) - { - if (null !== $options) { - $this->setOptions($options); - } - } - - /** - * Configure autoloader - * - * Allows specifying both "namespace" and "prefix" pairs, using the - * following structure: - * <code> - * array( - * 'namespaces' => array( - * 'Laminas' => '/path/to/Laminas/library', - * 'Doctrine' => '/path/to/Doctrine/library', - * ), - * 'prefixes' => array( - * 'Phly_' => '/path/to/Phly/library', - * ), - * 'fallback_autoloader' => true, - * ) - * </code> - * - * @param array|Traversable $options - * @throws Exception\InvalidArgumentException - * @return StandardAutoloader - */ - public function setOptions($options) - { - if (! is_array($options) && ! $options instanceof Traversable) { - require_once __DIR__ . '/Exception/InvalidArgumentException.php'; - throw new Exception\InvalidArgumentException('Options must be either an array or Traversable'); - } - - foreach ($options as $type => $pairs) { - switch ($type) { - case self::AUTOREGISTER_LAMINAS: - if ($pairs) { - $this->registerNamespace('Laminas', dirname(__DIR__)); - } - break; - case self::LOAD_NS: - if (is_array($pairs) || $pairs instanceof Traversable) { - $this->registerNamespaces($pairs); - } - break; - case self::LOAD_PREFIX: - if (is_array($pairs) || $pairs instanceof Traversable) { - $this->registerPrefixes($pairs); - } - break; - case self::ACT_AS_FALLBACK: - $this->setFallbackAutoloader($pairs); - break; - default: - // ignore - } - } - return $this; - } - - /** - * Set flag indicating fallback autoloader status - * - * @param bool $flag - * @return StandardAutoloader - */ - public function setFallbackAutoloader($flag) - { - $this->fallbackAutoloaderFlag = (bool) $flag; - return $this; - } - - /** - * Is this autoloader acting as a fallback autoloader? - * - * @return bool - */ - public function isFallbackAutoloader() - { - return $this->fallbackAutoloaderFlag; - } - - /** - * Register a namespace/directory pair - * - * @param string $namespace - * @param string $directory - * @return StandardAutoloader - */ - public function registerNamespace($namespace, $directory) - { - $namespace = rtrim($namespace, self::NS_SEPARATOR) . self::NS_SEPARATOR; - $this->namespaces[$namespace] = $this->normalizeDirectory($directory); - return $this; - } - - /** - * Register many namespace/directory pairs at once - * - * @param array $namespaces - * @throws Exception\InvalidArgumentException - * @return StandardAutoloader - */ - public function registerNamespaces($namespaces) - { - if (! is_array($namespaces) && ! $namespaces instanceof Traversable) { - require_once __DIR__ . '/Exception/InvalidArgumentException.php'; - throw new Exception\InvalidArgumentException('Namespace pairs must be either an array or Traversable'); - } - - foreach ($namespaces as $namespace => $directory) { - $this->registerNamespace($namespace, $directory); - } - return $this; - } - - /** - * Register a prefix/directory pair - * - * @param string $prefix - * @param string $directory - * @return StandardAutoloader - */ - public function registerPrefix($prefix, $directory) - { - $prefix = rtrim($prefix, self::PREFIX_SEPARATOR) . self::PREFIX_SEPARATOR; - $this->prefixes[$prefix] = $this->normalizeDirectory($directory); - return $this; - } - - /** - * Register many namespace/directory pairs at once - * - * @param array $prefixes - * @throws Exception\InvalidArgumentException - * @return StandardAutoloader - */ - public function registerPrefixes($prefixes) - { - if (! is_array($prefixes) && ! $prefixes instanceof Traversable) { - require_once __DIR__ . '/Exception/InvalidArgumentException.php'; - throw new Exception\InvalidArgumentException('Prefix pairs must be either an array or Traversable'); - } - - foreach ($prefixes as $prefix => $directory) { - $this->registerPrefix($prefix, $directory); - } - return $this; - } - - /** - * Defined by Autoloadable; autoload a class - * - * @param string $class - * @return false|string - */ - public function autoload($class) - { - $isFallback = $this->isFallbackAutoloader(); - if (false !== strpos($class, self::NS_SEPARATOR)) { - if ($this->loadClass($class, self::LOAD_NS)) { - return $class; - } elseif ($isFallback) { - return $this->loadClass($class, self::ACT_AS_FALLBACK); - } - return false; - } - if (false !== strpos($class, self::PREFIX_SEPARATOR)) { - if ($this->loadClass($class, self::LOAD_PREFIX)) { - return $class; - } elseif ($isFallback) { - return $this->loadClass($class, self::ACT_AS_FALLBACK); - } - return false; - } - if ($isFallback) { - return $this->loadClass($class, self::ACT_AS_FALLBACK); - } - return false; - } - - /** - * Register the autoloader with spl_autoload - * - * @return void - */ - public function register() - { - spl_autoload_register([$this, 'autoload']); - } - - /** - * Transform the class name to a filename - * - * @param string $class - * @param string $directory - * @return string - */ - protected function transformClassNameToFilename($class, $directory) - { - // $class may contain a namespace portion, in which case we need - // to preserve any underscores in that portion. - $matches = []; - preg_match('/(?P<namespace>.+\\\)?(?P<class>[^\\\]+$)/', $class, $matches); - - $class = $matches['class'] ?? ''; - $namespace = $matches['namespace'] ?? ''; - - return $directory - . str_replace(self::NS_SEPARATOR, '/', $namespace) - . str_replace(self::PREFIX_SEPARATOR, '/', $class) - . '.php'; - } - - /** - * Load a class, based on its type (namespaced or prefixed) - * - * @param string $class - * @param string $type - * @return bool|string - * @throws Exception\InvalidArgumentException - */ - protected function loadClass($class, $type) - { - if (! in_array($type, [self::LOAD_NS, self::LOAD_PREFIX, self::ACT_AS_FALLBACK])) { - require_once __DIR__ . '/Exception/InvalidArgumentException.php'; - throw new Exception\InvalidArgumentException(); - } - - // Fallback autoloading - if ($type === self::ACT_AS_FALLBACK) { - // create filename - $filename = $this->transformClassNameToFilename($class, ''); - $resolvedName = stream_resolve_include_path($filename); - if ($resolvedName !== false) { - return include $resolvedName; - } - return false; - } - - // Namespace and/or prefix autoloading - foreach ($this->$type as $leader => $path) { - if (0 === strpos($class, $leader)) { - // Trim off leader (namespace or prefix) - $trimmedClass = substr($class, strlen($leader)); - - // create filename - $filename = $this->transformClassNameToFilename($trimmedClass, $path); - if (file_exists($filename)) { - return include $filename; - } - } - } - return false; - } - - /** - * Normalize the directory to include a trailing directory separator - * - * @param string $directory - * @return string - */ - protected function normalizeDirectory($directory) - { - $last = $directory[strlen($directory) - 1]; - if (in_array($last, ['/', '\\'])) { - $directory[strlen($directory) - 1] = DIRECTORY_SEPARATOR; - return $directory; - } - $directory .= DIRECTORY_SEPARATOR; - return $directory; - } -} diff --git a/lib/laminas/laminas-mail/.laminas-ci.json b/lib/laminas/laminas-mail/.laminas-ci.json deleted file mode 100644 index bce3fa21b..000000000 --- a/lib/laminas/laminas-mail/.laminas-ci.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "ignore_php_platform_requirements": { - "8.1": true - } -} diff --git a/lib/laminas/laminas-mail/.laminas-ci/pre-run.sh b/lib/laminas/laminas-mail/.laminas-ci/pre-run.sh deleted file mode 100644 index eed79a3b2..000000000 --- a/lib/laminas/laminas-mail/.laminas-ci/pre-run.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -INTL_EXTENSION=$(php -r 'echo sprintf("php%s.%s-intl",PHP_MAJOR_VERSION,PHP_MINOR_VERSION);') - -echo -e "Removing $INTL_EXTENSION extension:\n" -sudo apt remove "$INTL_EXTENSION" -y - -echo -e "Cleaning up:\n" -sudo apt autoclean && sudo apt autoremove - -echo -e "Installed extensions:\n" -/usr/local/bin/php-extensions-with-version.php \ No newline at end of file diff --git a/lib/laminas/laminas-mail/COPYRIGHT.md b/lib/laminas/laminas-mail/COPYRIGHT.md deleted file mode 100644 index 0a8cccc06..000000000 --- a/lib/laminas/laminas-mail/COPYRIGHT.md +++ /dev/null @@ -1 +0,0 @@ -Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/) diff --git a/lib/laminas/laminas-mail/LICENSE.md b/lib/laminas/laminas-mail/LICENSE.md deleted file mode 100644 index 10b40f142..000000000 --- a/lib/laminas/laminas-mail/LICENSE.md +++ /dev/null @@ -1,26 +0,0 @@ -Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -- Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -- Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -- Neither the name of Laminas Foundation nor the names of its contributors may - be used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/lib/laminas/laminas-mail/README.md b/lib/laminas/laminas-mail/README.md deleted file mode 100644 index 16e57f835..000000000 --- a/lib/laminas/laminas-mail/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# laminas-mail - -[![Build Status](https://github.com/laminas/laminas-mail/workflows/Continuous%20Integration/badge.svg)](https://github.com/laminas/laminas-mail/actions?query=workflow%3A"Continuous+Integration") - -`Laminas\Mail` provides generalized functionality to compose and send both text and -MIME-compliant multipart email messages. Mail can be sent with `Laminas\Mail` via -the `Mail\Transport\Sendmail`, `Mail\Transport\Smtp` or the `Mail\Transport\File` -transport. Of course, you can also implement your own transport by implementing -the `Mail\Transport\TransportInterface`. - -- File issues at https://github.com/laminas/laminas-mail/issues -- Documentation is at https://docs.laminas.dev/laminas-mail/ diff --git a/lib/laminas/laminas-mail/composer.json b/lib/laminas/laminas-mail/composer.json deleted file mode 100644 index 96074d234..000000000 --- a/lib/laminas/laminas-mail/composer.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "name": "laminas/laminas-mail", - "description": "Provides generalized functionality to compose and send both text and MIME-compliant multipart e-mail messages", - "keywords": [ - "laminas", - "mail" - ], - "homepage": "https://laminas.dev", - "license": "BSD-3-Clause", - "require": { - "php": "^7.3 || ~8.0.0 || ~8.1.0", - "ext-iconv": "*", - "laminas/laminas-loader": "^2.8", - "laminas/laminas-mime": "^2.9.1", - "laminas/laminas-stdlib": "^3.6", - "laminas/laminas-validator": "^2.15", - "symfony/polyfill-mbstring": "^1.12.0", - "webmozart/assert": "^1.10", - "symfony/polyfill-intl-idn": "^1.24.0" - }, - "conflict": { - "zendframework/zend-mail": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~1.0.0", - "laminas/laminas-crypt": "^2.6 || ^3.4", - "laminas/laminas-db": "^2.13.3", - "laminas/laminas-servicemanager": "^3.7", - "phpunit/phpunit": "^9.5.5", - "psalm/plugin-phpunit": "^0.15.1", - "symfony/process": "^5.3.7", - "vimeo/psalm": "^4.7" - }, - "suggest": { - "laminas/laminas-crypt": "Crammd5 support in SMTP Auth", - "laminas/laminas-servicemanager": "^2.7.10 || ^3.3.1 when using SMTP to deliver messages" - }, - "config": { - "sort-packages": true, - "allow-plugins": { - "composer/package-versions-deprecated": true - }, - "platform": { - "php": "7.3.99" - } - }, - "extra": { - "laminas": { - "component": "Laminas\\Mail", - "config-provider": "Laminas\\Mail\\ConfigProvider" - } - }, - "autoload": { - "psr-4": { - "Laminas\\Mail\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "LaminasTest\\Mail\\": "test/" - } - }, - "scripts": { - "check": [ - "@cs-check", - "@static-analysis", - "@test" - ], - "cs-check": "phpcs", - "cs-fix": "phpcbf", - "static-analysis": "psalm --shepherd --stats", - "test": "phpunit --colors=always", - "test-coverage": "phpunit --colors=always --coverage-clover clover.xml" - }, - "support": { - "issues": "https://github.com/laminas/laminas-mail/issues", - "forum": "https://discourse.laminas.dev", - "chat": "https://laminas.dev/chat", - "source": "https://github.com/laminas/laminas-mail", - "docs": "https://docs.laminas.dev/laminas-mail/", - "rss": "https://github.com/laminas/laminas-mail/releases.atom" - } -} diff --git a/lib/laminas/laminas-mail/composer.lock b/lib/laminas/laminas-mail/composer.lock deleted file mode 100644 index b6263984b..000000000 --- a/lib/laminas/laminas-mail/composer.lock +++ /dev/null @@ -1,4882 +0,0 @@ -{ - "_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": "c4e2858fd3753937b8ef20cfc5096601", - "packages": [ - { - "name": "container-interop/container-interop", - "version": "1.2.0", - "source": { - "type": "git", - "url": "https://github.com/container-interop/container-interop.git", - "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8", - "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8", - "shasum": "" - }, - "require": { - "psr/container": "^1.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Interop\\Container\\": "src/Interop/Container/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", - "homepage": "https://github.com/container-interop/container-interop", - "support": { - "issues": "https://github.com/container-interop/container-interop/issues", - "source": "https://github.com/container-interop/container-interop/tree/master" - }, - "abandoned": "psr/container", - "time": "2017-02-14T19:40:03+00:00" - }, - { - "name": "laminas/laminas-loader", - "version": "2.8.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-loader.git", - "reference": "d0589ec9dd48365fd95ad10d1c906efd7711c16b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-loader/zipball/d0589ec9dd48365fd95ad10d1c906efd7711c16b", - "reference": "d0589ec9dd48365fd95ad10d1c906efd7711c16b", - "shasum": "" - }, - "require": { - "php": "^7.3 || ~8.0.0 || ~8.1.0" - }, - "conflict": { - "zendframework/zend-loader": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~2.2.1", - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Laminas\\Loader\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Autoloading and plugin loading strategies", - "homepage": "https://laminas.dev", - "keywords": [ - "laminas", - "loader" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-loader/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-loader/issues", - "rss": "https://github.com/laminas/laminas-loader/releases.atom", - "source": "https://github.com/laminas/laminas-loader" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2021-09-02T18:30:53+00:00" - }, - { - "name": "laminas/laminas-mime", - "version": "2.9.1", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-mime.git", - "reference": "72d21a1b4bb7086d4a4d7058c0abca180b209184" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-mime/zipball/72d21a1b4bb7086d4a4d7058c0abca180b209184", - "reference": "72d21a1b4bb7086d4a4d7058c0abca180b209184", - "shasum": "" - }, - "require": { - "laminas/laminas-stdlib": "^2.7 || ^3.0", - "php": "^7.3 || ~8.0.0 || ~8.1.0" - }, - "conflict": { - "zendframework/zend-mime": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~2.2.1", - "laminas/laminas-mail": "^2.12", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "laminas/laminas-mail": "Laminas\\Mail component" - }, - "type": "library", - "autoload": { - "psr-4": { - "Laminas\\Mime\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Create and parse MIME messages and parts", - "homepage": "https://laminas.dev", - "keywords": [ - "laminas", - "mime" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-mime/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-mime/issues", - "rss": "https://github.com/laminas/laminas-mime/releases.atom", - "source": "https://github.com/laminas/laminas-mime" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2021-09-20T21:19:24+00:00" - }, - { - "name": "laminas/laminas-stdlib", - "version": "3.7.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-stdlib.git", - "reference": "cba75fad2053bb5dc8d3e7f5e62b61d75eecfaf1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/cba75fad2053bb5dc8d3e7f5e62b61d75eecfaf1", - "reference": "cba75fad2053bb5dc8d3e7f5e62b61d75eecfaf1", - "shasum": "" - }, - "require": { - "php": "^7.3 || ~8.0.0 || ~8.1.0" - }, - "conflict": { - "zendframework/zend-stdlib": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~2.3.0", - "phpbench/phpbench": "^1.0", - "phpunit/phpunit": "^9.3.7", - "psalm/plugin-phpunit": "^0.16.0", - "vimeo/psalm": "^4.7" - }, - "type": "library", - "autoload": { - "psr-4": { - "Laminas\\Stdlib\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "SPL extensions, array utilities, error handlers, and more", - "homepage": "https://laminas.dev", - "keywords": [ - "laminas", - "stdlib" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-stdlib/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-stdlib/issues", - "rss": "https://github.com/laminas/laminas-stdlib/releases.atom", - "source": "https://github.com/laminas/laminas-stdlib" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2022-01-10T11:18:55+00:00" - }, - { - "name": "laminas/laminas-validator", - "version": "2.15.1", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-validator.git", - "reference": "fbd87f30c0a27aaeeee8adb2f934c14fb6046c80" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-validator/zipball/fbd87f30c0a27aaeeee8adb2f934c14fb6046c80", - "reference": "fbd87f30c0a27aaeeee8adb2f934c14fb6046c80", - "shasum": "" - }, - "require": { - "container-interop/container-interop": "^1.1", - "laminas/laminas-stdlib": "^3.6", - "php": "^7.3 || ~8.0.0 || ~8.1.0" - }, - "conflict": { - "zendframework/zend-validator": "*" - }, - "require-dev": { - "laminas/laminas-cache": "^2.6.1", - "laminas/laminas-coding-standard": "~2.2.1", - "laminas/laminas-db": "^2.7", - "laminas/laminas-filter": "^2.6", - "laminas/laminas-http": "^2.14.2", - "laminas/laminas-i18n": "^2.6", - "laminas/laminas-math": "^2.6", - "laminas/laminas-servicemanager": "^2.7.11 || ^3.0.3", - "laminas/laminas-session": "^2.8", - "laminas/laminas-uri": "^2.7", - "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^9.5.5", - "psalm/plugin-phpunit": "^0.15.0", - "psr/http-client": "^1.0", - "psr/http-factory": "^1.0", - "psr/http-message": "^1.0", - "vimeo/psalm": "^4.3" - }, - "suggest": { - "laminas/laminas-db": "Laminas\\Db component, required by the (No)RecordExists validator", - "laminas/laminas-filter": "Laminas\\Filter component, required by the Digits validator", - "laminas/laminas-i18n": "Laminas\\I18n component to allow translation of validation error messages", - "laminas/laminas-i18n-resources": "Translations of validator messages", - "laminas/laminas-math": "Laminas\\Math component, required by the Csrf validator", - "laminas/laminas-servicemanager": "Laminas\\ServiceManager component to allow using the ValidatorPluginManager and validator chains", - "laminas/laminas-session": "Laminas\\Session component, ^2.8; required by the Csrf validator", - "laminas/laminas-uri": "Laminas\\Uri component, required by the Uri and Sitemap\\Loc validators", - "psr/http-message": "psr/http-message, required when validating PSR-7 UploadedFileInterface instances via the Upload and UploadFile validators" - }, - "type": "library", - "extra": { - "laminas": { - "component": "Laminas\\Validator", - "config-provider": "Laminas\\Validator\\ConfigProvider" - } - }, - "autoload": { - "psr-4": { - "Laminas\\Validator\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Validation classes for a wide range of domains, and the ability to chain validators to create complex validation criteria", - "homepage": "https://laminas.dev", - "keywords": [ - "laminas", - "validator" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-validator/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-validator/issues", - "rss": "https://github.com/laminas/laminas-validator/releases.atom", - "source": "https://github.com/laminas/laminas-validator" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2021-12-02T14:23:06+00:00" - }, - { - "name": "psr/container", - "version": "1.1.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", - "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", - "shasum": "" - }, - "require": { - "php": ">=7.2.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.1" - }, - "time": "2021-03-05T17:36:06+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.24.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "30885182c981ab175d4d034db0f6f469898070ab" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab", - "reference": "30885182c981ab175d4d034db0f6f469898070ab", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-ctype": "*" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "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.24.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": "2021-10-20T20:35:02+00:00" - }, - { - "name": "symfony/polyfill-intl-idn", - "version": "v1.24.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "749045c69efb97c70d25d7463abba812e91f3a44" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/749045c69efb97c70d25d7463abba812e91f3a44", - "reference": "749045c69efb97c70d25d7463abba812e91f3a44", - "shasum": "" - }, - "require": { - "php": ">=7.1", - "symfony/polyfill-intl-normalizer": "^1.10", - "symfony/polyfill-php72": "^1.10" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Idn\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Laurent Bassin", - "email": "laurent@bassin.info" - }, - { - "name": "Trevor Rowbotham", - "email": "trevor.rowbotham@pm.me" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "idn", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.24.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": "2021-09-14T14:02:44+00:00" - }, - { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.24.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8", - "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "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.24.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": "2021-02-19T12:13:01+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.24.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825", - "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-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.24.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": "2021-11-30T18:21:41+00:00" - }, - { - "name": "symfony/polyfill-php72", - "version": "v1.24.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "9a142215a36a3888e30d0a9eeea9766764e96976" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9a142215a36a3888e30d0a9eeea9766764e96976", - "reference": "9a142215a36a3888e30d0a9eeea9766764e96976", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php72\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.24.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": "2021-05-27T09:17:38+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.10.0", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25", - "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.10.0" - }, - "time": "2021-03-09T10:59:23+00:00" - } - ], - "packages-dev": [ - { - "name": "amphp/amp", - "version": "v2.6.1", - "source": { - "type": "git", - "url": "https://github.com/amphp/amp.git", - "reference": "c5fc66a78ee38d7ac9195a37bacaf940eb3f65ae" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/amp/zipball/c5fc66a78ee38d7ac9195a37bacaf940eb3f65ae", - "reference": "c5fc66a78ee38d7ac9195a37bacaf940eb3f65ae", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1", - "ext-json": "*", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^7 | ^8 | ^9", - "psalm/phar": "^3.11@dev", - "react/promise": "^2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "files": [ - "lib/functions.php", - "lib/Internal/functions.php" - ], - "psr-4": { - "Amp\\": "lib" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Bob Weinand", - "email": "bobwei9@hotmail.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "A non-blocking concurrency framework for PHP applications.", - "homepage": "http://amphp.org/amp", - "keywords": [ - "async", - "asynchronous", - "awaitable", - "concurrency", - "event", - "event-loop", - "future", - "non-blocking", - "promise" - ], - "support": { - "irc": "irc://irc.freenode.org/amphp", - "issues": "https://github.com/amphp/amp/issues", - "source": "https://github.com/amphp/amp/tree/v2.6.1" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2021-09-23T18:43:08+00:00" - }, - { - "name": "amphp/byte-stream", - "version": "v1.8.1", - "source": { - "type": "git", - "url": "https://github.com/amphp/byte-stream.git", - "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/byte-stream/zipball/acbd8002b3536485c997c4e019206b3f10ca15bd", - "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd", - "shasum": "" - }, - "require": { - "amphp/amp": "^2", - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1.4", - "friendsofphp/php-cs-fixer": "^2.3", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^6 || ^7 || ^8", - "psalm/phar": "^3.11.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "files": [ - "lib/functions.php" - ], - "psr-4": { - "Amp\\ByteStream\\": "lib" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "A stream abstraction to make working with non-blocking I/O simple.", - "homepage": "http://amphp.org/byte-stream", - "keywords": [ - "amp", - "amphp", - "async", - "io", - "non-blocking", - "stream" - ], - "support": { - "irc": "irc://irc.freenode.org/amphp", - "issues": "https://github.com/amphp/byte-stream/issues", - "source": "https://github.com/amphp/byte-stream/tree/v1.8.1" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2021-03-30T17:13:30+00:00" - }, - { - "name": "composer/package-versions-deprecated", - "version": "1.11.99.4", - "source": { - "type": "git", - "url": "https://github.com/composer/package-versions-deprecated.git", - "reference": "b174585d1fe49ceed21928a945138948cb394600" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/b174585d1fe49ceed21928a945138948cb394600", - "reference": "b174585d1fe49ceed21928a945138948cb394600", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.1.0 || ^2.0", - "php": "^7 || ^8" - }, - "replace": { - "ocramius/package-versions": "1.11.99" - }, - "require-dev": { - "composer/composer": "^1.9.3 || ^2.0@dev", - "ext-zip": "^1.13", - "phpunit/phpunit": "^6.5 || ^7" - }, - "type": "composer-plugin", - "extra": { - "class": "PackageVersions\\Installer", - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "PackageVersions\\": "src/PackageVersions" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be" - } - ], - "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", - "support": { - "issues": "https://github.com/composer/package-versions-deprecated/issues", - "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.4" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2021-09-13T08:41:34+00:00" - }, - { - "name": "composer/pcre", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/composer/pcre.git", - "reference": "3d322d715c43a1ac36c7fe215fa59336265500f2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/3d322d715c43a1ac36c7fe215fa59336265500f2", - "reference": "3d322d715c43a1ac36c7fe215fa59336265500f2", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Pcre\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "PCRE wrapping library that offers type-safe preg_* replacements.", - "keywords": [ - "PCRE", - "preg", - "regex", - "regular expression" - ], - "support": { - "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/1.0.0" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2021-12-06T15:17:27+00:00" - }, - { - "name": "composer/semver", - "version": "3.2.7", - "source": { - "type": "git", - "url": "https://github.com/composer/semver.git", - "reference": "deac27056b57e46faf136fae7b449eeaa71661ee" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/deac27056b57e46faf136fae7b449eeaa71661ee", - "reference": "deac27056b57e46faf136fae7b449eeaa71661ee", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^0.12.54", - "symfony/phpunit-bridge": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Semver\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - }, - { - "name": "Rob Bast", - "email": "rob.bast@gmail.com", - "homepage": "http://robbast.nl" - } - ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", - "keywords": [ - "semantic", - "semver", - "validation", - "versioning" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.2.7" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-01-04T09:57:54+00:00" - }, - { - "name": "composer/xdebug-handler", - "version": "3.0.1", - "source": { - "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "12f1b79476638a5615ed00ea6adbb269cec96fd8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/12f1b79476638a5615ed00ea6adbb269cec96fd8", - "reference": "12f1b79476638a5615ed00ea6adbb269cec96fd8", - "shasum": "" - }, - "require": { - "composer/pcre": "^1", - "php": "^7.2.5 || ^8.0", - "psr/log": "^1 || ^2 || ^3" - }, - "require-dev": { - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without Xdebug.", - "keywords": [ - "Xdebug", - "performance" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/3.0.1" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-01-04T18:29:42+00:00" - }, - { - "name": "dnoegel/php-xdg-base-dir", - "version": "v0.1.1", - "source": { - "type": "git", - "url": "https://github.com/dnoegel/php-xdg-base-dir.git", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "require-dev": { - "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" - }, - "type": "library", - "autoload": { - "psr-4": { - "XdgBaseDir\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "implementation of xdg base directory specification for php", - "support": { - "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", - "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" - }, - "time": "2019-12-04T15:06:13+00:00" - }, - { - "name": "doctrine/instantiator", - "version": "1.4.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b", - "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^8.0", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^0.13 || 1.0.0-alpha2", - "phpstan/phpstan": "^0.12", - "phpstan/phpstan-phpunit": "^0.12", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.4.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" - } - ], - "time": "2020-11-10T18:47:58+00:00" - }, - { - "name": "felixfbecker/advanced-json-rpc", - "version": "v3.2.1", - "source": { - "type": "git", - "url": "https://github.com/felixfbecker/php-advanced-json-rpc.git", - "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447", - "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447", - "shasum": "" - }, - "require": { - "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "php": "^7.1 || ^8.0", - "phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0" - }, - "require-dev": { - "phpunit/phpunit": "^7.0 || ^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "AdvancedJsonRpc\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "ISC" - ], - "authors": [ - { - "name": "Felix Becker", - "email": "felix.b@outlook.com" - } - ], - "description": "A more advanced JSONRPC implementation", - "support": { - "issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues", - "source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.1" - }, - "time": "2021-06-11T22:34:44+00:00" - }, - { - "name": "felixfbecker/language-server-protocol", - "version": "1.5.1", - "source": { - "type": "git", - "url": "https://github.com/felixfbecker/php-language-server-protocol.git", - "reference": "9d846d1f5cf101deee7a61c8ba7caa0a975cd730" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/9d846d1f5cf101deee7a61c8ba7caa0a975cd730", - "reference": "9d846d1f5cf101deee7a61c8ba7caa0a975cd730", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "phpstan/phpstan": "*", - "squizlabs/php_codesniffer": "^3.1", - "vimeo/psalm": "^4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "LanguageServerProtocol\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "ISC" - ], - "authors": [ - { - "name": "Felix Becker", - "email": "felix.b@outlook.com" - } - ], - "description": "PHP classes for the Language Server Protocol", - "keywords": [ - "language", - "microsoft", - "php", - "server" - ], - "support": { - "issues": "https://github.com/felixfbecker/php-language-server-protocol/issues", - "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/1.5.1" - }, - "time": "2021-02-22T14:02:09+00:00" - }, - { - "name": "laminas/laminas-coding-standard", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-coding-standard.git", - "reference": "08880ce2fbfe62d471cd3cb766a91da630b32539" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-coding-standard/zipball/08880ce2fbfe62d471cd3cb766a91da630b32539", - "reference": "08880ce2fbfe62d471cd3cb766a91da630b32539", - "shasum": "" - }, - "require": { - "laminas/laminas-zendframework-bridge": "^1.0", - "squizlabs/php_codesniffer": "^2.7" - }, - "replace": { - "zendframework/zend-coding-standard": "self.version" - }, - "type": "library", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Laminas coding standard", - "homepage": "https://laminas.dev", - "keywords": [ - "Coding Standard", - "laminas" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-coding-standard/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-coding-standard/issues", - "rss": "https://github.com/laminas/laminas-coding-standard/releases.atom", - "source": "https://github.com/laminas/laminas-coding-standard" - }, - "time": "2019-12-31T16:28:26+00:00" - }, - { - "name": "laminas/laminas-crypt", - "version": "3.6.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-crypt.git", - "reference": "ad2c29c289a4bc837b37a7650f5178edda0fc548" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-crypt/zipball/ad2c29c289a4bc837b37a7650f5178edda0fc548", - "reference": "ad2c29c289a4bc837b37a7650f5178edda0fc548", - "shasum": "" - }, - "require": { - "container-interop/container-interop": "^1.2", - "ext-mbstring": "*", - "laminas/laminas-math": "^3.4", - "laminas/laminas-stdlib": "^3.6", - "php": "^7.3 || ~8.0.0 || ~8.1.0" - }, - "conflict": { - "zendframework/zend-crypt": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~1.0.0", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-openssl": "Required for most features of Laminas\\Crypt" - }, - "type": "library", - "autoload": { - "psr-4": { - "Laminas\\Crypt\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Strong cryptography tools and password hashing", - "homepage": "https://laminas.dev", - "keywords": [ - "crypt", - "laminas" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-crypt/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-crypt/issues", - "rss": "https://github.com/laminas/laminas-crypt/releases.atom", - "source": "https://github.com/laminas/laminas-crypt" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2021-12-06T01:25:27+00:00" - }, - { - "name": "laminas/laminas-db", - "version": "2.13.4", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-db.git", - "reference": "cdabb4bfa669c2c0edb0cb4e014c15b41afd3fb1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-db/zipball/cdabb4bfa669c2c0edb0cb4e014c15b41afd3fb1", - "reference": "cdabb4bfa669c2c0edb0cb4e014c15b41afd3fb1", - "shasum": "" - }, - "require": { - "laminas/laminas-stdlib": "^3.6", - "php": "^7.3 || ~8.0.0 || ~8.1.0" - }, - "conflict": { - "zendframework/zend-db": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~2.2.1", - "laminas/laminas-eventmanager": "^3.4", - "laminas/laminas-hydrator": "^3.2 || ^4.3", - "laminas/laminas-servicemanager": "^3.7", - "phpunit/phpunit": "^9.5.5" - }, - "suggest": { - "laminas/laminas-eventmanager": "Laminas\\EventManager component", - "laminas/laminas-hydrator": "(^3.2 || ^4.3) Laminas\\Hydrator component for using HydratingResultSets", - "laminas/laminas-servicemanager": "Laminas\\ServiceManager component" - }, - "type": "library", - "extra": { - "laminas": { - "component": "Laminas\\Db", - "config-provider": "Laminas\\Db\\ConfigProvider" - } - }, - "autoload": { - "psr-4": { - "Laminas\\Db\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Database abstraction layer, SQL abstraction, result set abstraction, and RowDataGateway and TableDataGateway implementations", - "homepage": "https://laminas.dev", - "keywords": [ - "db", - "laminas" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-db/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-db/issues", - "rss": "https://github.com/laminas/laminas-db/releases.atom", - "source": "https://github.com/laminas/laminas-db" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2021-09-21T18:59:44+00:00" - }, - { - "name": "laminas/laminas-math", - "version": "3.5.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-math.git", - "reference": "146d8187ab247ae152e811a6704a953d43537381" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-math/zipball/146d8187ab247ae152e811a6704a953d43537381", - "reference": "146d8187ab247ae152e811a6704a953d43537381", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": "^7.3 || ~8.0.0 || ~8.1.0" - }, - "conflict": { - "zendframework/zend-math": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~1.0.0", - "phpunit/phpunit": "^9.5.5" - }, - "suggest": { - "ext-bcmath": "If using the bcmath functionality", - "ext-gmp": "If using the gmp functionality" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2.x-dev", - "dev-develop": "3.3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Laminas\\Math\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Create cryptographically secure pseudo-random numbers, and manage big integers", - "homepage": "https://laminas.dev", - "keywords": [ - "laminas", - "math" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-math/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-math/issues", - "rss": "https://github.com/laminas/laminas-math/releases.atom", - "source": "https://github.com/laminas/laminas-math" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2021-12-06T02:02:07+00:00" - }, - { - "name": "laminas/laminas-servicemanager", - "version": "3.7.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-servicemanager.git", - "reference": "2b0aee477fdbd3191af7c302b93dbc5fda0626f4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-servicemanager/zipball/2b0aee477fdbd3191af7c302b93dbc5fda0626f4", - "reference": "2b0aee477fdbd3191af7c302b93dbc5fda0626f4", - "shasum": "" - }, - "require": { - "container-interop/container-interop": "^1.2", - "laminas/laminas-stdlib": "^3.2.1", - "laminas/laminas-zendframework-bridge": "^1.0", - "php": "^7.3 || ~8.0.0", - "psr/container": "^1.0" - }, - "conflict": { - "laminas/laminas-code": "<3.3.1", - "zendframework/zend-code": "<3.3.1" - }, - "provide": { - "container-interop/container-interop-implementation": "^1.2", - "psr/container-implementation": "^1.0" - }, - "replace": { - "zendframework/zend-servicemanager": "^3.4.0" - }, - "require-dev": { - "composer/package-versions-deprecated": "^1.0", - "laminas/laminas-coding-standard": "~2.2.0", - "laminas/laminas-container-config-test": "^0.3", - "laminas/laminas-dependency-plugin": "^2.1.2", - "mikey179/vfsstream": "^1.6.8", - "ocramius/proxy-manager": "^2.2.3", - "phpbench/phpbench": "^1.0.4", - "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^9.4", - "psalm/plugin-phpunit": "^0.16.1", - "vimeo/psalm": "^4.8" - }, - "suggest": { - "ocramius/proxy-manager": "ProxyManager ^2.1.1 to handle lazy initialization of services" - }, - "bin": [ - "bin/generate-deps-for-config-factory", - "bin/generate-factory-for-class" - ], - "type": "library", - "autoload": { - "psr-4": { - "Laminas\\ServiceManager\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Factory-Driven Dependency Injection Container", - "homepage": "https://laminas.dev", - "keywords": [ - "PSR-11", - "dependency-injection", - "di", - "dic", - "laminas", - "service-manager", - "servicemanager" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-servicemanager/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-servicemanager/issues", - "rss": "https://github.com/laminas/laminas-servicemanager/releases.atom", - "source": "https://github.com/laminas/laminas-servicemanager" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2021-07-24T19:33:07+00:00" - }, - { - "name": "laminas/laminas-zendframework-bridge", - "version": "1.4.1", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-zendframework-bridge.git", - "reference": "88bf037259869891afce6504cacc4f8a07b24d0f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/88bf037259869891afce6504cacc4f8a07b24d0f", - "reference": "88bf037259869891afce6504cacc4f8a07b24d0f", - "shasum": "" - }, - "require": { - "php": "^7.3 || ~8.0.0 || ~8.1.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3", - "psalm/plugin-phpunit": "^0.15.1", - "squizlabs/php_codesniffer": "^3.5", - "vimeo/psalm": "^4.6" - }, - "type": "library", - "extra": { - "laminas": { - "module": "Laminas\\ZendFrameworkBridge" - } - }, - "autoload": { - "files": [ - "src/autoload.php" - ], - "psr-4": { - "Laminas\\ZendFrameworkBridge\\": "src//" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Alias legacy ZF class names to Laminas Project equivalents.", - "keywords": [ - "ZendFramework", - "autoloading", - "laminas", - "zf" - ], - "support": { - "forum": "https://discourse.laminas.dev/", - "issues": "https://github.com/laminas/laminas-zendframework-bridge/issues", - "rss": "https://github.com/laminas/laminas-zendframework-bridge/releases.atom", - "source": "https://github.com/laminas/laminas-zendframework-bridge" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2021-12-21T14:34:37+00:00" - }, - { - "name": "myclabs/deep-copy", - "version": "1.10.2", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/collections": "^1.0", - "doctrine/common": "^2.6", - "phpunit/phpunit": "^7.1" - }, - "type": "library", - "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.10.2" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2020-11-13T09:40:50+00:00" - }, - { - "name": "netresearch/jsonmapper", - "version": "v4.0.0", - "source": { - "type": "git", - "url": "https://github.com/cweiske/jsonmapper.git", - "reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d", - "reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=7.1" - }, - "require-dev": { - "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0", - "squizlabs/php_codesniffer": "~3.5" - }, - "type": "library", - "autoload": { - "psr-0": { - "JsonMapper": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "OSL-3.0" - ], - "authors": [ - { - "name": "Christian Weiske", - "email": "cweiske@cweiske.de", - "homepage": "http://github.com/cweiske/jsonmapper/", - "role": "Developer" - } - ], - "description": "Map nested JSON structures onto PHP classes", - "support": { - "email": "cweiske@cweiske.de", - "issues": "https://github.com/cweiske/jsonmapper/issues", - "source": "https://github.com/cweiske/jsonmapper/tree/v4.0.0" - }, - "time": "2020-12-01T19:48:11+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v4.13.2", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "210577fe3cf7badcc5814d99455df46564f3c077" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/210577fe3cf7badcc5814d99455df46564f3c077", - "reference": "210577fe3cf7badcc5814d99455df46564f3c077", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=7.0" - }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.9-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.2" - }, - "time": "2021-11-30T19:35:32+00:00" - }, - { - "name": "openlss/lib-array2xml", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/nullivex/lib-array2xml.git", - "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nullivex/lib-array2xml/zipball/a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", - "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "type": "library", - "autoload": { - "psr-0": { - "LSS": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Bryan Tong", - "email": "bryan@nullivex.com", - "homepage": "https://www.nullivex.com" - }, - { - "name": "Tony Butler", - "email": "spudz76@gmail.com", - "homepage": "https://www.nullivex.com" - } - ], - "description": "Array2XML conversion library credit to lalit.org", - "homepage": "https://www.nullivex.com", - "keywords": [ - "array", - "array conversion", - "xml", - "xml conversion" - ], - "support": { - "issues": "https://github.com/nullivex/lib-array2xml/issues", - "source": "https://github.com/nullivex/lib-array2xml/tree/master" - }, - "time": "2019-03-29T20:06:56+00:00" - }, - { - "name": "phar-io/manifest", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.3" - }, - "time": "2021-07-20T11:28:43+00:00" - }, - { - "name": "phar-io/version", - "version": "3.1.0", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "bae7c545bef187884426f042434e561ab1ddb182" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/bae7c545bef187884426f042434e561ab1ddb182", - "reference": "bae7c545bef187884426f042434e561ab1ddb182", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.1.0" - }, - "time": "2021-02-23T14:00:09+00:00" - }, - { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" - }, - "time": "2020-06-27T09:03:43+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "5.3.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", - "shasum": "" - }, - "require": { - "ext-filter": "*", - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", - "webmozart/assert": "^1.9.1" - }, - "require-dev": { - "mockery/mockery": "~1.3.2", - "psalm/phar": "^4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - }, - { - "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" - }, - "time": "2021-10-19T17:43:47+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.6.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "93ebd0014cab80c4ea9f5e297ea48672f1b87706" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/93ebd0014cab80c4ea9f5e297ea48672f1b87706", - "reference": "93ebd0014cab80c4ea9f5e297ea48672f1b87706", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.0" - }, - "require-dev": { - "ext-tokenizer": "*", - "psalm/phar": "^4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.0" - }, - "time": "2022-01-04T19:58:01+00:00" - }, - { - "name": "phpspec/prophecy", - "version": "v1.15.0", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/bbcd7380b0ebf3961ee21409db7b38bc31d69a13", - "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.2", - "php": "^7.2 || ~8.0, <8.2", - "phpdocumentor/reflection-docblock": "^5.2", - "sebastian/comparator": "^3.0 || ^4.0", - "sebastian/recursion-context": "^3.0 || ^4.0" - }, - "require-dev": { - "phpspec/phpspec": "^6.0 || ^7.0", - "phpunit/phpunit": "^8.0 || ^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Prophecy\\": "src/Prophecy" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" - } - ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "support": { - "issues": "https://github.com/phpspec/prophecy/issues", - "source": "https://github.com/phpspec/prophecy/tree/v1.15.0" - }, - "time": "2021-12-08T12:19:24+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "9.2.10", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "d5850aaf931743067f4bfc1ae4cbd06468400687" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/d5850aaf931743067f4bfc1ae4cbd06468400687", - "reference": "d5850aaf931743067f4bfc1ae4cbd06468400687", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^4.13.0", - "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.3", - "phpunit/php-text-template": "^2.0.2", - "sebastian/code-unit-reverse-lookup": "^2.0.2", - "sebastian/complexity": "^2.0", - "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0.3", - "sebastian/version": "^3.0.1", - "theseer/tokenizer": "^1.2.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcov": "*", - "ext-xdebug": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.10" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-12-05T09:12:13+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "3.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-12-02T12:48:52+00:00" - }, - { - "name": "phpunit/php-invoker", - "version": "3.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:58:55+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T05:33:50+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "5.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:16:10+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "9.5.11", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "2406855036db1102126125537adb1406f7242fdd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2406855036db1102126125537adb1406f7242fdd", - "reference": "2406855036db1102126125537adb1406f7242fdd", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.3.1", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", - "php": ">=7.3", - "phpspec/prophecy": "^1.12.1", - "phpunit/php-code-coverage": "^9.2.7", - "phpunit/php-file-iterator": "^3.0.5", - "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.5", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.3", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^2.3.4", - "sebastian/version": "^3.0.2" - }, - "require-dev": { - "ext-pdo": "*", - "phpspec/prophecy-phpunit": "^2.0.1" - }, - "suggest": { - "ext-soap": "*", - "ext-xdebug": "*" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.5-dev" - } - }, - "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.11" - }, - "funding": [ - { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-12-25T07:07:57+00:00" - }, - { - "name": "psalm/plugin-phpunit", - "version": "0.15.2", - "source": { - "type": "git", - "url": "https://github.com/psalm/psalm-plugin-phpunit.git", - "reference": "31d15bbc0169a3c454e495e03fd8a6ccb663661b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/psalm/psalm-plugin-phpunit/zipball/31d15bbc0169a3c454e495e03fd8a6ccb663661b", - "reference": "31d15bbc0169a3c454e495e03fd8a6ccb663661b", - "shasum": "" - }, - "require": { - "composer/package-versions-deprecated": "^1.10", - "composer/semver": "^1.4 || ^2.0 || ^3.0", - "ext-simplexml": "*", - "php": "^7.1 || ^8.0", - "vimeo/psalm": "dev-master || dev-4.x || ^4.0" - }, - "conflict": { - "phpunit/phpunit": "<7.5" - }, - "require-dev": { - "codeception/codeception": "^4.0.3", - "php": "^7.3 || ^8.0", - "phpunit/phpunit": "^7.5 || ^8.0 || ^9.0", - "squizlabs/php_codesniffer": "^3.3.1", - "weirdan/codeception-psalm-module": "^0.11.0", - "weirdan/prophecy-shim": "^1.0 || ^2.0" - }, - "type": "psalm-plugin", - "extra": { - "psalm": { - "pluginClass": "Psalm\\PhpUnitPlugin\\Plugin" - } - }, - "autoload": { - "psr-4": { - "Psalm\\PhpUnitPlugin\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Matt Brown", - "email": "github@muglug.com" - } - ], - "description": "Psalm plugin for PHPUnit", - "support": { - "issues": "https://github.com/psalm/psalm-plugin-phpunit/issues", - "source": "https://github.com/psalm/psalm-plugin-phpunit/tree/0.15.2" - }, - "time": "2021-05-29T19:11:38+00:00" - }, - { - "name": "psr/log", - "version": "1.1.4", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "support": { - "source": "https://github.com/php-fig/log/tree/1.1.4" - }, - "time": "2021-05-03T11:20:27+00:00" - }, - { - "name": "sebastian/cli-parser", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", - "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:08:49+00:00" - }, - { - "name": "sebastian/code-unit", - "version": "1.0.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:08:54+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:30:19+00:00" - }, - { - "name": "sebastian/comparator", - "version": "4.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T15:49:45+00:00" - }, - { - "name": "sebastian/complexity", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.7", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", - "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T15:52:27+00:00" - }, - { - "name": "sebastian/diff", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/process": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:10:38+00:00" - }, - { - "name": "sebastian/environment", - "version": "5.1.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "388b6ced16caa751030f6a69e588299fa09200ac" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/388b6ced16caa751030f6a69e588299fa09200ac", - "reference": "388b6ced16caa751030f6a69e588299fa09200ac", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-posix": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:52:38+00:00" - }, - { - "name": "sebastian/exporter", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/65e8b7db476c5dd267e65eea9cab77584d3cfff9", - "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-11-11T14:18:36+00:00" - }, - { - "name": "sebastian/global-state", - "version": "5.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/23bd5951f7ff26f12d4e3242864df3e08dec4e49", - "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-06-11T13:31:12+00:00" - }, - { - "name": "sebastian/lines-of-code", - "version": "1.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.6", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", - "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-28T06:42:11+00:00" - }, - { - "name": "sebastian/object-enumerator", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:12:34+00:00" - }, - { - "name": "sebastian/object-reflector", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:14:26+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:17:30+00:00" - }, - { - "name": "sebastian/resource-operations", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:45:17+00:00" - }, - { - "name": "sebastian/type", - "version": "2.3.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b8cd8a1c753c90bc1a0f5372170e3e489136f914", - "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", - "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/2.3.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-06-15T12:49:02+00:00" - }, - { - "name": "sebastian/version", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:39:44+00:00" - }, - { - "name": "squizlabs/php_codesniffer", - "version": "2.9.2", - "source": { - "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "2acf168de78487db620ab4bc524135a13cfe6745" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/2acf168de78487db620ab4bc524135a13cfe6745", - "reference": "2acf168de78487db620ab4bc524135a13cfe6745", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.1.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "bin": [ - "scripts/phpcs", - "scripts/phpcbf" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "classmap": [ - "CodeSniffer.php", - "CodeSniffer/CLI.php", - "CodeSniffer/Exception.php", - "CodeSniffer/File.php", - "CodeSniffer/Fixer.php", - "CodeSniffer/Report.php", - "CodeSniffer/Reporting.php", - "CodeSniffer/Sniff.php", - "CodeSniffer/Tokens.php", - "CodeSniffer/Reports/", - "CodeSniffer/Tokenizers/", - "CodeSniffer/DocGenerators/", - "CodeSniffer/Standards/AbstractPatternSniff.php", - "CodeSniffer/Standards/AbstractScopeSniff.php", - "CodeSniffer/Standards/AbstractVariableSniff.php", - "CodeSniffer/Standards/IncorrectPatternException.php", - "CodeSniffer/Standards/Generic/Sniffs/", - "CodeSniffer/Standards/MySource/Sniffs/", - "CodeSniffer/Standards/PEAR/Sniffs/", - "CodeSniffer/Standards/PSR1/Sniffs/", - "CodeSniffer/Standards/PSR2/Sniffs/", - "CodeSniffer/Standards/Squiz/Sniffs/", - "CodeSniffer/Standards/Zend/Sniffs/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Greg Sherwood", - "role": "lead" - } - ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "http://www.squizlabs.com/php-codesniffer", - "keywords": [ - "phpcs", - "standards" - ], - "support": { - "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", - "source": "https://github.com/squizlabs/PHP_CodeSniffer", - "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" - }, - "time": "2018-11-07T22:31:41+00:00" - }, - { - "name": "symfony/console", - "version": "v5.4.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "a2c6b7ced2eb7799a35375fb9022519282b5405e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/a2c6b7ced2eb7799a35375fb9022519282b5405e", - "reference": "a2c6b7ced2eb7799a35375fb9022519282b5405e", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.1|^6.0" - }, - "conflict": { - "psr/log": ">=3", - "symfony/dependency-injection": "<4.4", - "symfony/dotenv": "<5.1", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" - }, - "provide": { - "psr/log-implementation": "1.0|2.0" - }, - "require-dev": { - "psr/log": "^1|^2", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/lock": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Eases the creation of beautiful and testable command line interfaces", - "homepage": "https://symfony.com", - "keywords": [ - "cli", - "command line", - "console", - "terminal" - ], - "support": { - "source": "https://github.com/symfony/console/tree/v5.4.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": "2021-12-20T16:11:12+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "v2.5.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/6f981ee24cf69ee7ce9736146d1c57c2780598a8", - "reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-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/v2.5.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": "2021-07-12T14:48:14+00:00" - }, - { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.24.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "81b86b50cf841a64252b439e738e97f4a34e2783" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/81b86b50cf841a64252b439e738e97f4a34e2783", - "reference": "81b86b50cf841a64252b439e738e97f4a34e2783", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "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.24.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": "2021-11-23T21:10:46+00:00" - }, - { - "name": "symfony/polyfill-php73", - "version": "v1.24.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/cc5db0e22b3cb4111010e48785a97f670b350ca5", - "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.24.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": "2021-06-05T21:20:04+00:00" - }, - { - "name": "symfony/polyfill-php80", - "version": "v1.24.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "57b712b08eddb97c762a8caa32c84e037892d2e9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/57b712b08eddb97c762a8caa32c84e037892d2e9", - "reference": "57b712b08eddb97c762a8caa32c84e037892d2e9", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.24.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": "2021-09-13T13:58:33+00:00" - }, - { - "name": "symfony/process", - "version": "v5.4.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "2b3ba8722c4aaf3e88011be5e7f48710088fb5e4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/2b3ba8722c4aaf3e88011be5e7f48710088fb5e4", - "reference": "2b3ba8722c4aaf3e88011be5e7f48710088fb5e4", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Process\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Executes commands in sub-processes", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/process/tree/v5.4.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": "2021-12-27T21:01:00+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v2.5.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc", - "reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "suggest": { - "symfony/service-implementation": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-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/v2.5.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": "2021-11-04T16:48:04+00:00" - }, - { - "name": "symfony/string", - "version": "v5.4.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "e6a5d5ecf6589c5247d18e0e74e30b11dfd51a3d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/e6a5d5ecf6589c5247d18e0e74e30b11dfd51a3d", - "reference": "e6a5d5ecf6589c5247d18e0e74e30b11dfd51a3d", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "~1.15" - }, - "conflict": { - "symfony/translation-contracts": ">=3.0" - }, - "require-dev": { - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/translation-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0|^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\String\\": "" - }, - "files": [ - "Resources/functions.php" - ], - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", - "homepage": "https://symfony.com", - "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" - ], - "support": { - "source": "https://github.com/symfony/string/tree/v5.4.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": "2021-12-16T21:52:00+00:00" - }, - { - "name": "theseer/tokenizer", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.1" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2021-07-28T10:34:58+00:00" - }, - { - "name": "vimeo/psalm", - "version": "4.18.1", - "source": { - "type": "git", - "url": "https://github.com/vimeo/psalm.git", - "reference": "dda05fa913f4dc6eb3386f2f7ce5a45d37a71bcb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/dda05fa913f4dc6eb3386f2f7ce5a45d37a71bcb", - "reference": "dda05fa913f4dc6eb3386f2f7ce5a45d37a71bcb", - "shasum": "" - }, - "require": { - "amphp/amp": "^2.4.2", - "amphp/byte-stream": "^1.5", - "composer/package-versions-deprecated": "^1.8.0", - "composer/semver": "^1.4 || ^2.0 || ^3.0", - "composer/xdebug-handler": "^1.1 || ^2.0 || ^3.0", - "dnoegel/php-xdg-base-dir": "^0.1.1", - "ext-ctype": "*", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-simplexml": "*", - "ext-tokenizer": "*", - "felixfbecker/advanced-json-rpc": "^3.0.3", - "felixfbecker/language-server-protocol": "^1.5", - "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "nikic/php-parser": "^4.13", - "openlss/lib-array2xml": "^1.0", - "php": "^7.1|^8", - "sebastian/diff": "^3.0 || ^4.0", - "symfony/console": "^3.4.17 || ^4.1.6 || ^5.0 || ^6.0", - "webmozart/path-util": "^2.3" - }, - "provide": { - "psalm/psalm": "self.version" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.2", - "brianium/paratest": "^4.0||^6.0", - "ext-curl": "*", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpdocumentor/reflection-docblock": "^5", - "phpmyadmin/sql-parser": "5.1.0||dev-master", - "phpspec/prophecy": ">=1.9.0", - "phpunit/phpunit": "^9.0", - "psalm/plugin-phpunit": "^0.16", - "slevomat/coding-standard": "^7.0", - "squizlabs/php_codesniffer": "^3.5", - "symfony/process": "^4.3 || ^5.0 || ^6.0", - "weirdan/prophecy-shim": "^1.0 || ^2.0" - }, - "suggest": { - "ext-curl": "In order to send data to shepherd", - "ext-igbinary": "^2.0.5 is required, used to serialize caching data" - }, - "bin": [ - "psalm", - "psalm-language-server", - "psalm-plugin", - "psalm-refactor", - "psalter" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.x-dev", - "dev-3.x": "3.x-dev", - "dev-2.x": "2.x-dev", - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "files": [ - "src/functions.php", - "src/spl_object_id.php" - ], - "psr-4": { - "Psalm\\": "src/Psalm/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Matthew Brown" - } - ], - "description": "A static analysis tool for finding errors in PHP applications", - "keywords": [ - "code", - "inspection", - "php" - ], - "support": { - "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm/tree/4.18.1" - }, - "time": "2022-01-08T21:21:26+00:00" - }, - { - "name": "webmozart/path-util", - "version": "2.3.0", - "source": { - "type": "git", - "url": "https://github.com/webmozart/path-util.git", - "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725", - "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "webmozart/assert": "~1.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\PathUtil\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.", - "support": { - "issues": "https://github.com/webmozart/path-util/issues", - "source": "https://github.com/webmozart/path-util/tree/2.3.0" - }, - "abandoned": "symfony/filesystem", - "time": "2015-12-17T08:42:14+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": "^7.3 || ~8.0.0 || ~8.1.0", - "ext-iconv": "*" - }, - "platform-dev": [], - "platform-overrides": { - "php": "7.3.99" - }, - "plugin-api-version": "2.2.0" -} diff --git a/lib/laminas/laminas-mail/src/Address.php b/lib/laminas/laminas-mail/src/Address.php deleted file mode 100644 index 7b2956f2e..000000000 --- a/lib/laminas/laminas-mail/src/Address.php +++ /dev/null @@ -1,162 +0,0 @@ -<?php - -namespace Laminas\Mail; - -use Laminas\Validator\EmailAddress as EmailAddressValidator; -use Laminas\Validator\Hostname; - -class Address implements Address\AddressInterface -{ - protected $comment; - protected $email; - protected $name; - - /** - * Create an instance from a string value. - * - * Parses a string representing a single address. If it is a valid format, - * it then creates and returns an instance of itself using the name and - * email it has parsed from the value. - * - * @param string $address - * @param null|string $comment Comment associated with the address, if any. - * @throws Exception\InvalidArgumentException - * @return self - */ - public static function fromString($address, $comment = null) - { - if (! preg_match('/^((?P<name>.*)<(?P<namedEmail>[^>]+)>|(?P<email>.+))$/', $address, $matches)) { - throw new Exception\InvalidArgumentException('Invalid address format'); - } - - $name = null; - if (isset($matches['name'])) { - $name = trim($matches['name']); - } - if (empty($name)) { - $name = null; - } - - if (isset($matches['namedEmail'])) { - $email = $matches['namedEmail']; - } - if (isset($matches['email'])) { - $email = $matches['email']; - } - $email = trim($email); - //trim single quotes, because outlook does add single quotes to emails sometimes which is technically not valid - $email = trim($email, '\''); - - return new static($email, $name, $comment); - } - - /** - * Constructor - * - * @param string $email - * @param null|string $name - * @param null|string $comment - * @throws Exception\InvalidArgumentException - */ - public function __construct($email, $name = null, $comment = null) - { - $emailAddressValidator = new EmailAddressValidator(Hostname::ALLOW_DNS | Hostname::ALLOW_LOCAL); - if (! is_string($email) || empty($email)) { - throw new Exception\InvalidArgumentException('Email must be a valid email address'); - } - - if (preg_match("/[\r\n]/", $email)) { - throw new Exception\InvalidArgumentException('CRLF injection detected'); - } - - if (! $emailAddressValidator->isValid($email)) { - $invalidMessages = $emailAddressValidator->getMessages(); - throw new Exception\InvalidArgumentException(array_shift($invalidMessages)); - } - - if (null !== $name) { - if (! is_string($name)) { - throw new Exception\InvalidArgumentException('Name must be a string'); - } - - if (preg_match("/[\r\n]/", $name)) { - throw new Exception\InvalidArgumentException('CRLF injection detected'); - } - - $this->name = $name; - } - - $this->email = $email; - - if (null !== $comment) { - $this->comment = $comment; - } - } - - /** - * Retrieve email - * - * @return string - */ - public function getEmail() - { - return $this->email; - } - - /** - * Retrieve name, if any - * - * @return null|string - */ - public function getName() - { - return $this->name; - } - - /** - * Retrieve comment, if any - * - * @return null|string - */ - public function getComment() - { - return $this->comment; - } - - /** - * String representation of address - * - * @return string - */ - public function toString() - { - $string = sprintf('<%s>', $this->getEmail()); - $name = $this->constructName(); - if (null === $name) { - return $string; - } - - return sprintf('%s %s', $name, $string); - } - - /** - * Constructs the name string - * - * If a comment is present, appends the comment (commented using parens) to - * the name before returning it; otherwise, returns just the name. - * - * @return null|string - */ - private function constructName() - { - $name = $this->getName(); - $comment = $this->getComment(); - - if ($comment === null || $comment === '') { - return $name; - } - - $string = sprintf('%s (%s)', $name, $comment); - return trim($string); - } -} diff --git a/lib/laminas/laminas-mail/src/Address/AddressInterface.php b/lib/laminas/laminas-mail/src/Address/AddressInterface.php deleted file mode 100644 index c75c6f75b..000000000 --- a/lib/laminas/laminas-mail/src/Address/AddressInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -namespace Laminas\Mail\Address; - -interface AddressInterface -{ - /** - * Retrieve email - * - * @return string - */ - public function getEmail(); - - /** - * Retrieve name, if any - * - * @return null|string - */ - public function getName(); - - /** - * String representation of address - * - * @return string - */ - public function toString(); -} diff --git a/lib/laminas/laminas-mail/src/AddressList.php b/lib/laminas/laminas-mail/src/AddressList.php deleted file mode 100644 index fd01388dc..000000000 --- a/lib/laminas/laminas-mail/src/AddressList.php +++ /dev/null @@ -1,238 +0,0 @@ -<?php - -namespace Laminas\Mail; - -use Countable; -use Iterator; -use ReturnTypeWillChange; - -class AddressList implements Countable, Iterator -{ - /** - * List of Address objects we're managing - * - * @var array - */ - protected $addresses = []; - - /** - * Add an address to the list - * - * @param string|Address\AddressInterface $emailOrAddress - * @param null|string $name - * @throws Exception\InvalidArgumentException - * @return AddressList - */ - public function add($emailOrAddress, $name = null) - { - if (is_string($emailOrAddress)) { - $emailOrAddress = $this->createAddress($emailOrAddress, $name); - } - - if (! $emailOrAddress instanceof Address\AddressInterface) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects an email address or %s\Address object as its first argument; received "%s"', - __METHOD__, - __NAMESPACE__, - (is_object($emailOrAddress) ? get_class($emailOrAddress) : gettype($emailOrAddress)) - )); - } - - $email = strtolower($emailOrAddress->getEmail()); - if ($this->has($email)) { - return $this; - } - - $this->addresses[$email] = $emailOrAddress; - return $this; - } - - /** - * Add many addresses at once - * - * If an email key is provided, it will be used as the email, and the value - * as the name. Otherwise, the value is passed as the sole argument to add(), - * and, as such, can be either email strings or Address\AddressInterface objects. - * - * @param array $addresses - * @throws Exception\RuntimeException - * @return AddressList - */ - public function addMany(array $addresses) - { - foreach ($addresses as $key => $value) { - if (is_int($key) || is_numeric($key)) { - $this->add($value); - continue; - } - - if (! is_string($key)) { - throw new Exception\RuntimeException(sprintf( - 'Invalid key type in provided addresses array ("%s")', - (is_object($key) ? get_class($key) : var_export($key, 1)) - )); - } - - $this->add($key, $value); - } - return $this; - } - - /** - * Add an address to the list from any valid string format, such as - * - "Laminas Dev" <dev@laminas.com> - * - dev@laminas.com - * - * @param string $address - * @param null|string $comment Comment associated with the address, if any. - * @throws Exception\InvalidArgumentException - * @return AddressList - */ - public function addFromString($address, $comment = null) - { - $this->add(Address::fromString($address, $comment)); - return $this; - } - - /** - * Merge another address list into this one - * - * @param AddressList $addressList - * @return AddressList - */ - public function merge(self $addressList) - { - foreach ($addressList as $address) { - $this->add($address); - } - return $this; - } - - /** - * Does the email exist in this list? - * - * @param string $email - * @return bool - */ - public function has($email) - { - $email = strtolower($email); - return isset($this->addresses[$email]); - } - - /** - * Get an address by email - * - * @param string $email - * @return bool|Address\AddressInterface - */ - public function get($email) - { - $email = strtolower($email); - if (! isset($this->addresses[$email])) { - return false; - } - - return $this->addresses[$email]; - } - - /** - * Delete an address from the list - * - * @param string $email - * @return bool - */ - public function delete($email) - { - $email = strtolower($email); - if (! isset($this->addresses[$email])) { - return false; - } - - unset($this->addresses[$email]); - return true; - } - - /** - * Return count of addresses - * - * @return int - */ - #[ReturnTypeWillChange] - public function count() - { - return count($this->addresses); - } - - /** - * Rewind iterator - * - * @return mixed the value of the first addresses element, or false if the addresses is - * empty. - * @see addresses - */ - #[ReturnTypeWillChange] - public function rewind() - { - return reset($this->addresses); - } - - /** - * Return current item in iteration - * - * @return Address - */ - #[ReturnTypeWillChange] - public function current() - { - return current($this->addresses); - } - - /** - * Return key of current item of iteration - * - * @return string - */ - #[ReturnTypeWillChange] - public function key() - { - return key($this->addresses); - } - - /** - * Move to next item - * - * @return mixed the addresses value in the next place that's pointed to by the - * internal array pointer, or false if there are no more elements. - * @see addresses - */ - #[ReturnTypeWillChange] - public function next() - { - return next($this->addresses); - } - - /** - * Is the current item of iteration valid? - * - * @return bool - */ - #[ReturnTypeWillChange] - public function valid() - { - $key = key($this->addresses); - return ($key !== null && $key !== false); - } - - /** - * Create an address object - * - * @param string $email - * @param string|null $name - * @return Address - */ - protected function createAddress($email, $name) - { - return new Address($email, $name); - } -} diff --git a/lib/laminas/laminas-mail/src/ConfigProvider.php b/lib/laminas/laminas-mail/src/ConfigProvider.php deleted file mode 100644 index d8468a3f6..000000000 --- a/lib/laminas/laminas-mail/src/ConfigProvider.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -namespace Laminas\Mail; - -class ConfigProvider -{ - /** - * Retrieve configuration for laminas-mail package. - * - * @return array - */ - public function __invoke() - { - return [ - 'dependencies' => $this->getDependencyConfig(), - ]; - } - - /** - * Retrieve dependency settings for laminas-mail package. - * - * @return array - */ - public function getDependencyConfig() - { - return [ - // Legacy Zend Framework aliases - 'aliases' => [ - \Zend\Mail\Protocol\SmtpPluginManager::class => Protocol\SmtpPluginManager::class, - ], - 'factories' => [ - Protocol\SmtpPluginManager::class => Protocol\SmtpPluginManagerFactory::class, - ], - ]; - } -} diff --git a/lib/laminas/laminas-mail/src/Exception/BadMethodCallException.php b/lib/laminas/laminas-mail/src/Exception/BadMethodCallException.php deleted file mode 100644 index 4020cc891..000000000 --- a/lib/laminas/laminas-mail/src/Exception/BadMethodCallException.php +++ /dev/null @@ -1,11 +0,0 @@ -<?php - -namespace Laminas\Mail\Exception; - -/** - * Exception for Laminas\Mail component. - */ -class BadMethodCallException extends \BadMethodCallException implements - ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-mail/src/Exception/DomainException.php b/lib/laminas/laminas-mail/src/Exception/DomainException.php deleted file mode 100644 index 4de35589a..000000000 --- a/lib/laminas/laminas-mail/src/Exception/DomainException.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php - -namespace Laminas\Mail\Exception; - -/** - * Exception for Laminas\Mail component. - */ -class DomainException extends \DomainException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-mail/src/Exception/ExceptionInterface.php b/lib/laminas/laminas-mail/src/Exception/ExceptionInterface.php deleted file mode 100644 index d903a0321..000000000 --- a/lib/laminas/laminas-mail/src/Exception/ExceptionInterface.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace Laminas\Mail\Exception; - -interface ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-mail/src/Exception/InvalidArgumentException.php b/lib/laminas/laminas-mail/src/Exception/InvalidArgumentException.php deleted file mode 100644 index 7ac984c69..000000000 --- a/lib/laminas/laminas-mail/src/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,11 +0,0 @@ -<?php - -namespace Laminas\Mail\Exception; - -/** - * Exception for Laminas\Mail component. - */ -class InvalidArgumentException extends \InvalidArgumentException implements - ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-mail/src/Exception/OutOfBoundsException.php b/lib/laminas/laminas-mail/src/Exception/OutOfBoundsException.php deleted file mode 100644 index b9ed19711..000000000 --- a/lib/laminas/laminas-mail/src/Exception/OutOfBoundsException.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php - -namespace Laminas\Mail\Exception; - -/** - * Exception for Laminas\Mail component. - */ -class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-mail/src/Exception/RuntimeException.php b/lib/laminas/laminas-mail/src/Exception/RuntimeException.php deleted file mode 100644 index cbf259347..000000000 --- a/lib/laminas/laminas-mail/src/Exception/RuntimeException.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php - -namespace Laminas\Mail\Exception; - -/** - * Exception for Laminas\Mail component. - */ -class RuntimeException extends \RuntimeException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-mail/src/Header/AbstractAddressList.php b/lib/laminas/laminas-mail/src/Header/AbstractAddressList.php deleted file mode 100644 index 020de6d0b..000000000 --- a/lib/laminas/laminas-mail/src/Header/AbstractAddressList.php +++ /dev/null @@ -1,276 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -use Laminas\Mail\Address; -use Laminas\Mail\AddressList; -use Laminas\Mail\Headers; -use Laminas\Mail\Storage\Exception\RuntimeException; -use Throwable; - -/** - * Base class for headers composing address lists (to, from, cc, bcc, reply-to) - */ -abstract class AbstractAddressList implements HeaderInterface -{ - private const IDNA_ERROR_MAP = [ - IDNA_ERROR_EMPTY_LABEL => 'empty label', - IDNA_ERROR_LABEL_TOO_LONG => 'label too long', - IDNA_ERROR_DOMAIN_NAME_TOO_LONG => 'domain name too long', - IDNA_ERROR_LEADING_HYPHEN => 'leading hyphen', - IDNA_ERROR_TRAILING_HYPHEN => 'trailing hyphen', - IDNA_ERROR_HYPHEN_3_4 => 'consecutive hyphens', - IDNA_ERROR_LEADING_COMBINING_MARK => 'leading combining mark', - IDNA_ERROR_DISALLOWED => 'disallowed', - IDNA_ERROR_PUNYCODE => 'invalid punycode encoding', - IDNA_ERROR_LABEL_HAS_DOT => 'has dot', - IDNA_ERROR_INVALID_ACE_LABEL => 'label not in ASCII encoding', - IDNA_ERROR_BIDI => 'fails bidirectional criteria', - IDNA_ERROR_CONTEXTJ => 'one or more characters fail CONTEXTJ rule', - ]; - - /** - * @var AddressList - */ - protected $addressList; - - /** - * @var string Normalized field name - */ - protected $fieldName; - - /** - * Header encoding - * - * @var string - */ - protected $encoding = 'ASCII'; - - /** - * @var string lower case field name - */ - protected static $type; - - public static function fromString($headerLine) - { - list($fieldName, $fieldValue) = GenericHeader::splitHeaderLine($headerLine); - if (strtolower($fieldName) !== static::$type) { - throw new Exception\InvalidArgumentException(sprintf( - 'Invalid header line for "%s" string', - __CLASS__ - )); - } - - // split value on "," - $fieldValue = str_replace(Headers::FOLDING, ' ', $fieldValue); - $fieldValue = preg_replace('/[^:]+:([^;]*);/', '$1,', $fieldValue); - $values = ListParser::parse($fieldValue); - - $wasEncoded = false; - $addresses = array_map( - function ($value) use (&$wasEncoded) { - $decodedValue = HeaderWrap::mimeDecodeValue($value); - $wasEncoded = $wasEncoded || ($decodedValue !== $value); - - $value = trim($decodedValue); - - $comments = self::getComments($value); - $value = self::stripComments($value); - - $value = preg_replace( - [ - '#(?<!\\\)"(.*)(?<!\\\)"#', // quoted-text - '#\\\([\x01-\x09\x0b\x0c\x0e-\x7f])#', // quoted-pair - ], - [ - '\\1', - '\\1', - ], - $value - ); - - return empty($value) ? null : Address::fromString($value, $comments); - }, - $values - ); - $addresses = array_filter($addresses); - - $header = new static(); - if ($wasEncoded) { - $header->setEncoding('UTF-8'); - } - - /** @var AddressList $addressList */ - $addressList = $header->getAddressList(); - foreach ($addresses as $address) { - $addressList->add($address); - } - - return $header; - } - - public function getFieldName() - { - return $this->fieldName; - } - - /** - * Safely convert UTF-8 encoded domain name to ASCII - * @param string $domainName the UTF-8 encoded email - * @return string - */ - protected function idnToAscii($domainName): string - { - $ascii = idn_to_ascii($domainName, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46, $conversionInfo); - if (false !== $ascii) { - return $ascii; - } - - $messages = []; - $errors = (int) $conversionInfo['errors']; - - foreach (self::IDNA_ERROR_MAP as $flag => $message) { - if (($flag & $errors) === $flag) { - $messages[] = $message; - } - } - - throw new RuntimeException(sprintf( - 'Failed encoding domain due to errors: %s', - implode(', ', $messages) - )); - } - - public function getFieldValue($format = HeaderInterface::FORMAT_RAW) - { - $emails = []; - $encoding = $this->getEncoding(); - - foreach ($this->getAddressList() as $address) { - $email = $address->getEmail(); - $name = $address->getName(); - - // quote $name if value requires so - if (! empty($name) && (false !== strpos($name, ',') || false !== strpos($name, ';'))) { - // FIXME: what if name contains double quote? - $name = sprintf('"%s"', $name); - } - - if ($format === HeaderInterface::FORMAT_ENCODED - && 'ASCII' !== $encoding - ) { - if (! empty($name)) { - $name = HeaderWrap::mimeEncodeValue($name, $encoding); - } - - if (preg_match('/^(.+)@([^@]+)$/', $email, $matches)) { - $localPart = $matches[1]; - $hostname = $this->idnToAscii($matches[2]); - $email = sprintf('%s@%s', $localPart, $hostname); - } - } - - if (empty($name)) { - $emails[] = $email; - } else { - $emails[] = sprintf('%s <%s>', $name, $email); - } - } - - // Ensure the values are valid before sending them. - if ($format !== HeaderInterface::FORMAT_RAW) { - foreach ($emails as $email) { - HeaderValue::assertValid($email); - } - } - - return implode(',' . Headers::FOLDING, $emails); - } - - public function setEncoding($encoding) - { - $this->encoding = $encoding; - return $this; - } - - public function getEncoding() - { - return $this->encoding; - } - - /** - * Set address list for this header - * - * @param AddressList $addressList - */ - public function setAddressList(AddressList $addressList) - { - $this->addressList = $addressList; - } - - /** - * Get address list managed by this header - * - * @return AddressList - */ - public function getAddressList() - { - if (null === $this->addressList) { - $this->setAddressList(new AddressList()); - } - return $this->addressList; - } - - public function toString() - { - $name = $this->getFieldName(); - $value = $this->getFieldValue(HeaderInterface::FORMAT_ENCODED); - return (empty($value)) ? '' : sprintf('%s: %s', $name, $value); - } - - /** - * Retrieve comments from value, if any. - * - * Supposed to be private, protected as a workaround for PHP bug 68194 - * - * @param string $value - * @return string - */ - protected static function getComments($value) - { - $matches = []; - preg_match_all( - '/\\( - (?P<comment>( - \\\\.| - [^\\\\)] - )+) - \\)/x', - $value, - $matches - ); - return isset($matches['comment']) ? implode(', ', $matches['comment']) : ''; - } - - /** - * Strip all comments from value, if any. - * - * Supposed to be private, protected as a workaround for PHP bug 68194 - * - * @param string $value - * @return string - */ - protected static function stripComments($value) - { - return preg_replace( - '/\\( - ( - \\\\.| - [^\\\\)] - )+ - \\)/x', - '', - $value - ); - } -} diff --git a/lib/laminas/laminas-mail/src/Header/Bcc.php b/lib/laminas/laminas-mail/src/Header/Bcc.php deleted file mode 100644 index 0fd3a12d8..000000000 --- a/lib/laminas/laminas-mail/src/Header/Bcc.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -class Bcc extends AbstractAddressList -{ - /** - * @var string - */ - protected $fieldName = 'Bcc'; - - /** - * @var string - */ - protected static $type = 'bcc'; -} diff --git a/lib/laminas/laminas-mail/src/Header/Cc.php b/lib/laminas/laminas-mail/src/Header/Cc.php deleted file mode 100644 index 625cec41c..000000000 --- a/lib/laminas/laminas-mail/src/Header/Cc.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -class Cc extends AbstractAddressList -{ - protected $fieldName = 'Cc'; - protected static $type = 'cc'; -} diff --git a/lib/laminas/laminas-mail/src/Header/ContentDisposition.php b/lib/laminas/laminas-mail/src/Header/ContentDisposition.php deleted file mode 100644 index 586c8eb14..000000000 --- a/lib/laminas/laminas-mail/src/Header/ContentDisposition.php +++ /dev/null @@ -1,315 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -use Laminas\Mail\Headers; -use Laminas\Mime\Mime; - -class ContentDisposition implements UnstructuredInterface -{ - /** - * 78 chars (RFC 2822) - (semicolon + space (Header::FOLDING)) - * - * @var int - */ - public const MAX_PARAMETER_LENGTH = 76; - - /** - * @var string - */ - protected $disposition = 'inline'; - - /** - * Header encoding - * - * @var string - */ - protected $encoding = 'ASCII'; - - /** - * @var array - */ - protected $parameters = []; - - /** - * @inheritDoc - */ - public static function fromString($headerLine) - { - list($name, $value) = GenericHeader::splitHeaderLine($headerLine); - $value = HeaderWrap::mimeDecodeValue($value); - - // check to ensure proper header type for this factory - if (strtolower($name) !== 'content-disposition') { - throw new Exception\InvalidArgumentException('Invalid header line for Content-Disposition string'); - } - - $value = str_replace(Headers::FOLDING, ' ', $value); - $parts = explode(';', $value, 2); - - $header = new static(); - $header->setDisposition($parts[0]); - - if (isset($parts[1])) { - $values = ListParser::parse(trim($parts[1]), [';', '=']); - $length = count($values); - $continuedValues = []; - - for ($i = 0; $i < $length; $i += 2) { - $value = $values[$i + 1]; - $value = trim($value, "'\" \t\n\r\0\x0B"); - $name = trim($values[$i], "'\" \t\n\r\0\x0B"); - - if (strpos($name, '*')) { - list($name, $count) = explode('*', $name); - // allow optional count: - // Content-Disposition: attachment; filename*=UTF-8''%64%61%61%6D%69%2D%6D%C3%B5%72%76%2E%6A%70%67 - if ($count === "") { - $count = 0; - } - - if (! is_numeric($count)) { - $type = gettype($count); - $value = var_export($count, 1); - throw new Exception\InvalidArgumentException(sprintf( - "Invalid header line for Content-Disposition string". - " - count expected to be numeric, got %s with value %s", - $type, - $value - )); - } - if (! isset($continuedValues[$name])) { - $continuedValues[$name] = []; - } - $continuedValues[$name][$count] = $value; - } else { - $header->setParameter($name, $value); - } - } - - foreach ($continuedValues as $name => $values) { - $value = ''; - for ($i = 0, $iMax = count($values); $i < $iMax; $i++) { - if (! isset($values[$i])) { - throw new Exception\InvalidArgumentException( - 'Invalid header line for Content-Disposition string - incomplete continuation'. - '; HeaderLine: '.$headerLine - ); - } - $value .= $values[$i]; - } - $header->setParameter($name, $value); - } - } - - return $header; - } - - /** - * @inheritDoc - */ - public function getFieldName() - { - return 'Content-Disposition'; - } - - /** - * @inheritDoc - */ - public function getFieldValue($format = HeaderInterface::FORMAT_RAW) - { - $result = $this->disposition; - if (empty($this->parameters)) { - return $result; - } - - foreach ($this->parameters as $attribute => $value) { - $valueIsEncoded = false; - if (HeaderInterface::FORMAT_ENCODED === $format && ! Mime::isPrintable($value)) { - $value = $this->getEncodedValue($value); - $valueIsEncoded = true; - } - - $line = sprintf('%s="%s"', $attribute, $value); - - if (strlen($line) < self::MAX_PARAMETER_LENGTH) { - $lines = explode(Headers::FOLDING, $result); - - if (count($lines) === 1) { - $existingLineLength = strlen('Content-Disposition: ' . $result); - } else { - $existingLineLength = 1 + strlen($lines[count($lines) - 1]); - } - - if ((2 + $existingLineLength + strlen($line)) <= self::MAX_PARAMETER_LENGTH) { - $result .= '; ' . $line; - } else { - $result .= ';' . Headers::FOLDING . $line; - } - } else { - // Use 'continuation' per RFC 2231 - if ($valueIsEncoded) { - $value = HeaderWrap::mimeDecodeValue($value); - } - - $i = 0; - $fullLength = mb_strlen($value, 'UTF-8'); - while ($fullLength > 0) { - $attributePart = $attribute . '*' . $i++ . '="'; - $attLen = mb_strlen($attributePart, 'UTF-8'); - - $subPos = 1; - $valuePart = ''; - while ($subPos <= $fullLength) { - $sub = mb_substr($value, 0, $subPos, 'UTF-8'); - if ($valueIsEncoded) { - $sub = $this->getEncodedValue($sub); - } - if ($attLen + mb_strlen($sub, 'UTF-8') >= self::MAX_PARAMETER_LENGTH) { - $subPos--; - break; - } - $subPos++; - $valuePart = $sub; - } - - $value = mb_substr($value, $subPos, null, 'UTF-8'); - $fullLength = mb_strlen($value, 'UTF-8'); - $result .= ';' . Headers::FOLDING . $attributePart . $valuePart . '"'; - } - } - } - - return $result; - } - - /** - * @param string $value - * @return string - */ - protected function getEncodedValue($value) - { - $configuredEncoding = $this->encoding; - $this->encoding = 'UTF-8'; - $value = HeaderWrap::wrap($value, $this); - $this->encoding = $configuredEncoding; - return $value; - } - - /** - * @inheritDoc - */ - public function setEncoding($encoding) - { - $this->encoding = $encoding; - return $this; - } - - /** - * @inheritDoc - */ - public function getEncoding() - { - return $this->encoding; - } - - /** - * @inheritDoc - */ - public function toString() - { - return 'Content-Disposition: ' . $this->getFieldValue(HeaderInterface::FORMAT_ENCODED); - } - - /** - * Set the content disposition - * Expected values include 'inline', 'attachment' - * - * @param string $disposition - * @return ContentDisposition - */ - public function setDisposition($disposition) - { - $this->disposition = strtolower($disposition); - return $this; - } - - /** - * Retrieve the content disposition - * - * @return string - */ - public function getDisposition() - { - return $this->disposition; - } - - /** - * Add a parameter pair - * - * @param string $name - * @param string $value - * @return ContentDisposition - */ - public function setParameter($name, $value) - { - $name = strtolower($name); - - if (! HeaderValue::isValid($name)) { - throw new Exception\InvalidArgumentException( - 'Invalid content-disposition parameter name detected' - ); - } - // '5' here is for the quotes & equal sign in `name="value"`, - // and the space & semicolon for line folding - if ((strlen($name) + 5) >= self::MAX_PARAMETER_LENGTH) { - throw new Exception\InvalidArgumentException( - 'Invalid content-disposition parameter name detected (too long)' - ); - } - - $this->parameters[$name] = $value; - return $this; - } - - /** - * Get all parameters - * - * @return array - */ - public function getParameters() - { - return $this->parameters; - } - - /** - * Get a parameter by name - * - * @param string $name - * @return null|string - */ - public function getParameter($name) - { - $name = strtolower($name); - if (isset($this->parameters[$name])) { - return $this->parameters[$name]; - } - return null; - } - - /** - * Remove a named parameter - * - * @param string $name - * @return bool - */ - public function removeParameter($name) - { - $name = strtolower($name); - if (isset($this->parameters[$name])) { - unset($this->parameters[$name]); - return true; - } - return false; - } -} diff --git a/lib/laminas/laminas-mail/src/Header/ContentTransferEncoding.php b/lib/laminas/laminas-mail/src/Header/ContentTransferEncoding.php deleted file mode 100644 index 3c80e9274..000000000 --- a/lib/laminas/laminas-mail/src/Header/ContentTransferEncoding.php +++ /dev/null @@ -1,108 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -class ContentTransferEncoding implements HeaderInterface -{ - /** - * Allowed Content-Transfer-Encoding parameters specified by RFC 1521 - * (reduced set) - * @var array - */ - protected static $allowedTransferEncodings = [ - '7bit', - '8bit', - 'quoted-printable', - 'base64', - 'binary', - /* - * not implemented: - * x-token: 'X-' - */ - ]; - - /** - * @var string - */ - protected $transferEncoding; - - /** - * @var array - */ - protected $parameters = []; - - public static function fromString($headerLine) - { - list($name, $value) = GenericHeader::splitHeaderLine($headerLine); - $value = HeaderWrap::mimeDecodeValue($value); - - // check to ensure proper header type for this factory - if (strtolower($name) !== 'content-transfer-encoding') { - throw new Exception\InvalidArgumentException('Invalid header line for Content-Transfer-Encoding string'); - } - - $header = new static(); - $header->setTransferEncoding($value); - - return $header; - } - - public function getFieldName() - { - return 'Content-Transfer-Encoding'; - } - - public function getFieldValue($format = HeaderInterface::FORMAT_RAW) - { - return $this->transferEncoding; - } - - public function setEncoding($encoding) - { - // Header must be always in US-ASCII - return $this; - } - - public function getEncoding() - { - return 'ASCII'; - } - - public function toString() - { - return 'Content-Transfer-Encoding: ' . $this->getFieldValue(); - } - - /** - * Set the content transfer encoding - * - * @param string $transferEncoding - * @throws Exception\InvalidArgumentException - * @return $this - */ - public function setTransferEncoding($transferEncoding) - { - // Per RFC 1521, the value of the header is not case sensitive - $transferEncoding = strtolower($transferEncoding); - - if (! in_array($transferEncoding, static::$allowedTransferEncodings)) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects one of "'. implode(', ', static::$allowedTransferEncodings) . '"; received "%s"', - __METHOD__, - (string) $transferEncoding - )); - } - $this->transferEncoding = $transferEncoding; - return $this; - } - - /** - * Retrieve the content transfer encoding - * - * @return string - */ - public function getTransferEncoding() - { - return $this->transferEncoding; - } -} diff --git a/lib/laminas/laminas-mail/src/Header/ContentType.php b/lib/laminas/laminas-mail/src/Header/ContentType.php deleted file mode 100644 index 99fa9ecc5..000000000 --- a/lib/laminas/laminas-mail/src/Header/ContentType.php +++ /dev/null @@ -1,197 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -use Laminas\Mail\Headers; -use Laminas\Mime\Mime; - -class ContentType implements UnstructuredInterface -{ - /** - * @var string - */ - protected $type; - - /** - * Header encoding - * - * @var string - */ - protected $encoding = 'ASCII'; - - /** - * @var array - */ - protected $parameters = []; - - public static function fromString($headerLine) - { - list($name, $value) = GenericHeader::splitHeaderLine($headerLine); - $value = HeaderWrap::mimeDecodeValue($value); - - // check to ensure proper header type for this factory - if (strtolower($name) !== 'content-type') { - throw new Exception\InvalidArgumentException('Invalid header line for Content-Type string'); - } - - $value = str_replace(Headers::FOLDING, ' ', $value); - $parts = explode(';', $value, 2); - - $header = new static(); - $header->setType($parts[0]); - - if (isset($parts[1])) { - $values = ListParser::parse(trim($parts[1]), [';', '=']); - $length = count($values); - - for ($i = 0; $i < $length; $i += 2) { - $value = $values[$i + 1]; - $value = trim($value, "'\" \t\n\r\0\x0B"); - $header->addParameter($values[$i], $value); - } - } - - return $header; - } - - public function getFieldName() - { - return 'Content-Type'; - } - - public function getFieldValue($format = HeaderInterface::FORMAT_RAW) - { - $prepared = $this->type; - if (empty($this->parameters)) { - return $prepared; - } - - $values = [$prepared]; - foreach ($this->parameters as $attribute => $value) { - if (HeaderInterface::FORMAT_ENCODED === $format && ! Mime::isPrintable($value)) { - $this->encoding = 'UTF-8'; - $value = HeaderWrap::wrap($value, $this); - $this->encoding = 'ASCII'; - } - - $values[] = sprintf('%s="%s"', $attribute, $value); - } - - return implode(';' . Headers::FOLDING, $values); - } - - public function setEncoding($encoding) - { - $this->encoding = $encoding; - return $this; - } - - public function getEncoding() - { - return $this->encoding; - } - - public function toString() - { - return 'Content-Type: ' . $this->getFieldValue(HeaderInterface::FORMAT_ENCODED); - } - - /** - * Set the content type - * - * @param string $type - * @throws Exception\InvalidArgumentException - * @return ContentType - */ - public function setType($type) - { - if (! preg_match('/^[a-z-]+\/[a-z0-9.+-]+$/i', $type)) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects a value in the format "type/subtype"; received "%s"', - __METHOD__, - (string) $type - )); - } - $this->type = $type; - return $this; - } - - /** - * Retrieve the content type - * - * @return string - */ - public function getType() - { - return $this->type; - } - - /** - * Add a parameter pair - * - * @param string $name - * @param string $value - * @return ContentType - * @throws Exception\InvalidArgumentException for parameter names that do not follow RFC 2822 - * @throws Exception\InvalidArgumentException for parameter values that do not follow RFC 2822 - */ - public function addParameter($name, $value) - { - $name = trim(strtolower($name)); - $value = (string) $value; - - if (! HeaderValue::isValid($name)) { - throw new Exception\InvalidArgumentException('Invalid content-type parameter name detected'); - } - if (! HeaderWrap::canBeEncoded($value)) { - throw new Exception\InvalidArgumentException( - 'Parameter value must be composed of printable US-ASCII or UTF-8 characters.' - ); - } - - $this->parameters[$name] = $value; - return $this; - } - - /** - * Get all parameters - * - * @return array - */ - public function getParameters() - { - return $this->parameters; - } - - /** - * Get a parameter by name - * - * @param string $name - * @return null|string - */ - public function getParameter($name) - { - $name = strtolower($name); - if (isset($this->parameters[$name])) { - return $this->parameters[$name]; - } - - return null; - } - - /** - * Remove a named parameter - * - * @param string $name - * @return bool - */ - public function removeParameter($name) - { - $name = strtolower($name); - if (isset($this->parameters[$name])) { - unset($this->parameters[$name]); - return true; - } - return false; - } -} diff --git a/lib/laminas/laminas-mail/src/Header/Date.php b/lib/laminas/laminas-mail/src/Header/Date.php deleted file mode 100644 index d6d3d732b..000000000 --- a/lib/laminas/laminas-mail/src/Header/Date.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -/** - * @todo Add accessors for setting date from DateTime, Laminas\Date, or a string - */ -class Date implements HeaderInterface -{ - /** - * @var string - */ - protected $value; - - public static function fromString($headerLine) - { - list($name, $value) = GenericHeader::splitHeaderLine($headerLine); - $value = HeaderWrap::mimeDecodeValue($value); - - // check to ensure proper header type for this factory - if (strtolower($name) !== 'date') { - throw new Exception\InvalidArgumentException('Invalid header line for Date string'); - } - - $header = new static($value); - - return $header; - } - - public function __construct($value) - { - if (! HeaderValue::isValid($value)) { - throw new Exception\InvalidArgumentException('Invalid Date header value detected'); - } - $this->value = $value; - } - - public function getFieldName() - { - return 'Date'; - } - - public function getFieldValue($format = HeaderInterface::FORMAT_RAW) - { - return $this->value; - } - - public function setEncoding($encoding) - { - // This header must be always in US-ASCII - return $this; - } - - public function getEncoding() - { - return 'ASCII'; - } - - public function toString() - { - return 'Date: ' . $this->getFieldValue(); - } -} diff --git a/lib/laminas/laminas-mail/src/Header/Exception/BadMethodCallException.php b/lib/laminas/laminas-mail/src/Header/Exception/BadMethodCallException.php deleted file mode 100644 index 7506af5f4..000000000 --- a/lib/laminas/laminas-mail/src/Header/Exception/BadMethodCallException.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -namespace Laminas\Mail\Header\Exception; - -use Laminas\Mail\Exception; - -class BadMethodCallException extends Exception\BadMethodCallException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-mail/src/Header/Exception/ExceptionInterface.php b/lib/laminas/laminas-mail/src/Header/Exception/ExceptionInterface.php deleted file mode 100644 index 37493256c..000000000 --- a/lib/laminas/laminas-mail/src/Header/Exception/ExceptionInterface.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -namespace Laminas\Mail\Header\Exception; - -use Laminas\Mail\Exception\ExceptionInterface as MailException; - -interface ExceptionInterface extends MailException -{ -} diff --git a/lib/laminas/laminas-mail/src/Header/Exception/InvalidArgumentException.php b/lib/laminas/laminas-mail/src/Header/Exception/InvalidArgumentException.php deleted file mode 100644 index 7579468f7..000000000 --- a/lib/laminas/laminas-mail/src/Header/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -namespace Laminas\Mail\Header\Exception; - -use Laminas\Mail\Exception; - -class InvalidArgumentException extends Exception\InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-mail/src/Header/Exception/RuntimeException.php b/lib/laminas/laminas-mail/src/Header/Exception/RuntimeException.php deleted file mode 100644 index 6a50b49bc..000000000 --- a/lib/laminas/laminas-mail/src/Header/Exception/RuntimeException.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -namespace Laminas\Mail\Header\Exception; - -use Laminas\Mail\Exception; - -class RuntimeException extends Exception\RuntimeException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-mail/src/Header/From.php b/lib/laminas/laminas-mail/src/Header/From.php deleted file mode 100644 index 8c9a95130..000000000 --- a/lib/laminas/laminas-mail/src/Header/From.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -class From extends AbstractAddressList -{ - protected $fieldName = 'From'; - protected static $type = 'from'; -} diff --git a/lib/laminas/laminas-mail/src/Header/GenericHeader.php b/lib/laminas/laminas-mail/src/Header/GenericHeader.php deleted file mode 100644 index f5ca2a1b2..000000000 --- a/lib/laminas/laminas-mail/src/Header/GenericHeader.php +++ /dev/null @@ -1,195 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -use Laminas\Mail\Header\Exception\InvalidArgumentException; -use Laminas\Mime\Mime; - -class GenericHeader implements HeaderInterface, UnstructuredInterface -{ - /** - * @var string - */ - protected $fieldName; - - /** - * @var string - */ - protected $fieldValue = ''; - - /** - * Header encoding - * - * @var null|string - */ - protected $encoding; - - /** - * @param string $headerLine - * @return GenericHeader - */ - public static function fromString($headerLine) - { - list($name, $value) = self::splitHeaderLine($headerLine); - $value = HeaderWrap::mimeDecodeValue($value); - $header = new static($name, $value); - - return $header; - } - - /** - * Splits the header line in `name` and `value` parts. - * - * @param string $headerLine - * @return string[] `name` in the first index and `value` in the second. - * @throws Exception\InvalidArgumentException If header does not match with the format ``name:value`` - */ - public static function splitHeaderLine($headerLine) - { - $parts = explode(':', $headerLine, 2); - if (count($parts) !== 2) { - throw new Exception\InvalidArgumentException('Header must match with the format "name:value"'); - } - - if (! HeaderName::isValid($parts[0])) { - throw new Exception\InvalidArgumentException('Invalid header name detected'); - } - - if (! HeaderValue::isValid($parts[1])) { - throw new Exception\InvalidArgumentException('Invalid header value detected'); - } - - $parts[1] = ltrim($parts[1]); - - return $parts; - } - - /** - * Constructor - * - * @param string $fieldName Optional - * @param null|string $fieldValue Optional - */ - public function __construct($fieldName = null, $fieldValue = null) - { - if (! $fieldName) { - throw new InvalidArgumentException('Header MUST contain a field name'); - } - - $this->setFieldName($fieldName); - - if ($fieldValue !== null) { - $this->setFieldValue($fieldValue); - } - } - - /** - * Set header name - * - * @param string $fieldName - * @return GenericHeader - * @throws Exception\InvalidArgumentException; - */ - public function setFieldName($fieldName) - { - if (! is_string($fieldName) || empty($fieldName)) { - throw new Exception\InvalidArgumentException('Header name must be a string'); - } - - // Pre-filter to normalize valid characters, change underscore to dash - $fieldName = str_replace(' ', '-', ucwords(str_replace(['_', '-'], ' ', $fieldName))); - - if (! HeaderName::isValid($fieldName)) { - throw new Exception\InvalidArgumentException( - 'Header name must be composed of printable US-ASCII characters, except colon.' - ); - } - - $this->fieldName = $fieldName; - return $this; - } - - public function getFieldName() - { - return $this->fieldName; - } - - /** - * Set header value - * - * @param string $fieldValue - * @return GenericHeader - * @throws Exception\InvalidArgumentException; - */ - public function setFieldValue($fieldValue) - { - $fieldValue = (string) $fieldValue; - - if (! HeaderWrap::canBeEncoded($fieldValue)) { - throw new Exception\InvalidArgumentException( - 'Header value must be composed of printable US-ASCII characters and valid folding sequences.' - ); - } - - $this->fieldValue = $fieldValue; - $this->encoding = null; - - return $this; - } - - public function getFieldValue($format = HeaderInterface::FORMAT_RAW) - { - if (HeaderInterface::FORMAT_ENCODED === $format) { - return HeaderWrap::wrap($this->fieldValue, $this); - } - - return $this->fieldValue; - } - - public function setEncoding($encoding) - { - if ($encoding === $this->encoding) { - return $this; - } - - if ($encoding === null) { - $this->encoding = null; - return $this; - } - - $encoding = strtoupper($encoding); - if ($encoding === 'UTF-8') { - $this->encoding = $encoding; - return $this; - } - - if ($encoding === 'ASCII' && Mime::isPrintable($this->fieldValue)) { - $this->encoding = $encoding; - return $this; - } - - $this->encoding = null; - - return $this; - } - - public function getEncoding() - { - if (! $this->encoding) { - $this->encoding = Mime::isPrintable($this->fieldValue) ? 'ASCII' : 'UTF-8'; - } - - return $this->encoding; - } - - public function toString() - { - $name = $this->getFieldName(); - if (empty($name)) { - throw new Exception\RuntimeException('Header name is not set, use setFieldName()'); - } - $value = $this->getFieldValue(HeaderInterface::FORMAT_ENCODED); - - return $name . ': ' . $value; - } -} diff --git a/lib/laminas/laminas-mail/src/Header/GenericMultiHeader.php b/lib/laminas/laminas-mail/src/Header/GenericMultiHeader.php deleted file mode 100644 index 9d62a63a0..000000000 --- a/lib/laminas/laminas-mail/src/Header/GenericMultiHeader.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -/** - * Generic class for Headers with multiple occurs in the same message - */ -class GenericMultiHeader extends GenericHeader implements MultipleHeadersInterface -{ - public static function fromString($headerLine) - { - list($fieldName, $fieldValue) = GenericHeader::splitHeaderLine($headerLine); - $fieldValue = HeaderWrap::mimeDecodeValue($fieldValue); - - if (strpos($fieldValue, ',')) { - $headers = []; - foreach (explode(',', $fieldValue) as $multiValue) { - $headers[] = new static($fieldName, $multiValue); - } - return $headers; - } - - return new static($fieldName, $fieldValue); - } - - /** - * Cast multiple header objects to a single string header - * - * @param array $headers - * @throws Exception\InvalidArgumentException - * @return string - */ - public function toStringMultipleHeaders(array $headers) - { - $name = $this->getFieldName(); - $values = [$this->getFieldValue(HeaderInterface::FORMAT_ENCODED)]; - - foreach ($headers as $header) { - if (! $header instanceof static) { - throw new Exception\InvalidArgumentException( - 'This method toStringMultipleHeaders was expecting an array of headers of the same type' - ); - } - $values[] = $header->getFieldValue(HeaderInterface::FORMAT_ENCODED); - } - - return $name . ': ' . implode(',', $values); - } -} diff --git a/lib/laminas/laminas-mail/src/Header/HeaderInterface.php b/lib/laminas/laminas-mail/src/Header/HeaderInterface.php deleted file mode 100644 index c5e98341c..000000000 --- a/lib/laminas/laminas-mail/src/Header/HeaderInterface.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -interface HeaderInterface -{ - /** - * Format value in Mime-Encoding (Quoted-Printable). Result is valid US-ASCII string - * - * @var bool - */ - public const FORMAT_ENCODED = true; - - /** - * Return value in internal encoding which is usually UTF-8 - * - * @var bool - */ - public const FORMAT_RAW = false; - - /** - * Factory to generate a header object from a string - * - * @param string $headerLine - * @return static - * @throws Exception\InvalidArgumentException If the header does not match with RFC 2822 definition. - * @see http://tools.ietf.org/html/rfc2822#section-2.2 - */ - public static function fromString($headerLine); - - /** - * Retrieve header name - * - * @return string - */ - public function getFieldName(); - - /** - * Retrieve header value - * - * @param bool $format Return the value in Mime::Encoded or in Raw format - * @return string - */ - public function getFieldValue($format = self::FORMAT_RAW); - - /** - * Set header encoding - * - * @param string $encoding - * @return $this - */ - public function setEncoding($encoding); - - /** - * Get header encoding - * - * @return string - */ - public function getEncoding(); - - /** - * Cast to string - * - * Returns in form of "NAME: VALUE" - * - * @return string - */ - public function toString(); -} diff --git a/lib/laminas/laminas-mail/src/Header/HeaderLoader.php b/lib/laminas/laminas-mail/src/Header/HeaderLoader.php deleted file mode 100644 index 7e622e37a..000000000 --- a/lib/laminas/laminas-mail/src/Header/HeaderLoader.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -use Laminas\Loader\PluginClassLoader; - -/** - * Plugin Class Loader implementation for HTTP headers - */ -class HeaderLoader extends PluginClassLoader -{ - /** - * @var array Pre-aliased Header plugins - */ - protected $plugins = [ - 'bcc' => Bcc::class, - 'cc' => Cc::class, - 'contentdisposition' => ContentDisposition::class, - 'content_disposition' => ContentDisposition::class, - 'content-disposition' => ContentDisposition::class, - 'contenttype' => ContentType::class, - 'content_type' => ContentType::class, - 'content-type' => ContentType::class, - 'contenttransferencoding' => ContentTransferEncoding::class, - 'content_transfer_encoding' => ContentTransferEncoding::class, - 'content-transfer-encoding' => ContentTransferEncoding::class, - 'date' => Date::class, - 'from' => From::class, - 'in-reply-to' => InReplyTo::class, - 'message-id' => MessageId::class, - 'mimeversion' => MimeVersion::class, - 'mime_version' => MimeVersion::class, - 'mime-version' => MimeVersion::class, - 'received' => Received::class, - 'references' => References::class, - 'replyto' => ReplyTo::class, - 'reply_to' => ReplyTo::class, - 'reply-to' => ReplyTo::class, - 'sender' => Sender::class, - 'subject' => Subject::class, - 'to' => To::class, - ]; -} diff --git a/lib/laminas/laminas-mail/src/Header/HeaderLocator.php b/lib/laminas/laminas-mail/src/Header/HeaderLocator.php deleted file mode 100644 index fcaf2774c..000000000 --- a/lib/laminas/laminas-mail/src/Header/HeaderLocator.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Mail\Header; - -/** - * Plugin Class Loader implementation for HTTP headers - */ -final class HeaderLocator implements HeaderLocatorInterface -{ - /** - * @var array Pre-aliased Header plugins - */ - private $plugins = [ - 'bcc' => Bcc::class, - 'cc' => Cc::class, - 'contentdisposition' => ContentDisposition::class, - 'content_disposition' => ContentDisposition::class, - 'content-disposition' => ContentDisposition::class, - 'contenttype' => ContentType::class, - 'content_type' => ContentType::class, - 'content-type' => ContentType::class, - 'contenttransferencoding' => ContentTransferEncoding::class, - 'content_transfer_encoding' => ContentTransferEncoding::class, - 'content-transfer-encoding' => ContentTransferEncoding::class, - 'date' => Date::class, - 'from' => From::class, - 'in-reply-to' => InReplyTo::class, - 'message-id' => MessageId::class, - 'mimeversion' => MimeVersion::class, - 'mime_version' => MimeVersion::class, - 'mime-version' => MimeVersion::class, - 'received' => Received::class, - 'references' => References::class, - 'replyto' => ReplyTo::class, - 'reply_to' => ReplyTo::class, - 'reply-to' => ReplyTo::class, - 'sender' => Sender::class, - 'subject' => Subject::class, - 'to' => To::class, - ]; - - public function get(string $name, ?string $default = null): ?string - { - $name = $this->normalizeName($name); - return $this->plugins[$name] ?? $default; - } - - public function has(string $name): bool - { - return isset($this->plugins[$this->normalizeName($name)]); - } - - public function add(string $name, string $class): void - { - $this->plugins[$this->normalizeName($name)] = $class; - } - - public function remove(string $name): void - { - unset($this->plugins[$this->normalizeName($name)]); - } - - private function normalizeName(string $name): string - { - return strtolower($name); - } -} diff --git a/lib/laminas/laminas-mail/src/Header/HeaderLocatorInterface.php b/lib/laminas/laminas-mail/src/Header/HeaderLocatorInterface.php deleted file mode 100644 index 28a93dc95..000000000 --- a/lib/laminas/laminas-mail/src/Header/HeaderLocatorInterface.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Mail\Header; - -/** - * Interface detailing how to resolve header names to classes. - */ -interface HeaderLocatorInterface -{ - public function get(string $name, ?string $default = null): ?string; - - public function has(string $name): bool; - - public function add(string $name, string $class): void; - - public function remove(string $name): void; -} diff --git a/lib/laminas/laminas-mail/src/Header/HeaderName.php b/lib/laminas/laminas-mail/src/Header/HeaderName.php deleted file mode 100644 index fcfcfcf09..000000000 --- a/lib/laminas/laminas-mail/src/Header/HeaderName.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -final class HeaderName -{ - /** - * No public constructor. - */ - private function __construct() - { - } - - /** - * Filter the header name according to RFC 2822 - * - * @see http://www.rfc-base.org/txt/rfc-2822.txt (section 2.2) - * @param string $name - * @return string - */ - public static function filter($name) - { - $result = ''; - $tot = strlen($name); - for ($i = 0; $i < $tot; $i += 1) { - $ord = ord($name[$i]); - if ($ord > 32 && $ord < 127 && $ord !== 58) { - $result .= $name[$i]; - } - } - return $result; - } - - /** - * Determine if the header name contains any invalid characters. - * - * @param string $name - * @return bool - */ - public static function isValid($name) - { - $tot = strlen($name); - for ($i = 0; $i < $tot; $i += 1) { - $ord = ord($name[$i]); - if ($ord < 33 || $ord > 126 || $ord === 58) { - return false; - } - } - return true; - } - - /** - * Assert that the header name is valid. - * - * Raises an exception if invalid. - * - * @param string $name - * @throws Exception\RuntimeException - * @return void - */ - public static function assertValid($name) - { - if (! self::isValid($name)) { - throw new Exception\RuntimeException('Invalid header name detected'); - } - } -} diff --git a/lib/laminas/laminas-mail/src/Header/HeaderValue.php b/lib/laminas/laminas-mail/src/Header/HeaderValue.php deleted file mode 100644 index 175801801..000000000 --- a/lib/laminas/laminas-mail/src/Header/HeaderValue.php +++ /dev/null @@ -1,110 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -final class HeaderValue -{ - /** - * No public constructor. - */ - private function __construct() - { - } - - /** - * Filter the header value according to RFC 2822 - * - * @see http://www.rfc-base.org/txt/rfc-2822.txt (section 2.2) - * @param string $value - * @return string - */ - public static function filter($value) - { - $result = ''; - $total = strlen($value); - - // Filter for CR and LF characters, leaving CRLF + WSP sequences for - // Long Header Fields (section 2.2.3 of RFC 2822) - for ($i = 0; $i < $total; $i += 1) { - $ord = ord($value[$i]); - if ($ord === 10 || $ord > 127) { - continue; - } - - if ($ord === 13) { - if ($i + 2 >= $total) { - continue; - } - - $lf = ord($value[$i + 1]); - $sp = ord($value[$i + 2]); - - if ($lf !== 10 || $sp !== 32) { - continue; - } - - $result .= "\r\n "; - $i += 2; - continue; - } - - $result .= $value[$i]; - } - - return $result; - } - - /** - * Determine if the header value contains any invalid characters. - * - * @see http://www.rfc-base.org/txt/rfc-2822.txt (section 2.2) - * @param string $value - * @return bool - */ - public static function isValid($value) - { - $total = strlen($value); - for ($i = 0; $i < $total; $i += 1) { - $ord = ord($value[$i]); - - // bare LF means we aren't valid - if ($ord === 10 || $ord > 127) { - return false; - } - - if ($ord === 13) { - if ($i + 2 >= $total) { - return false; - } - - $lf = ord($value[$i + 1]); - $sp = ord($value[$i + 2]); - - if ($lf !== 10 || ! in_array($sp, [9, 32], true)) { - return false; - } - - // skip over the LF following this - $i += 2; - } - } - - return true; - } - - /** - * Assert that the header value is valid. - * - * Raises an exception if invalid. - * - * @param string $value - * @throws Exception\RuntimeException - * @return void - */ - public static function assertValid($value) - { - if (! self::isValid($value)) { - throw new Exception\RuntimeException('Invalid header value detected'); - } - } -} diff --git a/lib/laminas/laminas-mail/src/Header/HeaderWrap.php b/lib/laminas/laminas-mail/src/Header/HeaderWrap.php deleted file mode 100644 index 483f51a53..000000000 --- a/lib/laminas/laminas-mail/src/Header/HeaderWrap.php +++ /dev/null @@ -1,155 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -use Laminas\Mail\Headers; -use Laminas\Mime\Mime; - -/** - * Utility class used for creating wrapped or MIME-encoded versions of header - * values. - */ -abstract class HeaderWrap -{ - /** - * Wrap a long header line - * - * @param string $value - * @param HeaderInterface $header - * @return string - */ - public static function wrap($value, HeaderInterface $header) - { - if ($header instanceof UnstructuredInterface) { - return static::wrapUnstructuredHeader($value, $header); - } elseif ($header instanceof StructuredInterface) { - return static::wrapStructuredHeader($value, $header); - } - return $value; - } - - /** - * Wrap an unstructured header line - * - * Wrap at 78 characters or before, based on whitespace. - * - * @param string $value - * @param HeaderInterface $header - * @return string - */ - protected static function wrapUnstructuredHeader($value, HeaderInterface $header) - { - $encoding = $header->getEncoding(); - if ($encoding == 'ASCII') { - return wordwrap($value, 78, Headers::FOLDING); - } - return static::mimeEncodeValue($value, $encoding, 78); - } - - /** - * Wrap a structured header line - * - * @param string $value - * @param StructuredInterface $header - * @return string - */ - protected static function wrapStructuredHeader($value, StructuredInterface $header) - { - $delimiter = $header->getDelimiter(); - - $length = strlen($value); - $lines = []; - $temp = ''; - for ($i = 0; $i < $length; $i++) { - $temp .= $value[$i]; - if ($value[$i] == $delimiter) { - $lines[] = $temp; - $temp = ''; - } - } - return implode(Headers::FOLDING, $lines); - } - - /** - * MIME-encode a value - * - * Performs quoted-printable encoding on a value, setting maximum - * line-length to 998. - * - * @param string $value - * @param string $encoding - * @param int $lineLength maximum line-length, by default 998 - * @return string Returns the mime encode value without the last line ending - */ - public static function mimeEncodeValue($value, $encoding, $lineLength = 998) - { - return Mime::encodeQuotedPrintableHeader($value, $encoding, $lineLength, Headers::EOL); - } - - /** - * MIME-decode a value - * - * Performs quoted-printable decoding on a value. - * - * @param string $value - * @return string Returns the mime encode value without the last line ending - */ - public static function mimeDecodeValue($value) - { - // unfold first, because iconv_mime_decode is discarding "\n" with no apparent reason - // making the resulting value no longer valid. - - // see https://tools.ietf.org/html/rfc2822#section-2.2.3 about unfolding - $parts = explode(Headers::FOLDING, $value); - $value = implode(' ', $parts); - - $decodedValue = iconv_mime_decode($value, ICONV_MIME_DECODE_CONTINUE_ON_ERROR, 'UTF-8'); - - // imap (unlike iconv) can handle multibyte headers which are splitted across multiple line - if (self::isNotDecoded($value, $decodedValue) && extension_loaded('imap')) { - return array_reduce( - imap_mime_header_decode(imap_utf8($value)), - function ($accumulator, $headerPart) { - return $accumulator . $headerPart->text; - }, - '' - ); - } - - return $decodedValue; - } - - private static function isNotDecoded($originalValue, $value) - { - return 0 === strpos($value, '=?') - && strlen($value) - 2 === strpos($value, '?=') - && false !== strpos($originalValue, $value); - } - - /** - * Test if is possible apply MIME-encoding - * - * @param string $value - * @return bool - */ - public static function canBeEncoded($value) - { - // avoid any wrapping by specifying line length long enough - // "test" -> 4 - // "x-test: =?ISO-8859-1?B?dGVzdA==?=" -> 33 - // 8 +2 +3 +3 -> 16 - $charset = 'UTF-8'; - $lineLength = strlen($value) * 4 + strlen($charset) + 16; - - $preferences = [ - 'scheme' => 'Q', - 'input-charset' => $charset, - 'output-charset' => $charset, - 'line-length' => $lineLength, - ]; - - $encoded = iconv_mime_encode('x-test', $value, $preferences); - - return (false !== $encoded); - } -} diff --git a/lib/laminas/laminas-mail/src/Header/IdentificationField.php b/lib/laminas/laminas-mail/src/Header/IdentificationField.php deleted file mode 100644 index 2c5084369..000000000 --- a/lib/laminas/laminas-mail/src/Header/IdentificationField.php +++ /dev/null @@ -1,137 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -use Laminas\Mail\Headers; - -/** - * @see https://tools.ietf.org/html/rfc5322#section-3.6.4 - */ -abstract class IdentificationField implements HeaderInterface -{ - /** - * @var string lower case field name - */ - protected static $type; - - /** - * @var string[] - */ - protected $messageIds; - - /** - * @var string - */ - protected $fieldName; - - /** - * @param string $headerLine - * @return static - */ - public static function fromString($headerLine) - { - list($name, $value) = GenericHeader::splitHeaderLine($headerLine); - if (strtolower($name) !== static::$type) { - throw new Exception\InvalidArgumentException(sprintf( - 'Invalid header line for "%s" string', - __CLASS__ - )); - } - - $value = HeaderWrap::mimeDecodeValue($value); - - $messageIds = array_map( - [self::class, "trimMessageId"], - explode(" ", $value) - ); - - $header = new static(); - $header->setIds($messageIds); - - return $header; - } - - /** - * @param string $id - * @return string - */ - private static function trimMessageId($id) - { - return trim($id, "\t\n\r\0\x0B<>"); - } - - /** - * @return string - */ - public function getFieldName() - { - return $this->fieldName; - } - - /** - * @param bool $format - * @return string - */ - public function getFieldValue($format = HeaderInterface::FORMAT_RAW) - { - return implode(Headers::FOLDING, array_map(function ($id) { - return sprintf('<%s>', $id); - }, $this->messageIds)); - } - - /** - * @param string $encoding Ignored; headers of this type MUST always be in - * ASCII. - * @return static This method is a no-op, and implements a fluent interface. - */ - public function setEncoding($encoding) - { - return $this; - } - - /** - * @return string Always returns ASCII - */ - public function getEncoding() - { - return 'ASCII'; - } - - /** - * @return string - */ - public function toString() - { - return sprintf('%s: %s', $this->getFieldName(), $this->getFieldValue()); - } - - /** - * Set the message ids - * - * @param string[] $ids - * @return static This method implements a fluent interface. - */ - public function setIds($ids) - { - foreach ($ids as $id) { - if (! HeaderValue::isValid($id) - || preg_match("/[\r\n]/", $id) - ) { - throw new Exception\InvalidArgumentException('Invalid ID detected'); - } - } - - $this->messageIds = array_map([self::class, "trimMessageId"], $ids); - return $this; - } - - /** - * Retrieve the message ids - * - * @return string[] - */ - public function getIds() - { - return $this->messageIds; - } -} diff --git a/lib/laminas/laminas-mail/src/Header/InReplyTo.php b/lib/laminas/laminas-mail/src/Header/InReplyTo.php deleted file mode 100644 index 6698d441a..000000000 --- a/lib/laminas/laminas-mail/src/Header/InReplyTo.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -class InReplyTo extends IdentificationField -{ - protected $fieldName = 'In-Reply-To'; - protected static $type = 'in-reply-to'; -} diff --git a/lib/laminas/laminas-mail/src/Header/ListParser.php b/lib/laminas/laminas-mail/src/Header/ListParser.php deleted file mode 100644 index bc3dcc070..000000000 --- a/lib/laminas/laminas-mail/src/Header/ListParser.php +++ /dev/null @@ -1,93 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -use function in_array; - -/** - * @internal - */ -class ListParser -{ - public const CHAR_QUOTES = ['\'', '"']; - public const CHAR_DELIMS = [',', ';']; - public const CHAR_ESCAPE = '\\'; - - /** - * @param string $value - * @param array $delims Delimiters allowed between values; parser will - * split on these, as long as they are not within quotes. Defaults - * to ListParser::CHAR_DELIMS. - * @return array - */ - public static function parse($value, array $delims = self::CHAR_DELIMS) - { - $values = []; - $length = strlen($value); - $currentValue = ''; - $inEscape = false; - $inQuote = false; - $currentQuoteDelim = null; - - for ($i = 0; $i < $length; $i += 1) { - $char = $value[$i]; - - // If we are in an escape sequence, append the character and continue. - if ($inEscape) { - $currentValue .= $char; - $inEscape = false; - continue; - } - - // If we are not in a quoted string, and have a delimiter, append - // the current value to the list, and reset the current value. - if (in_array($char, $delims, true) && ! $inQuote) { - $values [] = $currentValue; - $currentValue = ''; - continue; - } - - // Append the character to the current value - $currentValue .= $char; - - // Escape sequence discovered. - if (self::CHAR_ESCAPE === $char) { - $inEscape = true; - continue; - } - - // If the character is not a quote character, we are done - // processing it. - if (! in_array($char, self::CHAR_QUOTES)) { - continue; - } - - // If the character matches a previously matched quote delimiter, - // we reset our quote status and the currently opened quote - // delimiter. - if ($char === $currentQuoteDelim) { - $inQuote = false; - $currentQuoteDelim = null; - continue; - } - - // If already in quote and the character does not match the previously - // matched quote delimiter, we're done here. - if ($inQuote) { - continue; - } - - // Otherwise, we're starting a quoted string. - $inQuote = true; - $currentQuoteDelim = $char; - } - - // If we reached the end of the string and still have a current value, - // append it to the list (no delimiter was reached). - if ('' !== $currentValue) { - $values [] = $currentValue; - } - - return $values; - } -} diff --git a/lib/laminas/laminas-mail/src/Header/MessageId.php b/lib/laminas/laminas-mail/src/Header/MessageId.php deleted file mode 100644 index 4f9f9db44..000000000 --- a/lib/laminas/laminas-mail/src/Header/MessageId.php +++ /dev/null @@ -1,113 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -class MessageId implements HeaderInterface -{ - /** - * @var string - */ - protected $messageId; - - public static function fromString($headerLine) - { - list($name, $value) = GenericHeader::splitHeaderLine($headerLine); - $value = HeaderWrap::mimeDecodeValue($value); - - // check to ensure proper header type for this factory - if (strtolower($name) !== 'message-id') { - throw new Exception\InvalidArgumentException('Invalid header line for Message-ID string'); - } - - $header = new static(); - $header->setId($value); - - return $header; - } - - public function getFieldName() - { - return 'Message-ID'; - } - - public function getFieldValue($format = HeaderInterface::FORMAT_RAW) - { - return $this->messageId; - } - - public function setEncoding($encoding) - { - // This header must be always in US-ASCII - return $this; - } - - public function getEncoding() - { - return 'ASCII'; - } - - public function toString() - { - return 'Message-ID: ' . $this->getFieldValue(); - } - - /** - * Set the message id - * - * @param string|null $id - * @return MessageId - */ - public function setId($id = null) - { - if ($id === null) { - $id = $this->createMessageId(); - } else { - $id = trim($id, '<>'); - } - - if (! HeaderValue::isValid($id) - || preg_match("/[\r\n]/", $id) - ) { - throw new Exception\InvalidArgumentException('Invalid ID detected'); - } - - $this->messageId = sprintf('<%s>', $id); - return $this; - } - - /** - * Retrieve the message id - * - * @return string - */ - public function getId() - { - return $this->messageId; - } - - /** - * Creates the Message-ID - * - * @return string - */ - public function createMessageId() - { - $time = time(); - - if (isset($_SERVER['REMOTE_ADDR'])) { - $user = $_SERVER['REMOTE_ADDR']; - } else { - $user = getmypid(); - } - - $rand = mt_rand(); - - if (isset($_SERVER["SERVER_NAME"])) { - $hostName = $_SERVER["SERVER_NAME"]; - } else { - $hostName = php_uname('n'); - } - - return sha1($time . $user . $rand) . '@' . $hostName; - } -} diff --git a/lib/laminas/laminas-mail/src/Header/MimeVersion.php b/lib/laminas/laminas-mail/src/Header/MimeVersion.php deleted file mode 100644 index 435029470..000000000 --- a/lib/laminas/laminas-mail/src/Header/MimeVersion.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -class MimeVersion implements HeaderInterface -{ - /** - * @var string Version string - */ - protected $version = '1.0'; - - public static function fromString($headerLine) - { - list($name, $value) = GenericHeader::splitHeaderLine($headerLine); - $value = HeaderWrap::mimeDecodeValue($value); - - // check to ensure proper header type for this factory - if (strtolower($name) !== 'mime-version') { - throw new Exception\InvalidArgumentException('Invalid header line for MIME-Version string'); - } - - // Check for version, and set if found - $header = new static(); - if (preg_match('/^(?P<version>\d+\.\d+)$/', $value, $matches)) { - $header->setVersion($matches['version']); - } - - return $header; - } - - public function getFieldName() - { - return 'MIME-Version'; - } - - public function getFieldValue($format = HeaderInterface::FORMAT_RAW) - { - return $this->version; - } - - public function setEncoding($encoding) - { - // This header must be always in US-ASCII - return $this; - } - - public function getEncoding() - { - return 'ASCII'; - } - - public function toString() - { - return 'MIME-Version: ' . $this->getFieldValue(); - } - - /** - * Set the version string used in this header - * - * @param string $version - * @return MimeVersion - */ - public function setVersion($version) - { - if (! preg_match('/^[1-9]\d*\.\d+$/', $version)) { - throw new Exception\InvalidArgumentException('Invalid MIME-Version value detected'); - } - $this->version = $version; - return $this; - } - - /** - * Retrieve the version string for this header - * - * @return string - */ - public function getVersion() - { - return $this->version; - } -} diff --git a/lib/laminas/laminas-mail/src/Header/MultipleHeadersInterface.php b/lib/laminas/laminas-mail/src/Header/MultipleHeadersInterface.php deleted file mode 100644 index b109e68dd..000000000 --- a/lib/laminas/laminas-mail/src/Header/MultipleHeadersInterface.php +++ /dev/null @@ -1,8 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -interface MultipleHeadersInterface extends HeaderInterface -{ - public function toStringMultipleHeaders(array $headers); -} diff --git a/lib/laminas/laminas-mail/src/Header/Received.php b/lib/laminas/laminas-mail/src/Header/Received.php deleted file mode 100644 index 037b6bc79..000000000 --- a/lib/laminas/laminas-mail/src/Header/Received.php +++ /dev/null @@ -1,86 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -use Laminas\Mail\Headers; - -/** - * @todo Allow setting date from DateTime, Laminas\Date, or string - */ -class Received implements HeaderInterface, MultipleHeadersInterface -{ - /** - * @var string - */ - protected $value; - - public static function fromString($headerLine) - { - list($name, $value) = GenericHeader::splitHeaderLine($headerLine); - $value = HeaderWrap::mimeDecodeValue($value); - - // check to ensure proper header type for this factory - if (strtolower($name) !== 'received') { - throw new Exception\InvalidArgumentException('Invalid header line for Received string'); - } - - $header = new static($value); - - return $header; - } - - public function __construct($value = '') - { - if (! HeaderValue::isValid($value)) { - throw new Exception\InvalidArgumentException('Invalid Received value provided'); - } - $this->value = $value; - } - - public function getFieldName() - { - return 'Received'; - } - - public function getFieldValue($format = HeaderInterface::FORMAT_RAW) - { - return $this->value; - } - - public function setEncoding($encoding) - { - // This header must be always in US-ASCII - return $this; - } - - public function getEncoding() - { - return 'ASCII'; - } - - public function toString() - { - return 'Received: ' . $this->getFieldValue(); - } - - /** - * Serialize collection of Received headers to string - * - * @param array $headers - * @throws Exception\RuntimeException - * @return string - */ - public function toStringMultipleHeaders(array $headers) - { - $strings = [$this->toString()]; - foreach ($headers as $header) { - if (! $header instanceof self) { - throw new Exception\RuntimeException( - 'The Received multiple header implementation can only accept an array of Received headers' - ); - } - $strings[] = $header->toString(); - } - return implode(Headers::EOL, $strings); - } -} diff --git a/lib/laminas/laminas-mail/src/Header/References.php b/lib/laminas/laminas-mail/src/Header/References.php deleted file mode 100644 index 9b7b92fe7..000000000 --- a/lib/laminas/laminas-mail/src/Header/References.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -class References extends IdentificationField -{ - protected $fieldName = 'References'; - protected static $type = 'references'; -} diff --git a/lib/laminas/laminas-mail/src/Header/ReplyTo.php b/lib/laminas/laminas-mail/src/Header/ReplyTo.php deleted file mode 100644 index 9a8b9e7f4..000000000 --- a/lib/laminas/laminas-mail/src/Header/ReplyTo.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -class ReplyTo extends AbstractAddressList -{ - protected $fieldName = 'Reply-To'; - protected static $type = 'reply-to'; -} diff --git a/lib/laminas/laminas-mail/src/Header/Sender.php b/lib/laminas/laminas-mail/src/Header/Sender.php deleted file mode 100644 index fdc253315..000000000 --- a/lib/laminas/laminas-mail/src/Header/Sender.php +++ /dev/null @@ -1,147 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -use Laminas\Mail; -use Laminas\Mime\Mime; - -/** - * Sender header class methods. - * - * @see https://tools.ietf.org/html/rfc2822 RFC 2822 - * @see https://tools.ietf.org/html/rfc2047 RFC 2047 - */ -class Sender implements HeaderInterface -{ - /** - * @var \Laminas\Mail\Address\AddressInterface - */ - protected $address; - - /** - * Header encoding - * - * @var null|string - */ - protected $encoding; - - public static function fromString($headerLine) - { - list($name, $value) = GenericHeader::splitHeaderLine($headerLine); - $value = HeaderWrap::mimeDecodeValue($value); - - // check to ensure proper header type for this factory - if (strtolower($name) !== 'sender') { - throw new Exception\InvalidArgumentException('Invalid header name for Sender string'); - } - - $header = new static(); - - /** - * matches the header value so that the email must be enclosed by < > when a name is present - * 'name' and 'email' capture groups correspond respectively to 'display-name' and 'addr-spec' in the ABNF - * @see https://tools.ietf.org/html/rfc5322#section-3.4 - */ - $hasMatches = preg_match( - '/^(?:(?P<name>.+)\s)?(?(name)<|<?)(?P<email>[^\s]+?)(?(name)>|>?)$/', - $value, - $matches - ); - - if ($hasMatches !== 1) { - throw new Exception\InvalidArgumentException('Invalid header value for Sender string'); - } - - $senderName = trim($matches['name']); - - if (empty($senderName)) { - $senderName = null; - } - - $header->setAddress($matches['email'], $senderName); - - return $header; - } - - public function getFieldName() - { - return 'Sender'; - } - - public function getFieldValue($format = HeaderInterface::FORMAT_RAW) - { - if (! $this->address instanceof Mail\Address\AddressInterface) { - return ''; - } - - $email = sprintf('<%s>', $this->address->getEmail()); - $name = $this->address->getName(); - - if (! empty($name)) { - if ($format == HeaderInterface::FORMAT_ENCODED) { - $encoding = $this->getEncoding(); - if ('ASCII' !== $encoding) { - $name = HeaderWrap::mimeEncodeValue($name, $encoding); - } - } - $email = sprintf('%s %s', $name, $email); - } - - return $email; - } - - public function setEncoding($encoding) - { - $this->encoding = $encoding; - return $this; - } - - public function getEncoding() - { - if (! $this->encoding) { - $this->encoding = Mime::isPrintable($this->getFieldValue(HeaderInterface::FORMAT_RAW)) - ? 'ASCII' - : 'UTF-8'; - } - - return $this->encoding; - } - - public function toString() - { - return 'Sender: ' . $this->getFieldValue(HeaderInterface::FORMAT_ENCODED); - } - - /** - * Set the address used in this header - * - * @param string|\Laminas\Mail\Address\AddressInterface $emailOrAddress - * @param null|string $name - * @throws Exception\InvalidArgumentException - * @return Sender - */ - public function setAddress($emailOrAddress, $name = null) - { - if (is_string($emailOrAddress)) { - $emailOrAddress = new Mail\Address($emailOrAddress, $name); - } elseif (! $emailOrAddress instanceof Mail\Address\AddressInterface) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects a string or AddressInterface object; received "%s"', - __METHOD__, - (is_object($emailOrAddress) ? get_class($emailOrAddress) : gettype($emailOrAddress)) - )); - } - $this->address = $emailOrAddress; - return $this; - } - - /** - * Retrieve the internal address from this header - * - * @return \Laminas\Mail\Address\AddressInterface|null - */ - public function getAddress() - { - return $this->address; - } -} diff --git a/lib/laminas/laminas-mail/src/Header/StructuredInterface.php b/lib/laminas/laminas-mail/src/Header/StructuredInterface.php deleted file mode 100644 index f487bb3f2..000000000 --- a/lib/laminas/laminas-mail/src/Header/StructuredInterface.php +++ /dev/null @@ -1,13 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -interface StructuredInterface extends HeaderInterface -{ - /** - * Return the delimiter at which a header line should be wrapped - * - * @return string - */ - public function getDelimiter(); -} diff --git a/lib/laminas/laminas-mail/src/Header/Subject.php b/lib/laminas/laminas-mail/src/Header/Subject.php deleted file mode 100644 index 48074237f..000000000 --- a/lib/laminas/laminas-mail/src/Header/Subject.php +++ /dev/null @@ -1,113 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -use Laminas\Mime\Mime; - -/** - * Subject header class methods. - * - * @see https://tools.ietf.org/html/rfc2822 RFC 2822 - * @see https://tools.ietf.org/html/rfc2047 RFC 2047 - */ -class Subject implements UnstructuredInterface -{ - /** - * @var string - */ - protected $subject = ''; - - /** - * Header encoding - * - * @var null|string - */ - protected $encoding; - - public static function fromString($headerLine) - { - list($name, $value) = GenericHeader::splitHeaderLine($headerLine); - $value = HeaderWrap::mimeDecodeValue($value); - - // check to ensure proper header type for this factory - if (strtolower($name) !== 'subject') { - throw new Exception\InvalidArgumentException('Invalid header line for Subject string'); - } - - $header = new static(); - $header->setSubject($value); - - return $header; - } - - public function getFieldName() - { - return 'Subject'; - } - - public function getFieldValue($format = HeaderInterface::FORMAT_RAW) - { - if (HeaderInterface::FORMAT_ENCODED === $format) { - return HeaderWrap::wrap($this->subject, $this); - } - - return $this->subject; - } - - public function setEncoding($encoding) - { - if ($encoding === $this->encoding) { - return $this; - } - - if ($encoding === null) { - $this->encoding = null; - return $this; - } - - $encoding = strtoupper($encoding); - if ($encoding === 'UTF-8') { - $this->encoding = $encoding; - return $this; - } - - if ($encoding === 'ASCII' && Mime::isPrintable($this->subject)) { - $this->encoding = $encoding; - return $this; - } - - $this->encoding = null; - - return $this; - } - - public function getEncoding() - { - if (! $this->encoding) { - $this->encoding = Mime::isPrintable($this->subject) ? 'ASCII' : 'UTF-8'; - } - - return $this->encoding; - } - - public function setSubject($subject) - { - $subject = (string) $subject; - - if (! HeaderWrap::canBeEncoded($subject)) { - throw new Exception\InvalidArgumentException( - 'Subject value must be composed of printable US-ASCII or UTF-8 characters.' - ); - } - - $this->subject = $subject; - $this->encoding = null; - - return $this; - } - - public function toString() - { - return 'Subject: ' . $this->getFieldValue(HeaderInterface::FORMAT_ENCODED); - } -} diff --git a/lib/laminas/laminas-mail/src/Header/To.php b/lib/laminas/laminas-mail/src/Header/To.php deleted file mode 100644 index b3f50dead..000000000 --- a/lib/laminas/laminas-mail/src/Header/To.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -class To extends AbstractAddressList -{ - protected $fieldName = 'To'; - protected static $type = 'to'; -} diff --git a/lib/laminas/laminas-mail/src/Header/UnstructuredInterface.php b/lib/laminas/laminas-mail/src/Header/UnstructuredInterface.php deleted file mode 100644 index b8c2a1735..000000000 --- a/lib/laminas/laminas-mail/src/Header/UnstructuredInterface.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php - -namespace Laminas\Mail\Header; - -/** - * Marker interface for unstructured headers. - */ -interface UnstructuredInterface extends HeaderInterface -{ -} diff --git a/lib/laminas/laminas-mail/src/Headers.php b/lib/laminas/laminas-mail/src/Headers.php deleted file mode 100644 index 23475bc3f..000000000 --- a/lib/laminas/laminas-mail/src/Headers.php +++ /dev/null @@ -1,607 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Mail; - -use ArrayIterator; -use Countable; -use Iterator; -use Laminas\Loader\PluginClassLocator; -use Laminas\Mail\Header\GenericHeader; -use Laminas\Mail\Header\HeaderInterface; -use ReturnTypeWillChange; -use Traversable; - -/** - * Basic mail headers collection functionality - * - * Handles aggregation of headers - */ -class Headers implements Countable, Iterator -{ - /** @var string End of Line for fields */ - public const EOL = "\r\n"; - - /** @var string Start of Line when folding */ - public const FOLDING = "\r\n "; - - /** - * @var null|Header\HeaderLocatorInterface - */ - private $headerLocator; - - /** - * @todo Remove for 3.0.0. - * @var null|PluginClassLocator - */ - protected $pluginClassLoader; - - /** - * @var array key names for $headers array - */ - protected $headersKeys = []; - - /** - * @var Header\HeaderInterface[] instances - */ - protected $headers = []; - - /** - * Header encoding; defaults to ASCII - * - * @var string - */ - protected $encoding = 'ASCII'; - - /** - * Populates headers from string representation - * - * Parses a string for headers, and aggregates them, in order, in the - * current instance, primarily as strings until they are needed (they - * will be lazy loaded) - * - * @param string $string - * @param string $EOL EOL string; defaults to {@link EOL} - * @throws Exception\RuntimeException - * @return Headers - */ - public static function fromString($string, $EOL = self::EOL) - { - $headers = new static(); - $currentLine = ''; - $emptyLine = 0; - - // iterate the header lines, some might be continuations - $lines = explode($EOL, $string); - $total = count($lines); - for ($i = 0; $i < $total; $i += 1) { - $line = $lines[$i]; - - if ($line === "") { - // Empty line indicates end of headers - // EXCEPT if there are more lines, in which case, there's a possible error condition - $emptyLine += 1; - if ($emptyLine > 2) { - throw new Exception\RuntimeException('Malformed header detected'); - } - continue; - } elseif (preg_match('/^\s*$/', $line)) { - // skip empty continuation line - continue; - } - - if ($emptyLine > 1) { - throw new Exception\RuntimeException('Malformed header detected'); - } - - // check if a header name is present - if (preg_match('/^[\x21-\x39\x3B-\x7E]+:.*$/', $line)) { - if ($currentLine) { - // a header name was present, then store the current complete line - $headers->addHeaderLine($currentLine); - } - $currentLine = trim($line); - continue; - } - - // continuation: append to current line - // recover the whitespace that break the line (unfolding, rfc2822#section-2.2.3) - if (preg_match('/^\s+.*$/', $line)) { - $currentLine .= ' ' . trim($line); - continue; - } - - // Line does not match header format! - throw new Exception\RuntimeException(sprintf( - 'Line "%s" does not match header format!', - $line - )); - } - if ($currentLine) { - $headers->addHeaderLine($currentLine); - } - return $headers; - } - - /** - * Set an alternate PluginClassLocator implementation for loading header classes. - * - * @deprecated since 2.12.0 - * @todo Remove for version 3.0.0 - * @return $this - */ - public function setPluginClassLoader(PluginClassLocator $pluginClassLoader) - { - // Silenced; can be caught in custom error handlers. - @trigger_error(sprintf( - 'Since laminas/laminas-mail 2.12.0: Usage of %s is deprecated; use %s::setHeaderLocator() instead', - __METHOD__, - __CLASS__ - ), E_USER_DEPRECATED); - - $this->pluginClassLoader = $pluginClassLoader; - return $this; - } - - /** - * Return a PluginClassLocator instance for customizing headers. - * - * Lazyloads a Header\HeaderLoader if necessary. - * - * @deprecated since 2.12.0 - * @todo Remove for version 3.0.0 - * @return PluginClassLocator - */ - public function getPluginClassLoader() - { - // Silenced; can be caught in custom error handlers. - @trigger_error(sprintf( - 'Since laminas/laminas-mail 2.12.0: Usage of %s is deprecated; use %s::getHeaderLocator() instead', - __METHOD__, - __CLASS__ - ), E_USER_DEPRECATED); - - if (! $this->pluginClassLoader) { - $this->pluginClassLoader = new Header\HeaderLoader(); - } - - return $this->pluginClassLoader; - } - - /** - * Retrieve the header class locator for customizing headers. - * - * Lazyloads a Header\HeaderLocator instance if necessary. - */ - public function getHeaderLocator(): Header\HeaderLocatorInterface - { - if (! $this->headerLocator) { - $this->setHeaderLocator(new Header\HeaderLocator()); - } - return $this->headerLocator; - } - - /** - * @todo Return self when we update to 7.4 or later as minimum PHP version. - * @return $this - */ - public function setHeaderLocator(Header\HeaderLocatorInterface $headerLocator) - { - $this->headerLocator = $headerLocator; - return $this; - } - - /** - * Set the header encoding - * - * @param string $encoding - * @return Headers - */ - public function setEncoding($encoding) - { - $this->encoding = $encoding; - foreach ($this as $header) { - $header->setEncoding($encoding); - } - return $this; - } - - /** - * Get the header encoding - * - * @return string - */ - public function getEncoding() - { - return $this->encoding; - } - - /** - * Add many headers at once - * - * Expects an array (or Traversable object) of type/value pairs. - * - * @param array|Traversable $headers - * @throws Exception\InvalidArgumentException - * @return Headers - */ - public function addHeaders($headers) - { - if (! is_array($headers) && ! $headers instanceof Traversable) { - throw new Exception\InvalidArgumentException(sprintf( - 'Expected array or Traversable; received "%s"', - (is_object($headers) ? get_class($headers) : gettype($headers)) - )); - } - - foreach ($headers as $name => $value) { - if (is_int($name)) { - if (is_string($value)) { - $this->addHeaderLine($value); - } elseif (is_array($value) && count($value) == 1) { - $this->addHeaderLine(key($value), current($value)); - } elseif (is_array($value) && count($value) == 2) { - $this->addHeaderLine($value[0], $value[1]); - } elseif ($value instanceof Header\HeaderInterface) { - $this->addHeader($value); - } - } elseif (is_string($name)) { - $this->addHeaderLine($name, $value); - } - } - - return $this; - } - - /** - * Add a raw header line, either in name => value, or as a single string 'name: value' - * - * This method allows for lazy-loading in that the parsing and instantiation of HeaderInterface object - * will be delayed until they are retrieved by either get() or current() - * - * @throws Exception\InvalidArgumentException - * @param string $headerFieldNameOrLine - * @param string $fieldValue optional - * @return Headers - */ - public function addHeaderLine($headerFieldNameOrLine, $fieldValue = null) - { - if (! is_string($headerFieldNameOrLine)) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects its first argument to be a string; received "%s"', - __METHOD__, - (is_object($headerFieldNameOrLine) - ? get_class($headerFieldNameOrLine) - : gettype($headerFieldNameOrLine)) - )); - } - - if ($fieldValue === null) { - $headers = $this->loadHeader($headerFieldNameOrLine); - $headers = is_array($headers) ? $headers : [$headers]; - foreach ($headers as $header) { - $this->addHeader($header); - } - } elseif (is_array($fieldValue)) { - foreach ($fieldValue as $i) { - $this->addHeader(Header\GenericMultiHeader::fromString($headerFieldNameOrLine . ':' . $i)); - } - } else { - $this->addHeader(Header\GenericHeader::fromString($headerFieldNameOrLine . ':' . $fieldValue)); - } - - return $this; - } - - /** - * Add a Header\Interface to this container, for raw values see {@link addHeaderLine()} and {@link addHeaders()} - * - * @param Header\HeaderInterface $header - * @return Headers - */ - public function addHeader(Header\HeaderInterface $header) - { - $key = $this->normalizeFieldName($header->getFieldName()); - $this->headersKeys[] = $key; - $this->headers[] = $header; - if ($this->getEncoding() !== 'ASCII') { - $header->setEncoding($this->getEncoding()); - } - return $this; - } - - /** - * Remove a Header from the container - * - * @param string|Header\HeaderInterface field name or specific header instance to remove - * @return bool - */ - public function removeHeader($instanceOrFieldName) - { - if (! $instanceOrFieldName instanceof Header\HeaderInterface && ! is_string($instanceOrFieldName)) { - throw new Exception\InvalidArgumentException(sprintf( - '%s requires a string or %s instance; received %s', - __METHOD__, - Header\HeaderInterface::class, - is_object($instanceOrFieldName) ? get_class($instanceOrFieldName) : gettype($instanceOrFieldName) - )); - } - - if ($instanceOrFieldName instanceof Header\HeaderInterface) { - $indexes = array_keys($this->headers, $instanceOrFieldName, true); - } - - if (is_string($instanceOrFieldName)) { - $key = $this->normalizeFieldName($instanceOrFieldName); - $indexes = array_keys($this->headersKeys, $key, true); - } - - if (! empty($indexes)) { - foreach ($indexes as $index) { - unset($this->headersKeys[$index]); - unset($this->headers[$index]); - } - return true; - } - - return false; - } - - /** - * Clear all headers - * - * Removes all headers from queue - * - * @return Headers - */ - public function clearHeaders() - { - $this->headers = $this->headersKeys = []; - return $this; - } - - /** - * Get all headers of a certain name/type - * - * @param string $name - * @return bool|ArrayIterator|Header\HeaderInterface Returns false if there is no headers with $name in this - * contain, an ArrayIterator if the header is a MultipleHeadersInterface instance and finally returns - * HeaderInterface for the rest of cases. - */ - public function get($name) - { - $key = $this->normalizeFieldName($name); - $results = []; - - foreach (array_keys($this->headersKeys, $key, true) as $index) { - if ($this->headers[$index] instanceof Header\GenericHeader) { - $results[] = $this->lazyLoadHeader($index); - } else { - $results[] = $this->headers[$index]; - } - } - - switch (count($results)) { - case 0: - return false; - case 1: - if ($results[0] instanceof Header\MultipleHeadersInterface) { - return new ArrayIterator($results); - } - return $results[0]; - default: - return new ArrayIterator($results); - } - } - - /** - * Test for existence of a type of header - * - * @param string $name - * @return bool - */ - public function has($name) - { - $name = $this->normalizeFieldName($name); - return in_array($name, $this->headersKeys, true); - } - - /** - * Advance the pointer for this object as an iterator - * - */ - #[ReturnTypeWillChange] - public function next() - { - next($this->headers); - } - - /** - * Return the current key for this object as an iterator - * - * @return mixed - */ - #[ReturnTypeWillChange] - public function key() - { - return key($this->headers); - } - - /** - * Is this iterator still valid? - * - * @return bool - */ - #[ReturnTypeWillChange] - public function valid() - { - return (current($this->headers) !== false); - } - - /** - * Reset the internal pointer for this object as an iterator - * - */ - #[ReturnTypeWillChange] - public function rewind() - { - reset($this->headers); - } - - /** - * Return the current value for this iterator, lazy loading it if need be - * - * @return Header\HeaderInterface - */ - #[ReturnTypeWillChange] - public function current() - { - $current = current($this->headers); - if ($current instanceof Header\GenericHeader) { - $current = $this->lazyLoadHeader(key($this->headers)); - } - return $current; - } - - /** - * Return the number of headers in this contain, if all headers have not been parsed, actual count could - * increase if MultipleHeader objects exist in the Request/Response. If you need an exact count, iterate - * - * @return int count of currently known headers - */ - #[ReturnTypeWillChange] - public function count() - { - return count($this->headers); - } - - /** - * Render all headers at once - * - * This method handles the normal iteration of headers; it is up to the - * concrete classes to prepend with the appropriate status/request line. - * - * @return string - */ - public function toString() - { - $headers = ''; - foreach ($this as $header) { - if ($str = $header->toString()) { - $headers .= $str . self::EOL; - } - } - - return $headers; - } - - /** - * Return the headers container as an array - * - * @param bool $format Return the values in Mime::Encoded or in Raw format - * @return array - * @todo determine how to produce single line headers, if they are supported - */ - public function toArray($format = Header\HeaderInterface::FORMAT_RAW) - { - $headers = []; - /* @var $header Header\HeaderInterface */ - foreach ($this->headers as $header) { - if ($header instanceof Header\MultipleHeadersInterface) { - $name = $header->getFieldName(); - if (! isset($headers[$name])) { - $headers[$name] = []; - } - $headers[$name][] = $header->getFieldValue($format); - } else { - $headers[$header->getFieldName()] = $header->getFieldValue($format); - } - } - return $headers; - } - - /** - * By calling this, it will force parsing and loading of all headers, after this count() will be accurate - * - * @return bool - */ - public function forceLoading() - { - foreach ($this as $item) { - // $item should now be loaded - } - return true; - } - - /** - * Create Header object from header line - * - * @param string $headerLine - * @return Header\HeaderInterface|Header\HeaderInterface[] - */ - public function loadHeader($headerLine) - { - list($name) = Header\GenericHeader::splitHeaderLine($headerLine); - - /** @var HeaderInterface $class */ - $class = $this->resolveHeaderClass($name); - return $class::fromString($headerLine); - } - - /** - * @param $index - * @return mixed - */ - protected function lazyLoadHeader($index) - { - $current = $this->headers[$index]; - - $key = $this->headersKeys[$index]; - - /** @var GenericHeader $class */ - $class = $this->resolveHeaderClass($key); - - $encoding = $current->getEncoding(); - $headers = $class::fromString($current->toString()); - if (is_array($headers)) { - $current = array_shift($headers); - $current->setEncoding($encoding); - $this->headers[$index] = $current; - foreach ($headers as $header) { - $header->setEncoding($encoding); - $this->headersKeys[] = $key; - $this->headers[] = $header; - } - return $current; - } - - $current = $headers; - $current->setEncoding($encoding); - $this->headers[$index] = $current; - return $current; - } - - /** - * Normalize a field name - * - * @param string $fieldName - * @return string - */ - protected function normalizeFieldName($fieldName) - { - return str_replace(['-', '_', ' ', '.'], '', strtolower($fieldName)); - } - - /** - * @param string $key - * @return string - */ - private function resolveHeaderClass($key) - { - if ($this->pluginClassLoader) { - return $this->pluginClassLoader->load($key) ?: Header\GenericHeader::class; - } - return $this->getHeaderLocator()->get($key, Header\GenericHeader::class); - } -} diff --git a/lib/laminas/laminas-mail/src/Message.php b/lib/laminas/laminas-mail/src/Message.php deleted file mode 100644 index 67f429d67..000000000 --- a/lib/laminas/laminas-mail/src/Message.php +++ /dev/null @@ -1,576 +0,0 @@ -<?php - -namespace Laminas\Mail; - -use Laminas\Mail\Header\Bcc; -use Laminas\Mail\Header\Cc; -use Laminas\Mail\Header\ContentType; -use Laminas\Mail\Header\From; -use Laminas\Mail\Header\MimeVersion; -use Laminas\Mail\Header\ReplyTo; -use Laminas\Mail\Header\Sender; -use Laminas\Mail\Header\To; -use Laminas\Mime; -use Traversable; - -class Message -{ - /** - * Content of the message - * - * @var string|object|Mime\Message - */ - protected $body; - - /** - * @var Headers - */ - protected $headers; - - /** - * Message encoding - * - * Used to determine whether or not to encode headers; defaults to ASCII. - * - * @var string - */ - protected $encoding = 'ASCII'; - - /** - * Is the message valid? - * - * If we don't any From addresses, we're invalid, according to RFC2822. - * - * @return bool - */ - public function isValid() - { - $from = $this->getFrom(); - if (! $from instanceof AddressList) { - return false; - } - return (bool) count($from); - } - - /** - * Set the message encoding - * - * @param string $encoding - * @return Message - */ - public function setEncoding($encoding) - { - $this->encoding = $encoding; - $this->getHeaders()->setEncoding($encoding); - return $this; - } - - /** - * Get the message encoding - * - * @return string - */ - public function getEncoding() - { - return $this->encoding; - } - - /** - * Compose headers - * - * @param Headers $headers - * @return Message - */ - public function setHeaders(Headers $headers) - { - $this->headers = $headers; - $headers->setEncoding($this->getEncoding()); - return $this; - } - - /** - * Access headers collection - * - * Lazy-loads if not already attached. - * - * @return Headers - */ - public function getHeaders() - { - if (null === $this->headers) { - $this->setHeaders(new Headers()); - $date = Header\Date::fromString('Date: ' . date('r')); - $this->headers->addHeader($date); - } - return $this->headers; - } - - /** - * Set (overwrite) From addresses - * - * @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressList - * @param string|null $name - * @return Message - */ - public function setFrom($emailOrAddressList, $name = null) - { - $this->clearHeaderByName('from'); - return $this->addFrom($emailOrAddressList, $name); - } - - /** - * Add a "From" address - * - * @param string|Address|array|AddressList|Traversable $emailOrAddressOrList - * @param string|null $name - * @return Message - */ - public function addFrom($emailOrAddressOrList, $name = null) - { - $addressList = $this->getFrom(); - $this->updateAddressList($addressList, $emailOrAddressOrList, $name, __METHOD__); - return $this; - } - - /** - * Retrieve list of From senders - * - * @return AddressList - */ - public function getFrom() - { - return $this->getAddressListFromHeader('from', From::class); - } - - /** - * Overwrite the address list in the To recipients - * - * @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressList - * @param null|string $name - * @return Message - */ - public function setTo($emailOrAddressList, $name = null) - { - $this->clearHeaderByName('to'); - return $this->addTo($emailOrAddressList, $name); - } - - /** - * Add one or more addresses to the To recipients - * - * Appends to the list. - * - * @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressOrList - * @param null|string $name - * @return Message - */ - public function addTo($emailOrAddressOrList, $name = null) - { - $addressList = $this->getTo(); - $this->updateAddressList($addressList, $emailOrAddressOrList, $name, __METHOD__); - return $this; - } - - /** - * Access the address list of the To header - * - * @return AddressList - */ - public function getTo() - { - return $this->getAddressListFromHeader('to', To::class); - } - - /** - * Set (overwrite) CC addresses - * - * @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressList - * @param string|null $name - * @return Message - */ - public function setCc($emailOrAddressList, $name = null) - { - $this->clearHeaderByName('cc'); - return $this->addCc($emailOrAddressList, $name); - } - - /** - * Add a "Cc" address - * - * @param string|Address|array|AddressList|Traversable $emailOrAddressOrList - * @param string|null $name - * @return Message - */ - public function addCc($emailOrAddressOrList, $name = null) - { - $addressList = $this->getCc(); - $this->updateAddressList($addressList, $emailOrAddressOrList, $name, __METHOD__); - return $this; - } - - /** - * Retrieve list of CC recipients - * - * @return AddressList - */ - public function getCc() - { - return $this->getAddressListFromHeader('cc', Cc::class); - } - - /** - * Set (overwrite) BCC addresses - * - * @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressList - * @param string|null $name - * @return Message - */ - public function setBcc($emailOrAddressList, $name = null) - { - $this->clearHeaderByName('bcc'); - return $this->addBcc($emailOrAddressList, $name); - } - - /** - * Add a "Bcc" address - * - * @param string|Address|array|AddressList|Traversable $emailOrAddressOrList - * @param string|null $name - * @return Message - */ - public function addBcc($emailOrAddressOrList, $name = null) - { - $addressList = $this->getBcc(); - $this->updateAddressList($addressList, $emailOrAddressOrList, $name, __METHOD__); - return $this; - } - - /** - * Retrieve list of BCC recipients - * - * @return AddressList - */ - public function getBcc() - { - return $this->getAddressListFromHeader('bcc', Bcc::class); - } - - /** - * Overwrite the address list in the Reply-To recipients - * - * @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressList - * @param null|string $name - * @return Message - */ - public function setReplyTo($emailOrAddressList, $name = null) - { - $this->clearHeaderByName('reply-to'); - return $this->addReplyTo($emailOrAddressList, $name); - } - - /** - * Add one or more addresses to the Reply-To recipients - * - * Appends to the list. - * - * @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressOrList - * @param null|string $name - * @return Message - */ - public function addReplyTo($emailOrAddressOrList, $name = null) - { - $addressList = $this->getReplyTo(); - $this->updateAddressList($addressList, $emailOrAddressOrList, $name, __METHOD__); - return $this; - } - - /** - * Access the address list of the Reply-To header - * - * @return AddressList - */ - public function getReplyTo() - { - return $this->getAddressListFromHeader('reply-to', ReplyTo::class); - } - - /** - * setSender - * - * @param mixed $emailOrAddress - * @param mixed $name - * @return Message - */ - public function setSender($emailOrAddress, $name = null) - { - /** @var Sender $header */ - $header = $this->getHeaderByName('sender', Sender::class); - $header->setAddress($emailOrAddress, $name); - return $this; - } - - /** - * Retrieve the sender address, if any - * - * @return null|Address\AddressInterface - */ - public function getSender() - { - $headers = $this->getHeaders(); - if (! $headers->has('sender')) { - return null; - } - - /** @var Sender $header */ - $header = $this->getHeaderByName('sender', Sender::class); - return $header->getAddress(); - } - - /** - * Set the message subject header value - * - * @param string $subject - * @return Message - */ - public function setSubject($subject) - { - $headers = $this->getHeaders(); - if (! $headers->has('subject')) { - $header = new Header\Subject(); - $headers->addHeader($header); - } else { - $header = $headers->get('subject'); - } - $header->setSubject($subject); - $header->setEncoding($this->getEncoding()); - return $this; - } - - /** - * Get the message subject header value - * - * @return null|string - */ - public function getSubject() - { - $headers = $this->getHeaders(); - if (! $headers->has('subject')) { - return; - } - $header = $headers->get('subject'); - return $header->getFieldValue(); - } - - /** - * Set the message body - * - * @param null|string|\Laminas\Mime\Message|object $body - * @throws Exception\InvalidArgumentException - * @return Message - */ - public function setBody($body) - { - if (! is_string($body) && $body !== null) { - if (! is_object($body)) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects a string or object argument; received "%s"', - __METHOD__, - gettype($body) - )); - } - if (! $body instanceof Mime\Message) { - if (! method_exists($body, '__toString')) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects object arguments of type %s or implementing __toString();' - . ' object of type "%s" received', - __METHOD__, - Mime\Message::class, - get_class($body) - )); - } - } - } - $this->body = $body; - - if (! $this->body instanceof Mime\Message) { - return $this; - } - - // Get headers, and set Mime-Version header - $headers = $this->getHeaders(); - $this->getHeaderByName('mime-version', MimeVersion::class); - - // Multipart content headers - if ($this->body->isMultiPart()) { - $mime = $this->body->getMime(); - - /** @var ContentType $header */ - $header = $this->getHeaderByName('content-type', ContentType::class); - $header->setType('multipart/mixed'); - $header->addParameter('boundary', $mime->boundary()); - return $this; - } - - // MIME single part headers - $parts = $this->body->getParts(); - if (! empty($parts)) { - $part = array_shift($parts); - $headers->addHeaders($part->getHeadersArray("\r\n")); - } - return $this; - } - - /** - * Return the currently set message body - * - * @return object|string|Mime\Message - */ - public function getBody() - { - return $this->body; - } - - /** - * Get the string-serialized message body text - * - * @return string - */ - public function getBodyText() - { - if ($this->body instanceof Mime\Message) { - return $this->body->generateMessage(Headers::EOL); - } - - return (string) $this->body; - } - - /** - * Retrieve a header by name - * - * If not found, instantiates one based on $headerClass. - * - * @param string $headerName - * @param string $headerClass - * @return Header\HeaderInterface|\ArrayIterator header instance or collection of headers - */ - protected function getHeaderByName($headerName, $headerClass) - { - $headers = $this->getHeaders(); - if ($headers->has($headerName)) { - $header = $headers->get($headerName); - } else { - $header = new $headerClass(); - $headers->addHeader($header); - } - return $header; - } - - /** - * Clear a header by name - * - * @param string $headerName - */ - protected function clearHeaderByName($headerName) - { - $this->getHeaders()->removeHeader($headerName); - } - - /** - * Retrieve the AddressList from a named header - * - * Used with To, From, Cc, Bcc, and ReplyTo headers. If the header does not - * exist, instantiates it. - * - * @param string $headerName - * @param string $headerClass - * @throws Exception\DomainException - * @return AddressList - */ - protected function getAddressListFromHeader($headerName, $headerClass) - { - $header = $this->getHeaderByName($headerName, $headerClass); - if (! $header instanceof Header\AbstractAddressList) { - throw new Exception\DomainException(sprintf( - 'Cannot grab address list from header of type "%s"; not an AbstractAddressList implementation', - get_class($header) - )); - } - return $header->getAddressList(); - } - - /** - * Update an address list - * - * Proxied to this from addFrom, addTo, addCc, addBcc, and addReplyTo. - * - * @param AddressList $addressList - * @param string|Address\AddressInterface|array|AddressList|Traversable $emailOrAddressOrList - * @param null|string $name - * @param string $callingMethod - * @throws Exception\InvalidArgumentException - */ - protected function updateAddressList(AddressList $addressList, $emailOrAddressOrList, $name, $callingMethod) - { - if ($emailOrAddressOrList instanceof Traversable) { - foreach ($emailOrAddressOrList as $address) { - $addressList->add($address); - } - return; - } - if (is_array($emailOrAddressOrList)) { - $addressList->addMany($emailOrAddressOrList); - return; - } - if (! is_string($emailOrAddressOrList) && ! $emailOrAddressOrList instanceof Address\AddressInterface) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects a string, AddressInterface, array, AddressList, or Traversable as its first argument;' - . ' received "%s"', - $callingMethod, - (is_object($emailOrAddressOrList) ? get_class($emailOrAddressOrList) : gettype($emailOrAddressOrList)) - )); - } - - if (is_string($emailOrAddressOrList) && $name === null) { - $addressList->addFromString($emailOrAddressOrList); - return; - } - - $addressList->add($emailOrAddressOrList, $name); - } - - /** - * Serialize to string - * - * @return string - */ - public function toString() - { - $headers = $this->getHeaders(); - return $headers->toString() - . Headers::EOL - . $this->getBodyText(); - } - - /** - * Instantiate from raw message string - * - * @todo Restore body to Mime\Message - * @param string $rawMessage - * @return Message - */ - public static function fromString($rawMessage) - { - $message = new static(); - - /** @var Headers $headers */ - $headers = null; - $content = null; - Mime\Decode::splitMessage($rawMessage, $headers, $content, Headers::EOL); - if ($headers->has('mime-version')) { - // todo - restore body to mime\message - } - $message->setHeaders($headers); - $message->setBody($content); - return $message; - } -} diff --git a/lib/laminas/laminas-mail/src/MessageFactory.php b/lib/laminas/laminas-mail/src/MessageFactory.php deleted file mode 100644 index faf40fe76..000000000 --- a/lib/laminas/laminas-mail/src/MessageFactory.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php - -namespace Laminas\Mail; - -use Traversable; - -class MessageFactory -{ - /** - * @param array|Traversable $options - * @return Message - */ - public static function getInstance($options = []) - { - if (! is_array($options) && ! $options instanceof Traversable) { - throw new Exception\InvalidArgumentException(sprintf( - '"%s" expects an array or Traversable; received "%s"', - __METHOD__, - (is_object($options) ? get_class($options) : gettype($options)) - )); - } - - $message = new Message(); - - foreach ($options as $key => $value) { - $setter = self::getSetterMethod($key); - if (method_exists($message, $setter)) { - $message->{$setter}($value); - } - } - - return $message; - } - - /** - * Generate a setter method name based on a provided key. - * - * @param string $key - * @return string - */ - private static function getSetterMethod($key) - { - return 'set' - . str_replace( - ' ', - '', - ucwords( - strtr( - $key, - [ - '-' => ' ', - '_' => ' ', - ] - ) - ) - ); - } -} diff --git a/lib/laminas/laminas-mail/src/Module.php b/lib/laminas/laminas-mail/src/Module.php deleted file mode 100644 index 652dfcb7c..000000000 --- a/lib/laminas/laminas-mail/src/Module.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -namespace Laminas\Mail; - -class Module -{ - /** - * Retrieve laminas-mail package configuration for laminas-mvc context. - * - * @return array - */ - public function getConfig() - { - $provider = new ConfigProvider(); - return [ - 'service_manager' => $provider->getDependencyConfig(), - ]; - } -} diff --git a/lib/laminas/laminas-mail/src/Protocol/AbstractProtocol.php b/lib/laminas/laminas-mail/src/Protocol/AbstractProtocol.php deleted file mode 100644 index 304dfe15e..000000000 --- a/lib/laminas/laminas-mail/src/Protocol/AbstractProtocol.php +++ /dev/null @@ -1,344 +0,0 @@ -<?php - -namespace Laminas\Mail\Protocol; - -use Laminas\Validator; - -/** - * Provides low-level methods for concrete adapters to communicate with a - * remote mail server and track requests and responses. - * - * @todo Implement proxy settings - */ -abstract class AbstractProtocol -{ - /** - * Mail default EOL string - */ - public const EOL = "\r\n"; - - /** - * Default timeout in seconds for initiating session - */ - public const TIMEOUT_CONNECTION = 30; - - /** - * Maximum of the transaction log - * @var int - */ - protected $maximumLog = 64; - - /** - * Hostname or IP address of remote server - * @var string - */ - protected $host; - - /** - * Port number of connection - * @var int - */ - protected $port; - - /** - * Instance of Laminas\Validator\ValidatorChain to check hostnames - * @var \Laminas\Validator\ValidatorChain - */ - protected $validHost; - - /** - * Socket connection resource - * @var null|resource - */ - protected $socket; - - /** - * Last request sent to server - * @var string - */ - protected $request; - - /** - * Array of server responses to last request - * @var array - */ - protected $response; - - /** - * Log of mail requests and server responses for a session - * @var array - */ - private $log = []; - - /** - * Constructor. - * - * @param string $host OPTIONAL Hostname of remote connection (default: 127.0.0.1) - * @param int $port OPTIONAL Port number (default: null) - * @throws Exception\RuntimeException - */ - public function __construct($host = '127.0.0.1', $port = null) - { - $this->validHost = new Validator\ValidatorChain(); - $this->validHost->attach(new Validator\Hostname(Validator\Hostname::ALLOW_ALL)); - - if (! $this->validHost->isValid($host)) { - throw new Exception\RuntimeException(implode(', ', $this->validHost->getMessages())); - } - - $this->host = $host; - $this->port = $port; - } - - /** - * Class destructor to cleanup open resources - * - */ - public function __destruct() - { - $this->_disconnect(); - } - - /** - * Set the maximum log size - * - * @param int $maximumLog Maximum log size - */ - public function setMaximumLog($maximumLog) - { - $this->maximumLog = (int) $maximumLog; - } - - /** - * Get the maximum log size - * - * @return int the maximum log size - */ - public function getMaximumLog() - { - return $this->maximumLog; - } - - /** - * Create a connection to the remote host - * - * Concrete adapters for this class will implement their own unique connect - * scripts, using the _connect() method to create the socket resource. - */ - abstract public function connect(); - - /** - * Retrieve the last client request - * - * @return string - */ - public function getRequest() - { - return $this->request; - } - - /** - * Retrieve the last server response - * - * @return array - */ - public function getResponse() - { - return $this->response; - } - - /** - * Retrieve the transaction log - * - * @return string - */ - public function getLog() - { - return implode('', $this->log); - } - - /** - * Reset the transaction log - * - */ - public function resetLog() - { - $this->log = []; - } - - /** - * Add the transaction log - * - * @param string $value new transaction - */ - // @codingStandardsIgnoreLine PSR2.Methods.MethodDeclaration.Underscore - protected function _addLog($value) - { - if ($this->maximumLog >= 0 && count($this->log) >= $this->maximumLog) { - array_shift($this->log); - } - - $this->log[] = $value; - } - - /** - * Connect to the server using the supplied transport and target - * - * An example $remote string may be 'tcp://mail.example.com:25' or 'ssh://hostname.com:2222' - * - * @deprecated Since 1.12.0. Implementations should use the ProtocolTrait::setupSocket() method instead. - * @todo Remove for 3.0.0. - * @param string $remote Remote - * @throws Exception\RuntimeException - * @return bool - */ - // @codingStandardsIgnoreLine PSR2.Methods.MethodDeclaration.Underscore - protected function _connect($remote) - { - $errorNum = 0; - $errorStr = ''; - - // open connection - set_error_handler( - function ($error, $message = '') { - throw new Exception\RuntimeException(sprintf('Could not open socket: %s', $message), $error); - }, - E_WARNING - ); - $this->socket = stream_socket_client($remote, $errorNum, $errorStr, self::TIMEOUT_CONNECTION); - restore_error_handler(); - - if ($this->socket === false) { - if ($errorNum == 0) { - $errorStr = 'Could not open socket'; - } - throw new Exception\RuntimeException($errorStr); - } - - if (($result = stream_set_timeout($this->socket, self::TIMEOUT_CONNECTION)) === false) { - throw new Exception\RuntimeException('Could not set stream timeout'); - } - - return $result; - } - - /** - * Disconnect from remote host and free resource - * - */ - // @codingStandardsIgnoreLine PSR2.Methods.MethodDeclaration.Underscore - protected function _disconnect() - { - if (is_resource($this->socket)) { - fclose($this->socket); - } - } - - /** - * Send the given request followed by a LINEEND to the server. - * - * @param string $request - * @throws Exception\RuntimeException - * @return int|bool Number of bytes written to remote host - */ - // @codingStandardsIgnoreLine PSR2.Methods.MethodDeclaration.Underscore - protected function _send($request) - { - if (! is_resource($this->socket)) { - throw new Exception\RuntimeException('No connection has been established to ' . $this->host); - } - - $this->request = $request; - - $result = fwrite($this->socket, $request . self::EOL); - - // Save request to internal log - $this->_addLog($request . self::EOL); - - if ($result === false) { - throw new Exception\RuntimeException('Could not send request to ' . $this->host); - } - - return $result; - } - - /** - * Get a line from the stream. - * - * @param int $timeout Per-request timeout value if applicable - * @throws Exception\RuntimeException - * @return string - */ - // @codingStandardsIgnoreLine PSR2.Methods.MethodDeclaration.Underscore - protected function _receive($timeout = null) - { - if (! is_resource($this->socket)) { - throw new Exception\RuntimeException('No connection has been established to ' . $this->host); - } - - // Adapters may wish to supply per-commend timeouts according to appropriate RFC - if ($timeout !== null) { - stream_set_timeout($this->socket, $timeout); - } - - // Retrieve response - $response = fgets($this->socket, 1024); - - // Save request to internal log - $this->_addLog($response); - - // Check meta data to ensure connection is still valid - $info = stream_get_meta_data($this->socket); - - if ($info['timed_out']) { - throw new Exception\RuntimeException($this->host . ' has timed out'); - } - - if ($response === false) { - throw new Exception\RuntimeException('Could not read from ' . $this->host); - } - - return $response; - } - - /** - * Parse server response for successful codes - * - * Read the response from the stream and check for expected return code. - * Throws a Laminas\Mail\Protocol\Exception\ExceptionInterface if an unexpected code is returned. - * - * @param string|array $code One or more codes that indicate a successful response - * @param int $timeout Per-request timeout value if applicable - * @throws Exception\RuntimeException - * @return string Last line of response string - */ - // @codingStandardsIgnoreLine PSR2.Methods.MethodDeclaration.Underscore - protected function _expect($code, $timeout = null) - { - $this->response = []; - $errMsg = ''; - - if (! is_array($code)) { - $code = [$code]; - } - - do { - $this->response[] = $result = $this->_receive($timeout); - list($cmd, $more, $msg) = preg_split('/([\s-]+)/', $result, 2, PREG_SPLIT_DELIM_CAPTURE); - - if ($errMsg !== '') { - $errMsg .= ' ' . $msg; - } elseif ($cmd === null || ! in_array($cmd, $code)) { - $errMsg = $msg; - } - - // The '-' message prefix indicates an information string instead of a response string. - } while (strpos($more, '-') === 0); - - if ($errMsg !== '') { - throw new Exception\RuntimeException($errMsg); - } - - return $msg; - } -} diff --git a/lib/laminas/laminas-mail/src/Protocol/Exception/ExceptionInterface.php b/lib/laminas/laminas-mail/src/Protocol/Exception/ExceptionInterface.php deleted file mode 100644 index 05bfeee21..000000000 --- a/lib/laminas/laminas-mail/src/Protocol/Exception/ExceptionInterface.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -namespace Laminas\Mail\Protocol\Exception; - -use Laminas\Mail\Exception\ExceptionInterface as MailException; - -interface ExceptionInterface extends MailException -{ -} diff --git a/lib/laminas/laminas-mail/src/Protocol/Exception/InvalidArgumentException.php b/lib/laminas/laminas-mail/src/Protocol/Exception/InvalidArgumentException.php deleted file mode 100644 index 22451cc6b..000000000 --- a/lib/laminas/laminas-mail/src/Protocol/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -namespace Laminas\Mail\Protocol\Exception; - -use Laminas\Mail\Exception; - -/** - * Exception for Laminas\Mail component. - */ -class InvalidArgumentException extends Exception\InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-mail/src/Protocol/Exception/RuntimeException.php b/lib/laminas/laminas-mail/src/Protocol/Exception/RuntimeException.php deleted file mode 100644 index 39ad0512c..000000000 --- a/lib/laminas/laminas-mail/src/Protocol/Exception/RuntimeException.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -namespace Laminas\Mail\Protocol\Exception; - -use Laminas\Mail\Exception; - -/** - * Exception for Laminas\Mail component. - */ -class RuntimeException extends Exception\RuntimeException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-mail/src/Protocol/Imap.php b/lib/laminas/laminas-mail/src/Protocol/Imap.php deleted file mode 100644 index 8004e6140..000000000 --- a/lib/laminas/laminas-mail/src/Protocol/Imap.php +++ /dev/null @@ -1,819 +0,0 @@ -<?php - -namespace Laminas\Mail\Protocol; - -class Imap -{ - use ProtocolTrait; - - /** - * Default timeout in seconds for initiating session - */ - public const TIMEOUT_CONNECTION = 30; - - /** - * @var null|resource - */ - protected $socket; - - /** - * counter for request tag - * @var int - */ - protected $tagCount = 0; - - /** - * Public constructor - * - * @param string $host hostname or IP address of IMAP server, if given connect() is called - * @param int|null $port port of IMAP server, null for default (143 or 993 for ssl) - * @param string|bool $ssl use ssl? 'SSL', 'TLS' or false - * @param bool $novalidatecert set to true to skip SSL certificate validation - * @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface - */ - public function __construct($host = '', $port = null, $ssl = false, $novalidatecert = false) - { - $this->setNoValidateCert($novalidatecert); - - if ($host) { - $this->connect($host, $port, $ssl); - } - } - - /** - * Public destructor - */ - public function __destruct() - { - $this->logout(); - } - - /** - * Open connection to IMAP server - * - * @param string $host hostname or IP address of IMAP server - * @param int|null $port of IMAP server, default is 143 (993 for ssl) - * @param string|bool $ssl use 'SSL', 'TLS' or false - * @throws Exception\RuntimeException - * @return void - */ - public function connect($host, $port = null, $ssl = false) - { - $transport = 'tcp'; - $isTls = false; - - if ($ssl) { - $ssl = strtolower($ssl); - } - - switch ($ssl) { - case 'ssl': - $transport = 'ssl'; - if (! $port) { - $port = 993; - } - break; - case 'tls': - $isTls = true; - // break intentionally omitted - default: - if (! $port) { - $port = 143; - } - } - - $this->socket = $this->setupSocket($transport, $host, $port, self::TIMEOUT_CONNECTION); - - if (! $this->assumedNextLine('* OK')) { - throw new Exception\RuntimeException('host doesn\'t allow connection'); - } - - if ($isTls) { - $result = $this->requestAndResponse('STARTTLS'); - $result = $result && stream_socket_enable_crypto($this->socket, true, $this->getCryptoMethod()); - if (! $result) { - throw new Exception\RuntimeException('cannot enable TLS'); - } - } - } - - /** - * get the next line from socket with error checking, but nothing else - * - * @throws Exception\RuntimeException - * @return string next line - */ - protected function nextLine() - { - $line = fgets($this->socket); - if ($line === false) { - throw new Exception\RuntimeException('cannot read - connection closed?'); - } - - return $line; - } - - /** - * get next line and assume it starts with $start. some requests give a simple - * feedback so we can quickly check if we can go on. - * - * @param string $start the first bytes we assume to be in the next line - * @return bool line starts with $start - */ - protected function assumedNextLine($start) - { - $line = $this->nextLine(); - return strpos($line, $start) === 0; - } - - /** - * get next line and split the tag. that's the normal case for a response line - * - * @param string $tag tag of line is returned by reference - * @return string next line - */ - protected function nextTaggedLine(&$tag) - { - $line = $this->nextLine(); - - // separate tag from line - list($tag, $line) = explode(' ', $line, 2); - - return $line; - } - - /** - * split a given line in tokens. a token is literal of any form or a list - * - * @param string $line line to decode - * @return array tokens, literals are returned as string, lists as array - */ - protected function decodeLine($line) - { - $tokens = []; - $stack = []; - - /* - We start to decode the response here. The understood tokens are: - literal - "literal" or also "lit\\er\"al" - {bytes}<NL>literal - (literals*) - All tokens are returned in an array. Literals in braces (the last understood - token in the list) are returned as an array of tokens. I.e. the following response: - "foo" baz {3}<NL>bar ("f\\\"oo" bar) - would be returned as: - array('foo', 'baz', 'bar', array('f\\\"oo', 'bar')); - - // TODO: add handling of '[' and ']' to parser for easier handling of response text - */ - // replace any trailing <NL> including spaces with a single space - $line = rtrim($line) . ' '; - while (($pos = strpos($line, ' ')) !== false) { - $token = substr($line, 0, $pos); - if (! strlen($token)) { - continue; - } - while ($token[0] == '(') { - array_push($stack, $tokens); - $tokens = []; - $token = substr($token, 1); - } - if ($token[0] == '"') { - if (preg_match('%^\(*"((.|\\\\|\\")*?)" *%', $line, $matches)) { - $tokens[] = $matches[1]; - $line = substr($line, strlen($matches[0])); - continue; - } - } - if ($token[0] == '{') { - $endPos = strpos($token, '}'); - $chars = substr($token, 1, $endPos - 1); - if (is_numeric($chars)) { - $token = ''; - while (strlen($token) < $chars) { - $token .= $this->nextLine(); - } - $line = ''; - if (strlen($token) > $chars) { - $line = substr($token, $chars); - $token = substr($token, 0, $chars); - } else { - $line .= $this->nextLine(); - } - $tokens[] = $token; - $line = trim($line) . ' '; - continue; - } - } - if ($stack && $token[strlen($token) - 1] == ')') { - // closing braces are not separated by spaces, so we need to count them - $braces = strlen($token); - $token = rtrim($token, ')'); - // only count braces if more than one - $braces -= strlen($token) + 1; - // only add if token had more than just closing braces - if (rtrim($token) != '') { - $tokens[] = rtrim($token); - } - $token = $tokens; - $tokens = array_pop($stack); - // special handline if more than one closing brace - while ($braces-- > 0) { - $tokens[] = $token; - $token = $tokens; - $tokens = array_pop($stack); - } - } - $tokens[] = $token; - $line = substr($line, $pos + 1); - } - - // maybe the server forgot to send some closing braces - while ($stack) { - $child = $tokens; - $tokens = array_pop($stack); - $tokens[] = $child; - } - - return $tokens; - } - - /** - * read a response "line" (could also be more than one real line if response has {..}<NL>) - * and do a simple decode - * - * @param array|string $tokens decoded tokens are returned by reference, if $dontParse - * is true the unparsed line is returned here - * @param string $wantedTag check for this tag for response code. Default '*' is - * continuation tag. - * @param bool $dontParse if true only the unparsed line is returned $tokens - * @return bool if returned tag matches wanted tag - */ - public function readLine(&$tokens = [], $wantedTag = '*', $dontParse = false) - { - $tag = null; // define $tag variable before first use - $line = $this->nextTaggedLine($tag); // get next tag - if (! $dontParse) { - $tokens = $this->decodeLine($line); - } else { - $tokens = $line; - } - - // if tag is wanted tag we might be at the end of a multiline response - return $tag == $wantedTag; - } - - /** - * read all lines of response until given tag is found (last line of response) - * - * @param string $tag the tag of your request - * @param bool $dontParse if true every line is returned unparsed instead of - * the decoded tokens - * @return null|bool|array tokens if success, false if error, null if bad request - */ - public function readResponse($tag, $dontParse = false) - { - $lines = []; - $tokens = null; // define $tokens variable before first use - while (! $this->readLine($tokens, $tag, $dontParse)) { - $lines[] = $tokens; - } - - if ($dontParse) { - // last to chars are still needed for response code - $tokens = [substr($tokens, 0, 2)]; - } - - // last line has response code - if ($tokens[0] == 'OK') { - return $lines ? $lines : true; - } elseif ($tokens[0] == 'NO') { - return false; - } - } - - /** - * send a request - * - * @param string $command your request command - * @param array $tokens additional parameters to command, use escapeString() to prepare - * @param string $tag provide a tag otherwise an autogenerated is returned - * @throws Exception\RuntimeException - */ - public function sendRequest($command, $tokens = [], &$tag = null) - { - if (! $tag) { - ++$this->tagCount; - $tag = 'TAG' . $this->tagCount; - } - - $line = $tag . ' ' . $command; - - foreach ($tokens as $token) { - if (is_array($token)) { - if (fwrite($this->socket, $line . ' ' . $token[0] . "\r\n") === false) { - throw new Exception\RuntimeException('cannot write - connection closed?'); - } - if (! $this->assumedNextLine('+ ')) { - throw new Exception\RuntimeException('cannot send literal string'); - } - $line = $token[1]; - } else { - $line .= ' ' . $token; - } - } - - if (fwrite($this->socket, $line . "\r\n") === false) { - throw new Exception\RuntimeException('cannot write - connection closed?'); - } - } - - /** - * send a request and get response at once - * - * @param string $command command as in sendRequest() - * @param array $tokens parameters as in sendRequest() - * @param bool $dontParse if true unparsed lines are returned instead of tokens - * @return mixed response as in readResponse() - */ - public function requestAndResponse($command, $tokens = [], $dontParse = false) - { - $tag = null; // define $tag variable before first use - $this->sendRequest($command, $tokens, $tag); - $response = $this->readResponse($tag, $dontParse); - - return $response; - } - - /** - * escape one or more literals i.e. for sendRequest - * - * @param string|array $string the literal/-s - * @return string|array escape literals, literals with newline ar returned - * as array('{size}', 'string'); - */ - public function escapeString($string) - { - if (func_num_args() < 2) { - if (strpos($string, "\n") !== false) { - return ['{' . strlen($string) . '}', $string]; - } - - return '"' . str_replace(['\\', '"'], ['\\\\', '\\"'], $string) . '"'; - } - - $result = []; - foreach (func_get_args() as $string) { - $result[] = $this->escapeString($string); - } - return $result; - } - - /** - * escape a list with literals or lists - * - * @param array $list list with literals or lists as PHP array - * @return string escaped list for imap - */ - public function escapeList($list) - { - $result = []; - foreach ($list as $v) { - if (! is_array($v)) { - $result[] = $v; - continue; - } - $result[] = $this->escapeList($v); - } - return '(' . implode(' ', $result) . ')'; - } - - /** - * Login to IMAP server. - * - * @param string $user username - * @param string $password password - * @return bool success - */ - public function login($user, $password) - { - return $this->requestAndResponse('LOGIN', $this->escapeString($user, $password), true); - } - - /** - * logout of imap server - * - * @return bool success - */ - public function logout() - { - $result = false; - if ($this->socket) { - try { - $result = $this->requestAndResponse('LOGOUT', [], true); - } catch (Exception\ExceptionInterface $e) { - // ignoring exception - } - fclose($this->socket); - $this->socket = null; - } - return $result; - } - - /** - * Get capabilities from IMAP server - * - * @return array list of capabilities - * @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface - */ - public function capability() - { - $response = $this->requestAndResponse('CAPABILITY'); - - if (! $response) { - return []; - } - - $capabilities = []; - foreach ($response as $line) { - $capabilities = array_merge($capabilities, $line); - } - return $capabilities; - } - - /** - * Examine and select have the same response. The common code for both - * is in this method - * - * @param string $command can be 'EXAMINE' or 'SELECT' and this is used as command - * @param string $box which folder to change to or examine - * @return bool|array false if error, array with returned information - * otherwise (flags, exists, recent, uidvalidity) - * @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface - */ - public function examineOrSelect($command = 'EXAMINE', $box = 'INBOX') - { - $tag = null; // define $tag variable before first use - $this->sendRequest($command, [$this->escapeString($box)], $tag); - - $result = []; - $tokens = null; // define $tokens variable before first use - while (! $this->readLine($tokens, $tag)) { - if ($tokens[0] == 'FLAGS') { - array_shift($tokens); - $result['flags'] = $tokens; - continue; - } - switch ($tokens[1]) { - case 'EXISTS': - case 'RECENT': - $result[strtolower($tokens[1])] = $tokens[0]; - break; - case '[UIDVALIDITY': - $result['uidvalidity'] = (int) $tokens[2]; - break; - default: - // ignore - } - } - - if ($tokens[0] != 'OK') { - return false; - } - return $result; - } - - /** - * change folder - * - * @param string $box change to this folder - * @return bool|array see examineOrselect() - * @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface - */ - public function select($box = 'INBOX') - { - return $this->examineOrSelect('SELECT', $box); - } - - /** - * examine folder - * - * @param string $box examine this folder - * @return bool|array see examineOrselect() - * @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface - */ - public function examine($box = 'INBOX') - { - return $this->examineOrSelect('EXAMINE', $box); - } - - /** - * fetch one or more items of one or more messages - * - * @param string|array $items items to fetch from message(s) as string (if only one item) - * or array of strings - * @param int|array $from message for items or start message if $to !== null - * @param int|null $to if null only one message ($from) is fetched, else it's the - * last message, INF means last message available - * @param bool $uid set to true if passing a unique id - * @throws Exception\RuntimeException - * @return string|array if only one item of one message is fetched it's returned as string - * if items of one message are fetched it's returned as (name => value) - * if one items of messages are fetched it's returned as (msgno => value) - * if items of messages are fetched it's returned as (msgno => (name => value)) - */ - public function fetch($items, $from, $to = null, $uid = false) - { - if (is_array($from)) { - $set = implode(',', $from); - } elseif ($to === null) { - $set = (int) $from; - } elseif ($to === INF) { - $set = (int) $from . ':*'; - } else { - $set = (int) $from . ':' . (int) $to; - } - - $items = (array) $items; - $itemList = $this->escapeList($items); - - $tag = null; // define $tag variable before first use - $this->sendRequest(($uid ? 'UID ' : '') . 'FETCH', [$set, $itemList], $tag); - - $result = []; - $tokens = null; // define $tokens variable before first use - while (! $this->readLine($tokens, $tag)) { - // ignore other responses - if ($tokens[1] != 'FETCH') { - continue; - } - - // find array key of UID value; try the last elements, or search for it - if ($uid) { - $count = count($tokens[2]); - if ($tokens[2][$count - 2] == 'UID') { - $uidKey = $count - 1; - } else { - $uidKey = array_search('UID', $tokens[2]) + 1; - } - } - - // ignore other messages - if ($to === null && ! is_array($from) && ($uid ? $tokens[2][$uidKey] != $from : $tokens[0] != $from)) { - continue; - } - - // if we only want one item we return that one directly - if (count($items) == 1) { - if ($tokens[2][0] == $items[0]) { - $data = $tokens[2][1]; - } elseif ($uid && $tokens[2][2] == $items[0]) { - $data = $tokens[2][3]; - } else { - // maybe the server send an other field we didn't wanted - $count = count($tokens[2]); - // we start with 2, because 0 was already checked - for ($i = 2; $i < $count; $i += 2) { - if ($tokens[2][$i] != $items[0]) { - continue; - } - $data = $tokens[2][$i + 1]; - break; - } - } - } else { - $data = []; - while (key($tokens[2]) !== null) { - $data[current($tokens[2])] = next($tokens[2]); - next($tokens[2]); - } - } - - // if we want only one message we can ignore everything else and just return - if ($to === null && ! is_array($from) && ($uid ? $tokens[2][$uidKey] == $from : $tokens[0] == $from)) { - // we still need to read all lines - while (! $this->readLine($tokens, $tag)) { - } - return $data; - } - $result[$tokens[0]] = $data; - } - - if ($to === null && ! is_array($from)) { - throw new Exception\RuntimeException('the single id was not found in response'); - } - - return $result; - } - - /** - * get mailbox list - * - * this method can't be named after the IMAP command 'LIST', as list is a reserved keyword - * - * @param string $reference mailbox reference for list - * @param string $mailbox mailbox name match with wildcards - * @return array mailboxes that matched $mailbox as array(globalName => array('delim' => .., 'flags' => ..)) - * @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface - */ - public function listMailbox($reference = '', $mailbox = '*') - { - $result = []; - $list = $this->requestAndResponse('LIST', $this->escapeString($reference, $mailbox)); - if (! $list || $list === true) { - return $result; - } - - foreach ($list as $item) { - if (count($item) != 4 || $item[0] != 'LIST') { - continue; - } - $result[$item[3]] = ['delim' => $item[2], 'flags' => $item[1]]; - } - - return $result; - } - - /** - * set flags - * - * @param array $flags flags to set, add or remove - see $mode - * @param int $from message for items or start message if $to !== null - * @param int|null $to if null only one message ($from) is fetched, else it's the - * last message, INF means last message available - * @param string|null $mode '+' to add flags, '-' to remove flags, everything else sets the flags as given - * @param bool $silent if false the return values are the new flags for the wanted messages - * @return bool|array new flags if $silent is false, else true or false depending on success - * @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface - */ - public function store(array $flags, $from, $to = null, $mode = null, $silent = true) - { - $item = 'FLAGS'; - if ($mode == '+' || $mode == '-') { - $item = $mode . $item; - } - if ($silent) { - $item .= '.SILENT'; - } - - $flags = $this->escapeList($flags); - $set = (int) $from; - if ($to !== null) { - $set .= ':' . ($to == INF ? '*' : (int) $to); - } - - $result = $this->requestAndResponse('STORE', [$set, $item, $flags], $silent); - - if ($silent) { - return (bool) $result; - } - - $tokens = $result; - $result = []; - foreach ($tokens as $token) { - if ($token[1] != 'FETCH' || $token[2][0] != 'FLAGS') { - continue; - } - $result[$token[0]] = $token[2][1]; - } - - return $result; - } - - /** - * append a new message to given folder - * - * @param string $folder name of target folder - * @param string $message full message content - * @param array $flags flags for new message - * @param string $date date for new message - * @return bool success - * @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface - */ - public function append($folder, $message, $flags = null, $date = null) - { - $tokens = []; - $tokens[] = $this->escapeString($folder); - if ($flags !== null) { - $tokens[] = $this->escapeList($flags); - } - if ($date !== null) { - $tokens[] = $this->escapeString($date); - } - $tokens[] = $this->escapeString($message); - - return $this->requestAndResponse('APPEND', $tokens, true); - } - - /** - * copy message set from current folder to other folder - * - * @param string $folder destination folder - * @param $from - * @param int|null $to if null only one message ($from) is fetched, else it's the - * last message, INF means last message available - * @return bool success - */ - public function copy($folder, $from, $to = null) - { - $set = (int) $from; - if ($to !== null) { - $set .= ':' . ($to == INF ? '*' : (int) $to); - } - - return $this->requestAndResponse('COPY', [$set, $this->escapeString($folder)], true); - } - - /** - * create a new folder (and parent folders if needed) - * - * @param string $folder folder name - * @return bool success - */ - public function create($folder) - { - return $this->requestAndResponse('CREATE', [$this->escapeString($folder)], true); - } - - /** - * rename an existing folder - * - * @param string $old old name - * @param string $new new name - * @return bool success - */ - public function rename($old, $new) - { - return $this->requestAndResponse('RENAME', $this->escapeString($old, $new), true); - } - - /** - * remove a folder - * - * @param string $folder folder name - * @return bool success - */ - public function delete($folder) - { - return $this->requestAndResponse('DELETE', [$this->escapeString($folder)], true); - } - - /** - * subscribe to a folder - * - * @param string $folder folder name - * @return bool success - */ - public function subscribe($folder) - { - return $this->requestAndResponse('SUBSCRIBE', [$this->escapeString($folder)], true); - } - - /** - * permanently remove messages - * - * @return bool success - */ - public function expunge() - { - // TODO: parse response? - return $this->requestAndResponse('EXPUNGE'); - } - - /** - * send noop - * - * @return bool success - */ - public function noop() - { - // TODO: parse response - return $this->requestAndResponse('NOOP'); - } - - /** - * do a search request - * - * This method is currently marked as internal as the API might change and is not - * safe if you don't take precautions. - * - * @param array $params - * @return array message ids - */ - public function search(array $params) - { - $response = $this->requestAndResponse('SEARCH', $params); - if (! $response) { - return $response; - } - - foreach ($response as $ids) { - if ($ids[0] == 'SEARCH') { - array_shift($ids); - return $ids; - } - } - return []; - } -} diff --git a/lib/laminas/laminas-mail/src/Protocol/Pop3.php b/lib/laminas/laminas-mail/src/Protocol/Pop3.php deleted file mode 100644 index 8675491a2..000000000 --- a/lib/laminas/laminas-mail/src/Protocol/Pop3.php +++ /dev/null @@ -1,389 +0,0 @@ -<?php - -namespace Laminas\Mail\Protocol; - -use Laminas\Stdlib\ErrorHandler; - -class Pop3 -{ - use ProtocolTrait; - - /** - * Default timeout in seconds for initiating session - */ - public const TIMEOUT_CONNECTION = 30; - - /** - * saves if server supports top - * @var null|bool - */ - public $hasTop = null; - - /** - * @var null|resource - */ - protected $socket; - - /** - * greeting timestamp for apop - * @var null|string - */ - protected $timestamp; - - /** - * Public constructor - * - * @param string $host hostname or IP address of POP3 server, if given connect() is called - * @param int|null $port port of POP3 server, null for default (110 or 995 for ssl) - * @param bool|string $ssl use ssl? 'SSL', 'TLS' or false - * @param bool $novalidatecert set to true to skip SSL certificate validation - */ - public function __construct($host = '', $port = null, $ssl = false, $novalidatecert = false) - { - $this->setNoValidateCert($novalidatecert); - - if ($host) { - $this->connect($host, $port, $ssl); - } - } - - /** - * Public destructor - */ - public function __destruct() - { - $this->logout(); - } - - /** - * Open connection to POP3 server - * - * @param string $host hostname or IP address of POP3 server - * @param int|null $port of POP3 server, default is 110 (995 for ssl) - * @param string|bool $ssl use 'SSL', 'TLS' or false - * @throws Exception\RuntimeException - * @return string welcome message - */ - public function connect($host, $port = null, $ssl = false) - { - $transport = 'tcp'; - $isTls = false; - - if ($ssl) { - $ssl = strtolower($ssl); - } - - switch ($ssl) { - case 'ssl': - $transport = 'ssl'; - if (! $port) { - $port = 995; - } - break; - case 'tls': - $isTls = true; - // break intentionally omitted - default: - if (! $port) { - $port = 110; - } - } - - $this->socket = $this->setupSocket($transport, $host, $port, self::TIMEOUT_CONNECTION); - - $welcome = $this->readResponse(); - - strtok($welcome, '<'); - $this->timestamp = strtok('>'); - if (! strpos($this->timestamp, '@')) { - $this->timestamp = null; - } else { - $this->timestamp = '<' . $this->timestamp . '>'; - } - - if ($isTls) { - $this->request('STLS'); - $result = stream_socket_enable_crypto($this->socket, true, $this->getCryptoMethod()); - if (! $result) { - throw new Exception\RuntimeException('cannot enable TLS'); - } - } - - return $welcome; - } - - /** - * Send a request - * - * @param string $request your request without newline - * @throws Exception\RuntimeException - */ - public function sendRequest($request) - { - ErrorHandler::start(); - $result = fwrite($this->socket, $request . "\r\n"); - $error = ErrorHandler::stop(); - if (! $result) { - throw new Exception\RuntimeException('send failed - connection closed?', 0, $error); - } - } - - /** - * read a response - * - * @param bool $multiline response has multiple lines and should be read until "<nl>.<nl>" - * @throws Exception\RuntimeException - * @return string response - */ - public function readResponse($multiline = false) - { - ErrorHandler::start(); - $result = fgets($this->socket); - $error = ErrorHandler::stop(); - if (! is_string($result)) { - throw new Exception\RuntimeException('read failed - connection closed?', 0, $error); - } - - $result = trim($result); - if (strpos($result, ' ')) { - list($status, $message) = explode(' ', $result, 2); - } else { - $status = $result; - $message = ''; - } - - if ($status != '+OK') { - throw new Exception\RuntimeException('last request failed'); - } - - if ($multiline) { - $message = ''; - $line = fgets($this->socket); - while ($line && rtrim($line, "\r\n") != '.') { - if ($line[0] == '.') { - $line = substr($line, 1); - } - $message .= $line; - $line = fgets($this->socket); - } - } - - return $message; - } - - /** - * Send request and get response - * - * @see sendRequest() - * @see readResponse() - * @param string $request request - * @param bool $multiline multiline response? - * @return string result from readResponse() - */ - public function request($request, $multiline = false) - { - $this->sendRequest($request); - return $this->readResponse($multiline); - } - - /** - * End communication with POP3 server (also closes socket) - */ - public function logout() - { - if ($this->socket) { - try { - $this->request('QUIT'); - } catch (Exception\ExceptionInterface $e) { - // ignore error - we're closing the socket anyway - } - - fclose($this->socket); - $this->socket = null; - } - } - - /** - * Get capabilities from POP3 server - * - * @return array list of capabilities - */ - public function capa() - { - $result = $this->request('CAPA', true); - return explode("\n", $result); - } - - /** - * Login to POP3 server. Can use APOP - * - * @param string $user username - * @param string $password password - * @param bool $tryApop should APOP be tried? - */ - public function login($user, $password, $tryApop = true) - { - if ($tryApop && $this->timestamp) { - try { - $this->request("APOP $user " . md5($this->timestamp . $password)); - return; - } catch (Exception\ExceptionInterface $e) { - // ignore - } - } - - $this->request("USER $user"); - $this->request("PASS $password"); - } - - /** - * Make STAT call for message count and size sum - * - * @param int $messages out parameter with count of messages - * @param int $octets out parameter with size in octets of messages - */ - public function status(&$messages, &$octets) - { - $messages = 0; - $octets = 0; - $result = $this->request('STAT'); - - list($messages, $octets) = explode(' ', $result); - } - - /** - * Make LIST call for size of message(s) - * - * @param int|null $msgno number of message, null for all - * @return int|array size of given message or list with array(num => size) - */ - public function getList($msgno = null) - { - if ($msgno !== null) { - $result = $this->request("LIST $msgno"); - - list(, $result) = explode(' ', $result); - return (int) $result; - } - - $result = $this->request('LIST', true); - $messages = []; - $line = strtok($result, "\n"); - while ($line) { - list($no, $size) = explode(' ', trim($line)); - $messages[(int) $no] = (int) $size; - $line = strtok("\n"); - } - - return $messages; - } - - /** - * Make UIDL call for getting a uniqueid - * - * @param int|null $msgno number of message, null for all - * @return string|array uniqueid of message or list with array(num => uniqueid) - */ - public function uniqueid($msgno = null) - { - if ($msgno !== null) { - $result = $this->request("UIDL $msgno"); - - list(, $result) = explode(' ', $result); - return $result; - } - - $result = $this->request('UIDL', true); - - $result = explode("\n", $result); - $messages = []; - foreach ($result as $line) { - if (! $line) { - continue; - } - list($no, $id) = explode(' ', trim($line), 2); - $messages[(int) $no] = $id; - } - - return $messages; - } - - /** - * Make TOP call for getting headers and maybe some body lines - * This method also sets hasTop - before it it's not known if top is supported - * - * The fallback makes normal RETR call, which retrieves the whole message. Additional - * lines are not removed. - * - * @param int $msgno number of message - * @param int $lines number of wanted body lines (empty line is inserted after header lines) - * @param bool $fallback fallback with full retrieve if top is not supported - * @throws Exception\RuntimeException - * @throws Exception\ExceptionInterface - * @return string message headers with wanted body lines - */ - public function top($msgno, $lines = 0, $fallback = false) - { - if ($this->hasTop === false) { - if ($fallback) { - return $this->retrieve($msgno); - } - - throw new Exception\RuntimeException('top not supported and no fallback wanted'); - } - $this->hasTop = true; - - $lines = (! $lines || $lines < 1) ? 0 : (int) $lines; - - try { - $result = $this->request("TOP $msgno $lines", true); - } catch (Exception\ExceptionInterface $e) { - $this->hasTop = false; - if ($fallback) { - $result = $this->retrieve($msgno); - } else { - throw $e; - } - } - - return $result; - } - - /** - * Make a RETR call for retrieving a full message with headers and body - * - * @param int $msgno message number - * @return string message - */ - public function retrieve($msgno) - { - $result = $this->request("RETR $msgno", true); - return $result; - } - - /** - * Make a NOOP call, maybe needed for keeping the server happy - */ - public function noop() - { - $this->request('NOOP'); - } - - /** - * Make a DELE count to remove a message - * - * @param $msgno - */ - public function delete($msgno) - { - $this->request("DELE $msgno"); - } - - /** - * Make RSET call, which rollbacks delete requests - */ - public function undelete() - { - $this->request('RSET'); - } -} diff --git a/lib/laminas/laminas-mail/src/Protocol/ProtocolTrait.php b/lib/laminas/laminas-mail/src/Protocol/ProtocolTrait.php deleted file mode 100644 index a562a9e91..000000000 --- a/lib/laminas/laminas-mail/src/Protocol/ProtocolTrait.php +++ /dev/null @@ -1,112 +0,0 @@ -<?php - -namespace Laminas\Mail\Protocol; - -use Laminas\Stdlib\ErrorHandler; - -/** - * https://bugs.php.net/bug.php?id=69195 - */ -trait ProtocolTrait -{ - /** - * If set to true, do not validate the SSL certificate - * @var null|bool - */ - protected $novalidatecert; - - public function getCryptoMethod(): int - { - // Allow the best TLS version(s) we can - $cryptoMethod = STREAM_CRYPTO_METHOD_TLS_CLIENT; - - // PHP 5.6.7 dropped inclusion of TLS 1.1 and 1.2 in STREAM_CRYPTO_METHOD_TLS_CLIENT - // so add them back in manually if we can - if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) { - $cryptoMethod |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; - $cryptoMethod |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT; - } - - return $cryptoMethod; - } - - /** - * Do not validate SSL certificate - * - * @todo Update to return self when minimum supported PHP version is 7.4+ - * @param bool $novalidatecert Set to true to disable certificate validation - * @return $this - */ - public function setNoValidateCert(bool $novalidatecert) - { - $this->novalidatecert = $novalidatecert; - return $this; - } - - /** - * Should we validate SSL certificate? - * - * @return bool - */ - public function validateCert(): bool - { - return ! $this->novalidatecert; - } - - /** - * Prepare socket options - * - * @return array - */ - private function prepareSocketOptions(): array - { - return $this->novalidatecert - ? [ - 'ssl' => [ - 'verify_peer_name' => false, - 'verify_peer' => false, - ], - ] - : []; - } - - /** - * Setup connection socket - * - * @param string $host hostname or IP address of IMAP server - * @param int|null $port of IMAP server, default is 143 (993 for ssl) - * @param int $timeout timeout in seconds for initiating session - * @return resource The socket created. - * @throws Exception\RuntimeException If unable to connect to host. - */ - protected function setupSocket( - string $transport, - string $host, - ?int $port, - int $timeout - ) { - ErrorHandler::start(); - $socket = stream_socket_client( - sprintf('%s://%s:%d', $transport, $host, $port), - $errno, - $errstr, - $timeout, - STREAM_CLIENT_CONNECT, - stream_context_create($this->prepareSocketOptions()) - ); - $error = ErrorHandler::stop(); - - if (! $socket) { - throw new Exception\RuntimeException(sprintf( - 'cannot connect to host%s', - $error ? sprintf('; error = %s (errno = %d )', $error->getMessage(), $error->getCode()) : '' - ), 0, $error); - } - - if (false === stream_set_timeout($socket, $timeout)) { - throw new Exception\RuntimeException('Could not set stream timeout'); - } - - return $socket; - } -} diff --git a/lib/laminas/laminas-mail/src/Protocol/Smtp.php b/lib/laminas/laminas-mail/src/Protocol/Smtp.php deleted file mode 100644 index 0bbe3ee45..000000000 --- a/lib/laminas/laminas-mail/src/Protocol/Smtp.php +++ /dev/null @@ -1,514 +0,0 @@ -<?php - -namespace Laminas\Mail\Protocol; - -use Generator; -use Laminas\Mail\Headers; - -/** - * SMTP implementation of Laminas\Mail\Protocol\AbstractProtocol - * - * Minimum implementation according to RFC2821: EHLO, MAIL FROM, RCPT TO, DATA, - * RSET, NOOP, QUIT - */ -class Smtp extends AbstractProtocol -{ - use ProtocolTrait; - - /** - * RFC 5322 section-2.2.3 specifies maximum of 998 bytes per line. - * This may not be exceeded. - * @see https://tools.ietf.org/html/rfc5322#section-2.2.3 - */ - public const SMTP_LINE_LIMIT = 998; - - /** - * The transport method for the socket - * - * @var string - */ - protected $transport = 'tcp'; - - /** - * Indicates that a session is requested to be secure - * - * @var string - */ - protected $secure; - - /** - * Indicates an smtp session has been started by the HELO command - * - * @var bool - */ - protected $sess = false; - - /** - * Indicates an smtp AUTH has been issued and authenticated - * - * @var bool - */ - protected $auth = false; - - /** - * Indicates a MAIL command has been issued - * - * @var bool - */ - protected $mail = false; - - /** - * Indicates one or more RCTP commands have been issued - * - * @var bool - */ - protected $rcpt = false; - - /** - * Indicates that DATA has been issued and sent - * - * @var bool - */ - protected $data = null; - - /** - * Whether or not send QUIT command - * - * @var bool - */ - protected $useCompleteQuit = true; - - /** - * Constructor. - * - * The first argument may be an array of all options. If so, it must include - * the 'host' and 'port' keys in order to ensure that all required values - * are present. - * - * @param string|array $host - * @param null|int $port - * @param null|array $config - * @throws Exception\InvalidArgumentException - */ - public function __construct($host = '127.0.0.1', $port = null, array $config = null) - { - // Did we receive a configuration array? - if (is_array($host)) { - // Merge config array with principal array, if provided - if (is_array($config)) { - $config = array_replace_recursive($host, $config); - } else { - $config = $host; - } - - // Look for a host key; if none found, use default value - if (isset($config['host'])) { - $host = $config['host']; - } else { - $host = '127.0.0.1'; - } - - // Look for a port key; if none found, use default value - if (isset($config['port'])) { - $port = $config['port']; - } else { - $port = null; - } - } - - // If we don't have a config array, initialize it - if (null === $config) { - $config = []; - } - - if (isset($config['ssl'])) { - switch (strtolower($config['ssl'])) { - case 'tls': - $this->secure = 'tls'; - break; - - case 'ssl': - $this->transport = 'ssl'; - $this->secure = 'ssl'; - if ($port === null) { - $port = 465; - } - break; - - case '': - // fall-through - case 'none': - break; - - default: - throw new Exception\InvalidArgumentException($config['ssl'] . ' is unsupported SSL type'); - } - } - - if (array_key_exists('use_complete_quit', $config)) { - $this->setUseCompleteQuit($config['use_complete_quit']); - } - - // If no port has been specified then check the master PHP ini file. Defaults to 25 if the ini setting is null. - if ($port === null) { - if (($port = ini_get('smtp_port')) == '') { - $port = 25; - } - } - - if (array_key_exists('novalidatecert', $config)) { - $this->setNoValidateCert($config['novalidatecert']); - } - - parent::__construct($host, $port); - } - - /** - * Set whether or not send QUIT command - * - * @param bool $useCompleteQuit use complete quit - * @return bool - */ - public function setUseCompleteQuit($useCompleteQuit) - { - return $this->useCompleteQuit = (bool) $useCompleteQuit; - } - - /** - * Read $data as lines terminated by "\n" - * - * @param string $data - * @param int $chunkSize - * @return Generator|string[] - * @author Elan Ruusamäe <glen@pld-linux.org> - */ - private static function chunkedReader(string $data, int $chunkSize = 4096): Generator - { - if (($fp = fopen("php://temp", "r+")) === false) { - throw new Exception\RuntimeException('cannot fopen'); - } - if (fwrite($fp, $data) === false) { - throw new Exception\RuntimeException('cannot fwrite'); - } - rewind($fp); - - $line = null; - while (($buffer = fgets($fp, $chunkSize)) !== false) { - $line .= $buffer; - - // This is optimization to avoid calling length() in a loop. - // We need to match a condition that is when: - // 1. maximum was read from fgets, which is $chunkSize-1 - // 2. last byte of the buffer is not \n - // - // to access last byte of buffer, we can do - // - $buffer[strlen($buffer)-1] - // and when maximum is read from fgets, then: - // - strlen($buffer) === $chunkSize-1 - // - strlen($buffer)-1 === $chunkSize-2 - // which means this is also true: - // - $buffer[strlen($buffer)-1] === $buffer[$chunkSize-2] - // - // the null coalesce works, as string offset can never be null - $lastByte = $buffer[$chunkSize - 2] ?? null; - - // partial read, continue loop to read again to complete the line - // compare \n first as that's usually false - if ($lastByte !== "\n" && $lastByte !== null) { - continue; - } - - yield $line; - $line = null; - } - - if ($line !== null) { - yield $line; - } - - fclose($fp); - } - - /** - * Whether or not send QUIT command - * - * @return bool - */ - public function useCompleteQuit() - { - return $this->useCompleteQuit; - } - - /** - * Connect to the server with the parameters given in the constructor. - * - * @return bool - */ - public function connect() - { - $this->socket = $this->setupSocket( - $this->transport, - $this->host, - $this->port, - self::TIMEOUT_CONNECTION - ); - return true; - } - - /** - * Initiate HELO/EHLO sequence and set flag to indicate valid smtp session - * - * @param string $host The client hostname or IP address (default: 127.0.0.1) - * @throws Exception\RuntimeException - */ - public function helo($host = '127.0.0.1') - { - // Respect RFC 2821 and disallow HELO attempts if session is already initiated. - if ($this->sess === true) { - throw new Exception\RuntimeException('Cannot issue HELO to existing session'); - } - - // Validate client hostname - if (! $this->validHost->isValid($host)) { - throw new Exception\RuntimeException(implode(', ', $this->validHost->getMessages())); - } - - // Initiate helo sequence - $this->_expect(220, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2 - $this->ehlo($host); - - // If a TLS session is required, commence negotiation - if ($this->secure == 'tls') { - $this->_send('STARTTLS'); - $this->_expect(220, 180); - if (! stream_socket_enable_crypto($this->socket, true, $this->getCryptoMethod())) { - throw new Exception\RuntimeException('Unable to connect via TLS'); - } - $this->ehlo($host); - } - - $this->startSession(); - $this->auth(); - } - - /** - * Returns the perceived session status - * - * @return bool - */ - public function hasSession() - { - return $this->sess; - } - - /** - * Send EHLO or HELO depending on capabilities of smtp host - * - * @param string $host The client hostname or IP address (default: 127.0.0.1) - * @throws \Exception|Exception\ExceptionInterface - */ - protected function ehlo($host) - { - // Support for older, less-compliant remote servers. Tries multiple attempts of EHLO or HELO. - try { - $this->_send('EHLO ' . $host); - $this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2 - } catch (Exception\ExceptionInterface $e) { - $this->_send('HELO ' . $host); - $this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2 - } - } - - /** - * Issues MAIL command - * - * @param string $from Sender mailbox - * @throws Exception\RuntimeException - */ - public function mail($from) - { - if ($this->sess !== true) { - throw new Exception\RuntimeException('A valid session has not been started'); - } - - $this->_send('MAIL FROM:<' . $from . '>'); - $this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2 - - // Set mail to true, clear recipients and any existing data flags as per 4.1.1.2 of RFC 2821 - $this->mail = true; - $this->rcpt = false; - $this->data = false; - } - - /** - * Issues RCPT command - * - * @param string $to Receiver(s) mailbox - * @throws Exception\RuntimeException - */ - public function rcpt($to) - { - if ($this->mail !== true) { - throw new Exception\RuntimeException('No sender reverse path has been supplied'); - } - - // Set rcpt to true, as per 4.1.1.3 of RFC 2821 - $this->_send('RCPT TO:<' . $to . '>'); - $this->_expect([250, 251], 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2 - $this->rcpt = true; - } - - /** - * Issues DATA command - * - * @param string $data - * @throws Exception\RuntimeException - */ - public function data($data) - { - // Ensure recipients have been set - if ($this->rcpt !== true) { // Per RFC 2821 3.3 (page 18) - throw new Exception\RuntimeException('No recipient forward path has been supplied'); - } - - $this->_send('DATA'); - $this->_expect(354, 120); // Timeout set for 2 minutes as per RFC 2821 4.5.3.2 - - $reader = self::chunkedReader($data); - foreach ($reader as $line) { - $line = rtrim($line, "\r\n"); - if (isset($line[0]) && $line[0] === '.') { - // Escape lines prefixed with a '.' - $line = '.' . $line; - } - - if (strlen($line) > self::SMTP_LINE_LIMIT) { - // Long lines are "folded" by inserting "<CR><LF><SPACE>" - // https://tools.ietf.org/html/rfc5322#section-2.2.3 - // Add "-1" to stay within limits, - // because Headers::FOLDING includes a byte for space character after \r\n - $chunks = chunk_split($line, self::SMTP_LINE_LIMIT - 1, Headers::FOLDING); - $line = substr($chunks, 0, -strlen(Headers::FOLDING)); - } - - $this->_send($line); - } - - $this->_send('.'); - $this->_expect(250, 600); // Timeout set for 10 minutes as per RFC 2821 4.5.3.2 - $this->data = true; - } - - /** - * Issues the RSET command end validates answer - * - * Can be used to restore a clean smtp communication state when a - * transaction has been cancelled or commencing a new transaction. - */ - public function rset() - { - $this->_send('RSET'); - // MS ESMTP doesn't follow RFC, see https://zendframework.com/issues/browse/ZF-1377 - $this->_expect([250, 220]); - - $this->mail = false; - $this->rcpt = false; - $this->data = false; - } - - /** - * Issues the NOOP command end validates answer - * - * Not used by Laminas\Mail, could be used to keep a connection alive or check if it is still open. - * - */ - public function noop() - { - $this->_send('NOOP'); - $this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2 - } - - /** - * Issues the VRFY command end validates answer - * - * Not used by Laminas\Mail. - * - * @param string $user User Name or eMail to verify - */ - public function vrfy($user) - { - $this->_send('VRFY ' . $user); - $this->_expect([250, 251, 252], 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2 - } - - /** - * Issues the QUIT command and clears the current session - * - */ - public function quit() - { - if ($this->sess) { - $this->auth = false; - - if ($this->useCompleteQuit()) { - $this->_send('QUIT'); - $this->_expect(221, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2 - } - - $this->stopSession(); - } - } - - /** - * Default authentication method - * - * This default method is implemented by AUTH adapters to properly authenticate to a remote host. - * - * @throws Exception\RuntimeException - */ - public function auth() - { - if ($this->auth === true) { - throw new Exception\RuntimeException('Already authenticated for this session'); - } - } - - /** - * Closes connection - * - */ - public function disconnect() - { - $this->_disconnect(); - } - - /** - * Disconnect from remote host and free resource - */ - // @codingStandardsIgnoreLine PSR2.Methods.MethodDeclaration.Underscore - protected function _disconnect() - { - - // Make sure the session gets closed - $this->quit(); - parent::_disconnect(); - } - - /** - * Start mail session - * - */ - protected function startSession() - { - $this->sess = true; - } - - /** - * Stop mail session - * - */ - protected function stopSession() - { - $this->sess = false; - } -} diff --git a/lib/laminas/laminas-mail/src/Protocol/Smtp/Auth/Crammd5.php b/lib/laminas/laminas-mail/src/Protocol/Smtp/Auth/Crammd5.php deleted file mode 100644 index e5e2c7b32..000000000 --- a/lib/laminas/laminas-mail/src/Protocol/Smtp/Auth/Crammd5.php +++ /dev/null @@ -1,132 +0,0 @@ -<?php - -namespace Laminas\Mail\Protocol\Smtp\Auth; - -use Laminas\Crypt\Hmac; -use Laminas\Mail\Protocol\Smtp; - -/** - * Performs CRAM-MD5 authentication - */ -class Crammd5 extends Smtp -{ - /** - * @var string - */ - protected $username; - - /** - * @var string - */ - protected $password; - - /** - * Constructor. - * - * All parameters may be passed as an array to the first argument of the - * constructor. If so, - * - * @param string|array $host (Default: 127.0.0.1) - * @param null|int $port (Default: null) - * @param null|array $config Auth-specific parameters - */ - public function __construct($host = '127.0.0.1', $port = null, $config = null) - { - // Did we receive a configuration array? - $origConfig = $config; - if (is_array($host)) { - // Merge config array with principal array, if provided - if (is_array($config)) { - $config = array_replace_recursive($host, $config); - } else { - $config = $host; - } - } - - if (is_array($config)) { - if (isset($config['username'])) { - $this->setUsername($config['username']); - } - if (isset($config['password'])) { - $this->setPassword($config['password']); - } - } - - // Call parent with original arguments - parent::__construct($host, $port, $origConfig); - } - - /** - * Performs CRAM-MD5 authentication with supplied credentials - */ - public function auth() - { - // Ensure AUTH has not already been initiated. - parent::auth(); - - $this->_send('AUTH CRAM-MD5'); - $challenge = $this->_expect(334); - $challenge = base64_decode($challenge); - $digest = $this->hmacMd5($this->getPassword(), $challenge); - $this->_send(base64_encode($this->getUsername() . ' ' . $digest)); - $this->_expect(235); - $this->auth = true; - } - - /** - * Set value for username - * - * @param string $username - * @return Crammd5 - */ - public function setUsername($username) - { - $this->username = $username; - return $this; - } - - /** - * Get username - * - * @return string - */ - public function getUsername() - { - return $this->username; - } - - /** - * Set value for password - * - * @param string $password - * @return Crammd5 - */ - public function setPassword($password) - { - $this->password = $password; - return $this; - } - - /** - * Get password - * - * @return string - */ - public function getPassword() - { - return $this->password; - } - - /** - * Prepare CRAM-MD5 response to server's ticket - * - * @param string $key Challenge key (usually password) - * @param string $data Challenge data - * @param int $block Length of blocks (deprecated; unused) - * @return string - */ - protected function hmacMd5($key, $data, $block = 64) - { - return Hmac::compute($key, 'md5', $data); - } -} diff --git a/lib/laminas/laminas-mail/src/Protocol/Smtp/Auth/Login.php b/lib/laminas/laminas-mail/src/Protocol/Smtp/Auth/Login.php deleted file mode 100644 index 66225d4a5..000000000 --- a/lib/laminas/laminas-mail/src/Protocol/Smtp/Auth/Login.php +++ /dev/null @@ -1,120 +0,0 @@ -<?php - -namespace Laminas\Mail\Protocol\Smtp\Auth; - -use Laminas\Mail\Protocol\Smtp; - -/** - * Performs LOGIN authentication - */ -class Login extends Smtp -{ - /** - * LOGIN username - * - * @var string - */ - protected $username; - - /** - * LOGIN password - * - * @var string - */ - protected $password; - - /** - * Constructor. - * - * @param string $host (Default: 127.0.0.1) - * @param int $port (Default: null) - * @param array $config Auth-specific parameters - */ - public function __construct($host = '127.0.0.1', $port = null, $config = null) - { - // Did we receive a configuration array? - $origConfig = $config; - if (is_array($host)) { - // Merge config array with principal array, if provided - if (is_array($config)) { - $config = array_replace_recursive($host, $config); - } else { - $config = $host; - } - } - - if (is_array($config)) { - if (isset($config['username'])) { - $this->setUsername($config['username']); - } - if (isset($config['password'])) { - $this->setPassword($config['password']); - } - } - - // Call parent with original arguments - parent::__construct($host, $port, $origConfig); - } - - /** - * Perform LOGIN authentication with supplied credentials - * - */ - public function auth() - { - // Ensure AUTH has not already been initiated. - parent::auth(); - - $this->_send('AUTH LOGIN'); - $this->_expect(334); - $this->_send(base64_encode($this->getUsername())); - $this->_expect(334); - $this->_send(base64_encode($this->getPassword())); - $this->_expect(235); - $this->auth = true; - } - - /** - * Set value for username - * - * @param string $username - * @return Login - */ - public function setUsername($username) - { - $this->username = $username; - return $this; - } - - /** - * Get username - * - * @return string - */ - public function getUsername() - { - return $this->username; - } - - /** - * Set value for password - * - * @param string $password - * @return Login - */ - public function setPassword($password) - { - $this->password = $password; - return $this; - } - - /** - * Get password - * - * @return string - */ - public function getPassword() - { - return $this->password; - } -} diff --git a/lib/laminas/laminas-mail/src/Protocol/Smtp/Auth/Plain.php b/lib/laminas/laminas-mail/src/Protocol/Smtp/Auth/Plain.php deleted file mode 100644 index 0bd3c8a65..000000000 --- a/lib/laminas/laminas-mail/src/Protocol/Smtp/Auth/Plain.php +++ /dev/null @@ -1,118 +0,0 @@ -<?php - -namespace Laminas\Mail\Protocol\Smtp\Auth; - -use Laminas\Mail\Protocol\Smtp; - -/** - * Performs PLAIN authentication - */ -class Plain extends Smtp -{ - /** - * PLAIN username - * - * @var string - */ - protected $username; - - /** - * PLAIN password - * - * @var string - */ - protected $password; - - /** - * Constructor. - * - * @param string $host (Default: 127.0.0.1) - * @param int $port (Default: null) - * @param array $config Auth-specific parameters - */ - public function __construct($host = '127.0.0.1', $port = null, $config = null) - { - // Did we receive a configuration array? - $origConfig = $config; - if (is_array($host)) { - // Merge config array with principal array, if provided - if (is_array($config)) { - $config = array_replace_recursive($host, $config); - } else { - $config = $host; - } - } - - if (is_array($config)) { - if (isset($config['username'])) { - $this->setUsername($config['username']); - } - if (isset($config['password'])) { - $this->setPassword($config['password']); - } - } - - // Call parent with original arguments - parent::__construct($host, $port, $origConfig); - } - - /** - * Perform PLAIN authentication with supplied credentials - * - */ - public function auth() - { - // Ensure AUTH has not already been initiated. - parent::auth(); - - $this->_send('AUTH PLAIN'); - $this->_expect(334); - $this->_send(base64_encode("\0" . $this->getUsername() . "\0" . $this->getPassword())); - $this->_expect(235); - $this->auth = true; - } - - /** - * Set value for username - * - * @param string $username - * @return Plain - */ - public function setUsername($username) - { - $this->username = $username; - return $this; - } - - /** - * Get username - * - * @return string - */ - public function getUsername() - { - return $this->username; - } - - /** - * Set value for password - * - * @param string $password - * @return Plain - */ - public function setPassword($password) - { - $this->password = $password; - return $this; - } - - /** - * Get password - * - * @return string - */ - public function getPassword() - { - return $this->password; - } -} diff --git a/lib/laminas/laminas-mail/src/Protocol/SmtpPluginManager.php b/lib/laminas/laminas-mail/src/Protocol/SmtpPluginManager.php deleted file mode 100644 index 91c35dfa7..000000000 --- a/lib/laminas/laminas-mail/src/Protocol/SmtpPluginManager.php +++ /dev/null @@ -1,108 +0,0 @@ -<?php - -namespace Laminas\Mail\Protocol; - -use Laminas\ServiceManager\AbstractPluginManager; -use Laminas\ServiceManager\Exception\InvalidServiceException; -use Laminas\ServiceManager\Factory\InvokableFactory; - -/** - * Plugin manager implementation for SMTP extensions. - * - * Enforces that SMTP extensions retrieved are instances of Smtp. Additionally, - * it registers a number of default extensions available. - */ -class SmtpPluginManager extends AbstractPluginManager -{ - /** - * Service aliases - */ - protected $aliases = [ - 'crammd5' => Smtp\Auth\Crammd5::class, - 'cramMd5' => Smtp\Auth\Crammd5::class, - 'CramMd5' => Smtp\Auth\Crammd5::class, - 'cramMD5' => Smtp\Auth\Crammd5::class, - 'CramMD5' => Smtp\Auth\Crammd5::class, - 'login' => Smtp\Auth\Login::class, - 'Login' => Smtp\Auth\Login::class, - 'plain' => Smtp\Auth\Plain::class, - 'Plain' => Smtp\Auth\Plain::class, - 'smtp' => Smtp::class, - 'Smtp' => Smtp::class, - 'SMTP' => Smtp::class, - - // Legacy Zend Framework aliases - \Zend\Mail\Protocol\Smtp\Auth\Crammd5::class => Smtp\Auth\Crammd5::class, - \Zend\Mail\Protocol\Smtp\Auth\Login::class => Smtp\Auth\Login::class, - \Zend\Mail\Protocol\Smtp\Auth\Plain::class => Smtp\Auth\Plain::class, - \Zend\Mail\Protocol\Smtp::class => Smtp::class, - - // v2 normalized FQCNs - 'zendmailprotocolsmtpauthcrammd5' => Smtp\Auth\Crammd5::class, - 'zendmailprotocolsmtpauthlogin' => Smtp\Auth\Login::class, - 'zendmailprotocolsmtpauthplain' => Smtp\Auth\Plain::class, - 'zendmailprotocolsmtp' => Smtp::class, - ]; - - /** - * Service factories - * - * @var array - */ - protected $factories = [ - Smtp\Auth\Crammd5::class => InvokableFactory::class, - Smtp\Auth\Login::class => InvokableFactory::class, - Smtp\Auth\Plain::class => InvokableFactory::class, - Smtp::class => InvokableFactory::class, - - // v2 normalized service names - - 'laminasmailprotocolsmtpauthcrammd5' => InvokableFactory::class, - 'laminasmailprotocolsmtpauthlogin' => InvokableFactory::class, - 'laminasmailprotocolsmtpauthplain' => InvokableFactory::class, - 'laminasmailprotocolsmtp' => InvokableFactory::class, - ]; - - /** - * Plugins must be an instance of the Smtp class - * - * @var string - */ - protected $instanceOf = Smtp::class; - - /** - * Validate a retrieved plugin instance (v3). - * - * @param object|array $instance - * @throws InvalidServiceException - */ - public function validate($instance) - { - if (! $instance instanceof $this->instanceOf) { - throw new InvalidServiceException(sprintf( - 'Plugin of type %s is invalid; must extend %s', - (is_object($instance) ? get_class($instance) : gettype($instance)), - $this->instanceOf - )); - } - } - - /** - * Validate a retrieved plugin instance (v2). - * - * @param object $plugin - * @throws Exception\InvalidArgumentException - */ - public function validatePlugin($plugin) - { - try { - $this->validate($plugin); - } catch (InvalidServiceException $e) { - throw new Exception\InvalidArgumentException( - $e->getMessage(), - $e->getCode(), - $e - ); - } - } -} diff --git a/lib/laminas/laminas-mail/src/Protocol/SmtpPluginManagerFactory.php b/lib/laminas/laminas-mail/src/Protocol/SmtpPluginManagerFactory.php deleted file mode 100644 index 0b0555fce..000000000 --- a/lib/laminas/laminas-mail/src/Protocol/SmtpPluginManagerFactory.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php - -namespace Laminas\Mail\Protocol; - -use Interop\Container\ContainerInterface; -use Laminas\ServiceManager\FactoryInterface; -use Laminas\ServiceManager\ServiceLocatorInterface; - -class SmtpPluginManagerFactory implements FactoryInterface -{ - /** - * laminas-servicemanager v2 support for invocation options. - * - * @param array - */ - protected $creationOptions; - - /** - * {@inheritDoc} - * - * @return SmtpPluginManager - */ - public function __invoke(ContainerInterface $container, $name, array $options = null) - { - return new SmtpPluginManager($container, $options ?: []); - } - - /** - * {@inheritDoc} - * - * @return SmtpPluginManager - */ - public function createService(ServiceLocatorInterface $container, $name = null, $requestedName = null) - { - return $this($container, $requestedName ?: SmtpPluginManager::class, $this->creationOptions); - } - - /** - * laminas-servicemanager v2 support for invocation options. - * - * @param array $options - * @return void - */ - public function setCreationOptions(array $options) - { - $this->creationOptions = $options; - } -} diff --git a/lib/laminas/laminas-mail/src/Storage.php b/lib/laminas/laminas-mail/src/Storage.php deleted file mode 100644 index c4f8d9fe3..000000000 --- a/lib/laminas/laminas-mail/src/Storage.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php - -namespace Laminas\Mail; - -class Storage -{ - // maildir and IMAP flags, using IMAP names, where possible to be able to distinguish between IMAP - // system flags and other flags - public const FLAG_PASSED = 'Passed'; - public const FLAG_SEEN = '\Seen'; - public const FLAG_UNSEEN = '\Unseen'; - public const FLAG_ANSWERED = '\Answered'; - public const FLAG_FLAGGED = '\Flagged'; - public const FLAG_DELETED = '\Deleted'; - public const FLAG_DRAFT = '\Draft'; - public const FLAG_RECENT = '\Recent'; -} diff --git a/lib/laminas/laminas-mail/src/Storage/AbstractStorage.php b/lib/laminas/laminas-mail/src/Storage/AbstractStorage.php deleted file mode 100644 index 3340e359a..000000000 --- a/lib/laminas/laminas-mail/src/Storage/AbstractStorage.php +++ /dev/null @@ -1,325 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage; - -use ArrayAccess; -use Countable; -use ReturnTypeWillChange; -use SeekableIterator; - -abstract class AbstractStorage implements - ArrayAccess, - Countable, - SeekableIterator -{ - /** - * class capabilities with default values - * @var array - */ - protected $has = [ - 'uniqueid' => true, - 'delete' => false, - 'create' => false, - 'top' => false, - 'fetchPart' => true, - 'flags' => false, - ]; - - /** - * current iteration position - * @var int - */ - protected $iterationPos = 0; - - /** - * maximum iteration position (= message count) - * @var null|int - */ - protected $iterationMax = null; - - /** - * used message class, change it in an extended class to extend the returned message class - * @var string - */ - protected $messageClass = Message::class; - - /** - * Getter for has-properties. The standard has properties - * are: hasFolder, hasUniqueid, hasDelete, hasCreate, hasTop - * - * The valid values for the has-properties are: - * - true if a feature is supported - * - false if a feature is not supported - * - null is it's not yet known or it can't be know if a feature is supported - * - * @param string $var property name - * @throws Exception\InvalidArgumentException - * @return bool supported or not - */ - public function __get($var) - { - if (strpos($var, 'has') === 0) { - $var = strtolower(substr($var, 3)); - return isset($this->has[$var]) ? $this->has[$var] : null; - } - - throw new Exception\InvalidArgumentException($var . ' not found'); - } - - /** - * Get a full list of features supported by the specific mail lib and the server - * - * @return array list of features as array(feature_name => true|false[|null]) - */ - public function getCapabilities() - { - return $this->has; - } - - /** - * Count messages messages in current box/folder - * - * @return int number of messages - * @throws Exception\ExceptionInterface - */ - abstract public function countMessages(); - - /** - * Get a list of messages with number and size - * - * @param int $id number of message - * @return int|array size of given message of list with all messages as array(num => size) - */ - abstract public function getSize($id = 0); - - /** - * Get a message with headers and body - * - * @param $id int number of message - * @return Message - */ - abstract public function getMessage($id); - - /** - * Get raw header of message or part - * - * @param int $id number of message - * @param null|array|string $part path to part or null for message header - * @param int $topLines include this many lines with header (after an empty line) - * @return string raw header - */ - abstract public function getRawHeader($id, $part = null, $topLines = 0); - - /** - * Get raw content of message or part - * - * @param int $id number of message - * @param null|array|string $part path to part or null for message content - * @return string raw content - */ - abstract public function getRawContent($id, $part = null); - - /** - * Create instance with parameters - * - * @param array $params mail reader specific parameters - * @throws Exception\ExceptionInterface - */ - abstract public function __construct($params); - - /** - * Destructor calls close() and therefore closes the resource. - */ - public function __destruct() - { - $this->close(); - } - - /** - * Close resource for mail lib. If you need to control, when the resource - * is closed. Otherwise the destructor would call this. - */ - abstract public function close(); - - /** - * Keep the resource alive. - */ - abstract public function noop(); - - /** - * delete a message from current box/folder - * - * @param $id - */ - abstract public function removeMessage($id); - - /** - * get unique id for one or all messages - * - * if storage does not support unique ids it's the same as the message number - * - * @param int|null $id message number - * @return array|string message number for given message or all messages as array - * @throws Exception\ExceptionInterface - */ - abstract public function getUniqueId($id = null); - - /** - * get a message number from a unique id - * - * I.e. if you have a webmailer that supports deleting messages you should use unique ids - * as parameter and use this method to translate it to message number right before calling removeMessage() - * - * @param string $id unique id - * @return int message number - * @throws Exception\ExceptionInterface - */ - abstract public function getNumberByUniqueId($id); - - // interface implementations follows - - /** - * Countable::count() - * - * @return int - */ - #[ReturnTypeWillChange] - public function count() - { - return $this->countMessages(); - } - - /** - * ArrayAccess::offsetExists() - * - * @param int $id - * @return bool - */ - #[ReturnTypeWillChange] - public function offsetExists($id) - { - try { - if ($this->getMessage($id)) { - return true; - } - } catch (Exception\ExceptionInterface $e) { - } - - return false; - } - - /** - * ArrayAccess::offsetGet() - * - * @param int $id - * @return \Laminas\Mail\Storage\Message message object - */ - #[ReturnTypeWillChange] - public function offsetGet($id) - { - return $this->getMessage($id); - } - - /** - * ArrayAccess::offsetSet() - * - * @param mixed $id - * @param mixed $value - * @throws Exception\RuntimeException - */ - #[ReturnTypeWillChange] - public function offsetSet($id, $value) - { - throw new Exception\RuntimeException('cannot write mail messages via array access'); - } - - /** - * ArrayAccess::offsetUnset() - * - * @param int $id - * @return bool success - */ - #[ReturnTypeWillChange] - public function offsetUnset($id) - { - return $this->removeMessage($id); - } - - /** - * Iterator::rewind() - * - * Rewind always gets the new count from the storage. Thus if you use - * the interfaces and your scripts take long you should use reset() - * from time to time. - */ - #[ReturnTypeWillChange] - public function rewind() - { - $this->iterationMax = $this->countMessages(); - $this->iterationPos = 1; - } - - /** - * Iterator::current() - * - * @return Message current message - */ - #[ReturnTypeWillChange] - public function current() - { - return $this->getMessage($this->iterationPos); - } - - /** - * Iterator::key() - * - * @return int id of current position - */ - #[ReturnTypeWillChange] - public function key() - { - return $this->iterationPos; - } - - /** - * Iterator::next() - */ - #[ReturnTypeWillChange] - public function next() - { - ++$this->iterationPos; - } - - /** - * Iterator::valid() - * - * @return bool - */ - #[ReturnTypeWillChange] - public function valid() - { - if ($this->iterationMax === null) { - $this->iterationMax = $this->countMessages(); - } - return $this->iterationPos && $this->iterationPos <= $this->iterationMax; - } - - /** - * SeekableIterator::seek() - * - * @param int $pos - * @throws Exception\OutOfBoundsException - */ - #[ReturnTypeWillChange] - public function seek($pos) - { - if ($this->iterationMax === null) { - $this->iterationMax = $this->countMessages(); - } - - if ($pos > $this->iterationMax) { - throw new Exception\OutOfBoundsException('this position does not exist'); - } - $this->iterationPos = $pos; - } -} diff --git a/lib/laminas/laminas-mail/src/Storage/Exception/ExceptionInterface.php b/lib/laminas/laminas-mail/src/Storage/Exception/ExceptionInterface.php deleted file mode 100644 index 856cd626a..000000000 --- a/lib/laminas/laminas-mail/src/Storage/Exception/ExceptionInterface.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage\Exception; - -use Laminas\Mail\Exception\ExceptionInterface as MailException; - -interface ExceptionInterface extends MailException -{ -} diff --git a/lib/laminas/laminas-mail/src/Storage/Exception/InvalidArgumentException.php b/lib/laminas/laminas-mail/src/Storage/Exception/InvalidArgumentException.php deleted file mode 100644 index bef8b4b6c..000000000 --- a/lib/laminas/laminas-mail/src/Storage/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage\Exception; - -use Laminas\Mail\Exception; - -/** - * Exception for Laminas\Mail component. - */ -class InvalidArgumentException extends Exception\InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-mail/src/Storage/Exception/OutOfBoundsException.php b/lib/laminas/laminas-mail/src/Storage/Exception/OutOfBoundsException.php deleted file mode 100644 index 84b897d9e..000000000 --- a/lib/laminas/laminas-mail/src/Storage/Exception/OutOfBoundsException.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage\Exception; - -use Laminas\Mail\Exception; - -/** - * Exception for Laminas\Mail component. - */ -class OutOfBoundsException extends Exception\OutOfBoundsException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-mail/src/Storage/Exception/RuntimeException.php b/lib/laminas/laminas-mail/src/Storage/Exception/RuntimeException.php deleted file mode 100644 index d30aed065..000000000 --- a/lib/laminas/laminas-mail/src/Storage/Exception/RuntimeException.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage\Exception; - -use Laminas\Mail\Exception; - -/** - * Exception for Laminas\Mail component. - */ -class RuntimeException extends Exception\RuntimeException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-mail/src/Storage/Folder.php b/lib/laminas/laminas-mail/src/Storage/Folder.php deleted file mode 100644 index 2d6dce0d7..000000000 --- a/lib/laminas/laminas-mail/src/Storage/Folder.php +++ /dev/null @@ -1,211 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage; - -use RecursiveIterator; -use ReturnTypeWillChange; - -class Folder implements RecursiveIterator -{ - /** - * subfolders of folder array(localName => \Laminas\Mail\Storage\Folder folder) - * @var array - */ - protected $folders; - - /** - * local name (name of folder in parent folder) - * @var string - */ - protected $localName; - - /** - * global name (absolute name of folder) - * @var string - */ - protected $globalName; - - /** - * folder is selectable if folder is able to hold messages, otherwise it is a parent folder - * @var bool - */ - protected $selectable = true; - - /** - * create a new mail folder instance - * - * @param string $localName name of folder in current subdirectory - * @param string $globalName absolute name of folder - * @param bool $selectable if true folder holds messages, if false it's - * just a parent for subfolders (Default: true) - * @param array $folders init with given instances of Folder as subfolders - */ - public function __construct($localName, $globalName = '', $selectable = true, array $folders = []) - { - $this->localName = $localName; - $this->globalName = $globalName ? $globalName : $localName; - $this->selectable = $selectable; - $this->folders = $folders; - } - - /** - * implements RecursiveIterator::hasChildren() - * - * @return bool current element has children - */ - #[ReturnTypeWillChange] - public function hasChildren() - { - $current = $this->current(); - return $current && $current instanceof self && ! $current->isLeaf(); - } - - /** - * implements RecursiveIterator::getChildren() - * - * @return \Laminas\Mail\Storage\Folder same as self::current() - */ - #[ReturnTypeWillChange] - public function getChildren() - { - return $this->current(); - } - - /** - * implements Iterator::valid() - * - * @return bool check if there's a current element - */ - #[ReturnTypeWillChange] - public function valid() - { - return key($this->folders) !== null; - } - - /** - * implements Iterator::next() - */ - #[ReturnTypeWillChange] - public function next() - { - next($this->folders); - } - - /** - * implements Iterator::key() - * - * @return string key/local name of current element - */ - #[ReturnTypeWillChange] - public function key() - { - return key($this->folders); - } - - /** - * implements Iterator::current() - * - * @return \Laminas\Mail\Storage\Folder current folder - */ - #[ReturnTypeWillChange] - public function current() - { - return current($this->folders); - } - - /** - * implements Iterator::rewind() - */ - #[ReturnTypeWillChange] - public function rewind() - { - reset($this->folders); - } - - /** - * get subfolder named $name - * - * @param string $name wanted subfolder - * @throws Exception\InvalidArgumentException - * @return \Laminas\Mail\Storage\Folder folder named $folder - */ - public function __get($name) - { - if (! isset($this->folders[$name])) { - throw new Exception\InvalidArgumentException("no subfolder named $name"); - } - - return $this->folders[$name]; - } - - /** - * add or replace subfolder named $name - * - * @param string $name local name of subfolder - * @param \Laminas\Mail\Storage\Folder $folder instance for new subfolder - */ - public function __set($name, self $folder) - { - $this->folders[$name] = $folder; - } - - /** - * remove subfolder named $name - * - * @param string $name local name of subfolder - */ - public function __unset($name) - { - unset($this->folders[$name]); - } - - /** - * magic method for easy output of global name - * - * @return string global name of folder - */ - public function __toString() - { - return (string) $this->getGlobalName(); - } - - /** - * get local name - * - * @return string local name - */ - public function getLocalName() - { - return $this->localName; - } - - /** - * get global name - * - * @return string global name - */ - public function getGlobalName() - { - return $this->globalName; - } - - /** - * is this folder selectable? - * - * @return bool selectable - */ - public function isSelectable() - { - return $this->selectable; - } - - /** - * check if folder has no subfolder - * - * @return bool true if no subfolders - */ - public function isLeaf() - { - return empty($this->folders); - } -} diff --git a/lib/laminas/laminas-mail/src/Storage/Folder/FolderInterface.php b/lib/laminas/laminas-mail/src/Storage/Folder/FolderInterface.php deleted file mode 100644 index c26775b38..000000000 --- a/lib/laminas/laminas-mail/src/Storage/Folder/FolderInterface.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage\Folder; - -interface FolderInterface -{ - /** - * get root folder or given folder - * - * @param string $rootFolder get folder structure for given folder, else root - * @return FolderInterface root or wanted folder - */ - public function getFolders($rootFolder = null); - - /** - * select given folder - * - * folder must be selectable! - * - * @param FolderInterface|string $globalName global name of folder or instance for subfolder - * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface - */ - public function selectFolder($globalName); - - /** - * get Laminas\Mail\Storage\Folder instance for current folder - * - * @return FolderInterface instance of current folder - * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface - */ - public function getCurrentFolder(); -} diff --git a/lib/laminas/laminas-mail/src/Storage/Folder/Maildir.php b/lib/laminas/laminas-mail/src/Storage/Folder/Maildir.php deleted file mode 100644 index eafc2f299..000000000 --- a/lib/laminas/laminas-mail/src/Storage/Folder/Maildir.php +++ /dev/null @@ -1,223 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage\Folder; - -use Laminas\Mail\Storage; -use Laminas\Mail\Storage\Exception; -use Laminas\Mail\Storage\ParamsNormalizer; -use Laminas\Stdlib\ErrorHandler; - -class Maildir extends Storage\Maildir implements FolderInterface -{ - /** - * root folder for folder structure - * @var Storage\Folder - */ - protected $rootFolder; - - /** - * rootdir of folder structure - * @var string - */ - protected $rootdir; - - /** - * name of current folder - * @var string - */ - protected $currentFolder; - - /** - * delim char for subfolders - * @var string - */ - protected $delim; - - /** - * Create instance with parameters - * - * Supported parameters are: - * - * - dirname rootdir of maildir structure - * - delim delim char for folder structure, default is '.' - * - folder initial selected folder, default is 'INBOX' - * - * @param $params array mail reader specific parameters - * @throws Exception\InvalidArgumentException - */ - public function __construct($params) - { - $params = ParamsNormalizer::normalizeParams($params); - - if (! isset($params['dirname'])) { - throw new Exception\InvalidArgumentException('no dirname provided in params'); - } - - $dirname = (string) $params['dirname']; - - if (! is_dir($dirname)) { - throw new Exception\InvalidArgumentException('$dirname provided in params is not a directory'); - } - - $this->rootdir = rtrim($dirname, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; - - $delim = $params['delim'] ?? '.'; - $this->delim = (string) $delim; - - $folder = $params['folder'] ?? 'INBOX'; - - $this->buildFolderTree(); - $this->selectFolder((string) $folder); - $this->has['top'] = true; - $this->has['flags'] = true; - } - - /** - * find all subfolders and mbox files for folder structure - * - * Result is save in Storage\Folder instances with the root in $this->rootFolder. - * $parentFolder and $parentGlobalName are only used internally for recursion. - * - * @throws Exception\RuntimeException - */ - protected function buildFolderTree() - { - $this->rootFolder = new Storage\Folder('/', '/', false); - $this->rootFolder->INBOX = new Storage\Folder('INBOX', 'INBOX', true); - - ErrorHandler::start(E_WARNING); - $dh = opendir($this->rootdir); - $error = ErrorHandler::stop(); - if (! $dh) { - throw new Exception\RuntimeException("can't read folders in maildir", 0, $error); - } - $dirs = []; - - while (($entry = readdir($dh)) !== false) { - // maildir++ defines folders must start with . - if ($entry[0] != '.' || $entry == '.' || $entry == '..') { - continue; - } - - if ($this->isMaildir($this->rootdir . $entry)) { - $dirs[] = $entry; - } - } - closedir($dh); - - sort($dirs); - $stack = [null]; - $folderStack = [null]; - $parentFolder = $this->rootFolder; - $parent = '.'; - - foreach ($dirs as $dir) { - do { - if (strpos($dir, $parent) === 0) { - $local = substr($dir, strlen($parent)); - if (strpos($local, $this->delim) !== false) { - throw new Exception\RuntimeException('error while reading maildir'); - } - array_push($stack, $parent); - $parent = $dir . $this->delim; - $folder = new Storage\Folder($local, substr($dir, 1), true); - $parentFolder->$local = $folder; - array_push($folderStack, $parentFolder); - $parentFolder = $folder; - break; - } elseif ($stack) { - $parent = array_pop($stack); - $parentFolder = array_pop($folderStack); - } - } while ($stack); - if (! $stack) { - throw new Exception\RuntimeException('error while reading maildir'); - } - } - } - - /** - * get root folder or given folder - * - * @param string $rootFolder get folder structure for given folder, else root - * @throws \Laminas\Mail\Storage\Exception\InvalidArgumentException - * @return \Laminas\Mail\Storage\Folder root or wanted folder - */ - public function getFolders($rootFolder = null) - { - if (! $rootFolder || $rootFolder == 'INBOX') { - return $this->rootFolder; - } - - // rootdir is same as INBOX in maildir - if (strpos($rootFolder, 'INBOX' . $this->delim) === 0) { - $rootFolder = substr($rootFolder, 6); - } - $currentFolder = $this->rootFolder; - $subname = trim($rootFolder, $this->delim); - - while ($currentFolder) { - if (false !== strpos($subname, $this->delim)) { - list($entry, $subname) = explode($this->delim, $subname, 2); - } else { - $entry = $subname; - $subname = null; - } - - $currentFolder = $currentFolder->$entry; - - if (! $subname) { - break; - } - } - - if ($currentFolder->getGlobalName() != rtrim($rootFolder, $this->delim)) { - throw new Exception\InvalidArgumentException("folder $rootFolder not found"); - } - return $currentFolder; - } - - /** - * select given folder - * - * folder must be selectable! - * - * @param Storage\Folder|string $globalName global name of folder or - * instance for subfolder - * @throws Exception\RuntimeException - */ - public function selectFolder($globalName) - { - $this->currentFolder = (string) $globalName; - - // getting folder from folder tree for validation - $folder = $this->getFolders($this->currentFolder); - - try { - $this->openMaildir($this->rootdir . '.' . $folder->getGlobalName()); - } catch (Exception\ExceptionInterface $e) { - // check what went wrong - if (! $folder->isSelectable()) { - throw new Exception\RuntimeException("{$this->currentFolder} is not selectable", 0, $e); - } - // seems like file has vanished; rebuilding folder tree - but it's still an exception - $this->buildFolderTree(); - throw new Exception\RuntimeException( - 'seems like the maildir has vanished; I have rebuilt the folder tree; ' - . 'search for another folder and try again', - 0, - $e - ); - } - } - - /** - * get Storage\Folder instance for current folder - * - * @return Storage\Folder instance of current folder - */ - public function getCurrentFolder() - { - return $this->currentFolder; - } -} diff --git a/lib/laminas/laminas-mail/src/Storage/Folder/Mbox.php b/lib/laminas/laminas-mail/src/Storage/Folder/Mbox.php deleted file mode 100644 index 8fed65d89..000000000 --- a/lib/laminas/laminas-mail/src/Storage/Folder/Mbox.php +++ /dev/null @@ -1,219 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage\Folder; - -use Laminas\Mail\Storage; -use Laminas\Mail\Storage\Exception; -use Laminas\Mail\Storage\ParamsNormalizer; -use Laminas\Stdlib\ErrorHandler; - -class Mbox extends Storage\Mbox implements FolderInterface -{ - /** - * Storage\Folder root folder for folder structure - * @var Storage\Folder - */ - protected $rootFolder; - - /** - * rootdir of folder structure - * @var string - */ - protected $rootdir; - - /** - * name of current folder - * @var string - */ - protected $currentFolder; - - /** - * Create instance with parameters - * - * Disallowed parameters are: - * - filename use \Laminas\Mail\Storage\Mbox for a single file - * - * Supported parameters are: - * - * - dirname rootdir of mbox structure - * - folder initial selected folder, default is 'INBOX' - * - * @param $params array|object Array, iterable object, or stdClass object - * with reader specific parameters - * @throws Exception\InvalidArgumentException - */ - public function __construct($params) - { - $params = ParamsNormalizer::normalizeParams($params); - - if (isset($params['filename'])) { - throw new Exception\InvalidArgumentException(sprintf('use %s for a single file', Storage\Mbox::class)); - } - - if (! isset($params['dirname'])) { - throw new Exception\InvalidArgumentException('no dirname provided in params'); - } - - $dirname = (string) $params['dirname']; - - if (! is_dir($dirname)) { - throw new Exception\InvalidArgumentException('$dirname provided in params is not a directory'); - } - - $this->rootdir = rtrim($dirname, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; - $folder = $params['folder'] ?? 'INBOX'; - - $this->buildFolderTree($this->rootdir); - $this->selectFolder((string) $folder); - $this->has['top'] = true; - $this->has['uniqueid'] = false; - } - - /** - * find all subfolders and mbox files for folder structure - * - * Result is save in Storage\Folder instances with the root in $this->rootFolder. - * $parentFolder and $parentGlobalName are only used internally for recursion. - * - * @param string $currentDir call with root dir, also used for recursion. - * @param Storage\Folder|null $parentFolder used for recursion - * @param string $parentGlobalName used for recursion - * @throws Exception\InvalidArgumentException - */ - protected function buildFolderTree($currentDir, $parentFolder = null, $parentGlobalName = '') - { - if (! $parentFolder) { - $this->rootFolder = new Storage\Folder('/', '/', false); - $parentFolder = $this->rootFolder; - } - - ErrorHandler::start(E_WARNING); - $dh = opendir($currentDir); - ErrorHandler::stop(); - if (! $dh) { - throw new Exception\InvalidArgumentException("can't read dir $currentDir"); - } - while (($entry = readdir($dh)) !== false) { - // ignore hidden files for mbox - if ($entry[0] == '.') { - continue; - } - $absoluteEntry = $currentDir . $entry; - $globalName = $parentGlobalName . DIRECTORY_SEPARATOR . $entry; - if (is_file($absoluteEntry) && $this->isMboxFile($absoluteEntry)) { - $parentFolder->$entry = new Storage\Folder($entry, $globalName); - continue; - } - if (! is_dir($absoluteEntry) /* || $entry == '.' || $entry == '..' */) { - continue; - } - $folder = new Storage\Folder($entry, $globalName, false); - $parentFolder->$entry = $folder; - $this->buildFolderTree($absoluteEntry . DIRECTORY_SEPARATOR, $folder, $globalName); - } - - closedir($dh); - } - - /** - * get root folder or given folder - * - * @param string $rootFolder get folder structure for given folder, else root - * @return Storage\Folder root or wanted folder - * @throws Exception\InvalidArgumentException - */ - public function getFolders($rootFolder = null) - { - if (! $rootFolder) { - return $this->rootFolder; - } - - $currentFolder = $this->rootFolder; - $subname = trim($rootFolder, DIRECTORY_SEPARATOR); - while ($currentFolder) { - if (false !== strpos($subname, DIRECTORY_SEPARATOR)) { - list($entry, $subname) = explode(DIRECTORY_SEPARATOR, $subname, 2); - } else { - $entry = $subname; - $subname = null; - } - - $currentFolder = $currentFolder->$entry; - - if (! $subname) { - break; - } - } - - if ($currentFolder->getGlobalName() != DIRECTORY_SEPARATOR . trim($rootFolder, DIRECTORY_SEPARATOR)) { - throw new Exception\InvalidArgumentException("folder $rootFolder not found"); - } - return $currentFolder; - } - - /** - * select given folder - * - * folder must be selectable! - * - * @param Storage\Folder|string $globalName global name of folder or - * instance for subfolder - * @throws Exception\RuntimeException - */ - public function selectFolder($globalName) - { - $this->currentFolder = (string) $globalName; - - // getting folder from folder tree for validation - $folder = $this->getFolders($this->currentFolder); - - try { - $this->openMboxFile($this->rootdir . $folder->getGlobalName()); - } catch (Exception\ExceptionInterface $e) { - // check what went wrong - if (! $folder->isSelectable()) { - throw new Exception\RuntimeException("{$this->currentFolder} is not selectable", 0, $e); - } - // seems like file has vanished; rebuilding folder tree - but it's still an exception - $this->buildFolderTree($this->rootdir); - throw new Exception\RuntimeException( - 'seems like the mbox file has vanished; I have rebuilt the folder tree; ' - . 'search for another folder and try again', - 0, - $e - ); - } - } - - /** - * get Storage\Folder instance for current folder - * - * @return Storage\Folder instance of current folder - * @throws Exception\ExceptionInterface - */ - public function getCurrentFolder() - { - return $this->currentFolder; - } - - /** - * magic method for serialize() - * - * with this method you can cache the mbox class - * - * @return array name of variables - */ - public function __sleep() - { - return array_merge(parent::__sleep(), ['currentFolder', 'rootFolder', 'rootdir']); - } - - /** - * magic method for unserialize(), with this method you can cache the mbox class - */ - public function __wakeup() - { - // if cache is stall selectFolder() rebuilds the tree on error - parent::__wakeup(); - } -} diff --git a/lib/laminas/laminas-mail/src/Storage/Imap.php b/lib/laminas/laminas-mail/src/Storage/Imap.php deleted file mode 100644 index 30196a5a7..000000000 --- a/lib/laminas/laminas-mail/src/Storage/Imap.php +++ /dev/null @@ -1,553 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage; - -use Laminas\Mail; -use Laminas\Mail\Protocol; - -class Imap extends AbstractStorage implements Folder\FolderInterface, Writable\WritableInterface -{ - // TODO: with an internal cache we could optimize this class, or create an extra class with - // such optimizations. Especially the various fetch calls could be combined to one cache call - - /** - * protocol handler - * @var null|Protocol\Imap - */ - protected $protocol; - - /** - * name of current folder - * @var string - */ - protected $currentFolder = ''; - - /** - * IMAP folder delimiter character - * @var null|string - */ - protected $delimiter; - - /** - * IMAP flags to constants translation - * @var array - */ - protected static $knownFlags = [ - '\Passed' => Mail\Storage::FLAG_PASSED, - '\Answered' => Mail\Storage::FLAG_ANSWERED, - '\Seen' => Mail\Storage::FLAG_SEEN, - '\Unseen' => Mail\Storage::FLAG_UNSEEN, - '\Deleted' => Mail\Storage::FLAG_DELETED, - '\Draft' => Mail\Storage::FLAG_DRAFT, - '\Flagged' => Mail\Storage::FLAG_FLAGGED, - ]; - - /** - * IMAP flags to search criteria - * @var array - */ - protected static $searchFlags = [ - '\Recent' => 'RECENT', - '\Answered' => 'ANSWERED', - '\Seen' => 'SEEN', - '\Unseen' => 'UNSEEN', - '\Deleted' => 'DELETED', - '\Draft' => 'DRAFT', - '\Flagged' => 'FLAGGED', - ]; - - /** - * Count messages all messages in current box - * - * @param null $flags - * @throws Exception\RuntimeException - * @throws Protocol\Exception\RuntimeException - * @return int number of messages - */ - public function countMessages($flags = null) - { - if (! $this->currentFolder) { - throw new Exception\RuntimeException('No selected folder to count'); - } - - if ($flags === null) { - return count($this->protocol->search(['ALL'])); - } - - $params = []; - foreach ((array) $flags as $flag) { - if (isset(static::$searchFlags[$flag])) { - $params[] = static::$searchFlags[$flag]; - } else { - $params[] = 'KEYWORD'; - $params[] = $this->protocol->escapeString($flag); - } - } - return count($this->protocol->search($params)); - } - - /** - * get a list of messages with number and size - * - * @param int $id number of message - * @return int|array size of given message of list with all messages as [num => size] - * @throws Protocol\Exception\RuntimeException - */ - public function getSize($id = 0) - { - if ($id) { - return $this->protocol->fetch('RFC822.SIZE', $id); - } - return $this->protocol->fetch('RFC822.SIZE', 1, INF); - } - - /** - * Fetch a message - * - * @param int $id number of message - * @return Message - * @throws Protocol\Exception\RuntimeException - */ - public function getMessage($id) - { - $data = $this->protocol->fetch(['FLAGS', 'RFC822.HEADER'], $id); - $header = $data['RFC822.HEADER']; - - $flags = []; - foreach ($data['FLAGS'] as $flag) { - $flags[] = static::$knownFlags[$flag] ?? $flag; - } - - return new $this->messageClass(['handler' => $this, 'id' => $id, 'headers' => $header, 'flags' => $flags]); - } - - /* - * Get raw header of message or part - * - * @param int $id number of message - * @param null|array|string $part path to part or null for message header - * @param int $topLines include this many lines with header (after an empty line) - * @param int $topLines include this many lines with header (after an empty line) - * @return string raw header - * @throws Exception\RuntimeException - * @throws Protocol\Exception\RuntimeException - */ - public function getRawHeader($id, $part = null, $topLines = 0) - { - if ($part !== null) { - // TODO: implement - throw new Exception\RuntimeException('not implemented'); - } - - // TODO: toplines - return $this->protocol->fetch('RFC822.HEADER', $id); - } - - /* - * Get raw content of message or part - * - * @param int $id number of message - * @param null|array|string $part path to part or null for message content - * @return string raw content - * @throws Protocol\Exception\RuntimeException - * @throws Exception\RuntimeException - */ - public function getRawContent($id, $part = null) - { - if ($part !== null) { - // TODO: implement - throw new Exception\RuntimeException('not implemented'); - } - - return $this->protocol->fetch('RFC822.TEXT', $id); - } - - /** - * create instance with parameters - * - * Supported parameters are - * - * - user username - * - host hostname or ip address of IMAP server [optional, default = 'localhost'] - * - password password for user 'username' [optional, default = ''] - * - port port for IMAP server [optional, default = 110] - * - ssl 'SSL' or 'TLS' for secure sockets - * - folder select this folder [optional, default = 'INBOX'] - * - * @param array|object|Protocol\Imap $params mail reader specific - * parameters or configured Imap protocol object - * @throws Exception\RuntimeException - * @throws Exception\InvalidArgumentException - * @throws Protocol\Exception\RuntimeException - */ - public function __construct($params) - { - $this->has['flags'] = true; - - if ($params instanceof Protocol\Imap) { - $this->protocol = $params; - try { - $this->selectFolder('INBOX'); - } catch (Exception\ExceptionInterface $e) { - throw new Exception\RuntimeException('cannot select INBOX, is this a valid transport?', 0, $e); - } - return; - } - - $params = ParamsNormalizer::normalizeParams($params); - - if (! isset($params['user'])) { - throw new Exception\InvalidArgumentException('need at least user in params'); - } - - $host = $params['host'] ?? 'localhost'; - $password = $params['password'] ?? ''; - $port = $params['port'] ?? null; - $ssl = $params['ssl'] ?? false; - $folder = $params['folder'] ?? 'INBOX'; - - if (null !== $port) { - $port = (int) $port; - } - - if (! is_string($ssl)) { - $ssl = (bool) $ssl; - } - - $this->protocol = new Protocol\Imap(); - - if (array_key_exists('novalidatecert', $params)) { - $this->protocol->setNoValidateCert((bool) $params['novalidatecert']); - } - - $this->protocol->connect((string) $host, $port, $ssl); - if (! $this->protocol->login((string) $params['user'], (string) $password)) { - throw new Exception\RuntimeException('cannot login, user or password wrong'); - } - $this->selectFolder((string) $folder); - } - - /** - * Close resource for mail lib. - * - * If you need to control, when the resource is closed. Otherwise the - * destructor would call this. - */ - public function close() - { - $this->currentFolder = ''; - $this->protocol->logout(); - } - - /** - * Keep the server busy. - * - * @throws Exception\RuntimeException - */ - public function noop() - { - if (! $this->protocol->noop()) { - throw new Exception\RuntimeException('could not do nothing'); - } - } - - /** - * Remove a message from server. - * - * If you're doing that from a web environment you should be careful and - * use a uniqueid as parameter if possible to identify the message. - * - * @param int $id number of message - * @throws Exception\RuntimeException - */ - public function removeMessage($id) - { - if (! $this->protocol->store([Mail\Storage::FLAG_DELETED], $id, null, '+')) { - throw new Exception\RuntimeException('cannot set deleted flag'); - } - // TODO: expunge here or at close? we can handle an error here better and are more fail safe - if (! $this->protocol->expunge()) { - throw new Exception\RuntimeException('message marked as deleted, but could not expunge'); - } - } - - /** - * get unique id for one or all messages - * - * if storage does not support unique ids it's the same as the message - * number. - * - * @param int|null $id message number - * @return array|string message number for given message or all messages as array - * @throws Protocol\Exception\RuntimeException - */ - public function getUniqueId($id = null) - { - if ($id) { - return $this->protocol->fetch('UID', $id); - } - - return $this->protocol->fetch('UID', 1, INF); - } - - /** - * get a message number from a unique id - * - * I.e. if you have a webmailer that supports deleting messages you should - * use unique ids as parameter and use this method to translate it to - * message number right before calling removeMessage() - * - * @param string $id unique id - * @throws Exception\InvalidArgumentException - * @return int message number - */ - public function getNumberByUniqueId($id) - { - // TODO: use search to find number directly - $ids = $this->getUniqueId(); - foreach ($ids as $k => $v) { - if ($v == $id) { - return $k; - } - } - - throw new Exception\InvalidArgumentException('unique id not found'); - } - - /** - * get root folder or given folder - * - * @param string $rootFolder get folder structure for given folder, else root - * @throws Exception\RuntimeException - * @throws Exception\InvalidArgumentException - * @throws Protocol\Exception\RuntimeException - * @return Folder root or wanted folder - */ - public function getFolders($rootFolder = null) - { - $folders = $this->protocol->listMailbox((string) $rootFolder); - if (! $folders) { - throw new Exception\InvalidArgumentException('folder not found'); - } - - ksort($folders, SORT_STRING); - $root = new Folder('/', '/', false); - $stack = [null]; - $folderStack = [null]; - $parentFolder = $root; - $parent = ''; - - foreach ($folders as $globalName => $data) { - do { - if (! $parent || strpos($globalName, $parent) === 0) { - $pos = strrpos($globalName, $data['delim']); - if ($pos === false) { - $localName = $globalName; - } else { - $localName = substr($globalName, $pos + 1); - } - $selectable = ! $data['flags'] || ! in_array('\\Noselect', $data['flags']); - - array_push($stack, $parent); - $parent = $globalName . $data['delim']; - $folder = new Folder($localName, $globalName, $selectable); - $parentFolder->$localName = $folder; - array_push($folderStack, $parentFolder); - $parentFolder = $folder; - $this->delimiter = $data['delim']; - break; - } elseif ($stack) { - $parent = array_pop($stack); - $parentFolder = array_pop($folderStack); - } - } while ($stack); - if (! $stack) { - throw new Exception\RuntimeException('error while constructing folder tree'); - } - } - - return $root; - } - - /** - * select given folder - * - * folder must be selectable! - * - * @param Folder|string $globalName global name of folder or instance for subfolder - * @throws Exception\RuntimeException - * @throws Protocol\Exception\RuntimeException - */ - public function selectFolder($globalName) - { - $this->currentFolder = $globalName; - if (! $this->protocol->select($this->currentFolder)) { - $this->currentFolder = ''; - throw new Exception\RuntimeException('cannot change folder, maybe it does not exist'); - } - } - - /** - * get Folder instance for current folder - * - * @return Folder instance of current folder - */ - public function getCurrentFolder() - { - return $this->currentFolder; - } - - /** - * create a new folder - * - * This method also creates parent folders if necessary. Some mail storages - * may restrict, which folder may be used as parent or which chars may be - * used in the folder name - * - * @param string $name global name of folder, local name if $parentFolder - * is set - * @param string|Folder $parentFolder parent folder for new folder, else - * root folder is parent - * @throws Exception\RuntimeException - */ - public function createFolder($name, $parentFolder = null) - { - // TODO: we assume / as the hierarchy delim - need to get that from the folder class! - if ($parentFolder instanceof Folder) { - $folder = $parentFolder->getGlobalName() . '/' . $name; - } elseif ($parentFolder !== null) { - $folder = $parentFolder . '/' . $name; - } else { - $folder = $name; - } - - if (! $this->protocol->create($folder)) { - throw new Exception\RuntimeException('cannot create folder'); - } - } - - /** - * remove a folder - * - * @param string|Folder $name name or instance of folder - * @throws Exception\RuntimeException - */ - public function removeFolder($name) - { - if ($name instanceof Folder) { - $name = $name->getGlobalName(); - } - - if (! $this->protocol->delete($name)) { - throw new Exception\RuntimeException('cannot delete folder'); - } - } - - /** - * rename and/or move folder - * - * The new name has the same restrictions as in createFolder() - * - * @param string|Folder $oldName name or instance of folder - * @param string $newName new global name of folder - * @throws Exception\RuntimeException - */ - public function renameFolder($oldName, $newName) - { - if ($oldName instanceof Folder) { - $oldName = $oldName->getGlobalName(); - } - - if (! $this->protocol->rename($oldName, $newName)) { - throw new Exception\RuntimeException('cannot rename folder'); - } - } - - /** - * append a new message to mail storage - * - * @param string $message message as string or instance of message class - * @param null|string|Folder $folder folder for new message, else current - * folder is taken - * @param null|array $flags set flags for new message, else a default set - * is used - * @throws Exception\RuntimeException - */ - public function appendMessage($message, $folder = null, $flags = null) - { - if ($folder === null) { - $folder = $this->currentFolder; - } - - if ($flags === null) { - $flags = [Mail\Storage::FLAG_SEEN]; - } - - // TODO: handle class instances for $message - if (! $this->protocol->append($folder, $message, $flags)) { - throw new Exception\RuntimeException( - 'cannot create message, please check if the folder exists and your flags' - ); - } - } - - /** - * copy an existing message - * - * @param int $id number of message - * @param string|Folder $folder name or instance of target folder - * @throws Exception\RuntimeException - */ - public function copyMessage($id, $folder) - { - if (! $this->protocol->copy($folder, $id)) { - throw new Exception\RuntimeException('cannot copy message, does the folder exist?'); - } - } - - /** - * move an existing message - * - * NOTE: IMAP has no native move command, thus it's emulated with copy and delete - * - * @param int $id number of message - * @param string|Folder $folder name or instance of target folder - * @throws Exception\RuntimeException - */ - public function moveMessage($id, $folder) - { - $this->copyMessage($id, $folder); - $this->removeMessage($id); - } - - /** - * set flags for message - * - * NOTE: this method can't set the recent flag. - * - * @param int $id number of message - * @param array $flags new flags for message - * @throws Exception\RuntimeException - */ - public function setFlags($id, $flags) - { - if (! $this->protocol->store($flags, $id)) { - throw new Exception\RuntimeException( - 'cannot set flags, have you tried to set the recent flag or special chars?' - ); - } - } - - /** - * get IMAP delimiter - * - * @return string|null - */ - public function delimiter() - { - if (! isset($this->delimiter)) { - $this->getFolders(); - } - return $this->delimiter; - } -} diff --git a/lib/laminas/laminas-mail/src/Storage/Maildir.php b/lib/laminas/laminas-mail/src/Storage/Maildir.php deleted file mode 100644 index ce1c8901b..000000000 --- a/lib/laminas/laminas-mail/src/Storage/Maildir.php +++ /dev/null @@ -1,430 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage; - -use Laminas\Mail; -use Laminas\Stdlib\ErrorHandler; - -class Maildir extends AbstractStorage -{ - /** - * used message class, change it in an extended class to extend the returned message class - * @var string - */ - protected $messageClass = Message\File::class; - - /** - * data of found message files in maildir dir - * @var array - */ - protected $files = []; - - /** - * known flag chars in filenames - * - * This list has to be in alphabetical order for setFlags() - * - * @var array - */ - protected static $knownFlags = [ - 'D' => Mail\Storage::FLAG_DRAFT, - 'F' => Mail\Storage::FLAG_FLAGGED, - 'P' => Mail\Storage::FLAG_PASSED, - 'R' => Mail\Storage::FLAG_ANSWERED, - 'S' => Mail\Storage::FLAG_SEEN, - 'T' => Mail\Storage::FLAG_DELETED, - ]; - - // TODO: getFlags($id) for fast access if headers are not needed (i.e. just setting flags)? - - /** - * Count messages all messages in current box - * - * @param mixed $flags - * @return int number of messages - */ - public function countMessages($flags = null) - { - if ($flags === null) { - return count($this->files); - } - - $count = 0; - if (! is_array($flags)) { - foreach ($this->files as $file) { - if (isset($file['flaglookup'][$flags])) { - ++$count; - } - } - return $count; - } - - $flags = array_flip($flags); - foreach ($this->files as $file) { - foreach ($flags as $flag => $v) { - if (! isset($file['flaglookup'][$flag])) { - continue 2; - } - } - ++$count; - } - return $count; - } - - /** - * Get one or all fields from file structure. Also checks if message is valid - * - * @param int $id message number - * @param string|null $field wanted field - * @throws Exception\InvalidArgumentException - * @return string|array wanted field or all fields as array - */ - protected function getFileData($id, $field = null) - { - if (! isset($this->files[$id - 1])) { - throw new Exception\InvalidArgumentException('id does not exist'); - } - - if (! $field) { - return $this->files[$id - 1]; - } - - if (! isset($this->files[$id - 1][$field])) { - throw new Exception\InvalidArgumentException('field does not exist'); - } - - return $this->files[$id - 1][$field]; - } - - /** - * Get a list of messages with number and size - * - * @param int|null $id number of message or null for all messages - * @return int|array size of given message of list with all messages as array(num => size) - */ - public function getSize($id = null) - { - if ($id !== null) { - $filedata = $this->getFileData($id); - return $filedata['size'] ?? filesize($filedata['filename']); - } - - $result = []; - foreach ($this->files as $num => $data) { - $result[$num + 1] = $data['size'] ?? filesize($data['filename']); - } - - return $result; - } - - /** - * Fetch a message - * - * @param int $id number of message - * @return \Laminas\Mail\Storage\Message\File - * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface - */ - public function getMessage($id) - { - // TODO that's ugly, would be better to let the message class decide - if (\trim($this->messageClass, '\\') === Message\File::class - || is_subclass_of($this->messageClass, Message\File::class) - ) { - return new $this->messageClass([ - 'file' => $this->getFileData($id, 'filename'), - 'flags' => $this->getFileData($id, 'flags'), - ]); - } - - return new $this->messageClass([ - 'handler' => $this, - 'id' => $id, - 'headers' => $this->getRawHeader($id), - 'flags' => $this->getFileData($id, 'flags'), - ]); - } - - /* - * Get raw header of message or part - * - * @param int $id number of message - * @param null|array|string $part path to part or null for message header - * @param int $topLines include this many lines with header (after an empty line) - * @throws Exception\RuntimeException - * @return string raw header - */ - public function getRawHeader($id, $part = null, $topLines = 0) - { - if ($part !== null) { - // TODO: implement - throw new Exception\RuntimeException('not implemented'); - } - - $fh = fopen($this->getFileData($id, 'filename'), 'r'); - - $content = ''; - while (! feof($fh)) { - $line = fgets($fh); - if (! trim($line)) { - break; - } - $content .= $line; - } - - fclose($fh); - return $content; - } - - /* - * Get raw content of message or part - * - * @param int $id number of message - * @param null|array|string $part path to part or null for message content - * @throws Exception\RuntimeException - * @return string raw content - */ - public function getRawContent($id, $part = null) - { - if ($part !== null) { - // TODO: implement - throw new Exception\RuntimeException('not implemented'); - } - - $fh = fopen($this->getFileData($id, 'filename'), 'r'); - - while (! feof($fh)) { - $line = fgets($fh); - if (! trim($line)) { - break; - } - } - - $content = stream_get_contents($fh); - fclose($fh); - return $content; - } - - /** - * Create instance with parameters - * Supported parameters are: - * - dirname dirname of mbox file - * - * @param $params array|object Array, iterable object, or stdClass object - * with reader specific parameters - * @throws Exception\InvalidArgumentException - */ - public function __construct($params) - { - $params = ParamsNormalizer::normalizeParams($params); - - if (! isset($params['dirname'])) { - throw new Exception\InvalidArgumentException('no dirname provided in params'); - } - - $dirname = (string) $params['dirname'] ; - - if (! is_dir($dirname)) { - throw new Exception\InvalidArgumentException(sprintf('Maildir "%s" is not a directory', $dirname)); - } - - if (! $this->isMaildir($dirname)) { - throw new Exception\InvalidArgumentException('invalid maildir given'); - } - - $this->has['top'] = true; - $this->has['flags'] = true; - $this->openMaildir($dirname); - } - - /** - * check if a given dir is a valid maildir - * - * @param string $dirname name of dir - * @return bool dir is valid maildir - */ - protected function isMaildir($dirname) - { - if (file_exists($dirname . '/new') && ! is_dir($dirname . '/new')) { - return false; - } - if (file_exists($dirname . '/tmp') && ! is_dir($dirname . '/tmp')) { - return false; - } - return is_dir($dirname . '/cur'); - } - - /** - * open given dir as current maildir - * - * @param string $dirname name of maildir - * @throws Exception\RuntimeException - */ - protected function openMaildir($dirname) - { - if ($this->files) { - $this->close(); - } - - ErrorHandler::start(E_WARNING); - $dh = opendir($dirname . '/cur/'); - $error = ErrorHandler::stop(); - if (! $dh) { - throw new Exception\RuntimeException('cannot open maildir', 0, $error); - } - $this->getMaildirFiles($dh, $dirname . '/cur/'); - closedir($dh); - - ErrorHandler::start(E_WARNING); - $dh = opendir($dirname . '/new/'); - $error = ErrorHandler::stop(); - if (! $dh) { - throw new Exception\RuntimeException('cannot read recent mails in maildir', 0, $error); - } - - $this->getMaildirFiles($dh, $dirname . '/new/', [Mail\Storage::FLAG_RECENT]); - closedir($dh); - } - - /** - * find all files in opened dir handle and add to maildir files - * - * @param resource $dh dir handle used for search - * @param string $dirname dirname of dir in $dh - * @param array $defaultFlags default flags for given dir - */ - protected function getMaildirFiles($dh, $dirname, $defaultFlags = []) - { - while (($entry = readdir($dh)) !== false) { - if ($entry[0] == '.' || ! is_file($dirname . $entry)) { - continue; - } - - if (false !== strpos($entry, ':')) { - list($uniq, $info) = explode(':', $entry, 2); - } else { - $uniq = $entry; - $info = ''; - } - - if (false !== strpos($uniq, ',')) { - list(, $size) = explode(',', $uniq, 2); - } else { - $size = ''; - } - - if (strlen($size) >= 2 && $size[0] === 'S' && $size[1] === '=') { - $size = substr($size, 2); - } - - if (! ctype_digit($size)) { - $size = null; - } - - if (false !== strpos($info, ',')) { - list($version, $flags) = explode(',', $info, 2); - } else { - $version = $info; - $flags = ''; - } - - if ($version !== '2') { - $flags = ''; - } - - $namedFlags = $defaultFlags; - $length = strlen($flags); - for ($i = 0; $i < $length; ++$i) { - $flag = $flags[$i]; - $namedFlags[$flag] = static::$knownFlags[$flag] ?? $flag; - } - - $data = [ - 'uniq' => $uniq, - 'flags' => $namedFlags, - 'flaglookup' => array_flip($namedFlags), - 'filename' => $dirname . $entry, - ]; - if ($size !== null) { - $data['size'] = (int) $size; - } - $this->files[] = $data; - } - - \usort($this->files, function ($a, $b): int { - return \strcmp($a['filename'], $b['filename']); - }); - } - - /** - * Close resource for mail lib. If you need to control, when the resource - * is closed. Otherwise the destructor would call this. - * - */ - public function close() - { - $this->files = []; - } - - /** - * Waste some CPU cycles doing nothing. - * - * @return bool always return true - */ - public function noop() - { - return true; - } - - /** - * stub for not supported message deletion - * - * @param $id - * @throws Exception\RuntimeException - */ - public function removeMessage($id) - { - throw new Exception\RuntimeException('maildir is (currently) read-only'); - } - - /** - * get unique id for one or all messages - * - * if storage does not support unique ids it's the same as the message number - * - * @param int|null $id message number - * @return array|string message number for given message or all messages as array - */ - public function getUniqueId($id = null) - { - if ($id) { - return $this->getFileData($id, 'uniq'); - } - - $ids = []; - foreach ($this->files as $num => $file) { - $ids[$num + 1] = $file['uniq']; - } - return $ids; - } - - /** - * get a message number from a unique id - * - * I.e. if you have a webmailer that supports deleting messages you should use unique ids - * as parameter and use this method to translate it to message number right before calling removeMessage() - * - * @param string $id unique id - * @throws Exception\InvalidArgumentException - * @return int message number - */ - public function getNumberByUniqueId($id) - { - foreach ($this->files as $num => $file) { - if ($file['uniq'] == $id) { - return $num + 1; - } - } - - throw new Exception\InvalidArgumentException('unique id not found'); - } -} diff --git a/lib/laminas/laminas-mail/src/Storage/Mbox.php b/lib/laminas/laminas-mail/src/Storage/Mbox.php deleted file mode 100644 index 7e2ec748f..000000000 --- a/lib/laminas/laminas-mail/src/Storage/Mbox.php +++ /dev/null @@ -1,410 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage; - -use Laminas\Stdlib\ErrorHandler; - -class Mbox extends AbstractStorage -{ - /** - * file handle to mbox file - * @var null|resource - */ - protected $fh; - - /** - * filename of mbox file for __wakeup - * @var string - */ - protected $filename; - - /** - * modification date of mbox file for __wakeup - * @var int - */ - protected $filemtime; - - /** - * start and end position of messages as array('start' => start, 'separator' => headersep, 'end' => end) - * @var array - */ - protected $positions; - - /** - * used message class, change it in an extended class to extend the returned message class - * @var string - */ - protected $messageClass = Message\File::class; - - /** - * end of Line for messages - * - * @var string|null - */ - protected $messageEOL; - - /** - * Count messages all messages in current box - * - * @return int number of messages - * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface - */ - public function countMessages() - { - return count($this->positions); - } - - /** - * Get a list of messages with number and size - * - * @param int|null $id number of message or null for all messages - * @return int|array size of given message of list with all messages as array(num => size) - */ - public function getSize($id = 0) - { - if ($id) { - $pos = $this->positions[$id - 1]; - return $pos['end'] - $pos['start']; - } - - $result = []; - foreach ($this->positions as $num => $pos) { - $result[$num + 1] = $pos['end'] - $pos['start']; - } - - return $result; - } - - /** - * Get positions for mail message or throw exception if id is invalid - * - * @param int $id number of message - * @throws Exception\InvalidArgumentException - * @return array positions as in positions - */ - protected function getPos($id) - { - if (! isset($this->positions[$id - 1])) { - throw new Exception\InvalidArgumentException('id does not exist'); - } - - return $this->positions[$id - 1]; - } - - /** - * Fetch a message - * - * @param int $id number of message - * @return \Laminas\Mail\Storage\Message\File - * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface - */ - public function getMessage($id) - { - // TODO that's ugly, would be better to let the message class decide - if (is_subclass_of($this->messageClass, Message\File::class) - || strtolower($this->messageClass) === strtolower(Message\File::class)) { - // TODO top/body lines - $messagePos = $this->getPos($id); - - $messageClassParams = [ - 'file' => $this->fh, - 'startPos' => $messagePos['start'], - 'endPos' => $messagePos['end'], - ]; - - if (isset($this->messageEOL)) { - $messageClassParams['EOL'] = $this->messageEOL; - } - - return new $this->messageClass($messageClassParams); - } - - /** @todo Uncomment once we know how to count body lines */ - // $bodyLines = 0; - - $message = $this->getRawHeader($id); - - /* Once we know how to count body lines, we should uncomment the - * following, which would append the body content to the headers. - * - if ($bodyLines) { - $message .= "\n"; - while ($bodyLines-- && ftell($this->fh) < $this->positions[$id - 1]['end']) { - $message .= fgets($this->fh); - } - } - */ - - return new $this->messageClass(['handler' => $this, 'id' => $id, 'headers' => $message]); - } - - /* - * Get raw header of message or part - * - * @param int $id number of message - * @param null|array|string $part path to part or null for message header - * @param int $topLines include this many lines with header (after an empty line) - * @return string raw header - * @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface - * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface - */ - public function getRawHeader($id, $part = null, $topLines = 0) - { - if ($part !== null) { - // TODO: implement - throw new Exception\RuntimeException('not implemented'); - } - $messagePos = $this->getPos($id); - // TODO: toplines - return stream_get_contents($this->fh, $messagePos['separator'] - $messagePos['start'], $messagePos['start']); - } - - /* - * Get raw content of message or part - * - * @param int $id number of message - * @param null|array|string $part path to part or null for message content - * @return string raw content - * @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface - * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface - */ - public function getRawContent($id, $part = null) - { - if ($part !== null) { - // TODO: implement - throw new Exception\RuntimeException('not implemented'); - } - $messagePos = $this->getPos($id); - return stream_get_contents($this->fh, $messagePos['end'] - $messagePos['separator'], $messagePos['separator']); - } - - /** - * Create instance with parameters - * Supported parameters are: - * - filename filename of mbox file - * - * @param $params array|object|Config mail reader specific parameters - * @throws Exception\InvalidArgumentException - */ - public function __construct($params) - { - $params = ParamsNormalizer::normalizeParams($params); - - if (! isset($params['filename'])) { - throw new Exception\InvalidArgumentException('no valid filename given in params'); - } - - if (isset($params['messageEOL'])) { - $this->messageEOL = (string) $params['messageEOL']; - } - - $this->openMboxFile((string) $params['filename']); - $this->has['top'] = true; - $this->has['uniqueid'] = false; - } - - /** - * check if given file is a mbox file - * - * if $file is a resource its file pointer is moved after the first line - * - * @param resource|string $file stream resource of name of file - * @param bool $fileIsString file is string or resource - * @return bool file is mbox file - */ - protected function isMboxFile($file, $fileIsString = true) - { - if ($fileIsString) { - ErrorHandler::start(E_WARNING); - $file = fopen($file, 'r'); - ErrorHandler::stop(); - if (! $file) { - return false; - } - } else { - fseek($file, 0); - } - - $result = false; - - $line = fgets($file) ?: ''; - if (strpos($line, 'From ') === 0) { - $result = true; - } - - if ($fileIsString) { - ErrorHandler::start(E_WARNING); - fclose($file); - ErrorHandler::stop(); - } - - return $result; - } - - /** - * open given file as current mbox file - * - * @param string $filename filename of mbox file - * @throws Exception\RuntimeException - * @throws Exception\InvalidArgumentException - */ - protected function openMboxFile($filename) - { - if ($this->fh) { - $this->close(); - } - - if (is_dir($filename)) { - throw new Exception\InvalidArgumentException('file is not a valid mbox file'); - } - - ErrorHandler::start(); - $this->fh = fopen($filename, 'r'); - $error = ErrorHandler::stop(); - if (! $this->fh) { - throw new Exception\RuntimeException('cannot open mbox file', 0, $error); - } - $this->filename = $filename; - $this->filemtime = filemtime($this->filename); - - if (! $this->isMboxFile($this->fh, false)) { - ErrorHandler::start(E_WARNING); - fclose($this->fh); - $error = ErrorHandler::stop(); - throw new Exception\InvalidArgumentException('file is not a valid mbox format', 0, $error); - } - - $messagePos = ['start' => ftell($this->fh), 'separator' => 0, 'end' => 0]; - while (($line = fgets($this->fh)) !== false) { - if (strpos($line, 'From ') === 0) { - $messagePos['end'] = ftell($this->fh) - strlen($line) - 2; // + newline - if (! $messagePos['separator']) { - $messagePos['separator'] = $messagePos['end']; - } - $this->positions[] = $messagePos; - $messagePos = ['start' => ftell($this->fh), 'separator' => 0, 'end' => 0]; - } - if (! $messagePos['separator'] && ! trim($line)) { - $messagePos['separator'] = ftell($this->fh); - } - } - - $messagePos['end'] = ftell($this->fh); - if (! $messagePos['separator']) { - $messagePos['separator'] = $messagePos['end']; - } - $this->positions[] = $messagePos; - } - - /** - * Close resource for mail lib. If you need to control, when the resource - * is closed. Otherwise the destructor would call this. - * - */ - public function close() - { - if (is_resource($this->fh)) { - fclose($this->fh); - } - $this->positions = []; - } - - /** - * Waste some CPU cycles doing nothing. - * - * @return bool always return true - */ - public function noop() - { - return true; - } - - /** - * stub for not supported message deletion - * - * @param $id - * @throws Exception\RuntimeException - */ - public function removeMessage($id) - { - throw new Exception\RuntimeException('mbox is read-only'); - } - - /** - * get unique id for one or all messages - * - * Mbox does not support unique ids (yet) - it's always the same as the message number. - * That shouldn't be a problem, because we can't change mbox files. Therefor the message - * number is save enough. - * - * @param int|null $id message number - * @return array|string message number for given message or all messages as array - * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface - */ - public function getUniqueId($id = null) - { - if ($id) { - // check if id exists - $this->getPos($id); - return $id; - } - - $range = range(1, $this->countMessages()); - return array_combine($range, $range); - } - - /** - * get a message number from a unique id - * - * I.e. if you have a webmailer that supports deleting messages you should use unique ids - * as parameter and use this method to translate it to message number right before calling removeMessage() - * - * @param string $id unique id - * @return int message number - * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface - */ - public function getNumberByUniqueId($id) - { - // check if id exists - $this->getPos($id); - return $id; - } - - /** - * magic method for serialize() - * - * with this method you can cache the mbox class - * - * @return array name of variables - */ - public function __sleep() - { - return ['filename', 'positions', 'filemtime']; - } - - /** - * magic method for unserialize() - * - * with this method you can cache the mbox class - * for cache validation the mtime of the mbox file is used - * - * @throws Exception\RuntimeException - */ - public function __wakeup() - { - ErrorHandler::start(); - $filemtime = filemtime($this->filename); - ErrorHandler::stop(); - if ($this->filemtime != $filemtime) { - $this->close(); - $this->openMboxFile($this->filename); - } else { - ErrorHandler::start(); - $this->fh = fopen($this->filename, 'r'); - $error = ErrorHandler::stop(); - if (! $this->fh) { - throw new Exception\RuntimeException('cannot open mbox file', 0, $error); - } - } - } -} diff --git a/lib/laminas/laminas-mail/src/Storage/Message.php b/lib/laminas/laminas-mail/src/Storage/Message.php deleted file mode 100644 index d2307aed3..000000000 --- a/lib/laminas/laminas-mail/src/Storage/Message.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage; - -use Laminas\Stdlib\ErrorHandler; - -class Message extends Part implements Message\MessageInterface -{ - /** - * flags for this message - * @var array - */ - protected $flags = []; - - /** - * Public constructor - * - * In addition to the parameters of Part::__construct() this constructor supports: - * - file filename or file handle of a file with raw message content - * - flags array with flags for message, keys are ignored, use constants defined in \Laminas\Mail\Storage - * - * @param array $params - * @throws Exception\RuntimeException - */ - public function __construct(array $params) - { - if (isset($params['file'])) { - if (! is_resource($params['file'])) { - ErrorHandler::start(); - $params['raw'] = file_get_contents($params['file']); - $error = ErrorHandler::stop(); - if ($params['raw'] === false) { - throw new Exception\RuntimeException('could not open file', 0, $error); - } - } else { - $params['raw'] = stream_get_contents($params['file']); - } - - $params['raw'] = ltrim($params['raw']); - } - - if (! empty($params['flags'])) { - // set key and value to the same value for easy lookup - $this->flags = array_combine($params['flags'], $params['flags']); - } - - parent::__construct($params); - } - - /** - * return toplines as found after headers - * - * @return string toplines - */ - public function getTopLines() - { - return $this->topLines; - } - - /** - * check if flag is set - * - * @param mixed $flag a flag name, use constants defined in \Laminas\Mail\Storage - * @return bool true if set, otherwise false - */ - public function hasFlag($flag) - { - return isset($this->flags[$flag]); - } - - /** - * get all set flags - * - * @return array array with flags, key and value are the same for easy lookup - */ - public function getFlags() - { - return $this->flags; - } -} diff --git a/lib/laminas/laminas-mail/src/Storage/Message/File.php b/lib/laminas/laminas-mail/src/Storage/Message/File.php deleted file mode 100644 index b5ce38990..000000000 --- a/lib/laminas/laminas-mail/src/Storage/Message/File.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage\Message; - -use Laminas\Mail\Storage\Part; - -class File extends Part\File implements MessageInterface -{ - /** - * flags for this message - * @var array - */ - protected $flags = []; - - /** - * Public constructor - * - * In addition to the parameters of Laminas\Mail\Storage\Part::__construct() this constructor supports: - * - flags array with flags for message, keys are ignored, use constants defined in Laminas\Mail\Storage - * - * @param array $params - * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface - */ - public function __construct(array $params) - { - if (! empty($params['flags'])) { - // set key and value to the same value for easy lookup - $this->flags = array_combine($params['flags'], $params['flags']); - } - - parent::__construct($params); - } - - /** - * return toplines as found after headers - * - * @return string toplines - */ - public function getTopLines() - { - return $this->topLines; - } - - /** - * check if flag is set - * - * @param mixed $flag a flag name, use constants defined in \Laminas\Mail\Storage - * @return bool true if set, otherwise false - */ - public function hasFlag($flag) - { - return isset($this->flags[$flag]); - } - - /** - * get all set flags - * - * @return array array with flags, key and value are the same for easy lookup - */ - public function getFlags() - { - return $this->flags; - } -} diff --git a/lib/laminas/laminas-mail/src/Storage/Message/MessageInterface.php b/lib/laminas/laminas-mail/src/Storage/Message/MessageInterface.php deleted file mode 100644 index 15d82273c..000000000 --- a/lib/laminas/laminas-mail/src/Storage/Message/MessageInterface.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage\Message; - -interface MessageInterface -{ - /** - * return toplines as found after headers - * - * @return string toplines - */ - public function getTopLines(); - - /** - * check if flag is set - * - * @param mixed $flag a flag name, use constants defined in Laminas\Mail\Storage - * @return bool true if set, otherwise false - */ - public function hasFlag($flag); - - /** - * get all set flags - * - * @return array array with flags, key and value are the same for easy lookup - */ - public function getFlags(); -} diff --git a/lib/laminas/laminas-mail/src/Storage/ParamsNormalizer.php b/lib/laminas/laminas-mail/src/Storage/ParamsNormalizer.php deleted file mode 100644 index 91e5a548e..000000000 --- a/lib/laminas/laminas-mail/src/Storage/ParamsNormalizer.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage; - -use Traversable; -use Webmozart\Assert\Assert; - -/** - * @internal - */ -final class ParamsNormalizer -{ - /** - * @param mixed $params - * @return array<string, mixed> - */ - public static function normalizeParams($params): array - { - if ($params instanceof Traversable) { - $params = iterator_to_array($params); - } - - if (is_object($params)) { - $params = get_object_vars($params); - } - - if (! is_array($params)) { - throw new Exception\InvalidArgumentException(sprintf( - 'Invalid $params provided; expected array|Traversable|object, received %s', - gettype($params) - )); - } - - Assert::isMap($params, 'Expected $params to have only string keys'); - return $params; - } -} diff --git a/lib/laminas/laminas-mail/src/Storage/Part.php b/lib/laminas/laminas-mail/src/Storage/Part.php deleted file mode 100644 index c1f2f4681..000000000 --- a/lib/laminas/laminas-mail/src/Storage/Part.php +++ /dev/null @@ -1,474 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage; - -use Laminas\Mail\Header\HeaderInterface; -use Laminas\Mail\Headers; -use Laminas\Mime; -use RecursiveIterator; -use ReturnTypeWillChange; - -class Part implements RecursiveIterator, Part\PartInterface -{ - /** - * Headers of the part - * @var Headers|null - */ - protected $headers; - - /** - * raw part body - * @var null|string - */ - protected $content; - - /** - * toplines as fetched with headers - * @var string - */ - protected $topLines = ''; - - /** - * parts of multipart message - * @var array - */ - protected $parts = []; - - /** - * count of parts of a multipart message - * @var null|int - */ - protected $countParts; - - /** - * current position of iterator - * @var int - */ - protected $iterationPos = 1; - - /** - * mail handler, if late fetch is active - * @var null|AbstractStorage - */ - protected $mail; - - /** - * message number for mail handler - * @var int - */ - protected $messageNum = 0; - - /** - * Public constructor - * - * Part supports different sources for content. The possible params are: - * - handler an instance of AbstractStorage for late fetch - * - id number of message for handler - * - raw raw content with header and body as string - * - headers headers as array (name => value) or string, if a content part is found it's used as toplines - * - noToplines ignore content found after headers in param 'headers' - * - content content as string - * - strict strictly parse raw content - * - * @param array $params full message with or without headers - * @throws Exception\InvalidArgumentException - */ - public function __construct(array $params) - { - if (isset($params['handler'])) { - if (! $params['handler'] instanceof AbstractStorage) { - throw new Exception\InvalidArgumentException('handler is not a valid mail handler'); - } - if (! isset($params['id'])) { - throw new Exception\InvalidArgumentException('need a message id with a handler'); - } - - $this->mail = $params['handler']; - $this->messageNum = $params['id']; - } - - $params['strict'] = $params['strict'] ?? false; - - if (isset($params['raw'])) { - Mime\Decode::splitMessage( - $params['raw'], - $this->headers, - $this->content, - Mime\Mime::LINEEND, - $params['strict'] - ); - } elseif (isset($params['headers'])) { - if (is_array($params['headers'])) { - $this->headers = new Headers(); - $this->headers->addHeaders($params['headers']); - } else { - if (empty($params['noToplines'])) { - Mime\Decode::splitMessage($params['headers'], $this->headers, $this->topLines); - } else { - $this->headers = Headers::fromString($params['headers']); - } - } - - if (isset($params['content'])) { - $this->content = $params['content']; - } - } - } - - /** - * Check if part is a multipart message - * - * @return bool if part is multipart - */ - public function isMultipart() - { - try { - return stripos($this->contentType, 'multipart/') === 0; - } catch (Exception\ExceptionInterface $e) { - return false; - } - } - - /** - * Body of part - * - * If part is multipart the raw content of this part with all sub parts is returned - * - * @throws Exception\RuntimeException - * @return string body - */ - public function getContent() - { - if ($this->content !== null) { - return $this->content; - } - - if ($this->mail) { - return $this->mail->getRawContent($this->messageNum); - } - - throw new Exception\RuntimeException('no content'); - } - - /** - * Return size of part - * - * Quite simple implemented currently (not decoding). Handle with care. - * - * @return int size - */ - public function getSize() - { - return strlen($this->getContent()); - } - - /** - * Cache content and split in parts if multipart - * - * @throws Exception\RuntimeException - * @return null - */ - protected function cacheContent() - { - // caching content if we can't fetch parts - if ($this->content === null && $this->mail) { - $this->content = $this->mail->getRawContent($this->messageNum); - } - - if (! $this->isMultipart()) { - return; - } - - // split content in parts - $boundary = $this->getHeaderField('content-type', 'boundary'); - if (! $boundary) { - throw new Exception\RuntimeException('no boundary found in content type to split message'); - } - $parts = Mime\Decode::splitMessageStruct($this->content, $boundary); - if ($parts === null) { - return; - } - $counter = 1; - foreach ($parts as $part) { - $this->parts[$counter++] = new static(['headers' => $part['header'], 'content' => $part['body']]); - } - } - - /** - * Get part of multipart message - * - * @param int $num number of part starting with 1 for first part - * @throws Exception\RuntimeException - * @return Part wanted part - */ - public function getPart($num) - { - if (isset($this->parts[$num])) { - return $this->parts[$num]; - } - - if (! $this->mail && $this->content === null) { - throw new Exception\RuntimeException('part not found'); - } - - if ($this->mail && $this->mail->hasFetchPart) { - // TODO: fetch part - // return - } - - $this->cacheContent(); - - if (! isset($this->parts[$num])) { - throw new Exception\RuntimeException('part not found'); - } - - return $this->parts[$num]; - } - - /** - * Count parts of a multipart part - * - * @return int number of sub-parts - */ - public function countParts() - { - if ($this->countParts) { - return $this->countParts; - } - - $this->countParts = count($this->parts); - if ($this->countParts) { - return $this->countParts; - } - - if ($this->mail && $this->mail->hasFetchPart) { - // TODO: fetch part - // return - } - - $this->cacheContent(); - - $this->countParts = count($this->parts); - return $this->countParts; - } - - /** - * Access headers collection - * - * Lazy-loads if not already attached. - * - * @return Headers - * @throws Exception\RuntimeException - */ - public function getHeaders() - { - if (null === $this->headers) { - if ($this->mail) { - $part = $this->mail->getRawHeader($this->messageNum); - $this->headers = Headers::fromString($part); - } else { - $this->headers = new Headers(); - } - } - if (! $this->headers instanceof Headers) { - throw new Exception\RuntimeException( - '$this->headers must be an instance of Headers' - ); - } - - return $this->headers; - } - - /** - * Get a header in specified format - * - * Internally headers that occur more than once are saved as array, all other as string. If $format - * is set to string implode is used to concat the values (with Mime::LINEEND as delim). - * - * @param string $name name of header, matches case-insensitive, but camel-case is replaced with dashes - * @param string $format change type of return value to 'string' or 'array' - * @throws Exception\InvalidArgumentException - * @return string|array|HeaderInterface|\ArrayIterator value of header in wanted or internal format - */ - public function getHeader($name, $format = null) - { - $header = $this->getHeaders()->get($name); - if ($header === false) { - $lowerName = strtolower(preg_replace('%([a-z])([A-Z])%', '\1-\2', $name)); - $header = $this->getHeaders()->get($lowerName); - if ($header === false) { - throw new Exception\InvalidArgumentException( - "Header with Name $name or $lowerName not found" - ); - } - } - - switch ($format) { - case 'string': - if ($header instanceof HeaderInterface) { - $return = $header->getFieldValue(HeaderInterface::FORMAT_RAW); - } else { - $return = trim(implode( - Mime\Mime::LINEEND, - array_map(static function ($header): string { - return $header->getFieldValue(HeaderInterface::FORMAT_RAW); - }, iterator_to_array($header)) - ), Mime\Mime::LINEEND); - } - break; - case 'array': - if ($header instanceof HeaderInterface) { - $return = [$header->getFieldValue()]; - } else { - $return = []; - foreach ($header as $h) { - $return[] = $h->getFieldValue(HeaderInterface::FORMAT_RAW); - } - } - break; - default: - $return = $header; - } - - return $return; - } - - /** - * Get a specific field from a header like content type or all fields as array - * - * If the header occurs more than once, only the value from the first header - * is returned. - * - * Throws an Exception if the requested header does not exist. If - * the specific header field does not exist, returns null. - * - * @param string $name name of header, like in getHeader() - * @param string $wantedPart the wanted part, default is first, if null an array with all parts is returned - * @param string $firstName key name for the first part - * @return string|array wanted part or all parts as array($firstName => firstPart, partname => value) - * @throws \Laminas\Mime\Exception\RuntimeException - */ - public function getHeaderField($name, $wantedPart = '0', $firstName = '0') - { - return Mime\Decode::splitHeaderField(current($this->getHeader($name, 'array')), $wantedPart, $firstName); - } - - /** - * Getter for mail headers - name is matched in lowercase - * - * This getter is short for Part::getHeader($name, 'string') - * - * @see Part::getHeader() - * - * @param string $name header name - * @return string value of header - * @throws Exception\ExceptionInterface - */ - public function __get($name) - { - return $this->getHeader($name, 'string'); - } - - /** - * Isset magic method proxy to hasHeader - * - * This method is short syntax for Part::hasHeader($name); - * - * @see Part::hasHeader - * - * @param string - * @return bool - */ - public function __isset($name) - { - return $this->getHeaders()->has($name); - } - - /** - * magic method to get content of part - * - * @return string content - */ - public function __toString() - { - return $this->getContent(); - } - - /** - * implements RecursiveIterator::hasChildren() - * - * @return bool current element has children/is multipart - */ - #[ReturnTypeWillChange] - public function hasChildren() - { - $current = $this->current(); - return $current && $current instanceof self && $current->isMultipart(); - } - - /** - * implements RecursiveIterator::getChildren() - * - * @return Part same as self::current() - */ - #[ReturnTypeWillChange] - public function getChildren() - { - return $this->current(); - } - - /** - * implements Iterator::valid() - * - * @return bool check if there's a current element - */ - #[ReturnTypeWillChange] - public function valid() - { - if ($this->countParts === null) { - $this->countParts(); - } - return $this->iterationPos && $this->iterationPos <= $this->countParts; - } - - /** - * implements Iterator::next() - */ - #[ReturnTypeWillChange] - public function next() - { - ++$this->iterationPos; - } - - /** - * implements Iterator::key() - * - * @return string key/number of current part - */ - #[ReturnTypeWillChange] - public function key() - { - return $this->iterationPos; - } - - /** - * implements Iterator::current() - * - * @return Part current part - */ - #[ReturnTypeWillChange] - public function current() - { - return $this->getPart($this->iterationPos); - } - - /** - * implements Iterator::rewind() - */ - #[ReturnTypeWillChange] - public function rewind() - { - $this->countParts(); - $this->iterationPos = 1; - } -} diff --git a/lib/laminas/laminas-mail/src/Storage/Part/Exception/ExceptionInterface.php b/lib/laminas/laminas-mail/src/Storage/Part/Exception/ExceptionInterface.php deleted file mode 100644 index abebe1c35..000000000 --- a/lib/laminas/laminas-mail/src/Storage/Part/Exception/ExceptionInterface.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage\Part\Exception; - -use Laminas\Mail\Storage\Exception\ExceptionInterface as StorageException; - -interface ExceptionInterface extends StorageException -{ -} diff --git a/lib/laminas/laminas-mail/src/Storage/Part/Exception/InvalidArgumentException.php b/lib/laminas/laminas-mail/src/Storage/Part/Exception/InvalidArgumentException.php deleted file mode 100644 index 2fda253cf..000000000 --- a/lib/laminas/laminas-mail/src/Storage/Part/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage\Part\Exception; - -use Laminas\Mail\Storage\Exception; - -/** - * Exception for Laminas\Mail component. - */ -class InvalidArgumentException extends Exception\InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-mail/src/Storage/Part/Exception/RuntimeException.php b/lib/laminas/laminas-mail/src/Storage/Part/Exception/RuntimeException.php deleted file mode 100644 index 127cf9be5..000000000 --- a/lib/laminas/laminas-mail/src/Storage/Part/Exception/RuntimeException.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage\Part\Exception; - -use Laminas\Mail\Storage\Exception; - -/** - * Exception for Laminas\Mail component. - */ -class RuntimeException extends Exception\RuntimeException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-mail/src/Storage/Part/File.php b/lib/laminas/laminas-mail/src/Storage/Part/File.php deleted file mode 100644 index befdb576d..000000000 --- a/lib/laminas/laminas-mail/src/Storage/Part/File.php +++ /dev/null @@ -1,154 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage\Part; - -use Laminas\Mail\Headers; -use Laminas\Mail\Storage\Part; - -class File extends Part -{ - protected $contentPos = []; - protected $partPos = []; - protected $fh; - - /** - * Public constructor - * - * This handler supports the following params: - * - file filename or open file handler with message content (required) - * - startPos start position of message or part in file (default: current position) - * - endPos end position of message or part in file (default: end of file) - * - EOL end of Line for messages - * - * @param array $params full message with or without headers - * @throws Exception\RuntimeException - * @throws Exception\InvalidArgumentException - */ - public function __construct(array $params) - { - if (empty($params['file'])) { - throw new Exception\InvalidArgumentException('no file given in params'); - } - - if (! is_resource($params['file'])) { - $this->fh = fopen($params['file'], 'r'); - } else { - $this->fh = $params['file']; - } - if (! $this->fh) { - throw new Exception\RuntimeException('could not open file'); - } - if (isset($params['startPos'])) { - fseek($this->fh, $params['startPos']); - } - $header = ''; - $endPos = $params['endPos'] ?? null; - while (($endPos === null || ftell($this->fh) < $endPos) && trim($line = fgets($this->fh))) { - $header .= $line; - } - - if (isset($params['EOL'])) { - $this->headers = Headers::fromString($header, $params['EOL']); - } else { - $this->headers = Headers::fromString($header); - } - - $this->contentPos[0] = ftell($this->fh); - if ($endPos !== null) { - $this->contentPos[1] = $endPos; - } else { - fseek($this->fh, 0, SEEK_END); - $this->contentPos[1] = ftell($this->fh); - } - if (! $this->isMultipart()) { - return; - } - - $boundary = $this->getHeaderField('content-type', 'boundary'); - if (! $boundary) { - throw new Exception\RuntimeException('no boundary found in content type to split message'); - } - - $part = []; - $pos = $this->contentPos[0]; - fseek($this->fh, $pos); - while (! feof($this->fh) && ($endPos === null || $pos < $endPos)) { - $line = fgets($this->fh); - if ($line === false) { - if (feof($this->fh)) { - break; - } - throw new Exception\RuntimeException('error reading file'); - } - - $lastPos = $pos; - $pos = ftell($this->fh); - $line = trim($line); - - if ($line == '--' . $boundary) { - if ($part) { - // not first part - $part[1] = $lastPos; - $this->partPos[] = $part; - } - $part = [$pos]; - } elseif ($line == '--' . $boundary . '--') { - $part[1] = $lastPos; - $this->partPos[] = $part; - break; - } - } - $this->countParts = count($this->partPos); - } - - /** - * Body of part - * - * If part is multipart the raw content of this part with all sub parts is returned - * - * @param resource $stream Optional - * @return string body - */ - public function getContent($stream = null) - { - fseek($this->fh, $this->contentPos[0]); - if ($stream !== null) { - return stream_copy_to_stream($this->fh, $stream, $this->contentPos[1] - $this->contentPos[0]); - } - $length = $this->contentPos[1] - $this->contentPos[0]; - return $length < 1 ? '' : fread($this->fh, $length); - } - - /** - * Return size of part - * - * Quite simple implemented currently (not decoding). Handle with care. - * - * @return int size - */ - public function getSize() - { - return $this->contentPos[1] - $this->contentPos[0]; - } - - /** - * Get part of multipart message - * - * @param int $num number of part starting with 1 for first part - * @throws Exception\RuntimeException - * @return Part wanted part - */ - public function getPart($num) - { - --$num; - if (! isset($this->partPos[$num])) { - throw new Exception\RuntimeException('part not found'); - } - - return new static([ - 'file' => $this->fh, - 'startPos' => $this->partPos[$num][0], - 'endPos' => $this->partPos[$num][1], - ]); - } -} diff --git a/lib/laminas/laminas-mail/src/Storage/Part/PartInterface.php b/lib/laminas/laminas-mail/src/Storage/Part/PartInterface.php deleted file mode 100644 index 6161112bb..000000000 --- a/lib/laminas/laminas-mail/src/Storage/Part/PartInterface.php +++ /dev/null @@ -1,117 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage\Part; - -use ArrayIterator; -use Laminas\Mail\Header\HeaderInterface; -use Laminas\Mail\Headers; -use RecursiveIterator; - -interface PartInterface extends RecursiveIterator -{ - /** - * Check if part is a multipart message - * - * @return bool if part is multipart - */ - public function isMultipart(); - - /** - * Body of part - * - * If part is multipart the raw content of this part with all sub parts is - * returned. - * - * @return string body - * @throws Exception\ExceptionInterface - */ - public function getContent(); - - /** - * Return size of part - * - * @return int size - */ - public function getSize(); - - /** - * Get part of multipart message - * - * @param int $num number of part starting with 1 for first part - * @return PartInterface wanted part - * @throws Exception\ExceptionInterface - */ - public function getPart($num); - - /** - * Count parts of a multipart part - * - * @return int number of sub-parts - */ - public function countParts(); - - /** - * Get all headers - * - * The returned headers are as saved internally. All names are lowercased. - * The value is a string or an array if a header with the same name occurs - * more than once. - * - * @return Headers - */ - public function getHeaders(); - - /** - * Get a header in specified format - * - * Internally headers that occur more than once are saved as array, all - * other as string. If $format is set to string implode is used to concat - * the values (with Laminas\Mime\Mime::LINEEND as delim). - * - * @param string $name name of header, matches case-insensitive, but - * camel-case is replaced with dashes - * @param string $format change type of return value to 'string' or 'array' - * @return string|array|HeaderInterface|ArrayIterator value of header in - * wanted or internal format - * @throws Exception\ExceptionInterface - */ - public function getHeader($name, $format = null); - - /** - * Get a specific field from a header like content type or all fields as array - * - * If the header occurs more than once, only the value from the first - * header is returned. - * - * Throws an exception if the requested header does not exist. If the - * specific header field does not exist, returns null. - * - * @param string $name name of header, like in getHeader() - * @param string $wantedPart the wanted part, default is first, if null an - * array with all parts is returned - * @param string $firstName key name for the first part - * @return string|array wanted part or all parts as - * [$firstName => firstPart, partname => value] - * @throws Exception\ExceptionInterface - */ - public function getHeaderField($name, $wantedPart = '0', $firstName = '0'); - - /** - * Getter for mail headers - name is matched in lowercase - * - * This getter is short for PartInterface::getHeader($name, 'string') - * - * @see PartInterface::getHeader() - * @param string $name header name - * @return string value of header - * @throws Exception\ExceptionInterface - */ - public function __get($name); - - /** - * magic method to get content of part - * - * @return string content - */ - public function __toString(); -} diff --git a/lib/laminas/laminas-mail/src/Storage/Pop3.php b/lib/laminas/laminas-mail/src/Storage/Pop3.php deleted file mode 100644 index def4f97a9..000000000 --- a/lib/laminas/laminas-mail/src/Storage/Pop3.php +++ /dev/null @@ -1,288 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage; - -use Laminas\Mail\Exception as MailException; -use Laminas\Mail\Protocol; -use Laminas\Mime; - -class Pop3 extends AbstractStorage -{ - /** - * protocol handler - * @var null|\Laminas\Mail\Protocol\Pop3 - */ - protected $protocol; - - /** - * Count messages all messages in current box - * - * @return int number of messages - * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface - * @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface - */ - public function countMessages() - { - $count = 0; // "Declare" variable before first usage. - $octets = 0; // "Declare" variable since it's passed by reference - $this->protocol->status($count, $octets); - return (int) $count; - } - - /** - * get a list of messages with number and size - * - * @param int $id number of message - * @return int|array size of given message of list with all messages as array(num => size) - * @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface - */ - public function getSize($id = 0) - { - $id = $id ? $id : null; - return $this->protocol->getList($id); - } - - /** - * Fetch a message - * - * @param int $id number of message - * @return \Laminas\Mail\Storage\Message - * @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface - */ - public function getMessage($id) - { - $bodyLines = 0; - $message = $this->protocol->top($id, $bodyLines, true); - - return new $this->messageClass([ - 'handler' => $this, - 'id' => $id, - 'headers' => $message, - 'noToplines' => $bodyLines < 1, - ]); - } - - /* - * Get raw header of message or part - * - * @param int $id number of message - * @param null|array|string $part path to part or null for message header - * @param int $topLines include this many lines with header (after an empty line) - * @return string raw header - * @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface - * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface - */ - public function getRawHeader($id, $part = null, $topLines = 0) - { - if ($part !== null) { - // TODO: implement - throw new Exception\RuntimeException('not implemented'); - } - - return $this->protocol->top($id, 0, true); - } - - /* - * Get raw content of message or part - * - * @param int $id number of message - * @param null|array|string $part path to part or null for message content - * @return string raw content - * @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface - * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface - */ - public function getRawContent($id, $part = null) - { - if ($part !== null) { - // TODO: implement - throw new Exception\RuntimeException('not implemented'); - } - - $content = $this->protocol->retrieve($id); - // TODO: find a way to avoid decoding the headers - $headers = null; // "Declare" variable since it's passed by reference - $body = null; // "Declare" variable before first usage. - Mime\Decode::splitMessage($content, $headers, $body); - return $body; - } - - /** - * create instance with parameters - * Supported parameters are - * - host hostname or ip address of POP3 server - * - user username - * - password password for user 'username' [optional, default = ''] - * - port port for POP3 server [optional, default = 110] - * - ssl 'SSL' or 'TLS' for secure sockets - * - * @param array|object|Protocol\Pop3 $params mail reader specific - * parameters or configured Pop3 protocol object - * @throws \Laminas\Mail\Storage\Exception\InvalidArgumentException - * @throws \Laminas\Mail\Protocol\Exception\RuntimeException - */ - public function __construct($params) - { - $this->has['fetchPart'] = false; - $this->has['top'] = null; - $this->has['uniqueid'] = null; - - if ($params instanceof Protocol\Pop3) { - $this->protocol = $params; - return; - } - - $params = ParamsNormalizer::normalizeParams($params); - - if (! isset($params['user'])) { - throw new Exception\InvalidArgumentException('need at least user in params'); - } - - $host = $params['host'] ?? 'localhost'; - $password = $params['password'] ?? ''; - $port = $params['port'] ?? null; - $ssl = $params['ssl'] ?? false; - - if (null !== $port) { - $port = (int) $port; - } - - if (! is_string($ssl)) { - $ssl = (bool) $ssl; - } - - $this->protocol = new Protocol\Pop3(); - - if (array_key_exists('novalidatecert', $params)) { - $this->protocol->setNoValidateCert((bool) $params['novalidatecert']); - } - - $this->protocol->connect((string) $host, $port, $ssl); - $this->protocol->login((string) $params['user'], (string) $password); - } - - /** - * Close resource for mail lib. If you need to control, when the resource - * is closed. Otherwise the destructor would call this. - */ - public function close() - { - $this->protocol->logout(); - } - - /** - * Keep the server busy. - * - * @throws \Laminas\Mail\Protocol\Exception\RuntimeException - */ - public function noop() - { - $this->protocol->noop(); - } - - /** - * Remove a message from server. If you're doing that from a web environment - * you should be careful and use a uniqueid as parameter if possible to - * identify the message. - * - * @param int $id number of message - * @throws \Laminas\Mail\Protocol\Exception\RuntimeException - */ - public function removeMessage($id) - { - $this->protocol->delete($id); - } - - /** - * get unique id for one or all messages - * - * if storage does not support unique ids it's the same as the message number - * - * @param int|null $id message number - * @return array|string message number for given message or all messages as array - * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface - */ - public function getUniqueId($id = null) - { - if (! $this->hasUniqueid) { - if ($id) { - return $id; - } - $count = $this->countMessages(); - if ($count < 1) { - return []; - } - $range = range(1, $count); - return array_combine($range, $range); - } - - return $this->protocol->uniqueid($id); - } - - /** - * get a message number from a unique id - * - * I.e. if you have a webmailer that supports deleting messages you should use unique ids - * as parameter and use this method to translate it to message number right before calling removeMessage() - * - * @param string $id unique id - * @throws Exception\InvalidArgumentException - * @return int message number - */ - public function getNumberByUniqueId($id) - { - if (! $this->hasUniqueid) { - return $id; - } - - $ids = $this->getUniqueId(); - foreach ($ids as $k => $v) { - if ($v == $id) { - return $k; - } - } - - throw new Exception\InvalidArgumentException('unique id not found'); - } - - /** - * Special handling for hasTop and hasUniqueid. The headers of the first message is - * retrieved if Top wasn't needed/tried yet. - * - * @see AbstractStorage::__get() - * @param string $var - * @return string - */ - public function __get($var) - { - $result = parent::__get($var); - if ($result !== null) { - return $result; - } - - if (strtolower($var) == 'hastop') { - if ($this->protocol->hasTop === null) { - // need to make a real call, because not all server are honest in their capas - try { - $this->protocol->top(1, 0, false); - } catch (MailException\ExceptionInterface $e) { - // ignoring error - } - } - $this->has['top'] = $this->protocol->hasTop; - return $this->protocol->hasTop; - } - - if (strtolower($var) == 'hasuniqueid') { - $id = null; - try { - $id = $this->protocol->uniqueid(1); - } catch (MailException\ExceptionInterface $e) { - // ignoring error - } - $this->has['uniqueid'] = (bool) $id; - return $this->has['uniqueid']; - } - - return $result; - } -} diff --git a/lib/laminas/laminas-mail/src/Storage/Writable/Maildir.php b/lib/laminas/laminas-mail/src/Storage/Writable/Maildir.php deleted file mode 100644 index a8245b510..000000000 --- a/lib/laminas/laminas-mail/src/Storage/Writable/Maildir.php +++ /dev/null @@ -1,957 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage\Writable; - -use Laminas\Mail\Exception as MailException; -use Laminas\Mail\Storage; -use Laminas\Mail\Storage\Exception as StorageException; -use Laminas\Mail\Storage\Folder; -use Laminas\Stdlib\ErrorHandler; -use RecursiveIteratorIterator; - -class Maildir extends Folder\Maildir implements WritableInterface -{ - // TODO: init maildir (+ constructor option create if not found) - - /** - * use quota and size of quota if given - * - * @var bool|int - */ - protected $quota; - - /** - * create a new maildir - * - * If the given dir is already a valid maildir this will not fail. - * - * @param string $dir directory for the new maildir (may already exist) - * @throws \Laminas\Mail\Storage\Exception\RuntimeException - * @throws \Laminas\Mail\Storage\Exception\InvalidArgumentException - */ - public static function initMaildir($dir) - { - if (file_exists($dir)) { - if (! is_dir($dir)) { - throw new StorageException\InvalidArgumentException('maildir must be a directory if already exists'); - } - } else { - ErrorHandler::start(); - $test = mkdir($dir); - $error = ErrorHandler::stop(); - if (! $test) { - $dir = dirname($dir); - if (! file_exists($dir)) { - throw new StorageException\InvalidArgumentException("parent $dir not found", 0, $error); - } elseif (! is_dir($dir)) { - throw new StorageException\InvalidArgumentException("parent $dir not a directory", 0, $error); - } - - throw new StorageException\RuntimeException('cannot create maildir', 0, $error); - } - } - - foreach (['cur', 'tmp', 'new'] as $subdir) { - ErrorHandler::start(); - $test = mkdir($dir . DIRECTORY_SEPARATOR . $subdir); - $error = ErrorHandler::stop(); - if (! $test) { - // ignore if dir exists (i.e. was already valid maildir or two processes try to create one) - if (! file_exists($dir . DIRECTORY_SEPARATOR . $subdir)) { - throw new StorageException\RuntimeException('could not create subdir ' . $subdir, 0, $error); - } - } - } - } - - /** - * Create instance with parameters - * Additional parameters are (see parent for more): - * - create if true a new maildir is create if none exists - * - * @param $params array mail reader specific parameters - * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface - */ - public function __construct($params) - { - if (is_array($params)) { - $params = (object) $params; - } - - if (! empty($params->create) - && isset($params->dirname) - && ! file_exists($params->dirname . DIRECTORY_SEPARATOR . 'cur') - ) { - self::initMaildir($params->dirname); - } - - parent::__construct($params); - } - - /** - * create a new folder - * - * This method also creates parent folders if necessary. Some mail storages may restrict, which folder - * may be used as parent or which chars may be used in the folder name - * - * @param string $name global name of folder, local name if $parentFolder is set - * @param string|\Laminas\Mail\Storage\Folder $parentFolder parent of new folder, else root folder is parent - * @throws \Laminas\Mail\Storage\Exception\RuntimeException - * @return string only used internally (new created maildir) - */ - public function createFolder($name, $parentFolder = null) - { - if ($parentFolder instanceof Folder) { - $folder = $parentFolder->getGlobalName() . $this->delim . $name; - } elseif ($parentFolder !== null) { - $folder = rtrim($parentFolder, $this->delim) . $this->delim . $name; - } else { - $folder = $name; - } - - $folder = trim($folder, $this->delim); - - // first we check if we try to create a folder that does exist - $exists = null; - try { - $exists = $this->getFolders($folder); - } catch (MailException\ExceptionInterface $e) { - // ok - } - if ($exists) { - throw new StorageException\RuntimeException('folder already exists'); - } - - if (strpos($folder, $this->delim . $this->delim) !== false) { - throw new StorageException\RuntimeException('invalid name - folder parts may not be empty'); - } - - if (strpos($folder, 'INBOX' . $this->delim) === 0) { - $folder = substr($folder, 6); - } - - $fulldir = $this->rootdir . '.' . $folder; - - // check if we got tricked and would create a dir outside of the rootdir or not as direct child - if (strpos($folder, DIRECTORY_SEPARATOR) !== false || strpos($folder, '/') !== false - || dirname($fulldir) . DIRECTORY_SEPARATOR != $this->rootdir - ) { - throw new StorageException\RuntimeException('invalid name - no directory separator allowed in folder name'); - } - - // has a parent folder? - $parent = null; - if (strpos($folder, $this->delim)) { - // let's see if the parent folder exists - $parent = substr($folder, 0, strrpos($folder, $this->delim)); - try { - $this->getFolders($parent); - } catch (MailException\ExceptionInterface $e) { - // does not - create parent folder - $this->createFolder($parent); - } - } - - ErrorHandler::start(); - if (! mkdir($fulldir) || ! mkdir($fulldir . DIRECTORY_SEPARATOR . 'cur')) { - $error = ErrorHandler::stop(); - throw new StorageException\RuntimeException( - 'error while creating new folder, may be created incompletely', - 0, - $error - ); - } - ErrorHandler::stop(); - - mkdir($fulldir . DIRECTORY_SEPARATOR . 'new'); - mkdir($fulldir . DIRECTORY_SEPARATOR . 'tmp'); - - $localName = $parent ? substr($folder, strlen($parent) + 1) : $folder; - $this->getFolders($parent)->$localName = new Folder($localName, $folder, true); - - return $fulldir; - } - - /** - * remove a folder - * - * @param string|Folder $name name or instance of folder - * @throws \Laminas\Mail\Storage\Exception\RuntimeException - */ - public function removeFolder($name) - { - // TODO: This could fail in the middle of the task, which is not optimal. - // But there is no defined standard way to mark a folder as removed and there is no atomar fs-op - // to remove a directory. Also moving the folder to a/the trash folder is not possible, as - // all parent folders must be created. What we could do is add a dash to the front of the - // directory name and it should be ignored as long as other processes obey the standard. - - if ($name instanceof Folder) { - $name = $name->getGlobalName(); - } - - $name = trim($name, $this->delim); - if (strpos($name, 'INBOX' . $this->delim) === 0) { - $name = substr($name, 6); - } - - // check if folder exists and has no children - if (! $this->getFolders($name)->isLeaf()) { - throw new StorageException\RuntimeException('delete children first'); - } - - if ($name == 'INBOX' || $name == DIRECTORY_SEPARATOR || $name == '/') { - throw new StorageException\RuntimeException('wont delete INBOX'); - } - - if ($name == $this->getCurrentFolder()) { - throw new StorageException\RuntimeException('wont delete selected folder'); - } - - foreach (['tmp', 'new', 'cur', '.'] as $subdir) { - $dir = $this->rootdir . '.' . $name . DIRECTORY_SEPARATOR . $subdir; - if (! file_exists($dir)) { - continue; - } - $dh = opendir($dir); - if (! $dh) { - throw new StorageException\RuntimeException("error opening $subdir"); - } - while (($entry = readdir($dh)) !== false) { - if ($entry == '.' || $entry == '..') { - continue; - } - if (! unlink($dir . DIRECTORY_SEPARATOR . $entry)) { - throw new StorageException\RuntimeException("error cleaning $subdir"); - } - } - closedir($dh); - if ($subdir !== '.') { - if (! rmdir($dir)) { - throw new StorageException\RuntimeException("error removing $subdir"); - } - } - } - - if (! rmdir($this->rootdir . '.' . $name)) { - // at least we should try to make it a valid maildir again - mkdir($this->rootdir . '.' . $name . DIRECTORY_SEPARATOR . 'cur'); - throw new StorageException\RuntimeException("error removing maindir"); - } - - $parent = strpos($name, $this->delim) ? substr($name, 0, strrpos($name, $this->delim)) : null; - $localName = $parent ? substr($name, strlen($parent) + 1) : $name; - unset($this->getFolders($parent)->$localName); - } - - /** - * rename and/or move folder - * - * The new name has the same restrictions as in createFolder() - * - * @param string|\Laminas\Mail\Storage\Folder $oldName name or instance of folder - * @param string $newName new global name of folder - * @throws \Laminas\Mail\Storage\Exception\RuntimeException - */ - public function renameFolder($oldName, $newName) - { - // TODO: This is also not atomar and has similar problems as removeFolder() - - if ($oldName instanceof Folder) { - $oldName = $oldName->getGlobalName(); - } - - $oldName = trim($oldName, $this->delim); - if (strpos($oldName, 'INBOX' . $this->delim) === 0) { - $oldName = substr($oldName, 6); - } - - $newName = trim($newName, $this->delim); - if (strpos($newName, 'INBOX' . $this->delim) === 0) { - $newName = substr($newName, 6); - } - - if (strpos($newName, $oldName . $this->delim) === 0) { - throw new StorageException\RuntimeException('new folder cannot be a child of old folder'); - } - - // check if folder exists and has no children - $folder = $this->getFolders($oldName); - - if ($oldName == 'INBOX' || $oldName == DIRECTORY_SEPARATOR || $oldName == '/') { - throw new StorageException\RuntimeException('wont rename INBOX'); - } - - if ($oldName == $this->getCurrentFolder()) { - throw new StorageException\RuntimeException('wont rename selected folder'); - } - - $newdir = $this->createFolder($newName); - - if (! $folder->isLeaf()) { - foreach ($folder as $k => $v) { - $this->renameFolder($v->getGlobalName(), $newName . $this->delim . $k); - } - } - - $olddir = $this->rootdir . '.' . $folder; - foreach (['tmp', 'new', 'cur'] as $subdir) { - $subdir = DIRECTORY_SEPARATOR . $subdir; - if (! file_exists($olddir . $subdir)) { - continue; - } - // using copy or moving files would be even better - but also much slower - if (! rename($olddir . $subdir, $newdir . $subdir)) { - throw new StorageException\RuntimeException('error while moving ' . $subdir); - } - } - // create a dummy if removing fails - otherwise we can't read it next time - mkdir($olddir . DIRECTORY_SEPARATOR . 'cur'); - $this->removeFolder($oldName); - } - - /** - * create a uniqueid for maildir filename - * - * This is nearly the format defined in the maildir standard. The microtime() call should already - * create a uniqueid, the pid is for multicore/-cpu machine that manage to call this function at the - * exact same time, and uname() gives us the hostname for multiple machines accessing the same storage. - * - * If someone disables posix we create a random number of the same size, so this method should also - * work on Windows - if you manage to get maildir working on Windows. - * Microtime could also be disabled, although I've never seen it. - * - * @return string new uniqueid - */ - protected function createUniqueId() - { - $id = ''; - $id .= microtime(true); - $id .= '.' . getmypid(); - $id .= '.' . php_uname('n'); - - return $id; - } - - /** - * open a temporary maildir file - * - * makes sure tmp/ exists and create a file with a unique name - * you should close the returned filehandle! - * - * @param string $folder name of current folder without leading . - * @throws \Laminas\Mail\Storage\Exception\RuntimeException - * @return array array('dirname' => dir of maildir folder, 'uniq' => unique id, 'filename' => name of create file - * 'handle' => file opened for writing) - */ - protected function createTmpFile($folder = 'INBOX') - { - if ($folder == 'INBOX') { - $tmpdir = $this->rootdir . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR; - } else { - $tmpdir = $this->rootdir . '.' . $folder . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR; - } - if (! file_exists($tmpdir)) { - if (! mkdir($tmpdir)) { - throw new StorageException\RuntimeException('problems creating tmp dir'); - } - } - - // we should retry to create a unique id if a file with the same name exists - // to avoid a script timeout we only wait 1 second (instead of 2) and stop - // after a defined retry count - // if you change this variable take into account that it can take up to $maxTries seconds - // normally we should have a valid unique name after the first try, we're just following the "standard" here - $maxTries = 5; - for ($i = 0; $i < $maxTries; ++$i) { - $uniq = $this->createUniqueId(); - if (! file_exists($tmpdir . $uniq)) { - // here is the race condition! - as defined in the standard - // to avoid having a long time between stat()ing the file and creating it we're opening it here - // to mark the filename as taken - $fh = fopen($tmpdir . $uniq, 'w'); - if (! $fh) { - throw new StorageException\RuntimeException('could not open temp file'); - } - break; - } - sleep(1); - } - - if (! $fh) { - throw new StorageException\RuntimeException( - "tried {$maxTries} unique ids for a temp file, but all were taken - giving up" - ); - } - - return [ - 'dirname' => $this->rootdir . '.' . $folder, - 'uniq' => $uniq, - 'filename' => $tmpdir . $uniq, - 'handle' => $fh, - ]; - } - - /** - * create an info string for filenames with given flags - * - * @param array $flags wanted flags, with the reference you'll get the set - * flags with correct key (= char for flag) - * @return string info string for version 2 filenames including the leading colon - * @throws StorageException\InvalidArgumentException - */ - protected function getInfoString(&$flags) - { - // accessing keys is easier, faster and it removes duplicated flags - $wantedFlags = array_flip($flags); - if (isset($wantedFlags[Storage::FLAG_RECENT])) { - throw new StorageException\InvalidArgumentException('recent flag may not be set'); - } - - $info = ':2,'; - $flags = []; - foreach (Storage\Maildir::$knownFlags as $char => $flag) { - if (! isset($wantedFlags[$flag])) { - continue; - } - $info .= $char; - $flags[$char] = $flag; - unset($wantedFlags[$flag]); - } - - if (! empty($wantedFlags)) { - $wantedFlags = implode(', ', array_keys($wantedFlags)); - throw new StorageException\InvalidArgumentException('unknown flag(s): ' . $wantedFlags); - } - - return $info; - } - - /** - * append a new message to mail storage - * - * @param string|resource $message message as string or stream resource. - * @param null|string|Folder $folder folder for new message, else current - * folder is taken. - * @param null|array $flags set flags for new message, else a default set - * is used. - * @param bool $recent handle this mail as if recent flag has been set, - * should only be used in delivery. - * @throws StorageException\RuntimeException - */ - public function appendMessage($message, $folder = null, $flags = null, $recent = false) - { - if ($this->quota && $this->checkQuota()) { - throw new StorageException\RuntimeException('storage is over quota!'); - } - - if ($folder === null) { - $folder = $this->currentFolder; - } - - if (! ($folder instanceof Folder)) { - $folder = $this->getFolders($folder); - } - - if ($flags === null) { - $flags = [Storage::FLAG_SEEN]; - } - $info = $this->getInfoString($flags); - $tempFile = $this->createTmpFile($folder->getGlobalName()); - - // TODO: handle class instances for $message - if (is_resource($message) && get_resource_type($message) == 'stream') { - stream_copy_to_stream($message, $tempFile['handle']); - } else { - fwrite($tempFile['handle'], $message); - } - fclose($tempFile['handle']); - - // we're adding the size to the filename for maildir++ - $size = filesize($tempFile['filename']); - if ($size !== false) { - $info = ',S=' . $size . $info; - } - $newFilename = $tempFile['dirname'] . DIRECTORY_SEPARATOR; - $newFilename .= $recent ? 'new' : 'cur'; - $newFilename .= DIRECTORY_SEPARATOR . $tempFile['uniq'] . $info; - - // we're throwing any exception after removing our temp file and saving it to this variable instead - $exception = null; - - if (! link($tempFile['filename'], $newFilename)) { - $exception = new StorageException\RuntimeException('cannot link message file to final dir'); - } - - ErrorHandler::start(E_WARNING); - unlink($tempFile['filename']); - ErrorHandler::stop(); - - if ($exception) { - throw $exception; - } - - $this->files[] = [ - 'uniq' => $tempFile['uniq'], - 'flags' => $flags, - 'filename' => $newFilename, - ]; - if ($this->quota) { - $this->addQuotaEntry((int) $size, 1); - } - } - - /** - * copy an existing message - * - * @param int $id number of message - * @param string|\Laminas\Mail\Storage\Folder $folder name or instance of targer folder - * @throws \Laminas\Mail\Storage\Exception\RuntimeException - */ - public function copyMessage($id, $folder) - { - if ($this->quota && $this->checkQuota()) { - throw new StorageException\RuntimeException('storage is over quota!'); - } - - if (! ($folder instanceof Folder)) { - $folder = $this->getFolders($folder); - } - - $filedata = $this->getFileData($id); - $oldFile = $filedata['filename']; - $flags = $filedata['flags']; - - // copied message can't be recent - while (($key = array_search(Storage::FLAG_RECENT, $flags)) !== false) { - unset($flags[$key]); - } - $info = $this->getInfoString($flags); - - // we're creating the copy as temp file before moving to cur/ - $tempFile = $this->createTmpFile($folder->getGlobalName()); - // we don't write directly to the file - fclose($tempFile['handle']); - - // we're adding the size to the filename for maildir++ - $size = filesize($oldFile); - if ($size !== false) { - $info = ',S=' . $size . $info; - } - - $newFile = $tempFile['dirname'] . DIRECTORY_SEPARATOR . 'cur' . DIRECTORY_SEPARATOR . $tempFile['uniq'] . $info; - - // we're throwing any exception after removing our temp file and saving it to this variable instead - $exception = null; - - if (! copy($oldFile, $tempFile['filename'])) { - $exception = new StorageException\RuntimeException('cannot copy message file'); - } elseif (! link($tempFile['filename'], $newFile)) { - $exception = new StorageException\RuntimeException('cannot link message file to final dir'); - } - - ErrorHandler::start(E_WARNING); - unlink($tempFile['filename']); - ErrorHandler::stop(); - - if ($exception) { - throw $exception; - } - - if ($folder->getGlobalName() == $this->currentFolder - || ($this->currentFolder == 'INBOX' && $folder->getGlobalName() == '/') - ) { - $this->files[] = [ - 'uniq' => $tempFile['uniq'], - 'flags' => $flags, - 'filename' => $newFile, - ]; - } - - if ($this->quota) { - $this->addQuotaEntry((int) $size, 1); - } - } - - /** - * move an existing message - * - * @param int $id number of message - * @param string|\Laminas\Mail\Storage\Folder $folder name or instance of targer folder - * @throws \Laminas\Mail\Storage\Exception\RuntimeException - */ - public function moveMessage($id, $folder) - { - if (! ($folder instanceof Folder)) { - $folder = $this->getFolders($folder); - } - - if ($folder->getGlobalName() == $this->currentFolder - || ($this->currentFolder == 'INBOX' && $folder->getGlobalName() == '/') - ) { - throw new StorageException\RuntimeException('target is current folder'); - } - - $filedata = $this->getFileData($id); - $oldFile = $filedata['filename']; - $flags = $filedata['flags']; - - // moved message can't be recent - while (($key = array_search(Storage::FLAG_RECENT, $flags)) !== false) { - unset($flags[$key]); - } - $info = $this->getInfoString($flags); - - // reserving a new name - $tempFile = $this->createTmpFile($folder->getGlobalName()); - fclose($tempFile['handle']); - - // we're adding the size to the filename for maildir++ - $size = filesize($oldFile); - if ($size !== false) { - $info = ',S=' . $size . $info; - } - - $newFile = $tempFile['dirname'] . DIRECTORY_SEPARATOR . 'cur' . DIRECTORY_SEPARATOR . $tempFile['uniq'] . $info; - - // we're throwing any exception after removing our temp file and saving it to this variable instead - $exception = null; - - if (! rename($oldFile, $newFile)) { - $exception = new StorageException\RuntimeException('cannot move message file'); - } - - ErrorHandler::start(E_WARNING); - unlink($tempFile['filename']); - ErrorHandler::stop(); - - if ($exception) { - throw $exception; - } - - unset($this->files[$id - 1]); - // remove the gap - $this->files = array_values($this->files); - } - - /** - * set flags for message - * - * NOTE: this method can't set the recent flag. - * - * @param int $id number of message - * @param array $flags new flags for message - * @throws \Laminas\Mail\Storage\Exception\RuntimeException - */ - public function setFlags($id, $flags) - { - $info = $this->getInfoString($flags); - $filedata = $this->getFileData($id); - - // NOTE: double dirname to make sure we always move to cur. if recent - // flag has been set (message is in new) it will be moved to cur. - $newFilename = dirname($filedata['filename'], 2) - . DIRECTORY_SEPARATOR - . 'cur' - . DIRECTORY_SEPARATOR - . "$filedata[uniq]$info"; - - ErrorHandler::start(); - $test = rename($filedata['filename'], $newFilename); - $error = ErrorHandler::stop(); - if (! $test) { - throw new StorageException\RuntimeException('cannot rename file', 0, $error); - } - - $filedata['flags'] = $flags; - $filedata['filename'] = $newFilename; - - $this->files[$id - 1] = $filedata; - } - - /** - * stub for not supported message deletion - * - * @param $id - * @throws \Laminas\Mail\Storage\Exception\RuntimeException - */ - public function removeMessage($id) - { - $filename = $this->getFileData($id, 'filename'); - - if ($this->quota) { - $size = filesize($filename); - } - - ErrorHandler::start(); - $test = unlink($filename); - $error = ErrorHandler::stop(); - if (! $test) { - throw new StorageException\RuntimeException('cannot remove message', 0, $error); - } - unset($this->files[$id - 1]); - // remove the gap - $this->files = array_values($this->files); - if ($this->quota) { - $this->addQuotaEntry(0 - (int) $size, -1); - } - } - - /** - * enable/disable quota and set a quota value if wanted or needed - * - * You can enable/disable quota with true/false. If you don't have - * a MDA or want to enforce a quota value you can also set this value - * here. Use array('size' => SIZE_QUOTA, 'count' => MAX_MESSAGE) do - * define your quota. Order of these fields does matter! - * - * @param bool|array $value new quota value - */ - public function setQuota($value) - { - $this->quota = $value; - } - - /** - * get currently set quota - * - * @see \Laminas\Mail\Storage\Writable\Maildir::setQuota() - * @param bool $fromStorage - * @throws \Laminas\Mail\Storage\Exception\RuntimeException - * @return bool|array - */ - public function getQuota($fromStorage = false) - { - if ($fromStorage) { - ErrorHandler::start(E_WARNING); - $fh = fopen($this->rootdir . 'maildirsize', 'r'); - $error = ErrorHandler::stop(); - if (! $fh) { - throw new StorageException\RuntimeException('cannot open maildirsize', 0, $error); - } - $definition = fgets($fh); - fclose($fh); - $definition = explode(',', trim($definition)); - $quota = []; - foreach ($definition as $member) { - $key = $member[strlen($member) - 1]; - if ($key == 'S' || $key == 'C') { - $key = $key == 'C' ? 'count' : 'size'; - } - $quota[$key] = substr($member, 0, -1); - } - return $quota; - } - - return $this->quota; - } - - /** - * @see http://www.inter7.com/courierimap/README.maildirquota.html "Calculating maildirsize" - * @throws \Laminas\Mail\Storage\Exception\RuntimeException - * @return array - */ - protected function calculateMaildirsize() - { - $timestamps = []; - $messages = 0; - $totalSize = 0; - - if (is_array($this->quota)) { - $quota = $this->quota; - } else { - try { - $quota = $this->getQuota(true); - } catch (StorageException\ExceptionInterface $e) { - throw new StorageException\RuntimeException('no quota definition found', 0, $e); - } - } - - $folders = new RecursiveIteratorIterator($this->getFolders(), RecursiveIteratorIterator::SELF_FIRST); - foreach ($folders as $folder) { - $subdir = $folder->getGlobalName(); - if ($subdir == 'INBOX') { - $subdir = ''; - } else { - $subdir = '.' . $subdir; - } - if ($subdir == 'Trash') { - continue; - } - - foreach (['cur', 'new'] as $subsubdir) { - $dirname = $this->rootdir . $subdir . DIRECTORY_SEPARATOR . $subsubdir . DIRECTORY_SEPARATOR; - if (! file_exists($dirname)) { - continue; - } - // NOTE: we are using mtime instead of "the latest timestamp". The latest would be atime - // and as we are accessing the directory it would make the whole calculation useless. - $timestamps[$dirname] = filemtime($dirname); - - $dh = opendir($dirname); - // NOTE: Should have been checked in constructor. Not throwing an exception here, quotas will - // therefore not be fully enforced, but next request will fail anyway, if problem persists. - if (! $dh) { - continue; - } - - while (($entry = readdir()) !== false) { - if ($entry[0] == '.' || ! is_file($dirname . $entry)) { - continue; - } - - if (strpos($entry, ',S=')) { - strtok($entry, '='); - $filesize = strtok(':'); - if (is_numeric($filesize)) { - $totalSize += $filesize; - ++$messages; - continue; - } - } - $size = filesize($dirname . $entry); - if ($size === false) { - // ignore, as we assume file got removed - continue; - } - $totalSize += $size; - ++$messages; - } - } - } - - $tmp = $this->createTmpFile(); - $fh = $tmp['handle']; - $definition = []; - foreach ($quota as $type => $value) { - if ($type == 'size' || $type == 'count') { - $type = $type == 'count' ? 'C' : 'S'; - } - $definition[] = $value . $type; - } - $definition = implode(',', $definition); - fwrite($fh, "$definition\n"); - fwrite($fh, "$totalSize $messages\n"); - fclose($fh); - rename($tmp['filename'], $this->rootdir . 'maildirsize'); - foreach ($timestamps as $dir => $timestamp) { - if ($timestamp < filemtime($dir)) { - unlink($this->rootdir . 'maildirsize'); - break; - } - } - - return [ - 'size' => $totalSize, - 'count' => $messages, - 'quota' => $quota, - ]; - } - - /** - * @see http://www.inter7.com/courierimap/README.maildirquota.html "Calculating the quota for a Maildir++" - * @param bool $forceRecalc - * @return array - */ - protected function calculateQuota($forceRecalc = false) - { - $fh = null; - $totalSize = 0; - $messages = 0; - $maildirsize = ''; - if (! $forceRecalc - && file_exists($this->rootdir . 'maildirsize') - && filesize($this->rootdir . 'maildirsize') < 5120 - ) { - $fh = fopen($this->rootdir . 'maildirsize', 'r'); - } - if ($fh) { - $maildirsize = fread($fh, 5120); - if (strlen($maildirsize) >= 5120) { - fclose($fh); - $fh = null; - $maildirsize = ''; - } - } - if (! $fh) { - $result = $this->calculateMaildirsize(); - $totalSize = $result['size']; - $messages = $result['count']; - $quota = $result['quota']; - } else { - $maildirsize = explode("\n", $maildirsize); - if (is_array($this->quota)) { - $quota = $this->quota; - } else { - $definition = explode(',', $maildirsize[0]); - $quota = []; - foreach ($definition as $member) { - $key = $member[strlen($member) - 1]; - if ($key == 'S' || $key == 'C') { - $key = $key == 'C' ? 'count' : 'size'; - } - $quota[$key] = substr($member, 0, -1); - } - } - unset($maildirsize[0]); - foreach ($maildirsize as $line) { - list($size, $count) = explode(' ', trim($line)); - $totalSize += $size; - $messages += $count; - } - } - - $overQuota = false; - $overQuota = $overQuota || (isset($quota['size']) && $totalSize > $quota['size']); - $overQuota = $overQuota || (isset($quota['count']) && $messages > $quota['count']); - // NOTE: $maildirsize equals false if it wasn't set (AKA we recalculated) or it's only - // one line, because $maildirsize[0] gets unsetted. - // Also we're using local time to calculate the 15 minute offset. Touching a file just for known the - // local time of the file storage isn't worth the hassle. - if ($overQuota && ($maildirsize || filemtime($this->rootdir . 'maildirsize') > time() - 900)) { - $result = $this->calculateMaildirsize(); - $totalSize = $result['size']; - $messages = $result['count']; - $quota = $result['quota']; - $overQuota = false; - $overQuota = $overQuota || (isset($quota['size']) && $totalSize > $quota['size']); - $overQuota = $overQuota || (isset($quota['count']) && $messages > $quota['count']); - } - - if ($fh) { - // TODO is there a safe way to keep the handle open for writing? - fclose($fh); - } - - return [ - 'size' => $totalSize, - 'count' => $messages, - 'quota' => $quota, - 'over_quota' => $overQuota, - ]; - } - - protected function addQuotaEntry($size, $count = 1) - { - if (! file_exists($this->rootdir . 'maildirsize')) { - // TODO: should get file handler from calculateQuota - } - $size = (int) $size; - $count = (int) $count; - file_put_contents($this->rootdir . 'maildirsize', "$size $count\n", FILE_APPEND); - } - - /** - * check if storage is currently over quota - * - * @see calculateQuota() - * @param bool $detailedResponse return known data of quota and current size and message count - * @param bool $forceRecalc - * @return bool|array over quota state or detailed response - */ - public function checkQuota($detailedResponse = false, $forceRecalc = false) - { - $result = $this->calculateQuota($forceRecalc); - return $detailedResponse ? $result : $result['over_quota']; - } -} diff --git a/lib/laminas/laminas-mail/src/Storage/Writable/WritableInterface.php b/lib/laminas/laminas-mail/src/Storage/Writable/WritableInterface.php deleted file mode 100644 index 9a005ba3b..000000000 --- a/lib/laminas/laminas-mail/src/Storage/Writable/WritableInterface.php +++ /dev/null @@ -1,86 +0,0 @@ -<?php - -namespace Laminas\Mail\Storage\Writable; - -use Laminas\Mail\Message; -use Laminas\Mail\Storage; -use Laminas\Mime; - -interface WritableInterface -{ - /** - * create a new folder - * - * This method also creates parent folders if necessary. Some mail storages - * may restrict, which folder may be used as parent or which chars may be - * used in the folder name - * - * @param string $name global name of folder, local name if $parentFolder - * is set. - * @param string|Storage\Folder $parentFolder parent folder for new folder, - * else root folder is parent. - * @throws Storage\Exception\ExceptionInterface - */ - public function createFolder($name, $parentFolder = null); - - /** - * remove a folder - * - * @param string|Storage\Folder $name name or instance of folder. - * @throws Storage\Exception\ExceptionInterface - */ - public function removeFolder($name); - - /** - * rename and/or move folder - * - * The new name has the same restrictions as in createFolder() - * - * @param string|Storage\Folder $oldName name or instance of folder. - * @param string $newName new global name of folder. - * @throws Storage\Exception\ExceptionInterface - */ - public function renameFolder($oldName, $newName); - - /** - * append a new message to mail storage - * - * @param string|Message|Mime\Message $message message as string or - * instance of message class. - * @param null|string|Storage\Folder $folder folder for new message, else - * current folder is taken. - * @param null|array $flags set flags for new message, else a default set - * is used. - * @throws Storage\Exception\ExceptionInterface - */ - public function appendMessage($message, $folder = null, $flags = null); - - /** - * copy an existing message - * - * @param int $id number of message - * @param string|Storage\Folder $folder name or instance of target folder - * @throws Storage\Exception\ExceptionInterface - */ - public function copyMessage($id, $folder); - - /** - * move an existing message - * - * @param int $id number of message - * @param string|Storage\Folder $folder name or instance of target folder - * @throws Storage\Exception\ExceptionInterface - */ - public function moveMessage($id, $folder); - - /** - * set flags for message - * - * NOTE: this method can't set the recent flag. - * - * @param int $id number of message - * @param array $flags new flags for message - * @throws Storage\Exception\ExceptionInterface - */ - public function setFlags($id, $flags); -} diff --git a/lib/laminas/laminas-mail/src/Transport/Envelope.php b/lib/laminas/laminas-mail/src/Transport/Envelope.php deleted file mode 100644 index 1b046c614..000000000 --- a/lib/laminas/laminas-mail/src/Transport/Envelope.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php - -namespace Laminas\Mail\Transport; - -use Laminas\Stdlib\AbstractOptions; - -class Envelope extends AbstractOptions -{ - /** - * @var string|null - */ - protected $from; - - /** - * @var string|null - */ - protected $to; - - /** - * Get MAIL FROM - * - * @return string - */ - public function getFrom() - { - return $this->from; - } - - /** - * Set MAIL FROM - * - * @param string $from - */ - public function setFrom($from) - { - $this->from = (string) $from; - } - - /** - * Get RCPT TO - * - * @return string|null - */ - public function getTo() - { - return $this->to; - } - - /** - * Set RCPT TO - * - * @param string $to - */ - public function setTo($to) - { - $this->to = $to; - } -} diff --git a/lib/laminas/laminas-mail/src/Transport/Exception/DomainException.php b/lib/laminas/laminas-mail/src/Transport/Exception/DomainException.php deleted file mode 100644 index d92b9d122..000000000 --- a/lib/laminas/laminas-mail/src/Transport/Exception/DomainException.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -namespace Laminas\Mail\Transport\Exception; - -use Laminas\Mail\Exception; - -/** - * Exception for Laminas\Mail\Transport component. - */ -class DomainException extends Exception\DomainException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-mail/src/Transport/Exception/ExceptionInterface.php b/lib/laminas/laminas-mail/src/Transport/Exception/ExceptionInterface.php deleted file mode 100644 index 4e1356c2c..000000000 --- a/lib/laminas/laminas-mail/src/Transport/Exception/ExceptionInterface.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -namespace Laminas\Mail\Transport\Exception; - -use Laminas\Mail\Exception\ExceptionInterface as MailException; - -interface ExceptionInterface extends MailException -{ -} diff --git a/lib/laminas/laminas-mail/src/Transport/Exception/InvalidArgumentException.php b/lib/laminas/laminas-mail/src/Transport/Exception/InvalidArgumentException.php deleted file mode 100644 index d63332dd2..000000000 --- a/lib/laminas/laminas-mail/src/Transport/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -namespace Laminas\Mail\Transport\Exception; - -use Laminas\Mail\Exception; - -/** - * Exception for Laminas\Mail component. - */ -class InvalidArgumentException extends Exception\InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-mail/src/Transport/Exception/RuntimeException.php b/lib/laminas/laminas-mail/src/Transport/Exception/RuntimeException.php deleted file mode 100644 index 331a366e4..000000000 --- a/lib/laminas/laminas-mail/src/Transport/Exception/RuntimeException.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -namespace Laminas\Mail\Transport\Exception; - -use Laminas\Mail\Exception; - -/** - * Exception for Laminas\Mail component. - */ -class RuntimeException extends Exception\RuntimeException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-mail/src/Transport/Factory.php b/lib/laminas/laminas-mail/src/Transport/Factory.php deleted file mode 100644 index b9e34b552..000000000 --- a/lib/laminas/laminas-mail/src/Transport/Factory.php +++ /dev/null @@ -1,79 +0,0 @@ -<?php - -namespace Laminas\Mail\Transport; - -use Laminas\Stdlib\ArrayUtils; -use Traversable; - -abstract class Factory -{ - /** - * @var array Known transport types - */ - protected static $classMap = [ - 'file' => File::class, - 'inmemory' => InMemory::class, - 'memory' => InMemory::class, - 'null' => InMemory::class, - 'sendmail' => Sendmail::class, - 'smtp' => Smtp::class, - ]; - - /** - * @param array $spec - * @return TransportInterface - * @throws Exception\InvalidArgumentException - * @throws Exception\DomainException - */ - public static function create($spec = []) - { - if ($spec instanceof Traversable) { - $spec = ArrayUtils::iteratorToArray($spec); - } - - if (! is_array($spec)) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects an array or Traversable argument; received "%s"', - __METHOD__, - (is_object($spec) ? get_class($spec) : gettype($spec)) - )); - } - - $type = $spec['type'] ?? 'sendmail'; - - $normalizedType = strtolower($type); - - if (isset(static::$classMap[$normalizedType])) { - $type = static::$classMap[$normalizedType]; - } - - if (! class_exists($type)) { - throw new Exception\DomainException(sprintf( - '%s expects the "type" attribute to resolve to an existing class; received "%s"', - __METHOD__, - $type - )); - } - - $transport = new $type(); - - if (! $transport instanceof TransportInterface) { - throw new Exception\DomainException(sprintf( - '%s expects the "type" attribute to resolve to a valid %s instance; received "%s"', - __METHOD__, - TransportInterface::class, - $type - )); - } - - if ($transport instanceof Smtp && isset($spec['options'])) { - $transport->setOptions(new SmtpOptions($spec['options'])); - } - - if ($transport instanceof File && isset($spec['options'])) { - $transport->setOptions(new FileOptions($spec['options'])); - } - - return $transport; - } -} diff --git a/lib/laminas/laminas-mail/src/Transport/File.php b/lib/laminas/laminas-mail/src/Transport/File.php deleted file mode 100644 index 7e772bb7f..000000000 --- a/lib/laminas/laminas-mail/src/Transport/File.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php - -namespace Laminas\Mail\Transport; - -use Laminas\Mail\Message; - -/** - * File transport - * - * Class for saving outgoing emails in filesystem - */ -class File implements TransportInterface -{ - /** - * @var FileOptions - */ - protected $options; - - /** - * Last file written to - * - * @var string - */ - protected $lastFile; - - /** - * Constructor - * - * @param null|FileOptions $options OPTIONAL (Default: null) - */ - public function __construct(FileOptions $options = null) - { - if (! $options instanceof FileOptions) { - $options = new FileOptions(); - } - $this->setOptions($options); - } - - /** - * @return FileOptions - */ - public function getOptions() - { - return $this->options; - } - - /** - * Sets options - * - * @param FileOptions $options - */ - public function setOptions(FileOptions $options) - { - $this->options = $options; - } - - /** - * Saves e-mail message to a file - * - * @param Message $message - * @throws Exception\RuntimeException on not writable target directory or - * on file_put_contents() failure - */ - public function send(Message $message) - { - $options = $this->options; - $filename = $options->getCallback()($this); - $file = $options->getPath() . DIRECTORY_SEPARATOR . $filename; - $email = $message->toString(); - - if (false === file_put_contents($file, $email)) { - throw new Exception\RuntimeException(sprintf( - 'Unable to write mail to file (directory "%s")', - $options->getPath() - )); - } - - $this->lastFile = $file; - } - - /** - * Get the name of the last file written to - * - * @return string - */ - public function getLastFile() - { - return $this->lastFile; - } -} diff --git a/lib/laminas/laminas-mail/src/Transport/FileOptions.php b/lib/laminas/laminas-mail/src/Transport/FileOptions.php deleted file mode 100644 index d6a811ed8..000000000 --- a/lib/laminas/laminas-mail/src/Transport/FileOptions.php +++ /dev/null @@ -1,89 +0,0 @@ -<?php - -namespace Laminas\Mail\Transport; - -use Laminas\Mail\Exception; -use Laminas\Stdlib\AbstractOptions; - -class FileOptions extends AbstractOptions -{ - /** - * @var string Path to stored mail files - */ - protected $path; - - /** - * @var callable - */ - protected $callback; - - /** - * Set path to stored mail files - * - * @param string $path - * @throws \Laminas\Mail\Exception\InvalidArgumentException - * @return FileOptions - */ - public function setPath($path) - { - if (! is_dir($path) || ! is_writable($path)) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects a valid path in which to write mail files; received "%s"', - __METHOD__, - (string) $path - )); - } - $this->path = $path; - return $this; - } - - /** - * Get path - * - * If none is set, uses value from sys_get_temp_dir() - * - * @return string - */ - public function getPath() - { - if (null === $this->path) { - $this->setPath(sys_get_temp_dir()); - } - return $this->path; - } - - /** - * Set callback used to generate a file name - * - * @param callable $callback - * @throws \Laminas\Mail\Exception\InvalidArgumentException - * @return FileOptions - */ - public function setCallback($callback) - { - if (! is_callable($callback)) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects a valid callback; received "%s"', - __METHOD__, - (is_object($callback) ? get_class($callback) : gettype($callback)) - )); - } - $this->callback = $callback; - return $this; - } - - /** - * Get callback used to generate a file name - * - * @return callable - */ - public function getCallback() - { - if (null === $this->callback) { - $this->setCallback(function () { - return 'LaminasMail_' . time() . '_' . mt_rand() . '.eml'; - }); - } - return $this->callback; - } -} diff --git a/lib/laminas/laminas-mail/src/Transport/InMemory.php b/lib/laminas/laminas-mail/src/Transport/InMemory.php deleted file mode 100644 index 49caf6adb..000000000 --- a/lib/laminas/laminas-mail/src/Transport/InMemory.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -namespace Laminas\Mail\Transport; - -use Laminas\Mail\Message; - -/** - * InMemory transport - * - * This transport will just store the message in memory. It is helpful - * when unit testing, or to prevent sending email when in development or - * testing. - */ -class InMemory implements TransportInterface -{ - /** - * @var null|Message - */ - protected $lastMessage; - - /** - * Takes the last message and saves it for testing. - * - * @param Message $message - */ - public function send(Message $message) - { - $this->lastMessage = $message; - } - - /** - * Get the last message sent. - * - * @return null|Message - */ - public function getLastMessage() - { - return $this->lastMessage; - } -} diff --git a/lib/laminas/laminas-mail/src/Transport/Sendmail.php b/lib/laminas/laminas-mail/src/Transport/Sendmail.php deleted file mode 100644 index 807282017..000000000 --- a/lib/laminas/laminas-mail/src/Transport/Sendmail.php +++ /dev/null @@ -1,330 +0,0 @@ -<?php - -namespace Laminas\Mail\Transport; - -use Laminas\Mail; -use Laminas\Mail\Address\AddressInterface; -use Laminas\Mail\Header\HeaderInterface; -use Traversable; - -/** - * Class for sending email via the PHP internal mail() function - */ -class Sendmail implements TransportInterface -{ - /** - * Config options for sendmail parameters - * - * @var string - */ - protected $parameters; - - /** - * Callback to use when sending mail; typically, {@link mailHandler()} - * - * @var callable - */ - protected $callable; - - /** - * error information - * @var string - */ - protected $errstr; - - /** - * @var string - */ - protected $operatingSystem; - - /** - * Constructor. - * - * @param null|string|array|Traversable $parameters OPTIONAL (Default: null) - */ - public function __construct($parameters = null) - { - if ($parameters !== null) { - $this->setParameters($parameters); - } - $this->callable = [$this, 'mailHandler']; - } - - /** - * Set sendmail parameters - * - * Used to populate the additional_parameters argument to mail() - * - * @param null|string|array|Traversable $parameters - * @throws \Laminas\Mail\Transport\Exception\InvalidArgumentException - * @return Sendmail - */ - public function setParameters($parameters) - { - if ($parameters === null || is_string($parameters)) { - $this->parameters = $parameters; - return $this; - } - - if (! is_array($parameters) && ! $parameters instanceof Traversable) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects a string, array, or Traversable object of parameters; received "%s"', - __METHOD__, - (is_object($parameters) ? get_class($parameters) : gettype($parameters)) - )); - } - - $string = ''; - foreach ($parameters as $param) { - $string .= ' ' . $param; - } - - $this->parameters = trim($string); - return $this; - } - - /** - * Set callback to use for mail - * - * Primarily for testing purposes, but could be used to curry arguments. - * - * @param callable $callable - * @throws \Laminas\Mail\Transport\Exception\InvalidArgumentException - * @return Sendmail - */ - public function setCallable($callable) - { - if (! is_callable($callable)) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects a callable argument; received "%s"', - __METHOD__, - (is_object($callable) ? get_class($callable) : gettype($callable)) - )); - } - $this->callable = $callable; - return $this; - } - - /** - * Send a message - * - * @param \Laminas\Mail\Message $message - */ - public function send(Mail\Message $message) - { - $to = $this->prepareRecipients($message); - $subject = $this->prepareSubject($message); - $body = $this->prepareBody($message); - $headers = $this->prepareHeaders($message); - $params = $this->prepareParameters($message); - - // On *nix platforms, we need to replace \r\n with \n - // sendmail is not an SMTP server, it is a unix command - it expects LF - if (PHP_VERSION_ID < 80000 && ! $this->isWindowsOs()) { - $to = str_replace("\r\n", "\n", $to); - $subject = str_replace("\r\n", "\n", $subject); - $body = str_replace("\r\n", "\n", $body); - $headers = str_replace("\r\n", "\n", $headers); - } - - ($this->callable)($to, $subject, $body, $headers, $params); - } - - /** - * Prepare recipients list - * - * @param \Laminas\Mail\Message $message - * @throws \Laminas\Mail\Transport\Exception\RuntimeException - * @return string - */ - protected function prepareRecipients(Mail\Message $message) - { - $headers = $message->getHeaders(); - - $hasTo = $headers->has('to'); - if (! $hasTo && ! $headers->has('cc') && ! $headers->has('bcc')) { - throw new Exception\RuntimeException( - 'Invalid email; contains no at least one of "To", "Cc", and "Bcc" header' - ); - } - - if (! $hasTo) { - return ''; - } - - /** @var Mail\Header\To $to */ - $to = $headers->get('to'); - $list = $to->getAddressList(); - if (0 == count($list)) { - throw new Exception\RuntimeException('Invalid "To" header; contains no addresses'); - } - - // If not on Windows, return normal string - if (! $this->isWindowsOs()) { - return $to->getFieldValue(HeaderInterface::FORMAT_ENCODED); - } - - // Otherwise, return list of emails - $addresses = []; - foreach ($list as $address) { - $addresses[] = $address->getEmail(); - } - $addresses = implode(', ', $addresses); - return $addresses; - } - - /** - * Prepare the subject line string - * - * @param \Laminas\Mail\Message $message - * @return string - */ - protected function prepareSubject(Mail\Message $message) - { - $headers = $message->getHeaders(); - if (! $headers->has('subject')) { - return; - } - $header = $headers->get('subject'); - return $header->getFieldValue(HeaderInterface::FORMAT_ENCODED); - } - - /** - * Prepare the body string - * - * @param \Laminas\Mail\Message $message - * @return string - */ - protected function prepareBody(Mail\Message $message) - { - if (! $this->isWindowsOs()) { - // *nix platforms can simply return the body text - return $message->getBodyText(); - } - - // On windows, lines beginning with a full stop need to be fixed - $text = $message->getBodyText(); - $text = str_replace("\n.", "\n..", $text); - return $text; - } - - /** - * Prepare the textual representation of headers - * - * @param \Laminas\Mail\Message $message - * @return string - */ - protected function prepareHeaders(Mail\Message $message) - { - // Strip the "to" and "subject" headers - $headers = clone $message->getHeaders(); - $headers->removeHeader('To'); - $headers->removeHeader('Subject'); - - /** @var Mail\Header\From $from Sanitize the From header*/ - $from = $headers->get('From'); - if ($from) { - foreach ($from->getAddressList() as $address) { - if (strpos($address->getEmail(), '\\"') !== false) { - throw new Exception\RuntimeException('Potential code injection in From header'); - } - } - } - return $headers->toString(); - } - - /** - * Prepare additional_parameters argument - * - * Basically, overrides the MAIL FROM envelope with either the Sender or - * From address. - * - * @param \Laminas\Mail\Message $message - * @return string - */ - protected function prepareParameters(Mail\Message $message) - { - if ($this->isWindowsOs()) { - return; - } - - $parameters = (string) $this->parameters; - if (preg_match('/(^| )\-f.+/', $parameters)) { - return $parameters; - } - - $sender = $message->getSender(); - if ($sender instanceof AddressInterface) { - $parameters .= ' -f' . \escapeshellarg($sender->getEmail()); - return $parameters; - } - - $from = $message->getFrom(); - if (count($from)) { - $from->rewind(); - $sender = $from->current(); - $parameters .= ' -f' . \escapeshellarg($sender->getEmail()); - return $parameters; - } - - return $parameters; - } - - /** - * Send mail using PHP native mail() - * - * @param string $to - * @param string $subject - * @param string $message - * @param string $headers - * @param $parameters - * @throws \Laminas\Mail\Transport\Exception\RuntimeException - */ - public function mailHandler($to, $subject, $message, $headers, $parameters) - { - set_error_handler([$this, 'handleMailErrors']); - if ($parameters === null) { - $result = mail($to, $subject, $message, $headers); - } else { - $result = mail($to, $subject, $message, $headers, $parameters); - } - restore_error_handler(); - - if ($this->errstr !== null || ! $result) { - $errstr = $this->errstr; - if (empty($errstr)) { - $errstr = 'Unknown error'; - } - throw new Exception\RuntimeException('Unable to send mail: ' . $errstr); - } - } - - /** - * Temporary error handler for PHP native mail(). - * - * @param int $errno - * @param string $errstr - * @param string $errfile - * @param string $errline - * @param array $errcontext - * @return bool always true - */ - public function handleMailErrors($errno, $errstr, $errfile = null, $errline = null, array $errcontext = null) - { - $this->errstr = $errstr; - return true; - } - - /** - * Is this a windows OS? - * - * @return bool - */ - protected function isWindowsOs() - { - if (! $this->operatingSystem) { - $this->operatingSystem = strtoupper(substr(PHP_OS, 0, 3)); - } - return ($this->operatingSystem == 'WIN'); - } -} diff --git a/lib/laminas/laminas-mail/src/Transport/Smtp.php b/lib/laminas/laminas-mail/src/Transport/Smtp.php deleted file mode 100644 index 51e544697..000000000 --- a/lib/laminas/laminas-mail/src/Transport/Smtp.php +++ /dev/null @@ -1,400 +0,0 @@ -<?php - -namespace Laminas\Mail\Transport; - -use Laminas\Mail\Address; -use Laminas\Mail\Headers; -use Laminas\Mail\Message; -use Laminas\Mail\Protocol; -use Laminas\Mail\Protocol\Exception as ProtocolException; -use Laminas\ServiceManager\ServiceManager; - -/** - * SMTP connection object - * - * Loads an instance of Laminas\Mail\Protocol\Smtp and forwards smtp transactions - */ -class Smtp implements TransportInterface -{ - /** - * @var SmtpOptions - */ - protected $options; - - /** - * @var Envelope|null - */ - protected $envelope; - - /** - * @var Protocol\Smtp - */ - protected $connection; - - /** - * @var bool - */ - protected $autoDisconnect = true; - - /** - * @var Protocol\SmtpPluginManager - */ - protected $plugins; - - /** - * When did we connect to the server? - * - * @var int|null - */ - protected $connectedTime; - - /** - * Constructor. - * - * @param SmtpOptions $options Optional - */ - public function __construct(SmtpOptions $options = null) - { - if (! $options instanceof SmtpOptions) { - $options = new SmtpOptions(); - } - $this->setOptions($options); - } - - /** - * Set options - * - * @param SmtpOptions $options - * @return Smtp - */ - public function setOptions(SmtpOptions $options) - { - $this->options = $options; - return $this; - } - - /** - * Get options - * - * @return SmtpOptions - */ - public function getOptions() - { - return $this->options; - } - - /** - * Set options - * - * @param Envelope $envelope - */ - public function setEnvelope(Envelope $envelope) - { - $this->envelope = $envelope; - } - - /** - * Get envelope - * - * @return Envelope|null - */ - public function getEnvelope() - { - return $this->envelope; - } - - /** - * Set plugin manager for obtaining SMTP protocol connection - * - * @param Protocol\SmtpPluginManager $plugins - * @throws Exception\InvalidArgumentException - * @return Smtp - */ - public function setPluginManager(Protocol\SmtpPluginManager $plugins) - { - $this->plugins = $plugins; - return $this; - } - - /** - * Get plugin manager for loading SMTP protocol connection - * - * @return Protocol\SmtpPluginManager - */ - public function getPluginManager() - { - if (null === $this->plugins) { - $this->setPluginManager(new Protocol\SmtpPluginManager(new ServiceManager())); - } - return $this->plugins; - } - - /** - * Set the automatic disconnection when destruct - * - * @param bool $flag - * @return Smtp - */ - public function setAutoDisconnect($flag) - { - $this->autoDisconnect = (bool) $flag; - return $this; - } - - /** - * Get the automatic disconnection value - * - * @return bool - */ - public function getAutoDisconnect() - { - return $this->autoDisconnect; - } - - /** - * Return an SMTP connection - * - * @param string $name - * @param array|null $options - * @return Protocol\Smtp - */ - public function plugin($name, array $options = null) - { - return $this->getPluginManager()->get($name, $options); - } - - /** - * Class destructor to ensure all open connections are closed - */ - public function __destruct() - { - if (! $this->getConnection() instanceof Protocol\Smtp) { - return; - } - - try { - $this->getConnection()->quit(); - } catch (ProtocolException\ExceptionInterface $e) { - // ignore - } - - if ($this->autoDisconnect) { - $this->getConnection()->disconnect(); - } - } - - /** - * Sets the connection protocol instance - * - * @param Protocol\AbstractProtocol $connection - */ - public function setConnection(Protocol\AbstractProtocol $connection) - { - $this->connection = $connection; - if (($connection instanceof Protocol\Smtp) - && ($this->getOptions()->getConnectionTimeLimit() !== null) - ) { - $connection->setUseCompleteQuit(false); - } - } - - /** - * Gets the connection protocol instance - * - * @return Protocol\Smtp - */ - public function getConnection() - { - $timeLimit = $this->getOptions()->getConnectionTimeLimit(); - if ($timeLimit !== null - && $this->connectedTime !== null - && ((time() - $this->connectedTime) > $timeLimit) - ) { - $this->connection = null; - } - return $this->connection; - } - - /** - * Disconnect the connection protocol instance - * - * @return void - */ - public function disconnect() - { - if ($this->getConnection() instanceof Protocol\Smtp) { - $this->getConnection()->disconnect(); - $this->connectedTime = null; - } - } - - /** - * Send an email via the SMTP connection protocol - * - * The connection via the protocol adapter is made just-in-time to allow a - * developer to add a custom adapter if required before mail is sent. - * - * @param Message $message - * @throws Exception\RuntimeException - */ - public function send(Message $message) - { - // If sending multiple messages per session use existing adapter - $connection = $this->getConnection(); - - if (! ($connection instanceof Protocol\Smtp) || ! $connection->hasSession()) { - $connection = $this->connect(); - } else { - // Reset connection to ensure reliable transaction - $connection->rset(); - } - - // Prepare message - $from = $this->prepareFromAddress($message); - $recipients = $this->prepareRecipients($message); - $headers = $this->prepareHeaders($message); - $body = $this->prepareBody($message); - - if ((count($recipients) == 0) && (! empty($headers) || ! empty($body))) { - // Per RFC 2821 3.3 (page 18) - throw new Exception\RuntimeException( - sprintf( - '%s transport expects at least one recipient if the message has at least one header or body', - __CLASS__ - ) - ); - } - - // Set sender email address - $connection->mail($from); - - // Set recipient forward paths - foreach ($recipients as $recipient) { - $connection->rcpt($recipient); - } - - // Issue DATA command to client - $connection->data($headers . Headers::EOL . $body); - } - - /** - * Retrieve email address for envelope FROM - * - * @param Message $message - * @throws Exception\RuntimeException - * @return string - */ - protected function prepareFromAddress(Message $message) - { - if ($this->getEnvelope() && $this->getEnvelope()->getFrom()) { - return $this->getEnvelope()->getFrom(); - } - - $sender = $message->getSender(); - if ($sender instanceof Address\AddressInterface) { - return $sender->getEmail(); - } - - $from = $message->getFrom(); - if (! count($from)) { - // Per RFC 2822 3.6 - throw new Exception\RuntimeException(sprintf( - '%s transport expects either a Sender or at least one From address in the Message; none provided', - __CLASS__ - )); - } - - $from->rewind(); - $sender = $from->current(); - return $sender->getEmail(); - } - - /** - * Prepare array of email address recipients - * - * @param Message $message - * @return array - */ - protected function prepareRecipients(Message $message) - { - if ($this->getEnvelope() && $this->getEnvelope()->getTo()) { - return (array) $this->getEnvelope()->getTo(); - } - - $recipients = []; - foreach ($message->getTo() as $address) { - $recipients[] = $address->getEmail(); - } - foreach ($message->getCc() as $address) { - $recipients[] = $address->getEmail(); - } - foreach ($message->getBcc() as $address) { - $recipients[] = $address->getEmail(); - } - - $recipients = array_unique($recipients); - return $recipients; - } - - /** - * Prepare header string from message - * - * @param Message $message - * @return string - */ - protected function prepareHeaders(Message $message) - { - $headers = clone $message->getHeaders(); - $headers->removeHeader('Bcc'); - return $headers->toString(); - } - - /** - * Prepare body string from message - * - * @param Message $message - * @return string - */ - protected function prepareBody(Message $message) - { - return $message->getBodyText(); - } - - /** - * Lazy load the connection - * - * @return Protocol\Smtp - */ - protected function lazyLoadConnection() - { - // Check if authentication is required and determine required class - $options = $this->getOptions(); - $config = $options->getConnectionConfig(); - $config['host'] = $options->getHost(); - $config['port'] = $options->getPort(); - - $this->setConnection($this->plugin($options->getConnectionClass(), $config)); - - return $this->connect(); - } - - /** - * Connect the connection, and pass it helo - * - * @return Protocol\Smtp - */ - protected function connect() - { - if (! $this->connection instanceof Protocol\Smtp) { - return $this->lazyLoadConnection(); - } - - $this->connection->connect(); - - $this->connectedTime = time(); - - $this->connection->helo($this->getOptions()->getName()); - - return $this->connection; - } -} diff --git a/lib/laminas/laminas-mail/src/Transport/SmtpOptions.php b/lib/laminas/laminas-mail/src/Transport/SmtpOptions.php deleted file mode 100644 index 268d2ba4f..000000000 --- a/lib/laminas/laminas-mail/src/Transport/SmtpOptions.php +++ /dev/null @@ -1,203 +0,0 @@ -<?php - -namespace Laminas\Mail\Transport; - -use Laminas\Mail\Exception; -use Laminas\Stdlib\AbstractOptions; - -class SmtpOptions extends AbstractOptions -{ - /** - * @var string Local client hostname - */ - protected $name = 'localhost'; - - /** - * @var string - */ - protected $connectionClass = 'smtp'; - - /** - * Connection configuration (passed to the underlying Protocol class) - * - * @var array - */ - protected $connectionConfig = []; - - /** - * @var string Remote SMTP hostname or IP - */ - protected $host = '127.0.0.1'; - - /** - * @var int - */ - protected $port = 25; - - /** - * The timeout in seconds for the SMTP connection - * (Use null to disable it) - * - * @var int|null - */ - protected $connectionTimeLimit; - - /** - * Return the local client hostname - * - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * Set the local client hostname or IP - * - * @todo hostname/IP validation - * @param string $name - * @throws \Laminas\Mail\Exception\InvalidArgumentException - * @return SmtpOptions - */ - public function setName($name) - { - if (! is_string($name) && $name !== null) { - throw new Exception\InvalidArgumentException(sprintf( - 'Name must be a string or null; argument of type "%s" provided', - (is_object($name) ? get_class($name) : gettype($name)) - )); - } - $this->name = $name; - return $this; - } - - /** - * Get connection class - * - * This should be either the class Laminas\Mail\Protocol\Smtp or a class - * extending it -- typically a class in the Laminas\Mail\Protocol\Smtp\Auth - * namespace. - * - * @return string - */ - public function getConnectionClass() - { - return $this->connectionClass; - } - - /** - * Set connection class - * - * @param string $connectionClass the value to be set - * @throws \Laminas\Mail\Exception\InvalidArgumentException - * @return SmtpOptions - */ - public function setConnectionClass($connectionClass) - { - if (! is_string($connectionClass) && $connectionClass !== null) { - throw new Exception\InvalidArgumentException(sprintf( - 'Connection class must be a string or null; argument of type "%s" provided', - (is_object($connectionClass) ? get_class($connectionClass) : gettype($connectionClass)) - )); - } - $this->connectionClass = $connectionClass; - return $this; - } - - /** - * Get connection configuration array - * - * @return array - */ - public function getConnectionConfig() - { - return $this->connectionConfig; - } - - /** - * Set connection configuration array - * - * @param array $connectionConfig - * @return SmtpOptions - */ - public function setConnectionConfig(array $connectionConfig) - { - $this->connectionConfig = $connectionConfig; - return $this; - } - - /** - * Get the host name - * - * @return string - */ - public function getHost() - { - return $this->host; - } - - /** - * Set the SMTP host - * - * @todo hostname/IP validation - * @param string $host - * @return SmtpOptions - */ - public function setHost($host) - { - $this->host = (string) $host; - return $this; - } - - /** - * Get the port the SMTP server runs on - * - * @return int - */ - public function getPort() - { - return $this->port; - } - - /** - * Set the port the SMTP server runs on - * - * @param int $port - * @throws \Laminas\Mail\Exception\InvalidArgumentException - * @return SmtpOptions - */ - public function setPort($port) - { - $port = (int) $port; - if ($port < 1) { - throw new Exception\InvalidArgumentException(sprintf( - 'Port must be greater than 1; received "%d"', - $port - )); - } - $this->port = $port; - return $this; - } - - /** - * @return int|null - */ - public function getConnectionTimeLimit() - { - return $this->connectionTimeLimit; - } - - /** - * @param int|null $seconds - * @return self - */ - public function setConnectionTimeLimit($seconds) - { - $this->connectionTimeLimit = $seconds === null - ? null - : (int) $seconds; - - return $this; - } -} diff --git a/lib/laminas/laminas-mail/src/Transport/TransportInterface.php b/lib/laminas/laminas-mail/src/Transport/TransportInterface.php deleted file mode 100644 index 274d44e40..000000000 --- a/lib/laminas/laminas-mail/src/Transport/TransportInterface.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -namespace Laminas\Mail\Transport; - -use Laminas\Mail; - -/** - * Interface for mail transports - */ -interface TransportInterface -{ - /** - * Send a mail message - * - * @param \Laminas\Mail\Message $message - * @return - */ - public function send(Mail\Message $message); -} diff --git a/lib/laminas/laminas-mime/.laminas-ci.json b/lib/laminas/laminas-mime/.laminas-ci.json deleted file mode 100644 index bce3fa21b..000000000 --- a/lib/laminas/laminas-mime/.laminas-ci.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "ignore_php_platform_requirements": { - "8.1": true - } -} diff --git a/lib/laminas/laminas-mime/COPYRIGHT.md b/lib/laminas/laminas-mime/COPYRIGHT.md deleted file mode 100644 index 0a8cccc06..000000000 --- a/lib/laminas/laminas-mime/COPYRIGHT.md +++ /dev/null @@ -1 +0,0 @@ -Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/) diff --git a/lib/laminas/laminas-mime/LICENSE.md b/lib/laminas/laminas-mime/LICENSE.md deleted file mode 100644 index 10b40f142..000000000 --- a/lib/laminas/laminas-mime/LICENSE.md +++ /dev/null @@ -1,26 +0,0 @@ -Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -- Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -- Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -- Neither the name of Laminas Foundation nor the names of its contributors may - be used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/lib/laminas/laminas-mime/README.md b/lib/laminas/laminas-mime/README.md deleted file mode 100644 index a16037792..000000000 --- a/lib/laminas/laminas-mime/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# laminas-mime - -> This package is considered feature-complete, and is now in **security-only** maintenance mode, following a [decision by the Technical Steering Committee](https://github.com/laminas/technical-steering-committee/blob/2b55453e172a1b8c9c4c212be7cf7e7a58b9352c/meetings/minutes/2020-08-03-TSC-Minutes.md#vote-on-components-to-mark-as-security-only). -> If you have a security issue, please [follow our security reporting guidelines](https://getlaminas.org/security/). -> If you wish to take on the role of maintainer, please [nominate yourself](https://github.com/laminas/technical-steering-committee/issues/new?assignees=&labels=Nomination&template=Maintainer_Nomination.md&title=%5BNOMINATION%5D%5BMAINTAINER%5D%3A+%7Bname+of+person+being+nominated%7D) -> -> If you are looking for an actively maintained package alternative, we recommend: -> -> - [symfony/mime](https://symfony.com/doc/current/components/mime.html) - -[![Build Status](https://github.com/laminas/laminas-mime/workflows/Continuous%20Integration/badge.svg)](https://github.com/laminas/laminas-mime/actions?query=workflow%3A"Continuous+Integration") - -`Laminas\Mime` is a support class for handling multipart MIME messages. -It is used by `Laminas\Mail` and `Laminas\Mime\Message` and may be used by applications requiring MIME support. - -## Installation - -Run the following to install this library: - -```bash -$ composer require laminas/laminas-mime -``` - -## Documentation - -Browse the documentation online at https://docs.laminas.dev/laminas-mime/ - -## Support - -- [Issues](https://github.com/laminas/laminas-mime/issues/) -- [Chat](https://laminas.dev/chat/) -- [Forum](https://discourse.laminas.dev/) diff --git a/lib/laminas/laminas-mime/composer.json b/lib/laminas/laminas-mime/composer.json deleted file mode 100644 index abd18699a..000000000 --- a/lib/laminas/laminas-mime/composer.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "name": "laminas/laminas-mime", - "description": "Create and parse MIME messages and parts", - "license": "BSD-3-Clause", - "keywords": [ - "laminas", - "mime" - ], - "homepage": "https://laminas.dev", - "support": { - "docs": "https://docs.laminas.dev/laminas-mime/", - "issues": "https://github.com/laminas/laminas-mime/issues", - "source": "https://github.com/laminas/laminas-mime", - "rss": "https://github.com/laminas/laminas-mime/releases.atom", - "chat": "https://laminas.dev/chat", - "forum": "https://discourse.laminas.dev" - }, - "config": { - "sort-packages": true - }, - "require": { - "php": "^7.3 || ~8.0.0 || ~8.1.0", - "laminas/laminas-stdlib": "^2.7 || ^3.0" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~2.2.1", - "laminas/laminas-mail": "^2.12", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "laminas/laminas-mail": "Laminas\\Mail component" - }, - "autoload": { - "psr-4": { - "Laminas\\Mime\\": "src/" - } - }, - "autoload-dev": { - "files": [ - "test/TestAsset/Mail/Headers.php" - ], - "psr-4": { - "LaminasTest\\Mime\\": "test/" - } - }, - "scripts": { - "check": [ - "@cs-check", - "@test" - ], - "cs-check": "phpcs", - "cs-fix": "phpcbf", - "test": "phpunit --colors=always", - "test-coverage": "phpunit --colors=always --coverage-clover clover.xml" - }, - "conflict": { - "zendframework/zend-mime": "*" - } -} diff --git a/lib/laminas/laminas-mime/composer.lock b/lib/laminas/laminas-mime/composer.lock deleted file mode 100644 index aeeb2d372..000000000 --- a/lib/laminas/laminas-mime/composer.lock +++ /dev/null @@ -1,3023 +0,0 @@ -{ - "_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": "77a8daa5c98d4a651b4fab53280b68e4", - "packages": [ - { - "name": "laminas/laminas-stdlib", - "version": "3.6.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-stdlib.git", - "reference": "c53d8537f108fac3fae652677a19735db730ba46" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/c53d8537f108fac3fae652677a19735db730ba46", - "reference": "c53d8537f108fac3fae652677a19735db730ba46", - "shasum": "" - }, - "require": { - "php": "^7.3 || ~8.0.0 || ~8.1.0" - }, - "conflict": { - "zendframework/zend-stdlib": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~2.3.0", - "phpbench/phpbench": "^0.17.1", - "phpunit/phpunit": "~9.3.7", - "psalm/plugin-phpunit": "^0.16.0", - "vimeo/psalm": "^4.7" - }, - "type": "library", - "autoload": { - "psr-4": { - "Laminas\\Stdlib\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "SPL extensions, array utilities, error handlers, and more", - "homepage": "https://laminas.dev", - "keywords": [ - "laminas", - "stdlib" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-stdlib/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-stdlib/issues", - "rss": "https://github.com/laminas/laminas-stdlib/releases.atom", - "source": "https://github.com/laminas/laminas-stdlib" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2021-09-02T16:11:32+00:00" - } - ], - "packages-dev": [ - { - "name": "container-interop/container-interop", - "version": "1.2.0", - "source": { - "type": "git", - "url": "https://github.com/container-interop/container-interop.git", - "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8", - "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8", - "shasum": "" - }, - "require": { - "psr/container": "^1.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Interop\\Container\\": "src/Interop/Container/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", - "homepage": "https://github.com/container-interop/container-interop", - "support": { - "issues": "https://github.com/container-interop/container-interop/issues", - "source": "https://github.com/container-interop/container-interop/tree/master" - }, - "abandoned": "psr/container", - "time": "2017-02-14T19:40:03+00:00" - }, - { - "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "v0.7.1", - "source": { - "type": "git", - "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", - "reference": "fe390591e0241955f22eb9ba327d137e501c771c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/fe390591e0241955f22eb9ba327d137e501c771c", - "reference": "fe390591e0241955f22eb9ba327d137e501c771c", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.0 || ^2.0", - "php": ">=5.3", - "squizlabs/php_codesniffer": "^2.0 || ^3.0 || ^4.0" - }, - "require-dev": { - "composer/composer": "*", - "phpcompatibility/php-compatibility": "^9.0", - "sensiolabs/security-checker": "^4.1.0" - }, - "type": "composer-plugin", - "extra": { - "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" - }, - "autoload": { - "psr-4": { - "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Franck Nijhof", - "email": "franck.nijhof@dealerdirect.com", - "homepage": "http://www.frenck.nl", - "role": "Developer / IT Manager" - } - ], - "description": "PHP_CodeSniffer Standards Composer Installer Plugin", - "homepage": "http://www.dealerdirect.com", - "keywords": [ - "PHPCodeSniffer", - "PHP_CodeSniffer", - "code quality", - "codesniffer", - "composer", - "installer", - "phpcs", - "plugin", - "qa", - "quality", - "standard", - "standards", - "style guide", - "stylecheck", - "tests" - ], - "support": { - "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues", - "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer" - }, - "time": "2020-12-07T18:04:37+00:00" - }, - { - "name": "doctrine/instantiator", - "version": "1.4.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b", - "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^8.0", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^0.13 || 1.0.0-alpha2", - "phpstan/phpstan": "^0.12", - "phpstan/phpstan-phpunit": "^0.12", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.4.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" - } - ], - "time": "2020-11-10T18:47:58+00:00" - }, - { - "name": "laminas/laminas-coding-standard", - "version": "2.2.1", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-coding-standard.git", - "reference": "c953ecb1d37034f4aa326046e2c24a10fe0a2845" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-coding-standard/zipball/c953ecb1d37034f4aa326046e2c24a10fe0a2845", - "reference": "c953ecb1d37034f4aa326046e2c24a10fe0a2845", - "shasum": "" - }, - "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7", - "php": "^7.3 || ~8.0.0", - "slevomat/coding-standard": "^6.4.1", - "squizlabs/php_codesniffer": "^3.5.8", - "webimpress/coding-standard": "^1.1.6" - }, - "type": "phpcodesniffer-standard", - "autoload": { - "psr-4": { - "LaminasCodingStandard\\": "src/LaminasCodingStandard/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Laminas Coding Standard", - "homepage": "https://laminas.dev", - "keywords": [ - "Coding Standard", - "laminas" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-coding-standard/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-coding-standard/issues", - "rss": "https://github.com/laminas/laminas-coding-standard/releases.atom", - "source": "https://github.com/laminas/laminas-coding-standard" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2021-05-17T17:39:41+00:00" - }, - { - "name": "laminas/laminas-loader", - "version": "2.8.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-loader.git", - "reference": "d0589ec9dd48365fd95ad10d1c906efd7711c16b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-loader/zipball/d0589ec9dd48365fd95ad10d1c906efd7711c16b", - "reference": "d0589ec9dd48365fd95ad10d1c906efd7711c16b", - "shasum": "" - }, - "require": { - "php": "^7.3 || ~8.0.0 || ~8.1.0" - }, - "conflict": { - "zendframework/zend-loader": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~2.2.1", - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Laminas\\Loader\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Autoloading and plugin loading strategies", - "homepage": "https://laminas.dev", - "keywords": [ - "laminas", - "loader" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-loader/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-loader/issues", - "rss": "https://github.com/laminas/laminas-loader/releases.atom", - "source": "https://github.com/laminas/laminas-loader" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2021-09-02T18:30:53+00:00" - }, - { - "name": "laminas/laminas-mail", - "version": "2.14.1", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-mail.git", - "reference": "180c6c7baa37cba16fe9fd34af0f346e796cf1a1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-mail/zipball/180c6c7baa37cba16fe9fd34af0f346e796cf1a1", - "reference": "180c6c7baa37cba16fe9fd34af0f346e796cf1a1", - "shasum": "" - }, - "require": { - "ext-iconv": "*", - "laminas/laminas-loader": "^2.5", - "laminas/laminas-mime": "^2.5", - "laminas/laminas-stdlib": "^2.7 || ^3.0", - "laminas/laminas-validator": "^2.10.2", - "laminas/laminas-zendframework-bridge": "^1.0", - "php": "^7.3 || ~8.0.0", - "symfony/polyfill-mbstring": "^1.12.0", - "true/punycode": "^2.1" - }, - "replace": { - "zendframework/zend-mail": "^2.10.0" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~1.0.0", - "laminas/laminas-config": "^3.4", - "laminas/laminas-crypt": "^2.6 || ^3.0", - "laminas/laminas-servicemanager": "^3.2.1", - "phpunit/phpunit": "^9.3", - "psalm/plugin-phpunit": "^0.15.1", - "vimeo/psalm": "^4.7" - }, - "suggest": { - "laminas/laminas-crypt": "Crammd5 support in SMTP Auth", - "laminas/laminas-servicemanager": "^2.7.10 || ^3.3.1 when using SMTP to deliver messages" - }, - "type": "library", - "extra": { - "laminas": { - "component": "Laminas\\Mail", - "config-provider": "Laminas\\Mail\\ConfigProvider" - } - }, - "autoload": { - "psr-4": { - "Laminas\\Mail\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Provides generalized functionality to compose and send both text and MIME-compliant multipart e-mail messages", - "homepage": "https://laminas.dev", - "keywords": [ - "laminas", - "mail" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-mail/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-mail/issues", - "rss": "https://github.com/laminas/laminas-mail/releases.atom", - "source": "https://github.com/laminas/laminas-mail" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2021-05-20T04:00:23+00:00" - }, - { - "name": "laminas/laminas-validator", - "version": "2.14.5", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-validator.git", - "reference": "4680bc4241cb5b3ff78954c421fe43105ca413b7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-validator/zipball/4680bc4241cb5b3ff78954c421fe43105ca413b7", - "reference": "4680bc4241cb5b3ff78954c421fe43105ca413b7", - "shasum": "" - }, - "require": { - "container-interop/container-interop": "^1.1", - "laminas/laminas-stdlib": "^3.3", - "laminas/laminas-zendframework-bridge": "^1.0", - "php": "^7.3 || ~8.0.0" - }, - "replace": { - "zendframework/zend-validator": "^2.13.0" - }, - "require-dev": { - "laminas/laminas-cache": "^2.6.1", - "laminas/laminas-coding-standard": "~2.2.1", - "laminas/laminas-config": "^2.6", - "laminas/laminas-db": "^2.7", - "laminas/laminas-filter": "^2.6", - "laminas/laminas-http": "^2.14.2", - "laminas/laminas-i18n": "^2.6", - "laminas/laminas-math": "^2.6", - "laminas/laminas-servicemanager": "^2.7.11 || ^3.0.3", - "laminas/laminas-session": "^2.8", - "laminas/laminas-uri": "^2.7", - "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^9.3", - "psalm/plugin-phpunit": "^0.15.0", - "psr/http-client": "^1.0", - "psr/http-factory": "^1.0", - "psr/http-message": "^1.0", - "vimeo/psalm": "^4.3" - }, - "suggest": { - "laminas/laminas-db": "Laminas\\Db component, required by the (No)RecordExists validator", - "laminas/laminas-filter": "Laminas\\Filter component, required by the Digits validator", - "laminas/laminas-i18n": "Laminas\\I18n component to allow translation of validation error messages", - "laminas/laminas-i18n-resources": "Translations of validator messages", - "laminas/laminas-math": "Laminas\\Math component, required by the Csrf validator", - "laminas/laminas-servicemanager": "Laminas\\ServiceManager component to allow using the ValidatorPluginManager and validator chains", - "laminas/laminas-session": "Laminas\\Session component, ^2.8; required by the Csrf validator", - "laminas/laminas-uri": "Laminas\\Uri component, required by the Uri and Sitemap\\Loc validators", - "psr/http-message": "psr/http-message, required when validating PSR-7 UploadedFileInterface instances via the Upload and UploadFile validators" - }, - "type": "library", - "extra": { - "laminas": { - "component": "Laminas\\Validator", - "config-provider": "Laminas\\Validator\\ConfigProvider" - } - }, - "autoload": { - "psr-4": { - "Laminas\\Validator\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Validation classes for a wide range of domains, and the ability to chain validators to create complex validation criteria", - "homepage": "https://laminas.dev", - "keywords": [ - "laminas", - "validator" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-validator/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-validator/issues", - "rss": "https://github.com/laminas/laminas-validator/releases.atom", - "source": "https://github.com/laminas/laminas-validator" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2021-07-14T13:59:23+00:00" - }, - { - "name": "laminas/laminas-zendframework-bridge", - "version": "1.3.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-zendframework-bridge.git", - "reference": "13af2502d9bb6f7d33be2de4b51fb68c6cdb476e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/13af2502d9bb6f7d33be2de4b51fb68c6cdb476e", - "reference": "13af2502d9bb6f7d33be2de4b51fb68c6cdb476e", - "shasum": "" - }, - "require": { - "php": "^7.3 || ^8.0" - }, - "require-dev": { - "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.1 || ^9.3", - "psalm/plugin-phpunit": "^0.15.1", - "squizlabs/php_codesniffer": "^3.5", - "vimeo/psalm": "^4.6" - }, - "type": "library", - "extra": { - "laminas": { - "module": "Laminas\\ZendFrameworkBridge" - } - }, - "autoload": { - "files": [ - "src/autoload.php" - ], - "psr-4": { - "Laminas\\ZendFrameworkBridge\\": "src//" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Alias legacy ZF class names to Laminas Project equivalents.", - "keywords": [ - "ZendFramework", - "autoloading", - "laminas", - "zf" - ], - "support": { - "forum": "https://discourse.laminas.dev/", - "issues": "https://github.com/laminas/laminas-zendframework-bridge/issues", - "rss": "https://github.com/laminas/laminas-zendframework-bridge/releases.atom", - "source": "https://github.com/laminas/laminas-zendframework-bridge" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2021-06-24T12:49:22+00:00" - }, - { - "name": "myclabs/deep-copy", - "version": "1.10.2", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "replace": { - "myclabs/deep-copy": "self.version" - }, - "require-dev": { - "doctrine/collections": "^1.0", - "doctrine/common": "^2.6", - "phpunit/phpunit": "^7.1" - }, - "type": "library", - "autoload": { - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - }, - "files": [ - "src/DeepCopy/deep_copy.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.10.2" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2020-11-13T09:40:50+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v4.12.0", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "6608f01670c3cc5079e18c1dab1104e002579143" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/6608f01670c3cc5079e18c1dab1104e002579143", - "reference": "6608f01670c3cc5079e18c1dab1104e002579143", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=7.0" - }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.9-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.12.0" - }, - "time": "2021-07-21T10:44:31+00:00" - }, - { - "name": "phar-io/manifest", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.3" - }, - "time": "2021-07-20T11:28:43+00:00" - }, - { - "name": "phar-io/version", - "version": "3.1.0", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "bae7c545bef187884426f042434e561ab1ddb182" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/bae7c545bef187884426f042434e561ab1ddb182", - "reference": "bae7c545bef187884426f042434e561ab1ddb182", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.1.0" - }, - "time": "2021-02-23T14:00:09+00:00" - }, - { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" - }, - "time": "2020-06-27T09:03:43+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "5.2.2", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556", - "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556", - "shasum": "" - }, - "require": { - "ext-filter": "*", - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", - "webmozart/assert": "^1.9.1" - }, - "require-dev": { - "mockery/mockery": "~1.3.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - }, - { - "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/master" - }, - "time": "2020-09-03T19:13:55+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.4.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", - "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.0" - }, - "require-dev": { - "ext-tokenizer": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.4.0" - }, - "time": "2020-09-17T18:55:26+00:00" - }, - { - "name": "phpspec/prophecy", - "version": "1.13.0", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "be1996ed8adc35c3fd795488a653f4b518be70ea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/be1996ed8adc35c3fd795488a653f4b518be70ea", - "reference": "be1996ed8adc35c3fd795488a653f4b518be70ea", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.2", - "php": "^7.2 || ~8.0, <8.1", - "phpdocumentor/reflection-docblock": "^5.2", - "sebastian/comparator": "^3.0 || ^4.0", - "sebastian/recursion-context": "^3.0 || ^4.0" - }, - "require-dev": { - "phpspec/phpspec": "^6.0", - "phpunit/phpunit": "^8.0 || ^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.11.x-dev" - } - }, - "autoload": { - "psr-4": { - "Prophecy\\": "src/Prophecy" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" - } - ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "support": { - "issues": "https://github.com/phpspec/prophecy/issues", - "source": "https://github.com/phpspec/prophecy/tree/1.13.0" - }, - "time": "2021-03-17T13:42:18+00:00" - }, - { - "name": "phpstan/phpdoc-parser", - "version": "0.4.9", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "98a088b17966bdf6ee25c8a4b634df313d8aa531" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/98a088b17966bdf6ee25c8a4b634df313d8aa531", - "reference": "98a088b17966bdf6ee25c8a4b634df313d8aa531", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "consistence/coding-standard": "^3.5", - "ergebnis/composer-normalize": "^2.0.2", - "jakub-onderka/php-parallel-lint": "^0.9.2", - "phing/phing": "^2.16.0", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^0.12.26", - "phpstan/phpstan-strict-rules": "^0.12", - "phpunit/phpunit": "^6.3", - "slevomat/coding-standard": "^4.7.2", - "symfony/process": "^4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.4-dev" - } - }, - "autoload": { - "psr-4": { - "PHPStan\\PhpDocParser\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPDoc parser with support for nullable, intersection and generic types", - "support": { - "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/master" - }, - "time": "2020-08-03T20:32:43+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "9.2.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "f6293e1b30a2354e8428e004689671b83871edde" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f6293e1b30a2354e8428e004689671b83871edde", - "reference": "f6293e1b30a2354e8428e004689671b83871edde", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^4.10.2", - "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.3", - "phpunit/php-text-template": "^2.0.2", - "sebastian/code-unit-reverse-lookup": "^2.0.2", - "sebastian/complexity": "^2.0", - "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0.3", - "sebastian/version": "^3.0.1", - "theseer/tokenizer": "^1.2.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcov": "*", - "ext-xdebug": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-03-28T07:26:59+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "3.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/aa4be8575f26070b100fccb67faabb28f21f66f8", - "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:57:25+00:00" - }, - { - "name": "phpunit/php-invoker", - "version": "3.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:58:55+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T05:33:50+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "5.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:16:10+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "9.5.9", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "ea8c2dfb1065eb35a79b3681eee6e6fb0a6f273b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ea8c2dfb1065eb35a79b3681eee6e6fb0a6f273b", - "reference": "ea8c2dfb1065eb35a79b3681eee6e6fb0a6f273b", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.3.1", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", - "php": ">=7.3", - "phpspec/prophecy": "^1.12.1", - "phpunit/php-code-coverage": "^9.2.3", - "phpunit/php-file-iterator": "^3.0.5", - "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.5", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.3", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^2.3.4", - "sebastian/version": "^3.0.2" - }, - "require-dev": { - "ext-pdo": "*", - "phpspec/prophecy-phpunit": "^2.0.1" - }, - "suggest": { - "ext-soap": "*", - "ext-xdebug": "*" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.5-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ], - "files": [ - "src/Framework/Assert/Functions.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.9" - }, - "funding": [ - { - "url": "https://phpunit.de/donate.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-08-31T06:47:40+00:00" - }, - { - "name": "psr/container", - "version": "1.1.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", - "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", - "shasum": "" - }, - "require": { - "php": ">=7.2.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.1" - }, - "time": "2021-03-05T17:36:06+00:00" - }, - { - "name": "sebastian/cli-parser", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", - "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:08:49+00:00" - }, - { - "name": "sebastian/code-unit", - "version": "1.0.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:08:54+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:30:19+00:00" - }, - { - "name": "sebastian/comparator", - "version": "4.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T15:49:45+00:00" - }, - { - "name": "sebastian/complexity", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.7", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", - "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T15:52:27+00:00" - }, - { - "name": "sebastian/diff", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/process": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:10:38+00:00" - }, - { - "name": "sebastian/environment", - "version": "5.1.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "388b6ced16caa751030f6a69e588299fa09200ac" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/388b6ced16caa751030f6a69e588299fa09200ac", - "reference": "388b6ced16caa751030f6a69e588299fa09200ac", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-posix": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:52:38+00:00" - }, - { - "name": "sebastian/exporter", - "version": "4.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/d89cc98761b8cb5a1a235a6b703ae50d34080e65", - "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:24:23+00:00" - }, - { - "name": "sebastian/global-state", - "version": "5.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/23bd5951f7ff26f12d4e3242864df3e08dec4e49", - "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-06-11T13:31:12+00:00" - }, - { - "name": "sebastian/lines-of-code", - "version": "1.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.6", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", - "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-28T06:42:11+00:00" - }, - { - "name": "sebastian/object-enumerator", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:12:34+00:00" - }, - { - "name": "sebastian/object-reflector", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:14:26+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:17:30+00:00" - }, - { - "name": "sebastian/resource-operations", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:45:17+00:00" - }, - { - "name": "sebastian/type", - "version": "2.3.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b8cd8a1c753c90bc1a0f5372170e3e489136f914", - "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", - "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/2.3.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-06-15T12:49:02+00:00" - }, - { - "name": "sebastian/version", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:39:44+00:00" - }, - { - "name": "slevomat/coding-standard", - "version": "6.4.1", - "source": { - "type": "git", - "url": "https://github.com/slevomat/coding-standard.git", - "reference": "696dcca217d0c9da2c40d02731526c1e25b65346" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/696dcca217d0c9da2c40d02731526c1e25b65346", - "reference": "696dcca217d0c9da2c40d02731526c1e25b65346", - "shasum": "" - }, - "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7", - "php": "^7.1 || ^8.0", - "phpstan/phpdoc-parser": "0.4.5 - 0.4.9", - "squizlabs/php_codesniffer": "^3.5.6" - }, - "require-dev": { - "phing/phing": "2.16.3", - "php-parallel-lint/php-parallel-lint": "1.2.0", - "phpstan/phpstan": "0.12.48", - "phpstan/phpstan-deprecation-rules": "0.12.5", - "phpstan/phpstan-phpunit": "0.12.16", - "phpstan/phpstan-strict-rules": "0.12.5", - "phpunit/phpunit": "7.5.20|8.5.5|9.4.0" - }, - "type": "phpcodesniffer-standard", - "extra": { - "branch-alias": { - "dev-master": "6.x-dev" - } - }, - "autoload": { - "psr-4": { - "SlevomatCodingStandard\\": "SlevomatCodingStandard" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", - "support": { - "issues": "https://github.com/slevomat/coding-standard/issues", - "source": "https://github.com/slevomat/coding-standard/tree/6.4.1" - }, - "funding": [ - { - "url": "https://github.com/kukulich", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard", - "type": "tidelift" - } - ], - "time": "2020-10-05T12:39:37+00:00" - }, - { - "name": "squizlabs/php_codesniffer", - "version": "3.6.0", - "source": { - "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ffced0d2c8fa8e6cdc4d695a743271fab6c38625", - "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" - }, - "bin": [ - "bin/phpcs", - "bin/phpcbf" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Greg Sherwood", - "role": "lead" - } - ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", - "keywords": [ - "phpcs", - "standards" - ], - "support": { - "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", - "source": "https://github.com/squizlabs/PHP_CodeSniffer", - "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" - }, - "time": "2021-04-09T00:54:41+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.23.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce", - "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "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.23.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": "2021-02-19T12:13:01+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.23.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9174a3d80210dca8daa7f31fec659150bbeabfc6", - "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.1" - }, - "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": "2021-05-27T12:26:48+00:00" - }, - { - "name": "theseer/tokenizer", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.1" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2021-07-28T10:34:58+00:00" - }, - { - "name": "true/punycode", - "version": "v2.1.1", - "source": { - "type": "git", - "url": "https://github.com/true/php-punycode.git", - "reference": "a4d0c11a36dd7f4e7cd7096076cab6d3378a071e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/true/php-punycode/zipball/a4d0c11a36dd7f4e7cd7096076cab6d3378a071e", - "reference": "a4d0c11a36dd7f4e7cd7096076cab6d3378a071e", - "shasum": "" - }, - "require": { - "php": ">=5.3.0", - "symfony/polyfill-mbstring": "^1.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.7", - "squizlabs/php_codesniffer": "~2.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "TrueBV\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Renan Gonçalves", - "email": "renan.saddam@gmail.com" - } - ], - "description": "A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)", - "homepage": "https://github.com/true/php-punycode", - "keywords": [ - "idna", - "punycode" - ], - "support": { - "issues": "https://github.com/true/php-punycode/issues", - "source": "https://github.com/true/php-punycode/tree/master" - }, - "time": "2016-11-16T10:37:54+00:00" - }, - { - "name": "webimpress/coding-standard", - "version": "1.2.2", - "source": { - "type": "git", - "url": "https://github.com/webimpress/coding-standard.git", - "reference": "8f4a220de33f471a8101836f7ec72b852c3f9f03" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webimpress/coding-standard/zipball/8f4a220de33f471a8101836f7ec72b852c3f9f03", - "reference": "8f4a220de33f471a8101836f7ec72b852c3f9f03", - "shasum": "" - }, - "require": { - "php": "^7.3 || ^8.0", - "squizlabs/php_codesniffer": "^3.6" - }, - "require-dev": { - "phpunit/phpunit": "^9.5.4" - }, - "type": "phpcodesniffer-standard", - "extra": { - "dev-master": "1.2.x-dev", - "dev-develop": "1.3.x-dev" - }, - "autoload": { - "psr-4": { - "WebimpressCodingStandard\\": "src/WebimpressCodingStandard/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "description": "Webimpress Coding Standard", - "keywords": [ - "Coding Standard", - "PSR-2", - "phpcs", - "psr-12", - "webimpress" - ], - "support": { - "issues": "https://github.com/webimpress/coding-standard/issues", - "source": "https://github.com/webimpress/coding-standard/tree/1.2.2" - }, - "funding": [ - { - "url": "https://github.com/michalbundyra", - "type": "github" - } - ], - "time": "2021-04-12T12:51:27+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.10.0", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25", - "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.10.0" - }, - "time": "2021-03-09T10:59:23+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": "^7.3 || ~8.0.0 || ~8.1.0" - }, - "platform-dev": [], - "plugin-api-version": "2.0.0" -} diff --git a/lib/laminas/laminas-mime/phpcs.xml.dist b/lib/laminas/laminas-mime/phpcs.xml.dist deleted file mode 100644 index 7f391d80a..000000000 --- a/lib/laminas/laminas-mime/phpcs.xml.dist +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0"?> -<ruleset - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="./vendor/squizlabs/php_codesniffer/phpcs.xsd"> - - <arg name="basepath" value="."/> - <arg name="cache" value=".phpcs-cache"/> - <arg name="colors"/> - <arg name="extensions" value="php"/> - <arg name="parallel" value="80"/> - - <!-- Show progress --> - <arg value="p"/> - - <!-- Paths to check --> - <file>src</file> - <file>test</file> - - <!-- Include all rules from Laminas Coding Standard --> - <rule ref="LaminasCodingStandard"/> -</ruleset> diff --git a/lib/laminas/laminas-mime/src/Decode.php b/lib/laminas/laminas-mime/src/Decode.php deleted file mode 100644 index 5afdeab2d..000000000 --- a/lib/laminas/laminas-mime/src/Decode.php +++ /dev/null @@ -1,240 +0,0 @@ -<?php // phpcs:disable WebimpressCodingStandard.NamingConventions.ValidVariableName.NotCamelCaps - -namespace Laminas\Mime; - -use Laminas\Mail\Headers; -use Laminas\Stdlib\ErrorHandler; - -use function count; -use function explode; -use function iconv_mime_decode; -use function preg_match; -use function preg_match_all; -use function preg_split; -use function str_replace; -use function strcasecmp; -use function strlen; -use function strpos; -use function strtok; -use function strtolower; -use function substr; - -use const E_NOTICE; -use const E_WARNING; -use const ICONV_MIME_DECODE_CONTINUE_ON_ERROR; - -class Decode -{ - /** - * Explode MIME multipart string into separate parts - * - * Parts consist of the header and the body of each MIME part. - * - * @param string $body raw body of message - * @param string $boundary boundary as found in content-type - * @return array parts with content of each part, empty if no parts found - * @throws Exception\RuntimeException - */ - public static function splitMime($body, $boundary) - { - // TODO: we're ignoring \r for now - is this function fast enough and is it safe to assume noone needs \r? - $body = str_replace("\r", '', $body); - - $start = 0; - $res = []; - // find every mime part limiter and cut out the - // string before it. - // the part before the first boundary string is discarded: - $p = strpos($body, '--' . $boundary . "\n", $start); - if ($p === false) { - // no parts found! - return []; - } - - // position after first boundary line - $start = $p + 3 + strlen($boundary); - - while (($p = strpos($body, '--' . $boundary . "\n", $start)) !== false) { - $res[] = substr($body, $start, $p - $start); - $start = $p + 3 + strlen($boundary); - } - - // no more parts, find end boundary - $p = strpos($body, '--' . $boundary . '--', $start); - if ($p === false) { - throw new Exception\RuntimeException('Not a valid Mime Message: End Missing'); - } - - // the remaining part also needs to be parsed: - $res[] = substr($body, $start, $p - $start); - return $res; - } - - /** - * decodes a mime encoded String and returns a - * struct of parts with header and body - * - * @param string $message raw message content - * @param string $boundary boundary as found in content-type - * @param string $EOL EOL string; defaults to {@link Laminas\Mime\Mime::LINEEND} - * @return array|null parts as array('header' => array(name => value), 'body' => content), null if no parts found - * @throws Exception\RuntimeException - */ - public static function splitMessageStruct($message, $boundary, $EOL = Mime::LINEEND) - { - $parts = static::splitMime($message, $boundary); - if (! $parts) { - return; - } - $result = []; - $headers = null; // "Declare" variable before the first usage "for reading" - $body = null; // "Declare" variable before the first usage "for reading" - foreach ($parts as $part) { - static::splitMessage($part, $headers, $body, $EOL); - $result[] = [ - 'header' => $headers, - 'body' => $body, - ]; - } - return $result; - } - - /** - * split a message in header and body part, if no header or an - * invalid header is found $headers is empty - * - * The charset of the returned headers depend on your iconv settings. - * - * @param string|Headers $message raw message with header and optional content - * @param Headers $headers output param, headers container - * @param string $body output param, content of message - * @param string $EOL EOL string; defaults to {@link Laminas\Mime\Mime::LINEEND} - * @param bool $strict enable strict mode for parsing message - * @return null - */ - public static function splitMessage($message, &$headers, &$body, $EOL = Mime::LINEEND, $strict = false) - { - if ($message instanceof Headers) { - $message = $message->toString(); - } - // check for valid header at first line - $firstlinePos = strpos($message, "\n"); - $firstline = $firstlinePos === false ? $message : substr($message, 0, $firstlinePos); - if (! preg_match('%^[^\s]+[^:]*:%', $firstline)) { - $headers = new Headers(); - // TODO: we're ignoring \r for now - is this function fast enough and is it safe to assume noone needs \r? - $body = str_replace(["\r", "\n"], ['', $EOL], $message); - return; - } - - // see @Laminas-372, pops the first line off a message if it doesn't contain a header - if (! $strict) { - $parts = explode(':', $firstline, 2); - if (count($parts) !== 2) { - $message = substr($message, strpos($message, $EOL) + 1); - } - } - - // @todo splitMime removes "\r" sequences, which breaks valid mime - // messages as returned by many mail servers - $headersEOL = $EOL; - - // find an empty line between headers and body - // default is set new line - // @todo Maybe this is too much "magic"; we should be more strict here - if (strpos($message, $EOL . $EOL)) { - [$headers, $body] = explode($EOL . $EOL, $message, 2); - // next is the standard new line - } elseif ($EOL !== "\r\n" && strpos($message, "\r\n\r\n")) { - [$headers, $body] = explode("\r\n\r\n", $message, 2); - $headersEOL = "\r\n"; // Headers::fromString will fail with incorrect EOL - // next is the other "standard" new line - } elseif ($EOL !== "\n" && strpos($message, "\n\n")) { - [$headers, $body] = explode("\n\n", $message, 2); - $headersEOL = "\n"; - // at last resort find anything that looks like a new line - } else { - ErrorHandler::start(E_NOTICE | E_WARNING); - [$headers, $body] = preg_split("%([\r\n]+)\\1%U", $message, 2); - ErrorHandler::stop(); - } - - $headers = Headers::fromString($headers, $headersEOL); - } - - /** - * split a content type in its different parts - * - * @param string $type content-type - * @param string $wantedPart the wanted part, else an array with all parts is returned - * @return string|array wanted part or all parts as array('type' => content-type, partname => value) - */ - public static function splitContentType($type, $wantedPart = null) - { - return static::splitHeaderField($type, $wantedPart, 'type'); - } - - /** - * split a header field like content type in its different parts - * - * @param string $field header field - * @param string $wantedPart the wanted part, else an array with all parts is returned - * @param string $firstName key name for the first part - * @return string|array wanted part or all parts as array($firstName => firstPart, partname => value) - * @throws Exception\RuntimeException - */ - public static function splitHeaderField($field, $wantedPart = null, $firstName = '0') - { - $wantedPart = strtolower($wantedPart ?? ''); - $firstName = strtolower($firstName); - - // special case - a bit optimized - if ($firstName === $wantedPart) { - $field = strtok($field, ';'); - return $field[0] === '"' ? substr($field, 1, -1) : $field; - } - - $field = $firstName . '=' . $field; - if (! preg_match_all('%([^=\s]+)\s*=\s*("[^"]+"|[^;]+)(;\s*|$)%', $field, $matches)) { - throw new Exception\RuntimeException('not a valid header field'); - } - - if ($wantedPart) { - foreach ($matches[1] as $key => $name) { - if (strcasecmp($name, $wantedPart)) { - continue; - } - if ($matches[2][$key][0] !== '"') { - return $matches[2][$key]; - } - return substr($matches[2][$key], 1, -1); - } - return; - } - - $split = []; - foreach ($matches[1] as $key => $name) { - $name = strtolower($name); - if ($matches[2][$key][0] === '"') { - $split[$name] = substr($matches[2][$key], 1, -1); - } else { - $split[$name] = $matches[2][$key]; - } - } - - return $split; - } - - /** - * decode a quoted printable encoded string - * - * The charset of the returned string depends on your iconv settings. - * - * @param string $string encoded string - * @return string decoded string - */ - public static function decodeQuotedPrintable($string) - { - return iconv_mime_decode($string, ICONV_MIME_DECODE_CONTINUE_ON_ERROR, 'UTF-8'); - } -} diff --git a/lib/laminas/laminas-mime/src/Exception/ExceptionInterface.php b/lib/laminas/laminas-mime/src/Exception/ExceptionInterface.php deleted file mode 100644 index 762e2c007..000000000 --- a/lib/laminas/laminas-mime/src/Exception/ExceptionInterface.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace Laminas\Mime\Exception; - -interface ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-mime/src/Exception/InvalidArgumentException.php b/lib/laminas/laminas-mime/src/Exception/InvalidArgumentException.php deleted file mode 100644 index b50408f47..000000000 --- a/lib/laminas/laminas-mime/src/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,8 +0,0 @@ -<?php - -namespace Laminas\Mime\Exception; - -class InvalidArgumentException extends \InvalidArgumentException implements - ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-mime/src/Exception/RuntimeException.php b/lib/laminas/laminas-mime/src/Exception/RuntimeException.php deleted file mode 100644 index 42ce7f9c4..000000000 --- a/lib/laminas/laminas-mime/src/Exception/RuntimeException.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php - -namespace Laminas\Mime\Exception; - -/** - * Exception for Laminas\Mime component. - */ -class RuntimeException extends \RuntimeException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-mime/src/Message.php b/lib/laminas/laminas-mime/src/Message.php deleted file mode 100644 index 80cc8fb9c..000000000 --- a/lib/laminas/laminas-mime/src/Message.php +++ /dev/null @@ -1,321 +0,0 @@ -<?php // phpcs:disable WebimpressCodingStandard.NamingConventions.ValidVariableName.NotCamelCaps,PSR12.Files.FileHeader.SpacingAfterBlock,PSR2.Methods.MethodDeclaration.Underscore - -namespace Laminas\Mime; - -use Laminas\Mail\Header\HeaderInterface; -use Laminas\Mime\Mime; -use Laminas\Mime\Part; - -use function array_keys; -use function base64_decode; -use function count; -use function current; -use function quoted_printable_decode; -use function sprintf; -use function strlen; -use function strpos; -use function strtolower; -use function substr; -use function trim; - -class Message -{ - /** @var Part[] */ - protected $parts = []; - - /** @var null|Mime */ - protected $mime; - - /** - * Returns the list of all Laminas\Mime\Part in the message - * - * @return Part[] - */ - public function getParts() - { - return $this->parts; - } - - /** - * Sets the given array of Laminas\Mime\Part as the array for the message - * - * @param array $parts - * @return self - */ - public function setParts($parts) - { - $this->parts = $parts; - return $this; - } - - /** - * Append a new Laminas\Mime\Part to the current message - * - * @throws Exception\InvalidArgumentException - * @return self - */ - public function addPart(Part $part) - { - foreach ($this->getParts() as $row) { - if ($part === $row) { - throw new Exception\InvalidArgumentException(sprintf( - 'Provided part %s already defined.', - $part->getId() - )); - } - } - - $this->parts[] = $part; - return $this; - } - - /** - * Check if message needs to be sent as multipart - * MIME message or if it has only one part. - * - * @return bool - */ - public function isMultiPart() - { - return count($this->parts) > 1; - } - - /** - * Set Laminas\Mime\Mime object for the message - * - * This can be used to set the boundary specifically or to use a subclass of - * Laminas\Mime for generating the boundary. - * - * @return self - */ - public function setMime(Mime $mime) - { - $this->mime = $mime; - return $this; - } - - /** - * Returns the Laminas\Mime\Mime object in use by the message - * - * If the object was not present, it is created and returned. Can be used to - * determine the boundary used in this message. - * - * @return Mime - */ - public function getMime() - { - if ($this->mime === null) { - $this->mime = new Mime(); - } - - return $this->mime; - } - - /** - * Generate MIME-compliant message from the current configuration - * - * This can be a multipart message if more than one MIME part was added. If - * only one part is present, the content of this part is returned. If no - * part had been added, an empty string is returned. - * - * Parts are separated by the mime boundary as defined in Laminas\Mime\Mime. If - * {@link setMime()} has been called before this method, the Laminas\Mime\Mime - * object set by this call will be used. Otherwise, a new Laminas\Mime\Mime object - * is generated and used. - * - * @param string $EOL EOL string; defaults to {@link Laminas\Mime\Mime::LINEEND} - * @return string - */ - public function generateMessage($EOL = Mime::LINEEND) - { - if (! $this->isMultiPart()) { - if (empty($this->parts)) { - return ''; - } - $part = current($this->parts); - $body = $part->getContent($EOL); - } else { - $mime = $this->getMime(); - - $boundaryLine = $mime->boundaryLine($EOL); - $body = 'This is a message in Mime Format. If you see this, ' - . "your mail reader does not support this format." . $EOL; - - foreach (array_keys($this->parts) as $p) { - $body .= $boundaryLine - . $this->getPartHeaders($p, $EOL) - . $EOL - . $this->getPartContent($p, $EOL); - } - - $body .= $mime->mimeEnd($EOL); - } - - return trim($body); - } - - /** - * Get the headers of a given part as an array - * - * @param int $partnum - * @return array - */ - public function getPartHeadersArray($partnum) - { - return $this->parts[$partnum]->getHeadersArray(); - } - - /** - * Get the headers of a given part as a string - * - * @param int $partnum - * @param string $EOL - * @return string - */ - public function getPartHeaders($partnum, $EOL = Mime::LINEEND) - { - return $this->parts[$partnum]->getHeaders($EOL); - } - - /** - * Get the (encoded) content of a given part as a string - * - * @param int $partnum - * @param string $EOL - * @return string - */ - public function getPartContent($partnum, $EOL = Mime::LINEEND) - { - return $this->parts[$partnum]->getContent($EOL); - } - - /** - * Explode MIME multipart string into separate parts - * - * Parts consist of the header and the body of each MIME part. - * - * @param string $body - * @param string $boundary - * @throws Exception\RuntimeException - * @return array - */ - protected static function _disassembleMime($body, $boundary) - { - $start = 0; - $res = []; - // find every mime part limiter and cut out the - // string before it. - // the part before the first boundary string is discarded: - $p = strpos($body, '--' . $boundary . "\n", $start); - if ($p === false) { - // no parts found! - return []; - } - - // position after first boundary line - $start = $p + 3 + strlen($boundary); - - while (($p = strpos($body, '--' . $boundary . "\n", $start)) !== false) { - $res[] = substr($body, $start, $p - $start); - $start = $p + 3 + strlen($boundary); - } - - // no more parts, find end boundary - $p = strpos($body, '--' . $boundary . '--', $start); - if ($p === false) { - throw new Exception\RuntimeException('Not a valid Mime Message: End Missing'); - } - - // the remaining part also needs to be parsed: - $res[] = substr($body, $start, $p - $start); - return $res; - } - - /** - * Decodes a MIME encoded string and returns a Laminas\Mime\Message object with - * all the MIME parts set according to the given string - * - * @param string $message - * @param string $boundary Multipart boundary; if omitted, $message will be - * treated as a single part. - * @param string $EOL EOL string; defaults to {@link Laminas\Mime\Mime::LINEEND} - * @throws Exception\RuntimeException - * @return Message - */ - public static function createFromMessage($message, $boundary = null, $EOL = Mime::LINEEND) - { - if ($boundary) { - $parts = Decode::splitMessageStruct($message, $boundary, $EOL); - } else { - Decode::splitMessage($message, $headers, $body, $EOL); - $parts = [ - [ - 'header' => $headers, - 'body' => $body, - ], - ]; - } - - $res = new static(); - foreach ($parts as $part) { - // now we build a new MimePart for the current Message Part: - $properties = []; - foreach ($part['header'] as $header) { - /** @var HeaderInterface $header */ - /** - * @todo check for characterset and filename - */ - - $fieldName = $header->getFieldName(); - $fieldValue = $header->getFieldValue(); - switch (strtolower($fieldName)) { - case 'content-type': - $properties['type'] = $fieldValue; - break; - case 'content-transfer-encoding': - $properties['encoding'] = $fieldValue; - break; - case 'content-id': - $properties['id'] = trim($fieldValue, '<>'); - break; - case 'content-disposition': - $properties['disposition'] = $fieldValue; - break; - case 'content-description': - $properties['description'] = $fieldValue; - break; - case 'content-location': - $properties['location'] = $fieldValue; - break; - case 'content-language': - $properties['language'] = $fieldValue; - break; - default: - // Ignore unknown header - break; - } - } - - $body = $part['body']; - - if (isset($properties['encoding'])) { - switch ($properties['encoding']) { - case 'quoted-printable': - $body = quoted_printable_decode($body); - break; - case 'base64': - $body = base64_decode($body); - break; - } - } - - $newPart = new Part($body); - foreach ($properties as $key => $value) { - $newPart->$key = $value; - } - $res->addPart($newPart); - } - - return $res; - } -} diff --git a/lib/laminas/laminas-mime/src/Mime.php b/lib/laminas/laminas-mime/src/Mime.php deleted file mode 100644 index 70f08fa08..000000000 --- a/lib/laminas/laminas-mime/src/Mime.php +++ /dev/null @@ -1,709 +0,0 @@ -<?php - -namespace Laminas\Mime; - -use function base64_encode; -use function chunk_split; -use function count; -use function implode; -use function max; -use function md5; -use function microtime; -use function ord; -use function preg_match; -use function rtrim; -use function sprintf; -use function str_replace; -use function strcspn; -use function strlen; -use function strpos; -use function strrpos; -use function strtoupper; -use function substr; -use function substr_replace; -use function trim; - -/** - * Support class for MultiPart Mime Messages - */ -class Mime -{ - // phpcs:disable Generic.Files.LineLength.TooLong - public const TYPE_OCTETSTREAM = 'application/octet-stream'; - public const TYPE_TEXT = 'text/plain'; - public const TYPE_HTML = 'text/html'; - public const TYPE_ENRICHED = 'text/enriched'; - public const TYPE_XML = 'text/xml'; - public const ENCODING_7BIT = '7bit'; - public const ENCODING_8BIT = '8bit'; - public const ENCODING_QUOTEDPRINTABLE = 'quoted-printable'; - public const ENCODING_BASE64 = 'base64'; - public const DISPOSITION_ATTACHMENT = 'attachment'; - public const DISPOSITION_INLINE = 'inline'; - public const LINELENGTH = 72; - public const LINEEND = "\n"; - public const MULTIPART_ALTERNATIVE = 'multipart/alternative'; - public const MULTIPART_MIXED = 'multipart/mixed'; - public const MULTIPART_RELATED = 'multipart/related'; - public const MULTIPART_RELATIVE = 'multipart/relative'; - public const MULTIPART_REPORT = 'multipart/report'; - public const MESSAGE_RFC822 = 'message/rfc822'; - public const MESSAGE_DELIVERY_STATUS = 'message/delivery-status'; - public const CHARSET_REGEX = '#=\?(?P<charset>[\x21\x23-\x26\x2a\x2b\x2d\x5e\5f\60\x7b-\x7ea-zA-Z0-9]+)\?(?P<encoding>[\x21\x23-\x26\x2a\x2b\x2d\x5e\5f\60\x7b-\x7ea-zA-Z0-9]+)\?(?P<text>[\x21-\x3e\x40-\x7e]+)#'; - // phpcs:enable - - /** @var null|string */ - protected $boundary; - - /** @var int */ - protected static $makeUnique = 0; - - /** - * Lookup-tables for QuotedPrintable - * - * @var string[] - */ - public static $qpKeys = [ - "\x00", - "\x01", - "\x02", - "\x03", - "\x04", - "\x05", - "\x06", - "\x07", - "\x08", - "\x09", - "\x0A", - "\x0B", - "\x0C", - "\x0D", - "\x0E", - "\x0F", - "\x10", - "\x11", - "\x12", - "\x13", - "\x14", - "\x15", - "\x16", - "\x17", - "\x18", - "\x19", - "\x1A", - "\x1B", - "\x1C", - "\x1D", - "\x1E", - "\x1F", - "\x7F", - "\x80", - "\x81", - "\x82", - "\x83", - "\x84", - "\x85", - "\x86", - "\x87", - "\x88", - "\x89", - "\x8A", - "\x8B", - "\x8C", - "\x8D", - "\x8E", - "\x8F", - "\x90", - "\x91", - "\x92", - "\x93", - "\x94", - "\x95", - "\x96", - "\x97", - "\x98", - "\x99", - "\x9A", - "\x9B", - "\x9C", - "\x9D", - "\x9E", - "\x9F", - "\xA0", - "\xA1", - "\xA2", - "\xA3", - "\xA4", - "\xA5", - "\xA6", - "\xA7", - "\xA8", - "\xA9", - "\xAA", - "\xAB", - "\xAC", - "\xAD", - "\xAE", - "\xAF", - "\xB0", - "\xB1", - "\xB2", - "\xB3", - "\xB4", - "\xB5", - "\xB6", - "\xB7", - "\xB8", - "\xB9", - "\xBA", - "\xBB", - "\xBC", - "\xBD", - "\xBE", - "\xBF", - "\xC0", - "\xC1", - "\xC2", - "\xC3", - "\xC4", - "\xC5", - "\xC6", - "\xC7", - "\xC8", - "\xC9", - "\xCA", - "\xCB", - "\xCC", - "\xCD", - "\xCE", - "\xCF", - "\xD0", - "\xD1", - "\xD2", - "\xD3", - "\xD4", - "\xD5", - "\xD6", - "\xD7", - "\xD8", - "\xD9", - "\xDA", - "\xDB", - "\xDC", - "\xDD", - "\xDE", - "\xDF", - "\xE0", - "\xE1", - "\xE2", - "\xE3", - "\xE4", - "\xE5", - "\xE6", - "\xE7", - "\xE8", - "\xE9", - "\xEA", - "\xEB", - "\xEC", - "\xED", - "\xEE", - "\xEF", - "\xF0", - "\xF1", - "\xF2", - "\xF3", - "\xF4", - "\xF5", - "\xF6", - "\xF7", - "\xF8", - "\xF9", - "\xFA", - "\xFB", - "\xFC", - "\xFD", - "\xFE", - "\xFF", - ]; - - /** @var string[] */ - public static $qpReplaceValues = [ - "=00", - "=01", - "=02", - "=03", - "=04", - "=05", - "=06", - "=07", - "=08", - "=09", - "=0A", - "=0B", - "=0C", - "=0D", - "=0E", - "=0F", - "=10", - "=11", - "=12", - "=13", - "=14", - "=15", - "=16", - "=17", - "=18", - "=19", - "=1A", - "=1B", - "=1C", - "=1D", - "=1E", - "=1F", - "=7F", - "=80", - "=81", - "=82", - "=83", - "=84", - "=85", - "=86", - "=87", - "=88", - "=89", - "=8A", - "=8B", - "=8C", - "=8D", - "=8E", - "=8F", - "=90", - "=91", - "=92", - "=93", - "=94", - "=95", - "=96", - "=97", - "=98", - "=99", - "=9A", - "=9B", - "=9C", - "=9D", - "=9E", - "=9F", - "=A0", - "=A1", - "=A2", - "=A3", - "=A4", - "=A5", - "=A6", - "=A7", - "=A8", - "=A9", - "=AA", - "=AB", - "=AC", - "=AD", - "=AE", - "=AF", - "=B0", - "=B1", - "=B2", - "=B3", - "=B4", - "=B5", - "=B6", - "=B7", - "=B8", - "=B9", - "=BA", - "=BB", - "=BC", - "=BD", - "=BE", - "=BF", - "=C0", - "=C1", - "=C2", - "=C3", - "=C4", - "=C5", - "=C6", - "=C7", - "=C8", - "=C9", - "=CA", - "=CB", - "=CC", - "=CD", - "=CE", - "=CF", - "=D0", - "=D1", - "=D2", - "=D3", - "=D4", - "=D5", - "=D6", - "=D7", - "=D8", - "=D9", - "=DA", - "=DB", - "=DC", - "=DD", - "=DE", - "=DF", - "=E0", - "=E1", - "=E2", - "=E3", - "=E4", - "=E5", - "=E6", - "=E7", - "=E8", - "=E9", - "=EA", - "=EB", - "=EC", - "=ED", - "=EE", - "=EF", - "=F0", - "=F1", - "=F2", - "=F3", - "=F4", - "=F5", - "=F6", - "=F7", - "=F8", - "=F9", - "=FA", - "=FB", - "=FC", - "=FD", - "=FE", - "=FF", - ]; - // @codingStandardsIgnoreStart - public static $qpKeysString = - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"; - // @codingStandardsIgnoreEnd - - /** - * Check if the given string is "printable" - * - * Checks that a string contains no unprintable characters. If this returns - * false, encode the string for secure delivery. - * - * @param string $str - * @return bool - */ - public static function isPrintable($str) - { - return strcspn($str, static::$qpKeysString) === strlen($str); - } - - /** - * Encode a given string with the QUOTED_PRINTABLE mechanism and wrap the lines. - * - * @param string $str - * @param int $lineLength Defaults to {@link LINELENGTH} - * @param string $lineEnd Defaults to {@link LINEEND} - * @return string - */ - public static function encodeQuotedPrintable( - $str, - $lineLength = self::LINELENGTH, - $lineEnd = self::LINEEND - ) { - $out = ''; - $str = self::_encodeQuotedPrintable($str); - - // Split encoded text into separate lines - $initialPtr = 0; - $strLength = strlen($str); - while ($initialPtr < $strLength) { - $continueAt = $strLength - $initialPtr; - - if ($continueAt > $lineLength) { - $continueAt = $lineLength; - } - - $chunk = substr($str, $initialPtr, $continueAt); - - // Ensure we are not splitting across an encoded character - $endingMarkerPos = strrpos($chunk, '='); - if ($endingMarkerPos !== false && $endingMarkerPos >= strlen($chunk) - 2) { - $chunk = substr($chunk, 0, $endingMarkerPos); - $continueAt = $endingMarkerPos; - } - - if (ord($chunk[0]) === 0x2E) { // 0x2E is a dot - $chunk = '=2E' . substr($chunk, 1); - } - - // copied from swiftmailer https://git.io/vAXU1 - switch (ord(substr($chunk, strlen($chunk) - 1))) { - case 0x09: // Horizontal Tab - $chunk = substr_replace($chunk, '=09', strlen($chunk) - 1, 1); - break; - case 0x20: // Space - $chunk = substr_replace($chunk, '=20', strlen($chunk) - 1, 1); - break; - } - - // Add string and continue - $out .= $chunk . '=' . $lineEnd; - $initialPtr += $continueAt; - } - - $out = rtrim($out, $lineEnd); - $out = rtrim($out, '='); - return $out; - } - - /** - * Converts a string into quoted printable format. - * - * @param string $str - * @return string - */ - // @codingStandardsIgnoreStart - private static function _encodeQuotedPrintable($str) - { - // @codingStandardsIgnoreEnd - $str = str_replace('=', '=3D', $str); - $str = str_replace(static::$qpKeys, static::$qpReplaceValues, $str); - $str = rtrim($str); - return $str; - } - - /** - * Encode a given string with the QUOTED_PRINTABLE mechanism for Mail Headers. - * - * Mail headers depend on an extended quoted printable algorithm otherwise - * a range of bugs can occur. - * - * @param string $str - * @param string $charset - * @param int $lineLength Defaults to {@link LINELENGTH} - * @param string $lineEnd Defaults to {@link LINEEND} - * @return string - */ - public static function encodeQuotedPrintableHeader( - $str, - $charset, - $lineLength = self::LINELENGTH, - $lineEnd = self::LINEEND - ) { - // Reduce line-length by the length of the required delimiter, charsets and encoding - $prefix = sprintf('=?%s?Q?', $charset); - $lineLength = $lineLength - strlen($prefix) - 3; - - $str = self::_encodeQuotedPrintable($str); - - // Mail-Header required chars have to be encoded also: - $str = str_replace(['?', ',', ' ', '_'], ['=3F', '=2C', '=20', '=5F'], $str); - - // initialize first line, we need it anyways - $lines = [0 => '']; - - // Split encoded text into separate lines - $tmp = ''; - while (strlen($str) > 0) { - $currentLine = max(count($lines) - 1, 0); - $token = static::getNextQuotedPrintableToken($str); - $substr = substr($str, strlen($token)); - $str = false === $substr ? '' : $substr; - - $tmp .= $token; - if ($token === '=20') { - // only if we have a single char token or space, we can append the - // tempstring it to the current line or start a new line if necessary. - $lineLimitReached = strlen($lines[$currentLine] . $tmp) > $lineLength; - $noCurrentLine = $lines[$currentLine] === ''; - if ($noCurrentLine && $lineLimitReached) { - $lines[$currentLine] = $tmp; - $lines[$currentLine + 1] = ''; - } elseif ($lineLimitReached) { - $lines[$currentLine + 1] = $tmp; - } else { - $lines[$currentLine] .= $tmp; - } - $tmp = ''; - } - // don't forget to append the rest to the last line - if (strlen($str) === 0) { - $lines[$currentLine] .= $tmp; - } - } - - // assemble the lines together by pre- and appending delimiters, charset, encoding. - for ($i = 0, $count = count($lines); $i < $count; $i++) { - $lines[$i] = " " . $prefix . $lines[$i] . "?="; - } - $str = trim(implode($lineEnd, $lines)); - return $str; - } - - /** - * Retrieves the first token from a quoted printable string. - * - * @param string $str - * @return string - */ - private static function getNextQuotedPrintableToken($str) - { - if (0 === strpos($str, '=')) { - $token = substr($str, 0, 3); - } else { - $token = substr($str, 0, 1); - } - return $token; - } - - /** - * Encode a given string in mail header compatible base64 encoding. - * - * @param string $str - * @param string $charset - * @param int $lineLength Defaults to {@link LINELENGTH} - * @param string $lineEnd Defaults to {@link LINEEND} - * @return string - */ - public static function encodeBase64Header( - $str, - $charset, - $lineLength = self::LINELENGTH, - $lineEnd = self::LINEEND - ) { - $prefix = '=?' . $charset . '?B?'; - $suffix = '?='; - $remainingLength = $lineLength - strlen($prefix) - strlen($suffix); - - $encodedValue = static::encodeBase64($str, $remainingLength, $lineEnd); - $encodedValue = str_replace($lineEnd, $suffix . $lineEnd . ' ' . $prefix, $encodedValue); - $encodedValue = $prefix . $encodedValue . $suffix; - return $encodedValue; - } - - /** - * Encode a given string in base64 encoding and break lines - * according to the maximum linelength. - * - * @param string $str - * @param int $lineLength Defaults to {@link LINELENGTH} - * @param string $lineEnd Defaults to {@link LINEEND} - * @return string - */ - public static function encodeBase64( - $str, - $lineLength = self::LINELENGTH, - $lineEnd = self::LINEEND - ) { - $lineLength = $lineLength - ($lineLength % 4); - return rtrim(chunk_split(base64_encode($str), $lineLength, $lineEnd)); - } - - /** - * Constructor - * - * @param null|string $boundary - * @access public - */ - public function __construct($boundary = null) - { - // This string needs to be somewhat unique - if ($boundary === null) { - $this->boundary = '=_' . md5(microtime(1) . static::$makeUnique++); - } else { - $this->boundary = $boundary; - } - } - - // phpcs:disable WebimpressCodingStandard.NamingConventions.ValidVariableName.NotCamelCaps - - /** - * Encode the given string with the given encoding. - * - * @param string $str - * @param string $encoding - * @param string $EOL EOL string; defaults to {@link LINEEND} - * @return string - */ - public static function encode($str, $encoding, $EOL = self::LINEEND) - { - switch ($encoding) { - case self::ENCODING_BASE64: - return static::encodeBase64($str, self::LINELENGTH, $EOL); - - case self::ENCODING_QUOTEDPRINTABLE: - return static::encodeQuotedPrintable($str, self::LINELENGTH, $EOL); - - default: - /** - * @todo 7Bit and 8Bit is currently handled the same way. - */ - return $str; - } - } - - /** - * Return a MIME boundary - * - * @access public - * @return string - */ - public function boundary() - { - return $this->boundary; - } - - /** - * Return a MIME boundary line - * - * @param string $EOL Defaults to {@link LINEEND} - * @access public - * @return string - */ - public function boundaryLine($EOL = self::LINEEND) - { - return $EOL . '--' . $this->boundary . $EOL; - } - - /** - * Return MIME ending - * - * @param string $EOL Defaults to {@link LINEEND} - * @access public - * @return string - */ - public function mimeEnd($EOL = self::LINEEND) - { - return $EOL . '--' . $this->boundary . '--' . $EOL; - } - - /** - * Detect MIME charset - * - * Extract parts according to https://tools.ietf.org/html/rfc2047#section-2 - * - * @param string $str - * @return string - */ - public static function mimeDetectCharset($str) - { - if (preg_match(self::CHARSET_REGEX, $str, $matches)) { - return strtoupper($matches['charset']); - } - - return 'ASCII'; - } -} diff --git a/lib/laminas/laminas-mime/src/Part.php b/lib/laminas/laminas-mime/src/Part.php deleted file mode 100644 index 541da9c0f..000000000 --- a/lib/laminas/laminas-mime/src/Part.php +++ /dev/null @@ -1,549 +0,0 @@ -<?php - -namespace Laminas\Mime; - -use function array_key_exists; -use function get_class; -use function gettype; -use function is_object; -use function is_resource; -use function is_string; -use function rewind; -use function sprintf; -use function stream_filter_append; -use function stream_filter_remove; -use function stream_get_contents; -use function stream_get_meta_data; - -use const STREAM_FILTER_READ; - -/** - * Class representing a MIME part. - */ -class Part -{ - /** @var string */ - public $type = Mime::TYPE_OCTETSTREAM; - - /** @var string */ - public $encoding = Mime::ENCODING_8BIT; - - /** @var null|string */ - public $id; - - /** @var null|string */ - public $disposition; - - /** @var null|string */ - public $filename; - - /** @var null|string */ - public $description; - - /** @var null|string */ - public $charset; - - /** @var null|string */ - public $boundary; - - /** @var null|string */ - public $location; - - /** @var null|string */ - public $language; - - /** - * String or stream containing the content - * - * @var string|resource - */ - protected $content; - - /** @var bool */ - protected $isStream = false; - - /** @var array<array-key, resource> */ - protected $filters = []; - - /** - * create a new Mime Part. - * The (unencoded) content of the Part as passed - * as a string or stream - * - * @param mixed $content String or Stream containing the content - * @throws Exception\InvalidArgumentException - */ - public function __construct($content = '') - { - $this->setContent($content); - } - - /** - * @todo error checking for setting $type - * @todo error checking for setting $encoding - */ - - /** - * Set type - * - * @param string $type - * @return self - */ - public function setType($type = Mime::TYPE_OCTETSTREAM) - { - $this->type = $type; - return $this; - } - - /** - * Get type - * - * @return string - */ - public function getType() - { - return $this->type; - } - - /** - * Set encoding - * - * @param string $encoding - * @return self - */ - public function setEncoding($encoding = Mime::ENCODING_8BIT) - { - $this->encoding = $encoding; - return $this; - } - - /** - * Get encoding - * - * @return string - */ - public function getEncoding() - { - return $this->encoding; - } - - /** - * Set id - * - * @param string $id - * @return self - */ - public function setId($id) - { - $this->id = $id; - return $this; - } - - /** - * Get id - * - * @return string - */ - public function getId() - { - return $this->id; - } - - /** - * Set disposition - * - * @param string $disposition - * @return self - */ - public function setDisposition($disposition) - { - $this->disposition = $disposition; - return $this; - } - - /** - * Get disposition - * - * @return string - */ - public function getDisposition() - { - return $this->disposition; - } - - /** - * Set description - * - * @param string $description - * @return self - */ - public function setDescription($description) - { - $this->description = $description; - return $this; - } - - /** - * Get description - * - * @return string - */ - public function getDescription() - { - return $this->description; - } - - /** - * Set filename - * - * @param string $fileName - * @return self - */ - public function setFileName($fileName) - { - $this->filename = $fileName; - return $this; - } - - /** - * Get filename - * - * @return string - */ - public function getFileName() - { - return $this->filename; - } - - /** - * Set charset - * - * @param string $charset - * @return self - */ - public function setCharset($charset) - { - $this->charset = $charset; - return $this; - } - - /** - * Get charset - * - * @return string - */ - public function getCharset() - { - return $this->charset; - } - - /** - * Set boundary - * - * @param string $boundary - * @return self - */ - public function setBoundary($boundary) - { - $this->boundary = $boundary; - return $this; - } - - /** - * Get boundary - * - * @return string - */ - public function getBoundary() - { - return $this->boundary; - } - - /** - * Set location - * - * @param string $location - * @return self - */ - public function setLocation($location) - { - $this->location = $location; - return $this; - } - - /** - * Get location - * - * @return string - */ - public function getLocation() - { - return $this->location; - } - - /** - * Set language - * - * @param string $language - * @return self - */ - public function setLanguage($language) - { - $this->language = $language; - return $this; - } - - /** - * Get language - * - * @return string - */ - public function getLanguage() - { - return $this->language; - } - - /** - * Set content - * - * @param mixed $content String or Stream containing the content - * @throws Exception\InvalidArgumentException - * @return self - */ - public function setContent($content) - { - if (! is_string($content) && ! is_resource($content)) { - throw new Exception\InvalidArgumentException(sprintf( - 'Content must be string or resource; received "%s"', - is_object($content) ? get_class($content) : gettype($content) - )); - } - $this->content = $content; - if (is_resource($content)) { - $this->isStream = true; - } - - return $this; - } - - /** - * Set isStream - * - * @param bool $isStream - * @return self - */ - public function setIsStream($isStream = false) - { - $this->isStream = (bool) $isStream; - return $this; - } - - /** - * Get isStream - * - * @return bool - */ - public function getIsStream() - { - return $this->isStream; - } - - /** - * Set filters - * - * @param array<array-key, resource> $filters - * @return self - */ - public function setFilters($filters = []) - { - $this->filters = $filters; - return $this; - } - - /** - * Get Filters - * - * @return array<array-key, resource> - */ - public function getFilters() - { - return $this->filters; - } - - /** - * check if this part can be read as a stream. - * if true, getEncodedStream can be called, otherwise - * only getContent can be used to fetch the encoded - * content of the part - * - * @return bool - */ - public function isStream() - { - return $this->isStream; - } - - // phpcs:disable WebimpressCodingStandard.NamingConventions.ValidVariableName.NotCamelCaps - - /** - * if this was created with a stream, return a filtered stream for - * reading the content. very useful for large file attachments. - * - * @param string $EOL - * @return resource - * @throws Exception\RuntimeException If not a stream or unable to append filter. - */ - public function getEncodedStream($EOL = Mime::LINEEND) - { - if (! $this->isStream) { - throw new Exception\RuntimeException('Attempt to get a stream from a string part'); - } - - //stream_filter_remove(); // ??? is that right? - switch ($this->encoding) { - case Mime::ENCODING_QUOTEDPRINTABLE: - if (array_key_exists(Mime::ENCODING_QUOTEDPRINTABLE, $this->filters)) { - stream_filter_remove($this->filters[Mime::ENCODING_QUOTEDPRINTABLE]); - } - $filter = stream_filter_append( - $this->content, - 'convert.quoted-printable-encode', - STREAM_FILTER_READ, - [ - 'line-length' => 76, - 'line-break-chars' => $EOL, - ] - ); - $this->filters[Mime::ENCODING_QUOTEDPRINTABLE] = $filter; - if (! is_resource($filter)) { - throw new Exception\RuntimeException('Failed to append quoted-printable filter'); - } - break; - case Mime::ENCODING_BASE64: - if (array_key_exists(Mime::ENCODING_BASE64, $this->filters)) { - stream_filter_remove($this->filters[Mime::ENCODING_BASE64]); - } - $filter = stream_filter_append( - $this->content, - 'convert.base64-encode', - STREAM_FILTER_READ, - [ - 'line-length' => 76, - 'line-break-chars' => $EOL, - ] - ); - $this->filters[Mime::ENCODING_BASE64] = $filter; - if (! is_resource($filter)) { - throw new Exception\RuntimeException('Failed to append base64 filter'); - } - break; - default: - } - return $this->content; - } - - /** - * Get the Content of the current Mime Part in the given encoding. - * - * @param string $EOL - * @return string - */ - public function getContent($EOL = Mime::LINEEND) - { - if ($this->isStream) { - $encodedStream = $this->getEncodedStream($EOL); - $encodedStreamContents = stream_get_contents($encodedStream); - $streamMetaData = stream_get_meta_data($encodedStream); - - if (isset($streamMetaData['seekable']) && $streamMetaData['seekable']) { - rewind($encodedStream); - } - - return $encodedStreamContents; - } - return Mime::encode($this->content, $this->encoding, $EOL); - } - - /** - * Get the RAW unencoded content from this part - * - * @return string - */ - public function getRawContent() - { - if ($this->isStream) { - return stream_get_contents($this->content); - } - return $this->content; - } - - /** - * Create and return the array of headers for this MIME part - * - * @access public - * @param string $EOL - * @return array - */ - public function getHeadersArray($EOL = Mime::LINEEND) - { - $headers = []; - - $contentType = $this->type; - if ($this->charset) { - $contentType .= '; charset=' . $this->charset; - } - - if ($this->boundary) { - $contentType .= ';' . $EOL - . " boundary=\"" . $this->boundary . '"'; - } - - $headers[] = ['Content-Type', $contentType]; - - if ($this->encoding) { - $headers[] = ['Content-Transfer-Encoding', $this->encoding]; - } - - if ($this->id) { - $headers[] = ['Content-ID', '<' . $this->id . '>']; - } - - if ($this->disposition) { - $disposition = $this->disposition; - if ($this->filename) { - $disposition .= '; filename="' . $this->filename . '"'; - } - $headers[] = ['Content-Disposition', $disposition]; - } - - if ($this->description) { - $headers[] = ['Content-Description', $this->description]; - } - - if ($this->location) { - $headers[] = ['Content-Location', $this->location]; - } - - if ($this->language) { - $headers[] = ['Content-Language', $this->language]; - } - - return $headers; - } - - /** - * Return the headers for this part as a string - * - * @param string $EOL - * @return String - */ - public function getHeaders($EOL = Mime::LINEEND) - { - $res = ''; - foreach ($this->getHeadersArray($EOL) as $header) { - $res .= $header[0] . ': ' . $header[1] . $EOL; - } - - return $res; - } -} diff --git a/lib/laminas/laminas-servicemanager/COPYRIGHT.md b/lib/laminas/laminas-servicemanager/COPYRIGHT.md deleted file mode 100644 index 0a8cccc06..000000000 --- a/lib/laminas/laminas-servicemanager/COPYRIGHT.md +++ /dev/null @@ -1 +0,0 @@ -Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/) diff --git a/lib/laminas/laminas-servicemanager/LICENSE.md b/lib/laminas/laminas-servicemanager/LICENSE.md deleted file mode 100644 index 10b40f142..000000000 --- a/lib/laminas/laminas-servicemanager/LICENSE.md +++ /dev/null @@ -1,26 +0,0 @@ -Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -- Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -- Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -- Neither the name of Laminas Foundation nor the names of its contributors may - be used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/lib/laminas/laminas-servicemanager/README.md b/lib/laminas/laminas-servicemanager/README.md deleted file mode 100644 index 794a34029..000000000 --- a/lib/laminas/laminas-servicemanager/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# laminas-servicemanager - -[![Build Status](https://github.com/laminas/laminas-servicemanager/actions/workflows/continuous-integration.yml/badge.svg)](https://github.com/laminas/laminas-servicemanager/actions/workflows/continuous-integration.yml) -[![Psalm coverage](https://shepherd.dev/github/laminas/laminas-servicemanager/coverage.svg?)](https://shepherd.dev/github/laminas/laminas-servicemanager) - -> ## 🇷🇺 Русским гражданам -> -> Мы, участники Laminas, родились и живем в разных странах. У многих из нас есть друзья, родственники и коллеги как в России, так и в Украине. Некоторые из нас родились в России. Некоторые из нас живут в России. У некоторых бабушки и дедушки сражались с фашистами во Второй мировой войне. Здесь никто не поддерживает фашизм. -> -> У одного из нас есть украинская родственница, которая спаслась из дома вместе с сыном. Поезд задержался из-за бомбежки на дороге впереди. У нас есть друзья, которые прячутся в бомбоубежищах. Мы с тревогой ждем весточки от них после воздушных налетов, которые беспорядочно наносят удары и попадают по больницам, школам, детским садам и домам. Мы не берем это из каких-либо СМИ. Мы наблюдаем это напрямую. -> -> Вы доверяете нам достаточно, чтоб использовать наши программы, и мы просим вас довериться нам вновь. Мы нуждаемся в помощи. Выходите и протестуйте против этой бесполезной войны. Остановите кровопролитие. Скажите "Нет войне!" -> -> ## 🇺🇸 To Citizens of Russia -> -> We at Laminas come from all over the world. Many of us have friends, family and colleagues in both Russia and Ukraine. Some of us were born in Russia. Some of us currently live in Russia. Some have grandparents who fought Nazis in World War II. Nobody here supports fascism. -> -> One team member has a Ukrainian relative who fled her home with her son. The train was delayed due to bombing on the road ahead. We have friends who are hiding in bomb shelters. We anxiously follow up on them after the air raids, which indiscriminately fire at hospitals, schools, kindergartens and houses. We're not taking this from any media. These are our actual experiences. -> -> You trust us enough to use our software. We ask that you trust us to say the truth on this. We need your help. Go out and protest this unnecessary war. Stop the bloodshed. Say "stop the war!" - -The Service Locator design pattern is implemented by the `Laminas\ServiceManager` -component. The Service Locator is a service/object locator, tasked with -retrieving other objects. - -- File issues at https://github.com/laminas/laminas-servicemanager/issues -- [Online documentation](https://docs.laminas.dev/laminas-servicemanager) -- [Documentation source files](docs/book/) - -## Benchmarks - -We provide scripts for benchmarking laminas-servicemanager using the -[PHPBench](https://github.com/phpbench/phpbench) framework; these can be -found in the `benchmarks/` directory. - -To execute the benchmarks you can run the following command: - -```bash -$ vendor/bin/phpbench run --report=aggregate -``` diff --git a/lib/laminas/laminas-servicemanager/bin/generate-deps-for-config-factory b/lib/laminas/laminas-servicemanager/bin/generate-deps-for-config-factory deleted file mode 100644 index 8ee1105a5..000000000 --- a/lib/laminas/laminas-servicemanager/bin/generate-deps-for-config-factory +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env php -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager; - -// Setup/verify autoloading -if (file_exists($a = getcwd() . '/vendor/autoload.php')) { - require $a; -} elseif (file_exists($a = __DIR__ . '/../../../autoload.php')) { - require $a; -} elseif (file_exists($a = __DIR__ . '/../vendor/autoload.php')) { - require $a; -} else { - fwrite(STDERR, 'Cannot locate autoloader; please run "composer install"' . PHP_EOL); - exit(1); -} - -$command = new Tool\ConfigDumperCommand($argv[0]); -$status = $command(array_slice($argv, 1)); -exit($status); diff --git a/lib/laminas/laminas-servicemanager/bin/generate-factory-for-class b/lib/laminas/laminas-servicemanager/bin/generate-factory-for-class deleted file mode 100644 index a02701429..000000000 --- a/lib/laminas/laminas-servicemanager/bin/generate-factory-for-class +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env php -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager; - -// Setup/verify autoloading -if (file_exists($a = getcwd() . '/vendor/autoload.php')) { - require $a; -} elseif (file_exists($a = __DIR__ . '/../../../autoload.php')) { - require $a; -} elseif (file_exists($a = __DIR__ . '/../vendor/autoload.php')) { - require $a; -} else { - fwrite(STDERR, 'Cannot locate autoloader; please run "composer install"' . PHP_EOL); - exit(1); -} - -$command = new Tool\FactoryCreatorCommand($argv[0]); -$status = $command(array_slice($argv, 1)); -exit($status); diff --git a/lib/laminas/laminas-servicemanager/composer.json b/lib/laminas/laminas-servicemanager/composer.json deleted file mode 100644 index 4b871714c..000000000 --- a/lib/laminas/laminas-servicemanager/composer.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "name": "laminas/laminas-servicemanager", - "description": "Factory-Driven Dependency Injection Container", - "license": "BSD-3-Clause", - "keywords": [ - "laminas", - "di", - "dic", - "dependency-injection", - "psr-11", - "servicemanager", - "service-manager" - ], - "homepage": "https://laminas.dev", - "support": { - "docs": "https://docs.laminas.dev/laminas-servicemanager/", - "issues": "https://github.com/laminas/laminas-servicemanager/issues", - "source": "https://github.com/laminas/laminas-servicemanager", - "rss": "https://github.com/laminas/laminas-servicemanager/releases.atom", - "chat": "https://laminas.dev/chat", - "forum": "https://discourse.laminas.dev" - }, - "config": { - "platform": { - "php": "7.4.99" - }, - "sort-packages": true, - "allow-plugins": { - "dealerdirect/phpcodesniffer-composer-installer": true, - "composer/package-versions-deprecated": true, - "laminas/laminas-dependency-plugin": true - } - }, - "require": { - "php": "~7.4.0 || ~8.0.0 || ~8.1.0", - "laminas/laminas-stdlib": "^3.2.1", - "psr/container": "^1.0" - }, - "require-dev": { - "composer/package-versions-deprecated": "^1.0", - "laminas/laminas-coding-standard": "~2.3.0", - "laminas/laminas-container-config-test": "^0.7", - "laminas/laminas-dependency-plugin": "^2.1.2", - "mikey179/vfsstream": "^1.6.10@alpha", - "ocramius/proxy-manager": "^2.11", - "phpbench/phpbench": "^1.1", - "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^9.5.5", - "psalm/plugin-phpunit": "^0.17.0", - "vimeo/psalm": "^4.8" - }, - "provide": { - "psr/container-implementation": "^1.0" - }, - "conflict": { - "ext-psr": "*", - "laminas/laminas-code": "<3.3.1", - "zendframework/zend-code": "<3.3.1", - "zendframework/zend-servicemanager": "*" - }, - "suggest": { - "ocramius/proxy-manager": "ProxyManager ^2.1.1 to handle lazy initialization of services" - }, - "autoload": { - "psr-4": { - "Laminas\\ServiceManager\\": "src/" - }, - "files": ["src/autoload.php"] - }, - "autoload-dev": { - "files": [ - "test/autoload.php" - ], - "psr-4": { - "LaminasTest\\ServiceManager\\": "test/", - "LaminasBench\\ServiceManager\\": "benchmarks/" - } - }, - "bin": [ - "bin/generate-deps-for-config-factory", - "bin/generate-factory-for-class" - ], - "scripts": { - "benchmark": "phpbench run --revs=2 --iterations=2 --report=aggregate", - "check": [ - "@cs-check", - "@test" - ], - "cs-check": "phpcs", - "cs-fix": "phpcbf", - "test": "phpunit --colors=always", - "test-coverage": "phpunit --colors=always --coverage-clover clover.xml", - "static-analysis" : "psalm --shepherd --stats" - }, - "replace": { - "container-interop/container-interop": "^1.2.0" - } -} diff --git a/lib/laminas/laminas-servicemanager/composer.lock b/lib/laminas/laminas-servicemanager/composer.lock deleted file mode 100644 index fb4bb89ff..000000000 --- a/lib/laminas/laminas-servicemanager/composer.lock +++ /dev/null @@ -1,5437 +0,0 @@ -{ - "_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": "1eb3f9333785fbf2e89342f2052837c0", - "packages": [ - { - "name": "laminas/laminas-stdlib", - "version": "3.10.1", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-stdlib.git", - "reference": "0d669074845fc80a99add0f64025192f143ef836" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/0d669074845fc80a99add0f64025192f143ef836", - "reference": "0d669074845fc80a99add0f64025192f143ef836", - "shasum": "" - }, - "require": { - "php": "^7.3 || ~8.0.0 || ~8.1.0" - }, - "conflict": { - "zendframework/zend-stdlib": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~2.3.0", - "phpbench/phpbench": "^1.0", - "phpunit/phpunit": "^9.3.7", - "psalm/plugin-phpunit": "^0.16.0", - "vimeo/psalm": "^4.7" - }, - "type": "library", - "autoload": { - "psr-4": { - "Laminas\\Stdlib\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "SPL extensions, array utilities, error handlers, and more", - "homepage": "https://laminas.dev", - "keywords": [ - "laminas", - "stdlib" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-stdlib/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-stdlib/issues", - "rss": "https://github.com/laminas/laminas-stdlib/releases.atom", - "source": "https://github.com/laminas/laminas-stdlib" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2022-06-10T14:49:09+00:00" - }, - { - "name": "psr/container", - "version": "1.1.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.2" - }, - "time": "2021-11-05T16:50:12+00:00" - } - ], - "packages-dev": [ - { - "name": "amphp/amp", - "version": "v2.6.2", - "source": { - "type": "git", - "url": "https://github.com/amphp/amp.git", - "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/amp/zipball/9d5100cebffa729aaffecd3ad25dc5aeea4f13bb", - "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1", - "ext-json": "*", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^7 | ^8 | ^9", - "psalm/phar": "^3.11@dev", - "react/promise": "^2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "files": [ - "lib/functions.php", - "lib/Internal/functions.php" - ], - "psr-4": { - "Amp\\": "lib" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Bob Weinand", - "email": "bobwei9@hotmail.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "A non-blocking concurrency framework for PHP applications.", - "homepage": "https://amphp.org/amp", - "keywords": [ - "async", - "asynchronous", - "awaitable", - "concurrency", - "event", - "event-loop", - "future", - "non-blocking", - "promise" - ], - "support": { - "irc": "irc://irc.freenode.org/amphp", - "issues": "https://github.com/amphp/amp/issues", - "source": "https://github.com/amphp/amp/tree/v2.6.2" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2022-02-20T17:52:18+00:00" - }, - { - "name": "amphp/byte-stream", - "version": "v1.8.1", - "source": { - "type": "git", - "url": "https://github.com/amphp/byte-stream.git", - "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/byte-stream/zipball/acbd8002b3536485c997c4e019206b3f10ca15bd", - "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd", - "shasum": "" - }, - "require": { - "amphp/amp": "^2", - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1.4", - "friendsofphp/php-cs-fixer": "^2.3", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^6 || ^7 || ^8", - "psalm/phar": "^3.11.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "files": [ - "lib/functions.php" - ], - "psr-4": { - "Amp\\ByteStream\\": "lib" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "A stream abstraction to make working with non-blocking I/O simple.", - "homepage": "http://amphp.org/byte-stream", - "keywords": [ - "amp", - "amphp", - "async", - "io", - "non-blocking", - "stream" - ], - "support": { - "irc": "irc://irc.freenode.org/amphp", - "issues": "https://github.com/amphp/byte-stream/issues", - "source": "https://github.com/amphp/byte-stream/tree/v1.8.1" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2021-03-30T17:13:30+00:00" - }, - { - "name": "composer/package-versions-deprecated", - "version": "1.11.99.5", - "source": { - "type": "git", - "url": "https://github.com/composer/package-versions-deprecated.git", - "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/b4f54f74ef3453349c24a845d22392cd31e65f1d", - "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.1.0 || ^2.0", - "php": "^7 || ^8" - }, - "replace": { - "ocramius/package-versions": "1.11.99" - }, - "require-dev": { - "composer/composer": "^1.9.3 || ^2.0@dev", - "ext-zip": "^1.13", - "phpunit/phpunit": "^6.5 || ^7" - }, - "type": "composer-plugin", - "extra": { - "class": "PackageVersions\\Installer", - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "PackageVersions\\": "src/PackageVersions" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be" - } - ], - "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", - "support": { - "issues": "https://github.com/composer/package-versions-deprecated/issues", - "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.5" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-01-17T14:14:24+00:00" - }, - { - "name": "composer/pcre", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/composer/pcre.git", - "reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/e300eb6c535192decd27a85bc72a9290f0d6b3bd", - "reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.3", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Pcre\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "PCRE wrapping library that offers type-safe preg_* replacements.", - "keywords": [ - "PCRE", - "preg", - "regex", - "regular expression" - ], - "support": { - "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.0.0" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-02-25T20:21:48+00:00" - }, - { - "name": "composer/semver", - "version": "3.3.2", - "source": { - "type": "git", - "url": "https://github.com/composer/semver.git", - "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9", - "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.4", - "symfony/phpunit-bridge": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Semver\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - }, - { - "name": "Rob Bast", - "email": "rob.bast@gmail.com", - "homepage": "http://robbast.nl" - } - ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", - "keywords": [ - "semantic", - "semver", - "validation", - "versioning" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.3.2" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-04-01T19:23:25+00:00" - }, - { - "name": "composer/xdebug-handler", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "ced299686f41dce890debac69273b47ffe98a40c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c", - "reference": "ced299686f41dce890debac69273b47ffe98a40c", - "shasum": "" - }, - "require": { - "composer/pcre": "^1 || ^2 || ^3", - "php": "^7.2.5 || ^8.0", - "psr/log": "^1 || ^2 || ^3" - }, - "require-dev": { - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without Xdebug.", - "keywords": [ - "Xdebug", - "performance" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/3.0.3" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-02-25T21:32:43+00:00" - }, - { - "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "v0.7.2", - "source": { - "type": "git", - "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", - "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", - "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.0 || ^2.0", - "php": ">=5.3", - "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" - }, - "require-dev": { - "composer/composer": "*", - "php-parallel-lint/php-parallel-lint": "^1.3.1", - "phpcompatibility/php-compatibility": "^9.0" - }, - "type": "composer-plugin", - "extra": { - "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" - }, - "autoload": { - "psr-4": { - "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Franck Nijhof", - "email": "franck.nijhof@dealerdirect.com", - "homepage": "http://www.frenck.nl", - "role": "Developer / IT Manager" - }, - { - "name": "Contributors", - "homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors" - } - ], - "description": "PHP_CodeSniffer Standards Composer Installer Plugin", - "homepage": "http://www.dealerdirect.com", - "keywords": [ - "PHPCodeSniffer", - "PHP_CodeSniffer", - "code quality", - "codesniffer", - "composer", - "installer", - "phpcbf", - "phpcs", - "plugin", - "qa", - "quality", - "standard", - "standards", - "style guide", - "stylecheck", - "tests" - ], - "support": { - "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues", - "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer" - }, - "time": "2022-02-04T12:51:07+00:00" - }, - { - "name": "dnoegel/php-xdg-base-dir", - "version": "v0.1.1", - "source": { - "type": "git", - "url": "https://github.com/dnoegel/php-xdg-base-dir.git", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "require-dev": { - "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" - }, - "type": "library", - "autoload": { - "psr-4": { - "XdgBaseDir\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "implementation of xdg base directory specification for php", - "support": { - "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", - "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" - }, - "time": "2019-12-04T15:06:13+00:00" - }, - { - "name": "doctrine/annotations", - "version": "1.13.3", - "source": { - "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "648b0343343565c4a056bfc8392201385e8d89f0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/648b0343343565c4a056bfc8392201385e8d89f0", - "reference": "648b0343343565c4a056bfc8392201385e8d89f0", - "shasum": "" - }, - "require": { - "doctrine/lexer": "1.*", - "ext-tokenizer": "*", - "php": "^7.1 || ^8.0", - "psr/cache": "^1 || ^2 || ^3" - }, - "require-dev": { - "doctrine/cache": "^1.11 || ^2.0", - "doctrine/coding-standard": "^6.0 || ^8.1", - "phpstan/phpstan": "^1.4.10 || ^1.8.0", - "phpunit/phpunit": "^7.5 || ^8.0 || ^9.1.5", - "symfony/cache": "^4.4 || ^5.2", - "vimeo/psalm": "^4.10" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Docblock Annotations Parser", - "homepage": "https://www.doctrine-project.org/projects/annotations.html", - "keywords": [ - "annotations", - "docblock", - "parser" - ], - "support": { - "issues": "https://github.com/doctrine/annotations/issues", - "source": "https://github.com/doctrine/annotations/tree/1.13.3" - }, - "time": "2022-07-02T10:48:51+00:00" - }, - { - "name": "doctrine/instantiator", - "version": "1.4.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^0.16 || ^1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.22" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.4.1" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" - } - ], - "time": "2022-03-03T08:28:38+00:00" - }, - { - "name": "doctrine/lexer", - "version": "1.2.3", - "source": { - "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/c268e882d4dbdd85e36e4ad69e02dc284f89d229", - "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9.0", - "phpstan/phpstan": "^1.3", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.11" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "https://www.doctrine-project.org/projects/lexer.html", - "keywords": [ - "annotations", - "docblock", - "lexer", - "parser", - "php" - ], - "support": { - "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/1.2.3" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", - "type": "tidelift" - } - ], - "time": "2022-02-28T11:07:21+00:00" - }, - { - "name": "felixfbecker/advanced-json-rpc", - "version": "v3.2.1", - "source": { - "type": "git", - "url": "https://github.com/felixfbecker/php-advanced-json-rpc.git", - "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447", - "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447", - "shasum": "" - }, - "require": { - "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "php": "^7.1 || ^8.0", - "phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0" - }, - "require-dev": { - "phpunit/phpunit": "^7.0 || ^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "AdvancedJsonRpc\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "ISC" - ], - "authors": [ - { - "name": "Felix Becker", - "email": "felix.b@outlook.com" - } - ], - "description": "A more advanced JSONRPC implementation", - "support": { - "issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues", - "source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.1" - }, - "time": "2021-06-11T22:34:44+00:00" - }, - { - "name": "felixfbecker/language-server-protocol", - "version": "v1.5.2", - "source": { - "type": "git", - "url": "https://github.com/felixfbecker/php-language-server-protocol.git", - "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/6e82196ffd7c62f7794d778ca52b69feec9f2842", - "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "phpstan/phpstan": "*", - "squizlabs/php_codesniffer": "^3.1", - "vimeo/psalm": "^4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "LanguageServerProtocol\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "ISC" - ], - "authors": [ - { - "name": "Felix Becker", - "email": "felix.b@outlook.com" - } - ], - "description": "PHP classes for the Language Server Protocol", - "keywords": [ - "language", - "microsoft", - "php", - "server" - ], - "support": { - "issues": "https://github.com/felixfbecker/php-language-server-protocol/issues", - "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.2" - }, - "time": "2022-03-02T22:36:06+00:00" - }, - { - "name": "laminas/laminas-code", - "version": "4.5.2", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-code.git", - "reference": "da01fb74c08f37e20e7ae49f1e3ee09aa401ebad" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-code/zipball/da01fb74c08f37e20e7ae49f1e3ee09aa401ebad", - "reference": "da01fb74c08f37e20e7ae49f1e3ee09aa401ebad", - "shasum": "" - }, - "require": { - "php": ">=7.4, <8.2" - }, - "require-dev": { - "doctrine/annotations": "^1.13.2", - "ext-phar": "*", - "laminas/laminas-coding-standard": "^2.3.0", - "laminas/laminas-stdlib": "^3.6.1", - "phpunit/phpunit": "^9.5.10", - "psalm/plugin-phpunit": "^0.16.1", - "vimeo/psalm": "^4.13.1" - }, - "suggest": { - "doctrine/annotations": "Doctrine\\Common\\Annotations >=1.0 for annotation features", - "laminas/laminas-stdlib": "Laminas\\Stdlib component" - }, - "type": "library", - "autoload": { - "files": [ - "polyfill/ReflectionEnumPolyfill.php" - ], - "psr-4": { - "Laminas\\Code\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Extensions to the PHP Reflection API, static code scanning, and code generation", - "homepage": "https://laminas.dev", - "keywords": [ - "code", - "laminas", - "laminasframework" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-code/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-code/issues", - "rss": "https://github.com/laminas/laminas-code/releases.atom", - "source": "https://github.com/laminas/laminas-code" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2022-06-06T11:26:02+00:00" - }, - { - "name": "laminas/laminas-coding-standard", - "version": "2.3.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-coding-standard.git", - "reference": "bcf6e07fe4690240be7beb6d884d0b0fafa6a251" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-coding-standard/zipball/bcf6e07fe4690240be7beb6d884d0b0fafa6a251", - "reference": "bcf6e07fe4690240be7beb6d884d0b0fafa6a251", - "shasum": "" - }, - "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.7", - "php": "^7.3 || ^8.0", - "slevomat/coding-standard": "^7.0", - "squizlabs/php_codesniffer": "^3.6", - "webimpress/coding-standard": "^1.2" - }, - "type": "phpcodesniffer-standard", - "autoload": { - "psr-4": { - "LaminasCodingStandard\\": "src/LaminasCodingStandard/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Laminas Coding Standard", - "homepage": "https://laminas.dev", - "keywords": [ - "Coding Standard", - "laminas" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-coding-standard/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-coding-standard/issues", - "rss": "https://github.com/laminas/laminas-coding-standard/releases.atom", - "source": "https://github.com/laminas/laminas-coding-standard" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2021-05-29T15:53:59+00:00" - }, - { - "name": "laminas/laminas-container-config-test", - "version": "0.7.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-container-config-test.git", - "reference": "799bbd667c25bf5b88ff879be2ac0e33a5a15185" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-container-config-test/zipball/799bbd667c25bf5b88ff879be2ac0e33a5a15185", - "reference": "799bbd667c25bf5b88ff879be2ac0e33a5a15185", - "shasum": "" - }, - "require": { - "php": "^7.4 || ~8.0.0 || ~8.1.0", - "psr/container": "^1.0 || ^2.0" - }, - "conflict": { - "zendframework/zend-container-config-test": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "^2.3", - "phpunit/phpunit": "^9.5.21", - "psalm/plugin-phpunit": "^0.17.0", - "vimeo/psalm": "^4.24.0" - }, - "type": "library", - "autoload": { - "files": [ - "src/TestAsset/function-factory.php", - "src/TestAsset/function-factory-with-name.php", - "src/TestAsset/function-factory.legacy.php", - "src/TestAsset/function-factory-with-name.legacy.php" - ], - "psr-4": { - "Laminas\\ContainerConfigTest\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Mezzio PSR-11 container configuration tests", - "homepage": "https://laminas.dev", - "keywords": [ - "PSR-11", - "container", - "laminas", - "mezzio", - "test" - ], - "support": { - "chat": "https://laminas.dev/chat", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-container-config-test/issues", - "rss": "https://github.com/laminas/laminas-container-config-test/releases.atom", - "source": "https://github.com/laminas/laminas-container-config-test" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2022-07-24T20:30:12+00:00" - }, - { - "name": "laminas/laminas-dependency-plugin", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-dependency-plugin.git", - "reference": "73cfb63ddca9d6bfedad5e0a038f6d55063975a3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-dependency-plugin/zipball/73cfb63ddca9d6bfedad5e0a038f6d55063975a3", - "reference": "73cfb63ddca9d6bfedad5e0a038f6d55063975a3", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.1 || ^2.0", - "php": "^7.3 || ~8.0.0 || ~8.1.0" - }, - "require-dev": { - "composer/composer": "^1.9 || ^2.0", - "laminas/laminas-coding-standard": "^2.2.1", - "mikey179/vfsstream": "^1.6.10@alpha", - "phpunit/phpunit": "^9.5.5", - "psalm/plugin-phpunit": "^0.15.1", - "roave/security-advisories": "dev-master", - "vimeo/psalm": "^4.5" - }, - "type": "composer-plugin", - "extra": { - "class": "Laminas\\DependencyPlugin\\DependencyRewriterPluginDelegator" - }, - "autoload": { - "psr-4": { - "Laminas\\DependencyPlugin\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Replace zendframework and zfcampus packages with their Laminas Project equivalents.", - "support": { - "issues": "https://github.com/laminas/laminas-dependency-plugin/issues", - "source": "https://github.com/laminas/laminas-dependency-plugin/tree/2.2.0" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2021-09-08T17:51:35+00:00" - }, - { - "name": "mikey179/vfsstream", - "version": "v1.6.11", - "source": { - "type": "git", - "url": "https://github.com/bovigo/vfsStream.git", - "reference": "17d16a85e6c26ce1f3e2fa9ceeacdc2855db1e9f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/17d16a85e6c26ce1f3e2fa9ceeacdc2855db1e9f", - "reference": "17d16a85e6c26ce1f3e2fa9ceeacdc2855db1e9f", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.5|^5.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6.x-dev" - } - }, - "autoload": { - "psr-0": { - "org\\bovigo\\vfs\\": "src/main/php" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Frank Kleine", - "homepage": "http://frankkleine.de/", - "role": "Developer" - } - ], - "description": "Virtual file system to mock the real file system in unit tests.", - "homepage": "http://vfs.bovigo.org/", - "support": { - "issues": "https://github.com/bovigo/vfsStream/issues", - "source": "https://github.com/bovigo/vfsStream/tree/master", - "wiki": "https://github.com/bovigo/vfsStream/wiki" - }, - "time": "2022-02-23T02:02:42+00:00" - }, - { - "name": "myclabs/deep-copy", - "version": "1.11.0", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" - }, - "require-dev": { - "doctrine/collections": "^1.6.8", - "doctrine/common": "^2.13.3 || ^3.2.2", - "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" - }, - "type": "library", - "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2022-03-03T13:19:32+00:00" - }, - { - "name": "netresearch/jsonmapper", - "version": "v4.0.0", - "source": { - "type": "git", - "url": "https://github.com/cweiske/jsonmapper.git", - "reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d", - "reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=7.1" - }, - "require-dev": { - "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0", - "squizlabs/php_codesniffer": "~3.5" - }, - "type": "library", - "autoload": { - "psr-0": { - "JsonMapper": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "OSL-3.0" - ], - "authors": [ - { - "name": "Christian Weiske", - "email": "cweiske@cweiske.de", - "homepage": "http://github.com/cweiske/jsonmapper/", - "role": "Developer" - } - ], - "description": "Map nested JSON structures onto PHP classes", - "support": { - "email": "cweiske@cweiske.de", - "issues": "https://github.com/cweiske/jsonmapper/issues", - "source": "https://github.com/cweiske/jsonmapper/tree/v4.0.0" - }, - "time": "2020-12-01T19:48:11+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v4.14.0", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/34bea19b6e03d8153165d8f30bba4c3be86184c1", - "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=7.0" - }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.9-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.14.0" - }, - "time": "2022-05-31T20:59:12+00:00" - }, - { - "name": "ocramius/proxy-manager", - "version": "2.13.1", - "source": { - "type": "git", - "url": "https://github.com/Ocramius/ProxyManager.git", - "reference": "e32bc1986fb6fa318ce35e573c654e3ddfb4848d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Ocramius/ProxyManager/zipball/e32bc1986fb6fa318ce35e573c654e3ddfb4848d", - "reference": "e32bc1986fb6fa318ce35e573c654e3ddfb4848d", - "shasum": "" - }, - "require": { - "composer-runtime-api": "^2.1.0", - "laminas/laminas-code": "^4.3.0", - "php": "~7.4.1 || ~8.0.0", - "webimpress/safe-writer": "^2.2.0" - }, - "conflict": { - "doctrine/annotations": "<1.6.1", - "laminas/laminas-stdlib": "<3.2.1", - "thecodingmachine/safe": "<1.3.3", - "zendframework/zend-stdlib": "<3.2.1" - }, - "require-dev": { - "codelicia/xulieta": "^0.1.6", - "doctrine/coding-standard": "^8.2.1", - "ext-phar": "*", - "infection/infection": "^0.21.5", - "nikic/php-parser": "^4.10.5", - "phpbench/phpbench": "^0.17.1 || 1.0.0-alpha2", - "phpunit/phpunit": "^9.5.4", - "slevomat/coding-standard": "^6.3.10", - "squizlabs/php_codesniffer": "^3.6.0", - "vimeo/psalm": "^4.4.1" - }, - "suggest": { - "laminas/laminas-json": "To have the JsonRpc adapter (Remote Object feature)", - "laminas/laminas-soap": "To have the Soap adapter (Remote Object feature)", - "laminas/laminas-xmlrpc": "To have the XmlRpc adapter (Remote Object feature)", - "ocramius/generated-hydrator": "To have very fast object to array to object conversion for ghost objects" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "ProxyManager\\": "src/ProxyManager" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.io/" - } - ], - "description": "A library providing utilities to generate, instantiate and generally operate with Object Proxies", - "homepage": "https://github.com/Ocramius/ProxyManager", - "keywords": [ - "aop", - "lazy loading", - "proxy", - "proxy pattern", - "service proxies" - ], - "support": { - "issues": "https://github.com/Ocramius/ProxyManager/issues", - "source": "https://github.com/Ocramius/ProxyManager/tree/2.13.1" - }, - "funding": [ - { - "url": "https://github.com/Ocramius", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/ocramius/proxy-manager", - "type": "tidelift" - } - ], - "time": "2022-03-05T18:42:03+00:00" - }, - { - "name": "openlss/lib-array2xml", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/nullivex/lib-array2xml.git", - "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nullivex/lib-array2xml/zipball/a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", - "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "type": "library", - "autoload": { - "psr-0": { - "LSS": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Bryan Tong", - "email": "bryan@nullivex.com", - "homepage": "https://www.nullivex.com" - }, - { - "name": "Tony Butler", - "email": "spudz76@gmail.com", - "homepage": "https://www.nullivex.com" - } - ], - "description": "Array2XML conversion library credit to lalit.org", - "homepage": "https://www.nullivex.com", - "keywords": [ - "array", - "array conversion", - "xml", - "xml conversion" - ], - "support": { - "issues": "https://github.com/nullivex/lib-array2xml/issues", - "source": "https://github.com/nullivex/lib-array2xml/tree/master" - }, - "time": "2019-03-29T20:06:56+00:00" - }, - { - "name": "phar-io/manifest", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.3" - }, - "time": "2021-07-20T11:28:43+00:00" - }, - { - "name": "phar-io/version", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.2.1" - }, - "time": "2022-02-21T01:04:05+00:00" - }, - { - "name": "phpbench/container", - "version": "2.2.1", - "source": { - "type": "git", - "url": "https://github.com/phpbench/container.git", - "reference": "6d555ff7174fca13f9b1ec0b4a089ed41d0ab392" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpbench/container/zipball/6d555ff7174fca13f9b1ec0b4a089ed41d0ab392", - "reference": "6d555ff7174fca13f9b1ec0b4a089ed41d0ab392", - "shasum": "" - }, - "require": { - "psr/container": "^1.0|^2.0", - "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.16", - "phpstan/phpstan": "^0.12.52", - "phpunit/phpunit": "^8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "PhpBench\\DependencyInjection\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Leech", - "email": "daniel@dantleech.com" - } - ], - "description": "Simple, configurable, service container.", - "support": { - "issues": "https://github.com/phpbench/container/issues", - "source": "https://github.com/phpbench/container/tree/2.2.1" - }, - "time": "2022-01-25T10:17:35+00:00" - }, - { - "name": "phpbench/dom", - "version": "0.3.2", - "source": { - "type": "git", - "url": "https://github.com/phpbench/dom.git", - "reference": "b013b717832ddbaadf2a40984b04bc66af9a7110" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpbench/dom/zipball/b013b717832ddbaadf2a40984b04bc66af9a7110", - "reference": "b013b717832ddbaadf2a40984b04bc66af9a7110", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "php": "^7.2||^8.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.18", - "phpstan/phpstan": "^0.12.83", - "phpunit/phpunit": "^8.0||^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "psr-4": { - "PhpBench\\Dom\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Leech", - "email": "daniel@dantleech.com" - } - ], - "description": "DOM wrapper to simplify working with the PHP DOM implementation", - "support": { - "issues": "https://github.com/phpbench/dom/issues", - "source": "https://github.com/phpbench/dom/tree/0.3.2" - }, - "time": "2021-09-24T15:26:07+00:00" - }, - { - "name": "phpbench/phpbench", - "version": "1.2.6", - "source": { - "type": "git", - "url": "https://github.com/phpbench/phpbench.git", - "reference": "c30fac992e72b505a1f131790583647f4d3255c3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpbench/phpbench/zipball/c30fac992e72b505a1f131790583647f4d3255c3", - "reference": "c30fac992e72b505a1f131790583647f4d3255c3", - "shasum": "" - }, - "require": { - "doctrine/annotations": "^1.13", - "ext-dom": "*", - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "ext-tokenizer": "*", - "php": "^7.3 || ^8.0", - "phpbench/container": "^2.1", - "phpbench/dom": "~0.3.1", - "psr/log": "^1.1 || ^2.0 || ^3.0", - "seld/jsonlint": "^1.1", - "symfony/console": "^4.2 || ^5.0 || ^6.0", - "symfony/filesystem": "^4.2 || ^5.0 || ^6.0", - "symfony/finder": "^4.2 || ^5.0 || ^6.0", - "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0", - "symfony/process": "^4.2 || ^5.0 || ^6.0", - "webmozart/path-util": "^2.3" - }, - "require-dev": { - "dantleech/invoke": "^2.0", - "friendsofphp/php-cs-fixer": "^3.0", - "jangregor/phpstan-prophecy": "^0.8.1", - "phpspec/prophecy": "^1.12", - "phpstan/phpstan": "^0.12.7", - "phpunit/phpunit": "^8.5.8 || ^9.0", - "symfony/error-handler": "^5.2 || ^6.0", - "symfony/var-dumper": "^4.0 || ^5.0 || ^6.0" - }, - "suggest": { - "ext-xdebug": "For Xdebug profiling extension." - }, - "bin": [ - "bin/phpbench" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2-dev" - } - }, - "autoload": { - "files": [ - "lib/Report/Func/functions.php" - ], - "psr-4": { - "PhpBench\\": "lib/", - "PhpBench\\Extensions\\XDebug\\": "extensions/xdebug/lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Leech", - "email": "daniel@dantleech.com" - } - ], - "description": "PHP Benchmarking Framework", - "support": { - "issues": "https://github.com/phpbench/phpbench/issues", - "source": "https://github.com/phpbench/phpbench/tree/1.2.6" - }, - "funding": [ - { - "url": "https://github.com/dantleech", - "type": "github" - } - ], - "time": "2022-07-19T19:52:39+00:00" - }, - { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" - }, - "time": "2020-06-27T09:03:43+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "5.3.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", - "shasum": "" - }, - "require": { - "ext-filter": "*", - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", - "webmozart/assert": "^1.9.1" - }, - "require-dev": { - "mockery/mockery": "~1.3.2", - "psalm/phar": "^4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - }, - { - "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" - }, - "time": "2021-10-19T17:43:47+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.6.1", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "77a32518733312af16a44300404e945338981de3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3", - "reference": "77a32518733312af16a44300404e945338981de3", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.0" - }, - "require-dev": { - "ext-tokenizer": "*", - "psalm/phar": "^4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1" - }, - "time": "2022-03-15T21:29:03+00:00" - }, - { - "name": "phpspec/prophecy", - "version": "v1.15.0", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/bbcd7380b0ebf3961ee21409db7b38bc31d69a13", - "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.2", - "php": "^7.2 || ~8.0, <8.2", - "phpdocumentor/reflection-docblock": "^5.2", - "sebastian/comparator": "^3.0 || ^4.0", - "sebastian/recursion-context": "^3.0 || ^4.0" - }, - "require-dev": { - "phpspec/phpspec": "^6.0 || ^7.0", - "phpunit/phpunit": "^8.0 || ^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Prophecy\\": "src/Prophecy" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" - } - ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "support": { - "issues": "https://github.com/phpspec/prophecy/issues", - "source": "https://github.com/phpspec/prophecy/tree/v1.15.0" - }, - "time": "2021-12-08T12:19:24+00:00" - }, - { - "name": "phpspec/prophecy-phpunit", - "version": "v2.0.1", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy-phpunit.git", - "reference": "2d7a9df55f257d2cba9b1d0c0963a54960657177" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy-phpunit/zipball/2d7a9df55f257d2cba9b1d0c0963a54960657177", - "reference": "2d7a9df55f257d2cba9b1d0c0963a54960657177", - "shasum": "" - }, - "require": { - "php": "^7.3 || ^8", - "phpspec/prophecy": "^1.3", - "phpunit/phpunit": "^9.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "psr-4": { - "Prophecy\\PhpUnit\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christophe Coevoet", - "email": "stof@notk.org" - } - ], - "description": "Integrating the Prophecy mocking library in PHPUnit test cases", - "homepage": "http://phpspec.net", - "keywords": [ - "phpunit", - "prophecy" - ], - "support": { - "issues": "https://github.com/phpspec/prophecy-phpunit/issues", - "source": "https://github.com/phpspec/prophecy-phpunit/tree/v2.0.1" - }, - "time": "2020-07-09T08:33:42+00:00" - }, - { - "name": "phpstan/phpdoc-parser", - "version": "1.6.4", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "135607f9ccc297d6923d49c2bcf309f509413215" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/135607f9ccc297d6923d49c2bcf309f509413215", - "reference": "135607f9ccc297d6923d49c2bcf309f509413215", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^1.5", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^9.5", - "symfony/process": "^5.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "PHPStan\\PhpDocParser\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPDoc parser with support for nullable, intersection and generic types", - "support": { - "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.6.4" - }, - "time": "2022-06-26T13:09:08+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "9.2.15", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2e9da11878c4202f97915c1cb4bb1ca318a63f5f", - "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^4.13.0", - "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.3", - "phpunit/php-text-template": "^2.0.2", - "sebastian/code-unit-reverse-lookup": "^2.0.2", - "sebastian/complexity": "^2.0", - "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0.3", - "sebastian/version": "^3.0.1", - "theseer/tokenizer": "^1.2.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcov": "*", - "ext-xdebug": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.15" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-03-07T09:28:20+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "3.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-12-02T12:48:52+00:00" - }, - { - "name": "phpunit/php-invoker", - "version": "3.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:58:55+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T05:33:50+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "5.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:16:10+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "9.5.21", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "0e32b76be457de00e83213528f6bb37e2a38fcb1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0e32b76be457de00e83213528f6bb37e2a38fcb1", - "reference": "0e32b76be457de00e83213528f6bb37e2a38fcb1", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.3.1", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", - "php": ">=7.3", - "phpspec/prophecy": "^1.12.1", - "phpunit/php-code-coverage": "^9.2.13", - "phpunit/php-file-iterator": "^3.0.5", - "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.5", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.3", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.0", - "sebastian/version": "^3.0.2" - }, - "require-dev": { - "phpspec/prophecy-phpunit": "^2.0.1" - }, - "suggest": { - "ext-soap": "*", - "ext-xdebug": "*" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.5-dev" - } - }, - "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.21" - }, - "funding": [ - { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-06-19T12:14:25+00:00" - }, - { - "name": "psalm/plugin-phpunit", - "version": "0.17.0", - "source": { - "type": "git", - "url": "https://github.com/psalm/psalm-plugin-phpunit.git", - "reference": "45951541beef07e93e3ad197daf01da88e85c31d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/psalm/psalm-plugin-phpunit/zipball/45951541beef07e93e3ad197daf01da88e85c31d", - "reference": "45951541beef07e93e3ad197daf01da88e85c31d", - "shasum": "" - }, - "require": { - "composer/package-versions-deprecated": "^1.10", - "composer/semver": "^1.4 || ^2.0 || ^3.0", - "ext-simplexml": "*", - "php": "^7.1 || ^8.0", - "vimeo/psalm": "dev-master || dev-4.x || ^4.5" - }, - "conflict": { - "phpunit/phpunit": "<7.5" - }, - "require-dev": { - "codeception/codeception": "^4.0.3", - "php": "^7.3 || ^8.0", - "phpunit/phpunit": "^7.5 || ^8.0 || ^9.0", - "squizlabs/php_codesniffer": "^3.3.1", - "weirdan/codeception-psalm-module": "^0.11.0", - "weirdan/prophecy-shim": "^1.0 || ^2.0" - }, - "type": "psalm-plugin", - "extra": { - "psalm": { - "pluginClass": "Psalm\\PhpUnitPlugin\\Plugin" - } - }, - "autoload": { - "psr-4": { - "Psalm\\PhpUnitPlugin\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Matt Brown", - "email": "github@muglug.com" - } - ], - "description": "Psalm plugin for PHPUnit", - "support": { - "issues": "https://github.com/psalm/psalm-plugin-phpunit/issues", - "source": "https://github.com/psalm/psalm-plugin-phpunit/tree/0.17.0" - }, - "time": "2022-06-14T17:05:57+00:00" - }, - { - "name": "psr/cache", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Cache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for caching libraries", - "keywords": [ - "cache", - "psr", - "psr-6" - ], - "support": { - "source": "https://github.com/php-fig/cache/tree/master" - }, - "time": "2016-08-06T20:24:11+00:00" - }, - { - "name": "psr/log", - "version": "1.1.4", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "support": { - "source": "https://github.com/php-fig/log/tree/1.1.4" - }, - "time": "2021-05-03T11:20:27+00:00" - }, - { - "name": "sebastian/cli-parser", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", - "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:08:49+00:00" - }, - { - "name": "sebastian/code-unit", - "version": "1.0.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:08:54+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:30:19+00:00" - }, - { - "name": "sebastian/comparator", - "version": "4.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T15:49:45+00:00" - }, - { - "name": "sebastian/complexity", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.7", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", - "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T15:52:27+00:00" - }, - { - "name": "sebastian/diff", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/process": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:10:38+00:00" - }, - { - "name": "sebastian/environment", - "version": "5.1.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-posix": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-04-03T09:37:03+00:00" - }, - { - "name": "sebastian/exporter", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/65e8b7db476c5dd267e65eea9cab77584d3cfff9", - "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-11-11T14:18:36+00:00" - }, - { - "name": "sebastian/global-state", - "version": "5.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-02-14T08:28:10+00:00" - }, - { - "name": "sebastian/lines-of-code", - "version": "1.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.6", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", - "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-28T06:42:11+00:00" - }, - { - "name": "sebastian/object-enumerator", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:12:34+00:00" - }, - { - "name": "sebastian/object-reflector", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:14:26+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:17:30+00:00" - }, - { - "name": "sebastian/resource-operations", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:45:17+00:00" - }, - { - "name": "sebastian/type", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b233b84bc4465aff7b57cf1c4bc75c86d00d6dad", - "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", - "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-03-15T09:54:48+00:00" - }, - { - "name": "sebastian/version", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:39:44+00:00" - }, - { - "name": "seld/jsonlint", - "version": "1.9.0", - "source": { - "type": "git", - "url": "https://github.com/Seldaek/jsonlint.git", - "reference": "4211420d25eba80712bff236a98960ef68b866b7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/4211420d25eba80712bff236a98960ef68b866b7", - "reference": "4211420d25eba80712bff236a98960ef68b866b7", - "shasum": "" - }, - "require": { - "php": "^5.3 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.5", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13" - }, - "bin": [ - "bin/jsonlint" - ], - "type": "library", - "autoload": { - "psr-4": { - "Seld\\JsonLint\\": "src/Seld/JsonLint/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "JSON Linter", - "keywords": [ - "json", - "linter", - "parser", - "validator" - ], - "support": { - "issues": "https://github.com/Seldaek/jsonlint/issues", - "source": "https://github.com/Seldaek/jsonlint/tree/1.9.0" - }, - "funding": [ - { - "url": "https://github.com/Seldaek", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/seld/jsonlint", - "type": "tidelift" - } - ], - "time": "2022-04-01T13:37:23+00:00" - }, - { - "name": "slevomat/coding-standard", - "version": "7.2.1", - "source": { - "type": "git", - "url": "https://github.com/slevomat/coding-standard.git", - "reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/aff06ae7a84e4534bf6f821dc982a93a5d477c90", - "reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90", - "shasum": "" - }, - "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7", - "php": "^7.2 || ^8.0", - "phpstan/phpdoc-parser": "^1.5.1", - "squizlabs/php_codesniffer": "^3.6.2" - }, - "require-dev": { - "phing/phing": "2.17.3", - "php-parallel-lint/php-parallel-lint": "1.3.2", - "phpstan/phpstan": "1.4.10|1.7.1", - "phpstan/phpstan-deprecation-rules": "1.0.0", - "phpstan/phpstan-phpunit": "1.0.0|1.1.1", - "phpstan/phpstan-strict-rules": "1.2.3", - "phpunit/phpunit": "7.5.20|8.5.21|9.5.20" - }, - "type": "phpcodesniffer-standard", - "extra": { - "branch-alias": { - "dev-master": "7.x-dev" - } - }, - "autoload": { - "psr-4": { - "SlevomatCodingStandard\\": "SlevomatCodingStandard" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", - "support": { - "issues": "https://github.com/slevomat/coding-standard/issues", - "source": "https://github.com/slevomat/coding-standard/tree/7.2.1" - }, - "funding": [ - { - "url": "https://github.com/kukulich", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard", - "type": "tidelift" - } - ], - "time": "2022-05-25T10:58:12+00:00" - }, - { - "name": "squizlabs/php_codesniffer", - "version": "3.7.1", - "source": { - "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619", - "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" - }, - "bin": [ - "bin/phpcs", - "bin/phpcbf" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Greg Sherwood", - "role": "lead" - } - ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", - "keywords": [ - "phpcs", - "standards" - ], - "support": { - "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", - "source": "https://github.com/squizlabs/PHP_CodeSniffer", - "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" - }, - "time": "2022-06-18T07:21:10+00:00" - }, - { - "name": "symfony/console", - "version": "v5.4.10", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "4d671ab4ddac94ee439ea73649c69d9d200b5000" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/4d671ab4ddac94ee439ea73649c69d9d200b5000", - "reference": "4d671ab4ddac94ee439ea73649c69d9d200b5000", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.1|^6.0" - }, - "conflict": { - "psr/log": ">=3", - "symfony/dependency-injection": "<4.4", - "symfony/dotenv": "<5.1", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" - }, - "provide": { - "psr/log-implementation": "1.0|2.0" - }, - "require-dev": { - "psr/log": "^1|^2", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/lock": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Eases the creation of beautiful and testable command line interfaces", - "homepage": "https://symfony.com", - "keywords": [ - "cli", - "command line", - "console", - "terminal" - ], - "support": { - "source": "https://github.com/symfony/console/tree/v5.4.10" - }, - "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-06-26T13:00:04+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "v2.5.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-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/v2.5.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-01-02T09:53:40+00:00" - }, - { - "name": "symfony/filesystem", - "version": "v5.4.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "36a017fa4cce1eff1b8e8129ff53513abcef05ba" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/36a017fa4cce1eff1b8e8129ff53513abcef05ba", - "reference": "36a017fa4cce1eff1b8e8129ff53513abcef05ba", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides basic utilities for the filesystem", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.4.9" - }, - "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-20T13:55:35+00:00" - }, - { - "name": "symfony/finder", - "version": "v5.4.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "9b630f3427f3ebe7cd346c277a1408b00249dad9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/9b630f3427f3ebe7cd346c277a1408b00249dad9", - "reference": "9b630f3427f3ebe7cd346c277a1408b00249dad9", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Finds files and directories via an intuitive fluent interface", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/finder/tree/v5.4.8" - }, - "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-04-15T08:07:45+00:00" - }, - { - "name": "symfony/options-resolver", - "version": "v5.4.3", - "source": { - "type": "git", - "url": "https://github.com/symfony/options-resolver.git", - "reference": "cc1147cb11af1b43f503ac18f31aa3bec213aba8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/cc1147cb11af1b43f503ac18f31aa3bec213aba8", - "reference": "cc1147cb11af1b43f503ac18f31aa3bec213aba8", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php73": "~1.0", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\OptionsResolver\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an improved replacement for the array_replace PHP function", - "homepage": "https://symfony.com", - "keywords": [ - "config", - "configuration", - "options" - ], - "support": { - "source": "https://github.com/symfony/options-resolver/tree/v5.4.3" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-01-02T09:53:40+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", - "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-ctype": "*" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-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.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "433d05519ce6990bf3530fba6957499d327395c2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2", - "reference": "433d05519ce6990bf3530fba6957499d327395c2", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's grapheme_* functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "grapheme", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "219aa369ceff116e673852dce47c3a41794c14bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd", - "reference": "219aa369ceff116e673852dce47c3a41794c14bd", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-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.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", - "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-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.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-php73", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/e440d35fa0286f77fb45b79a03fedbeda9307e85", - "reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-php80", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace", - "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-10T07:21:04+00:00" - }, - { - "name": "symfony/process", - "version": "v5.4.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "597f3fff8e3e91836bb0bd38f5718b56ddbde2f3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/597f3fff8e3e91836bb0bd38f5718b56ddbde2f3", - "reference": "597f3fff8e3e91836bb0bd38f5718b56ddbde2f3", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Process\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Executes commands in sub-processes", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/process/tree/v5.4.8" - }, - "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-04-08T05:07:18+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v2.5.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1|^3" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "suggest": { - "symfony/service-implementation": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-30T19:17:29+00:00" - }, - { - "name": "symfony/string", - "version": "v5.4.10", - "source": { - "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "4432bc7df82a554b3e413a8570ce2fea90e94097" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/4432bc7df82a554b3e413a8570ce2fea90e94097", - "reference": "4432bc7df82a554b3e413a8570ce2fea90e94097", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "~1.15" - }, - "conflict": { - "symfony/translation-contracts": ">=3.0" - }, - "require-dev": { - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/translation-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0|^6.0" - }, - "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/v5.4.10" - }, - "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-06-26T15:57:47+00:00" - }, - { - "name": "theseer/tokenizer", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.1" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2021-07-28T10:34:58+00:00" - }, - { - "name": "vimeo/psalm", - "version": "4.24.0", - "source": { - "type": "git", - "url": "https://github.com/vimeo/psalm.git", - "reference": "06dd975cb55d36af80f242561738f16c5f58264f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/06dd975cb55d36af80f242561738f16c5f58264f", - "reference": "06dd975cb55d36af80f242561738f16c5f58264f", - "shasum": "" - }, - "require": { - "amphp/amp": "^2.4.2", - "amphp/byte-stream": "^1.5", - "composer/package-versions-deprecated": "^1.8.0", - "composer/semver": "^1.4 || ^2.0 || ^3.0", - "composer/xdebug-handler": "^1.1 || ^2.0 || ^3.0", - "dnoegel/php-xdg-base-dir": "^0.1.1", - "ext-ctype": "*", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-simplexml": "*", - "ext-tokenizer": "*", - "felixfbecker/advanced-json-rpc": "^3.0.3", - "felixfbecker/language-server-protocol": "^1.5", - "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "nikic/php-parser": "^4.13", - "openlss/lib-array2xml": "^1.0", - "php": "^7.1|^8", - "sebastian/diff": "^3.0 || ^4.0", - "symfony/console": "^3.4.17 || ^4.1.6 || ^5.0 || ^6.0", - "symfony/polyfill-php80": "^1.25", - "webmozart/path-util": "^2.3" - }, - "provide": { - "psalm/psalm": "self.version" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.2", - "brianium/paratest": "^4.0||^6.0", - "ext-curl": "*", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpdocumentor/reflection-docblock": "^5", - "phpmyadmin/sql-parser": "5.1.0||dev-master", - "phpspec/prophecy": ">=1.9.0", - "phpunit/phpunit": "^9.0", - "psalm/plugin-phpunit": "^0.16", - "slevomat/coding-standard": "^7.0", - "squizlabs/php_codesniffer": "^3.5", - "symfony/process": "^4.3 || ^5.0 || ^6.0", - "weirdan/prophecy-shim": "^1.0 || ^2.0" - }, - "suggest": { - "ext-curl": "In order to send data to shepherd", - "ext-igbinary": "^2.0.5 is required, used to serialize caching data" - }, - "bin": [ - "psalm", - "psalm-language-server", - "psalm-plugin", - "psalm-refactor", - "psalter" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.x-dev", - "dev-3.x": "3.x-dev", - "dev-2.x": "2.x-dev", - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "files": [ - "src/functions.php", - "src/spl_object_id.php" - ], - "psr-4": { - "Psalm\\": "src/Psalm/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Matthew Brown" - } - ], - "description": "A static analysis tool for finding errors in PHP applications", - "keywords": [ - "code", - "inspection", - "php" - ], - "support": { - "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm/tree/4.24.0" - }, - "time": "2022-06-26T11:47:54+00:00" - }, - { - "name": "webimpress/coding-standard", - "version": "1.2.4", - "source": { - "type": "git", - "url": "https://github.com/webimpress/coding-standard.git", - "reference": "cd0c4b0b97440c337c1f7da17b524674ca2f9ca9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webimpress/coding-standard/zipball/cd0c4b0b97440c337c1f7da17b524674ca2f9ca9", - "reference": "cd0c4b0b97440c337c1f7da17b524674ca2f9ca9", - "shasum": "" - }, - "require": { - "php": "^7.3 || ^8.0", - "squizlabs/php_codesniffer": "^3.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^9.5.13" - }, - "type": "phpcodesniffer-standard", - "extra": { - "dev-master": "1.2.x-dev", - "dev-develop": "1.3.x-dev" - }, - "autoload": { - "psr-4": { - "WebimpressCodingStandard\\": "src/WebimpressCodingStandard/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "description": "Webimpress Coding Standard", - "keywords": [ - "Coding Standard", - "PSR-2", - "phpcs", - "psr-12", - "webimpress" - ], - "support": { - "issues": "https://github.com/webimpress/coding-standard/issues", - "source": "https://github.com/webimpress/coding-standard/tree/1.2.4" - }, - "funding": [ - { - "url": "https://github.com/michalbundyra", - "type": "github" - } - ], - "time": "2022-02-15T19:52:12+00:00" - }, - { - "name": "webimpress/safe-writer", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/webimpress/safe-writer.git", - "reference": "9d37cc8bee20f7cb2f58f6e23e05097eab5072e6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webimpress/safe-writer/zipball/9d37cc8bee20f7cb2f58f6e23e05097eab5072e6", - "reference": "9d37cc8bee20f7cb2f58f6e23e05097eab5072e6", - "shasum": "" - }, - "require": { - "php": "^7.3 || ^8.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.5.4", - "vimeo/psalm": "^4.7", - "webimpress/coding-standard": "^1.2.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.2.x-dev", - "dev-develop": "2.3.x-dev", - "dev-release-1.0": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Webimpress\\SafeWriter\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "description": "Tool to write files safely, to avoid race conditions", - "keywords": [ - "concurrent write", - "file writer", - "race condition", - "safe writer", - "webimpress" - ], - "support": { - "issues": "https://github.com/webimpress/safe-writer/issues", - "source": "https://github.com/webimpress/safe-writer/tree/2.2.0" - }, - "funding": [ - { - "url": "https://github.com/michalbundyra", - "type": "github" - } - ], - "time": "2021-04-19T16:34:45+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": "" - }, - "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": "webmozart/path-util", - "version": "2.3.0", - "source": { - "type": "git", - "url": "https://github.com/webmozart/path-util.git", - "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725", - "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "webmozart/assert": "~1.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\PathUtil\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.", - "support": { - "issues": "https://github.com/webmozart/path-util/issues", - "source": "https://github.com/webmozart/path-util/tree/2.3.0" - }, - "abandoned": "symfony/filesystem", - "time": "2015-12-17T08:42:14+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": { - "mikey179/vfsstream": 15 - }, - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": "~7.4.0 || ~8.0.0 || ~8.1.0" - }, - "platform-dev": [], - "platform-overrides": { - "php": "7.4.99" - }, - "plugin-api-version": "2.3.0" -} diff --git a/lib/laminas/laminas-servicemanager/src/AbstractFactory/ConfigAbstractFactory.php b/lib/laminas/laminas-servicemanager/src/AbstractFactory/ConfigAbstractFactory.php deleted file mode 100644 index b51dfdf01..000000000 --- a/lib/laminas/laminas-servicemanager/src/AbstractFactory/ConfigAbstractFactory.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager\AbstractFactory; - -use ArrayObject; -use Laminas\ServiceManager\Exception\ServiceNotCreatedException; -use Laminas\ServiceManager\Factory\AbstractFactoryInterface; -use Psr\Container\ContainerInterface; - -use function array_key_exists; -use function array_map; -use function array_values; -use function is_array; -use function json_encode; - -final class ConfigAbstractFactory implements AbstractFactoryInterface -{ - /** - * Factory can create the service if there is a key for it in the config - * - * {@inheritdoc} - */ - public function canCreate(ContainerInterface $container, $requestedName) - { - if (! $container->has('config')) { - return false; - } - $config = $container->get('config'); - if (! isset($config[self::class])) { - return false; - } - $dependencies = $config[self::class]; - - return is_array($dependencies) && array_key_exists($requestedName, $dependencies); - } - - /** - * {@inheritDoc} - */ - public function __invoke(ContainerInterface $container, $requestedName, ?array $options = null) - { - if (! $container->has('config')) { - throw new ServiceNotCreatedException('Cannot find a config array in the container'); - } - - $config = $container->get('config'); - - if (! (is_array($config) || $config instanceof ArrayObject)) { - throw new ServiceNotCreatedException('Config must be an array or an instance of ArrayObject'); - } - if (! isset($config[self::class])) { - throw new ServiceNotCreatedException('Cannot find a `' . self::class . '` key in the config array'); - } - - $dependencies = $config[self::class]; - - if ( - ! is_array($dependencies) - || ! array_key_exists($requestedName, $dependencies) - || ! is_array($dependencies[$requestedName]) - ) { - throw new ServiceNotCreatedException('Service dependencies config must exist and be an array'); - } - - $serviceDependencies = $dependencies[$requestedName]; - - if ($serviceDependencies !== array_values(array_map('strval', $serviceDependencies))) { - $problem = json_encode(array_map('gettype', $serviceDependencies)); - throw new ServiceNotCreatedException( - 'Service dependencies config must be an array of strings, ' . $problem . ' given' - ); - } - - $arguments = array_map([$container, 'get'], $serviceDependencies); - - return new $requestedName(...$arguments); - } -} diff --git a/lib/laminas/laminas-servicemanager/src/AbstractFactory/ReflectionBasedAbstractFactory.php b/lib/laminas/laminas-servicemanager/src/AbstractFactory/ReflectionBasedAbstractFactory.php deleted file mode 100644 index 9d6bdc4aa..000000000 --- a/lib/laminas/laminas-servicemanager/src/AbstractFactory/ReflectionBasedAbstractFactory.php +++ /dev/null @@ -1,247 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager\AbstractFactory; - -use Laminas\ServiceManager\Exception\ServiceNotFoundException; -use Laminas\ServiceManager\Factory\AbstractFactoryInterface; -use Psr\Container\ContainerInterface; -use ReflectionClass; -use ReflectionNamedType; -use ReflectionParameter; - -use function array_map; -use function class_exists; -use function interface_exists; -use function is_string; -use function sprintf; - -/** - * Reflection-based factory. - * - * To ease development, this factory may be used for classes with - * type-hinted arguments that resolve to services in the application - * container; this allows omitting the step of writing a factory for - * each controller. - * - * You may use it as either an abstract factory: - * - * <code> - * 'service_manager' => [ - * 'abstract_factories' => [ - * ReflectionBasedAbstractFactory::class, - * ], - * ], - * </code> - * - * Or as a factory, mapping a class name to it: - * - * <code> - * 'service_manager' => [ - * 'factories' => [ - * MyClassWithDependencies::class => ReflectionBasedAbstractFactory::class, - * ], - * ], - * </code> - * - * The latter approach is more explicit, and also more performant. - * - * The factory has the following constraints/features: - * - * - A parameter named `$config` typehinted as an array will receive the - * application "config" service (i.e., the merged configuration). - * - Parameters type-hinted against array, but not named `$config` will - * be injected with an empty array. - * - Scalar parameters will result in an exception being thrown, unless - * a default value is present; if the default is present, that will be used. - * - If a service cannot be found for a given typehint, the factory will - * raise an exception detailing this. - * - Some services provided by Laminas components do not have - * entries based on their class name (for historical reasons); the - * factory allows defining a map of these class/interface names to the - * corresponding service name to allow them to resolve. - * - * `$options` passed to the factory are ignored in all cases, as we cannot - * make assumptions about which argument(s) they might replace. - * - * Based on the LazyControllerAbstractFactory from laminas-mvc. - */ -class ReflectionBasedAbstractFactory implements AbstractFactoryInterface -{ - /** - * Maps known classes/interfaces to the service that provides them; only - * required for those services with no entry based on the class/interface - * name. - * - * Extend the class if you wish to add to the list. - * - * Example: - * - * <code> - * [ - * \Laminas\Filter\FilterPluginManager::class => 'FilterManager', - * \Laminas\Validator\ValidatorPluginManager::class => 'ValidatorManager', - * ] - * </code> - * - * @var string[] - */ - protected $aliases = []; - - /** - * Allows overriding the internal list of aliases. These should be of the - * form `class name => well-known service name`; see the documentation for - * the `$aliases` property for details on what is accepted. - * - * @param string[] $aliases - */ - public function __construct(array $aliases = []) - { - if (! empty($aliases)) { - $this->aliases = $aliases; - } - } - - /** - * {@inheritDoc} - * - * @return DispatchableInterface - */ - public function __invoke(ContainerInterface $container, $requestedName, ?array $options = null) - { - $reflectionClass = new ReflectionClass($requestedName); - - if (null === ($constructor = $reflectionClass->getConstructor())) { - return new $requestedName(); - } - - $reflectionParameters = $constructor->getParameters(); - - if (empty($reflectionParameters)) { - return new $requestedName(); - } - - $resolver = $container->has('config') - ? $this->resolveParameterWithConfigService($container, $requestedName) - : $this->resolveParameterWithoutConfigService($container, $requestedName); - - $parameters = array_map($resolver, $reflectionParameters); - - return new $requestedName(...$parameters); - } - - /** - * {@inheritDoc} - */ - public function canCreate(ContainerInterface $container, $requestedName) - { - return class_exists($requestedName) && $this->canCallConstructor($requestedName); - } - - private function canCallConstructor(string $requestedName): bool - { - $constructor = (new ReflectionClass($requestedName))->getConstructor(); - - return $constructor === null || $constructor->isPublic(); - } - - /** - * Resolve a parameter to a value. - * - * Returns a callback for resolving a parameter to a value, but without - * allowing mapping array `$config` arguments to the `config` service. - * - * @param string $requestedName - * @return callable - */ - private function resolveParameterWithoutConfigService(ContainerInterface $container, $requestedName) - { - /** - * @param ReflectionParameter $parameter - * @return mixed - * @throws ServiceNotFoundException If type-hinted parameter cannot be - * resolved to a service in the container. - * @psalm-suppress MissingClosureReturnType - */ - return fn(ReflectionParameter $parameter) => $this->resolveParameter($parameter, $container, $requestedName); - } - - /** - * Returns a callback for resolving a parameter to a value, including mapping 'config' arguments. - * - * Unlike resolveParameter(), this version will detect `$config` array - * arguments and have them return the 'config' service. - * - * @param string $requestedName - * @return callable - */ - private function resolveParameterWithConfigService(ContainerInterface $container, $requestedName) - { - /** - * @param ReflectionParameter $parameter - * @return mixed - * @throws ServiceNotFoundException If type-hinted parameter cannot be - * resolved to a service in the container. - */ - return function (ReflectionParameter $parameter) use ($container, $requestedName) { - if ($parameter->getName() === 'config') { - $type = $parameter->getType(); - if ($type instanceof ReflectionNamedType && $type->getName() === 'array') { - return $container->get('config'); - } - } - return $this->resolveParameter($parameter, $container, $requestedName); - }; - } - - /** - * Logic common to all parameter resolution. - * - * @param string $requestedName - * @return mixed - * @throws ServiceNotFoundException If type-hinted parameter cannot be - * resolved to a service in the container. - */ - private function resolveParameter(ReflectionParameter $parameter, ContainerInterface $container, $requestedName) - { - $type = $parameter->getType(); - $type = $type instanceof ReflectionNamedType ? $type->getName() : null; - - if ($type === 'array') { - return []; - } - - if ($type === null || (is_string($type) && ! class_exists($type) && ! interface_exists($type))) { - if (! $parameter->isDefaultValueAvailable()) { - throw new ServiceNotFoundException(sprintf( - 'Unable to create service "%s"; unable to resolve parameter "%s" ' - . 'to a class, interface, or array type', - $requestedName, - $parameter->getName() - )); - } - - return $parameter->getDefaultValue(); - } - - $type = $this->aliases[$type] ?? $type; - - if ($container->has($type)) { - return $container->get($type); - } - - if (! $parameter->isOptional()) { - throw new ServiceNotFoundException(sprintf( - 'Unable to create service "%s"; unable to resolve parameter "%s" using type hint "%s"', - $requestedName, - $parameter->getName(), - $type - )); - } - - // Type not available in container, but the value is optional and has a - // default defined. - return $parameter->getDefaultValue(); - } -} diff --git a/lib/laminas/laminas-servicemanager/src/AbstractFactoryInterface.php b/lib/laminas/laminas-servicemanager/src/AbstractFactoryInterface.php deleted file mode 100644 index 2a8ff71b2..000000000 --- a/lib/laminas/laminas-servicemanager/src/AbstractFactoryInterface.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager; - -/** - * Backwards-compatibility shim for AbstractFactoryInterface. - * - * Implementations should update to implement only Laminas\ServiceManager\Factory\AbstractFactoryInterface. - * - * If upgrading from v2, take the following steps: - * - * - rename the method `canCreateServiceWithName()` to `canCreate()`, and: - * - rename the `$serviceLocator` argument to `$container`, and change the - * typehint to `Psr\Container\ContainerInterface` - * - merge the `$name` and `$requestedName` arguments - * - rename the method `createServiceWithName()` to `__invoke()`, and: - * - rename the `$serviceLocator` argument to `$container`, and change the - * typehint to `Psr\Container\ContainerInterface` - * - merge the `$name` and `$requestedName` arguments - * - add the optional `array $options = null` argument. - * - create a `canCreateServiceWithName()` method as defined in this interface, and have it - * proxy to `canCreate()`, passing `$requestedName` as the second argument. - * - create a `createServiceWithName()` method as defined in this interface, and have it - * proxy to `__invoke()`, passing `$requestedName` as the second argument. - * - * Once you have tested your code, you can then update your class to only implement - * Laminas\ServiceManager\Factory\AbstractFactoryInterface, and remove the `canCreateServiceWithName()` - * and `createServiceWithName()` methods. - * - * @deprecated Use Laminas\ServiceManager\Factory\AbstractFactoryInterface instead. - */ -interface AbstractFactoryInterface extends Factory\AbstractFactoryInterface -{ - /** - * Determine if we can create a service with name - * - * @param string $name - * @param string $requestedName - * @return bool - */ - public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName); - - /** - * Create service with name - * - * @param string $name - * @param string $requestedName - * @return mixed - */ - public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName); -} diff --git a/lib/laminas/laminas-servicemanager/src/AbstractPluginManager.php b/lib/laminas/laminas-servicemanager/src/AbstractPluginManager.php deleted file mode 100644 index fe8a85d4a..000000000 --- a/lib/laminas/laminas-servicemanager/src/AbstractPluginManager.php +++ /dev/null @@ -1,222 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager; - -use Laminas\ServiceManager\Exception\ContainerModificationsNotAllowedException; -use Laminas\ServiceManager\Exception\InvalidServiceException; -use Psr\Container\ContainerInterface; - -use function class_exists; -use function get_class; -use function gettype; -use function is_object; -use function method_exists; -use function sprintf; -use function trigger_error; - -use const E_USER_DEPRECATED; - -/** - * Abstract plugin manager. - * - * Abstract PluginManagerInterface implementation providing: - * - * - creation context support. The constructor accepts the parent container - * instance, which is then used when creating instances. - * - plugin validation. Implementations may define the `$instanceOf` property - * to indicate what class types constitute valid plugins, omitting the - * requirement to define the `validate()` method. - * - * The implementation extends `ServiceManager`, thus providing the same set - * of capabilities as found in that implementation. - * - * @template InstanceType - * @implements PluginManagerInterface<InstanceType> - * @psalm-import-type ServiceManagerConfiguration from ServiceManager - * @psalm-suppress PropertyNotSetInConstructor - */ -abstract class AbstractPluginManager extends ServiceManager implements PluginManagerInterface -{ - /** - * Whether or not to auto-add a FQCN as an invokable if it exists. - * - * @var bool - */ - protected $autoAddInvokableClass = true; - - /** - * An object type that the created instance must be instanced of - * - * @var null|string - * @psalm-var null|class-string<InstanceType> - */ - protected $instanceOf; - - /** - * Sets the provided $parentLocator as the creation context for all - * factories; for $config, {@see \Laminas\ServiceManager\ServiceManager::configure()} - * for details on its accepted structure. - * - * @param null|ConfigInterface|ContainerInterface $configInstanceOrParentLocator - * @param array $config - * @psalm-param ServiceManagerConfiguration $config - */ - public function __construct($configInstanceOrParentLocator = null, array $config = []) - { - /** @psalm-suppress DocblockTypeContradiction */ - if ( - null !== $configInstanceOrParentLocator - && ! $configInstanceOrParentLocator instanceof ConfigInterface - && ! $configInstanceOrParentLocator instanceof ContainerInterface - ) { - throw new Exception\InvalidArgumentException(sprintf( - '%s expects a ConfigInterface or ContainerInterface instance as the first argument; received %s', - self::class, - is_object($configInstanceOrParentLocator) - ? get_class($configInstanceOrParentLocator) - : gettype($configInstanceOrParentLocator) - )); - } - - if ($configInstanceOrParentLocator instanceof ConfigInterface) { - trigger_error(sprintf( - 'Usage of %s as a constructor argument for %s is now deprecated', - ConfigInterface::class, - static::class - ), E_USER_DEPRECATED); - $config = $configInstanceOrParentLocator->toArray(); - } - - parent::__construct($config); - - if (! $configInstanceOrParentLocator instanceof ContainerInterface) { - trigger_error(sprintf( - '%s now expects a %s instance representing the parent container; please update your code', - __METHOD__, - ContainerInterface::class - ), E_USER_DEPRECATED); - } - - $this->creationContext = $configInstanceOrParentLocator instanceof ContainerInterface - ? $configInstanceOrParentLocator - : $this; - } - - /** - * Override configure() to validate service instances. - * - * @param array $config - * @psalm-param ServiceManagerConfiguration $config - * @return self - * @throws InvalidServiceException If an instance passed in the `services` configuration is invalid for the - * plugin manager. - * @throws ContainerModificationsNotAllowedException If the allow override flag has been toggled off, and a - * service instanceexists for a given service. - */ - public function configure(array $config) - { - if (isset($config['services'])) { - /** @psalm-suppress MixedAssignment */ - foreach ($config['services'] as $service) { - $this->validate($service); - } - } - - parent::configure($config); - - return $this; - } - - /** - * Override setService for additional plugin validation. - * - * {@inheritDoc} - * - * @param string|class-string<InstanceType> $name - * @param InstanceType $service - */ - public function setService($name, $service) - { - $this->validate($service); - parent::setService($name, $service); - } - - /** - * @param class-string<InstanceType>|string $name Service name of plugin to retrieve. - * @param null|array<mixed> $options Options to use when creating the instance. - * @return mixed - * @psalm-return ($name is class-string ? InstanceType : mixed) - * @throws Exception\ServiceNotFoundException If the manager does not have - * a service definition for the instance, and the service is not - * auto-invokable. - * @throws InvalidServiceException If the plugin created is invalid for the - * plugin context. - */ - public function get($name, ?array $options = null) - { - if (! $this->has($name)) { - if (! $this->autoAddInvokableClass || ! class_exists($name)) { - throw new Exception\ServiceNotFoundException(sprintf( - 'A plugin by the name "%s" was not found in the plugin manager %s', - $name, - static::class - )); - } - - $this->setFactory($name, Factory\InvokableFactory::class); - } - - $instance = ! $options ? parent::get($name) : $this->build($name, $options); - $this->validate($instance); - return $instance; - } - - /** - * {@inheritDoc} - * - * @psalm-assert InstanceType $instance - */ - public function validate($instance) - { - if (method_exists($this, 'validatePlugin')) { - trigger_error(sprintf( - '%s::validatePlugin() has been deprecated as of 3.0; please define validate() instead', - static::class - ), E_USER_DEPRECATED); - $this->validatePlugin($instance); - return; - } - - if (empty($this->instanceOf) || $instance instanceof $this->instanceOf) { - return; - } - - throw new InvalidServiceException(sprintf( - 'Plugin manager "%s" expected an instance of type "%s", but "%s" was received', - self::class, - $this->instanceOf, - is_object($instance) ? get_class($instance) : gettype($instance) - )); - } - - /** - * Implemented for backwards compatibility only. - * - * Returns the creation context. - * - * @deprecated since 3.0.0. The creation context should be passed during - * instantiation instead. - * - * @return void - */ - public function setServiceLocator(ContainerInterface $container) - { - trigger_error(sprintf( - 'Usage of %s is deprecated since v3.0.0; please pass the container to the constructor instead', - __METHOD__ - ), E_USER_DEPRECATED); - $this->creationContext = $container; - } -} diff --git a/lib/laminas/laminas-servicemanager/src/Config.php b/lib/laminas/laminas-servicemanager/src/Config.php deleted file mode 100644 index 8024bdc0c..000000000 --- a/lib/laminas/laminas-servicemanager/src/Config.php +++ /dev/null @@ -1,102 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager; - -use Laminas\Stdlib\ArrayUtils; - -use function array_keys; - -/** - * Object for defining configuration and configuring an existing service manager instance. - * - * In order to provide configuration merging capabilities, this class implements - * the same functionality as `Laminas\Stdlib\ArrayUtils::merge()`. That routine - * allows developers to specifically shape how values are merged: - * - * - A value which is an instance of `MergeRemoveKey` indicates the value should - * be removed during merge. - * - A value that is an instance of `MergeReplaceKeyInterface` indicates that the - * value it contains should be used to replace any previous versions. - * - * These features are advanced, and not typically used. If you wish to use them, - * you will need to require the laminas-stdlib package in your application. - * - * @psalm-import-type ServiceManagerConfigurationType from ConfigInterface - */ -class Config implements ConfigInterface -{ - /** @var array<string,bool> */ - private array $allowedKeys = [ - 'abstract_factories' => true, - 'aliases' => true, - 'delegators' => true, - 'factories' => true, - 'initializers' => true, - 'invokables' => true, - 'lazy_services' => true, - 'services' => true, - 'shared' => true, - ]; - - /** - * @var array<string,array> - * @psalm-var ServiceManagerConfigurationType - */ - protected $config = [ - 'abstract_factories' => [], - 'aliases' => [], - 'delegators' => [], - 'factories' => [], - 'initializers' => [], - 'invokables' => [], - 'lazy_services' => [], - 'services' => [], - 'shared' => [], - ]; - - /** - * @psalm-param ServiceManagerConfigurationType $config - */ - public function __construct(array $config = []) - { - // Only merge keys we're interested in - foreach (array_keys($config) as $key) { - if (! isset($this->allowedKeys[$key])) { - unset($config[$key]); - } - } - - /** @psalm-suppress ArgumentTypeCoercion */ - $this->config = $this->merge($this->config, $config); - } - - /** - * @inheritDoc - */ - public function configureServiceManager(ServiceManager $serviceManager) - { - return $serviceManager->configure($this->config); - } - - /** - * @inheritDoc - */ - public function toArray() - { - return $this->config; - } - - /** - * @psalm-param ServiceManagerConfigurationType $a - * @psalm-param ServiceManagerConfigurationType $b - * @psalm-return ServiceManagerConfigurationType - * @psalm-suppress MixedReturnTypeCoercion - */ - private function merge(array $a, array $b) - { - /** @psalm-suppress MixedReturnTypeCoercion */ - return ArrayUtils::merge($a, $b); - } -} diff --git a/lib/laminas/laminas-servicemanager/src/ConfigInterface.php b/lib/laminas/laminas-servicemanager/src/ConfigInterface.php deleted file mode 100644 index a9c8fc59c..000000000 --- a/lib/laminas/laminas-servicemanager/src/ConfigInterface.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager; - -use ArrayAccess; -use Psr\Container\ContainerInterface; - -/** - * @see ContainerInterface - * @see ArrayAccess - * - * @psalm-type AbstractFactoriesConfigurationType = array< - * array-key, - * (class-string<Factory\AbstractFactoryInterface>|Factory\AbstractFactoryInterface) - * > - * @psalm-type DelegatorsConfigurationType = array< - * string, - * array< - * array-key, - * (class-string<Factory\DelegatorFactoryInterface>|Factory\DelegatorFactoryInterface) - * |callable(ContainerInterface,string,callable():object,array<mixed>|null):object - * > - * > - * @psalm-type FactoriesConfigurationType = array< - * string, - * (class-string<Factory\FactoryInterface>|Factory\FactoryInterface) - * |callable(ContainerInterface,string,array<mixed>|null):object - * > - * @psalm-type InitializersConfigurationType = array< - * array-key, - * (class-string<Initializer\InitializerInterface>|Initializer\InitializerInterface) - * |callable(ContainerInterface,object):void - * > - * @psalm-type LazyServicesConfigurationType = array{ - * class_map?:array<string,class-string>, - * proxies_namespace?:non-empty-string, - * proxies_target_dir?:non-empty-string, - * write_proxy_files?:bool - * } - * @psalm-type ServiceManagerConfigurationType = array{ - * abstract_factories?: AbstractFactoriesConfigurationType, - * aliases?: array<string,string>, - * delegators?: DelegatorsConfigurationType, - * factories?: FactoriesConfigurationType, - * initializers?: InitializersConfigurationType, - * invokables?: array<string,string>, - * lazy_services?: LazyServicesConfigurationType, - * services?: array<string,object|array>, - * shared?:array<string,bool> - * } - */ -interface ConfigInterface -{ - /** - * Configure a service manager. - * - * Implementations should pull configuration from somewhere (typically - * local properties) and pass it to a ServiceManager's withConfig() method, - * returning a new instance. - * - * @return ServiceManager - */ - public function configureServiceManager(ServiceManager $serviceManager); - - /** - * Return configuration for a service manager instance as an array. - * - * Implementations MUST return an array compatible with ServiceManager::configure, - * containing one or more of the following keys: - * - * - abstract_factories - * - aliases - * - delegators - * - factories - * - initializers - * - invokables - * - lazy_services - * - services - * - shared - * - * In other words, this should return configuration that can be used to instantiate - * a service manager or plugin manager, or pass to its `withConfig()` method. - * - * @return array - * @psalm-return ServiceManagerConfigurationType - */ - public function toArray(); -} diff --git a/lib/laminas/laminas-servicemanager/src/DelegatorFactoryInterface.php b/lib/laminas/laminas-servicemanager/src/DelegatorFactoryInterface.php deleted file mode 100644 index 1b30ecf60..000000000 --- a/lib/laminas/laminas-servicemanager/src/DelegatorFactoryInterface.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager; - -/** - * Backwards-compatibility shim for DelegatorFactoryInterface. - * - * Implementations should update to implement only Laminas\ServiceManager\Factory\DelegatorFactoryInterface. - * - * If upgrading from v2, take the following steps: - * - * - rename the method `createDelegatorWithName()` to `__invoke()`, and: - * - rename the `$serviceLocator` argument to `$container`, and change the - * typehint to `Psr\Container\ContainerInterface` - * - merge the `$name` and `$requestedName` arguments - * - add the `callable` typehint to the `$callback` argument - * - add the optional `array $options = null` argument as a final argument - * - create a `createDelegatorWithName()` method as defined in this interface, and have it - * proxy to `__invoke()`, passing `$requestedName` as the second argument. - * - * Once you have tested your code, you can then update your class to only implement - * Laminas\ServiceManager\Factory\DelegatorFactoryInterface, and remove the `createDelegatorWithName()` - * method. - * - * @deprecated Use Laminas\ServiceManager\Factory\DelegatorFactoryInterface instead. - */ -interface DelegatorFactoryInterface extends Factory\DelegatorFactoryInterface -{ - /** - * A factory that creates delegates of a given service - * - * @param ServiceLocatorInterface $serviceLocator the service locator which requested the service - * @param string $name the normalized service name - * @param string $requestedName the requested service name - * @param callable $callback the callback that is responsible for creating the service - * @return mixed - */ - public function createDelegatorWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName, $callback); -} diff --git a/lib/laminas/laminas-servicemanager/src/Exception/ContainerModificationsNotAllowedException.php b/lib/laminas/laminas-servicemanager/src/Exception/ContainerModificationsNotAllowedException.php deleted file mode 100644 index 82d834f59..000000000 --- a/lib/laminas/laminas-servicemanager/src/Exception/ContainerModificationsNotAllowedException.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager\Exception; - -use DomainException; - -use function sprintf; - -class ContainerModificationsNotAllowedException extends DomainException implements ExceptionInterface -{ - /** - * @param string $service Name of service that already exists. - */ - public static function fromExistingService(string $service): self - { - return new self(sprintf( - 'The container does not allow replacing or updating a service' - . ' with existing instances; the following service' - . ' already exists in the container: %s', - $service - )); - } -} diff --git a/lib/laminas/laminas-servicemanager/src/Exception/CyclicAliasException.php b/lib/laminas/laminas-servicemanager/src/Exception/CyclicAliasException.php deleted file mode 100644 index 51a42c2fc..000000000 --- a/lib/laminas/laminas-servicemanager/src/Exception/CyclicAliasException.php +++ /dev/null @@ -1,152 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager\Exception; - -use function array_filter; -use function array_keys; -use function array_map; -use function array_values; -use function implode; -use function reset; -use function serialize; -use function sort; -use function sprintf; - -class CyclicAliasException extends InvalidArgumentException -{ - /** - * @param string $alias conflicting alias key - * @param string[] $aliases map of referenced services, indexed by alias name (string) - */ - public static function fromCyclicAlias(string $alias, array $aliases): self - { - $cycle = $alias; - $cursor = $alias; - while (isset($aliases[$cursor]) && $aliases[$cursor] !== $alias) { - $cursor = $aliases[$cursor]; - $cycle .= ' -> ' . $cursor; - } - $cycle .= ' -> ' . $alias . "\n"; - - return new self(sprintf( - "A cycle was detected within the aliases definitions:\n%s", - $cycle - )); - } - - /** - * @param string[] $aliases map of referenced services, indexed by alias name (string) - * @return self - */ - public static function fromAliasesMap(array $aliases) - { - $detectedCycles = array_filter(array_map( - static fn($alias) => self::getCycleFor($aliases, $alias), - array_keys($aliases) - )); - - if (! $detectedCycles) { - return new self(sprintf( - "A cycle was detected within the following aliases map:\n\n%s", - self::printReferencesMap($aliases) - )); - } - - return new self(sprintf( - "Cycles were detected within the provided aliases:\n\n%s\n\n" - . "The cycle was detected in the following alias map:\n\n%s", - self::printCycles(self::deDuplicateDetectedCycles($detectedCycles)), - self::printReferencesMap($aliases) - )); - } - - /** - * Retrieves the cycle detected for the given $alias, or `null` if no cycle was detected - * - * @param string[] $aliases - * @param string $alias - * @return array|null - */ - private static function getCycleFor(array $aliases, $alias) - { - $cycleCandidate = []; - $targetName = $alias; - - while (isset($aliases[$targetName])) { - if (isset($cycleCandidate[$targetName])) { - return $cycleCandidate; - } - - $cycleCandidate[$targetName] = true; - $targetName = $aliases[$targetName]; - } - - return null; - } - - /** - * @param string[] $aliases - * @return string - */ - private static function printReferencesMap(array $aliases) - { - $map = []; - - foreach ($aliases as $alias => $reference) { - $map[] = '"' . $alias . '" => "' . $reference . '"'; - } - - return "[\n" . implode("\n", $map) . "\n]"; - } - - /** - * @param string[][] $detectedCycles - * @return string - */ - private static function printCycles(array $detectedCycles) - { - return "[\n" . implode("\n", array_map([self::class, 'printCycle'], $detectedCycles)) . "\n]"; - } - - /** - * @param string[] $detectedCycle - * @return string - * @phpcsSuppress SlevomatCodingStandard.Classes.UnusedPrivateElements.UnusedMethod - */ - private static function printCycle(array $detectedCycle) - { - $fullCycle = array_keys($detectedCycle); - $fullCycle[] = reset($fullCycle); - - return implode( - ' => ', - array_map( - static fn($cycle): string => '"' . $cycle . '"', - $fullCycle - ) - ); - } - - /** - * @param bool[][] $detectedCycles - * @return bool[][] de-duplicated - */ - private static function deDuplicateDetectedCycles(array $detectedCycles) - { - $detectedCyclesByHash = []; - - foreach ($detectedCycles as $detectedCycle) { - $cycleAliases = array_keys($detectedCycle); - - sort($cycleAliases); - - $hash = serialize($cycleAliases); - - $detectedCyclesByHash[$hash] ??= $detectedCycle; - } - - return array_values($detectedCyclesByHash); - } -} diff --git a/lib/laminas/laminas-servicemanager/src/Exception/ExceptionInterface.php b/lib/laminas/laminas-servicemanager/src/Exception/ExceptionInterface.php deleted file mode 100644 index cccc42df5..000000000 --- a/lib/laminas/laminas-servicemanager/src/Exception/ExceptionInterface.php +++ /dev/null @@ -1,14 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager\Exception; - -use Psr\Container\ContainerExceptionInterface; - -/** - * Base exception for all Laminas\ServiceManager exceptions. - */ -interface ExceptionInterface extends ContainerExceptionInterface -{ -} diff --git a/lib/laminas/laminas-servicemanager/src/Exception/InvalidArgumentException.php b/lib/laminas/laminas-servicemanager/src/Exception/InvalidArgumentException.php deleted file mode 100644 index 674ae9bbf..000000000 --- a/lib/laminas/laminas-servicemanager/src/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager\Exception; - -use InvalidArgumentException as SplInvalidArgumentException; -use Laminas\ServiceManager\AbstractFactoryInterface; -use Laminas\ServiceManager\Initializer\InitializerInterface; - -use function get_class; -use function gettype; -use function is_object; -use function sprintf; - -/** - * @inheritDoc - */ -class InvalidArgumentException extends SplInvalidArgumentException implements ExceptionInterface -{ - /** - * @param mixed $initializer - */ - public static function fromInvalidInitializer($initializer): self - { - return new self(sprintf( - 'An invalid initializer was registered. Expected a callable or an' - . ' instance of "%s"; received "%s"', - InitializerInterface::class, - is_object($initializer) ? get_class($initializer) : gettype($initializer) - )); - } - - /** - * @param mixed $abstractFactory - */ - public static function fromInvalidAbstractFactory($abstractFactory): self - { - return new self(sprintf( - 'An invalid abstract factory was registered. Expected an instance of or a valid' - . ' class name resolving to an implementation of "%s", but "%s" was received.', - AbstractFactoryInterface::class, - is_object($abstractFactory) ? get_class($abstractFactory) : gettype($abstractFactory) - )); - } -} diff --git a/lib/laminas/laminas-servicemanager/src/Exception/InvalidServiceException.php b/lib/laminas/laminas-servicemanager/src/Exception/InvalidServiceException.php deleted file mode 100644 index 1837b1d74..000000000 --- a/lib/laminas/laminas-servicemanager/src/Exception/InvalidServiceException.php +++ /dev/null @@ -1,15 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager\Exception; - -use RuntimeException as SplRuntimeException; - -/** - * This exception is thrown by plugin managers when the created object does not match - * the plugin manager's conditions - */ -class InvalidServiceException extends SplRuntimeException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-servicemanager/src/Exception/ServiceNotCreatedException.php b/lib/laminas/laminas-servicemanager/src/Exception/ServiceNotCreatedException.php deleted file mode 100644 index 3b9a45635..000000000 --- a/lib/laminas/laminas-servicemanager/src/Exception/ServiceNotCreatedException.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager\Exception; - -use RuntimeException as SplRuntimeException; - -/** - * This exception is thrown when the service locator do not manage to create - * the service (factory that has an error...) - */ -class ServiceNotCreatedException extends SplRuntimeException implements - ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-servicemanager/src/Exception/ServiceNotFoundException.php b/lib/laminas/laminas-servicemanager/src/Exception/ServiceNotFoundException.php deleted file mode 100644 index 186f33cf7..000000000 --- a/lib/laminas/laminas-servicemanager/src/Exception/ServiceNotFoundException.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager\Exception; - -use InvalidArgumentException as SplInvalidArgumentException; -use Psr\Container\NotFoundExceptionInterface; - -/** - * This exception is thrown when the service locator do not manage to find a - * valid factory to create a service - */ -class ServiceNotFoundException extends SplInvalidArgumentException implements - ExceptionInterface, - NotFoundExceptionInterface -{ -} diff --git a/lib/laminas/laminas-servicemanager/src/Factory/AbstractFactoryInterface.php b/lib/laminas/laminas-servicemanager/src/Factory/AbstractFactoryInterface.php deleted file mode 100644 index f73af4f7f..000000000 --- a/lib/laminas/laminas-servicemanager/src/Factory/AbstractFactoryInterface.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager\Factory; - -use Psr\Container\ContainerInterface; - -/** - * Interface for an abstract factory. - * - * An abstract factory extends the factory interface, but also has an - * additional "canCreate" method, which is called to check if the abstract - * factory has the ability to create an instance for the given service. You - * should limit the number of abstract factories to ensure good performance. - * Starting from ServiceManager v3, remember that you can also attach multiple - * names to the same factory, which reduces the need for abstract factories. - */ -interface AbstractFactoryInterface extends FactoryInterface -{ - /** - * Can the factory create an instance for the service? - * - * @param string $requestedName - * @return bool - */ - public function canCreate(ContainerInterface $container, $requestedName); -} diff --git a/lib/laminas/laminas-servicemanager/src/Factory/DelegatorFactoryInterface.php b/lib/laminas/laminas-servicemanager/src/Factory/DelegatorFactoryInterface.php deleted file mode 100644 index 5e2702d93..000000000 --- a/lib/laminas/laminas-servicemanager/src/Factory/DelegatorFactoryInterface.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager\Factory; - -use Laminas\ServiceManager\Exception\ServiceNotCreatedException; -use Laminas\ServiceManager\Exception\ServiceNotFoundException; -use Psr\Container\ContainerExceptionInterface; -use Psr\Container\ContainerInterface; - -/** - * Delegator factory interface. - * - * Defines the capabilities required by a delegator factory. Delegator - * factories are used to either decorate a service instance, or to allow - * decorating the instantiation of a service instance (for instance, to - * provide optional dependencies via setters, etc.). - */ -interface DelegatorFactoryInterface -{ - /** - * A factory that creates delegates of a given service - * - * @param string $name - * @psalm-param callable():mixed $callback - * @param null|array $options - * @return object - * @throws ServiceNotFoundException If unable to resolve the service. - * @throws ServiceNotCreatedException If an exception is raised when creating a service. - * @throws ContainerExceptionInterface If any other error occurs. - */ - public function __invoke(ContainerInterface $container, $name, callable $callback, ?array $options = null); -} diff --git a/lib/laminas/laminas-servicemanager/src/Factory/FactoryInterface.php b/lib/laminas/laminas-servicemanager/src/Factory/FactoryInterface.php deleted file mode 100644 index 68e61671d..000000000 --- a/lib/laminas/laminas-servicemanager/src/Factory/FactoryInterface.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager\Factory; - -use Laminas\ServiceManager\Exception\ServiceNotCreatedException; -use Laminas\ServiceManager\Exception\ServiceNotFoundException; -use Psr\Container\ContainerExceptionInterface; -use Psr\Container\ContainerInterface; - -/** - * Interface for a factory - * - * A factory is an callable object that is able to create an object. It is - * given the instance of the service locator, the requested name of the class - * you want to create, and any additional options that could be used to - * configure the instance state. - */ -interface FactoryInterface -{ - /** - * Create an object - * - * @param string $requestedName - * @param null|array<mixed> $options - * @return object - * @throws ServiceNotFoundException If unable to resolve the service. - * @throws ServiceNotCreatedException If an exception is raised when creating a service. - * @throws ContainerExceptionInterface If any other error occurs. - */ - public function __invoke(ContainerInterface $container, $requestedName, ?array $options = null); -} diff --git a/lib/laminas/laminas-servicemanager/src/Factory/InvokableFactory.php b/lib/laminas/laminas-servicemanager/src/Factory/InvokableFactory.php deleted file mode 100644 index ab09e38e6..000000000 --- a/lib/laminas/laminas-servicemanager/src/Factory/InvokableFactory.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager\Factory; - -use Psr\Container\ContainerInterface; - -/** - * Factory for instantiating classes with no dependencies or which accept a single array. - * - * The InvokableFactory can be used for any class that: - * - * - has no constructor arguments; - * - accepts a single array of arguments via the constructor. - * - * It replaces the "invokables" and "invokable class" functionality of the v2 - * service manager. - */ -final class InvokableFactory implements FactoryInterface -{ - /** - * {@inheritDoc} - */ - public function __invoke(ContainerInterface $container, $requestedName, ?array $options = null) - { - return null === $options ? new $requestedName() : new $requestedName($options); - } -} diff --git a/lib/laminas/laminas-servicemanager/src/FactoryInterface.php b/lib/laminas/laminas-servicemanager/src/FactoryInterface.php deleted file mode 100644 index f22069ee7..000000000 --- a/lib/laminas/laminas-servicemanager/src/FactoryInterface.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager; - -/** - * Backwards-compatibility shim for FactoryInterface. - * - * Implementations should update to implement only Laminas\ServiceManager\Factory\FactoryInterface. - * - * If upgrading from v2, take the following steps: - * - * - rename the method `createService()` to `__invoke()`, and: - * - rename the `$serviceLocator` argument to `$container`, and change the - * typehint to `Psr\Container\ContainerInterface` - * - add the `$requestedName` as a second argument - * - add the optional `array $options = null` argument as a final argument - * - create a `createService()` method as defined in this interface, and have it - * proxy to `__invoke()`. - * - * Once you have tested your code, you can then update your class to only implement - * Laminas\ServiceManager\Factory\FactoryInterface, and remove the `createService()` - * method. - * - * @deprecated Use Laminas\ServiceManager\Factory\FactoryInterface instead. - */ -interface FactoryInterface extends Factory\FactoryInterface -{ - /** - * Create service - * - * @return mixed - */ - public function createService(ServiceLocatorInterface $serviceLocator); -} diff --git a/lib/laminas/laminas-servicemanager/src/Initializer/InitializerInterface.php b/lib/laminas/laminas-servicemanager/src/Initializer/InitializerInterface.php deleted file mode 100644 index 794f1dc5b..000000000 --- a/lib/laminas/laminas-servicemanager/src/Initializer/InitializerInterface.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager\Initializer; - -use Psr\Container\ContainerInterface; - -/** - * Interface for an initializer - * - * An initializer can be registered to a service locator, and are run after an instance is created - * to inject additional dependencies through setters - */ -interface InitializerInterface -{ - /** - * Initialize the given instance - * - * @param object $instance - * @return void - */ - public function __invoke(ContainerInterface $container, $instance); -} diff --git a/lib/laminas/laminas-servicemanager/src/InitializerInterface.php b/lib/laminas/laminas-servicemanager/src/InitializerInterface.php deleted file mode 100644 index f092e7632..000000000 --- a/lib/laminas/laminas-servicemanager/src/InitializerInterface.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager; - -/** - * Backwards-compatibility shim for InitializerInterface. - * - * Implementations should update to implement only Laminas\ServiceManager\Initializer\InitializerInterface. - * - * If upgrading from v2, take the following steps: - * - * - rename the method `initialize()` to `__invoke()`, and: - * - rename the `$serviceLocator` argument to `$container`, and change the - * typehint to `Psr\Container\ContainerInterface` - * - swap the order of the arguments (so that `$instance` comes second) - * - create an `initialize()` method as defined in this interface, and have it - * proxy to `__invoke()`, passing the arguments in the new order. - * - * Once you have tested your code, you can then update your class to only implement - * Laminas\ServiceManager\Initializer\InitializerInterface, and remove the `initialize()` - * method. - * - * @deprecated Use Laminas\ServiceManager\Initializer\InitializerInterface instead. - */ -interface InitializerInterface extends Initializer\InitializerInterface -{ - /** - * Initialize - * - * @param mixed $instance - * @return mixed - */ - public function initialize($instance, ServiceLocatorInterface $serviceLocator); -} diff --git a/lib/laminas/laminas-servicemanager/src/PluginManagerInterface.php b/lib/laminas/laminas-servicemanager/src/PluginManagerInterface.php deleted file mode 100644 index f0d1540b4..000000000 --- a/lib/laminas/laminas-servicemanager/src/PluginManagerInterface.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager; - -use Laminas\ServiceManager\Exception\InvalidServiceException; -use Psr\Container\ContainerExceptionInterface; - -/** - * Interface for a plugin manager - * - * A plugin manager is a specialized service locator used to create homogeneous objects - * - * @template InstanceType - */ -interface PluginManagerInterface extends ServiceLocatorInterface -{ - /** - * Validate an instance - * - * @param mixed $instance - * @return void - * @throws InvalidServiceException If created instance does not respect the - * constraint on type imposed by the plugin manager. - * @throws ContainerExceptionInterface If any other error occurs. - * @psalm-assert InstanceType $instance - */ - public function validate($instance); -} diff --git a/lib/laminas/laminas-servicemanager/src/Proxy/LazyServiceFactory.php b/lib/laminas/laminas-servicemanager/src/Proxy/LazyServiceFactory.php deleted file mode 100644 index a873e8c74..000000000 --- a/lib/laminas/laminas-servicemanager/src/Proxy/LazyServiceFactory.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager\Proxy; - -use Laminas\ServiceManager\Exception; -use Laminas\ServiceManager\Factory\DelegatorFactoryInterface; -use ProxyManager\Factory\LazyLoadingValueHolderFactory; -use ProxyManager\Proxy\LazyLoadingInterface; -use ProxyManager\Proxy\VirtualProxyInterface; -use Psr\Container\ContainerInterface; - -use function sprintf; - -/** - * Delegator factory responsible of instantiating lazy loading value holder proxies of - * given services at runtime - * - * @link https://github.com/Ocramius/ProxyManager/blob/master/docs/lazy-loading-value-holder.md - */ -final class LazyServiceFactory implements DelegatorFactoryInterface -{ - private LazyLoadingValueHolderFactory $proxyFactory; - - /** @var array<string, class-string> map of service names to class names */ - private array $servicesMap; - - /** - * @param array<string, class-string> $servicesMap A map of service names to - * class names of their respective classes - */ - public function __construct(LazyLoadingValueHolderFactory $proxyFactory, array $servicesMap) - { - $this->proxyFactory = $proxyFactory; - $this->servicesMap = $servicesMap; - } - - /** - * {@inheritDoc} - * - * @param string $name - * @return VirtualProxyInterface - */ - public function __invoke(ContainerInterface $container, $name, callable $callback, ?array $options = null) - { - if (isset($this->servicesMap[$name])) { - $initializer = function (&$wrappedInstance, LazyLoadingInterface $proxy) use ($callback) { - $proxy->setProxyInitializer(null); - $wrappedInstance = $callback(); - - return true; - }; - - return $this->proxyFactory->createProxy($this->servicesMap[$name], $initializer); - } - - throw new Exception\ServiceNotFoundException( - sprintf('The requested service "%s" was not found in the provided services map', $name) - ); - } -} diff --git a/lib/laminas/laminas-servicemanager/src/ServiceLocatorInterface.php b/lib/laminas/laminas-servicemanager/src/ServiceLocatorInterface.php deleted file mode 100644 index a0dc4600f..000000000 --- a/lib/laminas/laminas-servicemanager/src/ServiceLocatorInterface.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager; - -use Psr\Container\ContainerExceptionInterface; -use Psr\Container\ContainerInterface; - -/** - * Interface for service locator - */ -interface ServiceLocatorInterface extends ContainerInterface -{ - /** - * Build a service by its name, using optional options (such services are NEVER cached). - * - * @template T of object - * @param string|class-string<T> $name - * @param null|array<mixed> $options - * @return mixed - * @psalm-return ($name is class-string ? T : mixed) - * @throws Exception\ServiceNotFoundException If no factory/abstract - * factory could be found to create the instance. - * @throws Exception\ServiceNotCreatedException If factory/delegator fails - * to create the instance. - * @throws ContainerExceptionInterface If any other error occurs. - */ - public function build($name, ?array $options = null); -} diff --git a/lib/laminas/laminas-servicemanager/src/ServiceManager.php b/lib/laminas/laminas-servicemanager/src/ServiceManager.php deleted file mode 100644 index c87879c12..000000000 --- a/lib/laminas/laminas-servicemanager/src/ServiceManager.php +++ /dev/null @@ -1,983 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager; - -use Exception; -use Laminas\ServiceManager\Exception\ContainerModificationsNotAllowedException; -use Laminas\ServiceManager\Exception\CyclicAliasException; -use Laminas\ServiceManager\Exception\InvalidArgumentException; -use Laminas\ServiceManager\Exception\ServiceNotCreatedException; -use Laminas\ServiceManager\Exception\ServiceNotFoundException; -use Laminas\ServiceManager\Proxy\LazyServiceFactory; -use Laminas\Stdlib\ArrayUtils; -use ProxyManager\Configuration as ProxyConfiguration; -use ProxyManager\Factory\LazyLoadingValueHolderFactory; -use ProxyManager\FileLocator\FileLocator; -use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy; -use ProxyManager\GeneratorStrategy\FileWriterGeneratorStrategy; -use Psr\Container\ContainerExceptionInterface; -use Psr\Container\ContainerInterface; - -use function array_intersect; -use function array_key_exists; -use function array_keys; -use function class_exists; -use function get_class; -use function gettype; -use function in_array; -use function is_callable; -use function is_object; -use function is_string; -use function spl_autoload_register; -use function spl_object_hash; -use function sprintf; -use function trigger_error; - -use const E_USER_DEPRECATED; - -/** - * Service Manager. - * - * Default implementation of the ServiceLocatorInterface, providing capabilities - * for object creation via: - * - * - factories - * - abstract factories - * - delegator factories - * - lazy service factories (generated proxies) - * - initializers (interface injection) - * - * It also provides the ability to inject specific service instances and to - * define aliases. - * - * @see ConfigInterface - * - * @psalm-import-type ServiceManagerConfigurationType from ConfigInterface - * @psalm-import-type AbstractFactoriesConfigurationType from ConfigInterface - * @psalm-import-type DelegatorsConfigurationType from ConfigInterface - * @psalm-import-type FactoriesConfigurationType from ConfigInterface - * @psalm-import-type InitializersConfigurationType from ConfigInterface - * @psalm-import-type LazyServicesConfigurationType from ConfigInterface - * @psalm-type ServiceManagerConfiguration = array{shared_by_default?:bool}&ServiceManagerConfigurationType - */ -class ServiceManager implements ServiceLocatorInterface -{ - /** @var Factory\AbstractFactoryInterface[] */ - protected $abstractFactories = []; - - /** - * A list of aliases - * - * Should map one alias to a service name, or another alias (aliases are recursively resolved) - * - * @var string[] - */ - protected $aliases = []; - - /** - * Whether or not changes may be made to this instance. - * - * @var bool - */ - protected $allowOverride = false; - - /** @var ContainerInterface */ - protected $creationContext; - - /** - * @var string[][]|Factory\DelegatorFactoryInterface[][] - * @psalm-var DelegatorsConfigurationType - */ - protected $delegators = []; - - /** - * A list of factories (either as string name or callable) - * - * @var string[]|callable[] - * @psalm-var FactoriesConfigurationType - */ - protected $factories = []; - - /** - * @var Initializer\InitializerInterface[]|callable[] - * @psalm-var InitializersConfigurationType - */ - protected $initializers = []; - - /** - * @var array - * @psalm-var LazyServicesConfigurationType - */ - protected $lazyServices = []; - - private ?LazyServiceFactory $lazyServicesDelegator = null; - - /** - * A list of already loaded services (this act as a local cache) - * - * @var array<string,array|object> - */ - protected $services = []; - - /** - * Enable/disable shared instances by service name. - * - * Example configuration: - * - * 'shared' => [ - * MyService::class => true, // will be shared, even if "sharedByDefault" is false - * MyOtherService::class => false // won't be shared, even if "sharedByDefault" is true - * ] - * - * @var array<string,bool> - */ - protected $shared = []; - - /** - * Should the services be shared by default? - * - * @var bool - */ - protected $sharedByDefault = true; - - /** - * Service manager was already configured? - * - * @var bool - */ - protected $configured = false; - - /** - * Cached abstract factories from string. - */ - private array $cachedAbstractFactories = []; - - /** - * See {@see \Laminas\ServiceManager\ServiceManager::configure()} for details - * on what $config accepts. - * - * @param array $config - * @psalm-param ServiceManagerConfiguration $config - */ - public function __construct(array $config = []) - { - $this->creationContext = $this; - $this->configure($config); - } - - /** - * Implemented for backwards compatibility with previous plugin managers only. - * - * Returns the creation context. - * - * @deprecated since 3.0.0. Factories using 3.0 should use the container - * instance passed to the factory instead. - * - * @return ContainerInterface - */ - public function getServiceLocator() - { - trigger_error(sprintf( - 'Usage of %s is deprecated since v3.0.0; please use the container passed to the factory instead', - __METHOD__ - ), E_USER_DEPRECATED); - return $this->creationContext; - } - - /** - * {@inheritDoc} - */ - public function get($name) - { - // We start by checking if we have cached the requested service; - // this is the fastest method. - if (isset($this->services[$name])) { - return $this->services[$name]; - } - - // Determine if the service should be shared. - $sharedService = $this->shared[$name] ?? $this->sharedByDefault; - - // We achieve better performance if we can let all alias - // considerations out. - if (! $this->aliases) { - $object = $this->doCreate($name); - - // Cache the object for later, if it is supposed to be shared. - if ($sharedService) { - $this->services[$name] = $object; - } - return $object; - } - - // We now deal with requests which may be aliases. - $resolvedName = $this->aliases[$name] ?? $name; - - // Update shared service information as we checked if the alias was shared before. - if ($resolvedName !== $name) { - $sharedService = $this->shared[$resolvedName] ?? $sharedService; - } - - // The following is only true if the requested service is a shared alias. - $sharedAlias = $sharedService && isset($this->services[$resolvedName]); - - // If the alias is configured as a shared service, we are done. - if ($sharedAlias) { - $this->services[$name] = $this->services[$resolvedName]; - return $this->services[$resolvedName]; - } - - // At this point, we have to create the object. - // We use the resolved name for that. - $object = $this->doCreate($resolvedName); - - // Cache the object for later, if it is supposed to be shared. - if ($sharedService) { - $this->services[$resolvedName] = $object; - } - - // Also cache under the alias name; this allows sharing based on the - // service name used. - if ($sharedAlias) { - $this->services[$name] = $object; - } - - return $object; - } - - /** - * {@inheritDoc} - */ - public function build($name, ?array $options = null) - { - // We never cache when using "build". - $name = $this->aliases[$name] ?? $name; - return $this->doCreate($name, $options); - } - - /** - * {@inheritDoc} - * - * @param string|class-string $name - * @return bool - */ - public function has($name) - { - // Check static services and factories first to speedup the most common requests. - return $this->staticServiceOrFactoryCanCreate($name) || $this->abstractFactoryCanCreate($name); - } - - /** - * Indicate whether or not the instance is immutable. - * - * @param bool $flag - */ - public function setAllowOverride($flag) - { - $this->allowOverride = (bool) $flag; - } - - /** - * Retrieve the flag indicating immutability status. - * - * @return bool - */ - public function getAllowOverride() - { - return $this->allowOverride; - } - - /** - * @param array $config - * @psalm-param ServiceManagerConfiguration $config - * @return self - * @throws ContainerModificationsNotAllowedException If the allow - * override flag has been toggled off, and a service instance - * exists for a given service. - */ - public function configure(array $config) - { - // This is a bulk update/initial configuration, - // so we check all definitions up front. - $this->validateServiceNames($config); - - if (isset($config['services'])) { - $this->services = $config['services'] + $this->services; - } - - if (isset($config['invokables']) && ! empty($config['invokables'])) { - $newAliases = $this->createAliasesAndFactoriesForInvokables($config['invokables']); - // override existing aliases with those created by invokables to ensure - // that they are still present after merging aliases later on - $config['aliases'] = $newAliases + ($config['aliases'] ?? []); - } - - if (isset($config['factories'])) { - $this->factories = $config['factories'] + $this->factories; - } - - if (isset($config['delegators'])) { - $this->mergeDelegators($config['delegators']); - } - - if (isset($config['shared'])) { - $this->shared = $config['shared'] + $this->shared; - } - - if (! empty($config['aliases'])) { - $this->aliases = $config['aliases'] + $this->aliases; - $this->mapAliasesToTargets(); - } elseif (! $this->configured && ! empty($this->aliases)) { - $this->mapAliasesToTargets(); - } - - if (isset($config['shared_by_default'])) { - $this->sharedByDefault = $config['shared_by_default']; - } - - // If lazy service configuration was provided, reset the lazy services - // delegator factory. - if (isset($config['lazy_services']) && ! empty($config['lazy_services'])) { - /** @psalm-suppress MixedPropertyTypeCoercion */ - $this->lazyServices = ArrayUtils::merge($this->lazyServices, $config['lazy_services']); - $this->lazyServicesDelegator = null; - } - - // For abstract factories and initializers, we always directly - // instantiate them to avoid checks during service construction. - if (isset($config['abstract_factories'])) { - $abstractFactories = $config['abstract_factories']; - // $key not needed, but foreach is faster than foreach + array_values. - foreach ($abstractFactories as $key => $abstractFactory) { - $this->resolveAbstractFactoryInstance($abstractFactory); - } - } - - if (isset($config['initializers'])) { - $this->resolveInitializers($config['initializers']); - } - - $this->configured = true; - - return $this; - } - - /** - * Add an alias. - * - * @param string $alias - * @param string $target - * @throws ContainerModificationsNotAllowedException If $alias already - * exists as a service and overrides are disallowed. - */ - public function setAlias($alias, $target) - { - if (isset($this->services[$alias]) && ! $this->allowOverride) { - throw ContainerModificationsNotAllowedException::fromExistingService($alias); - } - - $this->mapAliasToTarget($alias, $target); - } - - /** - * Add an invokable class mapping. - * - * @param string $name Service name - * @param null|string $class Class to which to map; if omitted, $name is - * assumed. - * @throws ContainerModificationsNotAllowedException If $name already - * exists as a service and overrides are disallowed. - */ - public function setInvokableClass($name, $class = null) - { - if (isset($this->services[$name]) && ! $this->allowOverride) { - throw ContainerModificationsNotAllowedException::fromExistingService($name); - } - - $this->createAliasesAndFactoriesForInvokables([$name => $class ?? $name]); - } - - /** - * Specify a factory for a given service name. - * - * @param string $name Service name - * @param string|callable|Factory\FactoryInterface $factory Factory to which to map. - * phpcs:disable Generic.Files.LineLength.TooLong - * @psalm-param class-string<Factory\FactoryInterface>|callable(ContainerInterface,string,array<mixed>|null):object|Factory\FactoryInterface $factory - * phpcs:enable Generic.Files.LineLength.TooLong - * @return void - * @throws ContainerModificationsNotAllowedException If $name already - * exists as a service and overrides are disallowed. - */ - public function setFactory($name, $factory) - { - if (isset($this->services[$name]) && ! $this->allowOverride) { - throw ContainerModificationsNotAllowedException::fromExistingService($name); - } - - $this->factories[$name] = $factory; - } - - /** - * Create a lazy service mapping to a class. - * - * @param string $name Service name to map - * @param null|string $class Class to which to map; if not provided, $name - * will be used for the mapping. - */ - public function mapLazyService($name, $class = null) - { - $this->configure(['lazy_services' => ['class_map' => [$name => $class ?: $name]]]); - } - - /** - * Add an abstract factory for resolving services. - * - * @param string|Factory\AbstractFactoryInterface $factory Abstract factory - * instance or class name. - * @psalm-param class-string<Factory\AbstractFactoryInterface>|Factory\AbstractFactoryInterface $factory - */ - public function addAbstractFactory($factory) - { - $this->resolveAbstractFactoryInstance($factory); - } - - /** - * Add a delegator for a given service. - * - * @param string $name Service name - * @param string|callable|Factory\DelegatorFactoryInterface $factory Delegator - * factory to assign. - * @psalm-param class-string<Factory\DelegatorFactoryInterface> - * |callable(ContainerInterface,string,callable,array<mixed>|null) $factory - */ - public function addDelegator($name, $factory) - { - $this->configure(['delegators' => [$name => [$factory]]]); - } - - /** - * Add an initializer. - * - * @param string|callable|Initializer\InitializerInterface $initializer - * @psalm-param class-string<Initializer\InitializerInterface> - * |callable(ContainerInterface,mixed):void - * |Initializer\InitializerInterface $initializer - */ - public function addInitializer($initializer) - { - $this->configure(['initializers' => [$initializer]]); - } - - /** - * Map a service. - * - * @param string $name Service name - * @param array|object $service - * @throws ContainerModificationsNotAllowedException If $name already - * exists as a service and overrides are disallowed. - */ - public function setService($name, $service) - { - if (isset($this->services[$name]) && ! $this->allowOverride) { - throw ContainerModificationsNotAllowedException::fromExistingService($name); - } - $this->services[$name] = $service; - } - - /** - * Add a service sharing rule. - * - * @param string $name Service name - * @param bool $flag Whether or not the service should be shared. - * @throws ContainerModificationsNotAllowedException If $name already - * exists as a service and overrides are disallowed. - */ - public function setShared($name, $flag) - { - if (isset($this->services[$name]) && ! $this->allowOverride) { - throw ContainerModificationsNotAllowedException::fromExistingService($name); - } - - $this->shared[$name] = (bool) $flag; - } - - /** - * Instantiate initializers for to avoid checks during service construction. - * - * @psalm-param InitializersConfigurationType $initializers - */ - private function resolveInitializers(array $initializers): void - { - foreach ($initializers as $initializer) { - if (is_string($initializer) && class_exists($initializer)) { - $initializer = new $initializer(); - } - - if (is_callable($initializer)) { - $this->initializers[] = $initializer; - continue; - } - - throw InvalidArgumentException::fromInvalidInitializer($initializer); - } - } - - /** - * Get a factory for the given service name - * - * @psalm-return (callable(ContainerInterface,string,array<mixed>|null):object)|Factory\FactoryInterface - * @throws ServiceNotFoundException - */ - private function getFactory(string $name): callable - { - $factory = $this->factories[$name] ?? null; - - $lazyLoaded = false; - if (is_string($factory) && class_exists($factory)) { - $factory = new $factory(); - $lazyLoaded = true; - } - - if (is_callable($factory)) { - if ($lazyLoaded) { - $this->factories[$name] = $factory; - } - - return $factory; - } - - // Check abstract factories - foreach ($this->abstractFactories as $abstractFactory) { - if ($abstractFactory->canCreate($this->creationContext, $name)) { - return $abstractFactory; - } - } - - throw new ServiceNotFoundException(sprintf( - 'Unable to resolve service "%s" to a factory; are you certain you provided it during configuration?', - $name - )); - } - - /** - * @return object - */ - private function createDelegatorFromName(string $name, ?array $options = null) - { - $creationCallback = function () use ($name, $options) { - // Code is inlined for performance reason, instead of abstracting the creation - $factory = $this->getFactory($name); - return $factory($this->creationContext, $name, $options); - }; - - $initialCreationContext = $this->creationContext; - - foreach ($this->delegators[$name] as $index => $delegatorFactory) { - $delegatorFactory = $this->delegators[$name][$index]; - - if ($delegatorFactory === LazyServiceFactory::class) { - $delegatorFactory = $this->createLazyServiceDelegatorFactory(); - } elseif (is_string($delegatorFactory) && class_exists($delegatorFactory)) { - $delegatorFactory = new $delegatorFactory(); - } - - $this->assertCallableDelegatorFactory($delegatorFactory); - - $this->delegators[$name][$index] = $delegatorFactory; - - $creationCallback = - /** @return object */ - static fn() => $delegatorFactory($initialCreationContext, $name, $creationCallback, $options); - } - - return $creationCallback(); - } - - /** - * Create a new instance with an already resolved name - * - * This is a highly performance sensitive method, do not modify if you have not benchmarked it carefully - * - * @return object - * @throws ServiceNotFoundException If unable to resolve the service. - * @throws ServiceNotCreatedException If an exception is raised when creating a service. - * @throws ContainerExceptionInterface If any other error occurs. - */ - private function doCreate(string $resolvedName, ?array $options = null) - { - try { - if (! isset($this->delegators[$resolvedName])) { - // Let's create the service by fetching the factory - $factory = $this->getFactory($resolvedName); - $object = $factory($this->creationContext, $resolvedName, $options); - } else { - $object = $this->createDelegatorFromName($resolvedName, $options); - } - } catch (ContainerExceptionInterface $exception) { - throw $exception; - } catch (Exception $exception) { - throw new ServiceNotCreatedException(sprintf( - 'Service with name "%s" could not be created. Reason: %s', - $resolvedName, - $exception->getMessage() - ), (int) $exception->getCode(), $exception); - } - - foreach ($this->initializers as $initializer) { - $initializer($this->creationContext, $object); - } - - return $object; - } - - /** - * Create the lazy services delegator factory. - * - * Creates the lazy services delegator factory based on the lazy_services - * configuration present. - * - * @throws ServiceNotCreatedException When the lazy service class_map configuration is missing. - */ - private function createLazyServiceDelegatorFactory(): LazyServiceFactory - { - if ($this->lazyServicesDelegator) { - return $this->lazyServicesDelegator; - } - - if (! isset($this->lazyServices['class_map'])) { - throw new ServiceNotCreatedException('Missing "class_map" config key in "lazy_services"'); - } - - $factoryConfig = new ProxyConfiguration(); - - if (isset($this->lazyServices['proxies_namespace'])) { - $factoryConfig->setProxiesNamespace($this->lazyServices['proxies_namespace']); - } - - if (isset($this->lazyServices['proxies_target_dir'])) { - $factoryConfig->setProxiesTargetDir($this->lazyServices['proxies_target_dir']); - } - - if (! isset($this->lazyServices['write_proxy_files']) || ! $this->lazyServices['write_proxy_files']) { - $factoryConfig->setGeneratorStrategy(new EvaluatingGeneratorStrategy()); - } else { - $factoryConfig->setGeneratorStrategy(new FileWriterGeneratorStrategy( - new FileLocator($factoryConfig->getProxiesTargetDir()) - )); - } - - spl_autoload_register($factoryConfig->getProxyAutoloader()); - - $this->lazyServicesDelegator = new LazyServiceFactory( - new LazyLoadingValueHolderFactory($factoryConfig), - $this->lazyServices['class_map'] - ); - - return $this->lazyServicesDelegator; - } - - /** - * Merge delegators avoiding multiple same delegators for the same service. - * It works with strings and class instances. - * It's not possible to de-duple anonymous functions - * - * @psalm-param DelegatorsConfigurationType $config - * @psalm-return DelegatorsConfigurationType - */ - private function mergeDelegators(array $config): array - { - foreach ($config as $key => $delegators) { - if (! array_key_exists($key, $this->delegators)) { - $this->delegators[$key] = $delegators; - continue; - } - - foreach ($delegators as $delegator) { - if (! in_array($delegator, $this->delegators[$key], true)) { - $this->delegators[$key][] = $delegator; - } - } - } - - return $this->delegators; - } - - /** - * Create aliases and factories for invokable classes. - * - * If an invokable service name does not match the class it maps to, this - * creates an alias to the class (which will later be mapped as an - * invokable factory). The newly created aliases will be returned as an array. - * - * @param array<string,string> $invokables - * @return array<string,string> - */ - private function createAliasesAndFactoriesForInvokables(array $invokables): array - { - $newAliases = []; - - foreach ($invokables as $name => $class) { - $this->factories[$class] = Factory\InvokableFactory::class; - if ($name !== $class) { - $this->aliases[$name] = $class; - $newAliases[$name] = $class; - } - } - - return $newAliases; - } - - /** - * Determine if a service for any name provided by a service - * manager configuration(services, aliases, factories, ...) - * already exists, and if it exists, determine if is it allowed - * to get overriden. - * - * Validation in the context of this class means, that for - * a given service name we do not have a service instance - * in the cache OR override is explicitly allowed. - * - * @psalm-param ServiceManagerConfigurationType $config - * @throws ContainerModificationsNotAllowedException If any - * service key is invalid. - */ - private function validateServiceNames(array $config): void - { - if ($this->allowOverride || ! $this->configured) { - return; - } - - if (isset($config['services'])) { - foreach (array_keys($config['services']) as $service) { - if (isset($this->services[$service])) { - throw ContainerModificationsNotAllowedException::fromExistingService($service); - } - } - } - - if (isset($config['aliases'])) { - foreach (array_keys($config['aliases']) as $service) { - if (isset($this->services[$service])) { - throw ContainerModificationsNotAllowedException::fromExistingService($service); - } - } - } - - if (isset($config['invokables'])) { - foreach (array_keys($config['invokables']) as $service) { - if (isset($this->services[$service])) { - throw ContainerModificationsNotAllowedException::fromExistingService($service); - } - } - } - - if (isset($config['factories'])) { - foreach (array_keys($config['factories']) as $service) { - if (isset($this->services[$service])) { - throw ContainerModificationsNotAllowedException::fromExistingService($service); - } - } - } - - if (isset($config['delegators'])) { - foreach (array_keys($config['delegators']) as $service) { - if (isset($this->services[$service])) { - throw ContainerModificationsNotAllowedException::fromExistingService($service); - } - } - } - - if (isset($config['shared'])) { - foreach (array_keys($config['shared']) as $service) { - if (isset($this->services[$service])) { - throw ContainerModificationsNotAllowedException::fromExistingService($service); - } - } - } - - if (isset($config['lazy_services']['class_map'])) { - foreach (array_keys($config['lazy_services']['class_map']) as $service) { - if (isset($this->services[$service])) { - throw ContainerModificationsNotAllowedException::fromExistingService($service); - } - } - } - } - - /** - * Assuming that the alias name is valid (see above) resolve/add it. - * - * This is done differently from bulk mapping aliases for performance reasons, as the - * algorithms for mapping a single item efficiently are different from those of mapping - * many. - */ - private function mapAliasToTarget(string $alias, string $target): void - { - // $target is either an alias or something else - // if it is an alias, resolve it - $this->aliases[$alias] = $this->aliases[$target] ?? $target; - - // a self-referencing alias indicates a cycle - if ($alias === $this->aliases[$alias]) { - throw CyclicAliasException::fromCyclicAlias($alias, $this->aliases); - } - - // finally we have to check if existing incomplete alias definitions - // exist which can get resolved by the new alias - if (in_array($alias, $this->aliases)) { - $r = array_intersect($this->aliases, [$alias]); - // found some, resolve them - foreach ($r as $name => $service) { - $this->aliases[$name] = $target; - } - } - } - - /** - * Assuming that all provided alias keys are valid resolve them. - * - * This function maps $this->aliases in place. - * - * This algorithm is an adaptated version of Tarjans Strongly - * Connected Components. Instead of returning the strongly - * connected components (i.e. cycles in our case), we throw. - * If nodes are not strongly connected (i.e. resolvable in - * our case), they get resolved. - * - * This algorithm is fast for mass updates through configure(). - * It is not appropriate if just a single alias is added. - * - * @see mapAliasToTarget above - */ - private function mapAliasesToTargets(): void - { - $tagged = []; - foreach ($this->aliases as $alias => $target) { - if (isset($tagged[$alias])) { - continue; - } - - $tCursor = $this->aliases[$alias]; - $aCursor = $alias; - if ($aCursor === $tCursor) { - throw CyclicAliasException::fromCyclicAlias($alias, $this->aliases); - } - if (! isset($this->aliases[$tCursor])) { - continue; - } - - $stack = []; - - while (isset($this->aliases[$tCursor])) { - $stack[] = $aCursor; - if ($aCursor === $this->aliases[$tCursor]) { - throw CyclicAliasException::fromCyclicAlias($alias, $this->aliases); - } - $aCursor = $tCursor; - $tCursor = $this->aliases[$tCursor]; - } - - $tagged[$aCursor] = true; - - foreach ($stack as $alias) { - if ($alias === $tCursor) { - throw CyclicAliasException::fromCyclicAlias($alias, $this->aliases); - } - $this->aliases[$alias] = $tCursor; - $tagged[$alias] = true; - } - } - } - - /** - * Instantiate abstract factories in order to avoid checks during service construction. - * - * @param string|Factory\AbstractFactoryInterface $abstractFactory - * @psalm-param class-string<Factory\AbstractFactoryInterface>|Factory\AbstractFactoryInterface $abstractFactory - */ - private function resolveAbstractFactoryInstance($abstractFactory): void - { - if (is_string($abstractFactory) && class_exists($abstractFactory)) { - // Cached string factory name - if (! isset($this->cachedAbstractFactories[$abstractFactory])) { - $this->cachedAbstractFactories[$abstractFactory] = new $abstractFactory(); - } - - $abstractFactory = $this->cachedAbstractFactories[$abstractFactory]; - } - - if (! $abstractFactory instanceof Factory\AbstractFactoryInterface) { - throw InvalidArgumentException::fromInvalidAbstractFactory($abstractFactory); - } - - $abstractFactoryObjHash = spl_object_hash($abstractFactory); - $this->abstractFactories[$abstractFactoryObjHash] = $abstractFactory; - } - - /** - * Check if a static service or factory exists for the given name. - */ - private function staticServiceOrFactoryCanCreate(string $name): bool - { - if (isset($this->services[$name]) || isset($this->factories[$name])) { - return true; - } - - $resolvedName = $this->aliases[$name] ?? $name; - if ($resolvedName !== $name) { - return $this->staticServiceOrFactoryCanCreate($resolvedName); - } - - return false; - } - - /** - * Check if an abstract factory exists that can create a service for the given name. - */ - private function abstractFactoryCanCreate(string $name): bool - { - foreach ($this->abstractFactories as $abstractFactory) { - if ($abstractFactory->canCreate($this->creationContext, $name)) { - return true; - } - } - - $resolvedName = $this->aliases[$name] ?? $name; - if ($resolvedName !== $name) { - return $this->abstractFactoryCanCreate($resolvedName); - } - - return false; - } - - /** - * @psalm-param mixed $delegatorFactory - * @psalm-assert callable(ContainerInterface,string,callable():object,array<mixed>|null):object $delegatorFactory - */ - private function assertCallableDelegatorFactory($delegatorFactory): void - { - if ( - $delegatorFactory instanceof Factory\DelegatorFactoryInterface - || is_callable($delegatorFactory) - ) { - return; - } - if (is_string($delegatorFactory)) { - throw new ServiceNotCreatedException(sprintf( - 'An invalid delegator factory was registered; resolved to class or function "%s"' - . ' which does not exist; please provide a valid function name or class name resolving' - . ' to an implementation of %s', - $delegatorFactory, - DelegatorFactoryInterface::class - )); - } - throw new ServiceNotCreatedException(sprintf( - 'A non-callable delegator, "%s", was provided; expected a callable or instance of "%s"', - is_object($delegatorFactory) ? get_class($delegatorFactory) : gettype($delegatorFactory), - DelegatorFactoryInterface::class - )); - } -} diff --git a/lib/laminas/laminas-servicemanager/src/Tool/ConfigDumper.php b/lib/laminas/laminas-servicemanager/src/Tool/ConfigDumper.php deleted file mode 100644 index c9e6b8752..000000000 --- a/lib/laminas/laminas-servicemanager/src/Tool/ConfigDumper.php +++ /dev/null @@ -1,263 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager\Tool; - -use Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory; -use Laminas\ServiceManager\Exception\InvalidArgumentException; -use Psr\Container\ContainerInterface; -use ReflectionClass; -use ReflectionParameter; -use Traversable; - -use function array_filter; -use function array_key_exists; -use function class_exists; -use function date; -use function gettype; -use function implode; -use function interface_exists; -use function is_array; -use function is_int; -use function is_string; -use function sprintf; -use function str_repeat; -use function var_export; - -class ConfigDumper -{ - public const CONFIG_TEMPLATE = <<<EOC -<?php - -/** - * This file generated by %s. - * Generated %s - */ - -return %s; -EOC; - - private ?ContainerInterface $container; - - public function __construct(?ContainerInterface $container = null) - { - $this->container = $container; - } - - /** - * @param array $config - * @param string $className - * @param bool $ignoreUnresolved - * @return array - * @throws InvalidArgumentException For invalid $className. - */ - public function createDependencyConfig(array $config, $className, $ignoreUnresolved = false) - { - $this->validateClassName($className); - - $reflectionClass = new ReflectionClass($className); - - // class is an interface; do nothing - if ($reflectionClass->isInterface()) { - return $config; - } - - // class has no constructor, treat it as an invokable - if (! $reflectionClass->getConstructor()) { - return $this->createInvokable($config, $className); - } - - $constructorArguments = $reflectionClass->getConstructor()->getParameters(); - $constructorArguments = array_filter( - $constructorArguments, - static fn(ReflectionParameter $argument): bool => ! $argument->isOptional() - ); - - // has no required parameters, treat it as an invokable - if (empty($constructorArguments)) { - return $this->createInvokable($config, $className); - } - - $classConfig = []; - - foreach ($constructorArguments as $constructorArgument) { - $type = $constructorArgument->getType(); - $argumentType = null !== $type && ! $type->isBuiltin() ? $type->getName() : null; - - if ($argumentType === null) { - if ($ignoreUnresolved) { - // don't throw an exception, just return the previous config - return $config; - } - // don't throw an exception if the class is an already defined service - if ($this->container && $this->container->has($className)) { - return $config; - } - throw new InvalidArgumentException(sprintf( - 'Cannot create config for constructor argument "%s", ' - . 'it has no type hint, or non-class/interface type hint', - $constructorArgument->getName() - )); - } - $config = $this->createDependencyConfig($config, $argumentType, $ignoreUnresolved); - $classConfig[] = $argumentType; - } - - $config[ConfigAbstractFactory::class][$className] = $classConfig; - - return $config; - } - - /** - * @param string $className - * @throws InvalidArgumentException If class name is not a string or does - * not exist. - */ - private function validateClassName($className) - { - if (! is_string($className)) { - throw new InvalidArgumentException('Class name must be a string, ' . gettype($className) . ' given'); - } - - if (! class_exists($className) && ! interface_exists($className)) { - throw new InvalidArgumentException('Cannot find class or interface with name ' . $className); - } - } - - /** - * @param array $config - * @param string $className - * @return array - */ - private function createInvokable(array $config, $className) - { - $config[ConfigAbstractFactory::class][$className] = []; - return $config; - } - - /** - * @param array $config - * @return array - * @throws InvalidArgumentException If ConfigAbstractFactory configuration - * value is not an array. - */ - public function createFactoryMappingsFromConfig(array $config) - { - if (! array_key_exists(ConfigAbstractFactory::class, $config)) { - return $config; - } - - if (! is_array($config[ConfigAbstractFactory::class])) { - throw new InvalidArgumentException( - 'Config key for ' . ConfigAbstractFactory::class . ' should be an array, ' . gettype( - $config[ConfigAbstractFactory::class] - ) . ' given' - ); - } - - foreach ($config[ConfigAbstractFactory::class] as $className => $dependency) { - $config = $this->createFactoryMappings($config, $className); - } - return $config; - } - - /** - * @param array $config - * @param string $className - * @return array - */ - public function createFactoryMappings(array $config, $className) - { - $this->validateClassName($className); - - if ( - array_key_exists('service_manager', $config) - && array_key_exists('factories', $config['service_manager']) - && array_key_exists($className, $config['service_manager']['factories']) - ) { - return $config; - } - - $config['service_manager']['factories'][$className] = ConfigAbstractFactory::class; - return $config; - } - - /** - * @param array $config - * @return string - */ - public function dumpConfigFile(array $config) - { - $prepared = $this->prepareConfig($config); - return sprintf( - self::CONFIG_TEMPLATE, - static::class, - date('Y-m-d H:i:s'), - $prepared - ); - } - - /** - * @param array|Traversable $config - * @param int $indentLevel - * @return string - */ - private function prepareConfig($config, $indentLevel = 1) - { - $indent = str_repeat(' ', $indentLevel * 4); - $entries = []; - foreach ($config as $key => $value) { - $key = $this->createConfigKey($key); - $entries[] = sprintf( - '%s%s%s,', - $indent, - $key ? sprintf('%s => ', $key) : '', - $this->createConfigValue($value, $indentLevel) - ); - } - - $outerIndent = str_repeat(' ', ($indentLevel - 1) * 4); - - return sprintf( - "[\n%s\n%s]", - implode("\n", $entries), - $outerIndent - ); - } - - /** - * @param string|int|null $key - * @return null|string - */ - private function createConfigKey($key) - { - if (is_string($key) && class_exists($key)) { - return sprintf('\\%s::class', $key); - } - - if (is_int($key)) { - return null; - } - - return sprintf("'%s'", $key); - } - - /** - * @param mixed $value - * @param int $indentLevel - * @return string - */ - private function createConfigValue($value, $indentLevel) - { - if (is_array($value) || $value instanceof Traversable) { - return $this->prepareConfig($value, $indentLevel + 1); - } - - if (is_string($value) && class_exists($value)) { - return sprintf('\\%s::class', $value); - } - - return var_export($value, true); - } -} diff --git a/lib/laminas/laminas-servicemanager/src/Tool/ConfigDumperCommand.php b/lib/laminas/laminas-servicemanager/src/Tool/ConfigDumperCommand.php deleted file mode 100644 index 6ce1fda83..000000000 --- a/lib/laminas/laminas-servicemanager/src/Tool/ConfigDumperCommand.php +++ /dev/null @@ -1,248 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager\Tool; - -use Laminas\ServiceManager\Exception; -use Laminas\Stdlib\ConsoleHelper; - -use function array_shift; -use function class_exists; -use function dirname; -use function file_exists; -use function file_put_contents; -use function in_array; -use function is_array; -use function is_writable; -use function sprintf; - -use const STDERR; -use const STDOUT; - -/** - * @psalm-type HelpObject = object{ - * command: string - * } - * @psalm-type ErrorObject = object{ - * command: string, - * message: string - * } - * @psalm-type ArgumentObject = object{ - * command: string, - * configFile: string, - * config: array<array-key, mixed>, - * class: string, - * ignoreUnresolved: bool - * } - */ -class ConfigDumperCommand -{ - public const COMMAND_DUMP = 'dump'; - public const COMMAND_ERROR = 'error'; - public const COMMAND_HELP = 'help'; - - public const DEFAULT_SCRIPT_NAME = self::class; - - public const HELP_TEMPLATE = <<<EOH -<info>Usage:</info> - - %s [-h|--help|help] [-i|--ignore-unresolved] <configFile> <className> - -<info>Arguments:</info> - - <info>-h|--help|help</info> This usage message - <info>-i|--ignore-unresolved</info> Ignore classes with unresolved direct dependencies. - <info><configFile></info> Path to a config file for which to generate - configuration. If the file does not exist, it will - be created. If it does exist, it must return an - array, and the file will be updated with new - configuration. - <info><className></info> Name of the class to reflect and for which to - generate dependency configuration. - -Reads the provided configuration file (creating it if it does not exist), -and injects it with ConfigAbstractFactory dependency configuration for -the provided class name, writing the changes back to the file. -EOH; - - private ConsoleHelper $helper; - - private string $scriptName; - - /** - * @param string $scriptName - */ - public function __construct($scriptName = self::DEFAULT_SCRIPT_NAME, ?ConsoleHelper $helper = null) - { - $this->scriptName = $scriptName; - $this->helper = $helper ?: new ConsoleHelper(); - } - - /** - * @param array $args Argument list, minus script name - * @return int Exit status - */ - public function __invoke(array $args) - { - $arguments = $this->parseArgs($args); - - switch ($arguments->command) { - case self::COMMAND_HELP: - $this->help(); - return 0; - case self::COMMAND_ERROR: - $this->helper->writeErrorMessage($arguments->message); - $this->help(STDERR); - return 1; - case self::COMMAND_DUMP: - // fall-through - default: - break; - } - - $dumper = new ConfigDumper(); - try { - $config = $dumper->createDependencyConfig( - $arguments->config, - $arguments->class, - $arguments->ignoreUnresolved - ); - } catch (Exception\InvalidArgumentException $e) { - $this->helper->writeErrorMessage(sprintf( - 'Unable to create config for "%s": %s', - $arguments->class, - $e->getMessage() - )); - $this->help(STDERR); - return 1; - } - - file_put_contents($arguments->configFile, $dumper->dumpConfigFile($config)); - - $this->helper->writeLine(sprintf( - '<info>[DONE]</info> Changes written to %s', - $arguments->configFile - )); - return 0; - } - - /** - * @param array $args - * @return object - */ - private function parseArgs(array $args) - { - if (! $args) { - return $this->createHelpArgument(); - } - - $arg1 = array_shift($args); - - if (in_array($arg1, ['-h', '--help', 'help'], true)) { - return $this->createHelpArgument(); - } - - $ignoreUnresolved = false; - if (in_array($arg1, ['-i', '--ignore-unresolved'], true)) { - $ignoreUnresolved = true; - $arg1 = array_shift($args); - } - - if (! $args) { - return $this->createErrorArgument('Missing class name'); - } - - $configFile = $arg1; - switch (file_exists($configFile)) { - case true: - $config = require $configFile; - - if (! is_array($config)) { - return $this->createErrorArgument(sprintf( - 'Configuration at path "%s" does not return an array.', - $configFile - )); - } - - break; - case false: - // fall-through - default: - if (! is_writable(dirname($configFile))) { - return $this->createErrorArgument(sprintf( - 'Cannot create configuration at path "%s"; not writable.', - $configFile - )); - } - - $config = []; - break; - } - - $class = array_shift($args); - - if (! class_exists($class)) { - return $this->createErrorArgument(sprintf( - 'Class "%s" does not exist or could not be autoloaded.', - $class - )); - } - - return $this->createArguments(self::COMMAND_DUMP, $configFile, $config, $class, $ignoreUnresolved); - } - - /** - * @param resource $resource Defaults to STDOUT - * @return void - */ - private function help($resource = STDOUT) - { - $this->helper->writeLine(sprintf( - self::HELP_TEMPLATE, - $this->scriptName - ), true, $resource); - } - - /** - * @param string $command - * @param string $configFile File from which config originates, and to - * which it will be written. - * @param array $config Parsed configuration. - * @param string $class Name of class to reflect. - * @param bool $ignoreUnresolved If to ignore classes with unresolved direct dependencies. - * @return ArgumentObject - */ - private function createArguments($command, $configFile, $config, $class, $ignoreUnresolved) - { - return (object) [ - 'command' => $command, - 'configFile' => $configFile, - 'config' => $config, - 'class' => $class, - 'ignoreUnresolved' => $ignoreUnresolved, - ]; - } - - /** - * @param string $message - * @return ErrorObject - */ - private function createErrorArgument($message) - { - return (object) [ - 'command' => self::COMMAND_ERROR, - 'message' => $message, - ]; - } - - /** - * @return HelpObject - */ - private function createHelpArgument() - { - return (object) [ - 'command' => self::COMMAND_HELP, - ]; - } -} diff --git a/lib/laminas/laminas-servicemanager/src/Tool/FactoryCreator.php b/lib/laminas/laminas-servicemanager/src/Tool/FactoryCreator.php deleted file mode 100644 index ae8f39847..000000000 --- a/lib/laminas/laminas-servicemanager/src/Tool/FactoryCreator.php +++ /dev/null @@ -1,164 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager\Tool; - -use Laminas\ServiceManager\Exception\InvalidArgumentException; -use Laminas\ServiceManager\Factory\FactoryInterface; -use Psr\Container\ContainerInterface; -use ReflectionClass; -use ReflectionParameter; - -use function array_filter; -use function array_map; -use function array_merge; -use function array_shift; -use function count; -use function implode; -use function preg_replace; -use function sort; -use function sprintf; -use function str_repeat; -use function strrpos; -use function substr; - -class FactoryCreator -{ - public const FACTORY_TEMPLATE = <<<'EOT' - <?php - - declare(strict_types=1); - - namespace %s; - - %s - - class %sFactory implements FactoryInterface - { - /** - * @param ContainerInterface $container - * @param string $requestedName - * @param null|array $options - * @return %s - */ - public function __invoke(ContainerInterface $container, $requestedName, array $options = null) - { - return new %s(%s); - } - } - - EOT; - - private const IMPORT_ALWAYS = [ - FactoryInterface::class, - ContainerInterface::class, - ]; - - /** - * @param string $className - * @return string - */ - public function createFactory($className) - { - $class = $this->getClassName($className); - - return sprintf( - self::FACTORY_TEMPLATE, - preg_replace('/\\\\' . $class . '$/', '', $className), - $this->createImportStatements($className), - $class, - $class, - $class, - $this->createArgumentString($className) - ); - } - - private function getClassName(string $className): string - { - return substr($className, strrpos($className, '\\') + 1); - } - - /** - * @param string $className - * @return array - */ - private function getConstructorParameters($className) - { - $reflectionClass = new ReflectionClass($className); - - if (! $reflectionClass->getConstructor()) { - return []; - } - - $constructorParameters = $reflectionClass->getConstructor()->getParameters(); - - if (empty($constructorParameters)) { - return []; - } - - $constructorParameters = array_filter( - $constructorParameters, - function (ReflectionParameter $argument): bool { - if ($argument->isOptional()) { - return false; - } - - $type = $argument->getType(); - $class = null !== $type && ! $type->isBuiltin() ? $type->getName() : null; - - if (null === $class) { - throw new InvalidArgumentException(sprintf( - 'Cannot identify type for constructor argument "%s"; ' - . 'no type hint, or non-class/interface type hint', - $argument->getName() - )); - } - - return true; - } - ); - - if (empty($constructorParameters)) { - return []; - } - - return array_map(function (ReflectionParameter $parameter): ?string { - $type = $parameter->getType(); - return null !== $type && ! $type->isBuiltin() ? $type->getName() : null; - }, $constructorParameters); - } - - /** - * @param string $className - * @return string - */ - private function createArgumentString($className) - { - $arguments = array_map(fn(string $dependency): string - => sprintf('$container->get(\\%s::class)', $dependency), $this->getConstructorParameters($className)); - - switch (count($arguments)) { - case 0: - return ''; - case 1: - return array_shift($arguments); - default: - $argumentPad = str_repeat(' ', 12); - $closePad = str_repeat(' ', 8); - return sprintf( - "\n%s%s\n%s", - $argumentPad, - implode(",\n" . $argumentPad, $arguments), - $closePad - ); - } - } - - private function createImportStatements(string $className): string - { - $imports = array_merge(self::IMPORT_ALWAYS, [$className]); - sort($imports); - return implode("\n", array_map(static fn(string $import): string => sprintf('use %s;', $import), $imports)); - } -} diff --git a/lib/laminas/laminas-servicemanager/src/Tool/FactoryCreatorCommand.php b/lib/laminas/laminas-servicemanager/src/Tool/FactoryCreatorCommand.php deleted file mode 100644 index ec6c1fc69..000000000 --- a/lib/laminas/laminas-servicemanager/src/Tool/FactoryCreatorCommand.php +++ /dev/null @@ -1,154 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\ServiceManager\Tool; - -use Laminas\ServiceManager\Exception; -use Laminas\Stdlib\ConsoleHelper; - -use function array_shift; -use function assert; -use function class_exists; -use function in_array; -use function is_string; -use function sprintf; - -use const STDERR; -use const STDOUT; - -/** - * @psalm-type ArgumentObject = object{command:string, class:null|string, message:null|string} - */ -class FactoryCreatorCommand -{ - public const COMMAND_DUMP = 'dump'; - public const COMMAND_ERROR = 'error'; - public const COMMAND_HELP = 'help'; - - public const DEFAULT_SCRIPT_NAME = self::class; - - public const HELP_TEMPLATE = <<<EOH -<info>Usage:</info> - - %s [-h|--help|help] <className> - -<info>Arguments:</info> - - <info>-h|--help|help</info> This usage message - <info><className></info> Name of the class to reflect and for which to generate - a factory. - -Generates to STDOUT a factory for creating the specified class; this may then -be added to your application, and configured as a factory for the class. -EOH; - - private ConsoleHelper $helper; - - private string $scriptName; - - /** - * @param string $scriptName - */ - public function __construct($scriptName = self::DEFAULT_SCRIPT_NAME, ?ConsoleHelper $helper = null) - { - $this->scriptName = $scriptName; - $this->helper = $helper ?: new ConsoleHelper(); - } - - /** - * @param array $args Argument list, minus script name - * @return int Exit status - */ - public function __invoke(array $args) - { - $arguments = $this->parseArgs($args); - - switch ($arguments->command) { - case self::COMMAND_HELP: - $this->help(); - return 0; - case self::COMMAND_ERROR: - assert(is_string($arguments->message)); - $this->helper->writeErrorMessage($arguments->message); - $this->help(STDERR); - return 1; - case self::COMMAND_DUMP: - // fall-through - default: - break; - } - - $generator = new FactoryCreator(); - assert(is_string($arguments->class)); - try { - $factory = $generator->createFactory($arguments->class); - } catch (Exception\InvalidArgumentException $e) { - $this->helper->writeErrorMessage(sprintf( - 'Unable to create factory for "%s": %s', - $arguments->class, - $e->getMessage() - )); - $this->help(STDERR); - return 1; - } - - $this->helper->write($factory, false); - return 0; - } - - /** - * @param array $args - * @return ArgumentObject - */ - private function parseArgs(array $args) - { - if (! $args) { - return $this->createArguments(self::COMMAND_HELP); - } - - $arg1 = array_shift($args); - - if (in_array($arg1, ['-h', '--help', 'help'], true)) { - return $this->createArguments(self::COMMAND_HELP); - } - - $class = $arg1; - - if (! class_exists($class)) { - return $this->createArguments(self::COMMAND_ERROR, null, sprintf( - 'Class "%s" does not exist or could not be autoloaded.', - $class - )); - } - - return $this->createArguments(self::COMMAND_DUMP, $class); - } - - /** - * @param resource $resource Defaults to STDOUT - * @return void - */ - private function help($resource = STDOUT) - { - $this->helper->writeLine(sprintf( - self::HELP_TEMPLATE, - $this->scriptName - ), true, $resource); - } - - /** - * @param string $command - * @param string|null $class Name of class to reflect. - * @param string|null $error Error message, if any. - * @return ArgumentObject - */ - private function createArguments($command, $class = null, $error = null) - { - return (object) [ - 'command' => $command, - 'class' => $class, - 'message' => $error, - ]; - } -} diff --git a/lib/laminas/laminas-servicemanager/src/autoload.php b/lib/laminas/laminas-servicemanager/src/autoload.php deleted file mode 100644 index 76bd64e07..000000000 --- a/lib/laminas/laminas-servicemanager/src/autoload.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php // phpcs:disable WebimpressCodingStandard.PHP.CorrectClassNameCase.Invalid - - -declare(strict_types=1); - -use Interop\Container\Containerinterface as InteropContainerInterface; -use Interop\Container\Exception\ContainerException as InteropContainerException; -use Interop\Container\Exception\NotFoundException as InteropNotFoundException; -use Psr\Container\ContainerExceptionInterface; -use Psr\Container\ContainerInterface; -use Psr\Container\NotFoundExceptionInterface; - -if (! interface_exists(InteropContainerInterface::class, false)) { - class_alias(ContainerInterface::class, InteropContainerInterface::class); -} -if (! interface_exists(InteropContainerException::class, false)) { - class_alias(ContainerExceptionInterface::class, InteropContainerException::class); -} -if (! interface_exists(InteropNotFoundException::class, false)) { - class_alias(NotFoundExceptionInterface::class, InteropNotFoundException::class); -} diff --git a/lib/laminas/laminas-stdlib/COPYRIGHT.md b/lib/laminas/laminas-stdlib/COPYRIGHT.md deleted file mode 100644 index 0a8cccc06..000000000 --- a/lib/laminas/laminas-stdlib/COPYRIGHT.md +++ /dev/null @@ -1 +0,0 @@ -Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/) diff --git a/lib/laminas/laminas-stdlib/LICENSE.md b/lib/laminas/laminas-stdlib/LICENSE.md deleted file mode 100644 index 10b40f142..000000000 --- a/lib/laminas/laminas-stdlib/LICENSE.md +++ /dev/null @@ -1,26 +0,0 @@ -Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -- Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -- Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -- Neither the name of Laminas Foundation nor the names of its contributors may - be used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/lib/laminas/laminas-stdlib/README.md b/lib/laminas/laminas-stdlib/README.md deleted file mode 100644 index 764f96573..000000000 --- a/lib/laminas/laminas-stdlib/README.md +++ /dev/null @@ -1,45 +0,0 @@ -# laminas-stdlib - -[![Build Status](https://github.com/laminas/laminas-stdlib/actions/workflows/continuous-integration.yml/badge.svg)](https://github.com/laminas/laminas-stdlib/actions/workflows/continuous-integration.yml) -[![Coverage Status](https://coveralls.io/repos/github/laminas/laminas-stdlib/badge.svg?branch=master)](https://coveralls.io/github/laminas/laminas-stdlib?branch=master) - -> ## 🇷🇺 Русским гражданам -> -> Мы, участники Laminas, родились и живем в разных странах. У многих из нас есть друзья, родственники и коллеги как в России, так и в Украине. Некоторые из нас родились в России. Некоторые из нас живут в России. У некоторых бабушки и дедушки сражались с фашистами во Второй мировой войне. Здесь никто не поддерживает фашизм. -> -> У одного из нас есть украинская родственница, которая спаслась из дома вместе с сыном. Поезд задержался из-за бомбежки на дороге впереди. У нас есть друзья, которые прячутся в бомбоубежищах. Мы с тревогой ждем весточки от них после воздушных налетов, которые беспорядочно наносят удары и попадают по больницам, школам, детским садам и домам. Мы не берем это из каких-либо СМИ. Мы наблюдаем это напрямую. -> -> Вы доверяете нам достаточно, чтоб использовать наши программы, и мы просим вас довериться нам вновь. Мы нуждаемся в помощи. Выходите и протестуйте против этой бесполезной войны. Остановите кровопролитие. Скажите "Нет войне!" -> -> ## 🇺🇸 To Citizens of Russia -> -> We at Laminas come from all over the world. Many of us have friends, family and colleagues in both Russia and Ukraine. Some of us were born in Russia. Some of us currently live in Russia. Some have grandparents who fought Nazis in World War II. Nobody here supports fascism. -> -> One team member has a Ukrainian relative who fled her home with her son. The train was delayed due to bombing on the road ahead. We have friends who are hiding in bomb shelters. We anxiously follow up on them after the air raids, which indiscriminately fire at hospitals, schools, kindergartens and houses. We're not taking this from any media. These are our actual experiences. -> -> You trust us enough to use our software. We ask that you trust us to say the truth on this. We need your help. Go out and protest this unnecessary war. Stop the bloodshed. Say "stop the war!" - -`Laminas\Stdlib` is a set of components that implements general purpose utility -class for different scopes like: - -- array utilities functions; -- general messaging systems; -- string wrappers; -- etc. - ---- - -- File issues at https://github.com/laminas/laminas-stdlib/issues -- Documentation is at https://docs.laminas.dev/laminas-stdlib/ - -## Benchmarks - -We provide scripts for benchmarking laminas-stdlib using the -[PHPBench](https://github.com/phpbench/phpbench) framework; these can be -found in the `benchmark/` directory. - -To execute the benchmarks you can run the following command: - -```bash -$ vendor/bin/phpbench run --report=aggregate -``` diff --git a/lib/laminas/laminas-stdlib/composer.json b/lib/laminas/laminas-stdlib/composer.json deleted file mode 100644 index 711b3fc95..000000000 --- a/lib/laminas/laminas-stdlib/composer.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "name": "laminas/laminas-stdlib", - "description": "SPL extensions, array utilities, error handlers, and more", - "license": "BSD-3-Clause", - "keywords": [ - "laminas", - "stdlib" - ], - "homepage": "https://laminas.dev", - "support": { - "docs": "https://docs.laminas.dev/laminas-stdlib/", - "issues": "https://github.com/laminas/laminas-stdlib/issues", - "source": "https://github.com/laminas/laminas-stdlib", - "rss": "https://github.com/laminas/laminas-stdlib/releases.atom", - "chat": "https://laminas.dev/chat", - "forum": "https://discourse.laminas.dev" - }, - "config": { - "sort-packages": true, - "platform": { - "php": "7.4.99" - }, - "allow-plugins": { - "dealerdirect/phpcodesniffer-composer-installer": true - } - }, - "extra": { - }, - "require": { - "php": "^7.4 || ~8.0.0 || ~8.1.0" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~2.3.0", - "phpbench/phpbench": "^1.2.6", - "phpunit/phpunit": "^9.5.23", - "psalm/plugin-phpunit": "^0.17.0", - "vimeo/psalm": "^4.26", - "phpstan/phpdoc-parser": "^0.5.4" - }, - "autoload": { - "psr-4": { - "Laminas\\Stdlib\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "LaminasTest\\Stdlib\\": "test/", - "LaminasBench\\Stdlib\\": "benchmark/" - } - }, - "scripts": { - "check": [ - "@cs-check", - "@test" - ], - "cs-check": "phpcs", - "cs-fix": "phpcbf", - "static-analysis": "psalm --shepherd --stats", - "test": "phpunit --colors=always", - "test-coverage": "phpunit --colors=always --coverage-clover clover.xml" - }, - "conflict": { - "zendframework/zend-stdlib": "*" - } -} diff --git a/lib/laminas/laminas-stdlib/composer.lock b/lib/laminas/laminas-stdlib/composer.lock deleted file mode 100644 index c2f7beca3..000000000 --- a/lib/laminas/laminas-stdlib/composer.lock +++ /dev/null @@ -1,4852 +0,0 @@ -{ - "_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": "6797353dc8a3d832ed036772471afd74", - "packages": [], - "packages-dev": [ - { - "name": "amphp/amp", - "version": "v2.6.2", - "source": { - "type": "git", - "url": "https://github.com/amphp/amp.git", - "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/amp/zipball/9d5100cebffa729aaffecd3ad25dc5aeea4f13bb", - "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1", - "ext-json": "*", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^7 | ^8 | ^9", - "psalm/phar": "^3.11@dev", - "react/promise": "^2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "files": [ - "lib/functions.php", - "lib/Internal/functions.php" - ], - "psr-4": { - "Amp\\": "lib" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Bob Weinand", - "email": "bobwei9@hotmail.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "A non-blocking concurrency framework for PHP applications.", - "homepage": "https://amphp.org/amp", - "keywords": [ - "async", - "asynchronous", - "awaitable", - "concurrency", - "event", - "event-loop", - "future", - "non-blocking", - "promise" - ], - "support": { - "irc": "irc://irc.freenode.org/amphp", - "issues": "https://github.com/amphp/amp/issues", - "source": "https://github.com/amphp/amp/tree/v2.6.2" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2022-02-20T17:52:18+00:00" - }, - { - "name": "amphp/byte-stream", - "version": "v1.8.1", - "source": { - "type": "git", - "url": "https://github.com/amphp/byte-stream.git", - "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/byte-stream/zipball/acbd8002b3536485c997c4e019206b3f10ca15bd", - "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd", - "shasum": "" - }, - "require": { - "amphp/amp": "^2", - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1.4", - "friendsofphp/php-cs-fixer": "^2.3", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^6 || ^7 || ^8", - "psalm/phar": "^3.11.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "files": [ - "lib/functions.php" - ], - "psr-4": { - "Amp\\ByteStream\\": "lib" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "A stream abstraction to make working with non-blocking I/O simple.", - "homepage": "http://amphp.org/byte-stream", - "keywords": [ - "amp", - "amphp", - "async", - "io", - "non-blocking", - "stream" - ], - "support": { - "irc": "irc://irc.freenode.org/amphp", - "issues": "https://github.com/amphp/byte-stream/issues", - "source": "https://github.com/amphp/byte-stream/tree/v1.8.1" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2021-03-30T17:13:30+00:00" - }, - { - "name": "composer/package-versions-deprecated", - "version": "1.11.99.5", - "source": { - "type": "git", - "url": "https://github.com/composer/package-versions-deprecated.git", - "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/b4f54f74ef3453349c24a845d22392cd31e65f1d", - "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.1.0 || ^2.0", - "php": "^7 || ^8" - }, - "replace": { - "ocramius/package-versions": "1.11.99" - }, - "require-dev": { - "composer/composer": "^1.9.3 || ^2.0@dev", - "ext-zip": "^1.13", - "phpunit/phpunit": "^6.5 || ^7" - }, - "type": "composer-plugin", - "extra": { - "class": "PackageVersions\\Installer", - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "PackageVersions\\": "src/PackageVersions" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be" - } - ], - "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", - "support": { - "issues": "https://github.com/composer/package-versions-deprecated/issues", - "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.5" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-01-17T14:14:24+00:00" - }, - { - "name": "composer/pcre", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/composer/pcre.git", - "reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/e300eb6c535192decd27a85bc72a9290f0d6b3bd", - "reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.3", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Pcre\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "PCRE wrapping library that offers type-safe preg_* replacements.", - "keywords": [ - "PCRE", - "preg", - "regex", - "regular expression" - ], - "support": { - "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.0.0" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-02-25T20:21:48+00:00" - }, - { - "name": "composer/semver", - "version": "3.3.2", - "source": { - "type": "git", - "url": "https://github.com/composer/semver.git", - "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9", - "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.4", - "symfony/phpunit-bridge": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Semver\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - }, - { - "name": "Rob Bast", - "email": "rob.bast@gmail.com", - "homepage": "http://robbast.nl" - } - ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", - "keywords": [ - "semantic", - "semver", - "validation", - "versioning" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.3.2" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-04-01T19:23:25+00:00" - }, - { - "name": "composer/xdebug-handler", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "ced299686f41dce890debac69273b47ffe98a40c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c", - "reference": "ced299686f41dce890debac69273b47ffe98a40c", - "shasum": "" - }, - "require": { - "composer/pcre": "^1 || ^2 || ^3", - "php": "^7.2.5 || ^8.0", - "psr/log": "^1 || ^2 || ^3" - }, - "require-dev": { - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without Xdebug.", - "keywords": [ - "Xdebug", - "performance" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/3.0.3" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-02-25T21:32:43+00:00" - }, - { - "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "v0.7.2", - "source": { - "type": "git", - "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", - "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", - "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.0 || ^2.0", - "php": ">=5.3", - "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" - }, - "require-dev": { - "composer/composer": "*", - "php-parallel-lint/php-parallel-lint": "^1.3.1", - "phpcompatibility/php-compatibility": "^9.0" - }, - "type": "composer-plugin", - "extra": { - "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" - }, - "autoload": { - "psr-4": { - "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Franck Nijhof", - "email": "franck.nijhof@dealerdirect.com", - "homepage": "http://www.frenck.nl", - "role": "Developer / IT Manager" - }, - { - "name": "Contributors", - "homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors" - } - ], - "description": "PHP_CodeSniffer Standards Composer Installer Plugin", - "homepage": "http://www.dealerdirect.com", - "keywords": [ - "PHPCodeSniffer", - "PHP_CodeSniffer", - "code quality", - "codesniffer", - "composer", - "installer", - "phpcbf", - "phpcs", - "plugin", - "qa", - "quality", - "standard", - "standards", - "style guide", - "stylecheck", - "tests" - ], - "support": { - "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues", - "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer" - }, - "time": "2022-02-04T12:51:07+00:00" - }, - { - "name": "dnoegel/php-xdg-base-dir", - "version": "v0.1.1", - "source": { - "type": "git", - "url": "https://github.com/dnoegel/php-xdg-base-dir.git", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "require-dev": { - "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" - }, - "type": "library", - "autoload": { - "psr-4": { - "XdgBaseDir\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "implementation of xdg base directory specification for php", - "support": { - "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", - "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" - }, - "time": "2019-12-04T15:06:13+00:00" - }, - { - "name": "doctrine/annotations", - "version": "1.13.3", - "source": { - "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "648b0343343565c4a056bfc8392201385e8d89f0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/648b0343343565c4a056bfc8392201385e8d89f0", - "reference": "648b0343343565c4a056bfc8392201385e8d89f0", - "shasum": "" - }, - "require": { - "doctrine/lexer": "1.*", - "ext-tokenizer": "*", - "php": "^7.1 || ^8.0", - "psr/cache": "^1 || ^2 || ^3" - }, - "require-dev": { - "doctrine/cache": "^1.11 || ^2.0", - "doctrine/coding-standard": "^6.0 || ^8.1", - "phpstan/phpstan": "^1.4.10 || ^1.8.0", - "phpunit/phpunit": "^7.5 || ^8.0 || ^9.1.5", - "symfony/cache": "^4.4 || ^5.2", - "vimeo/psalm": "^4.10" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Docblock Annotations Parser", - "homepage": "https://www.doctrine-project.org/projects/annotations.html", - "keywords": [ - "annotations", - "docblock", - "parser" - ], - "support": { - "issues": "https://github.com/doctrine/annotations/issues", - "source": "https://github.com/doctrine/annotations/tree/1.13.3" - }, - "time": "2022-07-02T10:48:51+00:00" - }, - { - "name": "doctrine/instantiator", - "version": "1.4.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^0.16 || ^1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.22" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.4.1" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" - } - ], - "time": "2022-03-03T08:28:38+00:00" - }, - { - "name": "doctrine/lexer", - "version": "1.2.3", - "source": { - "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/c268e882d4dbdd85e36e4ad69e02dc284f89d229", - "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9.0", - "phpstan/phpstan": "^1.3", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.11" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "https://www.doctrine-project.org/projects/lexer.html", - "keywords": [ - "annotations", - "docblock", - "lexer", - "parser", - "php" - ], - "support": { - "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/1.2.3" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", - "type": "tidelift" - } - ], - "time": "2022-02-28T11:07:21+00:00" - }, - { - "name": "felixfbecker/advanced-json-rpc", - "version": "v3.2.1", - "source": { - "type": "git", - "url": "https://github.com/felixfbecker/php-advanced-json-rpc.git", - "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447", - "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447", - "shasum": "" - }, - "require": { - "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "php": "^7.1 || ^8.0", - "phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0" - }, - "require-dev": { - "phpunit/phpunit": "^7.0 || ^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "AdvancedJsonRpc\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "ISC" - ], - "authors": [ - { - "name": "Felix Becker", - "email": "felix.b@outlook.com" - } - ], - "description": "A more advanced JSONRPC implementation", - "support": { - "issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues", - "source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.1" - }, - "time": "2021-06-11T22:34:44+00:00" - }, - { - "name": "felixfbecker/language-server-protocol", - "version": "v1.5.2", - "source": { - "type": "git", - "url": "https://github.com/felixfbecker/php-language-server-protocol.git", - "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/6e82196ffd7c62f7794d778ca52b69feec9f2842", - "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "phpstan/phpstan": "*", - "squizlabs/php_codesniffer": "^3.1", - "vimeo/psalm": "^4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "LanguageServerProtocol\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "ISC" - ], - "authors": [ - { - "name": "Felix Becker", - "email": "felix.b@outlook.com" - } - ], - "description": "PHP classes for the Language Server Protocol", - "keywords": [ - "language", - "microsoft", - "php", - "server" - ], - "support": { - "issues": "https://github.com/felixfbecker/php-language-server-protocol/issues", - "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.2" - }, - "time": "2022-03-02T22:36:06+00:00" - }, - { - "name": "laminas/laminas-coding-standard", - "version": "2.3.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-coding-standard.git", - "reference": "bcf6e07fe4690240be7beb6d884d0b0fafa6a251" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-coding-standard/zipball/bcf6e07fe4690240be7beb6d884d0b0fafa6a251", - "reference": "bcf6e07fe4690240be7beb6d884d0b0fafa6a251", - "shasum": "" - }, - "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.7", - "php": "^7.3 || ^8.0", - "slevomat/coding-standard": "^7.0", - "squizlabs/php_codesniffer": "^3.6", - "webimpress/coding-standard": "^1.2" - }, - "type": "phpcodesniffer-standard", - "autoload": { - "psr-4": { - "LaminasCodingStandard\\": "src/LaminasCodingStandard/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Laminas Coding Standard", - "homepage": "https://laminas.dev", - "keywords": [ - "Coding Standard", - "laminas" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-coding-standard/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-coding-standard/issues", - "rss": "https://github.com/laminas/laminas-coding-standard/releases.atom", - "source": "https://github.com/laminas/laminas-coding-standard" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2021-05-29T15:53:59+00:00" - }, - { - "name": "myclabs/deep-copy", - "version": "1.11.0", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" - }, - "require-dev": { - "doctrine/collections": "^1.6.8", - "doctrine/common": "^2.13.3 || ^3.2.2", - "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" - }, - "type": "library", - "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2022-03-03T13:19:32+00:00" - }, - { - "name": "netresearch/jsonmapper", - "version": "v4.0.0", - "source": { - "type": "git", - "url": "https://github.com/cweiske/jsonmapper.git", - "reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d", - "reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=7.1" - }, - "require-dev": { - "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0", - "squizlabs/php_codesniffer": "~3.5" - }, - "type": "library", - "autoload": { - "psr-0": { - "JsonMapper": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "OSL-3.0" - ], - "authors": [ - { - "name": "Christian Weiske", - "email": "cweiske@cweiske.de", - "homepage": "http://github.com/cweiske/jsonmapper/", - "role": "Developer" - } - ], - "description": "Map nested JSON structures onto PHP classes", - "support": { - "email": "cweiske@cweiske.de", - "issues": "https://github.com/cweiske/jsonmapper/issues", - "source": "https://github.com/cweiske/jsonmapper/tree/v4.0.0" - }, - "time": "2020-12-01T19:48:11+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v4.14.0", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/34bea19b6e03d8153165d8f30bba4c3be86184c1", - "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=7.0" - }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.9-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.14.0" - }, - "time": "2022-05-31T20:59:12+00:00" - }, - { - "name": "openlss/lib-array2xml", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/nullivex/lib-array2xml.git", - "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nullivex/lib-array2xml/zipball/a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", - "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "type": "library", - "autoload": { - "psr-0": { - "LSS": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Bryan Tong", - "email": "bryan@nullivex.com", - "homepage": "https://www.nullivex.com" - }, - { - "name": "Tony Butler", - "email": "spudz76@gmail.com", - "homepage": "https://www.nullivex.com" - } - ], - "description": "Array2XML conversion library credit to lalit.org", - "homepage": "https://www.nullivex.com", - "keywords": [ - "array", - "array conversion", - "xml", - "xml conversion" - ], - "support": { - "issues": "https://github.com/nullivex/lib-array2xml/issues", - "source": "https://github.com/nullivex/lib-array2xml/tree/master" - }, - "time": "2019-03-29T20:06:56+00:00" - }, - { - "name": "phar-io/manifest", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.3" - }, - "time": "2021-07-20T11:28:43+00:00" - }, - { - "name": "phar-io/version", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.2.1" - }, - "time": "2022-02-21T01:04:05+00:00" - }, - { - "name": "phpbench/container", - "version": "2.2.1", - "source": { - "type": "git", - "url": "https://github.com/phpbench/container.git", - "reference": "6d555ff7174fca13f9b1ec0b4a089ed41d0ab392" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpbench/container/zipball/6d555ff7174fca13f9b1ec0b4a089ed41d0ab392", - "reference": "6d555ff7174fca13f9b1ec0b4a089ed41d0ab392", - "shasum": "" - }, - "require": { - "psr/container": "^1.0|^2.0", - "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.16", - "phpstan/phpstan": "^0.12.52", - "phpunit/phpunit": "^8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "PhpBench\\DependencyInjection\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Leech", - "email": "daniel@dantleech.com" - } - ], - "description": "Simple, configurable, service container.", - "support": { - "issues": "https://github.com/phpbench/container/issues", - "source": "https://github.com/phpbench/container/tree/2.2.1" - }, - "time": "2022-01-25T10:17:35+00:00" - }, - { - "name": "phpbench/dom", - "version": "0.3.2", - "source": { - "type": "git", - "url": "https://github.com/phpbench/dom.git", - "reference": "b013b717832ddbaadf2a40984b04bc66af9a7110" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpbench/dom/zipball/b013b717832ddbaadf2a40984b04bc66af9a7110", - "reference": "b013b717832ddbaadf2a40984b04bc66af9a7110", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "php": "^7.2||^8.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.18", - "phpstan/phpstan": "^0.12.83", - "phpunit/phpunit": "^8.0||^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "psr-4": { - "PhpBench\\Dom\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Leech", - "email": "daniel@dantleech.com" - } - ], - "description": "DOM wrapper to simplify working with the PHP DOM implementation", - "support": { - "issues": "https://github.com/phpbench/dom/issues", - "source": "https://github.com/phpbench/dom/tree/0.3.2" - }, - "time": "2021-09-24T15:26:07+00:00" - }, - { - "name": "phpbench/phpbench", - "version": "1.2.6", - "source": { - "type": "git", - "url": "https://github.com/phpbench/phpbench.git", - "reference": "c30fac992e72b505a1f131790583647f4d3255c3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpbench/phpbench/zipball/c30fac992e72b505a1f131790583647f4d3255c3", - "reference": "c30fac992e72b505a1f131790583647f4d3255c3", - "shasum": "" - }, - "require": { - "doctrine/annotations": "^1.13", - "ext-dom": "*", - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "ext-tokenizer": "*", - "php": "^7.3 || ^8.0", - "phpbench/container": "^2.1", - "phpbench/dom": "~0.3.1", - "psr/log": "^1.1 || ^2.0 || ^3.0", - "seld/jsonlint": "^1.1", - "symfony/console": "^4.2 || ^5.0 || ^6.0", - "symfony/filesystem": "^4.2 || ^5.0 || ^6.0", - "symfony/finder": "^4.2 || ^5.0 || ^6.0", - "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0", - "symfony/process": "^4.2 || ^5.0 || ^6.0", - "webmozart/path-util": "^2.3" - }, - "require-dev": { - "dantleech/invoke": "^2.0", - "friendsofphp/php-cs-fixer": "^3.0", - "jangregor/phpstan-prophecy": "^0.8.1", - "phpspec/prophecy": "^1.12", - "phpstan/phpstan": "^0.12.7", - "phpunit/phpunit": "^8.5.8 || ^9.0", - "symfony/error-handler": "^5.2 || ^6.0", - "symfony/var-dumper": "^4.0 || ^5.0 || ^6.0" - }, - "suggest": { - "ext-xdebug": "For Xdebug profiling extension." - }, - "bin": [ - "bin/phpbench" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2-dev" - } - }, - "autoload": { - "files": [ - "lib/Report/Func/functions.php" - ], - "psr-4": { - "PhpBench\\": "lib/", - "PhpBench\\Extensions\\XDebug\\": "extensions/xdebug/lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Leech", - "email": "daniel@dantleech.com" - } - ], - "description": "PHP Benchmarking Framework", - "support": { - "issues": "https://github.com/phpbench/phpbench/issues", - "source": "https://github.com/phpbench/phpbench/tree/1.2.6" - }, - "funding": [ - { - "url": "https://github.com/dantleech", - "type": "github" - } - ], - "time": "2022-07-19T19:52:39+00:00" - }, - { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" - }, - "time": "2020-06-27T09:03:43+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "5.3.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", - "shasum": "" - }, - "require": { - "ext-filter": "*", - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", - "webmozart/assert": "^1.9.1" - }, - "require-dev": { - "mockery/mockery": "~1.3.2", - "psalm/phar": "^4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - }, - { - "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" - }, - "time": "2021-10-19T17:43:47+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.6.1", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "77a32518733312af16a44300404e945338981de3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3", - "reference": "77a32518733312af16a44300404e945338981de3", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.0" - }, - "require-dev": { - "ext-tokenizer": "*", - "psalm/phar": "^4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1" - }, - "time": "2022-03-15T21:29:03+00:00" - }, - { - "name": "phpstan/phpdoc-parser", - "version": "0.5.6", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "fac86158ffc7392e49636f77e63684c026df43b8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/fac86158ffc7392e49636f77e63684c026df43b8", - "reference": "fac86158ffc7392e49636f77e63684c026df43b8", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^0.12.87", - "phpstan/phpstan-strict-rules": "^0.12.5", - "phpunit/phpunit": "^9.5", - "symfony/process": "^5.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.5-dev" - } - }, - "autoload": { - "psr-4": { - "PHPStan\\PhpDocParser\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPDoc parser with support for nullable, intersection and generic types", - "support": { - "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/0.5.6" - }, - "time": "2021-08-31T08:08:22+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "9.2.16", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "2593003befdcc10db5e213f9f28814f5aa8ac073" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2593003befdcc10db5e213f9f28814f5aa8ac073", - "reference": "2593003befdcc10db5e213f9f28814f5aa8ac073", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^4.14", - "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.3", - "phpunit/php-text-template": "^2.0.2", - "sebastian/code-unit-reverse-lookup": "^2.0.2", - "sebastian/complexity": "^2.0", - "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0.3", - "sebastian/version": "^3.0.1", - "theseer/tokenizer": "^1.2.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcov": "*", - "ext-xdebug": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.16" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-08-20T05:26:47+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "3.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-12-02T12:48:52+00:00" - }, - { - "name": "phpunit/php-invoker", - "version": "3.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:58:55+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T05:33:50+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "5.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:16:10+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "9.5.23", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "888556852e7e9bbeeedb9656afe46118765ade34" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/888556852e7e9bbeeedb9656afe46118765ade34", - "reference": "888556852e7e9bbeeedb9656afe46118765ade34", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.3.1", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", - "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.13", - "phpunit/php-file-iterator": "^3.0.5", - "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.5", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.3", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.0", - "sebastian/version": "^3.0.2" - }, - "suggest": { - "ext-soap": "*", - "ext-xdebug": "*" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.5-dev" - } - }, - "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.23" - }, - "funding": [ - { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-08-22T14:01:36+00:00" - }, - { - "name": "psalm/plugin-phpunit", - "version": "0.17.0", - "source": { - "type": "git", - "url": "https://github.com/psalm/psalm-plugin-phpunit.git", - "reference": "45951541beef07e93e3ad197daf01da88e85c31d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/psalm/psalm-plugin-phpunit/zipball/45951541beef07e93e3ad197daf01da88e85c31d", - "reference": "45951541beef07e93e3ad197daf01da88e85c31d", - "shasum": "" - }, - "require": { - "composer/package-versions-deprecated": "^1.10", - "composer/semver": "^1.4 || ^2.0 || ^3.0", - "ext-simplexml": "*", - "php": "^7.1 || ^8.0", - "vimeo/psalm": "dev-master || dev-4.x || ^4.5" - }, - "conflict": { - "phpunit/phpunit": "<7.5" - }, - "require-dev": { - "codeception/codeception": "^4.0.3", - "php": "^7.3 || ^8.0", - "phpunit/phpunit": "^7.5 || ^8.0 || ^9.0", - "squizlabs/php_codesniffer": "^3.3.1", - "weirdan/codeception-psalm-module": "^0.11.0", - "weirdan/prophecy-shim": "^1.0 || ^2.0" - }, - "type": "psalm-plugin", - "extra": { - "psalm": { - "pluginClass": "Psalm\\PhpUnitPlugin\\Plugin" - } - }, - "autoload": { - "psr-4": { - "Psalm\\PhpUnitPlugin\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Matt Brown", - "email": "github@muglug.com" - } - ], - "description": "Psalm plugin for PHPUnit", - "support": { - "issues": "https://github.com/psalm/psalm-plugin-phpunit/issues", - "source": "https://github.com/psalm/psalm-plugin-phpunit/tree/0.17.0" - }, - "time": "2022-06-14T17:05:57+00:00" - }, - { - "name": "psr/cache", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Cache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for caching libraries", - "keywords": [ - "cache", - "psr", - "psr-6" - ], - "support": { - "source": "https://github.com/php-fig/cache/tree/master" - }, - "time": "2016-08-06T20:24:11+00:00" - }, - { - "name": "psr/container", - "version": "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": "" - }, - "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/log", - "version": "1.1.4", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "support": { - "source": "https://github.com/php-fig/log/tree/1.1.4" - }, - "time": "2021-05-03T11:20:27+00:00" - }, - { - "name": "sebastian/cli-parser", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", - "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:08:49+00:00" - }, - { - "name": "sebastian/code-unit", - "version": "1.0.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:08:54+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:30:19+00:00" - }, - { - "name": "sebastian/comparator", - "version": "4.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T15:49:45+00:00" - }, - { - "name": "sebastian/complexity", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.7", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", - "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T15:52:27+00:00" - }, - { - "name": "sebastian/diff", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/process": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:10:38+00:00" - }, - { - "name": "sebastian/environment", - "version": "5.1.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-posix": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-04-03T09:37:03+00:00" - }, - { - "name": "sebastian/exporter", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/65e8b7db476c5dd267e65eea9cab77584d3cfff9", - "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-11-11T14:18:36+00:00" - }, - { - "name": "sebastian/global-state", - "version": "5.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-02-14T08:28:10+00:00" - }, - { - "name": "sebastian/lines-of-code", - "version": "1.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.6", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", - "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-28T06:42:11+00:00" - }, - { - "name": "sebastian/object-enumerator", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:12:34+00:00" - }, - { - "name": "sebastian/object-reflector", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:14:26+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:17:30+00:00" - }, - { - "name": "sebastian/resource-operations", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:45:17+00:00" - }, - { - "name": "sebastian/type", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b233b84bc4465aff7b57cf1c4bc75c86d00d6dad", - "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", - "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-03-15T09:54:48+00:00" - }, - { - "name": "sebastian/version", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:39:44+00:00" - }, - { - "name": "seld/jsonlint", - "version": "1.9.0", - "source": { - "type": "git", - "url": "https://github.com/Seldaek/jsonlint.git", - "reference": "4211420d25eba80712bff236a98960ef68b866b7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/4211420d25eba80712bff236a98960ef68b866b7", - "reference": "4211420d25eba80712bff236a98960ef68b866b7", - "shasum": "" - }, - "require": { - "php": "^5.3 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.5", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13" - }, - "bin": [ - "bin/jsonlint" - ], - "type": "library", - "autoload": { - "psr-4": { - "Seld\\JsonLint\\": "src/Seld/JsonLint/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "JSON Linter", - "keywords": [ - "json", - "linter", - "parser", - "validator" - ], - "support": { - "issues": "https://github.com/Seldaek/jsonlint/issues", - "source": "https://github.com/Seldaek/jsonlint/tree/1.9.0" - }, - "funding": [ - { - "url": "https://github.com/Seldaek", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/seld/jsonlint", - "type": "tidelift" - } - ], - "time": "2022-04-01T13:37:23+00:00" - }, - { - "name": "slevomat/coding-standard", - "version": "7.0.15", - "source": { - "type": "git", - "url": "https://github.com/slevomat/coding-standard.git", - "reference": "cc80e59f9b4ca642f02dc1b615c37a9afc2a0f80" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/cc80e59f9b4ca642f02dc1b615c37a9afc2a0f80", - "reference": "cc80e59f9b4ca642f02dc1b615c37a9afc2a0f80", - "shasum": "" - }, - "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7", - "php": "^7.1 || ^8.0", - "phpstan/phpdoc-parser": "0.5.1 - 0.5.6", - "squizlabs/php_codesniffer": "^3.6.0" - }, - "require-dev": { - "phing/phing": "2.17.0", - "php-parallel-lint/php-parallel-lint": "1.3.1", - "phpstan/phpstan": "0.12.98", - "phpstan/phpstan-deprecation-rules": "0.12.6", - "phpstan/phpstan-phpunit": "0.12.22", - "phpstan/phpstan-strict-rules": "0.12.11", - "phpunit/phpunit": "7.5.20|8.5.5|9.5.9" - }, - "type": "phpcodesniffer-standard", - "extra": { - "branch-alias": { - "dev-master": "7.x-dev" - } - }, - "autoload": { - "psr-4": { - "SlevomatCodingStandard\\": "SlevomatCodingStandard" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", - "support": { - "issues": "https://github.com/slevomat/coding-standard/issues", - "source": "https://github.com/slevomat/coding-standard/tree/7.0.15" - }, - "funding": [ - { - "url": "https://github.com/kukulich", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard", - "type": "tidelift" - } - ], - "time": "2021-09-09T10:29:09+00:00" - }, - { - "name": "squizlabs/php_codesniffer", - "version": "3.7.1", - "source": { - "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619", - "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" - }, - "bin": [ - "bin/phpcs", - "bin/phpcbf" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Greg Sherwood", - "role": "lead" - } - ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", - "keywords": [ - "phpcs", - "standards" - ], - "support": { - "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", - "source": "https://github.com/squizlabs/PHP_CodeSniffer", - "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" - }, - "time": "2022-06-18T07:21:10+00:00" - }, - { - "name": "symfony/console", - "version": "v5.4.11", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "535846c7ee6bc4dd027ca0d93220601456734b10" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/535846c7ee6bc4dd027ca0d93220601456734b10", - "reference": "535846c7ee6bc4dd027ca0d93220601456734b10", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.1|^6.0" - }, - "conflict": { - "psr/log": ">=3", - "symfony/dependency-injection": "<4.4", - "symfony/dotenv": "<5.1", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" - }, - "provide": { - "psr/log-implementation": "1.0|2.0" - }, - "require-dev": { - "psr/log": "^1|^2", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/lock": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Eases the creation of beautiful and testable command line interfaces", - "homepage": "https://symfony.com", - "keywords": [ - "cli", - "command line", - "console", - "terminal" - ], - "support": { - "source": "https://github.com/symfony/console/tree/v5.4.11" - }, - "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-07-22T10:42:43+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "v2.5.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-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/v2.5.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-01-02T09:53:40+00:00" - }, - { - "name": "symfony/filesystem", - "version": "v5.4.11", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "6699fb0228d1bc35b12aed6dd5e7455457609ddd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/6699fb0228d1bc35b12aed6dd5e7455457609ddd", - "reference": "6699fb0228d1bc35b12aed6dd5e7455457609ddd", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides basic utilities for the filesystem", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.4.11" - }, - "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-07-20T13:00:38+00:00" - }, - { - "name": "symfony/finder", - "version": "v5.4.11", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "7872a66f57caffa2916a584db1aa7f12adc76f8c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/7872a66f57caffa2916a584db1aa7f12adc76f8c", - "reference": "7872a66f57caffa2916a584db1aa7f12adc76f8c", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Finds files and directories via an intuitive fluent interface", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/finder/tree/v5.4.11" - }, - "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-07-29T07:37:50+00:00" - }, - { - "name": "symfony/options-resolver", - "version": "v5.4.11", - "source": { - "type": "git", - "url": "https://github.com/symfony/options-resolver.git", - "reference": "54f14e36aa73cb8f7261d7686691fd4d75ea2690" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/54f14e36aa73cb8f7261d7686691fd4d75ea2690", - "reference": "54f14e36aa73cb8f7261d7686691fd4d75ea2690", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php73": "~1.0", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\OptionsResolver\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an improved replacement for the array_replace PHP function", - "homepage": "https://symfony.com", - "keywords": [ - "config", - "configuration", - "options" - ], - "support": { - "source": "https://github.com/symfony/options-resolver/tree/v5.4.11" - }, - "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-07-20T13:00:38+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", - "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-ctype": "*" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-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.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "433d05519ce6990bf3530fba6957499d327395c2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2", - "reference": "433d05519ce6990bf3530fba6957499d327395c2", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's grapheme_* functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "grapheme", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "219aa369ceff116e673852dce47c3a41794c14bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd", - "reference": "219aa369ceff116e673852dce47c3a41794c14bd", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-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.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", - "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-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.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-php73", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/e440d35fa0286f77fb45b79a03fedbeda9307e85", - "reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-php80", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace", - "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-10T07:21:04+00:00" - }, - { - "name": "symfony/process", - "version": "v5.4.11", - "source": { - "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "6e75fe6874cbc7e4773d049616ab450eff537bf1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/6e75fe6874cbc7e4773d049616ab450eff537bf1", - "reference": "6e75fe6874cbc7e4773d049616ab450eff537bf1", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Process\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Executes commands in sub-processes", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/process/tree/v5.4.11" - }, - "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-06-27T16:58:25+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v1.1.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "191afdcb5804db960d26d8566b7e9a2843cab3a0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/191afdcb5804db960d26d8566b7e9a2843cab3a0", - "reference": "191afdcb5804db960d26d8566b7e9a2843cab3a0", - "shasum": "" - }, - "require": { - "php": "^7.1.3" - }, - "suggest": { - "psr/container": "", - "symfony/service-implementation": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - } - }, - "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/v1.1.2" - }, - "time": "2019-05-28T07:50:59+00:00" - }, - { - "name": "symfony/string", - "version": "v5.4.11", - "source": { - "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "5eb661e49ad389e4ae2b6e4df8d783a8a6548322" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/5eb661e49ad389e4ae2b6e4df8d783a8a6548322", - "reference": "5eb661e49ad389e4ae2b6e4df8d783a8a6548322", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "~1.15" - }, - "conflict": { - "symfony/translation-contracts": ">=3.0" - }, - "require-dev": { - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/translation-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0|^6.0" - }, - "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/v5.4.11" - }, - "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-07-24T16:15:25+00:00" - }, - { - "name": "theseer/tokenizer", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.1" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2021-07-28T10:34:58+00:00" - }, - { - "name": "vimeo/psalm", - "version": "4.26.0", - "source": { - "type": "git", - "url": "https://github.com/vimeo/psalm.git", - "reference": "6998fabb2bf528b65777bf9941920888d23c03ac" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/6998fabb2bf528b65777bf9941920888d23c03ac", - "reference": "6998fabb2bf528b65777bf9941920888d23c03ac", - "shasum": "" - }, - "require": { - "amphp/amp": "^2.4.2", - "amphp/byte-stream": "^1.5", - "composer/package-versions-deprecated": "^1.8.0", - "composer/semver": "^1.4 || ^2.0 || ^3.0", - "composer/xdebug-handler": "^1.1 || ^2.0 || ^3.0", - "dnoegel/php-xdg-base-dir": "^0.1.1", - "ext-ctype": "*", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-simplexml": "*", - "ext-tokenizer": "*", - "felixfbecker/advanced-json-rpc": "^3.0.3", - "felixfbecker/language-server-protocol": "^1.5", - "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "nikic/php-parser": "^4.13", - "openlss/lib-array2xml": "^1.0", - "php": "^7.1|^8", - "sebastian/diff": "^3.0 || ^4.0", - "symfony/console": "^3.4.17 || ^4.1.6 || ^5.0 || ^6.0", - "symfony/polyfill-php80": "^1.25", - "webmozart/path-util": "^2.3" - }, - "provide": { - "psalm/psalm": "self.version" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.2", - "brianium/paratest": "^4.0||^6.0", - "ext-curl": "*", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpdocumentor/reflection-docblock": "^5", - "phpmyadmin/sql-parser": "5.1.0||dev-master", - "phpspec/prophecy": ">=1.9.0", - "phpunit/phpunit": "^9.0", - "psalm/plugin-phpunit": "^0.16", - "slevomat/coding-standard": "^7.0", - "squizlabs/php_codesniffer": "^3.5", - "symfony/process": "^4.3 || ^5.0 || ^6.0", - "weirdan/prophecy-shim": "^1.0 || ^2.0" - }, - "suggest": { - "ext-curl": "In order to send data to shepherd", - "ext-igbinary": "^2.0.5 is required, used to serialize caching data" - }, - "bin": [ - "psalm", - "psalm-language-server", - "psalm-plugin", - "psalm-refactor", - "psalter" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.x-dev", - "dev-3.x": "3.x-dev", - "dev-2.x": "2.x-dev", - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "files": [ - "src/functions.php", - "src/spl_object_id.php" - ], - "psr-4": { - "Psalm\\": "src/Psalm/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Matthew Brown" - } - ], - "description": "A static analysis tool for finding errors in PHP applications", - "keywords": [ - "code", - "inspection", - "php" - ], - "support": { - "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm/tree/4.26.0" - }, - "time": "2022-07-31T13:10:26+00:00" - }, - { - "name": "webimpress/coding-standard", - "version": "1.2.4", - "source": { - "type": "git", - "url": "https://github.com/webimpress/coding-standard.git", - "reference": "cd0c4b0b97440c337c1f7da17b524674ca2f9ca9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webimpress/coding-standard/zipball/cd0c4b0b97440c337c1f7da17b524674ca2f9ca9", - "reference": "cd0c4b0b97440c337c1f7da17b524674ca2f9ca9", - "shasum": "" - }, - "require": { - "php": "^7.3 || ^8.0", - "squizlabs/php_codesniffer": "^3.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^9.5.13" - }, - "type": "phpcodesniffer-standard", - "extra": { - "dev-master": "1.2.x-dev", - "dev-develop": "1.3.x-dev" - }, - "autoload": { - "psr-4": { - "WebimpressCodingStandard\\": "src/WebimpressCodingStandard/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "description": "Webimpress Coding Standard", - "keywords": [ - "Coding Standard", - "PSR-2", - "phpcs", - "psr-12", - "webimpress" - ], - "support": { - "issues": "https://github.com/webimpress/coding-standard/issues", - "source": "https://github.com/webimpress/coding-standard/tree/1.2.4" - }, - "funding": [ - { - "url": "https://github.com/michalbundyra", - "type": "github" - } - ], - "time": "2022-02-15T19:52:12+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": "" - }, - "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": "webmozart/path-util", - "version": "2.3.0", - "source": { - "type": "git", - "url": "https://github.com/webmozart/path-util.git", - "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725", - "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "webmozart/assert": "~1.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\PathUtil\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.", - "support": { - "issues": "https://github.com/webmozart/path-util/issues", - "source": "https://github.com/webmozart/path-util/tree/2.3.0" - }, - "abandoned": "symfony/filesystem", - "time": "2015-12-17T08:42:14+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": "^7.4 || ~8.0.0 || ~8.1.0" - }, - "platform-dev": [], - "platform-overrides": { - "php": "7.4.99" - }, - "plugin-api-version": "2.3.0" -} diff --git a/lib/laminas/laminas-stdlib/src/AbstractOptions.php b/lib/laminas/laminas-stdlib/src/AbstractOptions.php deleted file mode 100644 index d02221ab1..000000000 --- a/lib/laminas/laminas-stdlib/src/AbstractOptions.php +++ /dev/null @@ -1,194 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -use Traversable; - -use function array_shift; -use function is_array; -use function is_callable; -use function method_exists; -use function preg_replace_callback; -use function sprintf; -use function str_replace; -use function strtolower; -use function ucwords; - -abstract class AbstractOptions implements ParameterObjectInterface -{ - // phpcs:disable PSR2.Classes.PropertyDeclaration.Underscore,WebimpressCodingStandard.NamingConventions.ValidVariableName.NotCamelCapsProperty - - /** - * We use the __ prefix to avoid collisions with properties in - * user-implementations. - * - * @var bool - */ - protected $__strictMode__ = true; - - // phpcs:enable - - /** - * Constructor - * - * @param array|Traversable|null $options - */ - public function __construct($options = null) - { - if (null !== $options) { - $this->setFromArray($options); - } - } - - /** - * Set one or more configuration properties - * - * @param array|Traversable|AbstractOptions $options - * @throws Exception\InvalidArgumentException - * @return AbstractOptions Provides fluent interface - */ - public function setFromArray($options) - { - if ($options instanceof self) { - $options = $options->toArray(); - } - - if (! is_array($options) && ! $options instanceof Traversable) { - throw new Exception\InvalidArgumentException( - sprintf( - 'Parameter provided to %s must be an %s, %s or %s', - __METHOD__, - 'array', - 'Traversable', - self::class - ) - ); - } - - foreach ($options as $key => $value) { - $this->__set($key, $value); - } - - return $this; - } - - /** - * Cast to array - * - * @return array - */ - public function toArray() - { - $array = []; - - /** @param string[] $letters */ - $transform = static function (array $letters): string { - $letter = array_shift($letters); - return '_' . strtolower($letter); - }; - - foreach ($this as $key => $value) { - if ($key === '__strictMode__') { - continue; - } - $normalizedKey = preg_replace_callback('/([A-Z])/', $transform, $key); - $array[$normalizedKey] = $value; - } - - return $array; - } - - /** - * Set a configuration property - * - * @see ParameterObject::__set() - * - * @param string $key - * @param mixed $value - * @throws Exception\BadMethodCallException - * @return void - */ - public function __set($key, $value) - { - $setter = 'set' . str_replace('_', '', $key); - - if (is_callable([$this, $setter])) { - $this->{$setter}($value); - - return; - } - - if ($this->__strictMode__) { - throw new Exception\BadMethodCallException(sprintf( - 'The option "%s" does not have a callable "%s" ("%s") setter method which must be defined', - $key, - 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))), - $setter - )); - } - } - - /** - * Get a configuration property - * - * @see ParameterObject::__get() - * - * @param string $key - * @throws Exception\BadMethodCallException - * @return mixed - */ - public function __get($key) - { - $getter = 'get' . str_replace('_', '', $key); - - if (is_callable([$this, $getter])) { - return $this->{$getter}(); - } - - throw new Exception\BadMethodCallException(sprintf( - 'The option "%s" does not have a callable "%s" getter method which must be defined', - $key, - 'get' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))) - )); - } - - /** - * Test if a configuration property is null - * - * @see ParameterObject::__isset() - * - * @param string $key - * @return bool - */ - public function __isset($key) - { - $getter = 'get' . str_replace('_', '', $key); - - return method_exists($this, $getter) && null !== $this->__get($key); - } - - /** - * Set a configuration property to NULL - * - * @see ParameterObject::__unset() - * - * @param string $key - * @throws Exception\InvalidArgumentException - * @return void - */ - public function __unset($key) - { - try { - $this->__set($key, null); - } catch (Exception\BadMethodCallException $e) { - throw new Exception\InvalidArgumentException( - 'The class property $' . $key . ' cannot be unset as' - . ' NULL is an invalid value for it', - 0, - $e - ); - } - } -} diff --git a/lib/laminas/laminas-stdlib/src/ArrayObject.php b/lib/laminas/laminas-stdlib/src/ArrayObject.php deleted file mode 100644 index 6cc195ddd..000000000 --- a/lib/laminas/laminas-stdlib/src/ArrayObject.php +++ /dev/null @@ -1,505 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -use ArrayAccess; -use Countable; -use Iterator; -use IteratorAggregate; -use ReturnTypeWillChange; -use Serializable; -use UnexpectedValueException; - -use function array_key_exists; -use function array_keys; -use function asort; -use function class_exists; -use function count; -use function get_class; -use function get_object_vars; -use function gettype; -use function in_array; -use function is_array; -use function is_callable; -use function is_object; -use function is_string; -use function ksort; -use function natcasesort; -use function natsort; -use function serialize; -use function sprintf; -use function strpos; -use function uasort; -use function uksort; -use function unserialize; - -/** - * Custom framework ArrayObject implementation - * - * Extends version-specific "abstract" implementation. - */ -class ArrayObject implements IteratorAggregate, ArrayAccess, Serializable, Countable -{ - /** - * Properties of the object have their normal functionality - * when accessed as list (var_dump, foreach, etc.). - */ - public const STD_PROP_LIST = 1; - - /** - * Entries can be accessed as properties (read and write). - */ - public const ARRAY_AS_PROPS = 2; - - /** @var array */ - protected $storage; - - /** @var int */ - protected $flag; - - /** @var string */ - protected $iteratorClass; - - /** @var array */ - protected $protectedProperties; - - /** - * Constructor - * - * @param array|object $input Object values must act like ArrayAccess - * @param int $flags - * @param string $iteratorClass - */ - public function __construct($input = [], $flags = self::STD_PROP_LIST, $iteratorClass = 'ArrayIterator') - { - $this->setFlags($flags); - $this->storage = $input; - $this->setIteratorClass($iteratorClass); - $this->protectedProperties = array_keys(get_object_vars($this)); - } - - /** - * Returns whether the requested key exists - * - * @param mixed $key - * @return bool - */ - public function __isset($key) - { - if ($this->flag === self::ARRAY_AS_PROPS) { - return $this->offsetExists($key); - } - - if (in_array($key, $this->protectedProperties)) { - throw new Exception\InvalidArgumentException("$key is a protected property, use a different key"); - } - - return isset($this->$key); - } - - /** - * Sets the value at the specified key to value - * - * @param mixed $key - * @param mixed $value - * @return void - */ - public function __set($key, $value) - { - if ($this->flag === self::ARRAY_AS_PROPS) { - $this->offsetSet($key, $value); - return; - } - - if (in_array($key, $this->protectedProperties)) { - throw new Exception\InvalidArgumentException("$key is a protected property, use a different key"); - } - - $this->$key = $value; - } - - /** - * Unsets the value at the specified key - * - * @param mixed $key - * @return void - */ - public function __unset($key) - { - if ($this->flag === self::ARRAY_AS_PROPS) { - $this->offsetUnset($key); - return; - } - - if (in_array($key, $this->protectedProperties)) { - throw new Exception\InvalidArgumentException("$key is a protected property, use a different key"); - } - - unset($this->$key); - } - - /** - * Returns the value at the specified key by reference - * - * @param mixed $key - * @return mixed - */ - public function &__get($key) - { - if ($this->flag === self::ARRAY_AS_PROPS) { - $ret = &$this->offsetGet($key); - - return $ret; - } - - if (in_array($key, $this->protectedProperties, true)) { - throw new Exception\InvalidArgumentException("$key is a protected property, use a different key"); - } - - return $this->$key; - } - - /** - * Appends the value - * - * @param mixed $value - * @return void - */ - public function append($value) - { - $this->storage[] = $value; - } - - /** - * Sort the entries by value - * - * @return void - */ - public function asort() - { - asort($this->storage); - } - - /** - * Get the number of public properties in the ArrayObject - * - * @return int - */ - #[ReturnTypeWillChange] - public function count() - { - return count($this->storage); - } - - /** - * Exchange the array for another one. - * - * @param array|ArrayObject|ArrayIterator|object $data - * @return array - */ - public function exchangeArray($data) - { - if (! is_array($data) && ! is_object($data)) { - throw new Exception\InvalidArgumentException( - 'Passed variable is not an array or object, using empty array instead' - ); - } - - if (is_object($data) && ($data instanceof self || $data instanceof \ArrayObject)) { - $data = $data->getArrayCopy(); - } - if (! is_array($data)) { - $data = (array) $data; - } - - $storage = $this->storage; - - $this->storage = $data; - - return $storage; - } - - /** - * Creates a copy of the ArrayObject. - * - * @return array - */ - public function getArrayCopy() - { - return $this->storage; - } - - /** - * Gets the behavior flags. - * - * @return int - */ - public function getFlags() - { - return $this->flag; - } - - /** - * Create a new iterator from an ArrayObject instance - * - * @return Iterator - */ - #[ReturnTypeWillChange] - public function getIterator() - { - $class = $this->iteratorClass; - - return new $class($this->storage); - } - - /** - * Gets the iterator classname for the ArrayObject. - * - * @return string - */ - public function getIteratorClass() - { - return $this->iteratorClass; - } - - /** - * Sort the entries by key - * - * @return void - */ - public function ksort() - { - ksort($this->storage); - } - - /** - * Sort an array using a case insensitive "natural order" algorithm - * - * @return void - */ - public function natcasesort() - { - natcasesort($this->storage); - } - - /** - * Sort entries using a "natural order" algorithm - * - * @return void - */ - public function natsort() - { - natsort($this->storage); - } - - /** - * Returns whether the requested key exists - * - * @param mixed $key - * @return bool - */ - #[ReturnTypeWillChange] - public function offsetExists($key) - { - return isset($this->storage[$key]); - } - - /** - * Returns the value at the specified key - * - * @param mixed $key - * @return mixed - */ - #[ReturnTypeWillChange] - public function &offsetGet($key) - { - $ret = null; - if (! $this->offsetExists($key)) { - return $ret; - } - $ret = &$this->storage[$key]; - - return $ret; - } - - /** - * Sets the value at the specified key to value - * - * @param mixed $key - * @param mixed $value - * @return void - */ - #[ReturnTypeWillChange] - public function offsetSet($key, $value) - { - $this->storage[$key] = $value; - } - - /** - * Unsets the value at the specified key - * - * @param mixed $key - * @return void - */ - #[ReturnTypeWillChange] - public function offsetUnset($key) - { - if ($this->offsetExists($key)) { - unset($this->storage[$key]); - } - } - - /** - * Serialize an ArrayObject - * - * @return string - */ - public function serialize() - { - return serialize($this->__serialize()); - } - - /** - * Magic method used for serializing of an instance. - * - * @return array - */ - public function __serialize() - { - return get_object_vars($this); - } - - /** - * Sets the behavior flags - * - * @param int $flags - * @return void - */ - public function setFlags($flags) - { - $this->flag = $flags; - } - - /** - * Sets the iterator classname for the ArrayObject - * - * @param string $class - * @return void - */ - public function setIteratorClass($class) - { - if (class_exists($class)) { - $this->iteratorClass = $class; - - return; - } - - if (strpos($class, '\\') === 0) { - $class = '\\' . $class; - if (class_exists($class)) { - $this->iteratorClass = $class; - - return; - } - } - - throw new Exception\InvalidArgumentException('The iterator class does not exist'); - } - - /** - * Sort the entries with a user-defined comparison function and maintain key association - * - * @param callable $function - * @return void - */ - public function uasort($function) - { - if (is_callable($function)) { - uasort($this->storage, $function); - } - } - - /** - * Sort the entries by keys using a user-defined comparison function - * - * @param callable $function - * @return void - */ - public function uksort($function) - { - if (is_callable($function)) { - uksort($this->storage, $function); - } - } - - /** - * Unserialize an ArrayObject - * - * @param string $data - * @return void - */ - public function unserialize($data) - { - $toUnserialize = unserialize($data); - if (! is_array($toUnserialize)) { - throw new UnexpectedValueException(sprintf( - 'Cannot deserialize %s instance; corrupt serialization data', - self::class - )); - } - - $this->__unserialize($toUnserialize); - } - - /** - * Magic method used to rebuild an instance. - * - * @param array $data Data array. - * @return void - */ - public function __unserialize($data) - { - $this->protectedProperties = array_keys(get_object_vars($this)); - - // Unserialize protected internal properties first - if (array_key_exists('flag', $data)) { - $this->setFlags((int) $data['flag']); - unset($data['flag']); - } - - if (array_key_exists('storage', $data)) { - if (! is_array($data['storage']) && ! is_object($data['storage'])) { - throw new UnexpectedValueException(sprintf( - 'Cannot deserialize %s instance: corrupt storage data; expected array or object, received %s', - self::class, - gettype($data['storage']) - )); - } - $this->exchangeArray($data['storage']); - unset($data['storage']); - } - - if (array_key_exists('iteratorClass', $data)) { - if (! is_string($data['iteratorClass'])) { - throw new UnexpectedValueException(sprintf( - 'Cannot deserialize %s instance: invalid iteratorClass; expected string, received %s', - self::class, - is_object($data['iteratorClass']) - ? get_class($data['iteratorClass']) - : gettype($data['iteratorClass']) - )); - } - $this->setIteratorClass($data['iteratorClass']); - unset($data['iteratorClass']); - } - - unset($data['protectedProperties']); - - // Unserialize array keys after resolving protected properties to ensure configuration is used. - foreach ($data as $k => $v) { - $this->__set($k, $v); - } - } -} diff --git a/lib/laminas/laminas-stdlib/src/ArraySerializableInterface.php b/lib/laminas/laminas-stdlib/src/ArraySerializableInterface.php deleted file mode 100644 index f2544535b..000000000 --- a/lib/laminas/laminas-stdlib/src/ArraySerializableInterface.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -interface ArraySerializableInterface -{ - /** - * Exchange internal values from provided array - * - * @param array $array - * @return void - */ - public function exchangeArray(array $array); - - /** - * Return an array representation of the object - * - * @return array - */ - public function getArrayCopy(); -} diff --git a/lib/laminas/laminas-stdlib/src/ArrayStack.php b/lib/laminas/laminas-stdlib/src/ArrayStack.php deleted file mode 100644 index d25ba5a6e..000000000 --- a/lib/laminas/laminas-stdlib/src/ArrayStack.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -use ArrayIterator; -use ArrayObject as PhpArrayObject; -use ReturnTypeWillChange; - -use function array_reverse; - -/** - * ArrayObject that acts as a stack with regards to iteration - */ -class ArrayStack extends PhpArrayObject -{ - /** - * Retrieve iterator - * - * Retrieve an array copy of the object, reverse its order, and return an - * ArrayIterator with that reversed array. - * - * @return ArrayIterator - */ - #[ReturnTypeWillChange] - public function getIterator() - { - $array = $this->getArrayCopy(); - return new ArrayIterator(array_reverse($array)); - } -} diff --git a/lib/laminas/laminas-stdlib/src/ArrayUtils.php b/lib/laminas/laminas-stdlib/src/ArrayUtils.php deleted file mode 100644 index 285e644dd..000000000 --- a/lib/laminas/laminas-stdlib/src/ArrayUtils.php +++ /dev/null @@ -1,338 +0,0 @@ -<?php // phpcs:disable WebimpressCodingStandard.NamingConventions.AbstractClass.Prefix - - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -use Iterator; -use Laminas\Stdlib\ArrayUtils\MergeRemoveKey; -use Laminas\Stdlib\ArrayUtils\MergeReplaceKeyInterface; -use Traversable; - -use function array_filter; -use function array_key_exists; -use function array_keys; -use function array_values; -use function in_array; -use function is_array; -use function is_callable; -use function is_float; -use function is_int; -use function is_object; -use function is_scalar; -use function is_string; -use function iterator_to_array; -use function method_exists; -use function sprintf; - -/** - * Utility class for testing and manipulation of PHP arrays. - * - * Declared abstract, as we have no need for instantiation. - */ -abstract class ArrayUtils -{ - /** - * Compatibility Flag for ArrayUtils::filter - */ - public const ARRAY_FILTER_USE_BOTH = 1; - - /** - * Compatibility Flag for ArrayUtils::filter - */ - public const ARRAY_FILTER_USE_KEY = 2; - - /** - * Test whether an array contains one or more string keys - * - * @param mixed $value - * @param bool $allowEmpty Should an empty array() return true - * @return bool - */ - public static function hasStringKeys($value, $allowEmpty = false) - { - if (! is_array($value)) { - return false; - } - - if (! $value) { - return $allowEmpty; - } - - return [] !== array_filter(array_keys($value), 'is_string'); - } - - /** - * Test whether an array contains one or more integer keys - * - * @param mixed $value - * @param bool $allowEmpty Should an empty array() return true - * @return bool - */ - public static function hasIntegerKeys($value, $allowEmpty = false) - { - if (! is_array($value)) { - return false; - } - - if (! $value) { - return $allowEmpty; - } - - return [] !== array_filter(array_keys($value), 'is_int'); - } - - /** - * Test whether an array contains one or more numeric keys. - * - * A numeric key can be one of the following: - * - an integer 1, - * - a string with a number '20' - * - a string with negative number: '-1000' - * - a float: 2.2120, -78.150999 - * - a string with float: '4000.99999', '-10.10' - * - * @param mixed $value - * @param bool $allowEmpty Should an empty array() return true - * @return bool - */ - public static function hasNumericKeys($value, $allowEmpty = false) - { - if (! is_array($value)) { - return false; - } - - if (! $value) { - return $allowEmpty; - } - - return [] !== array_filter(array_keys($value), 'is_numeric'); - } - - /** - * Test whether an array is a list - * - * A list is a collection of values assigned to continuous integer keys - * starting at 0 and ending at count() - 1. - * - * For example: - * <code> - * $list = array('a', 'b', 'c', 'd'); - * $list = array( - * 0 => 'foo', - * 1 => 'bar', - * 2 => array('foo' => 'baz'), - * ); - * </code> - * - * @param mixed $value - * @param bool $allowEmpty Is an empty list a valid list? - * @return bool - */ - public static function isList($value, $allowEmpty = false) - { - if (! is_array($value)) { - return false; - } - - if (! $value) { - return $allowEmpty; - } - - return array_values($value) === $value; - } - - /** - * Test whether an array is a hash table. - * - * An array is a hash table if: - * - * 1. Contains one or more non-integer keys, or - * 2. Integer keys are non-continuous or misaligned (not starting with 0) - * - * For example: - * <code> - * $hash = array( - * 'foo' => 15, - * 'bar' => false, - * ); - * $hash = array( - * 1995 => 'Birth of PHP', - * 2009 => 'PHP 5.3.0', - * 2012 => 'PHP 5.4.0', - * ); - * $hash = array( - * 'formElement, - * 'options' => array( 'debug' => true ), - * ); - * </code> - * - * @param mixed $value - * @param bool $allowEmpty Is an empty array() a valid hash table? - * @return bool - */ - public static function isHashTable($value, $allowEmpty = false) - { - if (! is_array($value)) { - return false; - } - - if (! $value) { - return $allowEmpty; - } - - return array_values($value) !== $value; - } - - /** - * Checks if a value exists in an array. - * - * Due to "foo" == 0 === TRUE with in_array when strict = false, an option - * has been added to prevent this. When $strict = 0/false, the most secure - * non-strict check is implemented. if $strict = -1, the default in_array - * non-strict behaviour is used. - * - * @param mixed $needle - * @param array $haystack - * @param int|bool $strict - * @return bool - */ - public static function inArray($needle, array $haystack, $strict = false) - { - if (! $strict) { - if (is_int($needle) || is_float($needle)) { - $needle = (string) $needle; - } - if (is_string($needle)) { - foreach ($haystack as &$h) { - if (is_int($h) || is_float($h)) { - $h = (string) $h; - } - } - } - } - - return in_array($needle, $haystack, (bool) $strict); - } - - /** - * Converts an iterator to an array. The $recursive flag, on by default, - * hints whether or not you want to do so recursively. - * - * @template TKey - * @template TValue - * @param iterable<TKey, TValue> $iterator The array or Traversable object to convert - * @param bool $recursive Recursively check all nested structures - * @throws Exception\InvalidArgumentException If $iterator is not an array or a Traversable object. - * @return array<TKey, TValue> - */ - public static function iteratorToArray($iterator, $recursive = true) - { - /** @psalm-suppress DocblockTypeContradiction */ - if (! is_array($iterator) && ! $iterator instanceof Traversable) { - throw new Exception\InvalidArgumentException(__METHOD__ . ' expects an array or Traversable object'); - } - - if (! $recursive) { - if (is_array($iterator)) { - return $iterator; - } - - return iterator_to_array($iterator); - } - - if ( - is_object($iterator) - && ! $iterator instanceof Iterator - && method_exists($iterator, 'toArray') - ) { - /** @psalm-var array<TKey, TValue> $array */ - $array = $iterator->toArray(); - - return $array; - } - - $array = []; - foreach ($iterator as $key => $value) { - if (is_scalar($value)) { - $array[$key] = $value; - continue; - } - - if ($value instanceof Traversable) { - $array[$key] = static::iteratorToArray($value, $recursive); - continue; - } - - if (is_array($value)) { - $array[$key] = static::iteratorToArray($value, $recursive); - continue; - } - - $array[$key] = $value; - } - - /** @psalm-var array<TKey, TValue> $array */ - - return $array; - } - - /** - * Merge two arrays together. - * - * If an integer key exists in both arrays and preserveNumericKeys is false, the value - * from the second array will be appended to the first array. If both values are arrays, they - * are merged together, else the value of the second array overwrites the one of the first array. - * - * @param array $a - * @param array $b - * @param bool $preserveNumericKeys - * @return array - */ - public static function merge(array $a, array $b, $preserveNumericKeys = false) - { - foreach ($b as $key => $value) { - if ($value instanceof MergeReplaceKeyInterface) { - $a[$key] = $value->getData(); - } elseif (isset($a[$key]) || array_key_exists($key, $a)) { - if ($value instanceof MergeRemoveKey) { - unset($a[$key]); - } elseif (! $preserveNumericKeys && is_int($key)) { - $a[] = $value; - } elseif (is_array($value) && is_array($a[$key])) { - $a[$key] = static::merge($a[$key], $value, $preserveNumericKeys); - } else { - $a[$key] = $value; - } - } else { - if (! $value instanceof MergeRemoveKey) { - $a[$key] = $value; - } - } - } - - return $a; - } - - /** - * @deprecated Since 3.2.0; use the native array_filter methods - * - * @param array $data - * @param callable $callback - * @param null|int $flag - * @return array - * @throws Exception\InvalidArgumentException - */ - public static function filter(array $data, $callback, $flag = null) - { - if (! is_callable($callback)) { - throw new Exception\InvalidArgumentException(sprintf( - 'Second parameter of %s must be callable', - __METHOD__ - )); - } - - return array_filter($data, $callback, $flag ?? 0); - } -} diff --git a/lib/laminas/laminas-stdlib/src/ArrayUtils/MergeRemoveKey.php b/lib/laminas/laminas-stdlib/src/ArrayUtils/MergeRemoveKey.php deleted file mode 100644 index bde0b25ae..000000000 --- a/lib/laminas/laminas-stdlib/src/ArrayUtils/MergeRemoveKey.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib\ArrayUtils; - -final class MergeRemoveKey -{ -} diff --git a/lib/laminas/laminas-stdlib/src/ArrayUtils/MergeReplaceKey.php b/lib/laminas/laminas-stdlib/src/ArrayUtils/MergeReplaceKey.php deleted file mode 100644 index 6092747da..000000000 --- a/lib/laminas/laminas-stdlib/src/ArrayUtils/MergeReplaceKey.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib\ArrayUtils; - -final class MergeReplaceKey implements MergeReplaceKeyInterface -{ - /** @var mixed */ - protected $data; - - /** - * @param mixed $data - */ - public function __construct($data) - { - $this->data = $data; - } - - /** - * {@inheritDoc} - */ - public function getData() - { - return $this->data; - } -} diff --git a/lib/laminas/laminas-stdlib/src/ArrayUtils/MergeReplaceKeyInterface.php b/lib/laminas/laminas-stdlib/src/ArrayUtils/MergeReplaceKeyInterface.php deleted file mode 100644 index 47243fc24..000000000 --- a/lib/laminas/laminas-stdlib/src/ArrayUtils/MergeReplaceKeyInterface.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib\ArrayUtils; - -/** - * Marker interface: can be used to replace keys completely in {@see ArrayUtils::merge()} operations - */ -interface MergeReplaceKeyInterface -{ - /** - * @return mixed - */ - public function getData(); -} diff --git a/lib/laminas/laminas-stdlib/src/ConsoleHelper.php b/lib/laminas/laminas-stdlib/src/ConsoleHelper.php deleted file mode 100644 index ab876eb2e..000000000 --- a/lib/laminas/laminas-stdlib/src/ConsoleHelper.php +++ /dev/null @@ -1,162 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -use function function_exists; -use function fwrite; -use function getenv; -use function posix_isatty; -use function preg_replace; -use function sprintf; -use function str_replace; - -use const DIRECTORY_SEPARATOR; -use const PHP_EOL; -use const STDERR; -use const STDOUT; - -/** - * Utilities for console tooling. - * - * Provides the following facilities: - * - * - Colorize strings using markup (e.g., `<info>message</info>`, - * `<error>message</error>`) - * - Write output to a specified stream, optionally with colorization. - * - Write a line of output to a specified stream, optionally with - * colorization, using the system EOL sequence.. - * - Write an error message to STDERR. - * - * Colorization will only occur when expected sequences are discovered, and - * then, only if the console terminal allows it. - * - * Essentially, provides the bare minimum to allow you to provide messages to - * the current console. - */ -class ConsoleHelper -{ - public const COLOR_GREEN = "\033[32m"; - public const COLOR_RED = "\033[31m"; - public const COLOR_RESET = "\033[0m"; - - public const HIGHLIGHT_INFO = 'info'; - public const HIGHLIGHT_ERROR = 'error'; - - /** @psalm-var array<ConsoleHelper::HIGHLIGHT_*, ConsoleHelper::COLOR_GREEN|ConsoleHelper::COLOR_RED> */ - private array $highlightMap = [ - self::HIGHLIGHT_INFO => self::COLOR_GREEN, - self::HIGHLIGHT_ERROR => self::COLOR_RED, - ]; - - /** @var string Exists only for testing. */ - private string $eol = PHP_EOL; - - /** @var resource Exists only for testing. */ - private $stderr = STDERR; - - private bool $supportsColor; - - /** - * @param resource $resource - */ - public function __construct($resource = STDOUT) - { - $this->supportsColor = $this->detectColorCapabilities($resource); - } - - /** - * Colorize a string for use with the terminal. - * - * Takes strings formatted as `<key>string</key>` and formats them per the - * $highlightMap; if color support is disabled, simply removes the formatting - * tags. - * - * @param string $string - * @return string - */ - public function colorize($string) - { - $reset = $this->supportsColor ? self::COLOR_RESET : ''; - foreach ($this->highlightMap as $key => $color) { - $pattern = sprintf('#<%s>(.*?)</%s>#s', $key, $key); - $color = $this->supportsColor ? $color : ''; - $string = preg_replace($pattern, $color . '$1' . $reset, $string); - } - return $string; - } - - /** - * @param string $string - * @param bool $colorize Whether or not to colorize the string - * @param resource $resource Defaults to STDOUT - * @return void - */ - public function write($string, $colorize = true, $resource = STDOUT) - { - if ($colorize) { - $string = $this->colorize($string); - } - - $string = $this->formatNewlines($string); - - fwrite($resource, $string); - } - - /** - * @param string $string - * @param bool $colorize Whether or not to colorize the line - * @param resource $resource Defaults to STDOUT - * @return void - */ - public function writeLine($string, $colorize = true, $resource = STDOUT) - { - $this->write($string . $this->eol, $colorize, $resource); - } - - /** - * Emit an error message. - * - * Wraps the message in `<error></error>`, and passes it to `writeLine()`, - * using STDERR as the resource; emits an additional empty line when done, - * also to STDERR. - * - * @param string $message - * @return void - */ - public function writeErrorMessage($message) - { - $this->writeLine(sprintf('<error>%s</error>', $message), true, $this->stderr); - $this->writeLine('', false, $this->stderr); - } - - /** - * @param resource $resource - * @return bool - */ - private function detectColorCapabilities($resource = STDOUT) - { - if ('\\' === DIRECTORY_SEPARATOR) { - // Windows - return false !== getenv('ANSICON') - || 'ON' === getenv('ConEmuANSI') - || 'xterm' === getenv('TERM'); - } - - return function_exists('posix_isatty') && posix_isatty($resource); - } - - /** - * Ensure newlines are appropriate for the current terminal. - * - * @param string $string - * @return string - */ - private function formatNewlines($string) - { - $string = str_replace($this->eol, "\0PHP_EOL\0", $string); - $string = preg_replace("/(\r\n|\n|\r)/", $this->eol, $string); - return str_replace("\0PHP_EOL\0", $this->eol, $string); - } -} diff --git a/lib/laminas/laminas-stdlib/src/DispatchableInterface.php b/lib/laminas/laminas-stdlib/src/DispatchableInterface.php deleted file mode 100644 index a9b325a67..000000000 --- a/lib/laminas/laminas-stdlib/src/DispatchableInterface.php +++ /dev/null @@ -1,15 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -interface DispatchableInterface -{ - /** - * Dispatch a request - * - * @return Response|mixed - */ - public function dispatch(RequestInterface $request, ?ResponseInterface $response = null); -} diff --git a/lib/laminas/laminas-stdlib/src/ErrorHandler.php b/lib/laminas/laminas-stdlib/src/ErrorHandler.php deleted file mode 100644 index 39aa8cd75..000000000 --- a/lib/laminas/laminas-stdlib/src/ErrorHandler.php +++ /dev/null @@ -1,119 +0,0 @@ -<?php // phpcs:disable WebimpressCodingStandard.NamingConventions.AbstractClass.Prefix - - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -use ErrorException; - -use function array_pop; -use function count; -use function restore_error_handler; -use function set_error_handler; - -use const E_WARNING; - -/** - * ErrorHandler that can be used to catch internal PHP errors - * and convert to an ErrorException instance. - */ -abstract class ErrorHandler -{ - /** - * Active stack - * - * @var array - */ - protected static $stack = []; - - /** - * Check if this error handler is active - * - * @return bool - */ - public static function started() - { - return (bool) static::getNestedLevel(); - } - - /** - * Get the current nested level - * - * @return int - */ - public static function getNestedLevel() - { - return count(static::$stack); - } - - /** - * Starting the error handler - * - * @param int $errorLevel - * @return void - */ - public static function start($errorLevel = E_WARNING) - { - if (! static::$stack) { - set_error_handler([static::class, 'addError'], $errorLevel); - } - - static::$stack[] = null; - } - - /** - * Stopping the error handler - * - * @param bool $throw Throw the ErrorException if any - * @return null|ErrorException - * @throws ErrorException If an error has been caught and $throw is true. - */ - public static function stop($throw = false) - { - $errorException = null; - - if (static::$stack) { - $errorException = array_pop(static::$stack); - - if (! static::$stack) { - restore_error_handler(); - } - - if ($errorException && $throw) { - throw $errorException; - } - } - - return $errorException; - } - - /** - * Stop all active handler - * - * @return void - */ - public static function clean() - { - if (static::$stack) { - restore_error_handler(); - } - - static::$stack = []; - } - - /** - * Add an error to the stack - * - * @param int $errno - * @param string $errstr - * @param string $errfile - * @param int $errline - * @return void - */ - public static function addError($errno, $errstr = '', $errfile = '', $errline = 0) - { - $stack = &static::$stack[count(static::$stack) - 1]; - $stack = new ErrorException($errstr, 0, $errno, $errfile, $errline, $stack); - } -} diff --git a/lib/laminas/laminas-stdlib/src/Exception/BadMethodCallException.php b/lib/laminas/laminas-stdlib/src/Exception/BadMethodCallException.php deleted file mode 100644 index a62b91717..000000000 --- a/lib/laminas/laminas-stdlib/src/Exception/BadMethodCallException.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib\Exception; - -/** - * Bad method call exception - */ -class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-stdlib/src/Exception/DomainException.php b/lib/laminas/laminas-stdlib/src/Exception/DomainException.php deleted file mode 100644 index 616277fce..000000000 --- a/lib/laminas/laminas-stdlib/src/Exception/DomainException.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib\Exception; - -/** - * Domain exception - */ -class DomainException extends \DomainException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-stdlib/src/Exception/ExceptionInterface.php b/lib/laminas/laminas-stdlib/src/Exception/ExceptionInterface.php deleted file mode 100644 index a26dc1ea0..000000000 --- a/lib/laminas/laminas-stdlib/src/Exception/ExceptionInterface.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib\Exception; - -/** - * Exception marker interface - */ -interface ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-stdlib/src/Exception/ExtensionNotLoadedException.php b/lib/laminas/laminas-stdlib/src/Exception/ExtensionNotLoadedException.php deleted file mode 100644 index d88edbeaa..000000000 --- a/lib/laminas/laminas-stdlib/src/Exception/ExtensionNotLoadedException.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib\Exception; - -/** - * Extension not loaded exception - */ -class ExtensionNotLoadedException extends RuntimeException -{ -} diff --git a/lib/laminas/laminas-stdlib/src/Exception/InvalidArgumentException.php b/lib/laminas/laminas-stdlib/src/Exception/InvalidArgumentException.php deleted file mode 100644 index 375d9fbc4..000000000 --- a/lib/laminas/laminas-stdlib/src/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib\Exception; - -/** - * Invalid Argument Exception - */ -class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-stdlib/src/Exception/LogicException.php b/lib/laminas/laminas-stdlib/src/Exception/LogicException.php deleted file mode 100644 index a294d4387..000000000 --- a/lib/laminas/laminas-stdlib/src/Exception/LogicException.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib\Exception; - -/** - * Logic exception - */ -class LogicException extends \LogicException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-stdlib/src/Exception/RuntimeException.php b/lib/laminas/laminas-stdlib/src/Exception/RuntimeException.php deleted file mode 100644 index e048c0139..000000000 --- a/lib/laminas/laminas-stdlib/src/Exception/RuntimeException.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib\Exception; - -/** - * Runtime exception - */ -class RuntimeException extends \RuntimeException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-stdlib/src/FastPriorityQueue.php b/lib/laminas/laminas-stdlib/src/FastPriorityQueue.php deleted file mode 100644 index ae8f1d42a..000000000 --- a/lib/laminas/laminas-stdlib/src/FastPriorityQueue.php +++ /dev/null @@ -1,406 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -use Countable; -use Iterator; -use ReturnTypeWillChange; -use Serializable; -use SplPriorityQueue as PhpSplPriorityQueue; -use UnexpectedValueException; - -use function current; -use function in_array; -use function is_array; -use function is_int; -use function key; -use function max; -use function next; -use function reset; -use function serialize; -use function sprintf; -use function unserialize; - -/** - * This is an efficient implementation of an integer priority queue in PHP - * - * This class acts like a queue with insert() and extract(), removing the - * elements from the queue and it also acts like an Iterator without removing - * the elements. This behaviour can be used in mixed scenarios with high - * performance boost. - */ -class FastPriorityQueue implements Iterator, Countable, Serializable -{ - public const EXTR_DATA = PhpSplPriorityQueue::EXTR_DATA; - public const EXTR_PRIORITY = PhpSplPriorityQueue::EXTR_PRIORITY; - public const EXTR_BOTH = PhpSplPriorityQueue::EXTR_BOTH; - - /** @var integer */ - protected $extractFlag = self::EXTR_DATA; - - /** - * Elements of the queue, divided by priorities - * - * @var array - */ - protected $values = []; - - /** - * Array of priorities - * - * @var array - */ - protected $priorities = []; - - /** - * Array of priorities used for the iteration - * - * @var array - */ - protected $subPriorities = []; - - /** - * Max priority - * - * @var integer|null - */ - protected $maxPriority; - - /** - * Total number of elements in the queue - * - * @var integer - */ - protected $count = 0; - - /** - * Index of the current element in the queue - * - * @var integer - */ - protected $index = 0; - - /** - * Sub index of the current element in the same priority level - * - * @var integer - */ - protected $subIndex = 0; - - public function __serialize(): array - { - $clone = clone $this; - $clone->setExtractFlags(self::EXTR_BOTH); - - $data = []; - foreach ($clone as $item) { - $data[] = $item; - } - - return $data; - } - - public function __unserialize(array $data): void - { - foreach ($data as $item) { - $this->insert($item['data'], $item['priority']); - } - } - - /** - * Insert an element in the queue with a specified priority - * - * @param mixed $value - * @param integer $priority - * @return void - */ - public function insert($value, $priority) - { - if (! is_int($priority)) { - throw new Exception\InvalidArgumentException('The priority must be an integer'); - } - $this->values[$priority][] = $value; - if (! isset($this->priorities[$priority])) { - $this->priorities[$priority] = $priority; - $this->maxPriority = $this->maxPriority === null ? $priority : max($priority, $this->maxPriority); - } - ++$this->count; - } - - /** - * Extract an element in the queue according to the priority and the - * order of insertion - * - * @return mixed - */ - public function extract() - { - if (! $this->valid()) { - return false; - } - $value = $this->current(); - $this->nextAndRemove(); - return $value; - } - - /** - * Remove an item from the queue - * - * This is different than {@link extract()}; its purpose is to dequeue an - * item. - * - * Note: this removes the first item matching the provided item found. If - * the same item has been added multiple times, it will not remove other - * instances. - * - * @param mixed $datum - * @return bool False if the item was not found, true otherwise. - */ - public function remove($datum) - { - $currentIndex = $this->index; - $currentSubIndex = $this->subIndex; - $currentPriority = $this->maxPriority; - - $this->rewind(); - while ($this->valid()) { - if (current($this->values[$this->maxPriority]) === $datum) { - $index = key($this->values[$this->maxPriority]); - unset($this->values[$this->maxPriority][$index]); - - // The `next()` method advances the internal array pointer, so we need to use the `reset()` function, - // otherwise we would lose all elements before the place the pointer points. - reset($this->values[$this->maxPriority]); - - $this->index = $currentIndex; - $this->subIndex = $currentSubIndex; - - // If the array is empty we need to destroy the unnecessary priority, - // otherwise we would end up with an incorrect value of `$this->count` - // {@see \Laminas\Stdlib\FastPriorityQueue::nextAndRemove()}. - if (empty($this->values[$this->maxPriority])) { - unset($this->values[$this->maxPriority]); - unset($this->priorities[$this->maxPriority]); - if ($this->maxPriority === $currentPriority) { - $this->subIndex = 0; - } - } - - $this->maxPriority = empty($this->priorities) ? null : max($this->priorities); - --$this->count; - return true; - } - $this->next(); - } - return false; - } - - /** - * Get the total number of elements in the queue - * - * @return int - */ - #[ReturnTypeWillChange] - public function count() - { - return $this->count; - } - - /** - * Get the current element in the queue - * - * @return mixed - */ - #[ReturnTypeWillChange] - public function current() - { - switch ($this->extractFlag) { - case self::EXTR_DATA: - return current($this->values[$this->maxPriority]); - case self::EXTR_PRIORITY: - return $this->maxPriority; - case self::EXTR_BOTH: - return [ - 'data' => current($this->values[$this->maxPriority]), - 'priority' => $this->maxPriority, - ]; - } - } - - /** - * Get the index of the current element in the queue - * - * @return int - */ - #[ReturnTypeWillChange] - public function key() - { - return $this->index; - } - - /** - * Set the iterator pointer to the next element in the queue - * removing the previous element - * - * @return void - */ - protected function nextAndRemove() - { - $key = key($this->values[$this->maxPriority]); - - if (false === next($this->values[$this->maxPriority])) { - unset($this->priorities[$this->maxPriority]); - unset($this->values[$this->maxPriority]); - $this->maxPriority = empty($this->priorities) ? null : max($this->priorities); - $this->subIndex = -1; - } else { - unset($this->values[$this->maxPriority][$key]); - } - ++$this->index; - ++$this->subIndex; - --$this->count; - } - - /** - * Set the iterator pointer to the next element in the queue - * without removing the previous element - */ - #[ReturnTypeWillChange] - public function next() - { - if (false === next($this->values[$this->maxPriority])) { - unset($this->subPriorities[$this->maxPriority]); - reset($this->values[$this->maxPriority]); - $this->maxPriority = empty($this->subPriorities) ? null : max($this->subPriorities); - $this->subIndex = -1; - } - ++$this->index; - ++$this->subIndex; - } - - /** - * Check if the current iterator is valid - * - * @return bool - */ - #[ReturnTypeWillChange] - public function valid() - { - return isset($this->values[$this->maxPriority]); - } - - /** - * Rewind the current iterator - */ - #[ReturnTypeWillChange] - public function rewind() - { - $this->subPriorities = $this->priorities; - $this->maxPriority = empty($this->priorities) ? 0 : max($this->priorities); - $this->index = 0; - $this->subIndex = 0; - } - - /** - * Serialize to an array - * - * Array will be priority => data pairs - * - * @return array - */ - public function toArray() - { - $array = []; - foreach (clone $this as $item) { - $array[] = $item; - } - return $array; - } - - /** - * Serialize - * - * @return string - */ - public function serialize() - { - return serialize($this->__serialize()); - } - - /** - * Deserialize - * - * @param string $data - * @return void - */ - public function unserialize($data) - { - $toUnserialize = unserialize($data); - if (! is_array($toUnserialize)) { - throw new UnexpectedValueException(sprintf( - 'Cannot deserialize %s instance; corrupt serialization data', - self::class - )); - } - - $this->__unserialize($toUnserialize); - } - - /** - * Set the extract flag - * - * @param integer $flag - * @return void - */ - public function setExtractFlags($flag) - { - switch ($flag) { - case self::EXTR_DATA: - case self::EXTR_PRIORITY: - case self::EXTR_BOTH: - $this->extractFlag = $flag; - break; - default: - throw new Exception\InvalidArgumentException("The extract flag specified is not valid"); - } - } - - /** - * Check if the queue is empty - * - * @return boolean - */ - public function isEmpty() - { - return empty($this->values); - } - - /** - * Does the queue contain the given datum? - * - * @param mixed $datum - * @return bool - */ - public function contains($datum) - { - foreach ($this->values as $values) { - if (in_array($datum, $values)) { - return true; - } - } - return false; - } - - /** - * Does the queue have an item with the given priority? - * - * @param int $priority - * @return bool - */ - public function hasPriority($priority) - { - return isset($this->values[$priority]); - } -} diff --git a/lib/laminas/laminas-stdlib/src/Glob.php b/lib/laminas/laminas-stdlib/src/Glob.php deleted file mode 100644 index 5b5be710d..000000000 --- a/lib/laminas/laminas-stdlib/src/Glob.php +++ /dev/null @@ -1,226 +0,0 @@ -<?php // phpcs:disable WebimpressCodingStandard.NamingConventions.AbstractClass.Prefix,Generic.NamingConventions.ConstructorName.OldStyle - - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -use function array_merge; -use function array_unique; -use function defined; -use function glob; -use function strlen; -use function strpos; -use function substr; - -use const GLOB_BRACE; -use const GLOB_ERR; -use const GLOB_MARK; -use const GLOB_NOCHECK; -use const GLOB_NOESCAPE; -use const GLOB_NOSORT; -use const GLOB_ONLYDIR; - -/** - * Wrapper for glob with fallback if GLOB_BRACE is not available. - */ -abstract class Glob -{ - /**#@+ - * Glob constants. - */ - public const GLOB_MARK = 0x01; - public const GLOB_NOSORT = 0x02; - public const GLOB_NOCHECK = 0x04; - public const GLOB_NOESCAPE = 0x08; - public const GLOB_BRACE = 0x10; - public const GLOB_ONLYDIR = 0x20; - public const GLOB_ERR = 0x40; - /**#@-*/ - - /** - * Find pathnames matching a pattern. - * - * @see http://docs.php.net/glob - * - * @param string $pattern - * @param int $flags - * @param bool $forceFallback - * @return array - * @throws Exception\RuntimeException - */ - public static function glob($pattern, $flags = 0, $forceFallback = false) - { - if (! defined('GLOB_BRACE') || $forceFallback) { - return static::fallbackGlob($pattern, $flags); - } - - return static::systemGlob($pattern, $flags); - } - - /** - * Use the glob function provided by the system. - * - * @param string $pattern - * @param int $flags - * @return array - * @throws Exception\RuntimeException - */ - protected static function systemGlob($pattern, $flags) - { - if ($flags) { - $flagMap = [ - self::GLOB_MARK => GLOB_MARK, - self::GLOB_NOSORT => GLOB_NOSORT, - self::GLOB_NOCHECK => GLOB_NOCHECK, - self::GLOB_NOESCAPE => GLOB_NOESCAPE, - self::GLOB_BRACE => defined('GLOB_BRACE') ? GLOB_BRACE : 0, - self::GLOB_ONLYDIR => GLOB_ONLYDIR, - self::GLOB_ERR => GLOB_ERR, - ]; - - $globFlags = 0; - - foreach ($flagMap as $internalFlag => $globFlag) { - if ($flags & $internalFlag) { - $globFlags |= $globFlag; - } - } - } else { - $globFlags = 0; - } - - ErrorHandler::start(); - $res = glob($pattern, $globFlags); - $err = ErrorHandler::stop(); - if ($res === false) { - throw new Exception\RuntimeException("glob('{$pattern}', {$globFlags}) failed", 0, $err); - } - return $res; - } - - /** - * Expand braces manually, then use the system glob. - * - * @param string $pattern - * @param int $flags - * @return array - * @throws Exception\RuntimeException - */ - protected static function fallbackGlob($pattern, $flags) - { - if (! self::flagsIsEqualTo($flags, self::GLOB_BRACE)) { - return static::systemGlob($pattern, $flags); - } - - $flags &= ~self::GLOB_BRACE; - $length = strlen($pattern); - $paths = []; - - if ($flags & self::GLOB_NOESCAPE) { - $begin = strpos($pattern, '{'); - } else { - $begin = 0; - - while (true) { - if ($begin === $length) { - $begin = false; - break; - } elseif ($pattern[$begin] === '\\' && ($begin + 1) < $length) { - $begin++; - } elseif ($pattern[$begin] === '{') { - break; - } - - $begin++; - } - } - - if ($begin === false) { - return static::systemGlob($pattern, $flags); - } - - $next = static::nextBraceSub($pattern, $begin + 1, $flags); - - if ($next === null) { - return static::systemGlob($pattern, $flags); - } - - $rest = $next; - - while ($pattern[$rest] !== '}') { - $rest = static::nextBraceSub($pattern, $rest + 1, $flags); - - if ($rest === null) { - return static::systemGlob($pattern, $flags); - } - } - - $p = $begin + 1; - - while (true) { - $subPattern = substr($pattern, 0, $begin) - . substr($pattern, $p, $next - $p) - . substr($pattern, $rest + 1); - - $result = static::fallbackGlob($subPattern, $flags | self::GLOB_BRACE); - - if ($result) { - $paths = array_merge($paths, $result); - } - - if ($pattern[$next] === '}') { - break; - } - - $p = $next + 1; - $next = static::nextBraceSub($pattern, $p, $flags); - } - - return array_unique($paths); - } - - /** - * Find the end of the sub-pattern in a brace expression. - * - * @param string $pattern - * @param int $begin - * @param int $flags - * @return int|null - */ - protected static function nextBraceSub($pattern, $begin, $flags) - { - $length = strlen($pattern); - $depth = 0; - $current = $begin; - - while ($current < $length) { - $flagsEqualsNoEscape = self::flagsIsEqualTo($flags, self::GLOB_NOESCAPE); - - if ($flagsEqualsNoEscape && $pattern[$current] === '\\') { - if (++$current === $length) { - break; - } - - $current++; - } else { - if ( - ($pattern[$current] === '}' && $depth-- === 0) - || ($pattern[$current] === ',' && $depth === 0) - ) { - break; - } elseif ($pattern[$current++] === '{') { - $depth++; - } - } - } - - return $current < $length ? $current : null; - } - - /** @internal */ - public static function flagsIsEqualTo(int $flags, int $otherFlags): bool - { - return (bool) ($flags & $otherFlags); - } -} diff --git a/lib/laminas/laminas-stdlib/src/Guard/AllGuardsTrait.php b/lib/laminas/laminas-stdlib/src/Guard/AllGuardsTrait.php deleted file mode 100644 index b5abe5a62..000000000 --- a/lib/laminas/laminas-stdlib/src/Guard/AllGuardsTrait.php +++ /dev/null @@ -1,15 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib\Guard; - -/** - * An aggregate for all guard traits - */ -trait AllGuardsTrait -{ - use ArrayOrTraversableGuardTrait; - use EmptyGuardTrait; - use NullGuardTrait; -} diff --git a/lib/laminas/laminas-stdlib/src/Guard/ArrayOrTraversableGuardTrait.php b/lib/laminas/laminas-stdlib/src/Guard/ArrayOrTraversableGuardTrait.php deleted file mode 100644 index 392a88d3e..000000000 --- a/lib/laminas/laminas-stdlib/src/Guard/ArrayOrTraversableGuardTrait.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib\Guard; - -use Exception; -use Laminas\Stdlib\Exception\InvalidArgumentException; -use Traversable; - -use function get_class; -use function gettype; -use function is_array; -use function is_object; -use function sprintf; - -/** - * Provide a guard method for array or Traversable data - */ -trait ArrayOrTraversableGuardTrait -{ - /** - * Verifies that the data is an array or Traversable - * - * @param mixed $data the data to verify - * @param string $dataName the data name - * @param string $exceptionClass FQCN for the exception - * @return void - * @throws Exception - */ - protected function guardForArrayOrTraversable( - $data, - $dataName = 'Argument', - $exceptionClass = InvalidArgumentException::class - ) { - if (! is_array($data) && ! $data instanceof Traversable) { - $message = sprintf( - "%s must be an array or Traversable, [%s] given", - $dataName, - is_object($data) ? get_class($data) : gettype($data) - ); - throw new $exceptionClass($message); - } - } -} diff --git a/lib/laminas/laminas-stdlib/src/Guard/EmptyGuardTrait.php b/lib/laminas/laminas-stdlib/src/Guard/EmptyGuardTrait.php deleted file mode 100644 index bffaa38ae..000000000 --- a/lib/laminas/laminas-stdlib/src/Guard/EmptyGuardTrait.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib\Guard; - -use Exception; -use Laminas\Stdlib\Exception\InvalidArgumentException; - -use function sprintf; - -/** - * Provide a guard method against empty data - */ -trait EmptyGuardTrait -{ - /** - * Verify that the data is not empty - * - * @param mixed $data the data to verify - * @param string $dataName the data name - * @param string $exceptionClass FQCN for the exception - * @return void - * @throws Exception - */ - protected function guardAgainstEmpty( - $data, - $dataName = 'Argument', - $exceptionClass = InvalidArgumentException::class - ) { - if (empty($data)) { - $message = sprintf('%s cannot be empty', $dataName); - throw new $exceptionClass($message); - } - } -} diff --git a/lib/laminas/laminas-stdlib/src/Guard/NullGuardTrait.php b/lib/laminas/laminas-stdlib/src/Guard/NullGuardTrait.php deleted file mode 100644 index 32ef3400f..000000000 --- a/lib/laminas/laminas-stdlib/src/Guard/NullGuardTrait.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib\Guard; - -use Exception; -use Laminas\Stdlib\Exception\InvalidArgumentException; - -use function sprintf; - -/** - * Provide a guard method against null data - */ -trait NullGuardTrait -{ - /** - * Verify that the data is not null - * - * @param mixed $data the data to verify - * @param string $dataName the data name - * @param string $exceptionClass FQCN for the exception - * @return void - * @throws Exception - */ - protected function guardAgainstNull( - $data, - $dataName = 'Argument', - $exceptionClass = InvalidArgumentException::class - ) { - if (null === $data) { - $message = sprintf('%s cannot be null', $dataName); - throw new $exceptionClass($message); - } - } -} diff --git a/lib/laminas/laminas-stdlib/src/InitializableInterface.php b/lib/laminas/laminas-stdlib/src/InitializableInterface.php deleted file mode 100644 index d6e1a804a..000000000 --- a/lib/laminas/laminas-stdlib/src/InitializableInterface.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -/** - * Interface to allow objects to have initialization logic - */ -interface InitializableInterface -{ - /** - * Init an object - * - * @return void - */ - public function init(); -} diff --git a/lib/laminas/laminas-stdlib/src/JsonSerializable.php b/lib/laminas/laminas-stdlib/src/JsonSerializable.php deleted file mode 100644 index f3fd33f24..000000000 --- a/lib/laminas/laminas-stdlib/src/JsonSerializable.php +++ /dev/null @@ -1,13 +0,0 @@ -<?php // phpcs:disable WebimpressCodingStandard.NamingConventions.Interface.Suffix - - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -/** - * @deprecated Since 3.1.0; use the native JsonSerializable interface - */ -interface JsonSerializable extends \JsonSerializable -{ -} diff --git a/lib/laminas/laminas-stdlib/src/Message.php b/lib/laminas/laminas-stdlib/src/Message.php deleted file mode 100644 index d4f161407..000000000 --- a/lib/laminas/laminas-stdlib/src/Message.php +++ /dev/null @@ -1,117 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -use Traversable; - -use function array_key_exists; -use function get_class; -use function gettype; -use function is_array; -use function is_object; -use function is_scalar; -use function sprintf; - -class Message implements MessageInterface -{ - /** @var array */ - protected $metadata = []; - - /** @var mixed */ - protected $content = ''; - - /** - * Set message metadata - * - * Non-destructive setting of message metadata; always adds to the metadata, never overwrites - * the entire metadata container. - * - * @param string|int|array|Traversable $spec - * @param mixed $value - * @throws Exception\InvalidArgumentException - * @return Message - */ - public function setMetadata($spec, $value = null) - { - if (is_scalar($spec)) { - $this->metadata[$spec] = $value; - return $this; - } - if (! is_array($spec) && ! $spec instanceof Traversable) { - throw new Exception\InvalidArgumentException(sprintf( - 'Expected a string, array, or Traversable argument in first position; received "%s"', - is_object($spec) ? get_class($spec) : gettype($spec) - )); - } - foreach ($spec as $key => $value) { - $this->metadata[$key] = $value; - } - return $this; - } - - /** - * Retrieve all metadata or a single metadatum as specified by key - * - * @param null|string|int $key - * @param null|mixed $default - * @throws Exception\InvalidArgumentException - * @return mixed - */ - public function getMetadata($key = null, $default = null) - { - if (null === $key) { - return $this->metadata; - } - - if (! is_scalar($key)) { - throw new Exception\InvalidArgumentException('Non-scalar argument provided for key'); - } - - if (array_key_exists($key, $this->metadata)) { - return $this->metadata[$key]; - } - - return $default; - } - - /** - * Set message content - * - * @param mixed $value - * @return Message - */ - public function setContent($value) - { - $this->content = $value; - return $this; - } - - /** - * Get message content - * - * @return mixed - */ - public function getContent() - { - return $this->content; - } - - /** - * @return string - */ - public function toString() - { - $request = ''; - foreach ($this->getMetadata() as $key => $value) { - $request .= sprintf( - "%s: %s\r\n", - (string) $key, - (string) $value - ); - } - $request .= "\r\n" . $this->getContent(); - return $request; - } -} diff --git a/lib/laminas/laminas-stdlib/src/MessageInterface.php b/lib/laminas/laminas-stdlib/src/MessageInterface.php deleted file mode 100644 index 71a482081..000000000 --- a/lib/laminas/laminas-stdlib/src/MessageInterface.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -use Traversable; - -interface MessageInterface -{ - /** - * Set metadata - * - * @param string|int|array|Traversable $spec - * @param mixed $value - */ - public function setMetadata($spec, $value = null); - - /** - * Get metadata - * - * @param null|string|int $key - * @return mixed - */ - public function getMetadata($key = null); - - /** - * Set content - * - * @param mixed $content - * @return mixed - */ - public function setContent($content); - - /** - * Get content - * - * @return mixed - */ - public function getContent(); -} diff --git a/lib/laminas/laminas-stdlib/src/ParameterObjectInterface.php b/lib/laminas/laminas-stdlib/src/ParameterObjectInterface.php deleted file mode 100644 index 60f531a68..000000000 --- a/lib/laminas/laminas-stdlib/src/ParameterObjectInterface.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -interface ParameterObjectInterface -{ - /** - * @param string $key - * @param mixed $value - * @return void - */ - public function __set($key, $value); - - /** - * @param string $key - * @return mixed - */ - public function __get($key); - - /** - * @param string $key - * @return bool - */ - public function __isset($key); - - /** - * @param string $key - * @return void - */ - public function __unset($key); -} diff --git a/lib/laminas/laminas-stdlib/src/Parameters.php b/lib/laminas/laminas-stdlib/src/Parameters.php deleted file mode 100644 index 940cccacc..000000000 --- a/lib/laminas/laminas-stdlib/src/Parameters.php +++ /dev/null @@ -1,116 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -use ArrayObject as PhpArrayObject; -use ReturnTypeWillChange; - -use function http_build_query; -use function parse_str; - -class Parameters extends PhpArrayObject implements ParametersInterface -{ - /** - * Constructor - * - * Enforces that we have an array, and enforces parameter access to array - * elements. - * - * @param array $values - */ - public function __construct(?array $values = null) - { - if (null === $values) { - $values = []; - } - parent::__construct($values, ArrayObject::ARRAY_AS_PROPS); - } - - /** - * Populate from native PHP array - * - * @param array $values - * @return void - */ - public function fromArray(array $values) - { - $this->exchangeArray($values); - } - - /** - * Populate from query string - * - * @param string $string - * @return void - */ - public function fromString($string) - { - $array = []; - parse_str($string, $array); - $this->fromArray($array); - } - - /** - * Serialize to native PHP array - * - * @return array - */ - public function toArray() - { - return $this->getArrayCopy(); - } - - /** - * Serialize to query string - * - * @return string - */ - public function toString() - { - return http_build_query($this->toArray()); - } - - /** - * Retrieve by key - * - * Returns null if the key does not exist. - * - * @param string $name - * @return mixed - */ - #[ReturnTypeWillChange] - public function offsetGet($name) - { - if ($this->offsetExists($name)) { - return parent::offsetGet($name); - } - - return null; - } - - /** - * @param string $name - * @param mixed $default optional default value - * @return mixed - */ - public function get($name, $default = null) - { - if ($this->offsetExists($name)) { - return parent::offsetGet($name); - } - return $default; - } - - /** - * @param string $name - * @param mixed $value - * @return Parameters - */ - public function set($name, $value) - { - $this[$name] = $value; - return $this; - } -} diff --git a/lib/laminas/laminas-stdlib/src/ParametersInterface.php b/lib/laminas/laminas-stdlib/src/ParametersInterface.php deleted file mode 100644 index 8e07e070d..000000000 --- a/lib/laminas/laminas-stdlib/src/ParametersInterface.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -use ArrayAccess; -use Countable; -use Serializable; -use Traversable; - -/* - * Basically, an ArrayObject. You could simply define something like: - * class QueryParams extends ArrayObject implements Parameters {} - * and have 90% of the functionality - */ -interface ParametersInterface extends ArrayAccess, Countable, Serializable, Traversable -{ - /** - * Constructor - * - * @param array $values - */ - public function __construct(?array $values = null); - - /** - * From array - * - * Allow deserialization from standard array - * - * @param array $values - * @return mixed - */ - public function fromArray(array $values); - - /** - * From string - * - * Allow deserialization from raw body; e.g., for PUT requests - * - * @param string $string - * @return mixed - */ - public function fromString($string); - - /** - * To array - * - * Allow serialization back to standard array - * - * @return mixed - */ - public function toArray(); - - /** - * To string - * - * Allow serialization to query format; e.g., for PUT or POST requests - * - * @return mixed - */ - public function toString(); - - /** - * Get - * - * @param string $name - * @param mixed|null $default - * @return mixed - */ - public function get($name, $default = null); - - /** - * Set - * - * @param string $name - * @param mixed $value - * @return ParametersInterface - */ - public function set($name, $value); -} diff --git a/lib/laminas/laminas-stdlib/src/PriorityList.php b/lib/laminas/laminas-stdlib/src/PriorityList.php deleted file mode 100644 index f4ecf9c96..000000000 --- a/lib/laminas/laminas-stdlib/src/PriorityList.php +++ /dev/null @@ -1,283 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -use Countable; -use Exception; -use Iterator; -use ReturnTypeWillChange; - -use function array_map; -use function current; -use function key; -use function next; -use function reset; -use function uasort; - -class PriorityList implements Iterator, Countable -{ - public const EXTR_DATA = 0x00000001; - public const EXTR_PRIORITY = 0x00000002; - public const EXTR_BOTH = 0x00000003; - - /** - * Internal list of all items. - * - * @var array[] - */ - protected $items = []; - - /** - * Serial assigned to items to preserve LIFO. - * - * @var int - */ - protected $serial = 0; - - // phpcs:disable WebimpressCodingStandard.NamingConventions.ValidVariableName.NotCamelCapsProperty - - /** - * Serial order mode - * - * @var integer - */ - protected $isLIFO = 1; - - // phpcs:enable - - /** - * Internal counter to avoid usage of count(). - * - * @var int - */ - protected $count = 0; - - /** - * Whether the list was already sorted. - * - * @var bool - */ - protected $sorted = false; - - /** - * Insert a new item. - * - * @param string $name - * @param mixed $value - * @param int $priority - * @return void - */ - public function insert($name, $value, $priority = 0) - { - if (! isset($this->items[$name])) { - $this->count++; - } - - $this->sorted = false; - - $this->items[$name] = [ - 'data' => $value, - 'priority' => (int) $priority, - 'serial' => $this->serial++, - ]; - } - - /** - * @param string $name - * @param int $priority - * @return $this - * @throws Exception - */ - public function setPriority($name, $priority) - { - if (! isset($this->items[$name])) { - throw new Exception("item $name not found"); - } - - $this->items[$name]['priority'] = (int) $priority; - $this->sorted = false; - - return $this; - } - - /** - * Remove a item. - * - * @param string $name - * @return void - */ - public function remove($name) - { - if (isset($this->items[$name])) { - $this->count--; - } - - unset($this->items[$name]); - } - - /** - * Remove all items. - * - * @return void - */ - public function clear() - { - $this->items = []; - $this->serial = 0; - $this->count = 0; - $this->sorted = false; - } - - /** - * Get a item. - * - * @param string $name - * @return mixed - */ - public function get($name) - { - if (! isset($this->items[$name])) { - return; - } - - return $this->items[$name]['data']; - } - - /** - * Sort all items. - * - * @return void - */ - protected function sort() - { - if (! $this->sorted) { - uasort($this->items, [$this, 'compare']); - $this->sorted = true; - } - } - - /** - * Compare the priority of two items. - * - * @param array $item1, - * @param array $item2 - * @return int - */ - protected function compare(array $item1, array $item2) - { - return $item1['priority'] === $item2['priority'] - ? ($item1['serial'] > $item2['serial'] ? -1 : 1) * $this->isLIFO - : ($item1['priority'] > $item2['priority'] ? -1 : 1); - } - - /** - * Get/Set serial order mode - * - * @param bool|null $flag - * @return bool - */ - public function isLIFO($flag = null) - { - if ($flag !== null) { - $isLifo = $flag === true ? 1 : -1; - - if ($isLifo !== $this->isLIFO) { - $this->isLIFO = $isLifo; - $this->sorted = false; - } - } - - return 1 === $this->isLIFO; - } - - /** - * {@inheritDoc} - */ - #[ReturnTypeWillChange] - public function rewind() - { - $this->sort(); - reset($this->items); - } - - /** - * {@inheritDoc} - */ - #[ReturnTypeWillChange] - public function current() - { - $this->sorted || $this->sort(); - $node = current($this->items); - - return $node ? $node['data'] : false; - } - - /** - * {@inheritDoc} - */ - #[ReturnTypeWillChange] - public function key() - { - $this->sorted || $this->sort(); - return key($this->items); - } - - /** - * {@inheritDoc} - */ - #[ReturnTypeWillChange] - public function next() - { - $node = next($this->items); - - return $node ? $node['data'] : false; - } - - /** - * {@inheritDoc} - */ - #[ReturnTypeWillChange] - public function valid() - { - return current($this->items) !== false; - } - - /** - * @return self - */ - public function getIterator() - { - return clone $this; - } - - /** - * {@inheritDoc} - */ - #[ReturnTypeWillChange] - public function count() - { - return $this->count; - } - - /** - * Return list as array - * - * @param int $flag - * @return array - */ - public function toArray($flag = self::EXTR_DATA) - { - $this->sort(); - - if ($flag === self::EXTR_BOTH) { - return $this->items; - } - - return array_map( - static fn($item) => $flag === self::EXTR_PRIORITY ? $item['priority'] : $item['data'], - $this->items - ); - } -} diff --git a/lib/laminas/laminas-stdlib/src/PriorityQueue.php b/lib/laminas/laminas-stdlib/src/PriorityQueue.php deleted file mode 100644 index 92af39223..000000000 --- a/lib/laminas/laminas-stdlib/src/PriorityQueue.php +++ /dev/null @@ -1,385 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -use Countable; -use IteratorAggregate; -use ReturnTypeWillChange; -use Serializable; -use UnexpectedValueException; - -use function array_map; -use function count; -use function get_class; -use function is_array; -use function serialize; -use function sprintf; -use function unserialize; - -/** - * Re-usable, serializable priority queue implementation - * - * SplPriorityQueue acts as a heap; on iteration, each item is removed from the - * queue. If you wish to re-use such a queue, you need to clone it first. This - * makes for some interesting issues if you wish to delete items from the queue, - * or, as already stated, iterate over it multiple times. - * - * This class aggregates items for the queue itself, but also composes an - * "inner" iterator in the form of an SplPriorityQueue object for performing - * the actual iteration. - * - * @template T - * @template TPriority of int - * @implements IteratorAggregate<array-key, T> - */ -class PriorityQueue implements Countable, IteratorAggregate, Serializable -{ - public const EXTR_DATA = 0x00000001; - public const EXTR_PRIORITY = 0x00000002; - public const EXTR_BOTH = 0x00000003; - - /** - * Inner queue class to use for iteration - * - * @var class-string<\SplPriorityQueue> - */ - protected $queueClass = SplPriorityQueue::class; - - /** - * Actual items aggregated in the priority queue. Each item is an array - * with keys "data" and "priority". - * - * @var list<array{data: T, priority: TPriority}> - */ - protected $items = []; - - /** - * Inner queue object - * - * @var \SplPriorityQueue<TPriority, T>|null - */ - protected $queue; - - /** - * Insert an item into the queue - * - * Priority defaults to 1 (low priority) if none provided. - * - * @param T $data - * @param TPriority $priority - * @return $this - */ - public function insert($data, $priority = 1) - { - /** @psalm-var TPriority $priority */ - $priority = (int) $priority; - $this->items[] = [ - 'data' => $data, - 'priority' => $priority, - ]; - $this->getQueue()->insert($data, $priority); - return $this; - } - - /** - * Remove an item from the queue - * - * This is different than {@link extract()}; its purpose is to dequeue an - * item. - * - * This operation is potentially expensive, as it requires - * re-initialization and re-population of the inner queue. - * - * Note: this removes the first item matching the provided item found. If - * the same item has been added multiple times, it will not remove other - * instances. - * - * @param mixed $datum - * @return bool False if the item was not found, true otherwise. - */ - public function remove($datum) - { - $found = false; - $key = null; - foreach ($this->items as $key => $item) { - if ($item['data'] === $datum) { - $found = true; - break; - } - } - if ($found && $key !== null) { - unset($this->items[$key]); - $this->queue = null; - - if (! $this->isEmpty()) { - $queue = $this->getQueue(); - foreach ($this->items as $item) { - $queue->insert($item['data'], $item['priority']); - } - } - return true; - } - return false; - } - - /** - * Is the queue empty? - * - * @return bool - */ - public function isEmpty() - { - return 0 === $this->count(); - } - - /** - * How many items are in the queue? - * - * @return int - */ - #[ReturnTypeWillChange] - public function count() - { - return count($this->items); - } - - /** - * Peek at the top node in the queue, based on priority. - * - * @return T - */ - public function top() - { - $queue = clone $this->getQueue(); - - return $queue->top(); - } - - /** - * Extract a node from the inner queue and sift up - * - * @return T - */ - public function extract() - { - $value = $this->getQueue()->extract(); - - $keyToRemove = null; - $highestPriority = null; - foreach ($this->items as $key => $item) { - if ($item['data'] !== $value) { - continue; - } - - if (null === $highestPriority) { - $highestPriority = $item['priority']; - $keyToRemove = $key; - continue; - } - - if ($highestPriority >= $item['priority']) { - continue; - } - - $highestPriority = $item['priority']; - $keyToRemove = $key; - } - - if ($keyToRemove !== null) { - unset($this->items[$keyToRemove]); - } - - return $value; - } - - /** - * Retrieve the inner iterator - * - * SplPriorityQueue acts as a heap, which typically implies that as items - * are iterated, they are also removed. This does not work for situations - * where the queue may be iterated multiple times. As such, this class - * aggregates the values, and also injects an SplPriorityQueue. This method - * retrieves the inner queue object, and clones it for purposes of - * iteration. - * - * @return \SplPriorityQueue<TPriority, T> - */ - #[ReturnTypeWillChange] - public function getIterator() - { - $queue = $this->getQueue(); - return clone $queue; - } - - /** - * Serialize the data structure - * - * @return string - */ - public function serialize() - { - return serialize($this->__serialize()); - } - - /** - * Magic method used for serializing of an instance. - * - * @return list<array{data: T, priority: TPriority}> - */ - public function __serialize() - { - return $this->items; - } - - /** - * Unserialize a string into a PriorityQueue object - * - * Serialization format is compatible with {@link SplPriorityQueue} - * - * @param string $data - * @return void - */ - public function unserialize($data) - { - $toUnserialize = unserialize($data); - if (! is_array($toUnserialize)) { - throw new UnexpectedValueException(sprintf( - 'Cannot deserialize %s instance; corrupt serialization data', - self::class - )); - } - - /** @psalm-var list<array{data: T, priority: TPriority}> $toUnserialize */ - - $this->__unserialize($toUnserialize); - } - - /** - * Magic method used to rebuild an instance. - * - * @param list<array{data: T, priority: TPriority}> $data Data array. - * @return void - */ - public function __unserialize($data) - { - foreach ($data as $item) { - $this->insert($item['data'], $item['priority']); - } - } - - /** - * Serialize to an array - * By default, returns only the item data, and in the order registered (not - * sorted). You may provide one of the EXTR_* flags as an argument, allowing - * the ability to return priorities or both data and priority. - * - * @param int $flag - * @return array<array-key, mixed> - * @psalm-return ($flag is self::EXTR_BOTH - * ? list<array{data: T, priority: TPriority}> - * : $flag is self::EXTR_PRIORITY - * ? list<TPriority> - * : list<T> - * ) - */ - public function toArray($flag = self::EXTR_DATA) - { - switch ($flag) { - case self::EXTR_BOTH: - return $this->items; - case self::EXTR_PRIORITY: - return array_map(static fn($item) => $item['priority'], $this->items); - case self::EXTR_DATA: - default: - return array_map(static fn($item) => $item['data'], $this->items); - } - } - - /** - * Specify the internal queue class - * - * Please see {@link getIterator()} for details on the necessity of an - * internal queue class. The class provided should extend SplPriorityQueue. - * - * @param class-string<\SplPriorityQueue> $class - * @return $this - */ - public function setInternalQueueClass($class) - { - /** @psalm-suppress RedundantCastGivenDocblockType */ - $this->queueClass = (string) $class; - return $this; - } - - /** - * Does the queue contain the given datum? - * - * @param T $datum - * @return bool - */ - public function contains($datum) - { - foreach ($this->items as $item) { - if ($item['data'] === $datum) { - return true; - } - } - return false; - } - - /** - * Does the queue have an item with the given priority? - * - * @param TPriority $priority - * @return bool - */ - public function hasPriority($priority) - { - foreach ($this->items as $item) { - if ($item['priority'] === $priority) { - return true; - } - } - return false; - } - - /** - * Get the inner priority queue instance - * - * @throws Exception\DomainException - * @return \SplPriorityQueue<TPriority, T> - * @psalm-assert !null $this->queue - */ - protected function getQueue() - { - if (null === $this->queue) { - /** @psalm-suppress UnsafeInstantiation */ - $queue = new $this->queueClass(); - /** @psalm-var \SplPriorityQueue<TPriority, T> $queue */ - $this->queue = $queue; - /** @psalm-suppress DocblockTypeContradiction, MixedArgument */ - if (! $this->queue instanceof \SplPriorityQueue) { - throw new Exception\DomainException(sprintf( - 'PriorityQueue expects an internal queue of type SplPriorityQueue; received "%s"', - get_class($this->queue) - )); - } - } - - return $this->queue; - } - - /** - * Add support for deep cloning - * - * @return void - */ - public function __clone() - { - if (null !== $this->queue) { - $this->queue = clone $this->queue; - } - } -} diff --git a/lib/laminas/laminas-stdlib/src/Request.php b/lib/laminas/laminas-stdlib/src/Request.php deleted file mode 100644 index 65026f609..000000000 --- a/lib/laminas/laminas-stdlib/src/Request.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -class Request extends Message implements RequestInterface -{ - // generic request implementation -} diff --git a/lib/laminas/laminas-stdlib/src/RequestInterface.php b/lib/laminas/laminas-stdlib/src/RequestInterface.php deleted file mode 100644 index ef9a26169..000000000 --- a/lib/laminas/laminas-stdlib/src/RequestInterface.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -interface RequestInterface extends MessageInterface -{ -} diff --git a/lib/laminas/laminas-stdlib/src/Response.php b/lib/laminas/laminas-stdlib/src/Response.php deleted file mode 100644 index a78b3c4f4..000000000 --- a/lib/laminas/laminas-stdlib/src/Response.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -class Response extends Message implements ResponseInterface -{ - // generic response implementation -} diff --git a/lib/laminas/laminas-stdlib/src/ResponseInterface.php b/lib/laminas/laminas-stdlib/src/ResponseInterface.php deleted file mode 100644 index 30497ef78..000000000 --- a/lib/laminas/laminas-stdlib/src/ResponseInterface.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -interface ResponseInterface extends MessageInterface -{ -} diff --git a/lib/laminas/laminas-stdlib/src/SplPriorityQueue.php b/lib/laminas/laminas-stdlib/src/SplPriorityQueue.php deleted file mode 100644 index e55a0e9fd..000000000 --- a/lib/laminas/laminas-stdlib/src/SplPriorityQueue.php +++ /dev/null @@ -1,156 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -use Serializable; -use UnexpectedValueException; - -use function array_key_exists; -use function get_class; -use function gettype; -use function is_array; -use function is_object; -use function serialize; -use function sprintf; -use function unserialize; - -use const PHP_INT_MAX; - -/** - * Serializable version of SplPriorityQueue - * - * Also, provides predictable heap order for datums added with the same priority - * (i.e., they will be emitted in the same order they are enqueued). - * - * @psalm-type InternalPriority = array{0: mixed, 1: int} - * @template TValue - * @template TPriority of InternalPriority - * @extends \SplPriorityQueue<TPriority, TValue> - */ -class SplPriorityQueue extends \SplPriorityQueue implements Serializable -{ - /** @var int Seed used to ensure queue order for items of the same priority */ - protected $serial = PHP_INT_MAX; - - /** - * Insert a value with a given priority - * - * Utilizes {@var $serial} to ensure that values of equal priority are - * emitted in the same order in which they are inserted. - * - * @param TValue $datum - * @param TPriority|mixed $priority - * @return void - */ - public function insert($datum, $priority) - { - if (! is_array($priority)) { - $priority = [$priority, $this->serial--]; - } - - /** @psalm-var TPriority $priority */ - - parent::insert($datum, $priority); - } - - /** - * Serialize to an array - * - * Array will be priority => data pairs - * - * @return list<TValue> - */ - public function toArray() - { - $array = []; - foreach (clone $this as $item) { - $array[] = $item; - } - return $array; - } - - /** - * Serialize - * - * @return string - */ - public function serialize() - { - return serialize($this->__serialize()); - } - - /** - * Magic method used for serializing of an instance. - * - * @return array - */ - public function __serialize() - { - $clone = clone $this; - $clone->setExtractFlags(self::EXTR_BOTH); - - $data = []; - foreach ($clone as $item) { - $data[] = $item; - } - return $data; - } - - /** - * Deserialize - * - * @param string $data - * @return void - */ - public function unserialize($data) - { - $toUnserialize = unserialize($data); - if (! is_array($toUnserialize)) { - throw new UnexpectedValueException(sprintf( - 'Cannot deserialize %s instance; corrupt serialization data', - self::class - )); - } - - $this->__unserialize($toUnserialize); - } - - /** - * Magic method used to rebuild an instance. - * - * @param array $data Data array. - * @return void - */ - public function __unserialize($data) - { - $this->serial = PHP_INT_MAX; - - foreach ($data as $item) { - if (! is_array($item)) { - throw new UnexpectedValueException(sprintf( - 'Cannot deserialize %s instance: corrupt item; expected array, received %s', - self::class, - is_object($item) ? get_class($item) : gettype($item) - )); - } - - if (! array_key_exists('data', $item)) { - throw new UnexpectedValueException(sprintf( - 'Cannot deserialize %s instance: corrupt item; missing "data" element', - self::class - )); - } - - $priority = 1; - if (array_key_exists('priority', $item)) { - $priority = (int) $item['priority']; - } - - /** @psalm-var TValue $item['data'] */ - - $this->insert($item['data'], $priority); - } - } -} diff --git a/lib/laminas/laminas-stdlib/src/SplQueue.php b/lib/laminas/laminas-stdlib/src/SplQueue.php deleted file mode 100644 index 2656a856b..000000000 --- a/lib/laminas/laminas-stdlib/src/SplQueue.php +++ /dev/null @@ -1,94 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -use ReturnTypeWillChange; -use Serializable; -use UnexpectedValueException; - -use function is_array; -use function serialize; -use function sprintf; -use function unserialize; - -/** - * Serializable version of SplQueue - * - * @template TKey of array-key - * @template TValue - * @extends \SplQueue<TValue> - */ -class SplQueue extends \SplQueue implements Serializable -{ - /** - * Return an array representing the queue - * - * @return list<TValue> - */ - public function toArray() - { - $array = []; - foreach ($this as $item) { - $array[] = $item; - } - return $array; - } - - /** - * Serialize - * - * @return string - */ - #[ReturnTypeWillChange] - public function serialize() - { - return serialize($this->__serialize()); - } - - /** - * Magic method used for serializing of an instance. - * - * @return list<TValue> - */ - #[ReturnTypeWillChange] - public function __serialize() - { - return $this->toArray(); - } - - /** - * Unserialize - * - * @param string $data - * @return void - */ - #[ReturnTypeWillChange] - public function unserialize($data) - { - $toUnserialize = unserialize($data); - if (! is_array($toUnserialize)) { - throw new UnexpectedValueException(sprintf( - 'Cannot deserialize %s instance; corrupt serialization data', - self::class - )); - } - - $this->__unserialize($toUnserialize); - } - - /** - * Magic method used to rebuild an instance. - * - * @param array<array-key, TValue> $data Data array. - * @return void - */ - #[ReturnTypeWillChange] - public function __unserialize($data) - { - foreach ($data as $item) { - $this->push($item); - } - } -} diff --git a/lib/laminas/laminas-stdlib/src/SplStack.php b/lib/laminas/laminas-stdlib/src/SplStack.php deleted file mode 100644 index 52564fde8..000000000 --- a/lib/laminas/laminas-stdlib/src/SplStack.php +++ /dev/null @@ -1,93 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -use ReturnTypeWillChange; -use Serializable; -use UnexpectedValueException; - -use function is_array; -use function serialize; -use function sprintf; -use function unserialize; - -/** - * Serializable version of SplStack - * - * @template TValue - * @extends \SplStack<TValue> - */ -class SplStack extends \SplStack implements Serializable -{ - /** - * Serialize to an array representing the stack - * - * @return list<TValue> - */ - public function toArray() - { - $array = []; - foreach ($this as $item) { - $array[] = $item; - } - return $array; - } - - /** - * Serialize - * - * @return string - */ - #[ReturnTypeWillChange] - public function serialize() - { - return serialize($this->__serialize()); - } - - /** - * Magic method used for serializing of an instance. - * - * @return list<TValue> - */ - #[ReturnTypeWillChange] - public function __serialize() - { - return $this->toArray(); - } - - /** - * Unserialize - * - * @param string $data - * @return void - */ - #[ReturnTypeWillChange] - public function unserialize($data) - { - $toUnserialize = unserialize($data); - if (! is_array($toUnserialize)) { - throw new UnexpectedValueException(sprintf( - 'Cannot deserialize %s instance; corrupt serialization data', - self::class - )); - } - - $this->__unserialize($toUnserialize); - } - - /** - * Magic method used to rebuild an instance. - * - * @param array<array-key, TValue> $data Data array. - * @return void - */ - #[ReturnTypeWillChange] - public function __unserialize($data) - { - foreach ($data as $item) { - $this->unshift($item); - } - } -} diff --git a/lib/laminas/laminas-stdlib/src/StringUtils.php b/lib/laminas/laminas-stdlib/src/StringUtils.php deleted file mode 100644 index ffc3ad553..000000000 --- a/lib/laminas/laminas-stdlib/src/StringUtils.php +++ /dev/null @@ -1,213 +0,0 @@ -<?php // phpcs:disable WebimpressCodingStandard.NamingConventions.AbstractClass.Prefix - - -declare(strict_types=1); - -namespace Laminas\Stdlib; - -use Laminas\Stdlib\StringWrapper\Iconv; -use Laminas\Stdlib\StringWrapper\Intl; -use Laminas\Stdlib\StringWrapper\MbString; -use Laminas\Stdlib\StringWrapper\Native; -use Laminas\Stdlib\StringWrapper\StringWrapperInterface; - -use function array_search; -use function defined; -use function extension_loaded; -use function in_array; -use function is_string; -use function preg_match; -use function strtoupper; - -/** - * Utility class for handling strings of different character encodings - * using available PHP extensions. - * - * Declared abstract, as we have no need for instantiation. - */ -abstract class StringUtils -{ - /** - * Ordered list of registered string wrapper instances - * - * @var list<class-string<StringWrapperInterface>>|null - */ - protected static $wrapperRegistry; - - /** - * A list of known single-byte character encodings (upper-case) - * - * @var string[] - */ - protected static $singleByteEncodings = [ - 'ASCII', - '7BIT', - '8BIT', - 'ISO-8859-1', - 'ISO-8859-2', - 'ISO-8859-3', - 'ISO-8859-4', - 'ISO-8859-5', - 'ISO-8859-6', - 'ISO-8859-7', - 'ISO-8859-8', - 'ISO-8859-9', - 'ISO-8859-10', - 'ISO-8859-11', - 'ISO-8859-13', - 'ISO-8859-14', - 'ISO-8859-15', - 'ISO-8859-16', - 'CP-1251', - 'CP-1252', - // TODO - ]; - - /** - * Is PCRE compiled with Unicode support? - * - * @var bool - **/ - protected static $hasPcreUnicodeSupport; - - /** - * Get registered wrapper classes - * - * @return string[] - * @psalm-return list<class-string<StringWrapperInterface>> - */ - public static function getRegisteredWrappers() - { - if (static::$wrapperRegistry === null) { - static::$wrapperRegistry = []; - - if (extension_loaded('intl')) { - static::$wrapperRegistry[] = Intl::class; - } - - if (extension_loaded('mbstring')) { - static::$wrapperRegistry[] = MbString::class; - } - - if (extension_loaded('iconv')) { - static::$wrapperRegistry[] = Iconv::class; - } - - static::$wrapperRegistry[] = Native::class; - } - - return static::$wrapperRegistry; - } - - /** - * Register a string wrapper class - * - * @param class-string<StringWrapperInterface> $wrapper - * @return void - */ - public static function registerWrapper($wrapper) - { - $wrapper = (string) $wrapper; - // using getRegisteredWrappers() here to ensure that the list is initialized - if (! in_array($wrapper, static::getRegisteredWrappers(), true)) { - static::$wrapperRegistry[] = $wrapper; - } - } - - /** - * Unregister a string wrapper class - * - * @param class-string<StringWrapperInterface> $wrapper - * @return void - */ - public static function unregisterWrapper($wrapper) - { - // using getRegisteredWrappers() here to ensure that the list is initialized - $index = array_search((string) $wrapper, static::getRegisteredWrappers(), true); - if ($index !== false) { - unset(static::$wrapperRegistry[$index]); - } - } - - /** - * Reset all registered wrappers so the default wrappers will be used - * - * @return void - */ - public static function resetRegisteredWrappers() - { - static::$wrapperRegistry = null; - } - - /** - * Get the first string wrapper supporting the given character encoding - * and supports to convert into the given convert encoding. - * - * @param string $encoding Character encoding to support - * @param string|null $convertEncoding OPTIONAL character encoding to convert in - * @return StringWrapperInterface - * @throws Exception\RuntimeException If no wrapper supports given character encodings. - */ - public static function getWrapper($encoding = 'UTF-8', $convertEncoding = null) - { - foreach (static::getRegisteredWrappers() as $wrapperClass) { - if ($wrapperClass::isSupported($encoding, $convertEncoding)) { - $wrapper = new $wrapperClass($encoding, $convertEncoding); - $wrapper->setEncoding($encoding, $convertEncoding); - return $wrapper; - } - } - - throw new Exception\RuntimeException( - 'No wrapper found supporting "' . $encoding . '"' - . ($convertEncoding !== null ? ' and "' . $convertEncoding . '"' : '') - ); - } - - /** - * Get a list of all known single-byte character encodings - * - * @return string[] - */ - public static function getSingleByteEncodings() - { - return static::$singleByteEncodings; - } - - /** - * Check if a given encoding is a known single-byte character encoding - * - * @param string $encoding - * @return bool - */ - public static function isSingleByteEncoding($encoding) - { - return in_array(strtoupper($encoding), static::$singleByteEncodings); - } - - /** - * Check if a given string is valid UTF-8 encoded - * - * @param string $str - * @return bool - */ - public static function isValidUtf8($str) - { - return is_string($str) && ($str === '' || preg_match('/^./su', $str) === 1); - } - - /** - * Is PCRE compiled with Unicode support? - * - * @return bool - */ - public static function hasPcreUnicodeSupport() - { - if (static::$hasPcreUnicodeSupport === null) { - ErrorHandler::start(); - static::$hasPcreUnicodeSupport = defined('PREG_BAD_UTF8_OFFSET_ERROR') && preg_match('/\pL/u', 'a') === 1; - ErrorHandler::stop(); - } - return static::$hasPcreUnicodeSupport; - } -} diff --git a/lib/laminas/laminas-stdlib/src/StringWrapper/AbstractStringWrapper.php b/lib/laminas/laminas-stdlib/src/StringWrapper/AbstractStringWrapper.php deleted file mode 100644 index a96c7a468..000000000 --- a/lib/laminas/laminas-stdlib/src/StringWrapper/AbstractStringWrapper.php +++ /dev/null @@ -1,278 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib\StringWrapper; - -use Laminas\Stdlib\Exception; -use Laminas\Stdlib\StringUtils; - -use function floor; -use function in_array; -use function sprintf; -use function str_pad; -use function str_repeat; -use function strtoupper; -use function wordwrap; - -use const STR_PAD_BOTH; -use const STR_PAD_LEFT; -use const STR_PAD_RIGHT; - -abstract class AbstractStringWrapper implements StringWrapperInterface -{ - /** - * The character encoding working on - * - * @var string|null - */ - protected $encoding = 'UTF-8'; - - /** - * An optionally character encoding to convert to - * - * @var string|null - */ - protected $convertEncoding; - - /** - * Check if the given character encoding is supported by this wrapper - * and the character encoding to convert to is also supported. - * - * @param string $encoding - * @param string|null $convertEncoding - * @return bool - */ - public static function isSupported($encoding, $convertEncoding = null) - { - $supportedEncodings = static::getSupportedEncodings(); - - if (! in_array(strtoupper($encoding), $supportedEncodings)) { - return false; - } - - if ($convertEncoding !== null && ! in_array(strtoupper($convertEncoding), $supportedEncodings)) { - return false; - } - - return true; - } - - /** - * Set character encoding working with and convert to - * - * @param string $encoding The character encoding to work with - * @param string|null $convertEncoding The character encoding to convert to - * @return StringWrapperInterface - */ - public function setEncoding($encoding, $convertEncoding = null) - { - $supportedEncodings = static::getSupportedEncodings(); - - $encodingUpper = strtoupper($encoding); - if (! in_array($encodingUpper, $supportedEncodings)) { - throw new Exception\InvalidArgumentException( - 'Wrapper doesn\'t support character encoding "' . $encoding . '"' - ); - } - - if ($convertEncoding !== null) { - $convertEncodingUpper = strtoupper($convertEncoding); - if (! in_array($convertEncodingUpper, $supportedEncodings)) { - throw new Exception\InvalidArgumentException( - 'Wrapper doesn\'t support character encoding "' . $convertEncoding . '"' - ); - } - - $this->convertEncoding = $convertEncodingUpper; - } else { - $this->convertEncoding = null; - } - $this->encoding = $encodingUpper; - - return $this; - } - - /** - * Get the defined character encoding to work with - * - * @return null|string - * @throws Exception\LogicException If no encoding was defined. - */ - public function getEncoding() - { - return $this->encoding; - } - - /** - * Get the defined character encoding to convert to - * - * @return string|null - */ - public function getConvertEncoding() - { - return $this->convertEncoding; - } - - /** - * Convert a string from defined character encoding to the defined convert encoding - * - * @param string $str - * @param bool $reverse - * @return string|false - */ - public function convert($str, $reverse = false) - { - $encoding = $this->getEncoding(); - $convertEncoding = $this->getConvertEncoding(); - if ($convertEncoding === null) { - throw new Exception\LogicException( - 'No convert encoding defined' - ); - } - - if ($encoding === $convertEncoding) { - return $str; - } - - $from = $reverse ? $convertEncoding : $encoding; - $to = $reverse ? $encoding : $convertEncoding; - throw new Exception\RuntimeException(sprintf( - 'Converting from "%s" to "%s" isn\'t supported by this string wrapper', - $from ?? '', - $to ?? '' - )); - } - - /** - * Wraps a string to a given number of characters - * - * @param string $string - * @param int $width - * @param string $break - * @param bool $cut - * @return string|false - */ - public function wordWrap($string, $width = 75, $break = "\n", $cut = false) - { - $string = (string) $string; - if ($string === '') { - return ''; - } - - $break = (string) $break; - if ($break === '') { - throw new Exception\InvalidArgumentException('Break string cannot be empty'); - } - - $width = (int) $width; - if ($width === 0 && $cut) { - throw new Exception\InvalidArgumentException('Cannot force cut when width is zero'); - } - - if (null === $this->getEncoding() || StringUtils::isSingleByteEncoding($this->getEncoding())) { - return wordwrap($string, $width, $break, $cut); - } - - $stringWidth = $this->strlen($string); - $breakWidth = $this->strlen($break); - - $result = ''; - $lastStart = $lastSpace = 0; - - for ($current = 0; $current < $stringWidth; $current++) { - $char = $this->substr($string, $current, 1); - - $possibleBreak = $char; - if ($breakWidth !== 1) { - $possibleBreak = $this->substr($string, $current, $breakWidth); - } - - if ($possibleBreak === $break) { - $result .= $this->substr($string, $lastStart, $current - $lastStart + $breakWidth); - $current += $breakWidth - 1; - $lastStart = $lastSpace = $current + 1; - continue; - } - - if ($char === ' ') { - if ($current - $lastStart >= $width) { - $result .= $this->substr($string, $lastStart, $current - $lastStart) . $break; - $lastStart = $current + 1; - } - - $lastSpace = $current; - continue; - } - - if ($current - $lastStart >= $width && $cut && $lastStart >= $lastSpace) { - $result .= $this->substr($string, $lastStart, $current - $lastStart) . $break; - $lastStart = $lastSpace = $current; - continue; - } - - if ($current - $lastStart >= $width && $lastStart < $lastSpace) { - $result .= $this->substr($string, $lastStart, $lastSpace - $lastStart) . $break; - $lastStart = $lastSpace += 1; - continue; - } - } - - if ($lastStart !== $current) { - $result .= $this->substr($string, $lastStart, $current - $lastStart); - } - - return $result; - } - - /** - * Pad a string to a certain length with another string - * - * @param string $input - * @param int $padLength - * @param string $padString - * @param int $padType - * @return string - */ - public function strPad($input, $padLength, $padString = ' ', $padType = STR_PAD_RIGHT) - { - if (null === $this->getEncoding() || StringUtils::isSingleByteEncoding($this->getEncoding())) { - return str_pad($input, $padLength, $padString, $padType); - } - - $lengthOfPadding = $padLength - $this->strlen($input); - if ($lengthOfPadding <= 0) { - return $input; - } - - $padStringLength = $this->strlen($padString); - if ($padStringLength === 0) { - return $input; - } - - $repeatCount = (int) floor($lengthOfPadding / $padStringLength); - - if ($padType === STR_PAD_BOTH) { - $repeatCountLeft = $repeatCountRight = ($repeatCount - $repeatCount % 2) / 2; - - $lastStringLength = $lengthOfPadding - 2 * $repeatCountLeft * $padStringLength; - $lastStringLeftLength = $lastStringRightLength = (int) floor($lastStringLength / 2); - $lastStringRightLength += $lastStringLength % 2; - - $lastStringLeft = $this->substr($padString, 0, $lastStringLeftLength); - $lastStringRight = $this->substr($padString, 0, $lastStringRightLength); - - return str_repeat($padString, $repeatCountLeft) . $lastStringLeft - . $input - . str_repeat($padString, $repeatCountRight) . $lastStringRight; - } - - $lastString = $this->substr($padString, 0, $lengthOfPadding % $padStringLength); - - if ($padType === STR_PAD_LEFT) { - return str_repeat($padString, $repeatCount) . $lastString . $input; - } - - return $input . str_repeat($padString, $repeatCount) . $lastString; - } -} diff --git a/lib/laminas/laminas-stdlib/src/StringWrapper/Iconv.php b/lib/laminas/laminas-stdlib/src/StringWrapper/Iconv.php deleted file mode 100644 index 2f52b74e1..000000000 --- a/lib/laminas/laminas-stdlib/src/StringWrapper/Iconv.php +++ /dev/null @@ -1,302 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib\StringWrapper; - -use Laminas\Stdlib\Exception; - -use function assert; -use function extension_loaded; -use function iconv; -use function iconv_strlen; -use function iconv_strpos; -use function iconv_substr; - -class Iconv extends AbstractStringWrapper -{ - /** - * List of supported character sets (upper case) - * - * @link http://www.gnu.org/software/libiconv/ - * - * @var string[] - */ - protected static $encodings = [ - // European languages - 'ASCII', - 'ISO-8859-1', - 'ISO-8859-2', - 'ISO-8859-3', - 'ISO-8859-4', - 'ISO-8859-5', - 'ISO-8859-7', - 'ISO-8859-9', - 'ISO-8859-10', - 'ISO-8859-13', - 'ISO-8859-14', - 'ISO-8859-15', - 'ISO-8859-16', - 'KOI8-R', - 'KOI8-U', - 'KOI8-RU', - 'CP1250', - 'CP1251', - 'CP1252', - 'CP1253', - 'CP1254', - 'CP1257', - 'CP850', - 'CP866', - 'CP1131', - 'MACROMAN', - 'MACCENTRALEUROPE', - 'MACICELAND', - 'MACCROATIAN', - 'MACROMANIA', - 'MACCYRILLIC', - 'MACUKRAINE', - 'MACGREEK', - 'MACTURKISH', - 'MACINTOSH', - - // Semitic languages - 'ISO-8859-6', - 'ISO-8859-8', - 'CP1255', - 'CP1256', - 'CP862', - 'MACHEBREW', - 'MACARABIC', - - // Japanese - 'EUC-JP', - 'SHIFT_JIS', - 'CP932', - 'ISO-2022-JP', - 'ISO-2022-JP-2', - 'ISO-2022-JP-1', - - // Chinese - 'EUC-CN', - 'HZ', - 'GBK', - 'CP936', - 'GB18030', - 'EUC-TW', - 'BIG5', - 'CP950', - 'BIG5-HKSCS', - 'BIG5-HKSCS:2004', - 'BIG5-HKSCS:2001', - 'BIG5-HKSCS:1999', - 'ISO-2022-CN', - 'ISO-2022-CN-EXT', - - // Korean - 'EUC-KR', - 'CP949', - 'ISO-2022-KR', - 'JOHAB', - - // Armenian - 'ARMSCII-8', - - // Georgian - 'GEORGIAN-ACADEMY', - 'GEORGIAN-PS', - - // Tajik - 'KOI8-T', - - // Kazakh - 'PT154', - 'RK1048', - - // Thai - 'ISO-8859-11', - 'TIS-620', - 'CP874', - 'MACTHAI', - - // Laotian - 'MULELAO-1', - 'CP1133', - - // Vietnamese - 'VISCII', - 'TCVN', - 'CP1258', - - // Platform specifics - 'HP-ROMAN8', - 'NEXTSTEP', - - // Full Unicode - 'UTF-8', - 'UCS-2', - 'UCS-2BE', - 'UCS-2LE', - 'UCS-4', - 'UCS-4BE', - 'UCS-4LE', - 'UTF-16', - 'UTF-16BE', - 'UTF-16LE', - 'UTF-32', - 'UTF-32BE', - 'UTF-32LE', - 'UTF-7', - 'C99', - 'JAVA', - - /* Commented out because that's internal encodings not existing in real world - // Full Unicode, in terms of uint16_t or uint32_t (with machine dependent endianness and alignment) - 'UCS-2-INTERNAL', - 'UCS-4-INTERNAL', - - // Locale dependent, in terms of `char' or `wchar_t' (with machine dependent endianness and alignment, - // and with OS and locale dependent semantics) - 'char', - 'wchar_t', - '', // The empty encoding name is equivalent to "char": it denotes the locale dependent character encoding. - */ - - // When configured with the option --enable-extra-encodings, - // it also provides support for a few extra encodings: - - // European languages - 'CP437', - 'CP737', - 'CP775', - 'CP852', - 'CP853', - 'CP855', - 'CP857', - 'CP858', - 'CP860', - 'CP861', - 'CP863', - 'CP865', - 'CP869', - 'CP1125', - - // Semitic languages - 'CP864', - - // Japanese - 'EUC-JISX0213', - 'Shift_JISX0213', - 'ISO-2022-JP-3', - - // Chinese - 'BIG5-2003', // (experimental) - - // Turkmen - 'TDS565', - - // Platform specifics - 'ATARIST', - 'RISCOS-LATIN1', - ]; - - /** - * Get a list of supported character encodings - * - * @return string[] - */ - public static function getSupportedEncodings() - { - return static::$encodings; - } - - /** - * Constructor - * - * @throws Exception\ExtensionNotLoadedException - */ - public function __construct() - { - if (! extension_loaded('iconv')) { - throw new Exception\ExtensionNotLoadedException( - 'PHP extension "iconv" is required for this wrapper' - ); - } - } - - /** - * Returns the length of the given string - * - * @param string $str - * @return int|false - */ - public function strlen($str) - { - return iconv_strlen($str, $this->getEncoding()); - } - - /** - * Returns the portion of string specified by the start and length parameters - * - * @param string $str - * @param int $offset - * @param int|null $length - * @return string|false - */ - public function substr($str, $offset = 0, $length = null) - { - $length ??= $this->strlen($str); - assert($length !== false); - - return iconv_substr($str, $offset, $length, $this->getEncoding()); - } - - /** - * Find the position of the first occurrence of a substring in a string - * - * @param string $haystack - * @param string $needle - * @param int $offset - * @return int|false - */ - public function strpos($haystack, $needle, $offset = 0) - { - $encoding = $this->getEncoding(); - assert($encoding !== null); - - return iconv_strpos($haystack, $needle, $offset, $encoding); - } - - /** - * Convert a string from defined encoding to the defined convert encoding - * - * @param string $str - * @param bool $reverse - * @return string|false - */ - public function convert($str, $reverse = false) - { - $encoding = $this->getEncoding(); - $convertEncoding = $this->getConvertEncoding(); - if ($convertEncoding === null) { - throw new Exception\LogicException( - 'No convert encoding defined' - ); - } - - if ($encoding === $convertEncoding) { - return $str; - } - - $fromEncoding = $reverse ? $convertEncoding : $encoding; - $toEncoding = $reverse ? $encoding : $convertEncoding; - - if (null === $toEncoding || null === $fromEncoding) { - return $str; - } - - // automatically add "//IGNORE" to not stop converting on invalid characters - // invalid characters triggers a notice anyway - return iconv($fromEncoding, $toEncoding . '//IGNORE', $str); - } -} diff --git a/lib/laminas/laminas-stdlib/src/StringWrapper/Intl.php b/lib/laminas/laminas-stdlib/src/StringWrapper/Intl.php deleted file mode 100644 index 81a6b9a8a..000000000 --- a/lib/laminas/laminas-stdlib/src/StringWrapper/Intl.php +++ /dev/null @@ -1,89 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib\StringWrapper; - -use Laminas\Stdlib\Exception; - -use function extension_loaded; -use function grapheme_strlen; -use function grapheme_strpos; -use function grapheme_substr; - -class Intl extends AbstractStringWrapper -{ - /** - * List of supported character sets (upper case) - * - * @var string[] - */ - protected static $encodings = ['UTF-8']; - - /** - * Get a list of supported character encodings - * - * @return string[] - */ - public static function getSupportedEncodings() - { - return static::$encodings; - } - - /** - * Constructor - * - * @throws Exception\ExtensionNotLoadedException - */ - public function __construct() - { - if (! extension_loaded('intl')) { - throw new Exception\ExtensionNotLoadedException( - 'PHP extension "intl" is required for this wrapper' - ); - } - } - - /** - * Returns the length of the given string - * - * @param string $str - * @return false|int - */ - public function strlen($str) - { - $len = grapheme_strlen($str); - return $len ?? false; - } - - /** - * Returns the portion of string specified by the start and length parameters - * - * @param string $str - * @param int $offset - * @param int|null $length - * @return string|false - */ - public function substr($str, $offset = 0, $length = null) - { - // Due fix of PHP #62759 The third argument returns an empty string if is 0 or null. - if ($length !== null) { - return grapheme_substr($str, $offset, $length); - } - - return grapheme_substr($str, $offset); - } - - /** - * Find the position of the first occurrence of a substring in a string - * - * @param string $haystack - * @param string $needle - * @param int $offset - * @return int|false - */ - public function strpos($haystack, $needle, $offset = 0) - { - return grapheme_strpos($haystack, $needle, $offset); - } -} diff --git a/lib/laminas/laminas-stdlib/src/StringWrapper/MbString.php b/lib/laminas/laminas-stdlib/src/StringWrapper/MbString.php deleted file mode 100644 index d36168144..000000000 --- a/lib/laminas/laminas-stdlib/src/StringWrapper/MbString.php +++ /dev/null @@ -1,127 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib\StringWrapper; - -use Laminas\Stdlib\Exception; - -use function array_map; -use function array_search; -use function extension_loaded; -use function mb_convert_encoding; -use function mb_list_encodings; -use function mb_strlen; -use function mb_strpos; -use function mb_substr; - -class MbString extends AbstractStringWrapper -{ - /** - * List of supported character sets (upper case) - * - * @link http://php.net/manual/mbstring.supported-encodings.php - * - * @var null|string[] - */ - protected static $encodings; - - /** - * Get a list of supported character encodings - * - * @return string[] - */ - public static function getSupportedEncodings() - { - if (static::$encodings === null) { - static::$encodings = array_map('strtoupper', mb_list_encodings()); - - // FIXME: Converting € (UTF-8) to ISO-8859-16 gives a wrong result - $indexIso885916 = array_search('ISO-8859-16', static::$encodings, true); - if ($indexIso885916 !== false) { - unset(static::$encodings[$indexIso885916]); - } - } - - return static::$encodings; - } - - /** - * Constructor - * - * @throws Exception\ExtensionNotLoadedException - */ - public function __construct() - { - if (! extension_loaded('mbstring')) { - throw new Exception\ExtensionNotLoadedException( - 'PHP extension "mbstring" is required for this wrapper' - ); - } - } - - /** - * Returns the length of the given string - * - * @param string $str - * @return int|false - */ - public function strlen($str) - { - return mb_strlen($str, $this->getEncoding()); - } - - /** - * Returns the portion of string specified by the start and length parameters - * - * @param string $str - * @param int $offset - * @param int|null $length - * @return string|false - */ - public function substr($str, $offset = 0, $length = null) - { - return mb_substr($str, $offset, $length, $this->getEncoding()); - } - - /** - * Find the position of the first occurrence of a substring in a string - * - * @param string $haystack - * @param string $needle - * @param int $offset - * @return int|false - */ - public function strpos($haystack, $needle, $offset = 0) - { - return mb_strpos($haystack, $needle, $offset, $this->getEncoding()); - } - - /** - * Convert a string from defined encoding to the defined convert encoding - * - * @param string $str - * @param bool $reverse - * @return string|false - */ - public function convert($str, $reverse = false) - { - $encoding = $this->getEncoding(); - $convertEncoding = $this->getConvertEncoding(); - - if ($convertEncoding === null) { - throw new Exception\LogicException( - 'No convert encoding defined' - ); - } - - if ($encoding === $convertEncoding) { - return $str; - } - - $fromEncoding = $reverse ? $convertEncoding : $encoding; - $toEncoding = $reverse ? $encoding : $convertEncoding; - - return mb_convert_encoding($str, $toEncoding ?? '', $fromEncoding ?? ''); - } -} diff --git a/lib/laminas/laminas-stdlib/src/StringWrapper/Native.php b/lib/laminas/laminas-stdlib/src/StringWrapper/Native.php deleted file mode 100644 index a137d4ae1..000000000 --- a/lib/laminas/laminas-stdlib/src/StringWrapper/Native.php +++ /dev/null @@ -1,135 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib\StringWrapper; - -use Laminas\Stdlib\Exception; -use Laminas\Stdlib\StringUtils; - -use function in_array; -use function strlen; -use function strpos; -use function strtoupper; -use function substr; - -class Native extends AbstractStringWrapper -{ - /** - * The character encoding working on - * (overwritten to change default encoding) - * - * @var string - */ - protected $encoding = 'ASCII'; - - /** - * Check if the given character encoding is supported by this wrapper - * and the character encoding to convert to is also supported. - * - * @param string $encoding - * @param string|null $convertEncoding - * @return bool - */ - public static function isSupported($encoding, $convertEncoding = null) - { - $encodingUpper = strtoupper($encoding); - $supportedEncodings = static::getSupportedEncodings(); - - if (! in_array($encodingUpper, $supportedEncodings)) { - return false; - } - - // This adapter doesn't support to convert between encodings - if ($convertEncoding !== null && $encodingUpper !== strtoupper($convertEncoding)) { - return false; - } - - return true; - } - - /** - * Get a list of supported character encodings - * - * @return string[] - */ - public static function getSupportedEncodings() - { - return StringUtils::getSingleByteEncodings(); - } - - /** - * Set character encoding working with and convert to - * - * @param string $encoding The character encoding to work with - * @param string|null $convertEncoding The character encoding to convert to - * @return StringWrapperInterface - */ - public function setEncoding($encoding, $convertEncoding = null) - { - $supportedEncodings = static::getSupportedEncodings(); - - $encodingUpper = strtoupper($encoding); - if (! in_array($encodingUpper, $supportedEncodings)) { - throw new Exception\InvalidArgumentException( - 'Wrapper doesn\'t support character encoding "' . $encoding . '"' - ); - } - - if (null !== $convertEncoding && $encodingUpper !== strtoupper($convertEncoding)) { - $this->convertEncoding = $encodingUpper; - } - - if ($convertEncoding !== null) { - if ($encodingUpper !== strtoupper($convertEncoding)) { - throw new Exception\InvalidArgumentException( - 'Wrapper doesn\'t support to convert between character encodings' - ); - } - - $this->convertEncoding = $encodingUpper; - } else { - $this->convertEncoding = null; - } - $this->encoding = $encodingUpper; - - return $this; - } - - /** - * Returns the length of the given string - * - * @param string $str - * @return int|false - */ - public function strlen($str) - { - return strlen($str); - } - - /** - * Returns the portion of string specified by the start and length parameters - * - * @param string $str - * @param int $offset - * @param int|null $length - * @return string|false - */ - public function substr($str, $offset = 0, $length = null) - { - return substr($str, $offset, $length); - } - - /** - * Find the position of the first occurrence of a substring in a string - * - * @param string $haystack - * @param string $needle - * @param int $offset - * @return int|false - */ - public function strpos($haystack, $needle, $offset = 0) - { - return strpos($haystack, $needle, $offset); - } -} diff --git a/lib/laminas/laminas-stdlib/src/StringWrapper/StringWrapperInterface.php b/lib/laminas/laminas-stdlib/src/StringWrapper/StringWrapperInterface.php deleted file mode 100644 index 700799f91..000000000 --- a/lib/laminas/laminas-stdlib/src/StringWrapper/StringWrapperInterface.php +++ /dev/null @@ -1,108 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Stdlib\StringWrapper; - -use const STR_PAD_RIGHT; - -interface StringWrapperInterface -{ - /** - * Check if the given character encoding is supported by this wrapper - * and the character encoding to convert to is also supported. - * - * @param string $encoding - * @param string|null $convertEncoding - */ - public static function isSupported($encoding, $convertEncoding = null); - - /** - * Get a list of supported character encodings - * - * @return string[] - */ - public static function getSupportedEncodings(); - - /** - * Set character encoding working with and convert to - * - * @param string $encoding The character encoding to work with - * @param string|null $convertEncoding The character encoding to convert to - * @return StringWrapperInterface - */ - public function setEncoding($encoding, $convertEncoding = null); - - /** - * Get the defined character encoding to work with (upper case) - * - * @return string|null - */ - public function getEncoding(); - - /** - * Get the defined character encoding to convert to (upper case) - * - * @return string|null - */ - public function getConvertEncoding(); - - /** - * Returns the length of the given string - * - * @param string $str - * @return int|false - */ - public function strlen($str); - - /** - * Returns the portion of string specified by the start and length parameters - * - * @param string $str - * @param int $offset - * @param int|null $length - * @return string|false - */ - public function substr($str, $offset = 0, $length = null); - - /** - * Find the position of the first occurrence of a substring in a string - * - * @param string $haystack - * @param string $needle - * @param int $offset - * @return int|false - */ - public function strpos($haystack, $needle, $offset = 0); - - /** - * Convert a string from defined encoding to the defined convert encoding - * - * @param string $str - * @param bool $reverse - * @return string|false - */ - public function convert($str, $reverse = false); - - /** - * Wraps a string to a given number of characters - * - * @param string $str - * @param int $width - * @param string $break - * @param bool $cut - * @return string - */ - public function wordWrap($str, $width = 75, $break = "\n", $cut = false); - - /** - * Pad a string to a certain length with another string - * - * @param string $input - * @param int $padLength - * @param string $padString - * @param int $padType - * @return string - */ - public function strPad($input, $padLength, $padString = ' ', $padType = STR_PAD_RIGHT); -} diff --git a/lib/laminas/laminas-validator/COPYRIGHT.md b/lib/laminas/laminas-validator/COPYRIGHT.md deleted file mode 100644 index 0a8cccc06..000000000 --- a/lib/laminas/laminas-validator/COPYRIGHT.md +++ /dev/null @@ -1 +0,0 @@ -Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/) diff --git a/lib/laminas/laminas-validator/LICENSE.md b/lib/laminas/laminas-validator/LICENSE.md deleted file mode 100644 index 10b40f142..000000000 --- a/lib/laminas/laminas-validator/LICENSE.md +++ /dev/null @@ -1,26 +0,0 @@ -Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -- Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -- Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -- Neither the name of Laminas Foundation nor the names of its contributors may - be used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/lib/laminas/laminas-validator/README.md b/lib/laminas/laminas-validator/README.md deleted file mode 100644 index 77f1c46b8..000000000 --- a/lib/laminas/laminas-validator/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# laminas-validator - -[![Build Status](https://github.com/laminas/laminas-validator/actions/workflows/continuous-integration.yml/badge.svg)](https://github.com/laminas/laminas-validator/actions/workflows/continuous-integration.yml) - -> ## 🇷🇺 Русским гражданам -> -> Мы, участники Laminas, родились и живем в разных странах. У многих из нас есть друзья, родственники и коллеги как в России, так и в Украине. Некоторые из нас родились в России. Некоторые из нас живут в России. У некоторых бабушки и дедушки сражались с фашистами во Второй мировой войне. Здесь никто не поддерживает фашизм. -> -> У одного из нас есть украинская родственница, которая спаслась из дома вместе с сыном. Поезд задержался из-за бомбежки на дороге впереди. У нас есть друзья, которые прячутся в бомбоубежищах. Мы с тревогой ждем весточки от них после воздушных налетов, которые беспорядочно наносят удары и попадают по больницам, школам, детским садам и домам. Мы не берем это из каких-либо СМИ. Мы наблюдаем это напрямую. -> -> Вы доверяете нам достаточно, чтоб использовать наши программы, и мы просим вас довериться нам вновь. Мы нуждаемся в помощи. Выходите и протестуйте против этой бесполезной войны. Остановите кровопролитие. Скажите "Нет войне!" -> -> ## 🇺🇸 To Citizens of Russia -> -> We at Laminas come from all over the world. Many of us have friends, family and colleagues in both Russia and Ukraine. Some of us were born in Russia. Some of us currently live in Russia. Some have grandparents who fought Nazis in World War II. Nobody here supports fascism. -> -> One team member has a Ukrainian relative who fled her home with her son. The train was delayed due to bombing on the road ahead. We have friends who are hiding in bomb shelters. We anxiously follow up on them after the air raids, which indiscriminately fire at hospitals, schools, kindergartens and houses. We're not taking this from any media. These are our actual experiences. -> -> You trust us enough to use our software. We ask that you trust us to say the truth on this. We need your help. Go out and protest this unnecessary war. Stop the bloodshed. Say "stop the war!" - -laminas-validator provides a set of commonly needed validators. It also provides a -simple validator chaining mechanism by which multiple validators may be applied -to a single datum in a user-defined order. - -## Installation - -Run the following to install this library: - -```bash -$ composer require laminas/laminas-validator -``` - -## Documentation - -Browse the documentation online at https://docs.laminas.dev/laminas-validator/ - -## Support - -* [Issues](https://github.com/laminas/laminas-validator/issues/) -* [Chat](https://laminas.dev/chat/) -* [Forum](https://discourse.laminas.dev/) diff --git a/lib/laminas/laminas-validator/bin/update_hostname_validator.php b/lib/laminas/laminas-validator/bin/update_hostname_validator.php deleted file mode 100644 index fbc461634..000000000 --- a/lib/laminas/laminas-validator/bin/update_hostname_validator.php +++ /dev/null @@ -1,196 +0,0 @@ -<?php - -/** - * @see https://github.com/laminas/laminas-validator for the canonical source repository - * @copyright https://github.com/laminas/laminas-validator/blob/master/COPYRIGHT.md - * @license https://github.com/laminas/laminas-validator/blob/master/LICENSE.md New BSD License - */ - -use Laminas\Http\Client; -use Laminas\Validator\Hostname; - -require __DIR__ . '/../vendor/autoload.php'; - -define('IANA_URL', 'https://data.iana.org/TLD/tlds-alpha-by-domain.txt'); -define('LAMINAS_HOSTNAME_VALIDATOR_FILE', __DIR__.'/../src/Hostname.php'); - - -if (! file_exists(LAMINAS_HOSTNAME_VALIDATOR_FILE) || ! is_readable(LAMINAS_HOSTNAME_VALIDATOR_FILE)) { - printf("Error: cannot read file '%s'%s", LAMINAS_HOSTNAME_VALIDATOR_FILE, PHP_EOL); - exit(1); -} - -if (! is_writable(LAMINAS_HOSTNAME_VALIDATOR_FILE)) { - printf("Error: cannot update file '%s'%s", LAMINAS_HOSTNAME_VALIDATOR_FILE, PHP_EOL); - exit(1); -} - -/** @psalm-var list<string> $newFileContent */ -$newFileContent = []; // new file content -$insertDone = false; // becomes 'true' when we find start of $validTlds declaration -$insertFinish = false; // becomes 'true' when we find end of $validTlds declaration -$checkOnly = isset($argv[1]) ? $argv[1] === '--check-only' : false; -$response = getOfficialTLDs(); -$ianaVersion = getVersionFromString('Version', strtok($response->getBody(), "\n")); -$validatorVersion = getVersionFromString('IanaVersion', file_get_contents(LAMINAS_HOSTNAME_VALIDATOR_FILE)); - -if ($checkOnly && $ianaVersion > $validatorVersion) { - printf( - 'TLDs must be updated, please run `php bin/update_hostname_validator.php` and push your changes%s', - PHP_EOL - ); - exit(1); -} - -if ($checkOnly) { - printf('TLDs are up-to-date%s', PHP_EOL); - exit(0); -} - -foreach (file(LAMINAS_HOSTNAME_VALIDATOR_FILE) as $line) { - // Replace old version number with new one - if (preg_match('/\*\s+IanaVersion\s+\d+/', $line, $matches)) { - $newFileContent[] = sprintf(" * IanaVersion %s\n", $ianaVersion); - continue; - } - - if ($insertDone === $insertFinish) { - // Outside of $validTlds definition; keep line as-is - $newFileContent[] = $line; - } - - if ($insertFinish) { - continue; - } - - if ($insertDone) { - // Detect where the $validTlds declaration ends - if (preg_match('/^\s+\];\s*$/', $line)) { - $newFileContent[] = $line; - $insertFinish = true; - } - - continue; - } - - // Detect where the $validTlds declaration begins - if (preg_match('/^\s+protected\s+\$validTlds\s+=\s+\[\s*$/', $line)) { - $newFileContent = array_merge($newFileContent, getNewValidTlds($response->getBody())); - $insertDone = true; - } -} - -if (! $insertDone) { - printf('Error: cannot find line with "protected $validTlds"%s', PHP_EOL); - exit(1); -} - -if (!$insertFinish) { - printf('Error: cannot find end of $validTlds declaration%s', PHP_EOL); - exit(1); -} - -if (false === @file_put_contents(LAMINAS_HOSTNAME_VALIDATOR_FILE, $newFileContent)) { - printf('Error: cannot write info file "%s"%s', LAMINAS_HOSTNAME_VALIDATOR_FILE, PHP_EOL); - exit(1); -} - -printf('Validator TLD file updated.%s', PHP_EOL); -exit(0); - -/** - * Get Official TLDs - * - * @return \Laminas\Http\Response - * @throws Exception - */ -function getOfficialTLDs() -{ - $client = new Client(); - $client->setOptions([ - 'adapter' => 'Laminas\Http\Client\Adapter\Curl', - ]); - $client->setUri(IANA_URL); - $client->setMethod('GET'); - - $response = $client->send(); - if (! $response->isSuccess()) { - throw new \Exception(sprintf("Error: cannot get '%s'%s", IANA_URL, PHP_EOL)); - } - return $response; -} - -/** - * Extract the first match of a string like - * "Version 2015072300" from the given string - * - * @param string $prefix - * @param string $string - * @return string - * @throws Exception - */ -function getVersionFromString($prefix, $string) -{ - $matches = []; - if (! preg_match(sprintf('/%s\s+((\d+)?)/', $prefix), $string, $matches)) { - throw new Exception('Error: cannot get last update date'); - } - - return $matches[1]; -} - -/** - * Extract new Valid TLDs from a string containing one per line. - * - * @param string $string - * @return list<string> - */ -function getNewValidTlds($string) -{ - $decodePunycode = getPunycodeDecoder(); - - // Get new TLDs from the list previously fetched - $newValidTlds = []; - foreach (preg_grep('/^[^#]/', preg_split("#\r?\n#", $string)) as $line) { - $newValidTlds []= sprintf( - "%s'%s',\n", - str_repeat(' ', 8), - $decodePunycode(strtolower($line)) - ); - } - - return $newValidTlds; -} - -/** - * Retrieve and return a punycode decoder. - * - * TLDs are puny encoded. - * - * We need a decodePunycode function to translate TLDs to UTF-8: - * - * - use idn_to_utf8 if available - * - otherwise, use Hostname::decodePunycode() - * - * @return callable - */ -function getPunycodeDecoder() -{ - if (function_exists('idn_to_utf8')) { - return function ($domain) { - return idn_to_utf8($domain, 0, INTL_IDNA_VARIANT_UTS46); - }; - } - - $hostnameValidator = new Hostname(); - $reflection = new ReflectionClass(get_class($hostnameValidator)); - $decodePunyCode = $reflection->getMethod('decodePunycode'); - $decodePunyCode->setAccessible(true); - - return function ($encode) use ($hostnameValidator, $decodePunyCode) { - if (strpos($encode, 'xn--') === 0) { - return $decodePunyCode->invokeArgs($hostnameValidator, [substr($encode, 4)]); - } - return $encode; - }; -} diff --git a/lib/laminas/laminas-validator/composer.json b/lib/laminas/laminas-validator/composer.json deleted file mode 100644 index 3c552aa81..000000000 --- a/lib/laminas/laminas-validator/composer.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "name": "laminas/laminas-validator", - "description": "Validation classes for a wide range of domains, and the ability to chain validators to create complex validation criteria", - "license": "BSD-3-Clause", - "keywords": [ - "laminas", - "validator" - ], - "homepage": "https://laminas.dev", - "support": { - "docs": "https://docs.laminas.dev/laminas-validator/", - "issues": "https://github.com/laminas/laminas-validator/issues", - "source": "https://github.com/laminas/laminas-validator", - "rss": "https://github.com/laminas/laminas-validator/releases.atom", - "chat": "https://laminas.dev/chat", - "forum": "https://discourse.laminas.dev" - }, - "config": { - "sort-packages": true, - "platform": { - "php": "7.4.99" - }, - "allow-plugins": { - "dealerdirect/phpcodesniffer-composer-installer": true - } - }, - "extra": { - "laminas": { - "component": "Laminas\\Validator", - "config-provider": "Laminas\\Validator\\ConfigProvider" - } - }, - "require": { - "php": "^7.4 || ~8.0.0 || ~8.1.0", - "laminas/laminas-servicemanager": "^3.12.0", - "laminas/laminas-stdlib": "^3.10" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~2.3.0", - "laminas/laminas-db": "^2.7", - "laminas/laminas-filter": "^2.14.0", - "laminas/laminas-http": "^2.14.2", - "laminas/laminas-i18n": "^2.15.0", - "laminas/laminas-session": "^2.12.1", - "laminas/laminas-uri": "^2.9.1", - "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^9.5.21", - "psalm/plugin-phpunit": "^0.17.0", - "psr/http-client": "^1.0", - "psr/http-factory": "^1.0", - "psr/http-message": "^1.0", - "vimeo/psalm": "^4.24.0" - }, - "suggest": { - "laminas/laminas-db": "Laminas\\Db component, required by the (No)RecordExists validator", - "laminas/laminas-filter": "Laminas\\Filter component, required by the Digits validator", - "laminas/laminas-i18n": "Laminas\\I18n component to allow translation of validation error messages", - "laminas/laminas-i18n-resources": "Translations of validator messages", - "laminas/laminas-servicemanager": "Laminas\\ServiceManager component to allow using the ValidatorPluginManager and validator chains", - "laminas/laminas-session": "Laminas\\Session component, ^2.8; required by the Csrf validator", - "laminas/laminas-uri": "Laminas\\Uri component, required by the Uri and Sitemap\\Loc validators", - "psr/http-message": "psr/http-message, required when validating PSR-7 UploadedFileInterface instances via the Upload and UploadFile validators" - }, - "autoload": { - "psr-4": { - "Laminas\\Validator\\": "src/" - } - }, - "autoload-dev": { - "files": [ - "test/autoload.php" - ], - "psr-4": { - "LaminasTest\\Validator\\": "test/" - } - }, - "scripts": { - "check": [ - "@cs-check", - "@test" - ], - "cs-check": "phpcs", - "cs-fix": "phpcbf", - "test": "phpunit --colors=always", - "test-coverage": "phpunit --colors=always --coverage-clover clover.xml", - "static-analysis": "psalm --shepherd --stats" - }, - "conflict": { - "zendframework/zend-validator": "*" - } -} diff --git a/lib/laminas/laminas-validator/composer.lock b/lib/laminas/laminas-validator/composer.lock deleted file mode 100644 index 88be7a9da..000000000 --- a/lib/laminas/laminas-validator/composer.lock +++ /dev/null @@ -1,5217 +0,0 @@ -{ - "_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": "12f30984a08a09a9f205c4d8f7cef8a7", - "packages": [ - { - "name": "laminas/laminas-servicemanager", - "version": "3.15.1", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-servicemanager.git", - "reference": "216f972b179191b14c33a79337947b63bf7808ff" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-servicemanager/zipball/216f972b179191b14c33a79337947b63bf7808ff", - "reference": "216f972b179191b14c33a79337947b63bf7808ff", - "shasum": "" - }, - "require": { - "laminas/laminas-stdlib": "^3.2.1", - "php": "~7.4.0 || ~8.0.0 || ~8.1.0", - "psr/container": "^1.0" - }, - "conflict": { - "ext-psr": "*", - "laminas/laminas-code": "<3.3.1", - "zendframework/zend-code": "<3.3.1", - "zendframework/zend-servicemanager": "*" - }, - "provide": { - "psr/container-implementation": "^1.0" - }, - "replace": { - "container-interop/container-interop": "^1.2.0" - }, - "require-dev": { - "composer/package-versions-deprecated": "^1.0", - "laminas/laminas-coding-standard": "~2.3.0", - "laminas/laminas-container-config-test": "^0.6", - "laminas/laminas-dependency-plugin": "^2.1.2", - "mikey179/vfsstream": "^1.6.10@alpha", - "ocramius/proxy-manager": "^2.11", - "phpbench/phpbench": "^1.1", - "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^9.5.5", - "psalm/plugin-phpunit": "^0.17.0", - "vimeo/psalm": "^4.8" - }, - "suggest": { - "ocramius/proxy-manager": "ProxyManager ^2.1.1 to handle lazy initialization of services" - }, - "bin": [ - "bin/generate-deps-for-config-factory", - "bin/generate-factory-for-class" - ], - "type": "library", - "autoload": { - "files": [ - "src/autoload.php" - ], - "psr-4": { - "Laminas\\ServiceManager\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Factory-Driven Dependency Injection Container", - "homepage": "https://laminas.dev", - "keywords": [ - "PSR-11", - "dependency-injection", - "di", - "dic", - "laminas", - "service-manager", - "servicemanager" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-servicemanager/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-servicemanager/issues", - "rss": "https://github.com/laminas/laminas-servicemanager/releases.atom", - "source": "https://github.com/laminas/laminas-servicemanager" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2022-07-20T09:48:45+00:00" - }, - { - "name": "laminas/laminas-stdlib", - "version": "3.10.1", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-stdlib.git", - "reference": "0d669074845fc80a99add0f64025192f143ef836" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/0d669074845fc80a99add0f64025192f143ef836", - "reference": "0d669074845fc80a99add0f64025192f143ef836", - "shasum": "" - }, - "require": { - "php": "^7.3 || ~8.0.0 || ~8.1.0" - }, - "conflict": { - "zendframework/zend-stdlib": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~2.3.0", - "phpbench/phpbench": "^1.0", - "phpunit/phpunit": "^9.3.7", - "psalm/plugin-phpunit": "^0.16.0", - "vimeo/psalm": "^4.7" - }, - "type": "library", - "autoload": { - "psr-4": { - "Laminas\\Stdlib\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "SPL extensions, array utilities, error handlers, and more", - "homepage": "https://laminas.dev", - "keywords": [ - "laminas", - "stdlib" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-stdlib/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-stdlib/issues", - "rss": "https://github.com/laminas/laminas-stdlib/releases.atom", - "source": "https://github.com/laminas/laminas-stdlib" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2022-06-10T14:49:09+00:00" - }, - { - "name": "psr/container", - "version": "1.1.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.2" - }, - "time": "2021-11-05T16:50:12+00:00" - } - ], - "packages-dev": [ - { - "name": "amphp/amp", - "version": "v2.6.2", - "source": { - "type": "git", - "url": "https://github.com/amphp/amp.git", - "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/amp/zipball/9d5100cebffa729aaffecd3ad25dc5aeea4f13bb", - "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1", - "ext-json": "*", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^7 | ^8 | ^9", - "psalm/phar": "^3.11@dev", - "react/promise": "^2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "files": [ - "lib/functions.php", - "lib/Internal/functions.php" - ], - "psr-4": { - "Amp\\": "lib" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Bob Weinand", - "email": "bobwei9@hotmail.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "A non-blocking concurrency framework for PHP applications.", - "homepage": "https://amphp.org/amp", - "keywords": [ - "async", - "asynchronous", - "awaitable", - "concurrency", - "event", - "event-loop", - "future", - "non-blocking", - "promise" - ], - "support": { - "irc": "irc://irc.freenode.org/amphp", - "issues": "https://github.com/amphp/amp/issues", - "source": "https://github.com/amphp/amp/tree/v2.6.2" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2022-02-20T17:52:18+00:00" - }, - { - "name": "amphp/byte-stream", - "version": "v1.8.1", - "source": { - "type": "git", - "url": "https://github.com/amphp/byte-stream.git", - "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/byte-stream/zipball/acbd8002b3536485c997c4e019206b3f10ca15bd", - "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd", - "shasum": "" - }, - "require": { - "amphp/amp": "^2", - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1.4", - "friendsofphp/php-cs-fixer": "^2.3", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^6 || ^7 || ^8", - "psalm/phar": "^3.11.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "files": [ - "lib/functions.php" - ], - "psr-4": { - "Amp\\ByteStream\\": "lib" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "A stream abstraction to make working with non-blocking I/O simple.", - "homepage": "http://amphp.org/byte-stream", - "keywords": [ - "amp", - "amphp", - "async", - "io", - "non-blocking", - "stream" - ], - "support": { - "irc": "irc://irc.freenode.org/amphp", - "issues": "https://github.com/amphp/byte-stream/issues", - "source": "https://github.com/amphp/byte-stream/tree/v1.8.1" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2021-03-30T17:13:30+00:00" - }, - { - "name": "composer/package-versions-deprecated", - "version": "1.11.99.5", - "source": { - "type": "git", - "url": "https://github.com/composer/package-versions-deprecated.git", - "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/b4f54f74ef3453349c24a845d22392cd31e65f1d", - "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.1.0 || ^2.0", - "php": "^7 || ^8" - }, - "replace": { - "ocramius/package-versions": "1.11.99" - }, - "require-dev": { - "composer/composer": "^1.9.3 || ^2.0@dev", - "ext-zip": "^1.13", - "phpunit/phpunit": "^6.5 || ^7" - }, - "type": "composer-plugin", - "extra": { - "class": "PackageVersions\\Installer", - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "PackageVersions\\": "src/PackageVersions" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be" - } - ], - "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", - "support": { - "issues": "https://github.com/composer/package-versions-deprecated/issues", - "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.5" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-01-17T14:14:24+00:00" - }, - { - "name": "composer/pcre", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/composer/pcre.git", - "reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/e300eb6c535192decd27a85bc72a9290f0d6b3bd", - "reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.3", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Pcre\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "PCRE wrapping library that offers type-safe preg_* replacements.", - "keywords": [ - "PCRE", - "preg", - "regex", - "regular expression" - ], - "support": { - "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.0.0" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-02-25T20:21:48+00:00" - }, - { - "name": "composer/semver", - "version": "3.3.2", - "source": { - "type": "git", - "url": "https://github.com/composer/semver.git", - "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9", - "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.4", - "symfony/phpunit-bridge": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Semver\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - }, - { - "name": "Rob Bast", - "email": "rob.bast@gmail.com", - "homepage": "http://robbast.nl" - } - ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", - "keywords": [ - "semantic", - "semver", - "validation", - "versioning" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.3.2" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-04-01T19:23:25+00:00" - }, - { - "name": "composer/xdebug-handler", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "ced299686f41dce890debac69273b47ffe98a40c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c", - "reference": "ced299686f41dce890debac69273b47ffe98a40c", - "shasum": "" - }, - "require": { - "composer/pcre": "^1 || ^2 || ^3", - "php": "^7.2.5 || ^8.0", - "psr/log": "^1 || ^2 || ^3" - }, - "require-dev": { - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without Xdebug.", - "keywords": [ - "Xdebug", - "performance" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/3.0.3" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-02-25T21:32:43+00:00" - }, - { - "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "v0.7.2", - "source": { - "type": "git", - "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", - "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", - "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.0 || ^2.0", - "php": ">=5.3", - "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" - }, - "require-dev": { - "composer/composer": "*", - "php-parallel-lint/php-parallel-lint": "^1.3.1", - "phpcompatibility/php-compatibility": "^9.0" - }, - "type": "composer-plugin", - "extra": { - "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" - }, - "autoload": { - "psr-4": { - "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Franck Nijhof", - "email": "franck.nijhof@dealerdirect.com", - "homepage": "http://www.frenck.nl", - "role": "Developer / IT Manager" - }, - { - "name": "Contributors", - "homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors" - } - ], - "description": "PHP_CodeSniffer Standards Composer Installer Plugin", - "homepage": "http://www.dealerdirect.com", - "keywords": [ - "PHPCodeSniffer", - "PHP_CodeSniffer", - "code quality", - "codesniffer", - "composer", - "installer", - "phpcbf", - "phpcs", - "plugin", - "qa", - "quality", - "standard", - "standards", - "style guide", - "stylecheck", - "tests" - ], - "support": { - "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues", - "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer" - }, - "time": "2022-02-04T12:51:07+00:00" - }, - { - "name": "dnoegel/php-xdg-base-dir", - "version": "v0.1.1", - "source": { - "type": "git", - "url": "https://github.com/dnoegel/php-xdg-base-dir.git", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "require-dev": { - "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" - }, - "type": "library", - "autoload": { - "psr-4": { - "XdgBaseDir\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "implementation of xdg base directory specification for php", - "support": { - "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", - "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" - }, - "time": "2019-12-04T15:06:13+00:00" - }, - { - "name": "doctrine/instantiator", - "version": "1.4.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^0.16 || ^1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.22" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.4.1" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" - } - ], - "time": "2022-03-03T08:28:38+00:00" - }, - { - "name": "felixfbecker/advanced-json-rpc", - "version": "v3.2.1", - "source": { - "type": "git", - "url": "https://github.com/felixfbecker/php-advanced-json-rpc.git", - "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447", - "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447", - "shasum": "" - }, - "require": { - "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "php": "^7.1 || ^8.0", - "phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0" - }, - "require-dev": { - "phpunit/phpunit": "^7.0 || ^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "AdvancedJsonRpc\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "ISC" - ], - "authors": [ - { - "name": "Felix Becker", - "email": "felix.b@outlook.com" - } - ], - "description": "A more advanced JSONRPC implementation", - "support": { - "issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues", - "source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.1" - }, - "time": "2021-06-11T22:34:44+00:00" - }, - { - "name": "felixfbecker/language-server-protocol", - "version": "v1.5.2", - "source": { - "type": "git", - "url": "https://github.com/felixfbecker/php-language-server-protocol.git", - "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/6e82196ffd7c62f7794d778ca52b69feec9f2842", - "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "phpstan/phpstan": "*", - "squizlabs/php_codesniffer": "^3.1", - "vimeo/psalm": "^4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "LanguageServerProtocol\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "ISC" - ], - "authors": [ - { - "name": "Felix Becker", - "email": "felix.b@outlook.com" - } - ], - "description": "PHP classes for the Language Server Protocol", - "keywords": [ - "language", - "microsoft", - "php", - "server" - ], - "support": { - "issues": "https://github.com/felixfbecker/php-language-server-protocol/issues", - "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.2" - }, - "time": "2022-03-02T22:36:06+00:00" - }, - { - "name": "laminas/laminas-coding-standard", - "version": "2.3.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-coding-standard.git", - "reference": "bcf6e07fe4690240be7beb6d884d0b0fafa6a251" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-coding-standard/zipball/bcf6e07fe4690240be7beb6d884d0b0fafa6a251", - "reference": "bcf6e07fe4690240be7beb6d884d0b0fafa6a251", - "shasum": "" - }, - "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.7", - "php": "^7.3 || ^8.0", - "slevomat/coding-standard": "^7.0", - "squizlabs/php_codesniffer": "^3.6", - "webimpress/coding-standard": "^1.2" - }, - "type": "phpcodesniffer-standard", - "autoload": { - "psr-4": { - "LaminasCodingStandard\\": "src/LaminasCodingStandard/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Laminas Coding Standard", - "homepage": "https://laminas.dev", - "keywords": [ - "Coding Standard", - "laminas" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-coding-standard/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-coding-standard/issues", - "rss": "https://github.com/laminas/laminas-coding-standard/releases.atom", - "source": "https://github.com/laminas/laminas-coding-standard" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2021-05-29T15:53:59+00:00" - }, - { - "name": "laminas/laminas-db", - "version": "2.15.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-db.git", - "reference": "1125ef2e55108bdfcc1f0030d3a0f9b895e09606" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-db/zipball/1125ef2e55108bdfcc1f0030d3a0f9b895e09606", - "reference": "1125ef2e55108bdfcc1f0030d3a0f9b895e09606", - "shasum": "" - }, - "require": { - "laminas/laminas-stdlib": "^3.7.1", - "php": "^7.3 || ~8.0.0 || ~8.1.0" - }, - "conflict": { - "zendframework/zend-db": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~2.2.1", - "laminas/laminas-eventmanager": "^3.4.0", - "laminas/laminas-hydrator": "^3.2 || ^4.3", - "laminas/laminas-servicemanager": "^3.7.0", - "phpunit/phpunit": "^9.5.19" - }, - "suggest": { - "laminas/laminas-eventmanager": "Laminas\\EventManager component", - "laminas/laminas-hydrator": "(^3.2 || ^4.3) Laminas\\Hydrator component for using HydratingResultSets", - "laminas/laminas-servicemanager": "Laminas\\ServiceManager component" - }, - "type": "library", - "extra": { - "laminas": { - "component": "Laminas\\Db", - "config-provider": "Laminas\\Db\\ConfigProvider" - } - }, - "autoload": { - "psr-4": { - "Laminas\\Db\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Database abstraction layer, SQL abstraction, result set abstraction, and RowDataGateway and TableDataGateway implementations", - "homepage": "https://laminas.dev", - "keywords": [ - "db", - "laminas" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-db/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-db/issues", - "rss": "https://github.com/laminas/laminas-db/releases.atom", - "source": "https://github.com/laminas/laminas-db" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2022-04-11T13:26:20+00:00" - }, - { - "name": "laminas/laminas-escaper", - "version": "2.10.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-escaper.git", - "reference": "58af67282db37d24e584a837a94ee55b9c7552be" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/58af67282db37d24e584a837a94ee55b9c7552be", - "reference": "58af67282db37d24e584a837a94ee55b9c7552be", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "ext-mbstring": "*", - "php": "^7.4 || ~8.0.0 || ~8.1.0" - }, - "conflict": { - "zendframework/zend-escaper": "*" - }, - "require-dev": { - "infection/infection": "^0.26.6", - "laminas/laminas-coding-standard": "~2.3.0", - "maglnet/composer-require-checker": "^3.8.0", - "phpunit/phpunit": "^9.5.18", - "psalm/plugin-phpunit": "^0.16.1", - "vimeo/psalm": "^4.22.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Laminas\\Escaper\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Securely and safely escape HTML, HTML attributes, JavaScript, CSS, and URLs", - "homepage": "https://laminas.dev", - "keywords": [ - "escaper", - "laminas" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-escaper/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-escaper/issues", - "rss": "https://github.com/laminas/laminas-escaper/releases.atom", - "source": "https://github.com/laminas/laminas-escaper" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2022-03-08T20:15:36+00:00" - }, - { - "name": "laminas/laminas-eventmanager", - "version": "3.5.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-eventmanager.git", - "reference": "41f7209428f37cab9573365e361f4078209aaafa" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-eventmanager/zipball/41f7209428f37cab9573365e361f4078209aaafa", - "reference": "41f7209428f37cab9573365e361f4078209aaafa", - "shasum": "" - }, - "require": { - "php": "^7.4 || ~8.0.0 || ~8.1.0" - }, - "conflict": { - "container-interop/container-interop": "<1.2", - "zendframework/zend-eventmanager": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~2.2.1", - "laminas/laminas-stdlib": "^3.6", - "phpbench/phpbench": "^1.1", - "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^9.5.5", - "psr/container": "^1.1.2 || ^2.0.2" - }, - "suggest": { - "laminas/laminas-stdlib": "^2.7.3 || ^3.0, to use the FilterChain feature", - "psr/container": "^1.1.2 || ^2.0.2, to use the lazy listeners feature" - }, - "type": "library", - "autoload": { - "psr-4": { - "Laminas\\EventManager\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Trigger and listen to events within a PHP application", - "homepage": "https://laminas.dev", - "keywords": [ - "event", - "eventmanager", - "events", - "laminas" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-eventmanager/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-eventmanager/issues", - "rss": "https://github.com/laminas/laminas-eventmanager/releases.atom", - "source": "https://github.com/laminas/laminas-eventmanager" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2022-04-06T21:05:17+00:00" - }, - { - "name": "laminas/laminas-filter", - "version": "2.17.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-filter.git", - "reference": "7c78483f22e118fbc98be41dc24b39e8c17cdcae" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-filter/zipball/7c78483f22e118fbc98be41dc24b39e8c17cdcae", - "reference": "7c78483f22e118fbc98be41dc24b39e8c17cdcae", - "shasum": "" - }, - "require": { - "laminas/laminas-servicemanager": "^3.14.0", - "laminas/laminas-stdlib": "^3.6.1", - "php": "^7.4 || ~8.0.0 || ~8.1.0" - }, - "conflict": { - "laminas/laminas-validator": "<2.10.1", - "zendframework/zend-filter": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "^2.3.0", - "laminas/laminas-crypt": "^3.5.1", - "laminas/laminas-uri": "^2.9.1", - "pear/archive_tar": "^1.4.14", - "phpspec/prophecy-phpunit": "^2.0.1", - "phpunit/phpunit": "^9.5.10", - "psalm/plugin-phpunit": "^0.17.0", - "psr/http-factory": "^1.0.1", - "vimeo/psalm": "^4.24.0" - }, - "suggest": { - "laminas/laminas-crypt": "Laminas\\Crypt component, for encryption filters", - "laminas/laminas-i18n": "Laminas\\I18n component for filters depending on i18n functionality", - "laminas/laminas-uri": "Laminas\\Uri component, for the UriNormalize filter", - "psr/http-factory-implementation": "psr/http-factory-implementation, for creating file upload instances when consuming PSR-7 in file upload filters" - }, - "type": "library", - "extra": { - "laminas": { - "component": "Laminas\\Filter", - "config-provider": "Laminas\\Filter\\ConfigProvider" - } - }, - "autoload": { - "psr-4": { - "Laminas\\Filter\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Programmatically filter and normalize data and files", - "homepage": "https://laminas.dev", - "keywords": [ - "filter", - "laminas" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-filter/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-filter/issues", - "rss": "https://github.com/laminas/laminas-filter/releases.atom", - "source": "https://github.com/laminas/laminas-filter" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2022-07-17T11:58:06+00:00" - }, - { - "name": "laminas/laminas-http", - "version": "2.15.1", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-http.git", - "reference": "261f079c3dffcf6f123484db43c40e44c4bf1c79" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-http/zipball/261f079c3dffcf6f123484db43c40e44c4bf1c79", - "reference": "261f079c3dffcf6f123484db43c40e44c4bf1c79", - "shasum": "" - }, - "require": { - "laminas/laminas-loader": "^2.8", - "laminas/laminas-stdlib": "^3.6", - "laminas/laminas-uri": "^2.9.1", - "laminas/laminas-validator": "^2.15", - "php": "^7.3 || ~8.0.0 || ~8.1.0" - }, - "conflict": { - "zendframework/zend-http": "*" - }, - "require-dev": { - "ext-curl": "*", - "laminas/laminas-coding-standard": "~2.2.1", - "phpunit/phpunit": "^9.5.5" - }, - "suggest": { - "paragonie/certainty": "For automated management of cacert.pem" - }, - "type": "library", - "autoload": { - "psr-4": { - "Laminas\\Http\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Provides an easy interface for performing Hyper-Text Transfer Protocol (HTTP) requests", - "homepage": "https://laminas.dev", - "keywords": [ - "http", - "http client", - "laminas" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-http/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-http/issues", - "rss": "https://github.com/laminas/laminas-http/releases.atom", - "source": "https://github.com/laminas/laminas-http" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2021-12-03T10:17:11+00:00" - }, - { - "name": "laminas/laminas-i18n", - "version": "2.16.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-i18n.git", - "reference": "e77c04c050b7744125d26e213b2639c86d4514ad" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-i18n/zipball/e77c04c050b7744125d26e213b2639c86d4514ad", - "reference": "e77c04c050b7744125d26e213b2639c86d4514ad", - "shasum": "" - }, - "require": { - "ext-intl": "*", - "laminas/laminas-servicemanager": "^3.14.0", - "laminas/laminas-stdlib": "^2.7 || ^3.0", - "php": "^7.4 || ~8.0.0 || ~8.1.0" - }, - "conflict": { - "laminas/laminas-view": "<2.20.0", - "phpspec/prophecy": "<1.9.0", - "zendframework/zend-i18n": "*" - }, - "require-dev": { - "laminas/laminas-cache": "^3.1.2", - "laminas/laminas-cache-storage-adapter-memory": "^2.0.0", - "laminas/laminas-cache-storage-deprecated-factory": "^1.0.0", - "laminas/laminas-coding-standard": "~2.3.0", - "laminas/laminas-config": "^3.4.0", - "laminas/laminas-eventmanager": "^3.5.0", - "laminas/laminas-filter": "^2.16.0", - "laminas/laminas-validator": "^2.17.0", - "laminas/laminas-view": "^2.21.0", - "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^9.5.21", - "psalm/plugin-phpunit": "^0.17.0", - "vimeo/psalm": "^4.24.0" - }, - "suggest": { - "laminas/laminas-cache": "You should install this package to cache the translations", - "laminas/laminas-config": "You should install this package to use the INI translation format", - "laminas/laminas-eventmanager": "You should install this package to use the events in the translator", - "laminas/laminas-filter": "You should install this package to use the provided filters", - "laminas/laminas-i18n-resources": "This package provides validator and captcha translations", - "laminas/laminas-servicemanager": "You should install this package to use the translator", - "laminas/laminas-validator": "You should install this package to use the provided validators", - "laminas/laminas-view": "You should install this package to use the provided view helpers" - }, - "type": "library", - "extra": { - "laminas": { - "component": "Laminas\\I18n", - "config-provider": "Laminas\\I18n\\ConfigProvider" - } - }, - "autoload": { - "psr-4": { - "Laminas\\I18n\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Provide translations for your application, and filter and validate internationalized values", - "homepage": "https://laminas.dev", - "keywords": [ - "i18n", - "laminas" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-i18n/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-i18n/issues", - "rss": "https://github.com/laminas/laminas-i18n/releases.atom", - "source": "https://github.com/laminas/laminas-i18n" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2022-07-12T22:15:49+00:00" - }, - { - "name": "laminas/laminas-loader", - "version": "2.8.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-loader.git", - "reference": "d0589ec9dd48365fd95ad10d1c906efd7711c16b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-loader/zipball/d0589ec9dd48365fd95ad10d1c906efd7711c16b", - "reference": "d0589ec9dd48365fd95ad10d1c906efd7711c16b", - "shasum": "" - }, - "require": { - "php": "^7.3 || ~8.0.0 || ~8.1.0" - }, - "conflict": { - "zendframework/zend-loader": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~2.2.1", - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Laminas\\Loader\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Autoloading and plugin loading strategies", - "homepage": "https://laminas.dev", - "keywords": [ - "laminas", - "loader" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-loader/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-loader/issues", - "rss": "https://github.com/laminas/laminas-loader/releases.atom", - "source": "https://github.com/laminas/laminas-loader" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2021-09-02T18:30:53+00:00" - }, - { - "name": "laminas/laminas-session", - "version": "2.13.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-session.git", - "reference": "9f8a6077dd22b3b253583b1be84ddd5bf6fa1ef4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-session/zipball/9f8a6077dd22b3b253583b1be84ddd5bf6fa1ef4", - "reference": "9f8a6077dd22b3b253583b1be84ddd5bf6fa1ef4", - "shasum": "" - }, - "require": { - "laminas/laminas-eventmanager": "^3.5", - "laminas/laminas-servicemanager": "^3.15.1", - "laminas/laminas-stdlib": "^3.10.1", - "php": "^7.4 || ~8.0.0 || ~8.1.0" - }, - "conflict": { - "zendframework/zend-session": "*" - }, - "require-dev": { - "laminas/laminas-cache": "^3.1.3", - "laminas/laminas-cache-storage-adapter-memory": "^2.0.0", - "laminas/laminas-coding-standard": "~2.3.0", - "laminas/laminas-db": "^2.13.4", - "laminas/laminas-http": "^2.15", - "laminas/laminas-validator": "^2.15", - "mongodb/mongodb": "~1.12.0", - "php-mock/php-mock-phpunit": "^1.1.2 || ^2.0", - "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^9.5.9", - "psalm/plugin-phpunit": "^0.17.0", - "vimeo/psalm": "^4.24.0" - }, - "suggest": { - "laminas/laminas-cache": "Laminas\\Cache component", - "laminas/laminas-db": "Laminas\\Db component", - "laminas/laminas-http": "Laminas\\Http component", - "laminas/laminas-servicemanager": "Laminas\\ServiceManager component", - "laminas/laminas-validator": "Laminas\\Validator component", - "mongodb/mongodb": "If you want to use the MongoDB session save handler" - }, - "type": "library", - "extra": { - "laminas": { - "component": "Laminas\\Session", - "config-provider": "Laminas\\Session\\ConfigProvider" - } - }, - "autoload": { - "psr-4": { - "Laminas\\Session\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Object-oriented interface to PHP sessions and storage", - "homepage": "https://laminas.dev", - "keywords": [ - "laminas", - "session" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-session/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-session/issues", - "rss": "https://github.com/laminas/laminas-session/releases.atom", - "source": "https://github.com/laminas/laminas-session" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2022-07-22T10:26:33+00:00" - }, - { - "name": "laminas/laminas-uri", - "version": "2.9.1", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-uri.git", - "reference": "7e837dc15c8fd3949df7d1213246fd7c8640032b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-uri/zipball/7e837dc15c8fd3949df7d1213246fd7c8640032b", - "reference": "7e837dc15c8fd3949df7d1213246fd7c8640032b", - "shasum": "" - }, - "require": { - "laminas/laminas-escaper": "^2.9", - "laminas/laminas-validator": "^2.15", - "php": "^7.3 || ~8.0.0 || ~8.1.0" - }, - "conflict": { - "zendframework/zend-uri": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~2.2.1", - "phpunit/phpunit": "^9.5.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Laminas\\Uri\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "A component that aids in manipulating and validating » Uniform Resource Identifiers (URIs)", - "homepage": "https://laminas.dev", - "keywords": [ - "laminas", - "uri" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-uri/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-uri/issues", - "rss": "https://github.com/laminas/laminas-uri/releases.atom", - "source": "https://github.com/laminas/laminas-uri" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2021-09-09T18:37:15+00:00" - }, - { - "name": "myclabs/deep-copy", - "version": "1.11.0", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" - }, - "require-dev": { - "doctrine/collections": "^1.6.8", - "doctrine/common": "^2.13.3 || ^3.2.2", - "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" - }, - "type": "library", - "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2022-03-03T13:19:32+00:00" - }, - { - "name": "netresearch/jsonmapper", - "version": "v4.0.0", - "source": { - "type": "git", - "url": "https://github.com/cweiske/jsonmapper.git", - "reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d", - "reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=7.1" - }, - "require-dev": { - "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0", - "squizlabs/php_codesniffer": "~3.5" - }, - "type": "library", - "autoload": { - "psr-0": { - "JsonMapper": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "OSL-3.0" - ], - "authors": [ - { - "name": "Christian Weiske", - "email": "cweiske@cweiske.de", - "homepage": "http://github.com/cweiske/jsonmapper/", - "role": "Developer" - } - ], - "description": "Map nested JSON structures onto PHP classes", - "support": { - "email": "cweiske@cweiske.de", - "issues": "https://github.com/cweiske/jsonmapper/issues", - "source": "https://github.com/cweiske/jsonmapper/tree/v4.0.0" - }, - "time": "2020-12-01T19:48:11+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v4.14.0", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/34bea19b6e03d8153165d8f30bba4c3be86184c1", - "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=7.0" - }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.9-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.14.0" - }, - "time": "2022-05-31T20:59:12+00:00" - }, - { - "name": "openlss/lib-array2xml", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/nullivex/lib-array2xml.git", - "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nullivex/lib-array2xml/zipball/a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", - "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "type": "library", - "autoload": { - "psr-0": { - "LSS": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Bryan Tong", - "email": "bryan@nullivex.com", - "homepage": "https://www.nullivex.com" - }, - { - "name": "Tony Butler", - "email": "spudz76@gmail.com", - "homepage": "https://www.nullivex.com" - } - ], - "description": "Array2XML conversion library credit to lalit.org", - "homepage": "https://www.nullivex.com", - "keywords": [ - "array", - "array conversion", - "xml", - "xml conversion" - ], - "support": { - "issues": "https://github.com/nullivex/lib-array2xml/issues", - "source": "https://github.com/nullivex/lib-array2xml/tree/master" - }, - "time": "2019-03-29T20:06:56+00:00" - }, - { - "name": "phar-io/manifest", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.3" - }, - "time": "2021-07-20T11:28:43+00:00" - }, - { - "name": "phar-io/version", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.2.1" - }, - "time": "2022-02-21T01:04:05+00:00" - }, - { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" - }, - "time": "2020-06-27T09:03:43+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "5.3.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", - "shasum": "" - }, - "require": { - "ext-filter": "*", - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", - "webmozart/assert": "^1.9.1" - }, - "require-dev": { - "mockery/mockery": "~1.3.2", - "psalm/phar": "^4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - }, - { - "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" - }, - "time": "2021-10-19T17:43:47+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.6.1", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "77a32518733312af16a44300404e945338981de3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3", - "reference": "77a32518733312af16a44300404e945338981de3", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.0" - }, - "require-dev": { - "ext-tokenizer": "*", - "psalm/phar": "^4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1" - }, - "time": "2022-03-15T21:29:03+00:00" - }, - { - "name": "phpspec/prophecy", - "version": "v1.15.0", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/bbcd7380b0ebf3961ee21409db7b38bc31d69a13", - "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.2", - "php": "^7.2 || ~8.0, <8.2", - "phpdocumentor/reflection-docblock": "^5.2", - "sebastian/comparator": "^3.0 || ^4.0", - "sebastian/recursion-context": "^3.0 || ^4.0" - }, - "require-dev": { - "phpspec/phpspec": "^6.0 || ^7.0", - "phpunit/phpunit": "^8.0 || ^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Prophecy\\": "src/Prophecy" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" - } - ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "support": { - "issues": "https://github.com/phpspec/prophecy/issues", - "source": "https://github.com/phpspec/prophecy/tree/v1.15.0" - }, - "time": "2021-12-08T12:19:24+00:00" - }, - { - "name": "phpspec/prophecy-phpunit", - "version": "v2.0.1", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy-phpunit.git", - "reference": "2d7a9df55f257d2cba9b1d0c0963a54960657177" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy-phpunit/zipball/2d7a9df55f257d2cba9b1d0c0963a54960657177", - "reference": "2d7a9df55f257d2cba9b1d0c0963a54960657177", - "shasum": "" - }, - "require": { - "php": "^7.3 || ^8", - "phpspec/prophecy": "^1.3", - "phpunit/phpunit": "^9.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "psr-4": { - "Prophecy\\PhpUnit\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christophe Coevoet", - "email": "stof@notk.org" - } - ], - "description": "Integrating the Prophecy mocking library in PHPUnit test cases", - "homepage": "http://phpspec.net", - "keywords": [ - "phpunit", - "prophecy" - ], - "support": { - "issues": "https://github.com/phpspec/prophecy-phpunit/issues", - "source": "https://github.com/phpspec/prophecy-phpunit/tree/v2.0.1" - }, - "time": "2020-07-09T08:33:42+00:00" - }, - { - "name": "phpstan/phpdoc-parser", - "version": "1.6.4", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "135607f9ccc297d6923d49c2bcf309f509413215" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/135607f9ccc297d6923d49c2bcf309f509413215", - "reference": "135607f9ccc297d6923d49c2bcf309f509413215", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^1.5", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^9.5", - "symfony/process": "^5.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "PHPStan\\PhpDocParser\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPDoc parser with support for nullable, intersection and generic types", - "support": { - "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.6.4" - }, - "time": "2022-06-26T13:09:08+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "9.2.15", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2e9da11878c4202f97915c1cb4bb1ca318a63f5f", - "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^4.13.0", - "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.3", - "phpunit/php-text-template": "^2.0.2", - "sebastian/code-unit-reverse-lookup": "^2.0.2", - "sebastian/complexity": "^2.0", - "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0.3", - "sebastian/version": "^3.0.1", - "theseer/tokenizer": "^1.2.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcov": "*", - "ext-xdebug": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.15" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-03-07T09:28:20+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "3.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-12-02T12:48:52+00:00" - }, - { - "name": "phpunit/php-invoker", - "version": "3.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:58:55+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T05:33:50+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "5.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:16:10+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "9.5.21", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "0e32b76be457de00e83213528f6bb37e2a38fcb1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0e32b76be457de00e83213528f6bb37e2a38fcb1", - "reference": "0e32b76be457de00e83213528f6bb37e2a38fcb1", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.3.1", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", - "php": ">=7.3", - "phpspec/prophecy": "^1.12.1", - "phpunit/php-code-coverage": "^9.2.13", - "phpunit/php-file-iterator": "^3.0.5", - "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.5", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.3", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.0", - "sebastian/version": "^3.0.2" - }, - "require-dev": { - "phpspec/prophecy-phpunit": "^2.0.1" - }, - "suggest": { - "ext-soap": "*", - "ext-xdebug": "*" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.5-dev" - } - }, - "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.21" - }, - "funding": [ - { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-06-19T12:14:25+00:00" - }, - { - "name": "psalm/plugin-phpunit", - "version": "0.17.0", - "source": { - "type": "git", - "url": "https://github.com/psalm/psalm-plugin-phpunit.git", - "reference": "45951541beef07e93e3ad197daf01da88e85c31d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/psalm/psalm-plugin-phpunit/zipball/45951541beef07e93e3ad197daf01da88e85c31d", - "reference": "45951541beef07e93e3ad197daf01da88e85c31d", - "shasum": "" - }, - "require": { - "composer/package-versions-deprecated": "^1.10", - "composer/semver": "^1.4 || ^2.0 || ^3.0", - "ext-simplexml": "*", - "php": "^7.1 || ^8.0", - "vimeo/psalm": "dev-master || dev-4.x || ^4.5" - }, - "conflict": { - "phpunit/phpunit": "<7.5" - }, - "require-dev": { - "codeception/codeception": "^4.0.3", - "php": "^7.3 || ^8.0", - "phpunit/phpunit": "^7.5 || ^8.0 || ^9.0", - "squizlabs/php_codesniffer": "^3.3.1", - "weirdan/codeception-psalm-module": "^0.11.0", - "weirdan/prophecy-shim": "^1.0 || ^2.0" - }, - "type": "psalm-plugin", - "extra": { - "psalm": { - "pluginClass": "Psalm\\PhpUnitPlugin\\Plugin" - } - }, - "autoload": { - "psr-4": { - "Psalm\\PhpUnitPlugin\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Matt Brown", - "email": "github@muglug.com" - } - ], - "description": "Psalm plugin for PHPUnit", - "support": { - "issues": "https://github.com/psalm/psalm-plugin-phpunit/issues", - "source": "https://github.com/psalm/psalm-plugin-phpunit/tree/0.17.0" - }, - "time": "2022-06-14T17:05:57+00:00" - }, - { - "name": "psr/http-client", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-client.git", - "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", - "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", - "shasum": "" - }, - "require": { - "php": "^7.0 || ^8.0", - "psr/http-message": "^1.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": "http://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP clients", - "homepage": "https://github.com/php-fig/http-client", - "keywords": [ - "http", - "http-client", - "psr", - "psr-18" - ], - "support": { - "source": "https://github.com/php-fig/http-client/tree/master" - }, - "time": "2020-06-29T06:28:15+00:00" - }, - { - "name": "psr/http-factory", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-factory.git", - "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", - "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", - "shasum": "" - }, - "require": { - "php": ">=7.0.0", - "psr/http-message": "^1.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": "http://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/master" - }, - "time": "2019-04-30T12:38:16+00:00" - }, - { - "name": "psr/http-message", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "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": "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/master" - }, - "time": "2016-08-06T14:39:51+00:00" - }, - { - "name": "psr/log", - "version": "1.1.4", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "support": { - "source": "https://github.com/php-fig/log/tree/1.1.4" - }, - "time": "2021-05-03T11:20:27+00:00" - }, - { - "name": "sebastian/cli-parser", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", - "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:08:49+00:00" - }, - { - "name": "sebastian/code-unit", - "version": "1.0.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:08:54+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:30:19+00:00" - }, - { - "name": "sebastian/comparator", - "version": "4.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T15:49:45+00:00" - }, - { - "name": "sebastian/complexity", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.7", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", - "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T15:52:27+00:00" - }, - { - "name": "sebastian/diff", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/process": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:10:38+00:00" - }, - { - "name": "sebastian/environment", - "version": "5.1.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-posix": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-04-03T09:37:03+00:00" - }, - { - "name": "sebastian/exporter", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/65e8b7db476c5dd267e65eea9cab77584d3cfff9", - "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-11-11T14:18:36+00:00" - }, - { - "name": "sebastian/global-state", - "version": "5.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-02-14T08:28:10+00:00" - }, - { - "name": "sebastian/lines-of-code", - "version": "1.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.6", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", - "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-28T06:42:11+00:00" - }, - { - "name": "sebastian/object-enumerator", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:12:34+00:00" - }, - { - "name": "sebastian/object-reflector", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:14:26+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:17:30+00:00" - }, - { - "name": "sebastian/resource-operations", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:45:17+00:00" - }, - { - "name": "sebastian/type", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b233b84bc4465aff7b57cf1c4bc75c86d00d6dad", - "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", - "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-03-15T09:54:48+00:00" - }, - { - "name": "sebastian/version", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:39:44+00:00" - }, - { - "name": "slevomat/coding-standard", - "version": "7.2.1", - "source": { - "type": "git", - "url": "https://github.com/slevomat/coding-standard.git", - "reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/aff06ae7a84e4534bf6f821dc982a93a5d477c90", - "reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90", - "shasum": "" - }, - "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7", - "php": "^7.2 || ^8.0", - "phpstan/phpdoc-parser": "^1.5.1", - "squizlabs/php_codesniffer": "^3.6.2" - }, - "require-dev": { - "phing/phing": "2.17.3", - "php-parallel-lint/php-parallel-lint": "1.3.2", - "phpstan/phpstan": "1.4.10|1.7.1", - "phpstan/phpstan-deprecation-rules": "1.0.0", - "phpstan/phpstan-phpunit": "1.0.0|1.1.1", - "phpstan/phpstan-strict-rules": "1.2.3", - "phpunit/phpunit": "7.5.20|8.5.21|9.5.20" - }, - "type": "phpcodesniffer-standard", - "extra": { - "branch-alias": { - "dev-master": "7.x-dev" - } - }, - "autoload": { - "psr-4": { - "SlevomatCodingStandard\\": "SlevomatCodingStandard" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", - "support": { - "issues": "https://github.com/slevomat/coding-standard/issues", - "source": "https://github.com/slevomat/coding-standard/tree/7.2.1" - }, - "funding": [ - { - "url": "https://github.com/kukulich", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard", - "type": "tidelift" - } - ], - "time": "2022-05-25T10:58:12+00:00" - }, - { - "name": "squizlabs/php_codesniffer", - "version": "3.7.1", - "source": { - "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619", - "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" - }, - "bin": [ - "bin/phpcs", - "bin/phpcbf" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Greg Sherwood", - "role": "lead" - } - ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", - "keywords": [ - "phpcs", - "standards" - ], - "support": { - "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", - "source": "https://github.com/squizlabs/PHP_CodeSniffer", - "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" - }, - "time": "2022-06-18T07:21:10+00:00" - }, - { - "name": "symfony/console", - "version": "v5.4.10", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "4d671ab4ddac94ee439ea73649c69d9d200b5000" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/4d671ab4ddac94ee439ea73649c69d9d200b5000", - "reference": "4d671ab4ddac94ee439ea73649c69d9d200b5000", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.1|^6.0" - }, - "conflict": { - "psr/log": ">=3", - "symfony/dependency-injection": "<4.4", - "symfony/dotenv": "<5.1", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" - }, - "provide": { - "psr/log-implementation": "1.0|2.0" - }, - "require-dev": { - "psr/log": "^1|^2", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/lock": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Eases the creation of beautiful and testable command line interfaces", - "homepage": "https://symfony.com", - "keywords": [ - "cli", - "command line", - "console", - "terminal" - ], - "support": { - "source": "https://github.com/symfony/console/tree/v5.4.10" - }, - "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-06-26T13:00:04+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "v2.5.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-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/v2.5.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-01-02T09:53:40+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", - "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-ctype": "*" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-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.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "433d05519ce6990bf3530fba6957499d327395c2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2", - "reference": "433d05519ce6990bf3530fba6957499d327395c2", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's grapheme_* functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "grapheme", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "219aa369ceff116e673852dce47c3a41794c14bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd", - "reference": "219aa369ceff116e673852dce47c3a41794c14bd", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-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.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", - "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-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.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-php73", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/e440d35fa0286f77fb45b79a03fedbeda9307e85", - "reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-php80", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace", - "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-10T07:21:04+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v2.5.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1|^3" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "suggest": { - "symfony/service-implementation": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-30T19:17:29+00:00" - }, - { - "name": "symfony/string", - "version": "v5.4.10", - "source": { - "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "4432bc7df82a554b3e413a8570ce2fea90e94097" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/4432bc7df82a554b3e413a8570ce2fea90e94097", - "reference": "4432bc7df82a554b3e413a8570ce2fea90e94097", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "~1.15" - }, - "conflict": { - "symfony/translation-contracts": ">=3.0" - }, - "require-dev": { - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/translation-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0|^6.0" - }, - "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/v5.4.10" - }, - "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-06-26T15:57:47+00:00" - }, - { - "name": "theseer/tokenizer", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.1" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2021-07-28T10:34:58+00:00" - }, - { - "name": "vimeo/psalm", - "version": "4.24.0", - "source": { - "type": "git", - "url": "https://github.com/vimeo/psalm.git", - "reference": "06dd975cb55d36af80f242561738f16c5f58264f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/06dd975cb55d36af80f242561738f16c5f58264f", - "reference": "06dd975cb55d36af80f242561738f16c5f58264f", - "shasum": "" - }, - "require": { - "amphp/amp": "^2.4.2", - "amphp/byte-stream": "^1.5", - "composer/package-versions-deprecated": "^1.8.0", - "composer/semver": "^1.4 || ^2.0 || ^3.0", - "composer/xdebug-handler": "^1.1 || ^2.0 || ^3.0", - "dnoegel/php-xdg-base-dir": "^0.1.1", - "ext-ctype": "*", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-simplexml": "*", - "ext-tokenizer": "*", - "felixfbecker/advanced-json-rpc": "^3.0.3", - "felixfbecker/language-server-protocol": "^1.5", - "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "nikic/php-parser": "^4.13", - "openlss/lib-array2xml": "^1.0", - "php": "^7.1|^8", - "sebastian/diff": "^3.0 || ^4.0", - "symfony/console": "^3.4.17 || ^4.1.6 || ^5.0 || ^6.0", - "symfony/polyfill-php80": "^1.25", - "webmozart/path-util": "^2.3" - }, - "provide": { - "psalm/psalm": "self.version" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.2", - "brianium/paratest": "^4.0||^6.0", - "ext-curl": "*", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpdocumentor/reflection-docblock": "^5", - "phpmyadmin/sql-parser": "5.1.0||dev-master", - "phpspec/prophecy": ">=1.9.0", - "phpunit/phpunit": "^9.0", - "psalm/plugin-phpunit": "^0.16", - "slevomat/coding-standard": "^7.0", - "squizlabs/php_codesniffer": "^3.5", - "symfony/process": "^4.3 || ^5.0 || ^6.0", - "weirdan/prophecy-shim": "^1.0 || ^2.0" - }, - "suggest": { - "ext-curl": "In order to send data to shepherd", - "ext-igbinary": "^2.0.5 is required, used to serialize caching data" - }, - "bin": [ - "psalm", - "psalm-language-server", - "psalm-plugin", - "psalm-refactor", - "psalter" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.x-dev", - "dev-3.x": "3.x-dev", - "dev-2.x": "2.x-dev", - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "files": [ - "src/functions.php", - "src/spl_object_id.php" - ], - "psr-4": { - "Psalm\\": "src/Psalm/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Matthew Brown" - } - ], - "description": "A static analysis tool for finding errors in PHP applications", - "keywords": [ - "code", - "inspection", - "php" - ], - "support": { - "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm/tree/4.24.0" - }, - "time": "2022-06-26T11:47:54+00:00" - }, - { - "name": "webimpress/coding-standard", - "version": "1.2.4", - "source": { - "type": "git", - "url": "https://github.com/webimpress/coding-standard.git", - "reference": "cd0c4b0b97440c337c1f7da17b524674ca2f9ca9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webimpress/coding-standard/zipball/cd0c4b0b97440c337c1f7da17b524674ca2f9ca9", - "reference": "cd0c4b0b97440c337c1f7da17b524674ca2f9ca9", - "shasum": "" - }, - "require": { - "php": "^7.3 || ^8.0", - "squizlabs/php_codesniffer": "^3.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^9.5.13" - }, - "type": "phpcodesniffer-standard", - "extra": { - "dev-master": "1.2.x-dev", - "dev-develop": "1.3.x-dev" - }, - "autoload": { - "psr-4": { - "WebimpressCodingStandard\\": "src/WebimpressCodingStandard/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "description": "Webimpress Coding Standard", - "keywords": [ - "Coding Standard", - "PSR-2", - "phpcs", - "psr-12", - "webimpress" - ], - "support": { - "issues": "https://github.com/webimpress/coding-standard/issues", - "source": "https://github.com/webimpress/coding-standard/tree/1.2.4" - }, - "funding": [ - { - "url": "https://github.com/michalbundyra", - "type": "github" - } - ], - "time": "2022-02-15T19:52:12+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": "" - }, - "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": "webmozart/path-util", - "version": "2.3.0", - "source": { - "type": "git", - "url": "https://github.com/webmozart/path-util.git", - "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725", - "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "webmozart/assert": "~1.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\PathUtil\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.", - "support": { - "issues": "https://github.com/webmozart/path-util/issues", - "source": "https://github.com/webmozart/path-util/tree/2.3.0" - }, - "abandoned": "symfony/filesystem", - "time": "2015-12-17T08:42:14+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": "^7.4 || ~8.0.0 || ~8.1.0" - }, - "platform-dev": [], - "platform-overrides": { - "php": "7.4.99" - }, - "plugin-api-version": "2.3.0" -} diff --git a/lib/laminas/laminas-validator/renovate.json b/lib/laminas/laminas-validator/renovate.json deleted file mode 100644 index 060b1d1a2..000000000 --- a/lib/laminas/laminas-validator/renovate.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": [ - "local>laminas/.github:renovate-config" - ] -} diff --git a/lib/laminas/laminas-validator/src/AbstractValidator.php b/lib/laminas/laminas-validator/src/AbstractValidator.php deleted file mode 100644 index d7f3ccd3c..000000000 --- a/lib/laminas/laminas-validator/src/AbstractValidator.php +++ /dev/null @@ -1,623 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use Laminas\Stdlib\ArrayUtils; -use Traversable; - -use function array_key_exists; -use function array_keys; -use function array_unique; -use function current; -use function get_class; -use function implode; -use function is_array; -use function is_object; -use function is_string; -use function key; -use function method_exists; -use function str_repeat; -use function str_replace; -use function strlen; -use function substr; -use function ucfirst; -use function var_export; - -use const SORT_REGULAR; - -/** - * @psalm-type AbstractOptions = array{ - * messages: array<string, string>, - * messageTemplates: array<string, string>, - * messageVariables: array<string, mixed>, - * translator: Translator\TranslatorInterface|null, - * translatorTextDomain: string|null, - * translatorEnabled: bool, - * valueObscured: bool, - * } - * @property array<string, mixed> $options - * @property array<string, string> $messageTemplates - * @property array<string, mixed> $messageVariables - */ -abstract class AbstractValidator implements - Translator\TranslatorAwareInterface, - ValidatorInterface -{ - /** - * The value to be validated - * - * @var mixed - */ - protected $value; - - /** - * Default translation object for all validate objects - * - * @var Translator\TranslatorInterface - */ - protected static $defaultTranslator; - - /** - * Default text domain to be used with translator - * - * @var string - */ - protected static $defaultTranslatorTextDomain = 'default'; - - /** - * Limits the maximum returned length of an error message - * - * @var int - */ - protected static $messageLength = -1; - - /** @var AbstractOptions&array<string, mixed> */ - protected $abstractOptions = [ - 'messages' => [], // Array of validation failure messages - 'messageTemplates' => [], // Array of validation failure message templates - 'messageVariables' => [], // Array of additional variables available for validation failure messages - 'translator' => null, // Translation object to used -> Translator\TranslatorInterface - 'translatorTextDomain' => null, // Translation text domain - 'translatorEnabled' => true, // Is translation enabled? - 'valueObscured' => false, // Flag indicating whether value should be obfuscated in error messages - ]; - - /** - * Abstract constructor for all validators - * A validator should accept following parameters: - * - nothing f.e. Validator() - * - one or multiple scalar values f.e. Validator($first, $second, $third) - * - an array f.e. Validator(array($first => 'first', $second => 'second', $third => 'third')) - * - an instance of Traversable f.e. Validator($config_instance) - * - * @param array<string, mixed>|Traversable<string, mixed> $options - */ - public function __construct($options = null) - { - // The abstract constructor allows no scalar values - if ($options instanceof Traversable) { - $options = ArrayUtils::iteratorToArray($options); - } - - /** @psalm-suppress RedundantConditionGivenDocblockType */ - if (isset($this->messageTemplates) && is_array($this->messageTemplates)) { - $this->abstractOptions['messageTemplates'] = $this->messageTemplates; - } - - /** @psalm-suppress RedundantConditionGivenDocblockType */ - if (isset($this->messageVariables) && is_array($this->messageVariables)) { - $this->abstractOptions['messageVariables'] = $this->messageVariables; - } - - if (is_array($options)) { - $this->setOptions($options); - } - } - - /** - * Returns an option - * - * @param string $option Option to be returned - * @return mixed Returned option - * @throws Exception\InvalidArgumentException - */ - public function getOption($option) - { - if (array_key_exists($option, $this->abstractOptions)) { - return $this->abstractOptions[$option]; - } - - /** @psalm-suppress RedundantConditionGivenDocblockType */ - if (isset($this->options) && array_key_exists($option, $this->options)) { - return $this->options[$option]; - } - - throw new Exception\InvalidArgumentException("Invalid option '$option'"); - } - - /** - * Returns all available options - * - * @return array<string, mixed> Array with all available options - */ - public function getOptions() - { - $result = $this->abstractOptions; - /** @psalm-suppress RedundantConditionGivenDocblockType */ - if (isset($this->options) && is_array($this->options)) { - $result += $this->options; - } - return $result; - } - - /** - * Sets one or multiple options - * - * @param array<string, mixed>|Traversable<string, mixed> $options Options to set - * @return $this Provides fluid interface - * @throws Exception\InvalidArgumentException If $options is not an array or Traversable. - */ - public function setOptions($options = []) - { - /** @psalm-suppress DocblockTypeContradiction */ - if (! is_array($options) && ! $options instanceof Traversable) { - throw new Exception\InvalidArgumentException(__METHOD__ . ' expects an array or Traversable'); - } - - /** - * @psalm-suppress RedundantConditionGivenDocblockType - * @psalm-var mixed $option - */ - foreach ($options as $name => $option) { - $fname = 'set' . ucfirst($name); - $fname2 = 'is' . ucfirst($name); - if (($name !== 'setOptions') && method_exists($this, $name)) { - $this->{$name}($option); - } elseif (($fname !== 'setOptions') && method_exists($this, $fname)) { - $this->{$fname}($option); - } elseif (method_exists($this, $fname2)) { - $this->{$fname2}($option); - } elseif (isset($this->options) && is_array($this->options)) { - $this->options[$name] = $option; - } else { - $this->abstractOptions[$name] = $option; - } - } - - return $this; - } - - /** - * Returns array of validation failure messages - * - * @return array<string, string> - */ - public function getMessages() - { - return array_unique($this->abstractOptions['messages'], SORT_REGULAR); - } - - /** - * Invoke as command - * - * @param mixed $value - * @return bool - */ - public function __invoke($value) - { - return $this->isValid($value); - } - - /** - * Returns an array of the names of variables that are used in constructing validation failure messages - * - * @return list<string> - */ - public function getMessageVariables() - { - return array_keys($this->abstractOptions['messageVariables']); - } - - /** - * Returns the message templates from the validator - * - * @return array<string, string> - */ - public function getMessageTemplates() - { - return $this->abstractOptions['messageTemplates']; - } - - /** - * Sets the validation failure message template for a particular key - * - * @param string $messageString - * @param string|null $messageKey OPTIONAL - * @return $this Provides a fluent interface - * @throws Exception\InvalidArgumentException - */ - public function setMessage($messageString, $messageKey = null) - { - if ($messageKey === null) { - $keys = array_keys($this->abstractOptions['messageTemplates']); - foreach ($keys as $key) { - $this->setMessage($messageString, $key); - } - return $this; - } - - if (! isset($this->abstractOptions['messageTemplates'][$messageKey])) { - throw new Exception\InvalidArgumentException("No message template exists for key '$messageKey'"); - } - - $this->abstractOptions['messageTemplates'][$messageKey] = $messageString; - return $this; - } - - /** - * Sets validation failure message templates given as an array, where the array keys are the message keys, - * and the array values are the message template strings. - * - * @param array<string, string> $messages - * @return $this - */ - public function setMessages(array $messages) - { - foreach ($messages as $key => $message) { - $this->setMessage($message, $key); - } - return $this; - } - - /** - * Magic function returns the value of the requested property, if and only if it is the value or a - * message variable. - * - * @param string $property - * @return mixed - * @throws Exception\InvalidArgumentException - */ - public function __get($property) - { - if ($property === 'value') { - return $this->value; - } - - if (array_key_exists($property, $this->abstractOptions['messageVariables'])) { - /** @psalm-var mixed $result */ - $result = $this->abstractOptions['messageVariables'][$property]; - if (is_array($result)) { - return $this->{key($result)}[current($result)]; - } - return $this->{$result}; - } - - /** @psalm-suppress RedundantConditionGivenDocblockType */ - if (isset($this->messageVariables) && array_key_exists($property, $this->messageVariables)) { - /** @psalm-var mixed $result */ - $result = $this->{$this->messageVariables[$property]}; - if (is_array($result)) { - return $this->{key($result)}[current($result)]; - } - return $this->{$result}; - } - - throw new Exception\InvalidArgumentException("No property exists by the name '$property'"); - } - - /** - * Constructs and returns a validation failure message with the given message key and value. - * - * Returns null if and only if $messageKey does not correspond to an existing template. - * - * If a translator is available and a translation exists for $messageKey, - * the translation will be used. - * - * @param string $messageKey - * @param string|array|object $value - * @return null|string - */ - protected function createMessage($messageKey, $value) - { - if (! isset($this->abstractOptions['messageTemplates'][$messageKey])) { - return null; - } - - $message = $this->abstractOptions['messageTemplates'][$messageKey]; - - $message = $this->translateMessage($messageKey, $message); - - if (is_object($value)) { - $value = method_exists($value, '__toString') - ? (string) $value - : get_class($value) . ' object'; - } elseif (is_array($value)) { - $value = var_export($value, true); - } else { - /** @psalm-suppress RedundantCastGivenDocblockType $value */ - $value = (string) $value; - } - - if ($this->isValueObscured()) { - $value = str_repeat('*', strlen($value)); - } - - $message = str_replace('%value%', $value, $message); - foreach ($this->abstractOptions['messageVariables'] as $ident => $property) { - if (is_array($property)) { - $value = $this->{key($property)}[current($property)]; - if (is_array($value)) { - $value = '[' . implode(', ', $value) . ']'; - } - } else { - $value = $this->$property; - } - $message = str_replace("%$ident%", (string) $value, $message); - } - - $length = self::getMessageLength(); - if (($length > -1) && (strlen($message) > $length)) { - $message = substr($message, 0, $length - 3) . '...'; - } - - return $message; - } - - /** - * @param string|null $messageKey - * @param null|string|array|object $value OPTIONAL - * @return void - */ - protected function error($messageKey, $value = null) - { - if ($messageKey === null) { - $keys = array_keys($this->abstractOptions['messageTemplates']); - $messageKey = current($keys); - } - - if ($value === null) { - /** @psalm-var string|array|object $value */ - $value = $this->value; - } - - $message = $this->createMessage($messageKey, $value); - if (! is_string($message)) { - return; - } - - $this->abstractOptions['messages'][$messageKey] = $message; - } - - /** - * Returns the validation value - * - * @return mixed Value to be validated - */ - protected function getValue() - { - return $this->value; - } - - /** - * Sets the value to be validated and clears the messages and errors arrays - * - * @param mixed $value - * @return void - */ - protected function setValue($value) - { - $this->value = $value; - $this->abstractOptions['messages'] = []; - } - - /** - * Set flag indicating whether or not value should be obfuscated in messages - * - * @param bool $flag - * @return $this - */ - public function setValueObscured($flag) - { - /** @psalm-suppress RedundantCastGivenDocblockType */ - $this->abstractOptions['valueObscured'] = (bool) $flag; - return $this; - } - - /** - * Retrieve flag indicating whether or not value should be obfuscated in - * messages - * - * @return bool - */ - public function isValueObscured() - { - return $this->abstractOptions['valueObscured']; - } - - /** - * Set translation object - * - * @param string $textDomain (optional) - * @return $this - * @throws Exception\InvalidArgumentException - */ - public function setTranslator(?Translator\TranslatorInterface $translator = null, $textDomain = null) - { - $this->abstractOptions['translator'] = $translator; - if (null !== $textDomain) { - $this->setTranslatorTextDomain($textDomain); - } - return $this; - } - - /** - * Return translation object - * - * @return Translator\TranslatorInterface|null - */ - public function getTranslator() - { - if (! $this->isTranslatorEnabled()) { - return null; - } - - if (null === $this->abstractOptions['translator']) { - $this->abstractOptions['translator'] = self::getDefaultTranslator(); - } - - return $this->abstractOptions['translator']; - } - - /** - * Does this validator have its own specific translator? - * - * @return bool - */ - public function hasTranslator() - { - return (bool) $this->abstractOptions['translator']; - } - - /** - * Set translation text domain - * - * @param string $textDomain - * @return $this - */ - public function setTranslatorTextDomain($textDomain = 'default') - { - $this->abstractOptions['translatorTextDomain'] = $textDomain; - return $this; - } - - /** - * Return the translation text domain - * - * @return string - */ - public function getTranslatorTextDomain() - { - if (null === $this->abstractOptions['translatorTextDomain']) { - $this->abstractOptions['translatorTextDomain'] = - self::getDefaultTranslatorTextDomain(); - } - return $this->abstractOptions['translatorTextDomain']; - } - - /** - * Set default translation object for all validate objects - * - * @param string $textDomain (optional) - * @return void - * @throws Exception\InvalidArgumentException - */ - public static function setDefaultTranslator(?Translator\TranslatorInterface $translator = null, $textDomain = null) - { - static::$defaultTranslator = $translator; - if (null !== $textDomain) { - self::setDefaultTranslatorTextDomain($textDomain); - } - } - - /** - * Get default translation object for all validate objects - * - * @return Translator\TranslatorInterface|null - */ - public static function getDefaultTranslator() - { - return static::$defaultTranslator; - } - - /** - * Is there a default translation object set? - * - * @return bool - */ - public static function hasDefaultTranslator() - { - return (bool) static::$defaultTranslator; - } - - /** - * Set default translation text domain for all validate objects - * - * @param string $textDomain - * @return void - */ - public static function setDefaultTranslatorTextDomain($textDomain = 'default') - { - static::$defaultTranslatorTextDomain = $textDomain; - } - - /** - * Get default translation text domain for all validate objects - * - * @return string - */ - public static function getDefaultTranslatorTextDomain() - { - return static::$defaultTranslatorTextDomain; - } - - /** - * Indicate whether or not translation should be enabled - * - * @param bool $enabled - * @return $this - */ - public function setTranslatorEnabled($enabled = true) - { - /** @psalm-suppress RedundantCastGivenDocblockType */ - $this->abstractOptions['translatorEnabled'] = (bool) $enabled; - return $this; - } - - /** - * Is translation enabled? - * - * @return bool - */ - public function isTranslatorEnabled() - { - return $this->abstractOptions['translatorEnabled']; - } - - /** - * Returns the maximum allowed message length - * - * @return int - */ - public static function getMessageLength() - { - return static::$messageLength; - } - - /** - * Sets the maximum allowed message length - * - * @param int $length - * @return void - */ - public static function setMessageLength($length = -1) - { - static::$messageLength = $length; - } - - /** - * Translate a validation message - * - * @param string $messageKey - * @param string $message - * @return string - */ - protected function translateMessage($messageKey, $message) - { - $translator = $this->getTranslator(); - if (! $translator) { - return $message; - } - - return $translator->translate($message, $this->getTranslatorTextDomain()); - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode.php b/lib/laminas/laminas-validator/src/Barcode.php deleted file mode 100644 index 7ba7589af..000000000 --- a/lib/laminas/laminas-validator/src/Barcode.php +++ /dev/null @@ -1,199 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use Traversable; - -use function array_key_exists; -use function class_exists; -use function get_class; -use function gettype; -use function is_array; -use function is_object; -use function is_string; -use function property_exists; -use function sprintf; -use function strtolower; -use function substr; -use function ucfirst; - -class Barcode extends AbstractValidator -{ - public const INVALID = 'barcodeInvalid'; - public const FAILED = 'barcodeFailed'; - public const INVALID_CHARS = 'barcodeInvalidChars'; - public const INVALID_LENGTH = 'barcodeInvalidLength'; - - /** @var array<string, string> */ - protected $messageTemplates = [ - self::FAILED => 'The input failed checksum validation', - self::INVALID_CHARS => 'The input contains invalid characters', - self::INVALID_LENGTH => 'The input should have a length of %length% characters', - self::INVALID => 'Invalid type given. String expected', - ]; - - /** - * Additional variables available for validation failure messages - * - * @var array<string, array<string, string>> - */ - protected $messageVariables = [ - 'length' => ['options' => 'length'], - ]; - - /** @var array<string, mixed> */ - protected $options = [ - 'adapter' => null, // Barcode adapter Laminas\Validator\Barcode\AbstractAdapter - 'options' => null, // Options for this adapter - 'length' => null, - 'useChecksum' => null, - ]; - - /** - * Constructor for barcodes - * - * @param array|string $options Options to use - */ - public function __construct($options = null) - { - if ($options === null) { - $options = []; - } - - if (is_array($options)) { - if (array_key_exists('options', $options)) { - $options['options'] = ['options' => $options['options']]; - } - } elseif ($options instanceof Traversable) { - if (property_exists($options, 'options')) { - $options['options'] = ['options' => $options['options']]; - } - } else { - $options = ['adapter' => $options]; - } - - parent::__construct($options); - } - - /** - * Returns the set adapter - * - * @return Barcode\AbstractAdapter - */ - public function getAdapter() - { - if (! $this->options['adapter'] instanceof Barcode\AdapterInterface) { - $this->setAdapter('Ean13'); - } - - return $this->options['adapter']; - } - - /** - * Sets a new barcode adapter - * - * @param string|Barcode\AbstractAdapter $adapter Barcode adapter to use - * @param array $options Options for this adapter - * @return $this - * @throws Exception\InvalidArgumentException - */ - public function setAdapter($adapter, $options = null) - { - if (is_string($adapter)) { - $adapter = ucfirst(strtolower($adapter)); - $adapter = 'Laminas\\Validator\\Barcode\\' . $adapter; - - if (! class_exists($adapter)) { - throw new Exception\InvalidArgumentException('Barcode adapter matching "' . $adapter . '" not found'); - } - - $adapter = new $adapter($options); - } - - if (! $adapter instanceof Barcode\AdapterInterface) { - throw new Exception\InvalidArgumentException( - sprintf( - 'Adapter %s does not implement Laminas\\Validator\\Barcode\\AdapterInterface', - is_object($adapter) ? get_class($adapter) : gettype($adapter) - ) - ); - } - - $this->options['adapter'] = $adapter; - - return $this; - } - - /** - * Returns the checksum option - * - * @return string - */ - public function getChecksum() - { - return $this->getAdapter()->getChecksum(); - } - - /** - * Sets if checksum should be validated, if no value is given the actual setting is returned - * - * @param null|bool $checksum - * @return Barcode\AbstractAdapter|bool - */ - public function useChecksum($checksum = null) - { - return $this->getAdapter()->useChecksum($checksum); - } - - /** - * Defined by Laminas\Validator\ValidatorInterface - * - * Returns true if and only if $value contains a valid barcode - * - * @param string $value - * @return bool - */ - public function isValid($value) - { - if (! is_string($value)) { - $this->error(self::INVALID); - return false; - } - - $this->setValue($value); - $adapter = $this->getAdapter(); - $this->options['length'] = $adapter->getLength(); - $result = $adapter->hasValidLength($value); - if (! $result) { - if (is_array($this->options['length'])) { - $temp = $this->options['length']; - $this->options['length'] = ''; - foreach ($temp as $length) { - $this->options['length'] .= '/'; - $this->options['length'] .= $length; - } - - $this->options['length'] = substr($this->options['length'], 1); - } - - $this->error(self::INVALID_LENGTH); - return false; - } - - $result = $adapter->hasValidCharacters($value); - if (! $result) { - $this->error(self::INVALID_CHARS); - return false; - } - - if ($this->useChecksum(null)) { - $result = $adapter->hasValidChecksum($value); - if (! $result) { - $this->error(self::FAILED); - return false; - } - } - - return true; - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/AbstractAdapter.php b/lib/laminas/laminas-validator/src/Barcode/AbstractAdapter.php deleted file mode 100644 index 56a0164d0..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/AbstractAdapter.php +++ /dev/null @@ -1,312 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -use function chr; -use function is_array; -use function is_string; -use function method_exists; -use function str_replace; -use function str_split; -use function strlen; -use function substr; - -abstract class AbstractAdapter implements AdapterInterface -{ - /** - * Allowed options for this adapter - * - * @var array - */ - protected $options = [ - 'length' => null, // Allowed barcode lengths, integer, array, string - 'characters' => null, // Allowed barcode characters - 'checksum' => null, // Callback to checksum function - 'useChecksum' => true, // Is a checksum value included?, boolean - ]; - - /** - * Checks the length of a barcode - * - * @param string $value The barcode to check for proper length - * @return bool - */ - public function hasValidLength($value) - { - if (! is_string($value)) { - return false; - } - - $fixum = strlen($value); - $length = $this->getLength(); - - if (is_array($length)) { - foreach ($length as $value) { - if ($fixum === $value) { - return true; - } - - if ($value === -1) { - return true; - } - } - - return false; - } - - if ($fixum === $length) { - return true; - } - - if ($length === -1) { - return true; - } - - if ($length === 'even') { - $count = $fixum % 2; - return 0 === $count; - } - - if ($length === 'odd') { - $count = $fixum % 2; - return 1 === $count; - } - - return false; - } - - /** - * Checks for allowed characters within the barcode - * - * @param string $value The barcode to check for allowed characters - * @return bool - */ - public function hasValidCharacters($value) - { - if (! is_string($value)) { - return false; - } - - $characters = $this->getCharacters(); - if ($characters === 128) { - for ($x = 0; $x < 128; ++$x) { - $value = str_replace(chr($x), '', $value); - } - } else { - $chars = str_split($characters); - foreach ($chars as $char) { - $value = str_replace($char, '', $value); - } - } - - if (strlen($value) > 0) { - return false; - } - - return true; - } - - /** - * Validates the checksum - * - * @param string $value The barcode to check the checksum for - * @return bool - */ - public function hasValidChecksum($value) - { - $checksum = $this->getChecksum(); - if (! empty($checksum)) { - if (method_exists($this, $checksum)) { - return $this->$checksum($value); - } - } - - return false; - } - - /** - * Returns the allowed barcode length - * - * @return int|array - */ - public function getLength() - { - return $this->options['length']; - } - - /** - * Returns the allowed characters - * - * @return int|string|array - */ - public function getCharacters() - { - return $this->options['characters']; - } - - /** - * Returns the checksum function name - * - * @return string - */ - public function getChecksum() - { - return $this->options['checksum']; - } - - /** - * Sets the checksum validation method - * - * @param callable $checksum Checksum method to call - * @return $this - */ - protected function setChecksum($checksum) - { - $this->options['checksum'] = $checksum; - return $this; - } - - /** - * Sets the checksum validation, if no value is given, the actual setting is returned - * - * @param bool $check - * @return AbstractAdapter|bool - */ - public function useChecksum($check = null) - { - if ($check === null) { - return $this->options['useChecksum']; - } - - $this->options['useChecksum'] = (bool) $check; - return $this; - } - - /** - * Sets the length of this barcode - * - * @param int|array $length - * @return $this - */ - protected function setLength($length) - { - $this->options['length'] = $length; - return $this; - } - - /** - * Sets the allowed characters of this barcode - * - * @param int $characters - * @return $this - */ - protected function setCharacters($characters) - { - $this->options['characters'] = $characters; - return $this; - } - - /** - * Validates the checksum (Modulo 10) - * GTIN implementation factor 3 - * - * @param string $value The barcode to validate - * @return bool - */ - protected function gtin($value) - { - $barcode = substr($value, 0, -1); - $sum = 0; - $length = strlen($barcode) - 1; - - for ($i = 0; $i <= $length; $i++) { - if (($i % 2) === 0) { - $sum += $barcode[$length - $i] * 3; - } else { - $sum += $barcode[$length - $i]; - } - } - - $calc = $sum % 10; - $checksum = $calc === 0 ? 0 : 10 - $calc; - - return $value[$length + 1] === (string) $checksum; - } - - /** - * Validates the checksum (Modulo 10) - * IDENTCODE implementation factors 9 and 4 - * - * @param string $value The barcode to validate - * @return bool - */ - protected function identcode($value) - { - $barcode = substr($value, 0, -1); - $sum = 0; - $length = strlen($value) - 2; - - for ($i = 0; $i <= $length; $i++) { - if (($i % 2) === 0) { - $sum += $barcode[$length - $i] * 4; - } else { - $sum += $barcode[$length - $i] * 9; - } - } - - $calc = $sum % 10; - $checksum = $calc === 0 ? 0 : 10 - $calc; - - return $value[$length + 1] === (string) $checksum; - } - - /** - * Validates the checksum (Modulo 10) - * CODE25 implementation factor 3 - * - * @param string $value The barcode to validate - * @return bool - */ - protected function code25($value) - { - $barcode = substr($value, 0, -1); - $sum = 0; - $length = strlen($barcode) - 1; - - for ($i = 0; $i <= $length; $i++) { - if (($i % 2) === 0) { - $sum += $barcode[$i] * 3; - } else { - $sum += $barcode[$i]; - } - } - - $calc = $sum % 10; - $checksum = $calc === 0 ? 0 : 10 - $calc; - - return $value[$length + 1] === (string) $checksum; - } - - /** - * Validates the checksum () - * POSTNET implementation - * - * @param string $value The barcode to validate - * @return bool - */ - protected function postnet($value) - { - $checksum = substr($value, -1, 1); - $values = str_split(substr($value, 0, -1)); - - $check = 0; - foreach ($values as $row) { - $check += $row; - } - - $check %= 10; - $check = 10 - $check; - - return (string) $check === $checksum; - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/AdapterInterface.php b/lib/laminas/laminas-validator/src/Barcode/AdapterInterface.php deleted file mode 100644 index 5ccab6103..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/AdapterInterface.php +++ /dev/null @@ -1,59 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -interface AdapterInterface -{ - /** - * Checks the length of a barcode - * - * @param string $value The barcode to check for proper length - * @return bool - */ - public function hasValidLength($value); - - /** - * Checks for allowed characters within the barcode - * - * @param string $value The barcode to check for allowed characters - * @return bool - */ - public function hasValidCharacters($value); - - /** - * Validates the checksum - * - * @param string $value The barcode to check the checksum for - * @return bool - */ - public function hasValidChecksum($value); - - /** - * Returns the allowed barcode length - * - * @return int|array - */ - public function getLength(); - - /** - * Returns the allowed characters - * - * @return int|string|array - */ - public function getCharacters(); - - /** - * Returns if barcode uses a checksum - * - * @return bool|int|string - */ - public function getChecksum(); - - /** - * Sets the checksum validation, if no value is given, the actual setting is returned - * - * @param bool $check - * @return AbstractAdapter|bool - */ - public function useChecksum($check = null); -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Codabar.php b/lib/laminas/laminas-validator/src/Barcode/Codabar.php deleted file mode 100644 index 1b4321665..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Codabar.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -use function strpbrk; -use function substr; - -class Codabar extends AbstractAdapter -{ - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength(-1); - $this->setCharacters('0123456789-$:/.+ABCDTN*E'); - $this->useChecksum(false); - } - - /** - * Checks for allowed characters - * - * @see Laminas\Validator\Barcode.AbstractAdapter::checkChars() - * - * @param string $value - * @return bool - */ - public function hasValidCharacters($value) - { - if (strpbrk($value, 'ABCD')) { - $first = $value[0]; - if (! strpbrk($first, 'ABCD')) { - // Missing start char - return false; - } - - $last = substr($value, -1, 1); - if (! strpbrk($last, 'ABCD')) { - // Missing stop char - return false; - } - - $value = substr($value, 1, -1); - } elseif (strpbrk($value, 'TN*E')) { - $first = $value[0]; - if (! strpbrk($first, 'TN*E')) { - // Missing start char - return false; - } - - $last = substr($value, -1, 1); - if (! strpbrk($last, 'TN*E')) { - // Missing stop char - return false; - } - - $value = substr($value, 1, -1); - } - - $chars = $this->getCharacters(); - $this->setCharacters('0123456789-$:/.+'); - $result = parent::hasValidCharacters($value); - $this->setCharacters($chars); - return $result; - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Code128.php b/lib/laminas/laminas-validator/src/Barcode/Code128.php deleted file mode 100644 index 44d7a537f..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Code128.php +++ /dev/null @@ -1,739 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -use Laminas\Stdlib\StringUtils; -use Laminas\Stdlib\StringWrapper\StringWrapperInterface; -use Laminas\Validator\Exception; - -use function chr; -use function is_string; -use function ord; - -class Code128 extends AbstractAdapter -{ - /** - * The used string wrapper used for basic UTF-8 string functions - * - * @var StringWrapperInterface - */ - protected $utf8StringWrapper; - - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength(-1); - $this->setCharacters([ - 'A' => [ - 0 => ' ', - 1 => '!', - 2 => '"', - 3 => '#', - 4 => '$', - 5 => '%', - 6 => '&', - 7 => "'", - 8 => '(', - 9 => ')', - 10 => '*', - 11 => '+', - 12 => ',', - 13 => '-', - 14 => '.', - 15 => '/', - 16 => '0', - 17 => '1', - 18 => '2', - 19 => '3', - 20 => '4', - 21 => '5', - 22 => '6', - 23 => '7', - 24 => '8', - 25 => '9', - 26 => ':', - 27 => ';', - 28 => '<', - 29 => '=', - 30 => '>', - 31 => '?', - 32 => '@', - 33 => 'A', - 34 => 'B', - 35 => 'C', - 36 => 'D', - 37 => 'E', - 38 => 'F', - 39 => 'G', - 40 => 'H', - 41 => 'I', - 42 => 'J', - 43 => 'K', - 44 => 'L', - 45 => 'M', - 46 => 'N', - 47 => 'O', - 48 => 'P', - 49 => 'Q', - 50 => 'R', - 51 => 'S', - 52 => 'T', - 53 => 'U', - 54 => 'V', - 55 => 'W', - 56 => 'X', - 57 => 'Y', - 58 => 'Z', - 59 => '[', - 60 => '\\', - 61 => ']', - 62 => '^', - 63 => '_', - 64 => 0x00, - 65 => 0x01, - 66 => 0x02, - 67 => 0x03, - 68 => 0x04, - 69 => 0x05, - 70 => 0x06, - 71 => 0x07, - 72 => 0x08, - 73 => 0x09, - 74 => 0x0A, - 75 => 0x0B, - 76 => 0x0C, - 77 => 0x0D, - 78 => 0x0E, - 79 => 0x0F, - 80 => 0x10, - 81 => 0x11, - 82 => 0x12, - 83 => 0x13, - 84 => 0x14, - 85 => 0x15, - 86 => 0x16, - 87 => 0x17, - 88 => 0x18, - 89 => 0x19, - 90 => 0x1A, - 91 => 0x1B, - 92 => 0x1C, - 93 => 0x1D, - 94 => 0x1E, - 95 => 0x1F, - 96 => 'Ç', - 97 => 'ü', - 98 => 'é', - 99 => 'â', - 100 => 'ä', - 101 => 'à', - 102 => 'å', - 103 => '‡', - 104 => 'ˆ', - 105 => '‰', - 106 => 'Š', - ], - 'B' => [ - 0 => ' ', - 1 => '!', - 2 => '"', - 3 => '#', - 4 => '$', - 5 => '%', - 6 => '&', - 7 => "'", - 8 => '(', - 9 => ')', - 10 => '*', - 11 => '+', - 12 => ',', - 13 => '-', - 14 => '.', - 15 => '/', - 16 => '0', - 17 => '1', - 18 => '2', - 19 => '3', - 20 => '4', - 21 => '5', - 22 => '6', - 23 => '7', - 24 => '8', - 25 => '9', - 26 => ':', - 27 => ';', - 28 => '<', - 29 => '=', - 30 => '>', - 31 => '?', - 32 => '@', - 33 => 'A', - 34 => 'B', - 35 => 'C', - 36 => 'D', - 37 => 'E', - 38 => 'F', - 39 => 'G', - 40 => 'H', - 41 => 'I', - 42 => 'J', - 43 => 'K', - 44 => 'L', - 45 => 'M', - 46 => 'N', - 47 => 'O', - 48 => 'P', - 49 => 'Q', - 50 => 'R', - 51 => 'S', - 52 => 'T', - 53 => 'U', - 54 => 'V', - 55 => 'W', - 56 => 'X', - 57 => 'Y', - 58 => 'Z', - 59 => '[', - 60 => '\\', - 61 => ']', - 62 => '^', - 63 => '_', - 64 => '`', - 65 => 'a', - 66 => 'b', - 67 => 'c', - 68 => 'd', - 69 => 'e', - 70 => 'f', - 71 => 'g', - 72 => 'h', - 73 => 'i', - 74 => 'j', - 75 => 'k', - 76 => 'l', - 77 => 'm', - 78 => 'n', - 79 => 'o', - 80 => 'p', - 81 => 'q', - 82 => 'r', - 83 => 's', - 84 => 't', - 85 => 'u', - 86 => 'v', - 87 => 'w', - 88 => 'x', - 89 => 'y', - 90 => 'z', - 91 => '{', - 92 => '|', - 93 => '}', - 94 => '~', - 95 => 0x7F, - 96 => 'Ç', - 97 => 'ü', - 98 => 'é', - 99 => 'â', - 100 => 'ä', - 101 => 'à', - 102 => 'å', - 103 => '‡', - 104 => 'ˆ', - 105 => '‰', - 106 => 'Š', - ], - 'C' => [ - 0 => '00', - 1 => '01', - 2 => '02', - 3 => '03', - 4 => '04', - 5 => '05', - 6 => '06', - 7 => '07', - 8 => '08', - 9 => '09', - 10 => '10', - 11 => '11', - 12 => '12', - 13 => '13', - 14 => '14', - 15 => '15', - 16 => '16', - 17 => '17', - 18 => '18', - 19 => '19', - 20 => '20', - 21 => '21', - 22 => '22', - 23 => '23', - 24 => '24', - 25 => '25', - 26 => '26', - 27 => '27', - 28 => '28', - 29 => '29', - 30 => '30', - 31 => '31', - 32 => '32', - 33 => '33', - 34 => '34', - 35 => '35', - 36 => '36', - 37 => '37', - 38 => '38', - 39 => '39', - 40 => '40', - 41 => '41', - 42 => '42', - 43 => '43', - 44 => '44', - 45 => '45', - 46 => '46', - 47 => '47', - 48 => '48', - 49 => '49', - 50 => '50', - 51 => '51', - 52 => '52', - 53 => '53', - 54 => '54', - 55 => '55', - 56 => '56', - 57 => '57', - 58 => '58', - 59 => '59', - 60 => '60', - 61 => '61', - 62 => '62', - 63 => '63', - 64 => '64', - 65 => '65', - 66 => '66', - 67 => '67', - 68 => '68', - 69 => '69', - 70 => '70', - 71 => '71', - 72 => '72', - 73 => '73', - 74 => '74', - 75 => '75', - 76 => '76', - 77 => '77', - 78 => '78', - 79 => '79', - 80 => '80', - 81 => '81', - 82 => '82', - 83 => '83', - 84 => '84', - 85 => '85', - 86 => '86', - 87 => '87', - 88 => '88', - 89 => '89', - 90 => '90', - 91 => '91', - 92 => '92', - 93 => '93', - 94 => '94', - 95 => '95', - 96 => '96', - 97 => '97', - 98 => '98', - 99 => '99', - 100 => 'ä', - 101 => 'à', - 102 => 'å', - 103 => '‡', - 104 => 'ˆ', - 105 => '‰', - 106 => 'Š', - ], - ]); - $this->setChecksum('code128'); - } - - /** - * @return void - */ - public function setUtf8StringWrapper(StringWrapperInterface $utf8StringWrapper) - { - if (! $utf8StringWrapper->isSupported('UTF-8')) { - throw new Exception\InvalidArgumentException( - 'The string wrapper needs to support UTF-8 character encoding' - ); - } - $this->utf8StringWrapper = $utf8StringWrapper; - } - - /** - * Get the string wrapper supporting UTF-8 character encoding - * - * @return StringWrapperInterface - */ - public function getUtf8StringWrapper() - { - if (! $this->utf8StringWrapper) { - $this->utf8StringWrapper = StringUtils::getWrapper('UTF-8'); - } - return $this->utf8StringWrapper; - } - - /** - * Checks for allowed characters within the barcode - * - * @param string $value The barcode to check for allowed characters - * @return bool - */ - public function hasValidCharacters($value) - { - if (! is_string($value)) { - return false; - } - - // get used string wrapper for UTF-8 character encoding - $strWrapper = $this->getUtf8StringWrapper(); - - // detect starting charset - $set = $this->getCodingSet($value); - $read = $set; - if ($set !== '') { - $value = $strWrapper->substr($value, 1, null); - } - - // process barcode - while ($value !== '' && $value !== false) { - $char = $strWrapper->substr($value, 0, 1); - - switch ($char) { - // Function definition - case 'Ç': - case 'ü': - case 'å': - break; - - // Switch 1 char between A and B - case 'é': - if ($set === 'A') { - $read = 'B'; - break; - } - - if ($set === 'B') { - $read = 'A'; - break; - } - - break; - - // Switch to C - case 'â': - $set = 'C'; - $read = 'C'; - break; - - // Switch to B - case 'ä': - $set = 'B'; - $read = 'B'; - break; - - // Switch to A - case 'à': - $set = 'A'; - $read = 'A'; - break; - - // Doubled start character - case '‡': - case 'ˆ': - case '‰': - return false; - - // Chars after the stop character - case 'Š': - break 2; - - default: - // Does the char exist within the charset to read? - if ($this->ord128($char, $read) === -1) { - return false; - } - - break; - } - - $value = $strWrapper->substr($value, 1, null); - $read = $set; - } - - if ($value !== '' && is_string($value) && $strWrapper->strlen($value) !== 1) { - return false; - } - - return true; - } - - /** - * Validates the checksum () - * - * @param string $value The barcode to validate - * @return bool - */ - protected function code128($value) - { - $sum = 0; - $pos = 1; - $set = $this->getCodingSet($value); - $read = $set; - $usecheck = $this->useChecksum(null); - $strWrapper = $this->getUtf8StringWrapper(); - $char = $strWrapper->substr($value, 0, 1); - if ($char === '‡') { - $sum = 103; - } elseif ($char === 'ˆ') { - $sum = 104; - } elseif ($char === '‰') { - $sum = 105; - } elseif ($usecheck === true) { - // no start value, unable to detect a proper checksum - return false; - } - - $value = $strWrapper->substr($value, 1, null); - while ($strWrapper->strpos($value, 'Š') || ($value !== '')) { - $char = $strWrapper->substr($value, 0, 1); - if ($read === 'C') { - $char = $strWrapper->substr($value, 0, 2); - } - - switch ($char) { - // Function definition - case 'Ç': - case 'ü': - case 'å': - $sum += $pos * $this->ord128($char, $set); - break; - - case 'é': - $sum += $pos * $this->ord128($char, $set); - - if ($set === 'A') { - $read = 'B'; - break; - } - - if ($set === 'B') { - $read = 'A'; - break; - } - - break; - - // Switch to C - case 'â': - $sum += $pos * $this->ord128($char, $set); - $set = 'C'; - $read = 'C'; - break; - - // Switch to B - case 'ä': - $sum += $pos * $this->ord128($char, $set); - $set = 'B'; - $read = 'B'; - break; - - // Switch to A - case 'à': - $sum += $pos * $this->ord128($char, $set); - $set = 'A'; - $read = 'A'; - break; - - case '‡': - case 'ˆ': - case '‰': - return false; - - default: - // Does the char exist within the charset to read? - if ($this->ord128($char, $read) === -1) { - return false; - } - - $sum += $pos * $this->ord128($char, $set); - break; - } - - $value = $strWrapper->substr($value, 1); - ++$pos; - if (($strWrapper->strpos($value, 'Š') === 1) && ($strWrapper->strlen($value) === 2)) { - // break by stop and checksum char - break; - } - $read = $set; - } - - if (($strWrapper->strpos($value, 'Š') !== 1) || ($strWrapper->strlen($value) !== 2)) { - // return false if checksum is not readable and true if no startvalue is detected - return ! $usecheck; - } - - $mod = $sum % 103; - if ($strWrapper->substr($value, 0, 1) === $this->chr128($mod, $set)) { - return true; - } - - return false; - } - - /** - * Returns the coding set for a barcode - * - * @param string $value Barcode - * @return string - */ - protected function getCodingSet($value) - { - $value = $this->getUtf8StringWrapper()->substr($value, 0, 1); - switch ($value) { - case '‡': - return 'A'; - - case 'ˆ': - return 'B'; - - case '‰': - return 'C'; - } - - return ''; - } - - /** - * Internal method to return the code128 integer from an ascii value - * - * Table A - * ASCII CODE128 - * 32 to 95 == 0 to 63 - * 0 to 31 == 64 to 95 - * 128 to 138 == 96 to 106 - * - * Table B - * ASCII CODE128 - * 32 to 138 == 0 to 106 - * - * Table C - * ASCII CODE128 - * "00" to "99" == 0 to 99 - * 132 to 138 == 100 to 106 - * - * @param string $value - * @param string $set - * @return int - */ - protected function ord128($value, $set) - { - $ord = ord($value); - if ($set === 'A') { - if ($ord < 32) { - return $ord + 64; - } elseif ($ord < 96) { - return $ord - 32; - } elseif ($ord > 138) { - return -1; - } else { - return $ord - 32; - } - } elseif ($set === 'B') { - if ($ord < 32) { - return -1; - } elseif ($ord <= 138) { - return $ord - 32; - } else { - return -1; - } - } elseif ($set === 'C') { - $val = (int) $value; - if (($val >= 0) && ($val <= 99)) { - return $val; - } elseif (($ord >= 132) && ($ord <= 138)) { - return $ord - 32; - } else { - return -1; - } - } else { - if ($ord < 32) { - return $ord + 64; - } elseif ($ord <= 138) { - return $ord - 32; - } else { - return -1; - } - } - } - - /** - * Internal Method to return the ascii value from a code128 integer - * - * Table A - * ASCII CODE128 - * 32 to 95 == 0 to 63 - * 0 to 31 == 64 to 95 - * 128 to 138 == 96 to 106 - * - * Table B - * ASCII CODE128 - * 32 to 138 == 0 to 106 - * - * Table C - * ASCII CODE128 - * "00" to "99" == 0 to 99 - * 132 to 138 == 100 to 106 - * - * @param int $value - * @param string $set - * @return int|string - */ - protected function chr128($value, $set) - { - if ($set === 'A') { - if ($value < 64) { - return chr($value + 32); - } elseif ($value < 96) { - return chr($value - 64); - } elseif ($value > 106) { - return -1; - } else { - return chr($value + 32); - } - } elseif ($set === 'B') { - if ($value > 106) { - return -1; - } else { - return chr($value + 32); - } - } elseif ($set === 'C') { - if (($value >= 0) && ($value <= 9)) { - return '0' . (string) $value; - } elseif ($value <= 99) { - return (string) $value; - } elseif ($value <= 106) { - return chr($value + 32); - } else { - return -1; - } - } else { - if ($value <= 106) { - return $value + 32; - } else { - return -1; - } - } - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Code25.php b/lib/laminas/laminas-validator/src/Barcode/Code25.php deleted file mode 100644 index 7134eb7cd..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Code25.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -class Code25 extends AbstractAdapter -{ - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength(-1); - $this->setCharacters('0123456789'); - $this->setChecksum('code25'); - $this->useChecksum(false); - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Code25interleaved.php b/lib/laminas/laminas-validator/src/Barcode/Code25interleaved.php deleted file mode 100644 index cce21b20e..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Code25interleaved.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -class Code25interleaved extends AbstractAdapter -{ - /** - * Constructor - * - * Sets check flag to false. - */ - public function __construct() - { - $this->setLength('even'); - $this->setCharacters('0123456789'); - $this->setChecksum('code25'); - $this->useChecksum(false); - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Code39.php b/lib/laminas/laminas-validator/src/Barcode/Code39.php deleted file mode 100644 index 4b101191c..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Code39.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -use function str_split; -use function substr; - -class Code39 extends AbstractAdapter -{ - /** @var array */ - protected $check = [ - '0' => 0, - '1' => 1, - '2' => 2, - '3' => 3, - '4' => 4, - '5' => 5, - '6' => 6, - '7' => 7, - '8' => 8, - '9' => 9, - 'A' => 10, - 'B' => 11, - 'C' => 12, - 'D' => 13, - 'E' => 14, - 'F' => 15, - 'G' => 16, - 'H' => 17, - 'I' => 18, - 'J' => 19, - 'K' => 20, - 'L' => 21, - 'M' => 22, - 'N' => 23, - 'O' => 24, - 'P' => 25, - 'Q' => 26, - 'R' => 27, - 'S' => 28, - 'T' => 29, - 'U' => 30, - 'V' => 31, - 'W' => 32, - 'X' => 33, - 'Y' => 34, - 'Z' => 35, - '-' => 36, - '.' => 37, - ' ' => 38, - '$' => 39, - '/' => 40, - '+' => 41, - '%' => 42, - ]; - - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength(-1); - $this->setCharacters('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ -.$/+%'); - $this->setChecksum('code39'); - $this->useChecksum(false); - } - - /** - * Validates the checksum (Modulo 43) - * - * @param string $value The barcode to validate - * @return bool - */ - protected function code39($value) - { - $checksum = substr($value, -1, 1); - $value = str_split(substr($value, 0, -1)); - $count = 0; - foreach ($value as $char) { - $count += $this->check[$char]; - } - - $mod = $count % 43; - if ($mod === $this->check[$checksum]) { - return true; - } - - return false; - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Code39ext.php b/lib/laminas/laminas-validator/src/Barcode/Code39ext.php deleted file mode 100644 index d23123c0a..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Code39ext.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -class Code39ext extends AbstractAdapter -{ - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength(-1); - $this->setCharacters(128); - $this->useChecksum(false); - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Code93.php b/lib/laminas/laminas-validator/src/Barcode/Code93.php deleted file mode 100644 index 92905ec17..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Code93.php +++ /dev/null @@ -1,119 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -use function array_search; -use function count; -use function str_split; -use function substr; - -class Code93 extends AbstractAdapter -{ - /** - * Note that the characters !"§& are only synonyms - * - * @var array - */ - protected $check = [ - '0' => 0, - '1' => 1, - '2' => 2, - '3' => 3, - '4' => 4, - '5' => 5, - '6' => 6, - '7' => 7, - '8' => 8, - '9' => 9, - 'A' => 10, - 'B' => 11, - 'C' => 12, - 'D' => 13, - 'E' => 14, - 'F' => 15, - 'G' => 16, - 'H' => 17, - 'I' => 18, - 'J' => 19, - 'K' => 20, - 'L' => 21, - 'M' => 22, - 'N' => 23, - 'O' => 24, - 'P' => 25, - 'Q' => 26, - 'R' => 27, - 'S' => 28, - 'T' => 29, - 'U' => 30, - 'V' => 31, - 'W' => 32, - 'X' => 33, - 'Y' => 34, - 'Z' => 35, - '-' => 36, - '.' => 37, - ' ' => 38, - '$' => 39, - '/' => 40, - '+' => 41, - '%' => 42, - '!' => 43, - '"' => 44, - '§' => 45, - '&' => 46, - ]; - - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength(-1); - $this->setCharacters('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ -.$/+%'); - $this->setChecksum('code93'); - $this->useChecksum(false); - } - - /** - * Validates the checksum (Modulo CK) - * - * @param string $value The barcode to validate - * @return bool - */ - protected function code93($value) - { - $checksum = substr($value, -2, 2); - $value = str_split(substr($value, 0, -2)); - $count = 0; - $length = count($value) % 20; - foreach ($value as $char) { - if ($length === 0) { - $length = 20; - } - - $count += $this->check[$char] * $length; - --$length; - } - - $check = array_search($count % 47, $this->check); - $value[] = $check; - $count = 0; - $length = count($value) % 15; - foreach ($value as $char) { - if ($length === 0) { - $length = 15; - } - - $count += $this->check[$char] * $length; - --$length; - } - $check .= array_search($count % 47, $this->check); - - if ($check === $checksum) { - return true; - } - - return false; - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Code93ext.php b/lib/laminas/laminas-validator/src/Barcode/Code93ext.php deleted file mode 100644 index 216d72285..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Code93ext.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -class Code93ext extends AbstractAdapter -{ - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength(-1); - $this->setCharacters(128); - $this->useChecksum(false); - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Ean12.php b/lib/laminas/laminas-validator/src/Barcode/Ean12.php deleted file mode 100644 index 82be6c5a5..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Ean12.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -class Ean12 extends AbstractAdapter -{ - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength(12); - $this->setCharacters('0123456789'); - $this->setChecksum('gtin'); - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Ean13.php b/lib/laminas/laminas-validator/src/Barcode/Ean13.php deleted file mode 100644 index 261a687fd..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Ean13.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -class Ean13 extends AbstractAdapter -{ - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength(13); - $this->setCharacters('0123456789'); - $this->setChecksum('gtin'); - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Ean14.php b/lib/laminas/laminas-validator/src/Barcode/Ean14.php deleted file mode 100644 index 9be798b08..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Ean14.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -class Ean14 extends AbstractAdapter -{ - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength(14); - $this->setCharacters('0123456789'); - $this->setChecksum('gtin'); - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Ean18.php b/lib/laminas/laminas-validator/src/Barcode/Ean18.php deleted file mode 100644 index f2c32204e..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Ean18.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -class Ean18 extends AbstractAdapter -{ - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength(18); - $this->setCharacters('0123456789'); - $this->setChecksum('gtin'); - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Ean2.php b/lib/laminas/laminas-validator/src/Barcode/Ean2.php deleted file mode 100644 index a49ea9b9a..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Ean2.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -class Ean2 extends AbstractAdapter -{ - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength(2); - $this->setCharacters('0123456789'); - $this->useChecksum(false); - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Ean5.php b/lib/laminas/laminas-validator/src/Barcode/Ean5.php deleted file mode 100644 index 0433c80a2..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Ean5.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -class Ean5 extends AbstractAdapter -{ - /** - * Constructor - * - * Sets check flag to false. - */ - public function __construct() - { - $this->setLength(5); - $this->setCharacters('0123456789'); - $this->useChecksum(false); - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Ean8.php b/lib/laminas/laminas-validator/src/Barcode/Ean8.php deleted file mode 100644 index 7f1399a46..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Ean8.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -use function strlen; - -class Ean8 extends AbstractAdapter -{ - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength([7, 8]); - $this->setCharacters('0123456789'); - $this->setChecksum('gtin'); - } - - /** - * Overrides parent checkLength - * - * @param string $value Value - * @return bool - */ - public function hasValidLength($value) - { - if (strlen($value) === 7) { - $this->useChecksum(false); - } else { - $this->useChecksum(true); - } - - return parent::hasValidLength($value); - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Gtin12.php b/lib/laminas/laminas-validator/src/Barcode/Gtin12.php deleted file mode 100644 index f667d1f50..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Gtin12.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -class Gtin12 extends AbstractAdapter -{ - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength(12); - $this->setCharacters('0123456789'); - $this->setChecksum('gtin'); - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Gtin13.php b/lib/laminas/laminas-validator/src/Barcode/Gtin13.php deleted file mode 100644 index 4f02651ec..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Gtin13.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -class Gtin13 extends AbstractAdapter -{ - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength(13); - $this->setCharacters('0123456789'); - $this->setChecksum('gtin'); - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Gtin14.php b/lib/laminas/laminas-validator/src/Barcode/Gtin14.php deleted file mode 100644 index 2ec6624ce..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Gtin14.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -class Gtin14 extends AbstractAdapter -{ - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength(14); - $this->setCharacters('0123456789'); - $this->setChecksum('gtin'); - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Identcode.php b/lib/laminas/laminas-validator/src/Barcode/Identcode.php deleted file mode 100644 index a0c4cf63a..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Identcode.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -class Identcode extends AbstractAdapter -{ - /** - * Allowed barcode lengths - * - * @var int - */ - protected $length = 12; - - /** - * Allowed barcode characters - * - * @var string - */ - protected $characters = '0123456789'; - - /** - * Checksum function - * - * @var string - */ - protected $checksum = 'identcode'; - - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength(12); - $this->setCharacters('0123456789'); - $this->setChecksum('identcode'); - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Intelligentmail.php b/lib/laminas/laminas-validator/src/Barcode/Intelligentmail.php deleted file mode 100644 index d34569f1b..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Intelligentmail.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -class Intelligentmail extends AbstractAdapter -{ - /** - * Constructor - * - * Sets check flag to false. - */ - public function __construct() - { - $this->setLength([20, 25, 29, 31]); - $this->setCharacters('0123456789'); - $this->useChecksum(false); - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Issn.php b/lib/laminas/laminas-validator/src/Barcode/Issn.php deleted file mode 100644 index 73a0fcc3f..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Issn.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -use function str_split; -use function strlen; -use function strpos; -use function substr; - -class Issn extends AbstractAdapter -{ - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength([8, 13]); - $this->setCharacters('0123456789X'); - $this->setChecksum('gtin'); - } - - /** - * Allows X on length of 8 chars - * - * @param string $value The barcode to check for allowed characters - * @return bool - */ - public function hasValidCharacters($value) - { - if (strlen($value) !== 8) { - if (strpos($value, 'X') !== false) { - return false; - } - } - - return parent::hasValidCharacters($value); - } - - /** - * Validates the checksum - * - * @param string $value The barcode to check the checksum for - * @return bool - */ - public function hasValidChecksum($value) - { - if (strlen($value) === 8) { - $this->setChecksum('issn'); - } else { - $this->setChecksum('gtin'); - } - - return parent::hasValidChecksum($value); - } - - /** - * Validates the checksum () - * ISSN implementation (reversed mod11) - * - * @param string $value The barcode to validate - * @return bool - */ - protected function issn($value) - { - $checksum = substr($value, -1, 1); - $values = str_split(substr($value, 0, -1)); - $check = 0; - $multi = 8; - foreach ($values as $token) { - if ($token === 'X') { - $token = 10; - } - - $check += $token * $multi; - --$multi; - } - - $check %= 11; - $check = $check === 0 ? 0 : 11 - $check; - - if ((string) $check === $checksum) { - return true; - } - - if (($check === 10) && ($checksum === 'X')) { - return true; - } - - return false; - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Itf14.php b/lib/laminas/laminas-validator/src/Barcode/Itf14.php deleted file mode 100644 index c8683ff19..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Itf14.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -class Itf14 extends AbstractAdapter -{ - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength(14); - $this->setCharacters('0123456789'); - $this->setChecksum('gtin'); - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Leitcode.php b/lib/laminas/laminas-validator/src/Barcode/Leitcode.php deleted file mode 100644 index c4a0dc107..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Leitcode.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -class Leitcode extends AbstractAdapter -{ - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength(14); - $this->setCharacters('0123456789'); - $this->setChecksum('identcode'); - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Planet.php b/lib/laminas/laminas-validator/src/Barcode/Planet.php deleted file mode 100644 index e966065b9..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Planet.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -class Planet extends AbstractAdapter -{ - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength([12, 14]); - $this->setCharacters('0123456789'); - $this->setChecksum('postnet'); - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Postnet.php b/lib/laminas/laminas-validator/src/Barcode/Postnet.php deleted file mode 100644 index f3261e138..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Postnet.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -class Postnet extends AbstractAdapter -{ - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength([6, 7, 10, 12]); - $this->setCharacters('0123456789'); - $this->setChecksum('postnet'); - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Royalmail.php b/lib/laminas/laminas-validator/src/Barcode/Royalmail.php deleted file mode 100644 index 9c3d306ef..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Royalmail.php +++ /dev/null @@ -1,156 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -use function array_intersect; -use function array_keys; -use function current; -use function str_split; -use function strlen; -use function substr; - -class Royalmail extends AbstractAdapter -{ - /** @var array<string, int> */ - protected $rows = [ - '0' => 1, - '1' => 1, - '2' => 1, - '3' => 1, - '4' => 1, - '5' => 1, - '6' => 2, - '7' => 2, - '8' => 2, - '9' => 2, - 'A' => 2, - 'B' => 2, - 'C' => 3, - 'D' => 3, - 'E' => 3, - 'F' => 3, - 'G' => 3, - 'H' => 3, - 'I' => 4, - 'J' => 4, - 'K' => 4, - 'L' => 4, - 'M' => 4, - 'N' => 4, - 'O' => 5, - 'P' => 5, - 'Q' => 5, - 'R' => 5, - 'S' => 5, - 'T' => 5, - 'U' => 0, - 'V' => 0, - 'W' => 0, - 'X' => 0, - 'Y' => 0, - 'Z' => 0, - ]; - - /** @var array<string, int> */ - protected $columns = [ - '0' => 1, - '1' => 2, - '2' => 3, - '3' => 4, - '4' => 5, - '5' => 0, - '6' => 1, - '7' => 2, - '8' => 3, - '9' => 4, - 'A' => 5, - 'B' => 0, - 'C' => 1, - 'D' => 2, - 'E' => 3, - 'F' => 4, - 'G' => 5, - 'H' => 0, - 'I' => 1, - 'J' => 2, - 'K' => 3, - 'L' => 4, - 'M' => 5, - 'N' => 0, - 'O' => 1, - 'P' => 2, - 'Q' => 3, - 'R' => 4, - 'S' => 5, - 'T' => 0, - 'U' => 1, - 'V' => 2, - 'W' => 3, - 'X' => 4, - 'Y' => 5, - 'Z' => 0, - ]; - - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength(-1); - $this->setCharacters('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'); - $this->setChecksum('royalmail'); - } - - /** - * Validates the checksum () - * - * @param string $value The barcode to validate - * @return bool - */ - protected function royalmail($value) - { - $checksum = substr($value, -1, 1); - $values = str_split(substr($value, 0, -1)); - $rowvalue = 0; - $colvalue = 0; - foreach ($values as $row) { - $rowvalue += $this->rows[$row]; - $colvalue += $this->columns[$row]; - } - - $rowvalue %= 6; - $colvalue %= 6; - - $rowchkvalue = array_keys($this->rows, $rowvalue); - $colchkvalue = array_keys($this->columns, $colvalue); - $intersect = array_intersect($rowchkvalue, $colchkvalue); - $chkvalue = (string) current($intersect); - - if ($chkvalue === $checksum) { - return true; - } - - return false; - } - - /** - * Allows start and stop tag within checked chars - * - * @param string $value The barcode to check for allowed characters - * @return bool - */ - public function hasValidCharacters($value) - { - if ($value[0] === '(') { - $value = substr($value, 1); - - if ($value[strlen($value) - 1] === ')') { - $value = substr($value, 0, -1); - } else { - return false; - } - } - - return parent::hasValidCharacters($value); - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Sscc.php b/lib/laminas/laminas-validator/src/Barcode/Sscc.php deleted file mode 100644 index 44f804233..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Sscc.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -class Sscc extends AbstractAdapter -{ - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength(18); - $this->setCharacters('0123456789'); - $this->setChecksum('gtin'); - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Upca.php b/lib/laminas/laminas-validator/src/Barcode/Upca.php deleted file mode 100644 index d5d804177..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Upca.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -class Upca extends AbstractAdapter -{ - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength(12); - $this->setCharacters('0123456789'); - $this->setChecksum('gtin'); - } -} diff --git a/lib/laminas/laminas-validator/src/Barcode/Upce.php b/lib/laminas/laminas-validator/src/Barcode/Upce.php deleted file mode 100644 index 3532b42c6..000000000 --- a/lib/laminas/laminas-validator/src/Barcode/Upce.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -namespace Laminas\Validator\Barcode; - -use function strlen; - -class Upce extends AbstractAdapter -{ - /** - * Constructor for this barcode adapter - */ - public function __construct() - { - $this->setLength([6, 7, 8]); - $this->setCharacters('0123456789'); - $this->setChecksum('gtin'); - } - - /** - * Overrides parent checkLength - * - * @param string $value Value - * @return bool - */ - public function hasValidLength($value) - { - if (strlen($value) !== 8) { - $this->useChecksum(false); - } else { - $this->useChecksum(true); - } - - return parent::hasValidLength($value); - } -} diff --git a/lib/laminas/laminas-validator/src/Between.php b/lib/laminas/laminas-validator/src/Between.php deleted file mode 100644 index 8a34f4ae6..000000000 --- a/lib/laminas/laminas-validator/src/Between.php +++ /dev/null @@ -1,217 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use Laminas\Stdlib\ArrayUtils; -use Traversable; - -use function array_key_exists; -use function array_shift; -use function func_get_args; -use function is_array; -use function is_numeric; -use function is_string; - -use const PHP_INT_MAX; - -class Between extends AbstractValidator -{ - public const NOT_BETWEEN = 'notBetween'; - public const NOT_BETWEEN_STRICT = 'notBetweenStrict'; - public const VALUE_NOT_NUMERIC = 'valueNotNumeric'; - public const VALUE_NOT_STRING = 'valueNotString'; - - /** - * Retain if min and max are numeric values. Allow to not compare string and numeric types - */ - private ?bool $numeric = null; - - /** - * Validation failure message template definitions - * - * @var array<string, string> - */ - protected $messageTemplates = [ - self::NOT_BETWEEN => "The input is not between '%min%' and '%max%', inclusively", - self::NOT_BETWEEN_STRICT => "The input is not strictly between '%min%' and '%max%'", - self::VALUE_NOT_NUMERIC => "The min ('%min%') and max ('%max%') values are numeric, but the input is not", - self::VALUE_NOT_STRING => "The min ('%min%') and max ('%max%') values are non-numeric strings, " - . 'but the input is not a string', - ]; - - /** - * Additional variables available for validation failure messages - * - * @var array - */ - protected $messageVariables = [ - 'min' => ['options' => 'min'], - 'max' => ['options' => 'max'], - ]; - - /** - * Options for the between validator - * - * @var array - */ - protected $options = [ - 'inclusive' => true, // Whether to do inclusive comparisons, allowing equivalence to min and/or max - 'min' => 0, - 'max' => PHP_INT_MAX, - ]; - - /** - * Sets validator options - * Accepts the following option keys: - * 'min' => scalar, minimum border - * 'max' => scalar, maximum border - * 'inclusive' => boolean, inclusive border values - * - * @param array<string, mixed>|Traversable<string, mixed> $options - * @throws Exception\InvalidArgumentException - */ - public function __construct($options = null) - { - if ($options instanceof Traversable) { - $options = ArrayUtils::iteratorToArray($options); - } - if (! is_array($options)) { - $temp = []; - /** @psalm-var array<string, int|string> $options */ - $options = func_get_args(); - $temp['min'] = array_shift($options); - if (! empty($options)) { - $temp['max'] = array_shift($options); - } - - if (! empty($options)) { - $temp['inclusive'] = array_shift($options); - } - - $options = $temp; - } - - if (! array_key_exists('min', $options) || ! array_key_exists('max', $options)) { - throw new Exception\InvalidArgumentException("Missing option: 'min' and 'max' have to be given"); - } - - if ( - (isset($options['min']) && is_numeric($options['min'])) - && (isset($options['max']) && is_numeric($options['max'])) - ) { - $this->numeric = true; - } elseif ( - (isset($options['min']) && is_string($options['min'])) - && (isset($options['max']) && is_string($options['max'])) - ) { - $this->numeric = false; - } else { - throw new Exception\InvalidArgumentException( - "Invalid options: 'min' and 'max' should be of the same scalar type" - ); - } - - parent::__construct($options); - } - - /** - * Returns the min option - * - * @return mixed - */ - public function getMin() - { - return $this->options['min']; - } - - /** - * Sets the min option - * - * @param mixed $min - * @return $this Provides a fluent interface - */ - public function setMin($min) - { - $this->options['min'] = $min; - return $this; - } - - /** - * Returns the max option - * - * @return mixed - */ - public function getMax() - { - return $this->options['max']; - } - - /** - * Sets the max option - * - * @param mixed $max - * @return $this Provides a fluent interface - */ - public function setMax($max) - { - $this->options['max'] = $max; - return $this; - } - - /** - * Returns the inclusive option - * - * @return bool - */ - public function getInclusive() - { - return $this->options['inclusive']; - } - - /** - * Sets the inclusive option - * - * @param bool $inclusive - * @return $this Provides a fluent interface - */ - public function setInclusive($inclusive) - { - $this->options['inclusive'] = $inclusive; - return $this; - } - - /** - * Returns true if and only if $value is between min and max options, inclusively - * if inclusive option is true. - * - * @param mixed $value - * @return bool - */ - public function isValid($value) - { - $this->setValue($value); - - if ($this->numeric && ! is_numeric($value)) { - $this->error(self::VALUE_NOT_NUMERIC); - return false; - } - if (! $this->numeric && ! is_string($value)) { - $this->error(self::VALUE_NOT_STRING); - return false; - } - - if ($this->getInclusive()) { - if ($this->getMin() > $value || $value > $this->getMax()) { - $this->error(self::NOT_BETWEEN); - return false; - } - } else { - if ($this->getMin() >= $value || $value >= $this->getMax()) { - $this->error(self::NOT_BETWEEN_STRICT); - return false; - } - } - - return true; - } -} diff --git a/lib/laminas/laminas-validator/src/Bitwise.php b/lib/laminas/laminas-validator/src/Bitwise.php deleted file mode 100644 index d718a020f..000000000 --- a/lib/laminas/laminas-validator/src/Bitwise.php +++ /dev/null @@ -1,203 +0,0 @@ -<?php // phpcs:disable WebimpressCodingStandard.Formatting.Reference.UnexpectedSpace - -namespace Laminas\Validator; - -use Traversable; - -use function array_shift; -use function func_get_args; -use function is_array; -use function iterator_to_array; - -class Bitwise extends AbstractValidator -{ - public const OP_AND = 'and'; - public const OP_XOR = 'xor'; - - public const NOT_AND = 'notAnd'; - public const NOT_AND_STRICT = 'notAndStrict'; - public const NOT_XOR = 'notXor'; - public const NO_OP = 'noOp'; - - /** @var int */ - protected $control; - - /** - * Validation failure message template definitions - * - * @var array<string, string> - */ - protected $messageTemplates = [ - self::NOT_AND => "The input has no common bit set with '%control%'", - self::NOT_AND_STRICT => "The input doesn't have the same bits set as '%control%'", - self::NOT_XOR => "The input has common bit set with '%control%'", - self::NO_OP => "No operator was present to compare '%control%' against", - ]; - - /** - * Additional variables available for validation failure messages - * - * @var array<string, string> - */ - protected $messageVariables = [ - 'control' => 'control', - ]; - - /** @var null|int */ - protected $operator; - - /** @var bool */ - protected $strict = false; - - /** - * Sets validator options - * Accepts the following option keys: - * 'control' => int - * 'operator' => - * 'strict' => bool - * - * @param array|Traversable $options - */ - public function __construct($options = null) - { - if ($options instanceof Traversable) { - $options = iterator_to_array($options); - } - - if (! is_array($options)) { - $options = func_get_args(); - - $temp['control'] = array_shift($options); - - if (! empty($options)) { - $temp['operator'] = array_shift($options); - } - - if (! empty($options)) { - $temp['strict'] = array_shift($options); - } - - $options = $temp; - } - - parent::__construct($options); - } - - /** - * Returns the control parameter. - * - * @return integer - */ - public function getControl() - { - return $this->control; - } - - /** - * Returns the operator parameter. - * - * @return null|int - */ - public function getOperator() - { - return $this->operator; - } - - /** - * Returns the strict parameter. - * - * @return boolean - */ - public function getStrict() - { - return $this->strict; - } - - /** - * Returns true if and only if $value is between min and max options, inclusively - * if inclusive option is true. - * - * @param mixed $value - * @return bool - */ - public function isValid($value) - { - $this->setValue($value); - - if (self::OP_AND === $this->operator) { - if ($this->strict) { - // All the bits set in value must be set in control - $result = ($this->control & $value) === $value; - - if (! $result) { - $this->error(self::NOT_AND_STRICT); - } - - return $result; - } - - // At least one of the bits must be common between value and control - $result = (bool) ($this->control & $value); - - if (! $result) { - $this->error(self::NOT_AND); - } - - return $result; - } - - if (self::OP_XOR === $this->operator) { - // Parentheses are required due to order of operations with bitwise operations - // phpcs:ignore WebimpressCodingStandard.Formatting.RedundantParentheses.SingleEquality - $result = ($this->control ^ $value) === ($this->control | $value); - - if (! $result) { - $this->error(self::NOT_XOR); - } - - return $result; - } - - $this->error(self::NO_OP); - return false; - } - - /** - * Sets the control parameter. - * - * @param integer $control - * @return $this - */ - public function setControl($control) - { - $this->control = (int) $control; - - return $this; - } - - /** - * Sets the operator parameter. - * - * @param string $operator - * @return $this - */ - public function setOperator($operator) - { - $this->operator = $operator; - - return $this; - } - - /** - * Sets the strict parameter. - * - * @param boolean $strict - * @return $this - */ - public function setStrict($strict) - { - $this->strict = (bool) $strict; - - return $this; - } -} diff --git a/lib/laminas/laminas-validator/src/BusinessIdentifierCode.php b/lib/laminas/laminas-validator/src/BusinessIdentifierCode.php deleted file mode 100644 index f9df4feaa..000000000 --- a/lib/laminas/laminas-validator/src/BusinessIdentifierCode.php +++ /dev/null @@ -1,329 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use function in_array; -use function is_string; -use function preg_match; -use function strtoupper; - -class BusinessIdentifierCode extends AbstractValidator -{ - public const INVALID = 'valueNotBic'; - public const NOT_STRING = 'valueNotString'; - public const NOT_VALID_COUNTRY = 'valueNotCountry'; - - /** @var string[] */ - protected $messageTemplates = [ - self::NOT_STRING => 'Invalid type given; string expected', - self::INVALID => 'Invalid BIC format', - self::NOT_VALID_COUNTRY => 'Invalid country code', - ]; - - /** - * @see https://www.bundesbank.de/resource/blob/749660/d2c6e00664251b4d83483c229e084e44/mL/technische-spezifikationen-scc-anhang-112018-data.pdf (page 39) - */ - private const REGEX_BIC = '/^[a-z]{4}(?<country>[a-z]{2})[a-z2-9][a-np-z0-9]([0-9a-z]{3})?$/i'; - - /** - * List of all country codes defined by ISO 3166-1 alpha-2 - * - * @see https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Current_codes - * - * @var string[] - */ - private const ISO_COUNTRIES = [ - 'AD', - 'AE', - 'AF', - 'AG', - 'AI', - 'AL', - 'AM', - 'AO', - 'AQ', - 'AR', - 'AS', - 'AT', - 'AU', - 'AW', - 'AX', - 'AZ', - 'BA', - 'BB', - 'BD', - 'BE', - 'BF', - 'BG', - 'BH', - 'BI', - 'BJ', - 'BL', - 'BM', - 'BN', - 'BO', - 'BQ', - 'BQ', - 'BR', - 'BS', - 'BT', - 'BV', - 'BW', - 'BY', - 'BZ', - 'CA', - 'CC', - 'CD', - 'CF', - 'CG', - 'CH', - 'CI', - 'CK', - 'CL', - 'CM', - 'CN', - 'CO', - 'CR', - 'CU', - 'CV', - 'CW', - 'CX', - 'CY', - 'CZ', - 'DE', - 'DJ', - 'DK', - 'DM', - 'DO', - 'DZ', - 'EC', - 'EE', - 'EG', - 'EH', - 'ER', - 'ES', - 'ET', - 'FI', - 'FJ', - 'FK', - 'FM', - 'FO', - 'FR', - 'GA', - 'GB', - 'GD', - 'GE', - 'GF', - 'GG', - 'GH', - 'GI', - 'GL', - 'GM', - 'GN', - 'GP', - 'GQ', - 'GR', - 'GS', - 'GT', - 'GU', - 'GW', - 'GY', - 'HK', - 'HM', - 'HN', - 'HR', - 'HT', - 'HU', - 'ID', - 'IE', - 'IL', - 'IM', - 'IN', - 'IO', - 'IQ', - 'IR', - 'IS', - 'IT', - 'JE', - 'JM', - 'JO', - 'JP', - 'KE', - 'KG', - 'KH', - 'KI', - 'KM', - 'KN', - 'KP', - 'KR', - 'KW', - 'KY', - 'KZ', - 'LA', - 'LB', - 'LC', - 'LI', - 'LK', - 'LR', - 'LS', - 'LT', - 'LU', - 'LV', - 'LY', - 'MA', - 'MC', - 'MD', - 'ME', - 'MF', - 'MG', - 'MH', - 'MK', - 'ML', - 'MM', - 'MN', - 'MO', - 'MP', - 'MQ', - 'MR', - 'MS', - 'MT', - 'MU', - 'MV', - 'MW', - 'MX', - 'MY', - 'MZ', - 'NA', - 'NC', - 'NE', - 'NF', - 'NG', - 'NI', - 'NL', - 'NO', - 'NP', - 'NR', - 'NU', - 'NZ', - 'OM', - 'PA', - 'PE', - 'PF', - 'PG', - 'PH', - 'PK', - 'PL', - 'PM', - 'PN', - 'PR', - 'PS', - 'PT', - 'PW', - 'PY', - 'QA', - 'RE', - 'RO', - 'RS', - 'RU', - 'RW', - 'SA', - 'SB', - 'SC', - 'SD', - 'SE', - 'SG', - 'SH', - 'SI', - 'SJ', - 'SK', - 'SL', - 'SM', - 'SN', - 'SO', - 'SR', - 'SS', - 'ST', - 'SV', - 'SX', - 'SY', - 'SZ', - 'TC', - 'TD', - 'TF', - 'TG', - 'TH', - 'TJ', - 'TK', - 'TL', - 'TM', - 'TN', - 'TO', - 'TR', - 'TT', - 'TV', - 'TW', - 'TZ', - 'UA', - 'UG', - 'UM', - 'US', - 'UY', - 'UZ', - 'VA', - 'VC', - 'VE', - 'VG', - 'VI', - 'VN', - 'VU', - 'WF', - 'WS', - 'YE', - 'YT', - 'ZA', - 'ZM', - 'ZW', - ]; - - /** - * This code is the only one used by SWIFT that is not defined by ISO 3166-1 alpha-2 - * - * @see https://en.wikipedia.org/wiki/ISO_9362 - * - * @var string - */ - private const KOSOVO_EXCEPTION = 'XK'; - - /** - * @inheritDoc - */ - public function isValid($value): bool - { - if (! is_string($value)) { - $this->error(self::NOT_STRING); - return false; - } - - if ( - empty($value) - || ! preg_match(self::REGEX_BIC, $value, $matches) - ) { - $this->error(self::INVALID); - return false; - } - - if (! $this->isSwiftValidCountry($matches['country'])) { - $this->error(self::NOT_VALID_COUNTRY); - return false; - } - - return true; - } - - private function isSwiftValidCountry(string $countryCode): bool - { - $countryCode = strtoupper($countryCode); - return in_array($countryCode, self::ISO_COUNTRIES, true) - || $countryCode === self::KOSOVO_EXCEPTION; - } -} diff --git a/lib/laminas/laminas-validator/src/Callback.php b/lib/laminas/laminas-validator/src/Callback.php deleted file mode 100644 index 7d2dc52a4..000000000 --- a/lib/laminas/laminas-validator/src/Callback.php +++ /dev/null @@ -1,150 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use Exception; -use Laminas\Validator\Exception\InvalidArgumentException; - -use function array_merge; -use function call_user_func_array; -use function is_callable; - -class Callback extends AbstractValidator -{ - /** - * Invalid callback - */ - public const INVALID_CALLBACK = 'callbackInvalid'; - - /** - * Invalid value - */ - public const INVALID_VALUE = 'callbackValue'; - - /** - * Validation failure message template definitions - * - * @var array - */ - protected $messageTemplates = [ - self::INVALID_VALUE => 'The input is not valid', - self::INVALID_CALLBACK => 'An exception has been raised within the callback', - ]; - - /** - * Default options to set for the validator - * - * @var mixed - */ - protected $options = [ - 'callback' => null, // Callback in a call_user_func format, string || array - 'callbackOptions' => [], // Options for the callback - ]; - - /** - * Constructor - * - * @param array|callable $options - */ - public function __construct($options = null) - { - if (is_callable($options)) { - $options = ['callback' => $options]; - } - - parent::__construct($options); - } - - /** - * Returns the set callback - * - * @return mixed - */ - public function getCallback() - { - return $this->options['callback']; - } - - /** - * Sets the callback - * - * @param string|array|callable $callback - * @return $this Provides a fluent interface - * @throws InvalidArgumentException - */ - public function setCallback($callback) - { - if (! is_callable($callback)) { - throw new InvalidArgumentException('Invalid callback given'); - } - - $this->options['callback'] = $callback; - return $this; - } - - /** - * Returns the set options for the callback - * - * @return mixed - */ - public function getCallbackOptions() - { - return $this->options['callbackOptions']; - } - - /** - * Sets options for the callback - * - * @param mixed $options - * @return $this Provides a fluent interface - */ - public function setCallbackOptions($options) - { - $this->options['callbackOptions'] = (array) $options; - return $this; - } - - /** - * Returns true if and only if the set callback returns - * for the provided $value - * - * @param mixed $value - * @param mixed $context Additional context to provide to the callback - * @return bool - * @throws InvalidArgumentException - */ - public function isValid($value, $context = null) - { - $this->setValue($value); - - $options = $this->getCallbackOptions(); - $callback = $this->getCallback(); - if (empty($callback)) { - throw new InvalidArgumentException('No callback given'); - } - - $args = [$value]; - if (empty($options) && ! empty($context)) { - $args[] = $context; - } - if (! empty($options) && empty($context)) { - $args = array_merge($args, $options); - } - if (! empty($options) && ! empty($context)) { - $args[] = $context; - $args = array_merge($args, $options); - } - - try { - if (! call_user_func_array($callback, $args)) { - $this->error(self::INVALID_VALUE); - return false; - } - } catch (Exception $e) { - $this->error(self::INVALID_CALLBACK); - return false; - } - - return true; - } -} diff --git a/lib/laminas/laminas-validator/src/ConfigProvider.php b/lib/laminas/laminas-validator/src/ConfigProvider.php deleted file mode 100644 index 188ebc39d..000000000 --- a/lib/laminas/laminas-validator/src/ConfigProvider.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -namespace Laminas\Validator; - -class ConfigProvider -{ - /** - * Return configuration for this component. - * - * @return array - */ - public function __invoke() - { - return [ - 'dependencies' => $this->getDependencyConfig(), - ]; - } - - /** - * Return dependency mappings for this component. - * - * @return array - */ - public function getDependencyConfig() - { - return [ - 'aliases' => [ - 'ValidatorManager' => ValidatorPluginManager::class, - - // Legacy Zend Framework aliases - 'Zend\Validator\ValidatorPluginManager' => ValidatorPluginManager::class, - ], - 'factories' => [ - ValidatorPluginManager::class => ValidatorPluginManagerFactory::class, - ], - ]; - } -} diff --git a/lib/laminas/laminas-validator/src/CreditCard.php b/lib/laminas/laminas-validator/src/CreditCard.php deleted file mode 100644 index 24030ed67..000000000 --- a/lib/laminas/laminas-validator/src/CreditCard.php +++ /dev/null @@ -1,436 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use Exception; -use Laminas\Stdlib\ArrayUtils; -use Laminas\Validator\Exception\InvalidArgumentException; -use Traversable; - -use function array_key_exists; -use function array_keys; -use function array_shift; -use function constant; -use function ctype_digit; -use function defined; -use function floor; -use function func_get_args; -use function in_array; -use function is_array; -use function is_callable; -use function is_string; -use function strlen; -use function strpos; -use function strtoupper; - -class CreditCard extends AbstractValidator -{ - /** - * Detected CCI list - * - * @var string - */ - public const ALL = 'All'; - public const AMERICAN_EXPRESS = 'American_Express'; - public const UNIONPAY = 'Unionpay'; - public const DINERS_CLUB = 'Diners_Club'; - public const DINERS_CLUB_US = 'Diners_Club_US'; - public const DISCOVER = 'Discover'; - public const JCB = 'JCB'; - public const LASER = 'Laser'; - public const MAESTRO = 'Maestro'; - public const MASTERCARD = 'Mastercard'; - public const SOLO = 'Solo'; - public const VISA = 'Visa'; - public const MIR = 'Mir'; - - public const CHECKSUM = 'creditcardChecksum'; - public const CONTENT = 'creditcardContent'; - public const INVALID = 'creditcardInvalid'; - public const LENGTH = 'creditcardLength'; - public const PREFIX = 'creditcardPrefix'; - public const SERVICE = 'creditcardService'; - public const SERVICEFAILURE = 'creditcardServiceFailure'; - - /** - * Validation failure message template definitions - * - * @var array - */ - protected $messageTemplates = [ - self::CHECKSUM => 'The input seems to contain an invalid checksum', - self::CONTENT => 'The input must contain only digits', - self::INVALID => 'Invalid type given. String expected', - self::LENGTH => 'The input contains an invalid amount of digits', - self::PREFIX => 'The input is not from an allowed institute', - self::SERVICE => 'The input seems to be an invalid credit card number', - self::SERVICEFAILURE => 'An exception has been raised while validating the input', - ]; - - /** - * List of CCV names - * - * @var array - */ - protected $cardName = [ - 0 => self::AMERICAN_EXPRESS, - 1 => self::DINERS_CLUB, - 2 => self::DINERS_CLUB_US, - 3 => self::DISCOVER, - 4 => self::JCB, - 5 => self::LASER, - 6 => self::MAESTRO, - 7 => self::MASTERCARD, - 8 => self::SOLO, - 9 => self::UNIONPAY, - 10 => self::VISA, - 11 => self::MIR, - ]; - - /** - * List of allowed CCV lengths - * - * @var array - */ - protected $cardLength = [ - self::AMERICAN_EXPRESS => [15], - self::DINERS_CLUB => [14], - self::DINERS_CLUB_US => [16], - self::DISCOVER => [16, 19], - self::JCB => [15, 16], - self::LASER => [16, 17, 18, 19], - self::MAESTRO => [12, 13, 14, 15, 16, 17, 18, 19], - self::MASTERCARD => [16], - self::SOLO => [16, 18, 19], - self::UNIONPAY => [16, 17, 18, 19], - self::VISA => [13, 16, 19], - self::MIR => [13, 16], - ]; - - /** - * List of accepted CCV provider tags - * - * @var array - */ - protected $cardType = [ - self::AMERICAN_EXPRESS => ['34', '37'], - self::DINERS_CLUB => ['300', '301', '302', '303', '304', '305', '36'], - self::DINERS_CLUB_US => ['54', '55'], - self::DISCOVER => [ - '6011', - '622126', - '622127', - '622128', - '622129', - '62213', - '62214', - '62215', - '62216', - '62217', - '62218', - '62219', - '6222', - '6223', - '6224', - '6225', - '6226', - '6227', - '6228', - '62290', - '62291', - '622920', - '622921', - '622922', - '622923', - '622924', - '622925', - '644', - '645', - '646', - '647', - '648', - '649', - '65', - ], - self::JCB => ['1800', '2131', '3528', '3529', '353', '354', '355', '356', '357', '358'], - self::LASER => ['6304', '6706', '6771', '6709'], - self::MAESTRO => [ - '5018', - '5020', - '5038', - '6304', - '6759', - '6761', - '6762', - '6763', - '6764', - '6765', - '6766', - '6772', - ], - self::MASTERCARD => [ - '2221', - '2222', - '2223', - '2224', - '2225', - '2226', - '2227', - '2228', - '2229', - '223', - '224', - '225', - '226', - '227', - '228', - '229', - '23', - '24', - '25', - '26', - '271', - '2720', - '51', - '52', - '53', - '54', - '55', - ], - self::SOLO => ['6334', '6767'], - self::UNIONPAY => [ - '622126', - '622127', - '622128', - '622129', - '62213', - '62214', - '62215', - '62216', - '62217', - '62218', - '62219', - '6222', - '6223', - '6224', - '6225', - '6226', - '6227', - '6228', - '62290', - '62291', - '622920', - '622921', - '622922', - '622923', - '622924', - '622925', - ], - self::VISA => ['4'], - self::MIR => ['2200', '2201', '2202', '2203', '2204'], - ]; - - /** - * Options for this validator - * - * @var array - */ - protected $options = [ - 'service' => null, // Service callback for additional validation - 'type' => [], // CCIs which are accepted by validation - ]; - - /** - * Constructor - * - * @param string|array|Traversable $options OPTIONAL Type of CCI to allow - */ - public function __construct($options = []) - { - if ($options instanceof Traversable) { - $options = ArrayUtils::iteratorToArray($options); - } elseif (! is_array($options)) { - $options = func_get_args(); - $temp['type'] = array_shift($options); - if (! empty($options)) { - $temp['service'] = array_shift($options); - } - - $options = $temp; - } - - if (! array_key_exists('type', $options)) { - $options['type'] = self::ALL; - } - - $this->setType($options['type']); - unset($options['type']); - - if (array_key_exists('service', $options)) { - $this->setService($options['service']); - unset($options['service']); - } - - parent::__construct($options); - } - - /** - * Returns a list of accepted CCIs - * - * @return array - */ - public function getType() - { - return $this->options['type']; - } - - /** - * Sets CCIs which are accepted by validation - * - * @param string|array $type Type to allow for validation - * @return CreditCard Provides a fluid interface - */ - public function setType($type) - { - $this->options['type'] = []; - return $this->addType($type); - } - - /** - * Adds a CCI to be accepted by validation - * - * @param string|array $type Type to allow for validation - * @return $this Provides a fluid interface - */ - public function addType($type) - { - if (is_string($type)) { - $type = [$type]; - } - - foreach ($type as $typ) { - if ($typ === self::ALL) { - $this->options['type'] = array_keys($this->cardLength); - continue; - } - - if (in_array($typ, $this->options['type'])) { - continue; - } - - $constant = 'static::' . strtoupper($typ); - if (! defined($constant) || in_array(constant($constant), $this->options['type'])) { - continue; - } - $this->options['type'][] = constant($constant); - } - - return $this; - } - - /** - * Returns the actual set service - * - * @return callable - */ - public function getService() - { - return $this->options['service']; - } - - /** - * Sets a new callback for service validation - * - * @param callable $service - * @return $this - * @throws InvalidArgumentException On invalid service callback. - */ - public function setService($service) - { - if (! is_callable($service)) { - throw new InvalidArgumentException('Invalid callback given'); - } - - $this->options['service'] = $service; - return $this; - } - - /** - * Returns true if and only if $value follows the Luhn algorithm (mod-10 checksum) - * - * @param string $value - * @return bool - */ - public function isValid($value) - { - $this->setValue($value); - - if (! is_string($value)) { - $this->error(self::INVALID, $value); - return false; - } - - if (! ctype_digit($value)) { - $this->error(self::CONTENT, $value); - return false; - } - - $length = strlen($value); - $types = $this->getType(); - $foundp = false; - $foundl = false; - foreach ($types as $type) { - foreach ($this->cardType[$type] as $prefix) { - if (0 === strpos($value, (string) $prefix)) { - $foundp = true; - if (in_array($length, $this->cardLength[$type])) { - $foundl = true; - break 2; - } - } - } - } - - if ($foundp === false) { - $this->error(self::PREFIX, $value); - return false; - } - - if ($foundl === false) { - $this->error(self::LENGTH, $value); - return false; - } - - $sum = 0; - $weight = 2; - - for ($i = $length - 2; $i >= 0; $i--) { - $digit = $weight * $value[$i]; - $sum += floor($digit / 10) + $digit % 10; - $weight = $weight % 2 + 1; - } - - $checksum = (10 - $sum % 10) % 10; - if ((string) $checksum !== $value[$length - 1]) { - $this->error(self::CHECKSUM, $value); - return false; - } - - $service = $this->getService(); - if (! empty($service)) { - try { - $callback = new Callback($service); - $callback->setOptions($this->getType()); - if (! $callback->isValid($value)) { - $this->error(self::SERVICE, $value); - return false; - } - } catch (Exception $e) { - $this->error(self::SERVICEFAILURE, $value); - return false; - } - } - - return true; - } -} diff --git a/lib/laminas/laminas-validator/src/Csrf.php b/lib/laminas/laminas-validator/src/Csrf.php deleted file mode 100644 index 332d366ba..000000000 --- a/lib/laminas/laminas-validator/src/Csrf.php +++ /dev/null @@ -1,376 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use Laminas\Session\Container as SessionContainer; -use Laminas\Stdlib\ArrayUtils; -use Traversable; - -use function explode; -use function is_array; -use function is_string; -use function md5; -use function random_bytes; -use function sprintf; -use function str_replace; -use function strtolower; -use function strtr; - -class Csrf extends AbstractValidator -{ - /** - * Error codes - * - * @const string - */ - public const NOT_SAME = 'notSame'; - - /** - * Error messages - * - * @var array - */ - protected $messageTemplates = [ - self::NOT_SAME => 'The form submitted did not originate from the expected site', - ]; - - /** - * Actual hash used. - * - * @var mixed - */ - protected $hash; - - /** - * Static cache of the session names to generated hashes - * - * @todo unused, left here to avoid BC breaks - * @var array - */ - protected static $hashCache; - - /** - * Name of CSRF element (used to create non-colliding hashes) - * - * @var string - */ - protected $name = 'csrf'; - - /** - * Salt for CSRF token - * - * @var string - */ - protected $salt = 'salt'; - - /** @var SessionContainer */ - protected $session; - - /** - * TTL for CSRF token - * - * @var int|null - */ - protected $timeout = 300; - - /** - * Constructor - * - * @param array|Traversable $options - */ - public function __construct($options = []) - { - parent::__construct($options); - - if ($options instanceof Traversable) { - $options = ArrayUtils::iteratorToArray($options); - } - - if (! is_array($options)) { - $options = (array) $options; - } - - foreach ($options as $key => $value) { - switch (strtolower($key)) { - case 'name': - $this->setName($value); - break; - case 'salt': - $this->setSalt($value); - break; - case 'session': - $this->setSession($value); - break; - case 'timeout': - $this->setTimeout($value); - break; - default: - // ignore unknown options - break; - } - } - } - - /** - * Does the provided token match the one generated? - * - * @param string $value - * @param mixed $context - * @return bool - */ - public function isValid($value, $context = null) - { - if (! is_string($value)) { - return false; - } - - $this->setValue($value); - - $tokenId = $this->getTokenIdFromHash($value); - $hash = $this->getValidationToken($tokenId); - - $tokenFromValue = $this->getTokenFromHash($value); - $tokenFromHash = $this->getTokenFromHash($hash); - - if (! $tokenFromValue || ! $tokenFromHash || ($tokenFromValue !== $tokenFromHash)) { - $this->error(self::NOT_SAME); - return false; - } - - return true; - } - - /** - * Set CSRF name - * - * @param string $name - * @return $this - */ - public function setName($name) - { - $this->name = (string) $name; - return $this; - } - - /** - * Get CSRF name - * - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * Set session container - * - * @return $this - */ - public function setSession(SessionContainer $session) - { - $this->session = $session; - if ($this->hash) { - $this->initCsrfToken(); - } - return $this; - } - - /** - * Get session container - * - * Instantiate session container if none currently exists - * - * @return SessionContainer - */ - public function getSession() - { - if (null === $this->session) { - // Using fully qualified name, to ensure polyfill class alias is used - $this->session = new SessionContainer($this->getSessionName()); - } - return $this->session; - } - - /** - * Salt for CSRF token - * - * @param string $salt - * @return $this - */ - public function setSalt($salt) - { - $this->salt = (string) $salt; - return $this; - } - - /** - * Retrieve salt for CSRF token - * - * @return string - */ - public function getSalt() - { - return $this->salt; - } - - /** - * Retrieve CSRF token - * - * If no CSRF token currently exists, or should be regenerated, - * generates one. - * - * @param bool $regenerate default false - * @return string - */ - public function getHash($regenerate = false) - { - if ((null === $this->hash) || $regenerate) { - $this->generateHash(); - } - return $this->hash; - } - - /** - * Get session namespace for CSRF token - * - * Generates a session namespace based on salt, element name, and class. - * - * @return string - */ - public function getSessionName() - { - return str_replace('\\', '_', self::class) . '_' - . $this->getSalt() . '_' - . strtr($this->getName(), ['[' => '_', ']' => '']); - } - - /** - * Set timeout for CSRF session token - * - * @param int|null $ttl - * @return $this - */ - public function setTimeout($ttl) - { - $this->timeout = $ttl !== null ? (int) $ttl : null; - return $this; - } - - /** - * Get CSRF session token timeout - * - * @return int|null - */ - public function getTimeout() - { - return $this->timeout; - } - - /** - * Initialize CSRF token in session - * - * @return void - */ - protected function initCsrfToken() - { - $session = $this->getSession(); - $timeout = $this->getTimeout(); - if (null !== $timeout) { - $session->setExpirationSeconds($timeout); - } - - $hash = $this->getHash(); - $token = $this->getTokenFromHash($hash); - $tokenId = $this->getTokenIdFromHash($hash); - - if (! $session->tokenList) { - $session->tokenList = []; - } - $session->tokenList[$tokenId] = $token; - $session->hash = $hash; // @todo remove this, left for BC - } - - /** - * Generate CSRF token - * - * Generates CSRF token and stores both in {@link $hash} and element - * value. - * - * @return void - */ - protected function generateHash() - { - $token = md5($this->getSalt() . random_bytes(32) . $this->getName()); - - $this->hash = $this->formatHash($token, $this->generateTokenId()); - - $this->setValue($this->hash); - $this->initCsrfToken(); - } - - /** - * @return string - */ - protected function generateTokenId() - { - return md5(random_bytes(32)); - } - - /** - * Get validation token - * - * Retrieve token from session, if it exists. - * - * @param string $tokenId - * @return null|string - */ - protected function getValidationToken($tokenId = null) - { - $session = $this->getSession(); - - /** - * if no tokenId is passed we revert to the old behaviour - * - * @todo remove, here for BC - */ - if (! $tokenId && isset($session->hash)) { - return $session->hash; - } - - if ($tokenId && isset($session->tokenList[$tokenId])) { - return $this->formatHash($session->tokenList[$tokenId], $tokenId); - } - - return null; - } - - /** - * @return string - */ - protected function formatHash(string $token, string $tokenId) - { - return sprintf('%s-%s', $token, $tokenId); - } - - protected function getTokenFromHash(?string $hash): ?string - { - if (null === $hash) { - return null; - } - - $data = explode('-', $hash); - return $data[0] ?: null; - } - - protected function getTokenIdFromHash(string $hash): ?string - { - $data = explode('-', $hash); - - if (! isset($data[1])) { - return null; - } - - return $data[1]; - } -} diff --git a/lib/laminas/laminas-validator/src/Date.php b/lib/laminas/laminas-validator/src/Date.php deleted file mode 100644 index 2d85ade24..000000000 --- a/lib/laminas/laminas-validator/src/Date.php +++ /dev/null @@ -1,232 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Validator; - -use DateTime; -use DateTimeImmutable; -use DateTimeInterface; -use Traversable; - -use function array_shift; -use function func_get_args; -use function gettype; -use function implode; -use function is_array; -use function iterator_to_array; - -/** - * Validates that a given value is a DateTime instance or can be converted into one. - */ -class Date extends AbstractValidator -{ - /**#@+ - * Validity constants - */ - public const INVALID = 'dateInvalid'; - public const INVALID_DATE = 'dateInvalidDate'; - public const FALSEFORMAT = 'dateFalseFormat'; - /**#@-*/ - - /** - * Default format constant - */ - public const FORMAT_DEFAULT = 'Y-m-d'; - - /** - * Validation failure message template definitions - * - * @var string[] - */ - protected $messageTemplates = [ - self::INVALID => 'Invalid type given. String, integer, array or DateTime expected', - self::INVALID_DATE => 'The input does not appear to be a valid date', - self::FALSEFORMAT => "The input does not fit the date format '%format%'", - ]; - - /** @var string[] */ - protected $messageVariables = [ - 'format' => 'format', - ]; - - /** @var string */ - protected $format = self::FORMAT_DEFAULT; - - /** @var bool */ - protected $strict = false; - - /** - * Sets validator options - * - * @param string|array|Traversable $options OPTIONAL - */ - public function __construct($options = []) - { - if ($options instanceof Traversable) { - $options = iterator_to_array($options); - } elseif (! is_array($options)) { - $options = func_get_args(); - $temp['format'] = array_shift($options); - $options = $temp; - } - - parent::__construct($options); - } - - /** - * Returns the format option - * - * @return string - */ - public function getFormat() - { - return $this->format; - } - - /** - * Sets the format option - * - * Format cannot be null. It will always default to 'Y-m-d', even - * if null is provided. - * - * @param string|null $format - * @return $this provides a fluent interface - * @todo validate the format - */ - public function setFormat($format = self::FORMAT_DEFAULT) - { - $this->format = empty($format) ? self::FORMAT_DEFAULT : $format; - return $this; - } - - public function setStrict(bool $strict): self - { - $this->strict = $strict; - return $this; - } - - public function isStrict(): bool - { - return $this->strict; - } - - /** - * Returns true if $value is a DateTimeInterface instance or can be converted into one. - * - * @param string|numeric|array|DateTimeInterface $value - * @return bool - */ - public function isValid($value) - { - $this->setValue($value); - - $date = $this->convertToDateTime($value); - if (! $date) { - $this->error(self::INVALID_DATE); - return false; - } - - if ($this->isStrict() && $date->format($this->getFormat()) !== $value) { - $this->error(self::FALSEFORMAT); - return false; - } - - return true; - } - - /** - * Attempts to convert an int, string, or array to a DateTime object - * - * @param string|numeric|array|DateTimeInterface $param - * @param bool $addErrors - * @return false|DateTime - */ - protected function convertToDateTime($param, $addErrors = true) - { - if ($param instanceof DateTime) { - return $param; - } - - if ($param instanceof DateTimeImmutable) { - return DateTime::createFromImmutable($param); - } - - $type = gettype($param); - switch ($type) { - case 'string': - return $this->convertString($param, $addErrors); - case 'integer': - return $this->convertInteger($param); - case 'double': - return $this->convertDouble($param); - case 'array': - return $this->convertArray($param, $addErrors); - } - - if ($addErrors) { - $this->error(self::INVALID); - } - - return false; - } - - /** - * Attempts to convert an integer into a DateTime object - * - * @param integer $value - * @return false|DateTime - */ - protected function convertInteger($value) - { - return DateTime::createFromFormat('U', (string) $value); - } - - /** - * Attempts to convert an double into a DateTime object - * - * @param double $value - * @return false|DateTime - */ - protected function convertDouble($value) - { - return DateTime::createFromFormat('U', (string) $value); - } - - /** - * Attempts to convert a string into a DateTime object - * - * @param string $value - * @param bool $addErrors - * @return false|DateTime - */ - protected function convertString($value, $addErrors = true) - { - $date = DateTime::createFromFormat($this->format, $value); - - // Invalid dates can show up as warnings (ie. "2007-02-99") - // and still return a DateTime object. - $errors = DateTime::getLastErrors(); - if ($errors['warning_count'] > 0) { - if ($addErrors) { - $this->error(self::FALSEFORMAT); - } - return false; - } - - return $date; - } - - /** - * Implodes the array into a string and proxies to {@link convertString()}. - * - * @param array $value - * @param bool $addErrors - * @return false|DateTime - * @todo enhance the implosion - */ - protected function convertArray(array $value, $addErrors = true) - { - return $this->convertString(implode('-', $value), $addErrors); - } -} diff --git a/lib/laminas/laminas-validator/src/DateStep.php b/lib/laminas/laminas-validator/src/DateStep.php deleted file mode 100644 index 2ec86dac0..000000000 --- a/lib/laminas/laminas-validator/src/DateStep.php +++ /dev/null @@ -1,525 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Laminas\Validator; - -use DateInterval; -use DateTime; -use DateTimeImmutable; -use DateTimeInterface; -use DateTimeZone; -use Laminas\Stdlib\ArrayUtils; -use Traversable; - -use function array_combine; -use function array_count_values; -use function array_map; -use function array_shift; -use function ceil; -use function date_default_timezone_get; -use function explode; -use function floor; -use function func_get_args; -use function in_array; -use function is_array; -use function max; -use function min; -use function preg_match; -use function sprintf; -use function strpos; - -use const PHP_INT_MAX; - -class DateStep extends Date -{ - /** - * Validity constants - */ - public const NOT_STEP = 'dateStepNotStep'; - - /** - * Default format constant - */ - public const FORMAT_DEFAULT = DateTime::ISO8601; - - /** - * Validation failure message template definitions - * - * @var string[] - */ - protected $messageTemplates = [ - self::INVALID => 'Invalid type given. String, integer, array or DateTime expected', - self::INVALID_DATE => 'The input does not appear to be a valid date', - self::FALSEFORMAT => "The input does not fit the date format '%format%'", - self::NOT_STEP => 'The input is not a valid step', - ]; - - /** - * Optional base date value - * - * @var string|int|DateTimeInterface - */ - protected $baseValue = '1970-01-01T00:00:00Z'; - - /** - * Date step interval (defaults to 1 day). - * Uses the DateInterval specification. - * - * @var DateInterval - */ - protected $step; - - /** - * Optional timezone to be used when the baseValue - * and validation values do not contain timezone info - * - * @var DateTimeZone - */ - protected $timezone; - - /** - * Set default options for this instance - * - * @param string|array|Traversable $options - */ - public function __construct($options = []) - { - if ($options instanceof Traversable) { - $options = ArrayUtils::iteratorToArray($options); - } elseif (! is_array($options)) { - $options = func_get_args(); - $temp = []; - $temp['baseValue'] = array_shift($options); - if (! empty($options)) { - $temp['step'] = array_shift($options); - } - if (! empty($options)) { - $temp['format'] = array_shift($options); - } - if (! empty($options)) { - $temp['timezone'] = array_shift($options); - } - - $options = $temp; - } - - if (! isset($options['step'])) { - $options['step'] = new DateInterval('P1D'); - } - if (! isset($options['timezone'])) { - $options['timezone'] = new DateTimeZone(date_default_timezone_get()); - } - - parent::__construct($options); - } - - /** - * Sets the base value from which the step should be computed - * - * @param string|int|DateTimeInterface $baseValue - * @return $this - */ - public function setBaseValue($baseValue) - { - $this->baseValue = $baseValue; - return $this; - } - - /** - * Returns the base value from which the step should be computed - * - * @return string|int|DateTimeInterface - */ - public function getBaseValue() - { - return $this->baseValue; - } - - /** - * Sets the step date interval - * - * @return $this - */ - public function setStep(DateInterval $step) - { - $this->step = $step; - return $this; - } - - /** - * Returns the step date interval - * - * @return DateInterval - */ - public function getStep() - { - return $this->step; - } - - /** - * Returns the timezone option - * - * @return DateTimeZone - */ - public function getTimezone() - { - return $this->timezone; - } - - /** - * Sets the timezone option - * - * @return $this - */ - public function setTimezone(DateTimeZone $timezone) - { - $this->timezone = $timezone; - return $this; - } - - /** - * Supports formats with ISO week (W) definitions - * - * @see Date::convertString() - * - * @param string $value - * @param bool $addErrors - * @return DateTime|false - */ - protected function convertString($value, $addErrors = true) - { - // Custom week format support - if ( - strpos($this->format, 'Y-\WW') === 0 - && preg_match('/^([0-9]{4})\-W([0-9]{2})/', $value, $matches) - ) { - $date = new DateTime(); - $date->setISODate((int) $matches[1], (int) $matches[2]); - } else { - $date = DateTime::createFromFormat($this->format, $value, new DateTimeZone('UTC')); - } - - // Invalid dates can show up as warnings (ie. "2007-02-99") - // and still return a DateTime object. - $errors = DateTime::getLastErrors(); - if ($errors['warning_count'] > 0) { - if ($addErrors) { - $this->error(self::FALSEFORMAT); - } - return false; - } - - return $date; - } - - /** - * Returns true if a date is within a valid step - * - * @param string|int|DateTimeInterface $value - * @return bool - * @throws Exception\InvalidArgumentException - */ - public function isValid($value) - { - if (! parent::isValid($value)) { - return false; - } - - $valueDate = $this->convertToDateTime($value, false); // avoid duplicate errors - $baseDate = $this->convertToDateTime($this->baseValue, false); - - if (false === $valueDate || false === $baseDate) { - return false; - } - - $step = $this->getStep(); - - // Same date? - // phpcs:ignore SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedEqualOperator - if ($valueDate == $baseDate) { - return true; - } - - // Optimization for simple intervals. - // Handle intervals of just one date or time unit. - $intervalParts = explode('|', $step->format('%y|%m|%d|%h|%i|%s')); - $intervalParts = array_map('intval', $intervalParts); - $partCounts = array_count_values($intervalParts); - - $unitKeys = ['years', 'months', 'days', 'hours', 'minutes', 'seconds']; - $intervalParts = array_combine($unitKeys, $intervalParts); - - // Get absolute time difference to avoid special cases of missing/added time - $absoluteValueDate = new DateTime($valueDate->format('Y-m-d H:i:s'), new DateTimeZone('UTC')); - $absoluteBaseDate = new DateTime($baseDate->format('Y-m-d H:i:s'), new DateTimeZone('UTC')); - - $timeDiff = $absoluteValueDate->diff($absoluteBaseDate, true); - $diffParts = array_map('intval', explode('|', $timeDiff->format('%y|%m|%d|%h|%i|%s'))); - $diffParts = array_combine($unitKeys, $diffParts); - - if (5 === $partCounts[0]) { - // Find the unit with the non-zero interval - $intervalUnit = 'days'; - $stepValue = 1; - foreach ($intervalParts as $key => $value) { - if (0 !== $value) { - $intervalUnit = $key; - $stepValue = $value; - break; - } - } - - // Check date units - if (in_array($intervalUnit, ['years', 'months', 'days'])) { - switch ($intervalUnit) { - case 'years': - if ( - 0 === $diffParts['months'] && 0 === $diffParts['days'] - && 0 === $diffParts['hours'] && 0 === $diffParts['minutes'] - && 0 === $diffParts['seconds'] - ) { - if (($diffParts['years'] % $stepValue) === 0) { - return true; - } - } - break; - case 'months': - if ( - 0 === $diffParts['days'] && 0 === $diffParts['hours'] - && 0 === $diffParts['minutes'] && 0 === $diffParts['seconds'] - ) { - $months = ($diffParts['years'] * 12) + $diffParts['months']; - if (($months % $stepValue) === 0) { - return true; - } - } - break; - case 'days': - if ( - 0 === $diffParts['hours'] && 0 === $diffParts['minutes'] - && 0 === $diffParts['seconds'] - ) { - $days = (int) $timeDiff->format('%a'); // Total days - if (($days % $stepValue) === 0) { - return true; - } - } - break; - } - $this->error(self::NOT_STEP); - return false; - } - - // Check time units - if (in_array($intervalUnit, ['hours', 'minutes', 'seconds'])) { - // Simple test if $stepValue is 1. - if (1 === $stepValue) { - if ( - 'hours' === $intervalUnit - && 0 === $diffParts['minutes'] && 0 === $diffParts['seconds'] - ) { - return true; - } elseif ('minutes' === $intervalUnit && 0 === $diffParts['seconds']) { - return true; - } elseif ('seconds' === $intervalUnit) { - return true; - } - - $this->error(self::NOT_STEP); - - return false; - } - - // Simple test for same day, when using default baseDate - if ( - $baseDate->format('Y-m-d') === $valueDate->format('Y-m-d') - && $baseDate->format('Y-m-d') === '1970-01-01' - ) { - switch ($intervalUnit) { - case 'hours': - if (0 === $diffParts['minutes'] && 0 === $diffParts['seconds']) { - if (($diffParts['hours'] % $stepValue) === 0) { - return true; - } - } - break; - case 'minutes': - if (0 === $diffParts['seconds']) { - $minutes = ($diffParts['hours'] * 60) + $diffParts['minutes']; - if (($minutes % $stepValue) === 0) { - return true; - } - } - break; - case 'seconds': - $seconds = ($diffParts['hours'] * 60 * 60) - + ($diffParts['minutes'] * 60) - + $diffParts['seconds']; - if (($seconds % $stepValue) === 0) { - return true; - } - break; - } - $this->error(self::NOT_STEP); - return false; - } - } - } - - return $this->fallbackIncrementalIterationLogic($baseDate, $valueDate, $intervalParts, $diffParts, $step); - } - - /** - * Fall back to slower (but accurate) method for complex intervals. - * Keep adding steps to the base date until a match is found - * or until the value is exceeded. - * - * This is really slow if the interval is small, especially if the - * default base date of 1/1/1970 is used. We can skip a chunk of - * iterations by starting at the lower bound of steps needed to reach - * the target - * - * @param int[] $intervalParts - * @param int[] $diffParts - * @throws Exception\InvalidArgumentException - */ - private function fallbackIncrementalIterationLogic( - DateTimeInterface $baseDate, - DateTimeInterface $valueDate, - array $intervalParts, - array $diffParts, - DateInterval $step - ): bool { - [$minSteps, $requiredIterations] = $this->computeMinStepAndRequiredIterations($intervalParts, $diffParts); - $minimumInterval = $this->computeMinimumInterval($intervalParts, $minSteps); - $isIncrementalStepping = $baseDate < $valueDate; - - if (! ($baseDate instanceof DateTime || $baseDate instanceof DateTimeImmutable)) { - throw new Exception\InvalidArgumentException(sprintf( - 'Function %s requires the baseDate to be a DateTime or DateTimeImmutable instance.', - __FUNCTION__ - )); - } - - for ($offsetIterations = 0; $offsetIterations < $requiredIterations; $offsetIterations += 1) { - if ($isIncrementalStepping) { - $baseDate = $baseDate->add($minimumInterval); - } else { - $baseDate = $baseDate->sub($minimumInterval); - } - } - - while ( - ($isIncrementalStepping && $baseDate < $valueDate) - || (! $isIncrementalStepping && $baseDate > $valueDate) - ) { - if ($isIncrementalStepping) { - $baseDate = $baseDate->add($step); - } else { - $baseDate = $baseDate->sub($step); - } - - // phpcs:ignore SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedEqualOperator - if ($baseDate == $valueDate) { - return true; - } - } - - $this->error(self::NOT_STEP); - - return false; - } - - /** - * Computes minimum interval to use for iterations while checking steps - * - * @param int[] $intervalParts - * @param int|float $minSteps - */ - private function computeMinimumInterval(array $intervalParts, $minSteps): DateInterval - { - return new DateInterval(sprintf( - 'P%dY%dM%dDT%dH%dM%dS', - $intervalParts['years'] * $minSteps, - $intervalParts['months'] * $minSteps, - $intervalParts['days'] * $minSteps, - $intervalParts['hours'] * $minSteps, - $intervalParts['minutes'] * $minSteps, - $intervalParts['seconds'] * $minSteps - )); - } - - /** - * @param int[] $intervalParts - * @param int[] $diffParts - * @return int[] (ordered tuple containing minimum steps and required step iterations - * @psalm-return array{0: int, 1: int} - */ - private function computeMinStepAndRequiredIterations(array $intervalParts, array $diffParts): array - { - $minSteps = $this->computeMinSteps($intervalParts, $diffParts); - - // If we use PHP_INT_MAX DateInterval::__construct falls over with a bad format error - // before we reach the max on 64 bit machines - $maxInteger = min(2 ** 31, PHP_INT_MAX); - // check for integer overflow and split $minimum interval if needed - $maximumInterval = max($intervalParts); - $requiredStepIterations = 1; - - if (($minSteps * $maximumInterval) > $maxInteger) { - $requiredStepIterations = ceil(($minSteps * $maximumInterval) / $maxInteger); - $minSteps = floor($minSteps / $requiredStepIterations); - } - - return [(int) $minSteps, $minSteps ? (int) $requiredStepIterations : 0]; - } - - /** - * Multiply the step interval by the lower bound of steps to reach the target - * - * @param int[] $intervalParts - * @param int[] $diffParts - * @return float|int - */ - private function computeMinSteps(array $intervalParts, array $diffParts) - { - $intervalMaxSeconds = $this->computeIntervalMaxSeconds($intervalParts); - - return 0 === $intervalMaxSeconds - ? 0 - : max(floor($this->computeDiffMinSeconds($diffParts) / $intervalMaxSeconds) - 1, 0); - } - - /** - * Get upper bound of the given interval in seconds - * Converts a given `$intervalParts` array into seconds - * - * @param int[] $intervalParts - */ - private function computeIntervalMaxSeconds(array $intervalParts): int - { - return ($intervalParts['years'] * 60 * 60 * 24 * 366) - + ($intervalParts['months'] * 60 * 60 * 24 * 31) - + ($intervalParts['days'] * 60 * 60 * 24) - + ($intervalParts['hours'] * 60 * 60) - + ($intervalParts['minutes'] * 60) - + $intervalParts['seconds']; - } - - /** - * Get lower bound of difference in secondss - * Converts a given `$diffParts` array into seconds - * - * @param int[] $diffParts - */ - private function computeDiffMinSeconds(array $diffParts): int - { - return ($diffParts['years'] * 60 * 60 * 24 * 365) - + ($diffParts['months'] * 60 * 60 * 24 * 28) - + ($diffParts['days'] * 60 * 60 * 24) - + ($diffParts['hours'] * 60 * 60) - + ($diffParts['minutes'] * 60) - + $diffParts['seconds']; - } -} diff --git a/lib/laminas/laminas-validator/src/Db/AbstractDb.php b/lib/laminas/laminas-validator/src/Db/AbstractDb.php deleted file mode 100755 index 495cdf113..000000000 --- a/lib/laminas/laminas-validator/src/Db/AbstractDb.php +++ /dev/null @@ -1,315 +0,0 @@ -<?php - -namespace Laminas\Validator\Db; - -use Laminas\Db\Adapter\Adapter as DbAdapter; -use Laminas\Db\Adapter\AdapterAwareInterface; -use Laminas\Db\Adapter\AdapterAwareTrait; -use Laminas\Db\Sql\Select; -use Laminas\Db\Sql\Sql; -use Laminas\Db\Sql\TableIdentifier; -use Laminas\Stdlib\ArrayUtils; -use Laminas\Validator\AbstractValidator; -use Laminas\Validator\Exception; -use Laminas\Validator\Exception\InvalidArgumentException; -use Laminas\Validator\Exception\RuntimeException; -use Traversable; - -use function array_key_exists; -use function array_shift; -use function func_get_args; -use function func_num_args; -use function is_array; - -/** - * Class for Database record validation - */ -abstract class AbstractDb extends AbstractValidator implements AdapterAwareInterface -{ - use AdapterAwareTrait; - - /** - * Error constants - */ - public const ERROR_NO_RECORD_FOUND = 'noRecordFound'; - public const ERROR_RECORD_FOUND = 'recordFound'; - - /** @var array<string, string> Message templates */ - protected $messageTemplates = [ - self::ERROR_NO_RECORD_FOUND => 'No record matching the input was found', - self::ERROR_RECORD_FOUND => 'A record matching the input was found', - ]; - - /** - * Select object to use. can be set, or will be auto-generated - * - * @var Select - */ - protected $select; - - /** @var string */ - protected $schema; - - /** @var string */ - protected $table = ''; - - /** @var string */ - protected $field = ''; - - /** @var mixed */ - protected $exclude; - - /** - * Provides basic configuration for use with Laminas\Validator\Db Validators - * Setting $exclude allows a single record to be excluded from matching. - * Exclude can either be a String containing a where clause, or an array with `field` and `value` keys - * to define the where clause added to the sql. - * A database adapter may optionally be supplied to avoid using the registered default adapter. - * - * The following option keys are supported: - * 'table' => The database table to validate against - * 'schema' => The schema keys - * 'field' => The field to check for a match - * 'exclude' => An optional where clause or field/value pair to exclude from the query - * 'adapter' => An optional database adapter to use - * - * @param array|Traversable|Select $options Options to use for this validator - * @throws InvalidArgumentException - */ - public function __construct($options = null) - { - parent::__construct($options); - - if ($options instanceof Select) { - $this->setSelect($options); - return; - } - - if ($options instanceof Traversable) { - $options = ArrayUtils::iteratorToArray($options); - } elseif (func_num_args() > 1) { - $options = func_get_args(); - $firstArgument = array_shift($options); - if (is_array($firstArgument)) { - $temp = ArrayUtils::iteratorToArray($firstArgument); - } else { - $temp['table'] = $firstArgument; - } - - $temp['field'] = array_shift($options); - - if (! empty($options)) { - $temp['exclude'] = array_shift($options); - } - - if (! empty($options)) { - $temp['adapter'] = array_shift($options); - } - - $options = $temp; - } - - if (! array_key_exists('table', $options) && ! array_key_exists('schema', $options)) { - throw new Exception\InvalidArgumentException('Table or Schema option missing!'); - } - - if (! array_key_exists('field', $options)) { - throw new Exception\InvalidArgumentException('Field option missing!'); - } - - if (array_key_exists('adapter', $options)) { - $this->setAdapter($options['adapter']); - } - - if (array_key_exists('exclude', $options)) { - $this->setExclude($options['exclude']); - } - - $this->setField($options['field']); - if (array_key_exists('table', $options)) { - $this->setTable($options['table']); - } - - if (array_key_exists('schema', $options)) { - $this->setSchema($options['schema']); - } - } - - /** - * Returns the set adapter - * - * @throws RuntimeException When no database adapter is defined. - * @return DbAdapter - */ - public function getAdapter() - { - return $this->adapter; - } - - /** - * Sets a new database adapter - * - * @return self Provides a fluent interface - */ - public function setAdapter(DbAdapter $adapter) - { - return $this->setDbAdapter($adapter); - } - - /** - * Returns the set exclude clause - * - * @return string|array - */ - public function getExclude() - { - return $this->exclude; - } - - /** - * Sets a new exclude clause - * - * @param string|array $exclude - * @return $this Provides a fluent interface - */ - public function setExclude($exclude) - { - $this->exclude = $exclude; - $this->select = null; - return $this; - } - - /** - * Returns the set field - * - * @return string|array - */ - public function getField() - { - return $this->field; - } - - /** - * Sets a new field - * - * @param string $field - * @return $this - */ - public function setField($field) - { - $this->field = (string) $field; - $this->select = null; - return $this; - } - - /** - * Returns the set table - * - * @return string - */ - public function getTable() - { - return $this->table; - } - - /** - * Sets a new table - * - * @param string $table - * @return $this Provides a fluent interface - */ - public function setTable($table) - { - $this->table = (string) $table; - $this->select = null; - return $this; - } - - /** - * Returns the set schema - * - * @return string - */ - public function getSchema() - { - return $this->schema; - } - - /** - * Sets a new schema - * - * @param string $schema - * @return $this Provides a fluent interface - */ - public function setSchema($schema) - { - $this->schema = $schema; - $this->select = null; - return $this; - } - - /** - * Sets the select object to be used by the validator - * - * @return $this Provides a fluent interface - */ - public function setSelect(Select $select) - { - $this->select = $select; - return $this; - } - - /** - * Gets the select object to be used by the validator. - * If no select object was supplied to the constructor, - * then it will auto-generate one from the given table, - * schema, field, and adapter options. - * - * @return Select The Select object which will be used - */ - public function getSelect() - { - if ($this->select instanceof Select) { - return $this->select; - } - - // Build select object - $select = new Select(); - $tableIdentifier = new TableIdentifier($this->table, $this->schema); - $select->from($tableIdentifier)->columns([$this->field]); - $select->where->equalTo($this->field, null); - - if ($this->exclude !== null) { - if (is_array($this->exclude)) { - $select->where->notEqualTo( - $this->exclude['field'], - $this->exclude['value'] - ); - } else { - $select->where($this->exclude); - } - } - - $this->select = $select; - - return $this->select; - } - - /** - * Run query and returns matches, or null if no matches are found. - * - * @param string $value - * @return array when matches are found. - */ - protected function query($value) - { - $sql = new Sql($this->getAdapter()); - $select = $this->getSelect(); - $statement = $sql->prepareStatementForSqlObject($select); - $parameters = $statement->getParameterContainer(); - $parameters['where1'] = $value; - $result = $statement->execute(); - - return $result->current(); - } -} diff --git a/lib/laminas/laminas-validator/src/Db/NoRecordExists.php b/lib/laminas/laminas-validator/src/Db/NoRecordExists.php deleted file mode 100644 index 573a81ff8..000000000 --- a/lib/laminas/laminas-validator/src/Db/NoRecordExists.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -namespace Laminas\Validator\Db; - -use Laminas\Validator\Exception; - -/** - * Confirms a record does not exist in a table. - */ -class NoRecordExists extends AbstractDb -{ - /** - * @param mixed $value - * @return bool - */ - public function isValid($value) - { - /* - * Check for an adapter being defined. If not, throw an exception. - */ - if (null === $this->adapter) { - throw new Exception\RuntimeException('No database adapter present'); - } - - $valid = true; - $this->setValue($value); - - $result = $this->query($value); - if ($result) { - $valid = false; - $this->error(self::ERROR_RECORD_FOUND); - } - - return $valid; - } -} diff --git a/lib/laminas/laminas-validator/src/Db/RecordExists.php b/lib/laminas/laminas-validator/src/Db/RecordExists.php deleted file mode 100644 index bbc57db21..000000000 --- a/lib/laminas/laminas-validator/src/Db/RecordExists.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -namespace Laminas\Validator\Db; - -use Laminas\Validator\Exception; - -/** - * Confirms a record exists in a table. - */ -class RecordExists extends AbstractDb -{ - /** - * @param mixed $value - * @return bool - */ - public function isValid($value) - { - /* - * Check for an adapter being defined. If not, throw an exception. - */ - if (null === $this->adapter) { - throw new Exception\RuntimeException('No database adapter present'); - } - - $valid = true; - $this->setValue($value); - - $result = $this->query($value); - if (! $result) { - $valid = false; - $this->error(self::ERROR_NO_RECORD_FOUND); - } - - return $valid; - } -} diff --git a/lib/laminas/laminas-validator/src/Digits.php b/lib/laminas/laminas-validator/src/Digits.php deleted file mode 100644 index 34568a5c5..000000000 --- a/lib/laminas/laminas-validator/src/Digits.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use Laminas\Filter\Digits as DigitsFilter; - -use function is_float; -use function is_int; -use function is_string; - -class Digits extends AbstractValidator -{ - public const NOT_DIGITS = 'notDigits'; - public const STRING_EMPTY = 'digitsStringEmpty'; - public const INVALID = 'digitsInvalid'; - - /** - * Digits filter used for validation - * - * @var DigitsFilter - */ - protected static $filter; - - /** - * Validation failure message template definitions - * - * @var array - */ - protected $messageTemplates = [ - self::NOT_DIGITS => 'The input must contain only digits', - self::STRING_EMPTY => 'The input is an empty string', - self::INVALID => 'Invalid type given. String, integer or float expected', - ]; - - /** - * Returns true if and only if $value only contains digit characters - * - * @param string $value - * @return bool - */ - public function isValid($value) - { - if (! is_string($value) && ! is_int($value) && ! is_float($value)) { - $this->error(self::INVALID); - return false; - } - - $this->setValue((string) $value); - - if ('' === $this->getValue()) { - $this->error(self::STRING_EMPTY); - return false; - } - - if (null === static::$filter) { - static::$filter = new DigitsFilter(); - } - - if ($this->getValue() !== static::$filter->filter($this->getValue())) { - $this->error(self::NOT_DIGITS); - return false; - } - - return true; - } -} diff --git a/lib/laminas/laminas-validator/src/EmailAddress.php b/lib/laminas/laminas-validator/src/EmailAddress.php deleted file mode 100644 index e03070deb..000000000 --- a/lib/laminas/laminas-validator/src/EmailAddress.php +++ /dev/null @@ -1,617 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use Traversable; -use UConverter; - -use function array_combine; -use function array_flip; -use function array_keys; -use function array_shift; -use function arsort; -use function checkdnsrr; -use function defined; -use function extension_loaded; -use function func_get_args; -use function function_exists; -use function gethostbynamel; -use function getmxrr; -use function idn_to_ascii; -use function idn_to_utf8; -use function is_array; -use function is_string; -use function preg_match; -use function strlen; -use function strpos; -use function trim; - -use const INTL_IDNA_VARIANT_UTS46; - -class EmailAddress extends AbstractValidator -{ - public const INVALID = 'emailAddressInvalid'; - public const INVALID_FORMAT = 'emailAddressInvalidFormat'; - public const INVALID_HOSTNAME = 'emailAddressInvalidHostname'; - public const INVALID_MX_RECORD = 'emailAddressInvalidMxRecord'; - public const INVALID_SEGMENT = 'emailAddressInvalidSegment'; - public const DOT_ATOM = 'emailAddressDotAtom'; - public const QUOTED_STRING = 'emailAddressQuotedString'; - public const INVALID_LOCAL_PART = 'emailAddressInvalidLocalPart'; - public const LENGTH_EXCEEDED = 'emailAddressLengthExceeded'; - - // phpcs:disable Generic.Files.LineLength.TooLong - - /** @var array<string, string> */ - protected $messageTemplates = [ - self::INVALID => "Invalid type given. String expected", - self::INVALID_FORMAT => "The input is not a valid email address. Use the basic format local-part@hostname", - self::INVALID_HOSTNAME => "'%hostname%' is not a valid hostname for the email address", - self::INVALID_MX_RECORD => "'%hostname%' does not appear to have any valid MX or A records for the email address", - self::INVALID_SEGMENT => "'%hostname%' is not in a routable network segment. The email address should not be resolved from public network", - self::DOT_ATOM => "'%localPart%' can not be matched against dot-atom format", - self::QUOTED_STRING => "'%localPart%' can not be matched against quoted-string format", - self::INVALID_LOCAL_PART => "'%localPart%' is not a valid local part for the email address", - self::LENGTH_EXCEEDED => "The input exceeds the allowed length", - ]; - - // phpcs:enable - - /** @var array */ - protected $messageVariables = [ - 'hostname' => 'hostname', - 'localPart' => 'localPart', - ]; - - /** @var string */ - protected $hostname; - - /** @var string */ - protected $localPart; - - /** - * Returns the found mx record information - * - * @var array - */ - protected $mxRecord = []; - - /** - * Internal options array - * - * @var array<string, mixed> - */ - protected $options = [ - 'useMxCheck' => false, - 'useDeepMxCheck' => false, - 'useDomainCheck' => true, - 'allow' => Hostname::ALLOW_DNS, - 'strict' => true, - 'hostnameValidator' => null, - ]; - - /** - * Instantiates hostname validator for local use - * - * The following additional option keys are supported: - * 'hostnameValidator' => A hostname validator, see Laminas\Validator\Hostname - * 'allow' => Options for the hostname validator, see Laminas\Validator\Hostname::ALLOW_* - * 'strict' => Whether to adhere to strictest requirements in the spec - * 'useMxCheck' => If MX check should be enabled, boolean - * 'useDeepMxCheck' => If a deep MX check should be done, boolean - * - * @param array|Traversable $options OPTIONAL - */ - public function __construct($options = []) - { - if (! is_array($options)) { - $options = func_get_args(); - $temp['allow'] = array_shift($options); - if (! empty($options)) { - $temp['useMxCheck'] = array_shift($options); - } - - if (! empty($options)) { - $temp['hostnameValidator'] = array_shift($options); - } - - $options = $temp; - } - - parent::__construct($options); - } - - /** - * Sets the validation failure message template for a particular key - * Adds the ability to set messages to the attached hostname validator - * - * @param string $messageString - * @param string $messageKey OPTIONAL - * @return AbstractValidator Provides a fluent interface - */ - public function setMessage($messageString, $messageKey = null) - { - if ($messageKey === null) { - $this->getHostnameValidator()->setMessage($messageString); - parent::setMessage($messageString); - return $this; - } - - if (! isset($this->messageTemplates[$messageKey])) { - $this->getHostnameValidator()->setMessage($messageString, $messageKey); - } else { - parent::setMessage($messageString, $messageKey); - } - - return $this; - } - - /** - * Returns the set hostname validator - * - * If was not previously set then lazy load a new one - * - * @return Hostname - */ - public function getHostnameValidator() - { - if (! isset($this->options['hostnameValidator'])) { - $this->options['hostnameValidator'] = new Hostname($this->getAllow()); - } - - return $this->options['hostnameValidator']; - } - - /** - * @param Hostname $hostnameValidator OPTIONAL - * @return $this Provides a fluent interface - */ - public function setHostnameValidator(?Hostname $hostnameValidator = null) - { - $this->options['hostnameValidator'] = $hostnameValidator; - - return $this; - } - - /** - * Returns the allow option of the attached hostname validator - * - * @return int - */ - public function getAllow() - { - return $this->options['allow']; - } - - /** - * Sets the allow option of the hostname validator to use - * - * @param int $allow - * @return $this Provides a fluent interface - */ - public function setAllow($allow) - { - $this->options['allow'] = $allow; - if (isset($this->options['hostnameValidator'])) { - $this->options['hostnameValidator']->setAllow($allow); - } - - return $this; - } - - /** - * Whether MX checking via getmxrr is supported or not - * - * @return bool - */ - public function isMxSupported() - { - return function_exists('getmxrr'); - } - - /** - * Returns the set validateMx option - * - * @return bool - */ - public function getMxCheck() - { - return $this->options['useMxCheck']; - } - - /** - * Set whether we check for a valid MX record via DNS - * - * This only applies when DNS hostnames are validated - * - * @param bool $mx Set allowed to true to validate for MX records, and false to not validate them - * @return $this Fluid Interface - */ - public function useMxCheck($mx) - { - $this->options['useMxCheck'] = (bool) $mx; - return $this; - } - - /** - * Returns the set deepMxCheck option - * - * @return bool - */ - public function getDeepMxCheck() - { - return $this->options['useDeepMxCheck']; - } - - /** - * Use deep validation for MX records - * - * @param bool $deep Set deep to true to perform a deep validation process for MX records - * @return $this Fluid Interface - */ - public function useDeepMxCheck($deep) - { - $this->options['useDeepMxCheck'] = (bool) $deep; - return $this; - } - - /** - * Returns the set domainCheck option - * - * @return bool - */ - public function getDomainCheck() - { - return $this->options['useDomainCheck']; - } - - /** - * Sets if the domain should also be checked - * or only the local part of the email address - * - * @param bool $domain - * @return $this Fluid Interface - */ - public function useDomainCheck($domain = true) - { - $this->options['useDomainCheck'] = (bool) $domain; - return $this; - } - - /** - * Returns if the given host is reserved - * - * The following addresses are seen as reserved - * '0.0.0.0/8', '10.0.0.0/8', '127.0.0.0/8' - * '100.64.0.0/10' - * '172.16.0.0/12' - * '198.18.0.0/15' - * '169.254.0.0/16', '192.168.0.0/16' - * '192.0.2.0/24', '192.88.99.0/24', '198.51.100.0/24', '203.0.113.0/24' - * '224.0.0.0/4', '240.0.0.0/4' - * - * @see http://en.wikipedia.org/wiki/Reserved_IP_addresses - * - * As of RFC5753 (JAN 2010), the following blocks are no longer reserved: - * - 128.0.0.0/16 - * - 191.255.0.0/16 - * - 223.255.255.0/24 - * @see http://tools.ietf.org/html/rfc5735#page-6 - * - * As of RFC6598 (APR 2012), the following blocks are now reserved: - * - 100.64.0.0/10 - * @see http://tools.ietf.org/html/rfc6598#section-7 - * - * @param string $host - * @return bool Returns false when minimal one of the given addresses is not reserved - */ - protected function isReserved($host) - { - if (! preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $host)) { - $host = gethostbynamel($host); - } else { - $host = [$host]; - } - - if (empty($host)) { - return false; - } - - foreach ($host as $server) { - // @codingStandardsIgnoreStart - // Search for 0.0.0.0/8, 10.0.0.0/8, 127.0.0.0/8 - if (!preg_match('/^(0|10|127)(\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))){3}$/', $server) && - // Search for 100.64.0.0/10 - !preg_match('/^100\.(6[0-4]|[7-9][0-9]|1[0-1][0-9]|12[0-7])(\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))){2}$/', $server) && - // Search for 172.16.0.0/12 - !preg_match('/^172\.(1[6-9]|2[0-9]|3[0-1])(\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))){2}$/', $server) && - // Search for 198.18.0.0/15 - !preg_match('/^198\.(1[8-9])(\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))){2}$/', $server) && - // Search for 169.254.0.0/16, 192.168.0.0/16 - !preg_match('/^(169\.254|192\.168)(\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))){2}$/', $server) && - // Search for 192.0.2.0/24, 192.88.99.0/24, 198.51.100.0/24, 203.0.113.0/24 - !preg_match('/^(192\.0\.2|192\.88\.99|198\.51\.100|203\.0\.113)\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))$/', $server) && - // Search for 224.0.0.0/4, 240.0.0.0/4 - !preg_match('/^(2(2[4-9]|[3-4][0-9]|5[0-5]))(\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))){3}$/', $server) - ) { - return false; - } - // @codingStandardsIgnoreEnd - } - - return true; - } - - /** - * Internal method to validate the local part of the email address - * - * @return bool - */ - protected function validateLocalPart() - { - // First try to match the local part on the common dot-atom format - - // Dot-atom characters are: 1*atext *("." 1*atext) - // atext: ALPHA / DIGIT / and "!", "#", "$", "%", "&", "'", "*", - // "+", "-", "/", "=", "?", "^", "_", "`", "{", "|", "}", "~" - $atext = 'a-zA-Z0-9\x21\x23\x24\x25\x26\x27\x2a\x2b\x2d\x2f\x3d\x3f\x5e\x5f\x60\x7b\x7c\x7d\x7e'; - if (preg_match('/^[' . $atext . ']+(\x2e+[' . $atext . ']+)*$/', $this->localPart)) { - return true; - } - - if ($this->validateInternationalizedLocalPart($this->localPart)) { - return true; - } - - // Try quoted string format (RFC 5321 Chapter 4.1.2) - - // Quoted-string characters are: DQUOTE *(qtext/quoted-pair) DQUOTE - $qtext = '\x20-\x21\x23-\x5b\x5d-\x7e'; // %d32-33 / %d35-91 / %d93-126 - $quotedPair = '\x20-\x7e'; // %d92 %d32-126 - if (preg_match('/^"([' . $qtext . ']|\x5c[' . $quotedPair . '])*"$/', $this->localPart)) { - return true; - } - - $this->error(self::DOT_ATOM); - $this->error(self::QUOTED_STRING); - $this->error(self::INVALID_LOCAL_PART); - - return false; - } - - /** - * @param string $localPart Address local part to validate. - * @return bool - */ - protected function validateInternationalizedLocalPart($localPart) - { - if ( - extension_loaded('intl') - && false === UConverter::transcode($localPart, 'UTF-8', 'UTF-8') - ) { - // invalid utf? - return false; - } - - $atext = 'a-zA-Z0-9\x21\x23\x24\x25\x26\x27\x2a\x2b\x2d\x2f\x3d\x3f\x5e\x5f\x60\x7b\x7c\x7d\x7e'; - // RFC 6532 extends atext to include non-ascii utf - // @see https://tools.ietf.org/html/rfc6532#section-3.1 - $uatext = $atext . '\x{80}-\x{FFFF}'; - return (bool) preg_match('/^[' . $uatext . ']+(\x2e+[' . $uatext . ']+)*$/u', $localPart); - } - - /** - * Returns the found MX Record information after validation including weight for further processing - * - * @return array - */ - public function getMXRecord() - { - return $this->mxRecord; - } - - /** - * Internal method to validate the servers MX records - * - * @return bool|string[] - * @psalm-return bool|list<string> - */ - protected function validateMXRecords() - { - $mxHosts = []; - $weight = []; - $result = getmxrr($this->hostname, $mxHosts, $weight); - if (! empty($mxHosts) && ! empty($weight)) { - $this->mxRecord = array_combine($mxHosts, $weight) ?: []; - } else { - $this->mxRecord = []; - } - - arsort($this->mxRecord); - - // Fallback to IPv4 hosts if no MX record found (RFC 2821 SS 5). - if (! $result) { - $result = gethostbynamel($this->hostname); - if (is_array($result)) { - $this->mxRecord = array_flip($result); - } - } - - if (! $result) { - $this->error(self::INVALID_MX_RECORD); - return $result; - } - - if (! $this->options['useDeepMxCheck']) { - return $result; - } - - $validAddress = false; - $reserved = true; - foreach (array_keys($this->mxRecord) as $hostname) { - $res = $this->isReserved($hostname); - if (! $res) { - $reserved = false; - } - - if (! is_string($hostname) || ! trim($hostname)) { - continue; - } - - if ( - ! $res - && (checkdnsrr($hostname, 'A') - || checkdnsrr($hostname, 'AAAA') - || checkdnsrr($hostname, 'A6')) - ) { - $validAddress = true; - break; - } - } - - if (! $validAddress) { - $result = false; - $error = $reserved ? self::INVALID_SEGMENT : self::INVALID_MX_RECORD; - $this->error($error); - } - - return $result; - } - - /** - * Internal method to validate the hostname part of the email address - * - * @return bool|string[] - * @psalm-return bool|list<string> - */ - protected function validateHostnamePart() - { - $hostname = $this->getHostnameValidator()->setTranslator($this->getTranslator()) - ->isValid($this->hostname); - if (! $hostname) { - $this->error(self::INVALID_HOSTNAME); - // Get messages and errors from hostnameValidator - foreach ($this->getHostnameValidator()->getMessages() as $code => $message) { - $this->abstractOptions['messages'][$code] = $message; - } - } elseif ($this->options['useMxCheck']) { - // MX check on hostname - $hostname = $this->validateMXRecords(); - } - - return $hostname; - } - - /** - * Splits the given value in hostname and local part of the email address - * - * @param string $value Email address to be split - * @return bool Returns false when the email can not be split - */ - protected function splitEmailParts($value) - { - $value = is_string($value) ? $value : ''; - - // Split email address up and disallow '..' - if ( - strpos($value, '..') !== false - || ! preg_match('/^(.+)@([^@]+)$/', $value, $matches) - ) { - return false; - } - - $this->localPart = $matches[1]; - $this->hostname = $this->idnToAscii($matches[2]); - - return true; - } - - /** - * Defined by Laminas\Validator\ValidatorInterface - * - * Returns true if and only if $value is a valid email address - * according to RFC2822 - * - * @link http://www.ietf.org/rfc/rfc2822.txt RFC2822 - * @link http://www.columbia.edu/kermit/ascii.html US-ASCII characters - * - * @param string $value - * @return bool - */ - public function isValid($value) - { - if (! is_string($value)) { - $this->error(self::INVALID); - return false; - } - - $length = true; - $this->setValue($value); - - // Split email address up and disallow '..' - if (! $this->splitEmailParts($this->getValue())) { - $this->error(self::INVALID_FORMAT); - return false; - } - - if ($this->getOption('strict') && (strlen($this->localPart) > 64) || (strlen($this->hostname) > 255)) { - $length = false; - $this->error(self::LENGTH_EXCEEDED); - } - - // Match hostname part - $hostname = false; - if ($this->options['useDomainCheck']) { - $hostname = $this->validateHostnamePart(); - } - - $local = $this->validateLocalPart(); - - // If both parts valid, return true - return ($local && $length) && (! $this->options['useDomainCheck'] || $hostname); - } - - /** - * Safely convert UTF-8 encoded domain name to ASCII - * - * @param string $email the UTF-8 encoded email - * @return string - */ - protected function idnToAscii($email) - { - if (extension_loaded('intl')) { - if (defined('INTL_IDNA_VARIANT_UTS46')) { - return idn_to_ascii($email, 0, INTL_IDNA_VARIANT_UTS46) ?: $email; - } - return idn_to_ascii($email) ?: $email; - } - return $email; - } - - /** - * Safely convert ASCII encoded domain name to UTF-8 - * - * @param string $email the ASCII encoded email - * @return string - */ - protected function idnToUtf8($email) - { - if (strlen($email) === 0) { - return $email; - } - - if (extension_loaded('intl')) { - // The documentation does not clarify what kind of failure - // can happen in idn_to_utf8. One can assume if the source - // is not IDN encoded, it would fail, but it usually returns - // the source string in those cases. - // But not when the source string is long enough. - // Thus we default to source string ourselves. - if (defined('INTL_IDNA_VARIANT_UTS46')) { - return idn_to_utf8($email, 0, INTL_IDNA_VARIANT_UTS46) ?: $email; - } - return idn_to_utf8($email) ?: $email; - } - return $email; - } -} diff --git a/lib/laminas/laminas-validator/src/Exception/BadMethodCallException.php b/lib/laminas/laminas-validator/src/Exception/BadMethodCallException.php deleted file mode 100644 index 48ffcba69..000000000 --- a/lib/laminas/laminas-validator/src/Exception/BadMethodCallException.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace Laminas\Validator\Exception; - -class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-validator/src/Exception/ExceptionInterface.php b/lib/laminas/laminas-validator/src/Exception/ExceptionInterface.php deleted file mode 100644 index e5d22bb40..000000000 --- a/lib/laminas/laminas-validator/src/Exception/ExceptionInterface.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace Laminas\Validator\Exception; - -interface ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-validator/src/Exception/ExtensionNotLoadedException.php b/lib/laminas/laminas-validator/src/Exception/ExtensionNotLoadedException.php deleted file mode 100644 index b075c3197..000000000 --- a/lib/laminas/laminas-validator/src/Exception/ExtensionNotLoadedException.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace Laminas\Validator\Exception; - -class ExtensionNotLoadedException extends RuntimeException -{ -} diff --git a/lib/laminas/laminas-validator/src/Exception/InvalidArgumentException.php b/lib/laminas/laminas-validator/src/Exception/InvalidArgumentException.php deleted file mode 100644 index 3fcc1d8d5..000000000 --- a/lib/laminas/laminas-validator/src/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace Laminas\Validator\Exception; - -class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-validator/src/Exception/InvalidMagicMimeFileException.php b/lib/laminas/laminas-validator/src/Exception/InvalidMagicMimeFileException.php deleted file mode 100644 index a9b383206..000000000 --- a/lib/laminas/laminas-validator/src/Exception/InvalidMagicMimeFileException.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace Laminas\Validator\Exception; - -class InvalidMagicMimeFileException extends InvalidArgumentException -{ -} diff --git a/lib/laminas/laminas-validator/src/Exception/RuntimeException.php b/lib/laminas/laminas-validator/src/Exception/RuntimeException.php deleted file mode 100644 index 2acd6cc78..000000000 --- a/lib/laminas/laminas-validator/src/Exception/RuntimeException.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace Laminas\Validator\Exception; - -class RuntimeException extends \RuntimeException implements ExceptionInterface -{ -} diff --git a/lib/laminas/laminas-validator/src/Explode.php b/lib/laminas/laminas-validator/src/Explode.php deleted file mode 100644 index f07b1be9e..000000000 --- a/lib/laminas/laminas-validator/src/Explode.php +++ /dev/null @@ -1,204 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use Laminas\ServiceManager\ServiceManager; -use Laminas\Stdlib\ArrayUtils; -use Traversable; - -use function explode; -use function is_array; -use function is_string; -use function sprintf; - -/** - * @psalm-import-type ValidatorSpecification from ValidatorInterface - */ -class Explode extends AbstractValidator implements ValidatorPluginManagerAwareInterface -{ - public const INVALID = 'explodeInvalid'; - - /** @var null|ValidatorPluginManager */ - protected $pluginManager; - - /** @var array */ - protected $messageTemplates = [ - self::INVALID => 'Invalid type given', - ]; - - /** @var array */ - protected $messageVariables = []; - - /** @var string */ - protected $valueDelimiter = ','; - - /** @var ValidatorInterface|null */ - protected $validator; - - /** @var bool */ - protected $breakOnFirstFailure = false; - - /** - * Sets the delimiter string that the values will be split upon - * - * @param string $delimiter - * @return $this - */ - public function setValueDelimiter($delimiter) - { - $this->valueDelimiter = $delimiter; - return $this; - } - - /** - * Returns the delimiter string that the values will be split upon - * - * @return string - */ - public function getValueDelimiter() - { - return $this->valueDelimiter; - } - - /** - * Set validator plugin manager - * - * @return void - */ - public function setValidatorPluginManager(ValidatorPluginManager $pluginManager) - { - $this->pluginManager = $pluginManager; - } - - /** - * Get validator plugin manager - * - * @return ValidatorPluginManager - */ - public function getValidatorPluginManager() - { - if (! $this->pluginManager) { - $this->pluginManager = new ValidatorPluginManager(new ServiceManager()); - } - - return $this->pluginManager; - } - - /** - * Sets the Validator for validating each value - * - * @param ValidatorInterface|ValidatorSpecification $validator - * @throws Exception\RuntimeException - * @return $this - */ - public function setValidator($validator) - { - if (is_array($validator)) { - if (! isset($validator['name'])) { - throw new Exception\RuntimeException( - 'Invalid validator specification provided; does not include "name" key' - ); - } - $name = $validator['name']; - $options = $validator['options'] ?? []; - /** @psalm-suppress MixedAssignment $validator */ - $validator = $this->getValidatorPluginManager()->get($name, $options); - } - - if (! $validator instanceof ValidatorInterface) { - throw new Exception\RuntimeException( - 'Invalid validator given' - ); - } - - $this->validator = $validator; - return $this; - } - - /** - * Gets the Validator for validating each value - * - * @return ValidatorInterface|null - */ - public function getValidator() - { - return $this->validator; - } - - /** - * Set break on first failure setting - * - * @param bool $break - * @return $this - */ - public function setBreakOnFirstFailure($break) - { - $this->breakOnFirstFailure = (bool) $break; - return $this; - } - - /** - * Get break on first failure setting - * - * @return bool - */ - public function isBreakOnFirstFailure() - { - return $this->breakOnFirstFailure; - } - - /** - * Defined by Laminas\Validator\ValidatorInterface - * - * Returns true if all values validate true - * - * @param mixed $value - * @param mixed $context Extra "context" to provide the composed validator - * @return bool - * @throws Exception\RuntimeException - */ - public function isValid($value, $context = null) - { - $this->setValue($value); - - if ($value instanceof Traversable) { - $value = ArrayUtils::iteratorToArray($value); - } - - if (is_array($value)) { - $values = $value; - } elseif (is_string($value)) { - $delimiter = $this->getValueDelimiter(); - // Skip explode if delimiter is null, - // used when value is expected to be either an - // array when multiple values and a string for - // single values (ie. MultiCheckbox form behavior) - $values = null !== $delimiter - ? explode($this->valueDelimiter, $value) - : [$value]; - } else { - $values = [$value]; - } - - $validator = $this->getValidator(); - - if (! $validator) { - throw new Exception\RuntimeException(sprintf( - '%s expects a validator to be set; none given', - __METHOD__ - )); - } - - foreach ($values as $value) { - if (! $validator->isValid($value, $context)) { - $this->abstractOptions['messages'][] = $validator->getMessages(); - - if ($this->isBreakOnFirstFailure()) { - return false; - } - } - } - - return ! $this->abstractOptions['messages']; - } -} diff --git a/lib/laminas/laminas-validator/src/File/Count.php b/lib/laminas/laminas-validator/src/File/Count.php deleted file mode 100644 index 1f8ee0960..000000000 --- a/lib/laminas/laminas-validator/src/File/Count.php +++ /dev/null @@ -1,257 +0,0 @@ -<?php - -namespace Laminas\Validator\File; - -use Laminas\Validator\AbstractValidator; -use Laminas\Validator\Exception; -use Traversable; - -use function array_key_exists; -use function array_shift; -use function count; -use function dirname; -use function func_get_args; -use function func_num_args; -use function is_array; -use function is_numeric; -use function is_string; - -use const DIRECTORY_SEPARATOR; - -/** - * Validator for counting all given files - */ -class Count extends AbstractValidator -{ - /**#@+ - * - * @const string Error constants - */ - public const TOO_MANY = 'fileCountTooMany'; - public const TOO_FEW = 'fileCountTooFew'; - /**#@-*/ - - /** @var array Error message templates */ - protected $messageTemplates = [ - self::TOO_MANY => "Too many files, maximum '%max%' are allowed but '%count%' are given", - self::TOO_FEW => "Too few files, minimum '%min%' are expected but '%count%' are given", - ]; - - /** @var array Error message template variables */ - protected $messageVariables = [ - 'min' => ['options' => 'min'], - 'max' => ['options' => 'max'], - 'count' => 'count', - ]; - - /** - * Actual filecount - * - * @var int - */ - protected $count; - - /** - * Internal file array - * - * @var array - */ - protected $files; - - /** - * Options for this validator - * - * @var array - */ - protected $options = [ - 'min' => null, // Minimum file count, if null there is no minimum file count - 'max' => null, // Maximum file count, if null there is no maximum file count - ]; - - /** - * Sets validator options - * - * Min limits the file count, when used with max=null it is the maximum file count - * It also accepts an array with the keys 'min' and 'max' - * - * If $options is an integer, it will be used as maximum file count - * As Array is accepts the following keys: - * 'min': Minimum filecount - * 'max': Maximum filecount - * - * @param int|array|Traversable $options Options for the adapter - */ - public function __construct($options = null) - { - if (1 < func_num_args()) { - $args = func_get_args(); - $options = [ - 'min' => array_shift($args), - 'max' => array_shift($args), - ]; - } - - if (is_string($options) || is_numeric($options)) { - $options = ['max' => $options]; - } - - parent::__construct($options); - } - - /** - * Returns the minimum file count - * - * @return int - */ - public function getMin() - { - return $this->options['min']; - } - - /** - * Sets the minimum file count - * - * @param int|array $min The minimum file count - * @return $this Provides a fluent interface - * @throws Exception\InvalidArgumentException When min is greater than max. - */ - public function setMin($min) - { - if (is_array($min) && isset($min['min'])) { - $min = $min['min']; - } - - if (! is_numeric($min)) { - throw new Exception\InvalidArgumentException('Invalid options to validator provided'); - } - - $min = (int) $min; - if (($this->getMax() !== null) && ($min > $this->getMax())) { - throw new Exception\InvalidArgumentException( - "The minimum must be less than or equal to the maximum file count, but {$min} > {$this->getMax()}" - ); - } - - $this->options['min'] = $min; - return $this; - } - - /** - * Returns the maximum file count - * - * @return int - */ - public function getMax() - { - return $this->options['max']; - } - - /** - * Sets the maximum file count - * - * @param int|array $max The maximum file count - * @return $this Provides a fluent interface - * @throws Exception\InvalidArgumentException When max is smaller than min. - */ - public function setMax($max) - { - if (is_array($max) && isset($max['max'])) { - $max = $max['max']; - } - - if (! is_numeric($max)) { - throw new Exception\InvalidArgumentException('Invalid options to validator provided'); - } - - $max = (int) $max; - if (($this->getMin() !== null) && ($max < $this->getMin())) { - throw new Exception\InvalidArgumentException( - "The maximum must be greater than or equal to the minimum file count, but {$max} < {$this->getMin()}" - ); - } - - $this->options['max'] = $max; - return $this; - } - - /** - * Adds a file for validation - * - * @param string|array $file - * @return $this - */ - public function addFile($file) - { - if (is_string($file)) { - $file = [$file]; - } - - if (is_array($file)) { - foreach ($file as $name) { - if (! isset($this->files[$name]) && ! empty($name)) { - $this->files[$name] = $name; - } - } - } - - return $this; - } - - /** - * Returns true if and only if the file count of all checked files is at least min and - * not bigger than max (when max is not null). Attention: When checking with set min you - * must give all files with the first call, otherwise you will get a false. - * - * @param string|array $value Filenames to check for count - * @param array $file File data from \Laminas\File\Transfer\Transfer - * @return bool - */ - public function isValid($value, $file = null) - { - if (($file !== null) && ! array_key_exists('destination', $file)) { - $file['destination'] = dirname($value); - } - - if (($file !== null) && array_key_exists('tmp_name', $file)) { - $value = $file['destination'] . DIRECTORY_SEPARATOR . $file['name']; - } - - if (($file === null) || ! empty($file['tmp_name'])) { - $this->addFile($value); - } - - $this->count = count($this->files); - if (($this->getMax() !== null) && ($this->count > $this->getMax())) { - return $this->throwError($file, self::TOO_MANY); - } - - if (($this->getMin() !== null) && ($this->count < $this->getMin())) { - return $this->throwError($file, self::TOO_FEW); - } - - return true; - } - - /** - * Throws an error of the given type - * - * @param string $file - * @param string $errorType - * @return false - */ - protected function throwError($file, $errorType) - { - if ($file !== null) { - if (is_array($file)) { - if (array_key_exists('name', $file)) { - $this->value = $file['name']; - } - } elseif (is_string($file)) { - $this->value = $file; - } - } - - $this->error($errorType); - return false; - } -} diff --git a/lib/laminas/laminas-validator/src/File/Crc32.php b/lib/laminas/laminas-validator/src/File/Crc32.php deleted file mode 100644 index 94963bf1f..000000000 --- a/lib/laminas/laminas-validator/src/File/Crc32.php +++ /dev/null @@ -1,110 +0,0 @@ -<?php - -namespace Laminas\Validator\File; - -use function array_keys; -use function array_unique; -use function hash_file; -use function is_readable; - -/** - * Validator for the crc32 hash of given files - */ -class Crc32 extends Hash -{ - use FileInformationTrait; - - /** - * @const string Error constants - */ - public const DOES_NOT_MATCH = 'fileCrc32DoesNotMatch'; - public const NOT_DETECTED = 'fileCrc32NotDetected'; - public const NOT_FOUND = 'fileCrc32NotFound'; - - /** @var array Error message templates */ - protected $messageTemplates = [ - self::DOES_NOT_MATCH => 'File does not match the given crc32 hashes', - self::NOT_DETECTED => 'A crc32 hash could not be evaluated for the given file', - self::NOT_FOUND => 'File is not readable or does not exist', - ]; - - /** - * Options for this validator - * - * @var string - */ - protected $options = [ - 'algorithm' => 'crc32', - 'hash' => null, - ]; - - /** - * Returns all set crc32 hashes - * - * @return array - */ - public function getCrc32() - { - return $this->getHash(); - } - - /** - * Sets the crc32 hash for one or multiple files - * - * @param string|array $options - * @return $this Provides a fluent interface - */ - public function setCrc32($options) - { - $this->setHash($options); - return $this; - } - - /** - * Adds the crc32 hash for one or multiple files - * - * @param string|array $options - * @return $this Provides a fluent interface - */ - public function addCrc32($options) - { - $this->addHash($options); - return $this; - } - - /** - * Returns true if and only if the given file confirms the set hash - * - * @param string|array $value Filename to check for hash - * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) - * @return bool - */ - public function isValid($value, $file = null) - { - $fileInfo = $this->getFileInfo($value, $file); - - $this->setValue($fileInfo['filename']); - - // Is file readable ? - if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { - $this->error(self::NOT_FOUND); - return false; - } - - $hashes = array_unique(array_keys($this->getHash())); - $filehash = hash_file('crc32', $fileInfo['file']); - if ($filehash === false) { - $this->error(self::NOT_DETECTED); - return false; - } - - foreach ($hashes as $hash) { - if ($filehash === $hash) { - return true; - } - } - - $this->error(self::DOES_NOT_MATCH); - return false; - } -} diff --git a/lib/laminas/laminas-validator/src/File/ExcludeExtension.php b/lib/laminas/laminas-validator/src/File/ExcludeExtension.php deleted file mode 100644 index 47741fc26..000000000 --- a/lib/laminas/laminas-validator/src/File/ExcludeExtension.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php - -namespace Laminas\Validator\File; - -use function in_array; -use function is_readable; -use function strrpos; -use function strtolower; -use function substr; - -/** - * Validator for the excluding file extensions - */ -class ExcludeExtension extends Extension -{ - use FileInformationTrait; - - /** - * @const string Error constants - */ - public const FALSE_EXTENSION = 'fileExcludeExtensionFalse'; - public const NOT_FOUND = 'fileExcludeExtensionNotFound'; - - /** @var array Error message templates */ - protected $messageTemplates = [ - self::FALSE_EXTENSION => 'File has an incorrect extension', - self::NOT_FOUND => 'File is not readable or does not exist', - ]; - - /** - * Returns true if and only if the file extension of $value is not included in the - * set extension list - * - * @param string|array $value Real file to check for extension - * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) - * @return bool - */ - public function isValid($value, $file = null) - { - $fileInfo = $this->getFileInfo($value, $file); - - // Is file readable ? - if ( - ! $this->getAllowNonExistentFile() - && (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) - ) { - $this->error(self::NOT_FOUND); - return false; - } - - $this->setValue($fileInfo['filename']); - - $extension = substr($fileInfo['filename'], strrpos($fileInfo['filename'], '.') + 1); - $extensions = $this->getExtension(); - - if ($this->getCase() && (! in_array($extension, $extensions))) { - return true; - } elseif (! $this->getCase()) { - foreach ($extensions as $ext) { - if (strtolower($ext) === strtolower($extension)) { - $this->error(self::FALSE_EXTENSION); - return false; - } - } - - return true; - } - - $this->error(self::FALSE_EXTENSION); - return false; - } -} diff --git a/lib/laminas/laminas-validator/src/File/ExcludeMimeType.php b/lib/laminas/laminas-validator/src/File/ExcludeMimeType.php deleted file mode 100644 index f5a321c09..000000000 --- a/lib/laminas/laminas-validator/src/File/ExcludeMimeType.php +++ /dev/null @@ -1,97 +0,0 @@ -<?php - -namespace Laminas\Validator\File; - -use function array_merge; -use function class_exists; -use function explode; -use function finfo_file; -use function finfo_open; -use function in_array; -use function is_readable; - -use const FILEINFO_MIME_TYPE; - -/** - * Validator for the mime type of a file - */ -class ExcludeMimeType extends MimeType -{ - use FileInformationTrait; - - public const FALSE_TYPE = 'fileExcludeMimeTypeFalse'; - public const NOT_DETECTED = 'fileExcludeMimeTypeNotDetected'; - public const NOT_READABLE = 'fileExcludeMimeTypeNotReadable'; - - /** @var array Error message templates */ - protected $messageTemplates = [ - self::FALSE_TYPE => "File has an incorrect mimetype of '%type%'", - self::NOT_DETECTED => 'The mimetype could not be detected from the file', - self::NOT_READABLE => 'File is not readable or does not exist', - ]; - - /** - * Returns true if the mimetype of the file does not matche the given ones. Also parts - * of mimetypes can be checked. If you give for example "image" all image - * mime types will not be accepted like "image/gif", "image/jpeg" and so on. - * - * @param string|array $value Real file to check for mimetype - * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) - * @return bool - */ - public function isValid($value, $file = null) - { - $fileInfo = $this->getFileInfo($value, $file, true); - - $this->setValue($fileInfo['filename']); - - // Is file readable ? - if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { - $this->error(self::NOT_READABLE); - return false; - } - - $mimefile = $this->getMagicFile(); - if (class_exists('finfo', false)) { - if (! $this->isMagicFileDisabled() && (! empty($mimefile) && empty($this->finfo))) { - $this->finfo = finfo_open(FILEINFO_MIME_TYPE, $mimefile); - } - - if (empty($this->finfo)) { - $this->finfo = finfo_open(FILEINFO_MIME_TYPE); - } - - $this->type = null; - if (! empty($this->finfo)) { - $this->type = finfo_file($this->finfo, $fileInfo['file']); - } - } - - if (empty($this->type) && $this->getHeaderCheck()) { - $this->type = $fileInfo['filetype']; - } - - if (empty($this->type)) { - $this->error(self::NOT_DETECTED); - return false; - } - - $mimetype = $this->getMimeType(true); - if (in_array($this->type, $mimetype)) { - $this->error(self::FALSE_TYPE); - return false; - } - - $types = explode('/', $this->type); - $types = array_merge($types, explode('-', $this->type)); - $types = array_merge($types, explode(';', $this->type)); - foreach ($mimetype as $mime) { - if (in_array($mime, $types)) { - $this->error(self::FALSE_TYPE); - return false; - } - } - - return true; - } -} diff --git a/lib/laminas/laminas-validator/src/File/Exists.php b/lib/laminas/laminas-validator/src/File/Exists.php deleted file mode 100644 index 80a27c975..000000000 --- a/lib/laminas/laminas-validator/src/File/Exists.php +++ /dev/null @@ -1,183 +0,0 @@ -<?php - -namespace Laminas\Validator\File; - -use Laminas\Validator\AbstractValidator; -use Laminas\Validator\Exception; -use Traversable; - -use function array_key_exists; -use function array_unique; -use function explode; -use function file_exists; -use function implode; -use function is_array; -use function is_string; -use function trim; - -use const DIRECTORY_SEPARATOR; - -/** - * Validator which checks if the file already exists in the directory - */ -class Exists extends AbstractValidator -{ - use FileInformationTrait; - - /** - * @const string Error constants - */ - public const DOES_NOT_EXIST = 'fileExistsDoesNotExist'; - - /** @var array Error message templates */ - protected $messageTemplates = [ - self::DOES_NOT_EXIST => 'File does not exist', - ]; - - /** - * Options for this validator - * - * @var array - */ - protected $options = [ - 'directory' => null, // internal list of directories - ]; - - /** @var array Error message template variables */ - protected $messageVariables = [ - 'directory' => ['options' => 'directory'], - ]; - - /** - * Sets validator options - * - * @param string|array|Traversable $options - */ - public function __construct($options = null) - { - if (is_string($options)) { - $options = explode(',', $options); - } - - if (is_array($options) && ! array_key_exists('directory', $options)) { - $options = ['directory' => $options]; - } - - parent::__construct($options); - } - - /** - * Returns the set file directories which are checked - * - * @param bool $asArray Returns the values as array; when false, a concatenated string is returned - * @return string|null - */ - public function getDirectory($asArray = false) - { - $asArray = (bool) $asArray; - $directory = $this->options['directory']; - if ($asArray && isset($directory)) { - $directory = explode(',', (string) $directory); - } - - return $directory; - } - - /** - * Sets the file directory which will be checked - * - * @param string|array $directory The directories to validate - * @return self Provides a fluent interface - */ - public function setDirectory($directory) - { - $this->options['directory'] = null; - $this->addDirectory($directory); - return $this; - } - - /** - * Adds the file directory which will be checked - * - * @param string|array $directory The directory to add for validation - * @return self Provides a fluent interface - * @throws Exception\InvalidArgumentException - */ - public function addDirectory($directory) - { - $directories = $this->getDirectory(true); - if (! isset($directories)) { - $directories = []; - } - - if (is_string($directory)) { - $directory = explode(',', $directory); - } elseif (! is_array($directory)) { - throw new Exception\InvalidArgumentException('Invalid options to validator provided'); - } - - foreach ($directory as $content) { - if (empty($content) || ! is_string($content)) { - continue; - } - - $directories[] = trim($content); - } - $directories = array_unique($directories); - - // Sanity check to ensure no empty values - foreach ($directories as $key => $dir) { - if (empty($dir)) { - unset($directories[$key]); - } - } - - $this->options['directory'] = ! empty($directory) - ? implode(',', $directories) : null; - - return $this; - } - - /** - * Returns true if and only if the file already exists in the set directories - * - * @param string|array $value Real file to check for existence - * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) - * @return bool - */ - public function isValid($value, $file = null) - { - $fileInfo = $this->getFileInfo($value, $file, false, true); - - $this->setValue($fileInfo['filename']); - - $check = false; - $directories = $this->getDirectory(true); - if (! isset($directories)) { - $check = true; - if (! file_exists($fileInfo['file'])) { - $this->error(self::DOES_NOT_EXIST); - return false; - } - } else { - foreach ($directories as $directory) { - if (! isset($directory) || '' === $directory) { - continue; - } - - $check = true; - if (! file_exists($directory . DIRECTORY_SEPARATOR . $fileInfo['basename'])) { - $this->error(self::DOES_NOT_EXIST); - return false; - } - } - } - - if (! $check) { - $this->error(self::DOES_NOT_EXIST); - return false; - } - - return true; - } -} diff --git a/lib/laminas/laminas-validator/src/File/Extension.php b/lib/laminas/laminas-validator/src/File/Extension.php deleted file mode 100644 index c977d9bcd..000000000 --- a/lib/laminas/laminas-validator/src/File/Extension.php +++ /dev/null @@ -1,242 +0,0 @@ -<?php - -namespace Laminas\Validator\File; - -use Laminas\Stdlib\ArrayUtils; -use Laminas\Validator\AbstractValidator; -use Traversable; - -use function array_key_exists; -use function array_unique; -use function explode; -use function func_get_arg; -use function func_num_args; -use function implode; -use function in_array; -use function is_array; -use function is_readable; -use function is_string; -use function strrpos; -use function strtolower; -use function substr; -use function trim; - -/** - * Validator for the file extension of a file - */ -class Extension extends AbstractValidator -{ - use FileInformationTrait; - - /** - * @const string Error constants - */ - public const FALSE_EXTENSION = 'fileExtensionFalse'; - public const NOT_FOUND = 'fileExtensionNotFound'; - - /** @var array<string, string> Error message templates */ - protected $messageTemplates = [ - self::FALSE_EXTENSION => 'File has an incorrect extension', - self::NOT_FOUND => 'File is not readable or does not exist', - ]; - - /** - * Options for this validator - * - * @var array - */ - protected $options = [ - 'case' => false, // Validate case sensitive - 'extension' => '', // List of extensions - 'allowNonExistentFile' => false, // Allow validation even if file does not exist - ]; - - /** @var array Error message template variables */ - protected $messageVariables = [ - 'extension' => ['options' => 'extension'], - ]; - - /** - * Sets validator options - * - * @param string|array|Traversable $options - */ - public function __construct($options = null) - { - if ($options instanceof Traversable) { - $options = ArrayUtils::iteratorToArray($options); - } - - $case = null; - if (1 < func_num_args()) { - $case = func_get_arg(1); - } - - if (is_array($options)) { - if (isset($options['case'])) { - $case = $options['case']; - unset($options['case']); - } - - if (! array_key_exists('extension', $options)) { - $options = ['extension' => $options]; - } - } else { - $options = ['extension' => $options]; - } - - if ($case !== null) { - $options['case'] = $case; - } - - parent::__construct($options); - } - - /** - * Returns the case option - * - * @return bool - */ - public function getCase() - { - return $this->options['case']; - } - - /** - * Sets the case to use - * - * @param bool $case - * @return $this Provides a fluent interface - */ - public function setCase($case) - { - $this->options['case'] = (bool) $case; - return $this; - } - - /** - * Returns the set file extension - * - * @return array - */ - public function getExtension() - { - if ( - ! array_key_exists('extension', $this->options) - || ! is_string($this->options['extension']) - ) { - return []; - } - - return explode(',', $this->options['extension']); - } - - /** - * Sets the file extensions - * - * @param string|array $extension The extensions to validate - * @return $this Provides a fluent interface - */ - public function setExtension($extension) - { - $this->options['extension'] = null; - $this->addExtension($extension); - return $this; - } - - /** - * Adds the file extensions - * - * @param string|array $extension The extensions to add for validation - * @return $this Provides a fluent interface - */ - public function addExtension($extension) - { - $extensions = $this->getExtension(); - if (is_string($extension)) { - $extension = explode(',', $extension); - } - - foreach ($extension as $content) { - if (empty($content) || ! is_string($content)) { - continue; - } - - $extensions[] = trim($content); - } - - $extensions = array_unique($extensions); - - // Sanity check to ensure no empty values - foreach ($extensions as $key => $ext) { - if (empty($ext)) { - unset($extensions[$key]); - } - } - - $this->options['extension'] = implode(',', $extensions); - return $this; - } - - /** - * Returns whether or not to allow validation of non-existent files. - * - * @return bool - */ - public function getAllowNonExistentFile() - { - return $this->options['allowNonExistentFile']; - } - - /** - * Sets the flag indicating whether or not to allow validation of non-existent files. - * - * @param bool $flag Whether or not to allow validation of non-existent files. - * @return $this Provides a fluent interface - */ - public function setAllowNonExistentFile($flag) - { - $this->options['allowNonExistentFile'] = (bool) $flag; - return $this; - } - - /** - * Returns true if and only if the file extension of $value is included in the - * set extension list - * - * @param string|array $value Real file to check for extension - * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) - * @return bool - */ - public function isValid($value, $file = null) - { - $fileInfo = $this->getFileInfo($value, $file); - - // Is file readable ? - if ( - ! $this->getAllowNonExistentFile() - && (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) - ) { - $this->error(self::NOT_FOUND); - return false; - } - - $this->setValue($fileInfo['filename']); - - $extension = substr($fileInfo['filename'], strrpos($fileInfo['filename'], '.') + 1); - $extensions = $this->getExtension(); - - if ($this->getCase() && (in_array($extension, $extensions))) { - return true; - } elseif (! $this->getCase()) { - foreach ($extensions as $ext) { - if (strtolower($ext) === strtolower($extension)) { - return true; - } - } - } - - $this->error(self::FALSE_EXTENSION); - return false; - } -} diff --git a/lib/laminas/laminas-validator/src/File/FileInformationTrait.php b/lib/laminas/laminas-validator/src/File/FileInformationTrait.php deleted file mode 100644 index 295027b93..000000000 --- a/lib/laminas/laminas-validator/src/File/FileInformationTrait.php +++ /dev/null @@ -1,164 +0,0 @@ -<?php - -namespace Laminas\Validator\File; - -use Laminas\Validator\Exception; -use Psr\Http\Message\UploadedFileInterface; - -use function basename; -use function is_array; -use function is_string; - -trait FileInformationTrait -{ - /** - * Returns array if the procedure is identified - * - * @param string|array|object $value Filename to check - * @param null|array $file File data (when using legacy Laminas_File_Transfer API) - * @param bool $hasType Return with filetype (optional) - * @param bool $hasBasename Return with basename - is calculated from location path (optional) - * @return array - */ - protected function getFileInfo( - $value, - ?array $file = null, - $hasType = false, - $hasBasename = false - ) { - if (is_string($value) && is_array($file)) { - return $this->getLegacyFileInfo($file, $hasType, $hasBasename); - } - - if (is_array($value)) { - return $this->getSapiFileInfo($value, $hasType, $hasBasename); - } - - if ($value instanceof UploadedFileInterface) { - return $this->getPsr7FileInfo($value, $hasType, $hasBasename); - } - - return $this->getFileBasedFileInfo($value, $hasType, $hasBasename); - } - - /** - * Generate file information array with legacy Laminas_File_Transfer API - * - * @param array $file File data - * @param bool $hasType Return with filetype - * @param bool $hasBasename Basename is calculated from location path - * @return array - */ - private function getLegacyFileInfo( - array $file, - $hasType = false, - $hasBasename = false - ) { - $fileInfo = []; - - $fileInfo['filename'] = $file['name']; - $fileInfo['file'] = $file['tmp_name']; - - if ($hasBasename) { - $fileInfo['basename'] = basename($fileInfo['file']); - } - - if ($hasType) { - $fileInfo['filetype'] = $file['type']; - } - - return $fileInfo; - } - - /** - * Generate file information array with SAPI - * - * @param array $file File data from SAPI - * @param bool $hasType Return with filetype - * @param bool $hasBasename Filename is calculated from location path - * @return array - */ - private function getSapiFileInfo( - array $file, - $hasType = false, - $hasBasename = false - ) { - if (! isset($file['tmp_name']) || ! isset($file['name'])) { - throw new Exception\InvalidArgumentException( - 'Value array must be in $_FILES format' - ); - } - - $fileInfo = []; - - $fileInfo['file'] = $file['tmp_name']; - $fileInfo['filename'] = $file['name']; - - if ($hasBasename) { - $fileInfo['basename'] = basename($fileInfo['file']); - } - - if ($hasType) { - $fileInfo['filetype'] = $file['type']; - } - - return $fileInfo; - } - - /** - * Generate file information array with PSR-7 UploadedFileInterface - * - * @param bool $hasType Return with filetype - * @param bool $hasBasename Filename is calculated from location path - * @return array - */ - private function getPsr7FileInfo( - UploadedFileInterface $file, - $hasType = false, - $hasBasename = false - ) { - $fileInfo = []; - - $fileInfo['file'] = $file->getStream()->getMetadata('uri'); - $fileInfo['filename'] = $file->getClientFilename(); - - if ($hasBasename) { - $fileInfo['basename'] = basename($fileInfo['file']); - } - - if ($hasType) { - $fileInfo['filetype'] = $file->getClientMediaType(); - } - - return $fileInfo; - } - - /** - * Generate file information array with base method - * - * @param string $file File path - * @param bool $hasType Return with filetype - * @param bool $hasBasename Filename is calculated from location path - * @return array - */ - private function getFileBasedFileInfo( - $file, - $hasType = false, - $hasBasename = false - ) { - $fileInfo = []; - - $fileInfo['file'] = $file; - $fileInfo['filename'] = basename($fileInfo['file']); - - if ($hasBasename) { - $fileInfo['basename'] = basename($fileInfo['file']); - } - - if ($hasType) { - $fileInfo['filetype'] = null; - } - - return $fileInfo; - } -} diff --git a/lib/laminas/laminas-validator/src/File/FilesSize.php b/lib/laminas/laminas-validator/src/File/FilesSize.php deleted file mode 100644 index 25bd90250..000000000 --- a/lib/laminas/laminas-validator/src/File/FilesSize.php +++ /dev/null @@ -1,184 +0,0 @@ -<?php - -namespace Laminas\Validator\File; - -use Laminas\Stdlib\ArrayUtils; -use Laminas\Stdlib\ErrorHandler; -use Laminas\Validator\Exception; -use Laminas\Validator\Exception\InvalidArgumentException; -use Traversable; - -use function array_key_exists; -use function array_shift; -use function filesize; -use function func_get_args; -use function func_num_args; -use function is_array; -use function is_readable; -use function is_scalar; -use function is_string; - -/** - * Validator for the size of all files which will be validated in sum - */ -class FilesSize extends Size -{ - /** - * @const string Error constants - */ - public const TOO_BIG = 'fileFilesSizeTooBig'; - public const TOO_SMALL = 'fileFilesSizeTooSmall'; - public const NOT_READABLE = 'fileFilesSizeNotReadable'; - - /** @var array Error message templates */ - protected $messageTemplates = [ - self::TOO_BIG => "All files in sum should have a maximum size of '%max%' but '%size%' were detected", - self::TOO_SMALL => "All files in sum should have a minimum size of '%min%' but '%size%' were detected", - self::NOT_READABLE => 'One or more files can not be read', - ]; - - /** - * Internal file array - * - * @var array - */ - protected $files; - - /** - * Sets validator options - * - * Min limits the used disk space for all files, when used with max=null it is the maximum file size - * It also accepts an array with the keys 'min' and 'max' - * - * @param int|array|Traversable $options Options for this validator - * @throws InvalidArgumentException - */ - public function __construct($options = null) - { - $this->files = []; - $this->setSize(0); - - if ($options instanceof Traversable) { - $options = ArrayUtils::iteratorToArray($options); - } elseif (is_scalar($options)) { - $options = ['max' => $options]; - } elseif (! is_array($options)) { - throw new Exception\InvalidArgumentException('Invalid options to validator provided'); - } - - if (1 < func_num_args()) { - $argv = func_get_args(); - array_shift($argv); - $options['max'] = array_shift($argv); - if (! empty($argv)) { - $options['useByteString'] = array_shift($argv); - } - } - - parent::__construct($options); - } - - /** - * Returns true if and only if the disk usage of all files is at least min and - * not bigger than max (when max is not null). - * - * @param string|array $value Real file to check for size - * @param array $file File data from \Laminas\File\Transfer\Transfer - * @return bool - */ - public function isValid($value, $file = null) - { - if (is_string($value)) { - $value = [$value]; - } elseif (is_array($value) && isset($value['tmp_name'])) { - $value = [$value]; - } - - $min = $this->getMin(true); - $max = $this->getMax(true); - $size = $this->getSize(); - foreach ($value as $files) { - if (is_array($files)) { - if (! isset($files['tmp_name']) || ! isset($files['name'])) { - throw new Exception\InvalidArgumentException( - 'Value array must be in $_FILES format' - ); - } - $file = $files; - $files = $files['tmp_name']; - } - - // Is file readable ? - if (empty($files) || false === is_readable($files)) { - $this->throwError($file, self::NOT_READABLE); - continue; - } - - if (! isset($this->files[$files])) { - $this->files[$files] = $files; - } else { - // file already counted... do not count twice - continue; - } - - // limited to 2GB files - ErrorHandler::start(); - $size += filesize($files); - ErrorHandler::stop(); - $this->size = $size; - if (($max !== null) && ($max < $size)) { - if ($this->getByteString()) { - $this->options['max'] = $this->toByteString($max); - $this->size = $this->toByteString($size); - $this->throwError($file, self::TOO_BIG); - $this->options['max'] = $max; - $this->size = $size; - } else { - $this->throwError($file, self::TOO_BIG); - } - } - } - - // Check that aggregate files are >= minimum size - if (($min !== null) && ($size < $min)) { - if ($this->getByteString()) { - $this->options['min'] = $this->toByteString($min); - $this->size = $this->toByteString($size); - $this->throwError($file, self::TOO_SMALL); - $this->options['min'] = $min; - $this->size = $size; - } else { - $this->throwError($file, self::TOO_SMALL); - } - } - - if ($this->getMessages()) { - return false; - } - - return true; - } - - /** - * Throws an error of the given type - * - * @param string $file - * @param string $errorType - * @return false - */ - protected function throwError($file, $errorType) - { - if ($file !== null) { - if (is_array($file)) { - if (array_key_exists('name', $file)) { - $this->value = $file['name']; - } - } elseif (is_string($file)) { - $this->value = $file; - } - } - - $this->error($errorType); - return false; - } -} diff --git a/lib/laminas/laminas-validator/src/File/Hash.php b/lib/laminas/laminas-validator/src/File/Hash.php deleted file mode 100644 index bf11570b8..000000000 --- a/lib/laminas/laminas-validator/src/File/Hash.php +++ /dev/null @@ -1,177 +0,0 @@ -<?php - -namespace Laminas\Validator\File; - -use Laminas\Validator\AbstractValidator; -use Laminas\Validator\Exception; - -use function array_key_exists; -use function array_unique; -use function array_values; -use function func_get_arg; -use function func_num_args; -use function get_class; -use function gettype; -use function hash_algos; -use function hash_file; -use function in_array; -use function is_array; -use function is_object; -use function is_readable; -use function is_scalar; -use function is_string; -use function sprintf; - -/** - * Validator for the hash of given files - */ -class Hash extends AbstractValidator -{ - use FileInformationTrait; - - /** - * @const string Error constants - */ - public const DOES_NOT_MATCH = 'fileHashDoesNotMatch'; - public const NOT_DETECTED = 'fileHashHashNotDetected'; - public const NOT_FOUND = 'fileHashNotFound'; - - /** @var array Error message templates */ - protected $messageTemplates = [ - self::DOES_NOT_MATCH => 'File does not match the given hashes', - self::NOT_DETECTED => 'A hash could not be evaluated for the given file', - self::NOT_FOUND => 'File is not readable or does not exist', - ]; - - /** - * Options for this validator - * - * @var string - */ - protected $options = [ - 'algorithm' => 'crc32', - 'hash' => null, - ]; - - /** - * Sets validator options - * - * @param string|array $options - */ - public function __construct($options = null) - { - if ( - is_scalar($options) || - (is_array($options) && ! array_key_exists('hash', $options)) - ) { - $options = ['hash' => $options]; - } - - if (1 < func_num_args()) { - $options['algorithm'] = func_get_arg(1); - } - - parent::__construct($options); - } - - /** - * Returns the set hash values as array, the hash as key and the algorithm the value - * - * @return array - */ - public function getHash() - { - return $this->options['hash']; - } - - /** - * Sets the hash for one or multiple files - * - * @param string|array $options - * @return $this Provides a fluent interface - */ - public function setHash($options) - { - $this->options['hash'] = null; - $this->addHash($options); - - return $this; - } - - /** - * Adds the hash for one or multiple files - * - * @param string|array $options - * @throws Exception\InvalidArgumentException - * @return $this Provides a fluent interface - */ - public function addHash($options) - { - if (is_string($options)) { - $options = [$options]; - } elseif (! is_array($options)) { - throw new Exception\InvalidArgumentException('False parameter given'); - } - - $known = hash_algos(); - if (! isset($options['algorithm'])) { - $algorithm = $this->options['algorithm']; - } else { - $algorithm = $options['algorithm']; - unset($options['algorithm']); - } - - if (! in_array($algorithm, $known)) { - throw new Exception\InvalidArgumentException("Unknown algorithm '{$algorithm}'"); - } - - foreach ($options as $value) { - if (! is_string($value)) { - throw new Exception\InvalidArgumentException(sprintf( - 'Hash must be a string, %s received', - is_object($value) ? get_class($value) : gettype($value) - )); - } - $this->options['hash'][$value] = $algorithm; - } - - return $this; - } - - /** - * Returns true if and only if the given file confirms the set hash - * - * @param string|array $value File to check for hash - * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) - * @return bool - */ - public function isValid($value, $file = null) - { - $fileInfo = $this->getFileInfo($value, $file); - - $this->setValue($fileInfo['filename']); - - // Is file readable ? - if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { - $this->error(self::NOT_FOUND); - return false; - } - - $algos = array_unique(array_values($this->getHash())); - foreach ($algos as $algorithm) { - $filehash = hash_file($algorithm, $fileInfo['file']); - - if ($filehash === false) { - $this->error(self::NOT_DETECTED); - return false; - } - - if (isset($this->getHash()[$filehash]) && $this->getHash()[$filehash] === $algorithm) { - return true; - } - } - - $this->error(self::DOES_NOT_MATCH); - return false; - } -} diff --git a/lib/laminas/laminas-validator/src/File/ImageSize.php b/lib/laminas/laminas-validator/src/File/ImageSize.php deleted file mode 100644 index 91f478bb7..000000000 --- a/lib/laminas/laminas-validator/src/File/ImageSize.php +++ /dev/null @@ -1,377 +0,0 @@ -<?php - -namespace Laminas\Validator\File; - -use Laminas\Stdlib\ErrorHandler; -use Laminas\Validator\AbstractValidator; -use Laminas\Validator\Exception; -use Traversable; - -use function array_shift; -use function func_get_args; -use function func_num_args; -use function getimagesize; -use function is_array; -use function is_readable; - -/** - * Validator for the image size of an image file - */ -class ImageSize extends AbstractValidator -{ - use FileInformationTrait; - - /** - * @const string Error constants - */ - public const WIDTH_TOO_BIG = 'fileImageSizeWidthTooBig'; - public const WIDTH_TOO_SMALL = 'fileImageSizeWidthTooSmall'; - public const HEIGHT_TOO_BIG = 'fileImageSizeHeightTooBig'; - public const HEIGHT_TOO_SMALL = 'fileImageSizeHeightTooSmall'; - public const NOT_DETECTED = 'fileImageSizeNotDetected'; - public const NOT_READABLE = 'fileImageSizeNotReadable'; - - /** @var array Error message template */ - protected $messageTemplates = [ - self::WIDTH_TOO_BIG => "Maximum allowed width for image should be '%maxwidth%' but '%width%' detected", - self::WIDTH_TOO_SMALL => "Minimum expected width for image should be '%minwidth%' but '%width%' detected", - self::HEIGHT_TOO_BIG => "Maximum allowed height for image should be '%maxheight%' but '%height%' detected", - self::HEIGHT_TOO_SMALL => "Minimum expected height for image should be '%minheight%' but '%height%' detected", - self::NOT_DETECTED => 'The size of image could not be detected', - self::NOT_READABLE => 'File is not readable or does not exist', - ]; - - /** @var array Error message template variables */ - protected $messageVariables = [ - 'minwidth' => ['options' => 'minWidth'], - 'maxwidth' => ['options' => 'maxWidth'], - 'minheight' => ['options' => 'minHeight'], - 'maxheight' => ['options' => 'maxHeight'], - 'width' => 'width', - 'height' => 'height', - ]; - - /** - * Detected width - * - * @var int - */ - protected $width; - - /** - * Detected height - * - * @var int - */ - protected $height; - - /** - * Options for this validator - * - * @var array - */ - protected $options = [ - 'minWidth' => null, // Minimum image width - 'maxWidth' => null, // Maximum image width - 'minHeight' => null, // Minimum image height - 'maxHeight' => null, // Maximum image height - ]; - - /** - * Sets validator options - * - * Accepts the following option keys: - * - minheight - * - minwidth - * - maxheight - * - maxwidth - * - * @param null|array|Traversable $options - */ - public function __construct($options = null) - { - if (1 < func_num_args()) { - if (! is_array($options)) { - $options = ['minWidth' => $options]; - } - - $argv = func_get_args(); - array_shift($argv); - $options['minHeight'] = array_shift($argv); - if (! empty($argv)) { - $options['maxWidth'] = array_shift($argv); - if (! empty($argv)) { - $options['maxHeight'] = array_shift($argv); - } - } - } - - parent::__construct($options); - } - - /** - * Returns the minimum allowed width - * - * @return int - */ - public function getMinWidth() - { - return $this->options['minWidth']; - } - - /** - * Sets the minimum allowed width - * - * @param int $minWidth - * @return $this Provides a fluid interface - * @throws Exception\InvalidArgumentException When minwidth is greater than maxwidth. - */ - public function setMinWidth($minWidth) - { - if (($this->getMaxWidth() !== null) && ($minWidth > $this->getMaxWidth())) { - throw new Exception\InvalidArgumentException( - 'The minimum image width must be less than or equal to the ' - . " maximum image width, but {$minWidth} > {$this->getMaxWidth()}" - ); - } - - $this->options['minWidth'] = (int) $minWidth; - return $this; - } - - /** - * Returns the maximum allowed width - * - * @return int - */ - public function getMaxWidth() - { - return $this->options['maxWidth']; - } - - /** - * Sets the maximum allowed width - * - * @param int $maxWidth - * @return $this Provides a fluid interface - * @throws Exception\InvalidArgumentException When maxwidth is less than minwidth. - */ - public function setMaxWidth($maxWidth) - { - if (($this->getMinWidth() !== null) && ($maxWidth < $this->getMinWidth())) { - throw new Exception\InvalidArgumentException( - 'The maximum image width must be greater than or equal to the ' - . "minimum image width, but {$maxWidth} < {$this->getMinWidth()}" - ); - } - - $this->options['maxWidth'] = (int) $maxWidth; - return $this; - } - - /** - * Returns the minimum allowed height - * - * @return int - */ - public function getMinHeight() - { - return $this->options['minHeight']; - } - - /** - * Sets the minimum allowed height - * - * @param int $minHeight - * @return $this Provides a fluid interface - * @throws Exception\InvalidArgumentException When minheight is greater than maxheight. - */ - public function setMinHeight($minHeight) - { - if (($this->getMaxHeight() !== null) && ($minHeight > $this->getMaxHeight())) { - throw new Exception\InvalidArgumentException( - 'The minimum image height must be less than or equal to the ' - . " maximum image height, but {$minHeight} > {$this->getMaxHeight()}" - ); - } - - $this->options['minHeight'] = (int) $minHeight; - return $this; - } - - /** - * Returns the maximum allowed height - * - * @return int - */ - public function getMaxHeight() - { - return $this->options['maxHeight']; - } - - /** - * Sets the maximum allowed height - * - * @param int $maxHeight - * @return $this Provides a fluid interface - * @throws Exception\InvalidArgumentException When maxheight is less than minheight. - */ - public function setMaxHeight($maxHeight) - { - if (($this->getMinHeight() !== null) && ($maxHeight < $this->getMinHeight())) { - throw new Exception\InvalidArgumentException( - 'The maximum image height must be greater than or equal to the ' - . "minimum image height, but {$maxHeight} < {$this->getMinHeight()}" - ); - } - - $this->options['maxHeight'] = (int) $maxHeight; - return $this; - } - - /** - * Returns the set minimum image sizes - * - * @return array - */ - public function getImageMin() - { - return ['minWidth' => $this->getMinWidth(), 'minHeight' => $this->getMinHeight()]; - } - - /** - * Returns the set maximum image sizes - * - * @return array - */ - public function getImageMax() - { - return ['maxWidth' => $this->getMaxWidth(), 'maxHeight' => $this->getMaxHeight()]; - } - - /** - * Returns the set image width sizes - * - * @return array - */ - public function getImageWidth() - { - return ['minWidth' => $this->getMinWidth(), 'maxWidth' => $this->getMaxWidth()]; - } - - /** - * Returns the set image height sizes - * - * @return array - */ - public function getImageHeight() - { - return ['minHeight' => $this->getMinHeight(), 'maxHeight' => $this->getMaxHeight()]; - } - - /** - * Sets the minimum image size - * - * @param array $options The minimum image dimensions - * @return $this Provides a fluent interface - */ - public function setImageMin($options) - { - $this->setOptions($options); - return $this; - } - - /** - * Sets the maximum image size - * - * @param array|Traversable $options The maximum image dimensions - * @return $this Provides a fluent interface - */ - public function setImageMax($options) - { - $this->setOptions($options); - return $this; - } - - /** - * Sets the minimum and maximum image width - * - * @param array $options The image width dimensions - * @return $this Provides a fluent interface - */ - public function setImageWidth($options) - { - $this->setImageMin($options); - $this->setImageMax($options); - - return $this; - } - - /** - * Sets the minimum and maximum image height - * - * @param array $options The image height dimensions - * @return $this Provides a fluent interface - */ - public function setImageHeight($options) - { - $this->setImageMin($options); - $this->setImageMax($options); - - return $this; - } - - /** - * Returns true if and only if the image size of $value is at least min and - * not bigger than max - * - * @param string|array $value Real file to check for image size - * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) - * @return bool - */ - public function isValid($value, $file = null) - { - $fileInfo = $this->getFileInfo($value, $file); - - $this->setValue($fileInfo['filename']); - - // Is file readable ? - if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { - $this->error(self::NOT_READABLE); - return false; - } - - ErrorHandler::start(); - $size = getimagesize($fileInfo['file']); - ErrorHandler::stop(); - - if (empty($size) || ($size[0] === 0) || ($size[1] === 0)) { - $this->error(self::NOT_DETECTED); - return false; - } - - $this->width = $size[0]; - $this->height = $size[1]; - if ($this->width < $this->getMinWidth()) { - $this->error(self::WIDTH_TOO_SMALL); - } - - if (($this->getMaxWidth() !== null) && ($this->getMaxWidth() < $this->width)) { - $this->error(self::WIDTH_TOO_BIG); - } - - if ($this->height < $this->getMinHeight()) { - $this->error(self::HEIGHT_TOO_SMALL); - } - - if (($this->getMaxHeight() !== null) && ($this->getMaxHeight() < $this->height)) { - $this->error(self::HEIGHT_TOO_BIG); - } - - if ($this->getMessages()) { - return false; - } - - return true; - } -} diff --git a/lib/laminas/laminas-validator/src/File/IsCompressed.php b/lib/laminas/laminas-validator/src/File/IsCompressed.php deleted file mode 100644 index 86ce6164e..000000000 --- a/lib/laminas/laminas-validator/src/File/IsCompressed.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php - -namespace Laminas\Validator\File; - -use Laminas\Stdlib\ArrayUtils; -use Traversable; - -/** - * Validator which checks if the file already exists in the directory - */ -class IsCompressed extends MimeType -{ - /** - * @const string Error constants - */ - public const FALSE_TYPE = 'fileIsCompressedFalseType'; - public const NOT_DETECTED = 'fileIsCompressedNotDetected'; - public const NOT_READABLE = 'fileIsCompressedNotReadable'; - - /** @var array Error message templates */ - protected $messageTemplates = [ - self::FALSE_TYPE => "File is not compressed, '%type%' detected", - self::NOT_DETECTED => 'The mimetype could not be detected from the file', - self::NOT_READABLE => 'File is not readable or does not exist', - ]; - - /** - * Sets validator options - * - * @param string|array|Traversable $options - */ - public function __construct($options = []) - { - // http://hul.harvard.edu/ois/systems/wax/wax-public-help/mimetypes.htm - $default = [ - 'application/arj', - 'application/gnutar', - 'application/lha', - 'application/lzx', - 'application/vnd.ms-cab-compressed', - 'application/x-ace-compressed', - 'application/x-arc', - 'application/x-archive', - 'application/x-arj', - 'application/x-bzip', - 'application/x-bzip2', - 'application/x-cab-compressed', - 'application/x-compress', - 'application/x-compressed', - 'application/x-cpio', - 'application/x-debian-package', - 'application/x-eet', - 'application/x-gzip', - 'application/x-java-pack200', - 'application/x-lha', - 'application/x-lharc', - 'application/x-lzh', - 'application/x-lzma', - 'application/x-lzx', - 'application/x-rar', - 'application/x-sit', - 'application/x-stuffit', - 'application/x-tar', - 'application/zip', - 'application/x-zip', - 'application/zoo', - 'multipart/x-gzip', - ]; - - if ($options instanceof Traversable) { - $options = ArrayUtils::iteratorToArray($options); - } - - if ($options === null) { - $options = []; - } - - parent::__construct($options); - - if (! $this->getMimeType()) { - $this->setMimeType($default); - } - } -} diff --git a/lib/laminas/laminas-validator/src/File/IsImage.php b/lib/laminas/laminas-validator/src/File/IsImage.php deleted file mode 100644 index ced192753..000000000 --- a/lib/laminas/laminas-validator/src/File/IsImage.php +++ /dev/null @@ -1,110 +0,0 @@ -<?php - -namespace Laminas\Validator\File; - -use Laminas\Stdlib\ArrayUtils; -use Traversable; - -/** - * Validator which checks if the file is an image - */ -class IsImage extends MimeType -{ - /** - * @const string Error constants - */ - public const FALSE_TYPE = 'fileIsImageFalseType'; - public const NOT_DETECTED = 'fileIsImageNotDetected'; - public const NOT_READABLE = 'fileIsImageNotReadable'; - - /** @var array Error message templates */ - protected $messageTemplates = [ - self::FALSE_TYPE => "File is no image, '%type%' detected", - self::NOT_DETECTED => 'The mimetype could not be detected from the file', - self::NOT_READABLE => 'File is not readable or does not exist', - ]; - - /** - * Sets validator options - * - * @param array|Traversable|string $options - */ - public function __construct($options = []) - { - // http://www.iana.org/assignments/media-types/media-types.xhtml#image - $default = [ - 'application/cdf', - 'application/dicom', - 'application/fractals', - 'application/postscript', - 'application/vnd.hp-hpgl', - 'application/vnd.oasis.opendocument.graphics', - 'application/x-cdf', - 'application/x-cmu-raster', - 'application/x-ima', - 'application/x-inventor', - 'application/x-koan', - 'application/x-portable-anymap', - 'application/x-world-x-3dmf', - 'image/bmp', - 'image/c', - 'image/cgm', - 'image/fif', - 'image/gif', - 'image/heic', - 'image/heif', - 'image/jpeg', - 'image/jpm', - 'image/jpx', - 'image/jp2', - 'image/naplps', - 'image/pjpeg', - 'image/png', - 'image/svg', - 'image/svg+xml', - 'image/tiff', - 'image/vnd.adobe.photoshop', - 'image/vnd.djvu', - 'image/vnd.fpx', - 'image/vnd.net-fpx', - 'image/webp', - 'image/x-cmu-raster', - 'image/x-cmx', - 'image/x-coreldraw', - 'image/x-cpi', - 'image/x-emf', - 'image/x-ico', - 'image/x-icon', - 'image/x-jg', - 'image/x-ms-bmp', - 'image/x-niff', - 'image/x-pict', - 'image/x-pcx', - 'image/x-png', - 'image/x-portable-anymap', - 'image/x-portable-bitmap', - 'image/x-portable-greymap', - 'image/x-portable-pixmap', - 'image/x-quicktime', - 'image/x-rgb', - 'image/x-tiff', - 'image/x-unknown', - 'image/x-windows-bmp', - 'image/x-xpmi', - ]; - - if ($options instanceof Traversable) { - $options = ArrayUtils::iteratorToArray($options); - } - - if ($options === null) { - $options = []; - } - - parent::__construct($options); - - if (! $this->getMimeType()) { - $this->setMimeType($default); - } - } -} diff --git a/lib/laminas/laminas-validator/src/File/Md5.php b/lib/laminas/laminas-validator/src/File/Md5.php deleted file mode 100644 index 4d48edf4e..000000000 --- a/lib/laminas/laminas-validator/src/File/Md5.php +++ /dev/null @@ -1,110 +0,0 @@ -<?php - -namespace Laminas\Validator\File; - -use function array_keys; -use function array_unique; -use function hash_file; -use function is_readable; - -/** - * Validator for the md5 hash of given files - */ -class Md5 extends Hash -{ - use FileInformationTrait; - - /** - * @const string Error constants - */ - public const DOES_NOT_MATCH = 'fileMd5DoesNotMatch'; - public const NOT_DETECTED = 'fileMd5NotDetected'; - public const NOT_FOUND = 'fileMd5NotFound'; - - /** @var array Error message templates */ - protected $messageTemplates = [ - self::DOES_NOT_MATCH => 'File does not match the given md5 hashes', - self::NOT_DETECTED => 'An md5 hash could not be evaluated for the given file', - self::NOT_FOUND => 'File is not readable or does not exist', - ]; - - /** - * Options for this validator - * - * @var string - */ - protected $options = [ - 'algorithm' => 'md5', - 'hash' => null, - ]; - - /** - * Returns all set md5 hashes - * - * @return array - */ - public function getMd5() - { - return $this->getHash(); - } - - /** - * Sets the md5 hash for one or multiple files - * - * @param string|array $options - * @return Hash Provides a fluent interface - */ - public function setMd5($options) - { - $this->setHash($options); - return $this; - } - - /** - * Adds the md5 hash for one or multiple files - * - * @param string|array $options - * @return Hash Provides a fluent interface - */ - public function addMd5($options) - { - $this->addHash($options); - return $this; - } - - /** - * Returns true if and only if the given file confirms the set hash - * - * @param string|array $value Filename to check for hash - * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) - * @return bool - */ - public function isValid($value, $file = null) - { - $fileInfo = $this->getFileInfo($value, $file); - - $this->setValue($fileInfo['filename']); - - // Is file readable ? - if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { - $this->error(self::NOT_FOUND); - return false; - } - - $hashes = array_unique(array_keys($this->getHash())); - $filehash = hash_file('md5', $fileInfo['file']); - if ($filehash === false) { - $this->error(self::NOT_DETECTED); - return false; - } - - foreach ($hashes as $hash) { - if ($filehash === $hash) { - return true; - } - } - - $this->error(self::DOES_NOT_MATCH); - return false; - } -} diff --git a/lib/laminas/laminas-validator/src/File/MimeType.php b/lib/laminas/laminas-validator/src/File/MimeType.php deleted file mode 100644 index 8c2c43a04..000000000 --- a/lib/laminas/laminas-validator/src/File/MimeType.php +++ /dev/null @@ -1,416 +0,0 @@ -<?php - -namespace Laminas\Validator\File; - -use Laminas\Stdlib\ArrayUtils; -use Laminas\Stdlib\ErrorHandler; -use Laminas\Validator\AbstractValidator; -use Laminas\Validator\Exception; -use Traversable; - -use function array_key_exists; -use function array_keys; -use function array_merge; -use function array_unique; -use function class_exists; -use function explode; -use function finfo_file; -use function finfo_open; -use function getenv; -use function implode; -use function in_array; -use function is_array; -use function is_file; -use function is_int; -use function is_readable; -use function is_string; -use function sprintf; -use function trim; - -use const E_NOTICE; -use const E_WARNING; -use const FILEINFO_MIME_TYPE; - -/** - * Validator for the mime type of a file - */ -class MimeType extends AbstractValidator -{ - use FileInformationTrait; - - /**#@+ - * - * @const Error type constants - */ - public const FALSE_TYPE = 'fileMimeTypeFalse'; - public const NOT_DETECTED = 'fileMimeTypeNotDetected'; - public const NOT_READABLE = 'fileMimeTypeNotReadable'; - /**#@-*/ - - /** @var array Error message templates */ - protected $messageTemplates = [ - self::FALSE_TYPE => "File has an incorrect mimetype of '%type%'", - self::NOT_DETECTED => 'The mimetype could not be detected from the file', - self::NOT_READABLE => 'File is not readable or does not exist', - ]; - - /** @var array */ - protected $messageVariables = [ - 'type' => 'type', - ]; - - /** @var string */ - protected $type; - - /** - * Finfo object to use - * - * @var resource - */ - protected $finfo; - - /** - * If no environment variable 'MAGIC' is set, try and autodiscover it based on common locations - * - * @var array - */ - protected $magicFiles = [ - '/usr/share/misc/magic', - '/usr/share/misc/magic.mime', - '/usr/share/misc/magic.mgc', - '/usr/share/mime/magic', - '/usr/share/mime/magic.mime', - '/usr/share/mime/magic.mgc', - '/usr/share/file/magic', - '/usr/share/file/magic.mime', - '/usr/share/file/magic.mgc', - ]; - - /** - * Options for this validator - * - * @var array - */ - protected $options = [ - 'enableHeaderCheck' => false, // Allow header check - 'disableMagicFile' => false, // Disable usage of magicfile - 'magicFile' => null, // Magicfile to use - 'mimeType' => null, // Mimetype to allow - ]; - - /** - * Sets validator options - * - * Mimetype to accept - * - NULL means default PHP usage by using the environment variable 'magic' - * - FALSE means disabling searching for mimetype, should be used for PHP 5.3 - * - A string is the mimetype file to use - * - * @param string|array|Traversable $options - */ - public function __construct($options = null) - { - if ($options instanceof Traversable) { - $options = ArrayUtils::iteratorToArray($options); - } elseif (is_string($options)) { - $this->setMimeType($options); - $options = []; - } elseif (is_array($options)) { - if (isset($options['magicFile'])) { - $this->setMagicFile($options['magicFile']); - unset($options['magicFile']); - } - - if (isset($options['enableHeaderCheck'])) { - $this->enableHeaderCheck($options['enableHeaderCheck']); - unset($options['enableHeaderCheck']); - } - - if (array_key_exists('mimeType', $options)) { - $this->setMimeType($options['mimeType']); - unset($options['mimeType']); - } - - // Handle cases where mimetypes are interspersed with options, or - // options are simply an array of mime types - foreach (array_keys($options) as $key) { - if (! is_int($key)) { - continue; - } - $this->addMimeType($options[$key]); - unset($options[$key]); - } - } - - parent::__construct($options); - } - - /** - * Returns the actual set magicfile - * - * @return string - */ - public function getMagicFile() - { - if (null === $this->options['magicFile']) { - $magic = getenv('magic'); - if (! empty($magic)) { - $this->setMagicFile($magic); - if ($this->options['magicFile'] === null) { - $this->options['magicFile'] = false; - } - return $this->options['magicFile']; - } - - foreach ($this->magicFiles as $file) { - try { - $this->setMagicFile($file); - } catch (Exception\ExceptionInterface $e) { - // suppressing errors which are thrown due to open_basedir restrictions - continue; - } - - if ($this->options['magicFile'] !== null) { - return $this->options['magicFile']; - } - } - - if ($this->options['magicFile'] === null) { - $this->options['magicFile'] = false; - } - } - - return $this->options['magicFile']; - } - - /** - * Sets the magicfile to use - * if null, the MAGIC constant from php is used - * if the MAGIC file is erroneous, no file will be set - * if false, the default MAGIC file from PHP will be used - * - * @param string $file - * @throws Exception\RuntimeException When finfo can not read the magicfile. - * @throws Exception\InvalidArgumentException - * @throws Exception\InvalidMagicMimeFileException - * @return $this Provides fluid interface - */ - public function setMagicFile($file) - { - if ($file === false) { - $this->options['magicFile'] = false; - } elseif (empty($file)) { - $this->options['magicFile'] = null; - } elseif (! class_exists('finfo', false)) { - $this->options['magicFile'] = null; - throw new Exception\RuntimeException('Magicfile can not be set; there is no finfo extension installed'); - } elseif (! is_file($file) || ! is_readable($file)) { - throw new Exception\InvalidArgumentException(sprintf( - 'The given magicfile ("%s") could not be read', - $file - )); - } else { - ErrorHandler::start(E_NOTICE | E_WARNING); - $this->finfo = finfo_open(FILEINFO_MIME_TYPE, $file); - $error = ErrorHandler::stop(); - if (empty($this->finfo)) { - $this->finfo = null; - throw new Exception\InvalidMagicMimeFileException(sprintf( - 'The given magicfile ("%s") could not be used by ext/finfo', - $file - ), 0, $error); - } - $this->options['magicFile'] = $file; - } - - return $this; - } - - /** - * Disables usage of MagicFile - * - * @param bool $disable False disables usage of magic file; true enables it. - * @return self Provides fluid interface - */ - public function disableMagicFile($disable) - { - $this->options['disableMagicFile'] = (bool) $disable; - return $this; - } - - /** - * Is usage of MagicFile disabled? - * - * @return bool - */ - public function isMagicFileDisabled() - { - return $this->options['disableMagicFile']; - } - - /** - * Returns the Header Check option - * - * @return bool - */ - public function getHeaderCheck() - { - return $this->options['enableHeaderCheck']; - } - - /** - * Defines if the http header should be used - * Note that this is unsafe and therefor the default value is false - * - * @param bool $headerCheck - * @return $this Provides fluid interface - */ - public function enableHeaderCheck($headerCheck = true) - { - $this->options['enableHeaderCheck'] = (bool) $headerCheck; - return $this; - } - - /** - * Returns the set mimetypes - * - * @param bool $asArray Returns the values as array, when false a concatenated string is returned - * @return string|array - * @psalm-return ($asArray is true ? list<string> : string) - */ - public function getMimeType($asArray = false) - { - $asArray = (bool) $asArray; - $mimetype = (string) $this->options['mimeType']; - if ($asArray) { - $mimetype = explode(',', $mimetype); - } - - return $mimetype; - } - - /** - * Sets the mimetypes - * - * @param string|array $mimetype The mimetypes to validate - * @return $this Provides a fluent interface - */ - public function setMimeType($mimetype) - { - $this->options['mimeType'] = null; - $this->addMimeType($mimetype); - return $this; - } - - /** - * Adds the mimetypes - * - * @param string|array $mimetype The mimetypes to add for validation - * @throws Exception\InvalidArgumentException - * @return $this Provides a fluent interface - */ - public function addMimeType($mimetype) - { - $mimetypes = $this->getMimeType(true); - - if (is_string($mimetype)) { - $mimetype = explode(',', $mimetype); - } elseif (! is_array($mimetype)) { - throw new Exception\InvalidArgumentException('Invalid options to validator provided'); - } - - if (isset($mimetype['magicFile'])) { - unset($mimetype['magicFile']); - } - - foreach ($mimetype as $content) { - if (empty($content) || ! is_string($content)) { - continue; - } - $mimetypes[] = trim($content); - } - $mimetypes = array_unique($mimetypes); - - // Sanity check to ensure no empty values - foreach ($mimetypes as $key => $mt) { - if (empty($mt)) { - unset($mimetypes[$key]); - } - } - - $this->options['mimeType'] = implode(',', $mimetypes); - - return $this; - } - - /** - * Defined by Laminas\Validator\ValidatorInterface - * - * Returns true if the mimetype of the file matches the given ones. Also parts - * of mimetypes can be checked. If you give for example "image" all image - * mime types will be accepted like "image/gif", "image/jpeg" and so on. - * - * @param string|array $value Real file to check for mimetype - * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) - * @return bool - */ - public function isValid($value, $file = null) - { - $fileInfo = $this->getFileInfo($value, $file, true); - - $this->setValue($fileInfo['filename']); - - // Is file readable ? - if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { - $this->error(static::NOT_READABLE); - return false; - } - - $mimefile = $this->getMagicFile(); - if (class_exists('finfo', false)) { - if (! $this->isMagicFileDisabled() && (! empty($mimefile) && empty($this->finfo))) { - ErrorHandler::start(E_NOTICE | E_WARNING); - $this->finfo = finfo_open(FILEINFO_MIME_TYPE, $mimefile); - ErrorHandler::stop(); - } - - if (empty($this->finfo)) { - ErrorHandler::start(E_NOTICE | E_WARNING); - $this->finfo = finfo_open(FILEINFO_MIME_TYPE); - ErrorHandler::stop(); - } - - $this->type = null; - if (! empty($this->finfo)) { - $this->type = finfo_file($this->finfo, $fileInfo['file']); - unset($this->finfo); - } - } - - if (empty($this->type) && $this->getHeaderCheck()) { - $this->type = $fileInfo['filetype']; - } - - if (empty($this->type)) { - $this->error(static::NOT_DETECTED); - return false; - } - - $mimetype = $this->getMimeType(true); - if (in_array($this->type, $mimetype)) { - return true; - } - - $types = explode('/', $this->type); - $types = array_merge($types, explode('-', $this->type)); - $types = array_merge($types, explode(';', $this->type)); - foreach ($mimetype as $mime) { - if (in_array($mime, $types)) { - return true; - } - } - - $this->error(static::FALSE_TYPE); - return false; - } -} diff --git a/lib/laminas/laminas-validator/src/File/NotExists.php b/lib/laminas/laminas-validator/src/File/NotExists.php deleted file mode 100644 index 0ed8f2f18..000000000 --- a/lib/laminas/laminas-validator/src/File/NotExists.php +++ /dev/null @@ -1,68 +0,0 @@ -<?php - -namespace Laminas\Validator\File; - -use function file_exists; - -use const DIRECTORY_SEPARATOR; - -/** - * Validator which checks if the destination file does not exist - */ -class NotExists extends Exists -{ - use FileInformationTrait; - - /** - * @const string Error constants - */ - public const DOES_EXIST = 'fileNotExistsDoesExist'; - - /** @var array Error message templates */ - protected $messageTemplates = [ - self::DOES_EXIST => 'File exists', - ]; - - /** - * Returns true if and only if the file does not exist in the set destinations - * - * @param string|array $value Real file to check for existence - * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) - * @return bool - */ - public function isValid($value, $file = null) - { - $fileInfo = $this->getFileInfo($value, $file, false, true); - - $this->setValue($fileInfo['filename']); - - $check = false; - $directories = $this->getDirectory(true); - if (! isset($directories)) { - $check = true; - if (file_exists($fileInfo['file'])) { - $this->error(self::DOES_EXIST); - return false; - } - } else { - foreach ($directories as $directory) { - if (! isset($directory) || '' === $directory) { - continue; - } - - $check = true; - if (file_exists($directory . DIRECTORY_SEPARATOR . $fileInfo['basename'])) { - $this->error(self::DOES_EXIST); - return false; - } - } - } - - if (! $check) { - $this->error(self::DOES_EXIST); - return false; - } - - return true; - } -} diff --git a/lib/laminas/laminas-validator/src/File/Sha1.php b/lib/laminas/laminas-validator/src/File/Sha1.php deleted file mode 100644 index da90c45b7..000000000 --- a/lib/laminas/laminas-validator/src/File/Sha1.php +++ /dev/null @@ -1,110 +0,0 @@ -<?php - -namespace Laminas\Validator\File; - -use function array_keys; -use function array_unique; -use function hash_file; -use function is_readable; - -/** - * Validator for the sha1 hash of given files - */ -class Sha1 extends Hash -{ - use FileInformationTrait; - - /** - * @const string Error constants - */ - public const DOES_NOT_MATCH = 'fileSha1DoesNotMatch'; - public const NOT_DETECTED = 'fileSha1NotDetected'; - public const NOT_FOUND = 'fileSha1NotFound'; - - /** @var array Error message templates */ - protected $messageTemplates = [ - self::DOES_NOT_MATCH => 'File does not match the given sha1 hashes', - self::NOT_DETECTED => 'A sha1 hash could not be evaluated for the given file', - self::NOT_FOUND => 'File is not readable or does not exist', - ]; - - /** - * Options for this validator - * - * @var string - */ - protected $options = [ - 'algorithm' => 'sha1', - 'hash' => null, - ]; - - /** - * Returns all set sha1 hashes - * - * @return array - */ - public function getSha1() - { - return $this->getHash(); - } - - /** - * Sets the sha1 hash for one or multiple files - * - * @param string|array $options - * @return Hash Provides a fluent interface - */ - public function setSha1($options) - { - $this->setHash($options); - return $this; - } - - /** - * Adds the sha1 hash for one or multiple files - * - * @param string|array $options - * @return Hash Provides a fluent interface - */ - public function addSha1($options) - { - $this->addHash($options); - return $this; - } - - /** - * Returns true if and only if the given file confirms the set hash - * - * @param (int|string)[]|string $value Filename to check for hash - * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) - * @return bool - */ - public function isValid($value, $file = null) - { - $fileInfo = $this->getFileInfo($value, $file); - - $this->setValue($fileInfo['filename']); - - // Is file readable ? - if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { - $this->error(self::NOT_FOUND); - return false; - } - - $hashes = array_unique(array_keys($this->getHash())); - $filehash = hash_file('sha1', $fileInfo['file']); - if ($filehash === false) { - $this->error(self::NOT_DETECTED); - return false; - } - - foreach ($hashes as $hash) { - if ($filehash === $hash) { - return true; - } - } - - $this->error(self::DOES_NOT_MATCH); - return false; - } -} diff --git a/lib/laminas/laminas-validator/src/File/Size.php b/lib/laminas/laminas-validator/src/File/Size.php deleted file mode 100644 index d3dd64df1..000000000 --- a/lib/laminas/laminas-validator/src/File/Size.php +++ /dev/null @@ -1,359 +0,0 @@ -<?php - -namespace Laminas\Validator\File; - -use Laminas\Stdlib\ErrorHandler; -use Laminas\Validator\AbstractValidator; -use Laminas\Validator\Exception; -use Traversable; - -use function array_shift; -use function filesize; -use function func_get_args; -use function func_num_args; -use function is_numeric; -use function is_readable; -use function is_string; -use function round; -use function sprintf; -use function strtoupper; -use function substr; -use function trim; - -/** - * Validator for the maximum size of a file up to a max of 2GB - */ -class Size extends AbstractValidator -{ - use FileInformationTrait; - - /** - * @const string Error constants - */ - public const TOO_BIG = 'fileSizeTooBig'; - public const TOO_SMALL = 'fileSizeTooSmall'; - public const NOT_FOUND = 'fileSizeNotFound'; - - /** @var array Error message templates */ - protected $messageTemplates = [ - self::TOO_BIG => "Maximum allowed size for file is '%max%' but '%size%' detected", - self::TOO_SMALL => "Minimum expected size for file is '%min%' but '%size%' detected", - self::NOT_FOUND => 'File is not readable or does not exist', - ]; - - /** @var array Error message template variables */ - protected $messageVariables = [ - 'min' => ['options' => 'min'], - 'max' => ['options' => 'max'], - 'size' => 'size', - ]; - - /** - * Detected size - * - * @var int - */ - protected $size; - - /** - * Options for this validator - * - * @var array - */ - protected $options = [ - 'min' => null, // Minimum file size, if null there is no minimum - 'max' => null, // Maximum file size, if null there is no maximum - 'useByteString' => true, // Use byte string? - ]; - - /** - * Sets validator options - * - * If $options is an integer, it will be used as maximum file size - * As Array is accepts the following keys: - * 'min': Minimum file size - * 'max': Maximum file size - * 'useByteString': Use bytestring or real size for messages - * - * @param int|array|Traversable $options Options for the adapter - */ - public function __construct($options = null) - { - if (is_string($options) || is_numeric($options)) { - $options = ['max' => $options]; - } - - if (1 < func_num_args()) { - $argv = func_get_args(); - array_shift($argv); - $options['max'] = array_shift($argv); - if (! empty($argv)) { - $options['useByteString'] = array_shift($argv); - } - } - - parent::__construct($options); - } - - /** - * Should messages return bytes as integer or as string in SI notation - * - * @param bool $byteString Use bytestring ? - * @return self - */ - public function useByteString($byteString = true) - { - $this->options['useByteString'] = (bool) $byteString; - return $this; - } - - /** - * Will bytestring be used? - * - * @return bool - */ - public function getByteString() - { - return $this->options['useByteString']; - } - - /** - * Returns the minimum file size - * - * @param bool $raw Whether or not to force return of the raw value (defaults off) - * @return int|string - */ - public function getMin($raw = false) - { - $min = $this->options['min']; - if (! $raw && $this->getByteString()) { - $min = $this->toByteString($min); - } - - return $min; - } - - /** - * Sets the minimum file size - * - * File size can be an integer or a byte string - * This includes 'B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB' - * For example: 2000, 2MB, 0.2GB - * - * @param int|string $min The minimum file size - * @return $this Provides a fluent interface - * @throws Exception\InvalidArgumentException When min is greater than max. - */ - public function setMin($min) - { - if (! is_string($min) && ! is_numeric($min)) { - throw new Exception\InvalidArgumentException('Invalid options to validator provided'); - } - - $min = (int) $this->fromByteString($min); - $max = $this->getMax(true); - if (($max !== null) && ($min > $max)) { - throw new Exception\InvalidArgumentException( - "The minimum must be less than or equal to the maximum file size, but $min > $max" - ); - } - - $this->options['min'] = $min; - return $this; - } - - /** - * Returns the maximum file size - * - * @param bool $raw Whether or not to force return of the raw value (defaults off) - * @return int|string - */ - public function getMax($raw = false) - { - $max = $this->options['max']; - if (! $raw && $this->getByteString()) { - $max = $this->toByteString($max); - } - - return $max; - } - - /** - * Sets the maximum file size - * - * File size can be an integer or a byte string - * This includes 'B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB' - * For example: 2000, 2MB, 0.2GB - * - * @param int|string $max The maximum file size - * @return $this Provides a fluent interface - * @throws Exception\InvalidArgumentException When max is smaller than min. - */ - public function setMax($max) - { - if (! is_string($max) && ! is_numeric($max)) { - throw new Exception\InvalidArgumentException('Invalid options to validator provided'); - } - - $max = (int) $this->fromByteString($max); - $min = $this->getMin(true); - if (($min !== null) && ($max < $min)) { - throw new Exception\InvalidArgumentException( - "The maximum must be greater than or equal to the minimum file size, but $max < $min" - ); - } - - $this->options['max'] = $max; - return $this; - } - - /** - * Retrieve current detected file size - * - * @return int - */ - protected function getSize() - { - return $this->size; - } - - /** - * Set current size - * - * @param int $size - * @return $this - */ - protected function setSize($size) - { - $this->size = $size; - return $this; - } - - /** - * Returns true if and only if the file size of $value is at least min and - * not bigger than max (when max is not null). - * - * @param string|array $value File to check for size - * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) - * @return bool - */ - public function isValid($value, $file = null) - { - $fileInfo = $this->getFileInfo($value, $file); - - $this->setValue($fileInfo['filename']); - - // Is file readable ? - if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { - $this->error(self::NOT_FOUND); - return false; - } - - // limited to 4GB files - ErrorHandler::start(); - $size = sprintf('%u', filesize($fileInfo['file'])); - ErrorHandler::stop(); - $this->size = $size; - - // Check to see if it's smaller than min size - $min = $this->getMin(true); - $max = $this->getMax(true); - if (($min !== null) && ($size < $min)) { - if ($this->getByteString()) { - $this->options['min'] = $this->toByteString($min); - $this->size = $this->toByteString($size); - $this->error(self::TOO_SMALL); - $this->options['min'] = $min; - $this->size = $size; - } else { - $this->error(self::TOO_SMALL); - } - } - - // Check to see if it's larger than max size - if (($max !== null) && ($max < $size)) { - if ($this->getByteString()) { - $this->options['max'] = $this->toByteString($max); - $this->size = $this->toByteString($size); - $this->error(self::TOO_BIG); - $this->options['max'] = $max; - $this->size = $size; - } else { - $this->error(self::TOO_BIG); - } - } - - if ($this->getMessages()) { - return false; - } - - return true; - } - - /** - * Returns the formatted size - * - * @param int $size - * @return string - */ - protected function toByteString($size) - { - $sizes = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; - for ($i = 0; $size >= 1024 && $i < 9; $i++) { - $size /= 1024; - } - - return round($size, 2) . $sizes[$i]; - } - - /** - * Returns the unformatted size - * - * @param string $size - * @return float|int|string - */ - protected function fromByteString($size) - { - if (is_numeric($size)) { - return (int) $size; - } - - $type = trim(substr($size, -2, 1)); - - $value = substr($size, 0, -1); - if (! is_numeric($value)) { - $value = trim(substr($value, 0, -1)); - } - - switch (strtoupper($type)) { - case 'Y': - $value *= 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024; - break; - case 'Z': - $value *= 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024; - break; - case 'E': - $value *= 1024 * 1024 * 1024 * 1024 * 1024 * 1024; - break; - case 'P': - $value *= 1024 * 1024 * 1024 * 1024 * 1024; - break; - case 'T': - $value *= 1024 * 1024 * 1024 * 1024; - break; - case 'G': - $value *= 1024 * 1024 * 1024; - break; - case 'M': - $value *= 1024 * 1024; - break; - case 'K': - $value *= 1024; - break; - default: - break; - } - - return $value; - } -} diff --git a/lib/laminas/laminas-validator/src/File/Upload.php b/lib/laminas/laminas-validator/src/File/Upload.php deleted file mode 100644 index 10a0f2f3e..000000000 --- a/lib/laminas/laminas-validator/src/File/Upload.php +++ /dev/null @@ -1,270 +0,0 @@ -<?php - -namespace Laminas\Validator\File; - -use Laminas\Validator\AbstractValidator; -use Laminas\Validator\Exception; -use Psr\Http\Message\UploadedFileInterface; -use Traversable; - -use function array_key_exists; -use function array_merge; -use function count; -use function is_array; -use function is_countable; -use function is_string; -use function is_uploaded_file; - -/** - * Validator for the maximum size of a file up to a max of 2GB - */ -class Upload extends AbstractValidator -{ - /** - * @const string Error constants - */ - public const INI_SIZE = 'fileUploadErrorIniSize'; - public const FORM_SIZE = 'fileUploadErrorFormSize'; - public const PARTIAL = 'fileUploadErrorPartial'; - public const NO_FILE = 'fileUploadErrorNoFile'; - public const NO_TMP_DIR = 'fileUploadErrorNoTmpDir'; - public const CANT_WRITE = 'fileUploadErrorCantWrite'; - public const EXTENSION = 'fileUploadErrorExtension'; - public const ATTACK = 'fileUploadErrorAttack'; - public const FILE_NOT_FOUND = 'fileUploadErrorFileNotFound'; - public const UNKNOWN = 'fileUploadErrorUnknown'; - - /** @var array<string, string> Error message templates */ - protected $messageTemplates = [ - self::INI_SIZE => "File '%value%' exceeds upload_max_filesize directive in php.ini", - self::FORM_SIZE => "File '%value%' exceeds the MAX_FILE_SIZE directive that was " - . 'specified in the HTML form', - self::PARTIAL => "File '%value%' was only partially uploaded", - self::NO_FILE => "File '%value%' was not uploaded", - self::NO_TMP_DIR => "Missing a temporary folder to store '%value%'", - self::CANT_WRITE => "Failed to write file '%value%' to disk", - self::EXTENSION => "A PHP extension stopped uploading the file '%value%'", - self::ATTACK => "File '%value%' was illegally uploaded. This could be a possible attack", - self::FILE_NOT_FOUND => "File '%value%' was not found", - self::UNKNOWN => "Unknown error while uploading file '%value%'", - ]; - - /** @var array<string, mixed> */ - protected $options = [ - 'files' => [], - ]; - - /** - * Sets validator options - * - * The array $files must be given in syntax of Laminas\File\Transfer\Transfer to be checked - * If no files are given the $_FILES array will be used automatically. - * NOTE: This validator will only work with HTTP POST uploads! - * - * @param array|Traversable $options Array of files in syntax of \Laminas\File\Transfer\Transfer - */ - public function __construct($options = []) - { - if (is_array($options) && ! array_key_exists('files', $options)) { - $options = ['files' => $options]; - } - - parent::__construct($options); - } - - /** - * Returns the array of set files - * - * @param string $file (Optional) The file to return in detail - * @return array - * @throws Exception\InvalidArgumentException If file is not found. - */ - public function getFiles($file = null) - { - if ($file !== null) { - $return = []; - foreach ($this->options['files'] as $name => $content) { - if ($name === $file) { - $return[$file] = $this->options['files'][$name]; - } - - if ($content instanceof UploadedFileInterface) { - if ($content->getClientFilename() === $file) { - $return[$name] = $this->options['files'][$name]; - } - } elseif ($content['name'] === $file) { - $return[$name] = $this->options['files'][$name]; - } - } - - if (! $return) { - throw new Exception\InvalidArgumentException("The file '$file' was not found"); - } - - return $return; - } - - return $this->options['files']; - } - - /** - * Sets the files to be checked - * - * @param array $files The files to check in syntax of \Laminas\File\Transfer\Transfer - * @return $this Provides a fluent interface - */ - public function setFiles($files = []) - { - if ( - null === $files - || ((is_countable($files)) - && count($files) === 0) - ) { - $this->options['files'] = $_FILES; - } else { - $this->options['files'] = $files; - } - - if ($this->options['files'] === null) { - $this->options['files'] = []; - } - - foreach ($this->options['files'] as $file => $content) { - if ( - ! $content instanceof UploadedFileInterface - && ! isset($content['error']) - ) { - unset($this->options['files'][$file]); - } - } - - return $this; - } - - /** - * Returns true if and only if the file was uploaded without errors - * - * @param string $value Single file to check for upload errors, when giving null the $_FILES array - * from initialization will be used - * @param mixed $file - * @return bool - */ - public function isValid($value, $file = null) - { - $files = []; - $this->setValue($value); - if (array_key_exists($value, $this->getFiles())) { - $files = array_merge($files, $this->getFiles($value)); - } else { - foreach ($this->getFiles() as $file => $content) { - if ($content instanceof UploadedFileInterface) { - if ($content->getClientFilename() === $value) { - $files = array_merge($files, $this->getFiles($file)); - } - - // PSR cannot search by tmp_name because it does not have - // a public interface to get it, only user defined name - // from form field. - continue; - } - - if (isset($content['name']) && ($content['name'] === $value)) { - $files = array_merge($files, $this->getFiles($file)); - } - - if (isset($content['tmp_name']) && ($content['tmp_name'] === $value)) { - $files = array_merge($files, $this->getFiles($file)); - } - } - } - - if (empty($files)) { - return $this->throwError($file, self::FILE_NOT_FOUND); - } - - foreach ($files as $file => $content) { - $this->value = $file; - $error = $content instanceof UploadedFileInterface - ? $content->getError() - : $content['error']; - - switch ($error) { - case 0: - if ($content instanceof UploadedFileInterface) { - // done! - break; - } - - // For standard SAPI environments, check that the upload - // was valid - if (! is_uploaded_file($content['tmp_name'])) { - $this->throwError($content, self::ATTACK); - } - break; - - case 1: - $this->throwError($content, self::INI_SIZE); - break; - - case 2: - $this->throwError($content, self::FORM_SIZE); - break; - - case 3: - $this->throwError($content, self::PARTIAL); - break; - - case 4: - $this->throwError($content, self::NO_FILE); - break; - - case 6: - $this->throwError($content, self::NO_TMP_DIR); - break; - - case 7: - $this->throwError($content, self::CANT_WRITE); - break; - - case 8: - $this->throwError($content, self::EXTENSION); - break; - - default: - $this->throwError($content, self::UNKNOWN); - break; - } - } - - if ($this->getMessages()) { - return false; - } - - return true; - } - - /** - * Throws an error of the given type - * - * @param array|string|UploadedFileInterface $file - * @param string $errorType - * @return false - */ - protected function throwError($file, $errorType) - { - if ($file !== null) { - if (is_array($file)) { - if (array_key_exists('name', $file)) { - $this->value = $file['name']; - } - } elseif (is_string($file)) { - $this->value = $file; - } elseif ($file instanceof UploadedFileInterface) { - $this->value = $file->getClientFilename(); - } - } - - $this->error($errorType); - return false; - } -} diff --git a/lib/laminas/laminas-validator/src/File/UploadFile.php b/lib/laminas/laminas-validator/src/File/UploadFile.php deleted file mode 100644 index 9d73f54af..000000000 --- a/lib/laminas/laminas-validator/src/File/UploadFile.php +++ /dev/null @@ -1,175 +0,0 @@ -<?php - -namespace Laminas\Validator\File; - -use Laminas\Validator\AbstractValidator; -use Laminas\Validator\Exception; -use Psr\Http\Message\UploadedFileInterface; - -use function basename; -use function is_array; -use function is_file; -use function is_string; -use function is_uploaded_file; - -use const UPLOAD_ERR_CANT_WRITE; -use const UPLOAD_ERR_EXTENSION; -use const UPLOAD_ERR_FORM_SIZE; -use const UPLOAD_ERR_INI_SIZE; -use const UPLOAD_ERR_NO_FILE; -use const UPLOAD_ERR_NO_TMP_DIR; -use const UPLOAD_ERR_OK; -use const UPLOAD_ERR_PARTIAL; - -/** - * Validator for the maximum size of a file up to a max of 2GB - */ -class UploadFile extends AbstractValidator -{ - /** - * @const string Error constants - */ - public const INI_SIZE = 'fileUploadFileErrorIniSize'; - public const FORM_SIZE = 'fileUploadFileErrorFormSize'; - public const PARTIAL = 'fileUploadFileErrorPartial'; - public const NO_FILE = 'fileUploadFileErrorNoFile'; - public const NO_TMP_DIR = 'fileUploadFileErrorNoTmpDir'; - public const CANT_WRITE = 'fileUploadFileErrorCantWrite'; - public const EXTENSION = 'fileUploadFileErrorExtension'; - public const ATTACK = 'fileUploadFileErrorAttack'; - public const FILE_NOT_FOUND = 'fileUploadFileErrorFileNotFound'; - public const UNKNOWN = 'fileUploadFileErrorUnknown'; - - /** @var array Error message templates */ - protected $messageTemplates = [ - self::INI_SIZE => 'The uploaded file exceeds the upload_max_filesize directive in php.ini', - self::FORM_SIZE => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was ' - . 'specified in the HTML form', - self::PARTIAL => 'The uploaded file was only partially uploaded', - self::NO_FILE => 'No file was uploaded', - self::NO_TMP_DIR => 'Missing a temporary folder', - self::CANT_WRITE => 'Failed to write file to disk', - self::EXTENSION => 'A PHP extension stopped the file upload', - self::ATTACK => 'File was illegally uploaded. This could be a possible attack', - self::FILE_NOT_FOUND => 'File was not found', - self::UNKNOWN => 'Unknown error while uploading file', - ]; - - /** - * Returns true if and only if the file was uploaded without errors - * - * @param string|array|UploadedFileInterface $value File to check for upload errors - * @return bool - * @throws Exception\InvalidArgumentException - */ - public function isValid($value) - { - if (is_array($value)) { - if (! isset($value['tmp_name']) || ! isset($value['name']) || ! isset($value['error'])) { - throw new Exception\InvalidArgumentException( - 'Value array must be in $_FILES format' - ); - } - - return $this->validateUploadedFile( - $value['error'], - $value['name'], - $value['tmp_name'] - ); - } - - if ($value instanceof UploadedFileInterface) { - return $this->validatePsr7UploadedFile($value); - } - - if (is_string($value)) { - return $this->validateUploadedFile(0, basename($value), $value); - } - - $this->error(self::UNKNOWN); - return false; - } - - /** - * @param int $error UPLOAD_ERR_* constant value - * @return bool - */ - private function validateFileFromErrorCode($error) - { - switch ($error) { - case UPLOAD_ERR_OK: - return true; - - case UPLOAD_ERR_INI_SIZE: - $this->error(self::INI_SIZE); - return false; - - case UPLOAD_ERR_FORM_SIZE: - $this->error(self::FORM_SIZE); - return false; - - case UPLOAD_ERR_PARTIAL: - $this->error(self::PARTIAL); - return false; - - case UPLOAD_ERR_NO_FILE: - $this->error(self::NO_FILE); - return false; - - case UPLOAD_ERR_NO_TMP_DIR: - $this->error(self::NO_TMP_DIR); - return false; - - case UPLOAD_ERR_CANT_WRITE: - $this->error(self::CANT_WRITE); - return false; - - case UPLOAD_ERR_EXTENSION: - $this->error(self::EXTENSION); - return false; - - default: - $this->error(self::UNKNOWN); - return false; - } - } - - /** - * @param int $error UPLOAD_ERR_* constant - * @param string $filename - * @param string $uploadedFile Name of uploaded file (gen tmp_name) - * @return bool - */ - private function validateUploadedFile($error, $filename, $uploadedFile) - { - $this->setValue($filename); - - // Normal errors can be validated normally - if ($error !== UPLOAD_ERR_OK) { - return $this->validateFileFromErrorCode($error); - } - - // Did we get no name? Is the file missing? - if (empty($uploadedFile) || false === is_file($uploadedFile)) { - $this->error(self::FILE_NOT_FOUND); - return false; - } - - // Do we have an invalid upload? - if (! is_uploaded_file($uploadedFile)) { - $this->error(self::ATTACK); - return false; - } - - return true; - } - - /** - * @return bool - */ - private function validatePsr7UploadedFile(UploadedFileInterface $uploadedFile) - { - $this->setValue($uploadedFile); - return $this->validateFileFromErrorCode($uploadedFile->getError()); - } -} diff --git a/lib/laminas/laminas-validator/src/File/WordCount.php b/lib/laminas/laminas-validator/src/File/WordCount.php deleted file mode 100644 index 107fb6fdd..000000000 --- a/lib/laminas/laminas-validator/src/File/WordCount.php +++ /dev/null @@ -1,204 +0,0 @@ -<?php - -namespace Laminas\Validator\File; - -use Laminas\Validator\AbstractValidator; -use Laminas\Validator\Exception; -use Traversable; - -use function array_shift; -use function file_get_contents; -use function func_get_args; -use function func_num_args; -use function is_array; -use function is_numeric; -use function is_readable; -use function is_string; -use function str_word_count; - -/** - * Validator for counting all words in a file - */ -class WordCount extends AbstractValidator -{ - use FileInformationTrait; - - /** - * @const string Error constants - */ - public const TOO_MUCH = 'fileWordCountTooMuch'; - public const TOO_LESS = 'fileWordCountTooLess'; - public const NOT_FOUND = 'fileWordCountNotFound'; - - /** @var array Error message templates */ - protected $messageTemplates = [ - self::TOO_MUCH => "Too many words, maximum '%max%' are allowed but '%count%' were counted", - self::TOO_LESS => "Too few words, minimum '%min%' are expected but '%count%' were counted", - self::NOT_FOUND => 'File is not readable or does not exist', - ]; - - /** @var array Error message template variables */ - protected $messageVariables = [ - 'min' => ['options' => 'min'], - 'max' => ['options' => 'max'], - 'count' => 'count', - ]; - - /** - * Word count - * - * @var int - */ - protected $count; - - /** - * Options for this validator - * - * @var array - */ - protected $options = [ - 'min' => null, // Minimum word count, if null there is no minimum word count - 'max' => null, // Maximum word count, if null there is no maximum word count - ]; - - /** - * Sets validator options - * - * Min limits the word count, when used with max=null it is the maximum word count - * It also accepts an array with the keys 'min' and 'max' - * - * If $options is an integer, it will be used as maximum word count - * As Array is accepts the following keys: - * 'min': Minimum word count - * 'max': Maximum word count - * - * @param int|array|Traversable $options Options for the adapter - */ - public function __construct($options = null) - { - if (1 < func_num_args()) { - $args = func_get_args(); - $options = [ - 'min' => array_shift($args), - 'max' => array_shift($args), - ]; - } - - if (is_string($options) || is_numeric($options)) { - $options = ['max' => $options]; - } - - parent::__construct($options); - } - - /** - * Returns the minimum word count - * - * @return int - */ - public function getMin() - { - return $this->options['min']; - } - - /** - * Sets the minimum word count - * - * @param int|array $min The minimum word count - * @return $this Provides a fluent interface - * @throws Exception\InvalidArgumentException When min is greater than max. - */ - public function setMin($min) - { - if (is_array($min) && isset($min['min'])) { - $min = $min['min']; - } - - if (! is_numeric($min)) { - throw new Exception\InvalidArgumentException('Invalid options to validator provided'); - } - - $min = (int) $min; - if (($this->getMax() !== null) && ($min > $this->getMax())) { - throw new Exception\InvalidArgumentException( - "The minimum must be less than or equal to the maximum word count, but $min > {$this->getMax()}" - ); - } - - $this->options['min'] = $min; - return $this; - } - - /** - * Returns the maximum word count - * - * @return int - */ - public function getMax() - { - return $this->options['max']; - } - - /** - * Sets the maximum file count - * - * @param int|array $max The maximum word count - * @return $this Provides a fluent interface - * @throws Exception\InvalidArgumentException When max is smaller than min. - */ - public function setMax($max) - { - if (is_array($max) && isset($max['max'])) { - $max = $max['max']; - } - - if (! is_numeric($max)) { - throw new Exception\InvalidArgumentException('Invalid options to validator provided'); - } - - $max = (int) $max; - if (($this->getMin() !== null) && ($max < $this->getMin())) { - throw new Exception\InvalidArgumentException( - "The maximum must be greater than or equal to the minimum word count, but $max < {$this->getMin()}" - ); - } - - $this->options['max'] = $max; - return $this; - } - - /** - * Returns true if and only if the counted words are at least min and - * not bigger than max (when max is not null). - * - * @param string|array $value Filename to check for word count - * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) - * @return bool - */ - public function isValid($value, $file = null) - { - $fileInfo = $this->getFileInfo($value, $file); - - $this->setValue($fileInfo['filename']); - - // Is file readable ? - if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { - $this->error(self::NOT_FOUND); - return false; - } - - $content = file_get_contents($fileInfo['file']); - $this->count = str_word_count($content); - if (($this->getMax() !== null) && ($this->count > $this->getMax())) { - $this->error(self::TOO_MUCH); - return false; - } - - if (($this->getMin() !== null) && ($this->count < $this->getMin())) { - $this->error(self::TOO_LESS); - return false; - } - - return true; - } -} diff --git a/lib/laminas/laminas-validator/src/GpsPoint.php b/lib/laminas/laminas-validator/src/GpsPoint.php deleted file mode 100644 index 7090a4590..000000000 --- a/lib/laminas/laminas-validator/src/GpsPoint.php +++ /dev/null @@ -1,122 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use function explode; -use function preg_match; -use function preg_match_all; -use function preg_replace; -use function str_replace; -use function strpos; - -final class GpsPoint extends AbstractValidator -{ - public const OUT_OF_BOUNDS = 'gpsPointOutOfBounds'; - public const CONVERT_ERROR = 'gpsPointConvertError'; - public const INCOMPLETE_COORDINATE = 'gpsPointIncompleteCoordinate'; - - /** @var array */ - protected $messageTemplates = [ - 'gpsPointOutOfBounds' => '%value% is out of Bounds.', - 'gpsPointConvertError' => '%value% can not converted into a Decimal Degree Value.', - 'gpsPointIncompleteCoordinate' => '%value% did not provided a complete Coordinate', - ]; - - /** - * Returns true if and only if $value meets the validation requirements - * - * If $value fails validation, then this method returns false, and - * getMessages() will return an array of messages that explain why the - * validation failed. - * - * @param mixed $value - * @return bool - * @throws Exception\RuntimeException If validation of $value is impossible. - */ - public function isValid($value) - { - if (strpos($value, ',') === false) { - $this->error(self::INCOMPLETE_COORDINATE, $value); - return false; - } - - [$lat, $long] = explode(',', $value); - - if ($this->isValidCoordinate($lat, 90.0000) && $this->isValidCoordinate($long, 180.000)) { - return true; - } - - return false; - } - - /** - * @param string $value - */ - private function isValidCoordinate($value, float $maxBoundary): bool - { - $this->value = $value; - - $value = $this->removeWhiteSpace($value); - if ($this->isDMSValue($value)) { - $value = $this->convertValue($value); - } else { - $value = $this->removeDegreeSign($value); - } - - if ($value === false || $value === null) { - $this->error(self::CONVERT_ERROR); - return false; - } - - $doubleLatitude = (double) $value; - - if ($doubleLatitude <= $maxBoundary && $doubleLatitude >= $maxBoundary * -1) { - return true; - } - - $this->error(self::OUT_OF_BOUNDS); - return false; - } - - /** - * Determines if the give value is a Degrees Minutes Second Definition - */ - private function isDMSValue(string $value): bool - { - return preg_match('/([°\'"]+[NESW])/', $value) > 0; - } - - /** - * @param string $value - * @return false|float - */ - private function convertValue($value) - { - $matches = []; - $result = preg_match_all('/(\d{1,3})°(\d{1,2})\'(\d{1,2}[\.\d]{0,6})"[NESW]/i', $value, $matches); - - if ($result === false || $result === 0) { - return false; - } - - return $matches[1][0] + $matches[2][0] / 60 + ((double) $matches[3][0]) / 3600; - } - - /** - * @param string $value - * @return string - */ - private function removeWhiteSpace($value) - { - return preg_replace('/\s/', '', $value); - } - - /** - * @param string $value - * @return string - */ - private function removeDegreeSign($value) - { - return str_replace('°', '', $value); - } -} diff --git a/lib/laminas/laminas-validator/src/GreaterThan.php b/lib/laminas/laminas-validator/src/GreaterThan.php deleted file mode 100644 index bab3846ad..000000000 --- a/lib/laminas/laminas-validator/src/GreaterThan.php +++ /dev/null @@ -1,154 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use Laminas\Stdlib\ArrayUtils; -use Traversable; - -use function array_key_exists; -use function array_shift; -use function func_get_args; -use function is_array; - -class GreaterThan extends AbstractValidator -{ - public const NOT_GREATER = 'notGreaterThan'; - public const NOT_GREATER_INCLUSIVE = 'notGreaterThanInclusive'; - - /** - * Validation failure message template definitions - * - * @var array - */ - protected $messageTemplates = [ - self::NOT_GREATER => "The input is not greater than '%min%'", - self::NOT_GREATER_INCLUSIVE => "The input is not greater than or equal to '%min%'", - ]; - - /** @var array */ - protected $messageVariables = [ - 'min' => 'min', - ]; - - /** - * Minimum value - * - * @var mixed - */ - protected $min; - - /** - * Whether to do inclusive comparisons, allowing equivalence to max - * - * If false, then strict comparisons are done, and the value may equal - * the min option - * - * @var bool - */ - protected $inclusive; - - /** - * Sets validator options - * - * @param array|Traversable $options - * @throws Exception\InvalidArgumentException - */ - public function __construct($options = null) - { - if ($options instanceof Traversable) { - $options = ArrayUtils::iteratorToArray($options); - } - if (! is_array($options)) { - $options = func_get_args(); - $temp['min'] = array_shift($options); - - if (! empty($options)) { - $temp['inclusive'] = array_shift($options); - } - - $options = $temp; - } - - if (! array_key_exists('min', $options)) { - throw new Exception\InvalidArgumentException("Missing option 'min'"); - } - - if (! array_key_exists('inclusive', $options)) { - $options['inclusive'] = false; - } - - $this->setMin($options['min']) - ->setInclusive($options['inclusive']); - - parent::__construct($options); - } - - /** - * Returns the min option - * - * @return mixed - */ - public function getMin() - { - return $this->min; - } - - /** - * Sets the min option - * - * @param mixed $min - * @return $this Provides a fluent interface - */ - public function setMin($min) - { - $this->min = $min; - return $this; - } - - /** - * Returns the inclusive option - * - * @return bool - */ - public function getInclusive() - { - return $this->inclusive; - } - - /** - * Sets the inclusive option - * - * @param bool $inclusive - * @return $this Provides a fluent interface - */ - public function setInclusive($inclusive) - { - $this->inclusive = $inclusive; - return $this; - } - - /** - * Returns true if and only if $value is greater than min option - * - * @param mixed $value - * @return bool - */ - public function isValid($value) - { - $this->setValue($value); - - if ($this->inclusive) { - if ($this->min > $value) { - $this->error(self::NOT_GREATER_INCLUSIVE); - return false; - } - } else { - if ($this->min >= $value) { - $this->error(self::NOT_GREATER); - return false; - } - } - - return true; - } -} diff --git a/lib/laminas/laminas-validator/src/Hex.php b/lib/laminas/laminas-validator/src/Hex.php deleted file mode 100644 index b00198578..000000000 --- a/lib/laminas/laminas-validator/src/Hex.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use function ctype_xdigit; -use function is_int; -use function is_string; - -class Hex extends AbstractValidator -{ - public const INVALID = 'hexInvalid'; - public const NOT_HEX = 'notHex'; - - /** - * Validation failure message template definitions - * - * @var array - */ - protected $messageTemplates = [ - self::INVALID => 'Invalid type given. String expected', - self::NOT_HEX => 'The input contains non-hexadecimal characters', - ]; - - /** - * Returns true if and only if $value contains only hexadecimal digit characters - * - * @param string $value - * @return bool - */ - public function isValid($value) - { - if (! is_string($value) && ! is_int($value)) { - $this->error(self::INVALID); - return false; - } - - $this->setValue($value); - if (! ctype_xdigit((string) $value)) { - $this->error(self::NOT_HEX); - return false; - } - - return true; - } -} diff --git a/lib/laminas/laminas-validator/src/Hostname.php b/lib/laminas/laminas-validator/src/Hostname.php deleted file mode 100644 index a5fb700d5..000000000 --- a/lib/laminas/laminas-validator/src/Hostname.php +++ /dev/null @@ -1,2293 +0,0 @@ -<?php // phpcs:disable Generic.Files.LineLength.TooLong - -namespace Laminas\Validator; - -use Laminas\Stdlib\StringUtils; - -use function array_key_exists; -use function array_pop; -use function array_shift; -use function chr; -use function count; -use function end; -use function explode; -use function func_get_args; -use function implode; -use function in_array; -use function intval; -use function is_array; -use function is_string; -use function ord; -use function preg_match; -use function prev; -use function reset; -use function strlen; -use function strpos; -use function strrpos; -use function strtolower; -use function strtoupper; -use function substr; - -/** - * Please note there are two standalone test scripts for testing IDN characters due to problems - * with file encoding. - * - * The first is tests/Laminas/Validator/HostnameTestStandalone.php which is designed to be run on - * the command line. - * - * The second is tests/Laminas/Validator/HostnameTestForm.php which is designed to be run via HTML - * to allow users to test entering UTF-8 characters in a form. - */ -class Hostname extends AbstractValidator -{ - public const CANNOT_DECODE_PUNYCODE = 'hostnameCannotDecodePunycode'; - public const INVALID = 'hostnameInvalid'; - public const INVALID_DASH = 'hostnameDashCharacter'; - public const INVALID_HOSTNAME = 'hostnameInvalidHostname'; - public const INVALID_HOSTNAME_SCHEMA = 'hostnameInvalidHostnameSchema'; - public const INVALID_LOCAL_NAME = 'hostnameInvalidLocalName'; - public const INVALID_URI = 'hostnameInvalidUri'; - public const IP_ADDRESS_NOT_ALLOWED = 'hostnameIpAddressNotAllowed'; - public const LOCAL_NAME_NOT_ALLOWED = 'hostnameLocalNameNotAllowed'; - public const UNDECIPHERABLE_TLD = 'hostnameUndecipherableTld'; - public const UNKNOWN_TLD = 'hostnameUnknownTld'; - - /** @var array */ - protected $messageTemplates = [ - self::CANNOT_DECODE_PUNYCODE => "The input appears to be a DNS hostname but the given punycode notation cannot be decoded", - self::INVALID => "Invalid type given. String expected", - self::INVALID_DASH => "The input appears to be a DNS hostname but contains a dash in an invalid position", - self::INVALID_HOSTNAME => "The input does not match the expected structure for a DNS hostname", - self::INVALID_HOSTNAME_SCHEMA => "The input appears to be a DNS hostname but cannot match against hostname schema for TLD '%tld%'", - self::INVALID_LOCAL_NAME => "The input does not appear to be a valid local network name", - self::INVALID_URI => "The input does not appear to be a valid URI hostname", - self::IP_ADDRESS_NOT_ALLOWED => "The input appears to be an IP address, but IP addresses are not allowed", - self::LOCAL_NAME_NOT_ALLOWED => "The input appears to be a local network name but local network names are not allowed", - self::UNDECIPHERABLE_TLD => "The input appears to be a DNS hostname but cannot extract TLD part", - self::UNKNOWN_TLD => "The input appears to be a DNS hostname but cannot match TLD against known list", - ]; - - /** @var array */ - protected $messageVariables = [ - 'tld' => 'tld', - ]; - - public const ALLOW_DNS = 1; // Allows Internet domain names (e.g., example.com) - public const ALLOW_IP = 2; // Allows IP addresses - public const ALLOW_LOCAL = 4; // Allows local network names (e.g., localhost, www.localdomain) - public const ALLOW_URI = 8; // Allows URI hostnames - public const ALLOW_ALL = 15; // Allows all types of hostnames - - /** - * Array of valid top-level-domains - * IanaVersion 2022072400 - * - * @see ftp://data.iana.org/TLD/tlds-alpha-by-domain.txt List of all TLDs by domain - * @see http://www.iana.org/domains/root/db/ Official list of supported TLDs - * - * @var string[] - */ - protected $validTlds = [ - 'aaa', - 'aarp', - 'abarth', - 'abb', - 'abbott', - 'abbvie', - 'abc', - 'able', - 'abogado', - 'abudhabi', - 'ac', - 'academy', - 'accenture', - 'accountant', - 'accountants', - 'aco', - 'actor', - 'ad', - 'adac', - 'ads', - 'adult', - 'ae', - 'aeg', - 'aero', - 'aetna', - 'af', - 'afl', - 'africa', - 'ag', - 'agakhan', - 'agency', - 'ai', - 'aig', - 'airbus', - 'airforce', - 'airtel', - 'akdn', - 'al', - 'alfaromeo', - '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', - 'bugatti', - 'build', - 'builders', - 'business', - 'buy', - 'buzz', - 'bv', - 'bw', - 'by', - 'bz', - 'bzh', - 'ca', - 'cab', - 'cafe', - 'cal', - 'call', - 'calvinklein', - 'cam', - 'camera', - 'camp', - 'cancerresearch', - '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', - 'fiat', - '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', - 'lancia', - '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', - 'linde', - 'link', - 'lipsy', - 'live', - 'living', - 'lk', - 'llc', - 'llp', - 'loan', - 'loans', - 'locker', - 'locus', - 'loft', - 'lol', - 'london', - 'lotte', - 'lotto', - 'love', - 'lpl', - 'lplfinancial', - 'lr', - 'ls', - 'lt', - 'ltd', - 'ltda', - 'lu', - 'lundbeck', - 'luxe', - 'luxury', - 'lv', - 'ly', - 'ma', - 'macys', - 'madrid', - 'maif', - 'maison', - 'makeup', - 'man', - 'management', - 'mango', - 'map', - 'market', - 'marketing', - 'markets', - 'marriott', - 'marshalls', - 'maserati', - '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', - 'ses', - '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', - 'कॉम', - 'セール', - '佛山', - 'ಭಾರತ', - '慈善', - '集团', - '在线', - '한국', - 'ଭାରତ', - '点看', - 'คอม', - 'ভাৰত', - 'ভারত', - '八卦', - 'ישראל', - 'موقع', - 'বাংলা', - '公益', - '公司', - '香格里拉', - '网站', - '移动', - '我爱你', - 'москва', - 'қаз', - 'католик', - 'онлайн', - 'сайт', - '联通', - 'срб', - 'бг', - 'бел', - 'קום', - '时尚', - '微博', - '淡马锡', - 'ファッション', - 'орг', - 'नेट', - 'ストア', - 'アマゾン', - '삼성', - 'சிங்கப்பூர்', - '商标', - '商店', - '商城', - 'дети', - 'мкд', - 'ею', - 'ポイント', - '新闻', - '家電', - 'كوم', - '中文网', - '中信', - '中国', - '中國', - '娱乐', - '谷歌', - 'భారత్', - 'ලංකා', - '電訊盈科', - '购物', - 'クラウド', - 'ભારત', - '通販', - 'भारतम्', - 'भारत', - 'भारोत', - '网店', - 'संगठन', - '餐厅', - '网络', - 'ком', - 'укр', - '香港', - '亚马逊', - '诺基亚', - '食品', - '飞利浦', - '台湾', - '台灣', - '手机', - 'мон', - 'الجزائر', - 'عمان', - 'ارامكو', - 'ایران', - 'العليان', - 'اتصالات', - 'امارات', - 'بازار', - 'موريتانيا', - 'پاکستان', - 'الاردن', - 'بارت', - 'بھارت', - 'المغرب', - 'ابوظبي', - 'البحرين', - 'السعودية', - 'ڀارت', - 'كاثوليك', - 'سودان', - 'همراه', - 'عراق', - 'مليسيا', - '澳門', - '닷컴', - '政府', - 'شبكة', - 'بيتك', - 'عرب', - 'გე', - '机构', - '组织机构', - '健康', - 'ไทย', - 'سورية', - '招聘', - 'рус', - 'рф', - 'تونس', - '大拿', - 'ລາວ', - 'みんな', - 'グーグル', - 'ευ', - 'ελ', - '世界', - '書籍', - 'ഭാരതം', - 'ਭਾਰਤ', - '网址', - '닷넷', - 'コム', - '天主教', - '游戏', - 'vermögensberater', - 'vermögensberatung', - '企业', - '信息', - '嘉里大酒店', - '嘉里', - 'مصر', - 'قطر', - '广东', - 'இலங்கை', - 'இந்தியா', - 'հայ', - '新加坡', - 'فلسطين', - '政务', - 'xxx', - 'xyz', - 'yachts', - 'yahoo', - 'yamaxun', - 'yandex', - 'ye', - 'yodobashi', - 'yoga', - 'yokohama', - 'you', - 'youtube', - 'yt', - 'yun', - 'za', - 'zappos', - 'zara', - 'zero', - 'zip', - 'zm', - 'zone', - 'zuerich', - 'zw', - ]; - - /** - * Array for valid Idns - * - * @see http://www.iana.org/domains/idn-tables/ Official list of supported IDN Chars - * (.AC) Ascension Island http://www.nic.ac/pdf/AC-IDN-Policy.pdf - * (.AR) Argentina http://www.nic.ar/faqidn.html - * (.AS) American Samoa http://www.nic.as/idn/chars.cfm - * (.AT) Austria http://www.nic.at/en/service/technical_information/idn/charset_converter/ - * (.BIZ) International http://www.iana.org/domains/idn-tables/ - * (.BR) Brazil http://registro.br/faq/faq6.html - * (.BV) Bouvett Island http://www.norid.no/domeneregistrering/idn/idn_nyetegn.en.html - * (.CAT) Catalan http://www.iana.org/domains/idn-tables/tables/cat_ca_1.0.html - * (.CH) Switzerland https://nic.switch.ch/reg/ocView.action?res=EF6GW2JBPVTG67DLNIQXU234MN6SC33JNQQGI7L6#anhang1 - * (.CL) Chile http://www.iana.org/domains/idn-tables/tables/cl_latn_1.0.html - * (.COM) International http://www.verisign.com/information-services/naming-services/internationalized-domain-names/index.html - * (.DE) Germany https://www.denic.de/en/know-how/idn-domains/idn-character-list/ - * (.DK) Danmark http://www.dk-hostmaster.dk/index.php?id=151 - * (.EE) Estonia https://www.iana.org/domains/idn-tables/tables/pl_et-pl_1.0.html - * (.ES) Spain https://www.nic.es/media/2008-05/1210147705287.pdf - * (.FI) Finland http://www.ficora.fi/en/index/palvelut/fiverkkotunnukset/aakkostenkaytto.html - * (.GR) Greece https://grweb.ics.forth.gr/CharacterTable1_en.jsp - * (.HR) Croatia https://www.dns.hr/en/portal/files/Odluka-1,2alfanum-dijak.pdf - * (.HU) Hungary http://www.domain.hu/domain/English/szabalyzat/szabalyzat.html - * (.IL) Israel http://www.isoc.org.il/domains/il-domain-rules.html - * (.INFO) International http://www.nic.info/info/idn - * (.IO) British Indian Ocean Territory http://www.nic.io/IO-IDN-Policy.pdf - * (.IR) Iran http://www.nic.ir/Allowable_Characters_dot-iran - * (.IS) Iceland https://www.isnic.is/en/domain/rules#2 - * (.KR) Korea http://www.iana.org/domains/idn-tables/tables/kr_ko-kr_1.0.html - * (.LI) Liechtenstein https://nic.switch.ch/reg/ocView.action?res=EF6GW2JBPVTG67DLNIQXU234MN6SC33JNQQGI7L6#anhang1 - * (.LT) Lithuania http://www.domreg.lt/static/doc/public/idn_symbols-en.pdf - * (.MD) Moldova http://www.register.md/ - * (.MUSEUM) International http://www.iana.org/domains/idn-tables/tables/museum_latn_1.0.html - * (.NET) International http://www.verisign.com/information-services/naming-services/internationalized-domain-names/index.html - * (.NO) Norway http://www.norid.no/domeneregistrering/idn/idn_nyetegn.en.html - * (.NU) Niue http://www.worldnames.net/ - * (.ORG) International http://www.pir.org/index.php?db=content/FAQs&tbl=FAQs_Registrant&id=2 - * (.PE) Peru https://www.nic.pe/nuevas_politicas_faq_2.php - * (.PL) Poland http://www.dns.pl/IDN/allowed_character_sets.pdf - * (.PR) Puerto Rico http://www.nic.pr/idn_rules.asp - * (.PT) Portugal https://online.dns.pt/dns_2008/do?com=DS;8216320233;111;+PAGE(4000058)+K-CAT-CODIGO(C.125)+RCNT(100); - * (.RU) Russia http://www.iana.org/domains/idn-tables/tables/ru_ru-ru_1.0.html - * (.SA) Saudi Arabia http://www.iana.org/domains/idn-tables/tables/sa_ar_1.0.html - * (.SE) Sweden http://www.iis.se/english/IDN_campaignsite.shtml?lang=en - * (.SH) Saint Helena http://www.nic.sh/SH-IDN-Policy.pdf - * (.SJ) Svalbard and Jan Mayen http://www.norid.no/domeneregistrering/idn/idn_nyetegn.en.html - * (.TH) Thailand http://www.iana.org/domains/idn-tables/tables/th_th-th_1.0.html - * (.TM) Turkmenistan http://www.nic.tm/TM-IDN-Policy.pdf - * (.TR) Turkey https://www.nic.tr/index.php - * (.UA) Ukraine http://www.iana.org/domains/idn-tables/tables/ua_cyrl_1.2.html - * (.VE) Venice http://www.iana.org/domains/idn-tables/tables/ve_es_1.0.html - * (.VN) Vietnam http://www.vnnic.vn/english/5-6-300-2-2-04-20071115.htm#1.%20Introduction - * - * @var array<string, string|array<int, string>> - */ - protected $validIdns = [ - 'AC' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿāăąćĉċčďđēėęěĝġģĥħīįĵķĺļľŀłńņňŋőœŕŗřśŝşšţťŧūŭůűųŵŷźżž]{1,63}$/iu'], - 'AR' => [1 => '/^[\x{002d}0-9a-zà-ãç-êìíñ-õü]{1,63}$/iu'], - 'AS' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĸĺļľłńņňŋōŏőœŕŗřśŝşšţťŧũūŭůűųŵŷźż]{1,63}$/iu'], - 'AT' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿœšž]{1,63}$/iu'], - 'BIZ' => 'Hostname/Biz.php', - 'BR' => [1 => '/^[\x{002d}0-9a-zà-ãçéíó-õúü]{1,63}$/iu'], - 'BV' => [1 => '/^[\x{002d}0-9a-zàáä-éêñ-ôöøüčđńŋšŧž]{1,63}$/iu'], - 'CAT' => [1 => '/^[\x{002d}0-9a-z·àç-éíïòóúü]{1,63}$/iu'], - 'CH' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿœ]{1,63}$/iu'], - 'CL' => [1 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu'], - 'CN' => 'Hostname/Cn.php', - 'COM' => 'Hostname/Com.php', - 'DE' => [1 => '/^[\x{002d}0-9a-záàăâåäãąāæćĉčċçďđéèĕêěëėęēğĝġģĥħíìĭîïĩįīıĵķĺľļłńňñņŋóòŏôöőõøōœĸŕřŗśŝšşßťţŧúùŭûůüűũųūŵýŷÿźžżðþ]{1,63}$/iu'], - 'DK' => [1 => '/^[\x{002d}0-9a-zäåæéöøü]{1,63}$/iu'], - 'EE' => [1 => '/^[\x{002d}0-9a-zäõöüšž]{1,63}$/iu'], - 'ES' => [1 => '/^[\x{002d}0-9a-zàáçèéíïñòóúü·]{1,63}$/iu'], - 'EU' => [ - 1 => '/^[\x{002d}0-9a-zà-öø-ÿ]{1,63}$/iu', - 2 => '/^[\x{002d}0-9a-zāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĺļľŀłńņňʼnŋōŏőœŕŗřśŝšťŧũūŭůűųŵŷźżž]{1,63}$/iu', - 3 => '/^[\x{002d}0-9a-zșț]{1,63}$/iu', - 4 => '/^[\x{002d}0-9a-zΐάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ]{1,63}$/iu', - 5 => '/^[\x{002d}0-9a-zабвгдежзийклмнопрстуфхцчшщъыьэюя]{1,63}$/iu', - 6 => '/^[\x{002d}0-9a-zἀ-ἇἐ-ἕἠ-ἧἰ-ἷὀ-ὅὐ-ὗὠ-ὧὰ-ὼώᾀ-ᾇᾐ-ᾗᾠ-ᾧᾰ-ᾴᾶᾷῂῃῄῆῇῐ-ῒΐῖῗῠ-ῧῲῳῴῶῷ]{1,63}$/iu', - ], - 'FI' => [1 => '/^[\x{002d}0-9a-zäåö]{1,63}$/iu'], - 'GR' => [1 => '/^[\x{002d}0-9a-zΆΈΉΊΌΎ-ΡΣ-ώἀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼῂῃῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲῳῴῶ-ῼ]{1,63}$/iu'], - 'HK' => 'Hostname/Cn.php', - 'HR' => [1 => '/^[\x{002d}0-9a-zžćčđš]{1,63}$/iu'], - 'HU' => [1 => '/^[\x{002d}0-9a-záéíóöúüőű]{1,63}$/iu'], - 'IL' => [ - 1 => '/^[\x{002d}0-9\x{05D0}-\x{05EA}]{1,63}$/iu', - 2 => '/^[\x{002d}0-9a-z]{1,63}$/i', - ], - 'INFO' => [ - 1 => '/^[\x{002d}0-9a-zäåæéöøü]{1,63}$/iu', - 2 => '/^[\x{002d}0-9a-záéíóöúüőű]{1,63}$/iu', - 3 => '/^[\x{002d}0-9a-záæéíðóöúýþ]{1,63}$/iu', - 4 => '/^[\x{AC00}-\x{D7A3}]{1,17}$/iu', - 5 => '/^[\x{002d}0-9a-zāčēģīķļņōŗšūž]{1,63}$/iu', - 6 => '/^[\x{002d}0-9a-ząčėęįšūųž]{1,63}$/iu', - 7 => '/^[\x{002d}0-9a-zóąćęłńśźż]{1,63}$/iu', - 8 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu', - ], - 'IO' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿăąāćĉčċďđĕěėęēğĝġģĥħĭĩįīıĵķĺľļłńňņŋŏőōœĸŕřŗśŝšşťţŧŭůűũųūŵŷźžż]{1,63}$/iu'], - 'IS' => [1 => '/^[\x{002d}0-9a-záéýúíóþæöð]{1,63}$/iu'], - 'IT' => [1 => '/^[\x{002d}0-9a-zàâäèéêëìîïòôöùûüæœçÿß-]{1,63}$/iu'], - 'JP' => 'Hostname/Jp.php', - 'KR' => [1 => '/^[\x{AC00}-\x{D7A3}]{1,17}$/iu'], - 'LI' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿœ]{1,63}$/iu'], - 'LT' => [1 => '/^[\x{002d}0-9ąčęėįšųūž]{1,63}$/iu'], - 'MD' => [1 => '/^[\x{002d}0-9ăâîşţ]{1,63}$/iu'], - 'MUSEUM' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿāăąćċčďđēėęěğġģħīįıķĺļľłńņňŋōőœŕŗřśşšţťŧūůűųŵŷźżžǎǐǒǔ\x{01E5}\x{01E7}\x{01E9}\x{01EF}ə\x{0292}ẁẃẅỳ]{1,63}$/iu'], - 'NET' => 'Hostname/Com.php', - 'NO' => [1 => '/^[\x{002d}0-9a-zàáä-éêñ-ôöøüčđńŋšŧž]{1,63}$/iu'], - 'NU' => 'Hostname/Com.php', - 'ORG' => [ - 1 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu', - 2 => '/^[\x{002d}0-9a-zóąćęłńśźż]{1,63}$/iu', - 3 => '/^[\x{002d}0-9a-záäåæéëíðóöøúüýþ]{1,63}$/iu', - 4 => '/^[\x{002d}0-9a-záéíóöúüőű]{1,63}$/iu', - 5 => '/^[\x{002d}0-9a-ząčėęįšūųž]{1,63}$/iu', - 6 => '/^[\x{AC00}-\x{D7A3}]{1,17}$/iu', - 7 => '/^[\x{002d}0-9a-zāčēģīķļņōŗšūž]{1,63}$/iu', - ], - 'PE' => [1 => '/^[\x{002d}0-9a-zñáéíóúü]{1,63}$/iu'], - 'PL' => [ - 1 => '/^[\x{002d}0-9a-zāčēģīķļņōŗšūž]{1,63}$/iu', - 2 => '/^[\x{002d}а-ик-ш\x{0450}ѓѕјљњќџ]{1,63}$/iu', - 3 => '/^[\x{002d}0-9a-zâîăşţ]{1,63}$/iu', - 4 => '/^[\x{002d}0-9а-яё\x{04C2}]{1,63}$/iu', - 5 => '/^[\x{002d}0-9a-zàáâèéêìíîòóôùúûċġħż]{1,63}$/iu', - 6 => '/^[\x{002d}0-9a-zàäåæéêòóôöøü]{1,63}$/iu', - 7 => '/^[\x{002d}0-9a-zóąćęłńśźż]{1,63}$/iu', - 8 => '/^[\x{002d}0-9a-zàáâãçéêíòóôõúü]{1,63}$/iu', - 9 => '/^[\x{002d}0-9a-zâîăşţ]{1,63}$/iu', - 10 => '/^[\x{002d}0-9a-záäéíóôúýčďĺľňŕšťž]{1,63}$/iu', - 11 => '/^[\x{002d}0-9a-zçë]{1,63}$/iu', - 12 => '/^[\x{002d}0-9а-ик-шђјљњћџ]{1,63}$/iu', - 13 => '/^[\x{002d}0-9a-zćčđšž]{1,63}$/iu', - 14 => '/^[\x{002d}0-9a-zâçöûüğış]{1,63}$/iu', - 15 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu', - 16 => '/^[\x{002d}0-9a-zäõöüšž]{1,63}$/iu', - 17 => '/^[\x{002d}0-9a-zĉĝĥĵŝŭ]{1,63}$/iu', - 18 => '/^[\x{002d}0-9a-zâäéëîô]{1,63}$/iu', - 19 => '/^[\x{002d}0-9a-zàáâäåæçèéêëìíîïðñòôöøùúûüýćčłńřśš]{1,63}$/iu', - 20 => '/^[\x{002d}0-9a-zäåæõöøüšž]{1,63}$/iu', - 21 => '/^[\x{002d}0-9a-zàáçèéìíòóùú]{1,63}$/iu', - 22 => '/^[\x{002d}0-9a-zàáéíóöúüőű]{1,63}$/iu', - 23 => '/^[\x{002d}0-9ΐά-ώ]{1,63}$/iu', - 24 => '/^[\x{002d}0-9a-zàáâåæçèéêëðóôöøüþœ]{1,63}$/iu', - 25 => '/^[\x{002d}0-9a-záäéíóöúüýčďěňřšťůž]{1,63}$/iu', - 26 => '/^[\x{002d}0-9a-z·àçèéíïòóúü]{1,63}$/iu', - 27 => '/^[\x{002d}0-9а-ъьюя\x{0450}\x{045D}]{1,63}$/iu', - 28 => '/^[\x{002d}0-9а-яёіў]{1,63}$/iu', - 29 => '/^[\x{002d}0-9a-ząčėęįšūųž]{1,63}$/iu', - 30 => '/^[\x{002d}0-9a-záäåæéëíðóöøúüýþ]{1,63}$/iu', - 31 => '/^[\x{002d}0-9a-zàâæçèéêëîïñôùûüÿœ]{1,63}$/iu', - 32 => '/^[\x{002d}0-9а-щъыьэюяёєіїґ]{1,63}$/iu', - 33 => '/^[\x{002d}0-9א-ת]{1,63}$/iu', - ], - 'PR' => [1 => '/^[\x{002d}0-9a-záéíóúñäëïüöâêîôûàèùæçœãõ]{1,63}$/iu'], - 'PT' => [1 => '/^[\x{002d}0-9a-záàâãçéêíóôõú]{1,63}$/iu'], - 'RS' => [1 => '/^[\x{002d}0-9a-zßáâäçéëíîóôöúüýăąćčďđęěĺľłńňőŕřśşšţťůűźżž]{1,63}$/iu'], - 'RU' => [1 => '/^[\x{002d}0-9а-яё]{1,63}$/iu'], - 'SA' => [1 => '/^[\x{002d}.0-9\x{0621}-\x{063A}\x{0641}-\x{064A}\x{0660}-\x{0669}]{1,63}$/iu'], - 'SE' => [1 => '/^[\x{002d}0-9a-zäåéöü]{1,63}$/iu'], - 'SH' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿăąāćĉčċďđĕěėęēğĝġģĥħĭĩįīıĵķĺľļłńňņŋŏőōœĸŕřŗśŝšşťţŧŭůűũųūŵŷźžż]{1,63}$/iu'], - 'SI' => [ - 1 => '/^[\x{002d}0-9a-zà-öø-ÿ]{1,63}$/iu', - 2 => '/^[\x{002d}0-9a-zāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĺļľŀłńņňʼnŋōŏőœŕŗřśŝšťŧũūŭůűųŵŷźżž]{1,63}$/iu', - 3 => '/^[\x{002d}0-9a-zșț]{1,63}$/iu', - ], - 'SJ' => [1 => '/^[\x{002d}0-9a-zàáä-éêñ-ôöøüčđńŋšŧž]{1,63}$/iu'], - 'TH' => [1 => '/^[\x{002d}0-9a-z\x{0E01}-\x{0E3A}\x{0E40}-\x{0E4D}\x{0E50}-\x{0E59}]{1,63}$/iu'], - 'TM' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿāăąćĉċčďđēėęěĝġģĥħīįĵķĺļľŀłńņňŋőœŕŗřśŝşšţťŧūŭůűųŵŷźżž]{1,63}$/iu'], - 'TW' => 'Hostname/Cn.php', - 'TR' => [1 => '/^[\x{002d}0-9a-zğıüşöç]{1,63}$/iu'], - 'UA' => [1 => '/^[\x{002d}0-9a-zабвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓєѕіїјљњћќѝўџґӂʼ]{1,63}$/iu'], - 'VE' => [1 => '/^[\x{002d}0-9a-záéíóúüñ]{1,63}$/iu'], - 'VN' => [1 => '/^[ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚÝàáâãèéêìíòóôõùúýĂăĐđĨĩŨũƠơƯư\x{1EA0}-\x{1EF9}]{1,63}$/iu'], - 'мон' => [1 => '/^[\x{002d}0-9\x{0430}-\x{044F}]{1,63}$/iu'], - 'срб' => [1 => '/^[\x{002d}0-9а-ик-шђјљњћџ]{1,63}$/iu'], - 'сайт' => [1 => '/^[\x{002d}0-9а-яёіїѝйўґг]{1,63}$/iu'], - 'онлайн' => [1 => '/^[\x{002d}0-9а-яёіїѝйўґг]{1,63}$/iu'], - '中国' => 'Hostname/Cn.php', - '中國' => 'Hostname/Cn.php', - 'ලංකා' => [1 => '/^[\x{0d80}-\x{0dff}]{1,63}$/iu'], - '香港' => 'Hostname/Cn.php', - '台湾' => 'Hostname/Cn.php', - '台灣' => 'Hostname/Cn.php', - 'امارات' => [1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'], - 'الاردن' => [1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'], - 'السعودية' => [1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'], - 'ไทย' => [1 => '/^[\x{002d}0-9a-z\x{0E01}-\x{0E3A}\x{0E40}-\x{0E4D}\x{0E50}-\x{0E59}]{1,63}$/iu'], - 'рф' => [1 => '/^[\x{002d}0-9а-яё]{1,63}$/iu'], - 'تونس' => [1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'], - 'مصر' => [1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'], - 'இலங்கை' => [1 => '/^[\x{0b80}-\x{0bff}]{1,63}$/iu'], - 'فلسطين' => [1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'], - 'شبكة' => [1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'], - ]; - - /** @var array<string, array<int, int>> */ - protected $idnLength = [ - 'BIZ' => [5 => 17, 11 => 15, 12 => 20], - 'CN' => [1 => 20], - 'COM' => [3 => 17, 5 => 20], - 'HK' => [1 => 15], - 'INFO' => [4 => 17], - 'KR' => [1 => 17], - 'NET' => [3 => 17, 5 => 20], - 'ORG' => [6 => 17], - 'TW' => [1 => 20], - 'امارات' => [1 => 30], - 'الاردن' => [1 => 30], - 'السعودية' => [1 => 30], - 'تونس' => [1 => 30], - 'مصر' => [1 => 30], - 'فلسطين' => [1 => 30], - 'شبكة' => [1 => 30], - '中国' => [1 => 20], - '中國' => [1 => 20], - '香港' => [1 => 20], - '台湾' => [1 => 20], - '台灣' => [1 => 20], - ]; - - /** @var null|false|string */ - protected $tld; - - /** - * Options for the hostname validator - * - * @var array - */ - protected $options = [ - 'allow' => self::ALLOW_DNS, // Allow these hostnames - 'useIdnCheck' => true, // Check IDN domains - 'useTldCheck' => true, // Check TLD elements - 'ipValidator' => null, // IP validator to use - ]; - - // phpcs:disable Squiz.Commenting.FunctionComment.ExtraParamComment - - /** - * Sets validator options. - * - * @see http://www.iana.org/cctld/specifications-policies-cctlds-01apr02.htm Technical Specifications for ccTLDs - * - * @param array $options OPTIONAL Array of validator options; see Hostname::$options - * @param int $allow OPTIONAL Set what types of hostname to allow (default ALLOW_DNS) - * @param bool $useIdnCheck OPTIONAL Set whether IDN domains are validated (default true) - * @param bool $useTldCheck Set whether the TLD element of a hostname is validated (default true) - * @param Ip $ipValidator OPTIONAL - */ - public function __construct($options = []) - { - // phpcs:enable - if (! is_array($options)) { - $options = func_get_args(); - $temp['allow'] = array_shift($options); - if (! empty($options)) { - $temp['useIdnCheck'] = array_shift($options); - } - - if (! empty($options)) { - $temp['useTldCheck'] = array_shift($options); - } - - if (! empty($options)) { - $temp['ipValidator'] = array_shift($options); - } - - $options = $temp; - } - - if (! array_key_exists('ipValidator', $options)) { - $options['ipValidator'] = null; - } - - parent::__construct($options); - } - - /** - * Returns the set ip validator - * - * @return Ip - */ - public function getIpValidator() - { - return $this->options['ipValidator']; - } - - /** - * @param Ip $ipValidator OPTIONAL - * @return self - */ - public function setIpValidator(?Ip $ipValidator = null) - { - if ($ipValidator === null) { - $ipValidator = new Ip(); - } - - $this->options['ipValidator'] = $ipValidator; - return $this; - } - - /** - * Returns the allow option - * - * @return int - */ - public function getAllow() - { - return $this->options['allow']; - } - - /** - * Sets the allow option - * - * @param int $allow - * @return $this Provides a fluent interface - */ - public function setAllow($allow) - { - $this->options['allow'] = $allow; - return $this; - } - - /** - * Returns the set idn option - * - * @return bool - */ - public function getIdnCheck() - { - return $this->options['useIdnCheck']; - } - - /** - * Set whether IDN domains are validated - * - * This only applies when DNS hostnames are validated - * - * @param bool $useIdnCheck Set to true to validate IDN domains - * @return $this - */ - public function useIdnCheck($useIdnCheck) - { - $this->options['useIdnCheck'] = (bool) $useIdnCheck; - return $this; - } - - /** - * Returns the set tld option - * - * @return bool - */ - public function getTldCheck() - { - return $this->options['useTldCheck']; - } - - /** - * Set whether the TLD element of a hostname is validated - * - * This only applies when DNS hostnames are validated - * - * @param bool $useTldCheck Set to true to validate TLD elements - * @return $this - */ - public function useTldCheck($useTldCheck) - { - $this->options['useTldCheck'] = (bool) $useTldCheck; - return $this; - } - - /** - * Defined by Interface - * - * Returns true if and only if the $value is a valid hostname with respect to the current allow option - * - * @param string $value - * @return bool - */ - public function isValid($value) - { - if (! is_string($value)) { - $this->error(self::INVALID); - return false; - } - - $this->setValue($value); - // Check input against IP address schema - if ( - ((preg_match('/^[0-9.]*$/', $value) && strpos($value, '.') !== false) - || (preg_match('/^[0-9a-f:.]*$/i', $value) && strpos($value, ':') !== false)) - && $this->getIpValidator()->setTranslator($this->getTranslator())->isValid($value) - ) { - if (! ($this->getAllow() & self::ALLOW_IP)) { - $this->error(self::IP_ADDRESS_NOT_ALLOWED); - return false; - } - - return true; - } - - // Handle Regex compilation failure that may happen on .biz domain with has @ character, eg: tapi4457@hsoqvf.biz - // Technically, hostname with '@' character is invalid, so mark as invalid immediately - // @see https://github.com/laminas/laminas-validator/issues/8 - if (strpos($value, '@') !== false) { - $this->error(self::INVALID_HOSTNAME); - return false; - } - - // Local hostnames are allowed to be partial (ending '.') - if ($this->getAllow() & self::ALLOW_LOCAL) { - if (substr($value, -1) === '.') { - $value = substr($value, 0, -1); - if (substr($value, -1) === '.') { - // Empty hostnames (ending '..') are not allowed - $this->error(self::INVALID_LOCAL_NAME); - return false; - } - } - } - - $domainParts = explode('.', $value); - - // Prevent partial IP V4 addresses (ending '.') - if ( - count($domainParts) === 4 && preg_match('/^[0-9.a-e:.]*$/i', $value) - && $this->getIpValidator()->setTranslator($this->getTranslator())->isValid($value) - ) { - $this->error(self::INVALID_LOCAL_NAME); - } - - $utf8StrWrapper = StringUtils::getWrapper('UTF-8'); - - // Check input against DNS hostname schema - if ( - count($domainParts) > 1 - && $utf8StrWrapper->strlen($value) >= 4 - && $utf8StrWrapper->strlen($value) <= 254 - ) { - $status = false; - - do { - // First check TLD - $matches = []; - if ( - preg_match('/([^.]{2,63})$/u', end($domainParts), $matches) - || (array_key_exists(end($domainParts), $this->validIdns)) - ) { - reset($domainParts); - - // Hostname characters are: *(label dot)(label dot label); max 254 chars - // label: id-prefix [*ldh{61} id-prefix]; max 63 chars - // id-prefix: alpha / digit - // ldh: alpha / digit / dash - - $this->tld = $matches[1]; - // Decode Punycode TLD to IDN - if (strpos($this->tld, 'xn--') === 0) { - $this->tld = $this->decodePunycode(substr($this->tld, 4)); - if ($this->tld === false) { - return false; - } - } else { - $this->tld = strtoupper($this->tld); - } - - // Match TLD against known list - $removedTld = false; - if ($this->getTldCheck()) { - if ( - ! in_array(strtolower($this->tld), $this->validTlds) - && ! in_array($this->tld, $this->validTlds) - ) { - $this->error(self::UNKNOWN_TLD); - $status = false; - break; - } - // We have already validated that the TLD is fine. We don't want it to go through the below - // checks as new UTF-8 TLDs will incorrectly fail if there is no IDN regex for it. - array_pop($domainParts); - $removedTld = true; - } - - /** - * Match against IDN hostnames - * Note: Keep label regex short to avoid issues with long patterns when matching IDN hostnames - * - * @see Hostname\Interface - */ - $regexChars = [0 => '/^[a-z0-9\x2d]{1,63}$/i']; - if ($this->getIdnCheck() && isset($this->validIdns[$this->tld])) { - if (is_string($this->validIdns[$this->tld])) { - $regexChars += include __DIR__ . '/' . $this->validIdns[$this->tld]; - } else { - $regexChars += $this->validIdns[$this->tld]; - } - } - - // Check each hostname part - $check = 0; - $lastDomainPart = end($domainParts); - if (! $removedTld) { - $lastDomainPart = prev($domainParts); - } - foreach ($domainParts as $domainPart) { - // Decode Punycode domain names to IDN - if (strpos($domainPart, 'xn--') === 0) { - $domainPart = $this->decodePunycode(substr($domainPart, 4)); - if ($domainPart === false) { - return false; - } - } - - // Skip following checks if domain part is empty, as it definitely is not a valid hostname then - if ($domainPart === '') { - $this->error(self::INVALID_HOSTNAME); - $status = false; - break 2; - } - - // Check dash (-) does not start, end or appear in 3rd and 4th positions - if ( - $utf8StrWrapper->strpos($domainPart, '-') === 0 - || ($utf8StrWrapper->strlen($domainPart) > 2 - && $utf8StrWrapper->strpos($domainPart, '-', 2) === 2 - && $utf8StrWrapper->strpos($domainPart, '-', 3) === 3 - ) - || $utf8StrWrapper->substr($domainPart, -1) === '-' - ) { - $this->error(self::INVALID_DASH); - $status = false; - break 2; - } - - // Check each domain part - $checked = false; - $isSubDomain = $domainPart !== $lastDomainPart; - $partRegexChars = $isSubDomain ? ['/^[a-z0-9_\x2d]{1,63}$/i'] + $regexChars : $regexChars; - foreach ($partRegexChars as $regexKey => $regexChar) { - $status = preg_match($regexChar, $domainPart); - if ($status > 0) { - $length = 63; - if ( - array_key_exists($this->tld, $this->idnLength) - && array_key_exists($regexKey, $this->idnLength[$this->tld]) - ) { - $length = $this->idnLength[$this->tld]; - } - - if ($utf8StrWrapper->strlen($domainPart) > $length) { - $this->error(self::INVALID_HOSTNAME); - $status = false; - } else { - $checked = true; - break; - } - } - } - - if ($checked) { - ++$check; - } - } - - // If one of the labels doesn't match, the hostname is invalid - if ($check !== count($domainParts)) { - $this->error(self::INVALID_HOSTNAME_SCHEMA); - $status = false; - } - } else { - // Hostname not long enough - $this->error(self::UNDECIPHERABLE_TLD); - $status = false; - } - } while (false); - - // If the input passes as an Internet domain name, and domain names are allowed, then the hostname - // passes validation - if ($status && ($this->getAllow() & self::ALLOW_DNS)) { - return true; - } - } elseif ($this->getAllow() & self::ALLOW_DNS) { - $this->error(self::INVALID_HOSTNAME); - } - - // Check for URI Syntax (RFC3986) - if ($this->getAllow() & self::ALLOW_URI) { - if (preg_match("/^([a-zA-Z0-9-._~!$&\'()*+,;=]|%[[:xdigit:]]{2}){1,254}$/i", $value)) { - return true; - } - - $this->error(self::INVALID_URI); - } - - // Check input against local network name schema; last chance to pass validation - $regexLocal = '/^(([a-zA-Z0-9\x2d]{1,63}\x2e)*[a-zA-Z0-9\x2d]{1,63}[\x2e]{0,1}){1,254}$/'; - $status = preg_match($regexLocal, $value); - - // If the input passes as a local network name, and local network names are allowed, then the - // hostname passes validation - $allowLocal = $this->getAllow() & self::ALLOW_LOCAL; - if ($status && $allowLocal) { - return true; - } - - // If the input does not pass as a local network name, add a message - if (! $status) { - $this->error(self::INVALID_LOCAL_NAME); - } - - // If local network names are not allowed, add a message - if ($status && ! $allowLocal) { - $this->error(self::LOCAL_NAME_NOT_ALLOWED); - } - - return false; - } - - /** - * Decodes a punycode encoded string to it's original utf8 string - * Returns false in case of a decoding failure. - * - * @param string $encoded Punycode encoded string to decode - * @return string|false - */ - protected function decodePunycode($encoded) - { - if (! preg_match('/^[a-z0-9-]+$/i', $encoded)) { - // no punycode encoded string - $this->error(self::CANNOT_DECODE_PUNYCODE); - return false; - } - - $decoded = []; - $separator = strrpos($encoded, '-'); - if ($separator > 0) { - for ($x = 0; $x < $separator; ++$x) { - // prepare decoding matrix - $decoded[] = ord($encoded[$x]); - } - } - - $lengthd = count($decoded); - $lengthe = strlen($encoded); - - // decoding - $init = true; - $base = 72; - $index = 0; - $char = 0x80; - - for ($indexe = $separator ? $separator + 1 : 0; $indexe < $lengthe; ++$lengthd) { - for ($oldIndex = $index, $pos = 1, $key = 36; 1; $key += 36) { - $hex = ord($encoded[$indexe++]); - $digit = $hex - 48 < 10 ? $hex - 22 - : ($hex - 65 < 26 ? $hex - 65 - : ($hex - 97 < 26 ? $hex - 97 - : 36)); - - $index += $digit * $pos; - $tag = $key <= $base ? 1 : ($key >= $base + 26 ? 26 : $key - $base); - if ($digit < $tag) { - break; - } - - $pos = (int) ($pos * (36 - $tag)); - } - - $delta = intval($init ? ($index - $oldIndex) / 700 : ($index - $oldIndex) / 2); - $delta += intval($delta / ($lengthd + 1)); - for ($key = 0; $delta > 910 / 2; $key += 36) { - $delta = intval($delta / 35); - } - - $base = intval($key + 36 * $delta / ($delta + 38)); - $init = false; - $char += (int) ($index / ($lengthd + 1)); - $index %= $lengthd + 1; - if ($lengthd > 0) { - for ($i = $lengthd; $i > $index; $i--) { - $decoded[$i] = $decoded[$i - 1]; - } - } - - $decoded[$index++] = $char; - } - - // convert decoded ucs4 to utf8 string - foreach ($decoded as $key => $value) { - if ($value < 128) { - $decoded[$key] = chr($value); - } elseif ($value < 1 << 11) { - $decoded[$key] = chr(192 + ($value >> 6)); - $decoded[$key] .= chr(128 + ($value & 63)); - } elseif ($value < 1 << 16) { - $decoded[$key] = chr(224 + ($value >> 12)); - $decoded[$key] .= chr(128 + (($value >> 6) & 63)); - $decoded[$key] .= chr(128 + ($value & 63)); - } elseif ($value < 1 << 21) { - $decoded[$key] = chr(240 + ($value >> 18)); - $decoded[$key] .= chr(128 + (($value >> 12) & 63)); - $decoded[$key] .= chr(128 + (($value >> 6) & 63)); - $decoded[$key] .= chr(128 + ($value & 63)); - } else { - $this->error(self::CANNOT_DECODE_PUNYCODE); - return false; - } - } - - return implode($decoded); - } -} diff --git a/lib/laminas/laminas-validator/src/Hostname/Biz.php b/lib/laminas/laminas-validator/src/Hostname/Biz.php deleted file mode 100644 index f852cf1c2..000000000 --- a/lib/laminas/laminas-validator/src/Hostname/Biz.php +++ /dev/null @@ -1,2897 +0,0 @@ -<?php // phpcs:disable PSR12.Files.FileHeader.IncorrectOrder - -namespace Laminas\Validator\Hostname; - -/** - * Resource file for biz idn validation - */ - -return [ - 1 => '/^[\x{002d}0-9a-zäåæéöøü]{1,63}$/iu', - 2 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu', - 3 => '/^[\x{002d}0-9a-záéíóöúüőű]{1,63}$/iu', - 4 => '/^[\x{002d}0-9a-záæéíðóöúýþ]{1,63}$/iu', - 5 => '/^[\x{AC00}-\x{D7A3}]{1,17}$/iu', - 6 => '/^[\x{002d}0-9a-ząčėęįšūųž]{1,63}$/iu', - 7 => '/^[\x{002d}0-9a-zāčēģīķļņōŗšūž]{1,63}$/iu', - 8 => '/^[\x{002d}0-9a-zàáä-éêñ-ôöøüčđńŋšŧž]{1,63}$/iu', - 9 => '/^[\x{002d}0-9a-zóąćęłńśźż]{1,63}$/iu', - 10 => '/^[\x{002d}0-9a-záàâãçéêíóôõú]{1,63}$/iu', - 11 => '/^[\x{002d}0-9a-z\x{3005}-\x{3007}\x{3041}-\x{3093}\x{309D}\x{309E}\x{30A1}-\x{30F6}\x{30FC}' - . '\x{30FD}\x{30FE}\x{4E00}\x{4E01}\x{4E03}\x{4E07}\x{4E08}\x{4E09}\x{4E0A}' - . '\x{4E0B}\x{4E0D}\x{4E0E}\x{4E10}\x{4E11}\x{4E14}\x{4E15}\x{4E16}\x{4E17}' - . '\x{4E18}\x{4E19}\x{4E1E}\x{4E21}\x{4E26}\x{4E2A}\x{4E2D}\x{4E31}\x{4E32}' - . '\x{4E36}\x{4E38}\x{4E39}\x{4E3B}\x{4E3C}\x{4E3F}\x{4E42}\x{4E43}\x{4E45}' - . '\x{4E4B}\x{4E4D}\x{4E4E}\x{4E4F}\x{4E55}\x{4E56}\x{4E57}\x{4E58}\x{4E59}' - . '\x{4E5D}\x{4E5E}\x{4E5F}\x{4E62}\x{4E71}\x{4E73}\x{4E7E}\x{4E80}\x{4E82}' - . '\x{4E85}\x{4E86}\x{4E88}\x{4E89}\x{4E8A}\x{4E8B}\x{4E8C}\x{4E8E}\x{4E91}' - . '\x{4E92}\x{4E94}\x{4E95}\x{4E98}\x{4E99}\x{4E9B}\x{4E9C}\x{4E9E}\x{4E9F}' - . '\x{4EA0}\x{4EA1}\x{4EA2}\x{4EA4}\x{4EA5}\x{4EA6}\x{4EA8}\x{4EAB}\x{4EAC}' - . '\x{4EAD}\x{4EAE}\x{4EB0}\x{4EB3}\x{4EB6}\x{4EBA}\x{4EC0}\x{4EC1}\x{4EC2}' - . '\x{4EC4}\x{4EC6}\x{4EC7}\x{4ECA}\x{4ECB}\x{4ECD}\x{4ECE}\x{4ECF}\x{4ED4}' - . '\x{4ED5}\x{4ED6}\x{4ED7}\x{4ED8}\x{4ED9}\x{4EDD}\x{4EDE}\x{4EDF}\x{4EE3}' - . '\x{4EE4}\x{4EE5}\x{4EED}\x{4EEE}\x{4EF0}\x{4EF2}\x{4EF6}\x{4EF7}\x{4EFB}' - . '\x{4F01}\x{4F09}\x{4F0A}\x{4F0D}\x{4F0E}\x{4F0F}\x{4F10}\x{4F11}\x{4F1A}' - . '\x{4F1C}\x{4F1D}\x{4F2F}\x{4F30}\x{4F34}\x{4F36}\x{4F38}\x{4F3A}\x{4F3C}' - . '\x{4F3D}\x{4F43}\x{4F46}\x{4F47}\x{4F4D}\x{4F4E}\x{4F4F}\x{4F50}\x{4F51}' - . '\x{4F53}\x{4F55}\x{4F57}\x{4F59}\x{4F5A}\x{4F5B}\x{4F5C}\x{4F5D}\x{4F5E}' - . '\x{4F69}\x{4F6F}\x{4F70}\x{4F73}\x{4F75}\x{4F76}\x{4F7B}\x{4F7C}\x{4F7F}' - . '\x{4F83}\x{4F86}\x{4F88}\x{4F8B}\x{4F8D}\x{4F8F}\x{4F91}\x{4F96}\x{4F98}' - . '\x{4F9B}\x{4F9D}\x{4FA0}\x{4FA1}\x{4FAB}\x{4FAD}\x{4FAE}\x{4FAF}\x{4FB5}' - . '\x{4FB6}\x{4FBF}\x{4FC2}\x{4FC3}\x{4FC4}\x{4FCA}\x{4FCE}\x{4FD0}\x{4FD1}' - . '\x{4FD4}\x{4FD7}\x{4FD8}\x{4FDA}\x{4FDB}\x{4FDD}\x{4FDF}\x{4FE1}\x{4FE3}' - . '\x{4FE4}\x{4FE5}\x{4FEE}\x{4FEF}\x{4FF3}\x{4FF5}\x{4FF6}\x{4FF8}\x{4FFA}' - . '\x{4FFE}\x{5005}\x{5006}\x{5009}\x{500B}\x{500D}\x{500F}\x{5011}\x{5012}' - . '\x{5014}\x{5016}\x{5019}\x{501A}\x{501F}\x{5021}\x{5023}\x{5024}\x{5025}' - . '\x{5026}\x{5028}\x{5029}\x{502A}\x{502B}\x{502C}\x{502D}\x{5036}\x{5039}' - . '\x{5043}\x{5047}\x{5048}\x{5049}\x{504F}\x{5050}\x{5055}\x{5056}\x{505A}' - . '\x{505C}\x{5065}\x{506C}\x{5072}\x{5074}\x{5075}\x{5076}\x{5078}\x{507D}' - . '\x{5080}\x{5085}\x{508D}\x{5091}\x{5098}\x{5099}\x{509A}\x{50AC}\x{50AD}' - . '\x{50B2}\x{50B3}\x{50B4}\x{50B5}\x{50B7}\x{50BE}\x{50C2}\x{50C5}\x{50C9}' - . '\x{50CA}\x{50CD}\x{50CF}\x{50D1}\x{50D5}\x{50D6}\x{50DA}\x{50DE}\x{50E3}' - . '\x{50E5}\x{50E7}\x{50ED}\x{50EE}\x{50F5}\x{50F9}\x{50FB}\x{5100}\x{5101}' - . '\x{5102}\x{5104}\x{5109}\x{5112}\x{5114}\x{5115}\x{5116}\x{5118}\x{511A}' - . '\x{511F}\x{5121}\x{512A}\x{5132}\x{5137}\x{513A}\x{513B}\x{513C}\x{513F}' - . '\x{5140}\x{5141}\x{5143}\x{5144}\x{5145}\x{5146}\x{5147}\x{5148}\x{5149}' - . '\x{514B}\x{514C}\x{514D}\x{514E}\x{5150}\x{5152}\x{5154}\x{515A}\x{515C}' - . '\x{5162}\x{5165}\x{5168}\x{5169}\x{516A}\x{516B}\x{516C}\x{516D}\x{516E}' - . '\x{5171}\x{5175}\x{5176}\x{5177}\x{5178}\x{517C}\x{5180}\x{5182}\x{5185}' - . '\x{5186}\x{5189}\x{518A}\x{518C}\x{518D}\x{518F}\x{5190}\x{5191}\x{5192}' - . '\x{5193}\x{5195}\x{5196}\x{5197}\x{5199}\x{51A0}\x{51A2}\x{51A4}\x{51A5}' - . '\x{51A6}\x{51A8}\x{51A9}\x{51AA}\x{51AB}\x{51AC}\x{51B0}\x{51B1}\x{51B2}' - . '\x{51B3}\x{51B4}\x{51B5}\x{51B6}\x{51B7}\x{51BD}\x{51C4}\x{51C5}\x{51C6}' - . '\x{51C9}\x{51CB}\x{51CC}\x{51CD}\x{51D6}\x{51DB}\x{51DC}\x{51DD}\x{51E0}' - . '\x{51E1}\x{51E6}\x{51E7}\x{51E9}\x{51EA}\x{51ED}\x{51F0}\x{51F1}\x{51F5}' - . '\x{51F6}\x{51F8}\x{51F9}\x{51FA}\x{51FD}\x{51FE}\x{5200}\x{5203}\x{5204}' - . '\x{5206}\x{5207}\x{5208}\x{520A}\x{520B}\x{520E}\x{5211}\x{5214}\x{5217}' - . '\x{521D}\x{5224}\x{5225}\x{5227}\x{5229}\x{522A}\x{522E}\x{5230}\x{5233}' - . '\x{5236}\x{5237}\x{5238}\x{5239}\x{523A}\x{523B}\x{5243}\x{5244}\x{5247}' - . '\x{524A}\x{524B}\x{524C}\x{524D}\x{524F}\x{5254}\x{5256}\x{525B}\x{525E}' - . '\x{5263}\x{5264}\x{5265}\x{5269}\x{526A}\x{526F}\x{5270}\x{5271}\x{5272}' - . '\x{5273}\x{5274}\x{5275}\x{527D}\x{527F}\x{5283}\x{5287}\x{5288}\x{5289}' - . '\x{528D}\x{5291}\x{5292}\x{5294}\x{529B}\x{529F}\x{52A0}\x{52A3}\x{52A9}' - . '\x{52AA}\x{52AB}\x{52AC}\x{52AD}\x{52B1}\x{52B4}\x{52B5}\x{52B9}\x{52BC}' - . '\x{52BE}\x{52C1}\x{52C3}\x{52C5}\x{52C7}\x{52C9}\x{52CD}\x{52D2}\x{52D5}' - . '\x{52D7}\x{52D8}\x{52D9}\x{52DD}\x{52DE}\x{52DF}\x{52E0}\x{52E2}\x{52E3}' - . '\x{52E4}\x{52E6}\x{52E7}\x{52F2}\x{52F3}\x{52F5}\x{52F8}\x{52F9}\x{52FA}' - . '\x{52FE}\x{52FF}\x{5301}\x{5302}\x{5305}\x{5306}\x{5308}\x{530D}\x{530F}' - . '\x{5310}\x{5315}\x{5316}\x{5317}\x{5319}\x{531A}\x{531D}\x{5320}\x{5321}' - . '\x{5323}\x{532A}\x{532F}\x{5331}\x{5333}\x{5338}\x{5339}\x{533A}\x{533B}' - . '\x{533F}\x{5340}\x{5341}\x{5343}\x{5345}\x{5346}\x{5347}\x{5348}\x{5349}' - . '\x{534A}\x{534D}\x{5351}\x{5352}\x{5353}\x{5354}\x{5357}\x{5358}\x{535A}' - . '\x{535C}\x{535E}\x{5360}\x{5366}\x{5369}\x{536E}\x{536F}\x{5370}\x{5371}' - . '\x{5373}\x{5374}\x{5375}\x{5377}\x{5378}\x{537B}\x{537F}\x{5382}\x{5384}' - . '\x{5396}\x{5398}\x{539A}\x{539F}\x{53A0}\x{53A5}\x{53A6}\x{53A8}\x{53A9}' - . '\x{53AD}\x{53AE}\x{53B0}\x{53B3}\x{53B6}\x{53BB}\x{53C2}\x{53C3}\x{53C8}' - . '\x{53C9}\x{53CA}\x{53CB}\x{53CC}\x{53CD}\x{53CE}\x{53D4}\x{53D6}\x{53D7}' - . '\x{53D9}\x{53DB}\x{53DF}\x{53E1}\x{53E2}\x{53E3}\x{53E4}\x{53E5}\x{53E8}' - . '\x{53E9}\x{53EA}\x{53EB}\x{53EC}\x{53ED}\x{53EE}\x{53EF}\x{53F0}\x{53F1}' - . '\x{53F2}\x{53F3}\x{53F6}\x{53F7}\x{53F8}\x{53FA}\x{5401}\x{5403}\x{5404}' - . '\x{5408}\x{5409}\x{540A}\x{540B}\x{540C}\x{540D}\x{540E}\x{540F}\x{5410}' - . '\x{5411}\x{541B}\x{541D}\x{541F}\x{5420}\x{5426}\x{5429}\x{542B}\x{542C}' - . '\x{542D}\x{542E}\x{5436}\x{5438}\x{5439}\x{543B}\x{543C}\x{543D}\x{543E}' - . '\x{5440}\x{5442}\x{5446}\x{5448}\x{5449}\x{544A}\x{544E}\x{5451}\x{545F}' - . '\x{5468}\x{546A}\x{5470}\x{5471}\x{5473}\x{5475}\x{5476}\x{5477}\x{547B}' - . '\x{547C}\x{547D}\x{5480}\x{5484}\x{5486}\x{548B}\x{548C}\x{548E}\x{548F}' - . '\x{5490}\x{5492}\x{54A2}\x{54A4}\x{54A5}\x{54A8}\x{54AB}\x{54AC}\x{54AF}' - . '\x{54B2}\x{54B3}\x{54B8}\x{54BC}\x{54BD}\x{54BE}\x{54C0}\x{54C1}\x{54C2}' - . '\x{54C4}\x{54C7}\x{54C8}\x{54C9}\x{54D8}\x{54E1}\x{54E2}\x{54E5}\x{54E6}' - . '\x{54E8}\x{54E9}\x{54ED}\x{54EE}\x{54F2}\x{54FA}\x{54FD}\x{5504}\x{5506}' - . '\x{5507}\x{550F}\x{5510}\x{5514}\x{5516}\x{552E}\x{552F}\x{5531}\x{5533}' - . '\x{5538}\x{5539}\x{553E}\x{5540}\x{5544}\x{5545}\x{5546}\x{554C}\x{554F}' - . '\x{5553}\x{5556}\x{5557}\x{555C}\x{555D}\x{5563}\x{557B}\x{557C}\x{557E}' - . '\x{5580}\x{5583}\x{5584}\x{5587}\x{5589}\x{558A}\x{558B}\x{5598}\x{5599}' - . '\x{559A}\x{559C}\x{559D}\x{559E}\x{559F}\x{55A7}\x{55A8}\x{55A9}\x{55AA}' - . '\x{55AB}\x{55AC}\x{55AE}\x{55B0}\x{55B6}\x{55C4}\x{55C5}\x{55C7}\x{55D4}' - . '\x{55DA}\x{55DC}\x{55DF}\x{55E3}\x{55E4}\x{55F7}\x{55F9}\x{55FD}\x{55FE}' - . '\x{5606}\x{5609}\x{5614}\x{5616}\x{5617}\x{5618}\x{561B}\x{5629}\x{562F}' - . '\x{5631}\x{5632}\x{5634}\x{5636}\x{5638}\x{5642}\x{564C}\x{564E}\x{5650}' - . '\x{565B}\x{5664}\x{5668}\x{566A}\x{566B}\x{566C}\x{5674}\x{5678}\x{567A}' - . '\x{5680}\x{5686}\x{5687}\x{568A}\x{568F}\x{5694}\x{56A0}\x{56A2}\x{56A5}' - . '\x{56AE}\x{56B4}\x{56B6}\x{56BC}\x{56C0}\x{56C1}\x{56C2}\x{56C3}\x{56C8}' - . '\x{56CE}\x{56D1}\x{56D3}\x{56D7}\x{56D8}\x{56DA}\x{56DB}\x{56DE}\x{56E0}' - . '\x{56E3}\x{56EE}\x{56F0}\x{56F2}\x{56F3}\x{56F9}\x{56FA}\x{56FD}\x{56FF}' - . '\x{5700}\x{5703}\x{5704}\x{5708}\x{5709}\x{570B}\x{570D}\x{570F}\x{5712}' - . '\x{5713}\x{5716}\x{5718}\x{571C}\x{571F}\x{5726}\x{5727}\x{5728}\x{572D}' - . '\x{5730}\x{5737}\x{5738}\x{573B}\x{5740}\x{5742}\x{5747}\x{574A}\x{574E}' - . '\x{574F}\x{5750}\x{5751}\x{5761}\x{5764}\x{5766}\x{5769}\x{576A}\x{577F}' - . '\x{5782}\x{5788}\x{5789}\x{578B}\x{5793}\x{57A0}\x{57A2}\x{57A3}\x{57A4}' - . '\x{57AA}\x{57B0}\x{57B3}\x{57C0}\x{57C3}\x{57C6}\x{57CB}\x{57CE}\x{57D2}' - . '\x{57D3}\x{57D4}\x{57D6}\x{57DC}\x{57DF}\x{57E0}\x{57E3}\x{57F4}\x{57F7}' - . '\x{57F9}\x{57FA}\x{57FC}\x{5800}\x{5802}\x{5805}\x{5806}\x{580A}\x{580B}' - . '\x{5815}\x{5819}\x{581D}\x{5821}\x{5824}\x{582A}\x{582F}\x{5830}\x{5831}' - . '\x{5834}\x{5835}\x{583A}\x{583D}\x{5840}\x{5841}\x{584A}\x{584B}\x{5851}' - . '\x{5852}\x{5854}\x{5857}\x{5858}\x{5859}\x{585A}\x{585E}\x{5862}\x{5869}' - . '\x{586B}\x{5870}\x{5872}\x{5875}\x{5879}\x{587E}\x{5883}\x{5885}\x{5893}' - . '\x{5897}\x{589C}\x{589F}\x{58A8}\x{58AB}\x{58AE}\x{58B3}\x{58B8}\x{58B9}' - . '\x{58BA}\x{58BB}\x{58BE}\x{58C1}\x{58C5}\x{58C7}\x{58CA}\x{58CC}\x{58D1}' - . '\x{58D3}\x{58D5}\x{58D7}\x{58D8}\x{58D9}\x{58DC}\x{58DE}\x{58DF}\x{58E4}' - . '\x{58E5}\x{58EB}\x{58EC}\x{58EE}\x{58EF}\x{58F0}\x{58F1}\x{58F2}\x{58F7}' - . '\x{58F9}\x{58FA}\x{58FB}\x{58FC}\x{58FD}\x{5902}\x{5909}\x{590A}\x{590F}' - . '\x{5910}\x{5915}\x{5916}\x{5918}\x{5919}\x{591A}\x{591B}\x{591C}\x{5922}' - . '\x{5925}\x{5927}\x{5929}\x{592A}\x{592B}\x{592C}\x{592D}\x{592E}\x{5931}' - . '\x{5932}\x{5937}\x{5938}\x{593E}\x{5944}\x{5947}\x{5948}\x{5949}\x{594E}' - . '\x{594F}\x{5950}\x{5951}\x{5954}\x{5955}\x{5957}\x{5958}\x{595A}\x{5960}' - . '\x{5962}\x{5965}\x{5967}\x{5968}\x{5969}\x{596A}\x{596C}\x{596E}\x{5973}' - . '\x{5974}\x{5978}\x{597D}\x{5981}\x{5982}\x{5983}\x{5984}\x{598A}\x{598D}' - . '\x{5993}\x{5996}\x{5999}\x{599B}\x{599D}\x{59A3}\x{59A5}\x{59A8}\x{59AC}' - . '\x{59B2}\x{59B9}\x{59BB}\x{59BE}\x{59C6}\x{59C9}\x{59CB}\x{59D0}\x{59D1}' - . '\x{59D3}\x{59D4}\x{59D9}\x{59DA}\x{59DC}\x{59E5}\x{59E6}\x{59E8}\x{59EA}' - . '\x{59EB}\x{59F6}\x{59FB}\x{59FF}\x{5A01}\x{5A03}\x{5A09}\x{5A11}\x{5A18}' - . '\x{5A1A}\x{5A1C}\x{5A1F}\x{5A20}\x{5A25}\x{5A29}\x{5A2F}\x{5A35}\x{5A36}' - . '\x{5A3C}\x{5A40}\x{5A41}\x{5A46}\x{5A49}\x{5A5A}\x{5A62}\x{5A66}\x{5A6A}' - . '\x{5A6C}\x{5A7F}\x{5A92}\x{5A9A}\x{5A9B}\x{5ABC}\x{5ABD}\x{5ABE}\x{5AC1}' - . '\x{5AC2}\x{5AC9}\x{5ACB}\x{5ACC}\x{5AD0}\x{5AD6}\x{5AD7}\x{5AE1}\x{5AE3}' - . '\x{5AE6}\x{5AE9}\x{5AFA}\x{5AFB}\x{5B09}\x{5B0B}\x{5B0C}\x{5B16}\x{5B22}' - . '\x{5B2A}\x{5B2C}\x{5B30}\x{5B32}\x{5B36}\x{5B3E}\x{5B40}\x{5B43}\x{5B45}' - . '\x{5B50}\x{5B51}\x{5B54}\x{5B55}\x{5B57}\x{5B58}\x{5B5A}\x{5B5B}\x{5B5C}' - . '\x{5B5D}\x{5B5F}\x{5B63}\x{5B64}\x{5B65}\x{5B66}\x{5B69}\x{5B6B}\x{5B70}' - . '\x{5B71}\x{5B73}\x{5B75}\x{5B78}\x{5B7A}\x{5B80}\x{5B83}\x{5B85}\x{5B87}' - . '\x{5B88}\x{5B89}\x{5B8B}\x{5B8C}\x{5B8D}\x{5B8F}\x{5B95}\x{5B97}\x{5B98}' - . '\x{5B99}\x{5B9A}\x{5B9B}\x{5B9C}\x{5B9D}\x{5B9F}\x{5BA2}\x{5BA3}\x{5BA4}' - . '\x{5BA5}\x{5BA6}\x{5BAE}\x{5BB0}\x{5BB3}\x{5BB4}\x{5BB5}\x{5BB6}\x{5BB8}' - . '\x{5BB9}\x{5BBF}\x{5BC2}\x{5BC3}\x{5BC4}\x{5BC5}\x{5BC6}\x{5BC7}\x{5BC9}' - . '\x{5BCC}\x{5BD0}\x{5BD2}\x{5BD3}\x{5BD4}\x{5BDB}\x{5BDD}\x{5BDE}\x{5BDF}' - . '\x{5BE1}\x{5BE2}\x{5BE4}\x{5BE5}\x{5BE6}\x{5BE7}\x{5BE8}\x{5BE9}\x{5BEB}' - . '\x{5BEE}\x{5BF0}\x{5BF3}\x{5BF5}\x{5BF6}\x{5BF8}\x{5BFA}\x{5BFE}\x{5BFF}' - . '\x{5C01}\x{5C02}\x{5C04}\x{5C05}\x{5C06}\x{5C07}\x{5C08}\x{5C09}\x{5C0A}' - . '\x{5C0B}\x{5C0D}\x{5C0E}\x{5C0F}\x{5C11}\x{5C13}\x{5C16}\x{5C1A}\x{5C20}' - . '\x{5C22}\x{5C24}\x{5C28}\x{5C2D}\x{5C31}\x{5C38}\x{5C39}\x{5C3A}\x{5C3B}' - . '\x{5C3C}\x{5C3D}\x{5C3E}\x{5C3F}\x{5C40}\x{5C41}\x{5C45}\x{5C46}\x{5C48}' - . '\x{5C4A}\x{5C4B}\x{5C4D}\x{5C4E}\x{5C4F}\x{5C50}\x{5C51}\x{5C53}\x{5C55}' - . '\x{5C5E}\x{5C60}\x{5C61}\x{5C64}\x{5C65}\x{5C6C}\x{5C6E}\x{5C6F}\x{5C71}' - . '\x{5C76}\x{5C79}\x{5C8C}\x{5C90}\x{5C91}\x{5C94}\x{5CA1}\x{5CA8}\x{5CA9}' - . '\x{5CAB}\x{5CAC}\x{5CB1}\x{5CB3}\x{5CB6}\x{5CB7}\x{5CB8}\x{5CBB}\x{5CBC}' - . '\x{5CBE}\x{5CC5}\x{5CC7}\x{5CD9}\x{5CE0}\x{5CE1}\x{5CE8}\x{5CE9}\x{5CEA}' - . '\x{5CED}\x{5CEF}\x{5CF0}\x{5CF6}\x{5CFA}\x{5CFB}\x{5CFD}\x{5D07}\x{5D0B}' - . '\x{5D0E}\x{5D11}\x{5D14}\x{5D15}\x{5D16}\x{5D17}\x{5D18}\x{5D19}\x{5D1A}' - . '\x{5D1B}\x{5D1F}\x{5D22}\x{5D29}\x{5D4B}\x{5D4C}\x{5D4E}\x{5D50}\x{5D52}' - . '\x{5D5C}\x{5D69}\x{5D6C}\x{5D6F}\x{5D73}\x{5D76}\x{5D82}\x{5D84}\x{5D87}' - . '\x{5D8B}\x{5D8C}\x{5D90}\x{5D9D}\x{5DA2}\x{5DAC}\x{5DAE}\x{5DB7}\x{5DBA}' - . '\x{5DBC}\x{5DBD}\x{5DC9}\x{5DCC}\x{5DCD}\x{5DD2}\x{5DD3}\x{5DD6}\x{5DDB}' - . '\x{5DDD}\x{5DDE}\x{5DE1}\x{5DE3}\x{5DE5}\x{5DE6}\x{5DE7}\x{5DE8}\x{5DEB}' - . '\x{5DEE}\x{5DF1}\x{5DF2}\x{5DF3}\x{5DF4}\x{5DF5}\x{5DF7}\x{5DFB}\x{5DFD}' - . '\x{5DFE}\x{5E02}\x{5E03}\x{5E06}\x{5E0B}\x{5E0C}\x{5E11}\x{5E16}\x{5E19}' - . '\x{5E1A}\x{5E1B}\x{5E1D}\x{5E25}\x{5E2B}\x{5E2D}\x{5E2F}\x{5E30}\x{5E33}' - . '\x{5E36}\x{5E37}\x{5E38}\x{5E3D}\x{5E40}\x{5E43}\x{5E44}\x{5E45}\x{5E47}' - . '\x{5E4C}\x{5E4E}\x{5E54}\x{5E55}\x{5E57}\x{5E5F}\x{5E61}\x{5E62}\x{5E63}' - . '\x{5E64}\x{5E72}\x{5E73}\x{5E74}\x{5E75}\x{5E76}\x{5E78}\x{5E79}\x{5E7A}' - . '\x{5E7B}\x{5E7C}\x{5E7D}\x{5E7E}\x{5E7F}\x{5E81}\x{5E83}\x{5E84}\x{5E87}' - . '\x{5E8A}\x{5E8F}\x{5E95}\x{5E96}\x{5E97}\x{5E9A}\x{5E9C}\x{5EA0}\x{5EA6}' - . '\x{5EA7}\x{5EAB}\x{5EAD}\x{5EB5}\x{5EB6}\x{5EB7}\x{5EB8}\x{5EC1}\x{5EC2}' - . '\x{5EC3}\x{5EC8}\x{5EC9}\x{5ECA}\x{5ECF}\x{5ED0}\x{5ED3}\x{5ED6}\x{5EDA}' - . '\x{5EDB}\x{5EDD}\x{5EDF}\x{5EE0}\x{5EE1}\x{5EE2}\x{5EE3}\x{5EE8}\x{5EE9}' - . '\x{5EEC}\x{5EF0}\x{5EF1}\x{5EF3}\x{5EF4}\x{5EF6}\x{5EF7}\x{5EF8}\x{5EFA}' - . '\x{5EFB}\x{5EFC}\x{5EFE}\x{5EFF}\x{5F01}\x{5F03}\x{5F04}\x{5F09}\x{5F0A}' - . '\x{5F0B}\x{5F0C}\x{5F0D}\x{5F0F}\x{5F10}\x{5F11}\x{5F13}\x{5F14}\x{5F15}' - . '\x{5F16}\x{5F17}\x{5F18}\x{5F1B}\x{5F1F}\x{5F25}\x{5F26}\x{5F27}\x{5F29}' - . '\x{5F2D}\x{5F2F}\x{5F31}\x{5F35}\x{5F37}\x{5F38}\x{5F3C}\x{5F3E}\x{5F41}' - . '\x{5F48}\x{5F4A}\x{5F4C}\x{5F4E}\x{5F51}\x{5F53}\x{5F56}\x{5F57}\x{5F59}' - . '\x{5F5C}\x{5F5D}\x{5F61}\x{5F62}\x{5F66}\x{5F69}\x{5F6A}\x{5F6B}\x{5F6C}' - . '\x{5F6D}\x{5F70}\x{5F71}\x{5F73}\x{5F77}\x{5F79}\x{5F7C}\x{5F7F}\x{5F80}' - . '\x{5F81}\x{5F82}\x{5F83}\x{5F84}\x{5F85}\x{5F87}\x{5F88}\x{5F8A}\x{5F8B}' - . '\x{5F8C}\x{5F90}\x{5F91}\x{5F92}\x{5F93}\x{5F97}\x{5F98}\x{5F99}\x{5F9E}' - . '\x{5FA0}\x{5FA1}\x{5FA8}\x{5FA9}\x{5FAA}\x{5FAD}\x{5FAE}\x{5FB3}\x{5FB4}' - . '\x{5FB9}\x{5FBC}\x{5FBD}\x{5FC3}\x{5FC5}\x{5FCC}\x{5FCD}\x{5FD6}\x{5FD7}' - . '\x{5FD8}\x{5FD9}\x{5FDC}\x{5FDD}\x{5FE0}\x{5FE4}\x{5FEB}\x{5FF0}\x{5FF1}' - . '\x{5FF5}\x{5FF8}\x{5FFB}\x{5FFD}\x{5FFF}\x{600E}\x{600F}\x{6010}\x{6012}' - . '\x{6015}\x{6016}\x{6019}\x{601B}\x{601C}\x{601D}\x{6020}\x{6021}\x{6025}' - . '\x{6026}\x{6027}\x{6028}\x{6029}\x{602A}\x{602B}\x{602F}\x{6031}\x{603A}' - . '\x{6041}\x{6042}\x{6043}\x{6046}\x{604A}\x{604B}\x{604D}\x{6050}\x{6052}' - . '\x{6055}\x{6059}\x{605A}\x{605F}\x{6060}\x{6062}\x{6063}\x{6064}\x{6065}' - . '\x{6068}\x{6069}\x{606A}\x{606B}\x{606C}\x{606D}\x{606F}\x{6070}\x{6075}' - . '\x{6077}\x{6081}\x{6083}\x{6084}\x{6089}\x{608B}\x{608C}\x{608D}\x{6092}' - . '\x{6094}\x{6096}\x{6097}\x{609A}\x{609B}\x{609F}\x{60A0}\x{60A3}\x{60A6}' - . '\x{60A7}\x{60A9}\x{60AA}\x{60B2}\x{60B3}\x{60B4}\x{60B5}\x{60B6}\x{60B8}' - . '\x{60BC}\x{60BD}\x{60C5}\x{60C6}\x{60C7}\x{60D1}\x{60D3}\x{60D8}\x{60DA}' - . '\x{60DC}\x{60DF}\x{60E0}\x{60E1}\x{60E3}\x{60E7}\x{60E8}\x{60F0}\x{60F1}' - . '\x{60F3}\x{60F4}\x{60F6}\x{60F7}\x{60F9}\x{60FA}\x{60FB}\x{6100}\x{6101}' - . '\x{6103}\x{6106}\x{6108}\x{6109}\x{610D}\x{610E}\x{610F}\x{6115}\x{611A}' - . '\x{611B}\x{611F}\x{6121}\x{6127}\x{6128}\x{612C}\x{6134}\x{613C}\x{613D}' - . '\x{613E}\x{613F}\x{6142}\x{6144}\x{6147}\x{6148}\x{614A}\x{614B}\x{614C}' - . '\x{614D}\x{614E}\x{6153}\x{6155}\x{6158}\x{6159}\x{615A}\x{615D}\x{615F}' - . '\x{6162}\x{6163}\x{6165}\x{6167}\x{6168}\x{616B}\x{616E}\x{616F}\x{6170}' - . '\x{6171}\x{6173}\x{6174}\x{6175}\x{6176}\x{6177}\x{617E}\x{6182}\x{6187}' - . '\x{618A}\x{618E}\x{6190}\x{6191}\x{6194}\x{6196}\x{6199}\x{619A}\x{61A4}' - . '\x{61A7}\x{61A9}\x{61AB}\x{61AC}\x{61AE}\x{61B2}\x{61B6}\x{61BA}\x{61BE}' - . '\x{61C3}\x{61C6}\x{61C7}\x{61C8}\x{61C9}\x{61CA}\x{61CB}\x{61CC}\x{61CD}' - . '\x{61D0}\x{61E3}\x{61E6}\x{61F2}\x{61F4}\x{61F6}\x{61F7}\x{61F8}\x{61FA}' - . '\x{61FC}\x{61FD}\x{61FE}\x{61FF}\x{6200}\x{6208}\x{6209}\x{620A}\x{620C}' - . '\x{620D}\x{620E}\x{6210}\x{6211}\x{6212}\x{6214}\x{6216}\x{621A}\x{621B}' - . '\x{621D}\x{621E}\x{621F}\x{6221}\x{6226}\x{622A}\x{622E}\x{622F}\x{6230}' - . '\x{6232}\x{6233}\x{6234}\x{6238}\x{623B}\x{623F}\x{6240}\x{6241}\x{6247}' - . '\x{6248}\x{6249}\x{624B}\x{624D}\x{624E}\x{6253}\x{6255}\x{6258}\x{625B}' - . '\x{625E}\x{6260}\x{6263}\x{6268}\x{626E}\x{6271}\x{6276}\x{6279}\x{627C}' - . '\x{627E}\x{627F}\x{6280}\x{6282}\x{6283}\x{6284}\x{6289}\x{628A}\x{6291}' - . '\x{6292}\x{6293}\x{6294}\x{6295}\x{6296}\x{6297}\x{6298}\x{629B}\x{629C}' - . '\x{629E}\x{62AB}\x{62AC}\x{62B1}\x{62B5}\x{62B9}\x{62BB}\x{62BC}\x{62BD}' - . '\x{62C2}\x{62C5}\x{62C6}\x{62C7}\x{62C8}\x{62C9}\x{62CA}\x{62CC}\x{62CD}' - . '\x{62CF}\x{62D0}\x{62D1}\x{62D2}\x{62D3}\x{62D4}\x{62D7}\x{62D8}\x{62D9}' - . '\x{62DB}\x{62DC}\x{62DD}\x{62E0}\x{62E1}\x{62EC}\x{62ED}\x{62EE}\x{62EF}' - . '\x{62F1}\x{62F3}\x{62F5}\x{62F6}\x{62F7}\x{62FE}\x{62FF}\x{6301}\x{6302}' - . '\x{6307}\x{6308}\x{6309}\x{630C}\x{6311}\x{6319}\x{631F}\x{6327}\x{6328}' - . '\x{632B}\x{632F}\x{633A}\x{633D}\x{633E}\x{633F}\x{6349}\x{634C}\x{634D}' - . '\x{634F}\x{6350}\x{6355}\x{6357}\x{635C}\x{6367}\x{6368}\x{6369}\x{636B}' - . '\x{636E}\x{6372}\x{6376}\x{6377}\x{637A}\x{637B}\x{6380}\x{6383}\x{6388}' - . '\x{6389}\x{638C}\x{638E}\x{638F}\x{6392}\x{6396}\x{6398}\x{639B}\x{639F}' - . '\x{63A0}\x{63A1}\x{63A2}\x{63A3}\x{63A5}\x{63A7}\x{63A8}\x{63A9}\x{63AA}' - . '\x{63AB}\x{63AC}\x{63B2}\x{63B4}\x{63B5}\x{63BB}\x{63BE}\x{63C0}\x{63C3}' - . '\x{63C4}\x{63C6}\x{63C9}\x{63CF}\x{63D0}\x{63D2}\x{63D6}\x{63DA}\x{63DB}' - . '\x{63E1}\x{63E3}\x{63E9}\x{63EE}\x{63F4}\x{63F6}\x{63FA}\x{6406}\x{640D}' - . '\x{640F}\x{6413}\x{6416}\x{6417}\x{641C}\x{6426}\x{6428}\x{642C}\x{642D}' - . '\x{6434}\x{6436}\x{643A}\x{643E}\x{6442}\x{644E}\x{6458}\x{6467}\x{6469}' - . '\x{646F}\x{6476}\x{6478}\x{647A}\x{6483}\x{6488}\x{6492}\x{6493}\x{6495}' - . '\x{649A}\x{649E}\x{64A4}\x{64A5}\x{64A9}\x{64AB}\x{64AD}\x{64AE}\x{64B0}' - . '\x{64B2}\x{64B9}\x{64BB}\x{64BC}\x{64C1}\x{64C2}\x{64C5}\x{64C7}\x{64CD}' - . '\x{64D2}\x{64D4}\x{64D8}\x{64DA}\x{64E0}\x{64E1}\x{64E2}\x{64E3}\x{64E6}' - . '\x{64E7}\x{64EC}\x{64EF}\x{64F1}\x{64F2}\x{64F4}\x{64F6}\x{64FA}\x{64FD}' - . '\x{64FE}\x{6500}\x{6505}\x{6518}\x{651C}\x{651D}\x{6523}\x{6524}\x{652A}' - . '\x{652B}\x{652C}\x{652F}\x{6534}\x{6535}\x{6536}\x{6537}\x{6538}\x{6539}' - . '\x{653B}\x{653E}\x{653F}\x{6545}\x{6548}\x{654D}\x{654F}\x{6551}\x{6555}' - . '\x{6556}\x{6557}\x{6558}\x{6559}\x{655D}\x{655E}\x{6562}\x{6563}\x{6566}' - . '\x{656C}\x{6570}\x{6572}\x{6574}\x{6575}\x{6577}\x{6578}\x{6582}\x{6583}' - . '\x{6587}\x{6588}\x{6589}\x{658C}\x{658E}\x{6590}\x{6591}\x{6597}\x{6599}' - . '\x{659B}\x{659C}\x{659F}\x{65A1}\x{65A4}\x{65A5}\x{65A7}\x{65AB}\x{65AC}' - . '\x{65AD}\x{65AF}\x{65B0}\x{65B7}\x{65B9}\x{65BC}\x{65BD}\x{65C1}\x{65C3}' - . '\x{65C4}\x{65C5}\x{65C6}\x{65CB}\x{65CC}\x{65CF}\x{65D2}\x{65D7}\x{65D9}' - . '\x{65DB}\x{65E0}\x{65E1}\x{65E2}\x{65E5}\x{65E6}\x{65E7}\x{65E8}\x{65E9}' - . '\x{65EC}\x{65ED}\x{65F1}\x{65FA}\x{65FB}\x{6602}\x{6603}\x{6606}\x{6607}' - . '\x{660A}\x{660C}\x{660E}\x{660F}\x{6613}\x{6614}\x{661C}\x{661F}\x{6620}' - . '\x{6625}\x{6627}\x{6628}\x{662D}\x{662F}\x{6634}\x{6635}\x{6636}\x{663C}' - . '\x{663F}\x{6641}\x{6642}\x{6643}\x{6644}\x{6649}\x{664B}\x{664F}\x{6652}' - . '\x{665D}\x{665E}\x{665F}\x{6662}\x{6664}\x{6666}\x{6667}\x{6668}\x{6669}' - . '\x{666E}\x{666F}\x{6670}\x{6674}\x{6676}\x{667A}\x{6681}\x{6683}\x{6684}' - . '\x{6687}\x{6688}\x{6689}\x{668E}\x{6691}\x{6696}\x{6697}\x{6698}\x{669D}' - . '\x{66A2}\x{66A6}\x{66AB}\x{66AE}\x{66B4}\x{66B8}\x{66B9}\x{66BC}\x{66BE}' - . '\x{66C1}\x{66C4}\x{66C7}\x{66C9}\x{66D6}\x{66D9}\x{66DA}\x{66DC}\x{66DD}' - . '\x{66E0}\x{66E6}\x{66E9}\x{66F0}\x{66F2}\x{66F3}\x{66F4}\x{66F5}\x{66F7}' - . '\x{66F8}\x{66F9}\x{66FC}\x{66FD}\x{66FE}\x{66FF}\x{6700}\x{6703}\x{6708}' - . '\x{6709}\x{670B}\x{670D}\x{670F}\x{6714}\x{6715}\x{6716}\x{6717}\x{671B}' - . '\x{671D}\x{671E}\x{671F}\x{6726}\x{6727}\x{6728}\x{672A}\x{672B}\x{672C}' - . '\x{672D}\x{672E}\x{6731}\x{6734}\x{6736}\x{6737}\x{6738}\x{673A}\x{673D}' - . '\x{673F}\x{6741}\x{6746}\x{6749}\x{674E}\x{674F}\x{6750}\x{6751}\x{6753}' - . '\x{6756}\x{6759}\x{675C}\x{675E}\x{675F}\x{6760}\x{6761}\x{6762}\x{6763}' - . '\x{6764}\x{6765}\x{676A}\x{676D}\x{676F}\x{6770}\x{6771}\x{6772}\x{6773}' - . '\x{6775}\x{6777}\x{677C}\x{677E}\x{677F}\x{6785}\x{6787}\x{6789}\x{678B}' - . '\x{678C}\x{6790}\x{6795}\x{6797}\x{679A}\x{679C}\x{679D}\x{67A0}\x{67A1}' - . '\x{67A2}\x{67A6}\x{67A9}\x{67AF}\x{67B3}\x{67B4}\x{67B6}\x{67B7}\x{67B8}' - . '\x{67B9}\x{67C1}\x{67C4}\x{67C6}\x{67CA}\x{67CE}\x{67CF}\x{67D0}\x{67D1}' - . '\x{67D3}\x{67D4}\x{67D8}\x{67DA}\x{67DD}\x{67DE}\x{67E2}\x{67E4}\x{67E7}' - . '\x{67E9}\x{67EC}\x{67EE}\x{67EF}\x{67F1}\x{67F3}\x{67F4}\x{67F5}\x{67FB}' - . '\x{67FE}\x{67FF}\x{6802}\x{6803}\x{6804}\x{6813}\x{6816}\x{6817}\x{681E}' - . '\x{6821}\x{6822}\x{6829}\x{682A}\x{682B}\x{6832}\x{6834}\x{6838}\x{6839}' - . '\x{683C}\x{683D}\x{6840}\x{6841}\x{6842}\x{6843}\x{6846}\x{6848}\x{684D}' - . '\x{684E}\x{6850}\x{6851}\x{6853}\x{6854}\x{6859}\x{685C}\x{685D}\x{685F}' - . '\x{6863}\x{6867}\x{6874}\x{6876}\x{6877}\x{687E}\x{687F}\x{6881}\x{6883}' - . '\x{6885}\x{688D}\x{688F}\x{6893}\x{6894}\x{6897}\x{689B}\x{689D}\x{689F}' - . '\x{68A0}\x{68A2}\x{68A6}\x{68A7}\x{68A8}\x{68AD}\x{68AF}\x{68B0}\x{68B1}' - . '\x{68B3}\x{68B5}\x{68B6}\x{68B9}\x{68BA}\x{68BC}\x{68C4}\x{68C6}\x{68C9}' - . '\x{68CA}\x{68CB}\x{68CD}\x{68D2}\x{68D4}\x{68D5}\x{68D7}\x{68D8}\x{68DA}' - . '\x{68DF}\x{68E0}\x{68E1}\x{68E3}\x{68E7}\x{68EE}\x{68EF}\x{68F2}\x{68F9}' - . '\x{68FA}\x{6900}\x{6901}\x{6904}\x{6905}\x{6908}\x{690B}\x{690C}\x{690D}' - . '\x{690E}\x{690F}\x{6912}\x{6919}\x{691A}\x{691B}\x{691C}\x{6921}\x{6922}' - . '\x{6923}\x{6925}\x{6926}\x{6928}\x{692A}\x{6930}\x{6934}\x{6936}\x{6939}' - . '\x{693D}\x{693F}\x{694A}\x{6953}\x{6954}\x{6955}\x{6959}\x{695A}\x{695C}' - . '\x{695D}\x{695E}\x{6960}\x{6961}\x{6962}\x{696A}\x{696B}\x{696D}\x{696E}' - . '\x{696F}\x{6973}\x{6974}\x{6975}\x{6977}\x{6978}\x{6979}\x{697C}\x{697D}' - . '\x{697E}\x{6981}\x{6982}\x{698A}\x{698E}\x{6991}\x{6994}\x{6995}\x{699B}' - . '\x{699C}\x{69A0}\x{69A7}\x{69AE}\x{69B1}\x{69B2}\x{69B4}\x{69BB}\x{69BE}' - . '\x{69BF}\x{69C1}\x{69C3}\x{69C7}\x{69CA}\x{69CB}\x{69CC}\x{69CD}\x{69CE}' - . '\x{69D0}\x{69D3}\x{69D8}\x{69D9}\x{69DD}\x{69DE}\x{69E7}\x{69E8}\x{69EB}' - . '\x{69ED}\x{69F2}\x{69F9}\x{69FB}\x{69FD}\x{69FF}\x{6A02}\x{6A05}\x{6A0A}' - . '\x{6A0B}\x{6A0C}\x{6A12}\x{6A13}\x{6A14}\x{6A17}\x{6A19}\x{6A1B}\x{6A1E}' - . '\x{6A1F}\x{6A21}\x{6A22}\x{6A23}\x{6A29}\x{6A2A}\x{6A2B}\x{6A2E}\x{6A35}' - . '\x{6A36}\x{6A38}\x{6A39}\x{6A3A}\x{6A3D}\x{6A44}\x{6A47}\x{6A48}\x{6A4B}' - . '\x{6A58}\x{6A59}\x{6A5F}\x{6A61}\x{6A62}\x{6A66}\x{6A72}\x{6A78}\x{6A7F}' - . '\x{6A80}\x{6A84}\x{6A8D}\x{6A8E}\x{6A90}\x{6A97}\x{6A9C}\x{6AA0}\x{6AA2}' - . '\x{6AA3}\x{6AAA}\x{6AAC}\x{6AAE}\x{6AB3}\x{6AB8}\x{6ABB}\x{6AC1}\x{6AC2}' - . '\x{6AC3}\x{6AD1}\x{6AD3}\x{6ADA}\x{6ADB}\x{6ADE}\x{6ADF}\x{6AE8}\x{6AEA}' - . '\x{6AFA}\x{6AFB}\x{6B04}\x{6B05}\x{6B0A}\x{6B12}\x{6B16}\x{6B1D}\x{6B1F}' - . '\x{6B20}\x{6B21}\x{6B23}\x{6B27}\x{6B32}\x{6B37}\x{6B38}\x{6B39}\x{6B3A}' - . '\x{6B3D}\x{6B3E}\x{6B43}\x{6B47}\x{6B49}\x{6B4C}\x{6B4E}\x{6B50}\x{6B53}' - . '\x{6B54}\x{6B59}\x{6B5B}\x{6B5F}\x{6B61}\x{6B62}\x{6B63}\x{6B64}\x{6B66}' - . '\x{6B69}\x{6B6A}\x{6B6F}\x{6B73}\x{6B74}\x{6B78}\x{6B79}\x{6B7B}\x{6B7F}' - . '\x{6B80}\x{6B83}\x{6B84}\x{6B86}\x{6B89}\x{6B8A}\x{6B8B}\x{6B8D}\x{6B95}' - . '\x{6B96}\x{6B98}\x{6B9E}\x{6BA4}\x{6BAA}\x{6BAB}\x{6BAF}\x{6BB1}\x{6BB2}' - . '\x{6BB3}\x{6BB4}\x{6BB5}\x{6BB7}\x{6BBA}\x{6BBB}\x{6BBC}\x{6BBF}\x{6BC0}' - . '\x{6BC5}\x{6BC6}\x{6BCB}\x{6BCD}\x{6BCE}\x{6BD2}\x{6BD3}\x{6BD4}\x{6BD8}' - . '\x{6BDB}\x{6BDF}\x{6BEB}\x{6BEC}\x{6BEF}\x{6BF3}\x{6C08}\x{6C0F}\x{6C11}' - . '\x{6C13}\x{6C14}\x{6C17}\x{6C1B}\x{6C23}\x{6C24}\x{6C34}\x{6C37}\x{6C38}' - . '\x{6C3E}\x{6C40}\x{6C41}\x{6C42}\x{6C4E}\x{6C50}\x{6C55}\x{6C57}\x{6C5A}' - . '\x{6C5D}\x{6C5E}\x{6C5F}\x{6C60}\x{6C62}\x{6C68}\x{6C6A}\x{6C70}\x{6C72}' - . '\x{6C73}\x{6C7A}\x{6C7D}\x{6C7E}\x{6C81}\x{6C82}\x{6C83}\x{6C88}\x{6C8C}' - . '\x{6C8D}\x{6C90}\x{6C92}\x{6C93}\x{6C96}\x{6C99}\x{6C9A}\x{6C9B}\x{6CA1}' - . '\x{6CA2}\x{6CAB}\x{6CAE}\x{6CB1}\x{6CB3}\x{6CB8}\x{6CB9}\x{6CBA}\x{6CBB}' - . '\x{6CBC}\x{6CBD}\x{6CBE}\x{6CBF}\x{6CC1}\x{6CC4}\x{6CC5}\x{6CC9}\x{6CCA}' - . '\x{6CCC}\x{6CD3}\x{6CD5}\x{6CD7}\x{6CD9}\x{6CDB}\x{6CDD}\x{6CE1}\x{6CE2}' - . '\x{6CE3}\x{6CE5}\x{6CE8}\x{6CEA}\x{6CEF}\x{6CF0}\x{6CF1}\x{6CF3}\x{6D0B}' - . '\x{6D0C}\x{6D12}\x{6D17}\x{6D19}\x{6D1B}\x{6D1E}\x{6D1F}\x{6D25}\x{6D29}' - . '\x{6D2A}\x{6D2B}\x{6D32}\x{6D33}\x{6D35}\x{6D36}\x{6D38}\x{6D3B}\x{6D3D}' - . '\x{6D3E}\x{6D41}\x{6D44}\x{6D45}\x{6D59}\x{6D5A}\x{6D5C}\x{6D63}\x{6D64}' - . '\x{6D66}\x{6D69}\x{6D6A}\x{6D6C}\x{6D6E}\x{6D74}\x{6D77}\x{6D78}\x{6D79}' - . '\x{6D85}\x{6D88}\x{6D8C}\x{6D8E}\x{6D93}\x{6D95}\x{6D99}\x{6D9B}\x{6D9C}' - . '\x{6DAF}\x{6DB2}\x{6DB5}\x{6DB8}\x{6DBC}\x{6DC0}\x{6DC5}\x{6DC6}\x{6DC7}' - . '\x{6DCB}\x{6DCC}\x{6DD1}\x{6DD2}\x{6DD5}\x{6DD8}\x{6DD9}\x{6DDE}\x{6DE1}' - . '\x{6DE4}\x{6DE6}\x{6DE8}\x{6DEA}\x{6DEB}\x{6DEC}\x{6DEE}\x{6DF1}\x{6DF3}' - . '\x{6DF5}\x{6DF7}\x{6DF9}\x{6DFA}\x{6DFB}\x{6E05}\x{6E07}\x{6E08}\x{6E09}' - . '\x{6E0A}\x{6E0B}\x{6E13}\x{6E15}\x{6E19}\x{6E1A}\x{6E1B}\x{6E1D}\x{6E1F}' - . '\x{6E20}\x{6E21}\x{6E23}\x{6E24}\x{6E25}\x{6E26}\x{6E29}\x{6E2B}\x{6E2C}' - . '\x{6E2D}\x{6E2E}\x{6E2F}\x{6E38}\x{6E3A}\x{6E3E}\x{6E43}\x{6E4A}\x{6E4D}' - . '\x{6E4E}\x{6E56}\x{6E58}\x{6E5B}\x{6E5F}\x{6E67}\x{6E6B}\x{6E6E}\x{6E6F}' - . '\x{6E72}\x{6E76}\x{6E7E}\x{6E7F}\x{6E80}\x{6E82}\x{6E8C}\x{6E8F}\x{6E90}' - . '\x{6E96}\x{6E98}\x{6E9C}\x{6E9D}\x{6E9F}\x{6EA2}\x{6EA5}\x{6EAA}\x{6EAF}' - . '\x{6EB2}\x{6EB6}\x{6EB7}\x{6EBA}\x{6EBD}\x{6EC2}\x{6EC4}\x{6EC5}\x{6EC9}' - . '\x{6ECB}\x{6ECC}\x{6ED1}\x{6ED3}\x{6ED4}\x{6ED5}\x{6EDD}\x{6EDE}\x{6EEC}' - . '\x{6EEF}\x{6EF2}\x{6EF4}\x{6EF7}\x{6EF8}\x{6EFE}\x{6EFF}\x{6F01}\x{6F02}' - . '\x{6F06}\x{6F09}\x{6F0F}\x{6F11}\x{6F13}\x{6F14}\x{6F15}\x{6F20}\x{6F22}' - . '\x{6F23}\x{6F2B}\x{6F2C}\x{6F31}\x{6F32}\x{6F38}\x{6F3E}\x{6F3F}\x{6F41}' - . '\x{6F45}\x{6F54}\x{6F58}\x{6F5B}\x{6F5C}\x{6F5F}\x{6F64}\x{6F66}\x{6F6D}' - . '\x{6F6E}\x{6F6F}\x{6F70}\x{6F74}\x{6F78}\x{6F7A}\x{6F7C}\x{6F80}\x{6F81}' - . '\x{6F82}\x{6F84}\x{6F86}\x{6F8E}\x{6F91}\x{6F97}\x{6FA1}\x{6FA3}\x{6FA4}' - . '\x{6FAA}\x{6FB1}\x{6FB3}\x{6FB9}\x{6FC0}\x{6FC1}\x{6FC2}\x{6FC3}\x{6FC6}' - . '\x{6FD4}\x{6FD5}\x{6FD8}\x{6FDB}\x{6FDF}\x{6FE0}\x{6FE1}\x{6FE4}\x{6FEB}' - . '\x{6FEC}\x{6FEE}\x{6FEF}\x{6FF1}\x{6FF3}\x{6FF6}\x{6FFA}\x{6FFE}\x{7001}' - . '\x{7009}\x{700B}\x{700F}\x{7011}\x{7015}\x{7018}\x{701A}\x{701B}\x{701D}' - . '\x{701E}\x{701F}\x{7026}\x{7027}\x{702C}\x{7030}\x{7032}\x{703E}\x{704C}' - . '\x{7051}\x{7058}\x{7063}\x{706B}\x{706F}\x{7070}\x{7078}\x{707C}\x{707D}' - . '\x{7089}\x{708A}\x{708E}\x{7092}\x{7099}\x{70AC}\x{70AD}\x{70AE}\x{70AF}' - . '\x{70B3}\x{70B8}\x{70B9}\x{70BA}\x{70C8}\x{70CB}\x{70CF}\x{70D9}\x{70DD}' - . '\x{70DF}\x{70F1}\x{70F9}\x{70FD}\x{7109}\x{7114}\x{7119}\x{711A}\x{711C}' - . '\x{7121}\x{7126}\x{7136}\x{713C}\x{7149}\x{714C}\x{714E}\x{7155}\x{7156}' - . '\x{7159}\x{7162}\x{7164}\x{7165}\x{7166}\x{7167}\x{7169}\x{716C}\x{716E}' - . '\x{717D}\x{7184}\x{7188}\x{718A}\x{718F}\x{7194}\x{7195}\x{7199}\x{719F}' - . '\x{71A8}\x{71AC}\x{71B1}\x{71B9}\x{71BE}\x{71C3}\x{71C8}\x{71C9}\x{71CE}' - . '\x{71D0}\x{71D2}\x{71D4}\x{71D5}\x{71D7}\x{71DF}\x{71E0}\x{71E5}\x{71E6}' - . '\x{71E7}\x{71EC}\x{71ED}\x{71EE}\x{71F5}\x{71F9}\x{71FB}\x{71FC}\x{71FF}' - . '\x{7206}\x{720D}\x{7210}\x{721B}\x{7228}\x{722A}\x{722C}\x{722D}\x{7230}' - . '\x{7232}\x{7235}\x{7236}\x{723A}\x{723B}\x{723C}\x{723D}\x{723E}\x{723F}' - . '\x{7240}\x{7246}\x{7247}\x{7248}\x{724B}\x{724C}\x{7252}\x{7258}\x{7259}' - . '\x{725B}\x{725D}\x{725F}\x{7261}\x{7262}\x{7267}\x{7269}\x{7272}\x{7274}' - . '\x{7279}\x{727D}\x{727E}\x{7280}\x{7281}\x{7282}\x{7287}\x{7292}\x{7296}' - . '\x{72A0}\x{72A2}\x{72A7}\x{72AC}\x{72AF}\x{72B2}\x{72B6}\x{72B9}\x{72C2}' - . '\x{72C3}\x{72C4}\x{72C6}\x{72CE}\x{72D0}\x{72D2}\x{72D7}\x{72D9}\x{72DB}' - . '\x{72E0}\x{72E1}\x{72E2}\x{72E9}\x{72EC}\x{72ED}\x{72F7}\x{72F8}\x{72F9}' - . '\x{72FC}\x{72FD}\x{730A}\x{7316}\x{7317}\x{731B}\x{731C}\x{731D}\x{731F}' - . '\x{7325}\x{7329}\x{732A}\x{732B}\x{732E}\x{732F}\x{7334}\x{7336}\x{7337}' - . '\x{733E}\x{733F}\x{7344}\x{7345}\x{734E}\x{734F}\x{7357}\x{7363}\x{7368}' - . '\x{736A}\x{7370}\x{7372}\x{7375}\x{7378}\x{737A}\x{737B}\x{7384}\x{7387}' - . '\x{7389}\x{738B}\x{7396}\x{73A9}\x{73B2}\x{73B3}\x{73BB}\x{73C0}\x{73C2}' - . '\x{73C8}\x{73CA}\x{73CD}\x{73CE}\x{73DE}\x{73E0}\x{73E5}\x{73EA}\x{73ED}' - . '\x{73EE}\x{73F1}\x{73F8}\x{73FE}\x{7403}\x{7405}\x{7406}\x{7409}\x{7422}' - . '\x{7425}\x{7432}\x{7433}\x{7434}\x{7435}\x{7436}\x{743A}\x{743F}\x{7441}' - . '\x{7455}\x{7459}\x{745A}\x{745B}\x{745C}\x{745E}\x{745F}\x{7460}\x{7463}' - . '\x{7464}\x{7469}\x{746A}\x{746F}\x{7470}\x{7473}\x{7476}\x{747E}\x{7483}' - . '\x{748B}\x{749E}\x{74A2}\x{74A7}\x{74B0}\x{74BD}\x{74CA}\x{74CF}\x{74D4}' - . '\x{74DC}\x{74E0}\x{74E2}\x{74E3}\x{74E6}\x{74E7}\x{74E9}\x{74EE}\x{74F0}' - . '\x{74F1}\x{74F2}\x{74F6}\x{74F7}\x{74F8}\x{7503}\x{7504}\x{7505}\x{750C}' - . '\x{750D}\x{750E}\x{7511}\x{7513}\x{7515}\x{7518}\x{751A}\x{751C}\x{751E}' - . '\x{751F}\x{7523}\x{7525}\x{7526}\x{7528}\x{752B}\x{752C}\x{7530}\x{7531}' - . '\x{7532}\x{7533}\x{7537}\x{7538}\x{753A}\x{753B}\x{753C}\x{7544}\x{7546}' - . '\x{7549}\x{754A}\x{754B}\x{754C}\x{754D}\x{754F}\x{7551}\x{7554}\x{7559}' - . '\x{755A}\x{755B}\x{755C}\x{755D}\x{7560}\x{7562}\x{7564}\x{7565}\x{7566}' - . '\x{7567}\x{7569}\x{756A}\x{756B}\x{756D}\x{7570}\x{7573}\x{7574}\x{7576}' - . '\x{7577}\x{7578}\x{757F}\x{7582}\x{7586}\x{7587}\x{7589}\x{758A}\x{758B}' - . '\x{758E}\x{758F}\x{7591}\x{7594}\x{759A}\x{759D}\x{75A3}\x{75A5}\x{75AB}' - . '\x{75B1}\x{75B2}\x{75B3}\x{75B5}\x{75B8}\x{75B9}\x{75BC}\x{75BD}\x{75BE}' - . '\x{75C2}\x{75C3}\x{75C5}\x{75C7}\x{75CA}\x{75CD}\x{75D2}\x{75D4}\x{75D5}' - . '\x{75D8}\x{75D9}\x{75DB}\x{75DE}\x{75E2}\x{75E3}\x{75E9}\x{75F0}\x{75F2}' - . '\x{75F3}\x{75F4}\x{75FA}\x{75FC}\x{75FE}\x{75FF}\x{7601}\x{7609}\x{760B}' - . '\x{760D}\x{761F}\x{7620}\x{7621}\x{7622}\x{7624}\x{7627}\x{7630}\x{7634}' - . '\x{763B}\x{7642}\x{7646}\x{7647}\x{7648}\x{764C}\x{7652}\x{7656}\x{7658}' - . '\x{765C}\x{7661}\x{7662}\x{7667}\x{7668}\x{7669}\x{766A}\x{766C}\x{7670}' - . '\x{7672}\x{7676}\x{7678}\x{767A}\x{767B}\x{767C}\x{767D}\x{767E}\x{7680}' - . '\x{7683}\x{7684}\x{7686}\x{7687}\x{7688}\x{768B}\x{768E}\x{7690}\x{7693}' - . '\x{7696}\x{7699}\x{769A}\x{76AE}\x{76B0}\x{76B4}\x{76B7}\x{76B8}\x{76B9}' - . '\x{76BA}\x{76BF}\x{76C2}\x{76C3}\x{76C6}\x{76C8}\x{76CA}\x{76CD}\x{76D2}' - . '\x{76D6}\x{76D7}\x{76DB}\x{76DC}\x{76DE}\x{76DF}\x{76E1}\x{76E3}\x{76E4}' - . '\x{76E5}\x{76E7}\x{76EA}\x{76EE}\x{76F2}\x{76F4}\x{76F8}\x{76FB}\x{76FE}' - . '\x{7701}\x{7704}\x{7707}\x{7708}\x{7709}\x{770B}\x{770C}\x{771B}\x{771E}' - . '\x{771F}\x{7720}\x{7724}\x{7725}\x{7726}\x{7729}\x{7737}\x{7738}\x{773A}' - . '\x{773C}\x{7740}\x{7747}\x{775A}\x{775B}\x{7761}\x{7763}\x{7765}\x{7766}' - . '\x{7768}\x{776B}\x{7779}\x{777E}\x{777F}\x{778B}\x{778E}\x{7791}\x{779E}' - . '\x{77A0}\x{77A5}\x{77AC}\x{77AD}\x{77B0}\x{77B3}\x{77B6}\x{77B9}\x{77BB}' - . '\x{77BC}\x{77BD}\x{77BF}\x{77C7}\x{77CD}\x{77D7}\x{77DA}\x{77DB}\x{77DC}' - . '\x{77E2}\x{77E3}\x{77E5}\x{77E7}\x{77E9}\x{77ED}\x{77EE}\x{77EF}\x{77F3}' - . '\x{77FC}\x{7802}\x{780C}\x{7812}\x{7814}\x{7815}\x{7820}\x{7825}\x{7826}' - . '\x{7827}\x{7832}\x{7834}\x{783A}\x{783F}\x{7845}\x{785D}\x{786B}\x{786C}' - . '\x{786F}\x{7872}\x{7874}\x{787C}\x{7881}\x{7886}\x{7887}\x{788C}\x{788D}' - . '\x{788E}\x{7891}\x{7893}\x{7895}\x{7897}\x{789A}\x{78A3}\x{78A7}\x{78A9}' - . '\x{78AA}\x{78AF}\x{78B5}\x{78BA}\x{78BC}\x{78BE}\x{78C1}\x{78C5}\x{78C6}' - . '\x{78CA}\x{78CB}\x{78D0}\x{78D1}\x{78D4}\x{78DA}\x{78E7}\x{78E8}\x{78EC}' - . '\x{78EF}\x{78F4}\x{78FD}\x{7901}\x{7907}\x{790E}\x{7911}\x{7912}\x{7919}' - . '\x{7926}\x{792A}\x{792B}\x{792C}\x{793A}\x{793C}\x{793E}\x{7940}\x{7941}' - . '\x{7947}\x{7948}\x{7949}\x{7950}\x{7953}\x{7955}\x{7956}\x{7957}\x{795A}' - . '\x{795D}\x{795E}\x{795F}\x{7960}\x{7962}\x{7965}\x{7968}\x{796D}\x{7977}' - . '\x{797A}\x{797F}\x{7980}\x{7981}\x{7984}\x{7985}\x{798A}\x{798D}\x{798E}' - . '\x{798F}\x{799D}\x{79A6}\x{79A7}\x{79AA}\x{79AE}\x{79B0}\x{79B3}\x{79B9}' - . '\x{79BA}\x{79BD}\x{79BE}\x{79BF}\x{79C0}\x{79C1}\x{79C9}\x{79CB}\x{79D1}' - . '\x{79D2}\x{79D5}\x{79D8}\x{79DF}\x{79E1}\x{79E3}\x{79E4}\x{79E6}\x{79E7}' - . '\x{79E9}\x{79EC}\x{79F0}\x{79FB}\x{7A00}\x{7A08}\x{7A0B}\x{7A0D}\x{7A0E}' - . '\x{7A14}\x{7A17}\x{7A18}\x{7A19}\x{7A1A}\x{7A1C}\x{7A1F}\x{7A20}\x{7A2E}' - . '\x{7A31}\x{7A32}\x{7A37}\x{7A3B}\x{7A3C}\x{7A3D}\x{7A3E}\x{7A3F}\x{7A40}' - . '\x{7A42}\x{7A43}\x{7A46}\x{7A49}\x{7A4D}\x{7A4E}\x{7A4F}\x{7A50}\x{7A57}' - . '\x{7A61}\x{7A62}\x{7A63}\x{7A69}\x{7A6B}\x{7A70}\x{7A74}\x{7A76}\x{7A79}' - . '\x{7A7A}\x{7A7D}\x{7A7F}\x{7A81}\x{7A83}\x{7A84}\x{7A88}\x{7A92}\x{7A93}' - . '\x{7A95}\x{7A96}\x{7A97}\x{7A98}\x{7A9F}\x{7AA9}\x{7AAA}\x{7AAE}\x{7AAF}' - . '\x{7AB0}\x{7AB6}\x{7ABA}\x{7ABF}\x{7AC3}\x{7AC4}\x{7AC5}\x{7AC7}\x{7AC8}' - . '\x{7ACA}\x{7ACB}\x{7ACD}\x{7ACF}\x{7AD2}\x{7AD3}\x{7AD5}\x{7AD9}\x{7ADA}' - . '\x{7ADC}\x{7ADD}\x{7ADF}\x{7AE0}\x{7AE1}\x{7AE2}\x{7AE3}\x{7AE5}\x{7AE6}' - . '\x{7AEA}\x{7AED}\x{7AEF}\x{7AF0}\x{7AF6}\x{7AF8}\x{7AF9}\x{7AFA}\x{7AFF}' - . '\x{7B02}\x{7B04}\x{7B06}\x{7B08}\x{7B0A}\x{7B0B}\x{7B0F}\x{7B11}\x{7B18}' - . '\x{7B19}\x{7B1B}\x{7B1E}\x{7B20}\x{7B25}\x{7B26}\x{7B28}\x{7B2C}\x{7B33}' - . '\x{7B35}\x{7B36}\x{7B39}\x{7B45}\x{7B46}\x{7B48}\x{7B49}\x{7B4B}\x{7B4C}' - . '\x{7B4D}\x{7B4F}\x{7B50}\x{7B51}\x{7B52}\x{7B54}\x{7B56}\x{7B5D}\x{7B65}' - . '\x{7B67}\x{7B6C}\x{7B6E}\x{7B70}\x{7B71}\x{7B74}\x{7B75}\x{7B7A}\x{7B86}' - . '\x{7B87}\x{7B8B}\x{7B8D}\x{7B8F}\x{7B92}\x{7B94}\x{7B95}\x{7B97}\x{7B98}' - . '\x{7B99}\x{7B9A}\x{7B9C}\x{7B9D}\x{7B9F}\x{7BA1}\x{7BAA}\x{7BAD}\x{7BB1}' - . '\x{7BB4}\x{7BB8}\x{7BC0}\x{7BC1}\x{7BC4}\x{7BC6}\x{7BC7}\x{7BC9}\x{7BCB}' - . '\x{7BCC}\x{7BCF}\x{7BDD}\x{7BE0}\x{7BE4}\x{7BE5}\x{7BE6}\x{7BE9}\x{7BED}' - . '\x{7BF3}\x{7BF6}\x{7BF7}\x{7C00}\x{7C07}\x{7C0D}\x{7C11}\x{7C12}\x{7C13}' - . '\x{7C14}\x{7C17}\x{7C1F}\x{7C21}\x{7C23}\x{7C27}\x{7C2A}\x{7C2B}\x{7C37}' - . '\x{7C38}\x{7C3D}\x{7C3E}\x{7C3F}\x{7C40}\x{7C43}\x{7C4C}\x{7C4D}\x{7C4F}' - . '\x{7C50}\x{7C54}\x{7C56}\x{7C58}\x{7C5F}\x{7C60}\x{7C64}\x{7C65}\x{7C6C}' - . '\x{7C73}\x{7C75}\x{7C7E}\x{7C81}\x{7C82}\x{7C83}\x{7C89}\x{7C8B}\x{7C8D}' - . '\x{7C90}\x{7C92}\x{7C95}\x{7C97}\x{7C98}\x{7C9B}\x{7C9F}\x{7CA1}\x{7CA2}' - . '\x{7CA4}\x{7CA5}\x{7CA7}\x{7CA8}\x{7CAB}\x{7CAD}\x{7CAE}\x{7CB1}\x{7CB2}' - . '\x{7CB3}\x{7CB9}\x{7CBD}\x{7CBE}\x{7CC0}\x{7CC2}\x{7CC5}\x{7CCA}\x{7CCE}' - . '\x{7CD2}\x{7CD6}\x{7CD8}\x{7CDC}\x{7CDE}\x{7CDF}\x{7CE0}\x{7CE2}\x{7CE7}' - . '\x{7CEF}\x{7CF2}\x{7CF4}\x{7CF6}\x{7CF8}\x{7CFA}\x{7CFB}\x{7CFE}\x{7D00}' - . '\x{7D02}\x{7D04}\x{7D05}\x{7D06}\x{7D0A}\x{7D0B}\x{7D0D}\x{7D10}\x{7D14}' - . '\x{7D15}\x{7D17}\x{7D18}\x{7D19}\x{7D1A}\x{7D1B}\x{7D1C}\x{7D20}\x{7D21}' - . '\x{7D22}\x{7D2B}\x{7D2C}\x{7D2E}\x{7D2F}\x{7D30}\x{7D32}\x{7D33}\x{7D35}' - . '\x{7D39}\x{7D3A}\x{7D3F}\x{7D42}\x{7D43}\x{7D44}\x{7D45}\x{7D46}\x{7D4B}' - . '\x{7D4C}\x{7D4E}\x{7D4F}\x{7D50}\x{7D56}\x{7D5B}\x{7D5E}\x{7D61}\x{7D62}' - . '\x{7D63}\x{7D66}\x{7D68}\x{7D6E}\x{7D71}\x{7D72}\x{7D73}\x{7D75}\x{7D76}' - . '\x{7D79}\x{7D7D}\x{7D89}\x{7D8F}\x{7D93}\x{7D99}\x{7D9A}\x{7D9B}\x{7D9C}' - . '\x{7D9F}\x{7DA2}\x{7DA3}\x{7DAB}\x{7DAC}\x{7DAD}\x{7DAE}\x{7DAF}\x{7DB0}' - . '\x{7DB1}\x{7DB2}\x{7DB4}\x{7DB5}\x{7DB8}\x{7DBA}\x{7DBB}\x{7DBD}\x{7DBE}' - . '\x{7DBF}\x{7DC7}\x{7DCA}\x{7DCB}\x{7DCF}\x{7DD1}\x{7DD2}\x{7DD5}\x{7DD8}' - . '\x{7DDA}\x{7DDC}\x{7DDD}\x{7DDE}\x{7DE0}\x{7DE1}\x{7DE4}\x{7DE8}\x{7DE9}' - . '\x{7DEC}\x{7DEF}\x{7DF2}\x{7DF4}\x{7DFB}\x{7E01}\x{7E04}\x{7E05}\x{7E09}' - . '\x{7E0A}\x{7E0B}\x{7E12}\x{7E1B}\x{7E1E}\x{7E1F}\x{7E21}\x{7E22}\x{7E23}' - . '\x{7E26}\x{7E2B}\x{7E2E}\x{7E31}\x{7E32}\x{7E35}\x{7E37}\x{7E39}\x{7E3A}' - . '\x{7E3B}\x{7E3D}\x{7E3E}\x{7E41}\x{7E43}\x{7E46}\x{7E4A}\x{7E4B}\x{7E4D}' - . '\x{7E54}\x{7E55}\x{7E56}\x{7E59}\x{7E5A}\x{7E5D}\x{7E5E}\x{7E66}\x{7E67}' - . '\x{7E69}\x{7E6A}\x{7E6D}\x{7E70}\x{7E79}\x{7E7B}\x{7E7C}\x{7E7D}\x{7E7F}' - . '\x{7E82}\x{7E83}\x{7E88}\x{7E89}\x{7E8C}\x{7E8E}\x{7E8F}\x{7E90}\x{7E92}' - . '\x{7E93}\x{7E94}\x{7E96}\x{7E9B}\x{7E9C}\x{7F36}\x{7F38}\x{7F3A}\x{7F45}' - . '\x{7F4C}\x{7F4D}\x{7F4E}\x{7F50}\x{7F51}\x{7F54}\x{7F55}\x{7F58}\x{7F5F}' - . '\x{7F60}\x{7F67}\x{7F68}\x{7F69}\x{7F6A}\x{7F6B}\x{7F6E}\x{7F70}\x{7F72}' - . '\x{7F75}\x{7F77}\x{7F78}\x{7F79}\x{7F82}\x{7F83}\x{7F85}\x{7F86}\x{7F87}' - . '\x{7F88}\x{7F8A}\x{7F8C}\x{7F8E}\x{7F94}\x{7F9A}\x{7F9D}\x{7F9E}\x{7FA3}' - . '\x{7FA4}\x{7FA8}\x{7FA9}\x{7FAE}\x{7FAF}\x{7FB2}\x{7FB6}\x{7FB8}\x{7FB9}' - . '\x{7FBD}\x{7FC1}\x{7FC5}\x{7FC6}\x{7FCA}\x{7FCC}\x{7FD2}\x{7FD4}\x{7FD5}' - . '\x{7FE0}\x{7FE1}\x{7FE6}\x{7FE9}\x{7FEB}\x{7FF0}\x{7FF3}\x{7FF9}\x{7FFB}' - . '\x{7FFC}\x{8000}\x{8001}\x{8003}\x{8004}\x{8005}\x{8006}\x{800B}\x{800C}' - . '\x{8010}\x{8012}\x{8015}\x{8017}\x{8018}\x{8019}\x{801C}\x{8021}\x{8028}' - . '\x{8033}\x{8036}\x{803B}\x{803D}\x{803F}\x{8046}\x{804A}\x{8052}\x{8056}' - . '\x{8058}\x{805A}\x{805E}\x{805F}\x{8061}\x{8062}\x{8068}\x{806F}\x{8070}' - . '\x{8072}\x{8073}\x{8074}\x{8076}\x{8077}\x{8079}\x{807D}\x{807E}\x{807F}' - . '\x{8084}\x{8085}\x{8086}\x{8087}\x{8089}\x{808B}\x{808C}\x{8093}\x{8096}' - . '\x{8098}\x{809A}\x{809B}\x{809D}\x{80A1}\x{80A2}\x{80A5}\x{80A9}\x{80AA}' - . '\x{80AC}\x{80AD}\x{80AF}\x{80B1}\x{80B2}\x{80B4}\x{80BA}\x{80C3}\x{80C4}' - . '\x{80C6}\x{80CC}\x{80CE}\x{80D6}\x{80D9}\x{80DA}\x{80DB}\x{80DD}\x{80DE}' - . '\x{80E1}\x{80E4}\x{80E5}\x{80EF}\x{80F1}\x{80F4}\x{80F8}\x{80FC}\x{80FD}' - . '\x{8102}\x{8105}\x{8106}\x{8107}\x{8108}\x{8109}\x{810A}\x{811A}\x{811B}' - . '\x{8123}\x{8129}\x{812F}\x{8131}\x{8133}\x{8139}\x{813E}\x{8146}\x{814B}' - . '\x{814E}\x{8150}\x{8151}\x{8153}\x{8154}\x{8155}\x{815F}\x{8165}\x{8166}' - . '\x{816B}\x{816E}\x{8170}\x{8171}\x{8174}\x{8178}\x{8179}\x{817A}\x{817F}' - . '\x{8180}\x{8182}\x{8183}\x{8188}\x{818A}\x{818F}\x{8193}\x{8195}\x{819A}' - . '\x{819C}\x{819D}\x{81A0}\x{81A3}\x{81A4}\x{81A8}\x{81A9}\x{81B0}\x{81B3}' - . '\x{81B5}\x{81B8}\x{81BA}\x{81BD}\x{81BE}\x{81BF}\x{81C0}\x{81C2}\x{81C6}' - . '\x{81C8}\x{81C9}\x{81CD}\x{81D1}\x{81D3}\x{81D8}\x{81D9}\x{81DA}\x{81DF}' - . '\x{81E0}\x{81E3}\x{81E5}\x{81E7}\x{81E8}\x{81EA}\x{81ED}\x{81F3}\x{81F4}' - . '\x{81FA}\x{81FB}\x{81FC}\x{81FE}\x{8201}\x{8202}\x{8205}\x{8207}\x{8208}' - . '\x{8209}\x{820A}\x{820C}\x{820D}\x{820E}\x{8210}\x{8212}\x{8216}\x{8217}' - . '\x{8218}\x{821B}\x{821C}\x{821E}\x{821F}\x{8229}\x{822A}\x{822B}\x{822C}' - . '\x{822E}\x{8233}\x{8235}\x{8236}\x{8237}\x{8238}\x{8239}\x{8240}\x{8247}' - . '\x{8258}\x{8259}\x{825A}\x{825D}\x{825F}\x{8262}\x{8264}\x{8266}\x{8268}' - . '\x{826A}\x{826B}\x{826E}\x{826F}\x{8271}\x{8272}\x{8276}\x{8277}\x{8278}' - . '\x{827E}\x{828B}\x{828D}\x{8292}\x{8299}\x{829D}\x{829F}\x{82A5}\x{82A6}' - . '\x{82AB}\x{82AC}\x{82AD}\x{82AF}\x{82B1}\x{82B3}\x{82B8}\x{82B9}\x{82BB}' - . '\x{82BD}\x{82C5}\x{82D1}\x{82D2}\x{82D3}\x{82D4}\x{82D7}\x{82D9}\x{82DB}' - . '\x{82DC}\x{82DE}\x{82DF}\x{82E1}\x{82E3}\x{82E5}\x{82E6}\x{82E7}\x{82EB}' - . '\x{82F1}\x{82F3}\x{82F4}\x{82F9}\x{82FA}\x{82FB}\x{8302}\x{8303}\x{8304}' - . '\x{8305}\x{8306}\x{8309}\x{830E}\x{8316}\x{8317}\x{8318}\x{831C}\x{8323}' - . '\x{8328}\x{832B}\x{832F}\x{8331}\x{8332}\x{8334}\x{8335}\x{8336}\x{8338}' - . '\x{8339}\x{8340}\x{8345}\x{8349}\x{834A}\x{834F}\x{8350}\x{8352}\x{8358}' - . '\x{8373}\x{8375}\x{8377}\x{837B}\x{837C}\x{8385}\x{8387}\x{8389}\x{838A}' - . '\x{838E}\x{8393}\x{8396}\x{839A}\x{839E}\x{839F}\x{83A0}\x{83A2}\x{83A8}' - . '\x{83AA}\x{83AB}\x{83B1}\x{83B5}\x{83BD}\x{83C1}\x{83C5}\x{83CA}\x{83CC}' - . '\x{83CE}\x{83D3}\x{83D6}\x{83D8}\x{83DC}\x{83DF}\x{83E0}\x{83E9}\x{83EB}' - . '\x{83EF}\x{83F0}\x{83F1}\x{83F2}\x{83F4}\x{83F7}\x{83FB}\x{83FD}\x{8403}' - . '\x{8404}\x{8407}\x{840B}\x{840C}\x{840D}\x{840E}\x{8413}\x{8420}\x{8422}' - . '\x{8429}\x{842A}\x{842C}\x{8431}\x{8435}\x{8438}\x{843C}\x{843D}\x{8446}' - . '\x{8449}\x{844E}\x{8457}\x{845B}\x{8461}\x{8462}\x{8463}\x{8466}\x{8469}' - . '\x{846B}\x{846C}\x{846D}\x{846E}\x{846F}\x{8471}\x{8475}\x{8477}\x{8479}' - . '\x{847A}\x{8482}\x{8484}\x{848B}\x{8490}\x{8494}\x{8499}\x{849C}\x{849F}' - . '\x{84A1}\x{84AD}\x{84B2}\x{84B8}\x{84B9}\x{84BB}\x{84BC}\x{84BF}\x{84C1}' - . '\x{84C4}\x{84C6}\x{84C9}\x{84CA}\x{84CB}\x{84CD}\x{84D0}\x{84D1}\x{84D6}' - . '\x{84D9}\x{84DA}\x{84EC}\x{84EE}\x{84F4}\x{84FC}\x{84FF}\x{8500}\x{8506}' - . '\x{8511}\x{8513}\x{8514}\x{8515}\x{8517}\x{8518}\x{851A}\x{851F}\x{8521}' - . '\x{8526}\x{852C}\x{852D}\x{8535}\x{853D}\x{8540}\x{8541}\x{8543}\x{8548}' - . '\x{8549}\x{854A}\x{854B}\x{854E}\x{8555}\x{8557}\x{8558}\x{855A}\x{8563}' - . '\x{8568}\x{8569}\x{856A}\x{856D}\x{8577}\x{857E}\x{8580}\x{8584}\x{8587}' - . '\x{8588}\x{858A}\x{8590}\x{8591}\x{8594}\x{8597}\x{8599}\x{859B}\x{859C}' - . '\x{85A4}\x{85A6}\x{85A8}\x{85A9}\x{85AA}\x{85AB}\x{85AC}\x{85AE}\x{85AF}' - . '\x{85B9}\x{85BA}\x{85C1}\x{85C9}\x{85CD}\x{85CF}\x{85D0}\x{85D5}\x{85DC}' - . '\x{85DD}\x{85E4}\x{85E5}\x{85E9}\x{85EA}\x{85F7}\x{85F9}\x{85FA}\x{85FB}' - . '\x{85FE}\x{8602}\x{8606}\x{8607}\x{860A}\x{860B}\x{8613}\x{8616}\x{8617}' - . '\x{861A}\x{8622}\x{862D}\x{862F}\x{8630}\x{863F}\x{864D}\x{864E}\x{8650}' - . '\x{8654}\x{8655}\x{865A}\x{865C}\x{865E}\x{865F}\x{8667}\x{866B}\x{8671}' - . '\x{8679}\x{867B}\x{868A}\x{868B}\x{868C}\x{8693}\x{8695}\x{86A3}\x{86A4}' - . '\x{86A9}\x{86AA}\x{86AB}\x{86AF}\x{86B0}\x{86B6}\x{86C4}\x{86C6}\x{86C7}' - . '\x{86C9}\x{86CB}\x{86CD}\x{86CE}\x{86D4}\x{86D9}\x{86DB}\x{86DE}\x{86DF}' - . '\x{86E4}\x{86E9}\x{86EC}\x{86ED}\x{86EE}\x{86EF}\x{86F8}\x{86F9}\x{86FB}' - . '\x{86FE}\x{8700}\x{8702}\x{8703}\x{8706}\x{8708}\x{8709}\x{870A}\x{870D}' - . '\x{8711}\x{8712}\x{8718}\x{871A}\x{871C}\x{8725}\x{8729}\x{8734}\x{8737}' - . '\x{873B}\x{873F}\x{8749}\x{874B}\x{874C}\x{874E}\x{8753}\x{8755}\x{8757}' - . '\x{8759}\x{875F}\x{8760}\x{8763}\x{8766}\x{8768}\x{876A}\x{876E}\x{8774}' - . '\x{8776}\x{8778}\x{877F}\x{8782}\x{878D}\x{879F}\x{87A2}\x{87AB}\x{87AF}' - . '\x{87B3}\x{87BA}\x{87BB}\x{87BD}\x{87C0}\x{87C4}\x{87C6}\x{87C7}\x{87CB}' - . '\x{87D0}\x{87D2}\x{87E0}\x{87EF}\x{87F2}\x{87F6}\x{87F7}\x{87F9}\x{87FB}' - . '\x{87FE}\x{8805}\x{880D}\x{880E}\x{880F}\x{8811}\x{8815}\x{8816}\x{8821}' - . '\x{8822}\x{8823}\x{8827}\x{8831}\x{8836}\x{8839}\x{883B}\x{8840}\x{8842}' - . '\x{8844}\x{8846}\x{884C}\x{884D}\x{8852}\x{8853}\x{8857}\x{8859}\x{885B}' - . '\x{885D}\x{885E}\x{8861}\x{8862}\x{8863}\x{8868}\x{886B}\x{8870}\x{8872}' - . '\x{8875}\x{8877}\x{887D}\x{887E}\x{887F}\x{8881}\x{8882}\x{8888}\x{888B}' - . '\x{888D}\x{8892}\x{8896}\x{8897}\x{8899}\x{889E}\x{88A2}\x{88A4}\x{88AB}' - . '\x{88AE}\x{88B0}\x{88B1}\x{88B4}\x{88B5}\x{88B7}\x{88BF}\x{88C1}\x{88C2}' - . '\x{88C3}\x{88C4}\x{88C5}\x{88CF}\x{88D4}\x{88D5}\x{88D8}\x{88D9}\x{88DC}' - . '\x{88DD}\x{88DF}\x{88E1}\x{88E8}\x{88F2}\x{88F3}\x{88F4}\x{88F8}\x{88F9}' - . '\x{88FC}\x{88FD}\x{88FE}\x{8902}\x{8904}\x{8907}\x{890A}\x{890C}\x{8910}' - . '\x{8912}\x{8913}\x{891D}\x{891E}\x{8925}\x{892A}\x{892B}\x{8936}\x{8938}' - . '\x{893B}\x{8941}\x{8943}\x{8944}\x{894C}\x{894D}\x{8956}\x{895E}\x{895F}' - . '\x{8960}\x{8964}\x{8966}\x{896A}\x{896D}\x{896F}\x{8972}\x{8974}\x{8977}' - . '\x{897E}\x{897F}\x{8981}\x{8983}\x{8986}\x{8987}\x{8988}\x{898A}\x{898B}' - . '\x{898F}\x{8993}\x{8996}\x{8997}\x{8998}\x{899A}\x{89A1}\x{89A6}\x{89A7}' - . '\x{89A9}\x{89AA}\x{89AC}\x{89AF}\x{89B2}\x{89B3}\x{89BA}\x{89BD}\x{89BF}' - . '\x{89C0}\x{89D2}\x{89DA}\x{89DC}\x{89DD}\x{89E3}\x{89E6}\x{89E7}\x{89F4}' - . '\x{89F8}\x{8A00}\x{8A02}\x{8A03}\x{8A08}\x{8A0A}\x{8A0C}\x{8A0E}\x{8A10}' - . '\x{8A13}\x{8A16}\x{8A17}\x{8A18}\x{8A1B}\x{8A1D}\x{8A1F}\x{8A23}\x{8A25}' - . '\x{8A2A}\x{8A2D}\x{8A31}\x{8A33}\x{8A34}\x{8A36}\x{8A3A}\x{8A3B}\x{8A3C}' - . '\x{8A41}\x{8A46}\x{8A48}\x{8A50}\x{8A51}\x{8A52}\x{8A54}\x{8A55}\x{8A5B}' - . '\x{8A5E}\x{8A60}\x{8A62}\x{8A63}\x{8A66}\x{8A69}\x{8A6B}\x{8A6C}\x{8A6D}' - . '\x{8A6E}\x{8A70}\x{8A71}\x{8A72}\x{8A73}\x{8A7C}\x{8A82}\x{8A84}\x{8A85}' - . '\x{8A87}\x{8A89}\x{8A8C}\x{8A8D}\x{8A91}\x{8A93}\x{8A95}\x{8A98}\x{8A9A}' - . '\x{8A9E}\x{8AA0}\x{8AA1}\x{8AA3}\x{8AA4}\x{8AA5}\x{8AA6}\x{8AA8}\x{8AAC}' - . '\x{8AAD}\x{8AB0}\x{8AB2}\x{8AB9}\x{8ABC}\x{8ABF}\x{8AC2}\x{8AC4}\x{8AC7}' - . '\x{8ACB}\x{8ACC}\x{8ACD}\x{8ACF}\x{8AD2}\x{8AD6}\x{8ADA}\x{8ADB}\x{8ADC}' - . '\x{8ADE}\x{8AE0}\x{8AE1}\x{8AE2}\x{8AE4}\x{8AE6}\x{8AE7}\x{8AEB}\x{8AED}' - . '\x{8AEE}\x{8AF1}\x{8AF3}\x{8AF7}\x{8AF8}\x{8AFA}\x{8AFE}\x{8B00}\x{8B01}' - . '\x{8B02}\x{8B04}\x{8B07}\x{8B0C}\x{8B0E}\x{8B10}\x{8B14}\x{8B16}\x{8B17}' - . '\x{8B19}\x{8B1A}\x{8B1B}\x{8B1D}\x{8B20}\x{8B21}\x{8B26}\x{8B28}\x{8B2B}' - . '\x{8B2C}\x{8B33}\x{8B39}\x{8B3E}\x{8B41}\x{8B49}\x{8B4C}\x{8B4E}\x{8B4F}' - . '\x{8B56}\x{8B58}\x{8B5A}\x{8B5B}\x{8B5C}\x{8B5F}\x{8B66}\x{8B6B}\x{8B6C}' - . '\x{8B6F}\x{8B70}\x{8B71}\x{8B72}\x{8B74}\x{8B77}\x{8B7D}\x{8B80}\x{8B83}' - . '\x{8B8A}\x{8B8C}\x{8B8E}\x{8B90}\x{8B92}\x{8B93}\x{8B96}\x{8B99}\x{8B9A}' - . '\x{8C37}\x{8C3A}\x{8C3F}\x{8C41}\x{8C46}\x{8C48}\x{8C4A}\x{8C4C}\x{8C4E}' - . '\x{8C50}\x{8C55}\x{8C5A}\x{8C61}\x{8C62}\x{8C6A}\x{8C6B}\x{8C6C}\x{8C78}' - . '\x{8C79}\x{8C7A}\x{8C7C}\x{8C82}\x{8C85}\x{8C89}\x{8C8A}\x{8C8C}\x{8C8D}' - . '\x{8C8E}\x{8C94}\x{8C98}\x{8C9D}\x{8C9E}\x{8CA0}\x{8CA1}\x{8CA2}\x{8CA7}' - . '\x{8CA8}\x{8CA9}\x{8CAA}\x{8CAB}\x{8CAC}\x{8CAD}\x{8CAE}\x{8CAF}\x{8CB0}' - . '\x{8CB2}\x{8CB3}\x{8CB4}\x{8CB6}\x{8CB7}\x{8CB8}\x{8CBB}\x{8CBC}\x{8CBD}' - . '\x{8CBF}\x{8CC0}\x{8CC1}\x{8CC2}\x{8CC3}\x{8CC4}\x{8CC7}\x{8CC8}\x{8CCA}' - . '\x{8CCD}\x{8CCE}\x{8CD1}\x{8CD3}\x{8CDA}\x{8CDB}\x{8CDC}\x{8CDE}\x{8CE0}' - . '\x{8CE2}\x{8CE3}\x{8CE4}\x{8CE6}\x{8CEA}\x{8CED}\x{8CFA}\x{8CFB}\x{8CFC}' - . '\x{8CFD}\x{8D04}\x{8D05}\x{8D07}\x{8D08}\x{8D0A}\x{8D0B}\x{8D0D}\x{8D0F}' - . '\x{8D10}\x{8D13}\x{8D14}\x{8D16}\x{8D64}\x{8D66}\x{8D67}\x{8D6B}\x{8D6D}' - . '\x{8D70}\x{8D71}\x{8D73}\x{8D74}\x{8D77}\x{8D81}\x{8D85}\x{8D8A}\x{8D99}' - . '\x{8DA3}\x{8DA8}\x{8DB3}\x{8DBA}\x{8DBE}\x{8DC2}\x{8DCB}\x{8DCC}\x{8DCF}' - . '\x{8DD6}\x{8DDA}\x{8DDB}\x{8DDD}\x{8DDF}\x{8DE1}\x{8DE3}\x{8DE8}\x{8DEA}' - . '\x{8DEB}\x{8DEF}\x{8DF3}\x{8DF5}\x{8DFC}\x{8DFF}\x{8E08}\x{8E09}\x{8E0A}' - . '\x{8E0F}\x{8E10}\x{8E1D}\x{8E1E}\x{8E1F}\x{8E2A}\x{8E30}\x{8E34}\x{8E35}' - . '\x{8E42}\x{8E44}\x{8E47}\x{8E48}\x{8E49}\x{8E4A}\x{8E4C}\x{8E50}\x{8E55}' - . '\x{8E59}\x{8E5F}\x{8E60}\x{8E63}\x{8E64}\x{8E72}\x{8E74}\x{8E76}\x{8E7C}' - . '\x{8E81}\x{8E84}\x{8E85}\x{8E87}\x{8E8A}\x{8E8B}\x{8E8D}\x{8E91}\x{8E93}' - . '\x{8E94}\x{8E99}\x{8EA1}\x{8EAA}\x{8EAB}\x{8EAC}\x{8EAF}\x{8EB0}\x{8EB1}' - . '\x{8EBE}\x{8EC5}\x{8EC6}\x{8EC8}\x{8ECA}\x{8ECB}\x{8ECC}\x{8ECD}\x{8ED2}' - . '\x{8EDB}\x{8EDF}\x{8EE2}\x{8EE3}\x{8EEB}\x{8EF8}\x{8EFB}\x{8EFC}\x{8EFD}' - . '\x{8EFE}\x{8F03}\x{8F05}\x{8F09}\x{8F0A}\x{8F0C}\x{8F12}\x{8F13}\x{8F14}' - . '\x{8F15}\x{8F19}\x{8F1B}\x{8F1C}\x{8F1D}\x{8F1F}\x{8F26}\x{8F29}\x{8F2A}' - . '\x{8F2F}\x{8F33}\x{8F38}\x{8F39}\x{8F3B}\x{8F3E}\x{8F3F}\x{8F42}\x{8F44}' - . '\x{8F45}\x{8F46}\x{8F49}\x{8F4C}\x{8F4D}\x{8F4E}\x{8F57}\x{8F5C}\x{8F5F}' - . '\x{8F61}\x{8F62}\x{8F63}\x{8F64}\x{8F9B}\x{8F9C}\x{8F9E}\x{8F9F}\x{8FA3}' - . '\x{8FA7}\x{8FA8}\x{8FAD}\x{8FAE}\x{8FAF}\x{8FB0}\x{8FB1}\x{8FB2}\x{8FB7}' - . '\x{8FBA}\x{8FBB}\x{8FBC}\x{8FBF}\x{8FC2}\x{8FC4}\x{8FC5}\x{8FCE}\x{8FD1}' - . '\x{8FD4}\x{8FDA}\x{8FE2}\x{8FE5}\x{8FE6}\x{8FE9}\x{8FEA}\x{8FEB}\x{8FED}' - . '\x{8FEF}\x{8FF0}\x{8FF4}\x{8FF7}\x{8FF8}\x{8FF9}\x{8FFA}\x{8FFD}\x{9000}' - . '\x{9001}\x{9003}\x{9005}\x{9006}\x{900B}\x{900D}\x{900E}\x{900F}\x{9010}' - . '\x{9011}\x{9013}\x{9014}\x{9015}\x{9016}\x{9017}\x{9019}\x{901A}\x{901D}' - . '\x{901E}\x{901F}\x{9020}\x{9021}\x{9022}\x{9023}\x{9027}\x{902E}\x{9031}' - . '\x{9032}\x{9035}\x{9036}\x{9038}\x{9039}\x{903C}\x{903E}\x{9041}\x{9042}' - . '\x{9045}\x{9047}\x{9049}\x{904A}\x{904B}\x{904D}\x{904E}\x{904F}\x{9050}' - . '\x{9051}\x{9052}\x{9053}\x{9054}\x{9055}\x{9056}\x{9058}\x{9059}\x{905C}' - . '\x{905E}\x{9060}\x{9061}\x{9063}\x{9065}\x{9068}\x{9069}\x{906D}\x{906E}' - . '\x{906F}\x{9072}\x{9075}\x{9076}\x{9077}\x{9078}\x{907A}\x{907C}\x{907D}' - . '\x{907F}\x{9080}\x{9081}\x{9082}\x{9083}\x{9084}\x{9087}\x{9089}\x{908A}' - . '\x{908F}\x{9091}\x{90A3}\x{90A6}\x{90A8}\x{90AA}\x{90AF}\x{90B1}\x{90B5}' - . '\x{90B8}\x{90C1}\x{90CA}\x{90CE}\x{90DB}\x{90E1}\x{90E2}\x{90E4}\x{90E8}' - . '\x{90ED}\x{90F5}\x{90F7}\x{90FD}\x{9102}\x{9112}\x{9119}\x{912D}\x{9130}' - . '\x{9132}\x{9149}\x{914A}\x{914B}\x{914C}\x{914D}\x{914E}\x{9152}\x{9154}' - . '\x{9156}\x{9158}\x{9162}\x{9163}\x{9165}\x{9169}\x{916A}\x{916C}\x{9172}' - . '\x{9173}\x{9175}\x{9177}\x{9178}\x{9182}\x{9187}\x{9189}\x{918B}\x{918D}' - . '\x{9190}\x{9192}\x{9197}\x{919C}\x{91A2}\x{91A4}\x{91AA}\x{91AB}\x{91AF}' - . '\x{91B4}\x{91B5}\x{91B8}\x{91BA}\x{91C0}\x{91C1}\x{91C6}\x{91C7}\x{91C8}' - . '\x{91C9}\x{91CB}\x{91CC}\x{91CD}\x{91CE}\x{91CF}\x{91D0}\x{91D1}\x{91D6}' - . '\x{91D8}\x{91DB}\x{91DC}\x{91DD}\x{91DF}\x{91E1}\x{91E3}\x{91E6}\x{91E7}' - . '\x{91F5}\x{91F6}\x{91FC}\x{91FF}\x{920D}\x{920E}\x{9211}\x{9214}\x{9215}' - . '\x{921E}\x{9229}\x{922C}\x{9234}\x{9237}\x{923F}\x{9244}\x{9245}\x{9248}' - . '\x{9249}\x{924B}\x{9250}\x{9257}\x{925A}\x{925B}\x{925E}\x{9262}\x{9264}' - . '\x{9266}\x{9271}\x{927E}\x{9280}\x{9283}\x{9285}\x{9291}\x{9293}\x{9295}' - . '\x{9296}\x{9298}\x{929A}\x{929B}\x{929C}\x{92AD}\x{92B7}\x{92B9}\x{92CF}' - . '\x{92D2}\x{92E4}\x{92E9}\x{92EA}\x{92ED}\x{92F2}\x{92F3}\x{92F8}\x{92FA}' - . '\x{92FC}\x{9306}\x{930F}\x{9310}\x{9318}\x{9319}\x{931A}\x{9320}\x{9322}' - . '\x{9323}\x{9326}\x{9328}\x{932B}\x{932C}\x{932E}\x{932F}\x{9332}\x{9335}' - . '\x{933A}\x{933B}\x{9344}\x{934B}\x{934D}\x{9354}\x{9356}\x{935B}\x{935C}' - . '\x{9360}\x{936C}\x{936E}\x{9375}\x{937C}\x{937E}\x{938C}\x{9394}\x{9396}' - . '\x{9397}\x{939A}\x{93A7}\x{93AC}\x{93AD}\x{93AE}\x{93B0}\x{93B9}\x{93C3}' - . '\x{93C8}\x{93D0}\x{93D1}\x{93D6}\x{93D7}\x{93D8}\x{93DD}\x{93E1}\x{93E4}' - . '\x{93E5}\x{93E8}\x{9403}\x{9407}\x{9410}\x{9413}\x{9414}\x{9418}\x{9419}' - . '\x{941A}\x{9421}\x{942B}\x{9435}\x{9436}\x{9438}\x{943A}\x{9441}\x{9444}' - . '\x{9451}\x{9452}\x{9453}\x{945A}\x{945B}\x{945E}\x{9460}\x{9462}\x{946A}' - . '\x{9470}\x{9475}\x{9477}\x{947C}\x{947D}\x{947E}\x{947F}\x{9481}\x{9577}' - . '\x{9580}\x{9582}\x{9583}\x{9587}\x{9589}\x{958A}\x{958B}\x{958F}\x{9591}' - . '\x{9593}\x{9594}\x{9596}\x{9598}\x{9599}\x{95A0}\x{95A2}\x{95A3}\x{95A4}' - . '\x{95A5}\x{95A7}\x{95A8}\x{95AD}\x{95B2}\x{95B9}\x{95BB}\x{95BC}\x{95BE}' - . '\x{95C3}\x{95C7}\x{95CA}\x{95CC}\x{95CD}\x{95D4}\x{95D5}\x{95D6}\x{95D8}' - . '\x{95DC}\x{95E1}\x{95E2}\x{95E5}\x{961C}\x{9621}\x{9628}\x{962A}\x{962E}' - . '\x{962F}\x{9632}\x{963B}\x{963F}\x{9640}\x{9642}\x{9644}\x{964B}\x{964C}' - . '\x{964D}\x{964F}\x{9650}\x{965B}\x{965C}\x{965D}\x{965E}\x{965F}\x{9662}' - . '\x{9663}\x{9664}\x{9665}\x{9666}\x{966A}\x{966C}\x{9670}\x{9672}\x{9673}' - . '\x{9675}\x{9676}\x{9677}\x{9678}\x{967A}\x{967D}\x{9685}\x{9686}\x{9688}' - . '\x{968A}\x{968B}\x{968D}\x{968E}\x{968F}\x{9694}\x{9695}\x{9697}\x{9698}' - . '\x{9699}\x{969B}\x{969C}\x{96A0}\x{96A3}\x{96A7}\x{96A8}\x{96AA}\x{96B0}' - . '\x{96B1}\x{96B2}\x{96B4}\x{96B6}\x{96B7}\x{96B8}\x{96B9}\x{96BB}\x{96BC}' - . '\x{96C0}\x{96C1}\x{96C4}\x{96C5}\x{96C6}\x{96C7}\x{96C9}\x{96CB}\x{96CC}' - . '\x{96CD}\x{96CE}\x{96D1}\x{96D5}\x{96D6}\x{96D9}\x{96DB}\x{96DC}\x{96E2}' - . '\x{96E3}\x{96E8}\x{96EA}\x{96EB}\x{96F0}\x{96F2}\x{96F6}\x{96F7}\x{96F9}' - . '\x{96FB}\x{9700}\x{9704}\x{9706}\x{9707}\x{9708}\x{970A}\x{970D}\x{970E}' - . '\x{970F}\x{9711}\x{9713}\x{9716}\x{9719}\x{971C}\x{971E}\x{9724}\x{9727}' - . '\x{972A}\x{9730}\x{9732}\x{9738}\x{9739}\x{973D}\x{973E}\x{9742}\x{9744}' - . '\x{9746}\x{9748}\x{9749}\x{9752}\x{9756}\x{9759}\x{975C}\x{975E}\x{9760}' - . '\x{9761}\x{9762}\x{9764}\x{9766}\x{9768}\x{9769}\x{976B}\x{976D}\x{9771}' - . '\x{9774}\x{9779}\x{977A}\x{977C}\x{9781}\x{9784}\x{9785}\x{9786}\x{978B}' - . '\x{978D}\x{978F}\x{9790}\x{9798}\x{979C}\x{97A0}\x{97A3}\x{97A6}\x{97A8}' - . '\x{97AB}\x{97AD}\x{97B3}\x{97B4}\x{97C3}\x{97C6}\x{97C8}\x{97CB}\x{97D3}' - . '\x{97DC}\x{97ED}\x{97EE}\x{97F2}\x{97F3}\x{97F5}\x{97F6}\x{97FB}\x{97FF}' - . '\x{9801}\x{9802}\x{9803}\x{9805}\x{9806}\x{9808}\x{980C}\x{980F}\x{9810}' - . '\x{9811}\x{9812}\x{9813}\x{9817}\x{9818}\x{981A}\x{9821}\x{9824}\x{982C}' - . '\x{982D}\x{9834}\x{9837}\x{9838}\x{983B}\x{983C}\x{983D}\x{9846}\x{984B}' - . '\x{984C}\x{984D}\x{984E}\x{984F}\x{9854}\x{9855}\x{9858}\x{985B}\x{985E}' - . '\x{9867}\x{986B}\x{986F}\x{9870}\x{9871}\x{9873}\x{9874}\x{98A8}\x{98AA}' - . '\x{98AF}\x{98B1}\x{98B6}\x{98C3}\x{98C4}\x{98C6}\x{98DB}\x{98DC}\x{98DF}' - . '\x{98E2}\x{98E9}\x{98EB}\x{98ED}\x{98EE}\x{98EF}\x{98F2}\x{98F4}\x{98FC}' - . '\x{98FD}\x{98FE}\x{9903}\x{9905}\x{9909}\x{990A}\x{990C}\x{9910}\x{9912}' - . '\x{9913}\x{9914}\x{9918}\x{991D}\x{991E}\x{9920}\x{9921}\x{9924}\x{9928}' - . '\x{992C}\x{992E}\x{993D}\x{993E}\x{9942}\x{9945}\x{9949}\x{994B}\x{994C}' - . '\x{9950}\x{9951}\x{9952}\x{9955}\x{9957}\x{9996}\x{9997}\x{9998}\x{9999}' - . '\x{99A5}\x{99A8}\x{99AC}\x{99AD}\x{99AE}\x{99B3}\x{99B4}\x{99BC}\x{99C1}' - . '\x{99C4}\x{99C5}\x{99C6}\x{99C8}\x{99D0}\x{99D1}\x{99D2}\x{99D5}\x{99D8}' - . '\x{99DB}\x{99DD}\x{99DF}\x{99E2}\x{99ED}\x{99EE}\x{99F1}\x{99F2}\x{99F8}' - . '\x{99FB}\x{99FF}\x{9A01}\x{9A05}\x{9A0E}\x{9A0F}\x{9A12}\x{9A13}\x{9A19}' - . '\x{9A28}\x{9A2B}\x{9A30}\x{9A37}\x{9A3E}\x{9A40}\x{9A42}\x{9A43}\x{9A45}' - . '\x{9A4D}\x{9A55}\x{9A57}\x{9A5A}\x{9A5B}\x{9A5F}\x{9A62}\x{9A64}\x{9A65}' - . '\x{9A69}\x{9A6A}\x{9A6B}\x{9AA8}\x{9AAD}\x{9AB0}\x{9AB8}\x{9ABC}\x{9AC0}' - . '\x{9AC4}\x{9ACF}\x{9AD1}\x{9AD3}\x{9AD4}\x{9AD8}\x{9ADE}\x{9ADF}\x{9AE2}' - . '\x{9AE3}\x{9AE6}\x{9AEA}\x{9AEB}\x{9AED}\x{9AEE}\x{9AEF}\x{9AF1}\x{9AF4}' - . '\x{9AF7}\x{9AFB}\x{9B06}\x{9B18}\x{9B1A}\x{9B1F}\x{9B22}\x{9B23}\x{9B25}' - . '\x{9B27}\x{9B28}\x{9B29}\x{9B2A}\x{9B2E}\x{9B2F}\x{9B31}\x{9B32}\x{9B3B}' - . '\x{9B3C}\x{9B41}\x{9B42}\x{9B43}\x{9B44}\x{9B45}\x{9B4D}\x{9B4E}\x{9B4F}' - . '\x{9B51}\x{9B54}\x{9B58}\x{9B5A}\x{9B6F}\x{9B74}\x{9B83}\x{9B8E}\x{9B91}' - . '\x{9B92}\x{9B93}\x{9B96}\x{9B97}\x{9B9F}\x{9BA0}\x{9BA8}\x{9BAA}\x{9BAB}' - . '\x{9BAD}\x{9BAE}\x{9BB4}\x{9BB9}\x{9BC0}\x{9BC6}\x{9BC9}\x{9BCA}\x{9BCF}' - . '\x{9BD1}\x{9BD2}\x{9BD4}\x{9BD6}\x{9BDB}\x{9BE1}\x{9BE2}\x{9BE3}\x{9BE4}' - . '\x{9BE8}\x{9BF0}\x{9BF1}\x{9BF2}\x{9BF5}\x{9C04}\x{9C06}\x{9C08}\x{9C09}' - . '\x{9C0A}\x{9C0C}\x{9C0D}\x{9C10}\x{9C12}\x{9C13}\x{9C14}\x{9C15}\x{9C1B}' - . '\x{9C21}\x{9C24}\x{9C25}\x{9C2D}\x{9C2E}\x{9C2F}\x{9C30}\x{9C32}\x{9C39}' - . '\x{9C3A}\x{9C3B}\x{9C3E}\x{9C46}\x{9C47}\x{9C48}\x{9C52}\x{9C57}\x{9C5A}' - . '\x{9C60}\x{9C67}\x{9C76}\x{9C78}\x{9CE5}\x{9CE7}\x{9CE9}\x{9CEB}\x{9CEC}' - . '\x{9CF0}\x{9CF3}\x{9CF4}\x{9CF6}\x{9D03}\x{9D06}\x{9D07}\x{9D08}\x{9D09}' - . '\x{9D0E}\x{9D12}\x{9D15}\x{9D1B}\x{9D1F}\x{9D23}\x{9D26}\x{9D28}\x{9D2A}' - . '\x{9D2B}\x{9D2C}\x{9D3B}\x{9D3E}\x{9D3F}\x{9D41}\x{9D44}\x{9D46}\x{9D48}' - . '\x{9D50}\x{9D51}\x{9D59}\x{9D5C}\x{9D5D}\x{9D5E}\x{9D60}\x{9D61}\x{9D64}' - . '\x{9D6C}\x{9D6F}\x{9D72}\x{9D7A}\x{9D87}\x{9D89}\x{9D8F}\x{9D9A}\x{9DA4}' - . '\x{9DA9}\x{9DAB}\x{9DAF}\x{9DB2}\x{9DB4}\x{9DB8}\x{9DBA}\x{9DBB}\x{9DC1}' - . '\x{9DC2}\x{9DC4}\x{9DC6}\x{9DCF}\x{9DD3}\x{9DD9}\x{9DE6}\x{9DED}\x{9DEF}' - . '\x{9DF2}\x{9DF8}\x{9DF9}\x{9DFA}\x{9DFD}\x{9E1A}\x{9E1B}\x{9E1E}\x{9E75}' - . '\x{9E78}\x{9E79}\x{9E7D}\x{9E7F}\x{9E81}\x{9E88}\x{9E8B}\x{9E8C}\x{9E91}' - . '\x{9E92}\x{9E93}\x{9E95}\x{9E97}\x{9E9D}\x{9E9F}\x{9EA5}\x{9EA6}\x{9EA9}' - . '\x{9EAA}\x{9EAD}\x{9EB8}\x{9EB9}\x{9EBA}\x{9EBB}\x{9EBC}\x{9EBE}\x{9EBF}' - . '\x{9EC4}\x{9ECC}\x{9ECD}\x{9ECE}\x{9ECF}\x{9ED0}\x{9ED2}\x{9ED4}\x{9ED8}' - . '\x{9ED9}\x{9EDB}\x{9EDC}\x{9EDD}\x{9EDE}\x{9EE0}\x{9EE5}\x{9EE8}\x{9EEF}' - . '\x{9EF4}\x{9EF6}\x{9EF7}\x{9EF9}\x{9EFB}\x{9EFC}\x{9EFD}\x{9F07}\x{9F08}' - . '\x{9F0E}\x{9F13}\x{9F15}\x{9F20}\x{9F21}\x{9F2C}\x{9F3B}\x{9F3E}\x{9F4A}' - . '\x{9F4B}\x{9F4E}\x{9F4F}\x{9F52}\x{9F54}\x{9F5F}\x{9F60}\x{9F61}\x{9F62}' - . '\x{9F63}\x{9F66}\x{9F67}\x{9F6A}\x{9F6C}\x{9F72}\x{9F76}\x{9F77}\x{9F8D}' - . '\x{9F95}\x{9F9C}\x{9F9D}\x{9FA0}]{1,15}$/iu', - 12 => '/^[\x{002d}0-9a-z\x{3447}\x{3473}\x{359E}\x{360E}\x{361A}\x{3918}\x{396E}\x{39CF}\x{39D0}' - . '\x{39DF}\x{3A73}\x{3B4E}\x{3C6E}\x{3CE0}\x{4056}\x{415F}\x{4337}\x{43AC}' - . '\x{43B1}\x{43DD}\x{44D6}\x{464C}\x{4661}\x{4723}\x{4729}\x{477C}\x{478D}' - . '\x{4947}\x{497A}\x{497D}\x{4982}\x{4983}\x{4985}\x{4986}\x{499B}\x{499F}' - . '\x{49B6}\x{49B7}\x{4C77}\x{4C9F}\x{4CA0}\x{4CA1}\x{4CA2}\x{4CA3}\x{4D13}' - . '\x{4D14}\x{4D15}\x{4D16}\x{4D17}\x{4D18}\x{4D19}\x{4DAE}\x{4E00}\x{4E01}' - . '\x{4E02}\x{4E03}\x{4E04}\x{4E05}\x{4E06}\x{4E07}\x{4E08}\x{4E09}\x{4E0A}' - . '\x{4E0B}\x{4E0C}\x{4E0D}\x{4E0E}\x{4E0F}\x{4E10}\x{4E11}\x{4E13}\x{4E14}' - . '\x{4E15}\x{4E16}\x{4E17}\x{4E18}\x{4E19}\x{4E1A}\x{4E1B}\x{4E1C}\x{4E1D}' - . '\x{4E1E}\x{4E1F}\x{4E20}\x{4E21}\x{4E22}\x{4E23}\x{4E24}\x{4E25}\x{4E26}' - . '\x{4E27}\x{4E28}\x{4E2A}\x{4E2B}\x{4E2C}\x{4E2D}\x{4E2E}\x{4E2F}\x{4E30}' - . '\x{4E31}\x{4E32}\x{4E33}\x{4E34}\x{4E35}\x{4E36}\x{4E37}\x{4E38}\x{4E39}' - . '\x{4E3A}\x{4E3B}\x{4E3C}\x{4E3D}\x{4E3E}\x{4E3F}\x{4E40}\x{4E41}\x{4E42}' - . '\x{4E43}\x{4E44}\x{4E45}\x{4E46}\x{4E47}\x{4E48}\x{4E49}\x{4E4A}\x{4E4B}' - . '\x{4E4C}\x{4E4D}\x{4E4E}\x{4E4F}\x{4E50}\x{4E51}\x{4E52}\x{4E53}\x{4E54}' - . '\x{4E56}\x{4E57}\x{4E58}\x{4E59}\x{4E5A}\x{4E5B}\x{4E5C}\x{4E5D}\x{4E5E}' - . '\x{4E5F}\x{4E60}\x{4E61}\x{4E62}\x{4E63}\x{4E64}\x{4E65}\x{4E66}\x{4E67}' - . '\x{4E69}\x{4E6A}\x{4E6B}\x{4E6C}\x{4E6D}\x{4E6E}\x{4E6F}\x{4E70}\x{4E71}' - . '\x{4E72}\x{4E73}\x{4E74}\x{4E75}\x{4E76}\x{4E77}\x{4E78}\x{4E7A}\x{4E7B}' - . '\x{4E7C}\x{4E7D}\x{4E7E}\x{4E7F}\x{4E80}\x{4E81}\x{4E82}\x{4E83}\x{4E84}' - . '\x{4E85}\x{4E86}\x{4E87}\x{4E88}\x{4E89}\x{4E8B}\x{4E8C}\x{4E8D}\x{4E8E}' - . '\x{4E8F}\x{4E90}\x{4E91}\x{4E92}\x{4E93}\x{4E94}\x{4E95}\x{4E97}\x{4E98}' - . '\x{4E99}\x{4E9A}\x{4E9B}\x{4E9C}\x{4E9D}\x{4E9E}\x{4E9F}\x{4EA0}\x{4EA1}' - . '\x{4EA2}\x{4EA4}\x{4EA5}\x{4EA6}\x{4EA7}\x{4EA8}\x{4EA9}\x{4EAA}\x{4EAB}' - . '\x{4EAC}\x{4EAD}\x{4EAE}\x{4EAF}\x{4EB0}\x{4EB1}\x{4EB2}\x{4EB3}\x{4EB4}' - . '\x{4EB5}\x{4EB6}\x{4EB7}\x{4EB8}\x{4EB9}\x{4EBA}\x{4EBB}\x{4EBD}\x{4EBE}' - . '\x{4EBF}\x{4EC0}\x{4EC1}\x{4EC2}\x{4EC3}\x{4EC4}\x{4EC5}\x{4EC6}\x{4EC7}' - . '\x{4EC8}\x{4EC9}\x{4ECA}\x{4ECB}\x{4ECD}\x{4ECE}\x{4ECF}\x{4ED0}\x{4ED1}' - . '\x{4ED2}\x{4ED3}\x{4ED4}\x{4ED5}\x{4ED6}\x{4ED7}\x{4ED8}\x{4ED9}\x{4EDA}' - . '\x{4EDB}\x{4EDC}\x{4EDD}\x{4EDE}\x{4EDF}\x{4EE0}\x{4EE1}\x{4EE2}\x{4EE3}' - . '\x{4EE4}\x{4EE5}\x{4EE6}\x{4EE8}\x{4EE9}\x{4EEA}\x{4EEB}\x{4EEC}\x{4EEF}' - . '\x{4EF0}\x{4EF1}\x{4EF2}\x{4EF3}\x{4EF4}\x{4EF5}\x{4EF6}\x{4EF7}\x{4EFB}' - . '\x{4EFD}\x{4EFF}\x{4F00}\x{4F01}\x{4F02}\x{4F03}\x{4F04}\x{4F05}\x{4F06}' - . '\x{4F08}\x{4F09}\x{4F0A}\x{4F0B}\x{4F0C}\x{4F0D}\x{4F0E}\x{4F0F}\x{4F10}' - . '\x{4F11}\x{4F12}\x{4F13}\x{4F14}\x{4F15}\x{4F17}\x{4F18}\x{4F19}\x{4F1A}' - . '\x{4F1B}\x{4F1C}\x{4F1D}\x{4F1E}\x{4F1F}\x{4F20}\x{4F21}\x{4F22}\x{4F23}' - . '\x{4F24}\x{4F25}\x{4F26}\x{4F27}\x{4F29}\x{4F2A}\x{4F2B}\x{4F2C}\x{4F2D}' - . '\x{4F2E}\x{4F2F}\x{4F30}\x{4F32}\x{4F33}\x{4F34}\x{4F36}\x{4F38}\x{4F39}' - . '\x{4F3A}\x{4F3B}\x{4F3C}\x{4F3D}\x{4F3E}\x{4F3F}\x{4F41}\x{4F42}\x{4F43}' - . '\x{4F45}\x{4F46}\x{4F47}\x{4F48}\x{4F49}\x{4F4A}\x{4F4B}\x{4F4C}\x{4F4D}' - . '\x{4F4E}\x{4F4F}\x{4F50}\x{4F51}\x{4F52}\x{4F53}\x{4F54}\x{4F55}\x{4F56}' - . '\x{4F57}\x{4F58}\x{4F59}\x{4F5A}\x{4F5B}\x{4F5C}\x{4F5D}\x{4F5E}\x{4F5F}' - . '\x{4F60}\x{4F61}\x{4F62}\x{4F63}\x{4F64}\x{4F65}\x{4F66}\x{4F67}\x{4F68}' - . '\x{4F69}\x{4F6A}\x{4F6B}\x{4F6C}\x{4F6D}\x{4F6E}\x{4F6F}\x{4F70}\x{4F72}' - . '\x{4F73}\x{4F74}\x{4F75}\x{4F76}\x{4F77}\x{4F78}\x{4F79}\x{4F7A}\x{4F7B}' - . '\x{4F7C}\x{4F7D}\x{4F7E}\x{4F7F}\x{4F80}\x{4F81}\x{4F82}\x{4F83}\x{4F84}' - . '\x{4F85}\x{4F86}\x{4F87}\x{4F88}\x{4F89}\x{4F8A}\x{4F8B}\x{4F8D}\x{4F8F}' - . '\x{4F90}\x{4F91}\x{4F92}\x{4F93}\x{4F94}\x{4F95}\x{4F96}\x{4F97}\x{4F98}' - . '\x{4F99}\x{4F9A}\x{4F9B}\x{4F9C}\x{4F9D}\x{4F9E}\x{4F9F}\x{4FA0}\x{4FA1}' - . '\x{4FA3}\x{4FA4}\x{4FA5}\x{4FA6}\x{4FA7}\x{4FA8}\x{4FA9}\x{4FAA}\x{4FAB}' - . '\x{4FAC}\x{4FAE}\x{4FAF}\x{4FB0}\x{4FB1}\x{4FB2}\x{4FB3}\x{4FB4}\x{4FB5}' - . '\x{4FB6}\x{4FB7}\x{4FB8}\x{4FB9}\x{4FBA}\x{4FBB}\x{4FBC}\x{4FBE}\x{4FBF}' - . '\x{4FC0}\x{4FC1}\x{4FC2}\x{4FC3}\x{4FC4}\x{4FC5}\x{4FC7}\x{4FC9}\x{4FCA}' - . '\x{4FCB}\x{4FCD}\x{4FCE}\x{4FCF}\x{4FD0}\x{4FD1}\x{4FD2}\x{4FD3}\x{4FD4}' - . '\x{4FD5}\x{4FD6}\x{4FD7}\x{4FD8}\x{4FD9}\x{4FDA}\x{4FDB}\x{4FDC}\x{4FDD}' - . '\x{4FDE}\x{4FDF}\x{4FE0}\x{4FE1}\x{4FE3}\x{4FE4}\x{4FE5}\x{4FE6}\x{4FE7}' - . '\x{4FE8}\x{4FE9}\x{4FEA}\x{4FEB}\x{4FEC}\x{4FED}\x{4FEE}\x{4FEF}\x{4FF0}' - . '\x{4FF1}\x{4FF2}\x{4FF3}\x{4FF4}\x{4FF5}\x{4FF6}\x{4FF7}\x{4FF8}\x{4FF9}' - . '\x{4FFA}\x{4FFB}\x{4FFE}\x{4FFF}\x{5000}\x{5001}\x{5002}\x{5003}\x{5004}' - . '\x{5005}\x{5006}\x{5007}\x{5008}\x{5009}\x{500A}\x{500B}\x{500C}\x{500D}' - . '\x{500E}\x{500F}\x{5011}\x{5012}\x{5013}\x{5014}\x{5015}\x{5016}\x{5017}' - . '\x{5018}\x{5019}\x{501A}\x{501B}\x{501C}\x{501D}\x{501E}\x{501F}\x{5020}' - . '\x{5021}\x{5022}\x{5023}\x{5024}\x{5025}\x{5026}\x{5027}\x{5028}\x{5029}' - . '\x{502A}\x{502B}\x{502C}\x{502D}\x{502E}\x{502F}\x{5030}\x{5031}\x{5032}' - . '\x{5033}\x{5035}\x{5036}\x{5037}\x{5039}\x{503A}\x{503B}\x{503C}\x{503E}' - . '\x{503F}\x{5040}\x{5041}\x{5043}\x{5044}\x{5045}\x{5046}\x{5047}\x{5048}' - . '\x{5049}\x{504A}\x{504B}\x{504C}\x{504D}\x{504E}\x{504F}\x{5051}\x{5053}' - . '\x{5054}\x{5055}\x{5056}\x{5057}\x{5059}\x{505A}\x{505B}\x{505C}\x{505D}' - . '\x{505E}\x{505F}\x{5060}\x{5061}\x{5062}\x{5063}\x{5064}\x{5065}\x{5066}' - . '\x{5067}\x{5068}\x{5069}\x{506A}\x{506B}\x{506C}\x{506D}\x{506E}\x{506F}' - . '\x{5070}\x{5071}\x{5072}\x{5073}\x{5074}\x{5075}\x{5076}\x{5077}\x{5078}' - . '\x{5079}\x{507A}\x{507B}\x{507D}\x{507E}\x{507F}\x{5080}\x{5082}\x{5083}' - . '\x{5084}\x{5085}\x{5086}\x{5087}\x{5088}\x{5089}\x{508A}\x{508B}\x{508C}' - . '\x{508D}\x{508E}\x{508F}\x{5090}\x{5091}\x{5092}\x{5094}\x{5095}\x{5096}' - . '\x{5098}\x{5099}\x{509A}\x{509B}\x{509C}\x{509D}\x{509E}\x{50A2}\x{50A3}' - . '\x{50A4}\x{50A5}\x{50A6}\x{50A7}\x{50A8}\x{50A9}\x{50AA}\x{50AB}\x{50AC}' - . '\x{50AD}\x{50AE}\x{50AF}\x{50B0}\x{50B1}\x{50B2}\x{50B3}\x{50B4}\x{50B5}' - . '\x{50B6}\x{50B7}\x{50B8}\x{50BA}\x{50BB}\x{50BC}\x{50BD}\x{50BE}\x{50BF}' - . '\x{50C0}\x{50C1}\x{50C2}\x{50C4}\x{50C5}\x{50C6}\x{50C7}\x{50C8}\x{50C9}' - . '\x{50CA}\x{50CB}\x{50CC}\x{50CD}\x{50CE}\x{50CF}\x{50D0}\x{50D1}\x{50D2}' - . '\x{50D3}\x{50D4}\x{50D5}\x{50D6}\x{50D7}\x{50D9}\x{50DA}\x{50DB}\x{50DC}' - . '\x{50DD}\x{50DE}\x{50E0}\x{50E3}\x{50E4}\x{50E5}\x{50E6}\x{50E7}\x{50E8}' - . '\x{50E9}\x{50EA}\x{50EC}\x{50ED}\x{50EE}\x{50EF}\x{50F0}\x{50F1}\x{50F2}' - . '\x{50F3}\x{50F5}\x{50F6}\x{50F8}\x{50F9}\x{50FA}\x{50FB}\x{50FC}\x{50FD}' - . '\x{50FE}\x{50FF}\x{5100}\x{5101}\x{5102}\x{5103}\x{5104}\x{5105}\x{5106}' - . '\x{5107}\x{5108}\x{5109}\x{510A}\x{510B}\x{510C}\x{510D}\x{510E}\x{510F}' - . '\x{5110}\x{5111}\x{5112}\x{5113}\x{5114}\x{5115}\x{5116}\x{5117}\x{5118}' - . '\x{5119}\x{511A}\x{511C}\x{511D}\x{511E}\x{511F}\x{5120}\x{5121}\x{5122}' - . '\x{5123}\x{5124}\x{5125}\x{5126}\x{5127}\x{5129}\x{512A}\x{512C}\x{512D}' - . '\x{512E}\x{512F}\x{5130}\x{5131}\x{5132}\x{5133}\x{5134}\x{5135}\x{5136}' - . '\x{5137}\x{5138}\x{5139}\x{513A}\x{513B}\x{513C}\x{513D}\x{513E}\x{513F}' - . '\x{5140}\x{5141}\x{5143}\x{5144}\x{5145}\x{5146}\x{5147}\x{5148}\x{5149}' - . '\x{514B}\x{514C}\x{514D}\x{514E}\x{5150}\x{5151}\x{5152}\x{5154}\x{5155}' - . '\x{5156}\x{5157}\x{5159}\x{515A}\x{515B}\x{515C}\x{515D}\x{515E}\x{515F}' - . '\x{5161}\x{5162}\x{5163}\x{5165}\x{5166}\x{5167}\x{5168}\x{5169}\x{516A}' - . '\x{516B}\x{516C}\x{516D}\x{516E}\x{516F}\x{5170}\x{5171}\x{5173}\x{5174}' - . '\x{5175}\x{5176}\x{5177}\x{5178}\x{5179}\x{517A}\x{517B}\x{517C}\x{517D}' - . '\x{517F}\x{5180}\x{5181}\x{5182}\x{5185}\x{5186}\x{5187}\x{5188}\x{5189}' - . '\x{518A}\x{518B}\x{518C}\x{518D}\x{518F}\x{5190}\x{5191}\x{5192}\x{5193}' - . '\x{5194}\x{5195}\x{5196}\x{5197}\x{5198}\x{5199}\x{519A}\x{519B}\x{519C}' - . '\x{519D}\x{519E}\x{519F}\x{51A0}\x{51A2}\x{51A4}\x{51A5}\x{51A6}\x{51A7}' - . '\x{51A8}\x{51AA}\x{51AB}\x{51AC}\x{51AE}\x{51AF}\x{51B0}\x{51B1}\x{51B2}' - . '\x{51B3}\x{51B5}\x{51B6}\x{51B7}\x{51B9}\x{51BB}\x{51BC}\x{51BD}\x{51BE}' - . '\x{51BF}\x{51C0}\x{51C1}\x{51C3}\x{51C4}\x{51C5}\x{51C6}\x{51C7}\x{51C8}' - . '\x{51C9}\x{51CA}\x{51CB}\x{51CC}\x{51CD}\x{51CE}\x{51CF}\x{51D0}\x{51D1}' - . '\x{51D4}\x{51D5}\x{51D6}\x{51D7}\x{51D8}\x{51D9}\x{51DA}\x{51DB}\x{51DC}' - . '\x{51DD}\x{51DE}\x{51E0}\x{51E1}\x{51E2}\x{51E3}\x{51E4}\x{51E5}\x{51E7}' - . '\x{51E8}\x{51E9}\x{51EA}\x{51EB}\x{51ED}\x{51EF}\x{51F0}\x{51F1}\x{51F3}' - . '\x{51F4}\x{51F5}\x{51F6}\x{51F7}\x{51F8}\x{51F9}\x{51FA}\x{51FB}\x{51FC}' - . '\x{51FD}\x{51FE}\x{51FF}\x{5200}\x{5201}\x{5202}\x{5203}\x{5204}\x{5205}' - . '\x{5206}\x{5207}\x{5208}\x{5209}\x{520A}\x{520B}\x{520C}\x{520D}\x{520E}' - . '\x{520F}\x{5210}\x{5211}\x{5212}\x{5213}\x{5214}\x{5215}\x{5216}\x{5217}' - . '\x{5218}\x{5219}\x{521A}\x{521B}\x{521C}\x{521D}\x{521E}\x{521F}\x{5220}' - . '\x{5221}\x{5222}\x{5223}\x{5224}\x{5225}\x{5226}\x{5228}\x{5229}\x{522A}' - . '\x{522B}\x{522C}\x{522D}\x{522E}\x{522F}\x{5230}\x{5231}\x{5232}\x{5233}' - . '\x{5234}\x{5235}\x{5236}\x{5237}\x{5238}\x{5239}\x{523A}\x{523B}\x{523C}' - . '\x{523D}\x{523E}\x{523F}\x{5240}\x{5241}\x{5242}\x{5243}\x{5244}\x{5245}' - . '\x{5246}\x{5247}\x{5248}\x{5249}\x{524A}\x{524B}\x{524C}\x{524D}\x{524E}' - . '\x{5250}\x{5251}\x{5252}\x{5254}\x{5255}\x{5256}\x{5257}\x{5258}\x{5259}' - . '\x{525A}\x{525B}\x{525C}\x{525D}\x{525E}\x{525F}\x{5260}\x{5261}\x{5262}' - . '\x{5263}\x{5264}\x{5265}\x{5267}\x{5268}\x{5269}\x{526A}\x{526B}\x{526C}' - . '\x{526D}\x{526E}\x{526F}\x{5270}\x{5272}\x{5273}\x{5274}\x{5275}\x{5276}' - . '\x{5277}\x{5278}\x{527A}\x{527B}\x{527C}\x{527D}\x{527E}\x{527F}\x{5280}' - . '\x{5281}\x{5282}\x{5283}\x{5284}\x{5286}\x{5287}\x{5288}\x{5289}\x{528A}' - . '\x{528B}\x{528C}\x{528D}\x{528F}\x{5290}\x{5291}\x{5292}\x{5293}\x{5294}' - . '\x{5295}\x{5296}\x{5297}\x{5298}\x{5299}\x{529A}\x{529B}\x{529C}\x{529D}' - . '\x{529E}\x{529F}\x{52A0}\x{52A1}\x{52A2}\x{52A3}\x{52A5}\x{52A6}\x{52A7}' - . '\x{52A8}\x{52A9}\x{52AA}\x{52AB}\x{52AC}\x{52AD}\x{52AE}\x{52AF}\x{52B0}' - . '\x{52B1}\x{52B2}\x{52B3}\x{52B4}\x{52B5}\x{52B6}\x{52B7}\x{52B8}\x{52B9}' - . '\x{52BA}\x{52BB}\x{52BC}\x{52BD}\x{52BE}\x{52BF}\x{52C0}\x{52C1}\x{52C2}' - . '\x{52C3}\x{52C6}\x{52C7}\x{52C9}\x{52CA}\x{52CB}\x{52CD}\x{52CF}\x{52D0}' - . '\x{52D2}\x{52D3}\x{52D5}\x{52D6}\x{52D7}\x{52D8}\x{52D9}\x{52DA}\x{52DB}' - . '\x{52DC}\x{52DD}\x{52DE}\x{52DF}\x{52E0}\x{52E2}\x{52E3}\x{52E4}\x{52E6}' - . '\x{52E7}\x{52E8}\x{52E9}\x{52EA}\x{52EB}\x{52EC}\x{52ED}\x{52EF}\x{52F0}' - . '\x{52F1}\x{52F2}\x{52F3}\x{52F4}\x{52F5}\x{52F6}\x{52F7}\x{52F8}\x{52F9}' - . '\x{52FA}\x{52FB}\x{52FC}\x{52FD}\x{52FE}\x{52FF}\x{5300}\x{5301}\x{5302}' - . '\x{5305}\x{5306}\x{5307}\x{5308}\x{5309}\x{530A}\x{530B}\x{530C}\x{530D}' - . '\x{530E}\x{530F}\x{5310}\x{5311}\x{5312}\x{5313}\x{5314}\x{5315}\x{5316}' - . '\x{5317}\x{5319}\x{531A}\x{531C}\x{531D}\x{531F}\x{5320}\x{5321}\x{5322}' - . '\x{5323}\x{5324}\x{5325}\x{5326}\x{5328}\x{532A}\x{532B}\x{532C}\x{532D}' - . '\x{532E}\x{532F}\x{5330}\x{5331}\x{5333}\x{5334}\x{5337}\x{5339}\x{533A}' - . '\x{533B}\x{533C}\x{533D}\x{533E}\x{533F}\x{5340}\x{5341}\x{5343}\x{5344}' - . '\x{5345}\x{5346}\x{5347}\x{5348}\x{5349}\x{534A}\x{534B}\x{534C}\x{534D}' - . '\x{534E}\x{534F}\x{5350}\x{5351}\x{5352}\x{5353}\x{5354}\x{5355}\x{5356}' - . '\x{5357}\x{5358}\x{5359}\x{535A}\x{535C}\x{535E}\x{535F}\x{5360}\x{5361}' - . '\x{5362}\x{5363}\x{5364}\x{5365}\x{5366}\x{5367}\x{5369}\x{536B}\x{536C}' - . '\x{536E}\x{536F}\x{5370}\x{5371}\x{5372}\x{5373}\x{5374}\x{5375}\x{5376}' - . '\x{5377}\x{5378}\x{5379}\x{537A}\x{537B}\x{537C}\x{537D}\x{537E}\x{537F}' - . '\x{5381}\x{5382}\x{5383}\x{5384}\x{5385}\x{5386}\x{5387}\x{5388}\x{5389}' - . '\x{538A}\x{538B}\x{538C}\x{538D}\x{538E}\x{538F}\x{5390}\x{5391}\x{5392}' - . '\x{5393}\x{5394}\x{5395}\x{5396}\x{5397}\x{5398}\x{5399}\x{539A}\x{539B}' - . '\x{539C}\x{539D}\x{539E}\x{539F}\x{53A0}\x{53A2}\x{53A3}\x{53A4}\x{53A5}' - . '\x{53A6}\x{53A7}\x{53A8}\x{53A9}\x{53AC}\x{53AD}\x{53AE}\x{53B0}\x{53B1}' - . '\x{53B2}\x{53B3}\x{53B4}\x{53B5}\x{53B6}\x{53B7}\x{53B8}\x{53B9}\x{53BB}' - . '\x{53BC}\x{53BD}\x{53BE}\x{53BF}\x{53C0}\x{53C1}\x{53C2}\x{53C3}\x{53C4}' - . '\x{53C6}\x{53C7}\x{53C8}\x{53C9}\x{53CA}\x{53CB}\x{53CC}\x{53CD}\x{53CE}' - . '\x{53D0}\x{53D1}\x{53D2}\x{53D3}\x{53D4}\x{53D5}\x{53D6}\x{53D7}\x{53D8}' - . '\x{53D9}\x{53DB}\x{53DC}\x{53DF}\x{53E0}\x{53E1}\x{53E2}\x{53E3}\x{53E4}' - . '\x{53E5}\x{53E6}\x{53E8}\x{53E9}\x{53EA}\x{53EB}\x{53EC}\x{53ED}\x{53EE}' - . '\x{53EF}\x{53F0}\x{53F1}\x{53F2}\x{53F3}\x{53F4}\x{53F5}\x{53F6}\x{53F7}' - . '\x{53F8}\x{53F9}\x{53FA}\x{53FB}\x{53FC}\x{53FD}\x{53FE}\x{5401}\x{5402}' - . '\x{5403}\x{5404}\x{5405}\x{5406}\x{5407}\x{5408}\x{5409}\x{540A}\x{540B}' - . '\x{540C}\x{540D}\x{540E}\x{540F}\x{5410}\x{5411}\x{5412}\x{5413}\x{5414}' - . '\x{5415}\x{5416}\x{5417}\x{5418}\x{5419}\x{541B}\x{541C}\x{541D}\x{541E}' - . '\x{541F}\x{5420}\x{5421}\x{5423}\x{5424}\x{5425}\x{5426}\x{5427}\x{5428}' - . '\x{5429}\x{542A}\x{542B}\x{542C}\x{542D}\x{542E}\x{542F}\x{5430}\x{5431}' - . '\x{5432}\x{5433}\x{5434}\x{5435}\x{5436}\x{5437}\x{5438}\x{5439}\x{543A}' - . '\x{543B}\x{543C}\x{543D}\x{543E}\x{543F}\x{5440}\x{5441}\x{5442}\x{5443}' - . '\x{5444}\x{5445}\x{5446}\x{5447}\x{5448}\x{5449}\x{544A}\x{544B}\x{544D}' - . '\x{544E}\x{544F}\x{5450}\x{5451}\x{5452}\x{5453}\x{5454}\x{5455}\x{5456}' - . '\x{5457}\x{5458}\x{5459}\x{545A}\x{545B}\x{545C}\x{545E}\x{545F}\x{5460}' - . '\x{5461}\x{5462}\x{5463}\x{5464}\x{5465}\x{5466}\x{5467}\x{5468}\x{546A}' - . '\x{546B}\x{546C}\x{546D}\x{546E}\x{546F}\x{5470}\x{5471}\x{5472}\x{5473}' - . '\x{5474}\x{5475}\x{5476}\x{5477}\x{5478}\x{5479}\x{547A}\x{547B}\x{547C}' - . '\x{547D}\x{547E}\x{547F}\x{5480}\x{5481}\x{5482}\x{5483}\x{5484}\x{5485}' - . '\x{5486}\x{5487}\x{5488}\x{5489}\x{548B}\x{548C}\x{548D}\x{548E}\x{548F}' - . '\x{5490}\x{5491}\x{5492}\x{5493}\x{5494}\x{5495}\x{5496}\x{5497}\x{5498}' - . '\x{5499}\x{549A}\x{549B}\x{549C}\x{549D}\x{549E}\x{549F}\x{54A0}\x{54A1}' - . '\x{54A2}\x{54A3}\x{54A4}\x{54A5}\x{54A6}\x{54A7}\x{54A8}\x{54A9}\x{54AA}' - . '\x{54AB}\x{54AC}\x{54AD}\x{54AE}\x{54AF}\x{54B0}\x{54B1}\x{54B2}\x{54B3}' - . '\x{54B4}\x{54B6}\x{54B7}\x{54B8}\x{54B9}\x{54BA}\x{54BB}\x{54BC}\x{54BD}' - . '\x{54BE}\x{54BF}\x{54C0}\x{54C1}\x{54C2}\x{54C3}\x{54C4}\x{54C5}\x{54C6}' - . '\x{54C7}\x{54C8}\x{54C9}\x{54CA}\x{54CB}\x{54CC}\x{54CD}\x{54CE}\x{54CF}' - . '\x{54D0}\x{54D1}\x{54D2}\x{54D3}\x{54D4}\x{54D5}\x{54D6}\x{54D7}\x{54D8}' - . '\x{54D9}\x{54DA}\x{54DB}\x{54DC}\x{54DD}\x{54DE}\x{54DF}\x{54E0}\x{54E1}' - . '\x{54E2}\x{54E3}\x{54E4}\x{54E5}\x{54E6}\x{54E7}\x{54E8}\x{54E9}\x{54EA}' - . '\x{54EB}\x{54EC}\x{54ED}\x{54EE}\x{54EF}\x{54F0}\x{54F1}\x{54F2}\x{54F3}' - . '\x{54F4}\x{54F5}\x{54F7}\x{54F8}\x{54F9}\x{54FA}\x{54FB}\x{54FC}\x{54FD}' - . '\x{54FE}\x{54FF}\x{5500}\x{5501}\x{5502}\x{5503}\x{5504}\x{5505}\x{5506}' - . '\x{5507}\x{5508}\x{5509}\x{550A}\x{550B}\x{550C}\x{550D}\x{550E}\x{550F}' - . '\x{5510}\x{5511}\x{5512}\x{5513}\x{5514}\x{5516}\x{5517}\x{551A}\x{551B}' - . '\x{551C}\x{551D}\x{551E}\x{551F}\x{5520}\x{5521}\x{5522}\x{5523}\x{5524}' - . '\x{5525}\x{5526}\x{5527}\x{5528}\x{5529}\x{552A}\x{552B}\x{552C}\x{552D}' - . '\x{552E}\x{552F}\x{5530}\x{5531}\x{5532}\x{5533}\x{5534}\x{5535}\x{5536}' - . '\x{5537}\x{5538}\x{5539}\x{553A}\x{553B}\x{553C}\x{553D}\x{553E}\x{553F}' - . '\x{5540}\x{5541}\x{5542}\x{5543}\x{5544}\x{5545}\x{5546}\x{5548}\x{5549}' - . '\x{554A}\x{554B}\x{554C}\x{554D}\x{554E}\x{554F}\x{5550}\x{5551}\x{5552}' - . '\x{5553}\x{5554}\x{5555}\x{5556}\x{5557}\x{5558}\x{5559}\x{555A}\x{555B}' - . '\x{555C}\x{555D}\x{555E}\x{555F}\x{5561}\x{5562}\x{5563}\x{5564}\x{5565}' - . '\x{5566}\x{5567}\x{5568}\x{5569}\x{556A}\x{556B}\x{556C}\x{556D}\x{556E}' - . '\x{556F}\x{5570}\x{5571}\x{5572}\x{5573}\x{5574}\x{5575}\x{5576}\x{5577}' - . '\x{5578}\x{5579}\x{557B}\x{557C}\x{557D}\x{557E}\x{557F}\x{5580}\x{5581}' - . '\x{5582}\x{5583}\x{5584}\x{5585}\x{5586}\x{5587}\x{5588}\x{5589}\x{558A}' - . '\x{558B}\x{558C}\x{558D}\x{558E}\x{558F}\x{5590}\x{5591}\x{5592}\x{5593}' - . '\x{5594}\x{5595}\x{5596}\x{5597}\x{5598}\x{5599}\x{559A}\x{559B}\x{559C}' - . '\x{559D}\x{559E}\x{559F}\x{55A0}\x{55A1}\x{55A2}\x{55A3}\x{55A4}\x{55A5}' - . '\x{55A6}\x{55A7}\x{55A8}\x{55A9}\x{55AA}\x{55AB}\x{55AC}\x{55AD}\x{55AE}' - . '\x{55AF}\x{55B0}\x{55B1}\x{55B2}\x{55B3}\x{55B4}\x{55B5}\x{55B6}\x{55B7}' - . '\x{55B8}\x{55B9}\x{55BA}\x{55BB}\x{55BC}\x{55BD}\x{55BE}\x{55BF}\x{55C0}' - . '\x{55C1}\x{55C2}\x{55C3}\x{55C4}\x{55C5}\x{55C6}\x{55C7}\x{55C8}\x{55C9}' - . '\x{55CA}\x{55CB}\x{55CC}\x{55CD}\x{55CE}\x{55CF}\x{55D0}\x{55D1}\x{55D2}' - . '\x{55D3}\x{55D4}\x{55D5}\x{55D6}\x{55D7}\x{55D8}\x{55D9}\x{55DA}\x{55DB}' - . '\x{55DC}\x{55DD}\x{55DE}\x{55DF}\x{55E1}\x{55E2}\x{55E3}\x{55E4}\x{55E5}' - . '\x{55E6}\x{55E7}\x{55E8}\x{55E9}\x{55EA}\x{55EB}\x{55EC}\x{55ED}\x{55EE}' - . '\x{55EF}\x{55F0}\x{55F1}\x{55F2}\x{55F3}\x{55F4}\x{55F5}\x{55F6}\x{55F7}' - . '\x{55F9}\x{55FA}\x{55FB}\x{55FC}\x{55FD}\x{55FE}\x{55FF}\x{5600}\x{5601}' - . '\x{5602}\x{5603}\x{5604}\x{5606}\x{5607}\x{5608}\x{5609}\x{560C}\x{560D}' - . '\x{560E}\x{560F}\x{5610}\x{5611}\x{5612}\x{5613}\x{5614}\x{5615}\x{5616}' - . '\x{5617}\x{5618}\x{5619}\x{561A}\x{561B}\x{561C}\x{561D}\x{561E}\x{561F}' - . '\x{5621}\x{5622}\x{5623}\x{5624}\x{5625}\x{5626}\x{5627}\x{5628}\x{5629}' - . '\x{562A}\x{562C}\x{562D}\x{562E}\x{562F}\x{5630}\x{5631}\x{5632}\x{5633}' - . '\x{5634}\x{5635}\x{5636}\x{5638}\x{5639}\x{563A}\x{563B}\x{563D}\x{563E}' - . '\x{563F}\x{5640}\x{5641}\x{5642}\x{5643}\x{5645}\x{5646}\x{5647}\x{5648}' - . '\x{5649}\x{564A}\x{564C}\x{564D}\x{564E}\x{564F}\x{5650}\x{5652}\x{5653}' - . '\x{5654}\x{5655}\x{5657}\x{5658}\x{5659}\x{565A}\x{565B}\x{565C}\x{565D}' - . '\x{565E}\x{5660}\x{5662}\x{5663}\x{5664}\x{5665}\x{5666}\x{5667}\x{5668}' - . '\x{5669}\x{566A}\x{566B}\x{566C}\x{566D}\x{566E}\x{566F}\x{5670}\x{5671}' - . '\x{5672}\x{5673}\x{5674}\x{5676}\x{5677}\x{5678}\x{5679}\x{567A}\x{567B}' - . '\x{567C}\x{567E}\x{567F}\x{5680}\x{5681}\x{5682}\x{5683}\x{5684}\x{5685}' - . '\x{5686}\x{5687}\x{568A}\x{568C}\x{568D}\x{568E}\x{568F}\x{5690}\x{5691}' - . '\x{5692}\x{5693}\x{5694}\x{5695}\x{5697}\x{5698}\x{5699}\x{569A}\x{569B}' - . '\x{569C}\x{569D}\x{569F}\x{56A0}\x{56A1}\x{56A3}\x{56A4}\x{56A5}\x{56A6}' - . '\x{56A7}\x{56A8}\x{56A9}\x{56AA}\x{56AB}\x{56AC}\x{56AD}\x{56AE}\x{56AF}' - . '\x{56B0}\x{56B1}\x{56B2}\x{56B3}\x{56B4}\x{56B5}\x{56B6}\x{56B7}\x{56B8}' - . '\x{56B9}\x{56BB}\x{56BC}\x{56BD}\x{56BE}\x{56BF}\x{56C0}\x{56C1}\x{56C2}' - . '\x{56C3}\x{56C4}\x{56C5}\x{56C6}\x{56C7}\x{56C8}\x{56C9}\x{56CA}\x{56CB}' - . '\x{56CC}\x{56CD}\x{56CE}\x{56D0}\x{56D1}\x{56D2}\x{56D3}\x{56D4}\x{56D5}' - . '\x{56D6}\x{56D7}\x{56D8}\x{56DA}\x{56DB}\x{56DC}\x{56DD}\x{56DE}\x{56DF}' - . '\x{56E0}\x{56E1}\x{56E2}\x{56E3}\x{56E4}\x{56E5}\x{56E7}\x{56E8}\x{56E9}' - . '\x{56EA}\x{56EB}\x{56EC}\x{56ED}\x{56EE}\x{56EF}\x{56F0}\x{56F1}\x{56F2}' - . '\x{56F3}\x{56F4}\x{56F5}\x{56F7}\x{56F9}\x{56FA}\x{56FD}\x{56FE}\x{56FF}' - . '\x{5700}\x{5701}\x{5702}\x{5703}\x{5704}\x{5706}\x{5707}\x{5708}\x{5709}' - . '\x{570A}\x{570B}\x{570C}\x{570D}\x{570E}\x{570F}\x{5710}\x{5712}\x{5713}' - . '\x{5714}\x{5715}\x{5716}\x{5718}\x{5719}\x{571A}\x{571B}\x{571C}\x{571D}' - . '\x{571E}\x{571F}\x{5720}\x{5722}\x{5723}\x{5725}\x{5726}\x{5727}\x{5728}' - . '\x{5729}\x{572A}\x{572B}\x{572C}\x{572D}\x{572E}\x{572F}\x{5730}\x{5731}' - . '\x{5732}\x{5733}\x{5734}\x{5735}\x{5736}\x{5737}\x{5738}\x{5739}\x{573A}' - . '\x{573B}\x{573C}\x{573E}\x{573F}\x{5740}\x{5741}\x{5742}\x{5744}\x{5745}' - . '\x{5746}\x{5747}\x{5749}\x{574A}\x{574B}\x{574C}\x{574D}\x{574E}\x{574F}' - . '\x{5750}\x{5751}\x{5752}\x{5753}\x{5754}\x{5757}\x{5759}\x{575A}\x{575B}' - . '\x{575C}\x{575D}\x{575E}\x{575F}\x{5760}\x{5761}\x{5762}\x{5764}\x{5765}' - . '\x{5766}\x{5767}\x{5768}\x{5769}\x{576A}\x{576B}\x{576C}\x{576D}\x{576F}' - . '\x{5770}\x{5771}\x{5772}\x{5773}\x{5774}\x{5775}\x{5776}\x{5777}\x{5779}' - . '\x{577A}\x{577B}\x{577C}\x{577D}\x{577E}\x{577F}\x{5780}\x{5782}\x{5783}' - . '\x{5784}\x{5785}\x{5786}\x{5788}\x{5789}\x{578A}\x{578B}\x{578C}\x{578D}' - . '\x{578E}\x{578F}\x{5790}\x{5791}\x{5792}\x{5793}\x{5794}\x{5795}\x{5797}' - . '\x{5798}\x{5799}\x{579A}\x{579B}\x{579C}\x{579D}\x{579E}\x{579F}\x{57A0}' - . '\x{57A1}\x{57A2}\x{57A3}\x{57A4}\x{57A5}\x{57A6}\x{57A7}\x{57A9}\x{57AA}' - . '\x{57AB}\x{57AC}\x{57AD}\x{57AE}\x{57AF}\x{57B0}\x{57B1}\x{57B2}\x{57B3}' - . '\x{57B4}\x{57B5}\x{57B6}\x{57B7}\x{57B8}\x{57B9}\x{57BA}\x{57BB}\x{57BC}' - . '\x{57BD}\x{57BE}\x{57BF}\x{57C0}\x{57C1}\x{57C2}\x{57C3}\x{57C4}\x{57C5}' - . '\x{57C6}\x{57C7}\x{57C8}\x{57C9}\x{57CB}\x{57CC}\x{57CD}\x{57CE}\x{57CF}' - . '\x{57D0}\x{57D2}\x{57D3}\x{57D4}\x{57D5}\x{57D6}\x{57D8}\x{57D9}\x{57DA}' - . '\x{57DC}\x{57DD}\x{57DF}\x{57E0}\x{57E1}\x{57E2}\x{57E3}\x{57E4}\x{57E5}' - . '\x{57E6}\x{57E7}\x{57E8}\x{57E9}\x{57EA}\x{57EB}\x{57EC}\x{57ED}\x{57EE}' - . '\x{57EF}\x{57F0}\x{57F1}\x{57F2}\x{57F3}\x{57F4}\x{57F5}\x{57F6}\x{57F7}' - . '\x{57F8}\x{57F9}\x{57FA}\x{57FB}\x{57FC}\x{57FD}\x{57FE}\x{57FF}\x{5800}' - . '\x{5801}\x{5802}\x{5803}\x{5804}\x{5805}\x{5806}\x{5807}\x{5808}\x{5809}' - . '\x{580A}\x{580B}\x{580C}\x{580D}\x{580E}\x{580F}\x{5810}\x{5811}\x{5812}' - . '\x{5813}\x{5814}\x{5815}\x{5816}\x{5819}\x{581A}\x{581B}\x{581C}\x{581D}' - . '\x{581E}\x{581F}\x{5820}\x{5821}\x{5822}\x{5823}\x{5824}\x{5825}\x{5826}' - . '\x{5827}\x{5828}\x{5829}\x{582A}\x{582B}\x{582C}\x{582D}\x{582E}\x{582F}' - . '\x{5830}\x{5831}\x{5832}\x{5833}\x{5834}\x{5835}\x{5836}\x{5837}\x{5838}' - . '\x{5839}\x{583A}\x{583B}\x{583C}\x{583D}\x{583E}\x{583F}\x{5840}\x{5842}' - . '\x{5843}\x{5844}\x{5845}\x{5846}\x{5847}\x{5848}\x{5849}\x{584A}\x{584B}' - . '\x{584C}\x{584D}\x{584E}\x{584F}\x{5851}\x{5852}\x{5853}\x{5854}\x{5855}' - . '\x{5857}\x{5858}\x{5859}\x{585A}\x{585B}\x{585C}\x{585D}\x{585E}\x{585F}' - . '\x{5861}\x{5862}\x{5863}\x{5864}\x{5865}\x{5868}\x{5869}\x{586A}\x{586B}' - . '\x{586C}\x{586D}\x{586E}\x{586F}\x{5870}\x{5871}\x{5872}\x{5873}\x{5874}' - . '\x{5875}\x{5876}\x{5878}\x{5879}\x{587A}\x{587B}\x{587C}\x{587D}\x{587E}' - . '\x{587F}\x{5880}\x{5881}\x{5882}\x{5883}\x{5884}\x{5885}\x{5886}\x{5887}' - . '\x{5888}\x{5889}\x{588A}\x{588B}\x{588C}\x{588D}\x{588E}\x{588F}\x{5890}' - . '\x{5891}\x{5892}\x{5893}\x{5894}\x{5896}\x{5897}\x{5898}\x{5899}\x{589A}' - . '\x{589B}\x{589C}\x{589D}\x{589E}\x{589F}\x{58A0}\x{58A1}\x{58A2}\x{58A3}' - . '\x{58A4}\x{58A5}\x{58A6}\x{58A7}\x{58A8}\x{58A9}\x{58AB}\x{58AC}\x{58AD}' - . '\x{58AE}\x{58AF}\x{58B0}\x{58B1}\x{58B2}\x{58B3}\x{58B4}\x{58B7}\x{58B8}' - . '\x{58B9}\x{58BA}\x{58BB}\x{58BC}\x{58BD}\x{58BE}\x{58BF}\x{58C1}\x{58C2}' - . '\x{58C5}\x{58C6}\x{58C7}\x{58C8}\x{58C9}\x{58CA}\x{58CB}\x{58CE}\x{58CF}' - . '\x{58D1}\x{58D2}\x{58D3}\x{58D4}\x{58D5}\x{58D6}\x{58D7}\x{58D8}\x{58D9}' - . '\x{58DA}\x{58DB}\x{58DD}\x{58DE}\x{58DF}\x{58E0}\x{58E2}\x{58E3}\x{58E4}' - . '\x{58E5}\x{58E7}\x{58E8}\x{58E9}\x{58EA}\x{58EB}\x{58EC}\x{58ED}\x{58EE}' - . '\x{58EF}\x{58F0}\x{58F1}\x{58F2}\x{58F3}\x{58F4}\x{58F6}\x{58F7}\x{58F8}' - . '\x{58F9}\x{58FA}\x{58FB}\x{58FC}\x{58FD}\x{58FE}\x{58FF}\x{5900}\x{5902}' - . '\x{5903}\x{5904}\x{5906}\x{5907}\x{5909}\x{590A}\x{590B}\x{590C}\x{590D}' - . '\x{590E}\x{590F}\x{5910}\x{5912}\x{5914}\x{5915}\x{5916}\x{5917}\x{5918}' - . '\x{5919}\x{591A}\x{591B}\x{591C}\x{591D}\x{591E}\x{591F}\x{5920}\x{5921}' - . '\x{5922}\x{5924}\x{5925}\x{5926}\x{5927}\x{5928}\x{5929}\x{592A}\x{592B}' - . '\x{592C}\x{592D}\x{592E}\x{592F}\x{5930}\x{5931}\x{5932}\x{5934}\x{5935}' - . '\x{5937}\x{5938}\x{5939}\x{593A}\x{593B}\x{593C}\x{593D}\x{593E}\x{593F}' - . '\x{5940}\x{5941}\x{5942}\x{5943}\x{5944}\x{5945}\x{5946}\x{5947}\x{5948}' - . '\x{5949}\x{594A}\x{594B}\x{594C}\x{594D}\x{594E}\x{594F}\x{5950}\x{5951}' - . '\x{5952}\x{5953}\x{5954}\x{5955}\x{5956}\x{5957}\x{5958}\x{595A}\x{595C}' - . '\x{595D}\x{595E}\x{595F}\x{5960}\x{5961}\x{5962}\x{5963}\x{5964}\x{5965}' - . '\x{5966}\x{5967}\x{5968}\x{5969}\x{596A}\x{596B}\x{596C}\x{596D}\x{596E}' - . '\x{596F}\x{5970}\x{5971}\x{5972}\x{5973}\x{5974}\x{5975}\x{5976}\x{5977}' - . '\x{5978}\x{5979}\x{597A}\x{597B}\x{597C}\x{597D}\x{597E}\x{597F}\x{5980}' - . '\x{5981}\x{5982}\x{5983}\x{5984}\x{5985}\x{5986}\x{5987}\x{5988}\x{5989}' - . '\x{598A}\x{598B}\x{598C}\x{598D}\x{598E}\x{598F}\x{5990}\x{5991}\x{5992}' - . '\x{5993}\x{5994}\x{5995}\x{5996}\x{5997}\x{5998}\x{5999}\x{599A}\x{599C}' - . '\x{599D}\x{599E}\x{599F}\x{59A0}\x{59A1}\x{59A2}\x{59A3}\x{59A4}\x{59A5}' - . '\x{59A6}\x{59A7}\x{59A8}\x{59A9}\x{59AA}\x{59AB}\x{59AC}\x{59AD}\x{59AE}' - . '\x{59AF}\x{59B0}\x{59B1}\x{59B2}\x{59B3}\x{59B4}\x{59B5}\x{59B6}\x{59B8}' - . '\x{59B9}\x{59BA}\x{59BB}\x{59BC}\x{59BD}\x{59BE}\x{59BF}\x{59C0}\x{59C1}' - . '\x{59C2}\x{59C3}\x{59C4}\x{59C5}\x{59C6}\x{59C7}\x{59C8}\x{59C9}\x{59CA}' - . '\x{59CB}\x{59CC}\x{59CD}\x{59CE}\x{59CF}\x{59D0}\x{59D1}\x{59D2}\x{59D3}' - . '\x{59D4}\x{59D5}\x{59D6}\x{59D7}\x{59D8}\x{59D9}\x{59DA}\x{59DB}\x{59DC}' - . '\x{59DD}\x{59DE}\x{59DF}\x{59E0}\x{59E1}\x{59E2}\x{59E3}\x{59E4}\x{59E5}' - . '\x{59E6}\x{59E8}\x{59E9}\x{59EA}\x{59EB}\x{59EC}\x{59ED}\x{59EE}\x{59EF}' - . '\x{59F0}\x{59F1}\x{59F2}\x{59F3}\x{59F4}\x{59F5}\x{59F6}\x{59F7}\x{59F8}' - . '\x{59F9}\x{59FA}\x{59FB}\x{59FC}\x{59FD}\x{59FE}\x{59FF}\x{5A00}\x{5A01}' - . '\x{5A02}\x{5A03}\x{5A04}\x{5A05}\x{5A06}\x{5A07}\x{5A08}\x{5A09}\x{5A0A}' - . '\x{5A0B}\x{5A0C}\x{5A0D}\x{5A0E}\x{5A0F}\x{5A10}\x{5A11}\x{5A12}\x{5A13}' - . '\x{5A14}\x{5A15}\x{5A16}\x{5A17}\x{5A18}\x{5A19}\x{5A1A}\x{5A1B}\x{5A1C}' - . '\x{5A1D}\x{5A1E}\x{5A1F}\x{5A20}\x{5A21}\x{5A22}\x{5A23}\x{5A25}\x{5A27}' - . '\x{5A28}\x{5A29}\x{5A2A}\x{5A2B}\x{5A2D}\x{5A2E}\x{5A2F}\x{5A31}\x{5A32}' - . '\x{5A33}\x{5A34}\x{5A35}\x{5A36}\x{5A37}\x{5A38}\x{5A39}\x{5A3A}\x{5A3B}' - . '\x{5A3C}\x{5A3D}\x{5A3E}\x{5A3F}\x{5A40}\x{5A41}\x{5A42}\x{5A43}\x{5A44}' - . '\x{5A45}\x{5A46}\x{5A47}\x{5A48}\x{5A49}\x{5A4A}\x{5A4B}\x{5A4C}\x{5A4D}' - . '\x{5A4E}\x{5A4F}\x{5A50}\x{5A51}\x{5A52}\x{5A53}\x{5A55}\x{5A56}\x{5A57}' - . '\x{5A58}\x{5A5A}\x{5A5B}\x{5A5C}\x{5A5D}\x{5A5E}\x{5A5F}\x{5A60}\x{5A61}' - . '\x{5A62}\x{5A63}\x{5A64}\x{5A65}\x{5A66}\x{5A67}\x{5A68}\x{5A69}\x{5A6A}' - . '\x{5A6B}\x{5A6C}\x{5A6D}\x{5A6E}\x{5A70}\x{5A72}\x{5A73}\x{5A74}\x{5A75}' - . '\x{5A76}\x{5A77}\x{5A78}\x{5A79}\x{5A7A}\x{5A7B}\x{5A7C}\x{5A7D}\x{5A7E}' - . '\x{5A7F}\x{5A80}\x{5A81}\x{5A82}\x{5A83}\x{5A84}\x{5A85}\x{5A86}\x{5A88}' - . '\x{5A89}\x{5A8A}\x{5A8B}\x{5A8C}\x{5A8E}\x{5A8F}\x{5A90}\x{5A91}\x{5A92}' - . '\x{5A93}\x{5A94}\x{5A95}\x{5A96}\x{5A97}\x{5A98}\x{5A99}\x{5A9A}\x{5A9B}' - . '\x{5A9C}\x{5A9D}\x{5A9E}\x{5A9F}\x{5AA0}\x{5AA1}\x{5AA2}\x{5AA3}\x{5AA4}' - . '\x{5AA5}\x{5AA6}\x{5AA7}\x{5AA8}\x{5AA9}\x{5AAA}\x{5AAC}\x{5AAD}\x{5AAE}' - . '\x{5AAF}\x{5AB0}\x{5AB1}\x{5AB2}\x{5AB3}\x{5AB4}\x{5AB5}\x{5AB6}\x{5AB7}' - . '\x{5AB8}\x{5AB9}\x{5ABA}\x{5ABB}\x{5ABC}\x{5ABD}\x{5ABE}\x{5ABF}\x{5AC0}' - . '\x{5AC1}\x{5AC2}\x{5AC3}\x{5AC4}\x{5AC5}\x{5AC6}\x{5AC7}\x{5AC8}\x{5AC9}' - . '\x{5ACA}\x{5ACB}\x{5ACC}\x{5ACD}\x{5ACE}\x{5ACF}\x{5AD1}\x{5AD2}\x{5AD4}' - . '\x{5AD5}\x{5AD6}\x{5AD7}\x{5AD8}\x{5AD9}\x{5ADA}\x{5ADB}\x{5ADC}\x{5ADD}' - . '\x{5ADE}\x{5ADF}\x{5AE0}\x{5AE1}\x{5AE2}\x{5AE3}\x{5AE4}\x{5AE5}\x{5AE6}' - . '\x{5AE7}\x{5AE8}\x{5AE9}\x{5AEA}\x{5AEB}\x{5AEC}\x{5AED}\x{5AEE}\x{5AF1}' - . '\x{5AF2}\x{5AF3}\x{5AF4}\x{5AF5}\x{5AF6}\x{5AF7}\x{5AF8}\x{5AF9}\x{5AFA}' - . '\x{5AFB}\x{5AFC}\x{5AFD}\x{5AFE}\x{5AFF}\x{5B00}\x{5B01}\x{5B02}\x{5B03}' - . '\x{5B04}\x{5B05}\x{5B06}\x{5B07}\x{5B08}\x{5B09}\x{5B0B}\x{5B0C}\x{5B0E}' - . '\x{5B0F}\x{5B10}\x{5B11}\x{5B12}\x{5B13}\x{5B14}\x{5B15}\x{5B16}\x{5B17}' - . '\x{5B18}\x{5B19}\x{5B1A}\x{5B1B}\x{5B1C}\x{5B1D}\x{5B1E}\x{5B1F}\x{5B20}' - . '\x{5B21}\x{5B22}\x{5B23}\x{5B24}\x{5B25}\x{5B26}\x{5B27}\x{5B28}\x{5B29}' - . '\x{5B2A}\x{5B2B}\x{5B2C}\x{5B2D}\x{5B2E}\x{5B2F}\x{5B30}\x{5B31}\x{5B32}' - . '\x{5B33}\x{5B34}\x{5B35}\x{5B36}\x{5B37}\x{5B38}\x{5B3A}\x{5B3B}\x{5B3C}' - . '\x{5B3D}\x{5B3E}\x{5B3F}\x{5B40}\x{5B41}\x{5B42}\x{5B43}\x{5B44}\x{5B45}' - . '\x{5B47}\x{5B48}\x{5B49}\x{5B4A}\x{5B4B}\x{5B4C}\x{5B4D}\x{5B4E}\x{5B50}' - . '\x{5B51}\x{5B53}\x{5B54}\x{5B55}\x{5B56}\x{5B57}\x{5B58}\x{5B59}\x{5B5A}' - . '\x{5B5B}\x{5B5C}\x{5B5D}\x{5B5E}\x{5B5F}\x{5B62}\x{5B63}\x{5B64}\x{5B65}' - . '\x{5B66}\x{5B67}\x{5B68}\x{5B69}\x{5B6A}\x{5B6B}\x{5B6C}\x{5B6D}\x{5B6E}' - . '\x{5B70}\x{5B71}\x{5B72}\x{5B73}\x{5B74}\x{5B75}\x{5B76}\x{5B77}\x{5B78}' - . '\x{5B7A}\x{5B7B}\x{5B7C}\x{5B7D}\x{5B7F}\x{5B80}\x{5B81}\x{5B82}\x{5B83}' - . '\x{5B84}\x{5B85}\x{5B87}\x{5B88}\x{5B89}\x{5B8A}\x{5B8B}\x{5B8C}\x{5B8D}' - . '\x{5B8E}\x{5B8F}\x{5B91}\x{5B92}\x{5B93}\x{5B94}\x{5B95}\x{5B96}\x{5B97}' - . '\x{5B98}\x{5B99}\x{5B9A}\x{5B9B}\x{5B9C}\x{5B9D}\x{5B9E}\x{5B9F}\x{5BA0}' - . '\x{5BA1}\x{5BA2}\x{5BA3}\x{5BA4}\x{5BA5}\x{5BA6}\x{5BA7}\x{5BA8}\x{5BAA}' - . '\x{5BAB}\x{5BAC}\x{5BAD}\x{5BAE}\x{5BAF}\x{5BB0}\x{5BB1}\x{5BB3}\x{5BB4}' - . '\x{5BB5}\x{5BB6}\x{5BB8}\x{5BB9}\x{5BBA}\x{5BBB}\x{5BBD}\x{5BBE}\x{5BBF}' - . '\x{5BC0}\x{5BC1}\x{5BC2}\x{5BC3}\x{5BC4}\x{5BC5}\x{5BC6}\x{5BC7}\x{5BCA}' - . '\x{5BCB}\x{5BCC}\x{5BCD}\x{5BCE}\x{5BCF}\x{5BD0}\x{5BD1}\x{5BD2}\x{5BD3}' - . '\x{5BD4}\x{5BD5}\x{5BD6}\x{5BD8}\x{5BD9}\x{5BDB}\x{5BDC}\x{5BDD}\x{5BDE}' - . '\x{5BDF}\x{5BE0}\x{5BE1}\x{5BE2}\x{5BE3}\x{5BE4}\x{5BE5}\x{5BE6}\x{5BE7}' - . '\x{5BE8}\x{5BE9}\x{5BEA}\x{5BEB}\x{5BEC}\x{5BED}\x{5BEE}\x{5BEF}\x{5BF0}' - . '\x{5BF1}\x{5BF2}\x{5BF3}\x{5BF4}\x{5BF5}\x{5BF6}\x{5BF7}\x{5BF8}\x{5BF9}' - . '\x{5BFA}\x{5BFB}\x{5BFC}\x{5BFD}\x{5BFF}\x{5C01}\x{5C03}\x{5C04}\x{5C05}' - . '\x{5C06}\x{5C07}\x{5C08}\x{5C09}\x{5C0A}\x{5C0B}\x{5C0C}\x{5C0D}\x{5C0E}' - . '\x{5C0F}\x{5C10}\x{5C11}\x{5C12}\x{5C13}\x{5C14}\x{5C15}\x{5C16}\x{5C17}' - . '\x{5C18}\x{5C19}\x{5C1A}\x{5C1C}\x{5C1D}\x{5C1E}\x{5C1F}\x{5C20}\x{5C21}' - . '\x{5C22}\x{5C24}\x{5C25}\x{5C27}\x{5C28}\x{5C2A}\x{5C2B}\x{5C2C}\x{5C2D}' - . '\x{5C2E}\x{5C2F}\x{5C30}\x{5C31}\x{5C32}\x{5C33}\x{5C34}\x{5C35}\x{5C37}' - . '\x{5C38}\x{5C39}\x{5C3A}\x{5C3B}\x{5C3C}\x{5C3D}\x{5C3E}\x{5C3F}\x{5C40}' - . '\x{5C41}\x{5C42}\x{5C43}\x{5C44}\x{5C45}\x{5C46}\x{5C47}\x{5C48}\x{5C49}' - . '\x{5C4A}\x{5C4B}\x{5C4C}\x{5C4D}\x{5C4E}\x{5C4F}\x{5C50}\x{5C51}\x{5C52}' - . '\x{5C53}\x{5C54}\x{5C55}\x{5C56}\x{5C57}\x{5C58}\x{5C59}\x{5C5B}\x{5C5C}' - . '\x{5C5D}\x{5C5E}\x{5C5F}\x{5C60}\x{5C61}\x{5C62}\x{5C63}\x{5C64}\x{5C65}' - . '\x{5C66}\x{5C67}\x{5C68}\x{5C69}\x{5C6A}\x{5C6B}\x{5C6C}\x{5C6D}\x{5C6E}' - . '\x{5C6F}\x{5C70}\x{5C71}\x{5C72}\x{5C73}\x{5C74}\x{5C75}\x{5C76}\x{5C77}' - . '\x{5C78}\x{5C79}\x{5C7A}\x{5C7B}\x{5C7C}\x{5C7D}\x{5C7E}\x{5C7F}\x{5C80}' - . '\x{5C81}\x{5C82}\x{5C83}\x{5C84}\x{5C86}\x{5C87}\x{5C88}\x{5C89}\x{5C8A}' - . '\x{5C8B}\x{5C8C}\x{5C8D}\x{5C8E}\x{5C8F}\x{5C90}\x{5C91}\x{5C92}\x{5C93}' - . '\x{5C94}\x{5C95}\x{5C96}\x{5C97}\x{5C98}\x{5C99}\x{5C9A}\x{5C9B}\x{5C9C}' - . '\x{5C9D}\x{5C9E}\x{5C9F}\x{5CA0}\x{5CA1}\x{5CA2}\x{5CA3}\x{5CA4}\x{5CA5}' - . '\x{5CA6}\x{5CA7}\x{5CA8}\x{5CA9}\x{5CAA}\x{5CAB}\x{5CAC}\x{5CAD}\x{5CAE}' - . '\x{5CAF}\x{5CB0}\x{5CB1}\x{5CB2}\x{5CB3}\x{5CB5}\x{5CB6}\x{5CB7}\x{5CB8}' - . '\x{5CBA}\x{5CBB}\x{5CBC}\x{5CBD}\x{5CBE}\x{5CBF}\x{5CC1}\x{5CC2}\x{5CC3}' - . '\x{5CC4}\x{5CC5}\x{5CC6}\x{5CC7}\x{5CC8}\x{5CC9}\x{5CCA}\x{5CCB}\x{5CCC}' - . '\x{5CCD}\x{5CCE}\x{5CCF}\x{5CD0}\x{5CD1}\x{5CD2}\x{5CD3}\x{5CD4}\x{5CD6}' - . '\x{5CD7}\x{5CD8}\x{5CD9}\x{5CDA}\x{5CDB}\x{5CDC}\x{5CDE}\x{5CDF}\x{5CE0}' - . '\x{5CE1}\x{5CE2}\x{5CE3}\x{5CE4}\x{5CE5}\x{5CE6}\x{5CE7}\x{5CE8}\x{5CE9}' - . '\x{5CEA}\x{5CEB}\x{5CEC}\x{5CED}\x{5CEE}\x{5CEF}\x{5CF0}\x{5CF1}\x{5CF2}' - . '\x{5CF3}\x{5CF4}\x{5CF6}\x{5CF7}\x{5CF8}\x{5CF9}\x{5CFA}\x{5CFB}\x{5CFC}' - . '\x{5CFD}\x{5CFE}\x{5CFF}\x{5D00}\x{5D01}\x{5D02}\x{5D03}\x{5D04}\x{5D05}' - . '\x{5D06}\x{5D07}\x{5D08}\x{5D09}\x{5D0A}\x{5D0B}\x{5D0C}\x{5D0D}\x{5D0E}' - . '\x{5D0F}\x{5D10}\x{5D11}\x{5D12}\x{5D13}\x{5D14}\x{5D15}\x{5D16}\x{5D17}' - . '\x{5D18}\x{5D19}\x{5D1A}\x{5D1B}\x{5D1C}\x{5D1D}\x{5D1E}\x{5D1F}\x{5D20}' - . '\x{5D21}\x{5D22}\x{5D23}\x{5D24}\x{5D25}\x{5D26}\x{5D27}\x{5D28}\x{5D29}' - . '\x{5D2A}\x{5D2C}\x{5D2D}\x{5D2E}\x{5D30}\x{5D31}\x{5D32}\x{5D33}\x{5D34}' - . '\x{5D35}\x{5D36}\x{5D37}\x{5D38}\x{5D39}\x{5D3A}\x{5D3C}\x{5D3D}\x{5D3E}' - . '\x{5D3F}\x{5D40}\x{5D41}\x{5D42}\x{5D43}\x{5D44}\x{5D45}\x{5D46}\x{5D47}' - . '\x{5D48}\x{5D49}\x{5D4A}\x{5D4B}\x{5D4C}\x{5D4D}\x{5D4E}\x{5D4F}\x{5D50}' - . '\x{5D51}\x{5D52}\x{5D54}\x{5D55}\x{5D56}\x{5D58}\x{5D59}\x{5D5A}\x{5D5B}' - . '\x{5D5D}\x{5D5E}\x{5D5F}\x{5D61}\x{5D62}\x{5D63}\x{5D64}\x{5D65}\x{5D66}' - . '\x{5D67}\x{5D68}\x{5D69}\x{5D6A}\x{5D6B}\x{5D6C}\x{5D6D}\x{5D6E}\x{5D6F}' - . '\x{5D70}\x{5D71}\x{5D72}\x{5D73}\x{5D74}\x{5D75}\x{5D76}\x{5D77}\x{5D78}' - . '\x{5D79}\x{5D7A}\x{5D7B}\x{5D7C}\x{5D7D}\x{5D7E}\x{5D7F}\x{5D80}\x{5D81}' - . '\x{5D82}\x{5D84}\x{5D85}\x{5D86}\x{5D87}\x{5D88}\x{5D89}\x{5D8A}\x{5D8B}' - . '\x{5D8C}\x{5D8D}\x{5D8E}\x{5D8F}\x{5D90}\x{5D91}\x{5D92}\x{5D93}\x{5D94}' - . '\x{5D95}\x{5D97}\x{5D98}\x{5D99}\x{5D9A}\x{5D9B}\x{5D9C}\x{5D9D}\x{5D9E}' - . '\x{5D9F}\x{5DA0}\x{5DA1}\x{5DA2}\x{5DA5}\x{5DA6}\x{5DA7}\x{5DA8}\x{5DA9}' - . '\x{5DAA}\x{5DAC}\x{5DAD}\x{5DAE}\x{5DAF}\x{5DB0}\x{5DB1}\x{5DB2}\x{5DB4}' - . '\x{5DB5}\x{5DB6}\x{5DB7}\x{5DB8}\x{5DBA}\x{5DBB}\x{5DBC}\x{5DBD}\x{5DBE}' - . '\x{5DBF}\x{5DC0}\x{5DC1}\x{5DC2}\x{5DC3}\x{5DC5}\x{5DC6}\x{5DC7}\x{5DC8}' - . '\x{5DC9}\x{5DCA}\x{5DCB}\x{5DCC}\x{5DCD}\x{5DCE}\x{5DCF}\x{5DD0}\x{5DD1}' - . '\x{5DD2}\x{5DD3}\x{5DD4}\x{5DD5}\x{5DD6}\x{5DD8}\x{5DD9}\x{5DDB}\x{5DDD}' - . '\x{5DDE}\x{5DDF}\x{5DE0}\x{5DE1}\x{5DE2}\x{5DE3}\x{5DE4}\x{5DE5}\x{5DE6}' - . '\x{5DE7}\x{5DE8}\x{5DE9}\x{5DEA}\x{5DEB}\x{5DEC}\x{5DED}\x{5DEE}\x{5DEF}' - . '\x{5DF0}\x{5DF1}\x{5DF2}\x{5DF3}\x{5DF4}\x{5DF5}\x{5DF7}\x{5DF8}\x{5DF9}' - . '\x{5DFA}\x{5DFB}\x{5DFC}\x{5DFD}\x{5DFE}\x{5DFF}\x{5E00}\x{5E01}\x{5E02}' - . '\x{5E03}\x{5E04}\x{5E05}\x{5E06}\x{5E07}\x{5E08}\x{5E09}\x{5E0A}\x{5E0B}' - . '\x{5E0C}\x{5E0D}\x{5E0E}\x{5E0F}\x{5E10}\x{5E11}\x{5E13}\x{5E14}\x{5E15}' - . '\x{5E16}\x{5E17}\x{5E18}\x{5E19}\x{5E1A}\x{5E1B}\x{5E1C}\x{5E1D}\x{5E1E}' - . '\x{5E1F}\x{5E20}\x{5E21}\x{5E22}\x{5E23}\x{5E24}\x{5E25}\x{5E26}\x{5E27}' - . '\x{5E28}\x{5E29}\x{5E2A}\x{5E2B}\x{5E2C}\x{5E2D}\x{5E2E}\x{5E2F}\x{5E30}' - . '\x{5E31}\x{5E32}\x{5E33}\x{5E34}\x{5E35}\x{5E36}\x{5E37}\x{5E38}\x{5E39}' - . '\x{5E3A}\x{5E3B}\x{5E3C}\x{5E3D}\x{5E3E}\x{5E40}\x{5E41}\x{5E42}\x{5E43}' - . '\x{5E44}\x{5E45}\x{5E46}\x{5E47}\x{5E49}\x{5E4A}\x{5E4B}\x{5E4C}\x{5E4D}' - . '\x{5E4E}\x{5E4F}\x{5E50}\x{5E52}\x{5E53}\x{5E54}\x{5E55}\x{5E56}\x{5E57}' - . '\x{5E58}\x{5E59}\x{5E5A}\x{5E5B}\x{5E5C}\x{5E5D}\x{5E5E}\x{5E5F}\x{5E60}' - . '\x{5E61}\x{5E62}\x{5E63}\x{5E64}\x{5E65}\x{5E66}\x{5E67}\x{5E68}\x{5E69}' - . '\x{5E6A}\x{5E6B}\x{5E6C}\x{5E6D}\x{5E6E}\x{5E6F}\x{5E70}\x{5E71}\x{5E72}' - . '\x{5E73}\x{5E74}\x{5E75}\x{5E76}\x{5E77}\x{5E78}\x{5E79}\x{5E7A}\x{5E7B}' - . '\x{5E7C}\x{5E7D}\x{5E7E}\x{5E7F}\x{5E80}\x{5E81}\x{5E82}\x{5E83}\x{5E84}' - . '\x{5E85}\x{5E86}\x{5E87}\x{5E88}\x{5E89}\x{5E8A}\x{5E8B}\x{5E8C}\x{5E8D}' - . '\x{5E8E}\x{5E8F}\x{5E90}\x{5E91}\x{5E93}\x{5E94}\x{5E95}\x{5E96}\x{5E97}' - . '\x{5E98}\x{5E99}\x{5E9A}\x{5E9B}\x{5E9C}\x{5E9D}\x{5E9E}\x{5E9F}\x{5EA0}' - . '\x{5EA1}\x{5EA2}\x{5EA3}\x{5EA4}\x{5EA5}\x{5EA6}\x{5EA7}\x{5EA8}\x{5EA9}' - . '\x{5EAA}\x{5EAB}\x{5EAC}\x{5EAD}\x{5EAE}\x{5EAF}\x{5EB0}\x{5EB1}\x{5EB2}' - . '\x{5EB3}\x{5EB4}\x{5EB5}\x{5EB6}\x{5EB7}\x{5EB8}\x{5EB9}\x{5EBB}\x{5EBC}' - . '\x{5EBD}\x{5EBE}\x{5EBF}\x{5EC1}\x{5EC2}\x{5EC3}\x{5EC4}\x{5EC5}\x{5EC6}' - . '\x{5EC7}\x{5EC8}\x{5EC9}\x{5ECA}\x{5ECB}\x{5ECC}\x{5ECD}\x{5ECE}\x{5ECF}' - . '\x{5ED0}\x{5ED1}\x{5ED2}\x{5ED3}\x{5ED4}\x{5ED5}\x{5ED6}\x{5ED7}\x{5ED8}' - . '\x{5ED9}\x{5EDA}\x{5EDB}\x{5EDC}\x{5EDD}\x{5EDE}\x{5EDF}\x{5EE0}\x{5EE1}' - . '\x{5EE2}\x{5EE3}\x{5EE4}\x{5EE5}\x{5EE6}\x{5EE7}\x{5EE8}\x{5EE9}\x{5EEA}' - . '\x{5EEC}\x{5EED}\x{5EEE}\x{5EEF}\x{5EF0}\x{5EF1}\x{5EF2}\x{5EF3}\x{5EF4}' - . '\x{5EF5}\x{5EF6}\x{5EF7}\x{5EF8}\x{5EFA}\x{5EFB}\x{5EFC}\x{5EFD}\x{5EFE}' - . '\x{5EFF}\x{5F00}\x{5F01}\x{5F02}\x{5F03}\x{5F04}\x{5F05}\x{5F06}\x{5F07}' - . '\x{5F08}\x{5F0A}\x{5F0B}\x{5F0C}\x{5F0D}\x{5F0F}\x{5F11}\x{5F12}\x{5F13}' - . '\x{5F14}\x{5F15}\x{5F16}\x{5F17}\x{5F18}\x{5F19}\x{5F1A}\x{5F1B}\x{5F1C}' - . '\x{5F1D}\x{5F1E}\x{5F1F}\x{5F20}\x{5F21}\x{5F22}\x{5F23}\x{5F24}\x{5F25}' - . '\x{5F26}\x{5F27}\x{5F28}\x{5F29}\x{5F2A}\x{5F2B}\x{5F2C}\x{5F2D}\x{5F2E}' - . '\x{5F2F}\x{5F30}\x{5F31}\x{5F32}\x{5F33}\x{5F34}\x{5F35}\x{5F36}\x{5F37}' - . '\x{5F38}\x{5F39}\x{5F3A}\x{5F3C}\x{5F3E}\x{5F3F}\x{5F40}\x{5F41}\x{5F42}' - . '\x{5F43}\x{5F44}\x{5F45}\x{5F46}\x{5F47}\x{5F48}\x{5F49}\x{5F4A}\x{5F4B}' - . '\x{5F4C}\x{5F4D}\x{5F4E}\x{5F4F}\x{5F50}\x{5F51}\x{5F52}\x{5F53}\x{5F54}' - . '\x{5F55}\x{5F56}\x{5F57}\x{5F58}\x{5F59}\x{5F5A}\x{5F5B}\x{5F5C}\x{5F5D}' - . '\x{5F5E}\x{5F5F}\x{5F60}\x{5F61}\x{5F62}\x{5F63}\x{5F64}\x{5F65}\x{5F66}' - . '\x{5F67}\x{5F68}\x{5F69}\x{5F6A}\x{5F6B}\x{5F6C}\x{5F6D}\x{5F6E}\x{5F6F}' - . '\x{5F70}\x{5F71}\x{5F72}\x{5F73}\x{5F74}\x{5F75}\x{5F76}\x{5F77}\x{5F78}' - . '\x{5F79}\x{5F7A}\x{5F7B}\x{5F7C}\x{5F7D}\x{5F7E}\x{5F7F}\x{5F80}\x{5F81}' - . '\x{5F82}\x{5F83}\x{5F84}\x{5F85}\x{5F86}\x{5F87}\x{5F88}\x{5F89}\x{5F8A}' - . '\x{5F8B}\x{5F8C}\x{5F8D}\x{5F8E}\x{5F90}\x{5F91}\x{5F92}\x{5F93}\x{5F94}' - . '\x{5F95}\x{5F96}\x{5F97}\x{5F98}\x{5F99}\x{5F9B}\x{5F9C}\x{5F9D}\x{5F9E}' - . '\x{5F9F}\x{5FA0}\x{5FA1}\x{5FA2}\x{5FA5}\x{5FA6}\x{5FA7}\x{5FA8}\x{5FA9}' - . '\x{5FAA}\x{5FAB}\x{5FAC}\x{5FAD}\x{5FAE}\x{5FAF}\x{5FB1}\x{5FB2}\x{5FB3}' - . '\x{5FB4}\x{5FB5}\x{5FB6}\x{5FB7}\x{5FB8}\x{5FB9}\x{5FBA}\x{5FBB}\x{5FBC}' - . '\x{5FBD}\x{5FBE}\x{5FBF}\x{5FC0}\x{5FC1}\x{5FC3}\x{5FC4}\x{5FC5}\x{5FC6}' - . '\x{5FC7}\x{5FC8}\x{5FC9}\x{5FCA}\x{5FCB}\x{5FCC}\x{5FCD}\x{5FCF}\x{5FD0}' - . '\x{5FD1}\x{5FD2}\x{5FD3}\x{5FD4}\x{5FD5}\x{5FD6}\x{5FD7}\x{5FD8}\x{5FD9}' - . '\x{5FDA}\x{5FDC}\x{5FDD}\x{5FDE}\x{5FE0}\x{5FE1}\x{5FE3}\x{5FE4}\x{5FE5}' - . '\x{5FE6}\x{5FE7}\x{5FE8}\x{5FE9}\x{5FEA}\x{5FEB}\x{5FED}\x{5FEE}\x{5FEF}' - . '\x{5FF0}\x{5FF1}\x{5FF2}\x{5FF3}\x{5FF4}\x{5FF5}\x{5FF6}\x{5FF7}\x{5FF8}' - . '\x{5FF9}\x{5FFA}\x{5FFB}\x{5FFD}\x{5FFE}\x{5FFF}\x{6000}\x{6001}\x{6002}' - . '\x{6003}\x{6004}\x{6005}\x{6006}\x{6007}\x{6008}\x{6009}\x{600A}\x{600B}' - . '\x{600C}\x{600D}\x{600E}\x{600F}\x{6010}\x{6011}\x{6012}\x{6013}\x{6014}' - . '\x{6015}\x{6016}\x{6017}\x{6018}\x{6019}\x{601A}\x{601B}\x{601C}\x{601D}' - . '\x{601E}\x{601F}\x{6020}\x{6021}\x{6022}\x{6024}\x{6025}\x{6026}\x{6027}' - . '\x{6028}\x{6029}\x{602A}\x{602B}\x{602C}\x{602D}\x{602E}\x{602F}\x{6030}' - . '\x{6031}\x{6032}\x{6033}\x{6034}\x{6035}\x{6036}\x{6037}\x{6038}\x{6039}' - . '\x{603A}\x{603B}\x{603C}\x{603D}\x{603E}\x{603F}\x{6040}\x{6041}\x{6042}' - . '\x{6043}\x{6044}\x{6045}\x{6046}\x{6047}\x{6048}\x{6049}\x{604A}\x{604B}' - . '\x{604C}\x{604D}\x{604E}\x{604F}\x{6050}\x{6051}\x{6052}\x{6053}\x{6054}' - . '\x{6055}\x{6057}\x{6058}\x{6059}\x{605A}\x{605B}\x{605C}\x{605D}\x{605E}' - . '\x{605F}\x{6062}\x{6063}\x{6064}\x{6065}\x{6066}\x{6067}\x{6068}\x{6069}' - . '\x{606A}\x{606B}\x{606C}\x{606D}\x{606E}\x{606F}\x{6070}\x{6072}\x{6073}' - . '\x{6075}\x{6076}\x{6077}\x{6078}\x{6079}\x{607A}\x{607B}\x{607C}\x{607D}' - . '\x{607E}\x{607F}\x{6080}\x{6081}\x{6082}\x{6083}\x{6084}\x{6085}\x{6086}' - . '\x{6087}\x{6088}\x{6089}\x{608A}\x{608B}\x{608C}\x{608D}\x{608E}\x{608F}' - . '\x{6090}\x{6092}\x{6094}\x{6095}\x{6096}\x{6097}\x{6098}\x{6099}\x{609A}' - . '\x{609B}\x{609C}\x{609D}\x{609E}\x{609F}\x{60A0}\x{60A1}\x{60A2}\x{60A3}' - . '\x{60A4}\x{60A6}\x{60A7}\x{60A8}\x{60AA}\x{60AB}\x{60AC}\x{60AD}\x{60AE}' - . '\x{60AF}\x{60B0}\x{60B1}\x{60B2}\x{60B3}\x{60B4}\x{60B5}\x{60B6}\x{60B7}' - . '\x{60B8}\x{60B9}\x{60BA}\x{60BB}\x{60BC}\x{60BD}\x{60BE}\x{60BF}\x{60C0}' - . '\x{60C1}\x{60C2}\x{60C3}\x{60C4}\x{60C5}\x{60C6}\x{60C7}\x{60C8}\x{60C9}' - . '\x{60CA}\x{60CB}\x{60CC}\x{60CD}\x{60CE}\x{60CF}\x{60D0}\x{60D1}\x{60D3}' - . '\x{60D4}\x{60D5}\x{60D7}\x{60D8}\x{60D9}\x{60DA}\x{60DB}\x{60DC}\x{60DD}' - . '\x{60DF}\x{60E0}\x{60E1}\x{60E2}\x{60E4}\x{60E6}\x{60E7}\x{60E8}\x{60E9}' - . '\x{60EA}\x{60EB}\x{60EC}\x{60ED}\x{60EE}\x{60EF}\x{60F0}\x{60F1}\x{60F2}' - . '\x{60F3}\x{60F4}\x{60F5}\x{60F6}\x{60F7}\x{60F8}\x{60F9}\x{60FA}\x{60FB}' - . '\x{60FC}\x{60FE}\x{60FF}\x{6100}\x{6101}\x{6103}\x{6104}\x{6105}\x{6106}' - . '\x{6108}\x{6109}\x{610A}\x{610B}\x{610C}\x{610D}\x{610E}\x{610F}\x{6110}' - . '\x{6112}\x{6113}\x{6114}\x{6115}\x{6116}\x{6117}\x{6118}\x{6119}\x{611A}' - . '\x{611B}\x{611C}\x{611D}\x{611F}\x{6120}\x{6122}\x{6123}\x{6124}\x{6125}' - . '\x{6126}\x{6127}\x{6128}\x{6129}\x{612A}\x{612B}\x{612C}\x{612D}\x{612E}' - . '\x{612F}\x{6130}\x{6132}\x{6134}\x{6136}\x{6137}\x{613A}\x{613B}\x{613C}' - . '\x{613D}\x{613E}\x{613F}\x{6140}\x{6141}\x{6142}\x{6143}\x{6144}\x{6145}' - . '\x{6146}\x{6147}\x{6148}\x{6149}\x{614A}\x{614B}\x{614C}\x{614D}\x{614E}' - . '\x{614F}\x{6150}\x{6151}\x{6152}\x{6153}\x{6154}\x{6155}\x{6156}\x{6157}' - . '\x{6158}\x{6159}\x{615A}\x{615B}\x{615C}\x{615D}\x{615E}\x{615F}\x{6161}' - . '\x{6162}\x{6163}\x{6164}\x{6165}\x{6166}\x{6167}\x{6168}\x{6169}\x{616A}' - . '\x{616B}\x{616C}\x{616D}\x{616E}\x{6170}\x{6171}\x{6172}\x{6173}\x{6174}' - . '\x{6175}\x{6176}\x{6177}\x{6178}\x{6179}\x{617A}\x{617C}\x{617E}\x{6180}' - . '\x{6181}\x{6182}\x{6183}\x{6184}\x{6185}\x{6187}\x{6188}\x{6189}\x{618A}' - . '\x{618B}\x{618C}\x{618D}\x{618E}\x{618F}\x{6190}\x{6191}\x{6192}\x{6193}' - . '\x{6194}\x{6195}\x{6196}\x{6198}\x{6199}\x{619A}\x{619B}\x{619D}\x{619E}' - . '\x{619F}\x{61A0}\x{61A1}\x{61A2}\x{61A3}\x{61A4}\x{61A5}\x{61A6}\x{61A7}' - . '\x{61A8}\x{61A9}\x{61AA}\x{61AB}\x{61AC}\x{61AD}\x{61AE}\x{61AF}\x{61B0}' - . '\x{61B1}\x{61B2}\x{61B3}\x{61B4}\x{61B5}\x{61B6}\x{61B7}\x{61B8}\x{61BA}' - . '\x{61BC}\x{61BD}\x{61BE}\x{61BF}\x{61C0}\x{61C1}\x{61C2}\x{61C3}\x{61C4}' - . '\x{61C5}\x{61C6}\x{61C7}\x{61C8}\x{61C9}\x{61CA}\x{61CB}\x{61CC}\x{61CD}' - . '\x{61CE}\x{61CF}\x{61D0}\x{61D1}\x{61D2}\x{61D4}\x{61D6}\x{61D7}\x{61D8}' - . '\x{61D9}\x{61DA}\x{61DB}\x{61DC}\x{61DD}\x{61DE}\x{61DF}\x{61E0}\x{61E1}' - . '\x{61E2}\x{61E3}\x{61E4}\x{61E5}\x{61E6}\x{61E7}\x{61E8}\x{61E9}\x{61EA}' - . '\x{61EB}\x{61ED}\x{61EE}\x{61F0}\x{61F1}\x{61F2}\x{61F3}\x{61F5}\x{61F6}' - . '\x{61F7}\x{61F8}\x{61F9}\x{61FA}\x{61FB}\x{61FC}\x{61FD}\x{61FE}\x{61FF}' - . '\x{6200}\x{6201}\x{6202}\x{6203}\x{6204}\x{6206}\x{6207}\x{6208}\x{6209}' - . '\x{620A}\x{620B}\x{620C}\x{620D}\x{620E}\x{620F}\x{6210}\x{6211}\x{6212}' - . '\x{6213}\x{6214}\x{6215}\x{6216}\x{6217}\x{6218}\x{6219}\x{621A}\x{621B}' - . '\x{621C}\x{621D}\x{621E}\x{621F}\x{6220}\x{6221}\x{6222}\x{6223}\x{6224}' - . '\x{6225}\x{6226}\x{6227}\x{6228}\x{6229}\x{622A}\x{622B}\x{622C}\x{622D}' - . '\x{622E}\x{622F}\x{6230}\x{6231}\x{6232}\x{6233}\x{6234}\x{6236}\x{6237}' - . '\x{6238}\x{623A}\x{623B}\x{623C}\x{623D}\x{623E}\x{623F}\x{6240}\x{6241}' - . '\x{6242}\x{6243}\x{6244}\x{6245}\x{6246}\x{6247}\x{6248}\x{6249}\x{624A}' - . '\x{624B}\x{624C}\x{624D}\x{624E}\x{624F}\x{6250}\x{6251}\x{6252}\x{6253}' - . '\x{6254}\x{6255}\x{6256}\x{6258}\x{6259}\x{625A}\x{625B}\x{625C}\x{625D}' - . '\x{625E}\x{625F}\x{6260}\x{6261}\x{6262}\x{6263}\x{6264}\x{6265}\x{6266}' - . '\x{6267}\x{6268}\x{6269}\x{626A}\x{626B}\x{626C}\x{626D}\x{626E}\x{626F}' - . '\x{6270}\x{6271}\x{6272}\x{6273}\x{6274}\x{6275}\x{6276}\x{6277}\x{6278}' - . '\x{6279}\x{627A}\x{627B}\x{627C}\x{627D}\x{627E}\x{627F}\x{6280}\x{6281}' - . '\x{6283}\x{6284}\x{6285}\x{6286}\x{6287}\x{6288}\x{6289}\x{628A}\x{628B}' - . '\x{628C}\x{628E}\x{628F}\x{6290}\x{6291}\x{6292}\x{6293}\x{6294}\x{6295}' - . '\x{6296}\x{6297}\x{6298}\x{6299}\x{629A}\x{629B}\x{629C}\x{629E}\x{629F}' - . '\x{62A0}\x{62A1}\x{62A2}\x{62A3}\x{62A4}\x{62A5}\x{62A7}\x{62A8}\x{62A9}' - . '\x{62AA}\x{62AB}\x{62AC}\x{62AD}\x{62AE}\x{62AF}\x{62B0}\x{62B1}\x{62B2}' - . '\x{62B3}\x{62B4}\x{62B5}\x{62B6}\x{62B7}\x{62B8}\x{62B9}\x{62BA}\x{62BB}' - . '\x{62BC}\x{62BD}\x{62BE}\x{62BF}\x{62C0}\x{62C1}\x{62C2}\x{62C3}\x{62C4}' - . '\x{62C5}\x{62C6}\x{62C7}\x{62C8}\x{62C9}\x{62CA}\x{62CB}\x{62CC}\x{62CD}' - . '\x{62CE}\x{62CF}\x{62D0}\x{62D1}\x{62D2}\x{62D3}\x{62D4}\x{62D5}\x{62D6}' - . '\x{62D7}\x{62D8}\x{62D9}\x{62DA}\x{62DB}\x{62DC}\x{62DD}\x{62DF}\x{62E0}' - . '\x{62E1}\x{62E2}\x{62E3}\x{62E4}\x{62E5}\x{62E6}\x{62E7}\x{62E8}\x{62E9}' - . '\x{62EB}\x{62EC}\x{62ED}\x{62EE}\x{62EF}\x{62F0}\x{62F1}\x{62F2}\x{62F3}' - . '\x{62F4}\x{62F5}\x{62F6}\x{62F7}\x{62F8}\x{62F9}\x{62FA}\x{62FB}\x{62FC}' - . '\x{62FD}\x{62FE}\x{62FF}\x{6300}\x{6301}\x{6302}\x{6303}\x{6304}\x{6305}' - . '\x{6306}\x{6307}\x{6308}\x{6309}\x{630B}\x{630C}\x{630D}\x{630E}\x{630F}' - . '\x{6310}\x{6311}\x{6312}\x{6313}\x{6314}\x{6315}\x{6316}\x{6318}\x{6319}' - . '\x{631A}\x{631B}\x{631C}\x{631D}\x{631E}\x{631F}\x{6320}\x{6321}\x{6322}' - . '\x{6323}\x{6324}\x{6325}\x{6326}\x{6327}\x{6328}\x{6329}\x{632A}\x{632B}' - . '\x{632C}\x{632D}\x{632E}\x{632F}\x{6330}\x{6332}\x{6333}\x{6334}\x{6336}' - . '\x{6338}\x{6339}\x{633A}\x{633B}\x{633C}\x{633D}\x{633E}\x{6340}\x{6341}' - . '\x{6342}\x{6343}\x{6344}\x{6345}\x{6346}\x{6347}\x{6348}\x{6349}\x{634A}' - . '\x{634B}\x{634C}\x{634D}\x{634E}\x{634F}\x{6350}\x{6351}\x{6352}\x{6353}' - . '\x{6354}\x{6355}\x{6356}\x{6357}\x{6358}\x{6359}\x{635A}\x{635C}\x{635D}' - . '\x{635E}\x{635F}\x{6360}\x{6361}\x{6362}\x{6363}\x{6364}\x{6365}\x{6366}' - . '\x{6367}\x{6368}\x{6369}\x{636A}\x{636B}\x{636C}\x{636D}\x{636E}\x{636F}' - . '\x{6370}\x{6371}\x{6372}\x{6373}\x{6374}\x{6375}\x{6376}\x{6377}\x{6378}' - . '\x{6379}\x{637A}\x{637B}\x{637C}\x{637D}\x{637E}\x{6380}\x{6381}\x{6382}' - . '\x{6383}\x{6384}\x{6385}\x{6386}\x{6387}\x{6388}\x{6389}\x{638A}\x{638C}' - . '\x{638D}\x{638E}\x{638F}\x{6390}\x{6391}\x{6392}\x{6394}\x{6395}\x{6396}' - . '\x{6397}\x{6398}\x{6399}\x{639A}\x{639B}\x{639C}\x{639D}\x{639E}\x{639F}' - . '\x{63A0}\x{63A1}\x{63A2}\x{63A3}\x{63A4}\x{63A5}\x{63A6}\x{63A7}\x{63A8}' - . '\x{63A9}\x{63AA}\x{63AB}\x{63AC}\x{63AD}\x{63AE}\x{63AF}\x{63B0}\x{63B1}' - . '\x{63B2}\x{63B3}\x{63B4}\x{63B5}\x{63B6}\x{63B7}\x{63B8}\x{63B9}\x{63BA}' - . '\x{63BC}\x{63BD}\x{63BE}\x{63BF}\x{63C0}\x{63C1}\x{63C2}\x{63C3}\x{63C4}' - . '\x{63C5}\x{63C6}\x{63C7}\x{63C8}\x{63C9}\x{63CA}\x{63CB}\x{63CC}\x{63CD}' - . '\x{63CE}\x{63CF}\x{63D0}\x{63D2}\x{63D3}\x{63D4}\x{63D5}\x{63D6}\x{63D7}' - . '\x{63D8}\x{63D9}\x{63DA}\x{63DB}\x{63DC}\x{63DD}\x{63DE}\x{63DF}\x{63E0}' - . '\x{63E1}\x{63E2}\x{63E3}\x{63E4}\x{63E5}\x{63E6}\x{63E7}\x{63E8}\x{63E9}' - . '\x{63EA}\x{63EB}\x{63EC}\x{63ED}\x{63EE}\x{63EF}\x{63F0}\x{63F1}\x{63F2}' - . '\x{63F3}\x{63F4}\x{63F5}\x{63F6}\x{63F7}\x{63F8}\x{63F9}\x{63FA}\x{63FB}' - . '\x{63FC}\x{63FD}\x{63FE}\x{63FF}\x{6400}\x{6401}\x{6402}\x{6403}\x{6404}' - . '\x{6405}\x{6406}\x{6408}\x{6409}\x{640A}\x{640B}\x{640C}\x{640D}\x{640E}' - . '\x{640F}\x{6410}\x{6411}\x{6412}\x{6413}\x{6414}\x{6415}\x{6416}\x{6417}' - . '\x{6418}\x{6419}\x{641A}\x{641B}\x{641C}\x{641D}\x{641E}\x{641F}\x{6420}' - . '\x{6421}\x{6422}\x{6423}\x{6424}\x{6425}\x{6426}\x{6427}\x{6428}\x{6429}' - . '\x{642A}\x{642B}\x{642C}\x{642D}\x{642E}\x{642F}\x{6430}\x{6431}\x{6432}' - . '\x{6433}\x{6434}\x{6435}\x{6436}\x{6437}\x{6438}\x{6439}\x{643A}\x{643D}' - . '\x{643E}\x{643F}\x{6440}\x{6441}\x{6443}\x{6444}\x{6445}\x{6446}\x{6447}' - . '\x{6448}\x{644A}\x{644B}\x{644C}\x{644D}\x{644E}\x{644F}\x{6450}\x{6451}' - . '\x{6452}\x{6453}\x{6454}\x{6455}\x{6456}\x{6457}\x{6458}\x{6459}\x{645B}' - . '\x{645C}\x{645D}\x{645E}\x{645F}\x{6460}\x{6461}\x{6462}\x{6463}\x{6464}' - . '\x{6465}\x{6466}\x{6467}\x{6468}\x{6469}\x{646A}\x{646B}\x{646C}\x{646D}' - . '\x{646E}\x{646F}\x{6470}\x{6471}\x{6472}\x{6473}\x{6474}\x{6475}\x{6476}' - . '\x{6477}\x{6478}\x{6479}\x{647A}\x{647B}\x{647C}\x{647D}\x{647F}\x{6480}' - . '\x{6481}\x{6482}\x{6483}\x{6484}\x{6485}\x{6487}\x{6488}\x{6489}\x{648A}' - . '\x{648B}\x{648C}\x{648D}\x{648E}\x{648F}\x{6490}\x{6491}\x{6492}\x{6493}' - . '\x{6494}\x{6495}\x{6496}\x{6497}\x{6498}\x{6499}\x{649A}\x{649B}\x{649C}' - . '\x{649D}\x{649E}\x{649F}\x{64A0}\x{64A2}\x{64A3}\x{64A4}\x{64A5}\x{64A6}' - . '\x{64A7}\x{64A8}\x{64A9}\x{64AA}\x{64AB}\x{64AC}\x{64AD}\x{64AE}\x{64B0}' - . '\x{64B1}\x{64B2}\x{64B3}\x{64B4}\x{64B5}\x{64B7}\x{64B8}\x{64B9}\x{64BA}' - . '\x{64BB}\x{64BC}\x{64BD}\x{64BE}\x{64BF}\x{64C0}\x{64C1}\x{64C2}\x{64C3}' - . '\x{64C4}\x{64C5}\x{64C6}\x{64C7}\x{64C9}\x{64CA}\x{64CB}\x{64CC}\x{64CD}' - . '\x{64CE}\x{64CF}\x{64D0}\x{64D1}\x{64D2}\x{64D3}\x{64D4}\x{64D6}\x{64D7}' - . '\x{64D8}\x{64D9}\x{64DA}\x{64DB}\x{64DC}\x{64DD}\x{64DE}\x{64DF}\x{64E0}' - . '\x{64E2}\x{64E3}\x{64E4}\x{64E6}\x{64E7}\x{64E8}\x{64E9}\x{64EA}\x{64EB}' - . '\x{64EC}\x{64ED}\x{64EF}\x{64F0}\x{64F1}\x{64F2}\x{64F3}\x{64F4}\x{64F6}' - . '\x{64F7}\x{64F8}\x{64FA}\x{64FB}\x{64FC}\x{64FD}\x{64FE}\x{64FF}\x{6500}' - . '\x{6501}\x{6503}\x{6504}\x{6505}\x{6506}\x{6507}\x{6508}\x{6509}\x{650B}' - . '\x{650C}\x{650D}\x{650E}\x{650F}\x{6510}\x{6511}\x{6512}\x{6513}\x{6514}' - . '\x{6515}\x{6516}\x{6517}\x{6518}\x{6519}\x{651A}\x{651B}\x{651C}\x{651D}' - . '\x{651E}\x{6520}\x{6521}\x{6522}\x{6523}\x{6524}\x{6525}\x{6526}\x{6527}' - . '\x{6529}\x{652A}\x{652B}\x{652C}\x{652D}\x{652E}\x{652F}\x{6530}\x{6531}' - . '\x{6532}\x{6533}\x{6534}\x{6535}\x{6536}\x{6537}\x{6538}\x{6539}\x{653A}' - . '\x{653B}\x{653C}\x{653D}\x{653E}\x{653F}\x{6541}\x{6543}\x{6544}\x{6545}' - . '\x{6546}\x{6547}\x{6548}\x{6549}\x{654A}\x{654B}\x{654C}\x{654D}\x{654E}' - . '\x{654F}\x{6550}\x{6551}\x{6552}\x{6553}\x{6554}\x{6555}\x{6556}\x{6557}' - . '\x{6558}\x{6559}\x{655B}\x{655C}\x{655D}\x{655E}\x{6560}\x{6561}\x{6562}' - . '\x{6563}\x{6564}\x{6565}\x{6566}\x{6567}\x{6568}\x{6569}\x{656A}\x{656B}' - . '\x{656C}\x{656E}\x{656F}\x{6570}\x{6571}\x{6572}\x{6573}\x{6574}\x{6575}' - . '\x{6576}\x{6577}\x{6578}\x{6579}\x{657A}\x{657B}\x{657C}\x{657E}\x{657F}' - . '\x{6580}\x{6581}\x{6582}\x{6583}\x{6584}\x{6585}\x{6586}\x{6587}\x{6588}' - . '\x{6589}\x{658B}\x{658C}\x{658D}\x{658E}\x{658F}\x{6590}\x{6591}\x{6592}' - . '\x{6593}\x{6594}\x{6595}\x{6596}\x{6597}\x{6598}\x{6599}\x{659B}\x{659C}' - . '\x{659D}\x{659E}\x{659F}\x{65A0}\x{65A1}\x{65A2}\x{65A3}\x{65A4}\x{65A5}' - . '\x{65A6}\x{65A7}\x{65A8}\x{65A9}\x{65AA}\x{65AB}\x{65AC}\x{65AD}\x{65AE}' - . '\x{65AF}\x{65B0}\x{65B1}\x{65B2}\x{65B3}\x{65B4}\x{65B6}\x{65B7}\x{65B8}' - . '\x{65B9}\x{65BA}\x{65BB}\x{65BC}\x{65BD}\x{65BF}\x{65C0}\x{65C1}\x{65C2}' - . '\x{65C3}\x{65C4}\x{65C5}\x{65C6}\x{65C7}\x{65CA}\x{65CB}\x{65CC}\x{65CD}' - . '\x{65CE}\x{65CF}\x{65D0}\x{65D2}\x{65D3}\x{65D4}\x{65D5}\x{65D6}\x{65D7}' - . '\x{65DA}\x{65DB}\x{65DD}\x{65DE}\x{65DF}\x{65E0}\x{65E1}\x{65E2}\x{65E3}' - . '\x{65E5}\x{65E6}\x{65E7}\x{65E8}\x{65E9}\x{65EB}\x{65EC}\x{65ED}\x{65EE}' - . '\x{65EF}\x{65F0}\x{65F1}\x{65F2}\x{65F3}\x{65F4}\x{65F5}\x{65F6}\x{65F7}' - . '\x{65F8}\x{65FA}\x{65FB}\x{65FC}\x{65FD}\x{6600}\x{6601}\x{6602}\x{6603}' - . '\x{6604}\x{6605}\x{6606}\x{6607}\x{6608}\x{6609}\x{660A}\x{660B}\x{660C}' - . '\x{660D}\x{660E}\x{660F}\x{6610}\x{6611}\x{6612}\x{6613}\x{6614}\x{6615}' - . '\x{6616}\x{6618}\x{6619}\x{661A}\x{661B}\x{661C}\x{661D}\x{661F}\x{6620}' - . '\x{6621}\x{6622}\x{6623}\x{6624}\x{6625}\x{6626}\x{6627}\x{6628}\x{6629}' - . '\x{662A}\x{662B}\x{662D}\x{662E}\x{662F}\x{6630}\x{6631}\x{6632}\x{6633}' - . '\x{6634}\x{6635}\x{6636}\x{6639}\x{663A}\x{663C}\x{663D}\x{663E}\x{6640}' - . '\x{6641}\x{6642}\x{6643}\x{6644}\x{6645}\x{6646}\x{6647}\x{6649}\x{664A}' - . '\x{664B}\x{664C}\x{664E}\x{664F}\x{6650}\x{6651}\x{6652}\x{6653}\x{6654}' - . '\x{6655}\x{6656}\x{6657}\x{6658}\x{6659}\x{665A}\x{665B}\x{665C}\x{665D}' - . '\x{665E}\x{665F}\x{6661}\x{6662}\x{6664}\x{6665}\x{6666}\x{6668}\x{6669}' - . '\x{666A}\x{666B}\x{666C}\x{666D}\x{666E}\x{666F}\x{6670}\x{6671}\x{6672}' - . '\x{6673}\x{6674}\x{6675}\x{6676}\x{6677}\x{6678}\x{6679}\x{667A}\x{667B}' - . '\x{667C}\x{667D}\x{667E}\x{667F}\x{6680}\x{6681}\x{6682}\x{6683}\x{6684}' - . '\x{6685}\x{6686}\x{6687}\x{6688}\x{6689}\x{668A}\x{668B}\x{668C}\x{668D}' - . '\x{668E}\x{668F}\x{6690}\x{6691}\x{6693}\x{6694}\x{6695}\x{6696}\x{6697}' - . '\x{6698}\x{6699}\x{669A}\x{669B}\x{669D}\x{669F}\x{66A0}\x{66A1}\x{66A2}' - . '\x{66A3}\x{66A4}\x{66A5}\x{66A6}\x{66A7}\x{66A8}\x{66A9}\x{66AA}\x{66AB}' - . '\x{66AE}\x{66AF}\x{66B0}\x{66B1}\x{66B2}\x{66B3}\x{66B4}\x{66B5}\x{66B6}' - . '\x{66B7}\x{66B8}\x{66B9}\x{66BA}\x{66BB}\x{66BC}\x{66BD}\x{66BE}\x{66BF}' - . '\x{66C0}\x{66C1}\x{66C2}\x{66C3}\x{66C4}\x{66C5}\x{66C6}\x{66C7}\x{66C8}' - . '\x{66C9}\x{66CA}\x{66CB}\x{66CC}\x{66CD}\x{66CE}\x{66CF}\x{66D1}\x{66D2}' - . '\x{66D4}\x{66D5}\x{66D6}\x{66D8}\x{66D9}\x{66DA}\x{66DB}\x{66DC}\x{66DD}' - . '\x{66DE}\x{66E0}\x{66E1}\x{66E2}\x{66E3}\x{66E4}\x{66E5}\x{66E6}\x{66E7}' - . '\x{66E8}\x{66E9}\x{66EA}\x{66EB}\x{66EC}\x{66ED}\x{66EE}\x{66F0}\x{66F1}' - . '\x{66F2}\x{66F3}\x{66F4}\x{66F5}\x{66F6}\x{66F7}\x{66F8}\x{66F9}\x{66FA}' - . '\x{66FB}\x{66FC}\x{66FE}\x{66FF}\x{6700}\x{6701}\x{6703}\x{6704}\x{6705}' - . '\x{6706}\x{6708}\x{6709}\x{670A}\x{670B}\x{670C}\x{670D}\x{670E}\x{670F}' - . '\x{6710}\x{6711}\x{6712}\x{6713}\x{6714}\x{6715}\x{6716}\x{6717}\x{6718}' - . '\x{671A}\x{671B}\x{671C}\x{671D}\x{671E}\x{671F}\x{6720}\x{6721}\x{6722}' - . '\x{6723}\x{6725}\x{6726}\x{6727}\x{6728}\x{672A}\x{672B}\x{672C}\x{672D}' - . '\x{672E}\x{672F}\x{6730}\x{6731}\x{6732}\x{6733}\x{6734}\x{6735}\x{6736}' - . '\x{6737}\x{6738}\x{6739}\x{673A}\x{673B}\x{673C}\x{673D}\x{673E}\x{673F}' - . '\x{6740}\x{6741}\x{6742}\x{6743}\x{6744}\x{6745}\x{6746}\x{6747}\x{6748}' - . '\x{6749}\x{674A}\x{674B}\x{674C}\x{674D}\x{674E}\x{674F}\x{6750}\x{6751}' - . '\x{6752}\x{6753}\x{6754}\x{6755}\x{6756}\x{6757}\x{6758}\x{6759}\x{675A}' - . '\x{675B}\x{675C}\x{675D}\x{675E}\x{675F}\x{6760}\x{6761}\x{6762}\x{6763}' - . '\x{6764}\x{6765}\x{6766}\x{6768}\x{6769}\x{676A}\x{676B}\x{676C}\x{676D}' - . '\x{676E}\x{676F}\x{6770}\x{6771}\x{6772}\x{6773}\x{6774}\x{6775}\x{6776}' - . '\x{6777}\x{6778}\x{6779}\x{677A}\x{677B}\x{677C}\x{677D}\x{677E}\x{677F}' - . '\x{6780}\x{6781}\x{6782}\x{6783}\x{6784}\x{6785}\x{6786}\x{6787}\x{6789}' - . '\x{678A}\x{678B}\x{678C}\x{678D}\x{678E}\x{678F}\x{6790}\x{6791}\x{6792}' - . '\x{6793}\x{6794}\x{6795}\x{6797}\x{6798}\x{6799}\x{679A}\x{679B}\x{679C}' - . '\x{679D}\x{679E}\x{679F}\x{67A0}\x{67A1}\x{67A2}\x{67A3}\x{67A4}\x{67A5}' - . '\x{67A6}\x{67A7}\x{67A8}\x{67AA}\x{67AB}\x{67AC}\x{67AD}\x{67AE}\x{67AF}' - . '\x{67B0}\x{67B1}\x{67B2}\x{67B3}\x{67B4}\x{67B5}\x{67B6}\x{67B7}\x{67B8}' - . '\x{67B9}\x{67BA}\x{67BB}\x{67BC}\x{67BE}\x{67C0}\x{67C1}\x{67C2}\x{67C3}' - . '\x{67C4}\x{67C5}\x{67C6}\x{67C7}\x{67C8}\x{67C9}\x{67CA}\x{67CB}\x{67CC}' - . '\x{67CD}\x{67CE}\x{67CF}\x{67D0}\x{67D1}\x{67D2}\x{67D3}\x{67D4}\x{67D6}' - . '\x{67D8}\x{67D9}\x{67DA}\x{67DB}\x{67DC}\x{67DD}\x{67DE}\x{67DF}\x{67E0}' - . '\x{67E1}\x{67E2}\x{67E3}\x{67E4}\x{67E5}\x{67E6}\x{67E7}\x{67E8}\x{67E9}' - . '\x{67EA}\x{67EB}\x{67EC}\x{67ED}\x{67EE}\x{67EF}\x{67F0}\x{67F1}\x{67F2}' - . '\x{67F3}\x{67F4}\x{67F5}\x{67F6}\x{67F7}\x{67F8}\x{67FA}\x{67FB}\x{67FC}' - . '\x{67FD}\x{67FE}\x{67FF}\x{6800}\x{6802}\x{6803}\x{6804}\x{6805}\x{6806}' - . '\x{6807}\x{6808}\x{6809}\x{680A}\x{680B}\x{680C}\x{680D}\x{680E}\x{680F}' - . '\x{6810}\x{6811}\x{6812}\x{6813}\x{6814}\x{6816}\x{6817}\x{6818}\x{6819}' - . '\x{681A}\x{681B}\x{681C}\x{681D}\x{681F}\x{6820}\x{6821}\x{6822}\x{6823}' - . '\x{6824}\x{6825}\x{6826}\x{6828}\x{6829}\x{682A}\x{682B}\x{682C}\x{682D}' - . '\x{682E}\x{682F}\x{6831}\x{6832}\x{6833}\x{6834}\x{6835}\x{6836}\x{6837}' - . '\x{6838}\x{6839}\x{683A}\x{683B}\x{683C}\x{683D}\x{683E}\x{683F}\x{6840}' - . '\x{6841}\x{6842}\x{6843}\x{6844}\x{6845}\x{6846}\x{6847}\x{6848}\x{6849}' - . '\x{684A}\x{684B}\x{684C}\x{684D}\x{684E}\x{684F}\x{6850}\x{6851}\x{6852}' - . '\x{6853}\x{6854}\x{6855}\x{6856}\x{6857}\x{685B}\x{685D}\x{6860}\x{6861}' - . '\x{6862}\x{6863}\x{6864}\x{6865}\x{6866}\x{6867}\x{6868}\x{6869}\x{686A}' - . '\x{686B}\x{686C}\x{686D}\x{686E}\x{686F}\x{6870}\x{6871}\x{6872}\x{6873}' - . '\x{6874}\x{6875}\x{6876}\x{6877}\x{6878}\x{6879}\x{687B}\x{687C}\x{687D}' - . '\x{687E}\x{687F}\x{6880}\x{6881}\x{6882}\x{6883}\x{6884}\x{6885}\x{6886}' - . '\x{6887}\x{6888}\x{6889}\x{688A}\x{688B}\x{688C}\x{688D}\x{688E}\x{688F}' - . '\x{6890}\x{6891}\x{6892}\x{6893}\x{6894}\x{6896}\x{6897}\x{6898}\x{689A}' - . '\x{689B}\x{689C}\x{689D}\x{689E}\x{689F}\x{68A0}\x{68A1}\x{68A2}\x{68A3}' - . '\x{68A4}\x{68A6}\x{68A7}\x{68A8}\x{68A9}\x{68AA}\x{68AB}\x{68AC}\x{68AD}' - . '\x{68AE}\x{68AF}\x{68B0}\x{68B1}\x{68B2}\x{68B3}\x{68B4}\x{68B5}\x{68B6}' - . '\x{68B7}\x{68B9}\x{68BB}\x{68BC}\x{68BD}\x{68BE}\x{68BF}\x{68C0}\x{68C1}' - . '\x{68C2}\x{68C4}\x{68C6}\x{68C7}\x{68C8}\x{68C9}\x{68CA}\x{68CB}\x{68CC}' - . '\x{68CD}\x{68CE}\x{68CF}\x{68D0}\x{68D1}\x{68D2}\x{68D3}\x{68D4}\x{68D5}' - . '\x{68D6}\x{68D7}\x{68D8}\x{68DA}\x{68DB}\x{68DC}\x{68DD}\x{68DE}\x{68DF}' - . '\x{68E0}\x{68E1}\x{68E3}\x{68E4}\x{68E6}\x{68E7}\x{68E8}\x{68E9}\x{68EA}' - . '\x{68EB}\x{68EC}\x{68ED}\x{68EE}\x{68EF}\x{68F0}\x{68F1}\x{68F2}\x{68F3}' - . '\x{68F4}\x{68F5}\x{68F6}\x{68F7}\x{68F8}\x{68F9}\x{68FA}\x{68FB}\x{68FC}' - . '\x{68FD}\x{68FE}\x{68FF}\x{6901}\x{6902}\x{6903}\x{6904}\x{6905}\x{6906}' - . '\x{6907}\x{6908}\x{690A}\x{690B}\x{690C}\x{690D}\x{690E}\x{690F}\x{6910}' - . '\x{6911}\x{6912}\x{6913}\x{6914}\x{6915}\x{6916}\x{6917}\x{6918}\x{6919}' - . '\x{691A}\x{691B}\x{691C}\x{691D}\x{691E}\x{691F}\x{6920}\x{6921}\x{6922}' - . '\x{6923}\x{6924}\x{6925}\x{6926}\x{6927}\x{6928}\x{6929}\x{692A}\x{692B}' - . '\x{692C}\x{692D}\x{692E}\x{692F}\x{6930}\x{6931}\x{6932}\x{6933}\x{6934}' - . '\x{6935}\x{6936}\x{6937}\x{6938}\x{6939}\x{693A}\x{693B}\x{693C}\x{693D}' - . '\x{693F}\x{6940}\x{6941}\x{6942}\x{6943}\x{6944}\x{6945}\x{6946}\x{6947}' - . '\x{6948}\x{6949}\x{694A}\x{694B}\x{694C}\x{694E}\x{694F}\x{6950}\x{6951}' - . '\x{6952}\x{6953}\x{6954}\x{6955}\x{6956}\x{6957}\x{6958}\x{6959}\x{695A}' - . '\x{695B}\x{695C}\x{695D}\x{695E}\x{695F}\x{6960}\x{6961}\x{6962}\x{6963}' - . '\x{6964}\x{6965}\x{6966}\x{6967}\x{6968}\x{6969}\x{696A}\x{696B}\x{696C}' - . '\x{696D}\x{696E}\x{696F}\x{6970}\x{6971}\x{6972}\x{6973}\x{6974}\x{6975}' - . '\x{6976}\x{6977}\x{6978}\x{6979}\x{697A}\x{697B}\x{697C}\x{697D}\x{697E}' - . '\x{697F}\x{6980}\x{6981}\x{6982}\x{6983}\x{6984}\x{6985}\x{6986}\x{6987}' - . '\x{6988}\x{6989}\x{698A}\x{698B}\x{698C}\x{698D}\x{698E}\x{698F}\x{6990}' - . '\x{6991}\x{6992}\x{6993}\x{6994}\x{6995}\x{6996}\x{6997}\x{6998}\x{6999}' - . '\x{699A}\x{699B}\x{699C}\x{699D}\x{699E}\x{69A0}\x{69A1}\x{69A3}\x{69A4}' - . '\x{69A5}\x{69A6}\x{69A7}\x{69A8}\x{69A9}\x{69AA}\x{69AB}\x{69AC}\x{69AD}' - . '\x{69AE}\x{69AF}\x{69B0}\x{69B1}\x{69B2}\x{69B3}\x{69B4}\x{69B5}\x{69B6}' - . '\x{69B7}\x{69B8}\x{69B9}\x{69BA}\x{69BB}\x{69BC}\x{69BD}\x{69BE}\x{69BF}' - . '\x{69C1}\x{69C2}\x{69C3}\x{69C4}\x{69C5}\x{69C6}\x{69C7}\x{69C8}\x{69C9}' - . '\x{69CA}\x{69CB}\x{69CC}\x{69CD}\x{69CE}\x{69CF}\x{69D0}\x{69D3}\x{69D4}' - . '\x{69D8}\x{69D9}\x{69DA}\x{69DB}\x{69DC}\x{69DD}\x{69DE}\x{69DF}\x{69E0}' - . '\x{69E1}\x{69E2}\x{69E3}\x{69E4}\x{69E5}\x{69E6}\x{69E7}\x{69E8}\x{69E9}' - . '\x{69EA}\x{69EB}\x{69EC}\x{69ED}\x{69EE}\x{69EF}\x{69F0}\x{69F1}\x{69F2}' - . '\x{69F3}\x{69F4}\x{69F5}\x{69F6}\x{69F7}\x{69F8}\x{69FA}\x{69FB}\x{69FC}' - . '\x{69FD}\x{69FE}\x{69FF}\x{6A00}\x{6A01}\x{6A02}\x{6A04}\x{6A05}\x{6A06}' - . '\x{6A07}\x{6A08}\x{6A09}\x{6A0A}\x{6A0B}\x{6A0D}\x{6A0E}\x{6A0F}\x{6A10}' - . '\x{6A11}\x{6A12}\x{6A13}\x{6A14}\x{6A15}\x{6A16}\x{6A17}\x{6A18}\x{6A19}' - . '\x{6A1A}\x{6A1B}\x{6A1D}\x{6A1E}\x{6A1F}\x{6A20}\x{6A21}\x{6A22}\x{6A23}' - . '\x{6A25}\x{6A26}\x{6A27}\x{6A28}\x{6A29}\x{6A2A}\x{6A2B}\x{6A2C}\x{6A2D}' - . '\x{6A2E}\x{6A2F}\x{6A30}\x{6A31}\x{6A32}\x{6A33}\x{6A34}\x{6A35}\x{6A36}' - . '\x{6A38}\x{6A39}\x{6A3A}\x{6A3B}\x{6A3C}\x{6A3D}\x{6A3E}\x{6A3F}\x{6A40}' - . '\x{6A41}\x{6A42}\x{6A43}\x{6A44}\x{6A45}\x{6A46}\x{6A47}\x{6A48}\x{6A49}' - . '\x{6A4B}\x{6A4C}\x{6A4D}\x{6A4E}\x{6A4F}\x{6A50}\x{6A51}\x{6A52}\x{6A54}' - . '\x{6A55}\x{6A56}\x{6A57}\x{6A58}\x{6A59}\x{6A5A}\x{6A5B}\x{6A5D}\x{6A5E}' - . '\x{6A5F}\x{6A60}\x{6A61}\x{6A62}\x{6A63}\x{6A64}\x{6A65}\x{6A66}\x{6A67}' - . '\x{6A68}\x{6A69}\x{6A6A}\x{6A6B}\x{6A6C}\x{6A6D}\x{6A6F}\x{6A71}\x{6A72}' - . '\x{6A73}\x{6A74}\x{6A75}\x{6A76}\x{6A77}\x{6A78}\x{6A79}\x{6A7A}\x{6A7B}' - . '\x{6A7C}\x{6A7D}\x{6A7E}\x{6A7F}\x{6A80}\x{6A81}\x{6A82}\x{6A83}\x{6A84}' - . '\x{6A85}\x{6A87}\x{6A88}\x{6A89}\x{6A8B}\x{6A8C}\x{6A8D}\x{6A8E}\x{6A90}' - . '\x{6A91}\x{6A92}\x{6A93}\x{6A94}\x{6A95}\x{6A96}\x{6A97}\x{6A98}\x{6A9A}' - . '\x{6A9B}\x{6A9C}\x{6A9E}\x{6A9F}\x{6AA0}\x{6AA1}\x{6AA2}\x{6AA3}\x{6AA4}' - . '\x{6AA5}\x{6AA6}\x{6AA7}\x{6AA8}\x{6AA9}\x{6AAB}\x{6AAC}\x{6AAD}\x{6AAE}' - . '\x{6AAF}\x{6AB0}\x{6AB2}\x{6AB3}\x{6AB4}\x{6AB5}\x{6AB6}\x{6AB7}\x{6AB8}' - . '\x{6AB9}\x{6ABA}\x{6ABB}\x{6ABC}\x{6ABD}\x{6ABF}\x{6AC1}\x{6AC2}\x{6AC3}' - . '\x{6AC5}\x{6AC6}\x{6AC7}\x{6ACA}\x{6ACB}\x{6ACC}\x{6ACD}\x{6ACE}\x{6ACF}' - . '\x{6AD0}\x{6AD1}\x{6AD2}\x{6AD3}\x{6AD4}\x{6AD5}\x{6AD6}\x{6AD7}\x{6AD9}' - . '\x{6ADA}\x{6ADB}\x{6ADC}\x{6ADD}\x{6ADE}\x{6ADF}\x{6AE0}\x{6AE1}\x{6AE2}' - . '\x{6AE3}\x{6AE4}\x{6AE5}\x{6AE6}\x{6AE7}\x{6AE8}\x{6AEA}\x{6AEB}\x{6AEC}' - . '\x{6AED}\x{6AEE}\x{6AEF}\x{6AF0}\x{6AF1}\x{6AF2}\x{6AF3}\x{6AF4}\x{6AF5}' - . '\x{6AF6}\x{6AF7}\x{6AF8}\x{6AF9}\x{6AFA}\x{6AFB}\x{6AFC}\x{6AFD}\x{6AFE}' - . '\x{6AFF}\x{6B00}\x{6B01}\x{6B02}\x{6B03}\x{6B04}\x{6B05}\x{6B06}\x{6B07}' - . '\x{6B08}\x{6B09}\x{6B0A}\x{6B0B}\x{6B0C}\x{6B0D}\x{6B0F}\x{6B10}\x{6B11}' - . '\x{6B12}\x{6B13}\x{6B14}\x{6B15}\x{6B16}\x{6B17}\x{6B18}\x{6B19}\x{6B1A}' - . '\x{6B1C}\x{6B1D}\x{6B1E}\x{6B1F}\x{6B20}\x{6B21}\x{6B22}\x{6B23}\x{6B24}' - . '\x{6B25}\x{6B26}\x{6B27}\x{6B28}\x{6B29}\x{6B2A}\x{6B2B}\x{6B2C}\x{6B2D}' - . '\x{6B2F}\x{6B30}\x{6B31}\x{6B32}\x{6B33}\x{6B34}\x{6B36}\x{6B37}\x{6B38}' - . '\x{6B39}\x{6B3A}\x{6B3B}\x{6B3C}\x{6B3D}\x{6B3E}\x{6B3F}\x{6B41}\x{6B42}' - . '\x{6B43}\x{6B44}\x{6B45}\x{6B46}\x{6B47}\x{6B48}\x{6B49}\x{6B4A}\x{6B4B}' - . '\x{6B4C}\x{6B4D}\x{6B4E}\x{6B4F}\x{6B50}\x{6B51}\x{6B52}\x{6B53}\x{6B54}' - . '\x{6B55}\x{6B56}\x{6B59}\x{6B5A}\x{6B5B}\x{6B5C}\x{6B5E}\x{6B5F}\x{6B60}' - . '\x{6B61}\x{6B62}\x{6B63}\x{6B64}\x{6B65}\x{6B66}\x{6B67}\x{6B69}\x{6B6A}' - . '\x{6B6B}\x{6B6D}\x{6B6F}\x{6B70}\x{6B72}\x{6B73}\x{6B74}\x{6B76}\x{6B77}' - . '\x{6B78}\x{6B79}\x{6B7A}\x{6B7B}\x{6B7C}\x{6B7E}\x{6B7F}\x{6B80}\x{6B81}' - . '\x{6B82}\x{6B83}\x{6B84}\x{6B85}\x{6B86}\x{6B87}\x{6B88}\x{6B89}\x{6B8A}' - . '\x{6B8B}\x{6B8C}\x{6B8D}\x{6B8E}\x{6B8F}\x{6B90}\x{6B91}\x{6B92}\x{6B93}' - . '\x{6B94}\x{6B95}\x{6B96}\x{6B97}\x{6B98}\x{6B99}\x{6B9A}\x{6B9B}\x{6B9C}' - . '\x{6B9D}\x{6B9E}\x{6B9F}\x{6BA0}\x{6BA1}\x{6BA2}\x{6BA3}\x{6BA4}\x{6BA5}' - . '\x{6BA6}\x{6BA7}\x{6BA8}\x{6BA9}\x{6BAA}\x{6BAB}\x{6BAC}\x{6BAD}\x{6BAE}' - . '\x{6BAF}\x{6BB0}\x{6BB2}\x{6BB3}\x{6BB4}\x{6BB5}\x{6BB6}\x{6BB7}\x{6BB9}' - . '\x{6BBA}\x{6BBB}\x{6BBC}\x{6BBD}\x{6BBE}\x{6BBF}\x{6BC0}\x{6BC1}\x{6BC2}' - . '\x{6BC3}\x{6BC4}\x{6BC5}\x{6BC6}\x{6BC7}\x{6BC8}\x{6BC9}\x{6BCA}\x{6BCB}' - . '\x{6BCC}\x{6BCD}\x{6BCE}\x{6BCF}\x{6BD0}\x{6BD1}\x{6BD2}\x{6BD3}\x{6BD4}' - . '\x{6BD5}\x{6BD6}\x{6BD7}\x{6BD8}\x{6BD9}\x{6BDA}\x{6BDB}\x{6BDC}\x{6BDD}' - . '\x{6BDE}\x{6BDF}\x{6BE0}\x{6BE1}\x{6BE2}\x{6BE3}\x{6BE4}\x{6BE5}\x{6BE6}' - . '\x{6BE7}\x{6BE8}\x{6BEA}\x{6BEB}\x{6BEC}\x{6BED}\x{6BEE}\x{6BEF}\x{6BF0}' - . '\x{6BF2}\x{6BF3}\x{6BF5}\x{6BF6}\x{6BF7}\x{6BF8}\x{6BF9}\x{6BFB}\x{6BFC}' - . '\x{6BFD}\x{6BFE}\x{6BFF}\x{6C00}\x{6C01}\x{6C02}\x{6C03}\x{6C04}\x{6C05}' - . '\x{6C06}\x{6C07}\x{6C08}\x{6C09}\x{6C0B}\x{6C0C}\x{6C0D}\x{6C0E}\x{6C0F}' - . '\x{6C10}\x{6C11}\x{6C12}\x{6C13}\x{6C14}\x{6C15}\x{6C16}\x{6C18}\x{6C19}' - . '\x{6C1A}\x{6C1B}\x{6C1D}\x{6C1E}\x{6C1F}\x{6C20}\x{6C21}\x{6C22}\x{6C23}' - . '\x{6C24}\x{6C25}\x{6C26}\x{6C27}\x{6C28}\x{6C29}\x{6C2A}\x{6C2B}\x{6C2C}' - . '\x{6C2E}\x{6C2F}\x{6C30}\x{6C31}\x{6C32}\x{6C33}\x{6C34}\x{6C35}\x{6C36}' - . '\x{6C37}\x{6C38}\x{6C3A}\x{6C3B}\x{6C3D}\x{6C3E}\x{6C3F}\x{6C40}\x{6C41}' - . '\x{6C42}\x{6C43}\x{6C44}\x{6C46}\x{6C47}\x{6C48}\x{6C49}\x{6C4A}\x{6C4B}' - . '\x{6C4C}\x{6C4D}\x{6C4E}\x{6C4F}\x{6C50}\x{6C51}\x{6C52}\x{6C53}\x{6C54}' - . '\x{6C55}\x{6C56}\x{6C57}\x{6C58}\x{6C59}\x{6C5A}\x{6C5B}\x{6C5C}\x{6C5D}' - . '\x{6C5E}\x{6C5F}\x{6C60}\x{6C61}\x{6C62}\x{6C63}\x{6C64}\x{6C65}\x{6C66}' - . '\x{6C67}\x{6C68}\x{6C69}\x{6C6A}\x{6C6B}\x{6C6D}\x{6C6F}\x{6C70}\x{6C71}' - . '\x{6C72}\x{6C73}\x{6C74}\x{6C75}\x{6C76}\x{6C77}\x{6C78}\x{6C79}\x{6C7A}' - . '\x{6C7B}\x{6C7C}\x{6C7D}\x{6C7E}\x{6C7F}\x{6C80}\x{6C81}\x{6C82}\x{6C83}' - . '\x{6C84}\x{6C85}\x{6C86}\x{6C87}\x{6C88}\x{6C89}\x{6C8A}\x{6C8B}\x{6C8C}' - . '\x{6C8D}\x{6C8E}\x{6C8F}\x{6C90}\x{6C91}\x{6C92}\x{6C93}\x{6C94}\x{6C95}' - . '\x{6C96}\x{6C97}\x{6C98}\x{6C99}\x{6C9A}\x{6C9B}\x{6C9C}\x{6C9D}\x{6C9E}' - . '\x{6C9F}\x{6CA1}\x{6CA2}\x{6CA3}\x{6CA4}\x{6CA5}\x{6CA6}\x{6CA7}\x{6CA8}' - . '\x{6CA9}\x{6CAA}\x{6CAB}\x{6CAC}\x{6CAD}\x{6CAE}\x{6CAF}\x{6CB0}\x{6CB1}' - . '\x{6CB2}\x{6CB3}\x{6CB4}\x{6CB5}\x{6CB6}\x{6CB7}\x{6CB8}\x{6CB9}\x{6CBA}' - . '\x{6CBB}\x{6CBC}\x{6CBD}\x{6CBE}\x{6CBF}\x{6CC0}\x{6CC1}\x{6CC2}\x{6CC3}' - . '\x{6CC4}\x{6CC5}\x{6CC6}\x{6CC7}\x{6CC8}\x{6CC9}\x{6CCA}\x{6CCB}\x{6CCC}' - . '\x{6CCD}\x{6CCE}\x{6CCF}\x{6CD0}\x{6CD1}\x{6CD2}\x{6CD3}\x{6CD4}\x{6CD5}' - . '\x{6CD6}\x{6CD7}\x{6CD9}\x{6CDA}\x{6CDB}\x{6CDC}\x{6CDD}\x{6CDE}\x{6CDF}' - . '\x{6CE0}\x{6CE1}\x{6CE2}\x{6CE3}\x{6CE4}\x{6CE5}\x{6CE6}\x{6CE7}\x{6CE8}' - . '\x{6CE9}\x{6CEA}\x{6CEB}\x{6CEC}\x{6CED}\x{6CEE}\x{6CEF}\x{6CF0}\x{6CF1}' - . '\x{6CF2}\x{6CF3}\x{6CF5}\x{6CF6}\x{6CF7}\x{6CF8}\x{6CF9}\x{6CFA}\x{6CFB}' - . '\x{6CFC}\x{6CFD}\x{6CFE}\x{6CFF}\x{6D00}\x{6D01}\x{6D03}\x{6D04}\x{6D05}' - . '\x{6D06}\x{6D07}\x{6D08}\x{6D09}\x{6D0A}\x{6D0B}\x{6D0C}\x{6D0D}\x{6D0E}' - . '\x{6D0F}\x{6D10}\x{6D11}\x{6D12}\x{6D13}\x{6D14}\x{6D15}\x{6D16}\x{6D17}' - . '\x{6D18}\x{6D19}\x{6D1A}\x{6D1B}\x{6D1D}\x{6D1E}\x{6D1F}\x{6D20}\x{6D21}' - . '\x{6D22}\x{6D23}\x{6D25}\x{6D26}\x{6D27}\x{6D28}\x{6D29}\x{6D2A}\x{6D2B}' - . '\x{6D2C}\x{6D2D}\x{6D2E}\x{6D2F}\x{6D30}\x{6D31}\x{6D32}\x{6D33}\x{6D34}' - . '\x{6D35}\x{6D36}\x{6D37}\x{6D38}\x{6D39}\x{6D3A}\x{6D3B}\x{6D3C}\x{6D3D}' - . '\x{6D3E}\x{6D3F}\x{6D40}\x{6D41}\x{6D42}\x{6D43}\x{6D44}\x{6D45}\x{6D46}' - . '\x{6D47}\x{6D48}\x{6D49}\x{6D4A}\x{6D4B}\x{6D4C}\x{6D4D}\x{6D4E}\x{6D4F}' - . '\x{6D50}\x{6D51}\x{6D52}\x{6D53}\x{6D54}\x{6D55}\x{6D56}\x{6D57}\x{6D58}' - . '\x{6D59}\x{6D5A}\x{6D5B}\x{6D5C}\x{6D5D}\x{6D5E}\x{6D5F}\x{6D60}\x{6D61}' - . '\x{6D62}\x{6D63}\x{6D64}\x{6D65}\x{6D66}\x{6D67}\x{6D68}\x{6D69}\x{6D6A}' - . '\x{6D6B}\x{6D6C}\x{6D6D}\x{6D6E}\x{6D6F}\x{6D70}\x{6D72}\x{6D73}\x{6D74}' - . '\x{6D75}\x{6D76}\x{6D77}\x{6D78}\x{6D79}\x{6D7A}\x{6D7B}\x{6D7C}\x{6D7D}' - . '\x{6D7E}\x{6D7F}\x{6D80}\x{6D82}\x{6D83}\x{6D84}\x{6D85}\x{6D86}\x{6D87}' - . '\x{6D88}\x{6D89}\x{6D8A}\x{6D8B}\x{6D8C}\x{6D8D}\x{6D8E}\x{6D8F}\x{6D90}' - . '\x{6D91}\x{6D92}\x{6D93}\x{6D94}\x{6D95}\x{6D97}\x{6D98}\x{6D99}\x{6D9A}' - . '\x{6D9B}\x{6D9D}\x{6D9E}\x{6D9F}\x{6DA0}\x{6DA1}\x{6DA2}\x{6DA3}\x{6DA4}' - . '\x{6DA5}\x{6DA6}\x{6DA7}\x{6DA8}\x{6DA9}\x{6DAA}\x{6DAB}\x{6DAC}\x{6DAD}' - . '\x{6DAE}\x{6DAF}\x{6DB2}\x{6DB3}\x{6DB4}\x{6DB5}\x{6DB7}\x{6DB8}\x{6DB9}' - . '\x{6DBA}\x{6DBB}\x{6DBC}\x{6DBD}\x{6DBE}\x{6DBF}\x{6DC0}\x{6DC1}\x{6DC2}' - . '\x{6DC3}\x{6DC4}\x{6DC5}\x{6DC6}\x{6DC7}\x{6DC8}\x{6DC9}\x{6DCA}\x{6DCB}' - . '\x{6DCC}\x{6DCD}\x{6DCE}\x{6DCF}\x{6DD0}\x{6DD1}\x{6DD2}\x{6DD3}\x{6DD4}' - . '\x{6DD5}\x{6DD6}\x{6DD7}\x{6DD8}\x{6DD9}\x{6DDA}\x{6DDB}\x{6DDC}\x{6DDD}' - . '\x{6DDE}\x{6DDF}\x{6DE0}\x{6DE1}\x{6DE2}\x{6DE3}\x{6DE4}\x{6DE5}\x{6DE6}' - . '\x{6DE7}\x{6DE8}\x{6DE9}\x{6DEA}\x{6DEB}\x{6DEC}\x{6DED}\x{6DEE}\x{6DEF}' - . '\x{6DF0}\x{6DF1}\x{6DF2}\x{6DF3}\x{6DF4}\x{6DF5}\x{6DF6}\x{6DF7}\x{6DF8}' - . '\x{6DF9}\x{6DFA}\x{6DFB}\x{6DFC}\x{6DFD}\x{6E00}\x{6E03}\x{6E04}\x{6E05}' - . '\x{6E07}\x{6E08}\x{6E09}\x{6E0A}\x{6E0B}\x{6E0C}\x{6E0D}\x{6E0E}\x{6E0F}' - . '\x{6E10}\x{6E11}\x{6E14}\x{6E15}\x{6E16}\x{6E17}\x{6E19}\x{6E1A}\x{6E1B}' - . '\x{6E1C}\x{6E1D}\x{6E1E}\x{6E1F}\x{6E20}\x{6E21}\x{6E22}\x{6E23}\x{6E24}' - . '\x{6E25}\x{6E26}\x{6E27}\x{6E28}\x{6E29}\x{6E2B}\x{6E2C}\x{6E2D}\x{6E2E}' - . '\x{6E2F}\x{6E30}\x{6E31}\x{6E32}\x{6E33}\x{6E34}\x{6E35}\x{6E36}\x{6E37}' - . '\x{6E38}\x{6E39}\x{6E3A}\x{6E3B}\x{6E3C}\x{6E3D}\x{6E3E}\x{6E3F}\x{6E40}' - . '\x{6E41}\x{6E42}\x{6E43}\x{6E44}\x{6E45}\x{6E46}\x{6E47}\x{6E48}\x{6E49}' - . '\x{6E4A}\x{6E4B}\x{6E4D}\x{6E4E}\x{6E4F}\x{6E50}\x{6E51}\x{6E52}\x{6E53}' - . '\x{6E54}\x{6E55}\x{6E56}\x{6E57}\x{6E58}\x{6E59}\x{6E5A}\x{6E5B}\x{6E5C}' - . '\x{6E5D}\x{6E5E}\x{6E5F}\x{6E60}\x{6E61}\x{6E62}\x{6E63}\x{6E64}\x{6E65}' - . '\x{6E66}\x{6E67}\x{6E68}\x{6E69}\x{6E6A}\x{6E6B}\x{6E6D}\x{6E6E}\x{6E6F}' - . '\x{6E70}\x{6E71}\x{6E72}\x{6E73}\x{6E74}\x{6E75}\x{6E77}\x{6E78}\x{6E79}' - . '\x{6E7E}\x{6E7F}\x{6E80}\x{6E81}\x{6E82}\x{6E83}\x{6E84}\x{6E85}\x{6E86}' - . '\x{6E87}\x{6E88}\x{6E89}\x{6E8A}\x{6E8D}\x{6E8E}\x{6E8F}\x{6E90}\x{6E91}' - . '\x{6E92}\x{6E93}\x{6E94}\x{6E96}\x{6E97}\x{6E98}\x{6E99}\x{6E9A}\x{6E9B}' - . '\x{6E9C}\x{6E9D}\x{6E9E}\x{6E9F}\x{6EA0}\x{6EA1}\x{6EA2}\x{6EA3}\x{6EA4}' - . '\x{6EA5}\x{6EA6}\x{6EA7}\x{6EA8}\x{6EA9}\x{6EAA}\x{6EAB}\x{6EAC}\x{6EAD}' - . '\x{6EAE}\x{6EAF}\x{6EB0}\x{6EB1}\x{6EB2}\x{6EB3}\x{6EB4}\x{6EB5}\x{6EB6}' - . '\x{6EB7}\x{6EB8}\x{6EB9}\x{6EBA}\x{6EBB}\x{6EBC}\x{6EBD}\x{6EBE}\x{6EBF}' - . '\x{6EC0}\x{6EC1}\x{6EC2}\x{6EC3}\x{6EC4}\x{6EC5}\x{6EC6}\x{6EC7}\x{6EC8}' - . '\x{6EC9}\x{6ECA}\x{6ECB}\x{6ECC}\x{6ECD}\x{6ECE}\x{6ECF}\x{6ED0}\x{6ED1}' - . '\x{6ED2}\x{6ED3}\x{6ED4}\x{6ED5}\x{6ED6}\x{6ED7}\x{6ED8}\x{6ED9}\x{6EDA}' - . '\x{6EDC}\x{6EDE}\x{6EDF}\x{6EE0}\x{6EE1}\x{6EE2}\x{6EE4}\x{6EE5}\x{6EE6}' - . '\x{6EE7}\x{6EE8}\x{6EE9}\x{6EEA}\x{6EEB}\x{6EEC}\x{6EED}\x{6EEE}\x{6EEF}' - . '\x{6EF0}\x{6EF1}\x{6EF2}\x{6EF3}\x{6EF4}\x{6EF5}\x{6EF6}\x{6EF7}\x{6EF8}' - . '\x{6EF9}\x{6EFA}\x{6EFB}\x{6EFC}\x{6EFD}\x{6EFE}\x{6EFF}\x{6F00}\x{6F01}' - . '\x{6F02}\x{6F03}\x{6F05}\x{6F06}\x{6F07}\x{6F08}\x{6F09}\x{6F0A}\x{6F0C}' - . '\x{6F0D}\x{6F0E}\x{6F0F}\x{6F10}\x{6F11}\x{6F12}\x{6F13}\x{6F14}\x{6F15}' - . '\x{6F16}\x{6F17}\x{6F18}\x{6F19}\x{6F1A}\x{6F1B}\x{6F1C}\x{6F1D}\x{6F1E}' - . '\x{6F1F}\x{6F20}\x{6F21}\x{6F22}\x{6F23}\x{6F24}\x{6F25}\x{6F26}\x{6F27}' - . '\x{6F28}\x{6F29}\x{6F2A}\x{6F2B}\x{6F2C}\x{6F2D}\x{6F2E}\x{6F2F}\x{6F30}' - . '\x{6F31}\x{6F32}\x{6F33}\x{6F34}\x{6F35}\x{6F36}\x{6F37}\x{6F38}\x{6F39}' - . '\x{6F3A}\x{6F3B}\x{6F3C}\x{6F3D}\x{6F3E}\x{6F3F}\x{6F40}\x{6F41}\x{6F43}' - . '\x{6F44}\x{6F45}\x{6F46}\x{6F47}\x{6F49}\x{6F4B}\x{6F4C}\x{6F4D}\x{6F4E}' - . '\x{6F4F}\x{6F50}\x{6F51}\x{6F52}\x{6F53}\x{6F54}\x{6F55}\x{6F56}\x{6F57}' - . '\x{6F58}\x{6F59}\x{6F5A}\x{6F5B}\x{6F5C}\x{6F5D}\x{6F5E}\x{6F5F}\x{6F60}' - . '\x{6F61}\x{6F62}\x{6F63}\x{6F64}\x{6F65}\x{6F66}\x{6F67}\x{6F68}\x{6F69}' - . '\x{6F6A}\x{6F6B}\x{6F6C}\x{6F6D}\x{6F6E}\x{6F6F}\x{6F70}\x{6F71}\x{6F72}' - . '\x{6F73}\x{6F74}\x{6F75}\x{6F76}\x{6F77}\x{6F78}\x{6F7A}\x{6F7B}\x{6F7C}' - . '\x{6F7D}\x{6F7E}\x{6F7F}\x{6F80}\x{6F81}\x{6F82}\x{6F83}\x{6F84}\x{6F85}' - . '\x{6F86}\x{6F87}\x{6F88}\x{6F89}\x{6F8A}\x{6F8B}\x{6F8C}\x{6F8D}\x{6F8E}' - . '\x{6F8F}\x{6F90}\x{6F91}\x{6F92}\x{6F93}\x{6F94}\x{6F95}\x{6F96}\x{6F97}' - . '\x{6F99}\x{6F9B}\x{6F9C}\x{6F9D}\x{6F9E}\x{6FA0}\x{6FA1}\x{6FA2}\x{6FA3}' - . '\x{6FA4}\x{6FA5}\x{6FA6}\x{6FA7}\x{6FA8}\x{6FA9}\x{6FAA}\x{6FAB}\x{6FAC}' - . '\x{6FAD}\x{6FAE}\x{6FAF}\x{6FB0}\x{6FB1}\x{6FB2}\x{6FB3}\x{6FB4}\x{6FB5}' - . '\x{6FB6}\x{6FB8}\x{6FB9}\x{6FBA}\x{6FBB}\x{6FBC}\x{6FBD}\x{6FBE}\x{6FBF}' - . '\x{6FC0}\x{6FC1}\x{6FC2}\x{6FC3}\x{6FC4}\x{6FC6}\x{6FC7}\x{6FC8}\x{6FC9}' - . '\x{6FCA}\x{6FCB}\x{6FCC}\x{6FCD}\x{6FCE}\x{6FCF}\x{6FD1}\x{6FD2}\x{6FD4}' - . '\x{6FD5}\x{6FD6}\x{6FD7}\x{6FD8}\x{6FD9}\x{6FDA}\x{6FDB}\x{6FDC}\x{6FDD}' - . '\x{6FDE}\x{6FDF}\x{6FE0}\x{6FE1}\x{6FE2}\x{6FE3}\x{6FE4}\x{6FE5}\x{6FE6}' - . '\x{6FE7}\x{6FE8}\x{6FE9}\x{6FEA}\x{6FEB}\x{6FEC}\x{6FED}\x{6FEE}\x{6FEF}' - . '\x{6FF0}\x{6FF1}\x{6FF2}\x{6FF3}\x{6FF4}\x{6FF6}\x{6FF7}\x{6FF8}\x{6FF9}' - . '\x{6FFA}\x{6FFB}\x{6FFC}\x{6FFE}\x{6FFF}\x{7000}\x{7001}\x{7002}\x{7003}' - . '\x{7004}\x{7005}\x{7006}\x{7007}\x{7008}\x{7009}\x{700A}\x{700B}\x{700C}' - . '\x{700D}\x{700E}\x{700F}\x{7011}\x{7012}\x{7014}\x{7015}\x{7016}\x{7017}' - . '\x{7018}\x{7019}\x{701A}\x{701B}\x{701C}\x{701D}\x{701F}\x{7020}\x{7021}' - . '\x{7022}\x{7023}\x{7024}\x{7025}\x{7026}\x{7027}\x{7028}\x{7029}\x{702A}' - . '\x{702B}\x{702C}\x{702D}\x{702E}\x{702F}\x{7030}\x{7031}\x{7032}\x{7033}' - . '\x{7034}\x{7035}\x{7036}\x{7037}\x{7038}\x{7039}\x{703A}\x{703B}\x{703C}' - . '\x{703D}\x{703E}\x{703F}\x{7040}\x{7041}\x{7042}\x{7043}\x{7044}\x{7045}' - . '\x{7046}\x{7048}\x{7049}\x{704A}\x{704C}\x{704D}\x{704F}\x{7050}\x{7051}' - . '\x{7052}\x{7053}\x{7054}\x{7055}\x{7056}\x{7057}\x{7058}\x{7059}\x{705A}' - . '\x{705B}\x{705C}\x{705D}\x{705E}\x{705F}\x{7060}\x{7061}\x{7062}\x{7063}' - . '\x{7064}\x{7065}\x{7066}\x{7067}\x{7068}\x{7069}\x{706A}\x{706B}\x{706C}' - . '\x{706D}\x{706E}\x{706F}\x{7070}\x{7071}\x{7074}\x{7075}\x{7076}\x{7077}' - . '\x{7078}\x{7079}\x{707A}\x{707C}\x{707D}\x{707E}\x{707F}\x{7080}\x{7082}' - . '\x{7083}\x{7084}\x{7085}\x{7086}\x{7087}\x{7088}\x{7089}\x{708A}\x{708B}' - . '\x{708C}\x{708E}\x{708F}\x{7090}\x{7091}\x{7092}\x{7093}\x{7094}\x{7095}' - . '\x{7096}\x{7098}\x{7099}\x{709A}\x{709C}\x{709D}\x{709E}\x{709F}\x{70A0}' - . '\x{70A1}\x{70A2}\x{70A3}\x{70A4}\x{70A5}\x{70A6}\x{70A7}\x{70A8}\x{70A9}' - . '\x{70AB}\x{70AC}\x{70AD}\x{70AE}\x{70AF}\x{70B0}\x{70B1}\x{70B3}\x{70B4}' - . '\x{70B5}\x{70B7}\x{70B8}\x{70B9}\x{70BA}\x{70BB}\x{70BC}\x{70BD}\x{70BE}' - . '\x{70BF}\x{70C0}\x{70C1}\x{70C2}\x{70C3}\x{70C4}\x{70C5}\x{70C6}\x{70C7}' - . '\x{70C8}\x{70C9}\x{70CA}\x{70CB}\x{70CC}\x{70CD}\x{70CE}\x{70CF}\x{70D0}' - . '\x{70D1}\x{70D2}\x{70D3}\x{70D4}\x{70D6}\x{70D7}\x{70D8}\x{70D9}\x{70DA}' - . '\x{70DB}\x{70DC}\x{70DD}\x{70DE}\x{70DF}\x{70E0}\x{70E1}\x{70E2}\x{70E3}' - . '\x{70E4}\x{70E5}\x{70E6}\x{70E7}\x{70E8}\x{70E9}\x{70EA}\x{70EB}\x{70EC}' - . '\x{70ED}\x{70EE}\x{70EF}\x{70F0}\x{70F1}\x{70F2}\x{70F3}\x{70F4}\x{70F5}' - . '\x{70F6}\x{70F7}\x{70F8}\x{70F9}\x{70FA}\x{70FB}\x{70FC}\x{70FD}\x{70FF}' - . '\x{7100}\x{7101}\x{7102}\x{7103}\x{7104}\x{7105}\x{7106}\x{7107}\x{7109}' - . '\x{710A}\x{710B}\x{710C}\x{710D}\x{710E}\x{710F}\x{7110}\x{7111}\x{7112}' - . '\x{7113}\x{7115}\x{7116}\x{7117}\x{7118}\x{7119}\x{711A}\x{711B}\x{711C}' - . '\x{711D}\x{711E}\x{711F}\x{7120}\x{7121}\x{7122}\x{7123}\x{7125}\x{7126}' - . '\x{7127}\x{7128}\x{7129}\x{712A}\x{712B}\x{712C}\x{712D}\x{712E}\x{712F}' - . '\x{7130}\x{7131}\x{7132}\x{7135}\x{7136}\x{7137}\x{7138}\x{7139}\x{713A}' - . '\x{713B}\x{713D}\x{713E}\x{713F}\x{7140}\x{7141}\x{7142}\x{7143}\x{7144}' - . '\x{7145}\x{7146}\x{7147}\x{7148}\x{7149}\x{714A}\x{714B}\x{714C}\x{714D}' - . '\x{714E}\x{714F}\x{7150}\x{7151}\x{7152}\x{7153}\x{7154}\x{7156}\x{7158}' - . '\x{7159}\x{715A}\x{715B}\x{715C}\x{715D}\x{715E}\x{715F}\x{7160}\x{7161}' - . '\x{7162}\x{7163}\x{7164}\x{7165}\x{7166}\x{7167}\x{7168}\x{7169}\x{716A}' - . '\x{716C}\x{716E}\x{716F}\x{7170}\x{7171}\x{7172}\x{7173}\x{7174}\x{7175}' - . '\x{7176}\x{7177}\x{7178}\x{7179}\x{717A}\x{717B}\x{717C}\x{717D}\x{717E}' - . '\x{717F}\x{7180}\x{7181}\x{7182}\x{7183}\x{7184}\x{7185}\x{7186}\x{7187}' - . '\x{7188}\x{7189}\x{718A}\x{718B}\x{718C}\x{718E}\x{718F}\x{7190}\x{7191}' - . '\x{7192}\x{7193}\x{7194}\x{7195}\x{7197}\x{7198}\x{7199}\x{719A}\x{719B}' - . '\x{719C}\x{719D}\x{719E}\x{719F}\x{71A0}\x{71A1}\x{71A2}\x{71A3}\x{71A4}' - . '\x{71A5}\x{71A7}\x{71A8}\x{71A9}\x{71AA}\x{71AC}\x{71AD}\x{71AE}\x{71AF}' - . '\x{71B0}\x{71B1}\x{71B2}\x{71B3}\x{71B4}\x{71B5}\x{71B7}\x{71B8}\x{71B9}' - . '\x{71BA}\x{71BB}\x{71BC}\x{71BD}\x{71BE}\x{71BF}\x{71C0}\x{71C1}\x{71C2}' - . '\x{71C3}\x{71C4}\x{71C5}\x{71C6}\x{71C7}\x{71C8}\x{71C9}\x{71CA}\x{71CB}' - . '\x{71CD}\x{71CE}\x{71CF}\x{71D0}\x{71D1}\x{71D2}\x{71D4}\x{71D5}\x{71D6}' - . '\x{71D7}\x{71D8}\x{71D9}\x{71DA}\x{71DB}\x{71DC}\x{71DD}\x{71DE}\x{71DF}' - . '\x{71E0}\x{71E1}\x{71E2}\x{71E3}\x{71E4}\x{71E5}\x{71E6}\x{71E7}\x{71E8}' - . '\x{71E9}\x{71EA}\x{71EB}\x{71EC}\x{71ED}\x{71EE}\x{71EF}\x{71F0}\x{71F1}' - . '\x{71F2}\x{71F4}\x{71F5}\x{71F6}\x{71F7}\x{71F8}\x{71F9}\x{71FB}\x{71FC}' - . '\x{71FD}\x{71FE}\x{71FF}\x{7201}\x{7202}\x{7203}\x{7204}\x{7205}\x{7206}' - . '\x{7207}\x{7208}\x{7209}\x{720A}\x{720C}\x{720D}\x{720E}\x{720F}\x{7210}' - . '\x{7212}\x{7213}\x{7214}\x{7216}\x{7218}\x{7219}\x{721A}\x{721B}\x{721C}' - . '\x{721D}\x{721E}\x{721F}\x{7221}\x{7222}\x{7223}\x{7226}\x{7227}\x{7228}' - . '\x{7229}\x{722A}\x{722B}\x{722C}\x{722D}\x{722E}\x{7230}\x{7231}\x{7232}' - . '\x{7233}\x{7235}\x{7236}\x{7237}\x{7238}\x{7239}\x{723A}\x{723B}\x{723C}' - . '\x{723D}\x{723E}\x{723F}\x{7240}\x{7241}\x{7242}\x{7243}\x{7244}\x{7246}' - . '\x{7247}\x{7248}\x{7249}\x{724A}\x{724B}\x{724C}\x{724D}\x{724F}\x{7251}' - . '\x{7252}\x{7253}\x{7254}\x{7256}\x{7257}\x{7258}\x{7259}\x{725A}\x{725B}' - . '\x{725C}\x{725D}\x{725E}\x{725F}\x{7260}\x{7261}\x{7262}\x{7263}\x{7264}' - . '\x{7265}\x{7266}\x{7267}\x{7268}\x{7269}\x{726A}\x{726B}\x{726C}\x{726D}' - . '\x{726E}\x{726F}\x{7270}\x{7271}\x{7272}\x{7273}\x{7274}\x{7275}\x{7276}' - . '\x{7277}\x{7278}\x{7279}\x{727A}\x{727B}\x{727C}\x{727D}\x{727E}\x{727F}' - . '\x{7280}\x{7281}\x{7282}\x{7283}\x{7284}\x{7285}\x{7286}\x{7287}\x{7288}' - . '\x{7289}\x{728A}\x{728B}\x{728C}\x{728D}\x{728E}\x{728F}\x{7290}\x{7291}' - . '\x{7292}\x{7293}\x{7294}\x{7295}\x{7296}\x{7297}\x{7298}\x{7299}\x{729A}' - . '\x{729B}\x{729C}\x{729D}\x{729E}\x{729F}\x{72A1}\x{72A2}\x{72A3}\x{72A4}' - . '\x{72A5}\x{72A6}\x{72A7}\x{72A8}\x{72A9}\x{72AA}\x{72AC}\x{72AD}\x{72AE}' - . '\x{72AF}\x{72B0}\x{72B1}\x{72B2}\x{72B3}\x{72B4}\x{72B5}\x{72B6}\x{72B7}' - . '\x{72B8}\x{72B9}\x{72BA}\x{72BB}\x{72BC}\x{72BD}\x{72BF}\x{72C0}\x{72C1}' - . '\x{72C2}\x{72C3}\x{72C4}\x{72C5}\x{72C6}\x{72C7}\x{72C8}\x{72C9}\x{72CA}' - . '\x{72CB}\x{72CC}\x{72CD}\x{72CE}\x{72CF}\x{72D0}\x{72D1}\x{72D2}\x{72D3}' - . '\x{72D4}\x{72D5}\x{72D6}\x{72D7}\x{72D8}\x{72D9}\x{72DA}\x{72DB}\x{72DC}' - . '\x{72DD}\x{72DE}\x{72DF}\x{72E0}\x{72E1}\x{72E2}\x{72E3}\x{72E4}\x{72E5}' - . '\x{72E6}\x{72E7}\x{72E8}\x{72E9}\x{72EA}\x{72EB}\x{72EC}\x{72ED}\x{72EE}' - . '\x{72EF}\x{72F0}\x{72F1}\x{72F2}\x{72F3}\x{72F4}\x{72F5}\x{72F6}\x{72F7}' - . '\x{72F8}\x{72F9}\x{72FA}\x{72FB}\x{72FC}\x{72FD}\x{72FE}\x{72FF}\x{7300}' - . '\x{7301}\x{7303}\x{7304}\x{7305}\x{7306}\x{7307}\x{7308}\x{7309}\x{730A}' - . '\x{730B}\x{730C}\x{730D}\x{730E}\x{730F}\x{7311}\x{7312}\x{7313}\x{7314}' - . '\x{7315}\x{7316}\x{7317}\x{7318}\x{7319}\x{731A}\x{731B}\x{731C}\x{731D}' - . '\x{731E}\x{7320}\x{7321}\x{7322}\x{7323}\x{7324}\x{7325}\x{7326}\x{7327}' - . '\x{7329}\x{732A}\x{732B}\x{732C}\x{732D}\x{732E}\x{7330}\x{7331}\x{7332}' - . '\x{7333}\x{7334}\x{7335}\x{7336}\x{7337}\x{7338}\x{7339}\x{733A}\x{733B}' - . '\x{733C}\x{733D}\x{733E}\x{733F}\x{7340}\x{7341}\x{7342}\x{7343}\x{7344}' - . '\x{7345}\x{7346}\x{7347}\x{7348}\x{7349}\x{734A}\x{734B}\x{734C}\x{734D}' - . '\x{734E}\x{7350}\x{7351}\x{7352}\x{7354}\x{7355}\x{7356}\x{7357}\x{7358}' - . '\x{7359}\x{735A}\x{735B}\x{735C}\x{735D}\x{735E}\x{735F}\x{7360}\x{7361}' - . '\x{7362}\x{7364}\x{7365}\x{7366}\x{7367}\x{7368}\x{7369}\x{736A}\x{736B}' - . '\x{736C}\x{736D}\x{736E}\x{736F}\x{7370}\x{7371}\x{7372}\x{7373}\x{7374}' - . '\x{7375}\x{7376}\x{7377}\x{7378}\x{7379}\x{737A}\x{737B}\x{737C}\x{737D}' - . '\x{737E}\x{737F}\x{7380}\x{7381}\x{7382}\x{7383}\x{7384}\x{7385}\x{7386}' - . '\x{7387}\x{7388}\x{7389}\x{738A}\x{738B}\x{738C}\x{738D}\x{738E}\x{738F}' - . '\x{7390}\x{7391}\x{7392}\x{7393}\x{7394}\x{7395}\x{7396}\x{7397}\x{7398}' - . '\x{7399}\x{739A}\x{739B}\x{739D}\x{739E}\x{739F}\x{73A0}\x{73A1}\x{73A2}' - . '\x{73A3}\x{73A4}\x{73A5}\x{73A6}\x{73A7}\x{73A8}\x{73A9}\x{73AA}\x{73AB}' - . '\x{73AC}\x{73AD}\x{73AE}\x{73AF}\x{73B0}\x{73B1}\x{73B2}\x{73B3}\x{73B4}' - . '\x{73B5}\x{73B6}\x{73B7}\x{73B8}\x{73B9}\x{73BA}\x{73BB}\x{73BC}\x{73BD}' - . '\x{73BE}\x{73BF}\x{73C0}\x{73C2}\x{73C3}\x{73C4}\x{73C5}\x{73C6}\x{73C7}' - . '\x{73C8}\x{73C9}\x{73CA}\x{73CB}\x{73CC}\x{73CD}\x{73CE}\x{73CF}\x{73D0}' - . '\x{73D1}\x{73D2}\x{73D3}\x{73D4}\x{73D5}\x{73D6}\x{73D7}\x{73D8}\x{73D9}' - . '\x{73DA}\x{73DB}\x{73DC}\x{73DD}\x{73DE}\x{73DF}\x{73E0}\x{73E2}\x{73E3}' - . '\x{73E5}\x{73E6}\x{73E7}\x{73E8}\x{73E9}\x{73EA}\x{73EB}\x{73EC}\x{73ED}' - . '\x{73EE}\x{73EF}\x{73F0}\x{73F1}\x{73F2}\x{73F4}\x{73F5}\x{73F6}\x{73F7}' - . '\x{73F8}\x{73F9}\x{73FA}\x{73FC}\x{73FD}\x{73FE}\x{73FF}\x{7400}\x{7401}' - . '\x{7402}\x{7403}\x{7404}\x{7405}\x{7406}\x{7407}\x{7408}\x{7409}\x{740A}' - . '\x{740B}\x{740C}\x{740D}\x{740E}\x{740F}\x{7410}\x{7411}\x{7412}\x{7413}' - . '\x{7414}\x{7415}\x{7416}\x{7417}\x{7419}\x{741A}\x{741B}\x{741C}\x{741D}' - . '\x{741E}\x{741F}\x{7420}\x{7421}\x{7422}\x{7423}\x{7424}\x{7425}\x{7426}' - . '\x{7427}\x{7428}\x{7429}\x{742A}\x{742B}\x{742C}\x{742D}\x{742E}\x{742F}' - . '\x{7430}\x{7431}\x{7432}\x{7433}\x{7434}\x{7435}\x{7436}\x{7437}\x{7438}' - . '\x{743A}\x{743B}\x{743C}\x{743D}\x{743F}\x{7440}\x{7441}\x{7442}\x{7443}' - . '\x{7444}\x{7445}\x{7446}\x{7448}\x{744A}\x{744B}\x{744C}\x{744D}\x{744E}' - . '\x{744F}\x{7450}\x{7451}\x{7452}\x{7453}\x{7454}\x{7455}\x{7456}\x{7457}' - . '\x{7459}\x{745A}\x{745B}\x{745C}\x{745D}\x{745E}\x{745F}\x{7461}\x{7462}' - . '\x{7463}\x{7464}\x{7465}\x{7466}\x{7467}\x{7468}\x{7469}\x{746A}\x{746B}' - . '\x{746C}\x{746D}\x{746E}\x{746F}\x{7470}\x{7471}\x{7472}\x{7473}\x{7474}' - . '\x{7475}\x{7476}\x{7477}\x{7478}\x{7479}\x{747A}\x{747C}\x{747D}\x{747E}' - . '\x{747F}\x{7480}\x{7481}\x{7482}\x{7483}\x{7485}\x{7486}\x{7487}\x{7488}' - . '\x{7489}\x{748A}\x{748B}\x{748C}\x{748D}\x{748E}\x{748F}\x{7490}\x{7491}' - . '\x{7492}\x{7493}\x{7494}\x{7495}\x{7497}\x{7498}\x{7499}\x{749A}\x{749B}' - . '\x{749C}\x{749E}\x{749F}\x{74A0}\x{74A1}\x{74A3}\x{74A4}\x{74A5}\x{74A6}' - . '\x{74A7}\x{74A8}\x{74A9}\x{74AA}\x{74AB}\x{74AC}\x{74AD}\x{74AE}\x{74AF}' - . '\x{74B0}\x{74B1}\x{74B2}\x{74B3}\x{74B4}\x{74B5}\x{74B6}\x{74B7}\x{74B8}' - . '\x{74B9}\x{74BA}\x{74BB}\x{74BC}\x{74BD}\x{74BE}\x{74BF}\x{74C0}\x{74C1}' - . '\x{74C2}\x{74C3}\x{74C4}\x{74C5}\x{74C6}\x{74CA}\x{74CB}\x{74CD}\x{74CE}' - . '\x{74CF}\x{74D0}\x{74D1}\x{74D2}\x{74D3}\x{74D4}\x{74D5}\x{74D6}\x{74D7}' - . '\x{74D8}\x{74D9}\x{74DA}\x{74DB}\x{74DC}\x{74DD}\x{74DE}\x{74DF}\x{74E0}' - . '\x{74E1}\x{74E2}\x{74E3}\x{74E4}\x{74E5}\x{74E6}\x{74E7}\x{74E8}\x{74E9}' - . '\x{74EA}\x{74EC}\x{74ED}\x{74EE}\x{74EF}\x{74F0}\x{74F1}\x{74F2}\x{74F3}' - . '\x{74F4}\x{74F5}\x{74F6}\x{74F7}\x{74F8}\x{74F9}\x{74FA}\x{74FB}\x{74FC}' - . '\x{74FD}\x{74FE}\x{74FF}\x{7500}\x{7501}\x{7502}\x{7503}\x{7504}\x{7505}' - . '\x{7506}\x{7507}\x{7508}\x{7509}\x{750A}\x{750B}\x{750C}\x{750D}\x{750F}' - . '\x{7510}\x{7511}\x{7512}\x{7513}\x{7514}\x{7515}\x{7516}\x{7517}\x{7518}' - . '\x{7519}\x{751A}\x{751B}\x{751C}\x{751D}\x{751E}\x{751F}\x{7521}\x{7522}' - . '\x{7523}\x{7524}\x{7525}\x{7526}\x{7527}\x{7528}\x{7529}\x{752A}\x{752B}' - . '\x{752C}\x{752D}\x{752E}\x{752F}\x{7530}\x{7531}\x{7532}\x{7533}\x{7535}' - . '\x{7536}\x{7537}\x{7538}\x{7539}\x{753A}\x{753B}\x{753C}\x{753D}\x{753E}' - . '\x{753F}\x{7540}\x{7542}\x{7543}\x{7544}\x{7545}\x{7546}\x{7547}\x{7548}' - . '\x{7549}\x{754B}\x{754C}\x{754D}\x{754E}\x{754F}\x{7550}\x{7551}\x{7553}' - . '\x{7554}\x{7556}\x{7557}\x{7558}\x{7559}\x{755A}\x{755B}\x{755C}\x{755D}' - . '\x{755F}\x{7560}\x{7562}\x{7563}\x{7564}\x{7565}\x{7566}\x{7567}\x{7568}' - . '\x{7569}\x{756A}\x{756B}\x{756C}\x{756D}\x{756E}\x{756F}\x{7570}\x{7572}' - . '\x{7574}\x{7575}\x{7576}\x{7577}\x{7578}\x{7579}\x{757C}\x{757D}\x{757E}' - . '\x{757F}\x{7580}\x{7581}\x{7582}\x{7583}\x{7584}\x{7586}\x{7587}\x{7588}' - . '\x{7589}\x{758A}\x{758B}\x{758C}\x{758D}\x{758F}\x{7590}\x{7591}\x{7592}' - . '\x{7593}\x{7594}\x{7595}\x{7596}\x{7597}\x{7598}\x{7599}\x{759A}\x{759B}' - . '\x{759C}\x{759D}\x{759E}\x{759F}\x{75A0}\x{75A1}\x{75A2}\x{75A3}\x{75A4}' - . '\x{75A5}\x{75A6}\x{75A7}\x{75A8}\x{75AA}\x{75AB}\x{75AC}\x{75AD}\x{75AE}' - . '\x{75AF}\x{75B0}\x{75B1}\x{75B2}\x{75B3}\x{75B4}\x{75B5}\x{75B6}\x{75B8}' - . '\x{75B9}\x{75BA}\x{75BB}\x{75BC}\x{75BD}\x{75BE}\x{75BF}\x{75C0}\x{75C1}' - . '\x{75C2}\x{75C3}\x{75C4}\x{75C5}\x{75C6}\x{75C7}\x{75C8}\x{75C9}\x{75CA}' - . '\x{75CB}\x{75CC}\x{75CD}\x{75CE}\x{75CF}\x{75D0}\x{75D1}\x{75D2}\x{75D3}' - . '\x{75D4}\x{75D5}\x{75D6}\x{75D7}\x{75D8}\x{75D9}\x{75DA}\x{75DB}\x{75DD}' - . '\x{75DE}\x{75DF}\x{75E0}\x{75E1}\x{75E2}\x{75E3}\x{75E4}\x{75E5}\x{75E6}' - . '\x{75E7}\x{75E8}\x{75EA}\x{75EB}\x{75EC}\x{75ED}\x{75EF}\x{75F0}\x{75F1}' - . '\x{75F2}\x{75F3}\x{75F4}\x{75F5}\x{75F6}\x{75F7}\x{75F8}\x{75F9}\x{75FA}' - . '\x{75FB}\x{75FC}\x{75FD}\x{75FE}\x{75FF}\x{7600}\x{7601}\x{7602}\x{7603}' - . '\x{7604}\x{7605}\x{7606}\x{7607}\x{7608}\x{7609}\x{760A}\x{760B}\x{760C}' - . '\x{760D}\x{760E}\x{760F}\x{7610}\x{7611}\x{7612}\x{7613}\x{7614}\x{7615}' - . '\x{7616}\x{7617}\x{7618}\x{7619}\x{761A}\x{761B}\x{761C}\x{761D}\x{761E}' - . '\x{761F}\x{7620}\x{7621}\x{7622}\x{7623}\x{7624}\x{7625}\x{7626}\x{7627}' - . '\x{7628}\x{7629}\x{762A}\x{762B}\x{762D}\x{762E}\x{762F}\x{7630}\x{7631}' - . '\x{7632}\x{7633}\x{7634}\x{7635}\x{7636}\x{7637}\x{7638}\x{7639}\x{763A}' - . '\x{763B}\x{763C}\x{763D}\x{763E}\x{763F}\x{7640}\x{7641}\x{7642}\x{7643}' - . '\x{7646}\x{7647}\x{7648}\x{7649}\x{764A}\x{764B}\x{764C}\x{764D}\x{764F}' - . '\x{7650}\x{7652}\x{7653}\x{7654}\x{7656}\x{7657}\x{7658}\x{7659}\x{765A}' - . '\x{765B}\x{765C}\x{765D}\x{765E}\x{765F}\x{7660}\x{7661}\x{7662}\x{7663}' - . '\x{7664}\x{7665}\x{7666}\x{7667}\x{7668}\x{7669}\x{766A}\x{766B}\x{766C}' - . '\x{766D}\x{766E}\x{766F}\x{7670}\x{7671}\x{7672}\x{7674}\x{7675}\x{7676}' - . '\x{7677}\x{7678}\x{7679}\x{767B}\x{767C}\x{767D}\x{767E}\x{767F}\x{7680}' - . '\x{7681}\x{7682}\x{7683}\x{7684}\x{7685}\x{7686}\x{7687}\x{7688}\x{7689}' - . '\x{768A}\x{768B}\x{768C}\x{768E}\x{768F}\x{7690}\x{7691}\x{7692}\x{7693}' - . '\x{7694}\x{7695}\x{7696}\x{7697}\x{7698}\x{7699}\x{769A}\x{769B}\x{769C}' - . '\x{769D}\x{769E}\x{769F}\x{76A0}\x{76A3}\x{76A4}\x{76A6}\x{76A7}\x{76A9}' - . '\x{76AA}\x{76AB}\x{76AC}\x{76AD}\x{76AE}\x{76AF}\x{76B0}\x{76B1}\x{76B2}' - . '\x{76B4}\x{76B5}\x{76B7}\x{76B8}\x{76BA}\x{76BB}\x{76BC}\x{76BD}\x{76BE}' - . '\x{76BF}\x{76C0}\x{76C2}\x{76C3}\x{76C4}\x{76C5}\x{76C6}\x{76C7}\x{76C8}' - . '\x{76C9}\x{76CA}\x{76CD}\x{76CE}\x{76CF}\x{76D0}\x{76D1}\x{76D2}\x{76D3}' - . '\x{76D4}\x{76D5}\x{76D6}\x{76D7}\x{76D8}\x{76DA}\x{76DB}\x{76DC}\x{76DD}' - . '\x{76DE}\x{76DF}\x{76E0}\x{76E1}\x{76E2}\x{76E3}\x{76E4}\x{76E5}\x{76E6}' - . '\x{76E7}\x{76E8}\x{76E9}\x{76EA}\x{76EC}\x{76ED}\x{76EE}\x{76EF}\x{76F0}' - . '\x{76F1}\x{76F2}\x{76F3}\x{76F4}\x{76F5}\x{76F6}\x{76F7}\x{76F8}\x{76F9}' - . '\x{76FA}\x{76FB}\x{76FC}\x{76FD}\x{76FE}\x{76FF}\x{7701}\x{7703}\x{7704}' - . '\x{7705}\x{7706}\x{7707}\x{7708}\x{7709}\x{770A}\x{770B}\x{770C}\x{770D}' - . '\x{770F}\x{7710}\x{7711}\x{7712}\x{7713}\x{7714}\x{7715}\x{7716}\x{7717}' - . '\x{7718}\x{7719}\x{771A}\x{771B}\x{771C}\x{771D}\x{771E}\x{771F}\x{7720}' - . '\x{7722}\x{7723}\x{7725}\x{7726}\x{7727}\x{7728}\x{7729}\x{772A}\x{772C}' - . '\x{772D}\x{772E}\x{772F}\x{7730}\x{7731}\x{7732}\x{7733}\x{7734}\x{7735}' - . '\x{7736}\x{7737}\x{7738}\x{7739}\x{773A}\x{773B}\x{773C}\x{773D}\x{773E}' - . '\x{7740}\x{7741}\x{7743}\x{7744}\x{7745}\x{7746}\x{7747}\x{7748}\x{7749}' - . '\x{774A}\x{774B}\x{774C}\x{774D}\x{774E}\x{774F}\x{7750}\x{7751}\x{7752}' - . '\x{7753}\x{7754}\x{7755}\x{7756}\x{7757}\x{7758}\x{7759}\x{775A}\x{775B}' - . '\x{775C}\x{775D}\x{775E}\x{775F}\x{7760}\x{7761}\x{7762}\x{7763}\x{7765}' - . '\x{7766}\x{7767}\x{7768}\x{7769}\x{776A}\x{776B}\x{776C}\x{776D}\x{776E}' - . '\x{776F}\x{7770}\x{7771}\x{7772}\x{7773}\x{7774}\x{7775}\x{7776}\x{7777}' - . '\x{7778}\x{7779}\x{777A}\x{777B}\x{777C}\x{777D}\x{777E}\x{777F}\x{7780}' - . '\x{7781}\x{7782}\x{7783}\x{7784}\x{7785}\x{7786}\x{7787}\x{7788}\x{7789}' - . '\x{778A}\x{778B}\x{778C}\x{778D}\x{778E}\x{778F}\x{7790}\x{7791}\x{7792}' - . '\x{7793}\x{7794}\x{7795}\x{7797}\x{7798}\x{7799}\x{779A}\x{779B}\x{779C}' - . '\x{779D}\x{779E}\x{779F}\x{77A0}\x{77A1}\x{77A2}\x{77A3}\x{77A5}\x{77A6}' - . '\x{77A7}\x{77A8}\x{77A9}\x{77AA}\x{77AB}\x{77AC}\x{77AD}\x{77AE}\x{77AF}' - . '\x{77B0}\x{77B1}\x{77B2}\x{77B3}\x{77B4}\x{77B5}\x{77B6}\x{77B7}\x{77B8}' - . '\x{77B9}\x{77BA}\x{77BB}\x{77BC}\x{77BD}\x{77BF}\x{77C0}\x{77C2}\x{77C3}' - . '\x{77C4}\x{77C5}\x{77C6}\x{77C7}\x{77C8}\x{77C9}\x{77CA}\x{77CB}\x{77CC}' - . '\x{77CD}\x{77CE}\x{77CF}\x{77D0}\x{77D1}\x{77D3}\x{77D4}\x{77D5}\x{77D6}' - . '\x{77D7}\x{77D8}\x{77D9}\x{77DA}\x{77DB}\x{77DC}\x{77DE}\x{77DF}\x{77E0}' - . '\x{77E1}\x{77E2}\x{77E3}\x{77E5}\x{77E7}\x{77E8}\x{77E9}\x{77EA}\x{77EB}' - . '\x{77EC}\x{77ED}\x{77EE}\x{77EF}\x{77F0}\x{77F1}\x{77F2}\x{77F3}\x{77F6}' - . '\x{77F7}\x{77F8}\x{77F9}\x{77FA}\x{77FB}\x{77FC}\x{77FD}\x{77FE}\x{77FF}' - . '\x{7800}\x{7801}\x{7802}\x{7803}\x{7804}\x{7805}\x{7806}\x{7808}\x{7809}' - . '\x{780A}\x{780B}\x{780C}\x{780D}\x{780E}\x{780F}\x{7810}\x{7811}\x{7812}' - . '\x{7813}\x{7814}\x{7815}\x{7816}\x{7817}\x{7818}\x{7819}\x{781A}\x{781B}' - . '\x{781C}\x{781D}\x{781E}\x{781F}\x{7820}\x{7821}\x{7822}\x{7823}\x{7825}' - . '\x{7826}\x{7827}\x{7828}\x{7829}\x{782A}\x{782B}\x{782C}\x{782D}\x{782E}' - . '\x{782F}\x{7830}\x{7831}\x{7832}\x{7833}\x{7834}\x{7835}\x{7837}\x{7838}' - . '\x{7839}\x{783A}\x{783B}\x{783C}\x{783D}\x{783E}\x{7840}\x{7841}\x{7843}' - . '\x{7844}\x{7845}\x{7847}\x{7848}\x{7849}\x{784A}\x{784C}\x{784D}\x{784E}' - . '\x{7850}\x{7851}\x{7852}\x{7853}\x{7854}\x{7855}\x{7856}\x{7857}\x{7858}' - . '\x{7859}\x{785A}\x{785B}\x{785C}\x{785D}\x{785E}\x{785F}\x{7860}\x{7861}' - . '\x{7862}\x{7863}\x{7864}\x{7865}\x{7866}\x{7867}\x{7868}\x{7869}\x{786A}' - . '\x{786B}\x{786C}\x{786D}\x{786E}\x{786F}\x{7870}\x{7871}\x{7872}\x{7873}' - . '\x{7874}\x{7875}\x{7877}\x{7878}\x{7879}\x{787A}\x{787B}\x{787C}\x{787D}' - . '\x{787E}\x{787F}\x{7880}\x{7881}\x{7882}\x{7883}\x{7884}\x{7885}\x{7886}' - . '\x{7887}\x{7889}\x{788A}\x{788B}\x{788C}\x{788D}\x{788E}\x{788F}\x{7890}' - . '\x{7891}\x{7892}\x{7893}\x{7894}\x{7895}\x{7896}\x{7897}\x{7898}\x{7899}' - . '\x{789A}\x{789B}\x{789C}\x{789D}\x{789E}\x{789F}\x{78A0}\x{78A1}\x{78A2}' - . '\x{78A3}\x{78A4}\x{78A5}\x{78A6}\x{78A7}\x{78A8}\x{78A9}\x{78AA}\x{78AB}' - . '\x{78AC}\x{78AD}\x{78AE}\x{78AF}\x{78B0}\x{78B1}\x{78B2}\x{78B3}\x{78B4}' - . '\x{78B5}\x{78B6}\x{78B7}\x{78B8}\x{78B9}\x{78BA}\x{78BB}\x{78BC}\x{78BD}' - . '\x{78BE}\x{78BF}\x{78C0}\x{78C1}\x{78C3}\x{78C4}\x{78C5}\x{78C6}\x{78C8}' - . '\x{78C9}\x{78CA}\x{78CB}\x{78CC}\x{78CD}\x{78CE}\x{78CF}\x{78D0}\x{78D1}' - . '\x{78D3}\x{78D4}\x{78D5}\x{78D6}\x{78D7}\x{78D8}\x{78D9}\x{78DA}\x{78DB}' - . '\x{78DC}\x{78DD}\x{78DE}\x{78DF}\x{78E0}\x{78E1}\x{78E2}\x{78E3}\x{78E4}' - . '\x{78E5}\x{78E6}\x{78E7}\x{78E8}\x{78E9}\x{78EA}\x{78EB}\x{78EC}\x{78ED}' - . '\x{78EE}\x{78EF}\x{78F1}\x{78F2}\x{78F3}\x{78F4}\x{78F5}\x{78F6}\x{78F7}' - . '\x{78F9}\x{78FA}\x{78FB}\x{78FC}\x{78FD}\x{78FE}\x{78FF}\x{7901}\x{7902}' - . '\x{7903}\x{7904}\x{7905}\x{7906}\x{7907}\x{7909}\x{790A}\x{790B}\x{790C}' - . '\x{790E}\x{790F}\x{7910}\x{7911}\x{7912}\x{7913}\x{7914}\x{7916}\x{7917}' - . '\x{7918}\x{7919}\x{791A}\x{791B}\x{791C}\x{791D}\x{791E}\x{7921}\x{7922}' - . '\x{7923}\x{7924}\x{7925}\x{7926}\x{7927}\x{7928}\x{7929}\x{792A}\x{792B}' - . '\x{792C}\x{792D}\x{792E}\x{792F}\x{7930}\x{7931}\x{7933}\x{7934}\x{7935}' - . '\x{7937}\x{7938}\x{7939}\x{793A}\x{793B}\x{793C}\x{793D}\x{793E}\x{793F}' - . '\x{7940}\x{7941}\x{7942}\x{7943}\x{7944}\x{7945}\x{7946}\x{7947}\x{7948}' - . '\x{7949}\x{794A}\x{794B}\x{794C}\x{794D}\x{794E}\x{794F}\x{7950}\x{7951}' - . '\x{7952}\x{7953}\x{7954}\x{7955}\x{7956}\x{7957}\x{7958}\x{795A}\x{795B}' - . '\x{795C}\x{795D}\x{795E}\x{795F}\x{7960}\x{7961}\x{7962}\x{7963}\x{7964}' - . '\x{7965}\x{7966}\x{7967}\x{7968}\x{7969}\x{796A}\x{796B}\x{796D}\x{796F}' - . '\x{7970}\x{7971}\x{7972}\x{7973}\x{7974}\x{7977}\x{7978}\x{7979}\x{797A}' - . '\x{797B}\x{797C}\x{797D}\x{797E}\x{797F}\x{7980}\x{7981}\x{7982}\x{7983}' - . '\x{7984}\x{7985}\x{7988}\x{7989}\x{798A}\x{798B}\x{798C}\x{798D}\x{798E}' - . '\x{798F}\x{7990}\x{7991}\x{7992}\x{7993}\x{7994}\x{7995}\x{7996}\x{7997}' - . '\x{7998}\x{7999}\x{799A}\x{799B}\x{799C}\x{799F}\x{79A0}\x{79A1}\x{79A2}' - . '\x{79A3}\x{79A4}\x{79A5}\x{79A6}\x{79A7}\x{79A8}\x{79AA}\x{79AB}\x{79AC}' - . '\x{79AD}\x{79AE}\x{79AF}\x{79B0}\x{79B1}\x{79B2}\x{79B3}\x{79B4}\x{79B5}' - . '\x{79B6}\x{79B7}\x{79B8}\x{79B9}\x{79BA}\x{79BB}\x{79BD}\x{79BE}\x{79BF}' - . '\x{79C0}\x{79C1}\x{79C2}\x{79C3}\x{79C5}\x{79C6}\x{79C8}\x{79C9}\x{79CA}' - . '\x{79CB}\x{79CD}\x{79CE}\x{79CF}\x{79D0}\x{79D1}\x{79D2}\x{79D3}\x{79D5}' - . '\x{79D6}\x{79D8}\x{79D9}\x{79DA}\x{79DB}\x{79DC}\x{79DD}\x{79DE}\x{79DF}' - . '\x{79E0}\x{79E1}\x{79E2}\x{79E3}\x{79E4}\x{79E5}\x{79E6}\x{79E7}\x{79E8}' - . '\x{79E9}\x{79EA}\x{79EB}\x{79EC}\x{79ED}\x{79EE}\x{79EF}\x{79F0}\x{79F1}' - . '\x{79F2}\x{79F3}\x{79F4}\x{79F5}\x{79F6}\x{79F7}\x{79F8}\x{79F9}\x{79FA}' - . '\x{79FB}\x{79FC}\x{79FD}\x{79FE}\x{79FF}\x{7A00}\x{7A02}\x{7A03}\x{7A04}' - . '\x{7A05}\x{7A06}\x{7A08}\x{7A0A}\x{7A0B}\x{7A0C}\x{7A0D}\x{7A0E}\x{7A0F}' - . '\x{7A10}\x{7A11}\x{7A12}\x{7A13}\x{7A14}\x{7A15}\x{7A16}\x{7A17}\x{7A18}' - . '\x{7A19}\x{7A1A}\x{7A1B}\x{7A1C}\x{7A1D}\x{7A1E}\x{7A1F}\x{7A20}\x{7A21}' - . '\x{7A22}\x{7A23}\x{7A24}\x{7A25}\x{7A26}\x{7A27}\x{7A28}\x{7A29}\x{7A2A}' - . '\x{7A2B}\x{7A2D}\x{7A2E}\x{7A2F}\x{7A30}\x{7A31}\x{7A32}\x{7A33}\x{7A34}' - . '\x{7A35}\x{7A37}\x{7A39}\x{7A3B}\x{7A3C}\x{7A3D}\x{7A3E}\x{7A3F}\x{7A40}' - . '\x{7A41}\x{7A42}\x{7A43}\x{7A44}\x{7A45}\x{7A46}\x{7A47}\x{7A48}\x{7A49}' - . '\x{7A4A}\x{7A4B}\x{7A4C}\x{7A4D}\x{7A4E}\x{7A50}\x{7A51}\x{7A52}\x{7A53}' - . '\x{7A54}\x{7A55}\x{7A56}\x{7A57}\x{7A58}\x{7A59}\x{7A5A}\x{7A5B}\x{7A5C}' - . '\x{7A5D}\x{7A5E}\x{7A5F}\x{7A60}\x{7A61}\x{7A62}\x{7A65}\x{7A66}\x{7A67}' - . '\x{7A68}\x{7A69}\x{7A6B}\x{7A6C}\x{7A6D}\x{7A6E}\x{7A70}\x{7A71}\x{7A72}' - . '\x{7A73}\x{7A74}\x{7A75}\x{7A76}\x{7A77}\x{7A78}\x{7A79}\x{7A7A}\x{7A7B}' - . '\x{7A7C}\x{7A7D}\x{7A7E}\x{7A7F}\x{7A80}\x{7A81}\x{7A83}\x{7A84}\x{7A85}' - . '\x{7A86}\x{7A87}\x{7A88}\x{7A89}\x{7A8A}\x{7A8B}\x{7A8C}\x{7A8D}\x{7A8E}' - . '\x{7A8F}\x{7A90}\x{7A91}\x{7A92}\x{7A93}\x{7A94}\x{7A95}\x{7A96}\x{7A97}' - . '\x{7A98}\x{7A99}\x{7A9C}\x{7A9D}\x{7A9E}\x{7A9F}\x{7AA0}\x{7AA1}\x{7AA2}' - . '\x{7AA3}\x{7AA4}\x{7AA5}\x{7AA6}\x{7AA7}\x{7AA8}\x{7AA9}\x{7AAA}\x{7AAB}' - . '\x{7AAC}\x{7AAD}\x{7AAE}\x{7AAF}\x{7AB0}\x{7AB1}\x{7AB2}\x{7AB3}\x{7AB4}' - . '\x{7AB5}\x{7AB6}\x{7AB7}\x{7AB8}\x{7ABA}\x{7ABE}\x{7ABF}\x{7AC0}\x{7AC1}' - . '\x{7AC4}\x{7AC5}\x{7AC7}\x{7AC8}\x{7AC9}\x{7ACA}\x{7ACB}\x{7ACC}\x{7ACD}' - . '\x{7ACE}\x{7ACF}\x{7AD0}\x{7AD1}\x{7AD2}\x{7AD3}\x{7AD4}\x{7AD5}\x{7AD6}' - . '\x{7AD8}\x{7AD9}\x{7ADB}\x{7ADC}\x{7ADD}\x{7ADE}\x{7ADF}\x{7AE0}\x{7AE1}' - . '\x{7AE2}\x{7AE3}\x{7AE4}\x{7AE5}\x{7AE6}\x{7AE7}\x{7AE8}\x{7AEA}\x{7AEB}' - . '\x{7AEC}\x{7AED}\x{7AEE}\x{7AEF}\x{7AF0}\x{7AF1}\x{7AF2}\x{7AF3}\x{7AF4}' - . '\x{7AF6}\x{7AF7}\x{7AF8}\x{7AF9}\x{7AFA}\x{7AFB}\x{7AFD}\x{7AFE}\x{7AFF}' - . '\x{7B00}\x{7B01}\x{7B02}\x{7B03}\x{7B04}\x{7B05}\x{7B06}\x{7B08}\x{7B09}' - . '\x{7B0A}\x{7B0B}\x{7B0C}\x{7B0D}\x{7B0E}\x{7B0F}\x{7B10}\x{7B11}\x{7B12}' - . '\x{7B13}\x{7B14}\x{7B15}\x{7B16}\x{7B17}\x{7B18}\x{7B19}\x{7B1A}\x{7B1B}' - . '\x{7B1C}\x{7B1D}\x{7B1E}\x{7B20}\x{7B21}\x{7B22}\x{7B23}\x{7B24}\x{7B25}' - . '\x{7B26}\x{7B28}\x{7B2A}\x{7B2B}\x{7B2C}\x{7B2D}\x{7B2E}\x{7B2F}\x{7B30}' - . '\x{7B31}\x{7B32}\x{7B33}\x{7B34}\x{7B35}\x{7B36}\x{7B37}\x{7B38}\x{7B39}' - . '\x{7B3A}\x{7B3B}\x{7B3C}\x{7B3D}\x{7B3E}\x{7B3F}\x{7B40}\x{7B41}\x{7B43}' - . '\x{7B44}\x{7B45}\x{7B46}\x{7B47}\x{7B48}\x{7B49}\x{7B4A}\x{7B4B}\x{7B4C}' - . '\x{7B4D}\x{7B4E}\x{7B4F}\x{7B50}\x{7B51}\x{7B52}\x{7B54}\x{7B55}\x{7B56}' - . '\x{7B57}\x{7B58}\x{7B59}\x{7B5A}\x{7B5B}\x{7B5C}\x{7B5D}\x{7B5E}\x{7B5F}' - . '\x{7B60}\x{7B61}\x{7B62}\x{7B63}\x{7B64}\x{7B65}\x{7B66}\x{7B67}\x{7B68}' - . '\x{7B69}\x{7B6A}\x{7B6B}\x{7B6C}\x{7B6D}\x{7B6E}\x{7B70}\x{7B71}\x{7B72}' - . '\x{7B73}\x{7B74}\x{7B75}\x{7B76}\x{7B77}\x{7B78}\x{7B79}\x{7B7B}\x{7B7C}' - . '\x{7B7D}\x{7B7E}\x{7B7F}\x{7B80}\x{7B81}\x{7B82}\x{7B83}\x{7B84}\x{7B85}' - . '\x{7B87}\x{7B88}\x{7B89}\x{7B8A}\x{7B8B}\x{7B8C}\x{7B8D}\x{7B8E}\x{7B8F}' - . '\x{7B90}\x{7B91}\x{7B93}\x{7B94}\x{7B95}\x{7B96}\x{7B97}\x{7B98}\x{7B99}' - . '\x{7B9A}\x{7B9B}\x{7B9C}\x{7B9D}\x{7B9E}\x{7B9F}\x{7BA0}\x{7BA1}\x{7BA2}' - . '\x{7BA4}\x{7BA6}\x{7BA7}\x{7BA8}\x{7BA9}\x{7BAA}\x{7BAB}\x{7BAC}\x{7BAD}' - . '\x{7BAE}\x{7BAF}\x{7BB1}\x{7BB3}\x{7BB4}\x{7BB5}\x{7BB6}\x{7BB7}\x{7BB8}' - . '\x{7BB9}\x{7BBA}\x{7BBB}\x{7BBC}\x{7BBD}\x{7BBE}\x{7BBF}\x{7BC0}\x{7BC1}' - . '\x{7BC2}\x{7BC3}\x{7BC4}\x{7BC5}\x{7BC6}\x{7BC7}\x{7BC8}\x{7BC9}\x{7BCA}' - . '\x{7BCB}\x{7BCC}\x{7BCD}\x{7BCE}\x{7BD0}\x{7BD1}\x{7BD2}\x{7BD3}\x{7BD4}' - . '\x{7BD5}\x{7BD6}\x{7BD7}\x{7BD8}\x{7BD9}\x{7BDA}\x{7BDB}\x{7BDC}\x{7BDD}' - . '\x{7BDE}\x{7BDF}\x{7BE0}\x{7BE1}\x{7BE2}\x{7BE3}\x{7BE4}\x{7BE5}\x{7BE6}' - . '\x{7BE7}\x{7BE8}\x{7BE9}\x{7BEA}\x{7BEB}\x{7BEC}\x{7BED}\x{7BEE}\x{7BEF}' - . '\x{7BF0}\x{7BF1}\x{7BF2}\x{7BF3}\x{7BF4}\x{7BF5}\x{7BF6}\x{7BF7}\x{7BF8}' - . '\x{7BF9}\x{7BFB}\x{7BFC}\x{7BFD}\x{7BFE}\x{7BFF}\x{7C00}\x{7C01}\x{7C02}' - . '\x{7C03}\x{7C04}\x{7C05}\x{7C06}\x{7C07}\x{7C08}\x{7C09}\x{7C0A}\x{7C0B}' - . '\x{7C0C}\x{7C0D}\x{7C0E}\x{7C0F}\x{7C10}\x{7C11}\x{7C12}\x{7C13}\x{7C15}' - . '\x{7C16}\x{7C17}\x{7C18}\x{7C19}\x{7C1A}\x{7C1C}\x{7C1D}\x{7C1E}\x{7C1F}' - . '\x{7C20}\x{7C21}\x{7C22}\x{7C23}\x{7C24}\x{7C25}\x{7C26}\x{7C27}\x{7C28}' - . '\x{7C29}\x{7C2A}\x{7C2B}\x{7C2C}\x{7C2D}\x{7C30}\x{7C31}\x{7C32}\x{7C33}' - . '\x{7C34}\x{7C35}\x{7C36}\x{7C37}\x{7C38}\x{7C39}\x{7C3A}\x{7C3B}\x{7C3C}' - . '\x{7C3D}\x{7C3E}\x{7C3F}\x{7C40}\x{7C41}\x{7C42}\x{7C43}\x{7C44}\x{7C45}' - . '\x{7C46}\x{7C47}\x{7C48}\x{7C49}\x{7C4A}\x{7C4B}\x{7C4C}\x{7C4D}\x{7C4E}' - . '\x{7C50}\x{7C51}\x{7C53}\x{7C54}\x{7C56}\x{7C57}\x{7C58}\x{7C59}\x{7C5A}' - . '\x{7C5B}\x{7C5C}\x{7C5E}\x{7C5F}\x{7C60}\x{7C61}\x{7C62}\x{7C63}\x{7C64}' - . '\x{7C65}\x{7C66}\x{7C67}\x{7C68}\x{7C69}\x{7C6A}\x{7C6B}\x{7C6C}\x{7C6D}' - . '\x{7C6E}\x{7C6F}\x{7C70}\x{7C71}\x{7C72}\x{7C73}\x{7C74}\x{7C75}\x{7C77}' - . '\x{7C78}\x{7C79}\x{7C7A}\x{7C7B}\x{7C7C}\x{7C7D}\x{7C7E}\x{7C7F}\x{7C80}' - . '\x{7C81}\x{7C82}\x{7C84}\x{7C85}\x{7C86}\x{7C88}\x{7C89}\x{7C8A}\x{7C8B}' - . '\x{7C8C}\x{7C8D}\x{7C8E}\x{7C8F}\x{7C90}\x{7C91}\x{7C92}\x{7C94}\x{7C95}' - . '\x{7C96}\x{7C97}\x{7C98}\x{7C99}\x{7C9B}\x{7C9C}\x{7C9D}\x{7C9E}\x{7C9F}' - . '\x{7CA0}\x{7CA1}\x{7CA2}\x{7CA3}\x{7CA4}\x{7CA5}\x{7CA6}\x{7CA7}\x{7CA8}' - . '\x{7CA9}\x{7CAA}\x{7CAD}\x{7CAE}\x{7CAF}\x{7CB0}\x{7CB1}\x{7CB2}\x{7CB3}' - . '\x{7CB4}\x{7CB5}\x{7CB6}\x{7CB7}\x{7CB8}\x{7CB9}\x{7CBA}\x{7CBB}\x{7CBC}' - . '\x{7CBD}\x{7CBE}\x{7CBF}\x{7CC0}\x{7CC1}\x{7CC2}\x{7CC3}\x{7CC4}\x{7CC5}' - . '\x{7CC6}\x{7CC7}\x{7CC8}\x{7CC9}\x{7CCA}\x{7CCB}\x{7CCC}\x{7CCD}\x{7CCE}' - . '\x{7CCF}\x{7CD0}\x{7CD1}\x{7CD2}\x{7CD4}\x{7CD5}\x{7CD6}\x{7CD7}\x{7CD8}' - . '\x{7CD9}\x{7CDC}\x{7CDD}\x{7CDE}\x{7CDF}\x{7CE0}\x{7CE2}\x{7CE4}\x{7CE7}' - . '\x{7CE8}\x{7CE9}\x{7CEA}\x{7CEB}\x{7CEC}\x{7CED}\x{7CEE}\x{7CEF}\x{7CF0}' - . '\x{7CF1}\x{7CF2}\x{7CF3}\x{7CF4}\x{7CF5}\x{7CF6}\x{7CF7}\x{7CF8}\x{7CF9}' - . '\x{7CFA}\x{7CFB}\x{7CFD}\x{7CFE}\x{7D00}\x{7D01}\x{7D02}\x{7D03}\x{7D04}' - . '\x{7D05}\x{7D06}\x{7D07}\x{7D08}\x{7D09}\x{7D0A}\x{7D0B}\x{7D0C}\x{7D0D}' - . '\x{7D0E}\x{7D0F}\x{7D10}\x{7D11}\x{7D12}\x{7D13}\x{7D14}\x{7D15}\x{7D16}' - . '\x{7D17}\x{7D18}\x{7D19}\x{7D1A}\x{7D1B}\x{7D1C}\x{7D1D}\x{7D1E}\x{7D1F}' - . '\x{7D20}\x{7D21}\x{7D22}\x{7D24}\x{7D25}\x{7D26}\x{7D27}\x{7D28}\x{7D29}' - . '\x{7D2B}\x{7D2C}\x{7D2E}\x{7D2F}\x{7D30}\x{7D31}\x{7D32}\x{7D33}\x{7D34}' - . '\x{7D35}\x{7D36}\x{7D37}\x{7D38}\x{7D39}\x{7D3A}\x{7D3B}\x{7D3C}\x{7D3D}' - . '\x{7D3E}\x{7D3F}\x{7D40}\x{7D41}\x{7D42}\x{7D43}\x{7D44}\x{7D45}\x{7D46}' - . '\x{7D47}\x{7D49}\x{7D4A}\x{7D4B}\x{7D4C}\x{7D4E}\x{7D4F}\x{7D50}\x{7D51}' - . '\x{7D52}\x{7D53}\x{7D54}\x{7D55}\x{7D56}\x{7D57}\x{7D58}\x{7D59}\x{7D5B}' - . '\x{7D5C}\x{7D5D}\x{7D5E}\x{7D5F}\x{7D60}\x{7D61}\x{7D62}\x{7D63}\x{7D65}' - . '\x{7D66}\x{7D67}\x{7D68}\x{7D69}\x{7D6A}\x{7D6B}\x{7D6C}\x{7D6D}\x{7D6E}' - . '\x{7D6F}\x{7D70}\x{7D71}\x{7D72}\x{7D73}\x{7D74}\x{7D75}\x{7D76}\x{7D77}' - . '\x{7D79}\x{7D7A}\x{7D7B}\x{7D7C}\x{7D7D}\x{7D7E}\x{7D7F}\x{7D80}\x{7D81}' - . '\x{7D83}\x{7D84}\x{7D85}\x{7D86}\x{7D87}\x{7D88}\x{7D89}\x{7D8A}\x{7D8B}' - . '\x{7D8C}\x{7D8D}\x{7D8E}\x{7D8F}\x{7D90}\x{7D91}\x{7D92}\x{7D93}\x{7D94}' - . '\x{7D96}\x{7D97}\x{7D99}\x{7D9B}\x{7D9C}\x{7D9D}\x{7D9E}\x{7D9F}\x{7DA0}' - . '\x{7DA1}\x{7DA2}\x{7DA3}\x{7DA5}\x{7DA6}\x{7DA7}\x{7DA9}\x{7DAA}\x{7DAB}' - . '\x{7DAC}\x{7DAD}\x{7DAE}\x{7DAF}\x{7DB0}\x{7DB1}\x{7DB2}\x{7DB3}\x{7DB4}' - . '\x{7DB5}\x{7DB6}\x{7DB7}\x{7DB8}\x{7DB9}\x{7DBA}\x{7DBB}\x{7DBC}\x{7DBD}' - . '\x{7DBE}\x{7DBF}\x{7DC0}\x{7DC1}\x{7DC2}\x{7DC3}\x{7DC4}\x{7DC5}\x{7DC6}' - . '\x{7DC7}\x{7DC8}\x{7DC9}\x{7DCA}\x{7DCB}\x{7DCC}\x{7DCE}\x{7DCF}\x{7DD0}' - . '\x{7DD1}\x{7DD2}\x{7DD4}\x{7DD5}\x{7DD6}\x{7DD7}\x{7DD8}\x{7DD9}\x{7DDA}' - . '\x{7DDB}\x{7DDD}\x{7DDE}\x{7DDF}\x{7DE0}\x{7DE1}\x{7DE2}\x{7DE3}\x{7DE6}' - . '\x{7DE7}\x{7DE8}\x{7DE9}\x{7DEA}\x{7DEC}\x{7DED}\x{7DEE}\x{7DEF}\x{7DF0}' - . '\x{7DF1}\x{7DF2}\x{7DF3}\x{7DF4}\x{7DF5}\x{7DF6}\x{7DF7}\x{7DF8}\x{7DF9}' - . '\x{7DFA}\x{7DFB}\x{7DFC}\x{7E00}\x{7E01}\x{7E02}\x{7E03}\x{7E04}\x{7E05}' - . '\x{7E06}\x{7E07}\x{7E08}\x{7E09}\x{7E0A}\x{7E0B}\x{7E0C}\x{7E0D}\x{7E0E}' - . '\x{7E0F}\x{7E10}\x{7E11}\x{7E12}\x{7E13}\x{7E14}\x{7E15}\x{7E16}\x{7E17}' - . '\x{7E19}\x{7E1A}\x{7E1B}\x{7E1C}\x{7E1D}\x{7E1E}\x{7E1F}\x{7E20}\x{7E21}' - . '\x{7E22}\x{7E23}\x{7E24}\x{7E25}\x{7E26}\x{7E27}\x{7E28}\x{7E29}\x{7E2A}' - . '\x{7E2B}\x{7E2C}\x{7E2D}\x{7E2E}\x{7E2F}\x{7E30}\x{7E31}\x{7E32}\x{7E33}' - . '\x{7E34}\x{7E35}\x{7E36}\x{7E37}\x{7E38}\x{7E39}\x{7E3A}\x{7E3B}\x{7E3C}' - . '\x{7E3D}\x{7E3E}\x{7E3F}\x{7E40}\x{7E41}\x{7E42}\x{7E43}\x{7E44}\x{7E45}' - . '\x{7E46}\x{7E47}\x{7E48}\x{7E49}\x{7E4C}\x{7E4D}\x{7E4E}\x{7E4F}\x{7E50}' - . '\x{7E51}\x{7E52}\x{7E53}\x{7E54}\x{7E55}\x{7E56}\x{7E57}\x{7E58}\x{7E59}' - . '\x{7E5A}\x{7E5C}\x{7E5D}\x{7E5E}\x{7E5F}\x{7E60}\x{7E61}\x{7E62}\x{7E63}' - . '\x{7E65}\x{7E66}\x{7E67}\x{7E68}\x{7E69}\x{7E6A}\x{7E6B}\x{7E6C}\x{7E6D}' - . '\x{7E6E}\x{7E6F}\x{7E70}\x{7E71}\x{7E72}\x{7E73}\x{7E74}\x{7E75}\x{7E76}' - . '\x{7E77}\x{7E78}\x{7E79}\x{7E7A}\x{7E7B}\x{7E7C}\x{7E7D}\x{7E7E}\x{7E7F}' - . '\x{7E80}\x{7E81}\x{7E82}\x{7E83}\x{7E84}\x{7E85}\x{7E86}\x{7E87}\x{7E88}' - . '\x{7E89}\x{7E8A}\x{7E8B}\x{7E8C}\x{7E8D}\x{7E8E}\x{7E8F}\x{7E90}\x{7E91}' - . '\x{7E92}\x{7E93}\x{7E94}\x{7E95}\x{7E96}\x{7E97}\x{7E98}\x{7E99}\x{7E9A}' - . '\x{7E9B}\x{7E9C}\x{7E9E}\x{7E9F}\x{7EA0}\x{7EA1}\x{7EA2}\x{7EA3}\x{7EA4}' - . '\x{7EA5}\x{7EA6}\x{7EA7}\x{7EA8}\x{7EA9}\x{7EAA}\x{7EAB}\x{7EAC}\x{7EAD}' - . '\x{7EAE}\x{7EAF}\x{7EB0}\x{7EB1}\x{7EB2}\x{7EB3}\x{7EB4}\x{7EB5}\x{7EB6}' - . '\x{7EB7}\x{7EB8}\x{7EB9}\x{7EBA}\x{7EBB}\x{7EBC}\x{7EBD}\x{7EBE}\x{7EBF}' - . '\x{7EC0}\x{7EC1}\x{7EC2}\x{7EC3}\x{7EC4}\x{7EC5}\x{7EC6}\x{7EC7}\x{7EC8}' - . '\x{7EC9}\x{7ECA}\x{7ECB}\x{7ECC}\x{7ECD}\x{7ECE}\x{7ECF}\x{7ED0}\x{7ED1}' - . '\x{7ED2}\x{7ED3}\x{7ED4}\x{7ED5}\x{7ED6}\x{7ED7}\x{7ED8}\x{7ED9}\x{7EDA}' - . '\x{7EDB}\x{7EDC}\x{7EDD}\x{7EDE}\x{7EDF}\x{7EE0}\x{7EE1}\x{7EE2}\x{7EE3}' - . '\x{7EE4}\x{7EE5}\x{7EE6}\x{7EE7}\x{7EE8}\x{7EE9}\x{7EEA}\x{7EEB}\x{7EEC}' - . '\x{7EED}\x{7EEE}\x{7EEF}\x{7EF0}\x{7EF1}\x{7EF2}\x{7EF3}\x{7EF4}\x{7EF5}' - . '\x{7EF6}\x{7EF7}\x{7EF8}\x{7EF9}\x{7EFA}\x{7EFB}\x{7EFC}\x{7EFD}\x{7EFE}' - . '\x{7EFF}\x{7F00}\x{7F01}\x{7F02}\x{7F03}\x{7F04}\x{7F05}\x{7F06}\x{7F07}' - . '\x{7F08}\x{7F09}\x{7F0A}\x{7F0B}\x{7F0C}\x{7F0D}\x{7F0E}\x{7F0F}\x{7F10}' - . '\x{7F11}\x{7F12}\x{7F13}\x{7F14}\x{7F15}\x{7F16}\x{7F17}\x{7F18}\x{7F19}' - . '\x{7F1A}\x{7F1B}\x{7F1C}\x{7F1D}\x{7F1E}\x{7F1F}\x{7F20}\x{7F21}\x{7F22}' - . '\x{7F23}\x{7F24}\x{7F25}\x{7F26}\x{7F27}\x{7F28}\x{7F29}\x{7F2A}\x{7F2B}' - . '\x{7F2C}\x{7F2D}\x{7F2E}\x{7F2F}\x{7F30}\x{7F31}\x{7F32}\x{7F33}\x{7F34}' - . '\x{7F35}\x{7F36}\x{7F37}\x{7F38}\x{7F39}\x{7F3A}\x{7F3D}\x{7F3E}\x{7F3F}' - . '\x{7F40}\x{7F42}\x{7F43}\x{7F44}\x{7F45}\x{7F47}\x{7F48}\x{7F49}\x{7F4A}' - . '\x{7F4B}\x{7F4C}\x{7F4D}\x{7F4E}\x{7F4F}\x{7F50}\x{7F51}\x{7F52}\x{7F53}' - . '\x{7F54}\x{7F55}\x{7F56}\x{7F57}\x{7F58}\x{7F5A}\x{7F5B}\x{7F5C}\x{7F5D}' - . '\x{7F5E}\x{7F5F}\x{7F60}\x{7F61}\x{7F62}\x{7F63}\x{7F64}\x{7F65}\x{7F66}' - . '\x{7F67}\x{7F68}\x{7F69}\x{7F6A}\x{7F6B}\x{7F6C}\x{7F6D}\x{7F6E}\x{7F6F}' - . '\x{7F70}\x{7F71}\x{7F72}\x{7F73}\x{7F74}\x{7F75}\x{7F76}\x{7F77}\x{7F78}' - . '\x{7F79}\x{7F7A}\x{7F7B}\x{7F7C}\x{7F7D}\x{7F7E}\x{7F7F}\x{7F80}\x{7F81}' - . '\x{7F82}\x{7F83}\x{7F85}\x{7F86}\x{7F87}\x{7F88}\x{7F89}\x{7F8A}\x{7F8B}' - . '\x{7F8C}\x{7F8D}\x{7F8E}\x{7F8F}\x{7F91}\x{7F92}\x{7F93}\x{7F94}\x{7F95}' - . '\x{7F96}\x{7F98}\x{7F9A}\x{7F9B}\x{7F9C}\x{7F9D}\x{7F9E}\x{7F9F}\x{7FA0}' - . '\x{7FA1}\x{7FA2}\x{7FA3}\x{7FA4}\x{7FA5}\x{7FA6}\x{7FA7}\x{7FA8}\x{7FA9}' - . '\x{7FAA}\x{7FAB}\x{7FAC}\x{7FAD}\x{7FAE}\x{7FAF}\x{7FB0}\x{7FB1}\x{7FB2}' - . '\x{7FB3}\x{7FB5}\x{7FB6}\x{7FB7}\x{7FB8}\x{7FB9}\x{7FBA}\x{7FBB}\x{7FBC}' - . '\x{7FBD}\x{7FBE}\x{7FBF}\x{7FC0}\x{7FC1}\x{7FC2}\x{7FC3}\x{7FC4}\x{7FC5}' - . '\x{7FC6}\x{7FC7}\x{7FC8}\x{7FC9}\x{7FCA}\x{7FCB}\x{7FCC}\x{7FCD}\x{7FCE}' - . '\x{7FCF}\x{7FD0}\x{7FD1}\x{7FD2}\x{7FD3}\x{7FD4}\x{7FD5}\x{7FD7}\x{7FD8}' - . '\x{7FD9}\x{7FDA}\x{7FDB}\x{7FDC}\x{7FDE}\x{7FDF}\x{7FE0}\x{7FE1}\x{7FE2}' - . '\x{7FE3}\x{7FE5}\x{7FE6}\x{7FE7}\x{7FE8}\x{7FE9}\x{7FEA}\x{7FEB}\x{7FEC}' - . '\x{7FED}\x{7FEE}\x{7FEF}\x{7FF0}\x{7FF1}\x{7FF2}\x{7FF3}\x{7FF4}\x{7FF5}' - . '\x{7FF6}\x{7FF7}\x{7FF8}\x{7FF9}\x{7FFA}\x{7FFB}\x{7FFC}\x{7FFD}\x{7FFE}' - . '\x{7FFF}\x{8000}\x{8001}\x{8002}\x{8003}\x{8004}\x{8005}\x{8006}\x{8007}' - . '\x{8008}\x{8009}\x{800B}\x{800C}\x{800D}\x{800E}\x{800F}\x{8010}\x{8011}' - . '\x{8012}\x{8013}\x{8014}\x{8015}\x{8016}\x{8017}\x{8018}\x{8019}\x{801A}' - . '\x{801B}\x{801C}\x{801D}\x{801E}\x{801F}\x{8020}\x{8021}\x{8022}\x{8023}' - . '\x{8024}\x{8025}\x{8026}\x{8027}\x{8028}\x{8029}\x{802A}\x{802B}\x{802C}' - . '\x{802D}\x{802E}\x{8030}\x{8031}\x{8032}\x{8033}\x{8034}\x{8035}\x{8036}' - . '\x{8037}\x{8038}\x{8039}\x{803A}\x{803B}\x{803D}\x{803E}\x{803F}\x{8041}' - . '\x{8042}\x{8043}\x{8044}\x{8045}\x{8046}\x{8047}\x{8048}\x{8049}\x{804A}' - . '\x{804B}\x{804C}\x{804D}\x{804E}\x{804F}\x{8050}\x{8051}\x{8052}\x{8053}' - . '\x{8054}\x{8055}\x{8056}\x{8057}\x{8058}\x{8059}\x{805A}\x{805B}\x{805C}' - . '\x{805D}\x{805E}\x{805F}\x{8060}\x{8061}\x{8062}\x{8063}\x{8064}\x{8065}' - . '\x{8067}\x{8068}\x{8069}\x{806A}\x{806B}\x{806C}\x{806D}\x{806E}\x{806F}' - . '\x{8070}\x{8071}\x{8072}\x{8073}\x{8074}\x{8075}\x{8076}\x{8077}\x{8078}' - . '\x{8079}\x{807A}\x{807B}\x{807C}\x{807D}\x{807E}\x{807F}\x{8080}\x{8081}' - . '\x{8082}\x{8083}\x{8084}\x{8085}\x{8086}\x{8087}\x{8089}\x{808A}\x{808B}' - . '\x{808C}\x{808D}\x{808F}\x{8090}\x{8091}\x{8092}\x{8093}\x{8095}\x{8096}' - . '\x{8097}\x{8098}\x{8099}\x{809A}\x{809B}\x{809C}\x{809D}\x{809E}\x{809F}' - . '\x{80A0}\x{80A1}\x{80A2}\x{80A3}\x{80A4}\x{80A5}\x{80A9}\x{80AA}\x{80AB}' - . '\x{80AD}\x{80AE}\x{80AF}\x{80B0}\x{80B1}\x{80B2}\x{80B4}\x{80B5}\x{80B6}' - . '\x{80B7}\x{80B8}\x{80BA}\x{80BB}\x{80BC}\x{80BD}\x{80BE}\x{80BF}\x{80C0}' - . '\x{80C1}\x{80C2}\x{80C3}\x{80C4}\x{80C5}\x{80C6}\x{80C7}\x{80C8}\x{80C9}' - . '\x{80CA}\x{80CB}\x{80CC}\x{80CD}\x{80CE}\x{80CF}\x{80D0}\x{80D1}\x{80D2}' - . '\x{80D3}\x{80D4}\x{80D5}\x{80D6}\x{80D7}\x{80D8}\x{80D9}\x{80DA}\x{80DB}' - . '\x{80DC}\x{80DD}\x{80DE}\x{80E0}\x{80E1}\x{80E2}\x{80E3}\x{80E4}\x{80E5}' - . '\x{80E6}\x{80E7}\x{80E8}\x{80E9}\x{80EA}\x{80EB}\x{80EC}\x{80ED}\x{80EE}' - . '\x{80EF}\x{80F0}\x{80F1}\x{80F2}\x{80F3}\x{80F4}\x{80F5}\x{80F6}\x{80F7}' - . '\x{80F8}\x{80F9}\x{80FA}\x{80FB}\x{80FC}\x{80FD}\x{80FE}\x{80FF}\x{8100}' - . '\x{8101}\x{8102}\x{8105}\x{8106}\x{8107}\x{8108}\x{8109}\x{810A}\x{810B}' - . '\x{810C}\x{810D}\x{810E}\x{810F}\x{8110}\x{8111}\x{8112}\x{8113}\x{8114}' - . '\x{8115}\x{8116}\x{8118}\x{8119}\x{811A}\x{811B}\x{811C}\x{811D}\x{811E}' - . '\x{811F}\x{8120}\x{8121}\x{8122}\x{8123}\x{8124}\x{8125}\x{8126}\x{8127}' - . '\x{8128}\x{8129}\x{812A}\x{812B}\x{812C}\x{812D}\x{812E}\x{812F}\x{8130}' - . '\x{8131}\x{8132}\x{8136}\x{8137}\x{8138}\x{8139}\x{813A}\x{813B}\x{813C}' - . '\x{813D}\x{813E}\x{813F}\x{8140}\x{8141}\x{8142}\x{8143}\x{8144}\x{8145}' - . '\x{8146}\x{8147}\x{8148}\x{8149}\x{814A}\x{814B}\x{814C}\x{814D}\x{814E}' - . '\x{814F}\x{8150}\x{8151}\x{8152}\x{8153}\x{8154}\x{8155}\x{8156}\x{8157}' - . '\x{8158}\x{8159}\x{815A}\x{815B}\x{815C}\x{815D}\x{815E}\x{8160}\x{8161}' - . '\x{8162}\x{8163}\x{8164}\x{8165}\x{8166}\x{8167}\x{8168}\x{8169}\x{816A}' - . '\x{816B}\x{816C}\x{816D}\x{816E}\x{816F}\x{8170}\x{8171}\x{8172}\x{8173}' - . '\x{8174}\x{8175}\x{8176}\x{8177}\x{8178}\x{8179}\x{817A}\x{817B}\x{817C}' - . '\x{817D}\x{817E}\x{817F}\x{8180}\x{8181}\x{8182}\x{8183}\x{8185}\x{8186}' - . '\x{8187}\x{8188}\x{8189}\x{818A}\x{818B}\x{818C}\x{818D}\x{818E}\x{818F}' - . '\x{8191}\x{8192}\x{8193}\x{8194}\x{8195}\x{8197}\x{8198}\x{8199}\x{819A}' - . '\x{819B}\x{819C}\x{819D}\x{819E}\x{819F}\x{81A0}\x{81A1}\x{81A2}\x{81A3}' - . '\x{81A4}\x{81A5}\x{81A6}\x{81A7}\x{81A8}\x{81A9}\x{81AA}\x{81AB}\x{81AC}' - . '\x{81AD}\x{81AE}\x{81AF}\x{81B0}\x{81B1}\x{81B2}\x{81B3}\x{81B4}\x{81B5}' - . '\x{81B6}\x{81B7}\x{81B8}\x{81B9}\x{81BA}\x{81BB}\x{81BC}\x{81BD}\x{81BE}' - . '\x{81BF}\x{81C0}\x{81C1}\x{81C2}\x{81C3}\x{81C4}\x{81C5}\x{81C6}\x{81C7}' - . '\x{81C8}\x{81C9}\x{81CA}\x{81CC}\x{81CD}\x{81CE}\x{81CF}\x{81D0}\x{81D1}' - . '\x{81D2}\x{81D4}\x{81D5}\x{81D6}\x{81D7}\x{81D8}\x{81D9}\x{81DA}\x{81DB}' - . '\x{81DC}\x{81DD}\x{81DE}\x{81DF}\x{81E0}\x{81E1}\x{81E2}\x{81E3}\x{81E5}' - . '\x{81E6}\x{81E7}\x{81E8}\x{81E9}\x{81EA}\x{81EB}\x{81EC}\x{81ED}\x{81EE}' - . '\x{81F1}\x{81F2}\x{81F3}\x{81F4}\x{81F5}\x{81F6}\x{81F7}\x{81F8}\x{81F9}' - . '\x{81FA}\x{81FB}\x{81FC}\x{81FD}\x{81FE}\x{81FF}\x{8200}\x{8201}\x{8202}' - . '\x{8203}\x{8204}\x{8205}\x{8206}\x{8207}\x{8208}\x{8209}\x{820A}\x{820B}' - . '\x{820C}\x{820D}\x{820E}\x{820F}\x{8210}\x{8211}\x{8212}\x{8214}\x{8215}' - . '\x{8216}\x{8218}\x{8219}\x{821A}\x{821B}\x{821C}\x{821D}\x{821E}\x{821F}' - . '\x{8220}\x{8221}\x{8222}\x{8223}\x{8225}\x{8226}\x{8227}\x{8228}\x{8229}' - . '\x{822A}\x{822B}\x{822C}\x{822D}\x{822F}\x{8230}\x{8231}\x{8232}\x{8233}' - . '\x{8234}\x{8235}\x{8236}\x{8237}\x{8238}\x{8239}\x{823A}\x{823B}\x{823C}' - . '\x{823D}\x{823E}\x{823F}\x{8240}\x{8242}\x{8243}\x{8244}\x{8245}\x{8246}' - . '\x{8247}\x{8248}\x{8249}\x{824A}\x{824B}\x{824C}\x{824D}\x{824E}\x{824F}' - . '\x{8250}\x{8251}\x{8252}\x{8253}\x{8254}\x{8255}\x{8256}\x{8257}\x{8258}' - . '\x{8259}\x{825A}\x{825B}\x{825C}\x{825D}\x{825E}\x{825F}\x{8260}\x{8261}' - . '\x{8263}\x{8264}\x{8266}\x{8267}\x{8268}\x{8269}\x{826A}\x{826B}\x{826C}' - . '\x{826D}\x{826E}\x{826F}\x{8270}\x{8271}\x{8272}\x{8273}\x{8274}\x{8275}' - . '\x{8276}\x{8277}\x{8278}\x{8279}\x{827A}\x{827B}\x{827C}\x{827D}\x{827E}' - . '\x{827F}\x{8280}\x{8281}\x{8282}\x{8283}\x{8284}\x{8285}\x{8286}\x{8287}' - . '\x{8288}\x{8289}\x{828A}\x{828B}\x{828D}\x{828E}\x{828F}\x{8290}\x{8291}' - . '\x{8292}\x{8293}\x{8294}\x{8295}\x{8296}\x{8297}\x{8298}\x{8299}\x{829A}' - . '\x{829B}\x{829C}\x{829D}\x{829E}\x{829F}\x{82A0}\x{82A1}\x{82A2}\x{82A3}' - . '\x{82A4}\x{82A5}\x{82A6}\x{82A7}\x{82A8}\x{82A9}\x{82AA}\x{82AB}\x{82AC}' - . '\x{82AD}\x{82AE}\x{82AF}\x{82B0}\x{82B1}\x{82B3}\x{82B4}\x{82B5}\x{82B6}' - . '\x{82B7}\x{82B8}\x{82B9}\x{82BA}\x{82BB}\x{82BC}\x{82BD}\x{82BE}\x{82BF}' - . '\x{82C0}\x{82C1}\x{82C2}\x{82C3}\x{82C4}\x{82C5}\x{82C6}\x{82C7}\x{82C8}' - . '\x{82C9}\x{82CA}\x{82CB}\x{82CC}\x{82CD}\x{82CE}\x{82CF}\x{82D0}\x{82D1}' - . '\x{82D2}\x{82D3}\x{82D4}\x{82D5}\x{82D6}\x{82D7}\x{82D8}\x{82D9}\x{82DA}' - . '\x{82DB}\x{82DC}\x{82DD}\x{82DE}\x{82DF}\x{82E0}\x{82E1}\x{82E3}\x{82E4}' - . '\x{82E5}\x{82E6}\x{82E7}\x{82E8}\x{82E9}\x{82EA}\x{82EB}\x{82EC}\x{82ED}' - . '\x{82EE}\x{82EF}\x{82F0}\x{82F1}\x{82F2}\x{82F3}\x{82F4}\x{82F5}\x{82F6}' - . '\x{82F7}\x{82F8}\x{82F9}\x{82FA}\x{82FB}\x{82FD}\x{82FE}\x{82FF}\x{8300}' - . '\x{8301}\x{8302}\x{8303}\x{8304}\x{8305}\x{8306}\x{8307}\x{8308}\x{8309}' - . '\x{830B}\x{830C}\x{830D}\x{830E}\x{830F}\x{8311}\x{8312}\x{8313}\x{8314}' - . '\x{8315}\x{8316}\x{8317}\x{8318}\x{8319}\x{831A}\x{831B}\x{831C}\x{831D}' - . '\x{831E}\x{831F}\x{8320}\x{8321}\x{8322}\x{8323}\x{8324}\x{8325}\x{8326}' - . '\x{8327}\x{8328}\x{8329}\x{832A}\x{832B}\x{832C}\x{832D}\x{832E}\x{832F}' - . '\x{8331}\x{8332}\x{8333}\x{8334}\x{8335}\x{8336}\x{8337}\x{8338}\x{8339}' - . '\x{833A}\x{833B}\x{833C}\x{833D}\x{833E}\x{833F}\x{8340}\x{8341}\x{8342}' - . '\x{8343}\x{8344}\x{8345}\x{8346}\x{8347}\x{8348}\x{8349}\x{834A}\x{834B}' - . '\x{834C}\x{834D}\x{834E}\x{834F}\x{8350}\x{8351}\x{8352}\x{8353}\x{8354}' - . '\x{8356}\x{8357}\x{8358}\x{8359}\x{835A}\x{835B}\x{835C}\x{835D}\x{835E}' - . '\x{835F}\x{8360}\x{8361}\x{8362}\x{8363}\x{8364}\x{8365}\x{8366}\x{8367}' - . '\x{8368}\x{8369}\x{836A}\x{836B}\x{836C}\x{836D}\x{836E}\x{836F}\x{8370}' - . '\x{8371}\x{8372}\x{8373}\x{8374}\x{8375}\x{8376}\x{8377}\x{8378}\x{8379}' - . '\x{837A}\x{837B}\x{837C}\x{837D}\x{837E}\x{837F}\x{8380}\x{8381}\x{8382}' - . '\x{8383}\x{8384}\x{8385}\x{8386}\x{8387}\x{8388}\x{8389}\x{838A}\x{838B}' - . '\x{838C}\x{838D}\x{838E}\x{838F}\x{8390}\x{8391}\x{8392}\x{8393}\x{8394}' - . '\x{8395}\x{8396}\x{8397}\x{8398}\x{8399}\x{839A}\x{839B}\x{839C}\x{839D}' - . '\x{839E}\x{83A0}\x{83A1}\x{83A2}\x{83A3}\x{83A4}\x{83A5}\x{83A6}\x{83A7}' - . '\x{83A8}\x{83A9}\x{83AA}\x{83AB}\x{83AC}\x{83AD}\x{83AE}\x{83AF}\x{83B0}' - . '\x{83B1}\x{83B2}\x{83B3}\x{83B4}\x{83B6}\x{83B7}\x{83B8}\x{83B9}\x{83BA}' - . '\x{83BB}\x{83BC}\x{83BD}\x{83BF}\x{83C0}\x{83C1}\x{83C2}\x{83C3}\x{83C4}' - . '\x{83C5}\x{83C6}\x{83C7}\x{83C8}\x{83C9}\x{83CA}\x{83CB}\x{83CC}\x{83CD}' - . '\x{83CE}\x{83CF}\x{83D0}\x{83D1}\x{83D2}\x{83D3}\x{83D4}\x{83D5}\x{83D6}' - . '\x{83D7}\x{83D8}\x{83D9}\x{83DA}\x{83DB}\x{83DC}\x{83DD}\x{83DE}\x{83DF}' - . '\x{83E0}\x{83E1}\x{83E2}\x{83E3}\x{83E4}\x{83E5}\x{83E7}\x{83E8}\x{83E9}' - . '\x{83EA}\x{83EB}\x{83EC}\x{83EE}\x{83EF}\x{83F0}\x{83F1}\x{83F2}\x{83F3}' - . '\x{83F4}\x{83F5}\x{83F6}\x{83F7}\x{83F8}\x{83F9}\x{83FA}\x{83FB}\x{83FC}' - . '\x{83FD}\x{83FE}\x{83FF}\x{8400}\x{8401}\x{8402}\x{8403}\x{8404}\x{8405}' - . '\x{8406}\x{8407}\x{8408}\x{8409}\x{840A}\x{840B}\x{840C}\x{840D}\x{840E}' - . '\x{840F}\x{8410}\x{8411}\x{8412}\x{8413}\x{8415}\x{8418}\x{8419}\x{841A}' - . '\x{841B}\x{841C}\x{841D}\x{841E}\x{8421}\x{8422}\x{8423}\x{8424}\x{8425}' - . '\x{8426}\x{8427}\x{8428}\x{8429}\x{842A}\x{842B}\x{842C}\x{842D}\x{842E}' - . '\x{842F}\x{8430}\x{8431}\x{8432}\x{8433}\x{8434}\x{8435}\x{8436}\x{8437}' - . '\x{8438}\x{8439}\x{843A}\x{843B}\x{843C}\x{843D}\x{843E}\x{843F}\x{8440}' - . '\x{8441}\x{8442}\x{8443}\x{8444}\x{8445}\x{8446}\x{8447}\x{8448}\x{8449}' - . '\x{844A}\x{844B}\x{844C}\x{844D}\x{844E}\x{844F}\x{8450}\x{8451}\x{8452}' - . '\x{8453}\x{8454}\x{8455}\x{8456}\x{8457}\x{8459}\x{845A}\x{845B}\x{845C}' - . '\x{845D}\x{845E}\x{845F}\x{8460}\x{8461}\x{8462}\x{8463}\x{8464}\x{8465}' - . '\x{8466}\x{8467}\x{8468}\x{8469}\x{846A}\x{846B}\x{846C}\x{846D}\x{846E}' - . '\x{846F}\x{8470}\x{8471}\x{8472}\x{8473}\x{8474}\x{8475}\x{8476}\x{8477}' - . '\x{8478}\x{8479}\x{847A}\x{847B}\x{847C}\x{847D}\x{847E}\x{847F}\x{8480}' - . '\x{8481}\x{8482}\x{8484}\x{8485}\x{8486}\x{8487}\x{8488}\x{8489}\x{848A}' - . '\x{848B}\x{848C}\x{848D}\x{848E}\x{848F}\x{8490}\x{8491}\x{8492}\x{8493}' - . '\x{8494}\x{8496}\x{8497}\x{8498}\x{8499}\x{849A}\x{849B}\x{849C}\x{849D}' - . '\x{849E}\x{849F}\x{84A0}\x{84A1}\x{84A2}\x{84A3}\x{84A4}\x{84A5}\x{84A6}' - . '\x{84A7}\x{84A8}\x{84A9}\x{84AA}\x{84AB}\x{84AC}\x{84AE}\x{84AF}\x{84B0}' - . '\x{84B1}\x{84B2}\x{84B3}\x{84B4}\x{84B5}\x{84B6}\x{84B8}\x{84B9}\x{84BA}' - . '\x{84BB}\x{84BC}\x{84BD}\x{84BE}\x{84BF}\x{84C0}\x{84C1}\x{84C2}\x{84C4}' - . '\x{84C5}\x{84C6}\x{84C7}\x{84C8}\x{84C9}\x{84CA}\x{84CB}\x{84CC}\x{84CD}' - . '\x{84CE}\x{84CF}\x{84D0}\x{84D1}\x{84D2}\x{84D3}\x{84D4}\x{84D5}\x{84D6}' - . '\x{84D7}\x{84D8}\x{84D9}\x{84DB}\x{84DC}\x{84DD}\x{84DE}\x{84DF}\x{84E0}' - . '\x{84E1}\x{84E2}\x{84E3}\x{84E4}\x{84E5}\x{84E6}\x{84E7}\x{84E8}\x{84E9}' - . '\x{84EA}\x{84EB}\x{84EC}\x{84EE}\x{84EF}\x{84F0}\x{84F1}\x{84F2}\x{84F3}' - . '\x{84F4}\x{84F5}\x{84F6}\x{84F7}\x{84F8}\x{84F9}\x{84FA}\x{84FB}\x{84FC}' - . '\x{84FD}\x{84FE}\x{84FF}\x{8500}\x{8501}\x{8502}\x{8503}\x{8504}\x{8506}' - . '\x{8507}\x{8508}\x{8509}\x{850A}\x{850B}\x{850C}\x{850D}\x{850E}\x{850F}' - . '\x{8511}\x{8512}\x{8513}\x{8514}\x{8515}\x{8516}\x{8517}\x{8518}\x{8519}' - . '\x{851A}\x{851B}\x{851C}\x{851D}\x{851E}\x{851F}\x{8520}\x{8521}\x{8522}' - . '\x{8523}\x{8524}\x{8525}\x{8526}\x{8527}\x{8528}\x{8529}\x{852A}\x{852B}' - . '\x{852C}\x{852D}\x{852E}\x{852F}\x{8530}\x{8531}\x{8534}\x{8535}\x{8536}' - . '\x{8537}\x{8538}\x{8539}\x{853A}\x{853B}\x{853C}\x{853D}\x{853E}\x{853F}' - . '\x{8540}\x{8541}\x{8542}\x{8543}\x{8544}\x{8545}\x{8546}\x{8547}\x{8548}' - . '\x{8549}\x{854A}\x{854B}\x{854D}\x{854E}\x{854F}\x{8551}\x{8552}\x{8553}' - . '\x{8554}\x{8555}\x{8556}\x{8557}\x{8558}\x{8559}\x{855A}\x{855B}\x{855C}' - . '\x{855D}\x{855E}\x{855F}\x{8560}\x{8561}\x{8562}\x{8563}\x{8564}\x{8565}' - . '\x{8566}\x{8567}\x{8568}\x{8569}\x{856A}\x{856B}\x{856C}\x{856D}\x{856E}' - . '\x{856F}\x{8570}\x{8571}\x{8572}\x{8573}\x{8574}\x{8575}\x{8576}\x{8577}' - . '\x{8578}\x{8579}\x{857A}\x{857B}\x{857C}\x{857D}\x{857E}\x{8580}\x{8581}' - . '\x{8582}\x{8583}\x{8584}\x{8585}\x{8586}\x{8587}\x{8588}\x{8589}\x{858A}' - . '\x{858B}\x{858C}\x{858D}\x{858E}\x{858F}\x{8590}\x{8591}\x{8592}\x{8594}' - . '\x{8595}\x{8596}\x{8598}\x{8599}\x{859A}\x{859B}\x{859C}\x{859D}\x{859E}' - . '\x{859F}\x{85A0}\x{85A1}\x{85A2}\x{85A3}\x{85A4}\x{85A5}\x{85A6}\x{85A7}' - . '\x{85A8}\x{85A9}\x{85AA}\x{85AB}\x{85AC}\x{85AD}\x{85AE}\x{85AF}\x{85B0}' - . '\x{85B1}\x{85B3}\x{85B4}\x{85B5}\x{85B6}\x{85B7}\x{85B8}\x{85B9}\x{85BA}' - . '\x{85BC}\x{85BD}\x{85BE}\x{85BF}\x{85C0}\x{85C1}\x{85C2}\x{85C3}\x{85C4}' - . '\x{85C5}\x{85C6}\x{85C7}\x{85C8}\x{85C9}\x{85CA}\x{85CB}\x{85CD}\x{85CE}' - . '\x{85CF}\x{85D0}\x{85D1}\x{85D2}\x{85D3}\x{85D4}\x{85D5}\x{85D6}\x{85D7}' - . '\x{85D8}\x{85D9}\x{85DA}\x{85DB}\x{85DC}\x{85DD}\x{85DE}\x{85DF}\x{85E0}' - . '\x{85E1}\x{85E2}\x{85E3}\x{85E4}\x{85E5}\x{85E6}\x{85E7}\x{85E8}\x{85E9}' - . '\x{85EA}\x{85EB}\x{85EC}\x{85ED}\x{85EF}\x{85F0}\x{85F1}\x{85F2}\x{85F4}' - . '\x{85F5}\x{85F6}\x{85F7}\x{85F8}\x{85F9}\x{85FA}\x{85FB}\x{85FD}\x{85FE}' - . '\x{85FF}\x{8600}\x{8601}\x{8602}\x{8604}\x{8605}\x{8606}\x{8607}\x{8608}' - . '\x{8609}\x{860A}\x{860B}\x{860C}\x{860F}\x{8611}\x{8612}\x{8613}\x{8614}' - . '\x{8616}\x{8617}\x{8618}\x{8619}\x{861A}\x{861B}\x{861C}\x{861E}\x{861F}' - . '\x{8620}\x{8621}\x{8622}\x{8623}\x{8624}\x{8625}\x{8626}\x{8627}\x{8628}' - . '\x{8629}\x{862A}\x{862B}\x{862C}\x{862D}\x{862E}\x{862F}\x{8630}\x{8631}' - . '\x{8632}\x{8633}\x{8634}\x{8635}\x{8636}\x{8638}\x{8639}\x{863A}\x{863B}' - . '\x{863C}\x{863D}\x{863E}\x{863F}\x{8640}\x{8641}\x{8642}\x{8643}\x{8644}' - . '\x{8645}\x{8646}\x{8647}\x{8648}\x{8649}\x{864A}\x{864B}\x{864C}\x{864D}' - . '\x{864E}\x{864F}\x{8650}\x{8651}\x{8652}\x{8653}\x{8654}\x{8655}\x{8656}' - . '\x{8658}\x{8659}\x{865A}\x{865B}\x{865C}\x{865D}\x{865E}\x{865F}\x{8660}' - . '\x{8661}\x{8662}\x{8663}\x{8664}\x{8665}\x{8666}\x{8667}\x{8668}\x{8669}' - . '\x{866A}\x{866B}\x{866C}\x{866D}\x{866E}\x{866F}\x{8670}\x{8671}\x{8672}' - . '\x{8673}\x{8674}\x{8676}\x{8677}\x{8678}\x{8679}\x{867A}\x{867B}\x{867C}' - . '\x{867D}\x{867E}\x{867F}\x{8680}\x{8681}\x{8682}\x{8683}\x{8684}\x{8685}' - . '\x{8686}\x{8687}\x{8688}\x{868A}\x{868B}\x{868C}\x{868D}\x{868E}\x{868F}' - . '\x{8690}\x{8691}\x{8693}\x{8694}\x{8695}\x{8696}\x{8697}\x{8698}\x{8699}' - . '\x{869A}\x{869B}\x{869C}\x{869D}\x{869E}\x{869F}\x{86A1}\x{86A2}\x{86A3}' - . '\x{86A4}\x{86A5}\x{86A7}\x{86A8}\x{86A9}\x{86AA}\x{86AB}\x{86AC}\x{86AD}' - . '\x{86AE}\x{86AF}\x{86B0}\x{86B1}\x{86B2}\x{86B3}\x{86B4}\x{86B5}\x{86B6}' - . '\x{86B7}\x{86B8}\x{86B9}\x{86BA}\x{86BB}\x{86BC}\x{86BD}\x{86BE}\x{86BF}' - . '\x{86C0}\x{86C1}\x{86C2}\x{86C3}\x{86C4}\x{86C5}\x{86C6}\x{86C7}\x{86C8}' - . '\x{86C9}\x{86CA}\x{86CB}\x{86CC}\x{86CE}\x{86CF}\x{86D0}\x{86D1}\x{86D2}' - . '\x{86D3}\x{86D4}\x{86D6}\x{86D7}\x{86D8}\x{86D9}\x{86DA}\x{86DB}\x{86DC}' - . '\x{86DD}\x{86DE}\x{86DF}\x{86E1}\x{86E2}\x{86E3}\x{86E4}\x{86E5}\x{86E6}' - . '\x{86E8}\x{86E9}\x{86EA}\x{86EB}\x{86EC}\x{86ED}\x{86EE}\x{86EF}\x{86F0}' - . '\x{86F1}\x{86F2}\x{86F3}\x{86F4}\x{86F5}\x{86F6}\x{86F7}\x{86F8}\x{86F9}' - . '\x{86FA}\x{86FB}\x{86FC}\x{86FE}\x{86FF}\x{8700}\x{8701}\x{8702}\x{8703}' - . '\x{8704}\x{8705}\x{8706}\x{8707}\x{8708}\x{8709}\x{870A}\x{870B}\x{870C}' - . '\x{870D}\x{870E}\x{870F}\x{8710}\x{8711}\x{8712}\x{8713}\x{8714}\x{8715}' - . '\x{8716}\x{8717}\x{8718}\x{8719}\x{871A}\x{871B}\x{871C}\x{871E}\x{871F}' - . '\x{8720}\x{8721}\x{8722}\x{8723}\x{8724}\x{8725}\x{8726}\x{8727}\x{8728}' - . '\x{8729}\x{872A}\x{872B}\x{872C}\x{872D}\x{872E}\x{8730}\x{8731}\x{8732}' - . '\x{8733}\x{8734}\x{8735}\x{8736}\x{8737}\x{8738}\x{8739}\x{873A}\x{873B}' - . '\x{873C}\x{873E}\x{873F}\x{8740}\x{8741}\x{8742}\x{8743}\x{8744}\x{8746}' - . '\x{8747}\x{8748}\x{8749}\x{874A}\x{874C}\x{874D}\x{874E}\x{874F}\x{8750}' - . '\x{8751}\x{8752}\x{8753}\x{8754}\x{8755}\x{8756}\x{8757}\x{8758}\x{8759}' - . '\x{875A}\x{875B}\x{875C}\x{875D}\x{875E}\x{875F}\x{8760}\x{8761}\x{8762}' - . '\x{8763}\x{8764}\x{8765}\x{8766}\x{8767}\x{8768}\x{8769}\x{876A}\x{876B}' - . '\x{876C}\x{876D}\x{876E}\x{876F}\x{8770}\x{8772}\x{8773}\x{8774}\x{8775}' - . '\x{8776}\x{8777}\x{8778}\x{8779}\x{877A}\x{877B}\x{877C}\x{877D}\x{877E}' - . '\x{8780}\x{8781}\x{8782}\x{8783}\x{8784}\x{8785}\x{8786}\x{8787}\x{8788}' - . '\x{8789}\x{878A}\x{878B}\x{878C}\x{878D}\x{878F}\x{8790}\x{8791}\x{8792}' - . '\x{8793}\x{8794}\x{8795}\x{8796}\x{8797}\x{8798}\x{879A}\x{879B}\x{879C}' - . '\x{879D}\x{879E}\x{879F}\x{87A0}\x{87A1}\x{87A2}\x{87A3}\x{87A4}\x{87A5}' - . '\x{87A6}\x{87A7}\x{87A8}\x{87A9}\x{87AA}\x{87AB}\x{87AC}\x{87AD}\x{87AE}' - . '\x{87AF}\x{87B0}\x{87B1}\x{87B2}\x{87B3}\x{87B4}\x{87B5}\x{87B6}\x{87B7}' - . '\x{87B8}\x{87B9}\x{87BA}\x{87BB}\x{87BC}\x{87BD}\x{87BE}\x{87BF}\x{87C0}' - . '\x{87C1}\x{87C2}\x{87C3}\x{87C4}\x{87C5}\x{87C6}\x{87C7}\x{87C8}\x{87C9}' - . '\x{87CA}\x{87CB}\x{87CC}\x{87CD}\x{87CE}\x{87CF}\x{87D0}\x{87D1}\x{87D2}' - . '\x{87D3}\x{87D4}\x{87D5}\x{87D6}\x{87D7}\x{87D8}\x{87D9}\x{87DB}\x{87DC}' - . '\x{87DD}\x{87DE}\x{87DF}\x{87E0}\x{87E1}\x{87E2}\x{87E3}\x{87E4}\x{87E5}' - . '\x{87E6}\x{87E7}\x{87E8}\x{87E9}\x{87EA}\x{87EB}\x{87EC}\x{87ED}\x{87EE}' - . '\x{87EF}\x{87F1}\x{87F2}\x{87F3}\x{87F4}\x{87F5}\x{87F6}\x{87F7}\x{87F8}' - . '\x{87F9}\x{87FA}\x{87FB}\x{87FC}\x{87FD}\x{87FE}\x{87FF}\x{8800}\x{8801}' - . '\x{8802}\x{8803}\x{8804}\x{8805}\x{8806}\x{8808}\x{8809}\x{880A}\x{880B}' - . '\x{880C}\x{880D}\x{880E}\x{880F}\x{8810}\x{8811}\x{8813}\x{8814}\x{8815}' - . '\x{8816}\x{8817}\x{8818}\x{8819}\x{881A}\x{881B}\x{881C}\x{881D}\x{881E}' - . '\x{881F}\x{8820}\x{8821}\x{8822}\x{8823}\x{8824}\x{8825}\x{8826}\x{8827}' - . '\x{8828}\x{8829}\x{882A}\x{882B}\x{882C}\x{882E}\x{882F}\x{8830}\x{8831}' - . '\x{8832}\x{8833}\x{8834}\x{8835}\x{8836}\x{8837}\x{8838}\x{8839}\x{883B}' - . '\x{883C}\x{883D}\x{883E}\x{883F}\x{8840}\x{8841}\x{8842}\x{8843}\x{8844}' - . '\x{8845}\x{8846}\x{8848}\x{8849}\x{884A}\x{884B}\x{884C}\x{884D}\x{884E}' - . '\x{884F}\x{8850}\x{8851}\x{8852}\x{8853}\x{8854}\x{8855}\x{8856}\x{8857}' - . '\x{8859}\x{885A}\x{885B}\x{885D}\x{885E}\x{8860}\x{8861}\x{8862}\x{8863}' - . '\x{8864}\x{8865}\x{8866}\x{8867}\x{8868}\x{8869}\x{886A}\x{886B}\x{886C}' - . '\x{886D}\x{886E}\x{886F}\x{8870}\x{8871}\x{8872}\x{8873}\x{8874}\x{8875}' - . '\x{8876}\x{8877}\x{8878}\x{8879}\x{887B}\x{887C}\x{887D}\x{887E}\x{887F}' - . '\x{8880}\x{8881}\x{8882}\x{8883}\x{8884}\x{8885}\x{8886}\x{8887}\x{8888}' - . '\x{8889}\x{888A}\x{888B}\x{888C}\x{888D}\x{888E}\x{888F}\x{8890}\x{8891}' - . '\x{8892}\x{8893}\x{8894}\x{8895}\x{8896}\x{8897}\x{8898}\x{8899}\x{889A}' - . '\x{889B}\x{889C}\x{889D}\x{889E}\x{889F}\x{88A0}\x{88A1}\x{88A2}\x{88A3}' - . '\x{88A4}\x{88A5}\x{88A6}\x{88A7}\x{88A8}\x{88A9}\x{88AA}\x{88AB}\x{88AC}' - . '\x{88AD}\x{88AE}\x{88AF}\x{88B0}\x{88B1}\x{88B2}\x{88B3}\x{88B4}\x{88B6}' - . '\x{88B7}\x{88B8}\x{88B9}\x{88BA}\x{88BB}\x{88BC}\x{88BD}\x{88BE}\x{88BF}' - . '\x{88C0}\x{88C1}\x{88C2}\x{88C3}\x{88C4}\x{88C5}\x{88C6}\x{88C7}\x{88C8}' - . '\x{88C9}\x{88CA}\x{88CB}\x{88CC}\x{88CD}\x{88CE}\x{88CF}\x{88D0}\x{88D1}' - . '\x{88D2}\x{88D3}\x{88D4}\x{88D5}\x{88D6}\x{88D7}\x{88D8}\x{88D9}\x{88DA}' - . '\x{88DB}\x{88DC}\x{88DD}\x{88DE}\x{88DF}\x{88E0}\x{88E1}\x{88E2}\x{88E3}' - . '\x{88E4}\x{88E5}\x{88E7}\x{88E8}\x{88EA}\x{88EB}\x{88EC}\x{88EE}\x{88EF}' - . '\x{88F0}\x{88F1}\x{88F2}\x{88F3}\x{88F4}\x{88F5}\x{88F6}\x{88F7}\x{88F8}' - . '\x{88F9}\x{88FA}\x{88FB}\x{88FC}\x{88FD}\x{88FE}\x{88FF}\x{8900}\x{8901}' - . '\x{8902}\x{8904}\x{8905}\x{8906}\x{8907}\x{8908}\x{8909}\x{890A}\x{890B}' - . '\x{890C}\x{890D}\x{890E}\x{8910}\x{8911}\x{8912}\x{8913}\x{8914}\x{8915}' - . '\x{8916}\x{8917}\x{8918}\x{8919}\x{891A}\x{891B}\x{891C}\x{891D}\x{891E}' - . '\x{891F}\x{8920}\x{8921}\x{8922}\x{8923}\x{8925}\x{8926}\x{8927}\x{8928}' - . '\x{8929}\x{892A}\x{892B}\x{892C}\x{892D}\x{892E}\x{892F}\x{8930}\x{8931}' - . '\x{8932}\x{8933}\x{8934}\x{8935}\x{8936}\x{8937}\x{8938}\x{8939}\x{893A}' - . '\x{893B}\x{893C}\x{893D}\x{893E}\x{893F}\x{8940}\x{8941}\x{8942}\x{8943}' - . '\x{8944}\x{8945}\x{8946}\x{8947}\x{8948}\x{8949}\x{894A}\x{894B}\x{894C}' - . '\x{894E}\x{894F}\x{8950}\x{8951}\x{8952}\x{8953}\x{8954}\x{8955}\x{8956}' - . '\x{8957}\x{8958}\x{8959}\x{895A}\x{895B}\x{895C}\x{895D}\x{895E}\x{895F}' - . '\x{8960}\x{8961}\x{8962}\x{8963}\x{8964}\x{8966}\x{8967}\x{8968}\x{8969}' - . '\x{896A}\x{896B}\x{896C}\x{896D}\x{896E}\x{896F}\x{8970}\x{8971}\x{8972}' - . '\x{8973}\x{8974}\x{8976}\x{8977}\x{8978}\x{8979}\x{897A}\x{897B}\x{897C}' - . '\x{897E}\x{897F}\x{8980}\x{8981}\x{8982}\x{8983}\x{8984}\x{8985}\x{8986}' - . '\x{8987}\x{8988}\x{8989}\x{898A}\x{898B}\x{898C}\x{898E}\x{898F}\x{8991}' - . '\x{8992}\x{8993}\x{8995}\x{8996}\x{8997}\x{8998}\x{899A}\x{899B}\x{899C}' - . '\x{899D}\x{899E}\x{899F}\x{89A0}\x{89A1}\x{89A2}\x{89A3}\x{89A4}\x{89A5}' - . '\x{89A6}\x{89A7}\x{89A8}\x{89AA}\x{89AB}\x{89AC}\x{89AD}\x{89AE}\x{89AF}' - . '\x{89B1}\x{89B2}\x{89B3}\x{89B5}\x{89B6}\x{89B7}\x{89B8}\x{89B9}\x{89BA}' - . '\x{89BD}\x{89BE}\x{89BF}\x{89C0}\x{89C1}\x{89C2}\x{89C3}\x{89C4}\x{89C5}' - . '\x{89C6}\x{89C7}\x{89C8}\x{89C9}\x{89CA}\x{89CB}\x{89CC}\x{89CD}\x{89CE}' - . '\x{89CF}\x{89D0}\x{89D1}\x{89D2}\x{89D3}\x{89D4}\x{89D5}\x{89D6}\x{89D7}' - . '\x{89D8}\x{89D9}\x{89DA}\x{89DB}\x{89DC}\x{89DD}\x{89DE}\x{89DF}\x{89E0}' - . '\x{89E1}\x{89E2}\x{89E3}\x{89E4}\x{89E5}\x{89E6}\x{89E7}\x{89E8}\x{89E9}' - . '\x{89EA}\x{89EB}\x{89EC}\x{89ED}\x{89EF}\x{89F0}\x{89F1}\x{89F2}\x{89F3}' - . '\x{89F4}\x{89F6}\x{89F7}\x{89F8}\x{89FA}\x{89FB}\x{89FC}\x{89FE}\x{89FF}' - . '\x{8A00}\x{8A01}\x{8A02}\x{8A03}\x{8A04}\x{8A07}\x{8A08}\x{8A09}\x{8A0A}' - . '\x{8A0B}\x{8A0C}\x{8A0D}\x{8A0E}\x{8A0F}\x{8A10}\x{8A11}\x{8A12}\x{8A13}' - . '\x{8A15}\x{8A16}\x{8A17}\x{8A18}\x{8A1A}\x{8A1B}\x{8A1C}\x{8A1D}\x{8A1E}' - . '\x{8A1F}\x{8A22}\x{8A23}\x{8A24}\x{8A25}\x{8A26}\x{8A27}\x{8A28}\x{8A29}' - . '\x{8A2A}\x{8A2C}\x{8A2D}\x{8A2E}\x{8A2F}\x{8A30}\x{8A31}\x{8A32}\x{8A34}' - . '\x{8A35}\x{8A36}\x{8A37}\x{8A38}\x{8A39}\x{8A3A}\x{8A3B}\x{8A3C}\x{8A3E}' - . '\x{8A3F}\x{8A40}\x{8A41}\x{8A42}\x{8A43}\x{8A44}\x{8A45}\x{8A46}\x{8A47}' - . '\x{8A48}\x{8A49}\x{8A4A}\x{8A4C}\x{8A4D}\x{8A4E}\x{8A4F}\x{8A50}\x{8A51}' - . '\x{8A52}\x{8A53}\x{8A54}\x{8A55}\x{8A56}\x{8A57}\x{8A58}\x{8A59}\x{8A5A}' - . '\x{8A5B}\x{8A5C}\x{8A5D}\x{8A5E}\x{8A5F}\x{8A60}\x{8A61}\x{8A62}\x{8A63}' - . '\x{8A65}\x{8A66}\x{8A67}\x{8A68}\x{8A69}\x{8A6A}\x{8A6B}\x{8A6C}\x{8A6D}' - . '\x{8A6E}\x{8A6F}\x{8A70}\x{8A71}\x{8A72}\x{8A73}\x{8A74}\x{8A75}\x{8A76}' - . '\x{8A77}\x{8A79}\x{8A7A}\x{8A7B}\x{8A7C}\x{8A7E}\x{8A7F}\x{8A80}\x{8A81}' - . '\x{8A82}\x{8A83}\x{8A84}\x{8A85}\x{8A86}\x{8A87}\x{8A89}\x{8A8A}\x{8A8B}' - . '\x{8A8C}\x{8A8D}\x{8A8E}\x{8A8F}\x{8A90}\x{8A91}\x{8A92}\x{8A93}\x{8A94}' - . '\x{8A95}\x{8A96}\x{8A97}\x{8A98}\x{8A99}\x{8A9A}\x{8A9B}\x{8A9C}\x{8A9D}' - . '\x{8A9E}\x{8AA0}\x{8AA1}\x{8AA2}\x{8AA3}\x{8AA4}\x{8AA5}\x{8AA6}\x{8AA7}' - . '\x{8AA8}\x{8AA9}\x{8AAA}\x{8AAB}\x{8AAC}\x{8AAE}\x{8AB0}\x{8AB1}\x{8AB2}' - . '\x{8AB3}\x{8AB4}\x{8AB5}\x{8AB6}\x{8AB8}\x{8AB9}\x{8ABA}\x{8ABB}\x{8ABC}' - . '\x{8ABD}\x{8ABE}\x{8ABF}\x{8AC0}\x{8AC1}\x{8AC2}\x{8AC3}\x{8AC4}\x{8AC5}' - . '\x{8AC6}\x{8AC7}\x{8AC8}\x{8AC9}\x{8ACA}\x{8ACB}\x{8ACC}\x{8ACD}\x{8ACE}' - . '\x{8ACF}\x{8AD1}\x{8AD2}\x{8AD3}\x{8AD4}\x{8AD5}\x{8AD6}\x{8AD7}\x{8AD8}' - . '\x{8AD9}\x{8ADA}\x{8ADB}\x{8ADC}\x{8ADD}\x{8ADE}\x{8ADF}\x{8AE0}\x{8AE1}' - . '\x{8AE2}\x{8AE3}\x{8AE4}\x{8AE5}\x{8AE6}\x{8AE7}\x{8AE8}\x{8AE9}\x{8AEA}' - . '\x{8AEB}\x{8AED}\x{8AEE}\x{8AEF}\x{8AF0}\x{8AF1}\x{8AF2}\x{8AF3}\x{8AF4}' - . '\x{8AF5}\x{8AF6}\x{8AF7}\x{8AF8}\x{8AF9}\x{8AFA}\x{8AFB}\x{8AFC}\x{8AFD}' - . '\x{8AFE}\x{8AFF}\x{8B00}\x{8B01}\x{8B02}\x{8B03}\x{8B04}\x{8B05}\x{8B06}' - . '\x{8B07}\x{8B08}\x{8B09}\x{8B0A}\x{8B0B}\x{8B0D}\x{8B0E}\x{8B0F}\x{8B10}' - . '\x{8B11}\x{8B12}\x{8B13}\x{8B14}\x{8B15}\x{8B16}\x{8B17}\x{8B18}\x{8B19}' - . '\x{8B1A}\x{8B1B}\x{8B1C}\x{8B1D}\x{8B1E}\x{8B1F}\x{8B20}\x{8B21}\x{8B22}' - . '\x{8B23}\x{8B24}\x{8B25}\x{8B26}\x{8B27}\x{8B28}\x{8B2A}\x{8B2B}\x{8B2C}' - . '\x{8B2D}\x{8B2E}\x{8B2F}\x{8B30}\x{8B31}\x{8B33}\x{8B34}\x{8B35}\x{8B36}' - . '\x{8B37}\x{8B39}\x{8B3A}\x{8B3B}\x{8B3C}\x{8B3D}\x{8B3E}\x{8B40}\x{8B41}' - . '\x{8B42}\x{8B43}\x{8B44}\x{8B45}\x{8B46}\x{8B47}\x{8B48}\x{8B49}\x{8B4A}' - . '\x{8B4B}\x{8B4C}\x{8B4D}\x{8B4E}\x{8B4F}\x{8B50}\x{8B51}\x{8B52}\x{8B53}' - . '\x{8B54}\x{8B55}\x{8B56}\x{8B57}\x{8B58}\x{8B59}\x{8B5A}\x{8B5B}\x{8B5C}' - . '\x{8B5D}\x{8B5E}\x{8B5F}\x{8B60}\x{8B63}\x{8B64}\x{8B65}\x{8B66}\x{8B67}' - . '\x{8B68}\x{8B6A}\x{8B6B}\x{8B6C}\x{8B6D}\x{8B6E}\x{8B6F}\x{8B70}\x{8B71}' - . '\x{8B73}\x{8B74}\x{8B76}\x{8B77}\x{8B78}\x{8B79}\x{8B7A}\x{8B7B}\x{8B7D}' - . '\x{8B7E}\x{8B7F}\x{8B80}\x{8B82}\x{8B83}\x{8B84}\x{8B85}\x{8B86}\x{8B88}' - . '\x{8B89}\x{8B8A}\x{8B8B}\x{8B8C}\x{8B8E}\x{8B90}\x{8B91}\x{8B92}\x{8B93}' - . '\x{8B94}\x{8B95}\x{8B96}\x{8B97}\x{8B98}\x{8B99}\x{8B9A}\x{8B9C}\x{8B9D}' - . '\x{8B9E}\x{8B9F}\x{8BA0}\x{8BA1}\x{8BA2}\x{8BA3}\x{8BA4}\x{8BA5}\x{8BA6}' - . '\x{8BA7}\x{8BA8}\x{8BA9}\x{8BAA}\x{8BAB}\x{8BAC}\x{8BAD}\x{8BAE}\x{8BAF}' - . '\x{8BB0}\x{8BB1}\x{8BB2}\x{8BB3}\x{8BB4}\x{8BB5}\x{8BB6}\x{8BB7}\x{8BB8}' - . '\x{8BB9}\x{8BBA}\x{8BBB}\x{8BBC}\x{8BBD}\x{8BBE}\x{8BBF}\x{8BC0}\x{8BC1}' - . '\x{8BC2}\x{8BC3}\x{8BC4}\x{8BC5}\x{8BC6}\x{8BC7}\x{8BC8}\x{8BC9}\x{8BCA}' - . '\x{8BCB}\x{8BCC}\x{8BCD}\x{8BCE}\x{8BCF}\x{8BD0}\x{8BD1}\x{8BD2}\x{8BD3}' - . '\x{8BD4}\x{8BD5}\x{8BD6}\x{8BD7}\x{8BD8}\x{8BD9}\x{8BDA}\x{8BDB}\x{8BDC}' - . '\x{8BDD}\x{8BDE}\x{8BDF}\x{8BE0}\x{8BE1}\x{8BE2}\x{8BE3}\x{8BE4}\x{8BE5}' - . '\x{8BE6}\x{8BE7}\x{8BE8}\x{8BE9}\x{8BEA}\x{8BEB}\x{8BEC}\x{8BED}\x{8BEE}' - . '\x{8BEF}\x{8BF0}\x{8BF1}\x{8BF2}\x{8BF3}\x{8BF4}\x{8BF5}\x{8BF6}\x{8BF7}' - . '\x{8BF8}\x{8BF9}\x{8BFA}\x{8BFB}\x{8BFC}\x{8BFD}\x{8BFE}\x{8BFF}\x{8C00}' - . '\x{8C01}\x{8C02}\x{8C03}\x{8C04}\x{8C05}\x{8C06}\x{8C07}\x{8C08}\x{8C09}' - . '\x{8C0A}\x{8C0B}\x{8C0C}\x{8C0D}\x{8C0E}\x{8C0F}\x{8C10}\x{8C11}\x{8C12}' - . '\x{8C13}\x{8C14}\x{8C15}\x{8C16}\x{8C17}\x{8C18}\x{8C19}\x{8C1A}\x{8C1B}' - . '\x{8C1C}\x{8C1D}\x{8C1E}\x{8C1F}\x{8C20}\x{8C21}\x{8C22}\x{8C23}\x{8C24}' - . '\x{8C25}\x{8C26}\x{8C27}\x{8C28}\x{8C29}\x{8C2A}\x{8C2B}\x{8C2C}\x{8C2D}' - . '\x{8C2E}\x{8C2F}\x{8C30}\x{8C31}\x{8C32}\x{8C33}\x{8C34}\x{8C35}\x{8C36}' - . '\x{8C37}\x{8C39}\x{8C3A}\x{8C3B}\x{8C3C}\x{8C3D}\x{8C3E}\x{8C3F}\x{8C41}' - . '\x{8C42}\x{8C43}\x{8C45}\x{8C46}\x{8C47}\x{8C48}\x{8C49}\x{8C4A}\x{8C4B}' - . '\x{8C4C}\x{8C4D}\x{8C4E}\x{8C4F}\x{8C50}\x{8C54}\x{8C55}\x{8C56}\x{8C57}' - . '\x{8C59}\x{8C5A}\x{8C5B}\x{8C5C}\x{8C5D}\x{8C5E}\x{8C5F}\x{8C60}\x{8C61}' - . '\x{8C62}\x{8C63}\x{8C64}\x{8C65}\x{8C66}\x{8C67}\x{8C68}\x{8C69}\x{8C6A}' - . '\x{8C6B}\x{8C6C}\x{8C6D}\x{8C6E}\x{8C6F}\x{8C70}\x{8C71}\x{8C72}\x{8C73}' - . '\x{8C75}\x{8C76}\x{8C77}\x{8C78}\x{8C79}\x{8C7A}\x{8C7B}\x{8C7D}\x{8C7E}' - . '\x{8C80}\x{8C81}\x{8C82}\x{8C84}\x{8C85}\x{8C86}\x{8C88}\x{8C89}\x{8C8A}' - . '\x{8C8C}\x{8C8D}\x{8C8F}\x{8C90}\x{8C91}\x{8C92}\x{8C93}\x{8C94}\x{8C95}' - . '\x{8C96}\x{8C97}\x{8C98}\x{8C99}\x{8C9A}\x{8C9C}\x{8C9D}\x{8C9E}\x{8C9F}' - . '\x{8CA0}\x{8CA1}\x{8CA2}\x{8CA3}\x{8CA4}\x{8CA5}\x{8CA7}\x{8CA8}\x{8CA9}' - . '\x{8CAA}\x{8CAB}\x{8CAC}\x{8CAD}\x{8CAE}\x{8CAF}\x{8CB0}\x{8CB1}\x{8CB2}' - . '\x{8CB3}\x{8CB4}\x{8CB5}\x{8CB6}\x{8CB7}\x{8CB8}\x{8CB9}\x{8CBA}\x{8CBB}' - . '\x{8CBC}\x{8CBD}\x{8CBE}\x{8CBF}\x{8CC0}\x{8CC1}\x{8CC2}\x{8CC3}\x{8CC4}' - . '\x{8CC5}\x{8CC6}\x{8CC7}\x{8CC8}\x{8CC9}\x{8CCA}\x{8CCC}\x{8CCE}\x{8CCF}' - . '\x{8CD0}\x{8CD1}\x{8CD2}\x{8CD3}\x{8CD4}\x{8CD5}\x{8CD7}\x{8CD9}\x{8CDA}' - . '\x{8CDB}\x{8CDC}\x{8CDD}\x{8CDE}\x{8CDF}\x{8CE0}\x{8CE1}\x{8CE2}\x{8CE3}' - . '\x{8CE4}\x{8CE5}\x{8CE6}\x{8CE7}\x{8CE8}\x{8CEA}\x{8CEB}\x{8CEC}\x{8CED}' - . '\x{8CEE}\x{8CEF}\x{8CF0}\x{8CF1}\x{8CF2}\x{8CF3}\x{8CF4}\x{8CF5}\x{8CF6}' - . '\x{8CF8}\x{8CF9}\x{8CFA}\x{8CFB}\x{8CFC}\x{8CFD}\x{8CFE}\x{8CFF}\x{8D00}' - . '\x{8D02}\x{8D03}\x{8D04}\x{8D05}\x{8D06}\x{8D07}\x{8D08}\x{8D09}\x{8D0A}' - . '\x{8D0B}\x{8D0C}\x{8D0D}\x{8D0E}\x{8D0F}\x{8D10}\x{8D13}\x{8D14}\x{8D15}' - . '\x{8D16}\x{8D17}\x{8D18}\x{8D19}\x{8D1A}\x{8D1B}\x{8D1C}\x{8D1D}\x{8D1E}' - . '\x{8D1F}\x{8D20}\x{8D21}\x{8D22}\x{8D23}\x{8D24}\x{8D25}\x{8D26}\x{8D27}' - . '\x{8D28}\x{8D29}\x{8D2A}\x{8D2B}\x{8D2C}\x{8D2D}\x{8D2E}\x{8D2F}\x{8D30}' - . '\x{8D31}\x{8D32}\x{8D33}\x{8D34}\x{8D35}\x{8D36}\x{8D37}\x{8D38}\x{8D39}' - . '\x{8D3A}\x{8D3B}\x{8D3C}\x{8D3D}\x{8D3E}\x{8D3F}\x{8D40}\x{8D41}\x{8D42}' - . '\x{8D43}\x{8D44}\x{8D45}\x{8D46}\x{8D47}\x{8D48}\x{8D49}\x{8D4A}\x{8D4B}' - . '\x{8D4C}\x{8D4D}\x{8D4E}\x{8D4F}\x{8D50}\x{8D51}\x{8D52}\x{8D53}\x{8D54}' - . '\x{8D55}\x{8D56}\x{8D57}\x{8D58}\x{8D59}\x{8D5A}\x{8D5B}\x{8D5C}\x{8D5D}' - . '\x{8D5E}\x{8D5F}\x{8D60}\x{8D61}\x{8D62}\x{8D63}\x{8D64}\x{8D65}\x{8D66}' - . '\x{8D67}\x{8D68}\x{8D69}\x{8D6A}\x{8D6B}\x{8D6C}\x{8D6D}\x{8D6E}\x{8D6F}' - . '\x{8D70}\x{8D71}\x{8D72}\x{8D73}\x{8D74}\x{8D75}\x{8D76}\x{8D77}\x{8D78}' - . '\x{8D79}\x{8D7A}\x{8D7B}\x{8D7D}\x{8D7E}\x{8D7F}\x{8D80}\x{8D81}\x{8D82}' - . '\x{8D83}\x{8D84}\x{8D85}\x{8D86}\x{8D87}\x{8D88}\x{8D89}\x{8D8A}\x{8D8B}' - . '\x{8D8C}\x{8D8D}\x{8D8E}\x{8D8F}\x{8D90}\x{8D91}\x{8D92}\x{8D93}\x{8D94}' - . '\x{8D95}\x{8D96}\x{8D97}\x{8D98}\x{8D99}\x{8D9A}\x{8D9B}\x{8D9C}\x{8D9D}' - . '\x{8D9E}\x{8D9F}\x{8DA0}\x{8DA1}\x{8DA2}\x{8DA3}\x{8DA4}\x{8DA5}\x{8DA7}' - . '\x{8DA8}\x{8DA9}\x{8DAA}\x{8DAB}\x{8DAC}\x{8DAD}\x{8DAE}\x{8DAF}\x{8DB0}' - . '\x{8DB1}\x{8DB2}\x{8DB3}\x{8DB4}\x{8DB5}\x{8DB6}\x{8DB7}\x{8DB8}\x{8DB9}' - . '\x{8DBA}\x{8DBB}\x{8DBC}\x{8DBD}\x{8DBE}\x{8DBF}\x{8DC1}\x{8DC2}\x{8DC3}' - . '\x{8DC4}\x{8DC5}\x{8DC6}\x{8DC7}\x{8DC8}\x{8DC9}\x{8DCA}\x{8DCB}\x{8DCC}' - . '\x{8DCD}\x{8DCE}\x{8DCF}\x{8DD0}\x{8DD1}\x{8DD2}\x{8DD3}\x{8DD4}\x{8DD5}' - . '\x{8DD6}\x{8DD7}\x{8DD8}\x{8DD9}\x{8DDA}\x{8DDB}\x{8DDC}\x{8DDD}\x{8DDE}' - . '\x{8DDF}\x{8DE0}\x{8DE1}\x{8DE2}\x{8DE3}\x{8DE4}\x{8DE6}\x{8DE7}\x{8DE8}' - . '\x{8DE9}\x{8DEA}\x{8DEB}\x{8DEC}\x{8DED}\x{8DEE}\x{8DEF}\x{8DF0}\x{8DF1}' - . '\x{8DF2}\x{8DF3}\x{8DF4}\x{8DF5}\x{8DF6}\x{8DF7}\x{8DF8}\x{8DF9}\x{8DFA}' - . '\x{8DFB}\x{8DFC}\x{8DFD}\x{8DFE}\x{8DFF}\x{8E00}\x{8E02}\x{8E03}\x{8E04}' - . '\x{8E05}\x{8E06}\x{8E07}\x{8E08}\x{8E09}\x{8E0A}\x{8E0C}\x{8E0D}\x{8E0E}' - . '\x{8E0F}\x{8E10}\x{8E11}\x{8E12}\x{8E13}\x{8E14}\x{8E15}\x{8E16}\x{8E17}' - . '\x{8E18}\x{8E19}\x{8E1A}\x{8E1B}\x{8E1C}\x{8E1D}\x{8E1E}\x{8E1F}\x{8E20}' - . '\x{8E21}\x{8E22}\x{8E23}\x{8E24}\x{8E25}\x{8E26}\x{8E27}\x{8E28}\x{8E29}' - . '\x{8E2A}\x{8E2B}\x{8E2C}\x{8E2D}\x{8E2E}\x{8E2F}\x{8E30}\x{8E31}\x{8E33}' - . '\x{8E34}\x{8E35}\x{8E36}\x{8E37}\x{8E38}\x{8E39}\x{8E3A}\x{8E3B}\x{8E3C}' - . '\x{8E3D}\x{8E3E}\x{8E3F}\x{8E40}\x{8E41}\x{8E42}\x{8E43}\x{8E44}\x{8E45}' - . '\x{8E47}\x{8E48}\x{8E49}\x{8E4A}\x{8E4B}\x{8E4C}\x{8E4D}\x{8E4E}\x{8E50}' - . '\x{8E51}\x{8E52}\x{8E53}\x{8E54}\x{8E55}\x{8E56}\x{8E57}\x{8E58}\x{8E59}' - . '\x{8E5A}\x{8E5B}\x{8E5C}\x{8E5D}\x{8E5E}\x{8E5F}\x{8E60}\x{8E61}\x{8E62}' - . '\x{8E63}\x{8E64}\x{8E65}\x{8E66}\x{8E67}\x{8E68}\x{8E69}\x{8E6A}\x{8E6B}' - . '\x{8E6C}\x{8E6D}\x{8E6F}\x{8E70}\x{8E71}\x{8E72}\x{8E73}\x{8E74}\x{8E76}' - . '\x{8E78}\x{8E7A}\x{8E7B}\x{8E7C}\x{8E7D}\x{8E7E}\x{8E7F}\x{8E80}\x{8E81}' - . '\x{8E82}\x{8E83}\x{8E84}\x{8E85}\x{8E86}\x{8E87}\x{8E88}\x{8E89}\x{8E8A}' - . '\x{8E8B}\x{8E8C}\x{8E8D}\x{8E8E}\x{8E8F}\x{8E90}\x{8E91}\x{8E92}\x{8E93}' - . '\x{8E94}\x{8E95}\x{8E96}\x{8E97}\x{8E98}\x{8E9A}\x{8E9C}\x{8E9D}\x{8E9E}' - . '\x{8E9F}\x{8EA0}\x{8EA1}\x{8EA3}\x{8EA4}\x{8EA5}\x{8EA6}\x{8EA7}\x{8EA8}' - . '\x{8EA9}\x{8EAA}\x{8EAB}\x{8EAC}\x{8EAD}\x{8EAE}\x{8EAF}\x{8EB0}\x{8EB1}' - . '\x{8EB2}\x{8EB4}\x{8EB5}\x{8EB8}\x{8EB9}\x{8EBA}\x{8EBB}\x{8EBC}\x{8EBD}' - . '\x{8EBE}\x{8EBF}\x{8EC0}\x{8EC2}\x{8EC3}\x{8EC5}\x{8EC6}\x{8EC7}\x{8EC8}' - . '\x{8EC9}\x{8ECA}\x{8ECB}\x{8ECC}\x{8ECD}\x{8ECE}\x{8ECF}\x{8ED0}\x{8ED1}' - . '\x{8ED2}\x{8ED3}\x{8ED4}\x{8ED5}\x{8ED6}\x{8ED7}\x{8ED8}\x{8EDA}\x{8EDB}' - . '\x{8EDC}\x{8EDD}\x{8EDE}\x{8EDF}\x{8EE0}\x{8EE1}\x{8EE4}\x{8EE5}\x{8EE6}' - . '\x{8EE7}\x{8EE8}\x{8EE9}\x{8EEA}\x{8EEB}\x{8EEC}\x{8EED}\x{8EEE}\x{8EEF}' - . '\x{8EF1}\x{8EF2}\x{8EF3}\x{8EF4}\x{8EF5}\x{8EF6}\x{8EF7}\x{8EF8}\x{8EF9}' - . '\x{8EFA}\x{8EFB}\x{8EFC}\x{8EFD}\x{8EFE}\x{8EFF}\x{8F00}\x{8F01}\x{8F02}' - . '\x{8F03}\x{8F04}\x{8F05}\x{8F06}\x{8F07}\x{8F08}\x{8F09}\x{8F0A}\x{8F0B}' - . '\x{8F0D}\x{8F0E}\x{8F10}\x{8F11}\x{8F12}\x{8F13}\x{8F14}\x{8F15}\x{8F16}' - . '\x{8F17}\x{8F18}\x{8F1A}\x{8F1B}\x{8F1C}\x{8F1D}\x{8F1E}\x{8F1F}\x{8F20}' - . '\x{8F21}\x{8F22}\x{8F23}\x{8F24}\x{8F25}\x{8F26}\x{8F27}\x{8F28}\x{8F29}' - . '\x{8F2A}\x{8F2B}\x{8F2C}\x{8F2E}\x{8F2F}\x{8F30}\x{8F31}\x{8F32}\x{8F33}' - . '\x{8F34}\x{8F35}\x{8F36}\x{8F37}\x{8F38}\x{8F39}\x{8F3B}\x{8F3C}\x{8F3D}' - . '\x{8F3E}\x{8F3F}\x{8F40}\x{8F42}\x{8F43}\x{8F44}\x{8F45}\x{8F46}\x{8F47}' - . '\x{8F48}\x{8F49}\x{8F4A}\x{8F4B}\x{8F4C}\x{8F4D}\x{8F4E}\x{8F4F}\x{8F50}' - . '\x{8F51}\x{8F52}\x{8F53}\x{8F54}\x{8F55}\x{8F56}\x{8F57}\x{8F58}\x{8F59}' - . '\x{8F5A}\x{8F5B}\x{8F5D}\x{8F5E}\x{8F5F}\x{8F60}\x{8F61}\x{8F62}\x{8F63}' - . '\x{8F64}\x{8F65}\x{8F66}\x{8F67}\x{8F68}\x{8F69}\x{8F6A}\x{8F6B}\x{8F6C}' - . '\x{8F6D}\x{8F6E}\x{8F6F}\x{8F70}\x{8F71}\x{8F72}\x{8F73}\x{8F74}\x{8F75}' - . '\x{8F76}\x{8F77}\x{8F78}\x{8F79}\x{8F7A}\x{8F7B}\x{8F7C}\x{8F7D}\x{8F7E}' - . '\x{8F7F}\x{8F80}\x{8F81}\x{8F82}\x{8F83}\x{8F84}\x{8F85}\x{8F86}\x{8F87}' - . '\x{8F88}\x{8F89}\x{8F8A}\x{8F8B}\x{8F8C}\x{8F8D}\x{8F8E}\x{8F8F}\x{8F90}' - . '\x{8F91}\x{8F92}\x{8F93}\x{8F94}\x{8F95}\x{8F96}\x{8F97}\x{8F98}\x{8F99}' - . '\x{8F9A}\x{8F9B}\x{8F9C}\x{8F9E}\x{8F9F}\x{8FA0}\x{8FA1}\x{8FA2}\x{8FA3}' - . '\x{8FA5}\x{8FA6}\x{8FA7}\x{8FA8}\x{8FA9}\x{8FAA}\x{8FAB}\x{8FAC}\x{8FAD}' - . '\x{8FAE}\x{8FAF}\x{8FB0}\x{8FB1}\x{8FB2}\x{8FB4}\x{8FB5}\x{8FB6}\x{8FB7}' - . '\x{8FB8}\x{8FB9}\x{8FBB}\x{8FBC}\x{8FBD}\x{8FBE}\x{8FBF}\x{8FC0}\x{8FC1}' - . '\x{8FC2}\x{8FC4}\x{8FC5}\x{8FC6}\x{8FC7}\x{8FC8}\x{8FC9}\x{8FCB}\x{8FCC}' - . '\x{8FCD}\x{8FCE}\x{8FCF}\x{8FD0}\x{8FD1}\x{8FD2}\x{8FD3}\x{8FD4}\x{8FD5}' - . '\x{8FD6}\x{8FD7}\x{8FD8}\x{8FD9}\x{8FDA}\x{8FDB}\x{8FDC}\x{8FDD}\x{8FDE}' - . '\x{8FDF}\x{8FE0}\x{8FE1}\x{8FE2}\x{8FE3}\x{8FE4}\x{8FE5}\x{8FE6}\x{8FE8}' - . '\x{8FE9}\x{8FEA}\x{8FEB}\x{8FEC}\x{8FED}\x{8FEE}\x{8FEF}\x{8FF0}\x{8FF1}' - . '\x{8FF2}\x{8FF3}\x{8FF4}\x{8FF5}\x{8FF6}\x{8FF7}\x{8FF8}\x{8FF9}\x{8FFA}' - . '\x{8FFB}\x{8FFC}\x{8FFD}\x{8FFE}\x{8FFF}\x{9000}\x{9001}\x{9002}\x{9003}' - . '\x{9004}\x{9005}\x{9006}\x{9007}\x{9008}\x{9009}\x{900A}\x{900B}\x{900C}' - . '\x{900D}\x{900F}\x{9010}\x{9011}\x{9012}\x{9013}\x{9014}\x{9015}\x{9016}' - . '\x{9017}\x{9018}\x{9019}\x{901A}\x{901B}\x{901C}\x{901D}\x{901E}\x{901F}' - . '\x{9020}\x{9021}\x{9022}\x{9023}\x{9024}\x{9025}\x{9026}\x{9027}\x{9028}' - . '\x{9029}\x{902B}\x{902D}\x{902E}\x{902F}\x{9030}\x{9031}\x{9032}\x{9033}' - . '\x{9034}\x{9035}\x{9036}\x{9038}\x{903A}\x{903B}\x{903C}\x{903D}\x{903E}' - . '\x{903F}\x{9041}\x{9042}\x{9043}\x{9044}\x{9045}\x{9047}\x{9048}\x{9049}' - . '\x{904A}\x{904B}\x{904C}\x{904D}\x{904E}\x{904F}\x{9050}\x{9051}\x{9052}' - . '\x{9053}\x{9054}\x{9055}\x{9056}\x{9057}\x{9058}\x{9059}\x{905A}\x{905B}' - . '\x{905C}\x{905D}\x{905E}\x{905F}\x{9060}\x{9061}\x{9062}\x{9063}\x{9064}' - . '\x{9065}\x{9066}\x{9067}\x{9068}\x{9069}\x{906A}\x{906B}\x{906C}\x{906D}' - . '\x{906E}\x{906F}\x{9070}\x{9071}\x{9072}\x{9073}\x{9074}\x{9075}\x{9076}' - . '\x{9077}\x{9078}\x{9079}\x{907A}\x{907B}\x{907C}\x{907D}\x{907E}\x{907F}' - . '\x{9080}\x{9081}\x{9082}\x{9083}\x{9084}\x{9085}\x{9086}\x{9087}\x{9088}' - . '\x{9089}\x{908A}\x{908B}\x{908C}\x{908D}\x{908E}\x{908F}\x{9090}\x{9091}' - . '\x{9092}\x{9093}\x{9094}\x{9095}\x{9096}\x{9097}\x{9098}\x{9099}\x{909A}' - . '\x{909B}\x{909C}\x{909D}\x{909E}\x{909F}\x{90A0}\x{90A1}\x{90A2}\x{90A3}' - . '\x{90A4}\x{90A5}\x{90A6}\x{90A7}\x{90A8}\x{90A9}\x{90AA}\x{90AC}\x{90AD}' - . '\x{90AE}\x{90AF}\x{90B0}\x{90B1}\x{90B2}\x{90B3}\x{90B4}\x{90B5}\x{90B6}' - . '\x{90B7}\x{90B8}\x{90B9}\x{90BA}\x{90BB}\x{90BC}\x{90BD}\x{90BE}\x{90BF}' - . '\x{90C0}\x{90C1}\x{90C2}\x{90C3}\x{90C4}\x{90C5}\x{90C6}\x{90C7}\x{90C8}' - . '\x{90C9}\x{90CA}\x{90CB}\x{90CE}\x{90CF}\x{90D0}\x{90D1}\x{90D3}\x{90D4}' - . '\x{90D5}\x{90D6}\x{90D7}\x{90D8}\x{90D9}\x{90DA}\x{90DB}\x{90DC}\x{90DD}' - . '\x{90DE}\x{90DF}\x{90E0}\x{90E1}\x{90E2}\x{90E3}\x{90E4}\x{90E5}\x{90E6}' - . '\x{90E7}\x{90E8}\x{90E9}\x{90EA}\x{90EB}\x{90EC}\x{90ED}\x{90EE}\x{90EF}' - . '\x{90F0}\x{90F1}\x{90F2}\x{90F3}\x{90F4}\x{90F5}\x{90F7}\x{90F8}\x{90F9}' - . '\x{90FA}\x{90FB}\x{90FC}\x{90FD}\x{90FE}\x{90FF}\x{9100}\x{9101}\x{9102}' - . '\x{9103}\x{9104}\x{9105}\x{9106}\x{9107}\x{9108}\x{9109}\x{910B}\x{910C}' - . '\x{910D}\x{910E}\x{910F}\x{9110}\x{9111}\x{9112}\x{9113}\x{9114}\x{9115}' - . '\x{9116}\x{9117}\x{9118}\x{9119}\x{911A}\x{911B}\x{911C}\x{911D}\x{911E}' - . '\x{911F}\x{9120}\x{9121}\x{9122}\x{9123}\x{9124}\x{9125}\x{9126}\x{9127}' - . '\x{9128}\x{9129}\x{912A}\x{912B}\x{912C}\x{912D}\x{912E}\x{912F}\x{9130}' - . '\x{9131}\x{9132}\x{9133}\x{9134}\x{9135}\x{9136}\x{9137}\x{9138}\x{9139}' - . '\x{913A}\x{913B}\x{913E}\x{913F}\x{9140}\x{9141}\x{9142}\x{9143}\x{9144}' - . '\x{9145}\x{9146}\x{9147}\x{9148}\x{9149}\x{914A}\x{914B}\x{914C}\x{914D}' - . '\x{914E}\x{914F}\x{9150}\x{9151}\x{9152}\x{9153}\x{9154}\x{9155}\x{9156}' - . '\x{9157}\x{9158}\x{915A}\x{915B}\x{915C}\x{915D}\x{915E}\x{915F}\x{9160}' - . '\x{9161}\x{9162}\x{9163}\x{9164}\x{9165}\x{9166}\x{9167}\x{9168}\x{9169}' - . '\x{916A}\x{916B}\x{916C}\x{916D}\x{916E}\x{916F}\x{9170}\x{9171}\x{9172}' - . '\x{9173}\x{9174}\x{9175}\x{9176}\x{9177}\x{9178}\x{9179}\x{917A}\x{917C}' - . '\x{917D}\x{917E}\x{917F}\x{9180}\x{9181}\x{9182}\x{9183}\x{9184}\x{9185}' - . '\x{9186}\x{9187}\x{9188}\x{9189}\x{918A}\x{918B}\x{918C}\x{918D}\x{918E}' - . '\x{918F}\x{9190}\x{9191}\x{9192}\x{9193}\x{9194}\x{9196}\x{9199}\x{919A}' - . '\x{919B}\x{919C}\x{919D}\x{919E}\x{919F}\x{91A0}\x{91A1}\x{91A2}\x{91A3}' - . '\x{91A5}\x{91A6}\x{91A7}\x{91A8}\x{91AA}\x{91AB}\x{91AC}\x{91AD}\x{91AE}' - . '\x{91AF}\x{91B0}\x{91B1}\x{91B2}\x{91B3}\x{91B4}\x{91B5}\x{91B6}\x{91B7}' - . '\x{91B9}\x{91BA}\x{91BB}\x{91BC}\x{91BD}\x{91BE}\x{91C0}\x{91C1}\x{91C2}' - . '\x{91C3}\x{91C5}\x{91C6}\x{91C7}\x{91C9}\x{91CA}\x{91CB}\x{91CC}\x{91CD}' - . '\x{91CE}\x{91CF}\x{91D0}\x{91D1}\x{91D2}\x{91D3}\x{91D4}\x{91D5}\x{91D7}' - . '\x{91D8}\x{91D9}\x{91DA}\x{91DB}\x{91DC}\x{91DD}\x{91DE}\x{91DF}\x{91E2}' - . '\x{91E3}\x{91E4}\x{91E5}\x{91E6}\x{91E7}\x{91E8}\x{91E9}\x{91EA}\x{91EB}' - . '\x{91EC}\x{91ED}\x{91EE}\x{91F0}\x{91F1}\x{91F2}\x{91F3}\x{91F4}\x{91F5}' - . '\x{91F7}\x{91F8}\x{91F9}\x{91FA}\x{91FB}\x{91FD}\x{91FE}\x{91FF}\x{9200}' - . '\x{9201}\x{9202}\x{9203}\x{9204}\x{9205}\x{9206}\x{9207}\x{9208}\x{9209}' - . '\x{920A}\x{920B}\x{920C}\x{920D}\x{920E}\x{920F}\x{9210}\x{9211}\x{9212}' - . '\x{9214}\x{9215}\x{9216}\x{9217}\x{9218}\x{9219}\x{921A}\x{921B}\x{921C}' - . '\x{921D}\x{921E}\x{9220}\x{9221}\x{9223}\x{9224}\x{9225}\x{9226}\x{9227}' - . '\x{9228}\x{9229}\x{922A}\x{922B}\x{922D}\x{922E}\x{922F}\x{9230}\x{9231}' - . '\x{9232}\x{9233}\x{9234}\x{9235}\x{9236}\x{9237}\x{9238}\x{9239}\x{923A}' - . '\x{923B}\x{923C}\x{923D}\x{923E}\x{923F}\x{9240}\x{9241}\x{9242}\x{9245}' - . '\x{9246}\x{9247}\x{9248}\x{9249}\x{924A}\x{924B}\x{924C}\x{924D}\x{924E}' - . '\x{924F}\x{9250}\x{9251}\x{9252}\x{9253}\x{9254}\x{9255}\x{9256}\x{9257}' - . '\x{9258}\x{9259}\x{925A}\x{925B}\x{925C}\x{925D}\x{925E}\x{925F}\x{9260}' - . '\x{9261}\x{9262}\x{9263}\x{9264}\x{9265}\x{9266}\x{9267}\x{9268}\x{926B}' - . '\x{926C}\x{926D}\x{926E}\x{926F}\x{9270}\x{9272}\x{9273}\x{9274}\x{9275}' - . '\x{9276}\x{9277}\x{9278}\x{9279}\x{927A}\x{927B}\x{927C}\x{927D}\x{927E}' - . '\x{927F}\x{9280}\x{9282}\x{9283}\x{9285}\x{9286}\x{9287}\x{9288}\x{9289}' - . '\x{928A}\x{928B}\x{928C}\x{928D}\x{928E}\x{928F}\x{9290}\x{9291}\x{9292}' - . '\x{9293}\x{9294}\x{9295}\x{9296}\x{9297}\x{9298}\x{9299}\x{929A}\x{929B}' - . '\x{929C}\x{929D}\x{929F}\x{92A0}\x{92A1}\x{92A2}\x{92A3}\x{92A4}\x{92A5}' - . '\x{92A6}\x{92A7}\x{92A8}\x{92A9}\x{92AA}\x{92AB}\x{92AC}\x{92AD}\x{92AE}' - . '\x{92AF}\x{92B0}\x{92B1}\x{92B2}\x{92B3}\x{92B4}\x{92B5}\x{92B6}\x{92B7}' - . '\x{92B8}\x{92B9}\x{92BA}\x{92BB}\x{92BC}\x{92BE}\x{92BF}\x{92C0}\x{92C1}' - . '\x{92C2}\x{92C3}\x{92C4}\x{92C5}\x{92C6}\x{92C7}\x{92C8}\x{92C9}\x{92CA}' - . '\x{92CB}\x{92CC}\x{92CD}\x{92CE}\x{92CF}\x{92D0}\x{92D1}\x{92D2}\x{92D3}' - . '\x{92D5}\x{92D6}\x{92D7}\x{92D8}\x{92D9}\x{92DA}\x{92DC}\x{92DD}\x{92DE}' - . '\x{92DF}\x{92E0}\x{92E1}\x{92E3}\x{92E4}\x{92E5}\x{92E6}\x{92E7}\x{92E8}' - . '\x{92E9}\x{92EA}\x{92EB}\x{92EC}\x{92ED}\x{92EE}\x{92EF}\x{92F0}\x{92F1}' - . '\x{92F2}\x{92F3}\x{92F4}\x{92F5}\x{92F6}\x{92F7}\x{92F8}\x{92F9}\x{92FA}' - . '\x{92FB}\x{92FC}\x{92FD}\x{92FE}\x{92FF}\x{9300}\x{9301}\x{9302}\x{9303}' - . '\x{9304}\x{9305}\x{9306}\x{9307}\x{9308}\x{9309}\x{930A}\x{930B}\x{930C}' - . '\x{930D}\x{930E}\x{930F}\x{9310}\x{9311}\x{9312}\x{9313}\x{9314}\x{9315}' - . '\x{9316}\x{9317}\x{9318}\x{9319}\x{931A}\x{931B}\x{931D}\x{931E}\x{931F}' - . '\x{9320}\x{9321}\x{9322}\x{9323}\x{9324}\x{9325}\x{9326}\x{9327}\x{9328}' - . '\x{9329}\x{932A}\x{932B}\x{932D}\x{932E}\x{932F}\x{9332}\x{9333}\x{9334}' - . '\x{9335}\x{9336}\x{9337}\x{9338}\x{9339}\x{933A}\x{933B}\x{933C}\x{933D}' - . '\x{933E}\x{933F}\x{9340}\x{9341}\x{9342}\x{9343}\x{9344}\x{9345}\x{9346}' - . '\x{9347}\x{9348}\x{9349}\x{934A}\x{934B}\x{934C}\x{934D}\x{934E}\x{934F}' - . '\x{9350}\x{9351}\x{9352}\x{9353}\x{9354}\x{9355}\x{9356}\x{9357}\x{9358}' - . '\x{9359}\x{935A}\x{935B}\x{935C}\x{935D}\x{935E}\x{935F}\x{9360}\x{9361}' - . '\x{9363}\x{9364}\x{9365}\x{9366}\x{9367}\x{9369}\x{936A}\x{936C}\x{936D}' - . '\x{936E}\x{9370}\x{9371}\x{9372}\x{9374}\x{9375}\x{9376}\x{9377}\x{9379}' - . '\x{937A}\x{937B}\x{937C}\x{937D}\x{937E}\x{9380}\x{9382}\x{9383}\x{9384}' - . '\x{9385}\x{9386}\x{9387}\x{9388}\x{9389}\x{938A}\x{938C}\x{938D}\x{938E}' - . '\x{938F}\x{9390}\x{9391}\x{9392}\x{9393}\x{9394}\x{9395}\x{9396}\x{9397}' - . '\x{9398}\x{9399}\x{939A}\x{939B}\x{939D}\x{939E}\x{939F}\x{93A1}\x{93A2}' - . '\x{93A3}\x{93A4}\x{93A5}\x{93A6}\x{93A7}\x{93A8}\x{93A9}\x{93AA}\x{93AC}' - . '\x{93AD}\x{93AE}\x{93AF}\x{93B0}\x{93B1}\x{93B2}\x{93B3}\x{93B4}\x{93B5}' - . '\x{93B6}\x{93B7}\x{93B8}\x{93B9}\x{93BA}\x{93BC}\x{93BD}\x{93BE}\x{93BF}' - . '\x{93C0}\x{93C1}\x{93C2}\x{93C3}\x{93C4}\x{93C5}\x{93C6}\x{93C7}\x{93C8}' - . '\x{93C9}\x{93CA}\x{93CB}\x{93CC}\x{93CD}\x{93CE}\x{93CF}\x{93D0}\x{93D1}' - . '\x{93D2}\x{93D3}\x{93D4}\x{93D5}\x{93D6}\x{93D7}\x{93D8}\x{93D9}\x{93DA}' - . '\x{93DB}\x{93DC}\x{93DD}\x{93DE}\x{93DF}\x{93E1}\x{93E2}\x{93E3}\x{93E4}' - . '\x{93E6}\x{93E7}\x{93E8}\x{93E9}\x{93EA}\x{93EB}\x{93EC}\x{93ED}\x{93EE}' - . '\x{93EF}\x{93F0}\x{93F1}\x{93F2}\x{93F4}\x{93F5}\x{93F6}\x{93F7}\x{93F8}' - . '\x{93F9}\x{93FA}\x{93FB}\x{93FC}\x{93FD}\x{93FE}\x{93FF}\x{9400}\x{9401}' - . '\x{9403}\x{9404}\x{9405}\x{9406}\x{9407}\x{9408}\x{9409}\x{940A}\x{940B}' - . '\x{940C}\x{940D}\x{940E}\x{940F}\x{9410}\x{9411}\x{9412}\x{9413}\x{9414}' - . '\x{9415}\x{9416}\x{9418}\x{9419}\x{941B}\x{941D}\x{9420}\x{9422}\x{9423}' - . '\x{9425}\x{9426}\x{9427}\x{9428}\x{9429}\x{942A}\x{942B}\x{942C}\x{942D}' - . '\x{942E}\x{942F}\x{9430}\x{9431}\x{9432}\x{9433}\x{9434}\x{9435}\x{9436}' - . '\x{9437}\x{9438}\x{9439}\x{943A}\x{943B}\x{943C}\x{943D}\x{943E}\x{943F}' - . '\x{9440}\x{9441}\x{9442}\x{9444}\x{9445}\x{9446}\x{9447}\x{9448}\x{9449}' - . '\x{944A}\x{944B}\x{944C}\x{944D}\x{944F}\x{9450}\x{9451}\x{9452}\x{9453}' - . '\x{9454}\x{9455}\x{9456}\x{9457}\x{9458}\x{9459}\x{945B}\x{945C}\x{945D}' - . '\x{945E}\x{945F}\x{9460}\x{9461}\x{9462}\x{9463}\x{9464}\x{9465}\x{9466}' - . '\x{9467}\x{9468}\x{9469}\x{946A}\x{946B}\x{946D}\x{946E}\x{946F}\x{9470}' - . '\x{9471}\x{9472}\x{9473}\x{9474}\x{9475}\x{9476}\x{9477}\x{9478}\x{9479}' - . '\x{947A}\x{947C}\x{947D}\x{947E}\x{947F}\x{9480}\x{9481}\x{9482}\x{9483}' - . '\x{9484}\x{9485}\x{9486}\x{9487}\x{9488}\x{9489}\x{948A}\x{948B}\x{948C}' - . '\x{948D}\x{948E}\x{948F}\x{9490}\x{9491}\x{9492}\x{9493}\x{9494}\x{9495}' - . '\x{9496}\x{9497}\x{9498}\x{9499}\x{949A}\x{949B}\x{949C}\x{949D}\x{949E}' - . '\x{949F}\x{94A0}\x{94A1}\x{94A2}\x{94A3}\x{94A4}\x{94A5}\x{94A6}\x{94A7}' - . '\x{94A8}\x{94A9}\x{94AA}\x{94AB}\x{94AC}\x{94AD}\x{94AE}\x{94AF}\x{94B0}' - . '\x{94B1}\x{94B2}\x{94B3}\x{94B4}\x{94B5}\x{94B6}\x{94B7}\x{94B8}\x{94B9}' - . '\x{94BA}\x{94BB}\x{94BC}\x{94BD}\x{94BE}\x{94BF}\x{94C0}\x{94C1}\x{94C2}' - . '\x{94C3}\x{94C4}\x{94C5}\x{94C6}\x{94C7}\x{94C8}\x{94C9}\x{94CA}\x{94CB}' - . '\x{94CC}\x{94CD}\x{94CE}\x{94CF}\x{94D0}\x{94D1}\x{94D2}\x{94D3}\x{94D4}' - . '\x{94D5}\x{94D6}\x{94D7}\x{94D8}\x{94D9}\x{94DA}\x{94DB}\x{94DC}\x{94DD}' - . '\x{94DE}\x{94DF}\x{94E0}\x{94E1}\x{94E2}\x{94E3}\x{94E4}\x{94E5}\x{94E6}' - . '\x{94E7}\x{94E8}\x{94E9}\x{94EA}\x{94EB}\x{94EC}\x{94ED}\x{94EE}\x{94EF}' - . '\x{94F0}\x{94F1}\x{94F2}\x{94F3}\x{94F4}\x{94F5}\x{94F6}\x{94F7}\x{94F8}' - . '\x{94F9}\x{94FA}\x{94FB}\x{94FC}\x{94FD}\x{94FE}\x{94FF}\x{9500}\x{9501}' - . '\x{9502}\x{9503}\x{9504}\x{9505}\x{9506}\x{9507}\x{9508}\x{9509}\x{950A}' - . '\x{950B}\x{950C}\x{950D}\x{950E}\x{950F}\x{9510}\x{9511}\x{9512}\x{9513}' - . '\x{9514}\x{9515}\x{9516}\x{9517}\x{9518}\x{9519}\x{951A}\x{951B}\x{951C}' - . '\x{951D}\x{951E}\x{951F}\x{9520}\x{9521}\x{9522}\x{9523}\x{9524}\x{9525}' - . '\x{9526}\x{9527}\x{9528}\x{9529}\x{952A}\x{952B}\x{952C}\x{952D}\x{952E}' - . '\x{952F}\x{9530}\x{9531}\x{9532}\x{9533}\x{9534}\x{9535}\x{9536}\x{9537}' - . '\x{9538}\x{9539}\x{953A}\x{953B}\x{953C}\x{953D}\x{953E}\x{953F}\x{9540}' - . '\x{9541}\x{9542}\x{9543}\x{9544}\x{9545}\x{9546}\x{9547}\x{9548}\x{9549}' - . '\x{954A}\x{954B}\x{954C}\x{954D}\x{954E}\x{954F}\x{9550}\x{9551}\x{9552}' - . '\x{9553}\x{9554}\x{9555}\x{9556}\x{9557}\x{9558}\x{9559}\x{955A}\x{955B}' - . '\x{955C}\x{955D}\x{955E}\x{955F}\x{9560}\x{9561}\x{9562}\x{9563}\x{9564}' - . '\x{9565}\x{9566}\x{9567}\x{9568}\x{9569}\x{956A}\x{956B}\x{956C}\x{956D}' - . '\x{956E}\x{956F}\x{9570}\x{9571}\x{9572}\x{9573}\x{9574}\x{9575}\x{9576}' - . '\x{9577}\x{957A}\x{957B}\x{957C}\x{957D}\x{957F}\x{9580}\x{9581}\x{9582}' - . '\x{9583}\x{9584}\x{9586}\x{9587}\x{9588}\x{9589}\x{958A}\x{958B}\x{958C}' - . '\x{958D}\x{958E}\x{958F}\x{9590}\x{9591}\x{9592}\x{9593}\x{9594}\x{9595}' - . '\x{9596}\x{9598}\x{9599}\x{959A}\x{959B}\x{959C}\x{959D}\x{959E}\x{959F}' - . '\x{95A1}\x{95A2}\x{95A3}\x{95A4}\x{95A5}\x{95A6}\x{95A7}\x{95A8}\x{95A9}' - . '\x{95AA}\x{95AB}\x{95AC}\x{95AD}\x{95AE}\x{95AF}\x{95B0}\x{95B1}\x{95B2}' - . '\x{95B5}\x{95B6}\x{95B7}\x{95B9}\x{95BA}\x{95BB}\x{95BC}\x{95BD}\x{95BE}' - . '\x{95BF}\x{95C0}\x{95C2}\x{95C3}\x{95C4}\x{95C5}\x{95C6}\x{95C7}\x{95C8}' - . '\x{95C9}\x{95CA}\x{95CB}\x{95CC}\x{95CD}\x{95CE}\x{95CF}\x{95D0}\x{95D1}' - . '\x{95D2}\x{95D3}\x{95D4}\x{95D5}\x{95D6}\x{95D7}\x{95D8}\x{95DA}\x{95DB}' - . '\x{95DC}\x{95DE}\x{95DF}\x{95E0}\x{95E1}\x{95E2}\x{95E3}\x{95E4}\x{95E5}' - . '\x{95E6}\x{95E7}\x{95E8}\x{95E9}\x{95EA}\x{95EB}\x{95EC}\x{95ED}\x{95EE}' - . '\x{95EF}\x{95F0}\x{95F1}\x{95F2}\x{95F3}\x{95F4}\x{95F5}\x{95F6}\x{95F7}' - . '\x{95F8}\x{95F9}\x{95FA}\x{95FB}\x{95FC}\x{95FD}\x{95FE}\x{95FF}\x{9600}' - . '\x{9601}\x{9602}\x{9603}\x{9604}\x{9605}\x{9606}\x{9607}\x{9608}\x{9609}' - . '\x{960A}\x{960B}\x{960C}\x{960D}\x{960E}\x{960F}\x{9610}\x{9611}\x{9612}' - . '\x{9613}\x{9614}\x{9615}\x{9616}\x{9617}\x{9618}\x{9619}\x{961A}\x{961B}' - . '\x{961C}\x{961D}\x{961E}\x{961F}\x{9620}\x{9621}\x{9622}\x{9623}\x{9624}' - . '\x{9627}\x{9628}\x{962A}\x{962B}\x{962C}\x{962D}\x{962E}\x{962F}\x{9630}' - . '\x{9631}\x{9632}\x{9633}\x{9634}\x{9635}\x{9636}\x{9637}\x{9638}\x{9639}' - . '\x{963A}\x{963B}\x{963C}\x{963D}\x{963F}\x{9640}\x{9641}\x{9642}\x{9643}' - . '\x{9644}\x{9645}\x{9646}\x{9647}\x{9648}\x{9649}\x{964A}\x{964B}\x{964C}' - . '\x{964D}\x{964E}\x{964F}\x{9650}\x{9651}\x{9652}\x{9653}\x{9654}\x{9655}' - . '\x{9658}\x{9659}\x{965A}\x{965B}\x{965C}\x{965D}\x{965E}\x{965F}\x{9660}' - . '\x{9661}\x{9662}\x{9663}\x{9664}\x{9666}\x{9667}\x{9668}\x{9669}\x{966A}' - . '\x{966B}\x{966C}\x{966D}\x{966E}\x{966F}\x{9670}\x{9671}\x{9672}\x{9673}' - . '\x{9674}\x{9675}\x{9676}\x{9677}\x{9678}\x{967C}\x{967D}\x{967E}\x{9680}' - . '\x{9683}\x{9684}\x{9685}\x{9686}\x{9687}\x{9688}\x{9689}\x{968A}\x{968B}' - . '\x{968D}\x{968E}\x{968F}\x{9690}\x{9691}\x{9692}\x{9693}\x{9694}\x{9695}' - . '\x{9697}\x{9698}\x{9699}\x{969B}\x{969C}\x{969E}\x{96A0}\x{96A1}\x{96A2}' - . '\x{96A3}\x{96A4}\x{96A5}\x{96A6}\x{96A7}\x{96A8}\x{96A9}\x{96AA}\x{96AC}' - . '\x{96AD}\x{96AE}\x{96B0}\x{96B1}\x{96B3}\x{96B4}\x{96B6}\x{96B7}\x{96B8}' - . '\x{96B9}\x{96BA}\x{96BB}\x{96BC}\x{96BD}\x{96BE}\x{96BF}\x{96C0}\x{96C1}' - . '\x{96C2}\x{96C3}\x{96C4}\x{96C5}\x{96C6}\x{96C7}\x{96C8}\x{96C9}\x{96CA}' - . '\x{96CB}\x{96CC}\x{96CD}\x{96CE}\x{96CF}\x{96D0}\x{96D1}\x{96D2}\x{96D3}' - . '\x{96D4}\x{96D5}\x{96D6}\x{96D7}\x{96D8}\x{96D9}\x{96DA}\x{96DB}\x{96DC}' - . '\x{96DD}\x{96DE}\x{96DF}\x{96E0}\x{96E1}\x{96E2}\x{96E3}\x{96E5}\x{96E8}' - . '\x{96E9}\x{96EA}\x{96EB}\x{96EC}\x{96ED}\x{96EE}\x{96EF}\x{96F0}\x{96F1}' - . '\x{96F2}\x{96F3}\x{96F4}\x{96F5}\x{96F6}\x{96F7}\x{96F8}\x{96F9}\x{96FA}' - . '\x{96FB}\x{96FD}\x{96FE}\x{96FF}\x{9700}\x{9701}\x{9702}\x{9703}\x{9704}' - . '\x{9705}\x{9706}\x{9707}\x{9708}\x{9709}\x{970A}\x{970B}\x{970C}\x{970D}' - . '\x{970E}\x{970F}\x{9710}\x{9711}\x{9712}\x{9713}\x{9715}\x{9716}\x{9718}' - . '\x{9719}\x{971C}\x{971D}\x{971E}\x{971F}\x{9720}\x{9721}\x{9722}\x{9723}' - . '\x{9724}\x{9725}\x{9726}\x{9727}\x{9728}\x{9729}\x{972A}\x{972B}\x{972C}' - . '\x{972D}\x{972E}\x{972F}\x{9730}\x{9731}\x{9732}\x{9735}\x{9736}\x{9738}' - . '\x{9739}\x{973A}\x{973B}\x{973C}\x{973D}\x{973E}\x{973F}\x{9742}\x{9743}' - . '\x{9744}\x{9745}\x{9746}\x{9747}\x{9748}\x{9749}\x{974A}\x{974B}\x{974C}' - . '\x{974E}\x{974F}\x{9750}\x{9751}\x{9752}\x{9753}\x{9754}\x{9755}\x{9756}' - . '\x{9758}\x{9759}\x{975A}\x{975B}\x{975C}\x{975D}\x{975E}\x{975F}\x{9760}' - . '\x{9761}\x{9762}\x{9765}\x{9766}\x{9767}\x{9768}\x{9769}\x{976A}\x{976B}' - . '\x{976C}\x{976D}\x{976E}\x{976F}\x{9770}\x{9772}\x{9773}\x{9774}\x{9776}' - . '\x{9777}\x{9778}\x{9779}\x{977A}\x{977B}\x{977C}\x{977D}\x{977E}\x{977F}' - . '\x{9780}\x{9781}\x{9782}\x{9783}\x{9784}\x{9785}\x{9786}\x{9788}\x{978A}' - . '\x{978B}\x{978C}\x{978D}\x{978E}\x{978F}\x{9790}\x{9791}\x{9792}\x{9793}' - . '\x{9794}\x{9795}\x{9796}\x{9797}\x{9798}\x{9799}\x{979A}\x{979C}\x{979D}' - . '\x{979E}\x{979F}\x{97A0}\x{97A1}\x{97A2}\x{97A3}\x{97A4}\x{97A5}\x{97A6}' - . '\x{97A7}\x{97A8}\x{97AA}\x{97AB}\x{97AC}\x{97AD}\x{97AE}\x{97AF}\x{97B2}' - . '\x{97B3}\x{97B4}\x{97B6}\x{97B7}\x{97B8}\x{97B9}\x{97BA}\x{97BB}\x{97BC}' - . '\x{97BD}\x{97BF}\x{97C1}\x{97C2}\x{97C3}\x{97C4}\x{97C5}\x{97C6}\x{97C7}' - . '\x{97C8}\x{97C9}\x{97CA}\x{97CB}\x{97CC}\x{97CD}\x{97CE}\x{97CF}\x{97D0}' - . '\x{97D1}\x{97D3}\x{97D4}\x{97D5}\x{97D6}\x{97D7}\x{97D8}\x{97D9}\x{97DA}' - . '\x{97DB}\x{97DC}\x{97DD}\x{97DE}\x{97DF}\x{97E0}\x{97E1}\x{97E2}\x{97E3}' - . '\x{97E4}\x{97E5}\x{97E6}\x{97E7}\x{97E8}\x{97E9}\x{97EA}\x{97EB}\x{97EC}' - . '\x{97ED}\x{97EE}\x{97EF}\x{97F0}\x{97F1}\x{97F2}\x{97F3}\x{97F4}\x{97F5}' - . '\x{97F6}\x{97F7}\x{97F8}\x{97F9}\x{97FA}\x{97FB}\x{97FD}\x{97FE}\x{97FF}' - . '\x{9800}\x{9801}\x{9802}\x{9803}\x{9804}\x{9805}\x{9806}\x{9807}\x{9808}' - . '\x{9809}\x{980A}\x{980B}\x{980C}\x{980D}\x{980E}\x{980F}\x{9810}\x{9811}' - . '\x{9812}\x{9813}\x{9814}\x{9815}\x{9816}\x{9817}\x{9818}\x{9819}\x{981A}' - . '\x{981B}\x{981C}\x{981D}\x{981E}\x{9820}\x{9821}\x{9822}\x{9823}\x{9824}' - . '\x{9826}\x{9827}\x{9828}\x{9829}\x{982B}\x{982D}\x{982E}\x{982F}\x{9830}' - . '\x{9831}\x{9832}\x{9834}\x{9835}\x{9836}\x{9837}\x{9838}\x{9839}\x{983B}' - . '\x{983C}\x{983D}\x{983F}\x{9840}\x{9841}\x{9843}\x{9844}\x{9845}\x{9846}' - . '\x{9848}\x{9849}\x{984A}\x{984C}\x{984D}\x{984E}\x{984F}\x{9850}\x{9851}' - . '\x{9852}\x{9853}\x{9854}\x{9855}\x{9857}\x{9858}\x{9859}\x{985A}\x{985B}' - . '\x{985C}\x{985D}\x{985E}\x{985F}\x{9860}\x{9861}\x{9862}\x{9863}\x{9864}' - . '\x{9865}\x{9867}\x{9869}\x{986A}\x{986B}\x{986C}\x{986D}\x{986E}\x{986F}' - . '\x{9870}\x{9871}\x{9872}\x{9873}\x{9874}\x{9875}\x{9876}\x{9877}\x{9878}' - . '\x{9879}\x{987A}\x{987B}\x{987C}\x{987D}\x{987E}\x{987F}\x{9880}\x{9881}' - . '\x{9882}\x{9883}\x{9884}\x{9885}\x{9886}\x{9887}\x{9888}\x{9889}\x{988A}' - . '\x{988B}\x{988C}\x{988D}\x{988E}\x{988F}\x{9890}\x{9891}\x{9892}\x{9893}' - . '\x{9894}\x{9895}\x{9896}\x{9897}\x{9898}\x{9899}\x{989A}\x{989B}\x{989C}' - . '\x{989D}\x{989E}\x{989F}\x{98A0}\x{98A1}\x{98A2}\x{98A3}\x{98A4}\x{98A5}' - . '\x{98A6}\x{98A7}\x{98A8}\x{98A9}\x{98AA}\x{98AB}\x{98AC}\x{98AD}\x{98AE}' - . '\x{98AF}\x{98B0}\x{98B1}\x{98B2}\x{98B3}\x{98B4}\x{98B5}\x{98B6}\x{98B8}' - . '\x{98B9}\x{98BA}\x{98BB}\x{98BC}\x{98BD}\x{98BE}\x{98BF}\x{98C0}\x{98C1}' - . '\x{98C2}\x{98C3}\x{98C4}\x{98C5}\x{98C6}\x{98C8}\x{98C9}\x{98CB}\x{98CC}' - . '\x{98CD}\x{98CE}\x{98CF}\x{98D0}\x{98D1}\x{98D2}\x{98D3}\x{98D4}\x{98D5}' - . '\x{98D6}\x{98D7}\x{98D8}\x{98D9}\x{98DA}\x{98DB}\x{98DC}\x{98DD}\x{98DE}' - . '\x{98DF}\x{98E0}\x{98E2}\x{98E3}\x{98E5}\x{98E6}\x{98E7}\x{98E8}\x{98E9}' - . '\x{98EA}\x{98EB}\x{98ED}\x{98EF}\x{98F0}\x{98F2}\x{98F3}\x{98F4}\x{98F5}' - . '\x{98F6}\x{98F7}\x{98F9}\x{98FA}\x{98FC}\x{98FD}\x{98FE}\x{98FF}\x{9900}' - . '\x{9901}\x{9902}\x{9903}\x{9904}\x{9905}\x{9906}\x{9907}\x{9908}\x{9909}' - . '\x{990A}\x{990B}\x{990C}\x{990D}\x{990E}\x{990F}\x{9910}\x{9911}\x{9912}' - . '\x{9913}\x{9914}\x{9915}\x{9916}\x{9917}\x{9918}\x{991A}\x{991B}\x{991C}' - . '\x{991D}\x{991E}\x{991F}\x{9920}\x{9921}\x{9922}\x{9923}\x{9924}\x{9925}' - . '\x{9926}\x{9927}\x{9928}\x{9929}\x{992A}\x{992B}\x{992C}\x{992D}\x{992E}' - . '\x{992F}\x{9930}\x{9931}\x{9932}\x{9933}\x{9934}\x{9935}\x{9936}\x{9937}' - . '\x{9938}\x{9939}\x{993A}\x{993C}\x{993D}\x{993E}\x{993F}\x{9940}\x{9941}' - . '\x{9942}\x{9943}\x{9945}\x{9946}\x{9947}\x{9948}\x{9949}\x{994A}\x{994B}' - . '\x{994C}\x{994E}\x{994F}\x{9950}\x{9951}\x{9952}\x{9953}\x{9954}\x{9955}' - . '\x{9956}\x{9957}\x{9958}\x{9959}\x{995B}\x{995C}\x{995E}\x{995F}\x{9960}' - . '\x{9961}\x{9962}\x{9963}\x{9964}\x{9965}\x{9966}\x{9967}\x{9968}\x{9969}' - . '\x{996A}\x{996B}\x{996C}\x{996D}\x{996E}\x{996F}\x{9970}\x{9971}\x{9972}' - . '\x{9973}\x{9974}\x{9975}\x{9976}\x{9977}\x{9978}\x{9979}\x{997A}\x{997B}' - . '\x{997C}\x{997D}\x{997E}\x{997F}\x{9980}\x{9981}\x{9982}\x{9983}\x{9984}' - . '\x{9985}\x{9986}\x{9987}\x{9988}\x{9989}\x{998A}\x{998B}\x{998C}\x{998D}' - . '\x{998E}\x{998F}\x{9990}\x{9991}\x{9992}\x{9993}\x{9994}\x{9995}\x{9996}' - . '\x{9997}\x{9998}\x{9999}\x{999A}\x{999B}\x{999C}\x{999D}\x{999E}\x{999F}' - . '\x{99A0}\x{99A1}\x{99A2}\x{99A3}\x{99A4}\x{99A5}\x{99A6}\x{99A7}\x{99A8}' - . '\x{99A9}\x{99AA}\x{99AB}\x{99AC}\x{99AD}\x{99AE}\x{99AF}\x{99B0}\x{99B1}' - . '\x{99B2}\x{99B3}\x{99B4}\x{99B5}\x{99B6}\x{99B7}\x{99B8}\x{99B9}\x{99BA}' - . '\x{99BB}\x{99BC}\x{99BD}\x{99BE}\x{99C0}\x{99C1}\x{99C2}\x{99C3}\x{99C4}' - . '\x{99C6}\x{99C7}\x{99C8}\x{99C9}\x{99CA}\x{99CB}\x{99CC}\x{99CD}\x{99CE}' - . '\x{99CF}\x{99D0}\x{99D1}\x{99D2}\x{99D3}\x{99D4}\x{99D5}\x{99D6}\x{99D7}' - . '\x{99D8}\x{99D9}\x{99DA}\x{99DB}\x{99DC}\x{99DD}\x{99DE}\x{99DF}\x{99E1}' - . '\x{99E2}\x{99E3}\x{99E4}\x{99E5}\x{99E7}\x{99E8}\x{99E9}\x{99EA}\x{99EC}' - . '\x{99ED}\x{99EE}\x{99EF}\x{99F0}\x{99F1}\x{99F2}\x{99F3}\x{99F4}\x{99F6}' - . '\x{99F7}\x{99F8}\x{99F9}\x{99FA}\x{99FB}\x{99FC}\x{99FD}\x{99FE}\x{99FF}' - . '\x{9A00}\x{9A01}\x{9A02}\x{9A03}\x{9A04}\x{9A05}\x{9A06}\x{9A07}\x{9A08}' - . '\x{9A09}\x{9A0A}\x{9A0B}\x{9A0C}\x{9A0D}\x{9A0E}\x{9A0F}\x{9A11}\x{9A14}' - . '\x{9A15}\x{9A16}\x{9A19}\x{9A1A}\x{9A1B}\x{9A1C}\x{9A1D}\x{9A1E}\x{9A1F}' - . '\x{9A20}\x{9A21}\x{9A22}\x{9A23}\x{9A24}\x{9A25}\x{9A26}\x{9A27}\x{9A29}' - . '\x{9A2A}\x{9A2B}\x{9A2C}\x{9A2D}\x{9A2E}\x{9A2F}\x{9A30}\x{9A31}\x{9A32}' - . '\x{9A33}\x{9A34}\x{9A35}\x{9A36}\x{9A37}\x{9A38}\x{9A39}\x{9A3A}\x{9A3C}' - . '\x{9A3D}\x{9A3E}\x{9A3F}\x{9A40}\x{9A41}\x{9A42}\x{9A43}\x{9A44}\x{9A45}' - . '\x{9A46}\x{9A47}\x{9A48}\x{9A49}\x{9A4A}\x{9A4B}\x{9A4C}\x{9A4D}\x{9A4E}' - . '\x{9A4F}\x{9A50}\x{9A52}\x{9A53}\x{9A54}\x{9A55}\x{9A56}\x{9A57}\x{9A59}' - . '\x{9A5A}\x{9A5B}\x{9A5C}\x{9A5E}\x{9A5F}\x{9A60}\x{9A61}\x{9A62}\x{9A64}' - . '\x{9A65}\x{9A66}\x{9A67}\x{9A68}\x{9A69}\x{9A6A}\x{9A6B}\x{9A6C}\x{9A6D}' - . '\x{9A6E}\x{9A6F}\x{9A70}\x{9A71}\x{9A72}\x{9A73}\x{9A74}\x{9A75}\x{9A76}' - . '\x{9A77}\x{9A78}\x{9A79}\x{9A7A}\x{9A7B}\x{9A7C}\x{9A7D}\x{9A7E}\x{9A7F}' - . '\x{9A80}\x{9A81}\x{9A82}\x{9A83}\x{9A84}\x{9A85}\x{9A86}\x{9A87}\x{9A88}' - . '\x{9A89}\x{9A8A}\x{9A8B}\x{9A8C}\x{9A8D}\x{9A8E}\x{9A8F}\x{9A90}\x{9A91}' - . '\x{9A92}\x{9A93}\x{9A94}\x{9A95}\x{9A96}\x{9A97}\x{9A98}\x{9A99}\x{9A9A}' - . '\x{9A9B}\x{9A9C}\x{9A9D}\x{9A9E}\x{9A9F}\x{9AA0}\x{9AA1}\x{9AA2}\x{9AA3}' - . '\x{9AA4}\x{9AA5}\x{9AA6}\x{9AA7}\x{9AA8}\x{9AAA}\x{9AAB}\x{9AAC}\x{9AAD}' - . '\x{9AAE}\x{9AAF}\x{9AB0}\x{9AB1}\x{9AB2}\x{9AB3}\x{9AB4}\x{9AB5}\x{9AB6}' - . '\x{9AB7}\x{9AB8}\x{9AB9}\x{9ABA}\x{9ABB}\x{9ABC}\x{9ABE}\x{9ABF}\x{9AC0}' - . '\x{9AC1}\x{9AC2}\x{9AC3}\x{9AC4}\x{9AC5}\x{9AC6}\x{9AC7}\x{9AC9}\x{9ACA}' - . '\x{9ACB}\x{9ACC}\x{9ACD}\x{9ACE}\x{9ACF}\x{9AD0}\x{9AD1}\x{9AD2}\x{9AD3}' - . '\x{9AD4}\x{9AD5}\x{9AD6}\x{9AD8}\x{9AD9}\x{9ADA}\x{9ADB}\x{9ADC}\x{9ADD}' - . '\x{9ADE}\x{9ADF}\x{9AE1}\x{9AE2}\x{9AE3}\x{9AE5}\x{9AE6}\x{9AE7}\x{9AEA}' - . '\x{9AEB}\x{9AEC}\x{9AED}\x{9AEE}\x{9AEF}\x{9AF1}\x{9AF2}\x{9AF3}\x{9AF4}' - . '\x{9AF5}\x{9AF6}\x{9AF7}\x{9AF8}\x{9AF9}\x{9AFA}\x{9AFB}\x{9AFC}\x{9AFD}' - . '\x{9AFE}\x{9AFF}\x{9B01}\x{9B03}\x{9B04}\x{9B05}\x{9B06}\x{9B07}\x{9B08}' - . '\x{9B0A}\x{9B0B}\x{9B0C}\x{9B0D}\x{9B0E}\x{9B0F}\x{9B10}\x{9B11}\x{9B12}' - . '\x{9B13}\x{9B15}\x{9B16}\x{9B17}\x{9B18}\x{9B19}\x{9B1A}\x{9B1C}\x{9B1D}' - . '\x{9B1E}\x{9B1F}\x{9B20}\x{9B21}\x{9B22}\x{9B23}\x{9B24}\x{9B25}\x{9B26}' - . '\x{9B27}\x{9B28}\x{9B29}\x{9B2A}\x{9B2B}\x{9B2C}\x{9B2D}\x{9B2E}\x{9B2F}' - . '\x{9B30}\x{9B31}\x{9B32}\x{9B33}\x{9B35}\x{9B36}\x{9B37}\x{9B38}\x{9B39}' - . '\x{9B3A}\x{9B3B}\x{9B3C}\x{9B3E}\x{9B3F}\x{9B41}\x{9B42}\x{9B43}\x{9B44}' - . '\x{9B45}\x{9B46}\x{9B47}\x{9B48}\x{9B49}\x{9B4A}\x{9B4B}\x{9B4C}\x{9B4D}' - . '\x{9B4E}\x{9B4F}\x{9B51}\x{9B52}\x{9B53}\x{9B54}\x{9B55}\x{9B56}\x{9B58}' - . '\x{9B59}\x{9B5A}\x{9B5B}\x{9B5C}\x{9B5D}\x{9B5E}\x{9B5F}\x{9B60}\x{9B61}' - . '\x{9B63}\x{9B64}\x{9B65}\x{9B66}\x{9B67}\x{9B68}\x{9B69}\x{9B6A}\x{9B6B}' - . '\x{9B6C}\x{9B6D}\x{9B6E}\x{9B6F}\x{9B70}\x{9B71}\x{9B73}\x{9B74}\x{9B75}' - . '\x{9B76}\x{9B77}\x{9B78}\x{9B79}\x{9B7A}\x{9B7B}\x{9B7C}\x{9B7D}\x{9B7E}' - . '\x{9B7F}\x{9B80}\x{9B81}\x{9B82}\x{9B83}\x{9B84}\x{9B85}\x{9B86}\x{9B87}' - . '\x{9B88}\x{9B8A}\x{9B8B}\x{9B8D}\x{9B8E}\x{9B8F}\x{9B90}\x{9B91}\x{9B92}' - . '\x{9B93}\x{9B94}\x{9B95}\x{9B96}\x{9B97}\x{9B98}\x{9B9A}\x{9B9B}\x{9B9C}' - . '\x{9B9D}\x{9B9E}\x{9B9F}\x{9BA0}\x{9BA1}\x{9BA2}\x{9BA3}\x{9BA4}\x{9BA5}' - . '\x{9BA6}\x{9BA7}\x{9BA8}\x{9BA9}\x{9BAA}\x{9BAB}\x{9BAC}\x{9BAD}\x{9BAE}' - . '\x{9BAF}\x{9BB0}\x{9BB1}\x{9BB2}\x{9BB3}\x{9BB4}\x{9BB5}\x{9BB6}\x{9BB7}' - . '\x{9BB8}\x{9BB9}\x{9BBA}\x{9BBB}\x{9BBC}\x{9BBD}\x{9BBE}\x{9BBF}\x{9BC0}' - . '\x{9BC1}\x{9BC3}\x{9BC4}\x{9BC5}\x{9BC6}\x{9BC7}\x{9BC8}\x{9BC9}\x{9BCA}' - . '\x{9BCB}\x{9BCC}\x{9BCD}\x{9BCE}\x{9BCF}\x{9BD0}\x{9BD1}\x{9BD2}\x{9BD3}' - . '\x{9BD4}\x{9BD5}\x{9BD6}\x{9BD7}\x{9BD8}\x{9BD9}\x{9BDA}\x{9BDB}\x{9BDC}' - . '\x{9BDD}\x{9BDE}\x{9BDF}\x{9BE0}\x{9BE1}\x{9BE2}\x{9BE3}\x{9BE4}\x{9BE5}' - . '\x{9BE6}\x{9BE7}\x{9BE8}\x{9BE9}\x{9BEA}\x{9BEB}\x{9BEC}\x{9BED}\x{9BEE}' - . '\x{9BEF}\x{9BF0}\x{9BF1}\x{9BF2}\x{9BF3}\x{9BF4}\x{9BF5}\x{9BF7}\x{9BF8}' - . '\x{9BF9}\x{9BFA}\x{9BFB}\x{9BFC}\x{9BFD}\x{9BFE}\x{9BFF}\x{9C02}\x{9C05}' - . '\x{9C06}\x{9C07}\x{9C08}\x{9C09}\x{9C0A}\x{9C0B}\x{9C0C}\x{9C0D}\x{9C0E}' - . '\x{9C0F}\x{9C10}\x{9C11}\x{9C12}\x{9C13}\x{9C14}\x{9C15}\x{9C16}\x{9C17}' - . '\x{9C18}\x{9C19}\x{9C1A}\x{9C1B}\x{9C1C}\x{9C1D}\x{9C1E}\x{9C1F}\x{9C20}' - . '\x{9C21}\x{9C22}\x{9C23}\x{9C24}\x{9C25}\x{9C26}\x{9C27}\x{9C28}\x{9C29}' - . '\x{9C2A}\x{9C2B}\x{9C2C}\x{9C2D}\x{9C2F}\x{9C30}\x{9C31}\x{9C32}\x{9C33}' - . '\x{9C34}\x{9C35}\x{9C36}\x{9C37}\x{9C38}\x{9C39}\x{9C3A}\x{9C3B}\x{9C3C}' - . '\x{9C3D}\x{9C3E}\x{9C3F}\x{9C40}\x{9C41}\x{9C43}\x{9C44}\x{9C45}\x{9C46}' - . '\x{9C47}\x{9C48}\x{9C49}\x{9C4A}\x{9C4B}\x{9C4C}\x{9C4D}\x{9C4E}\x{9C50}' - . '\x{9C52}\x{9C53}\x{9C54}\x{9C55}\x{9C56}\x{9C57}\x{9C58}\x{9C59}\x{9C5A}' - . '\x{9C5B}\x{9C5C}\x{9C5D}\x{9C5E}\x{9C5F}\x{9C60}\x{9C62}\x{9C63}\x{9C65}' - . '\x{9C66}\x{9C67}\x{9C68}\x{9C69}\x{9C6A}\x{9C6B}\x{9C6C}\x{9C6D}\x{9C6E}' - . '\x{9C6F}\x{9C70}\x{9C71}\x{9C72}\x{9C73}\x{9C74}\x{9C75}\x{9C77}\x{9C78}' - . '\x{9C79}\x{9C7A}\x{9C7C}\x{9C7D}\x{9C7E}\x{9C7F}\x{9C80}\x{9C81}\x{9C82}' - . '\x{9C83}\x{9C84}\x{9C85}\x{9C86}\x{9C87}\x{9C88}\x{9C89}\x{9C8A}\x{9C8B}' - . '\x{9C8C}\x{9C8D}\x{9C8E}\x{9C8F}\x{9C90}\x{9C91}\x{9C92}\x{9C93}\x{9C94}' - . '\x{9C95}\x{9C96}\x{9C97}\x{9C98}\x{9C99}\x{9C9A}\x{9C9B}\x{9C9C}\x{9C9D}' - . '\x{9C9E}\x{9C9F}\x{9CA0}\x{9CA1}\x{9CA2}\x{9CA3}\x{9CA4}\x{9CA5}\x{9CA6}' - . '\x{9CA7}\x{9CA8}\x{9CA9}\x{9CAA}\x{9CAB}\x{9CAC}\x{9CAD}\x{9CAE}\x{9CAF}' - . '\x{9CB0}\x{9CB1}\x{9CB2}\x{9CB3}\x{9CB4}\x{9CB5}\x{9CB6}\x{9CB7}\x{9CB8}' - . '\x{9CB9}\x{9CBA}\x{9CBB}\x{9CBC}\x{9CBD}\x{9CBE}\x{9CBF}\x{9CC0}\x{9CC1}' - . '\x{9CC2}\x{9CC3}\x{9CC4}\x{9CC5}\x{9CC6}\x{9CC7}\x{9CC8}\x{9CC9}\x{9CCA}' - . '\x{9CCB}\x{9CCC}\x{9CCD}\x{9CCE}\x{9CCF}\x{9CD0}\x{9CD1}\x{9CD2}\x{9CD3}' - . '\x{9CD4}\x{9CD5}\x{9CD6}\x{9CD7}\x{9CD8}\x{9CD9}\x{9CDA}\x{9CDB}\x{9CDC}' - . '\x{9CDD}\x{9CDE}\x{9CDF}\x{9CE0}\x{9CE1}\x{9CE2}\x{9CE3}\x{9CE4}\x{9CE5}' - . '\x{9CE6}\x{9CE7}\x{9CE8}\x{9CE9}\x{9CEA}\x{9CEB}\x{9CEC}\x{9CED}\x{9CEE}' - . '\x{9CEF}\x{9CF0}\x{9CF1}\x{9CF2}\x{9CF3}\x{9CF4}\x{9CF5}\x{9CF6}\x{9CF7}' - . '\x{9CF8}\x{9CF9}\x{9CFA}\x{9CFB}\x{9CFC}\x{9CFD}\x{9CFE}\x{9CFF}\x{9D00}' - . '\x{9D01}\x{9D02}\x{9D03}\x{9D04}\x{9D05}\x{9D06}\x{9D07}\x{9D08}\x{9D09}' - . '\x{9D0A}\x{9D0B}\x{9D0F}\x{9D10}\x{9D12}\x{9D13}\x{9D14}\x{9D15}\x{9D16}' - . '\x{9D17}\x{9D18}\x{9D19}\x{9D1A}\x{9D1B}\x{9D1C}\x{9D1D}\x{9D1E}\x{9D1F}' - . '\x{9D20}\x{9D21}\x{9D22}\x{9D23}\x{9D24}\x{9D25}\x{9D26}\x{9D28}\x{9D29}' - . '\x{9D2B}\x{9D2D}\x{9D2E}\x{9D2F}\x{9D30}\x{9D31}\x{9D32}\x{9D33}\x{9D34}' - . '\x{9D36}\x{9D37}\x{9D38}\x{9D39}\x{9D3A}\x{9D3B}\x{9D3D}\x{9D3E}\x{9D3F}' - . '\x{9D40}\x{9D41}\x{9D42}\x{9D43}\x{9D45}\x{9D46}\x{9D47}\x{9D48}\x{9D49}' - . '\x{9D4A}\x{9D4B}\x{9D4C}\x{9D4D}\x{9D4E}\x{9D4F}\x{9D50}\x{9D51}\x{9D52}' - . '\x{9D53}\x{9D54}\x{9D55}\x{9D56}\x{9D57}\x{9D58}\x{9D59}\x{9D5A}\x{9D5B}' - . '\x{9D5C}\x{9D5D}\x{9D5E}\x{9D5F}\x{9D60}\x{9D61}\x{9D62}\x{9D63}\x{9D64}' - . '\x{9D65}\x{9D66}\x{9D67}\x{9D68}\x{9D69}\x{9D6A}\x{9D6B}\x{9D6C}\x{9D6E}' - . '\x{9D6F}\x{9D70}\x{9D71}\x{9D72}\x{9D73}\x{9D74}\x{9D75}\x{9D76}\x{9D77}' - . '\x{9D78}\x{9D79}\x{9D7A}\x{9D7B}\x{9D7C}\x{9D7D}\x{9D7E}\x{9D7F}\x{9D80}' - . '\x{9D81}\x{9D82}\x{9D83}\x{9D84}\x{9D85}\x{9D86}\x{9D87}\x{9D88}\x{9D89}' - . '\x{9D8A}\x{9D8B}\x{9D8C}\x{9D8D}\x{9D8E}\x{9D90}\x{9D91}\x{9D92}\x{9D93}' - . '\x{9D94}\x{9D96}\x{9D97}\x{9D98}\x{9D99}\x{9D9A}\x{9D9B}\x{9D9C}\x{9D9D}' - . '\x{9D9E}\x{9D9F}\x{9DA0}\x{9DA1}\x{9DA2}\x{9DA3}\x{9DA4}\x{9DA5}\x{9DA6}' - . '\x{9DA7}\x{9DA8}\x{9DA9}\x{9DAA}\x{9DAB}\x{9DAC}\x{9DAD}\x{9DAF}\x{9DB0}' - . '\x{9DB1}\x{9DB2}\x{9DB3}\x{9DB4}\x{9DB5}\x{9DB6}\x{9DB7}\x{9DB8}\x{9DB9}' - . '\x{9DBA}\x{9DBB}\x{9DBC}\x{9DBE}\x{9DBF}\x{9DC1}\x{9DC2}\x{9DC3}\x{9DC4}' - . '\x{9DC5}\x{9DC7}\x{9DC8}\x{9DC9}\x{9DCA}\x{9DCB}\x{9DCC}\x{9DCD}\x{9DCE}' - . '\x{9DCF}\x{9DD0}\x{9DD1}\x{9DD2}\x{9DD3}\x{9DD4}\x{9DD5}\x{9DD6}\x{9DD7}' - . '\x{9DD8}\x{9DD9}\x{9DDA}\x{9DDB}\x{9DDC}\x{9DDD}\x{9DDE}\x{9DDF}\x{9DE0}' - . '\x{9DE1}\x{9DE2}\x{9DE3}\x{9DE4}\x{9DE5}\x{9DE6}\x{9DE7}\x{9DE8}\x{9DE9}' - . '\x{9DEB}\x{9DEC}\x{9DED}\x{9DEE}\x{9DEF}\x{9DF0}\x{9DF1}\x{9DF2}\x{9DF3}' - . '\x{9DF4}\x{9DF5}\x{9DF6}\x{9DF7}\x{9DF8}\x{9DF9}\x{9DFA}\x{9DFB}\x{9DFD}' - . '\x{9DFE}\x{9DFF}\x{9E00}\x{9E01}\x{9E02}\x{9E03}\x{9E04}\x{9E05}\x{9E06}' - . '\x{9E07}\x{9E08}\x{9E09}\x{9E0A}\x{9E0B}\x{9E0C}\x{9E0D}\x{9E0F}\x{9E10}' - . '\x{9E11}\x{9E12}\x{9E13}\x{9E14}\x{9E15}\x{9E17}\x{9E18}\x{9E19}\x{9E1A}' - . '\x{9E1B}\x{9E1D}\x{9E1E}\x{9E1F}\x{9E20}\x{9E21}\x{9E22}\x{9E23}\x{9E24}' - . '\x{9E25}\x{9E26}\x{9E27}\x{9E28}\x{9E29}\x{9E2A}\x{9E2B}\x{9E2C}\x{9E2D}' - . '\x{9E2E}\x{9E2F}\x{9E30}\x{9E31}\x{9E32}\x{9E33}\x{9E34}\x{9E35}\x{9E36}' - . '\x{9E37}\x{9E38}\x{9E39}\x{9E3A}\x{9E3B}\x{9E3C}\x{9E3D}\x{9E3E}\x{9E3F}' - . '\x{9E40}\x{9E41}\x{9E42}\x{9E43}\x{9E44}\x{9E45}\x{9E46}\x{9E47}\x{9E48}' - . '\x{9E49}\x{9E4A}\x{9E4B}\x{9E4C}\x{9E4D}\x{9E4E}\x{9E4F}\x{9E50}\x{9E51}' - . '\x{9E52}\x{9E53}\x{9E54}\x{9E55}\x{9E56}\x{9E57}\x{9E58}\x{9E59}\x{9E5A}' - . '\x{9E5B}\x{9E5C}\x{9E5D}\x{9E5E}\x{9E5F}\x{9E60}\x{9E61}\x{9E62}\x{9E63}' - . '\x{9E64}\x{9E65}\x{9E66}\x{9E67}\x{9E68}\x{9E69}\x{9E6A}\x{9E6B}\x{9E6C}' - . '\x{9E6D}\x{9E6E}\x{9E6F}\x{9E70}\x{9E71}\x{9E72}\x{9E73}\x{9E74}\x{9E75}' - . '\x{9E76}\x{9E77}\x{9E79}\x{9E7A}\x{9E7C}\x{9E7D}\x{9E7E}\x{9E7F}\x{9E80}' - . '\x{9E81}\x{9E82}\x{9E83}\x{9E84}\x{9E85}\x{9E86}\x{9E87}\x{9E88}\x{9E89}' - . '\x{9E8A}\x{9E8B}\x{9E8C}\x{9E8D}\x{9E8E}\x{9E91}\x{9E92}\x{9E93}\x{9E94}' - . '\x{9E96}\x{9E97}\x{9E99}\x{9E9A}\x{9E9B}\x{9E9C}\x{9E9D}\x{9E9F}\x{9EA0}' - . '\x{9EA1}\x{9EA3}\x{9EA4}\x{9EA5}\x{9EA6}\x{9EA7}\x{9EA8}\x{9EA9}\x{9EAA}' - . '\x{9EAD}\x{9EAE}\x{9EAF}\x{9EB0}\x{9EB2}\x{9EB3}\x{9EB4}\x{9EB5}\x{9EB6}' - . '\x{9EB7}\x{9EB8}\x{9EBB}\x{9EBC}\x{9EBD}\x{9EBE}\x{9EBF}\x{9EC0}\x{9EC1}' - . '\x{9EC2}\x{9EC3}\x{9EC4}\x{9EC5}\x{9EC6}\x{9EC7}\x{9EC8}\x{9EC9}\x{9ECA}' - . '\x{9ECB}\x{9ECC}\x{9ECD}\x{9ECE}\x{9ECF}\x{9ED0}\x{9ED1}\x{9ED2}\x{9ED3}' - . '\x{9ED4}\x{9ED5}\x{9ED6}\x{9ED7}\x{9ED8}\x{9ED9}\x{9EDA}\x{9EDB}\x{9EDC}' - . '\x{9EDD}\x{9EDE}\x{9EDF}\x{9EE0}\x{9EE1}\x{9EE2}\x{9EE3}\x{9EE4}\x{9EE5}' - . '\x{9EE6}\x{9EE7}\x{9EE8}\x{9EE9}\x{9EEA}\x{9EEB}\x{9EED}\x{9EEE}\x{9EEF}' - . '\x{9EF0}\x{9EF2}\x{9EF3}\x{9EF4}\x{9EF5}\x{9EF6}\x{9EF7}\x{9EF8}\x{9EF9}' - . '\x{9EFA}\x{9EFB}\x{9EFC}\x{9EFD}\x{9EFE}\x{9EFF}\x{9F00}\x{9F01}\x{9F02}' - . '\x{9F04}\x{9F05}\x{9F06}\x{9F07}\x{9F08}\x{9F09}\x{9F0A}\x{9F0B}\x{9F0C}' - . '\x{9F0D}\x{9F0E}\x{9F0F}\x{9F10}\x{9F12}\x{9F13}\x{9F15}\x{9F16}\x{9F17}' - . '\x{9F18}\x{9F19}\x{9F1A}\x{9F1B}\x{9F1C}\x{9F1D}\x{9F1E}\x{9F1F}\x{9F20}' - . '\x{9F22}\x{9F23}\x{9F24}\x{9F25}\x{9F27}\x{9F28}\x{9F29}\x{9F2A}\x{9F2B}' - . '\x{9F2C}\x{9F2D}\x{9F2E}\x{9F2F}\x{9F30}\x{9F31}\x{9F32}\x{9F33}\x{9F34}' - . '\x{9F35}\x{9F36}\x{9F37}\x{9F38}\x{9F39}\x{9F3A}\x{9F3B}\x{9F3C}\x{9F3D}' - . '\x{9F3E}\x{9F3F}\x{9F40}\x{9F41}\x{9F42}\x{9F43}\x{9F44}\x{9F46}\x{9F47}' - . '\x{9F48}\x{9F49}\x{9F4A}\x{9F4B}\x{9F4C}\x{9F4D}\x{9F4E}\x{9F4F}\x{9F50}' - . '\x{9F51}\x{9F52}\x{9F54}\x{9F55}\x{9F56}\x{9F57}\x{9F58}\x{9F59}\x{9F5A}' - . '\x{9F5B}\x{9F5C}\x{9F5D}\x{9F5E}\x{9F5F}\x{9F60}\x{9F61}\x{9F63}\x{9F64}' - . '\x{9F65}\x{9F66}\x{9F67}\x{9F68}\x{9F69}\x{9F6A}\x{9F6B}\x{9F6C}\x{9F6E}' - . '\x{9F6F}\x{9F70}\x{9F71}\x{9F72}\x{9F73}\x{9F74}\x{9F75}\x{9F76}\x{9F77}' - . '\x{9F78}\x{9F79}\x{9F7A}\x{9F7B}\x{9F7C}\x{9F7D}\x{9F7E}\x{9F7F}\x{9F80}' - . '\x{9F81}\x{9F82}\x{9F83}\x{9F84}\x{9F85}\x{9F86}\x{9F87}\x{9F88}\x{9F89}' - . '\x{9F8A}\x{9F8B}\x{9F8C}\x{9F8D}\x{9F8E}\x{9F8F}\x{9F90}\x{9F91}\x{9F92}' - . '\x{9F93}\x{9F94}\x{9F95}\x{9F96}\x{9F97}\x{9F98}\x{9F99}\x{9F9A}\x{9F9B}' - . '\x{9F9C}\x{9F9D}\x{9F9E}\x{9F9F}\x{9FA0}\x{9FA2}\x{9FA4}\x{9FA5}]{1,20}$/iu', -]; diff --git a/lib/laminas/laminas-validator/src/Hostname/Cn.php b/lib/laminas/laminas-validator/src/Hostname/Cn.php deleted file mode 100644 index d280764b0..000000000 --- a/lib/laminas/laminas-validator/src/Hostname/Cn.php +++ /dev/null @@ -1,2179 +0,0 @@ -<?php // phpcs:disable PSR12.Files.FileHeader.IncorrectOrder - -namespace Laminas\Validator\Hostname; - -/** - * Resource file for chinese idn validation - */ - -return [ - 1 => '/^[\x{002d}0-9a-z\x{3447}\x{3473}\x{359E}\x{360E}\x{361A}\x{3918}\x{396E}\x{39CF}\x{39D0}' - . '\x{39DF}\x{3A73}\x{3B4E}\x{3C6E}\x{3CE0}\x{4056}\x{415F}\x{4337}\x{43AC}' - . '\x{43B1}\x{43DD}\x{44D6}\x{464C}\x{4661}\x{4723}\x{4729}\x{477C}\x{478D}' - . '\x{4947}\x{497A}\x{497D}\x{4982}\x{4983}\x{4985}\x{4986}\x{499B}\x{499F}' - . '\x{49B6}\x{49B7}\x{4C77}\x{4C9F}\x{4CA0}\x{4CA1}\x{4CA2}\x{4CA3}\x{4D13}' - . '\x{4D14}\x{4D15}\x{4D16}\x{4D17}\x{4D18}\x{4D19}\x{4DAE}\x{4E00}\x{4E01}' - . '\x{4E02}\x{4E03}\x{4E04}\x{4E05}\x{4E06}\x{4E07}\x{4E08}\x{4E09}\x{4E0A}' - . '\x{4E0B}\x{4E0C}\x{4E0D}\x{4E0E}\x{4E0F}\x{4E10}\x{4E11}\x{4E13}\x{4E14}' - . '\x{4E15}\x{4E16}\x{4E17}\x{4E18}\x{4E19}\x{4E1A}\x{4E1B}\x{4E1C}\x{4E1D}' - . '\x{4E1E}\x{4E1F}\x{4E20}\x{4E21}\x{4E22}\x{4E23}\x{4E24}\x{4E25}\x{4E26}' - . '\x{4E27}\x{4E28}\x{4E2A}\x{4E2B}\x{4E2C}\x{4E2D}\x{4E2E}\x{4E2F}\x{4E30}' - . '\x{4E31}\x{4E32}\x{4E33}\x{4E34}\x{4E35}\x{4E36}\x{4E37}\x{4E38}\x{4E39}' - . '\x{4E3A}\x{4E3B}\x{4E3C}\x{4E3D}\x{4E3E}\x{4E3F}\x{4E40}\x{4E41}\x{4E42}' - . '\x{4E43}\x{4E44}\x{4E45}\x{4E46}\x{4E47}\x{4E48}\x{4E49}\x{4E4A}\x{4E4B}' - . '\x{4E4C}\x{4E4D}\x{4E4E}\x{4E4F}\x{4E50}\x{4E51}\x{4E52}\x{4E53}\x{4E54}' - . '\x{4E56}\x{4E57}\x{4E58}\x{4E59}\x{4E5A}\x{4E5B}\x{4E5C}\x{4E5D}\x{4E5E}' - . '\x{4E5F}\x{4E60}\x{4E61}\x{4E62}\x{4E63}\x{4E64}\x{4E65}\x{4E66}\x{4E67}' - . '\x{4E69}\x{4E6A}\x{4E6B}\x{4E6C}\x{4E6D}\x{4E6E}\x{4E6F}\x{4E70}\x{4E71}' - . '\x{4E72}\x{4E73}\x{4E74}\x{4E75}\x{4E76}\x{4E77}\x{4E78}\x{4E7A}\x{4E7B}' - . '\x{4E7C}\x{4E7D}\x{4E7E}\x{4E7F}\x{4E80}\x{4E81}\x{4E82}\x{4E83}\x{4E84}' - . '\x{4E85}\x{4E86}\x{4E87}\x{4E88}\x{4E89}\x{4E8B}\x{4E8C}\x{4E8D}\x{4E8E}' - . '\x{4E8F}\x{4E90}\x{4E91}\x{4E92}\x{4E93}\x{4E94}\x{4E95}\x{4E97}\x{4E98}' - . '\x{4E99}\x{4E9A}\x{4E9B}\x{4E9C}\x{4E9D}\x{4E9E}\x{4E9F}\x{4EA0}\x{4EA1}' - . '\x{4EA2}\x{4EA4}\x{4EA5}\x{4EA6}\x{4EA7}\x{4EA8}\x{4EA9}\x{4EAA}\x{4EAB}' - . '\x{4EAC}\x{4EAD}\x{4EAE}\x{4EAF}\x{4EB0}\x{4EB1}\x{4EB2}\x{4EB3}\x{4EB4}' - . '\x{4EB5}\x{4EB6}\x{4EB7}\x{4EB8}\x{4EB9}\x{4EBA}\x{4EBB}\x{4EBD}\x{4EBE}' - . '\x{4EBF}\x{4EC0}\x{4EC1}\x{4EC2}\x{4EC3}\x{4EC4}\x{4EC5}\x{4EC6}\x{4EC7}' - . '\x{4EC8}\x{4EC9}\x{4ECA}\x{4ECB}\x{4ECD}\x{4ECE}\x{4ECF}\x{4ED0}\x{4ED1}' - . '\x{4ED2}\x{4ED3}\x{4ED4}\x{4ED5}\x{4ED6}\x{4ED7}\x{4ED8}\x{4ED9}\x{4EDA}' - . '\x{4EDB}\x{4EDC}\x{4EDD}\x{4EDE}\x{4EDF}\x{4EE0}\x{4EE1}\x{4EE2}\x{4EE3}' - . '\x{4EE4}\x{4EE5}\x{4EE6}\x{4EE8}\x{4EE9}\x{4EEA}\x{4EEB}\x{4EEC}\x{4EEF}' - . '\x{4EF0}\x{4EF1}\x{4EF2}\x{4EF3}\x{4EF4}\x{4EF5}\x{4EF6}\x{4EF7}\x{4EFB}' - . '\x{4EFD}\x{4EFF}\x{4F00}\x{4F01}\x{4F02}\x{4F03}\x{4F04}\x{4F05}\x{4F06}' - . '\x{4F08}\x{4F09}\x{4F0A}\x{4F0B}\x{4F0C}\x{4F0D}\x{4F0E}\x{4F0F}\x{4F10}' - . '\x{4F11}\x{4F12}\x{4F13}\x{4F14}\x{4F15}\x{4F17}\x{4F18}\x{4F19}\x{4F1A}' - . '\x{4F1B}\x{4F1C}\x{4F1D}\x{4F1E}\x{4F1F}\x{4F20}\x{4F21}\x{4F22}\x{4F23}' - . '\x{4F24}\x{4F25}\x{4F26}\x{4F27}\x{4F29}\x{4F2A}\x{4F2B}\x{4F2C}\x{4F2D}' - . '\x{4F2E}\x{4F2F}\x{4F30}\x{4F32}\x{4F33}\x{4F34}\x{4F36}\x{4F38}\x{4F39}' - . '\x{4F3A}\x{4F3B}\x{4F3C}\x{4F3D}\x{4F3E}\x{4F3F}\x{4F41}\x{4F42}\x{4F43}' - . '\x{4F45}\x{4F46}\x{4F47}\x{4F48}\x{4F49}\x{4F4A}\x{4F4B}\x{4F4C}\x{4F4D}' - . '\x{4F4E}\x{4F4F}\x{4F50}\x{4F51}\x{4F52}\x{4F53}\x{4F54}\x{4F55}\x{4F56}' - . '\x{4F57}\x{4F58}\x{4F59}\x{4F5A}\x{4F5B}\x{4F5C}\x{4F5D}\x{4F5E}\x{4F5F}' - . '\x{4F60}\x{4F61}\x{4F62}\x{4F63}\x{4F64}\x{4F65}\x{4F66}\x{4F67}\x{4F68}' - . '\x{4F69}\x{4F6A}\x{4F6B}\x{4F6C}\x{4F6D}\x{4F6E}\x{4F6F}\x{4F70}\x{4F72}' - . '\x{4F73}\x{4F74}\x{4F75}\x{4F76}\x{4F77}\x{4F78}\x{4F79}\x{4F7A}\x{4F7B}' - . '\x{4F7C}\x{4F7D}\x{4F7E}\x{4F7F}\x{4F80}\x{4F81}\x{4F82}\x{4F83}\x{4F84}' - . '\x{4F85}\x{4F86}\x{4F87}\x{4F88}\x{4F89}\x{4F8A}\x{4F8B}\x{4F8D}\x{4F8F}' - . '\x{4F90}\x{4F91}\x{4F92}\x{4F93}\x{4F94}\x{4F95}\x{4F96}\x{4F97}\x{4F98}' - . '\x{4F99}\x{4F9A}\x{4F9B}\x{4F9C}\x{4F9D}\x{4F9E}\x{4F9F}\x{4FA0}\x{4FA1}' - . '\x{4FA3}\x{4FA4}\x{4FA5}\x{4FA6}\x{4FA7}\x{4FA8}\x{4FA9}\x{4FAA}\x{4FAB}' - . '\x{4FAC}\x{4FAE}\x{4FAF}\x{4FB0}\x{4FB1}\x{4FB2}\x{4FB3}\x{4FB4}\x{4FB5}' - . '\x{4FB6}\x{4FB7}\x{4FB8}\x{4FB9}\x{4FBA}\x{4FBB}\x{4FBC}\x{4FBE}\x{4FBF}' - . '\x{4FC0}\x{4FC1}\x{4FC2}\x{4FC3}\x{4FC4}\x{4FC5}\x{4FC7}\x{4FC9}\x{4FCA}' - . '\x{4FCB}\x{4FCD}\x{4FCE}\x{4FCF}\x{4FD0}\x{4FD1}\x{4FD2}\x{4FD3}\x{4FD4}' - . '\x{4FD5}\x{4FD6}\x{4FD7}\x{4FD8}\x{4FD9}\x{4FDA}\x{4FDB}\x{4FDC}\x{4FDD}' - . '\x{4FDE}\x{4FDF}\x{4FE0}\x{4FE1}\x{4FE3}\x{4FE4}\x{4FE5}\x{4FE6}\x{4FE7}' - . '\x{4FE8}\x{4FE9}\x{4FEA}\x{4FEB}\x{4FEC}\x{4FED}\x{4FEE}\x{4FEF}\x{4FF0}' - . '\x{4FF1}\x{4FF2}\x{4FF3}\x{4FF4}\x{4FF5}\x{4FF6}\x{4FF7}\x{4FF8}\x{4FF9}' - . '\x{4FFA}\x{4FFB}\x{4FFE}\x{4FFF}\x{5000}\x{5001}\x{5002}\x{5003}\x{5004}' - . '\x{5005}\x{5006}\x{5007}\x{5008}\x{5009}\x{500A}\x{500B}\x{500C}\x{500D}' - . '\x{500E}\x{500F}\x{5011}\x{5012}\x{5013}\x{5014}\x{5015}\x{5016}\x{5017}' - . '\x{5018}\x{5019}\x{501A}\x{501B}\x{501C}\x{501D}\x{501E}\x{501F}\x{5020}' - . '\x{5021}\x{5022}\x{5023}\x{5024}\x{5025}\x{5026}\x{5027}\x{5028}\x{5029}' - . '\x{502A}\x{502B}\x{502C}\x{502D}\x{502E}\x{502F}\x{5030}\x{5031}\x{5032}' - . '\x{5033}\x{5035}\x{5036}\x{5037}\x{5039}\x{503A}\x{503B}\x{503C}\x{503E}' - . '\x{503F}\x{5040}\x{5041}\x{5043}\x{5044}\x{5045}\x{5046}\x{5047}\x{5048}' - . '\x{5049}\x{504A}\x{504B}\x{504C}\x{504D}\x{504E}\x{504F}\x{5051}\x{5053}' - . '\x{5054}\x{5055}\x{5056}\x{5057}\x{5059}\x{505A}\x{505B}\x{505C}\x{505D}' - . '\x{505E}\x{505F}\x{5060}\x{5061}\x{5062}\x{5063}\x{5064}\x{5065}\x{5066}' - . '\x{5067}\x{5068}\x{5069}\x{506A}\x{506B}\x{506C}\x{506D}\x{506E}\x{506F}' - . '\x{5070}\x{5071}\x{5072}\x{5073}\x{5074}\x{5075}\x{5076}\x{5077}\x{5078}' - . '\x{5079}\x{507A}\x{507B}\x{507D}\x{507E}\x{507F}\x{5080}\x{5082}\x{5083}' - . '\x{5084}\x{5085}\x{5086}\x{5087}\x{5088}\x{5089}\x{508A}\x{508B}\x{508C}' - . '\x{508D}\x{508E}\x{508F}\x{5090}\x{5091}\x{5092}\x{5094}\x{5095}\x{5096}' - . '\x{5098}\x{5099}\x{509A}\x{509B}\x{509C}\x{509D}\x{509E}\x{50A2}\x{50A3}' - . '\x{50A4}\x{50A5}\x{50A6}\x{50A7}\x{50A8}\x{50A9}\x{50AA}\x{50AB}\x{50AC}' - . '\x{50AD}\x{50AE}\x{50AF}\x{50B0}\x{50B1}\x{50B2}\x{50B3}\x{50B4}\x{50B5}' - . '\x{50B6}\x{50B7}\x{50B8}\x{50BA}\x{50BB}\x{50BC}\x{50BD}\x{50BE}\x{50BF}' - . '\x{50C0}\x{50C1}\x{50C2}\x{50C4}\x{50C5}\x{50C6}\x{50C7}\x{50C8}\x{50C9}' - . '\x{50CA}\x{50CB}\x{50CC}\x{50CD}\x{50CE}\x{50CF}\x{50D0}\x{50D1}\x{50D2}' - . '\x{50D3}\x{50D4}\x{50D5}\x{50D6}\x{50D7}\x{50D9}\x{50DA}\x{50DB}\x{50DC}' - . '\x{50DD}\x{50DE}\x{50E0}\x{50E3}\x{50E4}\x{50E5}\x{50E6}\x{50E7}\x{50E8}' - . '\x{50E9}\x{50EA}\x{50EC}\x{50ED}\x{50EE}\x{50EF}\x{50F0}\x{50F1}\x{50F2}' - . '\x{50F3}\x{50F5}\x{50F6}\x{50F8}\x{50F9}\x{50FA}\x{50FB}\x{50FC}\x{50FD}' - . '\x{50FE}\x{50FF}\x{5100}\x{5101}\x{5102}\x{5103}\x{5104}\x{5105}\x{5106}' - . '\x{5107}\x{5108}\x{5109}\x{510A}\x{510B}\x{510C}\x{510D}\x{510E}\x{510F}' - . '\x{5110}\x{5111}\x{5112}\x{5113}\x{5114}\x{5115}\x{5116}\x{5117}\x{5118}' - . '\x{5119}\x{511A}\x{511C}\x{511D}\x{511E}\x{511F}\x{5120}\x{5121}\x{5122}' - . '\x{5123}\x{5124}\x{5125}\x{5126}\x{5127}\x{5129}\x{512A}\x{512C}\x{512D}' - . '\x{512E}\x{512F}\x{5130}\x{5131}\x{5132}\x{5133}\x{5134}\x{5135}\x{5136}' - . '\x{5137}\x{5138}\x{5139}\x{513A}\x{513B}\x{513C}\x{513D}\x{513E}\x{513F}' - . '\x{5140}\x{5141}\x{5143}\x{5144}\x{5145}\x{5146}\x{5147}\x{5148}\x{5149}' - . '\x{514B}\x{514C}\x{514D}\x{514E}\x{5150}\x{5151}\x{5152}\x{5154}\x{5155}' - . '\x{5156}\x{5157}\x{5159}\x{515A}\x{515B}\x{515C}\x{515D}\x{515E}\x{515F}' - . '\x{5161}\x{5162}\x{5163}\x{5165}\x{5166}\x{5167}\x{5168}\x{5169}\x{516A}' - . '\x{516B}\x{516C}\x{516D}\x{516E}\x{516F}\x{5170}\x{5171}\x{5173}\x{5174}' - . '\x{5175}\x{5176}\x{5177}\x{5178}\x{5179}\x{517A}\x{517B}\x{517C}\x{517D}' - . '\x{517F}\x{5180}\x{5181}\x{5182}\x{5185}\x{5186}\x{5187}\x{5188}\x{5189}' - . '\x{518A}\x{518B}\x{518C}\x{518D}\x{518F}\x{5190}\x{5191}\x{5192}\x{5193}' - . '\x{5194}\x{5195}\x{5196}\x{5197}\x{5198}\x{5199}\x{519A}\x{519B}\x{519C}' - . '\x{519D}\x{519E}\x{519F}\x{51A0}\x{51A2}\x{51A4}\x{51A5}\x{51A6}\x{51A7}' - . '\x{51A8}\x{51AA}\x{51AB}\x{51AC}\x{51AE}\x{51AF}\x{51B0}\x{51B1}\x{51B2}' - . '\x{51B3}\x{51B5}\x{51B6}\x{51B7}\x{51B9}\x{51BB}\x{51BC}\x{51BD}\x{51BE}' - . '\x{51BF}\x{51C0}\x{51C1}\x{51C3}\x{51C4}\x{51C5}\x{51C6}\x{51C7}\x{51C8}' - . '\x{51C9}\x{51CA}\x{51CB}\x{51CC}\x{51CD}\x{51CE}\x{51CF}\x{51D0}\x{51D1}' - . '\x{51D4}\x{51D5}\x{51D6}\x{51D7}\x{51D8}\x{51D9}\x{51DA}\x{51DB}\x{51DC}' - . '\x{51DD}\x{51DE}\x{51E0}\x{51E1}\x{51E2}\x{51E3}\x{51E4}\x{51E5}\x{51E7}' - . '\x{51E8}\x{51E9}\x{51EA}\x{51EB}\x{51ED}\x{51EF}\x{51F0}\x{51F1}\x{51F3}' - . '\x{51F4}\x{51F5}\x{51F6}\x{51F7}\x{51F8}\x{51F9}\x{51FA}\x{51FB}\x{51FC}' - . '\x{51FD}\x{51FE}\x{51FF}\x{5200}\x{5201}\x{5202}\x{5203}\x{5204}\x{5205}' - . '\x{5206}\x{5207}\x{5208}\x{5209}\x{520A}\x{520B}\x{520C}\x{520D}\x{520E}' - . '\x{520F}\x{5210}\x{5211}\x{5212}\x{5213}\x{5214}\x{5215}\x{5216}\x{5217}' - . '\x{5218}\x{5219}\x{521A}\x{521B}\x{521C}\x{521D}\x{521E}\x{521F}\x{5220}' - . '\x{5221}\x{5222}\x{5223}\x{5224}\x{5225}\x{5226}\x{5228}\x{5229}\x{522A}' - . '\x{522B}\x{522C}\x{522D}\x{522E}\x{522F}\x{5230}\x{5231}\x{5232}\x{5233}' - . '\x{5234}\x{5235}\x{5236}\x{5237}\x{5238}\x{5239}\x{523A}\x{523B}\x{523C}' - . '\x{523D}\x{523E}\x{523F}\x{5240}\x{5241}\x{5242}\x{5243}\x{5244}\x{5245}' - . '\x{5246}\x{5247}\x{5248}\x{5249}\x{524A}\x{524B}\x{524C}\x{524D}\x{524E}' - . '\x{5250}\x{5251}\x{5252}\x{5254}\x{5255}\x{5256}\x{5257}\x{5258}\x{5259}' - . '\x{525A}\x{525B}\x{525C}\x{525D}\x{525E}\x{525F}\x{5260}\x{5261}\x{5262}' - . '\x{5263}\x{5264}\x{5265}\x{5267}\x{5268}\x{5269}\x{526A}\x{526B}\x{526C}' - . '\x{526D}\x{526E}\x{526F}\x{5270}\x{5272}\x{5273}\x{5274}\x{5275}\x{5276}' - . '\x{5277}\x{5278}\x{527A}\x{527B}\x{527C}\x{527D}\x{527E}\x{527F}\x{5280}' - . '\x{5281}\x{5282}\x{5283}\x{5284}\x{5286}\x{5287}\x{5288}\x{5289}\x{528A}' - . '\x{528B}\x{528C}\x{528D}\x{528F}\x{5290}\x{5291}\x{5292}\x{5293}\x{5294}' - . '\x{5295}\x{5296}\x{5297}\x{5298}\x{5299}\x{529A}\x{529B}\x{529C}\x{529D}' - . '\x{529E}\x{529F}\x{52A0}\x{52A1}\x{52A2}\x{52A3}\x{52A5}\x{52A6}\x{52A7}' - . '\x{52A8}\x{52A9}\x{52AA}\x{52AB}\x{52AC}\x{52AD}\x{52AE}\x{52AF}\x{52B0}' - . '\x{52B1}\x{52B2}\x{52B3}\x{52B4}\x{52B5}\x{52B6}\x{52B7}\x{52B8}\x{52B9}' - . '\x{52BA}\x{52BB}\x{52BC}\x{52BD}\x{52BE}\x{52BF}\x{52C0}\x{52C1}\x{52C2}' - . '\x{52C3}\x{52C6}\x{52C7}\x{52C9}\x{52CA}\x{52CB}\x{52CD}\x{52CF}\x{52D0}' - . '\x{52D2}\x{52D3}\x{52D5}\x{52D6}\x{52D7}\x{52D8}\x{52D9}\x{52DA}\x{52DB}' - . '\x{52DC}\x{52DD}\x{52DE}\x{52DF}\x{52E0}\x{52E2}\x{52E3}\x{52E4}\x{52E6}' - . '\x{52E7}\x{52E8}\x{52E9}\x{52EA}\x{52EB}\x{52EC}\x{52ED}\x{52EF}\x{52F0}' - . '\x{52F1}\x{52F2}\x{52F3}\x{52F4}\x{52F5}\x{52F6}\x{52F7}\x{52F8}\x{52F9}' - . '\x{52FA}\x{52FB}\x{52FC}\x{52FD}\x{52FE}\x{52FF}\x{5300}\x{5301}\x{5302}' - . '\x{5305}\x{5306}\x{5307}\x{5308}\x{5309}\x{530A}\x{530B}\x{530C}\x{530D}' - . '\x{530E}\x{530F}\x{5310}\x{5311}\x{5312}\x{5313}\x{5314}\x{5315}\x{5316}' - . '\x{5317}\x{5319}\x{531A}\x{531C}\x{531D}\x{531F}\x{5320}\x{5321}\x{5322}' - . '\x{5323}\x{5324}\x{5325}\x{5326}\x{5328}\x{532A}\x{532B}\x{532C}\x{532D}' - . '\x{532E}\x{532F}\x{5330}\x{5331}\x{5333}\x{5334}\x{5337}\x{5339}\x{533A}' - . '\x{533B}\x{533C}\x{533D}\x{533E}\x{533F}\x{5340}\x{5341}\x{5343}\x{5344}' - . '\x{5345}\x{5346}\x{5347}\x{5348}\x{5349}\x{534A}\x{534B}\x{534C}\x{534D}' - . '\x{534E}\x{534F}\x{5350}\x{5351}\x{5352}\x{5353}\x{5354}\x{5355}\x{5356}' - . '\x{5357}\x{5358}\x{5359}\x{535A}\x{535C}\x{535E}\x{535F}\x{5360}\x{5361}' - . '\x{5362}\x{5363}\x{5364}\x{5365}\x{5366}\x{5367}\x{5369}\x{536B}\x{536C}' - . '\x{536E}\x{536F}\x{5370}\x{5371}\x{5372}\x{5373}\x{5374}\x{5375}\x{5376}' - . '\x{5377}\x{5378}\x{5379}\x{537A}\x{537B}\x{537C}\x{537D}\x{537E}\x{537F}' - . '\x{5381}\x{5382}\x{5383}\x{5384}\x{5385}\x{5386}\x{5387}\x{5388}\x{5389}' - . '\x{538A}\x{538B}\x{538C}\x{538D}\x{538E}\x{538F}\x{5390}\x{5391}\x{5392}' - . '\x{5393}\x{5394}\x{5395}\x{5396}\x{5397}\x{5398}\x{5399}\x{539A}\x{539B}' - . '\x{539C}\x{539D}\x{539E}\x{539F}\x{53A0}\x{53A2}\x{53A3}\x{53A4}\x{53A5}' - . '\x{53A6}\x{53A7}\x{53A8}\x{53A9}\x{53AC}\x{53AD}\x{53AE}\x{53B0}\x{53B1}' - . '\x{53B2}\x{53B3}\x{53B4}\x{53B5}\x{53B6}\x{53B7}\x{53B8}\x{53B9}\x{53BB}' - . '\x{53BC}\x{53BD}\x{53BE}\x{53BF}\x{53C0}\x{53C1}\x{53C2}\x{53C3}\x{53C4}' - . '\x{53C6}\x{53C7}\x{53C8}\x{53C9}\x{53CA}\x{53CB}\x{53CC}\x{53CD}\x{53CE}' - . '\x{53D0}\x{53D1}\x{53D2}\x{53D3}\x{53D4}\x{53D5}\x{53D6}\x{53D7}\x{53D8}' - . '\x{53D9}\x{53DB}\x{53DC}\x{53DF}\x{53E0}\x{53E1}\x{53E2}\x{53E3}\x{53E4}' - . '\x{53E5}\x{53E6}\x{53E8}\x{53E9}\x{53EA}\x{53EB}\x{53EC}\x{53ED}\x{53EE}' - . '\x{53EF}\x{53F0}\x{53F1}\x{53F2}\x{53F3}\x{53F4}\x{53F5}\x{53F6}\x{53F7}' - . '\x{53F8}\x{53F9}\x{53FA}\x{53FB}\x{53FC}\x{53FD}\x{53FE}\x{5401}\x{5402}' - . '\x{5403}\x{5404}\x{5405}\x{5406}\x{5407}\x{5408}\x{5409}\x{540A}\x{540B}' - . '\x{540C}\x{540D}\x{540E}\x{540F}\x{5410}\x{5411}\x{5412}\x{5413}\x{5414}' - . '\x{5415}\x{5416}\x{5417}\x{5418}\x{5419}\x{541B}\x{541C}\x{541D}\x{541E}' - . '\x{541F}\x{5420}\x{5421}\x{5423}\x{5424}\x{5425}\x{5426}\x{5427}\x{5428}' - . '\x{5429}\x{542A}\x{542B}\x{542C}\x{542D}\x{542E}\x{542F}\x{5430}\x{5431}' - . '\x{5432}\x{5433}\x{5434}\x{5435}\x{5436}\x{5437}\x{5438}\x{5439}\x{543A}' - . '\x{543B}\x{543C}\x{543D}\x{543E}\x{543F}\x{5440}\x{5441}\x{5442}\x{5443}' - . '\x{5444}\x{5445}\x{5446}\x{5447}\x{5448}\x{5449}\x{544A}\x{544B}\x{544D}' - . '\x{544E}\x{544F}\x{5450}\x{5451}\x{5452}\x{5453}\x{5454}\x{5455}\x{5456}' - . '\x{5457}\x{5458}\x{5459}\x{545A}\x{545B}\x{545C}\x{545E}\x{545F}\x{5460}' - . '\x{5461}\x{5462}\x{5463}\x{5464}\x{5465}\x{5466}\x{5467}\x{5468}\x{546A}' - . '\x{546B}\x{546C}\x{546D}\x{546E}\x{546F}\x{5470}\x{5471}\x{5472}\x{5473}' - . '\x{5474}\x{5475}\x{5476}\x{5477}\x{5478}\x{5479}\x{547A}\x{547B}\x{547C}' - . '\x{547D}\x{547E}\x{547F}\x{5480}\x{5481}\x{5482}\x{5483}\x{5484}\x{5485}' - . '\x{5486}\x{5487}\x{5488}\x{5489}\x{548B}\x{548C}\x{548D}\x{548E}\x{548F}' - . '\x{5490}\x{5491}\x{5492}\x{5493}\x{5494}\x{5495}\x{5496}\x{5497}\x{5498}' - . '\x{5499}\x{549A}\x{549B}\x{549C}\x{549D}\x{549E}\x{549F}\x{54A0}\x{54A1}' - . '\x{54A2}\x{54A3}\x{54A4}\x{54A5}\x{54A6}\x{54A7}\x{54A8}\x{54A9}\x{54AA}' - . '\x{54AB}\x{54AC}\x{54AD}\x{54AE}\x{54AF}\x{54B0}\x{54B1}\x{54B2}\x{54B3}' - . '\x{54B4}\x{54B6}\x{54B7}\x{54B8}\x{54B9}\x{54BA}\x{54BB}\x{54BC}\x{54BD}' - . '\x{54BE}\x{54BF}\x{54C0}\x{54C1}\x{54C2}\x{54C3}\x{54C4}\x{54C5}\x{54C6}' - . '\x{54C7}\x{54C8}\x{54C9}\x{54CA}\x{54CB}\x{54CC}\x{54CD}\x{54CE}\x{54CF}' - . '\x{54D0}\x{54D1}\x{54D2}\x{54D3}\x{54D4}\x{54D5}\x{54D6}\x{54D7}\x{54D8}' - . '\x{54D9}\x{54DA}\x{54DB}\x{54DC}\x{54DD}\x{54DE}\x{54DF}\x{54E0}\x{54E1}' - . '\x{54E2}\x{54E3}\x{54E4}\x{54E5}\x{54E6}\x{54E7}\x{54E8}\x{54E9}\x{54EA}' - . '\x{54EB}\x{54EC}\x{54ED}\x{54EE}\x{54EF}\x{54F0}\x{54F1}\x{54F2}\x{54F3}' - . '\x{54F4}\x{54F5}\x{54F7}\x{54F8}\x{54F9}\x{54FA}\x{54FB}\x{54FC}\x{54FD}' - . '\x{54FE}\x{54FF}\x{5500}\x{5501}\x{5502}\x{5503}\x{5504}\x{5505}\x{5506}' - . '\x{5507}\x{5508}\x{5509}\x{550A}\x{550B}\x{550C}\x{550D}\x{550E}\x{550F}' - . '\x{5510}\x{5511}\x{5512}\x{5513}\x{5514}\x{5516}\x{5517}\x{551A}\x{551B}' - . '\x{551C}\x{551D}\x{551E}\x{551F}\x{5520}\x{5521}\x{5522}\x{5523}\x{5524}' - . '\x{5525}\x{5526}\x{5527}\x{5528}\x{5529}\x{552A}\x{552B}\x{552C}\x{552D}' - . '\x{552E}\x{552F}\x{5530}\x{5531}\x{5532}\x{5533}\x{5534}\x{5535}\x{5536}' - . '\x{5537}\x{5538}\x{5539}\x{553A}\x{553B}\x{553C}\x{553D}\x{553E}\x{553F}' - . '\x{5540}\x{5541}\x{5542}\x{5543}\x{5544}\x{5545}\x{5546}\x{5548}\x{5549}' - . '\x{554A}\x{554B}\x{554C}\x{554D}\x{554E}\x{554F}\x{5550}\x{5551}\x{5552}' - . '\x{5553}\x{5554}\x{5555}\x{5556}\x{5557}\x{5558}\x{5559}\x{555A}\x{555B}' - . '\x{555C}\x{555D}\x{555E}\x{555F}\x{5561}\x{5562}\x{5563}\x{5564}\x{5565}' - . '\x{5566}\x{5567}\x{5568}\x{5569}\x{556A}\x{556B}\x{556C}\x{556D}\x{556E}' - . '\x{556F}\x{5570}\x{5571}\x{5572}\x{5573}\x{5574}\x{5575}\x{5576}\x{5577}' - . '\x{5578}\x{5579}\x{557B}\x{557C}\x{557D}\x{557E}\x{557F}\x{5580}\x{5581}' - . '\x{5582}\x{5583}\x{5584}\x{5585}\x{5586}\x{5587}\x{5588}\x{5589}\x{558A}' - . '\x{558B}\x{558C}\x{558D}\x{558E}\x{558F}\x{5590}\x{5591}\x{5592}\x{5593}' - . '\x{5594}\x{5595}\x{5596}\x{5597}\x{5598}\x{5599}\x{559A}\x{559B}\x{559C}' - . '\x{559D}\x{559E}\x{559F}\x{55A0}\x{55A1}\x{55A2}\x{55A3}\x{55A4}\x{55A5}' - . '\x{55A6}\x{55A7}\x{55A8}\x{55A9}\x{55AA}\x{55AB}\x{55AC}\x{55AD}\x{55AE}' - . '\x{55AF}\x{55B0}\x{55B1}\x{55B2}\x{55B3}\x{55B4}\x{55B5}\x{55B6}\x{55B7}' - . '\x{55B8}\x{55B9}\x{55BA}\x{55BB}\x{55BC}\x{55BD}\x{55BE}\x{55BF}\x{55C0}' - . '\x{55C1}\x{55C2}\x{55C3}\x{55C4}\x{55C5}\x{55C6}\x{55C7}\x{55C8}\x{55C9}' - . '\x{55CA}\x{55CB}\x{55CC}\x{55CD}\x{55CE}\x{55CF}\x{55D0}\x{55D1}\x{55D2}' - . '\x{55D3}\x{55D4}\x{55D5}\x{55D6}\x{55D7}\x{55D8}\x{55D9}\x{55DA}\x{55DB}' - . '\x{55DC}\x{55DD}\x{55DE}\x{55DF}\x{55E1}\x{55E2}\x{55E3}\x{55E4}\x{55E5}' - . '\x{55E6}\x{55E7}\x{55E8}\x{55E9}\x{55EA}\x{55EB}\x{55EC}\x{55ED}\x{55EE}' - . '\x{55EF}\x{55F0}\x{55F1}\x{55F2}\x{55F3}\x{55F4}\x{55F5}\x{55F6}\x{55F7}' - . '\x{55F9}\x{55FA}\x{55FB}\x{55FC}\x{55FD}\x{55FE}\x{55FF}\x{5600}\x{5601}' - . '\x{5602}\x{5603}\x{5604}\x{5606}\x{5607}\x{5608}\x{5609}\x{560C}\x{560D}' - . '\x{560E}\x{560F}\x{5610}\x{5611}\x{5612}\x{5613}\x{5614}\x{5615}\x{5616}' - . '\x{5617}\x{5618}\x{5619}\x{561A}\x{561B}\x{561C}\x{561D}\x{561E}\x{561F}' - . '\x{5621}\x{5622}\x{5623}\x{5624}\x{5625}\x{5626}\x{5627}\x{5628}\x{5629}' - . '\x{562A}\x{562C}\x{562D}\x{562E}\x{562F}\x{5630}\x{5631}\x{5632}\x{5633}' - . '\x{5634}\x{5635}\x{5636}\x{5638}\x{5639}\x{563A}\x{563B}\x{563D}\x{563E}' - . '\x{563F}\x{5640}\x{5641}\x{5642}\x{5643}\x{5645}\x{5646}\x{5647}\x{5648}' - . '\x{5649}\x{564A}\x{564C}\x{564D}\x{564E}\x{564F}\x{5650}\x{5652}\x{5653}' - . '\x{5654}\x{5655}\x{5657}\x{5658}\x{5659}\x{565A}\x{565B}\x{565C}\x{565D}' - . '\x{565E}\x{5660}\x{5662}\x{5663}\x{5664}\x{5665}\x{5666}\x{5667}\x{5668}' - . '\x{5669}\x{566A}\x{566B}\x{566C}\x{566D}\x{566E}\x{566F}\x{5670}\x{5671}' - . '\x{5672}\x{5673}\x{5674}\x{5676}\x{5677}\x{5678}\x{5679}\x{567A}\x{567B}' - . '\x{567C}\x{567E}\x{567F}\x{5680}\x{5681}\x{5682}\x{5683}\x{5684}\x{5685}' - . '\x{5686}\x{5687}\x{568A}\x{568C}\x{568D}\x{568E}\x{568F}\x{5690}\x{5691}' - . '\x{5692}\x{5693}\x{5694}\x{5695}\x{5697}\x{5698}\x{5699}\x{569A}\x{569B}' - . '\x{569C}\x{569D}\x{569F}\x{56A0}\x{56A1}\x{56A3}\x{56A4}\x{56A5}\x{56A6}' - . '\x{56A7}\x{56A8}\x{56A9}\x{56AA}\x{56AB}\x{56AC}\x{56AD}\x{56AE}\x{56AF}' - . '\x{56B0}\x{56B1}\x{56B2}\x{56B3}\x{56B4}\x{56B5}\x{56B6}\x{56B7}\x{56B8}' - . '\x{56B9}\x{56BB}\x{56BC}\x{56BD}\x{56BE}\x{56BF}\x{56C0}\x{56C1}\x{56C2}' - . '\x{56C3}\x{56C4}\x{56C5}\x{56C6}\x{56C7}\x{56C8}\x{56C9}\x{56CA}\x{56CB}' - . '\x{56CC}\x{56CD}\x{56CE}\x{56D0}\x{56D1}\x{56D2}\x{56D3}\x{56D4}\x{56D5}' - . '\x{56D6}\x{56D7}\x{56D8}\x{56DA}\x{56DB}\x{56DC}\x{56DD}\x{56DE}\x{56DF}' - . '\x{56E0}\x{56E1}\x{56E2}\x{56E3}\x{56E4}\x{56E5}\x{56E7}\x{56E8}\x{56E9}' - . '\x{56EA}\x{56EB}\x{56EC}\x{56ED}\x{56EE}\x{56EF}\x{56F0}\x{56F1}\x{56F2}' - . '\x{56F3}\x{56F4}\x{56F5}\x{56F7}\x{56F9}\x{56FA}\x{56FD}\x{56FE}\x{56FF}' - . '\x{5700}\x{5701}\x{5702}\x{5703}\x{5704}\x{5706}\x{5707}\x{5708}\x{5709}' - . '\x{570A}\x{570B}\x{570C}\x{570D}\x{570E}\x{570F}\x{5710}\x{5712}\x{5713}' - . '\x{5714}\x{5715}\x{5716}\x{5718}\x{5719}\x{571A}\x{571B}\x{571C}\x{571D}' - . '\x{571E}\x{571F}\x{5720}\x{5722}\x{5723}\x{5725}\x{5726}\x{5727}\x{5728}' - . '\x{5729}\x{572A}\x{572B}\x{572C}\x{572D}\x{572E}\x{572F}\x{5730}\x{5731}' - . '\x{5732}\x{5733}\x{5734}\x{5735}\x{5736}\x{5737}\x{5738}\x{5739}\x{573A}' - . '\x{573B}\x{573C}\x{573E}\x{573F}\x{5740}\x{5741}\x{5742}\x{5744}\x{5745}' - . '\x{5746}\x{5747}\x{5749}\x{574A}\x{574B}\x{574C}\x{574D}\x{574E}\x{574F}' - . '\x{5750}\x{5751}\x{5752}\x{5753}\x{5754}\x{5757}\x{5759}\x{575A}\x{575B}' - . '\x{575C}\x{575D}\x{575E}\x{575F}\x{5760}\x{5761}\x{5762}\x{5764}\x{5765}' - . '\x{5766}\x{5767}\x{5768}\x{5769}\x{576A}\x{576B}\x{576C}\x{576D}\x{576F}' - . '\x{5770}\x{5771}\x{5772}\x{5773}\x{5774}\x{5775}\x{5776}\x{5777}\x{5779}' - . '\x{577A}\x{577B}\x{577C}\x{577D}\x{577E}\x{577F}\x{5780}\x{5782}\x{5783}' - . '\x{5784}\x{5785}\x{5786}\x{5788}\x{5789}\x{578A}\x{578B}\x{578C}\x{578D}' - . '\x{578E}\x{578F}\x{5790}\x{5791}\x{5792}\x{5793}\x{5794}\x{5795}\x{5797}' - . '\x{5798}\x{5799}\x{579A}\x{579B}\x{579C}\x{579D}\x{579E}\x{579F}\x{57A0}' - . '\x{57A1}\x{57A2}\x{57A3}\x{57A4}\x{57A5}\x{57A6}\x{57A7}\x{57A9}\x{57AA}' - . '\x{57AB}\x{57AC}\x{57AD}\x{57AE}\x{57AF}\x{57B0}\x{57B1}\x{57B2}\x{57B3}' - . '\x{57B4}\x{57B5}\x{57B6}\x{57B7}\x{57B8}\x{57B9}\x{57BA}\x{57BB}\x{57BC}' - . '\x{57BD}\x{57BE}\x{57BF}\x{57C0}\x{57C1}\x{57C2}\x{57C3}\x{57C4}\x{57C5}' - . '\x{57C6}\x{57C7}\x{57C8}\x{57C9}\x{57CB}\x{57CC}\x{57CD}\x{57CE}\x{57CF}' - . '\x{57D0}\x{57D2}\x{57D3}\x{57D4}\x{57D5}\x{57D6}\x{57D8}\x{57D9}\x{57DA}' - . '\x{57DC}\x{57DD}\x{57DF}\x{57E0}\x{57E1}\x{57E2}\x{57E3}\x{57E4}\x{57E5}' - . '\x{57E6}\x{57E7}\x{57E8}\x{57E9}\x{57EA}\x{57EB}\x{57EC}\x{57ED}\x{57EE}' - . '\x{57EF}\x{57F0}\x{57F1}\x{57F2}\x{57F3}\x{57F4}\x{57F5}\x{57F6}\x{57F7}' - . '\x{57F8}\x{57F9}\x{57FA}\x{57FB}\x{57FC}\x{57FD}\x{57FE}\x{57FF}\x{5800}' - . '\x{5801}\x{5802}\x{5803}\x{5804}\x{5805}\x{5806}\x{5807}\x{5808}\x{5809}' - . '\x{580A}\x{580B}\x{580C}\x{580D}\x{580E}\x{580F}\x{5810}\x{5811}\x{5812}' - . '\x{5813}\x{5814}\x{5815}\x{5816}\x{5819}\x{581A}\x{581B}\x{581C}\x{581D}' - . '\x{581E}\x{581F}\x{5820}\x{5821}\x{5822}\x{5823}\x{5824}\x{5825}\x{5826}' - . '\x{5827}\x{5828}\x{5829}\x{582A}\x{582B}\x{582C}\x{582D}\x{582E}\x{582F}' - . '\x{5830}\x{5831}\x{5832}\x{5833}\x{5834}\x{5835}\x{5836}\x{5837}\x{5838}' - . '\x{5839}\x{583A}\x{583B}\x{583C}\x{583D}\x{583E}\x{583F}\x{5840}\x{5842}' - . '\x{5843}\x{5844}\x{5845}\x{5846}\x{5847}\x{5848}\x{5849}\x{584A}\x{584B}' - . '\x{584C}\x{584D}\x{584E}\x{584F}\x{5851}\x{5852}\x{5853}\x{5854}\x{5855}' - . '\x{5857}\x{5858}\x{5859}\x{585A}\x{585B}\x{585C}\x{585D}\x{585E}\x{585F}' - . '\x{5861}\x{5862}\x{5863}\x{5864}\x{5865}\x{5868}\x{5869}\x{586A}\x{586B}' - . '\x{586C}\x{586D}\x{586E}\x{586F}\x{5870}\x{5871}\x{5872}\x{5873}\x{5874}' - . '\x{5875}\x{5876}\x{5878}\x{5879}\x{587A}\x{587B}\x{587C}\x{587D}\x{587E}' - . '\x{587F}\x{5880}\x{5881}\x{5882}\x{5883}\x{5884}\x{5885}\x{5886}\x{5887}' - . '\x{5888}\x{5889}\x{588A}\x{588B}\x{588C}\x{588D}\x{588E}\x{588F}\x{5890}' - . '\x{5891}\x{5892}\x{5893}\x{5894}\x{5896}\x{5897}\x{5898}\x{5899}\x{589A}' - . '\x{589B}\x{589C}\x{589D}\x{589E}\x{589F}\x{58A0}\x{58A1}\x{58A2}\x{58A3}' - . '\x{58A4}\x{58A5}\x{58A6}\x{58A7}\x{58A8}\x{58A9}\x{58AB}\x{58AC}\x{58AD}' - . '\x{58AE}\x{58AF}\x{58B0}\x{58B1}\x{58B2}\x{58B3}\x{58B4}\x{58B7}\x{58B8}' - . '\x{58B9}\x{58BA}\x{58BB}\x{58BC}\x{58BD}\x{58BE}\x{58BF}\x{58C1}\x{58C2}' - . '\x{58C5}\x{58C6}\x{58C7}\x{58C8}\x{58C9}\x{58CA}\x{58CB}\x{58CE}\x{58CF}' - . '\x{58D1}\x{58D2}\x{58D3}\x{58D4}\x{58D5}\x{58D6}\x{58D7}\x{58D8}\x{58D9}' - . '\x{58DA}\x{58DB}\x{58DD}\x{58DE}\x{58DF}\x{58E0}\x{58E2}\x{58E3}\x{58E4}' - . '\x{58E5}\x{58E7}\x{58E8}\x{58E9}\x{58EA}\x{58EB}\x{58EC}\x{58ED}\x{58EE}' - . '\x{58EF}\x{58F0}\x{58F1}\x{58F2}\x{58F3}\x{58F4}\x{58F6}\x{58F7}\x{58F8}' - . '\x{58F9}\x{58FA}\x{58FB}\x{58FC}\x{58FD}\x{58FE}\x{58FF}\x{5900}\x{5902}' - . '\x{5903}\x{5904}\x{5906}\x{5907}\x{5909}\x{590A}\x{590B}\x{590C}\x{590D}' - . '\x{590E}\x{590F}\x{5910}\x{5912}\x{5914}\x{5915}\x{5916}\x{5917}\x{5918}' - . '\x{5919}\x{591A}\x{591B}\x{591C}\x{591D}\x{591E}\x{591F}\x{5920}\x{5921}' - . '\x{5922}\x{5924}\x{5925}\x{5926}\x{5927}\x{5928}\x{5929}\x{592A}\x{592B}' - . '\x{592C}\x{592D}\x{592E}\x{592F}\x{5930}\x{5931}\x{5932}\x{5934}\x{5935}' - . '\x{5937}\x{5938}\x{5939}\x{593A}\x{593B}\x{593C}\x{593D}\x{593E}\x{593F}' - . '\x{5940}\x{5941}\x{5942}\x{5943}\x{5944}\x{5945}\x{5946}\x{5947}\x{5948}' - . '\x{5949}\x{594A}\x{594B}\x{594C}\x{594D}\x{594E}\x{594F}\x{5950}\x{5951}' - . '\x{5952}\x{5953}\x{5954}\x{5955}\x{5956}\x{5957}\x{5958}\x{595A}\x{595C}' - . '\x{595D}\x{595E}\x{595F}\x{5960}\x{5961}\x{5962}\x{5963}\x{5964}\x{5965}' - . '\x{5966}\x{5967}\x{5968}\x{5969}\x{596A}\x{596B}\x{596C}\x{596D}\x{596E}' - . '\x{596F}\x{5970}\x{5971}\x{5972}\x{5973}\x{5974}\x{5975}\x{5976}\x{5977}' - . '\x{5978}\x{5979}\x{597A}\x{597B}\x{597C}\x{597D}\x{597E}\x{597F}\x{5980}' - . '\x{5981}\x{5982}\x{5983}\x{5984}\x{5985}\x{5986}\x{5987}\x{5988}\x{5989}' - . '\x{598A}\x{598B}\x{598C}\x{598D}\x{598E}\x{598F}\x{5990}\x{5991}\x{5992}' - . '\x{5993}\x{5994}\x{5995}\x{5996}\x{5997}\x{5998}\x{5999}\x{599A}\x{599C}' - . '\x{599D}\x{599E}\x{599F}\x{59A0}\x{59A1}\x{59A2}\x{59A3}\x{59A4}\x{59A5}' - . '\x{59A6}\x{59A7}\x{59A8}\x{59A9}\x{59AA}\x{59AB}\x{59AC}\x{59AD}\x{59AE}' - . '\x{59AF}\x{59B0}\x{59B1}\x{59B2}\x{59B3}\x{59B4}\x{59B5}\x{59B6}\x{59B8}' - . '\x{59B9}\x{59BA}\x{59BB}\x{59BC}\x{59BD}\x{59BE}\x{59BF}\x{59C0}\x{59C1}' - . '\x{59C2}\x{59C3}\x{59C4}\x{59C5}\x{59C6}\x{59C7}\x{59C8}\x{59C9}\x{59CA}' - . '\x{59CB}\x{59CC}\x{59CD}\x{59CE}\x{59CF}\x{59D0}\x{59D1}\x{59D2}\x{59D3}' - . '\x{59D4}\x{59D5}\x{59D6}\x{59D7}\x{59D8}\x{59D9}\x{59DA}\x{59DB}\x{59DC}' - . '\x{59DD}\x{59DE}\x{59DF}\x{59E0}\x{59E1}\x{59E2}\x{59E3}\x{59E4}\x{59E5}' - . '\x{59E6}\x{59E8}\x{59E9}\x{59EA}\x{59EB}\x{59EC}\x{59ED}\x{59EE}\x{59EF}' - . '\x{59F0}\x{59F1}\x{59F2}\x{59F3}\x{59F4}\x{59F5}\x{59F6}\x{59F7}\x{59F8}' - . '\x{59F9}\x{59FA}\x{59FB}\x{59FC}\x{59FD}\x{59FE}\x{59FF}\x{5A00}\x{5A01}' - . '\x{5A02}\x{5A03}\x{5A04}\x{5A05}\x{5A06}\x{5A07}\x{5A08}\x{5A09}\x{5A0A}' - . '\x{5A0B}\x{5A0C}\x{5A0D}\x{5A0E}\x{5A0F}\x{5A10}\x{5A11}\x{5A12}\x{5A13}' - . '\x{5A14}\x{5A15}\x{5A16}\x{5A17}\x{5A18}\x{5A19}\x{5A1A}\x{5A1B}\x{5A1C}' - . '\x{5A1D}\x{5A1E}\x{5A1F}\x{5A20}\x{5A21}\x{5A22}\x{5A23}\x{5A25}\x{5A27}' - . '\x{5A28}\x{5A29}\x{5A2A}\x{5A2B}\x{5A2D}\x{5A2E}\x{5A2F}\x{5A31}\x{5A32}' - . '\x{5A33}\x{5A34}\x{5A35}\x{5A36}\x{5A37}\x{5A38}\x{5A39}\x{5A3A}\x{5A3B}' - . '\x{5A3C}\x{5A3D}\x{5A3E}\x{5A3F}\x{5A40}\x{5A41}\x{5A42}\x{5A43}\x{5A44}' - . '\x{5A45}\x{5A46}\x{5A47}\x{5A48}\x{5A49}\x{5A4A}\x{5A4B}\x{5A4C}\x{5A4D}' - . '\x{5A4E}\x{5A4F}\x{5A50}\x{5A51}\x{5A52}\x{5A53}\x{5A55}\x{5A56}\x{5A57}' - . '\x{5A58}\x{5A5A}\x{5A5B}\x{5A5C}\x{5A5D}\x{5A5E}\x{5A5F}\x{5A60}\x{5A61}' - . '\x{5A62}\x{5A63}\x{5A64}\x{5A65}\x{5A66}\x{5A67}\x{5A68}\x{5A69}\x{5A6A}' - . '\x{5A6B}\x{5A6C}\x{5A6D}\x{5A6E}\x{5A70}\x{5A72}\x{5A73}\x{5A74}\x{5A75}' - . '\x{5A76}\x{5A77}\x{5A78}\x{5A79}\x{5A7A}\x{5A7B}\x{5A7C}\x{5A7D}\x{5A7E}' - . '\x{5A7F}\x{5A80}\x{5A81}\x{5A82}\x{5A83}\x{5A84}\x{5A85}\x{5A86}\x{5A88}' - . '\x{5A89}\x{5A8A}\x{5A8B}\x{5A8C}\x{5A8E}\x{5A8F}\x{5A90}\x{5A91}\x{5A92}' - . '\x{5A93}\x{5A94}\x{5A95}\x{5A96}\x{5A97}\x{5A98}\x{5A99}\x{5A9A}\x{5A9B}' - . '\x{5A9C}\x{5A9D}\x{5A9E}\x{5A9F}\x{5AA0}\x{5AA1}\x{5AA2}\x{5AA3}\x{5AA4}' - . '\x{5AA5}\x{5AA6}\x{5AA7}\x{5AA8}\x{5AA9}\x{5AAA}\x{5AAC}\x{5AAD}\x{5AAE}' - . '\x{5AAF}\x{5AB0}\x{5AB1}\x{5AB2}\x{5AB3}\x{5AB4}\x{5AB5}\x{5AB6}\x{5AB7}' - . '\x{5AB8}\x{5AB9}\x{5ABA}\x{5ABB}\x{5ABC}\x{5ABD}\x{5ABE}\x{5ABF}\x{5AC0}' - . '\x{5AC1}\x{5AC2}\x{5AC3}\x{5AC4}\x{5AC5}\x{5AC6}\x{5AC7}\x{5AC8}\x{5AC9}' - . '\x{5ACA}\x{5ACB}\x{5ACC}\x{5ACD}\x{5ACE}\x{5ACF}\x{5AD1}\x{5AD2}\x{5AD4}' - . '\x{5AD5}\x{5AD6}\x{5AD7}\x{5AD8}\x{5AD9}\x{5ADA}\x{5ADB}\x{5ADC}\x{5ADD}' - . '\x{5ADE}\x{5ADF}\x{5AE0}\x{5AE1}\x{5AE2}\x{5AE3}\x{5AE4}\x{5AE5}\x{5AE6}' - . '\x{5AE7}\x{5AE8}\x{5AE9}\x{5AEA}\x{5AEB}\x{5AEC}\x{5AED}\x{5AEE}\x{5AF1}' - . '\x{5AF2}\x{5AF3}\x{5AF4}\x{5AF5}\x{5AF6}\x{5AF7}\x{5AF8}\x{5AF9}\x{5AFA}' - . '\x{5AFB}\x{5AFC}\x{5AFD}\x{5AFE}\x{5AFF}\x{5B00}\x{5B01}\x{5B02}\x{5B03}' - . '\x{5B04}\x{5B05}\x{5B06}\x{5B07}\x{5B08}\x{5B09}\x{5B0B}\x{5B0C}\x{5B0E}' - . '\x{5B0F}\x{5B10}\x{5B11}\x{5B12}\x{5B13}\x{5B14}\x{5B15}\x{5B16}\x{5B17}' - . '\x{5B18}\x{5B19}\x{5B1A}\x{5B1B}\x{5B1C}\x{5B1D}\x{5B1E}\x{5B1F}\x{5B20}' - . '\x{5B21}\x{5B22}\x{5B23}\x{5B24}\x{5B25}\x{5B26}\x{5B27}\x{5B28}\x{5B29}' - . '\x{5B2A}\x{5B2B}\x{5B2C}\x{5B2D}\x{5B2E}\x{5B2F}\x{5B30}\x{5B31}\x{5B32}' - . '\x{5B33}\x{5B34}\x{5B35}\x{5B36}\x{5B37}\x{5B38}\x{5B3A}\x{5B3B}\x{5B3C}' - . '\x{5B3D}\x{5B3E}\x{5B3F}\x{5B40}\x{5B41}\x{5B42}\x{5B43}\x{5B44}\x{5B45}' - . '\x{5B47}\x{5B48}\x{5B49}\x{5B4A}\x{5B4B}\x{5B4C}\x{5B4D}\x{5B4E}\x{5B50}' - . '\x{5B51}\x{5B53}\x{5B54}\x{5B55}\x{5B56}\x{5B57}\x{5B58}\x{5B59}\x{5B5A}' - . '\x{5B5B}\x{5B5C}\x{5B5D}\x{5B5E}\x{5B5F}\x{5B62}\x{5B63}\x{5B64}\x{5B65}' - . '\x{5B66}\x{5B67}\x{5B68}\x{5B69}\x{5B6A}\x{5B6B}\x{5B6C}\x{5B6D}\x{5B6E}' - . '\x{5B70}\x{5B71}\x{5B72}\x{5B73}\x{5B74}\x{5B75}\x{5B76}\x{5B77}\x{5B78}' - . '\x{5B7A}\x{5B7B}\x{5B7C}\x{5B7D}\x{5B7F}\x{5B80}\x{5B81}\x{5B82}\x{5B83}' - . '\x{5B84}\x{5B85}\x{5B87}\x{5B88}\x{5B89}\x{5B8A}\x{5B8B}\x{5B8C}\x{5B8D}' - . '\x{5B8E}\x{5B8F}\x{5B91}\x{5B92}\x{5B93}\x{5B94}\x{5B95}\x{5B96}\x{5B97}' - . '\x{5B98}\x{5B99}\x{5B9A}\x{5B9B}\x{5B9C}\x{5B9D}\x{5B9E}\x{5B9F}\x{5BA0}' - . '\x{5BA1}\x{5BA2}\x{5BA3}\x{5BA4}\x{5BA5}\x{5BA6}\x{5BA7}\x{5BA8}\x{5BAA}' - . '\x{5BAB}\x{5BAC}\x{5BAD}\x{5BAE}\x{5BAF}\x{5BB0}\x{5BB1}\x{5BB3}\x{5BB4}' - . '\x{5BB5}\x{5BB6}\x{5BB8}\x{5BB9}\x{5BBA}\x{5BBB}\x{5BBD}\x{5BBE}\x{5BBF}' - . '\x{5BC0}\x{5BC1}\x{5BC2}\x{5BC3}\x{5BC4}\x{5BC5}\x{5BC6}\x{5BC7}\x{5BCA}' - . '\x{5BCB}\x{5BCC}\x{5BCD}\x{5BCE}\x{5BCF}\x{5BD0}\x{5BD1}\x{5BD2}\x{5BD3}' - . '\x{5BD4}\x{5BD5}\x{5BD6}\x{5BD8}\x{5BD9}\x{5BDB}\x{5BDC}\x{5BDD}\x{5BDE}' - . '\x{5BDF}\x{5BE0}\x{5BE1}\x{5BE2}\x{5BE3}\x{5BE4}\x{5BE5}\x{5BE6}\x{5BE7}' - . '\x{5BE8}\x{5BE9}\x{5BEA}\x{5BEB}\x{5BEC}\x{5BED}\x{5BEE}\x{5BEF}\x{5BF0}' - . '\x{5BF1}\x{5BF2}\x{5BF3}\x{5BF4}\x{5BF5}\x{5BF6}\x{5BF7}\x{5BF8}\x{5BF9}' - . '\x{5BFA}\x{5BFB}\x{5BFC}\x{5BFD}\x{5BFF}\x{5C01}\x{5C03}\x{5C04}\x{5C05}' - . '\x{5C06}\x{5C07}\x{5C08}\x{5C09}\x{5C0A}\x{5C0B}\x{5C0C}\x{5C0D}\x{5C0E}' - . '\x{5C0F}\x{5C10}\x{5C11}\x{5C12}\x{5C13}\x{5C14}\x{5C15}\x{5C16}\x{5C17}' - . '\x{5C18}\x{5C19}\x{5C1A}\x{5C1C}\x{5C1D}\x{5C1E}\x{5C1F}\x{5C20}\x{5C21}' - . '\x{5C22}\x{5C24}\x{5C25}\x{5C27}\x{5C28}\x{5C2A}\x{5C2B}\x{5C2C}\x{5C2D}' - . '\x{5C2E}\x{5C2F}\x{5C30}\x{5C31}\x{5C32}\x{5C33}\x{5C34}\x{5C35}\x{5C37}' - . '\x{5C38}\x{5C39}\x{5C3A}\x{5C3B}\x{5C3C}\x{5C3D}\x{5C3E}\x{5C3F}\x{5C40}' - . '\x{5C41}\x{5C42}\x{5C43}\x{5C44}\x{5C45}\x{5C46}\x{5C47}\x{5C48}\x{5C49}' - . '\x{5C4A}\x{5C4B}\x{5C4C}\x{5C4D}\x{5C4E}\x{5C4F}\x{5C50}\x{5C51}\x{5C52}' - . '\x{5C53}\x{5C54}\x{5C55}\x{5C56}\x{5C57}\x{5C58}\x{5C59}\x{5C5B}\x{5C5C}' - . '\x{5C5D}\x{5C5E}\x{5C5F}\x{5C60}\x{5C61}\x{5C62}\x{5C63}\x{5C64}\x{5C65}' - . '\x{5C66}\x{5C67}\x{5C68}\x{5C69}\x{5C6A}\x{5C6B}\x{5C6C}\x{5C6D}\x{5C6E}' - . '\x{5C6F}\x{5C70}\x{5C71}\x{5C72}\x{5C73}\x{5C74}\x{5C75}\x{5C76}\x{5C77}' - . '\x{5C78}\x{5C79}\x{5C7A}\x{5C7B}\x{5C7C}\x{5C7D}\x{5C7E}\x{5C7F}\x{5C80}' - . '\x{5C81}\x{5C82}\x{5C83}\x{5C84}\x{5C86}\x{5C87}\x{5C88}\x{5C89}\x{5C8A}' - . '\x{5C8B}\x{5C8C}\x{5C8D}\x{5C8E}\x{5C8F}\x{5C90}\x{5C91}\x{5C92}\x{5C93}' - . '\x{5C94}\x{5C95}\x{5C96}\x{5C97}\x{5C98}\x{5C99}\x{5C9A}\x{5C9B}\x{5C9C}' - . '\x{5C9D}\x{5C9E}\x{5C9F}\x{5CA0}\x{5CA1}\x{5CA2}\x{5CA3}\x{5CA4}\x{5CA5}' - . '\x{5CA6}\x{5CA7}\x{5CA8}\x{5CA9}\x{5CAA}\x{5CAB}\x{5CAC}\x{5CAD}\x{5CAE}' - . '\x{5CAF}\x{5CB0}\x{5CB1}\x{5CB2}\x{5CB3}\x{5CB5}\x{5CB6}\x{5CB7}\x{5CB8}' - . '\x{5CBA}\x{5CBB}\x{5CBC}\x{5CBD}\x{5CBE}\x{5CBF}\x{5CC1}\x{5CC2}\x{5CC3}' - . '\x{5CC4}\x{5CC5}\x{5CC6}\x{5CC7}\x{5CC8}\x{5CC9}\x{5CCA}\x{5CCB}\x{5CCC}' - . '\x{5CCD}\x{5CCE}\x{5CCF}\x{5CD0}\x{5CD1}\x{5CD2}\x{5CD3}\x{5CD4}\x{5CD6}' - . '\x{5CD7}\x{5CD8}\x{5CD9}\x{5CDA}\x{5CDB}\x{5CDC}\x{5CDE}\x{5CDF}\x{5CE0}' - . '\x{5CE1}\x{5CE2}\x{5CE3}\x{5CE4}\x{5CE5}\x{5CE6}\x{5CE7}\x{5CE8}\x{5CE9}' - . '\x{5CEA}\x{5CEB}\x{5CEC}\x{5CED}\x{5CEE}\x{5CEF}\x{5CF0}\x{5CF1}\x{5CF2}' - . '\x{5CF3}\x{5CF4}\x{5CF6}\x{5CF7}\x{5CF8}\x{5CF9}\x{5CFA}\x{5CFB}\x{5CFC}' - . '\x{5CFD}\x{5CFE}\x{5CFF}\x{5D00}\x{5D01}\x{5D02}\x{5D03}\x{5D04}\x{5D05}' - . '\x{5D06}\x{5D07}\x{5D08}\x{5D09}\x{5D0A}\x{5D0B}\x{5D0C}\x{5D0D}\x{5D0E}' - . '\x{5D0F}\x{5D10}\x{5D11}\x{5D12}\x{5D13}\x{5D14}\x{5D15}\x{5D16}\x{5D17}' - . '\x{5D18}\x{5D19}\x{5D1A}\x{5D1B}\x{5D1C}\x{5D1D}\x{5D1E}\x{5D1F}\x{5D20}' - . '\x{5D21}\x{5D22}\x{5D23}\x{5D24}\x{5D25}\x{5D26}\x{5D27}\x{5D28}\x{5D29}' - . '\x{5D2A}\x{5D2C}\x{5D2D}\x{5D2E}\x{5D30}\x{5D31}\x{5D32}\x{5D33}\x{5D34}' - . '\x{5D35}\x{5D36}\x{5D37}\x{5D38}\x{5D39}\x{5D3A}\x{5D3C}\x{5D3D}\x{5D3E}' - . '\x{5D3F}\x{5D40}\x{5D41}\x{5D42}\x{5D43}\x{5D44}\x{5D45}\x{5D46}\x{5D47}' - . '\x{5D48}\x{5D49}\x{5D4A}\x{5D4B}\x{5D4C}\x{5D4D}\x{5D4E}\x{5D4F}\x{5D50}' - . '\x{5D51}\x{5D52}\x{5D54}\x{5D55}\x{5D56}\x{5D58}\x{5D59}\x{5D5A}\x{5D5B}' - . '\x{5D5D}\x{5D5E}\x{5D5F}\x{5D61}\x{5D62}\x{5D63}\x{5D64}\x{5D65}\x{5D66}' - . '\x{5D67}\x{5D68}\x{5D69}\x{5D6A}\x{5D6B}\x{5D6C}\x{5D6D}\x{5D6E}\x{5D6F}' - . '\x{5D70}\x{5D71}\x{5D72}\x{5D73}\x{5D74}\x{5D75}\x{5D76}\x{5D77}\x{5D78}' - . '\x{5D79}\x{5D7A}\x{5D7B}\x{5D7C}\x{5D7D}\x{5D7E}\x{5D7F}\x{5D80}\x{5D81}' - . '\x{5D82}\x{5D84}\x{5D85}\x{5D86}\x{5D87}\x{5D88}\x{5D89}\x{5D8A}\x{5D8B}' - . '\x{5D8C}\x{5D8D}\x{5D8E}\x{5D8F}\x{5D90}\x{5D91}\x{5D92}\x{5D93}\x{5D94}' - . '\x{5D95}\x{5D97}\x{5D98}\x{5D99}\x{5D9A}\x{5D9B}\x{5D9C}\x{5D9D}\x{5D9E}' - . '\x{5D9F}\x{5DA0}\x{5DA1}\x{5DA2}\x{5DA5}\x{5DA6}\x{5DA7}\x{5DA8}\x{5DA9}' - . '\x{5DAA}\x{5DAC}\x{5DAD}\x{5DAE}\x{5DAF}\x{5DB0}\x{5DB1}\x{5DB2}\x{5DB4}' - . '\x{5DB5}\x{5DB6}\x{5DB7}\x{5DB8}\x{5DBA}\x{5DBB}\x{5DBC}\x{5DBD}\x{5DBE}' - . '\x{5DBF}\x{5DC0}\x{5DC1}\x{5DC2}\x{5DC3}\x{5DC5}\x{5DC6}\x{5DC7}\x{5DC8}' - . '\x{5DC9}\x{5DCA}\x{5DCB}\x{5DCC}\x{5DCD}\x{5DCE}\x{5DCF}\x{5DD0}\x{5DD1}' - . '\x{5DD2}\x{5DD3}\x{5DD4}\x{5DD5}\x{5DD6}\x{5DD8}\x{5DD9}\x{5DDB}\x{5DDD}' - . '\x{5DDE}\x{5DDF}\x{5DE0}\x{5DE1}\x{5DE2}\x{5DE3}\x{5DE4}\x{5DE5}\x{5DE6}' - . '\x{5DE7}\x{5DE8}\x{5DE9}\x{5DEA}\x{5DEB}\x{5DEC}\x{5DED}\x{5DEE}\x{5DEF}' - . '\x{5DF0}\x{5DF1}\x{5DF2}\x{5DF3}\x{5DF4}\x{5DF5}\x{5DF7}\x{5DF8}\x{5DF9}' - . '\x{5DFA}\x{5DFB}\x{5DFC}\x{5DFD}\x{5DFE}\x{5DFF}\x{5E00}\x{5E01}\x{5E02}' - . '\x{5E03}\x{5E04}\x{5E05}\x{5E06}\x{5E07}\x{5E08}\x{5E09}\x{5E0A}\x{5E0B}' - . '\x{5E0C}\x{5E0D}\x{5E0E}\x{5E0F}\x{5E10}\x{5E11}\x{5E13}\x{5E14}\x{5E15}' - . '\x{5E16}\x{5E17}\x{5E18}\x{5E19}\x{5E1A}\x{5E1B}\x{5E1C}\x{5E1D}\x{5E1E}' - . '\x{5E1F}\x{5E20}\x{5E21}\x{5E22}\x{5E23}\x{5E24}\x{5E25}\x{5E26}\x{5E27}' - . '\x{5E28}\x{5E29}\x{5E2A}\x{5E2B}\x{5E2C}\x{5E2D}\x{5E2E}\x{5E2F}\x{5E30}' - . '\x{5E31}\x{5E32}\x{5E33}\x{5E34}\x{5E35}\x{5E36}\x{5E37}\x{5E38}\x{5E39}' - . '\x{5E3A}\x{5E3B}\x{5E3C}\x{5E3D}\x{5E3E}\x{5E40}\x{5E41}\x{5E42}\x{5E43}' - . '\x{5E44}\x{5E45}\x{5E46}\x{5E47}\x{5E49}\x{5E4A}\x{5E4B}\x{5E4C}\x{5E4D}' - . '\x{5E4E}\x{5E4F}\x{5E50}\x{5E52}\x{5E53}\x{5E54}\x{5E55}\x{5E56}\x{5E57}' - . '\x{5E58}\x{5E59}\x{5E5A}\x{5E5B}\x{5E5C}\x{5E5D}\x{5E5E}\x{5E5F}\x{5E60}' - . '\x{5E61}\x{5E62}\x{5E63}\x{5E64}\x{5E65}\x{5E66}\x{5E67}\x{5E68}\x{5E69}' - . '\x{5E6A}\x{5E6B}\x{5E6C}\x{5E6D}\x{5E6E}\x{5E6F}\x{5E70}\x{5E71}\x{5E72}' - . '\x{5E73}\x{5E74}\x{5E75}\x{5E76}\x{5E77}\x{5E78}\x{5E79}\x{5E7A}\x{5E7B}' - . '\x{5E7C}\x{5E7D}\x{5E7E}\x{5E7F}\x{5E80}\x{5E81}\x{5E82}\x{5E83}\x{5E84}' - . '\x{5E85}\x{5E86}\x{5E87}\x{5E88}\x{5E89}\x{5E8A}\x{5E8B}\x{5E8C}\x{5E8D}' - . '\x{5E8E}\x{5E8F}\x{5E90}\x{5E91}\x{5E93}\x{5E94}\x{5E95}\x{5E96}\x{5E97}' - . '\x{5E98}\x{5E99}\x{5E9A}\x{5E9B}\x{5E9C}\x{5E9D}\x{5E9E}\x{5E9F}\x{5EA0}' - . '\x{5EA1}\x{5EA2}\x{5EA3}\x{5EA4}\x{5EA5}\x{5EA6}\x{5EA7}\x{5EA8}\x{5EA9}' - . '\x{5EAA}\x{5EAB}\x{5EAC}\x{5EAD}\x{5EAE}\x{5EAF}\x{5EB0}\x{5EB1}\x{5EB2}' - . '\x{5EB3}\x{5EB4}\x{5EB5}\x{5EB6}\x{5EB7}\x{5EB8}\x{5EB9}\x{5EBB}\x{5EBC}' - . '\x{5EBD}\x{5EBE}\x{5EBF}\x{5EC1}\x{5EC2}\x{5EC3}\x{5EC4}\x{5EC5}\x{5EC6}' - . '\x{5EC7}\x{5EC8}\x{5EC9}\x{5ECA}\x{5ECB}\x{5ECC}\x{5ECD}\x{5ECE}\x{5ECF}' - . '\x{5ED0}\x{5ED1}\x{5ED2}\x{5ED3}\x{5ED4}\x{5ED5}\x{5ED6}\x{5ED7}\x{5ED8}' - . '\x{5ED9}\x{5EDA}\x{5EDB}\x{5EDC}\x{5EDD}\x{5EDE}\x{5EDF}\x{5EE0}\x{5EE1}' - . '\x{5EE2}\x{5EE3}\x{5EE4}\x{5EE5}\x{5EE6}\x{5EE7}\x{5EE8}\x{5EE9}\x{5EEA}' - . '\x{5EEC}\x{5EED}\x{5EEE}\x{5EEF}\x{5EF0}\x{5EF1}\x{5EF2}\x{5EF3}\x{5EF4}' - . '\x{5EF5}\x{5EF6}\x{5EF7}\x{5EF8}\x{5EFA}\x{5EFB}\x{5EFC}\x{5EFD}\x{5EFE}' - . '\x{5EFF}\x{5F00}\x{5F01}\x{5F02}\x{5F03}\x{5F04}\x{5F05}\x{5F06}\x{5F07}' - . '\x{5F08}\x{5F0A}\x{5F0B}\x{5F0C}\x{5F0D}\x{5F0F}\x{5F11}\x{5F12}\x{5F13}' - . '\x{5F14}\x{5F15}\x{5F16}\x{5F17}\x{5F18}\x{5F19}\x{5F1A}\x{5F1B}\x{5F1C}' - . '\x{5F1D}\x{5F1E}\x{5F1F}\x{5F20}\x{5F21}\x{5F22}\x{5F23}\x{5F24}\x{5F25}' - . '\x{5F26}\x{5F27}\x{5F28}\x{5F29}\x{5F2A}\x{5F2B}\x{5F2C}\x{5F2D}\x{5F2E}' - . '\x{5F2F}\x{5F30}\x{5F31}\x{5F32}\x{5F33}\x{5F34}\x{5F35}\x{5F36}\x{5F37}' - . '\x{5F38}\x{5F39}\x{5F3A}\x{5F3C}\x{5F3E}\x{5F3F}\x{5F40}\x{5F41}\x{5F42}' - . '\x{5F43}\x{5F44}\x{5F45}\x{5F46}\x{5F47}\x{5F48}\x{5F49}\x{5F4A}\x{5F4B}' - . '\x{5F4C}\x{5F4D}\x{5F4E}\x{5F4F}\x{5F50}\x{5F51}\x{5F52}\x{5F53}\x{5F54}' - . '\x{5F55}\x{5F56}\x{5F57}\x{5F58}\x{5F59}\x{5F5A}\x{5F5B}\x{5F5C}\x{5F5D}' - . '\x{5F5E}\x{5F5F}\x{5F60}\x{5F61}\x{5F62}\x{5F63}\x{5F64}\x{5F65}\x{5F66}' - . '\x{5F67}\x{5F68}\x{5F69}\x{5F6A}\x{5F6B}\x{5F6C}\x{5F6D}\x{5F6E}\x{5F6F}' - . '\x{5F70}\x{5F71}\x{5F72}\x{5F73}\x{5F74}\x{5F75}\x{5F76}\x{5F77}\x{5F78}' - . '\x{5F79}\x{5F7A}\x{5F7B}\x{5F7C}\x{5F7D}\x{5F7E}\x{5F7F}\x{5F80}\x{5F81}' - . '\x{5F82}\x{5F83}\x{5F84}\x{5F85}\x{5F86}\x{5F87}\x{5F88}\x{5F89}\x{5F8A}' - . '\x{5F8B}\x{5F8C}\x{5F8D}\x{5F8E}\x{5F90}\x{5F91}\x{5F92}\x{5F93}\x{5F94}' - . '\x{5F95}\x{5F96}\x{5F97}\x{5F98}\x{5F99}\x{5F9B}\x{5F9C}\x{5F9D}\x{5F9E}' - . '\x{5F9F}\x{5FA0}\x{5FA1}\x{5FA2}\x{5FA5}\x{5FA6}\x{5FA7}\x{5FA8}\x{5FA9}' - . '\x{5FAA}\x{5FAB}\x{5FAC}\x{5FAD}\x{5FAE}\x{5FAF}\x{5FB1}\x{5FB2}\x{5FB3}' - . '\x{5FB4}\x{5FB5}\x{5FB6}\x{5FB7}\x{5FB8}\x{5FB9}\x{5FBA}\x{5FBB}\x{5FBC}' - . '\x{5FBD}\x{5FBE}\x{5FBF}\x{5FC0}\x{5FC1}\x{5FC3}\x{5FC4}\x{5FC5}\x{5FC6}' - . '\x{5FC7}\x{5FC8}\x{5FC9}\x{5FCA}\x{5FCB}\x{5FCC}\x{5FCD}\x{5FCF}\x{5FD0}' - . '\x{5FD1}\x{5FD2}\x{5FD3}\x{5FD4}\x{5FD5}\x{5FD6}\x{5FD7}\x{5FD8}\x{5FD9}' - . '\x{5FDA}\x{5FDC}\x{5FDD}\x{5FDE}\x{5FE0}\x{5FE1}\x{5FE3}\x{5FE4}\x{5FE5}' - . '\x{5FE6}\x{5FE7}\x{5FE8}\x{5FE9}\x{5FEA}\x{5FEB}\x{5FED}\x{5FEE}\x{5FEF}' - . '\x{5FF0}\x{5FF1}\x{5FF2}\x{5FF3}\x{5FF4}\x{5FF5}\x{5FF6}\x{5FF7}\x{5FF8}' - . '\x{5FF9}\x{5FFA}\x{5FFB}\x{5FFD}\x{5FFE}\x{5FFF}\x{6000}\x{6001}\x{6002}' - . '\x{6003}\x{6004}\x{6005}\x{6006}\x{6007}\x{6008}\x{6009}\x{600A}\x{600B}' - . '\x{600C}\x{600D}\x{600E}\x{600F}\x{6010}\x{6011}\x{6012}\x{6013}\x{6014}' - . '\x{6015}\x{6016}\x{6017}\x{6018}\x{6019}\x{601A}\x{601B}\x{601C}\x{601D}' - . '\x{601E}\x{601F}\x{6020}\x{6021}\x{6022}\x{6024}\x{6025}\x{6026}\x{6027}' - . '\x{6028}\x{6029}\x{602A}\x{602B}\x{602C}\x{602D}\x{602E}\x{602F}\x{6030}' - . '\x{6031}\x{6032}\x{6033}\x{6034}\x{6035}\x{6036}\x{6037}\x{6038}\x{6039}' - . '\x{603A}\x{603B}\x{603C}\x{603D}\x{603E}\x{603F}\x{6040}\x{6041}\x{6042}' - . '\x{6043}\x{6044}\x{6045}\x{6046}\x{6047}\x{6048}\x{6049}\x{604A}\x{604B}' - . '\x{604C}\x{604D}\x{604E}\x{604F}\x{6050}\x{6051}\x{6052}\x{6053}\x{6054}' - . '\x{6055}\x{6057}\x{6058}\x{6059}\x{605A}\x{605B}\x{605C}\x{605D}\x{605E}' - . '\x{605F}\x{6062}\x{6063}\x{6064}\x{6065}\x{6066}\x{6067}\x{6068}\x{6069}' - . '\x{606A}\x{606B}\x{606C}\x{606D}\x{606E}\x{606F}\x{6070}\x{6072}\x{6073}' - . '\x{6075}\x{6076}\x{6077}\x{6078}\x{6079}\x{607A}\x{607B}\x{607C}\x{607D}' - . '\x{607E}\x{607F}\x{6080}\x{6081}\x{6082}\x{6083}\x{6084}\x{6085}\x{6086}' - . '\x{6087}\x{6088}\x{6089}\x{608A}\x{608B}\x{608C}\x{608D}\x{608E}\x{608F}' - . '\x{6090}\x{6092}\x{6094}\x{6095}\x{6096}\x{6097}\x{6098}\x{6099}\x{609A}' - . '\x{609B}\x{609C}\x{609D}\x{609E}\x{609F}\x{60A0}\x{60A1}\x{60A2}\x{60A3}' - . '\x{60A4}\x{60A6}\x{60A7}\x{60A8}\x{60AA}\x{60AB}\x{60AC}\x{60AD}\x{60AE}' - . '\x{60AF}\x{60B0}\x{60B1}\x{60B2}\x{60B3}\x{60B4}\x{60B5}\x{60B6}\x{60B7}' - . '\x{60B8}\x{60B9}\x{60BA}\x{60BB}\x{60BC}\x{60BD}\x{60BE}\x{60BF}\x{60C0}' - . '\x{60C1}\x{60C2}\x{60C3}\x{60C4}\x{60C5}\x{60C6}\x{60C7}\x{60C8}\x{60C9}' - . '\x{60CA}\x{60CB}\x{60CC}\x{60CD}\x{60CE}\x{60CF}\x{60D0}\x{60D1}\x{60D3}' - . '\x{60D4}\x{60D5}\x{60D7}\x{60D8}\x{60D9}\x{60DA}\x{60DB}\x{60DC}\x{60DD}' - . '\x{60DF}\x{60E0}\x{60E1}\x{60E2}\x{60E4}\x{60E6}\x{60E7}\x{60E8}\x{60E9}' - . '\x{60EA}\x{60EB}\x{60EC}\x{60ED}\x{60EE}\x{60EF}\x{60F0}\x{60F1}\x{60F2}' - . '\x{60F3}\x{60F4}\x{60F5}\x{60F6}\x{60F7}\x{60F8}\x{60F9}\x{60FA}\x{60FB}' - . '\x{60FC}\x{60FE}\x{60FF}\x{6100}\x{6101}\x{6103}\x{6104}\x{6105}\x{6106}' - . '\x{6108}\x{6109}\x{610A}\x{610B}\x{610C}\x{610D}\x{610E}\x{610F}\x{6110}' - . '\x{6112}\x{6113}\x{6114}\x{6115}\x{6116}\x{6117}\x{6118}\x{6119}\x{611A}' - . '\x{611B}\x{611C}\x{611D}\x{611F}\x{6120}\x{6122}\x{6123}\x{6124}\x{6125}' - . '\x{6126}\x{6127}\x{6128}\x{6129}\x{612A}\x{612B}\x{612C}\x{612D}\x{612E}' - . '\x{612F}\x{6130}\x{6132}\x{6134}\x{6136}\x{6137}\x{613A}\x{613B}\x{613C}' - . '\x{613D}\x{613E}\x{613F}\x{6140}\x{6141}\x{6142}\x{6143}\x{6144}\x{6145}' - . '\x{6146}\x{6147}\x{6148}\x{6149}\x{614A}\x{614B}\x{614C}\x{614D}\x{614E}' - . '\x{614F}\x{6150}\x{6151}\x{6152}\x{6153}\x{6154}\x{6155}\x{6156}\x{6157}' - . '\x{6158}\x{6159}\x{615A}\x{615B}\x{615C}\x{615D}\x{615E}\x{615F}\x{6161}' - . '\x{6162}\x{6163}\x{6164}\x{6165}\x{6166}\x{6167}\x{6168}\x{6169}\x{616A}' - . '\x{616B}\x{616C}\x{616D}\x{616E}\x{6170}\x{6171}\x{6172}\x{6173}\x{6174}' - . '\x{6175}\x{6176}\x{6177}\x{6178}\x{6179}\x{617A}\x{617C}\x{617E}\x{6180}' - . '\x{6181}\x{6182}\x{6183}\x{6184}\x{6185}\x{6187}\x{6188}\x{6189}\x{618A}' - . '\x{618B}\x{618C}\x{618D}\x{618E}\x{618F}\x{6190}\x{6191}\x{6192}\x{6193}' - . '\x{6194}\x{6195}\x{6196}\x{6198}\x{6199}\x{619A}\x{619B}\x{619D}\x{619E}' - . '\x{619F}\x{61A0}\x{61A1}\x{61A2}\x{61A3}\x{61A4}\x{61A5}\x{61A6}\x{61A7}' - . '\x{61A8}\x{61A9}\x{61AA}\x{61AB}\x{61AC}\x{61AD}\x{61AE}\x{61AF}\x{61B0}' - . '\x{61B1}\x{61B2}\x{61B3}\x{61B4}\x{61B5}\x{61B6}\x{61B7}\x{61B8}\x{61BA}' - . '\x{61BC}\x{61BD}\x{61BE}\x{61BF}\x{61C0}\x{61C1}\x{61C2}\x{61C3}\x{61C4}' - . '\x{61C5}\x{61C6}\x{61C7}\x{61C8}\x{61C9}\x{61CA}\x{61CB}\x{61CC}\x{61CD}' - . '\x{61CE}\x{61CF}\x{61D0}\x{61D1}\x{61D2}\x{61D4}\x{61D6}\x{61D7}\x{61D8}' - . '\x{61D9}\x{61DA}\x{61DB}\x{61DC}\x{61DD}\x{61DE}\x{61DF}\x{61E0}\x{61E1}' - . '\x{61E2}\x{61E3}\x{61E4}\x{61E5}\x{61E6}\x{61E7}\x{61E8}\x{61E9}\x{61EA}' - . '\x{61EB}\x{61ED}\x{61EE}\x{61F0}\x{61F1}\x{61F2}\x{61F3}\x{61F5}\x{61F6}' - . '\x{61F7}\x{61F8}\x{61F9}\x{61FA}\x{61FB}\x{61FC}\x{61FD}\x{61FE}\x{61FF}' - . '\x{6200}\x{6201}\x{6202}\x{6203}\x{6204}\x{6206}\x{6207}\x{6208}\x{6209}' - . '\x{620A}\x{620B}\x{620C}\x{620D}\x{620E}\x{620F}\x{6210}\x{6211}\x{6212}' - . '\x{6213}\x{6214}\x{6215}\x{6216}\x{6217}\x{6218}\x{6219}\x{621A}\x{621B}' - . '\x{621C}\x{621D}\x{621E}\x{621F}\x{6220}\x{6221}\x{6222}\x{6223}\x{6224}' - . '\x{6225}\x{6226}\x{6227}\x{6228}\x{6229}\x{622A}\x{622B}\x{622C}\x{622D}' - . '\x{622E}\x{622F}\x{6230}\x{6231}\x{6232}\x{6233}\x{6234}\x{6236}\x{6237}' - . '\x{6238}\x{623A}\x{623B}\x{623C}\x{623D}\x{623E}\x{623F}\x{6240}\x{6241}' - . '\x{6242}\x{6243}\x{6244}\x{6245}\x{6246}\x{6247}\x{6248}\x{6249}\x{624A}' - . '\x{624B}\x{624C}\x{624D}\x{624E}\x{624F}\x{6250}\x{6251}\x{6252}\x{6253}' - . '\x{6254}\x{6255}\x{6256}\x{6258}\x{6259}\x{625A}\x{625B}\x{625C}\x{625D}' - . '\x{625E}\x{625F}\x{6260}\x{6261}\x{6262}\x{6263}\x{6264}\x{6265}\x{6266}' - . '\x{6267}\x{6268}\x{6269}\x{626A}\x{626B}\x{626C}\x{626D}\x{626E}\x{626F}' - . '\x{6270}\x{6271}\x{6272}\x{6273}\x{6274}\x{6275}\x{6276}\x{6277}\x{6278}' - . '\x{6279}\x{627A}\x{627B}\x{627C}\x{627D}\x{627E}\x{627F}\x{6280}\x{6281}' - . '\x{6283}\x{6284}\x{6285}\x{6286}\x{6287}\x{6288}\x{6289}\x{628A}\x{628B}' - . '\x{628C}\x{628E}\x{628F}\x{6290}\x{6291}\x{6292}\x{6293}\x{6294}\x{6295}' - . '\x{6296}\x{6297}\x{6298}\x{6299}\x{629A}\x{629B}\x{629C}\x{629E}\x{629F}' - . '\x{62A0}\x{62A1}\x{62A2}\x{62A3}\x{62A4}\x{62A5}\x{62A7}\x{62A8}\x{62A9}' - . '\x{62AA}\x{62AB}\x{62AC}\x{62AD}\x{62AE}\x{62AF}\x{62B0}\x{62B1}\x{62B2}' - . '\x{62B3}\x{62B4}\x{62B5}\x{62B6}\x{62B7}\x{62B8}\x{62B9}\x{62BA}\x{62BB}' - . '\x{62BC}\x{62BD}\x{62BE}\x{62BF}\x{62C0}\x{62C1}\x{62C2}\x{62C3}\x{62C4}' - . '\x{62C5}\x{62C6}\x{62C7}\x{62C8}\x{62C9}\x{62CA}\x{62CB}\x{62CC}\x{62CD}' - . '\x{62CE}\x{62CF}\x{62D0}\x{62D1}\x{62D2}\x{62D3}\x{62D4}\x{62D5}\x{62D6}' - . '\x{62D7}\x{62D8}\x{62D9}\x{62DA}\x{62DB}\x{62DC}\x{62DD}\x{62DF}\x{62E0}' - . '\x{62E1}\x{62E2}\x{62E3}\x{62E4}\x{62E5}\x{62E6}\x{62E7}\x{62E8}\x{62E9}' - . '\x{62EB}\x{62EC}\x{62ED}\x{62EE}\x{62EF}\x{62F0}\x{62F1}\x{62F2}\x{62F3}' - . '\x{62F4}\x{62F5}\x{62F6}\x{62F7}\x{62F8}\x{62F9}\x{62FA}\x{62FB}\x{62FC}' - . '\x{62FD}\x{62FE}\x{62FF}\x{6300}\x{6301}\x{6302}\x{6303}\x{6304}\x{6305}' - . '\x{6306}\x{6307}\x{6308}\x{6309}\x{630B}\x{630C}\x{630D}\x{630E}\x{630F}' - . '\x{6310}\x{6311}\x{6312}\x{6313}\x{6314}\x{6315}\x{6316}\x{6318}\x{6319}' - . '\x{631A}\x{631B}\x{631C}\x{631D}\x{631E}\x{631F}\x{6320}\x{6321}\x{6322}' - . '\x{6323}\x{6324}\x{6325}\x{6326}\x{6327}\x{6328}\x{6329}\x{632A}\x{632B}' - . '\x{632C}\x{632D}\x{632E}\x{632F}\x{6330}\x{6332}\x{6333}\x{6334}\x{6336}' - . '\x{6338}\x{6339}\x{633A}\x{633B}\x{633C}\x{633D}\x{633E}\x{6340}\x{6341}' - . '\x{6342}\x{6343}\x{6344}\x{6345}\x{6346}\x{6347}\x{6348}\x{6349}\x{634A}' - . '\x{634B}\x{634C}\x{634D}\x{634E}\x{634F}\x{6350}\x{6351}\x{6352}\x{6353}' - . '\x{6354}\x{6355}\x{6356}\x{6357}\x{6358}\x{6359}\x{635A}\x{635C}\x{635D}' - . '\x{635E}\x{635F}\x{6360}\x{6361}\x{6362}\x{6363}\x{6364}\x{6365}\x{6366}' - . '\x{6367}\x{6368}\x{6369}\x{636A}\x{636B}\x{636C}\x{636D}\x{636E}\x{636F}' - . '\x{6370}\x{6371}\x{6372}\x{6373}\x{6374}\x{6375}\x{6376}\x{6377}\x{6378}' - . '\x{6379}\x{637A}\x{637B}\x{637C}\x{637D}\x{637E}\x{6380}\x{6381}\x{6382}' - . '\x{6383}\x{6384}\x{6385}\x{6386}\x{6387}\x{6388}\x{6389}\x{638A}\x{638C}' - . '\x{638D}\x{638E}\x{638F}\x{6390}\x{6391}\x{6392}\x{6394}\x{6395}\x{6396}' - . '\x{6397}\x{6398}\x{6399}\x{639A}\x{639B}\x{639C}\x{639D}\x{639E}\x{639F}' - . '\x{63A0}\x{63A1}\x{63A2}\x{63A3}\x{63A4}\x{63A5}\x{63A6}\x{63A7}\x{63A8}' - . '\x{63A9}\x{63AA}\x{63AB}\x{63AC}\x{63AD}\x{63AE}\x{63AF}\x{63B0}\x{63B1}' - . '\x{63B2}\x{63B3}\x{63B4}\x{63B5}\x{63B6}\x{63B7}\x{63B8}\x{63B9}\x{63BA}' - . '\x{63BC}\x{63BD}\x{63BE}\x{63BF}\x{63C0}\x{63C1}\x{63C2}\x{63C3}\x{63C4}' - . '\x{63C5}\x{63C6}\x{63C7}\x{63C8}\x{63C9}\x{63CA}\x{63CB}\x{63CC}\x{63CD}' - . '\x{63CE}\x{63CF}\x{63D0}\x{63D2}\x{63D3}\x{63D4}\x{63D5}\x{63D6}\x{63D7}' - . '\x{63D8}\x{63D9}\x{63DA}\x{63DB}\x{63DC}\x{63DD}\x{63DE}\x{63DF}\x{63E0}' - . '\x{63E1}\x{63E2}\x{63E3}\x{63E4}\x{63E5}\x{63E6}\x{63E7}\x{63E8}\x{63E9}' - . '\x{63EA}\x{63EB}\x{63EC}\x{63ED}\x{63EE}\x{63EF}\x{63F0}\x{63F1}\x{63F2}' - . '\x{63F3}\x{63F4}\x{63F5}\x{63F6}\x{63F7}\x{63F8}\x{63F9}\x{63FA}\x{63FB}' - . '\x{63FC}\x{63FD}\x{63FE}\x{63FF}\x{6400}\x{6401}\x{6402}\x{6403}\x{6404}' - . '\x{6405}\x{6406}\x{6408}\x{6409}\x{640A}\x{640B}\x{640C}\x{640D}\x{640E}' - . '\x{640F}\x{6410}\x{6411}\x{6412}\x{6413}\x{6414}\x{6415}\x{6416}\x{6417}' - . '\x{6418}\x{6419}\x{641A}\x{641B}\x{641C}\x{641D}\x{641E}\x{641F}\x{6420}' - . '\x{6421}\x{6422}\x{6423}\x{6424}\x{6425}\x{6426}\x{6427}\x{6428}\x{6429}' - . '\x{642A}\x{642B}\x{642C}\x{642D}\x{642E}\x{642F}\x{6430}\x{6431}\x{6432}' - . '\x{6433}\x{6434}\x{6435}\x{6436}\x{6437}\x{6438}\x{6439}\x{643A}\x{643D}' - . '\x{643E}\x{643F}\x{6440}\x{6441}\x{6443}\x{6444}\x{6445}\x{6446}\x{6447}' - . '\x{6448}\x{644A}\x{644B}\x{644C}\x{644D}\x{644E}\x{644F}\x{6450}\x{6451}' - . '\x{6452}\x{6453}\x{6454}\x{6455}\x{6456}\x{6457}\x{6458}\x{6459}\x{645B}' - . '\x{645C}\x{645D}\x{645E}\x{645F}\x{6460}\x{6461}\x{6462}\x{6463}\x{6464}' - . '\x{6465}\x{6466}\x{6467}\x{6468}\x{6469}\x{646A}\x{646B}\x{646C}\x{646D}' - . '\x{646E}\x{646F}\x{6470}\x{6471}\x{6472}\x{6473}\x{6474}\x{6475}\x{6476}' - . '\x{6477}\x{6478}\x{6479}\x{647A}\x{647B}\x{647C}\x{647D}\x{647F}\x{6480}' - . '\x{6481}\x{6482}\x{6483}\x{6484}\x{6485}\x{6487}\x{6488}\x{6489}\x{648A}' - . '\x{648B}\x{648C}\x{648D}\x{648E}\x{648F}\x{6490}\x{6491}\x{6492}\x{6493}' - . '\x{6494}\x{6495}\x{6496}\x{6497}\x{6498}\x{6499}\x{649A}\x{649B}\x{649C}' - . '\x{649D}\x{649E}\x{649F}\x{64A0}\x{64A2}\x{64A3}\x{64A4}\x{64A5}\x{64A6}' - . '\x{64A7}\x{64A8}\x{64A9}\x{64AA}\x{64AB}\x{64AC}\x{64AD}\x{64AE}\x{64B0}' - . '\x{64B1}\x{64B2}\x{64B3}\x{64B4}\x{64B5}\x{64B7}\x{64B8}\x{64B9}\x{64BA}' - . '\x{64BB}\x{64BC}\x{64BD}\x{64BE}\x{64BF}\x{64C0}\x{64C1}\x{64C2}\x{64C3}' - . '\x{64C4}\x{64C5}\x{64C6}\x{64C7}\x{64C9}\x{64CA}\x{64CB}\x{64CC}\x{64CD}' - . '\x{64CE}\x{64CF}\x{64D0}\x{64D1}\x{64D2}\x{64D3}\x{64D4}\x{64D6}\x{64D7}' - . '\x{64D8}\x{64D9}\x{64DA}\x{64DB}\x{64DC}\x{64DD}\x{64DE}\x{64DF}\x{64E0}' - . '\x{64E2}\x{64E3}\x{64E4}\x{64E6}\x{64E7}\x{64E8}\x{64E9}\x{64EA}\x{64EB}' - . '\x{64EC}\x{64ED}\x{64EF}\x{64F0}\x{64F1}\x{64F2}\x{64F3}\x{64F4}\x{64F6}' - . '\x{64F7}\x{64F8}\x{64FA}\x{64FB}\x{64FC}\x{64FD}\x{64FE}\x{64FF}\x{6500}' - . '\x{6501}\x{6503}\x{6504}\x{6505}\x{6506}\x{6507}\x{6508}\x{6509}\x{650B}' - . '\x{650C}\x{650D}\x{650E}\x{650F}\x{6510}\x{6511}\x{6512}\x{6513}\x{6514}' - . '\x{6515}\x{6516}\x{6517}\x{6518}\x{6519}\x{651A}\x{651B}\x{651C}\x{651D}' - . '\x{651E}\x{6520}\x{6521}\x{6522}\x{6523}\x{6524}\x{6525}\x{6526}\x{6527}' - . '\x{6529}\x{652A}\x{652B}\x{652C}\x{652D}\x{652E}\x{652F}\x{6530}\x{6531}' - . '\x{6532}\x{6533}\x{6534}\x{6535}\x{6536}\x{6537}\x{6538}\x{6539}\x{653A}' - . '\x{653B}\x{653C}\x{653D}\x{653E}\x{653F}\x{6541}\x{6543}\x{6544}\x{6545}' - . '\x{6546}\x{6547}\x{6548}\x{6549}\x{654A}\x{654B}\x{654C}\x{654D}\x{654E}' - . '\x{654F}\x{6550}\x{6551}\x{6552}\x{6553}\x{6554}\x{6555}\x{6556}\x{6557}' - . '\x{6558}\x{6559}\x{655B}\x{655C}\x{655D}\x{655E}\x{6560}\x{6561}\x{6562}' - . '\x{6563}\x{6564}\x{6565}\x{6566}\x{6567}\x{6568}\x{6569}\x{656A}\x{656B}' - . '\x{656C}\x{656E}\x{656F}\x{6570}\x{6571}\x{6572}\x{6573}\x{6574}\x{6575}' - . '\x{6576}\x{6577}\x{6578}\x{6579}\x{657A}\x{657B}\x{657C}\x{657E}\x{657F}' - . '\x{6580}\x{6581}\x{6582}\x{6583}\x{6584}\x{6585}\x{6586}\x{6587}\x{6588}' - . '\x{6589}\x{658B}\x{658C}\x{658D}\x{658E}\x{658F}\x{6590}\x{6591}\x{6592}' - . '\x{6593}\x{6594}\x{6595}\x{6596}\x{6597}\x{6598}\x{6599}\x{659B}\x{659C}' - . '\x{659D}\x{659E}\x{659F}\x{65A0}\x{65A1}\x{65A2}\x{65A3}\x{65A4}\x{65A5}' - . '\x{65A6}\x{65A7}\x{65A8}\x{65A9}\x{65AA}\x{65AB}\x{65AC}\x{65AD}\x{65AE}' - . '\x{65AF}\x{65B0}\x{65B1}\x{65B2}\x{65B3}\x{65B4}\x{65B6}\x{65B7}\x{65B8}' - . '\x{65B9}\x{65BA}\x{65BB}\x{65BC}\x{65BD}\x{65BF}\x{65C0}\x{65C1}\x{65C2}' - . '\x{65C3}\x{65C4}\x{65C5}\x{65C6}\x{65C7}\x{65CA}\x{65CB}\x{65CC}\x{65CD}' - . '\x{65CE}\x{65CF}\x{65D0}\x{65D2}\x{65D3}\x{65D4}\x{65D5}\x{65D6}\x{65D7}' - . '\x{65DA}\x{65DB}\x{65DD}\x{65DE}\x{65DF}\x{65E0}\x{65E1}\x{65E2}\x{65E3}' - . '\x{65E5}\x{65E6}\x{65E7}\x{65E8}\x{65E9}\x{65EB}\x{65EC}\x{65ED}\x{65EE}' - . '\x{65EF}\x{65F0}\x{65F1}\x{65F2}\x{65F3}\x{65F4}\x{65F5}\x{65F6}\x{65F7}' - . '\x{65F8}\x{65FA}\x{65FB}\x{65FC}\x{65FD}\x{6600}\x{6601}\x{6602}\x{6603}' - . '\x{6604}\x{6605}\x{6606}\x{6607}\x{6608}\x{6609}\x{660A}\x{660B}\x{660C}' - . '\x{660D}\x{660E}\x{660F}\x{6610}\x{6611}\x{6612}\x{6613}\x{6614}\x{6615}' - . '\x{6616}\x{6618}\x{6619}\x{661A}\x{661B}\x{661C}\x{661D}\x{661F}\x{6620}' - . '\x{6621}\x{6622}\x{6623}\x{6624}\x{6625}\x{6626}\x{6627}\x{6628}\x{6629}' - . '\x{662A}\x{662B}\x{662D}\x{662E}\x{662F}\x{6630}\x{6631}\x{6632}\x{6633}' - . '\x{6634}\x{6635}\x{6636}\x{6639}\x{663A}\x{663C}\x{663D}\x{663E}\x{6640}' - . '\x{6641}\x{6642}\x{6643}\x{6644}\x{6645}\x{6646}\x{6647}\x{6649}\x{664A}' - . '\x{664B}\x{664C}\x{664E}\x{664F}\x{6650}\x{6651}\x{6652}\x{6653}\x{6654}' - . '\x{6655}\x{6656}\x{6657}\x{6658}\x{6659}\x{665A}\x{665B}\x{665C}\x{665D}' - . '\x{665E}\x{665F}\x{6661}\x{6662}\x{6664}\x{6665}\x{6666}\x{6668}\x{6669}' - . '\x{666A}\x{666B}\x{666C}\x{666D}\x{666E}\x{666F}\x{6670}\x{6671}\x{6672}' - . '\x{6673}\x{6674}\x{6675}\x{6676}\x{6677}\x{6678}\x{6679}\x{667A}\x{667B}' - . '\x{667C}\x{667D}\x{667E}\x{667F}\x{6680}\x{6681}\x{6682}\x{6683}\x{6684}' - . '\x{6685}\x{6686}\x{6687}\x{6688}\x{6689}\x{668A}\x{668B}\x{668C}\x{668D}' - . '\x{668E}\x{668F}\x{6690}\x{6691}\x{6693}\x{6694}\x{6695}\x{6696}\x{6697}' - . '\x{6698}\x{6699}\x{669A}\x{669B}\x{669D}\x{669F}\x{66A0}\x{66A1}\x{66A2}' - . '\x{66A3}\x{66A4}\x{66A5}\x{66A6}\x{66A7}\x{66A8}\x{66A9}\x{66AA}\x{66AB}' - . '\x{66AE}\x{66AF}\x{66B0}\x{66B1}\x{66B2}\x{66B3}\x{66B4}\x{66B5}\x{66B6}' - . '\x{66B7}\x{66B8}\x{66B9}\x{66BA}\x{66BB}\x{66BC}\x{66BD}\x{66BE}\x{66BF}' - . '\x{66C0}\x{66C1}\x{66C2}\x{66C3}\x{66C4}\x{66C5}\x{66C6}\x{66C7}\x{66C8}' - . '\x{66C9}\x{66CA}\x{66CB}\x{66CC}\x{66CD}\x{66CE}\x{66CF}\x{66D1}\x{66D2}' - . '\x{66D4}\x{66D5}\x{66D6}\x{66D8}\x{66D9}\x{66DA}\x{66DB}\x{66DC}\x{66DD}' - . '\x{66DE}\x{66E0}\x{66E1}\x{66E2}\x{66E3}\x{66E4}\x{66E5}\x{66E6}\x{66E7}' - . '\x{66E8}\x{66E9}\x{66EA}\x{66EB}\x{66EC}\x{66ED}\x{66EE}\x{66F0}\x{66F1}' - . '\x{66F2}\x{66F3}\x{66F4}\x{66F5}\x{66F6}\x{66F7}\x{66F8}\x{66F9}\x{66FA}' - . '\x{66FB}\x{66FC}\x{66FE}\x{66FF}\x{6700}\x{6701}\x{6703}\x{6704}\x{6705}' - . '\x{6706}\x{6708}\x{6709}\x{670A}\x{670B}\x{670C}\x{670D}\x{670E}\x{670F}' - . '\x{6710}\x{6711}\x{6712}\x{6713}\x{6714}\x{6715}\x{6716}\x{6717}\x{6718}' - . '\x{671A}\x{671B}\x{671C}\x{671D}\x{671E}\x{671F}\x{6720}\x{6721}\x{6722}' - . '\x{6723}\x{6725}\x{6726}\x{6727}\x{6728}\x{672A}\x{672B}\x{672C}\x{672D}' - . '\x{672E}\x{672F}\x{6730}\x{6731}\x{6732}\x{6733}\x{6734}\x{6735}\x{6736}' - . '\x{6737}\x{6738}\x{6739}\x{673A}\x{673B}\x{673C}\x{673D}\x{673E}\x{673F}' - . '\x{6740}\x{6741}\x{6742}\x{6743}\x{6744}\x{6745}\x{6746}\x{6747}\x{6748}' - . '\x{6749}\x{674A}\x{674B}\x{674C}\x{674D}\x{674E}\x{674F}\x{6750}\x{6751}' - . '\x{6752}\x{6753}\x{6754}\x{6755}\x{6756}\x{6757}\x{6758}\x{6759}\x{675A}' - . '\x{675B}\x{675C}\x{675D}\x{675E}\x{675F}\x{6760}\x{6761}\x{6762}\x{6763}' - . '\x{6764}\x{6765}\x{6766}\x{6768}\x{6769}\x{676A}\x{676B}\x{676C}\x{676D}' - . '\x{676E}\x{676F}\x{6770}\x{6771}\x{6772}\x{6773}\x{6774}\x{6775}\x{6776}' - . '\x{6777}\x{6778}\x{6779}\x{677A}\x{677B}\x{677C}\x{677D}\x{677E}\x{677F}' - . '\x{6780}\x{6781}\x{6782}\x{6783}\x{6784}\x{6785}\x{6786}\x{6787}\x{6789}' - . '\x{678A}\x{678B}\x{678C}\x{678D}\x{678E}\x{678F}\x{6790}\x{6791}\x{6792}' - . '\x{6793}\x{6794}\x{6795}\x{6797}\x{6798}\x{6799}\x{679A}\x{679B}\x{679C}' - . '\x{679D}\x{679E}\x{679F}\x{67A0}\x{67A1}\x{67A2}\x{67A3}\x{67A4}\x{67A5}' - . '\x{67A6}\x{67A7}\x{67A8}\x{67AA}\x{67AB}\x{67AC}\x{67AD}\x{67AE}\x{67AF}' - . '\x{67B0}\x{67B1}\x{67B2}\x{67B3}\x{67B4}\x{67B5}\x{67B6}\x{67B7}\x{67B8}' - . '\x{67B9}\x{67BA}\x{67BB}\x{67BC}\x{67BE}\x{67C0}\x{67C1}\x{67C2}\x{67C3}' - . '\x{67C4}\x{67C5}\x{67C6}\x{67C7}\x{67C8}\x{67C9}\x{67CA}\x{67CB}\x{67CC}' - . '\x{67CD}\x{67CE}\x{67CF}\x{67D0}\x{67D1}\x{67D2}\x{67D3}\x{67D4}\x{67D6}' - . '\x{67D8}\x{67D9}\x{67DA}\x{67DB}\x{67DC}\x{67DD}\x{67DE}\x{67DF}\x{67E0}' - . '\x{67E1}\x{67E2}\x{67E3}\x{67E4}\x{67E5}\x{67E6}\x{67E7}\x{67E8}\x{67E9}' - . '\x{67EA}\x{67EB}\x{67EC}\x{67ED}\x{67EE}\x{67EF}\x{67F0}\x{67F1}\x{67F2}' - . '\x{67F3}\x{67F4}\x{67F5}\x{67F6}\x{67F7}\x{67F8}\x{67FA}\x{67FB}\x{67FC}' - . '\x{67FD}\x{67FE}\x{67FF}\x{6800}\x{6802}\x{6803}\x{6804}\x{6805}\x{6806}' - . '\x{6807}\x{6808}\x{6809}\x{680A}\x{680B}\x{680C}\x{680D}\x{680E}\x{680F}' - . '\x{6810}\x{6811}\x{6812}\x{6813}\x{6814}\x{6816}\x{6817}\x{6818}\x{6819}' - . '\x{681A}\x{681B}\x{681C}\x{681D}\x{681F}\x{6820}\x{6821}\x{6822}\x{6823}' - . '\x{6824}\x{6825}\x{6826}\x{6828}\x{6829}\x{682A}\x{682B}\x{682C}\x{682D}' - . '\x{682E}\x{682F}\x{6831}\x{6832}\x{6833}\x{6834}\x{6835}\x{6836}\x{6837}' - . '\x{6838}\x{6839}\x{683A}\x{683B}\x{683C}\x{683D}\x{683E}\x{683F}\x{6840}' - . '\x{6841}\x{6842}\x{6843}\x{6844}\x{6845}\x{6846}\x{6847}\x{6848}\x{6849}' - . '\x{684A}\x{684B}\x{684C}\x{684D}\x{684E}\x{684F}\x{6850}\x{6851}\x{6852}' - . '\x{6853}\x{6854}\x{6855}\x{6856}\x{6857}\x{685B}\x{685D}\x{6860}\x{6861}' - . '\x{6862}\x{6863}\x{6864}\x{6865}\x{6866}\x{6867}\x{6868}\x{6869}\x{686A}' - . '\x{686B}\x{686C}\x{686D}\x{686E}\x{686F}\x{6870}\x{6871}\x{6872}\x{6873}' - . '\x{6874}\x{6875}\x{6876}\x{6877}\x{6878}\x{6879}\x{687B}\x{687C}\x{687D}' - . '\x{687E}\x{687F}\x{6880}\x{6881}\x{6882}\x{6883}\x{6884}\x{6885}\x{6886}' - . '\x{6887}\x{6888}\x{6889}\x{688A}\x{688B}\x{688C}\x{688D}\x{688E}\x{688F}' - . '\x{6890}\x{6891}\x{6892}\x{6893}\x{6894}\x{6896}\x{6897}\x{6898}\x{689A}' - . '\x{689B}\x{689C}\x{689D}\x{689E}\x{689F}\x{68A0}\x{68A1}\x{68A2}\x{68A3}' - . '\x{68A4}\x{68A6}\x{68A7}\x{68A8}\x{68A9}\x{68AA}\x{68AB}\x{68AC}\x{68AD}' - . '\x{68AE}\x{68AF}\x{68B0}\x{68B1}\x{68B2}\x{68B3}\x{68B4}\x{68B5}\x{68B6}' - . '\x{68B7}\x{68B9}\x{68BB}\x{68BC}\x{68BD}\x{68BE}\x{68BF}\x{68C0}\x{68C1}' - . '\x{68C2}\x{68C4}\x{68C6}\x{68C7}\x{68C8}\x{68C9}\x{68CA}\x{68CB}\x{68CC}' - . '\x{68CD}\x{68CE}\x{68CF}\x{68D0}\x{68D1}\x{68D2}\x{68D3}\x{68D4}\x{68D5}' - . '\x{68D6}\x{68D7}\x{68D8}\x{68DA}\x{68DB}\x{68DC}\x{68DD}\x{68DE}\x{68DF}' - . '\x{68E0}\x{68E1}\x{68E3}\x{68E4}\x{68E6}\x{68E7}\x{68E8}\x{68E9}\x{68EA}' - . '\x{68EB}\x{68EC}\x{68ED}\x{68EE}\x{68EF}\x{68F0}\x{68F1}\x{68F2}\x{68F3}' - . '\x{68F4}\x{68F5}\x{68F6}\x{68F7}\x{68F8}\x{68F9}\x{68FA}\x{68FB}\x{68FC}' - . '\x{68FD}\x{68FE}\x{68FF}\x{6901}\x{6902}\x{6903}\x{6904}\x{6905}\x{6906}' - . '\x{6907}\x{6908}\x{690A}\x{690B}\x{690C}\x{690D}\x{690E}\x{690F}\x{6910}' - . '\x{6911}\x{6912}\x{6913}\x{6914}\x{6915}\x{6916}\x{6917}\x{6918}\x{6919}' - . '\x{691A}\x{691B}\x{691C}\x{691D}\x{691E}\x{691F}\x{6920}\x{6921}\x{6922}' - . '\x{6923}\x{6924}\x{6925}\x{6926}\x{6927}\x{6928}\x{6929}\x{692A}\x{692B}' - . '\x{692C}\x{692D}\x{692E}\x{692F}\x{6930}\x{6931}\x{6932}\x{6933}\x{6934}' - . '\x{6935}\x{6936}\x{6937}\x{6938}\x{6939}\x{693A}\x{693B}\x{693C}\x{693D}' - . '\x{693F}\x{6940}\x{6941}\x{6942}\x{6943}\x{6944}\x{6945}\x{6946}\x{6947}' - . '\x{6948}\x{6949}\x{694A}\x{694B}\x{694C}\x{694E}\x{694F}\x{6950}\x{6951}' - . '\x{6952}\x{6953}\x{6954}\x{6955}\x{6956}\x{6957}\x{6958}\x{6959}\x{695A}' - . '\x{695B}\x{695C}\x{695D}\x{695E}\x{695F}\x{6960}\x{6961}\x{6962}\x{6963}' - . '\x{6964}\x{6965}\x{6966}\x{6967}\x{6968}\x{6969}\x{696A}\x{696B}\x{696C}' - . '\x{696D}\x{696E}\x{696F}\x{6970}\x{6971}\x{6972}\x{6973}\x{6974}\x{6975}' - . '\x{6976}\x{6977}\x{6978}\x{6979}\x{697A}\x{697B}\x{697C}\x{697D}\x{697E}' - . '\x{697F}\x{6980}\x{6981}\x{6982}\x{6983}\x{6984}\x{6985}\x{6986}\x{6987}' - . '\x{6988}\x{6989}\x{698A}\x{698B}\x{698C}\x{698D}\x{698E}\x{698F}\x{6990}' - . '\x{6991}\x{6992}\x{6993}\x{6994}\x{6995}\x{6996}\x{6997}\x{6998}\x{6999}' - . '\x{699A}\x{699B}\x{699C}\x{699D}\x{699E}\x{69A0}\x{69A1}\x{69A3}\x{69A4}' - . '\x{69A5}\x{69A6}\x{69A7}\x{69A8}\x{69A9}\x{69AA}\x{69AB}\x{69AC}\x{69AD}' - . '\x{69AE}\x{69AF}\x{69B0}\x{69B1}\x{69B2}\x{69B3}\x{69B4}\x{69B5}\x{69B6}' - . '\x{69B7}\x{69B8}\x{69B9}\x{69BA}\x{69BB}\x{69BC}\x{69BD}\x{69BE}\x{69BF}' - . '\x{69C1}\x{69C2}\x{69C3}\x{69C4}\x{69C5}\x{69C6}\x{69C7}\x{69C8}\x{69C9}' - . '\x{69CA}\x{69CB}\x{69CC}\x{69CD}\x{69CE}\x{69CF}\x{69D0}\x{69D3}\x{69D4}' - . '\x{69D8}\x{69D9}\x{69DA}\x{69DB}\x{69DC}\x{69DD}\x{69DE}\x{69DF}\x{69E0}' - . '\x{69E1}\x{69E2}\x{69E3}\x{69E4}\x{69E5}\x{69E6}\x{69E7}\x{69E8}\x{69E9}' - . '\x{69EA}\x{69EB}\x{69EC}\x{69ED}\x{69EE}\x{69EF}\x{69F0}\x{69F1}\x{69F2}' - . '\x{69F3}\x{69F4}\x{69F5}\x{69F6}\x{69F7}\x{69F8}\x{69FA}\x{69FB}\x{69FC}' - . '\x{69FD}\x{69FE}\x{69FF}\x{6A00}\x{6A01}\x{6A02}\x{6A04}\x{6A05}\x{6A06}' - . '\x{6A07}\x{6A08}\x{6A09}\x{6A0A}\x{6A0B}\x{6A0D}\x{6A0E}\x{6A0F}\x{6A10}' - . '\x{6A11}\x{6A12}\x{6A13}\x{6A14}\x{6A15}\x{6A16}\x{6A17}\x{6A18}\x{6A19}' - . '\x{6A1A}\x{6A1B}\x{6A1D}\x{6A1E}\x{6A1F}\x{6A20}\x{6A21}\x{6A22}\x{6A23}' - . '\x{6A25}\x{6A26}\x{6A27}\x{6A28}\x{6A29}\x{6A2A}\x{6A2B}\x{6A2C}\x{6A2D}' - . '\x{6A2E}\x{6A2F}\x{6A30}\x{6A31}\x{6A32}\x{6A33}\x{6A34}\x{6A35}\x{6A36}' - . '\x{6A38}\x{6A39}\x{6A3A}\x{6A3B}\x{6A3C}\x{6A3D}\x{6A3E}\x{6A3F}\x{6A40}' - . '\x{6A41}\x{6A42}\x{6A43}\x{6A44}\x{6A45}\x{6A46}\x{6A47}\x{6A48}\x{6A49}' - . '\x{6A4B}\x{6A4C}\x{6A4D}\x{6A4E}\x{6A4F}\x{6A50}\x{6A51}\x{6A52}\x{6A54}' - . '\x{6A55}\x{6A56}\x{6A57}\x{6A58}\x{6A59}\x{6A5A}\x{6A5B}\x{6A5D}\x{6A5E}' - . '\x{6A5F}\x{6A60}\x{6A61}\x{6A62}\x{6A63}\x{6A64}\x{6A65}\x{6A66}\x{6A67}' - . '\x{6A68}\x{6A69}\x{6A6A}\x{6A6B}\x{6A6C}\x{6A6D}\x{6A6F}\x{6A71}\x{6A72}' - . '\x{6A73}\x{6A74}\x{6A75}\x{6A76}\x{6A77}\x{6A78}\x{6A79}\x{6A7A}\x{6A7B}' - . '\x{6A7C}\x{6A7D}\x{6A7E}\x{6A7F}\x{6A80}\x{6A81}\x{6A82}\x{6A83}\x{6A84}' - . '\x{6A85}\x{6A87}\x{6A88}\x{6A89}\x{6A8B}\x{6A8C}\x{6A8D}\x{6A8E}\x{6A90}' - . '\x{6A91}\x{6A92}\x{6A93}\x{6A94}\x{6A95}\x{6A96}\x{6A97}\x{6A98}\x{6A9A}' - . '\x{6A9B}\x{6A9C}\x{6A9E}\x{6A9F}\x{6AA0}\x{6AA1}\x{6AA2}\x{6AA3}\x{6AA4}' - . '\x{6AA5}\x{6AA6}\x{6AA7}\x{6AA8}\x{6AA9}\x{6AAB}\x{6AAC}\x{6AAD}\x{6AAE}' - . '\x{6AAF}\x{6AB0}\x{6AB2}\x{6AB3}\x{6AB4}\x{6AB5}\x{6AB6}\x{6AB7}\x{6AB8}' - . '\x{6AB9}\x{6ABA}\x{6ABB}\x{6ABC}\x{6ABD}\x{6ABF}\x{6AC1}\x{6AC2}\x{6AC3}' - . '\x{6AC5}\x{6AC6}\x{6AC7}\x{6ACA}\x{6ACB}\x{6ACC}\x{6ACD}\x{6ACE}\x{6ACF}' - . '\x{6AD0}\x{6AD1}\x{6AD2}\x{6AD3}\x{6AD4}\x{6AD5}\x{6AD6}\x{6AD7}\x{6AD9}' - . '\x{6ADA}\x{6ADB}\x{6ADC}\x{6ADD}\x{6ADE}\x{6ADF}\x{6AE0}\x{6AE1}\x{6AE2}' - . '\x{6AE3}\x{6AE4}\x{6AE5}\x{6AE6}\x{6AE7}\x{6AE8}\x{6AEA}\x{6AEB}\x{6AEC}' - . '\x{6AED}\x{6AEE}\x{6AEF}\x{6AF0}\x{6AF1}\x{6AF2}\x{6AF3}\x{6AF4}\x{6AF5}' - . '\x{6AF6}\x{6AF7}\x{6AF8}\x{6AF9}\x{6AFA}\x{6AFB}\x{6AFC}\x{6AFD}\x{6AFE}' - . '\x{6AFF}\x{6B00}\x{6B01}\x{6B02}\x{6B03}\x{6B04}\x{6B05}\x{6B06}\x{6B07}' - . '\x{6B08}\x{6B09}\x{6B0A}\x{6B0B}\x{6B0C}\x{6B0D}\x{6B0F}\x{6B10}\x{6B11}' - . '\x{6B12}\x{6B13}\x{6B14}\x{6B15}\x{6B16}\x{6B17}\x{6B18}\x{6B19}\x{6B1A}' - . '\x{6B1C}\x{6B1D}\x{6B1E}\x{6B1F}\x{6B20}\x{6B21}\x{6B22}\x{6B23}\x{6B24}' - . '\x{6B25}\x{6B26}\x{6B27}\x{6B28}\x{6B29}\x{6B2A}\x{6B2B}\x{6B2C}\x{6B2D}' - . '\x{6B2F}\x{6B30}\x{6B31}\x{6B32}\x{6B33}\x{6B34}\x{6B36}\x{6B37}\x{6B38}' - . '\x{6B39}\x{6B3A}\x{6B3B}\x{6B3C}\x{6B3D}\x{6B3E}\x{6B3F}\x{6B41}\x{6B42}' - . '\x{6B43}\x{6B44}\x{6B45}\x{6B46}\x{6B47}\x{6B48}\x{6B49}\x{6B4A}\x{6B4B}' - . '\x{6B4C}\x{6B4D}\x{6B4E}\x{6B4F}\x{6B50}\x{6B51}\x{6B52}\x{6B53}\x{6B54}' - . '\x{6B55}\x{6B56}\x{6B59}\x{6B5A}\x{6B5B}\x{6B5C}\x{6B5E}\x{6B5F}\x{6B60}' - . '\x{6B61}\x{6B62}\x{6B63}\x{6B64}\x{6B65}\x{6B66}\x{6B67}\x{6B69}\x{6B6A}' - . '\x{6B6B}\x{6B6D}\x{6B6F}\x{6B70}\x{6B72}\x{6B73}\x{6B74}\x{6B76}\x{6B77}' - . '\x{6B78}\x{6B79}\x{6B7A}\x{6B7B}\x{6B7C}\x{6B7E}\x{6B7F}\x{6B80}\x{6B81}' - . '\x{6B82}\x{6B83}\x{6B84}\x{6B85}\x{6B86}\x{6B87}\x{6B88}\x{6B89}\x{6B8A}' - . '\x{6B8B}\x{6B8C}\x{6B8D}\x{6B8E}\x{6B8F}\x{6B90}\x{6B91}\x{6B92}\x{6B93}' - . '\x{6B94}\x{6B95}\x{6B96}\x{6B97}\x{6B98}\x{6B99}\x{6B9A}\x{6B9B}\x{6B9C}' - . '\x{6B9D}\x{6B9E}\x{6B9F}\x{6BA0}\x{6BA1}\x{6BA2}\x{6BA3}\x{6BA4}\x{6BA5}' - . '\x{6BA6}\x{6BA7}\x{6BA8}\x{6BA9}\x{6BAA}\x{6BAB}\x{6BAC}\x{6BAD}\x{6BAE}' - . '\x{6BAF}\x{6BB0}\x{6BB2}\x{6BB3}\x{6BB4}\x{6BB5}\x{6BB6}\x{6BB7}\x{6BB9}' - . '\x{6BBA}\x{6BBB}\x{6BBC}\x{6BBD}\x{6BBE}\x{6BBF}\x{6BC0}\x{6BC1}\x{6BC2}' - . '\x{6BC3}\x{6BC4}\x{6BC5}\x{6BC6}\x{6BC7}\x{6BC8}\x{6BC9}\x{6BCA}\x{6BCB}' - . '\x{6BCC}\x{6BCD}\x{6BCE}\x{6BCF}\x{6BD0}\x{6BD1}\x{6BD2}\x{6BD3}\x{6BD4}' - . '\x{6BD5}\x{6BD6}\x{6BD7}\x{6BD8}\x{6BD9}\x{6BDA}\x{6BDB}\x{6BDC}\x{6BDD}' - . '\x{6BDE}\x{6BDF}\x{6BE0}\x{6BE1}\x{6BE2}\x{6BE3}\x{6BE4}\x{6BE5}\x{6BE6}' - . '\x{6BE7}\x{6BE8}\x{6BEA}\x{6BEB}\x{6BEC}\x{6BED}\x{6BEE}\x{6BEF}\x{6BF0}' - . '\x{6BF2}\x{6BF3}\x{6BF5}\x{6BF6}\x{6BF7}\x{6BF8}\x{6BF9}\x{6BFB}\x{6BFC}' - . '\x{6BFD}\x{6BFE}\x{6BFF}\x{6C00}\x{6C01}\x{6C02}\x{6C03}\x{6C04}\x{6C05}' - . '\x{6C06}\x{6C07}\x{6C08}\x{6C09}\x{6C0B}\x{6C0C}\x{6C0D}\x{6C0E}\x{6C0F}' - . '\x{6C10}\x{6C11}\x{6C12}\x{6C13}\x{6C14}\x{6C15}\x{6C16}\x{6C18}\x{6C19}' - . '\x{6C1A}\x{6C1B}\x{6C1D}\x{6C1E}\x{6C1F}\x{6C20}\x{6C21}\x{6C22}\x{6C23}' - . '\x{6C24}\x{6C25}\x{6C26}\x{6C27}\x{6C28}\x{6C29}\x{6C2A}\x{6C2B}\x{6C2C}' - . '\x{6C2E}\x{6C2F}\x{6C30}\x{6C31}\x{6C32}\x{6C33}\x{6C34}\x{6C35}\x{6C36}' - . '\x{6C37}\x{6C38}\x{6C3A}\x{6C3B}\x{6C3D}\x{6C3E}\x{6C3F}\x{6C40}\x{6C41}' - . '\x{6C42}\x{6C43}\x{6C44}\x{6C46}\x{6C47}\x{6C48}\x{6C49}\x{6C4A}\x{6C4B}' - . '\x{6C4C}\x{6C4D}\x{6C4E}\x{6C4F}\x{6C50}\x{6C51}\x{6C52}\x{6C53}\x{6C54}' - . '\x{6C55}\x{6C56}\x{6C57}\x{6C58}\x{6C59}\x{6C5A}\x{6C5B}\x{6C5C}\x{6C5D}' - . '\x{6C5E}\x{6C5F}\x{6C60}\x{6C61}\x{6C62}\x{6C63}\x{6C64}\x{6C65}\x{6C66}' - . '\x{6C67}\x{6C68}\x{6C69}\x{6C6A}\x{6C6B}\x{6C6D}\x{6C6F}\x{6C70}\x{6C71}' - . '\x{6C72}\x{6C73}\x{6C74}\x{6C75}\x{6C76}\x{6C77}\x{6C78}\x{6C79}\x{6C7A}' - . '\x{6C7B}\x{6C7C}\x{6C7D}\x{6C7E}\x{6C7F}\x{6C80}\x{6C81}\x{6C82}\x{6C83}' - . '\x{6C84}\x{6C85}\x{6C86}\x{6C87}\x{6C88}\x{6C89}\x{6C8A}\x{6C8B}\x{6C8C}' - . '\x{6C8D}\x{6C8E}\x{6C8F}\x{6C90}\x{6C91}\x{6C92}\x{6C93}\x{6C94}\x{6C95}' - . '\x{6C96}\x{6C97}\x{6C98}\x{6C99}\x{6C9A}\x{6C9B}\x{6C9C}\x{6C9D}\x{6C9E}' - . '\x{6C9F}\x{6CA1}\x{6CA2}\x{6CA3}\x{6CA4}\x{6CA5}\x{6CA6}\x{6CA7}\x{6CA8}' - . '\x{6CA9}\x{6CAA}\x{6CAB}\x{6CAC}\x{6CAD}\x{6CAE}\x{6CAF}\x{6CB0}\x{6CB1}' - . '\x{6CB2}\x{6CB3}\x{6CB4}\x{6CB5}\x{6CB6}\x{6CB7}\x{6CB8}\x{6CB9}\x{6CBA}' - . '\x{6CBB}\x{6CBC}\x{6CBD}\x{6CBE}\x{6CBF}\x{6CC0}\x{6CC1}\x{6CC2}\x{6CC3}' - . '\x{6CC4}\x{6CC5}\x{6CC6}\x{6CC7}\x{6CC8}\x{6CC9}\x{6CCA}\x{6CCB}\x{6CCC}' - . '\x{6CCD}\x{6CCE}\x{6CCF}\x{6CD0}\x{6CD1}\x{6CD2}\x{6CD3}\x{6CD4}\x{6CD5}' - . '\x{6CD6}\x{6CD7}\x{6CD9}\x{6CDA}\x{6CDB}\x{6CDC}\x{6CDD}\x{6CDE}\x{6CDF}' - . '\x{6CE0}\x{6CE1}\x{6CE2}\x{6CE3}\x{6CE4}\x{6CE5}\x{6CE6}\x{6CE7}\x{6CE8}' - . '\x{6CE9}\x{6CEA}\x{6CEB}\x{6CEC}\x{6CED}\x{6CEE}\x{6CEF}\x{6CF0}\x{6CF1}' - . '\x{6CF2}\x{6CF3}\x{6CF5}\x{6CF6}\x{6CF7}\x{6CF8}\x{6CF9}\x{6CFA}\x{6CFB}' - . '\x{6CFC}\x{6CFD}\x{6CFE}\x{6CFF}\x{6D00}\x{6D01}\x{6D03}\x{6D04}\x{6D05}' - . '\x{6D06}\x{6D07}\x{6D08}\x{6D09}\x{6D0A}\x{6D0B}\x{6D0C}\x{6D0D}\x{6D0E}' - . '\x{6D0F}\x{6D10}\x{6D11}\x{6D12}\x{6D13}\x{6D14}\x{6D15}\x{6D16}\x{6D17}' - . '\x{6D18}\x{6D19}\x{6D1A}\x{6D1B}\x{6D1D}\x{6D1E}\x{6D1F}\x{6D20}\x{6D21}' - . '\x{6D22}\x{6D23}\x{6D25}\x{6D26}\x{6D27}\x{6D28}\x{6D29}\x{6D2A}\x{6D2B}' - . '\x{6D2C}\x{6D2D}\x{6D2E}\x{6D2F}\x{6D30}\x{6D31}\x{6D32}\x{6D33}\x{6D34}' - . '\x{6D35}\x{6D36}\x{6D37}\x{6D38}\x{6D39}\x{6D3A}\x{6D3B}\x{6D3C}\x{6D3D}' - . '\x{6D3E}\x{6D3F}\x{6D40}\x{6D41}\x{6D42}\x{6D43}\x{6D44}\x{6D45}\x{6D46}' - . '\x{6D47}\x{6D48}\x{6D49}\x{6D4A}\x{6D4B}\x{6D4C}\x{6D4D}\x{6D4E}\x{6D4F}' - . '\x{6D50}\x{6D51}\x{6D52}\x{6D53}\x{6D54}\x{6D55}\x{6D56}\x{6D57}\x{6D58}' - . '\x{6D59}\x{6D5A}\x{6D5B}\x{6D5C}\x{6D5D}\x{6D5E}\x{6D5F}\x{6D60}\x{6D61}' - . '\x{6D62}\x{6D63}\x{6D64}\x{6D65}\x{6D66}\x{6D67}\x{6D68}\x{6D69}\x{6D6A}' - . '\x{6D6B}\x{6D6C}\x{6D6D}\x{6D6E}\x{6D6F}\x{6D70}\x{6D72}\x{6D73}\x{6D74}' - . '\x{6D75}\x{6D76}\x{6D77}\x{6D78}\x{6D79}\x{6D7A}\x{6D7B}\x{6D7C}\x{6D7D}' - . '\x{6D7E}\x{6D7F}\x{6D80}\x{6D82}\x{6D83}\x{6D84}\x{6D85}\x{6D86}\x{6D87}' - . '\x{6D88}\x{6D89}\x{6D8A}\x{6D8B}\x{6D8C}\x{6D8D}\x{6D8E}\x{6D8F}\x{6D90}' - . '\x{6D91}\x{6D92}\x{6D93}\x{6D94}\x{6D95}\x{6D97}\x{6D98}\x{6D99}\x{6D9A}' - . '\x{6D9B}\x{6D9D}\x{6D9E}\x{6D9F}\x{6DA0}\x{6DA1}\x{6DA2}\x{6DA3}\x{6DA4}' - . '\x{6DA5}\x{6DA6}\x{6DA7}\x{6DA8}\x{6DA9}\x{6DAA}\x{6DAB}\x{6DAC}\x{6DAD}' - . '\x{6DAE}\x{6DAF}\x{6DB2}\x{6DB3}\x{6DB4}\x{6DB5}\x{6DB7}\x{6DB8}\x{6DB9}' - . '\x{6DBA}\x{6DBB}\x{6DBC}\x{6DBD}\x{6DBE}\x{6DBF}\x{6DC0}\x{6DC1}\x{6DC2}' - . '\x{6DC3}\x{6DC4}\x{6DC5}\x{6DC6}\x{6DC7}\x{6DC8}\x{6DC9}\x{6DCA}\x{6DCB}' - . '\x{6DCC}\x{6DCD}\x{6DCE}\x{6DCF}\x{6DD0}\x{6DD1}\x{6DD2}\x{6DD3}\x{6DD4}' - . '\x{6DD5}\x{6DD6}\x{6DD7}\x{6DD8}\x{6DD9}\x{6DDA}\x{6DDB}\x{6DDC}\x{6DDD}' - . '\x{6DDE}\x{6DDF}\x{6DE0}\x{6DE1}\x{6DE2}\x{6DE3}\x{6DE4}\x{6DE5}\x{6DE6}' - . '\x{6DE7}\x{6DE8}\x{6DE9}\x{6DEA}\x{6DEB}\x{6DEC}\x{6DED}\x{6DEE}\x{6DEF}' - . '\x{6DF0}\x{6DF1}\x{6DF2}\x{6DF3}\x{6DF4}\x{6DF5}\x{6DF6}\x{6DF7}\x{6DF8}' - . '\x{6DF9}\x{6DFA}\x{6DFB}\x{6DFC}\x{6DFD}\x{6E00}\x{6E03}\x{6E04}\x{6E05}' - . '\x{6E07}\x{6E08}\x{6E09}\x{6E0A}\x{6E0B}\x{6E0C}\x{6E0D}\x{6E0E}\x{6E0F}' - . '\x{6E10}\x{6E11}\x{6E14}\x{6E15}\x{6E16}\x{6E17}\x{6E19}\x{6E1A}\x{6E1B}' - . '\x{6E1C}\x{6E1D}\x{6E1E}\x{6E1F}\x{6E20}\x{6E21}\x{6E22}\x{6E23}\x{6E24}' - . '\x{6E25}\x{6E26}\x{6E27}\x{6E28}\x{6E29}\x{6E2B}\x{6E2C}\x{6E2D}\x{6E2E}' - . '\x{6E2F}\x{6E30}\x{6E31}\x{6E32}\x{6E33}\x{6E34}\x{6E35}\x{6E36}\x{6E37}' - . '\x{6E38}\x{6E39}\x{6E3A}\x{6E3B}\x{6E3C}\x{6E3D}\x{6E3E}\x{6E3F}\x{6E40}' - . '\x{6E41}\x{6E42}\x{6E43}\x{6E44}\x{6E45}\x{6E46}\x{6E47}\x{6E48}\x{6E49}' - . '\x{6E4A}\x{6E4B}\x{6E4D}\x{6E4E}\x{6E4F}\x{6E50}\x{6E51}\x{6E52}\x{6E53}' - . '\x{6E54}\x{6E55}\x{6E56}\x{6E57}\x{6E58}\x{6E59}\x{6E5A}\x{6E5B}\x{6E5C}' - . '\x{6E5D}\x{6E5E}\x{6E5F}\x{6E60}\x{6E61}\x{6E62}\x{6E63}\x{6E64}\x{6E65}' - . '\x{6E66}\x{6E67}\x{6E68}\x{6E69}\x{6E6A}\x{6E6B}\x{6E6D}\x{6E6E}\x{6E6F}' - . '\x{6E70}\x{6E71}\x{6E72}\x{6E73}\x{6E74}\x{6E75}\x{6E77}\x{6E78}\x{6E79}' - . '\x{6E7E}\x{6E7F}\x{6E80}\x{6E81}\x{6E82}\x{6E83}\x{6E84}\x{6E85}\x{6E86}' - . '\x{6E87}\x{6E88}\x{6E89}\x{6E8A}\x{6E8D}\x{6E8E}\x{6E8F}\x{6E90}\x{6E91}' - . '\x{6E92}\x{6E93}\x{6E94}\x{6E96}\x{6E97}\x{6E98}\x{6E99}\x{6E9A}\x{6E9B}' - . '\x{6E9C}\x{6E9D}\x{6E9E}\x{6E9F}\x{6EA0}\x{6EA1}\x{6EA2}\x{6EA3}\x{6EA4}' - . '\x{6EA5}\x{6EA6}\x{6EA7}\x{6EA8}\x{6EA9}\x{6EAA}\x{6EAB}\x{6EAC}\x{6EAD}' - . '\x{6EAE}\x{6EAF}\x{6EB0}\x{6EB1}\x{6EB2}\x{6EB3}\x{6EB4}\x{6EB5}\x{6EB6}' - . '\x{6EB7}\x{6EB8}\x{6EB9}\x{6EBA}\x{6EBB}\x{6EBC}\x{6EBD}\x{6EBE}\x{6EBF}' - . '\x{6EC0}\x{6EC1}\x{6EC2}\x{6EC3}\x{6EC4}\x{6EC5}\x{6EC6}\x{6EC7}\x{6EC8}' - . '\x{6EC9}\x{6ECA}\x{6ECB}\x{6ECC}\x{6ECD}\x{6ECE}\x{6ECF}\x{6ED0}\x{6ED1}' - . '\x{6ED2}\x{6ED3}\x{6ED4}\x{6ED5}\x{6ED6}\x{6ED7}\x{6ED8}\x{6ED9}\x{6EDA}' - . '\x{6EDC}\x{6EDE}\x{6EDF}\x{6EE0}\x{6EE1}\x{6EE2}\x{6EE4}\x{6EE5}\x{6EE6}' - . '\x{6EE7}\x{6EE8}\x{6EE9}\x{6EEA}\x{6EEB}\x{6EEC}\x{6EED}\x{6EEE}\x{6EEF}' - . '\x{6EF0}\x{6EF1}\x{6EF2}\x{6EF3}\x{6EF4}\x{6EF5}\x{6EF6}\x{6EF7}\x{6EF8}' - . '\x{6EF9}\x{6EFA}\x{6EFB}\x{6EFC}\x{6EFD}\x{6EFE}\x{6EFF}\x{6F00}\x{6F01}' - . '\x{6F02}\x{6F03}\x{6F05}\x{6F06}\x{6F07}\x{6F08}\x{6F09}\x{6F0A}\x{6F0C}' - . '\x{6F0D}\x{6F0E}\x{6F0F}\x{6F10}\x{6F11}\x{6F12}\x{6F13}\x{6F14}\x{6F15}' - . '\x{6F16}\x{6F17}\x{6F18}\x{6F19}\x{6F1A}\x{6F1B}\x{6F1C}\x{6F1D}\x{6F1E}' - . '\x{6F1F}\x{6F20}\x{6F21}\x{6F22}\x{6F23}\x{6F24}\x{6F25}\x{6F26}\x{6F27}' - . '\x{6F28}\x{6F29}\x{6F2A}\x{6F2B}\x{6F2C}\x{6F2D}\x{6F2E}\x{6F2F}\x{6F30}' - . '\x{6F31}\x{6F32}\x{6F33}\x{6F34}\x{6F35}\x{6F36}\x{6F37}\x{6F38}\x{6F39}' - . '\x{6F3A}\x{6F3B}\x{6F3C}\x{6F3D}\x{6F3E}\x{6F3F}\x{6F40}\x{6F41}\x{6F43}' - . '\x{6F44}\x{6F45}\x{6F46}\x{6F47}\x{6F49}\x{6F4B}\x{6F4C}\x{6F4D}\x{6F4E}' - . '\x{6F4F}\x{6F50}\x{6F51}\x{6F52}\x{6F53}\x{6F54}\x{6F55}\x{6F56}\x{6F57}' - . '\x{6F58}\x{6F59}\x{6F5A}\x{6F5B}\x{6F5C}\x{6F5D}\x{6F5E}\x{6F5F}\x{6F60}' - . '\x{6F61}\x{6F62}\x{6F63}\x{6F64}\x{6F65}\x{6F66}\x{6F67}\x{6F68}\x{6F69}' - . '\x{6F6A}\x{6F6B}\x{6F6C}\x{6F6D}\x{6F6E}\x{6F6F}\x{6F70}\x{6F71}\x{6F72}' - . '\x{6F73}\x{6F74}\x{6F75}\x{6F76}\x{6F77}\x{6F78}\x{6F7A}\x{6F7B}\x{6F7C}' - . '\x{6F7D}\x{6F7E}\x{6F7F}\x{6F80}\x{6F81}\x{6F82}\x{6F83}\x{6F84}\x{6F85}' - . '\x{6F86}\x{6F87}\x{6F88}\x{6F89}\x{6F8A}\x{6F8B}\x{6F8C}\x{6F8D}\x{6F8E}' - . '\x{6F8F}\x{6F90}\x{6F91}\x{6F92}\x{6F93}\x{6F94}\x{6F95}\x{6F96}\x{6F97}' - . '\x{6F99}\x{6F9B}\x{6F9C}\x{6F9D}\x{6F9E}\x{6FA0}\x{6FA1}\x{6FA2}\x{6FA3}' - . '\x{6FA4}\x{6FA5}\x{6FA6}\x{6FA7}\x{6FA8}\x{6FA9}\x{6FAA}\x{6FAB}\x{6FAC}' - . '\x{6FAD}\x{6FAE}\x{6FAF}\x{6FB0}\x{6FB1}\x{6FB2}\x{6FB3}\x{6FB4}\x{6FB5}' - . '\x{6FB6}\x{6FB8}\x{6FB9}\x{6FBA}\x{6FBB}\x{6FBC}\x{6FBD}\x{6FBE}\x{6FBF}' - . '\x{6FC0}\x{6FC1}\x{6FC2}\x{6FC3}\x{6FC4}\x{6FC6}\x{6FC7}\x{6FC8}\x{6FC9}' - . '\x{6FCA}\x{6FCB}\x{6FCC}\x{6FCD}\x{6FCE}\x{6FCF}\x{6FD1}\x{6FD2}\x{6FD4}' - . '\x{6FD5}\x{6FD6}\x{6FD7}\x{6FD8}\x{6FD9}\x{6FDA}\x{6FDB}\x{6FDC}\x{6FDD}' - . '\x{6FDE}\x{6FDF}\x{6FE0}\x{6FE1}\x{6FE2}\x{6FE3}\x{6FE4}\x{6FE5}\x{6FE6}' - . '\x{6FE7}\x{6FE8}\x{6FE9}\x{6FEA}\x{6FEB}\x{6FEC}\x{6FED}\x{6FEE}\x{6FEF}' - . '\x{6FF0}\x{6FF1}\x{6FF2}\x{6FF3}\x{6FF4}\x{6FF6}\x{6FF7}\x{6FF8}\x{6FF9}' - . '\x{6FFA}\x{6FFB}\x{6FFC}\x{6FFE}\x{6FFF}\x{7000}\x{7001}\x{7002}\x{7003}' - . '\x{7004}\x{7005}\x{7006}\x{7007}\x{7008}\x{7009}\x{700A}\x{700B}\x{700C}' - . '\x{700D}\x{700E}\x{700F}\x{7011}\x{7012}\x{7014}\x{7015}\x{7016}\x{7017}' - . '\x{7018}\x{7019}\x{701A}\x{701B}\x{701C}\x{701D}\x{701F}\x{7020}\x{7021}' - . '\x{7022}\x{7023}\x{7024}\x{7025}\x{7026}\x{7027}\x{7028}\x{7029}\x{702A}' - . '\x{702B}\x{702C}\x{702D}\x{702E}\x{702F}\x{7030}\x{7031}\x{7032}\x{7033}' - . '\x{7034}\x{7035}\x{7036}\x{7037}\x{7038}\x{7039}\x{703A}\x{703B}\x{703C}' - . '\x{703D}\x{703E}\x{703F}\x{7040}\x{7041}\x{7042}\x{7043}\x{7044}\x{7045}' - . '\x{7046}\x{7048}\x{7049}\x{704A}\x{704C}\x{704D}\x{704F}\x{7050}\x{7051}' - . '\x{7052}\x{7053}\x{7054}\x{7055}\x{7056}\x{7057}\x{7058}\x{7059}\x{705A}' - . '\x{705B}\x{705C}\x{705D}\x{705E}\x{705F}\x{7060}\x{7061}\x{7062}\x{7063}' - . '\x{7064}\x{7065}\x{7066}\x{7067}\x{7068}\x{7069}\x{706A}\x{706B}\x{706C}' - . '\x{706D}\x{706E}\x{706F}\x{7070}\x{7071}\x{7074}\x{7075}\x{7076}\x{7077}' - . '\x{7078}\x{7079}\x{707A}\x{707C}\x{707D}\x{707E}\x{707F}\x{7080}\x{7082}' - . '\x{7083}\x{7084}\x{7085}\x{7086}\x{7087}\x{7088}\x{7089}\x{708A}\x{708B}' - . '\x{708C}\x{708E}\x{708F}\x{7090}\x{7091}\x{7092}\x{7093}\x{7094}\x{7095}' - . '\x{7096}\x{7098}\x{7099}\x{709A}\x{709C}\x{709D}\x{709E}\x{709F}\x{70A0}' - . '\x{70A1}\x{70A2}\x{70A3}\x{70A4}\x{70A5}\x{70A6}\x{70A7}\x{70A8}\x{70A9}' - . '\x{70AB}\x{70AC}\x{70AD}\x{70AE}\x{70AF}\x{70B0}\x{70B1}\x{70B3}\x{70B4}' - . '\x{70B5}\x{70B7}\x{70B8}\x{70B9}\x{70BA}\x{70BB}\x{70BC}\x{70BD}\x{70BE}' - . '\x{70BF}\x{70C0}\x{70C1}\x{70C2}\x{70C3}\x{70C4}\x{70C5}\x{70C6}\x{70C7}' - . '\x{70C8}\x{70C9}\x{70CA}\x{70CB}\x{70CC}\x{70CD}\x{70CE}\x{70CF}\x{70D0}' - . '\x{70D1}\x{70D2}\x{70D3}\x{70D4}\x{70D6}\x{70D7}\x{70D8}\x{70D9}\x{70DA}' - . '\x{70DB}\x{70DC}\x{70DD}\x{70DE}\x{70DF}\x{70E0}\x{70E1}\x{70E2}\x{70E3}' - . '\x{70E4}\x{70E5}\x{70E6}\x{70E7}\x{70E8}\x{70E9}\x{70EA}\x{70EB}\x{70EC}' - . '\x{70ED}\x{70EE}\x{70EF}\x{70F0}\x{70F1}\x{70F2}\x{70F3}\x{70F4}\x{70F5}' - . '\x{70F6}\x{70F7}\x{70F8}\x{70F9}\x{70FA}\x{70FB}\x{70FC}\x{70FD}\x{70FF}' - . '\x{7100}\x{7101}\x{7102}\x{7103}\x{7104}\x{7105}\x{7106}\x{7107}\x{7109}' - . '\x{710A}\x{710B}\x{710C}\x{710D}\x{710E}\x{710F}\x{7110}\x{7111}\x{7112}' - . '\x{7113}\x{7115}\x{7116}\x{7117}\x{7118}\x{7119}\x{711A}\x{711B}\x{711C}' - . '\x{711D}\x{711E}\x{711F}\x{7120}\x{7121}\x{7122}\x{7123}\x{7125}\x{7126}' - . '\x{7127}\x{7128}\x{7129}\x{712A}\x{712B}\x{712C}\x{712D}\x{712E}\x{712F}' - . '\x{7130}\x{7131}\x{7132}\x{7135}\x{7136}\x{7137}\x{7138}\x{7139}\x{713A}' - . '\x{713B}\x{713D}\x{713E}\x{713F}\x{7140}\x{7141}\x{7142}\x{7143}\x{7144}' - . '\x{7145}\x{7146}\x{7147}\x{7148}\x{7149}\x{714A}\x{714B}\x{714C}\x{714D}' - . '\x{714E}\x{714F}\x{7150}\x{7151}\x{7152}\x{7153}\x{7154}\x{7156}\x{7158}' - . '\x{7159}\x{715A}\x{715B}\x{715C}\x{715D}\x{715E}\x{715F}\x{7160}\x{7161}' - . '\x{7162}\x{7163}\x{7164}\x{7165}\x{7166}\x{7167}\x{7168}\x{7169}\x{716A}' - . '\x{716C}\x{716E}\x{716F}\x{7170}\x{7171}\x{7172}\x{7173}\x{7174}\x{7175}' - . '\x{7176}\x{7177}\x{7178}\x{7179}\x{717A}\x{717B}\x{717C}\x{717D}\x{717E}' - . '\x{717F}\x{7180}\x{7181}\x{7182}\x{7183}\x{7184}\x{7185}\x{7186}\x{7187}' - . '\x{7188}\x{7189}\x{718A}\x{718B}\x{718C}\x{718E}\x{718F}\x{7190}\x{7191}' - . '\x{7192}\x{7193}\x{7194}\x{7195}\x{7197}\x{7198}\x{7199}\x{719A}\x{719B}' - . '\x{719C}\x{719D}\x{719E}\x{719F}\x{71A0}\x{71A1}\x{71A2}\x{71A3}\x{71A4}' - . '\x{71A5}\x{71A7}\x{71A8}\x{71A9}\x{71AA}\x{71AC}\x{71AD}\x{71AE}\x{71AF}' - . '\x{71B0}\x{71B1}\x{71B2}\x{71B3}\x{71B4}\x{71B5}\x{71B7}\x{71B8}\x{71B9}' - . '\x{71BA}\x{71BB}\x{71BC}\x{71BD}\x{71BE}\x{71BF}\x{71C0}\x{71C1}\x{71C2}' - . '\x{71C3}\x{71C4}\x{71C5}\x{71C6}\x{71C7}\x{71C8}\x{71C9}\x{71CA}\x{71CB}' - . '\x{71CD}\x{71CE}\x{71CF}\x{71D0}\x{71D1}\x{71D2}\x{71D4}\x{71D5}\x{71D6}' - . '\x{71D7}\x{71D8}\x{71D9}\x{71DA}\x{71DB}\x{71DC}\x{71DD}\x{71DE}\x{71DF}' - . '\x{71E0}\x{71E1}\x{71E2}\x{71E3}\x{71E4}\x{71E5}\x{71E6}\x{71E7}\x{71E8}' - . '\x{71E9}\x{71EA}\x{71EB}\x{71EC}\x{71ED}\x{71EE}\x{71EF}\x{71F0}\x{71F1}' - . '\x{71F2}\x{71F4}\x{71F5}\x{71F6}\x{71F7}\x{71F8}\x{71F9}\x{71FB}\x{71FC}' - . '\x{71FD}\x{71FE}\x{71FF}\x{7201}\x{7202}\x{7203}\x{7204}\x{7205}\x{7206}' - . '\x{7207}\x{7208}\x{7209}\x{720A}\x{720C}\x{720D}\x{720E}\x{720F}\x{7210}' - . '\x{7212}\x{7213}\x{7214}\x{7216}\x{7218}\x{7219}\x{721A}\x{721B}\x{721C}' - . '\x{721D}\x{721E}\x{721F}\x{7221}\x{7222}\x{7223}\x{7226}\x{7227}\x{7228}' - . '\x{7229}\x{722A}\x{722B}\x{722C}\x{722D}\x{722E}\x{7230}\x{7231}\x{7232}' - . '\x{7233}\x{7235}\x{7236}\x{7237}\x{7238}\x{7239}\x{723A}\x{723B}\x{723C}' - . '\x{723D}\x{723E}\x{723F}\x{7240}\x{7241}\x{7242}\x{7243}\x{7244}\x{7246}' - . '\x{7247}\x{7248}\x{7249}\x{724A}\x{724B}\x{724C}\x{724D}\x{724F}\x{7251}' - . '\x{7252}\x{7253}\x{7254}\x{7256}\x{7257}\x{7258}\x{7259}\x{725A}\x{725B}' - . '\x{725C}\x{725D}\x{725E}\x{725F}\x{7260}\x{7261}\x{7262}\x{7263}\x{7264}' - . '\x{7265}\x{7266}\x{7267}\x{7268}\x{7269}\x{726A}\x{726B}\x{726C}\x{726D}' - . '\x{726E}\x{726F}\x{7270}\x{7271}\x{7272}\x{7273}\x{7274}\x{7275}\x{7276}' - . '\x{7277}\x{7278}\x{7279}\x{727A}\x{727B}\x{727C}\x{727D}\x{727E}\x{727F}' - . '\x{7280}\x{7281}\x{7282}\x{7283}\x{7284}\x{7285}\x{7286}\x{7287}\x{7288}' - . '\x{7289}\x{728A}\x{728B}\x{728C}\x{728D}\x{728E}\x{728F}\x{7290}\x{7291}' - . '\x{7292}\x{7293}\x{7294}\x{7295}\x{7296}\x{7297}\x{7298}\x{7299}\x{729A}' - . '\x{729B}\x{729C}\x{729D}\x{729E}\x{729F}\x{72A1}\x{72A2}\x{72A3}\x{72A4}' - . '\x{72A5}\x{72A6}\x{72A7}\x{72A8}\x{72A9}\x{72AA}\x{72AC}\x{72AD}\x{72AE}' - . '\x{72AF}\x{72B0}\x{72B1}\x{72B2}\x{72B3}\x{72B4}\x{72B5}\x{72B6}\x{72B7}' - . '\x{72B8}\x{72B9}\x{72BA}\x{72BB}\x{72BC}\x{72BD}\x{72BF}\x{72C0}\x{72C1}' - . '\x{72C2}\x{72C3}\x{72C4}\x{72C5}\x{72C6}\x{72C7}\x{72C8}\x{72C9}\x{72CA}' - . '\x{72CB}\x{72CC}\x{72CD}\x{72CE}\x{72CF}\x{72D0}\x{72D1}\x{72D2}\x{72D3}' - . '\x{72D4}\x{72D5}\x{72D6}\x{72D7}\x{72D8}\x{72D9}\x{72DA}\x{72DB}\x{72DC}' - . '\x{72DD}\x{72DE}\x{72DF}\x{72E0}\x{72E1}\x{72E2}\x{72E3}\x{72E4}\x{72E5}' - . '\x{72E6}\x{72E7}\x{72E8}\x{72E9}\x{72EA}\x{72EB}\x{72EC}\x{72ED}\x{72EE}' - . '\x{72EF}\x{72F0}\x{72F1}\x{72F2}\x{72F3}\x{72F4}\x{72F5}\x{72F6}\x{72F7}' - . '\x{72F8}\x{72F9}\x{72FA}\x{72FB}\x{72FC}\x{72FD}\x{72FE}\x{72FF}\x{7300}' - . '\x{7301}\x{7303}\x{7304}\x{7305}\x{7306}\x{7307}\x{7308}\x{7309}\x{730A}' - . '\x{730B}\x{730C}\x{730D}\x{730E}\x{730F}\x{7311}\x{7312}\x{7313}\x{7314}' - . '\x{7315}\x{7316}\x{7317}\x{7318}\x{7319}\x{731A}\x{731B}\x{731C}\x{731D}' - . '\x{731E}\x{7320}\x{7321}\x{7322}\x{7323}\x{7324}\x{7325}\x{7326}\x{7327}' - . '\x{7329}\x{732A}\x{732B}\x{732C}\x{732D}\x{732E}\x{7330}\x{7331}\x{7332}' - . '\x{7333}\x{7334}\x{7335}\x{7336}\x{7337}\x{7338}\x{7339}\x{733A}\x{733B}' - . '\x{733C}\x{733D}\x{733E}\x{733F}\x{7340}\x{7341}\x{7342}\x{7343}\x{7344}' - . '\x{7345}\x{7346}\x{7347}\x{7348}\x{7349}\x{734A}\x{734B}\x{734C}\x{734D}' - . '\x{734E}\x{7350}\x{7351}\x{7352}\x{7354}\x{7355}\x{7356}\x{7357}\x{7358}' - . '\x{7359}\x{735A}\x{735B}\x{735C}\x{735D}\x{735E}\x{735F}\x{7360}\x{7361}' - . '\x{7362}\x{7364}\x{7365}\x{7366}\x{7367}\x{7368}\x{7369}\x{736A}\x{736B}' - . '\x{736C}\x{736D}\x{736E}\x{736F}\x{7370}\x{7371}\x{7372}\x{7373}\x{7374}' - . '\x{7375}\x{7376}\x{7377}\x{7378}\x{7379}\x{737A}\x{737B}\x{737C}\x{737D}' - . '\x{737E}\x{737F}\x{7380}\x{7381}\x{7382}\x{7383}\x{7384}\x{7385}\x{7386}' - . '\x{7387}\x{7388}\x{7389}\x{738A}\x{738B}\x{738C}\x{738D}\x{738E}\x{738F}' - . '\x{7390}\x{7391}\x{7392}\x{7393}\x{7394}\x{7395}\x{7396}\x{7397}\x{7398}' - . '\x{7399}\x{739A}\x{739B}\x{739D}\x{739E}\x{739F}\x{73A0}\x{73A1}\x{73A2}' - . '\x{73A3}\x{73A4}\x{73A5}\x{73A6}\x{73A7}\x{73A8}\x{73A9}\x{73AA}\x{73AB}' - . '\x{73AC}\x{73AD}\x{73AE}\x{73AF}\x{73B0}\x{73B1}\x{73B2}\x{73B3}\x{73B4}' - . '\x{73B5}\x{73B6}\x{73B7}\x{73B8}\x{73B9}\x{73BA}\x{73BB}\x{73BC}\x{73BD}' - . '\x{73BE}\x{73BF}\x{73C0}\x{73C2}\x{73C3}\x{73C4}\x{73C5}\x{73C6}\x{73C7}' - . '\x{73C8}\x{73C9}\x{73CA}\x{73CB}\x{73CC}\x{73CD}\x{73CE}\x{73CF}\x{73D0}' - . '\x{73D1}\x{73D2}\x{73D3}\x{73D4}\x{73D5}\x{73D6}\x{73D7}\x{73D8}\x{73D9}' - . '\x{73DA}\x{73DB}\x{73DC}\x{73DD}\x{73DE}\x{73DF}\x{73E0}\x{73E2}\x{73E3}' - . '\x{73E5}\x{73E6}\x{73E7}\x{73E8}\x{73E9}\x{73EA}\x{73EB}\x{73EC}\x{73ED}' - . '\x{73EE}\x{73EF}\x{73F0}\x{73F1}\x{73F2}\x{73F4}\x{73F5}\x{73F6}\x{73F7}' - . '\x{73F8}\x{73F9}\x{73FA}\x{73FC}\x{73FD}\x{73FE}\x{73FF}\x{7400}\x{7401}' - . '\x{7402}\x{7403}\x{7404}\x{7405}\x{7406}\x{7407}\x{7408}\x{7409}\x{740A}' - . '\x{740B}\x{740C}\x{740D}\x{740E}\x{740F}\x{7410}\x{7411}\x{7412}\x{7413}' - . '\x{7414}\x{7415}\x{7416}\x{7417}\x{7419}\x{741A}\x{741B}\x{741C}\x{741D}' - . '\x{741E}\x{741F}\x{7420}\x{7421}\x{7422}\x{7423}\x{7424}\x{7425}\x{7426}' - . '\x{7427}\x{7428}\x{7429}\x{742A}\x{742B}\x{742C}\x{742D}\x{742E}\x{742F}' - . '\x{7430}\x{7431}\x{7432}\x{7433}\x{7434}\x{7435}\x{7436}\x{7437}\x{7438}' - . '\x{743A}\x{743B}\x{743C}\x{743D}\x{743F}\x{7440}\x{7441}\x{7442}\x{7443}' - . '\x{7444}\x{7445}\x{7446}\x{7448}\x{744A}\x{744B}\x{744C}\x{744D}\x{744E}' - . '\x{744F}\x{7450}\x{7451}\x{7452}\x{7453}\x{7454}\x{7455}\x{7456}\x{7457}' - . '\x{7459}\x{745A}\x{745B}\x{745C}\x{745D}\x{745E}\x{745F}\x{7461}\x{7462}' - . '\x{7463}\x{7464}\x{7465}\x{7466}\x{7467}\x{7468}\x{7469}\x{746A}\x{746B}' - . '\x{746C}\x{746D}\x{746E}\x{746F}\x{7470}\x{7471}\x{7472}\x{7473}\x{7474}' - . '\x{7475}\x{7476}\x{7477}\x{7478}\x{7479}\x{747A}\x{747C}\x{747D}\x{747E}' - . '\x{747F}\x{7480}\x{7481}\x{7482}\x{7483}\x{7485}\x{7486}\x{7487}\x{7488}' - . '\x{7489}\x{748A}\x{748B}\x{748C}\x{748D}\x{748E}\x{748F}\x{7490}\x{7491}' - . '\x{7492}\x{7493}\x{7494}\x{7495}\x{7497}\x{7498}\x{7499}\x{749A}\x{749B}' - . '\x{749C}\x{749E}\x{749F}\x{74A0}\x{74A1}\x{74A3}\x{74A4}\x{74A5}\x{74A6}' - . '\x{74A7}\x{74A8}\x{74A9}\x{74AA}\x{74AB}\x{74AC}\x{74AD}\x{74AE}\x{74AF}' - . '\x{74B0}\x{74B1}\x{74B2}\x{74B3}\x{74B4}\x{74B5}\x{74B6}\x{74B7}\x{74B8}' - . '\x{74B9}\x{74BA}\x{74BB}\x{74BC}\x{74BD}\x{74BE}\x{74BF}\x{74C0}\x{74C1}' - . '\x{74C2}\x{74C3}\x{74C4}\x{74C5}\x{74C6}\x{74CA}\x{74CB}\x{74CD}\x{74CE}' - . '\x{74CF}\x{74D0}\x{74D1}\x{74D2}\x{74D3}\x{74D4}\x{74D5}\x{74D6}\x{74D7}' - . '\x{74D8}\x{74D9}\x{74DA}\x{74DB}\x{74DC}\x{74DD}\x{74DE}\x{74DF}\x{74E0}' - . '\x{74E1}\x{74E2}\x{74E3}\x{74E4}\x{74E5}\x{74E6}\x{74E7}\x{74E8}\x{74E9}' - . '\x{74EA}\x{74EC}\x{74ED}\x{74EE}\x{74EF}\x{74F0}\x{74F1}\x{74F2}\x{74F3}' - . '\x{74F4}\x{74F5}\x{74F6}\x{74F7}\x{74F8}\x{74F9}\x{74FA}\x{74FB}\x{74FC}' - . '\x{74FD}\x{74FE}\x{74FF}\x{7500}\x{7501}\x{7502}\x{7503}\x{7504}\x{7505}' - . '\x{7506}\x{7507}\x{7508}\x{7509}\x{750A}\x{750B}\x{750C}\x{750D}\x{750F}' - . '\x{7510}\x{7511}\x{7512}\x{7513}\x{7514}\x{7515}\x{7516}\x{7517}\x{7518}' - . '\x{7519}\x{751A}\x{751B}\x{751C}\x{751D}\x{751E}\x{751F}\x{7521}\x{7522}' - . '\x{7523}\x{7524}\x{7525}\x{7526}\x{7527}\x{7528}\x{7529}\x{752A}\x{752B}' - . '\x{752C}\x{752D}\x{752E}\x{752F}\x{7530}\x{7531}\x{7532}\x{7533}\x{7535}' - . '\x{7536}\x{7537}\x{7538}\x{7539}\x{753A}\x{753B}\x{753C}\x{753D}\x{753E}' - . '\x{753F}\x{7540}\x{7542}\x{7543}\x{7544}\x{7545}\x{7546}\x{7547}\x{7548}' - . '\x{7549}\x{754B}\x{754C}\x{754D}\x{754E}\x{754F}\x{7550}\x{7551}\x{7553}' - . '\x{7554}\x{7556}\x{7557}\x{7558}\x{7559}\x{755A}\x{755B}\x{755C}\x{755D}' - . '\x{755F}\x{7560}\x{7562}\x{7563}\x{7564}\x{7565}\x{7566}\x{7567}\x{7568}' - . '\x{7569}\x{756A}\x{756B}\x{756C}\x{756D}\x{756E}\x{756F}\x{7570}\x{7572}' - . '\x{7574}\x{7575}\x{7576}\x{7577}\x{7578}\x{7579}\x{757C}\x{757D}\x{757E}' - . '\x{757F}\x{7580}\x{7581}\x{7582}\x{7583}\x{7584}\x{7586}\x{7587}\x{7588}' - . '\x{7589}\x{758A}\x{758B}\x{758C}\x{758D}\x{758F}\x{7590}\x{7591}\x{7592}' - . '\x{7593}\x{7594}\x{7595}\x{7596}\x{7597}\x{7598}\x{7599}\x{759A}\x{759B}' - . '\x{759C}\x{759D}\x{759E}\x{759F}\x{75A0}\x{75A1}\x{75A2}\x{75A3}\x{75A4}' - . '\x{75A5}\x{75A6}\x{75A7}\x{75A8}\x{75AA}\x{75AB}\x{75AC}\x{75AD}\x{75AE}' - . '\x{75AF}\x{75B0}\x{75B1}\x{75B2}\x{75B3}\x{75B4}\x{75B5}\x{75B6}\x{75B8}' - . '\x{75B9}\x{75BA}\x{75BB}\x{75BC}\x{75BD}\x{75BE}\x{75BF}\x{75C0}\x{75C1}' - . '\x{75C2}\x{75C3}\x{75C4}\x{75C5}\x{75C6}\x{75C7}\x{75C8}\x{75C9}\x{75CA}' - . '\x{75CB}\x{75CC}\x{75CD}\x{75CE}\x{75CF}\x{75D0}\x{75D1}\x{75D2}\x{75D3}' - . '\x{75D4}\x{75D5}\x{75D6}\x{75D7}\x{75D8}\x{75D9}\x{75DA}\x{75DB}\x{75DD}' - . '\x{75DE}\x{75DF}\x{75E0}\x{75E1}\x{75E2}\x{75E3}\x{75E4}\x{75E5}\x{75E6}' - . '\x{75E7}\x{75E8}\x{75EA}\x{75EB}\x{75EC}\x{75ED}\x{75EF}\x{75F0}\x{75F1}' - . '\x{75F2}\x{75F3}\x{75F4}\x{75F5}\x{75F6}\x{75F7}\x{75F8}\x{75F9}\x{75FA}' - . '\x{75FB}\x{75FC}\x{75FD}\x{75FE}\x{75FF}\x{7600}\x{7601}\x{7602}\x{7603}' - . '\x{7604}\x{7605}\x{7606}\x{7607}\x{7608}\x{7609}\x{760A}\x{760B}\x{760C}' - . '\x{760D}\x{760E}\x{760F}\x{7610}\x{7611}\x{7612}\x{7613}\x{7614}\x{7615}' - . '\x{7616}\x{7617}\x{7618}\x{7619}\x{761A}\x{761B}\x{761C}\x{761D}\x{761E}' - . '\x{761F}\x{7620}\x{7621}\x{7622}\x{7623}\x{7624}\x{7625}\x{7626}\x{7627}' - . '\x{7628}\x{7629}\x{762A}\x{762B}\x{762D}\x{762E}\x{762F}\x{7630}\x{7631}' - . '\x{7632}\x{7633}\x{7634}\x{7635}\x{7636}\x{7637}\x{7638}\x{7639}\x{763A}' - . '\x{763B}\x{763C}\x{763D}\x{763E}\x{763F}\x{7640}\x{7641}\x{7642}\x{7643}' - . '\x{7646}\x{7647}\x{7648}\x{7649}\x{764A}\x{764B}\x{764C}\x{764D}\x{764F}' - . '\x{7650}\x{7652}\x{7653}\x{7654}\x{7656}\x{7657}\x{7658}\x{7659}\x{765A}' - . '\x{765B}\x{765C}\x{765D}\x{765E}\x{765F}\x{7660}\x{7661}\x{7662}\x{7663}' - . '\x{7664}\x{7665}\x{7666}\x{7667}\x{7668}\x{7669}\x{766A}\x{766B}\x{766C}' - . '\x{766D}\x{766E}\x{766F}\x{7670}\x{7671}\x{7672}\x{7674}\x{7675}\x{7676}' - . '\x{7677}\x{7678}\x{7679}\x{767B}\x{767C}\x{767D}\x{767E}\x{767F}\x{7680}' - . '\x{7681}\x{7682}\x{7683}\x{7684}\x{7685}\x{7686}\x{7687}\x{7688}\x{7689}' - . '\x{768A}\x{768B}\x{768C}\x{768E}\x{768F}\x{7690}\x{7691}\x{7692}\x{7693}' - . '\x{7694}\x{7695}\x{7696}\x{7697}\x{7698}\x{7699}\x{769A}\x{769B}\x{769C}' - . '\x{769D}\x{769E}\x{769F}\x{76A0}\x{76A3}\x{76A4}\x{76A6}\x{76A7}\x{76A9}' - . '\x{76AA}\x{76AB}\x{76AC}\x{76AD}\x{76AE}\x{76AF}\x{76B0}\x{76B1}\x{76B2}' - . '\x{76B4}\x{76B5}\x{76B7}\x{76B8}\x{76BA}\x{76BB}\x{76BC}\x{76BD}\x{76BE}' - . '\x{76BF}\x{76C0}\x{76C2}\x{76C3}\x{76C4}\x{76C5}\x{76C6}\x{76C7}\x{76C8}' - . '\x{76C9}\x{76CA}\x{76CD}\x{76CE}\x{76CF}\x{76D0}\x{76D1}\x{76D2}\x{76D3}' - . '\x{76D4}\x{76D5}\x{76D6}\x{76D7}\x{76D8}\x{76DA}\x{76DB}\x{76DC}\x{76DD}' - . '\x{76DE}\x{76DF}\x{76E0}\x{76E1}\x{76E2}\x{76E3}\x{76E4}\x{76E5}\x{76E6}' - . '\x{76E7}\x{76E8}\x{76E9}\x{76EA}\x{76EC}\x{76ED}\x{76EE}\x{76EF}\x{76F0}' - . '\x{76F1}\x{76F2}\x{76F3}\x{76F4}\x{76F5}\x{76F6}\x{76F7}\x{76F8}\x{76F9}' - . '\x{76FA}\x{76FB}\x{76FC}\x{76FD}\x{76FE}\x{76FF}\x{7701}\x{7703}\x{7704}' - . '\x{7705}\x{7706}\x{7707}\x{7708}\x{7709}\x{770A}\x{770B}\x{770C}\x{770D}' - . '\x{770F}\x{7710}\x{7711}\x{7712}\x{7713}\x{7714}\x{7715}\x{7716}\x{7717}' - . '\x{7718}\x{7719}\x{771A}\x{771B}\x{771C}\x{771D}\x{771E}\x{771F}\x{7720}' - . '\x{7722}\x{7723}\x{7725}\x{7726}\x{7727}\x{7728}\x{7729}\x{772A}\x{772C}' - . '\x{772D}\x{772E}\x{772F}\x{7730}\x{7731}\x{7732}\x{7733}\x{7734}\x{7735}' - . '\x{7736}\x{7737}\x{7738}\x{7739}\x{773A}\x{773B}\x{773C}\x{773D}\x{773E}' - . '\x{7740}\x{7741}\x{7743}\x{7744}\x{7745}\x{7746}\x{7747}\x{7748}\x{7749}' - . '\x{774A}\x{774B}\x{774C}\x{774D}\x{774E}\x{774F}\x{7750}\x{7751}\x{7752}' - . '\x{7753}\x{7754}\x{7755}\x{7756}\x{7757}\x{7758}\x{7759}\x{775A}\x{775B}' - . '\x{775C}\x{775D}\x{775E}\x{775F}\x{7760}\x{7761}\x{7762}\x{7763}\x{7765}' - . '\x{7766}\x{7767}\x{7768}\x{7769}\x{776A}\x{776B}\x{776C}\x{776D}\x{776E}' - . '\x{776F}\x{7770}\x{7771}\x{7772}\x{7773}\x{7774}\x{7775}\x{7776}\x{7777}' - . '\x{7778}\x{7779}\x{777A}\x{777B}\x{777C}\x{777D}\x{777E}\x{777F}\x{7780}' - . '\x{7781}\x{7782}\x{7783}\x{7784}\x{7785}\x{7786}\x{7787}\x{7788}\x{7789}' - . '\x{778A}\x{778B}\x{778C}\x{778D}\x{778E}\x{778F}\x{7790}\x{7791}\x{7792}' - . '\x{7793}\x{7794}\x{7795}\x{7797}\x{7798}\x{7799}\x{779A}\x{779B}\x{779C}' - . '\x{779D}\x{779E}\x{779F}\x{77A0}\x{77A1}\x{77A2}\x{77A3}\x{77A5}\x{77A6}' - . '\x{77A7}\x{77A8}\x{77A9}\x{77AA}\x{77AB}\x{77AC}\x{77AD}\x{77AE}\x{77AF}' - . '\x{77B0}\x{77B1}\x{77B2}\x{77B3}\x{77B4}\x{77B5}\x{77B6}\x{77B7}\x{77B8}' - . '\x{77B9}\x{77BA}\x{77BB}\x{77BC}\x{77BD}\x{77BF}\x{77C0}\x{77C2}\x{77C3}' - . '\x{77C4}\x{77C5}\x{77C6}\x{77C7}\x{77C8}\x{77C9}\x{77CA}\x{77CB}\x{77CC}' - . '\x{77CD}\x{77CE}\x{77CF}\x{77D0}\x{77D1}\x{77D3}\x{77D4}\x{77D5}\x{77D6}' - . '\x{77D7}\x{77D8}\x{77D9}\x{77DA}\x{77DB}\x{77DC}\x{77DE}\x{77DF}\x{77E0}' - . '\x{77E1}\x{77E2}\x{77E3}\x{77E5}\x{77E7}\x{77E8}\x{77E9}\x{77EA}\x{77EB}' - . '\x{77EC}\x{77ED}\x{77EE}\x{77EF}\x{77F0}\x{77F1}\x{77F2}\x{77F3}\x{77F6}' - . '\x{77F7}\x{77F8}\x{77F9}\x{77FA}\x{77FB}\x{77FC}\x{77FD}\x{77FE}\x{77FF}' - . '\x{7800}\x{7801}\x{7802}\x{7803}\x{7804}\x{7805}\x{7806}\x{7808}\x{7809}' - . '\x{780A}\x{780B}\x{780C}\x{780D}\x{780E}\x{780F}\x{7810}\x{7811}\x{7812}' - . '\x{7813}\x{7814}\x{7815}\x{7816}\x{7817}\x{7818}\x{7819}\x{781A}\x{781B}' - . '\x{781C}\x{781D}\x{781E}\x{781F}\x{7820}\x{7821}\x{7822}\x{7823}\x{7825}' - . '\x{7826}\x{7827}\x{7828}\x{7829}\x{782A}\x{782B}\x{782C}\x{782D}\x{782E}' - . '\x{782F}\x{7830}\x{7831}\x{7832}\x{7833}\x{7834}\x{7835}\x{7837}\x{7838}' - . '\x{7839}\x{783A}\x{783B}\x{783C}\x{783D}\x{783E}\x{7840}\x{7841}\x{7843}' - . '\x{7844}\x{7845}\x{7847}\x{7848}\x{7849}\x{784A}\x{784C}\x{784D}\x{784E}' - . '\x{7850}\x{7851}\x{7852}\x{7853}\x{7854}\x{7855}\x{7856}\x{7857}\x{7858}' - . '\x{7859}\x{785A}\x{785B}\x{785C}\x{785D}\x{785E}\x{785F}\x{7860}\x{7861}' - . '\x{7862}\x{7863}\x{7864}\x{7865}\x{7866}\x{7867}\x{7868}\x{7869}\x{786A}' - . '\x{786B}\x{786C}\x{786D}\x{786E}\x{786F}\x{7870}\x{7871}\x{7872}\x{7873}' - . '\x{7874}\x{7875}\x{7877}\x{7878}\x{7879}\x{787A}\x{787B}\x{787C}\x{787D}' - . '\x{787E}\x{787F}\x{7880}\x{7881}\x{7882}\x{7883}\x{7884}\x{7885}\x{7886}' - . '\x{7887}\x{7889}\x{788A}\x{788B}\x{788C}\x{788D}\x{788E}\x{788F}\x{7890}' - . '\x{7891}\x{7892}\x{7893}\x{7894}\x{7895}\x{7896}\x{7897}\x{7898}\x{7899}' - . '\x{789A}\x{789B}\x{789C}\x{789D}\x{789E}\x{789F}\x{78A0}\x{78A1}\x{78A2}' - . '\x{78A3}\x{78A4}\x{78A5}\x{78A6}\x{78A7}\x{78A8}\x{78A9}\x{78AA}\x{78AB}' - . '\x{78AC}\x{78AD}\x{78AE}\x{78AF}\x{78B0}\x{78B1}\x{78B2}\x{78B3}\x{78B4}' - . '\x{78B5}\x{78B6}\x{78B7}\x{78B8}\x{78B9}\x{78BA}\x{78BB}\x{78BC}\x{78BD}' - . '\x{78BE}\x{78BF}\x{78C0}\x{78C1}\x{78C3}\x{78C4}\x{78C5}\x{78C6}\x{78C8}' - . '\x{78C9}\x{78CA}\x{78CB}\x{78CC}\x{78CD}\x{78CE}\x{78CF}\x{78D0}\x{78D1}' - . '\x{78D3}\x{78D4}\x{78D5}\x{78D6}\x{78D7}\x{78D8}\x{78D9}\x{78DA}\x{78DB}' - . '\x{78DC}\x{78DD}\x{78DE}\x{78DF}\x{78E0}\x{78E1}\x{78E2}\x{78E3}\x{78E4}' - . '\x{78E5}\x{78E6}\x{78E7}\x{78E8}\x{78E9}\x{78EA}\x{78EB}\x{78EC}\x{78ED}' - . '\x{78EE}\x{78EF}\x{78F1}\x{78F2}\x{78F3}\x{78F4}\x{78F5}\x{78F6}\x{78F7}' - . '\x{78F9}\x{78FA}\x{78FB}\x{78FC}\x{78FD}\x{78FE}\x{78FF}\x{7901}\x{7902}' - . '\x{7903}\x{7904}\x{7905}\x{7906}\x{7907}\x{7909}\x{790A}\x{790B}\x{790C}' - . '\x{790E}\x{790F}\x{7910}\x{7911}\x{7912}\x{7913}\x{7914}\x{7916}\x{7917}' - . '\x{7918}\x{7919}\x{791A}\x{791B}\x{791C}\x{791D}\x{791E}\x{7921}\x{7922}' - . '\x{7923}\x{7924}\x{7925}\x{7926}\x{7927}\x{7928}\x{7929}\x{792A}\x{792B}' - . '\x{792C}\x{792D}\x{792E}\x{792F}\x{7930}\x{7931}\x{7933}\x{7934}\x{7935}' - . '\x{7937}\x{7938}\x{7939}\x{793A}\x{793B}\x{793C}\x{793D}\x{793E}\x{793F}' - . '\x{7940}\x{7941}\x{7942}\x{7943}\x{7944}\x{7945}\x{7946}\x{7947}\x{7948}' - . '\x{7949}\x{794A}\x{794B}\x{794C}\x{794D}\x{794E}\x{794F}\x{7950}\x{7951}' - . '\x{7952}\x{7953}\x{7954}\x{7955}\x{7956}\x{7957}\x{7958}\x{795A}\x{795B}' - . '\x{795C}\x{795D}\x{795E}\x{795F}\x{7960}\x{7961}\x{7962}\x{7963}\x{7964}' - . '\x{7965}\x{7966}\x{7967}\x{7968}\x{7969}\x{796A}\x{796B}\x{796D}\x{796F}' - . '\x{7970}\x{7971}\x{7972}\x{7973}\x{7974}\x{7977}\x{7978}\x{7979}\x{797A}' - . '\x{797B}\x{797C}\x{797D}\x{797E}\x{797F}\x{7980}\x{7981}\x{7982}\x{7983}' - . '\x{7984}\x{7985}\x{7988}\x{7989}\x{798A}\x{798B}\x{798C}\x{798D}\x{798E}' - . '\x{798F}\x{7990}\x{7991}\x{7992}\x{7993}\x{7994}\x{7995}\x{7996}\x{7997}' - . '\x{7998}\x{7999}\x{799A}\x{799B}\x{799C}\x{799F}\x{79A0}\x{79A1}\x{79A2}' - . '\x{79A3}\x{79A4}\x{79A5}\x{79A6}\x{79A7}\x{79A8}\x{79AA}\x{79AB}\x{79AC}' - . '\x{79AD}\x{79AE}\x{79AF}\x{79B0}\x{79B1}\x{79B2}\x{79B3}\x{79B4}\x{79B5}' - . '\x{79B6}\x{79B7}\x{79B8}\x{79B9}\x{79BA}\x{79BB}\x{79BD}\x{79BE}\x{79BF}' - . '\x{79C0}\x{79C1}\x{79C2}\x{79C3}\x{79C5}\x{79C6}\x{79C8}\x{79C9}\x{79CA}' - . '\x{79CB}\x{79CD}\x{79CE}\x{79CF}\x{79D0}\x{79D1}\x{79D2}\x{79D3}\x{79D5}' - . '\x{79D6}\x{79D8}\x{79D9}\x{79DA}\x{79DB}\x{79DC}\x{79DD}\x{79DE}\x{79DF}' - . '\x{79E0}\x{79E1}\x{79E2}\x{79E3}\x{79E4}\x{79E5}\x{79E6}\x{79E7}\x{79E8}' - . '\x{79E9}\x{79EA}\x{79EB}\x{79EC}\x{79ED}\x{79EE}\x{79EF}\x{79F0}\x{79F1}' - . '\x{79F2}\x{79F3}\x{79F4}\x{79F5}\x{79F6}\x{79F7}\x{79F8}\x{79F9}\x{79FA}' - . '\x{79FB}\x{79FC}\x{79FD}\x{79FE}\x{79FF}\x{7A00}\x{7A02}\x{7A03}\x{7A04}' - . '\x{7A05}\x{7A06}\x{7A08}\x{7A0A}\x{7A0B}\x{7A0C}\x{7A0D}\x{7A0E}\x{7A0F}' - . '\x{7A10}\x{7A11}\x{7A12}\x{7A13}\x{7A14}\x{7A15}\x{7A16}\x{7A17}\x{7A18}' - . '\x{7A19}\x{7A1A}\x{7A1B}\x{7A1C}\x{7A1D}\x{7A1E}\x{7A1F}\x{7A20}\x{7A21}' - . '\x{7A22}\x{7A23}\x{7A24}\x{7A25}\x{7A26}\x{7A27}\x{7A28}\x{7A29}\x{7A2A}' - . '\x{7A2B}\x{7A2D}\x{7A2E}\x{7A2F}\x{7A30}\x{7A31}\x{7A32}\x{7A33}\x{7A34}' - . '\x{7A35}\x{7A37}\x{7A39}\x{7A3B}\x{7A3C}\x{7A3D}\x{7A3E}\x{7A3F}\x{7A40}' - . '\x{7A41}\x{7A42}\x{7A43}\x{7A44}\x{7A45}\x{7A46}\x{7A47}\x{7A48}\x{7A49}' - . '\x{7A4A}\x{7A4B}\x{7A4C}\x{7A4D}\x{7A4E}\x{7A50}\x{7A51}\x{7A52}\x{7A53}' - . '\x{7A54}\x{7A55}\x{7A56}\x{7A57}\x{7A58}\x{7A59}\x{7A5A}\x{7A5B}\x{7A5C}' - . '\x{7A5D}\x{7A5E}\x{7A5F}\x{7A60}\x{7A61}\x{7A62}\x{7A65}\x{7A66}\x{7A67}' - . '\x{7A68}\x{7A69}\x{7A6B}\x{7A6C}\x{7A6D}\x{7A6E}\x{7A70}\x{7A71}\x{7A72}' - . '\x{7A73}\x{7A74}\x{7A75}\x{7A76}\x{7A77}\x{7A78}\x{7A79}\x{7A7A}\x{7A7B}' - . '\x{7A7C}\x{7A7D}\x{7A7E}\x{7A7F}\x{7A80}\x{7A81}\x{7A83}\x{7A84}\x{7A85}' - . '\x{7A86}\x{7A87}\x{7A88}\x{7A89}\x{7A8A}\x{7A8B}\x{7A8C}\x{7A8D}\x{7A8E}' - . '\x{7A8F}\x{7A90}\x{7A91}\x{7A92}\x{7A93}\x{7A94}\x{7A95}\x{7A96}\x{7A97}' - . '\x{7A98}\x{7A99}\x{7A9C}\x{7A9D}\x{7A9E}\x{7A9F}\x{7AA0}\x{7AA1}\x{7AA2}' - . '\x{7AA3}\x{7AA4}\x{7AA5}\x{7AA6}\x{7AA7}\x{7AA8}\x{7AA9}\x{7AAA}\x{7AAB}' - . '\x{7AAC}\x{7AAD}\x{7AAE}\x{7AAF}\x{7AB0}\x{7AB1}\x{7AB2}\x{7AB3}\x{7AB4}' - . '\x{7AB5}\x{7AB6}\x{7AB7}\x{7AB8}\x{7ABA}\x{7ABE}\x{7ABF}\x{7AC0}\x{7AC1}' - . '\x{7AC4}\x{7AC5}\x{7AC7}\x{7AC8}\x{7AC9}\x{7ACA}\x{7ACB}\x{7ACC}\x{7ACD}' - . '\x{7ACE}\x{7ACF}\x{7AD0}\x{7AD1}\x{7AD2}\x{7AD3}\x{7AD4}\x{7AD5}\x{7AD6}' - . '\x{7AD8}\x{7AD9}\x{7ADB}\x{7ADC}\x{7ADD}\x{7ADE}\x{7ADF}\x{7AE0}\x{7AE1}' - . '\x{7AE2}\x{7AE3}\x{7AE4}\x{7AE5}\x{7AE6}\x{7AE7}\x{7AE8}\x{7AEA}\x{7AEB}' - . '\x{7AEC}\x{7AED}\x{7AEE}\x{7AEF}\x{7AF0}\x{7AF1}\x{7AF2}\x{7AF3}\x{7AF4}' - . '\x{7AF6}\x{7AF7}\x{7AF8}\x{7AF9}\x{7AFA}\x{7AFB}\x{7AFD}\x{7AFE}\x{7AFF}' - . '\x{7B00}\x{7B01}\x{7B02}\x{7B03}\x{7B04}\x{7B05}\x{7B06}\x{7B08}\x{7B09}' - . '\x{7B0A}\x{7B0B}\x{7B0C}\x{7B0D}\x{7B0E}\x{7B0F}\x{7B10}\x{7B11}\x{7B12}' - . '\x{7B13}\x{7B14}\x{7B15}\x{7B16}\x{7B17}\x{7B18}\x{7B19}\x{7B1A}\x{7B1B}' - . '\x{7B1C}\x{7B1D}\x{7B1E}\x{7B20}\x{7B21}\x{7B22}\x{7B23}\x{7B24}\x{7B25}' - . '\x{7B26}\x{7B28}\x{7B2A}\x{7B2B}\x{7B2C}\x{7B2D}\x{7B2E}\x{7B2F}\x{7B30}' - . '\x{7B31}\x{7B32}\x{7B33}\x{7B34}\x{7B35}\x{7B36}\x{7B37}\x{7B38}\x{7B39}' - . '\x{7B3A}\x{7B3B}\x{7B3C}\x{7B3D}\x{7B3E}\x{7B3F}\x{7B40}\x{7B41}\x{7B43}' - . '\x{7B44}\x{7B45}\x{7B46}\x{7B47}\x{7B48}\x{7B49}\x{7B4A}\x{7B4B}\x{7B4C}' - . '\x{7B4D}\x{7B4E}\x{7B4F}\x{7B50}\x{7B51}\x{7B52}\x{7B54}\x{7B55}\x{7B56}' - . '\x{7B57}\x{7B58}\x{7B59}\x{7B5A}\x{7B5B}\x{7B5C}\x{7B5D}\x{7B5E}\x{7B5F}' - . '\x{7B60}\x{7B61}\x{7B62}\x{7B63}\x{7B64}\x{7B65}\x{7B66}\x{7B67}\x{7B68}' - . '\x{7B69}\x{7B6A}\x{7B6B}\x{7B6C}\x{7B6D}\x{7B6E}\x{7B70}\x{7B71}\x{7B72}' - . '\x{7B73}\x{7B74}\x{7B75}\x{7B76}\x{7B77}\x{7B78}\x{7B79}\x{7B7B}\x{7B7C}' - . '\x{7B7D}\x{7B7E}\x{7B7F}\x{7B80}\x{7B81}\x{7B82}\x{7B83}\x{7B84}\x{7B85}' - . '\x{7B87}\x{7B88}\x{7B89}\x{7B8A}\x{7B8B}\x{7B8C}\x{7B8D}\x{7B8E}\x{7B8F}' - . '\x{7B90}\x{7B91}\x{7B93}\x{7B94}\x{7B95}\x{7B96}\x{7B97}\x{7B98}\x{7B99}' - . '\x{7B9A}\x{7B9B}\x{7B9C}\x{7B9D}\x{7B9E}\x{7B9F}\x{7BA0}\x{7BA1}\x{7BA2}' - . '\x{7BA4}\x{7BA6}\x{7BA7}\x{7BA8}\x{7BA9}\x{7BAA}\x{7BAB}\x{7BAC}\x{7BAD}' - . '\x{7BAE}\x{7BAF}\x{7BB1}\x{7BB3}\x{7BB4}\x{7BB5}\x{7BB6}\x{7BB7}\x{7BB8}' - . '\x{7BB9}\x{7BBA}\x{7BBB}\x{7BBC}\x{7BBD}\x{7BBE}\x{7BBF}\x{7BC0}\x{7BC1}' - . '\x{7BC2}\x{7BC3}\x{7BC4}\x{7BC5}\x{7BC6}\x{7BC7}\x{7BC8}\x{7BC9}\x{7BCA}' - . '\x{7BCB}\x{7BCC}\x{7BCD}\x{7BCE}\x{7BD0}\x{7BD1}\x{7BD2}\x{7BD3}\x{7BD4}' - . '\x{7BD5}\x{7BD6}\x{7BD7}\x{7BD8}\x{7BD9}\x{7BDA}\x{7BDB}\x{7BDC}\x{7BDD}' - . '\x{7BDE}\x{7BDF}\x{7BE0}\x{7BE1}\x{7BE2}\x{7BE3}\x{7BE4}\x{7BE5}\x{7BE6}' - . '\x{7BE7}\x{7BE8}\x{7BE9}\x{7BEA}\x{7BEB}\x{7BEC}\x{7BED}\x{7BEE}\x{7BEF}' - . '\x{7BF0}\x{7BF1}\x{7BF2}\x{7BF3}\x{7BF4}\x{7BF5}\x{7BF6}\x{7BF7}\x{7BF8}' - . '\x{7BF9}\x{7BFB}\x{7BFC}\x{7BFD}\x{7BFE}\x{7BFF}\x{7C00}\x{7C01}\x{7C02}' - . '\x{7C03}\x{7C04}\x{7C05}\x{7C06}\x{7C07}\x{7C08}\x{7C09}\x{7C0A}\x{7C0B}' - . '\x{7C0C}\x{7C0D}\x{7C0E}\x{7C0F}\x{7C10}\x{7C11}\x{7C12}\x{7C13}\x{7C15}' - . '\x{7C16}\x{7C17}\x{7C18}\x{7C19}\x{7C1A}\x{7C1C}\x{7C1D}\x{7C1E}\x{7C1F}' - . '\x{7C20}\x{7C21}\x{7C22}\x{7C23}\x{7C24}\x{7C25}\x{7C26}\x{7C27}\x{7C28}' - . '\x{7C29}\x{7C2A}\x{7C2B}\x{7C2C}\x{7C2D}\x{7C30}\x{7C31}\x{7C32}\x{7C33}' - . '\x{7C34}\x{7C35}\x{7C36}\x{7C37}\x{7C38}\x{7C39}\x{7C3A}\x{7C3B}\x{7C3C}' - . '\x{7C3D}\x{7C3E}\x{7C3F}\x{7C40}\x{7C41}\x{7C42}\x{7C43}\x{7C44}\x{7C45}' - . '\x{7C46}\x{7C47}\x{7C48}\x{7C49}\x{7C4A}\x{7C4B}\x{7C4C}\x{7C4D}\x{7C4E}' - . '\x{7C50}\x{7C51}\x{7C53}\x{7C54}\x{7C56}\x{7C57}\x{7C58}\x{7C59}\x{7C5A}' - . '\x{7C5B}\x{7C5C}\x{7C5E}\x{7C5F}\x{7C60}\x{7C61}\x{7C62}\x{7C63}\x{7C64}' - . '\x{7C65}\x{7C66}\x{7C67}\x{7C68}\x{7C69}\x{7C6A}\x{7C6B}\x{7C6C}\x{7C6D}' - . '\x{7C6E}\x{7C6F}\x{7C70}\x{7C71}\x{7C72}\x{7C73}\x{7C74}\x{7C75}\x{7C77}' - . '\x{7C78}\x{7C79}\x{7C7A}\x{7C7B}\x{7C7C}\x{7C7D}\x{7C7E}\x{7C7F}\x{7C80}' - . '\x{7C81}\x{7C82}\x{7C84}\x{7C85}\x{7C86}\x{7C88}\x{7C89}\x{7C8A}\x{7C8B}' - . '\x{7C8C}\x{7C8D}\x{7C8E}\x{7C8F}\x{7C90}\x{7C91}\x{7C92}\x{7C94}\x{7C95}' - . '\x{7C96}\x{7C97}\x{7C98}\x{7C99}\x{7C9B}\x{7C9C}\x{7C9D}\x{7C9E}\x{7C9F}' - . '\x{7CA0}\x{7CA1}\x{7CA2}\x{7CA3}\x{7CA4}\x{7CA5}\x{7CA6}\x{7CA7}\x{7CA8}' - . '\x{7CA9}\x{7CAA}\x{7CAD}\x{7CAE}\x{7CAF}\x{7CB0}\x{7CB1}\x{7CB2}\x{7CB3}' - . '\x{7CB4}\x{7CB5}\x{7CB6}\x{7CB7}\x{7CB8}\x{7CB9}\x{7CBA}\x{7CBB}\x{7CBC}' - . '\x{7CBD}\x{7CBE}\x{7CBF}\x{7CC0}\x{7CC1}\x{7CC2}\x{7CC3}\x{7CC4}\x{7CC5}' - . '\x{7CC6}\x{7CC7}\x{7CC8}\x{7CC9}\x{7CCA}\x{7CCB}\x{7CCC}\x{7CCD}\x{7CCE}' - . '\x{7CCF}\x{7CD0}\x{7CD1}\x{7CD2}\x{7CD4}\x{7CD5}\x{7CD6}\x{7CD7}\x{7CD8}' - . '\x{7CD9}\x{7CDC}\x{7CDD}\x{7CDE}\x{7CDF}\x{7CE0}\x{7CE2}\x{7CE4}\x{7CE7}' - . '\x{7CE8}\x{7CE9}\x{7CEA}\x{7CEB}\x{7CEC}\x{7CED}\x{7CEE}\x{7CEF}\x{7CF0}' - . '\x{7CF1}\x{7CF2}\x{7CF3}\x{7CF4}\x{7CF5}\x{7CF6}\x{7CF7}\x{7CF8}\x{7CF9}' - . '\x{7CFA}\x{7CFB}\x{7CFD}\x{7CFE}\x{7D00}\x{7D01}\x{7D02}\x{7D03}\x{7D04}' - . '\x{7D05}\x{7D06}\x{7D07}\x{7D08}\x{7D09}\x{7D0A}\x{7D0B}\x{7D0C}\x{7D0D}' - . '\x{7D0E}\x{7D0F}\x{7D10}\x{7D11}\x{7D12}\x{7D13}\x{7D14}\x{7D15}\x{7D16}' - . '\x{7D17}\x{7D18}\x{7D19}\x{7D1A}\x{7D1B}\x{7D1C}\x{7D1D}\x{7D1E}\x{7D1F}' - . '\x{7D20}\x{7D21}\x{7D22}\x{7D24}\x{7D25}\x{7D26}\x{7D27}\x{7D28}\x{7D29}' - . '\x{7D2B}\x{7D2C}\x{7D2E}\x{7D2F}\x{7D30}\x{7D31}\x{7D32}\x{7D33}\x{7D34}' - . '\x{7D35}\x{7D36}\x{7D37}\x{7D38}\x{7D39}\x{7D3A}\x{7D3B}\x{7D3C}\x{7D3D}' - . '\x{7D3E}\x{7D3F}\x{7D40}\x{7D41}\x{7D42}\x{7D43}\x{7D44}\x{7D45}\x{7D46}' - . '\x{7D47}\x{7D49}\x{7D4A}\x{7D4B}\x{7D4C}\x{7D4E}\x{7D4F}\x{7D50}\x{7D51}' - . '\x{7D52}\x{7D53}\x{7D54}\x{7D55}\x{7D56}\x{7D57}\x{7D58}\x{7D59}\x{7D5B}' - . '\x{7D5C}\x{7D5D}\x{7D5E}\x{7D5F}\x{7D60}\x{7D61}\x{7D62}\x{7D63}\x{7D65}' - . '\x{7D66}\x{7D67}\x{7D68}\x{7D69}\x{7D6A}\x{7D6B}\x{7D6C}\x{7D6D}\x{7D6E}' - . '\x{7D6F}\x{7D70}\x{7D71}\x{7D72}\x{7D73}\x{7D74}\x{7D75}\x{7D76}\x{7D77}' - . '\x{7D79}\x{7D7A}\x{7D7B}\x{7D7C}\x{7D7D}\x{7D7E}\x{7D7F}\x{7D80}\x{7D81}' - . '\x{7D83}\x{7D84}\x{7D85}\x{7D86}\x{7D87}\x{7D88}\x{7D89}\x{7D8A}\x{7D8B}' - . '\x{7D8C}\x{7D8D}\x{7D8E}\x{7D8F}\x{7D90}\x{7D91}\x{7D92}\x{7D93}\x{7D94}' - . '\x{7D96}\x{7D97}\x{7D99}\x{7D9B}\x{7D9C}\x{7D9D}\x{7D9E}\x{7D9F}\x{7DA0}' - . '\x{7DA1}\x{7DA2}\x{7DA3}\x{7DA5}\x{7DA6}\x{7DA7}\x{7DA9}\x{7DAA}\x{7DAB}' - . '\x{7DAC}\x{7DAD}\x{7DAE}\x{7DAF}\x{7DB0}\x{7DB1}\x{7DB2}\x{7DB3}\x{7DB4}' - . '\x{7DB5}\x{7DB6}\x{7DB7}\x{7DB8}\x{7DB9}\x{7DBA}\x{7DBB}\x{7DBC}\x{7DBD}' - . '\x{7DBE}\x{7DBF}\x{7DC0}\x{7DC1}\x{7DC2}\x{7DC3}\x{7DC4}\x{7DC5}\x{7DC6}' - . '\x{7DC7}\x{7DC8}\x{7DC9}\x{7DCA}\x{7DCB}\x{7DCC}\x{7DCE}\x{7DCF}\x{7DD0}' - . '\x{7DD1}\x{7DD2}\x{7DD4}\x{7DD5}\x{7DD6}\x{7DD7}\x{7DD8}\x{7DD9}\x{7DDA}' - . '\x{7DDB}\x{7DDD}\x{7DDE}\x{7DDF}\x{7DE0}\x{7DE1}\x{7DE2}\x{7DE3}\x{7DE6}' - . '\x{7DE7}\x{7DE8}\x{7DE9}\x{7DEA}\x{7DEC}\x{7DED}\x{7DEE}\x{7DEF}\x{7DF0}' - . '\x{7DF1}\x{7DF2}\x{7DF3}\x{7DF4}\x{7DF5}\x{7DF6}\x{7DF7}\x{7DF8}\x{7DF9}' - . '\x{7DFA}\x{7DFB}\x{7DFC}\x{7E00}\x{7E01}\x{7E02}\x{7E03}\x{7E04}\x{7E05}' - . '\x{7E06}\x{7E07}\x{7E08}\x{7E09}\x{7E0A}\x{7E0B}\x{7E0C}\x{7E0D}\x{7E0E}' - . '\x{7E0F}\x{7E10}\x{7E11}\x{7E12}\x{7E13}\x{7E14}\x{7E15}\x{7E16}\x{7E17}' - . '\x{7E19}\x{7E1A}\x{7E1B}\x{7E1C}\x{7E1D}\x{7E1E}\x{7E1F}\x{7E20}\x{7E21}' - . '\x{7E22}\x{7E23}\x{7E24}\x{7E25}\x{7E26}\x{7E27}\x{7E28}\x{7E29}\x{7E2A}' - . '\x{7E2B}\x{7E2C}\x{7E2D}\x{7E2E}\x{7E2F}\x{7E30}\x{7E31}\x{7E32}\x{7E33}' - . '\x{7E34}\x{7E35}\x{7E36}\x{7E37}\x{7E38}\x{7E39}\x{7E3A}\x{7E3B}\x{7E3C}' - . '\x{7E3D}\x{7E3E}\x{7E3F}\x{7E40}\x{7E41}\x{7E42}\x{7E43}\x{7E44}\x{7E45}' - . '\x{7E46}\x{7E47}\x{7E48}\x{7E49}\x{7E4C}\x{7E4D}\x{7E4E}\x{7E4F}\x{7E50}' - . '\x{7E51}\x{7E52}\x{7E53}\x{7E54}\x{7E55}\x{7E56}\x{7E57}\x{7E58}\x{7E59}' - . '\x{7E5A}\x{7E5C}\x{7E5D}\x{7E5E}\x{7E5F}\x{7E60}\x{7E61}\x{7E62}\x{7E63}' - . '\x{7E65}\x{7E66}\x{7E67}\x{7E68}\x{7E69}\x{7E6A}\x{7E6B}\x{7E6C}\x{7E6D}' - . '\x{7E6E}\x{7E6F}\x{7E70}\x{7E71}\x{7E72}\x{7E73}\x{7E74}\x{7E75}\x{7E76}' - . '\x{7E77}\x{7E78}\x{7E79}\x{7E7A}\x{7E7B}\x{7E7C}\x{7E7D}\x{7E7E}\x{7E7F}' - . '\x{7E80}\x{7E81}\x{7E82}\x{7E83}\x{7E84}\x{7E85}\x{7E86}\x{7E87}\x{7E88}' - . '\x{7E89}\x{7E8A}\x{7E8B}\x{7E8C}\x{7E8D}\x{7E8E}\x{7E8F}\x{7E90}\x{7E91}' - . '\x{7E92}\x{7E93}\x{7E94}\x{7E95}\x{7E96}\x{7E97}\x{7E98}\x{7E99}\x{7E9A}' - . '\x{7E9B}\x{7E9C}\x{7E9E}\x{7E9F}\x{7EA0}\x{7EA1}\x{7EA2}\x{7EA3}\x{7EA4}' - . '\x{7EA5}\x{7EA6}\x{7EA7}\x{7EA8}\x{7EA9}\x{7EAA}\x{7EAB}\x{7EAC}\x{7EAD}' - . '\x{7EAE}\x{7EAF}\x{7EB0}\x{7EB1}\x{7EB2}\x{7EB3}\x{7EB4}\x{7EB5}\x{7EB6}' - . '\x{7EB7}\x{7EB8}\x{7EB9}\x{7EBA}\x{7EBB}\x{7EBC}\x{7EBD}\x{7EBE}\x{7EBF}' - . '\x{7EC0}\x{7EC1}\x{7EC2}\x{7EC3}\x{7EC4}\x{7EC5}\x{7EC6}\x{7EC7}\x{7EC8}' - . '\x{7EC9}\x{7ECA}\x{7ECB}\x{7ECC}\x{7ECD}\x{7ECE}\x{7ECF}\x{7ED0}\x{7ED1}' - . '\x{7ED2}\x{7ED3}\x{7ED4}\x{7ED5}\x{7ED6}\x{7ED7}\x{7ED8}\x{7ED9}\x{7EDA}' - . '\x{7EDB}\x{7EDC}\x{7EDD}\x{7EDE}\x{7EDF}\x{7EE0}\x{7EE1}\x{7EE2}\x{7EE3}' - . '\x{7EE4}\x{7EE5}\x{7EE6}\x{7EE7}\x{7EE8}\x{7EE9}\x{7EEA}\x{7EEB}\x{7EEC}' - . '\x{7EED}\x{7EEE}\x{7EEF}\x{7EF0}\x{7EF1}\x{7EF2}\x{7EF3}\x{7EF4}\x{7EF5}' - . '\x{7EF6}\x{7EF7}\x{7EF8}\x{7EF9}\x{7EFA}\x{7EFB}\x{7EFC}\x{7EFD}\x{7EFE}' - . '\x{7EFF}\x{7F00}\x{7F01}\x{7F02}\x{7F03}\x{7F04}\x{7F05}\x{7F06}\x{7F07}' - . '\x{7F08}\x{7F09}\x{7F0A}\x{7F0B}\x{7F0C}\x{7F0D}\x{7F0E}\x{7F0F}\x{7F10}' - . '\x{7F11}\x{7F12}\x{7F13}\x{7F14}\x{7F15}\x{7F16}\x{7F17}\x{7F18}\x{7F19}' - . '\x{7F1A}\x{7F1B}\x{7F1C}\x{7F1D}\x{7F1E}\x{7F1F}\x{7F20}\x{7F21}\x{7F22}' - . '\x{7F23}\x{7F24}\x{7F25}\x{7F26}\x{7F27}\x{7F28}\x{7F29}\x{7F2A}\x{7F2B}' - . '\x{7F2C}\x{7F2D}\x{7F2E}\x{7F2F}\x{7F30}\x{7F31}\x{7F32}\x{7F33}\x{7F34}' - . '\x{7F35}\x{7F36}\x{7F37}\x{7F38}\x{7F39}\x{7F3A}\x{7F3D}\x{7F3E}\x{7F3F}' - . '\x{7F40}\x{7F42}\x{7F43}\x{7F44}\x{7F45}\x{7F47}\x{7F48}\x{7F49}\x{7F4A}' - . '\x{7F4B}\x{7F4C}\x{7F4D}\x{7F4E}\x{7F4F}\x{7F50}\x{7F51}\x{7F52}\x{7F53}' - . '\x{7F54}\x{7F55}\x{7F56}\x{7F57}\x{7F58}\x{7F5A}\x{7F5B}\x{7F5C}\x{7F5D}' - . '\x{7F5E}\x{7F5F}\x{7F60}\x{7F61}\x{7F62}\x{7F63}\x{7F64}\x{7F65}\x{7F66}' - . '\x{7F67}\x{7F68}\x{7F69}\x{7F6A}\x{7F6B}\x{7F6C}\x{7F6D}\x{7F6E}\x{7F6F}' - . '\x{7F70}\x{7F71}\x{7F72}\x{7F73}\x{7F74}\x{7F75}\x{7F76}\x{7F77}\x{7F78}' - . '\x{7F79}\x{7F7A}\x{7F7B}\x{7F7C}\x{7F7D}\x{7F7E}\x{7F7F}\x{7F80}\x{7F81}' - . '\x{7F82}\x{7F83}\x{7F85}\x{7F86}\x{7F87}\x{7F88}\x{7F89}\x{7F8A}\x{7F8B}' - . '\x{7F8C}\x{7F8D}\x{7F8E}\x{7F8F}\x{7F91}\x{7F92}\x{7F93}\x{7F94}\x{7F95}' - . '\x{7F96}\x{7F98}\x{7F9A}\x{7F9B}\x{7F9C}\x{7F9D}\x{7F9E}\x{7F9F}\x{7FA0}' - . '\x{7FA1}\x{7FA2}\x{7FA3}\x{7FA4}\x{7FA5}\x{7FA6}\x{7FA7}\x{7FA8}\x{7FA9}' - . '\x{7FAA}\x{7FAB}\x{7FAC}\x{7FAD}\x{7FAE}\x{7FAF}\x{7FB0}\x{7FB1}\x{7FB2}' - . '\x{7FB3}\x{7FB5}\x{7FB6}\x{7FB7}\x{7FB8}\x{7FB9}\x{7FBA}\x{7FBB}\x{7FBC}' - . '\x{7FBD}\x{7FBE}\x{7FBF}\x{7FC0}\x{7FC1}\x{7FC2}\x{7FC3}\x{7FC4}\x{7FC5}' - . '\x{7FC6}\x{7FC7}\x{7FC8}\x{7FC9}\x{7FCA}\x{7FCB}\x{7FCC}\x{7FCD}\x{7FCE}' - . '\x{7FCF}\x{7FD0}\x{7FD1}\x{7FD2}\x{7FD3}\x{7FD4}\x{7FD5}\x{7FD7}\x{7FD8}' - . '\x{7FD9}\x{7FDA}\x{7FDB}\x{7FDC}\x{7FDE}\x{7FDF}\x{7FE0}\x{7FE1}\x{7FE2}' - . '\x{7FE3}\x{7FE5}\x{7FE6}\x{7FE7}\x{7FE8}\x{7FE9}\x{7FEA}\x{7FEB}\x{7FEC}' - . '\x{7FED}\x{7FEE}\x{7FEF}\x{7FF0}\x{7FF1}\x{7FF2}\x{7FF3}\x{7FF4}\x{7FF5}' - . '\x{7FF6}\x{7FF7}\x{7FF8}\x{7FF9}\x{7FFA}\x{7FFB}\x{7FFC}\x{7FFD}\x{7FFE}' - . '\x{7FFF}\x{8000}\x{8001}\x{8002}\x{8003}\x{8004}\x{8005}\x{8006}\x{8007}' - . '\x{8008}\x{8009}\x{800B}\x{800C}\x{800D}\x{800E}\x{800F}\x{8010}\x{8011}' - . '\x{8012}\x{8013}\x{8014}\x{8015}\x{8016}\x{8017}\x{8018}\x{8019}\x{801A}' - . '\x{801B}\x{801C}\x{801D}\x{801E}\x{801F}\x{8020}\x{8021}\x{8022}\x{8023}' - . '\x{8024}\x{8025}\x{8026}\x{8027}\x{8028}\x{8029}\x{802A}\x{802B}\x{802C}' - . '\x{802D}\x{802E}\x{8030}\x{8031}\x{8032}\x{8033}\x{8034}\x{8035}\x{8036}' - . '\x{8037}\x{8038}\x{8039}\x{803A}\x{803B}\x{803D}\x{803E}\x{803F}\x{8041}' - . '\x{8042}\x{8043}\x{8044}\x{8045}\x{8046}\x{8047}\x{8048}\x{8049}\x{804A}' - . '\x{804B}\x{804C}\x{804D}\x{804E}\x{804F}\x{8050}\x{8051}\x{8052}\x{8053}' - . '\x{8054}\x{8055}\x{8056}\x{8057}\x{8058}\x{8059}\x{805A}\x{805B}\x{805C}' - . '\x{805D}\x{805E}\x{805F}\x{8060}\x{8061}\x{8062}\x{8063}\x{8064}\x{8065}' - . '\x{8067}\x{8068}\x{8069}\x{806A}\x{806B}\x{806C}\x{806D}\x{806E}\x{806F}' - . '\x{8070}\x{8071}\x{8072}\x{8073}\x{8074}\x{8075}\x{8076}\x{8077}\x{8078}' - . '\x{8079}\x{807A}\x{807B}\x{807C}\x{807D}\x{807E}\x{807F}\x{8080}\x{8081}' - . '\x{8082}\x{8083}\x{8084}\x{8085}\x{8086}\x{8087}\x{8089}\x{808A}\x{808B}' - . '\x{808C}\x{808D}\x{808F}\x{8090}\x{8091}\x{8092}\x{8093}\x{8095}\x{8096}' - . '\x{8097}\x{8098}\x{8099}\x{809A}\x{809B}\x{809C}\x{809D}\x{809E}\x{809F}' - . '\x{80A0}\x{80A1}\x{80A2}\x{80A3}\x{80A4}\x{80A5}\x{80A9}\x{80AA}\x{80AB}' - . '\x{80AD}\x{80AE}\x{80AF}\x{80B0}\x{80B1}\x{80B2}\x{80B4}\x{80B5}\x{80B6}' - . '\x{80B7}\x{80B8}\x{80BA}\x{80BB}\x{80BC}\x{80BD}\x{80BE}\x{80BF}\x{80C0}' - . '\x{80C1}\x{80C2}\x{80C3}\x{80C4}\x{80C5}\x{80C6}\x{80C7}\x{80C8}\x{80C9}' - . '\x{80CA}\x{80CB}\x{80CC}\x{80CD}\x{80CE}\x{80CF}\x{80D0}\x{80D1}\x{80D2}' - . '\x{80D3}\x{80D4}\x{80D5}\x{80D6}\x{80D7}\x{80D8}\x{80D9}\x{80DA}\x{80DB}' - . '\x{80DC}\x{80DD}\x{80DE}\x{80E0}\x{80E1}\x{80E2}\x{80E3}\x{80E4}\x{80E5}' - . '\x{80E6}\x{80E7}\x{80E8}\x{80E9}\x{80EA}\x{80EB}\x{80EC}\x{80ED}\x{80EE}' - . '\x{80EF}\x{80F0}\x{80F1}\x{80F2}\x{80F3}\x{80F4}\x{80F5}\x{80F6}\x{80F7}' - . '\x{80F8}\x{80F9}\x{80FA}\x{80FB}\x{80FC}\x{80FD}\x{80FE}\x{80FF}\x{8100}' - . '\x{8101}\x{8102}\x{8105}\x{8106}\x{8107}\x{8108}\x{8109}\x{810A}\x{810B}' - . '\x{810C}\x{810D}\x{810E}\x{810F}\x{8110}\x{8111}\x{8112}\x{8113}\x{8114}' - . '\x{8115}\x{8116}\x{8118}\x{8119}\x{811A}\x{811B}\x{811C}\x{811D}\x{811E}' - . '\x{811F}\x{8120}\x{8121}\x{8122}\x{8123}\x{8124}\x{8125}\x{8126}\x{8127}' - . '\x{8128}\x{8129}\x{812A}\x{812B}\x{812C}\x{812D}\x{812E}\x{812F}\x{8130}' - . '\x{8131}\x{8132}\x{8136}\x{8137}\x{8138}\x{8139}\x{813A}\x{813B}\x{813C}' - . '\x{813D}\x{813E}\x{813F}\x{8140}\x{8141}\x{8142}\x{8143}\x{8144}\x{8145}' - . '\x{8146}\x{8147}\x{8148}\x{8149}\x{814A}\x{814B}\x{814C}\x{814D}\x{814E}' - . '\x{814F}\x{8150}\x{8151}\x{8152}\x{8153}\x{8154}\x{8155}\x{8156}\x{8157}' - . '\x{8158}\x{8159}\x{815A}\x{815B}\x{815C}\x{815D}\x{815E}\x{8160}\x{8161}' - . '\x{8162}\x{8163}\x{8164}\x{8165}\x{8166}\x{8167}\x{8168}\x{8169}\x{816A}' - . '\x{816B}\x{816C}\x{816D}\x{816E}\x{816F}\x{8170}\x{8171}\x{8172}\x{8173}' - . '\x{8174}\x{8175}\x{8176}\x{8177}\x{8178}\x{8179}\x{817A}\x{817B}\x{817C}' - . '\x{817D}\x{817E}\x{817F}\x{8180}\x{8181}\x{8182}\x{8183}\x{8185}\x{8186}' - . '\x{8187}\x{8188}\x{8189}\x{818A}\x{818B}\x{818C}\x{818D}\x{818E}\x{818F}' - . '\x{8191}\x{8192}\x{8193}\x{8194}\x{8195}\x{8197}\x{8198}\x{8199}\x{819A}' - . '\x{819B}\x{819C}\x{819D}\x{819E}\x{819F}\x{81A0}\x{81A1}\x{81A2}\x{81A3}' - . '\x{81A4}\x{81A5}\x{81A6}\x{81A7}\x{81A8}\x{81A9}\x{81AA}\x{81AB}\x{81AC}' - . '\x{81AD}\x{81AE}\x{81AF}\x{81B0}\x{81B1}\x{81B2}\x{81B3}\x{81B4}\x{81B5}' - . '\x{81B6}\x{81B7}\x{81B8}\x{81B9}\x{81BA}\x{81BB}\x{81BC}\x{81BD}\x{81BE}' - . '\x{81BF}\x{81C0}\x{81C1}\x{81C2}\x{81C3}\x{81C4}\x{81C5}\x{81C6}\x{81C7}' - . '\x{81C8}\x{81C9}\x{81CA}\x{81CC}\x{81CD}\x{81CE}\x{81CF}\x{81D0}\x{81D1}' - . '\x{81D2}\x{81D4}\x{81D5}\x{81D6}\x{81D7}\x{81D8}\x{81D9}\x{81DA}\x{81DB}' - . '\x{81DC}\x{81DD}\x{81DE}\x{81DF}\x{81E0}\x{81E1}\x{81E2}\x{81E3}\x{81E5}' - . '\x{81E6}\x{81E7}\x{81E8}\x{81E9}\x{81EA}\x{81EB}\x{81EC}\x{81ED}\x{81EE}' - . '\x{81F1}\x{81F2}\x{81F3}\x{81F4}\x{81F5}\x{81F6}\x{81F7}\x{81F8}\x{81F9}' - . '\x{81FA}\x{81FB}\x{81FC}\x{81FD}\x{81FE}\x{81FF}\x{8200}\x{8201}\x{8202}' - . '\x{8203}\x{8204}\x{8205}\x{8206}\x{8207}\x{8208}\x{8209}\x{820A}\x{820B}' - . '\x{820C}\x{820D}\x{820E}\x{820F}\x{8210}\x{8211}\x{8212}\x{8214}\x{8215}' - . '\x{8216}\x{8218}\x{8219}\x{821A}\x{821B}\x{821C}\x{821D}\x{821E}\x{821F}' - . '\x{8220}\x{8221}\x{8222}\x{8223}\x{8225}\x{8226}\x{8227}\x{8228}\x{8229}' - . '\x{822A}\x{822B}\x{822C}\x{822D}\x{822F}\x{8230}\x{8231}\x{8232}\x{8233}' - . '\x{8234}\x{8235}\x{8236}\x{8237}\x{8238}\x{8239}\x{823A}\x{823B}\x{823C}' - . '\x{823D}\x{823E}\x{823F}\x{8240}\x{8242}\x{8243}\x{8244}\x{8245}\x{8246}' - . '\x{8247}\x{8248}\x{8249}\x{824A}\x{824B}\x{824C}\x{824D}\x{824E}\x{824F}' - . '\x{8250}\x{8251}\x{8252}\x{8253}\x{8254}\x{8255}\x{8256}\x{8257}\x{8258}' - . '\x{8259}\x{825A}\x{825B}\x{825C}\x{825D}\x{825E}\x{825F}\x{8260}\x{8261}' - . '\x{8263}\x{8264}\x{8266}\x{8267}\x{8268}\x{8269}\x{826A}\x{826B}\x{826C}' - . '\x{826D}\x{826E}\x{826F}\x{8270}\x{8271}\x{8272}\x{8273}\x{8274}\x{8275}' - . '\x{8276}\x{8277}\x{8278}\x{8279}\x{827A}\x{827B}\x{827C}\x{827D}\x{827E}' - . '\x{827F}\x{8280}\x{8281}\x{8282}\x{8283}\x{8284}\x{8285}\x{8286}\x{8287}' - . '\x{8288}\x{8289}\x{828A}\x{828B}\x{828D}\x{828E}\x{828F}\x{8290}\x{8291}' - . '\x{8292}\x{8293}\x{8294}\x{8295}\x{8296}\x{8297}\x{8298}\x{8299}\x{829A}' - . '\x{829B}\x{829C}\x{829D}\x{829E}\x{829F}\x{82A0}\x{82A1}\x{82A2}\x{82A3}' - . '\x{82A4}\x{82A5}\x{82A6}\x{82A7}\x{82A8}\x{82A9}\x{82AA}\x{82AB}\x{82AC}' - . '\x{82AD}\x{82AE}\x{82AF}\x{82B0}\x{82B1}\x{82B3}\x{82B4}\x{82B5}\x{82B6}' - . '\x{82B7}\x{82B8}\x{82B9}\x{82BA}\x{82BB}\x{82BC}\x{82BD}\x{82BE}\x{82BF}' - . '\x{82C0}\x{82C1}\x{82C2}\x{82C3}\x{82C4}\x{82C5}\x{82C6}\x{82C7}\x{82C8}' - . '\x{82C9}\x{82CA}\x{82CB}\x{82CC}\x{82CD}\x{82CE}\x{82CF}\x{82D0}\x{82D1}' - . '\x{82D2}\x{82D3}\x{82D4}\x{82D5}\x{82D6}\x{82D7}\x{82D8}\x{82D9}\x{82DA}' - . '\x{82DB}\x{82DC}\x{82DD}\x{82DE}\x{82DF}\x{82E0}\x{82E1}\x{82E3}\x{82E4}' - . '\x{82E5}\x{82E6}\x{82E7}\x{82E8}\x{82E9}\x{82EA}\x{82EB}\x{82EC}\x{82ED}' - . '\x{82EE}\x{82EF}\x{82F0}\x{82F1}\x{82F2}\x{82F3}\x{82F4}\x{82F5}\x{82F6}' - . '\x{82F7}\x{82F8}\x{82F9}\x{82FA}\x{82FB}\x{82FD}\x{82FE}\x{82FF}\x{8300}' - . '\x{8301}\x{8302}\x{8303}\x{8304}\x{8305}\x{8306}\x{8307}\x{8308}\x{8309}' - . '\x{830B}\x{830C}\x{830D}\x{830E}\x{830F}\x{8311}\x{8312}\x{8313}\x{8314}' - . '\x{8315}\x{8316}\x{8317}\x{8318}\x{8319}\x{831A}\x{831B}\x{831C}\x{831D}' - . '\x{831E}\x{831F}\x{8320}\x{8321}\x{8322}\x{8323}\x{8324}\x{8325}\x{8326}' - . '\x{8327}\x{8328}\x{8329}\x{832A}\x{832B}\x{832C}\x{832D}\x{832E}\x{832F}' - . '\x{8331}\x{8332}\x{8333}\x{8334}\x{8335}\x{8336}\x{8337}\x{8338}\x{8339}' - . '\x{833A}\x{833B}\x{833C}\x{833D}\x{833E}\x{833F}\x{8340}\x{8341}\x{8342}' - . '\x{8343}\x{8344}\x{8345}\x{8346}\x{8347}\x{8348}\x{8349}\x{834A}\x{834B}' - . '\x{834C}\x{834D}\x{834E}\x{834F}\x{8350}\x{8351}\x{8352}\x{8353}\x{8354}' - . '\x{8356}\x{8357}\x{8358}\x{8359}\x{835A}\x{835B}\x{835C}\x{835D}\x{835E}' - . '\x{835F}\x{8360}\x{8361}\x{8362}\x{8363}\x{8364}\x{8365}\x{8366}\x{8367}' - . '\x{8368}\x{8369}\x{836A}\x{836B}\x{836C}\x{836D}\x{836E}\x{836F}\x{8370}' - . '\x{8371}\x{8372}\x{8373}\x{8374}\x{8375}\x{8376}\x{8377}\x{8378}\x{8379}' - . '\x{837A}\x{837B}\x{837C}\x{837D}\x{837E}\x{837F}\x{8380}\x{8381}\x{8382}' - . '\x{8383}\x{8384}\x{8385}\x{8386}\x{8387}\x{8388}\x{8389}\x{838A}\x{838B}' - . '\x{838C}\x{838D}\x{838E}\x{838F}\x{8390}\x{8391}\x{8392}\x{8393}\x{8394}' - . '\x{8395}\x{8396}\x{8397}\x{8398}\x{8399}\x{839A}\x{839B}\x{839C}\x{839D}' - . '\x{839E}\x{83A0}\x{83A1}\x{83A2}\x{83A3}\x{83A4}\x{83A5}\x{83A6}\x{83A7}' - . '\x{83A8}\x{83A9}\x{83AA}\x{83AB}\x{83AC}\x{83AD}\x{83AE}\x{83AF}\x{83B0}' - . '\x{83B1}\x{83B2}\x{83B3}\x{83B4}\x{83B6}\x{83B7}\x{83B8}\x{83B9}\x{83BA}' - . '\x{83BB}\x{83BC}\x{83BD}\x{83BF}\x{83C0}\x{83C1}\x{83C2}\x{83C3}\x{83C4}' - . '\x{83C5}\x{83C6}\x{83C7}\x{83C8}\x{83C9}\x{83CA}\x{83CB}\x{83CC}\x{83CD}' - . '\x{83CE}\x{83CF}\x{83D0}\x{83D1}\x{83D2}\x{83D3}\x{83D4}\x{83D5}\x{83D6}' - . '\x{83D7}\x{83D8}\x{83D9}\x{83DA}\x{83DB}\x{83DC}\x{83DD}\x{83DE}\x{83DF}' - . '\x{83E0}\x{83E1}\x{83E2}\x{83E3}\x{83E4}\x{83E5}\x{83E7}\x{83E8}\x{83E9}' - . '\x{83EA}\x{83EB}\x{83EC}\x{83EE}\x{83EF}\x{83F0}\x{83F1}\x{83F2}\x{83F3}' - . '\x{83F4}\x{83F5}\x{83F6}\x{83F7}\x{83F8}\x{83F9}\x{83FA}\x{83FB}\x{83FC}' - . '\x{83FD}\x{83FE}\x{83FF}\x{8400}\x{8401}\x{8402}\x{8403}\x{8404}\x{8405}' - . '\x{8406}\x{8407}\x{8408}\x{8409}\x{840A}\x{840B}\x{840C}\x{840D}\x{840E}' - . '\x{840F}\x{8410}\x{8411}\x{8412}\x{8413}\x{8415}\x{8418}\x{8419}\x{841A}' - . '\x{841B}\x{841C}\x{841D}\x{841E}\x{8421}\x{8422}\x{8423}\x{8424}\x{8425}' - . '\x{8426}\x{8427}\x{8428}\x{8429}\x{842A}\x{842B}\x{842C}\x{842D}\x{842E}' - . '\x{842F}\x{8430}\x{8431}\x{8432}\x{8433}\x{8434}\x{8435}\x{8436}\x{8437}' - . '\x{8438}\x{8439}\x{843A}\x{843B}\x{843C}\x{843D}\x{843E}\x{843F}\x{8440}' - . '\x{8441}\x{8442}\x{8443}\x{8444}\x{8445}\x{8446}\x{8447}\x{8448}\x{8449}' - . '\x{844A}\x{844B}\x{844C}\x{844D}\x{844E}\x{844F}\x{8450}\x{8451}\x{8452}' - . '\x{8453}\x{8454}\x{8455}\x{8456}\x{8457}\x{8459}\x{845A}\x{845B}\x{845C}' - . '\x{845D}\x{845E}\x{845F}\x{8460}\x{8461}\x{8462}\x{8463}\x{8464}\x{8465}' - . '\x{8466}\x{8467}\x{8468}\x{8469}\x{846A}\x{846B}\x{846C}\x{846D}\x{846E}' - . '\x{846F}\x{8470}\x{8471}\x{8472}\x{8473}\x{8474}\x{8475}\x{8476}\x{8477}' - . '\x{8478}\x{8479}\x{847A}\x{847B}\x{847C}\x{847D}\x{847E}\x{847F}\x{8480}' - . '\x{8481}\x{8482}\x{8484}\x{8485}\x{8486}\x{8487}\x{8488}\x{8489}\x{848A}' - . '\x{848B}\x{848C}\x{848D}\x{848E}\x{848F}\x{8490}\x{8491}\x{8492}\x{8493}' - . '\x{8494}\x{8496}\x{8497}\x{8498}\x{8499}\x{849A}\x{849B}\x{849C}\x{849D}' - . '\x{849E}\x{849F}\x{84A0}\x{84A1}\x{84A2}\x{84A3}\x{84A4}\x{84A5}\x{84A6}' - . '\x{84A7}\x{84A8}\x{84A9}\x{84AA}\x{84AB}\x{84AC}\x{84AE}\x{84AF}\x{84B0}' - . '\x{84B1}\x{84B2}\x{84B3}\x{84B4}\x{84B5}\x{84B6}\x{84B8}\x{84B9}\x{84BA}' - . '\x{84BB}\x{84BC}\x{84BD}\x{84BE}\x{84BF}\x{84C0}\x{84C1}\x{84C2}\x{84C4}' - . '\x{84C5}\x{84C6}\x{84C7}\x{84C8}\x{84C9}\x{84CA}\x{84CB}\x{84CC}\x{84CD}' - . '\x{84CE}\x{84CF}\x{84D0}\x{84D1}\x{84D2}\x{84D3}\x{84D4}\x{84D5}\x{84D6}' - . '\x{84D7}\x{84D8}\x{84D9}\x{84DB}\x{84DC}\x{84DD}\x{84DE}\x{84DF}\x{84E0}' - . '\x{84E1}\x{84E2}\x{84E3}\x{84E4}\x{84E5}\x{84E6}\x{84E7}\x{84E8}\x{84E9}' - . '\x{84EA}\x{84EB}\x{84EC}\x{84EE}\x{84EF}\x{84F0}\x{84F1}\x{84F2}\x{84F3}' - . '\x{84F4}\x{84F5}\x{84F6}\x{84F7}\x{84F8}\x{84F9}\x{84FA}\x{84FB}\x{84FC}' - . '\x{84FD}\x{84FE}\x{84FF}\x{8500}\x{8501}\x{8502}\x{8503}\x{8504}\x{8506}' - . '\x{8507}\x{8508}\x{8509}\x{850A}\x{850B}\x{850C}\x{850D}\x{850E}\x{850F}' - . '\x{8511}\x{8512}\x{8513}\x{8514}\x{8515}\x{8516}\x{8517}\x{8518}\x{8519}' - . '\x{851A}\x{851B}\x{851C}\x{851D}\x{851E}\x{851F}\x{8520}\x{8521}\x{8522}' - . '\x{8523}\x{8524}\x{8525}\x{8526}\x{8527}\x{8528}\x{8529}\x{852A}\x{852B}' - . '\x{852C}\x{852D}\x{852E}\x{852F}\x{8530}\x{8531}\x{8534}\x{8535}\x{8536}' - . '\x{8537}\x{8538}\x{8539}\x{853A}\x{853B}\x{853C}\x{853D}\x{853E}\x{853F}' - . '\x{8540}\x{8541}\x{8542}\x{8543}\x{8544}\x{8545}\x{8546}\x{8547}\x{8548}' - . '\x{8549}\x{854A}\x{854B}\x{854D}\x{854E}\x{854F}\x{8551}\x{8552}\x{8553}' - . '\x{8554}\x{8555}\x{8556}\x{8557}\x{8558}\x{8559}\x{855A}\x{855B}\x{855C}' - . '\x{855D}\x{855E}\x{855F}\x{8560}\x{8561}\x{8562}\x{8563}\x{8564}\x{8565}' - . '\x{8566}\x{8567}\x{8568}\x{8569}\x{856A}\x{856B}\x{856C}\x{856D}\x{856E}' - . '\x{856F}\x{8570}\x{8571}\x{8572}\x{8573}\x{8574}\x{8575}\x{8576}\x{8577}' - . '\x{8578}\x{8579}\x{857A}\x{857B}\x{857C}\x{857D}\x{857E}\x{8580}\x{8581}' - . '\x{8582}\x{8583}\x{8584}\x{8585}\x{8586}\x{8587}\x{8588}\x{8589}\x{858A}' - . '\x{858B}\x{858C}\x{858D}\x{858E}\x{858F}\x{8590}\x{8591}\x{8592}\x{8594}' - . '\x{8595}\x{8596}\x{8598}\x{8599}\x{859A}\x{859B}\x{859C}\x{859D}\x{859E}' - . '\x{859F}\x{85A0}\x{85A1}\x{85A2}\x{85A3}\x{85A4}\x{85A5}\x{85A6}\x{85A7}' - . '\x{85A8}\x{85A9}\x{85AA}\x{85AB}\x{85AC}\x{85AD}\x{85AE}\x{85AF}\x{85B0}' - . '\x{85B1}\x{85B3}\x{85B4}\x{85B5}\x{85B6}\x{85B7}\x{85B8}\x{85B9}\x{85BA}' - . '\x{85BC}\x{85BD}\x{85BE}\x{85BF}\x{85C0}\x{85C1}\x{85C2}\x{85C3}\x{85C4}' - . '\x{85C5}\x{85C6}\x{85C7}\x{85C8}\x{85C9}\x{85CA}\x{85CB}\x{85CD}\x{85CE}' - . '\x{85CF}\x{85D0}\x{85D1}\x{85D2}\x{85D3}\x{85D4}\x{85D5}\x{85D6}\x{85D7}' - . '\x{85D8}\x{85D9}\x{85DA}\x{85DB}\x{85DC}\x{85DD}\x{85DE}\x{85DF}\x{85E0}' - . '\x{85E1}\x{85E2}\x{85E3}\x{85E4}\x{85E5}\x{85E6}\x{85E7}\x{85E8}\x{85E9}' - . '\x{85EA}\x{85EB}\x{85EC}\x{85ED}\x{85EF}\x{85F0}\x{85F1}\x{85F2}\x{85F4}' - . '\x{85F5}\x{85F6}\x{85F7}\x{85F8}\x{85F9}\x{85FA}\x{85FB}\x{85FD}\x{85FE}' - . '\x{85FF}\x{8600}\x{8601}\x{8602}\x{8604}\x{8605}\x{8606}\x{8607}\x{8608}' - . '\x{8609}\x{860A}\x{860B}\x{860C}\x{860F}\x{8611}\x{8612}\x{8613}\x{8614}' - . '\x{8616}\x{8617}\x{8618}\x{8619}\x{861A}\x{861B}\x{861C}\x{861E}\x{861F}' - . '\x{8620}\x{8621}\x{8622}\x{8623}\x{8624}\x{8625}\x{8626}\x{8627}\x{8628}' - . '\x{8629}\x{862A}\x{862B}\x{862C}\x{862D}\x{862E}\x{862F}\x{8630}\x{8631}' - . '\x{8632}\x{8633}\x{8634}\x{8635}\x{8636}\x{8638}\x{8639}\x{863A}\x{863B}' - . '\x{863C}\x{863D}\x{863E}\x{863F}\x{8640}\x{8641}\x{8642}\x{8643}\x{8644}' - . '\x{8645}\x{8646}\x{8647}\x{8648}\x{8649}\x{864A}\x{864B}\x{864C}\x{864D}' - . '\x{864E}\x{864F}\x{8650}\x{8651}\x{8652}\x{8653}\x{8654}\x{8655}\x{8656}' - . '\x{8658}\x{8659}\x{865A}\x{865B}\x{865C}\x{865D}\x{865E}\x{865F}\x{8660}' - . '\x{8661}\x{8662}\x{8663}\x{8664}\x{8665}\x{8666}\x{8667}\x{8668}\x{8669}' - . '\x{866A}\x{866B}\x{866C}\x{866D}\x{866E}\x{866F}\x{8670}\x{8671}\x{8672}' - . '\x{8673}\x{8674}\x{8676}\x{8677}\x{8678}\x{8679}\x{867A}\x{867B}\x{867C}' - . '\x{867D}\x{867E}\x{867F}\x{8680}\x{8681}\x{8682}\x{8683}\x{8684}\x{8685}' - . '\x{8686}\x{8687}\x{8688}\x{868A}\x{868B}\x{868C}\x{868D}\x{868E}\x{868F}' - . '\x{8690}\x{8691}\x{8693}\x{8694}\x{8695}\x{8696}\x{8697}\x{8698}\x{8699}' - . '\x{869A}\x{869B}\x{869C}\x{869D}\x{869E}\x{869F}\x{86A1}\x{86A2}\x{86A3}' - . '\x{86A4}\x{86A5}\x{86A7}\x{86A8}\x{86A9}\x{86AA}\x{86AB}\x{86AC}\x{86AD}' - . '\x{86AE}\x{86AF}\x{86B0}\x{86B1}\x{86B2}\x{86B3}\x{86B4}\x{86B5}\x{86B6}' - . '\x{86B7}\x{86B8}\x{86B9}\x{86BA}\x{86BB}\x{86BC}\x{86BD}\x{86BE}\x{86BF}' - . '\x{86C0}\x{86C1}\x{86C2}\x{86C3}\x{86C4}\x{86C5}\x{86C6}\x{86C7}\x{86C8}' - . '\x{86C9}\x{86CA}\x{86CB}\x{86CC}\x{86CE}\x{86CF}\x{86D0}\x{86D1}\x{86D2}' - . '\x{86D3}\x{86D4}\x{86D6}\x{86D7}\x{86D8}\x{86D9}\x{86DA}\x{86DB}\x{86DC}' - . '\x{86DD}\x{86DE}\x{86DF}\x{86E1}\x{86E2}\x{86E3}\x{86E4}\x{86E5}\x{86E6}' - . '\x{86E8}\x{86E9}\x{86EA}\x{86EB}\x{86EC}\x{86ED}\x{86EE}\x{86EF}\x{86F0}' - . '\x{86F1}\x{86F2}\x{86F3}\x{86F4}\x{86F5}\x{86F6}\x{86F7}\x{86F8}\x{86F9}' - . '\x{86FA}\x{86FB}\x{86FC}\x{86FE}\x{86FF}\x{8700}\x{8701}\x{8702}\x{8703}' - . '\x{8704}\x{8705}\x{8706}\x{8707}\x{8708}\x{8709}\x{870A}\x{870B}\x{870C}' - . '\x{870D}\x{870E}\x{870F}\x{8710}\x{8711}\x{8712}\x{8713}\x{8714}\x{8715}' - . '\x{8716}\x{8717}\x{8718}\x{8719}\x{871A}\x{871B}\x{871C}\x{871E}\x{871F}' - . '\x{8720}\x{8721}\x{8722}\x{8723}\x{8724}\x{8725}\x{8726}\x{8727}\x{8728}' - . '\x{8729}\x{872A}\x{872B}\x{872C}\x{872D}\x{872E}\x{8730}\x{8731}\x{8732}' - . '\x{8733}\x{8734}\x{8735}\x{8736}\x{8737}\x{8738}\x{8739}\x{873A}\x{873B}' - . '\x{873C}\x{873E}\x{873F}\x{8740}\x{8741}\x{8742}\x{8743}\x{8744}\x{8746}' - . '\x{8747}\x{8748}\x{8749}\x{874A}\x{874C}\x{874D}\x{874E}\x{874F}\x{8750}' - . '\x{8751}\x{8752}\x{8753}\x{8754}\x{8755}\x{8756}\x{8757}\x{8758}\x{8759}' - . '\x{875A}\x{875B}\x{875C}\x{875D}\x{875E}\x{875F}\x{8760}\x{8761}\x{8762}' - . '\x{8763}\x{8764}\x{8765}\x{8766}\x{8767}\x{8768}\x{8769}\x{876A}\x{876B}' - . '\x{876C}\x{876D}\x{876E}\x{876F}\x{8770}\x{8772}\x{8773}\x{8774}\x{8775}' - . '\x{8776}\x{8777}\x{8778}\x{8779}\x{877A}\x{877B}\x{877C}\x{877D}\x{877E}' - . '\x{8780}\x{8781}\x{8782}\x{8783}\x{8784}\x{8785}\x{8786}\x{8787}\x{8788}' - . '\x{8789}\x{878A}\x{878B}\x{878C}\x{878D}\x{878F}\x{8790}\x{8791}\x{8792}' - . '\x{8793}\x{8794}\x{8795}\x{8796}\x{8797}\x{8798}\x{879A}\x{879B}\x{879C}' - . '\x{879D}\x{879E}\x{879F}\x{87A0}\x{87A1}\x{87A2}\x{87A3}\x{87A4}\x{87A5}' - . '\x{87A6}\x{87A7}\x{87A8}\x{87A9}\x{87AA}\x{87AB}\x{87AC}\x{87AD}\x{87AE}' - . '\x{87AF}\x{87B0}\x{87B1}\x{87B2}\x{87B3}\x{87B4}\x{87B5}\x{87B6}\x{87B7}' - . '\x{87B8}\x{87B9}\x{87BA}\x{87BB}\x{87BC}\x{87BD}\x{87BE}\x{87BF}\x{87C0}' - . '\x{87C1}\x{87C2}\x{87C3}\x{87C4}\x{87C5}\x{87C6}\x{87C7}\x{87C8}\x{87C9}' - . '\x{87CA}\x{87CB}\x{87CC}\x{87CD}\x{87CE}\x{87CF}\x{87D0}\x{87D1}\x{87D2}' - . '\x{87D3}\x{87D4}\x{87D5}\x{87D6}\x{87D7}\x{87D8}\x{87D9}\x{87DB}\x{87DC}' - . '\x{87DD}\x{87DE}\x{87DF}\x{87E0}\x{87E1}\x{87E2}\x{87E3}\x{87E4}\x{87E5}' - . '\x{87E6}\x{87E7}\x{87E8}\x{87E9}\x{87EA}\x{87EB}\x{87EC}\x{87ED}\x{87EE}' - . '\x{87EF}\x{87F1}\x{87F2}\x{87F3}\x{87F4}\x{87F5}\x{87F6}\x{87F7}\x{87F8}' - . '\x{87F9}\x{87FA}\x{87FB}\x{87FC}\x{87FD}\x{87FE}\x{87FF}\x{8800}\x{8801}' - . '\x{8802}\x{8803}\x{8804}\x{8805}\x{8806}\x{8808}\x{8809}\x{880A}\x{880B}' - . '\x{880C}\x{880D}\x{880E}\x{880F}\x{8810}\x{8811}\x{8813}\x{8814}\x{8815}' - . '\x{8816}\x{8817}\x{8818}\x{8819}\x{881A}\x{881B}\x{881C}\x{881D}\x{881E}' - . '\x{881F}\x{8820}\x{8821}\x{8822}\x{8823}\x{8824}\x{8825}\x{8826}\x{8827}' - . '\x{8828}\x{8829}\x{882A}\x{882B}\x{882C}\x{882E}\x{882F}\x{8830}\x{8831}' - . '\x{8832}\x{8833}\x{8834}\x{8835}\x{8836}\x{8837}\x{8838}\x{8839}\x{883B}' - . '\x{883C}\x{883D}\x{883E}\x{883F}\x{8840}\x{8841}\x{8842}\x{8843}\x{8844}' - . '\x{8845}\x{8846}\x{8848}\x{8849}\x{884A}\x{884B}\x{884C}\x{884D}\x{884E}' - . '\x{884F}\x{8850}\x{8851}\x{8852}\x{8853}\x{8854}\x{8855}\x{8856}\x{8857}' - . '\x{8859}\x{885A}\x{885B}\x{885D}\x{885E}\x{8860}\x{8861}\x{8862}\x{8863}' - . '\x{8864}\x{8865}\x{8866}\x{8867}\x{8868}\x{8869}\x{886A}\x{886B}\x{886C}' - . '\x{886D}\x{886E}\x{886F}\x{8870}\x{8871}\x{8872}\x{8873}\x{8874}\x{8875}' - . '\x{8876}\x{8877}\x{8878}\x{8879}\x{887B}\x{887C}\x{887D}\x{887E}\x{887F}' - . '\x{8880}\x{8881}\x{8882}\x{8883}\x{8884}\x{8885}\x{8886}\x{8887}\x{8888}' - . '\x{8889}\x{888A}\x{888B}\x{888C}\x{888D}\x{888E}\x{888F}\x{8890}\x{8891}' - . '\x{8892}\x{8893}\x{8894}\x{8895}\x{8896}\x{8897}\x{8898}\x{8899}\x{889A}' - . '\x{889B}\x{889C}\x{889D}\x{889E}\x{889F}\x{88A0}\x{88A1}\x{88A2}\x{88A3}' - . '\x{88A4}\x{88A5}\x{88A6}\x{88A7}\x{88A8}\x{88A9}\x{88AA}\x{88AB}\x{88AC}' - . '\x{88AD}\x{88AE}\x{88AF}\x{88B0}\x{88B1}\x{88B2}\x{88B3}\x{88B4}\x{88B6}' - . '\x{88B7}\x{88B8}\x{88B9}\x{88BA}\x{88BB}\x{88BC}\x{88BD}\x{88BE}\x{88BF}' - . '\x{88C0}\x{88C1}\x{88C2}\x{88C3}\x{88C4}\x{88C5}\x{88C6}\x{88C7}\x{88C8}' - . '\x{88C9}\x{88CA}\x{88CB}\x{88CC}\x{88CD}\x{88CE}\x{88CF}\x{88D0}\x{88D1}' - . '\x{88D2}\x{88D3}\x{88D4}\x{88D5}\x{88D6}\x{88D7}\x{88D8}\x{88D9}\x{88DA}' - . '\x{88DB}\x{88DC}\x{88DD}\x{88DE}\x{88DF}\x{88E0}\x{88E1}\x{88E2}\x{88E3}' - . '\x{88E4}\x{88E5}\x{88E7}\x{88E8}\x{88EA}\x{88EB}\x{88EC}\x{88EE}\x{88EF}' - . '\x{88F0}\x{88F1}\x{88F2}\x{88F3}\x{88F4}\x{88F5}\x{88F6}\x{88F7}\x{88F8}' - . '\x{88F9}\x{88FA}\x{88FB}\x{88FC}\x{88FD}\x{88FE}\x{88FF}\x{8900}\x{8901}' - . '\x{8902}\x{8904}\x{8905}\x{8906}\x{8907}\x{8908}\x{8909}\x{890A}\x{890B}' - . '\x{890C}\x{890D}\x{890E}\x{8910}\x{8911}\x{8912}\x{8913}\x{8914}\x{8915}' - . '\x{8916}\x{8917}\x{8918}\x{8919}\x{891A}\x{891B}\x{891C}\x{891D}\x{891E}' - . '\x{891F}\x{8920}\x{8921}\x{8922}\x{8923}\x{8925}\x{8926}\x{8927}\x{8928}' - . '\x{8929}\x{892A}\x{892B}\x{892C}\x{892D}\x{892E}\x{892F}\x{8930}\x{8931}' - . '\x{8932}\x{8933}\x{8934}\x{8935}\x{8936}\x{8937}\x{8938}\x{8939}\x{893A}' - . '\x{893B}\x{893C}\x{893D}\x{893E}\x{893F}\x{8940}\x{8941}\x{8942}\x{8943}' - . '\x{8944}\x{8945}\x{8946}\x{8947}\x{8948}\x{8949}\x{894A}\x{894B}\x{894C}' - . '\x{894E}\x{894F}\x{8950}\x{8951}\x{8952}\x{8953}\x{8954}\x{8955}\x{8956}' - . '\x{8957}\x{8958}\x{8959}\x{895A}\x{895B}\x{895C}\x{895D}\x{895E}\x{895F}' - . '\x{8960}\x{8961}\x{8962}\x{8963}\x{8964}\x{8966}\x{8967}\x{8968}\x{8969}' - . '\x{896A}\x{896B}\x{896C}\x{896D}\x{896E}\x{896F}\x{8970}\x{8971}\x{8972}' - . '\x{8973}\x{8974}\x{8976}\x{8977}\x{8978}\x{8979}\x{897A}\x{897B}\x{897C}' - . '\x{897E}\x{897F}\x{8980}\x{8981}\x{8982}\x{8983}\x{8984}\x{8985}\x{8986}' - . '\x{8987}\x{8988}\x{8989}\x{898A}\x{898B}\x{898C}\x{898E}\x{898F}\x{8991}' - . '\x{8992}\x{8993}\x{8995}\x{8996}\x{8997}\x{8998}\x{899A}\x{899B}\x{899C}' - . '\x{899D}\x{899E}\x{899F}\x{89A0}\x{89A1}\x{89A2}\x{89A3}\x{89A4}\x{89A5}' - . '\x{89A6}\x{89A7}\x{89A8}\x{89AA}\x{89AB}\x{89AC}\x{89AD}\x{89AE}\x{89AF}' - . '\x{89B1}\x{89B2}\x{89B3}\x{89B5}\x{89B6}\x{89B7}\x{89B8}\x{89B9}\x{89BA}' - . '\x{89BD}\x{89BE}\x{89BF}\x{89C0}\x{89C1}\x{89C2}\x{89C3}\x{89C4}\x{89C5}' - . '\x{89C6}\x{89C7}\x{89C8}\x{89C9}\x{89CA}\x{89CB}\x{89CC}\x{89CD}\x{89CE}' - . '\x{89CF}\x{89D0}\x{89D1}\x{89D2}\x{89D3}\x{89D4}\x{89D5}\x{89D6}\x{89D7}' - . '\x{89D8}\x{89D9}\x{89DA}\x{89DB}\x{89DC}\x{89DD}\x{89DE}\x{89DF}\x{89E0}' - . '\x{89E1}\x{89E2}\x{89E3}\x{89E4}\x{89E5}\x{89E6}\x{89E7}\x{89E8}\x{89E9}' - . '\x{89EA}\x{89EB}\x{89EC}\x{89ED}\x{89EF}\x{89F0}\x{89F1}\x{89F2}\x{89F3}' - . '\x{89F4}\x{89F6}\x{89F7}\x{89F8}\x{89FA}\x{89FB}\x{89FC}\x{89FE}\x{89FF}' - . '\x{8A00}\x{8A01}\x{8A02}\x{8A03}\x{8A04}\x{8A07}\x{8A08}\x{8A09}\x{8A0A}' - . '\x{8A0B}\x{8A0C}\x{8A0D}\x{8A0E}\x{8A0F}\x{8A10}\x{8A11}\x{8A12}\x{8A13}' - . '\x{8A15}\x{8A16}\x{8A17}\x{8A18}\x{8A1A}\x{8A1B}\x{8A1C}\x{8A1D}\x{8A1E}' - . '\x{8A1F}\x{8A22}\x{8A23}\x{8A24}\x{8A25}\x{8A26}\x{8A27}\x{8A28}\x{8A29}' - . '\x{8A2A}\x{8A2C}\x{8A2D}\x{8A2E}\x{8A2F}\x{8A30}\x{8A31}\x{8A32}\x{8A34}' - . '\x{8A35}\x{8A36}\x{8A37}\x{8A38}\x{8A39}\x{8A3A}\x{8A3B}\x{8A3C}\x{8A3E}' - . '\x{8A3F}\x{8A40}\x{8A41}\x{8A42}\x{8A43}\x{8A44}\x{8A45}\x{8A46}\x{8A47}' - . '\x{8A48}\x{8A49}\x{8A4A}\x{8A4C}\x{8A4D}\x{8A4E}\x{8A4F}\x{8A50}\x{8A51}' - . '\x{8A52}\x{8A53}\x{8A54}\x{8A55}\x{8A56}\x{8A57}\x{8A58}\x{8A59}\x{8A5A}' - . '\x{8A5B}\x{8A5C}\x{8A5D}\x{8A5E}\x{8A5F}\x{8A60}\x{8A61}\x{8A62}\x{8A63}' - . '\x{8A65}\x{8A66}\x{8A67}\x{8A68}\x{8A69}\x{8A6A}\x{8A6B}\x{8A6C}\x{8A6D}' - . '\x{8A6E}\x{8A6F}\x{8A70}\x{8A71}\x{8A72}\x{8A73}\x{8A74}\x{8A75}\x{8A76}' - . '\x{8A77}\x{8A79}\x{8A7A}\x{8A7B}\x{8A7C}\x{8A7E}\x{8A7F}\x{8A80}\x{8A81}' - . '\x{8A82}\x{8A83}\x{8A84}\x{8A85}\x{8A86}\x{8A87}\x{8A89}\x{8A8A}\x{8A8B}' - . '\x{8A8C}\x{8A8D}\x{8A8E}\x{8A8F}\x{8A90}\x{8A91}\x{8A92}\x{8A93}\x{8A94}' - . '\x{8A95}\x{8A96}\x{8A97}\x{8A98}\x{8A99}\x{8A9A}\x{8A9B}\x{8A9C}\x{8A9D}' - . '\x{8A9E}\x{8AA0}\x{8AA1}\x{8AA2}\x{8AA3}\x{8AA4}\x{8AA5}\x{8AA6}\x{8AA7}' - . '\x{8AA8}\x{8AA9}\x{8AAA}\x{8AAB}\x{8AAC}\x{8AAE}\x{8AB0}\x{8AB1}\x{8AB2}' - . '\x{8AB3}\x{8AB4}\x{8AB5}\x{8AB6}\x{8AB8}\x{8AB9}\x{8ABA}\x{8ABB}\x{8ABC}' - . '\x{8ABD}\x{8ABE}\x{8ABF}\x{8AC0}\x{8AC1}\x{8AC2}\x{8AC3}\x{8AC4}\x{8AC5}' - . '\x{8AC6}\x{8AC7}\x{8AC8}\x{8AC9}\x{8ACA}\x{8ACB}\x{8ACC}\x{8ACD}\x{8ACE}' - . '\x{8ACF}\x{8AD1}\x{8AD2}\x{8AD3}\x{8AD4}\x{8AD5}\x{8AD6}\x{8AD7}\x{8AD8}' - . '\x{8AD9}\x{8ADA}\x{8ADB}\x{8ADC}\x{8ADD}\x{8ADE}\x{8ADF}\x{8AE0}\x{8AE1}' - . '\x{8AE2}\x{8AE3}\x{8AE4}\x{8AE5}\x{8AE6}\x{8AE7}\x{8AE8}\x{8AE9}\x{8AEA}' - . '\x{8AEB}\x{8AED}\x{8AEE}\x{8AEF}\x{8AF0}\x{8AF1}\x{8AF2}\x{8AF3}\x{8AF4}' - . '\x{8AF5}\x{8AF6}\x{8AF7}\x{8AF8}\x{8AF9}\x{8AFA}\x{8AFB}\x{8AFC}\x{8AFD}' - . '\x{8AFE}\x{8AFF}\x{8B00}\x{8B01}\x{8B02}\x{8B03}\x{8B04}\x{8B05}\x{8B06}' - . '\x{8B07}\x{8B08}\x{8B09}\x{8B0A}\x{8B0B}\x{8B0D}\x{8B0E}\x{8B0F}\x{8B10}' - . '\x{8B11}\x{8B12}\x{8B13}\x{8B14}\x{8B15}\x{8B16}\x{8B17}\x{8B18}\x{8B19}' - . '\x{8B1A}\x{8B1B}\x{8B1C}\x{8B1D}\x{8B1E}\x{8B1F}\x{8B20}\x{8B21}\x{8B22}' - . '\x{8B23}\x{8B24}\x{8B25}\x{8B26}\x{8B27}\x{8B28}\x{8B2A}\x{8B2B}\x{8B2C}' - . '\x{8B2D}\x{8B2E}\x{8B2F}\x{8B30}\x{8B31}\x{8B33}\x{8B34}\x{8B35}\x{8B36}' - . '\x{8B37}\x{8B39}\x{8B3A}\x{8B3B}\x{8B3C}\x{8B3D}\x{8B3E}\x{8B40}\x{8B41}' - . '\x{8B42}\x{8B43}\x{8B44}\x{8B45}\x{8B46}\x{8B47}\x{8B48}\x{8B49}\x{8B4A}' - . '\x{8B4B}\x{8B4C}\x{8B4D}\x{8B4E}\x{8B4F}\x{8B50}\x{8B51}\x{8B52}\x{8B53}' - . '\x{8B54}\x{8B55}\x{8B56}\x{8B57}\x{8B58}\x{8B59}\x{8B5A}\x{8B5B}\x{8B5C}' - . '\x{8B5D}\x{8B5E}\x{8B5F}\x{8B60}\x{8B63}\x{8B64}\x{8B65}\x{8B66}\x{8B67}' - . '\x{8B68}\x{8B6A}\x{8B6B}\x{8B6C}\x{8B6D}\x{8B6E}\x{8B6F}\x{8B70}\x{8B71}' - . '\x{8B73}\x{8B74}\x{8B76}\x{8B77}\x{8B78}\x{8B79}\x{8B7A}\x{8B7B}\x{8B7D}' - . '\x{8B7E}\x{8B7F}\x{8B80}\x{8B82}\x{8B83}\x{8B84}\x{8B85}\x{8B86}\x{8B88}' - . '\x{8B89}\x{8B8A}\x{8B8B}\x{8B8C}\x{8B8E}\x{8B90}\x{8B91}\x{8B92}\x{8B93}' - . '\x{8B94}\x{8B95}\x{8B96}\x{8B97}\x{8B98}\x{8B99}\x{8B9A}\x{8B9C}\x{8B9D}' - . '\x{8B9E}\x{8B9F}\x{8BA0}\x{8BA1}\x{8BA2}\x{8BA3}\x{8BA4}\x{8BA5}\x{8BA6}' - . '\x{8BA7}\x{8BA8}\x{8BA9}\x{8BAA}\x{8BAB}\x{8BAC}\x{8BAD}\x{8BAE}\x{8BAF}' - . '\x{8BB0}\x{8BB1}\x{8BB2}\x{8BB3}\x{8BB4}\x{8BB5}\x{8BB6}\x{8BB7}\x{8BB8}' - . '\x{8BB9}\x{8BBA}\x{8BBB}\x{8BBC}\x{8BBD}\x{8BBE}\x{8BBF}\x{8BC0}\x{8BC1}' - . '\x{8BC2}\x{8BC3}\x{8BC4}\x{8BC5}\x{8BC6}\x{8BC7}\x{8BC8}\x{8BC9}\x{8BCA}' - . '\x{8BCB}\x{8BCC}\x{8BCD}\x{8BCE}\x{8BCF}\x{8BD0}\x{8BD1}\x{8BD2}\x{8BD3}' - . '\x{8BD4}\x{8BD5}\x{8BD6}\x{8BD7}\x{8BD8}\x{8BD9}\x{8BDA}\x{8BDB}\x{8BDC}' - . '\x{8BDD}\x{8BDE}\x{8BDF}\x{8BE0}\x{8BE1}\x{8BE2}\x{8BE3}\x{8BE4}\x{8BE5}' - . '\x{8BE6}\x{8BE7}\x{8BE8}\x{8BE9}\x{8BEA}\x{8BEB}\x{8BEC}\x{8BED}\x{8BEE}' - . '\x{8BEF}\x{8BF0}\x{8BF1}\x{8BF2}\x{8BF3}\x{8BF4}\x{8BF5}\x{8BF6}\x{8BF7}' - . '\x{8BF8}\x{8BF9}\x{8BFA}\x{8BFB}\x{8BFC}\x{8BFD}\x{8BFE}\x{8BFF}\x{8C00}' - . '\x{8C01}\x{8C02}\x{8C03}\x{8C04}\x{8C05}\x{8C06}\x{8C07}\x{8C08}\x{8C09}' - . '\x{8C0A}\x{8C0B}\x{8C0C}\x{8C0D}\x{8C0E}\x{8C0F}\x{8C10}\x{8C11}\x{8C12}' - . '\x{8C13}\x{8C14}\x{8C15}\x{8C16}\x{8C17}\x{8C18}\x{8C19}\x{8C1A}\x{8C1B}' - . '\x{8C1C}\x{8C1D}\x{8C1E}\x{8C1F}\x{8C20}\x{8C21}\x{8C22}\x{8C23}\x{8C24}' - . '\x{8C25}\x{8C26}\x{8C27}\x{8C28}\x{8C29}\x{8C2A}\x{8C2B}\x{8C2C}\x{8C2D}' - . '\x{8C2E}\x{8C2F}\x{8C30}\x{8C31}\x{8C32}\x{8C33}\x{8C34}\x{8C35}\x{8C36}' - . '\x{8C37}\x{8C39}\x{8C3A}\x{8C3B}\x{8C3C}\x{8C3D}\x{8C3E}\x{8C3F}\x{8C41}' - . '\x{8C42}\x{8C43}\x{8C45}\x{8C46}\x{8C47}\x{8C48}\x{8C49}\x{8C4A}\x{8C4B}' - . '\x{8C4C}\x{8C4D}\x{8C4E}\x{8C4F}\x{8C50}\x{8C54}\x{8C55}\x{8C56}\x{8C57}' - . '\x{8C59}\x{8C5A}\x{8C5B}\x{8C5C}\x{8C5D}\x{8C5E}\x{8C5F}\x{8C60}\x{8C61}' - . '\x{8C62}\x{8C63}\x{8C64}\x{8C65}\x{8C66}\x{8C67}\x{8C68}\x{8C69}\x{8C6A}' - . '\x{8C6B}\x{8C6C}\x{8C6D}\x{8C6E}\x{8C6F}\x{8C70}\x{8C71}\x{8C72}\x{8C73}' - . '\x{8C75}\x{8C76}\x{8C77}\x{8C78}\x{8C79}\x{8C7A}\x{8C7B}\x{8C7D}\x{8C7E}' - . '\x{8C80}\x{8C81}\x{8C82}\x{8C84}\x{8C85}\x{8C86}\x{8C88}\x{8C89}\x{8C8A}' - . '\x{8C8C}\x{8C8D}\x{8C8F}\x{8C90}\x{8C91}\x{8C92}\x{8C93}\x{8C94}\x{8C95}' - . '\x{8C96}\x{8C97}\x{8C98}\x{8C99}\x{8C9A}\x{8C9C}\x{8C9D}\x{8C9E}\x{8C9F}' - . '\x{8CA0}\x{8CA1}\x{8CA2}\x{8CA3}\x{8CA4}\x{8CA5}\x{8CA7}\x{8CA8}\x{8CA9}' - . '\x{8CAA}\x{8CAB}\x{8CAC}\x{8CAD}\x{8CAE}\x{8CAF}\x{8CB0}\x{8CB1}\x{8CB2}' - . '\x{8CB3}\x{8CB4}\x{8CB5}\x{8CB6}\x{8CB7}\x{8CB8}\x{8CB9}\x{8CBA}\x{8CBB}' - . '\x{8CBC}\x{8CBD}\x{8CBE}\x{8CBF}\x{8CC0}\x{8CC1}\x{8CC2}\x{8CC3}\x{8CC4}' - . '\x{8CC5}\x{8CC6}\x{8CC7}\x{8CC8}\x{8CC9}\x{8CCA}\x{8CCC}\x{8CCE}\x{8CCF}' - . '\x{8CD0}\x{8CD1}\x{8CD2}\x{8CD3}\x{8CD4}\x{8CD5}\x{8CD7}\x{8CD9}\x{8CDA}' - . '\x{8CDB}\x{8CDC}\x{8CDD}\x{8CDE}\x{8CDF}\x{8CE0}\x{8CE1}\x{8CE2}\x{8CE3}' - . '\x{8CE4}\x{8CE5}\x{8CE6}\x{8CE7}\x{8CE8}\x{8CEA}\x{8CEB}\x{8CEC}\x{8CED}' - . '\x{8CEE}\x{8CEF}\x{8CF0}\x{8CF1}\x{8CF2}\x{8CF3}\x{8CF4}\x{8CF5}\x{8CF6}' - . '\x{8CF8}\x{8CF9}\x{8CFA}\x{8CFB}\x{8CFC}\x{8CFD}\x{8CFE}\x{8CFF}\x{8D00}' - . '\x{8D02}\x{8D03}\x{8D04}\x{8D05}\x{8D06}\x{8D07}\x{8D08}\x{8D09}\x{8D0A}' - . '\x{8D0B}\x{8D0C}\x{8D0D}\x{8D0E}\x{8D0F}\x{8D10}\x{8D13}\x{8D14}\x{8D15}' - . '\x{8D16}\x{8D17}\x{8D18}\x{8D19}\x{8D1A}\x{8D1B}\x{8D1C}\x{8D1D}\x{8D1E}' - . '\x{8D1F}\x{8D20}\x{8D21}\x{8D22}\x{8D23}\x{8D24}\x{8D25}\x{8D26}\x{8D27}' - . '\x{8D28}\x{8D29}\x{8D2A}\x{8D2B}\x{8D2C}\x{8D2D}\x{8D2E}\x{8D2F}\x{8D30}' - . '\x{8D31}\x{8D32}\x{8D33}\x{8D34}\x{8D35}\x{8D36}\x{8D37}\x{8D38}\x{8D39}' - . '\x{8D3A}\x{8D3B}\x{8D3C}\x{8D3D}\x{8D3E}\x{8D3F}\x{8D40}\x{8D41}\x{8D42}' - . '\x{8D43}\x{8D44}\x{8D45}\x{8D46}\x{8D47}\x{8D48}\x{8D49}\x{8D4A}\x{8D4B}' - . '\x{8D4C}\x{8D4D}\x{8D4E}\x{8D4F}\x{8D50}\x{8D51}\x{8D52}\x{8D53}\x{8D54}' - . '\x{8D55}\x{8D56}\x{8D57}\x{8D58}\x{8D59}\x{8D5A}\x{8D5B}\x{8D5C}\x{8D5D}' - . '\x{8D5E}\x{8D5F}\x{8D60}\x{8D61}\x{8D62}\x{8D63}\x{8D64}\x{8D65}\x{8D66}' - . '\x{8D67}\x{8D68}\x{8D69}\x{8D6A}\x{8D6B}\x{8D6C}\x{8D6D}\x{8D6E}\x{8D6F}' - . '\x{8D70}\x{8D71}\x{8D72}\x{8D73}\x{8D74}\x{8D75}\x{8D76}\x{8D77}\x{8D78}' - . '\x{8D79}\x{8D7A}\x{8D7B}\x{8D7D}\x{8D7E}\x{8D7F}\x{8D80}\x{8D81}\x{8D82}' - . '\x{8D83}\x{8D84}\x{8D85}\x{8D86}\x{8D87}\x{8D88}\x{8D89}\x{8D8A}\x{8D8B}' - . '\x{8D8C}\x{8D8D}\x{8D8E}\x{8D8F}\x{8D90}\x{8D91}\x{8D92}\x{8D93}\x{8D94}' - . '\x{8D95}\x{8D96}\x{8D97}\x{8D98}\x{8D99}\x{8D9A}\x{8D9B}\x{8D9C}\x{8D9D}' - . '\x{8D9E}\x{8D9F}\x{8DA0}\x{8DA1}\x{8DA2}\x{8DA3}\x{8DA4}\x{8DA5}\x{8DA7}' - . '\x{8DA8}\x{8DA9}\x{8DAA}\x{8DAB}\x{8DAC}\x{8DAD}\x{8DAE}\x{8DAF}\x{8DB0}' - . '\x{8DB1}\x{8DB2}\x{8DB3}\x{8DB4}\x{8DB5}\x{8DB6}\x{8DB7}\x{8DB8}\x{8DB9}' - . '\x{8DBA}\x{8DBB}\x{8DBC}\x{8DBD}\x{8DBE}\x{8DBF}\x{8DC1}\x{8DC2}\x{8DC3}' - . '\x{8DC4}\x{8DC5}\x{8DC6}\x{8DC7}\x{8DC8}\x{8DC9}\x{8DCA}\x{8DCB}\x{8DCC}' - . '\x{8DCD}\x{8DCE}\x{8DCF}\x{8DD0}\x{8DD1}\x{8DD2}\x{8DD3}\x{8DD4}\x{8DD5}' - . '\x{8DD6}\x{8DD7}\x{8DD8}\x{8DD9}\x{8DDA}\x{8DDB}\x{8DDC}\x{8DDD}\x{8DDE}' - . '\x{8DDF}\x{8DE0}\x{8DE1}\x{8DE2}\x{8DE3}\x{8DE4}\x{8DE6}\x{8DE7}\x{8DE8}' - . '\x{8DE9}\x{8DEA}\x{8DEB}\x{8DEC}\x{8DED}\x{8DEE}\x{8DEF}\x{8DF0}\x{8DF1}' - . '\x{8DF2}\x{8DF3}\x{8DF4}\x{8DF5}\x{8DF6}\x{8DF7}\x{8DF8}\x{8DF9}\x{8DFA}' - . '\x{8DFB}\x{8DFC}\x{8DFD}\x{8DFE}\x{8DFF}\x{8E00}\x{8E02}\x{8E03}\x{8E04}' - . '\x{8E05}\x{8E06}\x{8E07}\x{8E08}\x{8E09}\x{8E0A}\x{8E0C}\x{8E0D}\x{8E0E}' - . '\x{8E0F}\x{8E10}\x{8E11}\x{8E12}\x{8E13}\x{8E14}\x{8E15}\x{8E16}\x{8E17}' - . '\x{8E18}\x{8E19}\x{8E1A}\x{8E1B}\x{8E1C}\x{8E1D}\x{8E1E}\x{8E1F}\x{8E20}' - . '\x{8E21}\x{8E22}\x{8E23}\x{8E24}\x{8E25}\x{8E26}\x{8E27}\x{8E28}\x{8E29}' - . '\x{8E2A}\x{8E2B}\x{8E2C}\x{8E2D}\x{8E2E}\x{8E2F}\x{8E30}\x{8E31}\x{8E33}' - . '\x{8E34}\x{8E35}\x{8E36}\x{8E37}\x{8E38}\x{8E39}\x{8E3A}\x{8E3B}\x{8E3C}' - . '\x{8E3D}\x{8E3E}\x{8E3F}\x{8E40}\x{8E41}\x{8E42}\x{8E43}\x{8E44}\x{8E45}' - . '\x{8E47}\x{8E48}\x{8E49}\x{8E4A}\x{8E4B}\x{8E4C}\x{8E4D}\x{8E4E}\x{8E50}' - . '\x{8E51}\x{8E52}\x{8E53}\x{8E54}\x{8E55}\x{8E56}\x{8E57}\x{8E58}\x{8E59}' - . '\x{8E5A}\x{8E5B}\x{8E5C}\x{8E5D}\x{8E5E}\x{8E5F}\x{8E60}\x{8E61}\x{8E62}' - . '\x{8E63}\x{8E64}\x{8E65}\x{8E66}\x{8E67}\x{8E68}\x{8E69}\x{8E6A}\x{8E6B}' - . '\x{8E6C}\x{8E6D}\x{8E6F}\x{8E70}\x{8E71}\x{8E72}\x{8E73}\x{8E74}\x{8E76}' - . '\x{8E78}\x{8E7A}\x{8E7B}\x{8E7C}\x{8E7D}\x{8E7E}\x{8E7F}\x{8E80}\x{8E81}' - . '\x{8E82}\x{8E83}\x{8E84}\x{8E85}\x{8E86}\x{8E87}\x{8E88}\x{8E89}\x{8E8A}' - . '\x{8E8B}\x{8E8C}\x{8E8D}\x{8E8E}\x{8E8F}\x{8E90}\x{8E91}\x{8E92}\x{8E93}' - . '\x{8E94}\x{8E95}\x{8E96}\x{8E97}\x{8E98}\x{8E9A}\x{8E9C}\x{8E9D}\x{8E9E}' - . '\x{8E9F}\x{8EA0}\x{8EA1}\x{8EA3}\x{8EA4}\x{8EA5}\x{8EA6}\x{8EA7}\x{8EA8}' - . '\x{8EA9}\x{8EAA}\x{8EAB}\x{8EAC}\x{8EAD}\x{8EAE}\x{8EAF}\x{8EB0}\x{8EB1}' - . '\x{8EB2}\x{8EB4}\x{8EB5}\x{8EB8}\x{8EB9}\x{8EBA}\x{8EBB}\x{8EBC}\x{8EBD}' - . '\x{8EBE}\x{8EBF}\x{8EC0}\x{8EC2}\x{8EC3}\x{8EC5}\x{8EC6}\x{8EC7}\x{8EC8}' - . '\x{8EC9}\x{8ECA}\x{8ECB}\x{8ECC}\x{8ECD}\x{8ECE}\x{8ECF}\x{8ED0}\x{8ED1}' - . '\x{8ED2}\x{8ED3}\x{8ED4}\x{8ED5}\x{8ED6}\x{8ED7}\x{8ED8}\x{8EDA}\x{8EDB}' - . '\x{8EDC}\x{8EDD}\x{8EDE}\x{8EDF}\x{8EE0}\x{8EE1}\x{8EE4}\x{8EE5}\x{8EE6}' - . '\x{8EE7}\x{8EE8}\x{8EE9}\x{8EEA}\x{8EEB}\x{8EEC}\x{8EED}\x{8EEE}\x{8EEF}' - . '\x{8EF1}\x{8EF2}\x{8EF3}\x{8EF4}\x{8EF5}\x{8EF6}\x{8EF7}\x{8EF8}\x{8EF9}' - . '\x{8EFA}\x{8EFB}\x{8EFC}\x{8EFD}\x{8EFE}\x{8EFF}\x{8F00}\x{8F01}\x{8F02}' - . '\x{8F03}\x{8F04}\x{8F05}\x{8F06}\x{8F07}\x{8F08}\x{8F09}\x{8F0A}\x{8F0B}' - . '\x{8F0D}\x{8F0E}\x{8F10}\x{8F11}\x{8F12}\x{8F13}\x{8F14}\x{8F15}\x{8F16}' - . '\x{8F17}\x{8F18}\x{8F1A}\x{8F1B}\x{8F1C}\x{8F1D}\x{8F1E}\x{8F1F}\x{8F20}' - . '\x{8F21}\x{8F22}\x{8F23}\x{8F24}\x{8F25}\x{8F26}\x{8F27}\x{8F28}\x{8F29}' - . '\x{8F2A}\x{8F2B}\x{8F2C}\x{8F2E}\x{8F2F}\x{8F30}\x{8F31}\x{8F32}\x{8F33}' - . '\x{8F34}\x{8F35}\x{8F36}\x{8F37}\x{8F38}\x{8F39}\x{8F3B}\x{8F3C}\x{8F3D}' - . '\x{8F3E}\x{8F3F}\x{8F40}\x{8F42}\x{8F43}\x{8F44}\x{8F45}\x{8F46}\x{8F47}' - . '\x{8F48}\x{8F49}\x{8F4A}\x{8F4B}\x{8F4C}\x{8F4D}\x{8F4E}\x{8F4F}\x{8F50}' - . '\x{8F51}\x{8F52}\x{8F53}\x{8F54}\x{8F55}\x{8F56}\x{8F57}\x{8F58}\x{8F59}' - . '\x{8F5A}\x{8F5B}\x{8F5D}\x{8F5E}\x{8F5F}\x{8F60}\x{8F61}\x{8F62}\x{8F63}' - . '\x{8F64}\x{8F65}\x{8F66}\x{8F67}\x{8F68}\x{8F69}\x{8F6A}\x{8F6B}\x{8F6C}' - . '\x{8F6D}\x{8F6E}\x{8F6F}\x{8F70}\x{8F71}\x{8F72}\x{8F73}\x{8F74}\x{8F75}' - . '\x{8F76}\x{8F77}\x{8F78}\x{8F79}\x{8F7A}\x{8F7B}\x{8F7C}\x{8F7D}\x{8F7E}' - . '\x{8F7F}\x{8F80}\x{8F81}\x{8F82}\x{8F83}\x{8F84}\x{8F85}\x{8F86}\x{8F87}' - . '\x{8F88}\x{8F89}\x{8F8A}\x{8F8B}\x{8F8C}\x{8F8D}\x{8F8E}\x{8F8F}\x{8F90}' - . '\x{8F91}\x{8F92}\x{8F93}\x{8F94}\x{8F95}\x{8F96}\x{8F97}\x{8F98}\x{8F99}' - . '\x{8F9A}\x{8F9B}\x{8F9C}\x{8F9E}\x{8F9F}\x{8FA0}\x{8FA1}\x{8FA2}\x{8FA3}' - . '\x{8FA5}\x{8FA6}\x{8FA7}\x{8FA8}\x{8FA9}\x{8FAA}\x{8FAB}\x{8FAC}\x{8FAD}' - . '\x{8FAE}\x{8FAF}\x{8FB0}\x{8FB1}\x{8FB2}\x{8FB4}\x{8FB5}\x{8FB6}\x{8FB7}' - . '\x{8FB8}\x{8FB9}\x{8FBB}\x{8FBC}\x{8FBD}\x{8FBE}\x{8FBF}\x{8FC0}\x{8FC1}' - . '\x{8FC2}\x{8FC4}\x{8FC5}\x{8FC6}\x{8FC7}\x{8FC8}\x{8FC9}\x{8FCB}\x{8FCC}' - . '\x{8FCD}\x{8FCE}\x{8FCF}\x{8FD0}\x{8FD1}\x{8FD2}\x{8FD3}\x{8FD4}\x{8FD5}' - . '\x{8FD6}\x{8FD7}\x{8FD8}\x{8FD9}\x{8FDA}\x{8FDB}\x{8FDC}\x{8FDD}\x{8FDE}' - . '\x{8FDF}\x{8FE0}\x{8FE1}\x{8FE2}\x{8FE3}\x{8FE4}\x{8FE5}\x{8FE6}\x{8FE8}' - . '\x{8FE9}\x{8FEA}\x{8FEB}\x{8FEC}\x{8FED}\x{8FEE}\x{8FEF}\x{8FF0}\x{8FF1}' - . '\x{8FF2}\x{8FF3}\x{8FF4}\x{8FF5}\x{8FF6}\x{8FF7}\x{8FF8}\x{8FF9}\x{8FFA}' - . '\x{8FFB}\x{8FFC}\x{8FFD}\x{8FFE}\x{8FFF}\x{9000}\x{9001}\x{9002}\x{9003}' - . '\x{9004}\x{9005}\x{9006}\x{9007}\x{9008}\x{9009}\x{900A}\x{900B}\x{900C}' - . '\x{900D}\x{900F}\x{9010}\x{9011}\x{9012}\x{9013}\x{9014}\x{9015}\x{9016}' - . '\x{9017}\x{9018}\x{9019}\x{901A}\x{901B}\x{901C}\x{901D}\x{901E}\x{901F}' - . '\x{9020}\x{9021}\x{9022}\x{9023}\x{9024}\x{9025}\x{9026}\x{9027}\x{9028}' - . '\x{9029}\x{902B}\x{902D}\x{902E}\x{902F}\x{9030}\x{9031}\x{9032}\x{9033}' - . '\x{9034}\x{9035}\x{9036}\x{9038}\x{903A}\x{903B}\x{903C}\x{903D}\x{903E}' - . '\x{903F}\x{9041}\x{9042}\x{9043}\x{9044}\x{9045}\x{9047}\x{9048}\x{9049}' - . '\x{904A}\x{904B}\x{904C}\x{904D}\x{904E}\x{904F}\x{9050}\x{9051}\x{9052}' - . '\x{9053}\x{9054}\x{9055}\x{9056}\x{9057}\x{9058}\x{9059}\x{905A}\x{905B}' - . '\x{905C}\x{905D}\x{905E}\x{905F}\x{9060}\x{9061}\x{9062}\x{9063}\x{9064}' - . '\x{9065}\x{9066}\x{9067}\x{9068}\x{9069}\x{906A}\x{906B}\x{906C}\x{906D}' - . '\x{906E}\x{906F}\x{9070}\x{9071}\x{9072}\x{9073}\x{9074}\x{9075}\x{9076}' - . '\x{9077}\x{9078}\x{9079}\x{907A}\x{907B}\x{907C}\x{907D}\x{907E}\x{907F}' - . '\x{9080}\x{9081}\x{9082}\x{9083}\x{9084}\x{9085}\x{9086}\x{9087}\x{9088}' - . '\x{9089}\x{908A}\x{908B}\x{908C}\x{908D}\x{908E}\x{908F}\x{9090}\x{9091}' - . '\x{9092}\x{9093}\x{9094}\x{9095}\x{9096}\x{9097}\x{9098}\x{9099}\x{909A}' - . '\x{909B}\x{909C}\x{909D}\x{909E}\x{909F}\x{90A0}\x{90A1}\x{90A2}\x{90A3}' - . '\x{90A4}\x{90A5}\x{90A6}\x{90A7}\x{90A8}\x{90A9}\x{90AA}\x{90AC}\x{90AD}' - . '\x{90AE}\x{90AF}\x{90B0}\x{90B1}\x{90B2}\x{90B3}\x{90B4}\x{90B5}\x{90B6}' - . '\x{90B7}\x{90B8}\x{90B9}\x{90BA}\x{90BB}\x{90BC}\x{90BD}\x{90BE}\x{90BF}' - . '\x{90C0}\x{90C1}\x{90C2}\x{90C3}\x{90C4}\x{90C5}\x{90C6}\x{90C7}\x{90C8}' - . '\x{90C9}\x{90CA}\x{90CB}\x{90CE}\x{90CF}\x{90D0}\x{90D1}\x{90D3}\x{90D4}' - . '\x{90D5}\x{90D6}\x{90D7}\x{90D8}\x{90D9}\x{90DA}\x{90DB}\x{90DC}\x{90DD}' - . '\x{90DE}\x{90DF}\x{90E0}\x{90E1}\x{90E2}\x{90E3}\x{90E4}\x{90E5}\x{90E6}' - . '\x{90E7}\x{90E8}\x{90E9}\x{90EA}\x{90EB}\x{90EC}\x{90ED}\x{90EE}\x{90EF}' - . '\x{90F0}\x{90F1}\x{90F2}\x{90F3}\x{90F4}\x{90F5}\x{90F7}\x{90F8}\x{90F9}' - . '\x{90FA}\x{90FB}\x{90FC}\x{90FD}\x{90FE}\x{90FF}\x{9100}\x{9101}\x{9102}' - . '\x{9103}\x{9104}\x{9105}\x{9106}\x{9107}\x{9108}\x{9109}\x{910B}\x{910C}' - . '\x{910D}\x{910E}\x{910F}\x{9110}\x{9111}\x{9112}\x{9113}\x{9114}\x{9115}' - . '\x{9116}\x{9117}\x{9118}\x{9119}\x{911A}\x{911B}\x{911C}\x{911D}\x{911E}' - . '\x{911F}\x{9120}\x{9121}\x{9122}\x{9123}\x{9124}\x{9125}\x{9126}\x{9127}' - . '\x{9128}\x{9129}\x{912A}\x{912B}\x{912C}\x{912D}\x{912E}\x{912F}\x{9130}' - . '\x{9131}\x{9132}\x{9133}\x{9134}\x{9135}\x{9136}\x{9137}\x{9138}\x{9139}' - . '\x{913A}\x{913B}\x{913E}\x{913F}\x{9140}\x{9141}\x{9142}\x{9143}\x{9144}' - . '\x{9145}\x{9146}\x{9147}\x{9148}\x{9149}\x{914A}\x{914B}\x{914C}\x{914D}' - . '\x{914E}\x{914F}\x{9150}\x{9151}\x{9152}\x{9153}\x{9154}\x{9155}\x{9156}' - . '\x{9157}\x{9158}\x{915A}\x{915B}\x{915C}\x{915D}\x{915E}\x{915F}\x{9160}' - . '\x{9161}\x{9162}\x{9163}\x{9164}\x{9165}\x{9166}\x{9167}\x{9168}\x{9169}' - . '\x{916A}\x{916B}\x{916C}\x{916D}\x{916E}\x{916F}\x{9170}\x{9171}\x{9172}' - . '\x{9173}\x{9174}\x{9175}\x{9176}\x{9177}\x{9178}\x{9179}\x{917A}\x{917C}' - . '\x{917D}\x{917E}\x{917F}\x{9180}\x{9181}\x{9182}\x{9183}\x{9184}\x{9185}' - . '\x{9186}\x{9187}\x{9188}\x{9189}\x{918A}\x{918B}\x{918C}\x{918D}\x{918E}' - . '\x{918F}\x{9190}\x{9191}\x{9192}\x{9193}\x{9194}\x{9196}\x{9199}\x{919A}' - . '\x{919B}\x{919C}\x{919D}\x{919E}\x{919F}\x{91A0}\x{91A1}\x{91A2}\x{91A3}' - . '\x{91A5}\x{91A6}\x{91A7}\x{91A8}\x{91AA}\x{91AB}\x{91AC}\x{91AD}\x{91AE}' - . '\x{91AF}\x{91B0}\x{91B1}\x{91B2}\x{91B3}\x{91B4}\x{91B5}\x{91B6}\x{91B7}' - . '\x{91B9}\x{91BA}\x{91BB}\x{91BC}\x{91BD}\x{91BE}\x{91C0}\x{91C1}\x{91C2}' - . '\x{91C3}\x{91C5}\x{91C6}\x{91C7}\x{91C9}\x{91CA}\x{91CB}\x{91CC}\x{91CD}' - . '\x{91CE}\x{91CF}\x{91D0}\x{91D1}\x{91D2}\x{91D3}\x{91D4}\x{91D5}\x{91D7}' - . '\x{91D8}\x{91D9}\x{91DA}\x{91DB}\x{91DC}\x{91DD}\x{91DE}\x{91DF}\x{91E2}' - . '\x{91E3}\x{91E4}\x{91E5}\x{91E6}\x{91E7}\x{91E8}\x{91E9}\x{91EA}\x{91EB}' - . '\x{91EC}\x{91ED}\x{91EE}\x{91F0}\x{91F1}\x{91F2}\x{91F3}\x{91F4}\x{91F5}' - . '\x{91F7}\x{91F8}\x{91F9}\x{91FA}\x{91FB}\x{91FD}\x{91FE}\x{91FF}\x{9200}' - . '\x{9201}\x{9202}\x{9203}\x{9204}\x{9205}\x{9206}\x{9207}\x{9208}\x{9209}' - . '\x{920A}\x{920B}\x{920C}\x{920D}\x{920E}\x{920F}\x{9210}\x{9211}\x{9212}' - . '\x{9214}\x{9215}\x{9216}\x{9217}\x{9218}\x{9219}\x{921A}\x{921B}\x{921C}' - . '\x{921D}\x{921E}\x{9220}\x{9221}\x{9223}\x{9224}\x{9225}\x{9226}\x{9227}' - . '\x{9228}\x{9229}\x{922A}\x{922B}\x{922D}\x{922E}\x{922F}\x{9230}\x{9231}' - . '\x{9232}\x{9233}\x{9234}\x{9235}\x{9236}\x{9237}\x{9238}\x{9239}\x{923A}' - . '\x{923B}\x{923C}\x{923D}\x{923E}\x{923F}\x{9240}\x{9241}\x{9242}\x{9245}' - . '\x{9246}\x{9247}\x{9248}\x{9249}\x{924A}\x{924B}\x{924C}\x{924D}\x{924E}' - . '\x{924F}\x{9250}\x{9251}\x{9252}\x{9253}\x{9254}\x{9255}\x{9256}\x{9257}' - . '\x{9258}\x{9259}\x{925A}\x{925B}\x{925C}\x{925D}\x{925E}\x{925F}\x{9260}' - . '\x{9261}\x{9262}\x{9263}\x{9264}\x{9265}\x{9266}\x{9267}\x{9268}\x{926B}' - . '\x{926C}\x{926D}\x{926E}\x{926F}\x{9270}\x{9272}\x{9273}\x{9274}\x{9275}' - . '\x{9276}\x{9277}\x{9278}\x{9279}\x{927A}\x{927B}\x{927C}\x{927D}\x{927E}' - . '\x{927F}\x{9280}\x{9282}\x{9283}\x{9285}\x{9286}\x{9287}\x{9288}\x{9289}' - . '\x{928A}\x{928B}\x{928C}\x{928D}\x{928E}\x{928F}\x{9290}\x{9291}\x{9292}' - . '\x{9293}\x{9294}\x{9295}\x{9296}\x{9297}\x{9298}\x{9299}\x{929A}\x{929B}' - . '\x{929C}\x{929D}\x{929F}\x{92A0}\x{92A1}\x{92A2}\x{92A3}\x{92A4}\x{92A5}' - . '\x{92A6}\x{92A7}\x{92A8}\x{92A9}\x{92AA}\x{92AB}\x{92AC}\x{92AD}\x{92AE}' - . '\x{92AF}\x{92B0}\x{92B1}\x{92B2}\x{92B3}\x{92B4}\x{92B5}\x{92B6}\x{92B7}' - . '\x{92B8}\x{92B9}\x{92BA}\x{92BB}\x{92BC}\x{92BE}\x{92BF}\x{92C0}\x{92C1}' - . '\x{92C2}\x{92C3}\x{92C4}\x{92C5}\x{92C6}\x{92C7}\x{92C8}\x{92C9}\x{92CA}' - . '\x{92CB}\x{92CC}\x{92CD}\x{92CE}\x{92CF}\x{92D0}\x{92D1}\x{92D2}\x{92D3}' - . '\x{92D5}\x{92D6}\x{92D7}\x{92D8}\x{92D9}\x{92DA}\x{92DC}\x{92DD}\x{92DE}' - . '\x{92DF}\x{92E0}\x{92E1}\x{92E3}\x{92E4}\x{92E5}\x{92E6}\x{92E7}\x{92E8}' - . '\x{92E9}\x{92EA}\x{92EB}\x{92EC}\x{92ED}\x{92EE}\x{92EF}\x{92F0}\x{92F1}' - . '\x{92F2}\x{92F3}\x{92F4}\x{92F5}\x{92F6}\x{92F7}\x{92F8}\x{92F9}\x{92FA}' - . '\x{92FB}\x{92FC}\x{92FD}\x{92FE}\x{92FF}\x{9300}\x{9301}\x{9302}\x{9303}' - . '\x{9304}\x{9305}\x{9306}\x{9307}\x{9308}\x{9309}\x{930A}\x{930B}\x{930C}' - . '\x{930D}\x{930E}\x{930F}\x{9310}\x{9311}\x{9312}\x{9313}\x{9314}\x{9315}' - . '\x{9316}\x{9317}\x{9318}\x{9319}\x{931A}\x{931B}\x{931D}\x{931E}\x{931F}' - . '\x{9320}\x{9321}\x{9322}\x{9323}\x{9324}\x{9325}\x{9326}\x{9327}\x{9328}' - . '\x{9329}\x{932A}\x{932B}\x{932D}\x{932E}\x{932F}\x{9332}\x{9333}\x{9334}' - . '\x{9335}\x{9336}\x{9337}\x{9338}\x{9339}\x{933A}\x{933B}\x{933C}\x{933D}' - . '\x{933E}\x{933F}\x{9340}\x{9341}\x{9342}\x{9343}\x{9344}\x{9345}\x{9346}' - . '\x{9347}\x{9348}\x{9349}\x{934A}\x{934B}\x{934C}\x{934D}\x{934E}\x{934F}' - . '\x{9350}\x{9351}\x{9352}\x{9353}\x{9354}\x{9355}\x{9356}\x{9357}\x{9358}' - . '\x{9359}\x{935A}\x{935B}\x{935C}\x{935D}\x{935E}\x{935F}\x{9360}\x{9361}' - . '\x{9363}\x{9364}\x{9365}\x{9366}\x{9367}\x{9369}\x{936A}\x{936C}\x{936D}' - . '\x{936E}\x{9370}\x{9371}\x{9372}\x{9374}\x{9375}\x{9376}\x{9377}\x{9379}' - . '\x{937A}\x{937B}\x{937C}\x{937D}\x{937E}\x{9380}\x{9382}\x{9383}\x{9384}' - . '\x{9385}\x{9386}\x{9387}\x{9388}\x{9389}\x{938A}\x{938C}\x{938D}\x{938E}' - . '\x{938F}\x{9390}\x{9391}\x{9392}\x{9393}\x{9394}\x{9395}\x{9396}\x{9397}' - . '\x{9398}\x{9399}\x{939A}\x{939B}\x{939D}\x{939E}\x{939F}\x{93A1}\x{93A2}' - . '\x{93A3}\x{93A4}\x{93A5}\x{93A6}\x{93A7}\x{93A8}\x{93A9}\x{93AA}\x{93AC}' - . '\x{93AD}\x{93AE}\x{93AF}\x{93B0}\x{93B1}\x{93B2}\x{93B3}\x{93B4}\x{93B5}' - . '\x{93B6}\x{93B7}\x{93B8}\x{93B9}\x{93BA}\x{93BC}\x{93BD}\x{93BE}\x{93BF}' - . '\x{93C0}\x{93C1}\x{93C2}\x{93C3}\x{93C4}\x{93C5}\x{93C6}\x{93C7}\x{93C8}' - . '\x{93C9}\x{93CA}\x{93CB}\x{93CC}\x{93CD}\x{93CE}\x{93CF}\x{93D0}\x{93D1}' - . '\x{93D2}\x{93D3}\x{93D4}\x{93D5}\x{93D6}\x{93D7}\x{93D8}\x{93D9}\x{93DA}' - . '\x{93DB}\x{93DC}\x{93DD}\x{93DE}\x{93DF}\x{93E1}\x{93E2}\x{93E3}\x{93E4}' - . '\x{93E6}\x{93E7}\x{93E8}\x{93E9}\x{93EA}\x{93EB}\x{93EC}\x{93ED}\x{93EE}' - . '\x{93EF}\x{93F0}\x{93F1}\x{93F2}\x{93F4}\x{93F5}\x{93F6}\x{93F7}\x{93F8}' - . '\x{93F9}\x{93FA}\x{93FB}\x{93FC}\x{93FD}\x{93FE}\x{93FF}\x{9400}\x{9401}' - . '\x{9403}\x{9404}\x{9405}\x{9406}\x{9407}\x{9408}\x{9409}\x{940A}\x{940B}' - . '\x{940C}\x{940D}\x{940E}\x{940F}\x{9410}\x{9411}\x{9412}\x{9413}\x{9414}' - . '\x{9415}\x{9416}\x{9418}\x{9419}\x{941B}\x{941D}\x{9420}\x{9422}\x{9423}' - . '\x{9425}\x{9426}\x{9427}\x{9428}\x{9429}\x{942A}\x{942B}\x{942C}\x{942D}' - . '\x{942E}\x{942F}\x{9430}\x{9431}\x{9432}\x{9433}\x{9434}\x{9435}\x{9436}' - . '\x{9437}\x{9438}\x{9439}\x{943A}\x{943B}\x{943C}\x{943D}\x{943E}\x{943F}' - . '\x{9440}\x{9441}\x{9442}\x{9444}\x{9445}\x{9446}\x{9447}\x{9448}\x{9449}' - . '\x{944A}\x{944B}\x{944C}\x{944D}\x{944F}\x{9450}\x{9451}\x{9452}\x{9453}' - . '\x{9454}\x{9455}\x{9456}\x{9457}\x{9458}\x{9459}\x{945B}\x{945C}\x{945D}' - . '\x{945E}\x{945F}\x{9460}\x{9461}\x{9462}\x{9463}\x{9464}\x{9465}\x{9466}' - . '\x{9467}\x{9468}\x{9469}\x{946A}\x{946B}\x{946D}\x{946E}\x{946F}\x{9470}' - . '\x{9471}\x{9472}\x{9473}\x{9474}\x{9475}\x{9476}\x{9477}\x{9478}\x{9479}' - . '\x{947A}\x{947C}\x{947D}\x{947E}\x{947F}\x{9480}\x{9481}\x{9482}\x{9483}' - . '\x{9484}\x{9485}\x{9486}\x{9487}\x{9488}\x{9489}\x{948A}\x{948B}\x{948C}' - . '\x{948D}\x{948E}\x{948F}\x{9490}\x{9491}\x{9492}\x{9493}\x{9494}\x{9495}' - . '\x{9496}\x{9497}\x{9498}\x{9499}\x{949A}\x{949B}\x{949C}\x{949D}\x{949E}' - . '\x{949F}\x{94A0}\x{94A1}\x{94A2}\x{94A3}\x{94A4}\x{94A5}\x{94A6}\x{94A7}' - . '\x{94A8}\x{94A9}\x{94AA}\x{94AB}\x{94AC}\x{94AD}\x{94AE}\x{94AF}\x{94B0}' - . '\x{94B1}\x{94B2}\x{94B3}\x{94B4}\x{94B5}\x{94B6}\x{94B7}\x{94B8}\x{94B9}' - . '\x{94BA}\x{94BB}\x{94BC}\x{94BD}\x{94BE}\x{94BF}\x{94C0}\x{94C1}\x{94C2}' - . '\x{94C3}\x{94C4}\x{94C5}\x{94C6}\x{94C7}\x{94C8}\x{94C9}\x{94CA}\x{94CB}' - . '\x{94CC}\x{94CD}\x{94CE}\x{94CF}\x{94D0}\x{94D1}\x{94D2}\x{94D3}\x{94D4}' - . '\x{94D5}\x{94D6}\x{94D7}\x{94D8}\x{94D9}\x{94DA}\x{94DB}\x{94DC}\x{94DD}' - . '\x{94DE}\x{94DF}\x{94E0}\x{94E1}\x{94E2}\x{94E3}\x{94E4}\x{94E5}\x{94E6}' - . '\x{94E7}\x{94E8}\x{94E9}\x{94EA}\x{94EB}\x{94EC}\x{94ED}\x{94EE}\x{94EF}' - . '\x{94F0}\x{94F1}\x{94F2}\x{94F3}\x{94F4}\x{94F5}\x{94F6}\x{94F7}\x{94F8}' - . '\x{94F9}\x{94FA}\x{94FB}\x{94FC}\x{94FD}\x{94FE}\x{94FF}\x{9500}\x{9501}' - . '\x{9502}\x{9503}\x{9504}\x{9505}\x{9506}\x{9507}\x{9508}\x{9509}\x{950A}' - . '\x{950B}\x{950C}\x{950D}\x{950E}\x{950F}\x{9510}\x{9511}\x{9512}\x{9513}' - . '\x{9514}\x{9515}\x{9516}\x{9517}\x{9518}\x{9519}\x{951A}\x{951B}\x{951C}' - . '\x{951D}\x{951E}\x{951F}\x{9520}\x{9521}\x{9522}\x{9523}\x{9524}\x{9525}' - . '\x{9526}\x{9527}\x{9528}\x{9529}\x{952A}\x{952B}\x{952C}\x{952D}\x{952E}' - . '\x{952F}\x{9530}\x{9531}\x{9532}\x{9533}\x{9534}\x{9535}\x{9536}\x{9537}' - . '\x{9538}\x{9539}\x{953A}\x{953B}\x{953C}\x{953D}\x{953E}\x{953F}\x{9540}' - . '\x{9541}\x{9542}\x{9543}\x{9544}\x{9545}\x{9546}\x{9547}\x{9548}\x{9549}' - . '\x{954A}\x{954B}\x{954C}\x{954D}\x{954E}\x{954F}\x{9550}\x{9551}\x{9552}' - . '\x{9553}\x{9554}\x{9555}\x{9556}\x{9557}\x{9558}\x{9559}\x{955A}\x{955B}' - . '\x{955C}\x{955D}\x{955E}\x{955F}\x{9560}\x{9561}\x{9562}\x{9563}\x{9564}' - . '\x{9565}\x{9566}\x{9567}\x{9568}\x{9569}\x{956A}\x{956B}\x{956C}\x{956D}' - . '\x{956E}\x{956F}\x{9570}\x{9571}\x{9572}\x{9573}\x{9574}\x{9575}\x{9576}' - . '\x{9577}\x{957A}\x{957B}\x{957C}\x{957D}\x{957F}\x{9580}\x{9581}\x{9582}' - . '\x{9583}\x{9584}\x{9586}\x{9587}\x{9588}\x{9589}\x{958A}\x{958B}\x{958C}' - . '\x{958D}\x{958E}\x{958F}\x{9590}\x{9591}\x{9592}\x{9593}\x{9594}\x{9595}' - . '\x{9596}\x{9598}\x{9599}\x{959A}\x{959B}\x{959C}\x{959D}\x{959E}\x{959F}' - . '\x{95A1}\x{95A2}\x{95A3}\x{95A4}\x{95A5}\x{95A6}\x{95A7}\x{95A8}\x{95A9}' - . '\x{95AA}\x{95AB}\x{95AC}\x{95AD}\x{95AE}\x{95AF}\x{95B0}\x{95B1}\x{95B2}' - . '\x{95B5}\x{95B6}\x{95B7}\x{95B9}\x{95BA}\x{95BB}\x{95BC}\x{95BD}\x{95BE}' - . '\x{95BF}\x{95C0}\x{95C2}\x{95C3}\x{95C4}\x{95C5}\x{95C6}\x{95C7}\x{95C8}' - . '\x{95C9}\x{95CA}\x{95CB}\x{95CC}\x{95CD}\x{95CE}\x{95CF}\x{95D0}\x{95D1}' - . '\x{95D2}\x{95D3}\x{95D4}\x{95D5}\x{95D6}\x{95D7}\x{95D8}\x{95DA}\x{95DB}' - . '\x{95DC}\x{95DE}\x{95DF}\x{95E0}\x{95E1}\x{95E2}\x{95E3}\x{95E4}\x{95E5}' - . '\x{95E6}\x{95E7}\x{95E8}\x{95E9}\x{95EA}\x{95EB}\x{95EC}\x{95ED}\x{95EE}' - . '\x{95EF}\x{95F0}\x{95F1}\x{95F2}\x{95F3}\x{95F4}\x{95F5}\x{95F6}\x{95F7}' - . '\x{95F8}\x{95F9}\x{95FA}\x{95FB}\x{95FC}\x{95FD}\x{95FE}\x{95FF}\x{9600}' - . '\x{9601}\x{9602}\x{9603}\x{9604}\x{9605}\x{9606}\x{9607}\x{9608}\x{9609}' - . '\x{960A}\x{960B}\x{960C}\x{960D}\x{960E}\x{960F}\x{9610}\x{9611}\x{9612}' - . '\x{9613}\x{9614}\x{9615}\x{9616}\x{9617}\x{9618}\x{9619}\x{961A}\x{961B}' - . '\x{961C}\x{961D}\x{961E}\x{961F}\x{9620}\x{9621}\x{9622}\x{9623}\x{9624}' - . '\x{9627}\x{9628}\x{962A}\x{962B}\x{962C}\x{962D}\x{962E}\x{962F}\x{9630}' - . '\x{9631}\x{9632}\x{9633}\x{9634}\x{9635}\x{9636}\x{9637}\x{9638}\x{9639}' - . '\x{963A}\x{963B}\x{963C}\x{963D}\x{963F}\x{9640}\x{9641}\x{9642}\x{9643}' - . '\x{9644}\x{9645}\x{9646}\x{9647}\x{9648}\x{9649}\x{964A}\x{964B}\x{964C}' - . '\x{964D}\x{964E}\x{964F}\x{9650}\x{9651}\x{9652}\x{9653}\x{9654}\x{9655}' - . '\x{9658}\x{9659}\x{965A}\x{965B}\x{965C}\x{965D}\x{965E}\x{965F}\x{9660}' - . '\x{9661}\x{9662}\x{9663}\x{9664}\x{9666}\x{9667}\x{9668}\x{9669}\x{966A}' - . '\x{966B}\x{966C}\x{966D}\x{966E}\x{966F}\x{9670}\x{9671}\x{9672}\x{9673}' - . '\x{9674}\x{9675}\x{9676}\x{9677}\x{9678}\x{967C}\x{967D}\x{967E}\x{9680}' - . '\x{9683}\x{9684}\x{9685}\x{9686}\x{9687}\x{9688}\x{9689}\x{968A}\x{968B}' - . '\x{968D}\x{968E}\x{968F}\x{9690}\x{9691}\x{9692}\x{9693}\x{9694}\x{9695}' - . '\x{9697}\x{9698}\x{9699}\x{969B}\x{969C}\x{969E}\x{96A0}\x{96A1}\x{96A2}' - . '\x{96A3}\x{96A4}\x{96A5}\x{96A6}\x{96A7}\x{96A8}\x{96A9}\x{96AA}\x{96AC}' - . '\x{96AD}\x{96AE}\x{96B0}\x{96B1}\x{96B3}\x{96B4}\x{96B6}\x{96B7}\x{96B8}' - . '\x{96B9}\x{96BA}\x{96BB}\x{96BC}\x{96BD}\x{96BE}\x{96BF}\x{96C0}\x{96C1}' - . '\x{96C2}\x{96C3}\x{96C4}\x{96C5}\x{96C6}\x{96C7}\x{96C8}\x{96C9}\x{96CA}' - . '\x{96CB}\x{96CC}\x{96CD}\x{96CE}\x{96CF}\x{96D0}\x{96D1}\x{96D2}\x{96D3}' - . '\x{96D4}\x{96D5}\x{96D6}\x{96D7}\x{96D8}\x{96D9}\x{96DA}\x{96DB}\x{96DC}' - . '\x{96DD}\x{96DE}\x{96DF}\x{96E0}\x{96E1}\x{96E2}\x{96E3}\x{96E5}\x{96E8}' - . '\x{96E9}\x{96EA}\x{96EB}\x{96EC}\x{96ED}\x{96EE}\x{96EF}\x{96F0}\x{96F1}' - . '\x{96F2}\x{96F3}\x{96F4}\x{96F5}\x{96F6}\x{96F7}\x{96F8}\x{96F9}\x{96FA}' - . '\x{96FB}\x{96FD}\x{96FE}\x{96FF}\x{9700}\x{9701}\x{9702}\x{9703}\x{9704}' - . '\x{9705}\x{9706}\x{9707}\x{9708}\x{9709}\x{970A}\x{970B}\x{970C}\x{970D}' - . '\x{970E}\x{970F}\x{9710}\x{9711}\x{9712}\x{9713}\x{9715}\x{9716}\x{9718}' - . '\x{9719}\x{971C}\x{971D}\x{971E}\x{971F}\x{9720}\x{9721}\x{9722}\x{9723}' - . '\x{9724}\x{9725}\x{9726}\x{9727}\x{9728}\x{9729}\x{972A}\x{972B}\x{972C}' - . '\x{972D}\x{972E}\x{972F}\x{9730}\x{9731}\x{9732}\x{9735}\x{9736}\x{9738}' - . '\x{9739}\x{973A}\x{973B}\x{973C}\x{973D}\x{973E}\x{973F}\x{9742}\x{9743}' - . '\x{9744}\x{9745}\x{9746}\x{9747}\x{9748}\x{9749}\x{974A}\x{974B}\x{974C}' - . '\x{974E}\x{974F}\x{9750}\x{9751}\x{9752}\x{9753}\x{9754}\x{9755}\x{9756}' - . '\x{9758}\x{9759}\x{975A}\x{975B}\x{975C}\x{975D}\x{975E}\x{975F}\x{9760}' - . '\x{9761}\x{9762}\x{9765}\x{9766}\x{9767}\x{9768}\x{9769}\x{976A}\x{976B}' - . '\x{976C}\x{976D}\x{976E}\x{976F}\x{9770}\x{9772}\x{9773}\x{9774}\x{9776}' - . '\x{9777}\x{9778}\x{9779}\x{977A}\x{977B}\x{977C}\x{977D}\x{977E}\x{977F}' - . '\x{9780}\x{9781}\x{9782}\x{9783}\x{9784}\x{9785}\x{9786}\x{9788}\x{978A}' - . '\x{978B}\x{978C}\x{978D}\x{978E}\x{978F}\x{9790}\x{9791}\x{9792}\x{9793}' - . '\x{9794}\x{9795}\x{9796}\x{9797}\x{9798}\x{9799}\x{979A}\x{979C}\x{979D}' - . '\x{979E}\x{979F}\x{97A0}\x{97A1}\x{97A2}\x{97A3}\x{97A4}\x{97A5}\x{97A6}' - . '\x{97A7}\x{97A8}\x{97AA}\x{97AB}\x{97AC}\x{97AD}\x{97AE}\x{97AF}\x{97B2}' - . '\x{97B3}\x{97B4}\x{97B6}\x{97B7}\x{97B8}\x{97B9}\x{97BA}\x{97BB}\x{97BC}' - . '\x{97BD}\x{97BF}\x{97C1}\x{97C2}\x{97C3}\x{97C4}\x{97C5}\x{97C6}\x{97C7}' - . '\x{97C8}\x{97C9}\x{97CA}\x{97CB}\x{97CC}\x{97CD}\x{97CE}\x{97CF}\x{97D0}' - . '\x{97D1}\x{97D3}\x{97D4}\x{97D5}\x{97D6}\x{97D7}\x{97D8}\x{97D9}\x{97DA}' - . '\x{97DB}\x{97DC}\x{97DD}\x{97DE}\x{97DF}\x{97E0}\x{97E1}\x{97E2}\x{97E3}' - . '\x{97E4}\x{97E5}\x{97E6}\x{97E7}\x{97E8}\x{97E9}\x{97EA}\x{97EB}\x{97EC}' - . '\x{97ED}\x{97EE}\x{97EF}\x{97F0}\x{97F1}\x{97F2}\x{97F3}\x{97F4}\x{97F5}' - . '\x{97F6}\x{97F7}\x{97F8}\x{97F9}\x{97FA}\x{97FB}\x{97FD}\x{97FE}\x{97FF}' - . '\x{9800}\x{9801}\x{9802}\x{9803}\x{9804}\x{9805}\x{9806}\x{9807}\x{9808}' - . '\x{9809}\x{980A}\x{980B}\x{980C}\x{980D}\x{980E}\x{980F}\x{9810}\x{9811}' - . '\x{9812}\x{9813}\x{9814}\x{9815}\x{9816}\x{9817}\x{9818}\x{9819}\x{981A}' - . '\x{981B}\x{981C}\x{981D}\x{981E}\x{9820}\x{9821}\x{9822}\x{9823}\x{9824}' - . '\x{9826}\x{9827}\x{9828}\x{9829}\x{982B}\x{982D}\x{982E}\x{982F}\x{9830}' - . '\x{9831}\x{9832}\x{9834}\x{9835}\x{9836}\x{9837}\x{9838}\x{9839}\x{983B}' - . '\x{983C}\x{983D}\x{983F}\x{9840}\x{9841}\x{9843}\x{9844}\x{9845}\x{9846}' - . '\x{9848}\x{9849}\x{984A}\x{984C}\x{984D}\x{984E}\x{984F}\x{9850}\x{9851}' - . '\x{9852}\x{9853}\x{9854}\x{9855}\x{9857}\x{9858}\x{9859}\x{985A}\x{985B}' - . '\x{985C}\x{985D}\x{985E}\x{985F}\x{9860}\x{9861}\x{9862}\x{9863}\x{9864}' - . '\x{9865}\x{9867}\x{9869}\x{986A}\x{986B}\x{986C}\x{986D}\x{986E}\x{986F}' - . '\x{9870}\x{9871}\x{9872}\x{9873}\x{9874}\x{9875}\x{9876}\x{9877}\x{9878}' - . '\x{9879}\x{987A}\x{987B}\x{987C}\x{987D}\x{987E}\x{987F}\x{9880}\x{9881}' - . '\x{9882}\x{9883}\x{9884}\x{9885}\x{9886}\x{9887}\x{9888}\x{9889}\x{988A}' - . '\x{988B}\x{988C}\x{988D}\x{988E}\x{988F}\x{9890}\x{9891}\x{9892}\x{9893}' - . '\x{9894}\x{9895}\x{9896}\x{9897}\x{9898}\x{9899}\x{989A}\x{989B}\x{989C}' - . '\x{989D}\x{989E}\x{989F}\x{98A0}\x{98A1}\x{98A2}\x{98A3}\x{98A4}\x{98A5}' - . '\x{98A6}\x{98A7}\x{98A8}\x{98A9}\x{98AA}\x{98AB}\x{98AC}\x{98AD}\x{98AE}' - . '\x{98AF}\x{98B0}\x{98B1}\x{98B2}\x{98B3}\x{98B4}\x{98B5}\x{98B6}\x{98B8}' - . '\x{98B9}\x{98BA}\x{98BB}\x{98BC}\x{98BD}\x{98BE}\x{98BF}\x{98C0}\x{98C1}' - . '\x{98C2}\x{98C3}\x{98C4}\x{98C5}\x{98C6}\x{98C8}\x{98C9}\x{98CB}\x{98CC}' - . '\x{98CD}\x{98CE}\x{98CF}\x{98D0}\x{98D1}\x{98D2}\x{98D3}\x{98D4}\x{98D5}' - . '\x{98D6}\x{98D7}\x{98D8}\x{98D9}\x{98DA}\x{98DB}\x{98DC}\x{98DD}\x{98DE}' - . '\x{98DF}\x{98E0}\x{98E2}\x{98E3}\x{98E5}\x{98E6}\x{98E7}\x{98E8}\x{98E9}' - . '\x{98EA}\x{98EB}\x{98ED}\x{98EF}\x{98F0}\x{98F2}\x{98F3}\x{98F4}\x{98F5}' - . '\x{98F6}\x{98F7}\x{98F9}\x{98FA}\x{98FC}\x{98FD}\x{98FE}\x{98FF}\x{9900}' - . '\x{9901}\x{9902}\x{9903}\x{9904}\x{9905}\x{9906}\x{9907}\x{9908}\x{9909}' - . '\x{990A}\x{990B}\x{990C}\x{990D}\x{990E}\x{990F}\x{9910}\x{9911}\x{9912}' - . '\x{9913}\x{9914}\x{9915}\x{9916}\x{9917}\x{9918}\x{991A}\x{991B}\x{991C}' - . '\x{991D}\x{991E}\x{991F}\x{9920}\x{9921}\x{9922}\x{9923}\x{9924}\x{9925}' - . '\x{9926}\x{9927}\x{9928}\x{9929}\x{992A}\x{992B}\x{992C}\x{992D}\x{992E}' - . '\x{992F}\x{9930}\x{9931}\x{9932}\x{9933}\x{9934}\x{9935}\x{9936}\x{9937}' - . '\x{9938}\x{9939}\x{993A}\x{993C}\x{993D}\x{993E}\x{993F}\x{9940}\x{9941}' - . '\x{9942}\x{9943}\x{9945}\x{9946}\x{9947}\x{9948}\x{9949}\x{994A}\x{994B}' - . '\x{994C}\x{994E}\x{994F}\x{9950}\x{9951}\x{9952}\x{9953}\x{9954}\x{9955}' - . '\x{9956}\x{9957}\x{9958}\x{9959}\x{995B}\x{995C}\x{995E}\x{995F}\x{9960}' - . '\x{9961}\x{9962}\x{9963}\x{9964}\x{9965}\x{9966}\x{9967}\x{9968}\x{9969}' - . '\x{996A}\x{996B}\x{996C}\x{996D}\x{996E}\x{996F}\x{9970}\x{9971}\x{9972}' - . '\x{9973}\x{9974}\x{9975}\x{9976}\x{9977}\x{9978}\x{9979}\x{997A}\x{997B}' - . '\x{997C}\x{997D}\x{997E}\x{997F}\x{9980}\x{9981}\x{9982}\x{9983}\x{9984}' - . '\x{9985}\x{9986}\x{9987}\x{9988}\x{9989}\x{998A}\x{998B}\x{998C}\x{998D}' - . '\x{998E}\x{998F}\x{9990}\x{9991}\x{9992}\x{9993}\x{9994}\x{9995}\x{9996}' - . '\x{9997}\x{9998}\x{9999}\x{999A}\x{999B}\x{999C}\x{999D}\x{999E}\x{999F}' - . '\x{99A0}\x{99A1}\x{99A2}\x{99A3}\x{99A4}\x{99A5}\x{99A6}\x{99A7}\x{99A8}' - . '\x{99A9}\x{99AA}\x{99AB}\x{99AC}\x{99AD}\x{99AE}\x{99AF}\x{99B0}\x{99B1}' - . '\x{99B2}\x{99B3}\x{99B4}\x{99B5}\x{99B6}\x{99B7}\x{99B8}\x{99B9}\x{99BA}' - . '\x{99BB}\x{99BC}\x{99BD}\x{99BE}\x{99C0}\x{99C1}\x{99C2}\x{99C3}\x{99C4}' - . '\x{99C6}\x{99C7}\x{99C8}\x{99C9}\x{99CA}\x{99CB}\x{99CC}\x{99CD}\x{99CE}' - . '\x{99CF}\x{99D0}\x{99D1}\x{99D2}\x{99D3}\x{99D4}\x{99D5}\x{99D6}\x{99D7}' - . '\x{99D8}\x{99D9}\x{99DA}\x{99DB}\x{99DC}\x{99DD}\x{99DE}\x{99DF}\x{99E1}' - . '\x{99E2}\x{99E3}\x{99E4}\x{99E5}\x{99E7}\x{99E8}\x{99E9}\x{99EA}\x{99EC}' - . '\x{99ED}\x{99EE}\x{99EF}\x{99F0}\x{99F1}\x{99F2}\x{99F3}\x{99F4}\x{99F6}' - . '\x{99F7}\x{99F8}\x{99F9}\x{99FA}\x{99FB}\x{99FC}\x{99FD}\x{99FE}\x{99FF}' - . '\x{9A00}\x{9A01}\x{9A02}\x{9A03}\x{9A04}\x{9A05}\x{9A06}\x{9A07}\x{9A08}' - . '\x{9A09}\x{9A0A}\x{9A0B}\x{9A0C}\x{9A0D}\x{9A0E}\x{9A0F}\x{9A11}\x{9A14}' - . '\x{9A15}\x{9A16}\x{9A19}\x{9A1A}\x{9A1B}\x{9A1C}\x{9A1D}\x{9A1E}\x{9A1F}' - . '\x{9A20}\x{9A21}\x{9A22}\x{9A23}\x{9A24}\x{9A25}\x{9A26}\x{9A27}\x{9A29}' - . '\x{9A2A}\x{9A2B}\x{9A2C}\x{9A2D}\x{9A2E}\x{9A2F}\x{9A30}\x{9A31}\x{9A32}' - . '\x{9A33}\x{9A34}\x{9A35}\x{9A36}\x{9A37}\x{9A38}\x{9A39}\x{9A3A}\x{9A3C}' - . '\x{9A3D}\x{9A3E}\x{9A3F}\x{9A40}\x{9A41}\x{9A42}\x{9A43}\x{9A44}\x{9A45}' - . '\x{9A46}\x{9A47}\x{9A48}\x{9A49}\x{9A4A}\x{9A4B}\x{9A4C}\x{9A4D}\x{9A4E}' - . '\x{9A4F}\x{9A50}\x{9A52}\x{9A53}\x{9A54}\x{9A55}\x{9A56}\x{9A57}\x{9A59}' - . '\x{9A5A}\x{9A5B}\x{9A5C}\x{9A5E}\x{9A5F}\x{9A60}\x{9A61}\x{9A62}\x{9A64}' - . '\x{9A65}\x{9A66}\x{9A67}\x{9A68}\x{9A69}\x{9A6A}\x{9A6B}\x{9A6C}\x{9A6D}' - . '\x{9A6E}\x{9A6F}\x{9A70}\x{9A71}\x{9A72}\x{9A73}\x{9A74}\x{9A75}\x{9A76}' - . '\x{9A77}\x{9A78}\x{9A79}\x{9A7A}\x{9A7B}\x{9A7C}\x{9A7D}\x{9A7E}\x{9A7F}' - . '\x{9A80}\x{9A81}\x{9A82}\x{9A83}\x{9A84}\x{9A85}\x{9A86}\x{9A87}\x{9A88}' - . '\x{9A89}\x{9A8A}\x{9A8B}\x{9A8C}\x{9A8D}\x{9A8E}\x{9A8F}\x{9A90}\x{9A91}' - . '\x{9A92}\x{9A93}\x{9A94}\x{9A95}\x{9A96}\x{9A97}\x{9A98}\x{9A99}\x{9A9A}' - . '\x{9A9B}\x{9A9C}\x{9A9D}\x{9A9E}\x{9A9F}\x{9AA0}\x{9AA1}\x{9AA2}\x{9AA3}' - . '\x{9AA4}\x{9AA5}\x{9AA6}\x{9AA7}\x{9AA8}\x{9AAA}\x{9AAB}\x{9AAC}\x{9AAD}' - . '\x{9AAE}\x{9AAF}\x{9AB0}\x{9AB1}\x{9AB2}\x{9AB3}\x{9AB4}\x{9AB5}\x{9AB6}' - . '\x{9AB7}\x{9AB8}\x{9AB9}\x{9ABA}\x{9ABB}\x{9ABC}\x{9ABE}\x{9ABF}\x{9AC0}' - . '\x{9AC1}\x{9AC2}\x{9AC3}\x{9AC4}\x{9AC5}\x{9AC6}\x{9AC7}\x{9AC9}\x{9ACA}' - . '\x{9ACB}\x{9ACC}\x{9ACD}\x{9ACE}\x{9ACF}\x{9AD0}\x{9AD1}\x{9AD2}\x{9AD3}' - . '\x{9AD4}\x{9AD5}\x{9AD6}\x{9AD8}\x{9AD9}\x{9ADA}\x{9ADB}\x{9ADC}\x{9ADD}' - . '\x{9ADE}\x{9ADF}\x{9AE1}\x{9AE2}\x{9AE3}\x{9AE5}\x{9AE6}\x{9AE7}\x{9AEA}' - . '\x{9AEB}\x{9AEC}\x{9AED}\x{9AEE}\x{9AEF}\x{9AF1}\x{9AF2}\x{9AF3}\x{9AF4}' - . '\x{9AF5}\x{9AF6}\x{9AF7}\x{9AF8}\x{9AF9}\x{9AFA}\x{9AFB}\x{9AFC}\x{9AFD}' - . '\x{9AFE}\x{9AFF}\x{9B01}\x{9B03}\x{9B04}\x{9B05}\x{9B06}\x{9B07}\x{9B08}' - . '\x{9B0A}\x{9B0B}\x{9B0C}\x{9B0D}\x{9B0E}\x{9B0F}\x{9B10}\x{9B11}\x{9B12}' - . '\x{9B13}\x{9B15}\x{9B16}\x{9B17}\x{9B18}\x{9B19}\x{9B1A}\x{9B1C}\x{9B1D}' - . '\x{9B1E}\x{9B1F}\x{9B20}\x{9B21}\x{9B22}\x{9B23}\x{9B24}\x{9B25}\x{9B26}' - . '\x{9B27}\x{9B28}\x{9B29}\x{9B2A}\x{9B2B}\x{9B2C}\x{9B2D}\x{9B2E}\x{9B2F}' - . '\x{9B30}\x{9B31}\x{9B32}\x{9B33}\x{9B35}\x{9B36}\x{9B37}\x{9B38}\x{9B39}' - . '\x{9B3A}\x{9B3B}\x{9B3C}\x{9B3E}\x{9B3F}\x{9B41}\x{9B42}\x{9B43}\x{9B44}' - . '\x{9B45}\x{9B46}\x{9B47}\x{9B48}\x{9B49}\x{9B4A}\x{9B4B}\x{9B4C}\x{9B4D}' - . '\x{9B4E}\x{9B4F}\x{9B51}\x{9B52}\x{9B53}\x{9B54}\x{9B55}\x{9B56}\x{9B58}' - . '\x{9B59}\x{9B5A}\x{9B5B}\x{9B5C}\x{9B5D}\x{9B5E}\x{9B5F}\x{9B60}\x{9B61}' - . '\x{9B63}\x{9B64}\x{9B65}\x{9B66}\x{9B67}\x{9B68}\x{9B69}\x{9B6A}\x{9B6B}' - . '\x{9B6C}\x{9B6D}\x{9B6E}\x{9B6F}\x{9B70}\x{9B71}\x{9B73}\x{9B74}\x{9B75}' - . '\x{9B76}\x{9B77}\x{9B78}\x{9B79}\x{9B7A}\x{9B7B}\x{9B7C}\x{9B7D}\x{9B7E}' - . '\x{9B7F}\x{9B80}\x{9B81}\x{9B82}\x{9B83}\x{9B84}\x{9B85}\x{9B86}\x{9B87}' - . '\x{9B88}\x{9B8A}\x{9B8B}\x{9B8D}\x{9B8E}\x{9B8F}\x{9B90}\x{9B91}\x{9B92}' - . '\x{9B93}\x{9B94}\x{9B95}\x{9B96}\x{9B97}\x{9B98}\x{9B9A}\x{9B9B}\x{9B9C}' - . '\x{9B9D}\x{9B9E}\x{9B9F}\x{9BA0}\x{9BA1}\x{9BA2}\x{9BA3}\x{9BA4}\x{9BA5}' - . '\x{9BA6}\x{9BA7}\x{9BA8}\x{9BA9}\x{9BAA}\x{9BAB}\x{9BAC}\x{9BAD}\x{9BAE}' - . '\x{9BAF}\x{9BB0}\x{9BB1}\x{9BB2}\x{9BB3}\x{9BB4}\x{9BB5}\x{9BB6}\x{9BB7}' - . '\x{9BB8}\x{9BB9}\x{9BBA}\x{9BBB}\x{9BBC}\x{9BBD}\x{9BBE}\x{9BBF}\x{9BC0}' - . '\x{9BC1}\x{9BC3}\x{9BC4}\x{9BC5}\x{9BC6}\x{9BC7}\x{9BC8}\x{9BC9}\x{9BCA}' - . '\x{9BCB}\x{9BCC}\x{9BCD}\x{9BCE}\x{9BCF}\x{9BD0}\x{9BD1}\x{9BD2}\x{9BD3}' - . '\x{9BD4}\x{9BD5}\x{9BD6}\x{9BD7}\x{9BD8}\x{9BD9}\x{9BDA}\x{9BDB}\x{9BDC}' - . '\x{9BDD}\x{9BDE}\x{9BDF}\x{9BE0}\x{9BE1}\x{9BE2}\x{9BE3}\x{9BE4}\x{9BE5}' - . '\x{9BE6}\x{9BE7}\x{9BE8}\x{9BE9}\x{9BEA}\x{9BEB}\x{9BEC}\x{9BED}\x{9BEE}' - . '\x{9BEF}\x{9BF0}\x{9BF1}\x{9BF2}\x{9BF3}\x{9BF4}\x{9BF5}\x{9BF7}\x{9BF8}' - . '\x{9BF9}\x{9BFA}\x{9BFB}\x{9BFC}\x{9BFD}\x{9BFE}\x{9BFF}\x{9C02}\x{9C05}' - . '\x{9C06}\x{9C07}\x{9C08}\x{9C09}\x{9C0A}\x{9C0B}\x{9C0C}\x{9C0D}\x{9C0E}' - . '\x{9C0F}\x{9C10}\x{9C11}\x{9C12}\x{9C13}\x{9C14}\x{9C15}\x{9C16}\x{9C17}' - . '\x{9C18}\x{9C19}\x{9C1A}\x{9C1B}\x{9C1C}\x{9C1D}\x{9C1E}\x{9C1F}\x{9C20}' - . '\x{9C21}\x{9C22}\x{9C23}\x{9C24}\x{9C25}\x{9C26}\x{9C27}\x{9C28}\x{9C29}' - . '\x{9C2A}\x{9C2B}\x{9C2C}\x{9C2D}\x{9C2F}\x{9C30}\x{9C31}\x{9C32}\x{9C33}' - . '\x{9C34}\x{9C35}\x{9C36}\x{9C37}\x{9C38}\x{9C39}\x{9C3A}\x{9C3B}\x{9C3C}' - . '\x{9C3D}\x{9C3E}\x{9C3F}\x{9C40}\x{9C41}\x{9C43}\x{9C44}\x{9C45}\x{9C46}' - . '\x{9C47}\x{9C48}\x{9C49}\x{9C4A}\x{9C4B}\x{9C4C}\x{9C4D}\x{9C4E}\x{9C50}' - . '\x{9C52}\x{9C53}\x{9C54}\x{9C55}\x{9C56}\x{9C57}\x{9C58}\x{9C59}\x{9C5A}' - . '\x{9C5B}\x{9C5C}\x{9C5D}\x{9C5E}\x{9C5F}\x{9C60}\x{9C62}\x{9C63}\x{9C65}' - . '\x{9C66}\x{9C67}\x{9C68}\x{9C69}\x{9C6A}\x{9C6B}\x{9C6C}\x{9C6D}\x{9C6E}' - . '\x{9C6F}\x{9C70}\x{9C71}\x{9C72}\x{9C73}\x{9C74}\x{9C75}\x{9C77}\x{9C78}' - . '\x{9C79}\x{9C7A}\x{9C7C}\x{9C7D}\x{9C7E}\x{9C7F}\x{9C80}\x{9C81}\x{9C82}' - . '\x{9C83}\x{9C84}\x{9C85}\x{9C86}\x{9C87}\x{9C88}\x{9C89}\x{9C8A}\x{9C8B}' - . '\x{9C8C}\x{9C8D}\x{9C8E}\x{9C8F}\x{9C90}\x{9C91}\x{9C92}\x{9C93}\x{9C94}' - . '\x{9C95}\x{9C96}\x{9C97}\x{9C98}\x{9C99}\x{9C9A}\x{9C9B}\x{9C9C}\x{9C9D}' - . '\x{9C9E}\x{9C9F}\x{9CA0}\x{9CA1}\x{9CA2}\x{9CA3}\x{9CA4}\x{9CA5}\x{9CA6}' - . '\x{9CA7}\x{9CA8}\x{9CA9}\x{9CAA}\x{9CAB}\x{9CAC}\x{9CAD}\x{9CAE}\x{9CAF}' - . '\x{9CB0}\x{9CB1}\x{9CB2}\x{9CB3}\x{9CB4}\x{9CB5}\x{9CB6}\x{9CB7}\x{9CB8}' - . '\x{9CB9}\x{9CBA}\x{9CBB}\x{9CBC}\x{9CBD}\x{9CBE}\x{9CBF}\x{9CC0}\x{9CC1}' - . '\x{9CC2}\x{9CC3}\x{9CC4}\x{9CC5}\x{9CC6}\x{9CC7}\x{9CC8}\x{9CC9}\x{9CCA}' - . '\x{9CCB}\x{9CCC}\x{9CCD}\x{9CCE}\x{9CCF}\x{9CD0}\x{9CD1}\x{9CD2}\x{9CD3}' - . '\x{9CD4}\x{9CD5}\x{9CD6}\x{9CD7}\x{9CD8}\x{9CD9}\x{9CDA}\x{9CDB}\x{9CDC}' - . '\x{9CDD}\x{9CDE}\x{9CDF}\x{9CE0}\x{9CE1}\x{9CE2}\x{9CE3}\x{9CE4}\x{9CE5}' - . '\x{9CE6}\x{9CE7}\x{9CE8}\x{9CE9}\x{9CEA}\x{9CEB}\x{9CEC}\x{9CED}\x{9CEE}' - . '\x{9CEF}\x{9CF0}\x{9CF1}\x{9CF2}\x{9CF3}\x{9CF4}\x{9CF5}\x{9CF6}\x{9CF7}' - . '\x{9CF8}\x{9CF9}\x{9CFA}\x{9CFB}\x{9CFC}\x{9CFD}\x{9CFE}\x{9CFF}\x{9D00}' - . '\x{9D01}\x{9D02}\x{9D03}\x{9D04}\x{9D05}\x{9D06}\x{9D07}\x{9D08}\x{9D09}' - . '\x{9D0A}\x{9D0B}\x{9D0F}\x{9D10}\x{9D12}\x{9D13}\x{9D14}\x{9D15}\x{9D16}' - . '\x{9D17}\x{9D18}\x{9D19}\x{9D1A}\x{9D1B}\x{9D1C}\x{9D1D}\x{9D1E}\x{9D1F}' - . '\x{9D20}\x{9D21}\x{9D22}\x{9D23}\x{9D24}\x{9D25}\x{9D26}\x{9D28}\x{9D29}' - . '\x{9D2B}\x{9D2D}\x{9D2E}\x{9D2F}\x{9D30}\x{9D31}\x{9D32}\x{9D33}\x{9D34}' - . '\x{9D36}\x{9D37}\x{9D38}\x{9D39}\x{9D3A}\x{9D3B}\x{9D3D}\x{9D3E}\x{9D3F}' - . '\x{9D40}\x{9D41}\x{9D42}\x{9D43}\x{9D45}\x{9D46}\x{9D47}\x{9D48}\x{9D49}' - . '\x{9D4A}\x{9D4B}\x{9D4C}\x{9D4D}\x{9D4E}\x{9D4F}\x{9D50}\x{9D51}\x{9D52}' - . '\x{9D53}\x{9D54}\x{9D55}\x{9D56}\x{9D57}\x{9D58}\x{9D59}\x{9D5A}\x{9D5B}' - . '\x{9D5C}\x{9D5D}\x{9D5E}\x{9D5F}\x{9D60}\x{9D61}\x{9D62}\x{9D63}\x{9D64}' - . '\x{9D65}\x{9D66}\x{9D67}\x{9D68}\x{9D69}\x{9D6A}\x{9D6B}\x{9D6C}\x{9D6E}' - . '\x{9D6F}\x{9D70}\x{9D71}\x{9D72}\x{9D73}\x{9D74}\x{9D75}\x{9D76}\x{9D77}' - . '\x{9D78}\x{9D79}\x{9D7A}\x{9D7B}\x{9D7C}\x{9D7D}\x{9D7E}\x{9D7F}\x{9D80}' - . '\x{9D81}\x{9D82}\x{9D83}\x{9D84}\x{9D85}\x{9D86}\x{9D87}\x{9D88}\x{9D89}' - . '\x{9D8A}\x{9D8B}\x{9D8C}\x{9D8D}\x{9D8E}\x{9D90}\x{9D91}\x{9D92}\x{9D93}' - . '\x{9D94}\x{9D96}\x{9D97}\x{9D98}\x{9D99}\x{9D9A}\x{9D9B}\x{9D9C}\x{9D9D}' - . '\x{9D9E}\x{9D9F}\x{9DA0}\x{9DA1}\x{9DA2}\x{9DA3}\x{9DA4}\x{9DA5}\x{9DA6}' - . '\x{9DA7}\x{9DA8}\x{9DA9}\x{9DAA}\x{9DAB}\x{9DAC}\x{9DAD}\x{9DAF}\x{9DB0}' - . '\x{9DB1}\x{9DB2}\x{9DB3}\x{9DB4}\x{9DB5}\x{9DB6}\x{9DB7}\x{9DB8}\x{9DB9}' - . '\x{9DBA}\x{9DBB}\x{9DBC}\x{9DBE}\x{9DBF}\x{9DC1}\x{9DC2}\x{9DC3}\x{9DC4}' - . '\x{9DC5}\x{9DC7}\x{9DC8}\x{9DC9}\x{9DCA}\x{9DCB}\x{9DCC}\x{9DCD}\x{9DCE}' - . '\x{9DCF}\x{9DD0}\x{9DD1}\x{9DD2}\x{9DD3}\x{9DD4}\x{9DD5}\x{9DD6}\x{9DD7}' - . '\x{9DD8}\x{9DD9}\x{9DDA}\x{9DDB}\x{9DDC}\x{9DDD}\x{9DDE}\x{9DDF}\x{9DE0}' - . '\x{9DE1}\x{9DE2}\x{9DE3}\x{9DE4}\x{9DE5}\x{9DE6}\x{9DE7}\x{9DE8}\x{9DE9}' - . '\x{9DEB}\x{9DEC}\x{9DED}\x{9DEE}\x{9DEF}\x{9DF0}\x{9DF1}\x{9DF2}\x{9DF3}' - . '\x{9DF4}\x{9DF5}\x{9DF6}\x{9DF7}\x{9DF8}\x{9DF9}\x{9DFA}\x{9DFB}\x{9DFD}' - . '\x{9DFE}\x{9DFF}\x{9E00}\x{9E01}\x{9E02}\x{9E03}\x{9E04}\x{9E05}\x{9E06}' - . '\x{9E07}\x{9E08}\x{9E09}\x{9E0A}\x{9E0B}\x{9E0C}\x{9E0D}\x{9E0F}\x{9E10}' - . '\x{9E11}\x{9E12}\x{9E13}\x{9E14}\x{9E15}\x{9E17}\x{9E18}\x{9E19}\x{9E1A}' - . '\x{9E1B}\x{9E1D}\x{9E1E}\x{9E1F}\x{9E20}\x{9E21}\x{9E22}\x{9E23}\x{9E24}' - . '\x{9E25}\x{9E26}\x{9E27}\x{9E28}\x{9E29}\x{9E2A}\x{9E2B}\x{9E2C}\x{9E2D}' - . '\x{9E2E}\x{9E2F}\x{9E30}\x{9E31}\x{9E32}\x{9E33}\x{9E34}\x{9E35}\x{9E36}' - . '\x{9E37}\x{9E38}\x{9E39}\x{9E3A}\x{9E3B}\x{9E3C}\x{9E3D}\x{9E3E}\x{9E3F}' - . '\x{9E40}\x{9E41}\x{9E42}\x{9E43}\x{9E44}\x{9E45}\x{9E46}\x{9E47}\x{9E48}' - . '\x{9E49}\x{9E4A}\x{9E4B}\x{9E4C}\x{9E4D}\x{9E4E}\x{9E4F}\x{9E50}\x{9E51}' - . '\x{9E52}\x{9E53}\x{9E54}\x{9E55}\x{9E56}\x{9E57}\x{9E58}\x{9E59}\x{9E5A}' - . '\x{9E5B}\x{9E5C}\x{9E5D}\x{9E5E}\x{9E5F}\x{9E60}\x{9E61}\x{9E62}\x{9E63}' - . '\x{9E64}\x{9E65}\x{9E66}\x{9E67}\x{9E68}\x{9E69}\x{9E6A}\x{9E6B}\x{9E6C}' - . '\x{9E6D}\x{9E6E}\x{9E6F}\x{9E70}\x{9E71}\x{9E72}\x{9E73}\x{9E74}\x{9E75}' - . '\x{9E76}\x{9E77}\x{9E79}\x{9E7A}\x{9E7C}\x{9E7D}\x{9E7E}\x{9E7F}\x{9E80}' - . '\x{9E81}\x{9E82}\x{9E83}\x{9E84}\x{9E85}\x{9E86}\x{9E87}\x{9E88}\x{9E89}' - . '\x{9E8A}\x{9E8B}\x{9E8C}\x{9E8D}\x{9E8E}\x{9E91}\x{9E92}\x{9E93}\x{9E94}' - . '\x{9E96}\x{9E97}\x{9E99}\x{9E9A}\x{9E9B}\x{9E9C}\x{9E9D}\x{9E9F}\x{9EA0}' - . '\x{9EA1}\x{9EA3}\x{9EA4}\x{9EA5}\x{9EA6}\x{9EA7}\x{9EA8}\x{9EA9}\x{9EAA}' - . '\x{9EAD}\x{9EAE}\x{9EAF}\x{9EB0}\x{9EB2}\x{9EB3}\x{9EB4}\x{9EB5}\x{9EB6}' - . '\x{9EB7}\x{9EB8}\x{9EBB}\x{9EBC}\x{9EBD}\x{9EBE}\x{9EBF}\x{9EC0}\x{9EC1}' - . '\x{9EC2}\x{9EC3}\x{9EC4}\x{9EC5}\x{9EC6}\x{9EC7}\x{9EC8}\x{9EC9}\x{9ECA}' - . '\x{9ECB}\x{9ECC}\x{9ECD}\x{9ECE}\x{9ECF}\x{9ED0}\x{9ED1}\x{9ED2}\x{9ED3}' - . '\x{9ED4}\x{9ED5}\x{9ED6}\x{9ED7}\x{9ED8}\x{9ED9}\x{9EDA}\x{9EDB}\x{9EDC}' - . '\x{9EDD}\x{9EDE}\x{9EDF}\x{9EE0}\x{9EE1}\x{9EE2}\x{9EE3}\x{9EE4}\x{9EE5}' - . '\x{9EE6}\x{9EE7}\x{9EE8}\x{9EE9}\x{9EEA}\x{9EEB}\x{9EED}\x{9EEE}\x{9EEF}' - . '\x{9EF0}\x{9EF2}\x{9EF3}\x{9EF4}\x{9EF5}\x{9EF6}\x{9EF7}\x{9EF8}\x{9EF9}' - . '\x{9EFA}\x{9EFB}\x{9EFC}\x{9EFD}\x{9EFE}\x{9EFF}\x{9F00}\x{9F01}\x{9F02}' - . '\x{9F04}\x{9F05}\x{9F06}\x{9F07}\x{9F08}\x{9F09}\x{9F0A}\x{9F0B}\x{9F0C}' - . '\x{9F0D}\x{9F0E}\x{9F0F}\x{9F10}\x{9F12}\x{9F13}\x{9F15}\x{9F16}\x{9F17}' - . '\x{9F18}\x{9F19}\x{9F1A}\x{9F1B}\x{9F1C}\x{9F1D}\x{9F1E}\x{9F1F}\x{9F20}' - . '\x{9F22}\x{9F23}\x{9F24}\x{9F25}\x{9F27}\x{9F28}\x{9F29}\x{9F2A}\x{9F2B}' - . '\x{9F2C}\x{9F2D}\x{9F2E}\x{9F2F}\x{9F30}\x{9F31}\x{9F32}\x{9F33}\x{9F34}' - . '\x{9F35}\x{9F36}\x{9F37}\x{9F38}\x{9F39}\x{9F3A}\x{9F3B}\x{9F3C}\x{9F3D}' - . '\x{9F3E}\x{9F3F}\x{9F40}\x{9F41}\x{9F42}\x{9F43}\x{9F44}\x{9F46}\x{9F47}' - . '\x{9F48}\x{9F49}\x{9F4A}\x{9F4B}\x{9F4C}\x{9F4D}\x{9F4E}\x{9F4F}\x{9F50}' - . '\x{9F51}\x{9F52}\x{9F54}\x{9F55}\x{9F56}\x{9F57}\x{9F58}\x{9F59}\x{9F5A}' - . '\x{9F5B}\x{9F5C}\x{9F5D}\x{9F5E}\x{9F5F}\x{9F60}\x{9F61}\x{9F63}\x{9F64}' - . '\x{9F65}\x{9F66}\x{9F67}\x{9F68}\x{9F69}\x{9F6A}\x{9F6B}\x{9F6C}\x{9F6E}' - . '\x{9F6F}\x{9F70}\x{9F71}\x{9F72}\x{9F73}\x{9F74}\x{9F75}\x{9F76}\x{9F77}' - . '\x{9F78}\x{9F79}\x{9F7A}\x{9F7B}\x{9F7C}\x{9F7D}\x{9F7E}\x{9F7F}\x{9F80}' - . '\x{9F81}\x{9F82}\x{9F83}\x{9F84}\x{9F85}\x{9F86}\x{9F87}\x{9F88}\x{9F89}' - . '\x{9F8A}\x{9F8B}\x{9F8C}\x{9F8D}\x{9F8E}\x{9F8F}\x{9F90}\x{9F91}\x{9F92}' - . '\x{9F93}\x{9F94}\x{9F95}\x{9F96}\x{9F97}\x{9F98}\x{9F99}\x{9F9A}\x{9F9B}' - . '\x{9F9C}\x{9F9D}\x{9F9E}\x{9F9F}\x{9FA0}\x{9FA2}\x{9FA4}\x{9FA5}]{1,20}$/iu', -]; diff --git a/lib/laminas/laminas-validator/src/Hostname/Com.php b/lib/laminas/laminas-validator/src/Hostname/Com.php deleted file mode 100644 index 5db58df61..000000000 --- a/lib/laminas/laminas-validator/src/Hostname/Com.php +++ /dev/null @@ -1,176 +0,0 @@ -<?php // phpcs:disable PSR12.Files.FileHeader.IncorrectOrder,WebimpressCodingStandard.Arrays.DoubleArrow.SpacesBefore - -namespace Laminas\Validator\Hostname; - -/** - * Resource file for com and net idn validation - */ - -return [ - 1 => '/^[\x{002d}0-9\x{0400}-\x{052f}]{1,63}$/iu', - 2 => '/^[\x{002d}0-9\x{0370}-\x{03ff}]{1,63}$/iu', - 3 => '/^[\x{002d}0-9a-z\x{ac00}-\x{d7a3}]{1,17}$/iu', - // @codingStandardsIgnoreStart - 4 => '/^[\x{002d}0-9a-z·à-öø-ÿāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĸĺļľłńņňŋōŏőœŕŗřśŝşšţťŧũūŭůűųŵŷźżž]{1,63}$/iu', - // @codingStandardsIgnoreEnd - 5 => '/^[\x{002d}0-9A-Za-z\x{3400}-\x{3401}\x{3404}-\x{3406}\x{340C}\x{3416}\x{341C}' -. '\x{3421}\x{3424}\x{3428}-\x{3429}\x{342B}-\x{342E}\x{3430}-\x{3434}\x{3436}' -. '\x{3438}-\x{343C}\x{343E}\x{3441}-\x{3445}\x{3447}\x{3449}-\x{3451}\x{3453}' -. '\x{3457}-\x{345F}\x{3463}-\x{3467}\x{346E}-\x{3471}\x{3473}-\x{3477}\x{3479}-\x{348E}\x{3491}-\x{3497}' -. '\x{3499}-\x{34A1}\x{34A4}-\x{34AD}\x{34AF}-\x{34B0}\x{34B2}-\x{34BF}\x{34C2}-\x{34C5}\x{34C7}-\x{34CC}' -. '\x{34CE}-\x{34D1}\x{34D3}-\x{34D8}\x{34DA}-\x{34E4}\x{34E7}-\x{34E9}\x{34EC}-\x{34EF}\x{34F1}-\x{34FE}' -. '\x{3500}-\x{3507}\x{350A}-\x{3513}\x{3515}\x{3517}-\x{351A}\x{351C}-\x{351E}\x{3520}-\x{352A}' -. '\x{352C}-\x{3552}\x{3554}-\x{355C}\x{355E}-\x{3567}\x{3569}-\x{3573}\x{3575}-\x{357C}\x{3580}-\x{3588}' -. '\x{358F}-\x{3598}\x{359E}-\x{35AB}\x{35B4}-\x{35CD}\x{35D0}\x{35D3}-\x{35DC}\x{35E2}-\x{35ED}' -. '\x{35F0}-\x{35F6}\x{35FB}-\x{3602}\x{3605}-\x{360E}\x{3610}-\x{3611}\x{3613}-\x{3616}\x{3619}-\x{362D}' -. '\x{362F}-\x{3634}\x{3636}-\x{363B}\x{363F}-\x{3645}\x{3647}-\x{364B}\x{364D}-\x{3653}\x{3655}' -. '\x{3659}-\x{365E}\x{3660}-\x{3665}\x{3667}-\x{367C}\x{367E}\x{3680}-\x{3685}\x{3687}' -. '\x{3689}-\x{3690}\x{3692}-\x{3698}\x{369A}\x{369C}-\x{36AE}\x{36B0}-\x{36BF}\x{36C1}-\x{36C5}' -. '\x{36C9}-\x{36CA}\x{36CD}-\x{36DE}\x{36E1}-\x{36E2}\x{36E5}-\x{36FE}\x{3701}-\x{3713}\x{3715}-\x{371E}' -. '\x{3720}-\x{372C}\x{372E}-\x{3745}\x{3747}-\x{3748}\x{374A}\x{374C}-\x{3759}\x{375B}-\x{3760}' -. '\x{3762}-\x{3767}\x{3769}-\x{3772}\x{3774}-\x{378C}\x{378F}-\x{379C}\x{379F}\x{37A1}-\x{37AD}' -. '\x{37AF}-\x{37B7}\x{37B9}-\x{37C1}\x{37C3}-\x{37C5}\x{37C7}-\x{37D4}\x{37D6}-\x{37E0}\x{37E2}' -. '\x{37E5}-\x{37ED}\x{37EF}-\x{37F6}\x{37F8}-\x{3802}\x{3804}-\x{381D}\x{3820}-\x{3822}\x{3825}-\x{382A}' -. '\x{382D}-\x{382F}\x{3831}-\x{3832}\x{3834}-\x{384C}\x{384E}-\x{3860}\x{3862}-\x{3863}\x{3865}-\x{386B}' -. '\x{386D}-\x{3886}\x{3888}-\x{38A1}\x{38A3}\x{38A5}-\x{38AA}\x{38AC}\x{38AE}-\x{38B0}' -. '\x{38B2}-\x{38B6}\x{38B8}\x{38BA}-\x{38BE}\x{38C0}-\x{38C9}\x{38CB}-\x{38D4}\x{38D8}-\x{38E0}' -. '\x{38E2}-\x{38E6}\x{38EB}-\x{38ED}\x{38EF}-\x{38F2}\x{38F5}-\x{38F7}\x{38FA}-\x{38FF}\x{3901}-\x{392A}' -. '\x{392C}\x{392E}-\x{393B}\x{393E}-\x{3956}\x{395A}-\x{3969}\x{396B}-\x{397A}\x{397C}-\x{3987}' -. '\x{3989}-\x{3998}\x{399A}-\x{39B0}\x{39B2}\x{39B4}-\x{39D0}\x{39D2}-\x{39DA}\x{39DE}-\x{39DF}' -. '\x{39E1}-\x{39EF}\x{39F1}-\x{3A17}\x{3A19}-\x{3A2A}\x{3A2D}-\x{3A40}\x{3A43}-\x{3A4E}\x{3A50}' -. '\x{3A52}-\x{3A5E}\x{3A60}-\x{3A6D}\x{3A6F}-\x{3A77}\x{3A79}-\x{3A82}\x{3A84}-\x{3A85}\x{3A87}-\x{3A89}' -. '\x{3A8B}-\x{3A8F}\x{3A91}-\x{3A93}\x{3A95}-\x{3A96}\x{3A9A}\x{3A9C}-\x{3AA6}\x{3AA8}-\x{3AA9}' -. '\x{3AAB}-\x{3AB1}\x{3AB4}-\x{3ABC}\x{3ABE}-\x{3AC5}\x{3ACA}-\x{3ACB}\x{3ACD}-\x{3AD5}\x{3AD7}-\x{3AE1}' -. '\x{3AE4}-\x{3AE7}\x{3AE9}-\x{3AEC}\x{3AEE}-\x{3AFD}\x{3B01}-\x{3B10}\x{3B12}-\x{3B15}\x{3B17}-\x{3B1E}' -. '\x{3B20}-\x{3B23}\x{3B25}-\x{3B27}\x{3B29}-\x{3B36}\x{3B38}-\x{3B39}\x{3B3B}-\x{3B3C}\x{3B3F}' -. '\x{3B41}-\x{3B44}\x{3B47}-\x{3B4C}\x{3B4E}\x{3B51}-\x{3B55}\x{3B58}-\x{3B62}\x{3B68}-\x{3B72}' -. '\x{3B78}-\x{3B88}\x{3B8B}-\x{3B9F}\x{3BA1}\x{3BA3}-\x{3BBA}\x{3BBC}\x{3BBF}-\x{3BD0}' -. '\x{3BD3}-\x{3BE6}\x{3BEA}-\x{3BFB}\x{3BFE}-\x{3C12}\x{3C14}-\x{3C1B}\x{3C1D}-\x{3C37}\x{3C39}-\x{3C4F}' -. '\x{3C52}\x{3C54}-\x{3C5C}\x{3C5E}-\x{3C68}\x{3C6A}-\x{3C76}\x{3C78}-\x{3C8F}\x{3C91}-\x{3CA8}' -. '\x{3CAA}-\x{3CAD}\x{3CAF}-\x{3CBE}\x{3CC0}-\x{3CC8}\x{3CCA}-\x{3CD3}\x{3CD6}-\x{3CE0}\x{3CE4}-\x{3CEE}' -. '\x{3CF3}-\x{3D0A}\x{3D0E}-\x{3D1E}\x{3D20}-\x{3D21}\x{3D25}-\x{3D38}\x{3D3B}-\x{3D46}\x{3D4A}-\x{3D59}' -. '\x{3D5D}-\x{3D7B}\x{3D7D}-\x{3D81}\x{3D84}-\x{3D88}\x{3D8C}-\x{3D8F}\x{3D91}-\x{3D98}\x{3D9A}-\x{3D9C}' -. '\x{3D9E}-\x{3DA1}\x{3DA3}-\x{3DB0}\x{3DB2}-\x{3DB5}\x{3DB9}-\x{3DBC}\x{3DBE}-\x{3DCB}\x{3DCD}-\x{3DDB}' -. '\x{3DDF}-\x{3DE8}\x{3DEB}-\x{3DF0}\x{3DF3}-\x{3DF9}\x{3DFB}-\x{3DFC}\x{3DFE}-\x{3E05}\x{3E08}-\x{3E33}' -. '\x{3E35}-\x{3E3E}\x{3E40}-\x{3E47}\x{3E49}-\x{3E67}\x{3E6B}-\x{3E6F}\x{3E71}-\x{3E85}\x{3E87}-\x{3E8C}' -. '\x{3E8E}-\x{3E98}\x{3E9A}-\x{3EA1}\x{3EA3}-\x{3EAE}\x{3EB0}-\x{3EB5}\x{3EB7}-\x{3EBA}\x{3EBD}' -. '\x{3EBF}-\x{3EC4}\x{3EC7}-\x{3ECE}\x{3ED1}-\x{3ED7}\x{3ED9}-\x{3EDA}\x{3EDD}-\x{3EE3}\x{3EE7}-\x{3EE8}' -. '\x{3EEB}-\x{3EF2}\x{3EF5}-\x{3EFF}\x{3F01}-\x{3F02}\x{3F04}-\x{3F07}\x{3F09}-\x{3F44}\x{3F46}-\x{3F4E}' -. '\x{3F50}-\x{3F53}\x{3F55}-\x{3F72}\x{3F74}-\x{3F75}\x{3F77}-\x{3F7B}\x{3F7D}-\x{3FB0}\x{3FB6}-\x{3FBF}' -. '\x{3FC1}-\x{3FCF}\x{3FD1}-\x{3FD3}\x{3FD5}-\x{3FDF}\x{3FE1}-\x{400B}\x{400D}-\x{401C}\x{401E}-\x{4024}' -. '\x{4027}-\x{403F}\x{4041}-\x{4060}\x{4062}-\x{4069}\x{406B}-\x{408A}\x{408C}-\x{40A7}\x{40A9}-\x{40B4}' -. '\x{40B6}-\x{40C2}\x{40C7}-\x{40CF}\x{40D1}-\x{40DE}\x{40E0}-\x{40E7}\x{40E9}-\x{40EE}\x{40F0}-\x{40FB}' -. '\x{40FD}-\x{4109}\x{410B}-\x{4115}\x{4118}-\x{411D}\x{411F}-\x{4122}\x{4124}-\x{4133}\x{4136}-\x{4138}' -. '\x{413A}-\x{4148}\x{414A}-\x{4169}\x{416C}-\x{4185}\x{4188}-\x{418B}\x{418D}-\x{41AD}\x{41AF}-\x{41B3}' -. '\x{41B5}-\x{41C3}\x{41C5}-\x{41C9}\x{41CB}-\x{41F2}\x{41F5}-\x{41FE}\x{4200}-\x{4227}\x{422A}-\x{4246}' -. '\x{4248}-\x{4263}\x{4265}-\x{428B}\x{428D}-\x{42A1}\x{42A3}-\x{42C4}\x{42C8}-\x{42DC}\x{42DE}-\x{430A}' -. '\x{430C}-\x{4335}\x{4337}\x{4342}-\x{435F}\x{4361}-\x{439A}\x{439C}-\x{439D}\x{439F}-\x{43A4}' -. '\x{43A6}-\x{43EC}\x{43EF}-\x{4405}\x{4407}-\x{4429}\x{442B}-\x{4455}\x{4457}-\x{4468}\x{446A}-\x{446D}' -. '\x{446F}-\x{4476}\x{4479}-\x{447D}\x{447F}-\x{4486}\x{4488}-\x{4490}\x{4492}-\x{4498}\x{449A}-\x{44AD}' -. '\x{44B0}-\x{44BD}\x{44C1}-\x{44D3}\x{44D6}-\x{44E7}\x{44EA}\x{44EC}-\x{44FA}\x{44FC}-\x{4541}' -. '\x{4543}-\x{454F}\x{4551}-\x{4562}\x{4564}-\x{4575}\x{4577}-\x{45AB}\x{45AD}-\x{45BD}\x{45BF}-\x{45D5}' -. '\x{45D7}-\x{45EC}\x{45EE}-\x{45F2}\x{45F4}-\x{45FA}\x{45FC}-\x{461A}\x{461C}-\x{461D}\x{461F}-\x{4631}' -. '\x{4633}-\x{4649}\x{464C}\x{464E}-\x{4652}\x{4654}-\x{466A}\x{466C}-\x{4675}\x{4677}-\x{467A}' -. '\x{467C}-\x{4694}\x{4696}-\x{46A3}\x{46A5}-\x{46AB}\x{46AD}-\x{46D2}\x{46D4}-\x{4723}\x{4729}-\x{4732}' -. '\x{4734}-\x{4758}\x{475A}\x{475C}-\x{478B}\x{478D}\x{4791}-\x{47B1}\x{47B3}-\x{47F1}' -. '\x{47F3}-\x{480B}\x{480D}-\x{4815}\x{4817}-\x{4839}\x{483B}-\x{4870}\x{4872}-\x{487A}\x{487C}-\x{487F}' -. '\x{4883}-\x{488E}\x{4890}-\x{4896}\x{4899}-\x{48A2}\x{48A4}-\x{48B9}\x{48BB}-\x{48C8}\x{48CA}-\x{48D1}' -. '\x{48D3}-\x{48E5}\x{48E7}-\x{48F2}\x{48F4}-\x{48FF}\x{4901}-\x{4922}\x{4924}-\x{4928}\x{492A}-\x{4931}' -. '\x{4933}-\x{495B}\x{495D}-\x{4978}\x{497A}\x{497D}\x{4982}-\x{4983}\x{4985}-\x{49A8}' -. '\x{49AA}-\x{49AF}\x{49B1}-\x{49B7}\x{49B9}-\x{49BD}\x{49C1}-\x{49C7}\x{49C9}-\x{49CE}\x{49D0}-\x{49E8}' -. '\x{49EA}\x{49EC}\x{49EE}-\x{4A19}\x{4A1B}-\x{4A43}\x{4A45}-\x{4A4D}\x{4A4F}-\x{4A9E}' -. '\x{4AA0}-\x{4AA9}\x{4AAB}-\x{4B4E}\x{4B50}-\x{4B5B}\x{4B5D}-\x{4B69}\x{4B6B}-\x{4BC2}\x{4BC6}-\x{4BE8}' -. '\x{4BEA}-\x{4BFA}\x{4BFC}-\x{4C06}\x{4C08}-\x{4C2D}\x{4C2F}-\x{4C32}\x{4C34}-\x{4C35}\x{4C37}-\x{4C69}' -. '\x{4C6B}-\x{4C73}\x{4C75}-\x{4C86}\x{4C88}-\x{4C97}\x{4C99}-\x{4C9C}\x{4C9F}-\x{4CA3}\x{4CA5}-\x{4CB5}' -. '\x{4CB7}-\x{4CF8}\x{4CFA}-\x{4D27}\x{4D29}-\x{4DAC}\x{4DAE}-\x{4DB1}\x{4DB3}-\x{4DB5}\x{4E00}-\x{4E54}' -. '\x{4E56}-\x{4E89}\x{4E8B}-\x{4EEC}\x{4EEE}-\x{4FAC}\x{4FAE}-\x{503C}\x{503E}-\x{51E5}\x{51E7}-\x{5270}' -. '\x{5272}-\x{56A1}\x{56A3}-\x{5840}\x{5842}-\x{58B5}\x{58B7}-\x{58CB}\x{58CD}-\x{5BC8}\x{5BCA}-\x{5C01}' -. '\x{5C03}-\x{5C25}\x{5C27}-\x{5D5B}\x{5D5D}-\x{5F08}\x{5F0A}-\x{61F3}\x{61F5}-\x{63BA}\x{63BC}-\x{6441}' -. '\x{6443}-\x{657C}\x{657E}-\x{663E}\x{6640}-\x{66FC}\x{66FE}-\x{6728}\x{672A}-\x{6766}\x{6768}-\x{67A8}' -. '\x{67AA}-\x{685B}\x{685D}-\x{685E}\x{6860}-\x{68B9}\x{68BB}-\x{6AC8}\x{6ACA}-\x{6BB0}\x{6BB2}-\x{6C16}' -. '\x{6C18}-\x{6D9B}\x{6D9D}-\x{6E12}\x{6E14}-\x{6E8B}\x{6E8D}-\x{704D}\x{704F}-\x{7113}\x{7115}-\x{713B}' -. '\x{713D}-\x{7154}\x{7156}-\x{729F}\x{72A1}-\x{731E}\x{7320}-\x{7362}\x{7364}-\x{7533}\x{7535}-\x{7551}' -. '\x{7553}-\x{7572}\x{7574}-\x{75E8}\x{75EA}-\x{7679}\x{767B}-\x{783E}\x{7840}-\x{7A62}\x{7A64}-\x{7AC2}' -. '\x{7AC4}-\x{7B06}\x{7B08}-\x{7B79}\x{7B7B}-\x{7BCE}\x{7BD0}-\x{7D99}\x{7D9B}-\x{7E49}\x{7E4C}-\x{8132}' -. '\x{8134}\x{8136}-\x{81D2}\x{81D4}-\x{8216}\x{8218}-\x{822D}\x{822F}-\x{83B4}\x{83B6}-\x{841F}' -. '\x{8421}-\x{86CC}\x{86CE}-\x{874A}\x{874C}-\x{877E}\x{8780}-\x{8A32}\x{8A34}-\x{8B71}\x{8B73}-\x{8B8E}' -. '\x{8B90}-\x{8DE4}\x{8DE6}-\x{8E9A}\x{8E9C}-\x{8EE1}\x{8EE4}-\x{8F0B}\x{8F0D}-\x{8FB9}\x{8FBB}-\x{9038}' -. '\x{903A}-\x{9196}\x{9198}-\x{91A3}\x{91A5}-\x{91B7}\x{91B9}-\x{91C7}\x{91C9}-\x{91E0}\x{91E2}-\x{91FB}' -. '\x{91FD}-\x{922B}\x{922D}-\x{9270}\x{9272}-\x{9420}\x{9422}-\x{9664}\x{9666}-\x{9679}\x{967B}-\x{9770}' -. '\x{9772}-\x{982B}\x{982D}-\x{98ED}\x{98EF}-\x{99C4}\x{99C6}-\x{9A11}\x{9A14}-\x{9A27}\x{9A29}-\x{9D0D}' -. '\x{9D0F}-\x{9D2B}\x{9D2D}-\x{9D8E}\x{9D90}-\x{9DC5}\x{9DC7}-\x{9E77}\x{9E79}-\x{9EB8}\x{9EBB}-\x{9F20}' -. '\x{9F22}-\x{9F61}\x{9F63}-\x{9FA5}\x{FA28}]{1,20}$/iu', - 6 => '/^[\x{002d}0-9A-Za-z]{1,63}$/iu', - 7 => '/^[\x{00A1}-\x{00FF}]{1,63}$/iu', - 8 => '/^[\x{0100}-\x{017f}]{1,63}$/iu', - 9 => '/^[\x{0180}-\x{024f}]{1,63}$/iu', - 10 => '/^[\x{0250}-\x{02af}]{1,63}$/iu', - 11 => '/^[\x{02b0}-\x{02ff}]{1,63}$/iu', - 12 => '/^[\x{0300}-\x{036f}]{1,63}$/iu', - 13 => '/^[\x{0370}-\x{03ff}]{1,63}$/iu', - 14 => '/^[\x{0400}-\x{04ff}]{1,63}$/iu', - 15 => '/^[\x{0500}-\x{052f}]{1,63}$/iu', - 16 => '/^[\x{0530}-\x{058F}]{1,63}$/iu', - 17 => '/^[\x{0590}-\x{05FF}]{1,63}$/iu', - 18 => '/^[\x{0600}-\x{06FF}]{1,63}$/iu', - 19 => '/^[\x{0700}-\x{074F}]{1,63}$/iu', - 20 => '/^[\x{0780}-\x{07BF}]{1,63}$/iu', - 21 => '/^[\x{0900}-\x{097F}]{1,63}$/iu', - 22 => '/^[\x{0980}-\x{09FF}]{1,63}$/iu', - 23 => '/^[\x{0A00}-\x{0A7F}]{1,63}$/iu', - 24 => '/^[\x{0A80}-\x{0AFF}]{1,63}$/iu', - 25 => '/^[\x{0B00}-\x{0B7F}]{1,63}$/iu', - 26 => '/^[\x{0B80}-\x{0BFF}]{1,63}$/iu', - 27 => '/^[\x{0C00}-\x{0C7F}]{1,63}$/iu', - 28 => '/^[\x{0C80}-\x{0CFF}]{1,63}$/iu', - 29 => '/^[\x{0D00}-\x{0D7F}]{1,63}$/iu', - 30 => '/^[\x{0D80}-\x{0DFF}]{1,63}$/iu', - 31 => '/^[\x{0E00}-\x{0E7F}]{1,63}$/iu', - 32 => '/^[\x{0E80}-\x{0EFF}]{1,63}$/iu', - 33 => '/^[\x{0F00}-\x{0FFF}]{1,63}$/iu', - 34 => '/^[\x{1000}-\x{109F}]{1,63}$/iu', - 35 => '/^[\x{10A0}-\x{10FF}]{1,63}$/iu', - 36 => '/^[\x{1100}-\x{11FF}]{1,63}$/iu', - 37 => '/^[\x{1200}-\x{137F}]{1,63}$/iu', - 38 => '/^[\x{13A0}-\x{13FF}]{1,63}$/iu', - 39 => '/^[\x{1400}-\x{167F}]{1,63}$/iu', - 40 => '/^[\x{1680}-\x{169F}]{1,63}$/iu', - 41 => '/^[\x{16A0}-\x{16FF}]{1,63}$/iu', - 42 => '/^[\x{1700}-\x{171F}]{1,63}$/iu', - 43 => '/^[\x{1720}-\x{173F}]{1,63}$/iu', - 44 => '/^[\x{1740}-\x{175F}]{1,63}$/iu', - 45 => '/^[\x{1760}-\x{177F}]{1,63}$/iu', - 46 => '/^[\x{1780}-\x{17FF}]{1,63}$/iu', - 47 => '/^[\x{1800}-\x{18AF}]{1,63}$/iu', - 48 => '/^[\x{1E00}-\x{1EFF}]{1,63}$/iu', - 49 => '/^[\x{1F00}-\x{1FFF}]{1,63}$/iu', - 50 => '/^[\x{2070}-\x{209F}]{1,63}$/iu', - 51 => '/^[\x{2100}-\x{214F}]{1,63}$/iu', - 52 => '/^[\x{2150}-\x{218F}]{1,63}$/iu', - 53 => '/^[\x{2460}-\x{24FF}]{1,63}$/iu', - 54 => '/^[\x{2E80}-\x{2EFF}]{1,63}$/iu', - 55 => '/^[\x{2F00}-\x{2FDF}]{1,63}$/iu', - 56 => '/^[\x{2FF0}-\x{2FFF}]{1,63}$/iu', - 57 => '/^[\x{3040}-\x{309F}]{1,63}$/iu', - 58 => '/^[\x{30A0}-\x{30FF}]{1,63}$/iu', - 59 => '/^[\x{3100}-\x{312F}]{1,63}$/iu', - 60 => '/^[\x{3130}-\x{318F}]{1,63}$/iu', - 61 => '/^[\x{3190}-\x{319F}]{1,63}$/iu', - 62 => '/^[\x{31A0}-\x{31BF}]{1,63}$/iu', - 63 => '/^[\x{31F0}-\x{31FF}]{1,63}$/iu', - 64 => '/^[\x{3200}-\x{32FF}]{1,63}$/iu', - 65 => '/^[\x{3300}-\x{33FF}]{1,63}$/iu', - 66 => '/^[\x{3400}-\x{4DBF}]{1,63}$/iu', - 67 => '/^[\x{4E00}-\x{9FFF}]{1,63}$/iu', - 68 => '/^[\x{A000}-\x{A48F}]{1,63}$/iu', - 69 => '/^[\x{A490}-\x{A4CF}]{1,63}$/iu', - 70 => '/^[\x{AC00}-\x{D7AF}]{1,63}$/iu', - 73 => '/^[\x{F900}-\x{FAFF}]{1,63}$/iu', - 74 => '/^[\x{FB00}-\x{FB4F}]{1,63}$/iu', - 75 => '/^[\x{FB50}-\x{FDFF}]{1,63}$/iu', - 76 => '/^[\x{FE20}-\x{FE2F}]{1,63}$/iu', - 77 => '/^[\x{FE70}-\x{FEFF}]{1,63}$/iu', - 78 => '/^[\x{FF00}-\x{FFEF}]{1,63}$/iu', - 79 => '/^[\x{20000}-\x{2A6DF}]{1,63}$/iu', - 80 => '/^[\x{2F800}-\x{2FA1F}]{1,63}$/iu', -]; diff --git a/lib/laminas/laminas-validator/src/Hostname/Jp.php b/lib/laminas/laminas-validator/src/Hostname/Jp.php deleted file mode 100644 index 8520f6a1d..000000000 --- a/lib/laminas/laminas-validator/src/Hostname/Jp.php +++ /dev/null @@ -1,719 +0,0 @@ -<?php // phpcs:disable PSR12.Files.FileHeader.IncorrectOrder - -namespace Laminas\Validator\Hostname; - -/** - * Resource file for japanese idn validation - */ - -return [ - 1 => '/^[\x{002d}0-9a-z\x{3005}-\x{3007}\x{3041}-\x{3093}\x{309D}\x{309E}' - . '\x{30A1}-\x{30F6}\x{30FC}' - . '\x{30FD}\x{30FE}\x{4E00}\x{4E01}\x{4E03}\x{4E07}\x{4E08}\x{4E09}\x{4E0A}' - . '\x{4E0B}\x{4E0D}\x{4E0E}\x{4E10}\x{4E11}\x{4E14}\x{4E15}\x{4E16}\x{4E17}' - . '\x{4E18}\x{4E19}\x{4E1E}\x{4E21}\x{4E26}\x{4E2A}\x{4E2D}\x{4E31}\x{4E32}' - . '\x{4E36}\x{4E38}\x{4E39}\x{4E3B}\x{4E3C}\x{4E3F}\x{4E42}\x{4E43}\x{4E45}' - . '\x{4E4B}\x{4E4D}\x{4E4E}\x{4E4F}\x{4E55}\x{4E56}\x{4E57}\x{4E58}\x{4E59}' - . '\x{4E5D}\x{4E5E}\x{4E5F}\x{4E62}\x{4E71}\x{4E73}\x{4E7E}\x{4E80}\x{4E82}' - . '\x{4E85}\x{4E86}\x{4E88}\x{4E89}\x{4E8A}\x{4E8B}\x{4E8C}\x{4E8E}\x{4E91}' - . '\x{4E92}\x{4E94}\x{4E95}\x{4E98}\x{4E99}\x{4E9B}\x{4E9C}\x{4E9E}\x{4E9F}' - . '\x{4EA0}\x{4EA1}\x{4EA2}\x{4EA4}\x{4EA5}\x{4EA6}\x{4EA8}\x{4EAB}\x{4EAC}' - . '\x{4EAD}\x{4EAE}\x{4EB0}\x{4EB3}\x{4EB6}\x{4EBA}\x{4EC0}\x{4EC1}\x{4EC2}' - . '\x{4EC4}\x{4EC6}\x{4EC7}\x{4ECA}\x{4ECB}\x{4ECD}\x{4ECE}\x{4ECF}\x{4ED4}' - . '\x{4ED5}\x{4ED6}\x{4ED7}\x{4ED8}\x{4ED9}\x{4EDD}\x{4EDE}\x{4EDF}\x{4EE3}' - . '\x{4EE4}\x{4EE5}\x{4EED}\x{4EEE}\x{4EF0}\x{4EF2}\x{4EF6}\x{4EF7}\x{4EFB}' - . '\x{4F01}\x{4F09}\x{4F0A}\x{4F0D}\x{4F0E}\x{4F0F}\x{4F10}\x{4F11}\x{4F1A}' - . '\x{4F1C}\x{4F1D}\x{4F2F}\x{4F30}\x{4F34}\x{4F36}\x{4F38}\x{4F3A}\x{4F3C}' - . '\x{4F3D}\x{4F43}\x{4F46}\x{4F47}\x{4F4D}\x{4F4E}\x{4F4F}\x{4F50}\x{4F51}' - . '\x{4F53}\x{4F55}\x{4F57}\x{4F59}\x{4F5A}\x{4F5B}\x{4F5C}\x{4F5D}\x{4F5E}' - . '\x{4F69}\x{4F6F}\x{4F70}\x{4F73}\x{4F75}\x{4F76}\x{4F7B}\x{4F7C}\x{4F7F}' - . '\x{4F83}\x{4F86}\x{4F88}\x{4F8B}\x{4F8D}\x{4F8F}\x{4F91}\x{4F96}\x{4F98}' - . '\x{4F9B}\x{4F9D}\x{4FA0}\x{4FA1}\x{4FAB}\x{4FAD}\x{4FAE}\x{4FAF}\x{4FB5}' - . '\x{4FB6}\x{4FBF}\x{4FC2}\x{4FC3}\x{4FC4}\x{4FCA}\x{4FCE}\x{4FD0}\x{4FD1}' - . '\x{4FD4}\x{4FD7}\x{4FD8}\x{4FDA}\x{4FDB}\x{4FDD}\x{4FDF}\x{4FE1}\x{4FE3}' - . '\x{4FE4}\x{4FE5}\x{4FEE}\x{4FEF}\x{4FF3}\x{4FF5}\x{4FF6}\x{4FF8}\x{4FFA}' - . '\x{4FFE}\x{5005}\x{5006}\x{5009}\x{500B}\x{500D}\x{500F}\x{5011}\x{5012}' - . '\x{5014}\x{5016}\x{5019}\x{501A}\x{501F}\x{5021}\x{5023}\x{5024}\x{5025}' - . '\x{5026}\x{5028}\x{5029}\x{502A}\x{502B}\x{502C}\x{502D}\x{5036}\x{5039}' - . '\x{5043}\x{5047}\x{5048}\x{5049}\x{504F}\x{5050}\x{5055}\x{5056}\x{505A}' - . '\x{505C}\x{5065}\x{506C}\x{5072}\x{5074}\x{5075}\x{5076}\x{5078}\x{507D}' - . '\x{5080}\x{5085}\x{508D}\x{5091}\x{5098}\x{5099}\x{509A}\x{50AC}\x{50AD}' - . '\x{50B2}\x{50B3}\x{50B4}\x{50B5}\x{50B7}\x{50BE}\x{50C2}\x{50C5}\x{50C9}' - . '\x{50CA}\x{50CD}\x{50CF}\x{50D1}\x{50D5}\x{50D6}\x{50DA}\x{50DE}\x{50E3}' - . '\x{50E5}\x{50E7}\x{50ED}\x{50EE}\x{50F5}\x{50F9}\x{50FB}\x{5100}\x{5101}' - . '\x{5102}\x{5104}\x{5109}\x{5112}\x{5114}\x{5115}\x{5116}\x{5118}\x{511A}' - . '\x{511F}\x{5121}\x{512A}\x{5132}\x{5137}\x{513A}\x{513B}\x{513C}\x{513F}' - . '\x{5140}\x{5141}\x{5143}\x{5144}\x{5145}\x{5146}\x{5147}\x{5148}\x{5149}' - . '\x{514B}\x{514C}\x{514D}\x{514E}\x{5150}\x{5152}\x{5154}\x{515A}\x{515C}' - . '\x{5162}\x{5165}\x{5168}\x{5169}\x{516A}\x{516B}\x{516C}\x{516D}\x{516E}' - . '\x{5171}\x{5175}\x{5176}\x{5177}\x{5178}\x{517C}\x{5180}\x{5182}\x{5185}' - . '\x{5186}\x{5189}\x{518A}\x{518C}\x{518D}\x{518F}\x{5190}\x{5191}\x{5192}' - . '\x{5193}\x{5195}\x{5196}\x{5197}\x{5199}\x{51A0}\x{51A2}\x{51A4}\x{51A5}' - . '\x{51A6}\x{51A8}\x{51A9}\x{51AA}\x{51AB}\x{51AC}\x{51B0}\x{51B1}\x{51B2}' - . '\x{51B3}\x{51B4}\x{51B5}\x{51B6}\x{51B7}\x{51BD}\x{51C4}\x{51C5}\x{51C6}' - . '\x{51C9}\x{51CB}\x{51CC}\x{51CD}\x{51D6}\x{51DB}\x{51DC}\x{51DD}\x{51E0}' - . '\x{51E1}\x{51E6}\x{51E7}\x{51E9}\x{51EA}\x{51ED}\x{51F0}\x{51F1}\x{51F5}' - . '\x{51F6}\x{51F8}\x{51F9}\x{51FA}\x{51FD}\x{51FE}\x{5200}\x{5203}\x{5204}' - . '\x{5206}\x{5207}\x{5208}\x{520A}\x{520B}\x{520E}\x{5211}\x{5214}\x{5217}' - . '\x{521D}\x{5224}\x{5225}\x{5227}\x{5229}\x{522A}\x{522E}\x{5230}\x{5233}' - . '\x{5236}\x{5237}\x{5238}\x{5239}\x{523A}\x{523B}\x{5243}\x{5244}\x{5247}' - . '\x{524A}\x{524B}\x{524C}\x{524D}\x{524F}\x{5254}\x{5256}\x{525B}\x{525E}' - . '\x{5263}\x{5264}\x{5265}\x{5269}\x{526A}\x{526F}\x{5270}\x{5271}\x{5272}' - . '\x{5273}\x{5274}\x{5275}\x{527D}\x{527F}\x{5283}\x{5287}\x{5288}\x{5289}' - . '\x{528D}\x{5291}\x{5292}\x{5294}\x{529B}\x{529F}\x{52A0}\x{52A3}\x{52A9}' - . '\x{52AA}\x{52AB}\x{52AC}\x{52AD}\x{52B1}\x{52B4}\x{52B5}\x{52B9}\x{52BC}' - . '\x{52BE}\x{52C1}\x{52C3}\x{52C5}\x{52C7}\x{52C9}\x{52CD}\x{52D2}\x{52D5}' - . '\x{52D7}\x{52D8}\x{52D9}\x{52DD}\x{52DE}\x{52DF}\x{52E0}\x{52E2}\x{52E3}' - . '\x{52E4}\x{52E6}\x{52E7}\x{52F2}\x{52F3}\x{52F5}\x{52F8}\x{52F9}\x{52FA}' - . '\x{52FE}\x{52FF}\x{5301}\x{5302}\x{5305}\x{5306}\x{5308}\x{530D}\x{530F}' - . '\x{5310}\x{5315}\x{5316}\x{5317}\x{5319}\x{531A}\x{531D}\x{5320}\x{5321}' - . '\x{5323}\x{532A}\x{532F}\x{5331}\x{5333}\x{5338}\x{5339}\x{533A}\x{533B}' - . '\x{533F}\x{5340}\x{5341}\x{5343}\x{5345}\x{5346}\x{5347}\x{5348}\x{5349}' - . '\x{534A}\x{534D}\x{5351}\x{5352}\x{5353}\x{5354}\x{5357}\x{5358}\x{535A}' - . '\x{535C}\x{535E}\x{5360}\x{5366}\x{5369}\x{536E}\x{536F}\x{5370}\x{5371}' - . '\x{5373}\x{5374}\x{5375}\x{5377}\x{5378}\x{537B}\x{537F}\x{5382}\x{5384}' - . '\x{5396}\x{5398}\x{539A}\x{539F}\x{53A0}\x{53A5}\x{53A6}\x{53A8}\x{53A9}' - . '\x{53AD}\x{53AE}\x{53B0}\x{53B3}\x{53B6}\x{53BB}\x{53C2}\x{53C3}\x{53C8}' - . '\x{53C9}\x{53CA}\x{53CB}\x{53CC}\x{53CD}\x{53CE}\x{53D4}\x{53D6}\x{53D7}' - . '\x{53D9}\x{53DB}\x{53DF}\x{53E1}\x{53E2}\x{53E3}\x{53E4}\x{53E5}\x{53E8}' - . '\x{53E9}\x{53EA}\x{53EB}\x{53EC}\x{53ED}\x{53EE}\x{53EF}\x{53F0}\x{53F1}' - . '\x{53F2}\x{53F3}\x{53F6}\x{53F7}\x{53F8}\x{53FA}\x{5401}\x{5403}\x{5404}' - . '\x{5408}\x{5409}\x{540A}\x{540B}\x{540C}\x{540D}\x{540E}\x{540F}\x{5410}' - . '\x{5411}\x{541B}\x{541D}\x{541F}\x{5420}\x{5426}\x{5429}\x{542B}\x{542C}' - . '\x{542D}\x{542E}\x{5436}\x{5438}\x{5439}\x{543B}\x{543C}\x{543D}\x{543E}' - . '\x{5440}\x{5442}\x{5446}\x{5448}\x{5449}\x{544A}\x{544E}\x{5451}\x{545F}' - . '\x{5468}\x{546A}\x{5470}\x{5471}\x{5473}\x{5475}\x{5476}\x{5477}\x{547B}' - . '\x{547C}\x{547D}\x{5480}\x{5484}\x{5486}\x{548B}\x{548C}\x{548E}\x{548F}' - . '\x{5490}\x{5492}\x{54A2}\x{54A4}\x{54A5}\x{54A8}\x{54AB}\x{54AC}\x{54AF}' - . '\x{54B2}\x{54B3}\x{54B8}\x{54BC}\x{54BD}\x{54BE}\x{54C0}\x{54C1}\x{54C2}' - . '\x{54C4}\x{54C7}\x{54C8}\x{54C9}\x{54D8}\x{54E1}\x{54E2}\x{54E5}\x{54E6}' - . '\x{54E8}\x{54E9}\x{54ED}\x{54EE}\x{54F2}\x{54FA}\x{54FD}\x{5504}\x{5506}' - . '\x{5507}\x{550F}\x{5510}\x{5514}\x{5516}\x{552E}\x{552F}\x{5531}\x{5533}' - . '\x{5538}\x{5539}\x{553E}\x{5540}\x{5544}\x{5545}\x{5546}\x{554C}\x{554F}' - . '\x{5553}\x{5556}\x{5557}\x{555C}\x{555D}\x{5563}\x{557B}\x{557C}\x{557E}' - . '\x{5580}\x{5583}\x{5584}\x{5587}\x{5589}\x{558A}\x{558B}\x{5598}\x{5599}' - . '\x{559A}\x{559C}\x{559D}\x{559E}\x{559F}\x{55A7}\x{55A8}\x{55A9}\x{55AA}' - . '\x{55AB}\x{55AC}\x{55AE}\x{55B0}\x{55B6}\x{55C4}\x{55C5}\x{55C7}\x{55D4}' - . '\x{55DA}\x{55DC}\x{55DF}\x{55E3}\x{55E4}\x{55F7}\x{55F9}\x{55FD}\x{55FE}' - . '\x{5606}\x{5609}\x{5614}\x{5616}\x{5617}\x{5618}\x{561B}\x{5629}\x{562F}' - . '\x{5631}\x{5632}\x{5634}\x{5636}\x{5638}\x{5642}\x{564C}\x{564E}\x{5650}' - . '\x{565B}\x{5664}\x{5668}\x{566A}\x{566B}\x{566C}\x{5674}\x{5678}\x{567A}' - . '\x{5680}\x{5686}\x{5687}\x{568A}\x{568F}\x{5694}\x{56A0}\x{56A2}\x{56A5}' - . '\x{56AE}\x{56B4}\x{56B6}\x{56BC}\x{56C0}\x{56C1}\x{56C2}\x{56C3}\x{56C8}' - . '\x{56CE}\x{56D1}\x{56D3}\x{56D7}\x{56D8}\x{56DA}\x{56DB}\x{56DE}\x{56E0}' - . '\x{56E3}\x{56EE}\x{56F0}\x{56F2}\x{56F3}\x{56F9}\x{56FA}\x{56FD}\x{56FF}' - . '\x{5700}\x{5703}\x{5704}\x{5708}\x{5709}\x{570B}\x{570D}\x{570F}\x{5712}' - . '\x{5713}\x{5716}\x{5718}\x{571C}\x{571F}\x{5726}\x{5727}\x{5728}\x{572D}' - . '\x{5730}\x{5737}\x{5738}\x{573B}\x{5740}\x{5742}\x{5747}\x{574A}\x{574E}' - . '\x{574F}\x{5750}\x{5751}\x{5761}\x{5764}\x{5766}\x{5769}\x{576A}\x{577F}' - . '\x{5782}\x{5788}\x{5789}\x{578B}\x{5793}\x{57A0}\x{57A2}\x{57A3}\x{57A4}' - . '\x{57AA}\x{57B0}\x{57B3}\x{57C0}\x{57C3}\x{57C6}\x{57CB}\x{57CE}\x{57D2}' - . '\x{57D3}\x{57D4}\x{57D6}\x{57DC}\x{57DF}\x{57E0}\x{57E3}\x{57F4}\x{57F7}' - . '\x{57F9}\x{57FA}\x{57FC}\x{5800}\x{5802}\x{5805}\x{5806}\x{580A}\x{580B}' - . '\x{5815}\x{5819}\x{581D}\x{5821}\x{5824}\x{582A}\x{582F}\x{5830}\x{5831}' - . '\x{5834}\x{5835}\x{583A}\x{583D}\x{5840}\x{5841}\x{584A}\x{584B}\x{5851}' - . '\x{5852}\x{5854}\x{5857}\x{5858}\x{5859}\x{585A}\x{585E}\x{5862}\x{5869}' - . '\x{586B}\x{5870}\x{5872}\x{5875}\x{5879}\x{587E}\x{5883}\x{5885}\x{5893}' - . '\x{5897}\x{589C}\x{589F}\x{58A8}\x{58AB}\x{58AE}\x{58B3}\x{58B8}\x{58B9}' - . '\x{58BA}\x{58BB}\x{58BE}\x{58C1}\x{58C5}\x{58C7}\x{58CA}\x{58CC}\x{58D1}' - . '\x{58D3}\x{58D5}\x{58D7}\x{58D8}\x{58D9}\x{58DC}\x{58DE}\x{58DF}\x{58E4}' - . '\x{58E5}\x{58EB}\x{58EC}\x{58EE}\x{58EF}\x{58F0}\x{58F1}\x{58F2}\x{58F7}' - . '\x{58F9}\x{58FA}\x{58FB}\x{58FC}\x{58FD}\x{5902}\x{5909}\x{590A}\x{590F}' - . '\x{5910}\x{5915}\x{5916}\x{5918}\x{5919}\x{591A}\x{591B}\x{591C}\x{5922}' - . '\x{5925}\x{5927}\x{5929}\x{592A}\x{592B}\x{592C}\x{592D}\x{592E}\x{5931}' - . '\x{5932}\x{5937}\x{5938}\x{593E}\x{5944}\x{5947}\x{5948}\x{5949}\x{594E}' - . '\x{594F}\x{5950}\x{5951}\x{5954}\x{5955}\x{5957}\x{5958}\x{595A}\x{5960}' - . '\x{5962}\x{5965}\x{5967}\x{5968}\x{5969}\x{596A}\x{596C}\x{596E}\x{5973}' - . '\x{5974}\x{5978}\x{597D}\x{5981}\x{5982}\x{5983}\x{5984}\x{598A}\x{598D}' - . '\x{5993}\x{5996}\x{5999}\x{599B}\x{599D}\x{59A3}\x{59A5}\x{59A8}\x{59AC}' - . '\x{59B2}\x{59B9}\x{59BB}\x{59BE}\x{59C6}\x{59C9}\x{59CB}\x{59D0}\x{59D1}' - . '\x{59D3}\x{59D4}\x{59D9}\x{59DA}\x{59DC}\x{59E5}\x{59E6}\x{59E8}\x{59EA}' - . '\x{59EB}\x{59F6}\x{59FB}\x{59FF}\x{5A01}\x{5A03}\x{5A09}\x{5A11}\x{5A18}' - . '\x{5A1A}\x{5A1C}\x{5A1F}\x{5A20}\x{5A25}\x{5A29}\x{5A2F}\x{5A35}\x{5A36}' - . '\x{5A3C}\x{5A40}\x{5A41}\x{5A46}\x{5A49}\x{5A5A}\x{5A62}\x{5A66}\x{5A6A}' - . '\x{5A6C}\x{5A7F}\x{5A92}\x{5A9A}\x{5A9B}\x{5ABC}\x{5ABD}\x{5ABE}\x{5AC1}' - . '\x{5AC2}\x{5AC9}\x{5ACB}\x{5ACC}\x{5AD0}\x{5AD6}\x{5AD7}\x{5AE1}\x{5AE3}' - . '\x{5AE6}\x{5AE9}\x{5AFA}\x{5AFB}\x{5B09}\x{5B0B}\x{5B0C}\x{5B16}\x{5B22}' - . '\x{5B2A}\x{5B2C}\x{5B30}\x{5B32}\x{5B36}\x{5B3E}\x{5B40}\x{5B43}\x{5B45}' - . '\x{5B50}\x{5B51}\x{5B54}\x{5B55}\x{5B57}\x{5B58}\x{5B5A}\x{5B5B}\x{5B5C}' - . '\x{5B5D}\x{5B5F}\x{5B63}\x{5B64}\x{5B65}\x{5B66}\x{5B69}\x{5B6B}\x{5B70}' - . '\x{5B71}\x{5B73}\x{5B75}\x{5B78}\x{5B7A}\x{5B80}\x{5B83}\x{5B85}\x{5B87}' - . '\x{5B88}\x{5B89}\x{5B8B}\x{5B8C}\x{5B8D}\x{5B8F}\x{5B95}\x{5B97}\x{5B98}' - . '\x{5B99}\x{5B9A}\x{5B9B}\x{5B9C}\x{5B9D}\x{5B9F}\x{5BA2}\x{5BA3}\x{5BA4}' - . '\x{5BA5}\x{5BA6}\x{5BAE}\x{5BB0}\x{5BB3}\x{5BB4}\x{5BB5}\x{5BB6}\x{5BB8}' - . '\x{5BB9}\x{5BBF}\x{5BC2}\x{5BC3}\x{5BC4}\x{5BC5}\x{5BC6}\x{5BC7}\x{5BC9}' - . '\x{5BCC}\x{5BD0}\x{5BD2}\x{5BD3}\x{5BD4}\x{5BDB}\x{5BDD}\x{5BDE}\x{5BDF}' - . '\x{5BE1}\x{5BE2}\x{5BE4}\x{5BE5}\x{5BE6}\x{5BE7}\x{5BE8}\x{5BE9}\x{5BEB}' - . '\x{5BEE}\x{5BF0}\x{5BF3}\x{5BF5}\x{5BF6}\x{5BF8}\x{5BFA}\x{5BFE}\x{5BFF}' - . '\x{5C01}\x{5C02}\x{5C04}\x{5C05}\x{5C06}\x{5C07}\x{5C08}\x{5C09}\x{5C0A}' - . '\x{5C0B}\x{5C0D}\x{5C0E}\x{5C0F}\x{5C11}\x{5C13}\x{5C16}\x{5C1A}\x{5C20}' - . '\x{5C22}\x{5C24}\x{5C28}\x{5C2D}\x{5C31}\x{5C38}\x{5C39}\x{5C3A}\x{5C3B}' - . '\x{5C3C}\x{5C3D}\x{5C3E}\x{5C3F}\x{5C40}\x{5C41}\x{5C45}\x{5C46}\x{5C48}' - . '\x{5C4A}\x{5C4B}\x{5C4D}\x{5C4E}\x{5C4F}\x{5C50}\x{5C51}\x{5C53}\x{5C55}' - . '\x{5C5E}\x{5C60}\x{5C61}\x{5C64}\x{5C65}\x{5C6C}\x{5C6E}\x{5C6F}\x{5C71}' - . '\x{5C76}\x{5C79}\x{5C8C}\x{5C90}\x{5C91}\x{5C94}\x{5CA1}\x{5CA8}\x{5CA9}' - . '\x{5CAB}\x{5CAC}\x{5CB1}\x{5CB3}\x{5CB6}\x{5CB7}\x{5CB8}\x{5CBB}\x{5CBC}' - . '\x{5CBE}\x{5CC5}\x{5CC7}\x{5CD9}\x{5CE0}\x{5CE1}\x{5CE8}\x{5CE9}\x{5CEA}' - . '\x{5CED}\x{5CEF}\x{5CF0}\x{5CF6}\x{5CFA}\x{5CFB}\x{5CFD}\x{5D07}\x{5D0B}' - . '\x{5D0E}\x{5D11}\x{5D14}\x{5D15}\x{5D16}\x{5D17}\x{5D18}\x{5D19}\x{5D1A}' - . '\x{5D1B}\x{5D1F}\x{5D22}\x{5D29}\x{5D4B}\x{5D4C}\x{5D4E}\x{5D50}\x{5D52}' - . '\x{5D5C}\x{5D69}\x{5D6C}\x{5D6F}\x{5D73}\x{5D76}\x{5D82}\x{5D84}\x{5D87}' - . '\x{5D8B}\x{5D8C}\x{5D90}\x{5D9D}\x{5DA2}\x{5DAC}\x{5DAE}\x{5DB7}\x{5DBA}' - . '\x{5DBC}\x{5DBD}\x{5DC9}\x{5DCC}\x{5DCD}\x{5DD2}\x{5DD3}\x{5DD6}\x{5DDB}' - . '\x{5DDD}\x{5DDE}\x{5DE1}\x{5DE3}\x{5DE5}\x{5DE6}\x{5DE7}\x{5DE8}\x{5DEB}' - . '\x{5DEE}\x{5DF1}\x{5DF2}\x{5DF3}\x{5DF4}\x{5DF5}\x{5DF7}\x{5DFB}\x{5DFD}' - . '\x{5DFE}\x{5E02}\x{5E03}\x{5E06}\x{5E0B}\x{5E0C}\x{5E11}\x{5E16}\x{5E19}' - . '\x{5E1A}\x{5E1B}\x{5E1D}\x{5E25}\x{5E2B}\x{5E2D}\x{5E2F}\x{5E30}\x{5E33}' - . '\x{5E36}\x{5E37}\x{5E38}\x{5E3D}\x{5E40}\x{5E43}\x{5E44}\x{5E45}\x{5E47}' - . '\x{5E4C}\x{5E4E}\x{5E54}\x{5E55}\x{5E57}\x{5E5F}\x{5E61}\x{5E62}\x{5E63}' - . '\x{5E64}\x{5E72}\x{5E73}\x{5E74}\x{5E75}\x{5E76}\x{5E78}\x{5E79}\x{5E7A}' - . '\x{5E7B}\x{5E7C}\x{5E7D}\x{5E7E}\x{5E7F}\x{5E81}\x{5E83}\x{5E84}\x{5E87}' - . '\x{5E8A}\x{5E8F}\x{5E95}\x{5E96}\x{5E97}\x{5E9A}\x{5E9C}\x{5EA0}\x{5EA6}' - . '\x{5EA7}\x{5EAB}\x{5EAD}\x{5EB5}\x{5EB6}\x{5EB7}\x{5EB8}\x{5EC1}\x{5EC2}' - . '\x{5EC3}\x{5EC8}\x{5EC9}\x{5ECA}\x{5ECF}\x{5ED0}\x{5ED3}\x{5ED6}\x{5EDA}' - . '\x{5EDB}\x{5EDD}\x{5EDF}\x{5EE0}\x{5EE1}\x{5EE2}\x{5EE3}\x{5EE8}\x{5EE9}' - . '\x{5EEC}\x{5EF0}\x{5EF1}\x{5EF3}\x{5EF4}\x{5EF6}\x{5EF7}\x{5EF8}\x{5EFA}' - . '\x{5EFB}\x{5EFC}\x{5EFE}\x{5EFF}\x{5F01}\x{5F03}\x{5F04}\x{5F09}\x{5F0A}' - . '\x{5F0B}\x{5F0C}\x{5F0D}\x{5F0F}\x{5F10}\x{5F11}\x{5F13}\x{5F14}\x{5F15}' - . '\x{5F16}\x{5F17}\x{5F18}\x{5F1B}\x{5F1F}\x{5F25}\x{5F26}\x{5F27}\x{5F29}' - . '\x{5F2D}\x{5F2F}\x{5F31}\x{5F35}\x{5F37}\x{5F38}\x{5F3C}\x{5F3E}\x{5F41}' - . '\x{5F48}\x{5F4A}\x{5F4C}\x{5F4E}\x{5F51}\x{5F53}\x{5F56}\x{5F57}\x{5F59}' - . '\x{5F5C}\x{5F5D}\x{5F61}\x{5F62}\x{5F66}\x{5F69}\x{5F6A}\x{5F6B}\x{5F6C}' - . '\x{5F6D}\x{5F70}\x{5F71}\x{5F73}\x{5F77}\x{5F79}\x{5F7C}\x{5F7F}\x{5F80}' - . '\x{5F81}\x{5F82}\x{5F83}\x{5F84}\x{5F85}\x{5F87}\x{5F88}\x{5F8A}\x{5F8B}' - . '\x{5F8C}\x{5F90}\x{5F91}\x{5F92}\x{5F93}\x{5F97}\x{5F98}\x{5F99}\x{5F9E}' - . '\x{5FA0}\x{5FA1}\x{5FA8}\x{5FA9}\x{5FAA}\x{5FAD}\x{5FAE}\x{5FB3}\x{5FB4}' - . '\x{5FB9}\x{5FBC}\x{5FBD}\x{5FC3}\x{5FC5}\x{5FCC}\x{5FCD}\x{5FD6}\x{5FD7}' - . '\x{5FD8}\x{5FD9}\x{5FDC}\x{5FDD}\x{5FE0}\x{5FE4}\x{5FEB}\x{5FF0}\x{5FF1}' - . '\x{5FF5}\x{5FF8}\x{5FFB}\x{5FFD}\x{5FFF}\x{600E}\x{600F}\x{6010}\x{6012}' - . '\x{6015}\x{6016}\x{6019}\x{601B}\x{601C}\x{601D}\x{6020}\x{6021}\x{6025}' - . '\x{6026}\x{6027}\x{6028}\x{6029}\x{602A}\x{602B}\x{602F}\x{6031}\x{603A}' - . '\x{6041}\x{6042}\x{6043}\x{6046}\x{604A}\x{604B}\x{604D}\x{6050}\x{6052}' - . '\x{6055}\x{6059}\x{605A}\x{605F}\x{6060}\x{6062}\x{6063}\x{6064}\x{6065}' - . '\x{6068}\x{6069}\x{606A}\x{606B}\x{606C}\x{606D}\x{606F}\x{6070}\x{6075}' - . '\x{6077}\x{6081}\x{6083}\x{6084}\x{6089}\x{608B}\x{608C}\x{608D}\x{6092}' - . '\x{6094}\x{6096}\x{6097}\x{609A}\x{609B}\x{609F}\x{60A0}\x{60A3}\x{60A6}' - . '\x{60A7}\x{60A9}\x{60AA}\x{60B2}\x{60B3}\x{60B4}\x{60B5}\x{60B6}\x{60B8}' - . '\x{60BC}\x{60BD}\x{60C5}\x{60C6}\x{60C7}\x{60D1}\x{60D3}\x{60D8}\x{60DA}' - . '\x{60DC}\x{60DF}\x{60E0}\x{60E1}\x{60E3}\x{60E7}\x{60E8}\x{60F0}\x{60F1}' - . '\x{60F3}\x{60F4}\x{60F6}\x{60F7}\x{60F9}\x{60FA}\x{60FB}\x{6100}\x{6101}' - . '\x{6103}\x{6106}\x{6108}\x{6109}\x{610D}\x{610E}\x{610F}\x{6115}\x{611A}' - . '\x{611B}\x{611F}\x{6121}\x{6127}\x{6128}\x{612C}\x{6134}\x{613C}\x{613D}' - . '\x{613E}\x{613F}\x{6142}\x{6144}\x{6147}\x{6148}\x{614A}\x{614B}\x{614C}' - . '\x{614D}\x{614E}\x{6153}\x{6155}\x{6158}\x{6159}\x{615A}\x{615D}\x{615F}' - . '\x{6162}\x{6163}\x{6165}\x{6167}\x{6168}\x{616B}\x{616E}\x{616F}\x{6170}' - . '\x{6171}\x{6173}\x{6174}\x{6175}\x{6176}\x{6177}\x{617E}\x{6182}\x{6187}' - . '\x{618A}\x{618E}\x{6190}\x{6191}\x{6194}\x{6196}\x{6199}\x{619A}\x{61A4}' - . '\x{61A7}\x{61A9}\x{61AB}\x{61AC}\x{61AE}\x{61B2}\x{61B6}\x{61BA}\x{61BE}' - . '\x{61C3}\x{61C6}\x{61C7}\x{61C8}\x{61C9}\x{61CA}\x{61CB}\x{61CC}\x{61CD}' - . '\x{61D0}\x{61E3}\x{61E6}\x{61F2}\x{61F4}\x{61F6}\x{61F7}\x{61F8}\x{61FA}' - . '\x{61FC}\x{61FD}\x{61FE}\x{61FF}\x{6200}\x{6208}\x{6209}\x{620A}\x{620C}' - . '\x{620D}\x{620E}\x{6210}\x{6211}\x{6212}\x{6214}\x{6216}\x{621A}\x{621B}' - . '\x{621D}\x{621E}\x{621F}\x{6221}\x{6226}\x{622A}\x{622E}\x{622F}\x{6230}' - . '\x{6232}\x{6233}\x{6234}\x{6238}\x{623B}\x{623F}\x{6240}\x{6241}\x{6247}' - . '\x{6248}\x{6249}\x{624B}\x{624D}\x{624E}\x{6253}\x{6255}\x{6258}\x{625B}' - . '\x{625E}\x{6260}\x{6263}\x{6268}\x{626E}\x{6271}\x{6276}\x{6279}\x{627C}' - . '\x{627E}\x{627F}\x{6280}\x{6282}\x{6283}\x{6284}\x{6289}\x{628A}\x{6291}' - . '\x{6292}\x{6293}\x{6294}\x{6295}\x{6296}\x{6297}\x{6298}\x{629B}\x{629C}' - . '\x{629E}\x{62AB}\x{62AC}\x{62B1}\x{62B5}\x{62B9}\x{62BB}\x{62BC}\x{62BD}' - . '\x{62C2}\x{62C5}\x{62C6}\x{62C7}\x{62C8}\x{62C9}\x{62CA}\x{62CC}\x{62CD}' - . '\x{62CF}\x{62D0}\x{62D1}\x{62D2}\x{62D3}\x{62D4}\x{62D7}\x{62D8}\x{62D9}' - . '\x{62DB}\x{62DC}\x{62DD}\x{62E0}\x{62E1}\x{62EC}\x{62ED}\x{62EE}\x{62EF}' - . '\x{62F1}\x{62F3}\x{62F5}\x{62F6}\x{62F7}\x{62FE}\x{62FF}\x{6301}\x{6302}' - . '\x{6307}\x{6308}\x{6309}\x{630C}\x{6311}\x{6319}\x{631F}\x{6327}\x{6328}' - . '\x{632B}\x{632F}\x{633A}\x{633D}\x{633E}\x{633F}\x{6349}\x{634C}\x{634D}' - . '\x{634F}\x{6350}\x{6355}\x{6357}\x{635C}\x{6367}\x{6368}\x{6369}\x{636B}' - . '\x{636E}\x{6372}\x{6376}\x{6377}\x{637A}\x{637B}\x{6380}\x{6383}\x{6388}' - . '\x{6389}\x{638C}\x{638E}\x{638F}\x{6392}\x{6396}\x{6398}\x{639B}\x{639F}' - . '\x{63A0}\x{63A1}\x{63A2}\x{63A3}\x{63A5}\x{63A7}\x{63A8}\x{63A9}\x{63AA}' - . '\x{63AB}\x{63AC}\x{63B2}\x{63B4}\x{63B5}\x{63BB}\x{63BE}\x{63C0}\x{63C3}' - . '\x{63C4}\x{63C6}\x{63C9}\x{63CF}\x{63D0}\x{63D2}\x{63D6}\x{63DA}\x{63DB}' - . '\x{63E1}\x{63E3}\x{63E9}\x{63EE}\x{63F4}\x{63F6}\x{63FA}\x{6406}\x{640D}' - . '\x{640F}\x{6413}\x{6416}\x{6417}\x{641C}\x{6426}\x{6428}\x{642C}\x{642D}' - . '\x{6434}\x{6436}\x{643A}\x{643E}\x{6442}\x{644E}\x{6458}\x{6467}\x{6469}' - . '\x{646F}\x{6476}\x{6478}\x{647A}\x{6483}\x{6488}\x{6492}\x{6493}\x{6495}' - . '\x{649A}\x{649E}\x{64A4}\x{64A5}\x{64A9}\x{64AB}\x{64AD}\x{64AE}\x{64B0}' - . '\x{64B2}\x{64B9}\x{64BB}\x{64BC}\x{64C1}\x{64C2}\x{64C5}\x{64C7}\x{64CD}' - . '\x{64D2}\x{64D4}\x{64D8}\x{64DA}\x{64E0}\x{64E1}\x{64E2}\x{64E3}\x{64E6}' - . '\x{64E7}\x{64EC}\x{64EF}\x{64F1}\x{64F2}\x{64F4}\x{64F6}\x{64FA}\x{64FD}' - . '\x{64FE}\x{6500}\x{6505}\x{6518}\x{651C}\x{651D}\x{6523}\x{6524}\x{652A}' - . '\x{652B}\x{652C}\x{652F}\x{6534}\x{6535}\x{6536}\x{6537}\x{6538}\x{6539}' - . '\x{653B}\x{653E}\x{653F}\x{6545}\x{6548}\x{654D}\x{654F}\x{6551}\x{6555}' - . '\x{6556}\x{6557}\x{6558}\x{6559}\x{655D}\x{655E}\x{6562}\x{6563}\x{6566}' - . '\x{656C}\x{6570}\x{6572}\x{6574}\x{6575}\x{6577}\x{6578}\x{6582}\x{6583}' - . '\x{6587}\x{6588}\x{6589}\x{658C}\x{658E}\x{6590}\x{6591}\x{6597}\x{6599}' - . '\x{659B}\x{659C}\x{659F}\x{65A1}\x{65A4}\x{65A5}\x{65A7}\x{65AB}\x{65AC}' - . '\x{65AD}\x{65AF}\x{65B0}\x{65B7}\x{65B9}\x{65BC}\x{65BD}\x{65C1}\x{65C3}' - . '\x{65C4}\x{65C5}\x{65C6}\x{65CB}\x{65CC}\x{65CF}\x{65D2}\x{65D7}\x{65D9}' - . '\x{65DB}\x{65E0}\x{65E1}\x{65E2}\x{65E5}\x{65E6}\x{65E7}\x{65E8}\x{65E9}' - . '\x{65EC}\x{65ED}\x{65F1}\x{65FA}\x{65FB}\x{6602}\x{6603}\x{6606}\x{6607}' - . '\x{660A}\x{660C}\x{660E}\x{660F}\x{6613}\x{6614}\x{661C}\x{661F}\x{6620}' - . '\x{6625}\x{6627}\x{6628}\x{662D}\x{662F}\x{6634}\x{6635}\x{6636}\x{663C}' - . '\x{663F}\x{6641}\x{6642}\x{6643}\x{6644}\x{6649}\x{664B}\x{664F}\x{6652}' - . '\x{665D}\x{665E}\x{665F}\x{6662}\x{6664}\x{6666}\x{6667}\x{6668}\x{6669}' - . '\x{666E}\x{666F}\x{6670}\x{6674}\x{6676}\x{667A}\x{6681}\x{6683}\x{6684}' - . '\x{6687}\x{6688}\x{6689}\x{668E}\x{6691}\x{6696}\x{6697}\x{6698}\x{669D}' - . '\x{66A2}\x{66A6}\x{66AB}\x{66AE}\x{66B4}\x{66B8}\x{66B9}\x{66BC}\x{66BE}' - . '\x{66C1}\x{66C4}\x{66C7}\x{66C9}\x{66D6}\x{66D9}\x{66DA}\x{66DC}\x{66DD}' - . '\x{66E0}\x{66E6}\x{66E9}\x{66F0}\x{66F2}\x{66F3}\x{66F4}\x{66F5}\x{66F7}' - . '\x{66F8}\x{66F9}\x{66FC}\x{66FD}\x{66FE}\x{66FF}\x{6700}\x{6703}\x{6708}' - . '\x{6709}\x{670B}\x{670D}\x{670F}\x{6714}\x{6715}\x{6716}\x{6717}\x{671B}' - . '\x{671D}\x{671E}\x{671F}\x{6726}\x{6727}\x{6728}\x{672A}\x{672B}\x{672C}' - . '\x{672D}\x{672E}\x{6731}\x{6734}\x{6736}\x{6737}\x{6738}\x{673A}\x{673D}' - . '\x{673F}\x{6741}\x{6746}\x{6749}\x{674E}\x{674F}\x{6750}\x{6751}\x{6753}' - . '\x{6756}\x{6759}\x{675C}\x{675E}\x{675F}\x{6760}\x{6761}\x{6762}\x{6763}' - . '\x{6764}\x{6765}\x{676A}\x{676D}\x{676F}\x{6770}\x{6771}\x{6772}\x{6773}' - . '\x{6775}\x{6777}\x{677C}\x{677E}\x{677F}\x{6785}\x{6787}\x{6789}\x{678B}' - . '\x{678C}\x{6790}\x{6795}\x{6797}\x{679A}\x{679C}\x{679D}\x{67A0}\x{67A1}' - . '\x{67A2}\x{67A6}\x{67A9}\x{67AF}\x{67B3}\x{67B4}\x{67B6}\x{67B7}\x{67B8}' - . '\x{67B9}\x{67C1}\x{67C4}\x{67C6}\x{67CA}\x{67CE}\x{67CF}\x{67D0}\x{67D1}' - . '\x{67D3}\x{67D4}\x{67D8}\x{67DA}\x{67DD}\x{67DE}\x{67E2}\x{67E4}\x{67E7}' - . '\x{67E9}\x{67EC}\x{67EE}\x{67EF}\x{67F1}\x{67F3}\x{67F4}\x{67F5}\x{67FB}' - . '\x{67FE}\x{67FF}\x{6802}\x{6803}\x{6804}\x{6813}\x{6816}\x{6817}\x{681E}' - . '\x{6821}\x{6822}\x{6829}\x{682A}\x{682B}\x{6832}\x{6834}\x{6838}\x{6839}' - . '\x{683C}\x{683D}\x{6840}\x{6841}\x{6842}\x{6843}\x{6846}\x{6848}\x{684D}' - . '\x{684E}\x{6850}\x{6851}\x{6853}\x{6854}\x{6859}\x{685C}\x{685D}\x{685F}' - . '\x{6863}\x{6867}\x{6874}\x{6876}\x{6877}\x{687E}\x{687F}\x{6881}\x{6883}' - . '\x{6885}\x{688D}\x{688F}\x{6893}\x{6894}\x{6897}\x{689B}\x{689D}\x{689F}' - . '\x{68A0}\x{68A2}\x{68A6}\x{68A7}\x{68A8}\x{68AD}\x{68AF}\x{68B0}\x{68B1}' - . '\x{68B3}\x{68B5}\x{68B6}\x{68B9}\x{68BA}\x{68BC}\x{68C4}\x{68C6}\x{68C9}' - . '\x{68CA}\x{68CB}\x{68CD}\x{68D2}\x{68D4}\x{68D5}\x{68D7}\x{68D8}\x{68DA}' - . '\x{68DF}\x{68E0}\x{68E1}\x{68E3}\x{68E7}\x{68EE}\x{68EF}\x{68F2}\x{68F9}' - . '\x{68FA}\x{6900}\x{6901}\x{6904}\x{6905}\x{6908}\x{690B}\x{690C}\x{690D}' - . '\x{690E}\x{690F}\x{6912}\x{6919}\x{691A}\x{691B}\x{691C}\x{6921}\x{6922}' - . '\x{6923}\x{6925}\x{6926}\x{6928}\x{692A}\x{6930}\x{6934}\x{6936}\x{6939}' - . '\x{693D}\x{693F}\x{694A}\x{6953}\x{6954}\x{6955}\x{6959}\x{695A}\x{695C}' - . '\x{695D}\x{695E}\x{6960}\x{6961}\x{6962}\x{696A}\x{696B}\x{696D}\x{696E}' - . '\x{696F}\x{6973}\x{6974}\x{6975}\x{6977}\x{6978}\x{6979}\x{697C}\x{697D}' - . '\x{697E}\x{6981}\x{6982}\x{698A}\x{698E}\x{6991}\x{6994}\x{6995}\x{699B}' - . '\x{699C}\x{69A0}\x{69A7}\x{69AE}\x{69B1}\x{69B2}\x{69B4}\x{69BB}\x{69BE}' - . '\x{69BF}\x{69C1}\x{69C3}\x{69C7}\x{69CA}\x{69CB}\x{69CC}\x{69CD}\x{69CE}' - . '\x{69D0}\x{69D3}\x{69D8}\x{69D9}\x{69DD}\x{69DE}\x{69E7}\x{69E8}\x{69EB}' - . '\x{69ED}\x{69F2}\x{69F9}\x{69FB}\x{69FD}\x{69FF}\x{6A02}\x{6A05}\x{6A0A}' - . '\x{6A0B}\x{6A0C}\x{6A12}\x{6A13}\x{6A14}\x{6A17}\x{6A19}\x{6A1B}\x{6A1E}' - . '\x{6A1F}\x{6A21}\x{6A22}\x{6A23}\x{6A29}\x{6A2A}\x{6A2B}\x{6A2E}\x{6A35}' - . '\x{6A36}\x{6A38}\x{6A39}\x{6A3A}\x{6A3D}\x{6A44}\x{6A47}\x{6A48}\x{6A4B}' - . '\x{6A58}\x{6A59}\x{6A5F}\x{6A61}\x{6A62}\x{6A66}\x{6A72}\x{6A78}\x{6A7F}' - . '\x{6A80}\x{6A84}\x{6A8D}\x{6A8E}\x{6A90}\x{6A97}\x{6A9C}\x{6AA0}\x{6AA2}' - . '\x{6AA3}\x{6AAA}\x{6AAC}\x{6AAE}\x{6AB3}\x{6AB8}\x{6ABB}\x{6AC1}\x{6AC2}' - . '\x{6AC3}\x{6AD1}\x{6AD3}\x{6ADA}\x{6ADB}\x{6ADE}\x{6ADF}\x{6AE8}\x{6AEA}' - . '\x{6AFA}\x{6AFB}\x{6B04}\x{6B05}\x{6B0A}\x{6B12}\x{6B16}\x{6B1D}\x{6B1F}' - . '\x{6B20}\x{6B21}\x{6B23}\x{6B27}\x{6B32}\x{6B37}\x{6B38}\x{6B39}\x{6B3A}' - . '\x{6B3D}\x{6B3E}\x{6B43}\x{6B47}\x{6B49}\x{6B4C}\x{6B4E}\x{6B50}\x{6B53}' - . '\x{6B54}\x{6B59}\x{6B5B}\x{6B5F}\x{6B61}\x{6B62}\x{6B63}\x{6B64}\x{6B66}' - . '\x{6B69}\x{6B6A}\x{6B6F}\x{6B73}\x{6B74}\x{6B78}\x{6B79}\x{6B7B}\x{6B7F}' - . '\x{6B80}\x{6B83}\x{6B84}\x{6B86}\x{6B89}\x{6B8A}\x{6B8B}\x{6B8D}\x{6B95}' - . '\x{6B96}\x{6B98}\x{6B9E}\x{6BA4}\x{6BAA}\x{6BAB}\x{6BAF}\x{6BB1}\x{6BB2}' - . '\x{6BB3}\x{6BB4}\x{6BB5}\x{6BB7}\x{6BBA}\x{6BBB}\x{6BBC}\x{6BBF}\x{6BC0}' - . '\x{6BC5}\x{6BC6}\x{6BCB}\x{6BCD}\x{6BCE}\x{6BD2}\x{6BD3}\x{6BD4}\x{6BD8}' - . '\x{6BDB}\x{6BDF}\x{6BEB}\x{6BEC}\x{6BEF}\x{6BF3}\x{6C08}\x{6C0F}\x{6C11}' - . '\x{6C13}\x{6C14}\x{6C17}\x{6C1B}\x{6C23}\x{6C24}\x{6C34}\x{6C37}\x{6C38}' - . '\x{6C3E}\x{6C40}\x{6C41}\x{6C42}\x{6C4E}\x{6C50}\x{6C55}\x{6C57}\x{6C5A}' - . '\x{6C5D}\x{6C5E}\x{6C5F}\x{6C60}\x{6C62}\x{6C68}\x{6C6A}\x{6C70}\x{6C72}' - . '\x{6C73}\x{6C7A}\x{6C7D}\x{6C7E}\x{6C81}\x{6C82}\x{6C83}\x{6C88}\x{6C8C}' - . '\x{6C8D}\x{6C90}\x{6C92}\x{6C93}\x{6C96}\x{6C99}\x{6C9A}\x{6C9B}\x{6CA1}' - . '\x{6CA2}\x{6CAB}\x{6CAE}\x{6CB1}\x{6CB3}\x{6CB8}\x{6CB9}\x{6CBA}\x{6CBB}' - . '\x{6CBC}\x{6CBD}\x{6CBE}\x{6CBF}\x{6CC1}\x{6CC4}\x{6CC5}\x{6CC9}\x{6CCA}' - . '\x{6CCC}\x{6CD3}\x{6CD5}\x{6CD7}\x{6CD9}\x{6CDB}\x{6CDD}\x{6CE1}\x{6CE2}' - . '\x{6CE3}\x{6CE5}\x{6CE8}\x{6CEA}\x{6CEF}\x{6CF0}\x{6CF1}\x{6CF3}\x{6D0B}' - . '\x{6D0C}\x{6D12}\x{6D17}\x{6D19}\x{6D1B}\x{6D1E}\x{6D1F}\x{6D25}\x{6D29}' - . '\x{6D2A}\x{6D2B}\x{6D32}\x{6D33}\x{6D35}\x{6D36}\x{6D38}\x{6D3B}\x{6D3D}' - . '\x{6D3E}\x{6D41}\x{6D44}\x{6D45}\x{6D59}\x{6D5A}\x{6D5C}\x{6D63}\x{6D64}' - . '\x{6D66}\x{6D69}\x{6D6A}\x{6D6C}\x{6D6E}\x{6D74}\x{6D77}\x{6D78}\x{6D79}' - . '\x{6D85}\x{6D88}\x{6D8C}\x{6D8E}\x{6D93}\x{6D95}\x{6D99}\x{6D9B}\x{6D9C}' - . '\x{6DAF}\x{6DB2}\x{6DB5}\x{6DB8}\x{6DBC}\x{6DC0}\x{6DC5}\x{6DC6}\x{6DC7}' - . '\x{6DCB}\x{6DCC}\x{6DD1}\x{6DD2}\x{6DD5}\x{6DD8}\x{6DD9}\x{6DDE}\x{6DE1}' - . '\x{6DE4}\x{6DE6}\x{6DE8}\x{6DEA}\x{6DEB}\x{6DEC}\x{6DEE}\x{6DF1}\x{6DF3}' - . '\x{6DF5}\x{6DF7}\x{6DF9}\x{6DFA}\x{6DFB}\x{6E05}\x{6E07}\x{6E08}\x{6E09}' - . '\x{6E0A}\x{6E0B}\x{6E13}\x{6E15}\x{6E19}\x{6E1A}\x{6E1B}\x{6E1D}\x{6E1F}' - . '\x{6E20}\x{6E21}\x{6E23}\x{6E24}\x{6E25}\x{6E26}\x{6E29}\x{6E2B}\x{6E2C}' - . '\x{6E2D}\x{6E2E}\x{6E2F}\x{6E38}\x{6E3A}\x{6E3E}\x{6E43}\x{6E4A}\x{6E4D}' - . '\x{6E4E}\x{6E56}\x{6E58}\x{6E5B}\x{6E5F}\x{6E67}\x{6E6B}\x{6E6E}\x{6E6F}' - . '\x{6E72}\x{6E76}\x{6E7E}\x{6E7F}\x{6E80}\x{6E82}\x{6E8C}\x{6E8F}\x{6E90}' - . '\x{6E96}\x{6E98}\x{6E9C}\x{6E9D}\x{6E9F}\x{6EA2}\x{6EA5}\x{6EAA}\x{6EAF}' - . '\x{6EB2}\x{6EB6}\x{6EB7}\x{6EBA}\x{6EBD}\x{6EC2}\x{6EC4}\x{6EC5}\x{6EC9}' - . '\x{6ECB}\x{6ECC}\x{6ED1}\x{6ED3}\x{6ED4}\x{6ED5}\x{6EDD}\x{6EDE}\x{6EEC}' - . '\x{6EEF}\x{6EF2}\x{6EF4}\x{6EF7}\x{6EF8}\x{6EFE}\x{6EFF}\x{6F01}\x{6F02}' - . '\x{6F06}\x{6F09}\x{6F0F}\x{6F11}\x{6F13}\x{6F14}\x{6F15}\x{6F20}\x{6F22}' - . '\x{6F23}\x{6F2B}\x{6F2C}\x{6F31}\x{6F32}\x{6F38}\x{6F3E}\x{6F3F}\x{6F41}' - . '\x{6F45}\x{6F54}\x{6F58}\x{6F5B}\x{6F5C}\x{6F5F}\x{6F64}\x{6F66}\x{6F6D}' - . '\x{6F6E}\x{6F6F}\x{6F70}\x{6F74}\x{6F78}\x{6F7A}\x{6F7C}\x{6F80}\x{6F81}' - . '\x{6F82}\x{6F84}\x{6F86}\x{6F8E}\x{6F91}\x{6F97}\x{6FA1}\x{6FA3}\x{6FA4}' - . '\x{6FAA}\x{6FB1}\x{6FB3}\x{6FB9}\x{6FC0}\x{6FC1}\x{6FC2}\x{6FC3}\x{6FC6}' - . '\x{6FD4}\x{6FD5}\x{6FD8}\x{6FDB}\x{6FDF}\x{6FE0}\x{6FE1}\x{6FE4}\x{6FEB}' - . '\x{6FEC}\x{6FEE}\x{6FEF}\x{6FF1}\x{6FF3}\x{6FF6}\x{6FFA}\x{6FFE}\x{7001}' - . '\x{7009}\x{700B}\x{700F}\x{7011}\x{7015}\x{7018}\x{701A}\x{701B}\x{701D}' - . '\x{701E}\x{701F}\x{7026}\x{7027}\x{702C}\x{7030}\x{7032}\x{703E}\x{704C}' - . '\x{7051}\x{7058}\x{7063}\x{706B}\x{706F}\x{7070}\x{7078}\x{707C}\x{707D}' - . '\x{7089}\x{708A}\x{708E}\x{7092}\x{7099}\x{70AC}\x{70AD}\x{70AE}\x{70AF}' - . '\x{70B3}\x{70B8}\x{70B9}\x{70BA}\x{70C8}\x{70CB}\x{70CF}\x{70D9}\x{70DD}' - . '\x{70DF}\x{70F1}\x{70F9}\x{70FD}\x{7109}\x{7114}\x{7119}\x{711A}\x{711C}' - . '\x{7121}\x{7126}\x{7136}\x{713C}\x{7149}\x{714C}\x{714E}\x{7155}\x{7156}' - . '\x{7159}\x{7162}\x{7164}\x{7165}\x{7166}\x{7167}\x{7169}\x{716C}\x{716E}' - . '\x{717D}\x{7184}\x{7188}\x{718A}\x{718F}\x{7194}\x{7195}\x{7199}\x{719F}' - . '\x{71A8}\x{71AC}\x{71B1}\x{71B9}\x{71BE}\x{71C3}\x{71C8}\x{71C9}\x{71CE}' - . '\x{71D0}\x{71D2}\x{71D4}\x{71D5}\x{71D7}\x{71DF}\x{71E0}\x{71E5}\x{71E6}' - . '\x{71E7}\x{71EC}\x{71ED}\x{71EE}\x{71F5}\x{71F9}\x{71FB}\x{71FC}\x{71FF}' - . '\x{7206}\x{720D}\x{7210}\x{721B}\x{7228}\x{722A}\x{722C}\x{722D}\x{7230}' - . '\x{7232}\x{7235}\x{7236}\x{723A}\x{723B}\x{723C}\x{723D}\x{723E}\x{723F}' - . '\x{7240}\x{7246}\x{7247}\x{7248}\x{724B}\x{724C}\x{7252}\x{7258}\x{7259}' - . '\x{725B}\x{725D}\x{725F}\x{7261}\x{7262}\x{7267}\x{7269}\x{7272}\x{7274}' - . '\x{7279}\x{727D}\x{727E}\x{7280}\x{7281}\x{7282}\x{7287}\x{7292}\x{7296}' - . '\x{72A0}\x{72A2}\x{72A7}\x{72AC}\x{72AF}\x{72B2}\x{72B6}\x{72B9}\x{72C2}' - . '\x{72C3}\x{72C4}\x{72C6}\x{72CE}\x{72D0}\x{72D2}\x{72D7}\x{72D9}\x{72DB}' - . '\x{72E0}\x{72E1}\x{72E2}\x{72E9}\x{72EC}\x{72ED}\x{72F7}\x{72F8}\x{72F9}' - . '\x{72FC}\x{72FD}\x{730A}\x{7316}\x{7317}\x{731B}\x{731C}\x{731D}\x{731F}' - . '\x{7325}\x{7329}\x{732A}\x{732B}\x{732E}\x{732F}\x{7334}\x{7336}\x{7337}' - . '\x{733E}\x{733F}\x{7344}\x{7345}\x{734E}\x{734F}\x{7357}\x{7363}\x{7368}' - . '\x{736A}\x{7370}\x{7372}\x{7375}\x{7378}\x{737A}\x{737B}\x{7384}\x{7387}' - . '\x{7389}\x{738B}\x{7396}\x{73A9}\x{73B2}\x{73B3}\x{73BB}\x{73C0}\x{73C2}' - . '\x{73C8}\x{73CA}\x{73CD}\x{73CE}\x{73DE}\x{73E0}\x{73E5}\x{73EA}\x{73ED}' - . '\x{73EE}\x{73F1}\x{73F8}\x{73FE}\x{7403}\x{7405}\x{7406}\x{7409}\x{7422}' - . '\x{7425}\x{7432}\x{7433}\x{7434}\x{7435}\x{7436}\x{743A}\x{743F}\x{7441}' - . '\x{7455}\x{7459}\x{745A}\x{745B}\x{745C}\x{745E}\x{745F}\x{7460}\x{7463}' - . '\x{7464}\x{7469}\x{746A}\x{746F}\x{7470}\x{7473}\x{7476}\x{747E}\x{7483}' - . '\x{748B}\x{749E}\x{74A2}\x{74A7}\x{74B0}\x{74BD}\x{74CA}\x{74CF}\x{74D4}' - . '\x{74DC}\x{74E0}\x{74E2}\x{74E3}\x{74E6}\x{74E7}\x{74E9}\x{74EE}\x{74F0}' - . '\x{74F1}\x{74F2}\x{74F6}\x{74F7}\x{74F8}\x{7503}\x{7504}\x{7505}\x{750C}' - . '\x{750D}\x{750E}\x{7511}\x{7513}\x{7515}\x{7518}\x{751A}\x{751C}\x{751E}' - . '\x{751F}\x{7523}\x{7525}\x{7526}\x{7528}\x{752B}\x{752C}\x{7530}\x{7531}' - . '\x{7532}\x{7533}\x{7537}\x{7538}\x{753A}\x{753B}\x{753C}\x{7544}\x{7546}' - . '\x{7549}\x{754A}\x{754B}\x{754C}\x{754D}\x{754F}\x{7551}\x{7554}\x{7559}' - . '\x{755A}\x{755B}\x{755C}\x{755D}\x{7560}\x{7562}\x{7564}\x{7565}\x{7566}' - . '\x{7567}\x{7569}\x{756A}\x{756B}\x{756D}\x{7570}\x{7573}\x{7574}\x{7576}' - . '\x{7577}\x{7578}\x{757F}\x{7582}\x{7586}\x{7587}\x{7589}\x{758A}\x{758B}' - . '\x{758E}\x{758F}\x{7591}\x{7594}\x{759A}\x{759D}\x{75A3}\x{75A5}\x{75AB}' - . '\x{75B1}\x{75B2}\x{75B3}\x{75B5}\x{75B8}\x{75B9}\x{75BC}\x{75BD}\x{75BE}' - . '\x{75C2}\x{75C3}\x{75C5}\x{75C7}\x{75CA}\x{75CD}\x{75D2}\x{75D4}\x{75D5}' - . '\x{75D8}\x{75D9}\x{75DB}\x{75DE}\x{75E2}\x{75E3}\x{75E9}\x{75F0}\x{75F2}' - . '\x{75F3}\x{75F4}\x{75FA}\x{75FC}\x{75FE}\x{75FF}\x{7601}\x{7609}\x{760B}' - . '\x{760D}\x{761F}\x{7620}\x{7621}\x{7622}\x{7624}\x{7627}\x{7630}\x{7634}' - . '\x{763B}\x{7642}\x{7646}\x{7647}\x{7648}\x{764C}\x{7652}\x{7656}\x{7658}' - . '\x{765C}\x{7661}\x{7662}\x{7667}\x{7668}\x{7669}\x{766A}\x{766C}\x{7670}' - . '\x{7672}\x{7676}\x{7678}\x{767A}\x{767B}\x{767C}\x{767D}\x{767E}\x{7680}' - . '\x{7683}\x{7684}\x{7686}\x{7687}\x{7688}\x{768B}\x{768E}\x{7690}\x{7693}' - . '\x{7696}\x{7699}\x{769A}\x{76AE}\x{76B0}\x{76B4}\x{76B7}\x{76B8}\x{76B9}' - . '\x{76BA}\x{76BF}\x{76C2}\x{76C3}\x{76C6}\x{76C8}\x{76CA}\x{76CD}\x{76D2}' - . '\x{76D6}\x{76D7}\x{76DB}\x{76DC}\x{76DE}\x{76DF}\x{76E1}\x{76E3}\x{76E4}' - . '\x{76E5}\x{76E7}\x{76EA}\x{76EE}\x{76F2}\x{76F4}\x{76F8}\x{76FB}\x{76FE}' - . '\x{7701}\x{7704}\x{7707}\x{7708}\x{7709}\x{770B}\x{770C}\x{771B}\x{771E}' - . '\x{771F}\x{7720}\x{7724}\x{7725}\x{7726}\x{7729}\x{7737}\x{7738}\x{773A}' - . '\x{773C}\x{7740}\x{7747}\x{775A}\x{775B}\x{7761}\x{7763}\x{7765}\x{7766}' - . '\x{7768}\x{776B}\x{7779}\x{777E}\x{777F}\x{778B}\x{778E}\x{7791}\x{779E}' - . '\x{77A0}\x{77A5}\x{77AC}\x{77AD}\x{77B0}\x{77B3}\x{77B6}\x{77B9}\x{77BB}' - . '\x{77BC}\x{77BD}\x{77BF}\x{77C7}\x{77CD}\x{77D7}\x{77DA}\x{77DB}\x{77DC}' - . '\x{77E2}\x{77E3}\x{77E5}\x{77E7}\x{77E9}\x{77ED}\x{77EE}\x{77EF}\x{77F3}' - . '\x{77FC}\x{7802}\x{780C}\x{7812}\x{7814}\x{7815}\x{7820}\x{7825}\x{7826}' - . '\x{7827}\x{7832}\x{7834}\x{783A}\x{783F}\x{7845}\x{785D}\x{786B}\x{786C}' - . '\x{786F}\x{7872}\x{7874}\x{787C}\x{7881}\x{7886}\x{7887}\x{788C}\x{788D}' - . '\x{788E}\x{7891}\x{7893}\x{7895}\x{7897}\x{789A}\x{78A3}\x{78A7}\x{78A9}' - . '\x{78AA}\x{78AF}\x{78B5}\x{78BA}\x{78BC}\x{78BE}\x{78C1}\x{78C5}\x{78C6}' - . '\x{78CA}\x{78CB}\x{78D0}\x{78D1}\x{78D4}\x{78DA}\x{78E7}\x{78E8}\x{78EC}' - . '\x{78EF}\x{78F4}\x{78FD}\x{7901}\x{7907}\x{790E}\x{7911}\x{7912}\x{7919}' - . '\x{7926}\x{792A}\x{792B}\x{792C}\x{793A}\x{793C}\x{793E}\x{7940}\x{7941}' - . '\x{7947}\x{7948}\x{7949}\x{7950}\x{7953}\x{7955}\x{7956}\x{7957}\x{795A}' - . '\x{795D}\x{795E}\x{795F}\x{7960}\x{7962}\x{7965}\x{7968}\x{796D}\x{7977}' - . '\x{797A}\x{797F}\x{7980}\x{7981}\x{7984}\x{7985}\x{798A}\x{798D}\x{798E}' - . '\x{798F}\x{799D}\x{79A6}\x{79A7}\x{79AA}\x{79AE}\x{79B0}\x{79B3}\x{79B9}' - . '\x{79BA}\x{79BD}\x{79BE}\x{79BF}\x{79C0}\x{79C1}\x{79C9}\x{79CB}\x{79D1}' - . '\x{79D2}\x{79D5}\x{79D8}\x{79DF}\x{79E1}\x{79E3}\x{79E4}\x{79E6}\x{79E7}' - . '\x{79E9}\x{79EC}\x{79F0}\x{79FB}\x{7A00}\x{7A08}\x{7A0B}\x{7A0D}\x{7A0E}' - . '\x{7A14}\x{7A17}\x{7A18}\x{7A19}\x{7A1A}\x{7A1C}\x{7A1F}\x{7A20}\x{7A2E}' - . '\x{7A31}\x{7A32}\x{7A37}\x{7A3B}\x{7A3C}\x{7A3D}\x{7A3E}\x{7A3F}\x{7A40}' - . '\x{7A42}\x{7A43}\x{7A46}\x{7A49}\x{7A4D}\x{7A4E}\x{7A4F}\x{7A50}\x{7A57}' - . '\x{7A61}\x{7A62}\x{7A63}\x{7A69}\x{7A6B}\x{7A70}\x{7A74}\x{7A76}\x{7A79}' - . '\x{7A7A}\x{7A7D}\x{7A7F}\x{7A81}\x{7A83}\x{7A84}\x{7A88}\x{7A92}\x{7A93}' - . '\x{7A95}\x{7A96}\x{7A97}\x{7A98}\x{7A9F}\x{7AA9}\x{7AAA}\x{7AAE}\x{7AAF}' - . '\x{7AB0}\x{7AB6}\x{7ABA}\x{7ABF}\x{7AC3}\x{7AC4}\x{7AC5}\x{7AC7}\x{7AC8}' - . '\x{7ACA}\x{7ACB}\x{7ACD}\x{7ACF}\x{7AD2}\x{7AD3}\x{7AD5}\x{7AD9}\x{7ADA}' - . '\x{7ADC}\x{7ADD}\x{7ADF}\x{7AE0}\x{7AE1}\x{7AE2}\x{7AE3}\x{7AE5}\x{7AE6}' - . '\x{7AEA}\x{7AED}\x{7AEF}\x{7AF0}\x{7AF6}\x{7AF8}\x{7AF9}\x{7AFA}\x{7AFF}' - . '\x{7B02}\x{7B04}\x{7B06}\x{7B08}\x{7B0A}\x{7B0B}\x{7B0F}\x{7B11}\x{7B18}' - . '\x{7B19}\x{7B1B}\x{7B1E}\x{7B20}\x{7B25}\x{7B26}\x{7B28}\x{7B2C}\x{7B33}' - . '\x{7B35}\x{7B36}\x{7B39}\x{7B45}\x{7B46}\x{7B48}\x{7B49}\x{7B4B}\x{7B4C}' - . '\x{7B4D}\x{7B4F}\x{7B50}\x{7B51}\x{7B52}\x{7B54}\x{7B56}\x{7B5D}\x{7B65}' - . '\x{7B67}\x{7B6C}\x{7B6E}\x{7B70}\x{7B71}\x{7B74}\x{7B75}\x{7B7A}\x{7B86}' - . '\x{7B87}\x{7B8B}\x{7B8D}\x{7B8F}\x{7B92}\x{7B94}\x{7B95}\x{7B97}\x{7B98}' - . '\x{7B99}\x{7B9A}\x{7B9C}\x{7B9D}\x{7B9F}\x{7BA1}\x{7BAA}\x{7BAD}\x{7BB1}' - . '\x{7BB4}\x{7BB8}\x{7BC0}\x{7BC1}\x{7BC4}\x{7BC6}\x{7BC7}\x{7BC9}\x{7BCB}' - . '\x{7BCC}\x{7BCF}\x{7BDD}\x{7BE0}\x{7BE4}\x{7BE5}\x{7BE6}\x{7BE9}\x{7BED}' - . '\x{7BF3}\x{7BF6}\x{7BF7}\x{7C00}\x{7C07}\x{7C0D}\x{7C11}\x{7C12}\x{7C13}' - . '\x{7C14}\x{7C17}\x{7C1F}\x{7C21}\x{7C23}\x{7C27}\x{7C2A}\x{7C2B}\x{7C37}' - . '\x{7C38}\x{7C3D}\x{7C3E}\x{7C3F}\x{7C40}\x{7C43}\x{7C4C}\x{7C4D}\x{7C4F}' - . '\x{7C50}\x{7C54}\x{7C56}\x{7C58}\x{7C5F}\x{7C60}\x{7C64}\x{7C65}\x{7C6C}' - . '\x{7C73}\x{7C75}\x{7C7E}\x{7C81}\x{7C82}\x{7C83}\x{7C89}\x{7C8B}\x{7C8D}' - . '\x{7C90}\x{7C92}\x{7C95}\x{7C97}\x{7C98}\x{7C9B}\x{7C9F}\x{7CA1}\x{7CA2}' - . '\x{7CA4}\x{7CA5}\x{7CA7}\x{7CA8}\x{7CAB}\x{7CAD}\x{7CAE}\x{7CB1}\x{7CB2}' - . '\x{7CB3}\x{7CB9}\x{7CBD}\x{7CBE}\x{7CC0}\x{7CC2}\x{7CC5}\x{7CCA}\x{7CCE}' - . '\x{7CD2}\x{7CD6}\x{7CD8}\x{7CDC}\x{7CDE}\x{7CDF}\x{7CE0}\x{7CE2}\x{7CE7}' - . '\x{7CEF}\x{7CF2}\x{7CF4}\x{7CF6}\x{7CF8}\x{7CFA}\x{7CFB}\x{7CFE}\x{7D00}' - . '\x{7D02}\x{7D04}\x{7D05}\x{7D06}\x{7D0A}\x{7D0B}\x{7D0D}\x{7D10}\x{7D14}' - . '\x{7D15}\x{7D17}\x{7D18}\x{7D19}\x{7D1A}\x{7D1B}\x{7D1C}\x{7D20}\x{7D21}' - . '\x{7D22}\x{7D2B}\x{7D2C}\x{7D2E}\x{7D2F}\x{7D30}\x{7D32}\x{7D33}\x{7D35}' - . '\x{7D39}\x{7D3A}\x{7D3F}\x{7D42}\x{7D43}\x{7D44}\x{7D45}\x{7D46}\x{7D4B}' - . '\x{7D4C}\x{7D4E}\x{7D4F}\x{7D50}\x{7D56}\x{7D5B}\x{7D5E}\x{7D61}\x{7D62}' - . '\x{7D63}\x{7D66}\x{7D68}\x{7D6E}\x{7D71}\x{7D72}\x{7D73}\x{7D75}\x{7D76}' - . '\x{7D79}\x{7D7D}\x{7D89}\x{7D8F}\x{7D93}\x{7D99}\x{7D9A}\x{7D9B}\x{7D9C}' - . '\x{7D9F}\x{7DA2}\x{7DA3}\x{7DAB}\x{7DAC}\x{7DAD}\x{7DAE}\x{7DAF}\x{7DB0}' - . '\x{7DB1}\x{7DB2}\x{7DB4}\x{7DB5}\x{7DB8}\x{7DBA}\x{7DBB}\x{7DBD}\x{7DBE}' - . '\x{7DBF}\x{7DC7}\x{7DCA}\x{7DCB}\x{7DCF}\x{7DD1}\x{7DD2}\x{7DD5}\x{7DD8}' - . '\x{7DDA}\x{7DDC}\x{7DDD}\x{7DDE}\x{7DE0}\x{7DE1}\x{7DE4}\x{7DE8}\x{7DE9}' - . '\x{7DEC}\x{7DEF}\x{7DF2}\x{7DF4}\x{7DFB}\x{7E01}\x{7E04}\x{7E05}\x{7E09}' - . '\x{7E0A}\x{7E0B}\x{7E12}\x{7E1B}\x{7E1E}\x{7E1F}\x{7E21}\x{7E22}\x{7E23}' - . '\x{7E26}\x{7E2B}\x{7E2E}\x{7E31}\x{7E32}\x{7E35}\x{7E37}\x{7E39}\x{7E3A}' - . '\x{7E3B}\x{7E3D}\x{7E3E}\x{7E41}\x{7E43}\x{7E46}\x{7E4A}\x{7E4B}\x{7E4D}' - . '\x{7E54}\x{7E55}\x{7E56}\x{7E59}\x{7E5A}\x{7E5D}\x{7E5E}\x{7E66}\x{7E67}' - . '\x{7E69}\x{7E6A}\x{7E6D}\x{7E70}\x{7E79}\x{7E7B}\x{7E7C}\x{7E7D}\x{7E7F}' - . '\x{7E82}\x{7E83}\x{7E88}\x{7E89}\x{7E8C}\x{7E8E}\x{7E8F}\x{7E90}\x{7E92}' - . '\x{7E93}\x{7E94}\x{7E96}\x{7E9B}\x{7E9C}\x{7F36}\x{7F38}\x{7F3A}\x{7F45}' - . '\x{7F4C}\x{7F4D}\x{7F4E}\x{7F50}\x{7F51}\x{7F54}\x{7F55}\x{7F58}\x{7F5F}' - . '\x{7F60}\x{7F67}\x{7F68}\x{7F69}\x{7F6A}\x{7F6B}\x{7F6E}\x{7F70}\x{7F72}' - . '\x{7F75}\x{7F77}\x{7F78}\x{7F79}\x{7F82}\x{7F83}\x{7F85}\x{7F86}\x{7F87}' - . '\x{7F88}\x{7F8A}\x{7F8C}\x{7F8E}\x{7F94}\x{7F9A}\x{7F9D}\x{7F9E}\x{7FA3}' - . '\x{7FA4}\x{7FA8}\x{7FA9}\x{7FAE}\x{7FAF}\x{7FB2}\x{7FB6}\x{7FB8}\x{7FB9}' - . '\x{7FBD}\x{7FC1}\x{7FC5}\x{7FC6}\x{7FCA}\x{7FCC}\x{7FD2}\x{7FD4}\x{7FD5}' - . '\x{7FE0}\x{7FE1}\x{7FE6}\x{7FE9}\x{7FEB}\x{7FF0}\x{7FF3}\x{7FF9}\x{7FFB}' - . '\x{7FFC}\x{8000}\x{8001}\x{8003}\x{8004}\x{8005}\x{8006}\x{800B}\x{800C}' - . '\x{8010}\x{8012}\x{8015}\x{8017}\x{8018}\x{8019}\x{801C}\x{8021}\x{8028}' - . '\x{8033}\x{8036}\x{803B}\x{803D}\x{803F}\x{8046}\x{804A}\x{8052}\x{8056}' - . '\x{8058}\x{805A}\x{805E}\x{805F}\x{8061}\x{8062}\x{8068}\x{806F}\x{8070}' - . '\x{8072}\x{8073}\x{8074}\x{8076}\x{8077}\x{8079}\x{807D}\x{807E}\x{807F}' - . '\x{8084}\x{8085}\x{8086}\x{8087}\x{8089}\x{808B}\x{808C}\x{8093}\x{8096}' - . '\x{8098}\x{809A}\x{809B}\x{809D}\x{80A1}\x{80A2}\x{80A5}\x{80A9}\x{80AA}' - . '\x{80AC}\x{80AD}\x{80AF}\x{80B1}\x{80B2}\x{80B4}\x{80BA}\x{80C3}\x{80C4}' - . '\x{80C6}\x{80CC}\x{80CE}\x{80D6}\x{80D9}\x{80DA}\x{80DB}\x{80DD}\x{80DE}' - . '\x{80E1}\x{80E4}\x{80E5}\x{80EF}\x{80F1}\x{80F4}\x{80F8}\x{80FC}\x{80FD}' - . '\x{8102}\x{8105}\x{8106}\x{8107}\x{8108}\x{8109}\x{810A}\x{811A}\x{811B}' - . '\x{8123}\x{8129}\x{812F}\x{8131}\x{8133}\x{8139}\x{813E}\x{8146}\x{814B}' - . '\x{814E}\x{8150}\x{8151}\x{8153}\x{8154}\x{8155}\x{815F}\x{8165}\x{8166}' - . '\x{816B}\x{816E}\x{8170}\x{8171}\x{8174}\x{8178}\x{8179}\x{817A}\x{817F}' - . '\x{8180}\x{8182}\x{8183}\x{8188}\x{818A}\x{818F}\x{8193}\x{8195}\x{819A}' - . '\x{819C}\x{819D}\x{81A0}\x{81A3}\x{81A4}\x{81A8}\x{81A9}\x{81B0}\x{81B3}' - . '\x{81B5}\x{81B8}\x{81BA}\x{81BD}\x{81BE}\x{81BF}\x{81C0}\x{81C2}\x{81C6}' - . '\x{81C8}\x{81C9}\x{81CD}\x{81D1}\x{81D3}\x{81D8}\x{81D9}\x{81DA}\x{81DF}' - . '\x{81E0}\x{81E3}\x{81E5}\x{81E7}\x{81E8}\x{81EA}\x{81ED}\x{81F3}\x{81F4}' - . '\x{81FA}\x{81FB}\x{81FC}\x{81FE}\x{8201}\x{8202}\x{8205}\x{8207}\x{8208}' - . '\x{8209}\x{820A}\x{820C}\x{820D}\x{820E}\x{8210}\x{8212}\x{8216}\x{8217}' - . '\x{8218}\x{821B}\x{821C}\x{821E}\x{821F}\x{8229}\x{822A}\x{822B}\x{822C}' - . '\x{822E}\x{8233}\x{8235}\x{8236}\x{8237}\x{8238}\x{8239}\x{8240}\x{8247}' - . '\x{8258}\x{8259}\x{825A}\x{825D}\x{825F}\x{8262}\x{8264}\x{8266}\x{8268}' - . '\x{826A}\x{826B}\x{826E}\x{826F}\x{8271}\x{8272}\x{8276}\x{8277}\x{8278}' - . '\x{827E}\x{828B}\x{828D}\x{8292}\x{8299}\x{829D}\x{829F}\x{82A5}\x{82A6}' - . '\x{82AB}\x{82AC}\x{82AD}\x{82AF}\x{82B1}\x{82B3}\x{82B8}\x{82B9}\x{82BB}' - . '\x{82BD}\x{82C5}\x{82D1}\x{82D2}\x{82D3}\x{82D4}\x{82D7}\x{82D9}\x{82DB}' - . '\x{82DC}\x{82DE}\x{82DF}\x{82E1}\x{82E3}\x{82E5}\x{82E6}\x{82E7}\x{82EB}' - . '\x{82F1}\x{82F3}\x{82F4}\x{82F9}\x{82FA}\x{82FB}\x{8302}\x{8303}\x{8304}' - . '\x{8305}\x{8306}\x{8309}\x{830E}\x{8316}\x{8317}\x{8318}\x{831C}\x{8323}' - . '\x{8328}\x{832B}\x{832F}\x{8331}\x{8332}\x{8334}\x{8335}\x{8336}\x{8338}' - . '\x{8339}\x{8340}\x{8345}\x{8349}\x{834A}\x{834F}\x{8350}\x{8352}\x{8358}' - . '\x{8373}\x{8375}\x{8377}\x{837B}\x{837C}\x{8385}\x{8387}\x{8389}\x{838A}' - . '\x{838E}\x{8393}\x{8396}\x{839A}\x{839E}\x{839F}\x{83A0}\x{83A2}\x{83A8}' - . '\x{83AA}\x{83AB}\x{83B1}\x{83B5}\x{83BD}\x{83C1}\x{83C5}\x{83CA}\x{83CC}' - . '\x{83CE}\x{83D3}\x{83D6}\x{83D8}\x{83DC}\x{83DF}\x{83E0}\x{83E9}\x{83EB}' - . '\x{83EF}\x{83F0}\x{83F1}\x{83F2}\x{83F4}\x{83F7}\x{83FB}\x{83FD}\x{8403}' - . '\x{8404}\x{8407}\x{840B}\x{840C}\x{840D}\x{840E}\x{8413}\x{8420}\x{8422}' - . '\x{8429}\x{842A}\x{842C}\x{8431}\x{8435}\x{8438}\x{843C}\x{843D}\x{8446}' - . '\x{8449}\x{844E}\x{8457}\x{845B}\x{8461}\x{8462}\x{8463}\x{8466}\x{8469}' - . '\x{846B}\x{846C}\x{846D}\x{846E}\x{846F}\x{8471}\x{8475}\x{8477}\x{8479}' - . '\x{847A}\x{8482}\x{8484}\x{848B}\x{8490}\x{8494}\x{8499}\x{849C}\x{849F}' - . '\x{84A1}\x{84AD}\x{84B2}\x{84B8}\x{84B9}\x{84BB}\x{84BC}\x{84BF}\x{84C1}' - . '\x{84C4}\x{84C6}\x{84C9}\x{84CA}\x{84CB}\x{84CD}\x{84D0}\x{84D1}\x{84D6}' - . '\x{84D9}\x{84DA}\x{84EC}\x{84EE}\x{84F4}\x{84FC}\x{84FF}\x{8500}\x{8506}' - . '\x{8511}\x{8513}\x{8514}\x{8515}\x{8517}\x{8518}\x{851A}\x{851F}\x{8521}' - . '\x{8526}\x{852C}\x{852D}\x{8535}\x{853D}\x{8540}\x{8541}\x{8543}\x{8548}' - . '\x{8549}\x{854A}\x{854B}\x{854E}\x{8555}\x{8557}\x{8558}\x{855A}\x{8563}' - . '\x{8568}\x{8569}\x{856A}\x{856D}\x{8577}\x{857E}\x{8580}\x{8584}\x{8587}' - . '\x{8588}\x{858A}\x{8590}\x{8591}\x{8594}\x{8597}\x{8599}\x{859B}\x{859C}' - . '\x{85A4}\x{85A6}\x{85A8}\x{85A9}\x{85AA}\x{85AB}\x{85AC}\x{85AE}\x{85AF}' - . '\x{85B9}\x{85BA}\x{85C1}\x{85C9}\x{85CD}\x{85CF}\x{85D0}\x{85D5}\x{85DC}' - . '\x{85DD}\x{85E4}\x{85E5}\x{85E9}\x{85EA}\x{85F7}\x{85F9}\x{85FA}\x{85FB}' - . '\x{85FE}\x{8602}\x{8606}\x{8607}\x{860A}\x{860B}\x{8613}\x{8616}\x{8617}' - . '\x{861A}\x{8622}\x{862D}\x{862F}\x{8630}\x{863F}\x{864D}\x{864E}\x{8650}' - . '\x{8654}\x{8655}\x{865A}\x{865C}\x{865E}\x{865F}\x{8667}\x{866B}\x{8671}' - . '\x{8679}\x{867B}\x{868A}\x{868B}\x{868C}\x{8693}\x{8695}\x{86A3}\x{86A4}' - . '\x{86A9}\x{86AA}\x{86AB}\x{86AF}\x{86B0}\x{86B6}\x{86C4}\x{86C6}\x{86C7}' - . '\x{86C9}\x{86CB}\x{86CD}\x{86CE}\x{86D4}\x{86D9}\x{86DB}\x{86DE}\x{86DF}' - . '\x{86E4}\x{86E9}\x{86EC}\x{86ED}\x{86EE}\x{86EF}\x{86F8}\x{86F9}\x{86FB}' - . '\x{86FE}\x{8700}\x{8702}\x{8703}\x{8706}\x{8708}\x{8709}\x{870A}\x{870D}' - . '\x{8711}\x{8712}\x{8718}\x{871A}\x{871C}\x{8725}\x{8729}\x{8734}\x{8737}' - . '\x{873B}\x{873F}\x{8749}\x{874B}\x{874C}\x{874E}\x{8753}\x{8755}\x{8757}' - . '\x{8759}\x{875F}\x{8760}\x{8763}\x{8766}\x{8768}\x{876A}\x{876E}\x{8774}' - . '\x{8776}\x{8778}\x{877F}\x{8782}\x{878D}\x{879F}\x{87A2}\x{87AB}\x{87AF}' - . '\x{87B3}\x{87BA}\x{87BB}\x{87BD}\x{87C0}\x{87C4}\x{87C6}\x{87C7}\x{87CB}' - . '\x{87D0}\x{87D2}\x{87E0}\x{87EF}\x{87F2}\x{87F6}\x{87F7}\x{87F9}\x{87FB}' - . '\x{87FE}\x{8805}\x{880D}\x{880E}\x{880F}\x{8811}\x{8815}\x{8816}\x{8821}' - . '\x{8822}\x{8823}\x{8827}\x{8831}\x{8836}\x{8839}\x{883B}\x{8840}\x{8842}' - . '\x{8844}\x{8846}\x{884C}\x{884D}\x{8852}\x{8853}\x{8857}\x{8859}\x{885B}' - . '\x{885D}\x{885E}\x{8861}\x{8862}\x{8863}\x{8868}\x{886B}\x{8870}\x{8872}' - . '\x{8875}\x{8877}\x{887D}\x{887E}\x{887F}\x{8881}\x{8882}\x{8888}\x{888B}' - . '\x{888D}\x{8892}\x{8896}\x{8897}\x{8899}\x{889E}\x{88A2}\x{88A4}\x{88AB}' - . '\x{88AE}\x{88B0}\x{88B1}\x{88B4}\x{88B5}\x{88B7}\x{88BF}\x{88C1}\x{88C2}' - . '\x{88C3}\x{88C4}\x{88C5}\x{88CF}\x{88D4}\x{88D5}\x{88D8}\x{88D9}\x{88DC}' - . '\x{88DD}\x{88DF}\x{88E1}\x{88E8}\x{88F2}\x{88F3}\x{88F4}\x{88F8}\x{88F9}' - . '\x{88FC}\x{88FD}\x{88FE}\x{8902}\x{8904}\x{8907}\x{890A}\x{890C}\x{8910}' - . '\x{8912}\x{8913}\x{891D}\x{891E}\x{8925}\x{892A}\x{892B}\x{8936}\x{8938}' - . '\x{893B}\x{8941}\x{8943}\x{8944}\x{894C}\x{894D}\x{8956}\x{895E}\x{895F}' - . '\x{8960}\x{8964}\x{8966}\x{896A}\x{896D}\x{896F}\x{8972}\x{8974}\x{8977}' - . '\x{897E}\x{897F}\x{8981}\x{8983}\x{8986}\x{8987}\x{8988}\x{898A}\x{898B}' - . '\x{898F}\x{8993}\x{8996}\x{8997}\x{8998}\x{899A}\x{89A1}\x{89A6}\x{89A7}' - . '\x{89A9}\x{89AA}\x{89AC}\x{89AF}\x{89B2}\x{89B3}\x{89BA}\x{89BD}\x{89BF}' - . '\x{89C0}\x{89D2}\x{89DA}\x{89DC}\x{89DD}\x{89E3}\x{89E6}\x{89E7}\x{89F4}' - . '\x{89F8}\x{8A00}\x{8A02}\x{8A03}\x{8A08}\x{8A0A}\x{8A0C}\x{8A0E}\x{8A10}' - . '\x{8A13}\x{8A16}\x{8A17}\x{8A18}\x{8A1B}\x{8A1D}\x{8A1F}\x{8A23}\x{8A25}' - . '\x{8A2A}\x{8A2D}\x{8A31}\x{8A33}\x{8A34}\x{8A36}\x{8A3A}\x{8A3B}\x{8A3C}' - . '\x{8A41}\x{8A46}\x{8A48}\x{8A50}\x{8A51}\x{8A52}\x{8A54}\x{8A55}\x{8A5B}' - . '\x{8A5E}\x{8A60}\x{8A62}\x{8A63}\x{8A66}\x{8A69}\x{8A6B}\x{8A6C}\x{8A6D}' - . '\x{8A6E}\x{8A70}\x{8A71}\x{8A72}\x{8A73}\x{8A7C}\x{8A82}\x{8A84}\x{8A85}' - . '\x{8A87}\x{8A89}\x{8A8C}\x{8A8D}\x{8A91}\x{8A93}\x{8A95}\x{8A98}\x{8A9A}' - . '\x{8A9E}\x{8AA0}\x{8AA1}\x{8AA3}\x{8AA4}\x{8AA5}\x{8AA6}\x{8AA8}\x{8AAC}' - . '\x{8AAD}\x{8AB0}\x{8AB2}\x{8AB9}\x{8ABC}\x{8ABF}\x{8AC2}\x{8AC4}\x{8AC7}' - . '\x{8ACB}\x{8ACC}\x{8ACD}\x{8ACF}\x{8AD2}\x{8AD6}\x{8ADA}\x{8ADB}\x{8ADC}' - . '\x{8ADE}\x{8AE0}\x{8AE1}\x{8AE2}\x{8AE4}\x{8AE6}\x{8AE7}\x{8AEB}\x{8AED}' - . '\x{8AEE}\x{8AF1}\x{8AF3}\x{8AF7}\x{8AF8}\x{8AFA}\x{8AFE}\x{8B00}\x{8B01}' - . '\x{8B02}\x{8B04}\x{8B07}\x{8B0C}\x{8B0E}\x{8B10}\x{8B14}\x{8B16}\x{8B17}' - . '\x{8B19}\x{8B1A}\x{8B1B}\x{8B1D}\x{8B20}\x{8B21}\x{8B26}\x{8B28}\x{8B2B}' - . '\x{8B2C}\x{8B33}\x{8B39}\x{8B3E}\x{8B41}\x{8B49}\x{8B4C}\x{8B4E}\x{8B4F}' - . '\x{8B56}\x{8B58}\x{8B5A}\x{8B5B}\x{8B5C}\x{8B5F}\x{8B66}\x{8B6B}\x{8B6C}' - . '\x{8B6F}\x{8B70}\x{8B71}\x{8B72}\x{8B74}\x{8B77}\x{8B7D}\x{8B80}\x{8B83}' - . '\x{8B8A}\x{8B8C}\x{8B8E}\x{8B90}\x{8B92}\x{8B93}\x{8B96}\x{8B99}\x{8B9A}' - . '\x{8C37}\x{8C3A}\x{8C3F}\x{8C41}\x{8C46}\x{8C48}\x{8C4A}\x{8C4C}\x{8C4E}' - . '\x{8C50}\x{8C55}\x{8C5A}\x{8C61}\x{8C62}\x{8C6A}\x{8C6B}\x{8C6C}\x{8C78}' - . '\x{8C79}\x{8C7A}\x{8C7C}\x{8C82}\x{8C85}\x{8C89}\x{8C8A}\x{8C8C}\x{8C8D}' - . '\x{8C8E}\x{8C94}\x{8C98}\x{8C9D}\x{8C9E}\x{8CA0}\x{8CA1}\x{8CA2}\x{8CA7}' - . '\x{8CA8}\x{8CA9}\x{8CAA}\x{8CAB}\x{8CAC}\x{8CAD}\x{8CAE}\x{8CAF}\x{8CB0}' - . '\x{8CB2}\x{8CB3}\x{8CB4}\x{8CB6}\x{8CB7}\x{8CB8}\x{8CBB}\x{8CBC}\x{8CBD}' - . '\x{8CBF}\x{8CC0}\x{8CC1}\x{8CC2}\x{8CC3}\x{8CC4}\x{8CC7}\x{8CC8}\x{8CCA}' - . '\x{8CCD}\x{8CCE}\x{8CD1}\x{8CD3}\x{8CDA}\x{8CDB}\x{8CDC}\x{8CDE}\x{8CE0}' - . '\x{8CE2}\x{8CE3}\x{8CE4}\x{8CE6}\x{8CEA}\x{8CED}\x{8CFA}\x{8CFB}\x{8CFC}' - . '\x{8CFD}\x{8D04}\x{8D05}\x{8D07}\x{8D08}\x{8D0A}\x{8D0B}\x{8D0D}\x{8D0F}' - . '\x{8D10}\x{8D13}\x{8D14}\x{8D16}\x{8D64}\x{8D66}\x{8D67}\x{8D6B}\x{8D6D}' - . '\x{8D70}\x{8D71}\x{8D73}\x{8D74}\x{8D77}\x{8D81}\x{8D85}\x{8D8A}\x{8D99}' - . '\x{8DA3}\x{8DA8}\x{8DB3}\x{8DBA}\x{8DBE}\x{8DC2}\x{8DCB}\x{8DCC}\x{8DCF}' - . '\x{8DD6}\x{8DDA}\x{8DDB}\x{8DDD}\x{8DDF}\x{8DE1}\x{8DE3}\x{8DE8}\x{8DEA}' - . '\x{8DEB}\x{8DEF}\x{8DF3}\x{8DF5}\x{8DFC}\x{8DFF}\x{8E08}\x{8E09}\x{8E0A}' - . '\x{8E0F}\x{8E10}\x{8E1D}\x{8E1E}\x{8E1F}\x{8E2A}\x{8E30}\x{8E34}\x{8E35}' - . '\x{8E42}\x{8E44}\x{8E47}\x{8E48}\x{8E49}\x{8E4A}\x{8E4C}\x{8E50}\x{8E55}' - . '\x{8E59}\x{8E5F}\x{8E60}\x{8E63}\x{8E64}\x{8E72}\x{8E74}\x{8E76}\x{8E7C}' - . '\x{8E81}\x{8E84}\x{8E85}\x{8E87}\x{8E8A}\x{8E8B}\x{8E8D}\x{8E91}\x{8E93}' - . '\x{8E94}\x{8E99}\x{8EA1}\x{8EAA}\x{8EAB}\x{8EAC}\x{8EAF}\x{8EB0}\x{8EB1}' - . '\x{8EBE}\x{8EC5}\x{8EC6}\x{8EC8}\x{8ECA}\x{8ECB}\x{8ECC}\x{8ECD}\x{8ED2}' - . '\x{8EDB}\x{8EDF}\x{8EE2}\x{8EE3}\x{8EEB}\x{8EF8}\x{8EFB}\x{8EFC}\x{8EFD}' - . '\x{8EFE}\x{8F03}\x{8F05}\x{8F09}\x{8F0A}\x{8F0C}\x{8F12}\x{8F13}\x{8F14}' - . '\x{8F15}\x{8F19}\x{8F1B}\x{8F1C}\x{8F1D}\x{8F1F}\x{8F26}\x{8F29}\x{8F2A}' - . '\x{8F2F}\x{8F33}\x{8F38}\x{8F39}\x{8F3B}\x{8F3E}\x{8F3F}\x{8F42}\x{8F44}' - . '\x{8F45}\x{8F46}\x{8F49}\x{8F4C}\x{8F4D}\x{8F4E}\x{8F57}\x{8F5C}\x{8F5F}' - . '\x{8F61}\x{8F62}\x{8F63}\x{8F64}\x{8F9B}\x{8F9C}\x{8F9E}\x{8F9F}\x{8FA3}' - . '\x{8FA7}\x{8FA8}\x{8FAD}\x{8FAE}\x{8FAF}\x{8FB0}\x{8FB1}\x{8FB2}\x{8FB7}' - . '\x{8FBA}\x{8FBB}\x{8FBC}\x{8FBF}\x{8FC2}\x{8FC4}\x{8FC5}\x{8FCE}\x{8FD1}' - . '\x{8FD4}\x{8FDA}\x{8FE2}\x{8FE5}\x{8FE6}\x{8FE9}\x{8FEA}\x{8FEB}\x{8FED}' - . '\x{8FEF}\x{8FF0}\x{8FF4}\x{8FF7}\x{8FF8}\x{8FF9}\x{8FFA}\x{8FFD}\x{9000}' - . '\x{9001}\x{9003}\x{9005}\x{9006}\x{900B}\x{900D}\x{900E}\x{900F}\x{9010}' - . '\x{9011}\x{9013}\x{9014}\x{9015}\x{9016}\x{9017}\x{9019}\x{901A}\x{901D}' - . '\x{901E}\x{901F}\x{9020}\x{9021}\x{9022}\x{9023}\x{9027}\x{902E}\x{9031}' - . '\x{9032}\x{9035}\x{9036}\x{9038}\x{9039}\x{903C}\x{903E}\x{9041}\x{9042}' - . '\x{9045}\x{9047}\x{9049}\x{904A}\x{904B}\x{904D}\x{904E}\x{904F}\x{9050}' - . '\x{9051}\x{9052}\x{9053}\x{9054}\x{9055}\x{9056}\x{9058}\x{9059}\x{905C}' - . '\x{905E}\x{9060}\x{9061}\x{9063}\x{9065}\x{9068}\x{9069}\x{906D}\x{906E}' - . '\x{906F}\x{9072}\x{9075}\x{9076}\x{9077}\x{9078}\x{907A}\x{907C}\x{907D}' - . '\x{907F}\x{9080}\x{9081}\x{9082}\x{9083}\x{9084}\x{9087}\x{9089}\x{908A}' - . '\x{908F}\x{9091}\x{90A3}\x{90A6}\x{90A8}\x{90AA}\x{90AF}\x{90B1}\x{90B5}' - . '\x{90B8}\x{90C1}\x{90CA}\x{90CE}\x{90DB}\x{90E1}\x{90E2}\x{90E4}\x{90E8}' - . '\x{90ED}\x{90F5}\x{90F7}\x{90FD}\x{9102}\x{9112}\x{9119}\x{912D}\x{9130}' - . '\x{9132}\x{9149}\x{914A}\x{914B}\x{914C}\x{914D}\x{914E}\x{9152}\x{9154}' - . '\x{9156}\x{9158}\x{9162}\x{9163}\x{9165}\x{9169}\x{916A}\x{916C}\x{9172}' - . '\x{9173}\x{9175}\x{9177}\x{9178}\x{9182}\x{9187}\x{9189}\x{918B}\x{918D}' - . '\x{9190}\x{9192}\x{9197}\x{919C}\x{91A2}\x{91A4}\x{91AA}\x{91AB}\x{91AF}' - . '\x{91B4}\x{91B5}\x{91B8}\x{91BA}\x{91C0}\x{91C1}\x{91C6}\x{91C7}\x{91C8}' - . '\x{91C9}\x{91CB}\x{91CC}\x{91CD}\x{91CE}\x{91CF}\x{91D0}\x{91D1}\x{91D6}' - . '\x{91D8}\x{91DB}\x{91DC}\x{91DD}\x{91DF}\x{91E1}\x{91E3}\x{91E6}\x{91E7}' - . '\x{91F5}\x{91F6}\x{91FC}\x{91FF}\x{920D}\x{920E}\x{9211}\x{9214}\x{9215}' - . '\x{921E}\x{9229}\x{922C}\x{9234}\x{9237}\x{923F}\x{9244}\x{9245}\x{9248}' - . '\x{9249}\x{924B}\x{9250}\x{9257}\x{925A}\x{925B}\x{925E}\x{9262}\x{9264}' - . '\x{9266}\x{9271}\x{927E}\x{9280}\x{9283}\x{9285}\x{9291}\x{9293}\x{9295}' - . '\x{9296}\x{9298}\x{929A}\x{929B}\x{929C}\x{92AD}\x{92B7}\x{92B9}\x{92CF}' - . '\x{92D2}\x{92E4}\x{92E9}\x{92EA}\x{92ED}\x{92F2}\x{92F3}\x{92F8}\x{92FA}' - . '\x{92FC}\x{9306}\x{930F}\x{9310}\x{9318}\x{9319}\x{931A}\x{9320}\x{9322}' - . '\x{9323}\x{9326}\x{9328}\x{932B}\x{932C}\x{932E}\x{932F}\x{9332}\x{9335}' - . '\x{933A}\x{933B}\x{9344}\x{934B}\x{934D}\x{9354}\x{9356}\x{935B}\x{935C}' - . '\x{9360}\x{936C}\x{936E}\x{9375}\x{937C}\x{937E}\x{938C}\x{9394}\x{9396}' - . '\x{9397}\x{939A}\x{93A7}\x{93AC}\x{93AD}\x{93AE}\x{93B0}\x{93B9}\x{93C3}' - . '\x{93C8}\x{93D0}\x{93D1}\x{93D6}\x{93D7}\x{93D8}\x{93DD}\x{93E1}\x{93E4}' - . '\x{93E5}\x{93E8}\x{9403}\x{9407}\x{9410}\x{9413}\x{9414}\x{9418}\x{9419}' - . '\x{941A}\x{9421}\x{942B}\x{9435}\x{9436}\x{9438}\x{943A}\x{9441}\x{9444}' - . '\x{9451}\x{9452}\x{9453}\x{945A}\x{945B}\x{945E}\x{9460}\x{9462}\x{946A}' - . '\x{9470}\x{9475}\x{9477}\x{947C}\x{947D}\x{947E}\x{947F}\x{9481}\x{9577}' - . '\x{9580}\x{9582}\x{9583}\x{9587}\x{9589}\x{958A}\x{958B}\x{958F}\x{9591}' - . '\x{9593}\x{9594}\x{9596}\x{9598}\x{9599}\x{95A0}\x{95A2}\x{95A3}\x{95A4}' - . '\x{95A5}\x{95A7}\x{95A8}\x{95AD}\x{95B2}\x{95B9}\x{95BB}\x{95BC}\x{95BE}' - . '\x{95C3}\x{95C7}\x{95CA}\x{95CC}\x{95CD}\x{95D4}\x{95D5}\x{95D6}\x{95D8}' - . '\x{95DC}\x{95E1}\x{95E2}\x{95E5}\x{961C}\x{9621}\x{9628}\x{962A}\x{962E}' - . '\x{962F}\x{9632}\x{963B}\x{963F}\x{9640}\x{9642}\x{9644}\x{964B}\x{964C}' - . '\x{964D}\x{964F}\x{9650}\x{965B}\x{965C}\x{965D}\x{965E}\x{965F}\x{9662}' - . '\x{9663}\x{9664}\x{9665}\x{9666}\x{966A}\x{966C}\x{9670}\x{9672}\x{9673}' - . '\x{9675}\x{9676}\x{9677}\x{9678}\x{967A}\x{967D}\x{9685}\x{9686}\x{9688}' - . '\x{968A}\x{968B}\x{968D}\x{968E}\x{968F}\x{9694}\x{9695}\x{9697}\x{9698}' - . '\x{9699}\x{969B}\x{969C}\x{96A0}\x{96A3}\x{96A7}\x{96A8}\x{96AA}\x{96B0}' - . '\x{96B1}\x{96B2}\x{96B4}\x{96B6}\x{96B7}\x{96B8}\x{96B9}\x{96BB}\x{96BC}' - . '\x{96C0}\x{96C1}\x{96C4}\x{96C5}\x{96C6}\x{96C7}\x{96C9}\x{96CB}\x{96CC}' - . '\x{96CD}\x{96CE}\x{96D1}\x{96D5}\x{96D6}\x{96D9}\x{96DB}\x{96DC}\x{96E2}' - . '\x{96E3}\x{96E8}\x{96EA}\x{96EB}\x{96F0}\x{96F2}\x{96F6}\x{96F7}\x{96F9}' - . '\x{96FB}\x{9700}\x{9704}\x{9706}\x{9707}\x{9708}\x{970A}\x{970D}\x{970E}' - . '\x{970F}\x{9711}\x{9713}\x{9716}\x{9719}\x{971C}\x{971E}\x{9724}\x{9727}' - . '\x{972A}\x{9730}\x{9732}\x{9738}\x{9739}\x{973D}\x{973E}\x{9742}\x{9744}' - . '\x{9746}\x{9748}\x{9749}\x{9752}\x{9756}\x{9759}\x{975C}\x{975E}\x{9760}' - . '\x{9761}\x{9762}\x{9764}\x{9766}\x{9768}\x{9769}\x{976B}\x{976D}\x{9771}' - . '\x{9774}\x{9779}\x{977A}\x{977C}\x{9781}\x{9784}\x{9785}\x{9786}\x{978B}' - . '\x{978D}\x{978F}\x{9790}\x{9798}\x{979C}\x{97A0}\x{97A3}\x{97A6}\x{97A8}' - . '\x{97AB}\x{97AD}\x{97B3}\x{97B4}\x{97C3}\x{97C6}\x{97C8}\x{97CB}\x{97D3}' - . '\x{97DC}\x{97ED}\x{97EE}\x{97F2}\x{97F3}\x{97F5}\x{97F6}\x{97FB}\x{97FF}' - . '\x{9801}\x{9802}\x{9803}\x{9805}\x{9806}\x{9808}\x{980C}\x{980F}\x{9810}' - . '\x{9811}\x{9812}\x{9813}\x{9817}\x{9818}\x{981A}\x{9821}\x{9824}\x{982C}' - . '\x{982D}\x{9834}\x{9837}\x{9838}\x{983B}\x{983C}\x{983D}\x{9846}\x{984B}' - . '\x{984C}\x{984D}\x{984E}\x{984F}\x{9854}\x{9855}\x{9858}\x{985B}\x{985E}' - . '\x{9867}\x{986B}\x{986F}\x{9870}\x{9871}\x{9873}\x{9874}\x{98A8}\x{98AA}' - . '\x{98AF}\x{98B1}\x{98B6}\x{98C3}\x{98C4}\x{98C6}\x{98DB}\x{98DC}\x{98DF}' - . '\x{98E2}\x{98E9}\x{98EB}\x{98ED}\x{98EE}\x{98EF}\x{98F2}\x{98F4}\x{98FC}' - . '\x{98FD}\x{98FE}\x{9903}\x{9905}\x{9909}\x{990A}\x{990C}\x{9910}\x{9912}' - . '\x{9913}\x{9914}\x{9918}\x{991D}\x{991E}\x{9920}\x{9921}\x{9924}\x{9928}' - . '\x{992C}\x{992E}\x{993D}\x{993E}\x{9942}\x{9945}\x{9949}\x{994B}\x{994C}' - . '\x{9950}\x{9951}\x{9952}\x{9955}\x{9957}\x{9996}\x{9997}\x{9998}\x{9999}' - . '\x{99A5}\x{99A8}\x{99AC}\x{99AD}\x{99AE}\x{99B3}\x{99B4}\x{99BC}\x{99C1}' - . '\x{99C4}\x{99C5}\x{99C6}\x{99C8}\x{99D0}\x{99D1}\x{99D2}\x{99D5}\x{99D8}' - . '\x{99DB}\x{99DD}\x{99DF}\x{99E2}\x{99ED}\x{99EE}\x{99F1}\x{99F2}\x{99F8}' - . '\x{99FB}\x{99FF}\x{9A01}\x{9A05}\x{9A0E}\x{9A0F}\x{9A12}\x{9A13}\x{9A19}' - . '\x{9A28}\x{9A2B}\x{9A30}\x{9A37}\x{9A3E}\x{9A40}\x{9A42}\x{9A43}\x{9A45}' - . '\x{9A4D}\x{9A55}\x{9A57}\x{9A5A}\x{9A5B}\x{9A5F}\x{9A62}\x{9A64}\x{9A65}' - . '\x{9A69}\x{9A6A}\x{9A6B}\x{9AA8}\x{9AAD}\x{9AB0}\x{9AB8}\x{9ABC}\x{9AC0}' - . '\x{9AC4}\x{9ACF}\x{9AD1}\x{9AD3}\x{9AD4}\x{9AD8}\x{9ADE}\x{9ADF}\x{9AE2}' - . '\x{9AE3}\x{9AE6}\x{9AEA}\x{9AEB}\x{9AED}\x{9AEE}\x{9AEF}\x{9AF1}\x{9AF4}' - . '\x{9AF7}\x{9AFB}\x{9B06}\x{9B18}\x{9B1A}\x{9B1F}\x{9B22}\x{9B23}\x{9B25}' - . '\x{9B27}\x{9B28}\x{9B29}\x{9B2A}\x{9B2E}\x{9B2F}\x{9B31}\x{9B32}\x{9B3B}' - . '\x{9B3C}\x{9B41}\x{9B42}\x{9B43}\x{9B44}\x{9B45}\x{9B4D}\x{9B4E}\x{9B4F}' - . '\x{9B51}\x{9B54}\x{9B58}\x{9B5A}\x{9B6F}\x{9B74}\x{9B83}\x{9B8E}\x{9B91}' - . '\x{9B92}\x{9B93}\x{9B96}\x{9B97}\x{9B9F}\x{9BA0}\x{9BA8}\x{9BAA}\x{9BAB}' - . '\x{9BAD}\x{9BAE}\x{9BB4}\x{9BB9}\x{9BC0}\x{9BC6}\x{9BC9}\x{9BCA}\x{9BCF}' - . '\x{9BD1}\x{9BD2}\x{9BD4}\x{9BD6}\x{9BDB}\x{9BE1}\x{9BE2}\x{9BE3}\x{9BE4}' - . '\x{9BE8}\x{9BF0}\x{9BF1}\x{9BF2}\x{9BF5}\x{9C04}\x{9C06}\x{9C08}\x{9C09}' - . '\x{9C0A}\x{9C0C}\x{9C0D}\x{9C10}\x{9C12}\x{9C13}\x{9C14}\x{9C15}\x{9C1B}' - . '\x{9C21}\x{9C24}\x{9C25}\x{9C2D}\x{9C2E}\x{9C2F}\x{9C30}\x{9C32}\x{9C39}' - . '\x{9C3A}\x{9C3B}\x{9C3E}\x{9C46}\x{9C47}\x{9C48}\x{9C52}\x{9C57}\x{9C5A}' - . '\x{9C60}\x{9C67}\x{9C76}\x{9C78}\x{9CE5}\x{9CE7}\x{9CE9}\x{9CEB}\x{9CEC}' - . '\x{9CF0}\x{9CF3}\x{9CF4}\x{9CF6}\x{9D03}\x{9D06}\x{9D07}\x{9D08}\x{9D09}' - . '\x{9D0E}\x{9D12}\x{9D15}\x{9D1B}\x{9D1F}\x{9D23}\x{9D26}\x{9D28}\x{9D2A}' - . '\x{9D2B}\x{9D2C}\x{9D3B}\x{9D3E}\x{9D3F}\x{9D41}\x{9D44}\x{9D46}\x{9D48}' - . '\x{9D50}\x{9D51}\x{9D59}\x{9D5C}\x{9D5D}\x{9D5E}\x{9D60}\x{9D61}\x{9D64}' - . '\x{9D6C}\x{9D6F}\x{9D72}\x{9D7A}\x{9D87}\x{9D89}\x{9D8F}\x{9D9A}\x{9DA4}' - . '\x{9DA9}\x{9DAB}\x{9DAF}\x{9DB2}\x{9DB4}\x{9DB8}\x{9DBA}\x{9DBB}\x{9DC1}' - . '\x{9DC2}\x{9DC4}\x{9DC6}\x{9DCF}\x{9DD3}\x{9DD9}\x{9DE6}\x{9DED}\x{9DEF}' - . '\x{9DF2}\x{9DF8}\x{9DF9}\x{9DFA}\x{9DFD}\x{9E1A}\x{9E1B}\x{9E1E}\x{9E75}' - . '\x{9E78}\x{9E79}\x{9E7D}\x{9E7F}\x{9E81}\x{9E88}\x{9E8B}\x{9E8C}\x{9E91}' - . '\x{9E92}\x{9E93}\x{9E95}\x{9E97}\x{9E9D}\x{9E9F}\x{9EA5}\x{9EA6}\x{9EA9}' - . '\x{9EAA}\x{9EAD}\x{9EB8}\x{9EB9}\x{9EBA}\x{9EBB}\x{9EBC}\x{9EBE}\x{9EBF}' - . '\x{9EC4}\x{9ECC}\x{9ECD}\x{9ECE}\x{9ECF}\x{9ED0}\x{9ED2}\x{9ED4}\x{9ED8}' - . '\x{9ED9}\x{9EDB}\x{9EDC}\x{9EDD}\x{9EDE}\x{9EE0}\x{9EE5}\x{9EE8}\x{9EEF}' - . '\x{9EF4}\x{9EF6}\x{9EF7}\x{9EF9}\x{9EFB}\x{9EFC}\x{9EFD}\x{9F07}\x{9F08}' - . '\x{9F0E}\x{9F13}\x{9F15}\x{9F20}\x{9F21}\x{9F2C}\x{9F3B}\x{9F3E}\x{9F4A}' - . '\x{9F4B}\x{9F4E}\x{9F4F}\x{9F52}\x{9F54}\x{9F5F}\x{9F60}\x{9F61}\x{9F62}' - . '\x{9F63}\x{9F66}\x{9F67}\x{9F6A}\x{9F6C}\x{9F72}\x{9F76}\x{9F77}\x{9F8D}' - . '\x{9F95}\x{9F9C}\x{9F9D}\x{9FA0}]{1,15}$/iu', -]; diff --git a/lib/laminas/laminas-validator/src/Iban.php b/lib/laminas/laminas-validator/src/Iban.php deleted file mode 100644 index 65f23054f..000000000 --- a/lib/laminas/laminas-validator/src/Iban.php +++ /dev/null @@ -1,364 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use Laminas\Stdlib\ArrayUtils; -use Traversable; - -use function array_key_exists; -use function in_array; -use function intval; -use function is_string; -use function preg_match; -use function str_replace; -use function strlen; -use function strtoupper; -use function substr; - -/** - * Validates IBAN Numbers (International Bank Account Numbers) - */ -class Iban extends AbstractValidator -{ - public const NOTSUPPORTED = 'ibanNotSupported'; - public const SEPANOTSUPPORTED = 'ibanSepaNotSupported'; - public const FALSEFORMAT = 'ibanFalseFormat'; - public const CHECKFAILED = 'ibanCheckFailed'; - - /** - * Validation failure message template definitions - * - * @var array<string, string> - */ - protected $messageTemplates = [ - self::NOTSUPPORTED => 'Unknown country within the IBAN', - self::SEPANOTSUPPORTED => 'Countries outside the Single Euro Payments Area (SEPA) are not supported', - self::FALSEFORMAT => 'The input has a false IBAN format', - self::CHECKFAILED => 'The input has failed the IBAN check', - ]; - - /** - * Optional country code by ISO 3166-1 - * - * @var string|null - */ - protected $countryCode; - - /** - * Optionally allow IBAN codes from non-SEPA countries. Defaults to true - * - * @var bool - */ - protected $allowNonSepa = true; - - /** - * The SEPA country codes - * - * @var string[] ISO 3166-1 codes - */ - protected static $sepaCountries = [ - 'AT', - 'BE', - 'BG', - 'CY', - 'CZ', - 'DK', - 'FO', - 'GL', - 'EE', - 'FI', - 'FR', - 'DE', - 'GI', - 'GR', - 'HU', - 'IS', - 'IE', - 'IT', - 'LV', - 'LI', - 'LT', - 'LU', - 'MT', - 'MC', - 'NL', - 'NO', - 'PL', - 'PT', - 'RO', - 'SK', - 'SI', - 'ES', - 'SE', - 'CH', - 'GB', - 'SM', - 'HR', - ]; - - /** - * IBAN regexes by country code - * - * @var array - */ - protected static $ibanRegex = [ - 'AD' => 'AD[0-9]{2}[0-9]{4}[0-9]{4}[A-Z0-9]{12}', - 'AE' => 'AE[0-9]{2}[0-9]{3}[0-9]{16}', - 'AL' => 'AL[0-9]{2}[0-9]{8}[A-Z0-9]{16}', - 'AT' => 'AT[0-9]{2}[0-9]{5}[0-9]{11}', - 'AZ' => 'AZ[0-9]{2}[A-Z]{4}[A-Z0-9]{20}', - 'BA' => 'BA[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{8}[0-9]{2}', - 'BE' => 'BE[0-9]{2}[0-9]{3}[0-9]{7}[0-9]{2}', - 'BG' => 'BG[0-9]{2}[A-Z]{4}[0-9]{4}[0-9]{2}[A-Z0-9]{8}', - 'BH' => 'BH[0-9]{2}[A-Z]{4}[A-Z0-9]{14}', - 'BR' => 'BR[0-9]{2}[0-9]{8}[0-9]{5}[0-9]{10}[A-Z][A-Z0-9]', - 'BY' => 'BY[0-9]{2}[A-Z0-9]{4}[0-9]{4}[A-Z0-9]{16}', - 'CH' => 'CH[0-9]{2}[0-9]{5}[A-Z0-9]{12}', - 'CR' => 'CR[0-9]{2}[0-9]{3}[0-9]{14}', - 'CY' => 'CY[0-9]{2}[0-9]{3}[0-9]{5}[A-Z0-9]{16}', - 'CZ' => 'CZ[0-9]{2}[0-9]{20}', - 'DE' => 'DE[0-9]{2}[0-9]{8}[0-9]{10}', - 'DO' => 'DO[0-9]{2}[A-Z0-9]{4}[0-9]{20}', - 'DK' => 'DK[0-9]{2}[0-9]{14}', - 'EE' => 'EE[0-9]{2}[0-9]{2}[0-9]{2}[0-9]{11}[0-9]{1}', - 'ES' => 'ES[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{1}[0-9]{1}[0-9]{10}', - 'FI' => 'FI[0-9]{2}[0-9]{6}[0-9]{7}[0-9]{1}', - 'FO' => 'FO[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}', - 'FR' => 'FR[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}', - 'GB' => 'GB[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}', - 'GE' => 'GE[0-9]{2}[A-Z]{2}[0-9]{16}', - 'GI' => 'GI[0-9]{2}[A-Z]{4}[A-Z0-9]{15}', - 'GL' => 'GL[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}', - 'GR' => 'GR[0-9]{2}[0-9]{3}[0-9]{4}[A-Z0-9]{16}', - 'GT' => 'GT[0-9]{2}[A-Z0-9]{4}[A-Z0-9]{20}', - 'HR' => 'HR[0-9]{2}[0-9]{7}[0-9]{10}', - 'HU' => 'HU[0-9]{2}[0-9]{3}[0-9]{4}[0-9]{1}[0-9]{15}[0-9]{1}', - 'IE' => 'IE[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}', - 'IL' => 'IL[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{13}', - 'IS' => 'IS[0-9]{2}[0-9]{4}[0-9]{2}[0-9]{6}[0-9]{10}', - 'IT' => 'IT[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}', - 'KW' => 'KW[0-9]{2}[A-Z]{4}[0-9]{22}', - 'KZ' => 'KZ[0-9]{2}[0-9]{3}[A-Z0-9]{13}', - 'LB' => 'LB[0-9]{2}[0-9]{4}[A-Z0-9]{20}', - 'LI' => 'LI[0-9]{2}[0-9]{5}[A-Z0-9]{12}', - 'LT' => 'LT[0-9]{2}[0-9]{5}[0-9]{11}', - 'LU' => 'LU[0-9]{2}[0-9]{3}[A-Z0-9]{13}', - 'LV' => 'LV[0-9]{2}[A-Z]{4}[A-Z0-9]{13}', - 'MC' => 'MC[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}', - 'MD' => 'MD[0-9]{2}[A-Z0-9]{20}', - 'ME' => 'ME[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', - 'MK' => 'MK[0-9]{2}[0-9]{3}[A-Z0-9]{10}[0-9]{2}', - 'MR' => 'MR13[0-9]{5}[0-9]{5}[0-9]{11}[0-9]{2}', - 'MT' => 'MT[0-9]{2}[A-Z]{4}[0-9]{5}[A-Z0-9]{18}', - 'MU' => 'MU[0-9]{2}[A-Z]{4}[0-9]{2}[0-9]{2}[0-9]{12}[0-9]{3}[A-Z]{3}', - 'NL' => 'NL[0-9]{2}[A-Z]{4}[0-9]{10}', - 'NO' => 'NO[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{1}', - 'UA' => 'UA[0-9]{2}[0-9]{6}[0-9]{19}', - 'PK' => 'PK[0-9]{2}[A-Z]{4}[A-Z0-9]{16}', - 'PL' => 'PL[0-9]{2}[0-9]{8}[0-9]{16}', - 'PS' => 'PS[0-9]{2}[A-Z]{4}[A-Z0-9]{21}', - 'PT' => 'PT[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{11}[0-9]{2}', - 'RO' => 'RO[0-9]{2}[A-Z]{4}[A-Z0-9]{16}', - 'RS' => 'RS[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', - 'SA' => 'SA[0-9]{2}[0-9]{2}[A-Z0-9]{18}', - 'SE' => 'SE[0-9]{2}[0-9]{3}[0-9]{16}[0-9]{1}', - 'SI' => 'SI[0-9]{2}[0-9]{5}[0-9]{8}[0-9]{2}', - 'SK' => 'SK[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{10}', - 'SM' => 'SM[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}', - 'TN' => 'TN59[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', - 'TR' => 'TR[0-9]{2}[0-9]{5}[A-Z0-9]{1}[A-Z0-9]{16}', - 'VG' => 'VG[0-9]{2}[A-Z]{4}[0-9]{16}', - ]; - - /** - * Sets validator options - * - * @param array|Traversable $options OPTIONAL - */ - public function __construct($options = []) - { - if ($options instanceof Traversable) { - $options = ArrayUtils::iteratorToArray($options); - } - - if (array_key_exists('country_code', $options)) { - $this->setCountryCode($options['country_code']); - } - - if (array_key_exists('allow_non_sepa', $options)) { - $this->setAllowNonSepa($options['allow_non_sepa']); - } - - parent::__construct($options); - } - - /** - * Returns the optional country code by ISO 3166-1 - * - * @return string|null - */ - public function getCountryCode() - { - return $this->countryCode; - } - - /** - * Sets an optional country code by ISO 3166-1 - * - * @param string|null $countryCode - * @return $this provides a fluent interface - * @throws Exception\InvalidArgumentException - */ - public function setCountryCode($countryCode = null) - { - if ($countryCode !== null) { - $countryCode = (string) $countryCode; - - if (! isset(static::$ibanRegex[$countryCode])) { - throw new Exception\InvalidArgumentException( - "Country code '{$countryCode}' invalid by ISO 3166-1 or not supported" - ); - } - } - - $this->countryCode = $countryCode; - return $this; - } - - /** - * Returns the optional allow non-sepa countries setting - * - * @return bool - */ - public function allowNonSepa() - { - return $this->allowNonSepa; - } - - /** - * Sets the optional allow non-sepa countries setting - * - * @param bool $allowNonSepa - * @return $this provides a fluent interface - */ - public function setAllowNonSepa($allowNonSepa) - { - $this->allowNonSepa = (bool) $allowNonSepa; - return $this; - } - - /** - * Returns true if $value is a valid IBAN - * - * @param string $value - * @return bool - */ - public function isValid($value) - { - if (! is_string($value)) { - $this->error(self::FALSEFORMAT); - return false; - } - - $value = str_replace(' ', '', strtoupper($value)); - $this->setValue($value); - - $countryCode = $this->getCountryCode(); - if ($countryCode === null) { - $countryCode = substr($value, 0, 2); - } - - if (! array_key_exists($countryCode, static::$ibanRegex)) { - $this->setValue($countryCode); - $this->error(self::NOTSUPPORTED); - return false; - } - - if (! $this->allowNonSepa && ! in_array($countryCode, static::$sepaCountries)) { - $this->setValue($countryCode); - $this->error(self::SEPANOTSUPPORTED); - return false; - } - - if (! preg_match('/^' . static::$ibanRegex[$countryCode] . '$/', $value)) { - $this->error(self::FALSEFORMAT); - return false; - } - - $format = substr($value, 4) . substr($value, 0, 4); - $format = str_replace( - [ - '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', - ], - [ - '10', - '11', - '12', - '13', - '14', - '15', - '16', - '17', - '18', - '19', - '20', - '21', - '22', - '23', - '24', - '25', - '26', - '27', - '28', - '29', - '30', - '31', - '32', - '33', - '34', - '35', - ], - $format - ); - - $temp = intval(substr($format, 0, 1)); - $len = strlen($format); - for ($x = 1; $x < $len; ++$x) { - $temp *= 10; - $temp += intval(substr($format, $x, 1)); - $temp %= 97; - } - - if ($temp !== 1) { - $this->error(self::CHECKFAILED); - return false; - } - - return true; - } -} diff --git a/lib/laminas/laminas-validator/src/Identical.php b/lib/laminas/laminas-validator/src/Identical.php deleted file mode 100644 index 4bf3c358c..000000000 --- a/lib/laminas/laminas-validator/src/Identical.php +++ /dev/null @@ -1,221 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use ArrayAccess; -use Laminas\Stdlib\ArrayUtils; -use Traversable; - -use function array_key_exists; -use function get_class; -use function gettype; -use function is_array; -use function is_int; -use function is_object; -use function is_string; -use function key; -use function sprintf; -use function var_export; - -class Identical extends AbstractValidator -{ - /** - * Error codes - * - * @const string - */ - public const NOT_SAME = 'notSame'; - public const MISSING_TOKEN = 'missingToken'; - - /** - * Error messages - * - * @var array - */ - protected $messageTemplates = [ - self::NOT_SAME => 'The two given tokens do not match', - self::MISSING_TOKEN => 'No token was provided to match against', - ]; - - /** @var array */ - protected $messageVariables = [ - 'token' => 'tokenString', - ]; - - /** - * Original token against which to validate - * - * @var null|string - */ - protected $tokenString; - - /** @var null|string */ - protected $token; - - /** @var bool */ - protected $strict = true; - - /** @var bool */ - protected $literal = false; - - /** - * Sets validator options - * - * @param mixed $token - */ - public function __construct($token = null) - { - if ($token instanceof Traversable) { - $token = ArrayUtils::iteratorToArray($token); - } - - if (is_array($token) && array_key_exists('token', $token)) { - if (array_key_exists('strict', $token)) { - $this->setStrict($token['strict']); - } - - if (array_key_exists('literal', $token)) { - $this->setLiteral($token['literal']); - } - - $this->setToken($token['token']); - } elseif (null !== $token) { - $this->setToken($token); - } - - parent::__construct(is_array($token) ? $token : null); - } - - /** - * Retrieve token - * - * @return mixed - */ - public function getToken() - { - return $this->token; - } - - /** - * Set token against which to compare - * - * @param mixed $token - * @return $this - */ - public function setToken($token) - { - $this->tokenString = is_array($token) ? var_export($token, true) : (string) $token; - $this->token = $token; - return $this; - } - - /** - * Returns the strict parameter - * - * @return bool - */ - public function getStrict() - { - return $this->strict; - } - - /** - * Sets the strict parameter - * - * @param bool $strict - * @return $this - */ - public function setStrict($strict) - { - $this->strict = (bool) $strict; - return $this; - } - - /** - * Returns the literal parameter - * - * @return bool - */ - public function getLiteral() - { - return $this->literal; - } - - /** - * Sets the literal parameter - * - * @param bool $literal - * @return $this - */ - public function setLiteral($literal) - { - $this->literal = (bool) $literal; - return $this; - } - - /** - * Returns true if and only if a token has been set and the provided value - * matches that token. - * - * @param mixed $value - * @param null|array|ArrayAccess $context - * @throws Exception\InvalidArgumentException If context is not array or ArrayObject. - * @return bool - */ - public function isValid($value, $context = null) - { - $this->setValue($value); - - $token = $this->getToken(); - - if (! $this->getLiteral() && $context !== null) { - if (! is_array($context) && ! $context instanceof ArrayAccess) { - throw new Exception\InvalidArgumentException(sprintf( - 'Context passed to %s must be array, ArrayObject or null; received "%s"', - __METHOD__, - is_object($context) ? get_class($context) : gettype($context) - )); - } - - if (is_array($token)) { - while (is_array($token)) { - $key = key($token); - if (! isset($context[$key])) { - break; - } - $context = $context[$key]; - $token = $token[$key]; - } - } - - // if $token is an array it means the above loop didn't went all the way down to the leaf, - // so the $token structure doesn't match the $context structure - if ( - is_array($token) - || (! is_int($token) && ! is_string($token)) - || ! isset($context[$token]) - ) { - $token = $this->getToken(); - } else { - $token = $context[$token]; - } - } - - if ($token === null) { - $this->error(self::MISSING_TOKEN); - return false; - } - - $strict = $this->getStrict(); - if ( - ($strict && ($value !== $token)) - // phpcs:ignore SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedNotEqualOperator - || (! $strict && ($value != $token)) - ) { - $this->error(self::NOT_SAME); - return false; - } - - return true; - } -} diff --git a/lib/laminas/laminas-validator/src/InArray.php b/lib/laminas/laminas-validator/src/InArray.php deleted file mode 100644 index e1289c4cc..000000000 --- a/lib/laminas/laminas-validator/src/InArray.php +++ /dev/null @@ -1,253 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use RecursiveArrayIterator; -use RecursiveIteratorIterator; - -use function in_array; -use function is_bool; -use function is_float; -use function is_int; -use function is_string; - -class InArray extends AbstractValidator -{ - public const NOT_IN_ARRAY = 'notInArray'; - - // Type of Strict check - /** - * standard in_array strict checking value and type - */ - public const COMPARE_STRICT = 1; - - /** - * Non strict check but prevents "asdf" == 0 returning TRUE causing false/positive. - * This is the most secure option for non-strict checks and replaces strict = false - * This will only be effective when the input is a string - */ - public const COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY = 0; - - /** - * Standard non-strict check where "asdf" == 0 returns TRUE - * This will be wanted when comparing "0" against int 0 - */ - public const COMPARE_NOT_STRICT = -1; - - /** @var array<string, string> */ - protected $messageTemplates = [ - self::NOT_IN_ARRAY => 'The input was not found in the haystack', - ]; - - /** - * Haystack of possible values - * - * @var array - */ - protected $haystack; - - /** - * Type of strict check to be used. Due to "foo" == 0 === TRUE with in_array when strict = false, - * an option has been added to prevent this. When $strict = 0/false, the most - * secure non-strict check is implemented. if $strict = -1, the default in_array non-strict - * behaviour is used - * - * @var int - */ - protected $strict = self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY; - - /** - * Whether a recursive search should be done - * - * @var bool - */ - protected $recursive = false; - - /** - * Returns the haystack option - * - * @return mixed - * @throws Exception\RuntimeException If haystack option is not set. - */ - public function getHaystack() - { - if ($this->haystack === null) { - throw new Exception\RuntimeException('haystack option is mandatory'); - } - return $this->haystack; - } - - /** - * Sets the haystack option - * - * @param mixed $haystack - * @return $this Provides a fluent interface - */ - public function setHaystack(array $haystack) - { - $this->haystack = $haystack; - return $this; - } - - /** - * Returns the strict option - * - * @return bool|int - */ - public function getStrict() - { - // To keep BC with new strict modes - if ( - $this->strict === self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY - || $this->strict === self::COMPARE_STRICT - ) { - return (bool) $this->strict; - } - return $this->strict; - } - - /** - * Sets the strict option mode - * InArray::COMPARE_STRICT - * InArray::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY - * InArray::COMPARE_NOT_STRICT - * - * @param int|bool $strict - * @return $this Provides a fluent interface - * @throws Exception\InvalidArgumentException - */ - public function setStrict($strict) - { - if (is_bool($strict)) { - $strict = $strict ? self::COMPARE_STRICT : self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY; - } - - $checkTypes = [ - self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY, // 0 - self::COMPARE_STRICT, // 1 - self::COMPARE_NOT_STRICT, // -1 - ]; - - // validate strict value - if (! in_array($strict, $checkTypes)) { - throw new Exception\InvalidArgumentException('Strict option must be one of the COMPARE_ constants'); - } - - $this->strict = $strict; - return $this; - } - - /** - * Returns the recursive option - * - * @return bool - */ - public function getRecursive() - { - return $this->recursive; - } - - /** - * Sets the recursive option - * - * @param bool $recursive - * @return $this Provides a fluent interface - */ - public function setRecursive($recursive) - { - $this->recursive = (bool) $recursive; - return $this; - } - - /** - * Returns true if and only if $value is contained in the haystack option. If the strict - * option is true, then the type of $value is also checked. - * - * @param mixed $value - * See {@link http://php.net/manual/function.in-array.php#104501} - * @return bool - */ - public function isValid($value) - { - // we create a copy of the haystack in case we need to modify it - $haystack = $this->getHaystack(); - - // if the input is a string or float, and vulnerability protection is on - // we type cast the input to a string - if ( - self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY === $this->strict - && (is_int($value) || is_float($value)) - ) { - $value = (string) $value; - } - - $this->setValue($value); - - if ($this->getRecursive()) { - $iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($haystack)); - foreach ($iterator as $element) { - if (self::COMPARE_STRICT === $this->strict) { - if ($element === $value) { - return true; - } - - continue; - } - - // add protection to prevent string to int vuln's - $el = $element; - if ( - self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY === $this->strict - && is_string($value) && (is_int($el) || is_float($el)) - ) { - $el = (string) $el; - } - - // phpcs:ignore SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedEqualOperator - if ($el == $value) { - return true; - } - } - - $this->error(self::NOT_IN_ARRAY); - return false; - } - - /** - * If the check is not strict, then, to prevent "asdf" being converted to 0 - * and returning a false positive if 0 is in haystack, we type cast - * the haystack to strings. To prevent "56asdf" == 56 === TRUE we also - * type cast values like 56 to strings as well. - * - * This occurs only if the input is a string and a haystack member is an int - */ - if ( - self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY === $this->strict - && is_string($value) - ) { - foreach ($haystack as &$h) { - if (is_int($h) || is_float($h)) { - $h = (string) $h; - } - } - - if (in_array($value, $haystack, (bool) $this->strict)) { - return true; - } - - $this->error(self::NOT_IN_ARRAY); - return false; - } - - if (in_array($value, $haystack, self::COMPARE_STRICT === $this->strict)) { - return true; - } - - if (self::COMPARE_NOT_STRICT === $this->strict) { - return true; - } - - $this->error(self::NOT_IN_ARRAY); - return false; - } -} diff --git a/lib/laminas/laminas-validator/src/Ip.php b/lib/laminas/laminas-validator/src/Ip.php deleted file mode 100644 index 969faa5ef..000000000 --- a/lib/laminas/laminas-validator/src/Ip.php +++ /dev/null @@ -1,193 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use Traversable; - -use function bindec; -use function hexdec; -use function ip2long; -use function is_string; -use function long2ip; -use function preg_match; -use function strlen; -use function strpos; -use function strrpos; -use function substr; -use function substr_count; - -class Ip extends AbstractValidator -{ - public const INVALID = 'ipInvalid'; - public const NOT_IP_ADDRESS = 'notIpAddress'; - - /** @var array */ - protected $messageTemplates = [ - self::INVALID => 'Invalid type given. String expected', - self::NOT_IP_ADDRESS => 'The input does not appear to be a valid IP address', - ]; - - /** - * Internal options - * - * @var array - */ - protected $options = [ - 'allowipv4' => true, // Enable IPv4 Validation - 'allowipv6' => true, // Enable IPv6 Validation - 'allowipvfuture' => false, // Enable IPvFuture Validation - 'allowliteral' => true, // Enable IPs in literal format (only IPv6 and IPvFuture) - ]; - - /** - * Sets the options for this validator - * - * @param array|Traversable $options - * @throws Exception\InvalidArgumentException If there is any kind of IP allowed or $options is not an array - * or Traversable. - * @return AbstractValidator - */ - public function setOptions($options = []) - { - parent::setOptions($options); - - if (! $this->options['allowipv4'] && ! $this->options['allowipv6'] && ! $this->options['allowipvfuture']) { - throw new Exception\InvalidArgumentException('Nothing to validate. Check your options'); - } - - return $this; - } - - /** - * Returns true if and only if $value is a valid IP address - * - * @param mixed $value - * @return bool - */ - public function isValid($value) - { - if (! is_string($value)) { - $this->error(self::INVALID); - return false; - } - - $this->setValue($value); - - if ($this->options['allowipv4'] && $this->validateIPv4($value)) { - return true; - } else { - if ((bool) $this->options['allowliteral']) { - static $regex = '/^\[(.*)\]$/'; - if ((bool) preg_match($regex, $value, $matches)) { - $value = $matches[1]; - } - } - - if ( - ($this->options['allowipv6'] && $this->validateIPv6($value)) || - ($this->options['allowipvfuture'] && $this->validateIPvFuture($value)) - ) { - return true; - } - } - $this->error(self::NOT_IP_ADDRESS); - return false; - } - - /** - * Validates an IPv4 address - * - * @param string $value - * @return bool - */ - protected function validateIPv4($value) - { - if (preg_match('/^([01]{8}\.){3}[01]{8}\z/i', $value)) { - // binary format 00000000.00000000.00000000.00000000 - $value = bindec(substr($value, 0, 8)) . '.' . bindec(substr($value, 9, 8)) . '.' - . bindec(substr($value, 18, 8)) . '.' . bindec(substr($value, 27, 8)); - } elseif (preg_match('/^([0-9]{3}\.){3}[0-9]{3}\z/i', $value)) { - // octet format 777.777.777.777 - $value = (int) substr($value, 0, 3) . '.' . (int) substr($value, 4, 3) . '.' - . (int) substr($value, 8, 3) . '.' . (int) substr($value, 12, 3); - } elseif (preg_match('/^([0-9a-f]{2}\.){3}[0-9a-f]{2}\z/i', $value)) { - // hex format ff.ff.ff.ff - $value = hexdec(substr($value, 0, 2)) . '.' . hexdec(substr($value, 3, 2)) . '.' - . hexdec(substr($value, 6, 2)) . '.' . hexdec(substr($value, 9, 2)); - } - - $ip2long = ip2long($value); - if ($ip2long === false) { - return false; - } - - return $value === long2ip($ip2long); - } - - /** - * Validates an IPv6 address - * - * @param string $value Value to check against - * @return bool|int True when $value is a valid ipv6 address False otherwise - */ - protected function validateIPv6($value) - { - if (strlen($value) < 3) { - return $value === '::'; - } - - if (strpos($value, '.')) { - $lastcolon = strrpos($value, ':'); - if (! ($lastcolon && $this->validateIPv4(substr($value, $lastcolon + 1)))) { - return false; - } - - $value = substr($value, 0, $lastcolon) . ':0:0'; - } - - if (strpos($value, '::') === false) { - return preg_match('/\A(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}\z/i', $value); - } - - $colonCount = substr_count($value, ':'); - if ($colonCount < 8) { - return preg_match('/\A(?::|(?:[a-f0-9]{1,4}:)+):(?:(?:[a-f0-9]{1,4}:)*[a-f0-9]{1,4})?\z/i', $value); - } - - // special case with ending or starting double colon - if ($colonCount === 8) { - return preg_match('/\A(?:::)?(?:[a-f0-9]{1,4}:){6}[a-f0-9]{1,4}(?:::)?\z/i', $value); - } - - return false; - } - - /** - * Validates an IPvFuture address. - * - * IPvFuture is loosely defined in the Section 3.2.2 of RFC 3986 - * - * @param string $value Value to check against - * @return bool True when $value is a valid IPvFuture address - * False otherwise - */ - protected function validateIPvFuture($value) - { - /* - * ABNF: - * IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" ) - * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," - * / ";" / "=" - */ - static $regex = '/^v([[:xdigit:]]+)\.[[:alnum:]\-\._~!\$&\'\(\)\*\+,;=:]+$/'; - - $result = (bool) preg_match($regex, $value, $matches); - - /* - * "As such, implementations must not provide the version flag for the - * existing IPv4 and IPv6 literal address forms described below." - */ - return $result && $matches[1] !== '4' && $matches[1] !== '6'; - } -} diff --git a/lib/laminas/laminas-validator/src/IsCountable.php b/lib/laminas/laminas-validator/src/IsCountable.php deleted file mode 100644 index e62ad6556..000000000 --- a/lib/laminas/laminas-validator/src/IsCountable.php +++ /dev/null @@ -1,203 +0,0 @@ -<?php // phpcs:disable SlevomatCodingStandard.Classes.UnusedPrivateElements.UnusedMethod - -namespace Laminas\Validator; - -use Traversable; - -use function count; -use function is_array; -use function is_countable; -use function is_numeric; -use function sprintf; -use function ucfirst; - -/** - * Validate that a value is countable and the count meets expectations. - * - * The validator has five specific behaviors: - * - * - You can determine if a value is countable only - * - You can test if the value is an exact count - * - You can test if the value is greater than a minimum count value - * - You can test if the value is greater than a maximum count value - * - You can test if the value is between the minimum and maximum count values - * - * When creating the instance or calling `setOptions()`, if you specify a - * "count" option, specifying either "min" or "max" leads to an inconsistent - * state and, as such will raise an Exception\InvalidArgumentException. - */ -class IsCountable extends AbstractValidator -{ - public const NOT_COUNTABLE = 'notCountable'; - public const NOT_EQUALS = 'notEquals'; - public const GREATER_THAN = 'greaterThan'; - public const LESS_THAN = 'lessThan'; - - /** - * Validation failure message template definitions - * - * @var array - */ - protected $messageTemplates = [ - self::NOT_COUNTABLE => 'The input must be an array or an instance of \\Countable', - self::NOT_EQUALS => "The input count must equal '%count%'", - self::GREATER_THAN => "The input count must be less than '%max%', inclusively", - self::LESS_THAN => "The input count must be greater than '%min%', inclusively", - ]; - - /** - * Additional variables available for validation failure messages - * - * @var array - */ - protected $messageVariables = [ - 'count' => ['options' => 'count'], - 'min' => ['options' => 'min'], - 'max' => ['options' => 'max'], - ]; - - /** - * Options for the between validator - * - * @var array - */ - protected $options = [ - 'count' => null, - 'min' => null, - 'max' => null, - ]; - - /** - * @param array|Traversable $options - * @return $this Provides fluid interface - */ - public function setOptions($options = []) - { - foreach (['count', 'min', 'max'] as $option) { - if (! is_array($options) || ! isset($options[$option])) { - continue; - } - - $method = sprintf('set%s', ucfirst($option)); - $this->$method($options[$option]); - unset($options[$option]); - } - - return parent::setOptions($options); - } - - /** - * Returns true if and only if $value is countable (and the count validates against optional values). - * - * @param iterable $value - * @return bool - */ - public function isValid($value) - { - if (! is_countable($value)) { - $this->error(self::NOT_COUNTABLE); - return false; - } - - $count = count($value); - - if (is_numeric($this->getCount())) { - if ($count !== $this->getCount()) { - $this->error(self::NOT_EQUALS); - return false; - } - - return true; - } - - if (is_numeric($this->getMax()) && $count > $this->getMax()) { - $this->error(self::GREATER_THAN); - return false; - } - - if (is_numeric($this->getMin()) && $count < $this->getMin()) { - $this->error(self::LESS_THAN); - return false; - } - - return true; - } - - /** - * Returns the count option - * - * @return mixed - */ - public function getCount() - { - return $this->options['count']; - } - - /** - * Returns the min option - * - * @return mixed - */ - public function getMin() - { - return $this->options['min']; - } - - /** - * Returns the max option - * - * @return mixed - */ - public function getMax() - { - return $this->options['max']; - } - - /** - * @param mixed $value - * @return void - * @throws Exception\InvalidArgumentException If either a min or max option - * was previously set. - */ - private function setCount($value) - { - if (isset($this->options['min']) || isset($this->options['max'])) { - throw new Exception\InvalidArgumentException( - 'Cannot set count; conflicts with either a min or max option previously set' - ); - } - $this->options['count'] = $value; - } - - /** - * @param mixed $value - * @return void - * @throws Exception\InvalidArgumentException If either a count or max option - * was previously set. - */ - private function setMin($value) - { - if (isset($this->options['count'])) { - throw new Exception\InvalidArgumentException( - 'Cannot set count; conflicts with either a count option previously set' - ); - } - $this->options['min'] = $value; - } - - /** - * @param mixed $value - * @return void - * @throws Exception\InvalidArgumentException If either a count or min option - * was previously set. - */ - private function setMax($value) - { - if (isset($this->options['count'])) { - throw new Exception\InvalidArgumentException( - 'Cannot set count; conflicts with either a count option previously set' - ); - } - $this->options['max'] = $value; - } -} diff --git a/lib/laminas/laminas-validator/src/IsInstanceOf.php b/lib/laminas/laminas-validator/src/IsInstanceOf.php deleted file mode 100644 index e6009afb3..000000000 --- a/lib/laminas/laminas-validator/src/IsInstanceOf.php +++ /dev/null @@ -1,103 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use Traversable; - -use function array_key_exists; -use function array_shift; -use function func_get_args; -use function is_array; -use function iterator_to_array; - -class IsInstanceOf extends AbstractValidator -{ - public const NOT_INSTANCE_OF = 'notInstanceOf'; - - /** - * Validation failure message template definitions - * - * @var array - */ - protected $messageTemplates = [ - self::NOT_INSTANCE_OF => "The input is not an instance of '%className%'", - ]; - - /** - * Additional variables available for validation failure messages - * - * @var array - */ - protected $messageVariables = [ - 'className' => 'className', - ]; - - /** @var string */ - protected $className; - - /** - * Sets validator options - * - * @param array|Traversable $options - * @throws Exception\InvalidArgumentException - */ - public function __construct($options = null) - { - if ($options instanceof Traversable) { - $options = iterator_to_array($options); - } - - // If argument is not an array, consider first argument as class name - if (! is_array($options)) { - $options = func_get_args(); - - $tmpOptions = []; - $tmpOptions['className'] = array_shift($options); - - $options = $tmpOptions; - } - - if (! array_key_exists('className', $options)) { - throw new Exception\InvalidArgumentException('Missing option "className"'); - } - - parent::__construct($options); - } - - /** - * Get class name - * - * @return string - */ - public function getClassName() - { - return $this->className; - } - - /** - * Set class name - * - * @param string $className - * @return $this - */ - public function setClassName($className) - { - $this->className = $className; - return $this; - } - - /** - * Returns true if $value is instance of $this->className - * - * @param mixed $value - * @return bool - */ - public function isValid($value) - { - if ($value instanceof $this->className) { - return true; - } - $this->error(self::NOT_INSTANCE_OF); - return false; - } -} diff --git a/lib/laminas/laminas-validator/src/Isbn.php b/lib/laminas/laminas-validator/src/Isbn.php deleted file mode 100644 index d5d11876b..000000000 --- a/lib/laminas/laminas-validator/src/Isbn.php +++ /dev/null @@ -1,189 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use function in_array; -use function is_int; -use function is_string; -use function preg_match; -use function quotemeta; -use function str_replace; -use function strlen; -use function substr; - -class Isbn extends AbstractValidator -{ - public const AUTO = 'auto'; - public const ISBN10 = '10'; - public const ISBN13 = '13'; - public const INVALID = 'isbnInvalid'; - public const NO_ISBN = 'isbnNoIsbn'; - - /** - * Validation failure message template definitions. - * - * @var array - */ - protected $messageTemplates = [ - self::INVALID => 'Invalid type given. String or integer expected', - self::NO_ISBN => 'The input is not a valid ISBN number', - ]; - - /** @var array<string, mixed> */ - protected $options = [ - 'type' => self::AUTO, // Allowed type - 'separator' => '', // Separator character - ]; - - /** - * Detect input format. - * - * @return null|string - */ - protected function detectFormat() - { - // prepare separator and pattern list - $sep = quotemeta($this->getSeparator()); - $patterns = []; - $lengths = []; - $type = $this->getType(); - - // check for ISBN-10 - if ($type === self::ISBN10 || $type === self::AUTO) { - if (empty($sep)) { - $pattern = '/^[0-9]{9}[0-9X]{1}$/'; - $length = 10; - } else { - $pattern = "/^[0-9]{1,7}[{$sep}]{1}[0-9]{1,7}[{$sep}]{1}[0-9]{1,7}[{$sep}]{1}[0-9X]{1}$/"; - $length = 13; - } - - $patterns[$pattern] = self::ISBN10; - $lengths[$pattern] = $length; - } - - // check for ISBN-13 - if ($type === self::ISBN13 || $type === self::AUTO) { - if (empty($sep)) { - $pattern = '/^[0-9]{13}$/'; - $length = 13; - } else { - // @codingStandardsIgnoreStart - $pattern = "/^[0-9]{1,9}[{$sep}]{1}[0-9]{1,5}[{$sep}]{1}[0-9]{1,9}[{$sep}]{1}[0-9]{1,9}[{$sep}]{1}[0-9]{1}$/"; - // @codingStandardsIgnoreEnd - $length = 17; - } - - $patterns[$pattern] = self::ISBN13; - $lengths[$pattern] = $length; - } - - // check pattern list - foreach ($patterns as $pattern => $type) { - if ((strlen($this->getValue()) === $lengths[$pattern]) && preg_match($pattern, $this->getValue())) { - return $type; - } - } - - return null; - } - - /** - * Returns true if and only if $value is a valid ISBN. - * - * @param string $value - * @return bool - */ - public function isValid($value) - { - if (! is_string($value) && ! is_int($value)) { - $this->error(self::INVALID); - return false; - } - - $value = (string) $value; - $this->setValue($value); - - switch ($this->detectFormat()) { - case self::ISBN10: - $isbn = new Isbn\Isbn10(); - break; - - case self::ISBN13: - $isbn = new Isbn\Isbn13(); - break; - - default: - $this->error(self::NO_ISBN); - return false; - } - - $value = str_replace($this->getSeparator(), '', $value); - $checksum = $isbn->getChecksum($value); - - // validate - if (substr($this->getValue(), -1) !== (string) $checksum) { - $this->error(self::NO_ISBN); - return false; - } - return true; - } - - /** - * Set separator characters. - * - * It is allowed only empty string, hyphen and space. - * - * @param string $separator - * @throws Exception\InvalidArgumentException When $separator is not valid. - * @return $this Provides a fluent interface - */ - public function setSeparator($separator) - { - // check separator - if (! in_array($separator, ['-', ' ', ''])) { - throw new Exception\InvalidArgumentException('Invalid ISBN separator.'); - } - - $this->options['separator'] = $separator; - return $this; - } - - /** - * Get separator characters. - * - * @return string - */ - public function getSeparator() - { - return $this->options['separator']; - } - - /** - * Set allowed ISBN type. - * - * @param string $type - * @throws Exception\InvalidArgumentException When $type is not valid. - * @return $this Provides a fluent interface - */ - public function setType($type) - { - // check type - if (! in_array($type, [self::AUTO, self::ISBN10, self::ISBN13])) { - throw new Exception\InvalidArgumentException('Invalid ISBN type'); - } - - $this->options['type'] = $type; - return $this; - } - - /** - * Get allowed ISBN type. - * - * @return string - */ - public function getType() - { - return $this->options['type']; - } -} diff --git a/lib/laminas/laminas-validator/src/Isbn/Isbn10.php b/lib/laminas/laminas-validator/src/Isbn/Isbn10.php deleted file mode 100755 index 4bcc6570d..000000000 --- a/lib/laminas/laminas-validator/src/Isbn/Isbn10.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php - -namespace Laminas\Validator\Isbn; - -class Isbn10 -{ - /** - * @param string $value - * @return int|string - */ - public function getChecksum($value) - { - $sum = $this->sum($value); - return $this->checksum($sum); - } - - /** - * Calculate the value sum. - * - * @param string $value - * @return int - */ - private function sum($value) - { - $sum = 0; - - for ($i = 0; $i < 9; $i++) { - $sum += (10 - $i) * (int) $value[$i]; - } - - return $sum; - } - - /** - * Calculate the checksum for the value's sum. - * - * @param int $sum - * @return int|string - */ - private function checksum($sum) - { - $checksum = 11 - ($sum % 11); - - if ($checksum === 11) { - return '0'; - } - - if ($checksum === 10) { - return 'X'; - } - - return $checksum; - } -} diff --git a/lib/laminas/laminas-validator/src/Isbn/Isbn13.php b/lib/laminas/laminas-validator/src/Isbn/Isbn13.php deleted file mode 100755 index c5aaf494e..000000000 --- a/lib/laminas/laminas-validator/src/Isbn/Isbn13.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php - -namespace Laminas\Validator\Isbn; - -class Isbn13 -{ - /** - * @param string $value - * @return int|string - */ - public function getChecksum($value) - { - $sum = $this->sum($value); - return $this->checksum($sum); - } - - /** - * Calculate the value sum. - * - * @param string $value - * @return int - */ - private function sum($value) - { - $sum = 0; - - for ($i = 0; $i < 12; $i++) { - if ($i % 2 === 0) { - $sum += (int) $value[$i]; - continue; - } - - $sum += 3 * (int) $value[$i]; - } - - return $sum; - } - - /** - * Calculate the checksum for the value's sum. - * - * @param int $sum - * @return int|string - */ - private function checksum($sum) - { - $checksum = 10 - ($sum % 10); - - if ($checksum === 10) { - return '0'; - } - - return $checksum; - } -} diff --git a/lib/laminas/laminas-validator/src/LessThan.php b/lib/laminas/laminas-validator/src/LessThan.php deleted file mode 100644 index c2a6fccc9..000000000 --- a/lib/laminas/laminas-validator/src/LessThan.php +++ /dev/null @@ -1,159 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use Laminas\Stdlib\ArrayUtils; -use Traversable; - -use function array_key_exists; -use function array_shift; -use function func_get_args; -use function is_array; - -class LessThan extends AbstractValidator -{ - public const NOT_LESS = 'notLessThan'; - public const NOT_LESS_INCLUSIVE = 'notLessThanInclusive'; - - /** - * Validation failure message template definitions - * - * @var array - */ - protected $messageTemplates = [ - self::NOT_LESS => "The input is not less than '%max%'", - self::NOT_LESS_INCLUSIVE => "The input is not less or equal than '%max%'", - ]; - - /** - * Additional variables available for validation failure messages - * - * @var array - */ - protected $messageVariables = [ - 'max' => 'max', - ]; - - /** - * Maximum value - * - * @var mixed - */ - protected $max; - - /** - * Whether to do inclusive comparisons, allowing equivalence to max - * - * If false, then strict comparisons are done, and the value may equal - * the max option - * - * @var bool - */ - protected $inclusive; - - /** - * Sets validator options - * - * @param array|Traversable $options - * @throws Exception\InvalidArgumentException - */ - public function __construct($options = null) - { - if ($options instanceof Traversable) { - $options = ArrayUtils::iteratorToArray($options); - } - if (! is_array($options)) { - $options = func_get_args(); - $temp['max'] = array_shift($options); - - if (! empty($options)) { - $temp['inclusive'] = array_shift($options); - } - - $options = $temp; - } - - if (! array_key_exists('max', $options)) { - throw new Exception\InvalidArgumentException("Missing option 'max'"); - } - - if (! array_key_exists('inclusive', $options)) { - $options['inclusive'] = false; - } - - $this->setMax($options['max']) - ->setInclusive($options['inclusive']); - - parent::__construct($options); - } - - /** - * Returns the max option - * - * @return mixed - */ - public function getMax() - { - return $this->max; - } - - /** - * Sets the max option - * - * @param mixed $max - * @return $this Provides a fluent interface - */ - public function setMax($max) - { - $this->max = $max; - return $this; - } - - /** - * Returns the inclusive option - * - * @return bool - */ - public function getInclusive() - { - return $this->inclusive; - } - - /** - * Sets the inclusive option - * - * @param bool $inclusive - * @return $this Provides a fluent interface - */ - public function setInclusive($inclusive) - { - $this->inclusive = $inclusive; - return $this; - } - - /** - * Returns true if and only if $value is less than max option, inclusively - * when the inclusive option is true - * - * @param mixed $value - * @return bool - */ - public function isValid($value) - { - $this->setValue($value); - - if ($this->inclusive) { - if ($value > $this->max) { - $this->error(self::NOT_LESS_INCLUSIVE); - return false; - } - } else { - if ($value >= $this->max) { - $this->error(self::NOT_LESS); - return false; - } - } - - return true; - } -} diff --git a/lib/laminas/laminas-validator/src/Module.php b/lib/laminas/laminas-validator/src/Module.php deleted file mode 100644 index d95016ee6..000000000 --- a/lib/laminas/laminas-validator/src/Module.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use Laminas\ModuleManager\ModuleManager; - -class Module -{ - /** - * Return default laminas-validator configuration for laminas-mvc applications. - * - * @return array[] - * @psalm-return array{service_manager: array} - */ - public function getConfig() - { - $provider = new ConfigProvider(); - - return [ - 'service_manager' => $provider->getDependencyConfig(), - ]; - } - - /** - * Register a specification for the ValidatorManager with the ServiceListener. - * - * @param ModuleManager $moduleManager - * @return void - */ - public function init($moduleManager) - { - $event = $moduleManager->getEvent(); - $container = $event->getParam('ServiceManager'); - $serviceListener = $container->get('ServiceListener'); - - $serviceListener->addServiceManager( - 'ValidatorManager', - 'validators', - ValidatorProviderInterface::class, - 'getValidatorConfig' - ); - } -} diff --git a/lib/laminas/laminas-validator/src/NotEmpty.php b/lib/laminas/laminas-validator/src/NotEmpty.php deleted file mode 100644 index b342974f7..000000000 --- a/lib/laminas/laminas-validator/src/NotEmpty.php +++ /dev/null @@ -1,306 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use Countable; -use Laminas\Stdlib\ArrayUtils; -use Traversable; - -use function array_search; -use function array_shift; -use function count; -use function func_get_args; -use function in_array; -use function is_array; -use function is_bool; -use function is_float; -use function is_int; -use function is_object; -use function is_string; -use function method_exists; -use function preg_match; - -class NotEmpty extends AbstractValidator -{ - public const BOOLEAN = 0b000000000001; - public const INTEGER = 0b000000000010; - public const FLOAT = 0b000000000100; - public const STRING = 0b000000001000; - public const ZERO = 0b000000010000; - public const EMPTY_ARRAY = 0b000000100000; - public const NULL = 0b000001000000; - public const PHP = 0b000001111111; - public const SPACE = 0b000010000000; - public const OBJECT = 0b000100000000; - public const OBJECT_STRING = 0b001000000000; - public const OBJECT_COUNT = 0b010000000000; - public const ALL = 0b011111111111; - - public const INVALID = 'notEmptyInvalid'; - public const IS_EMPTY = 'isEmpty'; - - /** @var array<int, string> */ - protected $constants = [ - self::BOOLEAN => 'boolean', - self::INTEGER => 'integer', - self::FLOAT => 'float', - self::STRING => 'string', - self::ZERO => 'zero', - self::EMPTY_ARRAY => 'array', - self::NULL => 'null', - self::PHP => 'php', - self::SPACE => 'space', - self::OBJECT => 'object', - self::OBJECT_STRING => 'objectstring', - self::OBJECT_COUNT => 'objectcount', - self::ALL => 'all', - ]; - - /** - * Default value for types; value = 0b000111101001 - * - * @var array - */ - protected $defaultType = [ - self::OBJECT, - self::SPACE, - self::NULL, - self::EMPTY_ARRAY, - self::STRING, - self::BOOLEAN, - ]; - - /** @var array */ - protected $messageTemplates = [ - self::IS_EMPTY => "Value is required and can't be empty", - self::INVALID => 'Invalid type given. String, integer, float, boolean or array expected', - ]; - - /** - * Options for this validator - * - * @var array - */ - protected $options = []; - - /** - * Constructor - * - * @param array|Traversable|int $options OPTIONAL - */ - public function __construct($options = null) - { - if ($options instanceof Traversable) { - $options = ArrayUtils::iteratorToArray($options); - } - - if (! is_array($options)) { - $options = func_get_args(); - $temp = []; - if (! empty($options)) { - $temp['type'] = array_shift($options); - } - - $options = $temp; - } - - if (! isset($options['type'])) { - if (($type = $this->calculateTypeValue($options)) !== 0) { - $options['type'] = $type; - } else { - $options['type'] = $this->defaultType; - } - } - - parent::__construct($options); - } - - /** - * Returns the set types - * - * @return int - */ - public function getType() - { - return $this->options['type']; - } - - /** - * @return false|int|string - */ - public function getDefaultType() - { - return $this->calculateTypeValue($this->defaultType); - } - - /** - * @param array|int|string $type - * @return false|int|string - */ - protected function calculateTypeValue($type) - { - if (is_array($type)) { - $detected = 0; - foreach ($type as $value) { - if (is_int($value)) { - $detected |= $value; - } elseif (in_array($value, $this->constants, true)) { - $detected |= (int) array_search($value, $this->constants, true); - } - } - - $type = $detected; - } elseif (is_string($type) && in_array($type, $this->constants, true)) { - $type = array_search($type, $this->constants, true); - } - - return $type; - } - - /** - * Set the types - * - * @param int|int[] $type - * @throws Exception\InvalidArgumentException - * @return $this - */ - public function setType($type = null) - { - $type = $this->calculateTypeValue($type); - - if (! is_int($type) || ($type < 0) || ($type > self::ALL)) { - throw new Exception\InvalidArgumentException('Unknown type'); - } - - $this->options['type'] = $type; - - return $this; - } - - /** - * Returns true if and only if $value is not an empty value. - * - * @param mixed $value - * @return bool - */ - public function isValid($value) - { - if ( - $value !== null - && ! is_string($value) - && ! is_int($value) - && ! is_float($value) - && ! is_bool($value) - && ! is_array($value) - && ! is_object($value) - ) { - $this->error(self::INVALID); - return false; - } - - $type = $this->getType(); - $this->setValue($value); - $object = false; - - // OBJECT_COUNT (countable object) - if ($type & self::OBJECT_COUNT) { - $object = true; - - if (is_object($value) && $value instanceof Countable && (count($value) === 0)) { - $this->error(self::IS_EMPTY); - return false; - } - } - - // OBJECT_STRING (object's toString) - if ($type & self::OBJECT_STRING) { - $object = true; - - if ( - (is_object($value) && ! method_exists($value, '__toString')) - || (is_object($value) && method_exists($value, '__toString') && (string) $value === '') - ) { - $this->error(self::IS_EMPTY); - return false; - } - } - - // OBJECT (object) - // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedIf - if ($type & self::OBJECT) { - // fall through, objects are always not empty - } elseif ($object === false) { - // object not allowed but object given -> return false - if (is_object($value)) { - $this->error(self::IS_EMPTY); - return false; - } - } - - // SPACE (' ') - if ($type & self::SPACE) { - if (is_string($value) && (preg_match('/^\s+$/s', $value))) { - $this->error(self::IS_EMPTY); - return false; - } - } - - // NULL (null) - if ($type & self::NULL) { - if ($value === null) { - $this->error(self::IS_EMPTY); - return false; - } - } - - // EMPTY_ARRAY (array()) - if ($type & self::EMPTY_ARRAY) { - if ($value === []) { - $this->error(self::IS_EMPTY); - return false; - } - } - - // ZERO ('0') - if ($type & self::ZERO) { - if ($value === '0') { - $this->error(self::IS_EMPTY); - return false; - } - } - - // STRING ('') - if ($type & self::STRING) { - if ($value === '') { - $this->error(self::IS_EMPTY); - return false; - } - } - - // FLOAT (0.0) - if ($type & self::FLOAT) { - if ($value === 0.0) { - $this->error(self::IS_EMPTY); - return false; - } - } - - // INTEGER (0) - if ($type & self::INTEGER) { - if ($value === 0) { - $this->error(self::IS_EMPTY); - return false; - } - } - - // BOOLEAN (false) - if ($type & self::BOOLEAN) { - if ($value === false) { - $this->error(self::IS_EMPTY); - return false; - } - } - - return true; - } -} diff --git a/lib/laminas/laminas-validator/src/Regex.php b/lib/laminas/laminas-validator/src/Regex.php deleted file mode 100644 index d022fe3e9..000000000 --- a/lib/laminas/laminas-validator/src/Regex.php +++ /dev/null @@ -1,137 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use Laminas\Stdlib\ArrayUtils; -use Laminas\Stdlib\ErrorHandler; -use Traversable; - -use function array_key_exists; -use function is_array; -use function is_float; -use function is_int; -use function is_string; -use function preg_match; - -class Regex extends AbstractValidator -{ - public const INVALID = 'regexInvalid'; - public const NOT_MATCH = 'regexNotMatch'; - public const ERROROUS = 'regexErrorous'; - - /** @var array */ - protected $messageTemplates = [ - self::INVALID => 'Invalid type given. String, integer or float expected', - self::NOT_MATCH => "The input does not match against pattern '%pattern%'", - self::ERROROUS => "There was an internal error while using the pattern '%pattern%'", - ]; - - /** @var array */ - protected $messageVariables = [ - 'pattern' => 'pattern', - ]; - - /** - * Regular expression pattern - * - * @var string - */ - protected $pattern; - - /** - * Sets validator options - * - * @param string|array|Traversable $pattern - * @throws Exception\InvalidArgumentException On missing 'pattern' parameter. - */ - public function __construct($pattern) - { - if (is_string($pattern)) { - $this->setPattern($pattern); - parent::__construct([]); - return; - } - - if ($pattern instanceof Traversable) { - $pattern = ArrayUtils::iteratorToArray($pattern); - } - - if (! is_array($pattern)) { - throw new Exception\InvalidArgumentException('Invalid options provided to constructor'); - } - - if (! array_key_exists('pattern', $pattern)) { - throw new Exception\InvalidArgumentException("Missing option 'pattern'"); - } - - $this->setPattern($pattern['pattern']); - unset($pattern['pattern']); - parent::__construct($pattern); - } - - /** - * Returns the pattern option - * - * @return string - */ - public function getPattern() - { - return $this->pattern; - } - - /** - * Sets the pattern option - * - * @param string $pattern - * @throws Exception\InvalidArgumentException If there is a fatal error in pattern matching. - * @return $this Provides a fluent interface - */ - public function setPattern($pattern) - { - ErrorHandler::start(); - $this->pattern = (string) $pattern; - $status = preg_match($this->pattern, 'Test'); - $error = ErrorHandler::stop(); - - if (false === $status) { - throw new Exception\InvalidArgumentException( - "Internal error parsing the pattern '{$this->pattern}'", - 0, - $error - ); - } - - return $this; - } - - /** - * Returns true if and only if $value matches against the pattern option - * - * @param string $value - * @return bool - */ - public function isValid($value) - { - if (! is_string($value) && ! is_int($value) && ! is_float($value)) { - $this->error(self::INVALID); - return false; - } - - $this->setValue($value); - - ErrorHandler::start(); - $status = preg_match($this->pattern, $value); - ErrorHandler::stop(); - if (false === $status) { - $this->error(self::ERROROUS); - return false; - } - - if (! $status) { - $this->error(self::NOT_MATCH); - return false; - } - - return true; - } -} diff --git a/lib/laminas/laminas-validator/src/Sitemap/Changefreq.php b/lib/laminas/laminas-validator/src/Sitemap/Changefreq.php deleted file mode 100644 index af1cac18e..000000000 --- a/lib/laminas/laminas-validator/src/Sitemap/Changefreq.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php - -namespace Laminas\Validator\Sitemap; - -use Laminas\Validator\AbstractValidator; - -use function in_array; -use function is_string; - -/** - * Validates whether a given value is valid as a sitemap <changefreq> value - * - * @link http://www.sitemaps.org/protocol.php Sitemaps XML format - */ -class Changefreq extends AbstractValidator -{ - /** - * Validation key for not valid - */ - public const NOT_VALID = 'sitemapChangefreqNotValid'; - public const INVALID = 'sitemapChangefreqInvalid'; - - /** - * Validation failure message template definitions - * - * @var array - */ - protected $messageTemplates = [ - self::NOT_VALID => 'The input is not a valid sitemap changefreq', - self::INVALID => 'Invalid type given. String expected', - ]; - - /** - * Valid change frequencies - * - * @var array - */ - protected $changeFreqs = [ - 'always', - 'hourly', - 'daily', - 'weekly', - 'monthly', - 'yearly', - 'never', - ]; - - /** - * Validates if a string is valid as a sitemap changefreq - * - * @link http://www.sitemaps.org/protocol.php#changefreqdef <changefreq> - * - * @param string $value value to validate - * @return bool - */ - public function isValid($value) - { - if (! is_string($value)) { - $this->error(self::INVALID); - return false; - } - - $this->setValue($value); - - if (! in_array($value, $this->changeFreqs, true)) { - $this->error(self::NOT_VALID); - return false; - } - - return true; - } -} diff --git a/lib/laminas/laminas-validator/src/Sitemap/Lastmod.php b/lib/laminas/laminas-validator/src/Sitemap/Lastmod.php deleted file mode 100644 index 2f6884e4c..000000000 --- a/lib/laminas/laminas-validator/src/Sitemap/Lastmod.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php - -namespace Laminas\Validator\Sitemap; - -use Laminas\Stdlib\ErrorHandler; -use Laminas\Validator\AbstractValidator; - -use function is_string; -use function preg_match; - -/** - * Validates whether a given value is valid as a sitemap <lastmod> value - * - * @link http://www.sitemaps.org/protocol.php Sitemaps XML format - */ -class Lastmod extends AbstractValidator -{ - // phpcs:disable Generic.Files.LineLength.TooLong - - /** - * Regular expression to use when validating - */ - public const LASTMOD_REGEX = '/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])(T([0-1][0-9]|2[0-3])(:[0-5][0-9])(:[0-5][0-9])?(\\+|-)([0-1][0-9]|2[0-3]):[0-5][0-9])?$/'; - - // phpcs:enable - - /** - * Validation key for not valid - */ - public const NOT_VALID = 'sitemapLastmodNotValid'; - public const INVALID = 'sitemapLastmodInvalid'; - - /** - * Validation failure message template definitions - * - * @var array<string, string> - */ - protected $messageTemplates = [ - self::NOT_VALID => 'The input is not a valid sitemap lastmod', - self::INVALID => 'Invalid type given. String expected', - ]; - - /** - * Validates if a string is valid as a sitemap lastmod - * - * @link http://www.sitemaps.org/protocol.php#lastmoddef <lastmod> - * - * @param string $value value to validate - * @return bool - */ - public function isValid($value) - { - if (! is_string($value)) { - $this->error(self::INVALID); - return false; - } - - $this->setValue($value); - ErrorHandler::start(); - $result = preg_match(self::LASTMOD_REGEX, $value); - ErrorHandler::stop(); - if ($result !== 1) { - $this->error(self::NOT_VALID); - return false; - } - - return true; - } -} diff --git a/lib/laminas/laminas-validator/src/Sitemap/Loc.php b/lib/laminas/laminas-validator/src/Sitemap/Loc.php deleted file mode 100644 index 447a92d4d..000000000 --- a/lib/laminas/laminas-validator/src/Sitemap/Loc.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php - -namespace Laminas\Validator\Sitemap; - -use Laminas\Uri; -use Laminas\Validator\AbstractValidator; - -use function is_string; - -/** - * Validates whether a given value is valid as a sitemap <loc> value - * - * @link http://www.sitemaps.org/protocol.php Sitemaps XML format - * @see Laminas\Uri\Uri - */ -class Loc extends AbstractValidator -{ - /** - * Validation key for not valid - */ - public const NOT_VALID = 'sitemapLocNotValid'; - public const INVALID = 'sitemapLocInvalid'; - - /** - * Validation failure message template definitions - * - * @var array - */ - protected $messageTemplates = [ - self::NOT_VALID => 'The input is not a valid sitemap location', - self::INVALID => 'Invalid type given. String expected', - ]; - - /** - * Validates if a string is valid as a sitemap location - * - * @link http://www.sitemaps.org/protocol.php#locdef <loc> - * - * @param string $value value to validate - * @return bool - */ - public function isValid($value) - { - if (! is_string($value)) { - $this->error(self::INVALID); - return false; - } - - $this->setValue($value); - $uri = Uri\UriFactory::factory($value); - if (! $uri->isValid()) { - $this->error(self::NOT_VALID); - return false; - } - - return true; - } -} diff --git a/lib/laminas/laminas-validator/src/Sitemap/Priority.php b/lib/laminas/laminas-validator/src/Sitemap/Priority.php deleted file mode 100644 index 7bf6c02b8..000000000 --- a/lib/laminas/laminas-validator/src/Sitemap/Priority.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php - -namespace Laminas\Validator\Sitemap; - -use Laminas\Validator\AbstractValidator; - -use function is_numeric; - -/** - * Validates whether a given value is valid as a sitemap <priority> value - * - * @link http://www.sitemaps.org/protocol.php Sitemaps XML format - */ -class Priority extends AbstractValidator -{ - /** - * Validation key for not valid - */ - public const NOT_VALID = 'sitemapPriorityNotValid'; - public const INVALID = 'sitemapPriorityInvalid'; - - /** - * Validation failure message template definitions - * - * @var array - */ - protected $messageTemplates = [ - self::NOT_VALID => 'The input is not a valid sitemap priority', - self::INVALID => 'Invalid type given. Numeric string, integer or float expected', - ]; - - /** - * Validates if a string is valid as a sitemap priority - * - * @link http://www.sitemaps.org/protocol.php#prioritydef <priority> - * - * @param string $value value to validate - * @return bool - */ - public function isValid($value) - { - if (! is_numeric($value)) { - $this->error(self::INVALID); - return false; - } - - $this->setValue($value); - $value = (float) $value; - if ($value < 0 || $value > 1) { - $this->error(self::NOT_VALID); - return false; - } - - return true; - } -} diff --git a/lib/laminas/laminas-validator/src/StaticValidator.php b/lib/laminas/laminas-validator/src/StaticValidator.php deleted file mode 100644 index aba395d4a..000000000 --- a/lib/laminas/laminas-validator/src/StaticValidator.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use Laminas\ServiceManager\ServiceManager; - -use function array_values; -use function method_exists; - -class StaticValidator -{ - /** @var ValidatorPluginManager|null */ - protected static $plugins; - - /** - * Set plugin manager to use for locating validators - * - * @return void - */ - public static function setPluginManager(?ValidatorPluginManager $plugins = null) - { - // Don't share by default to allow different arguments on subsequent calls - if ($plugins instanceof ValidatorPluginManager) { - // Vary how the share by default flag is set based on laminas-servicemanager version - if (method_exists($plugins, 'configure')) { - $plugins->configure(['shared_by_default' => false]); - } else { - $plugins->setShareByDefault(false); - } - } - static::$plugins = $plugins; - } - - /** - * Get plugin manager for locating validators - * - * @return ValidatorPluginManager - */ - public static function getPluginManager() - { - if (! static::$plugins instanceof ValidatorPluginManager) { - $plugins = new ValidatorPluginManager(new ServiceManager()); - static::setPluginManager($plugins); - - return $plugins; - } - return static::$plugins; - } - - /** - * @param mixed $value - * @param class-string<ValidatorInterface> $classBaseName - * @param array $options OPTIONAL associative array of options to pass as - * the sole argument to the validator constructor. - * @return bool - * @throws Exception\InvalidArgumentException For an invalid $options argument. - */ - public static function execute($value, $classBaseName, array $options = []) - { - if ($options && array_values($options) === $options) { - throw new Exception\InvalidArgumentException( - 'Invalid options provided via $options argument; must be an associative array' - ); - } - - $plugins = static::getPluginManager(); - - $validator = $plugins->get($classBaseName, $options); - return $validator->isValid($value); - } -} diff --git a/lib/laminas/laminas-validator/src/Step.php b/lib/laminas/laminas-validator/src/Step.php deleted file mode 100644 index 1892f5209..000000000 --- a/lib/laminas/laminas-validator/src/Step.php +++ /dev/null @@ -1,176 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use Traversable; - -use function array_shift; -use function floor; -use function func_get_args; -use function is_array; -use function is_numeric; -use function iterator_to_array; -use function round; -use function strlen; -use function strpos; -use function substr; - -class Step extends AbstractValidator -{ - public const INVALID = 'typeInvalid'; - public const NOT_STEP = 'stepInvalid'; - - /** @var array */ - protected $messageTemplates = [ - self::INVALID => 'Invalid value given. Scalar expected', - self::NOT_STEP => 'The input is not a valid step', - ]; - - /** @var mixed */ - protected $baseValue = 0; - - /** @var mixed */ - protected $step = 1; - - /** - * Set default options for this instance - * - * @param array $options - */ - public function __construct($options = []) - { - if ($options instanceof Traversable) { - $options = iterator_to_array($options); - } elseif (! is_array($options)) { - $options = func_get_args(); - $temp['baseValue'] = array_shift($options); - if (! empty($options)) { - $temp['step'] = array_shift($options); - } - - $options = $temp; - } - - if (isset($options['baseValue'])) { - $this->setBaseValue($options['baseValue']); - } - if (isset($options['step'])) { - $this->setStep($options['step']); - } - - parent::__construct($options); - } - - /** - * Sets the base value from which the step should be computed - * - * @param mixed $baseValue - * @return $this - */ - public function setBaseValue($baseValue) - { - $this->baseValue = $baseValue; - return $this; - } - - /** - * Returns the base value from which the step should be computed - * - * @return string - */ - public function getBaseValue() - { - return $this->baseValue; - } - - /** - * Sets the step value - * - * @param mixed $step - * @return $this - */ - public function setStep($step) - { - $this->step = (float) $step; - return $this; - } - - /** - * Returns the step value - * - * @return string - */ - public function getStep() - { - return $this->step; - } - - /** - * Returns true if $value is a scalar and a valid step value - * - * @param mixed $value - * @return bool - */ - public function isValid($value) - { - if (! is_numeric($value)) { - $this->error(self::INVALID); - return false; - } - - $this->setValue($value); - - $substract = $this->sub($value, $this->baseValue); - - $fmod = $this->fmod($substract, $this->step); - - if ($fmod !== 0.0 && $fmod !== $this->step) { - $this->error(self::NOT_STEP); - return false; - } - - return true; - } - - /** - * replaces the internal fmod function which give wrong results on many cases - * - * @param int|float $x - * @param int|float $y - * @return float - */ - protected function fmod($x, $y) - { - if ($y === 0.0 || $y === 0) { - return 1.0; - } - - //find the maximum precision from both input params to give accurate results - $precision = $this->getPrecision($x) + $this->getPrecision($y); - - return round($x - $y * floor($x / $y), $precision); - } - - /** - * replaces the internal substraction operation which give wrong results on some cases - * - * @param float $x - * @param float $y - * @return float - */ - private function sub($x, $y) - { - $precision = $this->getPrecision($x) + $this->getPrecision($y); - return round($x - $y, $precision); - } - - /** - * @param float $float - * @return int - */ - private function getPrecision($float) - { - $segment = substr($float, strpos($float, '.') + 1); - return $segment ? strlen($segment) : 0; - } -} diff --git a/lib/laminas/laminas-validator/src/StringLength.php b/lib/laminas/laminas-validator/src/StringLength.php deleted file mode 100644 index 64edff34b..000000000 --- a/lib/laminas/laminas-validator/src/StringLength.php +++ /dev/null @@ -1,233 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use Laminas\Stdlib\StringUtils; -use Laminas\Stdlib\StringWrapper\StringWrapperInterface as StringWrapper; -use Laminas\Stdlib\StringWrapper\StringWrapperInterface; -use Traversable; - -use function array_shift; -use function func_get_args; -use function is_array; -use function is_string; -use function max; - -class StringLength extends AbstractValidator -{ - public const INVALID = 'stringLengthInvalid'; - public const TOO_SHORT = 'stringLengthTooShort'; - public const TOO_LONG = 'stringLengthTooLong'; - - /** @var array<string, string> */ - protected $messageTemplates = [ - self::INVALID => 'Invalid type given. String expected', - self::TOO_SHORT => 'The input is less than %min% characters long', - self::TOO_LONG => 'The input is more than %max% characters long', - ]; - - /** @var array<string, array<string, string>> */ - protected $messageVariables = [ - 'min' => ['options' => 'min'], - 'max' => ['options' => 'max'], - 'length' => ['options' => 'length'], - ]; - - /** @var array<string, mixed> */ - protected $options = [ - 'min' => 0, // Minimum length - 'max' => null, // Maximum length, null if there is no length limitation - 'encoding' => 'UTF-8', // Encoding to use - 'length' => 0, // Actual length - ]; - - /** @var null|StringWrapperInterface */ - protected $stringWrapper; - - /** - * Sets validator options - * - * @param int|array|Traversable $options - */ - public function __construct($options = []) - { - if (! is_array($options)) { - $options = func_get_args(); - $temp['min'] = array_shift($options); - if (! empty($options)) { - $temp['max'] = array_shift($options); - } - - if (! empty($options)) { - $temp['encoding'] = array_shift($options); - } - - $options = $temp; - } - - parent::__construct($options); - } - - /** - * Returns the min option - * - * @return int - */ - public function getMin() - { - return $this->options['min']; - } - - /** - * Sets the min option - * - * @param int $min - * @throws Exception\InvalidArgumentException - * @return $this Provides a fluent interface - */ - public function setMin($min) - { - if (null !== $this->getMax() && $min > $this->getMax()) { - throw new Exception\InvalidArgumentException( - "The minimum must be less than or equal to the maximum length, but {$min} > {$this->getMax()}" - ); - } - - $this->options['min'] = max(0, (int) $min); - return $this; - } - - /** - * Returns the max option - * - * @return int|null - */ - public function getMax() - { - return $this->options['max']; - } - - /** - * Sets the max option - * - * @param int|null $max - * @throws Exception\InvalidArgumentException - * @return $this Provides a fluent interface - */ - public function setMax($max) - { - if (null === $max) { - $this->options['max'] = null; - } elseif ($max < $this->getMin()) { - throw new Exception\InvalidArgumentException( - "The maximum must be greater than or equal to the minimum length, but {$max} < {$this->getMin()}" - ); - } else { - $this->options['max'] = (int) $max; - } - - return $this; - } - - /** - * Get the string wrapper to detect the string length - * - * @return StringWrapper - */ - public function getStringWrapper() - { - if (! $this->stringWrapper) { - $this->stringWrapper = StringUtils::getWrapper($this->getEncoding()); - } - return $this->stringWrapper; - } - - /** - * Set the string wrapper to detect the string length - * - * @return void - */ - public function setStringWrapper(StringWrapper $stringWrapper) - { - $stringWrapper->setEncoding($this->getEncoding()); - $this->stringWrapper = $stringWrapper; - } - - /** - * Returns the actual encoding - * - * @return string - */ - public function getEncoding() - { - return $this->options['encoding']; - } - - /** - * Sets a new encoding to use - * - * @param string $encoding - * @return $this - * @throws Exception\InvalidArgumentException - */ - public function setEncoding($encoding) - { - $this->stringWrapper = StringUtils::getWrapper($encoding); - $this->options['encoding'] = $encoding; - return $this; - } - - /** - * Returns the length option - * - * @return int - */ - private function getLength() - { - return $this->options['length']; - } - - /** - * Sets the length option - * - * @param int $length - * @return $this Provides a fluent interface - */ - private function setLength($length) - { - $this->options['length'] = (int) $length; - return $this; - } - - /** - * Returns true if and only if the string length of $value is at least the min option and - * no greater than the max option (when the max option is not null). - * - * @param string $value - * @return bool - */ - public function isValid($value) - { - if (! is_string($value)) { - $this->error(self::INVALID); - return false; - } - - $this->setValue($value); - - $this->setLength($this->getStringWrapper()->strlen($value)); - if ($this->getLength() < $this->getMin()) { - $this->error(self::TOO_SHORT); - } - - if (null !== $this->getMax() && $this->getMax() < $this->getLength()) { - $this->error(self::TOO_LONG); - } - - if ($this->getMessages()) { - return false; - } - - return true; - } -} diff --git a/lib/laminas/laminas-validator/src/Timezone.php b/lib/laminas/laminas-validator/src/Timezone.php deleted file mode 100644 index e262da225..000000000 --- a/lib/laminas/laminas-validator/src/Timezone.php +++ /dev/null @@ -1,173 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use DateTimeZone; - -use function array_key_exists; -use function array_search; -use function get_class; -use function gettype; -use function in_array; -use function is_array; -use function is_int; -use function is_object; -use function is_string; -use function sprintf; - -class Timezone extends AbstractValidator -{ - public const INVALID = 'invalidTimezone'; - public const INVALID_TIMEZONE_LOCATION = 'invalidTimezoneLocation'; - public const INVALID_TIMEZONE_ABBREVIATION = 'invalidTimezoneAbbreviation'; - - public const LOCATION = 0b01; - public const ABBREVIATION = 0b10; - public const ALL = 0b11; - - /** @var array */ - protected $constants = [ - self::LOCATION => 'location', - self::ABBREVIATION => 'abbreviation', - ]; - - /** - * Default value for types; value = 3 - * - * @var array - */ - protected $defaultType = [ - self::LOCATION, - self::ABBREVIATION, - ]; - - /** @var array */ - protected $messageTemplates = [ - self::INVALID => 'Invalid timezone given.', - self::INVALID_TIMEZONE_LOCATION => 'Invalid timezone location given.', - self::INVALID_TIMEZONE_ABBREVIATION => 'Invalid timezone abbreviation given.', - ]; - - /** - * Options for this validator - * - * @var array - */ - protected $options = []; - - /** - * Constructor - * - * @param array|int $options OPTIONAL - */ - public function __construct($options = []) - { - $opts['type'] = $this->defaultType; - - if (is_array($options)) { - if (array_key_exists('type', $options)) { - $opts['type'] = $options['type']; - } - } elseif (! empty($options)) { - $opts['type'] = $options; - } - - // setType called by parent constructor then setOptions method - parent::__construct($opts); - } - - /** - * Set the types - * - * @param int|array $type - * @return void - * @throws Exception\InvalidArgumentException - */ - public function setType($type = null) - { - $type = $this->calculateTypeValue($type); - - if (! is_int($type) || ($type < 1) || ($type > self::ALL)) { - throw new Exception\InvalidArgumentException(sprintf( - 'Unknown type "%s" provided', - is_string($type) || is_int($type) - ? $type - : (is_object($type) ? get_class($type) : gettype($type)) - )); - } - - $this->options['type'] = $type; - } - - /** - * Returns true if timezone location or timezone abbreviations is correct. - * - * @param mixed $value - * @return bool - */ - public function isValid($value) - { - if ($value !== null && ! is_string($value)) { - $this->error(self::INVALID); - return false; - } - - $type = $this->options['type']; - $this->setValue($value); - - switch (true) { - // Check in locations and abbreviations - case ($type & self::LOCATION) && ($type & self::ABBREVIATION): - $abbrs = DateTimeZone::listAbbreviations(); - $locations = DateTimeZone::listIdentifiers(); - - if (! array_key_exists($value, $abbrs) && ! in_array($value, $locations)) { - $this->error(self::INVALID); - return false; - } - break; - - // Check only in locations - case $type & self::LOCATION: - $locations = DateTimeZone::listIdentifiers(); - - if (! in_array($value, $locations)) { - $this->error(self::INVALID_TIMEZONE_LOCATION); - return false; - } - break; - - // Check only in abbreviations - case $type & self::ABBREVIATION: - $abbrs = DateTimeZone::listAbbreviations(); - - if (! array_key_exists($value, $abbrs)) { - $this->error(self::INVALID_TIMEZONE_ABBREVIATION); - return false; - } - break; - } - - return true; - } - - /** - * @param array|int|string $type - * @return float|int - */ - protected function calculateTypeValue($type) - { - $types = (array) $type; - $detected = 0; - - foreach ($types as $value) { - if (is_int($value)) { - $detected |= $value; - } elseif (false !== array_search($value, $this->constants)) { - $detected |= array_search($value, $this->constants); - } - } - - return $detected; - } -} diff --git a/lib/laminas/laminas-validator/src/Translator/TranslatorAwareInterface.php b/lib/laminas/laminas-validator/src/Translator/TranslatorAwareInterface.php deleted file mode 100644 index 9702abc8c..000000000 --- a/lib/laminas/laminas-validator/src/Translator/TranslatorAwareInterface.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php - -namespace Laminas\Validator\Translator; - -interface TranslatorAwareInterface -{ - /** - * Sets translator to use in helper - * - * @param TranslatorInterface $translator [optional] translator. - * Default is null, which sets no translator. - * @param string $textDomain [optional] text domain - * Default is null, which skips setTranslatorTextDomain - * @return self - */ - public function setTranslator(?TranslatorInterface $translator = null, $textDomain = null); - - /** - * Returns translator used in object - * - * @return TranslatorInterface|null - */ - public function getTranslator(); - - /** - * Checks if the object has a translator - * - * @return bool - */ - public function hasTranslator(); - - /** - * Sets whether translator is enabled and should be used - * - * @param bool $enabled [optional] whether translator should be used. - * Default is true. - * @return self - */ - public function setTranslatorEnabled($enabled = true); - - /** - * Returns whether translator is enabled and should be used - * - * @return bool - */ - public function isTranslatorEnabled(); - - /** - * Set translation text domain - * - * @param string $textDomain - * @return TranslatorAwareInterface - */ - public function setTranslatorTextDomain($textDomain = 'default'); - - /** - * Return the translation text domain - * - * @return string - */ - public function getTranslatorTextDomain(); -} diff --git a/lib/laminas/laminas-validator/src/Translator/TranslatorInterface.php b/lib/laminas/laminas-validator/src/Translator/TranslatorInterface.php deleted file mode 100644 index c61c54d40..000000000 --- a/lib/laminas/laminas-validator/src/Translator/TranslatorInterface.php +++ /dev/null @@ -1,14 +0,0 @@ -<?php - -namespace Laminas\Validator\Translator; - -interface TranslatorInterface -{ - /** - * @param string $message - * @param string $textDomain - * @param string $locale - * @return string - */ - public function translate($message, $textDomain = 'default', $locale = null); -} diff --git a/lib/laminas/laminas-validator/src/UndisclosedPassword.php b/lib/laminas/laminas-validator/src/UndisclosedPassword.php deleted file mode 100644 index aa89e13ca..000000000 --- a/lib/laminas/laminas-validator/src/UndisclosedPassword.php +++ /dev/null @@ -1,135 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use Psr\Http\Client\ClientExceptionInterface; -use Psr\Http\Client\ClientInterface; -use Psr\Http\Message\RequestFactoryInterface; - -use function array_filter; -use function explode; -use function is_string; -use function sha1; -use function strcmp; -use function strtoupper; -use function substr; - -final class UndisclosedPassword extends AbstractValidator -{ - // phpcs:disable SlevomatCodingStandard.Classes.UnusedPrivateElements.UnusedConstant - - private const HIBP_API_URI = 'https://api.pwnedpasswords.com'; - private const HIBP_API_REQUEST_TIMEOUT = 300; - private const HIBP_CLIENT_USER_AGENT_STRING = 'laminas-validator'; - private const HIBP_CLIENT_ACCEPT_HEADER = 'application/vnd.haveibeenpwned.v2+json'; - private const HIBP_K_ANONYMITY_HASH_RANGE_LENGTH = 5; - private const HIBP_K_ANONYMITY_HASH_RANGE_BASE = 0; - private const SHA1_STRING_LENGTH = 40; - - // phpcs:enable - - private const PASSWORD_BREACHED = 'passwordBreached'; - private const NOT_A_STRING = 'wrongInput'; - - // phpcs:disable Generic.Files.LineLength.TooLong - - /** @var array<string, string> */ - protected $messageTemplates = [ - self::PASSWORD_BREACHED => 'The provided password was found in previous breaches, please create another password', - self::NOT_A_STRING => 'The provided password is not a string, please provide a correct password', - ]; - - private ClientInterface $httpClient; - - private RequestFactoryInterface $makeHttpRequest; - - public function __construct(ClientInterface $httpClient, RequestFactoryInterface $makeHttpRequest) - { - parent::__construct(); - - $this->httpClient = $httpClient; - $this->makeHttpRequest = $makeHttpRequest; - } - - /** - * @inheritDoc - */ - public function isValid($value): bool - { - if (! is_string($value)) { - $this->error(self::NOT_A_STRING); - return false; - } - - if ($this->isPwnedPassword($value)) { - $this->error(self::PASSWORD_BREACHED); - return false; - } - - return true; - } - - private function isPwnedPassword(string $password): bool - { - $sha1Hash = $this->hashPassword($password); - $rangeHash = $this->getRangeHash($sha1Hash); - $hashList = $this->retrieveHashList($rangeHash); - - return $this->hashInResponse($sha1Hash, $hashList); - } - - /** - * We use a SHA1 hashed password for checking it against - * the breached data set of HIBP. - */ - private function hashPassword(string $password): string - { - $hashedPassword = sha1($password); - - return strtoupper($hashedPassword); - } - - /** - * Creates a hash range that will be send to HIBP API - * applying K-Anonymity - * - * @see https://www.troyhunt.com/enhancing-pwned-passwords-privacy-by-exclusively-supporting-anonymity/ - */ - private function getRangeHash(string $passwordHash): string - { - return substr($passwordHash, self::HIBP_K_ANONYMITY_HASH_RANGE_BASE, self::HIBP_K_ANONYMITY_HASH_RANGE_LENGTH); - } - - /** - * Making a connection to the HIBP API to retrieve a - * list of hashes that all have the same range as we - * provided. - * - * @throws ClientExceptionInterface - */ - private function retrieveHashList(string $passwordRange): string - { - $request = $this->makeHttpRequest->createRequest( - 'GET', - self::HIBP_API_URI . '/range/' . $passwordRange - ); - - $response = $this->httpClient->sendRequest($request); - return (string) $response->getBody(); - } - - /** - * Checks if the password is in the response from HIBP - */ - private function hashInResponse(string $sha1Hash, string $resultStream): bool - { - $data = explode("\r\n", $resultStream); - $hashes = array_filter($data, static function ($value) use ($sha1Hash) { - [$hash] = explode(':', $value); - - return strcmp($hash, substr($sha1Hash, self::HIBP_K_ANONYMITY_HASH_RANGE_LENGTH)) === 0; - }); - - return $hashes !== []; - } -} diff --git a/lib/laminas/laminas-validator/src/Uri.php b/lib/laminas/laminas-validator/src/Uri.php deleted file mode 100644 index ed2d3612e..000000000 --- a/lib/laminas/laminas-validator/src/Uri.php +++ /dev/null @@ -1,185 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use Laminas\Uri\Exception\ExceptionInterface as UriException; -use Laminas\Uri\Uri as UriHandler; -use Laminas\Validator\Exception\InvalidArgumentException; -use Traversable; - -use function array_shift; -use function class_exists; -use function func_get_args; -use function is_a; -use function is_array; -use function is_string; -use function iterator_to_array; -use function sprintf; - -class Uri extends AbstractValidator -{ - public const INVALID = 'uriInvalid'; - public const NOT_URI = 'notUri'; - - /** @var array<string, string> */ - protected $messageTemplates = [ - self::INVALID => 'Invalid type given. String expected', - self::NOT_URI => 'The input does not appear to be a valid Uri', - ]; - - /** @var UriHandler */ - protected $uriHandler; - - /** @var bool */ - protected $allowRelative = true; - - /** @var bool */ - protected $allowAbsolute = true; - - /** - * Sets default option values for this instance - * - * @param array|Traversable $options - */ - public function __construct($options = []) - { - if ($options instanceof Traversable) { - $options = iterator_to_array($options); - } elseif (! is_array($options)) { - $options = func_get_args(); - $temp['uriHandler'] = array_shift($options); - if (! empty($options)) { - $temp['allowRelative'] = array_shift($options); - } - if (! empty($options)) { - $temp['allowAbsolute'] = array_shift($options); - } - - $options = $temp; - } - - if (isset($options['uriHandler'])) { - $this->setUriHandler($options['uriHandler']); - } - if (isset($options['allowRelative'])) { - $this->setAllowRelative($options['allowRelative']); - } - if (isset($options['allowAbsolute'])) { - $this->setAllowAbsolute($options['allowAbsolute']); - } - - parent::__construct($options); - } - - /** - * @throws InvalidArgumentException - * @return UriHandler - */ - public function getUriHandler() - { - if (null === $this->uriHandler) { - // Lazy load the base Uri handler - $this->uriHandler = new UriHandler(); - } elseif (is_string($this->uriHandler) && class_exists($this->uriHandler)) { - // Instantiate string Uri handler that references a class - $this->uriHandler = new $this->uriHandler(); - } - return $this->uriHandler; - } - - /** - * @param UriHandler|string $uriHandler - * @throws InvalidArgumentException - * @return $this - */ - public function setUriHandler($uriHandler) - { - if (! is_a($uriHandler, UriHandler::class, true)) { - throw new InvalidArgumentException(sprintf( - 'Expecting a subclass name or instance of %s as $uriHandler', - UriHandler::class - )); - } - - $this->uriHandler = $uriHandler; - return $this; - } - - /** - * Returns the allowAbsolute option - * - * @return bool - */ - public function getAllowAbsolute() - { - return $this->allowAbsolute; - } - - /** - * Sets the allowAbsolute option - * - * @param bool $allowAbsolute - * @return $this - */ - public function setAllowAbsolute($allowAbsolute) - { - $this->allowAbsolute = (bool) $allowAbsolute; - return $this; - } - - /** - * Returns the allowRelative option - * - * @return bool - */ - public function getAllowRelative() - { - return $this->allowRelative; - } - - /** - * Sets the allowRelative option - * - * @param bool $allowRelative - * @return $this - */ - public function setAllowRelative($allowRelative) - { - $this->allowRelative = (bool) $allowRelative; - return $this; - } - - /** - * Returns true if and only if $value validates as a Uri - * - * @param string $value - * @return bool - */ - public function isValid($value) - { - if (! is_string($value)) { - $this->error(self::INVALID); - return false; - } - - $uriHandler = $this->getUriHandler(); - try { - $uriHandler->parse($value); - if ($uriHandler->isValid()) { - // It will either be a valid absolute or relative URI - if ( - ($this->allowRelative && $this->allowAbsolute) - || ($this->allowAbsolute && $uriHandler->isAbsolute()) - || ($this->allowRelative && $uriHandler->isValidRelative()) - ) { - return true; - } - } - } catch (UriException $ex) { - // Error parsing URI, it must be invalid - } - - $this->error(self::NOT_URI); - return false; - } -} diff --git a/lib/laminas/laminas-validator/src/Uuid.php b/lib/laminas/laminas-validator/src/Uuid.php deleted file mode 100644 index 77ecdd8b3..000000000 --- a/lib/laminas/laminas-validator/src/Uuid.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use function is_string; -use function preg_match; - -/** - * Uuid validator. - */ -final class Uuid extends AbstractValidator -{ - /** - * Matches Uuid's versions 1 to 5. - */ - public const REGEX_UUID = '/^[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}$/'; - - public const INVALID = 'valueNotUuid'; - public const NOT_STRING = 'valueNotString'; - - /** @var array */ - protected $messageTemplates = [ - self::NOT_STRING => 'Invalid type given; string expected', - self::INVALID => 'Invalid UUID format', - ]; - - /** - * Returns true if and only if $value meets the validation requirements. - * - * If $value fails validation, then this method returns false, and - * getMessages() will return an array of messages that explain why the - * validation failed. - * - * @param mixed $value - * @return bool - * @throws Exception\RuntimeException If validation of $value is impossible. - */ - public function isValid($value) - { - if (! is_string($value)) { - $this->error(self::NOT_STRING); - return false; - } - - $this->setValue($value); - - if ( - empty($value) - || $value !== '00000000-0000-0000-0000-000000000000' - && ! preg_match(self::REGEX_UUID, $value) - ) { - $this->error(self::INVALID); - return false; - } - - return true; - } -} diff --git a/lib/laminas/laminas-validator/src/ValidatorChain.php b/lib/laminas/laminas-validator/src/ValidatorChain.php deleted file mode 100644 index 798c52f2b..000000000 --- a/lib/laminas/laminas-validator/src/ValidatorChain.php +++ /dev/null @@ -1,334 +0,0 @@ -<?php // phpcs:disable SlevomatCodingStandard.Namespaces.UnusedUses.UnusedUse - -namespace Laminas\Validator; - -use Countable; -use Laminas\ServiceManager\ServiceManager; -use Laminas\Stdlib\PriorityQueue; -use ReturnTypeWillChange; - -use function array_replace; -use function assert; -use function count; -use function rsort; - -use const SORT_NUMERIC; - -/** - * @psalm-type QueueElement = array{instance: ValidatorInterface, breakChainOnFailure: bool} - */ -class ValidatorChain implements - Countable, - ValidatorInterface -{ - /** - * Default priority at which validators are added - */ - public const DEFAULT_PRIORITY = 1; - - /** @var ValidatorPluginManager<ValidatorInterface>|null */ - protected $plugins; - - /** - * Validator chain - * - * @var PriorityQueue<QueueElement, int> - */ - protected $validators; - - /** - * Array of validation failure messages - * - * @var array<string, string> - */ - protected $messages = []; - - /** - * Initialize validator chain - */ - public function __construct() - { - /** @psalm-suppress InvalidPropertyAssignmentValue */ - $this->validators = new PriorityQueue(); - } - - /** - * Return the count of attached validators - * - * @return int - */ - #[ReturnTypeWillChange] - public function count() - { - return count($this->validators); - } - - /** - * Get plugin manager instance - * - * @return ValidatorPluginManager<ValidatorInterface> - */ - public function getPluginManager() - { - if (! $this->plugins) { - $this->setPluginManager(new ValidatorPluginManager(new ServiceManager())); - } - return $this->plugins; - } - - /** - * Set plugin manager instance - * - * @param ValidatorPluginManager $plugins Plugin manager - * @psalm-assert ValidatorPluginManager $this->plugins - * @return $this - */ - public function setPluginManager(ValidatorPluginManager $plugins) - { - $this->plugins = $plugins; - return $this; - } - - /** - * Retrieve a validator by name - * - * @param string|class-string<ValidatorInterface> $name Name of validator to return - * @param null|array $options Options to pass to validator constructor - * (if not already instantiated) - * @return ValidatorInterface - * @template T of ValidatorInterface - * @psalm-param string|class-string<T> $name - * @psalm-return ValidatorInterface - */ - public function plugin($name, ?array $options = null) - { - $plugins = $this->getPluginManager(); - return $plugins->get($name, $options); - } - - /** - * Attach a validator to the end of the chain - * If $breakChainOnFailure is true, then if the validator fails, the next validator in the chain, - * if one exists, will not be executed. - * - * @param bool $breakChainOnFailure - * @param int $priority Priority at which to enqueue validator; defaults to - * 1 (higher executes earlier) - * @return $this - * @throws Exception\InvalidArgumentException - */ - public function attach( - ValidatorInterface $validator, - $breakChainOnFailure = false, - $priority = self::DEFAULT_PRIORITY - ) { - /** @psalm-suppress RedundantCastGivenDocblockType */ - $this->validators->insert( - [ - 'instance' => $validator, - 'breakChainOnFailure' => (bool) $breakChainOnFailure, - ], - $priority - ); - - return $this; - } - - /** - * Proxy to attach() to keep BC - * - * @deprecated Please use attach() - * - * @param bool $breakChainOnFailure - * @param int $priority - * @return ValidatorChain Provides a fluent interface - */ - public function addValidator( - ValidatorInterface $validator, - $breakChainOnFailure = false, - $priority = self::DEFAULT_PRIORITY - ) { - return $this->attach($validator, $breakChainOnFailure, $priority); - } - - /** - * Adds a validator to the beginning of the chain - * - * If $breakChainOnFailure is true, then if the validator fails, the next validator in the chain, - * if one exists, will not be executed. - * - * @param bool $breakChainOnFailure - * @return $this Provides a fluent interface - */ - public function prependValidator(ValidatorInterface $validator, $breakChainOnFailure = false) - { - $priority = self::DEFAULT_PRIORITY; - - if (! $this->validators->isEmpty()) { - $extractedNodes = $this->validators->toArray(PriorityQueue::EXTR_PRIORITY); - rsort($extractedNodes, SORT_NUMERIC); - $priority = $extractedNodes[0] + 1; - } - - /** @psalm-suppress RedundantCastGivenDocblockType */ - $this->validators->insert( - [ - 'instance' => $validator, - 'breakChainOnFailure' => (bool) $breakChainOnFailure, - ], - $priority - ); - return $this; - } - - /** - * Use the plugin manager to add a validator by name - * - * @param string|class-string<ValidatorInterface> $name - * @param array $options - * @param bool $breakChainOnFailure - * @param int $priority - * @return $this - */ - public function attachByName($name, $options = [], $breakChainOnFailure = false, $priority = self::DEFAULT_PRIORITY) - { - if (isset($options['break_chain_on_failure'])) { - $breakChainOnFailure = (bool) $options['break_chain_on_failure']; - } - - if (isset($options['breakchainonfailure'])) { - $breakChainOnFailure = (bool) $options['breakchainonfailure']; - } - - $this->attach($this->plugin($name, $options), $breakChainOnFailure, $priority); - - return $this; - } - - /** - * Proxy to attachByName() to keep BC - * - * @deprecated Please use attachByName() - * - * @param string $name - * @param array $options - * @param bool $breakChainOnFailure - * @return ValidatorChain - */ - public function addByName($name, $options = [], $breakChainOnFailure = false) - { - return $this->attachByName($name, $options, $breakChainOnFailure); - } - - /** - * Use the plugin manager to prepend a validator by name - * - * @param string|class-string<ValidatorInterface> $name - * @param array $options - * @param bool $breakChainOnFailure - * @return $this - */ - public function prependByName($name, $options = [], $breakChainOnFailure = false) - { - $validator = $this->plugin($name, $options); - $this->prependValidator($validator, $breakChainOnFailure); - return $this; - } - - /** - * Returns true if and only if $value passes all validations in the chain - * - * Validators are run in the order in which they were added to the chain (FIFO). - * - * @param mixed $value - * @param mixed $context Extra "context" to provide the validator - * @return bool - */ - public function isValid($value, $context = null) - { - $this->messages = []; - $result = true; - foreach ($this->validators as $element) { - $validator = $element['instance']; - assert($validator instanceof ValidatorInterface); - if ($validator->isValid($value, $context)) { - continue; - } - $result = false; - $messages = $validator->getMessages(); - $this->messages = array_replace($this->messages, $messages); - if ($element['breakChainOnFailure']) { - break; - } - } - return $result; - } - - /** - * Merge the validator chain with the one given in parameter - * - * @return $this - */ - public function merge(ValidatorChain $validatorChain) - { - foreach ($validatorChain->validators->toArray(PriorityQueue::EXTR_BOTH) as $item) { - $this->attach($item['data']['instance'], $item['data']['breakChainOnFailure'], $item['priority']); - } - - return $this; - } - - /** - * Returns array of validation failure messages - * - * @return array<string, string> - */ - public function getMessages() - { - return $this->messages; - } - - /** - * Get all the validators - * - * @return list<QueueElement> - */ - public function getValidators() - { - return $this->validators->toArray(PriorityQueue::EXTR_DATA); - } - - /** - * Invoke chain as command - * - * @param mixed $value - * @return bool - */ - public function __invoke($value) - { - return $this->isValid($value); - } - - /** - * Deep clone handling - */ - public function __clone() - { - $this->validators = clone $this->validators; - } - - /** - * Prepare validator chain for serialization - * - * Plugin manager (property 'plugins') cannot - * be serialized. On wakeup the property remains unset - * and next invocation to getPluginManager() sets - * the default plugin manager instance (ValidatorPluginManager). - * - * @return array - */ - public function __sleep() - { - return ['validators', 'messages']; - } -} diff --git a/lib/laminas/laminas-validator/src/ValidatorInterface.php b/lib/laminas/laminas-validator/src/ValidatorInterface.php deleted file mode 100644 index af83fbd0a..000000000 --- a/lib/laminas/laminas-validator/src/ValidatorInterface.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -namespace Laminas\Validator; - -/** - * @psalm-type ValidatorSpecification = array{ - * name: string|class-string<ValidatorInterface>, - * priority?: int, - * break_chain_on_failure?: bool, - * options?: array<string, mixed>, - * } - */ -interface ValidatorInterface -{ - /** - * Returns true if and only if $value meets the validation requirements - * - * If $value fails validation, then this method returns false, and - * getMessages() will return an array of messages that explain why the - * validation failed. - * - * @param mixed $value - * @return bool - * @throws Exception\RuntimeException If validation of $value is impossible. - */ - public function isValid($value); - - /** - * Returns an array of messages that explain why the most recent isValid() - * call returned false. The array keys are validation failure message identifiers, - * and the array values are the corresponding human-readable message strings. - * - * If isValid() was never called or if the most recent isValid() call - * returned true, then this method returns an empty array. - * - * @return array<string, string> - */ - public function getMessages(); -} diff --git a/lib/laminas/laminas-validator/src/ValidatorPluginManager.php b/lib/laminas/laminas-validator/src/ValidatorPluginManager.php deleted file mode 100644 index 58517ebc4..000000000 --- a/lib/laminas/laminas-validator/src/ValidatorPluginManager.php +++ /dev/null @@ -1,657 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use Laminas\I18n\Validator as I18nValidator; -use Laminas\ServiceManager\AbstractPluginManager; -use Laminas\ServiceManager\ConfigInterface; -use Laminas\ServiceManager\Exception\InvalidServiceException; -use Laminas\ServiceManager\Factory\InvokableFactory; -use Laminas\ServiceManager\ServiceManager; -use Psr\Container\ContainerInterface; -use Zend\I18n\Validator\Alnum; -use Zend\I18n\Validator\Alpha; -use Zend\I18n\Validator\DateTime; -use Zend\I18n\Validator\IsFloat; -use Zend\I18n\Validator\IsInt; -use Zend\I18n\Validator\PhoneNumber; -use Zend\I18n\Validator\PostCode; -use Zend\Validator\Db\NoRecordExists; -use Zend\Validator\Db\RecordExists; -use Zend\Validator\File\Count; -use Zend\Validator\File\Crc32; -use Zend\Validator\File\ExcludeExtension; -use Zend\Validator\File\ExcludeMimeType; -use Zend\Validator\File\Exists; -use Zend\Validator\File\Extension; -use Zend\Validator\File\FilesSize; -use Zend\Validator\File\Hash; -use Zend\Validator\File\ImageSize; -use Zend\Validator\File\IsCompressed; -use Zend\Validator\File\IsImage; -use Zend\Validator\File\Md5; -use Zend\Validator\File\MimeType; -use Zend\Validator\File\NotExists; -use Zend\Validator\File\Sha1; -use Zend\Validator\File\Size; -use Zend\Validator\File\Upload; -use Zend\Validator\File\UploadFile; -use Zend\Validator\File\WordCount; -use Zend\Validator\Sitemap\Changefreq; -use Zend\Validator\Sitemap\Lastmod; -use Zend\Validator\Sitemap\Loc; -use Zend\Validator\Sitemap\Priority; - -use function get_class; -use function gettype; -use function is_object; -use function method_exists; -use function sprintf; - -/** - * @link ConfigInterface - * @link ServiceManager - * - * @psalm-import-type ServiceManagerConfiguration from ServiceManager - * @psalm-import-type FactoriesConfigurationType from ConfigInterface - * @template InstanceType of ValidatorInterface - * @extends AbstractPluginManager<InstanceType> - */ -class ValidatorPluginManager extends AbstractPluginManager -{ - /** - * Default set of aliases - * - * @var array<array-key, string> - * @psalm-suppress UndefinedClass - */ - protected $aliases = [ - 'alnum' => I18nValidator\Alnum::class, - 'Alnum' => I18nValidator\Alnum::class, - 'alpha' => I18nValidator\Alpha::class, - 'Alpha' => I18nValidator\Alpha::class, - 'barcode' => Barcode::class, - 'Barcode' => Barcode::class, - 'between' => Between::class, - 'Between' => Between::class, - 'BIC' => BusinessIdentifierCode::class, - 'bic' => BusinessIdentifierCode::class, - 'bitwise' => Bitwise::class, - 'Bitwise' => Bitwise::class, - 'BusinessIdentifierCode' => BusinessIdentifierCode::class, - 'businessidentifiercode' => BusinessIdentifierCode::class, - 'callback' => Callback::class, - 'Callback' => Callback::class, - 'creditcard' => CreditCard::class, - 'creditCard' => CreditCard::class, - 'CreditCard' => CreditCard::class, - 'csrf' => Csrf::class, - 'Csrf' => Csrf::class, - 'date' => Date::class, - 'Date' => Date::class, - 'datestep' => DateStep::class, - 'dateStep' => DateStep::class, - 'DateStep' => DateStep::class, - 'datetime' => I18nValidator\DateTime::class, - 'dateTime' => I18nValidator\DateTime::class, - 'DateTime' => I18nValidator\DateTime::class, - 'dbnorecordexists' => Db\NoRecordExists::class, - 'dbNoRecordExists' => Db\NoRecordExists::class, - 'DbNoRecordExists' => Db\NoRecordExists::class, - 'dbrecordexists' => Db\RecordExists::class, - 'dbRecordExists' => Db\RecordExists::class, - 'DbRecordExists' => Db\RecordExists::class, - 'digits' => Digits::class, - 'Digits' => Digits::class, - 'emailaddress' => EmailAddress::class, - 'emailAddress' => EmailAddress::class, - 'EmailAddress' => EmailAddress::class, - 'explode' => Explode::class, - 'Explode' => Explode::class, - 'filecount' => File\Count::class, - 'fileCount' => File\Count::class, - 'FileCount' => File\Count::class, - 'filecrc32' => File\Crc32::class, - 'fileCrc32' => File\Crc32::class, - 'FileCrc32' => File\Crc32::class, - 'fileexcludeextension' => File\ExcludeExtension::class, - 'fileExcludeExtension' => File\ExcludeExtension::class, - 'FileExcludeExtension' => File\ExcludeExtension::class, - 'fileexcludemimetype' => File\ExcludeMimeType::class, - 'fileExcludeMimeType' => File\ExcludeMimeType::class, - 'FileExcludeMimeType' => File\ExcludeMimeType::class, - 'fileexists' => File\Exists::class, - 'fileExists' => File\Exists::class, - 'FileExists' => File\Exists::class, - 'fileextension' => File\Extension::class, - 'fileExtension' => File\Extension::class, - 'FileExtension' => File\Extension::class, - 'filefilessize' => File\FilesSize::class, - 'fileFilesSize' => File\FilesSize::class, - 'FileFilesSize' => File\FilesSize::class, - 'filehash' => File\Hash::class, - 'fileHash' => File\Hash::class, - 'FileHash' => File\Hash::class, - 'fileimagesize' => File\ImageSize::class, - 'fileImageSize' => File\ImageSize::class, - 'FileImageSize' => File\ImageSize::class, - 'fileiscompressed' => File\IsCompressed::class, - 'fileIsCompressed' => File\IsCompressed::class, - 'FileIsCompressed' => File\IsCompressed::class, - 'fileisimage' => File\IsImage::class, - 'fileIsImage' => File\IsImage::class, - 'FileIsImage' => File\IsImage::class, - 'filemd5' => File\Md5::class, - 'fileMd5' => File\Md5::class, - 'FileMd5' => File\Md5::class, - 'filemimetype' => File\MimeType::class, - 'fileMimeType' => File\MimeType::class, - 'FileMimeType' => File\MimeType::class, - 'filenotexists' => File\NotExists::class, - 'fileNotExists' => File\NotExists::class, - 'FileNotExists' => File\NotExists::class, - 'filesha1' => File\Sha1::class, - 'fileSha1' => File\Sha1::class, - 'FileSha1' => File\Sha1::class, - 'filesize' => File\Size::class, - 'fileSize' => File\Size::class, - 'FileSize' => File\Size::class, - 'fileupload' => File\Upload::class, - 'fileUpload' => File\Upload::class, - 'FileUpload' => File\Upload::class, - 'fileuploadfile' => File\UploadFile::class, - 'fileUploadFile' => File\UploadFile::class, - 'FileUploadFile' => File\UploadFile::class, - 'filewordcount' => File\WordCount::class, - 'fileWordCount' => File\WordCount::class, - 'FileWordCount' => File\WordCount::class, - 'float' => I18nValidator\IsFloat::class, - 'Float' => I18nValidator\IsFloat::class, - 'gpspoint' => GpsPoint::class, - 'gpsPoint' => GpsPoint::class, - 'GpsPoint' => GpsPoint::class, - 'greaterthan' => GreaterThan::class, - 'greaterThan' => GreaterThan::class, - 'GreaterThan' => GreaterThan::class, - 'hex' => Hex::class, - 'Hex' => Hex::class, - 'hostname' => Hostname::class, - 'Hostname' => Hostname::class, - 'iban' => Iban::class, - 'Iban' => Iban::class, - 'identical' => Identical::class, - 'Identical' => Identical::class, - 'inarray' => InArray::class, - 'inArray' => InArray::class, - 'InArray' => InArray::class, - 'int' => I18nValidator\IsInt::class, - 'Int' => I18nValidator\IsInt::class, - 'ip' => Ip::class, - 'Ip' => Ip::class, - 'isbn' => Isbn::class, - 'Isbn' => Isbn::class, - 'isCountable' => IsCountable::class, - 'IsCountable' => IsCountable::class, - 'iscountable' => IsCountable::class, - 'isfloat' => I18nValidator\IsFloat::class, - 'isFloat' => I18nValidator\IsFloat::class, - 'IsFloat' => I18nValidator\IsFloat::class, - 'isinstanceof' => IsInstanceOf::class, - 'isInstanceOf' => IsInstanceOf::class, - 'IsInstanceOf' => IsInstanceOf::class, - 'isint' => I18nValidator\IsInt::class, - 'isInt' => I18nValidator\IsInt::class, - 'IsInt' => I18nValidator\IsInt::class, - 'lessthan' => LessThan::class, - 'lessThan' => LessThan::class, - 'LessThan' => LessThan::class, - 'notempty' => NotEmpty::class, - 'notEmpty' => NotEmpty::class, - 'NotEmpty' => NotEmpty::class, - 'phonenumber' => I18nValidator\PhoneNumber::class, - 'phoneNumber' => I18nValidator\PhoneNumber::class, - 'PhoneNumber' => I18nValidator\PhoneNumber::class, - 'postcode' => I18nValidator\PostCode::class, - 'postCode' => I18nValidator\PostCode::class, - 'PostCode' => I18nValidator\PostCode::class, - 'regex' => Regex::class, - 'Regex' => Regex::class, - 'sitemapchangefreq' => Sitemap\Changefreq::class, - 'sitemapChangefreq' => Sitemap\Changefreq::class, - 'SitemapChangefreq' => Sitemap\Changefreq::class, - 'sitemaplastmod' => Sitemap\Lastmod::class, - 'sitemapLastmod' => Sitemap\Lastmod::class, - 'SitemapLastmod' => Sitemap\Lastmod::class, - 'sitemaploc' => Sitemap\Loc::class, - 'sitemapLoc' => Sitemap\Loc::class, - 'SitemapLoc' => Sitemap\Loc::class, - 'sitemappriority' => Sitemap\Priority::class, - 'sitemapPriority' => Sitemap\Priority::class, - 'SitemapPriority' => Sitemap\Priority::class, - 'stringlength' => StringLength::class, - 'stringLength' => StringLength::class, - 'StringLength' => StringLength::class, - 'step' => Step::class, - 'Step' => Step::class, - 'timezone' => Timezone::class, - 'Timezone' => Timezone::class, - 'uri' => Uri::class, - 'Uri' => Uri::class, - 'uuid' => Uuid::class, - 'Uuid' => Uuid::class, - - // Legacy Zend Framework aliases - Alnum::class => I18nValidator\Alnum::class, - Alpha::class => I18nValidator\Alpha::class, - \Zend\Validator\Barcode::class => Barcode::class, - \Zend\Validator\Between::class => Between::class, - \Zend\Validator\Bitwise::class => Bitwise::class, - \Zend\Validator\Callback::class => Callback::class, - \Zend\Validator\CreditCard::class => CreditCard::class, - \Zend\Validator\Csrf::class => Csrf::class, - \Zend\Validator\DateStep::class => DateStep::class, - \Zend\Validator\Date::class => Date::class, - DateTime::class => I18nValidator\DateTime::class, - NoRecordExists::class => Db\NoRecordExists::class, - RecordExists::class => Db\RecordExists::class, - \Zend\Validator\Digits::class => Digits::class, - \Zend\Validator\EmailAddress::class => EmailAddress::class, - \Zend\Validator\Explode::class => Explode::class, - Count::class => File\Count::class, - Crc32::class => File\Crc32::class, - ExcludeExtension::class => File\ExcludeExtension::class, - ExcludeMimeType::class => File\ExcludeMimeType::class, - Exists::class => File\Exists::class, - Extension::class => File\Extension::class, - FilesSize::class => File\FilesSize::class, - Hash::class => File\Hash::class, - ImageSize::class => File\ImageSize::class, - IsCompressed::class => File\IsCompressed::class, - IsImage::class => File\IsImage::class, - Md5::class => File\Md5::class, - MimeType::class => File\MimeType::class, - NotExists::class => File\NotExists::class, - Sha1::class => File\Sha1::class, - Size::class => File\Size::class, - Upload::class => File\Upload::class, - UploadFile::class => File\UploadFile::class, - WordCount::class => File\WordCount::class, - IsFloat::class => I18nValidator\IsFloat::class, - \Zend\Validator\GpsPoint::class => GpsPoint::class, - \Zend\Validator\GreaterThan::class => GreaterThan::class, - \Zend\Validator\Hex::class => Hex::class, - \Zend\Validator\Hostname::class => Hostname::class, - \Zend\Validator\Iban::class => Iban::class, - \Zend\Validator\Identical::class => Identical::class, - \Zend\Validator\InArray::class => InArray::class, - IsInt::class => I18nValidator\IsInt::class, - \Zend\Validator\Ip::class => Ip::class, - \Zend\Validator\Isbn::class => Isbn::class, - \Zend\Validator\IsInstanceOf::class => IsInstanceOf::class, - \Zend\Validator\LessThan::class => LessThan::class, - \Zend\Validator\NotEmpty::class => NotEmpty::class, - PhoneNumber::class => I18nValidator\PhoneNumber::class, - PostCode::class => I18nValidator\PostCode::class, - \Zend\Validator\Regex::class => Regex::class, - Changefreq::class => Sitemap\Changefreq::class, - Lastmod::class => Sitemap\Lastmod::class, - Loc::class => Sitemap\Loc::class, - Priority::class => Sitemap\Priority::class, - \Zend\Validator\StringLength::class => StringLength::class, - \Zend\Validator\Step::class => Step::class, - \Zend\Validator\Timezone::class => Timezone::class, - \Zend\Validator\Uri::class => Uri::class, - \Zend\Validator\Uuid::class => Uuid::class, - - // v2 normalized FQCNs - 'zendvalidatorbarcode' => Barcode::class, - 'zendvalidatorbetween' => Between::class, - 'zendvalidatorbitwise' => Bitwise::class, - 'zendvalidatorcallback' => Callback::class, - 'zendvalidatorcreditcard' => CreditCard::class, - 'zendvalidatorcsrf' => Csrf::class, - 'zendvalidatordatestep' => DateStep::class, - 'zendvalidatordate' => Date::class, - 'zendvalidatordbnorecordexists' => Db\NoRecordExists::class, - 'zendvalidatordbrecordexists' => Db\RecordExists::class, - 'zendvalidatordigits' => Digits::class, - 'zendvalidatoremailaddress' => EmailAddress::class, - 'zendvalidatorexplode' => Explode::class, - 'zendvalidatorfilecount' => File\Count::class, - 'zendvalidatorfilecrc32' => File\Crc32::class, - 'zendvalidatorfileexcludeextension' => File\ExcludeExtension::class, - 'zendvalidatorfileexcludemimetype' => File\ExcludeMimeType::class, - 'zendvalidatorfileexists' => File\Exists::class, - 'zendvalidatorfileextension' => File\Extension::class, - 'zendvalidatorfilefilessize' => File\FilesSize::class, - 'zendvalidatorfilehash' => File\Hash::class, - 'zendvalidatorfileimagesize' => File\ImageSize::class, - 'zendvalidatorfileiscompressed' => File\IsCompressed::class, - 'zendvalidatorfileisimage' => File\IsImage::class, - 'zendvalidatorfilemd5' => File\Md5::class, - 'zendvalidatorfilemimetype' => File\MimeType::class, - 'zendvalidatorfilenotexists' => File\NotExists::class, - 'zendvalidatorfilesha1' => File\Sha1::class, - 'zendvalidatorfilesize' => File\Size::class, - 'zendvalidatorfileupload' => File\Upload::class, - 'zendvalidatorfileuploadfile' => File\UploadFile::class, - 'zendvalidatorfilewordcount' => File\WordCount::class, - 'zendvalidatorgpspoint' => GpsPoint::class, - 'zendvalidatorgreaterthan' => GreaterThan::class, - 'zendvalidatorhex' => Hex::class, - 'zendvalidatorhostname' => Hostname::class, - 'zendi18nvalidatoralnum' => I18nValidator\Alnum::class, - 'zendi18nvalidatoralpha' => I18nValidator\Alpha::class, - 'zendi18nvalidatordatetime' => I18nValidator\DateTime::class, - 'zendi18nvalidatorisfloat' => I18nValidator\IsFloat::class, - 'zendi18nvalidatorisint' => I18nValidator\IsInt::class, - 'zendi18nvalidatorphonenumber' => I18nValidator\PhoneNumber::class, - 'zendi18nvalidatorpostcode' => I18nValidator\PostCode::class, - 'zendvalidatoriban' => Iban::class, - 'zendvalidatoridentical' => Identical::class, - 'zendvalidatorinarray' => InArray::class, - 'zendvalidatorip' => Ip::class, - 'zendvalidatorisbn' => Isbn::class, - 'zendvalidatorisinstanceof' => IsInstanceOf::class, - 'zendvalidatorlessthan' => LessThan::class, - 'zendvalidatornotempty' => NotEmpty::class, - 'zendvalidatorregex' => Regex::class, - 'zendvalidatorsitemapchangefreq' => Sitemap\Changefreq::class, - 'zendvalidatorsitemaplastmod' => Sitemap\Lastmod::class, - 'zendvalidatorsitemaploc' => Sitemap\Loc::class, - 'zendvalidatorsitemappriority' => Sitemap\Priority::class, - 'zendvalidatorstringlength' => StringLength::class, - 'zendvalidatorstep' => Step::class, - 'zendvalidatortimezone' => Timezone::class, - 'zendvalidatoruri' => Uri::class, - 'zendvalidatoruuid' => Uuid::class, - ]; - - /** - * Default set of factories - * - * @var FactoriesConfigurationType - */ - protected $factories = [ - I18nValidator\Alnum::class => InvokableFactory::class, - I18nValidator\Alpha::class => InvokableFactory::class, - Barcode::class => InvokableFactory::class, - Between::class => InvokableFactory::class, - Bitwise::class => InvokableFactory::class, - BusinessIdentifierCode::class => InvokableFactory::class, - Callback::class => InvokableFactory::class, - CreditCard::class => InvokableFactory::class, - Csrf::class => InvokableFactory::class, - DateStep::class => InvokableFactory::class, - Date::class => InvokableFactory::class, - I18nValidator\DateTime::class => InvokableFactory::class, - Db\NoRecordExists::class => InvokableFactory::class, - Db\RecordExists::class => InvokableFactory::class, - Digits::class => InvokableFactory::class, - EmailAddress::class => InvokableFactory::class, - Explode::class => InvokableFactory::class, - File\Count::class => InvokableFactory::class, - File\Crc32::class => InvokableFactory::class, - File\ExcludeExtension::class => InvokableFactory::class, - File\ExcludeMimeType::class => InvokableFactory::class, - File\Exists::class => InvokableFactory::class, - File\Extension::class => InvokableFactory::class, - File\FilesSize::class => InvokableFactory::class, - File\Hash::class => InvokableFactory::class, - File\ImageSize::class => InvokableFactory::class, - File\IsCompressed::class => InvokableFactory::class, - File\IsImage::class => InvokableFactory::class, - File\Md5::class => InvokableFactory::class, - File\MimeType::class => InvokableFactory::class, - File\NotExists::class => InvokableFactory::class, - File\Sha1::class => InvokableFactory::class, - File\Size::class => InvokableFactory::class, - File\Upload::class => InvokableFactory::class, - File\UploadFile::class => InvokableFactory::class, - File\WordCount::class => InvokableFactory::class, - I18nValidator\IsFloat::class => InvokableFactory::class, - GpsPoint::class => InvokableFactory::class, - GreaterThan::class => InvokableFactory::class, - Hex::class => InvokableFactory::class, - Hostname::class => InvokableFactory::class, - Iban::class => InvokableFactory::class, - Identical::class => InvokableFactory::class, - InArray::class => InvokableFactory::class, - I18nValidator\IsInt::class => InvokableFactory::class, - Ip::class => InvokableFactory::class, - Isbn::class => InvokableFactory::class, - IsCountable::class => InvokableFactory::class, - IsInstanceOf::class => InvokableFactory::class, - LessThan::class => InvokableFactory::class, - NotEmpty::class => InvokableFactory::class, - I18nValidator\PhoneNumber::class => InvokableFactory::class, - I18nValidator\PostCode::class => InvokableFactory::class, - Regex::class => InvokableFactory::class, - Sitemap\Changefreq::class => InvokableFactory::class, - Sitemap\Lastmod::class => InvokableFactory::class, - Sitemap\Loc::class => InvokableFactory::class, - Sitemap\Priority::class => InvokableFactory::class, - StringLength::class => InvokableFactory::class, - Step::class => InvokableFactory::class, - Timezone::class => InvokableFactory::class, - Uri::class => InvokableFactory::class, - Uuid::class => InvokableFactory::class, - - // v2 canonical FQCNs - 'laminasvalidatorbarcodecode25interleaved' => InvokableFactory::class, - 'laminasvalidatorbarcodecode25' => InvokableFactory::class, - 'laminasvalidatorbarcodecode39ext' => InvokableFactory::class, - 'laminasvalidatorbarcodecode39' => InvokableFactory::class, - 'laminasvalidatorbarcodecode93ext' => InvokableFactory::class, - 'laminasvalidatorbarcodecode93' => InvokableFactory::class, - 'laminasvalidatorbarcodeean12' => InvokableFactory::class, - 'laminasvalidatorbarcodeean13' => InvokableFactory::class, - 'laminasvalidatorbarcodeean14' => InvokableFactory::class, - 'laminasvalidatorbarcodeean18' => InvokableFactory::class, - 'laminasvalidatorbarcodeean2' => InvokableFactory::class, - 'laminasvalidatorbarcodeean5' => InvokableFactory::class, - 'laminasvalidatorbarcodeean8' => InvokableFactory::class, - 'laminasvalidatorbarcodegtin12' => InvokableFactory::class, - 'laminasvalidatorbarcodegtin13' => InvokableFactory::class, - 'laminasvalidatorbarcodegtin14' => InvokableFactory::class, - 'laminasvalidatorbarcodeidentcode' => InvokableFactory::class, - 'laminasvalidatorbarcodeintelligentmail' => InvokableFactory::class, - 'laminasvalidatorbarcodeissn' => InvokableFactory::class, - 'laminasvalidatorbarcodeitf14' => InvokableFactory::class, - 'laminasvalidatorbarcodeleitcode' => InvokableFactory::class, - 'laminasvalidatorbarcodeplanet' => InvokableFactory::class, - 'laminasvalidatorbarcodepostnet' => InvokableFactory::class, - 'laminasvalidatorbarcoderoyalmail' => InvokableFactory::class, - 'laminasvalidatorbarcodesscc' => InvokableFactory::class, - 'laminasvalidatorbarcodeupca' => InvokableFactory::class, - 'laminasvalidatorbarcodeupce' => InvokableFactory::class, - 'laminasvalidatorbarcode' => InvokableFactory::class, - 'laminasvalidatorbetween' => InvokableFactory::class, - 'laminasvalidatorbitwise' => InvokableFactory::class, - 'laminasvalidatorcallback' => InvokableFactory::class, - 'laminasvalidatorcreditcard' => InvokableFactory::class, - 'laminasvalidatorcsrf' => InvokableFactory::class, - 'laminasvalidatordatestep' => InvokableFactory::class, - 'laminasvalidatordate' => InvokableFactory::class, - 'laminasvalidatordbnorecordexists' => InvokableFactory::class, - 'laminasvalidatordbrecordexists' => InvokableFactory::class, - 'laminasvalidatordigits' => InvokableFactory::class, - 'laminasvalidatoremailaddress' => InvokableFactory::class, - 'laminasvalidatorexplode' => InvokableFactory::class, - 'laminasvalidatorfilecount' => InvokableFactory::class, - 'laminasvalidatorfilecrc32' => InvokableFactory::class, - 'laminasvalidatorfileexcludeextension' => InvokableFactory::class, - 'laminasvalidatorfileexcludemimetype' => InvokableFactory::class, - 'laminasvalidatorfileexists' => InvokableFactory::class, - 'laminasvalidatorfileextension' => InvokableFactory::class, - 'laminasvalidatorfilefilessize' => InvokableFactory::class, - 'laminasvalidatorfilehash' => InvokableFactory::class, - 'laminasvalidatorfileimagesize' => InvokableFactory::class, - 'laminasvalidatorfileiscompressed' => InvokableFactory::class, - 'laminasvalidatorfileisimage' => InvokableFactory::class, - 'laminasvalidatorfilemd5' => InvokableFactory::class, - 'laminasvalidatorfilemimetype' => InvokableFactory::class, - 'laminasvalidatorfilenotexists' => InvokableFactory::class, - 'laminasvalidatorfilesha1' => InvokableFactory::class, - 'laminasvalidatorfilesize' => InvokableFactory::class, - 'laminasvalidatorfileupload' => InvokableFactory::class, - 'laminasvalidatorfileuploadfile' => InvokableFactory::class, - 'laminasvalidatorfilewordcount' => InvokableFactory::class, - 'laminasvalidatorgpspoint' => InvokableFactory::class, - 'laminasvalidatorgreaterthan' => InvokableFactory::class, - 'laminasvalidatorhex' => InvokableFactory::class, - 'laminasvalidatorhostname' => InvokableFactory::class, - 'laminasi18nvalidatoralnum' => InvokableFactory::class, - 'laminasi18nvalidatoralpha' => InvokableFactory::class, - 'laminasi18nvalidatordatetime' => InvokableFactory::class, - 'laminasi18nvalidatorisfloat' => InvokableFactory::class, - 'laminasi18nvalidatorisint' => InvokableFactory::class, - 'laminasi18nvalidatorphonenumber' => InvokableFactory::class, - 'laminasi18nvalidatorpostcode' => InvokableFactory::class, - 'laminasvalidatoriban' => InvokableFactory::class, - 'laminasvalidatoridentical' => InvokableFactory::class, - 'laminasvalidatorinarray' => InvokableFactory::class, - 'laminasvalidatorip' => InvokableFactory::class, - 'laminasvalidatorisbn' => InvokableFactory::class, - 'laminasvalidatoriscountable' => InvokableFactory::class, - 'laminasvalidatorisinstanceof' => InvokableFactory::class, - 'laminasvalidatorlessthan' => InvokableFactory::class, - 'laminasvalidatornotempty' => InvokableFactory::class, - 'laminasvalidatorregex' => InvokableFactory::class, - 'laminasvalidatorsitemapchangefreq' => InvokableFactory::class, - 'laminasvalidatorsitemaplastmod' => InvokableFactory::class, - 'laminasvalidatorsitemaploc' => InvokableFactory::class, - 'laminasvalidatorsitemappriority' => InvokableFactory::class, - 'laminasvalidatorstringlength' => InvokableFactory::class, - 'laminasvalidatorstep' => InvokableFactory::class, - 'laminasvalidatortimezone' => InvokableFactory::class, - 'laminasvalidatoruri' => InvokableFactory::class, - 'laminasvalidatoruuid' => InvokableFactory::class, - ]; - - /** - * Whether or not to share by default; default to false (v2) - * - * @var bool - */ - protected $shareByDefault = false; - - /** - * Whether or not to share by default; default to false (v3) - * - * @var bool - */ - protected $sharedByDefault = false; - - /** - * Default instance type - * - * @var string - */ - protected $instanceOf = ValidatorInterface::class; - - /** - * Constructor - * - * After invoking parent constructor, add an initializer to inject the - * attached translator, if any, to the currently requested helper. - * - * {@inheritDoc} - * - * @param ServiceManagerConfiguration $v3config - */ - public function __construct($configOrContainerInstance = null, array $v3config = []) - { - parent::__construct($configOrContainerInstance, $v3config); - - $this->addInitializer([$this, 'injectTranslator']); - $this->addInitializer([$this, 'injectValidatorPluginManager']); - } - - /** - * Validate plugin instance - * - * {@inheritDoc} - */ - public function validate($instance) - { - if (! $instance instanceof $this->instanceOf) { - throw new InvalidServiceException(sprintf( - '%s expects only to create instances of %s; %s is invalid', - static::class, - $this->instanceOf, - is_object($instance) ? get_class($instance) : gettype($instance) - )); - } - } - - /** - * For v2 compatibility: validate plugin instance. - * - * Proxies to `validate()`. - * - * @param mixed $plugin - * @return void - * @throws Exception\RuntimeException - */ - public function validatePlugin($plugin) - { - try { - $this->validate($plugin); - } catch (InvalidServiceException $e) { - throw new Exception\RuntimeException(sprintf( - 'Plugin of type %s is invalid; must implement %s', - is_object($plugin) ? get_class($plugin) : gettype($plugin), - ValidatorInterface::class - ), $e->getCode(), $e); - } - } - - /** - * Inject a validator instance with the registered translator - * - * @param ContainerInterface|object $first - * @param ContainerInterface|object $second - * @return void - */ - public function injectTranslator($first, $second) - { - if ($first instanceof ContainerInterface) { - $container = $first; - $validator = $second; - } else { - $container = $second; - $validator = $first; - } - - // V2 means we pull it from the parent container - if ($container === $this && method_exists($container, 'getServiceLocator') && $container->getServiceLocator()) { - $container = $container->getServiceLocator(); - } - - if ($validator instanceof Translator\TranslatorAwareInterface) { - if ($container && $container->has('MvcTranslator')) { - $validator->setTranslator($container->get('MvcTranslator')); - } - } - } - - /** - * Inject a validator plugin manager - * - * @param ContainerInterface|object $first - * @param ContainerInterface|object $second - * @return void - */ - public function injectValidatorPluginManager($first, $second) - { - if ($first instanceof ContainerInterface) { - $validator = $second; - } else { - $validator = $first; - } - if ($validator instanceof ValidatorPluginManagerAwareInterface) { - $validator->setValidatorPluginManager($this); - } - } -} diff --git a/lib/laminas/laminas-validator/src/ValidatorPluginManagerAwareInterface.php b/lib/laminas/laminas-validator/src/ValidatorPluginManagerAwareInterface.php deleted file mode 100644 index d30cc7e79..000000000 --- a/lib/laminas/laminas-validator/src/ValidatorPluginManagerAwareInterface.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php - -namespace Laminas\Validator; - -interface ValidatorPluginManagerAwareInterface -{ - /** - * Set validator plugin manager - */ - public function setValidatorPluginManager(ValidatorPluginManager $pluginManager); - - /** - * Get validator plugin manager - * - * @return ValidatorPluginManager - */ - public function getValidatorPluginManager(); -} diff --git a/lib/laminas/laminas-validator/src/ValidatorPluginManagerFactory.php b/lib/laminas/laminas-validator/src/ValidatorPluginManagerFactory.php deleted file mode 100644 index 9b22deee4..000000000 --- a/lib/laminas/laminas-validator/src/ValidatorPluginManagerFactory.php +++ /dev/null @@ -1,85 +0,0 @@ -<?php - -namespace Laminas\Validator; - -use Laminas\ServiceManager\Config; -use Laminas\ServiceManager\FactoryInterface; -use Laminas\ServiceManager\ServiceLocatorInterface; -use Laminas\ServiceManager\ServiceManager; -use Psr\Container\ContainerInterface; - -use function is_array; - -/** - * @link ServiceManager - * - * @psalm-import-type ServiceManagerConfiguration from ServiceManager - */ -class ValidatorPluginManagerFactory implements FactoryInterface -{ - /** - * laminas-servicemanager v2 support for invocation options. - * - * @var null|ServiceManagerConfiguration - */ - protected $creationOptions; - - /** - * {@inheritDoc} - * - * @param string $name - * @param ServiceManagerConfiguration|null $options - * @return ValidatorPluginManager - * @psalm-suppress MoreSpecificImplementedParamType - */ - public function __invoke(ContainerInterface $container, $name, ?array $options = null) - { - $pluginManager = new ValidatorPluginManager($container, $options ?: []); - - // If this is in a laminas-mvc application, the ServiceListener will inject - // merged configuration during bootstrap. - if ($container->has('ServiceListener')) { - return $pluginManager; - } - - // If we do not have a config service, nothing more to do - if (! $container->has('config')) { - return $pluginManager; - } - - $config = $container->get('config'); - - // If we do not have validators configuration, nothing more to do - if (! isset($config['validators']) || ! is_array($config['validators'])) { - return $pluginManager; - } - - // Wire service configuration for validators - (new Config($config['validators']))->configureServiceManager($pluginManager); - - return $pluginManager; - } - - /** - * {@inheritDoc} - * - * @param string|null $name - * @param string|null $requestedName - * @return ValidatorPluginManager - */ - public function createService(ServiceLocatorInterface $container, $name = null, $requestedName = null) - { - return $this($container, $requestedName ?: ValidatorPluginManager::class, $this->creationOptions); - } - - /** - * laminas-servicemanager v2 support for invocation options. - * - * @param ServiceManagerConfiguration $options - * @return void - */ - public function setCreationOptions(array $options) - { - $this->creationOptions = $options; - } -} diff --git a/lib/laminas/laminas-validator/src/ValidatorProviderInterface.php b/lib/laminas/laminas-validator/src/ValidatorProviderInterface.php deleted file mode 100644 index fc6fbb298..000000000 --- a/lib/laminas/laminas-validator/src/ValidatorProviderInterface.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -namespace Laminas\Validator; - -/** - * Hint to the laminas-modulemanager ServiceListener that a module provides validators. - * - * Module classes implementing this interface hint to - * Laminas\ModuleManager\ServiceListener that they provide validators for the - * ValidatorPluginManager. - * - * For users of laminas-mvc/laminas-modulemanager v2, this poses no backwards-compatibility - * break as the method getValidatorConfig is still duck-typed within Laminas\Validator\Module - * when providing configuration to the ServiceListener. - */ -interface ValidatorProviderInterface -{ - /** - * Provide plugin manager configuration for validators. - * - * @return array - */ - public function getValidatorConfig(); -} diff --git a/lib/league/oauth2-client/LICENSE b/lib/league/oauth2-client/LICENSE deleted file mode 100644 index 7dfa39b7c..000000000 --- a/lib/league/oauth2-client/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013-2020 Alex Bilbie <hello@alexbilbie.com> - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -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/lib/league/oauth2-client/README.md b/lib/league/oauth2-client/README.md deleted file mode 100644 index f35d53e8a..000000000 --- a/lib/league/oauth2-client/README.md +++ /dev/null @@ -1,58 +0,0 @@ -# OAuth 2.0 Client - -This package provides a base for integrating with [OAuth 2.0](http://oauth.net/2/) service providers. - -[![Gitter Chat](https://img.shields.io/badge/gitter-join_chat-brightgreen.svg?style=flat-square)](https://gitter.im/thephpleague/oauth2-client) -[![Source Code](https://img.shields.io/badge/source-thephpleague/oauth2--client-blue.svg?style=flat-square)](https://github.com/thephpleague/oauth2-client) -[![Latest Version](https://img.shields.io/github/release/thephpleague/oauth2-client.svg?style=flat-square)](https://github.com/thephpleague/oauth2-client/releases) -[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](https://github.com/thephpleague/oauth2-client/blob/master/LICENSE) -[![Build Status](https://img.shields.io/github/workflow/status/thephpleague/oauth2-client/CI?label=CI&logo=github&style=flat-square)](https://github.com/thephpleague/oauth2-client/actions?query=workflow%3ACI) -[![Codecov Code Coverage](https://img.shields.io/codecov/c/gh/thephpleague/oauth2-client?label=codecov&logo=codecov&style=flat-square)](https://codecov.io/gh/thephpleague/oauth2-client) -[![Total Downloads](https://img.shields.io/packagist/dt/league/oauth2-client.svg?style=flat-square)](https://packagist.org/packages/league/oauth2-client) - ---- - -The OAuth 2.0 login flow, seen commonly around the web in the form of "Connect with Facebook/Google/etc." buttons, is a common integration added to web applications, but it can be tricky and tedious to do right. To help, we've created the `league/oauth2-client` package, which provides a base for integrating with various OAuth 2.0 providers, without overburdening your application with the concerns of [RFC 6749](http://tools.ietf.org/html/rfc6749). - -This OAuth 2.0 client library will work with any OAuth 2.0 provider that conforms to the OAuth 2.0 Authorization Framework. Out-of-the-box, we provide a `GenericProvider` class to connect to any service provider that uses [Bearer tokens](http://tools.ietf.org/html/rfc6750). See our [basic usage guide](https://oauth2-client.thephpleague.com/usage/) for examples using `GenericProvider`. - -Many service providers provide additional functionality above and beyond the OAuth 2.0 specification. For this reason, you may extend and wrap this library to support additional behavior. There are already many [official](https://oauth2-client.thephpleague.com/providers/league/) and [third-party](https://oauth2-client.thephpleague.com/providers/thirdparty/) provider clients available (e.g., Facebook, GitHub, Google, Instagram, LinkedIn, etc.). If your provider isn't in the list, feel free to add it. - -This package is compliant with [PSR-1][], [PSR-2][], [PSR-4][], and [PSR-7][]. If you notice compliance oversights, please send a patch via pull request. If you're interested in contributing to this library, please take a look at our [contributing guidelines](https://github.com/thephpleague/oauth2-client/blob/master/CONTRIBUTING.md). - -## Requirements - -We support the following versions of PHP: - -* PHP 8.1 -* PHP 8.0 -* PHP 7.4 -* PHP 7.3 -* PHP 7.2 -* PHP 7.1 -* PHP 7.0 -* PHP 5.6 - -## Provider Clients - -We provide a list of [official PHP League provider clients](https://oauth2-client.thephpleague.com/providers/league/), as well as [third-party provider clients](https://oauth2-client.thephpleague.com/providers/thirdparty/). - -To build your own provider client, please refer to "[Implementing a Provider Client](https://oauth2-client.thephpleague.com/providers/implementing/)." - -## Usage - -For usage and code examples, check out our [basic usage guide](https://oauth2-client.thephpleague.com/usage/). - -## Contributing - -Please see [our contributing guidelines](https://github.com/thephpleague/oauth2-client/blob/master/CONTRIBUTING.md) for details. - -## License - -The MIT License (MIT). Please see [LICENSE](https://github.com/thephpleague/oauth2-client/blob/master/LICENSE) for more information. - - -[PSR-1]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md -[PSR-2]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md -[PSR-4]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md -[PSR-7]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-7-http-message.md diff --git a/lib/league/oauth2-client/composer.json b/lib/league/oauth2-client/composer.json deleted file mode 100644 index 59201f48f..000000000 --- a/lib/league/oauth2-client/composer.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "name": "league/oauth2-client", - "description": "OAuth 2.0 Client Library", - "license": "MIT", - "config": { - "sort-packages": true - }, - "require": { - "php": "^5.6 || ^7.0 || ^8.0", - "guzzlehttp/guzzle": "^6.0 || ^7.0", - "paragonie/random_compat": "^1 || ^2 || ^9.99" - }, - "require-dev": { - "mockery/mockery": "^1.3.5", - "php-parallel-lint/php-parallel-lint": "^1.3.1", - "phpunit/phpunit": "^5.7 || ^6.0 || ^9.5", - "squizlabs/php_codesniffer": "^2.3 || ^3.0" - }, - "keywords": [ - "oauth", - "oauth2", - "authorization", - "authentication", - "idp", - "identity", - "sso", - "single sign on" - ], - "authors": [ - { - "name": "Alex Bilbie", - "email": "hello@alexbilbie.com", - "homepage": "http://www.alexbilbie.com", - "role": "Developer" - }, - { - "name": "Woody Gilk", - "homepage": "https://github.com/shadowhand", - "role": "Contributor" - } - - ], - "autoload": { - "psr-4": { - "League\\OAuth2\\Client\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "League\\OAuth2\\Client\\Test\\": "test/src/" - } - }, - "extra": { - "branch-alias": { - "dev-2.x": "2.0.x-dev" - } - } -} diff --git a/lib/league/oauth2-client/src/Grant/AbstractGrant.php b/lib/league/oauth2-client/src/Grant/AbstractGrant.php deleted file mode 100644 index 2c0244ba3..000000000 --- a/lib/league/oauth2-client/src/Grant/AbstractGrant.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\Grant; - -use League\OAuth2\Client\Tool\RequiredParameterTrait; - -/** - * Represents a type of authorization grant. - * - * An authorization grant is a credential representing the resource - * owner's authorization (to access its protected resources) used by the - * client to obtain an access token. OAuth 2.0 defines four - * grant types -- authorization code, implicit, resource owner password - * credentials, and client credentials -- as well as an extensibility - * mechanism for defining additional types. - * - * @link http://tools.ietf.org/html/rfc6749#section-1.3 Authorization Grant (RFC 6749, §1.3) - */ -abstract class AbstractGrant -{ - use RequiredParameterTrait; - - /** - * Returns the name of this grant, eg. 'grant_name', which is used as the - * grant type when encoding URL query parameters. - * - * @return string - */ - abstract protected function getName(); - - /** - * Returns a list of all required request parameters. - * - * @return array - */ - abstract protected function getRequiredRequestParameters(); - - /** - * Returns this grant's name as its string representation. This allows for - * string interpolation when building URL query parameters. - * - * @return string - */ - public function __toString() - { - return $this->getName(); - } - - /** - * Prepares an access token request's parameters by checking that all - * required parameters are set, then merging with any given defaults. - * - * @param array $defaults - * @param array $options - * @return array - */ - public function prepareRequestParameters(array $defaults, array $options) - { - $defaults['grant_type'] = $this->getName(); - - $required = $this->getRequiredRequestParameters(); - $provided = array_merge($defaults, $options); - - $this->checkRequiredParameters($required, $provided); - - return $provided; - } -} diff --git a/lib/league/oauth2-client/src/Grant/AuthorizationCode.php b/lib/league/oauth2-client/src/Grant/AuthorizationCode.php deleted file mode 100644 index c49460c02..000000000 --- a/lib/league/oauth2-client/src/Grant/AuthorizationCode.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\Grant; - -/** - * Represents an authorization code grant. - * - * @link http://tools.ietf.org/html/rfc6749#section-1.3.1 Authorization Code (RFC 6749, §1.3.1) - */ -class AuthorizationCode extends AbstractGrant -{ - /** - * @inheritdoc - */ - protected function getName() - { - return 'authorization_code'; - } - - /** - * @inheritdoc - */ - protected function getRequiredRequestParameters() - { - return [ - 'code', - ]; - } -} diff --git a/lib/league/oauth2-client/src/Grant/ClientCredentials.php b/lib/league/oauth2-client/src/Grant/ClientCredentials.php deleted file mode 100644 index dc78c4fda..000000000 --- a/lib/league/oauth2-client/src/Grant/ClientCredentials.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\Grant; - -/** - * Represents a client credentials grant. - * - * @link http://tools.ietf.org/html/rfc6749#section-1.3.4 Client Credentials (RFC 6749, §1.3.4) - */ -class ClientCredentials extends AbstractGrant -{ - /** - * @inheritdoc - */ - protected function getName() - { - return 'client_credentials'; - } - - /** - * @inheritdoc - */ - protected function getRequiredRequestParameters() - { - return []; - } -} diff --git a/lib/league/oauth2-client/src/Grant/Exception/InvalidGrantException.php b/lib/league/oauth2-client/src/Grant/Exception/InvalidGrantException.php deleted file mode 100644 index c3c4e677b..000000000 --- a/lib/league/oauth2-client/src/Grant/Exception/InvalidGrantException.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\Grant\Exception; - -use InvalidArgumentException; - -/** - * Exception thrown if the grant does not extend from AbstractGrant. - * - * @see League\OAuth2\Client\Grant\AbstractGrant - */ -class InvalidGrantException extends InvalidArgumentException -{ -} diff --git a/lib/league/oauth2-client/src/Grant/GrantFactory.php b/lib/league/oauth2-client/src/Grant/GrantFactory.php deleted file mode 100644 index 71990e83d..000000000 --- a/lib/league/oauth2-client/src/Grant/GrantFactory.php +++ /dev/null @@ -1,104 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\Grant; - -use League\OAuth2\Client\Grant\Exception\InvalidGrantException; - -/** - * Represents a factory used when retrieving an authorization grant type. - */ -class GrantFactory -{ - /** - * @var array - */ - protected $registry = []; - - /** - * Defines a grant singleton in the registry. - * - * @param string $name - * @param AbstractGrant $grant - * @return self - */ - public function setGrant($name, AbstractGrant $grant) - { - $this->registry[$name] = $grant; - - return $this; - } - - /** - * Returns a grant singleton by name. - * - * If the grant has not be registered, a default grant will be loaded. - * - * @param string $name - * @return AbstractGrant - */ - public function getGrant($name) - { - if (empty($this->registry[$name])) { - $this->registerDefaultGrant($name); - } - - return $this->registry[$name]; - } - - /** - * Registers a default grant singleton by name. - * - * @param string $name - * @return self - */ - protected function registerDefaultGrant($name) - { - // PascalCase the grant. E.g: 'authorization_code' becomes 'AuthorizationCode' - $class = str_replace(' ', '', ucwords(str_replace(['-', '_'], ' ', $name))); - $class = 'League\\OAuth2\\Client\\Grant\\' . $class; - - $this->checkGrant($class); - - return $this->setGrant($name, new $class); - } - - /** - * Determines if a variable is a valid grant. - * - * @param mixed $class - * @return boolean - */ - public function isGrant($class) - { - return is_subclass_of($class, AbstractGrant::class); - } - - /** - * Checks if a variable is a valid grant. - * - * @throws InvalidGrantException - * @param mixed $class - * @return void - */ - public function checkGrant($class) - { - if (!$this->isGrant($class)) { - throw new InvalidGrantException(sprintf( - 'Grant "%s" must extend AbstractGrant', - is_object($class) ? get_class($class) : $class - )); - } - } -} diff --git a/lib/league/oauth2-client/src/Grant/Password.php b/lib/league/oauth2-client/src/Grant/Password.php deleted file mode 100644 index 6543b2ebd..000000000 --- a/lib/league/oauth2-client/src/Grant/Password.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\Grant; - -/** - * Represents a resource owner password credentials grant. - * - * @link http://tools.ietf.org/html/rfc6749#section-1.3.3 Resource Owner Password Credentials (RFC 6749, §1.3.3) - */ -class Password extends AbstractGrant -{ - /** - * @inheritdoc - */ - protected function getName() - { - return 'password'; - } - - /** - * @inheritdoc - */ - protected function getRequiredRequestParameters() - { - return [ - 'username', - 'password', - ]; - } -} diff --git a/lib/league/oauth2-client/src/Grant/RefreshToken.php b/lib/league/oauth2-client/src/Grant/RefreshToken.php deleted file mode 100644 index 819218230..000000000 --- a/lib/league/oauth2-client/src/Grant/RefreshToken.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\Grant; - -/** - * Represents a refresh token grant. - * - * @link http://tools.ietf.org/html/rfc6749#section-6 Refreshing an Access Token (RFC 6749, §6) - */ -class RefreshToken extends AbstractGrant -{ - /** - * @inheritdoc - */ - protected function getName() - { - return 'refresh_token'; - } - - /** - * @inheritdoc - */ - protected function getRequiredRequestParameters() - { - return [ - 'refresh_token', - ]; - } -} diff --git a/lib/league/oauth2-client/src/OptionProvider/HttpBasicAuthOptionProvider.php b/lib/league/oauth2-client/src/OptionProvider/HttpBasicAuthOptionProvider.php deleted file mode 100644 index 3da406568..000000000 --- a/lib/league/oauth2-client/src/OptionProvider/HttpBasicAuthOptionProvider.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\OptionProvider; - -use InvalidArgumentException; - -/** - * Add http basic auth into access token request options - * @link https://tools.ietf.org/html/rfc6749#section-2.3.1 - */ -class HttpBasicAuthOptionProvider extends PostAuthOptionProvider -{ - /** - * @inheritdoc - */ - public function getAccessTokenOptions($method, array $params) - { - if (empty($params['client_id']) || empty($params['client_secret'])) { - throw new InvalidArgumentException('clientId and clientSecret are required for http basic auth'); - } - - $encodedCredentials = base64_encode(sprintf('%s:%s', $params['client_id'], $params['client_secret'])); - unset($params['client_id'], $params['client_secret']); - - $options = parent::getAccessTokenOptions($method, $params); - $options['headers']['Authorization'] = 'Basic ' . $encodedCredentials; - - return $options; - } -} diff --git a/lib/league/oauth2-client/src/OptionProvider/OptionProviderInterface.php b/lib/league/oauth2-client/src/OptionProvider/OptionProviderInterface.php deleted file mode 100644 index 1126d25aa..000000000 --- a/lib/league/oauth2-client/src/OptionProvider/OptionProviderInterface.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\OptionProvider; - -/** - * Interface for access token options provider - */ -interface OptionProviderInterface -{ - /** - * Builds request options used for requesting an access token. - * - * @param string $method - * @param array $params - * @return array - */ - public function getAccessTokenOptions($method, array $params); -} diff --git a/lib/league/oauth2-client/src/OptionProvider/PostAuthOptionProvider.php b/lib/league/oauth2-client/src/OptionProvider/PostAuthOptionProvider.php deleted file mode 100644 index 12d920ecf..000000000 --- a/lib/league/oauth2-client/src/OptionProvider/PostAuthOptionProvider.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\OptionProvider; - -use League\OAuth2\Client\Provider\AbstractProvider; -use League\OAuth2\Client\Tool\QueryBuilderTrait; - -/** - * Provide options for access token - */ -class PostAuthOptionProvider implements OptionProviderInterface -{ - use QueryBuilderTrait; - - /** - * @inheritdoc - */ - public function getAccessTokenOptions($method, array $params) - { - $options = ['headers' => ['content-type' => 'application/x-www-form-urlencoded']]; - - if ($method === AbstractProvider::METHOD_POST) { - $options['body'] = $this->getAccessTokenBody($params); - } - - return $options; - } - - /** - * Returns the request body for requesting an access token. - * - * @param array $params - * @return string - */ - protected function getAccessTokenBody(array $params) - { - return $this->buildQueryString($params); - } -} diff --git a/lib/league/oauth2-client/src/Provider/AbstractProvider.php b/lib/league/oauth2-client/src/Provider/AbstractProvider.php deleted file mode 100644 index d1679998c..000000000 --- a/lib/league/oauth2-client/src/Provider/AbstractProvider.php +++ /dev/null @@ -1,843 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\Provider; - -use GuzzleHttp\Client as HttpClient; -use GuzzleHttp\ClientInterface as HttpClientInterface; -use GuzzleHttp\Exception\BadResponseException; -use League\OAuth2\Client\Grant\AbstractGrant; -use League\OAuth2\Client\Grant\GrantFactory; -use League\OAuth2\Client\OptionProvider\OptionProviderInterface; -use League\OAuth2\Client\OptionProvider\PostAuthOptionProvider; -use League\OAuth2\Client\Provider\Exception\IdentityProviderException; -use League\OAuth2\Client\Token\AccessToken; -use League\OAuth2\Client\Token\AccessTokenInterface; -use League\OAuth2\Client\Tool\ArrayAccessorTrait; -use League\OAuth2\Client\Tool\GuardedPropertyTrait; -use League\OAuth2\Client\Tool\QueryBuilderTrait; -use League\OAuth2\Client\Tool\RequestFactory; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; -use UnexpectedValueException; - -/** - * Represents a service provider (authorization server). - * - * @link http://tools.ietf.org/html/rfc6749#section-1.1 Roles (RFC 6749, §1.1) - */ -abstract class AbstractProvider -{ - use ArrayAccessorTrait; - use GuardedPropertyTrait; - use QueryBuilderTrait; - - /** - * @var string Key used in a token response to identify the resource owner. - */ - const ACCESS_TOKEN_RESOURCE_OWNER_ID = null; - - /** - * @var string HTTP method used to fetch access tokens. - */ - const METHOD_GET = 'GET'; - - /** - * @var string HTTP method used to fetch access tokens. - */ - const METHOD_POST = 'POST'; - - /** - * @var string - */ - protected $clientId; - - /** - * @var string - */ - protected $clientSecret; - - /** - * @var string - */ - protected $redirectUri; - - /** - * @var string - */ - protected $state; - - /** - * @var GrantFactory - */ - protected $grantFactory; - - /** - * @var RequestFactory - */ - protected $requestFactory; - - /** - * @var HttpClientInterface - */ - protected $httpClient; - - /** - * @var OptionProviderInterface - */ - protected $optionProvider; - - /** - * Constructs an OAuth 2.0 service provider. - * - * @param array $options An array of options to set on this provider. - * Options include `clientId`, `clientSecret`, `redirectUri`, and `state`. - * Individual providers may introduce more options, as needed. - * @param array $collaborators An array of collaborators that may be used to - * override this provider's default behavior. Collaborators include - * `grantFactory`, `requestFactory`, and `httpClient`. - * Individual providers may introduce more collaborators, as needed. - */ - public function __construct(array $options = [], array $collaborators = []) - { - // We'll let the GuardedPropertyTrait handle mass assignment of incoming - // options, skipping any blacklisted properties defined in the provider - $this->fillProperties($options); - - if (empty($collaborators['grantFactory'])) { - $collaborators['grantFactory'] = new GrantFactory(); - } - $this->setGrantFactory($collaborators['grantFactory']); - - if (empty($collaborators['requestFactory'])) { - $collaborators['requestFactory'] = new RequestFactory(); - } - $this->setRequestFactory($collaborators['requestFactory']); - - if (empty($collaborators['httpClient'])) { - $client_options = $this->getAllowedClientOptions($options); - - $collaborators['httpClient'] = new HttpClient( - array_intersect_key($options, array_flip($client_options)) - ); - } - $this->setHttpClient($collaborators['httpClient']); - - if (empty($collaborators['optionProvider'])) { - $collaborators['optionProvider'] = new PostAuthOptionProvider(); - } - $this->setOptionProvider($collaborators['optionProvider']); - } - - /** - * Returns the list of options that can be passed to the HttpClient - * - * @param array $options An array of options to set on this provider. - * Options include `clientId`, `clientSecret`, `redirectUri`, and `state`. - * Individual providers may introduce more options, as needed. - * @return array The options to pass to the HttpClient constructor - */ - protected function getAllowedClientOptions(array $options) - { - $client_options = ['timeout', 'proxy']; - - // Only allow turning off ssl verification if it's for a proxy - if (!empty($options['proxy'])) { - $client_options[] = 'verify'; - } - - return $client_options; - } - - /** - * Sets the grant factory instance. - * - * @param GrantFactory $factory - * @return self - */ - public function setGrantFactory(GrantFactory $factory) - { - $this->grantFactory = $factory; - - return $this; - } - - /** - * Returns the current grant factory instance. - * - * @return GrantFactory - */ - public function getGrantFactory() - { - return $this->grantFactory; - } - - /** - * Sets the request factory instance. - * - * @param RequestFactory $factory - * @return self - */ - public function setRequestFactory(RequestFactory $factory) - { - $this->requestFactory = $factory; - - return $this; - } - - /** - * Returns the request factory instance. - * - * @return RequestFactory - */ - public function getRequestFactory() - { - return $this->requestFactory; - } - - /** - * Sets the HTTP client instance. - * - * @param HttpClientInterface $client - * @return self - */ - public function setHttpClient(HttpClientInterface $client) - { - $this->httpClient = $client; - - return $this; - } - - /** - * Returns the HTTP client instance. - * - * @return HttpClientInterface - */ - public function getHttpClient() - { - return $this->httpClient; - } - - /** - * Sets the option provider instance. - * - * @param OptionProviderInterface $provider - * @return self - */ - public function setOptionProvider(OptionProviderInterface $provider) - { - $this->optionProvider = $provider; - - return $this; - } - - /** - * Returns the option provider instance. - * - * @return OptionProviderInterface - */ - public function getOptionProvider() - { - return $this->optionProvider; - } - - /** - * Returns the current value of the state parameter. - * - * This can be accessed by the redirect handler during authorization. - * - * @return string - */ - public function getState() - { - return $this->state; - } - - /** - * Returns the base URL for authorizing a client. - * - * Eg. https://oauth.service.com/authorize - * - * @return string - */ - abstract public function getBaseAuthorizationUrl(); - - /** - * Returns the base URL for requesting an access token. - * - * Eg. https://oauth.service.com/token - * - * @param array $params - * @return string - */ - abstract public function getBaseAccessTokenUrl(array $params); - - /** - * Returns the URL for requesting the resource owner's details. - * - * @param AccessToken $token - * @return string - */ - abstract public function getResourceOwnerDetailsUrl(AccessToken $token); - - /** - * Returns a new random string to use as the state parameter in an - * authorization flow. - * - * @param int $length Length of the random string to be generated. - * @return string - */ - protected function getRandomState($length = 32) - { - // Converting bytes to hex will always double length. Hence, we can reduce - // the amount of bytes by half to produce the correct length. - return bin2hex(random_bytes($length / 2)); - } - - /** - * Returns the default scopes used by this provider. - * - * This should only be the scopes that are required to request the details - * of the resource owner, rather than all the available scopes. - * - * @return array - */ - abstract protected function getDefaultScopes(); - - /** - * Returns the string that should be used to separate scopes when building - * the URL for requesting an access token. - * - * @return string Scope separator, defaults to ',' - */ - protected function getScopeSeparator() - { - return ','; - } - - /** - * Returns authorization parameters based on provided options. - * - * @param array $options - * @return array Authorization parameters - */ - protected function getAuthorizationParameters(array $options) - { - if (empty($options['state'])) { - $options['state'] = $this->getRandomState(); - } - - if (empty($options['scope'])) { - $options['scope'] = $this->getDefaultScopes(); - } - - $options += [ - 'response_type' => 'code', - 'approval_prompt' => 'auto' - ]; - - if (is_array($options['scope'])) { - $separator = $this->getScopeSeparator(); - $options['scope'] = implode($separator, $options['scope']); - } - - // Store the state as it may need to be accessed later on. - $this->state = $options['state']; - - // Business code layer might set a different redirect_uri parameter - // depending on the context, leave it as-is - if (!isset($options['redirect_uri'])) { - $options['redirect_uri'] = $this->redirectUri; - } - - $options['client_id'] = $this->clientId; - - return $options; - } - - /** - * Builds the authorization URL's query string. - * - * @param array $params Query parameters - * @return string Query string - */ - protected function getAuthorizationQuery(array $params) - { - return $this->buildQueryString($params); - } - - /** - * Builds the authorization URL. - * - * @param array $options - * @return string Authorization URL - */ - public function getAuthorizationUrl(array $options = []) - { - $base = $this->getBaseAuthorizationUrl(); - $params = $this->getAuthorizationParameters($options); - $query = $this->getAuthorizationQuery($params); - - return $this->appendQuery($base, $query); - } - - /** - * Redirects the client for authorization. - * - * @param array $options - * @param callable|null $redirectHandler - * @return mixed - */ - public function authorize( - array $options = [], - callable $redirectHandler = null - ) { - $url = $this->getAuthorizationUrl($options); - if ($redirectHandler) { - return $redirectHandler($url, $this); - } - - // @codeCoverageIgnoreStart - header('Location: ' . $url); - exit; - // @codeCoverageIgnoreEnd - } - - /** - * Appends a query string to a URL. - * - * @param string $url The URL to append the query to - * @param string $query The HTTP query string - * @return string The resulting URL - */ - protected function appendQuery($url, $query) - { - $query = trim($query, '?&'); - - if ($query) { - $glue = strstr($url, '?') === false ? '?' : '&'; - return $url . $glue . $query; - } - - return $url; - } - - /** - * Returns the method to use when requesting an access token. - * - * @return string HTTP method - */ - protected function getAccessTokenMethod() - { - return self::METHOD_POST; - } - - /** - * Returns the key used in the access token response to identify the resource owner. - * - * @return string|null Resource owner identifier key - */ - protected function getAccessTokenResourceOwnerId() - { - return static::ACCESS_TOKEN_RESOURCE_OWNER_ID; - } - - /** - * Builds the access token URL's query string. - * - * @param array $params Query parameters - * @return string Query string - */ - protected function getAccessTokenQuery(array $params) - { - return $this->buildQueryString($params); - } - - /** - * Checks that a provided grant is valid, or attempts to produce one if the - * provided grant is a string. - * - * @param AbstractGrant|string $grant - * @return AbstractGrant - */ - protected function verifyGrant($grant) - { - if (is_string($grant)) { - return $this->grantFactory->getGrant($grant); - } - - $this->grantFactory->checkGrant($grant); - return $grant; - } - - /** - * Returns the full URL to use when requesting an access token. - * - * @param array $params Query parameters - * @return string - */ - protected function getAccessTokenUrl(array $params) - { - $url = $this->getBaseAccessTokenUrl($params); - - if ($this->getAccessTokenMethod() === self::METHOD_GET) { - $query = $this->getAccessTokenQuery($params); - return $this->appendQuery($url, $query); - } - - return $url; - } - - /** - * Returns a prepared request for requesting an access token. - * - * @param array $params Query string parameters - * @return RequestInterface - */ - protected function getAccessTokenRequest(array $params) - { - $method = $this->getAccessTokenMethod(); - $url = $this->getAccessTokenUrl($params); - $options = $this->optionProvider->getAccessTokenOptions($this->getAccessTokenMethod(), $params); - - return $this->getRequest($method, $url, $options); - } - - /** - * Requests an access token using a specified grant and option set. - * - * @param mixed $grant - * @param array $options - * @throws IdentityProviderException - * @return AccessTokenInterface - */ - public function getAccessToken($grant, array $options = []) - { - $grant = $this->verifyGrant($grant); - - $params = [ - 'client_id' => $this->clientId, - 'client_secret' => $this->clientSecret, - 'redirect_uri' => $this->redirectUri, - ]; - - $params = $grant->prepareRequestParameters($params, $options); - $request = $this->getAccessTokenRequest($params); - $response = $this->getParsedResponse($request); - if (false === is_array($response)) { - throw new UnexpectedValueException( - 'Invalid response received from Authorization Server. Expected JSON.' - ); - } - $prepared = $this->prepareAccessTokenResponse($response); - $token = $this->createAccessToken($prepared, $grant); - - return $token; - } - - /** - * Returns a PSR-7 request instance that is not authenticated. - * - * @param string $method - * @param string $url - * @param array $options - * @return RequestInterface - */ - public function getRequest($method, $url, array $options = []) - { - return $this->createRequest($method, $url, null, $options); - } - - /** - * Returns an authenticated PSR-7 request instance. - * - * @param string $method - * @param string $url - * @param AccessTokenInterface|string $token - * @param array $options Any of "headers", "body", and "protocolVersion". - * @return RequestInterface - */ - public function getAuthenticatedRequest($method, $url, $token, array $options = []) - { - return $this->createRequest($method, $url, $token, $options); - } - - /** - * Creates a PSR-7 request instance. - * - * @param string $method - * @param string $url - * @param AccessTokenInterface|string|null $token - * @param array $options - * @return RequestInterface - */ - protected function createRequest($method, $url, $token, array $options) - { - $defaults = [ - 'headers' => $this->getHeaders($token), - ]; - - $options = array_merge_recursive($defaults, $options); - $factory = $this->getRequestFactory(); - - return $factory->getRequestWithOptions($method, $url, $options); - } - - /** - * Sends a request instance and returns a response instance. - * - * WARNING: This method does not attempt to catch exceptions caused by HTTP - * errors! It is recommended to wrap this method in a try/catch block. - * - * @param RequestInterface $request - * @return ResponseInterface - */ - public function getResponse(RequestInterface $request) - { - return $this->getHttpClient()->send($request); - } - - /** - * Sends a request and returns the parsed response. - * - * @param RequestInterface $request - * @throws IdentityProviderException - * @return mixed - */ - public function getParsedResponse(RequestInterface $request) - { - try { - $response = $this->getResponse($request); - } catch (BadResponseException $e) { - $response = $e->getResponse(); - } - - $parsed = $this->parseResponse($response); - - $this->checkResponse($response, $parsed); - - return $parsed; - } - - /** - * Attempts to parse a JSON response. - * - * @param string $content JSON content from response body - * @return array Parsed JSON data - * @throws UnexpectedValueException if the content could not be parsed - */ - protected function parseJson($content) - { - $content = json_decode($content, true); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new UnexpectedValueException(sprintf( - "Failed to parse JSON response: %s", - json_last_error_msg() - )); - } - - return $content; - } - - /** - * Returns the content type header of a response. - * - * @param ResponseInterface $response - * @return string Semi-colon separated join of content-type headers. - */ - protected function getContentType(ResponseInterface $response) - { - return join(';', (array) $response->getHeader('content-type')); - } - - /** - * Parses the response according to its content-type header. - * - * @throws UnexpectedValueException - * @param ResponseInterface $response - * @return array - */ - protected function parseResponse(ResponseInterface $response) - { - $content = (string) $response->getBody(); - $type = $this->getContentType($response); - - if (strpos($type, 'urlencoded') !== false) { - parse_str($content, $parsed); - return $parsed; - } - - // Attempt to parse the string as JSON regardless of content type, - // since some providers use non-standard content types. Only throw an - // exception if the JSON could not be parsed when it was expected to. - try { - return $this->parseJson($content); - } catch (UnexpectedValueException $e) { - if (strpos($type, 'json') !== false) { - throw $e; - } - - if ($response->getStatusCode() == 500) { - throw new UnexpectedValueException( - 'An OAuth server error was encountered that did not contain a JSON body', - 0, - $e - ); - } - - return $content; - } - } - - /** - * Checks a provider response for errors. - * - * @throws IdentityProviderException - * @param ResponseInterface $response - * @param array|string $data Parsed response data - * @return void - */ - abstract protected function checkResponse(ResponseInterface $response, $data); - - /** - * Prepares an parsed access token response for a grant. - * - * Custom mapping of expiration, etc should be done here. Always call the - * parent method when overloading this method. - * - * @param mixed $result - * @return array - */ - protected function prepareAccessTokenResponse(array $result) - { - if ($this->getAccessTokenResourceOwnerId() !== null) { - $result['resource_owner_id'] = $this->getValueByKey( - $result, - $this->getAccessTokenResourceOwnerId() - ); - } - return $result; - } - - /** - * Creates an access token from a response. - * - * The grant that was used to fetch the response can be used to provide - * additional context. - * - * @param array $response - * @param AbstractGrant $grant - * @return AccessTokenInterface - */ - protected function createAccessToken(array $response, AbstractGrant $grant) - { - return new AccessToken($response); - } - - /** - * Generates a resource owner object from a successful resource owner - * details request. - * - * @param array $response - * @param AccessToken $token - * @return ResourceOwnerInterface - */ - abstract protected function createResourceOwner(array $response, AccessToken $token); - - /** - * Requests and returns the resource owner of given access token. - * - * @param AccessToken $token - * @return ResourceOwnerInterface - */ - public function getResourceOwner(AccessToken $token) - { - $response = $this->fetchResourceOwnerDetails($token); - - return $this->createResourceOwner($response, $token); - } - - /** - * Requests resource owner details. - * - * @param AccessToken $token - * @return mixed - */ - protected function fetchResourceOwnerDetails(AccessToken $token) - { - $url = $this->getResourceOwnerDetailsUrl($token); - - $request = $this->getAuthenticatedRequest(self::METHOD_GET, $url, $token); - - $response = $this->getParsedResponse($request); - - if (false === is_array($response)) { - throw new UnexpectedValueException( - 'Invalid response received from Authorization Server. Expected JSON.' - ); - } - - return $response; - } - - /** - * Returns the default headers used by this provider. - * - * Typically this is used to set 'Accept' or 'Content-Type' headers. - * - * @return array - */ - protected function getDefaultHeaders() - { - return []; - } - - /** - * Returns the authorization headers used by this provider. - * - * Typically this is "Bearer" or "MAC". For more information see: - * http://tools.ietf.org/html/rfc6749#section-7.1 - * - * No default is provided, providers must overload this method to activate - * authorization headers. - * - * @param mixed|null $token Either a string or an access token instance - * @return array - */ - protected function getAuthorizationHeaders($token = null) - { - return []; - } - - /** - * Returns all headers used by this provider for a request. - * - * The request will be authenticated if an access token is provided. - * - * @param mixed|null $token object or string - * @return array - */ - public function getHeaders($token = null) - { - if ($token) { - return array_merge( - $this->getDefaultHeaders(), - $this->getAuthorizationHeaders($token) - ); - } - - return $this->getDefaultHeaders(); - } -} diff --git a/lib/league/oauth2-client/src/Provider/Exception/IdentityProviderException.php b/lib/league/oauth2-client/src/Provider/Exception/IdentityProviderException.php deleted file mode 100644 index 52b7e0353..000000000 --- a/lib/league/oauth2-client/src/Provider/Exception/IdentityProviderException.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\Provider\Exception; - -/** - * Exception thrown if the provider response contains errors. - */ -class IdentityProviderException extends \Exception -{ - /** - * @var mixed - */ - protected $response; - - /** - * @param string $message - * @param int $code - * @param array|string $response The response body - */ - public function __construct($message, $code, $response) - { - $this->response = $response; - - parent::__construct($message, $code); - } - - /** - * Returns the exception's response body. - * - * @return array|string - */ - public function getResponseBody() - { - return $this->response; - } -} diff --git a/lib/league/oauth2-client/src/Provider/GenericProvider.php b/lib/league/oauth2-client/src/Provider/GenericProvider.php deleted file mode 100644 index 74393ffda..000000000 --- a/lib/league/oauth2-client/src/Provider/GenericProvider.php +++ /dev/null @@ -1,233 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\Provider; - -use InvalidArgumentException; -use League\OAuth2\Client\Provider\Exception\IdentityProviderException; -use League\OAuth2\Client\Token\AccessToken; -use League\OAuth2\Client\Tool\BearerAuthorizationTrait; -use Psr\Http\Message\ResponseInterface; - -/** - * Represents a generic service provider that may be used to interact with any - * OAuth 2.0 service provider, using Bearer token authentication. - */ -class GenericProvider extends AbstractProvider -{ - use BearerAuthorizationTrait; - - /** - * @var string - */ - private $urlAuthorize; - - /** - * @var string - */ - private $urlAccessToken; - - /** - * @var string - */ - private $urlResourceOwnerDetails; - - /** - * @var string - */ - private $accessTokenMethod; - - /** - * @var string - */ - private $accessTokenResourceOwnerId; - - /** - * @var array|null - */ - private $scopes = null; - - /** - * @var string - */ - private $scopeSeparator; - - /** - * @var string - */ - private $responseError = 'error'; - - /** - * @var string - */ - private $responseCode; - - /** - * @var string - */ - private $responseResourceOwnerId = 'id'; - - /** - * @param array $options - * @param array $collaborators - */ - public function __construct(array $options = [], array $collaborators = []) - { - $this->assertRequiredOptions($options); - - $possible = $this->getConfigurableOptions(); - $configured = array_intersect_key($options, array_flip($possible)); - - foreach ($configured as $key => $value) { - $this->$key = $value; - } - - // Remove all options that are only used locally - $options = array_diff_key($options, $configured); - - parent::__construct($options, $collaborators); - } - - /** - * Returns all options that can be configured. - * - * @return array - */ - protected function getConfigurableOptions() - { - return array_merge($this->getRequiredOptions(), [ - 'accessTokenMethod', - 'accessTokenResourceOwnerId', - 'scopeSeparator', - 'responseError', - 'responseCode', - 'responseResourceOwnerId', - 'scopes', - ]); - } - - /** - * Returns all options that are required. - * - * @return array - */ - protected function getRequiredOptions() - { - return [ - 'urlAuthorize', - 'urlAccessToken', - 'urlResourceOwnerDetails', - ]; - } - - /** - * Verifies that all required options have been passed. - * - * @param array $options - * @return void - * @throws InvalidArgumentException - */ - private function assertRequiredOptions(array $options) - { - $missing = array_diff_key(array_flip($this->getRequiredOptions()), $options); - - if (!empty($missing)) { - throw new InvalidArgumentException( - 'Required options not defined: ' . implode(', ', array_keys($missing)) - ); - } - } - - /** - * @inheritdoc - */ - public function getBaseAuthorizationUrl() - { - return $this->urlAuthorize; - } - - /** - * @inheritdoc - */ - public function getBaseAccessTokenUrl(array $params) - { - return $this->urlAccessToken; - } - - /** - * @inheritdoc - */ - public function getResourceOwnerDetailsUrl(AccessToken $token) - { - return $this->urlResourceOwnerDetails; - } - - /** - * @inheritdoc - */ - public function getDefaultScopes() - { - return $this->scopes; - } - - /** - * @inheritdoc - */ - protected function getAccessTokenMethod() - { - return $this->accessTokenMethod ?: parent::getAccessTokenMethod(); - } - - /** - * @inheritdoc - */ - protected function getAccessTokenResourceOwnerId() - { - return $this->accessTokenResourceOwnerId ?: parent::getAccessTokenResourceOwnerId(); - } - - /** - * @inheritdoc - */ - protected function getScopeSeparator() - { - return $this->scopeSeparator ?: parent::getScopeSeparator(); - } - - /** - * @inheritdoc - */ - protected function checkResponse(ResponseInterface $response, $data) - { - if (!empty($data[$this->responseError])) { - $error = $data[$this->responseError]; - if (!is_string($error)) { - $error = var_export($error, true); - } - $code = $this->responseCode && !empty($data[$this->responseCode])? $data[$this->responseCode] : 0; - if (!is_int($code)) { - $code = intval($code); - } - throw new IdentityProviderException($error, $code, $data); - } - } - - /** - * @inheritdoc - */ - protected function createResourceOwner(array $response, AccessToken $token) - { - return new GenericResourceOwner($response, $this->responseResourceOwnerId); - } -} diff --git a/lib/league/oauth2-client/src/Provider/GenericResourceOwner.php b/lib/league/oauth2-client/src/Provider/GenericResourceOwner.php deleted file mode 100644 index f87661485..000000000 --- a/lib/league/oauth2-client/src/Provider/GenericResourceOwner.php +++ /dev/null @@ -1,61 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\Provider; - -/** - * Represents a generic resource owner for use with the GenericProvider. - */ -class GenericResourceOwner implements ResourceOwnerInterface -{ - /** - * @var array - */ - protected $response; - - /** - * @var string - */ - protected $resourceOwnerId; - - /** - * @param array $response - * @param string $resourceOwnerId - */ - public function __construct(array $response, $resourceOwnerId) - { - $this->response = $response; - $this->resourceOwnerId = $resourceOwnerId; - } - - /** - * Returns the identifier of the authorized resource owner. - * - * @return mixed - */ - public function getId() - { - return $this->response[$this->resourceOwnerId]; - } - - /** - * Returns the raw resource owner response. - * - * @return array - */ - public function toArray() - { - return $this->response; - } -} diff --git a/lib/league/oauth2-client/src/Provider/ResourceOwnerInterface.php b/lib/league/oauth2-client/src/Provider/ResourceOwnerInterface.php deleted file mode 100644 index 828442425..000000000 --- a/lib/league/oauth2-client/src/Provider/ResourceOwnerInterface.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\Provider; - -/** - * Classes implementing `ResourceOwnerInterface` may be used to represent - * the resource owner authenticated with a service provider. - */ -interface ResourceOwnerInterface -{ - /** - * Returns the identifier of the authorized resource owner. - * - * @return mixed - */ - public function getId(); - - /** - * Return all of the owner details available as an array. - * - * @return array - */ - public function toArray(); -} diff --git a/lib/league/oauth2-client/src/Token/AccessToken.php b/lib/league/oauth2-client/src/Token/AccessToken.php deleted file mode 100644 index 81533c307..000000000 --- a/lib/league/oauth2-client/src/Token/AccessToken.php +++ /dev/null @@ -1,243 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\Token; - -use InvalidArgumentException; -use RuntimeException; - -/** - * Represents an access token. - * - * @link http://tools.ietf.org/html/rfc6749#section-1.4 Access Token (RFC 6749, §1.4) - */ -class AccessToken implements AccessTokenInterface, ResourceOwnerAccessTokenInterface -{ - /** - * @var string - */ - protected $accessToken; - - /** - * @var int - */ - protected $expires; - - /** - * @var string - */ - protected $refreshToken; - - /** - * @var string - */ - protected $resourceOwnerId; - - /** - * @var array - */ - protected $values = []; - - /** - * @var int - */ - private static $timeNow; - - /** - * Set the time now. This should only be used for testing purposes. - * - * @param int $timeNow the time in seconds since epoch - * @return void - */ - public static function setTimeNow($timeNow) - { - self::$timeNow = $timeNow; - } - - /** - * Reset the time now if it was set for test purposes. - * - * @return void - */ - public static function resetTimeNow() - { - self::$timeNow = null; - } - - /** - * @return int - */ - public function getTimeNow() - { - return self::$timeNow ? self::$timeNow : time(); - } - - /** - * Constructs an access token. - * - * @param array $options An array of options returned by the service provider - * in the access token request. The `access_token` option is required. - * @throws InvalidArgumentException if `access_token` is not provided in `$options`. - */ - public function __construct(array $options = []) - { - if (empty($options['access_token'])) { - throw new InvalidArgumentException('Required option not passed: "access_token"'); - } - - $this->accessToken = $options['access_token']; - - if (!empty($options['resource_owner_id'])) { - $this->resourceOwnerId = $options['resource_owner_id']; - } - - if (!empty($options['refresh_token'])) { - $this->refreshToken = $options['refresh_token']; - } - - // We need to know when the token expires. Show preference to - // 'expires_in' since it is defined in RFC6749 Section 5.1. - // Defer to 'expires' if it is provided instead. - if (isset($options['expires_in'])) { - if (!is_numeric($options['expires_in'])) { - throw new \InvalidArgumentException('expires_in value must be an integer'); - } - - $this->expires = $options['expires_in'] != 0 ? $this->getTimeNow() + $options['expires_in'] : 0; - } elseif (!empty($options['expires'])) { - // Some providers supply the seconds until expiration rather than - // the exact timestamp. Take a best guess at which we received. - $expires = $options['expires']; - - if (!$this->isExpirationTimestamp($expires)) { - $expires += $this->getTimeNow(); - } - - $this->expires = $expires; - } - - // Capture any additional values that might exist in the token but are - // not part of the standard response. Vendors will sometimes pass - // additional user data this way. - $this->values = array_diff_key($options, array_flip([ - 'access_token', - 'resource_owner_id', - 'refresh_token', - 'expires_in', - 'expires', - ])); - } - - /** - * Check if a value is an expiration timestamp or second value. - * - * @param integer $value - * @return bool - */ - protected function isExpirationTimestamp($value) - { - // If the given value is larger than the original OAuth 2 draft date, - // assume that it is meant to be a (possible expired) timestamp. - $oauth2InceptionDate = 1349067600; // 2012-10-01 - return ($value > $oauth2InceptionDate); - } - - /** - * @inheritdoc - */ - public function getToken() - { - return $this->accessToken; - } - - /** - * @inheritdoc - */ - public function getRefreshToken() - { - return $this->refreshToken; - } - - /** - * @inheritdoc - */ - public function getExpires() - { - return $this->expires; - } - - /** - * @inheritdoc - */ - public function getResourceOwnerId() - { - return $this->resourceOwnerId; - } - - /** - * @inheritdoc - */ - public function hasExpired() - { - $expires = $this->getExpires(); - - if (empty($expires)) { - throw new RuntimeException('"expires" is not set on the token'); - } - - return $expires < time(); - } - - /** - * @inheritdoc - */ - public function getValues() - { - return $this->values; - } - - /** - * @inheritdoc - */ - public function __toString() - { - return (string) $this->getToken(); - } - - /** - * @inheritdoc - */ - public function jsonSerialize() - { - $parameters = $this->values; - - if ($this->accessToken) { - $parameters['access_token'] = $this->accessToken; - } - - if ($this->refreshToken) { - $parameters['refresh_token'] = $this->refreshToken; - } - - if ($this->expires) { - $parameters['expires'] = $this->expires; - } - - if ($this->resourceOwnerId) { - $parameters['resource_owner_id'] = $this->resourceOwnerId; - } - - return $parameters; - } -} diff --git a/lib/league/oauth2-client/src/Token/AccessTokenInterface.php b/lib/league/oauth2-client/src/Token/AccessTokenInterface.php deleted file mode 100644 index 5fd219ffc..000000000 --- a/lib/league/oauth2-client/src/Token/AccessTokenInterface.php +++ /dev/null @@ -1,74 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\Token; - -use JsonSerializable; -use ReturnTypeWillChange; -use RuntimeException; - -interface AccessTokenInterface extends JsonSerializable -{ - /** - * Returns the access token string of this instance. - * - * @return string - */ - public function getToken(); - - /** - * Returns the refresh token, if defined. - * - * @return string|null - */ - public function getRefreshToken(); - - /** - * Returns the expiration timestamp in seconds, if defined. - * - * @return integer|null - */ - public function getExpires(); - - /** - * Checks if this token has expired. - * - * @return boolean true if the token has expired, false otherwise. - * @throws RuntimeException if 'expires' is not set on the token. - */ - public function hasExpired(); - - /** - * Returns additional vendor values stored in the token. - * - * @return array - */ - public function getValues(); - - /** - * Returns a string representation of the access token - * - * @return string - */ - public function __toString(); - - /** - * Returns an array of parameters to serialize when this is serialized with - * json_encode(). - * - * @return array - */ - #[ReturnTypeWillChange] - public function jsonSerialize(); -} diff --git a/lib/league/oauth2-client/src/Token/ResourceOwnerAccessTokenInterface.php b/lib/league/oauth2-client/src/Token/ResourceOwnerAccessTokenInterface.php deleted file mode 100644 index 51e4ce413..000000000 --- a/lib/league/oauth2-client/src/Token/ResourceOwnerAccessTokenInterface.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\Token; - -interface ResourceOwnerAccessTokenInterface extends AccessTokenInterface -{ - /** - * Returns the resource owner identifier, if defined. - * - * @return string|null - */ - public function getResourceOwnerId(); -} diff --git a/lib/league/oauth2-client/src/Tool/ArrayAccessorTrait.php b/lib/league/oauth2-client/src/Tool/ArrayAccessorTrait.php deleted file mode 100644 index a18198cf3..000000000 --- a/lib/league/oauth2-client/src/Tool/ArrayAccessorTrait.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\Tool; - -/** - * Provides generic array navigation tools. - */ -trait ArrayAccessorTrait -{ - /** - * Returns a value by key using dot notation. - * - * @param array $data - * @param string $key - * @param mixed|null $default - * @return mixed - */ - private function getValueByKey(array $data, $key, $default = null) - { - if (!is_string($key) || empty($key) || !count($data)) { - return $default; - } - - if (strpos($key, '.') !== false) { - $keys = explode('.', $key); - - foreach ($keys as $innerKey) { - if (!is_array($data) || !array_key_exists($innerKey, $data)) { - return $default; - } - - $data = $data[$innerKey]; - } - - return $data; - } - - return array_key_exists($key, $data) ? $data[$key] : $default; - } -} diff --git a/lib/league/oauth2-client/src/Tool/BearerAuthorizationTrait.php b/lib/league/oauth2-client/src/Tool/BearerAuthorizationTrait.php deleted file mode 100644 index 081c7c861..000000000 --- a/lib/league/oauth2-client/src/Tool/BearerAuthorizationTrait.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\Tool; - -use League\OAuth2\Client\Token\AccessTokenInterface; - -/** - * Enables `Bearer` header authorization for providers. - * - * @link http://tools.ietf.org/html/rfc6750 Bearer Token Usage (RFC 6750) - */ -trait BearerAuthorizationTrait -{ - /** - * Returns authorization headers for the 'bearer' grant. - * - * @param AccessTokenInterface|string|null $token Either a string or an access token instance - * @return array - */ - protected function getAuthorizationHeaders($token = null) - { - return ['Authorization' => 'Bearer ' . $token]; - } -} diff --git a/lib/league/oauth2-client/src/Tool/GuardedPropertyTrait.php b/lib/league/oauth2-client/src/Tool/GuardedPropertyTrait.php deleted file mode 100644 index 02c9ba5fb..000000000 --- a/lib/league/oauth2-client/src/Tool/GuardedPropertyTrait.php +++ /dev/null @@ -1,70 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\Tool; - -/** - * Provides support for blacklisting explicit properties from the - * mass assignment behavior. - */ -trait GuardedPropertyTrait -{ - /** - * The properties that aren't mass assignable. - * - * @var array - */ - protected $guarded = []; - - /** - * Attempts to mass assign the given options to explicitly defined properties, - * skipping over any properties that are defined in the guarded array. - * - * @param array $options - * @return mixed - */ - protected function fillProperties(array $options = []) - { - if (isset($options['guarded'])) { - unset($options['guarded']); - } - - foreach ($options as $option => $value) { - if (property_exists($this, $option) && !$this->isGuarded($option)) { - $this->{$option} = $value; - } - } - } - - /** - * Returns current guarded properties. - * - * @return array - */ - public function getGuarded() - { - return $this->guarded; - } - - /** - * Determines if the given property is guarded. - * - * @param string $property - * @return bool - */ - public function isGuarded($property) - { - return in_array($property, $this->getGuarded()); - } -} diff --git a/lib/league/oauth2-client/src/Tool/MacAuthorizationTrait.php b/lib/league/oauth2-client/src/Tool/MacAuthorizationTrait.php deleted file mode 100644 index f8dcd77c5..000000000 --- a/lib/league/oauth2-client/src/Tool/MacAuthorizationTrait.php +++ /dev/null @@ -1,83 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\Tool; - -use League\OAuth2\Client\Token\AccessToken; -use League\OAuth2\Client\Token\AccessTokenInterface; - -/** - * Enables `MAC` header authorization for providers. - * - * @link http://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac-05 Message Authentication Code (MAC) Tokens - */ -trait MacAuthorizationTrait -{ - /** - * Returns the id of this token for MAC generation. - * - * @param AccessToken $token - * @return string - */ - abstract protected function getTokenId(AccessToken $token); - - /** - * Returns the MAC signature for the current request. - * - * @param string $id - * @param integer $ts - * @param string $nonce - * @return string - */ - abstract protected function getMacSignature($id, $ts, $nonce); - - /** - * Returns a new random string to use as the state parameter in an - * authorization flow. - * - * @param int $length Length of the random string to be generated. - * @return string - */ - abstract protected function getRandomState($length = 32); - - /** - * Returns the authorization headers for the 'mac' grant. - * - * @param AccessTokenInterface|string|null $token Either a string or an access token instance - * @return array - * @codeCoverageIgnore - * - * @todo This is currently untested and provided only as an example. If you - * complete the implementation, please create a pull request for - * https://github.com/thephpleague/oauth2-client - */ - protected function getAuthorizationHeaders($token = null) - { - if ($token === null) { - return []; - } - - $ts = time(); - $id = $this->getTokenId($token); - $nonce = $this->getRandomState(16); - $mac = $this->getMacSignature($id, $ts, $nonce); - - $parts = []; - foreach (compact('id', 'ts', 'nonce', 'mac') as $key => $value) { - $parts[] = sprintf('%s="%s"', $key, $value); - } - - return ['Authorization' => 'MAC ' . implode(', ', $parts)]; - } -} diff --git a/lib/league/oauth2-client/src/Tool/ProviderRedirectTrait.php b/lib/league/oauth2-client/src/Tool/ProviderRedirectTrait.php deleted file mode 100644 index f81b511f9..000000000 --- a/lib/league/oauth2-client/src/Tool/ProviderRedirectTrait.php +++ /dev/null @@ -1,122 +0,0 @@ -<?php - -namespace League\OAuth2\Client\Tool; - -use GuzzleHttp\Exception\BadResponseException; -use GuzzleHttp\Psr7\Uri; -use InvalidArgumentException; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; - -trait ProviderRedirectTrait -{ - /** - * Maximum number of times to follow provider initiated redirects - * - * @var integer - */ - protected $redirectLimit = 2; - - /** - * Retrieves a response for a given request and retrieves subsequent - * responses, with authorization headers, if a redirect is detected. - * - * @param RequestInterface $request - * @return ResponseInterface - * @throws BadResponseException - */ - protected function followRequestRedirects(RequestInterface $request) - { - $response = null; - $attempts = 0; - - while ($attempts < $this->redirectLimit) { - $attempts++; - $response = $this->getHttpClient()->send($request, [ - 'allow_redirects' => false - ]); - - if ($this->isRedirect($response)) { - $redirectUrl = new Uri($response->getHeader('Location')[0]); - $request = $request->withUri($redirectUrl); - } else { - break; - } - } - - return $response; - } - - /** - * Returns the HTTP client instance. - * - * @return GuzzleHttp\ClientInterface - */ - abstract public function getHttpClient(); - - /** - * Retrieves current redirect limit. - * - * @return integer - */ - public function getRedirectLimit() - { - return $this->redirectLimit; - } - - /** - * Determines if a given response is a redirect. - * - * @param ResponseInterface $response - * - * @return boolean - */ - protected function isRedirect(ResponseInterface $response) - { - $statusCode = $response->getStatusCode(); - - return $statusCode > 300 && $statusCode < 400 && $response->hasHeader('Location'); - } - - /** - * Sends a request instance and returns a response instance. - * - * WARNING: This method does not attempt to catch exceptions caused by HTTP - * errors! It is recommended to wrap this method in a try/catch block. - * - * @param RequestInterface $request - * @return ResponseInterface - */ - public function getResponse(RequestInterface $request) - { - try { - $response = $this->followRequestRedirects($request); - } catch (BadResponseException $e) { - $response = $e->getResponse(); - } - - return $response; - } - - /** - * Updates the redirect limit. - * - * @param integer $limit - * @return League\OAuth2\Client\Provider\AbstractProvider - * @throws InvalidArgumentException - */ - public function setRedirectLimit($limit) - { - if (!is_int($limit)) { - throw new InvalidArgumentException('redirectLimit must be an integer.'); - } - - if ($limit < 1) { - throw new InvalidArgumentException('redirectLimit must be greater than or equal to one.'); - } - - $this->redirectLimit = $limit; - - return $this; - } -} diff --git a/lib/league/oauth2-client/src/Tool/QueryBuilderTrait.php b/lib/league/oauth2-client/src/Tool/QueryBuilderTrait.php deleted file mode 100644 index bdda3e79e..000000000 --- a/lib/league/oauth2-client/src/Tool/QueryBuilderTrait.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\Tool; - -/** - * Provides a standard way to generate query strings. - */ -trait QueryBuilderTrait -{ - /** - * Build a query string from an array. - * - * @param array $params - * - * @return string - */ - protected function buildQueryString(array $params) - { - return http_build_query($params, '', '&', \PHP_QUERY_RFC3986); - } -} diff --git a/lib/league/oauth2-client/src/Tool/RequestFactory.php b/lib/league/oauth2-client/src/Tool/RequestFactory.php deleted file mode 100644 index 1af434297..000000000 --- a/lib/league/oauth2-client/src/Tool/RequestFactory.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\Tool; - -use GuzzleHttp\Psr7\Request; - -/** - * Used to produce PSR-7 Request instances. - * - * @link https://github.com/guzzle/guzzle/pull/1101 - */ -class RequestFactory -{ - /** - * Creates a PSR-7 Request instance. - * - * @param null|string $method HTTP method for the request. - * @param null|string $uri URI for the request. - * @param array $headers Headers for the message. - * @param string|resource|StreamInterface $body Message body. - * @param string $version HTTP protocol version. - * - * @return Request - */ - public function getRequest( - $method, - $uri, - array $headers = [], - $body = null, - $version = '1.1' - ) { - return new Request($method, $uri, $headers, $body, $version); - } - - /** - * Parses simplified options. - * - * @param array $options Simplified options. - * - * @return array Extended options for use with getRequest. - */ - protected function parseOptions(array $options) - { - // Should match default values for getRequest - $defaults = [ - 'headers' => [], - 'body' => null, - 'version' => '1.1', - ]; - - return array_merge($defaults, $options); - } - - /** - * Creates a request using a simplified array of options. - * - * @param null|string $method - * @param null|string $uri - * @param array $options - * - * @return Request - */ - public function getRequestWithOptions($method, $uri, array $options = []) - { - $options = $this->parseOptions($options); - - return $this->getRequest( - $method, - $uri, - $options['headers'], - $options['body'], - $options['version'] - ); - } -} diff --git a/lib/league/oauth2-client/src/Tool/RequiredParameterTrait.php b/lib/league/oauth2-client/src/Tool/RequiredParameterTrait.php deleted file mode 100644 index 47da97717..000000000 --- a/lib/league/oauth2-client/src/Tool/RequiredParameterTrait.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php -/** - * This file is part of the league/oauth2-client library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Alex Bilbie <hello@alexbilbie.com> - * @license http://opensource.org/licenses/MIT MIT - * @link http://thephpleague.com/oauth2-client/ Documentation - * @link https://packagist.org/packages/league/oauth2-client Packagist - * @link https://github.com/thephpleague/oauth2-client GitHub - */ - -namespace League\OAuth2\Client\Tool; - -use BadMethodCallException; - -/** - * Provides functionality to check for required parameters. - */ -trait RequiredParameterTrait -{ - /** - * Checks for a required parameter in a hash. - * - * @throws BadMethodCallException - * @param string $name - * @param array $params - * @return void - */ - private function checkRequiredParameter($name, array $params) - { - if (!isset($params[$name])) { - throw new BadMethodCallException(sprintf( - 'Required parameter not passed: "%s"', - $name - )); - } - } - - /** - * Checks for multiple required parameters in a hash. - * - * @throws InvalidArgumentException - * @param array $names - * @param array $params - * @return void - */ - private function checkRequiredParameters(array $names, array $params) - { - foreach ($names as $name) { - $this->checkRequiredParameter($name, $params); - } - } -} diff --git a/lib/league/oauth2-google/CHANGELOG.md b/lib/league/oauth2-google/CHANGELOG.md deleted file mode 100644 index 18b1a9a6e..000000000 --- a/lib/league/oauth2-google/CHANGELOG.md +++ /dev/null @@ -1,72 +0,0 @@ -OAuth 2.0 Google Provider Changelog - -## 3.0.4 - 2021-01-27 - -### Fixed - -- Correct OAuth endpoint, #94 by @Slamdunk - -## 3.0.3 - 2020-07-24 - -### Fixed - -- Remove the `approval_prompt` from default parameters, #90 - -## 3.0.2 - 2019-11-16 - -### Fixed - -- Allow for `family_name` to be undefined in user information, #79 by @majkel89 - -## 3.0.1 - 2018-12-28 - -### Fixed - -- Correct conflict handling for prompt option, #69 by @mxdpeep - -## 3.0.0 - 2018-12-23 - -### Changed - -- Update to latest version of Google OAuth -- Use only OpenID Connect for user details - -### Fixed - -- Correct handling of selecting from multiple user accounts, #45 -- Prevent conflict when using prompt option, #42 - -### Added - -- Add "locale" to user details, #60 -- Support additional scopes at construction - -### Removed - -- Dropped support for Google+ user details, #34 and #63 - -## 2.2.0 - 2018-03-19 - -### Added - -- Hosted domain validation, #54 by @pradtke - -## 2.1.0 - 2018-03-09 - -### Added - -- OpenID Connect support, #48 by @pradtke - -## 2.0.0 - 2017-01-24 - -### Added - -- PHP 7.1 support - -### Removed - -- Dropped PHP 5.5 support - -## 1.0.0 - 2015-08-12 - -- Initial release diff --git a/lib/league/oauth2-google/CONTRIBUTING.md b/lib/league/oauth2-google/CONTRIBUTING.md deleted file mode 100644 index 84554556e..000000000 --- a/lib/league/oauth2-google/CONTRIBUTING.md +++ /dev/null @@ -1,42 +0,0 @@ -# Contributing - -Contributions are **welcome** and will be fully **credited**. - -We accept contributions via Pull Requests on [Github](https://github.com/thephpleague/oauth2-google). - - -## Pull Requests - -- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer). - -- **Add tests!** - Your patch won't be accepted if it doesn't have tests. - -- **Document any change in behaviour** - Make sure the README and any other relevant documentation are kept up-to-date. - -- **Consider our release cycle** - We try to follow SemVer. Randomly breaking public APIs is not an option. - -- **Create topic branches** - Don't ask us to pull from your master branch. - -- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. - -- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting. - -- **Ensure tests pass!** - Please run the tests (see below) before submitting your pull request, and make sure they pass. We won't accept a patch until all tests pass. - -- **Ensure no coding standards violations** - Please run PHP Code Sniffer using the PSR-2 standard (see below) before submitting your pull request. A violation will cause the build to fail, so please make sure there are no violations. We can't accept a patch if the build fails. - - -## Running Tests - -```sh -composer test -``` - - -## Running PHP Code Sniffer - -```sh -composer check -``` - -**Happy coding**! diff --git a/lib/league/oauth2-google/LICENSE b/lib/league/oauth2-google/LICENSE deleted file mode 100644 index 6d451561e..000000000 --- a/lib/league/oauth2-google/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Woody Gilk <woody.gilk@gmail.com> - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -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/lib/league/oauth2-google/README.md b/lib/league/oauth2-google/README.md deleted file mode 100644 index df69dcd12..000000000 --- a/lib/league/oauth2-google/README.md +++ /dev/null @@ -1,242 +0,0 @@ -# Google Provider for OAuth 2.0 Client - -[![Join the chat](https://img.shields.io/badge/gitter-join-1DCE73.svg)](https://gitter.im/thephpleague/oauth2-google) -[![Build Status](https://img.shields.io/travis/thephpleague/oauth2-google.svg)](https://travis-ci.org/thephpleague/oauth2-google) -[![Code Coverage](https://img.shields.io/coveralls/thephpleague/oauth2-google.svg)](https://coveralls.io/r/thephpleague/oauth2-google) -[![Code Quality](https://img.shields.io/scrutinizer/g/thephpleague/oauth2-google.svg)](https://scrutinizer-ci.com/g/thephpleague/oauth2-google/) -[![License](https://img.shields.io/packagist/l/league/oauth2-google.svg)](https://github.com/thephpleague/oauth2-google/blob/master/LICENSE) -[![Latest Stable Version](https://img.shields.io/packagist/v/league/oauth2-google.svg)](https://packagist.org/packages/league/oauth2-google) - -This package provides Google OAuth 2.0 support for the PHP League's [OAuth 2.0 Client](https://github.com/thephpleague/oauth2-client). - -This package is compliant with [PSR-1][], [PSR-2][] and [PSR-4][]. If you notice compliance oversights, please send -a patch via pull request. - -[PSR-1]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md -[PSR-2]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md -[PSR-4]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md - -## Requirements - -The following versions of PHP are supported. - -* PHP 7.0 -* PHP 7.1 -* PHP 7.2 -* PHP 7.3 -* PHP 7.4 - -This package uses [OpenID Connect][openid-connect] to authenticate users with -Google accounts. - -To use this package, it will be necessary to have a Google client ID and client -secret. These are referred to as `{google-client-id}` and `{google-client-secret}` -in the documentation. - -Please follow the [Google instructions][oauth-setup] to create the required credentials. - -[openid-connect]: https://developers.google.com/identity/protocols/OpenIDConnect -[oauth-setup]: https://developers.google.com/identity/protocols/OpenIDConnect#registeringyourapp - -## Installation - -To install, use composer: - -```sh -composer require league/oauth2-google -``` - -## Usage - -### Authorization Code Flow - -```php -require __DIR__ . '/vendor/autoload.php'; - -use League\OAuth2\Client\Provider\Google; - -session_start(); // Remove if session.auto_start=1 in php.ini - -$provider = new Google([ - 'clientId' => '{google-client-id}', - 'clientSecret' => '{google-client-secret}', - 'redirectUri' => 'https://example.com/callback-url', - 'hostedDomain' => 'example.com', // optional; used to restrict access to users on your G Suite/Google Apps for Business accounts -]); - -if (!empty($_GET['error'])) { - - // Got an error, probably user denied access - exit('Got error: ' . htmlspecialchars($_GET['error'], ENT_QUOTES, 'UTF-8')); - -} elseif (empty($_GET['code'])) { - - // If we don't have an authorization code then get one - $authUrl = $provider->getAuthorizationUrl(); - $_SESSION['oauth2state'] = $provider->getState(); - header('Location: ' . $authUrl); - exit; - -} elseif (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) { - - // State is invalid, possible CSRF attack in progress - unset($_SESSION['oauth2state']); - exit('Invalid state'); - -} else { - - // Try to get an access token (using the authorization code grant) - $token = $provider->getAccessToken('authorization_code', [ - 'code' => $_GET['code'] - ]); - - // Optional: Now you have a token you can look up a users profile data - try { - - // We got an access token, let's now get the owner details - $ownerDetails = $provider->getResourceOwner($token); - - // Use these details to create a new profile - printf('Hello %s!', $ownerDetails->getFirstName()); - - } catch (Exception $e) { - - // Failed to get user details - exit('Something went wrong: ' . $e->getMessage()); - - } - - // Use this to interact with an API on the users behalf - echo $token->getToken(); - - // Use this to get a new access token if the old one expires - echo $token->getRefreshToken(); - - // Unix timestamp at which the access token expires - echo $token->getExpires(); -} -``` - -#### Available Options - -The `Google` provider has the following [options][auth-params]: - -- `accessType` to use online or offline access -- `hostedDomain` to authenticate G Suite users -- `prompt` to modify the prompt that the user will see -- `scopes` to request access to additional user information - -[auth-params]: https://developers.google.com/identity/protocols/OpenIDConnect#authenticationuriparameters - -#### Accessing Token JWT - -Google provides a [JSON Web Token][jwt] (JWT) with all access tokens. This token -[contains basic information][openid-jwt] about the authenticated user. The JWT -can be accessed from the `id_token` value of the access token: - -```php -/** @var League\OAuth2\Client\Token\AccessToken $token */ -$values = $token->getValues(); - -/** @var string */ -$jwt = $values['id_token']; -``` - -Parsing the JWT will require a [JWT parser][jwt-parsers]. Refer to parser -documentation for instructions. - -[jwt]: https://jwt.io/ -[openid-jwt]: https://developers.google.com/identity/protocols/OpenIDConnect#obtainuserinfo -[jwt-parsers]: https://packagist.org/search/?q=jwt - -### Refreshing a Token - -Refresh tokens are only provided to applications which request offline access. You can specify offline access by setting the `accessType` option in your provider: - -```php -use League\OAuth2\Client\Provider\Google; - -$provider = new Google([ - 'clientId' => '{google-client-id}', - 'clientSecret' => '{google-client-secret}', - 'redirectUri' => 'https://example.com/callback-url', - 'accessType' => 'offline', -]); -``` - -It is important to note that the refresh token is only returned on the first request after this it will be `null`. You should securely store the refresh token when it is returned: - -```php -$token = $provider->getAccessToken('authorization_code', [ - 'code' => $code -]); - -// persist the token in a database -$refreshToken = $token->getRefreshToken(); -``` - -If you ever need to get a new refresh token you can request one by forcing the consent prompt: - -```php -$authUrl = $provider->getAuthorizationUrl(['prompt' => 'consent']); -``` - -Now you have everything you need to refresh an access token using a refresh token: - -```php -use League\OAuth2\Client\Provider\Google; -use League\OAuth2\Client\Grant\RefreshToken; - -$provider = new Google([ - 'clientId' => '{google-client-id}', - 'clientSecret' => '{google-client-secret}', - 'redirectUri' => 'https://example.com/callback-url', -]); - -$grant = new RefreshToken(); -$token = $provider->getAccessToken($grant, ['refresh_token' => $refreshToken]); -``` - -## Scopes - -Additional [scopes][scopes] can be set by using the `scope` parameter when -generating the authorization URL: - -```php -$authorizationUrl = $provider->getAuthorizationUrl([ - 'scope' => [ - 'scope-url-here' - ], -]); -``` - -[scopes]: https://developers.google.com/identity/protocols/googlescopes - -## Testing - -Tests can be run with: - -```sh -composer test -``` - -Style checks can be run with: - -```sh -composer check -``` - -## Contributing - -Please see [CONTRIBUTING](https://github.com/thephpleague/oauth2-google/blob/master/CONTRIBUTING.md) for details. - - -## Credits - -- [Woody Gilk](https://github.com/shadowhand) -- [All Contributors](https://github.com/thephpleague/oauth2-google/contributors) - - -## License - -The MIT License (MIT). Please see [License File](https://github.com/thephpleague/oauth2-google/blob/master/LICENSE) for more information. diff --git a/lib/league/oauth2-google/composer.json b/lib/league/oauth2-google/composer.json deleted file mode 100644 index f34a1cec9..000000000 --- a/lib/league/oauth2-google/composer.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "league/oauth2-google", - "description": "Google OAuth 2.0 Client Provider for The PHP League OAuth2-Client", - "license": "MIT", - "authors": [ - { - "name": "Woody Gilk", - "email": "woody.gilk@gmail.com", - "homepage": "http://shadowhand.me" - } - ], - "keywords": [ - "oauth", - "oauth2", - "client", - "authorization", - "authentication", - "google" - ], - "minimum-stability": "stable", - "require": { - "league/oauth2-client": "^2.0" - }, - "require-dev": { - "eloquent/phony-phpunit": "^2.0", - "phpunit/phpunit": "^6.0", - "php-coveralls/php-coveralls": "^2.1", - "squizlabs/php_codesniffer": "^2.0" - }, - "autoload": { - "psr-4": { - "League\\OAuth2\\Client\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "League\\OAuth2\\Client\\Test\\": "test/src/" - } - }, - "scripts": { - "test": "phpunit", - "check": "phpcs src --standard=psr2 -sp" - } -} diff --git a/lib/league/oauth2-google/examples/index.php b/lib/league/oauth2-google/examples/index.php deleted file mode 100644 index 913843777..000000000 --- a/lib/league/oauth2-google/examples/index.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -$provider = require __DIR__ . '/provider.php'; - -if (!empty($_GET['error'])) { - - // Got an error, probably user denied access - exit('Got error: ' . htmlspecialchars($_GET['error'], ENT_QUOTES, 'UTF-8')); - -} elseif (empty($_GET['code'])) { - - // If we don't have an authorization code then get one - $authUrl = $provider->getAuthorizationUrl(); - $_SESSION['oauth2state'] = $provider->getState(); - header('Location: ' . $authUrl); - exit; - -} elseif (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) { - - // State is invalid, possible CSRF attack in progress - unset($_SESSION['oauth2state']); - exit('Invalid state'); - -} else { - - // Try to get an access token (using the authorization code grant) - $token = $provider->getAccessToken('authorization_code', [ - 'code' => $_GET['code'] - ]); - - $_SESSION['token'] = serialize($token); - - // Optional: Now you have a token you can look up a users profile data - header('Location: /user.php'); -} diff --git a/lib/league/oauth2-google/examples/provider.php b/lib/league/oauth2-google/examples/provider.php deleted file mode 100644 index 4001f6857..000000000 --- a/lib/league/oauth2-google/examples/provider.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -require __DIR__ . '/../vendor/autoload.php'; - -use League\OAuth2\Client\Provider\Google; - -// Replace these with your token settings -// Create a project at https://console.developers.google.com/ -$clientId = 'your-client-id'; -$clientSecret = 'your-client-secret'; - -// Change this if you are not using the built-in PHP server -$redirectUri = 'http://localhost:8080/'; - -// Start the session -session_start(); - -// Initialize the provider -$provider = new Google(compact('clientId', 'clientSecret', 'redirectUri')); - -// No HTML for demo, prevents any attempt at XSS -header('Content-Type', 'text/plain'); - -return $provider; diff --git a/lib/league/oauth2-google/examples/reset.php b/lib/league/oauth2-google/examples/reset.php deleted file mode 100644 index 418ea7633..000000000 --- a/lib/league/oauth2-google/examples/reset.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -$provider = require __DIR__ . '/provider.php'; - -unset($_SESSION['token'], $_SESSION['state']); - -header('Location: /'); diff --git a/lib/league/oauth2-google/examples/server.sh b/lib/league/oauth2-google/examples/server.sh deleted file mode 100644 index 110297ce0..000000000 --- a/lib/league/oauth2-google/examples/server.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -php -S localhost:8080 diff --git a/lib/league/oauth2-google/examples/user.php b/lib/league/oauth2-google/examples/user.php deleted file mode 100644 index aacaf31a2..000000000 --- a/lib/league/oauth2-google/examples/user.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -$provider = require __DIR__ . '/provider.php'; - -if (isset($_GET['logout']) && 1 == $_GET['logout']) { - unset($_SESSION['token']); -} - -if (!empty($_SESSION['token'])) { - $token = unserialize($_SESSION['token']); -} - -if (empty($token)) { - header('Location: /'); - exit; -} - -try { - // We got an access token, let's now get the user's details - $userDetails = $provider->getResourceOwner($token); - - // Use these details to create a new profile - printf('Hello %s!<br/>', $userDetails->getFirstname()); -} catch (Exception $e) { - // Failed to get user details - exit('Something went wrong: ' . $e->getMessage()); -} - -// Use this to interact with an API on the users behalf -echo "Token is: <tt>", $token->getToken(), "</tt><br/>"; - -// Use this to get a new access token if the old one expires -echo "Refresh token is: <tt>", $token->getRefreshToken(), "</tt><br/>"; - -// Number of seconds until the access token will expire, and need refreshing -echo "Expires at ", date('r', $token->getExpires()), "<br/>"; - -// Allow the user to logout -echo '<a href="?logout=1">Logout</a><br/>'; diff --git a/lib/league/oauth2-google/phpunit.xml.dist b/lib/league/oauth2-google/phpunit.xml.dist deleted file mode 100644 index 7f37586aa..000000000 --- a/lib/league/oauth2-google/phpunit.xml.dist +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<phpunit backupGlobals="false" - backupStaticAttributes="false" - bootstrap="vendor/autoload.php" - colors="true" - convertErrorsToExceptions="true" - convertNoticesToExceptions="true" - convertWarningsToExceptions="true" - processIsolation="false" - stopOnFailure="false" - syntaxCheck="false" -> - <testsuites> - <testsuite name="all"> - <directory>./test</directory> - </testsuite> - </testsuites> - <filter> - <whitelist> - <directory suffix=".php">src/</directory> - </whitelist> - </filter> - <logging> - <log type="coverage-text" target="php://stdout"/> - <log type="coverage-clover" target="build/logs/clover.xml"/> - <log type="coverage-html" target="build/coverage" charset="UTF-8" yui="true" highlight="true"/> - </logging> -</phpunit> diff --git a/lib/league/oauth2-google/src/Exception/HostedDomainException.php b/lib/league/oauth2-google/src/Exception/HostedDomainException.php deleted file mode 100644 index b38a41580..000000000 --- a/lib/league/oauth2-google/src/Exception/HostedDomainException.php +++ /dev/null @@ -1,15 +0,0 @@ -<?php - -namespace League\OAuth2\Client\Exception; - -/** - * Exception thrown if the Google Provider is configured with a hosted domain that the user doesn't belong to - */ -class HostedDomainException extends \Exception -{ - - public static function notMatchingDomain($configuredDomain) - { - return new static("User is not part of domain '$configuredDomain'"); - } -} diff --git a/lib/league/oauth2-google/src/Provider/Google.php b/lib/league/oauth2-google/src/Provider/Google.php deleted file mode 100644 index 43938e0ec..000000000 --- a/lib/league/oauth2-google/src/Provider/Google.php +++ /dev/null @@ -1,152 +0,0 @@ -<?php - -namespace League\OAuth2\Client\Provider; - -use League\OAuth2\Client\Exception\HostedDomainException; -use League\OAuth2\Client\Provider\Exception\IdentityProviderException; -use League\OAuth2\Client\Token\AccessToken; -use League\OAuth2\Client\Tool\BearerAuthorizationTrait; -use Psr\Http\Message\ResponseInterface; - -class Google extends AbstractProvider -{ - use BearerAuthorizationTrait; - - /** - * @var string If set, this will be sent to google as the "access_type" parameter. - * @link https://developers.google.com/identity/protocols/OpenIDConnect#authenticationuriparameters - */ - protected $accessType; - - /** - * @var string If set, this will be sent to google as the "hd" parameter. - * @link https://developers.google.com/identity/protocols/OpenIDConnect#authenticationuriparameters - */ - protected $hostedDomain; - - /** - * @var string If set, this will be sent to google as the "prompt" parameter. - * @link https://developers.google.com/identity/protocols/OpenIDConnect#authenticationuriparameters - */ - protected $prompt; - - /** - * @var array List of scopes that will be used for authentication. - * @link https://developers.google.com/identity/protocols/googlescopes - */ - protected $scopes = []; - - public function getBaseAuthorizationUrl() - { - return 'https://accounts.google.com/o/oauth2/v2/auth'; - } - - public function getBaseAccessTokenUrl(array $params) - { - return 'https://oauth2.googleapis.com/token'; - } - - public function getResourceOwnerDetailsUrl(AccessToken $token) - { - return 'https://openidconnect.googleapis.com/v1/userinfo'; - } - - protected function getAuthorizationParameters(array $options) - { - if (empty($options['hd']) && $this->hostedDomain) { - $options['hd'] = $this->hostedDomain; - } - - if (empty($options['access_type']) && $this->accessType) { - $options['access_type'] = $this->accessType; - } - - if (empty($options['prompt']) && $this->prompt) { - $options['prompt'] = $this->prompt; - } - - // Default scopes MUST be included for OpenID Connect. - // Additional scopes MAY be added by constructor or option. - $scopes = array_merge($this->getDefaultScopes(), $this->scopes); - - if (!empty($options['scope'])) { - $scopes = array_merge($scopes, $options['scope']); - } - - $options['scope'] = array_unique($scopes); - - $options = parent::getAuthorizationParameters($options); - - // The "approval_prompt" MUST be removed as it is not supported by Google, use "prompt" instead: - // https://developers.google.com/identity/protocols/oauth2/openid-connect#prompt - unset($options['approval_prompt']); - - return $options; - } - - protected function getDefaultScopes() - { - // "openid" MUST be the first scope in the list. - return [ - 'openid', - 'email', - 'profile', - ]; - } - - protected function getScopeSeparator() - { - return ' '; - } - - protected function checkResponse(ResponseInterface $response, $data) - { - // @codeCoverageIgnoreStart - if (empty($data['error'])) { - return; - } - // @codeCoverageIgnoreEnd - - $code = 0; - $error = $data['error']; - - if (is_array($error)) { - $code = $error['code']; - $error = $error['message']; - } - - throw new IdentityProviderException($error, $code, $data); - } - - protected function createResourceOwner(array $response, AccessToken $token) - { - $user = new GoogleUser($response); - - $this->assertMatchingDomain($user->getHostedDomain()); - - return $user; - } - - /** - * @throws HostedDomainException If the domain does not match the configured domain. - */ - protected function assertMatchingDomain($hostedDomain) - { - if ($this->hostedDomain === null) { - // No hosted domain configured. - return; - } - - if ($this->hostedDomain === '*' && $hostedDomain) { - // Any hosted domain is allowed. - return; - } - - if ($this->hostedDomain === $hostedDomain) { - // Hosted domain is correct. - return; - } - - throw HostedDomainException::notMatchingDomain($this->hostedDomain); - } -} diff --git a/lib/league/oauth2-google/src/Provider/GoogleUser.php b/lib/league/oauth2-google/src/Provider/GoogleUser.php deleted file mode 100644 index 1100b1dbe..000000000 --- a/lib/league/oauth2-google/src/Provider/GoogleUser.php +++ /dev/null @@ -1,112 +0,0 @@ -<?php - -namespace League\OAuth2\Client\Provider; - -class GoogleUser implements ResourceOwnerInterface -{ - /** - * @var array - */ - protected $response; - - /** - * @param array $response - */ - public function __construct(array $response) - { - $this->response = $response; - } - - public function getId() - { - return $this->response['sub']; - } - - /** - * Get preferred display name. - * - * @return string - */ - public function getName() - { - return $this->response['name']; - } - - /** - * Get preferred first name. - * - * @return string|null - */ - public function getFirstName() - { - return $this->getResponseValue('given_name'); - } - - /** - * Get preferred last name. - * - * @return string|null - */ - public function getLastName() - { - return $this->getResponseValue('family_name'); - } - - /** - * Get locale. - * - * @return string|null - */ - public function getLocale() - { - return $this->getResponseValue('locale'); - } - - /** - * Get email address. - * - * @return string|null - */ - public function getEmail() - { - return $this->getResponseValue('email'); - } - - /** - * Get hosted domain. - * - * @return string|null - */ - public function getHostedDomain() - { - return $this->getResponseValue('hd'); - } - - /** - * Get avatar image URL. - * - * @return string|null - */ - public function getAvatar() - { - return $this->getResponseValue('picture'); - } - - /** - * Get user data as an array. - * - * @return array - */ - public function toArray() - { - return $this->response; - } - - private function getResponseValue($key) - { - if (array_key_exists($key, $this->response)) { - return $this->response[$key]; - } - return null; - } -} diff --git a/lib/nikic/php-parser/LICENSE b/lib/nikic/php-parser/LICENSE deleted file mode 100644 index 2e5671835..000000000 --- a/lib/nikic/php-parser/LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -BSD 3-Clause License - -Copyright (c) 2011, Nikita Popov -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/lib/nikic/php-parser/README.md b/lib/nikic/php-parser/README.md deleted file mode 100644 index 708cdfcbd..000000000 --- a/lib/nikic/php-parser/README.md +++ /dev/null @@ -1,225 +0,0 @@ -PHP Parser -========== - -[![Coverage Status](https://coveralls.io/repos/github/nikic/PHP-Parser/badge.svg?branch=master)](https://coveralls.io/github/nikic/PHP-Parser?branch=master) - -This is a PHP 5.2 to PHP 8.1 parser written in PHP. Its purpose is to simplify static code analysis and -manipulation. - -[**Documentation for version 4.x**][doc_master] (stable; for running on PHP >= 7.0; for parsing PHP 5.2 to PHP 8.1). - -[Documentation for version 3.x][doc_3_x] (unsupported; for running on PHP >= 5.5; for parsing PHP 5.2 to PHP 7.2). - -Features --------- - -The main features provided by this library are: - - * Parsing PHP 5, PHP 7, and PHP 8 code into an abstract syntax tree (AST). - * Invalid code can be parsed into a partial AST. - * The AST contains accurate location information. - * Dumping the AST in human-readable form. - * Converting an AST back to PHP code. - * Experimental: Formatting can be preserved for partially changed ASTs. - * Infrastructure to traverse and modify ASTs. - * Resolution of namespaced names. - * Evaluation of constant expressions. - * Builders to simplify AST construction for code generation. - * Converting an AST into JSON and back. - -Quick Start ------------ - -Install the library using [composer](https://getcomposer.org): - - php composer.phar require nikic/php-parser - -Parse some PHP code into an AST and dump the result in human-readable form: - -```php -<?php -use PhpParser\Error; -use PhpParser\NodeDumper; -use PhpParser\ParserFactory; - -$code = <<<'CODE' -<?php - -function test($foo) -{ - var_dump($foo); -} -CODE; - -$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7); -try { - $ast = $parser->parse($code); -} catch (Error $error) { - echo "Parse error: {$error->getMessage()}\n"; - return; -} - -$dumper = new NodeDumper; -echo $dumper->dump($ast) . "\n"; -``` - -This dumps an AST looking something like this: - -``` -array( - 0: Stmt_Function( - byRef: false - name: Identifier( - name: test - ) - params: array( - 0: Param( - type: null - byRef: false - variadic: false - var: Expr_Variable( - name: foo - ) - default: null - ) - ) - returnType: null - stmts: array( - 0: Stmt_Expression( - expr: Expr_FuncCall( - name: Name( - parts: array( - 0: var_dump - ) - ) - args: array( - 0: Arg( - value: Expr_Variable( - name: foo - ) - byRef: false - unpack: false - ) - ) - ) - ) - ) - ) -) -``` - -Let's traverse the AST and perform some kind of modification. For example, drop all function bodies: - -```php -use PhpParser\Node; -use PhpParser\Node\Stmt\Function_; -use PhpParser\NodeTraverser; -use PhpParser\NodeVisitorAbstract; - -$traverser = new NodeTraverser(); -$traverser->addVisitor(new class extends NodeVisitorAbstract { - public function enterNode(Node $node) { - if ($node instanceof Function_) { - // Clean out the function body - $node->stmts = []; - } - } -}); - -$ast = $traverser->traverse($ast); -echo $dumper->dump($ast) . "\n"; -``` - -This gives us an AST where the `Function_::$stmts` are empty: - -``` -array( - 0: Stmt_Function( - byRef: false - name: Identifier( - name: test - ) - params: array( - 0: Param( - type: null - byRef: false - variadic: false - var: Expr_Variable( - name: foo - ) - default: null - ) - ) - returnType: null - stmts: array( - ) - ) -) -``` - -Finally, we can convert the new AST back to PHP code: - -```php -use PhpParser\PrettyPrinter; - -$prettyPrinter = new PrettyPrinter\Standard; -echo $prettyPrinter->prettyPrintFile($ast); -``` - -This gives us our original code, minus the `var_dump()` call inside the function: - -```php -<?php - -function test($foo) -{ -} -``` - -For a more comprehensive introduction, see the documentation. - -Documentation -------------- - - 1. [Introduction](doc/0_Introduction.markdown) - 2. [Usage of basic components](doc/2_Usage_of_basic_components.markdown) - -Component documentation: - - * [Walking the AST](doc/component/Walking_the_AST.markdown) - * Node visitors - * Modifying the AST from a visitor - * Short-circuiting traversals - * Interleaved visitors - * Simple node finding API - * Parent and sibling references - * [Name resolution](doc/component/Name_resolution.markdown) - * Name resolver options - * Name resolution context - * [Pretty printing](doc/component/Pretty_printing.markdown) - * Converting AST back to PHP code - * Customizing formatting - * Formatting-preserving code transformations - * [AST builders](doc/component/AST_builders.markdown) - * Fluent builders for AST nodes - * [Lexer](doc/component/Lexer.markdown) - * Lexer options - * Token and file positions for nodes - * Custom attributes - * [Error handling](doc/component/Error_handling.markdown) - * Column information for errors - * Error recovery (parsing of syntactically incorrect code) - * [Constant expression evaluation](doc/component/Constant_expression_evaluation.markdown) - * Evaluating constant/property/etc initializers - * Handling errors and unsupported expressions - * [JSON representation](doc/component/JSON_representation.markdown) - * JSON encoding and decoding of ASTs - * [Performance](doc/component/Performance.markdown) - * Disabling Xdebug - * Reusing objects - * Garbage collection impact - * [Frequently asked questions](doc/component/FAQ.markdown) - * Parent and sibling references - - [doc_3_x]: https://github.com/nikic/PHP-Parser/tree/3.x/doc - [doc_master]: https://github.com/nikic/PHP-Parser/tree/master/doc diff --git a/lib/nikic/php-parser/bin/php-parse b/lib/nikic/php-parser/bin/php-parse deleted file mode 100755 index bb3e46df4..000000000 --- a/lib/nikic/php-parser/bin/php-parse +++ /dev/null @@ -1,205 +0,0 @@ -#!/usr/bin/env php -<?php - -foreach ([__DIR__ . '/../../../autoload.php', __DIR__ . '/../vendor/autoload.php'] as $file) { - if (file_exists($file)) { - require $file; - break; - } -} - -ini_set('xdebug.max_nesting_level', 3000); - -// Disable Xdebug var_dump() output truncation -ini_set('xdebug.var_display_max_children', -1); -ini_set('xdebug.var_display_max_data', -1); -ini_set('xdebug.var_display_max_depth', -1); - -list($operations, $files, $attributes) = parseArgs($argv); - -/* Dump nodes by default */ -if (empty($operations)) { - $operations[] = 'dump'; -} - -if (empty($files)) { - showHelp("Must specify at least one file."); -} - -$lexer = new PhpParser\Lexer\Emulative(['usedAttributes' => [ - 'startLine', 'endLine', 'startFilePos', 'endFilePos', 'comments' -]]); -$parser = (new PhpParser\ParserFactory)->create( - PhpParser\ParserFactory::PREFER_PHP7, - $lexer -); -$dumper = new PhpParser\NodeDumper([ - 'dumpComments' => true, - 'dumpPositions' => $attributes['with-positions'], -]); -$prettyPrinter = new PhpParser\PrettyPrinter\Standard; - -$traverser = new PhpParser\NodeTraverser(); -$traverser->addVisitor(new PhpParser\NodeVisitor\NameResolver); - -foreach ($files as $file) { - if (strpos($file, '<?php') === 0) { - $code = $file; - fwrite(STDERR, "====> Code $code\n"); - } else { - if (!file_exists($file)) { - fwrite(STDERR, "File $file does not exist.\n"); - exit(1); - } - - $code = file_get_contents($file); - fwrite(STDERR, "====> File $file:\n"); - } - - if ($attributes['with-recovery']) { - $errorHandler = new PhpParser\ErrorHandler\Collecting; - $stmts = $parser->parse($code, $errorHandler); - foreach ($errorHandler->getErrors() as $error) { - $message = formatErrorMessage($error, $code, $attributes['with-column-info']); - fwrite(STDERR, $message . "\n"); - } - if (null === $stmts) { - continue; - } - } else { - try { - $stmts = $parser->parse($code); - } catch (PhpParser\Error $error) { - $message = formatErrorMessage($error, $code, $attributes['with-column-info']); - fwrite(STDERR, $message . "\n"); - exit(1); - } - } - - foreach ($operations as $operation) { - if ('dump' === $operation) { - fwrite(STDERR, "==> Node dump:\n"); - echo $dumper->dump($stmts, $code), "\n"; - } elseif ('pretty-print' === $operation) { - fwrite(STDERR, "==> Pretty print:\n"); - echo $prettyPrinter->prettyPrintFile($stmts), "\n"; - } elseif ('json-dump' === $operation) { - fwrite(STDERR, "==> JSON dump:\n"); - echo json_encode($stmts, JSON_PRETTY_PRINT), "\n"; - } elseif ('var-dump' === $operation) { - fwrite(STDERR, "==> var_dump():\n"); - var_dump($stmts); - } elseif ('resolve-names' === $operation) { - fwrite(STDERR, "==> Resolved names.\n"); - $stmts = $traverser->traverse($stmts); - } - } -} - -function formatErrorMessage(PhpParser\Error $e, $code, $withColumnInfo) { - if ($withColumnInfo && $e->hasColumnInfo()) { - return $e->getMessageWithColumnInfo($code); - } else { - return $e->getMessage(); - } -} - -function showHelp($error = '') { - if ($error) { - fwrite(STDERR, $error . "\n\n"); - } - fwrite($error ? STDERR : STDOUT, <<<OUTPUT -Usage: php-parse [operations] file1.php [file2.php ...] - or: php-parse [operations] "<?php code" -Turn PHP source code into an abstract syntax tree. - -Operations is a list of the following options (--dump by default): - - -d, --dump Dump nodes using NodeDumper - -p, --pretty-print Pretty print file using PrettyPrinter\Standard - -j, --json-dump Print json_encode() result - --var-dump var_dump() nodes (for exact structure) - -N, --resolve-names Resolve names using NodeVisitor\NameResolver - -c, --with-column-info Show column-numbers for errors (if available) - -P, --with-positions Show positions in node dumps - -r, --with-recovery Use parsing with error recovery - -h, --help Display this page - -Example: - php-parse -d -p -N -d file.php - - Dumps nodes, pretty prints them, then resolves names and dumps them again. - - -OUTPUT - ); - exit($error ? 1 : 0); -} - -function parseArgs($args) { - $operations = []; - $files = []; - $attributes = [ - 'with-column-info' => false, - 'with-positions' => false, - 'with-recovery' => false, - ]; - - array_shift($args); - $parseOptions = true; - foreach ($args as $arg) { - if (!$parseOptions) { - $files[] = $arg; - continue; - } - - switch ($arg) { - case '--dump': - case '-d': - $operations[] = 'dump'; - break; - case '--pretty-print': - case '-p': - $operations[] = 'pretty-print'; - break; - case '--json-dump': - case '-j': - $operations[] = 'json-dump'; - break; - case '--var-dump': - $operations[] = 'var-dump'; - break; - case '--resolve-names': - case '-N'; - $operations[] = 'resolve-names'; - break; - case '--with-column-info': - case '-c'; - $attributes['with-column-info'] = true; - break; - case '--with-positions': - case '-P': - $attributes['with-positions'] = true; - break; - case '--with-recovery': - case '-r': - $attributes['with-recovery'] = true; - break; - case '--help': - case '-h'; - showHelp(); - break; - case '--': - $parseOptions = false; - break; - default: - if ($arg[0] === '-') { - showHelp("Invalid operation $arg."); - } else { - $files[] = $arg; - } - } - } - - return [$operations, $files, $attributes]; -} diff --git a/lib/nikic/php-parser/composer.json b/lib/nikic/php-parser/composer.json deleted file mode 100644 index 2fd064a21..000000000 --- a/lib/nikic/php-parser/composer.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "name": "nikic/php-parser", - "type": "library", - "description": "A PHP parser written in PHP", - "keywords": [ - "php", - "parser" - ], - "license": "BSD-3-Clause", - "authors": [ - { - "name": "Nikita Popov" - } - ], - "require": { - "php": ">=7.0", - "ext-tokenizer": "*" - }, - "require-dev": { - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0", - "ircmaxell/php-yacc": "^0.0.7" - }, - "extra": { - "branch-alias": { - "dev-master": "4.9-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "autoload-dev": { - "psr-4": { - "PhpParser\\": "test/PhpParser/" - } - }, - "bin": [ - "bin/php-parse" - ] -} diff --git a/lib/nikic/php-parser/grammar/README.md b/lib/nikic/php-parser/grammar/README.md deleted file mode 100644 index 4bae11d82..000000000 --- a/lib/nikic/php-parser/grammar/README.md +++ /dev/null @@ -1,30 +0,0 @@ -What do all those files mean? -============================= - - * `php5.y`: PHP 5 grammar written in a pseudo language - * `php7.y`: PHP 7 grammar written in a pseudo language - * `tokens.y`: Tokens definition shared between PHP 5 and PHP 7 grammars - * `parser.template`: A `kmyacc` parser prototype file for PHP - * `tokens.template`: A `kmyacc` prototype file for the `Tokens` class - * `rebuildParsers.php`: Preprocesses the grammar and builds the parser using `kmyacc` - -.phpy pseudo language -===================== - -The `.y` file is a normal grammar in `kmyacc` (`yacc`) style, with some transformations -applied to it: - - * Nodes are created using the syntax `Name[..., ...]`. This is transformed into - `new Name(..., ..., attributes())` - * Some function-like constructs are resolved (see `rebuildParsers.php` for a list) - -Building the parser -=================== - -Run `php grammar/rebuildParsers.php` to rebuild the parsers. Additional options: - - * The `KMYACC` environment variable can be used to specify an alternative `kmyacc` binary. - By default the `phpyacc` dev dependency will be used. To use the original `kmyacc`, you - need to compile [moriyoshi's fork](https://github.com/moriyoshi/kmyacc-forked). - * The `--debug` option enables emission of debug symbols and creates the `y.output` file. - * The `--keep-tmp-grammar` option preserves the preprocessed grammar file. diff --git a/lib/nikic/php-parser/grammar/parser.template b/lib/nikic/php-parser/grammar/parser.template deleted file mode 100644 index 6166607c9..000000000 --- a/lib/nikic/php-parser/grammar/parser.template +++ /dev/null @@ -1,106 +0,0 @@ -<?php -$meta # -#semval($) $this->semValue -#semval($,%t) $this->semValue -#semval(%n) $stackPos-(%l-%n) -#semval(%n,%t) $stackPos-(%l-%n) - -namespace PhpParser\Parser; - -use PhpParser\Error; -use PhpParser\Node; -use PhpParser\Node\Expr; -use PhpParser\Node\Name; -use PhpParser\Node\Scalar; -use PhpParser\Node\Stmt; -#include; - -/* This is an automatically GENERATED file, which should not be manually edited. - * Instead edit one of the following: - * * the grammar files grammar/php5.y or grammar/php7.y - * * the skeleton file grammar/parser.template - * * the preprocessing script grammar/rebuildParsers.php - */ -class #(-p) extends \PhpParser\ParserAbstract -{ - protected $tokenToSymbolMapSize = #(YYMAXLEX); - protected $actionTableSize = #(YYLAST); - protected $gotoTableSize = #(YYGLAST); - - protected $invalidSymbol = #(YYBADCH); - protected $errorSymbol = #(YYINTERRTOK); - protected $defaultAction = #(YYDEFAULT); - protected $unexpectedTokenRule = #(YYUNEXPECTED); - - protected $YY2TBLSTATE = #(YY2TBLSTATE); - protected $numNonLeafStates = #(YYNLSTATES); - - protected $symbolToName = array( - #listvar terminals - ); - - protected $tokenToSymbol = array( - #listvar yytranslate - ); - - protected $action = array( - #listvar yyaction - ); - - protected $actionCheck = array( - #listvar yycheck - ); - - protected $actionBase = array( - #listvar yybase - ); - - protected $actionDefault = array( - #listvar yydefault - ); - - protected $goto = array( - #listvar yygoto - ); - - protected $gotoCheck = array( - #listvar yygcheck - ); - - protected $gotoBase = array( - #listvar yygbase - ); - - protected $gotoDefault = array( - #listvar yygdefault - ); - - protected $ruleToNonTerminal = array( - #listvar yylhs - ); - - protected $ruleToLength = array( - #listvar yylen - ); -#if -t - - protected $productions = array( - #production-strings; - ); -#endif - - protected function initReduceCallbacks() { - $this->reduceCallbacks = [ -#reduce - %n => function ($stackPos) { - %b - }, -#noact - %n => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, -#endreduce - ]; - } -} -#tailcode; diff --git a/lib/nikic/php-parser/grammar/php5.y b/lib/nikic/php-parser/grammar/php5.y deleted file mode 100644 index a62e9a310..000000000 --- a/lib/nikic/php-parser/grammar/php5.y +++ /dev/null @@ -1,1036 +0,0 @@ -%pure_parser -%expect 6 - -%tokens - -%% - -start: - top_statement_list { $$ = $this->handleNamespaces($1); } -; - -top_statement_list_ex: - top_statement_list_ex top_statement { pushNormalizing($1, $2); } - | /* empty */ { init(); } -; - -top_statement_list: - top_statement_list_ex - { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); - if ($nop !== null) { $1[] = $nop; } $$ = $1; } -; - -ampersand: - T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG - | T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG -; - -reserved_non_modifiers: - T_INCLUDE | T_INCLUDE_ONCE | T_EVAL | T_REQUIRE | T_REQUIRE_ONCE | T_LOGICAL_OR | T_LOGICAL_XOR | T_LOGICAL_AND - | T_INSTANCEOF | T_NEW | T_CLONE | T_EXIT | T_IF | T_ELSEIF | T_ELSE | T_ENDIF | T_ECHO | T_DO | T_WHILE - | T_ENDWHILE | T_FOR | T_ENDFOR | T_FOREACH | T_ENDFOREACH | T_DECLARE | T_ENDDECLARE | T_AS | T_TRY | T_CATCH - | T_FINALLY | T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO - | T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT - | T_BREAK | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS - | T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_HALT_COMPILER | T_FN - | T_MATCH -; - -semi_reserved: - reserved_non_modifiers - | T_STATIC | T_ABSTRACT | T_FINAL | T_PRIVATE | T_PROTECTED | T_PUBLIC -; - -identifier_ex: - T_STRING { $$ = Node\Identifier[$1]; } - | semi_reserved { $$ = Node\Identifier[$1]; } -; - -identifier: - T_STRING { $$ = Node\Identifier[$1]; } -; - -reserved_non_modifiers_identifier: - reserved_non_modifiers { $$ = Node\Identifier[$1]; } -; - -namespace_name: - T_STRING { $$ = Name[$1]; } - | T_NAME_QUALIFIED { $$ = Name[$1]; } -; - -legacy_namespace_name: - namespace_name { $$ = $1; } - | T_NAME_FULLY_QUALIFIED { $$ = Name[substr($1, 1)]; } -; - -plain_variable: - T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; } -; - -top_statement: - statement { $$ = $1; } - | function_declaration_statement { $$ = $1; } - | class_declaration_statement { $$ = $1; } - | T_HALT_COMPILER - { $$ = Stmt\HaltCompiler[$this->lexer->handleHaltCompiler()]; } - | T_NAMESPACE namespace_name ';' - { $$ = Stmt\Namespace_[$2, null]; - $$->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON); - $this->checkNamespace($$); } - | T_NAMESPACE namespace_name '{' top_statement_list '}' - { $$ = Stmt\Namespace_[$2, $4]; - $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); - $this->checkNamespace($$); } - | T_NAMESPACE '{' top_statement_list '}' - { $$ = Stmt\Namespace_[null, $3]; - $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); - $this->checkNamespace($$); } - | T_USE use_declarations ';' { $$ = Stmt\Use_[$2, Stmt\Use_::TYPE_NORMAL]; } - | T_USE use_type use_declarations ';' { $$ = Stmt\Use_[$3, $2]; } - | group_use_declaration ';' { $$ = $1; } - | T_CONST constant_declaration_list ';' { $$ = Stmt\Const_[$2]; } -; - -use_type: - T_FUNCTION { $$ = Stmt\Use_::TYPE_FUNCTION; } - | T_CONST { $$ = Stmt\Use_::TYPE_CONSTANT; } -; - -group_use_declaration: - T_USE use_type legacy_namespace_name T_NS_SEPARATOR '{' unprefixed_use_declarations '}' - { $$ = Stmt\GroupUse[$3, $6, $2]; } - | T_USE legacy_namespace_name T_NS_SEPARATOR '{' inline_use_declarations '}' - { $$ = Stmt\GroupUse[$2, $5, Stmt\Use_::TYPE_UNKNOWN]; } -; - -unprefixed_use_declarations: - unprefixed_use_declarations ',' unprefixed_use_declaration - { push($1, $3); } - | unprefixed_use_declaration { init($1); } -; - -use_declarations: - use_declarations ',' use_declaration { push($1, $3); } - | use_declaration { init($1); } -; - -inline_use_declarations: - inline_use_declarations ',' inline_use_declaration { push($1, $3); } - | inline_use_declaration { init($1); } -; - -unprefixed_use_declaration: - namespace_name - { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); } - | namespace_name T_AS identifier - { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); } -; - -use_declaration: - legacy_namespace_name - { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); } - | legacy_namespace_name T_AS identifier - { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); } -; - -inline_use_declaration: - unprefixed_use_declaration { $$ = $1; $$->type = Stmt\Use_::TYPE_NORMAL; } - | use_type unprefixed_use_declaration { $$ = $2; $$->type = $1; } -; - -constant_declaration_list: - constant_declaration_list ',' constant_declaration { push($1, $3); } - | constant_declaration { init($1); } -; - -constant_declaration: - identifier '=' static_scalar { $$ = Node\Const_[$1, $3]; } -; - -class_const_list: - class_const_list ',' class_const { push($1, $3); } - | class_const { init($1); } -; - -class_const: - identifier_ex '=' static_scalar { $$ = Node\Const_[$1, $3]; } -; - -inner_statement_list_ex: - inner_statement_list_ex inner_statement { pushNormalizing($1, $2); } - | /* empty */ { init(); } -; - -inner_statement_list: - inner_statement_list_ex - { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); - if ($nop !== null) { $1[] = $nop; } $$ = $1; } -; - -inner_statement: - statement { $$ = $1; } - | function_declaration_statement { $$ = $1; } - | class_declaration_statement { $$ = $1; } - | T_HALT_COMPILER - { throw new Error('__HALT_COMPILER() can only be used from the outermost scope', attributes()); } -; - -non_empty_statement: - '{' inner_statement_list '}' - { - if ($2) { - $$ = $2; prependLeadingComments($$); - } else { - makeNop($$, $this->startAttributeStack[#1], $this->endAttributes); - if (null === $$) { $$ = array(); } - } - } - | T_IF parentheses_expr statement elseif_list else_single - { $$ = Stmt\If_[$2, ['stmts' => toArray($3), 'elseifs' => $4, 'else' => $5]]; } - | T_IF parentheses_expr ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';' - { $$ = Stmt\If_[$2, ['stmts' => $4, 'elseifs' => $5, 'else' => $6]]; } - | T_WHILE parentheses_expr while_statement { $$ = Stmt\While_[$2, $3]; } - | T_DO statement T_WHILE parentheses_expr ';' { $$ = Stmt\Do_ [$4, toArray($2)]; } - | T_FOR '(' for_expr ';' for_expr ';' for_expr ')' for_statement - { $$ = Stmt\For_[['init' => $3, 'cond' => $5, 'loop' => $7, 'stmts' => $9]]; } - | T_SWITCH parentheses_expr switch_case_list { $$ = Stmt\Switch_[$2, $3]; } - | T_BREAK ';' { $$ = Stmt\Break_[null]; } - | T_BREAK expr ';' { $$ = Stmt\Break_[$2]; } - | T_CONTINUE ';' { $$ = Stmt\Continue_[null]; } - | T_CONTINUE expr ';' { $$ = Stmt\Continue_[$2]; } - | T_RETURN ';' { $$ = Stmt\Return_[null]; } - | T_RETURN expr ';' { $$ = Stmt\Return_[$2]; } - | T_GLOBAL global_var_list ';' { $$ = Stmt\Global_[$2]; } - | T_STATIC static_var_list ';' { $$ = Stmt\Static_[$2]; } - | T_ECHO expr_list ';' { $$ = Stmt\Echo_[$2]; } - | T_INLINE_HTML { $$ = Stmt\InlineHTML[$1]; } - | yield_expr ';' { $$ = Stmt\Expression[$1]; } - | expr ';' { $$ = Stmt\Expression[$1]; } - | T_UNSET '(' variables_list ')' ';' { $$ = Stmt\Unset_[$3]; } - | T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement - { $$ = Stmt\Foreach_[$3, $5[0], ['keyVar' => null, 'byRef' => $5[1], 'stmts' => $7]]; } - | T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_statement - { $$ = Stmt\Foreach_[$3, $7[0], ['keyVar' => $5, 'byRef' => $7[1], 'stmts' => $9]]; } - | T_DECLARE '(' declare_list ')' declare_statement { $$ = Stmt\Declare_[$3, $5]; } - | T_TRY '{' inner_statement_list '}' catches optional_finally - { $$ = Stmt\TryCatch[$3, $5, $6]; $this->checkTryCatch($$); } - | T_THROW expr ';' { $$ = Stmt\Throw_[$2]; } - | T_GOTO identifier ';' { $$ = Stmt\Goto_[$2]; } - | identifier ':' { $$ = Stmt\Label[$1]; } - | expr error { $$ = Stmt\Expression[$1]; } - | error { $$ = array(); /* means: no statement */ } -; - -statement: - non_empty_statement { $$ = $1; } - | ';' - { makeNop($$, $this->startAttributeStack[#1], $this->endAttributes); - if ($$ === null) $$ = array(); /* means: no statement */ } -; - -catches: - /* empty */ { init(); } - | catches catch { push($1, $2); } -; - -catch: - T_CATCH '(' name plain_variable ')' '{' inner_statement_list '}' - { $$ = Stmt\Catch_[array($3), $4, $7]; } -; - -optional_finally: - /* empty */ { $$ = null; } - | T_FINALLY '{' inner_statement_list '}' { $$ = Stmt\Finally_[$3]; } -; - -variables_list: - variable { init($1); } - | variables_list ',' variable { push($1, $3); } -; - -optional_ref: - /* empty */ { $$ = false; } - | ampersand { $$ = true; } -; - -optional_arg_ref: - /* empty */ { $$ = false; } - | T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG { $$ = true; } -; - -optional_ellipsis: - /* empty */ { $$ = false; } - | T_ELLIPSIS { $$ = true; } -; - -function_declaration_statement: - T_FUNCTION optional_ref identifier '(' parameter_list ')' optional_return_type '{' inner_statement_list '}' - { $$ = Stmt\Function_[$3, ['byRef' => $2, 'params' => $5, 'returnType' => $7, 'stmts' => $9]]; } -; - -class_declaration_statement: - class_entry_type identifier extends_from implements_list '{' class_statement_list '}' - { $$ = Stmt\Class_[$2, ['type' => $1, 'extends' => $3, 'implements' => $4, 'stmts' => $6]]; - $this->checkClass($$, #2); } - | T_INTERFACE identifier interface_extends_list '{' class_statement_list '}' - { $$ = Stmt\Interface_[$2, ['extends' => $3, 'stmts' => $5]]; - $this->checkInterface($$, #2); } - | T_TRAIT identifier '{' class_statement_list '}' - { $$ = Stmt\Trait_[$2, ['stmts' => $4]]; } -; - -class_entry_type: - T_CLASS { $$ = 0; } - | T_ABSTRACT T_CLASS { $$ = Stmt\Class_::MODIFIER_ABSTRACT; } - | T_FINAL T_CLASS { $$ = Stmt\Class_::MODIFIER_FINAL; } -; - -extends_from: - /* empty */ { $$ = null; } - | T_EXTENDS class_name { $$ = $2; } -; - -interface_extends_list: - /* empty */ { $$ = array(); } - | T_EXTENDS class_name_list { $$ = $2; } -; - -implements_list: - /* empty */ { $$ = array(); } - | T_IMPLEMENTS class_name_list { $$ = $2; } -; - -class_name_list: - class_name { init($1); } - | class_name_list ',' class_name { push($1, $3); } -; - -for_statement: - statement { $$ = toArray($1); } - | ':' inner_statement_list T_ENDFOR ';' { $$ = $2; } -; - -foreach_statement: - statement { $$ = toArray($1); } - | ':' inner_statement_list T_ENDFOREACH ';' { $$ = $2; } -; - -declare_statement: - non_empty_statement { $$ = toArray($1); } - | ';' { $$ = null; } - | ':' inner_statement_list T_ENDDECLARE ';' { $$ = $2; } -; - -declare_list: - declare_list_element { init($1); } - | declare_list ',' declare_list_element { push($1, $3); } -; - -declare_list_element: - identifier '=' static_scalar { $$ = Stmt\DeclareDeclare[$1, $3]; } -; - -switch_case_list: - '{' case_list '}' { $$ = $2; } - | '{' ';' case_list '}' { $$ = $3; } - | ':' case_list T_ENDSWITCH ';' { $$ = $2; } - | ':' ';' case_list T_ENDSWITCH ';' { $$ = $3; } -; - -case_list: - /* empty */ { init(); } - | case_list case { push($1, $2); } -; - -case: - T_CASE expr case_separator inner_statement_list_ex { $$ = Stmt\Case_[$2, $4]; } - | T_DEFAULT case_separator inner_statement_list_ex { $$ = Stmt\Case_[null, $3]; } -; - -case_separator: - ':' - | ';' -; - -while_statement: - statement { $$ = toArray($1); } - | ':' inner_statement_list T_ENDWHILE ';' { $$ = $2; } -; - -elseif_list: - /* empty */ { init(); } - | elseif_list elseif { push($1, $2); } -; - -elseif: - T_ELSEIF parentheses_expr statement { $$ = Stmt\ElseIf_[$2, toArray($3)]; } -; - -new_elseif_list: - /* empty */ { init(); } - | new_elseif_list new_elseif { push($1, $2); } -; - -new_elseif: - T_ELSEIF parentheses_expr ':' inner_statement_list { $$ = Stmt\ElseIf_[$2, $4]; } -; - -else_single: - /* empty */ { $$ = null; } - | T_ELSE statement { $$ = Stmt\Else_[toArray($2)]; } -; - -new_else_single: - /* empty */ { $$ = null; } - | T_ELSE ':' inner_statement_list { $$ = Stmt\Else_[$3]; } -; - -foreach_variable: - variable { $$ = array($1, false); } - | ampersand variable { $$ = array($2, true); } - | list_expr { $$ = array($1, false); } -; - -parameter_list: - non_empty_parameter_list { $$ = $1; } - | /* empty */ { $$ = array(); } -; - -non_empty_parameter_list: - parameter { init($1); } - | non_empty_parameter_list ',' parameter { push($1, $3); } -; - -parameter: - optional_param_type optional_arg_ref optional_ellipsis plain_variable - { $$ = Node\Param[$4, null, $1, $2, $3]; $this->checkParam($$); } - | optional_param_type optional_arg_ref optional_ellipsis plain_variable '=' static_scalar - { $$ = Node\Param[$4, $6, $1, $2, $3]; $this->checkParam($$); } -; - -type: - name { $$ = $1; } - | T_ARRAY { $$ = Node\Identifier['array']; } - | T_CALLABLE { $$ = Node\Identifier['callable']; } -; - -optional_param_type: - /* empty */ { $$ = null; } - | type { $$ = $1; } -; - -optional_return_type: - /* empty */ { $$ = null; } - | ':' type { $$ = $2; } -; - -argument_list: - '(' ')' { $$ = array(); } - | '(' non_empty_argument_list ')' { $$ = $2; } - | '(' yield_expr ')' { $$ = array(Node\Arg[$2, false, false]); } -; - -non_empty_argument_list: - argument { init($1); } - | non_empty_argument_list ',' argument { push($1, $3); } -; - -argument: - expr { $$ = Node\Arg[$1, false, false]; } - | ampersand variable { $$ = Node\Arg[$2, true, false]; } - | T_ELLIPSIS expr { $$ = Node\Arg[$2, false, true]; } -; - -global_var_list: - global_var_list ',' global_var { push($1, $3); } - | global_var { init($1); } -; - -global_var: - plain_variable { $$ = $1; } - | '$' variable { $$ = Expr\Variable[$2]; } - | '$' '{' expr '}' { $$ = Expr\Variable[$3]; } -; - -static_var_list: - static_var_list ',' static_var { push($1, $3); } - | static_var { init($1); } -; - -static_var: - plain_variable { $$ = Stmt\StaticVar[$1, null]; } - | plain_variable '=' static_scalar { $$ = Stmt\StaticVar[$1, $3]; } -; - -class_statement_list_ex: - class_statement_list_ex class_statement { if ($2 !== null) { push($1, $2); } } - | /* empty */ { init(); } -; - -class_statement_list: - class_statement_list_ex - { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); - if ($nop !== null) { $1[] = $nop; } $$ = $1; } -; - -class_statement: - variable_modifiers property_declaration_list ';' - { $$ = Stmt\Property[$1, $2]; $this->checkProperty($$, #1); } - | T_CONST class_const_list ';' { $$ = Stmt\ClassConst[$2, 0]; } - | method_modifiers T_FUNCTION optional_ref identifier_ex '(' parameter_list ')' optional_return_type method_body - { $$ = Stmt\ClassMethod[$4, ['type' => $1, 'byRef' => $3, 'params' => $6, 'returnType' => $8, 'stmts' => $9]]; - $this->checkClassMethod($$, #1); } - | T_USE class_name_list trait_adaptations { $$ = Stmt\TraitUse[$2, $3]; } -; - -trait_adaptations: - ';' { $$ = array(); } - | '{' trait_adaptation_list '}' { $$ = $2; } -; - -trait_adaptation_list: - /* empty */ { init(); } - | trait_adaptation_list trait_adaptation { push($1, $2); } -; - -trait_adaptation: - trait_method_reference_fully_qualified T_INSTEADOF class_name_list ';' - { $$ = Stmt\TraitUseAdaptation\Precedence[$1[0], $1[1], $3]; } - | trait_method_reference T_AS member_modifier identifier_ex ';' - { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, $4]; } - | trait_method_reference T_AS member_modifier ';' - { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, null]; } - | trait_method_reference T_AS identifier ';' - { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; } - | trait_method_reference T_AS reserved_non_modifiers_identifier ';' - { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; } -; - -trait_method_reference_fully_qualified: - name T_PAAMAYIM_NEKUDOTAYIM identifier_ex { $$ = array($1, $3); } -; -trait_method_reference: - trait_method_reference_fully_qualified { $$ = $1; } - | identifier_ex { $$ = array(null, $1); } -; - -method_body: - ';' /* abstract method */ { $$ = null; } - | '{' inner_statement_list '}' { $$ = $2; } -; - -variable_modifiers: - non_empty_member_modifiers { $$ = $1; } - | T_VAR { $$ = 0; } -; - -method_modifiers: - /* empty */ { $$ = 0; } - | non_empty_member_modifiers { $$ = $1; } -; - -non_empty_member_modifiers: - member_modifier { $$ = $1; } - | non_empty_member_modifiers member_modifier { $this->checkModifier($1, $2, #2); $$ = $1 | $2; } -; - -member_modifier: - T_PUBLIC { $$ = Stmt\Class_::MODIFIER_PUBLIC; } - | T_PROTECTED { $$ = Stmt\Class_::MODIFIER_PROTECTED; } - | T_PRIVATE { $$ = Stmt\Class_::MODIFIER_PRIVATE; } - | T_STATIC { $$ = Stmt\Class_::MODIFIER_STATIC; } - | T_ABSTRACT { $$ = Stmt\Class_::MODIFIER_ABSTRACT; } - | T_FINAL { $$ = Stmt\Class_::MODIFIER_FINAL; } -; - -property_declaration_list: - property_declaration { init($1); } - | property_declaration_list ',' property_declaration { push($1, $3); } -; - -property_decl_name: - T_VARIABLE { $$ = Node\VarLikeIdentifier[parseVar($1)]; } -; - -property_declaration: - property_decl_name { $$ = Stmt\PropertyProperty[$1, null]; } - | property_decl_name '=' static_scalar { $$ = Stmt\PropertyProperty[$1, $3]; } -; - -expr_list: - expr_list ',' expr { push($1, $3); } - | expr { init($1); } -; - -for_expr: - /* empty */ { $$ = array(); } - | expr_list { $$ = $1; } -; - -expr: - variable { $$ = $1; } - | list_expr '=' expr { $$ = Expr\Assign[$1, $3]; } - | variable '=' expr { $$ = Expr\Assign[$1, $3]; } - | variable '=' ampersand variable { $$ = Expr\AssignRef[$1, $4]; } - | variable '=' ampersand new_expr { $$ = Expr\AssignRef[$1, $4]; } - | new_expr { $$ = $1; } - | T_CLONE expr { $$ = Expr\Clone_[$2]; } - | variable T_PLUS_EQUAL expr { $$ = Expr\AssignOp\Plus [$1, $3]; } - | variable T_MINUS_EQUAL expr { $$ = Expr\AssignOp\Minus [$1, $3]; } - | variable T_MUL_EQUAL expr { $$ = Expr\AssignOp\Mul [$1, $3]; } - | variable T_DIV_EQUAL expr { $$ = Expr\AssignOp\Div [$1, $3]; } - | variable T_CONCAT_EQUAL expr { $$ = Expr\AssignOp\Concat [$1, $3]; } - | variable T_MOD_EQUAL expr { $$ = Expr\AssignOp\Mod [$1, $3]; } - | variable T_AND_EQUAL expr { $$ = Expr\AssignOp\BitwiseAnd[$1, $3]; } - | variable T_OR_EQUAL expr { $$ = Expr\AssignOp\BitwiseOr [$1, $3]; } - | variable T_XOR_EQUAL expr { $$ = Expr\AssignOp\BitwiseXor[$1, $3]; } - | variable T_SL_EQUAL expr { $$ = Expr\AssignOp\ShiftLeft [$1, $3]; } - | variable T_SR_EQUAL expr { $$ = Expr\AssignOp\ShiftRight[$1, $3]; } - | variable T_POW_EQUAL expr { $$ = Expr\AssignOp\Pow [$1, $3]; } - | variable T_COALESCE_EQUAL expr { $$ = Expr\AssignOp\Coalesce [$1, $3]; } - | variable T_INC { $$ = Expr\PostInc[$1]; } - | T_INC variable { $$ = Expr\PreInc [$2]; } - | variable T_DEC { $$ = Expr\PostDec[$1]; } - | T_DEC variable { $$ = Expr\PreDec [$2]; } - | expr T_BOOLEAN_OR expr { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; } - | expr T_BOOLEAN_AND expr { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; } - | expr T_LOGICAL_OR expr { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; } - | expr T_LOGICAL_AND expr { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; } - | expr T_LOGICAL_XOR expr { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; } - | expr '|' expr { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; } - | expr T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } - | expr T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } - | expr '^' expr { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; } - | expr '.' expr { $$ = Expr\BinaryOp\Concat [$1, $3]; } - | expr '+' expr { $$ = Expr\BinaryOp\Plus [$1, $3]; } - | expr '-' expr { $$ = Expr\BinaryOp\Minus [$1, $3]; } - | expr '*' expr { $$ = Expr\BinaryOp\Mul [$1, $3]; } - | expr '/' expr { $$ = Expr\BinaryOp\Div [$1, $3]; } - | expr '%' expr { $$ = Expr\BinaryOp\Mod [$1, $3]; } - | expr T_SL expr { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; } - | expr T_SR expr { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; } - | expr T_POW expr { $$ = Expr\BinaryOp\Pow [$1, $3]; } - | '+' expr %prec T_INC { $$ = Expr\UnaryPlus [$2]; } - | '-' expr %prec T_INC { $$ = Expr\UnaryMinus[$2]; } - | '!' expr { $$ = Expr\BooleanNot[$2]; } - | '~' expr { $$ = Expr\BitwiseNot[$2]; } - | expr T_IS_IDENTICAL expr { $$ = Expr\BinaryOp\Identical [$1, $3]; } - | expr T_IS_NOT_IDENTICAL expr { $$ = Expr\BinaryOp\NotIdentical [$1, $3]; } - | expr T_IS_EQUAL expr { $$ = Expr\BinaryOp\Equal [$1, $3]; } - | expr T_IS_NOT_EQUAL expr { $$ = Expr\BinaryOp\NotEqual [$1, $3]; } - | expr T_SPACESHIP expr { $$ = Expr\BinaryOp\Spaceship [$1, $3]; } - | expr '<' expr { $$ = Expr\BinaryOp\Smaller [$1, $3]; } - | expr T_IS_SMALLER_OR_EQUAL expr { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; } - | expr '>' expr { $$ = Expr\BinaryOp\Greater [$1, $3]; } - | expr T_IS_GREATER_OR_EQUAL expr { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; } - | expr T_INSTANCEOF class_name_reference { $$ = Expr\Instanceof_[$1, $3]; } - | parentheses_expr { $$ = $1; } - /* we need a separate '(' new_expr ')' rule to avoid problems caused by a s/r conflict */ - | '(' new_expr ')' { $$ = $2; } - | expr '?' expr ':' expr { $$ = Expr\Ternary[$1, $3, $5]; } - | expr '?' ':' expr { $$ = Expr\Ternary[$1, null, $4]; } - | expr T_COALESCE expr { $$ = Expr\BinaryOp\Coalesce[$1, $3]; } - | T_ISSET '(' variables_list ')' { $$ = Expr\Isset_[$3]; } - | T_EMPTY '(' expr ')' { $$ = Expr\Empty_[$3]; } - | T_INCLUDE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE]; } - | T_INCLUDE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE_ONCE]; } - | T_EVAL parentheses_expr { $$ = Expr\Eval_[$2]; } - | T_REQUIRE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE]; } - | T_REQUIRE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE_ONCE]; } - | T_INT_CAST expr { $$ = Expr\Cast\Int_ [$2]; } - | T_DOUBLE_CAST expr - { $attrs = attributes(); - $attrs['kind'] = $this->getFloatCastKind($1); - $$ = new Expr\Cast\Double($2, $attrs); } - | T_STRING_CAST expr { $$ = Expr\Cast\String_ [$2]; } - | T_ARRAY_CAST expr { $$ = Expr\Cast\Array_ [$2]; } - | T_OBJECT_CAST expr { $$ = Expr\Cast\Object_ [$2]; } - | T_BOOL_CAST expr { $$ = Expr\Cast\Bool_ [$2]; } - | T_UNSET_CAST expr { $$ = Expr\Cast\Unset_ [$2]; } - | T_EXIT exit_expr - { $attrs = attributes(); - $attrs['kind'] = strtolower($1) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE; - $$ = new Expr\Exit_($2, $attrs); } - | '@' expr { $$ = Expr\ErrorSuppress[$2]; } - | scalar { $$ = $1; } - | array_expr { $$ = $1; } - | scalar_dereference { $$ = $1; } - | '`' backticks_expr '`' { $$ = Expr\ShellExec[$2]; } - | T_PRINT expr { $$ = Expr\Print_[$2]; } - | T_YIELD { $$ = Expr\Yield_[null, null]; } - | T_YIELD_FROM expr { $$ = Expr\YieldFrom[$2]; } - | T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type - '{' inner_statement_list '}' - { $$ = Expr\Closure[['static' => false, 'byRef' => $2, 'params' => $4, 'uses' => $6, 'returnType' => $7, 'stmts' => $9]]; } - | T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type - '{' inner_statement_list '}' - { $$ = Expr\Closure[['static' => true, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $10]]; } -; - -parentheses_expr: - '(' expr ')' { $$ = $2; } - | '(' yield_expr ')' { $$ = $2; } -; - -yield_expr: - T_YIELD expr { $$ = Expr\Yield_[$2, null]; } - | T_YIELD expr T_DOUBLE_ARROW expr { $$ = Expr\Yield_[$4, $2]; } -; - -array_expr: - T_ARRAY '(' array_pair_list ')' - { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_LONG; - $$ = new Expr\Array_($3, $attrs); } - | '[' array_pair_list ']' - { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_SHORT; - $$ = new Expr\Array_($2, $attrs); } -; - -scalar_dereference: - array_expr '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } - | T_CONSTANT_ENCAPSED_STRING '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[Scalar\String_::fromString($1, attributes()), $3]; } - | constant '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } - | scalar_dereference '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } - /* alternative array syntax missing intentionally */ -; - -anonymous_class: - T_CLASS ctor_arguments extends_from implements_list '{' class_statement_list '}' - { $$ = array(Stmt\Class_[null, ['type' => 0, 'extends' => $3, 'implements' => $4, 'stmts' => $6]], $2); - $this->checkClass($$[0], -1); } -; - -new_expr: - T_NEW class_name_reference ctor_arguments { $$ = Expr\New_[$2, $3]; } - | T_NEW anonymous_class - { list($class, $ctorArgs) = $2; $$ = Expr\New_[$class, $ctorArgs]; } -; - -lexical_vars: - /* empty */ { $$ = array(); } - | T_USE '(' lexical_var_list ')' { $$ = $3; } -; - -lexical_var_list: - lexical_var { init($1); } - | lexical_var_list ',' lexical_var { push($1, $3); } -; - -lexical_var: - optional_ref plain_variable { $$ = Expr\ClosureUse[$2, $1]; } -; - -function_call: - name argument_list { $$ = Expr\FuncCall[$1, $2]; } - | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier_ex argument_list - { $$ = Expr\StaticCall[$1, $3, $4]; } - | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '{' expr '}' argument_list - { $$ = Expr\StaticCall[$1, $4, $6]; } - | static_property argument_list - { $$ = $this->fixupPhp5StaticPropCall($1, $2, attributes()); } - | variable_without_objects argument_list - { $$ = Expr\FuncCall[$1, $2]; } - | function_call '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } - /* alternative array syntax missing intentionally */ -; - -class_name: - T_STATIC { $$ = Name[$1]; } - | name { $$ = $1; } -; - -name: - T_STRING { $$ = Name[$1]; } - | T_NAME_QUALIFIED { $$ = Name[$1]; } - | T_NAME_FULLY_QUALIFIED { $$ = Name\FullyQualified[substr($1, 1)]; } - | T_NAME_RELATIVE { $$ = Name\Relative[substr($1, 10)]; } -; - -class_name_reference: - class_name { $$ = $1; } - | dynamic_class_name_reference { $$ = $1; } -; - -dynamic_class_name_reference: - object_access_for_dcnr { $$ = $1; } - | base_variable { $$ = $1; } -; - -class_name_or_var: - class_name { $$ = $1; } - | reference_variable { $$ = $1; } -; - -object_access_for_dcnr: - base_variable T_OBJECT_OPERATOR object_property - { $$ = Expr\PropertyFetch[$1, $3]; } - | object_access_for_dcnr T_OBJECT_OPERATOR object_property - { $$ = Expr\PropertyFetch[$1, $3]; } - | object_access_for_dcnr '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } - | object_access_for_dcnr '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } -; - -exit_expr: - /* empty */ { $$ = null; } - | '(' ')' { $$ = null; } - | parentheses_expr { $$ = $1; } -; - -backticks_expr: - /* empty */ { $$ = array(); } - | T_ENCAPSED_AND_WHITESPACE - { $$ = array(Scalar\EncapsedStringPart[Scalar\String_::parseEscapeSequences($1, '`', false)]); } - | encaps_list { parseEncapsed($1, '`', false); $$ = $1; } -; - -ctor_arguments: - /* empty */ { $$ = array(); } - | argument_list { $$ = $1; } -; - -common_scalar: - T_LNUMBER { $$ = $this->parseLNumber($1, attributes(), true); } - | T_DNUMBER { $$ = Scalar\DNumber::fromString($1, attributes()); } - | T_CONSTANT_ENCAPSED_STRING { $$ = Scalar\String_::fromString($1, attributes(), false); } - | T_LINE { $$ = Scalar\MagicConst\Line[]; } - | T_FILE { $$ = Scalar\MagicConst\File[]; } - | T_DIR { $$ = Scalar\MagicConst\Dir[]; } - | T_CLASS_C { $$ = Scalar\MagicConst\Class_[]; } - | T_TRAIT_C { $$ = Scalar\MagicConst\Trait_[]; } - | T_METHOD_C { $$ = Scalar\MagicConst\Method[]; } - | T_FUNC_C { $$ = Scalar\MagicConst\Function_[]; } - | T_NS_C { $$ = Scalar\MagicConst\Namespace_[]; } - | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC - { $$ = $this->parseDocString($1, $2, $3, attributes(), stackAttributes(#3), false); } - | T_START_HEREDOC T_END_HEREDOC - { $$ = $this->parseDocString($1, '', $2, attributes(), stackAttributes(#2), false); } -; - -static_scalar: - common_scalar { $$ = $1; } - | class_name T_PAAMAYIM_NEKUDOTAYIM identifier_ex { $$ = Expr\ClassConstFetch[$1, $3]; } - | name { $$ = Expr\ConstFetch[$1]; } - | T_ARRAY '(' static_array_pair_list ')' { $$ = Expr\Array_[$3]; } - | '[' static_array_pair_list ']' { $$ = Expr\Array_[$2]; } - | static_operation { $$ = $1; } -; - -static_operation: - static_scalar T_BOOLEAN_OR static_scalar { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; } - | static_scalar T_BOOLEAN_AND static_scalar { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; } - | static_scalar T_LOGICAL_OR static_scalar { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; } - | static_scalar T_LOGICAL_AND static_scalar { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; } - | static_scalar T_LOGICAL_XOR static_scalar { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; } - | static_scalar '|' static_scalar { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; } - | static_scalar T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG static_scalar - { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } - | static_scalar T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG static_scalar - { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } - | static_scalar '^' static_scalar { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; } - | static_scalar '.' static_scalar { $$ = Expr\BinaryOp\Concat [$1, $3]; } - | static_scalar '+' static_scalar { $$ = Expr\BinaryOp\Plus [$1, $3]; } - | static_scalar '-' static_scalar { $$ = Expr\BinaryOp\Minus [$1, $3]; } - | static_scalar '*' static_scalar { $$ = Expr\BinaryOp\Mul [$1, $3]; } - | static_scalar '/' static_scalar { $$ = Expr\BinaryOp\Div [$1, $3]; } - | static_scalar '%' static_scalar { $$ = Expr\BinaryOp\Mod [$1, $3]; } - | static_scalar T_SL static_scalar { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; } - | static_scalar T_SR static_scalar { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; } - | static_scalar T_POW static_scalar { $$ = Expr\BinaryOp\Pow [$1, $3]; } - | '+' static_scalar %prec T_INC { $$ = Expr\UnaryPlus [$2]; } - | '-' static_scalar %prec T_INC { $$ = Expr\UnaryMinus[$2]; } - | '!' static_scalar { $$ = Expr\BooleanNot[$2]; } - | '~' static_scalar { $$ = Expr\BitwiseNot[$2]; } - | static_scalar T_IS_IDENTICAL static_scalar { $$ = Expr\BinaryOp\Identical [$1, $3]; } - | static_scalar T_IS_NOT_IDENTICAL static_scalar { $$ = Expr\BinaryOp\NotIdentical [$1, $3]; } - | static_scalar T_IS_EQUAL static_scalar { $$ = Expr\BinaryOp\Equal [$1, $3]; } - | static_scalar T_IS_NOT_EQUAL static_scalar { $$ = Expr\BinaryOp\NotEqual [$1, $3]; } - | static_scalar '<' static_scalar { $$ = Expr\BinaryOp\Smaller [$1, $3]; } - | static_scalar T_IS_SMALLER_OR_EQUAL static_scalar { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; } - | static_scalar '>' static_scalar { $$ = Expr\BinaryOp\Greater [$1, $3]; } - | static_scalar T_IS_GREATER_OR_EQUAL static_scalar { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; } - | static_scalar '?' static_scalar ':' static_scalar { $$ = Expr\Ternary[$1, $3, $5]; } - | static_scalar '?' ':' static_scalar { $$ = Expr\Ternary[$1, null, $4]; } - | static_scalar '[' static_scalar ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } - | '(' static_scalar ')' { $$ = $2; } -; - -constant: - name { $$ = Expr\ConstFetch[$1]; } - | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier_ex - { $$ = Expr\ClassConstFetch[$1, $3]; } -; - -scalar: - common_scalar { $$ = $1; } - | constant { $$ = $1; } - | '"' encaps_list '"' - { $attrs = attributes(); $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED; - parseEncapsed($2, '"', true); $$ = new Scalar\Encapsed($2, $attrs); } - | T_START_HEREDOC encaps_list T_END_HEREDOC - { $$ = $this->parseDocString($1, $2, $3, attributes(), stackAttributes(#3), true); } -; - -static_array_pair_list: - /* empty */ { $$ = array(); } - | non_empty_static_array_pair_list optional_comma { $$ = $1; } -; - -optional_comma: - /* empty */ - | ',' -; - -non_empty_static_array_pair_list: - non_empty_static_array_pair_list ',' static_array_pair { push($1, $3); } - | static_array_pair { init($1); } -; - -static_array_pair: - static_scalar T_DOUBLE_ARROW static_scalar { $$ = Expr\ArrayItem[$3, $1, false]; } - | static_scalar { $$ = Expr\ArrayItem[$1, null, false]; } -; - -variable: - object_access { $$ = $1; } - | base_variable { $$ = $1; } - | function_call { $$ = $1; } - | new_expr_array_deref { $$ = $1; } -; - -new_expr_array_deref: - '(' new_expr ')' '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$2, $5]; } - | new_expr_array_deref '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } - /* alternative array syntax missing intentionally */ -; - -object_access: - variable_or_new_expr T_OBJECT_OPERATOR object_property - { $$ = Expr\PropertyFetch[$1, $3]; } - | variable_or_new_expr T_OBJECT_OPERATOR object_property argument_list - { $$ = Expr\MethodCall[$1, $3, $4]; } - | object_access argument_list { $$ = Expr\FuncCall[$1, $2]; } - | object_access '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } - | object_access '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } -; - -variable_or_new_expr: - variable { $$ = $1; } - | '(' new_expr ')' { $$ = $2; } -; - -variable_without_objects: - reference_variable { $$ = $1; } - | '$' variable_without_objects { $$ = Expr\Variable[$2]; } -; - -base_variable: - variable_without_objects { $$ = $1; } - | static_property { $$ = $1; } -; - -static_property: - class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '$' reference_variable - { $$ = Expr\StaticPropertyFetch[$1, $4]; } - | static_property_with_arrays { $$ = $1; } -; - -static_property_simple_name: - T_VARIABLE - { $var = parseVar($1); $$ = \is_string($var) ? Node\VarLikeIdentifier[$var] : $var; } -; - -static_property_with_arrays: - class_name_or_var T_PAAMAYIM_NEKUDOTAYIM static_property_simple_name - { $$ = Expr\StaticPropertyFetch[$1, $3]; } - | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '$' '{' expr '}' - { $$ = Expr\StaticPropertyFetch[$1, $5]; } - | static_property_with_arrays '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } - | static_property_with_arrays '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } -; - -reference_variable: - reference_variable '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } - | reference_variable '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } - | plain_variable { $$ = $1; } - | '$' '{' expr '}' { $$ = Expr\Variable[$3]; } -; - -dim_offset: - /* empty */ { $$ = null; } - | expr { $$ = $1; } -; - -object_property: - identifier { $$ = $1; } - | '{' expr '}' { $$ = $2; } - | variable_without_objects { $$ = $1; } - | error { $$ = Expr\Error[]; $this->errorState = 2; } -; - -list_expr: - T_LIST '(' list_expr_elements ')' { $$ = Expr\List_[$3]; } -; - -list_expr_elements: - list_expr_elements ',' list_expr_element { push($1, $3); } - | list_expr_element { init($1); } -; - -list_expr_element: - variable { $$ = Expr\ArrayItem[$1, null, false]; } - | list_expr { $$ = Expr\ArrayItem[$1, null, false]; } - | /* empty */ { $$ = null; } -; - -array_pair_list: - /* empty */ { $$ = array(); } - | non_empty_array_pair_list optional_comma { $$ = $1; } -; - -non_empty_array_pair_list: - non_empty_array_pair_list ',' array_pair { push($1, $3); } - | array_pair { init($1); } -; - -array_pair: - expr T_DOUBLE_ARROW expr { $$ = Expr\ArrayItem[$3, $1, false]; } - | expr { $$ = Expr\ArrayItem[$1, null, false]; } - | expr T_DOUBLE_ARROW ampersand variable { $$ = Expr\ArrayItem[$4, $1, true]; } - | ampersand variable { $$ = Expr\ArrayItem[$2, null, true]; } - | T_ELLIPSIS expr { $$ = Expr\ArrayItem[$2, null, false, attributes(), true]; } -; - -encaps_list: - encaps_list encaps_var { push($1, $2); } - | encaps_list encaps_string_part { push($1, $2); } - | encaps_var { init($1); } - | encaps_string_part encaps_var { init($1, $2); } -; - -encaps_string_part: - T_ENCAPSED_AND_WHITESPACE { $$ = Scalar\EncapsedStringPart[$1]; } -; - -encaps_str_varname: - T_STRING_VARNAME { $$ = Expr\Variable[$1]; } -; - -encaps_var: - plain_variable { $$ = $1; } - | plain_variable '[' encaps_var_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } - | plain_variable T_OBJECT_OPERATOR identifier { $$ = Expr\PropertyFetch[$1, $3]; } - | T_DOLLAR_OPEN_CURLY_BRACES expr '}' { $$ = Expr\Variable[$2]; } - | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}' { $$ = Expr\Variable[$2]; } - | T_DOLLAR_OPEN_CURLY_BRACES encaps_str_varname '[' expr ']' '}' - { $$ = Expr\ArrayDimFetch[$2, $4]; } - | T_CURLY_OPEN variable '}' { $$ = $2; } -; - -encaps_var_offset: - T_STRING { $$ = Scalar\String_[$1]; } - | T_NUM_STRING { $$ = $this->parseNumString($1, attributes()); } - | plain_variable { $$ = $1; } -; - -%% diff --git a/lib/nikic/php-parser/grammar/php7.y b/lib/nikic/php-parser/grammar/php7.y deleted file mode 100644 index 087bc7392..000000000 --- a/lib/nikic/php-parser/grammar/php7.y +++ /dev/null @@ -1,1204 +0,0 @@ -%pure_parser -%expect 2 - -%tokens - -%% - -start: - top_statement_list { $$ = $this->handleNamespaces($1); } -; - -top_statement_list_ex: - top_statement_list_ex top_statement { pushNormalizing($1, $2); } - | /* empty */ { init(); } -; - -top_statement_list: - top_statement_list_ex - { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); - if ($nop !== null) { $1[] = $nop; } $$ = $1; } -; - -ampersand: - T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG - | T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG -; - -reserved_non_modifiers: - T_INCLUDE | T_INCLUDE_ONCE | T_EVAL | T_REQUIRE | T_REQUIRE_ONCE | T_LOGICAL_OR | T_LOGICAL_XOR | T_LOGICAL_AND - | T_INSTANCEOF | T_NEW | T_CLONE | T_EXIT | T_IF | T_ELSEIF | T_ELSE | T_ENDIF | T_ECHO | T_DO | T_WHILE - | T_ENDWHILE | T_FOR | T_ENDFOR | T_FOREACH | T_ENDFOREACH | T_DECLARE | T_ENDDECLARE | T_AS | T_TRY | T_CATCH - | T_FINALLY | T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO - | T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT - | T_BREAK | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS - | T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_HALT_COMPILER | T_FN - | T_MATCH | T_ENUM -; - -semi_reserved: - reserved_non_modifiers - | T_STATIC | T_ABSTRACT | T_FINAL | T_PRIVATE | T_PROTECTED | T_PUBLIC | T_READONLY -; - -identifier_maybe_reserved: - T_STRING { $$ = Node\Identifier[$1]; } - | semi_reserved { $$ = Node\Identifier[$1]; } -; - -identifier_not_reserved: - T_STRING { $$ = Node\Identifier[$1]; } -; - -reserved_non_modifiers_identifier: - reserved_non_modifiers { $$ = Node\Identifier[$1]; } -; - -namespace_declaration_name: - T_STRING { $$ = Name[$1]; } - | semi_reserved { $$ = Name[$1]; } - | T_NAME_QUALIFIED { $$ = Name[$1]; } -; - -namespace_name: - T_STRING { $$ = Name[$1]; } - | T_NAME_QUALIFIED { $$ = Name[$1]; } -; - -legacy_namespace_name: - namespace_name { $$ = $1; } - | T_NAME_FULLY_QUALIFIED { $$ = Name[substr($1, 1)]; } -; - -plain_variable: - T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; } -; - -semi: - ';' { /* nothing */ } - | error { /* nothing */ } -; - -no_comma: - /* empty */ { /* nothing */ } - | ',' { $this->emitError(new Error('A trailing comma is not allowed here', attributes())); } -; - -optional_comma: - /* empty */ - | ',' -; - -attribute_decl: - class_name { $$ = Node\Attribute[$1, []]; } - | class_name argument_list { $$ = Node\Attribute[$1, $2]; } -; - -attribute_group: - attribute_decl { init($1); } - | attribute_group ',' attribute_decl { push($1, $3); } -; - -attribute: - T_ATTRIBUTE attribute_group optional_comma ']' { $$ = Node\AttributeGroup[$2]; } -; - -attributes: - attribute { init($1); } - | attributes attribute { push($1, $2); } -; - -optional_attributes: - /* empty */ { $$ = []; } - | attributes { $$ = $1; } -; - -top_statement: - statement { $$ = $1; } - | function_declaration_statement { $$ = $1; } - | class_declaration_statement { $$ = $1; } - | T_HALT_COMPILER - { $$ = Stmt\HaltCompiler[$this->lexer->handleHaltCompiler()]; } - | T_NAMESPACE namespace_declaration_name semi - { $$ = Stmt\Namespace_[$2, null]; - $$->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON); - $this->checkNamespace($$); } - | T_NAMESPACE namespace_declaration_name '{' top_statement_list '}' - { $$ = Stmt\Namespace_[$2, $4]; - $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); - $this->checkNamespace($$); } - | T_NAMESPACE '{' top_statement_list '}' - { $$ = Stmt\Namespace_[null, $3]; - $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); - $this->checkNamespace($$); } - | T_USE use_declarations semi { $$ = Stmt\Use_[$2, Stmt\Use_::TYPE_NORMAL]; } - | T_USE use_type use_declarations semi { $$ = Stmt\Use_[$3, $2]; } - | group_use_declaration semi { $$ = $1; } - | T_CONST constant_declaration_list semi { $$ = Stmt\Const_[$2]; } -; - -use_type: - T_FUNCTION { $$ = Stmt\Use_::TYPE_FUNCTION; } - | T_CONST { $$ = Stmt\Use_::TYPE_CONSTANT; } -; - -group_use_declaration: - T_USE use_type legacy_namespace_name T_NS_SEPARATOR '{' unprefixed_use_declarations '}' - { $$ = Stmt\GroupUse[$3, $6, $2]; } - | T_USE legacy_namespace_name T_NS_SEPARATOR '{' inline_use_declarations '}' - { $$ = Stmt\GroupUse[$2, $5, Stmt\Use_::TYPE_UNKNOWN]; } -; - -unprefixed_use_declarations: - non_empty_unprefixed_use_declarations optional_comma { $$ = $1; } -; - -non_empty_unprefixed_use_declarations: - non_empty_unprefixed_use_declarations ',' unprefixed_use_declaration - { push($1, $3); } - | unprefixed_use_declaration { init($1); } -; - -use_declarations: - non_empty_use_declarations no_comma { $$ = $1; } -; - -non_empty_use_declarations: - non_empty_use_declarations ',' use_declaration { push($1, $3); } - | use_declaration { init($1); } -; - -inline_use_declarations: - non_empty_inline_use_declarations optional_comma { $$ = $1; } -; - -non_empty_inline_use_declarations: - non_empty_inline_use_declarations ',' inline_use_declaration - { push($1, $3); } - | inline_use_declaration { init($1); } -; - -unprefixed_use_declaration: - namespace_name - { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); } - | namespace_name T_AS identifier_not_reserved - { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); } -; - -use_declaration: - legacy_namespace_name - { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); } - | legacy_namespace_name T_AS identifier_not_reserved - { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); } -; - -inline_use_declaration: - unprefixed_use_declaration { $$ = $1; $$->type = Stmt\Use_::TYPE_NORMAL; } - | use_type unprefixed_use_declaration { $$ = $2; $$->type = $1; } -; - -constant_declaration_list: - non_empty_constant_declaration_list no_comma { $$ = $1; } -; - -non_empty_constant_declaration_list: - non_empty_constant_declaration_list ',' constant_declaration - { push($1, $3); } - | constant_declaration { init($1); } -; - -constant_declaration: - identifier_not_reserved '=' expr { $$ = Node\Const_[$1, $3]; } -; - -class_const_list: - non_empty_class_const_list no_comma { $$ = $1; } -; - -non_empty_class_const_list: - non_empty_class_const_list ',' class_const { push($1, $3); } - | class_const { init($1); } -; - -class_const: - identifier_maybe_reserved '=' expr { $$ = Node\Const_[$1, $3]; } -; - -inner_statement_list_ex: - inner_statement_list_ex inner_statement { pushNormalizing($1, $2); } - | /* empty */ { init(); } -; - -inner_statement_list: - inner_statement_list_ex - { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); - if ($nop !== null) { $1[] = $nop; } $$ = $1; } -; - -inner_statement: - statement { $$ = $1; } - | function_declaration_statement { $$ = $1; } - | class_declaration_statement { $$ = $1; } - | T_HALT_COMPILER - { throw new Error('__HALT_COMPILER() can only be used from the outermost scope', attributes()); } -; - -non_empty_statement: - '{' inner_statement_list '}' - { - if ($2) { - $$ = $2; prependLeadingComments($$); - } else { - makeNop($$, $this->startAttributeStack[#1], $this->endAttributes); - if (null === $$) { $$ = array(); } - } - } - | T_IF '(' expr ')' statement elseif_list else_single - { $$ = Stmt\If_[$3, ['stmts' => toArray($5), 'elseifs' => $6, 'else' => $7]]; } - | T_IF '(' expr ')' ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';' - { $$ = Stmt\If_[$3, ['stmts' => $6, 'elseifs' => $7, 'else' => $8]]; } - | T_WHILE '(' expr ')' while_statement { $$ = Stmt\While_[$3, $5]; } - | T_DO statement T_WHILE '(' expr ')' ';' { $$ = Stmt\Do_ [$5, toArray($2)]; } - | T_FOR '(' for_expr ';' for_expr ';' for_expr ')' for_statement - { $$ = Stmt\For_[['init' => $3, 'cond' => $5, 'loop' => $7, 'stmts' => $9]]; } - | T_SWITCH '(' expr ')' switch_case_list { $$ = Stmt\Switch_[$3, $5]; } - | T_BREAK optional_expr semi { $$ = Stmt\Break_[$2]; } - | T_CONTINUE optional_expr semi { $$ = Stmt\Continue_[$2]; } - | T_RETURN optional_expr semi { $$ = Stmt\Return_[$2]; } - | T_GLOBAL global_var_list semi { $$ = Stmt\Global_[$2]; } - | T_STATIC static_var_list semi { $$ = Stmt\Static_[$2]; } - | T_ECHO expr_list_forbid_comma semi { $$ = Stmt\Echo_[$2]; } - | T_INLINE_HTML { $$ = Stmt\InlineHTML[$1]; } - | expr semi { - $e = $1; - if ($e instanceof Expr\Throw_) { - // For backwards-compatibility reasons, convert throw in statement position into - // Stmt\Throw_ rather than Stmt\Expression(Expr\Throw_). - $$ = Stmt\Throw_[$e->expr]; - } else { - $$ = Stmt\Expression[$e]; - } - } - | T_UNSET '(' variables_list ')' semi { $$ = Stmt\Unset_[$3]; } - | T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement - { $$ = Stmt\Foreach_[$3, $5[0], ['keyVar' => null, 'byRef' => $5[1], 'stmts' => $7]]; } - | T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_statement - { $$ = Stmt\Foreach_[$3, $7[0], ['keyVar' => $5, 'byRef' => $7[1], 'stmts' => $9]]; } - | T_FOREACH '(' expr error ')' foreach_statement - { $$ = Stmt\Foreach_[$3, new Expr\Error(stackAttributes(#4)), ['stmts' => $6]]; } - | T_DECLARE '(' declare_list ')' declare_statement { $$ = Stmt\Declare_[$3, $5]; } - | T_TRY '{' inner_statement_list '}' catches optional_finally - { $$ = Stmt\TryCatch[$3, $5, $6]; $this->checkTryCatch($$); } - | T_GOTO identifier_not_reserved semi { $$ = Stmt\Goto_[$2]; } - | identifier_not_reserved ':' { $$ = Stmt\Label[$1]; } - | error { $$ = array(); /* means: no statement */ } -; - -statement: - non_empty_statement { $$ = $1; } - | ';' - { makeNop($$, $this->startAttributeStack[#1], $this->endAttributes); - if ($$ === null) $$ = array(); /* means: no statement */ } -; - -catches: - /* empty */ { init(); } - | catches catch { push($1, $2); } -; - -name_union: - name { init($1); } - | name_union '|' name { push($1, $3); } -; - -catch: - T_CATCH '(' name_union optional_plain_variable ')' '{' inner_statement_list '}' - { $$ = Stmt\Catch_[$3, $4, $7]; } -; - -optional_finally: - /* empty */ { $$ = null; } - | T_FINALLY '{' inner_statement_list '}' { $$ = Stmt\Finally_[$3]; } -; - -variables_list: - non_empty_variables_list optional_comma { $$ = $1; } -; - -non_empty_variables_list: - variable { init($1); } - | non_empty_variables_list ',' variable { push($1, $3); } -; - -optional_ref: - /* empty */ { $$ = false; } - | ampersand { $$ = true; } -; - -optional_arg_ref: - /* empty */ { $$ = false; } - | T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG { $$ = true; } -; - -optional_ellipsis: - /* empty */ { $$ = false; } - | T_ELLIPSIS { $$ = true; } -; - -block_or_error: - '{' inner_statement_list '}' { $$ = $2; } - | error { $$ = []; } -; - -function_declaration_statement: - T_FUNCTION optional_ref identifier_not_reserved '(' parameter_list ')' optional_return_type block_or_error - { $$ = Stmt\Function_[$3, ['byRef' => $2, 'params' => $5, 'returnType' => $7, 'stmts' => $8, 'attrGroups' => []]]; } - | attributes T_FUNCTION optional_ref identifier_not_reserved '(' parameter_list ')' optional_return_type block_or_error - { $$ = Stmt\Function_[$4, ['byRef' => $3, 'params' => $6, 'returnType' => $8, 'stmts' => $9, 'attrGroups' => $1]]; } -; - -class_declaration_statement: - optional_attributes class_entry_type identifier_not_reserved extends_from implements_list '{' class_statement_list '}' - { $$ = Stmt\Class_[$3, ['type' => $2, 'extends' => $4, 'implements' => $5, 'stmts' => $7, 'attrGroups' => $1]]; - $this->checkClass($$, #3); } - | optional_attributes T_INTERFACE identifier_not_reserved interface_extends_list '{' class_statement_list '}' - { $$ = Stmt\Interface_[$3, ['extends' => $4, 'stmts' => $6, 'attrGroups' => $1]]; - $this->checkInterface($$, #3); } - | optional_attributes T_TRAIT identifier_not_reserved '{' class_statement_list '}' - { $$ = Stmt\Trait_[$3, ['stmts' => $5, 'attrGroups' => $1]]; } - | optional_attributes T_ENUM identifier_not_reserved enum_scalar_type implements_list '{' class_statement_list '}' - { $$ = Stmt\Enum_[$3, ['scalarType' => $4, 'implements' => $5, 'stmts' => $7, 'attrGroups' => $1]]; - $this->checkEnum($$, #3); } -; - -enum_scalar_type: - /* empty */ { $$ = null; } - | ':' type { $$ = $2; } - -enum_case_expr: - /* empty */ { $$ = null; } - | '=' expr { $$ = $2; } -; - -class_entry_type: - T_CLASS { $$ = 0; } - | class_modifiers T_CLASS { $$ = $1; } -; - -class_modifiers: - class_modifier { $$ = $1; } - | class_modifiers class_modifier { $this->checkClassModifier($1, $2, #2); $$ = $1 | $2; } -; - -class_modifier: - T_ABSTRACT { $$ = Stmt\Class_::MODIFIER_ABSTRACT; } - | T_FINAL { $$ = Stmt\Class_::MODIFIER_FINAL; } - | T_READONLY { $$ = Stmt\Class_::MODIFIER_READONLY; } -; - -extends_from: - /* empty */ { $$ = null; } - | T_EXTENDS class_name { $$ = $2; } -; - -interface_extends_list: - /* empty */ { $$ = array(); } - | T_EXTENDS class_name_list { $$ = $2; } -; - -implements_list: - /* empty */ { $$ = array(); } - | T_IMPLEMENTS class_name_list { $$ = $2; } -; - -class_name_list: - non_empty_class_name_list no_comma { $$ = $1; } -; - -non_empty_class_name_list: - class_name { init($1); } - | non_empty_class_name_list ',' class_name { push($1, $3); } -; - -for_statement: - statement { $$ = toArray($1); } - | ':' inner_statement_list T_ENDFOR ';' { $$ = $2; } -; - -foreach_statement: - statement { $$ = toArray($1); } - | ':' inner_statement_list T_ENDFOREACH ';' { $$ = $2; } -; - -declare_statement: - non_empty_statement { $$ = toArray($1); } - | ';' { $$ = null; } - | ':' inner_statement_list T_ENDDECLARE ';' { $$ = $2; } -; - -declare_list: - non_empty_declare_list no_comma { $$ = $1; } -; - -non_empty_declare_list: - declare_list_element { init($1); } - | non_empty_declare_list ',' declare_list_element { push($1, $3); } -; - -declare_list_element: - identifier_not_reserved '=' expr { $$ = Stmt\DeclareDeclare[$1, $3]; } -; - -switch_case_list: - '{' case_list '}' { $$ = $2; } - | '{' ';' case_list '}' { $$ = $3; } - | ':' case_list T_ENDSWITCH ';' { $$ = $2; } - | ':' ';' case_list T_ENDSWITCH ';' { $$ = $3; } -; - -case_list: - /* empty */ { init(); } - | case_list case { push($1, $2); } -; - -case: - T_CASE expr case_separator inner_statement_list_ex { $$ = Stmt\Case_[$2, $4]; } - | T_DEFAULT case_separator inner_statement_list_ex { $$ = Stmt\Case_[null, $3]; } -; - -case_separator: - ':' - | ';' -; - -match: - T_MATCH '(' expr ')' '{' match_arm_list '}' { $$ = Expr\Match_[$3, $6]; } -; - -match_arm_list: - /* empty */ { $$ = []; } - | non_empty_match_arm_list optional_comma { $$ = $1; } -; - -non_empty_match_arm_list: - match_arm { init($1); } - | non_empty_match_arm_list ',' match_arm { push($1, $3); } -; - -match_arm: - expr_list_allow_comma T_DOUBLE_ARROW expr { $$ = Node\MatchArm[$1, $3]; } - | T_DEFAULT optional_comma T_DOUBLE_ARROW expr { $$ = Node\MatchArm[null, $4]; } -; - -while_statement: - statement { $$ = toArray($1); } - | ':' inner_statement_list T_ENDWHILE ';' { $$ = $2; } -; - -elseif_list: - /* empty */ { init(); } - | elseif_list elseif { push($1, $2); } -; - -elseif: - T_ELSEIF '(' expr ')' statement { $$ = Stmt\ElseIf_[$3, toArray($5)]; } -; - -new_elseif_list: - /* empty */ { init(); } - | new_elseif_list new_elseif { push($1, $2); } -; - -new_elseif: - T_ELSEIF '(' expr ')' ':' inner_statement_list { $$ = Stmt\ElseIf_[$3, $6]; } -; - -else_single: - /* empty */ { $$ = null; } - | T_ELSE statement { $$ = Stmt\Else_[toArray($2)]; } -; - -new_else_single: - /* empty */ { $$ = null; } - | T_ELSE ':' inner_statement_list { $$ = Stmt\Else_[$3]; } -; - -foreach_variable: - variable { $$ = array($1, false); } - | ampersand variable { $$ = array($2, true); } - | list_expr { $$ = array($1, false); } - | array_short_syntax { $$ = array($1, false); } -; - -parameter_list: - non_empty_parameter_list optional_comma { $$ = $1; } - | /* empty */ { $$ = array(); } -; - -non_empty_parameter_list: - parameter { init($1); } - | non_empty_parameter_list ',' parameter { push($1, $3); } -; - -optional_property_modifiers: - /* empty */ { $$ = 0; } - | optional_property_modifiers property_modifier - { $this->checkModifier($1, $2, #2); $$ = $1 | $2; } -; - -property_modifier: - T_PUBLIC { $$ = Stmt\Class_::MODIFIER_PUBLIC; } - | T_PROTECTED { $$ = Stmt\Class_::MODIFIER_PROTECTED; } - | T_PRIVATE { $$ = Stmt\Class_::MODIFIER_PRIVATE; } - | T_READONLY { $$ = Stmt\Class_::MODIFIER_READONLY; } -; - -parameter: - optional_attributes optional_property_modifiers optional_type_without_static - optional_arg_ref optional_ellipsis plain_variable - { $$ = new Node\Param($6, null, $3, $4, $5, attributes(), $2, $1); - $this->checkParam($$); } - | optional_attributes optional_property_modifiers optional_type_without_static - optional_arg_ref optional_ellipsis plain_variable '=' expr - { $$ = new Node\Param($6, $8, $3, $4, $5, attributes(), $2, $1); - $this->checkParam($$); } - | optional_attributes optional_property_modifiers optional_type_without_static - optional_arg_ref optional_ellipsis error - { $$ = new Node\Param(Expr\Error[], null, $3, $4, $5, attributes(), $2, $1); } -; - -type_expr: - type { $$ = $1; } - | '?' type { $$ = Node\NullableType[$2]; } - | union_type { $$ = Node\UnionType[$1]; } - | intersection_type { $$ = Node\IntersectionType[$1]; } -; - -type: - type_without_static { $$ = $1; } - | T_STATIC { $$ = Node\Name['static']; } -; - -type_without_static: - name { $$ = $this->handleBuiltinTypes($1); } - | T_ARRAY { $$ = Node\Identifier['array']; } - | T_CALLABLE { $$ = Node\Identifier['callable']; } -; - -union_type: - type '|' type { init($1, $3); } - | union_type '|' type { push($1, $3); } -; - -union_type_without_static: - type_without_static '|' type_without_static { init($1, $3); } - | union_type_without_static '|' type_without_static { push($1, $3); } -; - -intersection_type: - type T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type { init($1, $3); } - | intersection_type T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type - { push($1, $3); } -; - -intersection_type_without_static: - type_without_static T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type_without_static - { init($1, $3); } - | intersection_type_without_static T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type_without_static - { push($1, $3); } -; - -type_expr_without_static: - type_without_static { $$ = $1; } - | '?' type_without_static { $$ = Node\NullableType[$2]; } - | union_type_without_static { $$ = Node\UnionType[$1]; } - | intersection_type_without_static { $$ = Node\IntersectionType[$1]; } -; - -optional_type_without_static: - /* empty */ { $$ = null; } - | type_expr_without_static { $$ = $1; } -; - -optional_return_type: - /* empty */ { $$ = null; } - | ':' type_expr { $$ = $2; } - | ':' error { $$ = null; } -; - -argument_list: - '(' ')' { $$ = array(); } - | '(' non_empty_argument_list optional_comma ')' { $$ = $2; } - | '(' variadic_placeholder ')' { init($2); } -; - -variadic_placeholder: - T_ELLIPSIS { $$ = Node\VariadicPlaceholder[]; } -; - -non_empty_argument_list: - argument { init($1); } - | non_empty_argument_list ',' argument { push($1, $3); } -; - -argument: - expr { $$ = Node\Arg[$1, false, false]; } - | ampersand variable { $$ = Node\Arg[$2, true, false]; } - | T_ELLIPSIS expr { $$ = Node\Arg[$2, false, true]; } - | identifier_maybe_reserved ':' expr - { $$ = new Node\Arg($3, false, false, attributes(), $1); } -; - -global_var_list: - non_empty_global_var_list no_comma { $$ = $1; } -; - -non_empty_global_var_list: - non_empty_global_var_list ',' global_var { push($1, $3); } - | global_var { init($1); } -; - -global_var: - simple_variable { $$ = $1; } -; - -static_var_list: - non_empty_static_var_list no_comma { $$ = $1; } -; - -non_empty_static_var_list: - non_empty_static_var_list ',' static_var { push($1, $3); } - | static_var { init($1); } -; - -static_var: - plain_variable { $$ = Stmt\StaticVar[$1, null]; } - | plain_variable '=' expr { $$ = Stmt\StaticVar[$1, $3]; } -; - -class_statement_list_ex: - class_statement_list_ex class_statement { if ($2 !== null) { push($1, $2); } } - | /* empty */ { init(); } -; - -class_statement_list: - class_statement_list_ex - { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); - if ($nop !== null) { $1[] = $nop; } $$ = $1; } -; - -class_statement: - optional_attributes variable_modifiers optional_type_without_static property_declaration_list semi - { $$ = new Stmt\Property($2, $4, attributes(), $3, $1); - $this->checkProperty($$, #2); } - | optional_attributes method_modifiers T_CONST class_const_list semi - { $$ = new Stmt\ClassConst($4, $2, attributes(), $1); - $this->checkClassConst($$, #2); } - | optional_attributes method_modifiers T_FUNCTION optional_ref identifier_maybe_reserved '(' parameter_list ')' - optional_return_type method_body - { $$ = Stmt\ClassMethod[$5, ['type' => $2, 'byRef' => $4, 'params' => $7, 'returnType' => $9, 'stmts' => $10, 'attrGroups' => $1]]; - $this->checkClassMethod($$, #2); } - | T_USE class_name_list trait_adaptations { $$ = Stmt\TraitUse[$2, $3]; } - | optional_attributes T_CASE identifier_maybe_reserved enum_case_expr semi - { $$ = Stmt\EnumCase[$3, $4, $1]; } - | error { $$ = null; /* will be skipped */ } -; - -trait_adaptations: - ';' { $$ = array(); } - | '{' trait_adaptation_list '}' { $$ = $2; } -; - -trait_adaptation_list: - /* empty */ { init(); } - | trait_adaptation_list trait_adaptation { push($1, $2); } -; - -trait_adaptation: - trait_method_reference_fully_qualified T_INSTEADOF class_name_list ';' - { $$ = Stmt\TraitUseAdaptation\Precedence[$1[0], $1[1], $3]; } - | trait_method_reference T_AS member_modifier identifier_maybe_reserved ';' - { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, $4]; } - | trait_method_reference T_AS member_modifier ';' - { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, null]; } - | trait_method_reference T_AS identifier_not_reserved ';' - { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; } - | trait_method_reference T_AS reserved_non_modifiers_identifier ';' - { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; } -; - -trait_method_reference_fully_qualified: - name T_PAAMAYIM_NEKUDOTAYIM identifier_maybe_reserved { $$ = array($1, $3); } -; -trait_method_reference: - trait_method_reference_fully_qualified { $$ = $1; } - | identifier_maybe_reserved { $$ = array(null, $1); } -; - -method_body: - ';' /* abstract method */ { $$ = null; } - | block_or_error { $$ = $1; } -; - -variable_modifiers: - non_empty_member_modifiers { $$ = $1; } - | T_VAR { $$ = 0; } -; - -method_modifiers: - /* empty */ { $$ = 0; } - | non_empty_member_modifiers { $$ = $1; } -; - -non_empty_member_modifiers: - member_modifier { $$ = $1; } - | non_empty_member_modifiers member_modifier { $this->checkModifier($1, $2, #2); $$ = $1 | $2; } -; - -member_modifier: - T_PUBLIC { $$ = Stmt\Class_::MODIFIER_PUBLIC; } - | T_PROTECTED { $$ = Stmt\Class_::MODIFIER_PROTECTED; } - | T_PRIVATE { $$ = Stmt\Class_::MODIFIER_PRIVATE; } - | T_STATIC { $$ = Stmt\Class_::MODIFIER_STATIC; } - | T_ABSTRACT { $$ = Stmt\Class_::MODIFIER_ABSTRACT; } - | T_FINAL { $$ = Stmt\Class_::MODIFIER_FINAL; } - | T_READONLY { $$ = Stmt\Class_::MODIFIER_READONLY; } -; - -property_declaration_list: - non_empty_property_declaration_list no_comma { $$ = $1; } -; - -non_empty_property_declaration_list: - property_declaration { init($1); } - | non_empty_property_declaration_list ',' property_declaration - { push($1, $3); } -; - -property_decl_name: - T_VARIABLE { $$ = Node\VarLikeIdentifier[parseVar($1)]; } -; - -property_declaration: - property_decl_name { $$ = Stmt\PropertyProperty[$1, null]; } - | property_decl_name '=' expr { $$ = Stmt\PropertyProperty[$1, $3]; } -; - -expr_list_forbid_comma: - non_empty_expr_list no_comma { $$ = $1; } -; - -expr_list_allow_comma: - non_empty_expr_list optional_comma { $$ = $1; } -; - -non_empty_expr_list: - non_empty_expr_list ',' expr { push($1, $3); } - | expr { init($1); } -; - -for_expr: - /* empty */ { $$ = array(); } - | expr_list_forbid_comma { $$ = $1; } -; - -expr: - variable { $$ = $1; } - | list_expr '=' expr { $$ = Expr\Assign[$1, $3]; } - | array_short_syntax '=' expr { $$ = Expr\Assign[$1, $3]; } - | variable '=' expr { $$ = Expr\Assign[$1, $3]; } - | variable '=' ampersand variable { $$ = Expr\AssignRef[$1, $4]; } - | new_expr { $$ = $1; } - | match { $$ = $1; } - | T_CLONE expr { $$ = Expr\Clone_[$2]; } - | variable T_PLUS_EQUAL expr { $$ = Expr\AssignOp\Plus [$1, $3]; } - | variable T_MINUS_EQUAL expr { $$ = Expr\AssignOp\Minus [$1, $3]; } - | variable T_MUL_EQUAL expr { $$ = Expr\AssignOp\Mul [$1, $3]; } - | variable T_DIV_EQUAL expr { $$ = Expr\AssignOp\Div [$1, $3]; } - | variable T_CONCAT_EQUAL expr { $$ = Expr\AssignOp\Concat [$1, $3]; } - | variable T_MOD_EQUAL expr { $$ = Expr\AssignOp\Mod [$1, $3]; } - | variable T_AND_EQUAL expr { $$ = Expr\AssignOp\BitwiseAnd[$1, $3]; } - | variable T_OR_EQUAL expr { $$ = Expr\AssignOp\BitwiseOr [$1, $3]; } - | variable T_XOR_EQUAL expr { $$ = Expr\AssignOp\BitwiseXor[$1, $3]; } - | variable T_SL_EQUAL expr { $$ = Expr\AssignOp\ShiftLeft [$1, $3]; } - | variable T_SR_EQUAL expr { $$ = Expr\AssignOp\ShiftRight[$1, $3]; } - | variable T_POW_EQUAL expr { $$ = Expr\AssignOp\Pow [$1, $3]; } - | variable T_COALESCE_EQUAL expr { $$ = Expr\AssignOp\Coalesce [$1, $3]; } - | variable T_INC { $$ = Expr\PostInc[$1]; } - | T_INC variable { $$ = Expr\PreInc [$2]; } - | variable T_DEC { $$ = Expr\PostDec[$1]; } - | T_DEC variable { $$ = Expr\PreDec [$2]; } - | expr T_BOOLEAN_OR expr { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; } - | expr T_BOOLEAN_AND expr { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; } - | expr T_LOGICAL_OR expr { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; } - | expr T_LOGICAL_AND expr { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; } - | expr T_LOGICAL_XOR expr { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; } - | expr '|' expr { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; } - | expr T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } - | expr T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } - | expr '^' expr { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; } - | expr '.' expr { $$ = Expr\BinaryOp\Concat [$1, $3]; } - | expr '+' expr { $$ = Expr\BinaryOp\Plus [$1, $3]; } - | expr '-' expr { $$ = Expr\BinaryOp\Minus [$1, $3]; } - | expr '*' expr { $$ = Expr\BinaryOp\Mul [$1, $3]; } - | expr '/' expr { $$ = Expr\BinaryOp\Div [$1, $3]; } - | expr '%' expr { $$ = Expr\BinaryOp\Mod [$1, $3]; } - | expr T_SL expr { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; } - | expr T_SR expr { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; } - | expr T_POW expr { $$ = Expr\BinaryOp\Pow [$1, $3]; } - | '+' expr %prec T_INC { $$ = Expr\UnaryPlus [$2]; } - | '-' expr %prec T_INC { $$ = Expr\UnaryMinus[$2]; } - | '!' expr { $$ = Expr\BooleanNot[$2]; } - | '~' expr { $$ = Expr\BitwiseNot[$2]; } - | expr T_IS_IDENTICAL expr { $$ = Expr\BinaryOp\Identical [$1, $3]; } - | expr T_IS_NOT_IDENTICAL expr { $$ = Expr\BinaryOp\NotIdentical [$1, $3]; } - | expr T_IS_EQUAL expr { $$ = Expr\BinaryOp\Equal [$1, $3]; } - | expr T_IS_NOT_EQUAL expr { $$ = Expr\BinaryOp\NotEqual [$1, $3]; } - | expr T_SPACESHIP expr { $$ = Expr\BinaryOp\Spaceship [$1, $3]; } - | expr '<' expr { $$ = Expr\BinaryOp\Smaller [$1, $3]; } - | expr T_IS_SMALLER_OR_EQUAL expr { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; } - | expr '>' expr { $$ = Expr\BinaryOp\Greater [$1, $3]; } - | expr T_IS_GREATER_OR_EQUAL expr { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; } - | expr T_INSTANCEOF class_name_reference { $$ = Expr\Instanceof_[$1, $3]; } - | '(' expr ')' { $$ = $2; } - | expr '?' expr ':' expr { $$ = Expr\Ternary[$1, $3, $5]; } - | expr '?' ':' expr { $$ = Expr\Ternary[$1, null, $4]; } - | expr T_COALESCE expr { $$ = Expr\BinaryOp\Coalesce[$1, $3]; } - | T_ISSET '(' expr_list_allow_comma ')' { $$ = Expr\Isset_[$3]; } - | T_EMPTY '(' expr ')' { $$ = Expr\Empty_[$3]; } - | T_INCLUDE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE]; } - | T_INCLUDE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE_ONCE]; } - | T_EVAL '(' expr ')' { $$ = Expr\Eval_[$3]; } - | T_REQUIRE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE]; } - | T_REQUIRE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE_ONCE]; } - | T_INT_CAST expr { $$ = Expr\Cast\Int_ [$2]; } - | T_DOUBLE_CAST expr - { $attrs = attributes(); - $attrs['kind'] = $this->getFloatCastKind($1); - $$ = new Expr\Cast\Double($2, $attrs); } - | T_STRING_CAST expr { $$ = Expr\Cast\String_ [$2]; } - | T_ARRAY_CAST expr { $$ = Expr\Cast\Array_ [$2]; } - | T_OBJECT_CAST expr { $$ = Expr\Cast\Object_ [$2]; } - | T_BOOL_CAST expr { $$ = Expr\Cast\Bool_ [$2]; } - | T_UNSET_CAST expr { $$ = Expr\Cast\Unset_ [$2]; } - | T_EXIT exit_expr - { $attrs = attributes(); - $attrs['kind'] = strtolower($1) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE; - $$ = new Expr\Exit_($2, $attrs); } - | '@' expr { $$ = Expr\ErrorSuppress[$2]; } - | scalar { $$ = $1; } - | '`' backticks_expr '`' { $$ = Expr\ShellExec[$2]; } - | T_PRINT expr { $$ = Expr\Print_[$2]; } - | T_YIELD { $$ = Expr\Yield_[null, null]; } - | T_YIELD expr { $$ = Expr\Yield_[$2, null]; } - | T_YIELD expr T_DOUBLE_ARROW expr { $$ = Expr\Yield_[$4, $2]; } - | T_YIELD_FROM expr { $$ = Expr\YieldFrom[$2]; } - | T_THROW expr { $$ = Expr\Throw_[$2]; } - - | T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr %prec T_THROW - { $$ = Expr\ArrowFunction[['static' => false, 'byRef' => $2, 'params' => $4, 'returnType' => $6, 'expr' => $8, 'attrGroups' => []]]; } - | T_STATIC T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr %prec T_THROW - { $$ = Expr\ArrowFunction[['static' => true, 'byRef' => $3, 'params' => $5, 'returnType' => $7, 'expr' => $9, 'attrGroups' => []]]; } - | T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type block_or_error - { $$ = Expr\Closure[['static' => false, 'byRef' => $2, 'params' => $4, 'uses' => $6, 'returnType' => $7, 'stmts' => $8, 'attrGroups' => []]]; } - | T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type block_or_error - { $$ = Expr\Closure[['static' => true, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $9, 'attrGroups' => []]]; } - - | attributes T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr %prec T_THROW - { $$ = Expr\ArrowFunction[['static' => false, 'byRef' => $3, 'params' => $5, 'returnType' => $7, 'expr' => $9, 'attrGroups' => $1]]; } - | attributes T_STATIC T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr %prec T_THROW - { $$ = Expr\ArrowFunction[['static' => true, 'byRef' => $4, 'params' => $6, 'returnType' => $8, 'expr' => $10, 'attrGroups' => $1]]; } - | attributes T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type block_or_error - { $$ = Expr\Closure[['static' => false, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $9, 'attrGroups' => $1]]; } - | attributes T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type block_or_error - { $$ = Expr\Closure[['static' => true, 'byRef' => $4, 'params' => $6, 'uses' => $8, 'returnType' => $9, 'stmts' => $10, 'attrGroups' => $1]]; } -; - -anonymous_class: - optional_attributes T_CLASS ctor_arguments extends_from implements_list '{' class_statement_list '}' - { $$ = array(Stmt\Class_[null, ['type' => 0, 'extends' => $4, 'implements' => $5, 'stmts' => $7, 'attrGroups' => $1]], $3); - $this->checkClass($$[0], -1); } -; - -new_expr: - T_NEW class_name_reference ctor_arguments { $$ = Expr\New_[$2, $3]; } - | T_NEW anonymous_class - { list($class, $ctorArgs) = $2; $$ = Expr\New_[$class, $ctorArgs]; } -; - -lexical_vars: - /* empty */ { $$ = array(); } - | T_USE '(' lexical_var_list ')' { $$ = $3; } -; - -lexical_var_list: - non_empty_lexical_var_list optional_comma { $$ = $1; } -; - -non_empty_lexical_var_list: - lexical_var { init($1); } - | non_empty_lexical_var_list ',' lexical_var { push($1, $3); } -; - -lexical_var: - optional_ref plain_variable { $$ = Expr\ClosureUse[$2, $1]; } -; - -function_call: - name argument_list { $$ = Expr\FuncCall[$1, $2]; } - | callable_expr argument_list { $$ = Expr\FuncCall[$1, $2]; } - | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM member_name argument_list - { $$ = Expr\StaticCall[$1, $3, $4]; } -; - -class_name: - T_STATIC { $$ = Name[$1]; } - | name { $$ = $1; } -; - -name: - T_STRING { $$ = Name[$1]; } - | T_NAME_QUALIFIED { $$ = Name[$1]; } - | T_NAME_FULLY_QUALIFIED { $$ = Name\FullyQualified[substr($1, 1)]; } - | T_NAME_RELATIVE { $$ = Name\Relative[substr($1, 10)]; } -; - -class_name_reference: - class_name { $$ = $1; } - | new_variable { $$ = $1; } - | '(' expr ')' { $$ = $2; } - | error { $$ = Expr\Error[]; $this->errorState = 2; } -; - -class_name_or_var: - class_name { $$ = $1; } - | fully_dereferencable { $$ = $1; } -; - -exit_expr: - /* empty */ { $$ = null; } - | '(' optional_expr ')' { $$ = $2; } -; - -backticks_expr: - /* empty */ { $$ = array(); } - | T_ENCAPSED_AND_WHITESPACE - { $$ = array(Scalar\EncapsedStringPart[Scalar\String_::parseEscapeSequences($1, '`')]); } - | encaps_list { parseEncapsed($1, '`', true); $$ = $1; } -; - -ctor_arguments: - /* empty */ { $$ = array(); } - | argument_list { $$ = $1; } -; - -constant: - name { $$ = Expr\ConstFetch[$1]; } - | T_LINE { $$ = Scalar\MagicConst\Line[]; } - | T_FILE { $$ = Scalar\MagicConst\File[]; } - | T_DIR { $$ = Scalar\MagicConst\Dir[]; } - | T_CLASS_C { $$ = Scalar\MagicConst\Class_[]; } - | T_TRAIT_C { $$ = Scalar\MagicConst\Trait_[]; } - | T_METHOD_C { $$ = Scalar\MagicConst\Method[]; } - | T_FUNC_C { $$ = Scalar\MagicConst\Function_[]; } - | T_NS_C { $$ = Scalar\MagicConst\Namespace_[]; } -; - -class_constant: - class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier_maybe_reserved - { $$ = Expr\ClassConstFetch[$1, $3]; } - /* We interpret an isolated FOO:: as an unfinished class constant fetch. It could also be - an unfinished static property fetch or unfinished scoped call. */ - | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM error - { $$ = Expr\ClassConstFetch[$1, new Expr\Error(stackAttributes(#3))]; $this->errorState = 2; } -; - -array_short_syntax: - '[' array_pair_list ']' - { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_SHORT; - $$ = new Expr\Array_($2, $attrs); } -; - -dereferencable_scalar: - T_ARRAY '(' array_pair_list ')' - { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_LONG; - $$ = new Expr\Array_($3, $attrs); } - | array_short_syntax { $$ = $1; } - | T_CONSTANT_ENCAPSED_STRING { $$ = Scalar\String_::fromString($1, attributes()); } - | '"' encaps_list '"' - { $attrs = attributes(); $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED; - parseEncapsed($2, '"', true); $$ = new Scalar\Encapsed($2, $attrs); } -; - -scalar: - T_LNUMBER { $$ = $this->parseLNumber($1, attributes()); } - | T_DNUMBER { $$ = Scalar\DNumber::fromString($1, attributes()); } - | dereferencable_scalar { $$ = $1; } - | constant { $$ = $1; } - | class_constant { $$ = $1; } - | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC - { $$ = $this->parseDocString($1, $2, $3, attributes(), stackAttributes(#3), true); } - | T_START_HEREDOC T_END_HEREDOC - { $$ = $this->parseDocString($1, '', $2, attributes(), stackAttributes(#2), true); } - | T_START_HEREDOC encaps_list T_END_HEREDOC - { $$ = $this->parseDocString($1, $2, $3, attributes(), stackAttributes(#3), true); } -; - -optional_expr: - /* empty */ { $$ = null; } - | expr { $$ = $1; } -; - -fully_dereferencable: - variable { $$ = $1; } - | '(' expr ')' { $$ = $2; } - | dereferencable_scalar { $$ = $1; } - | class_constant { $$ = $1; } -; - -array_object_dereferencable: - fully_dereferencable { $$ = $1; } - | constant { $$ = $1; } -; - -callable_expr: - callable_variable { $$ = $1; } - | '(' expr ')' { $$ = $2; } - | dereferencable_scalar { $$ = $1; } -; - -callable_variable: - simple_variable { $$ = $1; } - | array_object_dereferencable '[' optional_expr ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } - | array_object_dereferencable '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } - | function_call { $$ = $1; } - | array_object_dereferencable T_OBJECT_OPERATOR property_name argument_list - { $$ = Expr\MethodCall[$1, $3, $4]; } - | array_object_dereferencable T_NULLSAFE_OBJECT_OPERATOR property_name argument_list - { $$ = Expr\NullsafeMethodCall[$1, $3, $4]; } -; - -optional_plain_variable: - /* empty */ { $$ = null; } - | plain_variable { $$ = $1; } -; - -variable: - callable_variable { $$ = $1; } - | static_member { $$ = $1; } - | array_object_dereferencable T_OBJECT_OPERATOR property_name - { $$ = Expr\PropertyFetch[$1, $3]; } - | array_object_dereferencable T_NULLSAFE_OBJECT_OPERATOR property_name - { $$ = Expr\NullsafePropertyFetch[$1, $3]; } -; - -simple_variable: - plain_variable { $$ = $1; } - | '$' '{' expr '}' { $$ = Expr\Variable[$3]; } - | '$' simple_variable { $$ = Expr\Variable[$2]; } - | '$' error { $$ = Expr\Variable[Expr\Error[]]; $this->errorState = 2; } -; - -static_member_prop_name: - simple_variable - { $var = $1->name; $$ = \is_string($var) ? Node\VarLikeIdentifier[$var] : $var; } -; - -static_member: - class_name_or_var T_PAAMAYIM_NEKUDOTAYIM static_member_prop_name - { $$ = Expr\StaticPropertyFetch[$1, $3]; } -; - -new_variable: - simple_variable { $$ = $1; } - | new_variable '[' optional_expr ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } - | new_variable '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } - | new_variable T_OBJECT_OPERATOR property_name { $$ = Expr\PropertyFetch[$1, $3]; } - | new_variable T_NULLSAFE_OBJECT_OPERATOR property_name { $$ = Expr\NullsafePropertyFetch[$1, $3]; } - | class_name T_PAAMAYIM_NEKUDOTAYIM static_member_prop_name - { $$ = Expr\StaticPropertyFetch[$1, $3]; } - | new_variable T_PAAMAYIM_NEKUDOTAYIM static_member_prop_name - { $$ = Expr\StaticPropertyFetch[$1, $3]; } -; - -member_name: - identifier_maybe_reserved { $$ = $1; } - | '{' expr '}' { $$ = $2; } - | simple_variable { $$ = $1; } -; - -property_name: - identifier_not_reserved { $$ = $1; } - | '{' expr '}' { $$ = $2; } - | simple_variable { $$ = $1; } - | error { $$ = Expr\Error[]; $this->errorState = 2; } -; - -list_expr: - T_LIST '(' inner_array_pair_list ')' { $$ = Expr\List_[$3]; } -; - -array_pair_list: - inner_array_pair_list - { $$ = $1; $end = count($$)-1; if ($$[$end] === null) array_pop($$); } -; - -comma_or_error: - ',' - | error - { /* do nothing -- prevent default action of $$=$1. See #551. */ } -; - -inner_array_pair_list: - inner_array_pair_list comma_or_error array_pair { push($1, $3); } - | array_pair { init($1); } -; - -array_pair: - expr { $$ = Expr\ArrayItem[$1, null, false]; } - | ampersand variable { $$ = Expr\ArrayItem[$2, null, true]; } - | list_expr { $$ = Expr\ArrayItem[$1, null, false]; } - | expr T_DOUBLE_ARROW expr { $$ = Expr\ArrayItem[$3, $1, false]; } - | expr T_DOUBLE_ARROW ampersand variable { $$ = Expr\ArrayItem[$4, $1, true]; } - | expr T_DOUBLE_ARROW list_expr { $$ = Expr\ArrayItem[$3, $1, false]; } - | T_ELLIPSIS expr { $$ = Expr\ArrayItem[$2, null, false, attributes(), true]; } - | /* empty */ { $$ = null; } -; - -encaps_list: - encaps_list encaps_var { push($1, $2); } - | encaps_list encaps_string_part { push($1, $2); } - | encaps_var { init($1); } - | encaps_string_part encaps_var { init($1, $2); } -; - -encaps_string_part: - T_ENCAPSED_AND_WHITESPACE { $$ = Scalar\EncapsedStringPart[$1]; } -; - -encaps_str_varname: - T_STRING_VARNAME { $$ = Expr\Variable[$1]; } -; - -encaps_var: - plain_variable { $$ = $1; } - | plain_variable '[' encaps_var_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } - | plain_variable T_OBJECT_OPERATOR identifier_not_reserved - { $$ = Expr\PropertyFetch[$1, $3]; } - | plain_variable T_NULLSAFE_OBJECT_OPERATOR identifier_not_reserved - { $$ = Expr\NullsafePropertyFetch[$1, $3]; } - | T_DOLLAR_OPEN_CURLY_BRACES expr '}' { $$ = Expr\Variable[$2]; } - | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}' { $$ = Expr\Variable[$2]; } - | T_DOLLAR_OPEN_CURLY_BRACES encaps_str_varname '[' expr ']' '}' - { $$ = Expr\ArrayDimFetch[$2, $4]; } - | T_CURLY_OPEN variable '}' { $$ = $2; } -; - -encaps_var_offset: - T_STRING { $$ = Scalar\String_[$1]; } - | T_NUM_STRING { $$ = $this->parseNumString($1, attributes()); } - | '-' T_NUM_STRING { $$ = $this->parseNumString('-' . $2, attributes()); } - | plain_variable { $$ = $1; } -; - -%% diff --git a/lib/nikic/php-parser/grammar/phpyLang.php b/lib/nikic/php-parser/grammar/phpyLang.php deleted file mode 100644 index 663c2a144..000000000 --- a/lib/nikic/php-parser/grammar/phpyLang.php +++ /dev/null @@ -1,184 +0,0 @@ -<?php - -/////////////////////////////// -/// Utility regex constants /// -/////////////////////////////// - -const LIB = '(?(DEFINE) - (?<singleQuotedString>\'[^\\\\\']*+(?:\\\\.[^\\\\\']*+)*+\') - (?<doubleQuotedString>"[^\\\\"]*+(?:\\\\.[^\\\\"]*+)*+") - (?<string>(?&singleQuotedString)|(?&doubleQuotedString)) - (?<comment>/\*[^*]*+(?:\*(?!/)[^*]*+)*+\*/) - (?<code>\{[^\'"/{}]*+(?:(?:(?&string)|(?&comment)|(?&code)|/)[^\'"/{}]*+)*+}) -)'; - -const PARAMS = '\[(?<params>[^[\]]*+(?:\[(?&params)\][^[\]]*+)*+)\]'; -const ARGS = '\((?<args>[^()]*+(?:\((?&args)\)[^()]*+)*+)\)'; - -/////////////////////////////// -/// Preprocessing functions /// -/////////////////////////////// - -function preprocessGrammar($code) { - $code = resolveNodes($code); - $code = resolveMacros($code); - $code = resolveStackAccess($code); - - return $code; -} - -function resolveNodes($code) { - return preg_replace_callback( - '~\b(?<name>[A-Z][a-zA-Z_\\\\]++)\s*' . PARAMS . '~', - function($matches) { - // recurse - $matches['params'] = resolveNodes($matches['params']); - - $params = magicSplit( - '(?:' . PARAMS . '|' . ARGS . ')(*SKIP)(*FAIL)|,', - $matches['params'] - ); - - $paramCode = ''; - foreach ($params as $param) { - $paramCode .= $param . ', '; - } - - return 'new ' . $matches['name'] . '(' . $paramCode . 'attributes())'; - }, - $code - ); -} - -function resolveMacros($code) { - return preg_replace_callback( - '~\b(?<!::|->)(?!array\()(?<name>[a-z][A-Za-z]++)' . ARGS . '~', - function($matches) { - // recurse - $matches['args'] = resolveMacros($matches['args']); - - $name = $matches['name']; - $args = magicSplit( - '(?:' . PARAMS . '|' . ARGS . ')(*SKIP)(*FAIL)|,', - $matches['args'] - ); - - if ('attributes' === $name) { - assertArgs(0, $args, $name); - return '$this->startAttributeStack[#1] + $this->endAttributes'; - } - - if ('stackAttributes' === $name) { - assertArgs(1, $args, $name); - return '$this->startAttributeStack[' . $args[0] . ']' - . ' + $this->endAttributeStack[' . $args[0] . ']'; - } - - if ('init' === $name) { - return '$$ = array(' . implode(', ', $args) . ')'; - } - - if ('push' === $name) { - assertArgs(2, $args, $name); - - return $args[0] . '[] = ' . $args[1] . '; $$ = ' . $args[0]; - } - - if ('pushNormalizing' === $name) { - assertArgs(2, $args, $name); - - return 'if (is_array(' . $args[1] . ')) { $$ = array_merge(' . $args[0] . ', ' . $args[1] . '); }' - . ' else { ' . $args[0] . '[] = ' . $args[1] . '; $$ = ' . $args[0] . '; }'; - } - - if ('toArray' == $name) { - assertArgs(1, $args, $name); - - return 'is_array(' . $args[0] . ') ? ' . $args[0] . ' : array(' . $args[0] . ')'; - } - - if ('parseVar' === $name) { - assertArgs(1, $args, $name); - - return 'substr(' . $args[0] . ', 1)'; - } - - if ('parseEncapsed' === $name) { - assertArgs(3, $args, $name); - - return 'foreach (' . $args[0] . ' as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) {' - . ' $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, ' . $args[1] . ', ' . $args[2] . '); } }'; - } - - if ('makeNop' === $name) { - assertArgs(3, $args, $name); - - return '$startAttributes = ' . $args[1] . ';' - . ' if (isset($startAttributes[\'comments\']))' - . ' { ' . $args[0] . ' = new Stmt\Nop($startAttributes + ' . $args[2] . '); }' - . ' else { ' . $args[0] . ' = null; }'; - } - - if ('makeZeroLengthNop' == $name) { - assertArgs(2, $args, $name); - - return '$startAttributes = ' . $args[1] . ';' - . ' if (isset($startAttributes[\'comments\']))' - . ' { ' . $args[0] . ' = new Stmt\Nop($this->createCommentNopAttributes($startAttributes[\'comments\'])); }' - . ' else { ' . $args[0] . ' = null; }'; - } - - if ('prependLeadingComments' === $name) { - assertArgs(1, $args, $name); - - return '$attrs = $this->startAttributeStack[#1]; $stmts = ' . $args[0] . '; ' - . 'if (!empty($attrs[\'comments\'])) {' - . '$stmts[0]->setAttribute(\'comments\', ' - . 'array_merge($attrs[\'comments\'], $stmts[0]->getAttribute(\'comments\', []))); }'; - } - - return $matches[0]; - }, - $code - ); -} - -function assertArgs($num, $args, $name) { - if ($num != count($args)) { - die('Wrong argument count for ' . $name . '().'); - } -} - -function resolveStackAccess($code) { - $code = preg_replace('/\$\d+/', '$this->semStack[$0]', $code); - $code = preg_replace('/#(\d+)/', '$$1', $code); - return $code; -} - -function removeTrailingWhitespace($code) { - $lines = explode("\n", $code); - $lines = array_map('rtrim', $lines); - return implode("\n", $lines); -} - -////////////////////////////// -/// Regex helper functions /// -////////////////////////////// - -function regex($regex) { - return '~' . LIB . '(?:' . str_replace('~', '\~', $regex) . ')~'; -} - -function magicSplit($regex, $string) { - $pieces = preg_split(regex('(?:(?&string)|(?&comment)|(?&code))(*SKIP)(*FAIL)|' . $regex), $string); - - foreach ($pieces as &$piece) { - $piece = trim($piece); - } - - if ($pieces === ['']) { - return []; - } - - return $pieces; -} diff --git a/lib/nikic/php-parser/grammar/rebuildParsers.php b/lib/nikic/php-parser/grammar/rebuildParsers.php deleted file mode 100644 index 2d0c6b14d..000000000 --- a/lib/nikic/php-parser/grammar/rebuildParsers.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php - -require __DIR__ . '/phpyLang.php'; - -$grammarFileToName = [ - __DIR__ . '/php5.y' => 'Php5', - __DIR__ . '/php7.y' => 'Php7', -]; - -$tokensFile = __DIR__ . '/tokens.y'; -$tokensTemplate = __DIR__ . '/tokens.template'; -$skeletonFile = __DIR__ . '/parser.template'; -$tmpGrammarFile = __DIR__ . '/tmp_parser.phpy'; -$tmpResultFile = __DIR__ . '/tmp_parser.php'; -$resultDir = __DIR__ . '/../lib/PhpParser/Parser'; -$tokensResultsFile = $resultDir . '/Tokens.php'; - -$kmyacc = getenv('KMYACC'); -if (!$kmyacc) { - // Use phpyacc from dev dependencies by default. - $kmyacc = __DIR__ . '/../vendor/bin/phpyacc'; -} - -$options = array_flip($argv); -$optionDebug = isset($options['--debug']); -$optionKeepTmpGrammar = isset($options['--keep-tmp-grammar']); - -/////////////////// -/// Main script /// -/////////////////// - -$tokens = file_get_contents($tokensFile); - -foreach ($grammarFileToName as $grammarFile => $name) { - echo "Building temporary $name grammar file.\n"; - - $grammarCode = file_get_contents($grammarFile); - $grammarCode = str_replace('%tokens', $tokens, $grammarCode); - $grammarCode = preprocessGrammar($grammarCode); - - file_put_contents($tmpGrammarFile, $grammarCode); - - $additionalArgs = $optionDebug ? '-t -v' : ''; - - echo "Building $name parser.\n"; - $output = execCmd("$kmyacc $additionalArgs -m $skeletonFile -p $name $tmpGrammarFile"); - - $resultCode = file_get_contents($tmpResultFile); - $resultCode = removeTrailingWhitespace($resultCode); - - ensureDirExists($resultDir); - file_put_contents("$resultDir/$name.php", $resultCode); - unlink($tmpResultFile); - - echo "Building token definition.\n"; - $output = execCmd("$kmyacc -m $tokensTemplate $tmpGrammarFile"); - rename($tmpResultFile, $tokensResultsFile); - - if (!$optionKeepTmpGrammar) { - unlink($tmpGrammarFile); - } -} - -//////////////////////////////// -/// Utility helper functions /// -//////////////////////////////// - -function ensureDirExists($dir) { - if (!is_dir($dir)) { - mkdir($dir, 0777, true); - } -} - -function execCmd($cmd) { - $output = trim(shell_exec("$cmd 2>&1")); - if ($output !== "") { - echo "> " . $cmd . "\n"; - echo $output; - } - return $output; -} diff --git a/lib/nikic/php-parser/grammar/tokens.template b/lib/nikic/php-parser/grammar/tokens.template deleted file mode 100644 index ba4e4901c..000000000 --- a/lib/nikic/php-parser/grammar/tokens.template +++ /dev/null @@ -1,17 +0,0 @@ -<?php -$meta # -#semval($) $this->semValue -#semval($,%t) $this->semValue -#semval(%n) $this->stackPos-(%l-%n) -#semval(%n,%t) $this->stackPos-(%l-%n) - -namespace PhpParser\Parser; -#include; - -/* GENERATED file based on grammar/tokens.y */ -final class Tokens -{ -#tokenval - const %s = %n; -#endtokenval -} diff --git a/lib/nikic/php-parser/grammar/tokens.y b/lib/nikic/php-parser/grammar/tokens.y deleted file mode 100644 index 8f0b21725..000000000 --- a/lib/nikic/php-parser/grammar/tokens.y +++ /dev/null @@ -1,115 +0,0 @@ -/* We currently rely on the token ID mapping to be the same between PHP 5 and PHP 7 - so the same lexer can be used for - * both. This is enforced by sharing this token file. */ - -%right T_THROW -%left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE -%left ',' -%left T_LOGICAL_OR -%left T_LOGICAL_XOR -%left T_LOGICAL_AND -%right T_PRINT -%right T_YIELD -%right T_DOUBLE_ARROW -%right T_YIELD_FROM -%left '=' T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL T_POW_EQUAL T_COALESCE_EQUAL -%left '?' ':' -%right T_COALESCE -%left T_BOOLEAN_OR -%left T_BOOLEAN_AND -%left '|' -%left '^' -%left T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG -%nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL T_SPACESHIP -%nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL -%left T_SL T_SR -%left '+' '-' '.' -%left '*' '/' '%' -%right '!' -%nonassoc T_INSTANCEOF -%right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@' -%right T_POW -%right '[' -%nonassoc T_NEW T_CLONE -%token T_EXIT -%token T_IF -%left T_ELSEIF -%left T_ELSE -%left T_ENDIF -%token T_LNUMBER -%token T_DNUMBER -%token T_STRING -%token T_STRING_VARNAME -%token T_VARIABLE -%token T_NUM_STRING -%token T_INLINE_HTML -%token T_ENCAPSED_AND_WHITESPACE -%token T_CONSTANT_ENCAPSED_STRING -%token T_ECHO -%token T_DO -%token T_WHILE -%token T_ENDWHILE -%token T_FOR -%token T_ENDFOR -%token T_FOREACH -%token T_ENDFOREACH -%token T_DECLARE -%token T_ENDDECLARE -%token T_AS -%token T_SWITCH -%token T_MATCH -%token T_ENDSWITCH -%token T_CASE -%token T_DEFAULT -%token T_BREAK -%token T_CONTINUE -%token T_GOTO -%token T_FUNCTION -%token T_FN -%token T_CONST -%token T_RETURN -%token T_TRY -%token T_CATCH -%token T_FINALLY -%token T_THROW -%token T_USE -%token T_INSTEADOF -%token T_GLOBAL -%right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC T_READONLY -%token T_VAR -%token T_UNSET -%token T_ISSET -%token T_EMPTY -%token T_HALT_COMPILER -%token T_CLASS -%token T_TRAIT -%token T_INTERFACE -%token T_ENUM -%token T_EXTENDS -%token T_IMPLEMENTS -%token T_OBJECT_OPERATOR -%token T_NULLSAFE_OBJECT_OPERATOR -%token T_DOUBLE_ARROW -%token T_LIST -%token T_ARRAY -%token T_CALLABLE -%token T_CLASS_C -%token T_TRAIT_C -%token T_METHOD_C -%token T_FUNC_C -%token T_LINE -%token T_FILE -%token T_START_HEREDOC -%token T_END_HEREDOC -%token T_DOLLAR_OPEN_CURLY_BRACES -%token T_CURLY_OPEN -%token T_PAAMAYIM_NEKUDOTAYIM -%token T_NAMESPACE -%token T_NS_C -%token T_DIR -%token T_NS_SEPARATOR -%token T_ELLIPSIS -%token T_NAME_FULLY_QUALIFIED -%token T_NAME_QUALIFIED -%token T_NAME_RELATIVE -%token T_ATTRIBUTE -%token T_ENUM diff --git a/lib/nikic/php-parser/lib/PhpParser/Builder.php b/lib/nikic/php-parser/lib/PhpParser/Builder.php deleted file mode 100644 index 26d8921ef..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Builder.php +++ /dev/null @@ -1,13 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser; - -interface Builder -{ - /** - * Returns the built node. - * - * @return Node The built node - */ - public function getNode() : Node; -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Builder/ClassConst.php b/lib/nikic/php-parser/lib/PhpParser/Builder/ClassConst.php deleted file mode 100644 index f616c6270..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Builder/ClassConst.php +++ /dev/null @@ -1,132 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace PhpParser\Builder; - -use PhpParser; -use PhpParser\BuilderHelpers; -use PhpParser\Node; -use PhpParser\Node\Const_; -use PhpParser\Node\Identifier; -use PhpParser\Node\Stmt; - -class ClassConst implements PhpParser\Builder -{ - protected $flags = 0; - protected $attributes = []; - protected $constants = []; - - /** @var Node\AttributeGroup[] */ - protected $attributeGroups = []; - - /** - * Creates a class constant builder - * - * @param string|Identifier $name Name - * @param Node\Expr|bool|null|int|float|string|array $value Value - */ - public function __construct($name, $value) { - $this->constants = [new Const_($name, BuilderHelpers::normalizeValue($value))]; - } - - /** - * Add another constant to const group - * - * @param string|Identifier $name Name - * @param Node\Expr|bool|null|int|float|string|array $value Value - * - * @return $this The builder instance (for fluid interface) - */ - public function addConst($name, $value) { - $this->constants[] = new Const_($name, BuilderHelpers::normalizeValue($value)); - - return $this; - } - - /** - * Makes the constant public. - * - * @return $this The builder instance (for fluid interface) - */ - public function makePublic() { - $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PUBLIC); - - return $this; - } - - /** - * Makes the constant protected. - * - * @return $this The builder instance (for fluid interface) - */ - public function makeProtected() { - $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PROTECTED); - - return $this; - } - - /** - * Makes the constant private. - * - * @return $this The builder instance (for fluid interface) - */ - public function makePrivate() { - $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PRIVATE); - - return $this; - } - - /** - * Makes the constant final. - * - * @return $this The builder instance (for fluid interface) - */ - public function makeFinal() { - $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_FINAL); - - return $this; - } - - /** - * Sets doc comment for the constant. - * - * @param PhpParser\Comment\Doc|string $docComment Doc comment to set - * - * @return $this The builder instance (for fluid interface) - */ - public function setDocComment($docComment) { - $this->attributes = [ - 'comments' => [BuilderHelpers::normalizeDocComment($docComment)] - ]; - - return $this; - } - - /** - * Adds an attribute group. - * - * @param Node\Attribute|Node\AttributeGroup $attribute - * - * @return $this The builder instance (for fluid interface) - */ - public function addAttribute($attribute) { - $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); - - return $this; - } - - /** - * Returns the built class node. - * - * @return Stmt\ClassConst The built constant node - */ - public function getNode(): PhpParser\Node { - return new Stmt\ClassConst( - $this->constants, - $this->flags, - $this->attributes, - $this->attributeGroups - ); - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Builder/Class_.php b/lib/nikic/php-parser/lib/PhpParser/Builder/Class_.php deleted file mode 100644 index 35b54d041..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Builder/Class_.php +++ /dev/null @@ -1,146 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Builder; - -use PhpParser; -use PhpParser\BuilderHelpers; -use PhpParser\Node; -use PhpParser\Node\Name; -use PhpParser\Node\Stmt; - -class Class_ extends Declaration -{ - protected $name; - - protected $extends = null; - protected $implements = []; - protected $flags = 0; - - protected $uses = []; - protected $constants = []; - protected $properties = []; - protected $methods = []; - - /** @var Node\AttributeGroup[] */ - protected $attributeGroups = []; - - /** - * Creates a class builder. - * - * @param string $name Name of the class - */ - public function __construct(string $name) { - $this->name = $name; - } - - /** - * Extends a class. - * - * @param Name|string $class Name of class to extend - * - * @return $this The builder instance (for fluid interface) - */ - public function extend($class) { - $this->extends = BuilderHelpers::normalizeName($class); - - return $this; - } - - /** - * Implements one or more interfaces. - * - * @param Name|string ...$interfaces Names of interfaces to implement - * - * @return $this The builder instance (for fluid interface) - */ - public function implement(...$interfaces) { - foreach ($interfaces as $interface) { - $this->implements[] = BuilderHelpers::normalizeName($interface); - } - - return $this; - } - - /** - * Makes the class abstract. - * - * @return $this The builder instance (for fluid interface) - */ - public function makeAbstract() { - $this->flags = BuilderHelpers::addClassModifier($this->flags, Stmt\Class_::MODIFIER_ABSTRACT); - - return $this; - } - - /** - * Makes the class final. - * - * @return $this The builder instance (for fluid interface) - */ - public function makeFinal() { - $this->flags = BuilderHelpers::addClassModifier($this->flags, Stmt\Class_::MODIFIER_FINAL); - - return $this; - } - - public function makeReadonly() { - $this->flags = BuilderHelpers::addClassModifier($this->flags, Stmt\Class_::MODIFIER_READONLY); - - return $this; - } - - /** - * Adds a statement. - * - * @param Stmt|PhpParser\Builder $stmt The statement to add - * - * @return $this The builder instance (for fluid interface) - */ - public function addStmt($stmt) { - $stmt = BuilderHelpers::normalizeNode($stmt); - - $targets = [ - Stmt\TraitUse::class => &$this->uses, - Stmt\ClassConst::class => &$this->constants, - Stmt\Property::class => &$this->properties, - Stmt\ClassMethod::class => &$this->methods, - ]; - - $class = \get_class($stmt); - if (!isset($targets[$class])) { - throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType())); - } - - $targets[$class][] = $stmt; - - return $this; - } - - /** - * Adds an attribute group. - * - * @param Node\Attribute|Node\AttributeGroup $attribute - * - * @return $this The builder instance (for fluid interface) - */ - public function addAttribute($attribute) { - $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); - - return $this; - } - - /** - * Returns the built class node. - * - * @return Stmt\Class_ The built class node - */ - public function getNode() : PhpParser\Node { - return new Stmt\Class_($this->name, [ - 'flags' => $this->flags, - 'extends' => $this->extends, - 'implements' => $this->implements, - 'stmts' => array_merge($this->uses, $this->constants, $this->properties, $this->methods), - 'attrGroups' => $this->attributeGroups, - ], $this->attributes); - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Builder/Declaration.php b/lib/nikic/php-parser/lib/PhpParser/Builder/Declaration.php deleted file mode 100644 index 830949928..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Builder/Declaration.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Builder; - -use PhpParser; -use PhpParser\BuilderHelpers; - -abstract class Declaration implements PhpParser\Builder -{ - protected $attributes = []; - - abstract public function addStmt($stmt); - - /** - * Adds multiple statements. - * - * @param array $stmts The statements to add - * - * @return $this The builder instance (for fluid interface) - */ - public function addStmts(array $stmts) { - foreach ($stmts as $stmt) { - $this->addStmt($stmt); - } - - return $this; - } - - /** - * Sets doc comment for the declaration. - * - * @param PhpParser\Comment\Doc|string $docComment Doc comment to set - * - * @return $this The builder instance (for fluid interface) - */ - public function setDocComment($docComment) { - $this->attributes['comments'] = [ - BuilderHelpers::normalizeDocComment($docComment) - ]; - - return $this; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Builder/EnumCase.php b/lib/nikic/php-parser/lib/PhpParser/Builder/EnumCase.php deleted file mode 100644 index 02fa83e62..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Builder/EnumCase.php +++ /dev/null @@ -1,85 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace PhpParser\Builder; - -use PhpParser; -use PhpParser\BuilderHelpers; -use PhpParser\Node; -use PhpParser\Node\Identifier; -use PhpParser\Node\Stmt; - -class EnumCase implements PhpParser\Builder -{ - protected $name; - protected $value = null; - protected $attributes = []; - - /** @var Node\AttributeGroup[] */ - protected $attributeGroups = []; - - /** - * Creates an enum case builder. - * - * @param string|Identifier $name Name - */ - public function __construct($name) { - $this->name = $name; - } - - /** - * Sets the value. - * - * @param Node\Expr|string|int $value - * - * @return $this - */ - public function setValue($value) { - $this->value = BuilderHelpers::normalizeValue($value); - - return $this; - } - - /** - * Sets doc comment for the constant. - * - * @param PhpParser\Comment\Doc|string $docComment Doc comment to set - * - * @return $this The builder instance (for fluid interface) - */ - public function setDocComment($docComment) { - $this->attributes = [ - 'comments' => [BuilderHelpers::normalizeDocComment($docComment)] - ]; - - return $this; - } - - /** - * Adds an attribute group. - * - * @param Node\Attribute|Node\AttributeGroup $attribute - * - * @return $this The builder instance (for fluid interface) - */ - public function addAttribute($attribute) { - $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); - - return $this; - } - - /** - * Returns the built enum case node. - * - * @return Stmt\EnumCase The built constant node - */ - public function getNode(): PhpParser\Node { - return new Stmt\EnumCase( - $this->name, - $this->value, - $this->attributes, - $this->attributeGroups - ); - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Builder/Enum_.php b/lib/nikic/php-parser/lib/PhpParser/Builder/Enum_.php deleted file mode 100644 index be7eef95f..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Builder/Enum_.php +++ /dev/null @@ -1,117 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Builder; - -use PhpParser; -use PhpParser\BuilderHelpers; -use PhpParser\Node; -use PhpParser\Node\Identifier; -use PhpParser\Node\Name; -use PhpParser\Node\Stmt; - -class Enum_ extends Declaration -{ - protected $name; - protected $scalarType = null; - - protected $implements = []; - - protected $uses = []; - protected $enumCases = []; - protected $constants = []; - protected $methods = []; - - /** @var Node\AttributeGroup[] */ - protected $attributeGroups = []; - - /** - * Creates an enum builder. - * - * @param string $name Name of the enum - */ - public function __construct(string $name) { - $this->name = $name; - } - - /** - * Sets the scalar type. - * - * @param string|Identifier $type - * - * @return $this - */ - public function setScalarType($scalarType) { - $this->scalarType = BuilderHelpers::normalizeType($scalarType); - - return $this; - } - - /** - * Implements one or more interfaces. - * - * @param Name|string ...$interfaces Names of interfaces to implement - * - * @return $this The builder instance (for fluid interface) - */ - public function implement(...$interfaces) { - foreach ($interfaces as $interface) { - $this->implements[] = BuilderHelpers::normalizeName($interface); - } - - return $this; - } - - /** - * Adds a statement. - * - * @param Stmt|PhpParser\Builder $stmt The statement to add - * - * @return $this The builder instance (for fluid interface) - */ - public function addStmt($stmt) { - $stmt = BuilderHelpers::normalizeNode($stmt); - - $targets = [ - Stmt\TraitUse::class => &$this->uses, - Stmt\EnumCase::class => &$this->enumCases, - Stmt\ClassConst::class => &$this->constants, - Stmt\ClassMethod::class => &$this->methods, - ]; - - $class = \get_class($stmt); - if (!isset($targets[$class])) { - throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType())); - } - - $targets[$class][] = $stmt; - - return $this; - } - - /** - * Adds an attribute group. - * - * @param Node\Attribute|Node\AttributeGroup $attribute - * - * @return $this The builder instance (for fluid interface) - */ - public function addAttribute($attribute) { - $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); - - return $this; - } - - /** - * Returns the built class node. - * - * @return Stmt\Enum_ The built enum node - */ - public function getNode() : PhpParser\Node { - return new Stmt\Enum_($this->name, [ - 'scalarType' => $this->scalarType, - 'implements' => $this->implements, - 'stmts' => array_merge($this->uses, $this->enumCases, $this->constants, $this->methods), - 'attrGroups' => $this->attributeGroups, - ], $this->attributes); - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php b/lib/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php deleted file mode 100644 index 98ea9d336..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php +++ /dev/null @@ -1,73 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Builder; - -use PhpParser\BuilderHelpers; -use PhpParser\Node; - -abstract class FunctionLike extends Declaration -{ - protected $returnByRef = false; - protected $params = []; - - /** @var string|Node\Name|Node\NullableType|null */ - protected $returnType = null; - - /** - * Make the function return by reference. - * - * @return $this The builder instance (for fluid interface) - */ - public function makeReturnByRef() { - $this->returnByRef = true; - - return $this; - } - - /** - * Adds a parameter. - * - * @param Node\Param|Param $param The parameter to add - * - * @return $this The builder instance (for fluid interface) - */ - public function addParam($param) { - $param = BuilderHelpers::normalizeNode($param); - - if (!$param instanceof Node\Param) { - throw new \LogicException(sprintf('Expected parameter node, got "%s"', $param->getType())); - } - - $this->params[] = $param; - - return $this; - } - - /** - * Adds multiple parameters. - * - * @param array $params The parameters to add - * - * @return $this The builder instance (for fluid interface) - */ - public function addParams(array $params) { - foreach ($params as $param) { - $this->addParam($param); - } - - return $this; - } - - /** - * Sets the return type for PHP 7. - * - * @param string|Node\Name|Node\Identifier|Node\ComplexType $type - * - * @return $this The builder instance (for fluid interface) - */ - public function setReturnType($type) { - $this->returnType = BuilderHelpers::normalizeType($type); - - return $this; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Builder/Function_.php b/lib/nikic/php-parser/lib/PhpParser/Builder/Function_.php deleted file mode 100644 index 1cd73c0d3..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Builder/Function_.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Builder; - -use PhpParser; -use PhpParser\BuilderHelpers; -use PhpParser\Node; -use PhpParser\Node\Stmt; - -class Function_ extends FunctionLike -{ - protected $name; - protected $stmts = []; - - /** @var Node\AttributeGroup[] */ - protected $attributeGroups = []; - - /** - * Creates a function builder. - * - * @param string $name Name of the function - */ - public function __construct(string $name) { - $this->name = $name; - } - - /** - * Adds a statement. - * - * @param Node|PhpParser\Builder $stmt The statement to add - * - * @return $this The builder instance (for fluid interface) - */ - public function addStmt($stmt) { - $this->stmts[] = BuilderHelpers::normalizeStmt($stmt); - - return $this; - } - - /** - * Adds an attribute group. - * - * @param Node\Attribute|Node\AttributeGroup $attribute - * - * @return $this The builder instance (for fluid interface) - */ - public function addAttribute($attribute) { - $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); - - return $this; - } - - /** - * Returns the built function node. - * - * @return Stmt\Function_ The built function node - */ - public function getNode() : Node { - return new Stmt\Function_($this->name, [ - 'byRef' => $this->returnByRef, - 'params' => $this->params, - 'returnType' => $this->returnType, - 'stmts' => $this->stmts, - 'attrGroups' => $this->attributeGroups, - ], $this->attributes); - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Builder/Interface_.php b/lib/nikic/php-parser/lib/PhpParser/Builder/Interface_.php deleted file mode 100644 index 7806e85fc..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Builder/Interface_.php +++ /dev/null @@ -1,93 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Builder; - -use PhpParser; -use PhpParser\BuilderHelpers; -use PhpParser\Node; -use PhpParser\Node\Name; -use PhpParser\Node\Stmt; - -class Interface_ extends Declaration -{ - protected $name; - protected $extends = []; - protected $constants = []; - protected $methods = []; - - /** @var Node\AttributeGroup[] */ - protected $attributeGroups = []; - - /** - * Creates an interface builder. - * - * @param string $name Name of the interface - */ - public function __construct(string $name) { - $this->name = $name; - } - - /** - * Extends one or more interfaces. - * - * @param Name|string ...$interfaces Names of interfaces to extend - * - * @return $this The builder instance (for fluid interface) - */ - public function extend(...$interfaces) { - foreach ($interfaces as $interface) { - $this->extends[] = BuilderHelpers::normalizeName($interface); - } - - return $this; - } - - /** - * Adds a statement. - * - * @param Stmt|PhpParser\Builder $stmt The statement to add - * - * @return $this The builder instance (for fluid interface) - */ - public function addStmt($stmt) { - $stmt = BuilderHelpers::normalizeNode($stmt); - - if ($stmt instanceof Stmt\ClassConst) { - $this->constants[] = $stmt; - } elseif ($stmt instanceof Stmt\ClassMethod) { - // we erase all statements in the body of an interface method - $stmt->stmts = null; - $this->methods[] = $stmt; - } else { - throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType())); - } - - return $this; - } - - /** - * Adds an attribute group. - * - * @param Node\Attribute|Node\AttributeGroup $attribute - * - * @return $this The builder instance (for fluid interface) - */ - public function addAttribute($attribute) { - $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); - - return $this; - } - - /** - * Returns the built interface node. - * - * @return Stmt\Interface_ The built interface node - */ - public function getNode() : PhpParser\Node { - return new Stmt\Interface_($this->name, [ - 'extends' => $this->extends, - 'stmts' => array_merge($this->constants, $this->methods), - 'attrGroups' => $this->attributeGroups, - ], $this->attributes); - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Builder/Method.php b/lib/nikic/php-parser/lib/PhpParser/Builder/Method.php deleted file mode 100644 index 232d7cb87..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Builder/Method.php +++ /dev/null @@ -1,146 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Builder; - -use PhpParser; -use PhpParser\BuilderHelpers; -use PhpParser\Node; -use PhpParser\Node\Stmt; - -class Method extends FunctionLike -{ - protected $name; - protected $flags = 0; - - /** @var array|null */ - protected $stmts = []; - - /** @var Node\AttributeGroup[] */ - protected $attributeGroups = []; - - /** - * Creates a method builder. - * - * @param string $name Name of the method - */ - public function __construct(string $name) { - $this->name = $name; - } - - /** - * Makes the method public. - * - * @return $this The builder instance (for fluid interface) - */ - public function makePublic() { - $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PUBLIC); - - return $this; - } - - /** - * Makes the method protected. - * - * @return $this The builder instance (for fluid interface) - */ - public function makeProtected() { - $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PROTECTED); - - return $this; - } - - /** - * Makes the method private. - * - * @return $this The builder instance (for fluid interface) - */ - public function makePrivate() { - $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PRIVATE); - - return $this; - } - - /** - * Makes the method static. - * - * @return $this The builder instance (for fluid interface) - */ - public function makeStatic() { - $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_STATIC); - - return $this; - } - - /** - * Makes the method abstract. - * - * @return $this The builder instance (for fluid interface) - */ - public function makeAbstract() { - if (!empty($this->stmts)) { - throw new \LogicException('Cannot make method with statements abstract'); - } - - $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_ABSTRACT); - $this->stmts = null; // abstract methods don't have statements - - return $this; - } - - /** - * Makes the method final. - * - * @return $this The builder instance (for fluid interface) - */ - public function makeFinal() { - $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_FINAL); - - return $this; - } - - /** - * Adds a statement. - * - * @param Node|PhpParser\Builder $stmt The statement to add - * - * @return $this The builder instance (for fluid interface) - */ - public function addStmt($stmt) { - if (null === $this->stmts) { - throw new \LogicException('Cannot add statements to an abstract method'); - } - - $this->stmts[] = BuilderHelpers::normalizeStmt($stmt); - - return $this; - } - - /** - * Adds an attribute group. - * - * @param Node\Attribute|Node\AttributeGroup $attribute - * - * @return $this The builder instance (for fluid interface) - */ - public function addAttribute($attribute) { - $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); - - return $this; - } - - /** - * Returns the built method node. - * - * @return Stmt\ClassMethod The built method node - */ - public function getNode() : Node { - return new Stmt\ClassMethod($this->name, [ - 'flags' => $this->flags, - 'byRef' => $this->returnByRef, - 'params' => $this->params, - 'returnType' => $this->returnType, - 'stmts' => $this->stmts, - 'attrGroups' => $this->attributeGroups, - ], $this->attributes); - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php b/lib/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php deleted file mode 100644 index 1c751e163..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Builder; - -use PhpParser; -use PhpParser\BuilderHelpers; -use PhpParser\Node; -use PhpParser\Node\Stmt; - -class Namespace_ extends Declaration -{ - private $name; - private $stmts = []; - - /** - * Creates a namespace builder. - * - * @param Node\Name|string|null $name Name of the namespace - */ - public function __construct($name) { - $this->name = null !== $name ? BuilderHelpers::normalizeName($name) : null; - } - - /** - * Adds a statement. - * - * @param Node|PhpParser\Builder $stmt The statement to add - * - * @return $this The builder instance (for fluid interface) - */ - public function addStmt($stmt) { - $this->stmts[] = BuilderHelpers::normalizeStmt($stmt); - - return $this; - } - - /** - * Returns the built node. - * - * @return Stmt\Namespace_ The built node - */ - public function getNode() : Node { - return new Stmt\Namespace_($this->name, $this->stmts, $this->attributes); - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Builder/Param.php b/lib/nikic/php-parser/lib/PhpParser/Builder/Param.php deleted file mode 100644 index de9aae7e5..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Builder/Param.php +++ /dev/null @@ -1,122 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Builder; - -use PhpParser; -use PhpParser\BuilderHelpers; -use PhpParser\Node; - -class Param implements PhpParser\Builder -{ - protected $name; - - protected $default = null; - - /** @var Node\Identifier|Node\Name|Node\NullableType|null */ - protected $type = null; - - protected $byRef = false; - - protected $variadic = false; - - /** @var Node\AttributeGroup[] */ - protected $attributeGroups = []; - - /** - * Creates a parameter builder. - * - * @param string $name Name of the parameter - */ - public function __construct(string $name) { - $this->name = $name; - } - - /** - * Sets default value for the parameter. - * - * @param mixed $value Default value to use - * - * @return $this The builder instance (for fluid interface) - */ - public function setDefault($value) { - $this->default = BuilderHelpers::normalizeValue($value); - - return $this; - } - - /** - * Sets type for the parameter. - * - * @param string|Node\Name|Node\Identifier|Node\ComplexType $type Parameter type - * - * @return $this The builder instance (for fluid interface) - */ - public function setType($type) { - $this->type = BuilderHelpers::normalizeType($type); - if ($this->type == 'void') { - throw new \LogicException('Parameter type cannot be void'); - } - - return $this; - } - - /** - * Sets type for the parameter. - * - * @param string|Node\Name|Node\Identifier|Node\ComplexType $type Parameter type - * - * @return $this The builder instance (for fluid interface) - * - * @deprecated Use setType() instead - */ - public function setTypeHint($type) { - return $this->setType($type); - } - - /** - * Make the parameter accept the value by reference. - * - * @return $this The builder instance (for fluid interface) - */ - public function makeByRef() { - $this->byRef = true; - - return $this; - } - - /** - * Make the parameter variadic - * - * @return $this The builder instance (for fluid interface) - */ - public function makeVariadic() { - $this->variadic = true; - - return $this; - } - - /** - * Adds an attribute group. - * - * @param Node\Attribute|Node\AttributeGroup $attribute - * - * @return $this The builder instance (for fluid interface) - */ - public function addAttribute($attribute) { - $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); - - return $this; - } - - /** - * Returns the built parameter node. - * - * @return Node\Param The built parameter node - */ - public function getNode() : Node { - return new Node\Param( - new Node\Expr\Variable($this->name), - $this->default, $this->type, $this->byRef, $this->variadic, [], 0, $this->attributeGroups - ); - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Builder/Property.php b/lib/nikic/php-parser/lib/PhpParser/Builder/Property.php deleted file mode 100644 index 68e318565..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Builder/Property.php +++ /dev/null @@ -1,161 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Builder; - -use PhpParser; -use PhpParser\BuilderHelpers; -use PhpParser\Node; -use PhpParser\Node\Identifier; -use PhpParser\Node\Name; -use PhpParser\Node\Stmt; -use PhpParser\Node\ComplexType; - -class Property implements PhpParser\Builder -{ - protected $name; - - protected $flags = 0; - protected $default = null; - protected $attributes = []; - - /** @var null|Identifier|Name|NullableType */ - protected $type; - - /** @var Node\AttributeGroup[] */ - protected $attributeGroups = []; - - /** - * Creates a property builder. - * - * @param string $name Name of the property - */ - public function __construct(string $name) { - $this->name = $name; - } - - /** - * Makes the property public. - * - * @return $this The builder instance (for fluid interface) - */ - public function makePublic() { - $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PUBLIC); - - return $this; - } - - /** - * Makes the property protected. - * - * @return $this The builder instance (for fluid interface) - */ - public function makeProtected() { - $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PROTECTED); - - return $this; - } - - /** - * Makes the property private. - * - * @return $this The builder instance (for fluid interface) - */ - public function makePrivate() { - $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PRIVATE); - - return $this; - } - - /** - * Makes the property static. - * - * @return $this The builder instance (for fluid interface) - */ - public function makeStatic() { - $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_STATIC); - - return $this; - } - - /** - * Makes the property readonly. - * - * @return $this The builder instance (for fluid interface) - */ - public function makeReadonly() { - $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_READONLY); - - return $this; - } - - /** - * Sets default value for the property. - * - * @param mixed $value Default value to use - * - * @return $this The builder instance (for fluid interface) - */ - public function setDefault($value) { - $this->default = BuilderHelpers::normalizeValue($value); - - return $this; - } - - /** - * Sets doc comment for the property. - * - * @param PhpParser\Comment\Doc|string $docComment Doc comment to set - * - * @return $this The builder instance (for fluid interface) - */ - public function setDocComment($docComment) { - $this->attributes = [ - 'comments' => [BuilderHelpers::normalizeDocComment($docComment)] - ]; - - return $this; - } - - /** - * Sets the property type for PHP 7.4+. - * - * @param string|Name|Identifier|ComplexType $type - * - * @return $this - */ - public function setType($type) { - $this->type = BuilderHelpers::normalizeType($type); - - return $this; - } - - /** - * Adds an attribute group. - * - * @param Node\Attribute|Node\AttributeGroup $attribute - * - * @return $this The builder instance (for fluid interface) - */ - public function addAttribute($attribute) { - $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); - - return $this; - } - - /** - * Returns the built class node. - * - * @return Stmt\Property The built property node - */ - public function getNode() : PhpParser\Node { - return new Stmt\Property( - $this->flags !== 0 ? $this->flags : Stmt\Class_::MODIFIER_PUBLIC, - [ - new Stmt\PropertyProperty($this->name, $this->default) - ], - $this->attributes, - $this->type, - $this->attributeGroups - ); - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Builder/TraitUse.php b/lib/nikic/php-parser/lib/PhpParser/Builder/TraitUse.php deleted file mode 100644 index 311e8cd7b..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Builder/TraitUse.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Builder; - -use PhpParser\Builder; -use PhpParser\BuilderHelpers; -use PhpParser\Node; -use PhpParser\Node\Stmt; - -class TraitUse implements Builder -{ - protected $traits = []; - protected $adaptations = []; - - /** - * Creates a trait use builder. - * - * @param Node\Name|string ...$traits Names of used traits - */ - public function __construct(...$traits) { - foreach ($traits as $trait) { - $this->and($trait); - } - } - - /** - * Adds used trait. - * - * @param Node\Name|string $trait Trait name - * - * @return $this The builder instance (for fluid interface) - */ - public function and($trait) { - $this->traits[] = BuilderHelpers::normalizeName($trait); - return $this; - } - - /** - * Adds trait adaptation. - * - * @param Stmt\TraitUseAdaptation|Builder\TraitUseAdaptation $adaptation Trait adaptation - * - * @return $this The builder instance (for fluid interface) - */ - public function with($adaptation) { - $adaptation = BuilderHelpers::normalizeNode($adaptation); - - if (!$adaptation instanceof Stmt\TraitUseAdaptation) { - throw new \LogicException('Adaptation must have type TraitUseAdaptation'); - } - - $this->adaptations[] = $adaptation; - return $this; - } - - /** - * Returns the built node. - * - * @return Node The built node - */ - public function getNode() : Node { - return new Stmt\TraitUse($this->traits, $this->adaptations); - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.php b/lib/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.php deleted file mode 100644 index eb6c0b622..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.php +++ /dev/null @@ -1,148 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Builder; - -use PhpParser\Builder; -use PhpParser\BuilderHelpers; -use PhpParser\Node; -use PhpParser\Node\Stmt; - -class TraitUseAdaptation implements Builder -{ - const TYPE_UNDEFINED = 0; - const TYPE_ALIAS = 1; - const TYPE_PRECEDENCE = 2; - - /** @var int Type of building adaptation */ - protected $type; - - protected $trait; - protected $method; - - protected $modifier = null; - protected $alias = null; - - protected $insteadof = []; - - /** - * Creates a trait use adaptation builder. - * - * @param Node\Name|string|null $trait Name of adaptated trait - * @param Node\Identifier|string $method Name of adaptated method - */ - public function __construct($trait, $method) { - $this->type = self::TYPE_UNDEFINED; - - $this->trait = is_null($trait)? null: BuilderHelpers::normalizeName($trait); - $this->method = BuilderHelpers::normalizeIdentifier($method); - } - - /** - * Sets alias of method. - * - * @param Node\Identifier|string $alias Alias for adaptated method - * - * @return $this The builder instance (for fluid interface) - */ - public function as($alias) { - if ($this->type === self::TYPE_UNDEFINED) { - $this->type = self::TYPE_ALIAS; - } - - if ($this->type !== self::TYPE_ALIAS) { - throw new \LogicException('Cannot set alias for not alias adaptation buider'); - } - - $this->alias = $alias; - return $this; - } - - /** - * Sets adaptated method public. - * - * @return $this The builder instance (for fluid interface) - */ - public function makePublic() { - $this->setModifier(Stmt\Class_::MODIFIER_PUBLIC); - return $this; - } - - /** - * Sets adaptated method protected. - * - * @return $this The builder instance (for fluid interface) - */ - public function makeProtected() { - $this->setModifier(Stmt\Class_::MODIFIER_PROTECTED); - return $this; - } - - /** - * Sets adaptated method private. - * - * @return $this The builder instance (for fluid interface) - */ - public function makePrivate() { - $this->setModifier(Stmt\Class_::MODIFIER_PRIVATE); - return $this; - } - - /** - * Adds overwritten traits. - * - * @param Node\Name|string ...$traits Traits for overwrite - * - * @return $this The builder instance (for fluid interface) - */ - public function insteadof(...$traits) { - if ($this->type === self::TYPE_UNDEFINED) { - if (is_null($this->trait)) { - throw new \LogicException('Precedence adaptation must have trait'); - } - - $this->type = self::TYPE_PRECEDENCE; - } - - if ($this->type !== self::TYPE_PRECEDENCE) { - throw new \LogicException('Cannot add overwritten traits for not precedence adaptation buider'); - } - - foreach ($traits as $trait) { - $this->insteadof[] = BuilderHelpers::normalizeName($trait); - } - - return $this; - } - - protected function setModifier(int $modifier) { - if ($this->type === self::TYPE_UNDEFINED) { - $this->type = self::TYPE_ALIAS; - } - - if ($this->type !== self::TYPE_ALIAS) { - throw new \LogicException('Cannot set access modifier for not alias adaptation buider'); - } - - if (is_null($this->modifier)) { - $this->modifier = $modifier; - } else { - throw new \LogicException('Multiple access type modifiers are not allowed'); - } - } - - /** - * Returns the built node. - * - * @return Node The built node - */ - public function getNode() : Node { - switch ($this->type) { - case self::TYPE_ALIAS: - return new Stmt\TraitUseAdaptation\Alias($this->trait, $this->method, $this->modifier, $this->alias); - case self::TYPE_PRECEDENCE: - return new Stmt\TraitUseAdaptation\Precedence($this->trait, $this->method, $this->insteadof); - default: - throw new \LogicException('Type of adaptation is not defined'); - } - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Builder/Trait_.php b/lib/nikic/php-parser/lib/PhpParser/Builder/Trait_.php deleted file mode 100644 index 97f32f98d..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Builder/Trait_.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Builder; - -use PhpParser; -use PhpParser\BuilderHelpers; -use PhpParser\Node; -use PhpParser\Node\Stmt; - -class Trait_ extends Declaration -{ - protected $name; - protected $uses = []; - protected $properties = []; - protected $methods = []; - - /** @var Node\AttributeGroup[] */ - protected $attributeGroups = []; - - /** - * Creates an interface builder. - * - * @param string $name Name of the interface - */ - public function __construct(string $name) { - $this->name = $name; - } - - /** - * Adds a statement. - * - * @param Stmt|PhpParser\Builder $stmt The statement to add - * - * @return $this The builder instance (for fluid interface) - */ - public function addStmt($stmt) { - $stmt = BuilderHelpers::normalizeNode($stmt); - - if ($stmt instanceof Stmt\Property) { - $this->properties[] = $stmt; - } elseif ($stmt instanceof Stmt\ClassMethod) { - $this->methods[] = $stmt; - } elseif ($stmt instanceof Stmt\TraitUse) { - $this->uses[] = $stmt; - } else { - throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType())); - } - - return $this; - } - - /** - * Adds an attribute group. - * - * @param Node\Attribute|Node\AttributeGroup $attribute - * - * @return $this The builder instance (for fluid interface) - */ - public function addAttribute($attribute) { - $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); - - return $this; - } - - /** - * Returns the built trait node. - * - * @return Stmt\Trait_ The built interface node - */ - public function getNode() : PhpParser\Node { - return new Stmt\Trait_( - $this->name, [ - 'stmts' => array_merge($this->uses, $this->properties, $this->methods), - 'attrGroups' => $this->attributeGroups, - ], $this->attributes - ); - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Builder/Use_.php b/lib/nikic/php-parser/lib/PhpParser/Builder/Use_.php deleted file mode 100644 index 4bd3d12df..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Builder/Use_.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Builder; - -use PhpParser\Builder; -use PhpParser\BuilderHelpers; -use PhpParser\Node; -use PhpParser\Node\Stmt; - -class Use_ implements Builder -{ - protected $name; - protected $type; - protected $alias = null; - - /** - * Creates a name use (alias) builder. - * - * @param Node\Name|string $name Name of the entity (namespace, class, function, constant) to alias - * @param int $type One of the Stmt\Use_::TYPE_* constants - */ - public function __construct($name, int $type) { - $this->name = BuilderHelpers::normalizeName($name); - $this->type = $type; - } - - /** - * Sets alias for used name. - * - * @param string $alias Alias to use (last component of full name by default) - * - * @return $this The builder instance (for fluid interface) - */ - public function as(string $alias) { - $this->alias = $alias; - return $this; - } - - /** - * Returns the built node. - * - * @return Stmt\Use_ The built node - */ - public function getNode() : Node { - return new Stmt\Use_([ - new Stmt\UseUse($this->name, $this->alias) - ], $this->type); - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/BuilderFactory.php b/lib/nikic/php-parser/lib/PhpParser/BuilderFactory.php deleted file mode 100644 index fef2579b3..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/BuilderFactory.php +++ /dev/null @@ -1,399 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser; - -use PhpParser\Node\Arg; -use PhpParser\Node\Expr; -use PhpParser\Node\Expr\BinaryOp\Concat; -use PhpParser\Node\Identifier; -use PhpParser\Node\Name; -use PhpParser\Node\Scalar\String_; -use PhpParser\Node\Stmt\Use_; - -class BuilderFactory -{ - /** - * Creates an attribute node. - * - * @param string|Name $name Name of the attribute - * @param array $args Attribute named arguments - * - * @return Node\Attribute - */ - public function attribute($name, array $args = []) : Node\Attribute { - return new Node\Attribute( - BuilderHelpers::normalizeName($name), - $this->args($args) - ); - } - - /** - * Creates a namespace builder. - * - * @param null|string|Node\Name $name Name of the namespace - * - * @return Builder\Namespace_ The created namespace builder - */ - public function namespace($name) : Builder\Namespace_ { - return new Builder\Namespace_($name); - } - - /** - * Creates a class builder. - * - * @param string $name Name of the class - * - * @return Builder\Class_ The created class builder - */ - public function class(string $name) : Builder\Class_ { - return new Builder\Class_($name); - } - - /** - * Creates an interface builder. - * - * @param string $name Name of the interface - * - * @return Builder\Interface_ The created interface builder - */ - public function interface(string $name) : Builder\Interface_ { - return new Builder\Interface_($name); - } - - /** - * Creates a trait builder. - * - * @param string $name Name of the trait - * - * @return Builder\Trait_ The created trait builder - */ - public function trait(string $name) : Builder\Trait_ { - return new Builder\Trait_($name); - } - - /** - * Creates an enum builder. - * - * @param string $name Name of the enum - * - * @return Builder\Enum_ The created enum builder - */ - public function enum(string $name) : Builder\Enum_ { - return new Builder\Enum_($name); - } - - /** - * Creates a trait use builder. - * - * @param Node\Name|string ...$traits Trait names - * - * @return Builder\TraitUse The create trait use builder - */ - public function useTrait(...$traits) : Builder\TraitUse { - return new Builder\TraitUse(...$traits); - } - - /** - * Creates a trait use adaptation builder. - * - * @param Node\Name|string|null $trait Trait name - * @param Node\Identifier|string $method Method name - * - * @return Builder\TraitUseAdaptation The create trait use adaptation builder - */ - public function traitUseAdaptation($trait, $method = null) : Builder\TraitUseAdaptation { - if ($method === null) { - $method = $trait; - $trait = null; - } - - return new Builder\TraitUseAdaptation($trait, $method); - } - - /** - * Creates a method builder. - * - * @param string $name Name of the method - * - * @return Builder\Method The created method builder - */ - public function method(string $name) : Builder\Method { - return new Builder\Method($name); - } - - /** - * Creates a parameter builder. - * - * @param string $name Name of the parameter - * - * @return Builder\Param The created parameter builder - */ - public function param(string $name) : Builder\Param { - return new Builder\Param($name); - } - - /** - * Creates a property builder. - * - * @param string $name Name of the property - * - * @return Builder\Property The created property builder - */ - public function property(string $name) : Builder\Property { - return new Builder\Property($name); - } - - /** - * Creates a function builder. - * - * @param string $name Name of the function - * - * @return Builder\Function_ The created function builder - */ - public function function(string $name) : Builder\Function_ { - return new Builder\Function_($name); - } - - /** - * Creates a namespace/class use builder. - * - * @param Node\Name|string $name Name of the entity (namespace or class) to alias - * - * @return Builder\Use_ The created use builder - */ - public function use($name) : Builder\Use_ { - return new Builder\Use_($name, Use_::TYPE_NORMAL); - } - - /** - * Creates a function use builder. - * - * @param Node\Name|string $name Name of the function to alias - * - * @return Builder\Use_ The created use function builder - */ - public function useFunction($name) : Builder\Use_ { - return new Builder\Use_($name, Use_::TYPE_FUNCTION); - } - - /** - * Creates a constant use builder. - * - * @param Node\Name|string $name Name of the const to alias - * - * @return Builder\Use_ The created use const builder - */ - public function useConst($name) : Builder\Use_ { - return new Builder\Use_($name, Use_::TYPE_CONSTANT); - } - - /** - * Creates a class constant builder. - * - * @param string|Identifier $name Name - * @param Node\Expr|bool|null|int|float|string|array $value Value - * - * @return Builder\ClassConst The created use const builder - */ - public function classConst($name, $value) : Builder\ClassConst { - return new Builder\ClassConst($name, $value); - } - - /** - * Creates an enum case builder. - * - * @param string|Identifier $name Name - * - * @return Builder\EnumCase The created use const builder - */ - public function enumCase($name) : Builder\EnumCase { - return new Builder\EnumCase($name); - } - - /** - * Creates node a for a literal value. - * - * @param Expr|bool|null|int|float|string|array $value $value - * - * @return Expr - */ - public function val($value) : Expr { - return BuilderHelpers::normalizeValue($value); - } - - /** - * Creates variable node. - * - * @param string|Expr $name Name - * - * @return Expr\Variable - */ - public function var($name) : Expr\Variable { - if (!\is_string($name) && !$name instanceof Expr) { - throw new \LogicException('Variable name must be string or Expr'); - } - - return new Expr\Variable($name); - } - - /** - * Normalizes an argument list. - * - * Creates Arg nodes for all arguments and converts literal values to expressions. - * - * @param array $args List of arguments to normalize - * - * @return Arg[] - */ - public function args(array $args) : array { - $normalizedArgs = []; - foreach ($args as $key => $arg) { - if (!($arg instanceof Arg)) { - $arg = new Arg(BuilderHelpers::normalizeValue($arg)); - } - if (\is_string($key)) { - $arg->name = BuilderHelpers::normalizeIdentifier($key); - } - $normalizedArgs[] = $arg; - } - return $normalizedArgs; - } - - /** - * Creates a function call node. - * - * @param string|Name|Expr $name Function name - * @param array $args Function arguments - * - * @return Expr\FuncCall - */ - public function funcCall($name, array $args = []) : Expr\FuncCall { - return new Expr\FuncCall( - BuilderHelpers::normalizeNameOrExpr($name), - $this->args($args) - ); - } - - /** - * Creates a method call node. - * - * @param Expr $var Variable the method is called on - * @param string|Identifier|Expr $name Method name - * @param array $args Method arguments - * - * @return Expr\MethodCall - */ - public function methodCall(Expr $var, $name, array $args = []) : Expr\MethodCall { - return new Expr\MethodCall( - $var, - BuilderHelpers::normalizeIdentifierOrExpr($name), - $this->args($args) - ); - } - - /** - * Creates a static method call node. - * - * @param string|Name|Expr $class Class name - * @param string|Identifier|Expr $name Method name - * @param array $args Method arguments - * - * @return Expr\StaticCall - */ - public function staticCall($class, $name, array $args = []) : Expr\StaticCall { - return new Expr\StaticCall( - BuilderHelpers::normalizeNameOrExpr($class), - BuilderHelpers::normalizeIdentifierOrExpr($name), - $this->args($args) - ); - } - - /** - * Creates an object creation node. - * - * @param string|Name|Expr $class Class name - * @param array $args Constructor arguments - * - * @return Expr\New_ - */ - public function new($class, array $args = []) : Expr\New_ { - return new Expr\New_( - BuilderHelpers::normalizeNameOrExpr($class), - $this->args($args) - ); - } - - /** - * Creates a constant fetch node. - * - * @param string|Name $name Constant name - * - * @return Expr\ConstFetch - */ - public function constFetch($name) : Expr\ConstFetch { - return new Expr\ConstFetch(BuilderHelpers::normalizeName($name)); - } - - /** - * Creates a property fetch node. - * - * @param Expr $var Variable holding object - * @param string|Identifier|Expr $name Property name - * - * @return Expr\PropertyFetch - */ - public function propertyFetch(Expr $var, $name) : Expr\PropertyFetch { - return new Expr\PropertyFetch($var, BuilderHelpers::normalizeIdentifierOrExpr($name)); - } - - /** - * Creates a class constant fetch node. - * - * @param string|Name|Expr $class Class name - * @param string|Identifier $name Constant name - * - * @return Expr\ClassConstFetch - */ - public function classConstFetch($class, $name): Expr\ClassConstFetch { - return new Expr\ClassConstFetch( - BuilderHelpers::normalizeNameOrExpr($class), - BuilderHelpers::normalizeIdentifier($name) - ); - } - - /** - * Creates nested Concat nodes from a list of expressions. - * - * @param Expr|string ...$exprs Expressions or literal strings - * - * @return Concat - */ - public function concat(...$exprs) : Concat { - $numExprs = count($exprs); - if ($numExprs < 2) { - throw new \LogicException('Expected at least two expressions'); - } - - $lastConcat = $this->normalizeStringExpr($exprs[0]); - for ($i = 1; $i < $numExprs; $i++) { - $lastConcat = new Concat($lastConcat, $this->normalizeStringExpr($exprs[$i])); - } - return $lastConcat; - } - - /** - * @param string|Expr $expr - * @return Expr - */ - private function normalizeStringExpr($expr) : Expr { - if ($expr instanceof Expr) { - return $expr; - } - - if (\is_string($expr)) { - return new String_($expr); - } - - throw new \LogicException('Expected string or Expr'); - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/BuilderHelpers.php b/lib/nikic/php-parser/lib/PhpParser/BuilderHelpers.php deleted file mode 100644 index b8839db32..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/BuilderHelpers.php +++ /dev/null @@ -1,322 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser; - -use PhpParser\Node\ComplexType; -use PhpParser\Node\Expr; -use PhpParser\Node\Identifier; -use PhpParser\Node\Name; -use PhpParser\Node\NullableType; -use PhpParser\Node\Scalar; -use PhpParser\Node\Stmt; - -/** - * This class defines helpers used in the implementation of builders. Don't use it directly. - * - * @internal - */ -final class BuilderHelpers -{ - /** - * Normalizes a node: Converts builder objects to nodes. - * - * @param Node|Builder $node The node to normalize - * - * @return Node The normalized node - */ - public static function normalizeNode($node) : Node { - if ($node instanceof Builder) { - return $node->getNode(); - } - - if ($node instanceof Node) { - return $node; - } - - throw new \LogicException('Expected node or builder object'); - } - - /** - * Normalizes a node to a statement. - * - * Expressions are wrapped in a Stmt\Expression node. - * - * @param Node|Builder $node The node to normalize - * - * @return Stmt The normalized statement node - */ - public static function normalizeStmt($node) : Stmt { - $node = self::normalizeNode($node); - if ($node instanceof Stmt) { - return $node; - } - - if ($node instanceof Expr) { - return new Stmt\Expression($node); - } - - throw new \LogicException('Expected statement or expression node'); - } - - /** - * Normalizes strings to Identifier. - * - * @param string|Identifier $name The identifier to normalize - * - * @return Identifier The normalized identifier - */ - public static function normalizeIdentifier($name) : Identifier { - if ($name instanceof Identifier) { - return $name; - } - - if (\is_string($name)) { - return new Identifier($name); - } - - throw new \LogicException('Expected string or instance of Node\Identifier'); - } - - /** - * Normalizes strings to Identifier, also allowing expressions. - * - * @param string|Identifier|Expr $name The identifier to normalize - * - * @return Identifier|Expr The normalized identifier or expression - */ - public static function normalizeIdentifierOrExpr($name) { - if ($name instanceof Identifier || $name instanceof Expr) { - return $name; - } - - if (\is_string($name)) { - return new Identifier($name); - } - - throw new \LogicException('Expected string or instance of Node\Identifier or Node\Expr'); - } - - /** - * Normalizes a name: Converts string names to Name nodes. - * - * @param Name|string $name The name to normalize - * - * @return Name The normalized name - */ - public static function normalizeName($name) : Name { - if ($name instanceof Name) { - return $name; - } - - if (is_string($name)) { - if (!$name) { - throw new \LogicException('Name cannot be empty'); - } - - if ($name[0] === '\\') { - return new Name\FullyQualified(substr($name, 1)); - } - - if (0 === strpos($name, 'namespace\\')) { - return new Name\Relative(substr($name, strlen('namespace\\'))); - } - - return new Name($name); - } - - throw new \LogicException('Name must be a string or an instance of Node\Name'); - } - - /** - * Normalizes a name: Converts string names to Name nodes, while also allowing expressions. - * - * @param Expr|Name|string $name The name to normalize - * - * @return Name|Expr The normalized name or expression - */ - public static function normalizeNameOrExpr($name) { - if ($name instanceof Expr) { - return $name; - } - - if (!is_string($name) && !($name instanceof Name)) { - throw new \LogicException( - 'Name must be a string or an instance of Node\Name or Node\Expr' - ); - } - - return self::normalizeName($name); - } - - /** - * Normalizes a type: Converts plain-text type names into proper AST representation. - * - * In particular, builtin types become Identifiers, custom types become Names and nullables - * are wrapped in NullableType nodes. - * - * @param string|Name|Identifier|ComplexType $type The type to normalize - * - * @return Name|Identifier|ComplexType The normalized type - */ - public static function normalizeType($type) { - if (!is_string($type)) { - if ( - !$type instanceof Name && !$type instanceof Identifier && - !$type instanceof ComplexType - ) { - throw new \LogicException( - 'Type must be a string, or an instance of Name, Identifier or ComplexType' - ); - } - return $type; - } - - $nullable = false; - if (strlen($type) > 0 && $type[0] === '?') { - $nullable = true; - $type = substr($type, 1); - } - - $builtinTypes = [ - 'array', 'callable', 'string', 'int', 'float', 'bool', 'iterable', 'void', 'object', 'mixed', 'never', - ]; - - $lowerType = strtolower($type); - if (in_array($lowerType, $builtinTypes)) { - $type = new Identifier($lowerType); - } else { - $type = self::normalizeName($type); - } - - $notNullableTypes = [ - 'void', 'mixed', 'never', - ]; - if ($nullable && in_array((string) $type, $notNullableTypes)) { - throw new \LogicException(sprintf('%s type cannot be nullable', $type)); - } - - return $nullable ? new NullableType($type) : $type; - } - - /** - * Normalizes a value: Converts nulls, booleans, integers, - * floats, strings and arrays into their respective nodes - * - * @param Node\Expr|bool|null|int|float|string|array $value The value to normalize - * - * @return Expr The normalized value - */ - public static function normalizeValue($value) : Expr { - if ($value instanceof Node\Expr) { - return $value; - } - - if (is_null($value)) { - return new Expr\ConstFetch( - new Name('null') - ); - } - - if (is_bool($value)) { - return new Expr\ConstFetch( - new Name($value ? 'true' : 'false') - ); - } - - if (is_int($value)) { - return new Scalar\LNumber($value); - } - - if (is_float($value)) { - return new Scalar\DNumber($value); - } - - if (is_string($value)) { - return new Scalar\String_($value); - } - - if (is_array($value)) { - $items = []; - $lastKey = -1; - foreach ($value as $itemKey => $itemValue) { - // for consecutive, numeric keys don't generate keys - if (null !== $lastKey && ++$lastKey === $itemKey) { - $items[] = new Expr\ArrayItem( - self::normalizeValue($itemValue) - ); - } else { - $lastKey = null; - $items[] = new Expr\ArrayItem( - self::normalizeValue($itemValue), - self::normalizeValue($itemKey) - ); - } - } - - return new Expr\Array_($items); - } - - throw new \LogicException('Invalid value'); - } - - /** - * Normalizes a doc comment: Converts plain strings to PhpParser\Comment\Doc. - * - * @param Comment\Doc|string $docComment The doc comment to normalize - * - * @return Comment\Doc The normalized doc comment - */ - public static function normalizeDocComment($docComment) : Comment\Doc { - if ($docComment instanceof Comment\Doc) { - return $docComment; - } - - if (is_string($docComment)) { - return new Comment\Doc($docComment); - } - - throw new \LogicException('Doc comment must be a string or an instance of PhpParser\Comment\Doc'); - } - - /** - * Normalizes a attribute: Converts attribute to the Attribute Group if needed. - * - * @param Node\Attribute|Node\AttributeGroup $attribute - * - * @return Node\AttributeGroup The Attribute Group - */ - public static function normalizeAttribute($attribute) : Node\AttributeGroup - { - if ($attribute instanceof Node\AttributeGroup) { - return $attribute; - } - - if (!($attribute instanceof Node\Attribute)) { - throw new \LogicException('Attribute must be an instance of PhpParser\Node\Attribute or PhpParser\Node\AttributeGroup'); - } - - return new Node\AttributeGroup([$attribute]); - } - - /** - * Adds a modifier and returns new modifier bitmask. - * - * @param int $modifiers Existing modifiers - * @param int $modifier Modifier to set - * - * @return int New modifiers - */ - public static function addModifier(int $modifiers, int $modifier) : int { - Stmt\Class_::verifyModifier($modifiers, $modifier); - return $modifiers | $modifier; - } - - /** - * Adds a modifier and returns new modifier bitmask. - * @return int New modifiers - */ - public static function addClassModifier(int $existingModifiers, int $modifierToSet) : int { - Stmt\Class_::verifyClassModifier($existingModifiers, $modifierToSet); - return $existingModifiers | $modifierToSet; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Comment.php b/lib/nikic/php-parser/lib/PhpParser/Comment.php deleted file mode 100644 index 61e98d3dc..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Comment.php +++ /dev/null @@ -1,239 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser; - -class Comment implements \JsonSerializable -{ - protected $text; - protected $startLine; - protected $startFilePos; - protected $startTokenPos; - protected $endLine; - protected $endFilePos; - protected $endTokenPos; - - /** - * Constructs a comment node. - * - * @param string $text Comment text (including comment delimiters like /*) - * @param int $startLine Line number the comment started on - * @param int $startFilePos File offset the comment started on - * @param int $startTokenPos Token offset the comment started on - */ - public function __construct( - string $text, - int $startLine = -1, int $startFilePos = -1, int $startTokenPos = -1, - int $endLine = -1, int $endFilePos = -1, int $endTokenPos = -1 - ) { - $this->text = $text; - $this->startLine = $startLine; - $this->startFilePos = $startFilePos; - $this->startTokenPos = $startTokenPos; - $this->endLine = $endLine; - $this->endFilePos = $endFilePos; - $this->endTokenPos = $endTokenPos; - } - - /** - * Gets the comment text. - * - * @return string The comment text (including comment delimiters like /*) - */ - public function getText() : string { - return $this->text; - } - - /** - * Gets the line number the comment started on. - * - * @return int Line number (or -1 if not available) - */ - public function getStartLine() : int { - return $this->startLine; - } - - /** - * Gets the file offset the comment started on. - * - * @return int File offset (or -1 if not available) - */ - public function getStartFilePos() : int { - return $this->startFilePos; - } - - /** - * Gets the token offset the comment started on. - * - * @return int Token offset (or -1 if not available) - */ - public function getStartTokenPos() : int { - return $this->startTokenPos; - } - - /** - * Gets the line number the comment ends on. - * - * @return int Line number (or -1 if not available) - */ - public function getEndLine() : int { - return $this->endLine; - } - - /** - * Gets the file offset the comment ends on. - * - * @return int File offset (or -1 if not available) - */ - public function getEndFilePos() : int { - return $this->endFilePos; - } - - /** - * Gets the token offset the comment ends on. - * - * @return int Token offset (or -1 if not available) - */ - public function getEndTokenPos() : int { - return $this->endTokenPos; - } - - /** - * Gets the line number the comment started on. - * - * @deprecated Use getStartLine() instead - * - * @return int Line number - */ - public function getLine() : int { - return $this->startLine; - } - - /** - * Gets the file offset the comment started on. - * - * @deprecated Use getStartFilePos() instead - * - * @return int File offset - */ - public function getFilePos() : int { - return $this->startFilePos; - } - - /** - * Gets the token offset the comment started on. - * - * @deprecated Use getStartTokenPos() instead - * - * @return int Token offset - */ - public function getTokenPos() : int { - return $this->startTokenPos; - } - - /** - * Gets the comment text. - * - * @return string The comment text (including comment delimiters like /*) - */ - public function __toString() : string { - return $this->text; - } - - /** - * Gets the reformatted comment text. - * - * "Reformatted" here means that we try to clean up the whitespace at the - * starts of the lines. This is necessary because we receive the comments - * without trailing whitespace on the first line, but with trailing whitespace - * on all subsequent lines. - * - * @return mixed|string - */ - public function getReformattedText() { - $text = trim($this->text); - $newlinePos = strpos($text, "\n"); - if (false === $newlinePos) { - // Single line comments don't need further processing - return $text; - } elseif (preg_match('((*BSR_ANYCRLF)(*ANYCRLF)^.*(?:\R\s+\*.*)+$)', $text)) { - // Multi line comment of the type - // - // /* - // * Some text. - // * Some more text. - // */ - // - // is handled by replacing the whitespace sequences before the * by a single space - return preg_replace('(^\s+\*)m', ' *', $this->text); - } elseif (preg_match('(^/\*\*?\s*[\r\n])', $text) && preg_match('(\n(\s*)\*/$)', $text, $matches)) { - // Multi line comment of the type - // - // /* - // Some text. - // Some more text. - // */ - // - // is handled by removing the whitespace sequence on the line before the closing - // */ on all lines. So if the last line is " */", then " " is removed at the - // start of all lines. - return preg_replace('(^' . preg_quote($matches[1]) . ')m', '', $text); - } elseif (preg_match('(^/\*\*?\s*(?!\s))', $text, $matches)) { - // Multi line comment of the type - // - // /* Some text. - // Some more text. - // Indented text. - // Even more text. */ - // - // is handled by removing the difference between the shortest whitespace prefix on all - // lines and the length of the "/* " opening sequence. - $prefixLen = $this->getShortestWhitespacePrefixLen(substr($text, $newlinePos + 1)); - $removeLen = $prefixLen - strlen($matches[0]); - return preg_replace('(^\s{' . $removeLen . '})m', '', $text); - } - - // No idea how to format this comment, so simply return as is - return $text; - } - - /** - * Get length of shortest whitespace prefix (at the start of a line). - * - * If there is a line with no prefix whitespace, 0 is a valid return value. - * - * @param string $str String to check - * @return int Length in characters. Tabs count as single characters. - */ - private function getShortestWhitespacePrefixLen(string $str) : int { - $lines = explode("\n", $str); - $shortestPrefixLen = \INF; - foreach ($lines as $line) { - preg_match('(^\s*)', $line, $matches); - $prefixLen = strlen($matches[0]); - if ($prefixLen < $shortestPrefixLen) { - $shortestPrefixLen = $prefixLen; - } - } - return $shortestPrefixLen; - } - - /** - * @return array - * @psalm-return array{nodeType:string, text:mixed, line:mixed, filePos:mixed} - */ - public function jsonSerialize() : array { - // Technically not a node, but we make it look like one anyway - $type = $this instanceof Comment\Doc ? 'Comment_Doc' : 'Comment'; - return [ - 'nodeType' => $type, - 'text' => $this->text, - // TODO: Rename these to include "start". - 'line' => $this->startLine, - 'filePos' => $this->startFilePos, - 'tokenPos' => $this->startTokenPos, - 'endLine' => $this->endLine, - 'endFilePos' => $this->endFilePos, - 'endTokenPos' => $this->endTokenPos, - ]; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Comment/Doc.php b/lib/nikic/php-parser/lib/PhpParser/Comment/Doc.php deleted file mode 100644 index a9db6128f..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Comment/Doc.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Comment; - -class Doc extends \PhpParser\Comment -{ -} diff --git a/lib/nikic/php-parser/lib/PhpParser/ConstExprEvaluationException.php b/lib/nikic/php-parser/lib/PhpParser/ConstExprEvaluationException.php deleted file mode 100644 index 49c92d595..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/ConstExprEvaluationException.php +++ /dev/null @@ -1,6 +0,0 @@ -<?php - -namespace PhpParser; - -class ConstExprEvaluationException extends \Exception -{} diff --git a/lib/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.php b/lib/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.php deleted file mode 100644 index 7131c3d25..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.php +++ /dev/null @@ -1,229 +0,0 @@ -<?php - -namespace PhpParser; - -use function array_merge; -use PhpParser\Node\Expr; -use PhpParser\Node\Scalar; - -/** - * Evaluates constant expressions. - * - * This evaluator is able to evaluate all constant expressions (as defined by PHP), which can be - * evaluated without further context. If a subexpression is not of this type, a user-provided - * fallback evaluator is invoked. To support all constant expressions that are also supported by - * PHP (and not already handled by this class), the fallback evaluator must be able to handle the - * following node types: - * - * * All Scalar\MagicConst\* nodes. - * * Expr\ConstFetch nodes. Only null/false/true are already handled by this class. - * * Expr\ClassConstFetch nodes. - * - * The fallback evaluator should throw ConstExprEvaluationException for nodes it cannot evaluate. - * - * The evaluation is dependent on runtime configuration in two respects: Firstly, floating - * point to string conversions are affected by the precision ini setting. Secondly, they are also - * affected by the LC_NUMERIC locale. - */ -class ConstExprEvaluator -{ - private $fallbackEvaluator; - - /** - * Create a constant expression evaluator. - * - * The provided fallback evaluator is invoked whenever a subexpression cannot be evaluated. See - * class doc comment for more information. - * - * @param callable|null $fallbackEvaluator To call if subexpression cannot be evaluated - */ - public function __construct(callable $fallbackEvaluator = null) { - $this->fallbackEvaluator = $fallbackEvaluator ?? function(Expr $expr) { - throw new ConstExprEvaluationException( - "Expression of type {$expr->getType()} cannot be evaluated" - ); - }; - } - - /** - * Silently evaluates a constant expression into a PHP value. - * - * Thrown Errors, warnings or notices will be converted into a ConstExprEvaluationException. - * The original source of the exception is available through getPrevious(). - * - * If some part of the expression cannot be evaluated, the fallback evaluator passed to the - * constructor will be invoked. By default, if no fallback is provided, an exception of type - * ConstExprEvaluationException is thrown. - * - * See class doc comment for caveats and limitations. - * - * @param Expr $expr Constant expression to evaluate - * @return mixed Result of evaluation - * - * @throws ConstExprEvaluationException if the expression cannot be evaluated or an error occurred - */ - public function evaluateSilently(Expr $expr) { - set_error_handler(function($num, $str, $file, $line) { - throw new \ErrorException($str, 0, $num, $file, $line); - }); - - try { - return $this->evaluate($expr); - } catch (\Throwable $e) { - if (!$e instanceof ConstExprEvaluationException) { - $e = new ConstExprEvaluationException( - "An error occurred during constant expression evaluation", 0, $e); - } - throw $e; - } finally { - restore_error_handler(); - } - } - - /** - * Directly evaluates a constant expression into a PHP value. - * - * May generate Error exceptions, warnings or notices. Use evaluateSilently() to convert these - * into a ConstExprEvaluationException. - * - * If some part of the expression cannot be evaluated, the fallback evaluator passed to the - * constructor will be invoked. By default, if no fallback is provided, an exception of type - * ConstExprEvaluationException is thrown. - * - * See class doc comment for caveats and limitations. - * - * @param Expr $expr Constant expression to evaluate - * @return mixed Result of evaluation - * - * @throws ConstExprEvaluationException if the expression cannot be evaluated - */ - public function evaluateDirectly(Expr $expr) { - return $this->evaluate($expr); - } - - private function evaluate(Expr $expr) { - if ($expr instanceof Scalar\LNumber - || $expr instanceof Scalar\DNumber - || $expr instanceof Scalar\String_ - ) { - return $expr->value; - } - - if ($expr instanceof Expr\Array_) { - return $this->evaluateArray($expr); - } - - // Unary operators - if ($expr instanceof Expr\UnaryPlus) { - return +$this->evaluate($expr->expr); - } - if ($expr instanceof Expr\UnaryMinus) { - return -$this->evaluate($expr->expr); - } - if ($expr instanceof Expr\BooleanNot) { - return !$this->evaluate($expr->expr); - } - if ($expr instanceof Expr\BitwiseNot) { - return ~$this->evaluate($expr->expr); - } - - if ($expr instanceof Expr\BinaryOp) { - return $this->evaluateBinaryOp($expr); - } - - if ($expr instanceof Expr\Ternary) { - return $this->evaluateTernary($expr); - } - - if ($expr instanceof Expr\ArrayDimFetch && null !== $expr->dim) { - return $this->evaluate($expr->var)[$this->evaluate($expr->dim)]; - } - - if ($expr instanceof Expr\ConstFetch) { - return $this->evaluateConstFetch($expr); - } - - return ($this->fallbackEvaluator)($expr); - } - - private function evaluateArray(Expr\Array_ $expr) { - $array = []; - foreach ($expr->items as $item) { - if (null !== $item->key) { - $array[$this->evaluate($item->key)] = $this->evaluate($item->value); - } elseif ($item->unpack) { - $array = array_merge($array, $this->evaluate($item->value)); - } else { - $array[] = $this->evaluate($item->value); - } - } - return $array; - } - - private function evaluateTernary(Expr\Ternary $expr) { - if (null === $expr->if) { - return $this->evaluate($expr->cond) ?: $this->evaluate($expr->else); - } - - return $this->evaluate($expr->cond) - ? $this->evaluate($expr->if) - : $this->evaluate($expr->else); - } - - private function evaluateBinaryOp(Expr\BinaryOp $expr) { - if ($expr instanceof Expr\BinaryOp\Coalesce - && $expr->left instanceof Expr\ArrayDimFetch - ) { - // This needs to be special cased to respect BP_VAR_IS fetch semantics - return $this->evaluate($expr->left->var)[$this->evaluate($expr->left->dim)] - ?? $this->evaluate($expr->right); - } - - // The evaluate() calls are repeated in each branch, because some of the operators are - // short-circuiting and evaluating the RHS in advance may be illegal in that case - $l = $expr->left; - $r = $expr->right; - switch ($expr->getOperatorSigil()) { - case '&': return $this->evaluate($l) & $this->evaluate($r); - case '|': return $this->evaluate($l) | $this->evaluate($r); - case '^': return $this->evaluate($l) ^ $this->evaluate($r); - case '&&': return $this->evaluate($l) && $this->evaluate($r); - case '||': return $this->evaluate($l) || $this->evaluate($r); - case '??': return $this->evaluate($l) ?? $this->evaluate($r); - case '.': return $this->evaluate($l) . $this->evaluate($r); - case '/': return $this->evaluate($l) / $this->evaluate($r); - case '==': return $this->evaluate($l) == $this->evaluate($r); - case '>': return $this->evaluate($l) > $this->evaluate($r); - case '>=': return $this->evaluate($l) >= $this->evaluate($r); - case '===': return $this->evaluate($l) === $this->evaluate($r); - case 'and': return $this->evaluate($l) and $this->evaluate($r); - case 'or': return $this->evaluate($l) or $this->evaluate($r); - case 'xor': return $this->evaluate($l) xor $this->evaluate($r); - case '-': return $this->evaluate($l) - $this->evaluate($r); - case '%': return $this->evaluate($l) % $this->evaluate($r); - case '*': return $this->evaluate($l) * $this->evaluate($r); - case '!=': return $this->evaluate($l) != $this->evaluate($r); - case '!==': return $this->evaluate($l) !== $this->evaluate($r); - case '+': return $this->evaluate($l) + $this->evaluate($r); - case '**': return $this->evaluate($l) ** $this->evaluate($r); - case '<<': return $this->evaluate($l) << $this->evaluate($r); - case '>>': return $this->evaluate($l) >> $this->evaluate($r); - case '<': return $this->evaluate($l) < $this->evaluate($r); - case '<=': return $this->evaluate($l) <= $this->evaluate($r); - case '<=>': return $this->evaluate($l) <=> $this->evaluate($r); - } - - throw new \Exception('Should not happen'); - } - - private function evaluateConstFetch(Expr\ConstFetch $expr) { - $name = $expr->name->toLowerString(); - switch ($name) { - case 'null': return null; - case 'false': return false; - case 'true': return true; - } - - return ($this->fallbackEvaluator)($expr); - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Error.php b/lib/nikic/php-parser/lib/PhpParser/Error.php deleted file mode 100644 index d1fb959d1..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Error.php +++ /dev/null @@ -1,180 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser; - -class Error extends \RuntimeException -{ - protected $rawMessage; - protected $attributes; - - /** - * Creates an Exception signifying a parse error. - * - * @param string $message Error message - * @param array|int $attributes Attributes of node/token where error occurred - * (or start line of error -- deprecated) - */ - public function __construct(string $message, $attributes = []) { - $this->rawMessage = $message; - if (is_array($attributes)) { - $this->attributes = $attributes; - } else { - $this->attributes = ['startLine' => $attributes]; - } - $this->updateMessage(); - } - - /** - * Gets the error message - * - * @return string Error message - */ - public function getRawMessage() : string { - return $this->rawMessage; - } - - /** - * Gets the line the error starts in. - * - * @return int Error start line - */ - public function getStartLine() : int { - return $this->attributes['startLine'] ?? -1; - } - - /** - * Gets the line the error ends in. - * - * @return int Error end line - */ - public function getEndLine() : int { - return $this->attributes['endLine'] ?? -1; - } - - /** - * Gets the attributes of the node/token the error occurred at. - * - * @return array - */ - public function getAttributes() : array { - return $this->attributes; - } - - /** - * Sets the attributes of the node/token the error occurred at. - * - * @param array $attributes - */ - public function setAttributes(array $attributes) { - $this->attributes = $attributes; - $this->updateMessage(); - } - - /** - * Sets the line of the PHP file the error occurred in. - * - * @param string $message Error message - */ - public function setRawMessage(string $message) { - $this->rawMessage = $message; - $this->updateMessage(); - } - - /** - * Sets the line the error starts in. - * - * @param int $line Error start line - */ - public function setStartLine(int $line) { - $this->attributes['startLine'] = $line; - $this->updateMessage(); - } - - /** - * Returns whether the error has start and end column information. - * - * For column information enable the startFilePos and endFilePos in the lexer options. - * - * @return bool - */ - public function hasColumnInfo() : bool { - return isset($this->attributes['startFilePos'], $this->attributes['endFilePos']); - } - - /** - * Gets the start column (1-based) into the line where the error started. - * - * @param string $code Source code of the file - * @return int - */ - public function getStartColumn(string $code) : int { - if (!$this->hasColumnInfo()) { - throw new \RuntimeException('Error does not have column information'); - } - - return $this->toColumn($code, $this->attributes['startFilePos']); - } - - /** - * Gets the end column (1-based) into the line where the error ended. - * - * @param string $code Source code of the file - * @return int - */ - public function getEndColumn(string $code) : int { - if (!$this->hasColumnInfo()) { - throw new \RuntimeException('Error does not have column information'); - } - - return $this->toColumn($code, $this->attributes['endFilePos']); - } - - /** - * Formats message including line and column information. - * - * @param string $code Source code associated with the error, for calculation of the columns - * - * @return string Formatted message - */ - public function getMessageWithColumnInfo(string $code) : string { - return sprintf( - '%s from %d:%d to %d:%d', $this->getRawMessage(), - $this->getStartLine(), $this->getStartColumn($code), - $this->getEndLine(), $this->getEndColumn($code) - ); - } - - /** - * Converts a file offset into a column. - * - * @param string $code Source code that $pos indexes into - * @param int $pos 0-based position in $code - * - * @return int 1-based column (relative to start of line) - */ - private function toColumn(string $code, int $pos) : int { - if ($pos > strlen($code)) { - throw new \RuntimeException('Invalid position information'); - } - - $lineStartPos = strrpos($code, "\n", $pos - strlen($code)); - if (false === $lineStartPos) { - $lineStartPos = -1; - } - - return $pos - $lineStartPos; - } - - /** - * Updates the exception message after a change to rawMessage or rawLine. - */ - protected function updateMessage() { - $this->message = $this->rawMessage; - - if (-1 === $this->getStartLine()) { - $this->message .= ' on unknown line'; - } else { - $this->message .= ' on line ' . $this->getStartLine(); - } - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/ErrorHandler.php b/lib/nikic/php-parser/lib/PhpParser/ErrorHandler.php deleted file mode 100644 index d620e7453..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/ErrorHandler.php +++ /dev/null @@ -1,13 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser; - -interface ErrorHandler -{ - /** - * Handle an error generated during lexing, parsing or some other operation. - * - * @param Error $error The error that needs to be handled - */ - public function handleError(Error $error); -} diff --git a/lib/nikic/php-parser/lib/PhpParser/ErrorHandler/Collecting.php b/lib/nikic/php-parser/lib/PhpParser/ErrorHandler/Collecting.php deleted file mode 100644 index 784b61b14..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/ErrorHandler/Collecting.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\ErrorHandler; - -use PhpParser\Error; -use PhpParser\ErrorHandler; - -/** - * Error handler that collects all errors into an array. - * - * This allows graceful handling of errors. - */ -class Collecting implements ErrorHandler -{ - /** @var Error[] Collected errors */ - private $errors = []; - - public function handleError(Error $error) { - $this->errors[] = $error; - } - - /** - * Get collected errors. - * - * @return Error[] - */ - public function getErrors() : array { - return $this->errors; - } - - /** - * Check whether there are any errors. - * - * @return bool - */ - public function hasErrors() : bool { - return !empty($this->errors); - } - - /** - * Reset/clear collected errors. - */ - public function clearErrors() { - $this->errors = []; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php b/lib/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php deleted file mode 100644 index aeee989b1..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\ErrorHandler; - -use PhpParser\Error; -use PhpParser\ErrorHandler; - -/** - * Error handler that handles all errors by throwing them. - * - * This is the default strategy used by all components. - */ -class Throwing implements ErrorHandler -{ - public function handleError(Error $error) { - throw $error; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Internal/DiffElem.php b/lib/nikic/php-parser/lib/PhpParser/Internal/DiffElem.php deleted file mode 100644 index a38b57ba9..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Internal/DiffElem.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Internal; - -/** - * @internal - */ -class DiffElem -{ - const TYPE_KEEP = 0; - const TYPE_REMOVE = 1; - const TYPE_ADD = 2; - const TYPE_REPLACE = 3; - - /** @var int One of the TYPE_* constants */ - public $type; - /** @var mixed Is null for add operations */ - public $old; - /** @var mixed Is null for remove operations */ - public $new; - - public function __construct(int $type, $old, $new) { - $this->type = $type; - $this->old = $old; - $this->new = $new; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Internal/Differ.php b/lib/nikic/php-parser/lib/PhpParser/Internal/Differ.php deleted file mode 100644 index 7f218c74f..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Internal/Differ.php +++ /dev/null @@ -1,164 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Internal; - -/** - * Implements the Myers diff algorithm. - * - * Myers, Eugene W. "An O (ND) difference algorithm and its variations." - * Algorithmica 1.1 (1986): 251-266. - * - * @internal - */ -class Differ -{ - private $isEqual; - - /** - * Create differ over the given equality relation. - * - * @param callable $isEqual Equality relation with signature function($a, $b) : bool - */ - public function __construct(callable $isEqual) { - $this->isEqual = $isEqual; - } - - /** - * Calculate diff (edit script) from $old to $new. - * - * @param array $old Original array - * @param array $new New array - * - * @return DiffElem[] Diff (edit script) - */ - public function diff(array $old, array $new) { - list($trace, $x, $y) = $this->calculateTrace($old, $new); - return $this->extractDiff($trace, $x, $y, $old, $new); - } - - /** - * Calculate diff, including "replace" operations. - * - * If a sequence of remove operations is followed by the same number of add operations, these - * will be coalesced into replace operations. - * - * @param array $old Original array - * @param array $new New array - * - * @return DiffElem[] Diff (edit script), including replace operations - */ - public function diffWithReplacements(array $old, array $new) { - return $this->coalesceReplacements($this->diff($old, $new)); - } - - private function calculateTrace(array $a, array $b) { - $n = \count($a); - $m = \count($b); - $max = $n + $m; - $v = [1 => 0]; - $trace = []; - for ($d = 0; $d <= $max; $d++) { - $trace[] = $v; - for ($k = -$d; $k <= $d; $k += 2) { - if ($k === -$d || ($k !== $d && $v[$k-1] < $v[$k+1])) { - $x = $v[$k+1]; - } else { - $x = $v[$k-1] + 1; - } - - $y = $x - $k; - while ($x < $n && $y < $m && ($this->isEqual)($a[$x], $b[$y])) { - $x++; - $y++; - } - - $v[$k] = $x; - if ($x >= $n && $y >= $m) { - return [$trace, $x, $y]; - } - } - } - throw new \Exception('Should not happen'); - } - - private function extractDiff(array $trace, int $x, int $y, array $a, array $b) { - $result = []; - for ($d = \count($trace) - 1; $d >= 0; $d--) { - $v = $trace[$d]; - $k = $x - $y; - - if ($k === -$d || ($k !== $d && $v[$k-1] < $v[$k+1])) { - $prevK = $k + 1; - } else { - $prevK = $k - 1; - } - - $prevX = $v[$prevK]; - $prevY = $prevX - $prevK; - - while ($x > $prevX && $y > $prevY) { - $result[] = new DiffElem(DiffElem::TYPE_KEEP, $a[$x-1], $b[$y-1]); - $x--; - $y--; - } - - if ($d === 0) { - break; - } - - while ($x > $prevX) { - $result[] = new DiffElem(DiffElem::TYPE_REMOVE, $a[$x-1], null); - $x--; - } - - while ($y > $prevY) { - $result[] = new DiffElem(DiffElem::TYPE_ADD, null, $b[$y-1]); - $y--; - } - } - return array_reverse($result); - } - - /** - * Coalesce equal-length sequences of remove+add into a replace operation. - * - * @param DiffElem[] $diff - * @return DiffElem[] - */ - private function coalesceReplacements(array $diff) { - $newDiff = []; - $c = \count($diff); - for ($i = 0; $i < $c; $i++) { - $diffType = $diff[$i]->type; - if ($diffType !== DiffElem::TYPE_REMOVE) { - $newDiff[] = $diff[$i]; - continue; - } - - $j = $i; - while ($j < $c && $diff[$j]->type === DiffElem::TYPE_REMOVE) { - $j++; - } - - $k = $j; - while ($k < $c && $diff[$k]->type === DiffElem::TYPE_ADD) { - $k++; - } - - if ($j - $i === $k - $j) { - $len = $j - $i; - for ($n = 0; $n < $len; $n++) { - $newDiff[] = new DiffElem( - DiffElem::TYPE_REPLACE, $diff[$i + $n]->old, $diff[$j + $n]->new - ); - } - } else { - for (; $i < $k; $i++) { - $newDiff[] = $diff[$i]; - } - } - $i = $k - 1; - } - return $newDiff; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php b/lib/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php deleted file mode 100644 index 3eeac04a4..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php +++ /dev/null @@ -1,61 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Internal; - -use PhpParser\Node; -use PhpParser\Node\Expr; - -/** - * This node is used internally by the format-preserving pretty printer to print anonymous classes. - * - * The normal anonymous class structure violates assumptions about the order of token offsets. - * Namely, the constructor arguments are part of the Expr\New_ node and follow the class node, even - * though they are actually interleaved with them. This special node type is used temporarily to - * restore a sane token offset order. - * - * @internal - */ -class PrintableNewAnonClassNode extends Expr -{ - /** @var Node\AttributeGroup[] PHP attribute groups */ - public $attrGroups; - /** @var Node\Arg[] Arguments */ - public $args; - /** @var null|Node\Name Name of extended class */ - public $extends; - /** @var Node\Name[] Names of implemented interfaces */ - public $implements; - /** @var Node\Stmt[] Statements */ - public $stmts; - - public function __construct( - array $attrGroups, array $args, Node\Name $extends = null, array $implements, - array $stmts, array $attributes - ) { - parent::__construct($attributes); - $this->attrGroups = $attrGroups; - $this->args = $args; - $this->extends = $extends; - $this->implements = $implements; - $this->stmts = $stmts; - } - - public static function fromNewNode(Expr\New_ $newNode) { - $class = $newNode->class; - assert($class instanceof Node\Stmt\Class_); - // We don't assert that $class->name is null here, to allow consumers to assign unique names - // to anonymous classes for their own purposes. We simplify ignore the name here. - return new self( - $class->attrGroups, $newNode->args, $class->extends, $class->implements, - $class->stmts, $newNode->getAttributes() - ); - } - - public function getType() : string { - return 'Expr_PrintableNewAnonClass'; - } - - public function getSubNodeNames() : array { - return ['attrGroups', 'args', 'extends', 'implements', 'stmts']; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php b/lib/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php deleted file mode 100644 index 84c0175ec..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php +++ /dev/null @@ -1,281 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Internal; - -/** - * Provides operations on token streams, for use by pretty printer. - * - * @internal - */ -class TokenStream -{ - /** @var array Tokens (in token_get_all format) */ - private $tokens; - /** @var int[] Map from position to indentation */ - private $indentMap; - - /** - * Create token stream instance. - * - * @param array $tokens Tokens in token_get_all() format - */ - public function __construct(array $tokens) { - $this->tokens = $tokens; - $this->indentMap = $this->calcIndentMap(); - } - - /** - * Whether the given position is immediately surrounded by parenthesis. - * - * @param int $startPos Start position - * @param int $endPos End position - * - * @return bool - */ - public function haveParens(int $startPos, int $endPos) : bool { - return $this->haveTokenImmediatelyBefore($startPos, '(') - && $this->haveTokenImmediatelyAfter($endPos, ')'); - } - - /** - * Whether the given position is immediately surrounded by braces. - * - * @param int $startPos Start position - * @param int $endPos End position - * - * @return bool - */ - public function haveBraces(int $startPos, int $endPos) : bool { - return ($this->haveTokenImmediatelyBefore($startPos, '{') - || $this->haveTokenImmediatelyBefore($startPos, T_CURLY_OPEN)) - && $this->haveTokenImmediatelyAfter($endPos, '}'); - } - - /** - * Check whether the position is directly preceded by a certain token type. - * - * During this check whitespace and comments are skipped. - * - * @param int $pos Position before which the token should occur - * @param int|string $expectedTokenType Token to check for - * - * @return bool Whether the expected token was found - */ - public function haveTokenImmediatelyBefore(int $pos, $expectedTokenType) : bool { - $tokens = $this->tokens; - $pos--; - for (; $pos >= 0; $pos--) { - $tokenType = $tokens[$pos][0]; - if ($tokenType === $expectedTokenType) { - return true; - } - if ($tokenType !== \T_WHITESPACE - && $tokenType !== \T_COMMENT && $tokenType !== \T_DOC_COMMENT) { - break; - } - } - return false; - } - - /** - * Check whether the position is directly followed by a certain token type. - * - * During this check whitespace and comments are skipped. - * - * @param int $pos Position after which the token should occur - * @param int|string $expectedTokenType Token to check for - * - * @return bool Whether the expected token was found - */ - public function haveTokenImmediatelyAfter(int $pos, $expectedTokenType) : bool { - $tokens = $this->tokens; - $pos++; - for (; $pos < \count($tokens); $pos++) { - $tokenType = $tokens[$pos][0]; - if ($tokenType === $expectedTokenType) { - return true; - } - if ($tokenType !== \T_WHITESPACE - && $tokenType !== \T_COMMENT && $tokenType !== \T_DOC_COMMENT) { - break; - } - } - return false; - } - - public function skipLeft(int $pos, $skipTokenType) { - $tokens = $this->tokens; - - $pos = $this->skipLeftWhitespace($pos); - if ($skipTokenType === \T_WHITESPACE) { - return $pos; - } - - if ($tokens[$pos][0] !== $skipTokenType) { - // Shouldn't happen. The skip token MUST be there - throw new \Exception('Encountered unexpected token'); - } - $pos--; - - return $this->skipLeftWhitespace($pos); - } - - public function skipRight(int $pos, $skipTokenType) { - $tokens = $this->tokens; - - $pos = $this->skipRightWhitespace($pos); - if ($skipTokenType === \T_WHITESPACE) { - return $pos; - } - - if ($tokens[$pos][0] !== $skipTokenType) { - // Shouldn't happen. The skip token MUST be there - throw new \Exception('Encountered unexpected token'); - } - $pos++; - - return $this->skipRightWhitespace($pos); - } - - /** - * Return first non-whitespace token position smaller or equal to passed position. - * - * @param int $pos Token position - * @return int Non-whitespace token position - */ - public function skipLeftWhitespace(int $pos) { - $tokens = $this->tokens; - for (; $pos >= 0; $pos--) { - $type = $tokens[$pos][0]; - if ($type !== \T_WHITESPACE && $type !== \T_COMMENT && $type !== \T_DOC_COMMENT) { - break; - } - } - return $pos; - } - - /** - * Return first non-whitespace position greater or equal to passed position. - * - * @param int $pos Token position - * @return int Non-whitespace token position - */ - public function skipRightWhitespace(int $pos) { - $tokens = $this->tokens; - for ($count = \count($tokens); $pos < $count; $pos++) { - $type = $tokens[$pos][0]; - if ($type !== \T_WHITESPACE && $type !== \T_COMMENT && $type !== \T_DOC_COMMENT) { - break; - } - } - return $pos; - } - - public function findRight(int $pos, $findTokenType) { - $tokens = $this->tokens; - for ($count = \count($tokens); $pos < $count; $pos++) { - $type = $tokens[$pos][0]; - if ($type === $findTokenType) { - return $pos; - } - } - return -1; - } - - /** - * Whether the given position range contains a certain token type. - * - * @param int $startPos Starting position (inclusive) - * @param int $endPos Ending position (exclusive) - * @param int|string $tokenType Token type to look for - * @return bool Whether the token occurs in the given range - */ - public function haveTokenInRange(int $startPos, int $endPos, $tokenType) { - $tokens = $this->tokens; - for ($pos = $startPos; $pos < $endPos; $pos++) { - if ($tokens[$pos][0] === $tokenType) { - return true; - } - } - return false; - } - - public function haveBracesInRange(int $startPos, int $endPos) { - return $this->haveTokenInRange($startPos, $endPos, '{') - || $this->haveTokenInRange($startPos, $endPos, T_CURLY_OPEN) - || $this->haveTokenInRange($startPos, $endPos, '}'); - } - - /** - * Get indentation before token position. - * - * @param int $pos Token position - * - * @return int Indentation depth (in spaces) - */ - public function getIndentationBefore(int $pos) : int { - return $this->indentMap[$pos]; - } - - /** - * Get the code corresponding to a token offset range, optionally adjusted for indentation. - * - * @param int $from Token start position (inclusive) - * @param int $to Token end position (exclusive) - * @param int $indent By how much the code should be indented (can be negative as well) - * - * @return string Code corresponding to token range, adjusted for indentation - */ - public function getTokenCode(int $from, int $to, int $indent) : string { - $tokens = $this->tokens; - $result = ''; - for ($pos = $from; $pos < $to; $pos++) { - $token = $tokens[$pos]; - if (\is_array($token)) { - $type = $token[0]; - $content = $token[1]; - if ($type === \T_CONSTANT_ENCAPSED_STRING || $type === \T_ENCAPSED_AND_WHITESPACE) { - $result .= $content; - } else { - // TODO Handle non-space indentation - if ($indent < 0) { - $result .= str_replace("\n" . str_repeat(" ", -$indent), "\n", $content); - } elseif ($indent > 0) { - $result .= str_replace("\n", "\n" . str_repeat(" ", $indent), $content); - } else { - $result .= $content; - } - } - } else { - $result .= $token; - } - } - return $result; - } - - /** - * Precalculate the indentation at every token position. - * - * @return int[] Token position to indentation map - */ - private function calcIndentMap() { - $indentMap = []; - $indent = 0; - foreach ($this->tokens as $token) { - $indentMap[] = $indent; - - if ($token[0] === \T_WHITESPACE) { - $content = $token[1]; - $newlinePos = \strrpos($content, "\n"); - if (false !== $newlinePos) { - $indent = \strlen($content) - $newlinePos - 1; - } - } - } - - // Add a sentinel for one past end of the file - $indentMap[] = $indent; - - return $indentMap; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/JsonDecoder.php b/lib/nikic/php-parser/lib/PhpParser/JsonDecoder.php deleted file mode 100644 index 47d2003d4..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/JsonDecoder.php +++ /dev/null @@ -1,103 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser; - -class JsonDecoder -{ - /** @var \ReflectionClass[] Node type to reflection class map */ - private $reflectionClassCache; - - public function decode(string $json) { - $value = json_decode($json, true); - if (json_last_error()) { - throw new \RuntimeException('JSON decoding error: ' . json_last_error_msg()); - } - - return $this->decodeRecursive($value); - } - - private function decodeRecursive($value) { - if (\is_array($value)) { - if (isset($value['nodeType'])) { - if ($value['nodeType'] === 'Comment' || $value['nodeType'] === 'Comment_Doc') { - return $this->decodeComment($value); - } - return $this->decodeNode($value); - } - return $this->decodeArray($value); - } - return $value; - } - - private function decodeArray(array $array) : array { - $decodedArray = []; - foreach ($array as $key => $value) { - $decodedArray[$key] = $this->decodeRecursive($value); - } - return $decodedArray; - } - - private function decodeNode(array $value) : Node { - $nodeType = $value['nodeType']; - if (!\is_string($nodeType)) { - throw new \RuntimeException('Node type must be a string'); - } - - $reflectionClass = $this->reflectionClassFromNodeType($nodeType); - /** @var Node $node */ - $node = $reflectionClass->newInstanceWithoutConstructor(); - - if (isset($value['attributes'])) { - if (!\is_array($value['attributes'])) { - throw new \RuntimeException('Attributes must be an array'); - } - - $node->setAttributes($this->decodeArray($value['attributes'])); - } - - foreach ($value as $name => $subNode) { - if ($name === 'nodeType' || $name === 'attributes') { - continue; - } - - $node->$name = $this->decodeRecursive($subNode); - } - - return $node; - } - - private function decodeComment(array $value) : Comment { - $className = $value['nodeType'] === 'Comment' ? Comment::class : Comment\Doc::class; - if (!isset($value['text'])) { - throw new \RuntimeException('Comment must have text'); - } - - return new $className( - $value['text'], - $value['line'] ?? -1, $value['filePos'] ?? -1, $value['tokenPos'] ?? -1, - $value['endLine'] ?? -1, $value['endFilePos'] ?? -1, $value['endTokenPos'] ?? -1 - ); - } - - private function reflectionClassFromNodeType(string $nodeType) : \ReflectionClass { - if (!isset($this->reflectionClassCache[$nodeType])) { - $className = $this->classNameFromNodeType($nodeType); - $this->reflectionClassCache[$nodeType] = new \ReflectionClass($className); - } - return $this->reflectionClassCache[$nodeType]; - } - - private function classNameFromNodeType(string $nodeType) : string { - $className = 'PhpParser\\Node\\' . strtr($nodeType, '_', '\\'); - if (class_exists($className)) { - return $className; - } - - $className .= '_'; - if (class_exists($className)) { - return $className; - } - - throw new \RuntimeException("Unknown node type \"$nodeType\""); - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Lexer.php b/lib/nikic/php-parser/lib/PhpParser/Lexer.php deleted file mode 100644 index e15dd0a5d..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Lexer.php +++ /dev/null @@ -1,560 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser; - -use PhpParser\Parser\Tokens; - -class Lexer -{ - protected $code; - protected $tokens; - protected $pos; - protected $line; - protected $filePos; - protected $prevCloseTagHasNewline; - - protected $tokenMap; - protected $dropTokens; - protected $identifierTokens; - - private $attributeStartLineUsed; - private $attributeEndLineUsed; - private $attributeStartTokenPosUsed; - private $attributeEndTokenPosUsed; - private $attributeStartFilePosUsed; - private $attributeEndFilePosUsed; - private $attributeCommentsUsed; - - /** - * Creates a Lexer. - * - * @param array $options Options array. Currently only the 'usedAttributes' option is supported, - * which is an array of attributes to add to the AST nodes. Possible - * attributes are: 'comments', 'startLine', 'endLine', 'startTokenPos', - * 'endTokenPos', 'startFilePos', 'endFilePos'. The option defaults to the - * first three. For more info see getNextToken() docs. - */ - public function __construct(array $options = []) { - // Create Map from internal tokens to PhpParser tokens. - $this->defineCompatibilityTokens(); - $this->tokenMap = $this->createTokenMap(); - $this->identifierTokens = $this->createIdentifierTokenMap(); - - // map of tokens to drop while lexing (the map is only used for isset lookup, - // that's why the value is simply set to 1; the value is never actually used.) - $this->dropTokens = array_fill_keys( - [\T_WHITESPACE, \T_OPEN_TAG, \T_COMMENT, \T_DOC_COMMENT, \T_BAD_CHARACTER], 1 - ); - - $defaultAttributes = ['comments', 'startLine', 'endLine']; - $usedAttributes = array_fill_keys($options['usedAttributes'] ?? $defaultAttributes, true); - - // Create individual boolean properties to make these checks faster. - $this->attributeStartLineUsed = isset($usedAttributes['startLine']); - $this->attributeEndLineUsed = isset($usedAttributes['endLine']); - $this->attributeStartTokenPosUsed = isset($usedAttributes['startTokenPos']); - $this->attributeEndTokenPosUsed = isset($usedAttributes['endTokenPos']); - $this->attributeStartFilePosUsed = isset($usedAttributes['startFilePos']); - $this->attributeEndFilePosUsed = isset($usedAttributes['endFilePos']); - $this->attributeCommentsUsed = isset($usedAttributes['comments']); - } - - /** - * Initializes the lexer for lexing the provided source code. - * - * This function does not throw if lexing errors occur. Instead, errors may be retrieved using - * the getErrors() method. - * - * @param string $code The source code to lex - * @param ErrorHandler|null $errorHandler Error handler to use for lexing errors. Defaults to - * ErrorHandler\Throwing - */ - public function startLexing(string $code, ErrorHandler $errorHandler = null) { - if (null === $errorHandler) { - $errorHandler = new ErrorHandler\Throwing(); - } - - $this->code = $code; // keep the code around for __halt_compiler() handling - $this->pos = -1; - $this->line = 1; - $this->filePos = 0; - - // If inline HTML occurs without preceding code, treat it as if it had a leading newline. - // This ensures proper composability, because having a newline is the "safe" assumption. - $this->prevCloseTagHasNewline = true; - - $scream = ini_set('xdebug.scream', '0'); - - $this->tokens = @token_get_all($code); - $this->postprocessTokens($errorHandler); - - if (false !== $scream) { - ini_set('xdebug.scream', $scream); - } - } - - private function handleInvalidCharacterRange($start, $end, $line, ErrorHandler $errorHandler) { - $tokens = []; - for ($i = $start; $i < $end; $i++) { - $chr = $this->code[$i]; - if ($chr === "\0") { - // PHP cuts error message after null byte, so need special case - $errorMsg = 'Unexpected null byte'; - } else { - $errorMsg = sprintf( - 'Unexpected character "%s" (ASCII %d)', $chr, ord($chr) - ); - } - - $tokens[] = [\T_BAD_CHARACTER, $chr, $line]; - $errorHandler->handleError(new Error($errorMsg, [ - 'startLine' => $line, - 'endLine' => $line, - 'startFilePos' => $i, - 'endFilePos' => $i, - ])); - } - return $tokens; - } - - /** - * Check whether comment token is unterminated. - * - * @return bool - */ - private function isUnterminatedComment($token) : bool { - return ($token[0] === \T_COMMENT || $token[0] === \T_DOC_COMMENT) - && substr($token[1], 0, 2) === '/*' - && substr($token[1], -2) !== '*/'; - } - - protected function postprocessTokens(ErrorHandler $errorHandler) { - // PHP's error handling for token_get_all() is rather bad, so if we want detailed - // error information we need to compute it ourselves. Invalid character errors are - // detected by finding "gaps" in the token array. Unterminated comments are detected - // by checking if a trailing comment has a "*/" at the end. - // - // Additionally, we perform a number of canonicalizations here: - // * Use the PHP 8.0 comment format, which does not include trailing whitespace anymore. - // * Use PHP 8.0 T_NAME_* tokens. - // * Use PHP 8.1 T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG and - // T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG tokens used to disambiguate intersection types. - - $filePos = 0; - $line = 1; - $numTokens = \count($this->tokens); - for ($i = 0; $i < $numTokens; $i++) { - $token = $this->tokens[$i]; - - // Since PHP 7.4 invalid characters are represented by a T_BAD_CHARACTER token. - // In this case we only need to emit an error. - if ($token[0] === \T_BAD_CHARACTER) { - $this->handleInvalidCharacterRange($filePos, $filePos + 1, $line, $errorHandler); - } - - if ($token[0] === \T_COMMENT && substr($token[1], 0, 2) !== '/*' - && preg_match('/(\r\n|\n|\r)$/D', $token[1], $matches)) { - $trailingNewline = $matches[0]; - $token[1] = substr($token[1], 0, -strlen($trailingNewline)); - $this->tokens[$i] = $token; - if (isset($this->tokens[$i + 1]) && $this->tokens[$i + 1][0] === \T_WHITESPACE) { - // Move trailing newline into following T_WHITESPACE token, if it already exists. - $this->tokens[$i + 1][1] = $trailingNewline . $this->tokens[$i + 1][1]; - $this->tokens[$i + 1][2]--; - } else { - // Otherwise, we need to create a new T_WHITESPACE token. - array_splice($this->tokens, $i + 1, 0, [ - [\T_WHITESPACE, $trailingNewline, $line], - ]); - $numTokens++; - } - } - - // Emulate PHP 8 T_NAME_* tokens, by combining sequences of T_NS_SEPARATOR and T_STRING - // into a single token. - if (\is_array($token) - && ($token[0] === \T_NS_SEPARATOR || isset($this->identifierTokens[$token[0]]))) { - $lastWasSeparator = $token[0] === \T_NS_SEPARATOR; - $text = $token[1]; - for ($j = $i + 1; isset($this->tokens[$j]); $j++) { - if ($lastWasSeparator) { - if (!isset($this->identifierTokens[$this->tokens[$j][0]])) { - break; - } - $lastWasSeparator = false; - } else { - if ($this->tokens[$j][0] !== \T_NS_SEPARATOR) { - break; - } - $lastWasSeparator = true; - } - $text .= $this->tokens[$j][1]; - } - if ($lastWasSeparator) { - // Trailing separator is not part of the name. - $j--; - $text = substr($text, 0, -1); - } - if ($j > $i + 1) { - if ($token[0] === \T_NS_SEPARATOR) { - $type = \T_NAME_FULLY_QUALIFIED; - } else if ($token[0] === \T_NAMESPACE) { - $type = \T_NAME_RELATIVE; - } else { - $type = \T_NAME_QUALIFIED; - } - $token = [$type, $text, $line]; - array_splice($this->tokens, $i, $j - $i, [$token]); - $numTokens -= $j - $i - 1; - } - } - - if ($token === '&') { - $next = $i + 1; - while (isset($this->tokens[$next]) && $this->tokens[$next][0] === \T_WHITESPACE) { - $next++; - } - $followedByVarOrVarArg = isset($this->tokens[$next]) && - ($this->tokens[$next][0] === \T_VARIABLE || $this->tokens[$next][0] === \T_ELLIPSIS); - $this->tokens[$i] = $token = [ - $followedByVarOrVarArg - ? \T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG - : \T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG, - '&', - $line, - ]; - } - - $tokenValue = \is_string($token) ? $token : $token[1]; - $tokenLen = \strlen($tokenValue); - - if (substr($this->code, $filePos, $tokenLen) !== $tokenValue) { - // Something is missing, must be an invalid character - $nextFilePos = strpos($this->code, $tokenValue, $filePos); - $badCharTokens = $this->handleInvalidCharacterRange( - $filePos, $nextFilePos, $line, $errorHandler); - $filePos = (int) $nextFilePos; - - array_splice($this->tokens, $i, 0, $badCharTokens); - $numTokens += \count($badCharTokens); - $i += \count($badCharTokens); - } - - $filePos += $tokenLen; - $line += substr_count($tokenValue, "\n"); - } - - if ($filePos !== \strlen($this->code)) { - if (substr($this->code, $filePos, 2) === '/*') { - // Unlike PHP, HHVM will drop unterminated comments entirely - $comment = substr($this->code, $filePos); - $errorHandler->handleError(new Error('Unterminated comment', [ - 'startLine' => $line, - 'endLine' => $line + substr_count($comment, "\n"), - 'startFilePos' => $filePos, - 'endFilePos' => $filePos + \strlen($comment), - ])); - - // Emulate the PHP behavior - $isDocComment = isset($comment[3]) && $comment[3] === '*'; - $this->tokens[] = [$isDocComment ? \T_DOC_COMMENT : \T_COMMENT, $comment, $line]; - } else { - // Invalid characters at the end of the input - $badCharTokens = $this->handleInvalidCharacterRange( - $filePos, \strlen($this->code), $line, $errorHandler); - $this->tokens = array_merge($this->tokens, $badCharTokens); - } - return; - } - - if (count($this->tokens) > 0) { - // Check for unterminated comment - $lastToken = $this->tokens[count($this->tokens) - 1]; - if ($this->isUnterminatedComment($lastToken)) { - $errorHandler->handleError(new Error('Unterminated comment', [ - 'startLine' => $line - substr_count($lastToken[1], "\n"), - 'endLine' => $line, - 'startFilePos' => $filePos - \strlen($lastToken[1]), - 'endFilePos' => $filePos, - ])); - } - } - } - - /** - * Fetches the next token. - * - * The available attributes are determined by the 'usedAttributes' option, which can - * be specified in the constructor. The following attributes are supported: - * - * * 'comments' => Array of PhpParser\Comment or PhpParser\Comment\Doc instances, - * representing all comments that occurred between the previous - * non-discarded token and the current one. - * * 'startLine' => Line in which the node starts. - * * 'endLine' => Line in which the node ends. - * * 'startTokenPos' => Offset into the token array of the first token in the node. - * * 'endTokenPos' => Offset into the token array of the last token in the node. - * * 'startFilePos' => Offset into the code string of the first character that is part of the node. - * * 'endFilePos' => Offset into the code string of the last character that is part of the node. - * - * @param mixed $value Variable to store token content in - * @param mixed $startAttributes Variable to store start attributes in - * @param mixed $endAttributes Variable to store end attributes in - * - * @return int Token id - */ - public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) : int { - $startAttributes = []; - $endAttributes = []; - - while (1) { - if (isset($this->tokens[++$this->pos])) { - $token = $this->tokens[$this->pos]; - } else { - // EOF token with ID 0 - $token = "\0"; - } - - if ($this->attributeStartLineUsed) { - $startAttributes['startLine'] = $this->line; - } - if ($this->attributeStartTokenPosUsed) { - $startAttributes['startTokenPos'] = $this->pos; - } - if ($this->attributeStartFilePosUsed) { - $startAttributes['startFilePos'] = $this->filePos; - } - - if (\is_string($token)) { - $value = $token; - if (isset($token[1])) { - // bug in token_get_all - $this->filePos += 2; - $id = ord('"'); - } else { - $this->filePos += 1; - $id = ord($token); - } - } elseif (!isset($this->dropTokens[$token[0]])) { - $value = $token[1]; - $id = $this->tokenMap[$token[0]]; - if (\T_CLOSE_TAG === $token[0]) { - $this->prevCloseTagHasNewline = false !== strpos($token[1], "\n") - || false !== strpos($token[1], "\r"); - } elseif (\T_INLINE_HTML === $token[0]) { - $startAttributes['hasLeadingNewline'] = $this->prevCloseTagHasNewline; - } - - $this->line += substr_count($value, "\n"); - $this->filePos += \strlen($value); - } else { - $origLine = $this->line; - $origFilePos = $this->filePos; - $this->line += substr_count($token[1], "\n"); - $this->filePos += \strlen($token[1]); - - if (\T_COMMENT === $token[0] || \T_DOC_COMMENT === $token[0]) { - if ($this->attributeCommentsUsed) { - $comment = \T_DOC_COMMENT === $token[0] - ? new Comment\Doc($token[1], - $origLine, $origFilePos, $this->pos, - $this->line, $this->filePos - 1, $this->pos) - : new Comment($token[1], - $origLine, $origFilePos, $this->pos, - $this->line, $this->filePos - 1, $this->pos); - $startAttributes['comments'][] = $comment; - } - } - continue; - } - - if ($this->attributeEndLineUsed) { - $endAttributes['endLine'] = $this->line; - } - if ($this->attributeEndTokenPosUsed) { - $endAttributes['endTokenPos'] = $this->pos; - } - if ($this->attributeEndFilePosUsed) { - $endAttributes['endFilePos'] = $this->filePos - 1; - } - - return $id; - } - - throw new \RuntimeException('Reached end of lexer loop'); - } - - /** - * Returns the token array for current code. - * - * The token array is in the same format as provided by the - * token_get_all() function and does not discard tokens (i.e. - * whitespace and comments are included). The token position - * attributes are against this token array. - * - * @return array Array of tokens in token_get_all() format - */ - public function getTokens() : array { - return $this->tokens; - } - - /** - * Handles __halt_compiler() by returning the text after it. - * - * @return string Remaining text - */ - public function handleHaltCompiler() : string { - // text after T_HALT_COMPILER, still including (); - $textAfter = substr($this->code, $this->filePos); - - // ensure that it is followed by (); - // this simplifies the situation, by not allowing any comments - // in between of the tokens. - if (!preg_match('~^\s*\(\s*\)\s*(?:;|\?>\r?\n?)~', $textAfter, $matches)) { - throw new Error('__HALT_COMPILER must be followed by "();"'); - } - - // prevent the lexer from returning any further tokens - $this->pos = count($this->tokens); - - // return with (); removed - return substr($textAfter, strlen($matches[0])); - } - - private function defineCompatibilityTokens() { - static $compatTokensDefined = false; - if ($compatTokensDefined) { - return; - } - - $compatTokens = [ - // PHP 7.4 - 'T_BAD_CHARACTER', - 'T_FN', - 'T_COALESCE_EQUAL', - // PHP 8.0 - 'T_NAME_QUALIFIED', - 'T_NAME_FULLY_QUALIFIED', - 'T_NAME_RELATIVE', - 'T_MATCH', - 'T_NULLSAFE_OBJECT_OPERATOR', - 'T_ATTRIBUTE', - // PHP 8.1 - 'T_ENUM', - 'T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG', - 'T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG', - 'T_READONLY', - ]; - - // PHP-Parser might be used together with another library that also emulates some or all - // of these tokens. Perform a sanity-check that all already defined tokens have been - // assigned a unique ID. - $usedTokenIds = []; - foreach ($compatTokens as $token) { - if (\defined($token)) { - $tokenId = \constant($token); - $clashingToken = $usedTokenIds[$tokenId] ?? null; - if ($clashingToken !== null) { - throw new \Error(sprintf( - 'Token %s has same ID as token %s, ' . - 'you may be using a library with broken token emulation', - $token, $clashingToken - )); - } - $usedTokenIds[$tokenId] = $token; - } - } - - // Now define any tokens that have not yet been emulated. Try to assign IDs from -1 - // downwards, but skip any IDs that may already be in use. - $newTokenId = -1; - foreach ($compatTokens as $token) { - if (!\defined($token)) { - while (isset($usedTokenIds[$newTokenId])) { - $newTokenId--; - } - \define($token, $newTokenId); - $newTokenId--; - } - } - - $compatTokensDefined = true; - } - - /** - * Creates the token map. - * - * The token map maps the PHP internal token identifiers - * to the identifiers used by the Parser. Additionally it - * maps T_OPEN_TAG_WITH_ECHO to T_ECHO and T_CLOSE_TAG to ';'. - * - * @return array The token map - */ - protected function createTokenMap() : array { - $tokenMap = []; - - // 256 is the minimum possible token number, as everything below - // it is an ASCII value - for ($i = 256; $i < 1000; ++$i) { - if (\T_DOUBLE_COLON === $i) { - // T_DOUBLE_COLON is equivalent to T_PAAMAYIM_NEKUDOTAYIM - $tokenMap[$i] = Tokens::T_PAAMAYIM_NEKUDOTAYIM; - } elseif(\T_OPEN_TAG_WITH_ECHO === $i) { - // T_OPEN_TAG_WITH_ECHO with dropped T_OPEN_TAG results in T_ECHO - $tokenMap[$i] = Tokens::T_ECHO; - } elseif(\T_CLOSE_TAG === $i) { - // T_CLOSE_TAG is equivalent to ';' - $tokenMap[$i] = ord(';'); - } elseif ('UNKNOWN' !== $name = token_name($i)) { - if ('T_HASHBANG' === $name) { - // HHVM uses a special token for #! hashbang lines - $tokenMap[$i] = Tokens::T_INLINE_HTML; - } elseif (defined($name = Tokens::class . '::' . $name)) { - // Other tokens can be mapped directly - $tokenMap[$i] = constant($name); - } - } - } - - // HHVM uses a special token for numbers that overflow to double - if (defined('T_ONUMBER')) { - $tokenMap[\T_ONUMBER] = Tokens::T_DNUMBER; - } - // HHVM also has a separate token for the __COMPILER_HALT_OFFSET__ constant - if (defined('T_COMPILER_HALT_OFFSET')) { - $tokenMap[\T_COMPILER_HALT_OFFSET] = Tokens::T_STRING; - } - - // Assign tokens for which we define compatibility constants, as token_name() does not know them. - $tokenMap[\T_FN] = Tokens::T_FN; - $tokenMap[\T_COALESCE_EQUAL] = Tokens::T_COALESCE_EQUAL; - $tokenMap[\T_NAME_QUALIFIED] = Tokens::T_NAME_QUALIFIED; - $tokenMap[\T_NAME_FULLY_QUALIFIED] = Tokens::T_NAME_FULLY_QUALIFIED; - $tokenMap[\T_NAME_RELATIVE] = Tokens::T_NAME_RELATIVE; - $tokenMap[\T_MATCH] = Tokens::T_MATCH; - $tokenMap[\T_NULLSAFE_OBJECT_OPERATOR] = Tokens::T_NULLSAFE_OBJECT_OPERATOR; - $tokenMap[\T_ATTRIBUTE] = Tokens::T_ATTRIBUTE; - $tokenMap[\T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG] = Tokens::T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG; - $tokenMap[\T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG] = Tokens::T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG; - $tokenMap[\T_ENUM] = Tokens::T_ENUM; - $tokenMap[\T_READONLY] = Tokens::T_READONLY; - - return $tokenMap; - } - - private function createIdentifierTokenMap(): array { - // Based on semi_reserved production. - return array_fill_keys([ - \T_STRING, - \T_STATIC, \T_ABSTRACT, \T_FINAL, \T_PRIVATE, \T_PROTECTED, \T_PUBLIC, \T_READONLY, - \T_INCLUDE, \T_INCLUDE_ONCE, \T_EVAL, \T_REQUIRE, \T_REQUIRE_ONCE, \T_LOGICAL_OR, \T_LOGICAL_XOR, \T_LOGICAL_AND, - \T_INSTANCEOF, \T_NEW, \T_CLONE, \T_EXIT, \T_IF, \T_ELSEIF, \T_ELSE, \T_ENDIF, \T_ECHO, \T_DO, \T_WHILE, - \T_ENDWHILE, \T_FOR, \T_ENDFOR, \T_FOREACH, \T_ENDFOREACH, \T_DECLARE, \T_ENDDECLARE, \T_AS, \T_TRY, \T_CATCH, - \T_FINALLY, \T_THROW, \T_USE, \T_INSTEADOF, \T_GLOBAL, \T_VAR, \T_UNSET, \T_ISSET, \T_EMPTY, \T_CONTINUE, \T_GOTO, - \T_FUNCTION, \T_CONST, \T_RETURN, \T_PRINT, \T_YIELD, \T_LIST, \T_SWITCH, \T_ENDSWITCH, \T_CASE, \T_DEFAULT, - \T_BREAK, \T_ARRAY, \T_CALLABLE, \T_EXTENDS, \T_IMPLEMENTS, \T_NAMESPACE, \T_TRAIT, \T_INTERFACE, \T_CLASS, - \T_CLASS_C, \T_TRAIT_C, \T_FUNC_C, \T_METHOD_C, \T_LINE, \T_FILE, \T_DIR, \T_NS_C, \T_HALT_COMPILER, \T_FN, - \T_MATCH, - ], true); - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php b/lib/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php deleted file mode 100644 index 5c56e026b..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php +++ /dev/null @@ -1,248 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Lexer; - -use PhpParser\Error; -use PhpParser\ErrorHandler; -use PhpParser\Lexer; -use PhpParser\Lexer\TokenEmulator\AttributeEmulator; -use PhpParser\Lexer\TokenEmulator\EnumTokenEmulator; -use PhpParser\Lexer\TokenEmulator\CoaleseEqualTokenEmulator; -use PhpParser\Lexer\TokenEmulator\ExplicitOctalEmulator; -use PhpParser\Lexer\TokenEmulator\FlexibleDocStringEmulator; -use PhpParser\Lexer\TokenEmulator\FnTokenEmulator; -use PhpParser\Lexer\TokenEmulator\MatchTokenEmulator; -use PhpParser\Lexer\TokenEmulator\NullsafeTokenEmulator; -use PhpParser\Lexer\TokenEmulator\NumericLiteralSeparatorEmulator; -use PhpParser\Lexer\TokenEmulator\ReadonlyTokenEmulator; -use PhpParser\Lexer\TokenEmulator\ReverseEmulator; -use PhpParser\Lexer\TokenEmulator\TokenEmulator; - -class Emulative extends Lexer -{ - const PHP_7_3 = '7.3dev'; - const PHP_7_4 = '7.4dev'; - const PHP_8_0 = '8.0dev'; - const PHP_8_1 = '8.1dev'; - - /** @var mixed[] Patches used to reverse changes introduced in the code */ - private $patches = []; - - /** @var TokenEmulator[] */ - private $emulators = []; - - /** @var string */ - private $targetPhpVersion; - - /** - * @param mixed[] $options Lexer options. In addition to the usual options, - * accepts a 'phpVersion' string that specifies the - * version to emulate. Defaults to newest supported. - */ - public function __construct(array $options = []) - { - $this->targetPhpVersion = $options['phpVersion'] ?? Emulative::PHP_8_1; - unset($options['phpVersion']); - - parent::__construct($options); - - $emulators = [ - new FlexibleDocStringEmulator(), - new FnTokenEmulator(), - new MatchTokenEmulator(), - new CoaleseEqualTokenEmulator(), - new NumericLiteralSeparatorEmulator(), - new NullsafeTokenEmulator(), - new AttributeEmulator(), - new EnumTokenEmulator(), - new ReadonlyTokenEmulator(), - new ExplicitOctalEmulator(), - ]; - - // Collect emulators that are relevant for the PHP version we're running - // and the PHP version we're targeting for emulation. - foreach ($emulators as $emulator) { - $emulatorPhpVersion = $emulator->getPhpVersion(); - if ($this->isForwardEmulationNeeded($emulatorPhpVersion)) { - $this->emulators[] = $emulator; - } else if ($this->isReverseEmulationNeeded($emulatorPhpVersion)) { - $this->emulators[] = new ReverseEmulator($emulator); - } - } - } - - public function startLexing(string $code, ErrorHandler $errorHandler = null) { - $emulators = array_filter($this->emulators, function($emulator) use($code) { - return $emulator->isEmulationNeeded($code); - }); - - if (empty($emulators)) { - // Nothing to emulate, yay - parent::startLexing($code, $errorHandler); - return; - } - - $this->patches = []; - foreach ($emulators as $emulator) { - $code = $emulator->preprocessCode($code, $this->patches); - } - - $collector = new ErrorHandler\Collecting(); - parent::startLexing($code, $collector); - $this->sortPatches(); - $this->fixupTokens(); - - $errors = $collector->getErrors(); - if (!empty($errors)) { - $this->fixupErrors($errors); - foreach ($errors as $error) { - $errorHandler->handleError($error); - } - } - - foreach ($emulators as $emulator) { - $this->tokens = $emulator->emulate($code, $this->tokens); - } - } - - private function isForwardEmulationNeeded(string $emulatorPhpVersion): bool { - return version_compare(\PHP_VERSION, $emulatorPhpVersion, '<') - && version_compare($this->targetPhpVersion, $emulatorPhpVersion, '>='); - } - - private function isReverseEmulationNeeded(string $emulatorPhpVersion): bool { - return version_compare(\PHP_VERSION, $emulatorPhpVersion, '>=') - && version_compare($this->targetPhpVersion, $emulatorPhpVersion, '<'); - } - - private function sortPatches() - { - // Patches may be contributed by different emulators. - // Make sure they are sorted by increasing patch position. - usort($this->patches, function($p1, $p2) { - return $p1[0] <=> $p2[0]; - }); - } - - private function fixupTokens() - { - if (\count($this->patches) === 0) { - return; - } - - // Load first patch - $patchIdx = 0; - - list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx]; - - // We use a manual loop over the tokens, because we modify the array on the fly - $pos = 0; - for ($i = 0, $c = \count($this->tokens); $i < $c; $i++) { - $token = $this->tokens[$i]; - if (\is_string($token)) { - if ($patchPos === $pos) { - // Only support replacement for string tokens. - assert($patchType === 'replace'); - $this->tokens[$i] = $patchText; - - // Fetch the next patch - $patchIdx++; - if ($patchIdx >= \count($this->patches)) { - // No more patches, we're done - return; - } - list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx]; - } - - $pos += \strlen($token); - continue; - } - - $len = \strlen($token[1]); - $posDelta = 0; - while ($patchPos >= $pos && $patchPos < $pos + $len) { - $patchTextLen = \strlen($patchText); - if ($patchType === 'remove') { - if ($patchPos === $pos && $patchTextLen === $len) { - // Remove token entirely - array_splice($this->tokens, $i, 1, []); - $i--; - $c--; - } else { - // Remove from token string - $this->tokens[$i][1] = substr_replace( - $token[1], '', $patchPos - $pos + $posDelta, $patchTextLen - ); - $posDelta -= $patchTextLen; - } - } elseif ($patchType === 'add') { - // Insert into the token string - $this->tokens[$i][1] = substr_replace( - $token[1], $patchText, $patchPos - $pos + $posDelta, 0 - ); - $posDelta += $patchTextLen; - } else if ($patchType === 'replace') { - // Replace inside the token string - $this->tokens[$i][1] = substr_replace( - $token[1], $patchText, $patchPos - $pos + $posDelta, $patchTextLen - ); - } else { - assert(false); - } - - // Fetch the next patch - $patchIdx++; - if ($patchIdx >= \count($this->patches)) { - // No more patches, we're done - return; - } - - list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx]; - - // Multiple patches may apply to the same token. Reload the current one to check - // If the new patch applies - $token = $this->tokens[$i]; - } - - $pos += $len; - } - - // A patch did not apply - assert(false); - } - - /** - * Fixup line and position information in errors. - * - * @param Error[] $errors - */ - private function fixupErrors(array $errors) { - foreach ($errors as $error) { - $attrs = $error->getAttributes(); - - $posDelta = 0; - $lineDelta = 0; - foreach ($this->patches as $patch) { - list($patchPos, $patchType, $patchText) = $patch; - if ($patchPos >= $attrs['startFilePos']) { - // No longer relevant - break; - } - - if ($patchType === 'add') { - $posDelta += strlen($patchText); - $lineDelta += substr_count($patchText, "\n"); - } else if ($patchType === 'remove') { - $posDelta -= strlen($patchText); - $lineDelta -= substr_count($patchText, "\n"); - } - } - - $attrs['startFilePos'] += $posDelta; - $attrs['endFilePos'] += $posDelta; - $attrs['startLine'] += $lineDelta; - $attrs['endLine'] += $lineDelta; - $error->setAttributes($attrs); - } - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php b/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php deleted file mode 100644 index 6776a5197..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Lexer\TokenEmulator; - -use PhpParser\Lexer\Emulative; - -final class AttributeEmulator extends TokenEmulator -{ - public function getPhpVersion(): string - { - return Emulative::PHP_8_0; - } - - public function isEmulationNeeded(string $code) : bool - { - return strpos($code, '#[') !== false; - } - - public function emulate(string $code, array $tokens): array - { - // We need to manually iterate and manage a count because we'll change - // the tokens array on the way. - $line = 1; - for ($i = 0, $c = count($tokens); $i < $c; ++$i) { - if ($tokens[$i] === '#' && isset($tokens[$i + 1]) && $tokens[$i + 1] === '[') { - array_splice($tokens, $i, 2, [ - [\T_ATTRIBUTE, '#[', $line] - ]); - $c--; - continue; - } - if (\is_array($tokens[$i])) { - $line += substr_count($tokens[$i][1], "\n"); - } - } - - return $tokens; - } - - public function reverseEmulate(string $code, array $tokens): array - { - // TODO - return $tokens; - } - - public function preprocessCode(string $code, array &$patches): string { - $pos = 0; - while (false !== $pos = strpos($code, '#[', $pos)) { - // Replace #[ with %[ - $code[$pos] = '%'; - $patches[] = [$pos, 'replace', '#']; - $pos += 2; - } - return $code; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/CoaleseEqualTokenEmulator.php b/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/CoaleseEqualTokenEmulator.php deleted file mode 100644 index d91da9214..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/CoaleseEqualTokenEmulator.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Lexer\TokenEmulator; - -use PhpParser\Lexer\Emulative; - -final class CoaleseEqualTokenEmulator extends TokenEmulator -{ - public function getPhpVersion(): string - { - return Emulative::PHP_7_4; - } - - public function isEmulationNeeded(string $code): bool - { - return strpos($code, '??=') !== false; - } - - public function emulate(string $code, array $tokens): array - { - // We need to manually iterate and manage a count because we'll change - // the tokens array on the way - $line = 1; - for ($i = 0, $c = count($tokens); $i < $c; ++$i) { - if (isset($tokens[$i + 1])) { - if ($tokens[$i][0] === T_COALESCE && $tokens[$i + 1] === '=') { - array_splice($tokens, $i, 2, [ - [\T_COALESCE_EQUAL, '??=', $line] - ]); - $c--; - continue; - } - } - if (\is_array($tokens[$i])) { - $line += substr_count($tokens[$i][1], "\n"); - } - } - - return $tokens; - } - - public function reverseEmulate(string $code, array $tokens): array - { - // ??= was not valid code previously, don't bother. - return $tokens; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/EnumTokenEmulator.php b/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/EnumTokenEmulator.php deleted file mode 100644 index 4ddc0b17e..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/EnumTokenEmulator.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Lexer\TokenEmulator; - -use PhpParser\Lexer\Emulative; - -final class EnumTokenEmulator extends KeywordEmulator -{ - public function getPhpVersion(): string - { - return Emulative::PHP_8_1; - } - - public function getKeywordString(): string - { - return 'enum'; - } - - public function getKeywordToken(): int - { - return \T_ENUM; - } - - protected function isKeywordContext(array $tokens, int $pos): bool - { - return parent::isKeywordContext($tokens, $pos) - && isset($tokens[$pos + 2]) - && $tokens[$pos + 1][0] === \T_WHITESPACE - && $tokens[$pos + 2][0] === \T_STRING; - } -} \ No newline at end of file diff --git a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ExplicitOctalEmulator.php b/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ExplicitOctalEmulator.php deleted file mode 100644 index f5f6805b8..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ExplicitOctalEmulator.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Lexer\TokenEmulator; - -use PhpParser\Lexer\Emulative; - -class ExplicitOctalEmulator extends TokenEmulator { - public function getPhpVersion(): string { - return Emulative::PHP_8_1; - } - - public function isEmulationNeeded(string $code): bool { - return strpos($code, '0o') !== false || strpos($code, '0O') !== false; - } - - public function emulate(string $code, array $tokens): array { - for ($i = 0, $c = count($tokens); $i < $c; ++$i) { - if ($tokens[$i][0] == \T_LNUMBER && $tokens[$i][1] === '0' && - isset($tokens[$i + 1]) && $tokens[$i + 1][0] == \T_STRING && - preg_match('/[oO][0-7]+(?:_[0-7]+)*/', $tokens[$i + 1][1]) - ) { - $tokenKind = $this->resolveIntegerOrFloatToken($tokens[$i + 1][1]); - array_splice($tokens, $i, 2, [ - [$tokenKind, '0' . $tokens[$i + 1][1], $tokens[$i][2]], - ]); - $c--; - } - } - return $tokens; - } - - private function resolveIntegerOrFloatToken(string $str): int - { - $str = substr($str, 1); - $str = str_replace('_', '', $str); - $num = octdec($str); - return is_float($num) ? \T_DNUMBER : \T_LNUMBER; - } - - public function reverseEmulate(string $code, array $tokens): array { - // Explicit octals were not legal code previously, don't bother. - return $tokens; - } -} \ No newline at end of file diff --git a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php b/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php deleted file mode 100644 index c15d6271f..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Lexer\TokenEmulator; - -use PhpParser\Lexer\Emulative; - -final class FlexibleDocStringEmulator extends TokenEmulator -{ - const FLEXIBLE_DOC_STRING_REGEX = <<<'REGEX' -/<<<[ \t]*(['"]?)([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)\1\r?\n -(?:.*\r?\n)*? -(?<indentation>\h*)\2(?![a-zA-Z0-9_\x80-\xff])(?<separator>(?:;?[\r\n])?)/x -REGEX; - - public function getPhpVersion(): string - { - return Emulative::PHP_7_3; - } - - public function isEmulationNeeded(string $code) : bool - { - return strpos($code, '<<<') !== false; - } - - public function emulate(string $code, array $tokens): array - { - // Handled by preprocessing + fixup. - return $tokens; - } - - public function reverseEmulate(string $code, array $tokens): array - { - // Not supported. - return $tokens; - } - - public function preprocessCode(string $code, array &$patches): string { - if (!preg_match_all(self::FLEXIBLE_DOC_STRING_REGEX, $code, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE)) { - // No heredoc/nowdoc found - return $code; - } - - // Keep track of how much we need to adjust string offsets due to the modifications we - // already made - $posDelta = 0; - foreach ($matches as $match) { - $indentation = $match['indentation'][0]; - $indentationStart = $match['indentation'][1]; - - $separator = $match['separator'][0]; - $separatorStart = $match['separator'][1]; - - if ($indentation === '' && $separator !== '') { - // Ordinary heredoc/nowdoc - continue; - } - - if ($indentation !== '') { - // Remove indentation - $indentationLen = strlen($indentation); - $code = substr_replace($code, '', $indentationStart + $posDelta, $indentationLen); - $patches[] = [$indentationStart + $posDelta, 'add', $indentation]; - $posDelta -= $indentationLen; - } - - if ($separator === '') { - // Insert newline as separator - $code = substr_replace($code, "\n", $separatorStart + $posDelta, 0); - $patches[] = [$separatorStart + $posDelta, 'remove', "\n"]; - $posDelta += 1; - } - } - - return $code; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php b/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php deleted file mode 100644 index eb7e49634..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Lexer\TokenEmulator; - -use PhpParser\Lexer\Emulative; - -final class FnTokenEmulator extends KeywordEmulator -{ - public function getPhpVersion(): string - { - return Emulative::PHP_7_4; - } - - public function getKeywordString(): string - { - return 'fn'; - } - - public function getKeywordToken(): int - { - return \T_FN; - } -} \ No newline at end of file diff --git a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php b/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php deleted file mode 100644 index ea261cc17..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Lexer\TokenEmulator; - -abstract class KeywordEmulator extends TokenEmulator -{ - abstract function getKeywordString(): string; - abstract function getKeywordToken(): int; - - public function isEmulationNeeded(string $code): bool - { - return strpos(strtolower($code), $this->getKeywordString()) !== false; - } - - protected function isKeywordContext(array $tokens, int $pos): bool - { - $previousNonSpaceToken = $this->getPreviousNonSpaceToken($tokens, $pos); - return $previousNonSpaceToken === null || $previousNonSpaceToken[0] !== \T_OBJECT_OPERATOR; - } - - public function emulate(string $code, array $tokens): array - { - $keywordString = $this->getKeywordString(); - foreach ($tokens as $i => $token) { - if ($token[0] === T_STRING && strtolower($token[1]) === $keywordString - && $this->isKeywordContext($tokens, $i)) { - $tokens[$i][0] = $this->getKeywordToken(); - } - } - - return $tokens; - } - - /** - * @param mixed[] $tokens - * @return mixed[]|null - */ - private function getPreviousNonSpaceToken(array $tokens, int $start) - { - for ($i = $start - 1; $i >= 0; --$i) { - if ($tokens[$i][0] === T_WHITESPACE) { - continue; - } - - return $tokens[$i]; - } - - return null; - } - - public function reverseEmulate(string $code, array $tokens): array - { - $keywordToken = $this->getKeywordToken(); - foreach ($tokens as $i => $token) { - if ($token[0] === $keywordToken) { - $tokens[$i][0] = \T_STRING; - } - } - - return $tokens; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php b/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php deleted file mode 100644 index 902a46dfc..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Lexer\TokenEmulator; - -use PhpParser\Lexer\Emulative; - -final class MatchTokenEmulator extends KeywordEmulator -{ - public function getPhpVersion(): string - { - return Emulative::PHP_8_0; - } - - public function getKeywordString(): string - { - return 'match'; - } - - public function getKeywordToken(): int - { - return \T_MATCH; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php b/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php deleted file mode 100644 index 1a29c676e..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Lexer\TokenEmulator; - -use PhpParser\Lexer\Emulative; - -final class NullsafeTokenEmulator extends TokenEmulator -{ - public function getPhpVersion(): string - { - return Emulative::PHP_8_0; - } - - public function isEmulationNeeded(string $code): bool - { - return strpos($code, '?->') !== false; - } - - public function emulate(string $code, array $tokens): array - { - // We need to manually iterate and manage a count because we'll change - // the tokens array on the way - $line = 1; - for ($i = 0, $c = count($tokens); $i < $c; ++$i) { - if ($tokens[$i] === '?' && isset($tokens[$i + 1]) && $tokens[$i + 1][0] === \T_OBJECT_OPERATOR) { - array_splice($tokens, $i, 2, [ - [\T_NULLSAFE_OBJECT_OPERATOR, '?->', $line] - ]); - $c--; - continue; - } - - // Handle ?-> inside encapsed string. - if ($tokens[$i][0] === \T_ENCAPSED_AND_WHITESPACE && isset($tokens[$i - 1]) - && $tokens[$i - 1][0] === \T_VARIABLE - && preg_match('/^\?->([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)/', $tokens[$i][1], $matches) - ) { - $replacement = [ - [\T_NULLSAFE_OBJECT_OPERATOR, '?->', $line], - [\T_STRING, $matches[1], $line], - ]; - if (\strlen($matches[0]) !== \strlen($tokens[$i][1])) { - $replacement[] = [ - \T_ENCAPSED_AND_WHITESPACE, - \substr($tokens[$i][1], \strlen($matches[0])), - $line - ]; - } - array_splice($tokens, $i, 1, $replacement); - $c += \count($replacement) - 1; - continue; - } - - if (\is_array($tokens[$i])) { - $line += substr_count($tokens[$i][1], "\n"); - } - } - - return $tokens; - } - - public function reverseEmulate(string $code, array $tokens): array - { - // ?-> was not valid code previously, don't bother. - return $tokens; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php b/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php deleted file mode 100644 index cdf793e46..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php +++ /dev/null @@ -1,105 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Lexer\TokenEmulator; - -use PhpParser\Lexer\Emulative; - -final class NumericLiteralSeparatorEmulator extends TokenEmulator -{ - const BIN = '(?:0b[01]+(?:_[01]+)*)'; - const HEX = '(?:0x[0-9a-f]+(?:_[0-9a-f]+)*)'; - const DEC = '(?:[0-9]+(?:_[0-9]+)*)'; - const SIMPLE_FLOAT = '(?:' . self::DEC . '\.' . self::DEC . '?|\.' . self::DEC . ')'; - const EXP = '(?:e[+-]?' . self::DEC . ')'; - const FLOAT = '(?:' . self::SIMPLE_FLOAT . self::EXP . '?|' . self::DEC . self::EXP . ')'; - const NUMBER = '~' . self::FLOAT . '|' . self::BIN . '|' . self::HEX . '|' . self::DEC . '~iA'; - - public function getPhpVersion(): string - { - return Emulative::PHP_7_4; - } - - public function isEmulationNeeded(string $code) : bool - { - return preg_match('~[0-9]_[0-9]~', $code) - || preg_match('~0x[0-9a-f]+_[0-9a-f]~i', $code); - } - - public function emulate(string $code, array $tokens): array - { - // We need to manually iterate and manage a count because we'll change - // the tokens array on the way - $codeOffset = 0; - for ($i = 0, $c = count($tokens); $i < $c; ++$i) { - $token = $tokens[$i]; - $tokenLen = \strlen(\is_array($token) ? $token[1] : $token); - - if ($token[0] !== T_LNUMBER && $token[0] !== T_DNUMBER) { - $codeOffset += $tokenLen; - continue; - } - - $res = preg_match(self::NUMBER, $code, $matches, 0, $codeOffset); - assert($res, "No number at number token position"); - - $match = $matches[0]; - $matchLen = \strlen($match); - if ($matchLen === $tokenLen) { - // Original token already holds the full number. - $codeOffset += $tokenLen; - continue; - } - - $tokenKind = $this->resolveIntegerOrFloatToken($match); - $newTokens = [[$tokenKind, $match, $token[2]]]; - - $numTokens = 1; - $len = $tokenLen; - while ($matchLen > $len) { - $nextToken = $tokens[$i + $numTokens]; - $nextTokenText = \is_array($nextToken) ? $nextToken[1] : $nextToken; - $nextTokenLen = \strlen($nextTokenText); - - $numTokens++; - if ($matchLen < $len + $nextTokenLen) { - // Split trailing characters into a partial token. - assert(is_array($nextToken), "Partial token should be an array token"); - $partialText = substr($nextTokenText, $matchLen - $len); - $newTokens[] = [$nextToken[0], $partialText, $nextToken[2]]; - break; - } - - $len += $nextTokenLen; - } - - array_splice($tokens, $i, $numTokens, $newTokens); - $c -= $numTokens - \count($newTokens); - $codeOffset += $matchLen; - } - - return $tokens; - } - - private function resolveIntegerOrFloatToken(string $str): int - { - $str = str_replace('_', '', $str); - - if (stripos($str, '0b') === 0) { - $num = bindec($str); - } elseif (stripos($str, '0x') === 0) { - $num = hexdec($str); - } elseif (stripos($str, '0') === 0 && ctype_digit($str)) { - $num = octdec($str); - } else { - $num = +$str; - } - - return is_float($num) ? T_DNUMBER : T_LNUMBER; - } - - public function reverseEmulate(string $code, array $tokens): array - { - // Numeric separators were not legal code previously, don't bother. - return $tokens; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyTokenEmulator.php b/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyTokenEmulator.php deleted file mode 100644 index b97f8d112..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyTokenEmulator.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Lexer\TokenEmulator; - -use PhpParser\Lexer\Emulative; - -final class ReadonlyTokenEmulator extends KeywordEmulator -{ - public function getPhpVersion(): string - { - return Emulative::PHP_8_1; - } - - public function getKeywordString(): string - { - return 'readonly'; - } - - public function getKeywordToken(): int - { - return \T_READONLY; - } -} \ No newline at end of file diff --git a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.php b/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.php deleted file mode 100644 index 90093f66b..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Lexer\TokenEmulator; - -/** - * Reverses emulation direction of the inner emulator. - */ -final class ReverseEmulator extends TokenEmulator -{ - /** @var TokenEmulator Inner emulator */ - private $emulator; - - public function __construct(TokenEmulator $emulator) { - $this->emulator = $emulator; - } - - public function getPhpVersion(): string { - return $this->emulator->getPhpVersion(); - } - - public function isEmulationNeeded(string $code): bool { - return $this->emulator->isEmulationNeeded($code); - } - - public function emulate(string $code, array $tokens): array { - return $this->emulator->reverseEmulate($code, $tokens); - } - - public function reverseEmulate(string $code, array $tokens): array { - return $this->emulator->emulate($code, $tokens); - } - - public function preprocessCode(string $code, array &$patches): string { - return $code; - } -} \ No newline at end of file diff --git a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php b/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php deleted file mode 100644 index a020bc0ff..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Lexer\TokenEmulator; - -/** @internal */ -abstract class TokenEmulator -{ - abstract public function getPhpVersion(): string; - - abstract public function isEmulationNeeded(string $code): bool; - - /** - * @return array Modified Tokens - */ - abstract public function emulate(string $code, array $tokens): array; - - /** - * @return array Modified Tokens - */ - abstract public function reverseEmulate(string $code, array $tokens): array; - - public function preprocessCode(string $code, array &$patches): string { - return $code; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/NameContext.php b/lib/nikic/php-parser/lib/PhpParser/NameContext.php deleted file mode 100644 index 777a4afde..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/NameContext.php +++ /dev/null @@ -1,285 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser; - -use PhpParser\Node\Name; -use PhpParser\Node\Name\FullyQualified; -use PhpParser\Node\Stmt; - -class NameContext -{ - /** @var null|Name Current namespace */ - protected $namespace; - - /** @var Name[][] Map of format [aliasType => [aliasName => originalName]] */ - protected $aliases = []; - - /** @var Name[][] Same as $aliases but preserving original case */ - protected $origAliases = []; - - /** @var ErrorHandler Error handler */ - protected $errorHandler; - - /** - * Create a name context. - * - * @param ErrorHandler $errorHandler Error handling used to report errors - */ - public function __construct(ErrorHandler $errorHandler) { - $this->errorHandler = $errorHandler; - } - - /** - * Start a new namespace. - * - * This also resets the alias table. - * - * @param Name|null $namespace Null is the global namespace - */ - public function startNamespace(Name $namespace = null) { - $this->namespace = $namespace; - $this->origAliases = $this->aliases = [ - Stmt\Use_::TYPE_NORMAL => [], - Stmt\Use_::TYPE_FUNCTION => [], - Stmt\Use_::TYPE_CONSTANT => [], - ]; - } - - /** - * Add an alias / import. - * - * @param Name $name Original name - * @param string $aliasName Aliased name - * @param int $type One of Stmt\Use_::TYPE_* - * @param array $errorAttrs Attributes to use to report an error - */ - public function addAlias(Name $name, string $aliasName, int $type, array $errorAttrs = []) { - // Constant names are case sensitive, everything else case insensitive - if ($type === Stmt\Use_::TYPE_CONSTANT) { - $aliasLookupName = $aliasName; - } else { - $aliasLookupName = strtolower($aliasName); - } - - if (isset($this->aliases[$type][$aliasLookupName])) { - $typeStringMap = [ - Stmt\Use_::TYPE_NORMAL => '', - Stmt\Use_::TYPE_FUNCTION => 'function ', - Stmt\Use_::TYPE_CONSTANT => 'const ', - ]; - - $this->errorHandler->handleError(new Error( - sprintf( - 'Cannot use %s%s as %s because the name is already in use', - $typeStringMap[$type], $name, $aliasName - ), - $errorAttrs - )); - return; - } - - $this->aliases[$type][$aliasLookupName] = $name; - $this->origAliases[$type][$aliasName] = $name; - } - - /** - * Get current namespace. - * - * @return null|Name Namespace (or null if global namespace) - */ - public function getNamespace() { - return $this->namespace; - } - - /** - * Get resolved name. - * - * @param Name $name Name to resolve - * @param int $type One of Stmt\Use_::TYPE_{FUNCTION|CONSTANT} - * - * @return null|Name Resolved name, or null if static resolution is not possible - */ - public function getResolvedName(Name $name, int $type) { - // don't resolve special class names - if ($type === Stmt\Use_::TYPE_NORMAL && $name->isSpecialClassName()) { - if (!$name->isUnqualified()) { - $this->errorHandler->handleError(new Error( - sprintf("'\\%s' is an invalid class name", $name->toString()), - $name->getAttributes() - )); - } - return $name; - } - - // fully qualified names are already resolved - if ($name->isFullyQualified()) { - return $name; - } - - // Try to resolve aliases - if (null !== $resolvedName = $this->resolveAlias($name, $type)) { - return $resolvedName; - } - - if ($type !== Stmt\Use_::TYPE_NORMAL && $name->isUnqualified()) { - if (null === $this->namespace) { - // outside of a namespace unaliased unqualified is same as fully qualified - return new FullyQualified($name, $name->getAttributes()); - } - - // Cannot resolve statically - return null; - } - - // if no alias exists prepend current namespace - return FullyQualified::concat($this->namespace, $name, $name->getAttributes()); - } - - /** - * Get resolved class name. - * - * @param Name $name Class ame to resolve - * - * @return Name Resolved name - */ - public function getResolvedClassName(Name $name) : Name { - return $this->getResolvedName($name, Stmt\Use_::TYPE_NORMAL); - } - - /** - * Get possible ways of writing a fully qualified name (e.g., by making use of aliases). - * - * @param string $name Fully-qualified name (without leading namespace separator) - * @param int $type One of Stmt\Use_::TYPE_* - * - * @return Name[] Possible representations of the name - */ - public function getPossibleNames(string $name, int $type) : array { - $lcName = strtolower($name); - - if ($type === Stmt\Use_::TYPE_NORMAL) { - // self, parent and static must always be unqualified - if ($lcName === "self" || $lcName === "parent" || $lcName === "static") { - return [new Name($name)]; - } - } - - // Collect possible ways to write this name, starting with the fully-qualified name - $possibleNames = [new FullyQualified($name)]; - - if (null !== $nsRelativeName = $this->getNamespaceRelativeName($name, $lcName, $type)) { - // Make sure there is no alias that makes the normally namespace-relative name - // into something else - if (null === $this->resolveAlias($nsRelativeName, $type)) { - $possibleNames[] = $nsRelativeName; - } - } - - // Check for relevant namespace use statements - foreach ($this->origAliases[Stmt\Use_::TYPE_NORMAL] as $alias => $orig) { - $lcOrig = $orig->toLowerString(); - if (0 === strpos($lcName, $lcOrig . '\\')) { - $possibleNames[] = new Name($alias . substr($name, strlen($lcOrig))); - } - } - - // Check for relevant type-specific use statements - foreach ($this->origAliases[$type] as $alias => $orig) { - if ($type === Stmt\Use_::TYPE_CONSTANT) { - // Constants are are complicated-sensitive - $normalizedOrig = $this->normalizeConstName($orig->toString()); - if ($normalizedOrig === $this->normalizeConstName($name)) { - $possibleNames[] = new Name($alias); - } - } else { - // Everything else is case-insensitive - if ($orig->toLowerString() === $lcName) { - $possibleNames[] = new Name($alias); - } - } - } - - return $possibleNames; - } - - /** - * Get shortest representation of this fully-qualified name. - * - * @param string $name Fully-qualified name (without leading namespace separator) - * @param int $type One of Stmt\Use_::TYPE_* - * - * @return Name Shortest representation - */ - public function getShortName(string $name, int $type) : Name { - $possibleNames = $this->getPossibleNames($name, $type); - - // Find shortest name - $shortestName = null; - $shortestLength = \INF; - foreach ($possibleNames as $possibleName) { - $length = strlen($possibleName->toCodeString()); - if ($length < $shortestLength) { - $shortestName = $possibleName; - $shortestLength = $length; - } - } - - return $shortestName; - } - - private function resolveAlias(Name $name, $type) { - $firstPart = $name->getFirst(); - - if ($name->isQualified()) { - // resolve aliases for qualified names, always against class alias table - $checkName = strtolower($firstPart); - if (isset($this->aliases[Stmt\Use_::TYPE_NORMAL][$checkName])) { - $alias = $this->aliases[Stmt\Use_::TYPE_NORMAL][$checkName]; - return FullyQualified::concat($alias, $name->slice(1), $name->getAttributes()); - } - } elseif ($name->isUnqualified()) { - // constant aliases are case-sensitive, function aliases case-insensitive - $checkName = $type === Stmt\Use_::TYPE_CONSTANT ? $firstPart : strtolower($firstPart); - if (isset($this->aliases[$type][$checkName])) { - // resolve unqualified aliases - return new FullyQualified($this->aliases[$type][$checkName], $name->getAttributes()); - } - } - - // No applicable aliases - return null; - } - - private function getNamespaceRelativeName(string $name, string $lcName, int $type) { - if (null === $this->namespace) { - return new Name($name); - } - - if ($type === Stmt\Use_::TYPE_CONSTANT) { - // The constants true/false/null always resolve to the global symbols, even inside a - // namespace, so they may be used without qualification - if ($lcName === "true" || $lcName === "false" || $lcName === "null") { - return new Name($name); - } - } - - $namespacePrefix = strtolower($this->namespace . '\\'); - if (0 === strpos($lcName, $namespacePrefix)) { - return new Name(substr($name, strlen($namespacePrefix))); - } - - return null; - } - - private function normalizeConstName(string $name) { - $nsSep = strrpos($name, '\\'); - if (false === $nsSep) { - return $name; - } - - // Constants have case-insensitive namespace and case-sensitive short-name - $ns = substr($name, 0, $nsSep); - $shortName = substr($name, $nsSep + 1); - return strtolower($ns) . '\\' . $shortName; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node.php b/lib/nikic/php-parser/lib/PhpParser/Node.php deleted file mode 100644 index befb25650..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node.php +++ /dev/null @@ -1,151 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser; - -interface Node -{ - /** - * Gets the type of the node. - * - * @return string Type of the node - */ - public function getType() : string; - - /** - * Gets the names of the sub nodes. - * - * @return array Names of sub nodes - */ - public function getSubNodeNames() : array; - - /** - * Gets line the node started in (alias of getStartLine). - * - * @return int Start line (or -1 if not available) - */ - public function getLine() : int; - - /** - * Gets line the node started in. - * - * Requires the 'startLine' attribute to be enabled in the lexer (enabled by default). - * - * @return int Start line (or -1 if not available) - */ - public function getStartLine() : int; - - /** - * Gets the line the node ended in. - * - * Requires the 'endLine' attribute to be enabled in the lexer (enabled by default). - * - * @return int End line (or -1 if not available) - */ - public function getEndLine() : int; - - /** - * Gets the token offset of the first token that is part of this node. - * - * The offset is an index into the array returned by Lexer::getTokens(). - * - * Requires the 'startTokenPos' attribute to be enabled in the lexer (DISABLED by default). - * - * @return int Token start position (or -1 if not available) - */ - public function getStartTokenPos() : int; - - /** - * Gets the token offset of the last token that is part of this node. - * - * The offset is an index into the array returned by Lexer::getTokens(). - * - * Requires the 'endTokenPos' attribute to be enabled in the lexer (DISABLED by default). - * - * @return int Token end position (or -1 if not available) - */ - public function getEndTokenPos() : int; - - /** - * Gets the file offset of the first character that is part of this node. - * - * Requires the 'startFilePos' attribute to be enabled in the lexer (DISABLED by default). - * - * @return int File start position (or -1 if not available) - */ - public function getStartFilePos() : int; - - /** - * Gets the file offset of the last character that is part of this node. - * - * Requires the 'endFilePos' attribute to be enabled in the lexer (DISABLED by default). - * - * @return int File end position (or -1 if not available) - */ - public function getEndFilePos() : int; - - /** - * Gets all comments directly preceding this node. - * - * The comments are also available through the "comments" attribute. - * - * @return Comment[] - */ - public function getComments() : array; - - /** - * Gets the doc comment of the node. - * - * @return null|Comment\Doc Doc comment object or null - */ - public function getDocComment(); - - /** - * Sets the doc comment of the node. - * - * This will either replace an existing doc comment or add it to the comments array. - * - * @param Comment\Doc $docComment Doc comment to set - */ - public function setDocComment(Comment\Doc $docComment); - - /** - * Sets an attribute on a node. - * - * @param string $key - * @param mixed $value - */ - public function setAttribute(string $key, $value); - - /** - * Returns whether an attribute exists. - * - * @param string $key - * - * @return bool - */ - public function hasAttribute(string $key) : bool; - - /** - * Returns the value of an attribute. - * - * @param string $key - * @param mixed $default - * - * @return mixed - */ - public function getAttribute(string $key, $default = null); - - /** - * Returns all the attributes of this node. - * - * @return array - */ - public function getAttributes() : array; - - /** - * Replaces all the attributes of this node. - * - * @param array $attributes - */ - public function setAttributes(array $attributes); -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Arg.php b/lib/nikic/php-parser/lib/PhpParser/Node/Arg.php deleted file mode 100644 index bcf130e68..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Arg.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node; - -use PhpParser\Node\VariadicPlaceholder; -use PhpParser\NodeAbstract; - -class Arg extends NodeAbstract -{ - /** @var Identifier|null Parameter name (for named parameters) */ - public $name; - /** @var Expr Value to pass */ - public $value; - /** @var bool Whether to pass by ref */ - public $byRef; - /** @var bool Whether to unpack the argument */ - public $unpack; - - /** - * Constructs a function call argument node. - * - * @param Expr $value Value to pass - * @param bool $byRef Whether to pass by ref - * @param bool $unpack Whether to unpack the argument - * @param array $attributes Additional attributes - * @param Identifier|null $name Parameter name (for named parameters) - */ - public function __construct( - Expr $value, bool $byRef = false, bool $unpack = false, array $attributes = [], - Identifier $name = null - ) { - $this->attributes = $attributes; - $this->name = $name; - $this->value = $value; - $this->byRef = $byRef; - $this->unpack = $unpack; - } - - public function getSubNodeNames() : array { - return ['name', 'value', 'byRef', 'unpack']; - } - - public function getType() : string { - return 'Arg'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Attribute.php b/lib/nikic/php-parser/lib/PhpParser/Node/Attribute.php deleted file mode 100644 index c96f66e51..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Attribute.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node; - -use PhpParser\Node; -use PhpParser\NodeAbstract; - -class Attribute extends NodeAbstract -{ - /** @var Name Attribute name */ - public $name; - - /** @var Arg[] Attribute arguments */ - public $args; - - /** - * @param Node\Name $name Attribute name - * @param Arg[] $args Attribute arguments - * @param array $attributes Additional node attributes - */ - public function __construct(Name $name, array $args = [], array $attributes = []) { - $this->attributes = $attributes; - $this->name = $name; - $this->args = $args; - } - - public function getSubNodeNames() : array { - return ['name', 'args']; - } - - public function getType() : string { - return 'Attribute'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php b/lib/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php deleted file mode 100644 index 613bfc413..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node; - -use PhpParser\Node; -use PhpParser\NodeAbstract; - -class AttributeGroup extends NodeAbstract -{ - /** @var Attribute[] Attributes */ - public $attrs; - - /** - * @param Attribute[] $attrs PHP attributes - * @param array $attributes Additional node attributes - */ - public function __construct(array $attrs, array $attributes = []) { - $this->attributes = $attributes; - $this->attrs = $attrs; - } - - public function getSubNodeNames() : array { - return ['attrs']; - } - - public function getType() : string { - return 'AttributeGroup'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/ComplexType.php b/lib/nikic/php-parser/lib/PhpParser/Node/ComplexType.php deleted file mode 100644 index 9505532ae..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/ComplexType.php +++ /dev/null @@ -1,14 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node; - -use PhpParser\NodeAbstract; - -/** - * This is a base class for complex types, including nullable types and union types. - * - * It does not provide any shared behavior and exists only for type-checking purposes. - */ -abstract class ComplexType extends NodeAbstract -{ -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Const_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Const_.php deleted file mode 100644 index 07a74df80..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Const_.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node; - -use PhpParser\NodeAbstract; - -class Const_ extends NodeAbstract -{ - /** @var Identifier Name */ - public $name; - /** @var Expr Value */ - public $value; - - /** @var Name|null Namespaced name (if using NameResolver) */ - public $namespacedName; - - /** - * Constructs a const node for use in class const and const statements. - * - * @param string|Identifier $name Name - * @param Expr $value Value - * @param array $attributes Additional attributes - */ - public function __construct($name, Expr $value, array $attributes = []) { - $this->attributes = $attributes; - $this->name = \is_string($name) ? new Identifier($name) : $name; - $this->value = $value; - } - - public function getSubNodeNames() : array { - return ['name', 'value']; - } - - public function getType() : string { - return 'Const'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr.php deleted file mode 100644 index 6cf4df223..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node; - -use PhpParser\NodeAbstract; - -abstract class Expr extends NodeAbstract -{ -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php deleted file mode 100644 index 71694478e..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class ArrayDimFetch extends Expr -{ - /** @var Expr Variable */ - public $var; - /** @var null|Expr Array index / dim */ - public $dim; - - /** - * Constructs an array index fetch node. - * - * @param Expr $var Variable - * @param null|Expr $dim Array index / dim - * @param array $attributes Additional attributes - */ - public function __construct(Expr $var, Expr $dim = null, array $attributes = []) { - $this->attributes = $attributes; - $this->var = $var; - $this->dim = $dim; - } - - public function getSubNodeNames() : array { - return ['var', 'dim']; - } - - public function getType() : string { - return 'Expr_ArrayDimFetch'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php deleted file mode 100644 index 1b078f821..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class ArrayItem extends Expr -{ - /** @var null|Expr Key */ - public $key; - /** @var Expr Value */ - public $value; - /** @var bool Whether to assign by reference */ - public $byRef; - /** @var bool Whether to unpack the argument */ - public $unpack; - - /** - * Constructs an array item node. - * - * @param Expr $value Value - * @param null|Expr $key Key - * @param bool $byRef Whether to assign by reference - * @param array $attributes Additional attributes - */ - public function __construct(Expr $value, Expr $key = null, bool $byRef = false, array $attributes = [], bool $unpack = false) { - $this->attributes = $attributes; - $this->key = $key; - $this->value = $value; - $this->byRef = $byRef; - $this->unpack = $unpack; - } - - public function getSubNodeNames() : array { - return ['key', 'value', 'byRef', 'unpack']; - } - - public function getType() : string { - return 'Expr_ArrayItem'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php deleted file mode 100644 index e6eaa2834..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class Array_ extends Expr -{ - // For use in "kind" attribute - const KIND_LONG = 1; // array() syntax - const KIND_SHORT = 2; // [] syntax - - /** @var (ArrayItem|null)[] Items */ - public $items; - - /** - * Constructs an array node. - * - * @param (ArrayItem|null)[] $items Items of the array - * @param array $attributes Additional attributes - */ - public function __construct(array $items = [], array $attributes = []) { - $this->attributes = $attributes; - $this->items = $items; - } - - public function getSubNodeNames() : array { - return ['items']; - } - - public function getType() : string { - return 'Expr_Array'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php deleted file mode 100644 index c273fb7ee..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php +++ /dev/null @@ -1,79 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node; -use PhpParser\Node\Expr; -use PhpParser\Node\FunctionLike; - -class ArrowFunction extends Expr implements FunctionLike -{ - /** @var bool */ - public $static; - - /** @var bool */ - public $byRef; - - /** @var Node\Param[] */ - public $params = []; - - /** @var null|Node\Identifier|Node\Name|Node\ComplexType */ - public $returnType; - - /** @var Expr */ - public $expr; - /** @var Node\AttributeGroup[] */ - public $attrGroups; - - /** - * @param array $subNodes Array of the following optional subnodes: - * 'static' => false : Whether the closure is static - * 'byRef' => false : Whether to return by reference - * 'params' => array() : Parameters - * 'returnType' => null : Return type - * 'expr' => Expr : Expression body - * 'attrGroups' => array() : PHP attribute groups - * @param array $attributes Additional attributes - */ - public function __construct(array $subNodes = [], array $attributes = []) { - $this->attributes = $attributes; - $this->static = $subNodes['static'] ?? false; - $this->byRef = $subNodes['byRef'] ?? false; - $this->params = $subNodes['params'] ?? []; - $returnType = $subNodes['returnType'] ?? null; - $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType; - $this->expr = $subNodes['expr']; - $this->attrGroups = $subNodes['attrGroups'] ?? []; - } - - public function getSubNodeNames() : array { - return ['attrGroups', 'static', 'byRef', 'params', 'returnType', 'expr']; - } - - public function returnsByRef() : bool { - return $this->byRef; - } - - public function getParams() : array { - return $this->params; - } - - public function getReturnType() { - return $this->returnType; - } - - public function getAttrGroups() : array { - return $this->attrGroups; - } - - /** - * @return Node\Stmt\Return_[] - */ - public function getStmts() : array { - return [new Node\Stmt\Return_($this->expr)]; - } - - public function getType() : string { - return 'Expr_ArrowFunction'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php deleted file mode 100644 index cf9e6e82b..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class Assign extends Expr -{ - /** @var Expr Variable */ - public $var; - /** @var Expr Expression */ - public $expr; - - /** - * Constructs an assignment node. - * - * @param Expr $var Variable - * @param Expr $expr Expression - * @param array $attributes Additional attributes - */ - public function __construct(Expr $var, Expr $expr, array $attributes = []) { - $this->attributes = $attributes; - $this->var = $var; - $this->expr = $expr; - } - - public function getSubNodeNames() : array { - return ['var', 'expr']; - } - - public function getType() : string { - return 'Expr_Assign'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php deleted file mode 100644 index bce8604f1..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -abstract class AssignOp extends Expr -{ - /** @var Expr Variable */ - public $var; - /** @var Expr Expression */ - public $expr; - - /** - * Constructs a compound assignment operation node. - * - * @param Expr $var Variable - * @param Expr $expr Expression - * @param array $attributes Additional attributes - */ - public function __construct(Expr $var, Expr $expr, array $attributes = []) { - $this->attributes = $attributes; - $this->var = $var; - $this->expr = $expr; - } - - public function getSubNodeNames() : array { - return ['var', 'expr']; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php deleted file mode 100644 index 420284cdc..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\AssignOp; - -use PhpParser\Node\Expr\AssignOp; - -class BitwiseAnd extends AssignOp -{ - public function getType() : string { - return 'Expr_AssignOp_BitwiseAnd'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php deleted file mode 100644 index 481ad3bbc..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\AssignOp; - -use PhpParser\Node\Expr\AssignOp; - -class BitwiseOr extends AssignOp -{ - public function getType() : string { - return 'Expr_AssignOp_BitwiseOr'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php deleted file mode 100644 index f41d4c8e7..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\AssignOp; - -use PhpParser\Node\Expr\AssignOp; - -class BitwiseXor extends AssignOp -{ - public function getType() : string { - return 'Expr_AssignOp_BitwiseXor'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Coalesce.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Coalesce.php deleted file mode 100644 index c0e9b316c..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Coalesce.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\AssignOp; - -use PhpParser\Node\Expr\AssignOp; - -class Coalesce extends AssignOp -{ - public function getType() : string { - return 'Expr_AssignOp_Coalesce'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.php deleted file mode 100644 index ac1682078..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\AssignOp; - -use PhpParser\Node\Expr\AssignOp; - -class Concat extends AssignOp -{ - public function getType() : string { - return 'Expr_AssignOp_Concat'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.php deleted file mode 100644 index f1fcfc09a..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\AssignOp; - -use PhpParser\Node\Expr\AssignOp; - -class Div extends AssignOp -{ - public function getType() : string { - return 'Expr_AssignOp_Div'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.php deleted file mode 100644 index 82ef4517b..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\AssignOp; - -use PhpParser\Node\Expr\AssignOp; - -class Minus extends AssignOp -{ - public function getType() : string { - return 'Expr_AssignOp_Minus'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.php deleted file mode 100644 index be3b4a0ad..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\AssignOp; - -use PhpParser\Node\Expr\AssignOp; - -class Mod extends AssignOp -{ - public function getType() : string { - return 'Expr_AssignOp_Mod'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.php deleted file mode 100644 index 5c196c3bc..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\AssignOp; - -use PhpParser\Node\Expr\AssignOp; - -class Mul extends AssignOp -{ - public function getType() : string { - return 'Expr_AssignOp_Mul'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.php deleted file mode 100644 index dd101c61c..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\AssignOp; - -use PhpParser\Node\Expr\AssignOp; - -class Plus extends AssignOp -{ - public function getType() : string { - return 'Expr_AssignOp_Plus'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.php deleted file mode 100644 index 5e1307d1d..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\AssignOp; - -use PhpParser\Node\Expr\AssignOp; - -class Pow extends AssignOp -{ - public function getType() : string { - return 'Expr_AssignOp_Pow'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php deleted file mode 100644 index b8f88269b..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\AssignOp; - -use PhpParser\Node\Expr\AssignOp; - -class ShiftLeft extends AssignOp -{ - public function getType() : string { - return 'Expr_AssignOp_ShiftLeft'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php deleted file mode 100644 index e0cc67b7f..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\AssignOp; - -use PhpParser\Node\Expr\AssignOp; - -class ShiftRight extends AssignOp -{ - public function getType() : string { - return 'Expr_AssignOp_ShiftRight'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignRef.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignRef.php deleted file mode 100644 index de3c644c3..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/AssignRef.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class AssignRef extends Expr -{ - /** @var Expr Variable reference is assigned to */ - public $var; - /** @var Expr Variable which is referenced */ - public $expr; - - /** - * Constructs an assignment node. - * - * @param Expr $var Variable - * @param Expr $expr Expression - * @param array $attributes Additional attributes - */ - public function __construct(Expr $var, Expr $expr, array $attributes = []) { - $this->attributes = $attributes; - $this->var = $var; - $this->expr = $expr; - } - - public function getSubNodeNames() : array { - return ['var', 'expr']; - } - - public function getType() : string { - return 'Expr_AssignRef'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php deleted file mode 100644 index d9c582b0d..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -abstract class BinaryOp extends Expr -{ - /** @var Expr The left hand side expression */ - public $left; - /** @var Expr The right hand side expression */ - public $right; - - /** - * Constructs a binary operator node. - * - * @param Expr $left The left hand side expression - * @param Expr $right The right hand side expression - * @param array $attributes Additional attributes - */ - public function __construct(Expr $left, Expr $right, array $attributes = []) { - $this->attributes = $attributes; - $this->left = $left; - $this->right = $right; - } - - public function getSubNodeNames() : array { - return ['left', 'right']; - } - - /** - * Get the operator sigil for this binary operation. - * - * In the case there are multiple possible sigils for an operator, this method does not - * necessarily return the one used in the parsed code. - * - * @return string - */ - abstract public function getOperatorSigil() : string; -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php deleted file mode 100644 index d907393bf..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class BitwiseAnd extends BinaryOp -{ - public function getOperatorSigil() : string { - return '&'; - } - - public function getType() : string { - return 'Expr_BinaryOp_BitwiseAnd'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php deleted file mode 100644 index d92069f32..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class BitwiseOr extends BinaryOp -{ - public function getOperatorSigil() : string { - return '|'; - } - - public function getType() : string { - return 'Expr_BinaryOp_BitwiseOr'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php deleted file mode 100644 index 40fa94f88..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class BitwiseXor extends BinaryOp -{ - public function getOperatorSigil() : string { - return '^'; - } - - public function getType() : string { - return 'Expr_BinaryOp_BitwiseXor'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php deleted file mode 100644 index 4c3c9e9b1..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class BooleanAnd extends BinaryOp -{ - public function getOperatorSigil() : string { - return '&&'; - } - - public function getType() : string { - return 'Expr_BinaryOp_BooleanAnd'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php deleted file mode 100644 index 5ad417279..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class BooleanOr extends BinaryOp -{ - public function getOperatorSigil() : string { - return '||'; - } - - public function getType() : string { - return 'Expr_BinaryOp_BooleanOr'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php deleted file mode 100644 index b8cf6f459..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class Coalesce extends BinaryOp -{ - public function getOperatorSigil() : string { - return '??'; - } - - public function getType() : string { - return 'Expr_BinaryOp_Coalesce'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.php deleted file mode 100644 index 9a8d9873c..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class Concat extends BinaryOp -{ - public function getOperatorSigil() : string { - return '.'; - } - - public function getType() : string { - return 'Expr_BinaryOp_Concat'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.php deleted file mode 100644 index d38df0db4..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class Div extends BinaryOp -{ - public function getOperatorSigil() : string { - return '/'; - } - - public function getType() : string { - return 'Expr_BinaryOp_Div'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.php deleted file mode 100644 index e7b11dc82..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class Equal extends BinaryOp -{ - public function getOperatorSigil() : string { - return '=='; - } - - public function getType() : string { - return 'Expr_BinaryOp_Equal'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.php deleted file mode 100644 index da01f7a10..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class Greater extends BinaryOp -{ - public function getOperatorSigil() : string { - return '>'; - } - - public function getType() : string { - return 'Expr_BinaryOp_Greater'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php deleted file mode 100644 index d677502cf..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class GreaterOrEqual extends BinaryOp -{ - public function getOperatorSigil() : string { - return '>='; - } - - public function getType() : string { - return 'Expr_BinaryOp_GreaterOrEqual'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php deleted file mode 100644 index 3d96285c6..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class Identical extends BinaryOp -{ - public function getOperatorSigil() : string { - return '==='; - } - - public function getType() : string { - return 'Expr_BinaryOp_Identical'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php deleted file mode 100644 index 2a3afd548..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class LogicalAnd extends BinaryOp -{ - public function getOperatorSigil() : string { - return 'and'; - } - - public function getType() : string { - return 'Expr_BinaryOp_LogicalAnd'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php deleted file mode 100644 index 21507dba6..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class LogicalOr extends BinaryOp -{ - public function getOperatorSigil() : string { - return 'or'; - } - - public function getType() : string { - return 'Expr_BinaryOp_LogicalOr'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php deleted file mode 100644 index 261c6a910..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class LogicalXor extends BinaryOp -{ - public function getOperatorSigil() : string { - return 'xor'; - } - - public function getType() : string { - return 'Expr_BinaryOp_LogicalXor'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.php deleted file mode 100644 index 54b3c6e90..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class Minus extends BinaryOp -{ - public function getOperatorSigil() : string { - return '-'; - } - - public function getType() : string { - return 'Expr_BinaryOp_Minus'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.php deleted file mode 100644 index 103404040..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class Mod extends BinaryOp -{ - public function getOperatorSigil() : string { - return '%'; - } - - public function getType() : string { - return 'Expr_BinaryOp_Mod'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.php deleted file mode 100644 index b82d0b2fc..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class Mul extends BinaryOp -{ - public function getOperatorSigil() : string { - return '*'; - } - - public function getType() : string { - return 'Expr_BinaryOp_Mul'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php deleted file mode 100644 index 51075da56..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class NotEqual extends BinaryOp -{ - public function getOperatorSigil() : string { - return '!='; - } - - public function getType() : string { - return 'Expr_BinaryOp_NotEqual'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php deleted file mode 100644 index fa4050e05..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class NotIdentical extends BinaryOp -{ - public function getOperatorSigil() : string { - return '!=='; - } - - public function getType() : string { - return 'Expr_BinaryOp_NotIdentical'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.php deleted file mode 100644 index 62f022998..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class Plus extends BinaryOp -{ - public function getOperatorSigil() : string { - return '+'; - } - - public function getType() : string { - return 'Expr_BinaryOp_Plus'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.php deleted file mode 100644 index 572a1e8e4..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class Pow extends BinaryOp -{ - public function getOperatorSigil() : string { - return '**'; - } - - public function getType() : string { - return 'Expr_BinaryOp_Pow'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php deleted file mode 100644 index 4e70b4ef0..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class ShiftLeft extends BinaryOp -{ - public function getOperatorSigil() : string { - return '<<'; - } - - public function getType() : string { - return 'Expr_BinaryOp_ShiftLeft'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php deleted file mode 100644 index 45acbd046..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class ShiftRight extends BinaryOp -{ - public function getOperatorSigil() : string { - return '>>'; - } - - public function getType() : string { - return 'Expr_BinaryOp_ShiftRight'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php deleted file mode 100644 index 3cb8e7e0d..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class Smaller extends BinaryOp -{ - public function getOperatorSigil() : string { - return '<'; - } - - public function getType() : string { - return 'Expr_BinaryOp_Smaller'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php deleted file mode 100644 index 83e8e214d..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class SmallerOrEqual extends BinaryOp -{ - public function getOperatorSigil() : string { - return '<='; - } - - public function getType() : string { - return 'Expr_BinaryOp_SmallerOrEqual'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php deleted file mode 100644 index 8c6d787f6..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\BinaryOp; - -use PhpParser\Node\Expr\BinaryOp; - -class Spaceship extends BinaryOp -{ - public function getOperatorSigil() : string { - return '<=>'; - } - - public function getType() : string { - return 'Expr_BinaryOp_Spaceship'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php deleted file mode 100644 index ed44984be..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class BitwiseNot extends Expr -{ - /** @var Expr Expression */ - public $expr; - - /** - * Constructs a bitwise not node. - * - * @param Expr $expr Expression - * @param array $attributes Additional attributes - */ - public function __construct(Expr $expr, array $attributes = []) { - $this->attributes = $attributes; - $this->expr = $expr; - } - - public function getSubNodeNames() : array { - return ['expr']; - } - - public function getType() : string { - return 'Expr_BitwiseNot'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php deleted file mode 100644 index bf27e9f65..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class BooleanNot extends Expr -{ - /** @var Expr Expression */ - public $expr; - - /** - * Constructs a boolean not node. - * - * @param Expr $expr Expression - * @param array $attributes Additional attributes - */ - public function __construct(Expr $expr, array $attributes = []) { - $this->attributes = $attributes; - $this->expr = $expr; - } - - public function getSubNodeNames() : array { - return ['expr']; - } - - public function getType() : string { - return 'Expr_BooleanNot'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/CallLike.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/CallLike.php deleted file mode 100644 index 78e1cf349..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/CallLike.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Arg; -use PhpParser\Node\Expr; -use PhpParser\Node\VariadicPlaceholder; - -abstract class CallLike extends Expr { - /** - * Return raw arguments, which may be actual Args, or VariadicPlaceholders for first-class - * callables. - * - * @return array<Arg|VariadicPlaceholder> - */ - abstract public function getRawArgs(): array; - - /** - * Returns whether this call expression is actually a first class callable. - */ - public function isFirstClassCallable(): bool { - foreach ($this->getRawArgs() as $arg) { - if ($arg instanceof VariadicPlaceholder) { - return true; - } - } - return false; - } - - /** - * Assert that this is not a first-class callable and return only ordinary Args. - * - * @return Arg[] - */ - public function getArgs(): array { - assert(!$this->isFirstClassCallable()); - return $this->getRawArgs(); - } -} \ No newline at end of file diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php deleted file mode 100644 index 36769d4fc..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -abstract class Cast extends Expr -{ - /** @var Expr Expression */ - public $expr; - - /** - * Constructs a cast node. - * - * @param Expr $expr Expression - * @param array $attributes Additional attributes - */ - public function __construct(Expr $expr, array $attributes = []) { - $this->attributes = $attributes; - $this->expr = $expr; - } - - public function getSubNodeNames() : array { - return ['expr']; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php deleted file mode 100644 index 57cc473b6..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\Cast; - -use PhpParser\Node\Expr\Cast; - -class Array_ extends Cast -{ - public function getType() : string { - return 'Expr_Cast_Array'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php deleted file mode 100644 index 04eb4af58..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\Cast; - -use PhpParser\Node\Expr\Cast; - -class Bool_ extends Cast -{ - public function getType() : string { - return 'Expr_Cast_Bool'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Double.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Double.php deleted file mode 100644 index 891ba5f87..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Double.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\Cast; - -use PhpParser\Node\Expr\Cast; - -class Double extends Cast -{ - // For use in "kind" attribute - const KIND_DOUBLE = 1; // "double" syntax - const KIND_FLOAT = 2; // "float" syntax - const KIND_REAL = 3; // "real" syntax - - public function getType() : string { - return 'Expr_Cast_Double'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.php deleted file mode 100644 index 01ed594bd..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\Cast; - -use PhpParser\Node\Expr\Cast; - -class Int_ extends Cast -{ - public function getType() : string { - return 'Expr_Cast_Int'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.php deleted file mode 100644 index 163752be8..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\Cast; - -use PhpParser\Node\Expr\Cast; - -class Object_ extends Cast -{ - public function getType() : string { - return 'Expr_Cast_Object'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/String_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/String_.php deleted file mode 100644 index b3d99270a..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/String_.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\Cast; - -use PhpParser\Node\Expr\Cast; - -class String_ extends Cast -{ - public function getType() : string { - return 'Expr_Cast_String'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.php deleted file mode 100644 index accda3e4f..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr\Cast; - -use PhpParser\Node\Expr\Cast; - -class Unset_ extends Cast -{ - public function getType() : string { - return 'Expr_Cast_Unset'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php deleted file mode 100644 index faf832f93..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; -use PhpParser\Node\Identifier; -use PhpParser\Node\Name; - -class ClassConstFetch extends Expr -{ - /** @var Name|Expr Class name */ - public $class; - /** @var Identifier|Error Constant name */ - public $name; - - /** - * Constructs a class const fetch node. - * - * @param Name|Expr $class Class name - * @param string|Identifier|Error $name Constant name - * @param array $attributes Additional attributes - */ - public function __construct($class, $name, array $attributes = []) { - $this->attributes = $attributes; - $this->class = $class; - $this->name = \is_string($name) ? new Identifier($name) : $name; - } - - public function getSubNodeNames() : array { - return ['class', 'name']; - } - - public function getType() : string { - return 'Expr_ClassConstFetch'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php deleted file mode 100644 index db216b8f8..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class Clone_ extends Expr -{ - /** @var Expr Expression */ - public $expr; - - /** - * Constructs a clone node. - * - * @param Expr $expr Expression - * @param array $attributes Additional attributes - */ - public function __construct(Expr $expr, array $attributes = []) { - $this->attributes = $attributes; - $this->expr = $expr; - } - - public function getSubNodeNames() : array { - return ['expr']; - } - - public function getType() : string { - return 'Expr_Clone'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php deleted file mode 100644 index 56ddea6aa..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php +++ /dev/null @@ -1,79 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node; -use PhpParser\Node\Expr; -use PhpParser\Node\FunctionLike; - -class Closure extends Expr implements FunctionLike -{ - /** @var bool Whether the closure is static */ - public $static; - /** @var bool Whether to return by reference */ - public $byRef; - /** @var Node\Param[] Parameters */ - public $params; - /** @var ClosureUse[] use()s */ - public $uses; - /** @var null|Node\Identifier|Node\Name|Node\ComplexType Return type */ - public $returnType; - /** @var Node\Stmt[] Statements */ - public $stmts; - /** @var Node\AttributeGroup[] PHP attribute groups */ - public $attrGroups; - - /** - * Constructs a lambda function node. - * - * @param array $subNodes Array of the following optional subnodes: - * 'static' => false : Whether the closure is static - * 'byRef' => false : Whether to return by reference - * 'params' => array(): Parameters - * 'uses' => array(): use()s - * 'returnType' => null : Return type - * 'stmts' => array(): Statements - * 'attrGroups' => array(): PHP attributes groups - * @param array $attributes Additional attributes - */ - public function __construct(array $subNodes = [], array $attributes = []) { - $this->attributes = $attributes; - $this->static = $subNodes['static'] ?? false; - $this->byRef = $subNodes['byRef'] ?? false; - $this->params = $subNodes['params'] ?? []; - $this->uses = $subNodes['uses'] ?? []; - $returnType = $subNodes['returnType'] ?? null; - $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType; - $this->stmts = $subNodes['stmts'] ?? []; - $this->attrGroups = $subNodes['attrGroups'] ?? []; - } - - public function getSubNodeNames() : array { - return ['attrGroups', 'static', 'byRef', 'params', 'uses', 'returnType', 'stmts']; - } - - public function returnsByRef() : bool { - return $this->byRef; - } - - public function getParams() : array { - return $this->params; - } - - public function getReturnType() { - return $this->returnType; - } - - /** @return Node\Stmt[] */ - public function getStmts() : array { - return $this->stmts; - } - - public function getAttrGroups() : array { - return $this->attrGroups; - } - - public function getType() : string { - return 'Expr_Closure'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php deleted file mode 100644 index 2b8a09666..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class ClosureUse extends Expr -{ - /** @var Expr\Variable Variable to use */ - public $var; - /** @var bool Whether to use by reference */ - public $byRef; - - /** - * Constructs a closure use node. - * - * @param Expr\Variable $var Variable to use - * @param bool $byRef Whether to use by reference - * @param array $attributes Additional attributes - */ - public function __construct(Expr\Variable $var, bool $byRef = false, array $attributes = []) { - $this->attributes = $attributes; - $this->var = $var; - $this->byRef = $byRef; - } - - public function getSubNodeNames() : array { - return ['var', 'byRef']; - } - - public function getType() : string { - return 'Expr_ClosureUse'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php deleted file mode 100644 index 14ebd16bd..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; -use PhpParser\Node\Name; - -class ConstFetch extends Expr -{ - /** @var Name Constant name */ - public $name; - - /** - * Constructs a const fetch node. - * - * @param Name $name Constant name - * @param array $attributes Additional attributes - */ - public function __construct(Name $name, array $attributes = []) { - $this->attributes = $attributes; - $this->name = $name; - } - - public function getSubNodeNames() : array { - return ['name']; - } - - public function getType() : string { - return 'Expr_ConstFetch'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php deleted file mode 100644 index 4042ec93c..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class Empty_ extends Expr -{ - /** @var Expr Expression */ - public $expr; - - /** - * Constructs an empty() node. - * - * @param Expr $expr Expression - * @param array $attributes Additional attributes - */ - public function __construct(Expr $expr, array $attributes = []) { - $this->attributes = $attributes; - $this->expr = $expr; - } - - public function getSubNodeNames() : array { - return ['expr']; - } - - public function getType() : string { - return 'Expr_Empty'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php deleted file mode 100644 index 1637f3aea..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -/** - * Error node used during parsing with error recovery. - * - * An error node may be placed at a position where an expression is required, but an error occurred. - * Error nodes will not be present if the parser is run in throwOnError mode (the default). - */ -class Error extends Expr -{ - /** - * Constructs an error node. - * - * @param array $attributes Additional attributes - */ - public function __construct(array $attributes = []) { - $this->attributes = $attributes; - } - - public function getSubNodeNames() : array { - return []; - } - - public function getType() : string { - return 'Expr_Error'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php deleted file mode 100644 index c44ff6f93..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class ErrorSuppress extends Expr -{ - /** @var Expr Expression */ - public $expr; - - /** - * Constructs an error suppress node. - * - * @param Expr $expr Expression - * @param array $attributes Additional attributes - */ - public function __construct(Expr $expr, array $attributes = []) { - $this->attributes = $attributes; - $this->expr = $expr; - } - - public function getSubNodeNames() : array { - return ['expr']; - } - - public function getType() : string { - return 'Expr_ErrorSuppress'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php deleted file mode 100644 index 856854743..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class Eval_ extends Expr -{ - /** @var Expr Expression */ - public $expr; - - /** - * Constructs an eval() node. - * - * @param Expr $expr Expression - * @param array $attributes Additional attributes - */ - public function __construct(Expr $expr, array $attributes = []) { - $this->attributes = $attributes; - $this->expr = $expr; - } - - public function getSubNodeNames() : array { - return ['expr']; - } - - public function getType() : string { - return 'Expr_Eval'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php deleted file mode 100644 index b88a8f7e6..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class Exit_ extends Expr -{ - /* For use in "kind" attribute */ - const KIND_EXIT = 1; - const KIND_DIE = 2; - - /** @var null|Expr Expression */ - public $expr; - - /** - * Constructs an exit() node. - * - * @param null|Expr $expr Expression - * @param array $attributes Additional attributes - */ - public function __construct(Expr $expr = null, array $attributes = []) { - $this->attributes = $attributes; - $this->expr = $expr; - } - - public function getSubNodeNames() : array { - return ['expr']; - } - - public function getType() : string { - return 'Expr_Exit'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php deleted file mode 100644 index 2de4d0dd5..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node; -use PhpParser\Node\Expr; - -class FuncCall extends CallLike -{ - /** @var Node\Name|Expr Function name */ - public $name; - /** @var array<Node\Arg|Node\VariadicPlaceholder> Arguments */ - public $args; - - /** - * Constructs a function call node. - * - * @param Node\Name|Expr $name Function name - * @param array<Node\Arg|Node\VariadicPlaceholder> $args Arguments - * @param array $attributes Additional attributes - */ - public function __construct($name, array $args = [], array $attributes = []) { - $this->attributes = $attributes; - $this->name = $name; - $this->args = $args; - } - - public function getSubNodeNames() : array { - return ['name', 'args']; - } - - public function getType() : string { - return 'Expr_FuncCall'; - } - - public function getRawArgs(): array { - return $this->args; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php deleted file mode 100644 index 07ce5968e..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class Include_ extends Expr -{ - const TYPE_INCLUDE = 1; - const TYPE_INCLUDE_ONCE = 2; - const TYPE_REQUIRE = 3; - const TYPE_REQUIRE_ONCE = 4; - - /** @var Expr Expression */ - public $expr; - /** @var int Type of include */ - public $type; - - /** - * Constructs an include node. - * - * @param Expr $expr Expression - * @param int $type Type of include - * @param array $attributes Additional attributes - */ - public function __construct(Expr $expr, int $type, array $attributes = []) { - $this->attributes = $attributes; - $this->expr = $expr; - $this->type = $type; - } - - public function getSubNodeNames() : array { - return ['expr', 'type']; - } - - public function getType() : string { - return 'Expr_Include'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php deleted file mode 100644 index 9000d47bb..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; -use PhpParser\Node\Name; - -class Instanceof_ extends Expr -{ - /** @var Expr Expression */ - public $expr; - /** @var Name|Expr Class name */ - public $class; - - /** - * Constructs an instanceof check node. - * - * @param Expr $expr Expression - * @param Name|Expr $class Class name - * @param array $attributes Additional attributes - */ - public function __construct(Expr $expr, $class, array $attributes = []) { - $this->attributes = $attributes; - $this->expr = $expr; - $this->class = $class; - } - - public function getSubNodeNames() : array { - return ['expr', 'class']; - } - - public function getType() : string { - return 'Expr_Instanceof'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php deleted file mode 100644 index 76b738758..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class Isset_ extends Expr -{ - /** @var Expr[] Variables */ - public $vars; - - /** - * Constructs an array node. - * - * @param Expr[] $vars Variables - * @param array $attributes Additional attributes - */ - public function __construct(array $vars, array $attributes = []) { - $this->attributes = $attributes; - $this->vars = $vars; - } - - public function getSubNodeNames() : array { - return ['vars']; - } - - public function getType() : string { - return 'Expr_Isset'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php deleted file mode 100644 index c27a27b95..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class List_ extends Expr -{ - /** @var (ArrayItem|null)[] List of items to assign to */ - public $items; - - /** - * Constructs a list() destructuring node. - * - * @param (ArrayItem|null)[] $items List of items to assign to - * @param array $attributes Additional attributes - */ - public function __construct(array $items, array $attributes = []) { - $this->attributes = $attributes; - $this->items = $items; - } - - public function getSubNodeNames() : array { - return ['items']; - } - - public function getType() : string { - return 'Expr_List'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.php deleted file mode 100644 index 2455a3026..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node; -use PhpParser\Node\MatchArm; - -class Match_ extends Node\Expr -{ - /** @var Node\Expr */ - public $cond; - /** @var MatchArm[] */ - public $arms; - - /** - * @param MatchArm[] $arms - */ - public function __construct(Node\Expr $cond, array $arms = [], array $attributes = []) { - $this->attributes = $attributes; - $this->cond = $cond; - $this->arms = $arms; - } - - public function getSubNodeNames() : array { - return ['cond', 'arms']; - } - - public function getType() : string { - return 'Expr_Match'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php deleted file mode 100644 index 49ca48356..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Arg; -use PhpParser\Node\Expr; -use PhpParser\Node\Identifier; -use PhpParser\Node\VariadicPlaceholder; - -class MethodCall extends CallLike -{ - /** @var Expr Variable holding object */ - public $var; - /** @var Identifier|Expr Method name */ - public $name; - /** @var array<Arg|VariadicPlaceholder> Arguments */ - public $args; - - /** - * Constructs a function call node. - * - * @param Expr $var Variable holding object - * @param string|Identifier|Expr $name Method name - * @param array<Arg|VariadicPlaceholder> $args Arguments - * @param array $attributes Additional attributes - */ - public function __construct(Expr $var, $name, array $args = [], array $attributes = []) { - $this->attributes = $attributes; - $this->var = $var; - $this->name = \is_string($name) ? new Identifier($name) : $name; - $this->args = $args; - } - - public function getSubNodeNames() : array { - return ['var', 'name', 'args']; - } - - public function getType() : string { - return 'Expr_MethodCall'; - } - - public function getRawArgs(): array { - return $this->args; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php deleted file mode 100644 index e2bb64928..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node; -use PhpParser\Node\Arg; -use PhpParser\Node\Expr; -use PhpParser\Node\VariadicPlaceholder; - -class New_ extends CallLike -{ - /** @var Node\Name|Expr|Node\Stmt\Class_ Class name */ - public $class; - /** @var array<Arg|VariadicPlaceholder> Arguments */ - public $args; - - /** - * Constructs a function call node. - * - * @param Node\Name|Expr|Node\Stmt\Class_ $class Class name (or class node for anonymous classes) - * @param array<Arg|VariadicPlaceholder> $args Arguments - * @param array $attributes Additional attributes - */ - public function __construct($class, array $args = [], array $attributes = []) { - $this->attributes = $attributes; - $this->class = $class; - $this->args = $args; - } - - public function getSubNodeNames() : array { - return ['class', 'args']; - } - - public function getType() : string { - return 'Expr_New'; - } - - public function getRawArgs(): array { - return $this->args; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php deleted file mode 100644 index 07a571fd8..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Arg; -use PhpParser\Node\Expr; -use PhpParser\Node\Identifier; -use PhpParser\Node\VariadicPlaceholder; - -class NullsafeMethodCall extends CallLike -{ - /** @var Expr Variable holding object */ - public $var; - /** @var Identifier|Expr Method name */ - public $name; - /** @var array<Arg|VariadicPlaceholder> Arguments */ - public $args; - - /** - * Constructs a nullsafe method call node. - * - * @param Expr $var Variable holding object - * @param string|Identifier|Expr $name Method name - * @param array<Arg|VariadicPlaceholder> $args Arguments - * @param array $attributes Additional attributes - */ - public function __construct(Expr $var, $name, array $args = [], array $attributes = []) { - $this->attributes = $attributes; - $this->var = $var; - $this->name = \is_string($name) ? new Identifier($name) : $name; - $this->args = $args; - } - - public function getSubNodeNames() : array { - return ['var', 'name', 'args']; - } - - public function getType() : string { - return 'Expr_NullsafeMethodCall'; - } - - public function getRawArgs(): array { - return $this->args; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php deleted file mode 100644 index 9317eb3b9..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; -use PhpParser\Node\Identifier; - -class NullsafePropertyFetch extends Expr -{ - /** @var Expr Variable holding object */ - public $var; - /** @var Identifier|Expr Property name */ - public $name; - - /** - * Constructs a nullsafe property fetch node. - * - * @param Expr $var Variable holding object - * @param string|Identifier|Expr $name Property name - * @param array $attributes Additional attributes - */ - public function __construct(Expr $var, $name, array $attributes = []) { - $this->attributes = $attributes; - $this->var = $var; - $this->name = \is_string($name) ? new Identifier($name) : $name; - } - - public function getSubNodeNames() : array { - return ['var', 'name']; - } - - public function getType() : string { - return 'Expr_NullsafePropertyFetch'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php deleted file mode 100644 index 94d6c296d..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class PostDec extends Expr -{ - /** @var Expr Variable */ - public $var; - - /** - * Constructs a post decrement node. - * - * @param Expr $var Variable - * @param array $attributes Additional attributes - */ - public function __construct(Expr $var, array $attributes = []) { - $this->attributes = $attributes; - $this->var = $var; - } - - public function getSubNodeNames() : array { - return ['var']; - } - - public function getType() : string { - return 'Expr_PostDec'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php deleted file mode 100644 index 005c443a2..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class PostInc extends Expr -{ - /** @var Expr Variable */ - public $var; - - /** - * Constructs a post increment node. - * - * @param Expr $var Variable - * @param array $attributes Additional attributes - */ - public function __construct(Expr $var, array $attributes = []) { - $this->attributes = $attributes; - $this->var = $var; - } - - public function getSubNodeNames() : array { - return ['var']; - } - - public function getType() : string { - return 'Expr_PostInc'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php deleted file mode 100644 index a5ca685a8..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class PreDec extends Expr -{ - /** @var Expr Variable */ - public $var; - - /** - * Constructs a pre decrement node. - * - * @param Expr $var Variable - * @param array $attributes Additional attributes - */ - public function __construct(Expr $var, array $attributes = []) { - $this->attributes = $attributes; - $this->var = $var; - } - - public function getSubNodeNames() : array { - return ['var']; - } - - public function getType() : string { - return 'Expr_PreDec'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php deleted file mode 100644 index 0986c4474..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class PreInc extends Expr -{ - /** @var Expr Variable */ - public $var; - - /** - * Constructs a pre increment node. - * - * @param Expr $var Variable - * @param array $attributes Additional attributes - */ - public function __construct(Expr $var, array $attributes = []) { - $this->attributes = $attributes; - $this->var = $var; - } - - public function getSubNodeNames() : array { - return ['var']; - } - - public function getType() : string { - return 'Expr_PreInc'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php deleted file mode 100644 index 2d43c2ac8..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class Print_ extends Expr -{ - /** @var Expr Expression */ - public $expr; - - /** - * Constructs an print() node. - * - * @param Expr $expr Expression - * @param array $attributes Additional attributes - */ - public function __construct(Expr $expr, array $attributes = []) { - $this->attributes = $attributes; - $this->expr = $expr; - } - - public function getSubNodeNames() : array { - return ['expr']; - } - - public function getType() : string { - return 'Expr_Print'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php deleted file mode 100644 index 4281f31cc..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; -use PhpParser\Node\Identifier; - -class PropertyFetch extends Expr -{ - /** @var Expr Variable holding object */ - public $var; - /** @var Identifier|Expr Property name */ - public $name; - - /** - * Constructs a function call node. - * - * @param Expr $var Variable holding object - * @param string|Identifier|Expr $name Property name - * @param array $attributes Additional attributes - */ - public function __construct(Expr $var, $name, array $attributes = []) { - $this->attributes = $attributes; - $this->var = $var; - $this->name = \is_string($name) ? new Identifier($name) : $name; - } - - public function getSubNodeNames() : array { - return ['var', 'name']; - } - - public function getType() : string { - return 'Expr_PropertyFetch'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php deleted file mode 100644 index 537a7cc80..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class ShellExec extends Expr -{ - /** @var array Encapsed string array */ - public $parts; - - /** - * Constructs a shell exec (backtick) node. - * - * @param array $parts Encapsed string array - * @param array $attributes Additional attributes - */ - public function __construct(array $parts, array $attributes = []) { - $this->attributes = $attributes; - $this->parts = $parts; - } - - public function getSubNodeNames() : array { - return ['parts']; - } - - public function getType() : string { - return 'Expr_ShellExec'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php deleted file mode 100644 index d0d099c47..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node; -use PhpParser\Node\Arg; -use PhpParser\Node\Expr; -use PhpParser\Node\Identifier; -use PhpParser\Node\VariadicPlaceholder; - -class StaticCall extends CallLike -{ - /** @var Node\Name|Expr Class name */ - public $class; - /** @var Identifier|Expr Method name */ - public $name; - /** @var array<Arg|VariadicPlaceholder> Arguments */ - public $args; - - /** - * Constructs a static method call node. - * - * @param Node\Name|Expr $class Class name - * @param string|Identifier|Expr $name Method name - * @param array<Arg|VariadicPlaceholder> $args Arguments - * @param array $attributes Additional attributes - */ - public function __construct($class, $name, array $args = [], array $attributes = []) { - $this->attributes = $attributes; - $this->class = $class; - $this->name = \is_string($name) ? new Identifier($name) : $name; - $this->args = $args; - } - - public function getSubNodeNames() : array { - return ['class', 'name', 'args']; - } - - public function getType() : string { - return 'Expr_StaticCall'; - } - - public function getRawArgs(): array { - return $this->args; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php deleted file mode 100644 index 1ee1a25e5..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; -use PhpParser\Node\Name; -use PhpParser\Node\VarLikeIdentifier; - -class StaticPropertyFetch extends Expr -{ - /** @var Name|Expr Class name */ - public $class; - /** @var VarLikeIdentifier|Expr Property name */ - public $name; - - /** - * Constructs a static property fetch node. - * - * @param Name|Expr $class Class name - * @param string|VarLikeIdentifier|Expr $name Property name - * @param array $attributes Additional attributes - */ - public function __construct($class, $name, array $attributes = []) { - $this->attributes = $attributes; - $this->class = $class; - $this->name = \is_string($name) ? new VarLikeIdentifier($name) : $name; - } - - public function getSubNodeNames() : array { - return ['class', 'name']; - } - - public function getType() : string { - return 'Expr_StaticPropertyFetch'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php deleted file mode 100644 index 9316f47d4..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class Ternary extends Expr -{ - /** @var Expr Condition */ - public $cond; - /** @var null|Expr Expression for true */ - public $if; - /** @var Expr Expression for false */ - public $else; - - /** - * Constructs a ternary operator node. - * - * @param Expr $cond Condition - * @param null|Expr $if Expression for true - * @param Expr $else Expression for false - * @param array $attributes Additional attributes - */ - public function __construct(Expr $cond, $if, Expr $else, array $attributes = []) { - $this->attributes = $attributes; - $this->cond = $cond; - $this->if = $if; - $this->else = $else; - } - - public function getSubNodeNames() : array { - return ['cond', 'if', 'else']; - } - - public function getType() : string { - return 'Expr_Ternary'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.php deleted file mode 100644 index 5c97f0e2b..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node; - -class Throw_ extends Node\Expr -{ - /** @var Node\Expr Expression */ - public $expr; - - /** - * Constructs a throw expression node. - * - * @param Node\Expr $expr Expression - * @param array $attributes Additional attributes - */ - public function __construct(Node\Expr $expr, array $attributes = []) { - $this->attributes = $attributes; - $this->expr = $expr; - } - - public function getSubNodeNames() : array { - return ['expr']; - } - - public function getType() : string { - return 'Expr_Throw'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php deleted file mode 100644 index ce8808bc6..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class UnaryMinus extends Expr -{ - /** @var Expr Expression */ - public $expr; - - /** - * Constructs a unary minus node. - * - * @param Expr $expr Expression - * @param array $attributes Additional attributes - */ - public function __construct(Expr $expr, array $attributes = []) { - $this->attributes = $attributes; - $this->expr = $expr; - } - - public function getSubNodeNames() : array { - return ['expr']; - } - - public function getType() : string { - return 'Expr_UnaryMinus'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php deleted file mode 100644 index d23047e54..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class UnaryPlus extends Expr -{ - /** @var Expr Expression */ - public $expr; - - /** - * Constructs a unary plus node. - * - * @param Expr $expr Expression - * @param array $attributes Additional attributes - */ - public function __construct(Expr $expr, array $attributes = []) { - $this->attributes = $attributes; - $this->expr = $expr; - } - - public function getSubNodeNames() : array { - return ['expr']; - } - - public function getType() : string { - return 'Expr_UnaryPlus'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php deleted file mode 100644 index b47d38e93..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class Variable extends Expr -{ - /** @var string|Expr Name */ - public $name; - - /** - * Constructs a variable node. - * - * @param string|Expr $name Name - * @param array $attributes Additional attributes - */ - public function __construct($name, array $attributes = []) { - $this->attributes = $attributes; - $this->name = $name; - } - - public function getSubNodeNames() : array { - return ['name']; - } - - public function getType() : string { - return 'Expr_Variable'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php deleted file mode 100644 index a3efce618..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class YieldFrom extends Expr -{ - /** @var Expr Expression to yield from */ - public $expr; - - /** - * Constructs an "yield from" node. - * - * @param Expr $expr Expression - * @param array $attributes Additional attributes - */ - public function __construct(Expr $expr, array $attributes = []) { - $this->attributes = $attributes; - $this->expr = $expr; - } - - public function getSubNodeNames() : array { - return ['expr']; - } - - public function getType() : string { - return 'Expr_YieldFrom'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php deleted file mode 100644 index aef8fc333..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Expr; - -use PhpParser\Node\Expr; - -class Yield_ extends Expr -{ - /** @var null|Expr Key expression */ - public $key; - /** @var null|Expr Value expression */ - public $value; - - /** - * Constructs a yield expression node. - * - * @param null|Expr $value Value expression - * @param null|Expr $key Key expression - * @param array $attributes Additional attributes - */ - public function __construct(Expr $value = null, Expr $key = null, array $attributes = []) { - $this->attributes = $attributes; - $this->key = $key; - $this->value = $value; - } - - public function getSubNodeNames() : array { - return ['key', 'value']; - } - - public function getType() : string { - return 'Expr_Yield'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php b/lib/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php deleted file mode 100644 index 5a825e731..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node; - -use PhpParser\Node; - -interface FunctionLike extends Node -{ - /** - * Whether to return by reference - * - * @return bool - */ - public function returnsByRef() : bool; - - /** - * List of parameters - * - * @return Param[] - */ - public function getParams() : array; - - /** - * Get the declared return type or null - * - * @return null|Identifier|Name|ComplexType - */ - public function getReturnType(); - - /** - * The function body - * - * @return Stmt[]|null - */ - public function getStmts(); - - /** - * Get PHP attribute groups. - * - * @return AttributeGroup[] - */ - public function getAttrGroups() : array; -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Identifier.php b/lib/nikic/php-parser/lib/PhpParser/Node/Identifier.php deleted file mode 100644 index 2f262db0a..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Identifier.php +++ /dev/null @@ -1,75 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node; - -use PhpParser\NodeAbstract; - -/** - * Represents a non-namespaced name. Namespaced names are represented using Name nodes. - */ -class Identifier extends NodeAbstract -{ - /** @var string Identifier as string */ - public $name; - - private static $specialClassNames = [ - 'self' => true, - 'parent' => true, - 'static' => true, - ]; - - /** - * Constructs an identifier node. - * - * @param string $name Identifier as string - * @param array $attributes Additional attributes - */ - public function __construct(string $name, array $attributes = []) { - $this->attributes = $attributes; - $this->name = $name; - } - - public function getSubNodeNames() : array { - return ['name']; - } - - /** - * Get identifier as string. - * - * @return string Identifier as string. - */ - public function toString() : string { - return $this->name; - } - - /** - * Get lowercased identifier as string. - * - * @return string Lowercased identifier as string - */ - public function toLowerString() : string { - return strtolower($this->name); - } - - /** - * Checks whether the identifier is a special class name (self, parent or static). - * - * @return bool Whether identifier is a special class name - */ - public function isSpecialClassName() : bool { - return isset(self::$specialClassNames[strtolower($this->name)]); - } - - /** - * Get identifier as string. - * - * @return string Identifier as string - */ - public function __toString() : string { - return $this->name; - } - - public function getType() : string { - return 'Identifier'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/IntersectionType.php b/lib/nikic/php-parser/lib/PhpParser/Node/IntersectionType.php deleted file mode 100644 index 9208e1392..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/IntersectionType.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node; - -use PhpParser\NodeAbstract; - -class IntersectionType extends ComplexType -{ - /** @var (Identifier|Name)[] Types */ - public $types; - - /** - * Constructs an intersection type. - * - * @param (Identifier|Name)[] $types Types - * @param array $attributes Additional attributes - */ - public function __construct(array $types, array $attributes = []) { - $this->attributes = $attributes; - $this->types = $types; - } - - public function getSubNodeNames() : array { - return ['types']; - } - - public function getType() : string { - return 'IntersectionType'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/MatchArm.php b/lib/nikic/php-parser/lib/PhpParser/Node/MatchArm.php deleted file mode 100644 index 2ae1c86b8..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/MatchArm.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node; - -use PhpParser\Node; -use PhpParser\NodeAbstract; - -class MatchArm extends NodeAbstract -{ - /** @var null|Node\Expr[] */ - public $conds; - /** @var Node\Expr */ - public $body; - - /** - * @param null|Node\Expr[] $conds - */ - public function __construct($conds, Node\Expr $body, array $attributes = []) { - $this->conds = $conds; - $this->body = $body; - $this->attributes = $attributes; - } - - public function getSubNodeNames() : array { - return ['conds', 'body']; - } - - public function getType() : string { - return 'MatchArm'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Name.php b/lib/nikic/php-parser/lib/PhpParser/Node/Name.php deleted file mode 100644 index 6b1cc9f8e..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Name.php +++ /dev/null @@ -1,242 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node; - -use PhpParser\NodeAbstract; - -class Name extends NodeAbstract -{ - /** @var string[] Parts of the name */ - public $parts; - - private static $specialClassNames = [ - 'self' => true, - 'parent' => true, - 'static' => true, - ]; - - /** - * Constructs a name node. - * - * @param string|string[]|self $name Name as string, part array or Name instance (copy ctor) - * @param array $attributes Additional attributes - */ - public function __construct($name, array $attributes = []) { - $this->attributes = $attributes; - $this->parts = self::prepareName($name); - } - - public function getSubNodeNames() : array { - return ['parts']; - } - - /** - * Gets the first part of the name, i.e. everything before the first namespace separator. - * - * @return string First part of the name - */ - public function getFirst() : string { - return $this->parts[0]; - } - - /** - * Gets the last part of the name, i.e. everything after the last namespace separator. - * - * @return string Last part of the name - */ - public function getLast() : string { - return $this->parts[count($this->parts) - 1]; - } - - /** - * Checks whether the name is unqualified. (E.g. Name) - * - * @return bool Whether the name is unqualified - */ - public function isUnqualified() : bool { - return 1 === count($this->parts); - } - - /** - * Checks whether the name is qualified. (E.g. Name\Name) - * - * @return bool Whether the name is qualified - */ - public function isQualified() : bool { - return 1 < count($this->parts); - } - - /** - * Checks whether the name is fully qualified. (E.g. \Name) - * - * @return bool Whether the name is fully qualified - */ - public function isFullyQualified() : bool { - return false; - } - - /** - * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name) - * - * @return bool Whether the name is relative - */ - public function isRelative() : bool { - return false; - } - - /** - * Returns a string representation of the name itself, without taking the name type into - * account (e.g., not including a leading backslash for fully qualified names). - * - * @return string String representation - */ - public function toString() : string { - return implode('\\', $this->parts); - } - - /** - * Returns a string representation of the name as it would occur in code (e.g., including - * leading backslash for fully qualified names. - * - * @return string String representation - */ - public function toCodeString() : string { - return $this->toString(); - } - - /** - * Returns lowercased string representation of the name, without taking the name type into - * account (e.g., no leading backslash for fully qualified names). - * - * @return string Lowercased string representation - */ - public function toLowerString() : string { - return strtolower(implode('\\', $this->parts)); - } - - /** - * Checks whether the identifier is a special class name (self, parent or static). - * - * @return bool Whether identifier is a special class name - */ - public function isSpecialClassName() : bool { - return count($this->parts) === 1 - && isset(self::$specialClassNames[strtolower($this->parts[0])]); - } - - /** - * Returns a string representation of the name by imploding the namespace parts with the - * namespace separator. - * - * @return string String representation - */ - public function __toString() : string { - return implode('\\', $this->parts); - } - - /** - * Gets a slice of a name (similar to array_slice). - * - * This method returns a new instance of the same type as the original and with the same - * attributes. - * - * If the slice is empty, null is returned. The null value will be correctly handled in - * concatenations using concat(). - * - * Offset and length have the same meaning as in array_slice(). - * - * @param int $offset Offset to start the slice at (may be negative) - * @param int|null $length Length of the slice (may be negative) - * - * @return static|null Sliced name - */ - public function slice(int $offset, int $length = null) { - $numParts = count($this->parts); - - $realOffset = $offset < 0 ? $offset + $numParts : $offset; - if ($realOffset < 0 || $realOffset > $numParts) { - throw new \OutOfBoundsException(sprintf('Offset %d is out of bounds', $offset)); - } - - if (null === $length) { - $realLength = $numParts - $realOffset; - } else { - $realLength = $length < 0 ? $length + $numParts - $realOffset : $length; - if ($realLength < 0 || $realLength > $numParts) { - throw new \OutOfBoundsException(sprintf('Length %d is out of bounds', $length)); - } - } - - if ($realLength === 0) { - // Empty slice is represented as null - return null; - } - - return new static(array_slice($this->parts, $realOffset, $realLength), $this->attributes); - } - - /** - * Concatenate two names, yielding a new Name instance. - * - * The type of the generated instance depends on which class this method is called on, for - * example Name\FullyQualified::concat() will yield a Name\FullyQualified instance. - * - * If one of the arguments is null, a new instance of the other name will be returned. If both - * arguments are null, null will be returned. As such, writing - * Name::concat($namespace, $shortName) - * where $namespace is a Name node or null will work as expected. - * - * @param string|string[]|self|null $name1 The first name - * @param string|string[]|self|null $name2 The second name - * @param array $attributes Attributes to assign to concatenated name - * - * @return static|null Concatenated name - */ - public static function concat($name1, $name2, array $attributes = []) { - if (null === $name1 && null === $name2) { - return null; - } elseif (null === $name1) { - return new static(self::prepareName($name2), $attributes); - } elseif (null === $name2) { - return new static(self::prepareName($name1), $attributes); - } else { - return new static( - array_merge(self::prepareName($name1), self::prepareName($name2)), $attributes - ); - } - } - - /** - * Prepares a (string, array or Name node) name for use in name changing methods by converting - * it to an array. - * - * @param string|string[]|self $name Name to prepare - * - * @return string[] Prepared name - */ - private static function prepareName($name) : array { - if (\is_string($name)) { - if ('' === $name) { - throw new \InvalidArgumentException('Name cannot be empty'); - } - - return explode('\\', $name); - } elseif (\is_array($name)) { - if (empty($name)) { - throw new \InvalidArgumentException('Name cannot be empty'); - } - - return $name; - } elseif ($name instanceof self) { - return $name->parts; - } - - throw new \InvalidArgumentException( - 'Expected string, array of parts or Name instance' - ); - } - - public function getType() : string { - return 'Name'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php b/lib/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php deleted file mode 100644 index 1df93a56b..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Name; - -class FullyQualified extends \PhpParser\Node\Name -{ - /** - * Checks whether the name is unqualified. (E.g. Name) - * - * @return bool Whether the name is unqualified - */ - public function isUnqualified() : bool { - return false; - } - - /** - * Checks whether the name is qualified. (E.g. Name\Name) - * - * @return bool Whether the name is qualified - */ - public function isQualified() : bool { - return false; - } - - /** - * Checks whether the name is fully qualified. (E.g. \Name) - * - * @return bool Whether the name is fully qualified - */ - public function isFullyQualified() : bool { - return true; - } - - /** - * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name) - * - * @return bool Whether the name is relative - */ - public function isRelative() : bool { - return false; - } - - public function toCodeString() : string { - return '\\' . $this->toString(); - } - - public function getType() : string { - return 'Name_FullyQualified'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php b/lib/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php deleted file mode 100644 index 57bf7af2b..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Name; - -class Relative extends \PhpParser\Node\Name -{ - /** - * Checks whether the name is unqualified. (E.g. Name) - * - * @return bool Whether the name is unqualified - */ - public function isUnqualified() : bool { - return false; - } - - /** - * Checks whether the name is qualified. (E.g. Name\Name) - * - * @return bool Whether the name is qualified - */ - public function isQualified() : bool { - return false; - } - - /** - * Checks whether the name is fully qualified. (E.g. \Name) - * - * @return bool Whether the name is fully qualified - */ - public function isFullyQualified() : bool { - return false; - } - - /** - * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name) - * - * @return bool Whether the name is relative - */ - public function isRelative() : bool { - return true; - } - - public function toCodeString() : string { - return 'namespace\\' . $this->toString(); - } - - public function getType() : string { - return 'Name_Relative'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/NullableType.php b/lib/nikic/php-parser/lib/PhpParser/Node/NullableType.php deleted file mode 100644 index d68e26a38..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/NullableType.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node; - -class NullableType extends ComplexType -{ - /** @var Identifier|Name Type */ - public $type; - - /** - * Constructs a nullable type (wrapping another type). - * - * @param string|Identifier|Name $type Type - * @param array $attributes Additional attributes - */ - public function __construct($type, array $attributes = []) { - $this->attributes = $attributes; - $this->type = \is_string($type) ? new Identifier($type) : $type; - } - - public function getSubNodeNames() : array { - return ['type']; - } - - public function getType() : string { - return 'NullableType'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Param.php b/lib/nikic/php-parser/lib/PhpParser/Node/Param.php deleted file mode 100644 index 1e90b7944..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Param.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node; - -use PhpParser\NodeAbstract; - -class Param extends NodeAbstract -{ - /** @var null|Identifier|Name|ComplexType Type declaration */ - public $type; - /** @var bool Whether parameter is passed by reference */ - public $byRef; - /** @var bool Whether this is a variadic argument */ - public $variadic; - /** @var Expr\Variable|Expr\Error Parameter variable */ - public $var; - /** @var null|Expr Default value */ - public $default; - /** @var int */ - public $flags; - /** @var AttributeGroup[] PHP attribute groups */ - public $attrGroups; - - /** - * Constructs a parameter node. - * - * @param Expr\Variable|Expr\Error $var Parameter variable - * @param null|Expr $default Default value - * @param null|string|Identifier|Name|ComplexType $type Type declaration - * @param bool $byRef Whether is passed by reference - * @param bool $variadic Whether this is a variadic argument - * @param array $attributes Additional attributes - * @param int $flags Optional visibility flags - * @param AttributeGroup[] $attrGroups PHP attribute groups - */ - public function __construct( - $var, Expr $default = null, $type = null, - bool $byRef = false, bool $variadic = false, - array $attributes = [], - int $flags = 0, - array $attrGroups = [] - ) { - $this->attributes = $attributes; - $this->type = \is_string($type) ? new Identifier($type) : $type; - $this->byRef = $byRef; - $this->variadic = $variadic; - $this->var = $var; - $this->default = $default; - $this->flags = $flags; - $this->attrGroups = $attrGroups; - } - - public function getSubNodeNames() : array { - return ['attrGroups', 'flags', 'type', 'byRef', 'variadic', 'var', 'default']; - } - - public function getType() : string { - return 'Param'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar.php b/lib/nikic/php-parser/lib/PhpParser/Node/Scalar.php deleted file mode 100644 index 8117909b6..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node; - -abstract class Scalar extends Expr -{ -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/DNumber.php b/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/DNumber.php deleted file mode 100644 index d4796d65b..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/DNumber.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Scalar; - -use PhpParser\Node\Scalar; - -class DNumber extends Scalar -{ - /** @var float Number value */ - public $value; - - /** - * Constructs a float number scalar node. - * - * @param float $value Value of the number - * @param array $attributes Additional attributes - */ - public function __construct(float $value, array $attributes = []) { - $this->attributes = $attributes; - $this->value = $value; - } - - public function getSubNodeNames() : array { - return ['value']; - } - - /** - * @param mixed[] $attributes - */ - public static function fromString(string $str, array $attributes = []): DNumber - { - $attributes['rawValue'] = $str; - $float = self::parse($str); - - return new DNumber($float, $attributes); - } - - /** - * @internal - * - * Parses a DNUMBER token like PHP would. - * - * @param string $str A string number - * - * @return float The parsed number - */ - public static function parse(string $str) : float { - $str = str_replace('_', '', $str); - - // if string contains any of .eE just cast it to float - if (false !== strpbrk($str, '.eE')) { - return (float) $str; - } - - // otherwise it's an integer notation that overflowed into a float - // if it starts with 0 it's one of the special integer notations - if ('0' === $str[0]) { - // hex - if ('x' === $str[1] || 'X' === $str[1]) { - return hexdec($str); - } - - // bin - if ('b' === $str[1] || 'B' === $str[1]) { - return bindec($str); - } - - // oct - // substr($str, 0, strcspn($str, '89')) cuts the string at the first invalid digit (8 or 9) - // so that only the digits before that are used - return octdec(substr($str, 0, strcspn($str, '89'))); - } - - // dec - return (float) $str; - } - - public function getType() : string { - return 'Scalar_DNumber'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php b/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php deleted file mode 100644 index fa5d2e268..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Scalar; - -use PhpParser\Node\Expr; -use PhpParser\Node\Scalar; - -class Encapsed extends Scalar -{ - /** @var Expr[] list of string parts */ - public $parts; - - /** - * Constructs an encapsed string node. - * - * @param Expr[] $parts Encaps list - * @param array $attributes Additional attributes - */ - public function __construct(array $parts, array $attributes = []) { - $this->attributes = $attributes; - $this->parts = $parts; - } - - public function getSubNodeNames() : array { - return ['parts']; - } - - public function getType() : string { - return 'Scalar_Encapsed'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php b/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php deleted file mode 100644 index bb3194c1d..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Scalar; - -use PhpParser\Node\Scalar; - -class EncapsedStringPart extends Scalar -{ - /** @var string String value */ - public $value; - - /** - * Constructs a node representing a string part of an encapsed string. - * - * @param string $value String value - * @param array $attributes Additional attributes - */ - public function __construct(string $value, array $attributes = []) { - $this->attributes = $attributes; - $this->value = $value; - } - - public function getSubNodeNames() : array { - return ['value']; - } - - public function getType() : string { - return 'Scalar_EncapsedStringPart'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php b/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php deleted file mode 100644 index 2cc2b22c8..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Scalar; - -use PhpParser\Error; -use PhpParser\Node\Scalar; - -class LNumber extends Scalar -{ - /* For use in "kind" attribute */ - const KIND_BIN = 2; - const KIND_OCT = 8; - const KIND_DEC = 10; - const KIND_HEX = 16; - - /** @var int Number value */ - public $value; - - /** - * Constructs an integer number scalar node. - * - * @param int $value Value of the number - * @param array $attributes Additional attributes - */ - public function __construct(int $value, array $attributes = []) { - $this->attributes = $attributes; - $this->value = $value; - } - - public function getSubNodeNames() : array { - return ['value']; - } - - /** - * Constructs an LNumber node from a string number literal. - * - * @param string $str String number literal (decimal, octal, hex or binary) - * @param array $attributes Additional attributes - * @param bool $allowInvalidOctal Whether to allow invalid octal numbers (PHP 5) - * - * @return LNumber The constructed LNumber, including kind attribute - */ - public static function fromString(string $str, array $attributes = [], bool $allowInvalidOctal = false) : LNumber { - $attributes['rawValue'] = $str; - - $str = str_replace('_', '', $str); - - if ('0' !== $str[0] || '0' === $str) { - $attributes['kind'] = LNumber::KIND_DEC; - return new LNumber((int) $str, $attributes); - } - - if ('x' === $str[1] || 'X' === $str[1]) { - $attributes['kind'] = LNumber::KIND_HEX; - return new LNumber(hexdec($str), $attributes); - } - - if ('b' === $str[1] || 'B' === $str[1]) { - $attributes['kind'] = LNumber::KIND_BIN; - return new LNumber(bindec($str), $attributes); - } - - if (!$allowInvalidOctal && strpbrk($str, '89')) { - throw new Error('Invalid numeric literal', $attributes); - } - - // Strip optional explicit octal prefix. - if ('o' === $str[1] || 'O' === $str[1]) { - $str = substr($str, 2); - } - - // use intval instead of octdec to get proper cutting behavior with malformed numbers - $attributes['kind'] = LNumber::KIND_OCT; - return new LNumber(intval($str, 8), $attributes); - } - - public function getType() : string { - return 'Scalar_LNumber'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php b/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php deleted file mode 100644 index 941f0c762..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Scalar; - -use PhpParser\Node\Scalar; - -abstract class MagicConst extends Scalar -{ - /** - * Constructs a magic constant node. - * - * @param array $attributes Additional attributes - */ - public function __construct(array $attributes = []) { - $this->attributes = $attributes; - } - - public function getSubNodeNames() : array { - return []; - } - - /** - * Get name of magic constant. - * - * @return string Name of magic constant - */ - abstract public function getName() : string; -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php deleted file mode 100644 index 244328476..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Scalar\MagicConst; - -use PhpParser\Node\Scalar\MagicConst; - -class Class_ extends MagicConst -{ - public function getName() : string { - return '__CLASS__'; - } - - public function getType() : string { - return 'Scalar_MagicConst_Class'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php b/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php deleted file mode 100644 index 2b618473e..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Scalar\MagicConst; - -use PhpParser\Node\Scalar\MagicConst; - -class Dir extends MagicConst -{ - public function getName() : string { - return '__DIR__'; - } - - public function getType() : string { - return 'Scalar_MagicConst_Dir'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php b/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php deleted file mode 100644 index 3422db069..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Scalar\MagicConst; - -use PhpParser\Node\Scalar\MagicConst; - -class File extends MagicConst -{ - public function getName() : string { - return '__FILE__'; - } - - public function getType() : string { - return 'Scalar_MagicConst_File'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.php deleted file mode 100644 index 1db65a151..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Scalar\MagicConst; - -use PhpParser\Node\Scalar\MagicConst; - -class Function_ extends MagicConst -{ - public function getName() : string { - return '__FUNCTION__'; - } - - public function getType() : string { - return 'Scalar_MagicConst_Function'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php b/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php deleted file mode 100644 index 25d3de57c..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Scalar\MagicConst; - -use PhpParser\Node\Scalar\MagicConst; - -class Line extends MagicConst -{ - public function getName() : string { - return '__LINE__'; - } - - public function getType() : string { - return 'Scalar_MagicConst_Line'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.php b/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.php deleted file mode 100644 index d168d56f1..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Scalar\MagicConst; - -use PhpParser\Node\Scalar\MagicConst; - -class Method extends MagicConst -{ - public function getName() : string { - return '__METHOD__'; - } - - public function getType() : string { - return 'Scalar_MagicConst_Method'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php deleted file mode 100644 index 4fabb751a..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Scalar\MagicConst; - -use PhpParser\Node\Scalar\MagicConst; - -class Namespace_ extends MagicConst -{ - public function getName() : string { - return '__NAMESPACE__'; - } - - public function getType() : string { - return 'Scalar_MagicConst_Namespace'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.php deleted file mode 100644 index 5ee7e40a3..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Scalar\MagicConst; - -use PhpParser\Node\Scalar\MagicConst; - -class Trait_ extends MagicConst -{ - public function getName() : string { - return '__TRAIT__'; - } - - public function getType() : string { - return 'Scalar_MagicConst_Trait'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/String_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/String_.php deleted file mode 100644 index 6690a16bf..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Scalar/String_.php +++ /dev/null @@ -1,157 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Scalar; - -use PhpParser\Error; -use PhpParser\Node\Scalar; - -class String_ extends Scalar -{ - /* For use in "kind" attribute */ - const KIND_SINGLE_QUOTED = 1; - const KIND_DOUBLE_QUOTED = 2; - const KIND_HEREDOC = 3; - const KIND_NOWDOC = 4; - - /** @var string String value */ - public $value; - - protected static $replacements = [ - '\\' => '\\', - '$' => '$', - 'n' => "\n", - 'r' => "\r", - 't' => "\t", - 'f' => "\f", - 'v' => "\v", - 'e' => "\x1B", - ]; - - /** - * Constructs a string scalar node. - * - * @param string $value Value of the string - * @param array $attributes Additional attributes - */ - public function __construct(string $value, array $attributes = []) { - $this->attributes = $attributes; - $this->value = $value; - } - - public function getSubNodeNames() : array { - return ['value']; - } - - /** - * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes - */ - public static function fromString(string $str, array $attributes = [], bool $parseUnicodeEscape = true): self - { - $attributes['kind'] = ($str[0] === "'" || ($str[1] === "'" && ($str[0] === 'b' || $str[0] === 'B'))) - ? Scalar\String_::KIND_SINGLE_QUOTED - : Scalar\String_::KIND_DOUBLE_QUOTED; - - $attributes['rawValue'] = $str; - - $string = self::parse($str, $parseUnicodeEscape); - - return new self($string, $attributes); - } - - /** - * @internal - * - * Parses a string token. - * - * @param string $str String token content - * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes - * - * @return string The parsed string - */ - public static function parse(string $str, bool $parseUnicodeEscape = true) : string { - $bLength = 0; - if ('b' === $str[0] || 'B' === $str[0]) { - $bLength = 1; - } - - if ('\'' === $str[$bLength]) { - return str_replace( - ['\\\\', '\\\''], - ['\\', '\''], - substr($str, $bLength + 1, -1) - ); - } else { - return self::parseEscapeSequences( - substr($str, $bLength + 1, -1), '"', $parseUnicodeEscape - ); - } - } - - /** - * @internal - * - * Parses escape sequences in strings (all string types apart from single quoted). - * - * @param string $str String without quotes - * @param null|string $quote Quote type - * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes - * - * @return string String with escape sequences parsed - */ - public static function parseEscapeSequences(string $str, $quote, bool $parseUnicodeEscape = true) : string { - if (null !== $quote) { - $str = str_replace('\\' . $quote, $quote, $str); - } - - $extra = ''; - if ($parseUnicodeEscape) { - $extra = '|u\{([0-9a-fA-F]+)\}'; - } - - return preg_replace_callback( - '~\\\\([\\\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3}' . $extra . ')~', - function($matches) { - $str = $matches[1]; - - if (isset(self::$replacements[$str])) { - return self::$replacements[$str]; - } elseif ('x' === $str[0] || 'X' === $str[0]) { - return chr(hexdec(substr($str, 1))); - } elseif ('u' === $str[0]) { - return self::codePointToUtf8(hexdec($matches[2])); - } else { - return chr(octdec($str)); - } - }, - $str - ); - } - - /** - * Converts a Unicode code point to its UTF-8 encoded representation. - * - * @param int $num Code point - * - * @return string UTF-8 representation of code point - */ - private static function codePointToUtf8(int $num) : string { - if ($num <= 0x7F) { - return chr($num); - } - if ($num <= 0x7FF) { - return chr(($num>>6) + 0xC0) . chr(($num&0x3F) + 0x80); - } - if ($num <= 0xFFFF) { - return chr(($num>>12) + 0xE0) . chr((($num>>6)&0x3F) + 0x80) . chr(($num&0x3F) + 0x80); - } - if ($num <= 0x1FFFFF) { - return chr(($num>>18) + 0xF0) . chr((($num>>12)&0x3F) + 0x80) - . chr((($num>>6)&0x3F) + 0x80) . chr(($num&0x3F) + 0x80); - } - throw new Error('Invalid UTF-8 codepoint escape sequence: Codepoint too large'); - } - - public function getType() : string { - return 'Scalar_String'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt.php deleted file mode 100644 index 69d33e579..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node; - -use PhpParser\NodeAbstract; - -abstract class Stmt extends NodeAbstract -{ -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Break_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Break_.php deleted file mode 100644 index 6adc5a6c6..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Break_.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class Break_ extends Node\Stmt -{ - /** @var null|Node\Expr Number of loops to break */ - public $num; - - /** - * Constructs a break node. - * - * @param null|Node\Expr $num Number of loops to break - * @param array $attributes Additional attributes - */ - public function __construct(Node\Expr $num = null, array $attributes = []) { - $this->attributes = $attributes; - $this->num = $num; - } - - public function getSubNodeNames() : array { - return ['num']; - } - - public function getType() : string { - return 'Stmt_Break'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php deleted file mode 100644 index 2bf044c90..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class Case_ extends Node\Stmt -{ - /** @var null|Node\Expr Condition (null for default) */ - public $cond; - /** @var Node\Stmt[] Statements */ - public $stmts; - - /** - * Constructs a case node. - * - * @param null|Node\Expr $cond Condition (null for default) - * @param Node\Stmt[] $stmts Statements - * @param array $attributes Additional attributes - */ - public function __construct($cond, array $stmts = [], array $attributes = []) { - $this->attributes = $attributes; - $this->cond = $cond; - $this->stmts = $stmts; - } - - public function getSubNodeNames() : array { - return ['cond', 'stmts']; - } - - public function getType() : string { - return 'Stmt_Case'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php deleted file mode 100644 index 9b9c09478..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; -use PhpParser\Node\Expr; - -class Catch_ extends Node\Stmt -{ - /** @var Node\Name[] Types of exceptions to catch */ - public $types; - /** @var Expr\Variable|null Variable for exception */ - public $var; - /** @var Node\Stmt[] Statements */ - public $stmts; - - /** - * Constructs a catch node. - * - * @param Node\Name[] $types Types of exceptions to catch - * @param Expr\Variable|null $var Variable for exception - * @param Node\Stmt[] $stmts Statements - * @param array $attributes Additional attributes - */ - public function __construct( - array $types, Expr\Variable $var = null, array $stmts = [], array $attributes = [] - ) { - $this->attributes = $attributes; - $this->types = $types; - $this->var = $var; - $this->stmts = $stmts; - } - - public function getSubNodeNames() : array { - return ['types', 'var', 'stmts']; - } - - public function getType() : string { - return 'Stmt_Catch'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php deleted file mode 100644 index 1fc7f3362..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class ClassConst extends Node\Stmt -{ - /** @var int Modifiers */ - public $flags; - /** @var Node\Const_[] Constant declarations */ - public $consts; - /** @var Node\AttributeGroup[] */ - public $attrGroups; - - /** - * Constructs a class const list node. - * - * @param Node\Const_[] $consts Constant declarations - * @param int $flags Modifiers - * @param array $attributes Additional attributes - * @param Node\AttributeGroup[] $attrGroups PHP attribute groups - */ - public function __construct( - array $consts, - int $flags = 0, - array $attributes = [], - array $attrGroups = [] - ) { - $this->attributes = $attributes; - $this->flags = $flags; - $this->consts = $consts; - $this->attrGroups = $attrGroups; - } - - public function getSubNodeNames() : array { - return ['attrGroups', 'flags', 'consts']; - } - - /** - * Whether constant is explicitly or implicitly public. - * - * @return bool - */ - public function isPublic() : bool { - return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0 - || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0; - } - - /** - * Whether constant is protected. - * - * @return bool - */ - public function isProtected() : bool { - return (bool) ($this->flags & Class_::MODIFIER_PROTECTED); - } - - /** - * Whether constant is private. - * - * @return bool - */ - public function isPrivate() : bool { - return (bool) ($this->flags & Class_::MODIFIER_PRIVATE); - } - - /** - * Whether constant is final. - * - * @return bool - */ - public function isFinal() : bool { - return (bool) ($this->flags & Class_::MODIFIER_FINAL); - } - - public function getType() : string { - return 'Stmt_ClassConst'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php deleted file mode 100644 index 2fa4e861b..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php +++ /dev/null @@ -1,109 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -abstract class ClassLike extends Node\Stmt -{ - /** @var Node\Identifier|null Name */ - public $name; - /** @var Node\Stmt[] Statements */ - public $stmts; - /** @var Node\AttributeGroup[] PHP attribute groups */ - public $attrGroups; - - /** @var Node\Name|null Namespaced name (if using NameResolver) */ - public $namespacedName; - - /** - * @return TraitUse[] - */ - public function getTraitUses() : array { - $traitUses = []; - foreach ($this->stmts as $stmt) { - if ($stmt instanceof TraitUse) { - $traitUses[] = $stmt; - } - } - return $traitUses; - } - - /** - * @return ClassConst[] - */ - public function getConstants() : array { - $constants = []; - foreach ($this->stmts as $stmt) { - if ($stmt instanceof ClassConst) { - $constants[] = $stmt; - } - } - return $constants; - } - - /** - * @return Property[] - */ - public function getProperties() : array { - $properties = []; - foreach ($this->stmts as $stmt) { - if ($stmt instanceof Property) { - $properties[] = $stmt; - } - } - return $properties; - } - - /** - * Gets property with the given name defined directly in this class/interface/trait. - * - * @param string $name Name of the property - * - * @return Property|null Property node or null if the property does not exist - */ - public function getProperty(string $name) { - foreach ($this->stmts as $stmt) { - if ($stmt instanceof Property) { - foreach ($stmt->props as $prop) { - if ($prop instanceof PropertyProperty && $name === $prop->name->toString()) { - return $stmt; - } - } - } - } - return null; - } - - /** - * Gets all methods defined directly in this class/interface/trait - * - * @return ClassMethod[] - */ - public function getMethods() : array { - $methods = []; - foreach ($this->stmts as $stmt) { - if ($stmt instanceof ClassMethod) { - $methods[] = $stmt; - } - } - return $methods; - } - - /** - * Gets method with the given name defined directly in this class/interface/trait. - * - * @param string $name Name of the method (compared case-insensitively) - * - * @return ClassMethod|null Method node or null if the method does not exist - */ - public function getMethod(string $name) { - $lowerName = strtolower($name); - foreach ($this->stmts as $stmt) { - if ($stmt instanceof ClassMethod && $lowerName === $stmt->name->toLowerString()) { - return $stmt; - } - } - return null; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php deleted file mode 100644 index 09b877a92..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php +++ /dev/null @@ -1,159 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; -use PhpParser\Node\FunctionLike; - -class ClassMethod extends Node\Stmt implements FunctionLike -{ - /** @var int Flags */ - public $flags; - /** @var bool Whether to return by reference */ - public $byRef; - /** @var Node\Identifier Name */ - public $name; - /** @var Node\Param[] Parameters */ - public $params; - /** @var null|Node\Identifier|Node\Name|Node\ComplexType Return type */ - public $returnType; - /** @var Node\Stmt[]|null Statements */ - public $stmts; - /** @var Node\AttributeGroup[] PHP attribute groups */ - public $attrGroups; - - private static $magicNames = [ - '__construct' => true, - '__destruct' => true, - '__call' => true, - '__callstatic' => true, - '__get' => true, - '__set' => true, - '__isset' => true, - '__unset' => true, - '__sleep' => true, - '__wakeup' => true, - '__tostring' => true, - '__set_state' => true, - '__clone' => true, - '__invoke' => true, - '__debuginfo' => true, - ]; - - /** - * Constructs a class method node. - * - * @param string|Node\Identifier $name Name - * @param array $subNodes Array of the following optional subnodes: - * 'flags => MODIFIER_PUBLIC: Flags - * 'byRef' => false : Whether to return by reference - * 'params' => array() : Parameters - * 'returnType' => null : Return type - * 'stmts' => array() : Statements - * 'attrGroups' => array() : PHP attribute groups - * @param array $attributes Additional attributes - */ - public function __construct($name, array $subNodes = [], array $attributes = []) { - $this->attributes = $attributes; - $this->flags = $subNodes['flags'] ?? $subNodes['type'] ?? 0; - $this->byRef = $subNodes['byRef'] ?? false; - $this->name = \is_string($name) ? new Node\Identifier($name) : $name; - $this->params = $subNodes['params'] ?? []; - $returnType = $subNodes['returnType'] ?? null; - $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType; - $this->stmts = array_key_exists('stmts', $subNodes) ? $subNodes['stmts'] : []; - $this->attrGroups = $subNodes['attrGroups'] ?? []; - } - - public function getSubNodeNames() : array { - return ['attrGroups', 'flags', 'byRef', 'name', 'params', 'returnType', 'stmts']; - } - - public function returnsByRef() : bool { - return $this->byRef; - } - - public function getParams() : array { - return $this->params; - } - - public function getReturnType() { - return $this->returnType; - } - - public function getStmts() { - return $this->stmts; - } - - public function getAttrGroups() : array { - return $this->attrGroups; - } - - /** - * Whether the method is explicitly or implicitly public. - * - * @return bool - */ - public function isPublic() : bool { - return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0 - || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0; - } - - /** - * Whether the method is protected. - * - * @return bool - */ - public function isProtected() : bool { - return (bool) ($this->flags & Class_::MODIFIER_PROTECTED); - } - - /** - * Whether the method is private. - * - * @return bool - */ - public function isPrivate() : bool { - return (bool) ($this->flags & Class_::MODIFIER_PRIVATE); - } - - /** - * Whether the method is abstract. - * - * @return bool - */ - public function isAbstract() : bool { - return (bool) ($this->flags & Class_::MODIFIER_ABSTRACT); - } - - /** - * Whether the method is final. - * - * @return bool - */ - public function isFinal() : bool { - return (bool) ($this->flags & Class_::MODIFIER_FINAL); - } - - /** - * Whether the method is static. - * - * @return bool - */ - public function isStatic() : bool { - return (bool) ($this->flags & Class_::MODIFIER_STATIC); - } - - /** - * Whether the method is magic. - * - * @return bool - */ - public function isMagic() : bool { - return isset(self::$magicNames[$this->name->toLowerString()]); - } - - public function getType() : string { - return 'Stmt_ClassMethod'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php deleted file mode 100644 index 52ed6c6cd..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php +++ /dev/null @@ -1,137 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Error; -use PhpParser\Node; - -class Class_ extends ClassLike -{ - const MODIFIER_PUBLIC = 1; - const MODIFIER_PROTECTED = 2; - const MODIFIER_PRIVATE = 4; - const MODIFIER_STATIC = 8; - const MODIFIER_ABSTRACT = 16; - const MODIFIER_FINAL = 32; - const MODIFIER_READONLY = 64; - - const VISIBILITY_MODIFIER_MASK = 7; // 1 | 2 | 4 - - /** @var int Type */ - public $flags; - /** @var null|Node\Name Name of extended class */ - public $extends; - /** @var Node\Name[] Names of implemented interfaces */ - public $implements; - - /** - * Constructs a class node. - * - * @param string|Node\Identifier|null $name Name - * @param array $subNodes Array of the following optional subnodes: - * 'flags' => 0 : Flags - * 'extends' => null : Name of extended class - * 'implements' => array(): Names of implemented interfaces - * 'stmts' => array(): Statements - * 'attrGroups' => array(): PHP attribute groups - * @param array $attributes Additional attributes - */ - public function __construct($name, array $subNodes = [], array $attributes = []) { - $this->attributes = $attributes; - $this->flags = $subNodes['flags'] ?? $subNodes['type'] ?? 0; - $this->name = \is_string($name) ? new Node\Identifier($name) : $name; - $this->extends = $subNodes['extends'] ?? null; - $this->implements = $subNodes['implements'] ?? []; - $this->stmts = $subNodes['stmts'] ?? []; - $this->attrGroups = $subNodes['attrGroups'] ?? []; - } - - public function getSubNodeNames() : array { - return ['attrGroups', 'flags', 'name', 'extends', 'implements', 'stmts']; - } - - /** - * Whether the class is explicitly abstract. - * - * @return bool - */ - public function isAbstract() : bool { - return (bool) ($this->flags & self::MODIFIER_ABSTRACT); - } - - /** - * Whether the class is final. - * - * @return bool - */ - public function isFinal() : bool { - return (bool) ($this->flags & self::MODIFIER_FINAL); - } - - public function isReadonly() : bool { - return (bool) ($this->flags & self::MODIFIER_READONLY); - } - - /** - * Whether the class is anonymous. - * - * @return bool - */ - public function isAnonymous() : bool { - return null === $this->name; - } - - /** - * @internal - */ - public static function verifyClassModifier($a, $b) { - if ($a & self::MODIFIER_ABSTRACT && $b & self::MODIFIER_ABSTRACT) { - throw new Error('Multiple abstract modifiers are not allowed'); - } - - if ($a & self::MODIFIER_FINAL && $b & self::MODIFIER_FINAL) { - throw new Error('Multiple final modifiers are not allowed'); - } - - if ($a & self::MODIFIER_READONLY && $b & self::MODIFIER_READONLY) { - throw new Error('Multiple readonly modifiers are not allowed'); - } - - if ($a & 48 && $b & 48) { - throw new Error('Cannot use the final modifier on an abstract class'); - } - } - - /** - * @internal - */ - public static function verifyModifier($a, $b) { - if ($a & self::VISIBILITY_MODIFIER_MASK && $b & self::VISIBILITY_MODIFIER_MASK) { - throw new Error('Multiple access type modifiers are not allowed'); - } - - if ($a & self::MODIFIER_ABSTRACT && $b & self::MODIFIER_ABSTRACT) { - throw new Error('Multiple abstract modifiers are not allowed'); - } - - if ($a & self::MODIFIER_STATIC && $b & self::MODIFIER_STATIC) { - throw new Error('Multiple static modifiers are not allowed'); - } - - if ($a & self::MODIFIER_FINAL && $b & self::MODIFIER_FINAL) { - throw new Error('Multiple final modifiers are not allowed'); - } - - if ($a & self::MODIFIER_READONLY && $b & self::MODIFIER_READONLY) { - throw new Error('Multiple readonly modifiers are not allowed'); - } - - if ($a & 48 && $b & 48) { - throw new Error('Cannot use the final modifier on an abstract class member'); - } - } - - public function getType() : string { - return 'Stmt_Class'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php deleted file mode 100644 index e6316345e..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class Const_ extends Node\Stmt -{ - /** @var Node\Const_[] Constant declarations */ - public $consts; - - /** - * Constructs a const list node. - * - * @param Node\Const_[] $consts Constant declarations - * @param array $attributes Additional attributes - */ - public function __construct(array $consts, array $attributes = []) { - $this->attributes = $attributes; - $this->consts = $consts; - } - - public function getSubNodeNames() : array { - return ['consts']; - } - - public function getType() : string { - return 'Stmt_Const'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php deleted file mode 100644 index 24882683b..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class Continue_ extends Node\Stmt -{ - /** @var null|Node\Expr Number of loops to continue */ - public $num; - - /** - * Constructs a continue node. - * - * @param null|Node\Expr $num Number of loops to continue - * @param array $attributes Additional attributes - */ - public function __construct(Node\Expr $num = null, array $attributes = []) { - $this->attributes = $attributes; - $this->num = $num; - } - - public function getSubNodeNames() : array { - return ['num']; - } - - public function getType() : string { - return 'Stmt_Continue'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php deleted file mode 100644 index ac07f30c7..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class DeclareDeclare extends Node\Stmt -{ - /** @var Node\Identifier Key */ - public $key; - /** @var Node\Expr Value */ - public $value; - - /** - * Constructs a declare key=>value pair node. - * - * @param string|Node\Identifier $key Key - * @param Node\Expr $value Value - * @param array $attributes Additional attributes - */ - public function __construct($key, Node\Expr $value, array $attributes = []) { - $this->attributes = $attributes; - $this->key = \is_string($key) ? new Node\Identifier($key) : $key; - $this->value = $value; - } - - public function getSubNodeNames() : array { - return ['key', 'value']; - } - - public function getType() : string { - return 'Stmt_DeclareDeclare'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php deleted file mode 100644 index f46ff0baf..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class Declare_ extends Node\Stmt -{ - /** @var DeclareDeclare[] List of declares */ - public $declares; - /** @var Node\Stmt[]|null Statements */ - public $stmts; - - /** - * Constructs a declare node. - * - * @param DeclareDeclare[] $declares List of declares - * @param Node\Stmt[]|null $stmts Statements - * @param array $attributes Additional attributes - */ - public function __construct(array $declares, array $stmts = null, array $attributes = []) { - $this->attributes = $attributes; - $this->declares = $declares; - $this->stmts = $stmts; - } - - public function getSubNodeNames() : array { - return ['declares', 'stmts']; - } - - public function getType() : string { - return 'Stmt_Declare'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php deleted file mode 100644 index 78e90da03..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class Do_ extends Node\Stmt -{ - /** @var Node\Stmt[] Statements */ - public $stmts; - /** @var Node\Expr Condition */ - public $cond; - - /** - * Constructs a do while node. - * - * @param Node\Expr $cond Condition - * @param Node\Stmt[] $stmts Statements - * @param array $attributes Additional attributes - */ - public function __construct(Node\Expr $cond, array $stmts = [], array $attributes = []) { - $this->attributes = $attributes; - $this->cond = $cond; - $this->stmts = $stmts; - } - - public function getSubNodeNames() : array { - return ['stmts', 'cond']; - } - - public function getType() : string { - return 'Stmt_Do'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php deleted file mode 100644 index 7cc50d5d6..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class Echo_ extends Node\Stmt -{ - /** @var Node\Expr[] Expressions */ - public $exprs; - - /** - * Constructs an echo node. - * - * @param Node\Expr[] $exprs Expressions - * @param array $attributes Additional attributes - */ - public function __construct(array $exprs, array $attributes = []) { - $this->attributes = $attributes; - $this->exprs = $exprs; - } - - public function getSubNodeNames() : array { - return ['exprs']; - } - - public function getType() : string { - return 'Stmt_Echo'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php deleted file mode 100644 index eef1ece32..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class ElseIf_ extends Node\Stmt -{ - /** @var Node\Expr Condition */ - public $cond; - /** @var Node\Stmt[] Statements */ - public $stmts; - - /** - * Constructs an elseif node. - * - * @param Node\Expr $cond Condition - * @param Node\Stmt[] $stmts Statements - * @param array $attributes Additional attributes - */ - public function __construct(Node\Expr $cond, array $stmts = [], array $attributes = []) { - $this->attributes = $attributes; - $this->cond = $cond; - $this->stmts = $stmts; - } - - public function getSubNodeNames() : array { - return ['cond', 'stmts']; - } - - public function getType() : string { - return 'Stmt_ElseIf'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php deleted file mode 100644 index 0e61778e2..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class Else_ extends Node\Stmt -{ - /** @var Node\Stmt[] Statements */ - public $stmts; - - /** - * Constructs an else node. - * - * @param Node\Stmt[] $stmts Statements - * @param array $attributes Additional attributes - */ - public function __construct(array $stmts = [], array $attributes = []) { - $this->attributes = $attributes; - $this->stmts = $stmts; - } - - public function getSubNodeNames() : array { - return ['stmts']; - } - - public function getType() : string { - return 'Stmt_Else'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/EnumCase.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/EnumCase.php deleted file mode 100644 index 5beff8b39..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/EnumCase.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; -use PhpParser\Node\AttributeGroup; - -class EnumCase extends Node\Stmt -{ - /** @var Node\Identifier Enum case name */ - public $name; - /** @var Node\Expr|null Enum case expression */ - public $expr; - /** @var Node\AttributeGroup[] PHP attribute groups */ - public $attrGroups; - - /** - * @param string|Node\Identifier $name Enum case name - * @param Node\Expr|null $expr Enum case expression - * @param AttributeGroup[] $attrGroups PHP attribute groups - * @param array $attributes Additional attributes - */ - public function __construct($name, Node\Expr $expr = null, array $attrGroups = [], array $attributes = []) { - parent::__construct($attributes); - $this->name = \is_string($name) ? new Node\Identifier($name) : $name; - $this->expr = $expr; - $this->attrGroups = $attrGroups; - } - - public function getSubNodeNames() : array { - return ['attrGroups', 'name', 'expr']; - } - - public function getType() : string { - return 'Stmt_EnumCase'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Enum_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Enum_.php deleted file mode 100644 index 3a50c225d..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Enum_.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class Enum_ extends ClassLike -{ - /** @var null|Node\Identifier Scalar Type */ - public $scalarType; - /** @var Node\Name[] Names of implemented interfaces */ - public $implements; - - /** - * @param string|Node\Identifier|null $name Name - * @param array $subNodes Array of the following optional subnodes: - * 'scalarType' => null : Scalar type - * 'implements' => array() : Names of implemented interfaces - * 'stmts' => array() : Statements - * 'attrGroups' => array() : PHP attribute groups - * @param array $attributes Additional attributes - */ - public function __construct($name, array $subNodes = [], array $attributes = []) { - $this->name = \is_string($name) ? new Node\Identifier($name) : $name; - $this->scalarType = $subNodes['scalarType'] ?? null; - $this->implements = $subNodes['implements'] ?? []; - $this->stmts = $subNodes['stmts'] ?? []; - $this->attrGroups = $subNodes['attrGroups'] ?? []; - - parent::__construct($attributes); - } - - public function getSubNodeNames() : array { - return ['attrGroups', 'name', 'scalarType', 'implements', 'stmts']; - } - - public function getType() : string { - return 'Stmt_Enum'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.php deleted file mode 100644 index 99d1687de..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -/** - * Represents statements of type "expr;" - */ -class Expression extends Node\Stmt -{ - /** @var Node\Expr Expression */ - public $expr; - - /** - * Constructs an expression statement. - * - * @param Node\Expr $expr Expression - * @param array $attributes Additional attributes - */ - public function __construct(Node\Expr $expr, array $attributes = []) { - $this->attributes = $attributes; - $this->expr = $expr; - } - - public function getSubNodeNames() : array { - return ['expr']; - } - - public function getType() : string { - return 'Stmt_Expression'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php deleted file mode 100644 index d55b8b687..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class Finally_ extends Node\Stmt -{ - /** @var Node\Stmt[] Statements */ - public $stmts; - - /** - * Constructs a finally node. - * - * @param Node\Stmt[] $stmts Statements - * @param array $attributes Additional attributes - */ - public function __construct(array $stmts = [], array $attributes = []) { - $this->attributes = $attributes; - $this->stmts = $stmts; - } - - public function getSubNodeNames() : array { - return ['stmts']; - } - - public function getType() : string { - return 'Stmt_Finally'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php deleted file mode 100644 index 1323d37cf..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class For_ extends Node\Stmt -{ - /** @var Node\Expr[] Init expressions */ - public $init; - /** @var Node\Expr[] Loop conditions */ - public $cond; - /** @var Node\Expr[] Loop expressions */ - public $loop; - /** @var Node\Stmt[] Statements */ - public $stmts; - - /** - * Constructs a for loop node. - * - * @param array $subNodes Array of the following optional subnodes: - * 'init' => array(): Init expressions - * 'cond' => array(): Loop conditions - * 'loop' => array(): Loop expressions - * 'stmts' => array(): Statements - * @param array $attributes Additional attributes - */ - public function __construct(array $subNodes = [], array $attributes = []) { - $this->attributes = $attributes; - $this->init = $subNodes['init'] ?? []; - $this->cond = $subNodes['cond'] ?? []; - $this->loop = $subNodes['loop'] ?? []; - $this->stmts = $subNodes['stmts'] ?? []; - } - - public function getSubNodeNames() : array { - return ['init', 'cond', 'loop', 'stmts']; - } - - public function getType() : string { - return 'Stmt_For'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php deleted file mode 100644 index 0556a7ce5..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class Foreach_ extends Node\Stmt -{ - /** @var Node\Expr Expression to iterate */ - public $expr; - /** @var null|Node\Expr Variable to assign key to */ - public $keyVar; - /** @var bool Whether to assign value by reference */ - public $byRef; - /** @var Node\Expr Variable to assign value to */ - public $valueVar; - /** @var Node\Stmt[] Statements */ - public $stmts; - - /** - * Constructs a foreach node. - * - * @param Node\Expr $expr Expression to iterate - * @param Node\Expr $valueVar Variable to assign value to - * @param array $subNodes Array of the following optional subnodes: - * 'keyVar' => null : Variable to assign key to - * 'byRef' => false : Whether to assign value by reference - * 'stmts' => array(): Statements - * @param array $attributes Additional attributes - */ - public function __construct(Node\Expr $expr, Node\Expr $valueVar, array $subNodes = [], array $attributes = []) { - $this->attributes = $attributes; - $this->expr = $expr; - $this->keyVar = $subNodes['keyVar'] ?? null; - $this->byRef = $subNodes['byRef'] ?? false; - $this->valueVar = $valueVar; - $this->stmts = $subNodes['stmts'] ?? []; - } - - public function getSubNodeNames() : array { - return ['expr', 'keyVar', 'byRef', 'valueVar', 'stmts']; - } - - public function getType() : string { - return 'Stmt_Foreach'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php deleted file mode 100644 index c2ccae24e..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; -use PhpParser\Node\FunctionLike; - -class Function_ extends Node\Stmt implements FunctionLike -{ - /** @var bool Whether function returns by reference */ - public $byRef; - /** @var Node\Identifier Name */ - public $name; - /** @var Node\Param[] Parameters */ - public $params; - /** @var null|Node\Identifier|Node\Name|Node\ComplexType Return type */ - public $returnType; - /** @var Node\Stmt[] Statements */ - public $stmts; - /** @var Node\AttributeGroup[] PHP attribute groups */ - public $attrGroups; - - /** @var Node\Name|null Namespaced name (if using NameResolver) */ - public $namespacedName; - - /** - * Constructs a function node. - * - * @param string|Node\Identifier $name Name - * @param array $subNodes Array of the following optional subnodes: - * 'byRef' => false : Whether to return by reference - * 'params' => array(): Parameters - * 'returnType' => null : Return type - * 'stmts' => array(): Statements - * 'attrGroups' => array(): PHP attribute groups - * @param array $attributes Additional attributes - */ - public function __construct($name, array $subNodes = [], array $attributes = []) { - $this->attributes = $attributes; - $this->byRef = $subNodes['byRef'] ?? false; - $this->name = \is_string($name) ? new Node\Identifier($name) : $name; - $this->params = $subNodes['params'] ?? []; - $returnType = $subNodes['returnType'] ?? null; - $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType; - $this->stmts = $subNodes['stmts'] ?? []; - $this->attrGroups = $subNodes['attrGroups'] ?? []; - } - - public function getSubNodeNames() : array { - return ['attrGroups', 'byRef', 'name', 'params', 'returnType', 'stmts']; - } - - public function returnsByRef() : bool { - return $this->byRef; - } - - public function getParams() : array { - return $this->params; - } - - public function getReturnType() { - return $this->returnType; - } - - public function getAttrGroups() : array { - return $this->attrGroups; - } - - /** @return Node\Stmt[] */ - public function getStmts() : array { - return $this->stmts; - } - - public function getType() : string { - return 'Stmt_Function'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php deleted file mode 100644 index a0022ad93..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class Global_ extends Node\Stmt -{ - /** @var Node\Expr[] Variables */ - public $vars; - - /** - * Constructs a global variables list node. - * - * @param Node\Expr[] $vars Variables to unset - * @param array $attributes Additional attributes - */ - public function __construct(array $vars, array $attributes = []) { - $this->attributes = $attributes; - $this->vars = $vars; - } - - public function getSubNodeNames() : array { - return ['vars']; - } - - public function getType() : string { - return 'Stmt_Global'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php deleted file mode 100644 index 24a57f780..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node\Identifier; -use PhpParser\Node\Stmt; - -class Goto_ extends Stmt -{ - /** @var Identifier Name of label to jump to */ - public $name; - - /** - * Constructs a goto node. - * - * @param string|Identifier $name Name of label to jump to - * @param array $attributes Additional attributes - */ - public function __construct($name, array $attributes = []) { - $this->attributes = $attributes; - $this->name = \is_string($name) ? new Identifier($name) : $name; - } - - public function getSubNodeNames() : array { - return ['name']; - } - - public function getType() : string { - return 'Stmt_Goto'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php deleted file mode 100644 index 24520d223..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node\Name; -use PhpParser\Node\Stmt; - -class GroupUse extends Stmt -{ - /** @var int Type of group use */ - public $type; - /** @var Name Prefix for uses */ - public $prefix; - /** @var UseUse[] Uses */ - public $uses; - - /** - * Constructs a group use node. - * - * @param Name $prefix Prefix for uses - * @param UseUse[] $uses Uses - * @param int $type Type of group use - * @param array $attributes Additional attributes - */ - public function __construct(Name $prefix, array $uses, int $type = Use_::TYPE_NORMAL, array $attributes = []) { - $this->attributes = $attributes; - $this->type = $type; - $this->prefix = $prefix; - $this->uses = $uses; - } - - public function getSubNodeNames() : array { - return ['type', 'prefix', 'uses']; - } - - public function getType() : string { - return 'Stmt_GroupUse'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php deleted file mode 100644 index 8e624e0f1..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node\Stmt; - -class HaltCompiler extends Stmt -{ - /** @var string Remaining text after halt compiler statement. */ - public $remaining; - - /** - * Constructs a __halt_compiler node. - * - * @param string $remaining Remaining text after halt compiler statement. - * @param array $attributes Additional attributes - */ - public function __construct(string $remaining, array $attributes = []) { - $this->attributes = $attributes; - $this->remaining = $remaining; - } - - public function getSubNodeNames() : array { - return ['remaining']; - } - - public function getType() : string { - return 'Stmt_HaltCompiler'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php deleted file mode 100644 index a1bae4bf8..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class If_ extends Node\Stmt -{ - /** @var Node\Expr Condition expression */ - public $cond; - /** @var Node\Stmt[] Statements */ - public $stmts; - /** @var ElseIf_[] Elseif clauses */ - public $elseifs; - /** @var null|Else_ Else clause */ - public $else; - - /** - * Constructs an if node. - * - * @param Node\Expr $cond Condition - * @param array $subNodes Array of the following optional subnodes: - * 'stmts' => array(): Statements - * 'elseifs' => array(): Elseif clauses - * 'else' => null : Else clause - * @param array $attributes Additional attributes - */ - public function __construct(Node\Expr $cond, array $subNodes = [], array $attributes = []) { - $this->attributes = $attributes; - $this->cond = $cond; - $this->stmts = $subNodes['stmts'] ?? []; - $this->elseifs = $subNodes['elseifs'] ?? []; - $this->else = $subNodes['else'] ?? null; - } - - public function getSubNodeNames() : array { - return ['cond', 'stmts', 'elseifs', 'else']; - } - - public function getType() : string { - return 'Stmt_If'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php deleted file mode 100644 index 0711d2842..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node\Stmt; - -class InlineHTML extends Stmt -{ - /** @var string String */ - public $value; - - /** - * Constructs an inline HTML node. - * - * @param string $value String - * @param array $attributes Additional attributes - */ - public function __construct(string $value, array $attributes = []) { - $this->attributes = $attributes; - $this->value = $value; - } - - public function getSubNodeNames() : array { - return ['value']; - } - - public function getType() : string { - return 'Stmt_InlineHTML'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php deleted file mode 100644 index 4d587dd48..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class Interface_ extends ClassLike -{ - /** @var Node\Name[] Extended interfaces */ - public $extends; - - /** - * Constructs a class node. - * - * @param string|Node\Identifier $name Name - * @param array $subNodes Array of the following optional subnodes: - * 'extends' => array(): Name of extended interfaces - * 'stmts' => array(): Statements - * 'attrGroups' => array(): PHP attribute groups - * @param array $attributes Additional attributes - */ - public function __construct($name, array $subNodes = [], array $attributes = []) { - $this->attributes = $attributes; - $this->name = \is_string($name) ? new Node\Identifier($name) : $name; - $this->extends = $subNodes['extends'] ?? []; - $this->stmts = $subNodes['stmts'] ?? []; - $this->attrGroups = $subNodes['attrGroups'] ?? []; - } - - public function getSubNodeNames() : array { - return ['attrGroups', 'name', 'extends', 'stmts']; - } - - public function getType() : string { - return 'Stmt_Interface'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php deleted file mode 100644 index 3edcb3be7..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node\Identifier; -use PhpParser\Node\Stmt; - -class Label extends Stmt -{ - /** @var Identifier Name */ - public $name; - - /** - * Constructs a label node. - * - * @param string|Identifier $name Name - * @param array $attributes Additional attributes - */ - public function __construct($name, array $attributes = []) { - $this->attributes = $attributes; - $this->name = \is_string($name) ? new Identifier($name) : $name; - } - - public function getSubNodeNames() : array { - return ['name']; - } - - public function getType() : string { - return 'Stmt_Label'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php deleted file mode 100644 index c63204577..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class Namespace_ extends Node\Stmt -{ - /* For use in the "kind" attribute */ - const KIND_SEMICOLON = 1; - const KIND_BRACED = 2; - - /** @var null|Node\Name Name */ - public $name; - /** @var Node\Stmt[] Statements */ - public $stmts; - - /** - * Constructs a namespace node. - * - * @param null|Node\Name $name Name - * @param null|Node\Stmt[] $stmts Statements - * @param array $attributes Additional attributes - */ - public function __construct(Node\Name $name = null, $stmts = [], array $attributes = []) { - $this->attributes = $attributes; - $this->name = $name; - $this->stmts = $stmts; - } - - public function getSubNodeNames() : array { - return ['name', 'stmts']; - } - - public function getType() : string { - return 'Stmt_Namespace'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php deleted file mode 100644 index f86f8df7d..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -/** Nop/empty statement (;). */ -class Nop extends Node\Stmt -{ - public function getSubNodeNames() : array { - return []; - } - - public function getType() : string { - return 'Stmt_Nop'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php deleted file mode 100644 index bc781bbff..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; -use PhpParser\Node\ComplexType; -use PhpParser\Node\Identifier; -use PhpParser\Node\Name; - -class Property extends Node\Stmt -{ - /** @var int Modifiers */ - public $flags; - /** @var PropertyProperty[] Properties */ - public $props; - /** @var null|Identifier|Name|ComplexType Type declaration */ - public $type; - /** @var Node\AttributeGroup[] PHP attribute groups */ - public $attrGroups; - - /** - * Constructs a class property list node. - * - * @param int $flags Modifiers - * @param PropertyProperty[] $props Properties - * @param array $attributes Additional attributes - * @param null|string|Identifier|Name|ComplexType $type Type declaration - * @param Node\AttributeGroup[] $attrGroups PHP attribute groups - */ - public function __construct(int $flags, array $props, array $attributes = [], $type = null, array $attrGroups = []) { - $this->attributes = $attributes; - $this->flags = $flags; - $this->props = $props; - $this->type = \is_string($type) ? new Identifier($type) : $type; - $this->attrGroups = $attrGroups; - } - - public function getSubNodeNames() : array { - return ['attrGroups', 'flags', 'type', 'props']; - } - - /** - * Whether the property is explicitly or implicitly public. - * - * @return bool - */ - public function isPublic() : bool { - return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0 - || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0; - } - - /** - * Whether the property is protected. - * - * @return bool - */ - public function isProtected() : bool { - return (bool) ($this->flags & Class_::MODIFIER_PROTECTED); - } - - /** - * Whether the property is private. - * - * @return bool - */ - public function isPrivate() : bool { - return (bool) ($this->flags & Class_::MODIFIER_PRIVATE); - } - - /** - * Whether the property is static. - * - * @return bool - */ - public function isStatic() : bool { - return (bool) ($this->flags & Class_::MODIFIER_STATIC); - } - - /** - * Whether the property is readonly. - * - * @return bool - */ - public function isReadonly() : bool { - return (bool) ($this->flags & Class_::MODIFIER_READONLY); - } - - public function getType() : string { - return 'Stmt_Property'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php deleted file mode 100644 index 205731e20..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class PropertyProperty extends Node\Stmt -{ - /** @var Node\VarLikeIdentifier Name */ - public $name; - /** @var null|Node\Expr Default */ - public $default; - - /** - * Constructs a class property node. - * - * @param string|Node\VarLikeIdentifier $name Name - * @param null|Node\Expr $default Default value - * @param array $attributes Additional attributes - */ - public function __construct($name, Node\Expr $default = null, array $attributes = []) { - $this->attributes = $attributes; - $this->name = \is_string($name) ? new Node\VarLikeIdentifier($name) : $name; - $this->default = $default; - } - - public function getSubNodeNames() : array { - return ['name', 'default']; - } - - public function getType() : string { - return 'Stmt_PropertyProperty'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php deleted file mode 100644 index efc578c58..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class Return_ extends Node\Stmt -{ - /** @var null|Node\Expr Expression */ - public $expr; - - /** - * Constructs a return node. - * - * @param null|Node\Expr $expr Expression - * @param array $attributes Additional attributes - */ - public function __construct(Node\Expr $expr = null, array $attributes = []) { - $this->attributes = $attributes; - $this->expr = $expr; - } - - public function getSubNodeNames() : array { - return ['expr']; - } - - public function getType() : string { - return 'Stmt_Return'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php deleted file mode 100644 index 29584560d..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; -use PhpParser\Node\Expr; - -class StaticVar extends Node\Stmt -{ - /** @var Expr\Variable Variable */ - public $var; - /** @var null|Node\Expr Default value */ - public $default; - - /** - * Constructs a static variable node. - * - * @param Expr\Variable $var Name - * @param null|Node\Expr $default Default value - * @param array $attributes Additional attributes - */ - public function __construct( - Expr\Variable $var, Node\Expr $default = null, array $attributes = [] - ) { - $this->attributes = $attributes; - $this->var = $var; - $this->default = $default; - } - - public function getSubNodeNames() : array { - return ['var', 'default']; - } - - public function getType() : string { - return 'Stmt_StaticVar'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php deleted file mode 100644 index 464898ffa..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node\Stmt; - -class Static_ extends Stmt -{ - /** @var StaticVar[] Variable definitions */ - public $vars; - - /** - * Constructs a static variables list node. - * - * @param StaticVar[] $vars Variable definitions - * @param array $attributes Additional attributes - */ - public function __construct(array $vars, array $attributes = []) { - $this->attributes = $attributes; - $this->vars = $vars; - } - - public function getSubNodeNames() : array { - return ['vars']; - } - - public function getType() : string { - return 'Stmt_Static'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php deleted file mode 100644 index 2c8dae022..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class Switch_ extends Node\Stmt -{ - /** @var Node\Expr Condition */ - public $cond; - /** @var Case_[] Case list */ - public $cases; - - /** - * Constructs a case node. - * - * @param Node\Expr $cond Condition - * @param Case_[] $cases Case list - * @param array $attributes Additional attributes - */ - public function __construct(Node\Expr $cond, array $cases, array $attributes = []) { - $this->attributes = $attributes; - $this->cond = $cond; - $this->cases = $cases; - } - - public function getSubNodeNames() : array { - return ['cond', 'cases']; - } - - public function getType() : string { - return 'Stmt_Switch'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php deleted file mode 100644 index a34e2b362..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class Throw_ extends Node\Stmt -{ - /** @var Node\Expr Expression */ - public $expr; - - /** - * Constructs a legacy throw statement node. - * - * @param Node\Expr $expr Expression - * @param array $attributes Additional attributes - */ - public function __construct(Node\Expr $expr, array $attributes = []) { - $this->attributes = $attributes; - $this->expr = $expr; - } - - public function getSubNodeNames() : array { - return ['expr']; - } - - public function getType() : string { - return 'Stmt_Throw'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php deleted file mode 100644 index 9e97053b4..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class TraitUse extends Node\Stmt -{ - /** @var Node\Name[] Traits */ - public $traits; - /** @var TraitUseAdaptation[] Adaptations */ - public $adaptations; - - /** - * Constructs a trait use node. - * - * @param Node\Name[] $traits Traits - * @param TraitUseAdaptation[] $adaptations Adaptations - * @param array $attributes Additional attributes - */ - public function __construct(array $traits, array $adaptations = [], array $attributes = []) { - $this->attributes = $attributes; - $this->traits = $traits; - $this->adaptations = $adaptations; - } - - public function getSubNodeNames() : array { - return ['traits', 'adaptations']; - } - - public function getType() : string { - return 'Stmt_TraitUse'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php deleted file mode 100644 index 8bdd2c041..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php +++ /dev/null @@ -1,13 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -abstract class TraitUseAdaptation extends Node\Stmt -{ - /** @var Node\Name|null Trait name */ - public $trait; - /** @var Node\Identifier Method name */ - public $method; -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php deleted file mode 100644 index a3bccbd10..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt\TraitUseAdaptation; - -use PhpParser\Node; - -class Alias extends Node\Stmt\TraitUseAdaptation -{ - /** @var null|int New modifier */ - public $newModifier; - /** @var null|Node\Identifier New name */ - public $newName; - - /** - * Constructs a trait use precedence adaptation node. - * - * @param null|Node\Name $trait Trait name - * @param string|Node\Identifier $method Method name - * @param null|int $newModifier New modifier - * @param null|string|Node\Identifier $newName New name - * @param array $attributes Additional attributes - */ - public function __construct($trait, $method, $newModifier, $newName, array $attributes = []) { - $this->attributes = $attributes; - $this->trait = $trait; - $this->method = \is_string($method) ? new Node\Identifier($method) : $method; - $this->newModifier = $newModifier; - $this->newName = \is_string($newName) ? new Node\Identifier($newName) : $newName; - } - - public function getSubNodeNames() : array { - return ['trait', 'method', 'newModifier', 'newName']; - } - - public function getType() : string { - return 'Stmt_TraitUseAdaptation_Alias'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php deleted file mode 100644 index 80385f64e..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt\TraitUseAdaptation; - -use PhpParser\Node; - -class Precedence extends Node\Stmt\TraitUseAdaptation -{ - /** @var Node\Name[] Overwritten traits */ - public $insteadof; - - /** - * Constructs a trait use precedence adaptation node. - * - * @param Node\Name $trait Trait name - * @param string|Node\Identifier $method Method name - * @param Node\Name[] $insteadof Overwritten traits - * @param array $attributes Additional attributes - */ - public function __construct(Node\Name $trait, $method, array $insteadof, array $attributes = []) { - $this->attributes = $attributes; - $this->trait = $trait; - $this->method = \is_string($method) ? new Node\Identifier($method) : $method; - $this->insteadof = $insteadof; - } - - public function getSubNodeNames() : array { - return ['trait', 'method', 'insteadof']; - } - - public function getType() : string { - return 'Stmt_TraitUseAdaptation_Precedence'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php deleted file mode 100644 index 0cec203ac..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class Trait_ extends ClassLike -{ - /** - * Constructs a trait node. - * - * @param string|Node\Identifier $name Name - * @param array $subNodes Array of the following optional subnodes: - * 'stmts' => array(): Statements - * 'attrGroups' => array(): PHP attribute groups - * @param array $attributes Additional attributes - */ - public function __construct($name, array $subNodes = [], array $attributes = []) { - $this->attributes = $attributes; - $this->name = \is_string($name) ? new Node\Identifier($name) : $name; - $this->stmts = $subNodes['stmts'] ?? []; - $this->attrGroups = $subNodes['attrGroups'] ?? []; - } - - public function getSubNodeNames() : array { - return ['attrGroups', 'name', 'stmts']; - } - - public function getType() : string { - return 'Stmt_Trait'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php deleted file mode 100644 index 7fc158c57..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class TryCatch extends Node\Stmt -{ - /** @var Node\Stmt[] Statements */ - public $stmts; - /** @var Catch_[] Catches */ - public $catches; - /** @var null|Finally_ Optional finally node */ - public $finally; - - /** - * Constructs a try catch node. - * - * @param Node\Stmt[] $stmts Statements - * @param Catch_[] $catches Catches - * @param null|Finally_ $finally Optional finally node - * @param array $attributes Additional attributes - */ - public function __construct(array $stmts, array $catches, Finally_ $finally = null, array $attributes = []) { - $this->attributes = $attributes; - $this->stmts = $stmts; - $this->catches = $catches; - $this->finally = $finally; - } - - public function getSubNodeNames() : array { - return ['stmts', 'catches', 'finally']; - } - - public function getType() : string { - return 'Stmt_TryCatch'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php deleted file mode 100644 index 310e427aa..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class Unset_ extends Node\Stmt -{ - /** @var Node\Expr[] Variables to unset */ - public $vars; - - /** - * Constructs an unset node. - * - * @param Node\Expr[] $vars Variables to unset - * @param array $attributes Additional attributes - */ - public function __construct(array $vars, array $attributes = []) { - $this->attributes = $attributes; - $this->vars = $vars; - } - - public function getSubNodeNames() : array { - return ['vars']; - } - - public function getType() : string { - return 'Stmt_Unset'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php deleted file mode 100644 index 32bd7847d..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; -use PhpParser\Node\Identifier; - -class UseUse extends Node\Stmt -{ - /** @var int One of the Stmt\Use_::TYPE_* constants. Will only differ from TYPE_UNKNOWN for mixed group uses */ - public $type; - /** @var Node\Name Namespace, class, function or constant to alias */ - public $name; - /** @var Identifier|null Alias */ - public $alias; - - /** - * Constructs an alias (use) node. - * - * @param Node\Name $name Namespace/Class to alias - * @param null|string|Identifier $alias Alias - * @param int $type Type of the use element (for mixed group use only) - * @param array $attributes Additional attributes - */ - public function __construct(Node\Name $name, $alias = null, int $type = Use_::TYPE_UNKNOWN, array $attributes = []) { - $this->attributes = $attributes; - $this->type = $type; - $this->name = $name; - $this->alias = \is_string($alias) ? new Identifier($alias) : $alias; - } - - public function getSubNodeNames() : array { - return ['type', 'name', 'alias']; - } - - /** - * Get alias. If not explicitly given this is the last component of the used name. - * - * @return Identifier - */ - public function getAlias() : Identifier { - if (null !== $this->alias) { - return $this->alias; - } - - return new Identifier($this->name->getLast()); - } - - public function getType() : string { - return 'Stmt_UseUse'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php deleted file mode 100644 index 8753da313..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node\Stmt; - -class Use_ extends Stmt -{ - /** - * Unknown type. Both Stmt\Use_ / Stmt\GroupUse and Stmt\UseUse have a $type property, one of them will always be - * TYPE_UNKNOWN while the other has one of the three other possible types. For normal use statements the type on the - * Stmt\UseUse is unknown. It's only the other way around for mixed group use declarations. - */ - const TYPE_UNKNOWN = 0; - /** Class or namespace import */ - const TYPE_NORMAL = 1; - /** Function import */ - const TYPE_FUNCTION = 2; - /** Constant import */ - const TYPE_CONSTANT = 3; - - /** @var int Type of alias */ - public $type; - /** @var UseUse[] Aliases */ - public $uses; - - /** - * Constructs an alias (use) list node. - * - * @param UseUse[] $uses Aliases - * @param int $type Type of alias - * @param array $attributes Additional attributes - */ - public function __construct(array $uses, int $type = self::TYPE_NORMAL, array $attributes = []) { - $this->attributes = $attributes; - $this->type = $type; - $this->uses = $uses; - } - - public function getSubNodeNames() : array { - return ['type', 'uses']; - } - - public function getType() : string { - return 'Stmt_Use'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php b/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php deleted file mode 100644 index f41034f8c..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node\Stmt; - -use PhpParser\Node; - -class While_ extends Node\Stmt -{ - /** @var Node\Expr Condition */ - public $cond; - /** @var Node\Stmt[] Statements */ - public $stmts; - - /** - * Constructs a while node. - * - * @param Node\Expr $cond Condition - * @param Node\Stmt[] $stmts Statements - * @param array $attributes Additional attributes - */ - public function __construct(Node\Expr $cond, array $stmts = [], array $attributes = []) { - $this->attributes = $attributes; - $this->cond = $cond; - $this->stmts = $stmts; - } - - public function getSubNodeNames() : array { - return ['cond', 'stmts']; - } - - public function getType() : string { - return 'Stmt_While'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/UnionType.php b/lib/nikic/php-parser/lib/PhpParser/Node/UnionType.php deleted file mode 100644 index 61c2d8106..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/UnionType.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node; - -class UnionType extends ComplexType -{ - /** @var (Identifier|Name)[] Types */ - public $types; - - /** - * Constructs a union type. - * - * @param (Identifier|Name)[] $types Types - * @param array $attributes Additional attributes - */ - public function __construct(array $types, array $attributes = []) { - $this->attributes = $attributes; - $this->types = $types; - } - - public function getSubNodeNames() : array { - return ['types']; - } - - public function getType() : string { - return 'UnionType'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php b/lib/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php deleted file mode 100644 index a30807a6d..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node; - -/** - * Represents a name that is written in source code with a leading dollar, - * but is not a proper variable. The leading dollar is not stored as part of the name. - * - * Examples: Names in property declarations are formatted as variables. Names in static property - * lookups are also formatted as variables. - */ -class VarLikeIdentifier extends Identifier -{ - public function getType() : string { - return 'VarLikeIdentifier'; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Node/VariadicPlaceholder.php b/lib/nikic/php-parser/lib/PhpParser/Node/VariadicPlaceholder.php deleted file mode 100644 index 403a24df2..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Node/VariadicPlaceholder.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Node; - -use PhpParser\NodeAbstract; - -/** - * Represents the "..." in "foo(...)" of the first-class callable syntax. - */ -class VariadicPlaceholder extends NodeAbstract { - /** - * Create a variadic argument placeholder (first-class callable syntax). - * - * @param array $attributes Additional attributes - */ - public function __construct(array $attributes = []) { - $this->attributes = $attributes; - } - - public function getType(): string { - return 'VariadicPlaceholder'; - } - - public function getSubNodeNames(): array { - return []; - } -} \ No newline at end of file diff --git a/lib/nikic/php-parser/lib/PhpParser/NodeAbstract.php b/lib/nikic/php-parser/lib/PhpParser/NodeAbstract.php deleted file mode 100644 index 04514da11..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/NodeAbstract.php +++ /dev/null @@ -1,178 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser; - -abstract class NodeAbstract implements Node, \JsonSerializable -{ - protected $attributes; - - /** - * Creates a Node. - * - * @param array $attributes Array of attributes - */ - public function __construct(array $attributes = []) { - $this->attributes = $attributes; - } - - /** - * Gets line the node started in (alias of getStartLine). - * - * @return int Start line (or -1 if not available) - */ - public function getLine() : int { - return $this->attributes['startLine'] ?? -1; - } - - /** - * Gets line the node started in. - * - * Requires the 'startLine' attribute to be enabled in the lexer (enabled by default). - * - * @return int Start line (or -1 if not available) - */ - public function getStartLine() : int { - return $this->attributes['startLine'] ?? -1; - } - - /** - * Gets the line the node ended in. - * - * Requires the 'endLine' attribute to be enabled in the lexer (enabled by default). - * - * @return int End line (or -1 if not available) - */ - public function getEndLine() : int { - return $this->attributes['endLine'] ?? -1; - } - - /** - * Gets the token offset of the first token that is part of this node. - * - * The offset is an index into the array returned by Lexer::getTokens(). - * - * Requires the 'startTokenPos' attribute to be enabled in the lexer (DISABLED by default). - * - * @return int Token start position (or -1 if not available) - */ - public function getStartTokenPos() : int { - return $this->attributes['startTokenPos'] ?? -1; - } - - /** - * Gets the token offset of the last token that is part of this node. - * - * The offset is an index into the array returned by Lexer::getTokens(). - * - * Requires the 'endTokenPos' attribute to be enabled in the lexer (DISABLED by default). - * - * @return int Token end position (or -1 if not available) - */ - public function getEndTokenPos() : int { - return $this->attributes['endTokenPos'] ?? -1; - } - - /** - * Gets the file offset of the first character that is part of this node. - * - * Requires the 'startFilePos' attribute to be enabled in the lexer (DISABLED by default). - * - * @return int File start position (or -1 if not available) - */ - public function getStartFilePos() : int { - return $this->attributes['startFilePos'] ?? -1; - } - - /** - * Gets the file offset of the last character that is part of this node. - * - * Requires the 'endFilePos' attribute to be enabled in the lexer (DISABLED by default). - * - * @return int File end position (or -1 if not available) - */ - public function getEndFilePos() : int { - return $this->attributes['endFilePos'] ?? -1; - } - - /** - * Gets all comments directly preceding this node. - * - * The comments are also available through the "comments" attribute. - * - * @return Comment[] - */ - public function getComments() : array { - return $this->attributes['comments'] ?? []; - } - - /** - * Gets the doc comment of the node. - * - * @return null|Comment\Doc Doc comment object or null - */ - public function getDocComment() { - $comments = $this->getComments(); - for ($i = count($comments) - 1; $i >= 0; $i--) { - $comment = $comments[$i]; - if ($comment instanceof Comment\Doc) { - return $comment; - } - } - - return null; - } - - /** - * Sets the doc comment of the node. - * - * This will either replace an existing doc comment or add it to the comments array. - * - * @param Comment\Doc $docComment Doc comment to set - */ - public function setDocComment(Comment\Doc $docComment) { - $comments = $this->getComments(); - for ($i = count($comments) - 1; $i >= 0; $i--) { - if ($comments[$i] instanceof Comment\Doc) { - // Replace existing doc comment. - $comments[$i] = $docComment; - $this->setAttribute('comments', $comments); - return; - } - } - - // Append new doc comment. - $comments[] = $docComment; - $this->setAttribute('comments', $comments); - } - - public function setAttribute(string $key, $value) { - $this->attributes[$key] = $value; - } - - public function hasAttribute(string $key) : bool { - return array_key_exists($key, $this->attributes); - } - - public function getAttribute(string $key, $default = null) { - if (array_key_exists($key, $this->attributes)) { - return $this->attributes[$key]; - } - - return $default; - } - - public function getAttributes() : array { - return $this->attributes; - } - - public function setAttributes(array $attributes) { - $this->attributes = $attributes; - } - - /** - * @return array - */ - public function jsonSerialize() : array { - return ['nodeType' => $this->getType()] + get_object_vars($this); - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/NodeDumper.php b/lib/nikic/php-parser/lib/PhpParser/NodeDumper.php deleted file mode 100644 index ba622efd1..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/NodeDumper.php +++ /dev/null @@ -1,206 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser; - -use PhpParser\Node\Expr\Include_; -use PhpParser\Node\Stmt\Class_; -use PhpParser\Node\Stmt\GroupUse; -use PhpParser\Node\Stmt\Use_; -use PhpParser\Node\Stmt\UseUse; - -class NodeDumper -{ - private $dumpComments; - private $dumpPositions; - private $code; - - /** - * Constructs a NodeDumper. - * - * Supported options: - * * bool dumpComments: Whether comments should be dumped. - * * bool dumpPositions: Whether line/offset information should be dumped. To dump offset - * information, the code needs to be passed to dump(). - * - * @param array $options Options (see description) - */ - public function __construct(array $options = []) { - $this->dumpComments = !empty($options['dumpComments']); - $this->dumpPositions = !empty($options['dumpPositions']); - } - - /** - * Dumps a node or array. - * - * @param array|Node $node Node or array to dump - * @param string|null $code Code corresponding to dumped AST. This only needs to be passed if - * the dumpPositions option is enabled and the dumping of node offsets - * is desired. - * - * @return string Dumped value - */ - public function dump($node, string $code = null) : string { - $this->code = $code; - return $this->dumpRecursive($node); - } - - protected function dumpRecursive($node) { - if ($node instanceof Node) { - $r = $node->getType(); - if ($this->dumpPositions && null !== $p = $this->dumpPosition($node)) { - $r .= $p; - } - $r .= '('; - - foreach ($node->getSubNodeNames() as $key) { - $r .= "\n " . $key . ': '; - - $value = $node->$key; - if (null === $value) { - $r .= 'null'; - } elseif (false === $value) { - $r .= 'false'; - } elseif (true === $value) { - $r .= 'true'; - } elseif (is_scalar($value)) { - if ('flags' === $key || 'newModifier' === $key) { - $r .= $this->dumpFlags($value); - } elseif ('type' === $key && $node instanceof Include_) { - $r .= $this->dumpIncludeType($value); - } elseif ('type' === $key - && ($node instanceof Use_ || $node instanceof UseUse || $node instanceof GroupUse)) { - $r .= $this->dumpUseType($value); - } else { - $r .= $value; - } - } else { - $r .= str_replace("\n", "\n ", $this->dumpRecursive($value)); - } - } - - if ($this->dumpComments && $comments = $node->getComments()) { - $r .= "\n comments: " . str_replace("\n", "\n ", $this->dumpRecursive($comments)); - } - } elseif (is_array($node)) { - $r = 'array('; - - foreach ($node as $key => $value) { - $r .= "\n " . $key . ': '; - - if (null === $value) { - $r .= 'null'; - } elseif (false === $value) { - $r .= 'false'; - } elseif (true === $value) { - $r .= 'true'; - } elseif (is_scalar($value)) { - $r .= $value; - } else { - $r .= str_replace("\n", "\n ", $this->dumpRecursive($value)); - } - } - } elseif ($node instanceof Comment) { - return $node->getReformattedText(); - } else { - throw new \InvalidArgumentException('Can only dump nodes and arrays.'); - } - - return $r . "\n)"; - } - - protected function dumpFlags($flags) { - $strs = []; - if ($flags & Class_::MODIFIER_PUBLIC) { - $strs[] = 'MODIFIER_PUBLIC'; - } - if ($flags & Class_::MODIFIER_PROTECTED) { - $strs[] = 'MODIFIER_PROTECTED'; - } - if ($flags & Class_::MODIFIER_PRIVATE) { - $strs[] = 'MODIFIER_PRIVATE'; - } - if ($flags & Class_::MODIFIER_ABSTRACT) { - $strs[] = 'MODIFIER_ABSTRACT'; - } - if ($flags & Class_::MODIFIER_STATIC) { - $strs[] = 'MODIFIER_STATIC'; - } - if ($flags & Class_::MODIFIER_FINAL) { - $strs[] = 'MODIFIER_FINAL'; - } - if ($flags & Class_::MODIFIER_READONLY) { - $strs[] = 'MODIFIER_READONLY'; - } - - if ($strs) { - return implode(' | ', $strs) . ' (' . $flags . ')'; - } else { - return $flags; - } - } - - protected function dumpIncludeType($type) { - $map = [ - Include_::TYPE_INCLUDE => 'TYPE_INCLUDE', - Include_::TYPE_INCLUDE_ONCE => 'TYPE_INCLUDE_ONCE', - Include_::TYPE_REQUIRE => 'TYPE_REQUIRE', - Include_::TYPE_REQUIRE_ONCE => 'TYPE_REQUIRE_ONCE', - ]; - - if (!isset($map[$type])) { - return $type; - } - return $map[$type] . ' (' . $type . ')'; - } - - protected function dumpUseType($type) { - $map = [ - Use_::TYPE_UNKNOWN => 'TYPE_UNKNOWN', - Use_::TYPE_NORMAL => 'TYPE_NORMAL', - Use_::TYPE_FUNCTION => 'TYPE_FUNCTION', - Use_::TYPE_CONSTANT => 'TYPE_CONSTANT', - ]; - - if (!isset($map[$type])) { - return $type; - } - return $map[$type] . ' (' . $type . ')'; - } - - /** - * Dump node position, if possible. - * - * @param Node $node Node for which to dump position - * - * @return string|null Dump of position, or null if position information not available - */ - protected function dumpPosition(Node $node) { - if (!$node->hasAttribute('startLine') || !$node->hasAttribute('endLine')) { - return null; - } - - $start = $node->getStartLine(); - $end = $node->getEndLine(); - if ($node->hasAttribute('startFilePos') && $node->hasAttribute('endFilePos') - && null !== $this->code - ) { - $start .= ':' . $this->toColumn($this->code, $node->getStartFilePos()); - $end .= ':' . $this->toColumn($this->code, $node->getEndFilePos()); - } - return "[$start - $end]"; - } - - // Copied from Error class - private function toColumn($code, $pos) { - if ($pos > strlen($code)) { - throw new \RuntimeException('Invalid position information'); - } - - $lineStartPos = strrpos($code, "\n", $pos - strlen($code)); - if (false === $lineStartPos) { - $lineStartPos = -1; - } - - return $pos - $lineStartPos; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/NodeFinder.php b/lib/nikic/php-parser/lib/PhpParser/NodeFinder.php deleted file mode 100644 index 2e7cfdad4..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/NodeFinder.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser; - -use PhpParser\NodeVisitor\FindingVisitor; -use PhpParser\NodeVisitor\FirstFindingVisitor; - -class NodeFinder -{ - /** - * Find all nodes satisfying a filter callback. - * - * @param Node|Node[] $nodes Single node or array of nodes to search in - * @param callable $filter Filter callback: function(Node $node) : bool - * - * @return Node[] Found nodes satisfying the filter callback - */ - public function find($nodes, callable $filter) : array { - if (!is_array($nodes)) { - $nodes = [$nodes]; - } - - $visitor = new FindingVisitor($filter); - - $traverser = new NodeTraverser; - $traverser->addVisitor($visitor); - $traverser->traverse($nodes); - - return $visitor->getFoundNodes(); - } - - /** - * Find all nodes that are instances of a certain class. - * - * @param Node|Node[] $nodes Single node or array of nodes to search in - * @param string $class Class name - * - * @return Node[] Found nodes (all instances of $class) - */ - public function findInstanceOf($nodes, string $class) : array { - return $this->find($nodes, function ($node) use ($class) { - return $node instanceof $class; - }); - } - - /** - * Find first node satisfying a filter callback. - * - * @param Node|Node[] $nodes Single node or array of nodes to search in - * @param callable $filter Filter callback: function(Node $node) : bool - * - * @return null|Node Found node (or null if none found) - */ - public function findFirst($nodes, callable $filter) { - if (!is_array($nodes)) { - $nodes = [$nodes]; - } - - $visitor = new FirstFindingVisitor($filter); - - $traverser = new NodeTraverser; - $traverser->addVisitor($visitor); - $traverser->traverse($nodes); - - return $visitor->getFoundNode(); - } - - /** - * Find first node that is an instance of a certain class. - * - * @param Node|Node[] $nodes Single node or array of nodes to search in - * @param string $class Class name - * - * @return null|Node Found node, which is an instance of $class (or null if none found) - */ - public function findFirstInstanceOf($nodes, string $class) { - return $this->findFirst($nodes, function ($node) use ($class) { - return $node instanceof $class; - }); - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/NodeTraverser.php b/lib/nikic/php-parser/lib/PhpParser/NodeTraverser.php deleted file mode 100644 index 97d45bdaa..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/NodeTraverser.php +++ /dev/null @@ -1,291 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser; - -class NodeTraverser implements NodeTraverserInterface -{ - /** - * If NodeVisitor::enterNode() returns DONT_TRAVERSE_CHILDREN, child nodes - * of the current node will not be traversed for any visitors. - * - * For subsequent visitors enterNode() will still be called on the current - * node and leaveNode() will also be invoked for the current node. - */ - const DONT_TRAVERSE_CHILDREN = 1; - - /** - * If NodeVisitor::enterNode() or NodeVisitor::leaveNode() returns - * STOP_TRAVERSAL, traversal is aborted. - * - * The afterTraverse() method will still be invoked. - */ - const STOP_TRAVERSAL = 2; - - /** - * If NodeVisitor::leaveNode() returns REMOVE_NODE for a node that occurs - * in an array, it will be removed from the array. - * - * For subsequent visitors leaveNode() will still be invoked for the - * removed node. - */ - const REMOVE_NODE = 3; - - /** - * If NodeVisitor::enterNode() returns DONT_TRAVERSE_CURRENT_AND_CHILDREN, child nodes - * of the current node will not be traversed for any visitors. - * - * For subsequent visitors enterNode() will not be called as well. - * leaveNode() will be invoked for visitors that has enterNode() method invoked. - */ - const DONT_TRAVERSE_CURRENT_AND_CHILDREN = 4; - - /** @var NodeVisitor[] Visitors */ - protected $visitors = []; - - /** @var bool Whether traversal should be stopped */ - protected $stopTraversal; - - public function __construct() { - // for BC - } - - /** - * Adds a visitor. - * - * @param NodeVisitor $visitor Visitor to add - */ - public function addVisitor(NodeVisitor $visitor) { - $this->visitors[] = $visitor; - } - - /** - * Removes an added visitor. - * - * @param NodeVisitor $visitor - */ - public function removeVisitor(NodeVisitor $visitor) { - foreach ($this->visitors as $index => $storedVisitor) { - if ($storedVisitor === $visitor) { - unset($this->visitors[$index]); - break; - } - } - } - - /** - * Traverses an array of nodes using the registered visitors. - * - * @param Node[] $nodes Array of nodes - * - * @return Node[] Traversed array of nodes - */ - public function traverse(array $nodes) : array { - $this->stopTraversal = false; - - foreach ($this->visitors as $visitor) { - if (null !== $return = $visitor->beforeTraverse($nodes)) { - $nodes = $return; - } - } - - $nodes = $this->traverseArray($nodes); - - foreach ($this->visitors as $visitor) { - if (null !== $return = $visitor->afterTraverse($nodes)) { - $nodes = $return; - } - } - - return $nodes; - } - - /** - * Recursively traverse a node. - * - * @param Node $node Node to traverse. - * - * @return Node Result of traversal (may be original node or new one) - */ - protected function traverseNode(Node $node) : Node { - foreach ($node->getSubNodeNames() as $name) { - $subNode =& $node->$name; - - if (\is_array($subNode)) { - $subNode = $this->traverseArray($subNode); - if ($this->stopTraversal) { - break; - } - } elseif ($subNode instanceof Node) { - $traverseChildren = true; - $breakVisitorIndex = null; - - foreach ($this->visitors as $visitorIndex => $visitor) { - $return = $visitor->enterNode($subNode); - if (null !== $return) { - if ($return instanceof Node) { - $this->ensureReplacementReasonable($subNode, $return); - $subNode = $return; - } elseif (self::DONT_TRAVERSE_CHILDREN === $return) { - $traverseChildren = false; - } elseif (self::DONT_TRAVERSE_CURRENT_AND_CHILDREN === $return) { - $traverseChildren = false; - $breakVisitorIndex = $visitorIndex; - break; - } elseif (self::STOP_TRAVERSAL === $return) { - $this->stopTraversal = true; - break 2; - } else { - throw new \LogicException( - 'enterNode() returned invalid value of type ' . gettype($return) - ); - } - } - } - - if ($traverseChildren) { - $subNode = $this->traverseNode($subNode); - if ($this->stopTraversal) { - break; - } - } - - foreach ($this->visitors as $visitorIndex => $visitor) { - $return = $visitor->leaveNode($subNode); - - if (null !== $return) { - if ($return instanceof Node) { - $this->ensureReplacementReasonable($subNode, $return); - $subNode = $return; - } elseif (self::STOP_TRAVERSAL === $return) { - $this->stopTraversal = true; - break 2; - } elseif (\is_array($return)) { - throw new \LogicException( - 'leaveNode() may only return an array ' . - 'if the parent structure is an array' - ); - } else { - throw new \LogicException( - 'leaveNode() returned invalid value of type ' . gettype($return) - ); - } - } - - if ($breakVisitorIndex === $visitorIndex) { - break; - } - } - } - } - - return $node; - } - - /** - * Recursively traverse array (usually of nodes). - * - * @param array $nodes Array to traverse - * - * @return array Result of traversal (may be original array or changed one) - */ - protected function traverseArray(array $nodes) : array { - $doNodes = []; - - foreach ($nodes as $i => &$node) { - if ($node instanceof Node) { - $traverseChildren = true; - $breakVisitorIndex = null; - - foreach ($this->visitors as $visitorIndex => $visitor) { - $return = $visitor->enterNode($node); - if (null !== $return) { - if ($return instanceof Node) { - $this->ensureReplacementReasonable($node, $return); - $node = $return; - } elseif (self::DONT_TRAVERSE_CHILDREN === $return) { - $traverseChildren = false; - } elseif (self::DONT_TRAVERSE_CURRENT_AND_CHILDREN === $return) { - $traverseChildren = false; - $breakVisitorIndex = $visitorIndex; - break; - } elseif (self::STOP_TRAVERSAL === $return) { - $this->stopTraversal = true; - break 2; - } else { - throw new \LogicException( - 'enterNode() returned invalid value of type ' . gettype($return) - ); - } - } - } - - if ($traverseChildren) { - $node = $this->traverseNode($node); - if ($this->stopTraversal) { - break; - } - } - - foreach ($this->visitors as $visitorIndex => $visitor) { - $return = $visitor->leaveNode($node); - - if (null !== $return) { - if ($return instanceof Node) { - $this->ensureReplacementReasonable($node, $return); - $node = $return; - } elseif (\is_array($return)) { - $doNodes[] = [$i, $return]; - break; - } elseif (self::REMOVE_NODE === $return) { - $doNodes[] = [$i, []]; - break; - } elseif (self::STOP_TRAVERSAL === $return) { - $this->stopTraversal = true; - break 2; - } elseif (false === $return) { - throw new \LogicException( - 'bool(false) return from leaveNode() no longer supported. ' . - 'Return NodeTraverser::REMOVE_NODE instead' - ); - } else { - throw new \LogicException( - 'leaveNode() returned invalid value of type ' . gettype($return) - ); - } - } - - if ($breakVisitorIndex === $visitorIndex) { - break; - } - } - } elseif (\is_array($node)) { - throw new \LogicException('Invalid node structure: Contains nested arrays'); - } - } - - if (!empty($doNodes)) { - while (list($i, $replace) = array_pop($doNodes)) { - array_splice($nodes, $i, 1, $replace); - } - } - - return $nodes; - } - - private function ensureReplacementReasonable($old, $new) { - if ($old instanceof Node\Stmt && $new instanceof Node\Expr) { - throw new \LogicException( - "Trying to replace statement ({$old->getType()}) " . - "with expression ({$new->getType()}). Are you missing a " . - "Stmt_Expression wrapper?" - ); - } - - if ($old instanceof Node\Expr && $new instanceof Node\Stmt) { - throw new \LogicException( - "Trying to replace expression ({$old->getType()}) " . - "with statement ({$new->getType()})" - ); - } - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php b/lib/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php deleted file mode 100644 index 77ff3d27f..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser; - -interface NodeTraverserInterface -{ - /** - * Adds a visitor. - * - * @param NodeVisitor $visitor Visitor to add - */ - public function addVisitor(NodeVisitor $visitor); - - /** - * Removes an added visitor. - * - * @param NodeVisitor $visitor - */ - public function removeVisitor(NodeVisitor $visitor); - - /** - * Traverses an array of nodes using the registered visitors. - * - * @param Node[] $nodes Array of nodes - * - * @return Node[] Traversed array of nodes - */ - public function traverse(array $nodes) : array; -} diff --git a/lib/nikic/php-parser/lib/PhpParser/NodeVisitor.php b/lib/nikic/php-parser/lib/PhpParser/NodeVisitor.php deleted file mode 100644 index f1f7f3e3e..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/NodeVisitor.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser; - -interface NodeVisitor -{ - /** - * Called once before traversal. - * - * Return value semantics: - * * null: $nodes stays as-is - * * otherwise: $nodes is set to the return value - * - * @param Node[] $nodes Array of nodes - * - * @return null|Node[] Array of nodes - */ - public function beforeTraverse(array $nodes); - - /** - * Called when entering a node. - * - * Return value semantics: - * * null - * => $node stays as-is - * * NodeTraverser::DONT_TRAVERSE_CHILDREN - * => Children of $node are not traversed. $node stays as-is - * * NodeTraverser::STOP_TRAVERSAL - * => Traversal is aborted. $node stays as-is - * * otherwise - * => $node is set to the return value - * - * @param Node $node Node - * - * @return null|int|Node Replacement node (or special return value) - */ - public function enterNode(Node $node); - - /** - * Called when leaving a node. - * - * Return value semantics: - * * null - * => $node stays as-is - * * NodeTraverser::REMOVE_NODE - * => $node is removed from the parent array - * * NodeTraverser::STOP_TRAVERSAL - * => Traversal is aborted. $node stays as-is - * * array (of Nodes) - * => The return value is merged into the parent array (at the position of the $node) - * * otherwise - * => $node is set to the return value - * - * @param Node $node Node - * - * @return null|int|Node|Node[] Replacement node (or special return value) - */ - public function leaveNode(Node $node); - - /** - * Called once after traversal. - * - * Return value semantics: - * * null: $nodes stays as-is - * * otherwise: $nodes is set to the return value - * - * @param Node[] $nodes Array of nodes - * - * @return null|Node[] Array of nodes - */ - public function afterTraverse(array $nodes); -} diff --git a/lib/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php b/lib/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php deleted file mode 100644 index a85fa493b..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\NodeVisitor; - -use PhpParser\Node; -use PhpParser\NodeVisitorAbstract; - -/** - * Visitor cloning all nodes and linking to the original nodes using an attribute. - * - * This visitor is required to perform format-preserving pretty prints. - */ -class CloningVisitor extends NodeVisitorAbstract -{ - public function enterNode(Node $origNode) { - $node = clone $origNode; - $node->setAttribute('origNode', $origNode); - return $node; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php b/lib/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php deleted file mode 100644 index 9531edbce..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\NodeVisitor; - -use PhpParser\Node; -use PhpParser\NodeVisitorAbstract; - -/** - * This visitor can be used to find and collect all nodes satisfying some criterion determined by - * a filter callback. - */ -class FindingVisitor extends NodeVisitorAbstract -{ - /** @var callable Filter callback */ - protected $filterCallback; - /** @var Node[] Found nodes */ - protected $foundNodes; - - public function __construct(callable $filterCallback) { - $this->filterCallback = $filterCallback; - } - - /** - * Get found nodes satisfying the filter callback. - * - * Nodes are returned in pre-order. - * - * @return Node[] Found nodes - */ - public function getFoundNodes() : array { - return $this->foundNodes; - } - - public function beforeTraverse(array $nodes) { - $this->foundNodes = []; - - return null; - } - - public function enterNode(Node $node) { - $filterCallback = $this->filterCallback; - if ($filterCallback($node)) { - $this->foundNodes[] = $node; - } - - return null; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.php b/lib/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.php deleted file mode 100644 index 596a7d7fd..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\NodeVisitor; - -use PhpParser\Node; -use PhpParser\NodeTraverser; -use PhpParser\NodeVisitorAbstract; - -/** - * This visitor can be used to find the first node satisfying some criterion determined by - * a filter callback. - */ -class FirstFindingVisitor extends NodeVisitorAbstract -{ - /** @var callable Filter callback */ - protected $filterCallback; - /** @var null|Node Found node */ - protected $foundNode; - - public function __construct(callable $filterCallback) { - $this->filterCallback = $filterCallback; - } - - /** - * Get found node satisfying the filter callback. - * - * Returns null if no node satisfies the filter callback. - * - * @return null|Node Found node (or null if not found) - */ - public function getFoundNode() { - return $this->foundNode; - } - - public function beforeTraverse(array $nodes) { - $this->foundNode = null; - - return null; - } - - public function enterNode(Node $node) { - $filterCallback = $this->filterCallback; - if ($filterCallback($node)) { - $this->foundNode = $node; - return NodeTraverser::STOP_TRAVERSAL; - } - - return null; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php b/lib/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php deleted file mode 100644 index 8e259c57b..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php +++ /dev/null @@ -1,257 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\NodeVisitor; - -use PhpParser\ErrorHandler; -use PhpParser\NameContext; -use PhpParser\Node; -use PhpParser\Node\Expr; -use PhpParser\Node\Name; -use PhpParser\Node\Name\FullyQualified; -use PhpParser\Node\Stmt; -use PhpParser\NodeVisitorAbstract; - -class NameResolver extends NodeVisitorAbstract -{ - /** @var NameContext Naming context */ - protected $nameContext; - - /** @var bool Whether to preserve original names */ - protected $preserveOriginalNames; - - /** @var bool Whether to replace resolved nodes in place, or to add resolvedNode attributes */ - protected $replaceNodes; - - /** - * Constructs a name resolution visitor. - * - * Options: - * * preserveOriginalNames (default false): An "originalName" attribute will be added to - * all name nodes that underwent resolution. - * * replaceNodes (default true): Resolved names are replaced in-place. Otherwise, a - * resolvedName attribute is added. (Names that cannot be statically resolved receive a - * namespacedName attribute, as usual.) - * - * @param ErrorHandler|null $errorHandler Error handler - * @param array $options Options - */ - public function __construct(ErrorHandler $errorHandler = null, array $options = []) { - $this->nameContext = new NameContext($errorHandler ?? new ErrorHandler\Throwing); - $this->preserveOriginalNames = $options['preserveOriginalNames'] ?? false; - $this->replaceNodes = $options['replaceNodes'] ?? true; - } - - /** - * Get name resolution context. - * - * @return NameContext - */ - public function getNameContext() : NameContext { - return $this->nameContext; - } - - public function beforeTraverse(array $nodes) { - $this->nameContext->startNamespace(); - return null; - } - - public function enterNode(Node $node) { - if ($node instanceof Stmt\Namespace_) { - $this->nameContext->startNamespace($node->name); - } elseif ($node instanceof Stmt\Use_) { - foreach ($node->uses as $use) { - $this->addAlias($use, $node->type, null); - } - } elseif ($node instanceof Stmt\GroupUse) { - foreach ($node->uses as $use) { - $this->addAlias($use, $node->type, $node->prefix); - } - } elseif ($node instanceof Stmt\Class_) { - if (null !== $node->extends) { - $node->extends = $this->resolveClassName($node->extends); - } - - foreach ($node->implements as &$interface) { - $interface = $this->resolveClassName($interface); - } - - $this->resolveAttrGroups($node); - if (null !== $node->name) { - $this->addNamespacedName($node); - } - } elseif ($node instanceof Stmt\Interface_) { - foreach ($node->extends as &$interface) { - $interface = $this->resolveClassName($interface); - } - - $this->resolveAttrGroups($node); - $this->addNamespacedName($node); - } elseif ($node instanceof Stmt\Enum_) { - foreach ($node->implements as &$interface) { - $interface = $this->resolveClassName($interface); - } - - $this->resolveAttrGroups($node); - if (null !== $node->name) { - $this->addNamespacedName($node); - } - } elseif ($node instanceof Stmt\Trait_) { - $this->resolveAttrGroups($node); - $this->addNamespacedName($node); - } elseif ($node instanceof Stmt\Function_) { - $this->resolveSignature($node); - $this->resolveAttrGroups($node); - $this->addNamespacedName($node); - } elseif ($node instanceof Stmt\ClassMethod - || $node instanceof Expr\Closure - || $node instanceof Expr\ArrowFunction - ) { - $this->resolveSignature($node); - $this->resolveAttrGroups($node); - } elseif ($node instanceof Stmt\Property) { - if (null !== $node->type) { - $node->type = $this->resolveType($node->type); - } - $this->resolveAttrGroups($node); - } elseif ($node instanceof Stmt\Const_) { - foreach ($node->consts as $const) { - $this->addNamespacedName($const); - } - } else if ($node instanceof Stmt\ClassConst) { - $this->resolveAttrGroups($node); - } else if ($node instanceof Stmt\EnumCase) { - $this->resolveAttrGroups($node); - } elseif ($node instanceof Expr\StaticCall - || $node instanceof Expr\StaticPropertyFetch - || $node instanceof Expr\ClassConstFetch - || $node instanceof Expr\New_ - || $node instanceof Expr\Instanceof_ - ) { - if ($node->class instanceof Name) { - $node->class = $this->resolveClassName($node->class); - } - } elseif ($node instanceof Stmt\Catch_) { - foreach ($node->types as &$type) { - $type = $this->resolveClassName($type); - } - } elseif ($node instanceof Expr\FuncCall) { - if ($node->name instanceof Name) { - $node->name = $this->resolveName($node->name, Stmt\Use_::TYPE_FUNCTION); - } - } elseif ($node instanceof Expr\ConstFetch) { - $node->name = $this->resolveName($node->name, Stmt\Use_::TYPE_CONSTANT); - } elseif ($node instanceof Stmt\TraitUse) { - foreach ($node->traits as &$trait) { - $trait = $this->resolveClassName($trait); - } - - foreach ($node->adaptations as $adaptation) { - if (null !== $adaptation->trait) { - $adaptation->trait = $this->resolveClassName($adaptation->trait); - } - - if ($adaptation instanceof Stmt\TraitUseAdaptation\Precedence) { - foreach ($adaptation->insteadof as &$insteadof) { - $insteadof = $this->resolveClassName($insteadof); - } - } - } - } - - return null; - } - - private function addAlias(Stmt\UseUse $use, $type, Name $prefix = null) { - // Add prefix for group uses - $name = $prefix ? Name::concat($prefix, $use->name) : $use->name; - // Type is determined either by individual element or whole use declaration - $type |= $use->type; - - $this->nameContext->addAlias( - $name, (string) $use->getAlias(), $type, $use->getAttributes() - ); - } - - /** @param Stmt\Function_|Stmt\ClassMethod|Expr\Closure $node */ - private function resolveSignature($node) { - foreach ($node->params as $param) { - $param->type = $this->resolveType($param->type); - $this->resolveAttrGroups($param); - } - $node->returnType = $this->resolveType($node->returnType); - } - - private function resolveType($node) { - if ($node instanceof Name) { - return $this->resolveClassName($node); - } - if ($node instanceof Node\NullableType) { - $node->type = $this->resolveType($node->type); - return $node; - } - if ($node instanceof Node\UnionType || $node instanceof Node\IntersectionType) { - foreach ($node->types as &$type) { - $type = $this->resolveType($type); - } - return $node; - } - return $node; - } - - /** - * Resolve name, according to name resolver options. - * - * @param Name $name Function or constant name to resolve - * @param int $type One of Stmt\Use_::TYPE_* - * - * @return Name Resolved name, or original name with attribute - */ - protected function resolveName(Name $name, int $type) : Name { - if (!$this->replaceNodes) { - $resolvedName = $this->nameContext->getResolvedName($name, $type); - if (null !== $resolvedName) { - $name->setAttribute('resolvedName', $resolvedName); - } else { - $name->setAttribute('namespacedName', FullyQualified::concat( - $this->nameContext->getNamespace(), $name, $name->getAttributes())); - } - return $name; - } - - if ($this->preserveOriginalNames) { - // Save the original name - $originalName = $name; - $name = clone $originalName; - $name->setAttribute('originalName', $originalName); - } - - $resolvedName = $this->nameContext->getResolvedName($name, $type); - if (null !== $resolvedName) { - return $resolvedName; - } - - // unqualified names inside a namespace cannot be resolved at compile-time - // add the namespaced version of the name as an attribute - $name->setAttribute('namespacedName', FullyQualified::concat( - $this->nameContext->getNamespace(), $name, $name->getAttributes())); - return $name; - } - - protected function resolveClassName(Name $name) { - return $this->resolveName($name, Stmt\Use_::TYPE_NORMAL); - } - - protected function addNamespacedName(Node $node) { - $node->namespacedName = Name::concat( - $this->nameContext->getNamespace(), (string) $node->name); - } - - protected function resolveAttrGroups(Node $node) - { - foreach ($node->attrGroups as $attrGroup) { - foreach ($attrGroup->attrs as $attr) { - $attr->name = $this->resolveClassName($attr->name); - } - } - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php b/lib/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php deleted file mode 100644 index ea372e5b9..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\NodeVisitor; - -use PhpParser\Node; -use PhpParser\NodeVisitorAbstract; - -/** - * Visitor that connects a child node to its parent node - * as well as its sibling nodes. - * - * On the child node, the parent node can be accessed through - * <code>$node->getAttribute('parent')</code>, the previous - * node can be accessed through <code>$node->getAttribute('previous')</code>, - * and the next node can be accessed through <code>$node->getAttribute('next')</code>. - */ -final class NodeConnectingVisitor extends NodeVisitorAbstract -{ - /** - * @var Node[] - */ - private $stack = []; - - /** - * @var ?Node - */ - private $previous; - - public function beforeTraverse(array $nodes) { - $this->stack = []; - $this->previous = null; - } - - public function enterNode(Node $node) { - if (!empty($this->stack)) { - $node->setAttribute('parent', $this->stack[count($this->stack) - 1]); - } - - if ($this->previous !== null && $this->previous->getAttribute('parent') === $node->getAttribute('parent')) { - $node->setAttribute('previous', $this->previous); - $this->previous->setAttribute('next', $node); - } - - $this->stack[] = $node; - } - - public function leaveNode(Node $node) { - $this->previous = $node; - - array_pop($this->stack); - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php b/lib/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php deleted file mode 100644 index b98d2bfa6..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\NodeVisitor; - -use function array_pop; -use function count; -use PhpParser\Node; -use PhpParser\NodeVisitorAbstract; - -/** - * Visitor that connects a child node to its parent node. - * - * On the child node, the parent node can be accessed through - * <code>$node->getAttribute('parent')</code>. - */ -final class ParentConnectingVisitor extends NodeVisitorAbstract -{ - /** - * @var Node[] - */ - private $stack = []; - - public function beforeTraverse(array $nodes) - { - $this->stack = []; - } - - public function enterNode(Node $node) - { - if (!empty($this->stack)) { - $node->setAttribute('parent', $this->stack[count($this->stack) - 1]); - } - - $this->stack[] = $node; - } - - public function leaveNode(Node $node) - { - array_pop($this->stack); - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php b/lib/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php deleted file mode 100644 index d378d6709..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser; - -/** - * @codeCoverageIgnore - */ -class NodeVisitorAbstract implements NodeVisitor -{ - public function beforeTraverse(array $nodes) { - return null; - } - - public function enterNode(Node $node) { - return null; - } - - public function leaveNode(Node $node) { - return null; - } - - public function afterTraverse(array $nodes) { - return null; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Parser.php b/lib/nikic/php-parser/lib/PhpParser/Parser.php deleted file mode 100644 index 8956c7671..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Parser.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser; - -interface Parser -{ - /** - * Parses PHP code into a node tree. - * - * @param string $code The source code to parse - * @param ErrorHandler|null $errorHandler Error handler to use for lexer/parser errors, defaults - * to ErrorHandler\Throwing. - * - * @return Node\Stmt[]|null Array of statements (or null non-throwing error handler is used and - * the parser was unable to recover from an error). - */ - public function parse(string $code, ErrorHandler $errorHandler = null); -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Parser/Multiple.php b/lib/nikic/php-parser/lib/PhpParser/Parser/Multiple.php deleted file mode 100644 index 77fd1f3fb..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Parser/Multiple.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\Parser; - -use PhpParser\Error; -use PhpParser\ErrorHandler; -use PhpParser\Parser; - -class Multiple implements Parser -{ - /** @var Parser[] List of parsers to try, in order of preference */ - private $parsers; - - /** - * Create a parser which will try multiple parsers in an order of preference. - * - * Parsers will be invoked in the order they're provided to the constructor. If one of the - * parsers runs without throwing, it's output is returned. Otherwise the exception that the - * first parser generated is thrown. - * - * @param Parser[] $parsers - */ - public function __construct(array $parsers) { - $this->parsers = $parsers; - } - - public function parse(string $code, ErrorHandler $errorHandler = null) { - if (null === $errorHandler) { - $errorHandler = new ErrorHandler\Throwing; - } - - list($firstStmts, $firstError) = $this->tryParse($this->parsers[0], $errorHandler, $code); - if ($firstError === null) { - return $firstStmts; - } - - for ($i = 1, $c = count($this->parsers); $i < $c; ++$i) { - list($stmts, $error) = $this->tryParse($this->parsers[$i], $errorHandler, $code); - if ($error === null) { - return $stmts; - } - } - - throw $firstError; - } - - private function tryParse(Parser $parser, ErrorHandler $errorHandler, $code) { - $stmts = null; - $error = null; - try { - $stmts = $parser->parse($code, $errorHandler); - } catch (Error $error) {} - return [$stmts, $error]; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Parser/Php5.php b/lib/nikic/php-parser/lib/PhpParser/Parser/Php5.php deleted file mode 100644 index d9c8fe049..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Parser/Php5.php +++ /dev/null @@ -1,2672 +0,0 @@ -<?php - -namespace PhpParser\Parser; - -use PhpParser\Error; -use PhpParser\Node; -use PhpParser\Node\Expr; -use PhpParser\Node\Name; -use PhpParser\Node\Scalar; -use PhpParser\Node\Stmt; - -/* This is an automatically GENERATED file, which should not be manually edited. - * Instead edit one of the following: - * * the grammar files grammar/php5.y or grammar/php7.y - * * the skeleton file grammar/parser.template - * * the preprocessing script grammar/rebuildParsers.php - */ -class Php5 extends \PhpParser\ParserAbstract -{ - protected $tokenToSymbolMapSize = 396; - protected $actionTableSize = 1093; - protected $gotoTableSize = 643; - - protected $invalidSymbol = 168; - protected $errorSymbol = 1; - protected $defaultAction = -32766; - protected $unexpectedTokenRule = 32767; - - protected $YY2TBLSTATE = 415; - protected $numNonLeafStates = 662; - - protected $symbolToName = array( - "EOF", - "error", - "T_THROW", - "T_INCLUDE", - "T_INCLUDE_ONCE", - "T_EVAL", - "T_REQUIRE", - "T_REQUIRE_ONCE", - "','", - "T_LOGICAL_OR", - "T_LOGICAL_XOR", - "T_LOGICAL_AND", - "T_PRINT", - "T_YIELD", - "T_DOUBLE_ARROW", - "T_YIELD_FROM", - "'='", - "T_PLUS_EQUAL", - "T_MINUS_EQUAL", - "T_MUL_EQUAL", - "T_DIV_EQUAL", - "T_CONCAT_EQUAL", - "T_MOD_EQUAL", - "T_AND_EQUAL", - "T_OR_EQUAL", - "T_XOR_EQUAL", - "T_SL_EQUAL", - "T_SR_EQUAL", - "T_POW_EQUAL", - "T_COALESCE_EQUAL", - "'?'", - "':'", - "T_COALESCE", - "T_BOOLEAN_OR", - "T_BOOLEAN_AND", - "'|'", - "'^'", - "T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG", - "T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG", - "T_IS_EQUAL", - "T_IS_NOT_EQUAL", - "T_IS_IDENTICAL", - "T_IS_NOT_IDENTICAL", - "T_SPACESHIP", - "'<'", - "T_IS_SMALLER_OR_EQUAL", - "'>'", - "T_IS_GREATER_OR_EQUAL", - "T_SL", - "T_SR", - "'+'", - "'-'", - "'.'", - "'*'", - "'/'", - "'%'", - "'!'", - "T_INSTANCEOF", - "'~'", - "T_INC", - "T_DEC", - "T_INT_CAST", - "T_DOUBLE_CAST", - "T_STRING_CAST", - "T_ARRAY_CAST", - "T_OBJECT_CAST", - "T_BOOL_CAST", - "T_UNSET_CAST", - "'@'", - "T_POW", - "'['", - "T_NEW", - "T_CLONE", - "T_EXIT", - "T_IF", - "T_ELSEIF", - "T_ELSE", - "T_ENDIF", - "T_LNUMBER", - "T_DNUMBER", - "T_STRING", - "T_STRING_VARNAME", - "T_VARIABLE", - "T_NUM_STRING", - "T_INLINE_HTML", - "T_ENCAPSED_AND_WHITESPACE", - "T_CONSTANT_ENCAPSED_STRING", - "T_ECHO", - "T_DO", - "T_WHILE", - "T_ENDWHILE", - "T_FOR", - "T_ENDFOR", - "T_FOREACH", - "T_ENDFOREACH", - "T_DECLARE", - "T_ENDDECLARE", - "T_AS", - "T_SWITCH", - "T_MATCH", - "T_ENDSWITCH", - "T_CASE", - "T_DEFAULT", - "T_BREAK", - "T_CONTINUE", - "T_GOTO", - "T_FUNCTION", - "T_FN", - "T_CONST", - "T_RETURN", - "T_TRY", - "T_CATCH", - "T_FINALLY", - "T_USE", - "T_INSTEADOF", - "T_GLOBAL", - "T_STATIC", - "T_ABSTRACT", - "T_FINAL", - "T_PRIVATE", - "T_PROTECTED", - "T_PUBLIC", - "T_VAR", - "T_UNSET", - "T_ISSET", - "T_EMPTY", - "T_HALT_COMPILER", - "T_CLASS", - "T_TRAIT", - "T_INTERFACE", - "T_EXTENDS", - "T_IMPLEMENTS", - "T_OBJECT_OPERATOR", - "T_LIST", - "T_ARRAY", - "T_CALLABLE", - "T_CLASS_C", - "T_TRAIT_C", - "T_METHOD_C", - "T_FUNC_C", - "T_LINE", - "T_FILE", - "T_START_HEREDOC", - "T_END_HEREDOC", - "T_DOLLAR_OPEN_CURLY_BRACES", - "T_CURLY_OPEN", - "T_PAAMAYIM_NEKUDOTAYIM", - "T_NAMESPACE", - "T_NS_C", - "T_DIR", - "T_NS_SEPARATOR", - "T_ELLIPSIS", - "T_NAME_FULLY_QUALIFIED", - "T_NAME_QUALIFIED", - "T_NAME_RELATIVE", - "';'", - "'{'", - "'}'", - "'('", - "')'", - "'$'", - "'`'", - "']'", - "'\"'", - "T_READONLY", - "T_ENUM", - "T_NULLSAFE_OBJECT_OPERATOR", - "T_ATTRIBUTE" - ); - - protected $tokenToSymbol = array( - 0, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 56, 163, 168, 160, 55, 168, 168, - 158, 159, 53, 50, 8, 51, 52, 54, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 31, 155, - 44, 16, 46, 30, 68, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 70, 168, 162, 36, 168, 161, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 156, 35, 157, 58, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 1, 2, 3, 4, - 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 32, 33, 34, 37, 38, 39, 40, - 41, 42, 43, 45, 47, 48, 49, 57, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 69, 71, 72, - 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, - 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, - 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, 116, 117, 118, 119, 120, 121, 164, - 122, 123, 124, 125, 126, 127, 128, 129, 165, 130, - 131, 132, 166, 133, 134, 135, 136, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 151, 152, 153, 154, 167 - ); - - protected $action = array( - 699, 669, 670, 671, 672, 673, 286, 674, 675, 676, - 712, 713, 223, 224, 225, 226, 227, 228, 229, 230, - 231, 232, 0, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244,-32766,-32766,-32766,-32766,-32766, - -32766,-32766,-32766,-32766,-32767,-32767,-32767,-32767, 245, 246, - 242, 243, 244,-32766,-32766, 677,-32766, 750,-32766,-32766, - -32766,-32766,-32766,-32766,-32766, 1224, 245, 246, 1225, 678, - 679, 680, 681, 682, 683, 684,-32766, 48, 746,-32766, - -32766,-32766,-32766,-32766,-32766, 685, 686, 687, 688, 689, - 690, 691, 692, 693, 694, 695, 715, 738, 716, 717, - 718, 719, 707, 708, 709, 737, 710, 711, 696, 697, - 698, 700, 701, 702, 740, 741, 742, 743, 744, 745, - 703, 704, 705, 706, 736, 727, 725, 726, 722, 723, - 751, 714, 720, 721, 728, 729, 731, 730, 732, 733, - 55, 56, 425, 57, 58, 724, 735, 734, 1073, 59, - 60, -224, 61,-32766,-32766,-32766,-32766,-32766,-32766,-32766, - -32766,-32766,-32766, 121,-32767,-32767,-32767,-32767, 29, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, - 118, 119, 1043, 766, 1071, 767, 580, 62, 63,-32766, - -32766,-32766,-32766, 64, 516, 65, 294, 295, 66, 67, - 68, 69, 70, 71, 72, 73, 822, 25, 302, 74, - 418, 981, 983, 1043, 1181, 1095, 1096, 1073, 748, 754, - 1075, 1074, 1076, 469,-32766,-32766,-32766, 337, 823, 54, - -32767,-32767,-32767,-32767, 98, 99, 100, 101, 102, 220, - 221, 222, 78, 361, 1107,-32766, 341,-32766,-32766,-32766, - -32766,-32766, 1107, 492, 949, 950, 951, 948, 947, 946, - 207, 477, 478, 949, 950, 951, 948, 947, 946, 1043, - 479, 480, 52, 1101, 1102, 1103, 1104, 1098, 1099, 319, - 872, 668, 667, 27, -511, 1105, 1100,-32766, 130, 1075, - 1074, 1076, 345, 668, 667, 41, 126, 341, 334, 369, - 336, 426, -128, -128, -128, 896, 897, 468, 220, 221, - 222, 811, 1195, 619, 40, 21, 427, -128, 470, -128, - 471, -128, 472, -128, 802, 428, -4, 823, 54, 207, - 33, 34, 429, 360, 317, 28, 35, 473,-32766,-32766, - -32766, 211, 356, 357, 474, 475,-32766,-32766,-32766, 754, - 476, 49, 313, 794, 843, 430, 431, 289, 125,-32766, - 813,-32766,-32766,-32766,-32766,-32766,-32766,-32766,-32767,-32767, - -32767,-32767,-32767,-32766,-32766,-32766, 769, 103, 104, 105, - 327, 307, 825, 633, -128, 1075, 1074, 1076, 221, 222, - 927, 748, 1146, 106,-32766, 129,-32766,-32766,-32766,-32766, - 426, 823, 54, 902, 873, 302, 468, 75, 207, 359, - 811, 668, 667, 40, 21, 427, 754, 470, 754, 471, - 423, 472, 1043, 127, 428, 435, 1043, 341, 1043, 33, - 34, 429, 360, 1181, 415, 35, 473, 122, 10, 315, - 128, 356, 357, 474, 475,-32766,-32766,-32766, 768, 476, - 668, 667, 758, 843, 430, 431, 754, 1043, 1147,-32766, - -32766,-32766, 754, 419, 342, 1215,-32766, 131,-32766,-32766, - -32766, 341, 363, 346, 426, 823, 54, 100, 101, 102, - 468, 825, 633, -4, 811, 442, 903, 40, 21, 427, - 754, 470, 435, 471, 341, 472, 341, 766, 428, 767, - -209, -209, -209, 33, 34, 429, 360, 479, 1196, 35, - 473, 345,-32766,-32766,-32766, 356, 357, 474, 475, 220, - 221, 222, 421, 476, 32, 297, 794, 843, 430, 431, - 754, 754, 435,-32766, 341,-32766,-32766, 9, 300, 51, - 207, 249, 324, 753, 120, 220, 221, 222, 426, 30, - 247, 941, 422, 424, 468, 825, 633, -209, 811, 1043, - 1061, 40, 21, 427, 129, 470, 207, 471, 341, 472, - 804, 20, 428, 124, -208, -208, -208, 33, 34, 429, - 360, 479, 212, 35, 473, 923, -259, 823, 54, 356, - 357, 474, 475,-32766,-32766,-32766, 1043, 476, 213, 806, - 794, 843, 430, 431,-32766,-32766, 435, 435, 341, 341, - 443, 79, 80, 81,-32766, 668, 667, 636, 344, 808, - 668, 667, 239, 240, 241, 123, 214, 538, 250, 825, - 633, -208, 36, 251, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 252, 307, - 426, 220, 221, 222, 823, 54, 468,-32766, 222, 765, - 811, 106, 134, 40, 21, 427, 571, 470, 207, 471, - 445, 472, 207,-32766, 428, 896, 897, 207, 307, 33, - 34, 429, 245, 246, 637, 35, 473, 452, 22, 809, - 922, 356, 357, 457, 588, 135, 374, 595, 596, 476, - -228, 759, 639, 938, 653, 926, 661, -86, 823, 54, - 314, 644, 647, 821, 133, 836, 43, 106, 603, 44, - 45, 46, 47, 748, 50, 53, 132, 426, 302,-32766, - 520, 825, 633, 468, -84, 607, 577, 811, 641, 362, - 40, 21, 427, -278, 470, 754, 471, 954, 472, 441, - 627, 428, 823, 54, 574, 844, 33, 34, 429, 11, - 615, 845, 35, 473, 444, 461, 285, -511, 356, 357, - 592, -419, 593, 1106, 1153, -410, 476, 368, 838, 38, - 658, 426, 645, 795, 1052, 0, 325, 468, 0,-32766, - 0, 811, 0, 0, 40, 21, 427, 0, 470, 0, - 471, 0, 472, 0, 322, 428, 823, 54, 825, 633, - 33, 34, 429, 0, 326, 0, 35, 473, 323, 0, - 316, 318, 356, 357, -512, 426, 0, 753, 531, 0, - 476, 468, 6, 0, 0, 811, 650, 7, 40, 21, - 427, 12, 470, 14, 471, 373, 472, -420, 562, 428, - 823, 54, 78, -225, 33, 34, 429, 39, 656, 657, - 35, 473, 859, 633, 764, 812, 356, 357, 820, 799, - 814, 875, 866, 867, 476, 797, 860, 857, 855, 426, - 933, 934, 931, 819, 803, 468, 805, 807, 810, 811, - 930, 762, 40, 21, 427, 763, 470, 932, 471, 335, - 472, 358, 634, 428, 638, 640, 825, 633, 33, 34, - 429, 642, 643, 646, 35, 473, 648, 649, 651, 652, - 356, 357, 635, 426, 1221, 1223, 761, 842, 476, 468, - 248, 760, 841, 811, 1222, 840, 40, 21, 427, 1057, - 470, 830, 471, 1045, 472, 839, 1046, 428, 828, 215, - 216, 939, 33, 34, 429, 217, 864, 218, 35, 473, - 825, 633, 24, 865, 356, 357, 456, 1220, 1189, 209, - 1187, 1172, 476, 1185, 215, 216, 1086, 1095, 1096, 914, - 217, 1193, 218, 1183, -224, 1097, 26, 31, 37, 42, - 76, 77, 210, 288, 209, 292, 293, 308, 309, 310, - 311, 339, 1095, 1096, 825, 633, 355, 291, 416, 1152, - 1097, 16, 17, 18, 393, 453, 460, 462, 466, 552, - 624, 1048, 1051, 904, 1111, 1047, 1023, 563, 1022, 1088, - 0, 0, -429, 558, 1041, 1101, 1102, 1103, 1104, 1098, - 1099, 398, 1054, 1053, 1056, 1055, 1070, 1105, 1100, 1186, - 1171, 1167, 1184, 1085, 1218, 1112, 1166, 219, 558, 599, - 1101, 1102, 1103, 1104, 1098, 1099, 398, 0, 0, 0, - 0, 0, 1105, 1100, 0, 0, 0, 0, 0, 0, - 0, 0, 219 - ); - - protected $actionCheck = array( - 2, 3, 4, 5, 6, 7, 14, 9, 10, 11, - 12, 13, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 0, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 9, 10, 11, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 69, 70, - 53, 54, 55, 9, 10, 57, 30, 80, 32, 33, - 34, 35, 36, 37, 38, 80, 69, 70, 83, 71, - 72, 73, 74, 75, 76, 77, 9, 70, 80, 33, - 34, 35, 36, 37, 38, 87, 88, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 153, 133, 134, 135, 136, 137, 138, 139, 140, 141, - 3, 4, 5, 6, 7, 147, 148, 149, 80, 12, - 13, 159, 15, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 156, 44, 45, 46, 47, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 13, 106, 116, 108, 85, 50, 51, 33, - 34, 35, 36, 56, 85, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 68, 1, 70, 71, 72, - 73, 59, 60, 13, 82, 78, 79, 80, 80, 82, - 152, 153, 154, 86, 9, 10, 11, 8, 1, 2, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 9, - 10, 11, 156, 106, 143, 30, 160, 32, 33, 34, - 35, 36, 143, 116, 116, 117, 118, 119, 120, 121, - 30, 124, 125, 116, 117, 118, 119, 120, 121, 13, - 133, 134, 70, 136, 137, 138, 139, 140, 141, 142, - 31, 37, 38, 8, 132, 148, 149, 116, 156, 152, - 153, 154, 160, 37, 38, 158, 8, 160, 161, 8, - 163, 74, 75, 76, 77, 134, 135, 80, 9, 10, - 11, 84, 1, 80, 87, 88, 89, 90, 91, 92, - 93, 94, 95, 96, 155, 98, 0, 1, 2, 30, - 103, 104, 105, 106, 132, 8, 109, 110, 9, 10, - 11, 8, 115, 116, 117, 118, 9, 10, 11, 82, - 123, 70, 8, 126, 127, 128, 129, 8, 156, 30, - 155, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 9, 10, 11, 157, 53, 54, 55, - 8, 57, 155, 156, 157, 152, 153, 154, 10, 11, - 157, 80, 162, 69, 30, 151, 32, 33, 34, 35, - 74, 1, 2, 159, 155, 71, 80, 151, 30, 8, - 84, 37, 38, 87, 88, 89, 82, 91, 82, 93, - 8, 95, 13, 156, 98, 158, 13, 160, 13, 103, - 104, 105, 106, 82, 108, 109, 110, 156, 8, 113, - 31, 115, 116, 117, 118, 9, 10, 11, 157, 123, - 37, 38, 126, 127, 128, 129, 82, 13, 159, 33, - 34, 35, 82, 127, 8, 85, 30, 156, 32, 33, - 34, 160, 8, 147, 74, 1, 2, 50, 51, 52, - 80, 155, 156, 157, 84, 31, 159, 87, 88, 89, - 82, 91, 158, 93, 160, 95, 160, 106, 98, 108, - 100, 101, 102, 103, 104, 105, 106, 133, 159, 109, - 110, 160, 9, 10, 11, 115, 116, 117, 118, 9, - 10, 11, 8, 123, 144, 145, 126, 127, 128, 129, - 82, 82, 158, 30, 160, 32, 33, 108, 8, 70, - 30, 31, 113, 152, 16, 9, 10, 11, 74, 14, - 14, 122, 8, 8, 80, 155, 156, 157, 84, 13, - 159, 87, 88, 89, 151, 91, 30, 93, 160, 95, - 155, 159, 98, 14, 100, 101, 102, 103, 104, 105, - 106, 133, 16, 109, 110, 155, 157, 1, 2, 115, - 116, 117, 118, 9, 10, 11, 13, 123, 16, 155, - 126, 127, 128, 129, 33, 34, 158, 158, 160, 160, - 156, 9, 10, 11, 30, 37, 38, 31, 70, 155, - 37, 38, 50, 51, 52, 156, 16, 81, 16, 155, - 156, 157, 30, 16, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 16, 57, - 74, 9, 10, 11, 1, 2, 80, 116, 11, 155, - 84, 69, 156, 87, 88, 89, 160, 91, 30, 93, - 132, 95, 30, 33, 98, 134, 135, 30, 57, 103, - 104, 105, 69, 70, 31, 109, 110, 75, 76, 155, - 155, 115, 116, 75, 76, 101, 102, 111, 112, 123, - 159, 155, 156, 155, 156, 155, 156, 31, 1, 2, - 31, 31, 31, 31, 31, 38, 70, 69, 77, 70, - 70, 70, 70, 80, 70, 70, 70, 74, 71, 85, - 85, 155, 156, 80, 97, 96, 100, 84, 31, 106, - 87, 88, 89, 82, 91, 82, 93, 82, 95, 89, - 92, 98, 1, 2, 90, 127, 103, 104, 105, 97, - 94, 127, 109, 110, 97, 97, 97, 132, 115, 116, - 100, 146, 113, 143, 143, 146, 123, 106, 151, 155, - 157, 74, 31, 157, 162, -1, 114, 80, -1, 116, - -1, 84, -1, -1, 87, 88, 89, -1, 91, -1, - 93, -1, 95, -1, 130, 98, 1, 2, 155, 156, - 103, 104, 105, -1, 130, -1, 109, 110, 131, -1, - 132, 132, 115, 116, 132, 74, -1, 152, 150, -1, - 123, 80, 146, -1, -1, 84, 31, 146, 87, 88, - 89, 146, 91, 146, 93, 146, 95, 146, 150, 98, - 1, 2, 156, 159, 103, 104, 105, 155, 155, 155, - 109, 110, 155, 156, 155, 155, 115, 116, 155, 155, - 155, 155, 155, 155, 123, 155, 155, 155, 155, 74, - 155, 155, 155, 155, 155, 80, 155, 155, 155, 84, - 155, 155, 87, 88, 89, 155, 91, 155, 93, 156, - 95, 156, 156, 98, 156, 156, 155, 156, 103, 104, - 105, 156, 156, 156, 109, 110, 156, 156, 156, 156, - 115, 116, 156, 74, 157, 157, 157, 157, 123, 80, - 31, 157, 157, 84, 157, 157, 87, 88, 89, 157, - 91, 157, 93, 157, 95, 157, 157, 98, 157, 50, - 51, 157, 103, 104, 105, 56, 157, 58, 109, 110, - 155, 156, 158, 157, 115, 116, 157, 157, 157, 70, - 157, 157, 123, 157, 50, 51, 157, 78, 79, 157, - 56, 157, 58, 157, 159, 86, 158, 158, 158, 158, - 158, 158, 158, 158, 70, 158, 158, 158, 158, 158, - 158, 158, 78, 79, 155, 156, 158, 160, 158, 163, - 86, 159, 159, 159, 159, 159, 159, 159, 159, 159, - 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, - -1, -1, 161, 134, 161, 136, 137, 138, 139, 140, - 141, 142, 162, 162, 162, 162, 162, 148, 149, 162, - 162, 162, 162, 162, 162, 162, 162, 158, 134, 162, - 136, 137, 138, 139, 140, 141, 142, -1, -1, -1, - -1, -1, 148, 149, -1, -1, -1, -1, -1, -1, - -1, -1, 158 - ); - - protected $actionBase = array( - 0, 227, 326, 400, 474, 233, 132, 132, 752, -2, - -2, 138, -2, -2, -2, 663, 761, 815, 761, 586, - 717, 859, 859, 859, 244, 256, 256, 256, 413, 583, - 583, 880, 546, 169, 415, 444, 409, 200, 200, 200, - 200, 137, 137, 200, 200, 200, 200, 200, 200, 200, - 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, - 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, - 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, - 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, - 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, - 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, - 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, - 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, - 200, 200, 200, 200, 200, 200, 249, 205, 738, 559, - 535, 739, 741, 742, 876, 679, 877, 820, 821, 693, - 823, 824, 826, 829, 832, 819, 834, 907, 836, 602, - 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, - 602, 67, 536, 299, 510, 230, 44, 652, 652, 652, - 652, 652, 652, 652, 337, 337, 337, 337, 337, 337, - 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, - 337, 337, 378, 584, 584, 584, 657, 909, 648, 934, - 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, - 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, - 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, - 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, - 934, 934, 934, 503, -21, -21, 436, 650, 364, 571, - 215, 426, 156, 26, 26, 329, 329, 329, 329, 329, - 46, 46, 5, 5, 5, 5, 152, 186, 186, 186, - 186, 120, 120, 120, 120, 374, 374, 429, 448, 448, - 334, 267, 449, 449, 449, 449, 449, 449, 449, 449, - 449, 449, 336, 427, 427, 572, 572, 408, 551, 551, - 551, 551, 671, 171, 171, 391, 311, 311, 311, 109, - 641, 856, 68, 68, 68, 68, 68, 68, 324, 324, - 324, -3, -3, -3, 655, 77, 380, 77, 380, 683, - 685, 86, 685, 654, -15, 516, 776, 281, 646, 809, - 680, 816, 560, 711, 202, 578, 857, 643, -23, 578, - 578, 578, 578, 857, 622, 628, 596, -23, 578, -23, - 639, 454, 849, 351, 249, 558, 469, 631, 743, 514, - 688, 746, 464, 544, 548, 556, 7, 412, 708, 750, - 878, 879, 349, 702, 631, 631, 631, 327, 101, 7, - -8, 623, 623, 623, 623, 219, 623, 623, 623, 623, - 291, 430, 545, 401, 745, 653, 653, 675, 839, 814, - 814, 653, 673, 653, 675, 841, 841, 841, 841, 653, - 653, 653, 653, 814, 814, 667, 814, 275, 684, 694, - 694, 841, 713, 714, 653, 653, 697, 814, 814, 814, - 697, 687, 841, 669, 637, 333, 814, 841, 689, 673, - 689, 653, 669, 689, 673, 673, 689, 22, 686, 656, - 840, 842, 860, 756, 638, 644, 847, 848, 843, 845, - 838, 692, 719, 720, 528, 659, 660, 661, 662, 696, - 664, 698, 643, 658, 658, 658, 645, 701, 645, 658, - 658, 658, 658, 658, 658, 658, 658, 632, 635, 709, - 699, 670, 723, 566, 582, 758, 640, 636, 872, 865, - 881, 883, 849, 870, 645, 890, 634, 288, 610, 850, - 633, 753, 645, 851, 645, 759, 645, 873, 777, 666, - 778, 779, 658, 874, 891, 892, 893, 894, 897, 898, - 899, 900, 665, 901, 724, 674, 866, 344, 844, 639, - 705, 677, 755, 725, 780, 372, 902, 784, 645, 645, - 765, 706, 645, 766, 726, 712, 862, 727, 867, 903, - 640, 678, 868, 645, 681, 785, 904, 372, 690, 651, - 704, 649, 728, 858, 875, 853, 767, 612, 617, 787, - 788, 792, 691, 730, 863, 864, 835, 731, 770, 642, - 771, 676, 794, 772, 852, 732, 796, 798, 871, 647, - 707, 682, 672, 668, 773, 799, 869, 733, 735, 736, - 801, 737, 804, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 137, 137, 137, 137, -2, -2, -2, - -2, 0, 0, -2, 0, 0, 0, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 0, 0, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 602, 602, - 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, - 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, - 602, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 602, -21, -21, -21, -21, 602, -21, - -21, -21, -21, -21, -21, -21, 602, 602, 602, 602, - 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, - 602, 602, 602, 602, -21, 602, 602, 602, -21, 68, - -21, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 602, 0, 0, 602, -21, - 602, -21, 602, -21, -21, 602, 602, 602, 602, 602, - 602, 602, -21, -21, -21, -21, -21, -21, 0, 324, - 324, 324, 324, -21, -21, -21, -21, 68, 68, 147, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 324, 324, -3, -3, 68, - 68, 68, 68, 68, 147, 68, 68, -23, 673, 673, - 673, 380, 380, 380, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 380, -23, 0, -23, - 0, 68, -23, 673, -23, 380, 673, 673, -23, 814, - 604, 604, 604, 604, 372, 7, 0, 0, 673, 673, - 0, 0, 0, 0, 0, 673, 0, 0, 0, 0, - 0, 0, 814, 0, 653, 0, 0, 0, 0, 658, - 288, 0, 677, 456, 0, 0, 0, 0, 0, 0, - 677, 456, 530, 530, 0, 665, 658, 658, 658, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 372 - ); - - protected $actionDefault = array( - 3,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767, 540, 540, 495,32767,32767, - 32767,32767,32767,32767,32767,32767,32767, 297, 297, 297, - 32767,32767,32767, 528, 528, 528, 528, 528, 528, 528, - 528, 528, 528, 528,32767,32767,32767,32767,32767,32767, - 381,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767, 387, - 545,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767, 362, - 363, 365, 366, 296, 548, 529, 245, 388, 544, 295, - 247, 325, 499,32767,32767,32767, 327, 122, 256, 201, - 498, 125, 294, 232, 380, 382, 326, 301, 306, 307, - 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 300, 454, 359, 358, 357, 456,32767, 455, 492, - 492, 495,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767, 323, 483, 482, 324, 452, 328, 453, - 331, 457, 460, 329, 330, 347, 348, 345, 346, 349, - 458, 459, 476, 477, 474, 475, 299, 350, 351, 352, - 353, 478, 479, 480, 481,32767,32767, 280, 539, 539, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767, 338, 339, 467, 468,32767, 236, 236, - 236, 236, 281, 236,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767, 333, 334, - 332, 462, 463, 461, 428,32767,32767,32767, 430,32767, - 32767,32767,32767,32767,32767,32767,32767, 500,32767,32767, - 32767,32767,32767, 513, 417, 171,32767, 409,32767, 171, - 171, 171, 171,32767, 220, 222, 167,32767, 171,32767, - 486,32767,32767,32767,32767,32767, 518, 343,32767,32767, - 116,32767,32767,32767, 555,32767, 513,32767, 116,32767, - 32767,32767,32767, 356, 335, 336, 337,32767,32767, 517, - 511, 470, 471, 472, 473,32767, 464, 465, 466, 469, - 32767,32767,32767,32767,32767,32767,32767,32767, 425, 431, - 431,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767, 516, 515,32767, 410, 494, 186, 184, - 184,32767, 206, 206,32767,32767, 188, 487, 506,32767, - 188, 173,32767, 398, 175, 494,32767,32767, 238,32767, - 238,32767, 398, 238,32767,32767, 238,32767, 411, 435, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767, 377, 378, 489, 502,32767, - 503,32767, 409, 341, 342, 344, 320,32767, 322, 367, - 368, 369, 370, 371, 372, 373, 375,32767, 415,32767, - 418,32767,32767,32767, 255,32767, 553,32767,32767, 304, - 553,32767,32767,32767, 547,32767,32767, 298,32767,32767, - 32767,32767, 251,32767, 169,32767, 537,32767, 554,32767, - 511,32767, 340,32767,32767,32767,32767,32767,32767,32767, - 32767,32767, 512,32767,32767,32767,32767, 227,32767, 448, - 32767, 116,32767,32767,32767, 187,32767,32767, 302, 246, - 32767,32767, 546,32767,32767,32767,32767,32767,32767,32767, - 32767, 114,32767, 170,32767,32767,32767, 189,32767,32767, - 511,32767,32767,32767,32767,32767,32767,32767, 293,32767, - 32767,32767,32767,32767,32767,32767, 511,32767,32767, 231, - 32767,32767,32767,32767,32767,32767,32767,32767,32767, 411, - 32767, 274,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767, 127, 127, 3, 127, 127, 258, 3, - 258, 127, 258, 258, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 214, 217, 206, 206, 164, 127, - 127, 266 - ); - - protected $goto = array( - 166, 140, 140, 140, 166, 187, 168, 144, 147, 141, - 142, 143, 149, 163, 163, 163, 163, 144, 144, 165, - 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, - 138, 159, 160, 161, 162, 184, 139, 185, 493, 494, - 377, 495, 499, 500, 501, 502, 503, 504, 505, 506, - 967, 164, 145, 146, 148, 171, 176, 186, 203, 253, - 256, 258, 260, 263, 264, 265, 266, 267, 268, 269, - 277, 278, 279, 280, 303, 304, 328, 329, 330, 394, - 395, 396, 542, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 200, 201, 150, 151, 152, - 167, 153, 169, 154, 204, 170, 155, 156, 157, 205, - 158, 136, 620, 560, 756, 560, 560, 560, 560, 560, - 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, - 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, - 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, - 560, 560, 560, 560, 560, 560, 560, 560, 560, 1108, - 628, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 757, 888, 888, 508, 1200, - 1200, 400, 606, 508, 536, 536, 568, 532, 534, 534, - 496, 498, 524, 540, 569, 572, 583, 590, 852, 852, - 852, 852, 847, 853, 174, 585, 519, 600, 601, 177, - 178, 179, 401, 402, 403, 404, 173, 202, 206, 208, - 257, 259, 261, 262, 270, 271, 272, 273, 274, 275, - 281, 282, 283, 284, 305, 306, 331, 332, 333, 406, - 407, 408, 409, 175, 180, 254, 255, 181, 182, 183, - 497, 497, 785, 497, 497, 497, 497, 497, 497, 497, - 497, 497, 497, 497, 497, 497, 497, 509, 578, 582, - 626, 749, 509, 544, 545, 546, 547, 548, 549, 550, - 551, 553, 586, 338, 559, 321, 559, 559, 559, 559, - 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, - 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, - 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, - 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, - 530, 349, 655, 555, 587, 352, 414, 591, 575, 604, - 885, 611, 612, 881, 616, 617, 623, 625, 630, 632, - 298, 296, 296, 296, 298, 290, 299, 944, 610, 816, - 1170, 613, 436, 436, 375, 436, 436, 436, 436, 436, - 436, 436, 436, 436, 436, 436, 436, 436, 436, 1072, - 1084, 1083, 945, 1065, 1072, 895, 895, 895, 895, 1178, - 895, 895, 1212, 1212, 1178, 388, 858, 561, 755, 1072, - 1072, 1072, 1072, 1072, 1072, 3, 4, 384, 384, 384, - 1212, 874, 856, 854, 856, 654, 465, 511, 883, 878, - 1089, 541, 384, 537, 384, 567, 384, 1026, 19, 15, - 371, 384, 1226, 510, 1204, 1192, 1192, 1192, 510, 906, - 372, 522, 533, 554, 912, 514, 1068, 1069, 13, 1065, - 378, 912, 1158, 594, 23, 965, 386, 386, 386, 602, - 1066, 1169, 1066, 937, 447, 449, 631, 752, 1177, 1067, - 1109, 614, 935, 1177, 605, 1197, 391, 1211, 1211, 543, - 892, 386, 1194, 1194, 1194, 399, 518, 1016, 901, 389, - 771, 529, 752, 340, 752, 1211, 518, 518, 385, 781, - 1214, 770, 772, 1063, 910, 774, 1058, 1176, 659, 953, - 514, 782, 862, 915, 450, 573, 1155, 0, 463, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 513, 528, 0, 0, 0, 0, - 513, 0, 528, 0, 350, 351, 0, 609, 512, 515, - 438, 439, 1064, 618, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 779, 1219, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 777, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 523, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 301, 301 - ); - - protected $gotoCheck = array( - 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 57, 68, 15, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 126, - 9, 126, 126, 126, 126, 126, 126, 126, 126, 126, - 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, - 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, - 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, - 126, 126, 126, 126, 126, 16, 76, 76, 68, 76, - 76, 51, 51, 68, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 68, 68, - 68, 68, 68, 68, 27, 66, 101, 66, 66, 27, - 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, - 117, 117, 29, 117, 117, 117, 117, 117, 117, 117, - 117, 117, 117, 117, 117, 117, 117, 117, 61, 61, - 61, 6, 117, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 125, 57, 125, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 32, 71, 32, 32, 69, 69, 69, 32, 40, 40, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 5, 5, 5, 5, 5, 5, 5, 97, 62, 50, - 81, 62, 57, 57, 62, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 124, 124, 97, 81, 57, 57, 57, 57, 57, 118, - 57, 57, 142, 142, 118, 12, 33, 12, 14, 57, - 57, 57, 57, 57, 57, 30, 30, 13, 13, 13, - 142, 14, 14, 14, 14, 14, 57, 14, 14, 14, - 34, 2, 13, 109, 13, 2, 13, 34, 34, 34, - 34, 13, 13, 122, 140, 9, 9, 9, 122, 83, - 58, 58, 58, 34, 13, 13, 81, 81, 58, 81, - 46, 13, 131, 127, 34, 101, 123, 123, 123, 34, - 81, 81, 81, 8, 8, 8, 8, 11, 119, 81, - 8, 8, 8, 119, 49, 138, 48, 141, 141, 47, - 78, 123, 119, 119, 119, 123, 47, 102, 80, 17, - 23, 9, 11, 18, 11, 141, 47, 47, 11, 23, - 141, 23, 24, 115, 84, 25, 113, 119, 73, 99, - 13, 26, 70, 85, 64, 65, 130, -1, 108, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 9, 9, -1, -1, -1, -1, - 9, -1, 9, -1, 71, 71, -1, 13, 9, 9, - 9, 9, 13, 13, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 9, 9, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 101, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 5, 5 - ); - - protected $gotoBase = array( - 0, 0, -184, 0, 0, 356, 290, 0, 488, 149, - 0, 182, 85, 118, 426, 112, 203, 179, 208, 0, - 0, 0, 0, 162, 190, 198, 120, 27, 0, 272, - -224, 0, -274, 406, 32, 0, 0, 0, 0, 0, - 330, 0, 0, -24, 0, 0, 440, 485, 213, 218, - 371, -74, 0, 0, 0, 0, 0, 107, 110, 0, - 0, -11, -72, 0, 104, 95, -405, 0, -94, 41, - 119, -82, 0, 164, 0, 0, -79, 0, 197, 0, - 204, 43, 0, 441, 171, 121, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 100, 0, 115, - 0, 195, 210, 0, 0, 0, 0, 0, 86, 427, - 259, 0, 0, 116, 0, 174, 0, -5, 117, 196, - 0, 0, 161, 170, 93, -21, -48, 273, 0, 0, - 91, 271, 0, 0, 0, 0, 0, 0, 216, 0, - 437, 187, 102, 0, 0 - ); - - protected $gotoDefault = array( - -32768, 467, 663, 2, 664, 834, 739, 747, 597, 481, - 629, 581, 380, 1188, 791, 792, 793, 381, 367, 482, - 379, 410, 405, 780, 773, 775, 783, 172, 411, 786, - 1, 788, 517, 824, 1017, 364, 796, 365, 589, 798, - 526, 800, 801, 137, 382, 383, 527, 483, 390, 576, - 815, 276, 387, 817, 366, 818, 827, 370, 464, 454, - 459, 556, 608, 432, 446, 570, 564, 535, 1081, 565, - 861, 348, 869, 660, 877, 880, 484, 557, 891, 451, - 899, 1094, 397, 905, 911, 916, 287, 919, 417, 412, - 584, 924, 925, 5, 929, 621, 622, 8, 312, 952, - 598, 966, 420, 1036, 1038, 485, 486, 521, 458, 507, - 525, 487, 1059, 440, 413, 1062, 488, 489, 433, 434, - 1078, 354, 1163, 353, 448, 320, 1150, 579, 1113, 455, - 1203, 1159, 347, 490, 491, 376, 1182, 392, 1198, 437, - 1205, 1213, 343, 539, 566 - ); - - protected $ruleToNonTerminal = array( - 0, 1, 3, 3, 2, 5, 5, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, - 7, 7, 7, 7, 8, 8, 9, 10, 11, 11, - 12, 12, 13, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 18, 18, 19, 19, 21, 21, - 17, 17, 22, 22, 23, 23, 24, 24, 25, 25, - 20, 20, 26, 28, 28, 29, 30, 30, 32, 31, - 31, 31, 31, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 14, 14, 54, 54, 56, 55, 55, 48, - 48, 58, 58, 59, 59, 60, 60, 15, 16, 16, - 16, 63, 63, 63, 64, 64, 67, 67, 65, 65, - 69, 69, 41, 41, 50, 50, 53, 53, 53, 52, - 52, 70, 42, 42, 42, 42, 71, 71, 72, 72, - 73, 73, 39, 39, 35, 35, 74, 37, 37, 75, - 36, 36, 38, 38, 49, 49, 49, 61, 61, 77, - 77, 78, 78, 80, 80, 80, 79, 79, 62, 62, - 81, 81, 81, 82, 82, 83, 83, 83, 44, 44, - 84, 84, 84, 45, 45, 85, 85, 86, 86, 66, - 87, 87, 87, 87, 92, 92, 93, 93, 94, 94, - 94, 94, 94, 95, 96, 96, 91, 91, 88, 88, - 90, 90, 98, 98, 97, 97, 97, 97, 97, 97, - 89, 89, 100, 99, 99, 46, 46, 40, 40, 43, - 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, - 43, 43, 43, 43, 43, 34, 34, 47, 47, 105, - 105, 106, 106, 106, 106, 112, 101, 101, 108, 108, - 114, 114, 115, 116, 116, 116, 116, 116, 116, 68, - 68, 57, 57, 57, 57, 102, 102, 120, 120, 117, - 117, 121, 121, 121, 121, 103, 103, 103, 107, 107, - 107, 113, 113, 126, 126, 126, 126, 126, 126, 126, - 126, 126, 126, 126, 126, 126, 27, 27, 27, 27, - 27, 27, 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 111, 111, 104, 104, - 104, 104, 127, 127, 130, 130, 129, 129, 131, 131, - 51, 51, 51, 51, 133, 133, 132, 132, 132, 132, - 132, 134, 134, 119, 119, 122, 122, 118, 118, 136, - 135, 135, 135, 135, 123, 123, 123, 123, 110, 110, - 124, 124, 124, 124, 76, 137, 137, 138, 138, 138, - 109, 109, 139, 139, 140, 140, 140, 140, 140, 125, - 125, 125, 125, 142, 143, 141, 141, 141, 141, 141, - 141, 141, 144, 144, 144 - ); - - protected $ruleToLength = array( - 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 3, 5, 4, - 3, 4, 2, 3, 1, 1, 7, 6, 3, 1, - 3, 1, 3, 1, 1, 3, 1, 3, 1, 2, - 3, 1, 3, 3, 1, 3, 2, 0, 1, 1, - 1, 1, 1, 3, 5, 8, 3, 5, 9, 3, - 2, 3, 2, 3, 2, 3, 3, 3, 3, 1, - 2, 2, 5, 7, 9, 5, 6, 3, 3, 2, - 2, 1, 1, 1, 0, 2, 8, 0, 4, 1, - 3, 0, 1, 0, 1, 0, 1, 10, 7, 6, - 5, 1, 2, 2, 0, 2, 0, 2, 0, 2, - 1, 3, 1, 4, 1, 4, 1, 1, 4, 1, - 3, 3, 3, 4, 4, 5, 0, 2, 4, 3, - 1, 1, 1, 4, 0, 2, 3, 0, 2, 4, - 0, 2, 0, 3, 1, 2, 1, 1, 0, 1, - 3, 4, 6, 1, 1, 1, 0, 1, 0, 2, - 2, 3, 3, 1, 3, 1, 2, 2, 3, 1, - 1, 2, 4, 3, 1, 1, 3, 2, 0, 1, - 3, 3, 9, 3, 1, 3, 0, 2, 4, 5, - 4, 4, 4, 3, 1, 1, 1, 3, 1, 1, - 0, 1, 1, 2, 1, 1, 1, 1, 1, 1, - 1, 3, 1, 1, 3, 3, 1, 0, 1, 1, - 3, 3, 4, 4, 1, 2, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, - 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 1, 3, 5, 4, 3, - 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 1, 1, 3, - 2, 1, 2, 10, 11, 3, 3, 2, 4, 4, - 3, 4, 4, 4, 4, 7, 3, 2, 0, 4, - 1, 3, 2, 2, 4, 6, 2, 2, 4, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 3, 3, 4, 4, 0, 2, 1, 0, 1, - 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 3, 2, 1, 3, 1, 4, - 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, - 3, 3, 5, 4, 4, 3, 1, 3, 1, 1, - 3, 3, 0, 2, 0, 1, 3, 1, 3, 1, - 1, 1, 1, 1, 6, 4, 3, 4, 2, 4, - 4, 1, 3, 1, 2, 1, 1, 4, 1, 1, - 3, 6, 4, 4, 4, 4, 1, 4, 0, 1, - 1, 3, 1, 1, 4, 3, 1, 1, 1, 0, - 0, 2, 3, 1, 3, 1, 4, 2, 2, 2, - 2, 1, 2, 1, 1, 1, 4, 3, 3, 3, - 6, 3, 1, 1, 1 - ); - - protected function initReduceCallbacks() { - $this->reduceCallbacks = [ - 0 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 1 => function ($stackPos) { - $this->semValue = $this->handleNamespaces($this->semStack[$stackPos-(1-1)]); - }, - 2 => function ($stackPos) { - if (is_array($this->semStack[$stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); } else { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }; - }, - 3 => function ($stackPos) { - $this->semValue = array(); - }, - 4 => function ($stackPos) { - $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; - if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 5 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 6 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 7 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 8 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 9 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 10 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 11 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 12 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 13 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 14 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 15 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 16 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 17 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 18 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 19 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 20 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 21 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 22 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 23 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 24 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 25 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 26 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 27 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 28 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 29 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 30 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 31 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 32 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 33 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 34 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 35 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 36 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 37 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 38 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 39 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 40 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 41 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 42 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 43 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 44 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 45 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 46 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 47 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 48 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 49 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 50 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 51 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 52 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 53 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 54 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 55 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 56 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 57 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 58 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 59 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 60 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 61 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 62 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 63 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 64 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 65 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 66 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 67 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 68 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 69 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 70 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 71 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 72 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 73 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 74 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 75 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 76 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 77 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 78 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 79 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 80 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 81 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 82 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 83 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 84 => function ($stackPos) { - $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 85 => function ($stackPos) { - $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 86 => function ($stackPos) { - $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 87 => function ($stackPos) { - $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 88 => function ($stackPos) { - $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 89 => function ($stackPos) { - $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 90 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 91 => function ($stackPos) { - $this->semValue = new Name(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 92 => function ($stackPos) { - $this->semValue = new Expr\Variable(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 93 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 94 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 95 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 96 => function ($stackPos) { - $this->semValue = new Stmt\HaltCompiler($this->lexer->handleHaltCompiler(), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 97 => function ($stackPos) { - $this->semValue = new Stmt\Namespace_($this->semStack[$stackPos-(3-2)], null, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON); - $this->checkNamespace($this->semValue); - }, - 98 => function ($stackPos) { - $this->semValue = new Stmt\Namespace_($this->semStack[$stackPos-(5-2)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); - $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); - $this->checkNamespace($this->semValue); - }, - 99 => function ($stackPos) { - $this->semValue = new Stmt\Namespace_(null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); - $this->checkNamespace($this->semValue); - }, - 100 => function ($stackPos) { - $this->semValue = new Stmt\Use_($this->semStack[$stackPos-(3-2)], Stmt\Use_::TYPE_NORMAL, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 101 => function ($stackPos) { - $this->semValue = new Stmt\Use_($this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 102 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 103 => function ($stackPos) { - $this->semValue = new Stmt\Const_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 104 => function ($stackPos) { - $this->semValue = Stmt\Use_::TYPE_FUNCTION; - }, - 105 => function ($stackPos) { - $this->semValue = Stmt\Use_::TYPE_CONSTANT; - }, - 106 => function ($stackPos) { - $this->semValue = new Stmt\GroupUse($this->semStack[$stackPos-(7-3)], $this->semStack[$stackPos-(7-6)], $this->semStack[$stackPos-(7-2)], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); - }, - 107 => function ($stackPos) { - $this->semValue = new Stmt\GroupUse($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-5)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); - }, - 108 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 109 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 110 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 111 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 112 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 113 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 114 => function ($stackPos) { - $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(1-1)); - }, - 115 => function ($stackPos) { - $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(3-3)); - }, - 116 => function ($stackPos) { - $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(1-1)); - }, - 117 => function ($stackPos) { - $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(3-3)); - }, - 118 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; $this->semValue->type = Stmt\Use_::TYPE_NORMAL; - }, - 119 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-2)]; $this->semValue->type = $this->semStack[$stackPos-(2-1)]; - }, - 120 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 121 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 122 => function ($stackPos) { - $this->semValue = new Node\Const_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 123 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 124 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 125 => function ($stackPos) { - $this->semValue = new Node\Const_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 126 => function ($stackPos) { - if (is_array($this->semStack[$stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); } else { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }; - }, - 127 => function ($stackPos) { - $this->semValue = array(); - }, - 128 => function ($stackPos) { - $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; - if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 129 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 130 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 131 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 132 => function ($stackPos) { - throw new Error('__HALT_COMPILER() can only be used from the outermost scope', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 133 => function ($stackPos) { - - if ($this->semStack[$stackPos-(3-2)]) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; $attrs = $this->startAttributeStack[$stackPos-(3-1)]; $stmts = $this->semValue; if (!empty($attrs['comments'])) {$stmts[0]->setAttribute('comments', array_merge($attrs['comments'], $stmts[0]->getAttribute('comments', []))); }; - } else { - $startAttributes = $this->startAttributeStack[$stackPos-(3-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; }; - if (null === $this->semValue) { $this->semValue = array(); } - } - - }, - 134 => function ($stackPos) { - $this->semValue = new Stmt\If_($this->semStack[$stackPos-(5-2)], ['stmts' => is_array($this->semStack[$stackPos-(5-3)]) ? $this->semStack[$stackPos-(5-3)] : array($this->semStack[$stackPos-(5-3)]), 'elseifs' => $this->semStack[$stackPos-(5-4)], 'else' => $this->semStack[$stackPos-(5-5)]], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); - }, - 135 => function ($stackPos) { - $this->semValue = new Stmt\If_($this->semStack[$stackPos-(8-2)], ['stmts' => $this->semStack[$stackPos-(8-4)], 'elseifs' => $this->semStack[$stackPos-(8-5)], 'else' => $this->semStack[$stackPos-(8-6)]], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); - }, - 136 => function ($stackPos) { - $this->semValue = new Stmt\While_($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 137 => function ($stackPos) { - $this->semValue = new Stmt\Do_($this->semStack[$stackPos-(5-4)], is_array($this->semStack[$stackPos-(5-2)]) ? $this->semStack[$stackPos-(5-2)] : array($this->semStack[$stackPos-(5-2)]), $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); - }, - 138 => function ($stackPos) { - $this->semValue = new Stmt\For_(['init' => $this->semStack[$stackPos-(9-3)], 'cond' => $this->semStack[$stackPos-(9-5)], 'loop' => $this->semStack[$stackPos-(9-7)], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); - }, - 139 => function ($stackPos) { - $this->semValue = new Stmt\Switch_($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 140 => function ($stackPos) { - $this->semValue = new Stmt\Break_(null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 141 => function ($stackPos) { - $this->semValue = new Stmt\Break_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 142 => function ($stackPos) { - $this->semValue = new Stmt\Continue_(null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 143 => function ($stackPos) { - $this->semValue = new Stmt\Continue_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 144 => function ($stackPos) { - $this->semValue = new Stmt\Return_(null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 145 => function ($stackPos) { - $this->semValue = new Stmt\Return_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 146 => function ($stackPos) { - $this->semValue = new Stmt\Global_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 147 => function ($stackPos) { - $this->semValue = new Stmt\Static_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 148 => function ($stackPos) { - $this->semValue = new Stmt\Echo_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 149 => function ($stackPos) { - $this->semValue = new Stmt\InlineHTML($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 150 => function ($stackPos) { - $this->semValue = new Stmt\Expression($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 151 => function ($stackPos) { - $this->semValue = new Stmt\Expression($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 152 => function ($stackPos) { - $this->semValue = new Stmt\Unset_($this->semStack[$stackPos-(5-3)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); - }, - 153 => function ($stackPos) { - $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(7-3)], $this->semStack[$stackPos-(7-5)][0], ['keyVar' => null, 'byRef' => $this->semStack[$stackPos-(7-5)][1], 'stmts' => $this->semStack[$stackPos-(7-7)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); - }, - 154 => function ($stackPos) { - $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(9-3)], $this->semStack[$stackPos-(9-7)][0], ['keyVar' => $this->semStack[$stackPos-(9-5)], 'byRef' => $this->semStack[$stackPos-(9-7)][1], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); - }, - 155 => function ($stackPos) { - $this->semValue = new Stmt\Declare_($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); - }, - 156 => function ($stackPos) { - $this->semValue = new Stmt\TryCatch($this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-5)], $this->semStack[$stackPos-(6-6)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); $this->checkTryCatch($this->semValue); - }, - 157 => function ($stackPos) { - $this->semValue = new Stmt\Throw_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 158 => function ($stackPos) { - $this->semValue = new Stmt\Goto_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 159 => function ($stackPos) { - $this->semValue = new Stmt\Label($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 160 => function ($stackPos) { - $this->semValue = new Stmt\Expression($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 161 => function ($stackPos) { - $this->semValue = array(); /* means: no statement */ - }, - 162 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 163 => function ($stackPos) { - $startAttributes = $this->startAttributeStack[$stackPos-(1-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; }; - if ($this->semValue === null) $this->semValue = array(); /* means: no statement */ - }, - 164 => function ($stackPos) { - $this->semValue = array(); - }, - 165 => function ($stackPos) { - $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 166 => function ($stackPos) { - $this->semValue = new Stmt\Catch_(array($this->semStack[$stackPos-(8-3)]), $this->semStack[$stackPos-(8-4)], $this->semStack[$stackPos-(8-7)], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); - }, - 167 => function ($stackPos) { - $this->semValue = null; - }, - 168 => function ($stackPos) { - $this->semValue = new Stmt\Finally_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 169 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 170 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 171 => function ($stackPos) { - $this->semValue = false; - }, - 172 => function ($stackPos) { - $this->semValue = true; - }, - 173 => function ($stackPos) { - $this->semValue = false; - }, - 174 => function ($stackPos) { - $this->semValue = true; - }, - 175 => function ($stackPos) { - $this->semValue = false; - }, - 176 => function ($stackPos) { - $this->semValue = true; - }, - 177 => function ($stackPos) { - $this->semValue = new Stmt\Function_($this->semStack[$stackPos-(10-3)], ['byRef' => $this->semStack[$stackPos-(10-2)], 'params' => $this->semStack[$stackPos-(10-5)], 'returnType' => $this->semStack[$stackPos-(10-7)], 'stmts' => $this->semStack[$stackPos-(10-9)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); - }, - 178 => function ($stackPos) { - $this->semValue = new Stmt\Class_($this->semStack[$stackPos-(7-2)], ['type' => $this->semStack[$stackPos-(7-1)], 'extends' => $this->semStack[$stackPos-(7-3)], 'implements' => $this->semStack[$stackPos-(7-4)], 'stmts' => $this->semStack[$stackPos-(7-6)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); - $this->checkClass($this->semValue, $stackPos-(7-2)); - }, - 179 => function ($stackPos) { - $this->semValue = new Stmt\Interface_($this->semStack[$stackPos-(6-2)], ['extends' => $this->semStack[$stackPos-(6-3)], 'stmts' => $this->semStack[$stackPos-(6-5)]], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); - $this->checkInterface($this->semValue, $stackPos-(6-2)); - }, - 180 => function ($stackPos) { - $this->semValue = new Stmt\Trait_($this->semStack[$stackPos-(5-2)], ['stmts' => $this->semStack[$stackPos-(5-4)]], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); - }, - 181 => function ($stackPos) { - $this->semValue = 0; - }, - 182 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; - }, - 183 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_FINAL; - }, - 184 => function ($stackPos) { - $this->semValue = null; - }, - 185 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-2)]; - }, - 186 => function ($stackPos) { - $this->semValue = array(); - }, - 187 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-2)]; - }, - 188 => function ($stackPos) { - $this->semValue = array(); - }, - 189 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-2)]; - }, - 190 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 191 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 192 => function ($stackPos) { - $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); - }, - 193 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(4-2)]; - }, - 194 => function ($stackPos) { - $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); - }, - 195 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(4-2)]; - }, - 196 => function ($stackPos) { - $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); - }, - 197 => function ($stackPos) { - $this->semValue = null; - }, - 198 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(4-2)]; - }, - 199 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 200 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 201 => function ($stackPos) { - $this->semValue = new Stmt\DeclareDeclare($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 202 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 203 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(4-3)]; - }, - 204 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(4-2)]; - }, - 205 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(5-3)]; - }, - 206 => function ($stackPos) { - $this->semValue = array(); - }, - 207 => function ($stackPos) { - $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 208 => function ($stackPos) { - $this->semValue = new Stmt\Case_($this->semStack[$stackPos-(4-2)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 209 => function ($stackPos) { - $this->semValue = new Stmt\Case_(null, $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 210 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 211 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 212 => function ($stackPos) { - $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); - }, - 213 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(4-2)]; - }, - 214 => function ($stackPos) { - $this->semValue = array(); - }, - 215 => function ($stackPos) { - $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 216 => function ($stackPos) { - $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos-(3-2)], is_array($this->semStack[$stackPos-(3-3)]) ? $this->semStack[$stackPos-(3-3)] : array($this->semStack[$stackPos-(3-3)]), $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 217 => function ($stackPos) { - $this->semValue = array(); - }, - 218 => function ($stackPos) { - $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 219 => function ($stackPos) { - $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos-(4-2)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 220 => function ($stackPos) { - $this->semValue = null; - }, - 221 => function ($stackPos) { - $this->semValue = new Stmt\Else_(is_array($this->semStack[$stackPos-(2-2)]) ? $this->semStack[$stackPos-(2-2)] : array($this->semStack[$stackPos-(2-2)]), $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 222 => function ($stackPos) { - $this->semValue = null; - }, - 223 => function ($stackPos) { - $this->semValue = new Stmt\Else_($this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 224 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)], false); - }, - 225 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(2-2)], true); - }, - 226 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)], false); - }, - 227 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 228 => function ($stackPos) { - $this->semValue = array(); - }, - 229 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 230 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 231 => function ($stackPos) { - $this->semValue = new Node\Param($this->semStack[$stackPos-(4-4)], null, $this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-2)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); $this->checkParam($this->semValue); - }, - 232 => function ($stackPos) { - $this->semValue = new Node\Param($this->semStack[$stackPos-(6-4)], $this->semStack[$stackPos-(6-6)], $this->semStack[$stackPos-(6-1)], $this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-3)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); $this->checkParam($this->semValue); - }, - 233 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 234 => function ($stackPos) { - $this->semValue = new Node\Identifier('array', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 235 => function ($stackPos) { - $this->semValue = new Node\Identifier('callable', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 236 => function ($stackPos) { - $this->semValue = null; - }, - 237 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 238 => function ($stackPos) { - $this->semValue = null; - }, - 239 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-2)]; - }, - 240 => function ($stackPos) { - $this->semValue = array(); - }, - 241 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 242 => function ($stackPos) { - $this->semValue = array(new Node\Arg($this->semStack[$stackPos-(3-2)], false, false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes)); - }, - 243 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 244 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 245 => function ($stackPos) { - $this->semValue = new Node\Arg($this->semStack[$stackPos-(1-1)], false, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 246 => function ($stackPos) { - $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], true, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 247 => function ($stackPos) { - $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], false, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 248 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 249 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 250 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 251 => function ($stackPos) { - $this->semValue = new Expr\Variable($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 252 => function ($stackPos) { - $this->semValue = new Expr\Variable($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 253 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 254 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 255 => function ($stackPos) { - $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 256 => function ($stackPos) { - $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 257 => function ($stackPos) { - if ($this->semStack[$stackPos-(2-2)] !== null) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; } - }, - 258 => function ($stackPos) { - $this->semValue = array(); - }, - 259 => function ($stackPos) { - $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; - if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 260 => function ($stackPos) { - $this->semValue = new Stmt\Property($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkProperty($this->semValue, $stackPos-(3-1)); - }, - 261 => function ($stackPos) { - $this->semValue = new Stmt\ClassConst($this->semStack[$stackPos-(3-2)], 0, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 262 => function ($stackPos) { - $this->semValue = new Stmt\ClassMethod($this->semStack[$stackPos-(9-4)], ['type' => $this->semStack[$stackPos-(9-1)], 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-6)], 'returnType' => $this->semStack[$stackPos-(9-8)], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); - $this->checkClassMethod($this->semValue, $stackPos-(9-1)); - }, - 263 => function ($stackPos) { - $this->semValue = new Stmt\TraitUse($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 264 => function ($stackPos) { - $this->semValue = array(); - }, - 265 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 266 => function ($stackPos) { - $this->semValue = array(); - }, - 267 => function ($stackPos) { - $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 268 => function ($stackPos) { - $this->semValue = new Stmt\TraitUseAdaptation\Precedence($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 269 => function ($stackPos) { - $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(5-1)][0], $this->semStack[$stackPos-(5-1)][1], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); - }, - 270 => function ($stackPos) { - $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], $this->semStack[$stackPos-(4-3)], null, $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 271 => function ($stackPos) { - $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 272 => function ($stackPos) { - $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 273 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); - }, - 274 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 275 => function ($stackPos) { - $this->semValue = array(null, $this->semStack[$stackPos-(1-1)]); - }, - 276 => function ($stackPos) { - $this->semValue = null; - }, - 277 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 278 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 279 => function ($stackPos) { - $this->semValue = 0; - }, - 280 => function ($stackPos) { - $this->semValue = 0; - }, - 281 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 282 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 283 => function ($stackPos) { - $this->checkModifier($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $this->semValue = $this->semStack[$stackPos-(2-1)] | $this->semStack[$stackPos-(2-2)]; - }, - 284 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_PUBLIC; - }, - 285 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_PROTECTED; - }, - 286 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_PRIVATE; - }, - 287 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_STATIC; - }, - 288 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; - }, - 289 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_FINAL; - }, - 290 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 291 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 292 => function ($stackPos) { - $this->semValue = new Node\VarLikeIdentifier(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 293 => function ($stackPos) { - $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 294 => function ($stackPos) { - $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 295 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 296 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 297 => function ($stackPos) { - $this->semValue = array(); - }, - 298 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 299 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 300 => function ($stackPos) { - $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 301 => function ($stackPos) { - $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 302 => function ($stackPos) { - $this->semValue = new Expr\AssignRef($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 303 => function ($stackPos) { - $this->semValue = new Expr\AssignRef($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 304 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 305 => function ($stackPos) { - $this->semValue = new Expr\Clone_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 306 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 307 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 308 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 309 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 310 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 311 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 312 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 313 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 314 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 315 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 316 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 317 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 318 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\Coalesce($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 319 => function ($stackPos) { - $this->semValue = new Expr\PostInc($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 320 => function ($stackPos) { - $this->semValue = new Expr\PreInc($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 321 => function ($stackPos) { - $this->semValue = new Expr\PostDec($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 322 => function ($stackPos) { - $this->semValue = new Expr\PreDec($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 323 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 324 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 325 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 326 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 327 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 328 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 329 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 330 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 331 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 332 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 333 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 334 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 335 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 336 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 337 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 338 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 339 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 340 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 341 => function ($stackPos) { - $this->semValue = new Expr\UnaryPlus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 342 => function ($stackPos) { - $this->semValue = new Expr\UnaryMinus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 343 => function ($stackPos) { - $this->semValue = new Expr\BooleanNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 344 => function ($stackPos) { - $this->semValue = new Expr\BitwiseNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 345 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 346 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 347 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 348 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 349 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Spaceship($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 350 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 351 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 352 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 353 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 354 => function ($stackPos) { - $this->semValue = new Expr\Instanceof_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 355 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 356 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 357 => function ($stackPos) { - $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(5-1)], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); - }, - 358 => function ($stackPos) { - $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(4-1)], null, $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 359 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Coalesce($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 360 => function ($stackPos) { - $this->semValue = new Expr\Isset_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 361 => function ($stackPos) { - $this->semValue = new Expr\Empty_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 362 => function ($stackPos) { - $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 363 => function ($stackPos) { - $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 364 => function ($stackPos) { - $this->semValue = new Expr\Eval_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 365 => function ($stackPos) { - $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 366 => function ($stackPos) { - $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 367 => function ($stackPos) { - $this->semValue = new Expr\Cast\Int_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 368 => function ($stackPos) { - $attrs = $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes; - $attrs['kind'] = $this->getFloatCastKind($this->semStack[$stackPos-(2-1)]); - $this->semValue = new Expr\Cast\Double($this->semStack[$stackPos-(2-2)], $attrs); - }, - 369 => function ($stackPos) { - $this->semValue = new Expr\Cast\String_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 370 => function ($stackPos) { - $this->semValue = new Expr\Cast\Array_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 371 => function ($stackPos) { - $this->semValue = new Expr\Cast\Object_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 372 => function ($stackPos) { - $this->semValue = new Expr\Cast\Bool_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 373 => function ($stackPos) { - $this->semValue = new Expr\Cast\Unset_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 374 => function ($stackPos) { - $attrs = $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes; - $attrs['kind'] = strtolower($this->semStack[$stackPos-(2-1)]) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE; - $this->semValue = new Expr\Exit_($this->semStack[$stackPos-(2-2)], $attrs); - }, - 375 => function ($stackPos) { - $this->semValue = new Expr\ErrorSuppress($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 376 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 377 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 378 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 379 => function ($stackPos) { - $this->semValue = new Expr\ShellExec($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 380 => function ($stackPos) { - $this->semValue = new Expr\Print_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 381 => function ($stackPos) { - $this->semValue = new Expr\Yield_(null, null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 382 => function ($stackPos) { - $this->semValue = new Expr\YieldFrom($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 383 => function ($stackPos) { - $this->semValue = new Expr\Closure(['static' => false, 'byRef' => $this->semStack[$stackPos-(10-2)], 'params' => $this->semStack[$stackPos-(10-4)], 'uses' => $this->semStack[$stackPos-(10-6)], 'returnType' => $this->semStack[$stackPos-(10-7)], 'stmts' => $this->semStack[$stackPos-(10-9)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); - }, - 384 => function ($stackPos) { - $this->semValue = new Expr\Closure(['static' => true, 'byRef' => $this->semStack[$stackPos-(11-3)], 'params' => $this->semStack[$stackPos-(11-5)], 'uses' => $this->semStack[$stackPos-(11-7)], 'returnType' => $this->semStack[$stackPos-(11-8)], 'stmts' => $this->semStack[$stackPos-(11-10)]], $this->startAttributeStack[$stackPos-(11-1)] + $this->endAttributes); - }, - 385 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 386 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 387 => function ($stackPos) { - $this->semValue = new Expr\Yield_($this->semStack[$stackPos-(2-2)], null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 388 => function ($stackPos) { - $this->semValue = new Expr\Yield_($this->semStack[$stackPos-(4-4)], $this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 389 => function ($stackPos) { - $attrs = $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_LONG; - $this->semValue = new Expr\Array_($this->semStack[$stackPos-(4-3)], $attrs); - }, - 390 => function ($stackPos) { - $attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_SHORT; - $this->semValue = new Expr\Array_($this->semStack[$stackPos-(3-2)], $attrs); - }, - 391 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 392 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch(Scalar\String_::fromString($this->semStack[$stackPos-(4-1)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes), $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 393 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 394 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 395 => function ($stackPos) { - $this->semValue = array(new Stmt\Class_(null, ['type' => 0, 'extends' => $this->semStack[$stackPos-(7-3)], 'implements' => $this->semStack[$stackPos-(7-4)], 'stmts' => $this->semStack[$stackPos-(7-6)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes), $this->semStack[$stackPos-(7-2)]); - $this->checkClass($this->semValue[0], -1); - }, - 396 => function ($stackPos) { - $this->semValue = new Expr\New_($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 397 => function ($stackPos) { - list($class, $ctorArgs) = $this->semStack[$stackPos-(2-2)]; $this->semValue = new Expr\New_($class, $ctorArgs, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 398 => function ($stackPos) { - $this->semValue = array(); - }, - 399 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(4-3)]; - }, - 400 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 401 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 402 => function ($stackPos) { - $this->semValue = new Expr\ClosureUse($this->semStack[$stackPos-(2-2)], $this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 403 => function ($stackPos) { - $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 404 => function ($stackPos) { - $this->semValue = new Expr\StaticCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 405 => function ($stackPos) { - $this->semValue = new Expr\StaticCall($this->semStack[$stackPos-(6-1)], $this->semStack[$stackPos-(6-4)], $this->semStack[$stackPos-(6-6)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); - }, - 406 => function ($stackPos) { - $this->semValue = $this->fixupPhp5StaticPropCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 407 => function ($stackPos) { - $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 408 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 409 => function ($stackPos) { - $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 410 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 411 => function ($stackPos) { - $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 412 => function ($stackPos) { - $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 413 => function ($stackPos) { - $this->semValue = new Name\FullyQualified(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 414 => function ($stackPos) { - $this->semValue = new Name\Relative(substr($this->semStack[$stackPos-(1-1)], 10), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 415 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 416 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 417 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 418 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 419 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 420 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 421 => function ($stackPos) { - $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 422 => function ($stackPos) { - $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 423 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 424 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 425 => function ($stackPos) { - $this->semValue = null; - }, - 426 => function ($stackPos) { - $this->semValue = null; - }, - 427 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 428 => function ($stackPos) { - $this->semValue = array(); - }, - 429 => function ($stackPos) { - $this->semValue = array(new Scalar\EncapsedStringPart(Scalar\String_::parseEscapeSequences($this->semStack[$stackPos-(1-1)], '`', false), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes)); - }, - 430 => function ($stackPos) { - foreach ($this->semStack[$stackPos-(1-1)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '`', false); } }; $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 431 => function ($stackPos) { - $this->semValue = array(); - }, - 432 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 433 => function ($stackPos) { - $this->semValue = $this->parseLNumber($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes, true); - }, - 434 => function ($stackPos) { - $this->semValue = Scalar\DNumber::fromString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 435 => function ($stackPos) { - $this->semValue = Scalar\String_::fromString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes, false); - }, - 436 => function ($stackPos) { - $this->semValue = new Scalar\MagicConst\Line($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 437 => function ($stackPos) { - $this->semValue = new Scalar\MagicConst\File($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 438 => function ($stackPos) { - $this->semValue = new Scalar\MagicConst\Dir($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 439 => function ($stackPos) { - $this->semValue = new Scalar\MagicConst\Class_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 440 => function ($stackPos) { - $this->semValue = new Scalar\MagicConst\Trait_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 441 => function ($stackPos) { - $this->semValue = new Scalar\MagicConst\Method($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 442 => function ($stackPos) { - $this->semValue = new Scalar\MagicConst\Function_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 443 => function ($stackPos) { - $this->semValue = new Scalar\MagicConst\Namespace_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 444 => function ($stackPos) { - $this->semValue = $this->parseDocString($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)], false); - }, - 445 => function ($stackPos) { - $this->semValue = $this->parseDocString($this->semStack[$stackPos-(2-1)], '', $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(2-2)] + $this->endAttributeStack[$stackPos-(2-2)], false); - }, - 446 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 447 => function ($stackPos) { - $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 448 => function ($stackPos) { - $this->semValue = new Expr\ConstFetch($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 449 => function ($stackPos) { - $this->semValue = new Expr\Array_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 450 => function ($stackPos) { - $this->semValue = new Expr\Array_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 451 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 452 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 453 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 454 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 455 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 456 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 457 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 458 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 459 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 460 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 461 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 462 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 463 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 464 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 465 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 466 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 467 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 468 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 469 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 470 => function ($stackPos) { - $this->semValue = new Expr\UnaryPlus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 471 => function ($stackPos) { - $this->semValue = new Expr\UnaryMinus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 472 => function ($stackPos) { - $this->semValue = new Expr\BooleanNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 473 => function ($stackPos) { - $this->semValue = new Expr\BitwiseNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 474 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 475 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 476 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 477 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 478 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 479 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 480 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 481 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 482 => function ($stackPos) { - $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(5-1)], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); - }, - 483 => function ($stackPos) { - $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(4-1)], null, $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 484 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 485 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 486 => function ($stackPos) { - $this->semValue = new Expr\ConstFetch($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 487 => function ($stackPos) { - $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 488 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 489 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 490 => function ($stackPos) { - $attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED; - foreach ($this->semStack[$stackPos-(3-2)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '"', true); } }; $this->semValue = new Scalar\Encapsed($this->semStack[$stackPos-(3-2)], $attrs); - }, - 491 => function ($stackPos) { - $this->semValue = $this->parseDocString($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)], true); - }, - 492 => function ($stackPos) { - $this->semValue = array(); - }, - 493 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 494 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 495 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 496 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 497 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 498 => function ($stackPos) { - $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 499 => function ($stackPos) { - $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 500 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 501 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 502 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 503 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 504 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-5)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); - }, - 505 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 506 => function ($stackPos) { - $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 507 => function ($stackPos) { - $this->semValue = new Expr\MethodCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 508 => function ($stackPos) { - $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 509 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 510 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 511 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 512 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 513 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 514 => function ($stackPos) { - $this->semValue = new Expr\Variable($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 515 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 516 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 517 => function ($stackPos) { - $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 518 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 519 => function ($stackPos) { - $var = substr($this->semStack[$stackPos-(1-1)], 1); $this->semValue = \is_string($var) ? new Node\VarLikeIdentifier($var, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes) : $var; - }, - 520 => function ($stackPos) { - $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 521 => function ($stackPos) { - $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(6-1)], $this->semStack[$stackPos-(6-5)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); - }, - 522 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 523 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 524 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 525 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 526 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 527 => function ($stackPos) { - $this->semValue = new Expr\Variable($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 528 => function ($stackPos) { - $this->semValue = null; - }, - 529 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 530 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 531 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 532 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 533 => function ($stackPos) { - $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2; - }, - 534 => function ($stackPos) { - $this->semValue = new Expr\List_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 535 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 536 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 537 => function ($stackPos) { - $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 538 => function ($stackPos) { - $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 539 => function ($stackPos) { - $this->semValue = null; - }, - 540 => function ($stackPos) { - $this->semValue = array(); - }, - 541 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 542 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 543 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 544 => function ($stackPos) { - $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 545 => function ($stackPos) { - $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 546 => function ($stackPos) { - $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(4-4)], $this->semStack[$stackPos-(4-1)], true, $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 547 => function ($stackPos) { - $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 548 => function ($stackPos) { - $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 549 => function ($stackPos) { - $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 550 => function ($stackPos) { - $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 551 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 552 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); - }, - 553 => function ($stackPos) { - $this->semValue = new Scalar\EncapsedStringPart($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 554 => function ($stackPos) { - $this->semValue = new Expr\Variable($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 555 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 556 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 557 => function ($stackPos) { - $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 558 => function ($stackPos) { - $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 559 => function ($stackPos) { - $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 560 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-4)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); - }, - 561 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 562 => function ($stackPos) { - $this->semValue = new Scalar\String_($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 563 => function ($stackPos) { - $this->semValue = $this->parseNumString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 564 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - ]; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Parser/Php7.php b/lib/nikic/php-parser/lib/PhpParser/Parser/Php7.php deleted file mode 100644 index 71ba0187e..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Parser/Php7.php +++ /dev/null @@ -1,2829 +0,0 @@ -<?php - -namespace PhpParser\Parser; - -use PhpParser\Error; -use PhpParser\Node; -use PhpParser\Node\Expr; -use PhpParser\Node\Name; -use PhpParser\Node\Scalar; -use PhpParser\Node\Stmt; - -/* This is an automatically GENERATED file, which should not be manually edited. - * Instead edit one of the following: - * * the grammar files grammar/php5.y or grammar/php7.y - * * the skeleton file grammar/parser.template - * * the preprocessing script grammar/rebuildParsers.php - */ -class Php7 extends \PhpParser\ParserAbstract -{ - protected $tokenToSymbolMapSize = 396; - protected $actionTableSize = 1189; - protected $gotoTableSize = 611; - - protected $invalidSymbol = 168; - protected $errorSymbol = 1; - protected $defaultAction = -32766; - protected $unexpectedTokenRule = 32767; - - protected $YY2TBLSTATE = 421; - protected $numNonLeafStates = 709; - - protected $symbolToName = array( - "EOF", - "error", - "T_THROW", - "T_INCLUDE", - "T_INCLUDE_ONCE", - "T_EVAL", - "T_REQUIRE", - "T_REQUIRE_ONCE", - "','", - "T_LOGICAL_OR", - "T_LOGICAL_XOR", - "T_LOGICAL_AND", - "T_PRINT", - "T_YIELD", - "T_DOUBLE_ARROW", - "T_YIELD_FROM", - "'='", - "T_PLUS_EQUAL", - "T_MINUS_EQUAL", - "T_MUL_EQUAL", - "T_DIV_EQUAL", - "T_CONCAT_EQUAL", - "T_MOD_EQUAL", - "T_AND_EQUAL", - "T_OR_EQUAL", - "T_XOR_EQUAL", - "T_SL_EQUAL", - "T_SR_EQUAL", - "T_POW_EQUAL", - "T_COALESCE_EQUAL", - "'?'", - "':'", - "T_COALESCE", - "T_BOOLEAN_OR", - "T_BOOLEAN_AND", - "'|'", - "'^'", - "T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG", - "T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG", - "T_IS_EQUAL", - "T_IS_NOT_EQUAL", - "T_IS_IDENTICAL", - "T_IS_NOT_IDENTICAL", - "T_SPACESHIP", - "'<'", - "T_IS_SMALLER_OR_EQUAL", - "'>'", - "T_IS_GREATER_OR_EQUAL", - "T_SL", - "T_SR", - "'+'", - "'-'", - "'.'", - "'*'", - "'/'", - "'%'", - "'!'", - "T_INSTANCEOF", - "'~'", - "T_INC", - "T_DEC", - "T_INT_CAST", - "T_DOUBLE_CAST", - "T_STRING_CAST", - "T_ARRAY_CAST", - "T_OBJECT_CAST", - "T_BOOL_CAST", - "T_UNSET_CAST", - "'@'", - "T_POW", - "'['", - "T_NEW", - "T_CLONE", - "T_EXIT", - "T_IF", - "T_ELSEIF", - "T_ELSE", - "T_ENDIF", - "T_LNUMBER", - "T_DNUMBER", - "T_STRING", - "T_STRING_VARNAME", - "T_VARIABLE", - "T_NUM_STRING", - "T_INLINE_HTML", - "T_ENCAPSED_AND_WHITESPACE", - "T_CONSTANT_ENCAPSED_STRING", - "T_ECHO", - "T_DO", - "T_WHILE", - "T_ENDWHILE", - "T_FOR", - "T_ENDFOR", - "T_FOREACH", - "T_ENDFOREACH", - "T_DECLARE", - "T_ENDDECLARE", - "T_AS", - "T_SWITCH", - "T_MATCH", - "T_ENDSWITCH", - "T_CASE", - "T_DEFAULT", - "T_BREAK", - "T_CONTINUE", - "T_GOTO", - "T_FUNCTION", - "T_FN", - "T_CONST", - "T_RETURN", - "T_TRY", - "T_CATCH", - "T_FINALLY", - "T_USE", - "T_INSTEADOF", - "T_GLOBAL", - "T_STATIC", - "T_ABSTRACT", - "T_FINAL", - "T_PRIVATE", - "T_PROTECTED", - "T_PUBLIC", - "T_READONLY", - "T_VAR", - "T_UNSET", - "T_ISSET", - "T_EMPTY", - "T_HALT_COMPILER", - "T_CLASS", - "T_TRAIT", - "T_INTERFACE", - "T_ENUM", - "T_EXTENDS", - "T_IMPLEMENTS", - "T_OBJECT_OPERATOR", - "T_NULLSAFE_OBJECT_OPERATOR", - "T_LIST", - "T_ARRAY", - "T_CALLABLE", - "T_CLASS_C", - "T_TRAIT_C", - "T_METHOD_C", - "T_FUNC_C", - "T_LINE", - "T_FILE", - "T_START_HEREDOC", - "T_END_HEREDOC", - "T_DOLLAR_OPEN_CURLY_BRACES", - "T_CURLY_OPEN", - "T_PAAMAYIM_NEKUDOTAYIM", - "T_NAMESPACE", - "T_NS_C", - "T_DIR", - "T_NS_SEPARATOR", - "T_ELLIPSIS", - "T_NAME_FULLY_QUALIFIED", - "T_NAME_QUALIFIED", - "T_NAME_RELATIVE", - "T_ATTRIBUTE", - "';'", - "']'", - "'{'", - "'}'", - "'('", - "')'", - "'`'", - "'\"'", - "'$'" - ); - - protected $tokenToSymbol = array( - 0, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 56, 166, 168, 167, 55, 168, 168, - 163, 164, 53, 50, 8, 51, 52, 54, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 31, 159, - 44, 16, 46, 30, 68, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 70, 168, 160, 36, 168, 165, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 161, 35, 162, 58, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 1, 2, 3, 4, - 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 32, 33, 34, 37, 38, 39, 40, - 41, 42, 43, 45, 47, 48, 49, 57, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 69, 71, 72, - 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, - 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, - 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, - 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, - 153, 154, 155, 156, 157, 158 - ); - - protected $action = array( - 132, 133, 134, 568, 135, 136, 0, 721, 722, 723, - 137, 37, 921, 448, 449, 450,-32766,-32766,-32766,-32767, - -32767,-32767,-32767, 101, 102, 103, 104, 105, 1071, 1072, - 1073, 1070, 1069, 1068, 1074, 715, 714,-32766,-32766,-32766, - -32766,-32766,-32766,-32766,-32766,-32766,-32767,-32767,-32767,-32767, - -32767, 371, 372, 240, 2, 724,-32766,-32766,-32766, 1001, - 1002, 415, 956,-32766,-32766,-32766, 373, 372, 12, 267, - 138, 397, 728, 729, 730, 731, 415,-32766, 421,-32766, - -32766,-32766,-32766,-32766,-32766, 732, 733, 734, 735, 736, - 737, 738, 739, 740, 741, 742, 762, 569, 763, 764, - 765, 766, 754, 755, 337, 338, 757, 758, 743, 744, - 745, 747, 748, 749, 347, 789, 790, 791, 792, 793, - 794, 750, 751, 570, 571, 783, 774, 772, 773, 786, - 769, 770, 284, 421, 572, 573, 768, 574, 575, 576, - 577, 578, 579, 597, -579,-32766,-32766, 797, 771, 580, - 581, -579, 139,-32766,-32766,-32766, 132, 133, 134, 568, - 135, 136, 1020, 721, 722, 723, 137, 37,-32766,-32766, - -32766, 542, 1306, 126,-32766, 1307,-32766,-32766,-32766,-32766, - -32766,-32766,-32766, 1071, 1072, 1073, 1070, 1069, 1068, 1074, - 957, 715, 714, -318, 993, 1261,-32766,-32766,-32766, -576, - 106, 107, 108, -268, 270, 890, -576, 910, 1196, 1195, - 1197, 724,-32766,-32766,-32766, 1049, 109,-32766,-32766,-32766, - -32766, 989, 988, 987, 990, 267, 138, 397, 728, 729, - 730, 731, 1233,-32766, 421,-32766,-32766,-32766,-32766, 1001, - 1002, 732, 733, 734, 735, 736, 737, 738, 739, 740, - 741, 742, 762, 569, 763, 764, 765, 766, 754, 755, - 337, 338, 757, 758, 743, 744, 745, 747, 748, 749, - 347, 789, 790, 791, 792, 793, 794, 750, 751, 570, - 571, 783, 774, 772, 773, 786, 769, 770, 880, 321, - 572, 573, 768, 574, 575, 576, 577, 578, 579,-32766, - 82, 83, 84, -579, 771, 580, 581, -579, 148, 746, - 716, 717, 718, 719, 720, 1281, 721, 722, 723, 759, - 760, 36, 1280, 85, 86, 87, 88, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 999, 270, -318, - -32766,-32766,-32766, 456, 457, 81, -193, 808, -576, 1019, - 109, 320, -576, 892, 724, 681, 802, 695, 1001, 1002, - 591,-32766, 1047,-32766,-32766,-32766, 715, 714, 725, 726, - 727, 728, 729, 730, 731, -192, -86, 795, 279, -530, - 284,-32766,-32766,-32766, 732, 733, 734, 735, 736, 737, - 738, 739, 740, 741, 742, 762, 785, 763, 764, 765, - 766, 754, 755, 756, 784, 757, 758, 743, 744, 745, - 747, 748, 749, 788, 789, 790, 791, 792, 793, 794, - 750, 751, 752, 753, 783, 774, 772, 773, 786, 769, - 770, 470, 803, 761, 767, 768, 775, 776, 778, 777, - 779, 780, -86, -530, -530, 637, 25, 771, 782, 781, - 49, 50, 51, 501, 52, 53, 239, 34, -530, 890, - 54, 55, -111, 56, 999, 128,-32766, -111, 1201, -111, - -530, -570, -536, 890, 300, -570, 144, -111, -111, -111, - -111, -111, -111, -111, -111, 1001, 1002, 1001, 1002, 686, - 1201, 925, 926, 1194, 806, 890, 927, 1296, 57, 58, - 799, 253, -193, 687, 59, 807, 60, 246, 247, 61, - 62, 63, 64, 65, 66, 67, 68, 304, 27, 268, - 69, 437, 502, -332, 306, 688, 1227, 1228, 503, 1192, - 806, -192, 318, 890, 1225, 41, 24, 504, 334, 505, - 14, 506, 880, 507, 653, 654, 508, 509, 280, 806, - 281, 43, 44, 438, 368, 367, 880, 45, 510, 35, - 249, 471, 1063, 359, 333, 103, 104, 105, 1196, 1195, - 1197, 806, 511, 512, 513, 335, 801, 1221, 880, 361, - 285, 683, 286, 365, 514, 515, 380, 1215, 1216, 1217, - 1218, 1212, 1213, 292, 433, -111, 715, 714, 434, 1219, - 1214, 149, 400, 1196, 1195, 1197, 293, -153, -153, -153, - -356, 70, -356, 316, 317, 320, 880, 892, -531, 681, - 435, 1048, -153, 707, -153, 293, -153, 1277, -153, 27, - 74, 892, 436, 681, 320, 369, 370, 833, 366, 834, - -529, 806, 382, 812, 11, 1225, 833, 150, 834, -111, - -111, 151, 74, 942, -111, 681, 320, 153, 806, 866, - -111, -111, -111, -111, 31, 110, 111, 112, 113, 114, - 115, 116, 117, 118, 119, 120, 121, 122, 715, 714, - 374, 375, -531, -531, 890, 154, 805, 155, -4, 890, - 157, 892, -88, 681, -153, 514, 515, -531, 1215, 1216, - 1217, 1218, 1212, 1213, -529, -529, 797, 1108, 1110, -531, - 1219, 1214, 715, 714, 690,-32766, 629, 630, -528, -529, - 32, 1194, 72, 123, 124, 317, 320, 129,-32766,-32766, - -32766, -529,-32766, -535,-32766, 130,-32766, 140, 143,-32766, - 158, 159, 160, 320,-32766,-32766,-32766, 161, -528,-32766, - -32766,-32766, -79, 282, -75, 1194,-32766, 412, -73, 27, - -72, -71,-32766,-32766,-32766,-32766,-32766, 880,-32766, 287, - -32766, 806, 880,-32766, -70, 1225, -69, -68,-32766,-32766, - -32766, -67, -528, -528,-32766,-32766, -66, 141, -47, -18, - -32766, 412, 147, 320, 366, 73, 428, -528, 271,-32766, - 278, 291, -51, 696, 699, -111, -111, 1201, -533, -528, - -111, 889, -528, -528, 48, 825, -111, -111, -111, -111, - 146, 327, 283, 270, 288, 109, 515, -528, 1215, 1216, - 1217, 1218, 1212, 1213, 131, 906, 661, -16, 9, -528, - 1219, 1214, 892, 797, 681,-32766, 145, 892, 1308, 681, - -4, 1194, 72,-32766, 638, 317, 320, 806,-32766,-32766, - -32766, 1078,-32766, 544,-32766, 627,-32766, 13, 656,-32766, - 548, 298, -533, -533,-32766,-32766,-32766,-32766, 296, 297, - -32766,-32766, 674, 1194, 643, 890,-32766, 412, 806, 453, - -32766,-32766,-32766, 364,-32766,-32766,-32766, 481,-32766, -533, - -32766,-32766, 47, -494, 890, 127,-32766,-32766,-32766,-32766, - 644, 657,-32766,-32766, 305, 1194, 890, 805,-32766, 412, - 1222, 301,-32766,-32766,-32766, 0,-32766,-32766,-32766, 432, - -32766, 299, 922,-32766, -111, 293, 554, 476,-32766,-32766, - -32766,-32766, 1232, -484,-32766,-32766, 697, 1194, 560, 908, - -32766, 412, 595, 817,-32766,-32766,-32766, 7,-32766,-32766, - -32766, 1234,-32766, 16, 293,-32766, 294, 295, 880, 74, - -32766,-32766,-32766, 320, 363, 39,-32766,-32766, 40, 704, - 705, 871,-32766, 412, -246, -246, -246, 880, 966, 943, - 366,-32766, 950, 125, 1247, 940, 951, 869, 938, 880, - 1052, -111, -111, -245, -245, -245, -111, 1055, 1056, 366, - 1053, 866, -111, -111, -111, -111, 1054, 1060, 701, 1265, - -111, -111, 1299, 632, -564, -111, 33, 315, -271, 362, - 866, -111, -111, -111, -111, 682, 685, 689, 691, 692, - 693, 694,-32766, 892, 698, 681, -246, 684, 1194, 867, - 1303, 1305, 828, 827, 836,-32766,-32766,-32766, 915,-32766, - 958,-32766, 892,-32766, 681, -245,-32766, 835, 1304, 914, - 916,-32766,-32766,-32766, 892, 913, 681,-32766,-32766, 1180, - 899, 909, 897,-32766, 412, 948, 949, 1302, 1259, 1248, - 1266, 1272,-32766, 1275, -269, -562, -536, -535, -534, 1, - 28, 29, 38, 42, 46, 71, 75, 76, 77, 78, - 79, 80, 142, 152, 156, 245, 322, 348, 349, 350, - 351, 352, 353, 354, 355, 356, 357, 358, 360, 429, - 0, -268, 0, 18, 19, 20, 21, 23, 399, 472, - 473, 480, 483, 484, 485, 486, 490, 491, 492, 499, - 668, 1205, 1148, 1223, 1022, 1021, 1184, -273, -103, 17, - 22, 26, 290, 398, 588, 592, 619, 673, 1152, 1200, - 1149, 1278, 0, -498, 1165, 0, 1226, 0, 320 - ); - - protected $actionCheck = array( - 2, 3, 4, 5, 6, 7, 0, 9, 10, 11, - 12, 13, 128, 129, 130, 131, 9, 10, 11, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 116, 117, - 118, 119, 120, 121, 122, 37, 38, 30, 116, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 106, 107, 14, 8, 57, 9, 10, 11, 137, - 138, 116, 31, 9, 10, 11, 106, 107, 8, 71, - 72, 73, 74, 75, 76, 77, 116, 30, 80, 32, - 33, 34, 35, 36, 30, 87, 88, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 30, 80, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 51, 1, 9, 10, 80, 150, 151, - 152, 8, 154, 9, 10, 11, 2, 3, 4, 5, - 6, 7, 164, 9, 10, 11, 12, 13, 9, 10, - 11, 85, 80, 14, 30, 83, 32, 33, 34, 35, - 36, 37, 38, 116, 117, 118, 119, 120, 121, 122, - 159, 37, 38, 8, 1, 1, 9, 10, 11, 1, - 53, 54, 55, 164, 57, 1, 8, 1, 155, 156, - 157, 57, 9, 10, 11, 162, 69, 30, 116, 32, - 33, 119, 120, 121, 122, 71, 72, 73, 74, 75, - 76, 77, 146, 30, 80, 32, 33, 34, 35, 137, - 138, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, - 126, 127, 128, 129, 130, 131, 132, 133, 84, 70, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 9, - 9, 10, 11, 160, 150, 151, 152, 164, 154, 2, - 3, 4, 5, 6, 7, 1, 9, 10, 11, 12, - 13, 30, 8, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 116, 57, 164, - 9, 10, 11, 134, 135, 161, 8, 1, 160, 1, - 69, 167, 164, 159, 57, 161, 80, 161, 137, 138, - 1, 30, 1, 32, 33, 34, 37, 38, 71, 72, - 73, 74, 75, 76, 77, 8, 31, 80, 30, 70, - 30, 9, 10, 11, 87, 88, 89, 90, 91, 92, - 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, - 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 31, 156, 136, 137, 138, 139, 140, 141, 142, - 143, 144, 97, 134, 135, 75, 76, 150, 151, 152, - 2, 3, 4, 5, 6, 7, 97, 8, 149, 1, - 12, 13, 101, 15, 116, 8, 116, 106, 1, 108, - 161, 160, 163, 1, 113, 164, 8, 116, 117, 118, - 119, 120, 121, 122, 123, 137, 138, 137, 138, 31, - 1, 117, 118, 80, 82, 1, 122, 85, 50, 51, - 80, 8, 164, 31, 56, 159, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 68, 8, 70, 71, - 72, 73, 74, 162, 8, 31, 78, 79, 80, 116, - 82, 164, 8, 1, 86, 87, 88, 89, 8, 91, - 101, 93, 84, 95, 75, 76, 98, 99, 35, 82, - 37, 103, 104, 105, 106, 107, 84, 109, 110, 147, - 148, 161, 123, 115, 116, 50, 51, 52, 155, 156, - 157, 82, 124, 125, 126, 8, 156, 1, 84, 8, - 35, 161, 37, 8, 136, 137, 8, 139, 140, 141, - 142, 143, 144, 145, 8, 128, 37, 38, 8, 151, - 152, 101, 102, 155, 156, 157, 158, 75, 76, 77, - 106, 163, 108, 165, 166, 167, 84, 159, 70, 161, - 8, 159, 90, 161, 92, 158, 94, 1, 96, 70, - 163, 159, 8, 161, 167, 106, 107, 106, 106, 108, - 70, 82, 106, 8, 108, 86, 106, 14, 108, 117, - 118, 14, 163, 159, 122, 161, 167, 14, 82, 127, - 128, 129, 130, 131, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 37, 38, - 106, 107, 134, 135, 1, 14, 155, 14, 0, 1, - 14, 159, 31, 161, 162, 136, 137, 149, 139, 140, - 141, 142, 143, 144, 134, 135, 80, 59, 60, 161, - 151, 152, 37, 38, 31, 74, 111, 112, 70, 149, - 14, 80, 163, 16, 16, 166, 167, 16, 87, 88, - 89, 161, 91, 163, 93, 16, 95, 161, 16, 98, - 16, 16, 16, 167, 103, 104, 105, 16, 70, 74, - 109, 110, 31, 35, 31, 80, 115, 116, 31, 70, - 31, 31, 87, 88, 89, 124, 91, 84, 93, 35, - 95, 82, 84, 98, 31, 86, 31, 31, 103, 104, - 105, 31, 134, 135, 109, 110, 31, 161, 31, 31, - 115, 116, 31, 167, 106, 154, 108, 149, 31, 124, - 31, 113, 31, 31, 31, 117, 118, 1, 70, 161, - 122, 31, 134, 135, 70, 127, 128, 129, 130, 131, - 31, 35, 37, 57, 37, 69, 137, 149, 139, 140, - 141, 142, 143, 144, 31, 38, 77, 31, 150, 161, - 151, 152, 159, 80, 161, 74, 70, 159, 83, 161, - 162, 80, 163, 85, 90, 166, 167, 82, 87, 88, - 89, 82, 91, 85, 93, 113, 95, 97, 94, 98, - 89, 132, 134, 135, 103, 104, 105, 74, 134, 135, - 109, 110, 92, 80, 96, 1, 115, 116, 82, 97, - 87, 88, 89, 149, 91, 124, 93, 97, 95, 161, - 116, 98, 70, 149, 1, 161, 103, 104, 105, 74, - 100, 100, 109, 110, 132, 80, 1, 155, 115, 116, - 160, 114, 87, 88, 89, -1, 91, 124, 93, 128, - 95, 133, 128, 98, 128, 158, 153, 102, 103, 104, - 105, 74, 146, 149, 109, 110, 31, 80, 81, 154, - 115, 116, 153, 160, 87, 88, 89, 149, 91, 124, - 93, 146, 95, 149, 158, 98, 134, 135, 84, 163, - 103, 104, 105, 167, 149, 159, 109, 110, 159, 159, - 159, 159, 115, 116, 100, 101, 102, 84, 159, 159, - 106, 124, 159, 161, 160, 159, 159, 159, 159, 84, - 159, 117, 118, 100, 101, 102, 122, 159, 159, 106, - 159, 127, 128, 129, 130, 131, 159, 159, 162, 160, - 117, 118, 160, 160, 163, 122, 161, 161, 164, 161, - 127, 128, 129, 130, 131, 161, 161, 161, 161, 161, - 161, 161, 74, 159, 161, 161, 162, 161, 80, 162, - 162, 162, 162, 162, 162, 87, 88, 89, 162, 91, - 162, 93, 159, 95, 161, 162, 98, 162, 162, 162, - 162, 103, 104, 105, 159, 162, 161, 109, 110, 162, - 162, 162, 162, 115, 116, 162, 162, 162, 162, 162, - 162, 162, 124, 162, 164, 163, 163, 163, 163, 163, - 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, - 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, - 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, - -1, 164, -1, 164, 164, 164, 164, 164, 164, 164, - 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, - 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, - 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, - 164, 164, -1, 165, 165, -1, 166, -1, 167 - ); - - protected $actionBase = array( - 0, -2, 154, 542, 698, 894, 913, 586, 53, 430, - 867, 307, 307, 67, 307, 307, 307, 482, 693, 693, - 925, 693, 468, 504, 204, 204, 204, 651, 651, 651, - 651, 685, 685, 845, 845, 877, 813, 781, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 356, 31, 369, 716, 1008, 1014, 1010, 1015, - 1006, 1005, 1009, 1011, 1016, 935, 936, 799, 937, 938, - 939, 941, 1012, 873, 1007, 1013, 291, 291, 291, 291, - 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, - 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, - 291, 291, 290, 159, 136, 382, 382, 382, 382, 382, - 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, - 382, 382, 382, 382, 382, 54, 54, 54, 187, 569, - 569, 341, 203, 658, 47, 699, 699, 699, 699, 699, - 699, 699, 699, 699, 699, 144, 144, 7, 7, 7, - 7, 7, 371, -25, -25, -25, -25, 816, 477, 102, - 499, 358, 449, 514, 525, 525, 360, -116, 231, 231, - 231, 231, 231, 231, -78, -78, -78, -78, -78, 319, - 580, 541, 86, 423, 636, 636, 636, 636, 423, 423, - 423, 423, 825, 1020, 423, 423, 423, 558, 688, 688, - 754, 147, 147, 147, 688, 550, 788, 422, 550, 422, - 194, 92, 794, -55, -40, 321, 814, 794, 748, 842, - 198, 143, 772, 539, 772, 1004, 778, 767, 733, 868, - 896, 1017, 820, 933, 821, 934, 219, 731, 1003, 1003, - 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1021, - 339, 1004, 286, 1021, 1021, 1021, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 615, 286, 380, 479, - 286, 796, 339, 356, 804, 356, 356, 356, 356, 964, - 356, 356, 356, 356, 356, 356, 969, 768, 410, 356, - 31, 206, 206, 472, 193, 206, 206, 206, 206, 356, - 356, 356, 539, 776, 793, 584, 809, 377, 776, 776, - 776, 355, 185, 39, 348, 555, 523, 546, 773, 773, - 789, 946, 946, 773, 785, 773, 789, 951, 773, 946, - 787, 467, 596, 540, 585, 600, 946, 519, 773, 773, - 773, 773, 622, 773, 503, 478, 773, 773, 749, 779, - 792, 46, 946, 946, 946, 792, 581, 808, 808, 808, - 830, 831, 762, 777, 534, 526, 645, 459, 807, 777, - 777, 773, 588, 762, 777, 762, 777, 805, 777, 777, - 777, 762, 777, 785, 577, 777, 734, 634, 60, 777, - 6, 952, 953, 671, 954, 949, 955, 976, 956, 957, - 884, 962, 950, 958, 948, 947, 790, 717, 718, 818, - 764, 945, 766, 766, 766, 943, 766, 766, 766, 766, - 766, 766, 766, 766, 717, 770, 835, 811, 791, 965, - 721, 729, 806, 897, 1018, 1019, 964, 997, 959, 826, - 732, 983, 966, 866, 876, 967, 968, 984, 998, 999, - 898, 786, 899, 900, 803, 970, 885, 766, 952, 957, - 950, 958, 948, 947, 765, 760, 755, 756, 753, 740, - 737, 739, 771, 1000, 942, 871, 844, 969, 944, 717, - 869, 979, 875, 985, 986, 878, 802, 775, 872, 901, - 971, 972, 973, 886, 1001, 829, 980, 874, 987, 810, - 902, 988, 989, 990, 991, 906, 887, 888, 889, 832, - 774, 940, 798, 908, 643, 744, 797, 975, 647, 963, - 890, 915, 916, 992, 993, 994, 917, 960, 839, 981, - 784, 982, 977, 840, 843, 653, 728, 795, 681, 683, - 918, 923, 927, 961, 782, 769, 846, 847, 1002, 928, - 686, 848, 735, 929, 996, 736, 741, 800, 893, 824, - 817, 780, 974, 783, 849, 930, 851, 858, 859, 995, - 861, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 458, 458, 458, 458, 458, 458, 307, 307, 307, 307, - 0, 0, 307, 0, 0, 0, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, - 458, 291, 291, 291, 291, 291, 291, 291, 291, 291, - 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, - 291, 291, 291, 291, 291, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 291, 291, 291, 291, 291, 291, 291, 291, 291, - 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, - 291, 291, 291, 291, 291, 291, 291, 291, 423, 423, - 291, 291, 0, 291, 423, 423, 423, 423, 423, 423, - 423, 423, 423, 423, 291, 291, 291, 291, 291, 291, - 291, 787, 147, 147, 147, 147, 423, 423, 423, 423, - 423, -88, -88, 147, 147, 423, 384, 423, 423, 423, - 423, 423, 423, 423, 423, 423, 423, 423, 0, 0, - 286, 422, 0, 785, 785, 785, 785, 0, 0, 0, - 0, 422, 422, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 286, 422, 0, 286, 0, 785, - 785, 423, 787, 787, 314, 384, 423, 0, 0, 0, - 0, 286, 785, 286, 339, 422, 339, 339, 206, 356, - 314, 510, 510, 510, 510, 0, 539, 787, 787, 787, - 787, 787, 787, 787, 787, 787, 787, 787, 785, 0, - 787, 0, 785, 785, 785, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 785, 0, 0, 946, 0, 0, 0, 0, 773, 0, - 0, 0, 0, 0, 0, 773, 951, 0, 0, 0, - 0, 0, 0, 785, 0, 0, 0, 0, 0, 0, - 0, 0, 766, 802, 0, 802, 0, 766, 766, 766 - ); - - protected $actionDefault = array( - 3,32767, 103,32767,32767,32767,32767,32767,32767,32767, - 32767,32767, 101,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767, 582, 582, 582, - 582,32767,32767, 250, 103,32767,32767, 458, 376, 376, - 376,32767,32767, 526, 526, 526, 526, 526, 526,32767, - 32767,32767,32767,32767,32767, 458,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767, 101,32767, - 32767,32767, 37, 7, 8, 10, 11, 50, 17, 314, - 32767,32767,32767,32767, 103,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767, 575,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767, 462, 441, 442, 444, - 445, 375, 527, 581, 317, 578, 374, 146, 329, 319, - 238, 320, 254, 463, 255, 464, 467, 468, 211, 283, - 371, 150, 405, 459, 407, 457, 461, 406, 381, 386, - 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, - 397, 398, 379, 380, 460, 438, 437, 436, 403,32767, - 32767, 404, 408, 378, 411,32767,32767,32767,32767,32767, - 32767,32767,32767, 103,32767, 409, 410, 427, 428, 425, - 426, 429,32767, 430, 431, 432, 433,32767,32767, 306, - 32767,32767, 355, 353, 418, 419, 306,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767, 520, - 435,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767, 103,32767, 101, 522, 400, 402, - 490, 413, 414, 412, 382,32767, 497,32767, 103, 499, - 32767,32767,32767, 112,32767,32767,32767,32767, 521,32767, - 528, 528,32767, 483, 101, 194,32767, 194, 194,32767, - 32767,32767,32767,32767,32767,32767, 589, 483, 111, 111, - 111, 111, 111, 111, 111, 111, 111, 111, 111,32767, - 194, 111,32767,32767,32767, 101, 194, 194, 194, 194, - 194, 194, 194, 194, 194, 194, 189,32767, 264, 266, - 103, 543, 194,32767, 502,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767, 495,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767, 483, 423, 139,32767, 139, 528, 415, 416, - 417, 485, 528, 528, 528, 302, 285,32767,32767,32767, - 32767, 500, 500, 101, 101, 101, 101, 495,32767,32767, - 112, 100, 100, 100, 100, 100, 104, 102,32767,32767, - 32767,32767, 100,32767, 102, 102,32767,32767, 221, 208, - 219, 102,32767, 547, 548, 219, 102, 223, 223, 223, - 243, 243, 474, 308, 102, 100, 102, 102, 196, 308, - 308,32767, 102, 474, 308, 474, 308, 198, 308, 308, - 308, 474, 308,32767, 102, 308, 210, 100, 100, 308, - 32767,32767,32767, 485,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767, 515,32767, - 532, 545, 421, 422, 424, 530, 446, 447, 448, 449, - 450, 451, 452, 454, 577,32767, 489,32767,32767,32767, - 32767, 328, 587,32767, 587,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 588,32767, 528,32767,32767,32767,32767, 420, 9, 76, - 43, 44, 52, 58, 506, 507, 508, 509, 503, 504, - 510, 505,32767,32767, 511, 553,32767,32767, 529, 580, - 32767,32767,32767,32767,32767,32767, 139,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767, 515,32767, 137, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767, 528,32767,32767,32767, 304, 305,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767, 528,32767,32767,32767, 287, 288,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767, 282,32767,32767, 370,32767,32767,32767,32767, - 349,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767, 152, 152, 3, 3, 331, 152, 152, 152, 331, - 152, 331, 331, 331, 152, 152, 152, 152, 152, 152, - 276, 184, 258, 261, 243, 243, 152, 341, 152 - ); - - protected $goto = array( - 194, 194, 669, 423, 642, 883, 839, 884, 1025, 417, - 308, 309, 330, 562, 314, 422, 331, 424, 621, 823, - 677, 851, 824, 585, 838, 857, 165, 165, 165, 165, - 218, 195, 191, 191, 175, 177, 213, 191, 191, 191, - 191, 191, 192, 192, 192, 192, 192, 192, 186, 187, - 188, 189, 190, 215, 213, 216, 522, 523, 413, 524, - 526, 527, 528, 529, 530, 531, 532, 533, 1094, 166, - 167, 168, 193, 169, 170, 171, 164, 172, 173, 174, - 176, 212, 214, 217, 235, 238, 241, 242, 244, 255, - 256, 257, 258, 259, 260, 261, 263, 264, 265, 266, - 274, 275, 311, 312, 313, 418, 419, 420, 567, 219, - 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, - 230, 231, 232, 233, 178, 234, 179, 196, 197, 198, - 236, 186, 187, 188, 189, 190, 215, 1094, 199, 180, - 181, 182, 200, 196, 183, 237, 201, 199, 163, 202, - 203, 184, 204, 205, 206, 185, 207, 208, 209, 210, - 211, 323, 323, 323, 323, 826, 607, 607, 800, 546, - 539, 1189, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, - 1224, 1224, 1242, 1242, 343, 464, 1267, 1268, 1242, 1242, - 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 389, 539, - 546, 555, 556, 396, 565, 587, 601, 602, 831, 798, - 879, 874, 875, 888, 15, 832, 876, 829, 877, 878, - 830, 455, 455, 941, 882, 804, 1190, 251, 251, 559, - 455, 1240, 1240, 814, 1046, 1042, 1043, 1240, 1240, 1240, - 1240, 1240, 1240, 1240, 1240, 1240, 1240, 605, 639, 1191, - 1250, 1251, 341, 248, 248, 248, 248, 250, 252, 819, - 819, 1193, 1193, 1000, 1193, 1000, 804, 416, 804, 596, - 1000, 1282, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, - 1000, 1000, 1000, 1264, 1264, 962, 1264, 1193, 488, 5, - 489, 6, 1193, 1193, 1193, 1193, 495, 385, 1193, 1193, - 1193, 1274, 1274, 1274, 1274, 277, 277, 277, 277, 558, - 1276, 1276, 1276, 1276, 1066, 1067, 895, 346, 553, 319, - 303, 896, 703, 620, 622, 641, 640, 346, 346, 1143, - 659, 663, 976, 667, 675, 972, 1260, 430, 1292, 1292, - 332, 346, 346, 816, 346, 636, 1309, 650, 651, 652, - 844, 536, 536, 924, 536, 1292, 525, 525, 541, 1269, - 1270, 346, 525, 525, 525, 525, 525, 525, 525, 525, - 525, 525, 1295, 617, 618, 1033, 819, 446, 395, 1262, - 1262, 1033, 935, 935, 935, 935, 563, 599, 446, 929, - 936, 933, 403, 676, 822, 1186, 552, 534, 534, 534, - 534, 841, 589, 600, 984, 1031, 1253, 965, 939, 939, - 937, 939, 702, 465, 538, 974, 969, 344, 345, 706, - 440, 900, 1082, 853, 946, 440, 440, 1035, 604, 662, - 469, 1293, 1293, 981, 1077, 540, 550, 0, 0, 0, - 540, 843, 550, 645, 960, 388, 1174, 911, 1293, 837, - 1175, 1178, 912, 1179, 0, 566, 458, 459, 460, 541, - 849, 1185, 0, 1300, 1301, 254, 254, 401, 402, 0, - 0, 0, 648, 0, 649, 0, 405, 406, 407, 0, - 660, 0, 0, 408, 0, 0, 0, 339, 847, 594, - 608, 611, 612, 613, 614, 633, 634, 635, 679, 918, - 995, 1003, 1007, 1004, 1008, 0, 440, 440, 440, 440, - 440, 440, 440, 440, 440, 440, 440, 0, 1188, 440, - 852, 840, 1030, 1034, 584, 1059, 0, 680, 666, 666, - 944, 496, 672, 1057, 387, 391, 547, 586, 590, 425, - 0, 0, 0, 0, 0, 0, 425, 0, 0, 0, - 0, 0, 0, 934, 1012, 1005, 1009, 1006, 1010, 0, - 0, 0, 0, 0, 272, 0, 0, 0, 0, 537, - 537, 0, 0, 0, 0, 1075, 856, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 979, - 979 - ); - - protected $gotoCheck = array( - 42, 42, 72, 65, 65, 64, 35, 64, 121, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 26, - 9, 35, 27, 124, 35, 45, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 23, 23, 23, 23, 15, 106, 106, 7, 75, - 75, 20, 106, 106, 106, 106, 106, 106, 106, 106, - 106, 106, 162, 162, 95, 168, 168, 168, 162, 162, - 162, 162, 162, 162, 162, 162, 162, 162, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, 15, 6, - 15, 15, 15, 15, 75, 15, 15, 15, 15, 15, - 15, 143, 143, 49, 15, 12, 20, 5, 5, 164, - 143, 163, 163, 20, 15, 15, 15, 163, 163, 163, - 163, 163, 163, 163, 163, 163, 163, 55, 55, 20, - 20, 20, 171, 5, 5, 5, 5, 5, 5, 22, - 22, 72, 72, 72, 72, 72, 12, 13, 12, 13, - 72, 173, 72, 72, 72, 72, 72, 72, 72, 72, - 72, 72, 72, 124, 124, 101, 124, 72, 149, 46, - 149, 46, 72, 72, 72, 72, 149, 61, 72, 72, - 72, 9, 9, 9, 9, 24, 24, 24, 24, 102, - 124, 124, 124, 124, 138, 138, 72, 14, 48, 161, - 161, 72, 48, 48, 48, 63, 48, 14, 14, 145, - 48, 48, 48, 48, 48, 48, 124, 111, 174, 174, - 29, 14, 14, 18, 14, 84, 14, 84, 84, 84, - 39, 19, 19, 90, 19, 174, 165, 165, 14, 170, - 170, 14, 165, 165, 165, 165, 165, 165, 165, 165, - 165, 165, 174, 83, 83, 124, 22, 19, 28, 124, - 124, 124, 19, 19, 19, 19, 2, 2, 19, 19, - 19, 91, 91, 91, 25, 154, 9, 105, 105, 105, - 105, 37, 105, 9, 108, 123, 14, 25, 25, 25, - 25, 25, 25, 151, 25, 25, 25, 95, 95, 97, - 23, 17, 17, 41, 94, 23, 23, 126, 17, 14, - 82, 175, 175, 17, 141, 9, 9, -1, -1, -1, - 9, 17, 9, 17, 17, 9, 78, 78, 175, 17, - 78, 78, 78, 78, -1, 9, 9, 9, 9, 14, - 9, 17, -1, 9, 9, 5, 5, 80, 80, -1, - -1, -1, 80, -1, 80, -1, 80, 80, 80, -1, - 80, -1, -1, 80, -1, -1, -1, 80, 9, 79, - 79, 79, 79, 79, 79, 79, 79, 79, 79, 87, - 87, 87, 87, 87, 87, -1, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, -1, 14, 23, - 16, 16, 16, 16, 8, 8, -1, 8, 8, 8, - 16, 8, 8, 8, 58, 58, 58, 58, 58, 115, - -1, -1, -1, -1, -1, -1, 115, -1, -1, -1, - -1, -1, -1, 16, 115, 115, 115, 115, 115, -1, - -1, -1, -1, -1, 24, -1, -1, -1, -1, 24, - 24, -1, -1, -1, -1, 16, 16, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 105, - 105 - ); - - protected $gotoBase = array( - 0, 0, -297, 0, 0, 226, 196, 159, 517, 7, - 0, 0, -66, -65, 25, -175, 78, -33, 39, 84, - -213, 0, -64, 158, 302, 390, 15, 18, 46, 49, - 0, 0, 0, 0, 0, -356, 0, 67, 0, 32, - 0, -10, -1, 0, 0, 13, -417, 0, -364, 200, - 0, 0, 0, 0, 0, 208, 0, 0, 490, 0, - 0, 256, 0, 85, -14, -236, 0, 0, 0, 0, - 0, 0, -6, 0, 0, -168, 0, 0, 45, 140, - -12, 0, -35, -95, -344, 0, 0, 221, 0, 0, - 27, 92, 0, 0, -11, -287, 0, 19, 0, 0, - 0, 251, 267, 0, 0, 370, -73, 0, 43, 0, - 0, 61, 0, 0, 0, 270, 0, 0, 0, 0, - 0, 6, 0, 40, 16, 0, -7, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, - 0, -2, 0, 188, 0, 59, 0, 0, 0, -195, - 0, -19, 0, 0, 35, 0, 0, 0, 0, 0, - 0, 3, -57, -8, 201, 117, 0, 0, -110, 0, - -4, 223, 0, 241, 36, 129, 0, 0 - ); - - protected $gotoDefault = array( - -32768, 500, 710, 4, 711, 904, 787, 796, 582, 516, - 678, 340, 609, 414, 1258, 881, 1081, 564, 815, 1202, - 1210, 447, 818, 324, 700, 863, 864, 865, 392, 377, - 383, 390, 631, 610, 482, 850, 443, 842, 474, 845, - 442, 854, 162, 411, 498, 858, 3, 860, 543, 891, - 378, 868, 379, 655, 870, 549, 872, 873, 386, 393, - 394, 1086, 557, 606, 885, 243, 551, 886, 376, 887, - 894, 381, 384, 664, 454, 493, 487, 404, 1061, 593, - 628, 451, 468, 616, 615, 603, 467, 426, 409, 326, - 923, 931, 475, 452, 945, 342, 953, 708, 1093, 623, - 477, 961, 624, 968, 971, 517, 518, 466, 983, 269, - 986, 478, 1018, 646, 647, 998, 625, 626, 1016, 461, - 583, 1024, 444, 1032, 1246, 445, 1036, 262, 1039, 276, - 410, 427, 1044, 1045, 8, 1051, 670, 671, 10, 273, - 497, 1076, 665, 441, 1092, 431, 1162, 1164, 545, 479, - 1182, 1181, 658, 494, 1187, 1249, 439, 519, 462, 310, - 520, 302, 328, 307, 535, 289, 329, 521, 463, 1255, - 1263, 325, 30, 1283, 1294, 336, 561, 598 - ); - - protected $ruleToNonTerminal = array( - 0, 1, 3, 3, 2, 5, 5, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, - 7, 7, 7, 7, 7, 7, 8, 8, 9, 10, - 11, 11, 11, 12, 12, 13, 13, 14, 15, 15, - 16, 16, 17, 17, 18, 18, 21, 21, 22, 23, - 23, 24, 24, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 29, 29, 30, 30, 32, 34, - 34, 28, 36, 36, 33, 38, 38, 35, 35, 37, - 37, 39, 39, 31, 40, 40, 41, 43, 44, 44, - 45, 46, 46, 48, 47, 47, 47, 47, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 25, 25, 68, 68, 71, 71, 70, 69, - 69, 62, 74, 74, 75, 75, 76, 76, 77, 77, - 78, 78, 26, 26, 27, 27, 27, 27, 86, 86, - 88, 88, 81, 81, 89, 89, 90, 90, 90, 82, - 82, 85, 85, 83, 83, 91, 92, 92, 56, 56, - 64, 64, 67, 67, 67, 66, 93, 93, 94, 57, - 57, 57, 57, 95, 95, 96, 96, 97, 97, 98, - 99, 99, 100, 100, 101, 101, 54, 54, 50, 50, - 103, 52, 52, 104, 51, 51, 53, 53, 63, 63, - 63, 63, 79, 79, 107, 107, 109, 109, 110, 110, - 110, 110, 108, 108, 108, 112, 112, 112, 112, 87, - 87, 115, 115, 115, 113, 113, 116, 116, 114, 114, - 117, 117, 118, 118, 118, 118, 111, 111, 80, 80, - 80, 20, 20, 20, 120, 119, 119, 121, 121, 121, - 121, 59, 122, 122, 123, 60, 125, 125, 126, 126, - 127, 127, 84, 128, 128, 128, 128, 128, 128, 133, - 133, 134, 134, 135, 135, 135, 135, 135, 136, 137, - 137, 132, 132, 129, 129, 131, 131, 139, 139, 138, - 138, 138, 138, 138, 138, 138, 130, 140, 140, 142, - 141, 141, 61, 102, 143, 143, 55, 55, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 150, 144, 144, 149, 149, 152, 153, 153, 154, - 155, 155, 155, 19, 19, 72, 72, 72, 72, 145, - 145, 145, 145, 157, 157, 146, 146, 148, 148, 148, - 151, 151, 162, 162, 162, 162, 162, 162, 162, 162, - 162, 163, 163, 106, 165, 165, 165, 165, 147, 147, - 147, 147, 147, 147, 147, 147, 58, 58, 160, 160, - 160, 160, 166, 166, 156, 156, 156, 167, 167, 167, - 167, 167, 167, 73, 73, 65, 65, 65, 65, 124, - 124, 124, 124, 170, 169, 159, 159, 159, 159, 159, - 159, 159, 158, 158, 158, 168, 168, 168, 168, 105, - 164, 172, 172, 171, 171, 173, 173, 173, 173, 173, - 173, 173, 173, 161, 161, 161, 161, 175, 176, 174, - 174, 174, 174, 174, 174, 174, 174, 177, 177, 177, - 177 - ); - - protected $ruleToLength = array( - 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 1, 0, 1, 1, 2, 1, 3, 4, 1, - 2, 0, 1, 1, 1, 1, 1, 3, 5, 4, - 3, 4, 2, 3, 1, 1, 7, 6, 2, 3, - 1, 2, 3, 1, 2, 3, 1, 1, 3, 1, - 3, 1, 2, 2, 3, 1, 3, 2, 3, 1, - 3, 2, 0, 1, 1, 1, 1, 1, 3, 7, - 10, 5, 7, 9, 5, 3, 3, 3, 3, 3, - 3, 1, 2, 5, 7, 9, 6, 5, 6, 3, - 2, 1, 1, 1, 0, 2, 1, 3, 8, 0, - 4, 2, 1, 3, 0, 1, 0, 1, 0, 1, - 3, 1, 8, 9, 8, 7, 6, 8, 0, 2, - 0, 2, 1, 2, 1, 2, 1, 1, 1, 0, - 2, 0, 2, 0, 2, 2, 1, 3, 1, 4, - 1, 4, 1, 1, 4, 2, 1, 3, 3, 3, - 4, 4, 5, 0, 2, 4, 3, 1, 1, 7, - 0, 2, 1, 3, 3, 4, 1, 4, 0, 2, - 5, 0, 2, 6, 0, 2, 0, 3, 1, 2, - 1, 1, 2, 0, 1, 3, 0, 2, 1, 1, - 1, 1, 6, 8, 6, 1, 2, 1, 1, 1, - 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, - 3, 3, 1, 2, 1, 1, 0, 1, 0, 2, - 2, 2, 4, 3, 1, 1, 3, 1, 2, 2, - 3, 2, 3, 1, 1, 2, 3, 1, 1, 3, - 2, 0, 1, 5, 5, 10, 3, 5, 1, 1, - 3, 0, 2, 4, 5, 4, 4, 4, 3, 1, - 1, 1, 1, 1, 1, 0, 1, 1, 2, 1, - 1, 1, 1, 1, 1, 1, 2, 1, 3, 1, - 1, 3, 2, 2, 3, 1, 0, 1, 1, 3, - 3, 3, 4, 1, 1, 2, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, - 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 5, 4, 3, 4, - 4, 2, 2, 4, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 1, 3, 2, 1, 2, - 4, 2, 2, 8, 9, 8, 9, 9, 10, 9, - 10, 8, 3, 2, 0, 4, 2, 1, 3, 2, - 2, 2, 4, 1, 1, 1, 1, 1, 1, 1, - 1, 3, 1, 1, 1, 0, 3, 0, 1, 1, - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 3, 3, 3, 4, 1, 1, 3, 1, 1, - 1, 1, 1, 3, 2, 3, 0, 1, 1, 3, - 1, 1, 1, 1, 1, 3, 1, 1, 4, 4, - 1, 4, 4, 0, 1, 1, 1, 3, 3, 1, - 4, 2, 2, 1, 3, 1, 4, 4, 3, 3, - 3, 3, 1, 3, 1, 1, 3, 1, 1, 4, - 1, 1, 1, 3, 1, 1, 2, 1, 3, 4, - 3, 2, 0, 2, 2, 1, 2, 1, 1, 1, - 4, 3, 3, 3, 3, 6, 3, 1, 1, 2, - 1 - ); - - protected function initReduceCallbacks() { - $this->reduceCallbacks = [ - 0 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 1 => function ($stackPos) { - $this->semValue = $this->handleNamespaces($this->semStack[$stackPos-(1-1)]); - }, - 2 => function ($stackPos) { - if (is_array($this->semStack[$stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); } else { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }; - }, - 3 => function ($stackPos) { - $this->semValue = array(); - }, - 4 => function ($stackPos) { - $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; - if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 5 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 6 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 7 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 8 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 9 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 10 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 11 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 12 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 13 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 14 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 15 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 16 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 17 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 18 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 19 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 20 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 21 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 22 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 23 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 24 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 25 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 26 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 27 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 28 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 29 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 30 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 31 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 32 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 33 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 34 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 35 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 36 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 37 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 38 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 39 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 40 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 41 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 42 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 43 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 44 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 45 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 46 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 47 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 48 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 49 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 50 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 51 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 52 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 53 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 54 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 55 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 56 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 57 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 58 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 59 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 60 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 61 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 62 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 63 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 64 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 65 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 66 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 67 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 68 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 69 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 70 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 71 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 72 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 73 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 74 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 75 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 76 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 77 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 78 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 79 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 80 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 81 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 82 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 83 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 84 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 85 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 86 => function ($stackPos) { - $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 87 => function ($stackPos) { - $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 88 => function ($stackPos) { - $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 89 => function ($stackPos) { - $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 90 => function ($stackPos) { - $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 91 => function ($stackPos) { - $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 92 => function ($stackPos) { - $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 93 => function ($stackPos) { - $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 94 => function ($stackPos) { - $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 95 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 96 => function ($stackPos) { - $this->semValue = new Name(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 97 => function ($stackPos) { - $this->semValue = new Expr\Variable(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 98 => function ($stackPos) { - /* nothing */ - }, - 99 => function ($stackPos) { - /* nothing */ - }, - 100 => function ($stackPos) { - /* nothing */ - }, - 101 => function ($stackPos) { - $this->emitError(new Error('A trailing comma is not allowed here', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes)); - }, - 102 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 103 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 104 => function ($stackPos) { - $this->semValue = new Node\Attribute($this->semStack[$stackPos-(1-1)], [], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 105 => function ($stackPos) { - $this->semValue = new Node\Attribute($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 106 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 107 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 108 => function ($stackPos) { - $this->semValue = new Node\AttributeGroup($this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 109 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 110 => function ($stackPos) { - $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 111 => function ($stackPos) { - $this->semValue = []; - }, - 112 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 113 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 114 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 115 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 116 => function ($stackPos) { - $this->semValue = new Stmt\HaltCompiler($this->lexer->handleHaltCompiler(), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 117 => function ($stackPos) { - $this->semValue = new Stmt\Namespace_($this->semStack[$stackPos-(3-2)], null, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON); - $this->checkNamespace($this->semValue); - }, - 118 => function ($stackPos) { - $this->semValue = new Stmt\Namespace_($this->semStack[$stackPos-(5-2)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); - $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); - $this->checkNamespace($this->semValue); - }, - 119 => function ($stackPos) { - $this->semValue = new Stmt\Namespace_(null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); - $this->checkNamespace($this->semValue); - }, - 120 => function ($stackPos) { - $this->semValue = new Stmt\Use_($this->semStack[$stackPos-(3-2)], Stmt\Use_::TYPE_NORMAL, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 121 => function ($stackPos) { - $this->semValue = new Stmt\Use_($this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 122 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 123 => function ($stackPos) { - $this->semValue = new Stmt\Const_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 124 => function ($stackPos) { - $this->semValue = Stmt\Use_::TYPE_FUNCTION; - }, - 125 => function ($stackPos) { - $this->semValue = Stmt\Use_::TYPE_CONSTANT; - }, - 126 => function ($stackPos) { - $this->semValue = new Stmt\GroupUse($this->semStack[$stackPos-(7-3)], $this->semStack[$stackPos-(7-6)], $this->semStack[$stackPos-(7-2)], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); - }, - 127 => function ($stackPos) { - $this->semValue = new Stmt\GroupUse($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-5)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); - }, - 128 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 129 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 130 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 131 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 132 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 133 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 134 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 135 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 136 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 137 => function ($stackPos) { - $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(1-1)); - }, - 138 => function ($stackPos) { - $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(3-3)); - }, - 139 => function ($stackPos) { - $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(1-1)); - }, - 140 => function ($stackPos) { - $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(3-3)); - }, - 141 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; $this->semValue->type = Stmt\Use_::TYPE_NORMAL; - }, - 142 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-2)]; $this->semValue->type = $this->semStack[$stackPos-(2-1)]; - }, - 143 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 144 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 145 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 146 => function ($stackPos) { - $this->semValue = new Node\Const_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 147 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 148 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 149 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 150 => function ($stackPos) { - $this->semValue = new Node\Const_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 151 => function ($stackPos) { - if (is_array($this->semStack[$stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); } else { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }; - }, - 152 => function ($stackPos) { - $this->semValue = array(); - }, - 153 => function ($stackPos) { - $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; - if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 154 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 155 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 156 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 157 => function ($stackPos) { - throw new Error('__HALT_COMPILER() can only be used from the outermost scope', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 158 => function ($stackPos) { - - if ($this->semStack[$stackPos-(3-2)]) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; $attrs = $this->startAttributeStack[$stackPos-(3-1)]; $stmts = $this->semValue; if (!empty($attrs['comments'])) {$stmts[0]->setAttribute('comments', array_merge($attrs['comments'], $stmts[0]->getAttribute('comments', []))); }; - } else { - $startAttributes = $this->startAttributeStack[$stackPos-(3-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; }; - if (null === $this->semValue) { $this->semValue = array(); } - } - - }, - 159 => function ($stackPos) { - $this->semValue = new Stmt\If_($this->semStack[$stackPos-(7-3)], ['stmts' => is_array($this->semStack[$stackPos-(7-5)]) ? $this->semStack[$stackPos-(7-5)] : array($this->semStack[$stackPos-(7-5)]), 'elseifs' => $this->semStack[$stackPos-(7-6)], 'else' => $this->semStack[$stackPos-(7-7)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); - }, - 160 => function ($stackPos) { - $this->semValue = new Stmt\If_($this->semStack[$stackPos-(10-3)], ['stmts' => $this->semStack[$stackPos-(10-6)], 'elseifs' => $this->semStack[$stackPos-(10-7)], 'else' => $this->semStack[$stackPos-(10-8)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); - }, - 161 => function ($stackPos) { - $this->semValue = new Stmt\While_($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); - }, - 162 => function ($stackPos) { - $this->semValue = new Stmt\Do_($this->semStack[$stackPos-(7-5)], is_array($this->semStack[$stackPos-(7-2)]) ? $this->semStack[$stackPos-(7-2)] : array($this->semStack[$stackPos-(7-2)]), $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); - }, - 163 => function ($stackPos) { - $this->semValue = new Stmt\For_(['init' => $this->semStack[$stackPos-(9-3)], 'cond' => $this->semStack[$stackPos-(9-5)], 'loop' => $this->semStack[$stackPos-(9-7)], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); - }, - 164 => function ($stackPos) { - $this->semValue = new Stmt\Switch_($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); - }, - 165 => function ($stackPos) { - $this->semValue = new Stmt\Break_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 166 => function ($stackPos) { - $this->semValue = new Stmt\Continue_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 167 => function ($stackPos) { - $this->semValue = new Stmt\Return_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 168 => function ($stackPos) { - $this->semValue = new Stmt\Global_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 169 => function ($stackPos) { - $this->semValue = new Stmt\Static_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 170 => function ($stackPos) { - $this->semValue = new Stmt\Echo_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 171 => function ($stackPos) { - $this->semValue = new Stmt\InlineHTML($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 172 => function ($stackPos) { - - $e = $this->semStack[$stackPos-(2-1)]; - if ($e instanceof Expr\Throw_) { - // For backwards-compatibility reasons, convert throw in statement position into - // Stmt\Throw_ rather than Stmt\Expression(Expr\Throw_). - $this->semValue = new Stmt\Throw_($e->expr, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - } else { - $this->semValue = new Stmt\Expression($e, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - } - - }, - 173 => function ($stackPos) { - $this->semValue = new Stmt\Unset_($this->semStack[$stackPos-(5-3)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); - }, - 174 => function ($stackPos) { - $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(7-3)], $this->semStack[$stackPos-(7-5)][0], ['keyVar' => null, 'byRef' => $this->semStack[$stackPos-(7-5)][1], 'stmts' => $this->semStack[$stackPos-(7-7)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); - }, - 175 => function ($stackPos) { - $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(9-3)], $this->semStack[$stackPos-(9-7)][0], ['keyVar' => $this->semStack[$stackPos-(9-5)], 'byRef' => $this->semStack[$stackPos-(9-7)][1], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); - }, - 176 => function ($stackPos) { - $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(6-3)], new Expr\Error($this->startAttributeStack[$stackPos-(6-4)] + $this->endAttributeStack[$stackPos-(6-4)]), ['stmts' => $this->semStack[$stackPos-(6-6)]], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); - }, - 177 => function ($stackPos) { - $this->semValue = new Stmt\Declare_($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); - }, - 178 => function ($stackPos) { - $this->semValue = new Stmt\TryCatch($this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-5)], $this->semStack[$stackPos-(6-6)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); $this->checkTryCatch($this->semValue); - }, - 179 => function ($stackPos) { - $this->semValue = new Stmt\Goto_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 180 => function ($stackPos) { - $this->semValue = new Stmt\Label($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 181 => function ($stackPos) { - $this->semValue = array(); /* means: no statement */ - }, - 182 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 183 => function ($stackPos) { - $startAttributes = $this->startAttributeStack[$stackPos-(1-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; }; - if ($this->semValue === null) $this->semValue = array(); /* means: no statement */ - }, - 184 => function ($stackPos) { - $this->semValue = array(); - }, - 185 => function ($stackPos) { - $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 186 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 187 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 188 => function ($stackPos) { - $this->semValue = new Stmt\Catch_($this->semStack[$stackPos-(8-3)], $this->semStack[$stackPos-(8-4)], $this->semStack[$stackPos-(8-7)], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); - }, - 189 => function ($stackPos) { - $this->semValue = null; - }, - 190 => function ($stackPos) { - $this->semValue = new Stmt\Finally_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 191 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 192 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 193 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 194 => function ($stackPos) { - $this->semValue = false; - }, - 195 => function ($stackPos) { - $this->semValue = true; - }, - 196 => function ($stackPos) { - $this->semValue = false; - }, - 197 => function ($stackPos) { - $this->semValue = true; - }, - 198 => function ($stackPos) { - $this->semValue = false; - }, - 199 => function ($stackPos) { - $this->semValue = true; - }, - 200 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 201 => function ($stackPos) { - $this->semValue = []; - }, - 202 => function ($stackPos) { - $this->semValue = new Stmt\Function_($this->semStack[$stackPos-(8-3)], ['byRef' => $this->semStack[$stackPos-(8-2)], 'params' => $this->semStack[$stackPos-(8-5)], 'returnType' => $this->semStack[$stackPos-(8-7)], 'stmts' => $this->semStack[$stackPos-(8-8)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); - }, - 203 => function ($stackPos) { - $this->semValue = new Stmt\Function_($this->semStack[$stackPos-(9-4)], ['byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-6)], 'returnType' => $this->semStack[$stackPos-(9-8)], 'stmts' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => $this->semStack[$stackPos-(9-1)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); - }, - 204 => function ($stackPos) { - $this->semValue = new Stmt\Class_($this->semStack[$stackPos-(8-3)], ['type' => $this->semStack[$stackPos-(8-2)], 'extends' => $this->semStack[$stackPos-(8-4)], 'implements' => $this->semStack[$stackPos-(8-5)], 'stmts' => $this->semStack[$stackPos-(8-7)], 'attrGroups' => $this->semStack[$stackPos-(8-1)]], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); - $this->checkClass($this->semValue, $stackPos-(8-3)); - }, - 205 => function ($stackPos) { - $this->semValue = new Stmt\Interface_($this->semStack[$stackPos-(7-3)], ['extends' => $this->semStack[$stackPos-(7-4)], 'stmts' => $this->semStack[$stackPos-(7-6)], 'attrGroups' => $this->semStack[$stackPos-(7-1)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); - $this->checkInterface($this->semValue, $stackPos-(7-3)); - }, - 206 => function ($stackPos) { - $this->semValue = new Stmt\Trait_($this->semStack[$stackPos-(6-3)], ['stmts' => $this->semStack[$stackPos-(6-5)], 'attrGroups' => $this->semStack[$stackPos-(6-1)]], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); - }, - 207 => function ($stackPos) { - $this->semValue = new Stmt\Enum_($this->semStack[$stackPos-(8-3)], ['scalarType' => $this->semStack[$stackPos-(8-4)], 'implements' => $this->semStack[$stackPos-(8-5)], 'stmts' => $this->semStack[$stackPos-(8-7)], 'attrGroups' => $this->semStack[$stackPos-(8-1)]], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); - $this->checkEnum($this->semValue, $stackPos-(8-3)); - }, - 208 => function ($stackPos) { - $this->semValue = null; - }, - 209 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-2)]; - }, - 210 => function ($stackPos) { - $this->semValue = null; - }, - 211 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-2)]; - }, - 212 => function ($stackPos) { - $this->semValue = 0; - }, - 213 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 214 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 215 => function ($stackPos) { - $this->checkClassModifier($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $this->semValue = $this->semStack[$stackPos-(2-1)] | $this->semStack[$stackPos-(2-2)]; - }, - 216 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; - }, - 217 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_FINAL; - }, - 218 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_READONLY; - }, - 219 => function ($stackPos) { - $this->semValue = null; - }, - 220 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-2)]; - }, - 221 => function ($stackPos) { - $this->semValue = array(); - }, - 222 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-2)]; - }, - 223 => function ($stackPos) { - $this->semValue = array(); - }, - 224 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-2)]; - }, - 225 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 226 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 227 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 228 => function ($stackPos) { - $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); - }, - 229 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(4-2)]; - }, - 230 => function ($stackPos) { - $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); - }, - 231 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(4-2)]; - }, - 232 => function ($stackPos) { - $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); - }, - 233 => function ($stackPos) { - $this->semValue = null; - }, - 234 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(4-2)]; - }, - 235 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 236 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 237 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 238 => function ($stackPos) { - $this->semValue = new Stmt\DeclareDeclare($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 239 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 240 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(4-3)]; - }, - 241 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(4-2)]; - }, - 242 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(5-3)]; - }, - 243 => function ($stackPos) { - $this->semValue = array(); - }, - 244 => function ($stackPos) { - $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 245 => function ($stackPos) { - $this->semValue = new Stmt\Case_($this->semStack[$stackPos-(4-2)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 246 => function ($stackPos) { - $this->semValue = new Stmt\Case_(null, $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 247 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 248 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 249 => function ($stackPos) { - $this->semValue = new Expr\Match_($this->semStack[$stackPos-(7-3)], $this->semStack[$stackPos-(7-6)], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); - }, - 250 => function ($stackPos) { - $this->semValue = []; - }, - 251 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 252 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 253 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 254 => function ($stackPos) { - $this->semValue = new Node\MatchArm($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 255 => function ($stackPos) { - $this->semValue = new Node\MatchArm(null, $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 256 => function ($stackPos) { - $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); - }, - 257 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(4-2)]; - }, - 258 => function ($stackPos) { - $this->semValue = array(); - }, - 259 => function ($stackPos) { - $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 260 => function ($stackPos) { - $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos-(5-3)], is_array($this->semStack[$stackPos-(5-5)]) ? $this->semStack[$stackPos-(5-5)] : array($this->semStack[$stackPos-(5-5)]), $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); - }, - 261 => function ($stackPos) { - $this->semValue = array(); - }, - 262 => function ($stackPos) { - $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 263 => function ($stackPos) { - $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-6)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); - }, - 264 => function ($stackPos) { - $this->semValue = null; - }, - 265 => function ($stackPos) { - $this->semValue = new Stmt\Else_(is_array($this->semStack[$stackPos-(2-2)]) ? $this->semStack[$stackPos-(2-2)] : array($this->semStack[$stackPos-(2-2)]), $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 266 => function ($stackPos) { - $this->semValue = null; - }, - 267 => function ($stackPos) { - $this->semValue = new Stmt\Else_($this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 268 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)], false); - }, - 269 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(2-2)], true); - }, - 270 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)], false); - }, - 271 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)], false); - }, - 272 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 273 => function ($stackPos) { - $this->semValue = array(); - }, - 274 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 275 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 276 => function ($stackPos) { - $this->semValue = 0; - }, - 277 => function ($stackPos) { - $this->checkModifier($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $this->semValue = $this->semStack[$stackPos-(2-1)] | $this->semStack[$stackPos-(2-2)]; - }, - 278 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_PUBLIC; - }, - 279 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_PROTECTED; - }, - 280 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_PRIVATE; - }, - 281 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_READONLY; - }, - 282 => function ($stackPos) { - $this->semValue = new Node\Param($this->semStack[$stackPos-(6-6)], null, $this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-4)], $this->semStack[$stackPos-(6-5)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes, $this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-1)]); - $this->checkParam($this->semValue); - }, - 283 => function ($stackPos) { - $this->semValue = new Node\Param($this->semStack[$stackPos-(8-6)], $this->semStack[$stackPos-(8-8)], $this->semStack[$stackPos-(8-3)], $this->semStack[$stackPos-(8-4)], $this->semStack[$stackPos-(8-5)], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes, $this->semStack[$stackPos-(8-2)], $this->semStack[$stackPos-(8-1)]); - $this->checkParam($this->semValue); - }, - 284 => function ($stackPos) { - $this->semValue = new Node\Param(new Expr\Error($this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes), null, $this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-4)], $this->semStack[$stackPos-(6-5)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes, $this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-1)]); - }, - 285 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 286 => function ($stackPos) { - $this->semValue = new Node\NullableType($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 287 => function ($stackPos) { - $this->semValue = new Node\UnionType($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 288 => function ($stackPos) { - $this->semValue = new Node\IntersectionType($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 289 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 290 => function ($stackPos) { - $this->semValue = new Node\Name('static', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 291 => function ($stackPos) { - $this->semValue = $this->handleBuiltinTypes($this->semStack[$stackPos-(1-1)]); - }, - 292 => function ($stackPos) { - $this->semValue = new Node\Identifier('array', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 293 => function ($stackPos) { - $this->semValue = new Node\Identifier('callable', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 294 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); - }, - 295 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 296 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); - }, - 297 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 298 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); - }, - 299 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 300 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); - }, - 301 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 302 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 303 => function ($stackPos) { - $this->semValue = new Node\NullableType($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 304 => function ($stackPos) { - $this->semValue = new Node\UnionType($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 305 => function ($stackPos) { - $this->semValue = new Node\IntersectionType($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 306 => function ($stackPos) { - $this->semValue = null; - }, - 307 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 308 => function ($stackPos) { - $this->semValue = null; - }, - 309 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-2)]; - }, - 310 => function ($stackPos) { - $this->semValue = null; - }, - 311 => function ($stackPos) { - $this->semValue = array(); - }, - 312 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(4-2)]; - }, - 313 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(3-2)]); - }, - 314 => function ($stackPos) { - $this->semValue = new Node\VariadicPlaceholder($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 315 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 316 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 317 => function ($stackPos) { - $this->semValue = new Node\Arg($this->semStack[$stackPos-(1-1)], false, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 318 => function ($stackPos) { - $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], true, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 319 => function ($stackPos) { - $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], false, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 320 => function ($stackPos) { - $this->semValue = new Node\Arg($this->semStack[$stackPos-(3-3)], false, false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->semStack[$stackPos-(3-1)]); - }, - 321 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 322 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 323 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 324 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 325 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 326 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 327 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 328 => function ($stackPos) { - $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 329 => function ($stackPos) { - $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 330 => function ($stackPos) { - if ($this->semStack[$stackPos-(2-2)] !== null) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; } - }, - 331 => function ($stackPos) { - $this->semValue = array(); - }, - 332 => function ($stackPos) { - $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; - if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 333 => function ($stackPos) { - $this->semValue = new Stmt\Property($this->semStack[$stackPos-(5-2)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes, $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-1)]); - $this->checkProperty($this->semValue, $stackPos-(5-2)); - }, - 334 => function ($stackPos) { - $this->semValue = new Stmt\ClassConst($this->semStack[$stackPos-(5-4)], $this->semStack[$stackPos-(5-2)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes, $this->semStack[$stackPos-(5-1)]); - $this->checkClassConst($this->semValue, $stackPos-(5-2)); - }, - 335 => function ($stackPos) { - $this->semValue = new Stmt\ClassMethod($this->semStack[$stackPos-(10-5)], ['type' => $this->semStack[$stackPos-(10-2)], 'byRef' => $this->semStack[$stackPos-(10-4)], 'params' => $this->semStack[$stackPos-(10-7)], 'returnType' => $this->semStack[$stackPos-(10-9)], 'stmts' => $this->semStack[$stackPos-(10-10)], 'attrGroups' => $this->semStack[$stackPos-(10-1)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); - $this->checkClassMethod($this->semValue, $stackPos-(10-2)); - }, - 336 => function ($stackPos) { - $this->semValue = new Stmt\TraitUse($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 337 => function ($stackPos) { - $this->semValue = new Stmt\EnumCase($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-4)], $this->semStack[$stackPos-(5-1)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); - }, - 338 => function ($stackPos) { - $this->semValue = null; /* will be skipped */ - }, - 339 => function ($stackPos) { - $this->semValue = array(); - }, - 340 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 341 => function ($stackPos) { - $this->semValue = array(); - }, - 342 => function ($stackPos) { - $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 343 => function ($stackPos) { - $this->semValue = new Stmt\TraitUseAdaptation\Precedence($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 344 => function ($stackPos) { - $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(5-1)][0], $this->semStack[$stackPos-(5-1)][1], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); - }, - 345 => function ($stackPos) { - $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], $this->semStack[$stackPos-(4-3)], null, $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 346 => function ($stackPos) { - $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 347 => function ($stackPos) { - $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 348 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); - }, - 349 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 350 => function ($stackPos) { - $this->semValue = array(null, $this->semStack[$stackPos-(1-1)]); - }, - 351 => function ($stackPos) { - $this->semValue = null; - }, - 352 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 353 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 354 => function ($stackPos) { - $this->semValue = 0; - }, - 355 => function ($stackPos) { - $this->semValue = 0; - }, - 356 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 357 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 358 => function ($stackPos) { - $this->checkModifier($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $this->semValue = $this->semStack[$stackPos-(2-1)] | $this->semStack[$stackPos-(2-2)]; - }, - 359 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_PUBLIC; - }, - 360 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_PROTECTED; - }, - 361 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_PRIVATE; - }, - 362 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_STATIC; - }, - 363 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; - }, - 364 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_FINAL; - }, - 365 => function ($stackPos) { - $this->semValue = Stmt\Class_::MODIFIER_READONLY; - }, - 366 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 367 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 368 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 369 => function ($stackPos) { - $this->semValue = new Node\VarLikeIdentifier(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 370 => function ($stackPos) { - $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 371 => function ($stackPos) { - $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 372 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 373 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 374 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 375 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 376 => function ($stackPos) { - $this->semValue = array(); - }, - 377 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 378 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 379 => function ($stackPos) { - $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 380 => function ($stackPos) { - $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 381 => function ($stackPos) { - $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 382 => function ($stackPos) { - $this->semValue = new Expr\AssignRef($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 383 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 384 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 385 => function ($stackPos) { - $this->semValue = new Expr\Clone_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 386 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 387 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 388 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 389 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 390 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 391 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 392 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 393 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 394 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 395 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 396 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 397 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 398 => function ($stackPos) { - $this->semValue = new Expr\AssignOp\Coalesce($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 399 => function ($stackPos) { - $this->semValue = new Expr\PostInc($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 400 => function ($stackPos) { - $this->semValue = new Expr\PreInc($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 401 => function ($stackPos) { - $this->semValue = new Expr\PostDec($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 402 => function ($stackPos) { - $this->semValue = new Expr\PreDec($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 403 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 404 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 405 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 406 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 407 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 408 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 409 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 410 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 411 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 412 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 413 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 414 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 415 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 416 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 417 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 418 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 419 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 420 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 421 => function ($stackPos) { - $this->semValue = new Expr\UnaryPlus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 422 => function ($stackPos) { - $this->semValue = new Expr\UnaryMinus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 423 => function ($stackPos) { - $this->semValue = new Expr\BooleanNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 424 => function ($stackPos) { - $this->semValue = new Expr\BitwiseNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 425 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 426 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 427 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 428 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 429 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Spaceship($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 430 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 431 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 432 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 433 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 434 => function ($stackPos) { - $this->semValue = new Expr\Instanceof_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 435 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 436 => function ($stackPos) { - $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(5-1)], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); - }, - 437 => function ($stackPos) { - $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(4-1)], null, $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 438 => function ($stackPos) { - $this->semValue = new Expr\BinaryOp\Coalesce($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 439 => function ($stackPos) { - $this->semValue = new Expr\Isset_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 440 => function ($stackPos) { - $this->semValue = new Expr\Empty_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 441 => function ($stackPos) { - $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 442 => function ($stackPos) { - $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 443 => function ($stackPos) { - $this->semValue = new Expr\Eval_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 444 => function ($stackPos) { - $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 445 => function ($stackPos) { - $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 446 => function ($stackPos) { - $this->semValue = new Expr\Cast\Int_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 447 => function ($stackPos) { - $attrs = $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes; - $attrs['kind'] = $this->getFloatCastKind($this->semStack[$stackPos-(2-1)]); - $this->semValue = new Expr\Cast\Double($this->semStack[$stackPos-(2-2)], $attrs); - }, - 448 => function ($stackPos) { - $this->semValue = new Expr\Cast\String_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 449 => function ($stackPos) { - $this->semValue = new Expr\Cast\Array_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 450 => function ($stackPos) { - $this->semValue = new Expr\Cast\Object_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 451 => function ($stackPos) { - $this->semValue = new Expr\Cast\Bool_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 452 => function ($stackPos) { - $this->semValue = new Expr\Cast\Unset_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 453 => function ($stackPos) { - $attrs = $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes; - $attrs['kind'] = strtolower($this->semStack[$stackPos-(2-1)]) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE; - $this->semValue = new Expr\Exit_($this->semStack[$stackPos-(2-2)], $attrs); - }, - 454 => function ($stackPos) { - $this->semValue = new Expr\ErrorSuppress($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 455 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 456 => function ($stackPos) { - $this->semValue = new Expr\ShellExec($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 457 => function ($stackPos) { - $this->semValue = new Expr\Print_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 458 => function ($stackPos) { - $this->semValue = new Expr\Yield_(null, null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 459 => function ($stackPos) { - $this->semValue = new Expr\Yield_($this->semStack[$stackPos-(2-2)], null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 460 => function ($stackPos) { - $this->semValue = new Expr\Yield_($this->semStack[$stackPos-(4-4)], $this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 461 => function ($stackPos) { - $this->semValue = new Expr\YieldFrom($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 462 => function ($stackPos) { - $this->semValue = new Expr\Throw_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 463 => function ($stackPos) { - $this->semValue = new Expr\ArrowFunction(['static' => false, 'byRef' => $this->semStack[$stackPos-(8-2)], 'params' => $this->semStack[$stackPos-(8-4)], 'returnType' => $this->semStack[$stackPos-(8-6)], 'expr' => $this->semStack[$stackPos-(8-8)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); - }, - 464 => function ($stackPos) { - $this->semValue = new Expr\ArrowFunction(['static' => true, 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-5)], 'returnType' => $this->semStack[$stackPos-(9-7)], 'expr' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); - }, - 465 => function ($stackPos) { - $this->semValue = new Expr\Closure(['static' => false, 'byRef' => $this->semStack[$stackPos-(8-2)], 'params' => $this->semStack[$stackPos-(8-4)], 'uses' => $this->semStack[$stackPos-(8-6)], 'returnType' => $this->semStack[$stackPos-(8-7)], 'stmts' => $this->semStack[$stackPos-(8-8)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); - }, - 466 => function ($stackPos) { - $this->semValue = new Expr\Closure(['static' => true, 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-5)], 'uses' => $this->semStack[$stackPos-(9-7)], 'returnType' => $this->semStack[$stackPos-(9-8)], 'stmts' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); - }, - 467 => function ($stackPos) { - $this->semValue = new Expr\ArrowFunction(['static' => false, 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-5)], 'returnType' => $this->semStack[$stackPos-(9-7)], 'expr' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => $this->semStack[$stackPos-(9-1)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); - }, - 468 => function ($stackPos) { - $this->semValue = new Expr\ArrowFunction(['static' => true, 'byRef' => $this->semStack[$stackPos-(10-4)], 'params' => $this->semStack[$stackPos-(10-6)], 'returnType' => $this->semStack[$stackPos-(10-8)], 'expr' => $this->semStack[$stackPos-(10-10)], 'attrGroups' => $this->semStack[$stackPos-(10-1)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); - }, - 469 => function ($stackPos) { - $this->semValue = new Expr\Closure(['static' => false, 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-5)], 'uses' => $this->semStack[$stackPos-(9-7)], 'returnType' => $this->semStack[$stackPos-(9-8)], 'stmts' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => $this->semStack[$stackPos-(9-1)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); - }, - 470 => function ($stackPos) { - $this->semValue = new Expr\Closure(['static' => true, 'byRef' => $this->semStack[$stackPos-(10-4)], 'params' => $this->semStack[$stackPos-(10-6)], 'uses' => $this->semStack[$stackPos-(10-8)], 'returnType' => $this->semStack[$stackPos-(10-9)], 'stmts' => $this->semStack[$stackPos-(10-10)], 'attrGroups' => $this->semStack[$stackPos-(10-1)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); - }, - 471 => function ($stackPos) { - $this->semValue = array(new Stmt\Class_(null, ['type' => 0, 'extends' => $this->semStack[$stackPos-(8-4)], 'implements' => $this->semStack[$stackPos-(8-5)], 'stmts' => $this->semStack[$stackPos-(8-7)], 'attrGroups' => $this->semStack[$stackPos-(8-1)]], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes), $this->semStack[$stackPos-(8-3)]); - $this->checkClass($this->semValue[0], -1); - }, - 472 => function ($stackPos) { - $this->semValue = new Expr\New_($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 473 => function ($stackPos) { - list($class, $ctorArgs) = $this->semStack[$stackPos-(2-2)]; $this->semValue = new Expr\New_($class, $ctorArgs, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 474 => function ($stackPos) { - $this->semValue = array(); - }, - 475 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(4-3)]; - }, - 476 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 477 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 478 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 479 => function ($stackPos) { - $this->semValue = new Expr\ClosureUse($this->semStack[$stackPos-(2-2)], $this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 480 => function ($stackPos) { - $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 481 => function ($stackPos) { - $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 482 => function ($stackPos) { - $this->semValue = new Expr\StaticCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 483 => function ($stackPos) { - $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 484 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 485 => function ($stackPos) { - $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 486 => function ($stackPos) { - $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 487 => function ($stackPos) { - $this->semValue = new Name\FullyQualified(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 488 => function ($stackPos) { - $this->semValue = new Name\Relative(substr($this->semStack[$stackPos-(1-1)], 10), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 489 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 490 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 491 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 492 => function ($stackPos) { - $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2; - }, - 493 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 494 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 495 => function ($stackPos) { - $this->semValue = null; - }, - 496 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 497 => function ($stackPos) { - $this->semValue = array(); - }, - 498 => function ($stackPos) { - $this->semValue = array(new Scalar\EncapsedStringPart(Scalar\String_::parseEscapeSequences($this->semStack[$stackPos-(1-1)], '`'), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes)); - }, - 499 => function ($stackPos) { - foreach ($this->semStack[$stackPos-(1-1)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '`', true); } }; $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 500 => function ($stackPos) { - $this->semValue = array(); - }, - 501 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 502 => function ($stackPos) { - $this->semValue = new Expr\ConstFetch($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 503 => function ($stackPos) { - $this->semValue = new Scalar\MagicConst\Line($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 504 => function ($stackPos) { - $this->semValue = new Scalar\MagicConst\File($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 505 => function ($stackPos) { - $this->semValue = new Scalar\MagicConst\Dir($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 506 => function ($stackPos) { - $this->semValue = new Scalar\MagicConst\Class_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 507 => function ($stackPos) { - $this->semValue = new Scalar\MagicConst\Trait_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 508 => function ($stackPos) { - $this->semValue = new Scalar\MagicConst\Method($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 509 => function ($stackPos) { - $this->semValue = new Scalar\MagicConst\Function_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 510 => function ($stackPos) { - $this->semValue = new Scalar\MagicConst\Namespace_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 511 => function ($stackPos) { - $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 512 => function ($stackPos) { - $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(3-1)], new Expr\Error($this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)]), $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->errorState = 2; - }, - 513 => function ($stackPos) { - $attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_SHORT; - $this->semValue = new Expr\Array_($this->semStack[$stackPos-(3-2)], $attrs); - }, - 514 => function ($stackPos) { - $attrs = $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_LONG; - $this->semValue = new Expr\Array_($this->semStack[$stackPos-(4-3)], $attrs); - }, - 515 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 516 => function ($stackPos) { - $this->semValue = Scalar\String_::fromString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 517 => function ($stackPos) { - $attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED; - foreach ($this->semStack[$stackPos-(3-2)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '"', true); } }; $this->semValue = new Scalar\Encapsed($this->semStack[$stackPos-(3-2)], $attrs); - }, - 518 => function ($stackPos) { - $this->semValue = $this->parseLNumber($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 519 => function ($stackPos) { - $this->semValue = Scalar\DNumber::fromString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 520 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 521 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 522 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 523 => function ($stackPos) { - $this->semValue = $this->parseDocString($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)], true); - }, - 524 => function ($stackPos) { - $this->semValue = $this->parseDocString($this->semStack[$stackPos-(2-1)], '', $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(2-2)] + $this->endAttributeStack[$stackPos-(2-2)], true); - }, - 525 => function ($stackPos) { - $this->semValue = $this->parseDocString($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)], true); - }, - 526 => function ($stackPos) { - $this->semValue = null; - }, - 527 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 528 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 529 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 530 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 531 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 532 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 533 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 534 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 535 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 536 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 537 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 538 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 539 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 540 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 541 => function ($stackPos) { - $this->semValue = new Expr\MethodCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 542 => function ($stackPos) { - $this->semValue = new Expr\NullsafeMethodCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 543 => function ($stackPos) { - $this->semValue = null; - }, - 544 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 545 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 546 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 547 => function ($stackPos) { - $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 548 => function ($stackPos) { - $this->semValue = new Expr\NullsafePropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 549 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 550 => function ($stackPos) { - $this->semValue = new Expr\Variable($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 551 => function ($stackPos) { - $this->semValue = new Expr\Variable($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 552 => function ($stackPos) { - $this->semValue = new Expr\Variable(new Expr\Error($this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes), $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); $this->errorState = 2; - }, - 553 => function ($stackPos) { - $var = $this->semStack[$stackPos-(1-1)]->name; $this->semValue = \is_string($var) ? new Node\VarLikeIdentifier($var, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes) : $var; - }, - 554 => function ($stackPos) { - $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 555 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 556 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 557 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 558 => function ($stackPos) { - $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 559 => function ($stackPos) { - $this->semValue = new Expr\NullsafePropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 560 => function ($stackPos) { - $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 561 => function ($stackPos) { - $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 562 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 563 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 564 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 565 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 566 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 567 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 568 => function ($stackPos) { - $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2; - }, - 569 => function ($stackPos) { - $this->semValue = new Expr\List_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 570 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; $end = count($this->semValue)-1; if ($this->semValue[$end] === null) array_pop($this->semValue); - }, - 571 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos]; - }, - 572 => function ($stackPos) { - /* do nothing -- prevent default action of $$=$this->semStack[$1]. See $551. */ - }, - 573 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 574 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 575 => function ($stackPos) { - $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 576 => function ($stackPos) { - $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 577 => function ($stackPos) { - $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 578 => function ($stackPos) { - $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 579 => function ($stackPos) { - $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(4-4)], $this->semStack[$stackPos-(4-1)], true, $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 580 => function ($stackPos) { - $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 581 => function ($stackPos) { - $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 582 => function ($stackPos) { - $this->semValue = null; - }, - 583 => function ($stackPos) { - $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 584 => function ($stackPos) { - $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 585 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 586 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); - }, - 587 => function ($stackPos) { - $this->semValue = new Scalar\EncapsedStringPart($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 588 => function ($stackPos) { - $this->semValue = new Expr\Variable($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 589 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 590 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 591 => function ($stackPos) { - $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 592 => function ($stackPos) { - $this->semValue = new Expr\NullsafePropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 593 => function ($stackPos) { - $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 594 => function ($stackPos) { - $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 595 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-4)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); - }, - 596 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 597 => function ($stackPos) { - $this->semValue = new Scalar\String_($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 598 => function ($stackPos) { - $this->semValue = $this->parseNumString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 599 => function ($stackPos) { - $this->semValue = $this->parseNumString('-' . $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 600 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - ]; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/Parser/Tokens.php b/lib/nikic/php-parser/lib/PhpParser/Parser/Tokens.php deleted file mode 100644 index b76a5d94c..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/Parser/Tokens.php +++ /dev/null @@ -1,148 +0,0 @@ -<?php - -namespace PhpParser\Parser; - -/* GENERATED file based on grammar/tokens.y */ -final class Tokens -{ - const YYERRTOK = 256; - const T_THROW = 257; - const T_INCLUDE = 258; - const T_INCLUDE_ONCE = 259; - const T_EVAL = 260; - const T_REQUIRE = 261; - const T_REQUIRE_ONCE = 262; - const T_LOGICAL_OR = 263; - const T_LOGICAL_XOR = 264; - const T_LOGICAL_AND = 265; - const T_PRINT = 266; - const T_YIELD = 267; - const T_DOUBLE_ARROW = 268; - const T_YIELD_FROM = 269; - const T_PLUS_EQUAL = 270; - const T_MINUS_EQUAL = 271; - const T_MUL_EQUAL = 272; - const T_DIV_EQUAL = 273; - const T_CONCAT_EQUAL = 274; - const T_MOD_EQUAL = 275; - const T_AND_EQUAL = 276; - const T_OR_EQUAL = 277; - const T_XOR_EQUAL = 278; - const T_SL_EQUAL = 279; - const T_SR_EQUAL = 280; - const T_POW_EQUAL = 281; - const T_COALESCE_EQUAL = 282; - const T_COALESCE = 283; - const T_BOOLEAN_OR = 284; - const T_BOOLEAN_AND = 285; - const T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG = 286; - const T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG = 287; - const T_IS_EQUAL = 288; - const T_IS_NOT_EQUAL = 289; - const T_IS_IDENTICAL = 290; - const T_IS_NOT_IDENTICAL = 291; - const T_SPACESHIP = 292; - const T_IS_SMALLER_OR_EQUAL = 293; - const T_IS_GREATER_OR_EQUAL = 294; - const T_SL = 295; - const T_SR = 296; - const T_INSTANCEOF = 297; - const T_INC = 298; - const T_DEC = 299; - const T_INT_CAST = 300; - const T_DOUBLE_CAST = 301; - const T_STRING_CAST = 302; - const T_ARRAY_CAST = 303; - const T_OBJECT_CAST = 304; - const T_BOOL_CAST = 305; - const T_UNSET_CAST = 306; - const T_POW = 307; - const T_NEW = 308; - const T_CLONE = 309; - const T_EXIT = 310; - const T_IF = 311; - const T_ELSEIF = 312; - const T_ELSE = 313; - const T_ENDIF = 314; - const T_LNUMBER = 315; - const T_DNUMBER = 316; - const T_STRING = 317; - const T_STRING_VARNAME = 318; - const T_VARIABLE = 319; - const T_NUM_STRING = 320; - const T_INLINE_HTML = 321; - const T_ENCAPSED_AND_WHITESPACE = 322; - const T_CONSTANT_ENCAPSED_STRING = 323; - const T_ECHO = 324; - const T_DO = 325; - const T_WHILE = 326; - const T_ENDWHILE = 327; - const T_FOR = 328; - const T_ENDFOR = 329; - const T_FOREACH = 330; - const T_ENDFOREACH = 331; - const T_DECLARE = 332; - const T_ENDDECLARE = 333; - const T_AS = 334; - const T_SWITCH = 335; - const T_MATCH = 336; - const T_ENDSWITCH = 337; - const T_CASE = 338; - const T_DEFAULT = 339; - const T_BREAK = 340; - const T_CONTINUE = 341; - const T_GOTO = 342; - const T_FUNCTION = 343; - const T_FN = 344; - const T_CONST = 345; - const T_RETURN = 346; - const T_TRY = 347; - const T_CATCH = 348; - const T_FINALLY = 349; - const T_USE = 350; - const T_INSTEADOF = 351; - const T_GLOBAL = 352; - const T_STATIC = 353; - const T_ABSTRACT = 354; - const T_FINAL = 355; - const T_PRIVATE = 356; - const T_PROTECTED = 357; - const T_PUBLIC = 358; - const T_READONLY = 359; - const T_VAR = 360; - const T_UNSET = 361; - const T_ISSET = 362; - const T_EMPTY = 363; - const T_HALT_COMPILER = 364; - const T_CLASS = 365; - const T_TRAIT = 366; - const T_INTERFACE = 367; - const T_ENUM = 368; - const T_EXTENDS = 369; - const T_IMPLEMENTS = 370; - const T_OBJECT_OPERATOR = 371; - const T_NULLSAFE_OBJECT_OPERATOR = 372; - const T_LIST = 373; - const T_ARRAY = 374; - const T_CALLABLE = 375; - const T_CLASS_C = 376; - const T_TRAIT_C = 377; - const T_METHOD_C = 378; - const T_FUNC_C = 379; - const T_LINE = 380; - const T_FILE = 381; - const T_START_HEREDOC = 382; - const T_END_HEREDOC = 383; - const T_DOLLAR_OPEN_CURLY_BRACES = 384; - const T_CURLY_OPEN = 385; - const T_PAAMAYIM_NEKUDOTAYIM = 386; - const T_NAMESPACE = 387; - const T_NS_C = 388; - const T_DIR = 389; - const T_NS_SEPARATOR = 390; - const T_ELLIPSIS = 391; - const T_NAME_FULLY_QUALIFIED = 392; - const T_NAME_QUALIFIED = 393; - const T_NAME_RELATIVE = 394; - const T_ATTRIBUTE = 395; -} diff --git a/lib/nikic/php-parser/lib/PhpParser/ParserAbstract.php b/lib/nikic/php-parser/lib/PhpParser/ParserAbstract.php deleted file mode 100644 index d485d78de..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/ParserAbstract.php +++ /dev/null @@ -1,1038 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser; - -/* - * This parser is based on a skeleton written by Moriyoshi Koizumi, which in - * turn is based on work by Masato Bito. - */ -use PhpParser\Node\Expr; -use PhpParser\Node\Expr\Cast\Double; -use PhpParser\Node\Name; -use PhpParser\Node\Param; -use PhpParser\Node\Scalar\Encapsed; -use PhpParser\Node\Scalar\LNumber; -use PhpParser\Node\Scalar\String_; -use PhpParser\Node\Stmt\Class_; -use PhpParser\Node\Stmt\ClassConst; -use PhpParser\Node\Stmt\ClassMethod; -use PhpParser\Node\Stmt\Enum_; -use PhpParser\Node\Stmt\Interface_; -use PhpParser\Node\Stmt\Namespace_; -use PhpParser\Node\Stmt\Property; -use PhpParser\Node\Stmt\TryCatch; -use PhpParser\Node\Stmt\UseUse; -use PhpParser\Node\VarLikeIdentifier; - -abstract class ParserAbstract implements Parser -{ - const SYMBOL_NONE = -1; - - /* - * The following members will be filled with generated parsing data: - */ - - /** @var int Size of $tokenToSymbol map */ - protected $tokenToSymbolMapSize; - /** @var int Size of $action table */ - protected $actionTableSize; - /** @var int Size of $goto table */ - protected $gotoTableSize; - - /** @var int Symbol number signifying an invalid token */ - protected $invalidSymbol; - /** @var int Symbol number of error recovery token */ - protected $errorSymbol; - /** @var int Action number signifying default action */ - protected $defaultAction; - /** @var int Rule number signifying that an unexpected token was encountered */ - protected $unexpectedTokenRule; - - protected $YY2TBLSTATE; - /** @var int Number of non-leaf states */ - protected $numNonLeafStates; - - /** @var int[] Map of lexer tokens to internal symbols */ - protected $tokenToSymbol; - /** @var string[] Map of symbols to their names */ - protected $symbolToName; - /** @var array Names of the production rules (only necessary for debugging) */ - protected $productions; - - /** @var int[] Map of states to a displacement into the $action table. The corresponding action for this - * state/symbol pair is $action[$actionBase[$state] + $symbol]. If $actionBase[$state] is 0, the - * action is defaulted, i.e. $actionDefault[$state] should be used instead. */ - protected $actionBase; - /** @var int[] Table of actions. Indexed according to $actionBase comment. */ - protected $action; - /** @var int[] Table indexed analogously to $action. If $actionCheck[$actionBase[$state] + $symbol] != $symbol - * then the action is defaulted, i.e. $actionDefault[$state] should be used instead. */ - protected $actionCheck; - /** @var int[] Map of states to their default action */ - protected $actionDefault; - /** @var callable[] Semantic action callbacks */ - protected $reduceCallbacks; - - /** @var int[] Map of non-terminals to a displacement into the $goto table. The corresponding goto state for this - * non-terminal/state pair is $goto[$gotoBase[$nonTerminal] + $state] (unless defaulted) */ - protected $gotoBase; - /** @var int[] Table of states to goto after reduction. Indexed according to $gotoBase comment. */ - protected $goto; - /** @var int[] Table indexed analogously to $goto. If $gotoCheck[$gotoBase[$nonTerminal] + $state] != $nonTerminal - * then the goto state is defaulted, i.e. $gotoDefault[$nonTerminal] should be used. */ - protected $gotoCheck; - /** @var int[] Map of non-terminals to the default state to goto after their reduction */ - protected $gotoDefault; - - /** @var int[] Map of rules to the non-terminal on their left-hand side, i.e. the non-terminal to use for - * determining the state to goto after reduction. */ - protected $ruleToNonTerminal; - /** @var int[] Map of rules to the length of their right-hand side, which is the number of elements that have to - * be popped from the stack(s) on reduction. */ - protected $ruleToLength; - - /* - * The following members are part of the parser state: - */ - - /** @var Lexer Lexer that is used when parsing */ - protected $lexer; - /** @var mixed Temporary value containing the result of last semantic action (reduction) */ - protected $semValue; - /** @var array Semantic value stack (contains values of tokens and semantic action results) */ - protected $semStack; - /** @var array[] Start attribute stack */ - protected $startAttributeStack; - /** @var array[] End attribute stack */ - protected $endAttributeStack; - /** @var array End attributes of last *shifted* token */ - protected $endAttributes; - /** @var array Start attributes of last *read* token */ - protected $lookaheadStartAttributes; - - /** @var ErrorHandler Error handler */ - protected $errorHandler; - /** @var int Error state, used to avoid error floods */ - protected $errorState; - - /** - * Initialize $reduceCallbacks map. - */ - abstract protected function initReduceCallbacks(); - - /** - * Creates a parser instance. - * - * Options: Currently none. - * - * @param Lexer $lexer A lexer - * @param array $options Options array. - */ - public function __construct(Lexer $lexer, array $options = []) { - $this->lexer = $lexer; - - if (isset($options['throwOnError'])) { - throw new \LogicException( - '"throwOnError" is no longer supported, use "errorHandler" instead'); - } - - $this->initReduceCallbacks(); - } - - /** - * Parses PHP code into a node tree. - * - * If a non-throwing error handler is used, the parser will continue parsing after an error - * occurred and attempt to build a partial AST. - * - * @param string $code The source code to parse - * @param ErrorHandler|null $errorHandler Error handler to use for lexer/parser errors, defaults - * to ErrorHandler\Throwing. - * - * @return Node\Stmt[]|null Array of statements (or null non-throwing error handler is used and - * the parser was unable to recover from an error). - */ - public function parse(string $code, ErrorHandler $errorHandler = null) { - $this->errorHandler = $errorHandler ?: new ErrorHandler\Throwing; - - $this->lexer->startLexing($code, $this->errorHandler); - $result = $this->doParse(); - - // Clear out some of the interior state, so we don't hold onto unnecessary - // memory between uses of the parser - $this->startAttributeStack = []; - $this->endAttributeStack = []; - $this->semStack = []; - $this->semValue = null; - - return $result; - } - - protected function doParse() { - // We start off with no lookahead-token - $symbol = self::SYMBOL_NONE; - - // The attributes for a node are taken from the first and last token of the node. - // From the first token only the startAttributes are taken and from the last only - // the endAttributes. Both are merged using the array union operator (+). - $startAttributes = []; - $endAttributes = []; - $this->endAttributes = $endAttributes; - - // Keep stack of start and end attributes - $this->startAttributeStack = []; - $this->endAttributeStack = [$endAttributes]; - - // Start off in the initial state and keep a stack of previous states - $state = 0; - $stateStack = [$state]; - - // Semantic value stack (contains values of tokens and semantic action results) - $this->semStack = []; - - // Current position in the stack(s) - $stackPos = 0; - - $this->errorState = 0; - - for (;;) { - //$this->traceNewState($state, $symbol); - - if ($this->actionBase[$state] === 0) { - $rule = $this->actionDefault[$state]; - } else { - if ($symbol === self::SYMBOL_NONE) { - // Fetch the next token id from the lexer and fetch additional info by-ref. - // The end attributes are fetched into a temporary variable and only set once the token is really - // shifted (not during read). Otherwise you would sometimes get off-by-one errors, when a rule is - // reduced after a token was read but not yet shifted. - $tokenId = $this->lexer->getNextToken($tokenValue, $startAttributes, $endAttributes); - - // map the lexer token id to the internally used symbols - $symbol = $tokenId >= 0 && $tokenId < $this->tokenToSymbolMapSize - ? $this->tokenToSymbol[$tokenId] - : $this->invalidSymbol; - - if ($symbol === $this->invalidSymbol) { - throw new \RangeException(sprintf( - 'The lexer returned an invalid token (id=%d, value=%s)', - $tokenId, $tokenValue - )); - } - - // Allow productions to access the start attributes of the lookahead token. - $this->lookaheadStartAttributes = $startAttributes; - - //$this->traceRead($symbol); - } - - $idx = $this->actionBase[$state] + $symbol; - if ((($idx >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol) - || ($state < $this->YY2TBLSTATE - && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $symbol) >= 0 - && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol)) - && ($action = $this->action[$idx]) !== $this->defaultAction) { - /* - * >= numNonLeafStates: shift and reduce - * > 0: shift - * = 0: accept - * < 0: reduce - * = -YYUNEXPECTED: error - */ - if ($action > 0) { - /* shift */ - //$this->traceShift($symbol); - - ++$stackPos; - $stateStack[$stackPos] = $state = $action; - $this->semStack[$stackPos] = $tokenValue; - $this->startAttributeStack[$stackPos] = $startAttributes; - $this->endAttributeStack[$stackPos] = $endAttributes; - $this->endAttributes = $endAttributes; - $symbol = self::SYMBOL_NONE; - - if ($this->errorState) { - --$this->errorState; - } - - if ($action < $this->numNonLeafStates) { - continue; - } - - /* $yyn >= numNonLeafStates means shift-and-reduce */ - $rule = $action - $this->numNonLeafStates; - } else { - $rule = -$action; - } - } else { - $rule = $this->actionDefault[$state]; - } - } - - for (;;) { - if ($rule === 0) { - /* accept */ - //$this->traceAccept(); - return $this->semValue; - } elseif ($rule !== $this->unexpectedTokenRule) { - /* reduce */ - //$this->traceReduce($rule); - - try { - $this->reduceCallbacks[$rule]($stackPos); - } catch (Error $e) { - if (-1 === $e->getStartLine() && isset($startAttributes['startLine'])) { - $e->setStartLine($startAttributes['startLine']); - } - - $this->emitError($e); - // Can't recover from this type of error - return null; - } - - /* Goto - shift nonterminal */ - $lastEndAttributes = $this->endAttributeStack[$stackPos]; - $ruleLength = $this->ruleToLength[$rule]; - $stackPos -= $ruleLength; - $nonTerminal = $this->ruleToNonTerminal[$rule]; - $idx = $this->gotoBase[$nonTerminal] + $stateStack[$stackPos]; - if ($idx >= 0 && $idx < $this->gotoTableSize && $this->gotoCheck[$idx] === $nonTerminal) { - $state = $this->goto[$idx]; - } else { - $state = $this->gotoDefault[$nonTerminal]; - } - - ++$stackPos; - $stateStack[$stackPos] = $state; - $this->semStack[$stackPos] = $this->semValue; - $this->endAttributeStack[$stackPos] = $lastEndAttributes; - if ($ruleLength === 0) { - // Empty productions use the start attributes of the lookahead token. - $this->startAttributeStack[$stackPos] = $this->lookaheadStartAttributes; - } - } else { - /* error */ - switch ($this->errorState) { - case 0: - $msg = $this->getErrorMessage($symbol, $state); - $this->emitError(new Error($msg, $startAttributes + $endAttributes)); - // Break missing intentionally - case 1: - case 2: - $this->errorState = 3; - - // Pop until error-expecting state uncovered - while (!( - (($idx = $this->actionBase[$state] + $this->errorSymbol) >= 0 - && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $this->errorSymbol) - || ($state < $this->YY2TBLSTATE - && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $this->errorSymbol) >= 0 - && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $this->errorSymbol) - ) || ($action = $this->action[$idx]) === $this->defaultAction) { // Not totally sure about this - if ($stackPos <= 0) { - // Could not recover from error - return null; - } - $state = $stateStack[--$stackPos]; - //$this->tracePop($state); - } - - //$this->traceShift($this->errorSymbol); - ++$stackPos; - $stateStack[$stackPos] = $state = $action; - - // We treat the error symbol as being empty, so we reset the end attributes - // to the end attributes of the last non-error symbol - $this->startAttributeStack[$stackPos] = $this->lookaheadStartAttributes; - $this->endAttributeStack[$stackPos] = $this->endAttributeStack[$stackPos - 1]; - $this->endAttributes = $this->endAttributeStack[$stackPos - 1]; - break; - - case 3: - if ($symbol === 0) { - // Reached EOF without recovering from error - return null; - } - - //$this->traceDiscard($symbol); - $symbol = self::SYMBOL_NONE; - break 2; - } - } - - if ($state < $this->numNonLeafStates) { - break; - } - - /* >= numNonLeafStates means shift-and-reduce */ - $rule = $state - $this->numNonLeafStates; - } - } - - throw new \RuntimeException('Reached end of parser loop'); - } - - protected function emitError(Error $error) { - $this->errorHandler->handleError($error); - } - - /** - * Format error message including expected tokens. - * - * @param int $symbol Unexpected symbol - * @param int $state State at time of error - * - * @return string Formatted error message - */ - protected function getErrorMessage(int $symbol, int $state) : string { - $expectedString = ''; - if ($expected = $this->getExpectedTokens($state)) { - $expectedString = ', expecting ' . implode(' or ', $expected); - } - - return 'Syntax error, unexpected ' . $this->symbolToName[$symbol] . $expectedString; - } - - /** - * Get limited number of expected tokens in given state. - * - * @param int $state State - * - * @return string[] Expected tokens. If too many, an empty array is returned. - */ - protected function getExpectedTokens(int $state) : array { - $expected = []; - - $base = $this->actionBase[$state]; - foreach ($this->symbolToName as $symbol => $name) { - $idx = $base + $symbol; - if ($idx >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol - || $state < $this->YY2TBLSTATE - && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $symbol) >= 0 - && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol - ) { - if ($this->action[$idx] !== $this->unexpectedTokenRule - && $this->action[$idx] !== $this->defaultAction - && $symbol !== $this->errorSymbol - ) { - if (count($expected) === 4) { - /* Too many expected tokens */ - return []; - } - - $expected[] = $name; - } - } - } - - return $expected; - } - - /* - * Tracing functions used for debugging the parser. - */ - - /* - protected function traceNewState($state, $symbol) { - echo '% State ' . $state - . ', Lookahead ' . ($symbol == self::SYMBOL_NONE ? '--none--' : $this->symbolToName[$symbol]) . "\n"; - } - - protected function traceRead($symbol) { - echo '% Reading ' . $this->symbolToName[$symbol] . "\n"; - } - - protected function traceShift($symbol) { - echo '% Shift ' . $this->symbolToName[$symbol] . "\n"; - } - - protected function traceAccept() { - echo "% Accepted.\n"; - } - - protected function traceReduce($n) { - echo '% Reduce by (' . $n . ') ' . $this->productions[$n] . "\n"; - } - - protected function tracePop($state) { - echo '% Recovering, uncovered state ' . $state . "\n"; - } - - protected function traceDiscard($symbol) { - echo '% Discard ' . $this->symbolToName[$symbol] . "\n"; - } - */ - - /* - * Helper functions invoked by semantic actions - */ - - /** - * Moves statements of semicolon-style namespaces into $ns->stmts and checks various error conditions. - * - * @param Node\Stmt[] $stmts - * @return Node\Stmt[] - */ - protected function handleNamespaces(array $stmts) : array { - $hasErrored = false; - $style = $this->getNamespacingStyle($stmts); - if (null === $style) { - // not namespaced, nothing to do - return $stmts; - } elseif ('brace' === $style) { - // For braced namespaces we only have to check that there are no invalid statements between the namespaces - $afterFirstNamespace = false; - foreach ($stmts as $stmt) { - if ($stmt instanceof Node\Stmt\Namespace_) { - $afterFirstNamespace = true; - } elseif (!$stmt instanceof Node\Stmt\HaltCompiler - && !$stmt instanceof Node\Stmt\Nop - && $afterFirstNamespace && !$hasErrored) { - $this->emitError(new Error( - 'No code may exist outside of namespace {}', $stmt->getAttributes())); - $hasErrored = true; // Avoid one error for every statement - } - } - return $stmts; - } else { - // For semicolon namespaces we have to move the statements after a namespace declaration into ->stmts - $resultStmts = []; - $targetStmts =& $resultStmts; - $lastNs = null; - foreach ($stmts as $stmt) { - if ($stmt instanceof Node\Stmt\Namespace_) { - if ($lastNs !== null) { - $this->fixupNamespaceAttributes($lastNs); - } - if ($stmt->stmts === null) { - $stmt->stmts = []; - $targetStmts =& $stmt->stmts; - $resultStmts[] = $stmt; - } else { - // This handles the invalid case of mixed style namespaces - $resultStmts[] = $stmt; - $targetStmts =& $resultStmts; - } - $lastNs = $stmt; - } elseif ($stmt instanceof Node\Stmt\HaltCompiler) { - // __halt_compiler() is not moved into the namespace - $resultStmts[] = $stmt; - } else { - $targetStmts[] = $stmt; - } - } - if ($lastNs !== null) { - $this->fixupNamespaceAttributes($lastNs); - } - return $resultStmts; - } - } - - private function fixupNamespaceAttributes(Node\Stmt\Namespace_ $stmt) { - // We moved the statements into the namespace node, as such the end of the namespace node - // needs to be extended to the end of the statements. - if (empty($stmt->stmts)) { - return; - } - - // We only move the builtin end attributes here. This is the best we can do with the - // knowledge we have. - $endAttributes = ['endLine', 'endFilePos', 'endTokenPos']; - $lastStmt = $stmt->stmts[count($stmt->stmts) - 1]; - foreach ($endAttributes as $endAttribute) { - if ($lastStmt->hasAttribute($endAttribute)) { - $stmt->setAttribute($endAttribute, $lastStmt->getAttribute($endAttribute)); - } - } - } - - /** - * Determine namespacing style (semicolon or brace) - * - * @param Node[] $stmts Top-level statements. - * - * @return null|string One of "semicolon", "brace" or null (no namespaces) - */ - private function getNamespacingStyle(array $stmts) { - $style = null; - $hasNotAllowedStmts = false; - foreach ($stmts as $i => $stmt) { - if ($stmt instanceof Node\Stmt\Namespace_) { - $currentStyle = null === $stmt->stmts ? 'semicolon' : 'brace'; - if (null === $style) { - $style = $currentStyle; - if ($hasNotAllowedStmts) { - $this->emitError(new Error( - 'Namespace declaration statement has to be the very first statement in the script', - $stmt->getLine() // Avoid marking the entire namespace as an error - )); - } - } elseif ($style !== $currentStyle) { - $this->emitError(new Error( - 'Cannot mix bracketed namespace declarations with unbracketed namespace declarations', - $stmt->getLine() // Avoid marking the entire namespace as an error - )); - // Treat like semicolon style for namespace normalization - return 'semicolon'; - } - continue; - } - - /* declare(), __halt_compiler() and nops can be used before a namespace declaration */ - if ($stmt instanceof Node\Stmt\Declare_ - || $stmt instanceof Node\Stmt\HaltCompiler - || $stmt instanceof Node\Stmt\Nop) { - continue; - } - - /* There may be a hashbang line at the very start of the file */ - if ($i === 0 && $stmt instanceof Node\Stmt\InlineHTML && preg_match('/\A#!.*\r?\n\z/', $stmt->value)) { - continue; - } - - /* Everything else if forbidden before namespace declarations */ - $hasNotAllowedStmts = true; - } - return $style; - } - - /** - * Fix up parsing of static property calls in PHP 5. - * - * In PHP 5 A::$b[c][d] and A::$b[c][d]() have very different interpretation. The former is - * interpreted as (A::$b)[c][d], while the latter is the same as A::{$b[c][d]}(). We parse the - * latter as the former initially and this method fixes the AST into the correct form when we - * encounter the "()". - * - * @param Node\Expr\StaticPropertyFetch|Node\Expr\ArrayDimFetch $prop - * @param Node\Arg[] $args - * @param array $attributes - * - * @return Expr\StaticCall - */ - protected function fixupPhp5StaticPropCall($prop, array $args, array $attributes) : Expr\StaticCall { - if ($prop instanceof Node\Expr\StaticPropertyFetch) { - $name = $prop->name instanceof VarLikeIdentifier - ? $prop->name->toString() : $prop->name; - $var = new Expr\Variable($name, $prop->name->getAttributes()); - return new Expr\StaticCall($prop->class, $var, $args, $attributes); - } elseif ($prop instanceof Node\Expr\ArrayDimFetch) { - $tmp = $prop; - while ($tmp->var instanceof Node\Expr\ArrayDimFetch) { - $tmp = $tmp->var; - } - - /** @var Expr\StaticPropertyFetch $staticProp */ - $staticProp = $tmp->var; - - // Set start attributes to attributes of innermost node - $tmp = $prop; - $this->fixupStartAttributes($tmp, $staticProp->name); - while ($tmp->var instanceof Node\Expr\ArrayDimFetch) { - $tmp = $tmp->var; - $this->fixupStartAttributes($tmp, $staticProp->name); - } - - $name = $staticProp->name instanceof VarLikeIdentifier - ? $staticProp->name->toString() : $staticProp->name; - $tmp->var = new Expr\Variable($name, $staticProp->name->getAttributes()); - return new Expr\StaticCall($staticProp->class, $prop, $args, $attributes); - } else { - throw new \Exception; - } - } - - protected function fixupStartAttributes(Node $to, Node $from) { - $startAttributes = ['startLine', 'startFilePos', 'startTokenPos']; - foreach ($startAttributes as $startAttribute) { - if ($from->hasAttribute($startAttribute)) { - $to->setAttribute($startAttribute, $from->getAttribute($startAttribute)); - } - } - } - - protected function handleBuiltinTypes(Name $name) { - $builtinTypes = [ - 'bool' => true, - 'int' => true, - 'float' => true, - 'string' => true, - 'iterable' => true, - 'void' => true, - 'object' => true, - 'null' => true, - 'false' => true, - 'mixed' => true, - 'never' => true, - ]; - - if (!$name->isUnqualified()) { - return $name; - } - - $lowerName = $name->toLowerString(); - if (!isset($builtinTypes[$lowerName])) { - return $name; - } - - return new Node\Identifier($lowerName, $name->getAttributes()); - } - - /** - * Get combined start and end attributes at a stack location - * - * @param int $pos Stack location - * - * @return array Combined start and end attributes - */ - protected function getAttributesAt(int $pos) : array { - return $this->startAttributeStack[$pos] + $this->endAttributeStack[$pos]; - } - - protected function getFloatCastKind(string $cast): int - { - $cast = strtolower($cast); - if (strpos($cast, 'float') !== false) { - return Double::KIND_FLOAT; - } - - if (strpos($cast, 'real') !== false) { - return Double::KIND_REAL; - } - - return Double::KIND_DOUBLE; - } - - protected function parseLNumber($str, $attributes, $allowInvalidOctal = false) { - try { - return LNumber::fromString($str, $attributes, $allowInvalidOctal); - } catch (Error $error) { - $this->emitError($error); - // Use dummy value - return new LNumber(0, $attributes); - } - } - - /** - * Parse a T_NUM_STRING token into either an integer or string node. - * - * @param string $str Number string - * @param array $attributes Attributes - * - * @return LNumber|String_ Integer or string node. - */ - protected function parseNumString(string $str, array $attributes) { - if (!preg_match('/^(?:0|-?[1-9][0-9]*)$/', $str)) { - return new String_($str, $attributes); - } - - $num = +$str; - if (!is_int($num)) { - return new String_($str, $attributes); - } - - return new LNumber($num, $attributes); - } - - protected function stripIndentation( - string $string, int $indentLen, string $indentChar, - bool $newlineAtStart, bool $newlineAtEnd, array $attributes - ) { - if ($indentLen === 0) { - return $string; - } - - $start = $newlineAtStart ? '(?:(?<=\n)|\A)' : '(?<=\n)'; - $end = $newlineAtEnd ? '(?:(?=[\r\n])|\z)' : '(?=[\r\n])'; - $regex = '/' . $start . '([ \t]*)(' . $end . ')?/'; - return preg_replace_callback( - $regex, - function ($matches) use ($indentLen, $indentChar, $attributes) { - $prefix = substr($matches[1], 0, $indentLen); - if (false !== strpos($prefix, $indentChar === " " ? "\t" : " ")) { - $this->emitError(new Error( - 'Invalid indentation - tabs and spaces cannot be mixed', $attributes - )); - } elseif (strlen($prefix) < $indentLen && !isset($matches[2])) { - $this->emitError(new Error( - 'Invalid body indentation level ' . - '(expecting an indentation level of at least ' . $indentLen . ')', - $attributes - )); - } - return substr($matches[0], strlen($prefix)); - }, - $string - ); - } - - protected function parseDocString( - string $startToken, $contents, string $endToken, - array $attributes, array $endTokenAttributes, bool $parseUnicodeEscape - ) { - $kind = strpos($startToken, "'") === false - ? String_::KIND_HEREDOC : String_::KIND_NOWDOC; - - $regex = '/\A[bB]?<<<[ \t]*[\'"]?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)[\'"]?(?:\r\n|\n|\r)\z/'; - $result = preg_match($regex, $startToken, $matches); - assert($result === 1); - $label = $matches[1]; - - $result = preg_match('/\A[ \t]*/', $endToken, $matches); - assert($result === 1); - $indentation = $matches[0]; - - $attributes['kind'] = $kind; - $attributes['docLabel'] = $label; - $attributes['docIndentation'] = $indentation; - - $indentHasSpaces = false !== strpos($indentation, " "); - $indentHasTabs = false !== strpos($indentation, "\t"); - if ($indentHasSpaces && $indentHasTabs) { - $this->emitError(new Error( - 'Invalid indentation - tabs and spaces cannot be mixed', - $endTokenAttributes - )); - - // Proceed processing as if this doc string is not indented - $indentation = ''; - } - - $indentLen = \strlen($indentation); - $indentChar = $indentHasSpaces ? " " : "\t"; - - if (\is_string($contents)) { - if ($contents === '') { - return new String_('', $attributes); - } - - $contents = $this->stripIndentation( - $contents, $indentLen, $indentChar, true, true, $attributes - ); - $contents = preg_replace('~(\r\n|\n|\r)\z~', '', $contents); - - if ($kind === String_::KIND_HEREDOC) { - $contents = String_::parseEscapeSequences($contents, null, $parseUnicodeEscape); - } - - return new String_($contents, $attributes); - } else { - assert(count($contents) > 0); - if (!$contents[0] instanceof Node\Scalar\EncapsedStringPart) { - // If there is no leading encapsed string part, pretend there is an empty one - $this->stripIndentation( - '', $indentLen, $indentChar, true, false, $contents[0]->getAttributes() - ); - } - - $newContents = []; - foreach ($contents as $i => $part) { - if ($part instanceof Node\Scalar\EncapsedStringPart) { - $isLast = $i === \count($contents) - 1; - $part->value = $this->stripIndentation( - $part->value, $indentLen, $indentChar, - $i === 0, $isLast, $part->getAttributes() - ); - $part->value = String_::parseEscapeSequences($part->value, null, $parseUnicodeEscape); - if ($isLast) { - $part->value = preg_replace('~(\r\n|\n|\r)\z~', '', $part->value); - } - if ('' === $part->value) { - continue; - } - } - $newContents[] = $part; - } - return new Encapsed($newContents, $attributes); - } - } - - /** - * Create attributes for a zero-length common-capturing nop. - * - * @param Comment[] $comments - * @return array - */ - protected function createCommentNopAttributes(array $comments) { - $comment = $comments[count($comments) - 1]; - $commentEndLine = $comment->getEndLine(); - $commentEndFilePos = $comment->getEndFilePos(); - $commentEndTokenPos = $comment->getEndTokenPos(); - - $attributes = ['comments' => $comments]; - if (-1 !== $commentEndLine) { - $attributes['startLine'] = $commentEndLine; - $attributes['endLine'] = $commentEndLine; - } - if (-1 !== $commentEndFilePos) { - $attributes['startFilePos'] = $commentEndFilePos + 1; - $attributes['endFilePos'] = $commentEndFilePos; - } - if (-1 !== $commentEndTokenPos) { - $attributes['startTokenPos'] = $commentEndTokenPos + 1; - $attributes['endTokenPos'] = $commentEndTokenPos; - } - return $attributes; - } - - protected function checkClassModifier($a, $b, $modifierPos) { - try { - Class_::verifyClassModifier($a, $b); - } catch (Error $error) { - $error->setAttributes($this->getAttributesAt($modifierPos)); - $this->emitError($error); - } - } - - protected function checkModifier($a, $b, $modifierPos) { - // Jumping through some hoops here because verifyModifier() is also used elsewhere - try { - Class_::verifyModifier($a, $b); - } catch (Error $error) { - $error->setAttributes($this->getAttributesAt($modifierPos)); - $this->emitError($error); - } - } - - protected function checkParam(Param $node) { - if ($node->variadic && null !== $node->default) { - $this->emitError(new Error( - 'Variadic parameter cannot have a default value', - $node->default->getAttributes() - )); - } - } - - protected function checkTryCatch(TryCatch $node) { - if (empty($node->catches) && null === $node->finally) { - $this->emitError(new Error( - 'Cannot use try without catch or finally', $node->getAttributes() - )); - } - } - - protected function checkNamespace(Namespace_ $node) { - if (null !== $node->stmts) { - foreach ($node->stmts as $stmt) { - if ($stmt instanceof Namespace_) { - $this->emitError(new Error( - 'Namespace declarations cannot be nested', $stmt->getAttributes() - )); - } - } - } - } - - private function checkClassName($name, $namePos) { - if (null !== $name && $name->isSpecialClassName()) { - $this->emitError(new Error( - sprintf('Cannot use \'%s\' as class name as it is reserved', $name), - $this->getAttributesAt($namePos) - )); - } - } - - private function checkImplementedInterfaces(array $interfaces) { - foreach ($interfaces as $interface) { - if ($interface->isSpecialClassName()) { - $this->emitError(new Error( - sprintf('Cannot use \'%s\' as interface name as it is reserved', $interface), - $interface->getAttributes() - )); - } - } - } - - protected function checkClass(Class_ $node, $namePos) { - $this->checkClassName($node->name, $namePos); - - if ($node->extends && $node->extends->isSpecialClassName()) { - $this->emitError(new Error( - sprintf('Cannot use \'%s\' as class name as it is reserved', $node->extends), - $node->extends->getAttributes() - )); - } - - $this->checkImplementedInterfaces($node->implements); - } - - protected function checkInterface(Interface_ $node, $namePos) { - $this->checkClassName($node->name, $namePos); - $this->checkImplementedInterfaces($node->extends); - } - - protected function checkEnum(Enum_ $node, $namePos) { - $this->checkClassName($node->name, $namePos); - $this->checkImplementedInterfaces($node->implements); - } - - protected function checkClassMethod(ClassMethod $node, $modifierPos) { - if ($node->flags & Class_::MODIFIER_STATIC) { - switch ($node->name->toLowerString()) { - case '__construct': - $this->emitError(new Error( - sprintf('Constructor %s() cannot be static', $node->name), - $this->getAttributesAt($modifierPos))); - break; - case '__destruct': - $this->emitError(new Error( - sprintf('Destructor %s() cannot be static', $node->name), - $this->getAttributesAt($modifierPos))); - break; - case '__clone': - $this->emitError(new Error( - sprintf('Clone method %s() cannot be static', $node->name), - $this->getAttributesAt($modifierPos))); - break; - } - } - - if ($node->flags & Class_::MODIFIER_READONLY) { - $this->emitError(new Error( - sprintf('Method %s() cannot be readonly', $node->name), - $this->getAttributesAt($modifierPos))); - } - } - - protected function checkClassConst(ClassConst $node, $modifierPos) { - if ($node->flags & Class_::MODIFIER_STATIC) { - $this->emitError(new Error( - "Cannot use 'static' as constant modifier", - $this->getAttributesAt($modifierPos))); - } - if ($node->flags & Class_::MODIFIER_ABSTRACT) { - $this->emitError(new Error( - "Cannot use 'abstract' as constant modifier", - $this->getAttributesAt($modifierPos))); - } - if ($node->flags & Class_::MODIFIER_READONLY) { - $this->emitError(new Error( - "Cannot use 'readonly' as constant modifier", - $this->getAttributesAt($modifierPos))); - } - } - - protected function checkProperty(Property $node, $modifierPos) { - if ($node->flags & Class_::MODIFIER_ABSTRACT) { - $this->emitError(new Error('Properties cannot be declared abstract', - $this->getAttributesAt($modifierPos))); - } - - if ($node->flags & Class_::MODIFIER_FINAL) { - $this->emitError(new Error('Properties cannot be declared final', - $this->getAttributesAt($modifierPos))); - } - } - - protected function checkUseUse(UseUse $node, $namePos) { - if ($node->alias && $node->alias->isSpecialClassName()) { - $this->emitError(new Error( - sprintf( - 'Cannot use %s as %s because \'%2$s\' is a special class name', - $node->name, $node->alias - ), - $this->getAttributesAt($namePos) - )); - } - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/ParserFactory.php b/lib/nikic/php-parser/lib/PhpParser/ParserFactory.php deleted file mode 100644 index f041e7ffe..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/ParserFactory.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser; - -class ParserFactory -{ - const PREFER_PHP7 = 1; - const PREFER_PHP5 = 2; - const ONLY_PHP7 = 3; - const ONLY_PHP5 = 4; - - /** - * Creates a Parser instance, according to the provided kind. - * - * @param int $kind One of ::PREFER_PHP7, ::PREFER_PHP5, ::ONLY_PHP7 or ::ONLY_PHP5 - * @param Lexer|null $lexer Lexer to use. Defaults to emulative lexer when not specified - * @param array $parserOptions Parser options. See ParserAbstract::__construct() argument - * - * @return Parser The parser instance - */ - public function create(int $kind, Lexer $lexer = null, array $parserOptions = []) : Parser { - if (null === $lexer) { - $lexer = new Lexer\Emulative(); - } - switch ($kind) { - case self::PREFER_PHP7: - return new Parser\Multiple([ - new Parser\Php7($lexer, $parserOptions), new Parser\Php5($lexer, $parserOptions) - ]); - case self::PREFER_PHP5: - return new Parser\Multiple([ - new Parser\Php5($lexer, $parserOptions), new Parser\Php7($lexer, $parserOptions) - ]); - case self::ONLY_PHP7: - return new Parser\Php7($lexer, $parserOptions); - case self::ONLY_PHP5: - return new Parser\Php5($lexer, $parserOptions); - default: - throw new \LogicException( - 'Kind must be one of ::PREFER_PHP7, ::PREFER_PHP5, ::ONLY_PHP7 or ::ONLY_PHP5' - ); - } - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php b/lib/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php deleted file mode 100644 index bb70de659..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php +++ /dev/null @@ -1,1105 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser\PrettyPrinter; - -use PhpParser\Node; -use PhpParser\Node\Expr; -use PhpParser\Node\Expr\AssignOp; -use PhpParser\Node\Expr\BinaryOp; -use PhpParser\Node\Expr\Cast; -use PhpParser\Node\Name; -use PhpParser\Node\Scalar; -use PhpParser\Node\Scalar\MagicConst; -use PhpParser\Node\Stmt; -use PhpParser\PrettyPrinterAbstract; - -class Standard extends PrettyPrinterAbstract -{ - // Special nodes - - protected function pParam(Node\Param $node) { - return $this->pAttrGroups($node->attrGroups, true) - . $this->pModifiers($node->flags) - . ($node->type ? $this->p($node->type) . ' ' : '') - . ($node->byRef ? '&' : '') - . ($node->variadic ? '...' : '') - . $this->p($node->var) - . ($node->default ? ' = ' . $this->p($node->default) : ''); - } - - protected function pArg(Node\Arg $node) { - return ($node->name ? $node->name->toString() . ': ' : '') - . ($node->byRef ? '&' : '') . ($node->unpack ? '...' : '') - . $this->p($node->value); - } - - protected function pVariadicPlaceholder(Node\VariadicPlaceholder $node) { - return '...'; - } - - protected function pConst(Node\Const_ $node) { - return $node->name . ' = ' . $this->p($node->value); - } - - protected function pNullableType(Node\NullableType $node) { - return '?' . $this->p($node->type); - } - - protected function pUnionType(Node\UnionType $node) { - return $this->pImplode($node->types, '|'); - } - - protected function pIntersectionType(Node\IntersectionType $node) { - return $this->pImplode($node->types, '&'); - } - - protected function pIdentifier(Node\Identifier $node) { - return $node->name; - } - - protected function pVarLikeIdentifier(Node\VarLikeIdentifier $node) { - return '$' . $node->name; - } - - protected function pAttribute(Node\Attribute $node) { - return $this->p($node->name) - . ($node->args ? '(' . $this->pCommaSeparated($node->args) . ')' : ''); - } - - protected function pAttributeGroup(Node\AttributeGroup $node) { - return '#[' . $this->pCommaSeparated($node->attrs) . ']'; - } - - // Names - - protected function pName(Name $node) { - return implode('\\', $node->parts); - } - - protected function pName_FullyQualified(Name\FullyQualified $node) { - return '\\' . implode('\\', $node->parts); - } - - protected function pName_Relative(Name\Relative $node) { - return 'namespace\\' . implode('\\', $node->parts); - } - - // Magic Constants - - protected function pScalar_MagicConst_Class(MagicConst\Class_ $node) { - return '__CLASS__'; - } - - protected function pScalar_MagicConst_Dir(MagicConst\Dir $node) { - return '__DIR__'; - } - - protected function pScalar_MagicConst_File(MagicConst\File $node) { - return '__FILE__'; - } - - protected function pScalar_MagicConst_Function(MagicConst\Function_ $node) { - return '__FUNCTION__'; - } - - protected function pScalar_MagicConst_Line(MagicConst\Line $node) { - return '__LINE__'; - } - - protected function pScalar_MagicConst_Method(MagicConst\Method $node) { - return '__METHOD__'; - } - - protected function pScalar_MagicConst_Namespace(MagicConst\Namespace_ $node) { - return '__NAMESPACE__'; - } - - protected function pScalar_MagicConst_Trait(MagicConst\Trait_ $node) { - return '__TRAIT__'; - } - - // Scalars - - protected function pScalar_String(Scalar\String_ $node) { - $kind = $node->getAttribute('kind', Scalar\String_::KIND_SINGLE_QUOTED); - switch ($kind) { - case Scalar\String_::KIND_NOWDOC: - $label = $node->getAttribute('docLabel'); - if ($label && !$this->containsEndLabel($node->value, $label)) { - if ($node->value === '') { - return "<<<'$label'\n$label" . $this->docStringEndToken; - } - - return "<<<'$label'\n$node->value\n$label" - . $this->docStringEndToken; - } - /* break missing intentionally */ - case Scalar\String_::KIND_SINGLE_QUOTED: - return $this->pSingleQuotedString($node->value); - case Scalar\String_::KIND_HEREDOC: - $label = $node->getAttribute('docLabel'); - if ($label && !$this->containsEndLabel($node->value, $label)) { - if ($node->value === '') { - return "<<<$label\n$label" . $this->docStringEndToken; - } - - $escaped = $this->escapeString($node->value, null); - return "<<<$label\n" . $escaped . "\n$label" - . $this->docStringEndToken; - } - /* break missing intentionally */ - case Scalar\String_::KIND_DOUBLE_QUOTED: - return '"' . $this->escapeString($node->value, '"') . '"'; - } - throw new \Exception('Invalid string kind'); - } - - protected function pScalar_Encapsed(Scalar\Encapsed $node) { - if ($node->getAttribute('kind') === Scalar\String_::KIND_HEREDOC) { - $label = $node->getAttribute('docLabel'); - if ($label && !$this->encapsedContainsEndLabel($node->parts, $label)) { - if (count($node->parts) === 1 - && $node->parts[0] instanceof Scalar\EncapsedStringPart - && $node->parts[0]->value === '' - ) { - return "<<<$label\n$label" . $this->docStringEndToken; - } - - return "<<<$label\n" . $this->pEncapsList($node->parts, null) . "\n$label" - . $this->docStringEndToken; - } - } - return '"' . $this->pEncapsList($node->parts, '"') . '"'; - } - - protected function pScalar_LNumber(Scalar\LNumber $node) { - if ($node->value === -\PHP_INT_MAX-1) { - // PHP_INT_MIN cannot be represented as a literal, - // because the sign is not part of the literal - return '(-' . \PHP_INT_MAX . '-1)'; - } - - $kind = $node->getAttribute('kind', Scalar\LNumber::KIND_DEC); - if (Scalar\LNumber::KIND_DEC === $kind) { - return (string) $node->value; - } - - if ($node->value < 0) { - $sign = '-'; - $str = (string) -$node->value; - } else { - $sign = ''; - $str = (string) $node->value; - } - switch ($kind) { - case Scalar\LNumber::KIND_BIN: - return $sign . '0b' . base_convert($str, 10, 2); - case Scalar\LNumber::KIND_OCT: - return $sign . '0' . base_convert($str, 10, 8); - case Scalar\LNumber::KIND_HEX: - return $sign . '0x' . base_convert($str, 10, 16); - } - throw new \Exception('Invalid number kind'); - } - - protected function pScalar_DNumber(Scalar\DNumber $node) { - if (!is_finite($node->value)) { - if ($node->value === \INF) { - return '\INF'; - } elseif ($node->value === -\INF) { - return '-\INF'; - } else { - return '\NAN'; - } - } - - // Try to find a short full-precision representation - $stringValue = sprintf('%.16G', $node->value); - if ($node->value !== (double) $stringValue) { - $stringValue = sprintf('%.17G', $node->value); - } - - // %G is locale dependent and there exists no locale-independent alternative. We don't want - // mess with switching locales here, so let's assume that a comma is the only non-standard - // decimal separator we may encounter... - $stringValue = str_replace(',', '.', $stringValue); - - // ensure that number is really printed as float - return preg_match('/^-?[0-9]+$/', $stringValue) ? $stringValue . '.0' : $stringValue; - } - - protected function pScalar_EncapsedStringPart(Scalar\EncapsedStringPart $node) { - throw new \LogicException('Cannot directly print EncapsedStringPart'); - } - - // Assignments - - protected function pExpr_Assign(Expr\Assign $node) { - return $this->pInfixOp(Expr\Assign::class, $node->var, ' = ', $node->expr); - } - - protected function pExpr_AssignRef(Expr\AssignRef $node) { - return $this->pInfixOp(Expr\AssignRef::class, $node->var, ' =& ', $node->expr); - } - - protected function pExpr_AssignOp_Plus(AssignOp\Plus $node) { - return $this->pInfixOp(AssignOp\Plus::class, $node->var, ' += ', $node->expr); - } - - protected function pExpr_AssignOp_Minus(AssignOp\Minus $node) { - return $this->pInfixOp(AssignOp\Minus::class, $node->var, ' -= ', $node->expr); - } - - protected function pExpr_AssignOp_Mul(AssignOp\Mul $node) { - return $this->pInfixOp(AssignOp\Mul::class, $node->var, ' *= ', $node->expr); - } - - protected function pExpr_AssignOp_Div(AssignOp\Div $node) { - return $this->pInfixOp(AssignOp\Div::class, $node->var, ' /= ', $node->expr); - } - - protected function pExpr_AssignOp_Concat(AssignOp\Concat $node) { - return $this->pInfixOp(AssignOp\Concat::class, $node->var, ' .= ', $node->expr); - } - - protected function pExpr_AssignOp_Mod(AssignOp\Mod $node) { - return $this->pInfixOp(AssignOp\Mod::class, $node->var, ' %= ', $node->expr); - } - - protected function pExpr_AssignOp_BitwiseAnd(AssignOp\BitwiseAnd $node) { - return $this->pInfixOp(AssignOp\BitwiseAnd::class, $node->var, ' &= ', $node->expr); - } - - protected function pExpr_AssignOp_BitwiseOr(AssignOp\BitwiseOr $node) { - return $this->pInfixOp(AssignOp\BitwiseOr::class, $node->var, ' |= ', $node->expr); - } - - protected function pExpr_AssignOp_BitwiseXor(AssignOp\BitwiseXor $node) { - return $this->pInfixOp(AssignOp\BitwiseXor::class, $node->var, ' ^= ', $node->expr); - } - - protected function pExpr_AssignOp_ShiftLeft(AssignOp\ShiftLeft $node) { - return $this->pInfixOp(AssignOp\ShiftLeft::class, $node->var, ' <<= ', $node->expr); - } - - protected function pExpr_AssignOp_ShiftRight(AssignOp\ShiftRight $node) { - return $this->pInfixOp(AssignOp\ShiftRight::class, $node->var, ' >>= ', $node->expr); - } - - protected function pExpr_AssignOp_Pow(AssignOp\Pow $node) { - return $this->pInfixOp(AssignOp\Pow::class, $node->var, ' **= ', $node->expr); - } - - protected function pExpr_AssignOp_Coalesce(AssignOp\Coalesce $node) { - return $this->pInfixOp(AssignOp\Coalesce::class, $node->var, ' ??= ', $node->expr); - } - - // Binary expressions - - protected function pExpr_BinaryOp_Plus(BinaryOp\Plus $node) { - return $this->pInfixOp(BinaryOp\Plus::class, $node->left, ' + ', $node->right); - } - - protected function pExpr_BinaryOp_Minus(BinaryOp\Minus $node) { - return $this->pInfixOp(BinaryOp\Minus::class, $node->left, ' - ', $node->right); - } - - protected function pExpr_BinaryOp_Mul(BinaryOp\Mul $node) { - return $this->pInfixOp(BinaryOp\Mul::class, $node->left, ' * ', $node->right); - } - - protected function pExpr_BinaryOp_Div(BinaryOp\Div $node) { - return $this->pInfixOp(BinaryOp\Div::class, $node->left, ' / ', $node->right); - } - - protected function pExpr_BinaryOp_Concat(BinaryOp\Concat $node) { - return $this->pInfixOp(BinaryOp\Concat::class, $node->left, ' . ', $node->right); - } - - protected function pExpr_BinaryOp_Mod(BinaryOp\Mod $node) { - return $this->pInfixOp(BinaryOp\Mod::class, $node->left, ' % ', $node->right); - } - - protected function pExpr_BinaryOp_BooleanAnd(BinaryOp\BooleanAnd $node) { - return $this->pInfixOp(BinaryOp\BooleanAnd::class, $node->left, ' && ', $node->right); - } - - protected function pExpr_BinaryOp_BooleanOr(BinaryOp\BooleanOr $node) { - return $this->pInfixOp(BinaryOp\BooleanOr::class, $node->left, ' || ', $node->right); - } - - protected function pExpr_BinaryOp_BitwiseAnd(BinaryOp\BitwiseAnd $node) { - return $this->pInfixOp(BinaryOp\BitwiseAnd::class, $node->left, ' & ', $node->right); - } - - protected function pExpr_BinaryOp_BitwiseOr(BinaryOp\BitwiseOr $node) { - return $this->pInfixOp(BinaryOp\BitwiseOr::class, $node->left, ' | ', $node->right); - } - - protected function pExpr_BinaryOp_BitwiseXor(BinaryOp\BitwiseXor $node) { - return $this->pInfixOp(BinaryOp\BitwiseXor::class, $node->left, ' ^ ', $node->right); - } - - protected function pExpr_BinaryOp_ShiftLeft(BinaryOp\ShiftLeft $node) { - return $this->pInfixOp(BinaryOp\ShiftLeft::class, $node->left, ' << ', $node->right); - } - - protected function pExpr_BinaryOp_ShiftRight(BinaryOp\ShiftRight $node) { - return $this->pInfixOp(BinaryOp\ShiftRight::class, $node->left, ' >> ', $node->right); - } - - protected function pExpr_BinaryOp_Pow(BinaryOp\Pow $node) { - return $this->pInfixOp(BinaryOp\Pow::class, $node->left, ' ** ', $node->right); - } - - protected function pExpr_BinaryOp_LogicalAnd(BinaryOp\LogicalAnd $node) { - return $this->pInfixOp(BinaryOp\LogicalAnd::class, $node->left, ' and ', $node->right); - } - - protected function pExpr_BinaryOp_LogicalOr(BinaryOp\LogicalOr $node) { - return $this->pInfixOp(BinaryOp\LogicalOr::class, $node->left, ' or ', $node->right); - } - - protected function pExpr_BinaryOp_LogicalXor(BinaryOp\LogicalXor $node) { - return $this->pInfixOp(BinaryOp\LogicalXor::class, $node->left, ' xor ', $node->right); - } - - protected function pExpr_BinaryOp_Equal(BinaryOp\Equal $node) { - return $this->pInfixOp(BinaryOp\Equal::class, $node->left, ' == ', $node->right); - } - - protected function pExpr_BinaryOp_NotEqual(BinaryOp\NotEqual $node) { - return $this->pInfixOp(BinaryOp\NotEqual::class, $node->left, ' != ', $node->right); - } - - protected function pExpr_BinaryOp_Identical(BinaryOp\Identical $node) { - return $this->pInfixOp(BinaryOp\Identical::class, $node->left, ' === ', $node->right); - } - - protected function pExpr_BinaryOp_NotIdentical(BinaryOp\NotIdentical $node) { - return $this->pInfixOp(BinaryOp\NotIdentical::class, $node->left, ' !== ', $node->right); - } - - protected function pExpr_BinaryOp_Spaceship(BinaryOp\Spaceship $node) { - return $this->pInfixOp(BinaryOp\Spaceship::class, $node->left, ' <=> ', $node->right); - } - - protected function pExpr_BinaryOp_Greater(BinaryOp\Greater $node) { - return $this->pInfixOp(BinaryOp\Greater::class, $node->left, ' > ', $node->right); - } - - protected function pExpr_BinaryOp_GreaterOrEqual(BinaryOp\GreaterOrEqual $node) { - return $this->pInfixOp(BinaryOp\GreaterOrEqual::class, $node->left, ' >= ', $node->right); - } - - protected function pExpr_BinaryOp_Smaller(BinaryOp\Smaller $node) { - return $this->pInfixOp(BinaryOp\Smaller::class, $node->left, ' < ', $node->right); - } - - protected function pExpr_BinaryOp_SmallerOrEqual(BinaryOp\SmallerOrEqual $node) { - return $this->pInfixOp(BinaryOp\SmallerOrEqual::class, $node->left, ' <= ', $node->right); - } - - protected function pExpr_BinaryOp_Coalesce(BinaryOp\Coalesce $node) { - return $this->pInfixOp(BinaryOp\Coalesce::class, $node->left, ' ?? ', $node->right); - } - - protected function pExpr_Instanceof(Expr\Instanceof_ $node) { - list($precedence, $associativity) = $this->precedenceMap[Expr\Instanceof_::class]; - return $this->pPrec($node->expr, $precedence, $associativity, -1) - . ' instanceof ' - . $this->pNewVariable($node->class); - } - - // Unary expressions - - protected function pExpr_BooleanNot(Expr\BooleanNot $node) { - return $this->pPrefixOp(Expr\BooleanNot::class, '!', $node->expr); - } - - protected function pExpr_BitwiseNot(Expr\BitwiseNot $node) { - return $this->pPrefixOp(Expr\BitwiseNot::class, '~', $node->expr); - } - - protected function pExpr_UnaryMinus(Expr\UnaryMinus $node) { - if ($node->expr instanceof Expr\UnaryMinus || $node->expr instanceof Expr\PreDec) { - // Enforce -(-$expr) instead of --$expr - return '-(' . $this->p($node->expr) . ')'; - } - return $this->pPrefixOp(Expr\UnaryMinus::class, '-', $node->expr); - } - - protected function pExpr_UnaryPlus(Expr\UnaryPlus $node) { - if ($node->expr instanceof Expr\UnaryPlus || $node->expr instanceof Expr\PreInc) { - // Enforce +(+$expr) instead of ++$expr - return '+(' . $this->p($node->expr) . ')'; - } - return $this->pPrefixOp(Expr\UnaryPlus::class, '+', $node->expr); - } - - protected function pExpr_PreInc(Expr\PreInc $node) { - return $this->pPrefixOp(Expr\PreInc::class, '++', $node->var); - } - - protected function pExpr_PreDec(Expr\PreDec $node) { - return $this->pPrefixOp(Expr\PreDec::class, '--', $node->var); - } - - protected function pExpr_PostInc(Expr\PostInc $node) { - return $this->pPostfixOp(Expr\PostInc::class, $node->var, '++'); - } - - protected function pExpr_PostDec(Expr\PostDec $node) { - return $this->pPostfixOp(Expr\PostDec::class, $node->var, '--'); - } - - protected function pExpr_ErrorSuppress(Expr\ErrorSuppress $node) { - return $this->pPrefixOp(Expr\ErrorSuppress::class, '@', $node->expr); - } - - protected function pExpr_YieldFrom(Expr\YieldFrom $node) { - return $this->pPrefixOp(Expr\YieldFrom::class, 'yield from ', $node->expr); - } - - protected function pExpr_Print(Expr\Print_ $node) { - return $this->pPrefixOp(Expr\Print_::class, 'print ', $node->expr); - } - - // Casts - - protected function pExpr_Cast_Int(Cast\Int_ $node) { - return $this->pPrefixOp(Cast\Int_::class, '(int) ', $node->expr); - } - - protected function pExpr_Cast_Double(Cast\Double $node) { - $kind = $node->getAttribute('kind', Cast\Double::KIND_DOUBLE); - if ($kind === Cast\Double::KIND_DOUBLE) { - $cast = '(double)'; - } elseif ($kind === Cast\Double::KIND_FLOAT) { - $cast = '(float)'; - } elseif ($kind === Cast\Double::KIND_REAL) { - $cast = '(real)'; - } - return $this->pPrefixOp(Cast\Double::class, $cast . ' ', $node->expr); - } - - protected function pExpr_Cast_String(Cast\String_ $node) { - return $this->pPrefixOp(Cast\String_::class, '(string) ', $node->expr); - } - - protected function pExpr_Cast_Array(Cast\Array_ $node) { - return $this->pPrefixOp(Cast\Array_::class, '(array) ', $node->expr); - } - - protected function pExpr_Cast_Object(Cast\Object_ $node) { - return $this->pPrefixOp(Cast\Object_::class, '(object) ', $node->expr); - } - - protected function pExpr_Cast_Bool(Cast\Bool_ $node) { - return $this->pPrefixOp(Cast\Bool_::class, '(bool) ', $node->expr); - } - - protected function pExpr_Cast_Unset(Cast\Unset_ $node) { - return $this->pPrefixOp(Cast\Unset_::class, '(unset) ', $node->expr); - } - - // Function calls and similar constructs - - protected function pExpr_FuncCall(Expr\FuncCall $node) { - return $this->pCallLhs($node->name) - . '(' . $this->pMaybeMultiline($node->args) . ')'; - } - - protected function pExpr_MethodCall(Expr\MethodCall $node) { - return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name) - . '(' . $this->pMaybeMultiline($node->args) . ')'; - } - - protected function pExpr_NullsafeMethodCall(Expr\NullsafeMethodCall $node) { - return $this->pDereferenceLhs($node->var) . '?->' . $this->pObjectProperty($node->name) - . '(' . $this->pMaybeMultiline($node->args) . ')'; - } - - protected function pExpr_StaticCall(Expr\StaticCall $node) { - return $this->pDereferenceLhs($node->class) . '::' - . ($node->name instanceof Expr - ? ($node->name instanceof Expr\Variable - ? $this->p($node->name) - : '{' . $this->p($node->name) . '}') - : $node->name) - . '(' . $this->pMaybeMultiline($node->args) . ')'; - } - - protected function pExpr_Empty(Expr\Empty_ $node) { - return 'empty(' . $this->p($node->expr) . ')'; - } - - protected function pExpr_Isset(Expr\Isset_ $node) { - return 'isset(' . $this->pCommaSeparated($node->vars) . ')'; - } - - protected function pExpr_Eval(Expr\Eval_ $node) { - return 'eval(' . $this->p($node->expr) . ')'; - } - - protected function pExpr_Include(Expr\Include_ $node) { - static $map = [ - Expr\Include_::TYPE_INCLUDE => 'include', - Expr\Include_::TYPE_INCLUDE_ONCE => 'include_once', - Expr\Include_::TYPE_REQUIRE => 'require', - Expr\Include_::TYPE_REQUIRE_ONCE => 'require_once', - ]; - - return $map[$node->type] . ' ' . $this->p($node->expr); - } - - protected function pExpr_List(Expr\List_ $node) { - return 'list(' . $this->pCommaSeparated($node->items) . ')'; - } - - // Other - - protected function pExpr_Error(Expr\Error $node) { - throw new \LogicException('Cannot pretty-print AST with Error nodes'); - } - - protected function pExpr_Variable(Expr\Variable $node) { - if ($node->name instanceof Expr) { - return '${' . $this->p($node->name) . '}'; - } else { - return '$' . $node->name; - } - } - - protected function pExpr_Array(Expr\Array_ $node) { - $syntax = $node->getAttribute('kind', - $this->options['shortArraySyntax'] ? Expr\Array_::KIND_SHORT : Expr\Array_::KIND_LONG); - if ($syntax === Expr\Array_::KIND_SHORT) { - return '[' . $this->pMaybeMultiline($node->items, true) . ']'; - } else { - return 'array(' . $this->pMaybeMultiline($node->items, true) . ')'; - } - } - - protected function pExpr_ArrayItem(Expr\ArrayItem $node) { - return (null !== $node->key ? $this->p($node->key) . ' => ' : '') - . ($node->byRef ? '&' : '') - . ($node->unpack ? '...' : '') - . $this->p($node->value); - } - - protected function pExpr_ArrayDimFetch(Expr\ArrayDimFetch $node) { - return $this->pDereferenceLhs($node->var) - . '[' . (null !== $node->dim ? $this->p($node->dim) : '') . ']'; - } - - protected function pExpr_ConstFetch(Expr\ConstFetch $node) { - return $this->p($node->name); - } - - protected function pExpr_ClassConstFetch(Expr\ClassConstFetch $node) { - return $this->pDereferenceLhs($node->class) . '::' . $this->p($node->name); - } - - protected function pExpr_PropertyFetch(Expr\PropertyFetch $node) { - return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name); - } - - protected function pExpr_NullsafePropertyFetch(Expr\NullsafePropertyFetch $node) { - return $this->pDereferenceLhs($node->var) . '?->' . $this->pObjectProperty($node->name); - } - - protected function pExpr_StaticPropertyFetch(Expr\StaticPropertyFetch $node) { - return $this->pDereferenceLhs($node->class) . '::$' . $this->pObjectProperty($node->name); - } - - protected function pExpr_ShellExec(Expr\ShellExec $node) { - return '`' . $this->pEncapsList($node->parts, '`') . '`'; - } - - protected function pExpr_Closure(Expr\Closure $node) { - return $this->pAttrGroups($node->attrGroups, true) - . ($node->static ? 'static ' : '') - . 'function ' . ($node->byRef ? '&' : '') - . '(' . $this->pCommaSeparated($node->params) . ')' - . (!empty($node->uses) ? ' use(' . $this->pCommaSeparated($node->uses) . ')' : '') - . (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '') - . ' {' . $this->pStmts($node->stmts) . $this->nl . '}'; - } - - protected function pExpr_Match(Expr\Match_ $node) { - return 'match (' . $this->p($node->cond) . ') {' - . $this->pCommaSeparatedMultiline($node->arms, true) - . $this->nl - . '}'; - } - - protected function pMatchArm(Node\MatchArm $node) { - return ($node->conds ? $this->pCommaSeparated($node->conds) : 'default') - . ' => ' . $this->p($node->body); - } - - protected function pExpr_ArrowFunction(Expr\ArrowFunction $node) { - return $this->pAttrGroups($node->attrGroups, true) - . ($node->static ? 'static ' : '') - . 'fn' . ($node->byRef ? '&' : '') - . '(' . $this->pCommaSeparated($node->params) . ')' - . (null !== $node->returnType ? ': ' . $this->p($node->returnType) : '') - . ' => ' - . $this->p($node->expr); - } - - protected function pExpr_ClosureUse(Expr\ClosureUse $node) { - return ($node->byRef ? '&' : '') . $this->p($node->var); - } - - protected function pExpr_New(Expr\New_ $node) { - if ($node->class instanceof Stmt\Class_) { - $args = $node->args ? '(' . $this->pMaybeMultiline($node->args) . ')' : ''; - return 'new ' . $this->pClassCommon($node->class, $args); - } - return 'new ' . $this->pNewVariable($node->class) - . '(' . $this->pMaybeMultiline($node->args) . ')'; - } - - protected function pExpr_Clone(Expr\Clone_ $node) { - return 'clone ' . $this->p($node->expr); - } - - protected function pExpr_Ternary(Expr\Ternary $node) { - // a bit of cheating: we treat the ternary as a binary op where the ?...: part is the operator. - // this is okay because the part between ? and : never needs parentheses. - return $this->pInfixOp(Expr\Ternary::class, - $node->cond, ' ?' . (null !== $node->if ? ' ' . $this->p($node->if) . ' ' : '') . ': ', $node->else - ); - } - - protected function pExpr_Exit(Expr\Exit_ $node) { - $kind = $node->getAttribute('kind', Expr\Exit_::KIND_DIE); - return ($kind === Expr\Exit_::KIND_EXIT ? 'exit' : 'die') - . (null !== $node->expr ? '(' . $this->p($node->expr) . ')' : ''); - } - - protected function pExpr_Throw(Expr\Throw_ $node) { - return 'throw ' . $this->p($node->expr); - } - - protected function pExpr_Yield(Expr\Yield_ $node) { - if ($node->value === null) { - return 'yield'; - } else { - // this is a bit ugly, but currently there is no way to detect whether the parentheses are necessary - return '(yield ' - . ($node->key !== null ? $this->p($node->key) . ' => ' : '') - . $this->p($node->value) - . ')'; - } - } - - // Declarations - - protected function pStmt_Namespace(Stmt\Namespace_ $node) { - if ($this->canUseSemicolonNamespaces) { - return 'namespace ' . $this->p($node->name) . ';' - . $this->nl . $this->pStmts($node->stmts, false); - } else { - return 'namespace' . (null !== $node->name ? ' ' . $this->p($node->name) : '') - . ' {' . $this->pStmts($node->stmts) . $this->nl . '}'; - } - } - - protected function pStmt_Use(Stmt\Use_ $node) { - return 'use ' . $this->pUseType($node->type) - . $this->pCommaSeparated($node->uses) . ';'; - } - - protected function pStmt_GroupUse(Stmt\GroupUse $node) { - return 'use ' . $this->pUseType($node->type) . $this->pName($node->prefix) - . '\{' . $this->pCommaSeparated($node->uses) . '};'; - } - - protected function pStmt_UseUse(Stmt\UseUse $node) { - return $this->pUseType($node->type) . $this->p($node->name) - . (null !== $node->alias ? ' as ' . $node->alias : ''); - } - - protected function pUseType($type) { - return $type === Stmt\Use_::TYPE_FUNCTION ? 'function ' - : ($type === Stmt\Use_::TYPE_CONSTANT ? 'const ' : ''); - } - - protected function pStmt_Interface(Stmt\Interface_ $node) { - return $this->pAttrGroups($node->attrGroups) - . 'interface ' . $node->name - . (!empty($node->extends) ? ' extends ' . $this->pCommaSeparated($node->extends) : '') - . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; - } - - protected function pStmt_Enum(Stmt\Enum_ $node) { - return $this->pAttrGroups($node->attrGroups) - . 'enum ' . $node->name - . ($node->scalarType ? " : $node->scalarType" : '') - . (!empty($node->implements) ? ' implements ' . $this->pCommaSeparated($node->implements) : '') - . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; - } - - protected function pStmt_Class(Stmt\Class_ $node) { - return $this->pClassCommon($node, ' ' . $node->name); - } - - protected function pStmt_Trait(Stmt\Trait_ $node) { - return $this->pAttrGroups($node->attrGroups) - . 'trait ' . $node->name - . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; - } - - protected function pStmt_EnumCase(Stmt\EnumCase $node) { - return $this->pAttrGroups($node->attrGroups) - . 'case ' . $node->name - . ($node->expr ? ' = ' . $this->p($node->expr) : '') - . ';'; - } - - protected function pStmt_TraitUse(Stmt\TraitUse $node) { - return 'use ' . $this->pCommaSeparated($node->traits) - . (empty($node->adaptations) - ? ';' - : ' {' . $this->pStmts($node->adaptations) . $this->nl . '}'); - } - - protected function pStmt_TraitUseAdaptation_Precedence(Stmt\TraitUseAdaptation\Precedence $node) { - return $this->p($node->trait) . '::' . $node->method - . ' insteadof ' . $this->pCommaSeparated($node->insteadof) . ';'; - } - - protected function pStmt_TraitUseAdaptation_Alias(Stmt\TraitUseAdaptation\Alias $node) { - return (null !== $node->trait ? $this->p($node->trait) . '::' : '') - . $node->method . ' as' - . (null !== $node->newModifier ? ' ' . rtrim($this->pModifiers($node->newModifier), ' ') : '') - . (null !== $node->newName ? ' ' . $node->newName : '') - . ';'; - } - - protected function pStmt_Property(Stmt\Property $node) { - return $this->pAttrGroups($node->attrGroups) - . (0 === $node->flags ? 'var ' : $this->pModifiers($node->flags)) - . ($node->type ? $this->p($node->type) . ' ' : '') - . $this->pCommaSeparated($node->props) . ';'; - } - - protected function pStmt_PropertyProperty(Stmt\PropertyProperty $node) { - return '$' . $node->name - . (null !== $node->default ? ' = ' . $this->p($node->default) : ''); - } - - protected function pStmt_ClassMethod(Stmt\ClassMethod $node) { - return $this->pAttrGroups($node->attrGroups) - . $this->pModifiers($node->flags) - . 'function ' . ($node->byRef ? '&' : '') . $node->name - . '(' . $this->pMaybeMultiline($node->params) . ')' - . (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '') - . (null !== $node->stmts - ? $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}' - : ';'); - } - - protected function pStmt_ClassConst(Stmt\ClassConst $node) { - return $this->pAttrGroups($node->attrGroups) - . $this->pModifiers($node->flags) - . 'const ' . $this->pCommaSeparated($node->consts) . ';'; - } - - protected function pStmt_Function(Stmt\Function_ $node) { - return $this->pAttrGroups($node->attrGroups) - . 'function ' . ($node->byRef ? '&' : '') . $node->name - . '(' . $this->pCommaSeparated($node->params) . ')' - . (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '') - . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; - } - - protected function pStmt_Const(Stmt\Const_ $node) { - return 'const ' . $this->pCommaSeparated($node->consts) . ';'; - } - - protected function pStmt_Declare(Stmt\Declare_ $node) { - return 'declare (' . $this->pCommaSeparated($node->declares) . ')' - . (null !== $node->stmts ? ' {' . $this->pStmts($node->stmts) . $this->nl . '}' : ';'); - } - - protected function pStmt_DeclareDeclare(Stmt\DeclareDeclare $node) { - return $node->key . '=' . $this->p($node->value); - } - - // Control flow - - protected function pStmt_If(Stmt\If_ $node) { - return 'if (' . $this->p($node->cond) . ') {' - . $this->pStmts($node->stmts) . $this->nl . '}' - . ($node->elseifs ? ' ' . $this->pImplode($node->elseifs, ' ') : '') - . (null !== $node->else ? ' ' . $this->p($node->else) : ''); - } - - protected function pStmt_ElseIf(Stmt\ElseIf_ $node) { - return 'elseif (' . $this->p($node->cond) . ') {' - . $this->pStmts($node->stmts) . $this->nl . '}'; - } - - protected function pStmt_Else(Stmt\Else_ $node) { - return 'else {' . $this->pStmts($node->stmts) . $this->nl . '}'; - } - - protected function pStmt_For(Stmt\For_ $node) { - return 'for (' - . $this->pCommaSeparated($node->init) . ';' . (!empty($node->cond) ? ' ' : '') - . $this->pCommaSeparated($node->cond) . ';' . (!empty($node->loop) ? ' ' : '') - . $this->pCommaSeparated($node->loop) - . ') {' . $this->pStmts($node->stmts) . $this->nl . '}'; - } - - protected function pStmt_Foreach(Stmt\Foreach_ $node) { - return 'foreach (' . $this->p($node->expr) . ' as ' - . (null !== $node->keyVar ? $this->p($node->keyVar) . ' => ' : '') - . ($node->byRef ? '&' : '') . $this->p($node->valueVar) . ') {' - . $this->pStmts($node->stmts) . $this->nl . '}'; - } - - protected function pStmt_While(Stmt\While_ $node) { - return 'while (' . $this->p($node->cond) . ') {' - . $this->pStmts($node->stmts) . $this->nl . '}'; - } - - protected function pStmt_Do(Stmt\Do_ $node) { - return 'do {' . $this->pStmts($node->stmts) . $this->nl - . '} while (' . $this->p($node->cond) . ');'; - } - - protected function pStmt_Switch(Stmt\Switch_ $node) { - return 'switch (' . $this->p($node->cond) . ') {' - . $this->pStmts($node->cases) . $this->nl . '}'; - } - - protected function pStmt_Case(Stmt\Case_ $node) { - return (null !== $node->cond ? 'case ' . $this->p($node->cond) : 'default') . ':' - . $this->pStmts($node->stmts); - } - - protected function pStmt_TryCatch(Stmt\TryCatch $node) { - return 'try {' . $this->pStmts($node->stmts) . $this->nl . '}' - . ($node->catches ? ' ' . $this->pImplode($node->catches, ' ') : '') - . ($node->finally !== null ? ' ' . $this->p($node->finally) : ''); - } - - protected function pStmt_Catch(Stmt\Catch_ $node) { - return 'catch (' . $this->pImplode($node->types, '|') - . ($node->var !== null ? ' ' . $this->p($node->var) : '') - . ') {' . $this->pStmts($node->stmts) . $this->nl . '}'; - } - - protected function pStmt_Finally(Stmt\Finally_ $node) { - return 'finally {' . $this->pStmts($node->stmts) . $this->nl . '}'; - } - - protected function pStmt_Break(Stmt\Break_ $node) { - return 'break' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';'; - } - - protected function pStmt_Continue(Stmt\Continue_ $node) { - return 'continue' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';'; - } - - protected function pStmt_Return(Stmt\Return_ $node) { - return 'return' . (null !== $node->expr ? ' ' . $this->p($node->expr) : '') . ';'; - } - - protected function pStmt_Throw(Stmt\Throw_ $node) { - return 'throw ' . $this->p($node->expr) . ';'; - } - - protected function pStmt_Label(Stmt\Label $node) { - return $node->name . ':'; - } - - protected function pStmt_Goto(Stmt\Goto_ $node) { - return 'goto ' . $node->name . ';'; - } - - // Other - - protected function pStmt_Expression(Stmt\Expression $node) { - return $this->p($node->expr) . ';'; - } - - protected function pStmt_Echo(Stmt\Echo_ $node) { - return 'echo ' . $this->pCommaSeparated($node->exprs) . ';'; - } - - protected function pStmt_Static(Stmt\Static_ $node) { - return 'static ' . $this->pCommaSeparated($node->vars) . ';'; - } - - protected function pStmt_Global(Stmt\Global_ $node) { - return 'global ' . $this->pCommaSeparated($node->vars) . ';'; - } - - protected function pStmt_StaticVar(Stmt\StaticVar $node) { - return $this->p($node->var) - . (null !== $node->default ? ' = ' . $this->p($node->default) : ''); - } - - protected function pStmt_Unset(Stmt\Unset_ $node) { - return 'unset(' . $this->pCommaSeparated($node->vars) . ');'; - } - - protected function pStmt_InlineHTML(Stmt\InlineHTML $node) { - $newline = $node->getAttribute('hasLeadingNewline', true) ? "\n" : ''; - return '?>' . $newline . $node->value . '<?php '; - } - - protected function pStmt_HaltCompiler(Stmt\HaltCompiler $node) { - return '__halt_compiler();' . $node->remaining; - } - - protected function pStmt_Nop(Stmt\Nop $node) { - return ''; - } - - // Helpers - - protected function pClassCommon(Stmt\Class_ $node, $afterClassToken) { - return $this->pAttrGroups($node->attrGroups, $node->name === null) - . $this->pModifiers($node->flags) - . 'class' . $afterClassToken - . (null !== $node->extends ? ' extends ' . $this->p($node->extends) : '') - . (!empty($node->implements) ? ' implements ' . $this->pCommaSeparated($node->implements) : '') - . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; - } - - protected function pObjectProperty($node) { - if ($node instanceof Expr) { - return '{' . $this->p($node) . '}'; - } else { - return $node; - } - } - - protected function pEncapsList(array $encapsList, $quote) { - $return = ''; - foreach ($encapsList as $element) { - if ($element instanceof Scalar\EncapsedStringPart) { - $return .= $this->escapeString($element->value, $quote); - } else { - $return .= '{' . $this->p($element) . '}'; - } - } - - return $return; - } - - protected function pSingleQuotedString(string $string) { - return '\'' . addcslashes($string, '\'\\') . '\''; - } - - protected function escapeString($string, $quote) { - if (null === $quote) { - // For doc strings, don't escape newlines - $escaped = addcslashes($string, "\t\f\v$\\"); - } else { - $escaped = addcslashes($string, "\n\r\t\f\v$" . $quote . "\\"); - } - - // Escape control characters and non-UTF-8 characters. - // Regex based on https://stackoverflow.com/a/11709412/385378. - $regex = '/( - [\x00-\x08\x0E-\x1F] # Control characters - | [\xC0-\xC1] # Invalid UTF-8 Bytes - | [\xF5-\xFF] # Invalid UTF-8 Bytes - | \xE0(?=[\x80-\x9F]) # Overlong encoding of prior code point - | \xF0(?=[\x80-\x8F]) # Overlong encoding of prior code point - | [\xC2-\xDF](?![\x80-\xBF]) # Invalid UTF-8 Sequence Start - | [\xE0-\xEF](?![\x80-\xBF]{2}) # Invalid UTF-8 Sequence Start - | [\xF0-\xF4](?![\x80-\xBF]{3}) # Invalid UTF-8 Sequence Start - | (?<=[\x00-\x7F\xF5-\xFF])[\x80-\xBF] # Invalid UTF-8 Sequence Middle - | (?<![\xC2-\xDF]|[\xE0-\xEF]|[\xE0-\xEF][\x80-\xBF]|[\xF0-\xF4]|[\xF0-\xF4][\x80-\xBF]|[\xF0-\xF4][\x80-\xBF]{2})[\x80-\xBF] # Overlong Sequence - | (?<=[\xE0-\xEF])[\x80-\xBF](?![\x80-\xBF]) # Short 3 byte sequence - | (?<=[\xF0-\xF4])[\x80-\xBF](?![\x80-\xBF]{2}) # Short 4 byte sequence - | (?<=[\xF0-\xF4][\x80-\xBF])[\x80-\xBF](?![\x80-\xBF]) # Short 4 byte sequence (2) - )/x'; - return preg_replace_callback($regex, function ($matches) { - assert(strlen($matches[0]) === 1); - $hex = dechex(ord($matches[0]));; - return '\\x' . str_pad($hex, 2, '0', \STR_PAD_LEFT); - }, $escaped); - } - - protected function containsEndLabel($string, $label, $atStart = true, $atEnd = true) { - $start = $atStart ? '(?:^|[\r\n])' : '[\r\n]'; - $end = $atEnd ? '(?:$|[;\r\n])' : '[;\r\n]'; - return false !== strpos($string, $label) - && preg_match('/' . $start . $label . $end . '/', $string); - } - - protected function encapsedContainsEndLabel(array $parts, $label) { - foreach ($parts as $i => $part) { - $atStart = $i === 0; - $atEnd = $i === count($parts) - 1; - if ($part instanceof Scalar\EncapsedStringPart - && $this->containsEndLabel($part->value, $label, $atStart, $atEnd) - ) { - return true; - } - } - return false; - } - - protected function pDereferenceLhs(Node $node) { - if (!$this->dereferenceLhsRequiresParens($node)) { - return $this->p($node); - } else { - return '(' . $this->p($node) . ')'; - } - } - - protected function pCallLhs(Node $node) { - if (!$this->callLhsRequiresParens($node)) { - return $this->p($node); - } else { - return '(' . $this->p($node) . ')'; - } - } - - protected function pNewVariable(Node $node) { - // TODO: This is not fully accurate. - return $this->pDereferenceLhs($node); - } - - /** - * @param Node[] $nodes - * @return bool - */ - protected function hasNodeWithComments(array $nodes) { - foreach ($nodes as $node) { - if ($node && $node->getComments()) { - return true; - } - } - return false; - } - - protected function pMaybeMultiline(array $nodes, bool $trailingComma = false) { - if (!$this->hasNodeWithComments($nodes)) { - return $this->pCommaSeparated($nodes); - } else { - return $this->pCommaSeparatedMultiline($nodes, $trailingComma) . $this->nl; - } - } - - protected function pAttrGroups(array $nodes, bool $inline = false): string { - $result = ''; - $sep = $inline ? ' ' : $this->nl; - foreach ($nodes as $node) { - $result .= $this->p($node) . $sep; - } - - return $result; - } -} diff --git a/lib/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php b/lib/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php deleted file mode 100644 index 2c7fc3070..000000000 --- a/lib/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php +++ /dev/null @@ -1,1506 +0,0 @@ -<?php declare(strict_types=1); - -namespace PhpParser; - -use PhpParser\Internal\DiffElem; -use PhpParser\Internal\PrintableNewAnonClassNode; -use PhpParser\Internal\TokenStream; -use PhpParser\Node\Expr; -use PhpParser\Node\Expr\AssignOp; -use PhpParser\Node\Expr\BinaryOp; -use PhpParser\Node\Expr\Cast; -use PhpParser\Node\Scalar; -use PhpParser\Node\Stmt; - -abstract class PrettyPrinterAbstract -{ - const FIXUP_PREC_LEFT = 0; // LHS operand affected by precedence - const FIXUP_PREC_RIGHT = 1; // RHS operand affected by precedence - const FIXUP_CALL_LHS = 2; // LHS of call - const FIXUP_DEREF_LHS = 3; // LHS of dereferencing operation - const FIXUP_BRACED_NAME = 4; // Name operand that may require bracing - const FIXUP_VAR_BRACED_NAME = 5; // Name operand that may require ${} bracing - const FIXUP_ENCAPSED = 6; // Encapsed string part - - protected $precedenceMap = [ - // [precedence, associativity] - // where for precedence -1 is %left, 0 is %nonassoc and 1 is %right - BinaryOp\Pow::class => [ 0, 1], - Expr\BitwiseNot::class => [ 10, 1], - Expr\PreInc::class => [ 10, 1], - Expr\PreDec::class => [ 10, 1], - Expr\PostInc::class => [ 10, -1], - Expr\PostDec::class => [ 10, -1], - Expr\UnaryPlus::class => [ 10, 1], - Expr\UnaryMinus::class => [ 10, 1], - Cast\Int_::class => [ 10, 1], - Cast\Double::class => [ 10, 1], - Cast\String_::class => [ 10, 1], - Cast\Array_::class => [ 10, 1], - Cast\Object_::class => [ 10, 1], - Cast\Bool_::class => [ 10, 1], - Cast\Unset_::class => [ 10, 1], - Expr\ErrorSuppress::class => [ 10, 1], - Expr\Instanceof_::class => [ 20, 0], - Expr\BooleanNot::class => [ 30, 1], - BinaryOp\Mul::class => [ 40, -1], - BinaryOp\Div::class => [ 40, -1], - BinaryOp\Mod::class => [ 40, -1], - BinaryOp\Plus::class => [ 50, -1], - BinaryOp\Minus::class => [ 50, -1], - BinaryOp\Concat::class => [ 50, -1], - BinaryOp\ShiftLeft::class => [ 60, -1], - BinaryOp\ShiftRight::class => [ 60, -1], - BinaryOp\Smaller::class => [ 70, 0], - BinaryOp\SmallerOrEqual::class => [ 70, 0], - BinaryOp\Greater::class => [ 70, 0], - BinaryOp\GreaterOrEqual::class => [ 70, 0], - BinaryOp\Equal::class => [ 80, 0], - BinaryOp\NotEqual::class => [ 80, 0], - BinaryOp\Identical::class => [ 80, 0], - BinaryOp\NotIdentical::class => [ 80, 0], - BinaryOp\Spaceship::class => [ 80, 0], - BinaryOp\BitwiseAnd::class => [ 90, -1], - BinaryOp\BitwiseXor::class => [100, -1], - BinaryOp\BitwiseOr::class => [110, -1], - BinaryOp\BooleanAnd::class => [120, -1], - BinaryOp\BooleanOr::class => [130, -1], - BinaryOp\Coalesce::class => [140, 1], - Expr\Ternary::class => [150, 0], - // parser uses %left for assignments, but they really behave as %right - Expr\Assign::class => [160, 1], - Expr\AssignRef::class => [160, 1], - AssignOp\Plus::class => [160, 1], - AssignOp\Minus::class => [160, 1], - AssignOp\Mul::class => [160, 1], - AssignOp\Div::class => [160, 1], - AssignOp\Concat::class => [160, 1], - AssignOp\Mod::class => [160, 1], - AssignOp\BitwiseAnd::class => [160, 1], - AssignOp\BitwiseOr::class => [160, 1], - AssignOp\BitwiseXor::class => [160, 1], - AssignOp\ShiftLeft::class => [160, 1], - AssignOp\ShiftRight::class => [160, 1], - AssignOp\Pow::class => [160, 1], - AssignOp\Coalesce::class => [160, 1], - Expr\YieldFrom::class => [165, 1], - Expr\Print_::class => [168, 1], - BinaryOp\LogicalAnd::class => [170, -1], - BinaryOp\LogicalXor::class => [180, -1], - BinaryOp\LogicalOr::class => [190, -1], - Expr\Include_::class => [200, -1], - ]; - - /** @var int Current indentation level. */ - protected $indentLevel; - /** @var string Newline including current indentation. */ - protected $nl; - /** @var string Token placed at end of doc string to ensure it is followed by a newline. */ - protected $docStringEndToken; - /** @var bool Whether semicolon namespaces can be used (i.e. no global namespace is used) */ - protected $canUseSemicolonNamespaces; - /** @var array Pretty printer options */ - protected $options; - - /** @var TokenStream Original tokens for use in format-preserving pretty print */ - protected $origTokens; - /** @var Internal\Differ Differ for node lists */ - protected $nodeListDiffer; - /** @var bool[] Map determining whether a certain character is a label character */ - protected $labelCharMap; - /** - * @var int[][] Map from token classes and subnode names to FIXUP_* constants. This is used - * during format-preserving prints to place additional parens/braces if necessary. - */ - protected $fixupMap; - /** - * @var int[][] Map from "{$node->getType()}->{$subNode}" to ['left' => $l, 'right' => $r], - * where $l and $r specify the token type that needs to be stripped when removing - * this node. - */ - protected $removalMap; - /** - * @var mixed[] Map from "{$node->getType()}->{$subNode}" to [$find, $beforeToken, $extraLeft, $extraRight]. - * $find is an optional token after which the insertion occurs. $extraLeft/Right - * are optionally added before/after the main insertions. - */ - protected $insertionMap; - /** - * @var string[] Map From "{$node->getType()}->{$subNode}" to string that should be inserted - * between elements of this list subnode. - */ - protected $listInsertionMap; - protected $emptyListInsertionMap; - /** @var int[] Map from "{$node->getType()}->{$subNode}" to token before which the modifiers - * should be reprinted. */ - protected $modifierChangeMap; - - /** - * Creates a pretty printer instance using the given options. - * - * Supported options: - * * bool $shortArraySyntax = false: Whether to use [] instead of array() as the default array - * syntax, if the node does not specify a format. - * - * @param array $options Dictionary of formatting options - */ - public function __construct(array $options = []) { - $this->docStringEndToken = '_DOC_STRING_END_' . mt_rand(); - - $defaultOptions = ['shortArraySyntax' => false]; - $this->options = $options + $defaultOptions; - } - - /** - * Reset pretty printing state. - */ - protected function resetState() { - $this->indentLevel = 0; - $this->nl = "\n"; - $this->origTokens = null; - } - - /** - * Set indentation level - * - * @param int $level Level in number of spaces - */ - protected function setIndentLevel(int $level) { - $this->indentLevel = $level; - $this->nl = "\n" . \str_repeat(' ', $level); - } - - /** - * Increase indentation level. - */ - protected function indent() { - $this->indentLevel += 4; - $this->nl .= ' '; - } - - /** - * Decrease indentation level. - */ - protected function outdent() { - assert($this->indentLevel >= 4); - $this->indentLevel -= 4; - $this->nl = "\n" . str_repeat(' ', $this->indentLevel); - } - - /** - * Pretty prints an array of statements. - * - * @param Node[] $stmts Array of statements - * - * @return string Pretty printed statements - */ - public function prettyPrint(array $stmts) : string { - $this->resetState(); - $this->preprocessNodes($stmts); - - return ltrim($this->handleMagicTokens($this->pStmts($stmts, false))); - } - - /** - * Pretty prints an expression. - * - * @param Expr $node Expression node - * - * @return string Pretty printed node - */ - public function prettyPrintExpr(Expr $node) : string { - $this->resetState(); - return $this->handleMagicTokens($this->p($node)); - } - - /** - * Pretty prints a file of statements (includes the opening <?php tag if it is required). - * - * @param Node[] $stmts Array of statements - * - * @return string Pretty printed statements - */ - public function prettyPrintFile(array $stmts) : string { - if (!$stmts) { - return "<?php\n\n"; - } - - $p = "<?php\n\n" . $this->prettyPrint($stmts); - - if ($stmts[0] instanceof Stmt\InlineHTML) { - $p = preg_replace('/^<\?php\s+\?>\n?/', '', $p); - } - if ($stmts[count($stmts) - 1] instanceof Stmt\InlineHTML) { - $p = preg_replace('/<\?php$/', '', rtrim($p)); - } - - return $p; - } - - /** - * Preprocesses the top-level nodes to initialize pretty printer state. - * - * @param Node[] $nodes Array of nodes - */ - protected function preprocessNodes(array $nodes) { - /* We can use semicolon-namespaces unless there is a global namespace declaration */ - $this->canUseSemicolonNamespaces = true; - foreach ($nodes as $node) { - if ($node instanceof Stmt\Namespace_ && null === $node->name) { - $this->canUseSemicolonNamespaces = false; - break; - } - } - } - - /** - * Handles (and removes) no-indent and doc-string-end tokens. - * - * @param string $str - * @return string - */ - protected function handleMagicTokens(string $str) : string { - // Replace doc-string-end tokens with nothing or a newline - $str = str_replace($this->docStringEndToken . ";\n", ";\n", $str); - $str = str_replace($this->docStringEndToken, "\n", $str); - - return $str; - } - - /** - * Pretty prints an array of nodes (statements) and indents them optionally. - * - * @param Node[] $nodes Array of nodes - * @param bool $indent Whether to indent the printed nodes - * - * @return string Pretty printed statements - */ - protected function pStmts(array $nodes, bool $indent = true) : string { - if ($indent) { - $this->indent(); - } - - $result = ''; - foreach ($nodes as $node) { - $comments = $node->getComments(); - if ($comments) { - $result .= $this->nl . $this->pComments($comments); - if ($node instanceof Stmt\Nop) { - continue; - } - } - - $result .= $this->nl . $this->p($node); - } - - if ($indent) { - $this->outdent(); - } - - return $result; - } - - /** - * Pretty-print an infix operation while taking precedence into account. - * - * @param string $class Node class of operator - * @param Node $leftNode Left-hand side node - * @param string $operatorString String representation of the operator - * @param Node $rightNode Right-hand side node - * - * @return string Pretty printed infix operation - */ - protected function pInfixOp(string $class, Node $leftNode, string $operatorString, Node $rightNode) : string { - list($precedence, $associativity) = $this->precedenceMap[$class]; - - return $this->pPrec($leftNode, $precedence, $associativity, -1) - . $operatorString - . $this->pPrec($rightNode, $precedence, $associativity, 1); - } - - /** - * Pretty-print a prefix operation while taking precedence into account. - * - * @param string $class Node class of operator - * @param string $operatorString String representation of the operator - * @param Node $node Node - * - * @return string Pretty printed prefix operation - */ - protected function pPrefixOp(string $class, string $operatorString, Node $node) : string { - list($precedence, $associativity) = $this->precedenceMap[$class]; - return $operatorString . $this->pPrec($node, $precedence, $associativity, 1); - } - - /** - * Pretty-print a postfix operation while taking precedence into account. - * - * @param string $class Node class of operator - * @param string $operatorString String representation of the operator - * @param Node $node Node - * - * @return string Pretty printed postfix operation - */ - protected function pPostfixOp(string $class, Node $node, string $operatorString) : string { - list($precedence, $associativity) = $this->precedenceMap[$class]; - return $this->pPrec($node, $precedence, $associativity, -1) . $operatorString; - } - - /** - * Prints an expression node with the least amount of parentheses necessary to preserve the meaning. - * - * @param Node $node Node to pretty print - * @param int $parentPrecedence Precedence of the parent operator - * @param int $parentAssociativity Associativity of parent operator - * (-1 is left, 0 is nonassoc, 1 is right) - * @param int $childPosition Position of the node relative to the operator - * (-1 is left, 1 is right) - * - * @return string The pretty printed node - */ - protected function pPrec(Node $node, int $parentPrecedence, int $parentAssociativity, int $childPosition) : string { - $class = \get_class($node); - if (isset($this->precedenceMap[$class])) { - $childPrecedence = $this->precedenceMap[$class][0]; - if ($childPrecedence > $parentPrecedence - || ($parentPrecedence === $childPrecedence && $parentAssociativity !== $childPosition) - ) { - return '(' . $this->p($node) . ')'; - } - } - - return $this->p($node); - } - - /** - * Pretty prints an array of nodes and implodes the printed values. - * - * @param Node[] $nodes Array of Nodes to be printed - * @param string $glue Character to implode with - * - * @return string Imploded pretty printed nodes - */ - protected function pImplode(array $nodes, string $glue = '') : string { - $pNodes = []; - foreach ($nodes as $node) { - if (null === $node) { - $pNodes[] = ''; - } else { - $pNodes[] = $this->p($node); - } - } - - return implode($glue, $pNodes); - } - - /** - * Pretty prints an array of nodes and implodes the printed values with commas. - * - * @param Node[] $nodes Array of Nodes to be printed - * - * @return string Comma separated pretty printed nodes - */ - protected function pCommaSeparated(array $nodes) : string { - return $this->pImplode($nodes, ', '); - } - - /** - * Pretty prints a comma-separated list of nodes in multiline style, including comments. - * - * The result includes a leading newline and one level of indentation (same as pStmts). - * - * @param Node[] $nodes Array of Nodes to be printed - * @param bool $trailingComma Whether to use a trailing comma - * - * @return string Comma separated pretty printed nodes in multiline style - */ - protected function pCommaSeparatedMultiline(array $nodes, bool $trailingComma) : string { - $this->indent(); - - $result = ''; - $lastIdx = count($nodes) - 1; - foreach ($nodes as $idx => $node) { - if ($node !== null) { - $comments = $node->getComments(); - if ($comments) { - $result .= $this->nl . $this->pComments($comments); - } - - $result .= $this->nl . $this->p($node); - } else { - $result .= $this->nl; - } - if ($trailingComma || $idx !== $lastIdx) { - $result .= ','; - } - } - - $this->outdent(); - return $result; - } - - /** - * Prints reformatted text of the passed comments. - * - * @param Comment[] $comments List of comments - * - * @return string Reformatted text of comments - */ - protected function pComments(array $comments) : string { - $formattedComments = []; - - foreach ($comments as $comment) { - $formattedComments[] = str_replace("\n", $this->nl, $comment->getReformattedText()); - } - - return implode($this->nl, $formattedComments); - } - - /** - * Perform a format-preserving pretty print of an AST. - * - * The format preservation is best effort. For some changes to the AST the formatting will not - * be preserved (at least not locally). - * - * In order to use this method a number of prerequisites must be satisfied: - * * The startTokenPos and endTokenPos attributes in the lexer must be enabled. - * * The CloningVisitor must be run on the AST prior to modification. - * * The original tokens must be provided, using the getTokens() method on the lexer. - * - * @param Node[] $stmts Modified AST with links to original AST - * @param Node[] $origStmts Original AST with token offset information - * @param array $origTokens Tokens of the original code - * - * @return string - */ - public function printFormatPreserving(array $stmts, array $origStmts, array $origTokens) : string { - $this->initializeNodeListDiffer(); - $this->initializeLabelCharMap(); - $this->initializeFixupMap(); - $this->initializeRemovalMap(); - $this->initializeInsertionMap(); - $this->initializeListInsertionMap(); - $this->initializeEmptyListInsertionMap(); - $this->initializeModifierChangeMap(); - - $this->resetState(); - $this->origTokens = new TokenStream($origTokens); - - $this->preprocessNodes($stmts); - - $pos = 0; - $result = $this->pArray($stmts, $origStmts, $pos, 0, 'File', 'stmts', null); - if (null !== $result) { - $result .= $this->origTokens->getTokenCode($pos, count($origTokens), 0); - } else { - // Fallback - // TODO Add <?php properly - $result = "<?php\n" . $this->pStmts($stmts, false); - } - - return ltrim($this->handleMagicTokens($result)); - } - - protected function pFallback(Node $node) { - return $this->{'p' . $node->getType()}($node); - } - - /** - * Pretty prints a node. - * - * This method also handles formatting preservation for nodes. - * - * @param Node $node Node to be pretty printed - * @param bool $parentFormatPreserved Whether parent node has preserved formatting - * - * @return string Pretty printed node - */ - protected function p(Node $node, $parentFormatPreserved = false) : string { - // No orig tokens means this is a normal pretty print without preservation of formatting - if (!$this->origTokens) { - return $this->{'p' . $node->getType()}($node); - } - - /** @var Node $origNode */ - $origNode = $node->getAttribute('origNode'); - if (null === $origNode) { - return $this->pFallback($node); - } - - $class = \get_class($node); - \assert($class === \get_class($origNode)); - - $startPos = $origNode->getStartTokenPos(); - $endPos = $origNode->getEndTokenPos(); - \assert($startPos >= 0 && $endPos >= 0); - - $fallbackNode = $node; - if ($node instanceof Expr\New_ && $node->class instanceof Stmt\Class_) { - // Normalize node structure of anonymous classes - $node = PrintableNewAnonClassNode::fromNewNode($node); - $origNode = PrintableNewAnonClassNode::fromNewNode($origNode); - } - - // InlineHTML node does not contain closing and opening PHP tags. If the parent formatting - // is not preserved, then we need to use the fallback code to make sure the tags are - // printed. - if ($node instanceof Stmt\InlineHTML && !$parentFormatPreserved) { - return $this->pFallback($fallbackNode); - } - - $indentAdjustment = $this->indentLevel - $this->origTokens->getIndentationBefore($startPos); - - $type = $node->getType(); - $fixupInfo = $this->fixupMap[$class] ?? null; - - $result = ''; - $pos = $startPos; - foreach ($node->getSubNodeNames() as $subNodeName) { - $subNode = $node->$subNodeName; - $origSubNode = $origNode->$subNodeName; - - if ((!$subNode instanceof Node && $subNode !== null) - || (!$origSubNode instanceof Node && $origSubNode !== null) - ) { - if ($subNode === $origSubNode) { - // Unchanged, can reuse old code - continue; - } - - if (is_array($subNode) && is_array($origSubNode)) { - // Array subnode changed, we might be able to reconstruct it - $listResult = $this->pArray( - $subNode, $origSubNode, $pos, $indentAdjustment, $type, $subNodeName, - $fixupInfo[$subNodeName] ?? null - ); - if (null === $listResult) { - return $this->pFallback($fallbackNode); - } - - $result .= $listResult; - continue; - } - - if (is_int($subNode) && is_int($origSubNode)) { - // Check if this is a modifier change - $key = $type . '->' . $subNodeName; - if (!isset($this->modifierChangeMap[$key])) { - return $this->pFallback($fallbackNode); - } - - $findToken = $this->modifierChangeMap[$key]; - $result .= $this->pModifiers($subNode); - $pos = $this->origTokens->findRight($pos, $findToken); - continue; - } - - // If a non-node, non-array subnode changed, we don't be able to do a partial - // reconstructions, as we don't have enough offset information. Pretty print the - // whole node instead. - return $this->pFallback($fallbackNode); - } - - $extraLeft = ''; - $extraRight = ''; - if ($origSubNode !== null) { - $subStartPos = $origSubNode->getStartTokenPos(); - $subEndPos = $origSubNode->getEndTokenPos(); - \assert($subStartPos >= 0 && $subEndPos >= 0); - } else { - if ($subNode === null) { - // Both null, nothing to do - continue; - } - - // A node has been inserted, check if we have insertion information for it - $key = $type . '->' . $subNodeName; - if (!isset($this->insertionMap[$key])) { - return $this->pFallback($fallbackNode); - } - - list($findToken, $beforeToken, $extraLeft, $extraRight) = $this->insertionMap[$key]; - if (null !== $findToken) { - $subStartPos = $this->origTokens->findRight($pos, $findToken) - + (int) !$beforeToken; - } else { - $subStartPos = $pos; - } - - if (null === $extraLeft && null !== $extraRight) { - // If inserting on the right only, skipping whitespace looks better - $subStartPos = $this->origTokens->skipRightWhitespace($subStartPos); - } - $subEndPos = $subStartPos - 1; - } - - if (null === $subNode) { - // A node has been removed, check if we have removal information for it - $key = $type . '->' . $subNodeName; - if (!isset($this->removalMap[$key])) { - return $this->pFallback($fallbackNode); - } - - // Adjust positions to account for additional tokens that must be skipped - $removalInfo = $this->removalMap[$key]; - if (isset($removalInfo['left'])) { - $subStartPos = $this->origTokens->skipLeft($subStartPos - 1, $removalInfo['left']) + 1; - } - if (isset($removalInfo['right'])) { - $subEndPos = $this->origTokens->skipRight($subEndPos + 1, $removalInfo['right']) - 1; - } - } - - $result .= $this->origTokens->getTokenCode($pos, $subStartPos, $indentAdjustment); - - if (null !== $subNode) { - $result .= $extraLeft; - - $origIndentLevel = $this->indentLevel; - $this->setIndentLevel($this->origTokens->getIndentationBefore($subStartPos) + $indentAdjustment); - - // If it's the same node that was previously in this position, it certainly doesn't - // need fixup. It's important to check this here, because our fixup checks are more - // conservative than strictly necessary. - if (isset($fixupInfo[$subNodeName]) - && $subNode->getAttribute('origNode') !== $origSubNode - ) { - $fixup = $fixupInfo[$subNodeName]; - $res = $this->pFixup($fixup, $subNode, $class, $subStartPos, $subEndPos); - } else { - $res = $this->p($subNode, true); - } - - $this->safeAppend($result, $res); - $this->setIndentLevel($origIndentLevel); - - $result .= $extraRight; - } - - $pos = $subEndPos + 1; - } - - $result .= $this->origTokens->getTokenCode($pos, $endPos + 1, $indentAdjustment); - return $result; - } - - /** - * Perform a format-preserving pretty print of an array. - * - * @param array $nodes New nodes - * @param array $origNodes Original nodes - * @param int $pos Current token position (updated by reference) - * @param int $indentAdjustment Adjustment for indentation - * @param string $parentNodeType Type of the containing node. - * @param string $subNodeName Name of array subnode. - * @param null|int $fixup Fixup information for array item nodes - * - * @return null|string Result of pretty print or null if cannot preserve formatting - */ - protected function pArray( - array $nodes, array $origNodes, int &$pos, int $indentAdjustment, - string $parentNodeType, string $subNodeName, $fixup - ) { - $diff = $this->nodeListDiffer->diffWithReplacements($origNodes, $nodes); - - $mapKey = $parentNodeType . '->' . $subNodeName; - $insertStr = $this->listInsertionMap[$mapKey] ?? null; - $isStmtList = $subNodeName === 'stmts'; - - $beforeFirstKeepOrReplace = true; - $skipRemovedNode = false; - $delayedAdd = []; - $lastElemIndentLevel = $this->indentLevel; - - $insertNewline = false; - if ($insertStr === "\n") { - $insertStr = ''; - $insertNewline = true; - } - - if ($isStmtList && \count($origNodes) === 1 && \count($nodes) !== 1) { - $startPos = $origNodes[0]->getStartTokenPos(); - $endPos = $origNodes[0]->getEndTokenPos(); - \assert($startPos >= 0 && $endPos >= 0); - if (!$this->origTokens->haveBraces($startPos, $endPos)) { - // This was a single statement without braces, but either additional statements - // have been added, or the single statement has been removed. This requires the - // addition of braces. For now fall back. - // TODO: Try to preserve formatting - return null; - } - } - - $result = ''; - foreach ($diff as $i => $diffElem) { - $diffType = $diffElem->type; - /** @var Node|null $arrItem */ - $arrItem = $diffElem->new; - /** @var Node|null $origArrItem */ - $origArrItem = $diffElem->old; - - if ($diffType === DiffElem::TYPE_KEEP || $diffType === DiffElem::TYPE_REPLACE) { - $beforeFirstKeepOrReplace = false; - - if ($origArrItem === null || $arrItem === null) { - // We can only handle the case where both are null - if ($origArrItem === $arrItem) { - continue; - } - return null; - } - - if (!$arrItem instanceof Node || !$origArrItem instanceof Node) { - // We can only deal with nodes. This can occur for Names, which use string arrays. - return null; - } - - $itemStartPos = $origArrItem->getStartTokenPos(); - $itemEndPos = $origArrItem->getEndTokenPos(); - \assert($itemStartPos >= 0 && $itemEndPos >= 0 && $itemStartPos >= $pos); - - $origIndentLevel = $this->indentLevel; - $lastElemIndentLevel = $this->origTokens->getIndentationBefore($itemStartPos) + $indentAdjustment; - $this->setIndentLevel($lastElemIndentLevel); - - $comments = $arrItem->getComments(); - $origComments = $origArrItem->getComments(); - $commentStartPos = $origComments ? $origComments[0]->getStartTokenPos() : $itemStartPos; - \assert($commentStartPos >= 0); - - if ($commentStartPos < $pos) { - // Comments may be assigned to multiple nodes if they start at the same position. - // Make sure we don't try to print them multiple times. - $commentStartPos = $itemStartPos; - } - - if ($skipRemovedNode) { - if ($isStmtList && $this->origTokens->haveBracesInRange($pos, $itemStartPos)) { - // We'd remove the brace of a code block. - // TODO: Preserve formatting. - $this->setIndentLevel($origIndentLevel); - return null; - } - } else { - $result .= $this->origTokens->getTokenCode( - $pos, $commentStartPos, $indentAdjustment); - } - - if (!empty($delayedAdd)) { - /** @var Node $delayedAddNode */ - foreach ($delayedAdd as $delayedAddNode) { - if ($insertNewline) { - $delayedAddComments = $delayedAddNode->getComments(); - if ($delayedAddComments) { - $result .= $this->pComments($delayedAddComments) . $this->nl; - } - } - - $this->safeAppend($result, $this->p($delayedAddNode, true)); - - if ($insertNewline) { - $result .= $insertStr . $this->nl; - } else { - $result .= $insertStr; - } - } - - $delayedAdd = []; - } - - if ($comments !== $origComments) { - if ($comments) { - $result .= $this->pComments($comments) . $this->nl; - } - } else { - $result .= $this->origTokens->getTokenCode( - $commentStartPos, $itemStartPos, $indentAdjustment); - } - - // If we had to remove anything, we have done so now. - $skipRemovedNode = false; - } elseif ($diffType === DiffElem::TYPE_ADD) { - if (null === $insertStr) { - // We don't have insertion information for this list type - return null; - } - - // We go multiline if the original code was multiline, - // or if it's an array item with a comment above it. - if ($insertStr === ', ' && - ($this->isMultiline($origNodes) || $arrItem->getComments()) - ) { - $insertStr = ','; - $insertNewline = true; - } - - if ($beforeFirstKeepOrReplace) { - // Will be inserted at the next "replace" or "keep" element - $delayedAdd[] = $arrItem; - continue; - } - - $itemStartPos = $pos; - $itemEndPos = $pos - 1; - - $origIndentLevel = $this->indentLevel; - $this->setIndentLevel($lastElemIndentLevel); - - if ($insertNewline) { - $result .= $insertStr . $this->nl; - $comments = $arrItem->getComments(); - if ($comments) { - $result .= $this->pComments($comments) . $this->nl; - } - } else { - $result .= $insertStr; - } - } elseif ($diffType === DiffElem::TYPE_REMOVE) { - if (!$origArrItem instanceof Node) { - // We only support removal for nodes - return null; - } - - $itemStartPos = $origArrItem->getStartTokenPos(); - $itemEndPos = $origArrItem->getEndTokenPos(); - \assert($itemStartPos >= 0 && $itemEndPos >= 0); - - // Consider comments part of the node. - $origComments = $origArrItem->getComments(); - if ($origComments) { - $itemStartPos = $origComments[0]->getStartTokenPos(); - } - - if ($i === 0) { - // If we're removing from the start, keep the tokens before the node and drop those after it, - // instead of the other way around. - $result .= $this->origTokens->getTokenCode( - $pos, $itemStartPos, $indentAdjustment); - $skipRemovedNode = true; - } else { - if ($isStmtList && $this->origTokens->haveBracesInRange($pos, $itemStartPos)) { - // We'd remove the brace of a code block. - // TODO: Preserve formatting. - return null; - } - } - - $pos = $itemEndPos + 1; - continue; - } else { - throw new \Exception("Shouldn't happen"); - } - - if (null !== $fixup && $arrItem->getAttribute('origNode') !== $origArrItem) { - $res = $this->pFixup($fixup, $arrItem, null, $itemStartPos, $itemEndPos); - } else { - $res = $this->p($arrItem, true); - } - $this->safeAppend($result, $res); - - $this->setIndentLevel($origIndentLevel); - $pos = $itemEndPos + 1; - } - - if ($skipRemovedNode) { - // TODO: Support removing single node. - return null; - } - - if (!empty($delayedAdd)) { - if (!isset($this->emptyListInsertionMap[$mapKey])) { - return null; - } - - list($findToken, $extraLeft, $extraRight) = $this->emptyListInsertionMap[$mapKey]; - if (null !== $findToken) { - $insertPos = $this->origTokens->findRight($pos, $findToken) + 1; - $result .= $this->origTokens->getTokenCode($pos, $insertPos, $indentAdjustment); - $pos = $insertPos; - } - - $first = true; - $result .= $extraLeft; - foreach ($delayedAdd as $delayedAddNode) { - if (!$first) { - $result .= $insertStr; - } - $result .= $this->p($delayedAddNode, true); - $first = false; - } - $result .= $extraRight; - } - - return $result; - } - - /** - * Print node with fixups. - * - * Fixups here refer to the addition of extra parentheses, braces or other characters, that - * are required to preserve program semantics in a certain context (e.g. to maintain precedence - * or because only certain expressions are allowed in certain places). - * - * @param int $fixup Fixup type - * @param Node $subNode Subnode to print - * @param string|null $parentClass Class of parent node - * @param int $subStartPos Original start pos of subnode - * @param int $subEndPos Original end pos of subnode - * - * @return string Result of fixed-up print of subnode - */ - protected function pFixup(int $fixup, Node $subNode, $parentClass, int $subStartPos, int $subEndPos) : string { - switch ($fixup) { - case self::FIXUP_PREC_LEFT: - case self::FIXUP_PREC_RIGHT: - if (!$this->origTokens->haveParens($subStartPos, $subEndPos)) { - list($precedence, $associativity) = $this->precedenceMap[$parentClass]; - return $this->pPrec($subNode, $precedence, $associativity, - $fixup === self::FIXUP_PREC_LEFT ? -1 : 1); - } - break; - case self::FIXUP_CALL_LHS: - if ($this->callLhsRequiresParens($subNode) - && !$this->origTokens->haveParens($subStartPos, $subEndPos) - ) { - return '(' . $this->p($subNode) . ')'; - } - break; - case self::FIXUP_DEREF_LHS: - if ($this->dereferenceLhsRequiresParens($subNode) - && !$this->origTokens->haveParens($subStartPos, $subEndPos) - ) { - return '(' . $this->p($subNode) . ')'; - } - break; - case self::FIXUP_BRACED_NAME: - case self::FIXUP_VAR_BRACED_NAME: - if ($subNode instanceof Expr - && !$this->origTokens->haveBraces($subStartPos, $subEndPos) - ) { - return ($fixup === self::FIXUP_VAR_BRACED_NAME ? '$' : '') - . '{' . $this->p($subNode) . '}'; - } - break; - case self::FIXUP_ENCAPSED: - if (!$subNode instanceof Scalar\EncapsedStringPart - && !$this->origTokens->haveBraces($subStartPos, $subEndPos) - ) { - return '{' . $this->p($subNode) . '}'; - } - break; - default: - throw new \Exception('Cannot happen'); - } - - // Nothing special to do - return $this->p($subNode); - } - - /** - * Appends to a string, ensuring whitespace between label characters. - * - * Example: "echo" and "$x" result in "echo$x", but "echo" and "x" result in "echo x". - * Without safeAppend the result would be "echox", which does not preserve semantics. - * - * @param string $str - * @param string $append - */ - protected function safeAppend(string &$str, string $append) { - if ($str === "") { - $str = $append; - return; - } - - if ($append === "") { - return; - } - - if (!$this->labelCharMap[$append[0]] - || !$this->labelCharMap[$str[\strlen($str) - 1]]) { - $str .= $append; - } else { - $str .= " " . $append; - } - } - - /** - * Determines whether the LHS of a call must be wrapped in parenthesis. - * - * @param Node $node LHS of a call - * - * @return bool Whether parentheses are required - */ - protected function callLhsRequiresParens(Node $node) : bool { - return !($node instanceof Node\Name - || $node instanceof Expr\Variable - || $node instanceof Expr\ArrayDimFetch - || $node instanceof Expr\FuncCall - || $node instanceof Expr\MethodCall - || $node instanceof Expr\NullsafeMethodCall - || $node instanceof Expr\StaticCall - || $node instanceof Expr\Array_); - } - - /** - * Determines whether the LHS of a dereferencing operation must be wrapped in parenthesis. - * - * @param Node $node LHS of dereferencing operation - * - * @return bool Whether parentheses are required - */ - protected function dereferenceLhsRequiresParens(Node $node) : bool { - return !($node instanceof Expr\Variable - || $node instanceof Node\Name - || $node instanceof Expr\ArrayDimFetch - || $node instanceof Expr\PropertyFetch - || $node instanceof Expr\NullsafePropertyFetch - || $node instanceof Expr\StaticPropertyFetch - || $node instanceof Expr\FuncCall - || $node instanceof Expr\MethodCall - || $node instanceof Expr\NullsafeMethodCall - || $node instanceof Expr\StaticCall - || $node instanceof Expr\Array_ - || $node instanceof Scalar\String_ - || $node instanceof Expr\ConstFetch - || $node instanceof Expr\ClassConstFetch); - } - - /** - * Print modifiers, including trailing whitespace. - * - * @param int $modifiers Modifier mask to print - * - * @return string Printed modifiers - */ - protected function pModifiers(int $modifiers) { - return ($modifiers & Stmt\Class_::MODIFIER_PUBLIC ? 'public ' : '') - . ($modifiers & Stmt\Class_::MODIFIER_PROTECTED ? 'protected ' : '') - . ($modifiers & Stmt\Class_::MODIFIER_PRIVATE ? 'private ' : '') - . ($modifiers & Stmt\Class_::MODIFIER_STATIC ? 'static ' : '') - . ($modifiers & Stmt\Class_::MODIFIER_ABSTRACT ? 'abstract ' : '') - . ($modifiers & Stmt\Class_::MODIFIER_FINAL ? 'final ' : '') - . ($modifiers & Stmt\Class_::MODIFIER_READONLY ? 'readonly ' : ''); - } - - /** - * Determine whether a list of nodes uses multiline formatting. - * - * @param (Node|null)[] $nodes Node list - * - * @return bool Whether multiline formatting is used - */ - protected function isMultiline(array $nodes) : bool { - if (\count($nodes) < 2) { - return false; - } - - $pos = -1; - foreach ($nodes as $node) { - if (null === $node) { - continue; - } - - $endPos = $node->getEndTokenPos() + 1; - if ($pos >= 0) { - $text = $this->origTokens->getTokenCode($pos, $endPos, 0); - if (false === strpos($text, "\n")) { - // We require that a newline is present between *every* item. If the formatting - // is inconsistent, with only some items having newlines, we don't consider it - // as multiline - return false; - } - } - $pos = $endPos; - } - - return true; - } - - /** - * Lazily initializes label char map. - * - * The label char map determines whether a certain character may occur in a label. - */ - protected function initializeLabelCharMap() { - if ($this->labelCharMap) return; - - $this->labelCharMap = []; - for ($i = 0; $i < 256; $i++) { - // Since PHP 7.1 The lower range is 0x80. However, we also want to support code for - // older versions. - $chr = chr($i); - $this->labelCharMap[$chr] = $i >= 0x7f || ctype_alnum($chr); - } - } - - /** - * Lazily initializes node list differ. - * - * The node list differ is used to determine differences between two array subnodes. - */ - protected function initializeNodeListDiffer() { - if ($this->nodeListDiffer) return; - - $this->nodeListDiffer = new Internal\Differ(function ($a, $b) { - if ($a instanceof Node && $b instanceof Node) { - return $a === $b->getAttribute('origNode'); - } - // Can happen for array destructuring - return $a === null && $b === null; - }); - } - - /** - * Lazily initializes fixup map. - * - * The fixup map is used to determine whether a certain subnode of a certain node may require - * some kind of "fixup" operation, e.g. the addition of parenthesis or braces. - */ - protected function initializeFixupMap() { - if ($this->fixupMap) return; - - $this->fixupMap = [ - Expr\PreInc::class => ['var' => self::FIXUP_PREC_RIGHT], - Expr\PreDec::class => ['var' => self::FIXUP_PREC_RIGHT], - Expr\PostInc::class => ['var' => self::FIXUP_PREC_LEFT], - Expr\PostDec::class => ['var' => self::FIXUP_PREC_LEFT], - Expr\Instanceof_::class => [ - 'expr' => self::FIXUP_PREC_LEFT, - 'class' => self::FIXUP_PREC_RIGHT, // TODO: FIXUP_NEW_VARIABLE - ], - Expr\Ternary::class => [ - 'cond' => self::FIXUP_PREC_LEFT, - 'else' => self::FIXUP_PREC_RIGHT, - ], - - Expr\FuncCall::class => ['name' => self::FIXUP_CALL_LHS], - Expr\StaticCall::class => ['class' => self::FIXUP_DEREF_LHS], - Expr\ArrayDimFetch::class => ['var' => self::FIXUP_DEREF_LHS], - Expr\ClassConstFetch::class => ['var' => self::FIXUP_DEREF_LHS], - Expr\New_::class => ['class' => self::FIXUP_DEREF_LHS], // TODO: FIXUP_NEW_VARIABLE - Expr\MethodCall::class => [ - 'var' => self::FIXUP_DEREF_LHS, - 'name' => self::FIXUP_BRACED_NAME, - ], - Expr\NullsafeMethodCall::class => [ - 'var' => self::FIXUP_DEREF_LHS, - 'name' => self::FIXUP_BRACED_NAME, - ], - Expr\StaticPropertyFetch::class => [ - 'class' => self::FIXUP_DEREF_LHS, - 'name' => self::FIXUP_VAR_BRACED_NAME, - ], - Expr\PropertyFetch::class => [ - 'var' => self::FIXUP_DEREF_LHS, - 'name' => self::FIXUP_BRACED_NAME, - ], - Expr\NullsafePropertyFetch::class => [ - 'var' => self::FIXUP_DEREF_LHS, - 'name' => self::FIXUP_BRACED_NAME, - ], - Scalar\Encapsed::class => [ - 'parts' => self::FIXUP_ENCAPSED, - ], - ]; - - $binaryOps = [ - BinaryOp\Pow::class, BinaryOp\Mul::class, BinaryOp\Div::class, BinaryOp\Mod::class, - BinaryOp\Plus::class, BinaryOp\Minus::class, BinaryOp\Concat::class, - BinaryOp\ShiftLeft::class, BinaryOp\ShiftRight::class, BinaryOp\Smaller::class, - BinaryOp\SmallerOrEqual::class, BinaryOp\Greater::class, BinaryOp\GreaterOrEqual::class, - BinaryOp\Equal::class, BinaryOp\NotEqual::class, BinaryOp\Identical::class, - BinaryOp\NotIdentical::class, BinaryOp\Spaceship::class, BinaryOp\BitwiseAnd::class, - BinaryOp\BitwiseXor::class, BinaryOp\BitwiseOr::class, BinaryOp\BooleanAnd::class, - BinaryOp\BooleanOr::class, BinaryOp\Coalesce::class, BinaryOp\LogicalAnd::class, - BinaryOp\LogicalXor::class, BinaryOp\LogicalOr::class, - ]; - foreach ($binaryOps as $binaryOp) { - $this->fixupMap[$binaryOp] = [ - 'left' => self::FIXUP_PREC_LEFT, - 'right' => self::FIXUP_PREC_RIGHT - ]; - } - - $assignOps = [ - Expr\Assign::class, Expr\AssignRef::class, AssignOp\Plus::class, AssignOp\Minus::class, - AssignOp\Mul::class, AssignOp\Div::class, AssignOp\Concat::class, AssignOp\Mod::class, - AssignOp\BitwiseAnd::class, AssignOp\BitwiseOr::class, AssignOp\BitwiseXor::class, - AssignOp\ShiftLeft::class, AssignOp\ShiftRight::class, AssignOp\Pow::class, AssignOp\Coalesce::class - ]; - foreach ($assignOps as $assignOp) { - $this->fixupMap[$assignOp] = [ - 'var' => self::FIXUP_PREC_LEFT, - 'expr' => self::FIXUP_PREC_RIGHT, - ]; - } - - $prefixOps = [ - Expr\BitwiseNot::class, Expr\BooleanNot::class, Expr\UnaryPlus::class, Expr\UnaryMinus::class, - Cast\Int_::class, Cast\Double::class, Cast\String_::class, Cast\Array_::class, - Cast\Object_::class, Cast\Bool_::class, Cast\Unset_::class, Expr\ErrorSuppress::class, - Expr\YieldFrom::class, Expr\Print_::class, Expr\Include_::class, - ]; - foreach ($prefixOps as $prefixOp) { - $this->fixupMap[$prefixOp] = ['expr' => self::FIXUP_PREC_RIGHT]; - } - } - - /** - * Lazily initializes the removal map. - * - * The removal map is used to determine which additional tokens should be removed when a - * certain node is replaced by null. - */ - protected function initializeRemovalMap() { - if ($this->removalMap) return; - - $stripBoth = ['left' => \T_WHITESPACE, 'right' => \T_WHITESPACE]; - $stripLeft = ['left' => \T_WHITESPACE]; - $stripRight = ['right' => \T_WHITESPACE]; - $stripDoubleArrow = ['right' => \T_DOUBLE_ARROW]; - $stripColon = ['left' => ':']; - $stripEquals = ['left' => '=']; - $this->removalMap = [ - 'Expr_ArrayDimFetch->dim' => $stripBoth, - 'Expr_ArrayItem->key' => $stripDoubleArrow, - 'Expr_ArrowFunction->returnType' => $stripColon, - 'Expr_Closure->returnType' => $stripColon, - 'Expr_Exit->expr' => $stripBoth, - 'Expr_Ternary->if' => $stripBoth, - 'Expr_Yield->key' => $stripDoubleArrow, - 'Expr_Yield->value' => $stripBoth, - 'Param->type' => $stripRight, - 'Param->default' => $stripEquals, - 'Stmt_Break->num' => $stripBoth, - 'Stmt_Catch->var' => $stripLeft, - 'Stmt_ClassMethod->returnType' => $stripColon, - 'Stmt_Class->extends' => ['left' => \T_EXTENDS], - 'Stmt_Enum->scalarType' => $stripColon, - 'Stmt_EnumCase->expr' => $stripEquals, - 'Expr_PrintableNewAnonClass->extends' => ['left' => \T_EXTENDS], - 'Stmt_Continue->num' => $stripBoth, - 'Stmt_Foreach->keyVar' => $stripDoubleArrow, - 'Stmt_Function->returnType' => $stripColon, - 'Stmt_If->else' => $stripLeft, - 'Stmt_Namespace->name' => $stripLeft, - 'Stmt_Property->type' => $stripRight, - 'Stmt_PropertyProperty->default' => $stripEquals, - 'Stmt_Return->expr' => $stripBoth, - 'Stmt_StaticVar->default' => $stripEquals, - 'Stmt_TraitUseAdaptation_Alias->newName' => $stripLeft, - 'Stmt_TryCatch->finally' => $stripLeft, - // 'Stmt_Case->cond': Replace with "default" - // 'Stmt_Class->name': Unclear what to do - // 'Stmt_Declare->stmts': Not a plain node - // 'Stmt_TraitUseAdaptation_Alias->newModifier': Not a plain node - ]; - } - - protected function initializeInsertionMap() { - if ($this->insertionMap) return; - - // TODO: "yield" where both key and value are inserted doesn't work - // [$find, $beforeToken, $extraLeft, $extraRight] - $this->insertionMap = [ - 'Expr_ArrayDimFetch->dim' => ['[', false, null, null], - 'Expr_ArrayItem->key' => [null, false, null, ' => '], - 'Expr_ArrowFunction->returnType' => [')', false, ' : ', null], - 'Expr_Closure->returnType' => [')', false, ' : ', null], - 'Expr_Ternary->if' => ['?', false, ' ', ' '], - 'Expr_Yield->key' => [\T_YIELD, false, null, ' => '], - 'Expr_Yield->value' => [\T_YIELD, false, ' ', null], - 'Param->type' => [null, false, null, ' '], - 'Param->default' => [null, false, ' = ', null], - 'Stmt_Break->num' => [\T_BREAK, false, ' ', null], - 'Stmt_Catch->var' => [null, false, ' ', null], - 'Stmt_ClassMethod->returnType' => [')', false, ' : ', null], - 'Stmt_Class->extends' => [null, false, ' extends ', null], - 'Stmt_Enum->scalarType' => [null, false, ' : ', null], - 'Stmt_EnumCase->expr' => [null, false, ' = ', null], - 'Expr_PrintableNewAnonClass->extends' => [null, ' extends ', null], - 'Stmt_Continue->num' => [\T_CONTINUE, false, ' ', null], - 'Stmt_Foreach->keyVar' => [\T_AS, false, null, ' => '], - 'Stmt_Function->returnType' => [')', false, ' : ', null], - 'Stmt_If->else' => [null, false, ' ', null], - 'Stmt_Namespace->name' => [\T_NAMESPACE, false, ' ', null], - 'Stmt_Property->type' => [\T_VARIABLE, true, null, ' '], - 'Stmt_PropertyProperty->default' => [null, false, ' = ', null], - 'Stmt_Return->expr' => [\T_RETURN, false, ' ', null], - 'Stmt_StaticVar->default' => [null, false, ' = ', null], - //'Stmt_TraitUseAdaptation_Alias->newName' => [T_AS, false, ' ', null], // TODO - 'Stmt_TryCatch->finally' => [null, false, ' ', null], - - // 'Expr_Exit->expr': Complicated due to optional () - // 'Stmt_Case->cond': Conversion from default to case - // 'Stmt_Class->name': Unclear - // 'Stmt_Declare->stmts': Not a proper node - // 'Stmt_TraitUseAdaptation_Alias->newModifier': Not a proper node - ]; - } - - protected function initializeListInsertionMap() { - if ($this->listInsertionMap) return; - - $this->listInsertionMap = [ - // special - //'Expr_ShellExec->parts' => '', // TODO These need to be treated more carefully - //'Scalar_Encapsed->parts' => '', - 'Stmt_Catch->types' => '|', - 'UnionType->types' => '|', - 'IntersectionType->types' => '&', - 'Stmt_If->elseifs' => ' ', - 'Stmt_TryCatch->catches' => ' ', - - // comma-separated lists - 'Expr_Array->items' => ', ', - 'Expr_ArrowFunction->params' => ', ', - 'Expr_Closure->params' => ', ', - 'Expr_Closure->uses' => ', ', - 'Expr_FuncCall->args' => ', ', - 'Expr_Isset->vars' => ', ', - 'Expr_List->items' => ', ', - 'Expr_MethodCall->args' => ', ', - 'Expr_NullsafeMethodCall->args' => ', ', - 'Expr_New->args' => ', ', - 'Expr_PrintableNewAnonClass->args' => ', ', - 'Expr_StaticCall->args' => ', ', - 'Stmt_ClassConst->consts' => ', ', - 'Stmt_ClassMethod->params' => ', ', - 'Stmt_Class->implements' => ', ', - 'Stmt_Enum->implements' => ', ', - 'Expr_PrintableNewAnonClass->implements' => ', ', - 'Stmt_Const->consts' => ', ', - 'Stmt_Declare->declares' => ', ', - 'Stmt_Echo->exprs' => ', ', - 'Stmt_For->init' => ', ', - 'Stmt_For->cond' => ', ', - 'Stmt_For->loop' => ', ', - 'Stmt_Function->params' => ', ', - 'Stmt_Global->vars' => ', ', - 'Stmt_GroupUse->uses' => ', ', - 'Stmt_Interface->extends' => ', ', - 'Stmt_Match->arms' => ', ', - 'Stmt_Property->props' => ', ', - 'Stmt_StaticVar->vars' => ', ', - 'Stmt_TraitUse->traits' => ', ', - 'Stmt_TraitUseAdaptation_Precedence->insteadof' => ', ', - 'Stmt_Unset->vars' => ', ', - 'Stmt_Use->uses' => ', ', - 'MatchArm->conds' => ', ', - 'AttributeGroup->attrs' => ', ', - - // statement lists - 'Expr_Closure->stmts' => "\n", - 'Stmt_Case->stmts' => "\n", - 'Stmt_Catch->stmts' => "\n", - 'Stmt_Class->stmts' => "\n", - 'Stmt_Enum->stmts' => "\n", - 'Expr_PrintableNewAnonClass->stmts' => "\n", - 'Stmt_Interface->stmts' => "\n", - 'Stmt_Trait->stmts' => "\n", - 'Stmt_ClassMethod->stmts' => "\n", - 'Stmt_Declare->stmts' => "\n", - 'Stmt_Do->stmts' => "\n", - 'Stmt_ElseIf->stmts' => "\n", - 'Stmt_Else->stmts' => "\n", - 'Stmt_Finally->stmts' => "\n", - 'Stmt_Foreach->stmts' => "\n", - 'Stmt_For->stmts' => "\n", - 'Stmt_Function->stmts' => "\n", - 'Stmt_If->stmts' => "\n", - 'Stmt_Namespace->stmts' => "\n", - 'Stmt_Class->attrGroups' => "\n", - 'Stmt_Enum->attrGroups' => "\n", - 'Stmt_EnumCase->attrGroups' => "\n", - 'Stmt_Interface->attrGroups' => "\n", - 'Stmt_Trait->attrGroups' => "\n", - 'Stmt_Function->attrGroups' => "\n", - 'Stmt_ClassMethod->attrGroups' => "\n", - 'Stmt_ClassConst->attrGroups' => "\n", - 'Stmt_Property->attrGroups' => "\n", - 'Expr_PrintableNewAnonClass->attrGroups' => ' ', - 'Expr_Closure->attrGroups' => ' ', - 'Expr_ArrowFunction->attrGroups' => ' ', - 'Param->attrGroups' => ' ', - 'Stmt_Switch->cases' => "\n", - 'Stmt_TraitUse->adaptations' => "\n", - 'Stmt_TryCatch->stmts' => "\n", - 'Stmt_While->stmts' => "\n", - - // dummy for top-level context - 'File->stmts' => "\n", - ]; - } - - protected function initializeEmptyListInsertionMap() { - if ($this->emptyListInsertionMap) return; - - // TODO Insertion into empty statement lists. - - // [$find, $extraLeft, $extraRight] - $this->emptyListInsertionMap = [ - 'Expr_ArrowFunction->params' => ['(', '', ''], - 'Expr_Closure->uses' => [')', ' use(', ')'], - 'Expr_Closure->params' => ['(', '', ''], - 'Expr_FuncCall->args' => ['(', '', ''], - 'Expr_MethodCall->args' => ['(', '', ''], - 'Expr_NullsafeMethodCall->args' => ['(', '', ''], - 'Expr_New->args' => ['(', '', ''], - 'Expr_PrintableNewAnonClass->args' => ['(', '', ''], - 'Expr_PrintableNewAnonClass->implements' => [null, ' implements ', ''], - 'Expr_StaticCall->args' => ['(', '', ''], - 'Stmt_Class->implements' => [null, ' implements ', ''], - 'Stmt_Enum->implements' => [null, ' implements ', ''], - 'Stmt_ClassMethod->params' => ['(', '', ''], - 'Stmt_Interface->extends' => [null, ' extends ', ''], - 'Stmt_Function->params' => ['(', '', ''], - - /* These cannot be empty to start with: - * Expr_Isset->vars - * Stmt_Catch->types - * Stmt_Const->consts - * Stmt_ClassConst->consts - * Stmt_Declare->declares - * Stmt_Echo->exprs - * Stmt_Global->vars - * Stmt_GroupUse->uses - * Stmt_Property->props - * Stmt_StaticVar->vars - * Stmt_TraitUse->traits - * Stmt_TraitUseAdaptation_Precedence->insteadof - * Stmt_Unset->vars - * Stmt_Use->uses - * UnionType->types - */ - - /* TODO - * Stmt_If->elseifs - * Stmt_TryCatch->catches - * Expr_Array->items - * Expr_List->items - * Stmt_For->init - * Stmt_For->cond - * Stmt_For->loop - */ - ]; - } - - protected function initializeModifierChangeMap() { - if ($this->modifierChangeMap) return; - - $this->modifierChangeMap = [ - 'Stmt_ClassConst->flags' => \T_CONST, - 'Stmt_ClassMethod->flags' => \T_FUNCTION, - 'Stmt_Class->flags' => \T_CLASS, - 'Stmt_Property->flags' => \T_VARIABLE, - 'Param->flags' => \T_VARIABLE, - //'Stmt_TraitUseAdaptation_Alias->newModifier' => 0, // TODO - ]; - - // List of integer subnodes that are not modifiers: - // Expr_Include->type - // Stmt_GroupUse->type - // Stmt_Use->type - // Stmt_UseUse->type - } -} diff --git a/lib/paragonie/random_compat/LICENSE b/lib/paragonie/random_compat/LICENSE deleted file mode 100644 index 45c7017df..000000000 --- a/lib/paragonie/random_compat/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Paragon Initiative Enterprises - -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/lib/paragonie/random_compat/build-phar.sh b/lib/paragonie/random_compat/build-phar.sh deleted file mode 100644 index b4a5ba31c..000000000 --- a/lib/paragonie/random_compat/build-phar.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -basedir=$( dirname $( readlink -f ${BASH_SOURCE[0]} ) ) - -php -dphar.readonly=0 "$basedir/other/build_phar.php" $* \ No newline at end of file diff --git a/lib/paragonie/random_compat/composer.json b/lib/paragonie/random_compat/composer.json deleted file mode 100644 index f2b9c4e51..000000000 --- a/lib/paragonie/random_compat/composer.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "paragonie/random_compat", - "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", - "keywords": [ - "csprng", - "random", - "polyfill", - "pseudorandom" - ], - "license": "MIT", - "type": "library", - "authors": [ - { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com", - "homepage": "https://paragonie.com" - } - ], - "support": { - "issues": "https://github.com/paragonie/random_compat/issues", - "email": "info@paragonie.com", - "source": "https://github.com/paragonie/random_compat" - }, - "require": { - "php": ">= 7" - }, - "require-dev": { - "vimeo/psalm": "^1", - "phpunit/phpunit": "4.*|5.*" - }, - "suggest": { - "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." - } -} diff --git a/lib/paragonie/random_compat/dist/random_compat.phar.pubkey b/lib/paragonie/random_compat/dist/random_compat.phar.pubkey deleted file mode 100644 index eb50ebfcd..000000000 --- a/lib/paragonie/random_compat/dist/random_compat.phar.pubkey +++ /dev/null @@ -1,5 +0,0 @@ ------BEGIN PUBLIC KEY----- -MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEEd+wCqJDrx5B4OldM0dQE0ZMX+lx1ZWm -pui0SUqD4G29L3NGsz9UhJ/0HjBdbnkhIK5xviT0X5vtjacF6ajgcCArbTB+ds+p -+h7Q084NuSuIpNb6YPfoUFgC/CL9kAoc ------END PUBLIC KEY----- diff --git a/lib/paragonie/random_compat/dist/random_compat.phar.pubkey.asc b/lib/paragonie/random_compat/dist/random_compat.phar.pubkey.asc deleted file mode 100644 index 6a1d7f300..000000000 --- a/lib/paragonie/random_compat/dist/random_compat.phar.pubkey.asc +++ /dev/null @@ -1,11 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2.0.22 (MingW32) - -iQEcBAABAgAGBQJWtW1hAAoJEGuXocKCZATaJf0H+wbZGgskK1dcRTsuVJl9IWip -QwGw/qIKI280SD6/ckoUMxKDCJiFuPR14zmqnS36k7N5UNPnpdTJTS8T11jttSpg -1LCmgpbEIpgaTah+cELDqFCav99fS+bEiAL5lWDAHBTE/XPjGVCqeehyPYref4IW -NDBIEsvnHPHPLsn6X5jq4+Yj5oUixgxaMPiR+bcO4Sh+RzOVB6i2D0upWfRXBFXA -NNnsg9/zjvoC7ZW73y9uSH+dPJTt/Vgfeiv52/v41XliyzbUyLalf02GNPY+9goV -JHG1ulEEBJOCiUD9cE1PUIJwHA/HqyhHIvV350YoEFiHl8iSwm7SiZu5kPjaq74= -=B6+8 ------END PGP SIGNATURE----- diff --git a/lib/paragonie/random_compat/lib/random.php b/lib/paragonie/random_compat/lib/random.php deleted file mode 100644 index c7731a56f..000000000 --- a/lib/paragonie/random_compat/lib/random.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php -/** - * Random_* Compatibility Library - * for using the new PHP 7 random_* API in PHP 5 projects - * - * @version 2.99.99 - * @released 2018-06-06 - * - * The MIT License (MIT) - * - * Copyright (c) 2015 - 2018 Paragon Initiative Enterprises - * - * 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. - */ - -// NOP diff --git a/lib/paragonie/random_compat/other/build_phar.php b/lib/paragonie/random_compat/other/build_phar.php deleted file mode 100644 index 70ef4b2ed..000000000 --- a/lib/paragonie/random_compat/other/build_phar.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php -$dist = dirname(__DIR__).'/dist'; -if (!is_dir($dist)) { - mkdir($dist, 0755); -} -if (file_exists($dist.'/random_compat.phar')) { - unlink($dist.'/random_compat.phar'); -} -$phar = new Phar( - $dist.'/random_compat.phar', - FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::KEY_AS_FILENAME, - 'random_compat.phar' -); -rename( - dirname(__DIR__).'/lib/random.php', - dirname(__DIR__).'/lib/index.php' -); -$phar->buildFromDirectory(dirname(__DIR__).'/lib'); -rename( - dirname(__DIR__).'/lib/index.php', - dirname(__DIR__).'/lib/random.php' -); - -/** - * If we pass an (optional) path to a private key as a second argument, we will - * sign the Phar with OpenSSL. - * - * If you leave this out, it will produce an unsigned .phar! - */ -if ($argc > 1) { - if (!@is_readable($argv[1])) { - echo 'Could not read the private key file:', $argv[1], "\n"; - exit(255); - } - $pkeyFile = file_get_contents($argv[1]); - - $private = openssl_get_privatekey($pkeyFile); - if ($private !== false) { - $pkey = ''; - openssl_pkey_export($private, $pkey); - $phar->setSignatureAlgorithm(Phar::OPENSSL, $pkey); - - /** - * Save the corresponding public key to the file - */ - if (!@is_readable($dist.'/random_compat.phar.pubkey')) { - $details = openssl_pkey_get_details($private); - file_put_contents( - $dist.'/random_compat.phar.pubkey', - $details['key'] - ); - } - } else { - echo 'An error occurred reading the private key from OpenSSL.', "\n"; - exit(255); - } -} diff --git a/lib/paragonie/random_compat/psalm-autoload.php b/lib/paragonie/random_compat/psalm-autoload.php deleted file mode 100644 index d71d1b818..000000000 --- a/lib/paragonie/random_compat/psalm-autoload.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -require_once 'lib/byte_safe_strings.php'; -require_once 'lib/cast_to_int.php'; -require_once 'lib/error_polyfill.php'; -require_once 'other/ide_stubs/libsodium.php'; -require_once 'lib/random.php'; - -$int = random_int(0, 65536); diff --git a/lib/paragonie/random_compat/psalm.xml b/lib/paragonie/random_compat/psalm.xml deleted file mode 100644 index 596d99dd6..000000000 --- a/lib/paragonie/random_compat/psalm.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0"?> -<psalm - autoloader="psalm-autoload.php" - stopOnFirstError="false" - useDocblockTypes="true" -> - <projectFiles> - <directory name="lib" /> - </projectFiles> - <issueHandlers> - <RedundantConditionGivenDocblockType errorLevel="info" /> - <UnresolvableInclude errorLevel="info" /> - <DuplicateClass errorLevel="info" /> - <InvalidOperand errorLevel="info" /> - <UndefinedConstant errorLevel="info" /> - <MissingReturnType errorLevel="info" /> - <InvalidReturnType errorLevel="info" /> - </issueHandlers> -</psalm> diff --git a/lib/pear/archive_tar/.github/FUNDING.yml b/lib/pear/archive_tar/.github/FUNDING.yml deleted file mode 100644 index 4a0f72b64..000000000 --- a/lib/pear/archive_tar/.github/FUNDING.yml +++ /dev/null @@ -1,2 +0,0 @@ -github: [mrook] -patreon: michielrook diff --git a/lib/pear/archive_tar/.github/dependabot.yml b/lib/pear/archive_tar/.github/dependabot.yml deleted file mode 100644 index a51bb0bd4..000000000 --- a/lib/pear/archive_tar/.github/dependabot.yml +++ /dev/null @@ -1,11 +0,0 @@ -# To get started with Dependabot version updates, you'll need to specify which -# package ecosystems to update and where the package manifests are located. -# Please see the documentation for all configuration options: -# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates - -version: 2 -updates: - - package-ecosystem: "composer" # See documentation for possible values - directory: "/" # Location of package manifests - schedule: - interval: "daily" diff --git a/lib/pear/archive_tar/.github/workflows/build.yml b/lib/pear/archive_tar/.github/workflows/build.yml deleted file mode 100644 index 5bcc73b50..000000000 --- a/lib/pear/archive_tar/.github/workflows/build.yml +++ /dev/null @@ -1,40 +0,0 @@ -on: - push: - branches: - - master - pull_request: - -jobs: - test: - runs-on: ${{ matrix.operating-system }} - strategy: - fail-fast: false - matrix: - operating-system: [ ubuntu-latest ] - php: [ '5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0' ] - dependencies: [ 'locked' ] - - name: PHP ${{ matrix.php }} on ${{ matrix.operating-system }} with ${{ matrix.dependencies }} dependencies - - steps: - - uses: actions/checkout@v2 - name: Checkout repository - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - - - uses: ramsey/composer-install@v1 - with: - dependency-versions: ${{ matrix.dependencies }} - - - name: Install PEAR - run: | - sudo apt-get install php-pear - - - name: Run tests - run: | - sudo pear install -f package.xml - pear version - pear run-tests -qr tests/ || { cat run-tests.log; for i in `find tests/ -name '*.out'`; do echo "$i"; cat "$i"; done; exit 1; } diff --git a/lib/pear/archive_tar/.gitignore b/lib/pear/archive_tar/.gitignore deleted file mode 100644 index c703991e8..000000000 --- a/lib/pear/archive_tar/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -# composer related -composer.lock -composer.phar -vendor -# IDE -.idea -# eclipse -.buildpath -.project -.settings -# pear -.tarballs -*.tgz -# phpunit -build diff --git a/lib/pear/archive_tar/.travis.yml b/lib/pear/archive_tar/.travis.yml deleted file mode 100644 index f103381b1..000000000 --- a/lib/pear/archive_tar/.travis.yml +++ /dev/null @@ -1,29 +0,0 @@ -sudo: false -language: php -matrix: - fast_finish: true - allow_failures: - - php: nightly - include: - - php: 5.2 - dist: precise - - php: 5.3 - dist: precise - - php: 5.4 - dist: trusty - - php: 5.5 - dist: trusty - - php: 5.6 - - php: 7.0 - - php: 7.1 - - php: 7.2 - - php: 7.3 - - php: 7.4 - - php: nightly -install: -# - pear upgrade --force --alldeps pear/pear - - pear install -f package.xml -script: - - pear version - - pear run-tests -qr tests/ - - for i in `find tests/ -name '*.out'`; do echo "$i"; cat "$i"; done diff --git a/lib/pear/archive_tar/Archive/Tar.php b/lib/pear/archive_tar/Archive/Tar.php deleted file mode 100644 index 3356ad6ac..000000000 --- a/lib/pear/archive_tar/Archive/Tar.php +++ /dev/null @@ -1,2530 +0,0 @@ -<?php -/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ - -/** - * File::CSV - * - * PHP versions 4 and 5 - * - * Copyright (c) 1997-2008, - * Vincent Blavet <vincent@phpconcept.net> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - * - * @category File_Formats - * @package Archive_Tar - * @author Vincent Blavet <vincent@phpconcept.net> - * @copyright 1997-2010 The Authors - * @license http://www.opensource.org/licenses/bsd-license.php New BSD License - * @version CVS: $Id$ - * @link http://pear.php.net/package/Archive_Tar - */ - -// If the PEAR class cannot be loaded via the autoloader, -// then try to require_once it from the PHP include path. -if (!class_exists('PEAR')) { - require_once 'PEAR.php'; -} - -define('ARCHIVE_TAR_ATT_SEPARATOR', 90001); -define('ARCHIVE_TAR_END_BLOCK', pack("a512", '')); - -if (!function_exists('gzopen') && function_exists('gzopen64')) { - function gzopen($filename, $mode, $use_include_path = 0) - { - return gzopen64($filename, $mode, $use_include_path); - } -} - -if (!function_exists('gztell') && function_exists('gztell64')) { - function gztell($zp) - { - return gztell64($zp); - } -} - -if (!function_exists('gzseek') && function_exists('gzseek64')) { - function gzseek($zp, $offset, $whence = SEEK_SET) - { - return gzseek64($zp, $offset, $whence); - } -} - -/** - * Creates a (compressed) Tar archive - * - * @package Archive_Tar - * @author Vincent Blavet <vincent@phpconcept.net> - * @license http://www.opensource.org/licenses/bsd-license.php New BSD License - * @version $Revision$ - */ -class Archive_Tar extends PEAR -{ - /** - * @var string Name of the Tar - */ - public $_tarname = ''; - - /** - * @var boolean if true, the Tar file will be gzipped - */ - public $_compress = false; - - /** - * @var string Type of compression : 'none', 'gz', 'bz2' or 'lzma2' - */ - public $_compress_type = 'none'; - - /** - * @var string Explode separator - */ - public $_separator = ' '; - - /** - * @var file descriptor - */ - public $_file = 0; - - /** - * @var string Local Tar name of a remote Tar (http:// or ftp://) - */ - public $_temp_tarname = ''; - - /** - * @var string regular expression for ignoring files or directories - */ - public $_ignore_regexp = ''; - - /** - * @var object PEAR_Error object - */ - public $error_object = null; - - /** - * Format for data extraction - * - * @var string - */ - public $_fmt = ''; - - /** - * @var int Length of the read buffer in bytes - */ - protected $buffer_length; - - /** - * Archive_Tar Class constructor. This flavour of the constructor only - * declare a new Archive_Tar object, identifying it by the name of the - * tar file. - * If the compress argument is set the tar will be read or created as a - * gzip or bz2 compressed TAR file. - * - * @param string $p_tarname The name of the tar archive to create - * @param string $p_compress can be null, 'gz', 'bz2' or 'lzma2'. This - * parameter indicates if gzip, bz2 or lzma2 compression - * is required. For compatibility reason the - * boolean value 'true' means 'gz'. - * @param int $buffer_length Length of the read buffer in bytes - * - * @return bool - */ - public function __construct($p_tarname, $p_compress = null, $buffer_length = 512) - { - parent::__construct(); - - $this->_compress = false; - $this->_compress_type = 'none'; - if (($p_compress === null) || ($p_compress == '')) { - if (@file_exists($p_tarname)) { - if ($fp = @fopen($p_tarname, "rb")) { - // look for gzip magic cookie - $data = fread($fp, 2); - fclose($fp); - if ($data == "\37\213") { - $this->_compress = true; - $this->_compress_type = 'gz'; - // No sure it's enought for a magic code .... - } elseif ($data == "BZ") { - $this->_compress = true; - $this->_compress_type = 'bz2'; - } elseif (file_get_contents($p_tarname, false, null, 1, 4) == '7zXZ') { - $this->_compress = true; - $this->_compress_type = 'lzma2'; - } - } - } else { - // probably a remote file or some file accessible - // through a stream interface - if (substr($p_tarname, -2) == 'gz') { - $this->_compress = true; - $this->_compress_type = 'gz'; - } elseif ((substr($p_tarname, -3) == 'bz2') || - (substr($p_tarname, -2) == 'bz') - ) { - $this->_compress = true; - $this->_compress_type = 'bz2'; - } else { - if (substr($p_tarname, -2) == 'xz') { - $this->_compress = true; - $this->_compress_type = 'lzma2'; - } - } - } - } else { - if (($p_compress === true) || ($p_compress == 'gz')) { - $this->_compress = true; - $this->_compress_type = 'gz'; - } else { - if ($p_compress == 'bz2') { - $this->_compress = true; - $this->_compress_type = 'bz2'; - } else { - if ($p_compress == 'lzma2') { - $this->_compress = true; - $this->_compress_type = 'lzma2'; - } else { - $this->_error( - "Unsupported compression type '$p_compress'\n" . - "Supported types are 'gz', 'bz2' and 'lzma2'.\n" - ); - return false; - } - } - } - } - $this->_tarname = $p_tarname; - if ($this->_compress) { // assert zlib or bz2 or xz extension support - if ($this->_compress_type == 'gz') { - $extname = 'zlib'; - } else { - if ($this->_compress_type == 'bz2') { - $extname = 'bz2'; - } else { - if ($this->_compress_type == 'lzma2') { - $extname = 'xz'; - } - } - } - - if (!extension_loaded($extname)) { - PEAR::loadExtension($extname); - } - if (!extension_loaded($extname)) { - $this->_error( - "The extension '$extname' couldn't be found.\n" . - "Please make sure your version of PHP was built " . - "with '$extname' support.\n" - ); - return false; - } - } - - - if (version_compare(PHP_VERSION, "5.5.0-dev") < 0) { - $this->_fmt = "a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/" . - "a8checksum/a1typeflag/a100link/a6magic/a2version/" . - "a32uname/a32gname/a8devmajor/a8devminor/a131prefix"; - } else { - $this->_fmt = "Z100filename/Z8mode/Z8uid/Z8gid/Z12size/Z12mtime/" . - "Z8checksum/Z1typeflag/Z100link/Z6magic/Z2version/" . - "Z32uname/Z32gname/Z8devmajor/Z8devminor/Z131prefix"; - } - - - $this->buffer_length = $buffer_length; - } - - public function __destruct() - { - $this->_close(); - // ----- Look for a local copy to delete - if ($this->_temp_tarname != '' && (bool) preg_match('/^tar[[:alnum:]]*\.tmp$/', $this->_temp_tarname)) { - @unlink($this->_temp_tarname); - } - } - - /** - * This method creates the archive file and add the files / directories - * that are listed in $p_filelist. - * If a file with the same name exist and is writable, it is replaced - * by the new tar. - * The method return false and a PEAR error text. - * The $p_filelist parameter can be an array of string, each string - * representing a filename or a directory name with their path if - * needed. It can also be a single string with names separated by a - * single blank. - * For each directory added in the archive, the files and - * sub-directories are also added. - * See also createModify() method for more details. - * - * @param array $p_filelist An array of filenames and directory names, or a - * single string with names separated by a single - * blank space. - * - * @return true on success, false on error. - * @see createModify() - */ - public function create($p_filelist) - { - return $this->createModify($p_filelist, '', ''); - } - - /** - * This method add the files / directories that are listed in $p_filelist in - * the archive. If the archive does not exist it is created. - * The method return false and a PEAR error text. - * The files and directories listed are only added at the end of the archive, - * even if a file with the same name is already archived. - * See also createModify() method for more details. - * - * @param array $p_filelist An array of filenames and directory names, or a - * single string with names separated by a single - * blank space. - * - * @return true on success, false on error. - * @see createModify() - * @access public - */ - public function add($p_filelist) - { - return $this->addModify($p_filelist, '', ''); - } - - /** - * @param string $p_path - * @param bool $p_preserve - * @param bool $p_symlinks - * @return bool - */ - public function extract($p_path = '', $p_preserve = false, $p_symlinks = true) - { - return $this->extractModify($p_path, '', $p_preserve, $p_symlinks); - } - - /** - * @return array|int - */ - public function listContent() - { - $v_list_detail = array(); - - if ($this->_openRead()) { - if (!$this->_extractList('', $v_list_detail, "list", '', '')) { - unset($v_list_detail); - $v_list_detail = 0; - } - $this->_close(); - } - - return $v_list_detail; - } - - /** - * This method creates the archive file and add the files / directories - * that are listed in $p_filelist. - * If the file already exists and is writable, it is replaced by the - * new tar. It is a create and not an add. If the file exists and is - * read-only or is a directory it is not replaced. The method return - * false and a PEAR error text. - * The $p_filelist parameter can be an array of string, each string - * representing a filename or a directory name with their path if - * needed. It can also be a single string with names separated by a - * single blank. - * The path indicated in $p_remove_dir will be removed from the - * memorized path of each file / directory listed when this path - * exists. By default nothing is removed (empty path '') - * The path indicated in $p_add_dir will be added at the beginning of - * the memorized path of each file / directory listed. However it can - * be set to empty ''. The adding of a path is done after the removing - * of path. - * The path add/remove ability enables the user to prepare an archive - * for extraction in a different path than the origin files are. - * See also addModify() method for file adding properties. - * - * @param array $p_filelist An array of filenames and directory names, - * or a single string with names separated by - * a single blank space. - * @param string $p_add_dir A string which contains a path to be added - * to the memorized path of each element in - * the list. - * @param string $p_remove_dir A string which contains a path to be - * removed from the memorized path of each - * element in the list, when relevant. - * - * @return boolean true on success, false on error. - * @see addModify() - */ - public function createModify($p_filelist, $p_add_dir, $p_remove_dir = '') - { - $v_result = true; - - if (!$this->_openWrite()) { - return false; - } - - if ($p_filelist != '') { - if (is_array($p_filelist)) { - $v_list = $p_filelist; - } elseif (is_string($p_filelist)) { - $v_list = explode($this->_separator, $p_filelist); - } else { - $this->_cleanFile(); - $this->_error('Invalid file list'); - return false; - } - - $v_result = $this->_addList($v_list, $p_add_dir, $p_remove_dir); - } - - if ($v_result) { - $this->_writeFooter(); - $this->_close(); - } else { - $this->_cleanFile(); - } - - return $v_result; - } - - /** - * This method add the files / directories listed in $p_filelist at the - * end of the existing archive. If the archive does not yet exists it - * is created. - * The $p_filelist parameter can be an array of string, each string - * representing a filename or a directory name with their path if - * needed. It can also be a single string with names separated by a - * single blank. - * The path indicated in $p_remove_dir will be removed from the - * memorized path of each file / directory listed when this path - * exists. By default nothing is removed (empty path '') - * The path indicated in $p_add_dir will be added at the beginning of - * the memorized path of each file / directory listed. However it can - * be set to empty ''. The adding of a path is done after the removing - * of path. - * The path add/remove ability enables the user to prepare an archive - * for extraction in a different path than the origin files are. - * If a file/dir is already in the archive it will only be added at the - * end of the archive. There is no update of the existing archived - * file/dir. However while extracting the archive, the last file will - * replace the first one. This results in a none optimization of the - * archive size. - * If a file/dir does not exist the file/dir is ignored. However an - * error text is send to PEAR error. - * If a file/dir is not readable the file/dir is ignored. However an - * error text is send to PEAR error. - * - * @param array $p_filelist An array of filenames and directory - * names, or a single string with names - * separated by a single blank space. - * @param string $p_add_dir A string which contains a path to be - * added to the memorized path of each - * element in the list. - * @param string $p_remove_dir A string which contains a path to be - * removed from the memorized path of - * each element in the list, when - * relevant. - * - * @return true on success, false on error. - */ - public function addModify($p_filelist, $p_add_dir, $p_remove_dir = '') - { - $v_result = true; - - if (!$this->_isArchive()) { - $v_result = $this->createModify( - $p_filelist, - $p_add_dir, - $p_remove_dir - ); - } else { - if (is_array($p_filelist)) { - $v_list = $p_filelist; - } elseif (is_string($p_filelist)) { - $v_list = explode($this->_separator, $p_filelist); - } else { - $this->_error('Invalid file list'); - return false; - } - - $v_result = $this->_append($v_list, $p_add_dir, $p_remove_dir); - } - - return $v_result; - } - - /** - * This method add a single string as a file at the - * end of the existing archive. If the archive does not yet exists it - * is created. - * - * @param string $p_filename A string which contains the full - * filename path that will be associated - * with the string. - * @param string $p_string The content of the file added in - * the archive. - * @param bool|int $p_datetime A custom date/time (unix timestamp) - * for the file (optional). - * @param array $p_params An array of optional params: - * stamp => the datetime (replaces - * datetime above if it exists) - * mode => the permissions on the - * file (600 by default) - * type => is this a link? See the - * tar specification for details. - * (default = regular file) - * uid => the user ID of the file - * (default = 0 = root) - * gid => the group ID of the file - * (default = 0 = root) - * - * @return true on success, false on error. - */ - public function addString($p_filename, $p_string, $p_datetime = false, $p_params = array()) - { - $p_stamp = @$p_params["stamp"] ? $p_params["stamp"] : ($p_datetime ? $p_datetime : time()); - $p_mode = @$p_params["mode"] ? $p_params["mode"] : 0600; - $p_type = @$p_params["type"] ? $p_params["type"] : ""; - $p_uid = @$p_params["uid"] ? $p_params["uid"] : ""; - $p_gid = @$p_params["gid"] ? $p_params["gid"] : ""; - $v_result = true; - - if (!$this->_isArchive()) { - if (!$this->_openWrite()) { - return false; - } - $this->_close(); - } - - if (!$this->_openAppend()) { - return false; - } - - // Need to check the get back to the temporary file ? .... - $v_result = $this->_addString($p_filename, $p_string, $p_datetime, $p_params); - - $this->_writeFooter(); - - $this->_close(); - - return $v_result; - } - - /** - * This method extract all the content of the archive in the directory - * indicated by $p_path. When relevant the memorized path of the - * files/dir can be modified by removing the $p_remove_path path at the - * beginning of the file/dir path. - * While extracting a file, if the directory path does not exists it is - * created. - * While extracting a file, if the file already exists it is replaced - * without looking for last modification date. - * While extracting a file, if the file already exists and is write - * protected, the extraction is aborted. - * While extracting a file, if a directory with the same name already - * exists, the extraction is aborted. - * While extracting a directory, if a file with the same name already - * exists, the extraction is aborted. - * While extracting a file/directory if the destination directory exist - * and is write protected, or does not exist but can not be created, - * the extraction is aborted. - * If after extraction an extracted file does not show the correct - * stored file size, the extraction is aborted. - * When the extraction is aborted, a PEAR error text is set and false - * is returned. However the result can be a partial extraction that may - * need to be manually cleaned. - * - * @param string $p_path The path of the directory where the - * files/dir need to by extracted. - * @param string $p_remove_path Part of the memorized path that can be - * removed if present at the beginning of - * the file/dir path. - * @param boolean $p_preserve Preserve user/group ownership of files - * @param boolean $p_symlinks Allow symlinks. - * - * @return boolean true on success, false on error. - * @see extractList() - */ - public function extractModify($p_path, $p_remove_path, $p_preserve = false, $p_symlinks = true) - { - $v_result = true; - $v_list_detail = array(); - - if ($v_result = $this->_openRead()) { - $v_result = $this->_extractList( - $p_path, - $v_list_detail, - "complete", - 0, - $p_remove_path, - $p_preserve, - $p_symlinks - ); - $this->_close(); - } - - return $v_result; - } - - /** - * This method extract from the archive one file identified by $p_filename. - * The return value is a string with the file content, or NULL on error. - * - * @param string $p_filename The path of the file to extract in a string. - * - * @return a string with the file content or NULL. - */ - public function extractInString($p_filename) - { - if ($this->_openRead()) { - $v_result = $this->_extractInString($p_filename); - $this->_close(); - } else { - $v_result = null; - } - - return $v_result; - } - - /** - * This method extract from the archive only the files indicated in the - * $p_filelist. These files are extracted in the current directory or - * in the directory indicated by the optional $p_path parameter. - * If indicated the $p_remove_path can be used in the same way as it is - * used in extractModify() method. - * - * @param array $p_filelist An array of filenames and directory names, - * or a single string with names separated - * by a single blank space. - * @param string $p_path The path of the directory where the - * files/dir need to by extracted. - * @param string $p_remove_path Part of the memorized path that can be - * removed if present at the beginning of - * the file/dir path. - * @param boolean $p_preserve Preserve user/group ownership of files - * @param boolean $p_symlinks Allow symlinks. - * - * @return true on success, false on error. - * @see extractModify() - */ - public function extractList($p_filelist, $p_path = '', $p_remove_path = '', $p_preserve = false, $p_symlinks = true) - { - $v_result = true; - $v_list_detail = array(); - - if (is_array($p_filelist)) { - $v_list = $p_filelist; - } elseif (is_string($p_filelist)) { - $v_list = explode($this->_separator, $p_filelist); - } else { - $this->_error('Invalid string list'); - return false; - } - - if ($v_result = $this->_openRead()) { - $v_result = $this->_extractList( - $p_path, - $v_list_detail, - "partial", - $v_list, - $p_remove_path, - $p_preserve, - $p_symlinks - ); - $this->_close(); - } - - return $v_result; - } - - /** - * This method set specific attributes of the archive. It uses a variable - * list of parameters, in the format attribute code + attribute values : - * $arch->setAttribute(ARCHIVE_TAR_ATT_SEPARATOR, ','); - * - * @return true on success, false on error. - */ - public function setAttribute() - { - $v_result = true; - - // ----- Get the number of variable list of arguments - if (($v_size = func_num_args()) == 0) { - return true; - } - - // ----- Get the arguments - $v_att_list = func_get_args(); - - // ----- Read the attributes - $i = 0; - while ($i < $v_size) { - - // ----- Look for next option - switch ($v_att_list[$i]) { - // ----- Look for options that request a string value - case ARCHIVE_TAR_ATT_SEPARATOR : - // ----- Check the number of parameters - if (($i + 1) >= $v_size) { - $this->_error( - 'Invalid number of parameters for ' - . 'attribute ARCHIVE_TAR_ATT_SEPARATOR' - ); - return false; - } - - // ----- Get the value - $this->_separator = $v_att_list[$i + 1]; - $i++; - break; - - default : - $this->_error('Unknown attribute code ' . $v_att_list[$i] . ''); - return false; - } - - // ----- Next attribute - $i++; - } - - return $v_result; - } - - /** - * This method sets the regular expression for ignoring files and directories - * at import, for example: - * $arch->setIgnoreRegexp("#CVS|\.svn#"); - * - * @param string $regexp regular expression defining which files or directories to ignore - */ - public function setIgnoreRegexp($regexp) - { - $this->_ignore_regexp = $regexp; - } - - /** - * This method sets the regular expression for ignoring all files and directories - * matching the filenames in the array list at import, for example: - * $arch->setIgnoreList(array('CVS', '.svn', 'bin/tool')); - * - * @param array $list a list of file or directory names to ignore - * - * @access public - */ - public function setIgnoreList($list) - { - $list = str_replace(array('#', '.', '^', '$'), array('\#', '\.', '\^', '\$'), $list); - $regexp = '#/' . join('$|/', $list) . '#'; - $this->setIgnoreRegexp($regexp); - } - - /** - * @param string $p_message - */ - public function _error($p_message) - { - $this->error_object = $this->raiseError($p_message); - } - - /** - * @param string $p_message - */ - public function _warning($p_message) - { - $this->error_object = $this->raiseError($p_message); - } - - /** - * @param string $p_filename - * @return bool - */ - public function _isArchive($p_filename = null) - { - if ($p_filename == null) { - $p_filename = $this->_tarname; - } - clearstatcache(); - return @is_file($p_filename) && !@is_link($p_filename); - } - - /** - * @return bool - */ - public function _openWrite() - { - if ($this->_compress_type == 'gz' && function_exists('gzopen')) { - $this->_file = @gzopen($this->_tarname, "wb9"); - } else { - if ($this->_compress_type == 'bz2' && function_exists('bzopen')) { - $this->_file = @bzopen($this->_tarname, "w"); - } else { - if ($this->_compress_type == 'lzma2' && function_exists('xzopen')) { - $this->_file = @xzopen($this->_tarname, 'w'); - } else { - if ($this->_compress_type == 'none') { - $this->_file = @fopen($this->_tarname, "wb"); - } else { - $this->_error( - 'Unknown or missing compression type (' - . $this->_compress_type . ')' - ); - return false; - } - } - } - } - - if ($this->_file == 0) { - $this->_error( - 'Unable to open in write mode \'' - . $this->_tarname . '\'' - ); - return false; - } - - return true; - } - - /** - * @return bool - */ - public function _openRead() - { - if (strtolower(substr($this->_tarname, 0, 7)) == 'http://') { - - // ----- Look if a local copy need to be done - if ($this->_temp_tarname == '') { - $this->_temp_tarname = uniqid('tar') . '.tmp'; - if (!$v_file_from = @fopen($this->_tarname, 'rb')) { - $this->_error( - 'Unable to open in read mode \'' - . $this->_tarname . '\'' - ); - $this->_temp_tarname = ''; - return false; - } - if (!$v_file_to = @fopen($this->_temp_tarname, 'wb')) { - $this->_error( - 'Unable to open in write mode \'' - . $this->_temp_tarname . '\'' - ); - $this->_temp_tarname = ''; - return false; - } - while ($v_data = @fread($v_file_from, 1024)) { - @fwrite($v_file_to, $v_data); - } - @fclose($v_file_from); - @fclose($v_file_to); - } - - // ----- File to open if the local copy - $v_filename = $this->_temp_tarname; - } else { - // ----- File to open if the normal Tar file - - $v_filename = $this->_tarname; - } - - if ($this->_compress_type == 'gz' && function_exists('gzopen')) { - $this->_file = @gzopen($v_filename, "rb"); - } else { - if ($this->_compress_type == 'bz2' && function_exists('bzopen')) { - $this->_file = @bzopen($v_filename, "r"); - } else { - if ($this->_compress_type == 'lzma2' && function_exists('xzopen')) { - $this->_file = @xzopen($v_filename, "r"); - } else { - if ($this->_compress_type == 'none') { - $this->_file = @fopen($v_filename, "rb"); - } else { - $this->_error( - 'Unknown or missing compression type (' - . $this->_compress_type . ')' - ); - return false; - } - } - } - } - - if ($this->_file == 0) { - $this->_error('Unable to open in read mode \'' . $v_filename . '\''); - return false; - } - - return true; - } - - /** - * @return bool - */ - public function _openReadWrite() - { - if ($this->_compress_type == 'gz') { - $this->_file = @gzopen($this->_tarname, "r+b"); - } else { - if ($this->_compress_type == 'bz2') { - $this->_error( - 'Unable to open bz2 in read/write mode \'' - . $this->_tarname . '\' (limitation of bz2 extension)' - ); - return false; - } else { - if ($this->_compress_type == 'lzma2') { - $this->_error( - 'Unable to open lzma2 in read/write mode \'' - . $this->_tarname . '\' (limitation of lzma2 extension)' - ); - return false; - } else { - if ($this->_compress_type == 'none') { - $this->_file = @fopen($this->_tarname, "r+b"); - } else { - $this->_error( - 'Unknown or missing compression type (' - . $this->_compress_type . ')' - ); - return false; - } - } - } - } - - if ($this->_file == 0) { - $this->_error( - 'Unable to open in read/write mode \'' - . $this->_tarname . '\'' - ); - return false; - } - - return true; - } - - /** - * @return bool - */ - public function _close() - { - //if (isset($this->_file)) { - if (is_resource($this->_file)) { - if ($this->_compress_type == 'gz') { - @gzclose($this->_file); - } else { - if ($this->_compress_type == 'bz2') { - @bzclose($this->_file); - } else { - if ($this->_compress_type == 'lzma2') { - @xzclose($this->_file); - } else { - if ($this->_compress_type == 'none') { - @fclose($this->_file); - } else { - $this->_error( - 'Unknown or missing compression type (' - . $this->_compress_type . ')' - ); - } - } - } - } - - $this->_file = 0; - } - - // ----- Look if a local copy need to be erase - // Note that it might be interesting to keep the url for a time : ToDo - if ($this->_temp_tarname != '') { - @unlink($this->_temp_tarname); - $this->_temp_tarname = ''; - } - - return true; - } - - /** - * @return bool - */ - public function _cleanFile() - { - $this->_close(); - - // ----- Look for a local copy - if ($this->_temp_tarname != '') { - // ----- Remove the local copy but not the remote tarname - @unlink($this->_temp_tarname); - $this->_temp_tarname = ''; - } else { - // ----- Remove the local tarname file - @unlink($this->_tarname); - } - $this->_tarname = ''; - - return true; - } - - /** - * @param mixed $p_binary_data - * @param integer $p_len - * @return bool - */ - public function _writeBlock($p_binary_data, $p_len = null) - { - if (is_resource($this->_file)) { - if ($p_len === null) { - if ($this->_compress_type == 'gz') { - @gzputs($this->_file, $p_binary_data); - } else { - if ($this->_compress_type == 'bz2') { - @bzwrite($this->_file, $p_binary_data); - } else { - if ($this->_compress_type == 'lzma2') { - @xzwrite($this->_file, $p_binary_data); - } else { - if ($this->_compress_type == 'none') { - @fputs($this->_file, $p_binary_data); - } else { - $this->_error( - 'Unknown or missing compression type (' - . $this->_compress_type . ')' - ); - } - } - } - } - } else { - if ($this->_compress_type == 'gz') { - @gzputs($this->_file, $p_binary_data, $p_len); - } else { - if ($this->_compress_type == 'bz2') { - @bzwrite($this->_file, $p_binary_data, $p_len); - } else { - if ($this->_compress_type == 'lzma2') { - @xzwrite($this->_file, $p_binary_data, $p_len); - } else { - if ($this->_compress_type == 'none') { - @fputs($this->_file, $p_binary_data, $p_len); - } else { - $this->_error( - 'Unknown or missing compression type (' - . $this->_compress_type . ')' - ); - } - } - } - } - } - } - return true; - } - - /** - * @return null|string - */ - public function _readBlock() - { - $v_block = null; - if (is_resource($this->_file)) { - if ($this->_compress_type == 'gz') { - $v_block = @gzread($this->_file, 512); - } else { - if ($this->_compress_type == 'bz2') { - $v_block = @bzread($this->_file, 512); - } else { - if ($this->_compress_type == 'lzma2') { - $v_block = @xzread($this->_file, 512); - } else { - if ($this->_compress_type == 'none') { - $v_block = @fread($this->_file, 512); - } else { - $this->_error( - 'Unknown or missing compression type (' - . $this->_compress_type . ')' - ); - } - } - } - } - } - return $v_block; - } - - /** - * @param null $p_len - * @return bool - */ - public function _jumpBlock($p_len = null) - { - if (is_resource($this->_file)) { - if ($p_len === null) { - $p_len = 1; - } - - if ($this->_compress_type == 'gz') { - @gzseek($this->_file, gztell($this->_file) + ($p_len * 512)); - } else { - if ($this->_compress_type == 'bz2') { - // ----- Replace missing bztell() and bzseek() - for ($i = 0; $i < $p_len; $i++) { - $this->_readBlock(); - } - } else { - if ($this->_compress_type == 'lzma2') { - // ----- Replace missing xztell() and xzseek() - for ($i = 0; $i < $p_len; $i++) { - $this->_readBlock(); - } - } else { - if ($this->_compress_type == 'none') { - @fseek($this->_file, $p_len * 512, SEEK_CUR); - } else { - $this->_error( - 'Unknown or missing compression type (' - . $this->_compress_type . ')' - ); - } - } - } - } - } - return true; - } - - /** - * @return bool - */ - public function _writeFooter() - { - if (is_resource($this->_file)) { - // ----- Write the last 0 filled block for end of archive - $v_binary_data = pack('a1024', ''); - $this->_writeBlock($v_binary_data); - } - return true; - } - - /** - * @param array $p_list - * @param string $p_add_dir - * @param string $p_remove_dir - * @return bool - */ - public function _addList($p_list, $p_add_dir, $p_remove_dir) - { - $v_result = true; - $v_header = array(); - - // ----- Remove potential windows directory separator - $p_add_dir = $this->_translateWinPath($p_add_dir); - $p_remove_dir = $this->_translateWinPath($p_remove_dir, false); - - if (!$this->_file) { - $this->_error('Invalid file descriptor'); - return false; - } - - if (sizeof($p_list) == 0) { - return true; - } - - foreach ($p_list as $v_filename) { - if (!$v_result) { - break; - } - - // ----- Skip the current tar name - if ($v_filename == $this->_tarname) { - continue; - } - - if ($v_filename == '') { - continue; - } - - // ----- ignore files and directories matching the ignore regular expression - if ($this->_ignore_regexp && preg_match($this->_ignore_regexp, '/' . $v_filename)) { - $this->_warning("File '$v_filename' ignored"); - continue; - } - - if (!file_exists($v_filename) && !is_link($v_filename)) { - $this->_warning("File '$v_filename' does not exist"); - continue; - } - - // ----- Add the file or directory header - if (!$this->_addFile($v_filename, $v_header, $p_add_dir, $p_remove_dir)) { - return false; - } - - if (@is_dir($v_filename) && !@is_link($v_filename)) { - if (!($p_hdir = opendir($v_filename))) { - $this->_warning("Directory '$v_filename' can not be read"); - continue; - } - while (false !== ($p_hitem = readdir($p_hdir))) { - if (($p_hitem != '.') && ($p_hitem != '..')) { - if ($v_filename != ".") { - $p_temp_list[0] = $v_filename . '/' . $p_hitem; - } else { - $p_temp_list[0] = $p_hitem; - } - - $v_result = $this->_addList( - $p_temp_list, - $p_add_dir, - $p_remove_dir - ); - } - } - - unset($p_temp_list); - unset($p_hdir); - unset($p_hitem); - } - } - - return $v_result; - } - - /** - * @param string $p_filename - * @param mixed $p_header - * @param string $p_add_dir - * @param string $p_remove_dir - * @param null $v_stored_filename - * @return bool - */ - public function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir, $v_stored_filename = null) - { - if (!$this->_file) { - $this->_error('Invalid file descriptor'); - return false; - } - - if ($p_filename == '') { - $this->_error('Invalid file name'); - return false; - } - - if (is_null($v_stored_filename)) { - // ----- Calculate the stored filename - $p_filename = $this->_translateWinPath($p_filename, false); - $v_stored_filename = $p_filename; - - if (strcmp($p_filename, $p_remove_dir) == 0) { - return true; - } - - if ($p_remove_dir != '') { - if (substr($p_remove_dir, -1) != '/') { - $p_remove_dir .= '/'; - } - - if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir) { - $v_stored_filename = substr($p_filename, strlen($p_remove_dir)); - } - } - - $v_stored_filename = $this->_translateWinPath($v_stored_filename); - if ($p_add_dir != '') { - if (substr($p_add_dir, -1) == '/') { - $v_stored_filename = $p_add_dir . $v_stored_filename; - } else { - $v_stored_filename = $p_add_dir . '/' . $v_stored_filename; - } - } - - $v_stored_filename = $this->_pathReduction($v_stored_filename); - } - - if ($this->_isArchive($p_filename)) { - if (($v_file = @fopen($p_filename, "rb")) == 0) { - $this->_warning( - "Unable to open file '" . $p_filename - . "' in binary read mode" - ); - return true; - } - - if (!$this->_writeHeader($p_filename, $v_stored_filename)) { - return false; - } - - while (($v_buffer = fread($v_file, $this->buffer_length)) != '') { - $buffer_length = strlen("$v_buffer"); - if ($buffer_length != $this->buffer_length) { - $pack_size = ((int)($buffer_length / 512) + ($buffer_length % 512 !== 0 ? 1 : 0)) * 512; - $pack_format = sprintf('a%d', $pack_size); - } else { - $pack_format = sprintf('a%d', $this->buffer_length); - } - $v_binary_data = pack($pack_format, "$v_buffer"); - $this->_writeBlock($v_binary_data); - } - - fclose($v_file); - } else { - // ----- Only header for dir - if (!$this->_writeHeader($p_filename, $v_stored_filename)) { - return false; - } - } - - return true; - } - - /** - * @param string $p_filename - * @param string $p_string - * @param bool $p_datetime - * @param array $p_params - * @return bool - */ - public function _addString($p_filename, $p_string, $p_datetime = false, $p_params = array()) - { - $p_stamp = @$p_params["stamp"] ? $p_params["stamp"] : ($p_datetime ? $p_datetime : time()); - $p_mode = @$p_params["mode"] ? $p_params["mode"] : 0600; - $p_type = @$p_params["type"] ? $p_params["type"] : ""; - $p_uid = @$p_params["uid"] ? $p_params["uid"] : 0; - $p_gid = @$p_params["gid"] ? $p_params["gid"] : 0; - if (!$this->_file) { - $this->_error('Invalid file descriptor'); - return false; - } - - if ($p_filename == '') { - $this->_error('Invalid file name'); - return false; - } - - // ----- Calculate the stored filename - $p_filename = $this->_translateWinPath($p_filename, false); - - // ----- If datetime is not specified, set current time - if ($p_datetime === false) { - $p_datetime = time(); - } - - if (!$this->_writeHeaderBlock( - $p_filename, - strlen($p_string), - $p_stamp, - $p_mode, - $p_type, - $p_uid, - $p_gid - ) - ) { - return false; - } - - $i = 0; - while (($v_buffer = substr($p_string, (($i++) * 512), 512)) != '') { - $v_binary_data = pack("a512", $v_buffer); - $this->_writeBlock($v_binary_data); - } - - return true; - } - - /** - * @param string $p_filename - * @param string $p_stored_filename - * @return bool - */ - public function _writeHeader($p_filename, $p_stored_filename) - { - if ($p_stored_filename == '') { - $p_stored_filename = $p_filename; - } - - $v_reduced_filename = $this->_pathReduction($p_stored_filename); - - if (strlen($v_reduced_filename) > 99) { - if (!$this->_writeLongHeader($v_reduced_filename, false)) { - return false; - } - } - - $v_linkname = ''; - if (@is_link($p_filename)) { - $v_linkname = readlink($p_filename); - } - - if (strlen($v_linkname) > 99) { - if (!$this->_writeLongHeader($v_linkname, true)) { - return false; - } - } - - $v_info = lstat($p_filename); - $v_uid = sprintf("%07s", DecOct($v_info[4])); - $v_gid = sprintf("%07s", DecOct($v_info[5])); - $v_perms = sprintf("%07s", DecOct($v_info['mode'] & 000777)); - $v_mtime = sprintf("%011s", DecOct($v_info['mtime'])); - - if (@is_link($p_filename)) { - $v_typeflag = '2'; - $v_size = sprintf("%011s", DecOct(0)); - } elseif (@is_dir($p_filename)) { - $v_typeflag = "5"; - $v_size = sprintf("%011s", DecOct(0)); - } else { - $v_typeflag = '0'; - clearstatcache(); - $v_size = sprintf("%011s", DecOct($v_info['size'])); - } - - $v_magic = 'ustar '; - $v_version = ' '; - $v_uname = ''; - $v_gname = ''; - - if (function_exists('posix_getpwuid')) { - $userinfo = posix_getpwuid($v_info[4]); - $groupinfo = posix_getgrgid($v_info[5]); - - if (isset($userinfo['name'])) { - $v_uname = $userinfo['name']; - } - - if (isset($groupinfo['name'])) { - $v_gname = $groupinfo['name']; - } - } - - $v_devmajor = ''; - $v_devminor = ''; - $v_prefix = ''; - - $v_binary_data_first = pack( - "a100a8a8a8a12a12", - $v_reduced_filename, - $v_perms, - $v_uid, - $v_gid, - $v_size, - $v_mtime - ); - $v_binary_data_last = pack( - "a1a100a6a2a32a32a8a8a155a12", - $v_typeflag, - $v_linkname, - $v_magic, - $v_version, - $v_uname, - $v_gname, - $v_devmajor, - $v_devminor, - $v_prefix, - '' - ); - - // ----- Calculate the checksum - $v_checksum = 0; - // ..... First part of the header - for ($i = 0; $i < 148; $i++) { - $v_checksum += ord(substr($v_binary_data_first, $i, 1)); - } - // ..... Ignore the checksum value and replace it by ' ' (space) - for ($i = 148; $i < 156; $i++) { - $v_checksum += ord(' '); - } - // ..... Last part of the header - for ($i = 156, $j = 0; $i < 512; $i++, $j++) { - $v_checksum += ord(substr($v_binary_data_last, $j, 1)); - } - - // ----- Write the first 148 bytes of the header in the archive - $this->_writeBlock($v_binary_data_first, 148); - - // ----- Write the calculated checksum - $v_checksum = sprintf("%06s\0 ", DecOct($v_checksum)); - $v_binary_data = pack("a8", $v_checksum); - $this->_writeBlock($v_binary_data, 8); - - // ----- Write the last 356 bytes of the header in the archive - $this->_writeBlock($v_binary_data_last, 356); - - return true; - } - - /** - * @param string $p_filename - * @param int $p_size - * @param int $p_mtime - * @param int $p_perms - * @param string $p_type - * @param int $p_uid - * @param int $p_gid - * @return bool - */ - public function _writeHeaderBlock( - $p_filename, - $p_size, - $p_mtime = 0, - $p_perms = 0, - $p_type = '', - $p_uid = 0, - $p_gid = 0 - ) - { - $p_filename = $this->_pathReduction($p_filename); - - if (strlen($p_filename) > 99) { - if (!$this->_writeLongHeader($p_filename, false)) { - return false; - } - } - - if ($p_type == "5") { - $v_size = sprintf("%011s", DecOct(0)); - } else { - $v_size = sprintf("%011s", DecOct($p_size)); - } - - $v_uid = sprintf("%07s", DecOct($p_uid)); - $v_gid = sprintf("%07s", DecOct($p_gid)); - $v_perms = sprintf("%07s", DecOct($p_perms & 000777)); - - $v_mtime = sprintf("%11s", DecOct($p_mtime)); - - $v_linkname = ''; - - $v_magic = 'ustar '; - - $v_version = ' '; - - if (function_exists('posix_getpwuid')) { - $userinfo = posix_getpwuid($p_uid); - $groupinfo = posix_getgrgid($p_gid); - - if ($userinfo === false || $groupinfo === false) { - $v_uname = ''; - $v_gname = ''; - } else { - $v_uname = $userinfo['name']; - $v_gname = $groupinfo['name']; - } - } else { - $v_uname = ''; - $v_gname = ''; - } - - $v_devmajor = ''; - - $v_devminor = ''; - - $v_prefix = ''; - - $v_binary_data_first = pack( - "a100a8a8a8a12A12", - $p_filename, - $v_perms, - $v_uid, - $v_gid, - $v_size, - $v_mtime - ); - $v_binary_data_last = pack( - "a1a100a6a2a32a32a8a8a155a12", - $p_type, - $v_linkname, - $v_magic, - $v_version, - $v_uname, - $v_gname, - $v_devmajor, - $v_devminor, - $v_prefix, - '' - ); - - // ----- Calculate the checksum - $v_checksum = 0; - // ..... First part of the header - for ($i = 0; $i < 148; $i++) { - $v_checksum += ord(substr($v_binary_data_first, $i, 1)); - } - // ..... Ignore the checksum value and replace it by ' ' (space) - for ($i = 148; $i < 156; $i++) { - $v_checksum += ord(' '); - } - // ..... Last part of the header - for ($i = 156, $j = 0; $i < 512; $i++, $j++) { - $v_checksum += ord(substr($v_binary_data_last, $j, 1)); - } - - // ----- Write the first 148 bytes of the header in the archive - $this->_writeBlock($v_binary_data_first, 148); - - // ----- Write the calculated checksum - $v_checksum = sprintf("%06s ", DecOct($v_checksum)); - $v_binary_data = pack("a8", $v_checksum); - $this->_writeBlock($v_binary_data, 8); - - // ----- Write the last 356 bytes of the header in the archive - $this->_writeBlock($v_binary_data_last, 356); - - return true; - } - - /** - * @param string $p_filename - * @return bool - */ - public function _writeLongHeader($p_filename, $is_link = false) - { - $v_uid = sprintf("%07s", 0); - $v_gid = sprintf("%07s", 0); - $v_perms = sprintf("%07s", 0); - $v_size = sprintf("%'011s", DecOct(strlen($p_filename))); - $v_mtime = sprintf("%011s", 0); - $v_typeflag = ($is_link ? 'K' : 'L'); - $v_linkname = ''; - $v_magic = 'ustar '; - $v_version = ' '; - $v_uname = ''; - $v_gname = ''; - $v_devmajor = ''; - $v_devminor = ''; - $v_prefix = ''; - - $v_binary_data_first = pack( - "a100a8a8a8a12a12", - '././@LongLink', - $v_perms, - $v_uid, - $v_gid, - $v_size, - $v_mtime - ); - $v_binary_data_last = pack( - "a1a100a6a2a32a32a8a8a155a12", - $v_typeflag, - $v_linkname, - $v_magic, - $v_version, - $v_uname, - $v_gname, - $v_devmajor, - $v_devminor, - $v_prefix, - '' - ); - - // ----- Calculate the checksum - $v_checksum = 0; - // ..... First part of the header - for ($i = 0; $i < 148; $i++) { - $v_checksum += ord(substr($v_binary_data_first, $i, 1)); - } - // ..... Ignore the checksum value and replace it by ' ' (space) - for ($i = 148; $i < 156; $i++) { - $v_checksum += ord(' '); - } - // ..... Last part of the header - for ($i = 156, $j = 0; $i < 512; $i++, $j++) { - $v_checksum += ord(substr($v_binary_data_last, $j, 1)); - } - - // ----- Write the first 148 bytes of the header in the archive - $this->_writeBlock($v_binary_data_first, 148); - - // ----- Write the calculated checksum - $v_checksum = sprintf("%06s\0 ", DecOct($v_checksum)); - $v_binary_data = pack("a8", $v_checksum); - $this->_writeBlock($v_binary_data, 8); - - // ----- Write the last 356 bytes of the header in the archive - $this->_writeBlock($v_binary_data_last, 356); - - // ----- Write the filename as content of the block - $i = 0; - while (($v_buffer = substr($p_filename, (($i++) * 512), 512)) != '') { - $v_binary_data = pack("a512", "$v_buffer"); - $this->_writeBlock($v_binary_data); - } - - return true; - } - - /** - * @param mixed $v_binary_data - * @param mixed $v_header - * @return bool - */ - public function _readHeader($v_binary_data, &$v_header) - { - if (strlen($v_binary_data) == 0) { - $v_header['filename'] = ''; - return true; - } - - if (strlen($v_binary_data) != 512) { - $v_header['filename'] = ''; - $this->_error('Invalid block size : ' . strlen($v_binary_data)); - return false; - } - - if (!is_array($v_header)) { - $v_header = array(); - } - // ----- Calculate the checksum - $v_checksum = 0; - // ..... First part of the header - $v_binary_split = str_split($v_binary_data); - $v_checksum += array_sum(array_map('ord', array_slice($v_binary_split, 0, 148))); - $v_checksum += array_sum(array_map('ord', array(' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',))); - $v_checksum += array_sum(array_map('ord', array_slice($v_binary_split, 156, 512))); - - - $v_data = unpack($this->_fmt, $v_binary_data); - - if (strlen($v_data["prefix"]) > 0) { - $v_data["filename"] = "$v_data[prefix]/$v_data[filename]"; - } - - // ----- Extract the checksum - $v_data_checksum = trim($v_data['checksum']); - if (!preg_match('/^[0-7]*$/', $v_data_checksum)) { - $this->_error( - 'Invalid checksum for file "' . $v_data['filename'] - . '" : ' . $v_data_checksum . ' extracted' - ); - return false; - } - - $v_header['checksum'] = OctDec($v_data_checksum); - if ($v_header['checksum'] != $v_checksum) { - $v_header['filename'] = ''; - - // ----- Look for last block (empty block) - if (($v_checksum == 256) && ($v_header['checksum'] == 0)) { - return true; - } - - $this->_error( - 'Invalid checksum for file "' . $v_data['filename'] - . '" : ' . $v_checksum . ' calculated, ' - . $v_header['checksum'] . ' expected' - ); - return false; - } - - // ----- Extract the properties - $v_header['filename'] = rtrim($v_data['filename'], "\0"); - if ($this->_isMaliciousFilename($v_header['filename'])) { - $this->_error( - 'Malicious .tar detected, file "' . $v_header['filename'] . - '" will not install in desired directory tree' - ); - return false; - } - $v_header['mode'] = OctDec(trim($v_data['mode'])); - $v_header['uid'] = OctDec(trim($v_data['uid'])); - $v_header['gid'] = OctDec(trim($v_data['gid'])); - $v_header['size'] = $this->_tarRecToSize($v_data['size']); - $v_header['mtime'] = OctDec(trim($v_data['mtime'])); - if (($v_header['typeflag'] = $v_data['typeflag']) == "5") { - $v_header['size'] = 0; - } - $v_header['link'] = trim($v_data['link']); - /* ----- All these fields are removed form the header because - they do not carry interesting info - $v_header[magic] = trim($v_data[magic]); - $v_header[version] = trim($v_data[version]); - $v_header[uname] = trim($v_data[uname]); - $v_header[gname] = trim($v_data[gname]); - $v_header[devmajor] = trim($v_data[devmajor]); - $v_header[devminor] = trim($v_data[devminor]); - */ - - return true; - } - - /** - * Convert Tar record size to actual size - * - * @param string $tar_size - * @return size of tar record in bytes - */ - private function _tarRecToSize($tar_size) - { - /* - * First byte of size has a special meaning if bit 7 is set. - * - * Bit 7 indicates base-256 encoding if set. - * Bit 6 is the sign bit. - * Bits 5:0 are most significant value bits. - */ - $ch = ord($tar_size[0]); - if ($ch & 0x80) { - // Full 12-bytes record is required. - $rec_str = $tar_size . "\x00"; - - $size = ($ch & 0x40) ? -1 : 0; - $size = ($size << 6) | ($ch & 0x3f); - - for ($num_ch = 1; $num_ch < 12; ++$num_ch) { - $size = ($size * 256) + ord($rec_str[$num_ch]); - } - - return $size; - - } else { - return OctDec(trim($tar_size)); - } - } - - /** - * Detect and report a malicious file name - * - * @param string $file - * - * @return bool - */ - private function _isMaliciousFilename($file) - { - if (strpos($file, '://') !== false) { - return true; - } - if (strpos($file, '../') !== false || strpos($file, '..\\') !== false) { - return true; - } - return false; - } - - /** - * @param $v_header - * @return bool - */ - public function _readLongHeader(&$v_header) - { - $v_filename = ''; - $v_filesize = $v_header['size']; - $n = floor($v_header['size'] / 512); - for ($i = 0; $i < $n; $i++) { - $v_content = $this->_readBlock(); - $v_filename .= $v_content; - } - if (($v_header['size'] % 512) != 0) { - $v_content = $this->_readBlock(); - $v_filename .= $v_content; - } - - // ----- Read the next header - $v_binary_data = $this->_readBlock(); - - if (!$this->_readHeader($v_binary_data, $v_header)) { - return false; - } - - $v_filename = rtrim(substr($v_filename, 0, $v_filesize), "\0"); - $v_header['filename'] = $v_filename; - if ($this->_isMaliciousFilename($v_filename)) { - $this->_error( - 'Malicious .tar detected, file "' . $v_filename . - '" will not install in desired directory tree' - ); - return false; - } - - return true; - } - - /** - * This method extract from the archive one file identified by $p_filename. - * The return value is a string with the file content, or null on error. - * - * @param string $p_filename The path of the file to extract in a string. - * - * @return a string with the file content or null. - */ - private function _extractInString($p_filename) - { - $v_result_str = ""; - - while (strlen($v_binary_data = $this->_readBlock()) != 0) { - if (!$this->_readHeader($v_binary_data, $v_header)) { - return null; - } - - if ($v_header['filename'] == '') { - continue; - } - - switch ($v_header['typeflag']) { - case 'L': - { - if (!$this->_readLongHeader($v_header)) { - return null; - } - } - break; - - case 'K': - { - $v_link_header = $v_header; - if (!$this->_readLongHeader($v_link_header)) { - return null; - } - $v_header['link'] = $v_link_header['filename']; - } - break; - } - - if ($v_header['filename'] == $p_filename) { - if ($v_header['typeflag'] == "5") { - $this->_error( - 'Unable to extract in string a directory ' - . 'entry {' . $v_header['filename'] . '}' - ); - return null; - } else { - $n = floor($v_header['size'] / 512); - for ($i = 0; $i < $n; $i++) { - $v_result_str .= $this->_readBlock(); - } - if (($v_header['size'] % 512) != 0) { - $v_content = $this->_readBlock(); - $v_result_str .= substr( - $v_content, - 0, - ($v_header['size'] % 512) - ); - } - return $v_result_str; - } - } else { - $this->_jumpBlock(ceil(($v_header['size'] / 512))); - } - } - - return null; - } - - /** - * @param string $p_path - * @param string $p_list_detail - * @param string $p_mode - * @param string $p_file_list - * @param string $p_remove_path - * @param bool $p_preserve - * @param bool $p_symlinks - * @return bool - */ - public function _extractList( - $p_path, - &$p_list_detail, - $p_mode, - $p_file_list, - $p_remove_path, - $p_preserve = false, - $p_symlinks = true - ) - { - $v_result = true; - $v_nb = 0; - $v_extract_all = true; - $v_listing = false; - - $p_path = $this->_translateWinPath($p_path, false); - if ($p_path == '' || (substr($p_path, 0, 1) != '/' - && substr($p_path, 0, 3) != "../" && !strpos($p_path, ':')) - ) { - $p_path = "./" . $p_path; - } - $p_remove_path = $this->_translateWinPath($p_remove_path); - - // ----- Look for path to remove format (should end by /) - if (($p_remove_path != '') && (substr($p_remove_path, -1) != '/')) { - $p_remove_path .= '/'; - } - $p_remove_path_size = strlen($p_remove_path); - - switch ($p_mode) { - case "complete" : - $v_extract_all = true; - $v_listing = false; - break; - case "partial" : - $v_extract_all = false; - $v_listing = false; - break; - case "list" : - $v_extract_all = false; - $v_listing = true; - break; - default : - $this->_error('Invalid extract mode (' . $p_mode . ')'); - return false; - } - - clearstatcache(); - - while (strlen($v_binary_data = $this->_readBlock()) != 0) { - $v_extract_file = false; - $v_extraction_stopped = 0; - - if (!$this->_readHeader($v_binary_data, $v_header)) { - return false; - } - - if ($v_header['filename'] == '') { - continue; - } - - switch ($v_header['typeflag']) { - case 'L': - { - if (!$this->_readLongHeader($v_header)) { - return null; - } - } - break; - - case 'K': - { - $v_link_header = $v_header; - if (!$this->_readLongHeader($v_link_header)) { - return null; - } - $v_header['link'] = $v_link_header['filename']; - } - break; - } - - // ignore extended / pax headers - if ($v_header['typeflag'] == 'x' || $v_header['typeflag'] == 'g') { - $this->_jumpBlock(ceil(($v_header['size'] / 512))); - continue; - } - - if ((!$v_extract_all) && (is_array($p_file_list))) { - // ----- By default no unzip if the file is not found - $v_extract_file = false; - - for ($i = 0; $i < sizeof($p_file_list); $i++) { - // ----- Look if it is a directory - if (substr($p_file_list[$i], -1) == '/') { - // ----- Look if the directory is in the filename path - if ((strlen($v_header['filename']) > strlen($p_file_list[$i])) - && (substr($v_header['filename'], 0, strlen($p_file_list[$i])) - == $p_file_list[$i]) - ) { - $v_extract_file = true; - break; - } - } // ----- It is a file, so compare the file names - elseif ($p_file_list[$i] == $v_header['filename']) { - $v_extract_file = true; - break; - } - } - } else { - $v_extract_file = true; - } - - // ----- Look if this file need to be extracted - if (($v_extract_file) && (!$v_listing)) { - if (($p_remove_path != '') - && (substr($v_header['filename'] . '/', 0, $p_remove_path_size) - == $p_remove_path) - ) { - $v_header['filename'] = substr( - $v_header['filename'], - $p_remove_path_size - ); - if ($v_header['filename'] == '') { - continue; - } - } - if (($p_path != './') && ($p_path != '/')) { - while (substr($p_path, -1) == '/') { - $p_path = substr($p_path, 0, strlen($p_path) - 1); - } - - if (substr($v_header['filename'], 0, 1) == '/') { - $v_header['filename'] = $p_path . $v_header['filename']; - } else { - $v_header['filename'] = $p_path . '/' . $v_header['filename']; - } - } - if (file_exists($v_header['filename'])) { - if ((@is_dir($v_header['filename'])) - && ($v_header['typeflag'] == '') - ) { - $this->_error( - 'File ' . $v_header['filename'] - . ' already exists as a directory' - ); - return false; - } - if (($this->_isArchive($v_header['filename'])) - && ($v_header['typeflag'] == "5") - ) { - $this->_error( - 'Directory ' . $v_header['filename'] - . ' already exists as a file' - ); - return false; - } - if (!is_writeable($v_header['filename'])) { - $this->_error( - 'File ' . $v_header['filename'] - . ' already exists and is write protected' - ); - return false; - } - if (filemtime($v_header['filename']) > $v_header['mtime']) { - // To be completed : An error or silent no replace ? - } - } // ----- Check the directory availability and create it if necessary - elseif (($v_result - = $this->_dirCheck( - ($v_header['typeflag'] == "5" - ? $v_header['filename'] - : dirname($v_header['filename'])) - )) != 1 - ) { - $this->_error('Unable to create path for ' . $v_header['filename']); - return false; - } - - if ($v_extract_file) { - if ($v_header['typeflag'] == "5") { - if (!@file_exists($v_header['filename'])) { - if (!@mkdir($v_header['filename'], 0777)) { - $this->_error( - 'Unable to create directory {' - . $v_header['filename'] . '}' - ); - return false; - } - } - } elseif ($v_header['typeflag'] == "2") { - if (!$p_symlinks) { - $this->_warning('Symbolic links are not allowed. ' - . 'Unable to extract {' - . $v_header['filename'] . '}' - ); - return false; - } - $absolute_link = FALSE; - $link_depth = 0; - if (strpos($v_header['link'], "/") === 0 || strpos($v_header['link'], ':') !== FALSE) { - $absolute_link = TRUE; - } - else { - $s_filename = preg_replace('@^' . preg_quote($p_path) . '@', "", $v_header['filename']); - $s_linkname = str_replace('\\', '/', $v_header['link']); - foreach (explode("/", $s_filename) as $dir) { - if ($dir === "..") { - $link_depth--; - } elseif ($dir !== "" && $dir !== "." ) { - $link_depth++; - } - } - foreach (explode("/", $s_linkname) as $dir){ - if ($link_depth <= 0) { - break; - } - if ($dir === "..") { - $link_depth--; - } elseif ($dir !== "" && $dir !== ".") { - $link_depth++; - } - } - } - if ($absolute_link || $link_depth <= 0) { - $this->_error( - 'Out-of-path file extraction {' - . $v_header['filename'] . ' --> ' . - $v_header['link'] . '}' - ); - return false; - } - if (@file_exists($v_header['filename'])) { - @unlink($v_header['filename']); - } - if (!@symlink($v_header['link'], $v_header['filename'])) { - $this->_error( - 'Unable to extract symbolic link {' - . $v_header['filename'] . '}' - ); - return false; - } - } else { - if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) { - $this->_error( - 'Error while opening {' . $v_header['filename'] - . '} in write binary mode' - ); - return false; - } else { - $n = floor($v_header['size'] / 512); - for ($i = 0; $i < $n; $i++) { - $v_content = $this->_readBlock(); - fwrite($v_dest_file, $v_content, 512); - } - if (($v_header['size'] % 512) != 0) { - $v_content = $this->_readBlock(); - fwrite($v_dest_file, $v_content, ($v_header['size'] % 512)); - } - - @fclose($v_dest_file); - - if ($p_preserve) { - @chown($v_header['filename'], $v_header['uid']); - @chgrp($v_header['filename'], $v_header['gid']); - } - - // ----- Change the file mode, mtime - @touch($v_header['filename'], $v_header['mtime']); - if ($v_header['mode'] & 0111) { - // make file executable, obey umask - $mode = fileperms($v_header['filename']) | (~umask() & 0111); - @chmod($v_header['filename'], $mode); - } - } - - // ----- Check the file size - clearstatcache(); - if (!is_file($v_header['filename'])) { - $this->_error( - 'Extracted file ' . $v_header['filename'] - . 'does not exist. Archive may be corrupted.' - ); - return false; - } - - $filesize = filesize($v_header['filename']); - if ($filesize != $v_header['size']) { - $this->_error( - 'Extracted file ' . $v_header['filename'] - . ' does not have the correct file size \'' - . $filesize - . '\' (' . $v_header['size'] - . ' expected). Archive may be corrupted.' - ); - return false; - } - } - } else { - $this->_jumpBlock(ceil(($v_header['size'] / 512))); - } - } else { - $this->_jumpBlock(ceil(($v_header['size'] / 512))); - } - - /* TBC : Seems to be unused ... - if ($this->_compress) - $v_end_of_file = @gzeof($this->_file); - else - $v_end_of_file = @feof($this->_file); - */ - - if ($v_listing || $v_extract_file || $v_extraction_stopped) { - // ----- Log extracted files - if (($v_file_dir = dirname($v_header['filename'])) - == $v_header['filename'] - ) { - $v_file_dir = ''; - } - if ((substr($v_header['filename'], 0, 1) == '/') && ($v_file_dir == '')) { - $v_file_dir = '/'; - } - - $p_list_detail[$v_nb++] = $v_header; - if (is_array($p_file_list) && (count($p_list_detail) == count($p_file_list))) { - return true; - } - } - } - - return true; - } - - /** - * @return bool - */ - public function _openAppend() - { - if (filesize($this->_tarname) == 0) { - return $this->_openWrite(); - } - - if ($this->_compress) { - $this->_close(); - - if (!@rename($this->_tarname, $this->_tarname . ".tmp")) { - $this->_error( - 'Error while renaming \'' . $this->_tarname - . '\' to temporary file \'' . $this->_tarname - . '.tmp\'' - ); - return false; - } - - if ($this->_compress_type == 'gz') { - $v_temp_tar = @gzopen($this->_tarname . ".tmp", "rb"); - } elseif ($this->_compress_type == 'bz2') { - $v_temp_tar = @bzopen($this->_tarname . ".tmp", "r"); - } elseif ($this->_compress_type == 'lzma2') { - $v_temp_tar = @xzopen($this->_tarname . ".tmp", "r"); - } - - - if ($v_temp_tar == 0) { - $this->_error( - 'Unable to open file \'' . $this->_tarname - . '.tmp\' in binary read mode' - ); - @rename($this->_tarname . ".tmp", $this->_tarname); - return false; - } - - if (!$this->_openWrite()) { - @rename($this->_tarname . ".tmp", $this->_tarname); - return false; - } - - if ($this->_compress_type == 'gz') { - $end_blocks = 0; - - while (!@gzeof($v_temp_tar)) { - $v_buffer = @gzread($v_temp_tar, 512); - if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) { - $end_blocks++; - // do not copy end blocks, we will re-make them - // after appending - continue; - } elseif ($end_blocks > 0) { - for ($i = 0; $i < $end_blocks; $i++) { - $this->_writeBlock(ARCHIVE_TAR_END_BLOCK); - } - $end_blocks = 0; - } - $v_binary_data = pack("a512", $v_buffer); - $this->_writeBlock($v_binary_data); - } - - @gzclose($v_temp_tar); - } elseif ($this->_compress_type == 'bz2') { - $end_blocks = 0; - - while (strlen($v_buffer = @bzread($v_temp_tar, 512)) > 0) { - if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) { - $end_blocks++; - // do not copy end blocks, we will re-make them - // after appending - continue; - } elseif ($end_blocks > 0) { - for ($i = 0; $i < $end_blocks; $i++) { - $this->_writeBlock(ARCHIVE_TAR_END_BLOCK); - } - $end_blocks = 0; - } - $v_binary_data = pack("a512", $v_buffer); - $this->_writeBlock($v_binary_data); - } - - @bzclose($v_temp_tar); - } elseif ($this->_compress_type == 'lzma2') { - $end_blocks = 0; - - while (strlen($v_buffer = @xzread($v_temp_tar, 512)) > 0) { - if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) { - $end_blocks++; - // do not copy end blocks, we will re-make them - // after appending - continue; - } elseif ($end_blocks > 0) { - for ($i = 0; $i < $end_blocks; $i++) { - $this->_writeBlock(ARCHIVE_TAR_END_BLOCK); - } - $end_blocks = 0; - } - $v_binary_data = pack("a512", $v_buffer); - $this->_writeBlock($v_binary_data); - } - - @xzclose($v_temp_tar); - } - - if (!@unlink($this->_tarname . ".tmp")) { - $this->_error( - 'Error while deleting temporary file \'' - . $this->_tarname . '.tmp\'' - ); - } - } else { - // ----- For not compressed tar, just add files before the last - // one or two 512 bytes block - if (!$this->_openReadWrite()) { - return false; - } - - clearstatcache(); - $v_size = filesize($this->_tarname); - - // We might have zero, one or two end blocks. - // The standard is two, but we should try to handle - // other cases. - fseek($this->_file, $v_size - 1024); - if (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) { - fseek($this->_file, $v_size - 1024); - } elseif (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) { - fseek($this->_file, $v_size - 512); - } - } - - return true; - } - - /** - * @param $p_filelist - * @param string $p_add_dir - * @param string $p_remove_dir - * @return bool - */ - public function _append($p_filelist, $p_add_dir = '', $p_remove_dir = '') - { - if (!$this->_openAppend()) { - return false; - } - - if ($this->_addList($p_filelist, $p_add_dir, $p_remove_dir)) { - $this->_writeFooter(); - } - - $this->_close(); - - return true; - } - - /** - * Check if a directory exists and create it (including parent - * dirs) if not. - * - * @param string $p_dir directory to check - * - * @return bool true if the directory exists or was created - */ - public function _dirCheck($p_dir) - { - clearstatcache(); - if ((@is_dir($p_dir)) || ($p_dir == '')) { - return true; - } - - $p_parent_dir = dirname($p_dir); - - if (($p_parent_dir != $p_dir) && - ($p_parent_dir != '') && - (!$this->_dirCheck($p_parent_dir)) - ) { - return false; - } - - if (!@mkdir($p_dir, 0777)) { - $this->_error("Unable to create directory '$p_dir'"); - return false; - } - - return true; - } - - /** - * Compress path by changing for example "/dir/foo/../bar" to "/dir/bar", - * rand emove double slashes. - * - * @param string $p_dir path to reduce - * - * @return string reduced path - */ - private function _pathReduction($p_dir) - { - $v_result = ''; - - // ----- Look for not empty path - if ($p_dir != '') { - // ----- Explode path by directory names - $v_list = explode('/', $p_dir); - - // ----- Study directories from last to first - for ($i = sizeof($v_list) - 1; $i >= 0; $i--) { - // ----- Look for current path - if ($v_list[$i] == ".") { - // ----- Ignore this directory - // Should be the first $i=0, but no check is done - } else { - if ($v_list[$i] == "..") { - // ----- Ignore it and ignore the $i-1 - $i--; - } else { - if (($v_list[$i] == '') - && ($i != (sizeof($v_list) - 1)) - && ($i != 0) - ) { - // ----- Ignore only the double '//' in path, - // but not the first and last / - } else { - $v_result = $v_list[$i] . ($i != (sizeof($v_list) - 1) ? '/' - . $v_result : ''); - } - } - } - } - } - - if (defined('OS_WINDOWS') && OS_WINDOWS) { - $v_result = strtr($v_result, '\\', '/'); - } - - return $v_result; - } - - /** - * @param $p_path - * @param bool $p_remove_disk_letter - * @return string - */ - public function _translateWinPath($p_path, $p_remove_disk_letter = true) - { - if (defined('OS_WINDOWS') && OS_WINDOWS) { - // ----- Look for potential disk letter - if (($p_remove_disk_letter) - && (($v_position = strpos($p_path, ':')) != false) - ) { - $p_path = substr($p_path, $v_position + 1); - } - // ----- Change potential windows directory separator - if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0, 1) == '\\')) { - $p_path = strtr($p_path, '\\', '/'); - } - } - return $p_path; - } -} diff --git a/lib/pear/archive_tar/README.md b/lib/pear/archive_tar/README.md deleted file mode 100644 index f9c53be1a..000000000 --- a/lib/pear/archive_tar/README.md +++ /dev/null @@ -1,34 +0,0 @@ -Archive_Tar -========== - -![.github/workflows/build.yml](https://github.com/pear/Archive_Tar/workflows/.github/workflows/build.yml/badge.svg) - -This package provides handling of tar files in PHP. -It supports creating, listing, extracting and adding to tar files. -Gzip support is available if PHP has the zlib extension built-in or -loaded. Bz2 compression is also supported with the bz2 extension loaded. -Also Lzma2 compressed archives are supported with xz extension. - -This package is hosted at http://pear.php.net/package/Archive_Tar - -Please report all new issues via the PEAR bug tracker. - -Pull requests are welcome! - - -Testing, building ------------------ - -To test, run either -$ phpunit tests/ - or -$ pear run-tests -r - -To build, simply -$ pear package - -To install from scratch -$ pear install package.xml - -To upgrade -$ pear upgrade -f package.xml diff --git a/lib/pear/archive_tar/composer.json b/lib/pear/archive_tar/composer.json deleted file mode 100644 index e464d9d7b..000000000 --- a/lib/pear/archive_tar/composer.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "name": "pear/archive_tar", - "description": "Tar file management class with compression support (gzip, bzip2, lzma2)", - "type": "library", - "keywords": [ - "archive", - "tar" - ], - "homepage": "https://github.com/pear/Archive_Tar", - "license": "BSD-3-Clause", - "authors": [ - { - "name": "Vincent Blavet", - "email": "vincent@phpconcept.net" - }, - { - "name": "Greg Beaver", - "email": "greg@chiaraquartet.net" - }, - { - "name": "Michiel Rook", - "email": "mrook@php.net" - } - ], - "require": { - "php": ">=5.2.0", - "pear/pear-core-minimal": "^1.10.0alpha2" - }, - "suggest": { - "ext-zlib": "Gzip compression support.", - "ext-bz2": "Bz2 compression support.", - "ext-xz": "Lzma2 compression support." - }, - "autoload": { - "psr-0": { - "Archive_Tar": "" - } - }, - "include-path": [ - "./" - ], - "support": { - "issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=Archive_Tar", - "source": "https://github.com/pear/Archive_Tar" - }, - "require-dev": { - "phpunit/phpunit": "*" - }, - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - } -} diff --git a/lib/pear/archive_tar/package.xml b/lib/pear/archive_tar/package.xml deleted file mode 100644 index d4f20bd4b..000000000 --- a/lib/pear/archive_tar/package.xml +++ /dev/null @@ -1,712 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<package packagerversion="1.9.4" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd"> - <name>Archive_Tar</name> - <channel>pear.php.net</channel> - <summary>Tar file management class</summary> - <description>This class provides handling of tar files in PHP. -It supports creating, listing, extracting and adding to tar files. -Gzip support is available if PHP has the zlib extension built-in or -loaded. Bz2 compression is also supported with the bz2 extension loaded. -Also Lzma2 compressed archives are supported with xz extension.</description> - <lead> - <name>Vincent Blavet</name> - <user>vblavet</user> - <email>vincent@phpconcept.net</email> - <active>no</active> - </lead> - <lead> - <name>Greg Beaver</name> - <user>cellog</user> - <email>greg@chiaraquartet.net</email> - <active>no</active> - </lead> - <lead> - <name>Michiel Rook</name> - <user>mrook</user> - <email>mrook@php.net</email> - <active>yes</active> - </lead> - <helper> - <name>Stig Bakken</name> - <user>ssb</user> - <email>stig@php.net</email> - <active>no</active> - </helper> - <date>2021-07-20</date> - <time>18:00:00</time> - <version> - <release>1.4.14</release> - <api>1.4.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> -* Properly fix symbolic link path traversal (CVE-2021-32610) - </notes> - <contents> - <dir name="/"> - <dir name="Archive"> - <file baseinstalldir="/" name="Tar.php" role="php" /> - </dir> <!-- /Archive --> - <dir name="docs"> - <file baseinstalldir="/" name="Archive_Tar.txt" role="doc" /> - </dir> <!-- /docs --> - </dir> <!-- / --> - </contents> - <compatible> - <name>PEAR</name> - <channel>pear.php.net</channel> - <min>1.8.0</min> - <max>1.10.10</max> - </compatible> - <dependencies> - <required> - <php> - <min>5.2.0</min> - </php> - <pearinstaller> - <min>1.9.0</min> - </pearinstaller> - </required> - </dependencies> - <phprelease /> - <changelog> - <release> - <version> - <release>1.4.13</release> - <api>1.4.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2021-02-16</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> - * Fix Bug #27010: Relative symlinks failing (out-of path file extraction) [mrook] - </notes> - </release> - <release> - <version> - <release>1.4.12</release> - <api>1.4.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2021-01-18</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> -* Fix Bug #27008: Symlink out-of-path write vulnerability (CVE-2020-36193) [mrook] - </notes> - </release> - <release> - <version> - <release>1.4.11</release> - <api>1.4.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2020-11-19</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> -* Fix Bug #27002: Filename manipulation vulnerabilities (CVE-2020-28948 / CVE-2020-28949) [mrook] - </notes> - </release> - <release> - <version> - <release>1.4.10</release> - <api>1.4.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2020-09-15</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> - * Fix block padding when the file buffer length is a multiple of 512 and smaller than Archive_Tar buffer length - * Don&apos;t try to copy username/groupname in chroot jail - </notes> - </release> - <release> - <version> - <release>1.4.9</release> - <api>1.4.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2019-12-04</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> -* Implement Feature #23861: Add option to disallow symlinks [mrook] - </notes> - </release> - <release> - <version> - <release>1.4.8</release> - <api>1.4.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2019-10-21</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> -* Fix Bug #23852: PHP 7.4 - Archive_Tar-&gt;_readHeader throws deprecation [mrook] - </notes> - </release> - <release> - <version> - <release>1.4.7</release> - <api>1.4.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2019-04-08</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> -* Improved performance by increasing read buffer size - </notes> - </release> - <release> - <version> - <release>1.4.6</release> - <api>1.4.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2019-02-01</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> -* Improve path traversal detection for forward and backward slashes - </notes> - </release> - <release> - <version> - <release>1.4.5</release> - <api>1.4.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2019-01-02</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> -* Fix Bug #23788: Relative symlinks are broken [mrook] - </notes> - </release> - <release> - <version> - <release>1.4.4</release> - <api>1.4.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2018-12-20</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> -* Fix Bug #21058: Long symlinks are not supported [mrook] - * Fix Bug #23782: Prevent phar:// files from being extracted [mrook] - </notes> - </release> - <release> - <version> - <release>1.4.3</release> - <api>1.4.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2017-06-11</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> -* Fix Bug #21218: Cannot use result of built-in function in write context in PHP - 7.2.0alpha1 [mrook] - </notes> - </release> - <release> - <version> - <release>1.4.2</release> - <api>1.4.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2016-02-25</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> -* Fix reading of archives with files &gt; 8GB -* Performance optimizations -* Do not try to call require_once on PEAR.php if it has already been loaded by the autoloader - </notes> - </release> - <release> - <version> - <release>1.4.1</release> - <api>1.4.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2015-08-05</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> -* Update composer.json to use pear-core-minimal 1.10.0alpha2 - </notes> - </release> - <release> - <version> - <release>1.4.0</release> - <api>1.4.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2015-07-20</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> -* Add support for PHP 7 -* Drop support for PHP 4 -* Add visibility declarations to methods and properties - </notes> - </release> - <release> - <version> - <release>1.3.16</release> - <api>1.3.1</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2015-04-14</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> -* Fix Bug #20514: invalid package.xml; not installable with pyrus [mrook] - </notes> - </release> - <release> - <version> - <release>1.3.15</release> - <api>1.3.1</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2015-03-05</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> -* Fixes composer.json parse error - </notes> - </release> - <release> - <version> - <release>1.3.14</release> - <api>1.3.1</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2015-02-26</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> -* Fix Bug #18505: Possible incorrect handling of file names in TAR [mrook] - </notes> - </release> - <release> - <version> - <release>1.3.13</release> - <api>1.3.1</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2014-09-02</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD - License</license> - <notes> -* Fix Bug #20382: gzopen fix [mrook] - </notes> - </release> - <release> - <version> - <release>1.3.12</release> - <api>1.3.1</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2014-08-04</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD - License</license> - <notes> -* Fix Bug #19964: Memory leaking in Archive_Tar [mrook] - * Fix Bug #20246: Broken with php 5.5.9 [mrook] - * Fix Bug #20275: &quot;pax_global_header&quot; looks like a regular file - * [mrook] - * Implement Feature #19827: pass filename to _addFile function - downstream - * patch [mrook] - * Implement Feature #20132: Add custom mode/uid/gid to addString() [mrook] - </notes> - </release> - <release> - <version> - <release>1.3.11</release> - <api>1.3.1</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2013-02-09</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD - License</license> - <notes> -* Fix Bug #19746: Broken with PHP 5.5 [mrook] - * Implement Feature #11258: Custom date/time in files added on-the-fly - * [mrook] - </notes> - </release> - <release> - <version> - <release>1.3.10</release> - <api>1.3.1</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2012-04-10</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD - License</license> - <notes> -* Fix Bug #13361: Unable to add() some files (ex. mp3) [mrook] - * Fix Bug #19330: Class creates incorrect (non-readable) tar.gz file - * [mrook] - </notes> - </release> - <release> - <version> - <release>1.3.9</release> - <api>1.3.1</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2012-02-27</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> -* Fix Bug #16759: No error thrown from missing PHP zlib functions [mrook] - * Fix Bug #18877: Incorrect handling of backslashes in filenames on Linux [mrook] - * Fix Bug #19085: Error while packaging [mrook] - * Fix Bug #19289: Invalid tar file generated [mrook] - </notes> - </release> - <release> - <version> - <release>1.3.8</release> - <api>1.3.1</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2011-10-14</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> -* Fix Bug #17853: Test failure: dirtraversal.phpt [mrook] - * Fix Bug #18512: dead links are not saved in tar file [mrook] - * Fix Bug #18702: Unpacks incorrectly on long file names using header prefix [mrook] - * Implement Feature #10145: Patch to return a Pear Error Object on failure [mrook] - * Implement Feature #17491: Option to preserve permissions [mrook] - * Implement Feature #17813: Prevent PHP notice when extracting corrupted archive [mrook] - </notes> - </release> - <release> - <version> - <release>1.3.7</release> - <api>1.3.1</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2010-04-26</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> -PEAR compatibility update - </notes> - </release> - <release> - <version> - <release>1.3.6</release> - <api>1.3.1</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2010-03-09</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> -* Fix Bug #16963: extractList can&apos;t extract zipped files from big tar [mrook] - * Implement Feature #4013: Ignoring files and directories on creating an archive. [mrook] - </notes> - </release> - <release> - <version> - <release>1.3.5</release> - <api>1.3.1</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2009-12-31</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> -* Fix Bug #16958: Update &apos;compatible&apos; tag in package.xml [mrook] - </notes> - </release> - <release> - <version> - <release>1.3.4</release> - <api>1.3.1</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2009-12-30</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> -* Fix Bug #11871: wrong result of ::listContent() if filename begins or ends with space [mrook] - * Fix Bug #12462: invalid tar magic [mrook] - * Fix Bug #13918: Long filenames may get up to 511 0x00 bytes appended on read [mrook] - * Fix Bug #16202: Bogus modification times [mrook] - * Implement Feature #16212: Die is not exception [mrook] - </notes> - </release> - <release> - <version> - <release>1.3.3</release> - <api>1.3.1</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2009-03-27</date> - <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> - <notes> -Change the license to New BSD license - - minor bugfix release - * fix Bug #9921 compression with bzip2 fails [cellog] - * fix Bug #11594 _readLongHeader leaves 0 bytes in filename [jamessas] - * fix Bug #11769 Incorrect symlink handing [fajar99] - </notes> - </release> - <release> - <version> - <release>1.3.2</release> - <api>1.3.1</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2007-01-03</date> - <license uri="http://www.php.net/license">PHP License</license> - <notes> -Correct Bug #4016 -Remove duplicate remove error display with &apos;@&apos; -Correct Bug #3909 : Check existence of OS_WINDOWS constant -Correct Bug #5452 fix for &quot;lone zero block&quot; when untarring packages -Change filemode (from pear-core/Archive/Tar.php v.1.21) -Correct Bug #6486 Can not extract symlinks -Correct Bug #6933 Archive_Tar (Tar file management class) Directory traversal -Correct Bug #8114 Files added on-the-fly not storing date -Correct Bug #9352 Bug on _dirCheck function over nfs path - </notes> - </release> - <release> - <version> - <release>1.3.1</release> - <api>1.3.1</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2005-03-17</date> - <license uri="http://www.php.net/license">PHP License</license> - <notes> -Correct Bug #3855 - </notes> - </release> - <release> - <version> - <release>1.3.0</release> - <api>1.3.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2005-03-06</date> - <license uri="http://www.php.net/license">PHP License</license> - <notes> -Bugs correction (2475, 2488, 2135, 2176) - </notes> - </release> - <release> - <version> - <release>1.2</release> - <api>1.2</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2004-05-08</date> - <license uri="http://www.php.net/license">PHP License</license> - <notes> -Add support for other separator than the space char and bug - correction - </notes> - </release> - <release> - <version> - <release>1.1</release> - <api>1.1</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2003-05-28</date> - <license uri="http://www.php.net/license">PHP License</license> - <notes> -* Add support for BZ2 compression -* Add support for add and extract without using temporary files : methods addString() and extractInString() - </notes> - </release> - <release> - <version> - <release>1.0</release> - <api>1.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2003-01-24</date> - <license uri="http://www.php.net/license">PHP License</license> - <notes> -Change status to stable - </notes> - </release> - <release> - <version> - <release>0.10-b1</release> - <api>0.10-b1</api> - </version> - <stability> - <release>beta</release> - <api>beta</api> - </stability> - <date>2003-01-08</date> - <license uri="http://www.php.net/license">PHP License</license> - <notes> -Add support for long filenames (greater than 99 characters) - </notes> - </release> - <release> - <version> - <release>0.9</release> - <api>0.9</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2002-05-27</date> - <license uri="http://www.php.net/license">PHP License</license> - <notes> -Auto-detect gzip&apos;ed files - </notes> - </release> - <release> - <version> - <release>0.4</release> - <api>0.4</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2002-05-20</date> - <license uri="http://www.php.net/license">PHP License</license> - <notes> -Windows bugfix: use forward slashes inside archives - </notes> - </release> - <release> - <version> - <release>0.2</release> - <api>0.2</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2002-02-18</date> - <license uri="http://www.php.net/license">PHP License</license> - <notes> -From initial commit to stable - </notes> - </release> - <release> - <version> - <release>0.3</release> - <api>0.3</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2002-04-13</date> - <license uri="http://www.php.net/license">PHP License</license> - <notes> -Windows bugfix: used wrong directory separators - </notes> - </release> - </changelog> -</package> diff --git a/lib/pear/console_getopt/.gitignore b/lib/pear/console_getopt/.gitignore deleted file mode 100644 index 783582816..000000000 --- a/lib/pear/console_getopt/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -# composer related -composer.lock -composer.phar -vendor -README.html -dist/ diff --git a/lib/pear/console_getopt/.travis.yml b/lib/pear/console_getopt/.travis.yml deleted file mode 100644 index 2711415f5..000000000 --- a/lib/pear/console_getopt/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -language: php -php: - - 7 - - 5.6 - - 5.5 - - 5.4 -sudo: false -script: - - pear run-tests -r tests/ diff --git a/lib/pear/console_getopt/Console/Getopt.php b/lib/pear/console_getopt/Console/Getopt.php deleted file mode 100644 index e5793bbb1..000000000 --- a/lib/pear/console_getopt/Console/Getopt.php +++ /dev/null @@ -1,365 +0,0 @@ -<?php -/* vim: set expandtab tabstop=4 shiftwidth=4: */ -/** - * PHP Version 5 - * - * Copyright (c) 2001-2015, The PEAR developers - * - * This source file is subject to the BSD-2-Clause license, - * that is bundled with this package in the file LICENSE, and is - * available through the world-wide-web at the following url: - * http://opensource.org/licenses/bsd-license.php. - * - * @category Console - * @package Console_Getopt - * @author Andrei Zmievski <andrei@php.net> - * @license http://opensource.org/licenses/bsd-license.php BSD-2-Clause - * @version CVS: $Id$ - * @link http://pear.php.net/package/Console_Getopt - */ - -require_once 'PEAR.php'; - -/** - * Command-line options parsing class. - * - * @category Console - * @package Console_Getopt - * @author Andrei Zmievski <andrei@php.net> - * @license http://opensource.org/licenses/bsd-license.php BSD-2-Clause - * @link http://pear.php.net/package/Console_Getopt - */ -class Console_Getopt -{ - - /** - * Parses the command-line options. - * - * The first parameter to this function should be the list of command-line - * arguments without the leading reference to the running program. - * - * The second parameter is a string of allowed short options. Each of the - * option letters can be followed by a colon ':' to specify that the option - * requires an argument, or a double colon '::' to specify that the option - * takes an optional argument. - * - * The third argument is an optional array of allowed long options. The - * leading '--' should not be included in the option name. Options that - * require an argument should be followed by '=', and options that take an - * option argument should be followed by '=='. - * - * The return value is an array of two elements: the list of parsed - * options and the list of non-option command-line arguments. Each entry in - * the list of parsed options is a pair of elements - the first one - * specifies the option, and the second one specifies the option argument, - * if there was one. - * - * Long and short options can be mixed. - * - * Most of the semantics of this function are based on GNU getopt_long(). - * - * @param array $args an array of command-line arguments - * @param string $short_options specifies the list of allowed short options - * @param array $long_options specifies the list of allowed long options - * @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option - * - * @return array two-element array containing the list of parsed options and - * the non-option arguments - */ - public static function getopt2($args, $short_options, $long_options = null, $skip_unknown = false) - { - return Console_Getopt::doGetopt(2, $args, $short_options, $long_options, $skip_unknown); - } - - /** - * This function expects $args to start with the script name (POSIX-style). - * Preserved for backwards compatibility. - * - * @param array $args an array of command-line arguments - * @param string $short_options specifies the list of allowed short options - * @param array $long_options specifies the list of allowed long options - * - * @see getopt2() - * @return array two-element array containing the list of parsed options and - * the non-option arguments - */ - public static function getopt($args, $short_options, $long_options = null, $skip_unknown = false) - { - return Console_Getopt::doGetopt(1, $args, $short_options, $long_options, $skip_unknown); - } - - /** - * The actual implementation of the argument parsing code. - * - * @param int $version Version to use - * @param array $args an array of command-line arguments - * @param string $short_options specifies the list of allowed short options - * @param array $long_options specifies the list of allowed long options - * @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option - * - * @return array - */ - public static function doGetopt($version, $args, $short_options, $long_options = null, $skip_unknown = false) - { - // in case you pass directly readPHPArgv() as the first arg - if (PEAR::isError($args)) { - return $args; - } - - if (empty($args)) { - return array(array(), array()); - } - - $non_opts = $opts = array(); - - settype($args, 'array'); - - if ($long_options) { - sort($long_options); - } - - /* - * Preserve backwards compatibility with callers that relied on - * erroneous POSIX fix. - */ - if ($version < 2) { - if (isset($args[0][0]) && $args[0][0] != '-') { - array_shift($args); - } - } - - for ($i = 0; $i < count($args); $i++) { - $arg = $args[$i]; - /* The special element '--' means explicit end of - options. Treat the rest of the arguments as non-options - and end the loop. */ - if ($arg == '--') { - $non_opts = array_merge($non_opts, array_slice($args, $i + 1)); - break; - } - - if ($arg[0] != '-' || (strlen($arg) > 1 && $arg[1] == '-' && !$long_options)) { - $non_opts = array_merge($non_opts, array_slice($args, $i)); - break; - } elseif (strlen($arg) > 1 && $arg[1] == '-') { - $error = Console_Getopt::_parseLongOption(substr($arg, 2), - $long_options, - $opts, - $i, - $args, - $skip_unknown); - if (PEAR::isError($error)) { - return $error; - } - } elseif ($arg == '-') { - // - is stdin - $non_opts = array_merge($non_opts, array_slice($args, $i)); - break; - } else { - $error = Console_Getopt::_parseShortOption(substr($arg, 1), - $short_options, - $opts, - $i, - $args, - $skip_unknown); - if (PEAR::isError($error)) { - return $error; - } - } - } - - return array($opts, $non_opts); - } - - /** - * Parse short option - * - * @param string $arg Argument - * @param string[] $short_options Available short options - * @param string[][] &$opts - * @param int &$argIdx - * @param string[] $args - * @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option - * - * @return void - */ - protected static function _parseShortOption($arg, $short_options, &$opts, &$argIdx, $args, $skip_unknown) - { - for ($i = 0; $i < strlen($arg); $i++) { - $opt = $arg[$i]; - $opt_arg = null; - - /* Try to find the short option in the specifier string. */ - if (($spec = strstr($short_options, $opt)) === false || $arg[$i] == ':') { - if ($skip_unknown === true) { - break; - } - - $msg = "Console_Getopt: unrecognized option -- $opt"; - return PEAR::raiseError($msg); - } - - if (strlen($spec) > 1 && $spec[1] == ':') { - if (strlen($spec) > 2 && $spec[2] == ':') { - if ($i + 1 < strlen($arg)) { - /* Option takes an optional argument. Use the remainder of - the arg string if there is anything left. */ - $opts[] = array($opt, substr($arg, $i + 1)); - break; - } - } else { - /* Option requires an argument. Use the remainder of the arg - string if there is anything left. */ - if ($i + 1 < strlen($arg)) { - $opts[] = array($opt, substr($arg, $i + 1)); - break; - } else if (isset($args[++$argIdx])) { - $opt_arg = $args[$argIdx]; - /* Else use the next argument. */; - if (Console_Getopt::_isShortOpt($opt_arg) - || Console_Getopt::_isLongOpt($opt_arg)) { - $msg = "option requires an argument --$opt"; - return PEAR::raiseError("Console_Getopt: " . $msg); - } - } else { - $msg = "option requires an argument --$opt"; - return PEAR::raiseError("Console_Getopt: " . $msg); - } - } - } - - $opts[] = array($opt, $opt_arg); - } - } - - /** - * Checks if an argument is a short option - * - * @param string $arg Argument to check - * - * @return bool - */ - protected static function _isShortOpt($arg) - { - return strlen($arg) == 2 && $arg[0] == '-' - && preg_match('/[a-zA-Z]/', $arg[1]); - } - - /** - * Checks if an argument is a long option - * - * @param string $arg Argument to check - * - * @return bool - */ - protected static function _isLongOpt($arg) - { - return strlen($arg) > 2 && $arg[0] == '-' && $arg[1] == '-' && - preg_match('/[a-zA-Z]+$/', substr($arg, 2)); - } - - /** - * Parse long option - * - * @param string $arg Argument - * @param string[] $long_options Available long options - * @param string[][] &$opts - * @param int &$argIdx - * @param string[] $args - * - * @return void|PEAR_Error - */ - protected static function _parseLongOption($arg, $long_options, &$opts, &$argIdx, $args, $skip_unknown) - { - @list($opt, $opt_arg) = explode('=', $arg, 2); - - $opt_len = strlen($opt); - - for ($i = 0; $i < count($long_options); $i++) { - $long_opt = $long_options[$i]; - $opt_start = substr($long_opt, 0, $opt_len); - - $long_opt_name = str_replace('=', '', $long_opt); - - /* Option doesn't match. Go on to the next one. */ - if ($long_opt_name != $opt) { - continue; - } - - $opt_rest = substr($long_opt, $opt_len); - - /* Check that the options uniquely matches one of the allowed - options. */ - if ($i + 1 < count($long_options)) { - $next_option_rest = substr($long_options[$i + 1], $opt_len); - } else { - $next_option_rest = ''; - } - - if ($opt_rest != '' && $opt[0] != '=' && - $i + 1 < count($long_options) && - $opt == substr($long_options[$i+1], 0, $opt_len) && - $next_option_rest != '' && - $next_option_rest[0] != '=') { - - $msg = "Console_Getopt: option --$opt is ambiguous"; - return PEAR::raiseError($msg); - } - - if (substr($long_opt, -1) == '=') { - if (substr($long_opt, -2) != '==') { - /* Long option requires an argument. - Take the next argument if one wasn't specified. */; - if (!strlen($opt_arg)) { - if (!isset($args[++$argIdx])) { - $msg = "Console_Getopt: option requires an argument --$opt"; - return PEAR::raiseError($msg); - } - $opt_arg = $args[$argIdx]; - } - - if (Console_Getopt::_isShortOpt($opt_arg) - || Console_Getopt::_isLongOpt($opt_arg)) { - $msg = "Console_Getopt: option requires an argument --$opt"; - return PEAR::raiseError($msg); - } - } - } else if ($opt_arg) { - $msg = "Console_Getopt: option --$opt doesn't allow an argument"; - return PEAR::raiseError($msg); - } - - $opts[] = array('--' . $opt, $opt_arg); - return; - } - - if ($skip_unknown === true) { - return; - } - - return PEAR::raiseError("Console_Getopt: unrecognized option --$opt"); - } - - /** - * Safely read the $argv PHP array across different PHP configurations. - * Will take care on register_globals and register_argc_argv ini directives - * - * @return mixed the $argv PHP array or PEAR error if not registered - */ - public static function readPHPArgv() - { - global $argv; - if (!is_array($argv)) { - if (!@is_array($_SERVER['argv'])) { - if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) { - $msg = "Could not read cmd args (register_argc_argv=Off?)"; - return PEAR::raiseError("Console_Getopt: " . $msg); - } - return $GLOBALS['HTTP_SERVER_VARS']['argv']; - } - return $_SERVER['argv']; - } - return $argv; - } - -} diff --git a/lib/pear/console_getopt/LICENSE b/lib/pear/console_getopt/LICENSE deleted file mode 100644 index 452b08839..000000000 --- a/lib/pear/console_getopt/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2001-2015, The PEAR developers -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -1. Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/lib/pear/console_getopt/README.rst b/lib/pear/console_getopt/README.rst deleted file mode 100644 index 64e5b41be..000000000 --- a/lib/pear/console_getopt/README.rst +++ /dev/null @@ -1,26 +0,0 @@ -******************************************* -Console_Getopt - Command-line option parser -******************************************* - -This is a PHP implementation of "getopt" supporting both short and long options. -It helps parsing command line options in your PHP script. - -Homepage: http://pear.php.net/package/Console_Getopt - -.. image:: https://travis-ci.org/pear/Console_Getopt.svg?branch=master - :target: https://travis-ci.org/pear/Console_Getopt - - -Alternatives -============ - -* Console_CommandLine__ (recommended) -* Console_GetoptPlus__ - -__ http://pear.php.net/package/Console_CommandLine -__ http://pear.php.net/package/Console_GetoptPlus - - -License -======= -BSD-2-Clause diff --git a/lib/pear/console_getopt/composer.json b/lib/pear/console_getopt/composer.json deleted file mode 100644 index 4dc7e7cca..000000000 --- a/lib/pear/console_getopt/composer.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "authors": [ - { - "email": "andrei@php.net", - "name": "Andrei Zmievski", - "role": "Lead" - }, - { - "email": "stig@php.net", - "name": "Stig Bakken", - "role": "Developer" - }, - { - "email": "cellog@php.net", - "name": "Greg Beaver", - "role": "Helper" - } - ], - "autoload": { - "psr-0": { - "Console": "./" - } - }, - "description": "More info available on: http://pear.php.net/package/Console_Getopt", - "include-path": [ - "./" - ], - "license": "BSD-2-Clause", - "name": "pear/console_getopt", - "support": { - "issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=Console_Getopt", - "source": "https://github.com/pear/Console_Getopt" - }, - "type": "library" -} diff --git a/lib/pear/console_getopt/package.xml b/lib/pear/console_getopt/package.xml deleted file mode 100644 index d3fd78402..000000000 --- a/lib/pear/console_getopt/package.xml +++ /dev/null @@ -1,302 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<package packagerversion="1.9.2" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd"> - <name>Console_Getopt</name> - <channel>pear.php.net</channel> - <summary>Command-line option parser</summary> - <description>This is a PHP implementation of &quot;getopt&quot; supporting both -short and long options.</description> - <lead> - <name>Andrei Zmievski</name> - <user>andrei</user> - <email>andrei@php.net</email> - <active>no</active> - </lead> - <developer> - <name>Stig Bakken</name> - <user>ssb</user> - <email>stig@php.net</email> - <active>no</active> - </developer> - <helper> - <name>Greg Beaver</name> - <user>cellog</user> - <email>cellog@php.net</email> - <active>no</active> - </helper> - - <date>2019-11-20</date> - <version> - <release>1.4.3</release> - <api>1.4.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <license uri="http://opensource.org/licenses/bsd-license.php">BSD-2-Clause</license> - - <notes> -* PR #4: Fix PHP 7.4 deprecation: array/string curly braces access -* PR #5: fix phplint warnings - </notes> - - <contents> - <dir name="/"> - <dir name="Console"> - <file name="Getopt.php" role="php" /> - </dir> - <dir name="tests"> - <file role="test" name="001-getopt.phpt" /> - <file role="test" name="bug10557.phpt" /> - <file role="test" name="bug11068.phpt" /> - <file role="test" name="bug13140.phpt" /> - </dir> - </dir> - </contents> - - <compatible> - <name>PEAR</name> - <channel>pear.php.net</channel> - <min>1.4.0</min> - <max>1.999.999</max> - </compatible> - - <dependencies> - <required> - <php> - <min>5.4.0</min> - </php> - <pearinstaller> - <min>1.8.0</min> - </pearinstaller> - </required> - </dependencies> - - <phprelease /> - - <changelog> - - <release> - <date>2019-11-20</date> - <version> - <release>1.4.3</release> - <api>1.4.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <license uri="http://opensource.org/licenses/bsd-license.php">BSD-2-Clause</license> - <notes> - * PR #4: Fix PHP 7.4 deprecation: array/string curly braces access - * PR #5: fix phplint warnings - </notes> - </release> - - <release> - <date>2019-02-06</date> - <version> - <release>1.4.2</release> - <api>1.4.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <license uri="http://opensource.org/licenses/bsd-license.php">BSD-2-Clause</license> - <notes> - * Remove use of each(), which is removed in PHP 8 - </notes> - </release> - - <release> - <date>2015-07-20</date> - <version> - <release>1.4.1</release> - <api>1.4.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <license uri="http://opensource.org/licenses/bsd-license.php">BSD-2-Clause</license> - <notes> - * Fix unit test on PHP 7 [cweiske] - </notes> - </release> - - <release> - <date>2015-02-22</date> - <version> - <release>1.4.0</release> - <api>1.4.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <license uri="http://opensource.org/licenses/bsd-license.php">BSD-2-Clause</license> - <notes> - * Change license to BSD-2-Clause - * Set minimum PHP version to 5.4.0 - * Mark static methods with "static" keyword - </notes> - </release> - - <release> - <date>2011-03-07</date> - <version> - <release>1.3.1</release> - <api>1.3.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <license uri="http://www.php.net/license">PHP License</license> - <notes> - * Change the minimum PEAR installer dep to be lower - </notes> - </release> - - <release> - <date>2010-12-11</date> - <time>20:20:13</time> - <version> - <release>1.3.0</release> - <api>1.3.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <license uri="http://www.php.net/license">PHP License</license> - <notes> - * Implement Request #13140: [PATCH] to skip unknown parameters. [patch by rquadling, improved on by dufuz] - </notes> - </release> - - <release> - <date>2007-06-12</date> - <version> - <release>1.2.3</release> - <api>1.2.1</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <license uri="http://www.php.net/license">PHP License</license> - <notes> -* fix Bug #11068: No way to read plain &quot;-&quot; option [cardoe] - </notes> - </release> - <release> - <version> - <release>1.2.2</release> - <api>1.2.1</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2007-02-17</date> - <license uri="http://www.php.net/license">PHP License</license> - <notes> -* fix Bug #4475: An ambiguous error occurred when specifying similar longoption name. -* fix Bug #10055: Not failing properly on short options missing required values - </notes> - </release> - <release> - <version> - <release>1.2.1</release> - <api>1.2.1</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2006-12-08</date> - <license uri="http://www.php.net/license">PHP License</license> - <notes> -Fixed bugs #4448 (Long parameter values truncated with longoption parameter) and #7444 (Trailing spaces after php closing tag) - </notes> - </release> - <release> - <version> - <release>1.2</release> - <api>1.2</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2003-12-11</date> - <license uri="http://www.php.net/license">PHP License</license> - <notes> -Fix to preserve BC with 1.0 and allow correct behaviour for new users - </notes> - </release> - <release> - <version> - <release>1.0</release> - <api>1.0</api> - </version> - <stability> - <release>stable</release> - <api>stable</api> - </stability> - <date>2002-09-13</date> - <license uri="http://www.php.net/license">PHP License</license> - <notes> -Stable release - </notes> - </release> - <release> - <version> - <release>0.11</release> - <api>0.11</api> - </version> - <stability> - <release>beta</release> - <api>beta</api> - </stability> - <date>2002-05-26</date> - <license uri="http://www.php.net/license">PHP License</license> - <notes> -POSIX getopt compatibility fix: treat first element of args - array as command name - </notes> - </release> - <release> - <version> - <release>0.10</release> - <api>0.10</api> - </version> - <stability> - <release>beta</release> - <api>beta</api> - </stability> - <date>2002-05-12</date> - <license uri="http://www.php.net/license">PHP License</license> - <notes> -Packaging fix - </notes> - </release> - <release> - <version> - <release>0.9</release> - <api>0.9</api> - </version> - <stability> - <release>beta</release> - <api>beta</api> - </stability> - <date>2002-05-12</date> - <license uri="http://www.php.net/license">PHP License</license> - <notes> -Initial release - </notes> - </release> - </changelog> -</package> diff --git a/lib/pear/pear-core-minimal/README.rst b/lib/pear/pear-core-minimal/README.rst deleted file mode 100644 index 9e412fbd1..000000000 --- a/lib/pear/pear-core-minimal/README.rst +++ /dev/null @@ -1,26 +0,0 @@ -****************************** -Minimal set of PEAR core files -****************************** - -This repository provides a set of files from ``pear-core`` -that are often used in PEAR packages. - -It follows the `pear-core`__ repository and gets updated whenever a new -PEAR version is released. - -It's meant to be used as dependency for composer packages. - -__ https://github.com/pear/pear-core - -============== -Included files -============== -- ``OS/Guess.php`` -- ``PEAR.php`` -- ``PEAR/Error.php`` -- ``PEAR/ErrorStack.php`` -- ``System.php`` - - -``PEAR/Error.php`` is a dummy file that only includes ``PEAR.php``, -to make autoloaders work without problems. diff --git a/lib/pear/pear-core-minimal/composer.json b/lib/pear/pear-core-minimal/composer.json deleted file mode 100644 index d805f56ae..000000000 --- a/lib/pear/pear-core-minimal/composer.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "pear/pear-core-minimal", - "description": "Minimal set of PEAR core files to be used as composer dependency", - "license": "BSD-3-Clause", - "authors": [ - { - "email": "cweiske@php.net", - "name": "Christian Weiske", - "role": "Lead" - } - ], - "autoload": { - "psr-0": { - "": "src/" - } - }, - "include-path": [ - "src/" - ], - "support": { - "issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=PEAR", - "source": "https://github.com/pear/pear-core-minimal" - }, - "type": "library", - "require": { - "pear/console_getopt": "~1.4", - "pear/pear_exception": "~1.0" - }, - "replace": { - "rsky/pear-core-min": "self.version" - } -} diff --git a/lib/pear/pear-core-minimal/src/OS/Guess.php b/lib/pear/pear-core-minimal/src/OS/Guess.php deleted file mode 100644 index 88cd65910..000000000 --- a/lib/pear/pear-core-minimal/src/OS/Guess.php +++ /dev/null @@ -1,395 +0,0 @@ -<?php -/** - * The OS_Guess class - * - * PHP versions 4 and 5 - * - * @category pear - * @package PEAR - * @author Stig Bakken <ssb@php.net> - * @author Gregory Beaver <cellog@php.net> - * @copyright 1997-2009 The Authors - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @link http://pear.php.net/package/PEAR - * @since File available since PEAR 0.1 - */ - -// {{{ uname examples - -// php_uname() without args returns the same as 'uname -a', or a PHP-custom -// string for Windows. -// PHP versions prior to 4.3 return the uname of the host where PHP was built, -// as of 4.3 it returns the uname of the host running the PHP code. -// -// PC RedHat Linux 7.1: -// Linux host.example.com 2.4.2-2 #1 Sun Apr 8 20:41:30 EDT 2001 i686 unknown -// -// PC Debian Potato: -// Linux host 2.4.17 #2 SMP Tue Feb 12 15:10:04 CET 2002 i686 unknown -// -// PC FreeBSD 3.3: -// FreeBSD host.example.com 3.3-STABLE FreeBSD 3.3-STABLE #0: Mon Feb 21 00:42:31 CET 2000 root@example.com:/usr/src/sys/compile/CONFIG i386 -// -// PC FreeBSD 4.3: -// FreeBSD host.example.com 4.3-RELEASE FreeBSD 4.3-RELEASE #1: Mon Jun 25 11:19:43 EDT 2001 root@example.com:/usr/src/sys/compile/CONFIG i386 -// -// PC FreeBSD 4.5: -// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb 6 23:59:23 CET 2002 root@example.com:/usr/src/sys/compile/CONFIG i386 -// -// PC FreeBSD 4.5 w/uname from GNU shellutils: -// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb i386 unknown -// -// HP 9000/712 HP-UX 10: -// HP-UX iq B.10.10 A 9000/712 2008429113 two-user license -// -// HP 9000/712 HP-UX 10 w/uname from GNU shellutils: -// HP-UX host B.10.10 A 9000/712 unknown -// -// IBM RS6000/550 AIX 4.3: -// AIX host 3 4 000003531C00 -// -// AIX 4.3 w/uname from GNU shellutils: -// AIX host 3 4 000003531C00 unknown -// -// SGI Onyx IRIX 6.5 w/uname from GNU shellutils: -// IRIX64 host 6.5 01091820 IP19 mips -// -// SGI Onyx IRIX 6.5: -// IRIX64 host 6.5 01091820 IP19 -// -// SparcStation 20 Solaris 8 w/uname from GNU shellutils: -// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc -// -// SparcStation 20 Solaris 8: -// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc SUNW,SPARCstation-20 -// -// Mac OS X (Darwin) -// Darwin home-eden.local 7.5.0 Darwin Kernel Version 7.5.0: Thu Aug 5 19:26:16 PDT 2004; root:xnu/xnu-517.7.21.obj~3/RELEASE_PPC Power Macintosh -// -// Mac OS X early versions -// - -// }}} - -/* TODO: - * - define endianness, to allow matchSignature("bigend") etc. - */ - -/** - * Retrieves information about the current operating system - * - * This class uses php_uname() to grok information about the current OS - * - * @category pear - * @package PEAR - * @author Stig Bakken <ssb@php.net> - * @author Gregory Beaver <cellog@php.net> - * @copyright 1997-2020 The Authors - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: @package_version@ - * @link http://pear.php.net/package/PEAR - * @since Class available since Release 0.1 - */ -class OS_Guess -{ - var $sysname; - var $nodename; - var $cpu; - var $release; - var $extra; - - function __construct($uname = null) - { - list($this->sysname, - $this->release, - $this->cpu, - $this->extra, - $this->nodename) = $this->parseSignature($uname); - } - - function parseSignature($uname = null) - { - static $sysmap = array( - 'HP-UX' => 'hpux', - 'IRIX64' => 'irix', - ); - static $cpumap = array( - 'i586' => 'i386', - 'i686' => 'i386', - 'ppc' => 'powerpc', - ); - if ($uname === null) { - $uname = php_uname(); - } - $parts = preg_split('/\s+/', trim($uname)); - $n = count($parts); - - $release = $machine = $cpu = ''; - $sysname = $parts[0]; - $nodename = $parts[1]; - $cpu = $parts[$n-1]; - $extra = ''; - if ($cpu == 'unknown') { - $cpu = $parts[$n - 2]; - } - - switch ($sysname) { - case 'AIX' : - $release = "$parts[3].$parts[2]"; - break; - case 'Windows' : - $release = $parts[1]; - if ($release == '95/98') { - $release = '9x'; - } - $cpu = 'i386'; - break; - case 'Linux' : - $extra = $this->_detectGlibcVersion(); - // use only the first two digits from the kernel version - $release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]); - break; - case 'Mac' : - $sysname = 'darwin'; - $nodename = $parts[2]; - $release = $parts[3]; - $cpu = $this->_determineIfPowerpc($cpu, $parts); - break; - case 'Darwin' : - $cpu = $this->_determineIfPowerpc($cpu, $parts); - $release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]); - break; - default: - $release = preg_replace('/-.*/', '', $parts[2]); - break; - } - - if (isset($sysmap[$sysname])) { - $sysname = $sysmap[$sysname]; - } else { - $sysname = strtolower($sysname); - } - if (isset($cpumap[$cpu])) { - $cpu = $cpumap[$cpu]; - } - return array($sysname, $release, $cpu, $extra, $nodename); - } - - function _determineIfPowerpc($cpu, $parts) - { - $n = count($parts); - if ($cpu == 'Macintosh' && $parts[$n - 2] == 'Power') { - $cpu = 'powerpc'; - } - return $cpu; - } - - function _detectGlibcVersion() - { - static $glibc = false; - if ($glibc !== false) { - return $glibc; // no need to run this multiple times - } - $major = $minor = 0; - include_once "System.php"; - - // Let's try reading possible libc.so.6 symlinks - $libcs = array( - '/lib64/libc.so.6', - '/lib/libc.so.6', - '/lib/i386-linux-gnu/libc.so.6' - ); - $versions = array(); - foreach ($libcs as $file) { - $versions = $this->_readGlibCVersionFromSymlink($file); - if ($versions != []) { - list($major, $minor) = $versions; - break; - } - } - - // Use glibc's <features.h> header file to - // get major and minor version number: - if (!($major && $minor)) { - $versions = $this->_readGlibCVersionFromFeaturesHeaderFile(); - } - if (is_array($versions) && $versions != []) { - list($major, $minor) = $versions; - } - - if (!($major && $minor)) { - return $glibc = ''; - } - - return $glibc = "glibc{$major}.{$minor}"; - } - - function _readGlibCVersionFromSymlink($file) - { - $versions = array(); - if (@is_link($file) - && (preg_match('/^libc-(.*)\.so$/', basename(readlink($file)), $matches)) - ) { - $versions = explode('.', $matches[1]); - } - return $versions; - } - - - function _readGlibCVersionFromFeaturesHeaderFile() - { - $features_header_file = '/usr/include/features.h'; - if (!(@file_exists($features_header_file) - && @is_readable($features_header_file)) - ) { - return array(); - } - if (!@file_exists('/usr/bin/cpp') || !@is_executable('/usr/bin/cpp')) { - return $this-_parseFeaturesHeaderFile($features_header_file); - } // no cpp - - return $this->_fromGlibCTest(); - } - - function _parseFeaturesHeaderFile($features_header_file) - { - $features_file = fopen($features_header_file, 'rb'); - while (!feof($features_file)) { - $line = fgets($features_file, 8192); - if (!$this->_IsADefinition($line)) { - continue; - } - if (strpos($line, '__GLIBC__')) { - // major version number #define __GLIBC__ version - $line = preg_split('/\s+/', $line); - $glibc_major = trim($line[2]); - if (isset($glibc_minor)) { - break; - } - continue; - } - - if (strpos($line, '__GLIBC_MINOR__')) { - // got the minor version number - // #define __GLIBC_MINOR__ version - $line = preg_split('/\s+/', $line); - $glibc_minor = trim($line[2]); - if (isset($glibc_major)) { - break; - } - } - } - fclose($features_file); - if (!isset($glibc_major) || !isset($glibc_minor)) { - return array(); - } - return array(trim($glibc_major), trim($glibc_minor)); - } - - function _IsADefinition($line) - { - if ($line === false) { - return false; - } - return strpos(trim($line), '#define') !== false; - } - - function _fromGlibCTest() - { - $major = null; - $minor = null; - - $tmpfile = System::mktemp("glibctest"); - $fp = fopen($tmpfile, "w"); - fwrite($fp, "#include <features.h>\n__GLIBC__ __GLIBC_MINOR__\n"); - fclose($fp); - $cpp = popen("/usr/bin/cpp $tmpfile", "r"); - while ($line = fgets($cpp, 1024)) { - if ($line[0] == '#' || trim($line) == '') { - continue; - } - - if (list($major, $minor) = explode(' ', trim($line))) { - break; - } - } - pclose($cpp); - unlink($tmpfile); - if ($major !== null && $minor !== null) { - return [$major, $minor]; - } - } - - function getSignature() - { - if (empty($this->extra)) { - return "{$this->sysname}-{$this->release}-{$this->cpu}"; - } - return "{$this->sysname}-{$this->release}-{$this->cpu}-{$this->extra}"; - } - - function getSysname() - { - return $this->sysname; - } - - function getNodename() - { - return $this->nodename; - } - - function getCpu() - { - return $this->cpu; - } - - function getRelease() - { - return $this->release; - } - - function getExtra() - { - return $this->extra; - } - - function matchSignature($match) - { - $fragments = is_array($match) ? $match : explode('-', $match); - $n = count($fragments); - $matches = 0; - if ($n > 0) { - $matches += $this->_matchFragment($fragments[0], $this->sysname); - } - if ($n > 1) { - $matches += $this->_matchFragment($fragments[1], $this->release); - } - if ($n > 2) { - $matches += $this->_matchFragment($fragments[2], $this->cpu); - } - if ($n > 3) { - $matches += $this->_matchFragment($fragments[3], $this->extra); - } - return ($matches == $n); - } - - function _matchFragment($fragment, $value) - { - if (strcspn($fragment, '*?') < strlen($fragment)) { - $expression = str_replace( - array('*', '?', '/'), - array('.*', '.', '\\/'), - $fragment - ); - $reg = '/^' . $expression . '\\z/'; - return preg_match($reg, $value); - } - return ($fragment == '*' || !strcasecmp($fragment, $value)); - } -} -/* - * Local Variables: - * indent-tabs-mode: nil - * c-basic-offset: 4 - * End: - */ diff --git a/lib/pear/pear-core-minimal/src/PEAR.php b/lib/pear/pear-core-minimal/src/PEAR.php deleted file mode 100644 index fee6638f4..000000000 --- a/lib/pear/pear-core-minimal/src/PEAR.php +++ /dev/null @@ -1,1135 +0,0 @@ -<?php -/** - * PEAR, the PHP Extension and Application Repository - * - * PEAR class and PEAR_Error class - * - * PHP versions 4 and 5 - * - * @category pear - * @package PEAR - * @author Sterling Hughes <sterling@php.net> - * @author Stig Bakken <ssb@php.net> - * @author Tomas V.V.Cox <cox@idecnet.com> - * @author Greg Beaver <cellog@php.net> - * @copyright 1997-2010 The Authors - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @link http://pear.php.net/package/PEAR - * @since File available since Release 0.1 - */ - -/**#@+ - * ERROR constants - */ -define('PEAR_ERROR_RETURN', 1); -define('PEAR_ERROR_PRINT', 2); -define('PEAR_ERROR_TRIGGER', 4); -define('PEAR_ERROR_DIE', 8); -define('PEAR_ERROR_CALLBACK', 16); -/** - * WARNING: obsolete - * @deprecated - */ -define('PEAR_ERROR_EXCEPTION', 32); -/**#@-*/ - -if (substr(PHP_OS, 0, 3) == 'WIN') { - define('OS_WINDOWS', true); - define('OS_UNIX', false); - define('PEAR_OS', 'Windows'); -} else { - define('OS_WINDOWS', false); - define('OS_UNIX', true); - define('PEAR_OS', 'Unix'); // blatant assumption -} - -$GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_RETURN; -$GLOBALS['_PEAR_default_error_options'] = E_USER_NOTICE; -$GLOBALS['_PEAR_destructor_object_list'] = array(); -$GLOBALS['_PEAR_shutdown_funcs'] = array(); -$GLOBALS['_PEAR_error_handler_stack'] = array(); - -@ini_set('track_errors', true); - -/** - * Base class for other PEAR classes. Provides rudimentary - * emulation of destructors. - * - * If you want a destructor in your class, inherit PEAR and make a - * destructor method called _yourclassname (same name as the - * constructor, but with a "_" prefix). Also, in your constructor you - * have to call the PEAR constructor: $this->PEAR();. - * The destructor method will be called without parameters. Note that - * at in some SAPI implementations (such as Apache), any output during - * the request shutdown (in which destructors are called) seems to be - * discarded. If you need to get any debug information from your - * destructor, use error_log(), syslog() or something similar. - * - * IMPORTANT! To use the emulated destructors you need to create the - * objects by reference: $obj =& new PEAR_child; - * - * @category pear - * @package PEAR - * @author Stig Bakken <ssb@php.net> - * @author Tomas V.V. Cox <cox@idecnet.com> - * @author Greg Beaver <cellog@php.net> - * @copyright 1997-2006 The PHP Group - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: @package_version@ - * @link http://pear.php.net/package/PEAR - * @see PEAR_Error - * @since Class available since PHP 4.0.2 - * @link http://pear.php.net/manual/en/core.pear.php#core.pear.pear - */ -class PEAR -{ - /** - * Whether to enable internal debug messages. - * - * @var bool - * @access private - */ - var $_debug = false; - - /** - * Default error mode for this object. - * - * @var int - * @access private - */ - var $_default_error_mode = null; - - /** - * Default error options used for this object when error mode - * is PEAR_ERROR_TRIGGER. - * - * @var int - * @access private - */ - var $_default_error_options = null; - - /** - * Default error handler (callback) for this object, if error mode is - * PEAR_ERROR_CALLBACK. - * - * @var string - * @access private - */ - var $_default_error_handler = ''; - - /** - * Which class to use for error objects. - * - * @var string - * @access private - */ - var $_error_class = 'PEAR_Error'; - - /** - * An array of expected errors. - * - * @var array - * @access private - */ - var $_expected_errors = array(); - - /** - * List of methods that can be called both statically and non-statically. - * @var array - */ - protected static $bivalentMethods = array( - 'setErrorHandling' => true, - 'raiseError' => true, - 'throwError' => true, - 'pushErrorHandling' => true, - 'popErrorHandling' => true, - ); - - /** - * Constructor. Registers this object in - * $_PEAR_destructor_object_list for destructor emulation if a - * destructor object exists. - * - * @param string $error_class (optional) which class to use for - * error objects, defaults to PEAR_Error. - * @access public - * @return void - */ - function __construct($error_class = null) - { - $classname = strtolower(get_class($this)); - if ($this->_debug) { - print "PEAR constructor called, class=$classname\n"; - } - - if ($error_class !== null) { - $this->_error_class = $error_class; - } - - while ($classname && strcasecmp($classname, "pear")) { - $destructor = "_$classname"; - if (method_exists($this, $destructor)) { - global $_PEAR_destructor_object_list; - $_PEAR_destructor_object_list[] = $this; - if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) { - register_shutdown_function("_PEAR_call_destructors"); - $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true; - } - break; - } else { - $classname = get_parent_class($classname); - } - } - } - - /** - * Only here for backwards compatibility. - * E.g. Archive_Tar calls $this->PEAR() in its constructor. - * - * @param string $error_class Which class to use for error objects, - * defaults to PEAR_Error. - */ - public function PEAR($error_class = null) - { - self::__construct($error_class); - } - - /** - * Destructor (the emulated type of...). Does nothing right now, - * but is included for forward compatibility, so subclass - * destructors should always call it. - * - * See the note in the class desciption about output from - * destructors. - * - * @access public - * @return void - */ - function _PEAR() { - if ($this->_debug) { - printf("PEAR destructor called, class=%s\n", strtolower(get_class($this))); - } - } - - public function __call($method, $arguments) - { - if (!isset(self::$bivalentMethods[$method])) { - trigger_error( - 'Call to undefined method PEAR::' . $method . '()', E_USER_ERROR - ); - } - return call_user_func_array( - array(get_class(), '_' . $method), - array_merge(array($this), $arguments) - ); - } - - public static function __callStatic($method, $arguments) - { - if (!isset(self::$bivalentMethods[$method])) { - trigger_error( - 'Call to undefined method PEAR::' . $method . '()', E_USER_ERROR - ); - } - return call_user_func_array( - array(get_class(), '_' . $method), - array_merge(array(null), $arguments) - ); - } - - /** - * If you have a class that's mostly/entirely static, and you need static - * properties, you can use this method to simulate them. Eg. in your method(s) - * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar'); - * You MUST use a reference, or they will not persist! - * - * @param string $class The calling classname, to prevent clashes - * @param string $var The variable to retrieve. - * @return mixed A reference to the variable. If not set it will be - * auto initialised to NULL. - */ - public static function &getStaticProperty($class, $var) - { - static $properties; - if (!isset($properties[$class])) { - $properties[$class] = array(); - } - - if (!array_key_exists($var, $properties[$class])) { - $properties[$class][$var] = null; - } - - return $properties[$class][$var]; - } - - /** - * Use this function to register a shutdown method for static - * classes. - * - * @param mixed $func The function name (or array of class/method) to call - * @param mixed $args The arguments to pass to the function - * - * @return void - */ - public static function registerShutdownFunc($func, $args = array()) - { - // if we are called statically, there is a potential - // that no shutdown func is registered. Bug #6445 - if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) { - register_shutdown_function("_PEAR_call_destructors"); - $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true; - } - $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args); - } - - /** - * Tell whether a value is a PEAR error. - * - * @param mixed $data the value to test - * @param int $code if $data is an error object, return true - * only if $code is a string and - * $obj->getMessage() == $code or - * $code is an integer and $obj->getCode() == $code - * - * @return bool true if parameter is an error - */ - public static function isError($data, $code = null) - { - if (!is_a($data, 'PEAR_Error')) { - return false; - } - - if (is_null($code)) { - return true; - } elseif (is_string($code)) { - return $data->getMessage() == $code; - } - - return $data->getCode() == $code; - } - - /** - * Sets how errors generated by this object should be handled. - * Can be invoked both in objects and statically. If called - * statically, setErrorHandling sets the default behaviour for all - * PEAR objects. If called in an object, setErrorHandling sets - * the default behaviour for that object. - * - * @param object $object - * Object the method was called on (non-static mode) - * - * @param int $mode - * One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT, - * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE, - * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION. - * - * @param mixed $options - * When $mode is PEAR_ERROR_TRIGGER, this is the error level (one - * of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR). - * - * When $mode is PEAR_ERROR_CALLBACK, this parameter is expected - * to be the callback function or method. A callback - * function is a string with the name of the function, a - * callback method is an array of two elements: the element - * at index 0 is the object, and the element at index 1 is - * the name of the method to call in the object. - * - * When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is - * a printf format string used when printing the error - * message. - * - * @access public - * @return void - * @see PEAR_ERROR_RETURN - * @see PEAR_ERROR_PRINT - * @see PEAR_ERROR_TRIGGER - * @see PEAR_ERROR_DIE - * @see PEAR_ERROR_CALLBACK - * @see PEAR_ERROR_EXCEPTION - * - * @since PHP 4.0.5 - */ - protected static function _setErrorHandling( - $object, $mode = null, $options = null - ) { - if ($object !== null) { - $setmode = &$object->_default_error_mode; - $setoptions = &$object->_default_error_options; - } else { - $setmode = &$GLOBALS['_PEAR_default_error_mode']; - $setoptions = &$GLOBALS['_PEAR_default_error_options']; - } - - switch ($mode) { - case PEAR_ERROR_EXCEPTION: - case PEAR_ERROR_RETURN: - case PEAR_ERROR_PRINT: - case PEAR_ERROR_TRIGGER: - case PEAR_ERROR_DIE: - case null: - $setmode = $mode; - $setoptions = $options; - break; - - case PEAR_ERROR_CALLBACK: - $setmode = $mode; - // class/object method callback - if (is_callable($options)) { - $setoptions = $options; - } else { - trigger_error("invalid error callback", E_USER_WARNING); - } - break; - - default: - trigger_error("invalid error mode", E_USER_WARNING); - break; - } - } - - /** - * This method is used to tell which errors you expect to get. - * Expected errors are always returned with error mode - * PEAR_ERROR_RETURN. Expected error codes are stored in a stack, - * and this method pushes a new element onto it. The list of - * expected errors are in effect until they are popped off the - * stack with the popExpect() method. - * - * Note that this method can not be called statically - * - * @param mixed $code a single error code or an array of error codes to expect - * - * @return int the new depth of the "expected errors" stack - * @access public - */ - function expectError($code = '*') - { - if (is_array($code)) { - array_push($this->_expected_errors, $code); - } else { - array_push($this->_expected_errors, array($code)); - } - return count($this->_expected_errors); - } - - /** - * This method pops one element off the expected error codes - * stack. - * - * @return array the list of error codes that were popped - */ - function popExpect() - { - return array_pop($this->_expected_errors); - } - - /** - * This method checks unsets an error code if available - * - * @param mixed error code - * @return bool true if the error code was unset, false otherwise - * @access private - * @since PHP 4.3.0 - */ - function _checkDelExpect($error_code) - { - $deleted = false; - foreach ($this->_expected_errors as $key => $error_array) { - if (in_array($error_code, $error_array)) { - unset($this->_expected_errors[$key][array_search($error_code, $error_array)]); - $deleted = true; - } - - // clean up empty arrays - if (0 == count($this->_expected_errors[$key])) { - unset($this->_expected_errors[$key]); - } - } - - return $deleted; - } - - /** - * This method deletes all occurrences of the specified element from - * the expected error codes stack. - * - * @param mixed $error_code error code that should be deleted - * @return mixed list of error codes that were deleted or error - * @access public - * @since PHP 4.3.0 - */ - function delExpect($error_code) - { - $deleted = false; - if ((is_array($error_code) && (0 != count($error_code)))) { - // $error_code is a non-empty array here; we walk through it trying - // to unset all values - foreach ($error_code as $key => $error) { - $deleted = $this->_checkDelExpect($error) ? true : false; - } - - return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME - } elseif (!empty($error_code)) { - // $error_code comes alone, trying to unset it - if ($this->_checkDelExpect($error_code)) { - return true; - } - - return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME - } - - // $error_code is empty - return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME - } - - /** - * This method is a wrapper that returns an instance of the - * configured error class with this object's default error - * handling applied. If the $mode and $options parameters are not - * specified, the object's defaults are used. - * - * @param mixed $message a text error message or a PEAR error object - * - * @param int $code a numeric error code (it is up to your class - * to define these if you want to use codes) - * - * @param int $mode One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT, - * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE, - * PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION. - * - * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter - * specifies the PHP-internal error level (one of - * E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR). - * If $mode is PEAR_ERROR_CALLBACK, this - * parameter specifies the callback function or - * method. In other error modes this parameter - * is ignored. - * - * @param string $userinfo If you need to pass along for example debug - * information, this parameter is meant for that. - * - * @param string $error_class The returned error object will be - * instantiated from this class, if specified. - * - * @param bool $skipmsg If true, raiseError will only pass error codes, - * the error message parameter will be dropped. - * - * @return object a PEAR error object - * @see PEAR::setErrorHandling - * @since PHP 4.0.5 - */ - protected static function _raiseError($object, - $message = null, - $code = null, - $mode = null, - $options = null, - $userinfo = null, - $error_class = null, - $skipmsg = false) - { - // The error is yet a PEAR error object - if (is_object($message)) { - $code = $message->getCode(); - $userinfo = $message->getUserInfo(); - $error_class = $message->getType(); - $message->error_message_prefix = ''; - $message = $message->getMessage(); - } - - if ( - $object !== null && - isset($object->_expected_errors) && - count($object->_expected_errors) > 0 && - count($exp = end($object->_expected_errors)) - ) { - if ($exp[0] === "*" || - (is_int(reset($exp)) && in_array($code, $exp)) || - (is_string(reset($exp)) && in_array($message, $exp)) - ) { - $mode = PEAR_ERROR_RETURN; - } - } - - // No mode given, try global ones - if ($mode === null) { - // Class error handler - if ($object !== null && isset($object->_default_error_mode)) { - $mode = $object->_default_error_mode; - $options = $object->_default_error_options; - // Global error handler - } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) { - $mode = $GLOBALS['_PEAR_default_error_mode']; - $options = $GLOBALS['_PEAR_default_error_options']; - } - } - - if ($error_class !== null) { - $ec = $error_class; - } elseif ($object !== null && isset($object->_error_class)) { - $ec = $object->_error_class; - } else { - $ec = 'PEAR_Error'; - } - - if ($skipmsg) { - $a = new $ec($code, $mode, $options, $userinfo); - } else { - $a = new $ec($message, $code, $mode, $options, $userinfo); - } - - return $a; - } - - /** - * Simpler form of raiseError with fewer options. In most cases - * message, code and userinfo are enough. - * - * @param mixed $message a text error message or a PEAR error object - * - * @param int $code a numeric error code (it is up to your class - * to define these if you want to use codes) - * - * @param string $userinfo If you need to pass along for example debug - * information, this parameter is meant for that. - * - * @return object a PEAR error object - * @see PEAR::raiseError - */ - protected static function _throwError($object, $message = null, $code = null, $userinfo = null) - { - if ($object !== null) { - $a = $object->raiseError($message, $code, null, null, $userinfo); - return $a; - } - - $a = PEAR::raiseError($message, $code, null, null, $userinfo); - return $a; - } - - public static function staticPushErrorHandling($mode, $options = null) - { - $stack = &$GLOBALS['_PEAR_error_handler_stack']; - $def_mode = &$GLOBALS['_PEAR_default_error_mode']; - $def_options = &$GLOBALS['_PEAR_default_error_options']; - $stack[] = array($def_mode, $def_options); - switch ($mode) { - case PEAR_ERROR_EXCEPTION: - case PEAR_ERROR_RETURN: - case PEAR_ERROR_PRINT: - case PEAR_ERROR_TRIGGER: - case PEAR_ERROR_DIE: - case null: - $def_mode = $mode; - $def_options = $options; - break; - - case PEAR_ERROR_CALLBACK: - $def_mode = $mode; - // class/object method callback - if (is_callable($options)) { - $def_options = $options; - } else { - trigger_error("invalid error callback", E_USER_WARNING); - } - break; - - default: - trigger_error("invalid error mode", E_USER_WARNING); - break; - } - $stack[] = array($mode, $options); - return true; - } - - public static function staticPopErrorHandling() - { - $stack = &$GLOBALS['_PEAR_error_handler_stack']; - $setmode = &$GLOBALS['_PEAR_default_error_mode']; - $setoptions = &$GLOBALS['_PEAR_default_error_options']; - array_pop($stack); - list($mode, $options) = $stack[sizeof($stack) - 1]; - array_pop($stack); - switch ($mode) { - case PEAR_ERROR_EXCEPTION: - case PEAR_ERROR_RETURN: - case PEAR_ERROR_PRINT: - case PEAR_ERROR_TRIGGER: - case PEAR_ERROR_DIE: - case null: - $setmode = $mode; - $setoptions = $options; - break; - - case PEAR_ERROR_CALLBACK: - $setmode = $mode; - // class/object method callback - if (is_callable($options)) { - $setoptions = $options; - } else { - trigger_error("invalid error callback", E_USER_WARNING); - } - break; - - default: - trigger_error("invalid error mode", E_USER_WARNING); - break; - } - return true; - } - - /** - * Push a new error handler on top of the error handler options stack. With this - * you can easily override the actual error handler for some code and restore - * it later with popErrorHandling. - * - * @param mixed $mode (same as setErrorHandling) - * @param mixed $options (same as setErrorHandling) - * - * @return bool Always true - * - * @see PEAR::setErrorHandling - */ - protected static function _pushErrorHandling($object, $mode, $options = null) - { - $stack = &$GLOBALS['_PEAR_error_handler_stack']; - if ($object !== null) { - $def_mode = &$object->_default_error_mode; - $def_options = &$object->_default_error_options; - } else { - $def_mode = &$GLOBALS['_PEAR_default_error_mode']; - $def_options = &$GLOBALS['_PEAR_default_error_options']; - } - $stack[] = array($def_mode, $def_options); - - if ($object !== null) { - $object->setErrorHandling($mode, $options); - } else { - PEAR::setErrorHandling($mode, $options); - } - $stack[] = array($mode, $options); - return true; - } - - /** - * Pop the last error handler used - * - * @return bool Always true - * - * @see PEAR::pushErrorHandling - */ - protected static function _popErrorHandling($object) - { - $stack = &$GLOBALS['_PEAR_error_handler_stack']; - array_pop($stack); - list($mode, $options) = $stack[sizeof($stack) - 1]; - array_pop($stack); - if ($object !== null) { - $object->setErrorHandling($mode, $options); - } else { - PEAR::setErrorHandling($mode, $options); - } - return true; - } - - /** - * OS independent PHP extension load. Remember to take care - * on the correct extension name for case sensitive OSes. - * - * @param string $ext The extension name - * @return bool Success or not on the dl() call - */ - public static function loadExtension($ext) - { - if (extension_loaded($ext)) { - return true; - } - - // if either returns true dl() will produce a FATAL error, stop that - if ( - function_exists('dl') === false || - ini_get('enable_dl') != 1 - ) { - return false; - } - - if (OS_WINDOWS) { - $suffix = '.dll'; - } elseif (PHP_OS == 'HP-UX') { - $suffix = '.sl'; - } elseif (PHP_OS == 'AIX') { - $suffix = '.a'; - } elseif (PHP_OS == 'OSX') { - $suffix = '.bundle'; - } else { - $suffix = '.so'; - } - - return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix); - } - - /** - * Get SOURCE_DATE_EPOCH environment variable - * See https://reproducible-builds.org/specs/source-date-epoch/ - * - * @return int - * @access public - */ - static function getSourceDateEpoch() - { - if ($source_date_epoch = getenv('SOURCE_DATE_EPOCH')) { - if (preg_match('/^\d+$/', $source_date_epoch)) { - return (int) $source_date_epoch; - } else { - // "If the value is malformed, the build process SHOULD exit with a non-zero error code." - self::raiseError("Invalid SOURCE_DATE_EPOCH: $source_date_epoch"); - exit(1); - } - } else { - return time(); - } - } -} - -function _PEAR_call_destructors() -{ - global $_PEAR_destructor_object_list; - if (is_array($_PEAR_destructor_object_list) && - sizeof($_PEAR_destructor_object_list)) - { - reset($_PEAR_destructor_object_list); - - $destructLifoExists = PEAR::getStaticProperty('PEAR', 'destructlifo'); - - if ($destructLifoExists) { - $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list); - } - - foreach ($_PEAR_destructor_object_list as $k => $objref) { - $classname = get_class($objref); - while ($classname) { - $destructor = "_$classname"; - if (method_exists($objref, $destructor)) { - $objref->$destructor(); - break; - } else { - $classname = get_parent_class($classname); - } - } - } - // Empty the object list to ensure that destructors are - // not called more than once. - $_PEAR_destructor_object_list = array(); - } - - // Now call the shutdown functions - if ( - isset($GLOBALS['_PEAR_shutdown_funcs']) && - is_array($GLOBALS['_PEAR_shutdown_funcs']) && - !empty($GLOBALS['_PEAR_shutdown_funcs']) - ) { - foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) { - call_user_func_array($value[0], $value[1]); - } - } -} - -/** - * Standard PEAR error class for PHP 4 - * - * This class is supserseded by {@link PEAR_Exception} in PHP 5 - * - * @category pear - * @package PEAR - * @author Stig Bakken <ssb@php.net> - * @author Tomas V.V. Cox <cox@idecnet.com> - * @author Gregory Beaver <cellog@php.net> - * @copyright 1997-2006 The PHP Group - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: @package_version@ - * @link http://pear.php.net/manual/en/core.pear.pear-error.php - * @see PEAR::raiseError(), PEAR::throwError() - * @since Class available since PHP 4.0.2 - */ -class PEAR_Error -{ - var $error_message_prefix = ''; - var $mode = PEAR_ERROR_RETURN; - var $level = E_USER_NOTICE; - var $code = -1; - var $message = ''; - var $userinfo = ''; - var $backtrace = null; - - /** - * PEAR_Error constructor - * - * @param string $message message - * - * @param int $code (optional) error code - * - * @param int $mode (optional) error mode, one of: PEAR_ERROR_RETURN, - * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER, - * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION - * - * @param mixed $options (optional) error level, _OR_ in the case of - * PEAR_ERROR_CALLBACK, the callback function or object/method - * tuple. - * - * @param string $userinfo (optional) additional user/debug info - * - * @access public - * - */ - function __construct($message = 'unknown error', $code = null, - $mode = null, $options = null, $userinfo = null) - { - if ($mode === null) { - $mode = PEAR_ERROR_RETURN; - } - $this->message = $message; - $this->code = $code; - $this->mode = $mode; - $this->userinfo = $userinfo; - - $skiptrace = PEAR::getStaticProperty('PEAR_Error', 'skiptrace'); - - if (!$skiptrace) { - $this->backtrace = debug_backtrace(); - if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) { - unset($this->backtrace[0]['object']); - } - } - - if ($mode & PEAR_ERROR_CALLBACK) { - $this->level = E_USER_NOTICE; - $this->callback = $options; - } else { - if ($options === null) { - $options = E_USER_NOTICE; - } - - $this->level = $options; - $this->callback = null; - } - - if ($this->mode & PEAR_ERROR_PRINT) { - if (is_null($options) || is_int($options)) { - $format = "%s"; - } else { - $format = $options; - } - - printf($format, $this->getMessage()); - } - - if ($this->mode & PEAR_ERROR_TRIGGER) { - trigger_error($this->getMessage(), $this->level); - } - - if ($this->mode & PEAR_ERROR_DIE) { - $msg = $this->getMessage(); - if (is_null($options) || is_int($options)) { - $format = "%s"; - if (substr($msg, -1) != "\n") { - $msg .= "\n"; - } - } else { - $format = $options; - } - printf($format, $msg); - exit($code); - } - - if ($this->mode & PEAR_ERROR_CALLBACK && is_callable($this->callback)) { - call_user_func($this->callback, $this); - } - - if ($this->mode & PEAR_ERROR_EXCEPTION) { - trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING); - eval('$e = new Exception($this->message, $this->code);throw($e);'); - } - } - - /** - * Only here for backwards compatibility. - * - * Class "Cache_Error" still uses it, among others. - * - * @param string $message Message - * @param int $code Error code - * @param int $mode Error mode - * @param mixed $options See __construct() - * @param string $userinfo Additional user/debug info - */ - public function PEAR_Error( - $message = 'unknown error', $code = null, $mode = null, - $options = null, $userinfo = null - ) { - self::__construct($message, $code, $mode, $options, $userinfo); - } - - /** - * Get the error mode from an error object. - * - * @return int error mode - * @access public - */ - function getMode() - { - return $this->mode; - } - - /** - * Get the callback function/method from an error object. - * - * @return mixed callback function or object/method array - * @access public - */ - function getCallback() - { - return $this->callback; - } - - /** - * Get the error message from an error object. - * - * @return string full error message - * @access public - */ - function getMessage() - { - return ($this->error_message_prefix . $this->message); - } - - /** - * Get error code from an error object - * - * @return int error code - * @access public - */ - function getCode() - { - return $this->code; - } - - /** - * Get the name of this error/exception. - * - * @return string error/exception name (type) - * @access public - */ - function getType() - { - return get_class($this); - } - - /** - * Get additional user-supplied information. - * - * @return string user-supplied information - * @access public - */ - function getUserInfo() - { - return $this->userinfo; - } - - /** - * Get additional debug information supplied by the application. - * - * @return string debug information - * @access public - */ - function getDebugInfo() - { - return $this->getUserInfo(); - } - - /** - * Get the call backtrace from where the error was generated. - * Supported with PHP 4.3.0 or newer. - * - * @param int $frame (optional) what frame to fetch - * @return array Backtrace, or NULL if not available. - * @access public - */ - function getBacktrace($frame = null) - { - if (defined('PEAR_IGNORE_BACKTRACE')) { - return null; - } - if ($frame === null) { - return $this->backtrace; - } - return $this->backtrace[$frame]; - } - - function addUserInfo($info) - { - if (empty($this->userinfo)) { - $this->userinfo = $info; - } else { - $this->userinfo .= " ** $info"; - } - } - - function __toString() - { - return $this->getMessage(); - } - - /** - * Make a string representation of this object. - * - * @return string a string with an object summary - * @access public - */ - function toString() - { - $modes = array(); - $levels = array(E_USER_NOTICE => 'notice', - E_USER_WARNING => 'warning', - E_USER_ERROR => 'error'); - if ($this->mode & PEAR_ERROR_CALLBACK) { - if (is_array($this->callback)) { - $callback = (is_object($this->callback[0]) ? - strtolower(get_class($this->callback[0])) : - $this->callback[0]) . '::' . - $this->callback[1]; - } else { - $callback = $this->callback; - } - return sprintf('[%s: message="%s" code=%d mode=callback '. - 'callback=%s prefix="%s" info="%s"]', - strtolower(get_class($this)), $this->message, $this->code, - $callback, $this->error_message_prefix, - $this->userinfo); - } - if ($this->mode & PEAR_ERROR_PRINT) { - $modes[] = 'print'; - } - if ($this->mode & PEAR_ERROR_TRIGGER) { - $modes[] = 'trigger'; - } - if ($this->mode & PEAR_ERROR_DIE) { - $modes[] = 'die'; - } - if ($this->mode & PEAR_ERROR_RETURN) { - $modes[] = 'return'; - } - return sprintf('[%s: message="%s" code=%d mode=%s level=%s '. - 'prefix="%s" info="%s"]', - strtolower(get_class($this)), $this->message, $this->code, - implode("|", $modes), $levels[$this->level], - $this->error_message_prefix, - $this->userinfo); - } -} - -/* - * Local Variables: - * mode: php - * tab-width: 4 - * c-basic-offset: 4 - * End: - */ diff --git a/lib/pear/pear-core-minimal/src/PEAR/Error.php b/lib/pear/pear-core-minimal/src/PEAR/Error.php deleted file mode 100644 index 96efff75d..000000000 --- a/lib/pear/pear-core-minimal/src/PEAR/Error.php +++ /dev/null @@ -1,14 +0,0 @@ -<?php -/** - * Dummy file to make autoloaders work - * - * PHP version 5 - * - * @category PEAR - * @package PEAR - * @author Christian Weiske <cweiske@php.net> - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @link http://pear.php.net/package/PEAR - */ -require_once __DIR__ . '/../PEAR.php'; -?> \ No newline at end of file diff --git a/lib/pear/pear-core-minimal/src/PEAR/ErrorStack.php b/lib/pear/pear-core-minimal/src/PEAR/ErrorStack.php deleted file mode 100644 index 6619fbb1e..000000000 --- a/lib/pear/pear-core-minimal/src/PEAR/ErrorStack.php +++ /dev/null @@ -1,979 +0,0 @@ -<?php -/** - * Error Stack Implementation - * - * This is an incredibly simple implementation of a very complex error handling - * facility. It contains the ability - * to track multiple errors from multiple packages simultaneously. In addition, - * it can track errors of many levels, save data along with the error, context - * information such as the exact file, line number, class and function that - * generated the error, and if necessary, it can raise a traditional PEAR_Error. - * It has built-in support for PEAR::Log, to log errors as they occur - * - * Since version 0.2alpha, it is also possible to selectively ignore errors, - * through the use of an error callback, see {@link pushCallback()} - * - * Since version 0.3alpha, it is possible to specify the exception class - * returned from {@link push()} - * - * Since version PEAR1.3.2, ErrorStack no longer instantiates an exception class. This can - * still be done quite handily in an error callback or by manipulating the returned array - * @category Debugging - * @package PEAR_ErrorStack - * @author Greg Beaver <cellog@php.net> - * @copyright 2004-2008 Greg Beaver - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @link http://pear.php.net/package/PEAR_ErrorStack - */ - -/** - * Singleton storage - * - * Format: - * <pre> - * array( - * 'package1' => PEAR_ErrorStack object, - * 'package2' => PEAR_ErrorStack object, - * ... - * ) - * </pre> - * @access private - * @global array $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] - */ -$GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] = array(); - -/** - * Global error callback (default) - * - * This is only used if set to non-false. * is the default callback for - * all packages, whereas specific packages may set a default callback - * for all instances, regardless of whether they are a singleton or not. - * - * To exclude non-singletons, only set the local callback for the singleton - * @see PEAR_ErrorStack::setDefaultCallback() - * @access private - * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] - */ -$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] = array( - '*' => false, -); - -/** - * Global Log object (default) - * - * This is only used if set to non-false. Use to set a default log object for - * all stacks, regardless of instantiation order or location - * @see PEAR_ErrorStack::setDefaultLogger() - * @access private - * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] - */ -$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = false; - -/** - * Global Overriding Callback - * - * This callback will override any error callbacks that specific loggers have set. - * Use with EXTREME caution - * @see PEAR_ErrorStack::staticPushCallback() - * @access private - * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] - */ -$GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array(); - -/**#@+ - * One of four possible return values from the error Callback - * @see PEAR_ErrorStack::_errorCallback() - */ -/** - * If this is returned, then the error will be both pushed onto the stack - * and logged. - */ -define('PEAR_ERRORSTACK_PUSHANDLOG', 1); -/** - * If this is returned, then the error will only be pushed onto the stack, - * and not logged. - */ -define('PEAR_ERRORSTACK_PUSH', 2); -/** - * If this is returned, then the error will only be logged, but not pushed - * onto the error stack. - */ -define('PEAR_ERRORSTACK_LOG', 3); -/** - * If this is returned, then the error is completely ignored. - */ -define('PEAR_ERRORSTACK_IGNORE', 4); -/** - * If this is returned, then the error is logged and die() is called. - */ -define('PEAR_ERRORSTACK_DIE', 5); -/**#@-*/ - -/** - * Error code for an attempt to instantiate a non-class as a PEAR_ErrorStack in - * the singleton method. - */ -define('PEAR_ERRORSTACK_ERR_NONCLASS', 1); - -/** - * Error code for an attempt to pass an object into {@link PEAR_ErrorStack::getMessage()} - * that has no __toString() method - */ -define('PEAR_ERRORSTACK_ERR_OBJTOSTRING', 2); -/** - * Error Stack Implementation - * - * Usage: - * <code> - * // global error stack - * $global_stack = &PEAR_ErrorStack::singleton('MyPackage'); - * // local error stack - * $local_stack = new PEAR_ErrorStack('MyPackage'); - * </code> - * @author Greg Beaver <cellog@php.net> - * @version @package_version@ - * @package PEAR_ErrorStack - * @category Debugging - * @copyright 2004-2008 Greg Beaver - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @link http://pear.php.net/package/PEAR_ErrorStack - */ -class PEAR_ErrorStack { - /** - * Errors are stored in the order that they are pushed on the stack. - * @since 0.4alpha Errors are no longer organized by error level. - * This renders pop() nearly unusable, and levels could be more easily - * handled in a callback anyway - * @var array - * @access private - */ - var $_errors = array(); - - /** - * Storage of errors by level. - * - * Allows easy retrieval and deletion of only errors from a particular level - * @since PEAR 1.4.0dev - * @var array - * @access private - */ - var $_errorsByLevel = array(); - - /** - * Package name this error stack represents - * @var string - * @access protected - */ - var $_package; - - /** - * Determines whether a PEAR_Error is thrown upon every error addition - * @var boolean - * @access private - */ - var $_compat = false; - - /** - * If set to a valid callback, this will be used to generate the error - * message from the error code, otherwise the message passed in will be - * used - * @var false|string|array - * @access private - */ - var $_msgCallback = false; - - /** - * If set to a valid callback, this will be used to generate the error - * context for an error. For PHP-related errors, this will be a file - * and line number as retrieved from debug_backtrace(), but can be - * customized for other purposes. The error might actually be in a separate - * configuration file, or in a database query. - * @var false|string|array - * @access protected - */ - var $_contextCallback = false; - - /** - * If set to a valid callback, this will be called every time an error - * is pushed onto the stack. The return value will be used to determine - * whether to allow an error to be pushed or logged. - * - * The return value must be one an PEAR_ERRORSTACK_* constant - * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG - * @var false|string|array - * @access protected - */ - var $_errorCallback = array(); - - /** - * PEAR::Log object for logging errors - * @var false|Log - * @access protected - */ - var $_logger = false; - - /** - * Error messages - designed to be overridden - * @var array - * @abstract - */ - var $_errorMsgs = array(); - - /** - * Set up a new error stack - * - * @param string $package name of the package this error stack represents - * @param callback $msgCallback callback used for error message generation - * @param callback $contextCallback callback used for context generation, - * defaults to {@link getFileLine()} - * @param boolean $throwPEAR_Error - */ - function __construct($package, $msgCallback = false, $contextCallback = false, - $throwPEAR_Error = false) - { - $this->_package = $package; - $this->setMessageCallback($msgCallback); - $this->setContextCallback($contextCallback); - $this->_compat = $throwPEAR_Error; - } - - /** - * Return a single error stack for this package. - * - * Note that all parameters are ignored if the stack for package $package - * has already been instantiated - * @param string $package name of the package this error stack represents - * @param callback $msgCallback callback used for error message generation - * @param callback $contextCallback callback used for context generation, - * defaults to {@link getFileLine()} - * @param boolean $throwPEAR_Error - * @param string $stackClass class to instantiate - * - * @return PEAR_ErrorStack - */ - public static function &singleton( - $package, $msgCallback = false, $contextCallback = false, - $throwPEAR_Error = false, $stackClass = 'PEAR_ErrorStack' - ) { - if (isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) { - return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]; - } - if (!class_exists($stackClass)) { - if (function_exists('debug_backtrace')) { - $trace = debug_backtrace(); - } - PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_NONCLASS, - 'exception', array('stackclass' => $stackClass), - 'stack class "%stackclass%" is not a valid class name (should be like PEAR_ErrorStack)', - false, $trace); - } - $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package] = - new $stackClass($package, $msgCallback, $contextCallback, $throwPEAR_Error); - - return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]; - } - - /** - * Internal error handler for PEAR_ErrorStack class - * - * Dies if the error is an exception (and would have died anyway) - * @access private - */ - function _handleError($err) - { - if ($err['level'] == 'exception') { - $message = $err['message']; - if (isset($_SERVER['REQUEST_URI'])) { - echo '<br />'; - } else { - echo "\n"; - } - var_dump($err['context']); - die($message); - } - } - - /** - * Set up a PEAR::Log object for all error stacks that don't have one - * @param Log $log - */ - public static function setDefaultLogger(&$log) - { - if (is_object($log) && method_exists($log, 'log') ) { - $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log; - } elseif (is_callable($log)) { - $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log; - } - } - - /** - * Set up a PEAR::Log object for this error stack - * @param Log $log - */ - function setLogger(&$log) - { - if (is_object($log) && method_exists($log, 'log') ) { - $this->_logger = &$log; - } elseif (is_callable($log)) { - $this->_logger = &$log; - } - } - - /** - * Set an error code => error message mapping callback - * - * This method sets the callback that can be used to generate error - * messages for any instance - * @param array|string Callback function/method - */ - function setMessageCallback($msgCallback) - { - if (!$msgCallback) { - $this->_msgCallback = array(&$this, 'getErrorMessage'); - } else { - if (is_callable($msgCallback)) { - $this->_msgCallback = $msgCallback; - } - } - } - - /** - * Get an error code => error message mapping callback - * - * This method returns the current callback that can be used to generate error - * messages - * @return array|string|false Callback function/method or false if none - */ - function getMessageCallback() - { - return $this->_msgCallback; - } - - /** - * Sets a default callback to be used by all error stacks - * - * This method sets the callback that can be used to generate error - * messages for a singleton - * @param array|string Callback function/method - * @param string Package name, or false for all packages - */ - public static function setDefaultCallback($callback = false, $package = false) - { - if (!is_callable($callback)) { - $callback = false; - } - $package = $package ? $package : '*'; - $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$package] = $callback; - } - - /** - * Set a callback that generates context information (location of error) for an error stack - * - * This method sets the callback that can be used to generate context - * information for an error. Passing in NULL will disable context generation - * and remove the expensive call to debug_backtrace() - * @param array|string|null Callback function/method - */ - function setContextCallback($contextCallback) - { - if ($contextCallback === null) { - return $this->_contextCallback = false; - } - if (!$contextCallback) { - $this->_contextCallback = array(&$this, 'getFileLine'); - } else { - if (is_callable($contextCallback)) { - $this->_contextCallback = $contextCallback; - } - } - } - - /** - * Set an error Callback - * If set to a valid callback, this will be called every time an error - * is pushed onto the stack. The return value will be used to determine - * whether to allow an error to be pushed or logged. - * - * The return value must be one of the ERRORSTACK_* constants. - * - * This functionality can be used to emulate PEAR's pushErrorHandling, and - * the PEAR_ERROR_CALLBACK mode, without affecting the integrity of - * the error stack or logging - * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG - * @see popCallback() - * @param string|array $cb - */ - function pushCallback($cb) - { - array_push($this->_errorCallback, $cb); - } - - /** - * Remove a callback from the error callback stack - * @see pushCallback() - * @return array|string|false - */ - function popCallback() - { - if (!count($this->_errorCallback)) { - return false; - } - return array_pop($this->_errorCallback); - } - - /** - * Set a temporary overriding error callback for every package error stack - * - * Use this to temporarily disable all existing callbacks (can be used - * to emulate the @ operator, for instance) - * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG - * @see staticPopCallback(), pushCallback() - * @param string|array $cb - */ - public static function staticPushCallback($cb) - { - array_push($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'], $cb); - } - - /** - * Remove a temporary overriding error callback - * @see staticPushCallback() - * @return array|string|false - */ - public static function staticPopCallback() - { - $ret = array_pop($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK']); - if (!is_array($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'])) { - $GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array(); - } - return $ret; - } - - /** - * Add an error to the stack - * - * If the message generator exists, it is called with 2 parameters. - * - the current Error Stack object - * - an array that is in the same format as an error. Available indices - * are 'code', 'package', 'time', 'params', 'level', and 'context' - * - * Next, if the error should contain context information, this is - * handled by the context grabbing method. - * Finally, the error is pushed onto the proper error stack - * @param int $code Package-specific error code - * @param string $level Error level. This is NOT spell-checked - * @param array $params associative array of error parameters - * @param string $msg Error message, or a portion of it if the message - * is to be generated - * @param array $repackage If this error re-packages an error pushed by - * another package, place the array returned from - * {@link pop()} in this parameter - * @param array $backtrace Protected parameter: use this to pass in the - * {@link debug_backtrace()} that should be used - * to find error context - * @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also - * thrown. If a PEAR_Error is returned, the userinfo - * property is set to the following array: - * - * <code> - * array( - * 'code' => $code, - * 'params' => $params, - * 'package' => $this->_package, - * 'level' => $level, - * 'time' => time(), - * 'context' => $context, - * 'message' => $msg, - * //['repackage' => $err] repackaged error array/Exception class - * ); - * </code> - * - * Normally, the previous array is returned. - */ - function push($code, $level = 'error', $params = array(), $msg = false, - $repackage = false, $backtrace = false) - { - $context = false; - // grab error context - if ($this->_contextCallback) { - if (!$backtrace) { - $backtrace = debug_backtrace(); - } - $context = call_user_func($this->_contextCallback, $code, $params, $backtrace); - } - - // save error - $time = explode(' ', microtime()); - $time = $time[1] + $time[0]; - $err = array( - 'code' => $code, - 'params' => $params, - 'package' => $this->_package, - 'level' => $level, - 'time' => $time, - 'context' => $context, - 'message' => $msg, - ); - - if ($repackage) { - $err['repackage'] = $repackage; - } - - // set up the error message, if necessary - if ($this->_msgCallback) { - $msg = call_user_func_array($this->_msgCallback, - array(&$this, $err)); - $err['message'] = $msg; - } - $push = $log = true; - $die = false; - // try the overriding callback first - $callback = $this->staticPopCallback(); - if ($callback) { - $this->staticPushCallback($callback); - } - if (!is_callable($callback)) { - // try the local callback next - $callback = $this->popCallback(); - if (is_callable($callback)) { - $this->pushCallback($callback); - } else { - // try the default callback - $callback = isset($GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package]) ? - $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package] : - $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']['*']; - } - } - if (is_callable($callback)) { - switch(call_user_func($callback, $err)){ - case PEAR_ERRORSTACK_IGNORE: - return $err; - break; - case PEAR_ERRORSTACK_PUSH: - $log = false; - break; - case PEAR_ERRORSTACK_LOG: - $push = false; - break; - case PEAR_ERRORSTACK_DIE: - $die = true; - break; - // anything else returned has the same effect as pushandlog - } - } - if ($push) { - array_unshift($this->_errors, $err); - if (!isset($this->_errorsByLevel[$err['level']])) { - $this->_errorsByLevel[$err['level']] = array(); - } - $this->_errorsByLevel[$err['level']][] = &$this->_errors[0]; - } - if ($log) { - if ($this->_logger || $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']) { - $this->_log($err); - } - } - if ($die) { - die(); - } - if ($this->_compat && $push) { - return $this->raiseError($msg, $code, null, null, $err); - } - return $err; - } - - /** - * Static version of {@link push()} - * - * @param string $package Package name this error belongs to - * @param int $code Package-specific error code - * @param string $level Error level. This is NOT spell-checked - * @param array $params associative array of error parameters - * @param string $msg Error message, or a portion of it if the message - * is to be generated - * @param array $repackage If this error re-packages an error pushed by - * another package, place the array returned from - * {@link pop()} in this parameter - * @param array $backtrace Protected parameter: use this to pass in the - * {@link debug_backtrace()} that should be used - * to find error context - * @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also - * thrown. see docs for {@link push()} - */ - public static function staticPush( - $package, $code, $level = 'error', $params = array(), - $msg = false, $repackage = false, $backtrace = false - ) { - $s = &PEAR_ErrorStack::singleton($package); - if ($s->_contextCallback) { - if (!$backtrace) { - if (function_exists('debug_backtrace')) { - $backtrace = debug_backtrace(); - } - } - } - return $s->push($code, $level, $params, $msg, $repackage, $backtrace); - } - - /** - * Log an error using PEAR::Log - * @param array $err Error array - * @param array $levels Error level => Log constant map - * @access protected - */ - function _log($err) - { - if ($this->_logger) { - $logger = &$this->_logger; - } else { - $logger = &$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']; - } - if (is_a($logger, 'Log')) { - $levels = array( - 'exception' => PEAR_LOG_CRIT, - 'alert' => PEAR_LOG_ALERT, - 'critical' => PEAR_LOG_CRIT, - 'error' => PEAR_LOG_ERR, - 'warning' => PEAR_LOG_WARNING, - 'notice' => PEAR_LOG_NOTICE, - 'info' => PEAR_LOG_INFO, - 'debug' => PEAR_LOG_DEBUG); - if (isset($levels[$err['level']])) { - $level = $levels[$err['level']]; - } else { - $level = PEAR_LOG_INFO; - } - $logger->log($err['message'], $level, $err); - } else { // support non-standard logs - call_user_func($logger, $err); - } - } - - - /** - * Pop an error off of the error stack - * - * @return false|array - * @since 0.4alpha it is no longer possible to specify a specific error - * level to return - the last error pushed will be returned, instead - */ - function pop() - { - $err = @array_shift($this->_errors); - if (!is_null($err)) { - @array_pop($this->_errorsByLevel[$err['level']]); - if (!count($this->_errorsByLevel[$err['level']])) { - unset($this->_errorsByLevel[$err['level']]); - } - } - return $err; - } - - /** - * Pop an error off of the error stack, static method - * - * @param string package name - * @return boolean - * @since PEAR1.5.0a1 - */ - static function staticPop($package) - { - if ($package) { - if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) { - return false; - } - return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->pop(); - } - } - - /** - * Determine whether there are any errors on the stack - * @param string|array Level name. Use to determine if any errors - * of level (string), or levels (array) have been pushed - * @return boolean - */ - function hasErrors($level = false) - { - if ($level) { - return isset($this->_errorsByLevel[$level]); - } - return count($this->_errors); - } - - /** - * Retrieve all errors since last purge - * - * @param boolean set in order to empty the error stack - * @param string level name, to return only errors of a particular severity - * @return array - */ - function getErrors($purge = false, $level = false) - { - if (!$purge) { - if ($level) { - if (!isset($this->_errorsByLevel[$level])) { - return array(); - } else { - return $this->_errorsByLevel[$level]; - } - } else { - return $this->_errors; - } - } - if ($level) { - $ret = $this->_errorsByLevel[$level]; - foreach ($this->_errorsByLevel[$level] as $i => $unused) { - // entries are references to the $_errors array - $this->_errorsByLevel[$level][$i] = false; - } - // array_filter removes all entries === false - $this->_errors = array_filter($this->_errors); - unset($this->_errorsByLevel[$level]); - return $ret; - } - $ret = $this->_errors; - $this->_errors = array(); - $this->_errorsByLevel = array(); - return $ret; - } - - /** - * Determine whether there are any errors on a single error stack, or on any error stack - * - * The optional parameter can be used to test the existence of any errors without the need of - * singleton instantiation - * @param string|false Package name to check for errors - * @param string Level name to check for a particular severity - * @return boolean - */ - public static function staticHasErrors($package = false, $level = false) - { - if ($package) { - if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) { - return false; - } - return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->hasErrors($level); - } - foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) { - if ($obj->hasErrors($level)) { - return true; - } - } - return false; - } - - /** - * Get a list of all errors since last purge, organized by package - * @since PEAR 1.4.0dev BC break! $level is now in the place $merge used to be - * @param boolean $purge Set to purge the error stack of existing errors - * @param string $level Set to a level name in order to retrieve only errors of a particular level - * @param boolean $merge Set to return a flat array, not organized by package - * @param array $sortfunc Function used to sort a merged array - default - * sorts by time, and should be good for most cases - * - * @return array - */ - public static function staticGetErrors( - $purge = false, $level = false, $merge = false, - $sortfunc = array('PEAR_ErrorStack', '_sortErrors') - ) { - $ret = array(); - if (!is_callable($sortfunc)) { - $sortfunc = array('PEAR_ErrorStack', '_sortErrors'); - } - foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) { - $test = $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->getErrors($purge, $level); - if ($test) { - if ($merge) { - $ret = array_merge($ret, $test); - } else { - $ret[$package] = $test; - } - } - } - if ($merge) { - usort($ret, $sortfunc); - } - return $ret; - } - - /** - * Error sorting function, sorts by time - * @access private - */ - public static function _sortErrors($a, $b) - { - if ($a['time'] == $b['time']) { - return 0; - } - if ($a['time'] < $b['time']) { - return 1; - } - return -1; - } - - /** - * Standard file/line number/function/class context callback - * - * This function uses a backtrace generated from {@link debug_backtrace()} - * and so will not work at all in PHP < 4.3.0. The frame should - * reference the frame that contains the source of the error. - * @return array|false either array('file' => file, 'line' => line, - * 'function' => function name, 'class' => class name) or - * if this doesn't work, then false - * @param unused - * @param integer backtrace frame. - * @param array Results of debug_backtrace() - */ - public static function getFileLine($code, $params, $backtrace = null) - { - if ($backtrace === null) { - return false; - } - $frame = 0; - $functionframe = 1; - if (!isset($backtrace[1])) { - $functionframe = 0; - } else { - while (isset($backtrace[$functionframe]['function']) && - $backtrace[$functionframe]['function'] == 'eval' && - isset($backtrace[$functionframe + 1])) { - $functionframe++; - } - } - if (isset($backtrace[$frame])) { - if (!isset($backtrace[$frame]['file'])) { - $frame++; - } - $funcbacktrace = $backtrace[$functionframe]; - $filebacktrace = $backtrace[$frame]; - $ret = array('file' => $filebacktrace['file'], - 'line' => $filebacktrace['line']); - // rearrange for eval'd code or create function errors - if (strpos($filebacktrace['file'], '(') && - preg_match(';^(.*?)\((\d+)\) : (.*?)\\z;', $filebacktrace['file'], - $matches)) { - $ret['file'] = $matches[1]; - $ret['line'] = $matches[2] + 0; - } - if (isset($funcbacktrace['function']) && isset($backtrace[1])) { - if ($funcbacktrace['function'] != 'eval') { - if ($funcbacktrace['function'] == '__lambda_func') { - $ret['function'] = 'create_function() code'; - } else { - $ret['function'] = $funcbacktrace['function']; - } - } - } - if (isset($funcbacktrace['class']) && isset($backtrace[1])) { - $ret['class'] = $funcbacktrace['class']; - } - return $ret; - } - return false; - } - - /** - * Standard error message generation callback - * - * This method may also be called by a custom error message generator - * to fill in template values from the params array, simply - * set the third parameter to the error message template string to use - * - * The special variable %__msg% is reserved: use it only to specify - * where a message passed in by the user should be placed in the template, - * like so: - * - * Error message: %msg% - internal error - * - * If the message passed like so: - * - * <code> - * $stack->push(ERROR_CODE, 'error', array(), 'server error 500'); - * </code> - * - * The returned error message will be "Error message: server error 500 - - * internal error" - * @param PEAR_ErrorStack - * @param array - * @param string|false Pre-generated error message template - * - * @return string - */ - public static function getErrorMessage(&$stack, $err, $template = false) - { - if ($template) { - $mainmsg = $template; - } else { - $mainmsg = $stack->getErrorMessageTemplate($err['code']); - } - $mainmsg = str_replace('%__msg%', $err['message'], $mainmsg); - if (is_array($err['params']) && count($err['params'])) { - foreach ($err['params'] as $name => $val) { - if (is_array($val)) { - // @ is needed in case $val is a multi-dimensional array - $val = @implode(', ', $val); - } - if (is_object($val)) { - if (method_exists($val, '__toString')) { - $val = $val->__toString(); - } else { - PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_OBJTOSTRING, - 'warning', array('obj' => get_class($val)), - 'object %obj% passed into getErrorMessage, but has no __toString() method'); - $val = 'Object'; - } - } - $mainmsg = str_replace('%' . $name . '%', $val, $mainmsg); - } - } - return $mainmsg; - } - - /** - * Standard Error Message Template generator from code - * @return string - */ - function getErrorMessageTemplate($code) - { - if (!isset($this->_errorMsgs[$code])) { - return '%__msg%'; - } - return $this->_errorMsgs[$code]; - } - - /** - * Set the Error Message Template array - * - * The array format must be: - * <pre> - * array(error code => 'message template',...) - * </pre> - * - * Error message parameters passed into {@link push()} will be used as input - * for the error message. If the template is 'message %foo% was %bar%', and the - * parameters are array('foo' => 'one', 'bar' => 'six'), the error message returned will - * be 'message one was six' - * @return string - */ - function setErrorMessageTemplate($template) - { - $this->_errorMsgs = $template; - } - - - /** - * emulate PEAR::raiseError() - * - * @return PEAR_Error - */ - function raiseError() - { - require_once 'PEAR.php'; - $args = func_get_args(); - return call_user_func_array(array('PEAR', 'raiseError'), $args); - } -} -$stack = &PEAR_ErrorStack::singleton('PEAR_ErrorStack'); -$stack->pushCallback(array('PEAR_ErrorStack', '_handleError')); -?> diff --git a/lib/pear/pear-core-minimal/src/System.php b/lib/pear/pear-core-minimal/src/System.php deleted file mode 100644 index a7ef46598..000000000 --- a/lib/pear/pear-core-minimal/src/System.php +++ /dev/null @@ -1,630 +0,0 @@ -<?php -/** - * File/Directory manipulation - * - * PHP versions 4 and 5 - * - * @category pear - * @package System - * @author Tomas V.V.Cox <cox@idecnet.com> - * @copyright 1997-2009 The Authors - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @link http://pear.php.net/package/PEAR - * @since File available since Release 0.1 - */ - -/** - * base class - */ -require_once 'PEAR.php'; -require_once 'Console/Getopt.php'; - -$GLOBALS['_System_temp_files'] = array(); - -/** -* System offers cross platform compatible system functions -* -* Static functions for different operations. Should work under -* Unix and Windows. The names and usage has been taken from its respectively -* GNU commands. The functions will return (bool) false on error and will -* trigger the error with the PHP trigger_error() function (you can silence -* the error by prefixing a '@' sign after the function call, but this -* is not recommended practice. Instead use an error handler with -* {@link set_error_handler()}). -* -* Documentation on this class you can find in: -* http://pear.php.net/manual/ -* -* Example usage: -* if (!@System::rm('-r file1 dir1')) { -* print "could not delete file1 or dir1"; -* } -* -* In case you need to to pass file names with spaces, -* pass the params as an array: -* -* System::rm(array('-r', $file1, $dir1)); -* -* @category pear -* @package System -* @author Tomas V.V. Cox <cox@idecnet.com> -* @copyright 1997-2006 The PHP Group -* @license http://opensource.org/licenses/bsd-license.php New BSD License -* @version Release: @package_version@ -* @link http://pear.php.net/package/PEAR -* @since Class available since Release 0.1 -* @static -*/ -class System -{ - /** - * returns the commandline arguments of a function - * - * @param string $argv the commandline - * @param string $short_options the allowed option short-tags - * @param string $long_options the allowed option long-tags - * @return array the given options and there values - */ - public static function _parseArgs($argv, $short_options, $long_options = null) - { - if (!is_array($argv) && $argv !== null) { - /* - // Quote all items that are a short option - $av = preg_split('/(\A| )--?[a-z0-9]+[ =]?((?<!\\\\)((,\s*)|((?<!,)\s+))?)/i', $argv, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE); - $offset = 0; - foreach ($av as $a) { - $b = trim($a[0]); - if ($b[0] == '"' || $b[0] == "'") { - continue; - } - - $escape = escapeshellarg($b); - $pos = $a[1] + $offset; - $argv = substr_replace($argv, $escape, $pos, strlen($b)); - $offset += 2; - } - */ - - // Find all items, quoted or otherwise - preg_match_all("/(?:[\"'])(.*?)(?:['\"])|([^\s]+)/", $argv, $av); - $argv = $av[1]; - foreach ($av[2] as $k => $a) { - if (empty($a)) { - continue; - } - $argv[$k] = trim($a) ; - } - } - - return Console_Getopt::getopt2($argv, $short_options, $long_options); - } - - /** - * Output errors with PHP trigger_error(). You can silence the errors - * with prefixing a "@" sign to the function call: @System::mkdir(..); - * - * @param mixed $error a PEAR error or a string with the error message - * @return bool false - */ - protected static function raiseError($error) - { - if (PEAR::isError($error)) { - $error = $error->getMessage(); - } - trigger_error($error, E_USER_WARNING); - return false; - } - - /** - * Creates a nested array representing the structure of a directory - * - * System::_dirToStruct('dir1', 0) => - * Array - * ( - * [dirs] => Array - * ( - * [0] => dir1 - * ) - * - * [files] => Array - * ( - * [0] => dir1/file2 - * [1] => dir1/file3 - * ) - * ) - * @param string $sPath Name of the directory - * @param integer $maxinst max. deep of the lookup - * @param integer $aktinst starting deep of the lookup - * @param bool $silent if true, do not emit errors. - * @return array the structure of the dir - */ - protected static function _dirToStruct($sPath, $maxinst, $aktinst = 0, $silent = false) - { - $struct = array('dirs' => array(), 'files' => array()); - if (($dir = @opendir($sPath)) === false) { - if (!$silent) { - System::raiseError("Could not open dir $sPath"); - } - return $struct; // XXX could not open error - } - - $struct['dirs'][] = $sPath = realpath($sPath); // XXX don't add if '.' or '..' ? - $list = array(); - while (false !== ($file = readdir($dir))) { - if ($file != '.' && $file != '..') { - $list[] = $file; - } - } - - closedir($dir); - natsort($list); - if ($aktinst < $maxinst || $maxinst == 0) { - foreach ($list as $val) { - $path = $sPath . DIRECTORY_SEPARATOR . $val; - if (is_dir($path) && !is_link($path)) { - $tmp = System::_dirToStruct($path, $maxinst, $aktinst+1, $silent); - $struct = array_merge_recursive($struct, $tmp); - } else { - $struct['files'][] = $path; - } - } - } - - return $struct; - } - - /** - * Creates a nested array representing the structure of a directory and files - * - * @param array $files Array listing files and dirs - * @return array - * @static - * @see System::_dirToStruct() - */ - protected static function _multipleToStruct($files) - { - $struct = array('dirs' => array(), 'files' => array()); - settype($files, 'array'); - foreach ($files as $file) { - if (is_dir($file) && !is_link($file)) { - $tmp = System::_dirToStruct($file, 0); - $struct = array_merge_recursive($tmp, $struct); - } else { - if (!in_array($file, $struct['files'])) { - $struct['files'][] = $file; - } - } - } - return $struct; - } - - /** - * The rm command for removing files. - * Supports multiple files and dirs and also recursive deletes - * - * @param string $args the arguments for rm - * @return mixed PEAR_Error or true for success - * @static - * @access public - */ - public static function rm($args) - { - $opts = System::_parseArgs($args, 'rf'); // "f" does nothing but I like it :-) - if (PEAR::isError($opts)) { - return System::raiseError($opts); - } - foreach ($opts[0] as $opt) { - if ($opt[0] == 'r') { - $do_recursive = true; - } - } - $ret = true; - if (isset($do_recursive)) { - $struct = System::_multipleToStruct($opts[1]); - foreach ($struct['files'] as $file) { - if (!@unlink($file)) { - $ret = false; - } - } - - rsort($struct['dirs']); - foreach ($struct['dirs'] as $dir) { - if (!@rmdir($dir)) { - $ret = false; - } - } - } else { - foreach ($opts[1] as $file) { - $delete = (is_dir($file)) ? 'rmdir' : 'unlink'; - if (!@$delete($file)) { - $ret = false; - } - } - } - return $ret; - } - - /** - * Make directories. - * - * The -p option will create parent directories - * @param string $args the name of the director(y|ies) to create - * @return bool True for success - */ - public static function mkDir($args) - { - $opts = System::_parseArgs($args, 'pm:'); - if (PEAR::isError($opts)) { - return System::raiseError($opts); - } - - $mode = 0777; // default mode - foreach ($opts[0] as $opt) { - if ($opt[0] == 'p') { - $create_parents = true; - } elseif ($opt[0] == 'm') { - // if the mode is clearly an octal number (starts with 0) - // convert it to decimal - if (strlen($opt[1]) && $opt[1][0] == '0') { - $opt[1] = octdec($opt[1]); - } else { - // convert to int - $opt[1] += 0; - } - $mode = $opt[1]; - } - } - - $ret = true; - if (isset($create_parents)) { - foreach ($opts[1] as $dir) { - $dirstack = array(); - while ((!file_exists($dir) || !is_dir($dir)) && - $dir != DIRECTORY_SEPARATOR) { - array_unshift($dirstack, $dir); - $dir = dirname($dir); - } - - while ($newdir = array_shift($dirstack)) { - if (!is_writeable(dirname($newdir))) { - $ret = false; - break; - } - - if (!mkdir($newdir, $mode)) { - $ret = false; - } - } - } - } else { - foreach($opts[1] as $dir) { - if ((@file_exists($dir) || !is_dir($dir)) && !mkdir($dir, $mode)) { - $ret = false; - } - } - } - - return $ret; - } - - /** - * Concatenate files - * - * Usage: - * 1) $var = System::cat('sample.txt test.txt'); - * 2) System::cat('sample.txt test.txt > final.txt'); - * 3) System::cat('sample.txt test.txt >> final.txt'); - * - * Note: as the class use fopen, urls should work also - * - * @param string $args the arguments - * @return boolean true on success - */ - public static function &cat($args) - { - $ret = null; - $files = array(); - if (!is_array($args)) { - $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY); - } - - $count_args = count($args); - for ($i = 0; $i < $count_args; $i++) { - if ($args[$i] == '>') { - $mode = 'wb'; - $outputfile = $args[$i+1]; - break; - } elseif ($args[$i] == '>>') { - $mode = 'ab+'; - $outputfile = $args[$i+1]; - break; - } else { - $files[] = $args[$i]; - } - } - $outputfd = false; - if (isset($mode)) { - if (!$outputfd = fopen($outputfile, $mode)) { - $err = System::raiseError("Could not open $outputfile"); - return $err; - } - $ret = true; - } - foreach ($files as $file) { - if (!$fd = fopen($file, 'r')) { - System::raiseError("Could not open $file"); - continue; - } - while ($cont = fread($fd, 2048)) { - if (is_resource($outputfd)) { - fwrite($outputfd, $cont); - } else { - $ret .= $cont; - } - } - fclose($fd); - } - if (is_resource($outputfd)) { - fclose($outputfd); - } - return $ret; - } - - /** - * Creates temporary files or directories. This function will remove - * the created files when the scripts finish its execution. - * - * Usage: - * 1) $tempfile = System::mktemp("prefix"); - * 2) $tempdir = System::mktemp("-d prefix"); - * 3) $tempfile = System::mktemp(); - * 4) $tempfile = System::mktemp("-t /var/tmp prefix"); - * - * prefix -> The string that will be prepended to the temp name - * (defaults to "tmp"). - * -d -> A temporary dir will be created instead of a file. - * -t -> The target dir where the temporary (file|dir) will be created. If - * this param is missing by default the env vars TMP on Windows or - * TMPDIR in Unix will be used. If these vars are also missing - * c:\windows\temp or /tmp will be used. - * - * @param string $args The arguments - * @return mixed the full path of the created (file|dir) or false - * @see System::tmpdir() - */ - public static function mktemp($args = null) - { - static $first_time = true; - $opts = System::_parseArgs($args, 't:d'); - if (PEAR::isError($opts)) { - return System::raiseError($opts); - } - - foreach ($opts[0] as $opt) { - if ($opt[0] == 'd') { - $tmp_is_dir = true; - } elseif ($opt[0] == 't') { - $tmpdir = $opt[1]; - } - } - - $prefix = (isset($opts[1][0])) ? $opts[1][0] : 'tmp'; - if (!isset($tmpdir)) { - $tmpdir = System::tmpdir(); - } - - if (!System::mkDir(array('-p', $tmpdir))) { - return false; - } - - $tmp = tempnam($tmpdir, $prefix); - if (isset($tmp_is_dir)) { - unlink($tmp); // be careful possible race condition here - if (!mkdir($tmp, 0700)) { - return System::raiseError("Unable to create temporary directory $tmpdir"); - } - } - - $GLOBALS['_System_temp_files'][] = $tmp; - if (isset($tmp_is_dir)) { - //$GLOBALS['_System_temp_files'][] = dirname($tmp); - } - - if ($first_time) { - PEAR::registerShutdownFunc(array('System', '_removeTmpFiles')); - $first_time = false; - } - - return $tmp; - } - - /** - * Remove temporary files created my mkTemp. This function is executed - * at script shutdown time - */ - public static function _removeTmpFiles() - { - if (count($GLOBALS['_System_temp_files'])) { - $delete = $GLOBALS['_System_temp_files']; - array_unshift($delete, '-r'); - System::rm($delete); - $GLOBALS['_System_temp_files'] = array(); - } - } - - /** - * Get the path of the temporal directory set in the system - * by looking in its environments variables. - * Note: php.ini-recommended removes the "E" from the variables_order setting, - * making unavaible the $_ENV array, that s why we do tests with _ENV - * - * @return string The temporary directory on the system - */ - public static function tmpdir() - { - if (OS_WINDOWS) { - if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) { - return $var; - } - if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) { - return $var; - } - if ($var = isset($_ENV['USERPROFILE']) ? $_ENV['USERPROFILE'] : getenv('USERPROFILE')) { - return $var; - } - if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) { - return $var; - } - return getenv('SystemRoot') . '\temp'; - } - if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) { - return $var; - } - return realpath(function_exists('sys_get_temp_dir') ? sys_get_temp_dir() : '/tmp'); - } - - /** - * The "which" command (show the full path of a command) - * - * @param string $program The command to search for - * @param mixed $fallback Value to return if $program is not found - * - * @return mixed A string with the full path or false if not found - * @author Stig Bakken <ssb@php.net> - */ - public static function which($program, $fallback = false) - { - // enforce API - if (!is_string($program) || '' == $program) { - return $fallback; - } - - // full path given - if (basename($program) != $program) { - $path_elements[] = dirname($program); - $program = basename($program); - } else { - $path = getenv('PATH'); - if (!$path) { - $path = getenv('Path'); // some OSes are just stupid enough to do this - } - - $path_elements = explode(PATH_SEPARATOR, $path); - } - - if (OS_WINDOWS) { - $exe_suffixes = getenv('PATHEXT') - ? explode(PATH_SEPARATOR, getenv('PATHEXT')) - : array('.exe','.bat','.cmd','.com'); - // allow passing a command.exe param - if (strpos($program, '.') !== false) { - array_unshift($exe_suffixes, ''); - } - } else { - $exe_suffixes = array(''); - } - - foreach ($exe_suffixes as $suff) { - foreach ($path_elements as $dir) { - $file = $dir . DIRECTORY_SEPARATOR . $program . $suff; - // It's possible to run a .bat on Windows that is_executable - // would return false for. The is_executable check is meaningless... - if (OS_WINDOWS) { - if (file_exists($file)) { - return $file; - } - } else { - if (is_executable($file)) { - return $file; - } - } - } - } - return $fallback; - } - - /** - * The "find" command - * - * Usage: - * - * System::find($dir); - * System::find("$dir -type d"); - * System::find("$dir -type f"); - * System::find("$dir -name *.php"); - * System::find("$dir -name *.php -name *.htm*"); - * System::find("$dir -maxdepth 1"); - * - * Params implemented: - * $dir -> Start the search at this directory - * -type d -> return only directories - * -type f -> return only files - * -maxdepth <n> -> max depth of recursion - * -name <pattern> -> search pattern (bash style). Multiple -name param allowed - * - * @param mixed Either array or string with the command line - * @return array Array of found files - */ - public static function find($args) - { - if (!is_array($args)) { - $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY); - } - $dir = realpath(array_shift($args)); - if (!$dir) { - return array(); - } - $patterns = array(); - $depth = 0; - $do_files = $do_dirs = true; - $args_count = count($args); - for ($i = 0; $i < $args_count; $i++) { - switch ($args[$i]) { - case '-type': - if (in_array($args[$i+1], array('d', 'f'))) { - if ($args[$i+1] == 'd') { - $do_files = false; - } else { - $do_dirs = false; - } - } - $i++; - break; - case '-name': - $name = preg_quote($args[$i+1], '#'); - // our magic characters ? and * have just been escaped, - // so now we change the escaped versions to PCRE operators - $name = strtr($name, array('\?' => '.', '\*' => '.*')); - $patterns[] = '('.$name.')'; - $i++; - break; - case '-maxdepth': - $depth = $args[$i+1]; - break; - } - } - $path = System::_dirToStruct($dir, $depth, 0, true); - if ($do_files && $do_dirs) { - $files = array_merge($path['files'], $path['dirs']); - } elseif ($do_dirs) { - $files = $path['dirs']; - } else { - $files = $path['files']; - } - if (count($patterns)) { - $dsq = preg_quote(DIRECTORY_SEPARATOR, '#'); - $pattern = '#(^|'.$dsq.')'.implode('|', $patterns).'($|'.$dsq.')#'; - $ret = array(); - $files_count = count($files); - for ($i = 0; $i < $files_count; $i++) { - // only search in the part of the file below the current directory - $filepart = basename($files[$i]); - if (preg_match($pattern, $filepart)) { - $ret[] = $files[$i]; - } - } - return $ret; - } - return $files; - } -} diff --git a/lib/pear/pear_exception/LICENSE b/lib/pear/pear_exception/LICENSE deleted file mode 100644 index a00a2421f..000000000 --- a/lib/pear/pear_exception/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 1997-2009, - Stig Bakken <ssb@php.net>, - Gregory Beaver <cellog@php.net>, - Helgi Þormar Þorbjörnsson <helgi@php.net>, - Tomas V.V.Cox <cox@idecnet.com>, - Martin Jansen <mj@php.net>. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -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/lib/pear/pear_exception/PEAR/Exception.php b/lib/pear/pear_exception/PEAR/Exception.php deleted file mode 100644 index a8ef6e086..000000000 --- a/lib/pear/pear_exception/PEAR/Exception.php +++ /dev/null @@ -1,456 +0,0 @@ -<?php -/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */ -/** - * PEAR_Exception - * - * PHP version 5 - * - * @category PEAR - * @package PEAR_Exception - * @author Tomas V. V. Cox <cox@idecnet.com> - * @author Hans Lellelid <hans@velum.net> - * @author Bertrand Mansion <bmansion@mamasam.com> - * @author Greg Beaver <cellog@php.net> - * @copyright 1997-2009 The Authors - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @link http://pear.php.net/package/PEAR_Exception - * @since File available since Release 1.0.0 - */ - - -/** - * Base PEAR_Exception Class - * - * 1) Features: - * - * - Nestable exceptions (throw new PEAR_Exception($msg, $prev_exception)) - * - Definable triggers, shot when exceptions occur - * - Pretty and informative error messages - * - Added more context info available (like class, method or cause) - * - cause can be a PEAR_Exception or an array of mixed - * PEAR_Exceptions/PEAR_ErrorStack warnings - * - callbacks for specific exception classes and their children - * - * 2) Ideas: - * - * - Maybe a way to define a 'template' for the output - * - * 3) Inherited properties from PHP Exception Class: - * - * protected $message - * protected $code - * protected $line - * protected $file - * private $trace - * - * 4) Inherited methods from PHP Exception Class: - * - * __clone - * __construct - * getMessage - * getCode - * getFile - * getLine - * getTraceSafe - * getTraceSafeAsString - * __toString - * - * 5) Usage example - * - * <code> - * require_once 'PEAR/Exception.php'; - * - * class Test { - * function foo() { - * throw new PEAR_Exception('Error Message', ERROR_CODE); - * } - * } - * - * function myLogger($pear_exception) { - * echo $pear_exception->getMessage(); - * } - * // each time a exception is thrown the 'myLogger' will be called - * // (its use is completely optional) - * PEAR_Exception::addObserver('myLogger'); - * $test = new Test; - * try { - * $test->foo(); - * } catch (PEAR_Exception $e) { - * print $e; - * } - * </code> - * - * @category PEAR - * @package PEAR_Exception - * @author Tomas V.V.Cox <cox@idecnet.com> - * @author Hans Lellelid <hans@velum.net> - * @author Bertrand Mansion <bmansion@mamasam.com> - * @author Greg Beaver <cellog@php.net> - * @copyright 1997-2009 The Authors - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: @package_version@ - * @link http://pear.php.net/package/PEAR_Exception - * @since Class available since Release 1.0.0 - */ -class PEAR_Exception extends Exception -{ - const OBSERVER_PRINT = -2; - const OBSERVER_TRIGGER = -4; - const OBSERVER_DIE = -8; - protected $cause; - private static $_observers = array(); - private static $_uniqueid = 0; - private $_trace; - - /** - * Supported signatures: - * - PEAR_Exception(string $message); - * - PEAR_Exception(string $message, int $code); - * - PEAR_Exception(string $message, Exception $cause); - * - PEAR_Exception(string $message, Exception $cause, int $code); - * - PEAR_Exception(string $message, PEAR_Error $cause); - * - PEAR_Exception(string $message, PEAR_Error $cause, int $code); - * - PEAR_Exception(string $message, array $causes); - * - PEAR_Exception(string $message, array $causes, int $code); - * - * @param string $message exception message - * @param int|Exception|PEAR_Error|array|null $p2 exception cause - * @param int|null $p3 exception code or null - */ - public function __construct($message, $p2 = null, $p3 = null) - { - if (is_int($p2)) { - $code = $p2; - $this->cause = null; - } elseif (is_object($p2) || is_array($p2)) { - // using is_object allows both Exception and PEAR_Error - if (is_object($p2) && !($p2 instanceof Exception)) { - if (!class_exists('PEAR_Error') || !($p2 instanceof PEAR_Error)) { - throw new PEAR_Exception( - 'exception cause must be Exception, ' . - 'array, or PEAR_Error' - ); - } - } - $code = $p3; - if (is_array($p2) && isset($p2['message'])) { - // fix potential problem of passing in a single warning - $p2 = array($p2); - } - $this->cause = $p2; - } else { - $code = null; - $this->cause = null; - } - parent::__construct($message, (int) $code); - $this->signal(); - } - - /** - * Add an exception observer - * - * @param mixed $callback - A valid php callback, see php func is_callable() - * - A PEAR_Exception::OBSERVER_* constant - * - An array(const PEAR_Exception::OBSERVER_*, - * mixed $options) - * @param string $label The name of the observer. Use this if you want - * to remove it later with removeObserver() - * - * @return void - */ - public static function addObserver($callback, $label = 'default') - { - self::$_observers[$label] = $callback; - } - - /** - * Remove an exception observer - * - * @param string $label Name of the observer - * - * @return void - */ - public static function removeObserver($label = 'default') - { - unset(self::$_observers[$label]); - } - - /** - * Generate a unique ID for an observer - * - * @return int unique identifier for an observer - */ - public static function getUniqueId() - { - return self::$_uniqueid++; - } - - /** - * Send a signal to all observers - * - * @return void - */ - protected function signal() - { - foreach (self::$_observers as $func) { - if (is_callable($func)) { - call_user_func($func, $this); - continue; - } - settype($func, 'array'); - switch ($func[0]) { - case self::OBSERVER_PRINT : - $f = (isset($func[1])) ? $func[1] : '%s'; - printf($f, $this->getMessage()); - break; - case self::OBSERVER_TRIGGER : - $f = (isset($func[1])) ? $func[1] : E_USER_NOTICE; - trigger_error($this->getMessage(), $f); - break; - case self::OBSERVER_DIE : - $f = (isset($func[1])) ? $func[1] : '%s'; - die(printf($f, $this->getMessage())); - break; - default: - trigger_error('invalid observer type', E_USER_WARNING); - } - } - } - - /** - * Return specific error information that can be used for more detailed - * error messages or translation. - * - * This method may be overridden in child exception classes in order - * to add functionality not present in PEAR_Exception and is a placeholder - * to define API - * - * The returned array must be an associative array of parameter => value like so: - * <pre> - * array('name' => $name, 'context' => array(...)) - * </pre> - * - * @return array - */ - public function getErrorData() - { - return array(); - } - - /** - * Returns the exception that caused this exception to be thrown - * - * @return Exception|array The context of the exception - */ - public function getCause() - { - return $this->cause; - } - - /** - * Function must be public to call on caused exceptions - * - * @param array $causes Array that gets filled. - * - * @return void - */ - public function getCauseMessage(&$causes) - { - $trace = $this->getTraceSafe(); - $cause = array('class' => get_class($this), - 'message' => $this->message, - 'file' => 'unknown', - 'line' => 'unknown'); - if (isset($trace[0])) { - if (isset($trace[0]['file'])) { - $cause['file'] = $trace[0]['file']; - $cause['line'] = $trace[0]['line']; - } - } - $causes[] = $cause; - if ($this->cause instanceof PEAR_Exception) { - $this->cause->getCauseMessage($causes); - } elseif ($this->cause instanceof Exception) { - $causes[] = array('class' => get_class($this->cause), - 'message' => $this->cause->getMessage(), - 'file' => $this->cause->getFile(), - 'line' => $this->cause->getLine()); - } elseif (class_exists('PEAR_Error') && $this->cause instanceof PEAR_Error) { - $causes[] = array('class' => get_class($this->cause), - 'message' => $this->cause->getMessage(), - 'file' => 'unknown', - 'line' => 'unknown'); - } elseif (is_array($this->cause)) { - foreach ($this->cause as $cause) { - if ($cause instanceof PEAR_Exception) { - $cause->getCauseMessage($causes); - } elseif ($cause instanceof Exception) { - $causes[] = array('class' => get_class($cause), - 'message' => $cause->getMessage(), - 'file' => $cause->getFile(), - 'line' => $cause->getLine()); - } elseif (class_exists('PEAR_Error') - && $cause instanceof PEAR_Error - ) { - $causes[] = array('class' => get_class($cause), - 'message' => $cause->getMessage(), - 'file' => 'unknown', - 'line' => 'unknown'); - } elseif (is_array($cause) && isset($cause['message'])) { - // PEAR_ErrorStack warning - $causes[] = array( - 'class' => $cause['package'], - 'message' => $cause['message'], - 'file' => isset($cause['context']['file']) ? - $cause['context']['file'] : - 'unknown', - 'line' => isset($cause['context']['line']) ? - $cause['context']['line'] : - 'unknown', - ); - } - } - } - } - - /** - * Build a backtrace and return it - * - * @return array Backtrace - */ - public function getTraceSafe() - { - if (!isset($this->_trace)) { - $this->_trace = $this->getTrace(); - if (empty($this->_trace)) { - $backtrace = debug_backtrace(); - $this->_trace = array($backtrace[count($backtrace)-1]); - } - } - return $this->_trace; - } - - /** - * Gets the first class of the backtrace - * - * @return string Class name - */ - public function getErrorClass() - { - $trace = $this->getTraceSafe(); - return $trace[0]['class']; - } - - /** - * Gets the first method of the backtrace - * - * @return string Method/function name - */ - public function getErrorMethod() - { - $trace = $this->getTraceSafe(); - return $trace[0]['function']; - } - - /** - * Converts the exception to a string (HTML or plain text) - * - * @return string String representation - * - * @see toHtml() - * @see toText() - */ - public function __toString() - { - if (isset($_SERVER['REQUEST_URI'])) { - return $this->toHtml(); - } - return $this->toText(); - } - - /** - * Generates a HTML representation of the exception - * - * @return string HTML code - */ - public function toHtml() - { - $trace = $this->getTraceSafe(); - $causes = array(); - $this->getCauseMessage($causes); - $html = '<table style="border: 1px" cellspacing="0">' . "\n"; - foreach ($causes as $i => $cause) { - $html .= '<tr><td colspan="3" style="background: #ff9999">' - . str_repeat('-', $i) . ' <b>' . $cause['class'] . '</b>: ' - . htmlspecialchars($cause['message']) - . ' in <b>' . $cause['file'] . '</b> ' - . 'on line <b>' . $cause['line'] . '</b>' - . "</td></tr>\n"; - } - $html .= '<tr><td colspan="3" style="background-color: #aaaaaa; text-align: center; font-weight: bold;">Exception trace</td></tr>' . "\n" - . '<tr><td style="text-align: center; background: #cccccc; width:20px; font-weight: bold;">#</td>' - . '<td style="text-align: center; background: #cccccc; font-weight: bold;">Function</td>' - . '<td style="text-align: center; background: #cccccc; font-weight: bold;">Location</td></tr>' . "\n"; - - foreach ($trace as $k => $v) { - $html .= '<tr><td style="text-align: center;">' . $k . '</td>' - . '<td>'; - if (!empty($v['class'])) { - $html .= $v['class'] . $v['type']; - } - $html .= $v['function']; - $args = array(); - if (!empty($v['args'])) { - foreach ($v['args'] as $arg) { - if (is_null($arg)) { - $args[] = 'null'; - } else if (is_array($arg)) { - $args[] = 'Array'; - } else if (is_object($arg)) { - $args[] = 'Object('.get_class($arg).')'; - } else if (is_bool($arg)) { - $args[] = $arg ? 'true' : 'false'; - } else if (is_int($arg) || is_double($arg)) { - $args[] = $arg; - } else { - $arg = (string)$arg; - $str = htmlspecialchars(substr($arg, 0, 16)); - if (strlen($arg) > 16) { - $str .= '&hellip;'; - } - $args[] = "'" . $str . "'"; - } - } - } - $html .= '(' . implode(', ', $args) . ')' - . '</td>' - . '<td>' . (isset($v['file']) ? $v['file'] : 'unknown') - . ':' . (isset($v['line']) ? $v['line'] : 'unknown') - . '</td></tr>' . "\n"; - } - $html .= '<tr><td style="text-align: center;">' . ($k+1) . '</td>' - . '<td>{main}</td>' - . '<td>&nbsp;</td></tr>' . "\n" - . '</table>'; - return $html; - } - - /** - * Generates text representation of the exception and stack trace - * - * @return string - */ - public function toText() - { - $causes = array(); - $this->getCauseMessage($causes); - $causeMsg = ''; - foreach ($causes as $i => $cause) { - $causeMsg .= str_repeat(' ', $i) . $cause['class'] . ': ' - . $cause['message'] . ' in ' . $cause['file'] - . ' on line ' . $cause['line'] . "\n"; - } - return $causeMsg . $this->getTraceAsString(); - } -} -?> diff --git a/lib/pear/pear_exception/composer.json b/lib/pear/pear_exception/composer.json deleted file mode 100644 index 9ffba9b3d..000000000 --- a/lib/pear/pear_exception/composer.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "name": "pear/pear_exception", - "description": "The PEAR Exception base class.", - "type": "class", - "keywords": [ - "exception" - ], - "homepage": "https://github.com/pear/PEAR_Exception", - "license": "BSD-2-Clause", - "authors": [ - { - "name": "Helgi Thormar", - "email": "dufuz@php.net" - }, - { - "name": "Greg Beaver", - "email": "cellog@php.net" - } - ], - "require": { - "php": ">=5.2.0" - }, - "autoload": { - "classmap": ["PEAR/"] - }, - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "include-path": [ - "." - ], - "support": { - "issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=PEAR_Exception", - "source": "https://github.com/pear/PEAR_Exception" - }, - "require-dev": { - "phpunit/phpunit": "<9" - } -} diff --git a/lib/pelago/emogrifier/CHANGELOG.md b/lib/pelago/emogrifier/CHANGELOG.md deleted file mode 100644 index 8e44e6e90..000000000 --- a/lib/pelago/emogrifier/CHANGELOG.md +++ /dev/null @@ -1,415 +0,0 @@ -# Emogrifier Change Log - -All notable changes to this project will be documented in this file. -This project adheres to [Semantic Versioning](https://semver.org/). - -## x.y.z - -### Added - -### Changed - -### Deprecated -- Support for PHP 7.3 will be removed in Emogrifier 8.0. - -### Removed - -### Fixed - -## 6.0.0 - -### Added -- Test with Symfony 6-dev (#1109) -- Add support for PHP 8.1 (#1103) -- Add a dedicated class for caching (#1097) -- Allow installation together with Symfony 6 (#1065) -- Support more file types in the `.editorconfig` (#1035) -- Set `align` attribute of `<th>` elements with `CssToAttributeConverter` (#1008) - -### Changed -- Use `sabberworm/php-css-parser` to parse the CSS (#1015) -- Also check the unit test code with Psalm (#1003) - -### Deprecated -- Support for PHP 7.2 will be removed in Emogrifier 7.0. - -### Removed -- Remove a redundant CSS data cache (#1018) -- Drop support for Symfony 5.1 and 5.2 (#972, #1104) -- Drop support for PHP 7.1 (#967) - -### Fixed -- Allow `@import` after ignored invalid `@charset` (@1081) -- Allow line feeds within `<html>` tag (#987) - -## 5.0.1 - -### Changed -- Switch the default branch from `master` to `main` (#951) - -### Fixed -- Ignore `http-equiv` `Content-Type` in `<body>` (#961) -- Allow "Content-Type" in content (#959) - -## 5.0.0 - -### Added -- Add an `.editorconfig` file (#940) -- Support PHP 8.0 (#926) -- Run the CI build once a week (#933) -- Move more development tools to PHIVE (#894, #907) - -### Changed -- Automatically add a backslash for global functions (#909) -- Update the development tools (#898, #895) -- Upgrade to PHPUnit 7.5 (#888) -- Enforce constant visibility (#892) -- Rename the PHPCS configuration file (#891, #896) -- Make use of PHP 7.1 language features (#883) - -### Deprecated -- Support for PHP 7.1 will be removed in Emogrifier 6.0. - -### Removed -- Drop support for Symfony 4.3 and 5.0 (#936) -- Stop checking `tests/` with Psalm (#885) -- Drop support for PHP 7.0 (#880) - -### Fixed -- Fix a nonsensical code example in the README (#920, #935) -- Remove `!important` from `style` attributes also when uppercase, mixed case or - having whitespace after `!` (#911) -- Copy rules using `:...of-type` without a type to the `<style>` element (#904) -- Support combinator followed by dynamic pseudo-class in minified CSS (#903) -- Preserve all uninlinable (or otherwise unprocessed) at-rules (#899) -- Allow Windows CLI to run development tools installed through PHIVE (#900) -- Switch to a maintained package for parallel PHP linting (#884) -- Add `.0` version suffixes to PHP version requirements (#881) - -## 4.0.0 - -### Added -- Extract and inject `@font-face` rules into head (#870) -- Test tag omission in conformant supplied HTML (#868) -- Check for missing return type hint annotations in the code sniffs (#860) -- Support `:only-of-type` (with a type) (#849, #856) -- Configuration setting methods now all return `$this` to allow chaining (#824, #854) -- Disable php-cs-fixer Yoda conditions (#791, #794) -- Check the code with psalm (#537, #779) -- Composer script to run tests with `--stop-on-failure` (#782) -- Test universal selector with combinators (#776) - -### Changed -- Normalize DOCTYPE declaration according to polyglot markup recommendation (#866) -- Upgrade to V2 of the PHP setup GitHub action (#861) -- Move the development tools to PHIVE (#850, #851) -- Switch the parallel linting to a maintained fork (#842) -- Move continuous integration from Travis CI to GitHub actions (#832, #834, #838, #839, #840, #841, #843, #846, #849) -- Clean up the folder structure and autoloading configuration (#529, #785) -- Use `self` as the return type for `fromHtml` (#784) -- Make use of PHP 7.0 language features (#777) - -### Deprecated -- Support for PHP 7.0 will be removed in Emogrifier 5.0. - -### Removed -- Drop support for Symfony versions that have reached their end of life (#847) -- Drop the `Emogrifier` class (#774) -- Drop support for PHP 5.6 (#773) - -### Fixed -- Allow `:last-of-type` etc. without type, without causing exception (#875) -- Make sure to use the Composer-installed development tools (#862, #865) -- Add missing `<head>` element when there's a `<header>` element (#844, #853) -- Fix mapping width/height when decimal is used (#845) -- Actually use the specified PHP version on GitHub actions (#836) -- Support `ci:php:lint` on Windows (#740, #780) - -## 3.1.0 - -### Added -- Add support for PHP 7.4 (#821, #829) - -### Changed -- Upgrade to Symfony 5.0 (#820) - -## 3.0.0 - -### Added -- Test and document excluding entire subtree with `addExcludedSelector()` (#347, #768) -- Test that rules with `:optional` or `:required` are copied to the `<style>` - element (#748, #765) -- Test that rules with `:only-of-type` are copied to the `<style>` element (#748, #760) -- Support `:last-of-type` (#748, #758) -- Support `:first-of-type` (#748, #757) -- Support `:empty` (#748, #756) -- Test that rules with `:any-link` are copied to the `<style>` element (#748, #755) -- Support and test `:only-child` (#747, #754) -- Support and test `:nth-last-of-type` (#747, #751) -- Support and test `:nth-last-child` (#747, #750) -- Support and test general sibling combinator (#723, #745) -- Test universal selector with combinators (#723, #743) -- Preserve `display: none` elements with `-emogrifier-keep` class (#252, #737) -- Preserve valid `@import` rules (#338, #334, #732, #735) -- Add `HtmlPruner::removeRedundantClassesAfterCssInlined` (#380, #724) -- Check on Travis that PHP-CS-Fixer will not change anything (#727) -- Support `:not(…)` as an entire selector (#469, #725) -- Add `HtmlPruner::removeRedundantClasses` (#380, #708) -- Support multiple attributes selectors (#385, #721) -- Support `> :first-child` and `> :last-child` in selectors (#384, #720) -- Add an `ArrayIntersector` class (#708, #710) -- Add `CssInliner::getMatchingUninlinableSelectors` (#380, #707) -- Add tests for `:nth-child` and `:nth-of-type` (#71, #698) - -### Changed -- Relax the dependency on `symfony/css-selector` (#762) -- Rename `HtmlPruner::removeInvisibleNodes` to - `HtmlPruner::removeElementsWithDisplayNone` (#717, #718) -- Mark the utility classes as internal (#715) -- Move utility classes to the `Pelago\Emogrifier\Utilities` namespace (#712) -- Make the `$css` parameter of the `inlineCss` method optional (#700) -- Update the development dependencies (#691) - -### Deprecated -- Support for PHP 5.6 will be removed in Emogrifier 4.0. -- Deprecate the `Emogrifier` class (#701) - -### Removed -- Drop `enableCssToHtmlMapping` and `disableInvisibleNodeRemoval` (#692) -- Drop support for PHP 5.5 (#690) - -### Fixed -- Fix PhpStorm code inspection warnings (#729, #770) -- Uppercase type combined with class or ID in selector (#590, #769) -- Dynamic pseudo-class combined with static one (rules copied to `<style>` - element, #746) -- Descendant attribute selectors (such as `html input[disabled]`) (#375, #709) -- Attribute selectors with hyphen in attribute name (#284, #540, #704) -- Attribute selectors with space, hyphen, colon, semicolon or (most) other - non-alphanumeric characters in attribute value (#284, #333, #550, #540, #704) -- Don’t create empty `style` attributes for unparsable declarations (#259, #702) -- Allow `:not(:behavioural-pseudo-class)` in selectors (#697, #703) - -## 2.2.0 - -### Added -- Add a `HtmlPruner` class (#679) -- Add `AbstractHtmlProcessor::fromDomDocument` (#676) -- Add `AbstractHtmlProcessor::fromHtml` (#675) - -### Changed -- Make the closures static (#674) -- Keep `<wbr>` elements by default with `CssInliner` (#665) -- Make the `CssInliner` inherit `AbstractHtmlProcessor` (#660) -- Separate `CssInliner::inlineCss` and the rendering (#654) - -### Removed -- Drop the removal of unprocessable tags from `CssInliner` (#685) -- Drop the removal of invisible nodes from `CssInliner` (#684) - -### Fixed -- Remove opening `<body>` tag from `body` content when element has attribute(s) (#677, #683) -- Keep development files out of the Composer packages (#678) -- Call all static methods statically in `CssConcatenator` (#670) -- Support all HTML5 self-closing tags, including `<embed>`, `<source>`, - `<track>` and `<wbr>` (#653) -- Remove all "unprocessable" (e.g. `<wbr>`) tags (#650) -- Correct translated xpath of `:nth-child` selector (#648) - -## 2.1.1 - -### Changed -- Add a test that a missing document type gets added (#641) - -### Fixed -- Keep the `style` element the `head` (#642) - -## 2.1.0 - -### Added -- PHP 7.3 support (#638) - - Allow PHP 7.3 in `composer.json` - - Test in Travis for PHP 7.3 -- Add a `renderBodyContent()` method (#633) -- Add a `getDomDocument()` method (#630) -- Add a Composer script for PHP CS Fixer (#607) -- Copy matching rules with dynamic pseudo-classes or pseudo-elements in - selectors to the style element (#280, #562, #567) -- Add a CssToAttributeConverter (#546) -- Expose the DOMDocument in AbstractHtmlProcessor (#520) -- Add an HtmlNormalizer class (#513, #516) -- Add a CssInliner class (#514, #522) -- Composer scripts for the various CI build steps -- Validate the composer.json on Travis (#476) - -### Changed -- Mark the work-in-progress classes as `@internal` (#640) -- Remove the unprocessable tags from the DOM, not from the raw HTML (#627) -- Reject empty HTML in `setHtml()` (#622) -- Stop passing the DOM document around (#618) -- Improve performance by using explicit namespaces for PHP functions (#573, #576) -- Add type hint checking to the code sniffs (#566) -- Check the code with PHPMD (#561) -- Add the cyclomatic complexity to the checked code sniffs (#558) -- Use the Symfony CSS selector component (#540) - -### Deprecated -- Support for PHP 5.5 will be removed in Emogrifier 3.0. -- Support for PHP 5.6 will be removed in Emogrifier 4.0. -- The removal of invisible nodes will be removed in Emogrifier 3.0. (#473) -- Converting CSS styles to (non-CSS) HTML attributes will be removed - in Emogrifier 3.0. Please use the new CssToAttributeConverter instead. (#474) -- Emogrifier 3.x.y will be the last release that supports usage without - Composer (i.e., you can still require the class file). - Starting with version 4.0, Emogrifier will only work with Composer. -- The Emogrifier class will be superseded by CssInliner class in - Emogrifier 3.0. For this, the Emogrifier class will be deprecated for - version 3.0 and removed for version 4.0. - -### Removed -- Drop the `@version` PHPDoc annotations (#637) -- Drop the destructors (#619) - -### Fixed -- Add required XML PHP extension to `composer.json` (#614) -- Add required DOM PHP extension to `composer.json` (#595) -- Escape hyphens in regular expressions (#588) -- Fix Travis for PHP 5.x (#589) -- Allow CSS between empty `@media` rule and another `@media` rule (#534) -- Allow additional whitespace in media-query-list of disallowed `@media` rules (#532) -- Allow multiple minified `@import` rules in the CSS without error (note: - `@import`s are currently ignored, #527) -- Style property ordering when multiple mixed individual and shorthand - properties apply (#511, #508) -- Calculation of selector precedence for selectors involving pseudo-classes - and/or attributes (#502) -- Allow `@charset` in the CSS without error (note: its value is currently - ignored, #507) -- Allow attribute selectors in descendants (#506, #381, #443) -- Allow adjacent sibling CSS selector combinator in minified CSS (#505) -- Allow CSS property values containing newlines (#504) - -## 2.0.0 - -### Added -- Support for CSS :not() selector (#431) -- Automatically remove !important annotations from final inline style declarations (#420) -- Automatically move `<style>` block from `<head>` to `<body>` (#396) -- PHP 7.2 support (#398) - - Allow PHP 7.2 in `composer.json`, cleaner PHP version constraint - - Test in Travis for PHP 7.2 -- Debug mode. Throw debug exceptions only if debug is active. (#392) - -### Changed -- Test with latest and oldest dependencies on Travis (#463) -- Always enable the debug mode in the tests (#448) -- Optimize the string operations (#430) - -### Deprecated -- Support for PHP 5.5 will be removed in Emogrifier 3.0. -- Support for PHP 5.6 will be removed in Emogrifier 4.0. - -### Removed -- Drop support for PHP 5.4 (#422) -- Drop support for HHVM (#386) - -### Fixed -- Handle invalid/unrecognized selectors in media query blocks (#442) -- Throw (the correct) exception for invalid excluded selectors (#437) -- emogrifyBody must not encode umlaut entities (#414) -- Fix mapped HTML attribute values (#405) -- Make sure the HTML always has a BODY element (#410) -- Make inline style priority higher than css block priority (#404) -- Fix media regex parsing (#402) -- Silence purposefully ignored PHP Warnings (#400) - -## 1.2.0 (2017-03-02) - -### Added -- Handling invalid xPath expression warnings (#361) - -### Deprecated -- Support for PHP 5.5 will be removed in Emogrifier 3.0. -- Support for PHP 5.4 will be removed in Emogrifier 2.0. - -### Fixed -- Allow colon (`:`) and semi-colon (`;`) when using the `*=` selector (#371) -- Ignore "auto" width and height (#365) - -## 1.1.0 (2016-09-18) - -### Added -- Add support for PHP 7.1 (#342) -- Support the attr|=value selector (#337) -- Support the attr*=value selector (#330) -- Support the attr$=value selector (#329) -- Support the attr^=value selector (#324) -- Support the attr~=value selector (#323) -- Add CSS to HTML attribute mapper (#288) - -### Changed -- Remove composer dependency from PHP mbstring extension (Actual code dependency were removed a lot of time ago) (#295) - -### Deprecated -- Support for PHP 5.5 will be removed in Emogrifier 3.0. -- Support for PHP 5.4 will be removed in Emogrifier 2.0. - -### Fixed -- Method emogrifyBodyContent() doesn't keeps utf8 umlauts (#349) -- Ignore value with words more than one in the attribute selector (#327) -- Ignore spaces around the > in the direct child selector (#322) -- Ignore empty media queries (#307) (#237) -- Ignore pseudo-class when combined with pseudo-element (#308) -- First-child and last-child selectors are broken (#293) -- Second !important rule needs to overwrite the first one (#292) - -## 1.0.0 (2015-10-15) - -### Added -- Add branch alias (#231) -- Remove media queries which do not impact the document (#217) -- Allow elements to be excluded from emogrification (#215) -- Handle !important (#214) -- emogrifyBodyContent() method (#206) -- Cache combinedStyles (#211) -- Allow user to define media types to keep (#200) -- Ignore invalid CSS selectors (#194) -- isRemoveDisplayNoneEnabled option (#162) -- Allow disabling of "inline style" and "style block" parsing (#156) -- Preserve @media if necessary (#62) -- Add extraction of style blocks within the HTML -- Add several new pseudo-selectors (first-child, last-child, nth-child, - and nth-of-type) - -### Changed -- Make HTML5 the default document type (#245) -- Make copyCssWithMediaToStyleNode private (#218) -- Stop encoding umlauts and dollar signs (#170) -- Convert the classes to namespaces (#41) - -### Deprecated -- Support for PHP 5.4 will be removed in Emogrifier 2.0. - -### Removed -- Drop support for PHP 5.3 (#114) -- Support for character sets other than UTF-8 was removed. - -### Fixed -- Fix failing tests on Windows due to line endings (#263) -- Parsing CSS declaration blocks (#261) -- Fix first-child and last-child selectors (#257) -- Fix parsing of CSS for data URIs (#243) -- Fix multi-line media queries (#241) -- Keep CSS media queries even if followed by CSS comments (#201) -- Fix CSS selectors with exact attribute only (#197) -- Properly handle UTF-8 characters and entities (#189) -- Add mbstring extension to composer.json (#93) -- Prevent incorrectly capitalized CSS selectors from being stripped (#85) -- Fix CSS selectors with exact attribute only (#197) -- Wrong selector extraction from minified CSS (#69) -- Restore libxml error handler state after clearing (#65) -- Ignore all warnings produced by DOMDocument::loadHTML() (#63) -- Style tags in HTML cause an Xpath invalid query error (#60) -- Fix PHP warnings with PHP 5.5 (#26) -- Make removal of invisible nodes operate in a case-insensitive manner -- Fix a bug that was overwriting existing inline styles from the original HTML diff --git a/lib/pelago/emogrifier/LICENSE b/lib/pelago/emogrifier/LICENSE deleted file mode 100644 index 577abe9a1..000000000 --- a/lib/pelago/emogrifier/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2008-2018 Pelago - -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/lib/pelago/emogrifier/README.md b/lib/pelago/emogrifier/README.md deleted file mode 100644 index f1b36ac39..000000000 --- a/lib/pelago/emogrifier/README.md +++ /dev/null @@ -1,427 +0,0 @@ -# Emogrifier - -[![Build Status](https://github.com/MyIntervals/emogrifier/workflows/CI/badge.svg?branch=main)](https://github.com/MyIntervals/emogrifier/actions/) -[![Latest Stable Version](https://poser.pugx.org/pelago/emogrifier/v/stable.svg)](https://packagist.org/packages/pelago/emogrifier) -[![Total Downloads](https://poser.pugx.org/pelago/emogrifier/downloads.svg)](https://packagist.org/packages/pelago/emogrifier) -[![Latest Unstable Version](https://poser.pugx.org/pelago/emogrifier/v/unstable.svg)](https://packagist.org/packages/pelago/emogrifier) -[![License](https://poser.pugx.org/pelago/emogrifier/license.svg)](https://packagist.org/packages/pelago/emogrifier) - -_n. e•mog•ri•fi•er [\ē-'mä-grƏ-,fī-Ər\] - a utility for changing completely the -nature or appearance of HTML email, esp. in a particularly fantastic or bizarre -manner_ - -Emogrifier converts CSS styles into inline style attributes in your HTML code. -This ensures proper display on email and mobile device readers that lack -stylesheet support. - -This utility was developed as part of [Intervals](http://www.myintervals.com/) -to deal with the problems posed by certain email clients (namely Outlook 2007 -and GoogleMail) when it comes to the way they handle styling contained in HTML -emails. As many web developers and designers already know, certain email -clients are notorious for their lack of CSS support. While attempts are being -made to develop common [email standards](http://www.email-standards.org/), -implementation is still a ways off. - -The primary problem with uncooperative email clients is that most tend to only -regard inline CSS, discarding all `<style>` elements and links to stylesheets -in `<link>` elements. Emogrifier solves this problem by converting CSS styles -into inline style attributes in your HTML code. - -- [How it works](#how-it-works) -- [Installation](#installation) -- [Usage](#usage) -- [Supported CSS selectors](#supported-css-selectors) -- [Caveats](#caveats) -- [Steps to release a new version](#steps-to-release-a-new-version) -- [Maintainers](#maintainers) - -## How it Works - -Emogrifier automagically transmogrifies your HTML by parsing your CSS and -inserting your CSS definitions into tags within your HTML based on your CSS -selectors. - -## Installation - -For installing emogrifier, either add `pelago/emogrifier` to the `require` -section in your project's `composer.json`, or you can use composer as below: - -```bash -composer require pelago/emogrifier -``` - -See https://getcomposer.org/ for more information and documentation. - -## Usage - -### Inlining Css - -The most basic way to use the `CssInliner` class is to create an instance with -the original HTML, inline the external CSS, and then get back the resulting -HTML: - -```php -use Pelago\Emogrifier\CssInliner; - -… - -$visualHtml = CssInliner::fromHtml($html)->inlineCss($css)->render(); -``` - -If there is no external CSS file and all CSS is located within `<style>` -elements in the HTML, you can omit the `$css` parameter: - -```php -$visualHtml = CssInliner::fromHtml($html)->inlineCss()->render(); -``` - -If you would like to get back only the content of the `<body>` element instead -of the complete HTML document, you can use the `renderBodyContent` method -instead: - -```php -$bodyContent = $visualHtml = CssInliner::fromHtml($html)->inlineCss() - ->renderBodyContent(); -``` - -If you would like to modify the inlining process with any of the available -[options](#options), you will need to call the corresponding methods -before inlining the CSS. The code then would look like this: - -```php -$visualHtml = CssInliner::fromHtml($html)->disableStyleBlocksParsing() - ->inlineCss($css)->render(); -``` - -There are also some other HTML-processing classes available -(all of which are subclasses of `AbstractHtmlProcessor`) which you can use -to further change the HTML after inlining the CSS. -(For more details on the classes, please have a look at the sections below.) -`CssInliner` and all HTML-processing classes can share the same `DOMDocument` -instance to work on: - -```php -use Pelago\Emogrifier\CssInliner; -use Pelago\Emogrifier\HtmlProcessor\CssToAttributeConverter; -use Pelago\Emogrifier\HtmlProcessor\HtmlPruner; - -… - -$cssInliner = CssInliner::fromHtml($html)->inlineCss($css); -$domDocument = $cssInliner->getDomDocument(); -HtmlPruner::fromDomDocument($domDocument)->removeElementsWithDisplayNone() - ->removeRedundantClassesAfterCssInlined($cssInliner); -$finalHtml = CssToAttributeConverter::fromDomDocument($domDocument) - ->convertCssToVisualAttributes()->render(); -``` - -### Normalizing and cleaning up HTML - -The `HtmlNormalizer` class normalizes the given HTML in the following ways: - -- add a document type (HTML5) if missing -- disentangle incorrectly nested tags -- add HEAD and BODY elements (if they are missing) -- reformat the HTML - -The class can be used like this: - -```php -use Pelago\Emogrifier\HtmlProcessor\HtmlNormalizer; - -… - -$cleanHtml = HtmlNormalizer::fromHtml($rawHtml)->render(); -``` - -### Converting CSS styles to visual HTML attributes - -The `CssToAttributeConverter` converts a few style attributes values to visual -HTML attributes. This allows to get at least a bit of visual styling for email -clients that do not support CSS well. For example, `style="width: 100px"` -will be converted to `width="100"`. - -The class can be used like this: - -```php -use Pelago\Emogrifier\HtmlProcessor\CssToAttributeConverter; - -… - -$visualHtml = CssToAttributeConverter::fromHtml($rawHtml) - ->convertCssToVisualAttributes()->render(); -``` - -You can also have the `CssToAttributeConverter` work on a `DOMDocument`: - -```php -$visualHtml = CssToAttributeConverter::fromDomDocument($domDocument) - ->convertCssToVisualAttributes()->render(); -``` - -### Removing redundant content and attributes from the HTML - -The `HtmlPruner` class can reduce the size of the HTML by removing elements with -a `display: none` style declaration, and/or removing classes from `class` -attributes that are not required. - -It can be used like this: - -```php -use Pelago\Emogrifier\HtmlProcessor\HtmlPruner; - -… - -$prunedHtml = HtmlPruner::fromHtml($html)->removeElementsWithDisplayNone() - ->removeRedundantClasses($classesToKeep)->render(); -``` - -The `removeRedundantClasses` method accepts a whitelist of names of classes that -should be retained. If this is a post-processing step after inlining CSS, you -can alternatively use `removeRedundantClassesAfterCssInlined`, passing it the -`CssInliner` instance that has inlined the CSS (and having the `HtmlPruner` work -on the `DOMDocument`). This will use information from the `CssInliner` to -determine which classes are still required (namely, those used in uninlinable -rules that have been copied to a `<style>` element): - -```php -$prunedHtml = HtmlPruner::fromDomDocument($cssInliner->getDomDocument()) - ->removeElementsWithDisplayNone() - ->removeRedundantClassesAfterCssInlined($cssInliner)->render(); -``` - -The `removeElementsWithDisplayNone` method will not remove any elements which -have the class `-emogrifier-keep`. So if, for example, there are elements which -by default have `display: none` but are revealed by an `@media` rule, or which -are intended as a preheader, you can add that class to those elements. The -paragraph in this HTML snippet will not be removed even though it has -`display: none` (which has presumably been applied by `CssInliner::inlineCss()` -from a CSS rule `.preheader { display: none; }`): - -```html -<p class="preheader -emogrifier-keep" style="display: none;"> - Hello World! -</p> -``` - -The `removeRedundantClassesAfterCssInlined` (or `removeRedundantClasses`) -method, if invoked after `removeElementsWithDisplayNone`, will remove the -`-emogrifier-keep` class. - -### Options - -There are several options that you can set on the `CssInliner` instance before -calling the `inlineCss` method: - -* `->disableStyleBlocksParsing()` - By default, `CssInliner` will grab - all `<style>` blocks in the HTML and will apply the CSS styles as inline - "style" attributes to the HTML. The `<style>` blocks will then be removed - from the HTML. If you want to disable this functionality so that `CssInliner` - leaves these `<style>` blocks in the HTML and does not parse them, you should - use this option. If you use this option, the contents of the `<style>` blocks - will _not_ be applied as inline styles and any CSS you want `CssInliner` to - use must be passed in as described in the [Usage section](#usage) above. -* `->disableInlineStyleAttributesParsing()` - By default, `CssInliner` - preserves all of the "style" attributes on tags in the HTML you pass to it. - However if you want to discard all existing inline styles in the HTML before - the CSS is applied, you should use this option. -* `->addAllowedMediaType(string $mediaName)` - By default, `CssInliner` - will keep only media types `all`, `screen` and `print`. If you want to keep - some others, you can use this method to define them. -* `->removeAllowedMediaType(string $mediaName)` - You can use this - method to remove media types that Emogrifier keeps. -* `->addExcludedSelector(string $selector)` - Keeps elements from - being affected by CSS inlining. Note that only elements matching the supplied - selector(s) will be excluded from CSS inlining, not necessarily their - descendants. If you wish to exclude an entire subtree, you should provide - selector(s) which will match all elements in the subtree, for example by using - the universal selector: - ```php - $cssInliner->addExcludedSelector('.message-preview'); - $cssInliner->addExcludedSelector('.message-preview *'); - ``` - -### Migrating from the dropped `Emogrifier` class to the `CssInliner` class - -#### Minimal example - -Old code using `Emogrifier`: - -```php -$emogrifier = new Emogrifier($html); -$html = $emogrifier->emogrify(); -``` - -New code using `CssInliner`: - -```php -$html = CssInliner::fromHtml($html)->inlineCss()->render(); -``` - -NB: In this example, the old code removes elements with `display: none;` -while the new code does not, as the default behaviors of the old and -the new class differ in this regard. - -#### More complex example - -Old code using `Emogrifier`: - -```php -$emogrifier = new Emogrifier($html, $css); -$emogrifier->enableCssToHtmlMapping(); - -$html = $emogrifier->emogrify(); -``` - -New code using `CssInliner` and family: - -```php -$domDocument = CssInliner::fromHtml($html)->inlineCss($css)->getDomDocument(); - -HtmlPruner::fromDomDocument($domDocument)->removeElementsWithDisplayNone(); -$html = CssToAttributeConverter::fromDomDocument($domDocument) - ->convertCssToVisualAttributes()->render(); -``` - -## Supported CSS selectors - -Emogrifier currently supports the following -[CSS selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors): - - * [type](https://developer.mozilla.org/en-US/docs/Web/CSS/Type_selectors) - * [class](https://developer.mozilla.org/en-US/docs/Web/CSS/Class_selectors) - * [ID](https://developer.mozilla.org/en-US/docs/Web/CSS/ID_selectors) - * [universal](https://developer.mozilla.org/en-US/docs/Web/CSS/Universal_selectors) - * [attribute](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors): - * presence - * exact value match - * value with `~` (one word within a whitespace-separated list of words) - * value with `|` (either exact value match or prefix followed by a hyphen) - * value with `^` (prefix match) - * value with `$` (suffix match) - * value with `*` (substring match) - * [adjacent](https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_selectors) - * [general sibling](https://developer.mozilla.org/en-US/docs/Web/CSS/General_sibling_combinator) - * [child](https://developer.mozilla.org/en-US/docs/Web/CSS/Child_selectors) - * [descendant](https://developer.mozilla.org/en-US/docs/Web/CSS/Descendant_selectors) - * [pseudo-classes](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes): - * [empty](https://developer.mozilla.org/en-US/docs/Web/CSS/:empty) - * [first-child](https://developer.mozilla.org/en-US/docs/Web/CSS/:first-child) - * [first-of-type](https://developer.mozilla.org/en-US/docs/Web/CSS/:first-of-type) - (with a type, e.g. `p:first-of-type` but not `*:first-of-type`) - * [last-child](https://developer.mozilla.org/en-US/docs/Web/CSS/:last-child) - * [last-of-type](https://developer.mozilla.org/en-US/docs/Web/CSS/:last-of-type) - (with a type) - * [not()](https://developer.mozilla.org/en-US/docs/Web/CSS/:not) - * [nth-child()](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-child) - * [nth-last-child()](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-last-child) - * [nth-last-of-type()](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-last-of-type) - (with a type) - * [nth-of-type()](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-of-type) - (with a type) - * [only-child](https://developer.mozilla.org/en-US/docs/Web/CSS/:only-child) - * [only-of-type](https://developer.mozilla.org/en-US/docs/Web/CSS/:only-of-type) - (with a type) - -The following selectors are not implemented yet: - - * [case-insensitive attribute value](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors#case-insensitive) - * static [pseudo-classes](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes) - not listed above as supported – rules involving them will nonetheless be - preserved and copied to a `<style>` element in the HTML – including (but not - necessarily limited to) the following: - * [any-link](https://developer.mozilla.org/en-US/docs/Web/CSS/:any-link) - * [first-of-type](https://developer.mozilla.org/en-US/docs/Web/CSS/:first-of-type) - without a type - * [last-of-type](https://developer.mozilla.org/en-US/docs/Web/CSS/:last-of-type) - without a type - * [nth-last-of-type()](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-last-of-type) - without a type - * [nth-of-type()](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-of-type) - without a type - * [only-of-type()](https://developer.mozilla.org/en-US/docs/Web/CSS/:only-of-type) - without a type - * [optional](https://developer.mozilla.org/en-US/docs/Web/CSS/:optional) - * [required](https://developer.mozilla.org/en-US/docs/Web/CSS/:required) - -Rules involving the following selectors cannot be applied as inline styles. -They will, however, be preserved and copied to a `<style>` element in the HTML: - - * dynamic [pseudo-classes](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes) - (such as `:hover`) - * [pseudo-elements](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements) - (such as `::after`) - -## Caveats - -* Emogrifier requires the HTML and the CSS to be UTF-8. Encodings like - ISO8859-1 or ISO8859-15 are not supported. -* Emogrifier preserves all valuable `@media` rules. Media queries can be very - useful in responsive email design. See - [media query support](https://litmus.com/help/email-clients/media-query-support/). - However, in order for them to be effective, you may need to add `!important` - to some of the declarations within them so that they will override CSS styles - that have been inlined. For example, with the following CSS, the `font-size` - declaration in the `@media` rule would not override the font size for `p` - elements from the preceding rule after that has been inlined as - `<p style="font-size: 16px;">` in the HTML, without the `!important` directive - (even though `!important` would not be necessary if the CSS were not inlined): - ```css - p { - font-size: 16px; - } - @media (max-width: 640px) { - p { - font-size: 14px !important; - } - } - ``` -* Emogrifier cannot inline CSS rules involving selectors with pseudo-elements - (such as `::after`) or dynamic pseudo-classes (such as `:hover`) – it is - impossible. However, such rules will be preserved and copied to a `<style>` - element, as for `@media` rules. The same caveat about the possible need for - the `!important` directive also applies with pseudo-classes. -* Emogrifier will grab existing inline style attributes _and_ will - grab `<style>` blocks from your HTML, but it will not grab CSS files - referenced in `<link>` elements or `@import` rules (though it will leave them - intact for email clients that support them). -* Even with styles inline, certain CSS properties are ignored by certain email - clients. For more information, refer to these resources: - * [http://www.email-standards.org/](http://www.email-standards.org/) - * [https://www.campaignmonitor.com/css/](https://www.campaignmonitor.com/css/) - * [http://templates.mailchimp.com/resources/email-client-css-support/](http://templates.mailchimp.com/resources/email-client-css-support/) -* All CSS attributes that apply to an element will be applied, even if they are - redundant. For example, if you define a font attribute _and_ a font-size - attribute, both attributes will be applied to that element (in other words, - the more specific attribute will not be combined into the more general - attribute). -* There's a good chance you might encounter problems if your HTML is not - well-formed and valid (DOMDocument might complain). If you get problems like - this, consider running your HTML through - [Tidy](http://php.net/manual/en/book.tidy.php) before you pass it to - Emogrifier. -* Emogrifier automatically converts the provided (X)HTML into HTML5, i.e., - self-closing tags will lose their slash. To keep your HTML valid, it is - recommended to use HTML5 instead of one of the XHTML variants. - -## Steps to release a new version - -1. In the [composer.json](composer.json), update the `branch-alias` entry to - point to the release _after_ the upcoming release. -1. In the [CHANGELOG.md](CHANGELOG.md), create a new section with subheadings - for changes _after_ the upcoming release, set the version number for the - upcoming release, and remove any empty sections. -1. Create a pull request "Prepare release of version x.y.z" with those - changes. -1. Have the pull request reviewed and merged. -1. Tag the new release. -1. In the [Releases tab](https://github.com/MyIntervals/emogrifier/releases), - create a new release and copy the change log entries to the new release. -1. Post about the new release on social media. - -## Maintainers - -* [Oliver Klee](https://github.com/oliverklee) -* [Zoli Szabó](https://github.com/zoliszabo) -* [Jake Hotson](https://github.com/JakeQZ) -* [John Reeve](https://github.com/jjriv) diff --git a/lib/pelago/emogrifier/composer.json b/lib/pelago/emogrifier/composer.json deleted file mode 100644 index a7e9a4e5e..000000000 --- a/lib/pelago/emogrifier/composer.json +++ /dev/null @@ -1,125 +0,0 @@ -{ - "name": "pelago/emogrifier", - "description": "Converts CSS styles into inline style attributes in your HTML code", - "keywords": [ - "email", - "css", - "pre-processing" - ], - "homepage": "https://www.myintervals.com/emogrifier.php", - "license": "MIT", - "authors": [ - { - "name": "Oliver Klee", - "email": "github@oliverklee.de" - }, - { - "name": "Zoli Szabó", - "email": "zoli.szabo+github@gmail.com" - }, - { - "name": "John Reeve", - "email": "jreeve@pelagodesign.com" - }, - { - "name": "Jake Hotson", - "email": "jake@qzdesign.co.uk" - }, - { - "name": "Cameron Brooks" - }, - { - "name": "Jaime Prado" - } - ], - "require": { - "php": "~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0", - "ext-dom": "*", - "ext-libxml": "*", - "sabberworm/php-css-parser": "^8.3.1", - "symfony/css-selector": "^3.4.32 || ^4.4 || ^5.3 || ^6.0" - }, - "require-dev": { - "php-parallel-lint/php-parallel-lint": "^1.3.0", - "phpunit/phpunit": "^8.5.16", - "rawr/cross-data-providers": "^2.3.0" - }, - "config": { - "preferred-install": { - "*": "dist" - }, - "sort-packages": true - }, - "extra": { - "branch-alias": { - "dev-main": "7.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Pelago\\Emogrifier\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "Pelago\\Emogrifier\\Tests\\": "tests/" - } - }, - "prefer-stable": true, - "scripts": { - "ci": [ - "@ci:static", - "@ci:dynamic" - ], - "ci:composer:normalize": "@php \"./.phive/composer-normalize\" --dry-run", - "ci:dynamic": [ - "@ci:tests" - ], - "ci:php:fixer": "@php \"./.phive/php-cs-fixer\" --config=config/php-cs-fixer.php fix --dry-run -v --show-progress=dots config/ src/ tests/", - "ci:php:lint": "\"./vendor/bin/parallel-lint\" config src tests", - "ci:php:md": "@php \"./.phive/phpmd\" src text config/phpmd.xml", - "ci:php:psalm": "@php \"./.phive/psalm\" --show-info=false", - "ci:php:sniff": "@php \"./.phive/phpcs\" config src tests", - "ci:static": [ - "@ci:composer:normalize", - "@ci:php:lint", - "@ci:php:sniff", - "@ci:php:fixer", - "@ci:php:md", - "@ci:php:psalm" - ], - "ci:tests": [ - "@ci:tests:unit" - ], - "ci:tests:sof": "@php \"./vendor/bin/phpunit\" --stop-on-failure", - "ci:tests:unit": "@php \"./vendor/bin/phpunit\"", - "composer:normalize": "@php \"./.phive/composer-normalize\"", - "php:fix": "@php \"./.phive/php-cs-fixer\" --config=config/php-cs-fixer.php fix config/ src/ tests/", - "php:version": "@php -v | grep -Po 'PHP\\s++\\K(?:\\d++\\.)*+\\d++(?:-\\w++)?+'", - "psalm:baseline": "@php \"./.phive/psalm\" --set-baseline=psalm.baseline.xml", - "psalm:cc": "@php \"./.phive/psalm\" --clear-cache" - }, - "scripts-descriptions": { - "ci": "Runs all dynamic and static code checks.", - "ci:composer:normalize": "Checks the formatting and structure of the composer.json.", - "ci:dynamic": "Runs all dynamic tests (i.e., currently, the unit tests).", - "ci:php:fixer": "Checks the code style with PHP CS Fixer.", - "ci:php:lint": "Lints the PHP files for syntax errors.", - "ci:php:md": "Checks the code complexity with PHPMD.", - "ci:php:psalm": "Checks the types with Psalm.", - "ci:php:sniff": "Checks the code style with PHP_CodeSniffer.", - "ci:static": "Runs all static code analysis checks for the code and the composer.json.", - "ci:tests": "Runs all dynamic tests (i.e., currently, the unit tests).", - "ci:tests:sof": "Runs the unit tests and stops at the first failure.", - "ci:tests:unit": "Runs all unit tests.", - "composer:normalize": "Reformats and sorts the composer.json file.", - "php:fix": "Reformats the code with php-cs-fixer.", - "php:version": "Outputs the installed PHP version.", - "psalm:baseline": "Updates the Psalm baseline file to match the code.", - "psalm:cc": "Clears the Psalm cache." - }, - "support": { - "issues": "https://github.com/MyIntervals/emogrifier/issues", - "source": "https://github.com/MyIntervals/emogrifier" - } -} diff --git a/lib/pelago/emogrifier/phpunit.xml b/lib/pelago/emogrifier/phpunit.xml deleted file mode 100644 index 1f869bac1..000000000 --- a/lib/pelago/emogrifier/phpunit.xml +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/8.5/phpunit.xsd" - bootstrap="vendor/autoload.php" - colors="true" - executionOrder="depends,defects" - forceCoversAnnotation="true" - beStrictAboutCoversAnnotation="true" - beStrictAboutOutputDuringTests="true" - beStrictAboutTodoAnnotatedTests="true" - verbose="true"> - <testsuites> - <testsuite name="default"> - <directory>tests</directory> - </testsuite> - </testsuites> - - <filter> - <whitelist processUncoveredFilesFromWhitelist="true"> - <directory suffix=".php">src</directory> - </whitelist> - </filter> -</phpunit> diff --git a/lib/pelago/emogrifier/src/Caching/SimpleStringCache.php b/lib/pelago/emogrifier/src/Caching/SimpleStringCache.php deleted file mode 100644 index aa7c462fa..000000000 --- a/lib/pelago/emogrifier/src/Caching/SimpleStringCache.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Pelago\Emogrifier\Caching; - -/** - * This cache caches string values with string keys. It is not PSR-6-compliant. - * - * Usage: - * - * ```php - * $cache = new SimpleStringCache(); - * $cache->set($key, $value); - * … - * if ($cache->has($key) { - * $cachedValue = $cache->get($value); - * } - * ``` - * - * @internal - */ -class SimpleStringCache -{ - /** - * @var array<string, string> - */ - private $values = []; - - /** - * Checks whether there is an entry stored for the given key. - * - * @param string $key the key to check; must not be empty - * - * @throws \InvalidArgumentException - */ - public function has(string $key): bool - { - $this->assertNotEmptyKey($key); - - return isset($this->values[$key]); - } - - /** - * Returns the entry stored for the given key, and throws an exception if the value does not exist - * (which helps keep the return type simple). - * - * @param string $key the key to of the item to retrieve; must not be empty - * - * @return string the retrieved value; may be empty - * - * @throws \BadMethodCallException - */ - public function get(string $key): string - { - if (!$this->has($key)) { - throw new \BadMethodCallException('You can only call `get` with a key for an existing value.', 1625996246); - } - - return $this->values[$key]; - } - - /** - * Sets or overwrites an entry. - * - * @param string $key the key to of the item to set; must not be empty - * @param string $value the value to set; can be empty - * - * @throws \BadMethodCallException - */ - public function set(string $key, string $value): void - { - $this->assertNotEmptyKey($key); - - $this->values[$key] = $value; - } - - /** - * @throws \InvalidArgumentException - */ - private function assertNotEmptyKey(string $key): void - { - if ($key === '') { - throw new \InvalidArgumentException('Please provide a non-empty key.', 1625995840); - } - } -} diff --git a/lib/pelago/emogrifier/src/Css/CssDocument.php b/lib/pelago/emogrifier/src/Css/CssDocument.php deleted file mode 100644 index 65f1b376a..000000000 --- a/lib/pelago/emogrifier/src/Css/CssDocument.php +++ /dev/null @@ -1,187 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Pelago\Emogrifier\Css; - -use Sabberworm\CSS\CSSList\AtRuleBlockList as CssAtRuleBlockList; -use Sabberworm\CSS\CSSList\Document as SabberwormCssDocument; -use Sabberworm\CSS\Parser as CssParser; -use Sabberworm\CSS\Property\AtRule as CssAtRule; -use Sabberworm\CSS\Property\Charset as CssCharset; -use Sabberworm\CSS\Property\Import as CssImport; -use Sabberworm\CSS\Renderable as CssRenderable; -use Sabberworm\CSS\RuleSet\DeclarationBlock as CssDeclarationBlock; -use Sabberworm\CSS\RuleSet\RuleSet as CssRuleSet; - -/** - * Parses and stores a CSS document from a string of CSS, and provides methods to obtain the CSS in parts or as data - * structures. - * - * @internal - */ -class CssDocument -{ - /** - * @var SabberwormCssDocument - */ - private $sabberwormCssDocument; - - /** - * `@import` rules must precede all other types of rules, except `@charset` rules. This property is used while - * rendering at-rules to enforce that. - * - * @var bool - */ - private $isImportRuleAllowed = true; - - /** - * @param string $css - */ - public function __construct(string $css) - { - $cssParser = new CssParser($css); - /** @var SabberwormCssDocument $sabberwormCssDocument */ - $sabberwormCssDocument = $cssParser->parse(); - $this->sabberwormCssDocument = $sabberwormCssDocument; - } - - /** - * Collates the media query, selectors and declarations for individual rules from the parsed CSS, in order. - * - * @param array<array-key, string> $allowedMediaTypes - * - * @return array<int, StyleRule> - */ - public function getStyleRulesData(array $allowedMediaTypes): array - { - $ruleMatches = []; - /** @var CssRenderable $rule */ - foreach ($this->sabberwormCssDocument->getContents() as $rule) { - if ($rule instanceof CssAtRuleBlockList) { - $containingAtRule = $this->getFilteredAtIdentifierAndRule($rule, $allowedMediaTypes); - if (\is_string($containingAtRule)) { - /** @var CssRenderable $nestedRule */ - foreach ($rule->getContents() as $nestedRule) { - if ($nestedRule instanceof CssDeclarationBlock) { - $ruleMatches[] = new StyleRule($nestedRule, $containingAtRule); - } - } - } - } elseif ($rule instanceof CssDeclarationBlock) { - $ruleMatches[] = new StyleRule($rule); - } - } - - return $ruleMatches; - } - - /** - * Renders at-rules from the parsed CSS that are valid and not conditional group rules (i.e. not rules such as - * `@media` which contain style rules whose data is returned by {@see getStyleRulesData}). Also does not render - * `@charset` rules; these are discarded (only UTF-8 is supported). - * - * @return string - */ - public function renderNonConditionalAtRules(): string - { - $this->isImportRuleAllowed = true; - /** @var array<int, CssRenderable> $cssContents */ - $cssContents = $this->sabberwormCssDocument->getContents(); - $atRules = \array_filter($cssContents, [$this, 'isValidAtRuleToRender']); - - if ($atRules === []) { - return ''; - } - - $atRulesDocument = new SabberwormCssDocument(); - $atRulesDocument->setContents($atRules); - - /** @var string $renderedRules */ - $renderedRules = $atRulesDocument->render(); - return $renderedRules; - } - - /** - * @param CssAtRuleBlockList $rule - * @param array<array-key, string> $allowedMediaTypes - * - * @return ?string - * If the nested at-rule is supported, it's opening declaration (e.g. "@media (max-width: 768px)") is - * returned; otherwise the return value is null. - */ - private function getFilteredAtIdentifierAndRule(CssAtRuleBlockList $rule, array $allowedMediaTypes): ?string - { - $result = null; - - if ($rule->atRuleName() === 'media') { - /** @var string $mediaQueryList */ - $mediaQueryList = $rule->atRuleArgs(); - [$mediaType] = \explode('(', $mediaQueryList, 2); - if (\trim($mediaType) !== '') { - $escapedAllowedMediaTypes = \array_map( - static function (string $allowedMediaType): string { - return \preg_quote($allowedMediaType, '/'); - }, - $allowedMediaTypes - ); - $mediaTypesMatcher = \implode('|', $escapedAllowedMediaTypes); - $isAllowed = \preg_match('/^\\s*+(?:only\\s++)?+(?:' . $mediaTypesMatcher . ')/i', $mediaType) > 0; - } else { - $isAllowed = true; - } - - if ($isAllowed) { - $result = '@media ' . $mediaQueryList; - } - } - - return $result; - } - - /** - * Tests if a CSS rule is an at-rule that should be passed though and copied to a `<style>` element unmodified: - * - `@charset` rules are discarded - only UTF-8 is supported - `false` is returned; - * - `@import` rules are passed through only if they satisfy the specification ("user agents must ignore any - * '@import' rule that occurs inside a block or after any non-ignored statement other than an '@charset' or an - * '@import' rule"); - * - `@media` rules are processed separately to see if their nested rules apply - `false` is returned; - * - `@font-face` rules are checked for validity - they must contain both a `src` and `font-family` property; - * - other at-rules are assumed to be valid and treated as a black box - `true` is returned. - * - * @param CssRenderable $rule - * - * @return bool - */ - private function isValidAtRuleToRender(CssRenderable $rule): bool - { - if ($rule instanceof CssCharset) { - return false; - } - - if ($rule instanceof CssImport) { - return $this->isImportRuleAllowed; - } - - $this->isImportRuleAllowed = false; - - if (!$rule instanceof CssAtRule) { - return false; - } - - switch ($rule->atRuleName()) { - case 'media': - $result = false; - break; - case 'font-face': - $result = $rule instanceof CssRuleSet - && $rule->getRules('font-family') !== [] - && $rule->getRules('src') !== []; - break; - default: - $result = true; - } - - return $result; - } -} diff --git a/lib/pelago/emogrifier/src/Css/StyleRule.php b/lib/pelago/emogrifier/src/Css/StyleRule.php deleted file mode 100644 index f2a20f86e..000000000 --- a/lib/pelago/emogrifier/src/Css/StyleRule.php +++ /dev/null @@ -1,83 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Pelago\Emogrifier\Css; - -use Sabberworm\CSS\Property\Selector; -use Sabberworm\CSS\RuleSet\DeclarationBlock; - -/** - * This class represents a CSS style rule, including selectors, a declaration block, and an optional containing at-rule. - * - * @internal - */ -class StyleRule -{ - /** - * @var DeclarationBlock - */ - private $declarationBlock; - - /** - * @var string - */ - private $containingAtRule; - - /** - * @param DeclarationBlock $declarationBlock - * @param string $containingAtRule e.g. `@media screen and (max-width: 480px)` - */ - public function __construct(DeclarationBlock $declarationBlock, string $containingAtRule = '') - { - $this->declarationBlock = $declarationBlock; - $this->containingAtRule = \trim($containingAtRule); - } - - /** - * @return array<int, string> the selectors, e.g. `["h1", "p"]` - */ - public function getSelectors(): array - { - /** @var array<int, Selector> $selectors */ - $selectors = $this->declarationBlock->getSelectors(); - return \array_map( - static function (Selector $selector): string { - return (string)$selector; - }, - $selectors - ); - } - - /** - * @return string the CSS declarations, separated and followed by a semicolon, e.g., `color: red; height: 4px;` - */ - public function getDeclarationAsText(): string - { - return \implode(' ', $this->declarationBlock->getRules()); - } - - /** - * Checks whether the declaration block has at least one declaration. - */ - public function hasAtLeastOneDeclaration(): bool - { - return $this->declarationBlock->getRules() !== []; - } - - /** - * @returns string e.g. `@media screen and (max-width: 480px)`, or an empty string - */ - public function getContainingAtRule(): string - { - return $this->containingAtRule; - } - - /** - * Checks whether the containing at-rule is non-empty and has any non-whitespace characters. - */ - public function hasContainingAtRule(): bool - { - return $this->getContainingAtRule() !== ''; - } -} diff --git a/lib/pelago/emogrifier/src/CssInliner.php b/lib/pelago/emogrifier/src/CssInliner.php deleted file mode 100644 index 99bf0677d..000000000 --- a/lib/pelago/emogrifier/src/CssInliner.php +++ /dev/null @@ -1,1196 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Pelago\Emogrifier; - -use Pelago\Emogrifier\Css\CssDocument; -use Pelago\Emogrifier\HtmlProcessor\AbstractHtmlProcessor; -use Pelago\Emogrifier\Utilities\CssConcatenator; -use Symfony\Component\CssSelector\CssSelectorConverter; -use Symfony\Component\CssSelector\Exception\ParseException; - -/** - * This class provides functions for converting CSS styles into inline style attributes in your HTML code. - */ -class CssInliner extends AbstractHtmlProcessor -{ - /** - * @var int - */ - private const CACHE_KEY_SELECTOR = 0; - - /** - * @var int - */ - private const CACHE_KEY_CSS_DECLARATIONS_BLOCK = 1; - - /** - * @var int - */ - private const CACHE_KEY_COMBINED_STYLES = 2; - - /** - * Regular expression component matching a static pseudo class in a selector, without the preceding ":", - * for which the applicable elements can be determined (by converting the selector to an XPath expression). - * (Contains alternation without a group and is intended to be placed within a capturing, non-capturing or lookahead - * group, as appropriate for the usage context.) - * - * @var string - */ - private const PSEUDO_CLASS_MATCHER - = 'empty|(?:first|last|nth(?:-last)?+|only)-(?:child|of-type)|not\\([[:ascii:]]*\\)'; - - /** - * This regular expression componenet matches an `...of-type` pseudo class name, without the preceding ":". These - * pseudo-classes can currently online be inlined if they have an associated type in the selector expression. - * - * @var string - */ - private const OF_TYPE_PSEUDO_CLASS_MATCHER = '(?:first|last|nth(?:-last)?+|only)-of-type'; - - /** - * regular expression component to match a selector combinator - * - * @var string - */ - private const COMBINATOR_MATCHER = '(?:\\s++|\\s*+[>+~]\\s*+)(?=[[:alpha:]_\\-.#*:\\[])'; - - /** - * @var array<string, bool> - */ - private $excludedSelectors = []; - - /** - * @var array<string, bool> - */ - private $allowedMediaTypes = ['all' => true, 'screen' => true, 'print' => true]; - - /** - * @var array{ - * 0: array<string, int>, - * 1: array<string, array<string, string>>, - * 2: array<string, string> - * } - */ - private $caches = [ - self::CACHE_KEY_SELECTOR => [], - self::CACHE_KEY_CSS_DECLARATIONS_BLOCK => [], - self::CACHE_KEY_COMBINED_STYLES => [], - ]; - - /** - * @var ?CssSelectorConverter - */ - private $cssSelectorConverter = null; - - /** - * the visited nodes with the XPath paths as array keys - * - * @var array<string, \DOMElement> - */ - private $visitedNodes = []; - - /** - * the styles to apply to the nodes with the XPath paths as array keys for the outer array - * and the attribute names/values as key/value pairs for the inner array - * - * @var array<string, array<string, string>> - */ - private $styleAttributesForNodes = []; - - /** - * Determines whether the "style" attributes of tags in the the HTML passed to this class should be preserved. - * If set to false, the value of the style attributes will be discarded. - * - * @var bool - */ - private $isInlineStyleAttributesParsingEnabled = true; - - /** - * Determines whether the `<style>` blocks in the HTML passed to this class should be parsed. - * - * If set to true, the `<style>` blocks will be removed from the HTML and their contents will be applied to the HTML - * via inline styles. - * - * If set to false, the `<style>` blocks will be left as they are in the HTML. - * - * @var bool - */ - private $isStyleBlocksParsingEnabled = true; - - /** - * For calculating selector precedence order. - * Keys are a regular expression part to match before a CSS name. - * Values are a multiplier factor per match to weight specificity. - * - * @var array<string, int> - */ - private $selectorPrecedenceMatchers = [ - // IDs: worth 10000 - '\\#' => 10000, - // classes, attributes, pseudo-classes (not pseudo-elements) except `:not`: worth 100 - '(?:\\.|\\[|(?<!:):(?!not\\())' => 100, - // elements (not attribute values or `:not`), pseudo-elements: worth 1 - '(?:(?<![="\':\\w\\-])|::)' => 1, - ]; - - /** - * array of data describing CSS rules which apply to the document but cannot be inlined, in the format returned by - * {@see collateCssRules} - * - * @var array<array-key, array{ - * media: string, - * selector: string, - * hasUnmatchablePseudo: bool, - * declarationsBlock: string, - * line: int - * }>|null - */ - private $matchingUninlinableCssRules = null; - - /** - * Emogrifier will throw Exceptions when it encounters an error instead of silently ignoring them. - * - * @var bool - */ - private $debug = false; - - /** - * Inlines the given CSS into the existing HTML. - * - * @param string $css the CSS to inline, must be UTF-8-encoded - * - * @return self fluent interface - * - * @throws ParseException in debug mode, if an invalid selector is encountered - * @throws \RuntimeException in debug mode, if an internal PCRE error occurs - */ - public function inlineCss(string $css = ''): self - { - $this->clearAllCaches(); - $this->purgeVisitedNodes(); - - $this->normalizeStyleAttributesOfAllNodes(); - - $combinedCss = $css; - // grab any existing style blocks from the HTML and append them to the existing CSS - // (these blocks should be appended so as to have precedence over conflicting styles in the existing CSS) - if ($this->isStyleBlocksParsingEnabled) { - $combinedCss .= $this->getCssFromAllStyleNodes(); - } - $parsedCss = new CssDocument($combinedCss); - - $excludedNodes = $this->getNodesToExclude(); - $cssRules = $this->collateCssRules($parsedCss); - $cssSelectorConverter = $this->getCssSelectorConverter(); - foreach ($cssRules['inlinable'] as $cssRule) { - try { - $nodesMatchingCssSelectors = $this->getXPath() - ->query($cssSelectorConverter->toXPath($cssRule['selector'])); - - /** @var \DOMElement $node */ - foreach ($nodesMatchingCssSelectors as $node) { - if (\in_array($node, $excludedNodes, true)) { - continue; - } - $this->copyInlinableCssToStyleAttribute($node, $cssRule); - } - } catch (ParseException $e) { - if ($this->debug) { - throw $e; - } - } - } - - if ($this->isInlineStyleAttributesParsingEnabled) { - $this->fillStyleAttributesWithMergedStyles(); - } - - $this->removeImportantAnnotationFromAllInlineStyles(); - - $this->determineMatchingUninlinableCssRules($cssRules['uninlinable']); - $this->copyUninlinableCssToStyleNode($parsedCss); - - return $this; - } - - /** - * Disables the parsing of inline styles. - * - * @return self fluent interface - */ - public function disableInlineStyleAttributesParsing(): self - { - $this->isInlineStyleAttributesParsingEnabled = false; - - return $this; - } - - /** - * Disables the parsing of `<style>` blocks. - * - * @return self fluent interface - */ - public function disableStyleBlocksParsing(): self - { - $this->isStyleBlocksParsingEnabled = false; - - return $this; - } - - /** - * Marks a media query type to keep. - * - * @param string $mediaName the media type name, e.g., "braille" - * - * @return self fluent interface - */ - public function addAllowedMediaType(string $mediaName): self - { - $this->allowedMediaTypes[$mediaName] = true; - - return $this; - } - - /** - * Drops a media query type from the allowed list. - * - * @param string $mediaName the tag name, e.g., "braille" - * - * @return self fluent interface - */ - public function removeAllowedMediaType(string $mediaName): self - { - if (isset($this->allowedMediaTypes[$mediaName])) { - unset($this->allowedMediaTypes[$mediaName]); - } - - return $this; - } - - /** - * Adds a selector to exclude nodes from emogrification. - * - * Any nodes that match the selector will not have their style altered. - * - * @param string $selector the selector to exclude, e.g., ".editor" - * - * @return self fluent interface - */ - public function addExcludedSelector(string $selector): self - { - $this->excludedSelectors[$selector] = true; - - return $this; - } - - /** - * No longer excludes the nodes matching this selector from emogrification. - * - * @param string $selector the selector to no longer exclude, e.g., ".editor" - * - * @return self fluent interface - */ - public function removeExcludedSelector(string $selector): self - { - if (isset($this->excludedSelectors[$selector])) { - unset($this->excludedSelectors[$selector]); - } - - return $this; - } - - /** - * Sets the debug mode. - * - * @param bool $debug set to true to enable debug mode - * - * @return self fluent interface - */ - public function setDebug(bool $debug): self - { - $this->debug = $debug; - - return $this; - } - - /** - * Gets the array of selectors present in the CSS provided to `inlineCss()` for which the declarations could not be - * applied as inline styles, but which may affect elements in the HTML. The relevant CSS will have been placed in a - * `<style>` element. The selectors may include those used within `@media` rules or those involving dynamic - * pseudo-classes (such as `:hover`) or pseudo-elements (such as `::after`). - * - * @return array<array-key, string> - * - * @throws \BadMethodCallException if `inlineCss` has not been called first - */ - public function getMatchingUninlinableSelectors(): array - { - return \array_column($this->getMatchingUninlinableCssRules(), 'selector'); - } - - /** - * @return array<array-key, array{ - * media: string, - * selector: string, - * hasUnmatchablePseudo: bool, - * declarationsBlock: string, - * line: int - * }> - * - * @throws \BadMethodCallException if `inlineCss` has not been called first - */ - private function getMatchingUninlinableCssRules(): array - { - if (!\is_array($this->matchingUninlinableCssRules)) { - throw new \BadMethodCallException('inlineCss must be called first', 1568385221); - } - - return $this->matchingUninlinableCssRules; - } - - /** - * Clears all caches. - */ - private function clearAllCaches(): void - { - $this->caches = [ - self::CACHE_KEY_SELECTOR => [], - self::CACHE_KEY_CSS_DECLARATIONS_BLOCK => [], - self::CACHE_KEY_COMBINED_STYLES => [], - ]; - } - - /** - * Purges the visited nodes. - */ - private function purgeVisitedNodes(): void - { - $this->visitedNodes = []; - $this->styleAttributesForNodes = []; - } - - /** - * Parses the document and normalizes all existing CSS attributes. - * This changes 'DISPLAY: none' to 'display: none'. - * We wouldn't have to do this if DOMXPath supported XPath 2.0. - * Also stores a reference of nodes with existing inline styles so we don't overwrite them. - */ - private function normalizeStyleAttributesOfAllNodes(): void - { - /** @var \DOMElement $node */ - foreach ($this->getAllNodesWithStyleAttribute() as $node) { - if ($this->isInlineStyleAttributesParsingEnabled) { - $this->normalizeStyleAttributes($node); - } - // Remove style attribute in every case, so we can add them back (if inline style attributes - // parsing is enabled) to the end of the style list, thus keeping the right priority of CSS rules; - // else original inline style rules may remain at the beginning of the final inline style definition - // of a node, which may give not the desired results - $node->removeAttribute('style'); - } - } - - /** - * Returns a list with all DOM nodes that have a style attribute. - * - * @return \DOMNodeList - * - * @throws \RuntimeException - */ - private function getAllNodesWithStyleAttribute(): \DOMNodeList - { - $query = '//*[@style]'; - $matches = $this->getXPath()->query($query); - if (!$matches instanceof \DOMNodeList) { - throw new \RuntimeException('XPatch query failed: ' . $query, 1618577797); - } - - return $matches; - } - - /** - * Normalizes the value of the "style" attribute and saves it. - * - * @param \DOMElement $node - */ - private function normalizeStyleAttributes(\DOMElement $node): void - { - $normalizedOriginalStyle = \preg_replace_callback( - '/-?+[_a-zA-Z][\\w\\-]*+(?=:)/S', - /** @param array<array-key, string> $propertyNameMatches */ - static function (array $propertyNameMatches): string { - return \strtolower($propertyNameMatches[0]); - }, - $node->getAttribute('style') - ); - - // In order to not overwrite existing style attributes in the HTML, we have to save the original HTML styles. - $nodePath = $node->getNodePath(); - if (\is_string($nodePath) && !isset($this->styleAttributesForNodes[$nodePath])) { - $this->styleAttributesForNodes[$nodePath] = $this->parseCssDeclarationsBlock($normalizedOriginalStyle); - $this->visitedNodes[$nodePath] = $node; - } - - $node->setAttribute('style', $normalizedOriginalStyle); - } - - /** - * Parses a CSS declaration block into property name/value pairs. - * - * Example: - * - * The declaration block - * - * "color: #000; font-weight: bold;" - * - * will be parsed into the following array: - * - * "color" => "#000" - * "font-weight" => "bold" - * - * @param string $cssDeclarationsBlock the CSS declarations block without the curly braces, may be empty - * - * @return array<string, string> - * the CSS declarations with the property names as array keys and the property values as array values - */ - private function parseCssDeclarationsBlock(string $cssDeclarationsBlock): array - { - if (isset($this->caches[self::CACHE_KEY_CSS_DECLARATIONS_BLOCK][$cssDeclarationsBlock])) { - return $this->caches[self::CACHE_KEY_CSS_DECLARATIONS_BLOCK][$cssDeclarationsBlock]; - } - - $properties = []; - foreach (\preg_split('/;(?!base64|charset)/', $cssDeclarationsBlock) as $declaration) { - /** @var array<int, string> $matches */ - $matches = []; - if (!\preg_match('/^([A-Za-z\\-]+)\\s*:\\s*(.+)$/s', \trim($declaration), $matches)) { - continue; - } - - $propertyName = \strtolower($matches[1]); - $propertyValue = $matches[2]; - $properties[$propertyName] = $propertyValue; - } - $this->caches[self::CACHE_KEY_CSS_DECLARATIONS_BLOCK][$cssDeclarationsBlock] = $properties; - - return $properties; - } - - /** - * Returns CSS content. - * - * @return string - */ - private function getCssFromAllStyleNodes(): string - { - $styleNodes = $this->getXPath()->query('//style'); - if ($styleNodes === false) { - return ''; - } - - $css = ''; - foreach ($styleNodes as $styleNode) { - $css .= "\n\n" . $styleNode->nodeValue; - $parentNode = $styleNode->parentNode; - if ($parentNode instanceof \DOMNode) { - $parentNode->removeChild($styleNode); - } - } - - return $css; - } - - /** - * Find the nodes that are not to be emogrified. - * - * @return array<int, \DOMElement> - * - * @throws ParseException - * @throws \UnexpectedValueException - */ - private function getNodesToExclude(): array - { - $excludedNodes = []; - foreach (\array_keys($this->excludedSelectors) as $selectorToExclude) { - try { - $matchingNodes = $this->getXPath() - ->query($this->getCssSelectorConverter()->toXPath($selectorToExclude)); - - foreach ($matchingNodes as $node) { - if (!$node instanceof \DOMElement) { - $path = $node->getNodePath() ?? '$node'; - throw new \UnexpectedValueException($path . ' is not a DOMElement.', 1617975914); - } - $excludedNodes[] = $node; - } - } catch (ParseException $e) { - if ($this->debug) { - throw $e; - } - } - } - - return $excludedNodes; - } - - /** - * @return CssSelectorConverter - */ - private function getCssSelectorConverter(): CssSelectorConverter - { - if (!$this->cssSelectorConverter instanceof CssSelectorConverter) { - $this->cssSelectorConverter = new CssSelectorConverter(); - } - - return $this->cssSelectorConverter; - } - - /** - * Collates the individual rules from a `CssDocument` object. - * - * @param CssDocument $parsedCss - * - * @return array<string, array<array-key, array{ - * media: string, - * selector: string, - * hasUnmatchablePseudo: bool, - * declarationsBlock: string, - * line: int - * }>> - * This 2-entry array has the key "inlinable" containing rules which can be inlined as `style` attributes - * and the key "uninlinable" containing rules which cannot. Each value is an array of sub-arrays with the - * following keys: - * - "media" (the media query string, e.g. "@media screen and (max-width: 480px)", - * or an empty string if not from a `@media` rule); - * - "selector" (the CSS selector, e.g., "*" or "header h1"); - * - "hasUnmatchablePseudo" (`true` if that selector contains pseudo-elements or dynamic pseudo-classes such - * that the declarations cannot be applied inline); - * - "declarationsBlock" (the semicolon-separated CSS declarations for that selector, - * e.g., `color: red; height: 4px;`); - * - "line" (the line number, e.g. 42). - */ - private function collateCssRules(CssDocument $parsedCss): array - { - $matches = $parsedCss->getStyleRulesData(\array_keys($this->allowedMediaTypes)); - - $cssRules = [ - 'inlinable' => [], - 'uninlinable' => [], - ]; - foreach ($matches as $key => $cssRule) { - if (!$cssRule->hasAtLeastOneDeclaration()) { - continue; - } - - $mediaQuery = $cssRule->getContainingAtRule(); - $declarationsBlock = $cssRule->getDeclarationAsText(); - foreach ($cssRule->getSelectors() as $selector) { - // don't process pseudo-elements and behavioral (dynamic) pseudo-classes; - // only allow structural pseudo-classes - $hasPseudoElement = \strpos($selector, '::') !== false; - $hasUnmatchablePseudo = $hasPseudoElement || $this->hasUnsupportedPseudoClass($selector); - - $parsedCssRule = [ - 'media' => $mediaQuery, - 'selector' => $selector, - 'hasUnmatchablePseudo' => $hasUnmatchablePseudo, - 'declarationsBlock' => $declarationsBlock, - // keep track of where it appears in the file, since order is important - 'line' => $key, - ]; - $ruleType = (!$cssRule->hasContainingAtRule() && !$hasUnmatchablePseudo) ? 'inlinable' : 'uninlinable'; - $cssRules[$ruleType][] = $parsedCssRule; - } - } - - \usort( - $cssRules['inlinable'], - /** - * @param array{selector: string, line: int} $first - * @param array{selector: string, line: int} $second - */ - function (array $first, array $second): int { - return $this->sortBySelectorPrecedence($first, $second); - } - ); - - return $cssRules; - } - - /** - * Tests if a selector contains a pseudo-class which would mean it cannot be converted to an XPath expression for - * inlining CSS declarations. - * - * Any pseudo class that does not match {@see PSEUDO_CLASS_MATCHER} cannot be converted. Additionally, `...of-type` - * pseudo-classes cannot be converted if they are not associated with a type selector. - * - * @param string $selector - * - * @return bool - */ - private function hasUnsupportedPseudoClass(string $selector): bool - { - if (\preg_match('/:(?!' . self::PSEUDO_CLASS_MATCHER . ')[\\w\\-]/i', $selector)) { - return true; - } - - if (!\preg_match('/:(?:' . self::OF_TYPE_PSEUDO_CLASS_MATCHER . ')/i', $selector)) { - return false; - } - - foreach (\preg_split('/' . self::COMBINATOR_MATCHER . '/', $selector) as $selectorPart) { - if ($this->selectorPartHasUnsupportedOfTypePseudoClass($selectorPart)) { - return true; - } - } - - return false; - } - - /** - * Tests if part of a selector contains an `...of-type` pseudo-class such that it cannot be converted to an XPath - * expression. - * - * @param string $selectorPart part of a selector which has been split up at combinators - * - * @return bool `true` if the selector part does not have a type but does have an `...of-type` pseudo-class - */ - private function selectorPartHasUnsupportedOfTypePseudoClass(string $selectorPart): bool - { - if (\preg_match('/^[\\w\\-]/', $selectorPart)) { - return false; - } - - return (bool)\preg_match('/:(?:' . self::OF_TYPE_PSEUDO_CLASS_MATCHER . ')/i', $selectorPart); - } - - /** - * @param array{selector: string, line: int} $first - * @param array{selector: string, line: int} $second - * - * @return int - */ - private function sortBySelectorPrecedence(array $first, array $second): int - { - $precedenceOfFirst = $this->getCssSelectorPrecedence($first['selector']); - $precedenceOfSecond = $this->getCssSelectorPrecedence($second['selector']); - - // We want these sorted in ascending order so selectors with lesser precedence get processed first and - // selectors with greater precedence get sorted last. - $precedenceForEquals = $first['line'] < $second['line'] ? -1 : 1; - $precedenceForNotEquals = $precedenceOfFirst < $precedenceOfSecond ? -1 : 1; - return ($precedenceOfFirst === $precedenceOfSecond) ? $precedenceForEquals : $precedenceForNotEquals; - } - - /** - * @param string $selector - * - * @return int - */ - private function getCssSelectorPrecedence(string $selector): int - { - $selectorKey = \md5($selector); - if (isset($this->caches[self::CACHE_KEY_SELECTOR][$selectorKey])) { - return $this->caches[self::CACHE_KEY_SELECTOR][$selectorKey]; - } - - $precedence = 0; - foreach ($this->selectorPrecedenceMatchers as $matcher => $value) { - if (\trim($selector) === '') { - break; - } - $number = 0; - $selector = \preg_replace('/' . $matcher . '\\w+/', '', $selector, -1, $number); - $precedence += ($value * (int)$number); - } - $this->caches[self::CACHE_KEY_SELECTOR][$selectorKey] = $precedence; - - return $precedence; - } - - /** - * Copies $cssRule into the style attribute of $node. - * - * Note: This method does not check whether $cssRule matches $node. - * - * @param \DOMElement $node - * @param array{ - * media: string, - * selector: string, - * hasUnmatchablePseudo: bool, - * declarationsBlock: string, - * line: int - * } $cssRule - */ - private function copyInlinableCssToStyleAttribute(\DOMElement $node, array $cssRule): void - { - $declarationsBlock = $cssRule['declarationsBlock']; - $newStyleDeclarations = $this->parseCssDeclarationsBlock($declarationsBlock); - if ($newStyleDeclarations === []) { - return; - } - - // if it has a style attribute, get it, process it, and append (overwrite) new stuff - if ($node->hasAttribute('style')) { - // break it up into an associative array - $oldStyleDeclarations = $this->parseCssDeclarationsBlock($node->getAttribute('style')); - } else { - $oldStyleDeclarations = []; - } - $node->setAttribute( - 'style', - $this->generateStyleStringFromDeclarationsArrays($oldStyleDeclarations, $newStyleDeclarations) - ); - } - - /** - * This method merges old or existing name/value array with new name/value array - * and then generates a string of the combined style suitable for placing inline. - * This becomes the single point for CSS string generation allowing for consistent - * CSS output no matter where the CSS originally came from. - * - * @param array<string, string> $oldStyles - * @param array<string, string> $newStyles - * - * @return string - */ - private function generateStyleStringFromDeclarationsArrays(array $oldStyles, array $newStyles): string - { - $cacheKey = \serialize([$oldStyles, $newStyles]); - if (isset($this->caches[self::CACHE_KEY_COMBINED_STYLES][$cacheKey])) { - return $this->caches[self::CACHE_KEY_COMBINED_STYLES][$cacheKey]; - } - - // Unset the overridden styles to preserve order, important if shorthand and individual properties are mixed - foreach ($oldStyles as $attributeName => $attributeValue) { - if (!isset($newStyles[$attributeName])) { - continue; - } - - $newAttributeValue = $newStyles[$attributeName]; - if ( - $this->attributeValueIsImportant($attributeValue) - && !$this->attributeValueIsImportant($newAttributeValue) - ) { - unset($newStyles[$attributeName]); - } else { - unset($oldStyles[$attributeName]); - } - } - - $combinedStyles = \array_merge($oldStyles, $newStyles); - - $style = ''; - foreach ($combinedStyles as $attributeName => $attributeValue) { - $style .= \strtolower(\trim($attributeName)) . ': ' . \trim($attributeValue) . '; '; - } - $trimmedStyle = \rtrim($style); - - $this->caches[self::CACHE_KEY_COMBINED_STYLES][$cacheKey] = $trimmedStyle; - - return $trimmedStyle; - } - - /** - * Checks whether $attributeValue is marked as !important. - * - * @param string $attributeValue - * - * @return bool - */ - private function attributeValueIsImportant(string $attributeValue): bool - { - return (bool)\preg_match('/!\\s*+important$/i', $attributeValue); - } - - /** - * Merges styles from styles attributes and style nodes and applies them to the attribute nodes - */ - private function fillStyleAttributesWithMergedStyles(): void - { - foreach ($this->styleAttributesForNodes as $nodePath => $styleAttributesForNode) { - $node = $this->visitedNodes[$nodePath]; - $currentStyleAttributes = $this->parseCssDeclarationsBlock($node->getAttribute('style')); - $node->setAttribute( - 'style', - $this->generateStyleStringFromDeclarationsArrays( - $currentStyleAttributes, - $styleAttributesForNode - ) - ); - } - } - - /** - * Searches for all nodes with a style attribute and removes the "!important" annotations out of - * the inline style declarations, eventually by rearranging declarations. - * - * @throws \RuntimeException - */ - private function removeImportantAnnotationFromAllInlineStyles(): void - { - /** @var \DOMElement $node */ - foreach ($this->getAllNodesWithStyleAttribute() as $node) { - $this->removeImportantAnnotationFromNodeInlineStyle($node); - } - } - - /** - * Removes the "!important" annotations out of the inline style declarations, - * eventually by rearranging declarations. - * Rearranging needed when !important shorthand properties are followed by some of their - * not !important expanded-version properties. - * For example "font: 12px serif !important; font-size: 13px;" must be reordered - * to "font-size: 13px; font: 12px serif;" in order to remain correct. - * - * @param \DOMElement $node - * - * @throws \RuntimeException - */ - private function removeImportantAnnotationFromNodeInlineStyle(\DOMElement $node): void - { - $inlineStyleDeclarations = $this->parseCssDeclarationsBlock($node->getAttribute('style')); - /** @var array<string, string> $regularStyleDeclarations */ - $regularStyleDeclarations = []; - /** @var array<string, string> $importantStyleDeclarations */ - $importantStyleDeclarations = []; - foreach ($inlineStyleDeclarations as $property => $value) { - if ($this->attributeValueIsImportant($value)) { - $importantStyleDeclarations[$property] = $this->pregReplace('/\\s*+!\\s*+important$/i', '', $value); - } else { - $regularStyleDeclarations[$property] = $value; - } - } - $inlineStyleDeclarationsInNewOrder = \array_merge($regularStyleDeclarations, $importantStyleDeclarations); - $node->setAttribute( - 'style', - $this->generateStyleStringFromSingleDeclarationsArray($inlineStyleDeclarationsInNewOrder) - ); - } - - /** - * Generates a CSS style string suitable to be used inline from the $styleDeclarations property => value array. - * - * @param array<string, string> $styleDeclarations - * - * @return string - */ - private function generateStyleStringFromSingleDeclarationsArray(array $styleDeclarations): string - { - return $this->generateStyleStringFromDeclarationsArrays([], $styleDeclarations); - } - - /** - * Determines which of `$cssRules` actually apply to `$this->domDocument`, and sets them in - * `$this->matchingUninlinableCssRules`. - * - * @param array<array-key, array{ - * media: string, - * selector: string, - * hasUnmatchablePseudo: bool, - * declarationsBlock: string, - * line: int - * }> $cssRules - * the "uninlinable" array of CSS rules returned by `collateCssRules` - */ - private function determineMatchingUninlinableCssRules(array $cssRules): void - { - $this->matchingUninlinableCssRules = \array_filter( - $cssRules, - function (array $cssRule): bool { - return $this->existsMatchForSelectorInCssRule($cssRule); - } - ); - } - - /** - * Checks whether there is at least one matching element for the CSS selector contained in the `selector` element - * of the provided CSS rule. - * - * Any dynamic pseudo-classes will be assumed to apply. If the selector matches a pseudo-element, - * it will test for a match with its originating element. - * - * @param array{ - * media: string, - * selector: string, - * hasUnmatchablePseudo: bool, - * declarationsBlock: string, - * line: int - * } $cssRule - * - * @return bool - * - * @throws ParseException - */ - private function existsMatchForSelectorInCssRule(array $cssRule): bool - { - $selector = $cssRule['selector']; - if ($cssRule['hasUnmatchablePseudo']) { - $selector = $this->removeUnmatchablePseudoComponents($selector); - } - return $this->existsMatchForCssSelector($selector); - } - - /** - * Checks whether there is at least one matching element for $cssSelector. - * When not in debug mode, it returns true also for invalid selectors (because they may be valid, - * just not implemented/recognized yet by Emogrifier). - * - * @param string $cssSelector - * - * @return bool - * - * @throws ParseException - */ - private function existsMatchForCssSelector(string $cssSelector): bool - { - try { - $nodesMatchingSelector = $this->getXPath()->query($this->getCssSelectorConverter()->toXPath($cssSelector)); - } catch (ParseException $e) { - if ($this->debug) { - throw $e; - } - return true; - } - - return $nodesMatchingSelector !== false && $nodesMatchingSelector->length !== 0; - } - - /** - * Removes pseudo-elements and dynamic pseudo-classes from a CSS selector, replacing them with "*" if necessary. - * If such a pseudo-component is within the argument of `:not`, the entire `:not` component is removed or replaced. - * - * @param string $selector - * - * @return string - * selector which will match the relevant DOM elements if the pseudo-classes are assumed to apply, or in the - * case of pseudo-elements will match their originating element - */ - private function removeUnmatchablePseudoComponents(string $selector): string - { - // The regex allows nested brackets via `(?2)`. - // A space is temporarily prepended because the callback can't determine if the match was at the very start. - $selectorWithoutNots = \ltrim(\preg_replace_callback( - '/([\\s>+~]?+):not(\\([^()]*+(?:(?2)[^()]*+)*+\\))/i', - /** @param array<array-key, string> $matches */ - function (array $matches): string { - return $this->replaceUnmatchableNotComponent($matches); - }, - ' ' . $selector - )); - - $selectorWithoutUnmatchablePseudoComponents = $this->removeSelectorComponents( - ':(?!' . self::PSEUDO_CLASS_MATCHER . '):?+[\\w\\-]++(?:\\([^\\)]*+\\))?+', - $selectorWithoutNots - ); - - if ( - !\preg_match( - '/:(?:' . self::OF_TYPE_PSEUDO_CLASS_MATCHER . ')/i', - $selectorWithoutUnmatchablePseudoComponents - ) - ) { - return $selectorWithoutUnmatchablePseudoComponents; - } - return \implode('', \array_map( - function (string $selectorPart): string { - return $this->removeUnsupportedOfTypePseudoClasses($selectorPart); - }, - \preg_split( - '/(' . self::COMBINATOR_MATCHER . ')/', - $selectorWithoutUnmatchablePseudoComponents, - -1, - PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY - ) - )); - } - - /** - * Helps `removeUnmatchablePseudoComponents()` replace or remove a selector `:not(...)` component if its argument - * contains pseudo-elements or dynamic pseudo-classes. - * - * @param array<array-key, string> $matches array of elements matched by the regular expression - * - * @return string - * the full match if there were no unmatchable pseudo components within; otherwise, any preceding combinator - * followed by "*", or an empty string if there was no preceding combinator - */ - private function replaceUnmatchableNotComponent(array $matches): string - { - [$notComponentWithAnyPrecedingCombinator, $anyPrecedingCombinator, $notArgumentInBrackets] = $matches; - - if ($this->hasUnsupportedPseudoClass($notArgumentInBrackets)) { - return $anyPrecedingCombinator !== '' ? $anyPrecedingCombinator . '*' : ''; - } - return $notComponentWithAnyPrecedingCombinator; - } - - /** - * Removes components from a CSS selector, replacing them with "*" if necessary. - * - * @param string $matcher regular expression part to match the components to remove - * @param string $selector - * - * @return string - * selector which will match the relevant DOM elements if the removed components are assumed to apply (or in - * the case of pseudo-elements will match their originating element) - */ - private function removeSelectorComponents(string $matcher, string $selector): string - { - return \preg_replace( - ['/([\\s>+~]|^)' . $matcher . '/i', '/' . $matcher . '/i'], - ['$1*', ''], - $selector - ); - } - - /** - * Removes any `...-of-type` pseudo-classes from part of a CSS selector, if it does not have a type, replacing them - * with "*" if necessary. - * - * @param string $selectorPart part of a selector which has been split up at combinators - * - * @return string - * selector part which will match the relevant DOM elements if the pseudo-classes are assumed to apply - */ - private function removeUnsupportedOfTypePseudoClasses(string $selectorPart): string - { - if (!$this->selectorPartHasUnsupportedOfTypePseudoClass($selectorPart)) { - return $selectorPart; - } - - return $this->removeSelectorComponents( - ':(?:' . self::OF_TYPE_PSEUDO_CLASS_MATCHER . ')(?:\\([^\\)]*+\\))?+', - $selectorPart - ); - } - - /** - * Applies `$this->matchingUninlinableCssRules` to `$this->domDocument` by placing them as CSS in a `<style>` - * element. - * If there are no uninlinable CSS rules to copy there, a `<style>` element will be created containing only the - * applicable at-rules from `$parsedCss`. - * If there are none of either, an empty `<style>` element will not be created. - * - * @param CssDocument $parsedCss - * This may contain various at-rules whose content `CssInliner` does not currently attempt to inline or - * process in any other way, such as `@import`, `@font-face`, `@keyframes`, etc., and which should precede - * the processed but found-to-be-uninlinable CSS placed in the `<style>` element. - * Note that `CssInliner` processes `@media` rules so that they can be ordered correctly with respect to - * other uninlinable rules; these will not be duplicated from `$parsedCss`. - */ - private function copyUninlinableCssToStyleNode(CssDocument $parsedCss): void - { - $css = $parsedCss->renderNonConditionalAtRules(); - - // avoid including unneeded class dependency if there are no rules - if ($this->getMatchingUninlinableCssRules() !== []) { - $cssConcatenator = new CssConcatenator(); - foreach ($this->getMatchingUninlinableCssRules() as $cssRule) { - $cssConcatenator->append([$cssRule['selector']], $cssRule['declarationsBlock'], $cssRule['media']); - } - $css .= $cssConcatenator->getCss(); - } - - // avoid adding empty style element - if ($css !== '') { - $this->addStyleElementToDocument($css); - } - } - - /** - * Adds a style element with $css to $this->domDocument. - * - * This method is protected to allow overriding. - * - * @see https://github.com/MyIntervals/emogrifier/issues/103 - * - * @param string $css - */ - protected function addStyleElementToDocument(string $css): void - { - $domDocument = $this->getDomDocument(); - $styleElement = $domDocument->createElement('style', $css); - $styleAttribute = $domDocument->createAttribute('type'); - $styleAttribute->value = 'text/css'; - $styleElement->appendChild($styleAttribute); - - $headElement = $this->getHeadElement(); - $headElement->appendChild($styleElement); - } - - /** - * Returns the HEAD element. - * - * This method assumes that there always is a HEAD element. - * - * @return \DOMElement - * - * @throws \UnexpectedValueException - */ - private function getHeadElement(): \DOMElement - { - $node = $this->getDomDocument()->getElementsByTagName('head')->item(0); - if (!$node instanceof \DOMElement) { - throw new \UnexpectedValueException('There is no HEAD element. This should never happen.', 1617923227); - } - - return $node; - } - - /** - * Wraps `preg_replace`. If an error occurs (which is highly unlikely), either it is logged and the original - * `$subject` is returned, or in debug mode an exception is thrown. - * - * This method only supports strings, not arrays of strings. - * - * @param string $pattern - * @param string $replacement - * @param string $subject - * - * @return string - * - * @throws \RuntimeException - */ - private function pregReplace(string $pattern, string $replacement, string $subject): string - { - $result = \preg_replace($pattern, $replacement, $subject); - - if (!\is_string($result)) { - $this->logOrThrowPregLastError(); - $result = $subject; - } - - return $result; - } - - /** - * Obtains the name of the error constant for `preg_last_error` (based on code posted at - * {@see https://www.php.net/manual/en/function.preg-last-error.php#124124}) and puts it into an error message - * which is either passed to `trigger_error` (in non-debug mode) or an exception which is thrown (in debug mode). - * - * @throws \RuntimeException - */ - private function logOrThrowPregLastError(): void - { - $pcreConstants = \get_defined_constants(true)['pcre']; - $pcreErrorConstantNames = \array_flip(\array_filter( - $pcreConstants, - static function (string $key): bool { - return \substr($key, -6) === '_ERROR'; - }, - ARRAY_FILTER_USE_KEY - )); - - $pregLastError = \preg_last_error(); - $message = 'PCRE regex execution error `' . (string)($pcreErrorConstantNames[$pregLastError] ?? $pregLastError) - . '`'; - - if ($this->debug) { - throw new \RuntimeException($message, 1592870147); - } - \trigger_error($message); - } -} diff --git a/lib/pelago/emogrifier/src/HtmlProcessor/AbstractHtmlProcessor.php b/lib/pelago/emogrifier/src/HtmlProcessor/AbstractHtmlProcessor.php deleted file mode 100644 index 2e203642f..000000000 --- a/lib/pelago/emogrifier/src/HtmlProcessor/AbstractHtmlProcessor.php +++ /dev/null @@ -1,472 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Pelago\Emogrifier\HtmlProcessor; - -/** - * Base class for HTML processor that e.g., can remove, add or modify nodes or attributes. - * - * The "vanilla" subclass is the HtmlNormalizer. - * - * @psalm-consistent-constructor - */ -abstract class AbstractHtmlProcessor -{ - /** - * @var string - */ - protected const DEFAULT_DOCUMENT_TYPE = '<!DOCTYPE html>'; - - /** - * @var string - */ - protected const CONTENT_TYPE_META_TAG = '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">'; - - /** - * @var string Regular expression part to match tag names that PHP's DOMDocument implementation is not aware are - * self-closing. These are mostly HTML5 elements, but for completeness <command> (obsolete) and <keygen> - * (deprecated) are also included. - * - * @see https://bugs.php.net/bug.php?id=73175 - */ - protected const PHP_UNRECOGNIZED_VOID_TAGNAME_MATCHER = '(?:command|embed|keygen|source|track|wbr)'; - - /** - * Regular expression part to match tag names that may appear before the start of the `<body>` element. A start tag - * for any other element would implicitly start the `<body>` element due to tag omission rules. - * - * @var string - */ - protected const TAGNAME_ALLOWED_BEFORE_BODY_MATCHER - = '(?:html|head|base|command|link|meta|noscript|script|style|template|title)'; - - /** - * regular expression pattern to match an HTML comment, including delimiters and modifiers - * - * @var string - */ - protected const HTML_COMMENT_PATTERN = '/<!--[^-]*+(?:-(?!->)[^-]*+)*+(?:-->|$)/'; - - /** - * regular expression pattern to match an HTML `<template>` element, including delimiters and modifiers - * - * @var string - */ - protected const HTML_TEMPLATE_ELEMENT_PATTERN - = '%<template[\\s>][^<]*+(?:<(?!/template>)[^<]*+)*+(?:</template>|$)%i'; - - /** - * @var ?\DOMDocument - */ - protected $domDocument = null; - - /** - * @var ?\DOMXPath - */ - private $xPath = null; - - /** - * The constructor. - * - * Please use `::fromHtml` or `::fromDomDocument` instead. - */ - private function __construct() - { - } - - /** - * Builds a new instance from the given HTML. - * - * @param string $unprocessedHtml raw HTML, must be UTF-encoded, must not be empty - * - * @return static - * - * @throws \InvalidArgumentException if $unprocessedHtml is anything other than a non-empty string - */ - public static function fromHtml(string $unprocessedHtml): self - { - if ($unprocessedHtml === '') { - throw new \InvalidArgumentException('The provided HTML must not be empty.', 1515763647); - } - - $instance = new static(); - $instance->setHtml($unprocessedHtml); - - return $instance; - } - - /** - * Builds a new instance from the given DOM document. - * - * @param \DOMDocument $document a DOM document returned by getDomDocument() of another instance - * - * @return static - */ - public static function fromDomDocument(\DOMDocument $document): self - { - $instance = new static(); - $instance->setDomDocument($document); - - return $instance; - } - - /** - * Sets the HTML to process. - * - * @param string $html the HTML to process, must be UTF-8-encoded - */ - private function setHtml(string $html): void - { - $this->createUnifiedDomDocument($html); - } - - /** - * Provides access to the internal DOMDocument representation of the HTML in its current state. - * - * @return \DOMDocument - * - * @throws \UnexpectedValueException - */ - public function getDomDocument(): \DOMDocument - { - if (!$this->domDocument instanceof \DOMDocument) { - $message = self::class . '::setDomDocument() has not yet been called on ' . static::class; - throw new \UnexpectedValueException($message, 1570472239); - } - - return $this->domDocument; - } - - /** - * @param \DOMDocument $domDocument - */ - private function setDomDocument(\DOMDocument $domDocument): void - { - $this->domDocument = $domDocument; - $this->xPath = new \DOMXPath($this->domDocument); - } - - /** - * @return \DOMXPath - * - * @throws \UnexpectedValueException - */ - protected function getXPath(): \DOMXPath - { - if (!$this->xPath instanceof \DOMXPath) { - $message = self::class . '::setDomDocument() has not yet been called on ' . static::class; - throw new \UnexpectedValueException($message, 1617819086); - } - - return $this->xPath; - } - - /** - * Renders the normalized and processed HTML. - * - * @return string - */ - public function render(): string - { - $htmlWithPossibleErroneousClosingTags = $this->getDomDocument()->saveHTML(); - - return $this->removeSelfClosingTagsClosingTags($htmlWithPossibleErroneousClosingTags); - } - - /** - * Renders the content of the BODY element of the normalized and processed HTML. - * - * @return string - */ - public function renderBodyContent(): string - { - $htmlWithPossibleErroneousClosingTags = $this->getDomDocument()->saveHTML($this->getBodyElement()); - $bodyNodeHtml = $this->removeSelfClosingTagsClosingTags($htmlWithPossibleErroneousClosingTags); - - return \preg_replace('%</?+body(?:\\s[^>]*+)?+>%', '', $bodyNodeHtml); - } - - /** - * Eliminates any invalid closing tags for void elements from the given HTML. - * - * @param string $html - * - * @return string - */ - private function removeSelfClosingTagsClosingTags(string $html): string - { - return \preg_replace('%</' . self::PHP_UNRECOGNIZED_VOID_TAGNAME_MATCHER . '>%', '', $html); - } - - /** - * Returns the BODY element. - * - * This method assumes that there always is a BODY element. - * - * @return \DOMElement - * - * @throws \RuntimeException - */ - private function getBodyElement(): \DOMElement - { - $node = $this->getDomDocument()->getElementsByTagName('body')->item(0); - if (!$node instanceof \DOMElement) { - throw new \RuntimeException('There is no body element.', 1617922607); - } - - return $node; - } - - /** - * Creates a DOM document from the given HTML and stores it in $this->domDocument. - * - * The DOM document will always have a BODY element and a document type. - * - * @param string $html - */ - private function createUnifiedDomDocument(string $html): void - { - $this->createRawDomDocument($html); - $this->ensureExistenceOfBodyElement(); - } - - /** - * Creates a DOMDocument instance from the given HTML and stores it in $this->domDocument. - * - * @param string $html - */ - private function createRawDomDocument(string $html): void - { - $domDocument = new \DOMDocument(); - $domDocument->strictErrorChecking = false; - $domDocument->formatOutput = true; - $libXmlState = \libxml_use_internal_errors(true); - $domDocument->loadHTML($this->prepareHtmlForDomConversion($html)); - \libxml_clear_errors(); - \libxml_use_internal_errors($libXmlState); - - $this->setDomDocument($domDocument); - } - - /** - * Returns the HTML with added document type, Content-Type meta tag, and self-closing slashes, if needed, - * ensuring that the HTML will be good for creating a DOM document from it. - * - * @param string $html - * - * @return string the unified HTML - */ - private function prepareHtmlForDomConversion(string $html): string - { - $htmlWithSelfClosingSlashes = $this->ensurePhpUnrecognizedSelfClosingTagsAreXml($html); - $htmlWithDocumentType = $this->ensureDocumentType($htmlWithSelfClosingSlashes); - - return $this->addContentTypeMetaTag($htmlWithDocumentType); - } - - /** - * Makes sure that the passed HTML has a document type, with lowercase "html". - * - * @param string $html - * - * @return string HTML with document type - */ - private function ensureDocumentType(string $html): string - { - $hasDocumentType = \stripos($html, '<!DOCTYPE') !== false; - if ($hasDocumentType) { - return $this->normalizeDocumentType($html); - } - - return self::DEFAULT_DOCUMENT_TYPE . $html; - } - - /** - * Makes sure the document type in the passed HTML has lowercase "html". - * - * @param string $html - * - * @return string HTML with normalized document type - */ - private function normalizeDocumentType(string $html): string - { - // Limit to replacing the first occurrence: as an optimization; and in case an example exists as unescaped text. - return \preg_replace( - '/<!DOCTYPE\\s++html(?=[\\s>])/i', - '<!DOCTYPE html', - $html, - 1 - ); - } - - /** - * Adds a Content-Type meta tag for the charset. - * - * This method also ensures that there is a HEAD element. - * - * @param string $html - * - * @return string the HTML with the meta tag added - */ - private function addContentTypeMetaTag(string $html): string - { - if ($this->hasContentTypeMetaTagInHead($html)) { - return $html; - } - - // We are trying to insert the meta tag to the right spot in the DOM. - // If we just prepended it to the HTML, we would lose attributes set to the HTML tag. - $hasHeadTag = \preg_match('/<head[\\s>]/i', $html); - $hasHtmlTag = \stripos($html, '<html') !== false; - - if ($hasHeadTag) { - $reworkedHtml = \preg_replace( - '/<head(?=[\\s>])([^>]*+)>/i', - '<head$1>' . self::CONTENT_TYPE_META_TAG, - $html - ); - } elseif ($hasHtmlTag) { - $reworkedHtml = \preg_replace( - '/<html(.*?)>/is', - '<html$1><head>' . self::CONTENT_TYPE_META_TAG . '</head>', - $html - ); - } else { - $reworkedHtml = self::CONTENT_TYPE_META_TAG . $html; - } - - return $reworkedHtml; - } - - /** - * Tests whether the given HTML has a valid `Content-Type` metadata element within the `<head>` element. Due to tag - * omission rules, HTML parsers are expected to end the `<head>` element and start the `<body>` element upon - * encountering a start tag for any element which is permitted only within the `<body>`. - * - * @param string $html - * - * @return bool - */ - private function hasContentTypeMetaTagInHead(string $html): bool - { - \preg_match('%^.*?(?=<meta(?=\\s)[^>]*\\shttp-equiv=(["\']?+)Content-Type\\g{-1}[\\s/>])%is', $html, $matches); - if (isset($matches[0])) { - $htmlBefore = $matches[0]; - try { - $hasContentTypeMetaTagInHead = !$this->hasEndOfHeadElement($htmlBefore); - } catch (\RuntimeException $exception) { - // If something unexpected occurs, assume the `Content-Type` that was found is valid. - \trigger_error($exception->getMessage()); - $hasContentTypeMetaTagInHead = true; - } - } else { - $hasContentTypeMetaTagInHead = false; - } - - return $hasContentTypeMetaTagInHead; - } - - /** - * Tests whether the `<head>` element ends within the given HTML. Due to tag omission rules, HTML parsers are - * expected to end the `<head>` element and start the `<body>` element upon encountering a start tag for any element - * which is permitted only within the `<body>`. - * - * @param string $html - * - * @return bool - * - * @throws \RuntimeException - */ - private function hasEndOfHeadElement(string $html): bool - { - $headEndTagMatchCount - = \preg_match('%<(?!' . self::TAGNAME_ALLOWED_BEFORE_BODY_MATCHER . '[\\s/>])\\w|</head>%i', $html); - if (\is_int($headEndTagMatchCount) && $headEndTagMatchCount > 0) { - // An exception to the implicit end of the `<head>` is any content within a `<template>` element, as well in - // comments. As an optimization, this is only checked for if a potential `<head>` end tag is found. - $htmlWithoutCommentsOrTemplates = $this->removeHtmlTemplateElements($this->removeHtmlComments($html)); - $hasEndOfHeadElement = $htmlWithoutCommentsOrTemplates === $html - || $this->hasEndOfHeadElement($htmlWithoutCommentsOrTemplates); - } else { - $hasEndOfHeadElement = false; - } - - return $hasEndOfHeadElement; - } - - /** - * Removes comments from the given HTML, including any which are unterminated, for which the remainder of the string - * is removed. - * - * @param string $html - * - * @return string - * - * @throws \RuntimeException - */ - private function removeHtmlComments(string $html): string - { - $result = \preg_replace(self::HTML_COMMENT_PATTERN, '', $html); - if (!\is_string($result)) { - throw new \RuntimeException('Internal PCRE error', 1616521475); - } - - return $result; - } - - /** - * Removes `<template>` elements from the given HTML, including any without an end tag, for which the remainder of - * the string is removed. - * - * @param string $html - * - * @return string - * - * @throws \RuntimeException - */ - private function removeHtmlTemplateElements(string $html): string - { - $result = \preg_replace(self::HTML_TEMPLATE_ELEMENT_PATTERN, '', $html); - if (!\is_string($result)) { - throw new \RuntimeException('Internal PCRE error', 1616519652); - } - - return $result; - } - - /** - * Makes sure that any self-closing tags not recognized as such by PHP's DOMDocument implementation have a - * self-closing slash. - * - * @param string $html - * - * @return string HTML with problematic tags converted. - */ - private function ensurePhpUnrecognizedSelfClosingTagsAreXml(string $html): string - { - return \preg_replace( - '%<' . self::PHP_UNRECOGNIZED_VOID_TAGNAME_MATCHER . '\\b[^>]*+(?<!/)(?=>)%', - '$0/', - $html - ); - } - - /** - * Checks that $this->domDocument has a BODY element and adds it if it is missing. - * - * @throws \UnexpectedValueException - */ - private function ensureExistenceOfBodyElement(): void - { - if ($this->getDomDocument()->getElementsByTagName('body')->item(0) instanceof \DOMElement) { - return; - } - - $htmlElement = $this->getDomDocument()->getElementsByTagName('html')->item(0); - if (!$htmlElement instanceof \DOMElement) { - throw new \UnexpectedValueException('There is no HTML element although there should be one.', 1569930853); - } - $htmlElement->appendChild($this->getDomDocument()->createElement('body')); - } -} diff --git a/lib/pelago/emogrifier/src/HtmlProcessor/CssToAttributeConverter.php b/lib/pelago/emogrifier/src/HtmlProcessor/CssToAttributeConverter.php deleted file mode 100644 index 6923c9132..000000000 --- a/lib/pelago/emogrifier/src/HtmlProcessor/CssToAttributeConverter.php +++ /dev/null @@ -1,303 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Pelago\Emogrifier\HtmlProcessor; - -/** - * This HtmlProcessor can convert style HTML attributes to the corresponding other visual HTML attributes, - * e.g. it converts style="width: 100px" to width="100". - * - * It will only add attributes, but leaves the style attribute untouched. - * - * To trigger the conversion, call the convertCssToVisualAttributes method. - */ -class CssToAttributeConverter extends AbstractHtmlProcessor -{ - /** - * This multi-level array contains simple mappings of CSS properties to - * HTML attributes. If a mapping only applies to certain HTML nodes or - * only for certain values, the mapping is an object with a whitelist - * of nodes and values. - * - * @var array<string, array{attribute: string, nodes?: array<int, string>, values?: array<int, string>}> - */ - private $cssToHtmlMap = [ - 'background-color' => [ - 'attribute' => 'bgcolor', - ], - 'text-align' => [ - 'attribute' => 'align', - 'nodes' => ['p', 'div', 'td', 'th'], - 'values' => ['left', 'right', 'center', 'justify'], - ], - 'float' => [ - 'attribute' => 'align', - 'nodes' => ['table', 'img'], - 'values' => ['left', 'right'], - ], - 'border-spacing' => [ - 'attribute' => 'cellspacing', - 'nodes' => ['table'], - ], - ]; - - /** - * @var array<string, array<string, string>> - */ - private static $parsedCssCache = []; - - /** - * Maps the CSS from the style nodes to visual HTML attributes. - * - * @return self fluent interface - */ - public function convertCssToVisualAttributes(): self - { - /** @var \DOMElement $node */ - foreach ($this->getAllNodesWithStyleAttribute() as $node) { - $inlineStyleDeclarations = $this->parseCssDeclarationsBlock($node->getAttribute('style')); - $this->mapCssToHtmlAttributes($inlineStyleDeclarations, $node); - } - - return $this; - } - - /** - * Returns a list with all DOM nodes that have a style attribute. - * - * @return \DOMNodeList - */ - private function getAllNodesWithStyleAttribute(): \DOMNodeList - { - return $this->getXPath()->query('//*[@style]'); - } - - /** - * Parses a CSS declaration block into property name/value pairs. - * - * Example: - * - * The declaration block - * - * "color: #000; font-weight: bold;" - * - * will be parsed into the following array: - * - * "color" => "#000" - * "font-weight" => "bold" - * - * @param string $cssDeclarationsBlock the CSS declarations block without the curly braces, may be empty - * - * @return array<string, string> - * the CSS declarations with the property names as array keys and the property values as array values - */ - private function parseCssDeclarationsBlock(string $cssDeclarationsBlock): array - { - if (isset(self::$parsedCssCache[$cssDeclarationsBlock])) { - return self::$parsedCssCache[$cssDeclarationsBlock]; - } - - $properties = []; - foreach (\preg_split('/;(?!base64|charset)/', $cssDeclarationsBlock) as $declaration) { - /** @var array<int, string> $matches */ - $matches = []; - if (!\preg_match('/^([A-Za-z\\-]+)\\s*:\\s*(.+)$/s', \trim($declaration), $matches)) { - continue; - } - - $propertyName = \strtolower($matches[1]); - $propertyValue = $matches[2]; - $properties[$propertyName] = $propertyValue; - } - self::$parsedCssCache[$cssDeclarationsBlock] = $properties; - - return $properties; - } - - /** - * Applies $styles to $node. - * - * This method maps CSS styles to HTML attributes and adds those to the - * node. - * - * @param array<string, string> $styles the new CSS styles taken from the global styles to be applied to this node - * @param \DOMElement $node node to apply styles to - */ - private function mapCssToHtmlAttributes(array $styles, \DOMElement $node): void - { - foreach ($styles as $property => $value) { - // Strip !important indicator - $value = \trim(\str_replace('!important', '', $value)); - $this->mapCssToHtmlAttribute($property, $value, $node); - } - } - - /** - * Tries to apply the CSS style to $node as an attribute. - * - * This method maps a CSS rule to HTML attributes and adds those to the node. - * - * @param string $property the name of the CSS property to map - * @param string $value the value of the style rule to map - * @param \DOMElement $node node to apply styles to - */ - private function mapCssToHtmlAttribute(string $property, string $value, \DOMElement $node): void - { - if (!$this->mapSimpleCssProperty($property, $value, $node)) { - $this->mapComplexCssProperty($property, $value, $node); - } - } - - /** - * Looks up the CSS property in the mapping table and maps it if it matches the conditions. - * - * @param string $property the name of the CSS property to map - * @param string $value the value of the style rule to map - * @param \DOMElement $node node to apply styles to - * - * @return bool true if the property can be mapped using the simple mapping table - */ - private function mapSimpleCssProperty(string $property, string $value, \DOMElement $node): bool - { - if (!isset($this->cssToHtmlMap[$property])) { - return false; - } - - $mapping = $this->cssToHtmlMap[$property]; - $nodesMatch = !isset($mapping['nodes']) || \in_array($node->nodeName, $mapping['nodes'], true); - $valuesMatch = !isset($mapping['values']) || \in_array($value, $mapping['values'], true); - $canBeMapped = $nodesMatch && $valuesMatch; - if ($canBeMapped) { - $node->setAttribute($mapping['attribute'], $value); - } - - return $canBeMapped; - } - - /** - * Maps CSS properties that need special transformation to an HTML attribute. - * - * @param string $property the name of the CSS property to map - * @param string $value the value of the style rule to map - * @param \DOMElement $node node to apply styles to - */ - private function mapComplexCssProperty(string $property, string $value, \DOMElement $node): void - { - switch ($property) { - case 'background': - $this->mapBackgroundProperty($node, $value); - break; - case 'width': - // intentional fall-through - case 'height': - $this->mapWidthOrHeightProperty($node, $value, $property); - break; - case 'margin': - $this->mapMarginProperty($node, $value); - break; - case 'border': - $this->mapBorderProperty($node, $value); - break; - default: - } - } - - /** - * @param \DOMElement $node node to apply styles to - * @param string $value the value of the style rule to map - */ - private function mapBackgroundProperty(\DOMElement $node, string $value): void - { - // parse out the color, if any - /** @var array<int, string> $styles */ - $styles = \explode(' ', $value, 2); - $first = $styles[0]; - if (\is_numeric($first[0]) || \strncmp($first, 'url', 3) === 0) { - return; - } - - // as this is not a position or image, assume it's a color - $node->setAttribute('bgcolor', $first); - } - - /** - * @param \DOMElement $node node to apply styles to - * @param string $value the value of the style rule to map - * @param string $property the name of the CSS property to map - */ - private function mapWidthOrHeightProperty(\DOMElement $node, string $value, string $property): void - { - // only parse values in px and %, but not values like "auto" - if (!\preg_match('/^(\\d+)(\\.(\\d+))?(px|%)$/', $value)) { - return; - } - - $number = \preg_replace('/[^0-9.%]/', '', $value); - $node->setAttribute($property, $number); - } - - /** - * @param \DOMElement $node node to apply styles to - * @param string $value the value of the style rule to map - */ - private function mapMarginProperty(\DOMElement $node, string $value): void - { - if (!$this->isTableOrImageNode($node)) { - return; - } - - $margins = $this->parseCssShorthandValue($value); - if ($margins['left'] === 'auto' && $margins['right'] === 'auto') { - $node->setAttribute('align', 'center'); - } - } - - /** - * @param \DOMElement $node node to apply styles to - * @param string $value the value of the style rule to map - */ - private function mapBorderProperty(\DOMElement $node, string $value): void - { - if (!$this->isTableOrImageNode($node)) { - return; - } - - if ($value === 'none' || $value === '0') { - $node->setAttribute('border', '0'); - } - } - - /** - * @param \DOMElement $node - * - * @return bool - */ - private function isTableOrImageNode(\DOMElement $node): bool - { - return $node->nodeName === 'table' || $node->nodeName === 'img'; - } - - /** - * Parses a shorthand CSS value and splits it into individual values. For example: `padding: 0 auto;` - `0 auto` is - * split into top: 0, left: auto, bottom: 0, right: auto. - * - * @param string $value a CSS property value with 1, 2, 3 or 4 sizes - * - * @return array<string, string> - * an array of values for top, right, bottom and left (using these as associative array keys) - */ - private function parseCssShorthandValue(string $value): array - { - /** @var array<int, string> $values */ - $values = \preg_split('/\\s+/', $value); - - $css = []; - $css['top'] = $values[0]; - $css['right'] = (\count($values) > 1) ? $values[1] : $css['top']; - $css['bottom'] = (\count($values) > 2) ? $values[2] : $css['top']; - $css['left'] = (\count($values) > 3) ? $values[3] : $css['right']; - - return $css; - } -} diff --git a/lib/pelago/emogrifier/src/HtmlProcessor/HtmlNormalizer.php b/lib/pelago/emogrifier/src/HtmlProcessor/HtmlNormalizer.php deleted file mode 100644 index 8572e7b38..000000000 --- a/lib/pelago/emogrifier/src/HtmlProcessor/HtmlNormalizer.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Pelago\Emogrifier\HtmlProcessor; - -/** - * Normalizes HTML: - * - add a document type (HTML5) if missing - * - disentangle incorrectly nested tags - * - add HEAD and BODY elements (if they are missing) - * - reformat the HTML - */ -class HtmlNormalizer extends AbstractHtmlProcessor -{ -} diff --git a/lib/pelago/emogrifier/src/HtmlProcessor/HtmlPruner.php b/lib/pelago/emogrifier/src/HtmlProcessor/HtmlPruner.php deleted file mode 100644 index a7ed2423a..000000000 --- a/lib/pelago/emogrifier/src/HtmlProcessor/HtmlPruner.php +++ /dev/null @@ -1,137 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Pelago\Emogrifier\HtmlProcessor; - -use Pelago\Emogrifier\CssInliner; -use Pelago\Emogrifier\Utilities\ArrayIntersector; - -/** - * This class can remove things from HTML. - */ -class HtmlPruner extends AbstractHtmlProcessor -{ - /** - * We need to look for display:none, but we need to do a case-insensitive search. Since DOMDocument only - * supports XPath 1.0, lower-case() isn't available to us. We've thus far only set attributes to lowercase, - * not attribute values. Consequently, we need to translate() the letters that would be in 'NONE' ("NOE") - * to lowercase. - * - * @var string - */ - private const DISPLAY_NONE_MATCHER - = '//*[@style and contains(translate(translate(@style," ",""),"NOE","noe"),"display:none")' - . ' and not(@class and contains(concat(" ", normalize-space(@class), " "), " -emogrifier-keep "))]'; - - /** - * Removes elements that have a "display: none;" style. - * - * @return self fluent interface - */ - public function removeElementsWithDisplayNone(): self - { - $elementsWithStyleDisplayNone = $this->getXPath()->query(self::DISPLAY_NONE_MATCHER); - if ($elementsWithStyleDisplayNone->length === 0) { - return $this; - } - - foreach ($elementsWithStyleDisplayNone as $element) { - $parentNode = $element->parentNode; - if ($parentNode !== null) { - $parentNode->removeChild($element); - } - } - - return $this; - } - - /** - * Removes classes that are no longer required (e.g. because there are no longer any CSS rules that reference them) - * from `class` attributes. - * - * Note that this does not inspect the CSS, but expects to be provided with a list of classes that are still in use. - * - * This method also has the (presumably beneficial) side-effect of minifying (removing superfluous whitespace from) - * `class` attributes. - * - * @param array<array-key, string> $classesToKeep names of classes that should not be removed - * - * @return self fluent interface - */ - public function removeRedundantClasses(array $classesToKeep = []): self - { - $elementsWithClassAttribute = $this->getXPath()->query('//*[@class]'); - - if ($classesToKeep !== []) { - $this->removeClassesFromElements($elementsWithClassAttribute, $classesToKeep); - } else { - // Avoid unnecessary processing if there are no classes to keep. - $this->removeClassAttributeFromElements($elementsWithClassAttribute); - } - - return $this; - } - - /** - * Removes classes from the `class` attribute of each element in `$elements`, except any in `$classesToKeep`, - * removing the `class` attribute itself if the resultant list is empty. - * - * @param \DOMNodeList $elements - * @param array<array-key, string> $classesToKeep - */ - private function removeClassesFromElements(\DOMNodeList $elements, array $classesToKeep): void - { - $classesToKeepIntersector = new ArrayIntersector($classesToKeep); - - /** @var \DOMElement $element */ - foreach ($elements as $element) { - $elementClasses = \preg_split('/\\s++/', \trim($element->getAttribute('class'))); - $elementClassesToKeep = $classesToKeepIntersector->intersectWith($elementClasses); - if ($elementClassesToKeep !== []) { - $element->setAttribute('class', \implode(' ', $elementClassesToKeep)); - } else { - $element->removeAttribute('class'); - } - } - } - - /** - * Removes the `class` attribute from each element in `$elements`. - * - * @param \DOMNodeList $elements - */ - private function removeClassAttributeFromElements(\DOMNodeList $elements): void - { - /** @var \DOMElement $element */ - foreach ($elements as $element) { - $element->removeAttribute('class'); - } - } - - /** - * After CSS has been inlined, there will likely be some classes in `class` attributes that are no longer referenced - * by any remaining (uninlinable) CSS. This method removes such classes. - * - * Note that it does not inspect the remaining CSS, but uses information readily available from the `CssInliner` - * instance about the CSS rules that could not be inlined. - * - * @param CssInliner $cssInliner object instance that performed the CSS inlining - * - * @return self fluent interface - * - * @throws \BadMethodCallException if `inlineCss` has not first been called on `$cssInliner` - */ - public function removeRedundantClassesAfterCssInlined(CssInliner $cssInliner): self - { - $classesToKeepAsKeys = []; - foreach ($cssInliner->getMatchingUninlinableSelectors() as $selector) { - \preg_match_all('/\\.(-?+[_a-zA-Z][\\w\\-]*+)/', $selector, $matches); - $classesToKeepAsKeys += \array_fill_keys($matches[1], true); - } - - $this->removeRedundantClasses(\array_keys($classesToKeepAsKeys)); - - return $this; - } -} diff --git a/lib/pelago/emogrifier/src/Utilities/ArrayIntersector.php b/lib/pelago/emogrifier/src/Utilities/ArrayIntersector.php deleted file mode 100644 index 72d38ef0c..000000000 --- a/lib/pelago/emogrifier/src/Utilities/ArrayIntersector.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Pelago\Emogrifier\Utilities; - -/** - * When computing many array intersections using the same array, it is more efficient to use `array_flip()` first and - * then `array_intersect_key()`, than `array_intersect()`. See the discussion at - * {@link https://stackoverflow.com/questions/6329211/php-array-intersect-efficiency Stack Overflow} for more - * information. - * - * Of course, this is only possible if the arrays contain integer or string values, and either don't contain duplicates, - * or that fact that duplicates will be removed does not matter. - * - * This class takes care of the detail. - * - * @internal - */ -class ArrayIntersector -{ - /** - * the array with which the object was constructed, with all its keys exchanged with their associated values - * - * @var array<array-key, array-key> - */ - private $invertedArray; - - /** - * Constructs the object with the array that will be reused for many intersection computations. - * - * @param array<array-key, array-key> $array - */ - public function __construct(array $array) - { - $this->invertedArray = \array_flip($array); - } - - /** - * Computes the intersection of `$array` and the array with which this object was constructed. - * - * @param array<array-key, array-key> $array - * - * @return array<array-key, array-key> - * Returns an array containing all of the values in `$array` whose values exist in the array - * with which this object was constructed. Note that keys are preserved, order is maintained, but - * duplicates are removed. - */ - public function intersectWith(array $array): array - { - $invertedArray = \array_flip($array); - - $invertedIntersection = \array_intersect_key($invertedArray, $this->invertedArray); - - return \array_flip($invertedIntersection); - } -} diff --git a/lib/pelago/emogrifier/src/Utilities/CssConcatenator.php b/lib/pelago/emogrifier/src/Utilities/CssConcatenator.php deleted file mode 100644 index 81b55cd50..000000000 --- a/lib/pelago/emogrifier/src/Utilities/CssConcatenator.php +++ /dev/null @@ -1,181 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Pelago\Emogrifier\Utilities; - -/** - * Facilitates building a CSS string by appending rule blocks one at a time, checking whether the media query, - * selectors, or declarations block are the same as those from the preceding block and combining blocks in such cases. - * - * Example: - * $concatenator = new CssConcatenator(); - * $concatenator->append(['body'], 'color: blue;'); - * $concatenator->append(['body'], 'font-size: 16px;'); - * $concatenator->append(['p'], 'margin: 1em 0;'); - * $concatenator->append(['ul', 'ol'], 'margin: 1em 0;'); - * $concatenator->append(['body'], 'font-size: 14px;', '@media screen and (max-width: 400px)'); - * $concatenator->append(['ul', 'ol'], 'margin: 0.75em 0;', '@media screen and (max-width: 400px)'); - * $css = $concatenator->getCss(); - * - * `$css` (if unminified) would contain the following CSS: - * ` body { - * ` color: blue; - * ` font-size: 16px; - * ` } - * ` p, ul, ol { - * ` margin: 1em 0; - * ` } - * ` @media screen and (max-width: 400px) { - * ` body { - * ` font-size: 14px; - * ` } - * ` ul, ol { - * ` margin: 0.75em 0; - * ` } - * ` } - * - * @internal - */ -class CssConcatenator -{ - /** - * Array of media rules in order. Each element is an object with the following properties: - * - string `media` - The media query string, e.g. "@media screen and (max-width:639px)", or an empty string for - * rules not within a media query block; - * - object[] `ruleBlocks` - Array of rule blocks in order, where each element is an object with the following - * properties: - * - mixed[] `selectorsAsKeys` - Array whose keys are selectors for the rule block (values are of no - * significance); - * - string `declarationsBlock` - The property declarations, e.g. "margin-top: 0.5em; padding: 0". - * - * @var array<int, object{ - * media: string, - * ruleBlocks: array<int, object{ - * selectorsAsKeys: array<string, array-key>, - * declarationsBlock: string - * }> - * }> - */ - private $mediaRules = []; - - /** - * Appends a declaration block to the CSS. - * - * @param array<array-key, string> $selectors - * array of selectors for the rule, e.g. ["ul", "ol", "p:first-child"] - * @param string $declarationsBlock - * the property declarations, e.g. "margin-top: 0.5em; padding: 0" - * @param string $media - * the media query for the rule, e.g. "@media screen and (max-width:639px)", or an empty string if none - */ - public function append(array $selectors, string $declarationsBlock, string $media = ''): void - { - $selectorsAsKeys = \array_flip($selectors); - - $mediaRule = $this->getOrCreateMediaRuleToAppendTo($media); - $ruleBlocks = $mediaRule->ruleBlocks; - $lastRuleBlock = \end($ruleBlocks); - - $hasSameDeclarationsAsLastRule = \is_object($lastRuleBlock) - && $declarationsBlock === $lastRuleBlock->declarationsBlock; - if ($hasSameDeclarationsAsLastRule) { - $lastRuleBlock->selectorsAsKeys += $selectorsAsKeys; - } else { - $lastRuleBlockSelectors = \is_object($lastRuleBlock) ? $lastRuleBlock->selectorsAsKeys : []; - $hasSameSelectorsAsLastRule = \is_object($lastRuleBlock) - && self::hasEquivalentSelectors($selectorsAsKeys, $lastRuleBlockSelectors); - if ($hasSameSelectorsAsLastRule) { - $lastDeclarationsBlockWithoutSemicolon = \rtrim(\rtrim($lastRuleBlock->declarationsBlock), ';'); - $lastRuleBlock->declarationsBlock = $lastDeclarationsBlockWithoutSemicolon . ';' . $declarationsBlock; - } else { - $mediaRule->ruleBlocks[] = (object)\compact('selectorsAsKeys', 'declarationsBlock'); - } - } - } - - /** - * @return string - */ - public function getCss(): string - { - return \implode('', \array_map([self::class, 'getMediaRuleCss'], $this->mediaRules)); - } - - /** - * @param string $media The media query for rules to be appended, e.g. "@media screen and (max-width:639px)", - * or an empty string if none. - * - * @return object{ - * media: string, - * ruleBlocks: array<int, object{ - * selectorsAsKeys: array<string, array-key>, - * declarationsBlock: string - * }> - * } - */ - private function getOrCreateMediaRuleToAppendTo(string $media): object - { - $lastMediaRule = \end($this->mediaRules); - if (\is_object($lastMediaRule) && $media === $lastMediaRule->media) { - return $lastMediaRule; - } - - $newMediaRule = (object)[ - 'media' => $media, - 'ruleBlocks' => [], - ]; - $this->mediaRules[] = $newMediaRule; - return $newMediaRule; - } - - /** - * Tests if two sets of selectors are equivalent (i.e. the same selectors, possibly in a different order). - * - * @param array<string, array-key> $selectorsAsKeys1 - * array in which the selectors are the keys, and the values are of no significance - * @param array<string, array-key> $selectorsAsKeys2 another such array - * - * @return bool - */ - private static function hasEquivalentSelectors(array $selectorsAsKeys1, array $selectorsAsKeys2): bool - { - return \count($selectorsAsKeys1) === \count($selectorsAsKeys2) - && \count($selectorsAsKeys1) === \count($selectorsAsKeys1 + $selectorsAsKeys2); - } - - /** - * @param object{ - * media: string, - * ruleBlocks: array<int, object{ - * selectorsAsKeys: array<string, array-key>, - * declarationsBlock: string - * }> - * } $mediaRule - * - * @return string CSS for the media rule. - */ - private static function getMediaRuleCss(object $mediaRule): string - { - $ruleBlocks = $mediaRule->ruleBlocks; - $css = \implode('', \array_map([self::class, 'getRuleBlockCss'], $ruleBlocks)); - $media = $mediaRule->media; - if ($media !== '') { - $css = $media . '{' . $css . '}'; - } - return $css; - } - - /** - * @param object{selectorsAsKeys: array<string, array-key>, declarationsBlock: string} $ruleBlock - * - * @return string CSS for the rule block. - */ - private static function getRuleBlockCss(object $ruleBlock): string - { - $selectorsAsKeys = $ruleBlock->selectorsAsKeys; - $selectors = \array_keys($selectorsAsKeys); - $declarationsBlock = $ruleBlock->declarationsBlock; - return \implode(',', $selectors) . '{' . $declarationsBlock . '}'; - } -} diff --git a/lib/psr/cache/CHANGELOG.md b/lib/psr/cache/CHANGELOG.md deleted file mode 100644 index 58ddab05a..000000000 --- a/lib/psr/cache/CHANGELOG.md +++ /dev/null @@ -1,16 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file, in reverse chronological order by release. - -## 1.0.1 - 2016-08-06 - -### Fixed - -- Make spacing consistent in phpdoc annotations php-fig/cache#9 - chalasr -- Fix grammar in phpdoc annotations php-fig/cache#10 - chalasr -- Be more specific in docblocks that `getItems()` and `deleteItems()` take an array of strings (`string[]`) compared to just `array` php-fig/cache#8 - GrahamCampbell -- For `expiresAt()` and `expiresAfter()` in CacheItemInterface fix docblock to specify null as a valid parameters as well as an implementation of DateTimeInterface php-fig/cache#7 - GrahamCampbell - -## 1.0.0 - 2015-12-11 - -Initial stable release; reflects accepted PSR-6 specification diff --git a/lib/psr/cache/LICENSE.txt b/lib/psr/cache/LICENSE.txt deleted file mode 100644 index b1c2c97b9..000000000 --- a/lib/psr/cache/LICENSE.txt +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2015 PHP Framework Interoperability Group - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/lib/psr/cache/README.md b/lib/psr/cache/README.md deleted file mode 100644 index c8706ceea..000000000 --- a/lib/psr/cache/README.md +++ /dev/null @@ -1,9 +0,0 @@ -PSR Cache -========= - -This repository holds all interfaces defined by -[PSR-6](http://www.php-fig.org/psr/psr-6/). - -Note that this is not a Cache implementation of its own. It is merely an -interface that describes a Cache implementation. See the specification for more -details. diff --git a/lib/psr/cache/composer.json b/lib/psr/cache/composer.json deleted file mode 100644 index e828fec94..000000000 --- a/lib/psr/cache/composer.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "psr/cache", - "description": "Common interface for caching libraries", - "keywords": ["psr", "psr-6", "cache"], - "license": "MIT", - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "require": { - "php": ">=5.3.0" - }, - "autoload": { - "psr-4": { - "Psr\\Cache\\": "src/" - } - }, - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - } -} diff --git a/lib/psr/cache/src/CacheException.php b/lib/psr/cache/src/CacheException.php deleted file mode 100644 index e27f22f8d..000000000 --- a/lib/psr/cache/src/CacheException.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php - -namespace Psr\Cache; - -/** - * Exception interface for all exceptions thrown by an Implementing Library. - */ -interface CacheException -{ -} diff --git a/lib/psr/cache/src/CacheItemInterface.php b/lib/psr/cache/src/CacheItemInterface.php deleted file mode 100644 index 63d05dd1f..000000000 --- a/lib/psr/cache/src/CacheItemInterface.php +++ /dev/null @@ -1,105 +0,0 @@ -<?php - -namespace Psr\Cache; - -/** - * CacheItemInterface defines an interface for interacting with objects inside a cache. - * - * Each Item object MUST be associated with a specific key, which can be set - * according to the implementing system and is typically passed by the - * Cache\CacheItemPoolInterface object. - * - * The Cache\CacheItemInterface object encapsulates the storage and retrieval of - * cache items. Each Cache\CacheItemInterface is generated by a - * Cache\CacheItemPoolInterface object, which is responsible for any required - * setup as well as associating the object with a unique Key. - * Cache\CacheItemInterface objects MUST be able to store and retrieve any type - * of PHP value defined in the Data section of the specification. - * - * Calling Libraries MUST NOT instantiate Item objects themselves. They may only - * be requested from a Pool object via the getItem() method. Calling Libraries - * SHOULD NOT assume that an Item created by one Implementing Library is - * compatible with a Pool from another Implementing Library. - */ -interface CacheItemInterface -{ - /** - * Returns the key for the current cache item. - * - * The key is loaded by the Implementing Library, but should be available to - * the higher level callers when needed. - * - * @return string - * The key string for this cache item. - */ - public function getKey(); - - /** - * Retrieves the value of the item from the cache associated with this object's key. - * - * The value returned must be identical to the value originally stored by set(). - * - * If isHit() returns false, this method MUST return null. Note that null - * is a legitimate cached value, so the isHit() method SHOULD be used to - * differentiate between "null value was found" and "no value was found." - * - * @return mixed - * The value corresponding to this cache item's key, or null if not found. - */ - public function get(); - - /** - * Confirms if the cache item lookup resulted in a cache hit. - * - * Note: This method MUST NOT have a race condition between calling isHit() - * and calling get(). - * - * @return bool - * True if the request resulted in a cache hit. False otherwise. - */ - public function isHit(); - - /** - * Sets the value represented by this cache item. - * - * The $value argument may be any item that can be serialized by PHP, - * although the method of serialization is left up to the Implementing - * Library. - * - * @param mixed $value - * The serializable value to be stored. - * - * @return static - * The invoked object. - */ - public function set($value); - - /** - * Sets the expiration time for this cache item. - * - * @param \DateTimeInterface|null $expiration - * The point in time after which the item MUST be considered expired. - * If null is passed explicitly, a default value MAY be used. If none is set, - * the value should be stored permanently or for as long as the - * implementation allows. - * - * @return static - * The called object. - */ - public function expiresAt($expiration); - - /** - * Sets the expiration time for this cache item. - * - * @param int|\DateInterval|null $time - * The period of time from the present after which the item MUST be considered - * expired. An integer parameter is understood to be the time in seconds until - * expiration. If null is passed explicitly, a default value MAY be used. - * If none is set, the value should be stored permanently or for as long as the - * implementation allows. - * - * @return static - * The called object. - */ - public function expiresAfter($time); -} diff --git a/lib/psr/cache/src/CacheItemPoolInterface.php b/lib/psr/cache/src/CacheItemPoolInterface.php deleted file mode 100644 index 035141967..000000000 --- a/lib/psr/cache/src/CacheItemPoolInterface.php +++ /dev/null @@ -1,138 +0,0 @@ -<?php - -namespace Psr\Cache; - -/** - * CacheItemPoolInterface generates CacheItemInterface objects. - * - * The primary purpose of Cache\CacheItemPoolInterface is to accept a key from - * the Calling Library and return the associated Cache\CacheItemInterface object. - * It is also the primary point of interaction with the entire cache collection. - * All configuration and initialization of the Pool is left up to an - * Implementing Library. - */ -interface CacheItemPoolInterface -{ - /** - * Returns a Cache Item representing the specified key. - * - * This method must always return a CacheItemInterface object, even in case of - * a cache miss. It MUST NOT return null. - * - * @param string $key - * The key for which to return the corresponding Cache Item. - * - * @throws InvalidArgumentException - * If the $key string is not a legal value a \Psr\Cache\InvalidArgumentException - * MUST be thrown. - * - * @return CacheItemInterface - * The corresponding Cache Item. - */ - public function getItem($key); - - /** - * Returns a traversable set of cache items. - * - * @param string[] $keys - * An indexed array of keys of items to retrieve. - * - * @throws InvalidArgumentException - * If any of the keys in $keys are not a legal value a \Psr\Cache\InvalidArgumentException - * MUST be thrown. - * - * @return array|\Traversable - * A traversable collection of Cache Items keyed by the cache keys of - * each item. A Cache item will be returned for each key, even if that - * key is not found. However, if no keys are specified then an empty - * traversable MUST be returned instead. - */ - public function getItems(array $keys = array()); - - /** - * Confirms if the cache contains specified cache item. - * - * Note: This method MAY avoid retrieving the cached value for performance reasons. - * This could result in a race condition with CacheItemInterface::get(). To avoid - * such situation use CacheItemInterface::isHit() instead. - * - * @param string $key - * The key for which to check existence. - * - * @throws InvalidArgumentException - * If the $key string is not a legal value a \Psr\Cache\InvalidArgumentException - * MUST be thrown. - * - * @return bool - * True if item exists in the cache, false otherwise. - */ - public function hasItem($key); - - /** - * Deletes all items in the pool. - * - * @return bool - * True if the pool was successfully cleared. False if there was an error. - */ - public function clear(); - - /** - * Removes the item from the pool. - * - * @param string $key - * The key to delete. - * - * @throws InvalidArgumentException - * If the $key string is not a legal value a \Psr\Cache\InvalidArgumentException - * MUST be thrown. - * - * @return bool - * True if the item was successfully removed. False if there was an error. - */ - public function deleteItem($key); - - /** - * Removes multiple items from the pool. - * - * @param string[] $keys - * An array of keys that should be removed from the pool. - - * @throws InvalidArgumentException - * If any of the keys in $keys are not a legal value a \Psr\Cache\InvalidArgumentException - * MUST be thrown. - * - * @return bool - * True if the items were successfully removed. False if there was an error. - */ - public function deleteItems(array $keys); - - /** - * Persists a cache item immediately. - * - * @param CacheItemInterface $item - * The cache item to save. - * - * @return bool - * True if the item was successfully persisted. False if there was an error. - */ - public function save(CacheItemInterface $item); - - /** - * Sets a cache item to be persisted later. - * - * @param CacheItemInterface $item - * The cache item to save. - * - * @return bool - * False if the item could not be queued or if a commit was attempted and failed. True otherwise. - */ - public function saveDeferred(CacheItemInterface $item); - - /** - * Persists any deferred cache items. - * - * @return bool - * True if all not-yet-saved items were successfully saved or there were none. False otherwise. - */ - public function commit(); -} diff --git a/lib/psr/cache/src/InvalidArgumentException.php b/lib/psr/cache/src/InvalidArgumentException.php deleted file mode 100644 index be7c6fa0e..000000000 --- a/lib/psr/cache/src/InvalidArgumentException.php +++ /dev/null @@ -1,13 +0,0 @@ -<?php - -namespace Psr\Cache; - -/** - * Exception interface for invalid cache arguments. - * - * Any time an invalid argument is passed into a method it must throw an - * exception class which implements Psr\Cache\InvalidArgumentException. - */ -interface InvalidArgumentException extends CacheException -{ -} diff --git a/lib/psr/container/.gitignore b/lib/psr/container/.gitignore deleted file mode 100644 index b2395aa05..000000000 --- a/lib/psr/container/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -composer.lock -composer.phar -/vendor/ diff --git a/lib/psr/container/LICENSE b/lib/psr/container/LICENSE deleted file mode 100644 index 2877a4894..000000000 --- a/lib/psr/container/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013-2016 container-interop -Copyright (c) 2016 PHP Framework Interoperability Group - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/lib/psr/container/README.md b/lib/psr/container/README.md deleted file mode 100644 index 1b9d9e570..000000000 --- a/lib/psr/container/README.md +++ /dev/null @@ -1,13 +0,0 @@ -Container interface -============== - -This repository holds all interfaces related to [PSR-11 (Container Interface)][psr-url]. - -Note that this is not a Container implementation of its own. It is merely abstractions that describe the components of a Dependency Injection Container. - -The installable [package][package-url] and [implementations][implementation-url] are listed on Packagist. - -[psr-url]: https://www.php-fig.org/psr/psr-11/ -[package-url]: https://packagist.org/packages/psr/container -[implementation-url]: https://packagist.org/providers/psr/container-implementation - diff --git a/lib/psr/container/composer.json b/lib/psr/container/composer.json deleted file mode 100644 index 017f41ea6..000000000 --- a/lib/psr/container/composer.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "psr/container", - "type": "library", - "description": "Common Container Interface (PHP FIG PSR-11)", - "keywords": ["psr", "psr-11", "container", "container-interop", "container-interface"], - "homepage": "https://github.com/php-fig/container", - "license": "MIT", - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "require": { - "php": ">=7.4.0" - }, - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - } -} diff --git a/lib/psr/container/src/ContainerExceptionInterface.php b/lib/psr/container/src/ContainerExceptionInterface.php deleted file mode 100644 index 0f213f2fe..000000000 --- a/lib/psr/container/src/ContainerExceptionInterface.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -namespace Psr\Container; - -use Throwable; - -/** - * Base interface representing a generic exception in a container. - */ -interface ContainerExceptionInterface extends Throwable -{ -} diff --git a/lib/psr/container/src/ContainerInterface.php b/lib/psr/container/src/ContainerInterface.php deleted file mode 100644 index cf8e7fd33..000000000 --- a/lib/psr/container/src/ContainerInterface.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Psr\Container; - -/** - * Describes the interface of a container that exposes methods to read its entries. - */ -interface ContainerInterface -{ - /** - * Finds an entry of the container by its identifier and returns it. - * - * @param string $id Identifier of the entry to look for. - * - * @throws NotFoundExceptionInterface No entry was found for **this** identifier. - * @throws ContainerExceptionInterface Error while retrieving the entry. - * - * @return mixed Entry. - */ - public function get(string $id); - - /** - * Returns true if the container can return an entry for the given identifier. - * Returns false otherwise. - * - * `has($id)` returning true does not mean that `get($id)` will not throw an exception. - * It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface`. - * - * @param string $id Identifier of the entry to look for. - * - * @return bool - */ - public function has(string $id); -} diff --git a/lib/psr/container/src/NotFoundExceptionInterface.php b/lib/psr/container/src/NotFoundExceptionInterface.php deleted file mode 100644 index 650bf464e..000000000 --- a/lib/psr/container/src/NotFoundExceptionInterface.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php - -namespace Psr\Container; - -/** - * No entry was found in the container. - */ -interface NotFoundExceptionInterface extends ContainerExceptionInterface -{ -} diff --git a/lib/psr/event-dispatcher/.editorconfig b/lib/psr/event-dispatcher/.editorconfig deleted file mode 100644 index 164f092d6..000000000 --- a/lib/psr/event-dispatcher/.editorconfig +++ /dev/null @@ -1,15 +0,0 @@ -; This file is for unifying the coding style for different editors and IDEs. -; More information at http://editorconfig.org - -root = true - -[*] -charset = utf-8 -indent_size = 4 -indent_style = space -end_of_line = lf -insert_final_newline = true -trim_trailing_whitespace = true - -[Makefile] -indent_style = tab diff --git a/lib/psr/event-dispatcher/.gitignore b/lib/psr/event-dispatcher/.gitignore deleted file mode 100644 index 3a9875b46..000000000 --- a/lib/psr/event-dispatcher/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/vendor/ -composer.lock diff --git a/lib/psr/event-dispatcher/LICENSE b/lib/psr/event-dispatcher/LICENSE deleted file mode 100644 index 3f1559b2a..000000000 --- a/lib/psr/event-dispatcher/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2018 PHP-FIG - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/lib/psr/event-dispatcher/README.md b/lib/psr/event-dispatcher/README.md deleted file mode 100644 index 294214afb..000000000 --- a/lib/psr/event-dispatcher/README.md +++ /dev/null @@ -1,6 +0,0 @@ -PSR Event Dispatcher -==================== - -This repository holds the interfaces related to [PSR-14](http://www.php-fig.org/psr/psr-14/). - -Note that this is not an Event Dispatcher implementation of its own. It is merely interfaces that describe the components of an Event Dispatcher. See the specification for more details. diff --git a/lib/psr/event-dispatcher/composer.json b/lib/psr/event-dispatcher/composer.json deleted file mode 100644 index 667a71448..000000000 --- a/lib/psr/event-dispatcher/composer.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "psr/event-dispatcher", - "description": "Standard interfaces for event handling.", - "type": "library", - "keywords": ["psr", "psr-14", "events"], - "license": "MIT", - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "require": { - "php": ">=7.2.0" - }, - "autoload": { - "psr-4": { - "Psr\\EventDispatcher\\": "src/" - } - }, - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - } -} diff --git a/lib/psr/event-dispatcher/src/EventDispatcherInterface.php b/lib/psr/event-dispatcher/src/EventDispatcherInterface.php deleted file mode 100644 index 4306fa915..000000000 --- a/lib/psr/event-dispatcher/src/EventDispatcherInterface.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Psr\EventDispatcher; - -/** - * Defines a dispatcher for events. - */ -interface EventDispatcherInterface -{ - /** - * Provide all relevant listeners with an event to process. - * - * @param object $event - * The object to process. - * - * @return object - * The Event that was passed, now modified by listeners. - */ - public function dispatch(object $event); -} diff --git a/lib/psr/event-dispatcher/src/ListenerProviderInterface.php b/lib/psr/event-dispatcher/src/ListenerProviderInterface.php deleted file mode 100644 index bdacb6e9c..000000000 --- a/lib/psr/event-dispatcher/src/ListenerProviderInterface.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Psr\EventDispatcher; - -/** - * Mapper from an event to the listeners that are applicable to that event. - */ -interface ListenerProviderInterface -{ - /** - * @param object $event - * An event for which to return the relevant listeners. - * @return iterable[callable] - * An iterable (array, iterator, or generator) of callables. Each - * callable MUST be type-compatible with $event. - */ - public function getListenersForEvent(object $event) : iterable; -} diff --git a/lib/psr/event-dispatcher/src/StoppableEventInterface.php b/lib/psr/event-dispatcher/src/StoppableEventInterface.php deleted file mode 100644 index 595508164..000000000 --- a/lib/psr/event-dispatcher/src/StoppableEventInterface.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Psr\EventDispatcher; - -/** - * An Event whose processing may be interrupted when the event has been handled. - * - * A Dispatcher implementation MUST check to determine if an Event - * is marked as stopped after each listener is called. If it is then it should - * return immediately without calling any further Listeners. - */ -interface StoppableEventInterface -{ - /** - * Is propagation stopped? - * - * This will typically only be used by the Dispatcher to determine if the - * previous listener halted propagation. - * - * @return bool - * True if the Event is complete and no further listeners should be called. - * False to continue calling listeners. - */ - public function isPropagationStopped() : bool; -} diff --git a/lib/psr/http-client/CHANGELOG.md b/lib/psr/http-client/CHANGELOG.md deleted file mode 100644 index e2dc25f51..000000000 --- a/lib/psr/http-client/CHANGELOG.md +++ /dev/null @@ -1,23 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file, in reverse chronological order by release. - -## 1.0.1 - -Allow installation with PHP 8. No code changes. - -## 1.0.0 - -First stable release. No changes since 0.3.0. - -## 0.3.0 - -Added Interface suffix on exceptions - -## 0.2.0 - -All exceptions are in `Psr\Http\Client` namespace - -## 0.1.0 - -First release diff --git a/lib/psr/http-client/LICENSE b/lib/psr/http-client/LICENSE deleted file mode 100644 index cd5e0020a..000000000 --- a/lib/psr/http-client/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2017 PHP Framework Interoperability Group - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/lib/psr/http-client/README.md b/lib/psr/http-client/README.md deleted file mode 100644 index 84af5c55d..000000000 --- a/lib/psr/http-client/README.md +++ /dev/null @@ -1,12 +0,0 @@ -HTTP Client -=========== - -This repository holds all the common code related to [PSR-18 (HTTP Client)][psr-url]. - -Note that this is not a HTTP Client implementation of its own. It is merely abstractions that describe the components of a HTTP Client. - -The installable [package][package-url] and [implementations][implementation-url] are listed on Packagist. - -[psr-url]: https://www.php-fig.org/psr/psr-18 -[package-url]: https://packagist.org/packages/psr/http-client -[implementation-url]: https://packagist.org/providers/psr/http-client-implementation diff --git a/lib/psr/http-client/composer.json b/lib/psr/http-client/composer.json deleted file mode 100644 index e4cab2f3e..000000000 --- a/lib/psr/http-client/composer.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "psr/http-client", - "description": "Common interface for HTTP clients", - "keywords": ["psr", "psr-18", "http", "http-client"], - "homepage": "https://github.com/php-fig/http-client", - "license": "MIT", - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "require": { - "php": "^7.0 || ^8.0", - "psr/http-message": "^1.0 || ^2.0" - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Client\\": "src/" - } - }, - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - } -} diff --git a/lib/psr/http-client/src/ClientExceptionInterface.php b/lib/psr/http-client/src/ClientExceptionInterface.php deleted file mode 100644 index aa0b9cf14..000000000 --- a/lib/psr/http-client/src/ClientExceptionInterface.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php - -namespace Psr\Http\Client; - -/** - * Every HTTP client related exception MUST implement this interface. - */ -interface ClientExceptionInterface extends \Throwable -{ -} diff --git a/lib/psr/http-client/src/ClientInterface.php b/lib/psr/http-client/src/ClientInterface.php deleted file mode 100644 index ad99fd4b7..000000000 --- a/lib/psr/http-client/src/ClientInterface.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php - -namespace Psr\Http\Client; - -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; - -interface ClientInterface -{ - /** - * Sends a PSR-7 request and returns a PSR-7 response. - * - * @param RequestInterface $request - * - * @return ResponseInterface - * - * @throws \Psr\Http\Client\ClientExceptionInterface If an error happens while processing the request. - */ - public function sendRequest(RequestInterface $request): ResponseInterface; -} diff --git a/lib/psr/http-client/src/NetworkExceptionInterface.php b/lib/psr/http-client/src/NetworkExceptionInterface.php deleted file mode 100644 index 4a11627c7..000000000 --- a/lib/psr/http-client/src/NetworkExceptionInterface.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -namespace Psr\Http\Client; - -use Psr\Http\Message\RequestInterface; - -/** - * Thrown when the request cannot be completed because of network issues. - * - * There is no response object as this exception is thrown when no response has been received. - * - * Example: the target host name can not be resolved or the connection failed. - */ -interface NetworkExceptionInterface extends ClientExceptionInterface -{ - /** - * Returns the request. - * - * The request object MAY be a different object from the one passed to ClientInterface::sendRequest() - * - * @return RequestInterface - */ - public function getRequest(): RequestInterface; -} diff --git a/lib/psr/http-client/src/RequestExceptionInterface.php b/lib/psr/http-client/src/RequestExceptionInterface.php deleted file mode 100644 index b17fc34fd..000000000 --- a/lib/psr/http-client/src/RequestExceptionInterface.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -namespace Psr\Http\Client; - -use Psr\Http\Message\RequestInterface; - -/** - * Exception for when a request failed. - * - * Examples: - * - Request is invalid (e.g. method is missing) - * - Runtime request errors (e.g. the body stream is not seekable) - */ -interface RequestExceptionInterface extends ClientExceptionInterface -{ - /** - * Returns the request. - * - * The request object MAY be a different object from the one passed to ClientInterface::sendRequest() - * - * @return RequestInterface - */ - public function getRequest(): RequestInterface; -} diff --git a/lib/psr/http-factory/LICENSE b/lib/psr/http-factory/LICENSE deleted file mode 100644 index 3f1559b2a..000000000 --- a/lib/psr/http-factory/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2018 PHP-FIG - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/lib/psr/http-factory/README.md b/lib/psr/http-factory/README.md deleted file mode 100644 index bf8913b57..000000000 --- a/lib/psr/http-factory/README.md +++ /dev/null @@ -1,12 +0,0 @@ -HTTP Factories -============== - -This repository holds all interfaces related to [PSR-17 (HTTP Factories)][psr-url]. - -Note that this is not a HTTP Factory implementation of its own. It is merely interfaces that describe the components of a HTTP Factory. - -The installable [package][package-url] and [implementations][implementation-url] are listed on Packagist. - -[psr-url]: https://www.php-fig.org/psr/psr-17/ -[package-url]: https://packagist.org/packages/psr/http-factory -[implementation-url]: https://packagist.org/providers/psr/http-factory-implementation diff --git a/lib/psr/http-factory/composer.json b/lib/psr/http-factory/composer.json deleted file mode 100644 index d1bbddeea..000000000 --- a/lib/psr/http-factory/composer.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "psr/http-factory", - "description": "Common interfaces for PSR-7 HTTP message factories", - "keywords": [ - "psr", - "psr-7", - "psr-17", - "http", - "factory", - "message", - "request", - "response" - ], - "license": "MIT", - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "require": { - "php": ">=7.0.0", - "psr/http-message": "^1.0 || ^2.0" - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - } -} diff --git a/lib/psr/http-factory/src/RequestFactoryInterface.php b/lib/psr/http-factory/src/RequestFactoryInterface.php deleted file mode 100644 index cb39a08bf..000000000 --- a/lib/psr/http-factory/src/RequestFactoryInterface.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php - -namespace Psr\Http\Message; - -interface RequestFactoryInterface -{ - /** - * Create a new request. - * - * @param string $method The HTTP method associated with the request. - * @param UriInterface|string $uri The URI associated with the request. If - * the value is a string, the factory MUST create a UriInterface - * instance based on it. - * - * @return RequestInterface - */ - public function createRequest(string $method, $uri): RequestInterface; -} diff --git a/lib/psr/http-factory/src/ResponseFactoryInterface.php b/lib/psr/http-factory/src/ResponseFactoryInterface.php deleted file mode 100644 index 212562f00..000000000 --- a/lib/psr/http-factory/src/ResponseFactoryInterface.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php - -namespace Psr\Http\Message; - -interface ResponseFactoryInterface -{ - /** - * Create a new response. - * - * @param int $code HTTP status code; defaults to 200 - * @param string $reasonPhrase Reason phrase to associate with status code - * in generated response; if none is provided implementations MAY use - * the defaults as suggested in the HTTP specification. - * - * @return ResponseInterface - */ - public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface; -} diff --git a/lib/psr/http-factory/src/ServerRequestFactoryInterface.php b/lib/psr/http-factory/src/ServerRequestFactoryInterface.php deleted file mode 100644 index 9fe031a8f..000000000 --- a/lib/psr/http-factory/src/ServerRequestFactoryInterface.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -namespace Psr\Http\Message; - -interface ServerRequestFactoryInterface -{ - /** - * Create a new server request. - * - * Note that server-params are taken precisely as given - no parsing/processing - * of the given values is performed, and, in particular, no attempt is made to - * determine the HTTP method or URI, which must be provided explicitly. - * - * @param string $method The HTTP method associated with the request. - * @param UriInterface|string $uri The URI associated with the request. If - * the value is a string, the factory MUST create a UriInterface - * instance based on it. - * @param array $serverParams Array of SAPI parameters with which to seed - * the generated request instance. - * - * @return ServerRequestInterface - */ - public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface; -} diff --git a/lib/psr/http-factory/src/StreamFactoryInterface.php b/lib/psr/http-factory/src/StreamFactoryInterface.php deleted file mode 100644 index 90e3240c4..000000000 --- a/lib/psr/http-factory/src/StreamFactoryInterface.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php - -namespace Psr\Http\Message; - -interface StreamFactoryInterface -{ - /** - * Create a new stream from a string. - * - * The stream SHOULD be created with a temporary resource. - * - * @param string $content String content with which to populate the stream. - * - * @return StreamInterface - */ - public function createStream(string $content = ''): StreamInterface; - - /** - * Create a stream from an existing file. - * - * The file MUST be opened using the given mode, which may be any mode - * supported by the `fopen` function. - * - * The `$filename` MAY be any string supported by `fopen()`. - * - * @param string $filename Filename or stream URI to use as basis of stream. - * @param string $mode Mode with which to open the underlying filename/stream. - * - * @return StreamInterface - * @throws \RuntimeException If the file cannot be opened. - * @throws \InvalidArgumentException If the mode is invalid. - */ - public function createStreamFromFile(string $filename, string $mode = 'r'): StreamInterface; - - /** - * Create a new stream from an existing resource. - * - * The stream MUST be readable and may be writable. - * - * @param resource $resource PHP resource to use as basis of stream. - * - * @return StreamInterface - */ - public function createStreamFromResource($resource): StreamInterface; -} diff --git a/lib/psr/http-factory/src/UploadedFileFactoryInterface.php b/lib/psr/http-factory/src/UploadedFileFactoryInterface.php deleted file mode 100644 index 7db4e30af..000000000 --- a/lib/psr/http-factory/src/UploadedFileFactoryInterface.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -namespace Psr\Http\Message; - -interface UploadedFileFactoryInterface -{ - /** - * Create a new uploaded file. - * - * If a size is not provided it will be determined by checking the size of - * the file. - * - * @see http://php.net/manual/features.file-upload.post-method.php - * @see http://php.net/manual/features.file-upload.errors.php - * - * @param StreamInterface $stream Underlying stream representing the - * uploaded file content. - * @param int $size in bytes - * @param int $error PHP file upload error - * @param string $clientFilename Filename as provided by the client, if any. - * @param string $clientMediaType Media type as provided by the client, if any. - * - * @return UploadedFileInterface - * - * @throws \InvalidArgumentException If the file resource is not readable. - */ - public function createUploadedFile( - StreamInterface $stream, - int $size = null, - int $error = \UPLOAD_ERR_OK, - string $clientFilename = null, - string $clientMediaType = null - ): UploadedFileInterface; -} diff --git a/lib/psr/http-factory/src/UriFactoryInterface.php b/lib/psr/http-factory/src/UriFactoryInterface.php deleted file mode 100644 index 06df0b46a..000000000 --- a/lib/psr/http-factory/src/UriFactoryInterface.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php - -namespace Psr\Http\Message; - -interface UriFactoryInterface -{ - /** - * Create a new URI. - * - * @param string $uri - * - * @return UriInterface - * - * @throws \InvalidArgumentException If the given URI cannot be parsed. - */ - public function createUri(string $uri = ''): UriInterface; -} diff --git a/lib/psr/http-message/CHANGELOG.md b/lib/psr/http-message/CHANGELOG.md deleted file mode 100644 index 74b1ef923..000000000 --- a/lib/psr/http-message/CHANGELOG.md +++ /dev/null @@ -1,36 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file, in reverse chronological order by release. - -## 1.0.1 - 2016-08-06 - -### Added - -- Nothing. - -### Deprecated - -- Nothing. - -### Removed - -- Nothing. - -### Fixed - -- Updated all `@return self` annotation references in interfaces to use - `@return static`, which more closelly follows the semantics of the - specification. -- Updated the `MessageInterface::getHeaders()` return annotation to use the - value `string[][]`, indicating the format is a nested array of strings. -- Updated the `@link` annotation for `RequestInterface::withRequestTarget()` - to point to the correct section of RFC 7230. -- Updated the `ServerRequestInterface::withUploadedFiles()` parameter annotation - to add the parameter name (`$uploadedFiles`). -- Updated a `@throws` annotation for the `UploadedFileInterface::moveTo()` - method to correctly reference the method parameter (it was referencing an - incorrect parameter name previously). - -## 1.0.0 - 2016-05-18 - -Initial stable release; reflects accepted PSR-7 specification. diff --git a/lib/psr/http-message/LICENSE b/lib/psr/http-message/LICENSE deleted file mode 100644 index c2d8e452d..000000000 --- a/lib/psr/http-message/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2014 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/lib/psr/http-message/README.md b/lib/psr/http-message/README.md deleted file mode 100644 index 2668be6c3..000000000 --- a/lib/psr/http-message/README.md +++ /dev/null @@ -1,16 +0,0 @@ -PSR Http Message -================ - -This repository holds all interfaces/classes/traits related to -[PSR-7](http://www.php-fig.org/psr/psr-7/). - -Note that this is not a HTTP message implementation of its own. It is merely an -interface that describes a HTTP message. See the specification for more details. - -Usage ------ - -Before reading the usage guide we recommend reading the PSR-7 interfaces method list: - -* [`PSR-7 Interfaces Method List`](docs/PSR7-Interfaces.md) -* [`PSR-7 Usage Guide`](docs/PSR7-Usage.md) \ No newline at end of file diff --git a/lib/psr/http-message/composer.json b/lib/psr/http-message/composer.json deleted file mode 100644 index c66e5aba4..000000000 --- a/lib/psr/http-message/composer.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "psr/http-message", - "description": "Common interface for HTTP messages", - "keywords": ["psr", "psr-7", "http", "http-message", "request", "response"], - "homepage": "https://github.com/php-fig/http-message", - "license": "MIT", - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "require": { - "php": "^7.2 || ^8.0" - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - } -} diff --git a/lib/psr/http-message/docs/PSR7-Interfaces.md b/lib/psr/http-message/docs/PSR7-Interfaces.md deleted file mode 100644 index 3a7e7dda6..000000000 --- a/lib/psr/http-message/docs/PSR7-Interfaces.md +++ /dev/null @@ -1,130 +0,0 @@ -# Interfaces - -The purpose of this list is to help in finding the methods when working with PSR-7. This can be considered as a cheatsheet for PSR-7 interfaces. - -The interfaces defined in PSR-7 are the following: - -| Class Name | Description | -|---|---| -| [Psr\Http\Message\MessageInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessagemessageinterface) | Representation of a HTTP message | -| [Psr\Http\Message\RequestInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessagerequestinterface) | Representation of an outgoing, client-side request. | -| [Psr\Http\Message\ServerRequestInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessageserverrequestinterface) | Representation of an incoming, server-side HTTP request. | -| [Psr\Http\Message\ResponseInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessageresponseinterface) | Representation of an outgoing, server-side response. | -| [Psr\Http\Message\StreamInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessagestreaminterface) | Describes a data stream | -| [Psr\Http\Message\UriInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessageuriinterface) | Value object representing a URI. | -| [Psr\Http\Message\UploadedFileInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessageuploadedfileinterface) | Value object representing a file uploaded through an HTTP request. | - -## `Psr\Http\Message\MessageInterface` Methods - -| Method Name | Description | Notes | -|------------------------------------| ----------- | ----- | -| `getProtocolVersion()` | Retrieve HTTP protocol version | 1.0 or 1.1 | -| `withProtocolVersion($version)` | Returns new message instance with given HTTP protocol version | | -| `getHeaders()` | Retrieve all HTTP Headers | [Request Header List](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Request_fields), [Response Header List](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Response_fields) | -| `hasHeader($name)` | Checks if HTTP Header with given name exists | | -| `getHeader($name)` | Retrieves a array with the values for a single header | | -| `getHeaderLine($name)` | Retrieves a comma-separated string of the values for a single header | | -| `withHeader($name, $value)` | Returns new message instance with given HTTP Header | if the header existed in the original instance, replaces the header value from the original message with the value provided when creating the new instance. | -| `withAddedHeader($name, $value)` | Returns new message instance with appended value to given header | If header already exists value will be appended, if not a new header will be created | -| `withoutHeader($name)` | Removes HTTP Header with given name| | -| `getBody()` | Retrieves the HTTP Message Body | Returns object implementing `StreamInterface`| -| `withBody(StreamInterface $body)` | Returns new message instance with given HTTP Message Body | | - - -## `Psr\Http\Message\RequestInterface` Methods - -Same methods as `Psr\Http\Message\MessageInterface` + the following methods: - -| Method Name | Description | Notes | -|------------------------------------| ----------- | ----- | -| `getRequestTarget()` | Retrieves the message's request target | origin-form, absolute-form, authority-form, asterisk-form ([RFC7230](https://www.rfc-editor.org/rfc/rfc7230.txt)) | -| `withRequestTarget($requestTarget)` | Return a new message instance with the specific request-target | | -| `getMethod()` | Retrieves the HTTP method of the request. | GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE (defined in [RFC7231](https://tools.ietf.org/html/rfc7231)), PATCH (defined in [RFC5789](https://tools.ietf.org/html/rfc5789)) | -| `withMethod($method)` | Returns a new message instance with the provided HTTP method | | -| `getUri()` | Retrieves the URI instance | | -| `withUri(UriInterface $uri, $preserveHost = false)` | Returns a new message instance with the provided URI | | - - -## `Psr\Http\Message\ServerRequestInterface` Methods - -Same methods as `Psr\Http\Message\RequestInterface` + the following methods: - -| Method Name | Description | Notes | -|------------------------------------| ----------- | ----- | -| `getServerParams() ` | Retrieve server parameters | Typically derived from `$_SERVER` | -| `getCookieParams()` | Retrieves cookies sent by the client to the server. | Typically derived from `$_COOKIES` | -| `withCookieParams(array $cookies)` | Returns a new request instance with the specified cookies | | -| `withQueryParams(array $query)` | Returns a new request instance with the specified query string arguments | | -| `getUploadedFiles()` | Retrieve normalized file upload data | | -| `withUploadedFiles(array $uploadedFiles)` | Returns a new request instance with the specified uploaded files | | -| `getParsedBody()` | Retrieve any parameters provided in the request body | | -| `withParsedBody($data)` | Returns a new request instance with the specified body parameters | | -| `getAttributes()` | Retrieve attributes derived from the request | | -| `getAttribute($name, $default = null)` | Retrieve a single derived request attribute | | -| `withAttribute($name, $value)` | Returns a new request instance with the specified derived request attribute | | -| `withoutAttribute($name)` | Returns a new request instance that without the specified derived request attribute | | - -## `Psr\Http\Message\ResponseInterface` Methods: - -Same methods as `Psr\Http\Message\MessageInterface` + the following methods: - -| Method Name | Description | Notes | -|------------------------------------| ----------- | ----- | -| `getStatusCode()` | Gets the response status code. | | -| `withStatus($code, $reasonPhrase = '')` | Returns a new response instance with the specified status code and, optionally, reason phrase. | | -| `getReasonPhrase()` | Gets the response reason phrase associated with the status code. | | - -## `Psr\Http\Message\StreamInterface` Methods - -| Method Name | Description | Notes | -|------------------------------------| ----------- | ----- | -| `__toString()` | Reads all data from the stream into a string, from the beginning to end. | | -| `close()` | Closes the stream and any underlying resources. | | -| `detach()` | Separates any underlying resources from the stream. | | -| `getSize()` | Get the size of the stream if known. | | -| `eof()` | Returns true if the stream is at the end of the stream.| | -| `isSeekable()` | Returns whether or not the stream is seekable. | | -| `seek($offset, $whence = SEEK_SET)` | Seek to a position in the stream. | | -| `rewind()` | Seek to the beginning of the stream. | | -| `isWritable()` | Returns whether or not the stream is writable. | | -| `write($string)` | Write data to the stream. | | -| `isReadable()` | Returns whether or not the stream is readable. | | -| `read($length)` | Read data from the stream. | | -| `getContents()` | Returns the remaining contents in a string | | -| `getMetadata($key = null)()` | Get stream metadata as an associative array or retrieve a specific key. | | - -## `Psr\Http\Message\UriInterface` Methods - -| Method Name | Description | Notes | -|------------------------------------| ----------- | ----- | -| `getScheme()` | Retrieve the scheme component of the URI. | | -| `getAuthority()` | Retrieve the authority component of the URI. | | -| `getUserInfo()` | Retrieve the user information component of the URI. | | -| `getHost()` | Retrieve the host component of the URI. | | -| `getPort()` | Retrieve the port component of the URI. | | -| `getPath()` | Retrieve the path component of the URI. | | -| `getQuery()` | Retrieve the query string of the URI. | | -| `getFragment()` | Retrieve the fragment component of the URI. | | -| `withScheme($scheme)` | Return an instance with the specified scheme. | | -| `withUserInfo($user, $password = null)` | Return an instance with the specified user information. | | -| `withHost($host)` | Return an instance with the specified host. | | -| `withPort($port)` | Return an instance with the specified port. | | -| `withPath($path)` | Return an instance with the specified path. | | -| `withQuery($query)` | Return an instance with the specified query string. | | -| `withFragment($fragment)` | Return an instance with the specified URI fragment. | | -| `__toString()` | Return the string representation as a URI reference. | | - -## `Psr\Http\Message\UploadedFileInterface` Methods - -| Method Name | Description | Notes | -|------------------------------------| ----------- | ----- | -| `getStream()` | Retrieve a stream representing the uploaded file. | | -| `moveTo($targetPath)` | Move the uploaded file to a new location. | | -| `getSize()` | Retrieve the file size. | | -| `getError()` | Retrieve the error associated with the uploaded file. | | -| `getClientFilename()` | Retrieve the filename sent by the client. | | -| `getClientMediaType()` | Retrieve the media type sent by the client. | | - -> `RequestInterface`, `ServerRequestInterface`, `ResponseInterface` extend `MessageInterface` because the `Request` and the `Response` are `HTTP Messages`. -> When using `ServerRequestInterface`, both `RequestInterface` and `Psr\Http\Message\MessageInterface` methods are considered. - diff --git a/lib/psr/http-message/docs/PSR7-Usage.md b/lib/psr/http-message/docs/PSR7-Usage.md deleted file mode 100644 index b6d048a34..000000000 --- a/lib/psr/http-message/docs/PSR7-Usage.md +++ /dev/null @@ -1,159 +0,0 @@ -### PSR-7 Usage - -All PSR-7 applications comply with these interfaces -They were created to establish a standard between middleware implementations. - -> `RequestInterface`, `ServerRequestInterface`, `ResponseInterface` extend `MessageInterface` because the `Request` and the `Response` are `HTTP Messages`. -> When using `ServerRequestInterface`, both `RequestInterface` and `Psr\Http\Message\MessageInterface` methods are considered. - - -The following examples will illustrate how basic operations are done in PSR-7. - -##### Examples - - -For this examples to work (at least) a PSR-7 implementation package is required. (eg: zendframework/zend-diactoros, guzzlehttp/psr7, slim/slim, etc) -All PSR-7 implementations should have the same behaviour. - -The following will be assumed: -`$request` is an object of `Psr\Http\Message\RequestInterface` and - -`$response` is an object implementing `Psr\Http\Message\RequestInterface` - - -### Working with HTTP Headers - -#### Adding headers to response: - -```php -$response->withHeader('My-Custom-Header', 'My Custom Message'); -``` - -#### Appending values to headers - -```php -$response->withAddedHeader('My-Custom-Header', 'The second message'); -``` - -#### Checking if header exists: - -```php -$request->hasHeader('My-Custom-Header'); // will return false -$response->hasHeader('My-Custom-Header'); // will return true -``` - -> Note: My-Custom-Header was only added in the Response - -#### Getting comma-separated values from a header (also applies to request) - -```php -// getting value from request headers -$request->getHeaderLine('Content-Type'); // will return: "text/html; charset=UTF-8" -// getting value from response headers -$response->getHeaderLine('My-Custom-Header'); // will return: "My Custom Message; The second message" -``` - -#### Getting array of value from a header (also applies to request) -```php -// getting value from request headers -$request->getHeader('Content-Type'); // will return: ["text/html", "charset=UTF-8"] -// getting value from response headers -$response->getHeader('My-Custom-Header'); // will return: ["My Custom Message", "The second message"] -``` - -#### Removing headers from HTTP Messages -```php -// removing a header from Request, removing deprecated "Content-MD5" header -$request->withoutHeader('Content-MD5'); - -// removing a header from Response -// effect: the browser won't know the size of the stream -// the browser will download the stream till it ends -$response->withoutHeader('Content-Length'); -``` - -### Working with HTTP Message Body - -When working with the PSR-7 there are two methods of implementation: -#### 1. Getting the body separately - -> This method makes the body handling easier to understand and is useful when repeatedly calling body methods. (You only call `getBody()` once). Using this method mistakes like `$response->write()` are also prevented. - -```php -$body = $response->getBody(); -// operations on body, eg. read, write, seek -// ... -// replacing the old body -$response->withBody($body); -// this last statement is optional as we working with objects -// in this case the "new" body is same with the "old" one -// the $body variable has the same value as the one in $request, only the reference is passed -``` - -#### 2. Working directly on response - -> This method is useful when only performing few operations as the `$request->getBody()` statement fragment is required - -```php -$response->getBody()->write('hello'); -``` - -### Getting the body contents - -The following snippet gets the contents of a stream contents. -> Note: Streams must be rewinded, if content was written into streams, it will be ignored when calling `getContents()` because the stream pointer is set to the last character, which is `\0` - meaning end of stream. -```php -$body = $response->getBody(); -$body->rewind(); // or $body->seek(0); -$bodyText = $body->getContents(); -``` -> Note: If `$body->seek(1)` is called before `$body->getContents()`, the first character will be ommited as the starting pointer is set to `1`, not `0`. This is why using `$body->rewind()` is recommended. - -### Append to body - -```php -$response->getBody()->write('Hello'); // writing directly -$body = $request->getBody(); // which is a `StreamInterface` -$body->write('xxxxx'); -``` - -### Prepend to body -Prepending is different when it comes to streams. The content must be copied before writing the content to be prepended. -The following example will explain the behaviour of streams. - -```php -// assuming our response is initially empty -$body = $repsonse->getBody(); -// writing the string "abcd" -$body->write('abcd'); - -// seeking to start of stream -$body->seek(0); -// writing 'ef' -$body->write('ef'); // at this point the stream contains "efcd" -``` - -#### Prepending by rewriting separately - -```php -// assuming our response body stream only contains: "abcd" -$body = $response->getBody(); -$body->rewind(); -$contents = $body->getContents(); // abcd -// seeking the stream to beginning -$body->rewind(); -$body->write('ef'); // stream contains "efcd" -$body->write($contents); // stream contains "efabcd" -``` - -> Note: `getContents()` seeks the stream while reading it, therefore if the second `rewind()` method call was not present the stream would have resulted in `abcdefabcd` because the `write()` method appends to stream if not preceeded by `rewind()` or `seek(0)`. - -#### Prepending by using contents as a string -```php -$body = $response->getBody(); -$body->rewind(); -$contents = $body->getContents(); // efabcd -$contents = 'ef'.$contents; -$body->rewind(); -$body->write($contents); -``` diff --git a/lib/psr/http-message/src/MessageInterface.php b/lib/psr/http-message/src/MessageInterface.php deleted file mode 100644 index a83c98518..000000000 --- a/lib/psr/http-message/src/MessageInterface.php +++ /dev/null @@ -1,187 +0,0 @@ -<?php - -namespace Psr\Http\Message; - -/** - * HTTP messages consist of requests from a client to a server and responses - * from a server to a client. This interface defines the methods common to - * each. - * - * Messages are considered immutable; all methods that might change state MUST - * be implemented such that they retain the internal state of the current - * message and return an instance that contains the changed state. - * - * @link http://www.ietf.org/rfc/rfc7230.txt - * @link http://www.ietf.org/rfc/rfc7231.txt - */ -interface MessageInterface -{ - /** - * Retrieves the HTTP protocol version as a string. - * - * The string MUST contain only the HTTP version number (e.g., "1.1", "1.0"). - * - * @return string HTTP protocol version. - */ - public function getProtocolVersion(): string; - - /** - * Return an instance with the specified HTTP protocol version. - * - * The version string MUST contain only the HTTP version number (e.g., - * "1.1", "1.0"). - * - * 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 protocol version. - * - * @param string $version HTTP protocol version - * @return static - */ - public function withProtocolVersion(string $version): MessageInterface; - - /** - * Retrieves all message header values. - * - * The keys represent the header name as it will be sent over the wire, and - * each value is an array of strings associated with the header. - * - * // Represent the headers as a string - * foreach ($message->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(): array; - - /** - * 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): bool; - - /** - * 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): array; - - /** - * 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): string; - - /** - * 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): MessageInterface; - - /** - * 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): MessageInterface; - - /** - * 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): MessageInterface; - - /** - * Gets the body of the message. - * - * @return StreamInterface Returns the body as a stream. - */ - public function getBody(): StreamInterface; - - /** - * 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): MessageInterface; -} diff --git a/lib/psr/http-message/src/RequestInterface.php b/lib/psr/http-message/src/RequestInterface.php deleted file mode 100644 index 33f85e559..000000000 --- a/lib/psr/http-message/src/RequestInterface.php +++ /dev/null @@ -1,130 +0,0 @@ -<?php - -namespace Psr\Http\Message; - -/** - * Representation of an outgoing, client-side request. - * - * Per the HTTP specification, this interface includes properties for - * each of the following: - * - * - Protocol version - * - HTTP method - * - URI - * - Headers - * - Message body - * - * During construction, implementations MUST attempt to set the Host header from - * a provided URI if no Host header is provided. - * - * Requests are considered immutable; all methods that might change state MUST - * be implemented such that they retain the internal state of the current - * message and return an instance that contains the changed state. - */ -interface RequestInterface extends MessageInterface -{ - /** - * Retrieves the message's request target. - * - * Retrieves the message's request-target either as it will appear (for - * clients), as it appeared at request (for servers), or as it was - * specified for the instance (see withRequestTarget()). - * - * In most cases, this will be the origin-form of the composed URI, - * unless a value was provided to the concrete implementation (see - * withRequestTarget() below). - * - * If no URI is available, and no request-target has been specifically - * provided, this method MUST return the string "/". - * - * @return string - */ - public function getRequestTarget(): string; - - /** - * Return an instance with the specific request-target. - * - * If the request needs a non-origin-form request-target — e.g., for - * specifying an absolute-form, authority-form, or asterisk-form — - * this method may be used to create an instance with the specified - * request-target, verbatim. - * - * 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 - * changed request target. - * - * @link http://tools.ietf.org/html/rfc7230#section-5.3 (for the various - * request-target forms allowed in request messages) - * @param string $requestTarget - * @return static - */ - public function withRequestTarget(string $requestTarget): RequestInterface; - - - /** - * Retrieves the HTTP method of the request. - * - * @return string Returns the request method. - */ - public function getMethod(): string; - - /** - * Return an instance with the provided HTTP method. - * - * While HTTP method names are typically all uppercase characters, HTTP - * method names are case-sensitive and thus implementations SHOULD NOT - * modify the given string. - * - * 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 - * changed request method. - * - * @param string $method Case-sensitive method. - * @return static - * @throws \InvalidArgumentException for invalid HTTP methods. - */ - public function withMethod(string $method): RequestInterface; - - /** - * Retrieves the URI instance. - * - * This method MUST return a UriInterface instance. - * - * @link http://tools.ietf.org/html/rfc3986#section-4.3 - * @return UriInterface Returns a UriInterface instance - * representing the URI of the request. - */ - public function getUri(): UriInterface; - - /** - * Returns an instance with the provided URI. - * - * This method MUST update the Host header of the returned request by - * default if the URI contains a host component. If the URI does not - * contain a host component, any pre-existing Host header MUST be carried - * over to the returned request. - * - * You can opt-in to preserving the original state of the Host header by - * setting `$preserveHost` to `true`. When `$preserveHost` is set to - * `true`, this method interacts with the Host header in the following ways: - * - * - If the Host header is missing or empty, and the new URI contains - * a host component, this method MUST update the Host header in the returned - * request. - * - If the Host header is missing or empty, and the new URI does not contain a - * host component, this method MUST NOT update the Host header in the returned - * request. - * - If a Host header is present and non-empty, this method MUST NOT update - * the Host header in the returned request. - * - * 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 UriInterface instance. - * - * @link http://tools.ietf.org/html/rfc3986#section-4.3 - * @param UriInterface $uri New request URI to use. - * @param bool $preserveHost Preserve the original state of the Host header. - * @return static - */ - public function withUri(UriInterface $uri, bool $preserveHost = false): RequestInterface; -} diff --git a/lib/psr/http-message/src/ResponseInterface.php b/lib/psr/http-message/src/ResponseInterface.php deleted file mode 100644 index e9299a914..000000000 --- a/lib/psr/http-message/src/ResponseInterface.php +++ /dev/null @@ -1,68 +0,0 @@ -<?php - -namespace Psr\Http\Message; - -/** - * Representation of an outgoing, server-side response. - * - * Per the HTTP specification, this interface includes properties for - * each of the following: - * - * - Protocol version - * - Status code and reason phrase - * - Headers - * - Message body - * - * Responses are considered immutable; all methods that might change state MUST - * be implemented such that they retain the internal state of the current - * message and return an instance that contains the changed state. - */ -interface ResponseInterface extends MessageInterface -{ - /** - * Gets the response status code. - * - * The status code is a 3-digit integer result code of the server's attempt - * to understand and satisfy the request. - * - * @return int Status code. - */ - public function getStatusCode(): int; - - /** - * Return an instance with the specified status code and, optionally, reason phrase. - * - * If no reason phrase is specified, implementations MAY choose to default - * to the RFC 7231 or IANA recommended reason phrase for the response's - * status code. - * - * 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 status and reason phrase. - * - * @link http://tools.ietf.org/html/rfc7231#section-6 - * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml - * @param int $code The 3-digit integer result code to set. - * @param string $reasonPhrase The reason phrase to use with the - * provided status code; if none is provided, implementations MAY - * use the defaults as suggested in the HTTP specification. - * @return static - * @throws \InvalidArgumentException For invalid status code arguments. - */ - public function withStatus(int $code, string $reasonPhrase = ''): ResponseInterface; - - /** - * Gets the response reason phrase associated with the status code. - * - * Because a reason phrase is not a required element in a response - * status line, the reason phrase value MAY be null. Implementations MAY - * choose to return the default RFC 7231 recommended reason phrase (or those - * listed in the IANA HTTP Status Code Registry) for the response's - * status code. - * - * @link http://tools.ietf.org/html/rfc7231#section-6 - * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml - * @return string Reason phrase; must return an empty string if none present. - */ - public function getReasonPhrase(): string; -} diff --git a/lib/psr/http-message/src/ServerRequestInterface.php b/lib/psr/http-message/src/ServerRequestInterface.php deleted file mode 100644 index 8625d0e10..000000000 --- a/lib/psr/http-message/src/ServerRequestInterface.php +++ /dev/null @@ -1,261 +0,0 @@ -<?php - -namespace Psr\Http\Message; - -/** - * Representation of an incoming, server-side HTTP request. - * - * Per the HTTP specification, this interface includes properties for - * each of the following: - * - * - Protocol version - * - HTTP method - * - URI - * - Headers - * - Message body - * - * Additionally, it encapsulates all data as it has arrived to the - * application from the CGI and/or PHP environment, including: - * - * - The values represented in $_SERVER. - * - Any cookies provided (generally via $_COOKIE) - * - Query string arguments (generally via $_GET, or as parsed via parse_str()) - * - Upload files, if any (as represented by $_FILES) - * - Deserialized body parameters (generally from $_POST) - * - * $_SERVER values MUST be treated as immutable, as they represent application - * state at the time of request; as such, no methods are provided to allow - * modification of those values. The other values provide such methods, as they - * can be restored from $_SERVER or the request body, and may need treatment - * during the application (e.g., body parameters may be deserialized based on - * content type). - * - * Additionally, this interface recognizes the utility of introspecting a - * request to derive and match additional parameters (e.g., via URI path - * matching, decrypting cookie values, deserializing non-form-encoded body - * content, matching authorization headers to users, etc). These parameters - * are stored in an "attributes" property. - * - * Requests are considered immutable; all methods that might change state MUST - * be implemented such that they retain the internal state of the current - * message and return an instance that contains the changed state. - */ -interface ServerRequestInterface extends RequestInterface -{ - /** - * Retrieve server parameters. - * - * Retrieves data related to the incoming request environment, - * typically derived from PHP's $_SERVER superglobal. The data IS NOT - * REQUIRED to originate from $_SERVER. - * - * @return array - */ - public function getServerParams(): array; - - /** - * Retrieve cookies. - * - * Retrieves cookies sent by the client to the server. - * - * The data MUST be compatible with the structure of the $_COOKIE - * superglobal. - * - * @return array - */ - public function getCookieParams(): array; - - /** - * Return an instance with the specified cookies. - * - * The data IS NOT REQUIRED to come from the $_COOKIE superglobal, but MUST - * be compatible with the structure of $_COOKIE. Typically, this data will - * be injected at instantiation. - * - * This method MUST NOT update the related Cookie header of the request - * instance, nor related 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 cookie values. - * - * @param array $cookies Array of key/value pairs representing cookies. - * @return static - */ - public function withCookieParams(array $cookies): ServerRequestInterface; - - /** - * Retrieve query string arguments. - * - * Retrieves the deserialized query string arguments, if any. - * - * Note: the query params might not be in sync with the URI or server - * params. If you need to ensure you are only getting the original - * values, you may need to parse the query string from `getUri()->getQuery()` - * or from the `QUERY_STRING` server param. - * - * @return array - */ - public function getQueryParams(): array; - - /** - * 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): ServerRequestInterface; - - /** - * 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(): array; - - /** - * 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): ServerRequestInterface; - - /** - * 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): ServerRequestInterface; - - /** - * 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(): array; - - /** - * 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): ServerRequestInterface; - - /** - * 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): ServerRequestInterface; -} diff --git a/lib/psr/http-message/src/StreamInterface.php b/lib/psr/http-message/src/StreamInterface.php deleted file mode 100644 index a62aabb82..000000000 --- a/lib/psr/http-message/src/StreamInterface.php +++ /dev/null @@ -1,158 +0,0 @@ -<?php - -namespace Psr\Http\Message; - -/** - * Describes a data stream. - * - * Typically, an instance will wrap a PHP stream; this interface provides - * a wrapper around the most common operations, including serialization of - * the entire stream to a string. - */ -interface StreamInterface -{ - /** - * Reads all data from the stream into a string, from the beginning to end. - * - * This method MUST attempt to seek to the beginning of the stream before - * reading data and read the stream until the end is reached. - * - * Warning: This could attempt to load a large amount of data into memory. - * - * This method MUST NOT raise an exception in order to conform with PHP's - * string casting operations. - * - * @see http://php.net/manual/en/language.oop5.magic.php#object.tostring - * @return string - */ - public function __toString(): string; - - /** - * Closes the stream and any underlying resources. - * - * @return void - */ - public function close(): void; - - /** - * Separates any underlying resources from the stream. - * - * After the stream has been detached, the stream is in an unusable state. - * - * @return resource|null Underlying PHP stream, if any - */ - public function detach(); - - /** - * Get the size of the stream if known. - * - * @return int|null Returns the size in bytes if known, or null if unknown. - */ - public function getSize(): ?int; - - /** - * Returns the current position of the file read/write pointer - * - * @return int Position of the file pointer - * @throws \RuntimeException on error. - */ - public function tell(): int; - - /** - * Returns true if the stream is at the end of the stream. - * - * @return bool - */ - public function eof(): bool; - - /** - * Returns whether or not the stream is seekable. - * - * @return bool - */ - public function isSeekable(): bool; - - /** - * Seek to a position in the stream. - * - * @link http://www.php.net/manual/en/function.fseek.php - * @param int $offset Stream offset - * @param int $whence Specifies how the cursor position will be calculated - * based on the seek offset. Valid values are identical to the built-in - * PHP $whence values for `fseek()`. SEEK_SET: Set position equal to - * offset bytes SEEK_CUR: Set position to current location plus offset - * SEEK_END: Set position to end-of-stream plus offset. - * @throws \RuntimeException on failure. - */ - public function seek(int $offset, int $whence = SEEK_SET): void; - - /** - * Seek to the beginning of the stream. - * - * If the stream is not seekable, this method will raise an exception; - * otherwise, it will perform a seek(0). - * - * @see seek() - * @link http://www.php.net/manual/en/function.fseek.php - * @throws \RuntimeException on failure. - */ - public function rewind(): void; - - /** - * Returns whether or not the stream is writable. - * - * @return bool - */ - public function isWritable(): bool; - - /** - * Write data to the stream. - * - * @param string $string The string that is to be written. - * @return int Returns the number of bytes written to the stream. - * @throws \RuntimeException on failure. - */ - public function write(string $string): int; - - /** - * Returns whether or not the stream is readable. - * - * @return bool - */ - public function isReadable(): bool; - - /** - * Read data from the stream. - * - * @param int $length Read up to $length bytes from the object and return - * them. Fewer than $length bytes may be returned if underlying stream - * call returns fewer bytes. - * @return string Returns the data read from the stream, or an empty string - * if no bytes are available. - * @throws \RuntimeException if an error occurs. - */ - public function read(int $length): string; - - /** - * Returns the remaining contents in a string - * - * @return string - * @throws \RuntimeException if unable to read or an error occurs while - * reading. - */ - public function getContents(): string; - - /** - * Get stream metadata as an associative array or retrieve a specific key. - * - * The keys returned are identical to the keys returned from PHP's - * stream_get_meta_data() function. - * - * @link http://php.net/manual/en/function.stream-get-meta-data.php - * @param string|null $key Specific metadata to retrieve. - * @return array|mixed|null Returns an associative array if no key is - * provided. Returns a specific key value if a key is provided and the - * value is found, or null if the key is not found. - */ - public function getMetadata(?string $key = null); -} diff --git a/lib/psr/http-message/src/UploadedFileInterface.php b/lib/psr/http-message/src/UploadedFileInterface.php deleted file mode 100644 index dd19d6538..000000000 --- a/lib/psr/http-message/src/UploadedFileInterface.php +++ /dev/null @@ -1,123 +0,0 @@ -<?php - -namespace Psr\Http\Message; - -/** - * Value object representing a file uploaded through an HTTP request. - * - * Instances of this interface are considered immutable; all methods that - * might change state MUST be implemented such that they retain the internal - * state of the current instance and return an instance that contains the - * changed state. - */ -interface UploadedFileInterface -{ - /** - * Retrieve a stream representing the uploaded file. - * - * This method MUST return a StreamInterface instance, representing the - * uploaded file. The purpose of this method is to allow utilizing native PHP - * stream functionality to manipulate the file upload, such as - * stream_copy_to_stream() (though the result will need to be decorated in a - * native PHP stream wrapper to work with such functions). - * - * If the moveTo() method has been called previously, this method MUST raise - * an exception. - * - * @return StreamInterface Stream representation of the uploaded file. - * @throws \RuntimeException in cases when no stream is available or can be - * created. - */ - public function getStream(): StreamInterface; - - /** - * Move the uploaded file to a new location. - * - * Use this method as an alternative to move_uploaded_file(). This method is - * guaranteed to work in both SAPI and non-SAPI environments. - * Implementations must determine which environment they are in, and use the - * appropriate method (move_uploaded_file(), rename(), or a stream - * operation) to perform the operation. - * - * $targetPath may be an absolute path, or a relative path. If it is a - * relative path, resolution should be the same as used by PHP's rename() - * function. - * - * The original file or stream MUST be removed on completion. - * - * If this method is called more than once, any subsequent calls MUST raise - * an exception. - * - * When used in an SAPI environment where $_FILES is populated, when writing - * files via moveTo(), is_uploaded_file() and move_uploaded_file() SHOULD be - * used to ensure permissions and upload status are verified correctly. - * - * If you wish to move to a stream, use getStream(), as SAPI operations - * cannot guarantee writing to stream destinations. - * - * @see http://php.net/is_uploaded_file - * @see http://php.net/move_uploaded_file - * @param string $targetPath Path to which to move the uploaded file. - * @throws \InvalidArgumentException if the $targetPath specified is invalid. - * @throws \RuntimeException on any error during the move operation, or on - * the second or subsequent call to the method. - */ - public function moveTo(string $targetPath): void; - - /** - * Retrieve the file size. - * - * Implementations SHOULD return the value stored in the "size" key of - * the file in the $_FILES array if available, as PHP calculates this based - * on the actual size transmitted. - * - * @return int|null The file size in bytes or null if unknown. - */ - public function getSize(): ?int; - - /** - * Retrieve the error associated with the uploaded file. - * - * The return value MUST be one of PHP's UPLOAD_ERR_XXX constants. - * - * If the file was uploaded successfully, this method MUST return - * UPLOAD_ERR_OK. - * - * Implementations SHOULD return the value stored in the "error" key of - * the file in the $_FILES array. - * - * @see http://php.net/manual/en/features.file-upload.errors.php - * @return int One of PHP's UPLOAD_ERR_XXX constants. - */ - public function getError(): int; - - /** - * Retrieve the filename sent by the client. - * - * Do not trust the value returned by this method. A client could send - * a malicious filename with the intention to corrupt or hack your - * application. - * - * Implementations SHOULD return the value stored in the "name" key of - * the file in the $_FILES array. - * - * @return string|null The filename sent by the client or null if none - * was provided. - */ - public function getClientFilename(): ?string; - - /** - * Retrieve the media type sent by the client. - * - * Do not trust the value returned by this method. A client could send - * a malicious media type with the intention to corrupt or hack your - * application. - * - * Implementations SHOULD return the value stored in the "type" key of - * the file in the $_FILES array. - * - * @return string|null The media type sent by the client or null if none - * was provided. - */ - public function getClientMediaType(): ?string; -} diff --git a/lib/psr/http-message/src/UriInterface.php b/lib/psr/http-message/src/UriInterface.php deleted file mode 100644 index 15e2cf286..000000000 --- a/lib/psr/http-message/src/UriInterface.php +++ /dev/null @@ -1,324 +0,0 @@ -<?php - -namespace Psr\Http\Message; - -/** - * Value object representing a URI. - * - * This interface is meant to represent URIs according to RFC 3986 and to - * provide methods for most common operations. Additional functionality for - * working with URIs can be provided on top of the interface or externally. - * Its primary use is for HTTP requests, but may also be used in other - * contexts. - * - * Instances of this interface are considered immutable; all methods that - * might change state MUST be implemented such that they retain the internal - * state of the current instance and return an instance that contains the - * changed state. - * - * Typically the Host header will be also be present in the request message. - * For server-side requests, the scheme will typically be discoverable in the - * server parameters. - * - * @link http://tools.ietf.org/html/rfc3986 (the URI specification) - */ -interface UriInterface -{ - /** - * Retrieve the scheme component of the URI. - * - * If no scheme is present, this method MUST return an empty string. - * - * The value returned MUST be normalized to lowercase, per RFC 3986 - * Section 3.1. - * - * The trailing ":" character is not part of the scheme and MUST NOT be - * added. - * - * @see https://tools.ietf.org/html/rfc3986#section-3.1 - * @return string The URI scheme. - */ - public function getScheme(): string; - - /** - * Retrieve the authority component of the URI. - * - * If no authority information is present, this method MUST return an empty - * string. - * - * The authority syntax of the URI is: - * - * <pre> - * [user-info@]host[:port] - * </pre> - * - * 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(): string; - - /** - * 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(): string; - - /** - * 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(): string; - - /** - * 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(): ?int; - - /** - * 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(): string; - - /** - * 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(): string; - - /** - * 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(): string; - - /** - * 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): UriInterface; - - /** - * 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): UriInterface; - - /** - * 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): UriInterface; - - /** - * 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): UriInterface; - - /** - * 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): UriInterface; - - /** - * 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): UriInterface; - - /** - * 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): UriInterface; - - /** - * 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(): string; -} diff --git a/lib/psr/log/LICENSE b/lib/psr/log/LICENSE deleted file mode 100644 index 474c952b4..000000000 --- a/lib/psr/log/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -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/lib/psr/log/Psr/Log/AbstractLogger.php b/lib/psr/log/Psr/Log/AbstractLogger.php deleted file mode 100644 index e02f9daf3..000000000 --- a/lib/psr/log/Psr/Log/AbstractLogger.php +++ /dev/null @@ -1,128 +0,0 @@ -<?php - -namespace Psr\Log; - -/** - * This is a simple Logger implementation that other Loggers can inherit from. - * - * It simply delegates all log-level-specific methods to the `log` method to - * reduce boilerplate code that a simple Logger that does the same thing with - * messages regardless of the error level has to implement. - */ -abstract class AbstractLogger implements LoggerInterface -{ - /** - * System is unusable. - * - * @param string $message - * @param mixed[] $context - * - * @return void - */ - public function emergency($message, array $context = array()) - { - $this->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 $message - * @param mixed[] $context - * - * @return void - */ - public function alert($message, array $context = array()) - { - $this->log(LogLevel::ALERT, $message, $context); - } - - /** - * Critical conditions. - * - * Example: Application component unavailable, unexpected exception. - * - * @param string $message - * @param mixed[] $context - * - * @return void - */ - public function critical($message, array $context = array()) - { - $this->log(LogLevel::CRITICAL, $message, $context); - } - - /** - * Runtime errors that do not require immediate action but should typically - * be logged and monitored. - * - * @param string $message - * @param mixed[] $context - * - * @return void - */ - public function error($message, array $context = array()) - { - $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 $message - * @param mixed[] $context - * - * @return void - */ - public function warning($message, array $context = array()) - { - $this->log(LogLevel::WARNING, $message, $context); - } - - /** - * Normal but significant events. - * - * @param string $message - * @param mixed[] $context - * - * @return void - */ - public function notice($message, array $context = array()) - { - $this->log(LogLevel::NOTICE, $message, $context); - } - - /** - * Interesting events. - * - * Example: User logs in, SQL logs. - * - * @param string $message - * @param mixed[] $context - * - * @return void - */ - public function info($message, array $context = array()) - { - $this->log(LogLevel::INFO, $message, $context); - } - - /** - * Detailed debug information. - * - * @param string $message - * @param mixed[] $context - * - * @return void - */ - public function debug($message, array $context = array()) - { - $this->log(LogLevel::DEBUG, $message, $context); - } -} diff --git a/lib/psr/log/Psr/Log/InvalidArgumentException.php b/lib/psr/log/Psr/Log/InvalidArgumentException.php deleted file mode 100644 index 67f852d1d..000000000 --- a/lib/psr/log/Psr/Log/InvalidArgumentException.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace Psr\Log; - -class InvalidArgumentException extends \InvalidArgumentException -{ -} diff --git a/lib/psr/log/Psr/Log/LogLevel.php b/lib/psr/log/Psr/Log/LogLevel.php deleted file mode 100644 index 9cebcace6..000000000 --- a/lib/psr/log/Psr/Log/LogLevel.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php - -namespace Psr\Log; - -/** - * Describes log levels. - */ -class LogLevel -{ - const EMERGENCY = 'emergency'; - const ALERT = 'alert'; - const CRITICAL = 'critical'; - const ERROR = 'error'; - const WARNING = 'warning'; - const NOTICE = 'notice'; - const INFO = 'info'; - const DEBUG = 'debug'; -} diff --git a/lib/psr/log/Psr/Log/LoggerAwareInterface.php b/lib/psr/log/Psr/Log/LoggerAwareInterface.php deleted file mode 100644 index 4d64f4786..000000000 --- a/lib/psr/log/Psr/Log/LoggerAwareInterface.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php - -namespace Psr\Log; - -/** - * Describes a logger-aware instance. - */ -interface LoggerAwareInterface -{ - /** - * Sets a logger instance on the object. - * - * @param LoggerInterface $logger - * - * @return void - */ - public function setLogger(LoggerInterface $logger); -} diff --git a/lib/psr/log/Psr/Log/LoggerAwareTrait.php b/lib/psr/log/Psr/Log/LoggerAwareTrait.php deleted file mode 100644 index 82bf45c89..000000000 --- a/lib/psr/log/Psr/Log/LoggerAwareTrait.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php - -namespace Psr\Log; - -/** - * Basic Implementation of LoggerAwareInterface. - */ -trait LoggerAwareTrait -{ - /** - * The logger instance. - * - * @var LoggerInterface|null - */ - protected $logger; - - /** - * Sets a logger. - * - * @param LoggerInterface $logger - */ - public function setLogger(LoggerInterface $logger) - { - $this->logger = $logger; - } -} diff --git a/lib/psr/log/Psr/Log/LoggerInterface.php b/lib/psr/log/Psr/Log/LoggerInterface.php deleted file mode 100644 index 2206cfde4..000000000 --- a/lib/psr/log/Psr/Log/LoggerInterface.php +++ /dev/null @@ -1,125 +0,0 @@ -<?php - -namespace Psr\Log; - -/** - * Describes a logger instance. - * - * The message MUST be a string or object implementing __toString(). - * - * The message MAY contain placeholders in the form: {foo} where foo - * will be replaced by the context data in key "foo". - * - * The context array can contain arbitrary data. The only assumption that - * can be made by implementors is that if an Exception instance is given - * to produce a stack trace, it MUST be in a key named "exception". - * - * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md - * for the full interface specification. - */ -interface LoggerInterface -{ - /** - * System is unusable. - * - * @param string $message - * @param mixed[] $context - * - * @return void - */ - public function emergency($message, array $context = array()); - - /** - * Action must be taken immediately. - * - * Example: Entire website down, database unavailable, etc. This should - * trigger the SMS alerts and wake you up. - * - * @param string $message - * @param mixed[] $context - * - * @return void - */ - public function alert($message, array $context = array()); - - /** - * Critical conditions. - * - * Example: Application component unavailable, unexpected exception. - * - * @param string $message - * @param mixed[] $context - * - * @return void - */ - public function critical($message, array $context = array()); - - /** - * Runtime errors that do not require immediate action but should typically - * be logged and monitored. - * - * @param string $message - * @param mixed[] $context - * - * @return void - */ - public function error($message, array $context = array()); - - /** - * 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 $message - * @param mixed[] $context - * - * @return void - */ - public function warning($message, array $context = array()); - - /** - * Normal but significant events. - * - * @param string $message - * @param mixed[] $context - * - * @return void - */ - public function notice($message, array $context = array()); - - /** - * Interesting events. - * - * Example: User logs in, SQL logs. - * - * @param string $message - * @param mixed[] $context - * - * @return void - */ - public function info($message, array $context = array()); - - /** - * Detailed debug information. - * - * @param string $message - * @param mixed[] $context - * - * @return void - */ - public function debug($message, array $context = array()); - - /** - * Logs with an arbitrary level. - * - * @param mixed $level - * @param string $message - * @param mixed[] $context - * - * @return void - * - * @throws \Psr\Log\InvalidArgumentException - */ - public function log($level, $message, array $context = array()); -} diff --git a/lib/psr/log/Psr/Log/LoggerTrait.php b/lib/psr/log/Psr/Log/LoggerTrait.php deleted file mode 100644 index e392fef0a..000000000 --- a/lib/psr/log/Psr/Log/LoggerTrait.php +++ /dev/null @@ -1,142 +0,0 @@ -<?php - -namespace Psr\Log; - -/** - * This is a simple Logger trait that classes unable to extend AbstractLogger - * (because they extend another class, etc) can include. - * - * It simply delegates all log-level-specific methods to the `log` method to - * reduce boilerplate code that a simple Logger that does the same thing with - * messages regardless of the error level has to implement. - */ -trait LoggerTrait -{ - /** - * System is unusable. - * - * @param string $message - * @param array $context - * - * @return void - */ - public function emergency($message, array $context = array()) - { - $this->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 $message - * @param array $context - * - * @return void - */ - public function alert($message, array $context = array()) - { - $this->log(LogLevel::ALERT, $message, $context); - } - - /** - * Critical conditions. - * - * Example: Application component unavailable, unexpected exception. - * - * @param string $message - * @param array $context - * - * @return void - */ - public function critical($message, array $context = array()) - { - $this->log(LogLevel::CRITICAL, $message, $context); - } - - /** - * Runtime errors that do not require immediate action but should typically - * be logged and monitored. - * - * @param string $message - * @param array $context - * - * @return void - */ - public function error($message, array $context = array()) - { - $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 $message - * @param array $context - * - * @return void - */ - public function warning($message, array $context = array()) - { - $this->log(LogLevel::WARNING, $message, $context); - } - - /** - * Normal but significant events. - * - * @param string $message - * @param array $context - * - * @return void - */ - public function notice($message, array $context = array()) - { - $this->log(LogLevel::NOTICE, $message, $context); - } - - /** - * Interesting events. - * - * Example: User logs in, SQL logs. - * - * @param string $message - * @param array $context - * - * @return void - */ - public function info($message, array $context = array()) - { - $this->log(LogLevel::INFO, $message, $context); - } - - /** - * Detailed debug information. - * - * @param string $message - * @param array $context - * - * @return void - */ - public function debug($message, array $context = array()) - { - $this->log(LogLevel::DEBUG, $message, $context); - } - - /** - * Logs with an arbitrary level. - * - * @param mixed $level - * @param string $message - * @param array $context - * - * @return void - * - * @throws \Psr\Log\InvalidArgumentException - */ - abstract public function log($level, $message, array $context = array()); -} diff --git a/lib/psr/log/Psr/Log/NullLogger.php b/lib/psr/log/Psr/Log/NullLogger.php deleted file mode 100644 index c8f7293b1..000000000 --- a/lib/psr/log/Psr/Log/NullLogger.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -namespace Psr\Log; - -/** - * This Logger can be used to avoid conditional log calls. - * - * Logging should always be optional, and if no logger is provided to your - * library creating a NullLogger instance to have something to throw logs at - * is a good way to avoid littering your code with `if ($this->logger) { }` - * blocks. - */ -class NullLogger extends AbstractLogger -{ - /** - * Logs with an arbitrary level. - * - * @param mixed $level - * @param string $message - * @param array $context - * - * @return void - * - * @throws \Psr\Log\InvalidArgumentException - */ - public function log($level, $message, array $context = array()) - { - // noop - } -} diff --git a/lib/psr/log/README.md b/lib/psr/log/README.md deleted file mode 100644 index a9f20c437..000000000 --- a/lib/psr/log/README.md +++ /dev/null @@ -1,58 +0,0 @@ -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 -<?php - -use Psr\Log\LoggerInterface; - -class Foo -{ - private $logger; - - public function __construct(LoggerInterface $logger = null) - { - $this->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/lib/psr/log/composer.json b/lib/psr/log/composer.json deleted file mode 100644 index ca0569537..000000000 --- a/lib/psr/log/composer.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "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": ">=5.3.0" - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } - } -} diff --git a/lib/ralouphie/getallheaders/LICENSE b/lib/ralouphie/getallheaders/LICENSE deleted file mode 100644 index be5540c2a..000000000 --- a/lib/ralouphie/getallheaders/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -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/lib/ralouphie/getallheaders/README.md b/lib/ralouphie/getallheaders/README.md deleted file mode 100644 index 9430d76bb..000000000 --- a/lib/ralouphie/getallheaders/README.md +++ /dev/null @@ -1,27 +0,0 @@ -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/lib/ralouphie/getallheaders/composer.json b/lib/ralouphie/getallheaders/composer.json deleted file mode 100644 index de8ce62e4..000000000 --- a/lib/ralouphie/getallheaders/composer.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "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/lib/ralouphie/getallheaders/src/getallheaders.php b/lib/ralouphie/getallheaders/src/getallheaders.php deleted file mode 100644 index c7285a5ba..000000000 --- a/lib/ralouphie/getallheaders/src/getallheaders.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -if (!function_exists('getallheaders')) { - - /** - * Get all HTTP header key/values as an associative array for the current request. - * - * @return string[string] The HTTP header key/value pairs. - */ - function getallheaders() - { - $headers = array(); - - $copy_server = array( - 'CONTENT_TYPE' => 'Content-Type', - 'CONTENT_LENGTH' => 'Content-Length', - 'CONTENT_MD5' => 'Content-Md5', - ); - - foreach ($_SERVER as $key => $value) { - if (substr($key, 0, 5) === 'HTTP_') { - $key = substr($key, 5); - if (!isset($copy_server[$key]) || !isset($_SERVER[$key])) { - $key = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $key)))); - $headers[$key] = $value; - } - } elseif (isset($copy_server[$key])) { - $headers[$copy_server[$key]] = $value; - } - } - - if (!isset($headers['Authorization'])) { - if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) { - $headers['Authorization'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION']; - } elseif (isset($_SERVER['PHP_AUTH_USER'])) { - $basic_pass = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : ''; - $headers['Authorization'] = 'Basic ' . base64_encode($_SERVER['PHP_AUTH_USER'] . ':' . $basic_pass); - } elseif (isset($_SERVER['PHP_AUTH_DIGEST'])) { - $headers['Authorization'] = $_SERVER['PHP_AUTH_DIGEST']; - } - } - - return $headers; - } - -} diff --git a/lib/sabberworm/php-css-parser/CHANGELOG.md b/lib/sabberworm/php-css-parser/CHANGELOG.md deleted file mode 100644 index a23fd0e68..000000000 --- a/lib/sabberworm/php-css-parser/CHANGELOG.md +++ /dev/null @@ -1,241 +0,0 @@ -# Revision History - -## 8.4.0 - -### Features - -* Support for PHP 8.x -* PHPDoc annotations -* Allow usage of CSS variables inside color functions (by parsing them as regular functions) -* Use PSR-12 code style -* *No deprecations* - -### Bugfixes - -* Improved handling of whitespace in `calc()` -* Fix parsing units whose prefix is also a valid unit, like `vmin` -* Allow passing an object to `CSSList#replace` -* Fix PHP 7.3 warnings -* Correctly parse keyframes with `%` -* Don’t convert large numbers to scientific notation -* Allow a file to end after an `@import` -* Preserve case of CSS variables as specced -* Allow identifiers to use escapes the same way as strings -* No longer use `eval` for the comparison in `getSelectorsBySpecificity`, in case it gets passed untrusted input (CVE-2020-13756). Also fixed in 8.3.1, 8.2.1, 8.1.1, 8.0.1, 7.0.4, 6.0.2, 5.2.1, 5.1.3, 5.0.9, 4.0.1, 3.0.1, 2.0.1, 1.0.1. -* Prevent an infinite loop when parsing invalid grid line names -* Remove invalid unit `vm` -* Retain rule order after expanding shorthands - -### Backwards-incompatible changes - -* PHP ≥ 5.6 is now required -* HHVM compatibility target dropped - -## 8.3.0 (2019-02-22) - -* Refactor parsing logic to mostly reside in the class files whose data structure is to be parsed (this should eventually allow us to unit-test specific parts of the parsing logic individually). -* Fix error in parsing `calc` expessions when the first operand is a negative number, thanks to @raxbg. -* Support parsing CSS4 colors in hex notation with alpha values, thanks to @raxbg. -* Swallow more errors in lenient mode, thanks to @raxbg. -* Allow specifying arbitrary strings to output before and after declaration blocks, thanks to @westonruter. -* *No backwards-incompatible changes* -* *No deprecations* - -## 8.2.0 (2018-07-13) - -* Support parsing `calc()`, thanks to @raxbg. -* Support parsing grid-lines, again thanks to @raxbg. -* Support parsing legacy IE filters (`progid:`) in lenient mode, thanks to @FMCorz -* Performance improvements parsing large files, again thanks to @FMCorz -* *No backwards-incompatible changes* -* *No deprecations* - -## 8.1.0 (2016-07-19) - -* Comments are no longer silently ignored but stored with the object with which they appear (no render support, though). Thanks to @FMCorz. -* The IE hacks using `\0` and `\9` can now be parsed (and rendered) in lenient mode. Thanks (again) to @FMCorz. -* Media queries with or without spaces before the query are parsed. Still no *real* parsing support, though. Sorry… -* PHPUnit is now listed as a dev-dependency in composer.json. -* *No backwards-incompatible changes* -* *No deprecations* - -## 8.0.0 (2016-06-30) - -* Store source CSS line numbers in tokens and parsing exceptions. -* *No deprecations* - -### Backwards-incompatible changes - -* Unrecoverable parser errors throw an exception of type `Sabberworm\CSS\Parsing\SourceException` instead of `\Exception`. - -## 7.0.3 (2016-04-27) - -* Fixed parsing empty CSS when multibyte is off -* *No backwards-incompatible changes* -* *No deprecations* - -## 7.0.2 (2016-02-11) - -* 150 time performance boost thanks to @[ossinkine](https://github.com/ossinkine) -* *No backwards-incompatible changes* -* *No deprecations* - -## 7.0.1 (2015-12-25) - -* No more suppressed `E_NOTICE` -* *No backwards-incompatible changes* -* *No deprecations* - -## 7.0.0 (2015-08-24) - -* Compatibility with PHP 7. Well timed, eh? -* *No deprecations* - -### Backwards-incompatible changes - -* The `Sabberworm\CSS\Value\String` class has been renamed to `Sabberworm\CSS\Value\CSSString`. - -## 6.0.1 (2015-08-24) - -* Remove some declarations in interfaces incompatible with PHP 5.3 (< 5.3.9) -* *No deprecations* - -## 6.0.0 (2014-07-03) - -* Format output using Sabberworm\CSS\OutputFormat -* *No backwards-incompatible changes* - -### Deprecations - -* The parse() method replaces __toString with an optional argument (instance of the OutputFormat class) - -## 5.2.0 (2014-06-30) - -* Support removing a selector from a declaration block using `$oBlock->removeSelector($mSelector)` -* Introduce a specialized exception (Sabberworm\CSS\Parsing\OuputException) for exceptions during output rendering - -* *No deprecations* - -#### Backwards-incompatible changes - -* Outputting a declaration block that has no selectors throws an OuputException instead of outputting an invalid ` {…}` into the CSS document. - -## 5.1.2 (2013-10-30) - -* Remove the use of consumeUntil in comment parsing. This makes it possible to parse comments such as `/** Perfectly valid **/` -* Add fr relative size unit -* Fix some issues with HHVM -* *No backwards-incompatible changes* -* *No deprecations* - -## 5.1.1 (2013-10-28) - -* Updated CHANGELOG.md to reflect changes since 5.0.4 -* *No backwards-incompatible changes* -* *No deprecations* - -## 5.1.0 (2013-10-24) - -* Performance enhancements by Michael M Slusarz -* More rescue entry points for lenient parsing (unexpected tokens between declaration blocks and unclosed comments) -* *No backwards-incompatible changes* -* *No deprecations* - -## 5.0.8 (2013-08-15) - -* Make default settings’ multibyte parsing option dependent on whether or not the mbstring extension is actually installed. -* *No backwards-incompatible changes* -* *No deprecations* - -## 5.0.7 (2013-08-04) - -* Fix broken decimal point output optimization -* *No backwards-incompatible changes* -* *No deprecations* - -## 5.0.6 (2013-05-31) - -* Fix broken unit test -* *No backwards-incompatible changes* -* *No deprecations* - -## 5.0.5 (2013-04-17) - -* Initial support for lenient parsing (setting this parser option will catch some exceptions internally and recover the parser’s state as neatly as possible). -* *No backwards-incompatible changes* -* *No deprecations* - -## 5.0.4 (2013-03-21) - -* Don’t output floats with locale-aware separator chars -* *No backwards-incompatible changes* -* *No deprecations* - -## 5.0.3 (2013-03-21) - -* More size units recognized -* *No backwards-incompatible changes* -* *No deprecations* - -## 5.0.2 (2013-03-21) - -* CHANGELOG.md file added to distribution -* *No backwards-incompatible changes* -* *No deprecations* - -## 5.0.1 (2013-03-20) - -* Internal cleanup -* *No backwards-incompatible changes* -* *No deprecations* - -## 5.0.0 (2013-03-20) - -* Correctly parse all known CSS 3 units (including Hz and kHz). -* Output RGB colors in short (#aaa or #ababab) notation -* Be case-insensitive when parsing identifiers. -* *No deprecations* - -### Backwards-incompatible changes - -* `Sabberworm\CSS\Value\Color`’s `__toString` method overrides `CSSList`’s to maybe return something other than `type(value, …)` (see above). - -## 4.0.0 (2013-03-19) - -* Support for more @-rules -* Generic interface `Sabberworm\CSS\Property\AtRule`, implemented by all @-rule classes -* *No deprecations* - -### Backwards-incompatible changes - -* `Sabberworm\CSS\RuleSet\AtRule` renamed to `Sabberworm\CSS\RuleSet\AtRuleSet` -* `Sabberworm\CSS\CSSList\MediaQuery` renamed to `Sabberworm\CSS\RuleSet\CSSList\AtRuleBlockList` with differing semantics and API (which also works for other block-list-based @-rules like `@supports`). - -## 3.0.0 (2013-03-06) - -* Support for lenient parsing (on by default) -* *No deprecations* - -### Backwards-incompatible changes - -* All properties (like whether or not to use `mb_`-functions, which default charset to use and – new – whether or not to be forgiving when parsing) are now encapsulated in an instance of `Sabberworm\CSS\Settings` which can be passed as the second argument to `Sabberworm\CSS\Parser->__construct()`. -* Specifying a charset as the second argument to `Sabberworm\CSS\Parser->__construct()` is no longer supported. Use `Sabberworm\CSS\Settings::create()->withDefaultCharset('some-charset')` instead. -* Setting `Sabberworm\CSS\Parser->bUseMbFunctions` has no effect. Use `Sabberworm\CSS\Settings::create()->withMultibyteSupport(true/false)` instead. -* `Sabberworm\CSS\Parser->parse()` may throw a `Sabberworm\CSS\Parsing\UnexpectedTokenException` when in strict parsing mode. - -## 2.0.0 (2013-01-29) - -* Allow multiple rules of the same type per rule set - -### Backwards-incompatible changes - -* `Sabberworm\CSS\RuleSet->getRules()` returns an index-based array instead of an associative array. Use `Sabberworm\CSS\RuleSet->getRulesAssoc()` (which eliminates duplicate rules and lets the later rule of the same name win). -* `Sabberworm\CSS\RuleSet->removeRule()` works as it did before except when passed an instance of `Sabberworm\CSS\Rule\Rule`, in which case it would only remove the exact rule given instead of all the rules of the same type. To get the old behaviour, use `Sabberworm\CSS\RuleSet->removeRule($oRule->getRule()`; - -## 1.0 - -Initial release of a stable public API. - -## 0.9 - -Last version not to use PSR-0 project organization semantics. diff --git a/lib/sabberworm/php-css-parser/LICENSE b/lib/sabberworm/php-css-parser/LICENSE deleted file mode 100644 index 686a4e311..000000000 --- a/lib/sabberworm/php-css-parser/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2011 Raphael Schweikert, https://www.sabberworm.com/ - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -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/lib/sabberworm/php-css-parser/README.md b/lib/sabberworm/php-css-parser/README.md deleted file mode 100644 index 66fb1c655..000000000 --- a/lib/sabberworm/php-css-parser/README.md +++ /dev/null @@ -1,632 +0,0 @@ -# PHP CSS Parser - -[![Build Status](https://github.com/sabberworm/PHP-CSS-Parser/workflows/CI/badge.svg?branch=master)](https://github.com/sabberworm/PHP-CSS-Parser/actions/) - -A Parser for CSS Files written in PHP. Allows extraction of CSS files into a data structure, manipulation of said structure and output as (optimized) CSS. - -## Usage - -### Installation using Composer - -```bash -composer require sabberworm/php-css-parser -``` - -### Extraction - -To use the CSS Parser, create a new instance. The constructor takes the following form: - -```php -new \Sabberworm\CSS\Parser($css); -``` - -To read a file, for example, you’d do the following: - -```php -$parser = new \Sabberworm\CSS\Parser(file_get_contents('somefile.css')); -$cssDocument = $parser->parse(); -``` - -The resulting CSS document structure can be manipulated prior to being output. - -### Options - -#### Charset - -The charset option is used only if no `@charset` declaration is found in the CSS file. UTF-8 is the default, so you won’t have to create a settings object at all if you don’t intend to change that. - -```php -$settings = \Sabberworm\CSS\Settings::create() - ->withDefaultCharset('windows-1252'); -$parser = new \Sabberworm\CSS\Parser($css, $settings); -``` - -#### Strict parsing - -To have the parser choke on invalid rules, supply a thusly configured `\Sabberworm\CSS\Settings` object: - -```php -$parser = new \Sabberworm\CSS\Parser( - file_get_contents('somefile.css'), - \Sabberworm\CSS\Settings::create()->beStrict() -); -``` - -#### Disable multibyte functions - -To achieve faster parsing, you can choose to have PHP-CSS-Parser use regular string functions instead of `mb_*` functions. This should work fine in most cases, even for UTF-8 files, as all the multibyte characters are in string literals. Still it’s not recommended using this with input you have no control over as it’s not thoroughly covered by test cases. - -```php -$settings = \Sabberworm\CSS\Settings::create()->withMultibyteSupport(false); -$parser = new \Sabberworm\CSS\Parser($css, $settings); -``` - -### Manipulation - -The resulting data structure consists mainly of five basic types: `CSSList`, `RuleSet`, `Rule`, `Selector` and `Value`. There are two additional types used: `Import` and `Charset`, which you won’t use often. - -#### CSSList - -`CSSList` represents a generic CSS container, most likely containing declaration blocks (rule sets with a selector), but it may also contain at-rules, charset declarations, etc. `CSSList` has the following concrete subtypes: - -* `Document` – representing the root of a CSS file. -* `MediaQuery` – represents a subsection of a `CSSList` that only applies to an output device matching the contained media query. - -To access the items stored in a `CSSList` – like the document you got back when calling `$parser->parse()` –, use `getContents()`, then iterate over that collection and use instanceof to check whether you’re dealing with another `CSSList`, a `RuleSet`, a `Import` or a `Charset`. - -To append a new item (selector, media query, etc.) to an existing `CSSList`, construct it using the constructor for this class and use the `append($oItem)` method. - -#### RuleSet - -`RuleSet` is a container for individual rules. The most common form of a rule set is one constrained by a selector. The following concrete subtypes exist: - -* `AtRuleSet` – for generic at-rules which do not match the ones specifically mentioned like `@import`, `@charset` or `@media`. A common example for this is `@font-face`. -* `DeclarationBlock` – a `RuleSet` constrained by a `Selector`; contains an array of selector objects (comma-separated in the CSS) as well as the rules to be applied to the matching elements. - -Note: A `CSSList` can contain other `CSSList`s (and `Import`s as well as a `Charset`), while a `RuleSet` can only contain `Rule`s. - -If you want to manipulate a `RuleSet`, use the methods `addRule(Rule $rule)`, `getRules()` and `removeRule($rule)` (which accepts either a `Rule` instance or a rule name; optionally suffixed by a dash to remove all related rules). - -#### Rule - -`Rule`s just have a key (the rule) and a value. These values are all instances of a `Value`. - -#### Value - -`Value` is an abstract class that only defines the `render` method. The concrete subclasses for atomic value types are: - -* `Size` – consists of a numeric `size` value and a unit. -* `Color` – colors can be input in the form #rrggbb, #rgb or schema(val1, val2, …) but are always stored as an array of ('s' => val1, 'c' => val2, 'h' => val3, …) and output in the second form. -* `CSSString` – this is just a wrapper for quoted strings to distinguish them from keywords; always output with double quotes. -* `URL` – URLs in CSS; always output in URL("") notation. - -There is another abstract subclass of `Value`, `ValueList`. A `ValueList` represents a lists of `Value`s, separated by some separation character (mostly `,`, whitespace, or `/`). There are two types of `ValueList`s: - -* `RuleValueList` – The default type, used to represent all multi-valued rules like `font: bold 12px/3 Helvetica, Verdana, sans-serif;` (where the value would be a whitespace-separated list of the primitive value `bold`, a slash-separated list and a comma-separated list). -* `CSSFunction` – A special kind of value that also contains a function name and where the values are the function’s arguments. Also handles equals-sign-separated argument lists like `filter: alpha(opacity=90);`. - -#### Convenience methods - -There are a few convenience methods on Document to ease finding, manipulating and deleting rules: - -* `getAllDeclarationBlocks()` – does what it says; no matter how deeply nested your selectors are. Aliased as `getAllSelectors()`. -* `getAllRuleSets()` – does what it says; no matter how deeply nested your rule sets are. -* `getAllValues()` – finds all `Value` objects inside `Rule`s. - -## To-Do - -* More convenience methods (like `selectorsWithElement($sId/Class/TagName)`, `attributesOfType($type)`, `removeAttributesOfType($type)`) -* Real multibyte support. Currently, only multibyte charsets whose first 255 code points take up only one byte and are identical with ASCII are supported (yes, UTF-8 fits this description). -* Named color support (using `Color` instead of an anonymous string literal) - -## Use cases - -### Use `Parser` to prepend an ID to all selectors - -```php -$myId = "#my_id"; -$parser = new \Sabberworm\CSS\Parser($css); -$cssDocument = $parser->parse(); -foreach ($cssDocument->getAllDeclarationBlocks() as $block) { - foreach ($block->getSelectors() as $selector) { - // Loop over all selector parts (the comma-separated strings in a - // selector) and prepend the ID. - $selector->setSelector($myId.' '.$selector->getSelector()); - } -} -``` - -### Shrink all absolute sizes to half - -```php -$parser = new \Sabberworm\CSS\Parser($css); -$cssDocument = $parser->parse(); -foreach ($cssDocument->getAllValues() as $value) { - if ($value instanceof CSSSize && !$value->isRelative()) { - $value->setSize($value->getSize() / 2); - } -} -``` - -### Remove unwanted rules - -```php -$parser = new \Sabberworm\CSS\Parser($css); -$cssDocument = $parser->parse(); -foreach($cssDocument->getAllRuleSets() as $oRuleSet) { - // Note that the added dash will make this remove all rules starting with - // `font-` (like `font-size`, `font-weight`, etc.) as well as a potential - // `font-rule`. - $oRuleSet->removeRule('font-'); - $oRuleSet->removeRule('cursor'); -} -``` - -### Output - -To output the entire CSS document into a variable, just use `->render()`: - -```php -$parser = new \Sabberworm\CSS\Parser(file_get_contents('somefile.css')); -$cssDocument = $parser->parse(); -print $cssDocument->render(); -``` - -If you want to format the output, pass an instance of type `\Sabberworm\CSS\OutputFormat`: - -```php -$format = \Sabberworm\CSS\OutputFormat::create() - ->indentWithSpaces(4)->setSpaceBetweenRules("\n"); -print $cssDocument->render($format); -``` - -Or use one of the predefined formats: - -```php -print $cssDocument->render(Sabberworm\CSS\OutputFormat::createPretty()); -print $cssDocument->render(Sabberworm\CSS\OutputFormat::createCompact()); -``` - -To see what you can do with output formatting, look at the tests in `tests/OutputFormatTest.php`. - -## Examples - -### Example 1 (At-Rules) - -#### Input - -```css -@charset "utf-8"; - -@font-face { - font-family: "CrassRoots"; - src: url("../media/cr.ttf"); -} - -html, body { - font-size: 1.6em; -} - -@keyframes mymove { - from { top: 0px; } - to { top: 200px; } -} - -``` - -#### Structure (`var_dump()`) - -```php -class Sabberworm\CSS\CSSList\Document#4 (2) { - protected $aContents => - array(4) { - [0] => - class Sabberworm\CSS\Property\Charset#6 (2) { - private $sCharset => - class Sabberworm\CSS\Value\CSSString#5 (2) { - private $sString => - string(5) "utf-8" - protected $iLineNo => - int(1) - } - protected $iLineNo => - int(1) - } - [1] => - class Sabberworm\CSS\RuleSet\AtRuleSet#7 (4) { - private $sType => - string(9) "font-face" - private $sArgs => - string(0) "" - private $aRules => - array(2) { - 'font-family' => - array(1) { - [0] => - class Sabberworm\CSS\Rule\Rule#8 (4) { - private $sRule => - string(11) "font-family" - private $mValue => - class Sabberworm\CSS\Value\CSSString#9 (2) { - private $sString => - string(10) "CrassRoots" - protected $iLineNo => - int(4) - } - private $bIsImportant => - bool(false) - protected $iLineNo => - int(4) - } - } - 'src' => - array(1) { - [0] => - class Sabberworm\CSS\Rule\Rule#10 (4) { - private $sRule => - string(3) "src" - private $mValue => - class Sabberworm\CSS\Value\URL#11 (2) { - private $oURL => - class Sabberworm\CSS\Value\CSSString#12 (2) { - private $sString => - string(15) "../media/cr.ttf" - protected $iLineNo => - int(5) - } - protected $iLineNo => - int(5) - } - private $bIsImportant => - bool(false) - protected $iLineNo => - int(5) - } - } - } - protected $iLineNo => - int(3) - } - [2] => - class Sabberworm\CSS\RuleSet\DeclarationBlock#13 (3) { - private $aSelectors => - array(2) { - [0] => - class Sabberworm\CSS\Property\Selector#14 (2) { - private $sSelector => - string(4) "html" - private $iSpecificity => - NULL - } - [1] => - class Sabberworm\CSS\Property\Selector#15 (2) { - private $sSelector => - string(4) "body" - private $iSpecificity => - NULL - } - } - private $aRules => - array(1) { - 'font-size' => - array(1) { - [0] => - class Sabberworm\CSS\Rule\Rule#16 (4) { - private $sRule => - string(9) "font-size" - private $mValue => - class Sabberworm\CSS\Value\Size#17 (4) { - private $fSize => - double(1.6) - private $sUnit => - string(2) "em" - private $bIsColorComponent => - bool(false) - protected $iLineNo => - int(9) - } - private $bIsImportant => - bool(false) - protected $iLineNo => - int(9) - } - } - } - protected $iLineNo => - int(8) - } - [3] => - class Sabberworm\CSS\CSSList\KeyFrame#18 (4) { - private $vendorKeyFrame => - string(9) "keyframes" - private $animationName => - string(6) "mymove" - protected $aContents => - array(2) { - [0] => - class Sabberworm\CSS\RuleSet\DeclarationBlock#19 (3) { - private $aSelectors => - array(1) { - [0] => - class Sabberworm\CSS\Property\Selector#20 (2) { - private $sSelector => - string(4) "from" - private $iSpecificity => - NULL - } - } - private $aRules => - array(1) { - 'top' => - array(1) { - [0] => - class Sabberworm\CSS\Rule\Rule#21 (4) { - private $sRule => - string(3) "top" - private $mValue => - class Sabberworm\CSS\Value\Size#22 (4) { - private $fSize => - double(0) - private $sUnit => - string(2) "px" - private $bIsColorComponent => - bool(false) - protected $iLineNo => - int(13) - } - private $bIsImportant => - bool(false) - protected $iLineNo => - int(13) - } - } - } - protected $iLineNo => - int(13) - } - [1] => - class Sabberworm\CSS\RuleSet\DeclarationBlock#23 (3) { - private $aSelectors => - array(1) { - [0] => - class Sabberworm\CSS\Property\Selector#24 (2) { - private $sSelector => - string(2) "to" - private $iSpecificity => - NULL - } - } - private $aRules => - array(1) { - 'top' => - array(1) { - [0] => - class Sabberworm\CSS\Rule\Rule#25 (4) { - private $sRule => - string(3) "top" - private $mValue => - class Sabberworm\CSS\Value\Size#26 (4) { - private $fSize => - double(200) - private $sUnit => - string(2) "px" - private $bIsColorComponent => - bool(false) - protected $iLineNo => - int(14) - } - private $bIsImportant => - bool(false) - protected $iLineNo => - int(14) - } - } - } - protected $iLineNo => - int(14) - } - } - protected $iLineNo => - int(12) - } - } - protected $iLineNo => - int(1) -} - -``` - -#### Output (`render()`) - -```css -@charset "utf-8"; -@font-face {font-family: "CrassRoots";src: url("../media/cr.ttf");} -html, body {font-size: 1.6em;} -@keyframes mymove {from {top: 0px;} to {top: 200px;}} -``` - -### Example 2 (Values) - -#### Input - -```css -#header { - margin: 10px 2em 1cm 2%; - font-family: Verdana, Helvetica, "Gill Sans", sans-serif; - color: red !important; -} - -``` - -#### Structure (`var_dump()`) - -```php -class Sabberworm\CSS\CSSList\Document#4 (2) { - protected $aContents => - array(1) { - [0] => - class Sabberworm\CSS\RuleSet\DeclarationBlock#5 (3) { - private $aSelectors => - array(1) { - [0] => - class Sabberworm\CSS\Property\Selector#6 (2) { - private $sSelector => - string(7) "#header" - private $iSpecificity => - NULL - } - } - private $aRules => - array(3) { - 'margin' => - array(1) { - [0] => - class Sabberworm\CSS\Rule\Rule#7 (4) { - private $sRule => - string(6) "margin" - private $mValue => - class Sabberworm\CSS\Value\RuleValueList#12 (3) { - protected $aComponents => - array(4) { - [0] => - class Sabberworm\CSS\Value\Size#8 (4) { - private $fSize => - double(10) - private $sUnit => - string(2) "px" - private $bIsColorComponent => - bool(false) - protected $iLineNo => - int(2) - } - [1] => - class Sabberworm\CSS\Value\Size#9 (4) { - private $fSize => - double(2) - private $sUnit => - string(2) "em" - private $bIsColorComponent => - bool(false) - protected $iLineNo => - int(2) - } - [2] => - class Sabberworm\CSS\Value\Size#10 (4) { - private $fSize => - double(1) - private $sUnit => - string(2) "cm" - private $bIsColorComponent => - bool(false) - protected $iLineNo => - int(2) - } - [3] => - class Sabberworm\CSS\Value\Size#11 (4) { - private $fSize => - double(2) - private $sUnit => - string(1) "%" - private $bIsColorComponent => - bool(false) - protected $iLineNo => - int(2) - } - } - protected $sSeparator => - string(1) " " - protected $iLineNo => - int(2) - } - private $bIsImportant => - bool(false) - protected $iLineNo => - int(2) - } - } - 'font-family' => - array(1) { - [0] => - class Sabberworm\CSS\Rule\Rule#13 (4) { - private $sRule => - string(11) "font-family" - private $mValue => - class Sabberworm\CSS\Value\RuleValueList#15 (3) { - protected $aComponents => - array(4) { - [0] => - string(7) "Verdana" - [1] => - string(9) "Helvetica" - [2] => - class Sabberworm\CSS\Value\CSSString#14 (2) { - private $sString => - string(9) "Gill Sans" - protected $iLineNo => - int(3) - } - [3] => - string(10) "sans-serif" - } - protected $sSeparator => - string(1) "," - protected $iLineNo => - int(3) - } - private $bIsImportant => - bool(false) - protected $iLineNo => - int(3) - } - } - 'color' => - array(1) { - [0] => - class Sabberworm\CSS\Rule\Rule#16 (4) { - private $sRule => - string(5) "color" - private $mValue => - string(3) "red" - private $bIsImportant => - bool(true) - protected $iLineNo => - int(4) - } - } - } - protected $iLineNo => - int(1) - } - } - protected $iLineNo => - int(1) -} - -``` - -#### Output (`render()`) - -```css -#header {margin: 10px 2em 1cm 2%;font-family: Verdana,Helvetica,"Gill Sans",sans-serif;color: red !important;} -``` - -## Contributors/Thanks to - -* [oliverklee](https://github.com/oliverklee) for lots of refactorings, code modernizations and CI integrations -* [raxbg](https://github.com/raxbg) for contributions to parse `calc`, grid lines, and various bugfixes. -* [westonruter](https://github.com/westonruter) for bugfixes and improvements. -* [FMCorz](https://github.com/FMCorz) for many patches and suggestions, for being able to parse comments and IE hacks (in lenient mode). -* [Lullabot](https://github.com/Lullabot) for a patch that allows to know the line number for each parsed token. -* [ju1ius](https://github.com/ju1ius) for the specificity parsing code and the ability to expand/compact shorthand properties. -* [ossinkine](https://github.com/ossinkine) for a 150 time performance boost. -* [GaryJones](https://github.com/GaryJones) for lots of input and [https://css-specificity.info/](https://css-specificity.info/). -* [docteurklein](https://github.com/docteurklein) for output formatting and `CSSList->remove()` inspiration. -* [nicolopignatelli](https://github.com/nicolopignatelli) for PSR-0 compatibility. -* [diegoembarcadero](https://github.com/diegoembarcadero) for keyframe at-rule parsing. -* [goetas](https://github.com/goetas) for @namespace at-rule support. -* [View full list](https://github.com/sabberworm/PHP-CSS-Parser/contributors) - -## Misc - -* Legacy Support: The latest pre-PSR-0 version of this project can be checked with the `0.9.0` tag. -* Running Tests: To run all unit tests for this project, run `composer install` to install phpunit and use `./vendor/bin/phpunit`. diff --git a/lib/sabberworm/php-css-parser/composer.json b/lib/sabberworm/php-css-parser/composer.json deleted file mode 100644 index e192dd56a..000000000 --- a/lib/sabberworm/php-css-parser/composer.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "name": "sabberworm/php-css-parser", - "type": "library", - "description": "Parser for CSS Files written in PHP", - "keywords": [ - "parser", - "css", - "stylesheet" - ], - "homepage": "https://www.sabberworm.com/blog/2010/6/10/php-css-parser", - "license": "MIT", - "authors": [ - { - "name": "Raphael Schweikert" - } - ], - "require": { - "php": ">=5.6.20", - "ext-iconv": "*" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.36", - "codacy/coverage": "^1.4" - }, - "suggest": { - "ext-mbstring": "for parsing UTF-8 CSS" - }, - "autoload": { - "psr-4": { - "Sabberworm\\CSS\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "Sabberworm\\CSS\\Tests\\": "tests/" - } - }, - "scripts": { - "ci": [ - "@ci:static" - ], - "ci:php:fixer": "@php ./.phive/php-cs-fixer.phar --config=config/php-cs-fixer.php fix --dry-run -v --show-progress=dots bin src tests", - "ci:php:sniffer": "@php ./.phive/phpcs.phar --standard=config/phpcs.xml bin src tests", - "ci:php:stan": "@php ./.phive/phpstan.phar --configuration=config/phpstan.neon", - "ci:static": [ - "@ci:php:fixer", - "@ci:php:sniffer", - "@ci:php:stan" - ], - "fix:php": [ - "@fix:php:fixer", - "@fix:php:sniffer" - ], - "fix:php:fixer": "@php ./.phive/php-cs-fixer.phar --config=config/php-cs-fixer.php fix bin src tests", - "fix:php:sniffer": "@php ./.phive/phpcbf.phar --standard=config/phpcs.xml bin src tests", - "phpstan:baseline": "@php ./.phive/phpstan.phar --configuration=config/phpstan.neon --generate-baseline=config/phpstan-baseline.neon" - }, - "scripts-descriptions": { - "ci": "Runs all dynamic and static code checks (i.e. currently, only the static checks).", - "ci:php:fixer": "Checks the code style with PHP CS Fixer.", - "ci:php:sniffer": "Checks the code style with PHP_CodeSniffer.", - "ci:php:stan": "Checks the types with PHPStan.", - "ci:static": "Runs all static code analysis checks for the code.", - "fix:php": "Autofixes all autofixable issues in the PHP code.", - "fix:php:fixer": "Fixes autofixable issues found by PHP CS Fixer.", - "fix:php:sniffer": "Fixes autofixable issues found by PHP_CodeSniffer.", - "phpstand:baseline": "Updates the PHPStan baseline file to match the code." - } -} diff --git a/lib/sabberworm/php-css-parser/src/CSSList/AtRuleBlockList.php b/lib/sabberworm/php-css-parser/src/CSSList/AtRuleBlockList.php deleted file mode 100644 index 218adb9a1..000000000 --- a/lib/sabberworm/php-css-parser/src/CSSList/AtRuleBlockList.php +++ /dev/null @@ -1,83 +0,0 @@ -<?php - -namespace Sabberworm\CSS\CSSList; - -use Sabberworm\CSS\OutputFormat; -use Sabberworm\CSS\Property\AtRule; - -/** - * A `BlockList` constructed by an unknown at-rule. `@media` rules are rendered into `AtRuleBlockList` objects. - */ -class AtRuleBlockList extends CSSBlockList implements AtRule -{ - /** - * @var string - */ - private $sType; - - /** - * @var string - */ - private $sArgs; - - /** - * @param string $sType - * @param string $sArgs - * @param int $iLineNo - */ - public function __construct($sType, $sArgs = '', $iLineNo = 0) - { - parent::__construct($iLineNo); - $this->sType = $sType; - $this->sArgs = $sArgs; - } - - /** - * @return string - */ - public function atRuleName() - { - return $this->sType; - } - - /** - * @return string - */ - public function atRuleArgs() - { - return $this->sArgs; - } - - /** - * @return string - */ - public function __toString() - { - return $this->render(new OutputFormat()); - } - - /** - * @return string - */ - public function render(OutputFormat $oOutputFormat) - { - $sArgs = $this->sArgs; - if ($sArgs) { - $sArgs = ' ' . $sArgs; - } - $sResult = $oOutputFormat->sBeforeAtRuleBlock; - $sResult .= "@{$this->sType}$sArgs{$oOutputFormat->spaceBeforeOpeningBrace()}{"; - $sResult .= parent::render($oOutputFormat); - $sResult .= '}'; - $sResult .= $oOutputFormat->sAfterAtRuleBlock; - return $sResult; - } - - /** - * @return bool - */ - public function isRootList() - { - return false; - } -} diff --git a/lib/sabberworm/php-css-parser/src/CSSList/CSSBlockList.php b/lib/sabberworm/php-css-parser/src/CSSList/CSSBlockList.php deleted file mode 100644 index fce7913eb..000000000 --- a/lib/sabberworm/php-css-parser/src/CSSList/CSSBlockList.php +++ /dev/null @@ -1,143 +0,0 @@ -<?php - -namespace Sabberworm\CSS\CSSList; - -use Sabberworm\CSS\Property\Selector; -use Sabberworm\CSS\Rule\Rule; -use Sabberworm\CSS\RuleSet\DeclarationBlock; -use Sabberworm\CSS\RuleSet\RuleSet; -use Sabberworm\CSS\Value\CSSFunction; -use Sabberworm\CSS\Value\Value; -use Sabberworm\CSS\Value\ValueList; - -/** - * A `CSSBlockList` is a `CSSList` whose `DeclarationBlock`s are guaranteed to contain valid declaration blocks or - * at-rules. - * - * Most `CSSList`s conform to this category but some at-rules (such as `@keyframes`) do not. - */ -abstract class CSSBlockList extends CSSList -{ - /** - * @param int $iLineNo - */ - public function __construct($iLineNo = 0) - { - parent::__construct($iLineNo); - } - - /** - * @param array<int, DeclarationBlock> $aResult - * - * @return void - */ - protected function allDeclarationBlocks(array &$aResult) - { - foreach ($this->aContents as $mContent) { - if ($mContent instanceof DeclarationBlock) { - $aResult[] = $mContent; - } elseif ($mContent instanceof CSSBlockList) { - $mContent->allDeclarationBlocks($aResult); - } - } - } - - /** - * @param array<int, RuleSet> $aResult - * - * @return void - */ - protected function allRuleSets(array &$aResult) - { - foreach ($this->aContents as $mContent) { - if ($mContent instanceof RuleSet) { - $aResult[] = $mContent; - } elseif ($mContent instanceof CSSBlockList) { - $mContent->allRuleSets($aResult); - } - } - } - - /** - * @param CSSList|Rule|RuleSet|Value $oElement - * @param array<int, Value> $aResult - * @param string|null $sSearchString - * @param bool $bSearchInFunctionArguments - * - * @return void - */ - protected function allValues($oElement, array &$aResult, $sSearchString = null, $bSearchInFunctionArguments = false) - { - if ($oElement instanceof CSSBlockList) { - foreach ($oElement->getContents() as $oContent) { - $this->allValues($oContent, $aResult, $sSearchString, $bSearchInFunctionArguments); - } - } elseif ($oElement instanceof RuleSet) { - foreach ($oElement->getRules($sSearchString) as $oRule) { - $this->allValues($oRule, $aResult, $sSearchString, $bSearchInFunctionArguments); - } - } elseif ($oElement instanceof Rule) { - $this->allValues($oElement->getValue(), $aResult, $sSearchString, $bSearchInFunctionArguments); - } elseif ($oElement instanceof ValueList) { - if ($bSearchInFunctionArguments || !($oElement instanceof CSSFunction)) { - foreach ($oElement->getListComponents() as $mComponent) { - $this->allValues($mComponent, $aResult, $sSearchString, $bSearchInFunctionArguments); - } - } - } else { - // Non-List `Value` or `CSSString` (CSS identifier) - $aResult[] = $oElement; - } - } - - /** - * @param array<int, Selector> $aResult - * @param string|null $sSpecificitySearch - * - * @return void - */ - protected function allSelectors(array &$aResult, $sSpecificitySearch = null) - { - /** @var array<int, DeclarationBlock> $aDeclarationBlocks */ - $aDeclarationBlocks = []; - $this->allDeclarationBlocks($aDeclarationBlocks); - foreach ($aDeclarationBlocks as $oBlock) { - foreach ($oBlock->getSelectors() as $oSelector) { - if ($sSpecificitySearch === null) { - $aResult[] = $oSelector; - } else { - $sComparator = '==='; - $aSpecificitySearch = explode(' ', $sSpecificitySearch); - $iTargetSpecificity = $aSpecificitySearch[0]; - if (count($aSpecificitySearch) > 1) { - $sComparator = $aSpecificitySearch[0]; - $iTargetSpecificity = $aSpecificitySearch[1]; - } - $iTargetSpecificity = (int)$iTargetSpecificity; - $iSelectorSpecificity = $oSelector->getSpecificity(); - $bMatches = false; - switch ($sComparator) { - case '<=': - $bMatches = $iSelectorSpecificity <= $iTargetSpecificity; - break; - case '<': - $bMatches = $iSelectorSpecificity < $iTargetSpecificity; - break; - case '>=': - $bMatches = $iSelectorSpecificity >= $iTargetSpecificity; - break; - case '>': - $bMatches = $iSelectorSpecificity > $iTargetSpecificity; - break; - default: - $bMatches = $iSelectorSpecificity === $iTargetSpecificity; - break; - } - if ($bMatches) { - $aResult[] = $oSelector; - } - } - } - } - } -} diff --git a/lib/sabberworm/php-css-parser/src/CSSList/CSSList.php b/lib/sabberworm/php-css-parser/src/CSSList/CSSList.php deleted file mode 100644 index 946740a49..000000000 --- a/lib/sabberworm/php-css-parser/src/CSSList/CSSList.php +++ /dev/null @@ -1,479 +0,0 @@ -<?php - -namespace Sabberworm\CSS\CSSList; - -use Sabberworm\CSS\Comment\Comment; -use Sabberworm\CSS\Comment\Commentable; -use Sabberworm\CSS\OutputFormat; -use Sabberworm\CSS\Parsing\ParserState; -use Sabberworm\CSS\Parsing\SourceException; -use Sabberworm\CSS\Parsing\UnexpectedEOFException; -use Sabberworm\CSS\Parsing\UnexpectedTokenException; -use Sabberworm\CSS\Property\AtRule; -use Sabberworm\CSS\Property\Charset; -use Sabberworm\CSS\Property\CSSNamespace; -use Sabberworm\CSS\Property\Import; -use Sabberworm\CSS\Property\Selector; -use Sabberworm\CSS\Renderable; -use Sabberworm\CSS\RuleSet\AtRuleSet; -use Sabberworm\CSS\RuleSet\DeclarationBlock; -use Sabberworm\CSS\RuleSet\RuleSet; -use Sabberworm\CSS\Settings; -use Sabberworm\CSS\Value\CSSString; -use Sabberworm\CSS\Value\URL; -use Sabberworm\CSS\Value\Value; - -/** - * A `CSSList` is the most generic container available. Its contents include `RuleSet` as well as other `CSSList` - * objects. - * - * Also, it may contain `Import` and `Charset` objects stemming from at-rules. - */ -abstract class CSSList implements Renderable, Commentable -{ - /** - * @var array<array-key, Comment> - */ - protected $aComments; - - /** - * @var array<int, RuleSet|CSSList|Import|Charset> - */ - protected $aContents; - - /** - * @var int - */ - protected $iLineNo; - - /** - * @param int $iLineNo - */ - public function __construct($iLineNo = 0) - { - $this->aComments = []; - $this->aContents = []; - $this->iLineNo = $iLineNo; - } - - /** - * @return void - * - * @throws UnexpectedTokenException - * @throws SourceException - */ - public static function parseList(ParserState $oParserState, CSSList $oList) - { - $bIsRoot = $oList instanceof Document; - if (is_string($oParserState)) { - $oParserState = new ParserState($oParserState, Settings::create()); - } - $bLenientParsing = $oParserState->getSettings()->bLenientParsing; - while (!$oParserState->isEnd()) { - $comments = $oParserState->consumeWhiteSpace(); - $oListItem = null; - if ($bLenientParsing) { - try { - $oListItem = self::parseListItem($oParserState, $oList); - } catch (UnexpectedTokenException $e) { - $oListItem = false; - } - } else { - $oListItem = self::parseListItem($oParserState, $oList); - } - if ($oListItem === null) { - // List parsing finished - return; - } - if ($oListItem) { - $oListItem->setComments($comments); - $oList->append($oListItem); - } - $oParserState->consumeWhiteSpace(); - } - if (!$bIsRoot && !$bLenientParsing) { - throw new SourceException("Unexpected end of document", $oParserState->currentLine()); - } - } - - /** - * @return AtRuleBlockList|KeyFrame|Charset|CSSNamespace|Import|AtRuleSet|DeclarationBlock|null|false - * - * @throws SourceException - * @throws UnexpectedEOFException - * @throws UnexpectedTokenException - */ - private static function parseListItem(ParserState $oParserState, CSSList $oList) - { - $bIsRoot = $oList instanceof Document; - if ($oParserState->comes('@')) { - $oAtRule = self::parseAtRule($oParserState); - if ($oAtRule instanceof Charset) { - if (!$bIsRoot) { - throw new UnexpectedTokenException( - '@charset may only occur in root document', - '', - 'custom', - $oParserState->currentLine() - ); - } - if (count($oList->getContents()) > 0) { - throw new UnexpectedTokenException( - '@charset must be the first parseable token in a document', - '', - 'custom', - $oParserState->currentLine() - ); - } - $oParserState->setCharset($oAtRule->getCharset()->getString()); - } - return $oAtRule; - } elseif ($oParserState->comes('}')) { - if (!$oParserState->getSettings()->bLenientParsing) { - throw new UnexpectedTokenException('CSS selector', '}', 'identifier', $oParserState->currentLine()); - } else { - if ($bIsRoot) { - if ($oParserState->getSettings()->bLenientParsing) { - return DeclarationBlock::parse($oParserState); - } else { - throw new SourceException("Unopened {", $oParserState->currentLine()); - } - } else { - return null; - } - } - } else { - return DeclarationBlock::parse($oParserState, $oList); - } - } - - /** - * @param ParserState $oParserState - * - * @return AtRuleBlockList|KeyFrame|Charset|CSSNamespace|Import|AtRuleSet|null - * - * @throws SourceException - * @throws UnexpectedTokenException - * @throws UnexpectedEOFException - */ - private static function parseAtRule(ParserState $oParserState) - { - $oParserState->consume('@'); - $sIdentifier = $oParserState->parseIdentifier(); - $iIdentifierLineNum = $oParserState->currentLine(); - $oParserState->consumeWhiteSpace(); - if ($sIdentifier === 'import') { - $oLocation = URL::parse($oParserState); - $oParserState->consumeWhiteSpace(); - $sMediaQuery = null; - if (!$oParserState->comes(';')) { - $sMediaQuery = trim($oParserState->consumeUntil([';', ParserState::EOF])); - } - $oParserState->consumeUntil([';', ParserState::EOF], true, true); - return new Import($oLocation, $sMediaQuery ?: null, $iIdentifierLineNum); - } elseif ($sIdentifier === 'charset') { - $sCharset = CSSString::parse($oParserState); - $oParserState->consumeWhiteSpace(); - $oParserState->consumeUntil([';', ParserState::EOF], true, true); - return new Charset($sCharset, $iIdentifierLineNum); - } elseif (self::identifierIs($sIdentifier, 'keyframes')) { - $oResult = new KeyFrame($iIdentifierLineNum); - $oResult->setVendorKeyFrame($sIdentifier); - $oResult->setAnimationName(trim($oParserState->consumeUntil('{', false, true))); - CSSList::parseList($oParserState, $oResult); - if ($oParserState->comes('}')) { - $oParserState->consume('}'); - } - return $oResult; - } elseif ($sIdentifier === 'namespace') { - $sPrefix = null; - $mUrl = Value::parsePrimitiveValue($oParserState); - if (!$oParserState->comes(';')) { - $sPrefix = $mUrl; - $mUrl = Value::parsePrimitiveValue($oParserState); - } - $oParserState->consumeUntil([';', ParserState::EOF], true, true); - if ($sPrefix !== null && !is_string($sPrefix)) { - throw new UnexpectedTokenException('Wrong namespace prefix', $sPrefix, 'custom', $iIdentifierLineNum); - } - if (!($mUrl instanceof CSSString || $mUrl instanceof URL)) { - throw new UnexpectedTokenException( - 'Wrong namespace url of invalid type', - $mUrl, - 'custom', - $iIdentifierLineNum - ); - } - return new CSSNamespace($mUrl, $sPrefix, $iIdentifierLineNum); - } else { - // Unknown other at rule (font-face or such) - $sArgs = trim($oParserState->consumeUntil('{', false, true)); - if (substr_count($sArgs, "(") != substr_count($sArgs, ")")) { - if ($oParserState->getSettings()->bLenientParsing) { - return null; - } else { - throw new SourceException("Unmatched brace count in media query", $oParserState->currentLine()); - } - } - $bUseRuleSet = true; - foreach (explode('/', AtRule::BLOCK_RULES) as $sBlockRuleName) { - if (self::identifierIs($sIdentifier, $sBlockRuleName)) { - $bUseRuleSet = false; - break; - } - } - if ($bUseRuleSet) { - $oAtRule = new AtRuleSet($sIdentifier, $sArgs, $iIdentifierLineNum); - RuleSet::parseRuleSet($oParserState, $oAtRule); - } else { - $oAtRule = new AtRuleBlockList($sIdentifier, $sArgs, $iIdentifierLineNum); - CSSList::parseList($oParserState, $oAtRule); - if ($oParserState->comes('}')) { - $oParserState->consume('}'); - } - } - return $oAtRule; - } - } - - /** - * Tests an identifier for a given value. Since identifiers are all keywords, they can be vendor-prefixed. - * We need to check for these versions too. - * - * @param string $sIdentifier - * @param string $sMatch - * - * @return bool - */ - private static function identifierIs($sIdentifier, $sMatch) - { - return (strcasecmp($sIdentifier, $sMatch) === 0) - ?: preg_match("/^(-\\w+-)?$sMatch$/i", $sIdentifier) === 1; - } - - /** - * @return int - */ - public function getLineNo() - { - return $this->iLineNo; - } - - /** - * Prepends an item to the list of contents. - * - * @param RuleSet|CSSList|Import|Charset $oItem - * - * @return void - */ - public function prepend($oItem) - { - array_unshift($this->aContents, $oItem); - } - - /** - * Appends an item to tje list of contents. - * - * @param RuleSet|CSSList|Import|Charset $oItem - * - * @return void - */ - public function append($oItem) - { - $this->aContents[] = $oItem; - } - - /** - * Splices the list of contents. - * - * @param int $iOffset - * @param int $iLength - * @param array<int, RuleSet|CSSList|Import|Charset> $mReplacement - * - * @return void - */ - public function splice($iOffset, $iLength = null, $mReplacement = null) - { - array_splice($this->aContents, $iOffset, $iLength, $mReplacement); - } - - /** - * Removes an item from the CSS list. - * - * @param RuleSet|Import|Charset|CSSList $oItemToRemove - * May be a RuleSet (most likely a DeclarationBlock), a Import, - * a Charset or another CSSList (most likely a MediaQuery) - * - * @return bool whether the item was removed - */ - public function remove($oItemToRemove) - { - $iKey = array_search($oItemToRemove, $this->aContents, true); - if ($iKey !== false) { - unset($this->aContents[$iKey]); - return true; - } - return false; - } - - /** - * Replaces an item from the CSS list. - * - * @param RuleSet|Import|Charset|CSSList $oOldItem - * May be a `RuleSet` (most likely a `DeclarationBlock`), an `Import`, a `Charset` - * or another `CSSList` (most likely a `MediaQuery`) - * - * @return bool - */ - public function replace($oOldItem, $mNewItem) - { - $iKey = array_search($oOldItem, $this->aContents, true); - if ($iKey !== false) { - if (is_array($mNewItem)) { - array_splice($this->aContents, $iKey, 1, $mNewItem); - } else { - array_splice($this->aContents, $iKey, 1, [$mNewItem]); - } - return true; - } - return false; - } - - /** - * @param array<int, RuleSet|Import|Charset|CSSList> $aContents - */ - public function setContents(array $aContents) - { - $this->aContents = []; - foreach ($aContents as $content) { - $this->append($content); - } - } - - /** - * Removes a declaration block from the CSS list if it matches all given selectors. - * - * @param DeclarationBlock|array<array-key, Selector>|string $mSelector the selectors to match - * @param bool $bRemoveAll whether to stop at the first declaration block found or remove all blocks - * - * @return void - */ - public function removeDeclarationBlockBySelector($mSelector, $bRemoveAll = false) - { - if ($mSelector instanceof DeclarationBlock) { - $mSelector = $mSelector->getSelectors(); - } - if (!is_array($mSelector)) { - $mSelector = explode(',', $mSelector); - } - foreach ($mSelector as $iKey => &$mSel) { - if (!($mSel instanceof Selector)) { - if (!Selector::isValid($mSel)) { - throw new UnexpectedTokenException( - "Selector did not match '" . Selector::SELECTOR_VALIDATION_RX . "'.", - $mSel, - "custom" - ); - } - $mSel = new Selector($mSel); - } - } - foreach ($this->aContents as $iKey => $mItem) { - if (!($mItem instanceof DeclarationBlock)) { - continue; - } - if ($mItem->getSelectors() == $mSelector) { - unset($this->aContents[$iKey]); - if (!$bRemoveAll) { - return; - } - } - } - } - - /** - * @return string - */ - public function __toString() - { - return $this->render(new OutputFormat()); - } - - /** - * @return string - */ - public function render(OutputFormat $oOutputFormat) - { - $sResult = ''; - $bIsFirst = true; - $oNextLevel = $oOutputFormat; - if (!$this->isRootList()) { - $oNextLevel = $oOutputFormat->nextLevel(); - } - foreach ($this->aContents as $oContent) { - $sRendered = $oOutputFormat->safely(function () use ($oNextLevel, $oContent) { - return $oContent->render($oNextLevel); - }); - if ($sRendered === null) { - continue; - } - if ($bIsFirst) { - $bIsFirst = false; - $sResult .= $oNextLevel->spaceBeforeBlocks(); - } else { - $sResult .= $oNextLevel->spaceBetweenBlocks(); - } - $sResult .= $sRendered; - } - - if (!$bIsFirst) { - // Had some output - $sResult .= $oOutputFormat->spaceAfterBlocks(); - } - - return $sResult; - } - - /** - * Return true if the list can not be further outdented. Only important when rendering. - * - * @return bool - */ - abstract public function isRootList(); - - /** - * @return array<int, RuleSet|Import|Charset|CSSList> - */ - public function getContents() - { - return $this->aContents; - } - - /** - * @param array<array-key, Comment> $aComments - * - * @return void - */ - public function addComments(array $aComments) - { - $this->aComments = array_merge($this->aComments, $aComments); - } - - /** - * @return array<array-key, Comment> - */ - public function getComments() - { - return $this->aComments; - } - - /** - * @param array<array-key, Comment> $aComments - * - * @return void - */ - public function setComments(array $aComments) - { - $this->aComments = $aComments; - } -} diff --git a/lib/sabberworm/php-css-parser/src/CSSList/Document.php b/lib/sabberworm/php-css-parser/src/CSSList/Document.php deleted file mode 100644 index 91ab2c6b2..000000000 --- a/lib/sabberworm/php-css-parser/src/CSSList/Document.php +++ /dev/null @@ -1,172 +0,0 @@ -<?php - -namespace Sabberworm\CSS\CSSList; - -use Sabberworm\CSS\OutputFormat; -use Sabberworm\CSS\Parsing\ParserState; -use Sabberworm\CSS\Parsing\SourceException; -use Sabberworm\CSS\Property\Selector; -use Sabberworm\CSS\RuleSet\DeclarationBlock; -use Sabberworm\CSS\RuleSet\RuleSet; -use Sabberworm\CSS\Value\Value; - -/** - * The root `CSSList` of a parsed file. Contains all top-level CSS contents, mostly declaration blocks, - * but also any at-rules encountered. - */ -class Document extends CSSBlockList -{ - /** - * @param int $iLineNo - */ - public function __construct($iLineNo = 0) - { - parent::__construct($iLineNo); - } - - /** - * @return Document - * - * @throws SourceException - */ - public static function parse(ParserState $oParserState) - { - $oDocument = new Document($oParserState->currentLine()); - CSSList::parseList($oParserState, $oDocument); - return $oDocument; - } - - /** - * Gets all `DeclarationBlock` objects recursively. - * - * @return array<int, DeclarationBlock> - */ - public function getAllDeclarationBlocks() - { - /** @var array<int, DeclarationBlock> $aResult */ - $aResult = []; - $this->allDeclarationBlocks($aResult); - return $aResult; - } - - /** - * Gets all `DeclarationBlock` objects recursively. - * - * @return array<int, DeclarationBlock> - * - * @deprecated will be removed in version 9.0; use `getAllDeclarationBlocks()` instead - */ - public function getAllSelectors() - { - return $this->getAllDeclarationBlocks(); - } - - /** - * Returns all `RuleSet` objects found recursively in the tree. - * - * @return array<int, RuleSet> - */ - public function getAllRuleSets() - { - /** @var array<int, RuleSet> $aResult */ - $aResult = []; - $this->allRuleSets($aResult); - return $aResult; - } - - /** - * Returns all `Value` objects found recursively in the tree. - * - * @param CSSList|RuleSet|string $mElement - * the `CSSList` or `RuleSet` to start the search from (defaults to the whole document). - * If a string is given, it is used as rule name filter. - * @param bool $bSearchInFunctionArguments whether to also return Value objects used as Function arguments. - * - * @return array<int, Value> - * - * @see RuleSet->getRules() - */ - public function getAllValues($mElement = null, $bSearchInFunctionArguments = false) - { - $sSearchString = null; - if ($mElement === null) { - $mElement = $this; - } elseif (is_string($mElement)) { - $sSearchString = $mElement; - $mElement = $this; - } - /** @var array<int, Value> $aResult */ - $aResult = []; - $this->allValues($mElement, $aResult, $sSearchString, $bSearchInFunctionArguments); - return $aResult; - } - - /** - * Returns all `Selector` objects found recursively in the tree. - * - * Note that this does not yield the full `DeclarationBlock` that the selector belongs to - * (and, currently, there is no way to get to that). - * - * @param string|null $sSpecificitySearch - * An optional filter by specificity. - * May contain a comparison operator and a number or just a number (defaults to "=="). - * - * @return array<int, Selector> - * @example `getSelectorsBySpecificity('>= 100')` - * - */ - public function getSelectorsBySpecificity($sSpecificitySearch = null) - { - /** @var array<int, Selector> $aResult */ - $aResult = []; - $this->allSelectors($aResult, $sSpecificitySearch); - return $aResult; - } - - /** - * Expands all shorthand properties to their long value. - * - * @return void - */ - public function expandShorthands() - { - foreach ($this->getAllDeclarationBlocks() as $oDeclaration) { - $oDeclaration->expandShorthands(); - } - } - - /** - * Create shorthands properties whenever possible. - * - * @return void - */ - public function createShorthands() - { - foreach ($this->getAllDeclarationBlocks() as $oDeclaration) { - $oDeclaration->createShorthands(); - } - } - - /** - * Overrides `render()` to make format argument optional. - * - * @param OutputFormat|null $oOutputFormat - * - * @return string - */ - public function render(OutputFormat $oOutputFormat = null) - { - if ($oOutputFormat === null) { - $oOutputFormat = new OutputFormat(); - } - return parent::render($oOutputFormat); - } - - /** - * @return bool - */ - public function isRootList() - { - return true; - } -} diff --git a/lib/sabberworm/php-css-parser/src/CSSList/KeyFrame.php b/lib/sabberworm/php-css-parser/src/CSSList/KeyFrame.php deleted file mode 100644 index d9420e9c0..000000000 --- a/lib/sabberworm/php-css-parser/src/CSSList/KeyFrame.php +++ /dev/null @@ -1,104 +0,0 @@ -<?php - -namespace Sabberworm\CSS\CSSList; - -use Sabberworm\CSS\OutputFormat; -use Sabberworm\CSS\Property\AtRule; - -class KeyFrame extends CSSList implements AtRule -{ - /** - * @var string|null - */ - private $vendorKeyFrame; - - /** - * @var string|null - */ - private $animationName; - - /** - * @param int $iLineNo - */ - public function __construct($iLineNo = 0) - { - parent::__construct($iLineNo); - $this->vendorKeyFrame = null; - $this->animationName = null; - } - - /** - * @param string $vendorKeyFrame - */ - public function setVendorKeyFrame($vendorKeyFrame) - { - $this->vendorKeyFrame = $vendorKeyFrame; - } - - /** - * @return string|null - */ - public function getVendorKeyFrame() - { - return $this->vendorKeyFrame; - } - - /** - * @param string $animationName - */ - public function setAnimationName($animationName) - { - $this->animationName = $animationName; - } - - /** - * @return string|null - */ - public function getAnimationName() - { - return $this->animationName; - } - - /** - * @return string - */ - public function __toString() - { - return $this->render(new OutputFormat()); - } - - /** - * @return string - */ - public function render(OutputFormat $oOutputFormat) - { - $sResult = "@{$this->vendorKeyFrame} {$this->animationName}{$oOutputFormat->spaceBeforeOpeningBrace()}{"; - $sResult .= parent::render($oOutputFormat); - $sResult .= '}'; - return $sResult; - } - - /** - * @return bool - */ - public function isRootList() - { - return false; - } - - /** - * @return string|null - */ - public function atRuleName() - { - return $this->vendorKeyFrame; - } - - /** - * @return string|null - */ - public function atRuleArgs() - { - return $this->animationName; - } -} diff --git a/lib/sabberworm/php-css-parser/src/Comment/Comment.php b/lib/sabberworm/php-css-parser/src/Comment/Comment.php deleted file mode 100644 index 6128d7498..000000000 --- a/lib/sabberworm/php-css-parser/src/Comment/Comment.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Comment; - -use Sabberworm\CSS\OutputFormat; -use Sabberworm\CSS\Renderable; - -class Comment implements Renderable -{ - /** - * @var int - */ - protected $iLineNo; - - /** - * @var string - */ - protected $sComment; - - /** - * @param string $sComment - * @param int $iLineNo - */ - public function __construct($sComment = '', $iLineNo = 0) - { - $this->sComment = $sComment; - $this->iLineNo = $iLineNo; - } - - /** - * @return string - */ - public function getComment() - { - return $this->sComment; - } - - /** - * @return int - */ - public function getLineNo() - { - return $this->iLineNo; - } - - /** - * @param string $sComment - * - * @return void - */ - public function setComment($sComment) - { - $this->sComment = $sComment; - } - - /** - * @return string - */ - public function __toString() - { - return $this->render(new OutputFormat()); - } - - /** - * @return string - */ - public function render(OutputFormat $oOutputFormat) - { - return '/*' . $this->sComment . '*/'; - } -} diff --git a/lib/sabberworm/php-css-parser/src/Comment/Commentable.php b/lib/sabberworm/php-css-parser/src/Comment/Commentable.php deleted file mode 100644 index 5e450bfb3..000000000 --- a/lib/sabberworm/php-css-parser/src/Comment/Commentable.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Comment; - -interface Commentable -{ - /** - * @param array<array-key, Comment> $aComments - * - * @return void - */ - public function addComments(array $aComments); - - /** - * @return array<array-key, Comment> - */ - public function getComments(); - - /** - * @param array<array-key, Comment> $aComments - * - * @return void - */ - public function setComments(array $aComments); -} diff --git a/lib/sabberworm/php-css-parser/src/OutputFormat.php b/lib/sabberworm/php-css-parser/src/OutputFormat.php deleted file mode 100644 index 595d30643..000000000 --- a/lib/sabberworm/php-css-parser/src/OutputFormat.php +++ /dev/null @@ -1,334 +0,0 @@ -<?php - -namespace Sabberworm\CSS; - -/** - * Class OutputFormat - * - * @method OutputFormat setSemicolonAfterLastRule(bool $bSemicolonAfterLastRule) Set whether semicolons are added after - * last rule. - */ -class OutputFormat -{ - /** - * Value format: `"` means double-quote, `'` means single-quote - * - * @var string - */ - public $sStringQuotingType = '"'; - - /** - * Output RGB colors in hash notation if possible - * - * @var string - */ - public $bRGBHashNotation = true; - - /** - * Declaration format - * - * Semicolon after the last rule of a declaration block can be omitted. To do that, set this false. - * - * @var bool - */ - public $bSemicolonAfterLastRule = true; - - /** - * Spacing - * Note that these strings are not sanity-checked: the value should only consist of whitespace - * Any newline character will be indented according to the current level. - * The triples (After, Before, Between) can be set using a wildcard (e.g. `$oFormat->set('Space*Rules', "\n");`) - */ - public $sSpaceAfterRuleName = ' '; - - /** - * @var string - */ - public $sSpaceBeforeRules = ''; - - /** - * @var string - */ - public $sSpaceAfterRules = ''; - - /** - * @var string - */ - public $sSpaceBetweenRules = ''; - - /** - * @var string - */ - public $sSpaceBeforeBlocks = ''; - - /** - * @var string - */ - public $sSpaceAfterBlocks = ''; - - /** - * @var string - */ - public $sSpaceBetweenBlocks = "\n"; - - /** - * Content injected in and around at-rule blocks. - * - * @var string - */ - public $sBeforeAtRuleBlock = ''; - - /** - * @var string - */ - public $sAfterAtRuleBlock = ''; - - /** - * This is what’s printed before and after the comma if a declaration block contains multiple selectors. - * - * @var string - */ - public $sSpaceBeforeSelectorSeparator = ''; - - /** - * @var string - */ - public $sSpaceAfterSelectorSeparator = ' '; - - /** - * This is what’s printed after the comma of value lists - * - * @var string - */ - public $sSpaceBeforeListArgumentSeparator = ''; - - /** - * @var string - */ - public $sSpaceAfterListArgumentSeparator = ''; - - /** - * @var string - */ - public $sSpaceBeforeOpeningBrace = ' '; - - /** - * Content injected in and around declaration blocks. - * - * @var string - */ - public $sBeforeDeclarationBlock = ''; - - /** - * @var string - */ - public $sAfterDeclarationBlockSelectors = ''; - - /** - * @var string - */ - public $sAfterDeclarationBlock = ''; - - /** - * Indentation character(s) per level. Only applicable if newlines are used in any of the spacing settings. - * - * @var string - */ - public $sIndentation = "\t"; - - /** - * Output exceptions. - * - * @var bool - */ - public $bIgnoreExceptions = false; - - /** - * @var OutputFormatter|null - */ - private $oFormatter = null; - - /** - * @var OutputFormat|null - */ - private $oNextLevelFormat = null; - - /** - * @var int - */ - private $iIndentationLevel = 0; - - public function __construct() - { - } - - /** - * @param string $sName - * - * @return string|null - */ - public function get($sName) - { - $aVarPrefixes = ['a', 's', 'm', 'b', 'f', 'o', 'c', 'i']; - foreach ($aVarPrefixes as $sPrefix) { - $sFieldName = $sPrefix . ucfirst($sName); - if (isset($this->$sFieldName)) { - return $this->$sFieldName; - } - } - return null; - } - - /** - * @param array<array-key, string>|string $aNames - * @param mixed $mValue - * - * @return self|false - */ - public function set($aNames, $mValue) - { - $aVarPrefixes = ['a', 's', 'm', 'b', 'f', 'o', 'c', 'i']; - if (is_string($aNames) && strpos($aNames, '*') !== false) { - $aNames = - [ - str_replace('*', 'Before', $aNames), - str_replace('*', 'Between', $aNames), - str_replace('*', 'After', $aNames), - ]; - } elseif (!is_array($aNames)) { - $aNames = [$aNames]; - } - foreach ($aVarPrefixes as $sPrefix) { - $bDidReplace = false; - foreach ($aNames as $sName) { - $sFieldName = $sPrefix . ucfirst($sName); - if (isset($this->$sFieldName)) { - $this->$sFieldName = $mValue; - $bDidReplace = true; - } - } - if ($bDidReplace) { - return $this; - } - } - // Break the chain so the user knows this option is invalid - return false; - } - - /** - * @param string $sMethodName - * @param array<array-key, mixed> $aArguments - * - * @return mixed - * - * @throws \Exception - */ - public function __call($sMethodName, array $aArguments) - { - if (strpos($sMethodName, 'set') === 0) { - return $this->set(substr($sMethodName, 3), $aArguments[0]); - } elseif (strpos($sMethodName, 'get') === 0) { - return $this->get(substr($sMethodName, 3)); - } elseif (method_exists(OutputFormatter::class, $sMethodName)) { - return call_user_func_array([$this->getFormatter(), $sMethodName], $aArguments); - } else { - throw new \Exception('Unknown OutputFormat method called: ' . $sMethodName); - } - } - - /** - * @param int $iNumber - * - * @return self - */ - public function indentWithTabs($iNumber = 1) - { - return $this->setIndentation(str_repeat("\t", $iNumber)); - } - - /** - * @param int $iNumber - * - * @return self - */ - public function indentWithSpaces($iNumber = 2) - { - return $this->setIndentation(str_repeat(" ", $iNumber)); - } - - /** - * @return OutputFormat - */ - public function nextLevel() - { - if ($this->oNextLevelFormat === null) { - $this->oNextLevelFormat = clone $this; - $this->oNextLevelFormat->iIndentationLevel++; - $this->oNextLevelFormat->oFormatter = null; - } - return $this->oNextLevelFormat; - } - - /** - * @return void - */ - public function beLenient() - { - $this->bIgnoreExceptions = true; - } - - /** - * @return OutputFormatter - */ - public function getFormatter() - { - if ($this->oFormatter === null) { - $this->oFormatter = new OutputFormatter($this); - } - return $this->oFormatter; - } - - /** - * @return int - */ - public function level() - { - return $this->iIndentationLevel; - } - - /** - * Creates an instance of this class without any particular formatting settings. - * - * @return self - */ - public static function create() - { - return new OutputFormat(); - } - - /** - * Creates an instance of this class with a preset for compact formatting. - * - * @return self - */ - public static function createCompact() - { - $format = self::create(); - $format->set('Space*Rules', "")->set('Space*Blocks', "")->setSpaceAfterRuleName('') - ->setSpaceBeforeOpeningBrace('')->setSpaceAfterSelectorSeparator(''); - return $format; - } - - /** - * Creates an instance of this class with a preset for pretty formatting. - * - * @return self - */ - public static function createPretty() - { - $format = self::create(); - $format->set('Space*Rules', "\n")->set('Space*Blocks', "\n") - ->setSpaceBetweenBlocks("\n\n")->set('SpaceAfterListArgumentSeparator', ['default' => '', ',' => ' ']); - return $format; - } -} diff --git a/lib/sabberworm/php-css-parser/src/OutputFormatter.php b/lib/sabberworm/php-css-parser/src/OutputFormatter.php deleted file mode 100644 index 535feca7f..000000000 --- a/lib/sabberworm/php-css-parser/src/OutputFormatter.php +++ /dev/null @@ -1,231 +0,0 @@ -<?php - -namespace Sabberworm\CSS; - -use Sabberworm\CSS\Parsing\OutputException; - -class OutputFormatter -{ - /** - * @var OutputFormat - */ - private $oFormat; - - public function __construct(OutputFormat $oFormat) - { - $this->oFormat = $oFormat; - } - - /** - * @param string $sName - * @param string|null $sType - * - * @return string - */ - public function space($sName, $sType = null) - { - $sSpaceString = $this->oFormat->get("Space$sName"); - // If $sSpaceString is an array, we have multiple values configured - // depending on the type of object the space applies to - if (is_array($sSpaceString)) { - if ($sType !== null && isset($sSpaceString[$sType])) { - $sSpaceString = $sSpaceString[$sType]; - } else { - $sSpaceString = reset($sSpaceString); - } - } - return $this->prepareSpace($sSpaceString); - } - - /** - * @return string - */ - public function spaceAfterRuleName() - { - return $this->space('AfterRuleName'); - } - - /** - * @return string - */ - public function spaceBeforeRules() - { - return $this->space('BeforeRules'); - } - - /** - * @return string - */ - public function spaceAfterRules() - { - return $this->space('AfterRules'); - } - - /** - * @return string - */ - public function spaceBetweenRules() - { - return $this->space('BetweenRules'); - } - - /** - * @return string - */ - public function spaceBeforeBlocks() - { - return $this->space('BeforeBlocks'); - } - - /** - * @return string - */ - public function spaceAfterBlocks() - { - return $this->space('AfterBlocks'); - } - - /** - * @return string - */ - public function spaceBetweenBlocks() - { - return $this->space('BetweenBlocks'); - } - - /** - * @return string - */ - public function spaceBeforeSelectorSeparator() - { - return $this->space('BeforeSelectorSeparator'); - } - - /** - * @return string - */ - public function spaceAfterSelectorSeparator() - { - return $this->space('AfterSelectorSeparator'); - } - - /** - * @param string $sSeparator - * - * @return string - */ - public function spaceBeforeListArgumentSeparator($sSeparator) - { - return $this->space('BeforeListArgumentSeparator', $sSeparator); - } - - /** - * @param string $sSeparator - * - * @return string - */ - public function spaceAfterListArgumentSeparator($sSeparator) - { - return $this->space('AfterListArgumentSeparator', $sSeparator); - } - - /** - * @return string - */ - public function spaceBeforeOpeningBrace() - { - return $this->space('BeforeOpeningBrace'); - } - - /** - * Runs the given code, either swallowing or passing exceptions, depending on the `bIgnoreExceptions` setting. - * - * @param string $cCode the name of the function to call - * - * @return string|null - */ - public function safely($cCode) - { - if ($this->oFormat->get('IgnoreExceptions')) { - // If output exceptions are ignored, run the code with exception guards - try { - return $cCode(); - } catch (OutputException $e) { - return null; - } // Do nothing - } else { - // Run the code as-is - return $cCode(); - } - } - - /** - * Clone of the `implode` function, but calls `render` with the current output format instead of `__toString()`. - * - * @param string $sSeparator - * @param array<array-key, Renderable|string> $aValues - * @param bool $bIncreaseLevel - * - * @return string - */ - public function implode($sSeparator, array $aValues, $bIncreaseLevel = false) - { - $sResult = ''; - $oFormat = $this->oFormat; - if ($bIncreaseLevel) { - $oFormat = $oFormat->nextLevel(); - } - $bIsFirst = true; - foreach ($aValues as $mValue) { - if ($bIsFirst) { - $bIsFirst = false; - } else { - $sResult .= $sSeparator; - } - if ($mValue instanceof Renderable) { - $sResult .= $mValue->render($oFormat); - } else { - $sResult .= $mValue; - } - } - return $sResult; - } - - /** - * @param string $sString - * - * @return string - */ - public function removeLastSemicolon($sString) - { - if ($this->oFormat->get('SemicolonAfterLastRule')) { - return $sString; - } - $sString = explode(';', $sString); - if (count($sString) < 2) { - return $sString[0]; - } - $sLast = array_pop($sString); - $sNextToLast = array_pop($sString); - array_push($sString, $sNextToLast . $sLast); - return implode(';', $sString); - } - - /** - * @param string $sSpaceString - * - * @return string - */ - private function prepareSpace($sSpaceString) - { - return str_replace("\n", "\n" . $this->indent(), $sSpaceString); - } - - /** - * @return string - */ - private function indent() - { - return str_repeat($this->oFormat->sIndentation, $this->oFormat->level()); - } -} diff --git a/lib/sabberworm/php-css-parser/src/Parser.php b/lib/sabberworm/php-css-parser/src/Parser.php deleted file mode 100644 index f3b0493a5..000000000 --- a/lib/sabberworm/php-css-parser/src/Parser.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php - -namespace Sabberworm\CSS; - -use Sabberworm\CSS\CSSList\Document; -use Sabberworm\CSS\Parsing\ParserState; -use Sabberworm\CSS\Parsing\SourceException; - -/** - * This class parses CSS from text into a data structure. - */ -class Parser -{ - /** - * @var ParserState - */ - private $oParserState; - - /** - * @param string $sText - * @param Settings|null $oParserSettings - * @param int $iLineNo the line number (starting from 1, not from 0) - */ - public function __construct($sText, Settings $oParserSettings = null, $iLineNo = 1) - { - if ($oParserSettings === null) { - $oParserSettings = Settings::create(); - } - $this->oParserState = new ParserState($sText, $oParserSettings, $iLineNo); - } - - /** - * @param string $sCharset - * - * @return void - */ - public function setCharset($sCharset) - { - $this->oParserState->setCharset($sCharset); - } - - /** - * @return void - */ - public function getCharset() - { - // Note: The `return` statement is missing here. This is a bug that needs to be fixed. - $this->oParserState->getCharset(); - } - - /** - * @return Document - * - * @throws SourceException - */ - public function parse() - { - return Document::parse($this->oParserState); - } -} diff --git a/lib/sabberworm/php-css-parser/src/Parsing/OutputException.php b/lib/sabberworm/php-css-parser/src/Parsing/OutputException.php deleted file mode 100644 index 9bfbc75fb..000000000 --- a/lib/sabberworm/php-css-parser/src/Parsing/OutputException.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Parsing; - -/** - * Thrown if the CSS parser attempts to print something invalid. - */ -class OutputException extends SourceException -{ - /** - * @param string $sMessage - * @param int $iLineNo - */ - public function __construct($sMessage, $iLineNo = 0) - { - parent::__construct($sMessage, $iLineNo); - } -} diff --git a/lib/sabberworm/php-css-parser/src/Parsing/ParserState.php b/lib/sabberworm/php-css-parser/src/Parsing/ParserState.php deleted file mode 100644 index e7d85ee0f..000000000 --- a/lib/sabberworm/php-css-parser/src/Parsing/ParserState.php +++ /dev/null @@ -1,516 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Parsing; - -use Sabberworm\CSS\Comment\Comment; -use Sabberworm\CSS\Settings; - -class ParserState -{ - /** - * @var null - */ - const EOF = null; - - /** - * @var Settings - */ - private $oParserSettings; - - /** - * @var string - */ - private $sText; - - /** - * @var array<int, string> - */ - private $aText; - - /** - * @var int - */ - private $iCurrentPosition; - - /** - * @var string - */ - private $sCharset; - - /** - * @var int - */ - private $iLength; - - /** - * @var int - */ - private $iLineNo; - - /** - * @param string $sText - * @param int $iLineNo - */ - public function __construct($sText, Settings $oParserSettings, $iLineNo = 1) - { - $this->oParserSettings = $oParserSettings; - $this->sText = $sText; - $this->iCurrentPosition = 0; - $this->iLineNo = $iLineNo; - $this->setCharset($this->oParserSettings->sDefaultCharset); - } - - /** - * @param string $sCharset - * - * @return void - */ - public function setCharset($sCharset) - { - $this->sCharset = $sCharset; - $this->aText = $this->strsplit($this->sText); - if (is_array($this->aText)) { - $this->iLength = count($this->aText); - } - } - - /** - * @return string - */ - public function getCharset() - { - return $this->sCharset; - } - - /** - * @return int - */ - public function currentLine() - { - return $this->iLineNo; - } - - /** - * @return int - */ - public function currentColumn() - { - return $this->iCurrentPosition; - } - - /** - * @return Settings - */ - public function getSettings() - { - return $this->oParserSettings; - } - - /** - * @param bool $bIgnoreCase - * - * @return string - * - * @throws UnexpectedTokenException - */ - public function parseIdentifier($bIgnoreCase = true) - { - $sResult = $this->parseCharacter(true); - if ($sResult === null) { - throw new UnexpectedTokenException($sResult, $this->peek(5), 'identifier', $this->iLineNo); - } - $sCharacter = null; - while (($sCharacter = $this->parseCharacter(true)) !== null) { - if (preg_match('/[a-zA-Z0-9\x{00A0}-\x{FFFF}_-]/Sux', $sCharacter)) { - $sResult .= $sCharacter; - } else { - $sResult .= '\\' . $sCharacter; - } - } - if ($bIgnoreCase) { - $sResult = $this->strtolower($sResult); - } - return $sResult; - } - - /** - * @param bool $bIsForIdentifier - * - * @return string|null - * - * @throws UnexpectedEOFException - * @throws UnexpectedTokenException - */ - public function parseCharacter($bIsForIdentifier) - { - if ($this->peek() === '\\') { - if ( - $bIsForIdentifier && $this->oParserSettings->bLenientParsing - && ($this->comes('\0') || $this->comes('\9')) - ) { - // Non-strings can contain \0 or \9 which is an IE hack supported in lenient parsing. - return null; - } - $this->consume('\\'); - if ($this->comes('\n') || $this->comes('\r')) { - return ''; - } - if (preg_match('/[0-9a-fA-F]/Su', $this->peek()) === 0) { - return $this->consume(1); - } - $sUnicode = $this->consumeExpression('/^[0-9a-fA-F]{1,6}/u', 6); - if ($this->strlen($sUnicode) < 6) { - // Consume whitespace after incomplete unicode escape - if (preg_match('/\\s/isSu', $this->peek())) { - if ($this->comes('\r\n')) { - $this->consume(2); - } else { - $this->consume(1); - } - } - } - $iUnicode = intval($sUnicode, 16); - $sUtf32 = ""; - for ($i = 0; $i < 4; ++$i) { - $sUtf32 .= chr($iUnicode & 0xff); - $iUnicode = $iUnicode >> 8; - } - return iconv('utf-32le', $this->sCharset, $sUtf32); - } - if ($bIsForIdentifier) { - $peek = ord($this->peek()); - // Ranges: a-z A-Z 0-9 - _ - if ( - ($peek >= 97 && $peek <= 122) - || ($peek >= 65 && $peek <= 90) - || ($peek >= 48 && $peek <= 57) - || ($peek === 45) - || ($peek === 95) - || ($peek > 0xa1) - ) { - return $this->consume(1); - } - } else { - return $this->consume(1); - } - return null; - } - - /** - * @return array<int, Comment>|void - * - * @throws UnexpectedEOFException - * @throws UnexpectedTokenException - */ - public function consumeWhiteSpace() - { - $comments = []; - do { - while (preg_match('/\\s/isSu', $this->peek()) === 1) { - $this->consume(1); - } - if ($this->oParserSettings->bLenientParsing) { - try { - $oComment = $this->consumeComment(); - } catch (UnexpectedEOFException $e) { - $this->iCurrentPosition = $this->iLength; - return; - } - } else { - $oComment = $this->consumeComment(); - } - if ($oComment !== false) { - $comments[] = $oComment; - } - } while ($oComment !== false); - return $comments; - } - - /** - * @param string $sString - * @param bool $bCaseInsensitive - * - * @return bool - */ - public function comes($sString, $bCaseInsensitive = false) - { - $sPeek = $this->peek(strlen($sString)); - return ($sPeek == '') - ? false - : $this->streql($sPeek, $sString, $bCaseInsensitive); - } - - /** - * @param int $iLength - * @param int $iOffset - * - * @return string - */ - public function peek($iLength = 1, $iOffset = 0) - { - $iOffset += $this->iCurrentPosition; - if ($iOffset >= $this->iLength) { - return ''; - } - return $this->substr($iOffset, $iLength); - } - - /** - * @param int $mValue - * - * @return string - * - * @throws UnexpectedEOFException - * @throws UnexpectedTokenException - */ - public function consume($mValue = 1) - { - if (is_string($mValue)) { - $iLineCount = substr_count($mValue, "\n"); - $iLength = $this->strlen($mValue); - if (!$this->streql($this->substr($this->iCurrentPosition, $iLength), $mValue)) { - throw new UnexpectedTokenException($mValue, $this->peek(max($iLength, 5)), $this->iLineNo); - } - $this->iLineNo += $iLineCount; - $this->iCurrentPosition += $this->strlen($mValue); - return $mValue; - } else { - if ($this->iCurrentPosition + $mValue > $this->iLength) { - throw new UnexpectedEOFException($mValue, $this->peek(5), 'count', $this->iLineNo); - } - $sResult = $this->substr($this->iCurrentPosition, $mValue); - $iLineCount = substr_count($sResult, "\n"); - $this->iLineNo += $iLineCount; - $this->iCurrentPosition += $mValue; - return $sResult; - } - } - - /** - * @param string $mExpression - * @param int|null $iMaxLength - * - * @return string - * - * @throws UnexpectedEOFException - * @throws UnexpectedTokenException - */ - public function consumeExpression($mExpression, $iMaxLength = null) - { - $aMatches = null; - $sInput = $iMaxLength !== null ? $this->peek($iMaxLength) : $this->inputLeft(); - if (preg_match($mExpression, $sInput, $aMatches, PREG_OFFSET_CAPTURE) === 1) { - return $this->consume($aMatches[0][0]); - } - throw new UnexpectedTokenException($mExpression, $this->peek(5), 'expression', $this->iLineNo); - } - - /** - * @return Comment|false - */ - public function consumeComment() - { - $mComment = false; - if ($this->comes('/*')) { - $iLineNo = $this->iLineNo; - $this->consume(1); - $mComment = ''; - while (($char = $this->consume(1)) !== '') { - $mComment .= $char; - if ($this->comes('*/')) { - $this->consume(2); - break; - } - } - } - - if ($mComment !== false) { - // We skip the * which was included in the comment. - return new Comment(substr($mComment, 1), $iLineNo); - } - - return $mComment; - } - - /** - * @return bool - */ - public function isEnd() - { - return $this->iCurrentPosition >= $this->iLength; - } - - /** - * @param array<array-key, string>|string $aEnd - * @param string $bIncludeEnd - * @param string $consumeEnd - * @param array<int, Comment> $comments - * - * @return string - * - * @throws UnexpectedEOFException - * @throws UnexpectedTokenException - */ - public function consumeUntil($aEnd, $bIncludeEnd = false, $consumeEnd = false, array &$comments = []) - { - $aEnd = is_array($aEnd) ? $aEnd : [$aEnd]; - $out = ''; - $start = $this->iCurrentPosition; - - while (!$this->isEnd()) { - $char = $this->consume(1); - if (in_array($char, $aEnd)) { - if ($bIncludeEnd) { - $out .= $char; - } elseif (!$consumeEnd) { - $this->iCurrentPosition -= $this->strlen($char); - } - return $out; - } - $out .= $char; - if ($comment = $this->consumeComment()) { - $comments[] = $comment; - } - } - - if (in_array(self::EOF, $aEnd)) { - return $out; - } - - $this->iCurrentPosition = $start; - throw new UnexpectedEOFException( - 'One of ("' . implode('","', $aEnd) . '")', - $this->peek(5), - 'search', - $this->iLineNo - ); - } - - /** - * @return string - */ - private function inputLeft() - { - return $this->substr($this->iCurrentPosition, -1); - } - - /** - * @param string $sString1 - * @param string $sString2 - * @param bool $bCaseInsensitive - * - * @return bool - */ - public function streql($sString1, $sString2, $bCaseInsensitive = true) - { - if ($bCaseInsensitive) { - return $this->strtolower($sString1) === $this->strtolower($sString2); - } else { - return $sString1 === $sString2; - } - } - - /** - * @param int $iAmount - * - * @return void - */ - public function backtrack($iAmount) - { - $this->iCurrentPosition -= $iAmount; - } - - /** - * @param string $sString - * - * @return int - */ - public function strlen($sString) - { - if ($this->oParserSettings->bMultibyteSupport) { - return mb_strlen($sString, $this->sCharset); - } else { - return strlen($sString); - } - } - - /** - * @param int $iStart - * @param int $iLength - * - * @return string - */ - private function substr($iStart, $iLength) - { - if ($iLength < 0) { - $iLength = $this->iLength - $iStart + $iLength; - } - if ($iStart + $iLength > $this->iLength) { - $iLength = $this->iLength - $iStart; - } - $sResult = ''; - while ($iLength > 0) { - $sResult .= $this->aText[$iStart]; - $iStart++; - $iLength--; - } - return $sResult; - } - - /** - * @param string $sString - * - * @return string - */ - private function strtolower($sString) - { - if ($this->oParserSettings->bMultibyteSupport) { - return mb_strtolower($sString, $this->sCharset); - } else { - return strtolower($sString); - } - } - - /** - * @param string $sString - * - * @return array<int, string> - */ - private function strsplit($sString) - { - if ($this->oParserSettings->bMultibyteSupport) { - if ($this->streql($this->sCharset, 'utf-8')) { - return preg_split('//u', $sString, -1, PREG_SPLIT_NO_EMPTY); - } else { - $iLength = mb_strlen($sString, $this->sCharset); - $aResult = []; - for ($i = 0; $i < $iLength; ++$i) { - $aResult[] = mb_substr($sString, $i, 1, $this->sCharset); - } - return $aResult; - } - } else { - if ($sString === '') { - return []; - } else { - return str_split($sString); - } - } - } - - /** - * @param string $sString - * @param string $sNeedle - * @param int $iOffset - * - * @return int|false - */ - private function strpos($sString, $sNeedle, $iOffset) - { - if ($this->oParserSettings->bMultibyteSupport) { - return mb_strpos($sString, $sNeedle, $iOffset, $this->sCharset); - } else { - return strpos($sString, $sNeedle, $iOffset); - } - } -} diff --git a/lib/sabberworm/php-css-parser/src/Parsing/SourceException.php b/lib/sabberworm/php-css-parser/src/Parsing/SourceException.php deleted file mode 100644 index 1ca668a99..000000000 --- a/lib/sabberworm/php-css-parser/src/Parsing/SourceException.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Parsing; - -class SourceException extends \Exception -{ - /** - * @var int - */ - private $iLineNo; - - /** - * @param string $sMessage - * @param int $iLineNo - */ - public function __construct($sMessage, $iLineNo = 0) - { - $this->iLineNo = $iLineNo; - if (!empty($iLineNo)) { - $sMessage .= " [line no: $iLineNo]"; - } - parent::__construct($sMessage); - } - - /** - * @return int - */ - public function getLineNo() - { - return $this->iLineNo; - } -} diff --git a/lib/sabberworm/php-css-parser/src/Parsing/UnexpectedEOFException.php b/lib/sabberworm/php-css-parser/src/Parsing/UnexpectedEOFException.php deleted file mode 100644 index 368ec70c7..000000000 --- a/lib/sabberworm/php-css-parser/src/Parsing/UnexpectedEOFException.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Parsing; - -/** - * Thrown if the CSS parser encounters end of file it did not expect. - * - * Extends `UnexpectedTokenException` in order to preserve backwards compatibility. - */ -class UnexpectedEOFException extends UnexpectedTokenException -{ -} diff --git a/lib/sabberworm/php-css-parser/src/Parsing/UnexpectedTokenException.php b/lib/sabberworm/php-css-parser/src/Parsing/UnexpectedTokenException.php deleted file mode 100644 index 7d5b1a64d..000000000 --- a/lib/sabberworm/php-css-parser/src/Parsing/UnexpectedTokenException.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Parsing; - -/** - * Thrown if the CSS parser encounters a token it did not expect. - */ -class UnexpectedTokenException extends SourceException -{ - /** - * @var string - */ - private $sExpected; - - /** - * @var string - */ - private $sFound; - - /** - * Possible values: literal, identifier, count, expression, search - * - * @var string - */ - private $sMatchType; - - /** - * @param string $sExpected - * @param string $sFound - * @param string $sMatchType - * @param int $iLineNo - */ - public function __construct($sExpected, $sFound, $sMatchType = 'literal', $iLineNo = 0) - { - $this->sExpected = $sExpected; - $this->sFound = $sFound; - $this->sMatchType = $sMatchType; - $sMessage = "Token “{$sExpected}” ({$sMatchType}) not found. Got “{$sFound}”."; - if ($this->sMatchType === 'search') { - $sMessage = "Search for “{$sExpected}” returned no results. Context: “{$sFound}”."; - } elseif ($this->sMatchType === 'count') { - $sMessage = "Next token was expected to have {$sExpected} chars. Context: “{$sFound}”."; - } elseif ($this->sMatchType === 'identifier') { - $sMessage = "Identifier expected. Got “{$sFound}”"; - } elseif ($this->sMatchType === 'custom') { - $sMessage = trim("$sExpected $sFound"); - } - - parent::__construct($sMessage, $iLineNo); - } -} diff --git a/lib/sabberworm/php-css-parser/src/Property/AtRule.php b/lib/sabberworm/php-css-parser/src/Property/AtRule.php deleted file mode 100644 index 9536ff5e9..000000000 --- a/lib/sabberworm/php-css-parser/src/Property/AtRule.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Property; - -use Sabberworm\CSS\Comment\Commentable; -use Sabberworm\CSS\Renderable; - -interface AtRule extends Renderable, Commentable -{ - /** - * Since there are more set rules than block rules, - * we’re whitelisting the block rules and have anything else be treated as a set rule. - * - * @var string - */ - const BLOCK_RULES = 'media/document/supports/region-style/font-feature-values'; - - /** - * … and more font-specific ones (to be used inside font-feature-values) - * - * @var string - */ - const SET_RULES = 'font-face/counter-style/page/swash/styleset/annotation'; - - /** - * @return string|null - */ - public function atRuleName(); - - /** - * @return string|null - */ - public function atRuleArgs(); -} diff --git a/lib/sabberworm/php-css-parser/src/Property/CSSNamespace.php b/lib/sabberworm/php-css-parser/src/Property/CSSNamespace.php deleted file mode 100644 index 0d7eb4969..000000000 --- a/lib/sabberworm/php-css-parser/src/Property/CSSNamespace.php +++ /dev/null @@ -1,154 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Property; - -use Sabberworm\CSS\Comment\Comment; -use Sabberworm\CSS\OutputFormat; - -/** - * `CSSNamespace` represents an `@namespace` rule. - */ -class CSSNamespace implements AtRule -{ - /** - * @var string - */ - private $mUrl; - - /** - * @var string - */ - private $sPrefix; - - /** - * @var int - */ - private $iLineNo; - - /** - * @var array<array-key, Comment> - */ - protected $aComments; - - /** - * @param string $mUrl - * @param string|null $sPrefix - * @param int $iLineNo - */ - public function __construct($mUrl, $sPrefix = null, $iLineNo = 0) - { - $this->mUrl = $mUrl; - $this->sPrefix = $sPrefix; - $this->iLineNo = $iLineNo; - $this->aComments = []; - } - - /** - * @return int - */ - public function getLineNo() - { - return $this->iLineNo; - } - - /** - * @return string - */ - public function __toString() - { - return $this->render(new OutputFormat()); - } - - /** - * @return string - */ - public function render(OutputFormat $oOutputFormat) - { - return '@namespace ' . ($this->sPrefix === null ? '' : $this->sPrefix . ' ') - . $this->mUrl->render($oOutputFormat) . ';'; - } - - /** - * @return string - */ - public function getUrl() - { - return $this->mUrl; - } - - /** - * @return string|null - */ - public function getPrefix() - { - return $this->sPrefix; - } - - /** - * @param string $mUrl - * - * @return void - */ - public function setUrl($mUrl) - { - $this->mUrl = $mUrl; - } - - /** - * @param string $sPrefix - * - * @return void - */ - public function setPrefix($sPrefix) - { - $this->sPrefix = $sPrefix; - } - - /** - * @return string - */ - public function atRuleName() - { - return 'namespace'; - } - - /** - * @return array<int, string> - */ - public function atRuleArgs() - { - $aResult = [$this->mUrl]; - if ($this->sPrefix) { - array_unshift($aResult, $this->sPrefix); - } - return $aResult; - } - - /** - * @param array<array-key, Comment> $aComments - * - * @return void - */ - public function addComments(array $aComments) - { - $this->aComments = array_merge($this->aComments, $aComments); - } - - /** - * @return array<array-key, Comment> - */ - public function getComments() - { - return $this->aComments; - } - - /** - * @param array<array-key, Comment> $aComments - * - * @return void - */ - public function setComments(array $aComments) - { - $this->aComments = $aComments; - } -} diff --git a/lib/sabberworm/php-css-parser/src/Property/Charset.php b/lib/sabberworm/php-css-parser/src/Property/Charset.php deleted file mode 100644 index 3ee0c3d04..000000000 --- a/lib/sabberworm/php-css-parser/src/Property/Charset.php +++ /dev/null @@ -1,129 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Property; - -use Sabberworm\CSS\Comment\Comment; -use Sabberworm\CSS\OutputFormat; - -/** - * Class representing an `@charset` rule. - * - * The following restrictions apply: - * - May not be found in any CSSList other than the Document. - * - May only appear at the very top of a Document’s contents. - * - Must not appear more than once. - */ -class Charset implements AtRule -{ - /** - * @var string - */ - private $sCharset; - - /** - * @var int - */ - protected $iLineNo; - - /** - * @var array<array-key, Comment> - */ - protected $aComments; - - /** - * @param string $sCharset - * @param int $iLineNo - */ - public function __construct($sCharset, $iLineNo = 0) - { - $this->sCharset = $sCharset; - $this->iLineNo = $iLineNo; - $this->aComments = []; - } - - /** - * @return int - */ - public function getLineNo() - { - return $this->iLineNo; - } - - /** - * @param string $sCharset - * - * @return void - */ - public function setCharset($sCharset) - { - $this->sCharset = $sCharset; - } - - /** - * @return string - */ - public function getCharset() - { - return $this->sCharset; - } - - /** - * @return string - */ - public function __toString() - { - return $this->render(new OutputFormat()); - } - - /** - * @return string - */ - public function render(OutputFormat $oOutputFormat) - { - return "@charset {$this->sCharset->render($oOutputFormat)};"; - } - - /** - * @return string - */ - public function atRuleName() - { - return 'charset'; - } - - /** - * @return string - */ - public function atRuleArgs() - { - return $this->sCharset; - } - - /** - * @param array<array-key, Comment> $aComments - * - * @return void - */ - public function addComments(array $aComments) - { - $this->aComments = array_merge($this->aComments, $aComments); - } - - /** - * @return array<array-key, Comment> - */ - public function getComments() - { - return $this->aComments; - } - - /** - * @param array<array-key, Comment> $aComments - * - * @return void - */ - public function setComments(array $aComments) - { - $this->aComments = $aComments; - } -} diff --git a/lib/sabberworm/php-css-parser/src/Property/Import.php b/lib/sabberworm/php-css-parser/src/Property/Import.php deleted file mode 100644 index a2253016b..000000000 --- a/lib/sabberworm/php-css-parser/src/Property/Import.php +++ /dev/null @@ -1,137 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Property; - -use Sabberworm\CSS\Comment\Comment; -use Sabberworm\CSS\OutputFormat; -use Sabberworm\CSS\Value\URL; - -/** - * Class representing an `@import` rule. - */ -class Import implements AtRule -{ - /** - * @var URL - */ - private $oLocation; - - /** - * @var string - */ - private $sMediaQuery; - - /** - * @var int - */ - protected $iLineNo; - - /** - * @var array<array-key, Comment> - */ - protected $aComments; - - /** - * @param URL $oLocation - * @param string $sMediaQuery - * @param int $iLineNo - */ - public function __construct(URL $oLocation, $sMediaQuery, $iLineNo = 0) - { - $this->oLocation = $oLocation; - $this->sMediaQuery = $sMediaQuery; - $this->iLineNo = $iLineNo; - $this->aComments = []; - } - - /** - * @return int - */ - public function getLineNo() - { - return $this->iLineNo; - } - - /** - * @param URL $oLocation - * - * @return void - */ - public function setLocation($oLocation) - { - $this->oLocation = $oLocation; - } - - /** - * @return URL - */ - public function getLocation() - { - return $this->oLocation; - } - - /** - * @return string - */ - public function __toString() - { - return $this->render(new OutputFormat()); - } - - /** - * @return string - */ - public function render(OutputFormat $oOutputFormat) - { - return "@import " . $this->oLocation->render($oOutputFormat) - . ($this->sMediaQuery === null ? '' : ' ' . $this->sMediaQuery) . ';'; - } - - /** - * @return string - */ - public function atRuleName() - { - return 'import'; - } - - /** - * @return array<int, URL|string> - */ - public function atRuleArgs() - { - $aResult = [$this->oLocation]; - if ($this->sMediaQuery) { - array_push($aResult, $this->sMediaQuery); - } - return $aResult; - } - - /** - * @param array<array-key, Comment> $aComments - * - * @return void - */ - public function addComments(array $aComments) - { - $this->aComments = array_merge($this->aComments, $aComments); - } - - /** - * @return array<array-key, Comment> - */ - public function getComments() - { - return $this->aComments; - } - - /** - * @param array<array-key, Comment> $aComments - * - * @return void - */ - public function setComments(array $aComments) - { - $this->aComments = $aComments; - } -} diff --git a/lib/sabberworm/php-css-parser/src/Property/KeyframeSelector.php b/lib/sabberworm/php-css-parser/src/Property/KeyframeSelector.php deleted file mode 100644 index 14ea5ebb7..000000000 --- a/lib/sabberworm/php-css-parser/src/Property/KeyframeSelector.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Property; - -class KeyframeSelector extends Selector -{ - /** - * regexp for specificity calculations - * - * @var string - */ - const SELECTOR_VALIDATION_RX = '/ - ^( - (?: - [a-zA-Z0-9\x{00A0}-\x{FFFF}_^$|*="\'~\[\]()\-\s\.:#+>]* # any sequence of valid unescaped characters - (?:\\\\.)? # a single escaped character - (?:([\'"]).*?(?<!\\\\)\2)? # a quoted text like [id="example"] - )* - )| - (\d+%) # keyframe animation progress percentage (e.g. 50%) - $ - /ux'; -} diff --git a/lib/sabberworm/php-css-parser/src/Property/Selector.php b/lib/sabberworm/php-css-parser/src/Property/Selector.php deleted file mode 100644 index 70c9b2fd5..000000000 --- a/lib/sabberworm/php-css-parser/src/Property/Selector.php +++ /dev/null @@ -1,138 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Property; - -/** - * Class representing a single CSS selector. Selectors have to be split by the comma prior to being passed into this - * class. - */ -class Selector -{ - /** - * regexp for specificity calculations - * - * @var string - */ - const NON_ID_ATTRIBUTES_AND_PSEUDO_CLASSES_RX = '/ - (\.[\w]+) # classes - | - \[(\w+) # attributes - | - (\:( # pseudo classes - link|visited|active - |hover|focus - |lang - |target - |enabled|disabled|checked|indeterminate - |root - |nth-child|nth-last-child|nth-of-type|nth-last-of-type - |first-child|last-child|first-of-type|last-of-type - |only-child|only-of-type - |empty|contains - )) - /ix'; - - /** - * regexp for specificity calculations - * - * @var string - */ - const ELEMENTS_AND_PSEUDO_ELEMENTS_RX = '/ - ((^|[\s\+\>\~]+)[\w]+ # elements - | - \:{1,2}( # pseudo-elements - after|before|first-letter|first-line|selection - )) - /ix'; - - /** - * regexp for specificity calculations - * - * @var string - */ - const SELECTOR_VALIDATION_RX = '/ - ^( - (?: - [a-zA-Z0-9\x{00A0}-\x{FFFF}_^$|*="\'~\[\]()\-\s\.:#+>]* # any sequence of valid unescaped characters - (?:\\\\.)? # a single escaped character - (?:([\'"]).*?(?<!\\\\)\2)? # a quoted text like [id="example"] - )* - )$ - /ux'; - - /** - * @var string - */ - private $sSelector; - - /** - * @var int|null - */ - private $iSpecificity; - - /** - * @param string $sSelector - * - * @return bool - */ - public static function isValid($sSelector) - { - return preg_match(static::SELECTOR_VALIDATION_RX, $sSelector); - } - - /** - * @param string $sSelector - * @param bool $bCalculateSpecificity - */ - public function __construct($sSelector, $bCalculateSpecificity = false) - { - $this->setSelector($sSelector); - if ($bCalculateSpecificity) { - $this->getSpecificity(); - } - } - - /** - * @return string - */ - public function getSelector() - { - return $this->sSelector; - } - - /** - * @param string $sSelector - * - * @return void - */ - public function setSelector($sSelector) - { - $this->sSelector = trim($sSelector); - $this->iSpecificity = null; - } - - /** - * @return string - */ - public function __toString() - { - return $this->getSelector(); - } - - /** - * @return int - */ - public function getSpecificity() - { - if ($this->iSpecificity === null) { - $a = 0; - /// @todo should exclude \# as well as "#" - $aMatches = null; - $b = substr_count($this->sSelector, '#'); - $c = preg_match_all(self::NON_ID_ATTRIBUTES_AND_PSEUDO_CLASSES_RX, $this->sSelector, $aMatches); - $d = preg_match_all(self::ELEMENTS_AND_PSEUDO_ELEMENTS_RX, $this->sSelector, $aMatches); - $this->iSpecificity = ($a * 1000) + ($b * 100) + ($c * 10) + $d; - } - return $this->iSpecificity; - } -} diff --git a/lib/sabberworm/php-css-parser/src/Renderable.php b/lib/sabberworm/php-css-parser/src/Renderable.php deleted file mode 100644 index dc1bff3c1..000000000 --- a/lib/sabberworm/php-css-parser/src/Renderable.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -namespace Sabberworm\CSS; - -interface Renderable -{ - /** - * @return string - */ - public function __toString(); - - /** - * @return string - */ - public function render(OutputFormat $oOutputFormat); - - /** - * @return int - */ - public function getLineNo(); -} diff --git a/lib/sabberworm/php-css-parser/src/Rule/Rule.php b/lib/sabberworm/php-css-parser/src/Rule/Rule.php deleted file mode 100644 index c1ea6df74..000000000 --- a/lib/sabberworm/php-css-parser/src/Rule/Rule.php +++ /dev/null @@ -1,392 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Rule; - -use Sabberworm\CSS\Comment\Comment; -use Sabberworm\CSS\Comment\Commentable; -use Sabberworm\CSS\OutputFormat; -use Sabberworm\CSS\Parsing\ParserState; -use Sabberworm\CSS\Parsing\UnexpectedEOFException; -use Sabberworm\CSS\Parsing\UnexpectedTokenException; -use Sabberworm\CSS\Renderable; -use Sabberworm\CSS\Value\RuleValueList; -use Sabberworm\CSS\Value\Value; - -/** - * RuleSets contains Rule objects which always have a key and a value. - * In CSS, Rules are expressed as follows: “key: value[0][0] value[0][1], value[1][0] value[1][1];” - */ -class Rule implements Renderable, Commentable -{ - /** - * @var string - */ - private $sRule; - - /** - * @var RuleValueList|null - */ - private $mValue; - - /** - * @var bool - */ - private $bIsImportant; - - /** - * @var array<int, int> - */ - private $aIeHack; - - /** - * @var int - */ - protected $iLineNo; - - /** - * @var int - */ - protected $iColNo; - - /** - * @var array<array-key, Comment> - */ - protected $aComments; - - /** - * @param string $sRule - * @param int $iLineNo - * @param int $iColNo - */ - public function __construct($sRule, $iLineNo = 0, $iColNo = 0) - { - $this->sRule = $sRule; - $this->mValue = null; - $this->bIsImportant = false; - $this->aIeHack = []; - $this->iLineNo = $iLineNo; - $this->iColNo = $iColNo; - $this->aComments = []; - } - - /** - * @return Rule - * - * @throws UnexpectedEOFException - * @throws UnexpectedTokenException - */ - public static function parse(ParserState $oParserState) - { - $aComments = $oParserState->consumeWhiteSpace(); - $oRule = new Rule( - $oParserState->parseIdentifier(!$oParserState->comes("--")), - $oParserState->currentLine(), - $oParserState->currentColumn() - ); - $oRule->setComments($aComments); - $oRule->addComments($oParserState->consumeWhiteSpace()); - $oParserState->consume(':'); - $oValue = Value::parseValue($oParserState, self::listDelimiterForRule($oRule->getRule())); - $oRule->setValue($oValue); - if ($oParserState->getSettings()->bLenientParsing) { - while ($oParserState->comes('\\')) { - $oParserState->consume('\\'); - $oRule->addIeHack($oParserState->consume()); - $oParserState->consumeWhiteSpace(); - } - } - $oParserState->consumeWhiteSpace(); - if ($oParserState->comes('!')) { - $oParserState->consume('!'); - $oParserState->consumeWhiteSpace(); - $oParserState->consume('important'); - $oRule->setIsImportant(true); - } - $oParserState->consumeWhiteSpace(); - while ($oParserState->comes(';')) { - $oParserState->consume(';'); - } - $oParserState->consumeWhiteSpace(); - - return $oRule; - } - - /** - * @param string $sRule - * - * @return array<int, string> - */ - private static function listDelimiterForRule($sRule) - { - if (preg_match('/^font($|-)/', $sRule)) { - return [',', '/', ' ']; - } - return [',', ' ', '/']; - } - - /** - * @return int - */ - public function getLineNo() - { - return $this->iLineNo; - } - - /** - * @return int - */ - public function getColNo() - { - return $this->iColNo; - } - - /** - * @param int $iLine - * @param int $iColumn - * - * @return void - */ - public function setPosition($iLine, $iColumn) - { - $this->iColNo = $iColumn; - $this->iLineNo = $iLine; - } - - /** - * @param string $sRule - * - * @return void - */ - public function setRule($sRule) - { - $this->sRule = $sRule; - } - - /** - * @return string - */ - public function getRule() - { - return $this->sRule; - } - - /** - * @return RuleValueList|null - */ - public function getValue() - { - return $this->mValue; - } - - /** - * @param RuleValueList|null $mValue - * - * @return void - */ - public function setValue($mValue) - { - $this->mValue = $mValue; - } - - /** - * @param array<array-key, array<array-key, RuleValueList>> $aSpaceSeparatedValues - * - * @return RuleValueList - * - * @deprecated will be removed in version 9.0 - * Old-Style 2-dimensional array given. Retained for (some) backwards-compatibility. - * Use `setValue()` instead and wrap the value inside a RuleValueList if necessary. - */ - public function setValues(array $aSpaceSeparatedValues) - { - $oSpaceSeparatedList = null; - if (count($aSpaceSeparatedValues) > 1) { - $oSpaceSeparatedList = new RuleValueList(' ', $this->iLineNo); - } - foreach ($aSpaceSeparatedValues as $aCommaSeparatedValues) { - $oCommaSeparatedList = null; - if (count($aCommaSeparatedValues) > 1) { - $oCommaSeparatedList = new RuleValueList(',', $this->iLineNo); - } - foreach ($aCommaSeparatedValues as $mValue) { - if (!$oSpaceSeparatedList && !$oCommaSeparatedList) { - $this->mValue = $mValue; - return $mValue; - } - if ($oCommaSeparatedList) { - $oCommaSeparatedList->addListComponent($mValue); - } else { - $oSpaceSeparatedList->addListComponent($mValue); - } - } - if (!$oSpaceSeparatedList) { - $this->mValue = $oCommaSeparatedList; - return $oCommaSeparatedList; - } else { - $oSpaceSeparatedList->addListComponent($oCommaSeparatedList); - } - } - $this->mValue = $oSpaceSeparatedList; - return $oSpaceSeparatedList; - } - - /** - * @return array<int, array<int, RuleValueList>> - * - * @deprecated will be removed in version 9.0 - * Old-Style 2-dimensional array returned. Retained for (some) backwards-compatibility. - * Use `getValue()` instead and check for the existence of a (nested set of) ValueList object(s). - */ - public function getValues() - { - if (!$this->mValue instanceof RuleValueList) { - return [[$this->mValue]]; - } - if ($this->mValue->getListSeparator() === ',') { - return [$this->mValue->getListComponents()]; - } - $aResult = []; - foreach ($this->mValue->getListComponents() as $mValue) { - if (!$mValue instanceof RuleValueList || $mValue->getListSeparator() !== ',') { - $aResult[] = [$mValue]; - continue; - } - if ($this->mValue->getListSeparator() === ' ' || count($aResult) === 0) { - $aResult[] = []; - } - foreach ($mValue->getListComponents() as $mValue) { - $aResult[count($aResult) - 1][] = $mValue; - } - } - return $aResult; - } - - /** - * Adds a value to the existing value. Value will be appended if a `RuleValueList` exists of the given type. - * Otherwise, the existing value will be wrapped by one. - * - * @param RuleValueList|array<int, RuleValueList> $mValue - * @param string $sType - * - * @return void - */ - public function addValue($mValue, $sType = ' ') - { - if (!is_array($mValue)) { - $mValue = [$mValue]; - } - if (!$this->mValue instanceof RuleValueList || $this->mValue->getListSeparator() !== $sType) { - $mCurrentValue = $this->mValue; - $this->mValue = new RuleValueList($sType, $this->iLineNo); - if ($mCurrentValue) { - $this->mValue->addListComponent($mCurrentValue); - } - } - foreach ($mValue as $mValueItem) { - $this->mValue->addListComponent($mValueItem); - } - } - - /** - * @param int $iModifier - * - * @return void - */ - public function addIeHack($iModifier) - { - $this->aIeHack[] = $iModifier; - } - - /** - * @param array<int, int> $aModifiers - * - * @return void - */ - public function setIeHack(array $aModifiers) - { - $this->aIeHack = $aModifiers; - } - - /** - * @return array<int, int> - */ - public function getIeHack() - { - return $this->aIeHack; - } - - /** - * @param bool $bIsImportant - * - * @return void - */ - public function setIsImportant($bIsImportant) - { - $this->bIsImportant = $bIsImportant; - } - - /** - * @return bool - */ - public function getIsImportant() - { - return $this->bIsImportant; - } - - /** - * @return string - */ - public function __toString() - { - return $this->render(new OutputFormat()); - } - - /** - * @return string - */ - public function render(OutputFormat $oOutputFormat) - { - $sResult = "{$this->sRule}:{$oOutputFormat->spaceAfterRuleName()}"; - if ($this->mValue instanceof Value) { //Can also be a ValueList - $sResult .= $this->mValue->render($oOutputFormat); - } else { - $sResult .= $this->mValue; - } - if (!empty($this->aIeHack)) { - $sResult .= ' \\' . implode('\\', $this->aIeHack); - } - if ($this->bIsImportant) { - $sResult .= ' !important'; - } - $sResult .= ';'; - return $sResult; - } - - /** - * @param array<array-key, Comment> $aComments - * - * @return void - */ - public function addComments(array $aComments) - { - $this->aComments = array_merge($this->aComments, $aComments); - } - - /** - * @return array<array-key, Comment> - */ - public function getComments() - { - return $this->aComments; - } - - /** - * @param array<array-key, Comment> $aComments - * - * @return void - */ - public function setComments(array $aComments) - { - $this->aComments = $aComments; - } -} diff --git a/lib/sabberworm/php-css-parser/src/RuleSet/AtRuleSet.php b/lib/sabberworm/php-css-parser/src/RuleSet/AtRuleSet.php deleted file mode 100644 index 88bc5bd31..000000000 --- a/lib/sabberworm/php-css-parser/src/RuleSet/AtRuleSet.php +++ /dev/null @@ -1,73 +0,0 @@ -<?php - -namespace Sabberworm\CSS\RuleSet; - -use Sabberworm\CSS\OutputFormat; -use Sabberworm\CSS\Property\AtRule; - -/** - * A RuleSet constructed by an unknown at-rule. `@font-face` rules are rendered into AtRuleSet objects. - */ -class AtRuleSet extends RuleSet implements AtRule -{ - /** - * @var string - */ - private $sType; - - /** - * @var string - */ - private $sArgs; - - /** - * @param string $sType - * @param string $sArgs - * @param int $iLineNo - */ - public function __construct($sType, $sArgs = '', $iLineNo = 0) - { - parent::__construct($iLineNo); - $this->sType = $sType; - $this->sArgs = $sArgs; - } - - /** - * @return string - */ - public function atRuleName() - { - return $this->sType; - } - - /** - * @return string - */ - public function atRuleArgs() - { - return $this->sArgs; - } - - /** - * @return string - */ - public function __toString() - { - return $this->render(new OutputFormat()); - } - - /** - * @return string - */ - public function render(OutputFormat $oOutputFormat) - { - $sArgs = $this->sArgs; - if ($sArgs) { - $sArgs = ' ' . $sArgs; - } - $sResult = "@{$this->sType}$sArgs{$oOutputFormat->spaceBeforeOpeningBrace()}{"; - $sResult .= parent::render($oOutputFormat); - $sResult .= '}'; - return $sResult; - } -} diff --git a/lib/sabberworm/php-css-parser/src/RuleSet/DeclarationBlock.php b/lib/sabberworm/php-css-parser/src/RuleSet/DeclarationBlock.php deleted file mode 100644 index c27cdd4c8..000000000 --- a/lib/sabberworm/php-css-parser/src/RuleSet/DeclarationBlock.php +++ /dev/null @@ -1,831 +0,0 @@ -<?php - -namespace Sabberworm\CSS\RuleSet; - -use Sabberworm\CSS\CSSList\CSSList; -use Sabberworm\CSS\CSSList\KeyFrame; -use Sabberworm\CSS\OutputFormat; -use Sabberworm\CSS\Parsing\OutputException; -use Sabberworm\CSS\Parsing\ParserState; -use Sabberworm\CSS\Parsing\UnexpectedEOFException; -use Sabberworm\CSS\Parsing\UnexpectedTokenException; -use Sabberworm\CSS\Property\KeyframeSelector; -use Sabberworm\CSS\Property\Selector; -use Sabberworm\CSS\Rule\Rule; -use Sabberworm\CSS\Value\Color; -use Sabberworm\CSS\Value\RuleValueList; -use Sabberworm\CSS\Value\Size; -use Sabberworm\CSS\Value\URL; -use Sabberworm\CSS\Value\Value; - -/** - * Declaration blocks are the parts of a CSS file which denote the rules belonging to a selector. - * - * Declaration blocks usually appear directly inside a `Document` or another `CSSList` (mostly a `MediaQuery`). - */ -class DeclarationBlock extends RuleSet -{ - /** - * @var array<int, Selector|string> - */ - private $aSelectors; - - /** - * @param int $iLineNo - */ - public function __construct($iLineNo = 0) - { - parent::__construct($iLineNo); - $this->aSelectors = []; - } - - /** - * @param CSSList|null $oList - * - * @return DeclarationBlock|false - * - * @throws UnexpectedTokenException - * @throws UnexpectedEOFException - */ - public static function parse(ParserState $oParserState, $oList = null) - { - $aComments = []; - $oResult = new DeclarationBlock($oParserState->currentLine()); - try { - $aSelectorParts = []; - $sStringWrapperChar = false; - do { - $aSelectorParts[] = $oParserState->consume(1) - . $oParserState->consumeUntil(['{', '}', '\'', '"'], false, false, $aComments); - if (in_array($oParserState->peek(), ['\'', '"']) && substr(end($aSelectorParts), -1) != "\\") { - if ($sStringWrapperChar === false) { - $sStringWrapperChar = $oParserState->peek(); - } elseif ($sStringWrapperChar == $oParserState->peek()) { - $sStringWrapperChar = false; - } - } - } while (!in_array($oParserState->peek(), ['{', '}']) || $sStringWrapperChar !== false); - $oResult->setSelectors(implode('', $aSelectorParts), $oList); - if ($oParserState->comes('{')) { - $oParserState->consume(1); - } - } catch (UnexpectedTokenException $e) { - if ($oParserState->getSettings()->bLenientParsing) { - if (!$oParserState->comes('}')) { - $oParserState->consumeUntil('}', false, true); - } - return false; - } else { - throw $e; - } - } - $oResult->setComments($aComments); - RuleSet::parseRuleSet($oParserState, $oResult); - return $oResult; - } - - /** - * @param array<int, Selector|string>|string $mSelector - * @param CSSList|null $oList - * - * @throws UnexpectedTokenException - */ - public function setSelectors($mSelector, $oList = null) - { - if (is_array($mSelector)) { - $this->aSelectors = $mSelector; - } else { - $this->aSelectors = explode(',', $mSelector); - } - foreach ($this->aSelectors as $iKey => $mSelector) { - if (!($mSelector instanceof Selector)) { - if ($oList === null || !($oList instanceof KeyFrame)) { - if (!Selector::isValid($mSelector)) { - throw new UnexpectedTokenException( - "Selector did not match '" . Selector::SELECTOR_VALIDATION_RX . "'.", - $mSelector, - "custom" - ); - } - $this->aSelectors[$iKey] = new Selector($mSelector); - } else { - if (!KeyframeSelector::isValid($mSelector)) { - throw new UnexpectedTokenException( - "Selector did not match '" . KeyframeSelector::SELECTOR_VALIDATION_RX . "'.", - $mSelector, - "custom" - ); - } - $this->aSelectors[$iKey] = new KeyframeSelector($mSelector); - } - } - } - } - - /** - * Remove one of the selectors of the block. - * - * @param Selector|string $mSelector - * - * @return bool - */ - public function removeSelector($mSelector) - { - if ($mSelector instanceof Selector) { - $mSelector = $mSelector->getSelector(); - } - foreach ($this->aSelectors as $iKey => $oSelector) { - if ($oSelector->getSelector() === $mSelector) { - unset($this->aSelectors[$iKey]); - return true; - } - } - return false; - } - - /** - * @return array<int, Selector|string> - * - * @deprecated will be removed in version 9.0; use `getSelectors()` instead - */ - public function getSelector() - { - return $this->getSelectors(); - } - - /** - * @param Selector|string $mSelector - * @param CSSList|null $oList - * - * @return void - * - * @deprecated will be removed in version 9.0; use `setSelectors()` instead - */ - public function setSelector($mSelector, $oList = null) - { - $this->setSelectors($mSelector, $oList); - } - - /** - * @return array<int, Selector|string> - */ - public function getSelectors() - { - return $this->aSelectors; - } - - /** - * Splits shorthand declarations (e.g. `margin` or `font`) into their constituent parts. - * - * @return void - */ - public function expandShorthands() - { - // border must be expanded before dimensions - $this->expandBorderShorthand(); - $this->expandDimensionsShorthand(); - $this->expandFontShorthand(); - $this->expandBackgroundShorthand(); - $this->expandListStyleShorthand(); - } - - /** - * Creates shorthand declarations (e.g. `margin` or `font`) whenever possible. - * - * @return void - */ - public function createShorthands() - { - $this->createBackgroundShorthand(); - $this->createDimensionsShorthand(); - // border must be shortened after dimensions - $this->createBorderShorthand(); - $this->createFontShorthand(); - $this->createListStyleShorthand(); - } - - /** - * Splits shorthand border declarations (e.g. `border: 1px red;`). - * - * Additional splitting happens in expandDimensionsShorthand. - * - * Multiple borders are not yet supported as of 3. - * - * @return void - */ - public function expandBorderShorthand() - { - $aBorderRules = [ - 'border', - 'border-left', - 'border-right', - 'border-top', - 'border-bottom', - ]; - $aBorderSizes = [ - 'thin', - 'medium', - 'thick', - ]; - $aRules = $this->getRulesAssoc(); - foreach ($aBorderRules as $sBorderRule) { - if (!isset($aRules[$sBorderRule])) { - continue; - } - $oRule = $aRules[$sBorderRule]; - $mRuleValue = $oRule->getValue(); - $aValues = []; - if (!$mRuleValue instanceof RuleValueList) { - $aValues[] = $mRuleValue; - } else { - $aValues = $mRuleValue->getListComponents(); - } - foreach ($aValues as $mValue) { - if ($mValue instanceof Value) { - $mNewValue = clone $mValue; - } else { - $mNewValue = $mValue; - } - if ($mValue instanceof Size) { - $sNewRuleName = $sBorderRule . "-width"; - } elseif ($mValue instanceof Color) { - $sNewRuleName = $sBorderRule . "-color"; - } else { - if (in_array($mValue, $aBorderSizes)) { - $sNewRuleName = $sBorderRule . "-width"; - } else { - $sNewRuleName = $sBorderRule . "-style"; - } - } - $oNewRule = new Rule($sNewRuleName, $oRule->getLineNo(), $oRule->getColNo()); - $oNewRule->setIsImportant($oRule->getIsImportant()); - $oNewRule->addValue([$mNewValue]); - $this->addRule($oNewRule); - } - $this->removeRule($sBorderRule); - } - } - - /** - * Splits shorthand dimensional declarations (e.g. `margin: 0px auto;`) - * into their constituent parts. - * - * Handles `margin`, `padding`, `border-color`, `border-style` and `border-width`. - * - * @return void - */ - public function expandDimensionsShorthand() - { - $aExpansions = [ - 'margin' => 'margin-%s', - 'padding' => 'padding-%s', - 'border-color' => 'border-%s-color', - 'border-style' => 'border-%s-style', - 'border-width' => 'border-%s-width', - ]; - $aRules = $this->getRulesAssoc(); - foreach ($aExpansions as $sProperty => $sExpanded) { - if (!isset($aRules[$sProperty])) { - continue; - } - $oRule = $aRules[$sProperty]; - $mRuleValue = $oRule->getValue(); - $aValues = []; - if (!$mRuleValue instanceof RuleValueList) { - $aValues[] = $mRuleValue; - } else { - $aValues = $mRuleValue->getListComponents(); - } - $top = $right = $bottom = $left = null; - switch (count($aValues)) { - case 1: - $top = $right = $bottom = $left = $aValues[0]; - break; - case 2: - $top = $bottom = $aValues[0]; - $left = $right = $aValues[1]; - break; - case 3: - $top = $aValues[0]; - $left = $right = $aValues[1]; - $bottom = $aValues[2]; - break; - case 4: - $top = $aValues[0]; - $right = $aValues[1]; - $bottom = $aValues[2]; - $left = $aValues[3]; - break; - } - foreach (['top', 'right', 'bottom', 'left'] as $sPosition) { - $oNewRule = new Rule(sprintf($sExpanded, $sPosition), $oRule->getLineNo(), $oRule->getColNo()); - $oNewRule->setIsImportant($oRule->getIsImportant()); - $oNewRule->addValue(${$sPosition}); - $this->addRule($oNewRule); - } - $this->removeRule($sProperty); - } - } - - /** - * Converts shorthand font declarations - * (e.g. `font: 300 italic 11px/14px verdana, helvetica, sans-serif;`) - * into their constituent parts. - * - * @return void - */ - public function expandFontShorthand() - { - $aRules = $this->getRulesAssoc(); - if (!isset($aRules['font'])) { - return; - } - $oRule = $aRules['font']; - // reset properties to 'normal' per http://www.w3.org/TR/21/fonts.html#font-shorthand - $aFontProperties = [ - 'font-style' => 'normal', - 'font-variant' => 'normal', - 'font-weight' => 'normal', - 'font-size' => 'normal', - 'line-height' => 'normal', - ]; - $mRuleValue = $oRule->getValue(); - $aValues = []; - if (!$mRuleValue instanceof RuleValueList) { - $aValues[] = $mRuleValue; - } else { - $aValues = $mRuleValue->getListComponents(); - } - foreach ($aValues as $mValue) { - if (!$mValue instanceof Value) { - $mValue = mb_strtolower($mValue); - } - if (in_array($mValue, ['normal', 'inherit'])) { - foreach (['font-style', 'font-weight', 'font-variant'] as $sProperty) { - if (!isset($aFontProperties[$sProperty])) { - $aFontProperties[$sProperty] = $mValue; - } - } - } elseif (in_array($mValue, ['italic', 'oblique'])) { - $aFontProperties['font-style'] = $mValue; - } elseif ($mValue == 'small-caps') { - $aFontProperties['font-variant'] = $mValue; - } elseif ( - in_array($mValue, ['bold', 'bolder', 'lighter']) - || ($mValue instanceof Size - && in_array($mValue->getSize(), range(100, 900, 100))) - ) { - $aFontProperties['font-weight'] = $mValue; - } elseif ($mValue instanceof RuleValueList && $mValue->getListSeparator() == '/') { - list($oSize, $oHeight) = $mValue->getListComponents(); - $aFontProperties['font-size'] = $oSize; - $aFontProperties['line-height'] = $oHeight; - } elseif ($mValue instanceof Size && $mValue->getUnit() !== null) { - $aFontProperties['font-size'] = $mValue; - } else { - $aFontProperties['font-family'] = $mValue; - } - } - foreach ($aFontProperties as $sProperty => $mValue) { - $oNewRule = new Rule($sProperty, $oRule->getLineNo(), $oRule->getColNo()); - $oNewRule->addValue($mValue); - $oNewRule->setIsImportant($oRule->getIsImportant()); - $this->addRule($oNewRule); - } - $this->removeRule('font'); - } - - /** - * Converts shorthand background declarations - * (e.g. `background: url("chess.png") gray 50% repeat fixed;`) - * into their constituent parts. - * - * @see http://www.w3.org/TR/21/colors.html#propdef-background - * - * @return void - */ - public function expandBackgroundShorthand() - { - $aRules = $this->getRulesAssoc(); - if (!isset($aRules['background'])) { - return; - } - $oRule = $aRules['background']; - $aBgProperties = [ - 'background-color' => ['transparent'], - 'background-image' => ['none'], - 'background-repeat' => ['repeat'], - 'background-attachment' => ['scroll'], - 'background-position' => [ - new Size(0, '%', null, false, $this->iLineNo), - new Size(0, '%', null, false, $this->iLineNo), - ], - ]; - $mRuleValue = $oRule->getValue(); - $aValues = []; - if (!$mRuleValue instanceof RuleValueList) { - $aValues[] = $mRuleValue; - } else { - $aValues = $mRuleValue->getListComponents(); - } - if (count($aValues) == 1 && $aValues[0] == 'inherit') { - foreach ($aBgProperties as $sProperty => $mValue) { - $oNewRule = new Rule($sProperty, $oRule->getLineNo(), $oRule->getColNo()); - $oNewRule->addValue('inherit'); - $oNewRule->setIsImportant($oRule->getIsImportant()); - $this->addRule($oNewRule); - } - $this->removeRule('background'); - return; - } - $iNumBgPos = 0; - foreach ($aValues as $mValue) { - if (!$mValue instanceof Value) { - $mValue = mb_strtolower($mValue); - } - if ($mValue instanceof URL) { - $aBgProperties['background-image'] = $mValue; - } elseif ($mValue instanceof Color) { - $aBgProperties['background-color'] = $mValue; - } elseif (in_array($mValue, ['scroll', 'fixed'])) { - $aBgProperties['background-attachment'] = $mValue; - } elseif (in_array($mValue, ['repeat', 'no-repeat', 'repeat-x', 'repeat-y'])) { - $aBgProperties['background-repeat'] = $mValue; - } elseif ( - in_array($mValue, ['left', 'center', 'right', 'top', 'bottom']) - || $mValue instanceof Size - ) { - if ($iNumBgPos == 0) { - $aBgProperties['background-position'][0] = $mValue; - $aBgProperties['background-position'][1] = 'center'; - } else { - $aBgProperties['background-position'][$iNumBgPos] = $mValue; - } - $iNumBgPos++; - } - } - foreach ($aBgProperties as $sProperty => $mValue) { - $oNewRule = new Rule($sProperty, $oRule->getLineNo(), $oRule->getColNo()); - $oNewRule->setIsImportant($oRule->getIsImportant()); - $oNewRule->addValue($mValue); - $this->addRule($oNewRule); - } - $this->removeRule('background'); - } - - /** - * @return void - */ - public function expandListStyleShorthand() - { - $aListProperties = [ - 'list-style-type' => 'disc', - 'list-style-position' => 'outside', - 'list-style-image' => 'none', - ]; - $aListStyleTypes = [ - 'none', - 'disc', - 'circle', - 'square', - 'decimal-leading-zero', - 'decimal', - 'lower-roman', - 'upper-roman', - 'lower-greek', - 'lower-alpha', - 'lower-latin', - 'upper-alpha', - 'upper-latin', - 'hebrew', - 'armenian', - 'georgian', - 'cjk-ideographic', - 'hiragana', - 'hira-gana-iroha', - 'katakana-iroha', - 'katakana', - ]; - $aListStylePositions = [ - 'inside', - 'outside', - ]; - $aRules = $this->getRulesAssoc(); - if (!isset($aRules['list-style'])) { - return; - } - $oRule = $aRules['list-style']; - $mRuleValue = $oRule->getValue(); - $aValues = []; - if (!$mRuleValue instanceof RuleValueList) { - $aValues[] = $mRuleValue; - } else { - $aValues = $mRuleValue->getListComponents(); - } - if (count($aValues) == 1 && $aValues[0] == 'inherit') { - foreach ($aListProperties as $sProperty => $mValue) { - $oNewRule = new Rule($sProperty, $oRule->getLineNo(), $oRule->getColNo()); - $oNewRule->addValue('inherit'); - $oNewRule->setIsImportant($oRule->getIsImportant()); - $this->addRule($oNewRule); - } - $this->removeRule('list-style'); - return; - } - foreach ($aValues as $mValue) { - if (!$mValue instanceof Value) { - $mValue = mb_strtolower($mValue); - } - if ($mValue instanceof Url) { - $aListProperties['list-style-image'] = $mValue; - } elseif (in_array($mValue, $aListStyleTypes)) { - $aListProperties['list-style-types'] = $mValue; - } elseif (in_array($mValue, $aListStylePositions)) { - $aListProperties['list-style-position'] = $mValue; - } - } - foreach ($aListProperties as $sProperty => $mValue) { - $oNewRule = new Rule($sProperty, $oRule->getLineNo(), $oRule->getColNo()); - $oNewRule->setIsImportant($oRule->getIsImportant()); - $oNewRule->addValue($mValue); - $this->addRule($oNewRule); - } - $this->removeRule('list-style'); - } - - /** - * @param array<array-key, string> $aProperties - * @param string $sShorthand - * - * @return void - */ - public function createShorthandProperties(array $aProperties, $sShorthand) - { - $aRules = $this->getRulesAssoc(); - $aNewValues = []; - foreach ($aProperties as $sProperty) { - if (!isset($aRules[$sProperty])) { - continue; - } - $oRule = $aRules[$sProperty]; - if (!$oRule->getIsImportant()) { - $mRuleValue = $oRule->getValue(); - $aValues = []; - if (!$mRuleValue instanceof RuleValueList) { - $aValues[] = $mRuleValue; - } else { - $aValues = $mRuleValue->getListComponents(); - } - foreach ($aValues as $mValue) { - $aNewValues[] = $mValue; - } - $this->removeRule($sProperty); - } - } - if (count($aNewValues)) { - $oNewRule = new Rule($sShorthand, $oRule->getLineNo(), $oRule->getColNo()); - foreach ($aNewValues as $mValue) { - $oNewRule->addValue($mValue); - } - $this->addRule($oNewRule); - } - } - - /** - * @return void - */ - public function createBackgroundShorthand() - { - $aProperties = [ - 'background-color', - 'background-image', - 'background-repeat', - 'background-position', - 'background-attachment', - ]; - $this->createShorthandProperties($aProperties, 'background'); - } - - /** - * @return void - */ - public function createListStyleShorthand() - { - $aProperties = [ - 'list-style-type', - 'list-style-position', - 'list-style-image', - ]; - $this->createShorthandProperties($aProperties, 'list-style'); - } - - /** - * Combines `border-color`, `border-style` and `border-width` into `border`. - * - * Should be run after `create_dimensions_shorthand`! - * - * @return void - */ - public function createBorderShorthand() - { - $aProperties = [ - 'border-width', - 'border-style', - 'border-color', - ]; - $this->createShorthandProperties($aProperties, 'border'); - } - - /** - * Looks for long format CSS dimensional properties - * (margin, padding, border-color, border-style and border-width) - * and converts them into shorthand CSS properties. - * - * @return void - */ - public function createDimensionsShorthand() - { - $aPositions = ['top', 'right', 'bottom', 'left']; - $aExpansions = [ - 'margin' => 'margin-%s', - 'padding' => 'padding-%s', - 'border-color' => 'border-%s-color', - 'border-style' => 'border-%s-style', - 'border-width' => 'border-%s-width', - ]; - $aRules = $this->getRulesAssoc(); - foreach ($aExpansions as $sProperty => $sExpanded) { - $aFoldable = []; - foreach ($aRules as $sRuleName => $oRule) { - foreach ($aPositions as $sPosition) { - if ($sRuleName == sprintf($sExpanded, $sPosition)) { - $aFoldable[$sRuleName] = $oRule; - } - } - } - // All four dimensions must be present - if (count($aFoldable) == 4) { - $aValues = []; - foreach ($aPositions as $sPosition) { - $oRule = $aRules[sprintf($sExpanded, $sPosition)]; - $mRuleValue = $oRule->getValue(); - $aRuleValues = []; - if (!$mRuleValue instanceof RuleValueList) { - $aRuleValues[] = $mRuleValue; - } else { - $aRuleValues = $mRuleValue->getListComponents(); - } - $aValues[$sPosition] = $aRuleValues; - } - $oNewRule = new Rule($sProperty, $oRule->getLineNo(), $oRule->getColNo()); - if ((string)$aValues['left'][0] == (string)$aValues['right'][0]) { - if ((string)$aValues['top'][0] == (string)$aValues['bottom'][0]) { - if ((string)$aValues['top'][0] == (string)$aValues['left'][0]) { - // All 4 sides are equal - $oNewRule->addValue($aValues['top']); - } else { - // Top and bottom are equal, left and right are equal - $oNewRule->addValue($aValues['top']); - $oNewRule->addValue($aValues['left']); - } - } else { - // Only left and right are equal - $oNewRule->addValue($aValues['top']); - $oNewRule->addValue($aValues['left']); - $oNewRule->addValue($aValues['bottom']); - } - } else { - // No sides are equal - $oNewRule->addValue($aValues['top']); - $oNewRule->addValue($aValues['left']); - $oNewRule->addValue($aValues['bottom']); - $oNewRule->addValue($aValues['right']); - } - $this->addRule($oNewRule); - foreach ($aPositions as $sPosition) { - $this->removeRule(sprintf($sExpanded, $sPosition)); - } - } - } - } - - /** - * Looks for long format CSS font properties (e.g. `font-weight`) and - * tries to convert them into a shorthand CSS `font` property. - * - * At least `font-size` AND `font-family` must be present in order to create a shorthand declaration. - * - * @return void - */ - public function createFontShorthand() - { - $aFontProperties = [ - 'font-style', - 'font-variant', - 'font-weight', - 'font-size', - 'line-height', - 'font-family', - ]; - $aRules = $this->getRulesAssoc(); - if (!isset($aRules['font-size']) || !isset($aRules['font-family'])) { - return; - } - $oOldRule = isset($aRules['font-size']) ? $aRules['font-size'] : $aRules['font-family']; - $oNewRule = new Rule('font', $oOldRule->getLineNo(), $oOldRule->getColNo()); - unset($oOldRule); - foreach (['font-style', 'font-variant', 'font-weight'] as $sProperty) { - if (isset($aRules[$sProperty])) { - $oRule = $aRules[$sProperty]; - $mRuleValue = $oRule->getValue(); - $aValues = []; - if (!$mRuleValue instanceof RuleValueList) { - $aValues[] = $mRuleValue; - } else { - $aValues = $mRuleValue->getListComponents(); - } - if ($aValues[0] !== 'normal') { - $oNewRule->addValue($aValues[0]); - } - } - } - // Get the font-size value - $oRule = $aRules['font-size']; - $mRuleValue = $oRule->getValue(); - $aFSValues = []; - if (!$mRuleValue instanceof RuleValueList) { - $aFSValues[] = $mRuleValue; - } else { - $aFSValues = $mRuleValue->getListComponents(); - } - // But wait to know if we have line-height to add it - if (isset($aRules['line-height'])) { - $oRule = $aRules['line-height']; - $mRuleValue = $oRule->getValue(); - $aLHValues = []; - if (!$mRuleValue instanceof RuleValueList) { - $aLHValues[] = $mRuleValue; - } else { - $aLHValues = $mRuleValue->getListComponents(); - } - if ($aLHValues[0] !== 'normal') { - $val = new RuleValueList('/', $this->iLineNo); - $val->addListComponent($aFSValues[0]); - $val->addListComponent($aLHValues[0]); - $oNewRule->addValue($val); - } - } else { - $oNewRule->addValue($aFSValues[0]); - } - $oRule = $aRules['font-family']; - $mRuleValue = $oRule->getValue(); - $aFFValues = []; - if (!$mRuleValue instanceof RuleValueList) { - $aFFValues[] = $mRuleValue; - } else { - $aFFValues = $mRuleValue->getListComponents(); - } - $oFFValue = new RuleValueList(',', $this->iLineNo); - $oFFValue->setListComponents($aFFValues); - $oNewRule->addValue($oFFValue); - - $this->addRule($oNewRule); - foreach ($aFontProperties as $sProperty) { - $this->removeRule($sProperty); - } - } - - /** - * @return string - * - * @throws OutputException - */ - public function __toString() - { - return $this->render(new OutputFormat()); - } - - /** - * @return string - * - * @throws OutputException - */ - public function render(OutputFormat $oOutputFormat) - { - if (count($this->aSelectors) === 0) { - // If all the selectors have been removed, this declaration block becomes invalid - throw new OutputException("Attempt to print declaration block with missing selector", $this->iLineNo); - } - $sResult = $oOutputFormat->sBeforeDeclarationBlock; - $sResult .= $oOutputFormat->implode( - $oOutputFormat->spaceBeforeSelectorSeparator() . ',' . $oOutputFormat->spaceAfterSelectorSeparator(), - $this->aSelectors - ); - $sResult .= $oOutputFormat->sAfterDeclarationBlockSelectors; - $sResult .= $oOutputFormat->spaceBeforeOpeningBrace() . '{'; - $sResult .= parent::render($oOutputFormat); - $sResult .= '}'; - $sResult .= $oOutputFormat->sAfterDeclarationBlock; - return $sResult; - } -} diff --git a/lib/sabberworm/php-css-parser/src/RuleSet/RuleSet.php b/lib/sabberworm/php-css-parser/src/RuleSet/RuleSet.php deleted file mode 100644 index 9404bb0bd..000000000 --- a/lib/sabberworm/php-css-parser/src/RuleSet/RuleSet.php +++ /dev/null @@ -1,326 +0,0 @@ -<?php - -namespace Sabberworm\CSS\RuleSet; - -use Sabberworm\CSS\Comment\Comment; -use Sabberworm\CSS\Comment\Commentable; -use Sabberworm\CSS\OutputFormat; -use Sabberworm\CSS\Parsing\ParserState; -use Sabberworm\CSS\Parsing\UnexpectedEOFException; -use Sabberworm\CSS\Parsing\UnexpectedTokenException; -use Sabberworm\CSS\Renderable; -use Sabberworm\CSS\Rule\Rule; - -/** - * RuleSet is a generic superclass denoting rules. The typical example for rule sets are declaration block. - * However, unknown At-Rules (like `@font-face`) are also rule sets. - */ -abstract class RuleSet implements Renderable, Commentable -{ - /** - * @var array<string, Rule> - */ - private $aRules; - - /** - * @var int - */ - protected $iLineNo; - - /** - * @var array<array-key, Comment> - */ - protected $aComments; - - /** - * @param int $iLineNo - */ - public function __construct($iLineNo = 0) - { - $this->aRules = []; - $this->iLineNo = $iLineNo; - $this->aComments = []; - } - - /** - * @return void - * - * @throws UnexpectedTokenException - * @throws UnexpectedEOFException - */ - public static function parseRuleSet(ParserState $oParserState, RuleSet $oRuleSet) - { - while ($oParserState->comes(';')) { - $oParserState->consume(';'); - } - while (!$oParserState->comes('}')) { - $oRule = null; - if ($oParserState->getSettings()->bLenientParsing) { - try { - $oRule = Rule::parse($oParserState); - } catch (UnexpectedTokenException $e) { - try { - $sConsume = $oParserState->consumeUntil(["\n", ";", '}'], true); - // We need to “unfind” the matches to the end of the ruleSet as this will be matched later - if ($oParserState->streql(substr($sConsume, -1), '}')) { - $oParserState->backtrack(1); - } else { - while ($oParserState->comes(';')) { - $oParserState->consume(';'); - } - } - } catch (UnexpectedTokenException $e) { - // We’ve reached the end of the document. Just close the RuleSet. - return; - } - } - } else { - $oRule = Rule::parse($oParserState); - } - if ($oRule) { - $oRuleSet->addRule($oRule); - } - } - $oParserState->consume('}'); - } - - /** - * @return int - */ - public function getLineNo() - { - return $this->iLineNo; - } - - /** - * @param Rule|null $oSibling - * - * @return void - */ - public function addRule(Rule $oRule, Rule $oSibling = null) - { - $sRule = $oRule->getRule(); - if (!isset($this->aRules[$sRule])) { - $this->aRules[$sRule] = []; - } - - $iPosition = count($this->aRules[$sRule]); - - if ($oSibling !== null) { - $iSiblingPos = array_search($oSibling, $this->aRules[$sRule], true); - if ($iSiblingPos !== false) { - $iPosition = $iSiblingPos; - $oRule->setPosition($oSibling->getLineNo(), $oSibling->getColNo() - 1); - } - } - if ($oRule->getLineNo() === 0 && $oRule->getColNo() === 0) { - //this node is added manually, give it the next best line - $rules = $this->getRules(); - $pos = count($rules); - if ($pos > 0) { - $last = $rules[$pos - 1]; - $oRule->setPosition($last->getLineNo() + 1, 0); - } - } - - array_splice($this->aRules[$sRule], $iPosition, 0, [$oRule]); - } - - /** - * Returns all rules matching the given rule name - * - * @example $oRuleSet->getRules('font') // returns array(0 => $oRule, …) or array(). - * - * @example $oRuleSet->getRules('font-') - * //returns an array of all rules either beginning with font- or matching font. - * - * @param Rule|string|null $mRule - * Pattern to search for. If null, returns all rules. - * If the pattern ends with a dash, all rules starting with the pattern are returned - * as well as one matching the pattern with the dash excluded. - * Passing a Rule behaves like calling `getRules($mRule->getRule())`. - * - * @return array<int, Rule> - */ - public function getRules($mRule = null) - { - if ($mRule instanceof Rule) { - $mRule = $mRule->getRule(); - } - /** @var array<int, Rule> $aResult */ - $aResult = []; - foreach ($this->aRules as $sName => $aRules) { - // Either no search rule is given or the search rule matches the found rule exactly - // or the search rule ends in “-” and the found rule starts with the search rule. - if ( - !$mRule || $sName === $mRule - || ( - strrpos($mRule, '-') === strlen($mRule) - strlen('-') - && (strpos($sName, $mRule) === 0 || $sName === substr($mRule, 0, -1)) - ) - ) { - $aResult = array_merge($aResult, $aRules); - } - } - usort($aResult, function (Rule $first, Rule $second) { - if ($first->getLineNo() === $second->getLineNo()) { - return $first->getColNo() - $second->getColNo(); - } - return $first->getLineNo() - $second->getLineNo(); - }); - return $aResult; - } - - /** - * Overrides all the rules of this set. - * - * @param array<array-key, Rule> $aRules The rules to override with. - * - * @return void - */ - public function setRules(array $aRules) - { - $this->aRules = []; - foreach ($aRules as $rule) { - $this->addRule($rule); - } - } - - /** - * Returns all rules matching the given pattern and returns them in an associative array with the rule’s name - * as keys. This method exists mainly for backwards-compatibility and is really only partially useful. - * - * Note: This method loses some information: Calling this (with an argument of `background-`) on a declaration block - * like `{ background-color: green; background-color; rgba(0, 127, 0, 0.7); }` will only yield an associative array - * containing the rgba-valued rule while `getRules()` would yield an indexed array containing both. - * - * @param Rule|string|null $mRule $mRule - * Pattern to search for. If null, returns all rules. If the pattern ends with a dash, - * all rules starting with the pattern are returned as well as one matching the pattern with the dash - * excluded. Passing a Rule behaves like calling `getRules($mRule->getRule())`. - * - * @return array<string, Rule> - */ - public function getRulesAssoc($mRule = null) - { - /** @var array<string, Rule> $aResult */ - $aResult = []; - foreach ($this->getRules($mRule) as $oRule) { - $aResult[$oRule->getRule()] = $oRule; - } - return $aResult; - } - - /** - * Removes a rule from this RuleSet. This accepts all the possible values that `getRules()` accepts. - * - * If given a Rule, it will only remove this particular rule (by identity). - * If given a name, it will remove all rules by that name. - * - * Note: this is different from pre-v.2.0 behaviour of PHP-CSS-Parser, where passing a Rule instance would - * remove all rules with the same name. To get the old behaviour, use `removeRule($oRule->getRule())`. - * - * @param Rule|string|null $mRule - * pattern to remove. If $mRule is null, all rules are removed. If the pattern ends in a dash, - * all rules starting with the pattern are removed as well as one matching the pattern with the dash - * excluded. Passing a Rule behaves matches by identity. - * - * @return void - */ - public function removeRule($mRule) - { - if ($mRule instanceof Rule) { - $sRule = $mRule->getRule(); - if (!isset($this->aRules[$sRule])) { - return; - } - foreach ($this->aRules[$sRule] as $iKey => $oRule) { - if ($oRule === $mRule) { - unset($this->aRules[$sRule][$iKey]); - } - } - } else { - foreach ($this->aRules as $sName => $aRules) { - // Either no search rule is given or the search rule matches the found rule exactly - // or the search rule ends in “-” and the found rule starts with the search rule or equals it - // (without the trailing dash). - if ( - !$mRule || $sName === $mRule - || (strrpos($mRule, '-') === strlen($mRule) - strlen('-') - && (strpos($sName, $mRule) === 0 || $sName === substr($mRule, 0, -1))) - ) { - unset($this->aRules[$sName]); - } - } - } - } - - /** - * @return string - */ - public function __toString() - { - return $this->render(new OutputFormat()); - } - - /** - * @return string - */ - public function render(OutputFormat $oOutputFormat) - { - $sResult = ''; - $bIsFirst = true; - foreach ($this->aRules as $aRules) { - foreach ($aRules as $oRule) { - $sRendered = $oOutputFormat->safely(function () use ($oRule, $oOutputFormat) { - return $oRule->render($oOutputFormat->nextLevel()); - }); - if ($sRendered === null) { - continue; - } - if ($bIsFirst) { - $bIsFirst = false; - $sResult .= $oOutputFormat->nextLevel()->spaceBeforeRules(); - } else { - $sResult .= $oOutputFormat->nextLevel()->spaceBetweenRules(); - } - $sResult .= $sRendered; - } - } - - if (!$bIsFirst) { - // Had some output - $sResult .= $oOutputFormat->spaceAfterRules(); - } - - return $oOutputFormat->removeLastSemicolon($sResult); - } - - /** - * @param array<string, Comment> $aComments - * - * @return void - */ - public function addComments(array $aComments) - { - $this->aComments = array_merge($this->aComments, $aComments); - } - - /** - * @return array<string, Comment> - */ - public function getComments() - { - return $this->aComments; - } - - /** - * @param array<string, Comment> $aComments - * - * @return void - */ - public function setComments(array $aComments) - { - $this->aComments = $aComments; - } -} diff --git a/lib/sabberworm/php-css-parser/src/Settings.php b/lib/sabberworm/php-css-parser/src/Settings.php deleted file mode 100644 index 7b8580962..000000000 --- a/lib/sabberworm/php-css-parser/src/Settings.php +++ /dev/null @@ -1,89 +0,0 @@ -<?php - -namespace Sabberworm\CSS; - -/** - * Parser settings class. - * - * Configure parser behaviour here. - */ -class Settings -{ - /** - * Multi-byte string support. - * If true (mbstring extension must be enabled), will use (slower) `mb_strlen`, `mb_convert_case`, `mb_substr` - * and `mb_strpos` functions. Otherwise, the normal (ASCII-Only) functions will be used. - * - * @var bool - */ - public $bMultibyteSupport; - - /** - * The default charset for the CSS if no `@charset` rule is found. Defaults to utf-8. - * - * @var string - */ - public $sDefaultCharset = 'utf-8'; - - /** - * Lenient parsing. When used (which is true by default), the parser will not choke - * on unexpected tokens but simply ignore them. - * - * @var bool - */ - public $bLenientParsing = true; - - private function __construct() - { - $this->bMultibyteSupport = extension_loaded('mbstring'); - } - - /** - * @return self new instance - */ - public static function create() - { - return new Settings(); - } - - /** - * @param bool $bMultibyteSupport - * - * @return self fluent interface - */ - public function withMultibyteSupport($bMultibyteSupport = true) - { - $this->bMultibyteSupport = $bMultibyteSupport; - return $this; - } - - /** - * @param string $sDefaultCharset - * - * @return self fluent interface - */ - public function withDefaultCharset($sDefaultCharset) - { - $this->sDefaultCharset = $sDefaultCharset; - return $this; - } - - /** - * @param bool $bLenientParsing - * - * @return self fluent interface - */ - public function withLenientParsing($bLenientParsing = true) - { - $this->bLenientParsing = $bLenientParsing; - return $this; - } - - /** - * @return self fluent interface - */ - public function beStrict() - { - return $this->withLenientParsing(false); - } -} diff --git a/lib/sabberworm/php-css-parser/src/Value/CSSFunction.php b/lib/sabberworm/php-css-parser/src/Value/CSSFunction.php deleted file mode 100644 index e6b8c1189..000000000 --- a/lib/sabberworm/php-css-parser/src/Value/CSSFunction.php +++ /dev/null @@ -1,73 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Value; - -use Sabberworm\CSS\OutputFormat; - -class CSSFunction extends ValueList -{ - /** - * @var string - */ - protected $sName; - - /** - * @param string $sName - * @param RuleValueList|array<int, RuleValueList|CSSFunction|CSSString|LineName|Size|URL|string> $aArguments - * @param string $sSeparator - * @param int $iLineNo - */ - public function __construct($sName, $aArguments, $sSeparator = ',', $iLineNo = 0) - { - if ($aArguments instanceof RuleValueList) { - $sSeparator = $aArguments->getListSeparator(); - $aArguments = $aArguments->getListComponents(); - } - $this->sName = $sName; - $this->iLineNo = $iLineNo; - parent::__construct($aArguments, $sSeparator, $iLineNo); - } - - /** - * @return string - */ - public function getName() - { - return $this->sName; - } - - /** - * @param string $sName - * - * @return void - */ - public function setName($sName) - { - $this->sName = $sName; - } - - /** - * @return array<int, RuleValueList|CSSFunction|CSSString|LineName|Size|URL|string> - */ - public function getArguments() - { - return $this->aComponents; - } - - /** - * @return string - */ - public function __toString() - { - return $this->render(new OutputFormat()); - } - - /** - * @return string - */ - public function render(OutputFormat $oOutputFormat) - { - $aArguments = parent::render($oOutputFormat); - return "{$this->sName}({$aArguments})"; - } -} diff --git a/lib/sabberworm/php-css-parser/src/Value/CSSString.php b/lib/sabberworm/php-css-parser/src/Value/CSSString.php deleted file mode 100644 index 9fafedd7a..000000000 --- a/lib/sabberworm/php-css-parser/src/Value/CSSString.php +++ /dev/null @@ -1,105 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Value; - -use Sabberworm\CSS\OutputFormat; -use Sabberworm\CSS\Parsing\ParserState; -use Sabberworm\CSS\Parsing\SourceException; -use Sabberworm\CSS\Parsing\UnexpectedEOFException; -use Sabberworm\CSS\Parsing\UnexpectedTokenException; - -class CSSString extends PrimitiveValue -{ - /** - * @var string - */ - private $sString; - - /** - * @param string $sString - * @param int $iLineNo - */ - public function __construct($sString, $iLineNo = 0) - { - $this->sString = $sString; - parent::__construct($iLineNo); - } - - /** - * @return CSSString - * - * @throws SourceException - * @throws UnexpectedEOFException - * @throws UnexpectedTokenException - */ - public static function parse(ParserState $oParserState) - { - $sBegin = $oParserState->peek(); - $sQuote = null; - if ($sBegin === "'") { - $sQuote = "'"; - } elseif ($sBegin === '"') { - $sQuote = '"'; - } - if ($sQuote !== null) { - $oParserState->consume($sQuote); - } - $sResult = ""; - $sContent = null; - if ($sQuote === null) { - // Unquoted strings end in whitespace or with braces, brackets, parentheses - while (!preg_match('/[\\s{}()<>\\[\\]]/isu', $oParserState->peek())) { - $sResult .= $oParserState->parseCharacter(false); - } - } else { - while (!$oParserState->comes($sQuote)) { - $sContent = $oParserState->parseCharacter(false); - if ($sContent === null) { - throw new SourceException( - "Non-well-formed quoted string {$oParserState->peek(3)}", - $oParserState->currentLine() - ); - } - $sResult .= $sContent; - } - $oParserState->consume($sQuote); - } - return new CSSString($sResult, $oParserState->currentLine()); - } - - /** - * @param string $sString - * - * @return void - */ - public function setString($sString) - { - $this->sString = $sString; - } - - /** - * @return string - */ - public function getString() - { - return $this->sString; - } - - /** - * @return string - */ - public function __toString() - { - return $this->render(new OutputFormat()); - } - - /** - * @return string - */ - public function render(OutputFormat $oOutputFormat) - { - $sString = addslashes($this->sString); - $sString = str_replace("\n", '\A', $sString); - return $oOutputFormat->getStringQuotingType() . $sString . $oOutputFormat->getStringQuotingType(); - } -} diff --git a/lib/sabberworm/php-css-parser/src/Value/CalcFunction.php b/lib/sabberworm/php-css-parser/src/Value/CalcFunction.php deleted file mode 100644 index 5c92e0c08..000000000 --- a/lib/sabberworm/php-css-parser/src/Value/CalcFunction.php +++ /dev/null @@ -1,89 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Value; - -use Sabberworm\CSS\Parsing\ParserState; -use Sabberworm\CSS\Parsing\UnexpectedEOFException; -use Sabberworm\CSS\Parsing\UnexpectedTokenException; - -class CalcFunction extends CSSFunction -{ - /** - * @var int - */ - const T_OPERAND = 1; - - /** - * @var int - */ - const T_OPERATOR = 2; - - /** - * @return CalcFunction - * - * @throws UnexpectedTokenException - * @throws UnexpectedEOFException - */ - public static function parse(ParserState $oParserState) - { - $aOperators = ['+', '-', '*', '/']; - $sFunction = trim($oParserState->consumeUntil('(', false, true)); - $oCalcList = new CalcRuleValueList($oParserState->currentLine()); - $oList = new RuleValueList(',', $oParserState->currentLine()); - $iNestingLevel = 0; - $iLastComponentType = null; - while (!$oParserState->comes(')') || $iNestingLevel > 0) { - $oParserState->consumeWhiteSpace(); - if ($oParserState->comes('(')) { - $iNestingLevel++; - $oCalcList->addListComponent($oParserState->consume(1)); - $oParserState->consumeWhiteSpace(); - continue; - } elseif ($oParserState->comes(')')) { - $iNestingLevel--; - $oCalcList->addListComponent($oParserState->consume(1)); - $oParserState->consumeWhiteSpace(); - continue; - } - if ($iLastComponentType != CalcFunction::T_OPERAND) { - $oVal = Value::parsePrimitiveValue($oParserState); - $oCalcList->addListComponent($oVal); - $iLastComponentType = CalcFunction::T_OPERAND; - } else { - if (in_array($oParserState->peek(), $aOperators)) { - if (($oParserState->comes('-') || $oParserState->comes('+'))) { - if ( - $oParserState->peek(1, -1) != ' ' - || !($oParserState->comes('- ') - || $oParserState->comes('+ ')) - ) { - throw new UnexpectedTokenException( - " {$oParserState->peek()} ", - $oParserState->peek(1, -1) . $oParserState->peek(2), - 'literal', - $oParserState->currentLine() - ); - } - } - $oCalcList->addListComponent($oParserState->consume(1)); - $iLastComponentType = CalcFunction::T_OPERATOR; - } else { - throw new UnexpectedTokenException( - sprintf( - 'Next token was expected to be an operand of type %s. Instead "%s" was found.', - implode(', ', $aOperators), - $oVal - ), - '', - 'custom', - $oParserState->currentLine() - ); - } - } - $oParserState->consumeWhiteSpace(); - } - $oList->addListComponent($oCalcList); - $oParserState->consume(')'); - return new CalcFunction($sFunction, $oList, ',', $oParserState->currentLine()); - } -} diff --git a/lib/sabberworm/php-css-parser/src/Value/CalcRuleValueList.php b/lib/sabberworm/php-css-parser/src/Value/CalcRuleValueList.php deleted file mode 100644 index 7dbd26a1b..000000000 --- a/lib/sabberworm/php-css-parser/src/Value/CalcRuleValueList.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Value; - -use Sabberworm\CSS\OutputFormat; - -class CalcRuleValueList extends RuleValueList -{ - /** - * @param int $iLineNo - */ - public function __construct($iLineNo = 0) - { - parent::__construct(',', $iLineNo); - } - - /** - * @return string - */ - public function render(OutputFormat $oOutputFormat) - { - return $oOutputFormat->implode(' ', $this->aComponents); - } -} diff --git a/lib/sabberworm/php-css-parser/src/Value/Color.php b/lib/sabberworm/php-css-parser/src/Value/Color.php deleted file mode 100644 index 8dc52960c..000000000 --- a/lib/sabberworm/php-css-parser/src/Value/Color.php +++ /dev/null @@ -1,166 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Value; - -use Sabberworm\CSS\OutputFormat; -use Sabberworm\CSS\Parsing\ParserState; -use Sabberworm\CSS\Parsing\UnexpectedEOFException; -use Sabberworm\CSS\Parsing\UnexpectedTokenException; - -class Color extends CSSFunction -{ - /** - * @param array<int, RuleValueList|CSSFunction|CSSString|LineName|Size|URL|string> $aColor - * @param int $iLineNo - */ - public function __construct(array $aColor, $iLineNo = 0) - { - parent::__construct(implode('', array_keys($aColor)), $aColor, ',', $iLineNo); - } - - /** - * @return Color|CSSFunction - * - * @throws UnexpectedEOFException - * @throws UnexpectedTokenException - */ - public static function parse(ParserState $oParserState) - { - $aColor = []; - if ($oParserState->comes('#')) { - $oParserState->consume('#'); - $sValue = $oParserState->parseIdentifier(false); - if ($oParserState->strlen($sValue) === 3) { - $sValue = $sValue[0] . $sValue[0] . $sValue[1] . $sValue[1] . $sValue[2] . $sValue[2]; - } elseif ($oParserState->strlen($sValue) === 4) { - $sValue = $sValue[0] . $sValue[0] . $sValue[1] . $sValue[1] . $sValue[2] . $sValue[2] . $sValue[3] - . $sValue[3]; - } - - if ($oParserState->strlen($sValue) === 8) { - $aColor = [ - 'r' => new Size(intval($sValue[0] . $sValue[1], 16), null, true, $oParserState->currentLine()), - 'g' => new Size(intval($sValue[2] . $sValue[3], 16), null, true, $oParserState->currentLine()), - 'b' => new Size(intval($sValue[4] . $sValue[5], 16), null, true, $oParserState->currentLine()), - 'a' => new Size( - round(self::mapRange(intval($sValue[6] . $sValue[7], 16), 0, 255, 0, 1), 2), - null, - true, - $oParserState->currentLine() - ), - ]; - } else { - $aColor = [ - 'r' => new Size(intval($sValue[0] . $sValue[1], 16), null, true, $oParserState->currentLine()), - 'g' => new Size(intval($sValue[2] . $sValue[3], 16), null, true, $oParserState->currentLine()), - 'b' => new Size(intval($sValue[4] . $sValue[5], 16), null, true, $oParserState->currentLine()), - ]; - } - } else { - $sColorMode = $oParserState->parseIdentifier(true); - $oParserState->consumeWhiteSpace(); - $oParserState->consume('('); - - $bContainsVar = false; - $iLength = $oParserState->strlen($sColorMode); - for ($i = 0; $i < $iLength; ++$i) { - $oParserState->consumeWhiteSpace(); - if ($oParserState->comes('var')) { - $aColor[$sColorMode[$i]] = CSSFunction::parseIdentifierOrFunction($oParserState); - $bContainsVar = true; - } else { - $aColor[$sColorMode[$i]] = Size::parse($oParserState, true); - } - - if ($bContainsVar && $oParserState->comes(')')) { - // With a var argument the function can have fewer arguments - break; - } - - $oParserState->consumeWhiteSpace(); - if ($i < ($iLength - 1)) { - $oParserState->consume(','); - } - } - $oParserState->consume(')'); - - if ($bContainsVar) { - return new CSSFunction($sColorMode, array_values($aColor), ',', $oParserState->currentLine()); - } - } - return new Color($aColor, $oParserState->currentLine()); - } - - /** - * @param float $fVal - * @param float $fFromMin - * @param float $fFromMax - * @param float $fToMin - * @param float $fToMax - * - * @return float - */ - private static function mapRange($fVal, $fFromMin, $fFromMax, $fToMin, $fToMax) - { - $fFromRange = $fFromMax - $fFromMin; - $fToRange = $fToMax - $fToMin; - $fMultiplier = $fToRange / $fFromRange; - $fNewVal = $fVal - $fFromMin; - $fNewVal *= $fMultiplier; - return $fNewVal + $fToMin; - } - - /** - * @return array<int, RuleValueList|CSSFunction|CSSString|LineName|Size|URL|string> - */ - public function getColor() - { - return $this->aComponents; - } - - /** - * @param array<int, RuleValueList|CSSFunction|CSSString|LineName|Size|URL|string> $aColor - * - * @return void - */ - public function setColor(array $aColor) - { - $this->setName(implode('', array_keys($aColor))); - $this->aComponents = $aColor; - } - - /** - * @return string - */ - public function getColorDescription() - { - return $this->getName(); - } - - /** - * @return string - */ - public function __toString() - { - return $this->render(new OutputFormat()); - } - - /** - * @return string - */ - public function render(OutputFormat $oOutputFormat) - { - // Shorthand RGB color values - if ($oOutputFormat->getRGBHashNotation() && implode('', array_keys($this->aComponents)) === 'rgb') { - $sResult = sprintf( - '%02x%02x%02x', - $this->aComponents['r']->getSize(), - $this->aComponents['g']->getSize(), - $this->aComponents['b']->getSize() - ); - return '#' . (($sResult[0] == $sResult[1]) && ($sResult[2] == $sResult[3]) && ($sResult[4] == $sResult[5]) - ? "$sResult[0]$sResult[2]$sResult[4]" : $sResult); - } - return parent::render($oOutputFormat); - } -} diff --git a/lib/sabberworm/php-css-parser/src/Value/LineName.php b/lib/sabberworm/php-css-parser/src/Value/LineName.php deleted file mode 100644 index e231ce38f..000000000 --- a/lib/sabberworm/php-css-parser/src/Value/LineName.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Value; - -use Sabberworm\CSS\OutputFormat; -use Sabberworm\CSS\Parsing\ParserState; -use Sabberworm\CSS\Parsing\UnexpectedEOFException; -use Sabberworm\CSS\Parsing\UnexpectedTokenException; - -class LineName extends ValueList -{ - /** - * @param array<int, RuleValueList|CSSFunction|CSSString|LineName|Size|URL|string> $aComponents - * @param int $iLineNo - */ - public function __construct(array $aComponents = [], $iLineNo = 0) - { - parent::__construct($aComponents, ' ', $iLineNo); - } - - /** - * @return LineName - * - * @throws UnexpectedTokenException - * @throws UnexpectedEOFException - */ - public static function parse(ParserState $oParserState) - { - $oParserState->consume('['); - $oParserState->consumeWhiteSpace(); - $aNames = []; - do { - if ($oParserState->getSettings()->bLenientParsing) { - try { - $aNames[] = $oParserState->parseIdentifier(); - } catch (UnexpectedTokenException $e) { - if (!$oParserState->comes(']')) { - throw $e; - } - } - } else { - $aNames[] = $oParserState->parseIdentifier(); - } - $oParserState->consumeWhiteSpace(); - } while (!$oParserState->comes(']')); - $oParserState->consume(']'); - return new LineName($aNames, $oParserState->currentLine()); - } - - /** - * @return string - */ - public function __toString() - { - return $this->render(new OutputFormat()); - } - - /** - * @return string - */ - public function render(OutputFormat $oOutputFormat) - { - return '[' . parent::render(OutputFormat::createCompact()) . ']'; - } -} diff --git a/lib/sabberworm/php-css-parser/src/Value/PrimitiveValue.php b/lib/sabberworm/php-css-parser/src/Value/PrimitiveValue.php deleted file mode 100644 index 055a43975..000000000 --- a/lib/sabberworm/php-css-parser/src/Value/PrimitiveValue.php +++ /dev/null @@ -1,14 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Value; - -abstract class PrimitiveValue extends Value -{ - /** - * @param int $iLineNo - */ - public function __construct($iLineNo = 0) - { - parent::__construct($iLineNo); - } -} diff --git a/lib/sabberworm/php-css-parser/src/Value/RuleValueList.php b/lib/sabberworm/php-css-parser/src/Value/RuleValueList.php deleted file mode 100644 index 5d533a7cb..000000000 --- a/lib/sabberworm/php-css-parser/src/Value/RuleValueList.php +++ /dev/null @@ -1,15 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Value; - -class RuleValueList extends ValueList -{ - /** - * @param string $sSeparator - * @param int $iLineNo - */ - public function __construct($sSeparator = ',', $iLineNo = 0) - { - parent::__construct([], $sSeparator, $iLineNo); - } -} diff --git a/lib/sabberworm/php-css-parser/src/Value/Size.php b/lib/sabberworm/php-css-parser/src/Value/Size.php deleted file mode 100644 index b3801dc17..000000000 --- a/lib/sabberworm/php-css-parser/src/Value/Size.php +++ /dev/null @@ -1,209 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Value; - -use Sabberworm\CSS\OutputFormat; -use Sabberworm\CSS\Parsing\ParserState; -use Sabberworm\CSS\Parsing\UnexpectedEOFException; -use Sabberworm\CSS\Parsing\UnexpectedTokenException; - -class Size extends PrimitiveValue -{ - /** - * vh/vw/vm(ax)/vmin/rem are absolute insofar as they don’t scale to the immediate parent (only the viewport) - * - * @var array<int, string> - */ - const ABSOLUTE_SIZE_UNITS = ['px', 'cm', 'mm', 'mozmm', 'in', 'pt', 'pc', 'vh', 'vw', 'vmin', 'vmax', 'rem']; - - /** - * @var array<int, string> - */ - const RELATIVE_SIZE_UNITS = ['%', 'em', 'ex', 'ch', 'fr']; - - /** - * @var array<int, string> - */ - const NON_SIZE_UNITS = ['deg', 'grad', 'rad', 's', 'ms', 'turns', 'Hz', 'kHz']; - - /** - * @var array<int, array<string, string>>|null - */ - private static $SIZE_UNITS = null; - - /** - * @var float - */ - private $fSize; - - /** - * @var string|null - */ - private $sUnit; - - /** - * @var bool - */ - private $bIsColorComponent; - - /** - * @param float|int|string $fSize - * @param string|null $sUnit - * @param bool $bIsColorComponent - * @param int $iLineNo - */ - public function __construct($fSize, $sUnit = null, $bIsColorComponent = false, $iLineNo = 0) - { - parent::__construct($iLineNo); - $this->fSize = (float)$fSize; - $this->sUnit = $sUnit; - $this->bIsColorComponent = $bIsColorComponent; - } - - /** - * @param bool $bIsColorComponent - * - * @return Size - * - * @throws UnexpectedEOFException - * @throws UnexpectedTokenException - */ - public static function parse(ParserState $oParserState, $bIsColorComponent = false) - { - $sSize = ''; - if ($oParserState->comes('-')) { - $sSize .= $oParserState->consume('-'); - } - while (is_numeric($oParserState->peek()) || $oParserState->comes('.')) { - if ($oParserState->comes('.')) { - $sSize .= $oParserState->consume('.'); - } else { - $sSize .= $oParserState->consume(1); - } - } - - $sUnit = null; - $aSizeUnits = self::getSizeUnits(); - foreach ($aSizeUnits as $iLength => &$aValues) { - $sKey = strtolower($oParserState->peek($iLength)); - if (array_key_exists($sKey, $aValues)) { - if (($sUnit = $aValues[$sKey]) !== null) { - $oParserState->consume($iLength); - break; - } - } - } - return new Size((float)$sSize, $sUnit, $bIsColorComponent, $oParserState->currentLine()); - } - - /** - * @return array<int, array<string, string>> - */ - private static function getSizeUnits() - { - if (!is_array(self::$SIZE_UNITS)) { - self::$SIZE_UNITS = []; - foreach (array_merge(self::ABSOLUTE_SIZE_UNITS, self::RELATIVE_SIZE_UNITS, self::NON_SIZE_UNITS) as $val) { - $iSize = strlen($val); - if (!isset(self::$SIZE_UNITS[$iSize])) { - self::$SIZE_UNITS[$iSize] = []; - } - self::$SIZE_UNITS[$iSize][strtolower($val)] = $val; - } - - krsort(self::$SIZE_UNITS, SORT_NUMERIC); - } - - return self::$SIZE_UNITS; - } - - /** - * @param string $sUnit - * - * @return void - */ - public function setUnit($sUnit) - { - $this->sUnit = $sUnit; - } - - /** - * @return string|null - */ - public function getUnit() - { - return $this->sUnit; - } - - /** - * @param float|int|string $fSize - */ - public function setSize($fSize) - { - $this->fSize = (float)$fSize; - } - - /** - * @return float - */ - public function getSize() - { - return $this->fSize; - } - - /** - * @return bool - */ - public function isColorComponent() - { - return $this->bIsColorComponent; - } - - /** - * Returns whether the number stored in this Size really represents a size (as in a length of something on screen). - * - * @return false if the unit an angle, a duration, a frequency or the number is a component in a Color object. - */ - public function isSize() - { - if (in_array($this->sUnit, self::NON_SIZE_UNITS, true)) { - return false; - } - return !$this->isColorComponent(); - } - - /** - * @return bool - */ - public function isRelative() - { - if (in_array($this->sUnit, self::RELATIVE_SIZE_UNITS, true)) { - return true; - } - if ($this->sUnit === null && $this->fSize != 0) { - return true; - } - return false; - } - - /** - * @return string - */ - public function __toString() - { - return $this->render(new OutputFormat()); - } - - /** - * @return string - */ - public function render(OutputFormat $oOutputFormat) - { - $l = localeconv(); - $sPoint = preg_quote($l['decimal_point'], '/'); - $sSize = preg_match("/[\d\.]+e[+-]?\d+/i", (string)$this->fSize) - ? preg_replace("/$sPoint?0+$/", "", sprintf("%f", $this->fSize)) : $this->fSize; - return preg_replace(["/$sPoint/", "/^(-?)0\./"], ['.', '$1.'], $sSize) - . ($this->sUnit === null ? '' : $this->sUnit); - } -} diff --git a/lib/sabberworm/php-css-parser/src/Value/URL.php b/lib/sabberworm/php-css-parser/src/Value/URL.php deleted file mode 100644 index 1467d505c..000000000 --- a/lib/sabberworm/php-css-parser/src/Value/URL.php +++ /dev/null @@ -1,82 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Value; - -use Sabberworm\CSS\OutputFormat; -use Sabberworm\CSS\Parsing\ParserState; -use Sabberworm\CSS\Parsing\SourceException; -use Sabberworm\CSS\Parsing\UnexpectedEOFException; -use Sabberworm\CSS\Parsing\UnexpectedTokenException; - -class URL extends PrimitiveValue -{ - /** - * @var CSSString - */ - private $oURL; - - /** - * @param int $iLineNo - */ - public function __construct(CSSString $oURL, $iLineNo = 0) - { - parent::__construct($iLineNo); - $this->oURL = $oURL; - } - - /** - * @return URL - * - * @throws SourceException - * @throws UnexpectedEOFException - * @throws UnexpectedTokenException - */ - public static function parse(ParserState $oParserState) - { - $bUseUrl = $oParserState->comes('url', true); - if ($bUseUrl) { - $oParserState->consume('url'); - $oParserState->consumeWhiteSpace(); - $oParserState->consume('('); - } - $oParserState->consumeWhiteSpace(); - $oResult = new URL(CSSString::parse($oParserState), $oParserState->currentLine()); - if ($bUseUrl) { - $oParserState->consumeWhiteSpace(); - $oParserState->consume(')'); - } - return $oResult; - } - - /** - * @return void - */ - public function setURL(CSSString $oURL) - { - $this->oURL = $oURL; - } - - /** - * @return CSSString - */ - public function getURL() - { - return $this->oURL; - } - - /** - * @return string - */ - public function __toString() - { - return $this->render(new OutputFormat()); - } - - /** - * @return string - */ - public function render(OutputFormat $oOutputFormat) - { - return "url({$this->oURL->render($oOutputFormat)})"; - } -} diff --git a/lib/sabberworm/php-css-parser/src/Value/Value.php b/lib/sabberworm/php-css-parser/src/Value/Value.php deleted file mode 100644 index 66cb9fd47..000000000 --- a/lib/sabberworm/php-css-parser/src/Value/Value.php +++ /dev/null @@ -1,198 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Value; - -use Sabberworm\CSS\Parsing\ParserState; -use Sabberworm\CSS\Parsing\SourceException; -use Sabberworm\CSS\Parsing\UnexpectedEOFException; -use Sabberworm\CSS\Parsing\UnexpectedTokenException; -use Sabberworm\CSS\Renderable; - -abstract class Value implements Renderable -{ - /** - * @var int - */ - protected $iLineNo; - - /** - * @param int $iLineNo - */ - public function __construct($iLineNo = 0) - { - $this->iLineNo = $iLineNo; - } - - /** - * @param array<array-key, string> $aListDelimiters - * - * @return RuleValueList|CSSFunction|CSSString|LineName|Size|URL|string - * - * @throws UnexpectedTokenException - * @throws UnexpectedEOFException - */ - public static function parseValue(ParserState $oParserState, array $aListDelimiters = []) - { - /** @var array<int, RuleValueList|CSSFunction|CSSString|LineName|Size|URL|string> $aStack */ - $aStack = []; - $oParserState->consumeWhiteSpace(); - //Build a list of delimiters and parsed values - while ( - !($oParserState->comes('}') || $oParserState->comes(';') || $oParserState->comes('!') - || $oParserState->comes(')') - || $oParserState->comes('\\')) - ) { - if (count($aStack) > 0) { - $bFoundDelimiter = false; - foreach ($aListDelimiters as $sDelimiter) { - if ($oParserState->comes($sDelimiter)) { - array_push($aStack, $oParserState->consume($sDelimiter)); - $oParserState->consumeWhiteSpace(); - $bFoundDelimiter = true; - break; - } - } - if (!$bFoundDelimiter) { - //Whitespace was the list delimiter - array_push($aStack, ' '); - } - } - array_push($aStack, self::parsePrimitiveValue($oParserState)); - $oParserState->consumeWhiteSpace(); - } - // Convert the list to list objects - foreach ($aListDelimiters as $sDelimiter) { - if (count($aStack) === 1) { - return $aStack[0]; - } - $iStartPosition = null; - while (($iStartPosition = array_search($sDelimiter, $aStack, true)) !== false) { - $iLength = 2; //Number of elements to be joined - for ($i = $iStartPosition + 2; $i < count($aStack); $i += 2, ++$iLength) { - if ($sDelimiter !== $aStack[$i]) { - break; - } - } - $oList = new RuleValueList($sDelimiter, $oParserState->currentLine()); - for ($i = $iStartPosition - 1; $i - $iStartPosition + 1 < $iLength * 2; $i += 2) { - $oList->addListComponent($aStack[$i]); - } - array_splice($aStack, $iStartPosition - 1, $iLength * 2 - 1, [$oList]); - } - } - if (!isset($aStack[0])) { - throw new UnexpectedTokenException( - " {$oParserState->peek()} ", - $oParserState->peek(1, -1) . $oParserState->peek(2), - 'literal', - $oParserState->currentLine() - ); - } - return $aStack[0]; - } - - /** - * @param bool $bIgnoreCase - * - * @return CSSFunction|string - * - * @throws UnexpectedEOFException - * @throws UnexpectedTokenException - */ - public static function parseIdentifierOrFunction(ParserState $oParserState, $bIgnoreCase = false) - { - $sResult = $oParserState->parseIdentifier($bIgnoreCase); - - if ($oParserState->comes('(')) { - $oParserState->consume('('); - $aArguments = Value::parseValue($oParserState, ['=', ' ', ',']); - $sResult = new CSSFunction($sResult, $aArguments, ',', $oParserState->currentLine()); - $oParserState->consume(')'); - } - - return $sResult; - } - - /** - * @return CSSFunction|CSSString|LineName|Size|URL|string - * - * @throws UnexpectedEOFException - * @throws UnexpectedTokenException - * @throws SourceException - */ - public static function parsePrimitiveValue(ParserState $oParserState) - { - $oValue = null; - $oParserState->consumeWhiteSpace(); - if ( - is_numeric($oParserState->peek()) - || ($oParserState->comes('-.') - && is_numeric($oParserState->peek(1, 2))) - || (($oParserState->comes('-') || $oParserState->comes('.')) && is_numeric($oParserState->peek(1, 1))) - ) { - $oValue = Size::parse($oParserState); - } elseif ($oParserState->comes('#') || $oParserState->comes('rgb', true) || $oParserState->comes('hsl', true)) { - $oValue = Color::parse($oParserState); - } elseif ($oParserState->comes('url', true)) { - $oValue = URL::parse($oParserState); - } elseif ( - $oParserState->comes('calc', true) || $oParserState->comes('-webkit-calc', true) - || $oParserState->comes('-moz-calc', true) - ) { - $oValue = CalcFunction::parse($oParserState); - } elseif ($oParserState->comes("'") || $oParserState->comes('"')) { - $oValue = CSSString::parse($oParserState); - } elseif ($oParserState->comes("progid:") && $oParserState->getSettings()->bLenientParsing) { - $oValue = self::parseMicrosoftFilter($oParserState); - } elseif ($oParserState->comes("[")) { - $oValue = LineName::parse($oParserState); - } elseif ($oParserState->comes("U+")) { - $oValue = self::parseUnicodeRangeValue($oParserState); - } else { - $oValue = self::parseIdentifierOrFunction($oParserState); - } - $oParserState->consumeWhiteSpace(); - return $oValue; - } - - /** - * @return CSSFunction - * - * @throws UnexpectedEOFException - * @throws UnexpectedTokenException - */ - private static function parseMicrosoftFilter(ParserState $oParserState) - { - $sFunction = $oParserState->consumeUntil('(', false, true); - $aArguments = Value::parseValue($oParserState, [',', '=']); - return new CSSFunction($sFunction, $aArguments, ',', $oParserState->currentLine()); - } - - /** - * @return string - * - * @throws UnexpectedEOFException - * @throws UnexpectedTokenException - */ - private static function parseUnicodeRangeValue(ParserState $oParserState) - { - $iCodepointMaxLength = 6; // Code points outside BMP can use up to six digits - $sRange = ""; - $oParserState->consume("U+"); - do { - if ($oParserState->comes('-')) { - $iCodepointMaxLength = 13; // Max length is 2 six digit code points + the dash(-) between them - } - $sRange .= $oParserState->consume(1); - } while (strlen($sRange) < $iCodepointMaxLength && preg_match("/[A-Fa-f0-9\?-]/", $oParserState->peek())); - return "U+{$sRange}"; - } - - /** - * @return int - */ - public function getLineNo() - { - return $this->iLineNo; - } -} diff --git a/lib/sabberworm/php-css-parser/src/Value/ValueList.php b/lib/sabberworm/php-css-parser/src/Value/ValueList.php deleted file mode 100644 index af5348b96..000000000 --- a/lib/sabberworm/php-css-parser/src/Value/ValueList.php +++ /dev/null @@ -1,100 +0,0 @@ -<?php - -namespace Sabberworm\CSS\Value; - -use Sabberworm\CSS\OutputFormat; - -abstract class ValueList extends Value -{ - /** - * @var array<int, RuleValueList|CSSFunction|CSSString|LineName|Size|URL|string> - */ - protected $aComponents; - - /** - * @var string - */ - protected $sSeparator; - - /** - * phpcs:ignore Generic.Files.LineLength - * @param array<int, RuleValueList|CSSFunction|CSSString|LineName|Size|URL|string>|RuleValueList|CSSFunction|CSSString|LineName|Size|URL|string $aComponents - * @param string $sSeparator - * @param int $iLineNo - */ - public function __construct($aComponents = [], $sSeparator = ',', $iLineNo = 0) - { - parent::__construct($iLineNo); - if (!is_array($aComponents)) { - $aComponents = [$aComponents]; - } - $this->aComponents = $aComponents; - $this->sSeparator = $sSeparator; - } - - /** - * @param RuleValueList|CSSFunction|CSSString|LineName|Size|URL|string $mComponent - * - * @return void - */ - public function addListComponent($mComponent) - { - $this->aComponents[] = $mComponent; - } - - /** - * @return array<int, RuleValueList|CSSFunction|CSSString|LineName|Size|URL|string> - */ - public function getListComponents() - { - return $this->aComponents; - } - - /** - * @param array<int, RuleValueList|CSSFunction|CSSString|LineName|Size|URL|string> $aComponents - * - * @return void - */ - public function setListComponents(array $aComponents) - { - $this->aComponents = $aComponents; - } - - /** - * @return string - */ - public function getListSeparator() - { - return $this->sSeparator; - } - - /** - * @param string $sSeparator - * - * @return void - */ - public function setListSeparator($sSeparator) - { - $this->sSeparator = $sSeparator; - } - - /** - * @return string - */ - public function __toString() - { - return $this->render(new OutputFormat()); - } - - /** - * @return string - */ - public function render(OutputFormat $oOutputFormat) - { - return $oOutputFormat->implode( - $oOutputFormat->spaceBeforeListArgumentSeparator($this->sSeparator) . $this->sSeparator - . $oOutputFormat->spaceAfterListArgumentSeparator($this->sSeparator), - $this->aComponents - ); - } -} diff --git a/lib/scssphp/scssphp/LICENSE.md b/lib/scssphp/scssphp/LICENSE.md deleted file mode 100644 index afcfdfb26..000000000 --- a/lib/scssphp/scssphp/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2015 Leaf Corcoran, http://scssphp.github.io/scssphp - -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/lib/scssphp/scssphp/README.md b/lib/scssphp/scssphp/README.md deleted file mode 100644 index 65bb93ea7..000000000 --- a/lib/scssphp/scssphp/README.md +++ /dev/null @@ -1,71 +0,0 @@ -# scssphp -### <https://scssphp.github.io/scssphp> - -![Build](https://github.com/scssphp/scssphp/workflows/CI/badge.svg) -[![License](https://poser.pugx.org/scssphp/scssphp/license)](https://packagist.org/packages/scssphp/scssphp) - -`scssphp` is a compiler for SCSS written in PHP. - -Checkout the homepage, <https://scssphp.github.io/scssphp>, for directions on how to use. - -## Running Tests - -`scssphp` uses [PHPUnit](https://github.com/sebastianbergmann/phpunit) for testing. - -Run the following command from the root directory to run every test: - - vendor/bin/phpunit tests - -There are several tests in the `tests/` directory: - -* `ApiTest.php` contains various unit tests that test the PHP interface. -* `ExceptionTest.php` contains unit tests that test for exceptions thrown by the parser and compiler. -* `FailingTest.php` contains tests reported in Github issues that demonstrate compatibility bugs. -* `InputTest.php` compiles every `.scss` file in the `tests/inputs` directory - then compares to the respective `.css` file in the `tests/outputs` directory. -* `SassSpecTest.php` extracts tests from the `sass/sass-spec` repository. - -When changing any of the tests in `tests/inputs`, the tests will most likely -fail because the output has changed. Once you verify that the output is correct -you can run the following command to rebuild all the tests: - - BUILD=1 vendor/bin/phpunit tests - -This will compile all the tests, and save results into `tests/outputs`. It also -updates the list of excluded specs from sass-spec. - -To enable the full `sass-spec` compatibility tests: - - TEST_SASS_SPEC=1 vendor/bin/phpunit tests - -## Coding Standard - -`scssphp` source conforms to [PSR12](https://www.php-fig.org/psr/psr-12/). - -Run the following command from the root directory to check the code for "sniffs". - - vendor/bin/phpcs --standard=PSR12 --extensions=php bin src tests *.php - -## Static Analysis - -`scssphp` uses [phpstan](https://phpstan.org/) for static analysis. - -Run the following command from the root directory to analyse the codebase: - - make phpstan - -As most of the codebase is composed of legacy code which cannot be type-checked -fully, the setup contains a baseline file with all errors we want to ignore. In -particular, we ignore all errors related to not specifying the types inside arrays -when these arrays correspond to the representation of Sass values and Sass AST nodes -in the parser and compiler. -When contributing, the proper process to deal with static analysis is the following: - -1. Make your change in the codebase -2. Run `make phpstan` -3. Fix errors reported by phpstan when possible -4. Repeat step 2 and 3 until nothing gets fixed anymore at step 3 -5. Run `make phpstan-baseline` to regenerate the phpstan baseline - -Additions to the baseline will be reviewed to avoid ignoring errors that should have -been fixed. diff --git a/lib/scssphp/scssphp/bin/pscss b/lib/scssphp/scssphp/bin/pscss deleted file mode 100644 index 0f009d6bd..000000000 --- a/lib/scssphp/scssphp/bin/pscss +++ /dev/null @@ -1,244 +0,0 @@ -#!/usr/bin/env php -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -error_reporting(E_ALL); - -if (version_compare(PHP_VERSION, '5.6') < 0) { - die('Requires PHP 5.6 or above'); -} - -include __DIR__ . '/../scss.inc.php'; - -use ScssPhp\ScssPhp\Compiler; -use ScssPhp\ScssPhp\Exception\SassException; -use ScssPhp\ScssPhp\OutputStyle; -use ScssPhp\ScssPhp\Parser; -use ScssPhp\ScssPhp\Version; - -$style = null; -$loadPaths = []; -$dumpTree = false; -$inputFile = null; -$changeDir = false; -$encoding = false; -$sourceMap = false; -$embedSources = false; -$embedSourceMap = false; - -/** - * Parse argument - * - * @param int $i - * @param string[] $options - * - * @return string|null - */ -function parseArgument(&$i, $options) { - global $argc; - global $argv; - - if (! preg_match('/^(?:' . implode('|', (array) $options) . ')=?(.*)/', $argv[$i], $matches)) { - return; - } - - if (strlen($matches[1])) { - return $matches[1]; - } - - if ($i + 1 < $argc) { - $i++; - - return $argv[$i]; - } -} - -$arguments = []; - -for ($i = 1; $i < $argc; $i++) { - if ($argv[$i] === '-?' || $argv[$i] === '-h' || $argv[$i] === '--help') { - $exe = $argv[0]; - - $HELP = <<<EOT -Usage: $exe [options] [input-file] [output-file] - -Options include: - - --help Show this message [-h, -?] - --continue-on-error [deprecated] Ignored - --debug-info [deprecated] Ignored [-g] - --dump-tree [deprecated] Dump formatted parse tree [-T] - --iso8859-1 Use iso8859-1 encoding instead of default utf-8 - --line-numbers [deprecated] Ignored [--line-comments] - --load-path=PATH Set import path [-I] - --precision=N [deprecated] Ignored. (default 10) [-p] - --sourcemap Create source map file - --embed-sources Embed source file contents in source maps - --embed-source-map Embed the source map contents in CSS (default if writing to stdout) - --style=FORMAT Set the output style (compressed or expanded) [-s, -t] - --version Print the version [-v] - -EOT; - exit($HELP); - } - - if ($argv[$i] === '-v' || $argv[$i] === '--version') { - exit(Version::VERSION . "\n"); - } - - // Keep parsing --continue-on-error to avoid BC breaks for scripts using it - if ($argv[$i] === '--continue-on-error') { - // TODO report it as a warning ? - continue; - } - - // Keep parsing it to avoid BC breaks for scripts using it - if ($argv[$i] === '-g' || $argv[$i] === '--debug-info') { - // TODO report it as a warning ? - continue; - } - - if ($argv[$i] === '--iso8859-1') { - $encoding = 'iso8859-1'; - continue; - } - - // Keep parsing it to avoid BC breaks for scripts using it - if ($argv[$i] === '--line-numbers' || $argv[$i] === '--line-comments') { - // TODO report it as a warning ? - continue; - } - - if ($argv[$i] === '--sourcemap') { - $sourceMap = true; - continue; - } - - if ($argv[$i] === '--embed-sources') { - $embedSources = true; - continue; - } - - if ($argv[$i] === '--embed-source-map') { - $embedSourceMap = true; - continue; - } - - if ($argv[$i] === '-T' || $argv[$i] === '--dump-tree') { - $dumpTree = true; - continue; - } - - $value = parseArgument($i, array('-t', '-s', '--style')); - - if (isset($value)) { - $style = $value; - continue; - } - - $value = parseArgument($i, array('-I', '--load-path')); - - if (isset($value)) { - $loadPaths[] = $value; - continue; - } - - // Keep parsing --precision to avoid BC breaks for scripts using it - $value = parseArgument($i, array('-p', '--precision')); - - if (isset($value)) { - // TODO report it as a warning ? - continue; - } - - $arguments[] = $argv[$i]; -} - - -if (isset($arguments[0]) && file_exists($arguments[0])) { - $inputFile = $arguments[0]; - $data = file_get_contents($inputFile); -} else { - $data = ''; - - while (! feof(STDIN)) { - $data .= fread(STDIN, 8192); - } -} - -if ($dumpTree) { - $parser = new Parser($inputFile); - - print_r(json_decode(json_encode($parser->parse($data)), true)); - - fwrite(STDERR, 'Warning: the --dump-tree option is deprecated. Use proper debugging tools instead.'); - - exit(); -} - -$scss = new Compiler(); - -if ($loadPaths) { - $scss->setImportPaths($loadPaths); -} - -if ($style) { - if ($style === OutputStyle::COMPRESSED || $style === OutputStyle::EXPANDED) { - $scss->setOutputStyle($style); - } else { - fwrite(STDERR, "WARNING: the $style style is deprecated.\n"); - $scss->setFormatter('ScssPhp\\ScssPhp\\Formatter\\' . ucfirst($style)); - } -} - -$outputFile = isset($arguments[1]) ? $arguments[1] : null; -$sourceMapFile = null; - -if ($sourceMap) { - $sourceMapOptions = array( - 'outputSourceFiles' => $embedSources, - ); - if ($embedSourceMap || $outputFile === null) { - $scss->setSourceMap(Compiler::SOURCE_MAP_INLINE); - } else { - $sourceMapFile = $outputFile . '.map'; - $sourceMapOptions['sourceMapWriteTo'] = $sourceMapFile; - $sourceMapOptions['sourceMapURL'] = basename($sourceMapFile); - $sourceMapOptions['sourceMapBasepath'] = getcwd(); - $sourceMapOptions['sourceMapFilename'] = basename($outputFile); - - $scss->setSourceMap(Compiler::SOURCE_MAP_FILE); - } - - $scss->setSourceMapOptions($sourceMapOptions); -} - -if ($encoding) { - $scss->setEncoding($encoding); -} - -try { - $result = $scss->compileString($data, $inputFile); -} catch (SassException $e) { - fwrite(STDERR, 'Error: '.$e->getMessage()."\n"); - exit(1); -} - -if ($outputFile) { - file_put_contents($outputFile, $result->getCss()); - - if ($sourceMapFile !== null && $result->getSourceMap() !== null) { - file_put_contents($sourceMapFile, $result->getSourceMap()); - } -} else { - echo $result->getCss(); -} diff --git a/lib/scssphp/scssphp/composer.json b/lib/scssphp/scssphp/composer.json deleted file mode 100644 index 269a4732f..000000000 --- a/lib/scssphp/scssphp/composer.json +++ /dev/null @@ -1,117 +0,0 @@ -{ - "name": "scssphp/scssphp", - "type": "library", - "description": "scssphp is a compiler for SCSS written in PHP.", - "keywords": ["css", "stylesheet", "scss", "sass", "less"], - "homepage": "http://scssphp.github.io/scssphp/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Anthon Pang", - "email": "apang@softwaredevelopment.ca", - "homepage": "https://github.com/robocoder" - }, - { - "name": "Cédric Morin", - "email": "cedric@yterium.com", - "homepage": "https://github.com/Cerdic" - } - ], - "autoload": { - "psr-4": { "ScssPhp\\ScssPhp\\": "src/" } - }, - "autoload-dev": { - "psr-4": { "ScssPhp\\ScssPhp\\Tests\\": "tests/" } - }, - "require": { - "php": ">=5.6.0", - "ext-json": "*", - "ext-ctype": "*" - }, - "suggest": { - "ext-mbstring": "For best performance, mbstring should be installed as it is faster than ext-iconv", - "ext-iconv": "Can be used as fallback when ext-mbstring is not available" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.4", - "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.3 || ^9.4", - "sass/sass-spec": "*", - "squizlabs/php_codesniffer": "~3.5", - "symfony/phpunit-bridge": "^5.1", - "thoughtbot/bourbon": "^7.0", - "twbs/bootstrap": "~5.0", - "twbs/bootstrap4": "4.6.1", - "zurb/foundation": "~6.5" - }, - "repositories": [ - { - "type": "package", - "package": { - "name": "sass/sass-spec", - "version": "2022.02.24", - "source": { - "type": "git", - "url": "https://github.com/sass/sass-spec.git", - "reference": "f41b9bfb9a3013392f2136c79f7f3356f15fb8ba" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sass/sass-spec/zipball/f41b9bfb9a3013392f2136c79f7f3356f15fb8ba", - "reference": "f41b9bfb9a3013392f2136c79f7f3356f15fb8ba", - "shasum": "" - } - } - }, - { - "type": "package", - "package": { - "name": "thoughtbot/bourbon", - "version": "v7.0.0", - "source": { - "type": "git", - "url": "https://github.com/thoughtbot/bourbon.git", - "reference": "fbe338ee6807e7f7aa996d82c8a16f248bb149b3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thoughtbot/bourbon/zipball/fbe338ee6807e7f7aa996d82c8a16f248bb149b3", - "reference": "fbe338ee6807e7f7aa996d82c8a16f248bb149b3", - "shasum": "" - } - } - }, - { - "type": "package", - "package": { - "name": "twbs/bootstrap4", - "version": "v4.6.1", - "source": { - "type": "git", - "url": "https://github.com/twbs/bootstrap.git", - "reference": "043a03c95a2ad6738f85b65e53b9dbdfb03b8d10" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/twbs/bootstrap/zipball/043a03c95a2ad6738f85b65e53b9dbdfb03b8d10", - "reference": "043a03c95a2ad6738f85b65e53b9dbdfb03b8d10", - "shasum": "" - } - } - } - ], - "bin": ["bin/pscss"], - "config": { - "sort-packages": true, - "allow-plugins": { - "bamarni/composer-bin-plugin": true - } - }, - "extra": { - "bamarni-bin": { - "forward-command": false, - "bin-links": false - } - } -} diff --git a/lib/scssphp/scssphp/scss.inc.php b/lib/scssphp/scssphp/scss.inc.php deleted file mode 100644 index 459837805..000000000 --- a/lib/scssphp/scssphp/scss.inc.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -if (version_compare(PHP_VERSION, '5.6') < 0) { - throw new \Exception('scssphp requires PHP 5.6 or above'); -} - -if (! class_exists('ScssPhp\ScssPhp\Version')) { - spl_autoload_register(function ($class) { - if (0 !== strpos($class, 'ScssPhp\ScssPhp\\')) { - // Not a ScssPhp class - return; - } - - $subClass = substr($class, strlen('ScssPhp\ScssPhp\\')); - $path = __DIR__ . '/src/' . str_replace('\\', '/', $subClass) . '.php'; - - if (file_exists($path)) { - require $path; - } - }); -} diff --git a/lib/scssphp/scssphp/src/Base/Range.php b/lib/scssphp/scssphp/src/Base/Range.php deleted file mode 100644 index 31d5ec565..000000000 --- a/lib/scssphp/scssphp/src/Base/Range.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2015-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Base; - -/** - * Range - * - * @author Anthon Pang <anthon.pang@gmail.com> - * - * @internal - */ -class Range -{ - /** - * @var float|int - */ - public $first; - - /** - * @var float|int - */ - public $last; - - /** - * Initialize range - * - * @param int|float $first - * @param int|float $last - */ - public function __construct($first, $last) - { - $this->first = $first; - $this->last = $last; - } - - /** - * Test for inclusion in range - * - * @param int|float $value - * - * @return bool - */ - public function includes($value) - { - return $value >= $this->first && $value <= $this->last; - } -} diff --git a/lib/scssphp/scssphp/src/Block.php b/lib/scssphp/scssphp/src/Block.php deleted file mode 100644 index 96668dc66..000000000 --- a/lib/scssphp/scssphp/src/Block.php +++ /dev/null @@ -1,73 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp; - -/** - * Block - * - * @author Anthon Pang <anthon.pang@gmail.com> - * - * @internal - */ -class Block -{ - /** - * @var string|null - */ - public $type; - - /** - * @var Block|null - */ - public $parent; - - /** - * @var string - */ - public $sourceName; - - /** - * @var int - */ - public $sourceIndex; - - /** - * @var int - */ - public $sourceLine; - - /** - * @var int - */ - public $sourceColumn; - - /** - * @var array|null - */ - public $selectors; - - /** - * @var array - */ - public $comments; - - /** - * @var array - */ - public $children; - - /** - * @var Block|null - */ - public $selfParent; -} diff --git a/lib/scssphp/scssphp/src/Block/AtRootBlock.php b/lib/scssphp/scssphp/src/Block/AtRootBlock.php deleted file mode 100644 index 41842c269..000000000 --- a/lib/scssphp/scssphp/src/Block/AtRootBlock.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Block; - -use ScssPhp\ScssPhp\Block; -use ScssPhp\ScssPhp\Type; - -/** - * @internal - */ -class AtRootBlock extends Block -{ - /** - * @var array|null - */ - public $selector; - - /** - * @var array|null - */ - public $with; - - public function __construct() - { - $this->type = Type::T_AT_ROOT; - } -} diff --git a/lib/scssphp/scssphp/src/Block/CallableBlock.php b/lib/scssphp/scssphp/src/Block/CallableBlock.php deleted file mode 100644 index a18a87c2a..000000000 --- a/lib/scssphp/scssphp/src/Block/CallableBlock.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Block; - -use ScssPhp\ScssPhp\Block; -use ScssPhp\ScssPhp\Compiler\Environment; - -/** - * @internal - */ -class CallableBlock extends Block -{ - /** - * @var string - */ - public $name; - - /** - * @var array|null - */ - public $args; - - /** - * @var Environment|null - */ - public $parentEnv; - - /** - * @param string $type - */ - public function __construct($type) - { - $this->type = $type; - } -} diff --git a/lib/scssphp/scssphp/src/Block/ContentBlock.php b/lib/scssphp/scssphp/src/Block/ContentBlock.php deleted file mode 100644 index 870849800..000000000 --- a/lib/scssphp/scssphp/src/Block/ContentBlock.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Block; - -use ScssPhp\ScssPhp\Block; -use ScssPhp\ScssPhp\Compiler\Environment; -use ScssPhp\ScssPhp\Type; - -/** - * @internal - */ -class ContentBlock extends Block -{ - /** - * @var array|null - */ - public $child; - - /** - * @var Environment|null - */ - public $scope; - - public function __construct() - { - $this->type = Type::T_INCLUDE; - } -} diff --git a/lib/scssphp/scssphp/src/Block/DirectiveBlock.php b/lib/scssphp/scssphp/src/Block/DirectiveBlock.php deleted file mode 100644 index b1d3d1a81..000000000 --- a/lib/scssphp/scssphp/src/Block/DirectiveBlock.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Block; - -use ScssPhp\ScssPhp\Block; -use ScssPhp\ScssPhp\Type; - -/** - * @internal - */ -class DirectiveBlock extends Block -{ - /** - * @var string|array - */ - public $name; - - /** - * @var string|array|null - */ - public $value; - - public function __construct() - { - $this->type = Type::T_DIRECTIVE; - } -} diff --git a/lib/scssphp/scssphp/src/Block/EachBlock.php b/lib/scssphp/scssphp/src/Block/EachBlock.php deleted file mode 100644 index b3289579d..000000000 --- a/lib/scssphp/scssphp/src/Block/EachBlock.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Block; - -use ScssPhp\ScssPhp\Block; -use ScssPhp\ScssPhp\Type; - -/** - * @internal - */ -class EachBlock extends Block -{ - /** - * @var string[] - */ - public $vars = []; - - /** - * @var array - */ - public $list; - - public function __construct() - { - $this->type = Type::T_EACH; - } -} diff --git a/lib/scssphp/scssphp/src/Block/ElseBlock.php b/lib/scssphp/scssphp/src/Block/ElseBlock.php deleted file mode 100644 index 6abb4d775..000000000 --- a/lib/scssphp/scssphp/src/Block/ElseBlock.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Block; - -use ScssPhp\ScssPhp\Block; -use ScssPhp\ScssPhp\Type; - -/** - * @internal - */ -class ElseBlock extends Block -{ - public function __construct() - { - $this->type = Type::T_ELSE; - } -} diff --git a/lib/scssphp/scssphp/src/Block/ElseifBlock.php b/lib/scssphp/scssphp/src/Block/ElseifBlock.php deleted file mode 100644 index 4622bca79..000000000 --- a/lib/scssphp/scssphp/src/Block/ElseifBlock.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Block; - -use ScssPhp\ScssPhp\Block; -use ScssPhp\ScssPhp\Type; - -/** - * @internal - */ -class ElseifBlock extends Block -{ - /** - * @var array - */ - public $cond; - - public function __construct() - { - $this->type = Type::T_ELSEIF; - } -} diff --git a/lib/scssphp/scssphp/src/Block/ForBlock.php b/lib/scssphp/scssphp/src/Block/ForBlock.php deleted file mode 100644 index a9cf6733b..000000000 --- a/lib/scssphp/scssphp/src/Block/ForBlock.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Block; - -use ScssPhp\ScssPhp\Block; -use ScssPhp\ScssPhp\Type; - -/** - * @internal - */ -class ForBlock extends Block -{ - /** - * @var string - */ - public $var; - - /** - * @var array - */ - public $start; - - /** - * @var array - */ - public $end; - - /** - * @var bool - */ - public $until; - - public function __construct() - { - $this->type = Type::T_FOR; - } -} diff --git a/lib/scssphp/scssphp/src/Block/IfBlock.php b/lib/scssphp/scssphp/src/Block/IfBlock.php deleted file mode 100644 index 9f21bf88a..000000000 --- a/lib/scssphp/scssphp/src/Block/IfBlock.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Block; - -use ScssPhp\ScssPhp\Block; -use ScssPhp\ScssPhp\Type; - -/** - * @internal - */ -class IfBlock extends Block -{ - /** - * @var array - */ - public $cond; - - /** - * @var array<ElseifBlock|ElseBlock> - */ - public $cases = []; - - public function __construct() - { - $this->type = Type::T_IF; - } -} diff --git a/lib/scssphp/scssphp/src/Block/MediaBlock.php b/lib/scssphp/scssphp/src/Block/MediaBlock.php deleted file mode 100644 index c49ee1b2b..000000000 --- a/lib/scssphp/scssphp/src/Block/MediaBlock.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Block; - -use ScssPhp\ScssPhp\Block; -use ScssPhp\ScssPhp\Type; - -/** - * @internal - */ -class MediaBlock extends Block -{ - /** - * @var string|array|null - */ - public $value; - - /** - * @var array|null - */ - public $queryList; - - public function __construct() - { - $this->type = Type::T_MEDIA; - } -} diff --git a/lib/scssphp/scssphp/src/Block/NestedPropertyBlock.php b/lib/scssphp/scssphp/src/Block/NestedPropertyBlock.php deleted file mode 100644 index 1ea4a6c8a..000000000 --- a/lib/scssphp/scssphp/src/Block/NestedPropertyBlock.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Block; - -use ScssPhp\ScssPhp\Block; -use ScssPhp\ScssPhp\Type; - -/** - * @internal - */ -class NestedPropertyBlock extends Block -{ - /** - * @var bool - */ - public $hasValue; - - /** - * @var array - */ - public $prefix; - - public function __construct() - { - $this->type = Type::T_NESTED_PROPERTY; - } -} diff --git a/lib/scssphp/scssphp/src/Block/WhileBlock.php b/lib/scssphp/scssphp/src/Block/WhileBlock.php deleted file mode 100644 index ac18d4e02..000000000 --- a/lib/scssphp/scssphp/src/Block/WhileBlock.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Block; - -use ScssPhp\ScssPhp\Block; -use ScssPhp\ScssPhp\Type; - -/** - * @internal - */ -class WhileBlock extends Block -{ - /** - * @var array - */ - public $cond; - - public function __construct() - { - $this->type = Type::T_WHILE; - } -} diff --git a/lib/scssphp/scssphp/src/Cache.php b/lib/scssphp/scssphp/src/Cache.php deleted file mode 100644 index 9731c60a7..000000000 --- a/lib/scssphp/scssphp/src/Cache.php +++ /dev/null @@ -1,272 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp; - -use Exception; -use ScssPhp\ScssPhp\Version; - -/** - * The scss cache manager. - * - * In short: - * - * allow to put in cache/get from cache a generic result from a known operation on a generic dataset, - * taking in account options that affects the result - * - * The cache manager is agnostic about data format and only the operation is expected to be described by string - */ - -/** - * SCSS cache - * - * @author Cedric Morin <cedric@yterium.com> - * - * @internal - */ -class Cache -{ - const CACHE_VERSION = 1; - - /** - * directory used for storing data - * - * @var string|false - */ - public static $cacheDir = false; - - /** - * prefix for the storing data - * - * @var string - */ - public static $prefix = 'scssphp_'; - - /** - * force a refresh : 'once' for refreshing the first hit on a cache only, true to never use the cache in this hit - * - * @var bool|string - */ - public static $forceRefresh = false; - - /** - * specifies the number of seconds after which data cached will be seen as 'garbage' and potentially cleaned up - * - * @var int - */ - public static $gcLifetime = 604800; - - /** - * array of already refreshed cache if $forceRefresh==='once' - * - * @var array<string, bool> - */ - protected static $refreshed = []; - - /** - * Constructor - * - * @param array $options - * - * @phpstan-param array{cacheDir?: string, prefix?: string, forceRefresh?: string} $options - */ - public function __construct($options) - { - // check $cacheDir - if (isset($options['cacheDir'])) { - self::$cacheDir = $options['cacheDir']; - } - - if (empty(self::$cacheDir)) { - throw new Exception('cacheDir not set'); - } - - if (isset($options['prefix'])) { - self::$prefix = $options['prefix']; - } - - if (empty(self::$prefix)) { - throw new Exception('prefix not set'); - } - - if (isset($options['forceRefresh'])) { - self::$forceRefresh = $options['forceRefresh']; - } - - self::checkCacheDir(); - } - - /** - * Get the cached result of $operation on $what, - * which is known as dependant from the content of $options - * - * @param string $operation parse, compile... - * @param mixed $what content key (e.g., filename to be treated) - * @param array $options any option that affect the operation result on the content - * @param int|null $lastModified last modified timestamp - * - * @return mixed - * - * @throws \Exception - */ - public function getCache($operation, $what, $options = [], $lastModified = null) - { - $fileCache = self::$cacheDir . self::cacheName($operation, $what, $options); - - if ( - ((self::$forceRefresh === false) || (self::$forceRefresh === 'once' && - isset(self::$refreshed[$fileCache]))) && file_exists($fileCache) - ) { - $cacheTime = filemtime($fileCache); - - if ( - (\is_null($lastModified) || $cacheTime > $lastModified) && - $cacheTime + self::$gcLifetime > time() - ) { - $c = file_get_contents($fileCache); - $c = unserialize($c); - - if (\is_array($c) && isset($c['value'])) { - return $c['value']; - } - } - } - - return null; - } - - /** - * Put in cache the result of $operation on $what, - * which is known as dependant from the content of $options - * - * @param string $operation - * @param mixed $what - * @param mixed $value - * @param array $options - * - * @return void - */ - public function setCache($operation, $what, $value, $options = []) - { - $fileCache = self::$cacheDir . self::cacheName($operation, $what, $options); - - $c = ['value' => $value]; - $c = serialize($c); - - file_put_contents($fileCache, $c); - - if (self::$forceRefresh === 'once') { - self::$refreshed[$fileCache] = true; - } - } - - /** - * Get the cache name for the caching of $operation on $what, - * which is known as dependant from the content of $options - * - * @param string $operation - * @param mixed $what - * @param array $options - * - * @return string - */ - private static function cacheName($operation, $what, $options = []) - { - $t = [ - 'version' => self::CACHE_VERSION, - 'scssphpVersion' => Version::VERSION, - 'operation' => $operation, - 'what' => $what, - 'options' => $options - ]; - - $t = self::$prefix - . sha1(json_encode($t)) - . ".$operation" - . ".scsscache"; - - return $t; - } - - /** - * Check that the cache dir exists and is writeable - * - * @return void - * - * @throws \Exception - */ - public static function checkCacheDir() - { - self::$cacheDir = str_replace('\\', '/', self::$cacheDir); - self::$cacheDir = rtrim(self::$cacheDir, '/') . '/'; - - if (! is_dir(self::$cacheDir)) { - throw new Exception('Cache directory doesn\'t exist: ' . self::$cacheDir); - } - - if (! is_writable(self::$cacheDir)) { - throw new Exception('Cache directory isn\'t writable: ' . self::$cacheDir); - } - } - - /** - * Delete unused cached files - * - * @return void - */ - public static function cleanCache() - { - static $clean = false; - - if ($clean || empty(self::$cacheDir)) { - return; - } - - $clean = true; - - // only remove files with extensions created by SCSSPHP Cache - // css files removed based on the list files - $removeTypes = ['scsscache' => 1]; - - $files = scandir(self::$cacheDir); - - if (! $files) { - return; - } - - $checkTime = time() - self::$gcLifetime; - - foreach ($files as $file) { - // don't delete if the file wasn't created with SCSSPHP Cache - if (strpos($file, self::$prefix) !== 0) { - continue; - } - - $parts = explode('.', $file); - $type = array_pop($parts); - - if (! isset($removeTypes[$type])) { - continue; - } - - $fullPath = self::$cacheDir . $file; - $mtime = filemtime($fullPath); - - // don't delete if it's a relatively new file - if ($mtime > $checkTime) { - continue; - } - - unlink($fullPath); - } - } -} diff --git a/lib/scssphp/scssphp/src/Colors.php b/lib/scssphp/scssphp/src/Colors.php deleted file mode 100644 index 2df39992b..000000000 --- a/lib/scssphp/scssphp/src/Colors.php +++ /dev/null @@ -1,247 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp; - -/** - * CSS Colors - * - * @author Leaf Corcoran <leafot@gmail.com> - * - * @internal - */ -class Colors -{ - /** - * CSS Colors - * - * @see http://www.w3.org/TR/css3-color - * - * @var array<string, string> - */ - protected static $cssColors = [ - 'aliceblue' => '240,248,255', - 'antiquewhite' => '250,235,215', - 'aqua' => '0,255,255', - 'cyan' => '0,255,255', - 'aquamarine' => '127,255,212', - 'azure' => '240,255,255', - 'beige' => '245,245,220', - 'bisque' => '255,228,196', - 'black' => '0,0,0', - 'blanchedalmond' => '255,235,205', - 'blue' => '0,0,255', - 'blueviolet' => '138,43,226', - 'brown' => '165,42,42', - 'burlywood' => '222,184,135', - 'cadetblue' => '95,158,160', - 'chartreuse' => '127,255,0', - 'chocolate' => '210,105,30', - 'coral' => '255,127,80', - 'cornflowerblue' => '100,149,237', - 'cornsilk' => '255,248,220', - 'crimson' => '220,20,60', - 'darkblue' => '0,0,139', - 'darkcyan' => '0,139,139', - 'darkgoldenrod' => '184,134,11', - 'darkgray' => '169,169,169', - 'darkgrey' => '169,169,169', - 'darkgreen' => '0,100,0', - 'darkkhaki' => '189,183,107', - 'darkmagenta' => '139,0,139', - 'darkolivegreen' => '85,107,47', - 'darkorange' => '255,140,0', - 'darkorchid' => '153,50,204', - 'darkred' => '139,0,0', - 'darksalmon' => '233,150,122', - 'darkseagreen' => '143,188,143', - 'darkslateblue' => '72,61,139', - 'darkslategray' => '47,79,79', - 'darkslategrey' => '47,79,79', - 'darkturquoise' => '0,206,209', - 'darkviolet' => '148,0,211', - 'deeppink' => '255,20,147', - 'deepskyblue' => '0,191,255', - 'dimgray' => '105,105,105', - 'dimgrey' => '105,105,105', - 'dodgerblue' => '30,144,255', - 'firebrick' => '178,34,34', - 'floralwhite' => '255,250,240', - 'forestgreen' => '34,139,34', - 'fuchsia' => '255,0,255', - 'magenta' => '255,0,255', - 'gainsboro' => '220,220,220', - 'ghostwhite' => '248,248,255', - 'gold' => '255,215,0', - 'goldenrod' => '218,165,32', - 'gray' => '128,128,128', - 'grey' => '128,128,128', - 'green' => '0,128,0', - 'greenyellow' => '173,255,47', - 'honeydew' => '240,255,240', - 'hotpink' => '255,105,180', - 'indianred' => '205,92,92', - 'indigo' => '75,0,130', - 'ivory' => '255,255,240', - 'khaki' => '240,230,140', - 'lavender' => '230,230,250', - 'lavenderblush' => '255,240,245', - 'lawngreen' => '124,252,0', - 'lemonchiffon' => '255,250,205', - 'lightblue' => '173,216,230', - 'lightcoral' => '240,128,128', - 'lightcyan' => '224,255,255', - 'lightgoldenrodyellow' => '250,250,210', - 'lightgray' => '211,211,211', - 'lightgrey' => '211,211,211', - 'lightgreen' => '144,238,144', - 'lightpink' => '255,182,193', - 'lightsalmon' => '255,160,122', - 'lightseagreen' => '32,178,170', - 'lightskyblue' => '135,206,250', - 'lightslategray' => '119,136,153', - 'lightslategrey' => '119,136,153', - 'lightsteelblue' => '176,196,222', - 'lightyellow' => '255,255,224', - 'lime' => '0,255,0', - 'limegreen' => '50,205,50', - 'linen' => '250,240,230', - 'maroon' => '128,0,0', - 'mediumaquamarine' => '102,205,170', - 'mediumblue' => '0,0,205', - 'mediumorchid' => '186,85,211', - 'mediumpurple' => '147,112,219', - 'mediumseagreen' => '60,179,113', - 'mediumslateblue' => '123,104,238', - 'mediumspringgreen' => '0,250,154', - 'mediumturquoise' => '72,209,204', - 'mediumvioletred' => '199,21,133', - 'midnightblue' => '25,25,112', - 'mintcream' => '245,255,250', - 'mistyrose' => '255,228,225', - 'moccasin' => '255,228,181', - 'navajowhite' => '255,222,173', - 'navy' => '0,0,128', - 'oldlace' => '253,245,230', - 'olive' => '128,128,0', - 'olivedrab' => '107,142,35', - 'orange' => '255,165,0', - 'orangered' => '255,69,0', - 'orchid' => '218,112,214', - 'palegoldenrod' => '238,232,170', - 'palegreen' => '152,251,152', - 'paleturquoise' => '175,238,238', - 'palevioletred' => '219,112,147', - 'papayawhip' => '255,239,213', - 'peachpuff' => '255,218,185', - 'peru' => '205,133,63', - 'pink' => '255,192,203', - 'plum' => '221,160,221', - 'powderblue' => '176,224,230', - 'purple' => '128,0,128', - 'red' => '255,0,0', - 'rosybrown' => '188,143,143', - 'royalblue' => '65,105,225', - 'saddlebrown' => '139,69,19', - 'salmon' => '250,128,114', - 'sandybrown' => '244,164,96', - 'seagreen' => '46,139,87', - 'seashell' => '255,245,238', - 'sienna' => '160,82,45', - 'silver' => '192,192,192', - 'skyblue' => '135,206,235', - 'slateblue' => '106,90,205', - 'slategray' => '112,128,144', - 'slategrey' => '112,128,144', - 'snow' => '255,250,250', - 'springgreen' => '0,255,127', - 'steelblue' => '70,130,180', - 'tan' => '210,180,140', - 'teal' => '0,128,128', - 'thistle' => '216,191,216', - 'tomato' => '255,99,71', - 'turquoise' => '64,224,208', - 'violet' => '238,130,238', - 'wheat' => '245,222,179', - 'white' => '255,255,255', - 'whitesmoke' => '245,245,245', - 'yellow' => '255,255,0', - 'yellowgreen' => '154,205,50', - 'rebeccapurple' => '102,51,153', - 'transparent' => '0,0,0,0', - ]; - - /** - * Convert named color in a [r,g,b[,a]] array - * - * @param string $colorName - * - * @return int[]|null - */ - public static function colorNameToRGBa($colorName) - { - if (\is_string($colorName) && isset(static::$cssColors[$colorName])) { - $rgba = explode(',', static::$cssColors[$colorName]); - - // only case with opacity is transparent, with opacity=0, so we can intval on opacity also - $rgba = array_map('intval', $rgba); - - return $rgba; - } - - return null; - } - - /** - * Reverse conversion : from RGBA to a color name if possible - * - * @param int $r - * @param int $g - * @param int $b - * @param int|float $a - * - * @return string|null - */ - public static function RGBaToColorName($r, $g, $b, $a = 1) - { - static $reverseColorTable = null; - - if (! is_numeric($r) || ! is_numeric($g) || ! is_numeric($b) || ! is_numeric($a)) { - return null; - } - - if ($a < 1) { - return null; - } - - if (\is_null($reverseColorTable)) { - $reverseColorTable = []; - - foreach (static::$cssColors as $name => $rgb_str) { - $rgb_str = explode(',', $rgb_str); - - if ( - \count($rgb_str) == 3 && - ! isset($reverseColorTable[\intval($rgb_str[0])][\intval($rgb_str[1])][\intval($rgb_str[2])]) - ) { - $reverseColorTable[\intval($rgb_str[0])][\intval($rgb_str[1])][\intval($rgb_str[2])] = $name; - } - } - } - - if (isset($reverseColorTable[\intval($r)][\intval($g)][\intval($b)])) { - return $reverseColorTable[\intval($r)][\intval($g)][\intval($b)]; - } - - return null; - } -} diff --git a/lib/scssphp/scssphp/src/CompilationResult.php b/lib/scssphp/scssphp/src/CompilationResult.php deleted file mode 100644 index 36adb0da4..000000000 --- a/lib/scssphp/scssphp/src/CompilationResult.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp; - -class CompilationResult -{ - /** - * @var string - */ - private $css; - - /** - * @var string|null - */ - private $sourceMap; - - /** - * @var string[] - */ - private $includedFiles; - - /** - * @param string $css - * @param string|null $sourceMap - * @param string[] $includedFiles - */ - public function __construct($css, $sourceMap, array $includedFiles) - { - $this->css = $css; - $this->sourceMap = $sourceMap; - $this->includedFiles = $includedFiles; - } - - /** - * @return string - */ - public function getCss() - { - return $this->css; - } - - /** - * @return string[] - */ - public function getIncludedFiles() - { - return $this->includedFiles; - } - - /** - * The sourceMap content, if it was generated - * - * @return null|string - */ - public function getSourceMap() - { - return $this->sourceMap; - } -} diff --git a/lib/scssphp/scssphp/src/Compiler.php b/lib/scssphp/scssphp/src/Compiler.php deleted file mode 100644 index e66cee3dc..000000000 --- a/lib/scssphp/scssphp/src/Compiler.php +++ /dev/null @@ -1,10408 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp; - -use ScssPhp\ScssPhp\Base\Range; -use ScssPhp\ScssPhp\Block\AtRootBlock; -use ScssPhp\ScssPhp\Block\CallableBlock; -use ScssPhp\ScssPhp\Block\DirectiveBlock; -use ScssPhp\ScssPhp\Block\EachBlock; -use ScssPhp\ScssPhp\Block\ElseBlock; -use ScssPhp\ScssPhp\Block\ElseifBlock; -use ScssPhp\ScssPhp\Block\ForBlock; -use ScssPhp\ScssPhp\Block\IfBlock; -use ScssPhp\ScssPhp\Block\MediaBlock; -use ScssPhp\ScssPhp\Block\NestedPropertyBlock; -use ScssPhp\ScssPhp\Block\WhileBlock; -use ScssPhp\ScssPhp\Compiler\CachedResult; -use ScssPhp\ScssPhp\Compiler\Environment; -use ScssPhp\ScssPhp\Exception\CompilerException; -use ScssPhp\ScssPhp\Exception\ParserException; -use ScssPhp\ScssPhp\Exception\SassException; -use ScssPhp\ScssPhp\Exception\SassScriptException; -use ScssPhp\ScssPhp\Formatter\Compressed; -use ScssPhp\ScssPhp\Formatter\Expanded; -use ScssPhp\ScssPhp\Formatter\OutputBlock; -use ScssPhp\ScssPhp\Logger\LoggerInterface; -use ScssPhp\ScssPhp\Logger\StreamLogger; -use ScssPhp\ScssPhp\Node\Number; -use ScssPhp\ScssPhp\SourceMap\SourceMapGenerator; -use ScssPhp\ScssPhp\Util\Path; - -/** - * The scss compiler and parser. - * - * Converting SCSS to CSS is a three stage process. The incoming file is parsed - * by `Parser` into a syntax tree, then it is compiled into another tree - * representing the CSS structure by `Compiler`. The CSS tree is fed into a - * formatter, like `Formatter` which then outputs CSS as a string. - * - * During the first compile, all values are *reduced*, which means that their - * types are brought to the lowest form before being dump as strings. This - * handles math equations, variable dereferences, and the like. - * - * The `compile` function of `Compiler` is the entry point. - * - * In summary: - * - * The `Compiler` class creates an instance of the parser, feeds it SCSS code, - * then transforms the resulting tree to a CSS tree. This class also holds the - * evaluation context, such as all available mixins and variables at any given - * time. - * - * The `Parser` class is only concerned with parsing its input. - * - * The `Formatter` takes a CSS tree, and dumps it to a formatted string, - * handling things like indentation. - */ - -/** - * SCSS compiler - * - * @author Leaf Corcoran <leafot@gmail.com> - * - * @final Extending the Compiler is deprecated - */ -class Compiler -{ - /** - * @deprecated - */ - const LINE_COMMENTS = 1; - /** - * @deprecated - */ - const DEBUG_INFO = 2; - - /** - * @deprecated - */ - const WITH_RULE = 1; - /** - * @deprecated - */ - const WITH_MEDIA = 2; - /** - * @deprecated - */ - const WITH_SUPPORTS = 4; - /** - * @deprecated - */ - const WITH_ALL = 7; - - const SOURCE_MAP_NONE = 0; - const SOURCE_MAP_INLINE = 1; - const SOURCE_MAP_FILE = 2; - - /** - * @var array<string, string> - */ - protected static $operatorNames = [ - '+' => 'add', - '-' => 'sub', - '*' => 'mul', - '/' => 'div', - '%' => 'mod', - - '==' => 'eq', - '!=' => 'neq', - '<' => 'lt', - '>' => 'gt', - - '<=' => 'lte', - '>=' => 'gte', - ]; - - /** - * @var array<string, string> - */ - protected static $namespaces = [ - 'special' => '%', - 'mixin' => '@', - 'function' => '^', - ]; - - public static $true = [Type::T_KEYWORD, 'true']; - public static $false = [Type::T_KEYWORD, 'false']; - /** @deprecated */ - public static $NaN = [Type::T_KEYWORD, 'NaN']; - /** @deprecated */ - public static $Infinity = [Type::T_KEYWORD, 'Infinity']; - public static $null = [Type::T_NULL]; - public static $nullString = [Type::T_STRING, '', []]; - public static $defaultValue = [Type::T_KEYWORD, '']; - public static $selfSelector = [Type::T_SELF]; - public static $emptyList = [Type::T_LIST, '', []]; - public static $emptyMap = [Type::T_MAP, [], []]; - public static $emptyString = [Type::T_STRING, '"', []]; - public static $with = [Type::T_KEYWORD, 'with']; - public static $without = [Type::T_KEYWORD, 'without']; - private static $emptyArgumentList = [Type::T_LIST, '', [], []]; - - /** - * @var array<int, string|callable> - */ - protected $importPaths = []; - /** - * @var array<string, Block> - */ - protected $importCache = []; - - /** - * @var string[] - */ - protected $importedFiles = []; - - /** - * @var array - * @phpstan-var array<string, array{0: callable, 1: string[]|null}> - */ - protected $userFunctions = []; - /** - * @var array<string, mixed> - */ - protected $registeredVars = []; - /** - * @var array<string, bool> - */ - protected $registeredFeatures = [ - 'extend-selector-pseudoclass' => false, - 'at-error' => true, - 'units-level-3' => true, - 'global-variable-shadowing' => false, - ]; - - /** - * @var string|null - */ - protected $encoding = null; - /** - * @var null - * @deprecated - */ - protected $lineNumberStyle = null; - - /** - * @var int|SourceMapGenerator - * @phpstan-var self::SOURCE_MAP_*|SourceMapGenerator - */ - protected $sourceMap = self::SOURCE_MAP_NONE; - - /** - * @var array - * @phpstan-var array{sourceRoot?: string, sourceMapFilename?: string|null, sourceMapURL?: string|null, sourceMapWriteTo?: string|null, outputSourceFiles?: bool, sourceMapRootpath?: string, sourceMapBasepath?: string} - */ - protected $sourceMapOptions = []; - - /** - * @var bool - */ - private $charset = true; - - /** - * @var Formatter - */ - protected $formatter; - - /** - * @var string - * @phpstan-var class-string<Formatter> - */ - private $configuredFormatter = Expanded::class; - - /** - * @var Environment - */ - protected $rootEnv; - /** - * @var OutputBlock|null - */ - protected $rootBlock; - - /** - * @var \ScssPhp\ScssPhp\Compiler\Environment - */ - protected $env; - /** - * @var OutputBlock|null - */ - protected $scope; - /** - * @var Environment|null - */ - protected $storeEnv; - /** - * @var bool|null - * - * @deprecated - */ - protected $charsetSeen; - /** - * @var array<int, string|null> - */ - protected $sourceNames; - - /** - * @var Cache|null - */ - protected $cache; - - /** - * @var bool - */ - protected $cacheCheckImportResolutions = false; - - /** - * @var int - */ - protected $indentLevel; - /** - * @var array[] - */ - protected $extends; - /** - * @var array<string, int[]> - */ - protected $extendsMap; - - /** - * @var array<string, int> - */ - protected $parsedFiles = []; - - /** - * @var Parser|null - */ - protected $parser; - /** - * @var int|null - */ - protected $sourceIndex; - /** - * @var int|null - */ - protected $sourceLine; - /** - * @var int|null - */ - protected $sourceColumn; - /** - * @var bool|null - */ - protected $shouldEvaluate; - /** - * @var null - * @deprecated - */ - protected $ignoreErrors; - /** - * @var bool - */ - protected $ignoreCallStackMessage = false; - - /** - * @var array[] - */ - protected $callStack = []; - - /** - * @var array - * @phpstan-var list<array{currentDir: string|null, path: string, filePath: string}> - */ - private $resolvedImports = []; - - /** - * The directory of the currently processed file - * - * @var string|null - */ - private $currentDirectory; - - /** - * The directory of the input file - * - * @var string - */ - private $rootDirectory; - - /** - * @var bool - */ - private $legacyCwdImportPath = true; - - /** - * @var LoggerInterface - */ - private $logger; - - /** - * @var array<string, bool> - */ - private $warnedChildFunctions = []; - - /** - * Constructor - * - * @param array|null $cacheOptions - * @phpstan-param array{cacheDir?: string, prefix?: string, forceRefresh?: string, checkImportResolutions?: bool}|null $cacheOptions - */ - public function __construct($cacheOptions = null) - { - $this->sourceNames = []; - - if ($cacheOptions) { - $this->cache = new Cache($cacheOptions); - if (!empty($cacheOptions['checkImportResolutions'])) { - $this->cacheCheckImportResolutions = true; - } - } - - $this->logger = new StreamLogger(fopen('php://stderr', 'w'), true); - } - - /** - * Get compiler options - * - * @return array<string, mixed> - * - * @internal - */ - public function getCompileOptions() - { - $options = [ - 'importPaths' => $this->importPaths, - 'registeredVars' => $this->registeredVars, - 'registeredFeatures' => $this->registeredFeatures, - 'encoding' => $this->encoding, - 'sourceMap' => serialize($this->sourceMap), - 'sourceMapOptions' => $this->sourceMapOptions, - 'formatter' => $this->configuredFormatter, - 'legacyImportPath' => $this->legacyCwdImportPath, - ]; - - return $options; - } - - /** - * Sets an alternative logger. - * - * Changing the logger in the middle of the compilation is not - * supported and will result in an undefined behavior. - * - * @param LoggerInterface $logger - * - * @return void - */ - public function setLogger(LoggerInterface $logger) - { - $this->logger = $logger; - } - - /** - * Set an alternative error output stream, for testing purpose only - * - * @param resource $handle - * - * @return void - * - * @deprecated Use {@see setLogger} instead - */ - public function setErrorOuput($handle) - { - @trigger_error('The method "setErrorOuput" is deprecated. Use "setLogger" instead.', E_USER_DEPRECATED); - - $this->logger = new StreamLogger($handle); - } - - /** - * Compile scss - * - * @param string $code - * @param string|null $path - * - * @return string - * - * @throws SassException when the source fails to compile - * - * @deprecated Use {@see compileString} instead. - */ - public function compile($code, $path = null) - { - @trigger_error(sprintf('The "%s" method is deprecated. Use "compileString" instead.', __METHOD__), E_USER_DEPRECATED); - - $result = $this->compileString($code, $path); - - $sourceMap = $result->getSourceMap(); - - if ($sourceMap !== null) { - if ($this->sourceMap instanceof SourceMapGenerator) { - $this->sourceMap->saveMap($sourceMap); - } elseif ($this->sourceMap === self::SOURCE_MAP_FILE) { - $sourceMapGenerator = new SourceMapGenerator($this->sourceMapOptions); - $sourceMapGenerator->saveMap($sourceMap); - } - } - - return $result->getCss(); - } - - /** - * Compile scss - * - * @param string $source - * @param string|null $path - * - * @return CompilationResult - * - * @throws SassException when the source fails to compile - */ - public function compileString($source, $path = null) - { - if ($this->cache) { - $cacheKey = ($path ? $path : '(stdin)') . ':' . md5($source); - $compileOptions = $this->getCompileOptions(); - $cachedResult = $this->cache->getCache('compile', $cacheKey, $compileOptions); - - if ($cachedResult instanceof CachedResult && $this->isFreshCachedResult($cachedResult)) { - return $cachedResult->getResult(); - } - } - - $this->indentLevel = -1; - $this->extends = []; - $this->extendsMap = []; - $this->sourceIndex = null; - $this->sourceLine = null; - $this->sourceColumn = null; - $this->env = null; - $this->scope = null; - $this->storeEnv = null; - $this->shouldEvaluate = null; - $this->ignoreCallStackMessage = false; - $this->parsedFiles = []; - $this->importedFiles = []; - $this->resolvedImports = []; - - if (!\is_null($path) && is_file($path)) { - $path = realpath($path) ?: $path; - $this->currentDirectory = dirname($path); - $this->rootDirectory = $this->currentDirectory; - } else { - $this->currentDirectory = null; - $this->rootDirectory = getcwd(); - } - - try { - $this->parser = $this->parserFactory($path); - $tree = $this->parser->parse($source); - $this->parser = null; - - $this->formatter = new $this->configuredFormatter(); - $this->rootBlock = null; - $this->rootEnv = $this->pushEnv($tree); - - $warnCallback = function ($message, $deprecation) { - $this->logger->warn($message, $deprecation); - }; - $previousWarnCallback = Warn::setCallback($warnCallback); - - try { - $this->injectVariables($this->registeredVars); - $this->compileRoot($tree); - $this->popEnv(); - } finally { - Warn::setCallback($previousWarnCallback); - } - - $sourceMapGenerator = null; - - if ($this->sourceMap) { - if (\is_object($this->sourceMap) && $this->sourceMap instanceof SourceMapGenerator) { - $sourceMapGenerator = $this->sourceMap; - $this->sourceMap = self::SOURCE_MAP_FILE; - } elseif ($this->sourceMap !== self::SOURCE_MAP_NONE) { - $sourceMapGenerator = new SourceMapGenerator($this->sourceMapOptions); - } - } - assert($this->scope !== null); - - $out = $this->formatter->format($this->scope, $sourceMapGenerator); - - $prefix = ''; - - if ($this->charset && strlen($out) !== Util::mbStrlen($out)) { - $prefix = '@charset "UTF-8";' . "\n"; - $out = $prefix . $out; - } - - $sourceMap = null; - - if (! empty($out) && $this->sourceMap && $this->sourceMap !== self::SOURCE_MAP_NONE) { - assert($sourceMapGenerator !== null); - $sourceMap = $sourceMapGenerator->generateJson($prefix); - $sourceMapUrl = null; - - switch ($this->sourceMap) { - case self::SOURCE_MAP_INLINE: - $sourceMapUrl = sprintf('data:application/json,%s', Util::encodeURIComponent($sourceMap)); - break; - - case self::SOURCE_MAP_FILE: - if (isset($this->sourceMapOptions['sourceMapURL'])) { - $sourceMapUrl = $this->sourceMapOptions['sourceMapURL']; - } - break; - } - - if ($sourceMapUrl !== null) { - $out .= sprintf('/*# sourceMappingURL=%s */', $sourceMapUrl); - } - } - } catch (SassScriptException $e) { - throw new CompilerException($this->addLocationToMessage($e->getMessage()), 0, $e); - } - - $includedFiles = []; - - foreach ($this->resolvedImports as $resolvedImport) { - $includedFiles[$resolvedImport['filePath']] = $resolvedImport['filePath']; - } - - $result = new CompilationResult($out, $sourceMap, array_values($includedFiles)); - - if ($this->cache && isset($cacheKey) && isset($compileOptions)) { - $this->cache->setCache('compile', $cacheKey, new CachedResult($result, $this->parsedFiles, $this->resolvedImports), $compileOptions); - } - - // Reset state to free memory - // TODO in 2.0, reset parsedFiles as well when the getter is removed. - $this->resolvedImports = []; - $this->importedFiles = []; - - return $result; - } - - /** - * @param CachedResult $result - * - * @return bool - */ - private function isFreshCachedResult(CachedResult $result) - { - // check if any dependency file changed since the result was compiled - foreach ($result->getParsedFiles() as $file => $mtime) { - if (! is_file($file) || filemtime($file) !== $mtime) { - return false; - } - } - - if ($this->cacheCheckImportResolutions) { - $resolvedImports = []; - - foreach ($result->getResolvedImports() as $import) { - $currentDir = $import['currentDir']; - $path = $import['path']; - // store the check across all the results in memory to avoid multiple findImport() on the same path - // with same context. - // this is happening in a same hit with multiple compilations (especially with big frameworks) - if (empty($resolvedImports[$currentDir][$path])) { - $resolvedImports[$currentDir][$path] = $this->findImport($path, $currentDir); - } - - if ($resolvedImports[$currentDir][$path] !== $import['filePath']) { - return false; - } - } - } - - return true; - } - - /** - * Instantiate parser - * - * @param string|null $path - * - * @return \ScssPhp\ScssPhp\Parser - */ - protected function parserFactory($path) - { - // https://sass-lang.com/documentation/at-rules/import - // CSS files imported by Sass don’t allow any special Sass features. - // In order to make sure authors don’t accidentally write Sass in their CSS, - // all Sass features that aren’t also valid CSS will produce errors. - // Otherwise, the CSS will be rendered as-is. It can even be extended! - $cssOnly = false; - - if ($path !== null && substr($path, -4) === '.css') { - $cssOnly = true; - } - - $parser = new Parser($path, \count($this->sourceNames), $this->encoding, $this->cache, $cssOnly, $this->logger); - - $this->sourceNames[] = $path; - $this->addParsedFile($path); - - return $parser; - } - - /** - * Is self extend? - * - * @param array $target - * @param array $origin - * - * @return bool - */ - protected function isSelfExtend($target, $origin) - { - foreach ($origin as $sel) { - if (\in_array($target, $sel)) { - return true; - } - } - - return false; - } - - /** - * Push extends - * - * @param string[] $target - * @param array $origin - * @param array|null $block - * - * @return void - */ - protected function pushExtends($target, $origin, $block) - { - $i = \count($this->extends); - $this->extends[] = [$target, $origin, $block]; - - foreach ($target as $part) { - if (isset($this->extendsMap[$part])) { - $this->extendsMap[$part][] = $i; - } else { - $this->extendsMap[$part] = [$i]; - } - } - } - - /** - * Make output block - * - * @param string|null $type - * @param string[]|null $selectors - * - * @return \ScssPhp\ScssPhp\Formatter\OutputBlock - */ - protected function makeOutputBlock($type, $selectors = null) - { - $out = new OutputBlock(); - $out->type = $type; - $out->lines = []; - $out->children = []; - $out->parent = $this->scope; - $out->selectors = $selectors; - $out->depth = $this->env->depth; - - if ($this->env->block instanceof Block) { - $out->sourceName = $this->env->block->sourceName; - $out->sourceLine = $this->env->block->sourceLine; - $out->sourceColumn = $this->env->block->sourceColumn; - } else { - $out->sourceName = isset($this->sourceNames[$this->sourceIndex]) ? $this->sourceNames[$this->sourceIndex] : '(stdin)'; - $out->sourceLine = $this->sourceLine; - $out->sourceColumn = $this->sourceColumn; - } - - return $out; - } - - /** - * Compile root - * - * @param \ScssPhp\ScssPhp\Block $rootBlock - * - * @return void - */ - protected function compileRoot(Block $rootBlock) - { - $this->rootBlock = $this->scope = $this->makeOutputBlock(Type::T_ROOT); - - $this->compileChildrenNoReturn($rootBlock->children, $this->scope); - assert($this->scope !== null); - $this->flattenSelectors($this->scope); - $this->missingSelectors(); - } - - /** - * Report missing selectors - * - * @return void - */ - protected function missingSelectors() - { - foreach ($this->extends as $extend) { - if (isset($extend[3])) { - continue; - } - - list($target, $origin, $block) = $extend; - - // ignore if !optional - if ($block[2]) { - continue; - } - - $target = implode(' ', $target); - $origin = $this->collapseSelectors($origin); - - $this->sourceLine = $block[Parser::SOURCE_LINE]; - throw $this->error("\"$origin\" failed to @extend \"$target\". The selector \"$target\" was not found."); - } - } - - /** - * Flatten selectors - * - * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block - * @param string $parentKey - * - * @return void - */ - protected function flattenSelectors(OutputBlock $block, $parentKey = null) - { - if ($block->selectors) { - $selectors = []; - - foreach ($block->selectors as $s) { - $selectors[] = $s; - - if (! \is_array($s)) { - continue; - } - - // check extends - if (! empty($this->extendsMap)) { - $this->matchExtends($s, $selectors); - - // remove duplicates - array_walk($selectors, function (&$value) { - $value = serialize($value); - }); - - $selectors = array_unique($selectors); - - array_walk($selectors, function (&$value) { - $value = unserialize($value); - }); - } - } - - $block->selectors = []; - $placeholderSelector = false; - - foreach ($selectors as $selector) { - if ($this->hasSelectorPlaceholder($selector)) { - $placeholderSelector = true; - continue; - } - - $block->selectors[] = $this->compileSelector($selector); - } - - if ($placeholderSelector && 0 === \count($block->selectors) && null !== $parentKey) { - assert($block->parent !== null); - unset($block->parent->children[$parentKey]); - - return; - } - } - - foreach ($block->children as $key => $child) { - $this->flattenSelectors($child, $key); - } - } - - /** - * Glue parts of :not( or :nth-child( ... that are in general split in selectors parts - * - * @param array $parts - * - * @return array - */ - protected function glueFunctionSelectors($parts) - { - $new = []; - - foreach ($parts as $part) { - if (\is_array($part)) { - $part = $this->glueFunctionSelectors($part); - $new[] = $part; - } else { - // a selector part finishing with a ) is the last part of a :not( or :nth-child( - // and need to be joined to this - if ( - \count($new) && \is_string($new[\count($new) - 1]) && - \strlen($part) && substr($part, -1) === ')' && strpos($part, '(') === false - ) { - while (\count($new) > 1 && substr($new[\count($new) - 1], -1) !== '(') { - $part = array_pop($new) . $part; - } - $new[\count($new) - 1] .= $part; - } else { - $new[] = $part; - } - } - } - - return $new; - } - - /** - * Match extends - * - * @param array $selector - * @param array $out - * @param int $from - * @param bool $initial - * - * @return void - */ - protected function matchExtends($selector, &$out, $from = 0, $initial = true) - { - static $partsPile = []; - $selector = $this->glueFunctionSelectors($selector); - - if (\count($selector) == 1 && \in_array(reset($selector), $partsPile)) { - return; - } - - $outRecurs = []; - - foreach ($selector as $i => $part) { - if ($i < $from) { - continue; - } - - // check that we are not building an infinite loop of extensions - // if the new part is just including a previous part don't try to extend anymore - if (\count($part) > 1) { - foreach ($partsPile as $previousPart) { - if (! \count(array_diff($previousPart, $part))) { - continue 2; - } - } - } - - $partsPile[] = $part; - - if ($this->matchExtendsSingle($part, $origin, $initial)) { - $after = \array_slice($selector, $i + 1); - $before = \array_slice($selector, 0, $i); - list($before, $nonBreakableBefore) = $this->extractRelationshipFromFragment($before); - - foreach ($origin as $new) { - $k = 0; - - // remove shared parts - if (\count($new) > 1) { - while ($k < $i && isset($new[$k]) && $selector[$k] === $new[$k]) { - $k++; - } - } - - if (\count($nonBreakableBefore) && $k === \count($new)) { - $k--; - } - - $replacement = []; - $tempReplacement = $k > 0 ? \array_slice($new, $k) : $new; - - for ($l = \count($tempReplacement) - 1; $l >= 0; $l--) { - $slice = []; - - foreach ($tempReplacement[$l] as $chunk) { - if (! \in_array($chunk, $slice)) { - $slice[] = $chunk; - } - } - - array_unshift($replacement, $slice); - - if (! $this->isImmediateRelationshipCombinator(end($slice))) { - break; - } - } - - $afterBefore = $l != 0 ? \array_slice($tempReplacement, 0, $l) : []; - - // Merge shared direct relationships. - $mergedBefore = $this->mergeDirectRelationships($afterBefore, $nonBreakableBefore); - - $result = array_merge( - $before, - $mergedBefore, - $replacement, - $after - ); - - if ($result === $selector) { - continue; - } - - $this->pushOrMergeExtentedSelector($out, $result); - - // recursively check for more matches - $startRecurseFrom = \count($before) + min(\count($nonBreakableBefore), \count($mergedBefore)); - - if (\count($origin) > 1) { - $this->matchExtends($result, $out, $startRecurseFrom, false); - } else { - $this->matchExtends($result, $outRecurs, $startRecurseFrom, false); - } - - // selector sequence merging - if (! empty($before) && \count($new) > 1) { - $preSharedParts = $k > 0 ? \array_slice($before, 0, $k) : []; - $postSharedParts = $k > 0 ? \array_slice($before, $k) : $before; - - list($betweenSharedParts, $nonBreakabl2) = $this->extractRelationshipFromFragment($afterBefore); - - $result2 = array_merge( - $preSharedParts, - $betweenSharedParts, - $postSharedParts, - $nonBreakabl2, - $nonBreakableBefore, - $replacement, - $after - ); - - $this->pushOrMergeExtentedSelector($out, $result2); - } - } - } - array_pop($partsPile); - } - - while (\count($outRecurs)) { - $result = array_shift($outRecurs); - $this->pushOrMergeExtentedSelector($out, $result); - } - } - - /** - * Test a part for being a pseudo selector - * - * @param string $part - * @param array $matches - * - * @return bool - */ - protected function isPseudoSelector($part, &$matches) - { - if ( - strpos($part, ':') === 0 && - preg_match(",^::?([\w-]+)\((.+)\)$,", $part, $matches) - ) { - return true; - } - - return false; - } - - /** - * Push extended selector except if - * - this is a pseudo selector - * - same as previous - * - in a white list - * in this case we merge the pseudo selector content - * - * @param array $out - * @param array $extended - * - * @return void - */ - protected function pushOrMergeExtentedSelector(&$out, $extended) - { - if (\count($out) && \count($extended) === 1 && \count(reset($extended)) === 1) { - $single = reset($extended); - $part = reset($single); - - if ( - $this->isPseudoSelector($part, $matchesExtended) && - \in_array($matchesExtended[1], [ 'slotted' ]) - ) { - $prev = end($out); - $prev = $this->glueFunctionSelectors($prev); - - if (\count($prev) === 1 && \count(reset($prev)) === 1) { - $single = reset($prev); - $part = reset($single); - - if ( - $this->isPseudoSelector($part, $matchesPrev) && - $matchesPrev[1] === $matchesExtended[1] - ) { - $extended = explode($matchesExtended[1] . '(', $matchesExtended[0], 2); - $extended[1] = $matchesPrev[2] . ', ' . $extended[1]; - $extended = implode($matchesExtended[1] . '(', $extended); - $extended = [ [ $extended ]]; - array_pop($out); - } - } - } - } - $out[] = $extended; - } - - /** - * Match extends single - * - * @param array $rawSingle - * @param array $outOrigin - * @param bool $initial - * - * @return bool - */ - protected function matchExtendsSingle($rawSingle, &$outOrigin, $initial = true) - { - $counts = []; - $single = []; - - // simple usual cases, no need to do the whole trick - if (\in_array($rawSingle, [['>'],['+'],['~']])) { - return false; - } - - foreach ($rawSingle as $part) { - // matches Number - if (! \is_string($part)) { - return false; - } - - if (! preg_match('/^[\[.:#%]/', $part) && \count($single)) { - $single[\count($single) - 1] .= $part; - } else { - $single[] = $part; - } - } - - $extendingDecoratedTag = false; - - if (\count($single) > 1) { - $matches = null; - $extendingDecoratedTag = preg_match('/^[a-z0-9]+$/i', $single[0], $matches) ? $matches[0] : false; - } - - $outOrigin = []; - $found = false; - - foreach ($single as $k => $part) { - if (isset($this->extendsMap[$part])) { - foreach ($this->extendsMap[$part] as $idx) { - $counts[$idx] = isset($counts[$idx]) ? $counts[$idx] + 1 : 1; - } - } - - if ( - $initial && - $this->isPseudoSelector($part, $matches) && - ! \in_array($matches[1], [ 'not' ]) - ) { - $buffer = $matches[2]; - $parser = $this->parserFactory(__METHOD__); - - if ($parser->parseSelector($buffer, $subSelectors, false)) { - foreach ($subSelectors as $ksub => $subSelector) { - $subExtended = []; - $this->matchExtends($subSelector, $subExtended, 0, false); - - if ($subExtended) { - $subSelectorsExtended = $subSelectors; - $subSelectorsExtended[$ksub] = $subExtended; - - foreach ($subSelectorsExtended as $ksse => $sse) { - $subSelectorsExtended[$ksse] = $this->collapseSelectors($sse); - } - - $subSelectorsExtended = implode(', ', $subSelectorsExtended); - $singleExtended = $single; - $singleExtended[$k] = str_replace('(' . $buffer . ')', "($subSelectorsExtended)", $part); - $outOrigin[] = [ $singleExtended ]; - $found = true; - } - } - } - } - } - - foreach ($counts as $idx => $count) { - list($target, $origin, /* $block */) = $this->extends[$idx]; - - $origin = $this->glueFunctionSelectors($origin); - - // check count - if ($count !== \count($target)) { - continue; - } - - $this->extends[$idx][3] = true; - - $rem = array_diff($single, $target); - - foreach ($origin as $j => $new) { - // prevent infinite loop when target extends itself - if ($this->isSelfExtend($single, $origin) && ! $initial) { - return false; - } - - $replacement = end($new); - - // Extending a decorated tag with another tag is not possible. - if ( - $extendingDecoratedTag && $replacement[0] != $extendingDecoratedTag && - preg_match('/^[a-z0-9]+$/i', $replacement[0]) - ) { - unset($origin[$j]); - continue; - } - - $combined = $this->combineSelectorSingle($replacement, $rem); - - if (\count(array_diff($combined, $origin[$j][\count($origin[$j]) - 1]))) { - $origin[$j][\count($origin[$j]) - 1] = $combined; - } - } - - $outOrigin = array_merge($outOrigin, $origin); - - $found = true; - } - - return $found; - } - - /** - * Extract a relationship from the fragment. - * - * When extracting the last portion of a selector we will be left with a - * fragment which may end with a direction relationship combinator. This - * method will extract the relationship fragment and return it along side - * the rest. - * - * @param array $fragment The selector fragment maybe ending with a direction relationship combinator. - * - * @return array The selector without the relationship fragment if any, the relationship fragment. - */ - protected function extractRelationshipFromFragment(array $fragment) - { - $parents = []; - $children = []; - - $j = $i = \count($fragment); - - for (;;) { - $children = $j != $i ? \array_slice($fragment, $j, $i - $j) : []; - $parents = \array_slice($fragment, 0, $j); - $slice = end($parents); - - if (empty($slice) || ! $this->isImmediateRelationshipCombinator($slice[0])) { - break; - } - - $j -= 2; - } - - return [$parents, $children]; - } - - /** - * Combine selector single - * - * @param array $base - * @param array $other - * - * @return array - */ - protected function combineSelectorSingle($base, $other) - { - $tag = []; - $out = []; - $wasTag = false; - $pseudo = []; - - while (\count($other) && strpos(end($other), ':') === 0) { - array_unshift($pseudo, array_pop($other)); - } - - foreach ([array_reverse($base), array_reverse($other)] as $single) { - $rang = count($single); - - foreach ($single as $part) { - if (preg_match('/^[\[:]/', $part)) { - $out[] = $part; - $wasTag = false; - } elseif (preg_match('/^[\.#]/', $part)) { - array_unshift($out, $part); - $wasTag = false; - } elseif (preg_match('/^[^_-]/', $part) && $rang === 1) { - $tag[] = $part; - $wasTag = true; - } elseif ($wasTag) { - $tag[\count($tag) - 1] .= $part; - } else { - array_unshift($out, $part); - } - $rang--; - } - } - - if (\count($tag)) { - array_unshift($out, $tag[0]); - } - - while (\count($pseudo)) { - $out[] = array_shift($pseudo); - } - - return $out; - } - - /** - * Compile media - * - * @param \ScssPhp\ScssPhp\Block $media - * - * @return void - */ - protected function compileMedia(Block $media) - { - assert($media instanceof MediaBlock); - $this->pushEnv($media); - - $mediaQueries = $this->compileMediaQuery($this->multiplyMedia($this->env)); - - if (! empty($mediaQueries)) { - assert($this->scope !== null); - $previousScope = $this->scope; - $parentScope = $this->mediaParent($this->scope); - - foreach ($mediaQueries as $mediaQuery) { - $this->scope = $this->makeOutputBlock(Type::T_MEDIA, [$mediaQuery]); - - $parentScope->children[] = $this->scope; - $parentScope = $this->scope; - } - - // top level properties in a media cause it to be wrapped - $needsWrap = false; - - foreach ($media->children as $child) { - $type = $child[0]; - - if ( - $type !== Type::T_BLOCK && - $type !== Type::T_MEDIA && - $type !== Type::T_DIRECTIVE && - $type !== Type::T_IMPORT - ) { - $needsWrap = true; - break; - } - } - - if ($needsWrap) { - $wrapped = new Block(); - $wrapped->sourceName = $media->sourceName; - $wrapped->sourceIndex = $media->sourceIndex; - $wrapped->sourceLine = $media->sourceLine; - $wrapped->sourceColumn = $media->sourceColumn; - $wrapped->selectors = []; - $wrapped->comments = []; - $wrapped->parent = $media; - $wrapped->children = $media->children; - - $media->children = [[Type::T_BLOCK, $wrapped]]; - } - - $this->compileChildrenNoReturn($media->children, $this->scope); - - $this->scope = $previousScope; - } - - $this->popEnv(); - } - - /** - * Media parent - * - * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $scope - * - * @return \ScssPhp\ScssPhp\Formatter\OutputBlock - */ - protected function mediaParent(OutputBlock $scope) - { - while (! empty($scope->parent)) { - if (! empty($scope->type) && $scope->type !== Type::T_MEDIA) { - break; - } - - $scope = $scope->parent; - } - - return $scope; - } - - /** - * Compile directive - * - * @param DirectiveBlock|array $directive - * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out - * - * @return void - */ - protected function compileDirective($directive, OutputBlock $out) - { - if (\is_array($directive)) { - $directiveName = $this->compileDirectiveName($directive[0]); - $s = '@' . $directiveName; - - if (! empty($directive[1])) { - $s .= ' ' . $this->compileValue($directive[1]); - } - // sass-spec compliance on newline after directives, a bit tricky :/ - $appendNewLine = (! empty($directive[2]) || strpos($s, "\n")) ? "\n" : ""; - if (\is_array($directive[0]) && empty($directive[1])) { - $appendNewLine = "\n"; - } - - if (empty($directive[3])) { - $this->appendRootDirective($s . ';' . $appendNewLine, $out, [Type::T_COMMENT, Type::T_DIRECTIVE]); - } else { - $this->appendOutputLine($out, Type::T_DIRECTIVE, $s . ';'); - } - } else { - $directive->name = $this->compileDirectiveName($directive->name); - $s = '@' . $directive->name; - - if (! empty($directive->value)) { - $s .= ' ' . $this->compileValue($directive->value); - } - - if ($directive->name === 'keyframes' || substr($directive->name, -10) === '-keyframes') { - $this->compileKeyframeBlock($directive, [$s]); - } else { - $this->compileNestedBlock($directive, [$s]); - } - } - } - - /** - * directive names can include some interpolation - * - * @param string|array $directiveName - * @return string - * @throws CompilerException - */ - protected function compileDirectiveName($directiveName) - { - if (is_string($directiveName)) { - return $directiveName; - } - - return $this->compileValue($directiveName); - } - - /** - * Compile at-root - * - * @param \ScssPhp\ScssPhp\Block $block - * - * @return void - */ - protected function compileAtRoot(Block $block) - { - assert($block instanceof AtRootBlock); - $env = $this->pushEnv($block); - $envs = $this->compactEnv($env); - list($with, $without) = $this->compileWith(isset($block->with) ? $block->with : null); - - // wrap inline selector - if ($block->selector) { - $wrapped = new Block(); - $wrapped->sourceName = $block->sourceName; - $wrapped->sourceIndex = $block->sourceIndex; - $wrapped->sourceLine = $block->sourceLine; - $wrapped->sourceColumn = $block->sourceColumn; - $wrapped->selectors = $block->selector; - $wrapped->comments = []; - $wrapped->parent = $block; - $wrapped->children = $block->children; - $wrapped->selfParent = $block->selfParent; - - $block->children = [[Type::T_BLOCK, $wrapped]]; - $block->selector = null; - } - - $selfParent = $block->selfParent; - assert($selfParent !== null, 'at-root blocks must have a selfParent set.'); - - if ( - ! $selfParent->selectors && - isset($block->parent) && - isset($block->parent->selectors) && $block->parent->selectors - ) { - $selfParent = $block->parent; - } - - $this->env = $this->filterWithWithout($envs, $with, $without); - - assert($this->scope !== null); - $saveScope = $this->scope; - $this->scope = $this->filterScopeWithWithout($saveScope, $with, $without); - - // propagate selfParent to the children where they still can be useful - $this->compileChildrenNoReturn($block->children, $this->scope, $selfParent); - - assert($this->scope !== null); - $this->completeScope($this->scope, $saveScope); - $this->scope = $saveScope; - $this->env = $this->extractEnv($envs); - - $this->popEnv(); - } - - /** - * Filter at-root scope depending on with/without option - * - * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $scope - * @param array $with - * @param array $without - * - * @return OutputBlock - */ - protected function filterScopeWithWithout($scope, $with, $without) - { - $filteredScopes = []; - $childStash = []; - - if ($scope->type === Type::T_ROOT) { - return $scope; - } - assert($this->rootBlock !== null); - - // start from the root - while ($scope->parent && $scope->parent->type !== Type::T_ROOT) { - array_unshift($childStash, $scope); - $scope = $scope->parent; - } - - for (;;) { - if (! $scope) { - break; - } - - if ($this->isWith($scope, $with, $without)) { - $s = clone $scope; - $s->children = []; - $s->lines = []; - $s->parent = null; - - if ($s->type !== Type::T_MEDIA && $s->type !== Type::T_DIRECTIVE) { - $s->selectors = []; - } - - $filteredScopes[] = $s; - } - - if (\count($childStash)) { - $scope = array_shift($childStash); - } elseif ($scope->children) { - $scope = end($scope->children); - } else { - $scope = null; - } - } - - if (! \count($filteredScopes)) { - return $this->rootBlock; - } - - $newScope = array_shift($filteredScopes); - $newScope->parent = $this->rootBlock; - - $this->rootBlock->children[] = $newScope; - - $p = &$newScope; - - while (\count($filteredScopes)) { - $s = array_shift($filteredScopes); - $s->parent = $p; - $p->children[] = $s; - $newScope = &$p->children[0]; - $p = &$p->children[0]; - } - - return $newScope; - } - - /** - * found missing selector from a at-root compilation in the previous scope - * (if at-root is just enclosing a property, the selector is in the parent tree) - * - * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $scope - * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $previousScope - * - * @return OutputBlock - */ - protected function completeScope($scope, $previousScope) - { - if (! $scope->type && ! $scope->selectors && \count($scope->lines)) { - $scope->selectors = $this->findScopeSelectors($previousScope, $scope->depth); - } - - if ($scope->children) { - foreach ($scope->children as $k => $c) { - $scope->children[$k] = $this->completeScope($c, $previousScope); - } - } - - return $scope; - } - - /** - * Find a selector by the depth node in the scope - * - * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $scope - * @param int $depth - * - * @return array - */ - protected function findScopeSelectors($scope, $depth) - { - if ($scope->depth === $depth && $scope->selectors) { - return $scope->selectors; - } - - if ($scope->children) { - foreach (array_reverse($scope->children) as $c) { - if ($s = $this->findScopeSelectors($c, $depth)) { - return $s; - } - } - } - - return []; - } - - /** - * Compile @at-root's with: inclusion / without: exclusion into 2 lists uses to filter scope/env later - * - * @param array|null $withCondition - * - * @return array - * - * @phpstan-return array{array<string, bool>, array<string, bool>} - */ - protected function compileWith($withCondition) - { - // just compile what we have in 2 lists - $with = []; - $without = ['rule' => true]; - - if ($withCondition) { - if ($withCondition[0] === Type::T_INTERPOLATE) { - $w = $this->compileValue($withCondition); - - $buffer = "($w)"; - $parser = $this->parserFactory(__METHOD__); - - if ($parser->parseValue($buffer, $reParsedWith)) { - $withCondition = $reParsedWith; - } - } - - $withConfig = $this->mapGet($withCondition, static::$with); - if ($withConfig !== null) { - $without = []; // cancel the default - $list = $this->coerceList($withConfig); - - foreach ($list[2] as $item) { - $keyword = $this->compileStringContent($this->coerceString($item)); - - $with[$keyword] = true; - } - } - - $withoutConfig = $this->mapGet($withCondition, static::$without); - if ($withoutConfig !== null) { - $without = []; // cancel the default - $list = $this->coerceList($withoutConfig); - - foreach ($list[2] as $item) { - $keyword = $this->compileStringContent($this->coerceString($item)); - - $without[$keyword] = true; - } - } - } - - return [$with, $without]; - } - - /** - * Filter env stack - * - * @param Environment[] $envs - * @param array $with - * @param array $without - * - * @return Environment - * - * @phpstan-param non-empty-array<Environment> $envs - */ - protected function filterWithWithout($envs, $with, $without) - { - $filtered = []; - - foreach ($envs as $e) { - if ($e->block && ! $this->isWith($e->block, $with, $without)) { - $ec = clone $e; - $ec->block = null; - $ec->selectors = []; - - $filtered[] = $ec; - } else { - $filtered[] = $e; - } - } - - return $this->extractEnv($filtered); - } - - /** - * Filter WITH rules - * - * @param \ScssPhp\ScssPhp\Block|\ScssPhp\ScssPhp\Formatter\OutputBlock $block - * @param array $with - * @param array $without - * - * @return bool - */ - protected function isWith($block, $with, $without) - { - if (isset($block->type)) { - if ($block->type === Type::T_MEDIA) { - return $this->testWithWithout('media', $with, $without); - } - - if ($block->type === Type::T_DIRECTIVE) { - assert($block instanceof DirectiveBlock || $block instanceof OutputBlock); - if (isset($block->name)) { - return $this->testWithWithout($this->compileDirectiveName($block->name), $with, $without); - } elseif (isset($block->selectors) && preg_match(',@(\w+),ims', json_encode($block->selectors), $m)) { - return $this->testWithWithout($m[1], $with, $without); - } else { - return $this->testWithWithout('???', $with, $without); - } - } - } elseif (isset($block->selectors)) { - // a selector starting with number is a keyframe rule - if (\count($block->selectors)) { - $s = reset($block->selectors); - - while (\is_array($s)) { - $s = reset($s); - } - - if (\is_object($s) && $s instanceof Number) { - return $this->testWithWithout('keyframes', $with, $without); - } - } - - return $this->testWithWithout('rule', $with, $without); - } - - return true; - } - - /** - * Test a single type of block against with/without lists - * - * @param string $what - * @param array $with - * @param array $without - * - * @return bool - * true if the block should be kept, false to reject - */ - protected function testWithWithout($what, $with, $without) - { - // if without, reject only if in the list (or 'all' is in the list) - if (\count($without)) { - return (isset($without[$what]) || isset($without['all'])) ? false : true; - } - - // otherwise reject all what is not in the with list - return (isset($with[$what]) || isset($with['all'])) ? true : false; - } - - - /** - * Compile keyframe block - * - * @param \ScssPhp\ScssPhp\Block $block - * @param string[] $selectors - * - * @return void - */ - protected function compileKeyframeBlock(Block $block, $selectors) - { - $env = $this->pushEnv($block); - - $envs = $this->compactEnv($env); - - $this->env = $this->extractEnv(array_filter($envs, function (Environment $e) { - return ! isset($e->block->selectors); - })); - - $this->scope = $this->makeOutputBlock($block->type, $selectors); - $this->scope->depth = 1; - assert($this->scope->parent !== null); - $this->scope->parent->children[] = $this->scope; - - $this->compileChildrenNoReturn($block->children, $this->scope); - - assert($this->scope !== null); - $this->scope = $this->scope->parent; - $this->env = $this->extractEnv($envs); - - $this->popEnv(); - } - - /** - * Compile nested properties lines - * - * @param \ScssPhp\ScssPhp\Block $block - * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out - * - * @return void - */ - protected function compileNestedPropertiesBlock(Block $block, OutputBlock $out) - { - assert($block instanceof NestedPropertyBlock); - $prefix = $this->compileValue($block->prefix) . '-'; - - $nested = $this->makeOutputBlock($block->type); - $nested->parent = $out; - - if ($block->hasValue) { - $nested->depth = $out->depth + 1; - } - - $out->children[] = $nested; - - foreach ($block->children as $child) { - switch ($child[0]) { - case Type::T_ASSIGN: - array_unshift($child[1][2], $prefix); - break; - - case Type::T_NESTED_PROPERTY: - assert($child[1] instanceof NestedPropertyBlock); - array_unshift($child[1]->prefix[2], $prefix); - break; - } - - $this->compileChild($child, $nested); - } - } - - /** - * Compile nested block - * - * @param \ScssPhp\ScssPhp\Block $block - * @param string[] $selectors - * - * @return void - */ - protected function compileNestedBlock(Block $block, $selectors) - { - $this->pushEnv($block); - - $this->scope = $this->makeOutputBlock($block->type, $selectors); - assert($this->scope->parent !== null); - $this->scope->parent->children[] = $this->scope; - - // wrap assign children in a block - // except for @font-face - if (!$block instanceof DirectiveBlock || $this->compileDirectiveName($block->name) !== 'font-face') { - // need wrapping? - $needWrapping = false; - - foreach ($block->children as $child) { - if ($child[0] === Type::T_ASSIGN) { - $needWrapping = true; - break; - } - } - - if ($needWrapping) { - $wrapped = new Block(); - $wrapped->sourceName = $block->sourceName; - $wrapped->sourceIndex = $block->sourceIndex; - $wrapped->sourceLine = $block->sourceLine; - $wrapped->sourceColumn = $block->sourceColumn; - $wrapped->selectors = []; - $wrapped->comments = []; - $wrapped->parent = $block; - $wrapped->children = $block->children; - $wrapped->selfParent = $block->selfParent; - - $block->children = [[Type::T_BLOCK, $wrapped]]; - } - } - - $this->compileChildrenNoReturn($block->children, $this->scope); - - assert($this->scope !== null); - $this->scope = $this->scope->parent; - - $this->popEnv(); - } - - /** - * Recursively compiles a block. - * - * A block is analogous to a CSS block in most cases. A single SCSS document - * is encapsulated in a block when parsed, but it does not have parent tags - * so all of its children appear on the root level when compiled. - * - * Blocks are made up of selectors and children. - * - * The children of a block are just all the blocks that are defined within. - * - * Compiling the block involves pushing a fresh environment on the stack, - * and iterating through the props, compiling each one. - * - * @see Compiler::compileChild() - * - * @param \ScssPhp\ScssPhp\Block $block - * - * @return void - */ - protected function compileBlock(Block $block) - { - $env = $this->pushEnv($block); - assert($block->selectors !== null); - $env->selectors = $this->evalSelectors($block->selectors); - - $out = $this->makeOutputBlock(null); - - assert($this->scope !== null); - $this->scope->children[] = $out; - - if (\count($block->children)) { - $out->selectors = $this->multiplySelectors($env, $block->selfParent); - - // propagate selfParent to the children where they still can be useful - $selfParentSelectors = null; - - if (isset($block->selfParent->selectors)) { - $selfParentSelectors = $block->selfParent->selectors; - $block->selfParent->selectors = $out->selectors; - } - - $this->compileChildrenNoReturn($block->children, $out, $block->selfParent); - - // and revert for the following children of the same block - if ($selfParentSelectors) { - assert($block->selfParent !== null); - $block->selfParent->selectors = $selfParentSelectors; - } - } - - $this->popEnv(); - } - - - /** - * Compile the value of a comment that can have interpolation - * - * @param array $value - * @param bool $pushEnv - * - * @return string - */ - protected function compileCommentValue($value, $pushEnv = false) - { - $c = $value[1]; - - if (isset($value[2])) { - if ($pushEnv) { - $this->pushEnv(); - } - - try { - $c = $this->compileValue($value[2]); - } catch (SassScriptException $e) { - $this->logger->warn('Ignoring interpolation errors in multiline comments is deprecated and will be removed in ScssPhp 2.0. ' . $this->addLocationToMessage($e->getMessage()), true); - // ignore error in comment compilation which are only interpolation - } catch (SassException $e) { - $this->logger->warn('Ignoring interpolation errors in multiline comments is deprecated and will be removed in ScssPhp 2.0. ' . $e->getMessage(), true); - // ignore error in comment compilation which are only interpolation - } - - if ($pushEnv) { - $this->popEnv(); - } - } - - return $c; - } - - /** - * Compile root level comment - * - * @param array $block - * - * @return void - */ - protected function compileComment($block) - { - $out = $this->makeOutputBlock(Type::T_COMMENT); - $out->lines[] = $this->compileCommentValue($block, true); - - assert($this->scope !== null); - $this->scope->children[] = $out; - } - - /** - * Evaluate selectors - * - * @param array $selectors - * - * @return array - */ - protected function evalSelectors($selectors) - { - $this->shouldEvaluate = false; - - $evaluatedSelectors = []; - foreach ($selectors as $selector) { - $evaluatedSelectors[] = $this->evalSelector($selector); - } - $selectors = $evaluatedSelectors; - - // after evaluating interpolates, we might need a second pass - if ($this->shouldEvaluate) { - $selectors = $this->replaceSelfSelector($selectors, '&'); - $buffer = $this->collapseSelectors($selectors); - $parser = $this->parserFactory(__METHOD__); - - try { - $isValid = $parser->parseSelector($buffer, $newSelectors, true); - } catch (ParserException $e) { - throw $this->error($e->getMessage()); - } - - if ($isValid) { - $selectors = array_map([$this, 'evalSelector'], $newSelectors); - } - } - - return $selectors; - } - - /** - * Evaluate selector - * - * @param array $selector - * - * @return array - * - * @phpstan-impure - */ - protected function evalSelector($selector) - { - return array_map([$this, 'evalSelectorPart'], $selector); - } - - /** - * Evaluate selector part; replaces all the interpolates, stripping quotes - * - * @param array $part - * - * @return array - * - * @phpstan-impure - */ - protected function evalSelectorPart($part) - { - foreach ($part as &$p) { - if (\is_array($p) && ($p[0] === Type::T_INTERPOLATE || $p[0] === Type::T_STRING)) { - $p = $this->compileValue($p); - - // force re-evaluation if self char or non standard char - if (preg_match(',[^\w-],', $p)) { - $this->shouldEvaluate = true; - } - } elseif ( - \is_string($p) && \strlen($p) >= 2 && - ($p[0] === '"' || $p[0] === "'") && - substr($p, -1) === $p[0] - ) { - $p = substr($p, 1, -1); - } - } - - return $this->flattenSelectorSingle($part); - } - - /** - * Collapse selectors - * - * @param array $selectors - * - * @return string - */ - protected function collapseSelectors($selectors) - { - $parts = []; - - foreach ($selectors as $selector) { - $output = []; - - foreach ($selector as $node) { - $compound = ''; - - array_walk_recursive( - $node, - function ($value, $key) use (&$compound) { - $compound .= $value; - } - ); - - $output[] = $compound; - } - - $parts[] = implode(' ', $output); - } - - return implode(', ', $parts); - } - - /** - * Collapse selectors - * - * @param array $selectors - * - * @return array - */ - private function collapseSelectorsAsList($selectors) - { - $parts = []; - - foreach ($selectors as $selector) { - $output = []; - $glueNext = false; - - foreach ($selector as $node) { - $compound = ''; - - array_walk_recursive( - $node, - function ($value, $key) use (&$compound) { - $compound .= $value; - } - ); - - if ($this->isImmediateRelationshipCombinator($compound)) { - if (\count($output)) { - $output[\count($output) - 1] .= ' ' . $compound; - } else { - $output[] = $compound; - } - - $glueNext = true; - } elseif ($glueNext) { - $output[\count($output) - 1] .= ' ' . $compound; - $glueNext = false; - } else { - $output[] = $compound; - } - } - - foreach ($output as &$o) { - $o = [Type::T_STRING, '', [$o]]; - } - - $parts[] = [Type::T_LIST, ' ', $output]; - } - - return [Type::T_LIST, ',', $parts]; - } - - /** - * Parse down the selector and revert [self] to "&" before a reparsing - * - * @param array $selectors - * @param string|null $replace - * - * @return array - */ - protected function replaceSelfSelector($selectors, $replace = null) - { - foreach ($selectors as &$part) { - if (\is_array($part)) { - if ($part === [Type::T_SELF]) { - if (\is_null($replace)) { - $replace = $this->reduce([Type::T_SELF]); - $replace = $this->compileValue($replace); - } - $part = $replace; - } else { - $part = $this->replaceSelfSelector($part, $replace); - } - } - } - - return $selectors; - } - - /** - * Flatten selector single; joins together .classes and #ids - * - * @param array $single - * - * @return array - */ - protected function flattenSelectorSingle($single) - { - $joined = []; - - foreach ($single as $part) { - if ( - empty($joined) || - ! \is_string($part) || - preg_match('/[\[.:#%]/', $part) - ) { - $joined[] = $part; - continue; - } - - if (\is_array(end($joined))) { - $joined[] = $part; - } else { - $joined[\count($joined) - 1] .= $part; - } - } - - return $joined; - } - - /** - * Compile selector to string; self(&) should have been replaced by now - * - * @param string|array $selector - * - * @return string - */ - protected function compileSelector($selector) - { - if (! \is_array($selector)) { - return $selector; // media and the like - } - - return implode( - ' ', - array_map( - [$this, 'compileSelectorPart'], - $selector - ) - ); - } - - /** - * Compile selector part - * - * @param array $piece - * - * @return string - */ - protected function compileSelectorPart($piece) - { - foreach ($piece as &$p) { - if (! \is_array($p)) { - continue; - } - - switch ($p[0]) { - case Type::T_SELF: - $p = '&'; - break; - - default: - $p = $this->compileValue($p); - break; - } - } - - return implode($piece); - } - - /** - * Has selector placeholder? - * - * @param array $selector - * - * @return bool - */ - protected function hasSelectorPlaceholder($selector) - { - if (! \is_array($selector)) { - return false; - } - - foreach ($selector as $parts) { - foreach ($parts as $part) { - if (\strlen($part) && '%' === $part[0]) { - return true; - } - } - } - - return false; - } - - /** - * @param string $name - * - * @return void - */ - protected function pushCallStack($name = '') - { - $this->callStack[] = [ - 'n' => $name, - Parser::SOURCE_INDEX => $this->sourceIndex, - Parser::SOURCE_LINE => $this->sourceLine, - Parser::SOURCE_COLUMN => $this->sourceColumn - ]; - - // infinite calling loop - if (\count($this->callStack) > 25000) { - // not displayed but you can var_dump it to deep debug - $msg = $this->callStackMessage(true, 100); - $msg = 'Infinite calling loop'; - - throw $this->error($msg); - } - } - - /** - * @return void - */ - protected function popCallStack() - { - array_pop($this->callStack); - } - - /** - * Compile children and return result - * - * @param array $stms - * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out - * @param string $traceName - * - * @return array|Number|null - */ - protected function compileChildren($stms, OutputBlock $out, $traceName = '') - { - $this->pushCallStack($traceName); - - foreach ($stms as $stm) { - $ret = $this->compileChild($stm, $out); - - if (isset($ret)) { - $this->popCallStack(); - - return $ret; - } - } - - $this->popCallStack(); - - return null; - } - - /** - * Compile children and throw exception if unexpected at-return - * - * @param array[] $stms - * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out - * @param \ScssPhp\ScssPhp\Block $selfParent - * @param string $traceName - * - * @return void - * - * @throws \Exception - */ - protected function compileChildrenNoReturn($stms, OutputBlock $out, $selfParent = null, $traceName = '') - { - $this->pushCallStack($traceName); - - foreach ($stms as $stm) { - if ($selfParent && isset($stm[1]) && \is_object($stm[1]) && $stm[1] instanceof Block) { - $oldSelfParent = $stm[1]->selfParent; - $stm[1]->selfParent = $selfParent; - $ret = $this->compileChild($stm, $out); - $stm[1]->selfParent = $oldSelfParent; - } elseif ($selfParent && \in_array($stm[0], [Type::T_INCLUDE, Type::T_EXTEND])) { - $stm['selfParent'] = $selfParent; - $ret = $this->compileChild($stm, $out); - } else { - $ret = $this->compileChild($stm, $out); - } - - if (isset($ret)) { - throw $this->error('@return may only be used within a function'); - } - } - - $this->popCallStack(); - } - - - /** - * evaluate media query : compile internal value keeping the structure unchanged - * - * @param array $queryList - * - * @return array - */ - protected function evaluateMediaQuery($queryList) - { - static $parser = null; - - $outQueryList = []; - - foreach ($queryList as $kql => $query) { - $shouldReparse = false; - - foreach ($query as $kq => $q) { - for ($i = 1; $i < \count($q); $i++) { - $value = $this->compileValue($q[$i]); - - // the parser had no mean to know if media type or expression if it was an interpolation - // so you need to reparse if the T_MEDIA_TYPE looks like anything else a media type - if ( - $q[0] == Type::T_MEDIA_TYPE && - (strpos($value, '(') !== false || - strpos($value, ')') !== false || - strpos($value, ':') !== false || - strpos($value, ',') !== false) - ) { - $shouldReparse = true; - } - - $queryList[$kql][$kq][$i] = [Type::T_KEYWORD, $value]; - } - } - - if ($shouldReparse) { - if (\is_null($parser)) { - $parser = $this->parserFactory(__METHOD__); - } - - $queryString = $this->compileMediaQuery([$queryList[$kql]]); - $queryString = reset($queryString); - - if ($queryString !== false && strpos($queryString, '@media ') === 0) { - $queryString = substr($queryString, 7); - $queries = []; - - if ($parser->parseMediaQueryList($queryString, $queries)) { - $queries = $this->evaluateMediaQuery($queries[2]); - - while (\count($queries)) { - $outQueryList[] = array_shift($queries); - } - - continue; - } - } - } - - $outQueryList[] = $queryList[$kql]; - } - - return $outQueryList; - } - - /** - * Compile media query - * - * @param array $queryList - * - * @return string[] - */ - protected function compileMediaQuery($queryList) - { - $start = '@media '; - $default = trim($start); - $out = []; - $current = ''; - - foreach ($queryList as $query) { - $type = null; - $parts = []; - - $mediaTypeOnly = true; - - foreach ($query as $q) { - if ($q[0] !== Type::T_MEDIA_TYPE) { - $mediaTypeOnly = false; - break; - } - } - - foreach ($query as $q) { - switch ($q[0]) { - case Type::T_MEDIA_TYPE: - $newType = array_map([$this, 'compileValue'], \array_slice($q, 1)); - - // combining not and anything else than media type is too risky and should be avoided - if (! $mediaTypeOnly) { - if (\in_array(Type::T_NOT, $newType) || ($type && \in_array(Type::T_NOT, $type) )) { - if ($type) { - array_unshift($parts, implode(' ', array_filter($type))); - } - - if (! empty($parts)) { - if (\strlen($current)) { - $current .= $this->formatter->tagSeparator; - } - - $current .= implode(' and ', $parts); - } - - if ($current) { - $out[] = $start . $current; - } - - $current = ''; - $type = null; - $parts = []; - } - } - - if ($newType === ['all'] && $default) { - $default = $start . 'all'; - } - - // all can be safely ignored and mixed with whatever else - if ($newType !== ['all']) { - if ($type) { - $type = $this->mergeMediaTypes($type, $newType); - - if (empty($type)) { - // merge failed : ignore this query that is not valid, skip to the next one - $parts = []; - $default = ''; // if everything fail, no @media at all - continue 3; - } - } else { - $type = $newType; - } - } - break; - - case Type::T_MEDIA_EXPRESSION: - if (isset($q[2])) { - $parts[] = '(' - . $this->compileValue($q[1]) - . $this->formatter->assignSeparator - . $this->compileValue($q[2]) - . ')'; - } else { - $parts[] = '(' - . $this->compileValue($q[1]) - . ')'; - } - break; - - case Type::T_MEDIA_VALUE: - $parts[] = $this->compileValue($q[1]); - break; - } - } - - if ($type) { - array_unshift($parts, implode(' ', array_filter($type))); - } - - if (! empty($parts)) { - if (\strlen($current)) { - $current .= $this->formatter->tagSeparator; - } - - $current .= implode(' and ', $parts); - } - } - - if ($current) { - $out[] = $start . $current; - } - - // no @media type except all, and no conflict? - if (! $out && $default) { - $out[] = $default; - } - - return $out; - } - - /** - * Merge direct relationships between selectors - * - * @param array $selectors1 - * @param array $selectors2 - * - * @return array - */ - protected function mergeDirectRelationships($selectors1, $selectors2) - { - if (empty($selectors1) || empty($selectors2)) { - return array_merge($selectors1, $selectors2); - } - - $part1 = end($selectors1); - $part2 = end($selectors2); - - if (! $this->isImmediateRelationshipCombinator($part1[0]) && $part1 !== $part2) { - return array_merge($selectors1, $selectors2); - } - - $merged = []; - - do { - $part1 = array_pop($selectors1); - $part2 = array_pop($selectors2); - - if (! $this->isImmediateRelationshipCombinator($part1[0]) && $part1 !== $part2) { - if ($this->isImmediateRelationshipCombinator(reset($merged)[0])) { - array_unshift($merged, [$part1[0] . $part2[0]]); - $merged = array_merge($selectors1, $selectors2, $merged); - } else { - $merged = array_merge($selectors1, [$part1], $selectors2, [$part2], $merged); - } - - break; - } - - array_unshift($merged, $part1); - } while (! empty($selectors1) && ! empty($selectors2)); - - return $merged; - } - - /** - * Merge media types - * - * @param array $type1 - * @param array $type2 - * - * @return array|null - */ - protected function mergeMediaTypes($type1, $type2) - { - if (empty($type1)) { - return $type2; - } - - if (empty($type2)) { - return $type1; - } - - if (\count($type1) > 1) { - $m1 = strtolower($type1[0]); - $t1 = strtolower($type1[1]); - } else { - $m1 = ''; - $t1 = strtolower($type1[0]); - } - - if (\count($type2) > 1) { - $m2 = strtolower($type2[0]); - $t2 = strtolower($type2[1]); - } else { - $m2 = ''; - $t2 = strtolower($type2[0]); - } - - if (($m1 === Type::T_NOT) ^ ($m2 === Type::T_NOT)) { - if ($t1 === $t2) { - return null; - } - - return [ - $m1 === Type::T_NOT ? $m2 : $m1, - $m1 === Type::T_NOT ? $t2 : $t1, - ]; - } - - if ($m1 === Type::T_NOT && $m2 === Type::T_NOT) { - // CSS has no way of representing "neither screen nor print" - if ($t1 !== $t2) { - return null; - } - - return [Type::T_NOT, $t1]; - } - - if ($t1 !== $t2) { - return null; - } - - // t1 == t2, neither m1 nor m2 are "not" - return [empty($m1) ? $m2 : $m1, $t1]; - } - - /** - * Compile import; returns true if the value was something that could be imported - * - * @param array $rawPath - * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out - * @param bool $once - * - * @return bool - */ - protected function compileImport($rawPath, OutputBlock $out, $once = false) - { - if ($rawPath[0] === Type::T_STRING) { - $path = $this->compileStringContent($rawPath); - - if (strpos($path, 'url(') !== 0 && $filePath = $this->findImport($path, $this->currentDirectory)) { - $this->registerImport($this->currentDirectory, $path, $filePath); - - if (! $once || ! \in_array($filePath, $this->importedFiles)) { - $this->importFile($filePath, $out); - $this->importedFiles[] = $filePath; - } - - return true; - } - - $this->appendRootDirective('@import ' . $this->compileImportPath($rawPath) . ';', $out); - - return false; - } - - if ($rawPath[0] === Type::T_LIST) { - // handle a list of strings - if (\count($rawPath[2]) === 0) { - return false; - } - - foreach ($rawPath[2] as $path) { - if ($path[0] !== Type::T_STRING) { - $this->appendRootDirective('@import ' . $this->compileImportPath($rawPath) . ';', $out); - - return false; - } - } - - foreach ($rawPath[2] as $path) { - $this->compileImport($path, $out, $once); - } - - return true; - } - - $this->appendRootDirective('@import ' . $this->compileImportPath($rawPath) . ';', $out); - - return false; - } - - /** - * @param array $rawPath - * @return string - * @throws CompilerException - */ - protected function compileImportPath($rawPath) - { - $path = $this->compileValue($rawPath); - - // case url() without quotes : suppress \r \n remaining in the path - // if this is a real string there can not be CR or LF char - if (strpos($path, 'url(') === 0) { - $path = str_replace(array("\r", "\n"), array('', ' '), $path); - } else { - // if this is a file name in a string, spaces should be escaped - $path = $this->reduce($rawPath); - $path = $this->escapeImportPathString($path); - $path = $this->compileValue($path); - } - - return $path; - } - - /** - * @param array $path - * @return array - * @throws CompilerException - */ - protected function escapeImportPathString($path) - { - switch ($path[0]) { - case Type::T_LIST: - foreach ($path[2] as $k => $v) { - $path[2][$k] = $this->escapeImportPathString($v); - } - break; - case Type::T_STRING: - if ($path[1]) { - $path = $this->compileValue($path); - $path = str_replace(' ', '\\ ', $path); - $path = [Type::T_KEYWORD, $path]; - } - break; - } - - return $path; - } - - /** - * Append a root directive like @import or @charset as near as the possible from the source code - * (keeping before comments, @import and @charset coming before in the source code) - * - * @param string $line - * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out - * @param array $allowed - * - * @return void - */ - protected function appendRootDirective($line, $out, $allowed = [Type::T_COMMENT]) - { - $root = $out; - - while ($root->parent) { - $root = $root->parent; - } - - $i = 0; - - while ($i < \count($root->children)) { - if (! isset($root->children[$i]->type) || ! \in_array($root->children[$i]->type, $allowed)) { - break; - } - - $i++; - } - - // remove incompatible children from the bottom of the list - $saveChildren = []; - - while ($i < \count($root->children)) { - $saveChildren[] = array_pop($root->children); - } - - // insert the directive as a comment - $child = $this->makeOutputBlock(Type::T_COMMENT); - $child->lines[] = $line; - $child->sourceName = $this->sourceNames[$this->sourceIndex] ?: '(stdin)'; - $child->sourceLine = $this->sourceLine; - $child->sourceColumn = $this->sourceColumn; - - $root->children[] = $child; - - // repush children - while (\count($saveChildren)) { - $root->children[] = array_pop($saveChildren); - } - } - - /** - * Append lines to the current output block: - * directly to the block or through a child if necessary - * - * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out - * @param string $type - * @param string $line - * - * @return void - */ - protected function appendOutputLine(OutputBlock $out, $type, $line) - { - $outWrite = &$out; - - // check if it's a flat output or not - if (\count($out->children)) { - $lastChild = &$out->children[\count($out->children) - 1]; - - if ( - $lastChild->depth === $out->depth && - \is_null($lastChild->selectors) && - ! \count($lastChild->children) - ) { - $outWrite = $lastChild; - } else { - $nextLines = $this->makeOutputBlock($type); - $nextLines->parent = $out; - $nextLines->depth = $out->depth; - - $out->children[] = $nextLines; - $outWrite = &$nextLines; - } - } - - $outWrite->lines[] = $line; - } - - /** - * Compile child; returns a value to halt execution - * - * @param array $child - * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out - * - * @return array|Number|null - */ - protected function compileChild($child, OutputBlock $out) - { - if (isset($child[Parser::SOURCE_LINE])) { - $this->sourceIndex = isset($child[Parser::SOURCE_INDEX]) ? $child[Parser::SOURCE_INDEX] : null; - $this->sourceLine = isset($child[Parser::SOURCE_LINE]) ? $child[Parser::SOURCE_LINE] : -1; - $this->sourceColumn = isset($child[Parser::SOURCE_COLUMN]) ? $child[Parser::SOURCE_COLUMN] : -1; - } elseif (\is_array($child) && isset($child[1]->sourceLine) && $child[1] instanceof Block) { - $this->sourceIndex = $child[1]->sourceIndex; - $this->sourceLine = $child[1]->sourceLine; - $this->sourceColumn = $child[1]->sourceColumn; - } elseif (! empty($out->sourceLine) && ! empty($out->sourceName)) { - $this->sourceLine = $out->sourceLine; - $sourceIndex = array_search($out->sourceName, $this->sourceNames); - $this->sourceColumn = $out->sourceColumn; - - if ($sourceIndex === false) { - $sourceIndex = null; - } - $this->sourceIndex = $sourceIndex; - } - - switch ($child[0]) { - case Type::T_SCSSPHP_IMPORT_ONCE: - $rawPath = $this->reduce($child[1]); - - $this->compileImport($rawPath, $out, true); - break; - - case Type::T_IMPORT: - $rawPath = $this->reduce($child[1]); - - $this->compileImport($rawPath, $out); - break; - - case Type::T_DIRECTIVE: - $this->compileDirective($child[1], $out); - break; - - case Type::T_AT_ROOT: - $this->compileAtRoot($child[1]); - break; - - case Type::T_MEDIA: - $this->compileMedia($child[1]); - break; - - case Type::T_BLOCK: - $this->compileBlock($child[1]); - break; - - case Type::T_CHARSET: - break; - - case Type::T_CUSTOM_PROPERTY: - list(, $name, $value) = $child; - $compiledName = $this->compileValue($name); - - // if the value reduces to null from something else then - // the property should be discarded - if ($value[0] !== Type::T_NULL) { - $value = $this->reduce($value); - - if ($value[0] === Type::T_NULL || $value === static::$nullString) { - break; - } - } - - $compiledValue = $this->compileValue($value); - - $line = $this->formatter->customProperty( - $compiledName, - $compiledValue - ); - - $this->appendOutputLine($out, Type::T_ASSIGN, $line); - break; - - case Type::T_ASSIGN: - list(, $name, $value) = $child; - - if ($name[0] === Type::T_VARIABLE) { - $flags = isset($child[3]) ? $child[3] : []; - $isDefault = \in_array('!default', $flags); - $isGlobal = \in_array('!global', $flags); - - if ($isGlobal) { - $this->set($name[1], $this->reduce($value), false, $this->rootEnv, $value); - break; - } - - $shouldSet = $isDefault && - (\is_null($result = $this->get($name[1], false)) || - $result === static::$null); - - if (! $isDefault || $shouldSet) { - $this->set($name[1], $this->reduce($value), true, null, $value); - } - break; - } - - $compiledName = $this->compileValue($name); - - // handle shorthand syntaxes : size / line-height... - if (\in_array($compiledName, ['font', 'grid-row', 'grid-column', 'border-radius'])) { - if ($value[0] === Type::T_VARIABLE) { - // if the font value comes from variable, the content is already reduced - // (i.e., formulas were already calculated), so we need the original unreduced value - $value = $this->get($value[1], true, null, true); - } - - $shorthandValue=&$value; - - $shorthandDividerNeedsUnit = false; - $maxListElements = null; - $maxShorthandDividers = 1; - - switch ($compiledName) { - case 'border-radius': - $maxListElements = 4; - $shorthandDividerNeedsUnit = true; - break; - } - - if ($compiledName === 'font' && $value[0] === Type::T_LIST && $value[1] === ',') { - // this is the case if more than one font is given: example: "font: 400 1em/1.3 arial,helvetica" - // we need to handle the first list element - $shorthandValue=&$value[2][0]; - } - - if ($shorthandValue[0] === Type::T_EXPRESSION && $shorthandValue[1] === '/') { - $revert = true; - - if ($shorthandDividerNeedsUnit) { - $divider = $shorthandValue[3]; - - if (\is_array($divider)) { - $divider = $this->reduce($divider, true); - } - - if ($divider instanceof Number && \intval($divider->getDimension()) && $divider->unitless()) { - $revert = false; - } - } - - if ($revert) { - $shorthandValue = $this->expToString($shorthandValue); - } - } elseif ($shorthandValue[0] === Type::T_LIST) { - foreach ($shorthandValue[2] as &$item) { - if ($item[0] === Type::T_EXPRESSION && $item[1] === '/') { - if ($maxShorthandDividers > 0) { - $revert = true; - - // if the list of values is too long, this has to be a shorthand, - // otherwise it could be a real division - if (\is_null($maxListElements) || \count($shorthandValue[2]) <= $maxListElements) { - if ($shorthandDividerNeedsUnit) { - $divider = $item[3]; - - if (\is_array($divider)) { - $divider = $this->reduce($divider, true); - } - - if ($divider instanceof Number && \intval($divider->getDimension()) && $divider->unitless()) { - $revert = false; - } - } - } - - if ($revert) { - $item = $this->expToString($item); - $maxShorthandDividers--; - } - } - } - } - } - } - - // if the value reduces to null from something else then - // the property should be discarded - if ($value[0] !== Type::T_NULL) { - $value = $this->reduce($value); - - if ($value[0] === Type::T_NULL || $value === static::$nullString) { - break; - } - } - - $compiledValue = $this->compileValue($value); - - // ignore empty value - if (\strlen($compiledValue)) { - $line = $this->formatter->property( - $compiledName, - $compiledValue - ); - $this->appendOutputLine($out, Type::T_ASSIGN, $line); - } - break; - - case Type::T_COMMENT: - if ($out->type === Type::T_ROOT) { - $this->compileComment($child); - break; - } - - $line = $this->compileCommentValue($child, true); - $this->appendOutputLine($out, Type::T_COMMENT, $line); - break; - - case Type::T_MIXIN: - case Type::T_FUNCTION: - list(, $block) = $child; - assert($block instanceof CallableBlock); - // the block need to be able to go up to it's parent env to resolve vars - $block->parentEnv = $this->getStoreEnv(); - $this->set(static::$namespaces[$block->type] . $block->name, $block, true); - break; - - case Type::T_EXTEND: - foreach ($child[1] as $sel) { - $replacedSel = $this->replaceSelfSelector($sel); - - if ($replacedSel !== $sel) { - throw $this->error('Parent selectors aren\'t allowed here.'); - } - - $results = $this->evalSelectors([$sel]); - - foreach ($results as $result) { - if (\count($result) !== 1) { - throw $this->error('complex selectors may not be extended.'); - } - - // only use the first one - $result = $result[0]; - $selectors = $out->selectors; - - if (! $selectors && isset($child['selfParent'])) { - $selectors = $this->multiplySelectors($this->env, $child['selfParent']); - } - assert($selectors !== null); - - if (\count($result) > 1) { - $replacement = implode(', ', $result); - $fname = $this->getPrettyPath($this->sourceNames[$this->sourceIndex]); - $line = $this->sourceLine; - - $message = <<<EOL -on line $line of $fname: -Compound selectors may no longer be extended. -Consider `@extend $replacement` instead. -See http://bit.ly/ExtendCompound for details. -EOL; - - $this->logger->warn($message); - } - - $this->pushExtends($result, $selectors, $child); - } - } - break; - - case Type::T_IF: - list(, $if) = $child; - assert($if instanceof IfBlock); - - if ($this->isTruthy($this->reduce($if->cond, true))) { - return $this->compileChildren($if->children, $out); - } - - foreach ($if->cases as $case) { - if ( - $case instanceof ElseBlock || - $case instanceof ElseifBlock && $this->isTruthy($this->reduce($case->cond)) - ) { - return $this->compileChildren($case->children, $out); - } - } - break; - - case Type::T_EACH: - list(, $each) = $child; - assert($each instanceof EachBlock); - - $list = $this->coerceList($this->reduce($each->list), ',', true); - - $this->pushEnv(); - - foreach ($list[2] as $item) { - if (\count($each->vars) === 1) { - $this->set($each->vars[0], $item, true); - } else { - list(,, $values) = $this->coerceList($item); - - foreach ($each->vars as $i => $var) { - $this->set($var, isset($values[$i]) ? $values[$i] : static::$null, true); - } - } - - $ret = $this->compileChildren($each->children, $out); - - if ($ret) { - $store = $this->env->store; - $this->popEnv(); - $this->backPropagateEnv($store, $each->vars); - - return $ret; - } - } - $store = $this->env->store; - $this->popEnv(); - $this->backPropagateEnv($store, $each->vars); - - break; - - case Type::T_WHILE: - list(, $while) = $child; - assert($while instanceof WhileBlock); - - while ($this->isTruthy($this->reduce($while->cond, true))) { - $ret = $this->compileChildren($while->children, $out); - - if ($ret) { - return $ret; - } - } - break; - - case Type::T_FOR: - list(, $for) = $child; - assert($for instanceof ForBlock); - - $startNumber = $this->assertNumber($this->reduce($for->start, true)); - $endNumber = $this->assertNumber($this->reduce($for->end, true)); - - $start = $this->assertInteger($startNumber); - - $numeratorUnits = $startNumber->getNumeratorUnits(); - $denominatorUnits = $startNumber->getDenominatorUnits(); - - $end = $this->assertInteger($endNumber->coerce($numeratorUnits, $denominatorUnits)); - - $d = $start < $end ? 1 : -1; - - $this->pushEnv(); - - for (;;) { - if ( - (! $for->until && $start - $d == $end) || - ($for->until && $start == $end) - ) { - break; - } - - $this->set($for->var, new Number($start, $numeratorUnits, $denominatorUnits)); - $start += $d; - - $ret = $this->compileChildren($for->children, $out); - - if ($ret) { - $store = $this->env->store; - $this->popEnv(); - $this->backPropagateEnv($store, [$for->var]); - - return $ret; - } - } - - $store = $this->env->store; - $this->popEnv(); - $this->backPropagateEnv($store, [$for->var]); - - break; - - case Type::T_RETURN: - return $this->reduce($child[1], true); - - case Type::T_NESTED_PROPERTY: - $this->compileNestedPropertiesBlock($child[1], $out); - break; - - case Type::T_INCLUDE: - // including a mixin - list(, $name, $argValues, $content, $argUsing) = $child; - - $mixin = $this->get(static::$namespaces['mixin'] . $name, false); - - if (! $mixin) { - throw $this->error("Undefined mixin $name"); - } - - assert($mixin instanceof CallableBlock); - - $callingScope = $this->getStoreEnv(); - - // push scope, apply args - $this->pushEnv(); - $this->env->depth--; - - // Find the parent selectors in the env to be able to know what '&' refers to in the mixin - // and assign this fake parent to childs - $selfParent = null; - - if (isset($child['selfParent']) && $child['selfParent'] instanceof Block && isset($child['selfParent']->selectors)) { - $selfParent = $child['selfParent']; - } else { - $parentSelectors = $this->multiplySelectors($this->env); - - if ($parentSelectors) { - $parent = new Block(); - $parent->selectors = $parentSelectors; - - foreach ($mixin->children as $k => $child) { - if (isset($child[1]) && $child[1] instanceof Block) { - $mixin->children[$k][1]->parent = $parent; - } - } - } - } - - // clone the stored content to not have its scope spoiled by a further call to the same mixin - // i.e., recursive @include of the same mixin - if (isset($content)) { - $copyContent = clone $content; - $copyContent->scope = clone $callingScope; - - $this->setRaw(static::$namespaces['special'] . 'content', $copyContent, $this->env); - } else { - $this->setRaw(static::$namespaces['special'] . 'content', null, $this->env); - } - - // save the "using" argument list for applying it to when "@content" is invoked - if (isset($argUsing)) { - $this->setRaw(static::$namespaces['special'] . 'using', $argUsing, $this->env); - } else { - $this->setRaw(static::$namespaces['special'] . 'using', null, $this->env); - } - - if (isset($mixin->args)) { - $this->applyArguments($mixin->args, $argValues); - } - - $this->env->marker = 'mixin'; - - if (! empty($mixin->parentEnv)) { - $this->env->declarationScopeParent = $mixin->parentEnv; - } else { - throw $this->error("@mixin $name() without parentEnv"); - } - - $this->compileChildrenNoReturn($mixin->children, $out, $selfParent, $this->env->marker . ' ' . $name); - - $this->popEnv(); - break; - - case Type::T_MIXIN_CONTENT: - $env = isset($this->storeEnv) ? $this->storeEnv : $this->env; - $content = $this->get(static::$namespaces['special'] . 'content', false, $env); - $argUsing = $this->get(static::$namespaces['special'] . 'using', false, $env); - $argContent = $child[1]; - - if (! $content) { - break; - } - - $storeEnv = $this->storeEnv; - $varsUsing = []; - - if (isset($argUsing) && isset($argContent)) { - // Get the arguments provided for the content with the names provided in the "using" argument list - $this->storeEnv = null; - $varsUsing = $this->applyArguments($argUsing, $argContent, false); - } - - // restore the scope from the @content - $this->storeEnv = $content->scope; - - // append the vars from using if any - foreach ($varsUsing as $name => $val) { - $this->set($name, $val, true, $this->storeEnv); - } - - $this->compileChildrenNoReturn($content->children, $out); - - $this->storeEnv = $storeEnv; - break; - - case Type::T_DEBUG: - list(, $value) = $child; - - $fname = $this->getPrettyPath($this->sourceNames[$this->sourceIndex]); - $line = $this->sourceLine; - $value = $this->compileDebugValue($value); - - $this->logger->debug("$fname:$line DEBUG: $value"); - break; - - case Type::T_WARN: - list(, $value) = $child; - - $fname = $this->getPrettyPath($this->sourceNames[$this->sourceIndex]); - $line = $this->sourceLine; - $value = $this->compileDebugValue($value); - - $this->logger->warn("$value\n on line $line of $fname"); - break; - - case Type::T_ERROR: - list(, $value) = $child; - - $fname = $this->getPrettyPath($this->sourceNames[$this->sourceIndex]); - $line = $this->sourceLine; - $value = $this->compileValue($this->reduce($value, true)); - - throw $this->error("File $fname on line $line ERROR: $value\n"); - - default: - throw $this->error("unknown child type: $child[0]"); - } - - return null; - } - - /** - * Reduce expression to string - * - * @param array $exp - * @param bool $keepParens - * - * @return array - */ - protected function expToString($exp, $keepParens = false) - { - list(, $op, $left, $right, $inParens, $whiteLeft, $whiteRight) = $exp; - - $content = []; - - if ($keepParens && $inParens) { - $content[] = '('; - } - - $content[] = $this->reduce($left); - - if ($whiteLeft) { - $content[] = ' '; - } - - $content[] = $op; - - if ($whiteRight) { - $content[] = ' '; - } - - $content[] = $this->reduce($right); - - if ($keepParens && $inParens) { - $content[] = ')'; - } - - return [Type::T_STRING, '', $content]; - } - - /** - * Is truthy? - * - * @param array|Number $value - * - * @return bool - */ - public function isTruthy($value) - { - return $value !== static::$false && $value !== static::$null; - } - - /** - * Is the value a direct relationship combinator? - * - * @param string $value - * - * @return bool - */ - protected function isImmediateRelationshipCombinator($value) - { - return $value === '>' || $value === '+' || $value === '~'; - } - - /** - * Should $value cause its operand to eval - * - * @param array $value - * - * @return bool - */ - protected function shouldEval($value) - { - switch ($value[0]) { - case Type::T_EXPRESSION: - if ($value[1] === '/') { - return $this->shouldEval($value[2]) || $this->shouldEval($value[3]); - } - - // fall-thru - case Type::T_VARIABLE: - case Type::T_FUNCTION_CALL: - return true; - } - - return false; - } - - /** - * Reduce value - * - * @param array|Number $value - * @param bool $inExp - * - * @return array|Number - */ - protected function reduce($value, $inExp = false) - { - if ($value instanceof Number) { - return $value; - } - - switch ($value[0]) { - case Type::T_EXPRESSION: - list(, $op, $left, $right, $inParens) = $value; - - $opName = isset(static::$operatorNames[$op]) ? static::$operatorNames[$op] : $op; - $inExp = $inExp || $this->shouldEval($left) || $this->shouldEval($right); - - $left = $this->reduce($left, true); - - if ($op !== 'and' && $op !== 'or') { - $right = $this->reduce($right, true); - } - - // special case: looks like css shorthand - if ( - $opName == 'div' && ! $inParens && ! $inExp && - (($right[0] !== Type::T_NUMBER && isset($right[2]) && $right[2] != '') || - ($right[0] === Type::T_NUMBER && ! $right->unitless())) - ) { - return $this->expToString($value); - } - - $left = $this->coerceForExpression($left); - $right = $this->coerceForExpression($right); - $ltype = $left[0]; - $rtype = $right[0]; - - $ucOpName = ucfirst($opName); - $ucLType = ucfirst($ltype); - $ucRType = ucfirst($rtype); - - $shouldEval = $inParens || $inExp; - - // this tries: - // 1. op[op name][left type][right type] - // 2. op[left type][right type] (passing the op as first arg) - // 3. op[op name] - if (\is_callable([$this, $fn = "op{$ucOpName}{$ucLType}{$ucRType}"])) { - $out = $this->$fn($left, $right, $shouldEval); - } elseif (\is_callable([$this, $fn = "op{$ucLType}{$ucRType}"])) { - $out = $this->$fn($op, $left, $right, $shouldEval); - } elseif (\is_callable([$this, $fn = "op{$ucOpName}"])) { - $out = $this->$fn($left, $right, $shouldEval); - } else { - $out = null; - } - - if (isset($out)) { - return $out; - } - - return $this->expToString($value); - - case Type::T_UNARY: - list(, $op, $exp, $inParens) = $value; - - $inExp = $inExp || $this->shouldEval($exp); - $exp = $this->reduce($exp); - - if ($exp instanceof Number) { - switch ($op) { - case '+': - return $exp; - - case '-': - return $exp->unaryMinus(); - } - } - - if ($op === 'not') { - if ($inExp || $inParens) { - if ($exp === static::$false || $exp === static::$null) { - return static::$true; - } - - return static::$false; - } - - $op = $op . ' '; - } - - return [Type::T_STRING, '', [$op, $exp]]; - - case Type::T_VARIABLE: - return $this->reduce($this->get($value[1])); - - case Type::T_LIST: - foreach ($value[2] as &$item) { - $item = $this->reduce($item); - } - unset($item); - - if (isset($value[3]) && \is_array($value[3])) { - foreach ($value[3] as &$item) { - $item = $this->reduce($item); - } - unset($item); - } - - return $value; - - case Type::T_MAP: - foreach ($value[1] as &$item) { - $item = $this->reduce($item); - } - - foreach ($value[2] as &$item) { - $item = $this->reduce($item); - } - - return $value; - - case Type::T_STRING: - foreach ($value[2] as &$item) { - if (\is_array($item) || $item instanceof Number) { - $item = $this->reduce($item); - } - } - - return $value; - - case Type::T_INTERPOLATE: - $value[1] = $this->reduce($value[1]); - - if ($inExp) { - return [Type::T_KEYWORD, $this->compileValue($value, false)]; - } - - return $value; - - case Type::T_FUNCTION_CALL: - return $this->fncall($value[1], $value[2]); - - case Type::T_SELF: - $selfParent = ! empty($this->env->block->selfParent) ? $this->env->block->selfParent : null; - $selfSelector = $this->multiplySelectors($this->env, $selfParent); - $selfSelector = $this->collapseSelectorsAsList($selfSelector); - - return $selfSelector; - - default: - return $value; - } - } - - /** - * Function caller - * - * @param string|array $functionReference - * @param array $argValues - * - * @return array|Number - */ - protected function fncall($functionReference, $argValues) - { - // a string means this is a static hard reference coming from the parsing - if (is_string($functionReference)) { - $name = $functionReference; - - $functionReference = $this->getFunctionReference($name); - if ($functionReference === static::$null || $functionReference[0] !== Type::T_FUNCTION_REFERENCE) { - $functionReference = [Type::T_FUNCTION, $name, [Type::T_LIST, ',', []]]; - } - } - - // a function type means we just want a plain css function call - if ($functionReference[0] === Type::T_FUNCTION) { - // for CSS functions, simply flatten the arguments into a list - $listArgs = []; - - foreach ((array) $argValues as $arg) { - if (empty($arg[0]) || count($argValues) === 1) { - $listArgs[] = $this->reduce($this->stringifyFncallArgs($arg[1])); - } - } - - return [Type::T_FUNCTION, $functionReference[1], [Type::T_LIST, ',', $listArgs]]; - } - - if ($functionReference === static::$null || $functionReference[0] !== Type::T_FUNCTION_REFERENCE) { - return static::$defaultValue; - } - - - switch ($functionReference[1]) { - // SCSS @function - case 'scss': - return $this->callScssFunction($functionReference[3], $argValues); - - // native PHP functions - case 'user': - case 'native': - list(,,$name, $fn, $prototype) = $functionReference; - - // special cases of css valid functions min/max - $name = strtolower($name); - if (\in_array($name, ['min', 'max']) && count($argValues) >= 1) { - $cssFunction = $this->cssValidArg( - [Type::T_FUNCTION_CALL, $name, $argValues], - ['min', 'max', 'calc', 'env', 'var'] - ); - if ($cssFunction !== false) { - return $cssFunction; - } - } - $returnValue = $this->callNativeFunction($name, $fn, $prototype, $argValues); - - if (! isset($returnValue)) { - return $this->fncall([Type::T_FUNCTION, $name, [Type::T_LIST, ',', []]], $argValues); - } - - return $returnValue; - - default: - return static::$defaultValue; - } - } - - /** - * @param array|Number $arg - * @param string[] $allowed_function - * @param bool $inFunction - * - * @return array|Number|false - */ - protected function cssValidArg($arg, $allowed_function = [], $inFunction = false) - { - if ($arg instanceof Number) { - return $this->stringifyFncallArgs($arg); - } - - switch ($arg[0]) { - case Type::T_INTERPOLATE: - return [Type::T_KEYWORD, $this->CompileValue($arg)]; - - case Type::T_FUNCTION: - if (! \in_array($arg[1], $allowed_function)) { - return false; - } - if ($arg[2][0] === Type::T_LIST) { - foreach ($arg[2][2] as $k => $subarg) { - $arg[2][2][$k] = $this->cssValidArg($subarg, $allowed_function, $arg[1]); - if ($arg[2][2][$k] === false) { - return false; - } - } - } - return $arg; - - case Type::T_FUNCTION_CALL: - if (! \in_array($arg[1], $allowed_function)) { - return false; - } - $cssArgs = []; - foreach ($arg[2] as $argValue) { - if ($argValue === static::$null) { - return false; - } - $cssArg = $this->cssValidArg($argValue[1], $allowed_function, $arg[1]); - if (empty($argValue[0]) && $cssArg !== false) { - $cssArgs[] = [$argValue[0], $cssArg]; - } else { - return false; - } - } - - return $this->fncall([Type::T_FUNCTION, $arg[1], [Type::T_LIST, ',', []]], $cssArgs); - - case Type::T_STRING: - case Type::T_KEYWORD: - if (!$inFunction or !\in_array($inFunction, ['calc', 'env', 'var'])) { - return false; - } - return $this->stringifyFncallArgs($arg); - - case Type::T_LIST: - if (!$inFunction) { - return false; - } - if (empty($arg['enclosing']) and $arg[1] === '') { - foreach ($arg[2] as $k => $subarg) { - $arg[2][$k] = $this->cssValidArg($subarg, $allowed_function, $inFunction); - if ($arg[2][$k] === false) { - return false; - } - } - $arg[0] = Type::T_STRING; - return $arg; - } - return false; - - case Type::T_EXPRESSION: - if (! \in_array($arg[1], ['+', '-', '/', '*'])) { - return false; - } - $arg[2] = $this->cssValidArg($arg[2], $allowed_function, $inFunction); - $arg[3] = $this->cssValidArg($arg[3], $allowed_function, $inFunction); - if ($arg[2] === false || $arg[3] === false) { - return false; - } - return $this->expToString($arg, true); - - case Type::T_VARIABLE: - case Type::T_SELF: - default: - return false; - } - } - - - /** - * Reformat fncall arguments to proper css function output - * - * @param array|Number $arg - * - * @return array|Number - */ - protected function stringifyFncallArgs($arg) - { - if ($arg instanceof Number) { - return $arg; - } - - switch ($arg[0]) { - case Type::T_LIST: - foreach ($arg[2] as $k => $v) { - $arg[2][$k] = $this->stringifyFncallArgs($v); - } - break; - - case Type::T_EXPRESSION: - if ($arg[1] === '/') { - $arg[2] = $this->stringifyFncallArgs($arg[2]); - $arg[3] = $this->stringifyFncallArgs($arg[3]); - $arg[5] = $arg[6] = false; // no space around / - $arg = $this->expToString($arg); - } - break; - - case Type::T_FUNCTION_CALL: - $name = strtolower($arg[1]); - - if (in_array($name, ['max', 'min', 'calc'])) { - $args = $arg[2]; - $arg = $this->fncall([Type::T_FUNCTION, $name, [Type::T_LIST, ',', []]], $args); - } - break; - } - - return $arg; - } - - /** - * Find a function reference - * @param string $name - * @param bool $safeCopy - * @return array - */ - protected function getFunctionReference($name, $safeCopy = false) - { - // SCSS @function - if ($func = $this->get(static::$namespaces['function'] . $name, false)) { - if ($safeCopy) { - $func = clone $func; - } - - return [Type::T_FUNCTION_REFERENCE, 'scss', $name, $func]; - } - - // native PHP functions - - // try to find a native lib function - $normalizedName = $this->normalizeName($name); - - if (isset($this->userFunctions[$normalizedName])) { - // see if we can find a user function - list($f, $prototype) = $this->userFunctions[$normalizedName]; - - return [Type::T_FUNCTION_REFERENCE, 'user', $name, $f, $prototype]; - } - - $lowercasedName = strtolower($normalizedName); - - // Special functions overriding a CSS function are case-insensitive. We normalize them as lowercase - // to avoid the deprecation warning about the wrong case being used. - if ($lowercasedName === 'min' || $lowercasedName === 'max' || $lowercasedName === 'rgb' || $lowercasedName === 'rgba' || $lowercasedName === 'hsl' || $lowercasedName === 'hsla') { - $normalizedName = $lowercasedName; - } - - if (($f = $this->getBuiltinFunction($normalizedName)) && \is_callable($f)) { - /** @var string $libName */ - $libName = $f[1]; - $prototype = isset(static::$$libName) ? static::$$libName : null; - - // All core functions have a prototype defined. Not finding the - // prototype can mean 2 things: - // - the function comes from a child class (deprecated just after) - // - the function was found with a different case, which relates to calling the - // wrong Sass function due to our camelCase usage (`fade-in()` vs `fadein()`), - // because PHP method names are case-insensitive while property names are - // case-sensitive. - if ($prototype === null || strtolower($normalizedName) !== $normalizedName) { - $r = new \ReflectionMethod($this, $libName); - $actualLibName = $r->name; - - if ($actualLibName !== $libName || strtolower($normalizedName) !== $normalizedName) { - $kebabCaseName = preg_replace('~(?<=\\w)([A-Z])~', '-$1', substr($actualLibName, 3)); - assert($kebabCaseName !== null); - $originalName = strtolower($kebabCaseName); - $warning = "Calling built-in functions with a non-standard name is deprecated since Scssphp 1.8.0 and will not work anymore in 2.0 (they will be treated as CSS function calls instead).\nUse \"$originalName\" instead of \"$name\"."; - @trigger_error($warning, E_USER_DEPRECATED); - $fname = $this->getPrettyPath($this->sourceNames[$this->sourceIndex]); - $line = $this->sourceLine; - Warn::deprecation("$warning\n on line $line of $fname"); - - // Use the actual function definition - $prototype = isset(static::$$actualLibName) ? static::$$actualLibName : null; - $f[1] = $libName = $actualLibName; - } - } - - if (\get_class($this) !== __CLASS__ && !isset($this->warnedChildFunctions[$libName])) { - $r = new \ReflectionMethod($this, $libName); - $declaringClass = $r->getDeclaringClass()->name; - - $needsWarning = $this->warnedChildFunctions[$libName] = $declaringClass !== __CLASS__; - - if ($needsWarning) { - if (method_exists(__CLASS__, $libName)) { - @trigger_error(sprintf('Overriding the "%s" core function by extending the Compiler is deprecated and will be unsupported in 2.0. Remove the "%s::%s" method.', $normalizedName, $declaringClass, $libName), E_USER_DEPRECATED); - } else { - @trigger_error(sprintf('Registering custom functions by extending the Compiler and using the lib* discovery mechanism is deprecated and will be removed in 2.0. Replace the "%s::%s" method with registering the "%s" function through "Compiler::registerFunction".', $declaringClass, $libName, $normalizedName), E_USER_DEPRECATED); - } - } - } - - return [Type::T_FUNCTION_REFERENCE, 'native', $name, $f, $prototype]; - } - - return static::$null; - } - - - /** - * Normalize name - * - * @param string $name - * - * @return string - */ - protected function normalizeName($name) - { - return str_replace('-', '_', $name); - } - - /** - * Normalize value - * - * @internal - * - * @param array|Number $value - * - * @return array|Number - */ - public function normalizeValue($value) - { - $value = $this->coerceForExpression($this->reduce($value)); - - if ($value instanceof Number) { - return $value; - } - - switch ($value[0]) { - case Type::T_LIST: - $value = $this->extractInterpolation($value); - - if ($value[0] !== Type::T_LIST) { - return [Type::T_KEYWORD, $this->compileValue($value)]; - } - - foreach ($value[2] as $key => $item) { - $value[2][$key] = $this->normalizeValue($item); - } - - if (! empty($value['enclosing'])) { - unset($value['enclosing']); - } - - if ($value[1] === '' && count($value[2]) > 1) { - $value[1] = ' '; - } - - return $value; - - case Type::T_STRING: - return [$value[0], '"', [$this->compileStringContent($value)]]; - - case Type::T_INTERPOLATE: - return [Type::T_KEYWORD, $this->compileValue($value)]; - - default: - return $value; - } - } - - /** - * Add numbers - * - * @param Number $left - * @param Number $right - * - * @return Number - */ - protected function opAddNumberNumber(Number $left, Number $right) - { - return $left->plus($right); - } - - /** - * Multiply numbers - * - * @param Number $left - * @param Number $right - * - * @return Number - */ - protected function opMulNumberNumber(Number $left, Number $right) - { - return $left->times($right); - } - - /** - * Subtract numbers - * - * @param Number $left - * @param Number $right - * - * @return Number - */ - protected function opSubNumberNumber(Number $left, Number $right) - { - return $left->minus($right); - } - - /** - * Divide numbers - * - * @param Number $left - * @param Number $right - * - * @return Number - */ - protected function opDivNumberNumber(Number $left, Number $right) - { - return $left->dividedBy($right); - } - - /** - * Mod numbers - * - * @param Number $left - * @param Number $right - * - * @return Number - */ - protected function opModNumberNumber(Number $left, Number $right) - { - return $left->modulo($right); - } - - /** - * Add strings - * - * @param array $left - * @param array $right - * - * @return array|null - */ - protected function opAdd($left, $right) - { - if ($strLeft = $this->coerceString($left)) { - if ($right[0] === Type::T_STRING) { - $right[1] = ''; - } - - $strLeft[2][] = $right; - - return $strLeft; - } - - if ($strRight = $this->coerceString($right)) { - if ($left[0] === Type::T_STRING) { - $left[1] = ''; - } - - array_unshift($strRight[2], $left); - - return $strRight; - } - - return null; - } - - /** - * Boolean and - * - * @param array|Number $left - * @param array|Number $right - * @param bool $shouldEval - * - * @return array|Number|null - */ - protected function opAnd($left, $right, $shouldEval) - { - $truthy = ($left === static::$null || $right === static::$null) || - ($left === static::$false || $left === static::$true) && - ($right === static::$false || $right === static::$true); - - if (! $shouldEval) { - if (! $truthy) { - return null; - } - } - - if ($left !== static::$false && $left !== static::$null) { - return $this->reduce($right, true); - } - - return $left; - } - - /** - * Boolean or - * - * @param array|Number $left - * @param array|Number $right - * @param bool $shouldEval - * - * @return array|Number|null - */ - protected function opOr($left, $right, $shouldEval) - { - $truthy = ($left === static::$null || $right === static::$null) || - ($left === static::$false || $left === static::$true) && - ($right === static::$false || $right === static::$true); - - if (! $shouldEval) { - if (! $truthy) { - return null; - } - } - - if ($left !== static::$false && $left !== static::$null) { - return $left; - } - - return $this->reduce($right, true); - } - - /** - * Compare colors - * - * @param string $op - * @param array $left - * @param array $right - * - * @return array - */ - protected function opColorColor($op, $left, $right) - { - if ($op !== '==' && $op !== '!=') { - $warning = "Color arithmetic is deprecated and will be an error in future versions.\n" - . "Consider using Sass's color functions instead."; - $fname = $this->getPrettyPath($this->sourceNames[$this->sourceIndex]); - $line = $this->sourceLine; - - Warn::deprecation("$warning\n on line $line of $fname"); - } - - $out = [Type::T_COLOR]; - - foreach ([1, 2, 3] as $i) { - $lval = isset($left[$i]) ? $left[$i] : 0; - $rval = isset($right[$i]) ? $right[$i] : 0; - - switch ($op) { - case '+': - $out[] = $lval + $rval; - break; - - case '-': - $out[] = $lval - $rval; - break; - - case '*': - $out[] = $lval * $rval; - break; - - case '%': - if ($rval == 0) { - throw $this->error("color: Can't take modulo by zero"); - } - - $out[] = $lval % $rval; - break; - - case '/': - if ($rval == 0) { - throw $this->error("color: Can't divide by zero"); - } - - $out[] = (int) ($lval / $rval); - break; - - case '==': - return $this->opEq($left, $right); - - case '!=': - return $this->opNeq($left, $right); - - default: - throw $this->error("color: unknown op $op"); - } - } - - if (isset($left[4])) { - $out[4] = $left[4]; - } elseif (isset($right[4])) { - $out[4] = $right[4]; - } - - return $this->fixColor($out); - } - - /** - * Compare color and number - * - * @param string $op - * @param array $left - * @param Number $right - * - * @return array - */ - protected function opColorNumber($op, $left, Number $right) - { - if ($op === '==') { - return static::$false; - } - - if ($op === '!=') { - return static::$true; - } - - $value = $right->getDimension(); - - return $this->opColorColor( - $op, - $left, - [Type::T_COLOR, $value, $value, $value] - ); - } - - /** - * Compare number and color - * - * @param string $op - * @param Number $left - * @param array $right - * - * @return array - */ - protected function opNumberColor($op, Number $left, $right) - { - if ($op === '==') { - return static::$false; - } - - if ($op === '!=') { - return static::$true; - } - - $value = $left->getDimension(); - - return $this->opColorColor( - $op, - [Type::T_COLOR, $value, $value, $value], - $right - ); - } - - /** - * Compare number1 == number2 - * - * @param array|Number $left - * @param array|Number $right - * - * @return array - */ - protected function opEq($left, $right) - { - if (($lStr = $this->coerceString($left)) && ($rStr = $this->coerceString($right))) { - $lStr[1] = ''; - $rStr[1] = ''; - - $left = $this->compileValue($lStr); - $right = $this->compileValue($rStr); - } - - return $this->toBool($left === $right); - } - - /** - * Compare number1 != number2 - * - * @param array|Number $left - * @param array|Number $right - * - * @return array - */ - protected function opNeq($left, $right) - { - if (($lStr = $this->coerceString($left)) && ($rStr = $this->coerceString($right))) { - $lStr[1] = ''; - $rStr[1] = ''; - - $left = $this->compileValue($lStr); - $right = $this->compileValue($rStr); - } - - return $this->toBool($left !== $right); - } - - /** - * Compare number1 == number2 - * - * @param Number $left - * @param Number $right - * - * @return array - */ - protected function opEqNumberNumber(Number $left, Number $right) - { - return $this->toBool($left->equals($right)); - } - - /** - * Compare number1 != number2 - * - * @param Number $left - * @param Number $right - * - * @return array - */ - protected function opNeqNumberNumber(Number $left, Number $right) - { - return $this->toBool(!$left->equals($right)); - } - - /** - * Compare number1 >= number2 - * - * @param Number $left - * @param Number $right - * - * @return array - */ - protected function opGteNumberNumber(Number $left, Number $right) - { - return $this->toBool($left->greaterThanOrEqual($right)); - } - - /** - * Compare number1 > number2 - * - * @param Number $left - * @param Number $right - * - * @return array - */ - protected function opGtNumberNumber(Number $left, Number $right) - { - return $this->toBool($left->greaterThan($right)); - } - - /** - * Compare number1 <= number2 - * - * @param Number $left - * @param Number $right - * - * @return array - */ - protected function opLteNumberNumber(Number $left, Number $right) - { - return $this->toBool($left->lessThanOrEqual($right)); - } - - /** - * Compare number1 < number2 - * - * @param Number $left - * @param Number $right - * - * @return array - */ - protected function opLtNumberNumber(Number $left, Number $right) - { - return $this->toBool($left->lessThan($right)); - } - - /** - * Cast to boolean - * - * @api - * - * @param bool $thing - * - * @return array - */ - public function toBool($thing) - { - return $thing ? static::$true : static::$false; - } - - /** - * Escape non printable chars in strings output as in dart-sass - * - * @internal - * - * @param string $string - * @param bool $inKeyword - * - * @return string - */ - public function escapeNonPrintableChars($string, $inKeyword = false) - { - static $replacement = []; - if (empty($replacement[$inKeyword])) { - for ($i = 0; $i < 32; $i++) { - if ($i !== 9 || $inKeyword) { - $replacement[$inKeyword][chr($i)] = '\\' . dechex($i) . ($inKeyword ? ' ' : chr(0)); - } - } - } - $string = str_replace(array_keys($replacement[$inKeyword]), array_values($replacement[$inKeyword]), $string); - // chr(0) is not a possible char from the input, so any chr(0) comes from our escaping replacement - if (strpos($string, chr(0)) !== false) { - if (substr($string, -1) === chr(0)) { - $string = substr($string, 0, -1); - } - $string = str_replace( - [chr(0) . '\\',chr(0) . ' '], - [ '\\', ' '], - $string - ); - if (strpos($string, chr(0)) !== false) { - $parts = explode(chr(0), $string); - $string = array_shift($parts); - while (count($parts)) { - $next = array_shift($parts); - if (strpos("0123456789abcdefABCDEF" . chr(9), $next[0]) !== false) { - $string .= " "; - } - $string .= $next; - } - } - } - - return $string; - } - - /** - * Compiles a primitive value into a CSS property value. - * - * Values in scssphp are typed by being wrapped in arrays, their format is - * typically: - * - * array(type, contents [, additional_contents]*) - * - * The input is expected to be reduced. This function will not work on - * things like expressions and variables. - * - * @api - * - * @param array|Number $value - * @param bool $quote - * - * @return string - */ - public function compileValue($value, $quote = true) - { - $value = $this->reduce($value); - - if ($value instanceof Number) { - return $value->output($this); - } - - switch ($value[0]) { - case Type::T_KEYWORD: - return $this->escapeNonPrintableChars($value[1], true); - - case Type::T_COLOR: - // [1] - red component (either number for a %) - // [2] - green component - // [3] - blue component - // [4] - optional alpha component - list(, $r, $g, $b) = $value; - - $r = $this->compileRGBAValue($r); - $g = $this->compileRGBAValue($g); - $b = $this->compileRGBAValue($b); - - if (\count($value) === 5) { - $alpha = $this->compileRGBAValue($value[4], true); - - if (! is_numeric($alpha) || $alpha < 1) { - $colorName = Colors::RGBaToColorName($r, $g, $b, $alpha); - - if (! \is_null($colorName)) { - return $colorName; - } - - if (is_numeric($alpha)) { - $a = new Number($alpha, ''); - } else { - $a = $alpha; - } - - return 'rgba(' . $r . ', ' . $g . ', ' . $b . ', ' . $a . ')'; - } - } - - if (! is_numeric($r) || ! is_numeric($g) || ! is_numeric($b)) { - return 'rgb(' . $r . ', ' . $g . ', ' . $b . ')'; - } - - $colorName = Colors::RGBaToColorName($r, $g, $b); - - if (! \is_null($colorName)) { - return $colorName; - } - - $h = sprintf('#%02x%02x%02x', $r, $g, $b); - - // Converting hex color to short notation (e.g. #003399 to #039) - if ($h[1] === $h[2] && $h[3] === $h[4] && $h[5] === $h[6]) { - $h = '#' . $h[1] . $h[3] . $h[5]; - } - - return $h; - - case Type::T_STRING: - $content = $this->compileStringContent($value, $quote); - - if ($value[1] && $quote) { - $content = str_replace('\\', '\\\\', $content); - - $content = $this->escapeNonPrintableChars($content); - - // force double quote as string quote for the output in certain cases - if ( - $value[1] === "'" && - (strpos($content, '"') === false or strpos($content, "'") !== false) - ) { - $value[1] = '"'; - } elseif ( - $value[1] === '"' && - (strpos($content, '"') !== false and strpos($content, "'") === false) - ) { - $value[1] = "'"; - } - - $content = str_replace($value[1], '\\' . $value[1], $content); - } - - return $value[1] . $content . $value[1]; - - case Type::T_FUNCTION: - $args = ! empty($value[2]) ? $this->compileValue($value[2], $quote) : ''; - - return "$value[1]($args)"; - - case Type::T_FUNCTION_REFERENCE: - $name = ! empty($value[2]) ? $value[2] : ''; - - return "get-function(\"$name\")"; - - case Type::T_LIST: - $value = $this->extractInterpolation($value); - - if ($value[0] !== Type::T_LIST) { - return $this->compileValue($value, $quote); - } - - list(, $delim, $items) = $value; - $pre = $post = ''; - - if (! empty($value['enclosing'])) { - switch ($value['enclosing']) { - case 'parent': - //$pre = '('; - //$post = ')'; - break; - case 'forced_parent': - $pre = '('; - $post = ')'; - break; - case 'bracket': - case 'forced_bracket': - $pre = '['; - $post = ']'; - break; - } - } - - $separator = $delim === '/' ? ' /' : $delim; - - $prefix_value = ''; - - if ($delim !== ' ') { - $prefix_value = ' '; - } - - $filtered = []; - - $same_string_quote = null; - foreach ($items as $item) { - if (\is_null($same_string_quote)) { - $same_string_quote = false; - if ($item[0] === Type::T_STRING) { - $same_string_quote = $item[1]; - foreach ($items as $ii) { - if ($ii[0] !== Type::T_STRING) { - $same_string_quote = false; - break; - } - } - } - } - if ($item[0] === Type::T_NULL) { - continue; - } - if ($same_string_quote === '"' && $item[0] === Type::T_STRING && $item[1]) { - $item[1] = $same_string_quote; - } - - $compiled = $this->compileValue($item, $quote); - - if ($prefix_value && \strlen($compiled)) { - $compiled = $prefix_value . $compiled; - } - - $filtered[] = $compiled; - } - - return $pre . substr(implode($separator, $filtered), \strlen($prefix_value)) . $post; - - case Type::T_MAP: - $keys = $value[1]; - $values = $value[2]; - $filtered = []; - - for ($i = 0, $s = \count($keys); $i < $s; $i++) { - $filtered[$this->compileValue($keys[$i], $quote)] = $this->compileValue($values[$i], $quote); - } - - array_walk($filtered, function (&$value, $key) { - $value = $key . ': ' . $value; - }); - - return '(' . implode(', ', $filtered) . ')'; - - case Type::T_INTERPOLATED: - // node created by extractInterpolation - list(, $interpolate, $left, $right) = $value; - list(,, $whiteLeft, $whiteRight) = $interpolate; - - $delim = $left[1]; - - if ($delim && $delim !== ' ' && ! $whiteLeft) { - $delim .= ' '; - } - - $left = \count($left[2]) > 0 - ? $this->compileValue($left, $quote) . $delim . $whiteLeft - : ''; - - $delim = $right[1]; - - if ($delim && $delim !== ' ') { - $delim .= ' '; - } - - $right = \count($right[2]) > 0 ? - $whiteRight . $delim . $this->compileValue($right, $quote) : ''; - - return $left . $this->compileValue($interpolate, $quote) . $right; - - case Type::T_INTERPOLATE: - // strip quotes if it's a string - $reduced = $this->reduce($value[1]); - - if ($reduced instanceof Number) { - return $this->compileValue($reduced, $quote); - } - - switch ($reduced[0]) { - case Type::T_LIST: - $reduced = $this->extractInterpolation($reduced); - - if ($reduced[0] !== Type::T_LIST) { - break; - } - - list(, $delim, $items) = $reduced; - - if ($delim !== ' ') { - $delim .= ' '; - } - - $filtered = []; - - foreach ($items as $item) { - if ($item[0] === Type::T_NULL) { - continue; - } - - if ($item[0] === Type::T_STRING) { - $filtered[] = $this->compileStringContent($item, $quote); - } elseif ($item[0] === Type::T_KEYWORD) { - $filtered[] = $item[1]; - } else { - $filtered[] = $this->compileValue($item, $quote); - } - } - - $reduced = [Type::T_KEYWORD, implode("$delim", $filtered)]; - break; - - case Type::T_STRING: - $reduced = [Type::T_STRING, '', [$this->compileStringContent($reduced)]]; - break; - - case Type::T_NULL: - $reduced = [Type::T_KEYWORD, '']; - } - - return $this->compileValue($reduced, $quote); - - case Type::T_NULL: - return 'null'; - - case Type::T_COMMENT: - return $this->compileCommentValue($value); - - default: - throw $this->error('unknown value type: ' . json_encode($value)); - } - } - - /** - * @param array|Number $value - * - * @return string - */ - protected function compileDebugValue($value) - { - $value = $this->reduce($value, true); - - if ($value instanceof Number) { - return $this->compileValue($value); - } - - switch ($value[0]) { - case Type::T_STRING: - return $this->compileStringContent($value); - - default: - return $this->compileValue($value); - } - } - - /** - * Flatten list - * - * @param array $list - * - * @return string - * - * @deprecated - */ - protected function flattenList($list) - { - @trigger_error(sprintf('The "%s" method is deprecated.', __METHOD__), E_USER_DEPRECATED); - - return $this->compileValue($list); - } - - /** - * Gets the text of a Sass string - * - * Calling this method on anything else than a SassString is unsupported. Use {@see assertString} first - * to ensure that the value is indeed a string. - * - * @param array $value - * - * @return string - */ - public function getStringText(array $value) - { - if ($value[0] !== Type::T_STRING) { - throw new \InvalidArgumentException('The argument is not a sass string. Did you forgot to use "assertString"?'); - } - - return $this->compileStringContent($value); - } - - /** - * Compile string content - * - * @param array $string - * @param bool $quote - * - * @return string - */ - protected function compileStringContent($string, $quote = true) - { - $parts = []; - - foreach ($string[2] as $part) { - if (\is_array($part) || $part instanceof Number) { - $parts[] = $this->compileValue($part, $quote); - } else { - $parts[] = $part; - } - } - - return implode($parts); - } - - /** - * Extract interpolation; it doesn't need to be recursive, compileValue will handle that - * - * @param array $list - * - * @return array - */ - protected function extractInterpolation($list) - { - $items = $list[2]; - - foreach ($items as $i => $item) { - if ($item[0] === Type::T_INTERPOLATE) { - $before = [Type::T_LIST, $list[1], \array_slice($items, 0, $i)]; - $after = [Type::T_LIST, $list[1], \array_slice($items, $i + 1)]; - - return [Type::T_INTERPOLATED, $item, $before, $after]; - } - } - - return $list; - } - - /** - * Find the final set of selectors - * - * @param \ScssPhp\ScssPhp\Compiler\Environment $env - * @param \ScssPhp\ScssPhp\Block $selfParent - * - * @return array - */ - protected function multiplySelectors(Environment $env, $selfParent = null) - { - $envs = $this->compactEnv($env); - $selectors = []; - $parentSelectors = [[]]; - - $selfParentSelectors = null; - - if (! \is_null($selfParent) && $selfParent->selectors) { - $selfParentSelectors = $this->evalSelectors($selfParent->selectors); - } - - while ($env = array_pop($envs)) { - if (empty($env->selectors)) { - continue; - } - - $selectors = $env->selectors; - - do { - $stillHasSelf = false; - $prevSelectors = $selectors; - $selectors = []; - - foreach ($parentSelectors as $parent) { - foreach ($prevSelectors as $selector) { - if ($selfParentSelectors) { - foreach ($selfParentSelectors as $selfParent) { - // if no '&' in the selector, each call will give same result, only add once - $s = $this->joinSelectors($parent, $selector, $stillHasSelf, $selfParent); - $selectors[serialize($s)] = $s; - } - } else { - $s = $this->joinSelectors($parent, $selector, $stillHasSelf); - $selectors[serialize($s)] = $s; - } - } - } - } while ($stillHasSelf); - - $parentSelectors = $selectors; - } - - $selectors = array_values($selectors); - - // case we are just starting a at-root : nothing to multiply but parentSelectors - if (! $selectors && $selfParentSelectors) { - $selectors = $selfParentSelectors; - } - - return $selectors; - } - - /** - * Join selectors; looks for & to replace, or append parent before child - * - * @param array $parent - * @param array $child - * @param bool $stillHasSelf - * @param array $selfParentSelectors - - * @return array - */ - protected function joinSelectors($parent, $child, &$stillHasSelf, $selfParentSelectors = null) - { - $setSelf = false; - $out = []; - - foreach ($child as $part) { - $newPart = []; - - foreach ($part as $p) { - // only replace & once and should be recalled to be able to make combinations - if ($p === static::$selfSelector && $setSelf) { - $stillHasSelf = true; - } - - if ($p === static::$selfSelector && ! $setSelf) { - $setSelf = true; - - if (\is_null($selfParentSelectors)) { - $selfParentSelectors = $parent; - } - - foreach ($selfParentSelectors as $i => $parentPart) { - if ($i > 0) { - $out[] = $newPart; - $newPart = []; - } - - foreach ($parentPart as $pp) { - if (\is_array($pp)) { - $flatten = []; - - array_walk_recursive($pp, function ($a) use (&$flatten) { - $flatten[] = $a; - }); - - $pp = implode($flatten); - } - - $newPart[] = $pp; - } - } - } else { - $newPart[] = $p; - } - } - - $out[] = $newPart; - } - - return $setSelf ? $out : array_merge($parent, $child); - } - - /** - * Multiply media - * - * @param \ScssPhp\ScssPhp\Compiler\Environment $env - * @param array $childQueries - * - * @return array - */ - protected function multiplyMedia(Environment $env = null, $childQueries = null) - { - if ( - ! isset($env) || - ! empty($env->block->type) && $env->block->type !== Type::T_MEDIA - ) { - return $childQueries; - } - - // plain old block, skip - if (empty($env->block->type)) { - return $this->multiplyMedia($env->parent, $childQueries); - } - - assert($env->block instanceof MediaBlock); - - $parentQueries = isset($env->block->queryList) - ? $env->block->queryList - : [[[Type::T_MEDIA_VALUE, $env->block->value]]]; - - $store = [$this->env, $this->storeEnv]; - - $this->env = $env; - $this->storeEnv = null; - $parentQueries = $this->evaluateMediaQuery($parentQueries); - - list($this->env, $this->storeEnv) = $store; - - if (\is_null($childQueries)) { - $childQueries = $parentQueries; - } else { - $originalQueries = $childQueries; - $childQueries = []; - - foreach ($parentQueries as $parentQuery) { - foreach ($originalQueries as $childQuery) { - $childQueries[] = array_merge( - $parentQuery, - [[Type::T_MEDIA_TYPE, [Type::T_KEYWORD, 'all']]], - $childQuery - ); - } - } - } - - return $this->multiplyMedia($env->parent, $childQueries); - } - - /** - * Convert env linked list to stack - * - * @param Environment $env - * - * @return Environment[] - * - * @phpstan-return non-empty-array<Environment> - */ - protected function compactEnv(Environment $env) - { - for ($envs = []; $env; $env = $env->parent) { - $envs[] = $env; - } - - return $envs; - } - - /** - * Convert env stack to singly linked list - * - * @param Environment[] $envs - * - * @return Environment - * - * @phpstan-param non-empty-array<Environment> $envs - */ - protected function extractEnv($envs) - { - for ($env = null; $e = array_pop($envs);) { - $e->parent = $env; - $env = $e; - } - - return $env; - } - - /** - * Push environment - * - * @param \ScssPhp\ScssPhp\Block $block - * - * @return \ScssPhp\ScssPhp\Compiler\Environment - */ - protected function pushEnv(Block $block = null) - { - $env = new Environment(); - $env->parent = $this->env; - $env->parentStore = $this->storeEnv; - $env->store = []; - $env->block = $block; - $env->depth = isset($this->env->depth) ? $this->env->depth + 1 : 0; - - $this->env = $env; - $this->storeEnv = null; - - return $env; - } - - /** - * Pop environment - * - * @return void - */ - protected function popEnv() - { - $this->storeEnv = $this->env->parentStore; - $this->env = $this->env->parent; - } - - /** - * Propagate vars from a just poped Env (used in @each and @for) - * - * @param array $store - * @param null|string[] $excludedVars - * - * @return void - */ - protected function backPropagateEnv($store, $excludedVars = null) - { - foreach ($store as $key => $value) { - if (empty($excludedVars) || ! \in_array($key, $excludedVars)) { - $this->set($key, $value, true); - } - } - } - - /** - * Get store environment - * - * @return \ScssPhp\ScssPhp\Compiler\Environment - */ - protected function getStoreEnv() - { - return isset($this->storeEnv) ? $this->storeEnv : $this->env; - } - - /** - * Set variable - * - * @param string $name - * @param mixed $value - * @param bool $shadow - * @param \ScssPhp\ScssPhp\Compiler\Environment $env - * @param mixed $valueUnreduced - * - * @return void - */ - protected function set($name, $value, $shadow = false, Environment $env = null, $valueUnreduced = null) - { - $name = $this->normalizeName($name); - - if (! isset($env)) { - $env = $this->getStoreEnv(); - } - - if ($shadow) { - $this->setRaw($name, $value, $env, $valueUnreduced); - } else { - $this->setExisting($name, $value, $env, $valueUnreduced); - } - } - - /** - * Set existing variable - * - * @param string $name - * @param mixed $value - * @param \ScssPhp\ScssPhp\Compiler\Environment $env - * @param mixed $valueUnreduced - * - * @return void - */ - protected function setExisting($name, $value, Environment $env, $valueUnreduced = null) - { - $storeEnv = $env; - $specialContentKey = static::$namespaces['special'] . 'content'; - - $hasNamespace = $name[0] === '^' || $name[0] === '@' || $name[0] === '%'; - - $maxDepth = 10000; - - for (;;) { - if ($maxDepth-- <= 0) { - break; - } - - if (\array_key_exists($name, $env->store)) { - break; - } - - if (! $hasNamespace && isset($env->marker)) { - if (! empty($env->store[$specialContentKey])) { - $env = $env->store[$specialContentKey]->scope; - continue; - } - - if (! empty($env->declarationScopeParent)) { - $env = $env->declarationScopeParent; - continue; - } else { - $env = $storeEnv; - break; - } - } - - if (isset($env->parentStore)) { - $env = $env->parentStore; - } elseif (isset($env->parent)) { - $env = $env->parent; - } else { - $env = $storeEnv; - break; - } - } - - $env->store[$name] = $value; - - if ($valueUnreduced) { - $env->storeUnreduced[$name] = $valueUnreduced; - } - } - - /** - * Set raw variable - * - * @param string $name - * @param mixed $value - * @param \ScssPhp\ScssPhp\Compiler\Environment $env - * @param mixed $valueUnreduced - * - * @return void - */ - protected function setRaw($name, $value, Environment $env, $valueUnreduced = null) - { - $env->store[$name] = $value; - - if ($valueUnreduced) { - $env->storeUnreduced[$name] = $valueUnreduced; - } - } - - /** - * Get variable - * - * @internal - * - * @param string $name - * @param bool $shouldThrow - * @param \ScssPhp\ScssPhp\Compiler\Environment $env - * @param bool $unreduced - * - * @return mixed|null - */ - public function get($name, $shouldThrow = true, Environment $env = null, $unreduced = false) - { - $normalizedName = $this->normalizeName($name); - $specialContentKey = static::$namespaces['special'] . 'content'; - - if (! isset($env)) { - $env = $this->getStoreEnv(); - } - - $hasNamespace = $normalizedName[0] === '^' || $normalizedName[0] === '@' || $normalizedName[0] === '%'; - - $maxDepth = 10000; - - for (;;) { - if ($maxDepth-- <= 0) { - break; - } - - if (\array_key_exists($normalizedName, $env->store)) { - if ($unreduced && isset($env->storeUnreduced[$normalizedName])) { - return $env->storeUnreduced[$normalizedName]; - } - - return $env->store[$normalizedName]; - } - - if (! $hasNamespace && isset($env->marker)) { - if (! empty($env->store[$specialContentKey])) { - $env = $env->store[$specialContentKey]->scope; - continue; - } - - if (! empty($env->declarationScopeParent)) { - $env = $env->declarationScopeParent; - } else { - $env = $this->rootEnv; - } - continue; - } - - if (isset($env->parentStore)) { - $env = $env->parentStore; - } elseif (isset($env->parent)) { - $env = $env->parent; - } else { - break; - } - } - - if ($shouldThrow) { - throw $this->error("Undefined variable \$$name" . ($maxDepth <= 0 ? ' (infinite recursion)' : '')); - } - - // found nothing - return null; - } - - /** - * Has variable? - * - * @param string $name - * @param \ScssPhp\ScssPhp\Compiler\Environment $env - * - * @return bool - */ - protected function has($name, Environment $env = null) - { - return ! \is_null($this->get($name, false, $env)); - } - - /** - * Inject variables - * - * @param array $args - * - * @return void - */ - protected function injectVariables(array $args) - { - if (empty($args)) { - return; - } - - $parser = $this->parserFactory(__METHOD__); - - foreach ($args as $name => $strValue) { - if ($name[0] === '$') { - $name = substr($name, 1); - } - - if (!\is_string($strValue) || ! $parser->parseValue($strValue, $value)) { - $value = $this->coerceValue($strValue); - } - - $this->set($name, $value); - } - } - - /** - * Replaces variables. - * - * @param array<string, mixed> $variables - * - * @return void - */ - public function replaceVariables(array $variables) - { - $this->registeredVars = []; - $this->addVariables($variables); - } - - /** - * Replaces variables. - * - * @param array<string, mixed> $variables - * - * @return void - */ - public function addVariables(array $variables) - { - $triggerWarning = false; - - foreach ($variables as $name => $value) { - if (!$value instanceof Number && !\is_array($value)) { - $triggerWarning = true; - } - - $this->registeredVars[$name] = $value; - } - - if ($triggerWarning) { - @trigger_error('Passing raw values to as custom variables to the Compiler is deprecated. Use "\ScssPhp\ScssPhp\ValueConverter::parseValue" or "\ScssPhp\ScssPhp\ValueConverter::fromPhp" to convert them instead.', E_USER_DEPRECATED); - } - } - - /** - * Set variables - * - * @api - * - * @param array $variables - * - * @return void - * - * @deprecated Use "addVariables" or "replaceVariables" instead. - */ - public function setVariables(array $variables) - { - @trigger_error('The method "setVariables" of the Compiler is deprecated. Use the "addVariables" method for the equivalent behavior or "replaceVariables" if merging with previous variables was not desired.'); - - $this->addVariables($variables); - } - - /** - * Unset variable - * - * @api - * - * @param string $name - * - * @return void - */ - public function unsetVariable($name) - { - unset($this->registeredVars[$name]); - } - - /** - * Returns list of variables - * - * @api - * - * @return array - */ - public function getVariables() - { - return $this->registeredVars; - } - - /** - * Adds to list of parsed files - * - * @internal - * - * @param string|null $path - * - * @return void - */ - public function addParsedFile($path) - { - if (! \is_null($path) && is_file($path)) { - $this->parsedFiles[realpath($path)] = filemtime($path); - } - } - - /** - * Returns list of parsed files - * - * @deprecated - * @return array<string, int> - */ - public function getParsedFiles() - { - @trigger_error('The method "getParsedFiles" of the Compiler is deprecated. Use the "getIncludedFiles" method on the CompilationResult instance returned by compileString() instead. Be careful that the signature of the method is different.', E_USER_DEPRECATED); - return $this->parsedFiles; - } - - /** - * Add import path - * - * @api - * - * @param string|callable $path - * - * @return void - */ - public function addImportPath($path) - { - if (! \in_array($path, $this->importPaths)) { - $this->importPaths[] = $path; - } - } - - /** - * Set import paths - * - * @api - * - * @param string|array<string|callable> $path - * - * @return void - */ - public function setImportPaths($path) - { - $paths = (array) $path; - $actualImportPaths = array_filter($paths, function ($path) { - return $path !== ''; - }); - - $this->legacyCwdImportPath = \count($actualImportPaths) !== \count($paths); - - if ($this->legacyCwdImportPath) { - @trigger_error('Passing an empty string in the import paths to refer to the current working directory is deprecated. If that\'s the intended behavior, the value of "getcwd()" should be used directly instead. If this was used for resolving relative imports of the input alongside "chdir" with the source directory, the path of the input file should be passed to "compileString()" instead.', E_USER_DEPRECATED); - } - - $this->importPaths = $actualImportPaths; - } - - /** - * Set number precision - * - * @api - * - * @param int $numberPrecision - * - * @return void - * - * @deprecated The number precision is not configurable anymore. The default is enough for all browsers. - */ - public function setNumberPrecision($numberPrecision) - { - @trigger_error('The number precision is not configurable anymore. ' - . 'The default is enough for all browsers.', E_USER_DEPRECATED); - } - - /** - * Sets the output style. - * - * @api - * - * @param string $style One of the OutputStyle constants - * - * @return void - * - * @phpstan-param OutputStyle::* $style - */ - public function setOutputStyle($style) - { - switch ($style) { - case OutputStyle::EXPANDED: - $this->configuredFormatter = Expanded::class; - break; - - case OutputStyle::COMPRESSED: - $this->configuredFormatter = Compressed::class; - break; - - default: - throw new \InvalidArgumentException(sprintf('Invalid output style "%s".', $style)); - } - } - - /** - * Set formatter - * - * @api - * - * @param string $formatterName - * - * @return void - * - * @deprecated Use {@see setOutputStyle} instead. - * - * @phpstan-param class-string<Formatter> $formatterName - */ - public function setFormatter($formatterName) - { - if (!\in_array($formatterName, [Expanded::class, Compressed::class], true)) { - @trigger_error('Formatters other than Expanded and Compressed are deprecated.', E_USER_DEPRECATED); - } - @trigger_error('The method "setFormatter" is deprecated. Use "setOutputStyle" instead.', E_USER_DEPRECATED); - - $this->configuredFormatter = $formatterName; - } - - /** - * Set line number style - * - * @api - * - * @param string $lineNumberStyle - * - * @return void - * - * @deprecated The line number output is not supported anymore. Use source maps instead. - */ - public function setLineNumberStyle($lineNumberStyle) - { - @trigger_error('The line number output is not supported anymore. ' - . 'Use source maps instead.', E_USER_DEPRECATED); - } - - /** - * Configures the handling of non-ASCII outputs. - * - * If $charset is `true`, this will include a `@charset` declaration or a - * UTF-8 [byte-order mark][] if the stylesheet contains any non-ASCII - * characters. Otherwise, it will never include a `@charset` declaration or a - * byte-order mark. - * - * [byte-order mark]: https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8 - * - * @param bool $charset - * - * @return void - */ - public function setCharset($charset) - { - $this->charset = $charset; - } - - /** - * Enable/disable source maps - * - * @api - * - * @param int $sourceMap - * - * @return void - * - * @phpstan-param self::SOURCE_MAP_* $sourceMap - */ - public function setSourceMap($sourceMap) - { - $this->sourceMap = $sourceMap; - } - - /** - * Set source map options - * - * @api - * - * @param array $sourceMapOptions - * - * @phpstan-param array{sourceRoot?: string, sourceMapFilename?: string|null, sourceMapURL?: string|null, sourceMapWriteTo?: string|null, outputSourceFiles?: bool, sourceMapRootpath?: string, sourceMapBasepath?: string} $sourceMapOptions - * - * @return void - */ - public function setSourceMapOptions($sourceMapOptions) - { - $this->sourceMapOptions = $sourceMapOptions; - } - - /** - * Register function - * - * @api - * - * @param string $name - * @param callable $callback - * @param string[]|null $argumentDeclaration - * - * @return void - */ - public function registerFunction($name, $callback, $argumentDeclaration = null) - { - if (self::isNativeFunction($name)) { - @trigger_error(sprintf('The "%s" function is a core sass function. Overriding it with a custom implementation through "%s" is deprecated and won\'t be supported in ScssPhp 2.0 anymore.', $name, __METHOD__), E_USER_DEPRECATED); - } - - if ($argumentDeclaration === null) { - @trigger_error('Omitting the argument declaration when registering custom function is deprecated and won\'t be supported in ScssPhp 2.0 anymore.', E_USER_DEPRECATED); - } - - $this->userFunctions[$this->normalizeName($name)] = [$callback, $argumentDeclaration]; - } - - /** - * Unregister function - * - * @api - * - * @param string $name - * - * @return void - */ - public function unregisterFunction($name) - { - unset($this->userFunctions[$this->normalizeName($name)]); - } - - /** - * Add feature - * - * @api - * - * @param string $name - * - * @return void - * - * @deprecated Registering additional features is deprecated. - */ - public function addFeature($name) - { - @trigger_error('Registering additional features is deprecated.', E_USER_DEPRECATED); - - $this->registeredFeatures[$name] = true; - } - - /** - * Import file - * - * @param string $path - * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out - * - * @return void - */ - protected function importFile($path, OutputBlock $out) - { - $this->pushCallStack('import ' . $this->getPrettyPath($path)); - // see if tree is cached - $realPath = realpath($path); - - if ($realPath === false) { - $realPath = $path; - } - - if (substr($path, -5) === '.sass') { - $this->sourceIndex = \count($this->sourceNames); - $this->sourceNames[] = $path; - $this->sourceLine = 1; - $this->sourceColumn = 1; - - throw $this->error('The Sass indented syntax is not implemented.'); - } - - if (isset($this->importCache[$realPath])) { - $this->handleImportLoop($realPath); - - $tree = $this->importCache[$realPath]; - } else { - $code = file_get_contents($path); - $parser = $this->parserFactory($path); - $tree = $parser->parse($code); - - $this->importCache[$realPath] = $tree; - } - - $currentDirectory = $this->currentDirectory; - $this->currentDirectory = dirname($path); - - $this->compileChildrenNoReturn($tree->children, $out); - $this->currentDirectory = $currentDirectory; - $this->popCallStack(); - } - - /** - * Save the imported files with their resolving path context - * - * @param string|null $currentDirectory - * @param string $path - * @param string $filePath - * - * @return void - */ - private function registerImport($currentDirectory, $path, $filePath) - { - $this->resolvedImports[] = ['currentDir' => $currentDirectory, 'path' => $path, 'filePath' => $filePath]; - } - - /** - * Detects whether the import is a CSS import. - * - * For legacy reasons, custom importers are called for those, allowing them - * to replace them with an actual Sass import. However this behavior is - * deprecated. Custom importers are expected to return null when they receive - * a CSS import. - * - * @param string $url - * - * @return bool - */ - public static function isCssImport($url) - { - return 1 === preg_match('~\.css$|^https?://|^//~', $url); - } - - /** - * Return the file path for an import url if it exists - * - * @internal - * - * @param string $url - * @param string|null $currentDir - * - * @return string|null - */ - public function findImport($url, $currentDir = null) - { - // Vanilla css and external requests. These are not meant to be Sass imports. - // Callback importers are still called for BC. - if (self::isCssImport($url)) { - foreach ($this->importPaths as $dir) { - if (\is_string($dir)) { - continue; - } - - if (\is_callable($dir)) { - // check custom callback for import path - $file = \call_user_func($dir, $url); - - if (! \is_null($file)) { - if (\is_array($dir)) { - $callableDescription = (\is_object($dir[0]) ? \get_class($dir[0]) : $dir[0]).'::'.$dir[1]; - } elseif ($dir instanceof \Closure) { - $r = new \ReflectionFunction($dir); - if (false !== strpos($r->name, '{closure}')) { - $callableDescription = sprintf('closure{%s:%s}', $r->getFileName(), $r->getStartLine()); - } elseif ($class = $r->getClosureScopeClass()) { - $callableDescription = $class->name.'::'.$r->name; - } else { - $callableDescription = $r->name; - } - } elseif (\is_object($dir)) { - $callableDescription = \get_class($dir) . '::__invoke'; - } else { - $callableDescription = 'callable'; // Fallback if we don't have a dedicated description - } - @trigger_error(sprintf('Returning a file to import for CSS or external references in custom importer callables is deprecated and will not be supported anymore in ScssPhp 2.0. This behavior is not compliant with the Sass specification. Update your "%s" importer.', $callableDescription), E_USER_DEPRECATED); - - return $file; - } - } - } - return null; - } - - if (!\is_null($currentDir)) { - $relativePath = $this->resolveImportPath($url, $currentDir); - - if (!\is_null($relativePath)) { - return $relativePath; - } - } - - foreach ($this->importPaths as $dir) { - if (\is_string($dir)) { - $path = $this->resolveImportPath($url, $dir); - - if (!\is_null($path)) { - return $path; - } - } elseif (\is_callable($dir)) { - // check custom callback for import path - $file = \call_user_func($dir, $url); - - if (! \is_null($file)) { - return $file; - } - } - } - - if ($this->legacyCwdImportPath) { - $path = $this->resolveImportPath($url, getcwd()); - - if (!\is_null($path)) { - @trigger_error('Resolving imports relatively to the current working directory is deprecated. If that\'s the intended behavior, the value of "getcwd()" should be added as an import path explicitly instead. If this was used for resolving relative imports of the input alongside "chdir" with the source directory, the path of the input file should be passed to "compileString()" instead.', E_USER_DEPRECATED); - - return $path; - } - } - - throw $this->error("`$url` file not found for @import"); - } - - /** - * @param string $url - * @param string $baseDir - * - * @return string|null - */ - private function resolveImportPath($url, $baseDir) - { - $path = Path::join($baseDir, $url); - - $hasExtension = preg_match('/.s[ac]ss$/', $url); - - if ($hasExtension) { - return $this->checkImportPathConflicts($this->tryImportPath($path)); - } - - $result = $this->checkImportPathConflicts($this->tryImportPathWithExtensions($path)); - - if (!\is_null($result)) { - return $result; - } - - return $this->tryImportPathAsDirectory($path); - } - - /** - * @param string[] $paths - * - * @return string|null - */ - private function checkImportPathConflicts(array $paths) - { - if (\count($paths) === 0) { - return null; - } - - if (\count($paths) === 1) { - return $paths[0]; - } - - $formattedPrettyPaths = []; - - foreach ($paths as $path) { - $formattedPrettyPaths[] = ' ' . $this->getPrettyPath($path); - } - - throw $this->error("It's not clear which file to import. Found:\n" . implode("\n", $formattedPrettyPaths)); - } - - /** - * @param string $path - * - * @return string[] - */ - private function tryImportPathWithExtensions($path) - { - $result = array_merge( - $this->tryImportPath($path.'.sass'), - $this->tryImportPath($path.'.scss') - ); - - if ($result) { - return $result; - } - - return $this->tryImportPath($path.'.css'); - } - - /** - * @param string $path - * - * @return string[] - */ - private function tryImportPath($path) - { - $partial = dirname($path).'/_'.basename($path); - - $candidates = []; - - if (is_file($partial)) { - $candidates[] = $partial; - } - - if (is_file($path)) { - $candidates[] = $path; - } - - return $candidates; - } - - /** - * @param string $path - * - * @return string|null - */ - private function tryImportPathAsDirectory($path) - { - if (!is_dir($path)) { - return null; - } - - return $this->checkImportPathConflicts($this->tryImportPathWithExtensions($path.'/index')); - } - - /** - * @param string|null $path - * - * @return string - */ - private function getPrettyPath($path) - { - if ($path === null) { - return '(unknown file)'; - } - - $normalizedPath = $path; - $normalizedRootDirectory = $this->rootDirectory.'/'; - - if (\DIRECTORY_SEPARATOR === '\\') { - $normalizedRootDirectory = str_replace('\\', '/', $normalizedRootDirectory); - $normalizedPath = str_replace('\\', '/', $path); - } - - if (0 === strpos($normalizedPath, $normalizedRootDirectory)) { - return substr($path, \strlen($normalizedRootDirectory)); - } - - return $path; - } - - /** - * Set encoding - * - * @api - * - * @param string|null $encoding - * - * @return void - * - * @deprecated Non-compliant support for other encodings than UTF-8 is deprecated. - */ - public function setEncoding($encoding) - { - if (!$encoding || strtolower($encoding) === 'utf-8') { - @trigger_error(sprintf('The "%s" method is deprecated.', __METHOD__), E_USER_DEPRECATED); - } else { - @trigger_error(sprintf('The "%s" method is deprecated. Parsing will only support UTF-8 in ScssPhp 2.0. The non-UTF-8 parsing of ScssPhp 1.x is not spec compliant.', __METHOD__), E_USER_DEPRECATED); - } - - $this->encoding = $encoding; - } - - /** - * Ignore errors? - * - * @api - * - * @param bool $ignoreErrors - * - * @return \ScssPhp\ScssPhp\Compiler - * - * @deprecated Ignoring Sass errors is not longer supported. - */ - public function setIgnoreErrors($ignoreErrors) - { - @trigger_error('Ignoring Sass errors is not longer supported.', E_USER_DEPRECATED); - - return $this; - } - - /** - * Get source position - * - * @api - * - * @return array - * - * @deprecated - */ - public function getSourcePosition() - { - @trigger_error(sprintf('The "%s" method is deprecated.', __METHOD__), E_USER_DEPRECATED); - - $sourceFile = isset($this->sourceNames[$this->sourceIndex]) ? $this->sourceNames[$this->sourceIndex] : ''; - - return [$sourceFile, $this->sourceLine, $this->sourceColumn]; - } - - /** - * Throw error (exception) - * - * @api - * - * @param string $msg Message with optional sprintf()-style vararg parameters - * - * @return never - * - * @throws \ScssPhp\ScssPhp\Exception\CompilerException - * - * @deprecated use "error" and throw the exception in the caller instead. - */ - public function throwError($msg) - { - @trigger_error( - 'The method "throwError" is deprecated. Use "error" and throw the exception in the caller instead', - E_USER_DEPRECATED - ); - - throw $this->error(...func_get_args()); - } - - /** - * Build an error (exception) - * - * @internal - * - * @param string $msg Message with optional sprintf()-style vararg parameters - * @param bool|float|int|string|null ...$args - * - * @return CompilerException - */ - public function error($msg, ...$args) - { - if ($args) { - $msg = sprintf($msg, ...$args); - } - - if (! $this->ignoreCallStackMessage) { - $msg = $this->addLocationToMessage($msg); - } - - return new CompilerException($msg); - } - - /** - * @param string $msg - * - * @return string - */ - private function addLocationToMessage($msg) - { - $line = $this->sourceLine; - $column = $this->sourceColumn; - - $loc = isset($this->sourceNames[$this->sourceIndex]) - ? $this->getPrettyPath($this->sourceNames[$this->sourceIndex]) . " on line $line, at column $column" - : "line: $line, column: $column"; - - $msg = "$msg: $loc"; - - $callStackMsg = $this->callStackMessage(); - - if ($callStackMsg) { - $msg .= "\nCall Stack:\n" . $callStackMsg; - } - - return $msg; - } - - /** - * @param string $functionName - * @param array $ExpectedArgs - * @param int $nbActual - * @return CompilerException - * - * @deprecated - */ - public function errorArgsNumber($functionName, $ExpectedArgs, $nbActual) - { - @trigger_error(sprintf('The "%s" method is deprecated.', __METHOD__), E_USER_DEPRECATED); - - $nbExpected = \count($ExpectedArgs); - - if ($nbActual > $nbExpected) { - return $this->error( - 'Error: Only %d arguments allowed in %s(), but %d were passed.', - $nbExpected, - $functionName, - $nbActual - ); - } else { - $missing = []; - - while (count($ExpectedArgs) && count($ExpectedArgs) > $nbActual) { - array_unshift($missing, array_pop($ExpectedArgs)); - } - - return $this->error( - 'Error: %s() argument%s %s missing.', - $functionName, - count($missing) > 1 ? 's' : '', - implode(', ', $missing) - ); - } - } - - /** - * Beautify call stack for output - * - * @param bool $all - * @param int|null $limit - * - * @return string - */ - protected function callStackMessage($all = false, $limit = null) - { - $callStackMsg = []; - $ncall = 0; - - if ($this->callStack) { - foreach (array_reverse($this->callStack) as $call) { - if ($all || (isset($call['n']) && $call['n'])) { - $msg = '#' . $ncall++ . ' ' . $call['n'] . ' '; - $msg .= (isset($this->sourceNames[$call[Parser::SOURCE_INDEX]]) - ? $this->getPrettyPath($this->sourceNames[$call[Parser::SOURCE_INDEX]]) - : '(unknown file)'); - $msg .= ' on line ' . $call[Parser::SOURCE_LINE]; - - $callStackMsg[] = $msg; - - if (! \is_null($limit) && $ncall > $limit) { - break; - } - } - } - } - - return implode("\n", $callStackMsg); - } - - /** - * Handle import loop - * - * @param string $name - * - * @return void - * - * @throws \Exception - */ - protected function handleImportLoop($name) - { - for ($env = $this->env; $env; $env = $env->parent) { - if (! $env->block) { - continue; - } - - $file = $this->sourceNames[$env->block->sourceIndex]; - - if ($file === null) { - continue; - } - - if (realpath($file) === $name) { - throw $this->error('An @import loop has been found: %s imports %s', $file, basename($file)); - } - } - } - - /** - * Call SCSS @function - * - * @param CallableBlock|null $func - * @param array $argValues - * - * @return array|Number - */ - protected function callScssFunction($func, $argValues) - { - if (! $func) { - return static::$defaultValue; - } - $name = $func->name; - - $this->pushEnv(); - - // set the args - if (isset($func->args)) { - $this->applyArguments($func->args, $argValues); - } - - // throw away lines and children - $tmp = new OutputBlock(); - $tmp->lines = []; - $tmp->children = []; - - $this->env->marker = 'function'; - - if (! empty($func->parentEnv)) { - $this->env->declarationScopeParent = $func->parentEnv; - } else { - throw $this->error("@function $name() without parentEnv"); - } - - $ret = $this->compileChildren($func->children, $tmp, $this->env->marker . ' ' . $name); - - $this->popEnv(); - - return ! isset($ret) ? static::$defaultValue : $ret; - } - - /** - * Call built-in and registered (PHP) functions - * - * @param string $name - * @param callable $function - * @param array $prototype - * @param array $args - * - * @return array|Number|null - */ - protected function callNativeFunction($name, $function, $prototype, $args) - { - $libName = (is_array($function) ? end($function) : null); - $sorted_kwargs = $this->sortNativeFunctionArgs($libName, $prototype, $args); - - if (\is_null($sorted_kwargs)) { - return null; - } - @list($sorted, $kwargs) = $sorted_kwargs; - - if ($name !== 'if') { - foreach ($sorted as &$val) { - if ($val !== null) { - $val = $this->reduce($val, true); - } - } - } - - $returnValue = \call_user_func($function, $sorted, $kwargs); - - if (! isset($returnValue)) { - return null; - } - - if (\is_array($returnValue) || $returnValue instanceof Number) { - return $returnValue; - } - - @trigger_error(sprintf('Returning a PHP value from the "%s" custom function is deprecated. A sass value must be returned instead.', $name), E_USER_DEPRECATED); - - return $this->coerceValue($returnValue); - } - - /** - * Get built-in function - * - * @param string $name Normalized name - * - * @return array - */ - protected function getBuiltinFunction($name) - { - $libName = self::normalizeNativeFunctionName($name); - return [$this, $libName]; - } - - /** - * Normalize native function name - * - * @internal - * - * @param string $name - * - * @return string - */ - public static function normalizeNativeFunctionName($name) - { - $name = str_replace("-", "_", $name); - $libName = 'lib' . preg_replace_callback( - '/_(.)/', - function ($m) { - return ucfirst($m[1]); - }, - ucfirst($name) - ); - return $libName; - } - - /** - * Check if a function is a native built-in scss function, for css parsing - * - * @internal - * - * @param string $name - * - * @return bool - */ - public static function isNativeFunction($name) - { - return method_exists(Compiler::class, self::normalizeNativeFunctionName($name)); - } - - /** - * Sorts keyword arguments - * - * @param string $functionName - * @param array|null $prototypes - * @param array $args - * - * @return array|null - */ - protected function sortNativeFunctionArgs($functionName, $prototypes, $args) - { - static $parser = null; - - if (! isset($prototypes)) { - $keyArgs = []; - $posArgs = []; - - if (\is_array($args) && \count($args) && \end($args) === static::$null) { - array_pop($args); - } - - // separate positional and keyword arguments - foreach ($args as $arg) { - list($key, $value) = $arg; - - if (empty($key) or empty($key[1])) { - $posArgs[] = empty($arg[2]) ? $value : $arg; - } else { - $keyArgs[$key[1]] = $value; - } - } - - return [$posArgs, $keyArgs]; - } - - // specific cases ? - if (\in_array($functionName, ['libRgb', 'libRgba', 'libHsl', 'libHsla'])) { - // notation 100 127 255 / 0 is in fact a simple list of 4 values - foreach ($args as $k => $arg) { - if (!isset($arg[1])) { - continue; // This happens when using a trailing comma - } - if ($arg[1][0] === Type::T_LIST && \count($arg[1][2]) === 3) { - $args[$k][1][2] = $this->extractSlashAlphaInColorFunction($arg[1][2]); - } - } - } - - list($positionalArgs, $namedArgs, $names, $separator, $hasSplat) = $this->evaluateArguments($args, false); - - if (! \is_array(reset($prototypes))) { - $prototypes = [$prototypes]; - } - - $parsedPrototypes = array_map([$this, 'parseFunctionPrototype'], $prototypes); - assert(!empty($parsedPrototypes)); - $matchedPrototype = $this->selectFunctionPrototype($parsedPrototypes, \count($positionalArgs), $names); - - $this->verifyPrototype($matchedPrototype, \count($positionalArgs), $names, $hasSplat); - - $vars = $this->applyArgumentsToDeclaration($matchedPrototype, $positionalArgs, $namedArgs, $separator); - - $finalArgs = []; - $keyArgs = []; - - foreach ($matchedPrototype['arguments'] as $argument) { - list($normalizedName, $originalName, $default) = $argument; - - if (isset($vars[$normalizedName])) { - $value = $vars[$normalizedName]; - } else { - $value = $default; - } - - // special null value as default: translate to real null here - if ($value === [Type::T_KEYWORD, 'null']) { - $value = null; - } - - $finalArgs[] = $value; - $keyArgs[$originalName] = $value; - } - - if ($matchedPrototype['rest_argument'] !== null) { - $value = $vars[$matchedPrototype['rest_argument']]; - - $finalArgs[] = $value; - $keyArgs[$matchedPrototype['rest_argument']] = $value; - } - - return [$finalArgs, $keyArgs]; - } - - /** - * Parses a function prototype to the internal representation of arguments. - * - * The input is an array of strings describing each argument, as supported - * in {@see registerFunction}. Argument names don't include the `$`. - * The output contains the list of positional argument, with their normalized - * name (underscores are replaced by dashes), their original name (to be used - * in case of error reporting) and their default value. The output also contains - * the normalized name of the rest argument, or null if the function prototype - * is not variadic. - * - * @param string[] $prototype - * - * @return array - * @phpstan-return array{arguments: list<array{0: string, 1: string, 2: array|Number|null}>, rest_argument: string|null} - */ - private function parseFunctionPrototype(array $prototype) - { - static $parser = null; - - $arguments = []; - $restArgument = null; - - foreach ($prototype as $p) { - if (null !== $restArgument) { - throw new \InvalidArgumentException('The argument declaration is invalid. The rest argument must be the last one.'); - } - - $default = null; - $p = explode(':', $p, 2); - $name = str_replace('_', '-', $p[0]); - - if (isset($p[1])) { - $defaultSource = trim($p[1]); - - if ($defaultSource === 'null') { - // differentiate this null from the static::$null - $default = [Type::T_KEYWORD, 'null']; - } else { - if (\is_null($parser)) { - $parser = $this->parserFactory(__METHOD__); - } - - $parser->parseValue($defaultSource, $default); - } - } - - if (substr($name, -3) === '...') { - $restArgument = substr($name, 0, -3); - } else { - $arguments[] = [$name, $p[0], $default]; - } - } - - return [ - 'arguments' => $arguments, - 'rest_argument' => $restArgument, - ]; - } - - /** - * Returns the function prototype for the given positional and named arguments. - * - * If no exact match is found, finds the closest approximation. Note that this - * doesn't guarantee that $positional and $names are valid for the returned - * prototype. - * - * @param array[] $prototypes - * @param int $positional - * @param array<string, string> $names A set of names, as both keys and values - * - * @return array - * - * @phpstan-param non-empty-list<array{arguments: list<array{0: string, 1: string, 2: array|Number|null}>, rest_argument: string|null}> $prototypes - * @phpstan-return array{arguments: list<array{0: string, 1: string, 2: array|Number|null}>, rest_argument: string|null} - */ - private function selectFunctionPrototype(array $prototypes, $positional, array $names) - { - $fuzzyMatch = null; - $minMismatchDistance = null; - - foreach ($prototypes as $prototype) { - // Ideally, find an exact match. - if ($this->checkPrototypeMatches($prototype, $positional, $names)) { - return $prototype; - } - - $mismatchDistance = \count($prototype['arguments']) - $positional; - - if ($minMismatchDistance !== null) { - if (abs($mismatchDistance) > abs($minMismatchDistance)) { - continue; - } - - // If two overloads have the same mismatch distance, favor the overload - // that has more arguments. - if (abs($mismatchDistance) === abs($minMismatchDistance) && $mismatchDistance < 0) { - continue; - } - } - - $minMismatchDistance = $mismatchDistance; - $fuzzyMatch = $prototype; - } - - return $fuzzyMatch; - } - - /** - * Checks whether the argument invocation matches the callable prototype. - * - * The rules are similar to {@see verifyPrototype}. The boolean return value - * avoids the overhead of building and catching exceptions when the reason of - * not matching the prototype does not need to be known. - * - * @param array $prototype - * @param int $positional - * @param array<string, string> $names - * - * @return bool - * - * @phpstan-param array{arguments: list<array{0: string, 1: string, 2: array|Number|null}>, rest_argument: string|null} $prototype - */ - private function checkPrototypeMatches(array $prototype, $positional, array $names) - { - $nameUsed = 0; - - foreach ($prototype['arguments'] as $i => $argument) { - list ($name, $originalName, $default) = $argument; - - if ($i < $positional) { - if (isset($names[$name])) { - return false; - } - } elseif (isset($names[$name])) { - $nameUsed++; - } elseif ($default === null) { - return false; - } - } - - if ($prototype['rest_argument'] !== null) { - return true; - } - - if ($positional > \count($prototype['arguments'])) { - return false; - } - - if ($nameUsed < \count($names)) { - return false; - } - - return true; - } - - /** - * Verifies that the argument invocation is valid for the callable prototype. - * - * @param array $prototype - * @param int $positional - * @param array<string, string> $names - * @param bool $hasSplat - * - * @return void - * - * @throws SassScriptException - * - * @phpstan-param array{arguments: list<array{0: string, 1: string, 2: array|Number|null}>, rest_argument: string|null} $prototype - */ - private function verifyPrototype(array $prototype, $positional, array $names, $hasSplat) - { - $nameUsed = 0; - - foreach ($prototype['arguments'] as $i => $argument) { - list ($name, $originalName, $default) = $argument; - - if ($i < $positional) { - if (isset($names[$name])) { - throw new SassScriptException(sprintf('Argument $%s was passed both by position and by name.', $originalName)); - } - } elseif (isset($names[$name])) { - $nameUsed++; - } elseif ($default === null) { - throw new SassScriptException(sprintf('Missing argument $%s', $originalName)); - } - } - - if ($prototype['rest_argument'] !== null) { - return; - } - - if ($positional > \count($prototype['arguments'])) { - $message = sprintf( - 'Only %d %sargument%s allowed, but %d %s passed.', - \count($prototype['arguments']), - empty($names) ? '' : 'positional ', - \count($prototype['arguments']) === 1 ? '' : 's', - $positional, - $positional === 1 ? 'was' : 'were' - ); - if (!$hasSplat) { - throw new SassScriptException($message); - } - - $message = $this->addLocationToMessage($message); - $message .= "\nThis will be an error in future versions of Sass."; - $this->logger->warn($message, true); - } - - if ($nameUsed < \count($names)) { - $unknownNames = array_values(array_diff($names, array_column($prototype['arguments'], 0))); - $lastName = array_pop($unknownNames); - $message = sprintf( - 'No argument%s named $%s%s.', - $unknownNames ? 's' : '', - $unknownNames ? implode(', $', $unknownNames) . ' or $' : '', - $lastName - ); - throw new SassScriptException($message); - } - } - - /** - * Evaluates the argument from the invocation. - * - * This returns several things about this invocation: - * - the list of positional arguments - * - the map of named arguments, indexed by normalized names - * - the set of names used in the arguments (that's an array using the normalized names as keys for O(1) access) - * - the separator used by the list using the splat operator, if any - * - a boolean indicator whether any splat argument (list or map) was used, to support the incomplete error reporting. - * - * @param array[] $args - * @param bool $reduce Whether arguments should be reduced to their value - * - * @return array - * - * @throws SassScriptException - * - * @phpstan-return array{0: list<array|Number>, 1: array<string, array|Number>, 2: array<string, string>, 3: string|null, 4: bool} - */ - private function evaluateArguments(array $args, $reduce = true) - { - // this represents trailing commas - if (\count($args) && end($args) === static::$null) { - array_pop($args); - } - - $splatSeparator = null; - $keywordArgs = []; - $names = []; - $positionalArgs = []; - $hasKeywordArgument = false; - $hasSplat = false; - - foreach ($args as $arg) { - if (!empty($arg[0])) { - $hasKeywordArgument = true; - - assert(\is_string($arg[0][1])); - $name = str_replace('_', '-', $arg[0][1]); - - if (isset($keywordArgs[$name])) { - throw new SassScriptException(sprintf('Duplicate named argument $%s.', $arg[0][1])); - } - - $keywordArgs[$name] = $this->maybeReduce($reduce, $arg[1]); - $names[$name] = $name; - } elseif (! empty($arg[2])) { - // $arg[2] means a var followed by ... in the arg ($list... ) - $val = $this->reduce($arg[1], true); - $hasSplat = true; - - if ($val[0] === Type::T_LIST) { - foreach ($val[2] as $item) { - if (\is_null($splatSeparator)) { - $splatSeparator = $val[1]; - } - - $positionalArgs[] = $this->maybeReduce($reduce, $item); - } - - if (isset($val[3]) && \is_array($val[3])) { - foreach ($val[3] as $name => $item) { - assert(\is_string($name)); - - $normalizedName = str_replace('_', '-', $name); - - if (isset($keywordArgs[$normalizedName])) { - throw new SassScriptException(sprintf('Duplicate named argument $%s.', $name)); - } - - $keywordArgs[$normalizedName] = $this->maybeReduce($reduce, $item); - $names[$normalizedName] = $normalizedName; - $hasKeywordArgument = true; - } - } - } elseif ($val[0] === Type::T_MAP) { - foreach ($val[1] as $i => $name) { - $name = $this->compileStringContent($this->coerceString($name)); - $item = $val[2][$i]; - - if (! is_numeric($name)) { - $normalizedName = str_replace('_', '-', $name); - - if (isset($keywordArgs[$normalizedName])) { - throw new SassScriptException(sprintf('Duplicate named argument $%s.', $name)); - } - - $keywordArgs[$normalizedName] = $this->maybeReduce($reduce, $item); - $names[$normalizedName] = $normalizedName; - $hasKeywordArgument = true; - } else { - if (\is_null($splatSeparator)) { - $splatSeparator = $val[1]; - } - - $positionalArgs[] = $this->maybeReduce($reduce, $item); - } - } - } elseif ($val[0] !== Type::T_NULL) { // values other than null are treated a single-element lists, while null is the empty list - $positionalArgs[] = $this->maybeReduce($reduce, $val); - } - } elseif ($hasKeywordArgument) { - throw new SassScriptException('Positional arguments must come before keyword arguments.'); - } else { - $positionalArgs[] = $this->maybeReduce($reduce, $arg[1]); - } - } - - return [$positionalArgs, $keywordArgs, $names, $splatSeparator, $hasSplat]; - } - - /** - * @param bool $reduce - * @param array|Number $value - * - * @return array|Number - */ - private function maybeReduce($reduce, $value) - { - if ($reduce) { - return $this->reduce($value, true); - } - - return $value; - } - - /** - * Apply argument values per definition - * - * @param array[] $argDef - * @param array|null $argValues - * @param bool $storeInEnv - * @param bool $reduce only used if $storeInEnv = false - * - * @return array<string, array|Number> - * - * @phpstan-param list<array{0: string, 1: array|Number|null, 2: bool}> $argDef - * - * @throws \Exception - */ - protected function applyArguments($argDef, $argValues, $storeInEnv = true, $reduce = true) - { - $output = []; - - if (\is_null($argValues)) { - $argValues = []; - } - - if ($storeInEnv) { - $storeEnv = $this->getStoreEnv(); - - $env = new Environment(); - $env->store = $storeEnv->store; - } - - $prototype = ['arguments' => [], 'rest_argument' => null]; - $originalRestArgumentName = null; - - foreach ($argDef as $arg) { - list($name, $default, $isVariable) = $arg; - $normalizedName = str_replace('_', '-', $name); - - if ($isVariable) { - $originalRestArgumentName = $name; - $prototype['rest_argument'] = $normalizedName; - } else { - $prototype['arguments'][] = [$normalizedName, $name, !empty($default) ? $default : null]; - } - } - - list($positionalArgs, $namedArgs, $names, $splatSeparator, $hasSplat) = $this->evaluateArguments($argValues, $reduce); - - $this->verifyPrototype($prototype, \count($positionalArgs), $names, $hasSplat); - - $vars = $this->applyArgumentsToDeclaration($prototype, $positionalArgs, $namedArgs, $splatSeparator); - - foreach ($prototype['arguments'] as $argument) { - list($normalizedName, $name) = $argument; - - if (!isset($vars[$normalizedName])) { - continue; - } - - $val = $vars[$normalizedName]; - - if ($storeInEnv) { - $this->set($name, $this->reduce($val, true), true, $env); - } else { - $output[$name] = ($reduce ? $this->reduce($val, true) : $val); - } - } - - if ($prototype['rest_argument'] !== null) { - assert($originalRestArgumentName !== null); - $name = $originalRestArgumentName; - $val = $vars[$prototype['rest_argument']]; - - if ($storeInEnv) { - $this->set($name, $this->reduce($val, true), true, $env); - } else { - $output[$name] = ($reduce ? $this->reduce($val, true) : $val); - } - } - - if ($storeInEnv) { - $storeEnv->store = $env->store; - } - - foreach ($prototype['arguments'] as $argument) { - list($normalizedName, $name, $default) = $argument; - - if (isset($vars[$normalizedName])) { - continue; - } - assert($default !== null); - - if ($storeInEnv) { - $this->set($name, $this->reduce($default, true), true); - } else { - $output[$name] = ($reduce ? $this->reduce($default, true) : $default); - } - } - - return $output; - } - - /** - * Apply argument values per definition. - * - * This method assumes that the arguments are valid for the provided prototype. - * The validation with {@see verifyPrototype} must have been run before calling - * it. - * Arguments are returned as a map from the normalized argument names to the - * value. Additional arguments are collected in a sass argument list available - * under the name of the rest argument in the result. - * - * Defaults are not applied as they are resolved in a different environment. - * - * @param array $prototype - * @param array<array|Number> $positionalArgs - * @param array<string, array|Number> $namedArgs - * @param string|null $splatSeparator - * - * @return array<string, array|Number> - * - * @phpstan-param array{arguments: list<array{0: string, 1: string, 2: array|Number|null}>, rest_argument: string|null} $prototype - */ - private function applyArgumentsToDeclaration(array $prototype, array $positionalArgs, array $namedArgs, $splatSeparator) - { - $output = []; - $minLength = min(\count($positionalArgs), \count($prototype['arguments'])); - - for ($i = 0; $i < $minLength; $i++) { - list($name) = $prototype['arguments'][$i]; - $val = $positionalArgs[$i]; - - $output[$name] = $val; - } - - $restNamed = $namedArgs; - - for ($i = \count($positionalArgs); $i < \count($prototype['arguments']); $i++) { - $argument = $prototype['arguments'][$i]; - list($name) = $argument; - - if (isset($namedArgs[$name])) { - $val = $namedArgs[$name]; - unset($restNamed[$name]); - } else { - continue; - } - - $output[$name] = $val; - } - - if ($prototype['rest_argument'] !== null) { - $name = $prototype['rest_argument']; - $rest = array_values(array_slice($positionalArgs, \count($prototype['arguments']))); - - $val = [Type::T_LIST, \is_null($splatSeparator) ? ',' : $splatSeparator , $rest, $restNamed]; - - $output[$name] = $val; - } - - return $output; - } - - /** - * Coerce a php value into a scss one - * - * @param mixed $value - * - * @return array|Number - */ - protected function coerceValue($value) - { - if (\is_array($value) || $value instanceof Number) { - return $value; - } - - if (\is_bool($value)) { - return $this->toBool($value); - } - - if (\is_null($value)) { - return static::$null; - } - - if (is_numeric($value)) { - return new Number($value, ''); - } - - if ($value === '') { - return static::$emptyString; - } - - $value = [Type::T_KEYWORD, $value]; - $color = $this->coerceColor($value); - - if ($color) { - return $color; - } - - return $value; - } - - /** - * Tries to convert an item to a Sass map - * - * @param Number|array $item - * - * @return array|null - */ - private function tryMap($item) - { - if ($item instanceof Number) { - return null; - } - - if ($item[0] === Type::T_MAP) { - return $item; - } - - if ( - $item[0] === Type::T_LIST && - $item[2] === [] - ) { - return static::$emptyMap; - } - - return null; - } - - /** - * Coerce something to map - * - * @param array|Number $item - * - * @return array|Number - */ - protected function coerceMap($item) - { - $map = $this->tryMap($item); - - if ($map !== null) { - return $map; - } - - return $item; - } - - /** - * Coerce something to list - * - * @param array|Number $item - * @param string $delim - * @param bool $removeTrailingNull - * - * @return array - */ - protected function coerceList($item, $delim = ',', $removeTrailingNull = false) - { - if ($item instanceof Number) { - return [Type::T_LIST, '', [$item]]; - } - - if ($item[0] === Type::T_LIST) { - // remove trailing null from the list - if ($removeTrailingNull && end($item[2]) === static::$null) { - array_pop($item[2]); - } - - return $item; - } - - if ($item[0] === Type::T_MAP) { - $keys = $item[1]; - $values = $item[2]; - $list = []; - - for ($i = 0, $s = \count($keys); $i < $s; $i++) { - $key = $keys[$i]; - $value = $values[$i]; - - $list[] = [ - Type::T_LIST, - ' ', - [$key, $value] - ]; - } - - return [Type::T_LIST, $list ? ',' : '', $list]; - } - - return [Type::T_LIST, '', [$item]]; - } - - /** - * Coerce color for expression - * - * @param array|Number $value - * - * @return array|Number - */ - protected function coerceForExpression($value) - { - if ($color = $this->coerceColor($value)) { - return $color; - } - - return $value; - } - - /** - * Coerce value to color - * - * @param array|Number $value - * @param bool $inRGBFunction - * - * @return array|null - */ - protected function coerceColor($value, $inRGBFunction = false) - { - if ($value instanceof Number) { - return null; - } - - switch ($value[0]) { - case Type::T_COLOR: - for ($i = 1; $i <= 3; $i++) { - if (! is_numeric($value[$i])) { - $cv = $this->compileRGBAValue($value[$i]); - - if (! is_numeric($cv)) { - return null; - } - - $value[$i] = $cv; - } - - if (isset($value[4])) { - if (! is_numeric($value[4])) { - $cv = $this->compileRGBAValue($value[4], true); - - if (! is_numeric($cv)) { - return null; - } - - $value[4] = $cv; - } - } - } - - return $value; - - case Type::T_LIST: - if ($inRGBFunction) { - if (\count($value[2]) == 3 || \count($value[2]) == 4) { - $color = $value[2]; - array_unshift($color, Type::T_COLOR); - - return $this->coerceColor($color); - } - } - - return null; - - case Type::T_KEYWORD: - if (! \is_string($value[1])) { - return null; - } - - $name = strtolower($value[1]); - - // hexa color? - if (preg_match('/^#([0-9a-f]+)$/i', $name, $m)) { - $nofValues = \strlen($m[1]); - - if (\in_array($nofValues, [3, 4, 6, 8])) { - $nbChannels = 3; - $color = []; - $num = hexdec($m[1]); - - switch ($nofValues) { - case 4: - $nbChannels = 4; - // then continuing with the case 3: - case 3: - for ($i = 0; $i < $nbChannels; $i++) { - $t = $num & 0xf; - array_unshift($color, $t << 4 | $t); - $num >>= 4; - } - - break; - - case 8: - $nbChannels = 4; - // then continuing with the case 6: - case 6: - for ($i = 0; $i < $nbChannels; $i++) { - array_unshift($color, $num & 0xff); - $num >>= 8; - } - - break; - } - - if ($nbChannels === 4) { - if ($color[3] === 255) { - $color[3] = 1; // fully opaque - } else { - $color[3] = round($color[3] / 255, Number::PRECISION); - } - } - - array_unshift($color, Type::T_COLOR); - - return $color; - } - } - - if ($rgba = Colors::colorNameToRGBa($name)) { - return isset($rgba[3]) - ? [Type::T_COLOR, $rgba[0], $rgba[1], $rgba[2], $rgba[3]] - : [Type::T_COLOR, $rgba[0], $rgba[1], $rgba[2]]; - } - - return null; - } - - return null; - } - - /** - * @param int|Number $value - * @param bool $isAlpha - * - * @return int|mixed - */ - protected function compileRGBAValue($value, $isAlpha = false) - { - if ($isAlpha) { - return $this->compileColorPartValue($value, 0, 1, false); - } - - return $this->compileColorPartValue($value, 0, 255, true); - } - - /** - * @param mixed $value - * @param int|float $min - * @param int|float $max - * @param bool $isInt - * - * @return int|mixed - */ - protected function compileColorPartValue($value, $min, $max, $isInt = true) - { - if (! is_numeric($value)) { - if (\is_array($value)) { - $reduced = $this->reduce($value); - - if ($reduced instanceof Number) { - $value = $reduced; - } - } - - if ($value instanceof Number) { - if ($value->unitless()) { - $num = $value->getDimension(); - } elseif ($value->hasUnit('%')) { - $num = $max * $value->getDimension() / 100; - } else { - throw $this->error('Expected %s to have no units or "%%".', $value); - } - - $value = $num; - } elseif (\is_array($value)) { - $value = $this->compileValue($value); - } - } - - if (is_numeric($value)) { - if ($isInt) { - $value = round($value); - } - - $value = min($max, max($min, $value)); - - return $value; - } - - return $value; - } - - /** - * Coerce value to string - * - * @param array|Number $value - * - * @return array - */ - protected function coerceString($value) - { - if ($value[0] === Type::T_STRING) { - assert(\is_array($value)); - - return $value; - } - - return [Type::T_STRING, '', [$this->compileValue($value)]]; - } - - /** - * Assert value is a string - * - * This method deals with internal implementation details of the value - * representation where unquoted strings can sometimes be stored under - * other types. - * The returned value is always using the T_STRING type. - * - * @api - * - * @param array|Number $value - * @param string|null $varName - * - * @return array - * - * @throws SassScriptException - */ - public function assertString($value, $varName = null) - { - // case of url(...) parsed a a function - if ($value[0] === Type::T_FUNCTION) { - $value = $this->coerceString($value); - } - - if (! \in_array($value[0], [Type::T_STRING, Type::T_KEYWORD])) { - $value = $this->compileValue($value); - throw SassScriptException::forArgument("$value is not a string.", $varName); - } - - return $this->coerceString($value); - } - - /** - * Coerce value to a percentage - * - * @param array|Number $value - * - * @return int|float - * - * @deprecated - */ - protected function coercePercent($value) - { - @trigger_error(sprintf('"%s" is deprecated since 1.7.0.', __METHOD__), E_USER_DEPRECATED); - - if ($value instanceof Number) { - if ($value->hasUnit('%')) { - return $value->getDimension() / 100; - } - - return $value->getDimension(); - } - - return 0; - } - - /** - * Assert value is a map - * - * @api - * - * @param array|Number $value - * @param string|null $varName - * - * @return array - * - * @throws SassScriptException - */ - public function assertMap($value, $varName = null) - { - $map = $this->tryMap($value); - - if ($map === null) { - $value = $this->compileValue($value); - - throw SassScriptException::forArgument("$value is not a map.", $varName); - } - - return $map; - } - - /** - * Assert value is a list - * - * @api - * - * @param array|Number $value - * - * @return array - * - * @throws \Exception - */ - public function assertList($value) - { - if ($value[0] !== Type::T_LIST) { - throw $this->error('expecting list, %s received', $value[0]); - } - assert(\is_array($value)); - - return $value; - } - - /** - * Gets the keywords of an argument list. - * - * Keys in the returned array are normalized names (underscores are replaced with dashes) - * without the leading `$`. - * Calling this helper with anything that an argument list received for a rest argument - * of the function argument declaration is not supported. - * - * @param array|Number $value - * - * @return array<string, array|Number> - */ - public function getArgumentListKeywords($value) - { - if ($value[0] !== Type::T_LIST || !isset($value[3]) || !\is_array($value[3])) { - throw new \InvalidArgumentException('The argument is not a sass argument list.'); - } - - return $value[3]; - } - - /** - * Assert value is a color - * - * @api - * - * @param array|Number $value - * @param string|null $varName - * - * @return array - * - * @throws SassScriptException - */ - public function assertColor($value, $varName = null) - { - if ($color = $this->coerceColor($value)) { - return $color; - } - - $value = $this->compileValue($value); - - throw SassScriptException::forArgument("$value is not a color.", $varName); - } - - /** - * Assert value is a number - * - * @api - * - * @param array|Number $value - * @param string|null $varName - * - * @return Number - * - * @throws SassScriptException - */ - public function assertNumber($value, $varName = null) - { - if (!$value instanceof Number) { - $value = $this->compileValue($value); - throw SassScriptException::forArgument("$value is not a number.", $varName); - } - - return $value; - } - - /** - * Assert value is a integer - * - * @api - * - * @param array|Number $value - * @param string|null $varName - * - * @return int - * - * @throws SassScriptException - */ - public function assertInteger($value, $varName = null) - { - $value = $this->assertNumber($value, $varName)->getDimension(); - if (round($value - \intval($value), Number::PRECISION) > 0) { - throw SassScriptException::forArgument("$value is not an integer.", $varName); - } - - return intval($value); - } - - /** - * Extract the ... / alpha on the last argument of channel arg - * in color functions - * - * @param array $args - * @return array - */ - private function extractSlashAlphaInColorFunction($args) - { - $last = end($args); - if (\count($args) === 3 && $last[0] === Type::T_EXPRESSION && $last[1] === '/') { - array_pop($args); - $args[] = $last[2]; - $args[] = $last[3]; - } - return $args; - } - - - /** - * Make sure a color's components don't go out of bounds - * - * @param array $c - * - * @return array - */ - protected function fixColor($c) - { - foreach ([1, 2, 3] as $i) { - if ($c[$i] < 0) { - $c[$i] = 0; - } - - if ($c[$i] > 255) { - $c[$i] = 255; - } - - if (!\is_int($c[$i])) { - $c[$i] = round($c[$i]); - } - } - - return $c; - } - - /** - * Convert RGB to HSL - * - * @internal - * - * @param int $red - * @param int $green - * @param int $blue - * - * @return array - */ - public function toHSL($red, $green, $blue) - { - $min = min($red, $green, $blue); - $max = max($red, $green, $blue); - - $l = $min + $max; - $d = $max - $min; - - if ((int) $d === 0) { - $h = $s = 0; - } else { - if ($l < 255) { - $s = $d / $l; - } else { - $s = $d / (510 - $l); - } - - if ($red == $max) { - $h = 60 * ($green - $blue) / $d; - } elseif ($green == $max) { - $h = 60 * ($blue - $red) / $d + 120; - } else { - $h = 60 * ($red - $green) / $d + 240; - } - } - - return [Type::T_HSL, fmod($h + 360, 360), $s * 100, $l / 5.1]; - } - - /** - * Hue to RGB helper - * - * @param float $m1 - * @param float $m2 - * @param float $h - * - * @return float - */ - protected function hueToRGB($m1, $m2, $h) - { - if ($h < 0) { - $h += 1; - } elseif ($h > 1) { - $h -= 1; - } - - if ($h * 6 < 1) { - return $m1 + ($m2 - $m1) * $h * 6; - } - - if ($h * 2 < 1) { - return $m2; - } - - if ($h * 3 < 2) { - return $m1 + ($m2 - $m1) * (2 / 3 - $h) * 6; - } - - return $m1; - } - - /** - * Convert HSL to RGB - * - * @internal - * - * @param int|float $hue H from 0 to 360 - * @param int|float $saturation S from 0 to 100 - * @param int|float $lightness L from 0 to 100 - * - * @return array - */ - public function toRGB($hue, $saturation, $lightness) - { - if ($hue < 0) { - $hue += 360; - } - - $h = $hue / 360; - $s = min(100, max(0, $saturation)) / 100; - $l = min(100, max(0, $lightness)) / 100; - - $m2 = $l <= 0.5 ? $l * ($s + 1) : $l + $s - $l * $s; - $m1 = $l * 2 - $m2; - - $r = $this->hueToRGB($m1, $m2, $h + 1 / 3) * 255; - $g = $this->hueToRGB($m1, $m2, $h) * 255; - $b = $this->hueToRGB($m1, $m2, $h - 1 / 3) * 255; - - $out = [Type::T_COLOR, $r, $g, $b]; - - return $out; - } - - /** - * Convert HWB to RGB - * https://www.w3.org/TR/css-color-4/#hwb-to-rgb - * - * @api - * - * @param int|float $hue H from 0 to 360 - * @param int|float $whiteness W from 0 to 100 - * @param int|float $blackness B from 0 to 100 - * - * @return array - */ - private function HWBtoRGB($hue, $whiteness, $blackness) - { - $w = min(100, max(0, $whiteness)) / 100; - $b = min(100, max(0, $blackness)) / 100; - - $sum = $w + $b; - if ($sum > 1.0) { - $w = $w / $sum; - $b = $b / $sum; - } - $b = min(1.0 - $w, $b); - - $rgb = $this->toRGB($hue, 100, 50); - for($i = 1; $i < 4; $i++) { - $rgb[$i] *= (1.0 - $w - $b); - $rgb[$i] = round($rgb[$i] + 255 * $w + 0.0001); - } - - return $rgb; - } - - /** - * Convert RGB to HWB - * - * @api - * - * @param int $red - * @param int $green - * @param int $blue - * - * @return array - */ - private function RGBtoHWB($red, $green, $blue) - { - $min = min($red, $green, $blue); - $max = max($red, $green, $blue); - - $d = $max - $min; - - if ((int) $d === 0) { - $h = 0; - } else { - - if ($red == $max) { - $h = 60 * ($green - $blue) / $d; - } elseif ($green == $max) { - $h = 60 * ($blue - $red) / $d + 120; - } else { - $h = 60 * ($red - $green) / $d + 240; - } - } - - return [Type::T_HWB, fmod($h, 360), $min / 255 * 100, 100 - $max / 255 *100]; - } - - - // Built in functions - - protected static $libCall = ['function', 'args...']; - protected function libCall($args) - { - $functionReference = $args[0]; - - if (in_array($functionReference[0], [Type::T_STRING, Type::T_KEYWORD])) { - $name = $this->compileStringContent($this->coerceString($functionReference)); - $warning = "Passing a string to call() is deprecated and will be illegal\n" - . "in Sass 4.0. Use call(function-reference($name)) instead."; - Warn::deprecation($warning); - $functionReference = $this->libGetFunction([$this->assertString($functionReference, 'function')]); - } - - if ($functionReference === static::$null) { - return static::$null; - } - - if (! in_array($functionReference[0], [Type::T_FUNCTION_REFERENCE, Type::T_FUNCTION])) { - throw $this->error('Function reference expected, got ' . $functionReference[0]); - } - - $callArgs = [ - [null, $args[1], true] - ]; - - return $this->reduce([Type::T_FUNCTION_CALL, $functionReference, $callArgs]); - } - - - protected static $libGetFunction = [ - ['name'], - ['name', 'css'] - ]; - protected function libGetFunction($args) - { - $name = $this->compileStringContent($this->assertString(array_shift($args), 'name')); - $isCss = false; - - if (count($args)) { - $isCss = array_shift($args); - $isCss = (($isCss === static::$true) ? true : false); - } - - if ($isCss) { - return [Type::T_FUNCTION, $name, [Type::T_LIST, ',', []]]; - } - - return $this->getFunctionReference($name, true); - } - - protected static $libIf = ['condition', 'if-true', 'if-false:']; - protected function libIf($args) - { - list($cond, $t, $f) = $args; - - if (! $this->isTruthy($this->reduce($cond, true))) { - return $this->reduce($f, true); - } - - return $this->reduce($t, true); - } - - protected static $libIndex = ['list', 'value']; - protected function libIndex($args) - { - list($list, $value) = $args; - - if ( - $list[0] === Type::T_MAP || - $list[0] === Type::T_STRING || - $list[0] === Type::T_KEYWORD || - $list[0] === Type::T_INTERPOLATE - ) { - $list = $this->coerceList($list, ' '); - } - - if ($list[0] !== Type::T_LIST) { - return static::$null; - } - - // Numbers are represented with value objects, for which the PHP equality operator does not - // match the Sass rules (and we cannot overload it). As they are the only type of values - // represented with a value object for now, they require a special case. - if ($value instanceof Number) { - $key = 0; - foreach ($list[2] as $item) { - $key++; - $itemValue = $this->normalizeValue($item); - - if ($itemValue instanceof Number && $value->equals($itemValue)) { - return new Number($key, ''); - } - } - return static::$null; - } - - $values = []; - - foreach ($list[2] as $item) { - $values[] = $this->normalizeValue($item); - } - - $key = array_search($this->normalizeValue($value), $values); - - return false === $key ? static::$null : new Number($key + 1, ''); - } - - protected static $libRgb = [ - ['color'], - ['color', 'alpha'], - ['channels'], - ['red', 'green', 'blue'], - ['red', 'green', 'blue', 'alpha'] ]; - - /** - * @param array $args - * @param array $kwargs - * @param string $funcName - * - * @return array - */ - protected function libRgb($args, $kwargs, $funcName = 'rgb') - { - switch (\count($args)) { - case 1: - if (! $color = $this->coerceColor($args[0], true)) { - $color = [Type::T_STRING, '', [$funcName . '(', $args[0], ')']]; - } - break; - - case 3: - $color = [Type::T_COLOR, $args[0], $args[1], $args[2]]; - - if (! $color = $this->coerceColor($color)) { - $color = [Type::T_STRING, '', [$funcName . '(', $args[0], ', ', $args[1], ', ', $args[2], ')']]; - } - - return $color; - - case 2: - if ($color = $this->coerceColor($args[0], true)) { - $alpha = $this->compileRGBAValue($args[1], true); - - if (is_numeric($alpha)) { - $color[4] = $alpha; - } else { - $color = [Type::T_STRING, '', - [$funcName . '(', $color[1], ', ', $color[2], ', ', $color[3], ', ', $alpha, ')']]; - } - } else { - $color = [Type::T_STRING, '', [$funcName . '(', $args[0], ', ', $args[1], ')']]; - } - break; - - case 4: - default: - $color = [Type::T_COLOR, $args[0], $args[1], $args[2], $args[3]]; - - if (! $color = $this->coerceColor($color)) { - $color = [Type::T_STRING, '', - [$funcName . '(', $args[0], ', ', $args[1], ', ', $args[2], ', ', $args[3], ')']]; - } - break; - } - - return $color; - } - - protected static $libRgba = [ - ['color'], - ['color', 'alpha'], - ['channels'], - ['red', 'green', 'blue'], - ['red', 'green', 'blue', 'alpha'] ]; - protected function libRgba($args, $kwargs) - { - return $this->libRgb($args, $kwargs, 'rgba'); - } - - /** - * Helper function for adjust_color, change_color, and scale_color - * - * @param array<array|Number> $args - * @param string $operation - * @param callable $fn - * - * @return array - * - * @phpstan-param callable(float|int, float|int|null, float|int): (float|int) $fn - */ - protected function alterColor(array $args, $operation, $fn) - { - $color = $this->assertColor($args[0], 'color'); - - if ($args[1][2]) { - throw new SassScriptException('Only one positional argument is allowed. All other arguments must be passed by name.'); - } - - $kwargs = $this->getArgumentListKeywords($args[1]); - - $scale = $operation === 'scale'; - $change = $operation === 'change'; - - /** @phpstan-var callable(string, float|int, bool=, bool=): (float|int|null) $getParam */ - $getParam = function ($name, $max, $checkPercent = false, $assertPercent = false) use (&$kwargs, $scale, $change) { - if (!isset($kwargs[$name])) { - return null; - } - - $number = $this->assertNumber($kwargs[$name], $name); - unset($kwargs[$name]); - - if (!$scale && $checkPercent) { - if (!$number->hasUnit('%')) { - $warning = $this->error("{$name} Passing a number `$number` without unit % is deprecated."); - $this->logger->warn($warning->getMessage(), true); - } - } - - if ($scale || $assertPercent) { - $number->assertUnit('%', $name); - } - - if ($scale) { - $max = 100; - } - - return $number->valueInRange($change ? 0 : -$max, $max, $name); - }; - - $alpha = $getParam('alpha', 1); - $red = $getParam('red', 255); - $green = $getParam('green', 255); - $blue = $getParam('blue', 255); - - if ($scale || !isset($kwargs['hue'])) { - $hue = null; - } else { - $hueNumber = $this->assertNumber($kwargs['hue'], 'hue'); - unset($kwargs['hue']); - $hue = $hueNumber->getDimension(); - } - $saturation = $getParam('saturation', 100, true); - $lightness = $getParam('lightness', 100, true); - $whiteness = $getParam('whiteness', 100, false, true); - $blackness = $getParam('blackness', 100, false, true); - - if (!empty($kwargs)) { - $unknownNames = array_keys($kwargs); - $lastName = array_pop($unknownNames); - $message = sprintf( - 'No argument%s named $%s%s.', - $unknownNames ? 's' : '', - $unknownNames ? implode(', $', $unknownNames) . ' or $' : '', - $lastName - ); - throw new SassScriptException($message); - } - - $hasRgb = $red !== null || $green !== null || $blue !== null; - $hasSL = $saturation !== null || $lightness !== null; - $hasWB = $whiteness !== null || $blackness !== null; - - if ($hasRgb && ($hasSL || $hasWB || $hue !== null)) { - throw new SassScriptException(sprintf('RGB parameters may not be passed along with %s parameters.', $hasWB ? 'HWB' : 'HSL')); - } - - if ($hasWB && $hasSL) { - throw new SassScriptException('HSL parameters may not be passed along with HWB parameters.'); - } - - if ($hasRgb) { - $color[1] = round($fn($color[1], $red, 255)); - $color[2] = round($fn($color[2], $green, 255)); - $color[3] = round($fn($color[3], $blue, 255)); - } elseif ($hasWB) { - $hwb = $this->RGBtoHWB($color[1], $color[2], $color[3]); - if ($hue !== null) { - $hwb[1] = $change ? $hue : $hwb[1] + $hue; - } - $hwb[2] = $fn($hwb[2], $whiteness, 100); - $hwb[3] = $fn($hwb[3], $blackness, 100); - - $rgb = $this->HWBtoRGB($hwb[1], $hwb[2], $hwb[3]); - - if (isset($color[4])) { - $rgb[4] = $color[4]; - } - - $color = $rgb; - } elseif ($hue !== null || $hasSL) { - $hsl = $this->toHSL($color[1], $color[2], $color[3]); - - if ($hue !== null) { - $hsl[1] = $change ? $hue : $hsl[1] + $hue; - } - $hsl[2] = $fn($hsl[2], $saturation, 100); - $hsl[3] = $fn($hsl[3], $lightness, 100); - - $rgb = $this->toRGB($hsl[1], $hsl[2], $hsl[3]); - - if (isset($color[4])) { - $rgb[4] = $color[4]; - } - - $color = $rgb; - } - - if ($alpha !== null) { - $existingAlpha = isset($color[4]) ? $color[4] : 1; - $color[4] = $fn($existingAlpha, $alpha, 1); - } - - return $color; - } - - protected static $libAdjustColor = ['color', 'kwargs...']; - protected function libAdjustColor($args) - { - return $this->alterColor($args, 'adjust', function ($base, $alter, $max) { - if ($alter === null) { - return $base; - } - - $new = $base + $alter; - - if ($new < 0) { - return 0; - } - - if ($new > $max) { - return $max; - } - - return $new; - }); - } - - protected static $libChangeColor = ['color', 'kwargs...']; - protected function libChangeColor($args) - { - return $this->alterColor($args,'change', function ($base, $alter, $max) { - if ($alter === null) { - return $base; - } - - return $alter; - }); - } - - protected static $libScaleColor = ['color', 'kwargs...']; - protected function libScaleColor($args) - { - return $this->alterColor($args, 'scale', function ($base, $scale, $max) { - if ($scale === null) { - return $base; - } - - $scale = $scale / 100; - - if ($scale < 0) { - return $base * $scale + $base; - } - - return ($max - $base) * $scale + $base; - }); - } - - protected static $libIeHexStr = ['color']; - protected function libIeHexStr($args) - { - $color = $this->coerceColor($args[0]); - - if (\is_null($color)) { - throw $this->error('Error: argument `$color` of `ie-hex-str($color)` must be a color'); - } - - $color[4] = isset($color[4]) ? round(255 * $color[4]) : 255; - - return [Type::T_STRING, '', [sprintf('#%02X%02X%02X%02X', $color[4], $color[1], $color[2], $color[3])]]; - } - - protected static $libRed = ['color']; - protected function libRed($args) - { - $color = $this->coerceColor($args[0]); - - if (\is_null($color)) { - throw $this->error('Error: argument `$color` of `red($color)` must be a color'); - } - - return new Number((int) $color[1], ''); - } - - protected static $libGreen = ['color']; - protected function libGreen($args) - { - $color = $this->coerceColor($args[0]); - - if (\is_null($color)) { - throw $this->error('Error: argument `$color` of `green($color)` must be a color'); - } - - return new Number((int) $color[2], ''); - } - - protected static $libBlue = ['color']; - protected function libBlue($args) - { - $color = $this->coerceColor($args[0]); - - if (\is_null($color)) { - throw $this->error('Error: argument `$color` of `blue($color)` must be a color'); - } - - return new Number((int) $color[3], ''); - } - - protected static $libAlpha = ['color']; - protected function libAlpha($args) - { - if ($color = $this->coerceColor($args[0])) { - return new Number(isset($color[4]) ? $color[4] : 1, ''); - } - - // this might be the IE function, so return value unchanged - return null; - } - - protected static $libOpacity = ['color']; - protected function libOpacity($args) - { - $value = $args[0]; - - if ($value instanceof Number) { - return null; - } - - return $this->libAlpha($args); - } - - // mix two colors - protected static $libMix = [ - ['color1', 'color2', 'weight:50%'], - ['color-1', 'color-2', 'weight:50%'] - ]; - protected function libMix($args) - { - list($first, $second, $weight) = $args; - - $first = $this->assertColor($first, 'color1'); - $second = $this->assertColor($second, 'color2'); - $weightScale = $this->assertNumber($weight, 'weight')->valueInRange(0, 100, 'weight') / 100; - - $firstAlpha = isset($first[4]) ? $first[4] : 1; - $secondAlpha = isset($second[4]) ? $second[4] : 1; - - $normalizedWeight = $weightScale * 2 - 1; - $alphaDistance = $firstAlpha - $secondAlpha; - - $combinedWeight = $normalizedWeight * $alphaDistance == -1 ? $normalizedWeight : ($normalizedWeight + $alphaDistance) / (1 + $normalizedWeight * $alphaDistance); - $weight1 = ($combinedWeight + 1) / 2.0; - $weight2 = 1.0 - $weight1; - - $new = [Type::T_COLOR, - $weight1 * $first[1] + $weight2 * $second[1], - $weight1 * $first[2] + $weight2 * $second[2], - $weight1 * $first[3] + $weight2 * $second[3], - ]; - - if ($firstAlpha != 1.0 || $secondAlpha != 1.0) { - $new[] = $firstAlpha * $weightScale + $secondAlpha * (1 - $weightScale); - } - - return $this->fixColor($new); - } - - protected static $libHsl = [ - ['channels'], - ['hue', 'saturation'], - ['hue', 'saturation', 'lightness'], - ['hue', 'saturation', 'lightness', 'alpha'] ]; - - /** - * @param array $args - * @param array $kwargs - * @param string $funcName - * - * @return array|null - */ - protected function libHsl($args, $kwargs, $funcName = 'hsl') - { - $args_to_check = $args; - - if (\count($args) == 1) { - if ($args[0][0] !== Type::T_LIST || \count($args[0][2]) < 3 || \count($args[0][2]) > 4) { - return [Type::T_STRING, '', [$funcName . '(', $args[0], ')']]; - } - - $args = $args[0][2]; - $args_to_check = $kwargs['channels'][2]; - } - - if (\count($args) === 2) { - // if var() is used as an argument, return as a css function - foreach ($args as $arg) { - if ($arg[0] === Type::T_FUNCTION && in_array($arg[1], ['var'])) { - return null; - } - } - - throw new SassScriptException('Missing argument $lightness.'); - } - - foreach ($kwargs as $arg) { - if (in_array($arg[0], [Type::T_FUNCTION_CALL, Type::T_FUNCTION]) && in_array($arg[1], ['min', 'max'])) { - return null; - } - } - - foreach ($args_to_check as $k => $arg) { - if (in_array($arg[0], [Type::T_FUNCTION_CALL, Type::T_FUNCTION]) && in_array($arg[1], ['min', 'max'])) { - if (count($kwargs) > 1 || ($k >= 2 && count($args) === 4)) { - return null; - } - - $args[$k] = $this->stringifyFncallArgs($arg); - } - - if ( - $k >= 2 && count($args) === 4 && - in_array($arg[0], [Type::T_FUNCTION_CALL, Type::T_FUNCTION]) && - in_array($arg[1], ['calc','env']) - ) { - return null; - } - } - - $hue = $this->reduce($args[0]); - $saturation = $this->reduce($args[1]); - $lightness = $this->reduce($args[2]); - $alpha = null; - - if (\count($args) === 4) { - $alpha = $this->compileColorPartValue($args[3], 0, 100, false); - - if (!$hue instanceof Number || !$saturation instanceof Number || ! $lightness instanceof Number || ! is_numeric($alpha)) { - return [Type::T_STRING, '', - [$funcName . '(', $args[0], ', ', $args[1], ', ', $args[2], ', ', $args[3], ')']]; - } - } else { - if (!$hue instanceof Number || !$saturation instanceof Number || ! $lightness instanceof Number) { - return [Type::T_STRING, '', [$funcName . '(', $args[0], ', ', $args[1], ', ', $args[2], ')']]; - } - } - - $hueValue = fmod($hue->getDimension(), 360); - - while ($hueValue < 0) { - $hueValue += 360; - } - - $color = $this->toRGB($hueValue, max(0, min($saturation->getDimension(), 100)), max(0, min($lightness->getDimension(), 100))); - - if (! \is_null($alpha)) { - $color[4] = $alpha; - } - - return $color; - } - - protected static $libHsla = [ - ['channels'], - ['hue', 'saturation'], - ['hue', 'saturation', 'lightness'], - ['hue', 'saturation', 'lightness', 'alpha']]; - protected function libHsla($args, $kwargs) - { - return $this->libHsl($args, $kwargs, 'hsla'); - } - - protected static $libHue = ['color']; - protected function libHue($args) - { - $color = $this->assertColor($args[0], 'color'); - $hsl = $this->toHSL($color[1], $color[2], $color[3]); - - return new Number($hsl[1], 'deg'); - } - - protected static $libSaturation = ['color']; - protected function libSaturation($args) - { - $color = $this->assertColor($args[0], 'color'); - $hsl = $this->toHSL($color[1], $color[2], $color[3]); - - return new Number($hsl[2], '%'); - } - - protected static $libLightness = ['color']; - protected function libLightness($args) - { - $color = $this->assertColor($args[0], 'color'); - $hsl = $this->toHSL($color[1], $color[2], $color[3]); - - return new Number($hsl[3], '%'); - } - - /* - * Todo : a integrer dans le futur module color - protected static $libHwb = [ - ['channels'], - ['hue', 'whiteness', 'blackness'], - ['hue', 'whiteness', 'blackness', 'alpha'] ]; - protected function libHwb($args, $kwargs, $funcName = 'hwb') - { - $args_to_check = $args; - - if (\count($args) == 1) { - if ($args[0][0] !== Type::T_LIST) { - throw $this->error("Missing elements \$whiteness and \$blackness"); - } - - if (\trim($args[0][1])) { - throw $this->error("\$channels must be a space-separated list."); - } - - if (! empty($args[0]['enclosing'])) { - throw $this->error("\$channels must be an unbracketed list."); - } - - $args = $args[0][2]; - if (\count($args) > 3) { - throw $this->error("hwb() : Only 3 elements are allowed but ". \count($args) . "were passed"); - } - - $args_to_check = $this->extractSlashAlphaInColorFunction($kwargs['channels'][2]); - if (\count($args_to_check) !== \count($kwargs['channels'][2])) { - $args = $args_to_check; - } - } - - if (\count($args_to_check) < 2) { - throw $this->error("Missing elements \$whiteness and \$blackness"); - } - if (\count($args_to_check) < 3) { - throw $this->error("Missing element \$blackness"); - } - if (\count($args_to_check) > 4) { - throw $this->error("hwb() : Only 4 elements are allowed but ". \count($args) . "were passed"); - } - - foreach ($kwargs as $k => $arg) { - if (in_array($arg[0], [Type::T_FUNCTION_CALL]) && in_array($arg[1], ['min', 'max'])) { - return null; - } - } - - foreach ($args_to_check as $k => $arg) { - if (in_array($arg[0], [Type::T_FUNCTION_CALL]) && in_array($arg[1], ['min', 'max'])) { - if (count($kwargs) > 1 || ($k >= 2 && count($args) === 4)) { - return null; - } - - $args[$k] = $this->stringifyFncallArgs($arg); - } - - if ( - $k >= 2 && count($args) === 4 && - in_array($arg[0], [Type::T_FUNCTION_CALL, Type::T_FUNCTION]) && - in_array($arg[1], ['calc','env']) - ) { - return null; - } - } - - $hue = $this->reduce($args[0]); - $whiteness = $this->reduce($args[1]); - $blackness = $this->reduce($args[2]); - $alpha = null; - - if (\count($args) === 4) { - $alpha = $this->compileColorPartValue($args[3], 0, 1, false); - - if (! \is_numeric($alpha)) { - $val = $this->compileValue($args[3]); - throw $this->error("\$alpha: $val is not a number"); - } - } - - $this->assertNumber($hue, 'hue'); - $this->assertUnit($whiteness, ['%'], 'whiteness'); - $this->assertUnit($blackness, ['%'], 'blackness'); - - $this->assertRange($whiteness, 0, 100, "0% and 100%", "whiteness"); - $this->assertRange($blackness, 0, 100, "0% and 100%", "blackness"); - - $w = $whiteness->getDimension(); - $b = $blackness->getDimension(); - - $hueValue = $hue->getDimension() % 360; - - while ($hueValue < 0) { - $hueValue += 360; - } - - $color = $this->HWBtoRGB($hueValue, $w, $b); - - if (! \is_null($alpha)) { - $color[4] = $alpha; - } - - return $color; - } - - protected static $libWhiteness = ['color']; - protected function libWhiteness($args, $kwargs, $funcName = 'whiteness') { - - $color = $this->assertColor($args[0]); - $hwb = $this->RGBtoHWB($color[1], $color[2], $color[3]); - - return new Number($hwb[2], '%'); - } - - protected static $libBlackness = ['color']; - protected function libBlackness($args, $kwargs, $funcName = 'blackness') { - - $color = $this->assertColor($args[0]); - $hwb = $this->RGBtoHWB($color[1], $color[2], $color[3]); - - return new Number($hwb[3], '%'); - } - */ - - /** - * @param array $color - * @param int $idx - * @param int|float $amount - * - * @return array - */ - protected function adjustHsl($color, $idx, $amount) - { - $hsl = $this->toHSL($color[1], $color[2], $color[3]); - $hsl[$idx] += $amount; - - if ($idx !== 1) { - // Clamp the saturation and lightness - $hsl[$idx] = min(max(0, $hsl[$idx]), 100); - } - - $out = $this->toRGB($hsl[1], $hsl[2], $hsl[3]); - - if (isset($color[4])) { - $out[4] = $color[4]; - } - - return $out; - } - - protected static $libAdjustHue = ['color', 'degrees']; - protected function libAdjustHue($args) - { - $color = $this->assertColor($args[0], 'color'); - $degrees = $this->assertNumber($args[1], 'degrees')->getDimension(); - - return $this->adjustHsl($color, 1, $degrees); - } - - protected static $libLighten = ['color', 'amount']; - protected function libLighten($args) - { - $color = $this->assertColor($args[0], 'color'); - $amount = Util::checkRange('amount', new Range(0, 100), $args[1], '%'); - - return $this->adjustHsl($color, 3, $amount); - } - - protected static $libDarken = ['color', 'amount']; - protected function libDarken($args) - { - $color = $this->assertColor($args[0], 'color'); - $amount = Util::checkRange('amount', new Range(0, 100), $args[1], '%'); - - return $this->adjustHsl($color, 3, -$amount); - } - - protected static $libSaturate = [['color', 'amount'], ['amount']]; - protected function libSaturate($args) - { - $value = $args[0]; - - if (count($args) === 1) { - $this->assertNumber($args[0], 'amount'); - - return null; - } - - $color = $this->assertColor($args[0], 'color'); - $amount = $this->assertNumber($args[1], 'amount'); - - return $this->adjustHsl($color, 2, $amount->valueInRange(0, 100, 'amount')); - } - - protected static $libDesaturate = ['color', 'amount']; - protected function libDesaturate($args) - { - $color = $this->assertColor($args[0], 'color'); - $amount = $this->assertNumber($args[1], 'amount'); - - return $this->adjustHsl($color, 2, -$amount->valueInRange(0, 100, 'amount')); - } - - protected static $libGrayscale = ['color']; - protected function libGrayscale($args) - { - $value = $args[0]; - - if ($value instanceof Number) { - return null; - } - - return $this->adjustHsl($this->assertColor($value, 'color'), 2, -100); - } - - protected static $libComplement = ['color']; - protected function libComplement($args) - { - return $this->adjustHsl($this->assertColor($args[0], 'color'), 1, 180); - } - - protected static $libInvert = ['color', 'weight:100%']; - protected function libInvert($args) - { - $value = $args[0]; - - $weight = $this->assertNumber($args[1], 'weight'); - - if ($value instanceof Number) { - if ($weight->getDimension() != 100 || !$weight->hasUnit('%')) { - throw new SassScriptException('Only one argument may be passed to the plain-CSS invert() function.'); - } - - return null; - } - - $color = $this->assertColor($value, 'color'); - $inverted = $color; - $inverted[1] = 255 - $inverted[1]; - $inverted[2] = 255 - $inverted[2]; - $inverted[3] = 255 - $inverted[3]; - - return $this->libMix([$inverted, $color, $weight]); - } - - // increases opacity by amount - protected static $libOpacify = ['color', 'amount']; - protected function libOpacify($args) - { - $color = $this->assertColor($args[0], 'color'); - $amount = $this->assertNumber($args[1], 'amount'); - - $color[4] = (isset($color[4]) ? $color[4] : 1) + $amount->valueInRange(0, 1, 'amount'); - $color[4] = min(1, max(0, $color[4])); - - return $color; - } - - protected static $libFadeIn = ['color', 'amount']; - protected function libFadeIn($args) - { - return $this->libOpacify($args); - } - - // decreases opacity by amount - protected static $libTransparentize = ['color', 'amount']; - protected function libTransparentize($args) - { - $color = $this->assertColor($args[0], 'color'); - $amount = $this->assertNumber($args[1], 'amount'); - - $color[4] = (isset($color[4]) ? $color[4] : 1) - $amount->valueInRange(0, 1, 'amount'); - $color[4] = min(1, max(0, $color[4])); - - return $color; - } - - protected static $libFadeOut = ['color', 'amount']; - protected function libFadeOut($args) - { - return $this->libTransparentize($args); - } - - protected static $libUnquote = ['string']; - protected function libUnquote($args) - { - try { - $str = $this->assertString($args[0], 'string'); - } catch (SassScriptException $e) { - $value = $this->compileValue($args[0]); - $fname = $this->getPrettyPath($this->sourceNames[$this->sourceIndex]); - $line = $this->sourceLine; - - $message = "Passing $value, a non-string value, to unquote() -will be an error in future versions of Sass.\n on line $line of $fname"; - - $this->logger->warn($message, true); - - return $args[0]; - } - - $str[1] = ''; - - return $str; - } - - protected static $libQuote = ['string']; - protected function libQuote($args) - { - $value = $this->assertString($args[0], 'string'); - - $value[1] = '"'; - - return $value; - } - - protected static $libPercentage = ['number']; - protected function libPercentage($args) - { - $num = $this->assertNumber($args[0], 'number'); - $num->assertNoUnits('number'); - - return new Number($num->getDimension() * 100, '%'); - } - - protected static $libRound = ['number']; - protected function libRound($args) - { - $num = $this->assertNumber($args[0], 'number'); - - return new Number(round($num->getDimension()), $num->getNumeratorUnits(), $num->getDenominatorUnits()); - } - - protected static $libFloor = ['number']; - protected function libFloor($args) - { - $num = $this->assertNumber($args[0], 'number'); - - return new Number(floor($num->getDimension()), $num->getNumeratorUnits(), $num->getDenominatorUnits()); - } - - protected static $libCeil = ['number']; - protected function libCeil($args) - { - $num = $this->assertNumber($args[0], 'number'); - - return new Number(ceil($num->getDimension()), $num->getNumeratorUnits(), $num->getDenominatorUnits()); - } - - protected static $libAbs = ['number']; - protected function libAbs($args) - { - $num = $this->assertNumber($args[0], 'number'); - - return new Number(abs($num->getDimension()), $num->getNumeratorUnits(), $num->getDenominatorUnits()); - } - - protected static $libMin = ['numbers...']; - protected function libMin($args) - { - /** - * @var Number|null - */ - $min = null; - - foreach ($args[0][2] as $arg) { - $number = $this->assertNumber($arg); - - if (\is_null($min) || $min->greaterThan($number)) { - $min = $number; - } - } - - if (!\is_null($min)) { - return $min; - } - - throw $this->error('At least one argument must be passed.'); - } - - protected static $libMax = ['numbers...']; - protected function libMax($args) - { - /** - * @var Number|null - */ - $max = null; - - foreach ($args[0][2] as $arg) { - $number = $this->assertNumber($arg); - - if (\is_null($max) || $max->lessThan($number)) { - $max = $number; - } - } - - if (!\is_null($max)) { - return $max; - } - - throw $this->error('At least one argument must be passed.'); - } - - protected static $libLength = ['list']; - protected function libLength($args) - { - $list = $this->coerceList($args[0], ',', true); - - return new Number(\count($list[2]), ''); - } - - protected static $libListSeparator = ['list']; - protected function libListSeparator($args) - { - if (! \in_array($args[0][0], [Type::T_LIST, Type::T_MAP])) { - return [Type::T_KEYWORD, 'space']; - } - - $list = $this->coerceList($args[0]); - - if ($list[1] === '' && \count($list[2]) <= 1 && empty($list['enclosing'])) { - return [Type::T_KEYWORD, 'space']; - } - - if ($list[1] === ',') { - return [Type::T_KEYWORD, 'comma']; - } - - if ($list[1] === '/') { - return [Type::T_KEYWORD, 'slash']; - } - - return [Type::T_KEYWORD, 'space']; - } - - protected static $libNth = ['list', 'n']; - protected function libNth($args) - { - $list = $this->coerceList($args[0], ',', false); - $n = $this->assertInteger($args[1]); - - if ($n > 0) { - $n--; - } elseif ($n < 0) { - $n += \count($list[2]); - } - - return isset($list[2][$n]) ? $list[2][$n] : static::$defaultValue; - } - - protected static $libSetNth = ['list', 'n', 'value']; - protected function libSetNth($args) - { - $list = $this->coerceList($args[0]); - $n = $this->assertInteger($args[1]); - - if ($n > 0) { - $n--; - } elseif ($n < 0) { - $n += \count($list[2]); - } - - if (! isset($list[2][$n])) { - throw $this->error('Invalid argument for "n"'); - } - - $list[2][$n] = $args[2]; - - return $list; - } - - protected static $libMapGet = ['map', 'key', 'keys...']; - protected function libMapGet($args) - { - $map = $this->assertMap($args[0], 'map'); - if (!isset($args[2])) { - // BC layer for usages of the function from PHP code rather than from the Sass function - $args[2] = self::$emptyArgumentList; - } - $keys = array_merge([$args[1]], $args[2][2]); - $value = static::$null; - - foreach ($keys as $key) { - if (!\is_array($map) || $map[0] !== Type::T_MAP) { - return static::$null; - } - - $map = $this->mapGet($map, $key); - - if ($map === null) { - return static::$null; - } - - $value = $map; - } - - return $value; - } - - /** - * Gets the value corresponding to that key in the map - * - * @param array $map - * @param Number|array $key - * - * @return Number|array|null - */ - private function mapGet(array $map, $key) - { - $index = $this->mapGetEntryIndex($map, $key); - - if ($index !== null) { - return $map[2][$index]; - } - - return null; - } - - /** - * Gets the index corresponding to that key in the map entries - * - * @param array $map - * @param Number|array $key - * - * @return int|null - */ - private function mapGetEntryIndex(array $map, $key) - { - $key = $this->compileStringContent($this->coerceString($key)); - - for ($i = \count($map[1]) - 1; $i >= 0; $i--) { - if ($key === $this->compileStringContent($this->coerceString($map[1][$i]))) { - return $i; - } - } - - return null; - } - - protected static $libMapKeys = ['map']; - protected function libMapKeys($args) - { - $map = $this->assertMap($args[0], 'map'); - $keys = $map[1]; - - return [Type::T_LIST, ',', $keys]; - } - - protected static $libMapValues = ['map']; - protected function libMapValues($args) - { - $map = $this->assertMap($args[0], 'map'); - $values = $map[2]; - - return [Type::T_LIST, ',', $values]; - } - - protected static $libMapRemove = [ - ['map'], - ['map', 'key', 'keys...'], - ]; - protected function libMapRemove($args) - { - $map = $this->assertMap($args[0], 'map'); - - if (\count($args) === 1) { - return $map; - } - - $keys = []; - $keys[] = $this->compileStringContent($this->coerceString($args[1])); - - foreach ($args[2][2] as $key) { - $keys[] = $this->compileStringContent($this->coerceString($key)); - } - - for ($i = \count($map[1]) - 1; $i >= 0; $i--) { - if (in_array($this->compileStringContent($this->coerceString($map[1][$i])), $keys)) { - array_splice($map[1], $i, 1); - array_splice($map[2], $i, 1); - } - } - - return $map; - } - - protected static $libMapHasKey = ['map', 'key', 'keys...']; - protected function libMapHasKey($args) - { - $map = $this->assertMap($args[0], 'map'); - if (!isset($args[2])) { - // BC layer for usages of the function from PHP code rather than from the Sass function - $args[2] = self::$emptyArgumentList; - } - $keys = array_merge([$args[1]], $args[2][2]); - $lastKey = array_pop($keys); - - foreach ($keys as $key) { - $value = $this->mapGet($map, $key); - - if ($value === null || $value instanceof Number || $value[0] !== Type::T_MAP) { - return self::$false; - } - - $map = $value; - } - - return $this->toBool($this->mapHasKey($map, $lastKey)); - } - - /** - * @param array|Number $keyValue - * - * @return bool - */ - private function mapHasKey(array $map, $keyValue) - { - $key = $this->compileStringContent($this->coerceString($keyValue)); - - for ($i = \count($map[1]) - 1; $i >= 0; $i--) { - if ($key === $this->compileStringContent($this->coerceString($map[1][$i]))) { - return true; - } - } - - return false; - } - - protected static $libMapMerge = [ - ['map1', 'map2'], - ['map-1', 'map-2'], - ['map1', 'args...'] - ]; - protected function libMapMerge($args) - { - $map1 = $this->assertMap($args[0], 'map1'); - $map2 = $args[1]; - $keys = []; - if ($map2[0] === Type::T_LIST && isset($map2[3]) && \is_array($map2[3])) { - // This is an argument list for the variadic signature - if (\count($map2[2]) === 0) { - throw new SassScriptException('Expected $args to contain a key.'); - } - if (\count($map2[2]) === 1) { - throw new SassScriptException('Expected $args to contain a value.'); - } - $keys = $map2[2]; - $map2 = array_pop($keys); - } - $map2 = $this->assertMap($map2, 'map2'); - - return $this->modifyMap($map1, $keys, function ($oldValue) use ($map2) { - $nestedMap = $this->tryMap($oldValue); - - if ($nestedMap === null) { - return $map2; - } - - return $this->mergeMaps($nestedMap, $map2); - }); - } - - /** - * @param array $map - * @param array $keys - * @param callable $modify - * @param bool $addNesting - * - * @return Number|array - * - * @phpstan-param array<Number|array> $keys - * @phpstan-param callable(Number|array): (Number|array) $modify - */ - private function modifyMap(array $map, array $keys, callable $modify, $addNesting = true) - { - if ($keys === []) { - return $modify($map); - } - - return $this->modifyNestedMap($map, $keys, $modify, $addNesting); - } - - /** - * @param array $map - * @param array $keys - * @param callable $modify - * @param bool $addNesting - * - * @return array - * - * @phpstan-param non-empty-array<Number|array> $keys - * @phpstan-param callable(Number|array): (Number|array) $modify - */ - private function modifyNestedMap(array $map, array $keys, callable $modify, $addNesting) - { - $key = array_shift($keys); - - $nestedValueIndex = $this->mapGetEntryIndex($map, $key); - - if ($keys === []) { - if ($nestedValueIndex !== null) { - $map[2][$nestedValueIndex] = $modify($map[2][$nestedValueIndex]); - } else { - $map[1][] = $key; - $map[2][] = $modify(self::$null); - } - - return $map; - } - - $nestedMap = $nestedValueIndex !== null ? $this->tryMap($map[2][$nestedValueIndex]) : null; - - if ($nestedMap === null && !$addNesting) { - return $map; - } - - if ($nestedMap === null) { - $nestedMap = self::$emptyMap; - } - - $newNestedMap = $this->modifyNestedMap($nestedMap, $keys, $modify, $addNesting); - - if ($nestedValueIndex !== null) { - $map[2][$nestedValueIndex] = $newNestedMap; - } else { - $map[1][] = $key; - $map[2][] = $newNestedMap; - } - - return $map; - } - - /** - * Merges 2 Sass maps together - * - * @param array $map1 - * @param array $map2 - * - * @return array - */ - private function mergeMaps(array $map1, array $map2) - { - foreach ($map2[1] as $i2 => $key2) { - $map1EntryIndex = $this->mapGetEntryIndex($map1, $key2); - - if ($map1EntryIndex !== null) { - $map1[2][$map1EntryIndex] = $map2[2][$i2]; - continue; - } - - $map1[1][] = $key2; - $map1[2][] = $map2[2][$i2]; - } - - return $map1; - } - - protected static $libKeywords = ['args']; - protected function libKeywords($args) - { - $value = $args[0]; - - if ($value[0] !== Type::T_LIST || !isset($value[3]) || !\is_array($value[3])) { - $compiledValue = $this->compileValue($value); - - throw SassScriptException::forArgument($compiledValue . ' is not an argument list.', 'args'); - } - - $keys = []; - $values = []; - - foreach ($this->getArgumentListKeywords($value) as $name => $arg) { - $keys[] = [Type::T_KEYWORD, $name]; - $values[] = $arg; - } - - return [Type::T_MAP, $keys, $values]; - } - - protected static $libIsBracketed = ['list']; - protected function libIsBracketed($args) - { - $list = $args[0]; - $this->coerceList($list, ' '); - - if (! empty($list['enclosing']) && $list['enclosing'] === 'bracket') { - return self::$true; - } - - return self::$false; - } - - /** - * @param array $list1 - * @param array|Number|null $sep - * - * @return string - * @throws CompilerException - * - * @deprecated - */ - protected function listSeparatorForJoin($list1, $sep) - { - @trigger_error(sprintf('The "%s" method is deprecated.', __METHOD__), E_USER_DEPRECATED); - - if (! isset($sep)) { - return $list1[1]; - } - - switch ($this->compileValue($sep)) { - case 'comma': - return ','; - - case 'space': - return ' '; - - default: - return $list1[1]; - } - } - - protected static $libJoin = ['list1', 'list2', 'separator:auto', 'bracketed:auto']; - protected function libJoin($args) - { - list($list1, $list2, $sep, $bracketed) = $args; - - $list1 = $this->coerceList($list1, ' ', true); - $list2 = $this->coerceList($list2, ' ', true); - - switch ($this->compileStringContent($this->assertString($sep, 'separator'))) { - case 'comma': - $separator = ','; - break; - - case 'space': - $separator = ' '; - break; - - case 'slash': - $separator = '/'; - break; - - case 'auto': - if ($list1[1] !== '' || count($list1[2]) > 1 || !empty($list1['enclosing']) && $list1['enclosing'] !== 'parent') { - $separator = $list1[1] ?: ' '; - } elseif ($list2[1] !== '' || count($list2[2]) > 1 || !empty($list2['enclosing']) && $list2['enclosing'] !== 'parent') { - $separator = $list2[1] ?: ' '; - } else { - $separator = ' '; - } - break; - - default: - throw SassScriptException::forArgument('Must be "space", "comma", "slash", or "auto".', 'separator'); - } - - if ($bracketed === static::$true) { - $bracketed = true; - } elseif ($bracketed === static::$false) { - $bracketed = false; - } elseif ($bracketed === [Type::T_KEYWORD, 'auto']) { - $bracketed = 'auto'; - } elseif ($bracketed === static::$null) { - $bracketed = false; - } else { - $bracketed = $this->compileValue($bracketed); - $bracketed = ! ! $bracketed; - - if ($bracketed === true) { - $bracketed = true; - } - } - - if ($bracketed === 'auto') { - $bracketed = false; - - if (! empty($list1['enclosing']) && $list1['enclosing'] === 'bracket') { - $bracketed = true; - } - } - - $res = [Type::T_LIST, $separator, array_merge($list1[2], $list2[2])]; - - if ($bracketed) { - $res['enclosing'] = 'bracket'; - } - - return $res; - } - - protected static $libAppend = ['list', 'val', 'separator:auto']; - protected function libAppend($args) - { - list($list1, $value, $sep) = $args; - - $list1 = $this->coerceList($list1, ' ', true); - - switch ($this->compileStringContent($this->assertString($sep, 'separator'))) { - case 'comma': - $separator = ','; - break; - - case 'space': - $separator = ' '; - break; - - case 'slash': - $separator = '/'; - break; - - case 'auto': - $separator = $list1[1] === '' && \count($list1[2]) <= 1 && (empty($list1['enclosing']) || $list1['enclosing'] === 'parent') ? ' ' : $list1[1]; - break; - - default: - throw SassScriptException::forArgument('Must be "space", "comma", "slash", or "auto".', 'separator'); - } - - $res = [Type::T_LIST, $separator, array_merge($list1[2], [$value])]; - - if (isset($list1['enclosing'])) { - $res['enclosing'] = $list1['enclosing']; - } - - return $res; - } - - protected static $libZip = ['lists...']; - protected function libZip($args) - { - $argLists = []; - foreach ($args[0][2] as $arg) { - $argLists[] = $this->coerceList($arg); - } - - $lists = []; - $firstList = array_shift($argLists); - - $result = [Type::T_LIST, ',', $lists]; - if (! \is_null($firstList)) { - foreach ($firstList[2] as $key => $item) { - $list = [Type::T_LIST, ' ', [$item]]; - - foreach ($argLists as $arg) { - if (isset($arg[2][$key])) { - $list[2][] = $arg[2][$key]; - } else { - break 2; - } - } - - $lists[] = $list; - } - - $result[2] = $lists; - } else { - $result['enclosing'] = 'parent'; - } - - return $result; - } - - protected static $libTypeOf = ['value']; - protected function libTypeOf($args) - { - $value = $args[0]; - - return [Type::T_KEYWORD, $this->getTypeOf($value)]; - } - - /** - * @param array|Number $value - * - * @return string - */ - private function getTypeOf($value) - { - switch ($value[0]) { - case Type::T_KEYWORD: - if ($value === static::$true || $value === static::$false) { - return 'bool'; - } - - if ($this->coerceColor($value)) { - return 'color'; - } - - // fall-thru - case Type::T_FUNCTION: - return 'string'; - - case Type::T_FUNCTION_REFERENCE: - return 'function'; - - case Type::T_LIST: - if (isset($value[3]) && \is_array($value[3])) { - return 'arglist'; - } - - // fall-thru - default: - return $value[0]; - } - } - - protected static $libUnit = ['number']; - protected function libUnit($args) - { - $num = $this->assertNumber($args[0], 'number'); - - return [Type::T_STRING, '"', [$num->unitStr()]]; - } - - protected static $libUnitless = ['number']; - protected function libUnitless($args) - { - $value = $this->assertNumber($args[0], 'number'); - - return $this->toBool($value->unitless()); - } - - protected static $libComparable = [ - ['number1', 'number2'], - ['number-1', 'number-2'] - ]; - protected function libComparable($args) - { - list($number1, $number2) = $args; - - if ( - ! $number1 instanceof Number || - ! $number2 instanceof Number - ) { - throw $this->error('Invalid argument(s) for "comparable"'); - } - - return $this->toBool($number1->isComparableTo($number2)); - } - - protected static $libStrIndex = ['string', 'substring']; - protected function libStrIndex($args) - { - $string = $this->assertString($args[0], 'string'); - $stringContent = $this->compileStringContent($string); - - $substring = $this->assertString($args[1], 'substring'); - $substringContent = $this->compileStringContent($substring); - - if (! \strlen($substringContent)) { - $result = 0; - } else { - $result = Util::mbStrpos($stringContent, $substringContent); - } - - return $result === false ? static::$null : new Number($result + 1, ''); - } - - protected static $libStrInsert = ['string', 'insert', 'index']; - protected function libStrInsert($args) - { - $string = $this->assertString($args[0], 'string'); - $stringContent = $this->compileStringContent($string); - - $insert = $this->assertString($args[1], 'insert'); - $insertContent = $this->compileStringContent($insert); - - $index = $this->assertInteger($args[2], 'index'); - if ($index > 0) { - $index = $index - 1; - } - if ($index < 0) { - $index = max(Util::mbStrlen($stringContent) + 1 + $index, 0); - } - - $string[2] = [ - Util::mbSubstr($stringContent, 0, $index), - $insertContent, - Util::mbSubstr($stringContent, $index) - ]; - - return $string; - } - - protected static $libStrLength = ['string']; - protected function libStrLength($args) - { - $string = $this->assertString($args[0], 'string'); - $stringContent = $this->compileStringContent($string); - - return new Number(Util::mbStrlen($stringContent), ''); - } - - protected static $libStrSlice = ['string', 'start-at', 'end-at:-1']; - protected function libStrSlice($args) - { - $string = $this->assertString($args[0], 'string'); - $stringContent = $this->compileStringContent($string); - - $start = $this->assertNumber($args[1], 'start-at'); - $start->assertNoUnits('start-at'); - $startInt = $this->assertInteger($start, 'start-at'); - $end = $this->assertNumber($args[2], 'end-at'); - $end->assertNoUnits('end-at'); - $endInt = $this->assertInteger($end, 'end-at'); - - if ($endInt === 0) { - return [Type::T_STRING, $string[1], []]; - } - - if ($startInt > 0) { - $startInt--; - } - - if ($endInt < 0) { - $endInt = Util::mbStrlen($stringContent) + $endInt; - } else { - $endInt--; - } - - if ($endInt < $startInt) { - return [Type::T_STRING, $string[1], []]; - } - - $length = $endInt - $startInt + 1; // The end of the slice is inclusive - - $string[2] = [Util::mbSubstr($stringContent, $startInt, $length)]; - - return $string; - } - - protected static $libToLowerCase = ['string']; - protected function libToLowerCase($args) - { - $string = $this->assertString($args[0], 'string'); - $stringContent = $this->compileStringContent($string); - - $string[2] = [$this->stringTransformAsciiOnly($stringContent, 'strtolower')]; - - return $string; - } - - protected static $libToUpperCase = ['string']; - protected function libToUpperCase($args) - { - $string = $this->assertString($args[0], 'string'); - $stringContent = $this->compileStringContent($string); - - $string[2] = [$this->stringTransformAsciiOnly($stringContent, 'strtoupper')]; - - return $string; - } - - /** - * Apply a filter on a string content, only on ascii chars - * let extended chars untouched - * - * @param string $stringContent - * @param callable $filter - * @return string - */ - protected function stringTransformAsciiOnly($stringContent, $filter) - { - $mblength = Util::mbStrlen($stringContent); - if ($mblength === strlen($stringContent)) { - return $filter($stringContent); - } - $filteredString = ""; - for ($i = 0; $i < $mblength; $i++) { - $char = Util::mbSubstr($stringContent, $i, 1); - if (strlen($char) > 1) { - $filteredString .= $char; - } else { - $filteredString .= $filter($char); - } - } - - return $filteredString; - } - - protected static $libFeatureExists = ['feature']; - protected function libFeatureExists($args) - { - $string = $this->assertString($args[0], 'feature'); - $name = $this->compileStringContent($string); - - return $this->toBool( - \array_key_exists($name, $this->registeredFeatures) ? $this->registeredFeatures[$name] : false - ); - } - - protected static $libFunctionExists = ['name']; - protected function libFunctionExists($args) - { - $string = $this->assertString($args[0], 'name'); - $name = $this->compileStringContent($string); - - // user defined functions - if ($this->has(static::$namespaces['function'] . $name)) { - return self::$true; - } - - $name = $this->normalizeName($name); - - if (isset($this->userFunctions[$name])) { - return self::$true; - } - - // built-in functions - $f = $this->getBuiltinFunction($name); - - return $this->toBool(\is_callable($f)); - } - - protected static $libGlobalVariableExists = ['name']; - protected function libGlobalVariableExists($args) - { - $string = $this->assertString($args[0], 'name'); - $name = $this->compileStringContent($string); - - return $this->toBool($this->has($name, $this->rootEnv)); - } - - protected static $libMixinExists = ['name']; - protected function libMixinExists($args) - { - $string = $this->assertString($args[0], 'name'); - $name = $this->compileStringContent($string); - - return $this->toBool($this->has(static::$namespaces['mixin'] . $name)); - } - - protected static $libVariableExists = ['name']; - protected function libVariableExists($args) - { - $string = $this->assertString($args[0], 'name'); - $name = $this->compileStringContent($string); - - return $this->toBool($this->has($name)); - } - - protected static $libCounter = ['args...']; - /** - * Workaround IE7's content counter bug. - * - * @param array $args - * - * @return array - */ - protected function libCounter($args) - { - $list = array_map([$this, 'compileValue'], $args[0][2]); - - return [Type::T_STRING, '', ['counter(' . implode(',', $list) . ')']]; - } - - protected static $libRandom = ['limit:null']; - protected function libRandom($args) - { - if (isset($args[0]) && $args[0] !== static::$null) { - $n = $this->assertInteger($args[0], 'limit'); - - if ($n < 1) { - throw new SassScriptException("\$limit: Must be greater than 0, was $n."); - } - - return new Number(mt_rand(1, $n), ''); - } - - $max = mt_getrandmax(); - return new Number(mt_rand(0, $max - 1) / $max, ''); - } - - protected static $libUniqueId = []; - protected function libUniqueId() - { - static $id; - - if (! isset($id)) { - $id = PHP_INT_SIZE === 4 - ? mt_rand(0, pow(36, 5)) . str_pad(mt_rand(0, pow(36, 5)) % 10000000, 7, '0', STR_PAD_LEFT) - : mt_rand(0, pow(36, 8)); - } - - $id += mt_rand(0, 10) + 1; - - return [Type::T_STRING, '', ['u' . str_pad(base_convert($id, 10, 36), 8, '0', STR_PAD_LEFT)]]; - } - - /** - * @param array|Number $value - * @param bool $force_enclosing_display - * - * @return array - */ - protected function inspectFormatValue($value, $force_enclosing_display = false) - { - if ($value === static::$null) { - $value = [Type::T_KEYWORD, 'null']; - } - - $stringValue = [$value]; - - if ($value instanceof Number) { - return [Type::T_STRING, '', $stringValue]; - } - - if ($value[0] === Type::T_LIST) { - if (end($value[2]) === static::$null) { - array_pop($value[2]); - $value[2][] = [Type::T_STRING, '', ['']]; - $force_enclosing_display = true; - } - - if ( - ! empty($value['enclosing']) && - ($force_enclosing_display || - ($value['enclosing'] === 'bracket') || - ! \count($value[2])) - ) { - $value['enclosing'] = 'forced_' . $value['enclosing']; - $force_enclosing_display = true; - } elseif (! \count($value[2])) { - $value['enclosing'] = 'forced_parent'; - } - - foreach ($value[2] as $k => $listelement) { - $value[2][$k] = $this->inspectFormatValue($listelement, $force_enclosing_display); - } - - $stringValue = [$value]; - } - - return [Type::T_STRING, '', $stringValue]; - } - - protected static $libInspect = ['value']; - protected function libInspect($args) - { - $value = $args[0]; - - return $this->inspectFormatValue($value); - } - - /** - * Preprocess selector args - * - * @param array $arg - * @param string|null $varname - * @param bool $allowParent - * - * @return array - */ - protected function getSelectorArg($arg, $varname = null, $allowParent = false) - { - static $parser = null; - - if (\is_null($parser)) { - $parser = $this->parserFactory(__METHOD__); - } - - if (! $this->checkSelectorArgType($arg)) { - $var_value = $this->compileValue($arg); - throw SassScriptException::forArgument("$var_value is not a valid selector: it must be a string, a list of strings, or a list of lists of strings", $varname); - } - - - if ($arg[0] === Type::T_STRING) { - $arg[1] = ''; - } - $arg = $this->compileValue($arg); - - $parsedSelector = []; - - if ($parser->parseSelector($arg, $parsedSelector, true)) { - $selector = $this->evalSelectors($parsedSelector); - $gluedSelector = $this->glueFunctionSelectors($selector); - - if (! $allowParent) { - foreach ($gluedSelector as $selector) { - foreach ($selector as $s) { - if (in_array(static::$selfSelector, $s)) { - throw SassScriptException::forArgument("Parent selectors aren't allowed here.", $varname); - } - } - } - } - - return $gluedSelector; - } - - throw SassScriptException::forArgument("expected more input, invalid selector.", $varname); - } - - /** - * Check variable type for getSelectorArg() function - * @param array $arg - * @param int $maxDepth - * @return bool - */ - protected function checkSelectorArgType($arg, $maxDepth = 2) - { - if ($arg[0] === Type::T_LIST && $maxDepth > 0) { - foreach ($arg[2] as $elt) { - if (! $this->checkSelectorArgType($elt, $maxDepth - 1)) { - return false; - } - } - return true; - } - if (!in_array($arg[0], [Type::T_STRING, Type::T_KEYWORD])) { - return false; - } - return true; - } - - /** - * Postprocess selector to output in right format - * - * @param array $selectors - * - * @return array - */ - protected function formatOutputSelector($selectors) - { - $selectors = $this->collapseSelectorsAsList($selectors); - - return $selectors; - } - - protected static $libIsSuperselector = ['super', 'sub']; - protected function libIsSuperselector($args) - { - list($super, $sub) = $args; - - $super = $this->getSelectorArg($super, 'super'); - $sub = $this->getSelectorArg($sub, 'sub'); - - return $this->toBool($this->isSuperSelector($super, $sub)); - } - - /** - * Test a $super selector again $sub - * - * @param array $super - * @param array $sub - * - * @return bool - */ - protected function isSuperSelector($super, $sub) - { - // one and only one selector for each arg - if (! $super) { - throw $this->error('Invalid super selector for isSuperSelector()'); - } - - if (! $sub) { - throw $this->error('Invalid sub selector for isSuperSelector()'); - } - - if (count($sub) > 1) { - foreach ($sub as $s) { - if (! $this->isSuperSelector($super, [$s])) { - return false; - } - } - return true; - } - - if (count($super) > 1) { - foreach ($super as $s) { - if ($this->isSuperSelector([$s], $sub)) { - return true; - } - } - return false; - } - - $super = reset($super); - $sub = reset($sub); - - $i = 0; - $nextMustMatch = false; - - foreach ($super as $node) { - $compound = ''; - - array_walk_recursive( - $node, - function ($value, $key) use (&$compound) { - $compound .= $value; - } - ); - - if ($this->isImmediateRelationshipCombinator($compound)) { - if ($node !== $sub[$i]) { - return false; - } - - $nextMustMatch = true; - $i++; - } else { - while ($i < \count($sub) && ! $this->isSuperPart($node, $sub[$i])) { - if ($nextMustMatch) { - return false; - } - - $i++; - } - - if ($i >= \count($sub)) { - return false; - } - - $nextMustMatch = false; - $i++; - } - } - - return true; - } - - /** - * Test a part of super selector again a part of sub selector - * - * @param array $superParts - * @param array $subParts - * - * @return bool - */ - protected function isSuperPart($superParts, $subParts) - { - $i = 0; - - foreach ($superParts as $superPart) { - while ($i < \count($subParts) && $subParts[$i] !== $superPart) { - $i++; - } - - if ($i >= \count($subParts)) { - return false; - } - - $i++; - } - - return true; - } - - protected static $libSelectorAppend = ['selector...']; - protected function libSelectorAppend($args) - { - // get the selector... list - $args = reset($args); - $args = $args[2]; - - if (\count($args) < 1) { - throw $this->error('selector-append() needs at least 1 argument'); - } - - $selectors = []; - foreach ($args as $arg) { - $selectors[] = $this->getSelectorArg($arg, 'selector'); - } - - return $this->formatOutputSelector($this->selectorAppend($selectors)); - } - - /** - * Append parts of the last selector in the list to the previous, recursively - * - * @param array $selectors - * - * @return array - * - * @throws \ScssPhp\ScssPhp\Exception\CompilerException - */ - protected function selectorAppend($selectors) - { - $lastSelectors = array_pop($selectors); - - if (! $lastSelectors) { - throw $this->error('Invalid selector list in selector-append()'); - } - - while (\count($selectors)) { - $previousSelectors = array_pop($selectors); - - if (! $previousSelectors) { - throw $this->error('Invalid selector list in selector-append()'); - } - - // do the trick, happening $lastSelector to $previousSelector - $appended = []; - - foreach ($previousSelectors as $previousSelector) { - foreach ($lastSelectors as $lastSelector) { - $previous = $previousSelector; - foreach ($previousSelector as $j => $previousSelectorParts) { - foreach ($lastSelector as $lastSelectorParts) { - foreach ($lastSelectorParts as $lastSelectorPart) { - $previous[$j][] = $lastSelectorPart; - } - } - } - - $appended[] = $previous; - } - } - - $lastSelectors = $appended; - } - - return $lastSelectors; - } - - protected static $libSelectorExtend = [ - ['selector', 'extendee', 'extender'], - ['selectors', 'extendee', 'extender'] - ]; - protected function libSelectorExtend($args) - { - list($selectors, $extendee, $extender) = $args; - - $selectors = $this->getSelectorArg($selectors, 'selector'); - $extendee = $this->getSelectorArg($extendee, 'extendee'); - $extender = $this->getSelectorArg($extender, 'extender'); - - if (! $selectors || ! $extendee || ! $extender) { - throw $this->error('selector-extend() invalid arguments'); - } - - $extended = $this->extendOrReplaceSelectors($selectors, $extendee, $extender); - - return $this->formatOutputSelector($extended); - } - - protected static $libSelectorReplace = [ - ['selector', 'original', 'replacement'], - ['selectors', 'original', 'replacement'] - ]; - protected function libSelectorReplace($args) - { - list($selectors, $original, $replacement) = $args; - - $selectors = $this->getSelectorArg($selectors, 'selector'); - $original = $this->getSelectorArg($original, 'original'); - $replacement = $this->getSelectorArg($replacement, 'replacement'); - - if (! $selectors || ! $original || ! $replacement) { - throw $this->error('selector-replace() invalid arguments'); - } - - $replaced = $this->extendOrReplaceSelectors($selectors, $original, $replacement, true); - - return $this->formatOutputSelector($replaced); - } - - /** - * Extend/replace in selectors - * used by selector-extend and selector-replace that use the same logic - * - * @param array $selectors - * @param array $extendee - * @param array $extender - * @param bool $replace - * - * @return array - */ - protected function extendOrReplaceSelectors($selectors, $extendee, $extender, $replace = false) - { - $saveExtends = $this->extends; - $saveExtendsMap = $this->extendsMap; - - $this->extends = []; - $this->extendsMap = []; - - foreach ($extendee as $es) { - if (\count($es) !== 1) { - throw $this->error('Can\'t extend complex selector.'); - } - - // only use the first one - $this->pushExtends(reset($es), $extender, null); - } - - $extended = []; - - foreach ($selectors as $selector) { - if (! $replace) { - $extended[] = $selector; - } - - $n = \count($extended); - - $this->matchExtends($selector, $extended); - - // if didnt match, keep the original selector if we are in a replace operation - if ($replace && \count($extended) === $n) { - $extended[] = $selector; - } - } - - $this->extends = $saveExtends; - $this->extendsMap = $saveExtendsMap; - - return $extended; - } - - protected static $libSelectorNest = ['selector...']; - protected function libSelectorNest($args) - { - // get the selector... list - $args = reset($args); - $args = $args[2]; - - if (\count($args) < 1) { - throw $this->error('selector-nest() needs at least 1 argument'); - } - - $selectorsMap = []; - foreach ($args as $arg) { - $selectorsMap[] = $this->getSelectorArg($arg, 'selector', true); - } - - assert(!empty($selectorsMap)); - - $envs = []; - - foreach ($selectorsMap as $selectors) { - $env = new Environment(); - $env->selectors = $selectors; - - $envs[] = $env; - } - - $envs = array_reverse($envs); - $env = $this->extractEnv($envs); - $outputSelectors = $this->multiplySelectors($env); - - return $this->formatOutputSelector($outputSelectors); - } - - protected static $libSelectorParse = [ - ['selector'], - ['selectors'] - ]; - protected function libSelectorParse($args) - { - $selectors = reset($args); - $selectors = $this->getSelectorArg($selectors, 'selector'); - - return $this->formatOutputSelector($selectors); - } - - protected static $libSelectorUnify = ['selectors1', 'selectors2']; - protected function libSelectorUnify($args) - { - list($selectors1, $selectors2) = $args; - - $selectors1 = $this->getSelectorArg($selectors1, 'selectors1'); - $selectors2 = $this->getSelectorArg($selectors2, 'selectors2'); - - if (! $selectors1 || ! $selectors2) { - throw $this->error('selector-unify() invalid arguments'); - } - - // only consider the first compound of each - $compound1 = reset($selectors1); - $compound2 = reset($selectors2); - - // unify them and that's it - $unified = $this->unifyCompoundSelectors($compound1, $compound2); - - return $this->formatOutputSelector($unified); - } - - /** - * The selector-unify magic as its best - * (at least works as expected on test cases) - * - * @param array $compound1 - * @param array $compound2 - * - * @return array - */ - protected function unifyCompoundSelectors($compound1, $compound2) - { - if (! \count($compound1)) { - return $compound2; - } - - if (! \count($compound2)) { - return $compound1; - } - - // check that last part are compatible - $lastPart1 = array_pop($compound1); - $lastPart2 = array_pop($compound2); - $last = $this->mergeParts($lastPart1, $lastPart2); - - if (! $last) { - return [[]]; - } - - $unifiedCompound = [$last]; - $unifiedSelectors = [$unifiedCompound]; - - // do the rest - while (\count($compound1) || \count($compound2)) { - $part1 = end($compound1); - $part2 = end($compound2); - - if ($part1 && ($match2 = $this->matchPartInCompound($part1, $compound2))) { - list($compound2, $part2, $after2) = $match2; - - if ($after2) { - $unifiedSelectors = $this->prependSelectors($unifiedSelectors, $after2); - } - - $c = $this->mergeParts($part1, $part2); - $unifiedSelectors = $this->prependSelectors($unifiedSelectors, [$c]); - - $part1 = $part2 = null; - - array_pop($compound1); - } - - if ($part2 && ($match1 = $this->matchPartInCompound($part2, $compound1))) { - list($compound1, $part1, $after1) = $match1; - - if ($after1) { - $unifiedSelectors = $this->prependSelectors($unifiedSelectors, $after1); - } - - $c = $this->mergeParts($part2, $part1); - $unifiedSelectors = $this->prependSelectors($unifiedSelectors, [$c]); - - $part1 = $part2 = null; - - array_pop($compound2); - } - - $new = []; - - if ($part1 && $part2) { - array_pop($compound1); - array_pop($compound2); - - $s = $this->prependSelectors($unifiedSelectors, [$part2]); - $new = array_merge($new, $this->prependSelectors($s, [$part1])); - $s = $this->prependSelectors($unifiedSelectors, [$part1]); - $new = array_merge($new, $this->prependSelectors($s, [$part2])); - } elseif ($part1) { - array_pop($compound1); - - $new = array_merge($new, $this->prependSelectors($unifiedSelectors, [$part1])); - } elseif ($part2) { - array_pop($compound2); - - $new = array_merge($new, $this->prependSelectors($unifiedSelectors, [$part2])); - } - - if ($new) { - $unifiedSelectors = $new; - } - } - - return $unifiedSelectors; - } - - /** - * Prepend each selector from $selectors with $parts - * - * @param array $selectors - * @param array $parts - * - * @return array - */ - protected function prependSelectors($selectors, $parts) - { - $new = []; - - foreach ($selectors as $compoundSelector) { - array_unshift($compoundSelector, $parts); - - $new[] = $compoundSelector; - } - - return $new; - } - - /** - * Try to find a matching part in a compound: - * - with same html tag name - * - with some class or id or something in common - * - * @param array $part - * @param array $compound - * - * @return array|false - */ - protected function matchPartInCompound($part, $compound) - { - $partTag = $this->findTagName($part); - $before = $compound; - $after = []; - - // try to find a match by tag name first - while (\count($before)) { - $p = array_pop($before); - - if ($partTag && $partTag !== '*' && $partTag == $this->findTagName($p)) { - return [$before, $p, $after]; - } - - $after[] = $p; - } - - // try again matching a non empty intersection and a compatible tagname - $before = $compound; - $after = []; - - while (\count($before)) { - $p = array_pop($before); - - if ($this->checkCompatibleTags($partTag, $this->findTagName($p))) { - if (\count(array_intersect($part, $p))) { - return [$before, $p, $after]; - } - } - - $after[] = $p; - } - - return false; - } - - /** - * Merge two part list taking care that - * - the html tag is coming first - if any - * - the :something are coming last - * - * @param array $parts1 - * @param array $parts2 - * - * @return array - */ - protected function mergeParts($parts1, $parts2) - { - $tag1 = $this->findTagName($parts1); - $tag2 = $this->findTagName($parts2); - $tag = $this->checkCompatibleTags($tag1, $tag2); - - // not compatible tags - if ($tag === false) { - return []; - } - - if ($tag) { - if ($tag1) { - $parts1 = array_diff($parts1, [$tag1]); - } - - if ($tag2) { - $parts2 = array_diff($parts2, [$tag2]); - } - } - - $mergedParts = array_merge($parts1, $parts2); - $mergedOrderedParts = []; - - foreach ($mergedParts as $part) { - if (strpos($part, ':') === 0) { - $mergedOrderedParts[] = $part; - } - } - - $mergedParts = array_diff($mergedParts, $mergedOrderedParts); - $mergedParts = array_merge($mergedParts, $mergedOrderedParts); - - if ($tag) { - array_unshift($mergedParts, $tag); - } - - return $mergedParts; - } - - /** - * Check the compatibility between two tag names: - * if both are defined they should be identical or one has to be '*' - * - * @param string $tag1 - * @param string $tag2 - * - * @return array|false - */ - protected function checkCompatibleTags($tag1, $tag2) - { - $tags = [$tag1, $tag2]; - $tags = array_unique($tags); - $tags = array_filter($tags); - - if (\count($tags) > 1) { - $tags = array_diff($tags, ['*']); - } - - // not compatible nodes - if (\count($tags) > 1) { - return false; - } - - return $tags; - } - - /** - * Find the html tag name in a selector parts list - * - * @param string[] $parts - * - * @return string - */ - protected function findTagName($parts) - { - foreach ($parts as $part) { - if (! preg_match('/^[\[.:#%_-]/', $part)) { - return $part; - } - } - - return ''; - } - - protected static $libSimpleSelectors = ['selector']; - protected function libSimpleSelectors($args) - { - $selector = reset($args); - $selector = $this->getSelectorArg($selector, 'selector'); - - // remove selectors list layer, keeping the first one - $selector = reset($selector); - - // remove parts list layer, keeping the first part - $part = reset($selector); - - $listParts = []; - - foreach ($part as $p) { - $listParts[] = [Type::T_STRING, '', [$p]]; - } - - return [Type::T_LIST, ',', $listParts]; - } - - protected static $libScssphpGlob = ['pattern']; - protected function libScssphpGlob($args) - { - @trigger_error(sprintf('The "scssphp-glob" function is deprecated an will be removed in ScssPhp 2.0. Register your own alternative through "%s::registerFunction', __CLASS__), E_USER_DEPRECATED); - - $this->logger->warn('The "scssphp-glob" function is deprecated an will be removed in ScssPhp 2.0.', true); - - $string = $this->assertString($args[0], 'pattern'); - $pattern = $this->compileStringContent($string); - $matches = glob($pattern); - $listParts = []; - - foreach ($matches as $match) { - if (! is_file($match)) { - continue; - } - - $listParts[] = [Type::T_STRING, '"', [$match]]; - } - - return [Type::T_LIST, ',', $listParts]; - } -} diff --git a/lib/scssphp/scssphp/src/Compiler/CachedResult.php b/lib/scssphp/scssphp/src/Compiler/CachedResult.php deleted file mode 100644 index a66291996..000000000 --- a/lib/scssphp/scssphp/src/Compiler/CachedResult.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Compiler; - -use ScssPhp\ScssPhp\CompilationResult; - -/** - * @internal - */ -class CachedResult -{ - /** - * @var CompilationResult - */ - private $result; - - /** - * @var array<string, int> - */ - private $parsedFiles; - - /** - * @var array - * @phpstan-var list<array{currentDir: string|null, path: string, filePath: string}> - */ - private $resolvedImports; - - /** - * @param CompilationResult $result - * @param array<string, int> $parsedFiles - * @param array $resolvedImports - * - * @phpstan-param list<array{currentDir: string|null, path: string, filePath: string}> $resolvedImports - */ - public function __construct(CompilationResult $result, array $parsedFiles, array $resolvedImports) - { - $this->result = $result; - $this->parsedFiles = $parsedFiles; - $this->resolvedImports = $resolvedImports; - } - - /** - * @return CompilationResult - */ - public function getResult() - { - return $this->result; - } - - /** - * @return array<string, int> - */ - public function getParsedFiles() - { - return $this->parsedFiles; - } - - /** - * @return array - * - * @phpstan-return list<array{currentDir: string|null, path: string, filePath: string}> - */ - public function getResolvedImports() - { - return $this->resolvedImports; - } -} diff --git a/lib/scssphp/scssphp/src/Compiler/Environment.php b/lib/scssphp/scssphp/src/Compiler/Environment.php deleted file mode 100644 index b205a077f..000000000 --- a/lib/scssphp/scssphp/src/Compiler/Environment.php +++ /dev/null @@ -1,68 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Compiler; - -/** - * Compiler environment - * - * @author Anthon Pang <anthon.pang@gmail.com> - * - * @internal - */ -class Environment -{ - /** - * @var \ScssPhp\ScssPhp\Block|null - */ - public $block; - - /** - * @var \ScssPhp\ScssPhp\Compiler\Environment|null - */ - public $parent; - - /** - * @var Environment|null - */ - public $declarationScopeParent; - - /** - * @var Environment|null - */ - public $parentStore; - - /** - * @var array|null - */ - public $selectors; - - /** - * @var string|null - */ - public $marker; - - /** - * @var array - */ - public $store; - - /** - * @var array - */ - public $storeUnreduced; - - /** - * @var int - */ - public $depth; -} diff --git a/lib/scssphp/scssphp/src/Exception/CompilerException.php b/lib/scssphp/scssphp/src/Exception/CompilerException.php deleted file mode 100644 index 0b00cf525..000000000 --- a/lib/scssphp/scssphp/src/Exception/CompilerException.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Exception; - -/** - * Compiler exception - * - * @author Oleksandr Savchenko <traveltino@gmail.com> - * - * @internal - */ -class CompilerException extends \Exception implements SassException -{ -} diff --git a/lib/scssphp/scssphp/src/Exception/ParserException.php b/lib/scssphp/scssphp/src/Exception/ParserException.php deleted file mode 100644 index f0726698f..000000000 --- a/lib/scssphp/scssphp/src/Exception/ParserException.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Exception; - -/** - * Parser Exception - * - * @author Oleksandr Savchenko <traveltino@gmail.com> - * - * @internal - */ -class ParserException extends \Exception implements SassException -{ - /** - * @var array|null - * @phpstan-var array{string, int, int}|null - */ - private $sourcePosition; - - /** - * Get source position - * - * @api - * - * @return array|null - * @phpstan-return array{string, int, int}|null - */ - public function getSourcePosition() - { - return $this->sourcePosition; - } - - /** - * Set source position - * - * @api - * - * @param array $sourcePosition - * - * @return void - * - * @phpstan-param array{string, int, int} $sourcePosition - */ - public function setSourcePosition($sourcePosition) - { - $this->sourcePosition = $sourcePosition; - } -} diff --git a/lib/scssphp/scssphp/src/Exception/RangeException.php b/lib/scssphp/scssphp/src/Exception/RangeException.php deleted file mode 100644 index 4be4dee70..000000000 --- a/lib/scssphp/scssphp/src/Exception/RangeException.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Exception; - -/** - * Range exception - * - * @author Anthon Pang <anthon.pang@gmail.com> - * - * @internal - */ -class RangeException extends \Exception implements SassException -{ -} diff --git a/lib/scssphp/scssphp/src/Exception/SassException.php b/lib/scssphp/scssphp/src/Exception/SassException.php deleted file mode 100644 index 9f62b3cd2..000000000 --- a/lib/scssphp/scssphp/src/Exception/SassException.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace ScssPhp\ScssPhp\Exception; - -interface SassException -{ -} diff --git a/lib/scssphp/scssphp/src/Exception/SassScriptException.php b/lib/scssphp/scssphp/src/Exception/SassScriptException.php deleted file mode 100644 index 19356a7a1..000000000 --- a/lib/scssphp/scssphp/src/Exception/SassScriptException.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -namespace ScssPhp\ScssPhp\Exception; - -/** - * An exception thrown by SassScript. - * - * This class does not implement SassException on purpose, as it should - * never be returned to the outside code. The compilation will catch it - * and replace it with a SassException reporting the location of the - * error. - */ -class SassScriptException extends \Exception -{ - /** - * Creates a SassScriptException with support for an argument name. - * - * This helper ensures a consistent handling of argument names in the - * error message, without duplicating it. - * - * @param string $message - * @param string|null $name The argument name, without $ - * - * @return SassScriptException - */ - public static function forArgument($message, $name = null) - { - $varDisplay = !\is_null($name) ? "\${$name}: " : ''; - - return new self($varDisplay . $message); - } -} diff --git a/lib/scssphp/scssphp/src/Exception/ServerException.php b/lib/scssphp/scssphp/src/Exception/ServerException.php deleted file mode 100644 index e593c4014..000000000 --- a/lib/scssphp/scssphp/src/Exception/ServerException.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Exception; - -@trigger_error(sprintf('The "%s" class is deprecated.', ServerException::class), E_USER_DEPRECATED); - -/** - * Server Exception - * - * @author Anthon Pang <anthon.pang@gmail.com> - * - * @deprecated The Scssphp server should define its own exception instead. - */ -class ServerException extends \Exception implements SassException -{ -} diff --git a/lib/scssphp/scssphp/src/Formatter.php b/lib/scssphp/scssphp/src/Formatter.php deleted file mode 100644 index 6137dc650..000000000 --- a/lib/scssphp/scssphp/src/Formatter.php +++ /dev/null @@ -1,377 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp; - -use ScssPhp\ScssPhp\Formatter\OutputBlock; -use ScssPhp\ScssPhp\SourceMap\SourceMapGenerator; - -/** - * Base formatter - * - * @author Leaf Corcoran <leafot@gmail.com> - * - * @internal - */ -abstract class Formatter -{ - /** - * @var int - */ - public $indentLevel; - - /** - * @var string - */ - public $indentChar; - - /** - * @var string - */ - public $break; - - /** - * @var string - */ - public $open; - - /** - * @var string - */ - public $close; - - /** - * @var string - */ - public $tagSeparator; - - /** - * @var string - */ - public $assignSeparator; - - /** - * @var bool - */ - public $keepSemicolons; - - /** - * @var \ScssPhp\ScssPhp\Formatter\OutputBlock - */ - protected $currentBlock; - - /** - * @var int - */ - protected $currentLine; - - /** - * @var int - */ - protected $currentColumn; - - /** - * @var \ScssPhp\ScssPhp\SourceMap\SourceMapGenerator|null - */ - protected $sourceMapGenerator; - - /** - * @var string - */ - protected $strippedSemicolon; - - /** - * Initialize formatter - * - * @api - */ - abstract public function __construct(); - - /** - * Return indentation (whitespace) - * - * @return string - */ - protected function indentStr() - { - return ''; - } - - /** - * Return property assignment - * - * @api - * - * @param string $name - * @param mixed $value - * - * @return string - */ - public function property($name, $value) - { - return rtrim($name) . $this->assignSeparator . $value . ';'; - } - - /** - * Return custom property assignment - * differs in that you have to keep spaces in the value as is - * - * @api - * - * @param string $name - * @param mixed $value - * - * @return string - */ - public function customProperty($name, $value) - { - return rtrim($name) . trim($this->assignSeparator) . $value . ';'; - } - - /** - * Output lines inside a block - * - * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block - * - * @return void - */ - protected function blockLines(OutputBlock $block) - { - $inner = $this->indentStr(); - $glue = $this->break . $inner; - - $this->write($inner . implode($glue, $block->lines)); - - if (! empty($block->children)) { - $this->write($this->break); - } - } - - /** - * Output block selectors - * - * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block - * - * @return void - */ - protected function blockSelectors(OutputBlock $block) - { - assert(! empty($block->selectors)); - - $inner = $this->indentStr(); - - $this->write($inner - . implode($this->tagSeparator, $block->selectors) - . $this->open . $this->break); - } - - /** - * Output block children - * - * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block - * - * @return void - */ - protected function blockChildren(OutputBlock $block) - { - foreach ($block->children as $child) { - $this->block($child); - } - } - - /** - * Output non-empty block - * - * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block - * - * @return void - */ - protected function block(OutputBlock $block) - { - if (empty($block->lines) && empty($block->children)) { - return; - } - - $this->currentBlock = $block; - - $pre = $this->indentStr(); - - if (! empty($block->selectors)) { - $this->blockSelectors($block); - - $this->indentLevel++; - } - - if (! empty($block->lines)) { - $this->blockLines($block); - } - - if (! empty($block->children)) { - $this->blockChildren($block); - } - - if (! empty($block->selectors)) { - $this->indentLevel--; - - if (! $this->keepSemicolons) { - $this->strippedSemicolon = ''; - } - - if (empty($block->children)) { - $this->write($this->break); - } - - $this->write($pre . $this->close . $this->break); - } - } - - /** - * Test and clean safely empty children - * - * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block - * - * @return bool - */ - protected function testEmptyChildren($block) - { - $isEmpty = empty($block->lines); - - if ($block->children) { - foreach ($block->children as $k => &$child) { - if (! $this->testEmptyChildren($child)) { - $isEmpty = false; - continue; - } - - if ($child->type === Type::T_MEDIA || $child->type === Type::T_DIRECTIVE) { - $child->children = []; - $child->selectors = null; - } - } - } - - return $isEmpty; - } - - /** - * Entry point to formatting a block - * - * @api - * - * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block An abstract syntax tree - * @param \ScssPhp\ScssPhp\SourceMap\SourceMapGenerator|null $sourceMapGenerator Optional source map generator - * - * @return string - */ - public function format(OutputBlock $block, SourceMapGenerator $sourceMapGenerator = null) - { - $this->sourceMapGenerator = null; - - if ($sourceMapGenerator) { - $this->currentLine = 1; - $this->currentColumn = 0; - $this->sourceMapGenerator = $sourceMapGenerator; - } - - $this->testEmptyChildren($block); - - ob_start(); - - try { - $this->block($block); - } catch (\Exception $e) { - ob_end_clean(); - throw $e; - } catch (\Throwable $e) { - ob_end_clean(); - throw $e; - } - - $out = ob_get_clean(); - assert($out !== false); - - return $out; - } - - /** - * Output content - * - * @param string $str - * - * @return void - */ - protected function write($str) - { - if (! empty($this->strippedSemicolon)) { - echo $this->strippedSemicolon; - - $this->strippedSemicolon = ''; - } - - /* - * Maybe Strip semi-colon appended by property(); it's a separator, not a terminator - * will be striped for real before a closing, otherwise displayed unchanged starting the next write - */ - if ( - ! $this->keepSemicolons && - $str && - (strpos($str, ';') !== false) && - (substr($str, -1) === ';') - ) { - $str = substr($str, 0, -1); - - $this->strippedSemicolon = ';'; - } - - if ($this->sourceMapGenerator) { - $lines = explode("\n", $str); - $lastLine = array_pop($lines); - - foreach ($lines as $line) { - // If the written line starts is empty, adding a mapping would add it for - // a non-existent column as we are at the end of the line - if ($line !== '') { - assert($this->currentBlock->sourceLine !== null); - assert($this->currentBlock->sourceName !== null); - $this->sourceMapGenerator->addMapping( - $this->currentLine, - $this->currentColumn, - $this->currentBlock->sourceLine, - //columns from parser are off by one - $this->currentBlock->sourceColumn > 0 ? $this->currentBlock->sourceColumn - 1 : 0, - $this->currentBlock->sourceName - ); - } - - $this->currentLine++; - $this->currentColumn = 0; - } - - if ($lastLine !== '') { - assert($this->currentBlock->sourceLine !== null); - assert($this->currentBlock->sourceName !== null); - $this->sourceMapGenerator->addMapping( - $this->currentLine, - $this->currentColumn, - $this->currentBlock->sourceLine, - //columns from parser are off by one - $this->currentBlock->sourceColumn > 0 ? $this->currentBlock->sourceColumn - 1 : 0, - $this->currentBlock->sourceName - ); - } - - $this->currentColumn += \strlen($lastLine); - } - - echo $str; - } -} diff --git a/lib/scssphp/scssphp/src/Formatter/Compact.php b/lib/scssphp/scssphp/src/Formatter/Compact.php deleted file mode 100644 index 22f226889..000000000 --- a/lib/scssphp/scssphp/src/Formatter/Compact.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Formatter; - -use ScssPhp\ScssPhp\Formatter; - -/** - * Compact formatter - * - * @author Leaf Corcoran <leafot@gmail.com> - * - * @deprecated since 1.4.0. Use the Compressed formatter instead. - * - * @internal - */ -class Compact extends Formatter -{ - /** - * {@inheritdoc} - */ - public function __construct() - { - @trigger_error('The Compact formatter is deprecated since 1.4.0. Use the Compressed formatter instead.', E_USER_DEPRECATED); - - $this->indentLevel = 0; - $this->indentChar = ''; - $this->break = ''; - $this->open = ' {'; - $this->close = "}\n\n"; - $this->tagSeparator = ','; - $this->assignSeparator = ':'; - $this->keepSemicolons = true; - } - - /** - * {@inheritdoc} - */ - public function indentStr() - { - return ' '; - } -} diff --git a/lib/scssphp/scssphp/src/Formatter/Compressed.php b/lib/scssphp/scssphp/src/Formatter/Compressed.php deleted file mode 100644 index 58ebe3f11..000000000 --- a/lib/scssphp/scssphp/src/Formatter/Compressed.php +++ /dev/null @@ -1,83 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Formatter; - -use ScssPhp\ScssPhp\Formatter; - -/** - * Compressed formatter - * - * @author Leaf Corcoran <leafot@gmail.com> - * - * @internal - */ -class Compressed extends Formatter -{ - /** - * {@inheritdoc} - */ - public function __construct() - { - $this->indentLevel = 0; - $this->indentChar = ' '; - $this->break = ''; - $this->open = '{'; - $this->close = '}'; - $this->tagSeparator = ','; - $this->assignSeparator = ':'; - $this->keepSemicolons = false; - } - - /** - * {@inheritdoc} - */ - public function blockLines(OutputBlock $block) - { - $inner = $this->indentStr(); - - $glue = $this->break . $inner; - - foreach ($block->lines as $index => $line) { - if (substr($line, 0, 2) === '/*' && substr($line, 2, 1) !== '!') { - unset($block->lines[$index]); - } - } - - $this->write($inner . implode($glue, $block->lines)); - - if (! empty($block->children)) { - $this->write($this->break); - } - } - - /** - * Output block selectors - * - * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block - */ - protected function blockSelectors(OutputBlock $block) - { - assert(! empty($block->selectors)); - - $inner = $this->indentStr(); - - $this->write( - $inner - . implode( - $this->tagSeparator, - str_replace([' > ', ' + ', ' ~ '], ['>', '+', '~'], $block->selectors) - ) - . $this->open . $this->break - ); - } -} diff --git a/lib/scssphp/scssphp/src/Formatter/Crunched.php b/lib/scssphp/scssphp/src/Formatter/Crunched.php deleted file mode 100644 index 2bc1e9299..000000000 --- a/lib/scssphp/scssphp/src/Formatter/Crunched.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Formatter; - -use ScssPhp\ScssPhp\Formatter; - -/** - * Crunched formatter - * - * @author Anthon Pang <anthon.pang@gmail.com> - * - * @deprecated since 1.4.0. Use the Compressed formatter instead. - * - * @internal - */ -class Crunched extends Formatter -{ - /** - * {@inheritdoc} - */ - public function __construct() - { - @trigger_error('The Crunched formatter is deprecated since 1.4.0. Use the Compressed formatter instead.', E_USER_DEPRECATED); - - $this->indentLevel = 0; - $this->indentChar = ' '; - $this->break = ''; - $this->open = '{'; - $this->close = '}'; - $this->tagSeparator = ','; - $this->assignSeparator = ':'; - $this->keepSemicolons = false; - } - - /** - * {@inheritdoc} - */ - public function blockLines(OutputBlock $block) - { - $inner = $this->indentStr(); - - $glue = $this->break . $inner; - - foreach ($block->lines as $index => $line) { - if (substr($line, 0, 2) === '/*') { - unset($block->lines[$index]); - } - } - - $this->write($inner . implode($glue, $block->lines)); - - if (! empty($block->children)) { - $this->write($this->break); - } - } - - /** - * Output block selectors - * - * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block - */ - protected function blockSelectors(OutputBlock $block) - { - assert(! empty($block->selectors)); - - $inner = $this->indentStr(); - - $this->write( - $inner - . implode( - $this->tagSeparator, - str_replace([' > ', ' + ', ' ~ '], ['>', '+', '~'], $block->selectors) - ) - . $this->open . $this->break - ); - } -} diff --git a/lib/scssphp/scssphp/src/Formatter/Debug.php b/lib/scssphp/scssphp/src/Formatter/Debug.php deleted file mode 100644 index b3f442253..000000000 --- a/lib/scssphp/scssphp/src/Formatter/Debug.php +++ /dev/null @@ -1,127 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Formatter; - -use ScssPhp\ScssPhp\Formatter; - -/** - * Debug formatter - * - * @author Anthon Pang <anthon.pang@gmail.com> - * - * @deprecated since 1.4.0. - * - * @internal - */ -class Debug extends Formatter -{ - /** - * {@inheritdoc} - */ - public function __construct() - { - @trigger_error('The Debug formatter is deprecated since 1.4.0.', E_USER_DEPRECATED); - - $this->indentLevel = 0; - $this->indentChar = ''; - $this->break = "\n"; - $this->open = ' {'; - $this->close = ' }'; - $this->tagSeparator = ', '; - $this->assignSeparator = ': '; - $this->keepSemicolons = true; - } - - /** - * {@inheritdoc} - */ - protected function indentStr() - { - return str_repeat(' ', $this->indentLevel); - } - - /** - * {@inheritdoc} - */ - protected function blockLines(OutputBlock $block) - { - $indent = $this->indentStr(); - - if (empty($block->lines)) { - $this->write("{$indent}block->lines: []\n"); - - return; - } - - foreach ($block->lines as $index => $line) { - $this->write("{$indent}block->lines[{$index}]: $line\n"); - } - } - - /** - * {@inheritdoc} - */ - protected function blockSelectors(OutputBlock $block) - { - $indent = $this->indentStr(); - - if (empty($block->selectors)) { - $this->write("{$indent}block->selectors: []\n"); - - return; - } - - foreach ($block->selectors as $index => $selector) { - $this->write("{$indent}block->selectors[{$index}]: $selector\n"); - } - } - - /** - * {@inheritdoc} - */ - protected function blockChildren(OutputBlock $block) - { - $indent = $this->indentStr(); - - if (empty($block->children)) { - $this->write("{$indent}block->children: []\n"); - - return; - } - - $this->indentLevel++; - - foreach ($block->children as $i => $child) { - $this->block($child); - } - - $this->indentLevel--; - } - - /** - * {@inheritdoc} - */ - protected function block(OutputBlock $block) - { - $indent = $this->indentStr(); - - $this->write("{$indent}block->type: {$block->type}\n" . - "{$indent}block->depth: {$block->depth}\n"); - - $this->currentBlock = $block; - - $this->blockSelectors($block); - $this->blockLines($block); - $this->blockChildren($block); - } -} diff --git a/lib/scssphp/scssphp/src/Formatter/Expanded.php b/lib/scssphp/scssphp/src/Formatter/Expanded.php deleted file mode 100644 index 6eb4a0cb7..000000000 --- a/lib/scssphp/scssphp/src/Formatter/Expanded.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Formatter; - -use ScssPhp\ScssPhp\Formatter; - -/** - * Expanded formatter - * - * @author Leaf Corcoran <leafot@gmail.com> - * - * @internal - */ -class Expanded extends Formatter -{ - /** - * {@inheritdoc} - */ - public function __construct() - { - $this->indentLevel = 0; - $this->indentChar = ' '; - $this->break = "\n"; - $this->open = ' {'; - $this->close = '}'; - $this->tagSeparator = ', '; - $this->assignSeparator = ': '; - $this->keepSemicolons = true; - } - - /** - * {@inheritdoc} - */ - protected function indentStr() - { - return str_repeat($this->indentChar, $this->indentLevel); - } - - /** - * {@inheritdoc} - */ - protected function blockLines(OutputBlock $block) - { - $inner = $this->indentStr(); - - $glue = $this->break . $inner; - - foreach ($block->lines as $index => $line) { - if (substr($line, 0, 2) === '/*') { - $replacedLine = preg_replace('/\r\n?|\n|\f/', $this->break, $line); - assert($replacedLine !== null); - $block->lines[$index] = $replacedLine; - } - } - - $this->write($inner . implode($glue, $block->lines)); - - if (empty($block->selectors) || ! empty($block->children)) { - $this->write($this->break); - } - } -} diff --git a/lib/scssphp/scssphp/src/Formatter/Nested.php b/lib/scssphp/scssphp/src/Formatter/Nested.php deleted file mode 100644 index d5ed85cc2..000000000 --- a/lib/scssphp/scssphp/src/Formatter/Nested.php +++ /dev/null @@ -1,238 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Formatter; - -use ScssPhp\ScssPhp\Formatter; -use ScssPhp\ScssPhp\Type; - -/** - * Nested formatter - * - * @author Leaf Corcoran <leafot@gmail.com> - * - * @deprecated since 1.4.0. Use the Expanded formatter instead. - * - * @internal - */ -class Nested extends Formatter -{ - /** - * @var int - */ - private $depth; - - /** - * {@inheritdoc} - */ - public function __construct() - { - @trigger_error('The Nested formatter is deprecated since 1.4.0. Use the Expanded formatter instead.', E_USER_DEPRECATED); - - $this->indentLevel = 0; - $this->indentChar = ' '; - $this->break = "\n"; - $this->open = ' {'; - $this->close = ' }'; - $this->tagSeparator = ', '; - $this->assignSeparator = ': '; - $this->keepSemicolons = true; - } - - /** - * {@inheritdoc} - */ - protected function indentStr() - { - $n = $this->depth - 1; - - return str_repeat($this->indentChar, max($this->indentLevel + $n, 0)); - } - - /** - * {@inheritdoc} - */ - protected function blockLines(OutputBlock $block) - { - $inner = $this->indentStr(); - $glue = $this->break . $inner; - - foreach ($block->lines as $index => $line) { - if (substr($line, 0, 2) === '/*') { - $replacedLine = preg_replace('/\r\n?|\n|\f/', $this->break, $line); - assert($replacedLine !== null); - $block->lines[$index] = $replacedLine; - } - } - - $this->write($inner . implode($glue, $block->lines)); - } - - /** - * {@inheritdoc} - */ - protected function block(OutputBlock $block) - { - static $depths; - static $downLevel; - static $closeBlock; - static $previousEmpty; - static $previousHasSelector; - - if ($block->type === 'root') { - $depths = [ 0 ]; - $downLevel = ''; - $closeBlock = ''; - $this->depth = 0; - $previousEmpty = false; - $previousHasSelector = false; - } - - $isMediaOrDirective = \in_array($block->type, [Type::T_DIRECTIVE, Type::T_MEDIA]); - $isSupport = ($block->type === Type::T_DIRECTIVE - && $block->selectors && strpos(implode('', $block->selectors), '@supports') !== false); - - while ($block->depth < end($depths) || ($block->depth == 1 && end($depths) == 1)) { - array_pop($depths); - $this->depth--; - - if ( - ! $this->depth && ($block->depth <= 1 || (! $this->indentLevel && $block->type === Type::T_COMMENT)) && - (($block->selectors && ! $isMediaOrDirective) || $previousHasSelector) - ) { - $downLevel = $this->break; - } - - if (empty($block->lines) && empty($block->children)) { - $previousEmpty = true; - } - } - - if (empty($block->lines) && empty($block->children)) { - return; - } - - $this->currentBlock = $block; - - if (! empty($block->lines) || (! empty($block->children) && ($this->depth < 1 || $isSupport))) { - if ($block->depth > end($depths)) { - if (! $previousEmpty || $this->depth < 1) { - $this->depth++; - - $depths[] = $block->depth; - } else { - // keep the current depth unchanged but take the block depth as a new reference for following blocks - array_pop($depths); - - $depths[] = $block->depth; - } - } - } - - $previousEmpty = ($block->type === Type::T_COMMENT); - $previousHasSelector = false; - - if (! empty($block->selectors)) { - if ($closeBlock) { - $this->write($closeBlock); - $closeBlock = ''; - } - - if ($downLevel) { - $this->write($downLevel); - $downLevel = ''; - } - - $this->blockSelectors($block); - - $this->indentLevel++; - } - - if (! empty($block->lines)) { - if ($closeBlock) { - $this->write($closeBlock); - $closeBlock = ''; - } - - if ($downLevel) { - $this->write($downLevel); - $downLevel = ''; - } - - $this->blockLines($block); - - $closeBlock = $this->break; - } - - if (! empty($block->children)) { - if ($this->depth > 0 && ($isMediaOrDirective || ! $this->hasFlatChild($block))) { - array_pop($depths); - - $this->depth--; - $this->blockChildren($block); - $this->depth++; - - $depths[] = $block->depth; - } else { - $this->blockChildren($block); - } - } - - // reclear to not be spoiled by children if T_DIRECTIVE - if ($block->type === Type::T_DIRECTIVE) { - $previousHasSelector = false; - } - - if (! empty($block->selectors)) { - $this->indentLevel--; - - if (! $this->keepSemicolons) { - $this->strippedSemicolon = ''; - } - - $this->write($this->close); - - $closeBlock = $this->break; - - if ($this->depth > 1 && ! empty($block->children)) { - array_pop($depths); - $this->depth--; - } - - if (! $isMediaOrDirective) { - $previousHasSelector = true; - } - } - - if ($block->type === 'root') { - $this->write($this->break); - } - } - - /** - * Block has flat child - * - * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block - * - * @return bool - */ - private function hasFlatChild($block) - { - foreach ($block->children as $child) { - if (empty($child->selectors)) { - return true; - } - } - - return false; - } -} diff --git a/lib/scssphp/scssphp/src/Formatter/OutputBlock.php b/lib/scssphp/scssphp/src/Formatter/OutputBlock.php deleted file mode 100644 index 2799656a4..000000000 --- a/lib/scssphp/scssphp/src/Formatter/OutputBlock.php +++ /dev/null @@ -1,68 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Formatter; - -/** - * Output block - * - * @author Anthon Pang <anthon.pang@gmail.com> - * - * @internal - */ -class OutputBlock -{ - /** - * @var string|null - */ - public $type; - - /** - * @var int - */ - public $depth; - - /** - * @var array|null - */ - public $selectors; - - /** - * @var string[] - */ - public $lines; - - /** - * @var OutputBlock[] - */ - public $children; - - /** - * @var OutputBlock|null - */ - public $parent; - - /** - * @var string|null - */ - public $sourceName; - - /** - * @var int|null - */ - public $sourceLine; - - /** - * @var int|null - */ - public $sourceColumn; -} diff --git a/lib/scssphp/scssphp/src/Logger/LoggerInterface.php b/lib/scssphp/scssphp/src/Logger/LoggerInterface.php deleted file mode 100644 index 7c0a2f76e..000000000 --- a/lib/scssphp/scssphp/src/Logger/LoggerInterface.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Logger; - -/** - * Interface implemented by loggers for warnings and debug messages. - * - * The official Sass implementation recommends that loggers report the - * messages immediately rather than waiting for the end of the - * compilation, to provide a better debugging experience when the - * compilation does not end (error or infinite loop after the warning - * for instance). - */ -interface LoggerInterface -{ - /** - * Emits a warning with the given message. - * - * If $deprecation is true, it indicates that this is a deprecation - * warning. Implementations should surface all this information to - * the end user. - * - * @param string $message - * @param bool $deprecation - * - * @return void - */ - public function warn($message, $deprecation = false); - - /** - * Emits a debugging message. - * - * @param string $message - * - * @return void - */ - public function debug($message); -} diff --git a/lib/scssphp/scssphp/src/Logger/QuietLogger.php b/lib/scssphp/scssphp/src/Logger/QuietLogger.php deleted file mode 100644 index ad7c07537..000000000 --- a/lib/scssphp/scssphp/src/Logger/QuietLogger.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Logger; - -/** - * A logger that silently ignores all messages. - * - * @final - */ -class QuietLogger implements LoggerInterface -{ - public function warn($message, $deprecation = false) - { - } - - public function debug($message) - { - } -} diff --git a/lib/scssphp/scssphp/src/Logger/StreamLogger.php b/lib/scssphp/scssphp/src/Logger/StreamLogger.php deleted file mode 100644 index 7db7cc189..000000000 --- a/lib/scssphp/scssphp/src/Logger/StreamLogger.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Logger; - -/** - * A logger that prints to a PHP stream (for instance stderr) - * - * @final - */ -class StreamLogger implements LoggerInterface -{ - private $stream; - private $closeOnDestruct; - - /** - * @param resource $stream A stream resource - * @param bool $closeOnDestruct If true, takes ownership of the stream and close it on destruct to avoid leaks. - */ - public function __construct($stream, $closeOnDestruct = false) - { - $this->stream = $stream; - $this->closeOnDestruct = $closeOnDestruct; - } - - /** - * @internal - */ - public function __destruct() - { - if ($this->closeOnDestruct) { - fclose($this->stream); - } - } - - /** - * @inheritDoc - */ - public function warn($message, $deprecation = false) - { - $prefix = ($deprecation ? 'DEPRECATION ' : '') . 'WARNING: '; - - fwrite($this->stream, $prefix . $message . "\n\n"); - } - - /** - * @inheritDoc - */ - public function debug($message) - { - fwrite($this->stream, $message . "\n"); - } -} diff --git a/lib/scssphp/scssphp/src/Node.php b/lib/scssphp/scssphp/src/Node.php deleted file mode 100644 index fcaf8a95f..000000000 --- a/lib/scssphp/scssphp/src/Node.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp; - -/** - * Base node - * - * @author Anthon Pang <anthon.pang@gmail.com> - * - * @internal - */ -abstract class Node -{ - /** - * @var string - */ - public $type; - - /** - * @var int - */ - public $sourceIndex; - - /** - * @var int|null - */ - public $sourceLine; - - /** - * @var int|null - */ - public $sourceColumn; -} diff --git a/lib/scssphp/scssphp/src/Node/Number.php b/lib/scssphp/scssphp/src/Node/Number.php deleted file mode 100644 index ca9b5b652..000000000 --- a/lib/scssphp/scssphp/src/Node/Number.php +++ /dev/null @@ -1,804 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\Node; - -use ScssPhp\ScssPhp\Base\Range; -use ScssPhp\ScssPhp\Compiler; -use ScssPhp\ScssPhp\Exception\RangeException; -use ScssPhp\ScssPhp\Exception\SassScriptException; -use ScssPhp\ScssPhp\Node; -use ScssPhp\ScssPhp\Type; -use ScssPhp\ScssPhp\Util; - -/** - * Dimension + optional units - * - * {@internal - * This is a work-in-progress. - * - * The \ArrayAccess interface is temporary until the migration is complete. - * }} - * - * @author Anthon Pang <anthon.pang@gmail.com> - * - * @template-implements \ArrayAccess<int, mixed> - */ -class Number extends Node implements \ArrayAccess -{ - const PRECISION = 10; - - /** - * @var int - * @deprecated use {Number::PRECISION} instead to read the precision. Configuring it is not supported anymore. - */ - public static $precision = self::PRECISION; - - /** - * @see http://www.w3.org/TR/2012/WD-css3-values-20120308/ - * - * @var array - * @phpstan-var array<string, array<string, float|int>> - */ - protected static $unitTable = [ - 'in' => [ - 'in' => 1, - 'pc' => 6, - 'pt' => 72, - 'px' => 96, - 'cm' => 2.54, - 'mm' => 25.4, - 'q' => 101.6, - ], - 'turn' => [ - 'deg' => 360, - 'grad' => 400, - 'rad' => 6.28318530717958647692528676, // 2 * M_PI - 'turn' => 1, - ], - 's' => [ - 's' => 1, - 'ms' => 1000, - ], - 'Hz' => [ - 'Hz' => 1, - 'kHz' => 0.001, - ], - 'dpi' => [ - 'dpi' => 1, - 'dpcm' => 1 / 2.54, - 'dppx' => 1 / 96, - ], - ]; - - /** - * @var int|float - */ - private $dimension; - - /** - * @var string[] - * @phpstan-var list<string> - */ - private $numeratorUnits; - - /** - * @var string[] - * @phpstan-var list<string> - */ - private $denominatorUnits; - - /** - * Initialize number - * - * @param int|float $dimension - * @param string[]|string $numeratorUnits - * @param string[] $denominatorUnits - * - * @phpstan-param list<string>|string $numeratorUnits - * @phpstan-param list<string> $denominatorUnits - */ - public function __construct($dimension, $numeratorUnits, array $denominatorUnits = []) - { - if (is_string($numeratorUnits)) { - $numeratorUnits = $numeratorUnits ? [$numeratorUnits] : []; - } elseif (isset($numeratorUnits['numerator_units'], $numeratorUnits['denominator_units'])) { - // TODO get rid of this once `$number[2]` is not used anymore - $denominatorUnits = $numeratorUnits['denominator_units']; - $numeratorUnits = $numeratorUnits['numerator_units']; - } - - $this->dimension = $dimension; - $this->numeratorUnits = $numeratorUnits; - $this->denominatorUnits = $denominatorUnits; - } - - /** - * @return float|int - */ - public function getDimension() - { - return $this->dimension; - } - - /** - * @return string[] - */ - public function getNumeratorUnits() - { - return $this->numeratorUnits; - } - - /** - * @return string[] - */ - public function getDenominatorUnits() - { - return $this->denominatorUnits; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function offsetExists($offset) - { - if ($offset === -3) { - return ! \is_null($this->sourceColumn); - } - - if ($offset === -2) { - return ! \is_null($this->sourceLine); - } - - if ( - $offset === -1 || - $offset === 0 || - $offset === 1 || - $offset === 2 - ) { - return true; - } - - return false; - } - - /** - * @return mixed - */ - #[\ReturnTypeWillChange] - public function offsetGet($offset) - { - switch ($offset) { - case -3: - return $this->sourceColumn; - - case -2: - return $this->sourceLine; - - case -1: - return $this->sourceIndex; - - case 0: - return Type::T_NUMBER; - - case 1: - return $this->dimension; - - case 2: - return array('numerator_units' => $this->numeratorUnits, 'denominator_units' => $this->denominatorUnits); - } - } - - /** - * @return void - */ - #[\ReturnTypeWillChange] - public function offsetSet($offset, $value) - { - throw new \BadMethodCallException('Number is immutable'); - } - - /** - * @return void - */ - #[\ReturnTypeWillChange] - public function offsetUnset($offset) - { - throw new \BadMethodCallException('Number is immutable'); - } - - /** - * Returns true if the number is unitless - * - * @return bool - */ - public function unitless() - { - return \count($this->numeratorUnits) === 0 && \count($this->denominatorUnits) === 0; - } - - /** - * Checks whether the number has exactly this unit - * - * @param string $unit - * - * @return bool - */ - public function hasUnit($unit) - { - return \count($this->numeratorUnits) === 1 && \count($this->denominatorUnits) === 0 && $this->numeratorUnits[0] === $unit; - } - - /** - * Returns unit(s) as the product of numerator units divided by the product of denominator units - * - * @return string - */ - public function unitStr() - { - if ($this->unitless()) { - return ''; - } - - return self::getUnitString($this->numeratorUnits, $this->denominatorUnits); - } - - /** - * @param float|int $min - * @param float|int $max - * @param string|null $name - * - * @return float|int - * @throws SassScriptException - */ - public function valueInRange($min, $max, $name = null) - { - try { - return Util::checkRange('', new Range($min, $max), $this); - } catch (RangeException $e) { - throw SassScriptException::forArgument(sprintf('Expected %s to be within %s%s and %s%3$s', $this, $min, $this->unitStr(), $max), $name); - } - } - - /** - * @param string|null $varName - * - * @return void - */ - public function assertNoUnits($varName = null) - { - if ($this->unitless()) { - return; - } - - throw SassScriptException::forArgument(sprintf('Expected %s to have no units.', $this), $varName); - } - - /** - * @param string $unit - * @param string|null $varName - * - * @return void - */ - public function assertUnit($unit, $varName = null) - { - if ($this->hasUnit($unit)) { - return; - } - - throw SassScriptException::forArgument(sprintf('Expected %s to have unit "%s".', $this, $unit), $varName); - } - - /** - * @param Number $other - * - * @return void - */ - public function assertSameUnitOrUnitless(Number $other) - { - if ($other->unitless()) { - return; - } - - if ($this->numeratorUnits === $other->numeratorUnits && $this->denominatorUnits === $other->denominatorUnits) { - return; - } - - throw new SassScriptException(sprintf( - 'Incompatible units %s and %s.', - self::getUnitString($this->numeratorUnits, $this->denominatorUnits), - self::getUnitString($other->numeratorUnits, $other->denominatorUnits) - )); - } - - /** - * Returns a copy of this number, converted to the units represented by $newNumeratorUnits and $newDenominatorUnits. - * - * This does not throw an error if this number is unitless and - * $newNumeratorUnits/$newDenominatorUnits are not empty, or vice versa. Instead, - * it treats all unitless numbers as convertible to and from all units without - * changing the value. - * - * @param string[] $newNumeratorUnits - * @param string[] $newDenominatorUnits - * - * @return Number - * - * @phpstan-param list<string> $newNumeratorUnits - * @phpstan-param list<string> $newDenominatorUnits - * - * @throws SassScriptException if this number's units are not compatible with $newNumeratorUnits and $newDenominatorUnits - */ - public function coerce(array $newNumeratorUnits, array $newDenominatorUnits) - { - return new Number($this->valueInUnits($newNumeratorUnits, $newDenominatorUnits), $newNumeratorUnits, $newDenominatorUnits); - } - - /** - * @param Number $other - * - * @return bool - */ - public function isComparableTo(Number $other) - { - if ($this->unitless() || $other->unitless()) { - return true; - } - - try { - $this->greaterThan($other); - return true; - } catch (SassScriptException $e) { - return false; - } - } - - /** - * @param Number $other - * - * @return bool - */ - public function lessThan(Number $other) - { - return $this->coerceUnits($other, function ($num1, $num2) { - return $num1 < $num2; - }); - } - - /** - * @param Number $other - * - * @return bool - */ - public function lessThanOrEqual(Number $other) - { - return $this->coerceUnits($other, function ($num1, $num2) { - return $num1 <= $num2; - }); - } - - /** - * @param Number $other - * - * @return bool - */ - public function greaterThan(Number $other) - { - return $this->coerceUnits($other, function ($num1, $num2) { - return $num1 > $num2; - }); - } - - /** - * @param Number $other - * - * @return bool - */ - public function greaterThanOrEqual(Number $other) - { - return $this->coerceUnits($other, function ($num1, $num2) { - return $num1 >= $num2; - }); - } - - /** - * @param Number $other - * - * @return Number - */ - public function plus(Number $other) - { - return $this->coerceNumber($other, function ($num1, $num2) { - return $num1 + $num2; - }); - } - - /** - * @param Number $other - * - * @return Number - */ - public function minus(Number $other) - { - return $this->coerceNumber($other, function ($num1, $num2) { - return $num1 - $num2; - }); - } - - /** - * @return Number - */ - public function unaryMinus() - { - return new Number(-$this->dimension, $this->numeratorUnits, $this->denominatorUnits); - } - - /** - * @param Number $other - * - * @return Number - */ - public function modulo(Number $other) - { - return $this->coerceNumber($other, function ($num1, $num2) { - if ($num2 == 0) { - return NAN; - } - - $result = fmod($num1, $num2); - - if ($result == 0) { - return 0; - } - - if ($num2 < 0 xor $num1 < 0) { - $result += $num2; - } - - return $result; - }); - } - - /** - * @param Number $other - * - * @return Number - */ - public function times(Number $other) - { - return $this->multiplyUnits($this->dimension * $other->dimension, $this->numeratorUnits, $this->denominatorUnits, $other->numeratorUnits, $other->denominatorUnits); - } - - /** - * @param Number $other - * - * @return Number - */ - public function dividedBy(Number $other) - { - if ($other->dimension == 0) { - if ($this->dimension == 0) { - $value = NAN; - } elseif ($this->dimension > 0) { - $value = INF; - } else { - $value = -INF; - } - } else { - $value = $this->dimension / $other->dimension; - } - - return $this->multiplyUnits($value, $this->numeratorUnits, $this->denominatorUnits, $other->denominatorUnits, $other->numeratorUnits); - } - - /** - * @param Number $other - * - * @return bool - */ - public function equals(Number $other) - { - // Unitless numbers are convertable to unit numbers, but not equal, so we special-case unitless here. - if ($this->unitless() !== $other->unitless()) { - return false; - } - - // In Sass, neither NaN nor Infinity are equal to themselves, while PHP defines INF==INF - if (is_nan($this->dimension) || is_nan($other->dimension) || !is_finite($this->dimension) || !is_finite($other->dimension)) { - return false; - } - - if ($this->unitless()) { - return round($this->dimension, self::PRECISION) == round($other->dimension, self::PRECISION); - } - - try { - return $this->coerceUnits($other, function ($num1, $num2) { - return round($num1,self::PRECISION) == round($num2, self::PRECISION); - }); - } catch (SassScriptException $e) { - return false; - } - } - - /** - * Output number - * - * @param \ScssPhp\ScssPhp\Compiler $compiler - * - * @return string - */ - public function output(Compiler $compiler = null) - { - $dimension = round($this->dimension, self::PRECISION); - - if (is_nan($dimension)) { - return 'NaN'; - } - - if ($dimension === INF) { - return 'Infinity'; - } - - if ($dimension === -INF) { - return '-Infinity'; - } - - if ($compiler) { - $unit = $this->unitStr(); - } elseif (isset($this->numeratorUnits[0])) { - $unit = $this->numeratorUnits[0]; - } else { - $unit = ''; - } - - $dimension = number_format($dimension, self::PRECISION, '.', ''); - - return rtrim(rtrim($dimension, '0'), '.') . $unit; - } - - /** - * {@inheritdoc} - */ - public function __toString() - { - return $this->output(); - } - - /** - * @param Number $other - * @param callable $operation - * - * @return Number - * - * @phpstan-param callable(int|float, int|float): (int|float) $operation - */ - private function coerceNumber(Number $other, $operation) - { - $result = $this->coerceUnits($other, $operation); - - if (!$this->unitless()) { - return new Number($result, $this->numeratorUnits, $this->denominatorUnits); - } - - return new Number($result, $other->numeratorUnits, $other->denominatorUnits); - } - - /** - * @param Number $other - * @param callable $operation - * - * @return mixed - * - * @phpstan-template T - * @phpstan-param callable(int|float, int|float): T $operation - * @phpstan-return T - */ - private function coerceUnits(Number $other, $operation) - { - if (!$this->unitless()) { - $num1 = $this->dimension; - $num2 = $other->valueInUnits($this->numeratorUnits, $this->denominatorUnits); - } else { - $num1 = $this->valueInUnits($other->numeratorUnits, $other->denominatorUnits); - $num2 = $other->dimension; - } - - return \call_user_func($operation, $num1, $num2); - } - - /** - * @param string[] $numeratorUnits - * @param string[] $denominatorUnits - * - * @return int|float - * - * @phpstan-param list<string> $numeratorUnits - * @phpstan-param list<string> $denominatorUnits - * - * @throws SassScriptException if this number's units are not compatible with $numeratorUnits and $denominatorUnits - */ - private function valueInUnits(array $numeratorUnits, array $denominatorUnits) - { - if ( - $this->unitless() - || (\count($numeratorUnits) === 0 && \count($denominatorUnits) === 0) - || ($this->numeratorUnits === $numeratorUnits && $this->denominatorUnits === $denominatorUnits) - ) { - return $this->dimension; - } - - $value = $this->dimension; - $oldNumerators = $this->numeratorUnits; - - foreach ($numeratorUnits as $newNumerator) { - foreach ($oldNumerators as $key => $oldNumerator) { - $conversionFactor = self::getConversionFactor($newNumerator, $oldNumerator); - - if (\is_null($conversionFactor)) { - continue; - } - - $value *= $conversionFactor; - unset($oldNumerators[$key]); - continue 2; - } - - throw new SassScriptException(sprintf( - 'Incompatible units %s and %s.', - self::getUnitString($this->numeratorUnits, $this->denominatorUnits), - self::getUnitString($numeratorUnits, $denominatorUnits) - )); - } - - $oldDenominators = $this->denominatorUnits; - - foreach ($denominatorUnits as $newDenominator) { - foreach ($oldDenominators as $key => $oldDenominator) { - $conversionFactor = self::getConversionFactor($newDenominator, $oldDenominator); - - if (\is_null($conversionFactor)) { - continue; - } - - $value /= $conversionFactor; - unset($oldDenominators[$key]); - continue 2; - } - - throw new SassScriptException(sprintf( - 'Incompatible units %s and %s.', - self::getUnitString($this->numeratorUnits, $this->denominatorUnits), - self::getUnitString($numeratorUnits, $denominatorUnits) - )); - } - - if (\count($oldNumerators) || \count($oldDenominators)) { - throw new SassScriptException(sprintf( - 'Incompatible units %s and %s.', - self::getUnitString($this->numeratorUnits, $this->denominatorUnits), - self::getUnitString($numeratorUnits, $denominatorUnits) - )); - } - - return $value; - } - - /** - * @param int|float $value - * @param string[] $numerators1 - * @param string[] $denominators1 - * @param string[] $numerators2 - * @param string[] $denominators2 - * - * @return Number - * - * @phpstan-param list<string> $numerators1 - * @phpstan-param list<string> $denominators1 - * @phpstan-param list<string> $numerators2 - * @phpstan-param list<string> $denominators2 - */ - private function multiplyUnits($value, array $numerators1, array $denominators1, array $numerators2, array $denominators2) - { - $newNumerators = array(); - - foreach ($numerators1 as $numerator) { - foreach ($denominators2 as $key => $denominator) { - $conversionFactor = self::getConversionFactor($numerator, $denominator); - - if (\is_null($conversionFactor)) { - continue; - } - - $value /= $conversionFactor; - unset($denominators2[$key]); - continue 2; - } - - $newNumerators[] = $numerator; - } - - foreach ($numerators2 as $numerator) { - foreach ($denominators1 as $key => $denominator) { - $conversionFactor = self::getConversionFactor($numerator, $denominator); - - if (\is_null($conversionFactor)) { - continue; - } - - $value /= $conversionFactor; - unset($denominators1[$key]); - continue 2; - } - - $newNumerators[] = $numerator; - } - - $newDenominators = array_values(array_merge($denominators1, $denominators2)); - - return new Number($value, $newNumerators, $newDenominators); - } - - /** - * Returns the number of [unit1]s per [unit2]. - * - * Equivalently, `1unit1 * conversionFactor(unit1, unit2) = 1unit2`. - * - * @param string $unit1 - * @param string $unit2 - * - * @return float|int|null - */ - private static function getConversionFactor($unit1, $unit2) - { - if ($unit1 === $unit2) { - return 1; - } - - foreach (static::$unitTable as $unitVariants) { - if (isset($unitVariants[$unit1]) && isset($unitVariants[$unit2])) { - return $unitVariants[$unit1] / $unitVariants[$unit2]; - } - } - - return null; - } - - /** - * Returns unit(s) as the product of numerator units divided by the product of denominator units - * - * @param string[] $numerators - * @param string[] $denominators - * - * @phpstan-param list<string> $numerators - * @phpstan-param list<string> $denominators - * - * @return string - */ - private static function getUnitString(array $numerators, array $denominators) - { - if (!\count($numerators)) { - if (\count($denominators) === 0) { - return 'no units'; - } - - if (\count($denominators) === 1) { - return $denominators[0] . '^-1'; - } - - return '(' . implode('*', $denominators) . ')^-1'; - } - - return implode('*', $numerators) . (\count($denominators) ? '/' . implode('*', $denominators) : ''); - } -} diff --git a/lib/scssphp/scssphp/src/OutputStyle.php b/lib/scssphp/scssphp/src/OutputStyle.php deleted file mode 100644 index c284639c1..000000000 --- a/lib/scssphp/scssphp/src/OutputStyle.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -namespace ScssPhp\ScssPhp; - -final class OutputStyle -{ - const EXPANDED = 'expanded'; - const COMPRESSED = 'compressed'; -} diff --git a/lib/scssphp/scssphp/src/Parser.php b/lib/scssphp/scssphp/src/Parser.php deleted file mode 100644 index e9cbaf375..000000000 --- a/lib/scssphp/scssphp/src/Parser.php +++ /dev/null @@ -1,4201 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp; - -use ScssPhp\ScssPhp\Block\AtRootBlock; -use ScssPhp\ScssPhp\Block\CallableBlock; -use ScssPhp\ScssPhp\Block\ContentBlock; -use ScssPhp\ScssPhp\Block\DirectiveBlock; -use ScssPhp\ScssPhp\Block\EachBlock; -use ScssPhp\ScssPhp\Block\ElseBlock; -use ScssPhp\ScssPhp\Block\ElseifBlock; -use ScssPhp\ScssPhp\Block\ForBlock; -use ScssPhp\ScssPhp\Block\IfBlock; -use ScssPhp\ScssPhp\Block\MediaBlock; -use ScssPhp\ScssPhp\Block\NestedPropertyBlock; -use ScssPhp\ScssPhp\Block\WhileBlock; -use ScssPhp\ScssPhp\Exception\ParserException; -use ScssPhp\ScssPhp\Logger\LoggerInterface; -use ScssPhp\ScssPhp\Logger\QuietLogger; -use ScssPhp\ScssPhp\Node\Number; - -/** - * Parser - * - * @author Leaf Corcoran <leafot@gmail.com> - * - * @internal - */ -class Parser -{ - const SOURCE_INDEX = -1; - const SOURCE_LINE = -2; - const SOURCE_COLUMN = -3; - - /** - * @var array<string, int> - */ - protected static $precedence = [ - '=' => 0, - 'or' => 1, - 'and' => 2, - '==' => 3, - '!=' => 3, - '<=' => 4, - '>=' => 4, - '<' => 4, - '>' => 4, - '+' => 5, - '-' => 5, - '*' => 6, - '/' => 6, - '%' => 6, - ]; - - /** - * @var string - */ - protected static $commentPattern; - /** - * @var string - */ - protected static $operatorPattern; - /** - * @var string - */ - protected static $whitePattern; - - /** - * @var Cache|null - */ - protected $cache; - - private $sourceName; - private $sourceIndex; - /** - * @var array<int, int> - */ - private $sourcePositions; - /** - * The current offset in the buffer - * - * @var int - */ - private $count; - /** - * @var Block|null - */ - private $env; - /** - * @var bool - */ - private $inParens; - /** - * @var bool - */ - private $eatWhiteDefault; - /** - * @var bool - */ - private $discardComments; - private $allowVars; - /** - * @var string - */ - private $buffer; - private $utf8; - /** - * @var string|null - */ - private $encoding; - private $patternModifiers; - private $commentsSeen; - - private $cssOnly; - - /** - * @var LoggerInterface - */ - private $logger; - - /** - * Constructor - * - * @api - * - * @param string|null $sourceName - * @param int $sourceIndex - * @param string|null $encoding - * @param Cache|null $cache - * @param bool $cssOnly - * @param LoggerInterface|null $logger - */ - public function __construct($sourceName, $sourceIndex = 0, $encoding = 'utf-8', Cache $cache = null, $cssOnly = false, LoggerInterface $logger = null) - { - $this->sourceName = $sourceName ?: '(stdin)'; - $this->sourceIndex = $sourceIndex; - $this->utf8 = ! $encoding || strtolower($encoding) === 'utf-8'; - $this->patternModifiers = $this->utf8 ? 'Aisu' : 'Ais'; - $this->commentsSeen = []; - $this->allowVars = true; - $this->cssOnly = $cssOnly; - $this->logger = $logger ?: new QuietLogger(); - - if (empty(static::$operatorPattern)) { - static::$operatorPattern = '([*\/%+-]|[!=]\=|\>\=?|\<\=?|and|or)'; - - $commentSingle = '\/\/'; - $commentMultiLeft = '\/\*'; - $commentMultiRight = '\*\/'; - - static::$commentPattern = $commentMultiLeft . '.*?' . $commentMultiRight; - static::$whitePattern = $this->utf8 - ? '/' . $commentSingle . '[^\n]*\s*|(' . static::$commentPattern . ')\s*|\s+/AisuS' - : '/' . $commentSingle . '[^\n]*\s*|(' . static::$commentPattern . ')\s*|\s+/AisS'; - } - - $this->cache = $cache; - } - - /** - * Get source file name - * - * @api - * - * @return string - */ - public function getSourceName() - { - return $this->sourceName; - } - - /** - * Throw parser error - * - * @api - * - * @param string $msg - * - * @phpstan-return never-return - * - * @throws ParserException - * - * @deprecated use "parseError" and throw the exception in the caller instead. - */ - public function throwParseError($msg = 'parse error') - { - @trigger_error( - 'The method "throwParseError" is deprecated. Use "parseError" and throw the exception in the caller instead', - E_USER_DEPRECATED - ); - - throw $this->parseError($msg); - } - - /** - * Creates a parser error - * - * @api - * - * @param string $msg - * - * @return ParserException - */ - public function parseError($msg = 'parse error') - { - list($line, $column) = $this->getSourcePosition($this->count); - - $loc = empty($this->sourceName) - ? "line: $line, column: $column" - : "$this->sourceName on line $line, at column $column"; - - if ($this->peek('(.*?)(\n|$)', $m, $this->count)) { - $this->restoreEncoding(); - - $e = new ParserException("$msg: failed at `$m[1]` $loc"); - $e->setSourcePosition([$this->sourceName, $line, $column]); - - return $e; - } - - $this->restoreEncoding(); - - $e = new ParserException("$msg: $loc"); - $e->setSourcePosition([$this->sourceName, $line, $column]); - - return $e; - } - - /** - * Parser buffer - * - * @api - * - * @param string $buffer - * - * @return Block - */ - public function parse($buffer) - { - if ($this->cache) { - $cacheKey = $this->sourceName . ':' . md5($buffer); - $parseOptions = [ - 'utf8' => $this->utf8, - ]; - $v = $this->cache->getCache('parse', $cacheKey, $parseOptions); - - if (! \is_null($v)) { - return $v; - } - } - - // strip BOM (byte order marker) - if (substr($buffer, 0, 3) === "\xef\xbb\xbf") { - $buffer = substr($buffer, 3); - } - - $this->buffer = rtrim($buffer, "\x00..\x1f"); - $this->count = 0; - $this->env = null; - $this->inParens = false; - $this->eatWhiteDefault = true; - - $this->saveEncoding(); - $this->extractLineNumbers($buffer); - - $this->pushBlock(null); // root block - $this->whitespace(); - $this->pushBlock(null); - $this->popBlock(); - - while ($this->parseChunk()) { - ; - } - - if ($this->count !== \strlen($this->buffer)) { - throw $this->parseError(); - } - - if (! empty($this->env->parent)) { - throw $this->parseError('unclosed block'); - } - - $this->restoreEncoding(); - assert($this->env !== null); - - if ($this->cache) { - $this->cache->setCache('parse', $cacheKey, $this->env, $parseOptions); - } - - return $this->env; - } - - /** - * Parse a value or value list - * - * @api - * - * @param string $buffer - * @param string|array $out - * - * @return bool - */ - public function parseValue($buffer, &$out) - { - $this->count = 0; - $this->env = null; - $this->inParens = false; - $this->eatWhiteDefault = true; - $this->buffer = (string) $buffer; - - $this->saveEncoding(); - $this->extractLineNumbers($this->buffer); - - $list = $this->valueList($out); - - $this->restoreEncoding(); - - return $list; - } - - /** - * Parse a selector or selector list - * - * @api - * - * @param string $buffer - * @param string|array $out - * @param bool $shouldValidate - * - * @return bool - */ - public function parseSelector($buffer, &$out, $shouldValidate = true) - { - $this->count = 0; - $this->env = null; - $this->inParens = false; - $this->eatWhiteDefault = true; - $this->buffer = (string) $buffer; - - $this->saveEncoding(); - $this->extractLineNumbers($this->buffer); - - // discard space/comments at the start - $this->discardComments = true; - $this->whitespace(); - $this->discardComments = false; - - $selector = $this->selectors($out); - - $this->restoreEncoding(); - - if ($shouldValidate && $this->count !== strlen($buffer)) { - throw $this->parseError("`" . substr($buffer, $this->count) . "` is not a valid Selector in `$buffer`"); - } - - return $selector; - } - - /** - * Parse a media Query - * - * @api - * - * @param string $buffer - * @param array $out - * - * @return bool - */ - public function parseMediaQueryList($buffer, &$out) - { - $this->count = 0; - $this->env = null; - $this->inParens = false; - $this->eatWhiteDefault = true; - $this->buffer = (string) $buffer; - - $this->saveEncoding(); - $this->extractLineNumbers($this->buffer); - - $isMediaQuery = $this->mediaQueryList($out); - - $this->restoreEncoding(); - - return $isMediaQuery; - } - - /** - * Parse a single chunk off the head of the buffer and append it to the - * current parse environment. - * - * Returns false when the buffer is empty, or when there is an error. - * - * This function is called repeatedly until the entire document is - * parsed. - * - * This parser is most similar to a recursive descent parser. Single - * functions represent discrete grammatical rules for the language, and - * they are able to capture the text that represents those rules. - * - * Consider the function Compiler::keyword(). (All parse functions are - * structured the same.) - * - * The function takes a single reference argument. When calling the - * function it will attempt to match a keyword on the head of the buffer. - * If it is successful, it will place the keyword in the referenced - * argument, advance the position in the buffer, and return true. If it - * fails then it won't advance the buffer and it will return false. - * - * All of these parse functions are powered by Compiler::match(), which behaves - * the same way, but takes a literal regular expression. Sometimes it is - * more convenient to use match instead of creating a new function. - * - * Because of the format of the functions, to parse an entire string of - * grammatical rules, you can chain them together using &&. - * - * But, if some of the rules in the chain succeed before one fails, then - * the buffer position will be left at an invalid state. In order to - * avoid this, Compiler::seek() is used to remember and set buffer positions. - * - * Before parsing a chain, use $s = $this->count to remember the current - * position into $s. Then if a chain fails, use $this->seek($s) to - * go back where we started. - * - * @return bool - */ - protected function parseChunk() - { - $s = $this->count; - - // the directives - if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] === '@') { - if ( - $this->literal('@at-root', 8) && - ($this->selectors($selector) || true) && - ($this->map($with) || true) && - (($this->matchChar('(') && - $this->interpolation($with) && - $this->matchChar(')')) || true) && - $this->matchChar('{', false) - ) { - ! $this->cssOnly || $this->assertPlainCssValid(false, $s); - - $atRoot = new AtRootBlock(); - $this->registerPushedBlock($atRoot, $s); - $atRoot->selector = $selector; - $atRoot->with = $with; - - return true; - } - - $this->seek($s); - - if ( - $this->literal('@media', 6) && - $this->mediaQueryList($mediaQueryList) && - $this->matchChar('{', false) - ) { - $media = new MediaBlock(); - $this->registerPushedBlock($media, $s); - $media->queryList = $mediaQueryList[2]; - - return true; - } - - $this->seek($s); - - if ( - $this->literal('@mixin', 6) && - $this->keyword($mixinName) && - ($this->argumentDef($args) || true) && - $this->matchChar('{', false) - ) { - ! $this->cssOnly || $this->assertPlainCssValid(false, $s); - - $mixin = new CallableBlock(Type::T_MIXIN); - $this->registerPushedBlock($mixin, $s); - $mixin->name = $mixinName; - $mixin->args = $args; - - return true; - } - - $this->seek($s); - - if ( - ($this->literal('@include', 8) && - $this->keyword($mixinName) && - ($this->matchChar('(') && - ($this->argValues($argValues) || true) && - $this->matchChar(')') || true) && - ($this->end()) || - ($this->literal('using', 5) && - $this->argumentDef($argUsing) && - ($this->end() || $this->matchChar('{') && $hasBlock = true)) || - $this->matchChar('{') && $hasBlock = true) - ) { - ! $this->cssOnly || $this->assertPlainCssValid(false, $s); - - $child = [ - Type::T_INCLUDE, - $mixinName, - isset($argValues) ? $argValues : null, - null, - isset($argUsing) ? $argUsing : null - ]; - - if (! empty($hasBlock)) { - $include = new ContentBlock(); - $this->registerPushedBlock($include, $s); - $include->child = $child; - } else { - $this->append($child, $s); - } - - return true; - } - - $this->seek($s); - - if ( - $this->literal('@scssphp-import-once', 20) && - $this->valueList($importPath) && - $this->end() - ) { - ! $this->cssOnly || $this->assertPlainCssValid(false, $s); - - list($line, $column) = $this->getSourcePosition($s); - $file = $this->sourceName; - $this->logger->warn("The \"@scssphp-import-once\" directive is deprecated and will be removed in ScssPhp 2.0, in \"$file\", line $line, column $column.", true); - - $this->append([Type::T_SCSSPHP_IMPORT_ONCE, $importPath], $s); - - return true; - } - - $this->seek($s); - - if ( - $this->literal('@import', 7) && - $this->valueList($importPath) && - $importPath[0] !== Type::T_FUNCTION_CALL && - $this->end() - ) { - if ($this->cssOnly) { - $this->assertPlainCssValid([Type::T_IMPORT, $importPath], $s); - $this->append([Type::T_COMMENT, rtrim(substr($this->buffer, $s, $this->count - $s))]); - return true; - } - - $this->append([Type::T_IMPORT, $importPath], $s); - - return true; - } - - $this->seek($s); - - if ( - $this->literal('@import', 7) && - $this->url($importPath) && - $this->end() - ) { - if ($this->cssOnly) { - $this->assertPlainCssValid([Type::T_IMPORT, $importPath], $s); - $this->append([Type::T_COMMENT, rtrim(substr($this->buffer, $s, $this->count - $s))]); - return true; - } - - $this->append([Type::T_IMPORT, $importPath], $s); - - return true; - } - - $this->seek($s); - - if ( - $this->literal('@extend', 7) && - $this->selectors($selectors) && - $this->end() - ) { - ! $this->cssOnly || $this->assertPlainCssValid(false, $s); - - // check for '!flag' - $optional = $this->stripOptionalFlag($selectors); - $this->append([Type::T_EXTEND, $selectors, $optional], $s); - - return true; - } - - $this->seek($s); - - if ( - $this->literal('@function', 9) && - $this->keyword($fnName) && - $this->argumentDef($args) && - $this->matchChar('{', false) - ) { - ! $this->cssOnly || $this->assertPlainCssValid(false, $s); - - $func = new CallableBlock(Type::T_FUNCTION); - $this->registerPushedBlock($func, $s); - $func->name = $fnName; - $func->args = $args; - - return true; - } - - $this->seek($s); - - if ( - $this->literal('@return', 7) && - ($this->valueList($retVal) || true) && - $this->end() - ) { - ! $this->cssOnly || $this->assertPlainCssValid(false, $s); - - $this->append([Type::T_RETURN, isset($retVal) ? $retVal : [Type::T_NULL]], $s); - - return true; - } - - $this->seek($s); - - if ( - $this->literal('@each', 5) && - $this->genericList($varNames, 'variable', ',', false) && - $this->literal('in', 2) && - $this->valueList($list) && - $this->matchChar('{', false) - ) { - ! $this->cssOnly || $this->assertPlainCssValid(false, $s); - - $each = new EachBlock(); - $this->registerPushedBlock($each, $s); - - foreach ($varNames[2] as $varName) { - $each->vars[] = $varName[1]; - } - - $each->list = $list; - - return true; - } - - $this->seek($s); - - if ( - $this->literal('@while', 6) && - $this->expression($cond) && - $this->matchChar('{', false) - ) { - ! $this->cssOnly || $this->assertPlainCssValid(false, $s); - - while ( - $cond[0] === Type::T_LIST && - ! empty($cond['enclosing']) && - $cond['enclosing'] === 'parent' && - \count($cond[2]) == 1 - ) { - $cond = reset($cond[2]); - } - - $while = new WhileBlock(); - $this->registerPushedBlock($while, $s); - $while->cond = $cond; - - return true; - } - - $this->seek($s); - - if ( - $this->literal('@for', 4) && - $this->variable($varName) && - $this->literal('from', 4) && - $this->expression($start) && - ($this->literal('through', 7) || - ($forUntil = true && $this->literal('to', 2))) && - $this->expression($end) && - $this->matchChar('{', false) - ) { - ! $this->cssOnly || $this->assertPlainCssValid(false, $s); - - $for = new ForBlock(); - $this->registerPushedBlock($for, $s); - $for->var = $varName[1]; - $for->start = $start; - $for->end = $end; - $for->until = isset($forUntil); - - return true; - } - - $this->seek($s); - - if ( - $this->literal('@if', 3) && - $this->functionCallArgumentsList($cond, false, '{', false) - ) { - ! $this->cssOnly || $this->assertPlainCssValid(false, $s); - - $if = new IfBlock(); - $this->registerPushedBlock($if, $s); - - while ( - $cond[0] === Type::T_LIST && - ! empty($cond['enclosing']) && - $cond['enclosing'] === 'parent' && - \count($cond[2]) == 1 - ) { - $cond = reset($cond[2]); - } - - $if->cond = $cond; - $if->cases = []; - - return true; - } - - $this->seek($s); - - if ( - $this->literal('@debug', 6) && - $this->functionCallArgumentsList($value, false) - ) { - ! $this->cssOnly || $this->assertPlainCssValid(false, $s); - - $this->append([Type::T_DEBUG, $value], $s); - - return true; - } - - $this->seek($s); - - if ( - $this->literal('@warn', 5) && - $this->functionCallArgumentsList($value, false) - ) { - ! $this->cssOnly || $this->assertPlainCssValid(false, $s); - - $this->append([Type::T_WARN, $value], $s); - - return true; - } - - $this->seek($s); - - if ( - $this->literal('@error', 6) && - $this->functionCallArgumentsList($value, false) - ) { - ! $this->cssOnly || $this->assertPlainCssValid(false, $s); - - $this->append([Type::T_ERROR, $value], $s); - - return true; - } - - $this->seek($s); - - if ( - $this->literal('@content', 8) && - ($this->end() || - $this->matchChar('(') && - $this->argValues($argContent) && - $this->matchChar(')') && - $this->end()) - ) { - ! $this->cssOnly || $this->assertPlainCssValid(false, $s); - - $this->append([Type::T_MIXIN_CONTENT, isset($argContent) ? $argContent : null], $s); - - return true; - } - - $this->seek($s); - - $last = $this->last(); - - if (isset($last) && $last[0] === Type::T_IF) { - list(, $if) = $last; - assert($if instanceof IfBlock); - - if ($this->literal('@else', 5)) { - if ($this->matchChar('{', false)) { - $else = new ElseBlock(); - } elseif ( - $this->literal('if', 2) && - $this->functionCallArgumentsList($cond, false, '{', false) - ) { - $else = new ElseifBlock(); - $else->cond = $cond; - } - - if (isset($else)) { - $this->registerPushedBlock($else, $s); - $if->cases[] = $else; - - return true; - } - } - - $this->seek($s); - } - - // only retain the first @charset directive encountered - if ( - $this->literal('@charset', 8) && - $this->valueList($charset) && - $this->end() - ) { - return true; - } - - $this->seek($s); - - if ( - $this->literal('@supports', 9) && - ($t1 = $this->supportsQuery($supportQuery)) && - ($t2 = $this->matchChar('{', false)) - ) { - $directive = new DirectiveBlock(); - $this->registerPushedBlock($directive, $s); - $directive->name = 'supports'; - $directive->value = $supportQuery; - - return true; - } - - $this->seek($s); - - // doesn't match built in directive, do generic one - if ( - $this->matchChar('@', false) && - $this->mixedKeyword($dirName) && - $this->directiveValue($dirValue, '{') - ) { - if (count($dirName) === 1 && is_string(reset($dirName))) { - $dirName = reset($dirName); - } else { - $dirName = [Type::T_STRING, '', $dirName]; - } - if ($dirName === 'media') { - $directive = new MediaBlock(); - } else { - $directive = new DirectiveBlock(); - $directive->name = $dirName; - } - $this->registerPushedBlock($directive, $s); - - if (isset($dirValue)) { - ! $this->cssOnly || ($dirValue = $this->assertPlainCssValid($dirValue)); - $directive->value = $dirValue; - } - - return true; - } - - $this->seek($s); - - // maybe it's a generic blockless directive - if ( - $this->matchChar('@', false) && - $this->mixedKeyword($dirName) && - ! $this->isKnownGenericDirective($dirName) && - ($this->end(false) || ($this->directiveValue($dirValue, '') && $this->end(false))) - ) { - if (\count($dirName) === 1 && \is_string(\reset($dirName))) { - $dirName = \reset($dirName); - } else { - $dirName = [Type::T_STRING, '', $dirName]; - } - if ( - ! empty($this->env->parent) && - $this->env->type && - ! \in_array($this->env->type, [Type::T_DIRECTIVE, Type::T_MEDIA]) - ) { - $plain = \trim(\substr($this->buffer, $s, $this->count - $s)); - throw $this->parseError( - "Unknown directive `{$plain}` not allowed in `" . $this->env->type . "` block" - ); - } - // blockless directives with a blank line after keeps their blank lines after - // sass-spec compliance purpose - $s = $this->count; - $hasBlankLine = false; - if ($this->match('\s*?\n\s*\n', $out, false)) { - $hasBlankLine = true; - $this->seek($s); - } - $isNotRoot = ! empty($this->env->parent); - $this->append([Type::T_DIRECTIVE, [$dirName, $dirValue, $hasBlankLine, $isNotRoot]], $s); - $this->whitespace(); - - return true; - } - - $this->seek($s); - - return false; - } - - $inCssSelector = null; - if ($this->cssOnly) { - $inCssSelector = (! empty($this->env->parent) && - ! in_array($this->env->type, [Type::T_DIRECTIVE, Type::T_MEDIA])); - } - // custom properties : right part is static - if (($this->customProperty($name) ) && $this->matchChar(':', false)) { - $start = $this->count; - - // but can be complex and finish with ; or } - foreach ([';','}'] as $ending) { - if ( - $this->openString($ending, $stringValue, '(', ')', false) && - $this->end() - ) { - $end = $this->count; - $value = $stringValue; - - // check if we have only a partial value due to nested [] or { } to take in account - $nestingPairs = [['[', ']'], ['{', '}']]; - - foreach ($nestingPairs as $nestingPair) { - $p = strpos($this->buffer, $nestingPair[0], $start); - - if ($p && $p < $end) { - $this->seek($start); - - if ( - $this->openString($ending, $stringValue, $nestingPair[0], $nestingPair[1], false) && - $this->end() && - $this->count > $end - ) { - $end = $this->count; - $value = $stringValue; - } - } - } - - $this->seek($end); - $this->append([Type::T_CUSTOM_PROPERTY, $name, $value], $s); - - return true; - } - } - - // TODO: output an error here if nothing found according to sass spec - } - - $this->seek($s); - - // property shortcut - // captures most properties before having to parse a selector - if ( - $this->keyword($name, false) && - $this->literal(': ', 2) && - $this->valueList($value) && - $this->end() - ) { - $name = [Type::T_STRING, '', [$name]]; - $this->append([Type::T_ASSIGN, $name, $value], $s); - - return true; - } - - $this->seek($s); - - // variable assigns - if ( - $this->variable($name) && - $this->matchChar(':') && - $this->valueList($value) && - $this->end() - ) { - ! $this->cssOnly || $this->assertPlainCssValid(false, $s); - - // check for '!flag' - $assignmentFlags = $this->stripAssignmentFlags($value); - $this->append([Type::T_ASSIGN, $name, $value, $assignmentFlags], $s); - - return true; - } - - $this->seek($s); - - // opening css block - if ( - $this->selectors($selectors) && - $this->matchChar('{', false) - ) { - ! $this->cssOnly || ! $inCssSelector || $this->assertPlainCssValid(false); - - $this->pushBlock($selectors, $s); - - if ($this->eatWhiteDefault) { - $this->whitespace(); - $this->append(null); // collect comments at the beginning if needed - } - - return true; - } - - $this->seek($s); - - // property assign, or nested assign - if ( - $this->propertyName($name) && - $this->matchChar(':') - ) { - $foundSomething = false; - - if ($this->valueList($value)) { - if (empty($this->env->parent)) { - throw $this->parseError('expected "{"'); - } - - $this->append([Type::T_ASSIGN, $name, $value], $s); - $foundSomething = true; - } - - if ($this->matchChar('{', false)) { - ! $this->cssOnly || $this->assertPlainCssValid(false); - - $propBlock = new NestedPropertyBlock(); - $this->registerPushedBlock($propBlock, $s); - $propBlock->prefix = $name; - $propBlock->hasValue = $foundSomething; - - $foundSomething = true; - } elseif ($foundSomething) { - $foundSomething = $this->end(); - } - - if ($foundSomething) { - return true; - } - } - - $this->seek($s); - - // closing a block - if ($this->matchChar('}', false)) { - $block = $this->popBlock(); - - if (! isset($block->type) || $block->type !== Type::T_IF) { - assert($this->env !== null); - - if ($this->env->parent) { - $this->append(null); // collect comments before next statement if needed - } - } - - if ($block instanceof ContentBlock) { - $include = $block->child; - assert(\is_array($include)); - unset($block->child); - $include[3] = $block; - $this->append($include, $s); - } elseif (!$block instanceof ElseBlock && !$block instanceof ElseifBlock) { - $type = isset($block->type) ? $block->type : Type::T_BLOCK; - $this->append([$type, $block], $s); - } - - // collect comments just after the block closing if needed - if ($this->eatWhiteDefault) { - $this->whitespace(); - assert($this->env !== null); - - if ($this->env->comments) { - $this->append(null); - } - } - - return true; - } - - // extra stuff - if ($this->matchChar(';')) { - return true; - } - - return false; - } - - /** - * Push block onto parse tree - * - * @param array|null $selectors - * @param int $pos - * - * @return Block - */ - protected function pushBlock($selectors, $pos = 0) - { - $b = new Block(); - $b->selectors = $selectors; - - $this->registerPushedBlock($b, $pos); - - return $b; - } - - /** - * @param Block $b - * @param int $pos - * - * @return void - */ - private function registerPushedBlock(Block $b, $pos) - { - list($line, $column) = $this->getSourcePosition($pos); - - $b->sourceName = $this->sourceName; - $b->sourceLine = $line; - $b->sourceColumn = $column; - $b->sourceIndex = $this->sourceIndex; - $b->comments = []; - $b->parent = $this->env; - - if (! $this->env) { - $b->children = []; - } elseif (empty($this->env->children)) { - $this->env->children = $this->env->comments; - $b->children = []; - $this->env->comments = []; - } else { - $b->children = $this->env->comments; - $this->env->comments = []; - } - - $this->env = $b; - - // collect comments at the beginning of a block if needed - if ($this->eatWhiteDefault) { - $this->whitespace(); - assert($this->env !== null); - - if ($this->env->comments) { - $this->append(null); - } - } - } - - /** - * Push special (named) block onto parse tree - * - * @deprecated - * - * @param string $type - * @param int $pos - * - * @return Block - */ - protected function pushSpecialBlock($type, $pos) - { - $block = $this->pushBlock(null, $pos); - $block->type = $type; - - return $block; - } - - /** - * Pop scope and return last block - * - * @return Block - * - * @throws \Exception - */ - protected function popBlock() - { - assert($this->env !== null); - - // collect comments ending just before of a block closing - if ($this->env->comments) { - $this->append(null); - } - - // pop the block - $block = $this->env; - - if (empty($block->parent)) { - throw $this->parseError('unexpected }'); - } - - if ($block->type == Type::T_AT_ROOT) { - // keeps the parent in case of self selector & - $block->selfParent = $block->parent; - } - - $this->env = $block->parent; - - unset($block->parent); - - return $block; - } - - /** - * Peek input stream - * - * @param string $regex - * @param array $out - * @param int $from - * - * @return int - */ - protected function peek($regex, &$out, $from = null) - { - if (! isset($from)) { - $from = $this->count; - } - - $r = '/' . $regex . '/' . $this->patternModifiers; - $result = preg_match($r, $this->buffer, $out, 0, $from); - - return $result; - } - - /** - * Seek to position in input stream (or return current position in input stream) - * - * @param int $where - * - * @return void - */ - protected function seek($where) - { - $this->count = $where; - } - - /** - * Assert a parsed part is plain CSS Valid - * - * @param array|false $parsed - * @param int $startPos - * - * @return array - * - * @throws ParserException - */ - protected function assertPlainCssValid($parsed, $startPos = null) - { - $type = ''; - if ($parsed) { - $type = $parsed[0]; - $parsed = $this->isPlainCssValidElement($parsed); - } - if (! $parsed) { - if (! \is_null($startPos)) { - $plain = rtrim(substr($this->buffer, $startPos, $this->count - $startPos)); - $message = "Error : `{$plain}` isn't allowed in plain CSS"; - } else { - $message = 'Error: SCSS syntax not allowed in CSS file'; - } - if ($type) { - $message .= " ($type)"; - } - throw $this->parseError($message); - } - - return $parsed; - } - - /** - * Check a parsed element is plain CSS Valid - * - * @param array $parsed - * @param bool $allowExpression - * - * @return array|false - */ - protected function isPlainCssValidElement($parsed, $allowExpression = false) - { - // keep string as is - if (is_string($parsed)) { - return $parsed; - } - - if ( - \in_array($parsed[0], [Type::T_FUNCTION, Type::T_FUNCTION_CALL]) && - !\in_array($parsed[1], [ - 'alpha', - 'attr', - 'calc', - 'cubic-bezier', - 'env', - 'grayscale', - 'hsl', - 'hsla', - 'hwb', - 'invert', - 'linear-gradient', - 'min', - 'max', - 'radial-gradient', - 'repeating-linear-gradient', - 'repeating-radial-gradient', - 'rgb', - 'rgba', - 'rotate', - 'saturate', - 'var', - ]) && - Compiler::isNativeFunction($parsed[1]) - ) { - return false; - } - - switch ($parsed[0]) { - case Type::T_BLOCK: - case Type::T_KEYWORD: - case Type::T_NULL: - case Type::T_NUMBER: - case Type::T_MEDIA: - return $parsed; - - case Type::T_COMMENT: - if (isset($parsed[2])) { - return false; - } - return $parsed; - - case Type::T_DIRECTIVE: - if (\is_array($parsed[1])) { - $parsed[1][1] = $this->isPlainCssValidElement($parsed[1][1]); - if (! $parsed[1][1]) { - return false; - } - } - - return $parsed; - - case Type::T_IMPORT: - if ($parsed[1][0] === Type::T_LIST) { - return false; - } - $parsed[1] = $this->isPlainCssValidElement($parsed[1]); - if ($parsed[1] === false) { - return false; - } - return $parsed; - - case Type::T_STRING: - foreach ($parsed[2] as $k => $substr) { - if (\is_array($substr)) { - $parsed[2][$k] = $this->isPlainCssValidElement($substr); - if (! $parsed[2][$k]) { - return false; - } - } - } - return $parsed; - - case Type::T_LIST: - if (!empty($parsed['enclosing'])) { - return false; - } - foreach ($parsed[2] as $k => $listElement) { - $parsed[2][$k] = $this->isPlainCssValidElement($listElement); - if (! $parsed[2][$k]) { - return false; - } - } - return $parsed; - - case Type::T_ASSIGN: - foreach ([1, 2, 3] as $k) { - if (! empty($parsed[$k])) { - $parsed[$k] = $this->isPlainCssValidElement($parsed[$k]); - if (! $parsed[$k]) { - return false; - } - } - } - return $parsed; - - case Type::T_EXPRESSION: - list( ,$op, $lhs, $rhs, $inParens, $whiteBefore, $whiteAfter) = $parsed; - if (! $allowExpression && ! \in_array($op, ['and', 'or', '/'])) { - return false; - } - $lhs = $this->isPlainCssValidElement($lhs, true); - if (! $lhs) { - return false; - } - $rhs = $this->isPlainCssValidElement($rhs, true); - if (! $rhs) { - return false; - } - - return [ - Type::T_STRING, - '', [ - $this->inParens ? '(' : '', - $lhs, - ($whiteBefore ? ' ' : '') . $op . ($whiteAfter ? ' ' : ''), - $rhs, - $this->inParens ? ')' : '' - ] - ]; - - case Type::T_CUSTOM_PROPERTY: - case Type::T_UNARY: - $parsed[2] = $this->isPlainCssValidElement($parsed[2]); - if (! $parsed[2]) { - return false; - } - return $parsed; - - case Type::T_FUNCTION: - $argsList = $parsed[2]; - foreach ($argsList[2] as $argElement) { - if (! $this->isPlainCssValidElement($argElement)) { - return false; - } - } - return $parsed; - - case Type::T_FUNCTION_CALL: - $parsed[0] = Type::T_FUNCTION; - $argsList = [Type::T_LIST, ',', []]; - foreach ($parsed[2] as $arg) { - if ($arg[0] || ! empty($arg[2])) { - // no named arguments possible in a css function call - // nor ... argument - return false; - } - $arg = $this->isPlainCssValidElement($arg[1], $parsed[1] === 'calc'); - if (! $arg) { - return false; - } - $argsList[2][] = $arg; - } - $parsed[2] = $argsList; - return $parsed; - } - - return false; - } - - /** - * Match string looking for either ending delim, escape, or string interpolation - * - * {@internal This is a workaround for preg_match's 250K string match limit. }} - * - * @param array $m Matches (passed by reference) - * @param string $delim Delimiter - * - * @return bool True if match; false otherwise - * - * @phpstan-impure - */ - protected function matchString(&$m, $delim) - { - $token = null; - - $end = \strlen($this->buffer); - - // look for either ending delim, escape, or string interpolation - foreach (['#{', '\\', "\r", $delim] as $lookahead) { - $pos = strpos($this->buffer, $lookahead, $this->count); - - if ($pos !== false && $pos < $end) { - $end = $pos; - $token = $lookahead; - } - } - - if (! isset($token)) { - return false; - } - - $match = substr($this->buffer, $this->count, $end - $this->count); - $m = [ - $match . $token, - $match, - $token - ]; - $this->count = $end + \strlen($token); - - return true; - } - - /** - * Try to match something on head of buffer - * - * @param string $regex - * @param array $out - * @param bool $eatWhitespace - * - * @return bool - * - * @phpstan-impure - */ - protected function match($regex, &$out, $eatWhitespace = null) - { - $r = '/' . $regex . '/' . $this->patternModifiers; - - if (! preg_match($r, $this->buffer, $out, 0, $this->count)) { - return false; - } - - $this->count += \strlen($out[0]); - - if (! isset($eatWhitespace)) { - $eatWhitespace = $this->eatWhiteDefault; - } - - if ($eatWhitespace) { - $this->whitespace(); - } - - return true; - } - - /** - * Match a single string - * - * @param string $char - * @param bool $eatWhitespace - * - * @return bool - * - * @phpstan-impure - */ - protected function matchChar($char, $eatWhitespace = null) - { - if (! isset($this->buffer[$this->count]) || $this->buffer[$this->count] !== $char) { - return false; - } - - $this->count++; - - if (! isset($eatWhitespace)) { - $eatWhitespace = $this->eatWhiteDefault; - } - - if ($eatWhitespace) { - $this->whitespace(); - } - - return true; - } - - /** - * Match literal string - * - * @param string $what - * @param int $len - * @param bool $eatWhitespace - * - * @return bool - * - * @phpstan-impure - */ - protected function literal($what, $len, $eatWhitespace = null) - { - if (strcasecmp(substr($this->buffer, $this->count, $len), $what) !== 0) { - return false; - } - - $this->count += $len; - - if (! isset($eatWhitespace)) { - $eatWhitespace = $this->eatWhiteDefault; - } - - if ($eatWhitespace) { - $this->whitespace(); - } - - return true; - } - - /** - * Match some whitespace - * - * @return bool - * - * @phpstan-impure - */ - protected function whitespace() - { - $gotWhite = false; - - while (preg_match(static::$whitePattern, $this->buffer, $m, 0, $this->count)) { - if (isset($m[1]) && empty($this->commentsSeen[$this->count])) { - // comment that are kept in the output CSS - $comment = []; - $startCommentCount = $this->count; - $endCommentCount = $this->count + \strlen($m[1]); - - // find interpolations in comment - $p = strpos($this->buffer, '#{', $this->count); - - while ($p !== false && $p < $endCommentCount) { - $c = substr($this->buffer, $this->count, $p - $this->count); - $comment[] = $c; - $this->count = $p; - $out = null; - - if ($this->interpolation($out)) { - // keep right spaces in the following string part - if ($out[3]) { - while ($this->buffer[$this->count - 1] !== '}') { - $this->count--; - } - - $out[3] = ''; - } - - $comment[] = [Type::T_COMMENT, substr($this->buffer, $p, $this->count - $p), $out]; - } else { - list($line, $column) = $this->getSourcePosition($this->count); - $file = $this->sourceName; - if (!$this->discardComments) { - $this->logger->warn("Unterminated interpolations in multiline comments are deprecated and will be removed in ScssPhp 2.0, in \"$file\", line $line, column $column.", true); - } - $comment[] = substr($this->buffer, $this->count, 2); - - $this->count += 2; - } - - $p = strpos($this->buffer, '#{', $this->count); - } - - // remaining part - $c = substr($this->buffer, $this->count, $endCommentCount - $this->count); - - if (! $comment) { - // single part static comment - $commentStatement = [Type::T_COMMENT, $c]; - } else { - $comment[] = $c; - $staticComment = substr($this->buffer, $startCommentCount, $endCommentCount - $startCommentCount); - $commentStatement = [Type::T_COMMENT, $staticComment, [Type::T_STRING, '', $comment]]; - } - - list($line, $column) = $this->getSourcePosition($startCommentCount); - $commentStatement[self::SOURCE_LINE] = $line; - $commentStatement[self::SOURCE_COLUMN] = $column; - $commentStatement[self::SOURCE_INDEX] = $this->sourceIndex; - - $this->appendComment($commentStatement); - - $this->commentsSeen[$startCommentCount] = true; - $this->count = $endCommentCount; - } else { - // comment that are ignored and not kept in the output css - $this->count += \strlen($m[0]); - // silent comments are not allowed in plain CSS files - ! $this->cssOnly - || ! \strlen(trim($m[0])) - || $this->assertPlainCssValid(false, $this->count - \strlen($m[0])); - } - - $gotWhite = true; - } - - return $gotWhite; - } - - /** - * Append comment to current block - * - * @param array $comment - * - * @return void - */ - protected function appendComment($comment) - { - assert($this->env !== null); - - if (! $this->discardComments) { - $this->env->comments[] = $comment; - } - } - - /** - * Append statement to current block - * - * @param array|null $statement - * @param int $pos - * - * @return void - */ - protected function append($statement, $pos = null) - { - assert($this->env !== null); - - if (! \is_null($statement)) { - ! $this->cssOnly || ($statement = $this->assertPlainCssValid($statement, $pos)); - - if (! \is_null($pos)) { - list($line, $column) = $this->getSourcePosition($pos); - - $statement[static::SOURCE_LINE] = $line; - $statement[static::SOURCE_COLUMN] = $column; - $statement[static::SOURCE_INDEX] = $this->sourceIndex; - } - - $this->env->children[] = $statement; - } - - $comments = $this->env->comments; - - if ($comments) { - $this->env->children = array_merge($this->env->children, $comments); - $this->env->comments = []; - } - } - - /** - * Returns last child was appended - * - * @return array|null - */ - protected function last() - { - assert($this->env !== null); - - $i = \count($this->env->children) - 1; - - if (isset($this->env->children[$i])) { - return $this->env->children[$i]; - } - - return null; - } - - /** - * Parse media query list - * - * @param array $out - * - * @return bool - */ - protected function mediaQueryList(&$out) - { - return $this->genericList($out, 'mediaQuery', ',', false); - } - - /** - * Parse media query - * - * @param array $out - * - * @return bool - */ - protected function mediaQuery(&$out) - { - $expressions = null; - $parts = []; - - if ( - ($this->literal('only', 4) && ($only = true) || - $this->literal('not', 3) && ($not = true) || true) && - $this->mixedKeyword($mediaType) - ) { - $prop = [Type::T_MEDIA_TYPE]; - - if (isset($only)) { - $prop[] = [Type::T_KEYWORD, 'only']; - } - - if (isset($not)) { - $prop[] = [Type::T_KEYWORD, 'not']; - } - - $media = [Type::T_LIST, '', []]; - - foreach ((array) $mediaType as $type) { - if (\is_array($type)) { - $media[2][] = $type; - } else { - $media[2][] = [Type::T_KEYWORD, $type]; - } - } - - $prop[] = $media; - $parts[] = $prop; - } - - if (empty($parts) || $this->literal('and', 3)) { - $this->genericList($expressions, 'mediaExpression', 'and', false); - - if (\is_array($expressions)) { - $parts = array_merge($parts, $expressions[2]); - } - } - - $out = $parts; - - return true; - } - - /** - * Parse supports query - * - * @param array $out - * - * @return bool - */ - protected function supportsQuery(&$out) - { - $expressions = null; - $parts = []; - - $s = $this->count; - - $not = false; - - if ( - ($this->literal('not', 3) && ($not = true) || true) && - $this->matchChar('(') && - ($this->expression($property)) && - $this->literal(': ', 2) && - $this->valueList($value) && - $this->matchChar(')') - ) { - $support = [Type::T_STRING, '', [[Type::T_KEYWORD, ($not ? 'not ' : '') . '(']]]; - $support[2][] = $property; - $support[2][] = [Type::T_KEYWORD, ': ']; - $support[2][] = $value; - $support[2][] = [Type::T_KEYWORD, ')']; - - $parts[] = $support; - $s = $this->count; - } else { - $this->seek($s); - } - - if ( - $this->matchChar('(') && - $this->supportsQuery($subQuery) && - $this->matchChar(')') - ) { - $parts[] = [Type::T_STRING, '', [[Type::T_KEYWORD, '('], $subQuery, [Type::T_KEYWORD, ')']]]; - $s = $this->count; - } else { - $this->seek($s); - } - - if ( - $this->literal('not', 3) && - $this->supportsQuery($subQuery) - ) { - $parts[] = [Type::T_STRING, '', [[Type::T_KEYWORD, 'not '], $subQuery]]; - $s = $this->count; - } else { - $this->seek($s); - } - - if ( - $this->literal('selector(', 9) && - $this->selector($selector) && - $this->matchChar(')') - ) { - $support = [Type::T_STRING, '', [[Type::T_KEYWORD, 'selector(']]]; - - $selectorList = [Type::T_LIST, '', []]; - - foreach ($selector as $sc) { - $compound = [Type::T_STRING, '', []]; - - foreach ($sc as $scp) { - if (\is_array($scp)) { - $compound[2][] = $scp; - } else { - $compound[2][] = [Type::T_KEYWORD, $scp]; - } - } - - $selectorList[2][] = $compound; - } - - $support[2][] = $selectorList; - $support[2][] = [Type::T_KEYWORD, ')']; - $parts[] = $support; - $s = $this->count; - } else { - $this->seek($s); - } - - if ($this->variable($var) or $this->interpolation($var)) { - $parts[] = $var; - $s = $this->count; - } else { - $this->seek($s); - } - - if ( - $this->literal('and', 3) && - $this->genericList($expressions, 'supportsQuery', ' and', false) - ) { - array_unshift($expressions[2], [Type::T_STRING, '', $parts]); - - $parts = [$expressions]; - $s = $this->count; - } else { - $this->seek($s); - } - - if ( - $this->literal('or', 2) && - $this->genericList($expressions, 'supportsQuery', ' or', false) - ) { - array_unshift($expressions[2], [Type::T_STRING, '', $parts]); - - $parts = [$expressions]; - $s = $this->count; - } else { - $this->seek($s); - } - - if (\count($parts)) { - if ($this->eatWhiteDefault) { - $this->whitespace(); - } - - $out = [Type::T_STRING, '', $parts]; - - return true; - } - - return false; - } - - - /** - * Parse media expression - * - * @param array $out - * - * @return bool - */ - protected function mediaExpression(&$out) - { - $s = $this->count; - $value = null; - - if ( - $this->matchChar('(') && - $this->expression($feature) && - ($this->matchChar(':') && - $this->expression($value) || true) && - $this->matchChar(')') - ) { - $out = [Type::T_MEDIA_EXPRESSION, $feature]; - - if ($value) { - $out[] = $value; - } - - return true; - } - - $this->seek($s); - - return false; - } - - /** - * Parse argument values - * - * @param array $out - * - * @return bool - */ - protected function argValues(&$out) - { - $discardComments = $this->discardComments; - $this->discardComments = true; - - if ($this->genericList($list, 'argValue', ',', false)) { - $out = $list[2]; - - $this->discardComments = $discardComments; - - return true; - } - - $this->discardComments = $discardComments; - - return false; - } - - /** - * Parse argument value - * - * @param array $out - * - * @return bool - */ - protected function argValue(&$out) - { - $s = $this->count; - - $keyword = null; - - if (! $this->variable($keyword) || ! $this->matchChar(':')) { - $this->seek($s); - - $keyword = null; - } - - if ($this->genericList($value, 'expression', '', true)) { - $out = [$keyword, $value, false]; - $s = $this->count; - - if ($this->literal('...', 3)) { - $out[2] = true; - } else { - $this->seek($s); - } - - return true; - } - - return false; - } - - /** - * Check if a generic directive is known to be able to allow almost any syntax or not - * @param mixed $directiveName - * @return bool - */ - protected function isKnownGenericDirective($directiveName) - { - if (\is_array($directiveName) && \is_string(reset($directiveName))) { - $directiveName = reset($directiveName); - } - if (! \is_string($directiveName)) { - return false; - } - if ( - \in_array($directiveName, [ - 'at-root', - 'media', - 'mixin', - 'include', - 'scssphp-import-once', - 'import', - 'extend', - 'function', - 'break', - 'continue', - 'return', - 'each', - 'while', - 'for', - 'if', - 'debug', - 'warn', - 'error', - 'content', - 'else', - 'charset', - 'supports', - // Todo - 'use', - 'forward', - ]) - ) { - return true; - } - return false; - } - - /** - * Parse directive value list that considers $vars as keyword - * - * @param array $out - * @param string|false $endChar - * - * @return bool - * - * @phpstan-impure - */ - protected function directiveValue(&$out, $endChar = false) - { - $s = $this->count; - - if ($this->variable($out)) { - if ($endChar && $this->matchChar($endChar, false)) { - return true; - } - - if (! $endChar && $this->end()) { - return true; - } - } - - $this->seek($s); - - if (\is_string($endChar) && $this->openString($endChar ? $endChar : ';', $out, null, null, true, ";}{")) { - if ($endChar && $this->matchChar($endChar, false)) { - return true; - } - $ss = $this->count; - if (!$endChar && $this->end()) { - $this->seek($ss); - return true; - } - } - - $this->seek($s); - - $allowVars = $this->allowVars; - $this->allowVars = false; - - $res = $this->genericList($out, 'spaceList', ','); - $this->allowVars = $allowVars; - - if ($res) { - if ($endChar && $this->matchChar($endChar, false)) { - return true; - } - - if (! $endChar && $this->end()) { - return true; - } - } - - $this->seek($s); - - if ($endChar && $this->matchChar($endChar, false)) { - return true; - } - - return false; - } - - /** - * Parse comma separated value list - * - * @param array $out - * - * @return bool - */ - protected function valueList(&$out) - { - $discardComments = $this->discardComments; - $this->discardComments = true; - $res = $this->genericList($out, 'spaceList', ','); - $this->discardComments = $discardComments; - - return $res; - } - - /** - * Parse a function call, where externals () are part of the call - * and not of the value list - * - * @param array $out - * @param bool $mandatoryEnclos - * @param null|string $charAfter - * @param null|bool $eatWhiteSp - * - * @return bool - */ - protected function functionCallArgumentsList(&$out, $mandatoryEnclos = true, $charAfter = null, $eatWhiteSp = null) - { - $s = $this->count; - - if ( - $this->matchChar('(') && - $this->valueList($out) && - $this->matchChar(')') && - ($charAfter ? $this->matchChar($charAfter, $eatWhiteSp) : $this->end()) - ) { - return true; - } - - if (! $mandatoryEnclos) { - $this->seek($s); - - if ( - $this->valueList($out) && - ($charAfter ? $this->matchChar($charAfter, $eatWhiteSp) : $this->end()) - ) { - return true; - } - } - - $this->seek($s); - - return false; - } - - /** - * Parse space separated value list - * - * @param array $out - * - * @return bool - */ - protected function spaceList(&$out) - { - return $this->genericList($out, 'expression'); - } - - /** - * Parse generic list - * - * @param array $out - * @param string $parseItem The name of the method used to parse items - * @param string $delim - * @param bool $flatten - * - * @return bool - */ - protected function genericList(&$out, $parseItem, $delim = '', $flatten = true) - { - $s = $this->count; - $items = []; - /** @var array|Number|null $value */ - $value = null; - - while ($this->$parseItem($value)) { - $trailing_delim = false; - $items[] = $value; - - if ($delim) { - if (! $this->literal($delim, \strlen($delim))) { - break; - } - - $trailing_delim = true; - } else { - assert(\is_array($value) || $value instanceof Number); - // if no delim watch that a keyword didn't eat the single/double quote - // from the following starting string - if ($value[0] === Type::T_KEYWORD) { - assert(\is_array($value)); - /** @var string $word */ - $word = $value[1]; - - $last_char = substr($word, -1); - - if ( - strlen($word) > 1 && - in_array($last_char, [ "'", '"']) && - substr($word, -2, 1) !== '\\' - ) { - // if there is a non escaped opening quote in the keyword, this seems unlikely a mistake - $word = str_replace('\\' . $last_char, '\\\\', $word); - if (strpos($word, $last_char) < strlen($word) - 1) { - continue; - } - - $currentCount = $this->count; - - // let's try to rewind to previous char and try a parse - $this->count--; - // in case the keyword also eat spaces - while (substr($this->buffer, $this->count, 1) !== $last_char) { - $this->count--; - } - - /** @var array|Number|null $nextValue */ - $nextValue = null; - if ($this->$parseItem($nextValue)) { - assert(\is_array($nextValue) || $nextValue instanceof Number); - if ($nextValue[0] === Type::T_KEYWORD && $nextValue[1] === $last_char) { - // bad try, forget it - $this->seek($currentCount); - continue; - } - if ($nextValue[0] !== Type::T_STRING) { - // bad try, forget it - $this->seek($currentCount); - continue; - } - - // OK it was a good idea - $value[1] = substr($value[1], 0, -1); - array_pop($items); - $items[] = $value; - $items[] = $nextValue; - } else { - // bad try, forget it - $this->seek($currentCount); - continue; - } - } - } - } - } - - if (! $items) { - $this->seek($s); - - return false; - } - - if ($trailing_delim) { - $items[] = [Type::T_NULL]; - } - - if ($flatten && \count($items) === 1) { - $out = $items[0]; - } else { - $out = [Type::T_LIST, $delim, $items]; - } - - return true; - } - - /** - * Parse expression - * - * @param array $out - * @param bool $listOnly - * @param bool $lookForExp - * - * @return bool - * - * @phpstan-impure - */ - protected function expression(&$out, $listOnly = false, $lookForExp = true) - { - $s = $this->count; - $discard = $this->discardComments; - $this->discardComments = true; - $allowedTypes = ($listOnly ? [Type::T_LIST] : [Type::T_LIST, Type::T_MAP]); - - if ($this->matchChar('(')) { - if ($this->enclosedExpression($lhs, $s, ')', $allowedTypes)) { - if ($lookForExp) { - $out = $this->expHelper($lhs, 0); - } else { - $out = $lhs; - } - - $this->discardComments = $discard; - - return true; - } - - $this->seek($s); - } - - if (\in_array(Type::T_LIST, $allowedTypes) && $this->matchChar('[')) { - if ($this->enclosedExpression($lhs, $s, ']', [Type::T_LIST])) { - if ($lookForExp) { - $out = $this->expHelper($lhs, 0); - } else { - $out = $lhs; - } - - $this->discardComments = $discard; - - return true; - } - - $this->seek($s); - } - - if (! $listOnly && $this->value($lhs)) { - if ($lookForExp) { - $out = $this->expHelper($lhs, 0); - } else { - $out = $lhs; - } - - $this->discardComments = $discard; - - return true; - } - - $this->discardComments = $discard; - - return false; - } - - /** - * Parse expression specifically checking for lists in parenthesis or brackets - * - * @param array $out - * @param int $s - * @param string $closingParen - * @param string[] $allowedTypes - * - * @return bool - * - * @phpstan-param array<Type::*> $allowedTypes - */ - protected function enclosedExpression(&$out, $s, $closingParen = ')', $allowedTypes = [Type::T_LIST, Type::T_MAP]) - { - if ($this->matchChar($closingParen) && \in_array(Type::T_LIST, $allowedTypes)) { - $out = [Type::T_LIST, '', []]; - - switch ($closingParen) { - case ')': - $out['enclosing'] = 'parent'; // parenthesis list - break; - - case ']': - $out['enclosing'] = 'bracket'; // bracketed list - break; - } - - return true; - } - - if ( - $this->valueList($out) && - $this->matchChar($closingParen) && ! ($closingParen === ')' && - \in_array($out[0], [Type::T_EXPRESSION, Type::T_UNARY])) && - \in_array(Type::T_LIST, $allowedTypes) - ) { - if ($out[0] !== Type::T_LIST || ! empty($out['enclosing'])) { - $out = [Type::T_LIST, '', [$out]]; - } - - switch ($closingParen) { - case ')': - $out['enclosing'] = 'parent'; // parenthesis list - break; - - case ']': - $out['enclosing'] = 'bracket'; // bracketed list - break; - } - - return true; - } - - $this->seek($s); - - if (\in_array(Type::T_MAP, $allowedTypes) && $this->map($out)) { - return true; - } - - return false; - } - - /** - * Parse left-hand side of subexpression - * - * @param array $lhs - * @param int $minP - * - * @return array - */ - protected function expHelper($lhs, $minP) - { - $operators = static::$operatorPattern; - - $ss = $this->count; - $whiteBefore = isset($this->buffer[$this->count - 1]) && - ctype_space($this->buffer[$this->count - 1]); - - while ($this->match($operators, $m, false) && static::$precedence[$m[1]] >= $minP) { - $whiteAfter = isset($this->buffer[$this->count]) && - ctype_space($this->buffer[$this->count]); - $varAfter = isset($this->buffer[$this->count]) && - $this->buffer[$this->count] === '$'; - - $this->whitespace(); - - $op = $m[1]; - - // don't turn negative numbers into expressions - if ($op === '-' && $whiteBefore && ! $whiteAfter && ! $varAfter) { - break; - } - - if (! $this->value($rhs) && ! $this->expression($rhs, true, false)) { - break; - } - - if ($op === '-' && ! $whiteAfter && $rhs[0] === Type::T_KEYWORD) { - break; - } - - // consume higher-precedence operators on the right-hand side - $rhs = $this->expHelper($rhs, static::$precedence[$op] + 1); - - $lhs = [Type::T_EXPRESSION, $op, $lhs, $rhs, $this->inParens, $whiteBefore, $whiteAfter]; - - $ss = $this->count; - $whiteBefore = isset($this->buffer[$this->count - 1]) && - ctype_space($this->buffer[$this->count - 1]); - } - - $this->seek($ss); - - return $lhs; - } - - /** - * Parse value - * - * @param array $out - * - * @return bool - */ - protected function value(&$out) - { - if (! isset($this->buffer[$this->count])) { - return false; - } - - $s = $this->count; - $char = $this->buffer[$this->count]; - - if ( - $this->literal('url(', 4) && - $this->match('data:([a-z]+)\/([a-z0-9.+-]+);base64,', $m, false) - ) { - $len = strspn( - $this->buffer, - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwyxz0123456789+/=', - $this->count - ); - - $this->count += $len; - - if ($this->matchChar(')')) { - $content = substr($this->buffer, $s, $this->count - $s); - $out = [Type::T_KEYWORD, $content]; - - return true; - } - } - - $this->seek($s); - - if ( - $this->literal('url(', 4, false) && - $this->match('\s*(\/\/[^\s\)]+)\s*', $m) - ) { - $content = 'url(' . $m[1]; - - if ($this->matchChar(')')) { - $content .= ')'; - $out = [Type::T_KEYWORD, $content]; - - return true; - } - } - - $this->seek($s); - - // not - if ($char === 'n' && $this->literal('not', 3, false)) { - if ( - $this->whitespace() && - $this->value($inner) - ) { - $out = [Type::T_UNARY, 'not', $inner, $this->inParens]; - - return true; - } - - $this->seek($s); - - if ($this->parenValue($inner)) { - $out = [Type::T_UNARY, 'not', $inner, $this->inParens]; - - return true; - } - - $this->seek($s); - } - - // addition - if ($char === '+') { - $this->count++; - - $follow_white = $this->whitespace(); - - if ($this->value($inner)) { - $out = [Type::T_UNARY, '+', $inner, $this->inParens]; - - return true; - } - - if ($follow_white) { - $out = [Type::T_KEYWORD, $char]; - return true; - } - - $this->seek($s); - - return false; - } - - // negation - if ($char === '-') { - if ($this->customProperty($out)) { - return true; - } - - $this->count++; - - $follow_white = $this->whitespace(); - - if ($this->variable($inner) || $this->unit($inner) || $this->parenValue($inner)) { - $out = [Type::T_UNARY, '-', $inner, $this->inParens]; - - return true; - } - - if ( - $this->keyword($inner) && - ! $this->func($inner, $out) - ) { - $out = [Type::T_UNARY, '-', $inner, $this->inParens]; - - return true; - } - - if ($follow_white) { - $out = [Type::T_KEYWORD, $char]; - - return true; - } - - $this->seek($s); - } - - // paren - if ($char === '(' && $this->parenValue($out)) { - return true; - } - - if ($char === '#') { - if ($this->interpolation($out) || $this->color($out)) { - return true; - } - - $this->count++; - - if ($this->keyword($keyword)) { - $out = [Type::T_KEYWORD, '#' . $keyword]; - - return true; - } - - $this->count--; - } - - if ($this->matchChar('&', true)) { - $out = [Type::T_SELF]; - - return true; - } - - if ($char === '$' && $this->variable($out)) { - return true; - } - - if ($char === 'p' && $this->progid($out)) { - return true; - } - - if (($char === '"' || $char === "'") && $this->string($out)) { - return true; - } - - if ($this->unit($out)) { - return true; - } - - // unicode range with wildcards - if ( - $this->literal('U+', 2) && - $this->match('\?+|([0-9A-F]+(\?+|(-[0-9A-F]+))?)', $m, false) - ) { - $unicode = explode('-', $m[0]); - if (strlen(reset($unicode)) <= 6 && strlen(end($unicode)) <= 6) { - $out = [Type::T_KEYWORD, 'U+' . $m[0]]; - - return true; - } - $this->count -= strlen($m[0]) + 2; - } - - if ($this->keyword($keyword, false)) { - if ($this->func($keyword, $out)) { - return true; - } - - $this->whitespace(); - - if ($keyword === 'null') { - $out = [Type::T_NULL]; - } else { - $out = [Type::T_KEYWORD, $keyword]; - } - - return true; - } - - return false; - } - - /** - * Parse parenthesized value - * - * @param array $out - * - * @return bool - */ - protected function parenValue(&$out) - { - $s = $this->count; - - $inParens = $this->inParens; - - if ($this->matchChar('(')) { - if ($this->matchChar(')')) { - $out = [Type::T_LIST, '', []]; - - return true; - } - - $this->inParens = true; - - if ( - $this->expression($exp) && - $this->matchChar(')') - ) { - $out = $exp; - $this->inParens = $inParens; - - return true; - } - } - - $this->inParens = $inParens; - $this->seek($s); - - return false; - } - - /** - * Parse "progid:" - * - * @param array $out - * - * @return bool - */ - protected function progid(&$out) - { - $s = $this->count; - - if ( - $this->literal('progid:', 7, false) && - $this->openString('(', $fn) && - $this->matchChar('(') - ) { - $this->openString(')', $args, '('); - - if ($this->matchChar(')')) { - $out = [Type::T_STRING, '', [ - 'progid:', $fn, '(', $args, ')' - ]]; - - return true; - } - } - - $this->seek($s); - - return false; - } - - /** - * Parse function call - * - * @param string $name - * @param array $func - * - * @return bool - */ - protected function func($name, &$func) - { - $s = $this->count; - - if ($this->matchChar('(')) { - if ($name === 'alpha' && $this->argumentList($args)) { - $func = [Type::T_FUNCTION, $name, [Type::T_STRING, '', $args]]; - - return true; - } - - if ($name !== 'expression' && ! preg_match('/^(-[a-z]+-)?calc$/', $name)) { - $ss = $this->count; - - if ( - $this->argValues($args) && - $this->matchChar(')') - ) { - $func = [Type::T_FUNCTION_CALL, $name, $args]; - - return true; - } - - $this->seek($ss); - } - - if ( - ($this->openString(')', $str, '(') || true) && - $this->matchChar(')') - ) { - $args = []; - - if (! empty($str)) { - $args[] = [null, [Type::T_STRING, '', [$str]]]; - } - - $func = [Type::T_FUNCTION_CALL, $name, $args]; - - return true; - } - } - - $this->seek($s); - - return false; - } - - /** - * Parse function call argument list - * - * @param array $out - * - * @return bool - */ - protected function argumentList(&$out) - { - $s = $this->count; - $this->matchChar('('); - - $args = []; - - while ($this->keyword($var)) { - if ( - $this->matchChar('=') && - $this->expression($exp) - ) { - $args[] = [Type::T_STRING, '', [$var . '=']]; - $arg = $exp; - } else { - break; - } - - $args[] = $arg; - - if (! $this->matchChar(',')) { - break; - } - - $args[] = [Type::T_STRING, '', [', ']]; - } - - if (! $this->matchChar(')') || ! $args) { - $this->seek($s); - - return false; - } - - $out = $args; - - return true; - } - - /** - * Parse mixin/function definition argument list - * - * @param array $out - * - * @return bool - */ - protected function argumentDef(&$out) - { - $s = $this->count; - $this->matchChar('('); - - $args = []; - - while ($this->variable($var)) { - $arg = [$var[1], null, false]; - - $ss = $this->count; - - if ( - $this->matchChar(':') && - $this->genericList($defaultVal, 'expression', '', true) - ) { - $arg[1] = $defaultVal; - } else { - $this->seek($ss); - } - - $ss = $this->count; - - if ($this->literal('...', 3)) { - $sss = $this->count; - - if (! $this->matchChar(')')) { - throw $this->parseError('... has to be after the final argument'); - } - - $arg[2] = true; - - $this->seek($sss); - } else { - $this->seek($ss); - } - - $args[] = $arg; - - if (! $this->matchChar(',')) { - break; - } - } - - if (! $this->matchChar(')')) { - $this->seek($s); - - return false; - } - - $out = $args; - - return true; - } - - /** - * Parse map - * - * @param array $out - * - * @return bool - */ - protected function map(&$out) - { - $s = $this->count; - - if (! $this->matchChar('(')) { - return false; - } - - $keys = []; - $values = []; - - while ( - $this->genericList($key, 'expression', '', true) && - $this->matchChar(':') && - $this->genericList($value, 'expression', '', true) - ) { - $keys[] = $key; - $values[] = $value; - - if (! $this->matchChar(',')) { - break; - } - } - - if (! $keys || ! $this->matchChar(')')) { - $this->seek($s); - - return false; - } - - $out = [Type::T_MAP, $keys, $values]; - - return true; - } - - /** - * Parse color - * - * @param array $out - * - * @return bool - */ - protected function color(&$out) - { - $s = $this->count; - - if ($this->match('(#([0-9a-f]+)\b)', $m)) { - if (\in_array(\strlen($m[2]), [3,4,6,8])) { - $out = [Type::T_KEYWORD, $m[0]]; - - return true; - } - - $this->seek($s); - - return false; - } - - return false; - } - - /** - * Parse number with unit - * - * @param array $unit - * - * @return bool - */ - protected function unit(&$unit) - { - $s = $this->count; - - if ($this->match('([0-9]*(\.)?[0-9]+)([%a-zA-Z]+)?', $m, false)) { - if (\strlen($this->buffer) === $this->count || ! ctype_digit($this->buffer[$this->count])) { - $this->whitespace(); - - $unit = new Node\Number($m[1], empty($m[3]) ? '' : $m[3]); - - return true; - } - - $this->seek($s); - } - - return false; - } - - /** - * Parse string - * - * @param array $out - * @param bool $keepDelimWithInterpolation - * - * @return bool - */ - protected function string(&$out, $keepDelimWithInterpolation = false) - { - $s = $this->count; - - if ($this->matchChar('"', false)) { - $delim = '"'; - } elseif ($this->matchChar("'", false)) { - $delim = "'"; - } else { - return false; - } - - $content = []; - $oldWhite = $this->eatWhiteDefault; - $this->eatWhiteDefault = false; - $hasInterpolation = false; - - while ($this->matchString($m, $delim)) { - if ($m[1] !== '') { - $content[] = $m[1]; - } - - if ($m[2] === '#{') { - $this->count -= \strlen($m[2]); - - if ($this->interpolation($inter, false)) { - $content[] = $inter; - $hasInterpolation = true; - } else { - $this->count += \strlen($m[2]); - $content[] = '#{'; // ignore it - } - } elseif ($m[2] === "\r") { - $content[] = chr(10); - // TODO : warning - # DEPRECATION WARNING on line x, column y of zzz: - # Unescaped multiline strings are deprecated and will be removed in a future version of Sass. - # To include a newline in a string, use "\a" or "\a " as in CSS. - if ($this->matchChar("\n", false)) { - $content[] = ' '; - } - } elseif ($m[2] === '\\') { - if ( - $this->literal("\r\n", 2, false) || - $this->matchChar("\r", false) || - $this->matchChar("\n", false) || - $this->matchChar("\f", false) - ) { - // this is a continuation escaping, to be ignored - } elseif ($this->matchEscapeCharacter($c)) { - $content[] = $c; - } else { - throw $this->parseError('Unterminated escape sequence'); - } - } else { - $this->count -= \strlen($delim); - break; // delim - } - } - - $this->eatWhiteDefault = $oldWhite; - - if ($this->literal($delim, \strlen($delim))) { - if ($hasInterpolation && ! $keepDelimWithInterpolation) { - $delim = '"'; - } - - $out = [Type::T_STRING, $delim, $content]; - - return true; - } - - $this->seek($s); - - return false; - } - - /** - * @param string $out - * @param bool $inKeywords - * - * @return bool - */ - protected function matchEscapeCharacter(&$out, $inKeywords = false) - { - $s = $this->count; - if ($this->match('[a-f0-9]', $m, false)) { - $hex = $m[0]; - - for ($i = 5; $i--;) { - if ($this->match('[a-f0-9]', $m, false)) { - $hex .= $m[0]; - } else { - break; - } - } - - // CSS allows Unicode escape sequences to be followed by a delimiter space - // (necessary in some cases for shorter sequences to disambiguate their end) - $this->matchChar(' ', false); - - $value = hexdec($hex); - - if (!$inKeywords && ($value == 0 || ($value >= 0xD800 && $value <= 0xDFFF) || $value >= 0x10FFFF)) { - $out = "\xEF\xBF\xBD"; // "\u{FFFD}" but with a syntax supported on PHP 5 - } elseif ($value < 0x20) { - $out = Util::mbChr($value); - } else { - $out = Util::mbChr($value); - } - - return true; - } - - if ($this->match('.', $m, false)) { - if ($inKeywords && in_array($m[0], ["'",'"','@','&',' ','\\',':','/','%'])) { - $this->seek($s); - return false; - } - $out = $m[0]; - - return true; - } - - return false; - } - - /** - * Parse keyword or interpolation - * - * @param array $out - * @param bool $restricted - * - * @return bool - */ - protected function mixedKeyword(&$out, $restricted = false) - { - $parts = []; - - $oldWhite = $this->eatWhiteDefault; - $this->eatWhiteDefault = false; - - for (;;) { - if ($restricted ? $this->restrictedKeyword($key) : $this->keyword($key)) { - $parts[] = $key; - continue; - } - - if ($this->interpolation($inter)) { - $parts[] = $inter; - continue; - } - - break; - } - - $this->eatWhiteDefault = $oldWhite; - - if (! $parts) { - return false; - } - - if ($this->eatWhiteDefault) { - $this->whitespace(); - } - - $out = $parts; - - return true; - } - - /** - * Parse an unbounded string stopped by $end - * - * @param string $end - * @param array $out - * @param string $nestOpen - * @param string $nestClose - * @param bool $rtrim - * @param string $disallow - * - * @return bool - */ - protected function openString($end, &$out, $nestOpen = null, $nestClose = null, $rtrim = true, $disallow = null) - { - $oldWhite = $this->eatWhiteDefault; - $this->eatWhiteDefault = false; - - if ($nestOpen && ! $nestClose) { - $nestClose = $end; - } - - $patt = ($disallow ? '[^' . $this->pregQuote($disallow) . ']' : '.'); - $patt = '(' . $patt . '*?)([\'"]|#\{|' - . $this->pregQuote($end) . '|' - . (($nestClose && $nestClose !== $end) ? $this->pregQuote($nestClose) . '|' : '') - . static::$commentPattern . ')'; - - $nestingLevel = 0; - - $content = []; - - while ($this->match($patt, $m, false)) { - if (isset($m[1]) && $m[1] !== '') { - $content[] = $m[1]; - - if ($nestOpen) { - $nestingLevel += substr_count($m[1], $nestOpen); - } - } - - $tok = $m[2]; - - $this->count -= \strlen($tok); - - if ($tok === $end && ! $nestingLevel) { - break; - } - - if ($tok === $nestClose) { - $nestingLevel--; - } - - if (($tok === "'" || $tok === '"') && $this->string($str, true)) { - $content[] = $str; - continue; - } - - if ($tok === '#{' && $this->interpolation($inter)) { - $content[] = $inter; - continue; - } - - $content[] = $tok; - $this->count += \strlen($tok); - } - - $this->eatWhiteDefault = $oldWhite; - - if (! $content || $tok !== $end) { - return false; - } - - // trim the end - if ($rtrim && \is_string(end($content))) { - $content[\count($content) - 1] = rtrim(end($content)); - } - - $out = [Type::T_STRING, '', $content]; - - return true; - } - - /** - * Parser interpolation - * - * @param string|array $out - * @param bool $lookWhite save information about whitespace before and after - * - * @return bool - */ - protected function interpolation(&$out, $lookWhite = true) - { - $oldWhite = $this->eatWhiteDefault; - $allowVars = $this->allowVars; - $this->allowVars = true; - $this->eatWhiteDefault = true; - - $s = $this->count; - - if ( - $this->literal('#{', 2) && - $this->valueList($value) && - $this->matchChar('}', false) - ) { - if ($value === [Type::T_SELF]) { - $out = $value; - } else { - if ($lookWhite) { - $left = ($s > 0 && preg_match('/\s/', $this->buffer[$s - 1])) ? ' ' : ''; - $right = ( - ! empty($this->buffer[$this->count]) && - preg_match('/\s/', $this->buffer[$this->count]) - ) ? ' ' : ''; - } else { - $left = $right = false; - } - - $out = [Type::T_INTERPOLATE, $value, $left, $right]; - } - - $this->eatWhiteDefault = $oldWhite; - $this->allowVars = $allowVars; - - if ($this->eatWhiteDefault) { - $this->whitespace(); - } - - return true; - } - - $this->seek($s); - - $this->eatWhiteDefault = $oldWhite; - $this->allowVars = $allowVars; - - return false; - } - - /** - * Parse property name (as an array of parts or a string) - * - * @param array $out - * - * @return bool - */ - protected function propertyName(&$out) - { - $parts = []; - - $oldWhite = $this->eatWhiteDefault; - $this->eatWhiteDefault = false; - - for (;;) { - if ($this->interpolation($inter)) { - $parts[] = $inter; - continue; - } - - if ($this->keyword($text)) { - $parts[] = $text; - continue; - } - - if (! $parts && $this->match('[:.#]', $m, false)) { - // css hacks - $parts[] = $m[0]; - continue; - } - - break; - } - - $this->eatWhiteDefault = $oldWhite; - - if (! $parts) { - return false; - } - - // match comment hack - if (preg_match(static::$whitePattern, $this->buffer, $m, 0, $this->count)) { - if (! empty($m[0])) { - $parts[] = $m[0]; - $this->count += \strlen($m[0]); - } - } - - $this->whitespace(); // get any extra whitespace - - $out = [Type::T_STRING, '', $parts]; - - return true; - } - - /** - * Parse custom property name (as an array of parts or a string) - * - * @param array $out - * - * @return bool - */ - protected function customProperty(&$out) - { - $s = $this->count; - - if (! $this->literal('--', 2, false)) { - return false; - } - - $parts = ['--']; - - $oldWhite = $this->eatWhiteDefault; - $this->eatWhiteDefault = false; - - for (;;) { - if ($this->interpolation($inter)) { - $parts[] = $inter; - continue; - } - - if ($this->matchChar('&', false)) { - $parts[] = [Type::T_SELF]; - continue; - } - - if ($this->variable($var)) { - $parts[] = $var; - continue; - } - - if ($this->keyword($text)) { - $parts[] = $text; - continue; - } - - break; - } - - $this->eatWhiteDefault = $oldWhite; - - if (\count($parts) == 1) { - $this->seek($s); - - return false; - } - - $this->whitespace(); // get any extra whitespace - - $out = [Type::T_STRING, '', $parts]; - - return true; - } - - /** - * Parse comma separated selector list - * - * @param array $out - * @param string|bool $subSelector - * - * @return bool - */ - protected function selectors(&$out, $subSelector = false) - { - $s = $this->count; - $selectors = []; - - while ($this->selector($sel, $subSelector)) { - $selectors[] = $sel; - - if (! $this->matchChar(',', true)) { - break; - } - - while ($this->matchChar(',', true)) { - ; // ignore extra - } - } - - if (! $selectors) { - $this->seek($s); - - return false; - } - - $out = $selectors; - - return true; - } - - /** - * Parse whitespace separated selector list - * - * @param array $out - * @param string|bool $subSelector - * - * @return bool - */ - protected function selector(&$out, $subSelector = false) - { - $selector = []; - - $discardComments = $this->discardComments; - $this->discardComments = true; - - for (;;) { - $s = $this->count; - - if ($this->match('[>+~]+', $m, true)) { - if ( - $subSelector && \is_string($subSelector) && strpos($subSelector, 'nth-') === 0 && - $m[0] === '+' && $this->match("(\d+|n\b)", $counter) - ) { - $this->seek($s); - } else { - $selector[] = [$m[0]]; - continue; - } - } - - if ($this->selectorSingle($part, $subSelector)) { - $selector[] = $part; - $this->whitespace(); - continue; - } - - break; - } - - $this->discardComments = $discardComments; - - if (! $selector) { - return false; - } - - $out = $selector; - - return true; - } - - /** - * parsing escaped chars in selectors: - * - escaped single chars are kept escaped in the selector but in a normalized form - * (if not in 0-9a-f range as this would be ambigous) - * - other escaped sequences (multibyte chars or 0-9a-f) are kept in their initial escaped form, - * normalized to lowercase - * - * TODO: this is a fallback solution. Ideally escaped chars in selectors should be encoded as the genuine chars, - * and escaping added when printing in the Compiler, where/if it's mandatory - * - but this require a better formal selector representation instead of the array we have now - * - * @param string $out - * @param bool $keepEscapedNumber - * - * @return bool - */ - protected function matchEscapeCharacterInSelector(&$out, $keepEscapedNumber = false) - { - $s_escape = $this->count; - if ($this->match('\\\\', $m)) { - $out = '\\' . $m[0]; - return true; - } - - if ($this->matchEscapeCharacter($escapedout, true)) { - if (strlen($escapedout) === 1) { - if (!preg_match(",\w,", $escapedout)) { - $out = '\\' . $escapedout; - return true; - } elseif (! $keepEscapedNumber || ! \is_numeric($escapedout)) { - $out = $escapedout; - return true; - } - } - $escape_sequence = rtrim(substr($this->buffer, $s_escape, $this->count - $s_escape)); - if (strlen($escape_sequence) < 6) { - $escape_sequence .= ' '; - } - $out = '\\' . strtolower($escape_sequence); - return true; - } - if ($this->match('\\S', $m)) { - $out = '\\' . $m[0]; - return true; - } - - - return false; - } - - /** - * Parse the parts that make up a selector - * - * {@internal - * div[yes=no]#something.hello.world:nth-child(-2n+1)%placeholder - * }} - * - * @param array $out - * @param string|bool $subSelector - * - * @return bool - */ - protected function selectorSingle(&$out, $subSelector = false) - { - $oldWhite = $this->eatWhiteDefault; - $this->eatWhiteDefault = false; - - $parts = []; - - if ($this->matchChar('*', false)) { - $parts[] = '*'; - } - - for (;;) { - if (! isset($this->buffer[$this->count])) { - break; - } - - $s = $this->count; - $char = $this->buffer[$this->count]; - - // see if we can stop early - if ($char === '{' || $char === ',' || $char === ';' || $char === '}' || $char === '@') { - break; - } - - // parsing a sub selector in () stop with the closing ) - if ($subSelector && $char === ')') { - break; - } - - //self - switch ($char) { - case '&': - $parts[] = Compiler::$selfSelector; - $this->count++; - ! $this->cssOnly || $this->assertPlainCssValid(false, $s); - continue 2; - - case '.': - $parts[] = '.'; - $this->count++; - continue 2; - - case '|': - $parts[] = '|'; - $this->count++; - continue 2; - } - - // handling of escaping in selectors : get the escaped char - if ($char === '\\') { - $this->count++; - if ($this->matchEscapeCharacterInSelector($escaped, true)) { - $parts[] = $escaped; - continue; - } - $this->count--; - } - - if ($char === '%') { - $this->count++; - - if ($this->placeholder($placeholder)) { - $parts[] = '%'; - $parts[] = $placeholder; - ! $this->cssOnly || $this->assertPlainCssValid(false, $s); - continue; - } - - break; - } - - if ($char === '#') { - if ($this->interpolation($inter)) { - $parts[] = $inter; - ! $this->cssOnly || $this->assertPlainCssValid(false, $s); - continue; - } - - $parts[] = '#'; - $this->count++; - continue; - } - - // a pseudo selector - if ($char === ':') { - if ($this->buffer[$this->count + 1] === ':') { - $this->count += 2; - $part = '::'; - } else { - $this->count++; - $part = ':'; - } - - if ($this->mixedKeyword($nameParts, true)) { - $parts[] = $part; - - foreach ($nameParts as $sub) { - $parts[] = $sub; - } - - $ss = $this->count; - - if ( - $nameParts === ['not'] || - $nameParts === ['is'] || - $nameParts === ['has'] || - $nameParts === ['where'] || - $nameParts === ['slotted'] || - $nameParts === ['nth-child'] || - $nameParts === ['nth-last-child'] || - $nameParts === ['nth-of-type'] || - $nameParts === ['nth-last-of-type'] - ) { - if ( - $this->matchChar('(', true) && - ($this->selectors($subs, reset($nameParts)) || true) && - $this->matchChar(')') - ) { - $parts[] = '('; - - while ($sub = array_shift($subs)) { - while ($ps = array_shift($sub)) { - foreach ($ps as &$p) { - $parts[] = $p; - } - - if (\count($sub) && reset($sub)) { - $parts[] = ' '; - } - } - - if (\count($subs) && reset($subs)) { - $parts[] = ', '; - } - } - - $parts[] = ')'; - } else { - $this->seek($ss); - } - } elseif ( - $this->matchChar('(', true) && - ($this->openString(')', $str, '(') || true) && - $this->matchChar(')') - ) { - $parts[] = '('; - - if (! empty($str)) { - $parts[] = $str; - } - - $parts[] = ')'; - } else { - $this->seek($ss); - } - - continue; - } - } - - $this->seek($s); - - // 2n+1 - if ($subSelector && \is_string($subSelector) && strpos($subSelector, 'nth-') === 0) { - if ($this->match("(\s*(\+\s*|\-\s*)?(\d+|n|\d+n))+", $counter)) { - $parts[] = $counter[0]; - //$parts[] = str_replace(' ', '', $counter[0]); - continue; - } - } - - $this->seek($s); - - // attribute selector - if ( - $char === '[' && - $this->matchChar('[') && - ($this->openString(']', $str, '[') || true) && - $this->matchChar(']') - ) { - $parts[] = '['; - - if (! empty($str)) { - $parts[] = $str; - } - - $parts[] = ']'; - continue; - } - - $this->seek($s); - - // for keyframes - if ($this->unit($unit)) { - $parts[] = $unit; - continue; - } - - if ($this->restrictedKeyword($name, false, true)) { - $parts[] = $name; - continue; - } - - break; - } - - $this->eatWhiteDefault = $oldWhite; - - if (! $parts) { - return false; - } - - $out = $parts; - - return true; - } - - /** - * Parse a variable - * - * @param array $out - * - * @return bool - */ - protected function variable(&$out) - { - $s = $this->count; - - if ( - $this->matchChar('$', false) && - $this->keyword($name) - ) { - if ($this->allowVars) { - $out = [Type::T_VARIABLE, $name]; - } else { - $out = [Type::T_KEYWORD, '$' . $name]; - } - - return true; - } - - $this->seek($s); - - return false; - } - - /** - * Parse a keyword - * - * @param string $word - * @param bool $eatWhitespace - * @param bool $inSelector - * - * @return bool - */ - protected function keyword(&$word, $eatWhitespace = null, $inSelector = false) - { - $s = $this->count; - $match = $this->match( - $this->utf8 - ? '(([\pL\w\x{00A0}-\x{10FFFF}_\-\*!"\']|\\\\[a-f0-9]{6} ?|\\\\[a-f0-9]{1,5}(?![a-f0-9]) ?|[\\\\].)([\pL\w\x{00A0}-\x{10FFFF}\-_"\']|\\\\[a-f0-9]{6} ?|\\\\[a-f0-9]{1,5}(?![a-f0-9]) ?|[\\\\].)*)' - : '(([\w_\-\*!"\']|\\\\[a-f0-9]{6} ?|\\\\[a-f0-9]{1,5}(?![a-f0-9]) ?|[\\\\].)([\w\-_"\']|\\\\[a-f0-9]{6} ?|\\\\[a-f0-9]{1,5}(?![a-f0-9]) ?|[\\\\].)*)', - $m, - false - ); - - if ($match) { - $word = $m[1]; - - // handling of escaping in keyword : get the escaped char - if (strpos($word, '\\') !== false) { - $send = $this->count; - $escapedWord = []; - $this->seek($s); - $previousEscape = false; - while ($this->count < $send) { - $char = $this->buffer[$this->count]; - $this->count++; - if ( - $this->count < $send - && $char === '\\' - && !$previousEscape - && ( - $inSelector ? - $this->matchEscapeCharacterInSelector($out) - : - $this->matchEscapeCharacter($out, true) - ) - ) { - $escapedWord[] = $out; - } else { - if ($previousEscape) { - $previousEscape = false; - } elseif ($char === '\\') { - $previousEscape = true; - } - $escapedWord[] = $char; - } - } - - $word = implode('', $escapedWord); - } - - if (is_null($eatWhitespace) ? $this->eatWhiteDefault : $eatWhitespace) { - $this->whitespace(); - } - - return true; - } - - return false; - } - - /** - * Parse a keyword that should not start with a number - * - * @param string $word - * @param bool $eatWhitespace - * @param bool $inSelector - * - * @return bool - */ - protected function restrictedKeyword(&$word, $eatWhitespace = null, $inSelector = false) - { - $s = $this->count; - - if ($this->keyword($word, $eatWhitespace, $inSelector) && (\ord($word[0]) > 57 || \ord($word[0]) < 48)) { - return true; - } - - $this->seek($s); - - return false; - } - - /** - * Parse a placeholder - * - * @param string|array $placeholder - * - * @return bool - */ - protected function placeholder(&$placeholder) - { - $match = $this->match( - $this->utf8 - ? '([\pL\w\-_]+)' - : '([\w\-_]+)', - $m - ); - - if ($match) { - $placeholder = $m[1]; - - return true; - } - - if ($this->interpolation($placeholder)) { - return true; - } - - return false; - } - - /** - * Parse a url - * - * @param array $out - * - * @return bool - */ - protected function url(&$out) - { - if ($this->literal('url(', 4)) { - $s = $this->count; - - if ( - ($this->string($out) || $this->spaceList($out)) && - $this->matchChar(')') - ) { - $out = [Type::T_STRING, '', ['url(', $out, ')']]; - - return true; - } - - $this->seek($s); - - if ( - $this->openString(')', $out) && - $this->matchChar(')') - ) { - $out = [Type::T_STRING, '', ['url(', $out, ')']]; - - return true; - } - } - - return false; - } - - /** - * Consume an end of statement delimiter - * @param bool $eatWhitespace - * - * @return bool - */ - protected function end($eatWhitespace = null) - { - if ($this->matchChar(';', $eatWhitespace)) { - return true; - } - - if ($this->count === \strlen($this->buffer) || $this->buffer[$this->count] === '}') { - // if there is end of file or a closing block next then we don't need a ; - return true; - } - - return false; - } - - /** - * Strip assignment flag from the list - * - * @param array $value - * - * @return string[] - */ - protected function stripAssignmentFlags(&$value) - { - $flags = []; - - for ($token = &$value; $token[0] === Type::T_LIST && ($s = \count($token[2])); $token = &$lastNode) { - $lastNode = &$token[2][$s - 1]; - - while ($lastNode[0] === Type::T_KEYWORD && \in_array($lastNode[1], ['!default', '!global'])) { - array_pop($token[2]); - - $node = end($token[2]); - $token = $this->flattenList($token); - $flags[] = $lastNode[1]; - $lastNode = $node; - } - } - - return $flags; - } - - /** - * Strip optional flag from selector list - * - * @param array $selectors - * - * @return bool - */ - protected function stripOptionalFlag(&$selectors) - { - $optional = false; - $selector = end($selectors); - $part = end($selector); - - if ($part === ['!optional']) { - array_pop($selectors[\count($selectors) - 1]); - - $optional = true; - } - - return $optional; - } - - /** - * Turn list of length 1 into value type - * - * @param array $value - * - * @return array - */ - protected function flattenList($value) - { - if ($value[0] === Type::T_LIST && \count($value[2]) === 1) { - return $this->flattenList($value[2][0]); - } - - return $value; - } - - /** - * Quote regular expression - * - * @param string $what - * - * @return string - */ - private function pregQuote($what) - { - return preg_quote($what, '/'); - } - - /** - * Extract line numbers from buffer - * - * @param string $buffer - * - * @return void - */ - private function extractLineNumbers($buffer) - { - $this->sourcePositions = [0 => 0]; - $prev = 0; - - while (($pos = strpos($buffer, "\n", $prev)) !== false) { - $this->sourcePositions[] = $pos; - $prev = $pos + 1; - } - - $this->sourcePositions[] = \strlen($buffer); - - if (substr($buffer, -1) !== "\n") { - $this->sourcePositions[] = \strlen($buffer) + 1; - } - } - - /** - * Get source line number and column (given character position in the buffer) - * - * @param int $pos - * - * @return array - * @phpstan-return array{int, int} - */ - private function getSourcePosition($pos) - { - $low = 0; - $high = \count($this->sourcePositions); - - while ($low < $high) { - $mid = (int) (($high + $low) / 2); - - if ($pos < $this->sourcePositions[$mid]) { - $high = $mid - 1; - continue; - } - - if ($pos >= $this->sourcePositions[$mid + 1]) { - $low = $mid + 1; - continue; - } - - return [$mid + 1, $pos - $this->sourcePositions[$mid]]; - } - - return [$low + 1, $pos - $this->sourcePositions[$low]]; - } - - /** - * Save internal encoding of mbstring - * - * When mbstring.func_overload is used to replace the standard PHP string functions, - * this method configures the internal encoding to a single-byte one so that the - * behavior matches the normal behavior of PHP string functions while using the parser. - * The existing internal encoding is saved and will be restored when calling {@see restoreEncoding}. - * - * If mbstring.func_overload is not used (or does not override string functions), this method is a no-op. - * - * @return void - */ - private function saveEncoding() - { - if (\PHP_VERSION_ID < 80000 && \extension_loaded('mbstring') && (2 & (int) ini_get('mbstring.func_overload')) > 0) { - $this->encoding = mb_internal_encoding(); - - mb_internal_encoding('iso-8859-1'); - } - } - - /** - * Restore internal encoding - * - * @return void - */ - private function restoreEncoding() - { - if (\extension_loaded('mbstring') && $this->encoding) { - mb_internal_encoding($this->encoding); - } - } -} diff --git a/lib/scssphp/scssphp/src/SourceMap/Base64.php b/lib/scssphp/scssphp/src/SourceMap/Base64.php deleted file mode 100644 index 00b6b4545..000000000 --- a/lib/scssphp/scssphp/src/SourceMap/Base64.php +++ /dev/null @@ -1,187 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\SourceMap; - -/** - * Base 64 Encode/Decode - * - * @author Anthon Pang <anthon.pang@gmail.com> - * - * @internal - */ -class Base64 -{ - /** - * @var array<int, string> - */ - private static $encodingMap = [ - 0 => 'A', - 1 => 'B', - 2 => 'C', - 3 => 'D', - 4 => 'E', - 5 => 'F', - 6 => 'G', - 7 => 'H', - 8 => 'I', - 9 => 'J', - 10 => 'K', - 11 => 'L', - 12 => 'M', - 13 => 'N', - 14 => 'O', - 15 => 'P', - 16 => 'Q', - 17 => 'R', - 18 => 'S', - 19 => 'T', - 20 => 'U', - 21 => 'V', - 22 => 'W', - 23 => 'X', - 24 => 'Y', - 25 => 'Z', - 26 => 'a', - 27 => 'b', - 28 => 'c', - 29 => 'd', - 30 => 'e', - 31 => 'f', - 32 => 'g', - 33 => 'h', - 34 => 'i', - 35 => 'j', - 36 => 'k', - 37 => 'l', - 38 => 'm', - 39 => 'n', - 40 => 'o', - 41 => 'p', - 42 => 'q', - 43 => 'r', - 44 => 's', - 45 => 't', - 46 => 'u', - 47 => 'v', - 48 => 'w', - 49 => 'x', - 50 => 'y', - 51 => 'z', - 52 => '0', - 53 => '1', - 54 => '2', - 55 => '3', - 56 => '4', - 57 => '5', - 58 => '6', - 59 => '7', - 60 => '8', - 61 => '9', - 62 => '+', - 63 => '/', - ]; - - /** - * @var array<string|int, int> - */ - private static $decodingMap = [ - 'A' => 0, - 'B' => 1, - 'C' => 2, - 'D' => 3, - 'E' => 4, - 'F' => 5, - 'G' => 6, - 'H' => 7, - 'I' => 8, - 'J' => 9, - 'K' => 10, - 'L' => 11, - 'M' => 12, - 'N' => 13, - 'O' => 14, - 'P' => 15, - 'Q' => 16, - 'R' => 17, - 'S' => 18, - 'T' => 19, - 'U' => 20, - 'V' => 21, - 'W' => 22, - 'X' => 23, - 'Y' => 24, - 'Z' => 25, - 'a' => 26, - 'b' => 27, - 'c' => 28, - 'd' => 29, - 'e' => 30, - 'f' => 31, - 'g' => 32, - 'h' => 33, - 'i' => 34, - 'j' => 35, - 'k' => 36, - 'l' => 37, - 'm' => 38, - 'n' => 39, - 'o' => 40, - 'p' => 41, - 'q' => 42, - 'r' => 43, - 's' => 44, - 't' => 45, - 'u' => 46, - 'v' => 47, - 'w' => 48, - 'x' => 49, - 'y' => 50, - 'z' => 51, - 0 => 52, - 1 => 53, - 2 => 54, - 3 => 55, - 4 => 56, - 5 => 57, - 6 => 58, - 7 => 59, - 8 => 60, - 9 => 61, - '+' => 62, - '/' => 63, - ]; - - /** - * Convert to base64 - * - * @param int $value - * - * @return string - */ - public static function encode($value) - { - return self::$encodingMap[$value]; - } - - /** - * Convert from base64 - * - * @param string $value - * - * @return int - */ - public static function decode($value) - { - return self::$decodingMap[$value]; - } -} diff --git a/lib/scssphp/scssphp/src/SourceMap/Base64VLQ.php b/lib/scssphp/scssphp/src/SourceMap/Base64VLQ.php deleted file mode 100644 index 2a5210c68..000000000 --- a/lib/scssphp/scssphp/src/SourceMap/Base64VLQ.php +++ /dev/null @@ -1,151 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\SourceMap; - -/** - * Base 64 VLQ - * - * Based on the Base 64 VLQ implementation in Closure Compiler: - * https://github.com/google/closure-compiler/blob/master/src/com/google/debugging/sourcemap/Base64VLQ.java - * - * Copyright 2011 The Closure Compiler Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @author John Lenz <johnlenz@google.com> - * @author Anthon Pang <anthon.pang@gmail.com> - * - * @internal - */ -class Base64VLQ -{ - // A Base64 VLQ digit can represent 5 bits, so it is base-32. - const VLQ_BASE_SHIFT = 5; - - // A mask of bits for a VLQ digit (11111), 31 decimal. - const VLQ_BASE_MASK = 31; - - // The continuation bit is the 6th bit. - const VLQ_CONTINUATION_BIT = 32; - - /** - * Returns the VLQ encoded value. - * - * @param int $value - * - * @return string - */ - public static function encode($value) - { - $encoded = ''; - $vlq = self::toVLQSigned($value); - - do { - $digit = $vlq & self::VLQ_BASE_MASK; - - //$vlq >>>= self::VLQ_BASE_SHIFT; // unsigned right shift - $vlq = (($vlq >> 1) & PHP_INT_MAX) >> (self::VLQ_BASE_SHIFT - 1); - - if ($vlq > 0) { - $digit |= self::VLQ_CONTINUATION_BIT; - } - - $encoded .= Base64::encode($digit); - } while ($vlq > 0); - - return $encoded; - } - - /** - * Decodes VLQValue. - * - * @param string $str - * @param int $index - * - * @return int - */ - public static function decode($str, &$index) - { - $result = 0; - $shift = 0; - - do { - $c = $str[$index++]; - $digit = Base64::decode($c); - $continuation = ($digit & self::VLQ_CONTINUATION_BIT) != 0; - $digit &= self::VLQ_BASE_MASK; - $result = $result + ($digit << $shift); - $shift = $shift + self::VLQ_BASE_SHIFT; - } while ($continuation); - - return self::fromVLQSigned($result); - } - - /** - * Converts from a two-complement value to a value where the sign bit is - * is placed in the least significant bit. For example, as decimals: - * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) - * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) - * - * @param int $value - * - * @return int - */ - private static function toVLQSigned($value) - { - if ($value < 0) { - return ((-$value) << 1) + 1; - } - - return ($value << 1) + 0; - } - - /** - * Converts to a two-complement value from a value where the sign bit is - * is placed in the least significant bit. For example, as decimals: - * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 - * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 - * - * @param int $value - * - * @return int - */ - private static function fromVLQSigned($value) - { - $negate = ($value & 1) === 1; - - //$value >>>= 1; // unsigned right shift - $value = ($value >> 1) & PHP_INT_MAX; - - if (! $negate) { - return $value; - } - - // We need to OR 0x80000000 here to ensure the 32nd bit (the sign bit) is - // always set for negative numbers. If `value` were 1, (meaning `negate` is - // true and all other bits were zeros), `value` would now be 0. -0 is just - // 0, and doesn't flip the 32nd bit as intended. All positive numbers will - // successfully flip the 32nd bit without issue, so it's a noop for them. - return -$value | 0x80000000; - } -} diff --git a/lib/scssphp/scssphp/src/SourceMap/SourceMapGenerator.php b/lib/scssphp/scssphp/src/SourceMap/SourceMapGenerator.php deleted file mode 100644 index ccd4f0261..000000000 --- a/lib/scssphp/scssphp/src/SourceMap/SourceMapGenerator.php +++ /dev/null @@ -1,390 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp\SourceMap; - -use ScssPhp\ScssPhp\Exception\CompilerException; - -/** - * Source Map Generator - * - * {@internal Derivative of oyejorge/less.php's lib/SourceMap/Generator.php, relicensed with permission. }} - * - * @author Josh Schmidt <oyejorge@gmail.com> - * @author Nicolas FRANÇOIS <nicolas.francois@frog-labs.com> - * - * @internal - */ -class SourceMapGenerator -{ - /** - * What version of source map does the generator generate? - */ - const VERSION = 3; - - /** - * Array of default options - * - * @var array - * @phpstan-var array{sourceRoot: string, sourceMapFilename: string|null, sourceMapURL: string|null, sourceMapWriteTo: string|null, outputSourceFiles: bool, sourceMapRootpath: string, sourceMapBasepath: string} - */ - protected $defaultOptions = [ - // an optional source root, useful for relocating source files - // on a server or removing repeated values in the 'sources' entry. - // This value is prepended to the individual entries in the 'source' field. - 'sourceRoot' => '', - - // an optional name of the generated code that this source map is associated with. - 'sourceMapFilename' => null, - - // url of the map - 'sourceMapURL' => null, - - // absolute path to a file to write the map to - 'sourceMapWriteTo' => null, - - // output source contents? - 'outputSourceFiles' => false, - - // base path for filename normalization - 'sourceMapRootpath' => '', - - // base path for filename normalization - 'sourceMapBasepath' => '' - ]; - - /** - * The base64 VLQ encoder - * - * @var \ScssPhp\ScssPhp\SourceMap\Base64VLQ - */ - protected $encoder; - - /** - * Array of mappings - * - * @var array - * @phpstan-var list<array{generated_line: int, generated_column: int, original_line: int, original_column: int, source_file: string}> - */ - protected $mappings = []; - - /** - * Array of contents map - * - * @var array - */ - protected $contentsMap = []; - - /** - * File to content map - * - * @var array<string, string> - */ - protected $sources = []; - - /** - * @var array<string, int> - */ - protected $sourceKeys = []; - - /** - * @var array - * @phpstan-var array{sourceRoot: string, sourceMapFilename: string|null, sourceMapURL: string|null, sourceMapWriteTo: string|null, outputSourceFiles: bool, sourceMapRootpath: string, sourceMapBasepath: string} - */ - private $options; - - /** - * @phpstan-param array{sourceRoot?: string, sourceMapFilename?: string|null, sourceMapURL?: string|null, sourceMapWriteTo?: string|null, outputSourceFiles?: bool, sourceMapRootpath?: string, sourceMapBasepath?: string} $options - */ - public function __construct(array $options = []) - { - $this->options = array_replace($this->defaultOptions, $options); - $this->encoder = new Base64VLQ(); - } - - /** - * Adds a mapping - * - * @param int $generatedLine The line number in generated file - * @param int $generatedColumn The column number in generated file - * @param int $originalLine The line number in original file - * @param int $originalColumn The column number in original file - * @param string $sourceFile The original source file - * - * @return void - */ - public function addMapping($generatedLine, $generatedColumn, $originalLine, $originalColumn, $sourceFile) - { - $this->mappings[] = [ - 'generated_line' => $generatedLine, - 'generated_column' => $generatedColumn, - 'original_line' => $originalLine, - 'original_column' => $originalColumn, - 'source_file' => $sourceFile - ]; - - $this->sources[$sourceFile] = $sourceFile; - } - - /** - * Saves the source map to a file - * - * @param string $content The content to write - * - * @return string|null - * - * @throws \ScssPhp\ScssPhp\Exception\CompilerException If the file could not be saved - * @deprecated - */ - public function saveMap($content) - { - $file = $this->options['sourceMapWriteTo']; - assert($file !== null); - $dir = \dirname($file); - - // directory does not exist - if (! is_dir($dir)) { - // FIXME: create the dir automatically? - throw new CompilerException( - sprintf('The directory "%s" does not exist. Cannot save the source map.', $dir) - ); - } - - // FIXME: proper saving, with dir write check! - if (file_put_contents($file, $content) === false) { - throw new CompilerException(sprintf('Cannot save the source map to "%s"', $file)); - } - - return $this->options['sourceMapURL']; - } - - /** - * Generates the JSON source map - * - * @param string $prefix A prefix added in the output file, which needs to shift mappings - * - * @return string - * - * @see https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit# - */ - public function generateJson($prefix = '') - { - $sourceMap = []; - $mappings = $this->generateMappings($prefix); - - // File version (always the first entry in the object) and must be a positive integer. - $sourceMap['version'] = self::VERSION; - - // An optional name of the generated code that this source map is associated with. - $file = $this->options['sourceMapFilename']; - - if ($file) { - $sourceMap['file'] = $file; - } - - // An optional source root, useful for relocating source files on a server or removing repeated values in the - // 'sources' entry. This value is prepended to the individual entries in the 'source' field. - $root = $this->options['sourceRoot']; - - if ($root) { - $sourceMap['sourceRoot'] = $root; - } - - // A list of original sources used by the 'mappings' entry. - $sourceMap['sources'] = []; - - foreach ($this->sources as $sourceFilename) { - $sourceMap['sources'][] = $this->normalizeFilename($sourceFilename); - } - - // A list of symbol names used by the 'mappings' entry. - $sourceMap['names'] = []; - - // A string with the encoded mapping data. - $sourceMap['mappings'] = $mappings; - - if ($this->options['outputSourceFiles']) { - // An optional list of source content, useful when the 'source' can't be hosted. - // The contents are listed in the same order as the sources above. - // 'null' may be used if some original sources should be retrieved by name. - $sourceMap['sourcesContent'] = $this->getSourcesContent(); - } - - // less.js compat fixes - if (\count($sourceMap['sources']) && empty($sourceMap['sourceRoot'])) { - unset($sourceMap['sourceRoot']); - } - - $jsonSourceMap = json_encode($sourceMap, JSON_UNESCAPED_SLASHES); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new \RuntimeException(json_last_error_msg()); - } - - assert($jsonSourceMap !== false); - - return $jsonSourceMap; - } - - /** - * Returns the sources contents - * - * @return string[]|null - */ - protected function getSourcesContent() - { - if (empty($this->sources)) { - return null; - } - - $content = []; - - foreach ($this->sources as $sourceFile) { - $content[] = file_get_contents($sourceFile); - } - - return $content; - } - - /** - * Generates the mappings string - * - * @param string $prefix A prefix added in the output file, which needs to shift mappings - * - * @return string - */ - public function generateMappings($prefix = '') - { - if (! \count($this->mappings)) { - return ''; - } - - $prefixLines = substr_count($prefix, "\n"); - $lastPrefixNewLine = strrpos($prefix, "\n"); - $lastPrefixLineStart = false === $lastPrefixNewLine ? 0 : $lastPrefixNewLine + 1; - $prefixColumn = strlen($prefix) - $lastPrefixLineStart; - - $this->sourceKeys = array_flip(array_keys($this->sources)); - - // group mappings by generated line number. - $groupedMap = $groupedMapEncoded = []; - - foreach ($this->mappings as $m) { - $groupedMap[$m['generated_line']][] = $m; - } - - ksort($groupedMap); - - $lastGeneratedLine = $lastOriginalIndex = $lastOriginalLine = $lastOriginalColumn = 0; - - foreach ($groupedMap as $lineNumber => $lineMap) { - if ($lineNumber > 1) { - // The prefix only impacts the column for the first line of the original output - $prefixColumn = 0; - } - $lineNumber += $prefixLines; - - while (++$lastGeneratedLine < $lineNumber) { - $groupedMapEncoded[] = ';'; - } - - $lineMapEncoded = []; - $lastGeneratedColumn = 0; - - foreach ($lineMap as $m) { - $generatedColumn = $m['generated_column'] + $prefixColumn; - - $mapEncoded = $this->encoder->encode($generatedColumn - $lastGeneratedColumn); - $lastGeneratedColumn = $generatedColumn; - - // find the index - if ($m['source_file']) { - $index = $this->findFileIndex($m['source_file']); - - if ($index !== false) { - $mapEncoded .= $this->encoder->encode($index - $lastOriginalIndex); - $lastOriginalIndex = $index; - // lines are stored 0-based in SourceMap spec version 3 - $mapEncoded .= $this->encoder->encode($m['original_line'] - 1 - $lastOriginalLine); - $lastOriginalLine = $m['original_line'] - 1; - $mapEncoded .= $this->encoder->encode($m['original_column'] - $lastOriginalColumn); - $lastOriginalColumn = $m['original_column']; - } - } - - $lineMapEncoded[] = $mapEncoded; - } - - $groupedMapEncoded[] = implode(',', $lineMapEncoded) . ';'; - } - - return rtrim(implode($groupedMapEncoded), ';'); - } - - /** - * Finds the index for the filename - * - * @param string $filename - * - * @return int|false - */ - protected function findFileIndex($filename) - { - return $this->sourceKeys[$filename]; - } - - /** - * Normalize filename - * - * @param string $filename - * - * @return string - */ - protected function normalizeFilename($filename) - { - $filename = $this->fixWindowsPath($filename); - $rootpath = $this->options['sourceMapRootpath']; - $basePath = $this->options['sourceMapBasepath']; - - // "Trim" the 'sourceMapBasepath' from the output filename. - if (\strlen($basePath) && strpos($filename, $basePath) === 0) { - $filename = substr($filename, \strlen($basePath)); - } - - // Remove extra leading path separators. - if (strpos($filename, '\\') === 0 || strpos($filename, '/') === 0) { - $filename = substr($filename, 1); - } - - return $rootpath . $filename; - } - - /** - * Fix windows paths - * - * @param string $path - * @param bool $addEndSlash - * - * @return string - */ - public function fixWindowsPath($path, $addEndSlash = false) - { - $slash = ($addEndSlash) ? '/' : ''; - - if (! empty($path)) { - $path = str_replace('\\', '/', $path); - $path = rtrim($path, '/') . $slash; - } - - return $path; - } -} diff --git a/lib/scssphp/scssphp/src/Type.php b/lib/scssphp/scssphp/src/Type.php deleted file mode 100644 index d43088785..000000000 --- a/lib/scssphp/scssphp/src/Type.php +++ /dev/null @@ -1,208 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp; - -/** - * Block/node types - * - * @author Anthon Pang <anthon.pang@gmail.com> - */ -class Type -{ - /** - * @internal - */ - const T_ASSIGN = 'assign'; - /** - * @internal - */ - const T_AT_ROOT = 'at-root'; - /** - * @internal - */ - const T_BLOCK = 'block'; - /** - * @deprecated - * @internal - */ - const T_BREAK = 'break'; - /** - * @internal - */ - const T_CHARSET = 'charset'; - const T_COLOR = 'color'; - /** - * @internal - */ - const T_COMMENT = 'comment'; - /** - * @deprecated - * @internal - */ - const T_CONTINUE = 'continue'; - /** - * @deprecated - * @internal - */ - const T_CONTROL = 'control'; - /** - * @internal - */ - const T_CUSTOM_PROPERTY = 'custom'; - /** - * @internal - */ - const T_DEBUG = 'debug'; - /** - * @internal - */ - const T_DIRECTIVE = 'directive'; - /** - * @internal - */ - const T_EACH = 'each'; - /** - * @internal - */ - const T_ELSE = 'else'; - /** - * @internal - */ - const T_ELSEIF = 'elseif'; - /** - * @internal - */ - const T_ERROR = 'error'; - /** - * @internal - */ - const T_EXPRESSION = 'exp'; - /** - * @internal - */ - const T_EXTEND = 'extend'; - /** - * @internal - */ - const T_FOR = 'for'; - const T_FUNCTION = 'function'; - /** - * @internal - */ - const T_FUNCTION_REFERENCE = 'function-reference'; - /** - * @internal - */ - const T_FUNCTION_CALL = 'fncall'; - /** - * @internal - */ - const T_HSL = 'hsl'; - /** - * @internal - */ - const T_HWB = 'hwb'; - /** - * @internal - */ - const T_IF = 'if'; - /** - * @internal - */ - const T_IMPORT = 'import'; - /** - * @internal - */ - const T_INCLUDE = 'include'; - /** - * @internal - */ - const T_INTERPOLATE = 'interpolate'; - /** - * @internal - */ - const T_INTERPOLATED = 'interpolated'; - /** - * @internal - */ - const T_KEYWORD = 'keyword'; - const T_LIST = 'list'; - const T_MAP = 'map'; - /** - * @internal - */ - const T_MEDIA = 'media'; - /** - * @internal - */ - const T_MEDIA_EXPRESSION = 'mediaExp'; - /** - * @internal - */ - const T_MEDIA_TYPE = 'mediaType'; - /** - * @internal - */ - const T_MEDIA_VALUE = 'mediaValue'; - /** - * @internal - */ - const T_MIXIN = 'mixin'; - /** - * @internal - */ - const T_MIXIN_CONTENT = 'mixin_content'; - /** - * @internal - */ - const T_NESTED_PROPERTY = 'nestedprop'; - /** - * @internal - */ - const T_NOT = 'not'; - const T_NULL = 'null'; - const T_NUMBER = 'number'; - /** - * @internal - */ - const T_RETURN = 'return'; - /** - * @internal - */ - const T_ROOT = 'root'; - /** - * @internal - */ - const T_SCSSPHP_IMPORT_ONCE = 'scssphp-import-once'; - /** - * @internal - */ - const T_SELF = 'self'; - const T_STRING = 'string'; - /** - * @internal - */ - const T_UNARY = 'unary'; - /** - * @internal - */ - const T_VARIABLE = 'var'; - /** - * @internal - */ - const T_WARN = 'warn'; - /** - * @internal - */ - const T_WHILE = 'while'; -} diff --git a/lib/scssphp/scssphp/src/Util.php b/lib/scssphp/scssphp/src/Util.php deleted file mode 100644 index ad608ceb3..000000000 --- a/lib/scssphp/scssphp/src/Util.php +++ /dev/null @@ -1,184 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp; - -use ScssPhp\ScssPhp\Base\Range; -use ScssPhp\ScssPhp\Exception\RangeException; -use ScssPhp\ScssPhp\Node\Number; - -/** - * Utility functions - * - * @author Anthon Pang <anthon.pang@gmail.com> - * - * @internal - */ -class Util -{ - /** - * Asserts that `value` falls within `range` (inclusive), leaving - * room for slight floating-point errors. - * - * @param string $name The name of the value. Used in the error message. - * @param Range $range Range of values. - * @param array|Number $value The value to check. - * @param string $unit The unit of the value. Used in error reporting. - * - * @return mixed `value` adjusted to fall within range, if it was outside by a floating-point margin. - * - * @throws \ScssPhp\ScssPhp\Exception\RangeException - */ - public static function checkRange($name, Range $range, $value, $unit = '') - { - $val = $value[1]; - $grace = new Range(-0.00001, 0.00001); - - if (! \is_numeric($val)) { - throw new RangeException("$name {$val} is not a number."); - } - - if ($range->includes($val)) { - return $val; - } - - if ($grace->includes($val - $range->first)) { - return $range->first; - } - - if ($grace->includes($val - $range->last)) { - return $range->last; - } - - throw new RangeException("$name {$val} must be between {$range->first} and {$range->last}$unit"); - } - - /** - * Encode URI component - * - * @param string $string - * - * @return string - */ - public static function encodeURIComponent($string) - { - $revert = ['%21' => '!', '%2A' => '*', '%27' => "'", '%28' => '(', '%29' => ')']; - - return strtr(rawurlencode($string), $revert); - } - - /** - * mb_chr() wrapper - * - * @param int $code - * - * @return string - */ - public static function mbChr($code) - { - // Use the native implementation if available, but not on PHP 7.2 as mb_chr(0) is buggy there - if (\PHP_VERSION_ID > 70300 && \function_exists('mb_chr')) { - return mb_chr($code, 'UTF-8'); - } - - 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); - } - - return $s; - } - - /** - * mb_strlen() wrapper - * - * @param string $string - * @return int - */ - public static function mbStrlen($string) - { - // Use the native implementation if available. - if (\function_exists('mb_strlen')) { - return mb_strlen($string, 'UTF-8'); - } - - if (\function_exists('iconv_strlen')) { - return (int) @iconv_strlen($string, 'UTF-8'); - } - - throw new \LogicException('Either mbstring (recommended) or iconv is necessary to use Scssphp.'); - } - - /** - * mb_substr() wrapper - * @param string $string - * @param int $start - * @param null|int $length - * @return string - */ - public static function mbSubstr($string, $start, $length = null) - { - // Use the native implementation if available. - if (\function_exists('mb_substr')) { - return mb_substr($string, $start, $length, 'UTF-8'); - } - - if (\function_exists('iconv_substr')) { - if ($start < 0) { - $start = static::mbStrlen($string) + $start; - if ($start < 0) { - $start = 0; - } - } - - if (null === $length) { - $length = 2147483647; - } elseif ($length < 0) { - $length = static::mbStrlen($string) + $length - $start; - if ($length < 0) { - return ''; - } - } - - return (string)iconv_substr($string, $start, $length, 'UTF-8'); - } - - throw new \LogicException('Either mbstring (recommended) or iconv is necessary to use Scssphp.'); - } - - /** - * mb_strpos wrapper - * @param string $haystack - * @param string $needle - * @param int $offset - * - * @return int|false - */ - public static function mbStrpos($haystack, $needle, $offset = 0) - { - if (\function_exists('mb_strpos')) { - return mb_strpos($haystack, $needle, $offset, 'UTF-8'); - } - - if (\function_exists('iconv_strpos')) { - return iconv_strpos($haystack, $needle, $offset, 'UTF-8'); - } - - throw new \LogicException('Either mbstring (recommended) or iconv is necessary to use Scssphp.'); - } -} diff --git a/lib/scssphp/scssphp/src/Util/Path.php b/lib/scssphp/scssphp/src/Util/Path.php deleted file mode 100644 index f399e41ab..000000000 --- a/lib/scssphp/scssphp/src/Util/Path.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php - -namespace ScssPhp\ScssPhp\Util; - -/** - * @internal - */ -class Path -{ - /** - * @param string $path - * - * @return bool - */ - public static function isAbsolute($path) - { - if ($path === '') { - return false; - } - - if ($path[0] === '/') { - return true; - } - - if (\DIRECTORY_SEPARATOR !== '\\') { - return false; - } - - if ($path[0] === '\\') { - return true; - } - - if (\strlen($path) < 3) { - return false; - } - - if ($path[1] !== ':') { - return false; - } - - if ($path[2] !== '/' && $path[2] !== '\\') { - return false; - } - - if (!preg_match('/^[A-Za-z]$/', $path[0])) { - return false; - } - - return true; - } - - /** - * @param string $part1 - * @param string $part2 - * - * @return string - */ - public static function join($part1, $part2) - { - if ($part1 === '' || self::isAbsolute($part2)) { - return $part2; - } - - if ($part2 === '') { - return $part1; - } - - $last = $part1[\strlen($part1) - 1]; - $separator = \DIRECTORY_SEPARATOR; - - if ($last === '/' || $last === \DIRECTORY_SEPARATOR) { - $separator = ''; - } - - return $part1 . $separator . $part2; - } -} diff --git a/lib/scssphp/scssphp/src/ValueConverter.php b/lib/scssphp/scssphp/src/ValueConverter.php deleted file mode 100644 index e12a0eb54..000000000 --- a/lib/scssphp/scssphp/src/ValueConverter.php +++ /dev/null @@ -1,95 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp; - -use ScssPhp\ScssPhp\Node\Number; - -final class ValueConverter -{ - // Prevent instantiating it - private function __construct() - { - } - - /** - * Parses a value from a Scss source string. - * - * The returned value is guaranteed to be supported by the - * Compiler methods for registering custom variables. No other - * guarantee about it is provided. It should be considered - * opaque values by the caller. - * - * @param string $source - * - * @return mixed - */ - public static function parseValue($source) - { - $parser = new Parser(__CLASS__); - - if (!$parser->parseValue($source, $value)) { - throw new \InvalidArgumentException(sprintf('Invalid value source "%s".', $source)); - } - - return $value; - } - - /** - * Converts a PHP value to a Sass value - * - * The returned value is guaranteed to be supported by the - * Compiler methods for registering custom variables. No other - * guarantee about it is provided. It should be considered - * opaque values by the caller. - * - * @param mixed $value - * - * @return mixed - */ - public static function fromPhp($value) - { - if ($value instanceof Number) { - return $value; - } - - if (is_array($value) && isset($value[0]) && \in_array($value[0], [Type::T_NULL, Type::T_COLOR, Type::T_KEYWORD, Type::T_LIST, Type::T_MAP, Type::T_STRING])) { - return $value; - } - - if ($value === null) { - return Compiler::$null; - } - - if ($value === true) { - return Compiler::$true; - } - - if ($value === false) { - return Compiler::$false; - } - - if ($value === '') { - return Compiler::$emptyString; - } - - if (\is_int($value) || \is_float($value)) { - return new Number($value, ''); - } - - if (\is_string($value)) { - return [Type::T_STRING, '"', [$value]]; - } - - throw new \InvalidArgumentException(sprintf('Cannot convert the value of type "%s" to a Sass value.', gettype($value))); - } -} diff --git a/lib/scssphp/scssphp/src/Version.php b/lib/scssphp/scssphp/src/Version.php deleted file mode 100644 index 5848a0ed0..000000000 --- a/lib/scssphp/scssphp/src/Version.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp; - -/** - * SCSSPHP version - * - * @author Leaf Corcoran <leafot@gmail.com> - */ -class Version -{ - const VERSION = '1.10.5'; -} diff --git a/lib/scssphp/scssphp/src/Warn.php b/lib/scssphp/scssphp/src/Warn.php deleted file mode 100644 index 592b44c70..000000000 --- a/lib/scssphp/scssphp/src/Warn.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php - -/** - * SCSSPHP - * - * @copyright 2012-2020 Leaf Corcoran - * - * @license http://opensource.org/licenses/MIT MIT - * - * @link http://scssphp.github.io/scssphp - */ - -namespace ScssPhp\ScssPhp; - -final class Warn -{ - /** - * @var callable|null - * @phpstan-var (callable(string, bool): void)|null - */ - private static $callback; - - /** - * Prints a warning message associated with the current `@import` or function call. - * - * This may only be called within a custom function or importer callback. - * - * @param string $message - * - * @return void - */ - public static function warning($message) - { - self::reportWarning($message, false); - } - - /** - * Prints a deprecation warning message associated with the current `@import` or function call. - * - * This may only be called within a custom function or importer callback. - * - * @param string $message - * - * @return void - */ - public static function deprecation($message) - { - self::reportWarning($message, true); - } - - /** - * @param callable|null $callback - * - * @return callable|null The previous warn callback - * - * @phpstan-param (callable(string, bool): void)|null $callback - * - * @phpstan-return (callable(string, bool): void)|null - * - * @internal - */ - public static function setCallback(callable $callback = null) - { - $previousCallback = self::$callback; - self::$callback = $callback; - - return $previousCallback; - } - - /** - * @param string $message - * @param bool $deprecation - * - * @return void - */ - private static function reportWarning($message, $deprecation) - { - if (self::$callback === null) { - throw new \BadMethodCallException('The warning Reporter may only be called within a custom function or importer callback.'); - } - - \call_user_func(self::$callback, $message, $deprecation); - } -} diff --git a/lib/symfony/cache-contracts/.gitignore b/lib/symfony/cache-contracts/.gitignore deleted file mode 100644 index c49a5d8df..000000000 --- a/lib/symfony/cache-contracts/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -vendor/ -composer.lock -phpunit.xml diff --git a/lib/symfony/cache-contracts/CHANGELOG.md b/lib/symfony/cache-contracts/CHANGELOG.md deleted file mode 100644 index 7932e2613..000000000 --- a/lib/symfony/cache-contracts/CHANGELOG.md +++ /dev/null @@ -1,5 +0,0 @@ -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/lib/symfony/cache-contracts/CacheInterface.php b/lib/symfony/cache-contracts/CacheInterface.php deleted file mode 100644 index 67e4dfd3a..000000000 --- a/lib/symfony/cache-contracts/CacheInterface.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Cache; - -use Psr\Cache\CacheItemInterface; -use Psr\Cache\InvalidArgumentException; - -/** - * Covers most simple to advanced caching needs. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -interface CacheInterface -{ - /** - * Fetches a value from the pool or computes it if not found. - * - * On cache misses, a callback is called that should return the missing value. - * This callback is given a PSR-6 CacheItemInterface instance corresponding to the - * requested key, that could be used e.g. for expiration control. It could also - * be an ItemInterface instance when its additional features are needed. - * - * @param string $key The key of the item to retrieve from the cache - * @param callable|CallbackInterface $callback Should return the computed value for the given key/item - * @param float|null $beta A float that, as it grows, controls the likeliness of triggering - * early expiration. 0 disables it, INF forces immediate expiration. - * The default (or providing null) is implementation dependent but should - * typically be 1.0, which should provide optimal stampede protection. - * See https://en.wikipedia.org/wiki/Cache_stampede#Probabilistic_early_expiration - * @param array &$metadata The metadata of the cached item {@see ItemInterface::getMetadata()} - * - * @return mixed - * - * @throws InvalidArgumentException When $key is not valid or when $beta is negative - */ - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null); - - /** - * Removes an item from the pool. - * - * @param string $key The key to delete - * - * @throws InvalidArgumentException When $key is not valid - * - * @return bool True if the item was successfully removed, false if there was any error - */ - public function delete(string $key): bool; -} diff --git a/lib/symfony/cache-contracts/CacheTrait.php b/lib/symfony/cache-contracts/CacheTrait.php deleted file mode 100644 index d340e0696..000000000 --- a/lib/symfony/cache-contracts/CacheTrait.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Cache; - -use Psr\Cache\CacheItemPoolInterface; -use Psr\Cache\InvalidArgumentException; -use Psr\Log\LoggerInterface; - -// Help opcache.preload discover always-needed symbols -class_exists(InvalidArgumentException::class); - -/** - * An implementation of CacheInterface for PSR-6 CacheItemPoolInterface classes. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -trait CacheTrait -{ - /** - * {@inheritdoc} - * - * @return mixed - */ - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) - { - return $this->doGet($this, $key, $callback, $beta, $metadata); - } - - /** - * {@inheritdoc} - */ - public function delete(string $key): bool - { - return $this->deleteItem($key); - } - - private function doGet(CacheItemPoolInterface $pool, string $key, callable $callback, ?float $beta, array &$metadata = null, LoggerInterface $logger = null) - { - if (0 > $beta = $beta ?? 1.0) { - throw new class(sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', static::class, $beta)) extends \InvalidArgumentException implements InvalidArgumentException { }; - } - - $item = $pool->getItem($key); - $recompute = !$item->isHit() || \INF === $beta; - $metadata = $item instanceof ItemInterface ? $item->getMetadata() : []; - - if (!$recompute && $metadata) { - $expiry = $metadata[ItemInterface::METADATA_EXPIRY] ?? false; - $ctime = $metadata[ItemInterface::METADATA_CTIME] ?? false; - - if ($recompute = $ctime && $expiry && $expiry <= ($now = microtime(true)) - $ctime / 1000 * $beta * log(random_int(1, \PHP_INT_MAX) / \PHP_INT_MAX)) { - // force applying defaultLifetime to expiry - $item->expiresAt(null); - $logger && $logger->info('Item "{key}" elected for early recomputation {delta}s before its expiration', [ - 'key' => $key, - 'delta' => sprintf('%.1f', $expiry - $now), - ]); - } - } - - if ($recompute) { - $save = true; - $item->set($callback($item, $save)); - if ($save) { - $pool->save($item); - } - } - - return $item->get(); - } -} diff --git a/lib/symfony/cache-contracts/CallbackInterface.php b/lib/symfony/cache-contracts/CallbackInterface.php deleted file mode 100644 index 7dae2aac3..000000000 --- a/lib/symfony/cache-contracts/CallbackInterface.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Cache; - -use Psr\Cache\CacheItemInterface; - -/** - * Computes and returns the cached value of an item. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -interface CallbackInterface -{ - /** - * @param CacheItemInterface|ItemInterface $item The item to compute the value for - * @param bool &$save Should be set to false when the value should not be saved in the pool - * - * @return mixed The computed value for the passed item - */ - public function __invoke(CacheItemInterface $item, bool &$save); -} diff --git a/lib/symfony/cache-contracts/ItemInterface.php b/lib/symfony/cache-contracts/ItemInterface.php deleted file mode 100644 index 10c048897..000000000 --- a/lib/symfony/cache-contracts/ItemInterface.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Cache; - -use Psr\Cache\CacheException; -use Psr\Cache\CacheItemInterface; -use Psr\Cache\InvalidArgumentException; - -/** - * Augments PSR-6's CacheItemInterface with support for tags and metadata. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -interface ItemInterface extends CacheItemInterface -{ - /** - * References the Unix timestamp stating when the item will expire. - */ - public const METADATA_EXPIRY = 'expiry'; - - /** - * References the time the item took to be created, in milliseconds. - */ - public const METADATA_CTIME = 'ctime'; - - /** - * References the list of tags that were assigned to the item, as string[]. - */ - public const METADATA_TAGS = 'tags'; - - /** - * Reserved characters that cannot be used in a key or tag. - */ - public const RESERVED_CHARACTERS = '{}()/\@:'; - - /** - * Adds a tag to a cache item. - * - * Tags are strings that follow the same validation rules as keys. - * - * @param string|string[] $tags A tag or array of tags - * - * @return $this - * - * @throws InvalidArgumentException When $tag is not valid - * @throws CacheException When the item comes from a pool that is not tag-aware - */ - public function tag($tags): self; - - /** - * Returns a list of metadata info that were saved alongside with the cached value. - * - * See ItemInterface::METADATA_* consts for keys potentially found in the returned array. - */ - public function getMetadata(): array; -} diff --git a/lib/symfony/cache-contracts/LICENSE b/lib/symfony/cache-contracts/LICENSE deleted file mode 100644 index 74cdc2dbf..000000000 --- a/lib/symfony/cache-contracts/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -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/lib/symfony/cache-contracts/README.md b/lib/symfony/cache-contracts/README.md deleted file mode 100644 index 7085a6996..000000000 --- a/lib/symfony/cache-contracts/README.md +++ /dev/null @@ -1,9 +0,0 @@ -Symfony Cache 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/lib/symfony/cache-contracts/TagAwareCacheInterface.php b/lib/symfony/cache-contracts/TagAwareCacheInterface.php deleted file mode 100644 index 7c4cf1111..000000000 --- a/lib/symfony/cache-contracts/TagAwareCacheInterface.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Cache; - -use Psr\Cache\InvalidArgumentException; - -/** - * Allows invalidating cached items using tags. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -interface TagAwareCacheInterface extends CacheInterface -{ - /** - * Invalidates cached items using tags. - * - * When implemented on a PSR-6 pool, invalidation should not apply - * to deferred items. Instead, they should be committed as usual. - * This allows replacing old tagged values by new ones without - * race conditions. - * - * @param string[] $tags An array of tags to invalidate - * - * @return bool True on success - * - * @throws InvalidArgumentException When $tags is not valid - */ - public function invalidateTags(array $tags); -} diff --git a/lib/symfony/cache-contracts/composer.json b/lib/symfony/cache-contracts/composer.json deleted file mode 100644 index 9f45e1780..000000000 --- a/lib/symfony/cache-contracts/composer.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "symfony/cache-contracts", - "type": "library", - "description": "Generic abstractions related to caching", - "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "psr/cache": "^1.0|^2.0|^3.0" - }, - "suggest": { - "symfony/cache-implementation": "" - }, - "autoload": { - "psr-4": { "Symfony\\Contracts\\Cache\\": "" } - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - } -} diff --git a/lib/symfony/cache/Adapter/AbstractAdapter.php b/lib/symfony/cache/Adapter/AbstractAdapter.php deleted file mode 100644 index 3d0140922..000000000 --- a/lib/symfony/cache/Adapter/AbstractAdapter.php +++ /dev/null @@ -1,208 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Psr\Log\LoggerAwareInterface; -use Psr\Log\LoggerInterface; -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\ResettableInterface; -use Symfony\Component\Cache\Traits\AbstractAdapterTrait; -use Symfony\Component\Cache\Traits\ContractsTrait; -use Symfony\Contracts\Cache\CacheInterface; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -abstract class AbstractAdapter implements AdapterInterface, CacheInterface, LoggerAwareInterface, ResettableInterface -{ - use AbstractAdapterTrait; - use ContractsTrait; - - /** - * @internal - */ - protected const NS_SEPARATOR = ':'; - - private static $apcuSupported; - private static $phpFilesSupported; - - protected function __construct(string $namespace = '', int $defaultLifetime = 0) - { - $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).static::NS_SEPARATOR; - $this->defaultLifetime = $defaultLifetime; - if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength - 24) { - throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s").', $this->maxIdLength - 24, \strlen($namespace), $namespace)); - } - self::$createCacheItem ?? self::$createCacheItem = \Closure::bind( - static function ($key, $value, $isHit) { - $item = new CacheItem(); - $item->key = $key; - $item->value = $v = $value; - $item->isHit = $isHit; - // Detect wrapped values that encode for their expiry and creation duration - // For compactness, these values are packed in the key of an array using - // magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F - if (\is_array($v) && 1 === \count($v) && 10 === \strlen($k = (string) array_key_first($v)) && "\x9D" === $k[0] && "\0" === $k[5] && "\x5F" === $k[9]) { - $item->value = $v[$k]; - $v = unpack('Ve/Nc', substr($k, 1, -1)); - $item->metadata[CacheItem::METADATA_EXPIRY] = $v['e'] + CacheItem::METADATA_EXPIRY_OFFSET; - $item->metadata[CacheItem::METADATA_CTIME] = $v['c']; - } - - return $item; - }, - null, - CacheItem::class - ); - self::$mergeByLifetime ?? self::$mergeByLifetime = \Closure::bind( - static function ($deferred, $namespace, &$expiredIds, $getId, $defaultLifetime) { - $byLifetime = []; - $now = microtime(true); - $expiredIds = []; - - foreach ($deferred as $key => $item) { - $key = (string) $key; - if (null === $item->expiry) { - $ttl = 0 < $defaultLifetime ? $defaultLifetime : 0; - } elseif (!$item->expiry) { - $ttl = 0; - } elseif (0 >= $ttl = (int) (0.1 + $item->expiry - $now)) { - $expiredIds[] = $getId($key); - continue; - } - if (isset(($metadata = $item->newMetadata)[CacheItem::METADATA_TAGS])) { - unset($metadata[CacheItem::METADATA_TAGS]); - } - // For compactness, expiry and creation duration are packed in the key of an array, using magic numbers as separators - $byLifetime[$ttl][$getId($key)] = $metadata ? ["\x9D".pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME])."\x5F" => $item->value] : $item->value; - } - - return $byLifetime; - }, - null, - CacheItem::class - ); - } - - /** - * Returns the best possible adapter that your runtime supports. - * - * Using ApcuAdapter makes system caches compatible with read-only filesystems. - * - * @return AdapterInterface - */ - public static function createSystemCache(string $namespace, int $defaultLifetime, string $version, string $directory, LoggerInterface $logger = null) - { - $opcache = new PhpFilesAdapter($namespace, $defaultLifetime, $directory, true); - if (null !== $logger) { - $opcache->setLogger($logger); - } - - if (!self::$apcuSupported = self::$apcuSupported ?? ApcuAdapter::isSupported()) { - return $opcache; - } - - if (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && !filter_var(\ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) { - return $opcache; - } - - $apcu = new ApcuAdapter($namespace, intdiv($defaultLifetime, 5), $version); - if (null !== $logger) { - $apcu->setLogger($logger); - } - - return new ChainAdapter([$apcu, $opcache]); - } - - public static function createConnection(string $dsn, array $options = []) - { - if (str_starts_with($dsn, 'redis:') || str_starts_with($dsn, 'rediss:')) { - return RedisAdapter::createConnection($dsn, $options); - } - if (str_starts_with($dsn, 'memcached:')) { - return MemcachedAdapter::createConnection($dsn, $options); - } - if (0 === strpos($dsn, 'couchbase:')) { - if (CouchbaseBucketAdapter::isSupported()) { - return CouchbaseBucketAdapter::createConnection($dsn, $options); - } - - return CouchbaseCollectionAdapter::createConnection($dsn, $options); - } - - throw new InvalidArgumentException(sprintf('Unsupported DSN: "%s".', $dsn)); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function commit() - { - $ok = true; - $byLifetime = (self::$mergeByLifetime)($this->deferred, $this->namespace, $expiredIds, \Closure::fromCallable([$this, 'getId']), $this->defaultLifetime); - $retry = $this->deferred = []; - - if ($expiredIds) { - try { - $this->doDelete($expiredIds); - } catch (\Exception $e) { - $ok = false; - CacheItem::log($this->logger, 'Failed to delete expired items: '.$e->getMessage(), ['exception' => $e, 'cache-adapter' => get_debug_type($this)]); - } - } - foreach ($byLifetime as $lifetime => $values) { - try { - $e = $this->doSave($values, $lifetime); - } catch (\Exception $e) { - } - if (true === $e || [] === $e) { - continue; - } - if (\is_array($e) || 1 === \count($values)) { - foreach (\is_array($e) ? $e : array_keys($values) as $id) { - $ok = false; - $v = $values[$id]; - $type = get_debug_type($v); - $message = sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.'); - CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]); - } - } else { - foreach ($values as $id => $v) { - $retry[$lifetime][] = $id; - } - } - } - - // When bulk-save failed, retry each item individually - foreach ($retry as $lifetime => $ids) { - foreach ($ids as $id) { - try { - $v = $byLifetime[$lifetime][$id]; - $e = $this->doSave([$id => $v], $lifetime); - } catch (\Exception $e) { - } - if (true === $e || [] === $e) { - continue; - } - $ok = false; - $type = get_debug_type($v); - $message = sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.'); - CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]); - } - } - - return $ok; - } -} diff --git a/lib/symfony/cache/Adapter/AbstractTagAwareAdapter.php b/lib/symfony/cache/Adapter/AbstractTagAwareAdapter.php deleted file mode 100644 index a384b16ad..000000000 --- a/lib/symfony/cache/Adapter/AbstractTagAwareAdapter.php +++ /dev/null @@ -1,330 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Psr\Log\LoggerAwareInterface; -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\ResettableInterface; -use Symfony\Component\Cache\Traits\AbstractAdapterTrait; -use Symfony\Component\Cache\Traits\ContractsTrait; -use Symfony\Contracts\Cache\TagAwareCacheInterface; - -/** - * Abstract for native TagAware adapters. - * - * To keep info on tags, the tags are both serialized as part of cache value and provided as tag ids - * to Adapters on operations when needed for storage to doSave(), doDelete() & doInvalidate(). - * - * @author Nicolas Grekas <p@tchwork.com> - * @author André Rømcke <andre.romcke+symfony@gmail.com> - * - * @internal - */ -abstract class AbstractTagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface, LoggerAwareInterface, ResettableInterface -{ - use AbstractAdapterTrait; - use ContractsTrait; - - private const TAGS_PREFIX = "\0tags\0"; - - protected function __construct(string $namespace = '', int $defaultLifetime = 0) - { - $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).':'; - $this->defaultLifetime = $defaultLifetime; - if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength - 24) { - throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s").', $this->maxIdLength - 24, \strlen($namespace), $namespace)); - } - self::$createCacheItem ?? self::$createCacheItem = \Closure::bind( - static function ($key, $value, $isHit) { - $item = new CacheItem(); - $item->key = $key; - $item->isTaggable = true; - // If structure does not match what we expect return item as is (no value and not a hit) - if (!\is_array($value) || !\array_key_exists('value', $value)) { - return $item; - } - $item->isHit = $isHit; - // Extract value, tags and meta data from the cache value - $item->value = $value['value']; - $item->metadata[CacheItem::METADATA_TAGS] = $value['tags'] ?? []; - if (isset($value['meta'])) { - // For compactness these values are packed, & expiry is offset to reduce size - $v = unpack('Ve/Nc', $value['meta']); - $item->metadata[CacheItem::METADATA_EXPIRY] = $v['e'] + CacheItem::METADATA_EXPIRY_OFFSET; - $item->metadata[CacheItem::METADATA_CTIME] = $v['c']; - } - - return $item; - }, - null, - CacheItem::class - ); - self::$mergeByLifetime ?? self::$mergeByLifetime = \Closure::bind( - static function ($deferred, &$expiredIds, $getId, $tagPrefix, $defaultLifetime) { - $byLifetime = []; - $now = microtime(true); - $expiredIds = []; - - foreach ($deferred as $key => $item) { - $key = (string) $key; - if (null === $item->expiry) { - $ttl = 0 < $defaultLifetime ? $defaultLifetime : 0; - } elseif (!$item->expiry) { - $ttl = 0; - } elseif (0 >= $ttl = (int) (0.1 + $item->expiry - $now)) { - $expiredIds[] = $getId($key); - continue; - } - // Store Value and Tags on the cache value - if (isset(($metadata = $item->newMetadata)[CacheItem::METADATA_TAGS])) { - $value = ['value' => $item->value, 'tags' => $metadata[CacheItem::METADATA_TAGS]]; - unset($metadata[CacheItem::METADATA_TAGS]); - } else { - $value = ['value' => $item->value, 'tags' => []]; - } - - if ($metadata) { - // For compactness, expiry and creation duration are packed, using magic numbers as separators - $value['meta'] = pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME]); - } - - // Extract tag changes, these should be removed from values in doSave() - $value['tag-operations'] = ['add' => [], 'remove' => []]; - $oldTags = $item->metadata[CacheItem::METADATA_TAGS] ?? []; - foreach (array_diff($value['tags'], $oldTags) as $addedTag) { - $value['tag-operations']['add'][] = $getId($tagPrefix.$addedTag); - } - foreach (array_diff($oldTags, $value['tags']) as $removedTag) { - $value['tag-operations']['remove'][] = $getId($tagPrefix.$removedTag); - } - - $byLifetime[$ttl][$getId($key)] = $value; - $item->metadata = $item->newMetadata; - } - - return $byLifetime; - }, - null, - CacheItem::class - ); - } - - /** - * Persists several cache items immediately. - * - * @param array $values The values to cache, indexed by their cache identifier - * @param int $lifetime The lifetime of the cached values, 0 for persisting until manual cleaning - * @param array[] $addTagData Hash where key is tag id, and array value is list of cache id's to add to tag - * @param array[] $removeTagData Hash where key is tag id, and array value is list of cache id's to remove to tag - * - * @return array The identifiers that failed to be cached or a boolean stating if caching succeeded or not - */ - abstract protected function doSave(array $values, int $lifetime, array $addTagData = [], array $removeTagData = []): array; - - /** - * Removes multiple items from the pool and their corresponding tags. - * - * @param array $ids An array of identifiers that should be removed from the pool - * - * @return bool - */ - abstract protected function doDelete(array $ids); - - /** - * Removes relations between tags and deleted items. - * - * @param array $tagData Array of tag => key identifiers that should be removed from the pool - */ - abstract protected function doDeleteTagRelations(array $tagData): bool; - - /** - * Invalidates cached items using tags. - * - * @param string[] $tagIds An array of tags to invalidate, key is tag and value is tag id - */ - abstract protected function doInvalidate(array $tagIds): bool; - - /** - * Delete items and yields the tags they were bound to. - */ - protected function doDeleteYieldTags(array $ids): iterable - { - foreach ($this->doFetch($ids) as $id => $value) { - yield $id => \is_array($value) && \is_array($value['tags'] ?? null) ? $value['tags'] : []; - } - - $this->doDelete($ids); - } - - /** - * {@inheritdoc} - */ - public function commit(): bool - { - $ok = true; - $byLifetime = (self::$mergeByLifetime)($this->deferred, $expiredIds, \Closure::fromCallable([$this, 'getId']), self::TAGS_PREFIX, $this->defaultLifetime); - $retry = $this->deferred = []; - - if ($expiredIds) { - // Tags are not cleaned up in this case, however that is done on invalidateTags(). - try { - $this->doDelete($expiredIds); - } catch (\Exception $e) { - $ok = false; - CacheItem::log($this->logger, 'Failed to delete expired items: '.$e->getMessage(), ['exception' => $e, 'cache-adapter' => get_debug_type($this)]); - } - } - foreach ($byLifetime as $lifetime => $values) { - try { - $values = $this->extractTagData($values, $addTagData, $removeTagData); - $e = $this->doSave($values, $lifetime, $addTagData, $removeTagData); - } catch (\Exception $e) { - } - if (true === $e || [] === $e) { - continue; - } - if (\is_array($e) || 1 === \count($values)) { - foreach (\is_array($e) ? $e : array_keys($values) as $id) { - $ok = false; - $v = $values[$id]; - $type = get_debug_type($v); - $message = sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.'); - CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]); - } - } else { - foreach ($values as $id => $v) { - $retry[$lifetime][] = $id; - } - } - } - - // When bulk-save failed, retry each item individually - foreach ($retry as $lifetime => $ids) { - foreach ($ids as $id) { - try { - $v = $byLifetime[$lifetime][$id]; - $values = $this->extractTagData([$id => $v], $addTagData, $removeTagData); - $e = $this->doSave($values, $lifetime, $addTagData, $removeTagData); - } catch (\Exception $e) { - } - if (true === $e || [] === $e) { - continue; - } - $ok = false; - $type = get_debug_type($v); - $message = sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.'); - CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]); - } - } - - return $ok; - } - - /** - * {@inheritdoc} - */ - public function deleteItems(array $keys): bool - { - if (!$keys) { - return true; - } - - $ok = true; - $ids = []; - $tagData = []; - - foreach ($keys as $key) { - $ids[$key] = $this->getId($key); - unset($this->deferred[$key]); - } - - try { - foreach ($this->doDeleteYieldTags(array_values($ids)) as $id => $tags) { - foreach ($tags as $tag) { - $tagData[$this->getId(self::TAGS_PREFIX.$tag)][] = $id; - } - } - } catch (\Exception $e) { - $ok = false; - } - - try { - if ((!$tagData || $this->doDeleteTagRelations($tagData)) && $ok) { - return true; - } - } catch (\Exception $e) { - } - - // When bulk-delete failed, retry each item individually - foreach ($ids as $key => $id) { - try { - $e = null; - if ($this->doDelete([$id])) { - continue; - } - } catch (\Exception $e) { - } - $message = 'Failed to delete key "{key}"'.($e instanceof \Exception ? ': '.$e->getMessage() : '.'); - CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]); - $ok = false; - } - - return $ok; - } - - /** - * {@inheritdoc} - */ - public function invalidateTags(array $tags) - { - if (empty($tags)) { - return false; - } - - $tagIds = []; - foreach (array_unique($tags) as $tag) { - $tagIds[] = $this->getId(self::TAGS_PREFIX.$tag); - } - - try { - if ($this->doInvalidate($tagIds)) { - return true; - } - } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to invalidate tags: '.$e->getMessage(), ['exception' => $e, 'cache-adapter' => get_debug_type($this)]); - } - - return false; - } - - /** - * Extracts tags operation data from $values set in mergeByLifetime, and returns values without it. - */ - private function extractTagData(array $values, ?array &$addTagData, ?array &$removeTagData): array - { - $addTagData = $removeTagData = []; - foreach ($values as $id => $value) { - foreach ($value['tag-operations']['add'] as $tag => $tagId) { - $addTagData[$tagId][] = $id; - } - - foreach ($value['tag-operations']['remove'] as $tag => $tagId) { - $removeTagData[$tagId][] = $id; - } - - unset($values[$id]['tag-operations']); - } - - return $values; - } -} diff --git a/lib/symfony/cache/Adapter/AdapterInterface.php b/lib/symfony/cache/Adapter/AdapterInterface.php deleted file mode 100644 index f8dce866d..000000000 --- a/lib/symfony/cache/Adapter/AdapterInterface.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Cache\CacheItem; - -// Help opcache.preload discover always-needed symbols -class_exists(CacheItem::class); - -/** - * Interface for adapters managing instances of Symfony's CacheItem. - * - * @author Kévin Dunglas <dunglas@gmail.com> - */ -interface AdapterInterface extends CacheItemPoolInterface -{ - /** - * {@inheritdoc} - * - * @return CacheItem - */ - public function getItem($key); - - /** - * {@inheritdoc} - * - * @return \Traversable<string, CacheItem> - */ - public function getItems(array $keys = []); - - /** - * {@inheritdoc} - * - * @return bool - */ - public function clear(string $prefix = ''); -} diff --git a/lib/symfony/cache/Adapter/ApcuAdapter.php b/lib/symfony/cache/Adapter/ApcuAdapter.php deleted file mode 100644 index 270a139e8..000000000 --- a/lib/symfony/cache/Adapter/ApcuAdapter.php +++ /dev/null @@ -1,138 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\Cache\Exception\CacheException; -use Symfony\Component\Cache\Marshaller\MarshallerInterface; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class ApcuAdapter extends AbstractAdapter -{ - private $marshaller; - - /** - * @throws CacheException if APCu is not enabled - */ - public function __construct(string $namespace = '', int $defaultLifetime = 0, string $version = null, MarshallerInterface $marshaller = null) - { - if (!static::isSupported()) { - throw new CacheException('APCu is not enabled.'); - } - if ('cli' === \PHP_SAPI) { - ini_set('apc.use_request_time', 0); - } - parent::__construct($namespace, $defaultLifetime); - - if (null !== $version) { - CacheItem::validateKey($version); - - if (!apcu_exists($version.'@'.$namespace)) { - $this->doClear($namespace); - apcu_add($version.'@'.$namespace, null); - } - } - - $this->marshaller = $marshaller; - } - - public static function isSupported() - { - return \function_exists('apcu_fetch') && filter_var(\ini_get('apc.enabled'), \FILTER_VALIDATE_BOOLEAN); - } - - /** - * {@inheritdoc} - */ - protected function doFetch(array $ids) - { - $unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback'); - try { - $values = []; - $ids = array_flip($ids); - foreach (apcu_fetch(array_keys($ids), $ok) ?: [] as $k => $v) { - if (!isset($ids[$k])) { - // work around https://github.com/krakjoe/apcu/issues/247 - $k = key($ids); - } - unset($ids[$k]); - - if (null !== $v || $ok) { - $values[$k] = null !== $this->marshaller ? $this->marshaller->unmarshall($v) : $v; - } - } - - return $values; - } catch (\Error $e) { - throw new \ErrorException($e->getMessage(), $e->getCode(), \E_ERROR, $e->getFile(), $e->getLine()); - } finally { - ini_set('unserialize_callback_func', $unserializeCallbackHandler); - } - } - - /** - * {@inheritdoc} - */ - protected function doHave(string $id) - { - return apcu_exists($id); - } - - /** - * {@inheritdoc} - */ - protected function doClear(string $namespace) - { - return isset($namespace[0]) && class_exists(\APCUIterator::class, false) && ('cli' !== \PHP_SAPI || filter_var(\ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) - ? apcu_delete(new \APCUIterator(sprintf('/^%s/', preg_quote($namespace, '/')), \APC_ITER_KEY)) - : apcu_clear_cache(); - } - - /** - * {@inheritdoc} - */ - protected function doDelete(array $ids) - { - foreach ($ids as $id) { - apcu_delete($id); - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doSave(array $values, int $lifetime) - { - if (null !== $this->marshaller && (!$values = $this->marshaller->marshall($values, $failed))) { - return $failed; - } - - try { - if (false === $failures = apcu_store($values, null, $lifetime)) { - $failures = $values; - } - - return array_keys($failures); - } catch (\Throwable $e) { - if (1 === \count($values)) { - // Workaround https://github.com/krakjoe/apcu/issues/170 - apcu_delete(array_key_first($values)); - } - - throw $e; - } - } -} diff --git a/lib/symfony/cache/Adapter/ArrayAdapter.php b/lib/symfony/cache/Adapter/ArrayAdapter.php deleted file mode 100644 index d8695b743..000000000 --- a/lib/symfony/cache/Adapter/ArrayAdapter.php +++ /dev/null @@ -1,407 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Psr\Cache\CacheItemInterface; -use Psr\Log\LoggerAwareInterface; -use Psr\Log\LoggerAwareTrait; -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\ResettableInterface; -use Symfony\Contracts\Cache\CacheInterface; - -/** - * An in-memory cache storage. - * - * Acts as a least-recently-used (LRU) storage when configured with a maximum number of items. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInterface, ResettableInterface -{ - use LoggerAwareTrait; - - private $storeSerialized; - private $values = []; - private $expiries = []; - private $defaultLifetime; - private $maxLifetime; - private $maxItems; - - private static $createCacheItem; - - /** - * @param bool $storeSerialized Disabling serialization can lead to cache corruptions when storing mutable values but increases performance otherwise - */ - public function __construct(int $defaultLifetime = 0, bool $storeSerialized = true, float $maxLifetime = 0, int $maxItems = 0) - { - if (0 > $maxLifetime) { - throw new InvalidArgumentException(sprintf('Argument $maxLifetime must be positive, %F passed.', $maxLifetime)); - } - - if (0 > $maxItems) { - throw new InvalidArgumentException(sprintf('Argument $maxItems must be a positive integer, %d passed.', $maxItems)); - } - - $this->defaultLifetime = $defaultLifetime; - $this->storeSerialized = $storeSerialized; - $this->maxLifetime = $maxLifetime; - $this->maxItems = $maxItems; - self::$createCacheItem ?? self::$createCacheItem = \Closure::bind( - static function ($key, $value, $isHit) { - $item = new CacheItem(); - $item->key = $key; - $item->value = $value; - $item->isHit = $isHit; - - return $item; - }, - null, - CacheItem::class - ); - } - - /** - * {@inheritdoc} - */ - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) - { - $item = $this->getItem($key); - $metadata = $item->getMetadata(); - - // ArrayAdapter works in memory, we don't care about stampede protection - if (\INF === $beta || !$item->isHit()) { - $save = true; - $item->set($callback($item, $save)); - if ($save) { - $this->save($item); - } - } - - return $item->get(); - } - - /** - * {@inheritdoc} - */ - public function delete(string $key): bool - { - return $this->deleteItem($key); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function hasItem($key) - { - if (\is_string($key) && isset($this->expiries[$key]) && $this->expiries[$key] > microtime(true)) { - if ($this->maxItems) { - // Move the item last in the storage - $value = $this->values[$key]; - unset($this->values[$key]); - $this->values[$key] = $value; - } - - return true; - } - \assert('' !== CacheItem::validateKey($key)); - - return isset($this->expiries[$key]) && !$this->deleteItem($key); - } - - /** - * {@inheritdoc} - */ - public function getItem($key) - { - if (!$isHit = $this->hasItem($key)) { - $value = null; - - if (!$this->maxItems) { - // Track misses in non-LRU mode only - $this->values[$key] = null; - } - } else { - $value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key]; - } - - return (self::$createCacheItem)($key, $value, $isHit); - } - - /** - * {@inheritdoc} - */ - public function getItems(array $keys = []) - { - \assert(self::validateKeys($keys)); - - return $this->generateItems($keys, microtime(true), self::$createCacheItem); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItem($key) - { - \assert('' !== CacheItem::validateKey($key)); - unset($this->values[$key], $this->expiries[$key]); - - return true; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItems(array $keys) - { - foreach ($keys as $key) { - $this->deleteItem($key); - } - - return true; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function save(CacheItemInterface $item) - { - if (!$item instanceof CacheItem) { - return false; - } - $item = (array) $item; - $key = $item["\0*\0key"]; - $value = $item["\0*\0value"]; - $expiry = $item["\0*\0expiry"]; - - $now = microtime(true); - - if (null !== $expiry) { - if (!$expiry) { - $expiry = \PHP_INT_MAX; - } elseif ($expiry <= $now) { - $this->deleteItem($key); - - return true; - } - } - if ($this->storeSerialized && null === $value = $this->freeze($value, $key)) { - return false; - } - if (null === $expiry && 0 < $this->defaultLifetime) { - $expiry = $this->defaultLifetime; - $expiry = $now + ($expiry > ($this->maxLifetime ?: $expiry) ? $this->maxLifetime : $expiry); - } elseif ($this->maxLifetime && (null === $expiry || $expiry > $now + $this->maxLifetime)) { - $expiry = $now + $this->maxLifetime; - } - - if ($this->maxItems) { - unset($this->values[$key]); - - // Iterate items and vacuum expired ones while we are at it - foreach ($this->values as $k => $v) { - if ($this->expiries[$k] > $now && \count($this->values) < $this->maxItems) { - break; - } - - unset($this->values[$k], $this->expiries[$k]); - } - } - - $this->values[$key] = $value; - $this->expiries[$key] = $expiry ?? \PHP_INT_MAX; - - return true; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function saveDeferred(CacheItemInterface $item) - { - return $this->save($item); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function commit() - { - return true; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function clear(string $prefix = '') - { - if ('' !== $prefix) { - $now = microtime(true); - - foreach ($this->values as $key => $value) { - if (!isset($this->expiries[$key]) || $this->expiries[$key] <= $now || 0 === strpos($key, $prefix)) { - unset($this->values[$key], $this->expiries[$key]); - } - } - - if ($this->values) { - return true; - } - } - - $this->values = $this->expiries = []; - - return true; - } - - /** - * Returns all cached values, with cache miss as null. - * - * @return array - */ - public function getValues() - { - if (!$this->storeSerialized) { - return $this->values; - } - - $values = $this->values; - foreach ($values as $k => $v) { - if (null === $v || 'N;' === $v) { - continue; - } - if (!\is_string($v) || !isset($v[2]) || ':' !== $v[1]) { - $values[$k] = serialize($v); - } - } - - return $values; - } - - /** - * {@inheritdoc} - */ - public function reset() - { - $this->clear(); - } - - private function generateItems(array $keys, float $now, \Closure $f): \Generator - { - foreach ($keys as $i => $key) { - if (!$isHit = isset($this->expiries[$key]) && ($this->expiries[$key] > $now || !$this->deleteItem($key))) { - $value = null; - - if (!$this->maxItems) { - // Track misses in non-LRU mode only - $this->values[$key] = null; - } - } else { - if ($this->maxItems) { - // Move the item last in the storage - $value = $this->values[$key]; - unset($this->values[$key]); - $this->values[$key] = $value; - } - - $value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key]; - } - unset($keys[$i]); - - yield $key => $f($key, $value, $isHit); - } - - foreach ($keys as $key) { - yield $key => $f($key, null, false); - } - } - - private function freeze($value, string $key) - { - if (null === $value) { - return 'N;'; - } - if (\is_string($value)) { - // Serialize strings if they could be confused with serialized objects or arrays - if ('N;' === $value || (isset($value[2]) && ':' === $value[1])) { - return serialize($value); - } - } elseif (!\is_scalar($value)) { - try { - $serialized = serialize($value); - } catch (\Exception $e) { - unset($this->values[$key]); - $type = get_debug_type($value); - $message = sprintf('Failed to save key "{key}" of type %s: %s', $type, $e->getMessage()); - CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]); - - return; - } - // Keep value serialized if it contains any objects or any internal references - if ('C' === $serialized[0] || 'O' === $serialized[0] || preg_match('/;[OCRr]:[1-9]/', $serialized)) { - return $serialized; - } - } - - return $value; - } - - private function unfreeze(string $key, bool &$isHit) - { - if ('N;' === $value = $this->values[$key]) { - return null; - } - if (\is_string($value) && isset($value[2]) && ':' === $value[1]) { - try { - $value = unserialize($value); - } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to unserialize key "{key}": '.$e->getMessage(), ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]); - $value = false; - } - if (false === $value) { - $value = null; - $isHit = false; - - if (!$this->maxItems) { - $this->values[$key] = null; - } - } - } - - return $value; - } - - private function validateKeys(array $keys): bool - { - foreach ($keys as $key) { - if (!\is_string($key) || !isset($this->expiries[$key])) { - CacheItem::validateKey($key); - } - } - - return true; - } -} diff --git a/lib/symfony/cache/Adapter/ChainAdapter.php b/lib/symfony/cache/Adapter/ChainAdapter.php deleted file mode 100644 index 059c0ed27..000000000 --- a/lib/symfony/cache/Adapter/ChainAdapter.php +++ /dev/null @@ -1,342 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Psr\Cache\CacheItemInterface; -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\ResettableInterface; -use Symfony\Component\Cache\Traits\ContractsTrait; -use Symfony\Contracts\Cache\CacheInterface; -use Symfony\Contracts\Service\ResetInterface; - -/** - * Chains several adapters together. - * - * Cached items are fetched from the first adapter having them in its data store. - * They are saved and deleted in all adapters at once. - * - * @author Kévin Dunglas <dunglas@gmail.com> - */ -class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface -{ - use ContractsTrait; - - private $adapters = []; - private $adapterCount; - private $defaultLifetime; - - private static $syncItem; - - /** - * @param CacheItemPoolInterface[] $adapters The ordered list of adapters used to fetch cached items - * @param int $defaultLifetime The default lifetime of items propagated from lower adapters to upper ones - */ - public function __construct(array $adapters, int $defaultLifetime = 0) - { - if (!$adapters) { - throw new InvalidArgumentException('At least one adapter must be specified.'); - } - - foreach ($adapters as $adapter) { - if (!$adapter instanceof CacheItemPoolInterface) { - throw new InvalidArgumentException(sprintf('The class "%s" does not implement the "%s" interface.', get_debug_type($adapter), CacheItemPoolInterface::class)); - } - if (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && $adapter instanceof ApcuAdapter && !filter_var(\ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) { - continue; // skip putting APCu in the chain when the backend is disabled - } - - if ($adapter instanceof AdapterInterface) { - $this->adapters[] = $adapter; - } else { - $this->adapters[] = new ProxyAdapter($adapter); - } - } - $this->adapterCount = \count($this->adapters); - $this->defaultLifetime = $defaultLifetime; - - self::$syncItem ?? self::$syncItem = \Closure::bind( - static function ($sourceItem, $item, $defaultLifetime, $sourceMetadata = null) { - $sourceItem->isTaggable = false; - $sourceMetadata = $sourceMetadata ?? $sourceItem->metadata; - unset($sourceMetadata[CacheItem::METADATA_TAGS]); - - $item->value = $sourceItem->value; - $item->isHit = $sourceItem->isHit; - $item->metadata = $item->newMetadata = $sourceItem->metadata = $sourceMetadata; - - if (isset($item->metadata[CacheItem::METADATA_EXPIRY])) { - $item->expiresAt(\DateTime::createFromFormat('U.u', sprintf('%.6F', $item->metadata[CacheItem::METADATA_EXPIRY]))); - } elseif (0 < $defaultLifetime) { - $item->expiresAfter($defaultLifetime); - } - - return $item; - }, - null, - CacheItem::class - ); - } - - /** - * {@inheritdoc} - */ - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) - { - $doSave = true; - $callback = static function (CacheItem $item, bool &$save) use ($callback, &$doSave) { - $value = $callback($item, $save); - $doSave = $save; - - return $value; - }; - - $lastItem = null; - $i = 0; - $wrap = function (CacheItem $item = null, bool &$save = true) use ($key, $callback, $beta, &$wrap, &$i, &$doSave, &$lastItem, &$metadata) { - $adapter = $this->adapters[$i]; - if (isset($this->adapters[++$i])) { - $callback = $wrap; - $beta = \INF === $beta ? \INF : 0; - } - if ($adapter instanceof CacheInterface) { - $value = $adapter->get($key, $callback, $beta, $metadata); - } else { - $value = $this->doGet($adapter, $key, $callback, $beta, $metadata); - } - if (null !== $item) { - (self::$syncItem)($lastItem = $lastItem ?? $item, $item, $this->defaultLifetime, $metadata); - } - $save = $doSave; - - return $value; - }; - - return $wrap(); - } - - /** - * {@inheritdoc} - */ - public function getItem($key) - { - $syncItem = self::$syncItem; - $misses = []; - - foreach ($this->adapters as $i => $adapter) { - $item = $adapter->getItem($key); - - if ($item->isHit()) { - while (0 <= --$i) { - $this->adapters[$i]->save($syncItem($item, $misses[$i], $this->defaultLifetime)); - } - - return $item; - } - - $misses[$i] = $item; - } - - return $item; - } - - /** - * {@inheritdoc} - */ - public function getItems(array $keys = []) - { - return $this->generateItems($this->adapters[0]->getItems($keys), 0); - } - - private function generateItems(iterable $items, int $adapterIndex): \Generator - { - $missing = []; - $misses = []; - $nextAdapterIndex = $adapterIndex + 1; - $nextAdapter = $this->adapters[$nextAdapterIndex] ?? null; - - foreach ($items as $k => $item) { - if (!$nextAdapter || $item->isHit()) { - yield $k => $item; - } else { - $missing[] = $k; - $misses[$k] = $item; - } - } - - if ($missing) { - $syncItem = self::$syncItem; - $adapter = $this->adapters[$adapterIndex]; - $items = $this->generateItems($nextAdapter->getItems($missing), $nextAdapterIndex); - - foreach ($items as $k => $item) { - if ($item->isHit()) { - $adapter->save($syncItem($item, $misses[$k], $this->defaultLifetime)); - } - - yield $k => $item; - } - } - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function hasItem($key) - { - foreach ($this->adapters as $adapter) { - if ($adapter->hasItem($key)) { - return true; - } - } - - return false; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function clear(string $prefix = '') - { - $cleared = true; - $i = $this->adapterCount; - - while ($i--) { - if ($this->adapters[$i] instanceof AdapterInterface) { - $cleared = $this->adapters[$i]->clear($prefix) && $cleared; - } else { - $cleared = $this->adapters[$i]->clear() && $cleared; - } - } - - return $cleared; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItem($key) - { - $deleted = true; - $i = $this->adapterCount; - - while ($i--) { - $deleted = $this->adapters[$i]->deleteItem($key) && $deleted; - } - - return $deleted; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItems(array $keys) - { - $deleted = true; - $i = $this->adapterCount; - - while ($i--) { - $deleted = $this->adapters[$i]->deleteItems($keys) && $deleted; - } - - return $deleted; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function save(CacheItemInterface $item) - { - $saved = true; - $i = $this->adapterCount; - - while ($i--) { - $saved = $this->adapters[$i]->save($item) && $saved; - } - - return $saved; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function saveDeferred(CacheItemInterface $item) - { - $saved = true; - $i = $this->adapterCount; - - while ($i--) { - $saved = $this->adapters[$i]->saveDeferred($item) && $saved; - } - - return $saved; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function commit() - { - $committed = true; - $i = $this->adapterCount; - - while ($i--) { - $committed = $this->adapters[$i]->commit() && $committed; - } - - return $committed; - } - - /** - * {@inheritdoc} - */ - public function prune() - { - $pruned = true; - - foreach ($this->adapters as $adapter) { - if ($adapter instanceof PruneableInterface) { - $pruned = $adapter->prune() && $pruned; - } - } - - return $pruned; - } - - /** - * {@inheritdoc} - */ - public function reset() - { - foreach ($this->adapters as $adapter) { - if ($adapter instanceof ResetInterface) { - $adapter->reset(); - } - } - } -} diff --git a/lib/symfony/cache/Adapter/CouchbaseBucketAdapter.php b/lib/symfony/cache/Adapter/CouchbaseBucketAdapter.php deleted file mode 100644 index 36d5249b4..000000000 --- a/lib/symfony/cache/Adapter/CouchbaseBucketAdapter.php +++ /dev/null @@ -1,252 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Symfony\Component\Cache\Exception\CacheException; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\Marshaller\DefaultMarshaller; -use Symfony\Component\Cache\Marshaller\MarshallerInterface; - -/** - * @author Antonio Jose Cerezo Aranda <aj.cerezo@gmail.com> - */ -class CouchbaseBucketAdapter extends AbstractAdapter -{ - private const THIRTY_DAYS_IN_SECONDS = 2592000; - private const MAX_KEY_LENGTH = 250; - private const KEY_NOT_FOUND = 13; - private const VALID_DSN_OPTIONS = [ - 'operationTimeout', - 'configTimeout', - 'configNodeTimeout', - 'n1qlTimeout', - 'httpTimeout', - 'configDelay', - 'htconfigIdleTimeout', - 'durabilityInterval', - 'durabilityTimeout', - ]; - - private $bucket; - private $marshaller; - - public function __construct(\CouchbaseBucket $bucket, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) - { - if (!static::isSupported()) { - throw new CacheException('Couchbase >= 2.6.0 < 3.0.0 is required.'); - } - - $this->maxIdLength = static::MAX_KEY_LENGTH; - - $this->bucket = $bucket; - - parent::__construct($namespace, $defaultLifetime); - $this->enableVersioning(); - $this->marshaller = $marshaller ?? new DefaultMarshaller(); - } - - /** - * @param array|string $servers - */ - public static function createConnection($servers, array $options = []): \CouchbaseBucket - { - if (\is_string($servers)) { - $servers = [$servers]; - } elseif (!\is_array($servers)) { - throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be array or string, "%s" given.', __METHOD__, get_debug_type($servers))); - } - - if (!static::isSupported()) { - throw new CacheException('Couchbase >= 2.6.0 < 3.0.0 is required.'); - } - - set_error_handler(function ($type, $msg, $file, $line) { throw new \ErrorException($msg, 0, $type, $file, $line); }); - - $dsnPattern = '/^(?<protocol>couchbase(?:s)?)\:\/\/(?:(?<username>[^\:]+)\:(?<password>[^\@]{6,})@)?' - .'(?<host>[^\:]+(?:\:\d+)?)(?:\/(?<bucketName>[^\?]+))(?:\?(?<options>.*))?$/i'; - - $newServers = []; - $protocol = 'couchbase'; - try { - $options = self::initOptions($options); - $username = $options['username']; - $password = $options['password']; - - foreach ($servers as $dsn) { - if (0 !== strpos($dsn, 'couchbase:')) { - throw new InvalidArgumentException(sprintf('Invalid Couchbase DSN: "%s" does not start with "couchbase:".', $dsn)); - } - - preg_match($dsnPattern, $dsn, $matches); - - $username = $matches['username'] ?: $username; - $password = $matches['password'] ?: $password; - $protocol = $matches['protocol'] ?: $protocol; - - if (isset($matches['options'])) { - $optionsInDsn = self::getOptions($matches['options']); - - foreach ($optionsInDsn as $parameter => $value) { - $options[$parameter] = $value; - } - } - - $newServers[] = $matches['host']; - } - - $connectionString = $protocol.'://'.implode(',', $newServers); - - $client = new \CouchbaseCluster($connectionString); - $client->authenticateAs($username, $password); - - $bucket = $client->openBucket($matches['bucketName']); - - unset($options['username'], $options['password']); - foreach ($options as $option => $value) { - if (!empty($value)) { - $bucket->$option = $value; - } - } - - return $bucket; - } finally { - restore_error_handler(); - } - } - - public static function isSupported(): bool - { - return \extension_loaded('couchbase') && version_compare(phpversion('couchbase'), '2.6.0', '>=') && version_compare(phpversion('couchbase'), '3.0', '<'); - } - - private static function getOptions(string $options): array - { - $results = []; - $optionsInArray = explode('&', $options); - - foreach ($optionsInArray as $option) { - [$key, $value] = explode('=', $option); - - if (\in_array($key, static::VALID_DSN_OPTIONS, true)) { - $results[$key] = $value; - } - } - - return $results; - } - - private static function initOptions(array $options): array - { - $options['username'] = $options['username'] ?? ''; - $options['password'] = $options['password'] ?? ''; - $options['operationTimeout'] = $options['operationTimeout'] ?? 0; - $options['configTimeout'] = $options['configTimeout'] ?? 0; - $options['configNodeTimeout'] = $options['configNodeTimeout'] ?? 0; - $options['n1qlTimeout'] = $options['n1qlTimeout'] ?? 0; - $options['httpTimeout'] = $options['httpTimeout'] ?? 0; - $options['configDelay'] = $options['configDelay'] ?? 0; - $options['htconfigIdleTimeout'] = $options['htconfigIdleTimeout'] ?? 0; - $options['durabilityInterval'] = $options['durabilityInterval'] ?? 0; - $options['durabilityTimeout'] = $options['durabilityTimeout'] ?? 0; - - return $options; - } - - /** - * {@inheritdoc} - */ - protected function doFetch(array $ids) - { - $resultsCouchbase = $this->bucket->get($ids); - - $results = []; - foreach ($resultsCouchbase as $key => $value) { - if (null !== $value->error) { - continue; - } - $results[$key] = $this->marshaller->unmarshall($value->value); - } - - return $results; - } - - /** - * {@inheritdoc} - */ - protected function doHave(string $id): bool - { - return false !== $this->bucket->get($id); - } - - /** - * {@inheritdoc} - */ - protected function doClear(string $namespace): bool - { - if ('' === $namespace) { - $this->bucket->manager()->flush(); - - return true; - } - - return false; - } - - /** - * {@inheritdoc} - */ - protected function doDelete(array $ids): bool - { - $results = $this->bucket->remove(array_values($ids)); - - foreach ($results as $key => $result) { - if (null !== $result->error && static::KEY_NOT_FOUND !== $result->error->getCode()) { - continue; - } - unset($results[$key]); - } - - return 0 === \count($results); - } - - /** - * {@inheritdoc} - */ - protected function doSave(array $values, int $lifetime) - { - if (!$values = $this->marshaller->marshall($values, $failed)) { - return $failed; - } - - $lifetime = $this->normalizeExpiry($lifetime); - - $ko = []; - foreach ($values as $key => $value) { - $result = $this->bucket->upsert($key, $value, ['expiry' => $lifetime]); - - if (null !== $result->error) { - $ko[$key] = $result; - } - } - - return [] === $ko ? true : $ko; - } - - private function normalizeExpiry(int $expiry): int - { - if ($expiry && $expiry > static::THIRTY_DAYS_IN_SECONDS) { - $expiry += time(); - } - - return $expiry; - } -} diff --git a/lib/symfony/cache/Adapter/CouchbaseCollectionAdapter.php b/lib/symfony/cache/Adapter/CouchbaseCollectionAdapter.php deleted file mode 100644 index 79f648531..000000000 --- a/lib/symfony/cache/Adapter/CouchbaseCollectionAdapter.php +++ /dev/null @@ -1,222 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Couchbase\Bucket; -use Couchbase\Cluster; -use Couchbase\ClusterOptions; -use Couchbase\Collection; -use Couchbase\DocumentNotFoundException; -use Couchbase\UpsertOptions; -use Symfony\Component\Cache\Exception\CacheException; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\Marshaller\DefaultMarshaller; -use Symfony\Component\Cache\Marshaller\MarshallerInterface; - -/** - * @author Antonio Jose Cerezo Aranda <aj.cerezo@gmail.com> - */ -class CouchbaseCollectionAdapter extends AbstractAdapter -{ - private const MAX_KEY_LENGTH = 250; - - /** @var Collection */ - private $connection; - private $marshaller; - - public function __construct(Collection $connection, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) - { - if (!static::isSupported()) { - throw new CacheException('Couchbase >= 3.0.0 < 4.0.0 is required.'); - } - - $this->maxIdLength = static::MAX_KEY_LENGTH; - - $this->connection = $connection; - - parent::__construct($namespace, $defaultLifetime); - $this->enableVersioning(); - $this->marshaller = $marshaller ?? new DefaultMarshaller(); - } - - /** - * @param array|string $dsn - * - * @return Bucket|Collection - */ - public static function createConnection($dsn, array $options = []) - { - if (\is_string($dsn)) { - $dsn = [$dsn]; - } elseif (!\is_array($dsn)) { - throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be array or string, "%s" given.', __METHOD__, get_debug_type($dsn))); - } - - if (!static::isSupported()) { - throw new CacheException('Couchbase >= 3.0.0 < 4.0.0 is required.'); - } - - set_error_handler(function ($type, $msg, $file, $line): bool { throw new \ErrorException($msg, 0, $type, $file, $line); }); - - $dsnPattern = '/^(?<protocol>couchbase(?:s)?)\:\/\/(?:(?<username>[^\:]+)\:(?<password>[^\@]{6,})@)?' - .'(?<host>[^\:]+(?:\:\d+)?)(?:\/(?<bucketName>[^\/\?]+))(?:(?:\/(?<scopeName>[^\/]+))' - .'(?:\/(?<collectionName>[^\/\?]+)))?(?:\/)?(?:\?(?<options>.*))?$/i'; - - $newServers = []; - $protocol = 'couchbase'; - try { - $username = $options['username'] ?? ''; - $password = $options['password'] ?? ''; - - foreach ($dsn as $server) { - if (0 !== strpos($server, 'couchbase:')) { - throw new InvalidArgumentException(sprintf('Invalid Couchbase DSN: "%s" does not start with "couchbase:".', $server)); - } - - preg_match($dsnPattern, $server, $matches); - - $username = $matches['username'] ?: $username; - $password = $matches['password'] ?: $password; - $protocol = $matches['protocol'] ?: $protocol; - - if (isset($matches['options'])) { - $optionsInDsn = self::getOptions($matches['options']); - - foreach ($optionsInDsn as $parameter => $value) { - $options[$parameter] = $value; - } - } - - $newServers[] = $matches['host']; - } - - $option = isset($matches['options']) ? '?'.$matches['options'] : ''; - $connectionString = $protocol.'://'.implode(',', $newServers).$option; - - $clusterOptions = new ClusterOptions(); - $clusterOptions->credentials($username, $password); - - $client = new Cluster($connectionString, $clusterOptions); - - $bucket = $client->bucket($matches['bucketName']); - $collection = $bucket->defaultCollection(); - if (!empty($matches['scopeName'])) { - $scope = $bucket->scope($matches['scopeName']); - $collection = $scope->collection($matches['collectionName']); - } - - return $collection; - } finally { - restore_error_handler(); - } - } - - public static function isSupported(): bool - { - return \extension_loaded('couchbase') && version_compare(phpversion('couchbase'), '3.0.5', '>=') && version_compare(phpversion('couchbase'), '4.0', '<'); - } - - private static function getOptions(string $options): array - { - $results = []; - $optionsInArray = explode('&', $options); - - foreach ($optionsInArray as $option) { - [$key, $value] = explode('=', $option); - - $results[$key] = $value; - } - - return $results; - } - - /** - * {@inheritdoc} - */ - protected function doFetch(array $ids): array - { - $results = []; - foreach ($ids as $id) { - try { - $resultCouchbase = $this->connection->get($id); - } catch (DocumentNotFoundException $exception) { - continue; - } - - $content = $resultCouchbase->value ?? $resultCouchbase->content(); - - $results[$id] = $this->marshaller->unmarshall($content); - } - - return $results; - } - - /** - * {@inheritdoc} - */ - protected function doHave($id): bool - { - return $this->connection->exists($id)->exists(); - } - - /** - * {@inheritdoc} - */ - protected function doClear($namespace): bool - { - return false; - } - - /** - * {@inheritdoc} - */ - protected function doDelete(array $ids): bool - { - $idsErrors = []; - foreach ($ids as $id) { - try { - $result = $this->connection->remove($id); - - if (null === $result->mutationToken()) { - $idsErrors[] = $id; - } - } catch (DocumentNotFoundException $exception) { - } - } - - return 0 === \count($idsErrors); - } - - /** - * {@inheritdoc} - */ - protected function doSave(array $values, $lifetime) - { - if (!$values = $this->marshaller->marshall($values, $failed)) { - return $failed; - } - - $upsertOptions = new UpsertOptions(); - $upsertOptions->expiry($lifetime); - - $ko = []; - foreach ($values as $key => $value) { - try { - $this->connection->upsert($key, $value, $upsertOptions); - } catch (\Exception $exception) { - $ko[$key] = ''; - } - } - - return [] === $ko ? true : $ko; - } -} diff --git a/lib/symfony/cache/Adapter/DoctrineAdapter.php b/lib/symfony/cache/Adapter/DoctrineAdapter.php deleted file mode 100644 index efa30c842..000000000 --- a/lib/symfony/cache/Adapter/DoctrineAdapter.php +++ /dev/null @@ -1,110 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Doctrine\Common\Cache\CacheProvider; -use Doctrine\Common\Cache\Psr6\CacheAdapter; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @deprecated Since Symfony 5.4, use Doctrine\Common\Cache\Psr6\CacheAdapter instead - */ -class DoctrineAdapter extends AbstractAdapter -{ - private $provider; - - public function __construct(CacheProvider $provider, string $namespace = '', int $defaultLifetime = 0) - { - trigger_deprecation('symfony/cache', '5.4', '"%s" is deprecated, use "%s" instead.', __CLASS__, CacheAdapter::class); - - parent::__construct('', $defaultLifetime); - $this->provider = $provider; - $provider->setNamespace($namespace); - } - - /** - * {@inheritdoc} - */ - public function reset() - { - parent::reset(); - $this->provider->setNamespace($this->provider->getNamespace()); - } - - /** - * {@inheritdoc} - */ - protected function doFetch(array $ids) - { - $unserializeCallbackHandler = ini_set('unserialize_callback_func', parent::class.'::handleUnserializeCallback'); - try { - return $this->provider->fetchMultiple($ids); - } catch (\Error $e) { - $trace = $e->getTrace(); - - if (isset($trace[0]['function']) && !isset($trace[0]['class'])) { - switch ($trace[0]['function']) { - case 'unserialize': - case 'apcu_fetch': - case 'apc_fetch': - throw new \ErrorException($e->getMessage(), $e->getCode(), \E_ERROR, $e->getFile(), $e->getLine()); - } - } - - throw $e; - } finally { - ini_set('unserialize_callback_func', $unserializeCallbackHandler); - } - } - - /** - * {@inheritdoc} - */ - protected function doHave(string $id) - { - return $this->provider->contains($id); - } - - /** - * {@inheritdoc} - */ - protected function doClear(string $namespace) - { - $namespace = $this->provider->getNamespace(); - - return isset($namespace[0]) - ? $this->provider->deleteAll() - : $this->provider->flushAll(); - } - - /** - * {@inheritdoc} - */ - protected function doDelete(array $ids) - { - $ok = true; - foreach ($ids as $id) { - $ok = $this->provider->delete($id) && $ok; - } - - return $ok; - } - - /** - * {@inheritdoc} - */ - protected function doSave(array $values, int $lifetime) - { - return $this->provider->saveMultiple($values, $lifetime); - } -} diff --git a/lib/symfony/cache/Adapter/DoctrineDbalAdapter.php b/lib/symfony/cache/Adapter/DoctrineDbalAdapter.php deleted file mode 100644 index 73f0ea6bc..000000000 --- a/lib/symfony/cache/Adapter/DoctrineDbalAdapter.php +++ /dev/null @@ -1,397 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Driver\ServerInfoAwareConnection; -use Doctrine\DBAL\DriverManager; -use Doctrine\DBAL\Exception as DBALException; -use Doctrine\DBAL\Exception\TableNotFoundException; -use Doctrine\DBAL\ParameterType; -use Doctrine\DBAL\Schema\Schema; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\Marshaller\DefaultMarshaller; -use Symfony\Component\Cache\Marshaller\MarshallerInterface; -use Symfony\Component\Cache\PruneableInterface; - -class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface -{ - protected $maxIdLength = 255; - - private $marshaller; - private $conn; - private $platformName; - private $serverVersion; - private $table = 'cache_items'; - private $idCol = 'item_id'; - private $dataCol = 'item_data'; - private $lifetimeCol = 'item_lifetime'; - private $timeCol = 'item_time'; - private $namespace; - - /** - * You can either pass an existing database Doctrine DBAL Connection or - * a DSN string that will be used to connect to the database. - * - * The cache table is created automatically when possible. - * Otherwise, use the createTable() method. - * - * List of available options: - * * db_table: The name of the table [default: cache_items] - * * db_id_col: The column where to store the cache id [default: item_id] - * * db_data_col: The column where to store the cache data [default: item_data] - * * db_lifetime_col: The column where to store the lifetime [default: item_lifetime] - * * db_time_col: The column where to store the timestamp [default: item_time] - * - * @param Connection|string $connOrDsn - * - * @throws InvalidArgumentException When namespace contains invalid characters - */ - public function __construct($connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], MarshallerInterface $marshaller = null) - { - if (isset($namespace[0]) && preg_match('#[^-+.A-Za-z0-9]#', $namespace, $match)) { - throw new InvalidArgumentException(sprintf('Namespace contains "%s" but only characters in [-+.A-Za-z0-9] are allowed.', $match[0])); - } - - if ($connOrDsn instanceof Connection) { - $this->conn = $connOrDsn; - } elseif (\is_string($connOrDsn)) { - if (!class_exists(DriverManager::class)) { - throw new InvalidArgumentException(sprintf('Failed to parse the DSN "%s". Try running "composer require doctrine/dbal".', $connOrDsn)); - } - $this->conn = DriverManager::getConnection(['url' => $connOrDsn]); - } else { - throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be "%s" or string, "%s" given.', __METHOD__, Connection::class, get_debug_type($connOrDsn))); - } - - $this->table = $options['db_table'] ?? $this->table; - $this->idCol = $options['db_id_col'] ?? $this->idCol; - $this->dataCol = $options['db_data_col'] ?? $this->dataCol; - $this->lifetimeCol = $options['db_lifetime_col'] ?? $this->lifetimeCol; - $this->timeCol = $options['db_time_col'] ?? $this->timeCol; - $this->namespace = $namespace; - $this->marshaller = $marshaller ?? new DefaultMarshaller(); - - parent::__construct($namespace, $defaultLifetime); - } - - /** - * Creates the table to store cache items which can be called once for setup. - * - * Cache ID are saved in a column of maximum length 255. Cache data is - * saved in a BLOB. - * - * @throws DBALException When the table already exists - */ - public function createTable() - { - $schema = new Schema(); - $this->addTableToSchema($schema); - - foreach ($schema->toSql($this->conn->getDatabasePlatform()) as $sql) { - $this->conn->executeStatement($sql); - } - } - - /** - * {@inheritdoc} - */ - public function configureSchema(Schema $schema, Connection $forConnection): void - { - // only update the schema for this connection - if ($forConnection !== $this->conn) { - return; - } - - if ($schema->hasTable($this->table)) { - return; - } - - $this->addTableToSchema($schema); - } - - /** - * {@inheritdoc} - */ - public function prune(): bool - { - $deleteSql = "DELETE FROM $this->table WHERE $this->lifetimeCol + $this->timeCol <= ?"; - $params = [time()]; - $paramTypes = [ParameterType::INTEGER]; - - if ('' !== $this->namespace) { - $deleteSql .= " AND $this->idCol LIKE ?"; - $params[] = sprintf('%s%%', $this->namespace); - $paramTypes[] = ParameterType::STRING; - } - - try { - $this->conn->executeStatement($deleteSql, $params, $paramTypes); - } catch (TableNotFoundException $e) { - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doFetch(array $ids): iterable - { - $now = time(); - $expired = []; - - $sql = "SELECT $this->idCol, CASE WHEN $this->lifetimeCol IS NULL OR $this->lifetimeCol + $this->timeCol > ? THEN $this->dataCol ELSE NULL END FROM $this->table WHERE $this->idCol IN (?)"; - $result = $this->conn->executeQuery($sql, [ - $now, - $ids, - ], [ - ParameterType::INTEGER, - Connection::PARAM_STR_ARRAY, - ])->iterateNumeric(); - - foreach ($result as $row) { - if (null === $row[1]) { - $expired[] = $row[0]; - } else { - yield $row[0] => $this->marshaller->unmarshall(\is_resource($row[1]) ? stream_get_contents($row[1]) : $row[1]); - } - } - - if ($expired) { - $sql = "DELETE FROM $this->table WHERE $this->lifetimeCol + $this->timeCol <= ? AND $this->idCol IN (?)"; - $this->conn->executeStatement($sql, [ - $now, - $expired, - ], [ - ParameterType::INTEGER, - Connection::PARAM_STR_ARRAY, - ]); - } - } - - /** - * {@inheritdoc} - */ - protected function doHave(string $id): bool - { - $sql = "SELECT 1 FROM $this->table WHERE $this->idCol = ? AND ($this->lifetimeCol IS NULL OR $this->lifetimeCol + $this->timeCol > ?)"; - $result = $this->conn->executeQuery($sql, [ - $id, - time(), - ], [ - ParameterType::STRING, - ParameterType::INTEGER, - ]); - - return (bool) $result->fetchOne(); - } - - /** - * {@inheritdoc} - */ - protected function doClear(string $namespace): bool - { - if ('' === $namespace) { - if ('sqlite' === $this->getPlatformName()) { - $sql = "DELETE FROM $this->table"; - } else { - $sql = "TRUNCATE TABLE $this->table"; - } - } else { - $sql = "DELETE FROM $this->table WHERE $this->idCol LIKE '$namespace%'"; - } - - try { - $this->conn->executeStatement($sql); - } catch (TableNotFoundException $e) { - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doDelete(array $ids): bool - { - $sql = "DELETE FROM $this->table WHERE $this->idCol IN (?)"; - try { - $this->conn->executeStatement($sql, [array_values($ids)], [Connection::PARAM_STR_ARRAY]); - } catch (TableNotFoundException $e) { - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doSave(array $values, int $lifetime) - { - if (!$values = $this->marshaller->marshall($values, $failed)) { - return $failed; - } - - $platformName = $this->getPlatformName(); - $insertSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?)"; - - switch (true) { - case 'mysql' === $platformName: - $sql = $insertSql." ON DUPLICATE KEY UPDATE $this->dataCol = VALUES($this->dataCol), $this->lifetimeCol = VALUES($this->lifetimeCol), $this->timeCol = VALUES($this->timeCol)"; - break; - case 'oci' === $platformName: - // DUAL is Oracle specific dummy table - $sql = "MERGE INTO $this->table USING DUAL ON ($this->idCol = ?) ". - "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ". - "WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?"; - break; - case 'sqlsrv' === $platformName && version_compare($this->getServerVersion(), '10', '>='): - // MERGE is only available since SQL Server 2008 and must be terminated by semicolon - // It also requires HOLDLOCK according to http://weblogs.sqlteam.com/dang/archive/2009/01/31/UPSERT-Race-Condition-With-MERGE.aspx - $sql = "MERGE INTO $this->table WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ($this->idCol = ?) ". - "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ". - "WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?;"; - break; - case 'sqlite' === $platformName: - $sql = 'INSERT OR REPLACE'.substr($insertSql, 6); - break; - case 'pgsql' === $platformName && version_compare($this->getServerVersion(), '9.5', '>='): - $sql = $insertSql." ON CONFLICT ($this->idCol) DO UPDATE SET ($this->dataCol, $this->lifetimeCol, $this->timeCol) = (EXCLUDED.$this->dataCol, EXCLUDED.$this->lifetimeCol, EXCLUDED.$this->timeCol)"; - break; - default: - $platformName = null; - $sql = "UPDATE $this->table SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ? WHERE $this->idCol = ?"; - break; - } - - $now = time(); - $lifetime = $lifetime ?: null; - try { - $stmt = $this->conn->prepare($sql); - } catch (TableNotFoundException $e) { - if (!$this->conn->isTransactionActive() || \in_array($platformName, ['pgsql', 'sqlite', 'sqlsrv'], true)) { - $this->createTable(); - } - $stmt = $this->conn->prepare($sql); - } - - // $id and $data are defined later in the loop. Binding is done by reference, values are read on execution. - if ('sqlsrv' === $platformName || 'oci' === $platformName) { - $stmt->bindParam(1, $id); - $stmt->bindParam(2, $id); - $stmt->bindParam(3, $data, ParameterType::LARGE_OBJECT); - $stmt->bindValue(4, $lifetime, ParameterType::INTEGER); - $stmt->bindValue(5, $now, ParameterType::INTEGER); - $stmt->bindParam(6, $data, ParameterType::LARGE_OBJECT); - $stmt->bindValue(7, $lifetime, ParameterType::INTEGER); - $stmt->bindValue(8, $now, ParameterType::INTEGER); - } elseif (null !== $platformName) { - $stmt->bindParam(1, $id); - $stmt->bindParam(2, $data, ParameterType::LARGE_OBJECT); - $stmt->bindValue(3, $lifetime, ParameterType::INTEGER); - $stmt->bindValue(4, $now, ParameterType::INTEGER); - } else { - $stmt->bindParam(1, $data, ParameterType::LARGE_OBJECT); - $stmt->bindValue(2, $lifetime, ParameterType::INTEGER); - $stmt->bindValue(3, $now, ParameterType::INTEGER); - $stmt->bindParam(4, $id); - - $insertStmt = $this->conn->prepare($insertSql); - $insertStmt->bindParam(1, $id); - $insertStmt->bindParam(2, $data, ParameterType::LARGE_OBJECT); - $insertStmt->bindValue(3, $lifetime, ParameterType::INTEGER); - $insertStmt->bindValue(4, $now, ParameterType::INTEGER); - } - - foreach ($values as $id => $data) { - try { - $rowCount = $stmt->executeStatement(); - } catch (TableNotFoundException $e) { - if (!$this->conn->isTransactionActive() || \in_array($platformName, ['pgsql', 'sqlite', 'sqlsrv'], true)) { - $this->createTable(); - } - $rowCount = $stmt->executeStatement(); - } - if (null === $platformName && 0 === $rowCount) { - try { - $insertStmt->executeStatement(); - } catch (DBALException $e) { - // A concurrent write won, let it be - } - } - } - - return $failed; - } - - private function getPlatformName(): string - { - if (isset($this->platformName)) { - return $this->platformName; - } - - $platform = $this->conn->getDatabasePlatform(); - - switch (true) { - case $platform instanceof \Doctrine\DBAL\Platforms\MySQLPlatform: - case $platform instanceof \Doctrine\DBAL\Platforms\MySQL57Platform: - return $this->platformName = 'mysql'; - - case $platform instanceof \Doctrine\DBAL\Platforms\SqlitePlatform: - return $this->platformName = 'sqlite'; - - case $platform instanceof \Doctrine\DBAL\Platforms\PostgreSQLPlatform: - case $platform instanceof \Doctrine\DBAL\Platforms\PostgreSQL94Platform: - return $this->platformName = 'pgsql'; - - case $platform instanceof \Doctrine\DBAL\Platforms\OraclePlatform: - return $this->platformName = 'oci'; - - case $platform instanceof \Doctrine\DBAL\Platforms\SQLServerPlatform: - case $platform instanceof \Doctrine\DBAL\Platforms\SQLServer2012Platform: - return $this->platformName = 'sqlsrv'; - - default: - return $this->platformName = \get_class($platform); - } - } - - private function getServerVersion(): string - { - if (isset($this->serverVersion)) { - return $this->serverVersion; - } - - $conn = $this->conn->getWrappedConnection(); - if ($conn instanceof ServerInfoAwareConnection) { - return $this->serverVersion = $conn->getServerVersion(); - } - - return $this->serverVersion = '0'; - } - - private function addTableToSchema(Schema $schema): void - { - $types = [ - 'mysql' => 'binary', - 'sqlite' => 'text', - ]; - - $table = $schema->createTable($this->table); - $table->addColumn($this->idCol, $types[$this->getPlatformName()] ?? 'string', ['length' => 255]); - $table->addColumn($this->dataCol, 'blob', ['length' => 16777215]); - $table->addColumn($this->lifetimeCol, 'integer', ['unsigned' => true, 'notnull' => false]); - $table->addColumn($this->timeCol, 'integer', ['unsigned' => true]); - $table->setPrimaryKey([$this->idCol]); - } -} diff --git a/lib/symfony/cache/Adapter/FilesystemAdapter.php b/lib/symfony/cache/Adapter/FilesystemAdapter.php deleted file mode 100644 index 7185dd487..000000000 --- a/lib/symfony/cache/Adapter/FilesystemAdapter.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Symfony\Component\Cache\Marshaller\DefaultMarshaller; -use Symfony\Component\Cache\Marshaller\MarshallerInterface; -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\Traits\FilesystemTrait; - -class FilesystemAdapter extends AbstractAdapter implements PruneableInterface -{ - use FilesystemTrait; - - public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, MarshallerInterface $marshaller = null) - { - $this->marshaller = $marshaller ?? new DefaultMarshaller(); - parent::__construct('', $defaultLifetime); - $this->init($namespace, $directory); - } -} diff --git a/lib/symfony/cache/Adapter/FilesystemTagAwareAdapter.php b/lib/symfony/cache/Adapter/FilesystemTagAwareAdapter.php deleted file mode 100644 index afde84375..000000000 --- a/lib/symfony/cache/Adapter/FilesystemTagAwareAdapter.php +++ /dev/null @@ -1,239 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Symfony\Component\Cache\Marshaller\MarshallerInterface; -use Symfony\Component\Cache\Marshaller\TagAwareMarshaller; -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\Traits\FilesystemTrait; - -/** - * Stores tag id <> cache id relationship as a symlink, and lookup on invalidation calls. - * - * @author Nicolas Grekas <p@tchwork.com> - * @author André Rømcke <andre.romcke+symfony@gmail.com> - */ -class FilesystemTagAwareAdapter extends AbstractTagAwareAdapter implements PruneableInterface -{ - use FilesystemTrait { - doClear as private doClearCache; - doSave as private doSaveCache; - } - - /** - * Folder used for tag symlinks. - */ - private const TAG_FOLDER = 'tags'; - - public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, MarshallerInterface $marshaller = null) - { - $this->marshaller = new TagAwareMarshaller($marshaller); - parent::__construct('', $defaultLifetime); - $this->init($namespace, $directory); - } - - /** - * {@inheritdoc} - */ - protected function doClear(string $namespace) - { - $ok = $this->doClearCache($namespace); - - if ('' !== $namespace) { - return $ok; - } - - set_error_handler(static function () {}); - $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; - - try { - foreach ($this->scanHashDir($this->directory.self::TAG_FOLDER.\DIRECTORY_SEPARATOR) as $dir) { - if (rename($dir, $renamed = substr_replace($dir, bin2hex(random_bytes(4)), -8))) { - $dir = $renamed.\DIRECTORY_SEPARATOR; - } else { - $dir .= \DIRECTORY_SEPARATOR; - $renamed = null; - } - - for ($i = 0; $i < 38; ++$i) { - if (!is_dir($dir.$chars[$i])) { - continue; - } - for ($j = 0; $j < 38; ++$j) { - if (!is_dir($d = $dir.$chars[$i].\DIRECTORY_SEPARATOR.$chars[$j])) { - continue; - } - foreach (scandir($d, \SCANDIR_SORT_NONE) ?: [] as $link) { - if ('.' !== $link && '..' !== $link && (null !== $renamed || !realpath($d.\DIRECTORY_SEPARATOR.$link))) { - unlink($d.\DIRECTORY_SEPARATOR.$link); - } - } - null === $renamed ?: rmdir($d); - } - null === $renamed ?: rmdir($dir.$chars[$i]); - } - null === $renamed ?: rmdir($renamed); - } - } finally { - restore_error_handler(); - } - - return $ok; - } - - /** - * {@inheritdoc} - */ - protected function doSave(array $values, int $lifetime, array $addTagData = [], array $removeTagData = []): array - { - $failed = $this->doSaveCache($values, $lifetime); - - // Add Tags as symlinks - foreach ($addTagData as $tagId => $ids) { - $tagFolder = $this->getTagFolder($tagId); - foreach ($ids as $id) { - if ($failed && \in_array($id, $failed, true)) { - continue; - } - - $file = $this->getFile($id); - - if (!@symlink($file, $tagLink = $this->getFile($id, true, $tagFolder)) && !is_link($tagLink)) { - @unlink($file); - $failed[] = $id; - } - } - } - - // Unlink removed Tags - foreach ($removeTagData as $tagId => $ids) { - $tagFolder = $this->getTagFolder($tagId); - foreach ($ids as $id) { - if ($failed && \in_array($id, $failed, true)) { - continue; - } - - @unlink($this->getFile($id, false, $tagFolder)); - } - } - - return $failed; - } - - /** - * {@inheritdoc} - */ - protected function doDeleteYieldTags(array $ids): iterable - { - foreach ($ids as $id) { - $file = $this->getFile($id); - if (!is_file($file) || !$h = @fopen($file, 'r')) { - continue; - } - - if ((\PHP_VERSION_ID >= 70300 || '\\' !== \DIRECTORY_SEPARATOR) && !@unlink($file)) { - fclose($h); - continue; - } - - $meta = explode("\n", fread($h, 4096), 3)[2] ?? ''; - - // detect the compact format used in marshall() using magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F - if (13 < \strlen($meta) && "\x9D" === $meta[0] && "\0" === $meta[5] && "\x5F" === $meta[9]) { - $meta[9] = "\0"; - $tagLen = unpack('Nlen', $meta, 9)['len']; - $meta = substr($meta, 13, $tagLen); - - if (0 < $tagLen -= \strlen($meta)) { - $meta .= fread($h, $tagLen); - } - - try { - yield $id => '' === $meta ? [] : $this->marshaller->unmarshall($meta); - } catch (\Exception $e) { - yield $id => []; - } - } - - fclose($h); - - if (\PHP_VERSION_ID < 70300 && '\\' === \DIRECTORY_SEPARATOR) { - @unlink($file); - } - } - } - - /** - * {@inheritdoc} - */ - protected function doDeleteTagRelations(array $tagData): bool - { - foreach ($tagData as $tagId => $idList) { - $tagFolder = $this->getTagFolder($tagId); - foreach ($idList as $id) { - @unlink($this->getFile($id, false, $tagFolder)); - } - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doInvalidate(array $tagIds): bool - { - foreach ($tagIds as $tagId) { - if (!is_dir($tagFolder = $this->getTagFolder($tagId))) { - continue; - } - - set_error_handler(static function () {}); - - try { - if (rename($tagFolder, $renamed = substr_replace($tagFolder, bin2hex(random_bytes(4)), -9))) { - $tagFolder = $renamed.\DIRECTORY_SEPARATOR; - } else { - $renamed = null; - } - - foreach ($this->scanHashDir($tagFolder) as $itemLink) { - unlink(realpath($itemLink) ?: $itemLink); - unlink($itemLink); - } - - if (null === $renamed) { - continue; - } - - $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; - - for ($i = 0; $i < 38; ++$i) { - for ($j = 0; $j < 38; ++$j) { - rmdir($tagFolder.$chars[$i].\DIRECTORY_SEPARATOR.$chars[$j]); - } - rmdir($tagFolder.$chars[$i]); - } - rmdir($renamed); - } finally { - restore_error_handler(); - } - } - - return true; - } - - private function getTagFolder(string $tagId): string - { - return $this->getFile($tagId, false, $this->directory.self::TAG_FOLDER.\DIRECTORY_SEPARATOR).\DIRECTORY_SEPARATOR; - } -} diff --git a/lib/symfony/cache/Adapter/MemcachedAdapter.php b/lib/symfony/cache/Adapter/MemcachedAdapter.php deleted file mode 100644 index 5c2933fcf..000000000 --- a/lib/symfony/cache/Adapter/MemcachedAdapter.php +++ /dev/null @@ -1,353 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Symfony\Component\Cache\Exception\CacheException; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\Marshaller\DefaultMarshaller; -use Symfony\Component\Cache\Marshaller\MarshallerInterface; - -/** - * @author Rob Frawley 2nd <rmf@src.run> - * @author Nicolas Grekas <p@tchwork.com> - */ -class MemcachedAdapter extends AbstractAdapter -{ - /** - * We are replacing characters that are illegal in Memcached keys with reserved characters from - * {@see \Symfony\Contracts\Cache\ItemInterface::RESERVED_CHARACTERS} that are legal in Memcached. - * Note: don’t use {@see \Symfony\Component\Cache\Adapter\AbstractAdapter::NS_SEPARATOR}. - */ - private const RESERVED_MEMCACHED = " \n\r\t\v\f\0"; - private const RESERVED_PSR6 = '@()\{}/'; - - protected $maxIdLength = 250; - - private const DEFAULT_CLIENT_OPTIONS = [ - 'persistent_id' => null, - 'username' => null, - 'password' => null, - \Memcached::OPT_SERIALIZER => \Memcached::SERIALIZER_PHP, - ]; - - private $marshaller; - private $client; - private $lazyClient; - - /** - * Using a MemcachedAdapter with a TagAwareAdapter for storing tags is discouraged. - * Using a RedisAdapter is recommended instead. If you cannot do otherwise, be aware that: - * - the Memcached::OPT_BINARY_PROTOCOL must be enabled - * (that's the default when using MemcachedAdapter::createConnection()); - * - tags eviction by Memcached's LRU algorithm will break by-tags invalidation; - * your Memcached memory should be large enough to never trigger LRU. - * - * Using a MemcachedAdapter as a pure items store is fine. - */ - public function __construct(\Memcached $client, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) - { - if (!static::isSupported()) { - throw new CacheException('Memcached '.(\PHP_VERSION_ID >= 80100 ? '> 3.1.5' : '>= 2.2.0').' is required.'); - } - if ('Memcached' === \get_class($client)) { - $opt = $client->getOption(\Memcached::OPT_SERIALIZER); - if (\Memcached::SERIALIZER_PHP !== $opt && \Memcached::SERIALIZER_IGBINARY !== $opt) { - throw new CacheException('MemcachedAdapter: "serializer" option must be "php" or "igbinary".'); - } - $this->maxIdLength -= \strlen($client->getOption(\Memcached::OPT_PREFIX_KEY)); - $this->client = $client; - } else { - $this->lazyClient = $client; - } - - parent::__construct($namespace, $defaultLifetime); - $this->enableVersioning(); - $this->marshaller = $marshaller ?? new DefaultMarshaller(); - } - - public static function isSupported() - { - return \extension_loaded('memcached') && version_compare(phpversion('memcached'), \PHP_VERSION_ID >= 80100 ? '3.1.6' : '2.2.0', '>='); - } - - /** - * Creates a Memcached instance. - * - * By default, the binary protocol, no block, and libketama compatible options are enabled. - * - * Examples for servers: - * - 'memcached://user:pass@localhost?weight=33' - * - [['localhost', 11211, 33]] - * - * @param array[]|string|string[] $servers An array of servers, a DSN, or an array of DSNs - * - * @return \Memcached - * - * @throws \ErrorException When invalid options or servers are provided - */ - public static function createConnection($servers, array $options = []) - { - if (\is_string($servers)) { - $servers = [$servers]; - } elseif (!\is_array($servers)) { - throw new InvalidArgumentException(sprintf('MemcachedAdapter::createClient() expects array or string as first argument, "%s" given.', get_debug_type($servers))); - } - if (!static::isSupported()) { - throw new CacheException('Memcached '.(\PHP_VERSION_ID >= 80100 ? '> 3.1.5' : '>= 2.2.0').' is required.'); - } - set_error_handler(function ($type, $msg, $file, $line) { throw new \ErrorException($msg, 0, $type, $file, $line); }); - try { - $options += static::DEFAULT_CLIENT_OPTIONS; - $client = new \Memcached($options['persistent_id']); - $username = $options['username']; - $password = $options['password']; - - // parse any DSN in $servers - foreach ($servers as $i => $dsn) { - if (\is_array($dsn)) { - continue; - } - if (!str_starts_with($dsn, 'memcached:')) { - throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: "%s" does not start with "memcached:".', $dsn)); - } - $params = preg_replace_callback('#^memcached:(//)?(?:([^@]*+)@)?#', function ($m) use (&$username, &$password) { - if (!empty($m[2])) { - [$username, $password] = explode(':', $m[2], 2) + [1 => null]; - } - - return 'file:'.($m[1] ?? ''); - }, $dsn); - if (false === $params = parse_url($params)) { - throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: "%s".', $dsn)); - } - $query = $hosts = []; - if (isset($params['query'])) { - parse_str($params['query'], $query); - - if (isset($query['host'])) { - if (!\is_array($hosts = $query['host'])) { - throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: "%s".', $dsn)); - } - foreach ($hosts as $host => $weight) { - if (false === $port = strrpos($host, ':')) { - $hosts[$host] = [$host, 11211, (int) $weight]; - } else { - $hosts[$host] = [substr($host, 0, $port), (int) substr($host, 1 + $port), (int) $weight]; - } - } - $hosts = array_values($hosts); - unset($query['host']); - } - if ($hosts && !isset($params['host']) && !isset($params['path'])) { - unset($servers[$i]); - $servers = array_merge($servers, $hosts); - continue; - } - } - if (!isset($params['host']) && !isset($params['path'])) { - throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: "%s".', $dsn)); - } - if (isset($params['path']) && preg_match('#/(\d+)$#', $params['path'], $m)) { - $params['weight'] = $m[1]; - $params['path'] = substr($params['path'], 0, -\strlen($m[0])); - } - $params += [ - 'host' => $params['host'] ?? $params['path'], - 'port' => isset($params['host']) ? 11211 : null, - 'weight' => 0, - ]; - if ($query) { - $params += $query; - $options = $query + $options; - } - - $servers[$i] = [$params['host'], $params['port'], $params['weight']]; - - if ($hosts) { - $servers = array_merge($servers, $hosts); - } - } - - // set client's options - unset($options['persistent_id'], $options['username'], $options['password'], $options['weight'], $options['lazy']); - $options = array_change_key_case($options, \CASE_UPPER); - $client->setOption(\Memcached::OPT_BINARY_PROTOCOL, true); - $client->setOption(\Memcached::OPT_NO_BLOCK, true); - $client->setOption(\Memcached::OPT_TCP_NODELAY, true); - if (!\array_key_exists('LIBKETAMA_COMPATIBLE', $options) && !\array_key_exists(\Memcached::OPT_LIBKETAMA_COMPATIBLE, $options)) { - $client->setOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE, true); - } - foreach ($options as $name => $value) { - if (\is_int($name)) { - continue; - } - if ('HASH' === $name || 'SERIALIZER' === $name || 'DISTRIBUTION' === $name) { - $value = \constant('Memcached::'.$name.'_'.strtoupper($value)); - } - unset($options[$name]); - - if (\defined('Memcached::OPT_'.$name)) { - $options[\constant('Memcached::OPT_'.$name)] = $value; - } - } - $client->setOptions($options); - - // set client's servers, taking care of persistent connections - if (!$client->isPristine()) { - $oldServers = []; - foreach ($client->getServerList() as $server) { - $oldServers[] = [$server['host'], $server['port']]; - } - - $newServers = []; - foreach ($servers as $server) { - if (1 < \count($server)) { - $server = array_values($server); - unset($server[2]); - $server[1] = (int) $server[1]; - } - $newServers[] = $server; - } - - if ($oldServers !== $newServers) { - $client->resetServerList(); - $client->addServers($servers); - } - } else { - $client->addServers($servers); - } - - if (null !== $username || null !== $password) { - if (!method_exists($client, 'setSaslAuthData')) { - trigger_error('Missing SASL support: the memcached extension must be compiled with --enable-memcached-sasl.'); - } - $client->setSaslAuthData($username, $password); - } - - return $client; - } finally { - restore_error_handler(); - } - } - - /** - * {@inheritdoc} - */ - protected function doSave(array $values, int $lifetime) - { - if (!$values = $this->marshaller->marshall($values, $failed)) { - return $failed; - } - - if ($lifetime && $lifetime > 30 * 86400) { - $lifetime += time(); - } - - $encodedValues = []; - foreach ($values as $key => $value) { - $encodedValues[self::encodeKey($key)] = $value; - } - - return $this->checkResultCode($this->getClient()->setMulti($encodedValues, $lifetime)) ? $failed : false; - } - - /** - * {@inheritdoc} - */ - protected function doFetch(array $ids) - { - try { - $encodedIds = array_map([__CLASS__, 'encodeKey'], $ids); - - $encodedResult = $this->checkResultCode($this->getClient()->getMulti($encodedIds)); - - $result = []; - foreach ($encodedResult as $key => $value) { - $result[self::decodeKey($key)] = $this->marshaller->unmarshall($value); - } - - return $result; - } catch (\Error $e) { - throw new \ErrorException($e->getMessage(), $e->getCode(), \E_ERROR, $e->getFile(), $e->getLine()); - } - } - - /** - * {@inheritdoc} - */ - protected function doHave(string $id) - { - return false !== $this->getClient()->get(self::encodeKey($id)) || $this->checkResultCode(\Memcached::RES_SUCCESS === $this->client->getResultCode()); - } - - /** - * {@inheritdoc} - */ - protected function doDelete(array $ids) - { - $ok = true; - $encodedIds = array_map([__CLASS__, 'encodeKey'], $ids); - foreach ($this->checkResultCode($this->getClient()->deleteMulti($encodedIds)) as $result) { - if (\Memcached::RES_SUCCESS !== $result && \Memcached::RES_NOTFOUND !== $result) { - $ok = false; - } - } - - return $ok; - } - - /** - * {@inheritdoc} - */ - protected function doClear(string $namespace) - { - return '' === $namespace && $this->getClient()->flush(); - } - - private function checkResultCode($result) - { - $code = $this->client->getResultCode(); - - if (\Memcached::RES_SUCCESS === $code || \Memcached::RES_NOTFOUND === $code) { - return $result; - } - - throw new CacheException('MemcachedAdapter client error: '.strtolower($this->client->getResultMessage())); - } - - private function getClient(): \Memcached - { - if ($this->client) { - return $this->client; - } - - $opt = $this->lazyClient->getOption(\Memcached::OPT_SERIALIZER); - if (\Memcached::SERIALIZER_PHP !== $opt && \Memcached::SERIALIZER_IGBINARY !== $opt) { - throw new CacheException('MemcachedAdapter: "serializer" option must be "php" or "igbinary".'); - } - if ('' !== $prefix = (string) $this->lazyClient->getOption(\Memcached::OPT_PREFIX_KEY)) { - throw new CacheException(sprintf('MemcachedAdapter: "prefix_key" option must be empty when using proxified connections, "%s" given.', $prefix)); - } - - return $this->client = $this->lazyClient; - } - - private static function encodeKey(string $key): string - { - return strtr($key, self::RESERVED_MEMCACHED, self::RESERVED_PSR6); - } - - private static function decodeKey(string $key): string - { - return strtr($key, self::RESERVED_PSR6, self::RESERVED_MEMCACHED); - } -} diff --git a/lib/symfony/cache/Adapter/NullAdapter.php b/lib/symfony/cache/Adapter/NullAdapter.php deleted file mode 100644 index 15f7f8c45..000000000 --- a/lib/symfony/cache/Adapter/NullAdapter.php +++ /dev/null @@ -1,152 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Psr\Cache\CacheItemInterface; -use Symfony\Component\Cache\CacheItem; -use Symfony\Contracts\Cache\CacheInterface; - -/** - * @author Titouan Galopin <galopintitouan@gmail.com> - */ -class NullAdapter implements AdapterInterface, CacheInterface -{ - private static $createCacheItem; - - public function __construct() - { - self::$createCacheItem ?? self::$createCacheItem = \Closure::bind( - static function ($key) { - $item = new CacheItem(); - $item->key = $key; - $item->isHit = false; - - return $item; - }, - null, - CacheItem::class - ); - } - - /** - * {@inheritdoc} - */ - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) - { - $save = true; - - return $callback((self::$createCacheItem)($key), $save); - } - - /** - * {@inheritdoc} - */ - public function getItem($key) - { - return (self::$createCacheItem)($key); - } - - /** - * {@inheritdoc} - */ - public function getItems(array $keys = []) - { - return $this->generateItems($keys); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function hasItem($key) - { - return false; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function clear(string $prefix = '') - { - return true; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItem($key) - { - return true; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItems(array $keys) - { - return true; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function save(CacheItemInterface $item) - { - return true; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function saveDeferred(CacheItemInterface $item) - { - return true; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function commit() - { - return true; - } - - /** - * {@inheritdoc} - */ - public function delete(string $key): bool - { - return $this->deleteItem($key); - } - - private function generateItems(array $keys): \Generator - { - $f = self::$createCacheItem; - - foreach ($keys as $key) { - yield $key => $f($key); - } - } -} diff --git a/lib/symfony/cache/Adapter/ParameterNormalizer.php b/lib/symfony/cache/Adapter/ParameterNormalizer.php deleted file mode 100644 index e33ae9f46..000000000 --- a/lib/symfony/cache/Adapter/ParameterNormalizer.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -/** - * @author Lars Strojny <lars@strojny.net> - */ -final class ParameterNormalizer -{ - public static function normalizeDuration(string $duration): int - { - if (is_numeric($duration)) { - return $duration; - } - - if (false !== $time = strtotime($duration, 0)) { - return $time; - } - - try { - return \DateTime::createFromFormat('U', 0)->add(new \DateInterval($duration))->getTimestamp(); - } catch (\Exception $e) { - throw new \InvalidArgumentException(sprintf('Cannot parse date interval "%s".', $duration), 0, $e); - } - } -} diff --git a/lib/symfony/cache/Adapter/PdoAdapter.php b/lib/symfony/cache/Adapter/PdoAdapter.php deleted file mode 100644 index 5d1072443..000000000 --- a/lib/symfony/cache/Adapter/PdoAdapter.php +++ /dev/null @@ -1,583 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Schema\Schema; -use Psr\Cache\CacheItemInterface; -use Psr\Log\LoggerInterface; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\Marshaller\DefaultMarshaller; -use Symfony\Component\Cache\Marshaller\MarshallerInterface; -use Symfony\Component\Cache\PruneableInterface; - -class PdoAdapter extends AbstractAdapter implements PruneableInterface -{ - protected $maxIdLength = 255; - - private $marshaller; - private $conn; - private $dsn; - private $driver; - private $serverVersion; - private $table = 'cache_items'; - private $idCol = 'item_id'; - private $dataCol = 'item_data'; - private $lifetimeCol = 'item_lifetime'; - private $timeCol = 'item_time'; - private $username = ''; - private $password = ''; - private $connectionOptions = []; - private $namespace; - - private $dbalAdapter; - - /** - * You can either pass an existing database connection as PDO instance or - * a DSN string that will be used to lazy-connect to the database when the - * cache is actually used. - * - * List of available options: - * * db_table: The name of the table [default: cache_items] - * * db_id_col: The column where to store the cache id [default: item_id] - * * db_data_col: The column where to store the cache data [default: item_data] - * * db_lifetime_col: The column where to store the lifetime [default: item_lifetime] - * * db_time_col: The column where to store the timestamp [default: item_time] - * * db_username: The username when lazy-connect [default: ''] - * * db_password: The password when lazy-connect [default: ''] - * * db_connection_options: An array of driver-specific connection options [default: []] - * - * @param \PDO|string $connOrDsn - * - * @throws InvalidArgumentException When first argument is not PDO nor Connection nor string - * @throws InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION - * @throws InvalidArgumentException When namespace contains invalid characters - */ - public function __construct($connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], MarshallerInterface $marshaller = null) - { - if ($connOrDsn instanceof Connection || (\is_string($connOrDsn) && str_contains($connOrDsn, '://'))) { - trigger_deprecation('symfony/cache', '5.4', 'Usage of a DBAL Connection with "%s" is deprecated and will be removed in symfony 6.0. Use "%s" instead.', __CLASS__, DoctrineDbalAdapter::class); - $this->dbalAdapter = new DoctrineDbalAdapter($connOrDsn, $namespace, $defaultLifetime, $options, $marshaller); - - return; - } - - if (isset($namespace[0]) && preg_match('#[^-+.A-Za-z0-9]#', $namespace, $match)) { - throw new InvalidArgumentException(sprintf('Namespace contains "%s" but only characters in [-+.A-Za-z0-9] are allowed.', $match[0])); - } - - if ($connOrDsn instanceof \PDO) { - if (\PDO::ERRMODE_EXCEPTION !== $connOrDsn->getAttribute(\PDO::ATTR_ERRMODE)) { - throw new InvalidArgumentException(sprintf('"%s" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)).', __CLASS__)); - } - - $this->conn = $connOrDsn; - } elseif (\is_string($connOrDsn)) { - $this->dsn = $connOrDsn; - } else { - throw new InvalidArgumentException(sprintf('"%s" requires PDO or Doctrine\DBAL\Connection instance or DSN string as first argument, "%s" given.', __CLASS__, get_debug_type($connOrDsn))); - } - - $this->table = $options['db_table'] ?? $this->table; - $this->idCol = $options['db_id_col'] ?? $this->idCol; - $this->dataCol = $options['db_data_col'] ?? $this->dataCol; - $this->lifetimeCol = $options['db_lifetime_col'] ?? $this->lifetimeCol; - $this->timeCol = $options['db_time_col'] ?? $this->timeCol; - $this->username = $options['db_username'] ?? $this->username; - $this->password = $options['db_password'] ?? $this->password; - $this->connectionOptions = $options['db_connection_options'] ?? $this->connectionOptions; - $this->namespace = $namespace; - $this->marshaller = $marshaller ?? new DefaultMarshaller(); - - parent::__construct($namespace, $defaultLifetime); - } - - /** - * {@inheritDoc} - */ - public function getItem($key) - { - if (isset($this->dbalAdapter)) { - return $this->dbalAdapter->getItem($key); - } - - return parent::getItem($key); - } - - /** - * {@inheritDoc} - */ - public function getItems(array $keys = []) - { - if (isset($this->dbalAdapter)) { - return $this->dbalAdapter->getItems($keys); - } - - return parent::getItems($keys); - } - - /** - * {@inheritDoc} - */ - public function hasItem($key) - { - if (isset($this->dbalAdapter)) { - return $this->dbalAdapter->hasItem($key); - } - - return parent::hasItem($key); - } - - /** - * {@inheritDoc} - */ - public function deleteItem($key) - { - if (isset($this->dbalAdapter)) { - return $this->dbalAdapter->deleteItem($key); - } - - return parent::deleteItem($key); - } - - /** - * {@inheritDoc} - */ - public function deleteItems(array $keys) - { - if (isset($this->dbalAdapter)) { - return $this->dbalAdapter->deleteItems($keys); - } - - return parent::deleteItems($keys); - } - - /** - * {@inheritDoc} - */ - public function clear(string $prefix = '') - { - if (isset($this->dbalAdapter)) { - return $this->dbalAdapter->clear($prefix); - } - - return parent::clear($prefix); - } - - /** - * {@inheritDoc} - */ - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) - { - if (isset($this->dbalAdapter)) { - return $this->dbalAdapter->get($key, $callback, $beta, $metadata); - } - - return parent::get($key, $callback, $beta, $metadata); - } - - /** - * {@inheritDoc} - */ - public function delete(string $key): bool - { - if (isset($this->dbalAdapter)) { - return $this->dbalAdapter->delete($key); - } - - return parent::delete($key); - } - - /** - * {@inheritDoc} - */ - public function save(CacheItemInterface $item) - { - if (isset($this->dbalAdapter)) { - return $this->dbalAdapter->save($item); - } - - return parent::save($item); - } - - /** - * {@inheritDoc} - */ - public function saveDeferred(CacheItemInterface $item) - { - if (isset($this->dbalAdapter)) { - return $this->dbalAdapter->saveDeferred($item); - } - - return parent::saveDeferred($item); - } - - /** - * {@inheritDoc} - */ - public function setLogger(LoggerInterface $logger): void - { - if (isset($this->dbalAdapter)) { - $this->dbalAdapter->setLogger($logger); - - return; - } - - parent::setLogger($logger); - } - - /** - * {@inheritDoc} - */ - public function commit() - { - if (isset($this->dbalAdapter)) { - return $this->dbalAdapter->commit(); - } - - return parent::commit(); - } - - /** - * {@inheritDoc} - */ - public function reset() - { - if (isset($this->dbalAdapter)) { - $this->dbalAdapter->reset(); - - return; - } - - parent::reset(); - } - - /** - * Creates the table to store cache items which can be called once for setup. - * - * Cache ID are saved in a column of maximum length 255. Cache data is - * saved in a BLOB. - * - * @throws \PDOException When the table already exists - * @throws \DomainException When an unsupported PDO driver is used - */ - public function createTable() - { - if (isset($this->dbalAdapter)) { - $this->dbalAdapter->createTable(); - - return; - } - - // connect if we are not yet - $conn = $this->getConnection(); - - switch ($this->driver) { - case 'mysql': - // We use varbinary for the ID column because it prevents unwanted conversions: - // - character set conversions between server and client - // - trailing space removal - // - case-insensitivity - // - language processing like é == e - $sql = "CREATE TABLE $this->table ($this->idCol VARBINARY(255) NOT NULL PRIMARY KEY, $this->dataCol MEDIUMBLOB NOT NULL, $this->lifetimeCol INTEGER UNSIGNED, $this->timeCol INTEGER UNSIGNED NOT NULL) COLLATE utf8mb4_bin, ENGINE = InnoDB"; - break; - case 'sqlite': - $sql = "CREATE TABLE $this->table ($this->idCol TEXT NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)"; - break; - case 'pgsql': - $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR(255) NOT NULL PRIMARY KEY, $this->dataCol BYTEA NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)"; - break; - case 'oci': - $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR2(255) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)"; - break; - case 'sqlsrv': - $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR(255) NOT NULL PRIMARY KEY, $this->dataCol VARBINARY(MAX) NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)"; - break; - default: - throw new \DomainException(sprintf('Creating the cache table is currently not implemented for PDO driver "%s".', $this->driver)); - } - - $conn->exec($sql); - } - - /** - * Adds the Table to the Schema if the adapter uses this Connection. - * - * @deprecated since symfony/cache 5.4 use DoctrineDbalAdapter instead - */ - public function configureSchema(Schema $schema, Connection $forConnection): void - { - if (isset($this->dbalAdapter)) { - $this->dbalAdapter->configureSchema($schema, $forConnection); - } - } - - /** - * {@inheritdoc} - */ - public function prune() - { - if (isset($this->dbalAdapter)) { - return $this->dbalAdapter->prune(); - } - - $deleteSql = "DELETE FROM $this->table WHERE $this->lifetimeCol + $this->timeCol <= :time"; - - if ('' !== $this->namespace) { - $deleteSql .= " AND $this->idCol LIKE :namespace"; - } - - $connection = $this->getConnection(); - - try { - $delete = $connection->prepare($deleteSql); - } catch (\PDOException $e) { - return true; - } - $delete->bindValue(':time', time(), \PDO::PARAM_INT); - - if ('' !== $this->namespace) { - $delete->bindValue(':namespace', sprintf('%s%%', $this->namespace), \PDO::PARAM_STR); - } - try { - return $delete->execute(); - } catch (\PDOException $e) { - return true; - } - } - - /** - * {@inheritdoc} - */ - protected function doFetch(array $ids) - { - $connection = $this->getConnection(); - - $now = time(); - $expired = []; - - $sql = str_pad('', (\count($ids) << 1) - 1, '?,'); - $sql = "SELECT $this->idCol, CASE WHEN $this->lifetimeCol IS NULL OR $this->lifetimeCol + $this->timeCol > ? THEN $this->dataCol ELSE NULL END FROM $this->table WHERE $this->idCol IN ($sql)"; - $stmt = $connection->prepare($sql); - $stmt->bindValue($i = 1, $now, \PDO::PARAM_INT); - foreach ($ids as $id) { - $stmt->bindValue(++$i, $id); - } - $result = $stmt->execute(); - - if (\is_object($result)) { - $result = $result->iterateNumeric(); - } else { - $stmt->setFetchMode(\PDO::FETCH_NUM); - $result = $stmt; - } - - foreach ($result as $row) { - if (null === $row[1]) { - $expired[] = $row[0]; - } else { - yield $row[0] => $this->marshaller->unmarshall(\is_resource($row[1]) ? stream_get_contents($row[1]) : $row[1]); - } - } - - if ($expired) { - $sql = str_pad('', (\count($expired) << 1) - 1, '?,'); - $sql = "DELETE FROM $this->table WHERE $this->lifetimeCol + $this->timeCol <= ? AND $this->idCol IN ($sql)"; - $stmt = $connection->prepare($sql); - $stmt->bindValue($i = 1, $now, \PDO::PARAM_INT); - foreach ($expired as $id) { - $stmt->bindValue(++$i, $id); - } - $stmt->execute(); - } - } - - /** - * {@inheritdoc} - */ - protected function doHave(string $id) - { - $connection = $this->getConnection(); - - $sql = "SELECT 1 FROM $this->table WHERE $this->idCol = :id AND ($this->lifetimeCol IS NULL OR $this->lifetimeCol + $this->timeCol > :time)"; - $stmt = $connection->prepare($sql); - - $stmt->bindValue(':id', $id); - $stmt->bindValue(':time', time(), \PDO::PARAM_INT); - $stmt->execute(); - - return (bool) $stmt->fetchColumn(); - } - - /** - * {@inheritdoc} - */ - protected function doClear(string $namespace) - { - $conn = $this->getConnection(); - - if ('' === $namespace) { - if ('sqlite' === $this->driver) { - $sql = "DELETE FROM $this->table"; - } else { - $sql = "TRUNCATE TABLE $this->table"; - } - } else { - $sql = "DELETE FROM $this->table WHERE $this->idCol LIKE '$namespace%'"; - } - - try { - $conn->exec($sql); - } catch (\PDOException $e) { - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doDelete(array $ids) - { - $sql = str_pad('', (\count($ids) << 1) - 1, '?,'); - $sql = "DELETE FROM $this->table WHERE $this->idCol IN ($sql)"; - try { - $stmt = $this->getConnection()->prepare($sql); - $stmt->execute(array_values($ids)); - } catch (\PDOException $e) { - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doSave(array $values, int $lifetime) - { - if (!$values = $this->marshaller->marshall($values, $failed)) { - return $failed; - } - - $conn = $this->getConnection(); - - $driver = $this->driver; - $insertSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time)"; - - switch (true) { - case 'mysql' === $driver: - $sql = $insertSql." ON DUPLICATE KEY UPDATE $this->dataCol = VALUES($this->dataCol), $this->lifetimeCol = VALUES($this->lifetimeCol), $this->timeCol = VALUES($this->timeCol)"; - break; - case 'oci' === $driver: - // DUAL is Oracle specific dummy table - $sql = "MERGE INTO $this->table USING DUAL ON ($this->idCol = ?) ". - "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ". - "WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?"; - break; - case 'sqlsrv' === $driver && version_compare($this->getServerVersion(), '10', '>='): - // MERGE is only available since SQL Server 2008 and must be terminated by semicolon - // It also requires HOLDLOCK according to http://weblogs.sqlteam.com/dang/archive/2009/01/31/UPSERT-Race-Condition-With-MERGE.aspx - $sql = "MERGE INTO $this->table WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ($this->idCol = ?) ". - "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ". - "WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?;"; - break; - case 'sqlite' === $driver: - $sql = 'INSERT OR REPLACE'.substr($insertSql, 6); - break; - case 'pgsql' === $driver && version_compare($this->getServerVersion(), '9.5', '>='): - $sql = $insertSql." ON CONFLICT ($this->idCol) DO UPDATE SET ($this->dataCol, $this->lifetimeCol, $this->timeCol) = (EXCLUDED.$this->dataCol, EXCLUDED.$this->lifetimeCol, EXCLUDED.$this->timeCol)"; - break; - default: - $driver = null; - $sql = "UPDATE $this->table SET $this->dataCol = :data, $this->lifetimeCol = :lifetime, $this->timeCol = :time WHERE $this->idCol = :id"; - break; - } - - $now = time(); - $lifetime = $lifetime ?: null; - try { - $stmt = $conn->prepare($sql); - } catch (\PDOException $e) { - if (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) { - $this->createTable(); - } - $stmt = $conn->prepare($sql); - } - - // $id and $data are defined later in the loop. Binding is done by reference, values are read on execution. - if ('sqlsrv' === $driver || 'oci' === $driver) { - $stmt->bindParam(1, $id); - $stmt->bindParam(2, $id); - $stmt->bindParam(3, $data, \PDO::PARAM_LOB); - $stmt->bindValue(4, $lifetime, \PDO::PARAM_INT); - $stmt->bindValue(5, $now, \PDO::PARAM_INT); - $stmt->bindParam(6, $data, \PDO::PARAM_LOB); - $stmt->bindValue(7, $lifetime, \PDO::PARAM_INT); - $stmt->bindValue(8, $now, \PDO::PARAM_INT); - } else { - $stmt->bindParam(':id', $id); - $stmt->bindParam(':data', $data, \PDO::PARAM_LOB); - $stmt->bindValue(':lifetime', $lifetime, \PDO::PARAM_INT); - $stmt->bindValue(':time', $now, \PDO::PARAM_INT); - } - if (null === $driver) { - $insertStmt = $conn->prepare($insertSql); - - $insertStmt->bindParam(':id', $id); - $insertStmt->bindParam(':data', $data, \PDO::PARAM_LOB); - $insertStmt->bindValue(':lifetime', $lifetime, \PDO::PARAM_INT); - $insertStmt->bindValue(':time', $now, \PDO::PARAM_INT); - } - - foreach ($values as $id => $data) { - try { - $stmt->execute(); - } catch (\PDOException $e) { - if (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) { - $this->createTable(); - } - $stmt->execute(); - } - if (null === $driver && !$stmt->rowCount()) { - try { - $insertStmt->execute(); - } catch (\PDOException $e) { - // A concurrent write won, let it be - } - } - } - - return $failed; - } - - private function getConnection(): \PDO - { - if (null === $this->conn) { - $this->conn = new \PDO($this->dsn, $this->username, $this->password, $this->connectionOptions); - $this->conn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); - } - if (null === $this->driver) { - $this->driver = $this->conn->getAttribute(\PDO::ATTR_DRIVER_NAME); - } - - return $this->conn; - } - - private function getServerVersion(): string - { - if (null === $this->serverVersion) { - $this->serverVersion = $this->conn->getAttribute(\PDO::ATTR_SERVER_VERSION); - } - - return $this->serverVersion; - } -} diff --git a/lib/symfony/cache/Adapter/PhpArrayAdapter.php b/lib/symfony/cache/Adapter/PhpArrayAdapter.php deleted file mode 100644 index 8c8fb9164..000000000 --- a/lib/symfony/cache/Adapter/PhpArrayAdapter.php +++ /dev/null @@ -1,435 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Psr\Cache\CacheItemInterface; -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\ResettableInterface; -use Symfony\Component\Cache\Traits\ContractsTrait; -use Symfony\Component\Cache\Traits\ProxyTrait; -use Symfony\Component\VarExporter\VarExporter; -use Symfony\Contracts\Cache\CacheInterface; - -/** - * Caches items at warm up time using a PHP array that is stored in shared memory by OPCache since PHP 7.0. - * Warmed up items are read-only and run-time discovered items are cached using a fallback adapter. - * - * @author Titouan Galopin <galopintitouan@gmail.com> - * @author Nicolas Grekas <p@tchwork.com> - */ -class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface -{ - use ContractsTrait; - use ProxyTrait; - - private $file; - private $keys; - private $values; - - private static $createCacheItem; - private static $valuesCache = []; - - /** - * @param string $file The PHP file were values are cached - * @param AdapterInterface $fallbackPool A pool to fallback on when an item is not hit - */ - public function __construct(string $file, AdapterInterface $fallbackPool) - { - $this->file = $file; - $this->pool = $fallbackPool; - self::$createCacheItem ?? self::$createCacheItem = \Closure::bind( - static function ($key, $value, $isHit) { - $item = new CacheItem(); - $item->key = $key; - $item->value = $value; - $item->isHit = $isHit; - - return $item; - }, - null, - CacheItem::class - ); - } - - /** - * This adapter takes advantage of how PHP stores arrays in its latest versions. - * - * @param string $file The PHP file were values are cached - * @param CacheItemPoolInterface $fallbackPool A pool to fallback on when an item is not hit - * - * @return CacheItemPoolInterface - */ - public static function create(string $file, CacheItemPoolInterface $fallbackPool) - { - if (!$fallbackPool instanceof AdapterInterface) { - $fallbackPool = new ProxyAdapter($fallbackPool); - } - - return new static($file, $fallbackPool); - } - - /** - * {@inheritdoc} - */ - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) - { - if (null === $this->values) { - $this->initialize(); - } - if (!isset($this->keys[$key])) { - get_from_pool: - if ($this->pool instanceof CacheInterface) { - return $this->pool->get($key, $callback, $beta, $metadata); - } - - return $this->doGet($this->pool, $key, $callback, $beta, $metadata); - } - $value = $this->values[$this->keys[$key]]; - - if ('N;' === $value) { - return null; - } - try { - if ($value instanceof \Closure) { - return $value(); - } - } catch (\Throwable $e) { - unset($this->keys[$key]); - goto get_from_pool; - } - - return $value; - } - - /** - * {@inheritdoc} - */ - public function getItem($key) - { - if (!\is_string($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', get_debug_type($key))); - } - if (null === $this->values) { - $this->initialize(); - } - if (!isset($this->keys[$key])) { - return $this->pool->getItem($key); - } - - $value = $this->values[$this->keys[$key]]; - $isHit = true; - - if ('N;' === $value) { - $value = null; - } elseif ($value instanceof \Closure) { - try { - $value = $value(); - } catch (\Throwable $e) { - $value = null; - $isHit = false; - } - } - - return (self::$createCacheItem)($key, $value, $isHit); - } - - /** - * {@inheritdoc} - */ - public function getItems(array $keys = []) - { - foreach ($keys as $key) { - if (!\is_string($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', get_debug_type($key))); - } - } - if (null === $this->values) { - $this->initialize(); - } - - return $this->generateItems($keys); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function hasItem($key) - { - if (!\is_string($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', get_debug_type($key))); - } - if (null === $this->values) { - $this->initialize(); - } - - return isset($this->keys[$key]) || $this->pool->hasItem($key); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItem($key) - { - if (!\is_string($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', get_debug_type($key))); - } - if (null === $this->values) { - $this->initialize(); - } - - return !isset($this->keys[$key]) && $this->pool->deleteItem($key); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItems(array $keys) - { - $deleted = true; - $fallbackKeys = []; - - foreach ($keys as $key) { - if (!\is_string($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', get_debug_type($key))); - } - - if (isset($this->keys[$key])) { - $deleted = false; - } else { - $fallbackKeys[] = $key; - } - } - if (null === $this->values) { - $this->initialize(); - } - - if ($fallbackKeys) { - $deleted = $this->pool->deleteItems($fallbackKeys) && $deleted; - } - - return $deleted; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function save(CacheItemInterface $item) - { - if (null === $this->values) { - $this->initialize(); - } - - return !isset($this->keys[$item->getKey()]) && $this->pool->save($item); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function saveDeferred(CacheItemInterface $item) - { - if (null === $this->values) { - $this->initialize(); - } - - return !isset($this->keys[$item->getKey()]) && $this->pool->saveDeferred($item); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function commit() - { - return $this->pool->commit(); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function clear(string $prefix = '') - { - $this->keys = $this->values = []; - - $cleared = @unlink($this->file) || !file_exists($this->file); - unset(self::$valuesCache[$this->file]); - - if ($this->pool instanceof AdapterInterface) { - return $this->pool->clear($prefix) && $cleared; - } - - return $this->pool->clear() && $cleared; - } - - /** - * Store an array of cached values. - * - * @param array $values The cached values - * - * @return string[] A list of classes to preload on PHP 7.4+ - */ - public function warmUp(array $values) - { - if (file_exists($this->file)) { - if (!is_file($this->file)) { - throw new InvalidArgumentException(sprintf('Cache path exists and is not a file: "%s".', $this->file)); - } - - if (!is_writable($this->file)) { - throw new InvalidArgumentException(sprintf('Cache file is not writable: "%s".', $this->file)); - } - } else { - $directory = \dirname($this->file); - - if (!is_dir($directory) && !@mkdir($directory, 0777, true)) { - throw new InvalidArgumentException(sprintf('Cache directory does not exist and cannot be created: "%s".', $directory)); - } - - if (!is_writable($directory)) { - throw new InvalidArgumentException(sprintf('Cache directory is not writable: "%s".', $directory)); - } - } - - $preload = []; - $dumpedValues = ''; - $dumpedMap = []; - $dump = <<<'EOF' -<?php - -// This file has been auto-generated by the Symfony Cache Component. - -return [[ - - -EOF; - - foreach ($values as $key => $value) { - CacheItem::validateKey(\is_int($key) ? (string) $key : $key); - $isStaticValue = true; - - if (null === $value) { - $value = "'N;'"; - } elseif (\is_object($value) || \is_array($value)) { - try { - $value = VarExporter::export($value, $isStaticValue, $preload); - } catch (\Exception $e) { - throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable "%s" value.', $key, get_debug_type($value)), 0, $e); - } - } elseif (\is_string($value)) { - // Wrap "N;" in a closure to not confuse it with an encoded `null` - if ('N;' === $value) { - $isStaticValue = false; - } - $value = var_export($value, true); - } elseif (!\is_scalar($value)) { - throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable "%s" value.', $key, get_debug_type($value))); - } else { - $value = var_export($value, true); - } - - if (!$isStaticValue) { - $value = str_replace("\n", "\n ", $value); - $value = "static function () {\n return {$value};\n}"; - } - $hash = hash('md5', $value); - - if (null === $id = $dumpedMap[$hash] ?? null) { - $id = $dumpedMap[$hash] = \count($dumpedMap); - $dumpedValues .= "{$id} => {$value},\n"; - } - - $dump .= var_export($key, true)." => {$id},\n"; - } - - $dump .= "\n], [\n\n{$dumpedValues}\n]];\n"; - - $tmpFile = uniqid($this->file, true); - - file_put_contents($tmpFile, $dump); - @chmod($tmpFile, 0666 & ~umask()); - unset($serialized, $value, $dump); - - @rename($tmpFile, $this->file); - unset(self::$valuesCache[$this->file]); - - $this->initialize(); - - return $preload; - } - - /** - * Load the cache file. - */ - private function initialize() - { - if (isset(self::$valuesCache[$this->file])) { - $values = self::$valuesCache[$this->file]; - } elseif (!is_file($this->file)) { - $this->keys = $this->values = []; - - return; - } else { - $values = self::$valuesCache[$this->file] = (include $this->file) ?: [[], []]; - } - - if (2 !== \count($values) || !isset($values[0], $values[1])) { - $this->keys = $this->values = []; - } else { - [$this->keys, $this->values] = $values; - } - } - - private function generateItems(array $keys): \Generator - { - $f = self::$createCacheItem; - $fallbackKeys = []; - - foreach ($keys as $key) { - if (isset($this->keys[$key])) { - $value = $this->values[$this->keys[$key]]; - - if ('N;' === $value) { - yield $key => $f($key, null, true); - } elseif ($value instanceof \Closure) { - try { - yield $key => $f($key, $value(), true); - } catch (\Throwable $e) { - yield $key => $f($key, null, false); - } - } else { - yield $key => $f($key, $value, true); - } - } else { - $fallbackKeys[] = $key; - } - } - - if ($fallbackKeys) { - yield from $this->pool->getItems($fallbackKeys); - } - } -} diff --git a/lib/symfony/cache/Adapter/PhpFilesAdapter.php b/lib/symfony/cache/Adapter/PhpFilesAdapter.php deleted file mode 100644 index 2fb08375a..000000000 --- a/lib/symfony/cache/Adapter/PhpFilesAdapter.php +++ /dev/null @@ -1,330 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Symfony\Component\Cache\Exception\CacheException; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\Traits\FilesystemCommonTrait; -use Symfony\Component\VarExporter\VarExporter; - -/** - * @author Piotr Stankowski <git@trakos.pl> - * @author Nicolas Grekas <p@tchwork.com> - * @author Rob Frawley 2nd <rmf@src.run> - */ -class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface -{ - use FilesystemCommonTrait { - doClear as private doCommonClear; - doDelete as private doCommonDelete; - } - - private $includeHandler; - private $appendOnly; - private $values = []; - private $files = []; - - private static $startTime; - private static $valuesCache = []; - - /** - * @param $appendOnly Set to `true` to gain extra performance when the items stored in this pool never expire. - * Doing so is encouraged because it fits perfectly OPcache's memory model. - * - * @throws CacheException if OPcache is not enabled - */ - public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, bool $appendOnly = false) - { - $this->appendOnly = $appendOnly; - self::$startTime = self::$startTime ?? $_SERVER['REQUEST_TIME'] ?? time(); - parent::__construct('', $defaultLifetime); - $this->init($namespace, $directory); - $this->includeHandler = static function ($type, $msg, $file, $line) { - throw new \ErrorException($msg, 0, $type, $file, $line); - }; - } - - public static function isSupported() - { - self::$startTime = self::$startTime ?? $_SERVER['REQUEST_TIME'] ?? time(); - - return \function_exists('opcache_invalidate') && filter_var(\ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) || filter_var(\ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOLEAN)); - } - - /** - * @return bool - */ - public function prune() - { - $time = time(); - $pruned = true; - $getExpiry = true; - - set_error_handler($this->includeHandler); - try { - foreach ($this->scanHashDir($this->directory) as $file) { - try { - if (\is_array($expiresAt = include $file)) { - $expiresAt = $expiresAt[0]; - } - } catch (\ErrorException $e) { - $expiresAt = $time; - } - - if ($time >= $expiresAt) { - $pruned = $this->doUnlink($file) && !file_exists($file) && $pruned; - } - } - } finally { - restore_error_handler(); - } - - return $pruned; - } - - /** - * {@inheritdoc} - */ - protected function doFetch(array $ids) - { - if ($this->appendOnly) { - $now = 0; - $missingIds = []; - } else { - $now = time(); - $missingIds = $ids; - $ids = []; - } - $values = []; - - begin: - $getExpiry = false; - - foreach ($ids as $id) { - if (null === $value = $this->values[$id] ?? null) { - $missingIds[] = $id; - } elseif ('N;' === $value) { - $values[$id] = null; - } elseif (!\is_object($value)) { - $values[$id] = $value; - } elseif (!$value instanceof LazyValue) { - $values[$id] = $value(); - } elseif (false === $values[$id] = include $value->file) { - unset($values[$id], $this->values[$id]); - $missingIds[] = $id; - } - if (!$this->appendOnly) { - unset($this->values[$id]); - } - } - - if (!$missingIds) { - return $values; - } - - set_error_handler($this->includeHandler); - try { - $getExpiry = true; - - foreach ($missingIds as $k => $id) { - try { - $file = $this->files[$id] ?? $this->files[$id] = $this->getFile($id); - - if (isset(self::$valuesCache[$file])) { - [$expiresAt, $this->values[$id]] = self::$valuesCache[$file]; - } elseif (\is_array($expiresAt = include $file)) { - if ($this->appendOnly) { - self::$valuesCache[$file] = $expiresAt; - } - - [$expiresAt, $this->values[$id]] = $expiresAt; - } elseif ($now < $expiresAt) { - $this->values[$id] = new LazyValue($file); - } - - if ($now >= $expiresAt) { - unset($this->values[$id], $missingIds[$k], self::$valuesCache[$file]); - } - } catch (\ErrorException $e) { - unset($missingIds[$k]); - } - } - } finally { - restore_error_handler(); - } - - $ids = $missingIds; - $missingIds = []; - goto begin; - } - - /** - * {@inheritdoc} - */ - protected function doHave(string $id) - { - if ($this->appendOnly && isset($this->values[$id])) { - return true; - } - - set_error_handler($this->includeHandler); - try { - $file = $this->files[$id] ?? $this->files[$id] = $this->getFile($id); - $getExpiry = true; - - if (isset(self::$valuesCache[$file])) { - [$expiresAt, $value] = self::$valuesCache[$file]; - } elseif (\is_array($expiresAt = include $file)) { - if ($this->appendOnly) { - self::$valuesCache[$file] = $expiresAt; - } - - [$expiresAt, $value] = $expiresAt; - } elseif ($this->appendOnly) { - $value = new LazyValue($file); - } - } catch (\ErrorException $e) { - return false; - } finally { - restore_error_handler(); - } - if ($this->appendOnly) { - $now = 0; - $this->values[$id] = $value; - } else { - $now = time(); - } - - return $now < $expiresAt; - } - - /** - * {@inheritdoc} - */ - protected function doSave(array $values, int $lifetime) - { - $ok = true; - $expiry = $lifetime ? time() + $lifetime : 'PHP_INT_MAX'; - $allowCompile = self::isSupported(); - - foreach ($values as $key => $value) { - unset($this->values[$key]); - $isStaticValue = true; - if (null === $value) { - $value = "'N;'"; - } elseif (\is_object($value) || \is_array($value)) { - try { - $value = VarExporter::export($value, $isStaticValue); - } catch (\Exception $e) { - throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable "%s" value.', $key, get_debug_type($value)), 0, $e); - } - } elseif (\is_string($value)) { - // Wrap "N;" in a closure to not confuse it with an encoded `null` - if ('N;' === $value) { - $isStaticValue = false; - } - $value = var_export($value, true); - } elseif (!\is_scalar($value)) { - throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable "%s" value.', $key, get_debug_type($value))); - } else { - $value = var_export($value, true); - } - - $encodedKey = rawurlencode($key); - - if ($isStaticValue) { - $value = "return [{$expiry}, {$value}];"; - } elseif ($this->appendOnly) { - $value = "return [{$expiry}, static function () { return {$value}; }];"; - } else { - // We cannot use a closure here because of https://bugs.php.net/76982 - $value = str_replace('\Symfony\Component\VarExporter\Internal\\', '', $value); - $value = "namespace Symfony\Component\VarExporter\Internal;\n\nreturn \$getExpiry ? {$expiry} : {$value};"; - } - - $file = $this->files[$key] = $this->getFile($key, true); - // Since OPcache only compiles files older than the script execution start, set the file's mtime in the past - $ok = $this->write($file, "<?php //{$encodedKey}\n\n{$value}\n", self::$startTime - 10) && $ok; - - if ($allowCompile) { - @opcache_invalidate($file, true); - @opcache_compile_file($file); - } - unset(self::$valuesCache[$file]); - } - - if (!$ok && !is_writable($this->directory)) { - throw new CacheException(sprintf('Cache directory is not writable (%s).', $this->directory)); - } - - return $ok; - } - - /** - * {@inheritdoc} - */ - protected function doClear(string $namespace) - { - $this->values = []; - - return $this->doCommonClear($namespace); - } - - /** - * {@inheritdoc} - */ - protected function doDelete(array $ids) - { - foreach ($ids as $id) { - unset($this->values[$id]); - } - - return $this->doCommonDelete($ids); - } - - protected function doUnlink(string $file) - { - unset(self::$valuesCache[$file]); - - if (self::isSupported()) { - @opcache_invalidate($file, true); - } - - return @unlink($file); - } - - private function getFileKey(string $file): string - { - if (!$h = @fopen($file, 'r')) { - return ''; - } - - $encodedKey = substr(fgets($h), 8); - fclose($h); - - return rawurldecode(rtrim($encodedKey)); - } -} - -/** - * @internal - */ -class LazyValue -{ - public $file; - - public function __construct(string $file) - { - $this->file = $file; - } -} diff --git a/lib/symfony/cache/Adapter/ProxyAdapter.php b/lib/symfony/cache/Adapter/ProxyAdapter.php deleted file mode 100644 index c715cade5..000000000 --- a/lib/symfony/cache/Adapter/ProxyAdapter.php +++ /dev/null @@ -1,268 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Psr\Cache\CacheItemInterface; -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\ResettableInterface; -use Symfony\Component\Cache\Traits\ContractsTrait; -use Symfony\Component\Cache\Traits\ProxyTrait; -use Symfony\Contracts\Cache\CacheInterface; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface -{ - use ContractsTrait; - use ProxyTrait; - - private $namespace = ''; - private $namespaceLen; - private $poolHash; - private $defaultLifetime; - - private static $createCacheItem; - private static $setInnerItem; - - public function __construct(CacheItemPoolInterface $pool, string $namespace = '', int $defaultLifetime = 0) - { - $this->pool = $pool; - $this->poolHash = $poolHash = spl_object_hash($pool); - if ('' !== $namespace) { - \assert('' !== CacheItem::validateKey($namespace)); - $this->namespace = $namespace; - } - $this->namespaceLen = \strlen($namespace); - $this->defaultLifetime = $defaultLifetime; - self::$createCacheItem ?? self::$createCacheItem = \Closure::bind( - static function ($key, $innerItem, $poolHash) { - $item = new CacheItem(); - $item->key = $key; - - if (null === $innerItem) { - return $item; - } - - $item->value = $v = $innerItem->get(); - $item->isHit = $innerItem->isHit(); - $item->innerItem = $innerItem; - $item->poolHash = $poolHash; - - // Detect wrapped values that encode for their expiry and creation duration - // For compactness, these values are packed in the key of an array using - // magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F - if (\is_array($v) && 1 === \count($v) && 10 === \strlen($k = (string) array_key_first($v)) && "\x9D" === $k[0] && "\0" === $k[5] && "\x5F" === $k[9]) { - $item->value = $v[$k]; - $v = unpack('Ve/Nc', substr($k, 1, -1)); - $item->metadata[CacheItem::METADATA_EXPIRY] = $v['e'] + CacheItem::METADATA_EXPIRY_OFFSET; - $item->metadata[CacheItem::METADATA_CTIME] = $v['c']; - } elseif ($innerItem instanceof CacheItem) { - $item->metadata = $innerItem->metadata; - } - $innerItem->set(null); - - return $item; - }, - null, - CacheItem::class - ); - self::$setInnerItem ?? self::$setInnerItem = \Closure::bind( - /** - * @param array $item A CacheItem cast to (array); accessing protected properties requires adding the "\0*\0" PHP prefix - */ - static function (CacheItemInterface $innerItem, array $item) { - // Tags are stored separately, no need to account for them when considering this item's newly set metadata - if (isset(($metadata = $item["\0*\0newMetadata"])[CacheItem::METADATA_TAGS])) { - unset($metadata[CacheItem::METADATA_TAGS]); - } - if ($metadata) { - // For compactness, expiry and creation duration are packed in the key of an array, using magic numbers as separators - $item["\0*\0value"] = ["\x9D".pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME])."\x5F" => $item["\0*\0value"]]; - } - $innerItem->set($item["\0*\0value"]); - $innerItem->expiresAt(null !== $item["\0*\0expiry"] ? \DateTime::createFromFormat('U.u', sprintf('%.6F', $item["\0*\0expiry"])) : null); - }, - null, - CacheItem::class - ); - } - - /** - * {@inheritdoc} - */ - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) - { - if (!$this->pool instanceof CacheInterface) { - return $this->doGet($this, $key, $callback, $beta, $metadata); - } - - return $this->pool->get($this->getId($key), function ($innerItem, bool &$save) use ($key, $callback) { - $item = (self::$createCacheItem)($key, $innerItem, $this->poolHash); - $item->set($value = $callback($item, $save)); - (self::$setInnerItem)($innerItem, (array) $item); - - return $value; - }, $beta, $metadata); - } - - /** - * {@inheritdoc} - */ - public function getItem($key) - { - $item = $this->pool->getItem($this->getId($key)); - - return (self::$createCacheItem)($key, $item, $this->poolHash); - } - - /** - * {@inheritdoc} - */ - public function getItems(array $keys = []) - { - if ($this->namespaceLen) { - foreach ($keys as $i => $key) { - $keys[$i] = $this->getId($key); - } - } - - return $this->generateItems($this->pool->getItems($keys)); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function hasItem($key) - { - return $this->pool->hasItem($this->getId($key)); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function clear(string $prefix = '') - { - if ($this->pool instanceof AdapterInterface) { - return $this->pool->clear($this->namespace.$prefix); - } - - return $this->pool->clear(); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItem($key) - { - return $this->pool->deleteItem($this->getId($key)); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItems(array $keys) - { - if ($this->namespaceLen) { - foreach ($keys as $i => $key) { - $keys[$i] = $this->getId($key); - } - } - - return $this->pool->deleteItems($keys); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function save(CacheItemInterface $item) - { - return $this->doSave($item, __FUNCTION__); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function saveDeferred(CacheItemInterface $item) - { - return $this->doSave($item, __FUNCTION__); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function commit() - { - return $this->pool->commit(); - } - - private function doSave(CacheItemInterface $item, string $method) - { - if (!$item instanceof CacheItem) { - return false; - } - $item = (array) $item; - if (null === $item["\0*\0expiry"] && 0 < $this->defaultLifetime) { - $item["\0*\0expiry"] = microtime(true) + $this->defaultLifetime; - } - - if ($item["\0*\0poolHash"] === $this->poolHash && $item["\0*\0innerItem"]) { - $innerItem = $item["\0*\0innerItem"]; - } elseif ($this->pool instanceof AdapterInterface) { - // this is an optimization specific for AdapterInterface implementations - // so we can save a round-trip to the backend by just creating a new item - $innerItem = (self::$createCacheItem)($this->namespace.$item["\0*\0key"], null, $this->poolHash); - } else { - $innerItem = $this->pool->getItem($this->namespace.$item["\0*\0key"]); - } - - (self::$setInnerItem)($innerItem, $item); - - return $this->pool->$method($innerItem); - } - - private function generateItems(iterable $items): \Generator - { - $f = self::$createCacheItem; - - foreach ($items as $key => $item) { - if ($this->namespaceLen) { - $key = substr($key, $this->namespaceLen); - } - - yield $key => $f($key, $item, $this->poolHash); - } - } - - private function getId($key): string - { - \assert('' !== CacheItem::validateKey($key)); - - return $this->namespace.$key; - } -} diff --git a/lib/symfony/cache/Adapter/Psr16Adapter.php b/lib/symfony/cache/Adapter/Psr16Adapter.php deleted file mode 100644 index a56aa3930..000000000 --- a/lib/symfony/cache/Adapter/Psr16Adapter.php +++ /dev/null @@ -1,86 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Psr\SimpleCache\CacheInterface; -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\ResettableInterface; -use Symfony\Component\Cache\Traits\ProxyTrait; - -/** - * Turns a PSR-16 cache into a PSR-6 one. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class Psr16Adapter extends AbstractAdapter implements PruneableInterface, ResettableInterface -{ - use ProxyTrait; - - /** - * @internal - */ - protected const NS_SEPARATOR = '_'; - - private $miss; - - public function __construct(CacheInterface $pool, string $namespace = '', int $defaultLifetime = 0) - { - parent::__construct($namespace, $defaultLifetime); - - $this->pool = $pool; - $this->miss = new \stdClass(); - } - - /** - * {@inheritdoc} - */ - protected function doFetch(array $ids) - { - foreach ($this->pool->getMultiple($ids, $this->miss) as $key => $value) { - if ($this->miss !== $value) { - yield $key => $value; - } - } - } - - /** - * {@inheritdoc} - */ - protected function doHave(string $id) - { - return $this->pool->has($id); - } - - /** - * {@inheritdoc} - */ - protected function doClear(string $namespace) - { - return $this->pool->clear(); - } - - /** - * {@inheritdoc} - */ - protected function doDelete(array $ids) - { - return $this->pool->deleteMultiple($ids); - } - - /** - * {@inheritdoc} - */ - protected function doSave(array $values, int $lifetime) - { - return $this->pool->setMultiple($values, 0 === $lifetime ? null : $lifetime); - } -} diff --git a/lib/symfony/cache/Adapter/RedisAdapter.php b/lib/symfony/cache/Adapter/RedisAdapter.php deleted file mode 100644 index eb5950e53..000000000 --- a/lib/symfony/cache/Adapter/RedisAdapter.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Symfony\Component\Cache\Marshaller\MarshallerInterface; -use Symfony\Component\Cache\Traits\RedisClusterProxy; -use Symfony\Component\Cache\Traits\RedisProxy; -use Symfony\Component\Cache\Traits\RedisTrait; - -class RedisAdapter extends AbstractAdapter -{ - use RedisTrait; - - /** - * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis The redis client - * @param string $namespace The default namespace - * @param int $defaultLifetime The default lifetime - */ - public function __construct($redis, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) - { - $this->init($redis, $namespace, $defaultLifetime, $marshaller); - } -} diff --git a/lib/symfony/cache/Adapter/RedisTagAwareAdapter.php b/lib/symfony/cache/Adapter/RedisTagAwareAdapter.php deleted file mode 100644 index 865491e19..000000000 --- a/lib/symfony/cache/Adapter/RedisTagAwareAdapter.php +++ /dev/null @@ -1,325 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Predis\Connection\Aggregate\ClusterInterface; -use Predis\Connection\Aggregate\PredisCluster; -use Predis\Connection\Aggregate\ReplicationInterface; -use Predis\Response\ErrorInterface; -use Predis\Response\Status; -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\Exception\LogicException; -use Symfony\Component\Cache\Marshaller\DeflateMarshaller; -use Symfony\Component\Cache\Marshaller\MarshallerInterface; -use Symfony\Component\Cache\Marshaller\TagAwareMarshaller; -use Symfony\Component\Cache\Traits\RedisClusterProxy; -use Symfony\Component\Cache\Traits\RedisProxy; -use Symfony\Component\Cache\Traits\RedisTrait; - -/** - * Stores tag id <> cache id relationship as a Redis Set. - * - * Set (tag relation info) is stored without expiry (non-volatile), while cache always gets an expiry (volatile) even - * if not set by caller. Thus if you configure redis with the right eviction policy you can be safe this tag <> cache - * relationship survives eviction (cache cleanup when Redis runs out of memory). - * - * Redis server 2.8+ with any `volatile-*` eviction policy, OR `noeviction` if you're sure memory will NEVER fill up - * - * Design limitations: - * - Max 4 billion cache keys per cache tag as limited by Redis Set datatype. - * E.g. If you use a "all" items tag for expiry instead of clear(), that limits you to 4 billion cache items also. - * - * @see https://redis.io/topics/lru-cache#eviction-policies Documentation for Redis eviction policies. - * @see https://redis.io/topics/data-types#sets Documentation for Redis Set datatype. - * - * @author Nicolas Grekas <p@tchwork.com> - * @author André Rømcke <andre.romcke+symfony@gmail.com> - */ -class RedisTagAwareAdapter extends AbstractTagAwareAdapter -{ - use RedisTrait; - - /** - * On cache items without a lifetime set, we set it to 100 days. This is to make sure cache items are - * preferred to be evicted over tag Sets, if eviction policy is configured according to requirements. - */ - private const DEFAULT_CACHE_TTL = 8640000; - - /** - * @var string|null detected eviction policy used on Redis server - */ - private $redisEvictionPolicy; - private $namespace; - - /** - * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis The redis client - * @param string $namespace The default namespace - * @param int $defaultLifetime The default lifetime - */ - public function __construct($redis, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) - { - if ($redis instanceof \Predis\ClientInterface && $redis->getConnection() instanceof ClusterInterface && !$redis->getConnection() instanceof PredisCluster) { - throw new InvalidArgumentException(sprintf('Unsupported Predis cluster connection: only "%s" is, "%s" given.', PredisCluster::class, get_debug_type($redis->getConnection()))); - } - - if (\defined('Redis::OPT_COMPRESSION') && ($redis instanceof \Redis || $redis instanceof \RedisArray || $redis instanceof \RedisCluster)) { - $compression = $redis->getOption(\Redis::OPT_COMPRESSION); - - foreach (\is_array($compression) ? $compression : [$compression] as $c) { - if (\Redis::COMPRESSION_NONE !== $c) { - throw new InvalidArgumentException(sprintf('phpredis compression must be disabled when using "%s", use "%s" instead.', static::class, DeflateMarshaller::class)); - } - } - } - - $this->init($redis, $namespace, $defaultLifetime, new TagAwareMarshaller($marshaller)); - $this->namespace = $namespace; - } - - /** - * {@inheritdoc} - */ - protected function doSave(array $values, int $lifetime, array $addTagData = [], array $delTagData = []): array - { - $eviction = $this->getRedisEvictionPolicy(); - if ('noeviction' !== $eviction && !str_starts_with($eviction, 'volatile-')) { - throw new LogicException(sprintf('Redis maxmemory-policy setting "%s" is *not* supported by RedisTagAwareAdapter, use "noeviction" or "volatile-*" eviction policies.', $eviction)); - } - - // serialize values - if (!$serialized = $this->marshaller->marshall($values, $failed)) { - return $failed; - } - - // While pipeline isn't supported on RedisCluster, other setups will at least benefit from doing this in one op - $results = $this->pipeline(static function () use ($serialized, $lifetime, $addTagData, $delTagData, $failed) { - // Store cache items, force a ttl if none is set, as there is no MSETEX we need to set each one - foreach ($serialized as $id => $value) { - yield 'setEx' => [ - $id, - 0 >= $lifetime ? self::DEFAULT_CACHE_TTL : $lifetime, - $value, - ]; - } - - // Add and Remove Tags - foreach ($addTagData as $tagId => $ids) { - if (!$failed || $ids = array_diff($ids, $failed)) { - yield 'sAdd' => array_merge([$tagId], $ids); - } - } - - foreach ($delTagData as $tagId => $ids) { - if (!$failed || $ids = array_diff($ids, $failed)) { - yield 'sRem' => array_merge([$tagId], $ids); - } - } - }); - - foreach ($results as $id => $result) { - // Skip results of SADD/SREM operations, they'll be 1 or 0 depending on if set value already existed or not - if (is_numeric($result)) { - continue; - } - // setEx results - if (true !== $result && (!$result instanceof Status || Status::get('OK') !== $result)) { - $failed[] = $id; - } - } - - return $failed; - } - - /** - * {@inheritdoc} - */ - protected function doDeleteYieldTags(array $ids): iterable - { - $lua = <<<'EOLUA' - local v = redis.call('GET', KEYS[1]) - local e = redis.pcall('UNLINK', KEYS[1]) - - if type(e) ~= 'number' then - redis.call('DEL', KEYS[1]) - end - - if not v or v:len() <= 13 or v:byte(1) ~= 0x9D or v:byte(6) ~= 0 or v:byte(10) ~= 0x5F then - return '' - end - - return v:sub(14, 13 + v:byte(13) + v:byte(12) * 256 + v:byte(11) * 65536) -EOLUA; - - $results = $this->pipeline(function () use ($ids, $lua) { - foreach ($ids as $id) { - yield 'eval' => $this->redis instanceof \Predis\ClientInterface ? [$lua, 1, $id] : [$lua, [$id], 1]; - } - }); - - foreach ($results as $id => $result) { - if ($result instanceof \RedisException || $result instanceof ErrorInterface) { - CacheItem::log($this->logger, 'Failed to delete key "{key}": '.$result->getMessage(), ['key' => substr($id, \strlen($this->namespace)), 'exception' => $result]); - - continue; - } - - try { - yield $id => !\is_string($result) || '' === $result ? [] : $this->marshaller->unmarshall($result); - } catch (\Exception $e) { - yield $id => []; - } - } - } - - /** - * {@inheritdoc} - */ - protected function doDeleteTagRelations(array $tagData): bool - { - $results = $this->pipeline(static function () use ($tagData) { - foreach ($tagData as $tagId => $idList) { - array_unshift($idList, $tagId); - yield 'sRem' => $idList; - } - }); - foreach ($results as $result) { - // no-op - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doInvalidate(array $tagIds): bool - { - // This script scans the set of items linked to tag: it empties the set - // and removes the linked items. When the set is still not empty after - // the scan, it means we're in cluster mode and that the linked items - // are on other nodes: we move the links to a temporary set and we - // gargage collect that set from the client side. - - $lua = <<<'EOLUA' - redis.replicate_commands() - - local cursor = '0' - local id = KEYS[1] - repeat - local result = redis.call('SSCAN', id, cursor, 'COUNT', 5000); - cursor = result[1]; - local rems = {} - - for _, v in ipairs(result[2]) do - local ok, _ = pcall(redis.call, 'DEL', ARGV[1]..v) - if ok then - table.insert(rems, v) - end - end - if 0 < #rems then - redis.call('SREM', id, unpack(rems)) - end - until '0' == cursor; - - redis.call('SUNIONSTORE', '{'..id..'}'..id, id) - redis.call('DEL', id) - - return redis.call('SSCAN', '{'..id..'}'..id, '0', 'COUNT', 5000) -EOLUA; - - $results = $this->pipeline(function () use ($tagIds, $lua) { - if ($this->redis instanceof \Predis\ClientInterface) { - $prefix = $this->redis->getOptions()->prefix ? $this->redis->getOptions()->prefix->getPrefix() : ''; - } elseif (\is_array($prefix = $this->redis->getOption(\Redis::OPT_PREFIX) ?? '')) { - $prefix = current($prefix); - } - - foreach ($tagIds as $id) { - yield 'eval' => $this->redis instanceof \Predis\ClientInterface ? [$lua, 1, $id, $prefix] : [$lua, [$id, $prefix], 1]; - } - }); - - $lua = <<<'EOLUA' - redis.replicate_commands() - - local id = KEYS[1] - local cursor = table.remove(ARGV) - redis.call('SREM', '{'..id..'}'..id, unpack(ARGV)) - - return redis.call('SSCAN', '{'..id..'}'..id, cursor, 'COUNT', 5000) -EOLUA; - - $success = true; - foreach ($results as $id => $values) { - if ($values instanceof \RedisException || $values instanceof ErrorInterface) { - CacheItem::log($this->logger, 'Failed to invalidate key "{key}": '.$values->getMessage(), ['key' => substr($id, \strlen($this->namespace)), 'exception' => $values]); - $success = false; - - continue; - } - - [$cursor, $ids] = $values; - - while ($ids || '0' !== $cursor) { - $this->doDelete($ids); - - $evalArgs = [$id, $cursor]; - array_splice($evalArgs, 1, 0, $ids); - - if ($this->redis instanceof \Predis\ClientInterface) { - array_unshift($evalArgs, $lua, 1); - } else { - $evalArgs = [$lua, $evalArgs, 1]; - } - - $results = $this->pipeline(function () use ($evalArgs) { - yield 'eval' => $evalArgs; - }); - - foreach ($results as [$cursor, $ids]) { - // no-op - } - } - } - - return $success; - } - - private function getRedisEvictionPolicy(): string - { - if (null !== $this->redisEvictionPolicy) { - return $this->redisEvictionPolicy; - } - - $hosts = $this->getHosts(); - $host = reset($hosts); - if ($host instanceof \Predis\Client && $host->getConnection() instanceof ReplicationInterface) { - // Predis supports info command only on the master in replication environments - $hosts = [$host->getClientFor('master')]; - } - - foreach ($hosts as $host) { - $info = $host->info('Memory'); - - if ($info instanceof ErrorInterface) { - continue; - } - - $info = $info['Memory'] ?? $info; - - return $this->redisEvictionPolicy = $info['maxmemory_policy']; - } - - return $this->redisEvictionPolicy = ''; - } -} diff --git a/lib/symfony/cache/Adapter/TagAwareAdapter.php b/lib/symfony/cache/Adapter/TagAwareAdapter.php deleted file mode 100644 index ff22e5a8a..000000000 --- a/lib/symfony/cache/Adapter/TagAwareAdapter.php +++ /dev/null @@ -1,428 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Psr\Cache\CacheItemInterface; -use Psr\Cache\InvalidArgumentException; -use Psr\Log\LoggerAwareInterface; -use Psr\Log\LoggerAwareTrait; -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\ResettableInterface; -use Symfony\Component\Cache\Traits\ContractsTrait; -use Symfony\Component\Cache\Traits\ProxyTrait; -use Symfony\Contracts\Cache\TagAwareCacheInterface; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface, PruneableInterface, ResettableInterface, LoggerAwareInterface -{ - use ContractsTrait; - use LoggerAwareTrait; - use ProxyTrait; - - public const TAGS_PREFIX = "\0tags\0"; - - private $deferred = []; - private $tags; - private $knownTagVersions = []; - private $knownTagVersionsTtl; - - private static $createCacheItem; - private static $setCacheItemTags; - private static $getTagsByKey; - private static $saveTags; - - public function __construct(AdapterInterface $itemsPool, AdapterInterface $tagsPool = null, float $knownTagVersionsTtl = 0.15) - { - $this->pool = $itemsPool; - $this->tags = $tagsPool ?: $itemsPool; - $this->knownTagVersionsTtl = $knownTagVersionsTtl; - self::$createCacheItem ?? self::$createCacheItem = \Closure::bind( - static function ($key, $value, CacheItem $protoItem) { - $item = new CacheItem(); - $item->key = $key; - $item->value = $value; - $item->expiry = $protoItem->expiry; - $item->poolHash = $protoItem->poolHash; - - return $item; - }, - null, - CacheItem::class - ); - self::$setCacheItemTags ?? self::$setCacheItemTags = \Closure::bind( - static function (CacheItem $item, $key, array &$itemTags) { - $item->isTaggable = true; - if (!$item->isHit) { - return $item; - } - if (isset($itemTags[$key])) { - foreach ($itemTags[$key] as $tag => $version) { - $item->metadata[CacheItem::METADATA_TAGS][$tag] = $tag; - } - unset($itemTags[$key]); - } else { - $item->value = null; - $item->isHit = false; - } - - return $item; - }, - null, - CacheItem::class - ); - self::$getTagsByKey ?? self::$getTagsByKey = \Closure::bind( - static function ($deferred) { - $tagsByKey = []; - foreach ($deferred as $key => $item) { - $tagsByKey[$key] = $item->newMetadata[CacheItem::METADATA_TAGS] ?? []; - $item->metadata = $item->newMetadata; - } - - return $tagsByKey; - }, - null, - CacheItem::class - ); - self::$saveTags ?? self::$saveTags = \Closure::bind( - static function (AdapterInterface $tagsAdapter, array $tags) { - ksort($tags); - - foreach ($tags as $v) { - $v->expiry = 0; - $tagsAdapter->saveDeferred($v); - } - - return $tagsAdapter->commit(); - }, - null, - CacheItem::class - ); - } - - /** - * {@inheritdoc} - */ - public function invalidateTags(array $tags) - { - $ids = []; - foreach ($tags as $tag) { - \assert('' !== CacheItem::validateKey($tag)); - unset($this->knownTagVersions[$tag]); - $ids[] = $tag.static::TAGS_PREFIX; - } - - return !$tags || $this->tags->deleteItems($ids); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function hasItem($key) - { - if (\is_string($key) && isset($this->deferred[$key])) { - $this->commit(); - } - - if (!$this->pool->hasItem($key)) { - return false; - } - - $itemTags = $this->pool->getItem(static::TAGS_PREFIX.$key); - - if (!$itemTags->isHit()) { - return false; - } - - if (!$itemTags = $itemTags->get()) { - return true; - } - - foreach ($this->getTagVersions([$itemTags]) as $tag => $version) { - if ($itemTags[$tag] !== $version) { - return false; - } - } - - return true; - } - - /** - * {@inheritdoc} - */ - public function getItem($key) - { - foreach ($this->getItems([$key]) as $item) { - return $item; - } - - return null; - } - - /** - * {@inheritdoc} - */ - public function getItems(array $keys = []) - { - $tagKeys = []; - $commit = false; - - foreach ($keys as $key) { - if ('' !== $key && \is_string($key)) { - $commit = $commit || isset($this->deferred[$key]); - $key = static::TAGS_PREFIX.$key; - $tagKeys[$key] = $key; - } - } - - if ($commit) { - $this->commit(); - } - - try { - $items = $this->pool->getItems($tagKeys + $keys); - } catch (InvalidArgumentException $e) { - $this->pool->getItems($keys); // Should throw an exception - - throw $e; - } - - return $this->generateItems($items, $tagKeys); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function clear(string $prefix = '') - { - if ('' !== $prefix) { - foreach ($this->deferred as $key => $item) { - if (str_starts_with($key, $prefix)) { - unset($this->deferred[$key]); - } - } - } else { - $this->deferred = []; - } - - if ($this->pool instanceof AdapterInterface) { - return $this->pool->clear($prefix); - } - - return $this->pool->clear(); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItem($key) - { - return $this->deleteItems([$key]); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItems(array $keys) - { - foreach ($keys as $key) { - if ('' !== $key && \is_string($key)) { - $keys[] = static::TAGS_PREFIX.$key; - } - } - - return $this->pool->deleteItems($keys); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function save(CacheItemInterface $item) - { - if (!$item instanceof CacheItem) { - return false; - } - $this->deferred[$item->getKey()] = $item; - - return $this->commit(); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function saveDeferred(CacheItemInterface $item) - { - if (!$item instanceof CacheItem) { - return false; - } - $this->deferred[$item->getKey()] = $item; - - return true; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function commit() - { - if (!$this->deferred) { - return true; - } - - $ok = true; - foreach ($this->deferred as $key => $item) { - if (!$this->pool->saveDeferred($item)) { - unset($this->deferred[$key]); - $ok = false; - } - } - - $items = $this->deferred; - $tagsByKey = (self::$getTagsByKey)($items); - $this->deferred = []; - - $tagVersions = $this->getTagVersions($tagsByKey); - $f = self::$createCacheItem; - - foreach ($tagsByKey as $key => $tags) { - $this->pool->saveDeferred($f(static::TAGS_PREFIX.$key, array_intersect_key($tagVersions, $tags), $items[$key])); - } - - return $this->pool->commit() && $ok; - } - - /** - * @return array - */ - public function __sleep() - { - throw new \BadMethodCallException('Cannot serialize '.__CLASS__); - } - - public function __wakeup() - { - throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); - } - - public function __destruct() - { - $this->commit(); - } - - private function generateItems(iterable $items, array $tagKeys): \Generator - { - $bufferedItems = $itemTags = []; - $f = self::$setCacheItemTags; - - foreach ($items as $key => $item) { - if (!$tagKeys) { - yield $key => $f($item, static::TAGS_PREFIX.$key, $itemTags); - continue; - } - if (!isset($tagKeys[$key])) { - $bufferedItems[$key] = $item; - continue; - } - - unset($tagKeys[$key]); - - if ($item->isHit()) { - $itemTags[$key] = $item->get() ?: []; - } - - if (!$tagKeys) { - $tagVersions = $this->getTagVersions($itemTags); - - foreach ($itemTags as $key => $tags) { - foreach ($tags as $tag => $version) { - if ($tagVersions[$tag] !== $version) { - unset($itemTags[$key]); - continue 2; - } - } - } - $tagVersions = $tagKeys = null; - - foreach ($bufferedItems as $key => $item) { - yield $key => $f($item, static::TAGS_PREFIX.$key, $itemTags); - } - $bufferedItems = null; - } - } - } - - private function getTagVersions(array $tagsByKey) - { - $tagVersions = []; - $fetchTagVersions = false; - - foreach ($tagsByKey as $tags) { - $tagVersions += $tags; - - foreach ($tags as $tag => $version) { - if ($tagVersions[$tag] !== $version) { - unset($this->knownTagVersions[$tag]); - } - } - } - - if (!$tagVersions) { - return []; - } - - $now = microtime(true); - $tags = []; - foreach ($tagVersions as $tag => $version) { - $tags[$tag.static::TAGS_PREFIX] = $tag; - if ($fetchTagVersions || ($this->knownTagVersions[$tag][1] ?? null) !== $version || $now - $this->knownTagVersions[$tag][0] >= $this->knownTagVersionsTtl) { - // reuse previously fetched tag versions up to the ttl - $fetchTagVersions = true; - } - } - - if (!$fetchTagVersions) { - return $tagVersions; - } - - $newTags = []; - $newVersion = null; - foreach ($this->tags->getItems(array_keys($tags)) as $tag => $version) { - if (!$version->isHit()) { - $newTags[$tag] = $version->set($newVersion ?? $newVersion = random_int(\PHP_INT_MIN, \PHP_INT_MAX)); - } - $tagVersions[$tag = $tags[$tag]] = $version->get(); - $this->knownTagVersions[$tag] = [$now, $tagVersions[$tag]]; - } - - if ($newTags) { - (self::$saveTags)($this->tags, $newTags); - } - - return $tagVersions; - } -} diff --git a/lib/symfony/cache/Adapter/TagAwareAdapterInterface.php b/lib/symfony/cache/Adapter/TagAwareAdapterInterface.php deleted file mode 100644 index afa18d3b5..000000000 --- a/lib/symfony/cache/Adapter/TagAwareAdapterInterface.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Psr\Cache\InvalidArgumentException; - -/** - * Interface for invalidating cached items using tags. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -interface TagAwareAdapterInterface extends AdapterInterface -{ - /** - * Invalidates cached items using tags. - * - * @param string[] $tags An array of tags to invalidate - * - * @return bool - * - * @throws InvalidArgumentException When $tags is not valid - */ - public function invalidateTags(array $tags); -} diff --git a/lib/symfony/cache/Adapter/TraceableAdapter.php b/lib/symfony/cache/Adapter/TraceableAdapter.php deleted file mode 100644 index 4b06557f8..000000000 --- a/lib/symfony/cache/Adapter/TraceableAdapter.php +++ /dev/null @@ -1,295 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Psr\Cache\CacheItemInterface; -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\ResettableInterface; -use Symfony\Contracts\Cache\CacheInterface; -use Symfony\Contracts\Service\ResetInterface; - -/** - * An adapter that collects data about all cache calls. - * - * @author Aaron Scherer <aequasi@gmail.com> - * @author Tobias Nyholm <tobias.nyholm@gmail.com> - * @author Nicolas Grekas <p@tchwork.com> - */ -class TraceableAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface -{ - protected $pool; - private $calls = []; - - public function __construct(AdapterInterface $pool) - { - $this->pool = $pool; - } - - /** - * {@inheritdoc} - */ - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) - { - if (!$this->pool instanceof CacheInterface) { - throw new \BadMethodCallException(sprintf('Cannot call "%s::get()": this class doesn\'t implement "%s".', get_debug_type($this->pool), CacheInterface::class)); - } - - $isHit = true; - $callback = function (CacheItem $item, bool &$save) use ($callback, &$isHit) { - $isHit = $item->isHit(); - - return $callback($item, $save); - }; - - $event = $this->start(__FUNCTION__); - try { - $value = $this->pool->get($key, $callback, $beta, $metadata); - $event->result[$key] = get_debug_type($value); - } finally { - $event->end = microtime(true); - } - if ($isHit) { - ++$event->hits; - } else { - ++$event->misses; - } - - return $value; - } - - /** - * {@inheritdoc} - */ - public function getItem($key) - { - $event = $this->start(__FUNCTION__); - try { - $item = $this->pool->getItem($key); - } finally { - $event->end = microtime(true); - } - if ($event->result[$key] = $item->isHit()) { - ++$event->hits; - } else { - ++$event->misses; - } - - return $item; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function hasItem($key) - { - $event = $this->start(__FUNCTION__); - try { - return $event->result[$key] = $this->pool->hasItem($key); - } finally { - $event->end = microtime(true); - } - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItem($key) - { - $event = $this->start(__FUNCTION__); - try { - return $event->result[$key] = $this->pool->deleteItem($key); - } finally { - $event->end = microtime(true); - } - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function save(CacheItemInterface $item) - { - $event = $this->start(__FUNCTION__); - try { - return $event->result[$item->getKey()] = $this->pool->save($item); - } finally { - $event->end = microtime(true); - } - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function saveDeferred(CacheItemInterface $item) - { - $event = $this->start(__FUNCTION__); - try { - return $event->result[$item->getKey()] = $this->pool->saveDeferred($item); - } finally { - $event->end = microtime(true); - } - } - - /** - * {@inheritdoc} - */ - public function getItems(array $keys = []) - { - $event = $this->start(__FUNCTION__); - try { - $result = $this->pool->getItems($keys); - } finally { - $event->end = microtime(true); - } - $f = function () use ($result, $event) { - $event->result = []; - foreach ($result as $key => $item) { - if ($event->result[$key] = $item->isHit()) { - ++$event->hits; - } else { - ++$event->misses; - } - yield $key => $item; - } - }; - - return $f(); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function clear(string $prefix = '') - { - $event = $this->start(__FUNCTION__); - try { - if ($this->pool instanceof AdapterInterface) { - return $event->result = $this->pool->clear($prefix); - } - - return $event->result = $this->pool->clear(); - } finally { - $event->end = microtime(true); - } - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItems(array $keys) - { - $event = $this->start(__FUNCTION__); - $event->result['keys'] = $keys; - try { - return $event->result['result'] = $this->pool->deleteItems($keys); - } finally { - $event->end = microtime(true); - } - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function commit() - { - $event = $this->start(__FUNCTION__); - try { - return $event->result = $this->pool->commit(); - } finally { - $event->end = microtime(true); - } - } - - /** - * {@inheritdoc} - */ - public function prune() - { - if (!$this->pool instanceof PruneableInterface) { - return false; - } - $event = $this->start(__FUNCTION__); - try { - return $event->result = $this->pool->prune(); - } finally { - $event->end = microtime(true); - } - } - - /** - * {@inheritdoc} - */ - public function reset() - { - if ($this->pool instanceof ResetInterface) { - $this->pool->reset(); - } - - $this->clearCalls(); - } - - /** - * {@inheritdoc} - */ - public function delete(string $key): bool - { - $event = $this->start(__FUNCTION__); - try { - return $event->result[$key] = $this->pool->deleteItem($key); - } finally { - $event->end = microtime(true); - } - } - - public function getCalls() - { - return $this->calls; - } - - public function clearCalls() - { - $this->calls = []; - } - - protected function start(string $name) - { - $this->calls[] = $event = new TraceableAdapterEvent(); - $event->name = $name; - $event->start = microtime(true); - - return $event; - } -} - -class TraceableAdapterEvent -{ - public $name; - public $start; - public $end; - public $result; - public $hits = 0; - public $misses = 0; -} diff --git a/lib/symfony/cache/Adapter/TraceableTagAwareAdapter.php b/lib/symfony/cache/Adapter/TraceableTagAwareAdapter.php deleted file mode 100644 index 69461b8b6..000000000 --- a/lib/symfony/cache/Adapter/TraceableTagAwareAdapter.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Symfony\Contracts\Cache\TagAwareCacheInterface; - -/** - * @author Robin Chalas <robin.chalas@gmail.com> - */ -class TraceableTagAwareAdapter extends TraceableAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface -{ - public function __construct(TagAwareAdapterInterface $pool) - { - parent::__construct($pool); - } - - /** - * {@inheritdoc} - */ - public function invalidateTags(array $tags) - { - $event = $this->start(__FUNCTION__); - try { - return $event->result = $this->pool->invalidateTags($tags); - } finally { - $event->end = microtime(true); - } - } -} diff --git a/lib/symfony/cache/CHANGELOG.md b/lib/symfony/cache/CHANGELOG.md deleted file mode 100644 index 60a862740..000000000 --- a/lib/symfony/cache/CHANGELOG.md +++ /dev/null @@ -1,108 +0,0 @@ -CHANGELOG -========= - -5.4 ---- - - * Deprecate `DoctrineProvider` and `DoctrineAdapter` because these classes have been added to the `doctrine/cache` package - * Add `DoctrineDbalAdapter` identical to `PdoAdapter` for `Doctrine\DBAL\Connection` or DBAL URL - * Deprecate usage of `PdoAdapter` with `Doctrine\DBAL\Connection` or DBAL URL - -5.3 ---- - - * added support for connecting to Redis Sentinel clusters when using the Redis PHP extension - * add support for a custom serializer to the `ApcuAdapter` class - -5.2.0 ------ - - * added integration with Messenger to allow computing cached values in a worker - * allow ISO 8601 time intervals to specify default lifetime - -5.1.0 ------ - - * added max-items + LRU + max-lifetime capabilities to `ArrayCache` - * added `CouchbaseBucketAdapter` - * added context `cache-adapter` to log messages - -5.0.0 ------ - - * removed all PSR-16 implementations in the `Simple` namespace - * removed `SimpleCacheAdapter` - * removed `AbstractAdapter::unserialize()` - * removed `CacheItem::getPreviousTags()` - -4.4.0 ------ - - * added support for connecting to Redis Sentinel clusters - * added argument `$prefix` to `AdapterInterface::clear()` - * improved `RedisTagAwareAdapter` to support Redis server >= 2.8 and up to 4B items per tag - * added `TagAwareMarshaller` for optimized data storage when using `AbstractTagAwareAdapter` - * added `DeflateMarshaller` to compress serialized values - * removed support for phpredis 4 `compression` - * [BC BREAK] `RedisTagAwareAdapter` is not compatible with `RedisCluster` from `Predis` anymore, use `phpredis` instead - * Marked the `CacheDataCollector` class as `@final`. - * added `SodiumMarshaller` to encrypt/decrypt values using libsodium - -4.3.0 ------ - - * removed `psr/simple-cache` dependency, run `composer require psr/simple-cache` if you need it - * deprecated all PSR-16 adapters, use `Psr16Cache` or `Symfony\Contracts\Cache\CacheInterface` implementations instead - * deprecated `SimpleCacheAdapter`, use `Psr16Adapter` instead - -4.2.0 ------ - - * added support for connecting to Redis clusters via DSN - * added support for configuring multiple Memcached servers via DSN - * added `MarshallerInterface` and `DefaultMarshaller` to allow changing the serializer and provide one that automatically uses igbinary when available - * implemented `CacheInterface`, which provides stampede protection via probabilistic early expiration and should become the preferred way to use a cache - * added sub-second expiry accuracy for backends that support it - * added support for phpredis 4 `compression` and `tcp_keepalive` options - * added automatic table creation when using Doctrine DBAL with PDO-based backends - * throw `LogicException` when `CacheItem::tag()` is called on an item coming from a non tag-aware pool - * deprecated `CacheItem::getPreviousTags()`, use `CacheItem::getMetadata()` instead - * deprecated the `AbstractAdapter::unserialize()` and `AbstractCache::unserialize()` methods - * added `CacheCollectorPass` (originally in `FrameworkBundle`) - * added `CachePoolClearerPass` (originally in `FrameworkBundle`) - * added `CachePoolPass` (originally in `FrameworkBundle`) - * added `CachePoolPrunerPass` (originally in `FrameworkBundle`) - -3.4.0 ------ - - * added using options from Memcached DSN - * added PruneableInterface so PSR-6 or PSR-16 cache implementations can declare support for manual stale cache pruning - * added prune logic to FilesystemTrait, PhpFilesTrait, PdoTrait, TagAwareAdapter and ChainTrait - * now FilesystemAdapter, PhpFilesAdapter, FilesystemCache, PhpFilesCache, PdoAdapter, PdoCache, ChainAdapter, and - ChainCache implement PruneableInterface and support manual stale cache pruning - -3.3.0 ------ - - * added CacheItem::getPreviousTags() to get bound tags coming from the pool storage if any - * added PSR-16 "Simple Cache" implementations for all existing PSR-6 adapters - * added Psr6Cache and SimpleCacheAdapter for bidirectional interoperability between PSR-6 and PSR-16 - * added MemcachedAdapter (PSR-6) and MemcachedCache (PSR-16) - * added TraceableAdapter (PSR-6) and TraceableCache (PSR-16) - -3.2.0 ------ - - * added TagAwareAdapter for tags-based invalidation - * added PdoAdapter with PDO and Doctrine DBAL support - * added PhpArrayAdapter and PhpFilesAdapter for OPcache-backed shared memory storage (PHP 7+ only) - * added NullAdapter - -3.1.0 ------ - - * added the component with strict PSR-6 implementations - * added ApcuAdapter, ArrayAdapter, FilesystemAdapter and RedisAdapter - * added AbstractAdapter, ChainAdapter and ProxyAdapter - * added DoctrineAdapter and DoctrineProvider for bidirectional interoperability with Doctrine Cache diff --git a/lib/symfony/cache/CacheItem.php b/lib/symfony/cache/CacheItem.php deleted file mode 100644 index 091d9e9b8..000000000 --- a/lib/symfony/cache/CacheItem.php +++ /dev/null @@ -1,192 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache; - -use Psr\Log\LoggerInterface; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\Exception\LogicException; -use Symfony\Contracts\Cache\ItemInterface; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -final class CacheItem implements ItemInterface -{ - private const METADATA_EXPIRY_OFFSET = 1527506807; - - protected $key; - protected $value; - protected $isHit = false; - protected $expiry; - protected $metadata = []; - protected $newMetadata = []; - protected $innerItem; - protected $poolHash; - protected $isTaggable = false; - - /** - * {@inheritdoc} - */ - public function getKey(): string - { - return $this->key; - } - - /** - * {@inheritdoc} - * - * @return mixed - */ - public function get() - { - return $this->value; - } - - /** - * {@inheritdoc} - */ - public function isHit(): bool - { - return $this->isHit; - } - - /** - * {@inheritdoc} - * - * @return $this - */ - public function set($value): self - { - $this->value = $value; - - return $this; - } - - /** - * {@inheritdoc} - * - * @return $this - */ - public function expiresAt($expiration): self - { - if (null === $expiration) { - $this->expiry = null; - } elseif ($expiration instanceof \DateTimeInterface) { - $this->expiry = (float) $expiration->format('U.u'); - } else { - throw new InvalidArgumentException(sprintf('Expiration date must implement DateTimeInterface or be null, "%s" given.', get_debug_type($expiration))); - } - - return $this; - } - - /** - * {@inheritdoc} - * - * @return $this - */ - public function expiresAfter($time): self - { - if (null === $time) { - $this->expiry = null; - } elseif ($time instanceof \DateInterval) { - $this->expiry = microtime(true) + \DateTime::createFromFormat('U', 0)->add($time)->format('U.u'); - } elseif (\is_int($time)) { - $this->expiry = $time + microtime(true); - } else { - throw new InvalidArgumentException(sprintf('Expiration date must be an integer, a DateInterval or null, "%s" given.', get_debug_type($time))); - } - - return $this; - } - - /** - * {@inheritdoc} - */ - public function tag($tags): ItemInterface - { - if (!$this->isTaggable) { - throw new LogicException(sprintf('Cache item "%s" comes from a non tag-aware pool: you cannot tag it.', $this->key)); - } - if (!is_iterable($tags)) { - $tags = [$tags]; - } - foreach ($tags as $tag) { - if (!\is_string($tag) && !(\is_object($tag) && method_exists($tag, '__toString'))) { - throw new InvalidArgumentException(sprintf('Cache tag must be string or object that implements __toString(), "%s" given.', \is_object($tag) ? \get_class($tag) : \gettype($tag))); - } - $tag = (string) $tag; - if (isset($this->newMetadata[self::METADATA_TAGS][$tag])) { - continue; - } - if ('' === $tag) { - throw new InvalidArgumentException('Cache tag length must be greater than zero.'); - } - if (false !== strpbrk($tag, self::RESERVED_CHARACTERS)) { - throw new InvalidArgumentException(sprintf('Cache tag "%s" contains reserved characters "%s".', $tag, self::RESERVED_CHARACTERS)); - } - $this->newMetadata[self::METADATA_TAGS][$tag] = $tag; - } - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getMetadata(): array - { - return $this->metadata; - } - - /** - * Validates a cache key according to PSR-6. - * - * @param mixed $key The key to validate - * - * @throws InvalidArgumentException When $key is not valid - */ - public static function validateKey($key): string - { - if (!\is_string($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', get_debug_type($key))); - } - if ('' === $key) { - throw new InvalidArgumentException('Cache key length must be greater than zero.'); - } - if (false !== strpbrk($key, self::RESERVED_CHARACTERS)) { - throw new InvalidArgumentException(sprintf('Cache key "%s" contains reserved characters "%s".', $key, self::RESERVED_CHARACTERS)); - } - - return $key; - } - - /** - * Internal logging helper. - * - * @internal - */ - public static function log(?LoggerInterface $logger, string $message, array $context = []) - { - if ($logger) { - $logger->warning($message, $context); - } else { - $replace = []; - foreach ($context as $k => $v) { - if (\is_scalar($v)) { - $replace['{'.$k.'}'] = $v; - } - } - @trigger_error(strtr($message, $replace), \E_USER_WARNING); - } - } -} diff --git a/lib/symfony/cache/DataCollector/CacheDataCollector.php b/lib/symfony/cache/DataCollector/CacheDataCollector.php deleted file mode 100644 index 9590436dc..000000000 --- a/lib/symfony/cache/DataCollector/CacheDataCollector.php +++ /dev/null @@ -1,185 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\DataCollector; - -use Symfony\Component\Cache\Adapter\TraceableAdapter; -use Symfony\Component\Cache\Adapter\TraceableAdapterEvent; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\DataCollector\DataCollector; -use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; - -/** - * @author Aaron Scherer <aequasi@gmail.com> - * @author Tobias Nyholm <tobias.nyholm@gmail.com> - * - * @final - */ -class CacheDataCollector extends DataCollector implements LateDataCollectorInterface -{ - /** - * @var TraceableAdapter[] - */ - private $instances = []; - - public function addInstance(string $name, TraceableAdapter $instance) - { - $this->instances[$name] = $instance; - } - - /** - * {@inheritdoc} - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - $empty = ['calls' => [], 'config' => [], 'options' => [], 'statistics' => []]; - $this->data = ['instances' => $empty, 'total' => $empty]; - foreach ($this->instances as $name => $instance) { - $this->data['instances']['calls'][$name] = $instance->getCalls(); - } - - $this->data['instances']['statistics'] = $this->calculateStatistics(); - $this->data['total']['statistics'] = $this->calculateTotalStatistics(); - } - - public function reset() - { - $this->data = []; - foreach ($this->instances as $instance) { - $instance->clearCalls(); - } - } - - public function lateCollect() - { - $this->data['instances']['calls'] = $this->cloneVar($this->data['instances']['calls']); - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'cache'; - } - - /** - * Method returns amount of logged Cache reads: "get" calls. - */ - public function getStatistics(): array - { - return $this->data['instances']['statistics']; - } - - /** - * Method returns the statistic totals. - */ - public function getTotals(): array - { - return $this->data['total']['statistics']; - } - - /** - * Method returns all logged Cache call objects. - * - * @return mixed - */ - public function getCalls() - { - return $this->data['instances']['calls']; - } - - private function calculateStatistics(): array - { - $statistics = []; - foreach ($this->data['instances']['calls'] as $name => $calls) { - $statistics[$name] = [ - 'calls' => 0, - 'time' => 0, - 'reads' => 0, - 'writes' => 0, - 'deletes' => 0, - 'hits' => 0, - 'misses' => 0, - ]; - /** @var TraceableAdapterEvent $call */ - foreach ($calls as $call) { - ++$statistics[$name]['calls']; - $statistics[$name]['time'] += $call->end - $call->start; - if ('get' === $call->name) { - ++$statistics[$name]['reads']; - if ($call->hits) { - ++$statistics[$name]['hits']; - } else { - ++$statistics[$name]['misses']; - ++$statistics[$name]['writes']; - } - } elseif ('getItem' === $call->name) { - ++$statistics[$name]['reads']; - if ($call->hits) { - ++$statistics[$name]['hits']; - } else { - ++$statistics[$name]['misses']; - } - } elseif ('getItems' === $call->name) { - $statistics[$name]['reads'] += $call->hits + $call->misses; - $statistics[$name]['hits'] += $call->hits; - $statistics[$name]['misses'] += $call->misses; - } elseif ('hasItem' === $call->name) { - ++$statistics[$name]['reads']; - if (false === $call->result) { - ++$statistics[$name]['misses']; - } else { - ++$statistics[$name]['hits']; - } - } elseif ('save' === $call->name) { - ++$statistics[$name]['writes']; - } elseif ('deleteItem' === $call->name) { - ++$statistics[$name]['deletes']; - } - } - if ($statistics[$name]['reads']) { - $statistics[$name]['hit_read_ratio'] = round(100 * $statistics[$name]['hits'] / $statistics[$name]['reads'], 2); - } else { - $statistics[$name]['hit_read_ratio'] = null; - } - } - - return $statistics; - } - - private function calculateTotalStatistics(): array - { - $statistics = $this->getStatistics(); - $totals = [ - 'calls' => 0, - 'time' => 0, - 'reads' => 0, - 'writes' => 0, - 'deletes' => 0, - 'hits' => 0, - 'misses' => 0, - ]; - foreach ($statistics as $name => $values) { - foreach ($totals as $key => $value) { - $totals[$key] += $statistics[$name][$key]; - } - } - if ($totals['reads']) { - $totals['hit_read_ratio'] = round(100 * $totals['hits'] / $totals['reads'], 2); - } else { - $totals['hit_read_ratio'] = null; - } - - return $totals; - } -} diff --git a/lib/symfony/cache/DependencyInjection/CacheCollectorPass.php b/lib/symfony/cache/DependencyInjection/CacheCollectorPass.php deleted file mode 100644 index 843232e44..000000000 --- a/lib/symfony/cache/DependencyInjection/CacheCollectorPass.php +++ /dev/null @@ -1,94 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\DependencyInjection; - -use Symfony\Component\Cache\Adapter\TagAwareAdapterInterface; -use Symfony\Component\Cache\Adapter\TraceableAdapter; -use Symfony\Component\Cache\Adapter\TraceableTagAwareAdapter; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Inject a data collector to all the cache services to be able to get detailed statistics. - * - * @author Tobias Nyholm <tobias.nyholm@gmail.com> - */ -class CacheCollectorPass implements CompilerPassInterface -{ - private $dataCollectorCacheId; - private $cachePoolTag; - private $cachePoolRecorderInnerSuffix; - - public function __construct(string $dataCollectorCacheId = 'data_collector.cache', string $cachePoolTag = 'cache.pool', string $cachePoolRecorderInnerSuffix = '.recorder_inner') - { - if (0 < \func_num_args()) { - trigger_deprecation('symfony/cache', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->dataCollectorCacheId = $dataCollectorCacheId; - $this->cachePoolTag = $cachePoolTag; - $this->cachePoolRecorderInnerSuffix = $cachePoolRecorderInnerSuffix; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition($this->dataCollectorCacheId)) { - return; - } - - foreach ($container->findTaggedServiceIds($this->cachePoolTag) as $id => $attributes) { - $poolName = $attributes[0]['name'] ?? $id; - - $this->addToCollector($id, $poolName, $container); - } - } - - private function addToCollector(string $id, string $name, ContainerBuilder $container) - { - $definition = $container->getDefinition($id); - if ($definition->isAbstract()) { - return; - } - - $collectorDefinition = $container->getDefinition($this->dataCollectorCacheId); - $recorder = new Definition(is_subclass_of($definition->getClass(), TagAwareAdapterInterface::class) ? TraceableTagAwareAdapter::class : TraceableAdapter::class); - $recorder->setTags($definition->getTags()); - if (!$definition->isPublic() || !$definition->isPrivate()) { - $recorder->setPublic($definition->isPublic()); - } - $recorder->setArguments([new Reference($innerId = $id.$this->cachePoolRecorderInnerSuffix)]); - - foreach ($definition->getMethodCalls() as [$method, $args]) { - if ('setCallbackWrapper' !== $method || !$args[0] instanceof Definition || !($args[0]->getArguments()[2] ?? null) instanceof Definition) { - continue; - } - if ([new Reference($id), 'setCallbackWrapper'] == $args[0]->getArguments()[2]->getFactory()) { - $args[0]->getArguments()[2]->setFactory([new Reference($innerId), 'setCallbackWrapper']); - } - } - - $definition->setTags([]); - $definition->setPublic(false); - - $container->setDefinition($innerId, $definition); - $container->setDefinition($id, $recorder); - - // Tell the collector to add the new instance - $collectorDefinition->addMethodCall('addInstance', [$name, new Reference($id)]); - $collectorDefinition->setPublic(false); - } -} diff --git a/lib/symfony/cache/DependencyInjection/CachePoolClearerPass.php b/lib/symfony/cache/DependencyInjection/CachePoolClearerPass.php deleted file mode 100644 index c9b04adda..000000000 --- a/lib/symfony/cache/DependencyInjection/CachePoolClearerPass.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\DependencyInjection; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class CachePoolClearerPass implements CompilerPassInterface -{ - private $cachePoolClearerTag; - - public function __construct(string $cachePoolClearerTag = 'cache.pool.clearer') - { - if (0 < \func_num_args()) { - trigger_deprecation('symfony/cache', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->cachePoolClearerTag = $cachePoolClearerTag; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - $container->getParameterBag()->remove('cache.prefix.seed'); - - foreach ($container->findTaggedServiceIds($this->cachePoolClearerTag) as $id => $attr) { - $clearer = $container->getDefinition($id); - $pools = []; - foreach ($clearer->getArgument(0) as $name => $ref) { - if ($container->hasDefinition($ref)) { - $pools[$name] = new Reference($ref); - } - } - $clearer->replaceArgument(0, $pools); - } - } -} diff --git a/lib/symfony/cache/DependencyInjection/CachePoolPass.php b/lib/symfony/cache/DependencyInjection/CachePoolPass.php deleted file mode 100644 index 14ac2bde4..000000000 --- a/lib/symfony/cache/DependencyInjection/CachePoolPass.php +++ /dev/null @@ -1,274 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\DependencyInjection; - -use Symfony\Component\Cache\Adapter\AbstractAdapter; -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\ChainAdapter; -use Symfony\Component\Cache\Adapter\NullAdapter; -use Symfony\Component\Cache\Adapter\ParameterNormalizer; -use Symfony\Component\Cache\Messenger\EarlyExpirationDispatcher; -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class CachePoolPass implements CompilerPassInterface -{ - private $cachePoolTag; - private $kernelResetTag; - private $cacheClearerId; - private $cachePoolClearerTag; - private $cacheSystemClearerId; - private $cacheSystemClearerTag; - private $reverseContainerId; - private $reversibleTag; - private $messageHandlerId; - - public function __construct(string $cachePoolTag = 'cache.pool', string $kernelResetTag = 'kernel.reset', string $cacheClearerId = 'cache.global_clearer', string $cachePoolClearerTag = 'cache.pool.clearer', string $cacheSystemClearerId = 'cache.system_clearer', string $cacheSystemClearerTag = 'kernel.cache_clearer', string $reverseContainerId = 'reverse_container', string $reversibleTag = 'container.reversible', string $messageHandlerId = 'cache.early_expiration_handler') - { - if (0 < \func_num_args()) { - trigger_deprecation('symfony/cache', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->cachePoolTag = $cachePoolTag; - $this->kernelResetTag = $kernelResetTag; - $this->cacheClearerId = $cacheClearerId; - $this->cachePoolClearerTag = $cachePoolClearerTag; - $this->cacheSystemClearerId = $cacheSystemClearerId; - $this->cacheSystemClearerTag = $cacheSystemClearerTag; - $this->reverseContainerId = $reverseContainerId; - $this->reversibleTag = $reversibleTag; - $this->messageHandlerId = $messageHandlerId; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - if ($container->hasParameter('cache.prefix.seed')) { - $seed = $container->getParameterBag()->resolveValue($container->getParameter('cache.prefix.seed')); - } else { - $seed = '_'.$container->getParameter('kernel.project_dir'); - $seed .= '.'.$container->getParameter('kernel.container_class'); - } - - $needsMessageHandler = false; - $allPools = []; - $clearers = []; - $attributes = [ - 'provider', - 'name', - 'namespace', - 'default_lifetime', - 'early_expiration_message_bus', - 'reset', - ]; - foreach ($container->findTaggedServiceIds($this->cachePoolTag) as $id => $tags) { - $adapter = $pool = $container->getDefinition($id); - if ($pool->isAbstract()) { - continue; - } - $class = $adapter->getClass(); - while ($adapter instanceof ChildDefinition) { - $adapter = $container->findDefinition($adapter->getParent()); - $class = $class ?: $adapter->getClass(); - if ($t = $adapter->getTag($this->cachePoolTag)) { - $tags[0] += $t[0]; - } - } - $name = $tags[0]['name'] ?? $id; - if (!isset($tags[0]['namespace'])) { - $namespaceSeed = $seed; - if (null !== $class) { - $namespaceSeed .= '.'.$class; - } - - $tags[0]['namespace'] = $this->getNamespace($namespaceSeed, $name); - } - if (isset($tags[0]['clearer'])) { - $clearer = $tags[0]['clearer']; - while ($container->hasAlias($clearer)) { - $clearer = (string) $container->getAlias($clearer); - } - } else { - $clearer = null; - } - unset($tags[0]['clearer'], $tags[0]['name']); - - if (isset($tags[0]['provider'])) { - $tags[0]['provider'] = new Reference(static::getServiceProvider($container, $tags[0]['provider'])); - } - - if (ChainAdapter::class === $class) { - $adapters = []; - foreach ($adapter->getArgument(0) as $provider => $adapter) { - if ($adapter instanceof ChildDefinition) { - $chainedPool = $adapter; - } else { - $chainedPool = $adapter = new ChildDefinition($adapter); - } - - $chainedTags = [\is_int($provider) ? [] : ['provider' => $provider]]; - $chainedClass = ''; - - while ($adapter instanceof ChildDefinition) { - $adapter = $container->findDefinition($adapter->getParent()); - $chainedClass = $chainedClass ?: $adapter->getClass(); - if ($t = $adapter->getTag($this->cachePoolTag)) { - $chainedTags[0] += $t[0]; - } - } - - if (ChainAdapter::class === $chainedClass) { - throw new InvalidArgumentException(sprintf('Invalid service "%s": chain of adapters cannot reference another chain, found "%s".', $id, $chainedPool->getParent())); - } - - $i = 0; - - if (isset($chainedTags[0]['provider'])) { - $chainedPool->replaceArgument($i++, new Reference(static::getServiceProvider($container, $chainedTags[0]['provider']))); - } - - if (isset($tags[0]['namespace']) && !\in_array($adapter->getClass(), [ArrayAdapter::class, NullAdapter::class], true)) { - $chainedPool->replaceArgument($i++, $tags[0]['namespace']); - } - - if (isset($tags[0]['default_lifetime'])) { - $chainedPool->replaceArgument($i++, $tags[0]['default_lifetime']); - } - - $adapters[] = $chainedPool; - } - - $pool->replaceArgument(0, $adapters); - unset($tags[0]['provider'], $tags[0]['namespace']); - $i = 1; - } else { - $i = 0; - } - - foreach ($attributes as $attr) { - if (!isset($tags[0][$attr])) { - // no-op - } elseif ('reset' === $attr) { - if ($tags[0][$attr]) { - $pool->addTag($this->kernelResetTag, ['method' => $tags[0][$attr]]); - } - } elseif ('early_expiration_message_bus' === $attr) { - $needsMessageHandler = true; - $pool->addMethodCall('setCallbackWrapper', [(new Definition(EarlyExpirationDispatcher::class)) - ->addArgument(new Reference($tags[0]['early_expiration_message_bus'])) - ->addArgument(new Reference($this->reverseContainerId)) - ->addArgument((new Definition('callable')) - ->setFactory([new Reference($id), 'setCallbackWrapper']) - ->addArgument(null) - ), - ]); - $pool->addTag($this->reversibleTag); - } elseif ('namespace' !== $attr || !\in_array($class, [ArrayAdapter::class, NullAdapter::class], true)) { - $argument = $tags[0][$attr]; - - if ('default_lifetime' === $attr && !is_numeric($argument)) { - $argument = (new Definition('int', [$argument])) - ->setFactory([ParameterNormalizer::class, 'normalizeDuration']); - } - - $pool->replaceArgument($i++, $argument); - } - unset($tags[0][$attr]); - } - if (!empty($tags[0])) { - throw new InvalidArgumentException(sprintf('Invalid "%s" tag for service "%s": accepted attributes are "clearer", "provider", "name", "namespace", "default_lifetime", "early_expiration_message_bus" and "reset", found "%s".', $this->cachePoolTag, $id, implode('", "', array_keys($tags[0])))); - } - - if (null !== $clearer) { - $clearers[$clearer][$name] = new Reference($id, $container::IGNORE_ON_UNINITIALIZED_REFERENCE); - } - - $allPools[$name] = new Reference($id, $container::IGNORE_ON_UNINITIALIZED_REFERENCE); - } - - if (!$needsMessageHandler) { - $container->removeDefinition($this->messageHandlerId); - } - - $notAliasedCacheClearerId = $this->cacheClearerId; - while ($container->hasAlias($this->cacheClearerId)) { - $this->cacheClearerId = (string) $container->getAlias($this->cacheClearerId); - } - if ($container->hasDefinition($this->cacheClearerId)) { - $clearers[$notAliasedCacheClearerId] = $allPools; - } - - foreach ($clearers as $id => $pools) { - $clearer = $container->getDefinition($id); - if ($clearer instanceof ChildDefinition) { - $clearer->replaceArgument(0, $pools); - } else { - $clearer->setArgument(0, $pools); - } - $clearer->addTag($this->cachePoolClearerTag); - - if ($this->cacheSystemClearerId === $id) { - $clearer->addTag($this->cacheSystemClearerTag); - } - } - - $allPoolsKeys = array_keys($allPools); - - if ($container->hasDefinition('console.command.cache_pool_list')) { - $container->getDefinition('console.command.cache_pool_list')->replaceArgument(0, $allPoolsKeys); - } - - if ($container->hasDefinition('console.command.cache_pool_clear')) { - $container->getDefinition('console.command.cache_pool_clear')->addArgument($allPoolsKeys); - } - - if ($container->hasDefinition('console.command.cache_pool_delete')) { - $container->getDefinition('console.command.cache_pool_delete')->addArgument($allPoolsKeys); - } - } - - private function getNamespace(string $seed, string $id) - { - return substr(str_replace('/', '-', base64_encode(hash('sha256', $id.$seed, true))), 0, 10); - } - - /** - * @internal - */ - public static function getServiceProvider(ContainerBuilder $container, string $name) - { - $container->resolveEnvPlaceholders($name, null, $usedEnvs); - - if ($usedEnvs || preg_match('#^[a-z]++:#', $name)) { - $dsn = $name; - - if (!$container->hasDefinition($name = '.cache_connection.'.ContainerBuilder::hash($dsn))) { - $definition = new Definition(AbstractAdapter::class); - $definition->setPublic(false); - $definition->setFactory([AbstractAdapter::class, 'createConnection']); - $definition->setArguments([$dsn, ['lazy' => true]]); - $container->setDefinition($name, $definition); - } - } - - return $name; - } -} diff --git a/lib/symfony/cache/DependencyInjection/CachePoolPrunerPass.php b/lib/symfony/cache/DependencyInjection/CachePoolPrunerPass.php deleted file mode 100644 index 86a1906ad..000000000 --- a/lib/symfony/cache/DependencyInjection/CachePoolPrunerPass.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\DependencyInjection; - -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * @author Rob Frawley 2nd <rmf@src.run> - */ -class CachePoolPrunerPass implements CompilerPassInterface -{ - private $cacheCommandServiceId; - private $cachePoolTag; - - public function __construct(string $cacheCommandServiceId = 'console.command.cache_pool_prune', string $cachePoolTag = 'cache.pool') - { - if (0 < \func_num_args()) { - trigger_deprecation('symfony/cache', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->cacheCommandServiceId = $cacheCommandServiceId; - $this->cachePoolTag = $cachePoolTag; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition($this->cacheCommandServiceId)) { - return; - } - - $services = []; - - foreach ($container->findTaggedServiceIds($this->cachePoolTag) as $id => $tags) { - $class = $container->getParameterBag()->resolveValue($container->getDefinition($id)->getClass()); - - if (!$reflection = $container->getReflectionClass($class)) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); - } - - if ($reflection->implementsInterface(PruneableInterface::class)) { - $services[$id] = new Reference($id); - } - } - - $container->getDefinition($this->cacheCommandServiceId)->replaceArgument(0, new IteratorArgument($services)); - } -} diff --git a/lib/symfony/cache/DoctrineProvider.php b/lib/symfony/cache/DoctrineProvider.php deleted file mode 100644 index 7b55aae23..000000000 --- a/lib/symfony/cache/DoctrineProvider.php +++ /dev/null @@ -1,124 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache; - -use Doctrine\Common\Cache\CacheProvider; -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Contracts\Service\ResetInterface; - -if (!class_exists(CacheProvider::class)) { - return; -} - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @deprecated Use Doctrine\Common\Cache\Psr6\DoctrineProvider instead - */ -class DoctrineProvider extends CacheProvider implements PruneableInterface, ResettableInterface -{ - private $pool; - - public function __construct(CacheItemPoolInterface $pool) - { - trigger_deprecation('symfony/cache', '5.4', '"%s" is deprecated, use "Doctrine\Common\Cache\Psr6\DoctrineProvider" instead.', __CLASS__); - - $this->pool = $pool; - } - - /** - * {@inheritdoc} - */ - public function prune() - { - return $this->pool instanceof PruneableInterface && $this->pool->prune(); - } - - /** - * {@inheritdoc} - */ - public function reset() - { - if ($this->pool instanceof ResetInterface) { - $this->pool->reset(); - } - $this->setNamespace($this->getNamespace()); - } - - /** - * {@inheritdoc} - * - * @return mixed - */ - protected function doFetch($id) - { - $item = $this->pool->getItem(rawurlencode($id)); - - return $item->isHit() ? $item->get() : false; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - protected function doContains($id) - { - return $this->pool->hasItem(rawurlencode($id)); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - protected function doSave($id, $data, $lifeTime = 0) - { - $item = $this->pool->getItem(rawurlencode($id)); - - if (0 < $lifeTime) { - $item->expiresAfter($lifeTime); - } - - return $this->pool->save($item->set($data)); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - protected function doDelete($id) - { - return $this->pool->deleteItem(rawurlencode($id)); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - protected function doFlush() - { - return $this->pool->clear(); - } - - /** - * {@inheritdoc} - * - * @return array|null - */ - protected function doGetStats() - { - return null; - } -} diff --git a/lib/symfony/cache/Exception/CacheException.php b/lib/symfony/cache/Exception/CacheException.php deleted file mode 100644 index d2e975b2b..000000000 --- a/lib/symfony/cache/Exception/CacheException.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Exception; - -use Psr\Cache\CacheException as Psr6CacheInterface; -use Psr\SimpleCache\CacheException as SimpleCacheInterface; - -if (interface_exists(SimpleCacheInterface::class)) { - class CacheException extends \Exception implements Psr6CacheInterface, SimpleCacheInterface - { - } -} else { - class CacheException extends \Exception implements Psr6CacheInterface - { - } -} diff --git a/lib/symfony/cache/Exception/InvalidArgumentException.php b/lib/symfony/cache/Exception/InvalidArgumentException.php deleted file mode 100644 index 7f9584a26..000000000 --- a/lib/symfony/cache/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Exception; - -use Psr\Cache\InvalidArgumentException as Psr6CacheInterface; -use Psr\SimpleCache\InvalidArgumentException as SimpleCacheInterface; - -if (interface_exists(SimpleCacheInterface::class)) { - class InvalidArgumentException extends \InvalidArgumentException implements Psr6CacheInterface, SimpleCacheInterface - { - } -} else { - class InvalidArgumentException extends \InvalidArgumentException implements Psr6CacheInterface - { - } -} diff --git a/lib/symfony/cache/Exception/LogicException.php b/lib/symfony/cache/Exception/LogicException.php deleted file mode 100644 index 9ffa7ed69..000000000 --- a/lib/symfony/cache/Exception/LogicException.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Exception; - -use Psr\Cache\CacheException as Psr6CacheInterface; -use Psr\SimpleCache\CacheException as SimpleCacheInterface; - -if (interface_exists(SimpleCacheInterface::class)) { - class LogicException extends \LogicException implements Psr6CacheInterface, SimpleCacheInterface - { - } -} else { - class LogicException extends \LogicException implements Psr6CacheInterface - { - } -} diff --git a/lib/symfony/cache/LICENSE b/lib/symfony/cache/LICENSE deleted file mode 100644 index 7fa953905..000000000 --- a/lib/symfony/cache/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2016-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/lib/symfony/cache/LockRegistry.php b/lib/symfony/cache/LockRegistry.php deleted file mode 100644 index 65f20bb73..000000000 --- a/lib/symfony/cache/LockRegistry.php +++ /dev/null @@ -1,165 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache; - -use Psr\Log\LoggerInterface; -use Symfony\Contracts\Cache\CacheInterface; -use Symfony\Contracts\Cache\ItemInterface; - -/** - * LockRegistry is used internally by existing adapters to protect against cache stampede. - * - * It does so by wrapping the computation of items in a pool of locks. - * Foreach each apps, there can be at most 20 concurrent processes that - * compute items at the same time and only one per cache-key. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -final class LockRegistry -{ - private static $openedFiles = []; - private static $lockedFiles; - private static $signalingException; - private static $signalingCallback; - - /** - * The number of items in this list controls the max number of concurrent processes. - */ - private static $files = [ - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'AbstractAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'AbstractTagAwareAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'AdapterInterface.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ApcuAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ArrayAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ChainAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'CouchbaseBucketAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'CouchbaseCollectionAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'DoctrineAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'DoctrineDbalAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'FilesystemAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'FilesystemTagAwareAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'MemcachedAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'NullAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ParameterNormalizer.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'PdoAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'PhpArrayAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'PhpFilesAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ProxyAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'Psr16Adapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'RedisAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'RedisTagAwareAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'TagAwareAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'TagAwareAdapterInterface.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'TraceableAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'TraceableTagAwareAdapter.php', - ]; - - /** - * Defines a set of existing files that will be used as keys to acquire locks. - * - * @return array The previously defined set of files - */ - public static function setFiles(array $files): array - { - $previousFiles = self::$files; - self::$files = $files; - - foreach (self::$openedFiles as $file) { - if ($file) { - flock($file, \LOCK_UN); - fclose($file); - } - } - self::$openedFiles = self::$lockedFiles = []; - - return $previousFiles; - } - - public static function compute(callable $callback, ItemInterface $item, bool &$save, CacheInterface $pool, \Closure $setMetadata = null, LoggerInterface $logger = null) - { - if ('\\' === \DIRECTORY_SEPARATOR && null === self::$lockedFiles) { - // disable locking on Windows by default - self::$files = self::$lockedFiles = []; - } - - $key = self::$files ? abs(crc32($item->getKey())) % \count(self::$files) : -1; - - if ($key < 0 || self::$lockedFiles || !$lock = self::open($key)) { - return $callback($item, $save); - } - - self::$signalingException ?? self::$signalingException = unserialize("O:9:\"Exception\":1:{s:16:\"\0Exception\0trace\";a:0:{}}"); - self::$signalingCallback ?? self::$signalingCallback = function () { throw self::$signalingException; }; - - while (true) { - try { - $locked = false; - // race to get the lock in non-blocking mode - $locked = flock($lock, \LOCK_EX | \LOCK_NB, $wouldBlock); - - if ($locked || !$wouldBlock) { - $logger && $logger->info(sprintf('Lock %s, now computing item "{key}"', $locked ? 'acquired' : 'not supported'), ['key' => $item->getKey()]); - self::$lockedFiles[$key] = true; - - $value = $callback($item, $save); - - if ($save) { - if ($setMetadata) { - $setMetadata($item); - } - - $pool->save($item->set($value)); - $save = false; - } - - return $value; - } - // if we failed the race, retry locking in blocking mode to wait for the winner - $logger && $logger->info('Item "{key}" is locked, waiting for it to be released', ['key' => $item->getKey()]); - flock($lock, \LOCK_SH); - } finally { - flock($lock, \LOCK_UN); - unset(self::$lockedFiles[$key]); - } - - try { - $value = $pool->get($item->getKey(), self::$signalingCallback, 0); - $logger && $logger->info('Item "{key}" retrieved after lock was released', ['key' => $item->getKey()]); - $save = false; - - return $value; - } catch (\Exception $e) { - if (self::$signalingException !== $e) { - throw $e; - } - $logger && $logger->info('Item "{key}" not found while lock was released, now retrying', ['key' => $item->getKey()]); - } - } - - return null; - } - - private static function open(int $key) - { - if (null !== $h = self::$openedFiles[$key] ?? null) { - return $h; - } - set_error_handler(function () {}); - try { - $h = fopen(self::$files[$key], 'r+'); - } finally { - restore_error_handler(); - } - - return self::$openedFiles[$key] = $h ?: @fopen(self::$files[$key], 'r'); - } -} diff --git a/lib/symfony/cache/Marshaller/DefaultMarshaller.php b/lib/symfony/cache/Marshaller/DefaultMarshaller.php deleted file mode 100644 index 3202dd69c..000000000 --- a/lib/symfony/cache/Marshaller/DefaultMarshaller.php +++ /dev/null @@ -1,104 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Marshaller; - -use Symfony\Component\Cache\Exception\CacheException; - -/** - * Serializes/unserializes values using igbinary_serialize() if available, serialize() otherwise. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class DefaultMarshaller implements MarshallerInterface -{ - private $useIgbinarySerialize = true; - private $throwOnSerializationFailure; - - public function __construct(bool $useIgbinarySerialize = null, bool $throwOnSerializationFailure = false) - { - if (null === $useIgbinarySerialize) { - $useIgbinarySerialize = \extension_loaded('igbinary') && (\PHP_VERSION_ID < 70400 || version_compare('3.1.6', phpversion('igbinary'), '<=')); - } elseif ($useIgbinarySerialize && (!\extension_loaded('igbinary') || (\PHP_VERSION_ID >= 70400 && version_compare('3.1.6', phpversion('igbinary'), '>')))) { - throw new CacheException(\extension_loaded('igbinary') && \PHP_VERSION_ID >= 70400 ? 'Please upgrade the "igbinary" PHP extension to v3.1.6 or higher.' : 'The "igbinary" PHP extension is not loaded.'); - } - $this->useIgbinarySerialize = $useIgbinarySerialize; - $this->throwOnSerializationFailure = $throwOnSerializationFailure; - } - - /** - * {@inheritdoc} - */ - public function marshall(array $values, ?array &$failed): array - { - $serialized = $failed = []; - - foreach ($values as $id => $value) { - try { - if ($this->useIgbinarySerialize) { - $serialized[$id] = igbinary_serialize($value); - } else { - $serialized[$id] = serialize($value); - } - } catch (\Exception $e) { - if ($this->throwOnSerializationFailure) { - throw new \ValueError($e->getMessage(), 0, $e); - } - $failed[] = $id; - } - } - - return $serialized; - } - - /** - * {@inheritdoc} - */ - public function unmarshall(string $value) - { - if ('b:0;' === $value) { - return false; - } - if ('N;' === $value) { - return null; - } - static $igbinaryNull; - if ($value === ($igbinaryNull ?? $igbinaryNull = \extension_loaded('igbinary') ? igbinary_serialize(null) : false)) { - return null; - } - $unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback'); - try { - if (':' === ($value[1] ?? ':')) { - if (false !== $value = unserialize($value)) { - return $value; - } - } elseif (false === $igbinaryNull) { - throw new \RuntimeException('Failed to unserialize values, did you forget to install the "igbinary" extension?'); - } elseif (null !== $value = igbinary_unserialize($value)) { - return $value; - } - - throw new \DomainException(error_get_last() ? error_get_last()['message'] : 'Failed to unserialize values.'); - } catch (\Error $e) { - throw new \ErrorException($e->getMessage(), $e->getCode(), \E_ERROR, $e->getFile(), $e->getLine()); - } finally { - ini_set('unserialize_callback_func', $unserializeCallbackHandler); - } - } - - /** - * @internal - */ - public static function handleUnserializeCallback(string $class) - { - throw new \DomainException('Class not found: '.$class); - } -} diff --git a/lib/symfony/cache/Marshaller/DeflateMarshaller.php b/lib/symfony/cache/Marshaller/DeflateMarshaller.php deleted file mode 100644 index 554480611..000000000 --- a/lib/symfony/cache/Marshaller/DeflateMarshaller.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Marshaller; - -use Symfony\Component\Cache\Exception\CacheException; - -/** - * Compresses values using gzdeflate(). - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class DeflateMarshaller implements MarshallerInterface -{ - private $marshaller; - - public function __construct(MarshallerInterface $marshaller) - { - if (!\function_exists('gzdeflate')) { - throw new CacheException('The "zlib" PHP extension is not loaded.'); - } - - $this->marshaller = $marshaller; - } - - /** - * {@inheritdoc} - */ - public function marshall(array $values, ?array &$failed): array - { - return array_map('gzdeflate', $this->marshaller->marshall($values, $failed)); - } - - /** - * {@inheritdoc} - */ - public function unmarshall(string $value) - { - if (false !== $inflatedValue = @gzinflate($value)) { - $value = $inflatedValue; - } - - return $this->marshaller->unmarshall($value); - } -} diff --git a/lib/symfony/cache/Marshaller/MarshallerInterface.php b/lib/symfony/cache/Marshaller/MarshallerInterface.php deleted file mode 100644 index cdd6c4022..000000000 --- a/lib/symfony/cache/Marshaller/MarshallerInterface.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Marshaller; - -/** - * Serializes/unserializes PHP values. - * - * Implementations of this interface MUST deal with errors carefully. They MUST - * also deal with forward and backward compatibility at the storage format level. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -interface MarshallerInterface -{ - /** - * Serializes a list of values. - * - * When serialization fails for a specific value, no exception should be - * thrown. Instead, its key should be listed in $failed. - */ - public function marshall(array $values, ?array &$failed): array; - - /** - * Unserializes a single value and throws an exception if anything goes wrong. - * - * @return mixed - * - * @throws \Exception Whenever unserialization fails - */ - public function unmarshall(string $value); -} diff --git a/lib/symfony/cache/Marshaller/SodiumMarshaller.php b/lib/symfony/cache/Marshaller/SodiumMarshaller.php deleted file mode 100644 index dbf486a72..000000000 --- a/lib/symfony/cache/Marshaller/SodiumMarshaller.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Marshaller; - -use Symfony\Component\Cache\Exception\CacheException; -use Symfony\Component\Cache\Exception\InvalidArgumentException; - -/** - * Encrypt/decrypt values using Libsodium. - * - * @author Ahmed TAILOULOUTE <ahmed.tailouloute@gmail.com> - */ -class SodiumMarshaller implements MarshallerInterface -{ - private $marshaller; - private $decryptionKeys; - - /** - * @param string[] $decryptionKeys The key at index "0" is required and is used to decrypt and encrypt values; - * more rotating keys can be provided to decrypt values; - * each key must be generated using sodium_crypto_box_keypair() - */ - public function __construct(array $decryptionKeys, MarshallerInterface $marshaller = null) - { - if (!self::isSupported()) { - throw new CacheException('The "sodium" PHP extension is not loaded.'); - } - - if (!isset($decryptionKeys[0])) { - throw new InvalidArgumentException('At least one decryption key must be provided at index "0".'); - } - - $this->marshaller = $marshaller ?? new DefaultMarshaller(); - $this->decryptionKeys = $decryptionKeys; - } - - public static function isSupported(): bool - { - return \function_exists('sodium_crypto_box_seal'); - } - - /** - * {@inheritdoc} - */ - public function marshall(array $values, ?array &$failed): array - { - $encryptionKey = sodium_crypto_box_publickey($this->decryptionKeys[0]); - - $encryptedValues = []; - foreach ($this->marshaller->marshall($values, $failed) as $k => $v) { - $encryptedValues[$k] = sodium_crypto_box_seal($v, $encryptionKey); - } - - return $encryptedValues; - } - - /** - * {@inheritdoc} - */ - public function unmarshall(string $value) - { - foreach ($this->decryptionKeys as $k) { - if (false !== $decryptedValue = @sodium_crypto_box_seal_open($value, $k)) { - $value = $decryptedValue; - break; - } - } - - return $this->marshaller->unmarshall($value); - } -} diff --git a/lib/symfony/cache/Marshaller/TagAwareMarshaller.php b/lib/symfony/cache/Marshaller/TagAwareMarshaller.php deleted file mode 100644 index 5d1e303b4..000000000 --- a/lib/symfony/cache/Marshaller/TagAwareMarshaller.php +++ /dev/null @@ -1,89 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Marshaller; - -/** - * A marshaller optimized for data structures generated by AbstractTagAwareAdapter. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class TagAwareMarshaller implements MarshallerInterface -{ - private $marshaller; - - public function __construct(MarshallerInterface $marshaller = null) - { - $this->marshaller = $marshaller ?? new DefaultMarshaller(); - } - - /** - * {@inheritdoc} - */ - public function marshall(array $values, ?array &$failed): array - { - $failed = $notSerialized = $serialized = []; - - foreach ($values as $id => $value) { - if (\is_array($value) && \is_array($value['tags'] ?? null) && \array_key_exists('value', $value) && \count($value) === 2 + (\is_string($value['meta'] ?? null) && 8 === \strlen($value['meta']))) { - // if the value is an array with keys "tags", "value" and "meta", use a compact serialization format - // magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F allow detecting this format quickly in unmarshall() - - $v = $this->marshaller->marshall($value, $f); - - if ($f) { - $f = []; - $failed[] = $id; - } else { - if ([] === $value['tags']) { - $v['tags'] = ''; - } - - $serialized[$id] = "\x9D".($value['meta'] ?? "\0\0\0\0\0\0\0\0").pack('N', \strlen($v['tags'])).$v['tags'].$v['value']; - $serialized[$id][9] = "\x5F"; - } - } else { - // other arbitratry values are serialized using the decorated marshaller below - $notSerialized[$id] = $value; - } - } - - if ($notSerialized) { - $serialized += $this->marshaller->marshall($notSerialized, $f); - $failed = array_merge($failed, $f); - } - - return $serialized; - } - - /** - * {@inheritdoc} - */ - public function unmarshall(string $value) - { - // detect the compact format used in marshall() using magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F - if (13 >= \strlen($value) || "\x9D" !== $value[0] || "\0" !== $value[5] || "\x5F" !== $value[9]) { - return $this->marshaller->unmarshall($value); - } - - // data consists of value, tags and metadata which we need to unpack - $meta = substr($value, 1, 12); - $meta[8] = "\0"; - $tagLen = unpack('Nlen', $meta, 8)['len']; - $meta = substr($meta, 0, 8); - - return [ - 'value' => $this->marshaller->unmarshall(substr($value, 13 + $tagLen)), - 'tags' => $tagLen ? $this->marshaller->unmarshall(substr($value, 13, $tagLen)) : [], - 'meta' => "\0\0\0\0\0\0\0\0" === $meta ? null : $meta, - ]; - } -} diff --git a/lib/symfony/cache/Messenger/EarlyExpirationDispatcher.php b/lib/symfony/cache/Messenger/EarlyExpirationDispatcher.php deleted file mode 100644 index 6f11b8b5a..000000000 --- a/lib/symfony/cache/Messenger/EarlyExpirationDispatcher.php +++ /dev/null @@ -1,61 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Messenger; - -use Psr\Log\LoggerInterface; -use Symfony\Component\Cache\Adapter\AdapterInterface; -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\DependencyInjection\ReverseContainer; -use Symfony\Component\Messenger\MessageBusInterface; -use Symfony\Component\Messenger\Stamp\HandledStamp; - -/** - * Sends the computation of cached values to a message bus. - */ -class EarlyExpirationDispatcher -{ - private $bus; - private $reverseContainer; - private $callbackWrapper; - - public function __construct(MessageBusInterface $bus, ReverseContainer $reverseContainer, callable $callbackWrapper = null) - { - $this->bus = $bus; - $this->reverseContainer = $reverseContainer; - $this->callbackWrapper = $callbackWrapper; - } - - public function __invoke(callable $callback, CacheItem $item, bool &$save, AdapterInterface $pool, \Closure $setMetadata, LoggerInterface $logger = null) - { - if (!$item->isHit() || null === $message = EarlyExpirationMessage::create($this->reverseContainer, $callback, $item, $pool)) { - // The item is stale or the callback cannot be reversed: we must compute the value now - $logger && $logger->info('Computing item "{key}" online: '.($item->isHit() ? 'callback cannot be reversed' : 'item is stale'), ['key' => $item->getKey()]); - - return null !== $this->callbackWrapper ? ($this->callbackWrapper)($callback, $item, $save, $pool, $setMetadata, $logger) : $callback($item, $save); - } - - $envelope = $this->bus->dispatch($message); - - if ($logger) { - if ($envelope->last(HandledStamp::class)) { - $logger->info('Item "{key}" was computed online', ['key' => $item->getKey()]); - } else { - $logger->info('Item "{key}" sent for recomputation', ['key' => $item->getKey()]); - } - } - - // The item's value is not stale, no need to write it to the backend - $save = false; - - return $message->getItem()->get() ?? $item->get(); - } -} diff --git a/lib/symfony/cache/Messenger/EarlyExpirationHandler.php b/lib/symfony/cache/Messenger/EarlyExpirationHandler.php deleted file mode 100644 index 1f0bd565c..000000000 --- a/lib/symfony/cache/Messenger/EarlyExpirationHandler.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Messenger; - -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\DependencyInjection\ReverseContainer; -use Symfony\Component\Messenger\Handler\MessageHandlerInterface; - -/** - * Computes cached values sent to a message bus. - */ -class EarlyExpirationHandler implements MessageHandlerInterface -{ - private $reverseContainer; - private $processedNonces = []; - - public function __construct(ReverseContainer $reverseContainer) - { - $this->reverseContainer = $reverseContainer; - } - - public function __invoke(EarlyExpirationMessage $message) - { - $item = $message->getItem(); - $metadata = $item->getMetadata(); - $expiry = $metadata[CacheItem::METADATA_EXPIRY] ?? 0; - $ctime = $metadata[CacheItem::METADATA_CTIME] ?? 0; - - if ($expiry && $ctime) { - // skip duplicate or expired messages - - $processingNonce = [$expiry, $ctime]; - $pool = $message->getPool(); - $key = $item->getKey(); - - if (($this->processedNonces[$pool][$key] ?? null) === $processingNonce) { - return; - } - - if (microtime(true) >= $expiry) { - return; - } - - $this->processedNonces[$pool] = [$key => $processingNonce] + ($this->processedNonces[$pool] ?? []); - - if (\count($this->processedNonces[$pool]) > 100) { - array_pop($this->processedNonces[$pool]); - } - } - - static $setMetadata; - - $setMetadata ?? $setMetadata = \Closure::bind( - function (CacheItem $item, float $startTime) { - if ($item->expiry > $endTime = microtime(true)) { - $item->newMetadata[CacheItem::METADATA_EXPIRY] = $item->expiry; - $item->newMetadata[CacheItem::METADATA_CTIME] = (int) ceil(1000 * ($endTime - $startTime)); - } - }, - null, - CacheItem::class - ); - - $startTime = microtime(true); - $pool = $message->findPool($this->reverseContainer); - $callback = $message->findCallback($this->reverseContainer); - $value = $callback($item); - $setMetadata($item, $startTime); - $pool->save($item->set($value)); - } -} diff --git a/lib/symfony/cache/Messenger/EarlyExpirationMessage.php b/lib/symfony/cache/Messenger/EarlyExpirationMessage.php deleted file mode 100644 index e25c07e9a..000000000 --- a/lib/symfony/cache/Messenger/EarlyExpirationMessage.php +++ /dev/null @@ -1,97 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Messenger; - -use Symfony\Component\Cache\Adapter\AdapterInterface; -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\DependencyInjection\ReverseContainer; - -/** - * Conveys a cached value that needs to be computed. - */ -final class EarlyExpirationMessage -{ - private $item; - private $pool; - private $callback; - - public static function create(ReverseContainer $reverseContainer, callable $callback, CacheItem $item, AdapterInterface $pool): ?self - { - try { - $item = clone $item; - $item->set(null); - } catch (\Exception $e) { - return null; - } - - $pool = $reverseContainer->getId($pool); - - if (\is_object($callback)) { - if (null === $id = $reverseContainer->getId($callback)) { - return null; - } - - $callback = '@'.$id; - } elseif (!\is_array($callback)) { - $callback = (string) $callback; - } elseif (!\is_object($callback[0])) { - $callback = [(string) $callback[0], (string) $callback[1]]; - } else { - if (null === $id = $reverseContainer->getId($callback[0])) { - return null; - } - - $callback = ['@'.$id, (string) $callback[1]]; - } - - return new self($item, $pool, $callback); - } - - public function getItem(): CacheItem - { - return $this->item; - } - - public function getPool(): string - { - return $this->pool; - } - - public function getCallback() - { - return $this->callback; - } - - public function findPool(ReverseContainer $reverseContainer): AdapterInterface - { - return $reverseContainer->getService($this->pool); - } - - public function findCallback(ReverseContainer $reverseContainer): callable - { - if (\is_string($callback = $this->callback)) { - return '@' === $callback[0] ? $reverseContainer->getService(substr($callback, 1)) : $callback; - } - if ('@' === $callback[0][0]) { - $callback[0] = $reverseContainer->getService(substr($callback[0], 1)); - } - - return $callback; - } - - private function __construct(CacheItem $item, string $pool, $callback) - { - $this->item = $item; - $this->pool = $pool; - $this->callback = $callback; - } -} diff --git a/lib/symfony/cache/PruneableInterface.php b/lib/symfony/cache/PruneableInterface.php deleted file mode 100644 index 426152536..000000000 --- a/lib/symfony/cache/PruneableInterface.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache; - -/** - * Interface extends psr-6 and psr-16 caches to allow for pruning (deletion) of all expired cache items. - */ -interface PruneableInterface -{ - /** - * @return bool - */ - public function prune(); -} diff --git a/lib/symfony/cache/Psr16Cache.php b/lib/symfony/cache/Psr16Cache.php deleted file mode 100644 index 28c7de605..000000000 --- a/lib/symfony/cache/Psr16Cache.php +++ /dev/null @@ -1,289 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache; - -use Psr\Cache\CacheException as Psr6CacheException; -use Psr\Cache\CacheItemPoolInterface; -use Psr\SimpleCache\CacheException as SimpleCacheException; -use Psr\SimpleCache\CacheInterface; -use Symfony\Component\Cache\Adapter\AdapterInterface; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\Traits\ProxyTrait; - -if (null !== (new \ReflectionMethod(CacheInterface::class, 'get'))->getReturnType()) { - throw new \LogicException('psr/simple-cache 3.0+ is not compatible with this version of symfony/cache. Please upgrade symfony/cache to 6.0+ or downgrade psr/simple-cache to 1.x or 2.x.'); -} - -/** - * Turns a PSR-6 cache into a PSR-16 one. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class Psr16Cache implements CacheInterface, PruneableInterface, ResettableInterface -{ - use ProxyTrait; - - private const METADATA_EXPIRY_OFFSET = 1527506807; - - private $createCacheItem; - private $cacheItemPrototype; - - public function __construct(CacheItemPoolInterface $pool) - { - $this->pool = $pool; - - if (!$pool instanceof AdapterInterface) { - return; - } - $cacheItemPrototype = &$this->cacheItemPrototype; - $createCacheItem = \Closure::bind( - static function ($key, $value, $allowInt = false) use (&$cacheItemPrototype) { - $item = clone $cacheItemPrototype; - $item->poolHash = $item->innerItem = null; - if ($allowInt && \is_int($key)) { - $item->key = (string) $key; - } else { - \assert('' !== CacheItem::validateKey($key)); - $item->key = $key; - } - $item->value = $value; - $item->isHit = false; - - return $item; - }, - null, - CacheItem::class - ); - $this->createCacheItem = function ($key, $value, $allowInt = false) use ($createCacheItem) { - if (null === $this->cacheItemPrototype) { - $this->get($allowInt && \is_int($key) ? (string) $key : $key); - } - $this->createCacheItem = $createCacheItem; - - return $createCacheItem($key, null, $allowInt)->set($value); - }; - } - - /** - * {@inheritdoc} - * - * @return mixed - */ - public function get($key, $default = null) - { - try { - $item = $this->pool->getItem($key); - } catch (SimpleCacheException $e) { - throw $e; - } catch (Psr6CacheException $e) { - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } - if (null === $this->cacheItemPrototype) { - $this->cacheItemPrototype = clone $item; - $this->cacheItemPrototype->set(null); - } - - return $item->isHit() ? $item->get() : $default; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function set($key, $value, $ttl = null) - { - try { - if (null !== $f = $this->createCacheItem) { - $item = $f($key, $value); - } else { - $item = $this->pool->getItem($key)->set($value); - } - } catch (SimpleCacheException $e) { - throw $e; - } catch (Psr6CacheException $e) { - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } - if (null !== $ttl) { - $item->expiresAfter($ttl); - } - - return $this->pool->save($item); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function delete($key) - { - try { - return $this->pool->deleteItem($key); - } catch (SimpleCacheException $e) { - throw $e; - } catch (Psr6CacheException $e) { - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function clear() - { - return $this->pool->clear(); - } - - /** - * {@inheritdoc} - * - * @return iterable - */ - public function getMultiple($keys, $default = null) - { - if ($keys instanceof \Traversable) { - $keys = iterator_to_array($keys, false); - } elseif (!\is_array($keys)) { - throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given.', get_debug_type($keys))); - } - - try { - $items = $this->pool->getItems($keys); - } catch (SimpleCacheException $e) { - throw $e; - } catch (Psr6CacheException $e) { - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } - $values = []; - - if (!$this->pool instanceof AdapterInterface) { - foreach ($items as $key => $item) { - $values[$key] = $item->isHit() ? $item->get() : $default; - } - - return $values; - } - - foreach ($items as $key => $item) { - if (!$item->isHit()) { - $values[$key] = $default; - continue; - } - $values[$key] = $item->get(); - - if (!$metadata = $item->getMetadata()) { - continue; - } - unset($metadata[CacheItem::METADATA_TAGS]); - - if ($metadata) { - $values[$key] = ["\x9D".pack('VN', (int) (0.1 + $metadata[CacheItem::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[CacheItem::METADATA_CTIME])."\x5F" => $values[$key]]; - } - } - - return $values; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function setMultiple($values, $ttl = null) - { - $valuesIsArray = \is_array($values); - if (!$valuesIsArray && !$values instanceof \Traversable) { - throw new InvalidArgumentException(sprintf('Cache values must be array or Traversable, "%s" given.', get_debug_type($values))); - } - $items = []; - - try { - if (null !== $f = $this->createCacheItem) { - $valuesIsArray = false; - foreach ($values as $key => $value) { - $items[$key] = $f($key, $value, true); - } - } elseif ($valuesIsArray) { - $items = []; - foreach ($values as $key => $value) { - $items[] = (string) $key; - } - $items = $this->pool->getItems($items); - } else { - foreach ($values as $key => $value) { - if (\is_int($key)) { - $key = (string) $key; - } - $items[$key] = $this->pool->getItem($key)->set($value); - } - } - } catch (SimpleCacheException $e) { - throw $e; - } catch (Psr6CacheException $e) { - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } - $ok = true; - - foreach ($items as $key => $item) { - if ($valuesIsArray) { - $item->set($values[$key]); - } - if (null !== $ttl) { - $item->expiresAfter($ttl); - } - $ok = $this->pool->saveDeferred($item) && $ok; - } - - return $this->pool->commit() && $ok; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteMultiple($keys) - { - if ($keys instanceof \Traversable) { - $keys = iterator_to_array($keys, false); - } elseif (!\is_array($keys)) { - throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given.', get_debug_type($keys))); - } - - try { - return $this->pool->deleteItems($keys); - } catch (SimpleCacheException $e) { - throw $e; - } catch (Psr6CacheException $e) { - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function has($key) - { - try { - return $this->pool->hasItem($key); - } catch (SimpleCacheException $e) { - throw $e; - } catch (Psr6CacheException $e) { - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } - } -} diff --git a/lib/symfony/cache/README.md b/lib/symfony/cache/README.md deleted file mode 100644 index 74052052c..000000000 --- a/lib/symfony/cache/README.md +++ /dev/null @@ -1,19 +0,0 @@ -Symfony PSR-6 implementation for caching -======================================== - -The Cache component provides an extended -[PSR-6](http://www.php-fig.org/psr/psr-6/) implementation for adding cache to -your applications. It is designed to have a low overhead so that caching is -fastest. It ships with a few caching adapters for the most widespread and -suited to caching backends. It also provides a `doctrine/cache` proxy adapter -to cover more advanced caching needs and a proxy adapter for greater -interoperability between PSR-6 implementations. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/cache.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/lib/symfony/cache/ResettableInterface.php b/lib/symfony/cache/ResettableInterface.php deleted file mode 100644 index 7b0a853f2..000000000 --- a/lib/symfony/cache/ResettableInterface.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache; - -use Symfony\Contracts\Service\ResetInterface; - -/** - * Resets a pool's local state. - */ -interface ResettableInterface extends ResetInterface -{ -} diff --git a/lib/symfony/cache/Traits/AbstractAdapterTrait.php b/lib/symfony/cache/Traits/AbstractAdapterTrait.php deleted file mode 100644 index f0173c422..000000000 --- a/lib/symfony/cache/Traits/AbstractAdapterTrait.php +++ /dev/null @@ -1,424 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Traits; - -use Psr\Cache\CacheItemInterface; -use Psr\Log\LoggerAwareTrait; -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\Cache\Exception\InvalidArgumentException; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -trait AbstractAdapterTrait -{ - use LoggerAwareTrait; - - /** - * @var \Closure needs to be set by class, signature is function(string <key>, mixed <value>, bool <isHit>) - */ - private static $createCacheItem; - - /** - * @var \Closure needs to be set by class, signature is function(array <deferred>, string <namespace>, array <&expiredIds>) - */ - private static $mergeByLifetime; - - private $namespace = ''; - private $defaultLifetime; - private $namespaceVersion = ''; - private $versioningIsEnabled = false; - private $deferred = []; - private $ids = []; - - /** - * @var int|null The maximum length to enforce for identifiers or null when no limit applies - */ - protected $maxIdLength; - - /** - * Fetches several cache items. - * - * @param array $ids The cache identifiers to fetch - * - * @return array|\Traversable - */ - abstract protected function doFetch(array $ids); - - /** - * Confirms if the cache contains specified cache item. - * - * @param string $id The identifier for which to check existence - * - * @return bool - */ - abstract protected function doHave(string $id); - - /** - * Deletes all items in the pool. - * - * @param string $namespace The prefix used for all identifiers managed by this pool - * - * @return bool - */ - abstract protected function doClear(string $namespace); - - /** - * Removes multiple items from the pool. - * - * @param array $ids An array of identifiers that should be removed from the pool - * - * @return bool - */ - abstract protected function doDelete(array $ids); - - /** - * Persists several cache items immediately. - * - * @param array $values The values to cache, indexed by their cache identifier - * @param int $lifetime The lifetime of the cached values, 0 for persisting until manual cleaning - * - * @return array|bool The identifiers that failed to be cached or a boolean stating if caching succeeded or not - */ - abstract protected function doSave(array $values, int $lifetime); - - /** - * {@inheritdoc} - * - * @return bool - */ - public function hasItem($key) - { - $id = $this->getId($key); - - if (isset($this->deferred[$key])) { - $this->commit(); - } - - try { - return $this->doHave($id); - } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to check if key "{key}" is cached: '.$e->getMessage(), ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]); - - return false; - } - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function clear(string $prefix = '') - { - $this->deferred = []; - if ($cleared = $this->versioningIsEnabled) { - if ('' === $namespaceVersionToClear = $this->namespaceVersion) { - foreach ($this->doFetch([static::NS_SEPARATOR.$this->namespace]) as $v) { - $namespaceVersionToClear = $v; - } - } - $namespaceToClear = $this->namespace.$namespaceVersionToClear; - $namespaceVersion = self::formatNamespaceVersion(mt_rand()); - try { - $e = $this->doSave([static::NS_SEPARATOR.$this->namespace => $namespaceVersion], 0); - } catch (\Exception $e) { - } - if (true !== $e && [] !== $e) { - $cleared = false; - $message = 'Failed to save the new namespace'.($e instanceof \Exception ? ': '.$e->getMessage() : '.'); - CacheItem::log($this->logger, $message, ['exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]); - } else { - $this->namespaceVersion = $namespaceVersion; - $this->ids = []; - } - } else { - $namespaceToClear = $this->namespace.$prefix; - } - - try { - return $this->doClear($namespaceToClear) || $cleared; - } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to clear the cache: '.$e->getMessage(), ['exception' => $e, 'cache-adapter' => get_debug_type($this)]); - - return false; - } - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItem($key) - { - return $this->deleteItems([$key]); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItems(array $keys) - { - $ids = []; - - foreach ($keys as $key) { - $ids[$key] = $this->getId($key); - unset($this->deferred[$key]); - } - - try { - if ($this->doDelete($ids)) { - return true; - } - } catch (\Exception $e) { - } - - $ok = true; - - // When bulk-delete failed, retry each item individually - foreach ($ids as $key => $id) { - try { - $e = null; - if ($this->doDelete([$id])) { - continue; - } - } catch (\Exception $e) { - } - $message = 'Failed to delete key "{key}"'.($e instanceof \Exception ? ': '.$e->getMessage() : '.'); - CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]); - $ok = false; - } - - return $ok; - } - - /** - * {@inheritdoc} - */ - public function getItem($key) - { - $id = $this->getId($key); - - if (isset($this->deferred[$key])) { - $this->commit(); - } - - $isHit = false; - $value = null; - - try { - foreach ($this->doFetch([$id]) as $value) { - $isHit = true; - } - - return (self::$createCacheItem)($key, $value, $isHit); - } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to fetch key "{key}": '.$e->getMessage(), ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]); - } - - return (self::$createCacheItem)($key, null, false); - } - - /** - * {@inheritdoc} - */ - public function getItems(array $keys = []) - { - $ids = []; - $commit = false; - - foreach ($keys as $key) { - $ids[] = $this->getId($key); - $commit = $commit || isset($this->deferred[$key]); - } - - if ($commit) { - $this->commit(); - } - - try { - $items = $this->doFetch($ids); - } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to fetch items: '.$e->getMessage(), ['keys' => $keys, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]); - $items = []; - } - $ids = array_combine($ids, $keys); - - return $this->generateItems($items, $ids); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function save(CacheItemInterface $item) - { - if (!$item instanceof CacheItem) { - return false; - } - $this->deferred[$item->getKey()] = $item; - - return $this->commit(); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function saveDeferred(CacheItemInterface $item) - { - if (!$item instanceof CacheItem) { - return false; - } - $this->deferred[$item->getKey()] = $item; - - return true; - } - - /** - * Enables/disables versioning of items. - * - * When versioning is enabled, clearing the cache is atomic and doesn't require listing existing keys to proceed, - * but old keys may need garbage collection and extra round-trips to the back-end are required. - * - * Calling this method also clears the memoized namespace version and thus forces a resynchonization of it. - * - * @return bool the previous state of versioning - */ - public function enableVersioning(bool $enable = true) - { - $wasEnabled = $this->versioningIsEnabled; - $this->versioningIsEnabled = $enable; - $this->namespaceVersion = ''; - $this->ids = []; - - return $wasEnabled; - } - - /** - * {@inheritdoc} - */ - public function reset() - { - if ($this->deferred) { - $this->commit(); - } - $this->namespaceVersion = ''; - $this->ids = []; - } - - /** - * @return array - */ - public function __sleep() - { - throw new \BadMethodCallException('Cannot serialize '.__CLASS__); - } - - public function __wakeup() - { - throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); - } - - public function __destruct() - { - if ($this->deferred) { - $this->commit(); - } - } - - private function generateItems(iterable $items, array &$keys): \Generator - { - $f = self::$createCacheItem; - - try { - foreach ($items as $id => $value) { - if (!isset($keys[$id])) { - throw new InvalidArgumentException(sprintf('Could not match value id "%s" to keys "%s".', $id, implode('", "', $keys))); - } - $key = $keys[$id]; - unset($keys[$id]); - yield $key => $f($key, $value, true); - } - } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to fetch items: '.$e->getMessage(), ['keys' => array_values($keys), 'exception' => $e, 'cache-adapter' => get_debug_type($this)]); - } - - foreach ($keys as $key) { - yield $key => $f($key, null, false); - } - } - - private function getId($key) - { - if ($this->versioningIsEnabled && '' === $this->namespaceVersion) { - $this->ids = []; - $this->namespaceVersion = '1'.static::NS_SEPARATOR; - try { - foreach ($this->doFetch([static::NS_SEPARATOR.$this->namespace]) as $v) { - $this->namespaceVersion = $v; - } - $e = true; - if ('1'.static::NS_SEPARATOR === $this->namespaceVersion) { - $this->namespaceVersion = self::formatNamespaceVersion(time()); - $e = $this->doSave([static::NS_SEPARATOR.$this->namespace => $this->namespaceVersion], 0); - } - } catch (\Exception $e) { - } - if (true !== $e && [] !== $e) { - $message = 'Failed to save the new namespace'.($e instanceof \Exception ? ': '.$e->getMessage() : '.'); - CacheItem::log($this->logger, $message, ['exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]); - } - } - - if (\is_string($key) && isset($this->ids[$key])) { - return $this->namespace.$this->namespaceVersion.$this->ids[$key]; - } - \assert('' !== CacheItem::validateKey($key)); - $this->ids[$key] = $key; - - if (\count($this->ids) > 1000) { - array_splice($this->ids, 0, 500); // stop memory leak if there are many keys - } - - if (null === $this->maxIdLength) { - return $this->namespace.$this->namespaceVersion.$key; - } - if (\strlen($id = $this->namespace.$this->namespaceVersion.$key) > $this->maxIdLength) { - // Use MD5 to favor speed over security, which is not an issue here - $this->ids[$key] = $id = substr_replace(base64_encode(hash('md5', $key, true)), static::NS_SEPARATOR, -(\strlen($this->namespaceVersion) + 2)); - $id = $this->namespace.$this->namespaceVersion.$id; - } - - return $id; - } - - /** - * @internal - */ - public static function handleUnserializeCallback(string $class) - { - throw new \DomainException('Class not found: '.$class); - } - - private static function formatNamespaceVersion(int $value): string - { - return strtr(substr_replace(base64_encode(pack('V', $value)), static::NS_SEPARATOR, 5), '/', '_'); - } -} diff --git a/lib/symfony/cache/Traits/ContractsTrait.php b/lib/symfony/cache/Traits/ContractsTrait.php deleted file mode 100644 index 9a491adb5..000000000 --- a/lib/symfony/cache/Traits/ContractsTrait.php +++ /dev/null @@ -1,109 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Traits; - -use Psr\Log\LoggerInterface; -use Symfony\Component\Cache\Adapter\AdapterInterface; -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\LockRegistry; -use Symfony\Contracts\Cache\CacheInterface; -use Symfony\Contracts\Cache\CacheTrait; -use Symfony\Contracts\Cache\ItemInterface; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -trait ContractsTrait -{ - use CacheTrait { - doGet as private contractsGet; - } - - private $callbackWrapper; - private $computing = []; - - /** - * Wraps the callback passed to ->get() in a callable. - * - * @return callable the previous callback wrapper - */ - public function setCallbackWrapper(?callable $callbackWrapper): callable - { - if (!isset($this->callbackWrapper)) { - $this->callbackWrapper = \Closure::fromCallable([LockRegistry::class, 'compute']); - - if (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { - $this->setCallbackWrapper(null); - } - } - - $previousWrapper = $this->callbackWrapper; - $this->callbackWrapper = $callbackWrapper ?? static function (callable $callback, ItemInterface $item, bool &$save, CacheInterface $pool, \Closure $setMetadata, ?LoggerInterface $logger) { - return $callback($item, $save); - }; - - return $previousWrapper; - } - - private function doGet(AdapterInterface $pool, string $key, callable $callback, ?float $beta, array &$metadata = null) - { - if (0 > $beta = $beta ?? 1.0) { - throw new InvalidArgumentException(sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', static::class, $beta)); - } - - static $setMetadata; - - $setMetadata ?? $setMetadata = \Closure::bind( - static function (CacheItem $item, float $startTime, ?array &$metadata) { - if ($item->expiry > $endTime = microtime(true)) { - $item->newMetadata[CacheItem::METADATA_EXPIRY] = $metadata[CacheItem::METADATA_EXPIRY] = $item->expiry; - $item->newMetadata[CacheItem::METADATA_CTIME] = $metadata[CacheItem::METADATA_CTIME] = (int) ceil(1000 * ($endTime - $startTime)); - } else { - unset($metadata[CacheItem::METADATA_EXPIRY], $metadata[CacheItem::METADATA_CTIME]); - } - }, - null, - CacheItem::class - ); - - return $this->contractsGet($pool, $key, function (CacheItem $item, bool &$save) use ($pool, $callback, $setMetadata, &$metadata, $key) { - // don't wrap nor save recursive calls - if (isset($this->computing[$key])) { - $value = $callback($item, $save); - $save = false; - - return $value; - } - - $this->computing[$key] = $key; - $startTime = microtime(true); - - if (!isset($this->callbackWrapper)) { - $this->setCallbackWrapper($this->setCallbackWrapper(null)); - } - - try { - $value = ($this->callbackWrapper)($callback, $item, $save, $pool, function (CacheItem $item) use ($setMetadata, $startTime, &$metadata) { - $setMetadata($item, $startTime, $metadata); - }, $this->logger ?? null); - $setMetadata($item, $startTime, $metadata); - - return $value; - } finally { - unset($this->computing[$key]); - } - }, $beta, $metadata, $this->logger ?? null); - } -} diff --git a/lib/symfony/cache/Traits/FilesystemCommonTrait.php b/lib/symfony/cache/Traits/FilesystemCommonTrait.php deleted file mode 100644 index c06cc309a..000000000 --- a/lib/symfony/cache/Traits/FilesystemCommonTrait.php +++ /dev/null @@ -1,196 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Traits; - -use Symfony\Component\Cache\Exception\InvalidArgumentException; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -trait FilesystemCommonTrait -{ - private $directory; - private $tmp; - - private function init(string $namespace, ?string $directory) - { - if (!isset($directory[0])) { - $directory = sys_get_temp_dir().\DIRECTORY_SEPARATOR.'symfony-cache'; - } else { - $directory = realpath($directory) ?: $directory; - } - if (isset($namespace[0])) { - if (preg_match('#[^-+_.A-Za-z0-9]#', $namespace, $match)) { - throw new InvalidArgumentException(sprintf('Namespace contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.', $match[0])); - } - $directory .= \DIRECTORY_SEPARATOR.$namespace; - } else { - $directory .= \DIRECTORY_SEPARATOR.'@'; - } - if (!is_dir($directory)) { - @mkdir($directory, 0777, true); - } - $directory .= \DIRECTORY_SEPARATOR; - // On Windows the whole path is limited to 258 chars - if ('\\' === \DIRECTORY_SEPARATOR && \strlen($directory) > 234) { - throw new InvalidArgumentException(sprintf('Cache directory too long (%s).', $directory)); - } - - $this->directory = $directory; - } - - /** - * {@inheritdoc} - */ - protected function doClear(string $namespace) - { - $ok = true; - - foreach ($this->scanHashDir($this->directory) as $file) { - if ('' !== $namespace && !str_starts_with($this->getFileKey($file), $namespace)) { - continue; - } - - $ok = ($this->doUnlink($file) || !file_exists($file)) && $ok; - } - - return $ok; - } - - /** - * {@inheritdoc} - */ - protected function doDelete(array $ids) - { - $ok = true; - - foreach ($ids as $id) { - $file = $this->getFile($id); - $ok = (!is_file($file) || $this->doUnlink($file) || !file_exists($file)) && $ok; - } - - return $ok; - } - - protected function doUnlink(string $file) - { - return @unlink($file); - } - - private function write(string $file, string $data, int $expiresAt = null) - { - set_error_handler(__CLASS__.'::throwError'); - try { - if (null === $this->tmp) { - $this->tmp = $this->directory.bin2hex(random_bytes(6)); - } - try { - $h = fopen($this->tmp, 'x'); - } catch (\ErrorException $e) { - if (!str_contains($e->getMessage(), 'File exists')) { - throw $e; - } - - $this->tmp = $this->directory.bin2hex(random_bytes(6)); - $h = fopen($this->tmp, 'x'); - } - fwrite($h, $data); - fclose($h); - - if (null !== $expiresAt) { - touch($this->tmp, $expiresAt ?: time() + 31556952); // 1 year in seconds - } - - return rename($this->tmp, $file); - } finally { - restore_error_handler(); - } - } - - private function getFile(string $id, bool $mkdir = false, string $directory = null) - { - // Use MD5 to favor speed over security, which is not an issue here - $hash = str_replace('/', '-', base64_encode(hash('md5', static::class.$id, true))); - $dir = ($directory ?? $this->directory).strtoupper($hash[0].\DIRECTORY_SEPARATOR.$hash[1].\DIRECTORY_SEPARATOR); - - if ($mkdir && !is_dir($dir)) { - @mkdir($dir, 0777, true); - } - - return $dir.substr($hash, 2, 20); - } - - private function getFileKey(string $file): string - { - return ''; - } - - private function scanHashDir(string $directory): \Generator - { - if (!is_dir($directory)) { - return; - } - - $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; - - for ($i = 0; $i < 38; ++$i) { - if (!is_dir($directory.$chars[$i])) { - continue; - } - - for ($j = 0; $j < 38; ++$j) { - if (!is_dir($dir = $directory.$chars[$i].\DIRECTORY_SEPARATOR.$chars[$j])) { - continue; - } - - foreach (@scandir($dir, \SCANDIR_SORT_NONE) ?: [] as $file) { - if ('.' !== $file && '..' !== $file) { - yield $dir.\DIRECTORY_SEPARATOR.$file; - } - } - } - } - } - - /** - * @internal - */ - public static function throwError(int $type, string $message, string $file, int $line) - { - throw new \ErrorException($message, 0, $type, $file, $line); - } - - /** - * @return array - */ - public function __sleep() - { - throw new \BadMethodCallException('Cannot serialize '.__CLASS__); - } - - public function __wakeup() - { - throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); - } - - public function __destruct() - { - if (method_exists(parent::class, '__destruct')) { - parent::__destruct(); - } - if (null !== $this->tmp && is_file($this->tmp)) { - unlink($this->tmp); - } - } -} diff --git a/lib/symfony/cache/Traits/FilesystemTrait.php b/lib/symfony/cache/Traits/FilesystemTrait.php deleted file mode 100644 index 38b741f1c..000000000 --- a/lib/symfony/cache/Traits/FilesystemTrait.php +++ /dev/null @@ -1,124 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Traits; - -use Symfony\Component\Cache\Exception\CacheException; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * @author Rob Frawley 2nd <rmf@src.run> - * - * @internal - */ -trait FilesystemTrait -{ - use FilesystemCommonTrait; - - private $marshaller; - - /** - * @return bool - */ - public function prune() - { - $time = time(); - $pruned = true; - - foreach ($this->scanHashDir($this->directory) as $file) { - if (!$h = @fopen($file, 'r')) { - continue; - } - - if (($expiresAt = (int) fgets($h)) && $time >= $expiresAt) { - fclose($h); - $pruned = @unlink($file) && !file_exists($file) && $pruned; - } else { - fclose($h); - } - } - - return $pruned; - } - - /** - * {@inheritdoc} - */ - protected function doFetch(array $ids) - { - $values = []; - $now = time(); - - foreach ($ids as $id) { - $file = $this->getFile($id); - if (!is_file($file) || !$h = @fopen($file, 'r')) { - continue; - } - if (($expiresAt = (int) fgets($h)) && $now >= $expiresAt) { - fclose($h); - @unlink($file); - } else { - $i = rawurldecode(rtrim(fgets($h))); - $value = stream_get_contents($h); - fclose($h); - if ($i === $id) { - $values[$id] = $this->marshaller->unmarshall($value); - } - } - } - - return $values; - } - - /** - * {@inheritdoc} - */ - protected function doHave(string $id) - { - $file = $this->getFile($id); - - return is_file($file) && (@filemtime($file) > time() || $this->doFetch([$id])); - } - - /** - * {@inheritdoc} - */ - protected function doSave(array $values, int $lifetime) - { - $expiresAt = $lifetime ? (time() + $lifetime) : 0; - $values = $this->marshaller->marshall($values, $failed); - - foreach ($values as $id => $value) { - if (!$this->write($this->getFile($id, true), $expiresAt."\n".rawurlencode($id)."\n".$value, $expiresAt)) { - $failed[] = $id; - } - } - - if ($failed && !is_writable($this->directory)) { - throw new CacheException(sprintf('Cache directory is not writable (%s).', $this->directory)); - } - - return $failed; - } - - private function getFileKey(string $file): string - { - if (!$h = @fopen($file, 'r')) { - return ''; - } - - fgets($h); // expiry - $encodedKey = fgets($h); - fclose($h); - - return rawurldecode(rtrim($encodedKey)); - } -} diff --git a/lib/symfony/cache/Traits/ProxyTrait.php b/lib/symfony/cache/Traits/ProxyTrait.php deleted file mode 100644 index c86f360ab..000000000 --- a/lib/symfony/cache/Traits/ProxyTrait.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Traits; - -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Contracts\Service\ResetInterface; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -trait ProxyTrait -{ - private $pool; - - /** - * {@inheritdoc} - */ - public function prune() - { - return $this->pool instanceof PruneableInterface && $this->pool->prune(); - } - - /** - * {@inheritdoc} - */ - public function reset() - { - if ($this->pool instanceof ResetInterface) { - $this->pool->reset(); - } - } -} diff --git a/lib/symfony/cache/Traits/RedisClusterNodeProxy.php b/lib/symfony/cache/Traits/RedisClusterNodeProxy.php deleted file mode 100644 index deba74f6a..000000000 --- a/lib/symfony/cache/Traits/RedisClusterNodeProxy.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Traits; - -/** - * This file acts as a wrapper to the \RedisCluster implementation so it can accept the same type of calls as - * individual \Redis objects. - * - * Calls are made to individual nodes via: RedisCluster->{method}($host, ...args)' - * according to https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#directed-node-commands - * - * @author Jack Thomas <jack.thomas@solidalpha.com> - * - * @internal - */ -class RedisClusterNodeProxy -{ - private $host; - private $redis; - - /** - * @param \RedisCluster|RedisClusterProxy $redis - */ - public function __construct(array $host, $redis) - { - $this->host = $host; - $this->redis = $redis; - } - - public function __call(string $method, array $args) - { - return $this->redis->{$method}($this->host, ...$args); - } - - public function scan(&$iIterator, $strPattern = null, $iCount = null) - { - return $this->redis->scan($iIterator, $this->host, $strPattern, $iCount); - } - - public function getOption($name) - { - return $this->redis->getOption($name); - } -} diff --git a/lib/symfony/cache/Traits/RedisClusterProxy.php b/lib/symfony/cache/Traits/RedisClusterProxy.php deleted file mode 100644 index 73c6a4fdb..000000000 --- a/lib/symfony/cache/Traits/RedisClusterProxy.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Traits; - -/** - * @author Alessandro Chitolina <alekitto@gmail.com> - * - * @internal - */ -class RedisClusterProxy -{ - private $redis; - private $initializer; - - public function __construct(\Closure $initializer) - { - $this->initializer = $initializer; - } - - public function __call(string $method, array $args) - { - $this->redis ?: $this->redis = $this->initializer->__invoke(); - - return $this->redis->{$method}(...$args); - } - - public function hscan($strKey, &$iIterator, $strPattern = null, $iCount = null) - { - $this->redis ?: $this->redis = $this->initializer->__invoke(); - - return $this->redis->hscan($strKey, $iIterator, $strPattern, $iCount); - } - - public function scan(&$iIterator, $strPattern = null, $iCount = null) - { - $this->redis ?: $this->redis = $this->initializer->__invoke(); - - return $this->redis->scan($iIterator, $strPattern, $iCount); - } - - public function sscan($strKey, &$iIterator, $strPattern = null, $iCount = null) - { - $this->redis ?: $this->redis = $this->initializer->__invoke(); - - return $this->redis->sscan($strKey, $iIterator, $strPattern, $iCount); - } - - public function zscan($strKey, &$iIterator, $strPattern = null, $iCount = null) - { - $this->redis ?: $this->redis = $this->initializer->__invoke(); - - return $this->redis->zscan($strKey, $iIterator, $strPattern, $iCount); - } -} diff --git a/lib/symfony/cache/Traits/RedisProxy.php b/lib/symfony/cache/Traits/RedisProxy.php deleted file mode 100644 index ec5cfabb3..000000000 --- a/lib/symfony/cache/Traits/RedisProxy.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Traits; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -class RedisProxy -{ - private $redis; - private $initializer; - private $ready = false; - - public function __construct(\Redis $redis, \Closure $initializer) - { - $this->redis = $redis; - $this->initializer = $initializer; - } - - public function __call(string $method, array $args) - { - $this->ready ?: $this->ready = $this->initializer->__invoke($this->redis); - - return $this->redis->{$method}(...$args); - } - - public function hscan($strKey, &$iIterator, $strPattern = null, $iCount = null) - { - $this->ready ?: $this->ready = $this->initializer->__invoke($this->redis); - - return $this->redis->hscan($strKey, $iIterator, $strPattern, $iCount); - } - - public function scan(&$iIterator, $strPattern = null, $iCount = null) - { - $this->ready ?: $this->ready = $this->initializer->__invoke($this->redis); - - return $this->redis->scan($iIterator, $strPattern, $iCount); - } - - public function sscan($strKey, &$iIterator, $strPattern = null, $iCount = null) - { - $this->ready ?: $this->ready = $this->initializer->__invoke($this->redis); - - return $this->redis->sscan($strKey, $iIterator, $strPattern, $iCount); - } - - public function zscan($strKey, &$iIterator, $strPattern = null, $iCount = null) - { - $this->ready ?: $this->ready = $this->initializer->__invoke($this->redis); - - return $this->redis->zscan($strKey, $iIterator, $strPattern, $iCount); - } -} diff --git a/lib/symfony/cache/Traits/RedisTrait.php b/lib/symfony/cache/Traits/RedisTrait.php deleted file mode 100644 index accee44bc..000000000 --- a/lib/symfony/cache/Traits/RedisTrait.php +++ /dev/null @@ -1,603 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Traits; - -use Predis\Command\Redis\UNLINK; -use Predis\Connection\Aggregate\ClusterInterface; -use Predis\Connection\Aggregate\RedisCluster; -use Predis\Connection\Aggregate\ReplicationInterface; -use Predis\Response\ErrorInterface; -use Predis\Response\Status; -use Symfony\Component\Cache\Exception\CacheException; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\Marshaller\DefaultMarshaller; -use Symfony\Component\Cache\Marshaller\MarshallerInterface; - -/** - * @author Aurimas Niekis <aurimas@niekis.lt> - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -trait RedisTrait -{ - private static $defaultConnectionOptions = [ - 'class' => null, - 'persistent' => 0, - 'persistent_id' => null, - 'timeout' => 30, - 'read_timeout' => 0, - 'retry_interval' => 0, - 'tcp_keepalive' => 0, - 'lazy' => null, - 'redis_cluster' => false, - 'redis_sentinel' => null, - 'dbindex' => 0, - 'failover' => 'none', - 'ssl' => null, // see https://php.net/context.ssl - ]; - private $redis; - private $marshaller; - - /** - * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis - */ - private function init($redis, string $namespace, int $defaultLifetime, ?MarshallerInterface $marshaller) - { - parent::__construct($namespace, $defaultLifetime); - - if (preg_match('#[^-+_.A-Za-z0-9]#', $namespace, $match)) { - throw new InvalidArgumentException(sprintf('RedisAdapter namespace contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.', $match[0])); - } - - if (!$redis instanceof \Redis && !$redis instanceof \RedisArray && !$redis instanceof \RedisCluster && !$redis instanceof \Predis\ClientInterface && !$redis instanceof RedisProxy && !$redis instanceof RedisClusterProxy) { - throw new InvalidArgumentException(sprintf('"%s()" expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\ClientInterface, "%s" given.', __METHOD__, get_debug_type($redis))); - } - - if ($redis instanceof \Predis\ClientInterface && $redis->getOptions()->exceptions) { - $options = clone $redis->getOptions(); - \Closure::bind(function () { $this->options['exceptions'] = false; }, $options, $options)(); - $redis = new $redis($redis->getConnection(), $options); - } - - $this->redis = $redis; - $this->marshaller = $marshaller ?? new DefaultMarshaller(); - } - - /** - * Creates a Redis connection using a DSN configuration. - * - * Example DSN: - * - redis://localhost - * - redis://example.com:1234 - * - redis://secret@example.com/13 - * - redis:///var/run/redis.sock - * - redis://secret@/var/run/redis.sock/13 - * - * @param array $options See self::$defaultConnectionOptions - * - * @return \Redis|\RedisArray|\RedisCluster|RedisClusterProxy|RedisProxy|\Predis\ClientInterface According to the "class" option - * - * @throws InvalidArgumentException when the DSN is invalid - */ - public static function createConnection(string $dsn, array $options = []) - { - if (str_starts_with($dsn, 'redis:')) { - $scheme = 'redis'; - } elseif (str_starts_with($dsn, 'rediss:')) { - $scheme = 'rediss'; - } else { - throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s" does not start with "redis:" or "rediss".', $dsn)); - } - - if (!\extension_loaded('redis') && !class_exists(\Predis\Client::class)) { - throw new CacheException(sprintf('Cannot find the "redis" extension nor the "predis/predis" package: "%s".', $dsn)); - } - - $params = preg_replace_callback('#^'.$scheme.':(//)?(?:(?:[^:@]*+:)?([^@]*+)@)?#', function ($m) use (&$auth) { - if (isset($m[2])) { - $auth = $m[2]; - - if ('' === $auth) { - $auth = null; - } - } - - return 'file:'.($m[1] ?? ''); - }, $dsn); - - if (false === $params = parse_url($params)) { - throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s".', $dsn)); - } - - $query = $hosts = []; - - $tls = 'rediss' === $scheme; - $tcpScheme = $tls ? 'tls' : 'tcp'; - - if (isset($params['query'])) { - parse_str($params['query'], $query); - - if (isset($query['host'])) { - if (!\is_array($hosts = $query['host'])) { - throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s".', $dsn)); - } - foreach ($hosts as $host => $parameters) { - if (\is_string($parameters)) { - parse_str($parameters, $parameters); - } - if (false === $i = strrpos($host, ':')) { - $hosts[$host] = ['scheme' => $tcpScheme, 'host' => $host, 'port' => 6379] + $parameters; - } elseif ($port = (int) substr($host, 1 + $i)) { - $hosts[$host] = ['scheme' => $tcpScheme, 'host' => substr($host, 0, $i), 'port' => $port] + $parameters; - } else { - $hosts[$host] = ['scheme' => 'unix', 'path' => substr($host, 0, $i)] + $parameters; - } - } - $hosts = array_values($hosts); - } - } - - if (isset($params['host']) || isset($params['path'])) { - if (!isset($params['dbindex']) && isset($params['path'])) { - if (preg_match('#/(\d+)$#', $params['path'], $m)) { - $params['dbindex'] = $m[1]; - $params['path'] = substr($params['path'], 0, -\strlen($m[0])); - } elseif (isset($params['host'])) { - throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s", the "dbindex" parameter must be a number.', $dsn)); - } - } - - if (isset($params['host'])) { - array_unshift($hosts, ['scheme' => $tcpScheme, 'host' => $params['host'], 'port' => $params['port'] ?? 6379]); - } else { - array_unshift($hosts, ['scheme' => 'unix', 'path' => $params['path']]); - } - } - - if (!$hosts) { - throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s".', $dsn)); - } - - $params += $query + $options + self::$defaultConnectionOptions; - - if (isset($params['redis_sentinel']) && !class_exists(\Predis\Client::class) && !class_exists(\RedisSentinel::class)) { - throw new CacheException(sprintf('Redis Sentinel support requires the "predis/predis" package or the "redis" extension v5.2 or higher: "%s".', $dsn)); - } - - if ($params['redis_cluster'] && isset($params['redis_sentinel'])) { - throw new InvalidArgumentException(sprintf('Cannot use both "redis_cluster" and "redis_sentinel" at the same time: "%s".', $dsn)); - } - - if (null === $params['class'] && \extension_loaded('redis')) { - $class = $params['redis_cluster'] ? \RedisCluster::class : (1 < \count($hosts) && !isset($params['redis_sentinel']) ? \RedisArray::class : \Redis::class); - } else { - $class = $params['class'] ?? \Predis\Client::class; - - if (isset($params['redis_sentinel']) && !is_a($class, \Predis\Client::class, true) && !class_exists(\RedisSentinel::class)) { - throw new CacheException(sprintf('Cannot use Redis Sentinel: class "%s" does not extend "Predis\Client" and ext-redis >= 5.2 not found: "%s".', $class, $dsn)); - } - } - - if (is_a($class, \Redis::class, true)) { - $connect = $params['persistent'] || $params['persistent_id'] ? 'pconnect' : 'connect'; - $redis = new $class(); - - $initializer = static function ($redis) use ($connect, $params, $dsn, $auth, $hosts, $tls) { - $hostIndex = 0; - do { - $host = $hosts[$hostIndex]['host'] ?? $hosts[$hostIndex]['path']; - $port = $hosts[$hostIndex]['port'] ?? 0; - $address = false; - - if (isset($hosts[$hostIndex]['host']) && $tls) { - $host = 'tls://'.$host; - } - - if (!isset($params['redis_sentinel'])) { - break; - } - - $sentinel = new \RedisSentinel($host, $port, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval'], $params['read_timeout']); - - if ($address = $sentinel->getMasterAddrByName($params['redis_sentinel'])) { - [$host, $port] = $address; - } - } while (++$hostIndex < \count($hosts) && !$address); - - if (isset($params['redis_sentinel']) && !$address) { - throw new InvalidArgumentException(sprintf('Failed to retrieve master information from sentinel "%s" and dsn "%s".', $params['redis_sentinel'], $dsn)); - } - - try { - @$redis->{$connect}($host, $port, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval'], $params['read_timeout'], ...\defined('Redis::SCAN_PREFIX') ? [['stream' => $params['ssl'] ?? null]] : []); - - set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); - try { - $isConnected = $redis->isConnected(); - } finally { - restore_error_handler(); - } - if (!$isConnected) { - $error = preg_match('/^Redis::p?connect\(\): (.*)/', $error, $error) ? sprintf(' (%s)', $error[1]) : ''; - throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$error.'.'); - } - - if ((null !== $auth && !$redis->auth($auth)) - || ($params['dbindex'] && !$redis->select($params['dbindex'])) - ) { - $e = preg_replace('/^ERR /', '', $redis->getLastError()); - throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$e.'.'); - } - - if (0 < $params['tcp_keepalive'] && \defined('Redis::OPT_TCP_KEEPALIVE')) { - $redis->setOption(\Redis::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']); - } - } catch (\RedisException $e) { - throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$e->getMessage()); - } - - return true; - }; - - if ($params['lazy']) { - $redis = new RedisProxy($redis, $initializer); - } else { - $initializer($redis); - } - } elseif (is_a($class, \RedisArray::class, true)) { - foreach ($hosts as $i => $host) { - switch ($host['scheme']) { - case 'tcp': $hosts[$i] = $host['host'].':'.$host['port']; break; - case 'tls': $hosts[$i] = 'tls://'.$host['host'].':'.$host['port']; break; - default: $hosts[$i] = $host['path']; - } - } - $params['lazy_connect'] = $params['lazy'] ?? true; - $params['connect_timeout'] = $params['timeout']; - - try { - $redis = new $class($hosts, $params); - } catch (\RedisClusterException $e) { - throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$e->getMessage()); - } - - if (0 < $params['tcp_keepalive'] && \defined('Redis::OPT_TCP_KEEPALIVE')) { - $redis->setOption(\Redis::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']); - } - } elseif (is_a($class, \RedisCluster::class, true)) { - $initializer = static function () use ($class, $params, $dsn, $hosts) { - foreach ($hosts as $i => $host) { - switch ($host['scheme']) { - case 'tcp': $hosts[$i] = $host['host'].':'.$host['port']; break; - case 'tls': $hosts[$i] = 'tls://'.$host['host'].':'.$host['port']; break; - default: $hosts[$i] = $host['path']; - } - } - - try { - $redis = new $class(null, $hosts, $params['timeout'], $params['read_timeout'], (bool) $params['persistent'], $params['auth'] ?? '', ...\defined('Redis::SCAN_PREFIX') ? [$params['ssl'] ?? null] : []); - } catch (\RedisClusterException $e) { - throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$e->getMessage()); - } - - if (0 < $params['tcp_keepalive'] && \defined('Redis::OPT_TCP_KEEPALIVE')) { - $redis->setOption(\Redis::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']); - } - switch ($params['failover']) { - case 'error': $redis->setOption(\RedisCluster::OPT_SLAVE_FAILOVER, \RedisCluster::FAILOVER_ERROR); break; - case 'distribute': $redis->setOption(\RedisCluster::OPT_SLAVE_FAILOVER, \RedisCluster::FAILOVER_DISTRIBUTE); break; - case 'slaves': $redis->setOption(\RedisCluster::OPT_SLAVE_FAILOVER, \RedisCluster::FAILOVER_DISTRIBUTE_SLAVES); break; - } - - return $redis; - }; - - $redis = $params['lazy'] ? new RedisClusterProxy($initializer) : $initializer(); - } elseif (is_a($class, \Predis\ClientInterface::class, true)) { - if ($params['redis_cluster']) { - $params['cluster'] = 'redis'; - } elseif (isset($params['redis_sentinel'])) { - $params['replication'] = 'sentinel'; - $params['service'] = $params['redis_sentinel']; - } - $params += ['parameters' => []]; - $params['parameters'] += [ - 'persistent' => $params['persistent'], - 'timeout' => $params['timeout'], - 'read_write_timeout' => $params['read_timeout'], - 'tcp_nodelay' => true, - ]; - if ($params['dbindex']) { - $params['parameters']['database'] = $params['dbindex']; - } - if (null !== $auth) { - $params['parameters']['password'] = $auth; - } - if (1 === \count($hosts) && !($params['redis_cluster'] || $params['redis_sentinel'])) { - $hosts = $hosts[0]; - } elseif (\in_array($params['failover'], ['slaves', 'distribute'], true) && !isset($params['replication'])) { - $params['replication'] = true; - $hosts[0] += ['alias' => 'master']; - } - $params['exceptions'] = false; - - $redis = new $class($hosts, array_diff_key($params, array_diff_key(self::$defaultConnectionOptions, ['ssl' => null]))); - if (isset($params['redis_sentinel'])) { - $redis->getConnection()->setSentinelTimeout($params['timeout']); - } - } elseif (class_exists($class, false)) { - throw new InvalidArgumentException(sprintf('"%s" is not a subclass of "Redis", "RedisArray", "RedisCluster" nor "Predis\ClientInterface".', $class)); - } else { - throw new InvalidArgumentException(sprintf('Class "%s" does not exist.', $class)); - } - - return $redis; - } - - /** - * {@inheritdoc} - */ - protected function doFetch(array $ids) - { - if (!$ids) { - return []; - } - - $result = []; - - if ($this->redis instanceof \Predis\ClientInterface && $this->redis->getConnection() instanceof ClusterInterface) { - $values = $this->pipeline(function () use ($ids) { - foreach ($ids as $id) { - yield 'get' => [$id]; - } - }); - } else { - $values = $this->redis->mget($ids); - - if (!\is_array($values) || \count($values) !== \count($ids)) { - return []; - } - - $values = array_combine($ids, $values); - } - - foreach ($values as $id => $v) { - if ($v) { - $result[$id] = $this->marshaller->unmarshall($v); - } - } - - return $result; - } - - /** - * {@inheritdoc} - */ - protected function doHave(string $id) - { - return (bool) $this->redis->exists($id); - } - - /** - * {@inheritdoc} - */ - protected function doClear(string $namespace) - { - if ($this->redis instanceof \Predis\ClientInterface) { - $prefix = $this->redis->getOptions()->prefix ? $this->redis->getOptions()->prefix->getPrefix() : ''; - $prefixLen = \strlen($prefix ?? ''); - } - - $cleared = true; - $hosts = $this->getHosts(); - $host = reset($hosts); - if ($host instanceof \Predis\Client && $host->getConnection() instanceof ReplicationInterface) { - // Predis supports info command only on the master in replication environments - $hosts = [$host->getClientFor('master')]; - } - - foreach ($hosts as $host) { - if (!isset($namespace[0])) { - $cleared = $host->flushDb() && $cleared; - continue; - } - - $info = $host->info('Server'); - $info = !$info instanceof ErrorInterface ? $info['Server'] ?? $info : ['redis_version' => '2.0']; - - if (!$host instanceof \Predis\ClientInterface) { - $prefix = \defined('Redis::SCAN_PREFIX') && (\Redis::SCAN_PREFIX & $host->getOption(\Redis::OPT_SCAN)) ? '' : $host->getOption(\Redis::OPT_PREFIX); - $prefixLen = \strlen($host->getOption(\Redis::OPT_PREFIX) ?? ''); - } - $pattern = $prefix.$namespace.'*'; - - if (!version_compare($info['redis_version'], '2.8', '>=')) { - // As documented in Redis documentation (http://redis.io/commands/keys) using KEYS - // can hang your server when it is executed against large databases (millions of items). - // Whenever you hit this scale, you should really consider upgrading to Redis 2.8 or above. - $unlink = version_compare($info['redis_version'], '4.0', '>=') ? 'UNLINK' : 'DEL'; - $args = $this->redis instanceof \Predis\ClientInterface ? [0, $pattern] : [[$pattern], 0]; - $cleared = $host->eval("local keys=redis.call('KEYS',ARGV[1]) for i=1,#keys,5000 do redis.call('$unlink',unpack(keys,i,math.min(i+4999,#keys))) end return 1", $args[0], $args[1]) && $cleared; - continue; - } - - $cursor = null; - do { - $keys = $host instanceof \Predis\ClientInterface ? $host->scan($cursor, 'MATCH', $pattern, 'COUNT', 1000) : $host->scan($cursor, $pattern, 1000); - if (isset($keys[1]) && \is_array($keys[1])) { - $cursor = $keys[0]; - $keys = $keys[1]; - } - if ($keys) { - if ($prefixLen) { - foreach ($keys as $i => $key) { - $keys[$i] = substr($key, $prefixLen); - } - } - $this->doDelete($keys); - } - } while ($cursor = (int) $cursor); - } - - return $cleared; - } - - /** - * {@inheritdoc} - */ - protected function doDelete(array $ids) - { - if (!$ids) { - return true; - } - - if ($this->redis instanceof \Predis\ClientInterface && $this->redis->getConnection() instanceof ClusterInterface) { - static $del; - $del = $del ?? (class_exists(UNLINK::class) ? 'unlink' : 'del'); - - $this->pipeline(function () use ($ids, $del) { - foreach ($ids as $id) { - yield $del => [$id]; - } - })->rewind(); - } else { - static $unlink = true; - - if ($unlink) { - try { - $unlink = false !== $this->redis->unlink($ids); - } catch (\Throwable $e) { - $unlink = false; - } - } - - if (!$unlink) { - $this->redis->del($ids); - } - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doSave(array $values, int $lifetime) - { - if (!$values = $this->marshaller->marshall($values, $failed)) { - return $failed; - } - - $results = $this->pipeline(function () use ($values, $lifetime) { - foreach ($values as $id => $value) { - if (0 >= $lifetime) { - yield 'set' => [$id, $value]; - } else { - yield 'setEx' => [$id, $lifetime, $value]; - } - } - }); - - foreach ($results as $id => $result) { - if (true !== $result && (!$result instanceof Status || Status::get('OK') !== $result)) { - $failed[] = $id; - } - } - - return $failed; - } - - private function pipeline(\Closure $generator, object $redis = null): \Generator - { - $ids = []; - $redis = $redis ?? $this->redis; - - if ($redis instanceof RedisClusterProxy || $redis instanceof \RedisCluster || ($redis instanceof \Predis\ClientInterface && $redis->getConnection() instanceof RedisCluster)) { - // phpredis & predis don't support pipelining with RedisCluster - // see https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#pipelining - // see https://github.com/nrk/predis/issues/267#issuecomment-123781423 - $results = []; - foreach ($generator() as $command => $args) { - $results[] = $redis->{$command}(...$args); - $ids[] = 'eval' === $command ? ($redis instanceof \Predis\ClientInterface ? $args[2] : $args[1][0]) : $args[0]; - } - } elseif ($redis instanceof \Predis\ClientInterface) { - $results = $redis->pipeline(static function ($redis) use ($generator, &$ids) { - foreach ($generator() as $command => $args) { - $redis->{$command}(...$args); - $ids[] = 'eval' === $command ? $args[2] : $args[0]; - } - }); - } elseif ($redis instanceof \RedisArray) { - $connections = $results = $ids = []; - foreach ($generator() as $command => $args) { - $id = 'eval' === $command ? $args[1][0] : $args[0]; - if (!isset($connections[$h = $redis->_target($id)])) { - $connections[$h] = [$redis->_instance($h), -1]; - $connections[$h][0]->multi(\Redis::PIPELINE); - } - $connections[$h][0]->{$command}(...$args); - $results[] = [$h, ++$connections[$h][1]]; - $ids[] = $id; - } - foreach ($connections as $h => $c) { - $connections[$h] = $c[0]->exec(); - } - foreach ($results as $k => [$h, $c]) { - $results[$k] = $connections[$h][$c]; - } - } else { - $redis->multi(\Redis::PIPELINE); - foreach ($generator() as $command => $args) { - $redis->{$command}(...$args); - $ids[] = 'eval' === $command ? $args[1][0] : $args[0]; - } - $results = $redis->exec(); - } - - if (!$redis instanceof \Predis\ClientInterface && 'eval' === $command && $redis->getLastError()) { - $e = new \RedisException($redis->getLastError()); - $results = array_map(function ($v) use ($e) { return false === $v ? $e : $v; }, $results); - } - - foreach ($ids as $k => $id) { - yield $id => $results[$k]; - } - } - - private function getHosts(): array - { - $hosts = [$this->redis]; - if ($this->redis instanceof \Predis\ClientInterface) { - $connection = $this->redis->getConnection(); - if ($connection instanceof ClusterInterface && $connection instanceof \Traversable) { - $hosts = []; - foreach ($connection as $c) { - $hosts[] = new \Predis\Client($c); - } - } - } elseif ($this->redis instanceof \RedisArray) { - $hosts = []; - foreach ($this->redis->_hosts() as $host) { - $hosts[] = $this->redis->_instance($host); - } - } elseif ($this->redis instanceof RedisClusterProxy || $this->redis instanceof \RedisCluster) { - $hosts = []; - foreach ($this->redis->_masters() as $host) { - $hosts[] = new RedisClusterNodeProxy($host, $this->redis); - } - } - - return $hosts; - } -} diff --git a/lib/symfony/cache/composer.json b/lib/symfony/cache/composer.json deleted file mode 100644 index 1ebcfc9b3..000000000 --- a/lib/symfony/cache/composer.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "name": "symfony/cache", - "type": "library", - "description": "Provides an extended PSR-6, PSR-16 (and tags) implementation", - "keywords": ["caching", "psr6"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "provide": { - "psr/cache-implementation": "1.0|2.0", - "psr/simple-cache-implementation": "1.0|2.0", - "symfony/cache-implementation": "1.0|2.0" - }, - "require": { - "php": ">=7.2.5", - "psr/cache": "^1.0|^2.0", - "psr/log": "^1.1|^2|^3", - "symfony/cache-contracts": "^1.1.7|^2", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/var-exporter": "^4.4|^5.0|^6.0" - }, - "require-dev": { - "cache/integration-tests": "dev-master", - "doctrine/cache": "^1.6|^2.0", - "doctrine/dbal": "^2.13.1|^3.0", - "predis/predis": "^1.1", - "psr/simple-cache": "^1.0|^2.0", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/filesystem": "^4.4|^5.0|^6.0", - "symfony/http-kernel": "^4.4|^5.0|^6.0", - "symfony/messenger": "^4.4|^5.0|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0" - }, - "conflict": { - "doctrine/dbal": "<2.13.1", - "symfony/dependency-injection": "<4.4", - "symfony/http-kernel": "<4.4", - "symfony/var-dumper": "<4.4" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\Cache\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/lib/symfony/config/Builder/ClassBuilder.php b/lib/symfony/config/Builder/ClassBuilder.php deleted file mode 100644 index 9960d6508..000000000 --- a/lib/symfony/config/Builder/ClassBuilder.php +++ /dev/null @@ -1,174 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Builder; - -/** - * Build PHP classes to generate config. - * - * @internal - * - * @author Tobias Nyholm <tobias.nyholm@gmail.com> - */ -class ClassBuilder -{ - /** @var string */ - private $namespace; - - /** @var string */ - private $name; - - /** @var Property[] */ - private $properties = []; - - /** @var Method[] */ - private $methods = []; - private $require = []; - private $use = []; - private $implements = []; - private $allowExtraKeys = false; - - public function __construct(string $namespace, string $name) - { - $this->namespace = $namespace; - $this->name = ucfirst($this->camelCase($name)).'Config'; - } - - public function getDirectory(): string - { - return str_replace('\\', \DIRECTORY_SEPARATOR, $this->namespace); - } - - public function getFilename(): string - { - return $this->name.'.php'; - } - - public function build(): string - { - $rootPath = explode(\DIRECTORY_SEPARATOR, $this->getDirectory()); - $require = ''; - foreach ($this->require as $class) { - // figure out relative path. - $path = explode(\DIRECTORY_SEPARATOR, $class->getDirectory()); - $path[] = $class->getFilename(); - foreach ($rootPath as $key => $value) { - if ($path[$key] !== $value) { - break; - } - unset($path[$key]); - } - $require .= sprintf('require_once __DIR__.\DIRECTORY_SEPARATOR.\'%s\';', implode('\'.\DIRECTORY_SEPARATOR.\'', $path))."\n"; - } - $use = $require ? "\n" : ''; - foreach (array_keys($this->use) as $statement) { - $use .= sprintf('use %s;', $statement)."\n"; - } - - $implements = [] === $this->implements ? '' : 'implements '.implode(', ', $this->implements); - $body = ''; - foreach ($this->properties as $property) { - $body .= ' '.$property->getContent()."\n"; - } - foreach ($this->methods as $method) { - $lines = explode("\n", $method->getContent()); - foreach ($lines as $line) { - $body .= ($line ? ' '.$line : '')."\n"; - } - } - - $content = strtr('<?php - -namespace NAMESPACE; - -REQUIREUSE -/** - * This class is automatically generated to help in creating a config. - */ -class CLASS IMPLEMENTS -{ -BODY -} -', ['NAMESPACE' => $this->namespace, 'REQUIRE' => $require, 'USE' => $use, 'CLASS' => $this->getName(), 'IMPLEMENTS' => $implements, 'BODY' => $body]); - - return $content; - } - - public function addRequire(self $class): void - { - $this->require[] = $class; - } - - public function addUse(string $class): void - { - $this->use[$class] = true; - } - - public function addImplements(string $interface): void - { - $this->implements[] = '\\'.ltrim($interface, '\\'); - } - - public function addMethod(string $name, string $body, array $params = []): void - { - $this->methods[] = new Method(strtr($body, ['NAME' => $this->camelCase($name)] + $params)); - } - - public function addProperty(string $name, string $classType = null, string $defaultValue = null): Property - { - $property = new Property($name, '_' !== $name[0] ? $this->camelCase($name) : $name); - if (null !== $classType) { - $property->setType($classType); - } - $this->properties[] = $property; - $defaultValue = null !== $defaultValue ? sprintf(' = %s', $defaultValue) : ''; - $property->setContent(sprintf('private $%s%s;', $property->getName(), $defaultValue)); - - return $property; - } - - public function getProperties(): array - { - return $this->properties; - } - - private function camelCase(string $input): string - { - $output = lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $input)))); - - return preg_replace('#\W#', '', $output); - } - - public function getName(): string - { - return $this->name; - } - - public function getNamespace(): string - { - return $this->namespace; - } - - public function getFqcn(): string - { - return '\\'.$this->namespace.'\\'.$this->name; - } - - public function setAllowExtraKeys(bool $allowExtraKeys): void - { - $this->allowExtraKeys = $allowExtraKeys; - } - - public function shouldAllowExtraKeys(): bool - { - return $this->allowExtraKeys; - } -} diff --git a/lib/symfony/config/Builder/ConfigBuilderGenerator.php b/lib/symfony/config/Builder/ConfigBuilderGenerator.php deleted file mode 100644 index c63917bcb..000000000 --- a/lib/symfony/config/Builder/ConfigBuilderGenerator.php +++ /dev/null @@ -1,561 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Builder; - -use Symfony\Component\Config\Definition\ArrayNode; -use Symfony\Component\Config\Definition\BooleanNode; -use Symfony\Component\Config\Definition\ConfigurationInterface; -use Symfony\Component\Config\Definition\EnumNode; -use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; -use Symfony\Component\Config\Definition\FloatNode; -use Symfony\Component\Config\Definition\IntegerNode; -use Symfony\Component\Config\Definition\NodeInterface; -use Symfony\Component\Config\Definition\PrototypedArrayNode; -use Symfony\Component\Config\Definition\ScalarNode; -use Symfony\Component\Config\Definition\VariableNode; -use Symfony\Component\Config\Loader\ParamConfigurator; - -/** - * Generate ConfigBuilders to help create valid config. - * - * @author Tobias Nyholm <tobias.nyholm@gmail.com> - */ -class ConfigBuilderGenerator implements ConfigBuilderGeneratorInterface -{ - /** - * @var ClassBuilder[] - */ - private $classes; - private $outputDir; - - public function __construct(string $outputDir) - { - $this->outputDir = $outputDir; - } - - /** - * @return \Closure that will return the root config class - */ - public function build(ConfigurationInterface $configuration): \Closure - { - $this->classes = []; - - $rootNode = $configuration->getConfigTreeBuilder()->buildTree(); - $rootClass = new ClassBuilder('Symfony\\Config', $rootNode->getName()); - - $path = $this->getFullPath($rootClass); - if (!is_file($path)) { - // Generate the class if the file not exists - $this->classes[] = $rootClass; - $this->buildNode($rootNode, $rootClass, $this->getSubNamespace($rootClass)); - $rootClass->addImplements(ConfigBuilderInterface::class); - $rootClass->addMethod('getExtensionAlias', ' -public function NAME(): string -{ - return \'ALIAS\'; -}', ['ALIAS' => $rootNode->getPath()]); - - $this->writeClasses(); - } - - $loader = \Closure::fromCallable(function () use ($path, $rootClass) { - require_once $path; - $className = $rootClass->getFqcn(); - - return new $className(); - }); - - return $loader; - } - - private function getFullPath(ClassBuilder $class): string - { - $directory = $this->outputDir.\DIRECTORY_SEPARATOR.$class->getDirectory(); - if (!is_dir($directory)) { - @mkdir($directory, 0777, true); - } - - return $directory.\DIRECTORY_SEPARATOR.$class->getFilename(); - } - - private function writeClasses(): void - { - foreach ($this->classes as $class) { - $this->buildConstructor($class); - $this->buildToArray($class); - if ($class->getProperties()) { - $class->addProperty('_usedProperties', null, '[]'); - } - $this->buildSetExtraKey($class); - - file_put_contents($this->getFullPath($class), $class->build()); - } - - $this->classes = []; - } - - private function buildNode(NodeInterface $node, ClassBuilder $class, string $namespace): void - { - if (!$node instanceof ArrayNode) { - throw new \LogicException('The node was expected to be an ArrayNode. This Configuration includes an edge case not supported yet.'); - } - - foreach ($node->getChildren() as $child) { - switch (true) { - case $child instanceof ScalarNode: - $this->handleScalarNode($child, $class); - break; - case $child instanceof PrototypedArrayNode: - $this->handlePrototypedArrayNode($child, $class, $namespace); - break; - case $child instanceof VariableNode: - $this->handleVariableNode($child, $class); - break; - case $child instanceof ArrayNode: - $this->handleArrayNode($child, $class, $namespace); - break; - default: - throw new \RuntimeException(sprintf('Unknown node "%s".', \get_class($child))); - } - } - } - - private function handleArrayNode(ArrayNode $node, ClassBuilder $class, string $namespace): void - { - $childClass = new ClassBuilder($namespace, $node->getName()); - $childClass->setAllowExtraKeys($node->shouldIgnoreExtraKeys()); - $class->addRequire($childClass); - $this->classes[] = $childClass; - - $hasNormalizationClosures = $this->hasNormalizationClosures($node); - $property = $class->addProperty( - $node->getName(), - $this->getType($childClass->getFqcn(), $hasNormalizationClosures) - ); - $body = $hasNormalizationClosures ? ' -/** - * @return CLASS|$this - */ -public function NAME($value = []) -{ - if (!\is_array($value)) { - $this->_usedProperties[\'PROPERTY\'] = true; - $this->PROPERTY = $value; - - return $this; - } - - if (!$this->PROPERTY instanceof CLASS) { - $this->_usedProperties[\'PROPERTY\'] = true; - $this->PROPERTY = new CLASS($value); - } elseif (0 < \func_num_args()) { - throw new InvalidConfigurationException(\'The node created by "NAME()" has already been initialized. You cannot pass values the second time you call NAME().\'); - } - - return $this->PROPERTY; -}' : ' -public function NAME(array $value = []): CLASS -{ - if (null === $this->PROPERTY) { - $this->_usedProperties[\'PROPERTY\'] = true; - $this->PROPERTY = new CLASS($value); - } elseif (0 < \func_num_args()) { - throw new InvalidConfigurationException(\'The node created by "NAME()" has already been initialized. You cannot pass values the second time you call NAME().\'); - } - - return $this->PROPERTY; -}'; - $class->addUse(InvalidConfigurationException::class); - $class->addMethod($node->getName(), $body, ['PROPERTY' => $property->getName(), 'CLASS' => $childClass->getFqcn()]); - - $this->buildNode($node, $childClass, $this->getSubNamespace($childClass)); - } - - private function handleVariableNode(VariableNode $node, ClassBuilder $class): void - { - $comment = $this->getComment($node); - $property = $class->addProperty($node->getName()); - $class->addUse(ParamConfigurator::class); - - $body = ' -/** -COMMENT * @return $this - */ -public function NAME($valueDEFAULT): self -{ - $this->_usedProperties[\'PROPERTY\'] = true; - $this->PROPERTY = $value; - - return $this; -}'; - $class->addMethod($node->getName(), $body, ['PROPERTY' => $property->getName(), 'COMMENT' => $comment, 'DEFAULT' => $node->hasDefaultValue() ? ' = '.var_export($node->getDefaultValue(), true) : '']); - } - - private function handlePrototypedArrayNode(PrototypedArrayNode $node, ClassBuilder $class, string $namespace): void - { - $name = $this->getSingularName($node); - $prototype = $node->getPrototype(); - $methodName = $name; - - $parameterType = $this->getParameterType($prototype); - if (null !== $parameterType || $prototype instanceof ScalarNode) { - $class->addUse(ParamConfigurator::class); - $property = $class->addProperty($node->getName()); - if (null === $key = $node->getKeyAttribute()) { - // This is an array of values; don't use singular name - $body = ' -/** - * @param ParamConfigurator|list<TYPE|ParamConfigurator> $value - * @return $this - */ -public function NAME($value): self -{ - $this->_usedProperties[\'PROPERTY\'] = true; - $this->PROPERTY = $value; - - return $this; -}'; - - $class->addMethod($node->getName(), $body, ['PROPERTY' => $property->getName(), 'TYPE' => '' === $parameterType ? 'mixed' : $parameterType]); - } else { - $body = ' -/** - * @param ParamConfigurator|TYPE $value - * @return $this - */ -public function NAME(string $VAR, $VALUE): self -{ - $this->_usedProperties[\'PROPERTY\'] = true; - $this->PROPERTY[$VAR] = $VALUE; - - return $this; -}'; - - $class->addMethod($methodName, $body, ['PROPERTY' => $property->getName(), 'TYPE' => '' === $parameterType ? 'mixed' : $parameterType, 'VAR' => '' === $key ? 'key' : $key, 'VALUE' => 'value' === $key ? 'data' : 'value']); - } - - return; - } - - $childClass = new ClassBuilder($namespace, $name); - if ($prototype instanceof ArrayNode) { - $childClass->setAllowExtraKeys($prototype->shouldIgnoreExtraKeys()); - } - $class->addRequire($childClass); - $this->classes[] = $childClass; - - $hasNormalizationClosures = $this->hasNormalizationClosures($node) || $this->hasNormalizationClosures($prototype); - $property = $class->addProperty( - $node->getName(), - $this->getType($childClass->getFqcn().'[]', $hasNormalizationClosures) - ); - - if (null === $key = $node->getKeyAttribute()) { - $body = $hasNormalizationClosures ? ' -/** - * @return CLASS|$this - */ -public function NAME($value = []) -{ - $this->_usedProperties[\'PROPERTY\'] = true; - if (!\is_array($value)) { - $this->PROPERTY[] = $value; - - return $this; - } - - return $this->PROPERTY[] = new CLASS($value); -}' : ' -public function NAME(array $value = []): CLASS -{ - $this->_usedProperties[\'PROPERTY\'] = true; - - return $this->PROPERTY[] = new CLASS($value); -}'; - $class->addMethod($methodName, $body, ['PROPERTY' => $property->getName(), 'CLASS' => $childClass->getFqcn()]); - } else { - $body = $hasNormalizationClosures ? ' -/** - * @return CLASS|$this - */ -public function NAME(string $VAR, $VALUE = []) -{ - if (!\is_array($VALUE)) { - $this->_usedProperties[\'PROPERTY\'] = true; - $this->PROPERTY[$VAR] = $VALUE; - - return $this; - } - - if (!isset($this->PROPERTY[$VAR]) || !$this->PROPERTY[$VAR] instanceof CLASS) { - $this->_usedProperties[\'PROPERTY\'] = true; - $this->PROPERTY[$VAR] = new CLASS($VALUE); - } elseif (1 < \func_num_args()) { - throw new InvalidConfigurationException(\'The node created by "NAME()" has already been initialized. You cannot pass values the second time you call NAME().\'); - } - - return $this->PROPERTY[$VAR]; -}' : ' -public function NAME(string $VAR, array $VALUE = []): CLASS -{ - if (!isset($this->PROPERTY[$VAR])) { - $this->_usedProperties[\'PROPERTY\'] = true; - $this->PROPERTY[$VAR] = new CLASS($VALUE); - } elseif (1 < \func_num_args()) { - throw new InvalidConfigurationException(\'The node created by "NAME()" has already been initialized. You cannot pass values the second time you call NAME().\'); - } - - return $this->PROPERTY[$VAR]; -}'; - $class->addUse(InvalidConfigurationException::class); - $class->addMethod($methodName, $body, ['PROPERTY' => $property->getName(), 'CLASS' => $childClass->getFqcn(), 'VAR' => '' === $key ? 'key' : $key, 'VALUE' => 'value' === $key ? 'data' : 'value']); - } - - $this->buildNode($prototype, $childClass, $namespace.'\\'.$childClass->getName()); - } - - private function handleScalarNode(ScalarNode $node, ClassBuilder $class): void - { - $comment = $this->getComment($node); - $property = $class->addProperty($node->getName()); - $class->addUse(ParamConfigurator::class); - - $body = ' -/** -COMMENT * @return $this - */ -public function NAME($value): self -{ - $this->_usedProperties[\'PROPERTY\'] = true; - $this->PROPERTY = $value; - - return $this; -}'; - - $class->addMethod($node->getName(), $body, ['PROPERTY' => $property->getName(), 'COMMENT' => $comment]); - } - - private function getParameterType(NodeInterface $node): ?string - { - if ($node instanceof BooleanNode) { - return 'bool'; - } - - if ($node instanceof IntegerNode) { - return 'int'; - } - - if ($node instanceof FloatNode) { - return 'float'; - } - - if ($node instanceof EnumNode) { - return ''; - } - - if ($node instanceof PrototypedArrayNode && $node->getPrototype() instanceof ScalarNode) { - // This is just an array of variables - return 'array'; - } - - if ($node instanceof VariableNode) { - // mixed - return ''; - } - - return null; - } - - private function getComment(VariableNode $node): string - { - $comment = ''; - if ('' !== $info = (string) $node->getInfo()) { - $comment .= ' * '.$info."\n"; - } - - foreach ((array) ($node->getExample() ?? []) as $example) { - $comment .= ' * @example '.$example."\n"; - } - - if ('' !== $default = $node->getDefaultValue()) { - $comment .= ' * @default '.(null === $default ? 'null' : var_export($default, true))."\n"; - } - - if ($node instanceof EnumNode) { - $comment .= sprintf(' * @param ParamConfigurator|%s $value', implode('|', array_map(function ($a) { - return var_export($a, true); - }, $node->getValues())))."\n"; - } else { - $parameterType = $this->getParameterType($node); - if (null === $parameterType || '' === $parameterType) { - $parameterType = 'mixed'; - } - $comment .= ' * @param ParamConfigurator|'.$parameterType.' $value'."\n"; - } - - if ($node->isDeprecated()) { - $comment .= ' * @deprecated '.$node->getDeprecation($node->getName(), $node->getParent()->getName())['message']."\n"; - } - - return $comment; - } - - /** - * Pick a good singular name. - */ - private function getSingularName(PrototypedArrayNode $node): string - { - $name = $node->getName(); - if ('s' !== substr($name, -1)) { - return $name; - } - - $parent = $node->getParent(); - $mappings = $parent instanceof ArrayNode ? $parent->getXmlRemappings() : []; - foreach ($mappings as $map) { - if ($map[1] === $name) { - $name = $map[0]; - break; - } - } - - return $name; - } - - private function buildToArray(ClassBuilder $class): void - { - $body = '$output = [];'; - foreach ($class->getProperties() as $p) { - $code = '$this->PROPERTY'; - if (null !== $p->getType()) { - if ($p->isArray()) { - $code = $p->areScalarsAllowed() - ? 'array_map(function ($v) { return $v instanceof CLASS ? $v->toArray() : $v; }, $this->PROPERTY)' - : 'array_map(function ($v) { return $v->toArray(); }, $this->PROPERTY)' - ; - } else { - $code = $p->areScalarsAllowed() - ? '$this->PROPERTY instanceof CLASS ? $this->PROPERTY->toArray() : $this->PROPERTY' - : '$this->PROPERTY->toArray()' - ; - } - } - - $body .= strtr(' - if (isset($this->_usedProperties[\'PROPERTY\'])) { - $output[\'ORG_NAME\'] = '.$code.'; - }', ['PROPERTY' => $p->getName(), 'ORG_NAME' => $p->getOriginalName(), 'CLASS' => $p->getType()]); - } - - $extraKeys = $class->shouldAllowExtraKeys() ? ' + $this->_extraKeys' : ''; - - $class->addMethod('toArray', ' -public function NAME(): array -{ - '.$body.' - - return $output'.$extraKeys.'; -}'); - } - - private function buildConstructor(ClassBuilder $class): void - { - $body = ''; - foreach ($class->getProperties() as $p) { - $code = '$value[\'ORG_NAME\']'; - if (null !== $p->getType()) { - if ($p->isArray()) { - $code = $p->areScalarsAllowed() - ? 'array_map(function ($v) { return \is_array($v) ? new '.$p->getType().'($v) : $v; }, $value[\'ORG_NAME\'])' - : 'array_map(function ($v) { return new '.$p->getType().'($v); }, $value[\'ORG_NAME\'])' - ; - } else { - $code = $p->areScalarsAllowed() - ? '\is_array($value[\'ORG_NAME\']) ? new '.$p->getType().'($value[\'ORG_NAME\']) : $value[\'ORG_NAME\']' - : 'new '.$p->getType().'($value[\'ORG_NAME\'])' - ; - } - } - - $body .= strtr(' - if (array_key_exists(\'ORG_NAME\', $value)) { - $this->_usedProperties[\'PROPERTY\'] = true; - $this->PROPERTY = '.$code.'; - unset($value[\'ORG_NAME\']); - } -', ['PROPERTY' => $p->getName(), 'ORG_NAME' => $p->getOriginalName()]); - } - - if ($class->shouldAllowExtraKeys()) { - $body .= ' - $this->_extraKeys = $value; -'; - } else { - $body .= ' - if ([] !== $value) { - throw new InvalidConfigurationException(sprintf(\'The following keys are not supported by "%s": \', __CLASS__).implode(\', \', array_keys($value))); - }'; - - $class->addUse(InvalidConfigurationException::class); - } - - $class->addMethod('__construct', ' -public function __construct(array $value = []) -{'.$body.' -}'); - } - - private function buildSetExtraKey(ClassBuilder $class): void - { - if (!$class->shouldAllowExtraKeys()) { - return; - } - - $class->addUse(ParamConfigurator::class); - - $class->addProperty('_extraKeys'); - - $class->addMethod('set', ' -/** - * @param ParamConfigurator|mixed $value - * @return $this - */ -public function NAME(string $key, $value): self -{ - $this->_extraKeys[$key] = $value; - - return $this; -}'); - } - - private function getSubNamespace(ClassBuilder $rootClass): string - { - return sprintf('%s\\%s', $rootClass->getNamespace(), substr($rootClass->getName(), 0, -6)); - } - - private function hasNormalizationClosures(NodeInterface $node): bool - { - try { - $r = new \ReflectionProperty($node, 'normalizationClosures'); - } catch (\ReflectionException $e) { - return false; - } - $r->setAccessible(true); - - return [] !== $r->getValue($node); - } - - private function getType(string $classType, bool $hasNormalizationClosures): string - { - return $classType.($hasNormalizationClosures ? '|scalar' : ''); - } -} diff --git a/lib/symfony/config/Builder/ConfigBuilderGeneratorInterface.php b/lib/symfony/config/Builder/ConfigBuilderGeneratorInterface.php deleted file mode 100644 index c52c9e5d5..000000000 --- a/lib/symfony/config/Builder/ConfigBuilderGeneratorInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Builder; - -use Symfony\Component\Config\Definition\ConfigurationInterface; - -/** - * Generates ConfigBuilders to help create valid config. - * - * @author Tobias Nyholm <tobias.nyholm@gmail.com> - */ -interface ConfigBuilderGeneratorInterface -{ - /** - * @return \Closure that will return the root config class - */ - public function build(ConfigurationInterface $configuration): \Closure; -} diff --git a/lib/symfony/config/Builder/ConfigBuilderInterface.php b/lib/symfony/config/Builder/ConfigBuilderInterface.php deleted file mode 100644 index fd3129c58..000000000 --- a/lib/symfony/config/Builder/ConfigBuilderInterface.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Builder; - -/** - * A ConfigBuilder provides helper methods to build a large complex array. - * - * @author Tobias Nyholm <tobias.nyholm@gmail.com> - */ -interface ConfigBuilderInterface -{ - /** - * Gets all configuration represented as an array. - */ - public function toArray(): array; - - /** - * Gets the alias for the extension which config we are building. - */ - public function getExtensionAlias(): string; -} diff --git a/lib/symfony/config/Builder/Method.php b/lib/symfony/config/Builder/Method.php deleted file mode 100644 index 3577e3d7a..000000000 --- a/lib/symfony/config/Builder/Method.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Builder; - -/** - * Represents a method when building classes. - * - * @internal - * - * @author Tobias Nyholm <tobias.nyholm@gmail.com> - */ -class Method -{ - private $content; - - public function __construct(string $content) - { - $this->content = $content; - } - - public function getContent(): string - { - return $this->content; - } -} diff --git a/lib/symfony/config/Builder/Property.php b/lib/symfony/config/Builder/Property.php deleted file mode 100644 index 5a6f7e31b..000000000 --- a/lib/symfony/config/Builder/Property.php +++ /dev/null @@ -1,86 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Builder; - -/** - * Represents a property when building classes. - * - * @internal - * - * @author Tobias Nyholm <tobias.nyholm@gmail.com> - */ -class Property -{ - private $name; - private $originalName; - private $array = false; - private $scalarsAllowed = false; - private $type = null; - private $content; - - public function __construct(string $originalName, string $name) - { - $this->name = $name; - $this->originalName = $originalName; - } - - public function getName(): string - { - return $this->name; - } - - public function getOriginalName(): string - { - return $this->originalName; - } - - public function setType(string $type): void - { - $this->array = false; - $this->type = $type; - - if ('|scalar' === substr($type, -7)) { - $this->scalarsAllowed = true; - $this->type = $type = substr($type, 0, -7); - } - - if ('[]' === substr($type, -2)) { - $this->array = true; - $this->type = substr($type, 0, -2); - } - } - - public function getType(): ?string - { - return $this->type; - } - - public function getContent(): ?string - { - return $this->content; - } - - public function setContent(string $content): void - { - $this->content = $content; - } - - public function isArray(): bool - { - return $this->array; - } - - public function areScalarsAllowed(): bool - { - return $this->scalarsAllowed; - } -} diff --git a/lib/symfony/config/CHANGELOG.md b/lib/symfony/config/CHANGELOG.md deleted file mode 100644 index 75ef8bc44..000000000 --- a/lib/symfony/config/CHANGELOG.md +++ /dev/null @@ -1,129 +0,0 @@ -CHANGELOG -========= - -5.3.0 ------ - - * Add support for generating `ConfigBuilder` for extensions - -5.1.0 ------ - - * updated the signature of method `NodeDefinition::setDeprecated()` to `NodeDefinition::setDeprecation(string $package, string $version, string $message)` - * updated the signature of method `BaseNode::setDeprecated()` to `BaseNode::setDeprecation(string $package, string $version, string $message)` - * deprecated passing a null message to `BaseNode::setDeprecated()` to un-deprecate a node - * deprecated `BaseNode::getDeprecationMessage()`, use `BaseNode::getDeprecation()` instead - -5.0.0 ------ - - * Dropped support for constructing a `TreeBuilder` without passing root node information. - * Removed the `root()` method in `TreeBuilder`, pass the root node information to the constructor instead - * Added method `getChildNodeDefinitions()` to ParentNodeDefinitionInterface - * Removed `FileLoaderLoadException`, use `LoaderLoadException` instead - -4.4.0 ------ - - * added a way to exclude patterns of resources from being imported by the `import()` method - -4.3.0 ------ - - * deprecated using environment variables with `cannotBeEmpty()` if the value is validated with `validate()` - * made `Resource\*` classes final and not implement `Serializable` anymore - * deprecated the `root()` method in `TreeBuilder`, pass the root node information to the constructor instead - -4.2.0 ------ - - * deprecated constructing a `TreeBuilder` without passing root node information - * renamed `FileLoaderLoadException` to `LoaderLoadException` - -4.1.0 ------ - - * added `setPathSeparator` method to `NodeBuilder` class - * added third `$pathSeparator` constructor argument to `BaseNode` - * the `Processor` class has been made final - -4.0.0 ------ - - * removed `ConfigCachePass` - -3.4.0 ------ - - * added `setDeprecated()` method to indicate a deprecated node - * added `XmlUtils::parse()` method to parse an XML string - * deprecated `ConfigCachePass` - -3.3.0 ------ - - * added `ReflectionClassResource` class - * added second `$exists` constructor argument to `ClassExistenceResource` - * made `ClassExistenceResource` work with interfaces and traits - * added `ConfigCachePass` (originally in FrameworkBundle) - * added `castToArray()` helper to turn any config value into an array - -3.0.0 ------ - - * removed `ReferenceDumper` class - * removed the `ResourceInterface::isFresh()` method - * removed `BCResourceInterfaceChecker` class - * removed `ResourceInterface::getResource()` method - -2.8.0 ------ - -The edge case of defining just one value for nodes of type Enum is now allowed: - -```php -$rootNode - ->children() - ->enumNode('variable') - ->values(['value']) - ->end() - ->end() -; -``` - -Before: `InvalidArgumentException` (variable must contain at least two -distinct elements). -After: the code will work as expected and it will restrict the values of the -`variable` option to just `value`. - - * deprecated the `ResourceInterface::isFresh()` method. If you implement custom resource types and they - can be validated that way, make them implement the new `SelfCheckingResourceInterface`. - * deprecated the getResource() method in ResourceInterface. You can still call this method - on concrete classes implementing the interface, but it does not make sense at the interface - level as you need to know about the particular type of resource at hand to understand the - semantics of the returned value. - -2.7.0 ------ - - * added `ConfigCacheInterface`, `ConfigCacheFactoryInterface` and a basic `ConfigCacheFactory` - implementation to delegate creation of ConfigCache instances - -2.2.0 ------ - - * added `ArrayNodeDefinition::canBeEnabled()` and `ArrayNodeDefinition::canBeDisabled()` - to ease configuration when some sections are respectively disabled / enabled - by default. - * added a `normalizeKeys()` method for array nodes (to avoid key normalization) - * added numerical type handling for config definitions - * added convenience methods for optional configuration sections to `ArrayNodeDefinition` - * added a utils class for XML manipulations - -2.1.0 ------ - - * added a way to add documentation on configuration - * implemented `Serializable` on resources - * `LoaderResolverInterface` is now used instead of `LoaderResolver` for type - hinting diff --git a/lib/symfony/config/ConfigCache.php b/lib/symfony/config/ConfigCache.php deleted file mode 100644 index 3b090525e..000000000 --- a/lib/symfony/config/ConfigCache.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config; - -use Symfony\Component\Config\Resource\SelfCheckingResourceChecker; - -/** - * ConfigCache caches arbitrary content in files on disk. - * - * When in debug mode, those metadata resources that implement - * \Symfony\Component\Config\Resource\SelfCheckingResourceInterface will - * be used to check cache freshness. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Matthias Pigulla <mp@webfactory.de> - */ -class ConfigCache extends ResourceCheckerConfigCache -{ - private $debug; - - /** - * @param string $file The absolute cache path - * @param bool $debug Whether debugging is enabled or not - */ - public function __construct(string $file, bool $debug) - { - $this->debug = $debug; - - $checkers = []; - if (true === $this->debug) { - $checkers = [new SelfCheckingResourceChecker()]; - } - - parent::__construct($file, $checkers); - } - - /** - * Checks if the cache is still fresh. - * - * This implementation always returns true when debug is off and the - * cache file exists. - * - * @return bool - */ - public function isFresh() - { - if (!$this->debug && is_file($this->getPath())) { - return true; - } - - return parent::isFresh(); - } -} diff --git a/lib/symfony/config/ConfigCacheFactory.php b/lib/symfony/config/ConfigCacheFactory.php deleted file mode 100644 index 11fd3cb3a..000000000 --- a/lib/symfony/config/ConfigCacheFactory.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config; - -/** - * Basic implementation of ConfigCacheFactoryInterface that - * creates an instance of the default ConfigCache. - * - * This factory and/or cache <em>do not</em> support cache validation - * by means of ResourceChecker instances (that is, service-based). - * - * @author Matthias Pigulla <mp@webfactory.de> - */ -class ConfigCacheFactory implements ConfigCacheFactoryInterface -{ - private $debug; - - /** - * @param bool $debug The debug flag to pass to ConfigCache - */ - public function __construct(bool $debug) - { - $this->debug = $debug; - } - - /** - * {@inheritdoc} - */ - public function cache(string $file, callable $callback) - { - $cache = new ConfigCache($file, $this->debug); - if (!$cache->isFresh()) { - $callback($cache); - } - - return $cache; - } -} diff --git a/lib/symfony/config/ConfigCacheFactoryInterface.php b/lib/symfony/config/ConfigCacheFactoryInterface.php deleted file mode 100644 index 146ee9b56..000000000 --- a/lib/symfony/config/ConfigCacheFactoryInterface.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config; - -/** - * Interface for a ConfigCache factory. This factory creates - * an instance of ConfigCacheInterface and initializes the - * cache if necessary. - * - * @author Matthias Pigulla <mp@webfactory.de> - */ -interface ConfigCacheFactoryInterface -{ - /** - * Creates a cache instance and (re-)initializes it if necessary. - * - * @param string $file The absolute cache file path - * @param callable $callable The callable to be executed when the cache needs to be filled (i. e. is not fresh). The cache will be passed as the only parameter to this callback - * - * @return ConfigCacheInterface - */ - public function cache(string $file, callable $callable); -} diff --git a/lib/symfony/config/ConfigCacheInterface.php b/lib/symfony/config/ConfigCacheInterface.php deleted file mode 100644 index 3cd7a5cc0..000000000 --- a/lib/symfony/config/ConfigCacheInterface.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config; - -use Symfony\Component\Config\Resource\ResourceInterface; - -/** - * Interface for ConfigCache. - * - * @author Matthias Pigulla <mp@webfactory.de> - */ -interface ConfigCacheInterface -{ - /** - * Gets the cache file path. - * - * @return string - */ - public function getPath(); - - /** - * Checks if the cache is still fresh. - * - * This check should take the metadata passed to the write() method into consideration. - * - * @return bool - */ - public function isFresh(); - - /** - * Writes the given content into the cache file. Metadata will be stored - * independently and can be used to check cache freshness at a later time. - * - * @param string $content The content to write into the cache - * @param ResourceInterface[]|null $metadata An array of ResourceInterface instances - * - * @throws \RuntimeException When the cache file cannot be written - */ - public function write(string $content, array $metadata = null); -} diff --git a/lib/symfony/config/Definition/ArrayNode.php b/lib/symfony/config/Definition/ArrayNode.php deleted file mode 100644 index bd0eae9fd..000000000 --- a/lib/symfony/config/Definition/ArrayNode.php +++ /dev/null @@ -1,404 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; -use Symfony\Component\Config\Definition\Exception\InvalidTypeException; -use Symfony\Component\Config\Definition\Exception\UnsetKeyException; - -/** - * Represents an Array node in the config tree. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class ArrayNode extends BaseNode implements PrototypeNodeInterface -{ - protected $xmlRemappings = []; - protected $children = []; - protected $allowFalse = false; - protected $allowNewKeys = true; - protected $addIfNotSet = false; - protected $performDeepMerging = true; - protected $ignoreExtraKeys = false; - protected $removeExtraKeys = true; - protected $normalizeKeys = true; - - public function setNormalizeKeys(bool $normalizeKeys) - { - $this->normalizeKeys = $normalizeKeys; - } - - /** - * {@inheritdoc} - * - * Namely, you mostly have foo_bar in YAML while you have foo-bar in XML. - * After running this method, all keys are normalized to foo_bar. - * - * If you have a mixed key like foo-bar_moo, it will not be altered. - * The key will also not be altered if the target key already exists. - */ - protected function preNormalize($value) - { - if (!$this->normalizeKeys || !\is_array($value)) { - return $value; - } - - $normalized = []; - - foreach ($value as $k => $v) { - if (str_contains($k, '-') && !str_contains($k, '_') && !\array_key_exists($normalizedKey = str_replace('-', '_', $k), $value)) { - $normalized[$normalizedKey] = $v; - } else { - $normalized[$k] = $v; - } - } - - return $normalized; - } - - /** - * Retrieves the children of this node. - * - * @return array<string, NodeInterface> - */ - public function getChildren() - { - return $this->children; - } - - /** - * Sets the xml remappings that should be performed. - * - * @param array $remappings An array of the form [[string, string]] - */ - public function setXmlRemappings(array $remappings) - { - $this->xmlRemappings = $remappings; - } - - /** - * Gets the xml remappings that should be performed. - * - * @return array an array of the form [[string, string]] - */ - public function getXmlRemappings() - { - return $this->xmlRemappings; - } - - /** - * Sets whether to add default values for this array if it has not been - * defined in any of the configuration files. - */ - public function setAddIfNotSet(bool $boolean) - { - $this->addIfNotSet = $boolean; - } - - /** - * Sets whether false is allowed as value indicating that the array should be unset. - */ - public function setAllowFalse(bool $allow) - { - $this->allowFalse = $allow; - } - - /** - * Sets whether new keys can be defined in subsequent configurations. - */ - public function setAllowNewKeys(bool $allow) - { - $this->allowNewKeys = $allow; - } - - /** - * Sets if deep merging should occur. - */ - public function setPerformDeepMerging(bool $boolean) - { - $this->performDeepMerging = $boolean; - } - - /** - * Whether extra keys should just be ignored without an exception. - * - * @param bool $boolean To allow extra keys - * @param bool $remove To remove extra keys - */ - public function setIgnoreExtraKeys(bool $boolean, bool $remove = true) - { - $this->ignoreExtraKeys = $boolean; - $this->removeExtraKeys = $this->ignoreExtraKeys && $remove; - } - - /** - * Returns true when extra keys should be ignored without an exception. - */ - public function shouldIgnoreExtraKeys(): bool - { - return $this->ignoreExtraKeys; - } - - /** - * {@inheritdoc} - */ - public function setName(string $name) - { - $this->name = $name; - } - - /** - * {@inheritdoc} - */ - public function hasDefaultValue() - { - return $this->addIfNotSet; - } - - /** - * {@inheritdoc} - */ - public function getDefaultValue() - { - if (!$this->hasDefaultValue()) { - throw new \RuntimeException(sprintf('The node at path "%s" has no default value.', $this->getPath())); - } - - $defaults = []; - foreach ($this->children as $name => $child) { - if ($child->hasDefaultValue()) { - $defaults[$name] = $child->getDefaultValue(); - } - } - - return $defaults; - } - - /** - * Adds a child node. - * - * @throws \InvalidArgumentException when the child node has no name - * @throws \InvalidArgumentException when the child node's name is not unique - */ - public function addChild(NodeInterface $node) - { - $name = $node->getName(); - if ('' === $name) { - throw new \InvalidArgumentException('Child nodes must be named.'); - } - if (isset($this->children[$name])) { - throw new \InvalidArgumentException(sprintf('A child node named "%s" already exists.', $name)); - } - - $this->children[$name] = $node; - } - - /** - * {@inheritdoc} - * - * @throws UnsetKeyException - * @throws InvalidConfigurationException if the node doesn't have enough children - */ - protected function finalizeValue($value) - { - if (false === $value) { - throw new UnsetKeyException(sprintf('Unsetting key for path "%s", value: %s.', $this->getPath(), json_encode($value))); - } - - foreach ($this->children as $name => $child) { - if (!\array_key_exists($name, $value)) { - if ($child->isRequired()) { - $message = sprintf('The child config "%s" under "%s" must be configured', $name, $this->getPath()); - if ($child->getInfo()) { - $message .= sprintf(': %s', $child->getInfo()); - } else { - $message .= '.'; - } - $ex = new InvalidConfigurationException($message); - $ex->setPath($this->getPath()); - - throw $ex; - } - - if ($child->hasDefaultValue()) { - $value[$name] = $child->getDefaultValue(); - } - - continue; - } - - if ($child->isDeprecated()) { - $deprecation = $child->getDeprecation($name, $this->getPath()); - trigger_deprecation($deprecation['package'], $deprecation['version'], $deprecation['message']); - } - - try { - $value[$name] = $child->finalize($value[$name]); - } catch (UnsetKeyException $e) { - unset($value[$name]); - } - } - - return $value; - } - - /** - * {@inheritdoc} - */ - protected function validateType($value) - { - if (!\is_array($value) && (!$this->allowFalse || false !== $value)) { - $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected "array", but got "%s"', $this->getPath(), get_debug_type($value))); - if ($hint = $this->getInfo()) { - $ex->addHint($hint); - } - $ex->setPath($this->getPath()); - - throw $ex; - } - } - - /** - * {@inheritdoc} - * - * @throws InvalidConfigurationException - */ - protected function normalizeValue($value) - { - if (false === $value) { - return $value; - } - - $value = $this->remapXml($value); - - $normalized = []; - foreach ($value as $name => $val) { - if (isset($this->children[$name])) { - try { - $normalized[$name] = $this->children[$name]->normalize($val); - } catch (UnsetKeyException $e) { - } - unset($value[$name]); - } elseif (!$this->removeExtraKeys) { - $normalized[$name] = $val; - } - } - - // if extra fields are present, throw exception - if (\count($value) && !$this->ignoreExtraKeys) { - $proposals = array_keys($this->children); - sort($proposals); - $guesses = []; - - foreach (array_keys($value) as $subject) { - $minScore = \INF; - foreach ($proposals as $proposal) { - $distance = levenshtein($subject, $proposal); - if ($distance <= $minScore && $distance < 3) { - $guesses[$proposal] = $distance; - $minScore = $distance; - } - } - } - - $msg = sprintf('Unrecognized option%s "%s" under "%s"', 1 === \count($value) ? '' : 's', implode(', ', array_keys($value)), $this->getPath()); - - if (\count($guesses)) { - asort($guesses); - $msg .= sprintf('. Did you mean "%s"?', implode('", "', array_keys($guesses))); - } else { - $msg .= sprintf('. Available option%s %s "%s".', 1 === \count($proposals) ? '' : 's', 1 === \count($proposals) ? 'is' : 'are', implode('", "', $proposals)); - } - - $ex = new InvalidConfigurationException($msg); - $ex->setPath($this->getPath()); - - throw $ex; - } - - return $normalized; - } - - /** - * Remaps multiple singular values to a single plural value. - * - * @return array - */ - protected function remapXml(array $value) - { - foreach ($this->xmlRemappings as [$singular, $plural]) { - if (!isset($value[$singular])) { - continue; - } - - $value[$plural] = Processor::normalizeConfig($value, $singular, $plural); - unset($value[$singular]); - } - - return $value; - } - - /** - * {@inheritdoc} - * - * @throws InvalidConfigurationException - * @throws \RuntimeException - */ - protected function mergeValues($leftSide, $rightSide) - { - if (false === $rightSide) { - // if this is still false after the last config has been merged the - // finalization pass will take care of removing this key entirely - return false; - } - - if (false === $leftSide || !$this->performDeepMerging) { - return $rightSide; - } - - foreach ($rightSide as $k => $v) { - // no conflict - if (!\array_key_exists($k, $leftSide)) { - if (!$this->allowNewKeys) { - $ex = new InvalidConfigurationException(sprintf('You are not allowed to define new elements for path "%s". Please define all elements for this path in one config file. If you are trying to overwrite an element, make sure you redefine it with the same name.', $this->getPath())); - $ex->setPath($this->getPath()); - - throw $ex; - } - - $leftSide[$k] = $v; - continue; - } - - if (!isset($this->children[$k])) { - if (!$this->ignoreExtraKeys || $this->removeExtraKeys) { - throw new \RuntimeException('merge() expects a normalized config array.'); - } - - $leftSide[$k] = $v; - continue; - } - - $leftSide[$k] = $this->children[$k]->merge($leftSide[$k], $v); - } - - return $leftSide; - } - - /** - * {@inheritdoc} - */ - protected function allowPlaceholders(): bool - { - return false; - } -} diff --git a/lib/symfony/config/Definition/BaseNode.php b/lib/symfony/config/Definition/BaseNode.php deleted file mode 100644 index 673cfaf60..000000000 --- a/lib/symfony/config/Definition/BaseNode.php +++ /dev/null @@ -1,589 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -use Symfony\Component\Config\Definition\Exception\Exception; -use Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException; -use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; -use Symfony\Component\Config\Definition\Exception\InvalidTypeException; -use Symfony\Component\Config\Definition\Exception\UnsetKeyException; - -/** - * The base node class. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -abstract class BaseNode implements NodeInterface -{ - public const DEFAULT_PATH_SEPARATOR = '.'; - - private static $placeholderUniquePrefixes = []; - private static $placeholders = []; - - protected $name; - protected $parent; - protected $normalizationClosures = []; - protected $finalValidationClosures = []; - protected $allowOverwrite = true; - protected $required = false; - protected $deprecation = []; - protected $equivalentValues = []; - protected $attributes = []; - protected $pathSeparator; - - private $handlingPlaceholder; - - /** - * @throws \InvalidArgumentException if the name contains a period - */ - public function __construct(?string $name, NodeInterface $parent = null, string $pathSeparator = self::DEFAULT_PATH_SEPARATOR) - { - if (str_contains($name = (string) $name, $pathSeparator)) { - throw new \InvalidArgumentException('The name must not contain ".'.$pathSeparator.'".'); - } - - $this->name = $name; - $this->parent = $parent; - $this->pathSeparator = $pathSeparator; - } - - /** - * Register possible (dummy) values for a dynamic placeholder value. - * - * Matching configuration values will be processed with a provided value, one by one. After a provided value is - * successfully processed the configuration value is returned as is, thus preserving the placeholder. - * - * @internal - */ - public static function setPlaceholder(string $placeholder, array $values): void - { - if (!$values) { - throw new \InvalidArgumentException('At least one value must be provided.'); - } - - self::$placeholders[$placeholder] = $values; - } - - /** - * Adds a common prefix for dynamic placeholder values. - * - * Matching configuration values will be skipped from being processed and are returned as is, thus preserving the - * placeholder. An exact match provided by {@see setPlaceholder()} might take precedence. - * - * @internal - */ - public static function setPlaceholderUniquePrefix(string $prefix): void - { - self::$placeholderUniquePrefixes[] = $prefix; - } - - /** - * Resets all current placeholders available. - * - * @internal - */ - public static function resetPlaceholders(): void - { - self::$placeholderUniquePrefixes = []; - self::$placeholders = []; - } - - public function setAttribute(string $key, $value) - { - $this->attributes[$key] = $value; - } - - /** - * @return mixed - */ - public function getAttribute(string $key, $default = null) - { - return $this->attributes[$key] ?? $default; - } - - /** - * @return bool - */ - public function hasAttribute(string $key) - { - return isset($this->attributes[$key]); - } - - /** - * @return array - */ - public function getAttributes() - { - return $this->attributes; - } - - public function setAttributes(array $attributes) - { - $this->attributes = $attributes; - } - - public function removeAttribute(string $key) - { - unset($this->attributes[$key]); - } - - /** - * Sets an info message. - */ - public function setInfo(string $info) - { - $this->setAttribute('info', $info); - } - - /** - * Returns info message. - * - * @return string|null - */ - public function getInfo() - { - return $this->getAttribute('info'); - } - - /** - * Sets the example configuration for this node. - * - * @param string|array $example - */ - public function setExample($example) - { - $this->setAttribute('example', $example); - } - - /** - * Retrieves the example configuration for this node. - * - * @return string|array|null - */ - public function getExample() - { - return $this->getAttribute('example'); - } - - /** - * Adds an equivalent value. - * - * @param mixed $originalValue - * @param mixed $equivalentValue - */ - public function addEquivalentValue($originalValue, $equivalentValue) - { - $this->equivalentValues[] = [$originalValue, $equivalentValue]; - } - - /** - * Set this node as required. - */ - public function setRequired(bool $boolean) - { - $this->required = $boolean; - } - - /** - * Sets this node as deprecated. - * - * @param string $package The name of the composer package that is triggering the deprecation - * @param string $version The version of the package that introduced the deprecation - * @param string $message the deprecation message to use - * - * You can use %node% and %path% placeholders in your message to display, - * respectively, the node name and its complete path - */ - public function setDeprecated(?string $package/* , string $version, string $message = 'The child node "%node%" at path "%path%" is deprecated.' */) - { - $args = \func_get_args(); - - if (\func_num_args() < 2) { - trigger_deprecation('symfony/config', '5.1', 'The signature of method "%s()" requires 3 arguments: "string $package, string $version, string $message", not defining them is deprecated.', __METHOD__); - - if (!isset($args[0])) { - trigger_deprecation('symfony/config', '5.1', 'Passing a null message to un-deprecate a node is deprecated.'); - - $this->deprecation = []; - - return; - } - - $message = (string) $args[0]; - $package = $version = ''; - } else { - $package = (string) $args[0]; - $version = (string) $args[1]; - $message = (string) ($args[2] ?? 'The child node "%node%" at path "%path%" is deprecated.'); - } - - $this->deprecation = [ - 'package' => $package, - 'version' => $version, - 'message' => $message, - ]; - } - - /** - * Sets if this node can be overridden. - */ - public function setAllowOverwrite(bool $allow) - { - $this->allowOverwrite = $allow; - } - - /** - * Sets the closures used for normalization. - * - * @param \Closure[] $closures An array of Closures used for normalization - */ - public function setNormalizationClosures(array $closures) - { - $this->normalizationClosures = $closures; - } - - /** - * Sets the closures used for final validation. - * - * @param \Closure[] $closures An array of Closures used for final validation - */ - public function setFinalValidationClosures(array $closures) - { - $this->finalValidationClosures = $closures; - } - - /** - * {@inheritdoc} - */ - public function isRequired() - { - return $this->required; - } - - /** - * Checks if this node is deprecated. - * - * @return bool - */ - public function isDeprecated() - { - return (bool) $this->deprecation; - } - - /** - * Returns the deprecated message. - * - * @param string $node the configuration node name - * @param string $path the path of the node - * - * @return string - * - * @deprecated since Symfony 5.1, use "getDeprecation()" instead. - */ - public function getDeprecationMessage(string $node, string $path) - { - trigger_deprecation('symfony/config', '5.1', 'The "%s()" method is deprecated, use "getDeprecation()" instead.', __METHOD__); - - return $this->getDeprecation($node, $path)['message']; - } - - /** - * @param string $node The configuration node name - * @param string $path The path of the node - */ - public function getDeprecation(string $node, string $path): array - { - return [ - 'package' => $this->deprecation['package'] ?? '', - 'version' => $this->deprecation['version'] ?? '', - 'message' => strtr($this->deprecation['message'] ?? '', ['%node%' => $node, '%path%' => $path]), - ]; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->name; - } - - /** - * {@inheritdoc} - */ - public function getPath() - { - if (null !== $this->parent) { - return $this->parent->getPath().$this->pathSeparator.$this->name; - } - - return $this->name; - } - - /** - * {@inheritdoc} - */ - final public function merge($leftSide, $rightSide) - { - if (!$this->allowOverwrite) { - throw new ForbiddenOverwriteException(sprintf('Configuration path "%s" cannot be overwritten. You have to define all options for this path, and any of its sub-paths in one configuration section.', $this->getPath())); - } - - if ($leftSide !== $leftPlaceholders = self::resolvePlaceholderValue($leftSide)) { - foreach ($leftPlaceholders as $leftPlaceholder) { - $this->handlingPlaceholder = $leftSide; - try { - $this->merge($leftPlaceholder, $rightSide); - } finally { - $this->handlingPlaceholder = null; - } - } - - return $rightSide; - } - - if ($rightSide !== $rightPlaceholders = self::resolvePlaceholderValue($rightSide)) { - foreach ($rightPlaceholders as $rightPlaceholder) { - $this->handlingPlaceholder = $rightSide; - try { - $this->merge($leftSide, $rightPlaceholder); - } finally { - $this->handlingPlaceholder = null; - } - } - - return $rightSide; - } - - $this->doValidateType($leftSide); - $this->doValidateType($rightSide); - - return $this->mergeValues($leftSide, $rightSide); - } - - /** - * {@inheritdoc} - */ - final public function normalize($value) - { - $value = $this->preNormalize($value); - - // run custom normalization closures - foreach ($this->normalizationClosures as $closure) { - $value = $closure($value); - } - - // resolve placeholder value - if ($value !== $placeholders = self::resolvePlaceholderValue($value)) { - foreach ($placeholders as $placeholder) { - $this->handlingPlaceholder = $value; - try { - $this->normalize($placeholder); - } finally { - $this->handlingPlaceholder = null; - } - } - - return $value; - } - - // replace value with their equivalent - foreach ($this->equivalentValues as $data) { - if ($data[0] === $value) { - $value = $data[1]; - } - } - - // validate type - $this->doValidateType($value); - - // normalize value - return $this->normalizeValue($value); - } - - /** - * Normalizes the value before any other normalization is applied. - * - * @param mixed $value - * - * @return mixed - */ - protected function preNormalize($value) - { - return $value; - } - - /** - * Returns parent node for this node. - * - * @return NodeInterface|null - */ - public function getParent() - { - return $this->parent; - } - - /** - * {@inheritdoc} - */ - final public function finalize($value) - { - if ($value !== $placeholders = self::resolvePlaceholderValue($value)) { - foreach ($placeholders as $placeholder) { - $this->handlingPlaceholder = $value; - try { - $this->finalize($placeholder); - } finally { - $this->handlingPlaceholder = null; - } - } - - return $value; - } - - $this->doValidateType($value); - - $value = $this->finalizeValue($value); - - // Perform validation on the final value if a closure has been set. - // The closure is also allowed to return another value. - foreach ($this->finalValidationClosures as $closure) { - try { - $value = $closure($value); - } catch (Exception $e) { - if ($e instanceof UnsetKeyException && null !== $this->handlingPlaceholder) { - continue; - } - - throw $e; - } catch (\Exception $e) { - throw new InvalidConfigurationException(sprintf('Invalid configuration for path "%s": ', $this->getPath()).$e->getMessage(), $e->getCode(), $e); - } - } - - return $value; - } - - /** - * Validates the type of a Node. - * - * @param mixed $value The value to validate - * - * @throws InvalidTypeException when the value is invalid - */ - abstract protected function validateType($value); - - /** - * Normalizes the value. - * - * @param mixed $value The value to normalize - * - * @return mixed - */ - abstract protected function normalizeValue($value); - - /** - * Merges two values together. - * - * @param mixed $leftSide - * @param mixed $rightSide - * - * @return mixed - */ - abstract protected function mergeValues($leftSide, $rightSide); - - /** - * Finalizes a value. - * - * @param mixed $value The value to finalize - * - * @return mixed - */ - abstract protected function finalizeValue($value); - - /** - * Tests if placeholder values are allowed for this node. - */ - protected function allowPlaceholders(): bool - { - return true; - } - - /** - * Tests if a placeholder is being handled currently. - */ - protected function isHandlingPlaceholder(): bool - { - return null !== $this->handlingPlaceholder; - } - - /** - * Gets allowed dynamic types for this node. - */ - protected function getValidPlaceholderTypes(): array - { - return []; - } - - private static function resolvePlaceholderValue($value) - { - if (\is_string($value)) { - if (isset(self::$placeholders[$value])) { - return self::$placeholders[$value]; - } - - foreach (self::$placeholderUniquePrefixes as $placeholderUniquePrefix) { - if (str_starts_with($value, $placeholderUniquePrefix)) { - return []; - } - } - } - - return $value; - } - - private function doValidateType($value): void - { - if (null !== $this->handlingPlaceholder && !$this->allowPlaceholders()) { - $e = new InvalidTypeException(sprintf('A dynamic value is not compatible with a "%s" node type at path "%s".', static::class, $this->getPath())); - $e->setPath($this->getPath()); - - throw $e; - } - - if (null === $this->handlingPlaceholder || null === $value) { - $this->validateType($value); - - return; - } - - $knownTypes = array_keys(self::$placeholders[$this->handlingPlaceholder]); - $validTypes = $this->getValidPlaceholderTypes(); - - if ($validTypes && array_diff($knownTypes, $validTypes)) { - $e = new InvalidTypeException(sprintf( - 'Invalid type for path "%s". Expected %s, but got %s.', - $this->getPath(), - 1 === \count($validTypes) ? '"'.reset($validTypes).'"' : 'one of "'.implode('", "', $validTypes).'"', - 1 === \count($knownTypes) ? '"'.reset($knownTypes).'"' : 'one of "'.implode('", "', $knownTypes).'"' - )); - if ($hint = $this->getInfo()) { - $e->addHint($hint); - } - $e->setPath($this->getPath()); - - throw $e; - } - - $this->validateType($value); - } -} diff --git a/lib/symfony/config/Definition/BooleanNode.php b/lib/symfony/config/Definition/BooleanNode.php deleted file mode 100644 index c64ecb839..000000000 --- a/lib/symfony/config/Definition/BooleanNode.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -use Symfony\Component\Config\Definition\Exception\InvalidTypeException; - -/** - * This node represents a Boolean value in the config tree. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class BooleanNode extends ScalarNode -{ - /** - * {@inheritdoc} - */ - protected function validateType($value) - { - if (!\is_bool($value)) { - $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected "bool", but got "%s".', $this->getPath(), get_debug_type($value))); - if ($hint = $this->getInfo()) { - $ex->addHint($hint); - } - $ex->setPath($this->getPath()); - - throw $ex; - } - } - - /** - * {@inheritdoc} - */ - protected function isValueEmpty($value) - { - // a boolean value cannot be empty - return false; - } - - /** - * {@inheritdoc} - */ - protected function getValidPlaceholderTypes(): array - { - return ['bool']; - } -} diff --git a/lib/symfony/config/Definition/Builder/ArrayNodeDefinition.php b/lib/symfony/config/Definition/Builder/ArrayNodeDefinition.php deleted file mode 100644 index eb5b04021..000000000 --- a/lib/symfony/config/Definition/Builder/ArrayNodeDefinition.php +++ /dev/null @@ -1,549 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -use Symfony\Component\Config\Definition\ArrayNode; -use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException; -use Symfony\Component\Config\Definition\PrototypedArrayNode; - -/** - * This class provides a fluent interface for defining an array node. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinitionInterface -{ - protected $performDeepMerging = true; - protected $ignoreExtraKeys = false; - protected $removeExtraKeys = true; - protected $children = []; - protected $prototype; - protected $atLeastOne = false; - protected $allowNewKeys = true; - protected $key; - protected $removeKeyItem; - protected $addDefaults = false; - protected $addDefaultChildren = false; - protected $nodeBuilder; - protected $normalizeKeys = true; - - /** - * {@inheritdoc} - */ - public function __construct(?string $name, NodeParentInterface $parent = null) - { - parent::__construct($name, $parent); - - $this->nullEquivalent = []; - $this->trueEquivalent = []; - } - - /** - * {@inheritdoc} - */ - public function setBuilder(NodeBuilder $builder) - { - $this->nodeBuilder = $builder; - } - - /** - * {@inheritdoc} - */ - public function children() - { - return $this->getNodeBuilder(); - } - - /** - * Sets a prototype for child nodes. - * - * @return NodeDefinition - */ - public function prototype(string $type) - { - return $this->prototype = $this->getNodeBuilder()->node(null, $type)->setParent($this); - } - - /** - * @return VariableNodeDefinition - */ - public function variablePrototype() - { - return $this->prototype('variable'); - } - - /** - * @return ScalarNodeDefinition - */ - public function scalarPrototype() - { - return $this->prototype('scalar'); - } - - /** - * @return BooleanNodeDefinition - */ - public function booleanPrototype() - { - return $this->prototype('boolean'); - } - - /** - * @return IntegerNodeDefinition - */ - public function integerPrototype() - { - return $this->prototype('integer'); - } - - /** - * @return FloatNodeDefinition - */ - public function floatPrototype() - { - return $this->prototype('float'); - } - - /** - * @return ArrayNodeDefinition - */ - public function arrayPrototype() - { - return $this->prototype('array'); - } - - /** - * @return EnumNodeDefinition - */ - public function enumPrototype() - { - return $this->prototype('enum'); - } - - /** - * Adds the default value if the node is not set in the configuration. - * - * This method is applicable to concrete nodes only (not to prototype nodes). - * If this function has been called and the node is not set during the finalization - * phase, it's default value will be derived from its children default values. - * - * @return $this - */ - public function addDefaultsIfNotSet() - { - $this->addDefaults = true; - - return $this; - } - - /** - * Adds children with a default value when none are defined. - * - * This method is applicable to prototype nodes only. - * - * @param int|string|array|null $children The number of children|The child name|The children names to be added - * - * @return $this - */ - public function addDefaultChildrenIfNoneSet($children = null) - { - $this->addDefaultChildren = $children; - - return $this; - } - - /** - * Requires the node to have at least one element. - * - * This method is applicable to prototype nodes only. - * - * @return $this - */ - public function requiresAtLeastOneElement() - { - $this->atLeastOne = true; - - return $this; - } - - /** - * Disallows adding news keys in a subsequent configuration. - * - * If used all keys have to be defined in the same configuration file. - * - * @return $this - */ - public function disallowNewKeysInSubsequentConfigs() - { - $this->allowNewKeys = false; - - return $this; - } - - /** - * Sets a normalization rule for XML configurations. - * - * @param string $singular The key to remap - * @param string|null $plural The plural of the key for irregular plurals - * - * @return $this - */ - public function fixXmlConfig(string $singular, string $plural = null) - { - $this->normalization()->remap($singular, $plural); - - return $this; - } - - /** - * Sets the attribute which value is to be used as key. - * - * This is useful when you have an indexed array that should be an - * associative array. You can select an item from within the array - * to be the key of the particular item. For example, if "id" is the - * "key", then: - * - * [ - * ['id' => 'my_name', 'foo' => 'bar'], - * ]; - * - * becomes - * - * [ - * 'my_name' => ['foo' => 'bar'], - * ]; - * - * If you'd like "'id' => 'my_name'" to still be present in the resulting - * array, then you can set the second argument of this method to false. - * - * This method is applicable to prototype nodes only. - * - * @param string $name The name of the key - * @param bool $removeKeyItem Whether or not the key item should be removed - * - * @return $this - */ - public function useAttributeAsKey(string $name, bool $removeKeyItem = true) - { - $this->key = $name; - $this->removeKeyItem = $removeKeyItem; - - return $this; - } - - /** - * Sets whether the node can be unset. - * - * @return $this - */ - public function canBeUnset(bool $allow = true) - { - $this->merge()->allowUnset($allow); - - return $this; - } - - /** - * Adds an "enabled" boolean to enable the current section. - * - * By default, the section is disabled. If any configuration is specified then - * the node will be automatically enabled: - * - * enableableArrayNode: {enabled: true, ...} # The config is enabled & default values get overridden - * enableableArrayNode: ~ # The config is enabled & use the default values - * enableableArrayNode: true # The config is enabled & use the default values - * enableableArrayNode: {other: value, ...} # The config is enabled & default values get overridden - * enableableArrayNode: {enabled: false, ...} # The config is disabled - * enableableArrayNode: false # The config is disabled - * - * @return $this - */ - public function canBeEnabled() - { - $this - ->addDefaultsIfNotSet() - ->treatFalseLike(['enabled' => false]) - ->treatTrueLike(['enabled' => true]) - ->treatNullLike(['enabled' => true]) - ->beforeNormalization() - ->ifArray() - ->then(function (array $v) { - $v['enabled'] = $v['enabled'] ?? true; - - return $v; - }) - ->end() - ->children() - ->booleanNode('enabled') - ->defaultFalse() - ; - - return $this; - } - - /** - * Adds an "enabled" boolean to enable the current section. - * - * By default, the section is enabled. - * - * @return $this - */ - public function canBeDisabled() - { - $this - ->addDefaultsIfNotSet() - ->treatFalseLike(['enabled' => false]) - ->treatTrueLike(['enabled' => true]) - ->treatNullLike(['enabled' => true]) - ->children() - ->booleanNode('enabled') - ->defaultTrue() - ; - - return $this; - } - - /** - * Disables the deep merging of the node. - * - * @return $this - */ - public function performNoDeepMerging() - { - $this->performDeepMerging = false; - - return $this; - } - - /** - * Allows extra config keys to be specified under an array without - * throwing an exception. - * - * Those config values are ignored and removed from the resulting - * array. This should be used only in special cases where you want - * to send an entire configuration array through a special tree that - * processes only part of the array. - * - * @param bool $remove Whether to remove the extra keys - * - * @return $this - */ - public function ignoreExtraKeys(bool $remove = true) - { - $this->ignoreExtraKeys = true; - $this->removeExtraKeys = $remove; - - return $this; - } - - /** - * Sets whether to enable key normalization. - * - * @return $this - */ - public function normalizeKeys(bool $bool) - { - $this->normalizeKeys = $bool; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function append(NodeDefinition $node) - { - $this->children[$node->name] = $node->setParent($this); - - return $this; - } - - /** - * Returns a node builder to be used to add children and prototype. - * - * @return NodeBuilder - */ - protected function getNodeBuilder() - { - if (null === $this->nodeBuilder) { - $this->nodeBuilder = new NodeBuilder(); - } - - return $this->nodeBuilder->setParent($this); - } - - /** - * {@inheritdoc} - */ - protected function createNode() - { - if (null === $this->prototype) { - $node = new ArrayNode($this->name, $this->parent, $this->pathSeparator); - - $this->validateConcreteNode($node); - - $node->setAddIfNotSet($this->addDefaults); - - foreach ($this->children as $child) { - $child->parent = $node; - $node->addChild($child->getNode()); - } - } else { - $node = new PrototypedArrayNode($this->name, $this->parent, $this->pathSeparator); - - $this->validatePrototypeNode($node); - - if (null !== $this->key) { - $node->setKeyAttribute($this->key, $this->removeKeyItem); - } - - if (true === $this->atLeastOne || false === $this->allowEmptyValue) { - $node->setMinNumberOfElements(1); - } - - if ($this->default) { - if (!\is_array($this->defaultValue)) { - throw new \InvalidArgumentException(sprintf('%s: the default value of an array node has to be an array.', $node->getPath())); - } - - $node->setDefaultValue($this->defaultValue); - } - - if (false !== $this->addDefaultChildren) { - $node->setAddChildrenIfNoneSet($this->addDefaultChildren); - if ($this->prototype instanceof static && null === $this->prototype->prototype) { - $this->prototype->addDefaultsIfNotSet(); - } - } - - $this->prototype->parent = $node; - $node->setPrototype($this->prototype->getNode()); - } - - $node->setAllowNewKeys($this->allowNewKeys); - $node->addEquivalentValue(null, $this->nullEquivalent); - $node->addEquivalentValue(true, $this->trueEquivalent); - $node->addEquivalentValue(false, $this->falseEquivalent); - $node->setPerformDeepMerging($this->performDeepMerging); - $node->setRequired($this->required); - $node->setIgnoreExtraKeys($this->ignoreExtraKeys, $this->removeExtraKeys); - $node->setNormalizeKeys($this->normalizeKeys); - - if ($this->deprecation) { - $node->setDeprecated($this->deprecation['package'], $this->deprecation['version'], $this->deprecation['message']); - } - - if (null !== $this->normalization) { - $node->setNormalizationClosures($this->normalization->before); - $node->setXmlRemappings($this->normalization->remappings); - } - - if (null !== $this->merge) { - $node->setAllowOverwrite($this->merge->allowOverwrite); - $node->setAllowFalse($this->merge->allowFalse); - } - - if (null !== $this->validation) { - $node->setFinalValidationClosures($this->validation->rules); - } - - return $node; - } - - /** - * Validate the configuration of a concrete node. - * - * @throws InvalidDefinitionException - */ - protected function validateConcreteNode(ArrayNode $node) - { - $path = $node->getPath(); - - if (null !== $this->key) { - throw new InvalidDefinitionException(sprintf('->useAttributeAsKey() is not applicable to concrete nodes at path "%s".', $path)); - } - - if (false === $this->allowEmptyValue) { - throw new InvalidDefinitionException(sprintf('->cannotBeEmpty() is not applicable to concrete nodes at path "%s".', $path)); - } - - if (true === $this->atLeastOne) { - throw new InvalidDefinitionException(sprintf('->requiresAtLeastOneElement() is not applicable to concrete nodes at path "%s".', $path)); - } - - if ($this->default) { - throw new InvalidDefinitionException(sprintf('->defaultValue() is not applicable to concrete nodes at path "%s".', $path)); - } - - if (false !== $this->addDefaultChildren) { - throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() is not applicable to concrete nodes at path "%s".', $path)); - } - } - - /** - * Validate the configuration of a prototype node. - * - * @throws InvalidDefinitionException - */ - protected function validatePrototypeNode(PrototypedArrayNode $node) - { - $path = $node->getPath(); - - if ($this->addDefaults) { - throw new InvalidDefinitionException(sprintf('->addDefaultsIfNotSet() is not applicable to prototype nodes at path "%s".', $path)); - } - - if (false !== $this->addDefaultChildren) { - if ($this->default) { - throw new InvalidDefinitionException(sprintf('A default value and default children might not be used together at path "%s".', $path)); - } - - if (null !== $this->key && (null === $this->addDefaultChildren || \is_int($this->addDefaultChildren) && $this->addDefaultChildren > 0)) { - throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() should set default children names as ->useAttributeAsKey() is used at path "%s".', $path)); - } - - if (null === $this->key && (\is_string($this->addDefaultChildren) || \is_array($this->addDefaultChildren))) { - throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() might not set default children names as ->useAttributeAsKey() is not used at path "%s".', $path)); - } - } - } - - /** - * @return NodeDefinition[] - */ - public function getChildNodeDefinitions() - { - return $this->children; - } - - /** - * Finds a node defined by the given $nodePath. - * - * @param string $nodePath The path of the node to find. e.g "doctrine.orm.mappings" - */ - public function find(string $nodePath): NodeDefinition - { - $firstPathSegment = (false === $pathSeparatorPos = strpos($nodePath, $this->pathSeparator)) - ? $nodePath - : substr($nodePath, 0, $pathSeparatorPos); - - if (null === $node = ($this->children[$firstPathSegment] ?? null)) { - throw new \RuntimeException(sprintf('Node with name "%s" does not exist in the current node "%s".', $firstPathSegment, $this->name)); - } - - if (false === $pathSeparatorPos) { - return $node; - } - - return $node->find(substr($nodePath, $pathSeparatorPos + \strlen($this->pathSeparator))); - } -} diff --git a/lib/symfony/config/Definition/Builder/BooleanNodeDefinition.php b/lib/symfony/config/Definition/Builder/BooleanNodeDefinition.php deleted file mode 100644 index ace0b34a2..000000000 --- a/lib/symfony/config/Definition/Builder/BooleanNodeDefinition.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -use Symfony\Component\Config\Definition\BooleanNode; -use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException; - -/** - * This class provides a fluent interface for defining a node. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class BooleanNodeDefinition extends ScalarNodeDefinition -{ - /** - * {@inheritdoc} - */ - public function __construct(?string $name, NodeParentInterface $parent = null) - { - parent::__construct($name, $parent); - - $this->nullEquivalent = true; - } - - /** - * Instantiate a Node. - * - * @return BooleanNode - */ - protected function instantiateNode() - { - return new BooleanNode($this->name, $this->parent, $this->pathSeparator); - } - - /** - * {@inheritdoc} - * - * @throws InvalidDefinitionException - */ - public function cannotBeEmpty() - { - throw new InvalidDefinitionException('->cannotBeEmpty() is not applicable to BooleanNodeDefinition.'); - } -} diff --git a/lib/symfony/config/Definition/Builder/BuilderAwareInterface.php b/lib/symfony/config/Definition/Builder/BuilderAwareInterface.php deleted file mode 100644 index f30b8736c..000000000 --- a/lib/symfony/config/Definition/Builder/BuilderAwareInterface.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -/** - * An interface that can be implemented by nodes which build other nodes. - * - * @author Roland Franssen <franssen.roland@gmail.com> - */ -interface BuilderAwareInterface -{ - /** - * Sets a custom children builder. - */ - public function setBuilder(NodeBuilder $builder); -} diff --git a/lib/symfony/config/Definition/Builder/EnumNodeDefinition.php b/lib/symfony/config/Definition/Builder/EnumNodeDefinition.php deleted file mode 100644 index 52e2fd111..000000000 --- a/lib/symfony/config/Definition/Builder/EnumNodeDefinition.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -use Symfony\Component\Config\Definition\EnumNode; - -/** - * Enum Node Definition. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class EnumNodeDefinition extends ScalarNodeDefinition -{ - private $values; - - /** - * @return $this - */ - public function values(array $values) - { - $values = array_unique($values); - - if (empty($values)) { - throw new \InvalidArgumentException('->values() must be called with at least one value.'); - } - - $this->values = $values; - - return $this; - } - - /** - * Instantiate a Node. - * - * @return EnumNode - * - * @throws \RuntimeException - */ - protected function instantiateNode() - { - if (null === $this->values) { - throw new \RuntimeException('You must call ->values() on enum nodes.'); - } - - return new EnumNode($this->name, $this->parent, $this->values, $this->pathSeparator); - } -} diff --git a/lib/symfony/config/Definition/Builder/ExprBuilder.php b/lib/symfony/config/Definition/Builder/ExprBuilder.php deleted file mode 100644 index 14387b51b..000000000 --- a/lib/symfony/config/Definition/Builder/ExprBuilder.php +++ /dev/null @@ -1,246 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -use Symfony\Component\Config\Definition\Exception\UnsetKeyException; - -/** - * This class builds an if expression. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - * @author Christophe Coevoet <stof@notk.org> - */ -class ExprBuilder -{ - protected $node; - public $ifPart; - public $thenPart; - - public function __construct(NodeDefinition $node) - { - $this->node = $node; - } - - /** - * Marks the expression as being always used. - * - * @return $this - */ - public function always(\Closure $then = null) - { - $this->ifPart = function () { return true; }; - - if (null !== $then) { - $this->thenPart = $then; - } - - return $this; - } - - /** - * Sets a closure to use as tests. - * - * The default one tests if the value is true. - * - * @return $this - */ - public function ifTrue(\Closure $closure = null) - { - if (null === $closure) { - $closure = function ($v) { return true === $v; }; - } - - $this->ifPart = $closure; - - return $this; - } - - /** - * Tests if the value is a string. - * - * @return $this - */ - public function ifString() - { - $this->ifPart = function ($v) { return \is_string($v); }; - - return $this; - } - - /** - * Tests if the value is null. - * - * @return $this - */ - public function ifNull() - { - $this->ifPart = function ($v) { return null === $v; }; - - return $this; - } - - /** - * Tests if the value is empty. - * - * @return $this - */ - public function ifEmpty() - { - $this->ifPart = function ($v) { return empty($v); }; - - return $this; - } - - /** - * Tests if the value is an array. - * - * @return $this - */ - public function ifArray() - { - $this->ifPart = function ($v) { return \is_array($v); }; - - return $this; - } - - /** - * Tests if the value is in an array. - * - * @return $this - */ - public function ifInArray(array $array) - { - $this->ifPart = function ($v) use ($array) { return \in_array($v, $array, true); }; - - return $this; - } - - /** - * Tests if the value is not in an array. - * - * @return $this - */ - public function ifNotInArray(array $array) - { - $this->ifPart = function ($v) use ($array) { return !\in_array($v, $array, true); }; - - return $this; - } - - /** - * Transforms variables of any type into an array. - * - * @return $this - */ - public function castToArray() - { - $this->ifPart = function ($v) { return !\is_array($v); }; - $this->thenPart = function ($v) { return [$v]; }; - - return $this; - } - - /** - * Sets the closure to run if the test pass. - * - * @return $this - */ - public function then(\Closure $closure) - { - $this->thenPart = $closure; - - return $this; - } - - /** - * Sets a closure returning an empty array. - * - * @return $this - */ - public function thenEmptyArray() - { - $this->thenPart = function () { return []; }; - - return $this; - } - - /** - * Sets a closure marking the value as invalid at processing time. - * - * if you want to add the value of the node in your message just use a %s placeholder. - * - * @return $this - * - * @throws \InvalidArgumentException - */ - public function thenInvalid(string $message) - { - $this->thenPart = function ($v) use ($message) { throw new \InvalidArgumentException(sprintf($message, json_encode($v))); }; - - return $this; - } - - /** - * Sets a closure unsetting this key of the array at processing time. - * - * @return $this - * - * @throws UnsetKeyException - */ - public function thenUnset() - { - $this->thenPart = function () { throw new UnsetKeyException('Unsetting key.'); }; - - return $this; - } - - /** - * Returns the related node. - * - * @return NodeDefinition|ArrayNodeDefinition|VariableNodeDefinition - * - * @throws \RuntimeException - */ - public function end() - { - if (null === $this->ifPart) { - throw new \RuntimeException('You must specify an if part.'); - } - if (null === $this->thenPart) { - throw new \RuntimeException('You must specify a then part.'); - } - - return $this->node; - } - - /** - * Builds the expressions. - * - * @param ExprBuilder[] $expressions An array of ExprBuilder instances to build - * - * @return array - */ - public static function buildExpressions(array $expressions) - { - foreach ($expressions as $k => $expr) { - if ($expr instanceof self) { - $if = $expr->ifPart; - $then = $expr->thenPart; - $expressions[$k] = function ($v) use ($if, $then) { - return $if($v) ? $then($v) : $v; - }; - } - } - - return $expressions; - } -} diff --git a/lib/symfony/config/Definition/Builder/FloatNodeDefinition.php b/lib/symfony/config/Definition/Builder/FloatNodeDefinition.php deleted file mode 100644 index f50f190f8..000000000 --- a/lib/symfony/config/Definition/Builder/FloatNodeDefinition.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -use Symfony\Component\Config\Definition\FloatNode; - -/** - * This class provides a fluent interface for defining a float node. - * - * @author Jeanmonod David <david.jeanmonod@gmail.com> - */ -class FloatNodeDefinition extends NumericNodeDefinition -{ - /** - * Instantiates a Node. - * - * @return FloatNode - */ - protected function instantiateNode() - { - return new FloatNode($this->name, $this->parent, $this->min, $this->max, $this->pathSeparator); - } -} diff --git a/lib/symfony/config/Definition/Builder/IntegerNodeDefinition.php b/lib/symfony/config/Definition/Builder/IntegerNodeDefinition.php deleted file mode 100644 index d28e5aecb..000000000 --- a/lib/symfony/config/Definition/Builder/IntegerNodeDefinition.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -use Symfony\Component\Config\Definition\IntegerNode; - -/** - * This class provides a fluent interface for defining an integer node. - * - * @author Jeanmonod David <david.jeanmonod@gmail.com> - */ -class IntegerNodeDefinition extends NumericNodeDefinition -{ - /** - * Instantiates a Node. - * - * @return IntegerNode - */ - protected function instantiateNode() - { - return new IntegerNode($this->name, $this->parent, $this->min, $this->max, $this->pathSeparator); - } -} diff --git a/lib/symfony/config/Definition/Builder/MergeBuilder.php b/lib/symfony/config/Definition/Builder/MergeBuilder.php deleted file mode 100644 index a88d49ba9..000000000 --- a/lib/symfony/config/Definition/Builder/MergeBuilder.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -/** - * This class builds merge conditions. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class MergeBuilder -{ - protected $node; - public $allowFalse = false; - public $allowOverwrite = true; - - public function __construct(NodeDefinition $node) - { - $this->node = $node; - } - - /** - * Sets whether the node can be unset. - * - * @return $this - */ - public function allowUnset(bool $allow = true) - { - $this->allowFalse = $allow; - - return $this; - } - - /** - * Sets whether the node can be overwritten. - * - * @return $this - */ - public function denyOverwrite(bool $deny = true) - { - $this->allowOverwrite = !$deny; - - return $this; - } - - /** - * Returns the related node. - * - * @return NodeDefinition|ArrayNodeDefinition|VariableNodeDefinition - */ - public function end() - { - return $this->node; - } -} diff --git a/lib/symfony/config/Definition/Builder/NodeBuilder.php b/lib/symfony/config/Definition/Builder/NodeBuilder.php deleted file mode 100644 index 245e97277..000000000 --- a/lib/symfony/config/Definition/Builder/NodeBuilder.php +++ /dev/null @@ -1,219 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -/** - * This class provides a fluent interface for building a node. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class NodeBuilder implements NodeParentInterface -{ - protected $parent; - protected $nodeMapping; - - public function __construct() - { - $this->nodeMapping = [ - 'variable' => VariableNodeDefinition::class, - 'scalar' => ScalarNodeDefinition::class, - 'boolean' => BooleanNodeDefinition::class, - 'integer' => IntegerNodeDefinition::class, - 'float' => FloatNodeDefinition::class, - 'array' => ArrayNodeDefinition::class, - 'enum' => EnumNodeDefinition::class, - ]; - } - - /** - * Set the parent node. - * - * @return $this - */ - public function setParent(ParentNodeDefinitionInterface $parent = null) - { - $this->parent = $parent; - - return $this; - } - - /** - * Creates a child array node. - * - * @return ArrayNodeDefinition - */ - public function arrayNode(string $name) - { - return $this->node($name, 'array'); - } - - /** - * Creates a child scalar node. - * - * @return ScalarNodeDefinition - */ - public function scalarNode(string $name) - { - return $this->node($name, 'scalar'); - } - - /** - * Creates a child Boolean node. - * - * @return BooleanNodeDefinition - */ - public function booleanNode(string $name) - { - return $this->node($name, 'boolean'); - } - - /** - * Creates a child integer node. - * - * @return IntegerNodeDefinition - */ - public function integerNode(string $name) - { - return $this->node($name, 'integer'); - } - - /** - * Creates a child float node. - * - * @return FloatNodeDefinition - */ - public function floatNode(string $name) - { - return $this->node($name, 'float'); - } - - /** - * Creates a child EnumNode. - * - * @return EnumNodeDefinition - */ - public function enumNode(string $name) - { - return $this->node($name, 'enum'); - } - - /** - * Creates a child variable node. - * - * @return VariableNodeDefinition - */ - public function variableNode(string $name) - { - return $this->node($name, 'variable'); - } - - /** - * Returns the parent node. - * - * @return NodeDefinition&ParentNodeDefinitionInterface - */ - public function end() - { - return $this->parent; - } - - /** - * Creates a child node. - * - * @return NodeDefinition - * - * @throws \RuntimeException When the node type is not registered - * @throws \RuntimeException When the node class is not found - */ - public function node(?string $name, string $type) - { - $class = $this->getNodeClass($type); - - $node = new $class($name); - - $this->append($node); - - return $node; - } - - /** - * Appends a node definition. - * - * Usage: - * - * $node = new ArrayNodeDefinition('name') - * ->children() - * ->scalarNode('foo')->end() - * ->scalarNode('baz')->end() - * ->append($this->getBarNodeDefinition()) - * ->end() - * ; - * - * @return $this - */ - public function append(NodeDefinition $node) - { - if ($node instanceof BuilderAwareInterface) { - $builder = clone $this; - $builder->setParent(null); - $node->setBuilder($builder); - } - - if (null !== $this->parent) { - $this->parent->append($node); - // Make this builder the node parent to allow for a fluid interface - $node->setParent($this); - } - - return $this; - } - - /** - * Adds or overrides a node Type. - * - * @param string $type The name of the type - * @param string $class The fully qualified name the node definition class - * - * @return $this - */ - public function setNodeClass(string $type, string $class) - { - $this->nodeMapping[strtolower($type)] = $class; - - return $this; - } - - /** - * Returns the class name of the node definition. - * - * @return string - * - * @throws \RuntimeException When the node type is not registered - * @throws \RuntimeException When the node class is not found - */ - protected function getNodeClass(string $type) - { - $type = strtolower($type); - - if (!isset($this->nodeMapping[$type])) { - throw new \RuntimeException(sprintf('The node type "%s" is not registered.', $type)); - } - - $class = $this->nodeMapping[$type]; - - if (!class_exists($class)) { - throw new \RuntimeException(sprintf('The node class "%s" does not exist.', $class)); - } - - return $class; - } -} diff --git a/lib/symfony/config/Definition/Builder/NodeDefinition.php b/lib/symfony/config/Definition/Builder/NodeDefinition.php deleted file mode 100644 index cf153f01c..000000000 --- a/lib/symfony/config/Definition/Builder/NodeDefinition.php +++ /dev/null @@ -1,383 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -use Symfony\Component\Config\Definition\BaseNode; -use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException; -use Symfony\Component\Config\Definition\NodeInterface; - -/** - * This class provides a fluent interface for defining a node. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -abstract class NodeDefinition implements NodeParentInterface -{ - protected $name; - protected $normalization; - protected $validation; - protected $defaultValue; - protected $default = false; - protected $required = false; - protected $deprecation = []; - protected $merge; - protected $allowEmptyValue = true; - protected $nullEquivalent; - protected $trueEquivalent = true; - protected $falseEquivalent = false; - protected $pathSeparator = BaseNode::DEFAULT_PATH_SEPARATOR; - protected $parent; - protected $attributes = []; - - public function __construct(?string $name, NodeParentInterface $parent = null) - { - $this->parent = $parent; - $this->name = $name; - } - - /** - * Sets the parent node. - * - * @return $this - */ - public function setParent(NodeParentInterface $parent) - { - $this->parent = $parent; - - return $this; - } - - /** - * Sets info message. - * - * @return $this - */ - public function info(string $info) - { - return $this->attribute('info', $info); - } - - /** - * Sets example configuration. - * - * @param string|array $example - * - * @return $this - */ - public function example($example) - { - return $this->attribute('example', $example); - } - - /** - * Sets an attribute on the node. - * - * @param mixed $value - * - * @return $this - */ - public function attribute(string $key, $value) - { - $this->attributes[$key] = $value; - - return $this; - } - - /** - * Returns the parent node. - * - * @return NodeParentInterface|NodeBuilder|NodeDefinition|ArrayNodeDefinition|VariableNodeDefinition|null - */ - public function end() - { - return $this->parent; - } - - /** - * Creates the node. - * - * @return NodeInterface - */ - public function getNode(bool $forceRootNode = false) - { - if ($forceRootNode) { - $this->parent = null; - } - - if (null !== $this->normalization) { - $this->normalization->before = ExprBuilder::buildExpressions($this->normalization->before); - } - - if (null !== $this->validation) { - $this->validation->rules = ExprBuilder::buildExpressions($this->validation->rules); - } - - $node = $this->createNode(); - if ($node instanceof BaseNode) { - $node->setAttributes($this->attributes); - } - - return $node; - } - - /** - * Sets the default value. - * - * @param mixed $value The default value - * - * @return $this - */ - public function defaultValue($value) - { - $this->default = true; - $this->defaultValue = $value; - - return $this; - } - - /** - * Sets the node as required. - * - * @return $this - */ - public function isRequired() - { - $this->required = true; - - return $this; - } - - /** - * Sets the node as deprecated. - * - * @param string $package The name of the composer package that is triggering the deprecation - * @param string $version The version of the package that introduced the deprecation - * @param string $message the deprecation message to use - * - * You can use %node% and %path% placeholders in your message to display, - * respectively, the node name and its complete path - * - * @return $this - */ - public function setDeprecated(/* string $package, string $version, string $message = 'The child node "%node%" at path "%path%" is deprecated.' */) - { - $args = \func_get_args(); - - if (\func_num_args() < 2) { - trigger_deprecation('symfony/config', '5.1', 'The signature of method "%s()" requires 3 arguments: "string $package, string $version, string $message", not defining them is deprecated.', __METHOD__); - - $message = $args[0] ?? 'The child node "%node%" at path "%path%" is deprecated.'; - $package = $version = ''; - } else { - $package = (string) $args[0]; - $version = (string) $args[1]; - $message = (string) ($args[2] ?? 'The child node "%node%" at path "%path%" is deprecated.'); - } - - $this->deprecation = [ - 'package' => $package, - 'version' => $version, - 'message' => $message, - ]; - - return $this; - } - - /** - * Sets the equivalent value used when the node contains null. - * - * @param mixed $value - * - * @return $this - */ - public function treatNullLike($value) - { - $this->nullEquivalent = $value; - - return $this; - } - - /** - * Sets the equivalent value used when the node contains true. - * - * @param mixed $value - * - * @return $this - */ - public function treatTrueLike($value) - { - $this->trueEquivalent = $value; - - return $this; - } - - /** - * Sets the equivalent value used when the node contains false. - * - * @param mixed $value - * - * @return $this - */ - public function treatFalseLike($value) - { - $this->falseEquivalent = $value; - - return $this; - } - - /** - * Sets null as the default value. - * - * @return $this - */ - public function defaultNull() - { - return $this->defaultValue(null); - } - - /** - * Sets true as the default value. - * - * @return $this - */ - public function defaultTrue() - { - return $this->defaultValue(true); - } - - /** - * Sets false as the default value. - * - * @return $this - */ - public function defaultFalse() - { - return $this->defaultValue(false); - } - - /** - * Sets an expression to run before the normalization. - * - * @return ExprBuilder - */ - public function beforeNormalization() - { - return $this->normalization()->before(); - } - - /** - * Denies the node value being empty. - * - * @return $this - */ - public function cannotBeEmpty() - { - $this->allowEmptyValue = false; - - return $this; - } - - /** - * Sets an expression to run for the validation. - * - * The expression receives the value of the node and must return it. It can - * modify it. - * An exception should be thrown when the node is not valid. - * - * @return ExprBuilder - */ - public function validate() - { - return $this->validation()->rule(); - } - - /** - * Sets whether the node can be overwritten. - * - * @return $this - */ - public function cannotBeOverwritten(bool $deny = true) - { - $this->merge()->denyOverwrite($deny); - - return $this; - } - - /** - * Gets the builder for validation rules. - * - * @return ValidationBuilder - */ - protected function validation() - { - if (null === $this->validation) { - $this->validation = new ValidationBuilder($this); - } - - return $this->validation; - } - - /** - * Gets the builder for merging rules. - * - * @return MergeBuilder - */ - protected function merge() - { - if (null === $this->merge) { - $this->merge = new MergeBuilder($this); - } - - return $this->merge; - } - - /** - * Gets the builder for normalization rules. - * - * @return NormalizationBuilder - */ - protected function normalization() - { - if (null === $this->normalization) { - $this->normalization = new NormalizationBuilder($this); - } - - return $this->normalization; - } - - /** - * Instantiate and configure the node according to this definition. - * - * @return NodeInterface - * - * @throws InvalidDefinitionException When the definition is invalid - */ - abstract protected function createNode(); - - /** - * Set PathSeparator to use. - * - * @return $this - */ - public function setPathSeparator(string $separator) - { - if ($this instanceof ParentNodeDefinitionInterface) { - foreach ($this->getChildNodeDefinitions() as $child) { - $child->setPathSeparator($separator); - } - } - - $this->pathSeparator = $separator; - - return $this; - } -} diff --git a/lib/symfony/config/Definition/Builder/NodeParentInterface.php b/lib/symfony/config/Definition/Builder/NodeParentInterface.php deleted file mode 100644 index 305e99316..000000000 --- a/lib/symfony/config/Definition/Builder/NodeParentInterface.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -/** - * An interface that must be implemented by all node parents. - * - * @author Victor Berchet <victor@suumit.com> - */ -interface NodeParentInterface -{ -} diff --git a/lib/symfony/config/Definition/Builder/NormalizationBuilder.php b/lib/symfony/config/Definition/Builder/NormalizationBuilder.php deleted file mode 100644 index 06cbbd434..000000000 --- a/lib/symfony/config/Definition/Builder/NormalizationBuilder.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -/** - * This class builds normalization conditions. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class NormalizationBuilder -{ - protected $node; - public $before = []; - public $remappings = []; - - public function __construct(NodeDefinition $node) - { - $this->node = $node; - } - - /** - * Registers a key to remap to its plural form. - * - * @param string $key The key to remap - * @param string|null $plural The plural of the key in case of irregular plural - * - * @return $this - */ - public function remap(string $key, string $plural = null) - { - $this->remappings[] = [$key, null === $plural ? $key.'s' : $plural]; - - return $this; - } - - /** - * Registers a closure to run before the normalization or an expression builder to build it if null is provided. - * - * @return ExprBuilder|$this - */ - public function before(\Closure $closure = null) - { - if (null !== $closure) { - $this->before[] = $closure; - - return $this; - } - - return $this->before[] = new ExprBuilder($this->node); - } -} diff --git a/lib/symfony/config/Definition/Builder/NumericNodeDefinition.php b/lib/symfony/config/Definition/Builder/NumericNodeDefinition.php deleted file mode 100644 index c4bff1756..000000000 --- a/lib/symfony/config/Definition/Builder/NumericNodeDefinition.php +++ /dev/null @@ -1,73 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException; - -/** - * Abstract class that contains common code of integer and float node definitions. - * - * @author David Jeanmonod <david.jeanmonod@gmail.com> - */ -abstract class NumericNodeDefinition extends ScalarNodeDefinition -{ - protected $min; - protected $max; - - /** - * Ensures that the value is smaller than the given reference. - * - * @param int|float $max - * - * @return $this - * - * @throws \InvalidArgumentException when the constraint is inconsistent - */ - public function max($max) - { - if (isset($this->min) && $this->min > $max) { - throw new \InvalidArgumentException(sprintf('You cannot define a max(%s) as you already have a min(%s).', $max, $this->min)); - } - $this->max = $max; - - return $this; - } - - /** - * Ensures that the value is bigger than the given reference. - * - * @param int|float $min - * - * @return $this - * - * @throws \InvalidArgumentException when the constraint is inconsistent - */ - public function min($min) - { - if (isset($this->max) && $this->max < $min) { - throw new \InvalidArgumentException(sprintf('You cannot define a min(%s) as you already have a max(%s).', $min, $this->max)); - } - $this->min = $min; - - return $this; - } - - /** - * {@inheritdoc} - * - * @throws InvalidDefinitionException - */ - public function cannotBeEmpty() - { - throw new InvalidDefinitionException('->cannotBeEmpty() is not applicable to NumericNodeDefinition.'); - } -} diff --git a/lib/symfony/config/Definition/Builder/ParentNodeDefinitionInterface.php b/lib/symfony/config/Definition/Builder/ParentNodeDefinitionInterface.php deleted file mode 100644 index 449b91afd..000000000 --- a/lib/symfony/config/Definition/Builder/ParentNodeDefinitionInterface.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -/** - * An interface that must be implemented by nodes which can have children. - * - * @author Victor Berchet <victor@suumit.com> - */ -interface ParentNodeDefinitionInterface extends BuilderAwareInterface -{ - /** - * Returns a builder to add children nodes. - * - * @return NodeBuilder - */ - public function children(); - - /** - * Appends a node definition. - * - * Usage: - * - * $node = $parentNode - * ->children() - * ->scalarNode('foo')->end() - * ->scalarNode('baz')->end() - * ->append($this->getBarNodeDefinition()) - * ->end() - * ; - * - * @return $this - */ - public function append(NodeDefinition $node); - - /** - * Gets the child node definitions. - * - * @return NodeDefinition[] - */ - public function getChildNodeDefinitions(); -} diff --git a/lib/symfony/config/Definition/Builder/ScalarNodeDefinition.php b/lib/symfony/config/Definition/Builder/ScalarNodeDefinition.php deleted file mode 100644 index 076f74b34..000000000 --- a/lib/symfony/config/Definition/Builder/ScalarNodeDefinition.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -use Symfony\Component\Config\Definition\ScalarNode; - -/** - * This class provides a fluent interface for defining a node. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class ScalarNodeDefinition extends VariableNodeDefinition -{ - /** - * Instantiate a Node. - * - * @return ScalarNode - */ - protected function instantiateNode() - { - return new ScalarNode($this->name, $this->parent, $this->pathSeparator); - } -} diff --git a/lib/symfony/config/Definition/Builder/TreeBuilder.php b/lib/symfony/config/Definition/Builder/TreeBuilder.php deleted file mode 100644 index f3c3c2109..000000000 --- a/lib/symfony/config/Definition/Builder/TreeBuilder.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -use Symfony\Component\Config\Definition\NodeInterface; - -/** - * This is the entry class for building a config tree. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class TreeBuilder implements NodeParentInterface -{ - protected $tree; - protected $root; - - public function __construct(string $name, string $type = 'array', NodeBuilder $builder = null) - { - $builder = $builder ?? new NodeBuilder(); - $this->root = $builder->node($name, $type)->setParent($this); - } - - /** - * @return NodeDefinition|ArrayNodeDefinition The root node (as an ArrayNodeDefinition when the type is 'array') - */ - public function getRootNode(): NodeDefinition - { - return $this->root; - } - - /** - * Builds the tree. - * - * @return NodeInterface - * - * @throws \RuntimeException - */ - public function buildTree() - { - if (null !== $this->tree) { - return $this->tree; - } - - return $this->tree = $this->root->getNode(true); - } - - public function setPathSeparator(string $separator) - { - // unset last built as changing path separator changes all nodes - $this->tree = null; - - $this->root->setPathSeparator($separator); - } -} diff --git a/lib/symfony/config/Definition/Builder/ValidationBuilder.php b/lib/symfony/config/Definition/Builder/ValidationBuilder.php deleted file mode 100644 index 4efc726c0..000000000 --- a/lib/symfony/config/Definition/Builder/ValidationBuilder.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -/** - * This class builds validation conditions. - * - * @author Christophe Coevoet <stof@notk.org> - */ -class ValidationBuilder -{ - protected $node; - public $rules = []; - - public function __construct(NodeDefinition $node) - { - $this->node = $node; - } - - /** - * Registers a closure to run as normalization or an expression builder to build it if null is provided. - * - * @return ExprBuilder|$this - */ - public function rule(\Closure $closure = null) - { - if (null !== $closure) { - $this->rules[] = $closure; - - return $this; - } - - return $this->rules[] = new ExprBuilder($this->node); - } -} diff --git a/lib/symfony/config/Definition/Builder/VariableNodeDefinition.php b/lib/symfony/config/Definition/Builder/VariableNodeDefinition.php deleted file mode 100644 index eea16cc32..000000000 --- a/lib/symfony/config/Definition/Builder/VariableNodeDefinition.php +++ /dev/null @@ -1,68 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -use Symfony\Component\Config\Definition\VariableNode; - -/** - * This class provides a fluent interface for defining a node. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class VariableNodeDefinition extends NodeDefinition -{ - /** - * Instantiate a Node. - * - * @return VariableNode - */ - protected function instantiateNode() - { - return new VariableNode($this->name, $this->parent, $this->pathSeparator); - } - - /** - * {@inheritdoc} - */ - protected function createNode() - { - $node = $this->instantiateNode(); - - if (null !== $this->normalization) { - $node->setNormalizationClosures($this->normalization->before); - } - - if (null !== $this->merge) { - $node->setAllowOverwrite($this->merge->allowOverwrite); - } - - if (true === $this->default) { - $node->setDefaultValue($this->defaultValue); - } - - $node->setAllowEmptyValue($this->allowEmptyValue); - $node->addEquivalentValue(null, $this->nullEquivalent); - $node->addEquivalentValue(true, $this->trueEquivalent); - $node->addEquivalentValue(false, $this->falseEquivalent); - $node->setRequired($this->required); - - if ($this->deprecation) { - $node->setDeprecated($this->deprecation['package'], $this->deprecation['version'], $this->deprecation['message']); - } - - if (null !== $this->validation) { - $node->setFinalValidationClosures($this->validation->rules); - } - - return $node; - } -} diff --git a/lib/symfony/config/Definition/ConfigurationInterface.php b/lib/symfony/config/Definition/ConfigurationInterface.php deleted file mode 100644 index 7b5d443fe..000000000 --- a/lib/symfony/config/Definition/ConfigurationInterface.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -use Symfony\Component\Config\Definition\Builder\TreeBuilder; - -/** - * Configuration interface. - * - * @author Victor Berchet <victor@suumit.com> - */ -interface ConfigurationInterface -{ - /** - * Generates the configuration tree builder. - * - * @return TreeBuilder - */ - public function getConfigTreeBuilder(); -} diff --git a/lib/symfony/config/Definition/Dumper/XmlReferenceDumper.php b/lib/symfony/config/Definition/Dumper/XmlReferenceDumper.php deleted file mode 100644 index a8b18a023..000000000 --- a/lib/symfony/config/Definition/Dumper/XmlReferenceDumper.php +++ /dev/null @@ -1,306 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Dumper; - -use Symfony\Component\Config\Definition\ArrayNode; -use Symfony\Component\Config\Definition\BaseNode; -use Symfony\Component\Config\Definition\ConfigurationInterface; -use Symfony\Component\Config\Definition\EnumNode; -use Symfony\Component\Config\Definition\NodeInterface; -use Symfony\Component\Config\Definition\PrototypedArrayNode; - -/** - * Dumps an XML reference configuration for the given configuration/node instance. - * - * @author Wouter J <waldio.webdesign@gmail.com> - */ -class XmlReferenceDumper -{ - private $reference; - - public function dump(ConfigurationInterface $configuration, string $namespace = null) - { - return $this->dumpNode($configuration->getConfigTreeBuilder()->buildTree(), $namespace); - } - - public function dumpNode(NodeInterface $node, string $namespace = null) - { - $this->reference = ''; - $this->writeNode($node, 0, true, $namespace); - $ref = $this->reference; - $this->reference = null; - - return $ref; - } - - private function writeNode(NodeInterface $node, int $depth = 0, bool $root = false, string $namespace = null) - { - $rootName = ($root ? 'config' : $node->getName()); - $rootNamespace = ($namespace ?: ($root ? 'http://example.org/schema/dic/'.$node->getName() : null)); - - // xml remapping - if ($node->getParent()) { - $remapping = array_filter($node->getParent()->getXmlRemappings(), function (array $mapping) use ($rootName) { - return $rootName === $mapping[1]; - }); - - if (\count($remapping)) { - [$singular] = current($remapping); - $rootName = $singular; - } - } - $rootName = str_replace('_', '-', $rootName); - - $rootAttributes = []; - $rootAttributeComments = []; - $rootChildren = []; - $rootComments = []; - - if ($node instanceof ArrayNode) { - $children = $node->getChildren(); - - // comments about the root node - if ($rootInfo = $node->getInfo()) { - $rootComments[] = $rootInfo; - } - - if ($rootNamespace) { - $rootComments[] = 'Namespace: '.$rootNamespace; - } - - // render prototyped nodes - if ($node instanceof PrototypedArrayNode) { - $prototype = $node->getPrototype(); - - $info = 'prototype'; - if (null !== $prototype->getInfo()) { - $info .= ': '.$prototype->getInfo(); - } - array_unshift($rootComments, $info); - - if ($key = $node->getKeyAttribute()) { - $rootAttributes[$key] = str_replace('-', ' ', $rootName).' '.$key; - } - - if ($prototype instanceof PrototypedArrayNode) { - $prototype->setName($key ?? ''); - $children = [$key => $prototype]; - } elseif ($prototype instanceof ArrayNode) { - $children = $prototype->getChildren(); - } else { - if ($prototype->hasDefaultValue()) { - $prototypeValue = $prototype->getDefaultValue(); - } else { - switch (\get_class($prototype)) { - case 'Symfony\Component\Config\Definition\ScalarNode': - $prototypeValue = 'scalar value'; - break; - - case 'Symfony\Component\Config\Definition\FloatNode': - case 'Symfony\Component\Config\Definition\IntegerNode': - $prototypeValue = 'numeric value'; - break; - - case 'Symfony\Component\Config\Definition\BooleanNode': - $prototypeValue = 'true|false'; - break; - - case 'Symfony\Component\Config\Definition\EnumNode': - $prototypeValue = implode('|', array_map('json_encode', $prototype->getValues())); - break; - - default: - $prototypeValue = 'value'; - } - } - } - } - - // get attributes and elements - foreach ($children as $child) { - if ($child instanceof ArrayNode) { - // get elements - $rootChildren[] = $child; - - continue; - } - - // get attributes - - // metadata - $name = str_replace('_', '-', $child->getName()); - $value = '%%%%not_defined%%%%'; // use a string which isn't used in the normal world - - // comments - $comments = []; - if ($child instanceof BaseNode && $info = $child->getInfo()) { - $comments[] = $info; - } - - if ($child instanceof BaseNode && $example = $child->getExample()) { - $comments[] = 'Example: '.$example; - } - - if ($child->isRequired()) { - $comments[] = 'Required'; - } - - if ($child instanceof BaseNode && $child->isDeprecated()) { - $deprecation = $child->getDeprecation($child->getName(), $node->getPath()); - $comments[] = sprintf('Deprecated (%s)', ($deprecation['package'] || $deprecation['version'] ? "Since {$deprecation['package']} {$deprecation['version']}: " : '').$deprecation['message']); - } - - if ($child instanceof EnumNode) { - $comments[] = 'One of '.implode('; ', array_map('json_encode', $child->getValues())); - } - - if (\count($comments)) { - $rootAttributeComments[$name] = implode(";\n", $comments); - } - - // default values - if ($child->hasDefaultValue()) { - $value = $child->getDefaultValue(); - } - - // append attribute - $rootAttributes[$name] = $value; - } - } - - // render comments - - // root node comment - if (\count($rootComments)) { - foreach ($rootComments as $comment) { - $this->writeLine('<!-- '.$comment.' -->', $depth); - } - } - - // attribute comments - if (\count($rootAttributeComments)) { - foreach ($rootAttributeComments as $attrName => $comment) { - $commentDepth = $depth + 4 + \strlen($attrName) + 2; - $commentLines = explode("\n", $comment); - $multiline = (\count($commentLines) > 1); - $comment = implode(\PHP_EOL.str_repeat(' ', $commentDepth), $commentLines); - - if ($multiline) { - $this->writeLine('<!--', $depth); - $this->writeLine($attrName.': '.$comment, $depth + 4); - $this->writeLine('-->', $depth); - } else { - $this->writeLine('<!-- '.$attrName.': '.$comment.' -->', $depth); - } - } - } - - // render start tag + attributes - $rootIsVariablePrototype = isset($prototypeValue); - $rootIsEmptyTag = (0 === \count($rootChildren) && !$rootIsVariablePrototype); - $rootOpenTag = '<'.$rootName; - if (1 >= ($attributesCount = \count($rootAttributes))) { - if (1 === $attributesCount) { - $rootOpenTag .= sprintf(' %s="%s"', current(array_keys($rootAttributes)), $this->writeValue(current($rootAttributes))); - } - - $rootOpenTag .= $rootIsEmptyTag ? ' />' : '>'; - - if ($rootIsVariablePrototype) { - $rootOpenTag .= $prototypeValue.'</'.$rootName.'>'; - } - - $this->writeLine($rootOpenTag, $depth); - } else { - $this->writeLine($rootOpenTag, $depth); - - $i = 1; - - foreach ($rootAttributes as $attrName => $attrValue) { - $attr = sprintf('%s="%s"', $attrName, $this->writeValue($attrValue)); - - $this->writeLine($attr, $depth + 4); - - if ($attributesCount === $i++) { - $this->writeLine($rootIsEmptyTag ? '/>' : '>', $depth); - - if ($rootIsVariablePrototype) { - $rootOpenTag .= $prototypeValue.'</'.$rootName.'>'; - } - } - } - } - - // render children tags - foreach ($rootChildren as $child) { - $this->writeLine(''); - $this->writeNode($child, $depth + 4); - } - - // render end tag - if (!$rootIsEmptyTag && !$rootIsVariablePrototype) { - $this->writeLine(''); - - $rootEndTag = '</'.$rootName.'>'; - $this->writeLine($rootEndTag, $depth); - } - } - - /** - * Outputs a single config reference line. - */ - private function writeLine(string $text, int $indent = 0) - { - $indent = \strlen($text) + $indent; - $format = '%'.$indent.'s'; - - $this->reference .= sprintf($format, $text).\PHP_EOL; - } - - /** - * Renders the string conversion of the value. - * - * @param mixed $value - */ - private function writeValue($value): string - { - if ('%%%%not_defined%%%%' === $value) { - return ''; - } - - if (\is_string($value) || is_numeric($value)) { - return $value; - } - - if (false === $value) { - return 'false'; - } - - if (true === $value) { - return 'true'; - } - - if (null === $value) { - return 'null'; - } - - if (empty($value)) { - return ''; - } - - if (\is_array($value)) { - return implode(',', $value); - } - - return ''; - } -} diff --git a/lib/symfony/config/Definition/Dumper/YamlReferenceDumper.php b/lib/symfony/config/Definition/Dumper/YamlReferenceDumper.php deleted file mode 100644 index 6fcfb71bd..000000000 --- a/lib/symfony/config/Definition/Dumper/YamlReferenceDumper.php +++ /dev/null @@ -1,251 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Dumper; - -use Symfony\Component\Config\Definition\ArrayNode; -use Symfony\Component\Config\Definition\BaseNode; -use Symfony\Component\Config\Definition\ConfigurationInterface; -use Symfony\Component\Config\Definition\EnumNode; -use Symfony\Component\Config\Definition\NodeInterface; -use Symfony\Component\Config\Definition\PrototypedArrayNode; -use Symfony\Component\Config\Definition\ScalarNode; -use Symfony\Component\Config\Definition\VariableNode; -use Symfony\Component\Yaml\Inline; - -/** - * Dumps a Yaml reference configuration for the given configuration/node instance. - * - * @author Kevin Bond <kevinbond@gmail.com> - */ -class YamlReferenceDumper -{ - private $reference; - - public function dump(ConfigurationInterface $configuration) - { - return $this->dumpNode($configuration->getConfigTreeBuilder()->buildTree()); - } - - public function dumpAtPath(ConfigurationInterface $configuration, string $path) - { - $rootNode = $node = $configuration->getConfigTreeBuilder()->buildTree(); - - foreach (explode('.', $path) as $step) { - if (!$node instanceof ArrayNode) { - throw new \UnexpectedValueException(sprintf('Unable to find node at path "%s.%s".', $rootNode->getName(), $path)); - } - - /** @var NodeInterface[] $children */ - $children = $node instanceof PrototypedArrayNode ? $this->getPrototypeChildren($node) : $node->getChildren(); - - foreach ($children as $child) { - if ($child->getName() === $step) { - $node = $child; - - continue 2; - } - } - - throw new \UnexpectedValueException(sprintf('Unable to find node at path "%s.%s".', $rootNode->getName(), $path)); - } - - return $this->dumpNode($node); - } - - public function dumpNode(NodeInterface $node) - { - $this->reference = ''; - $this->writeNode($node); - $ref = $this->reference; - $this->reference = null; - - return $ref; - } - - private function writeNode(NodeInterface $node, NodeInterface $parentNode = null, int $depth = 0, bool $prototypedArray = false) - { - $comments = []; - $default = ''; - $defaultArray = null; - $children = null; - $example = null; - if ($node instanceof BaseNode) { - $example = $node->getExample(); - } - - // defaults - if ($node instanceof ArrayNode) { - $children = $node->getChildren(); - - if ($node instanceof PrototypedArrayNode) { - $children = $this->getPrototypeChildren($node); - } - - if (!$children) { - if ($node->hasDefaultValue() && \count($defaultArray = $node->getDefaultValue())) { - $default = ''; - } elseif (!\is_array($example)) { - $default = '[]'; - } - } - } elseif ($node instanceof EnumNode) { - $comments[] = 'One of '.implode('; ', array_map('json_encode', $node->getValues())); - $default = $node->hasDefaultValue() ? Inline::dump($node->getDefaultValue()) : '~'; - } elseif (VariableNode::class === \get_class($node) && \is_array($example)) { - // If there is an array example, we are sure we dont need to print a default value - $default = ''; - } else { - $default = '~'; - - if ($node->hasDefaultValue()) { - $default = $node->getDefaultValue(); - - if (\is_array($default)) { - if (\count($defaultArray = $node->getDefaultValue())) { - $default = ''; - } elseif (!\is_array($example)) { - $default = '[]'; - } - } else { - $default = Inline::dump($default); - } - } - } - - // required? - if ($node->isRequired()) { - $comments[] = 'Required'; - } - - // deprecated? - if ($node instanceof BaseNode && $node->isDeprecated()) { - $deprecation = $node->getDeprecation($node->getName(), $parentNode ? $parentNode->getPath() : $node->getPath()); - $comments[] = sprintf('Deprecated (%s)', ($deprecation['package'] || $deprecation['version'] ? "Since {$deprecation['package']} {$deprecation['version']}: " : '').$deprecation['message']); - } - - // example - if ($example && !\is_array($example)) { - $comments[] = 'Example: '.Inline::dump($example); - } - - $default = '' != (string) $default ? ' '.$default : ''; - $comments = \count($comments) ? '# '.implode(', ', $comments) : ''; - - $key = $prototypedArray ? '-' : $node->getName().':'; - $text = rtrim(sprintf('%-21s%s %s', $key, $default, $comments), ' '); - - if ($node instanceof BaseNode && $info = $node->getInfo()) { - $this->writeLine(''); - // indenting multi-line info - $info = str_replace("\n", sprintf("\n%".($depth * 4).'s# ', ' '), $info); - $this->writeLine('# '.$info, $depth * 4); - } - - $this->writeLine($text, $depth * 4); - - // output defaults - if ($defaultArray) { - $this->writeLine(''); - - $message = \count($defaultArray) > 1 ? 'Defaults' : 'Default'; - - $this->writeLine('# '.$message.':', $depth * 4 + 4); - - $this->writeArray($defaultArray, $depth + 1); - } - - if (\is_array($example)) { - $this->writeLine(''); - - $message = \count($example) > 1 ? 'Examples' : 'Example'; - - $this->writeLine('# '.$message.':', $depth * 4 + 4); - - $this->writeArray(array_map([Inline::class, 'dump'], $example), $depth + 1); - } - - if ($children) { - foreach ($children as $childNode) { - $this->writeNode($childNode, $node, $depth + 1, $node instanceof PrototypedArrayNode && !$node->getKeyAttribute()); - } - } - } - - /** - * Outputs a single config reference line. - */ - private function writeLine(string $text, int $indent = 0) - { - $indent = \strlen($text) + $indent; - $format = '%'.$indent.'s'; - - $this->reference .= sprintf($format, $text)."\n"; - } - - private function writeArray(array $array, int $depth) - { - $isIndexed = array_values($array) === $array; - - foreach ($array as $key => $value) { - if (\is_array($value)) { - $val = ''; - } else { - $val = $value; - } - - if ($isIndexed) { - $this->writeLine('- '.$val, $depth * 4); - } else { - $this->writeLine(sprintf('%-20s %s', $key.':', $val), $depth * 4); - } - - if (\is_array($value)) { - $this->writeArray($value, $depth + 1); - } - } - } - - private function getPrototypeChildren(PrototypedArrayNode $node): array - { - $prototype = $node->getPrototype(); - $key = $node->getKeyAttribute(); - - // Do not expand prototype if it isn't an array node nor uses attribute as key - if (!$key && !$prototype instanceof ArrayNode) { - return $node->getChildren(); - } - - if ($prototype instanceof ArrayNode) { - $keyNode = new ArrayNode($key, $node); - $children = $prototype->getChildren(); - - if ($prototype instanceof PrototypedArrayNode && $prototype->getKeyAttribute()) { - $children = $this->getPrototypeChildren($prototype); - } - - // add children - foreach ($children as $childNode) { - $keyNode->addChild($childNode); - } - } else { - $keyNode = new ScalarNode($key, $node); - } - - $info = 'Prototype'; - if (null !== $prototype->getInfo()) { - $info .= ': '.$prototype->getInfo(); - } - $keyNode->setInfo($info); - - return [$key => $keyNode]; - } -} diff --git a/lib/symfony/config/Definition/EnumNode.php b/lib/symfony/config/Definition/EnumNode.php deleted file mode 100644 index 822e6b57f..000000000 --- a/lib/symfony/config/Definition/EnumNode.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; - -/** - * Node which only allows a finite set of values. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class EnumNode extends ScalarNode -{ - private $values; - - public function __construct(?string $name, NodeInterface $parent = null, array $values = [], string $pathSeparator = BaseNode::DEFAULT_PATH_SEPARATOR) - { - $values = array_unique($values); - if (empty($values)) { - throw new \InvalidArgumentException('$values must contain at least one element.'); - } - - parent::__construct($name, $parent, $pathSeparator); - $this->values = $values; - } - - public function getValues() - { - return $this->values; - } - - /** - * {@inheritdoc} - */ - protected function finalizeValue($value) - { - $value = parent::finalizeValue($value); - - if (!\in_array($value, $this->values, true)) { - $ex = new InvalidConfigurationException(sprintf('The value %s is not allowed for path "%s". Permissible values: %s', json_encode($value), $this->getPath(), implode(', ', array_map('json_encode', $this->values)))); - $ex->setPath($this->getPath()); - - throw $ex; - } - - return $value; - } - - /** - * {@inheritdoc} - */ - protected function allowPlaceholders(): bool - { - return false; - } -} diff --git a/lib/symfony/config/Definition/Exception/DuplicateKeyException.php b/lib/symfony/config/Definition/Exception/DuplicateKeyException.php deleted file mode 100644 index 48dd9325e..000000000 --- a/lib/symfony/config/Definition/Exception/DuplicateKeyException.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Exception; - -/** - * This exception is thrown whenever the key of an array is not unique. This can - * only be the case if the configuration is coming from an XML file. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class DuplicateKeyException extends InvalidConfigurationException -{ -} diff --git a/lib/symfony/config/Definition/Exception/Exception.php b/lib/symfony/config/Definition/Exception/Exception.php deleted file mode 100644 index 8933a4923..000000000 --- a/lib/symfony/config/Definition/Exception/Exception.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Exception; - -/** - * Base exception for all configuration exceptions. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class Exception extends \RuntimeException -{ -} diff --git a/lib/symfony/config/Definition/Exception/ForbiddenOverwriteException.php b/lib/symfony/config/Definition/Exception/ForbiddenOverwriteException.php deleted file mode 100644 index 726c07fb8..000000000 --- a/lib/symfony/config/Definition/Exception/ForbiddenOverwriteException.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Exception; - -/** - * This exception is thrown when a configuration path is overwritten from a - * subsequent configuration file, but the entry node specifically forbids this. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class ForbiddenOverwriteException extends InvalidConfigurationException -{ -} diff --git a/lib/symfony/config/Definition/Exception/InvalidConfigurationException.php b/lib/symfony/config/Definition/Exception/InvalidConfigurationException.php deleted file mode 100644 index ceb5e239b..000000000 --- a/lib/symfony/config/Definition/Exception/InvalidConfigurationException.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Exception; - -/** - * A very general exception which can be thrown whenever non of the more specific - * exceptions is suitable. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class InvalidConfigurationException extends Exception -{ - private $path; - private $containsHints = false; - - public function setPath(string $path) - { - $this->path = $path; - } - - public function getPath() - { - return $this->path; - } - - /** - * Adds extra information that is suffixed to the original exception message. - */ - public function addHint(string $hint) - { - if (!$this->containsHints) { - $this->message .= "\nHint: ".$hint; - $this->containsHints = true; - } else { - $this->message .= ', '.$hint; - } - } -} diff --git a/lib/symfony/config/Definition/Exception/InvalidDefinitionException.php b/lib/symfony/config/Definition/Exception/InvalidDefinitionException.php deleted file mode 100644 index 98310dae0..000000000 --- a/lib/symfony/config/Definition/Exception/InvalidDefinitionException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Exception; - -/** - * Thrown when an error is detected in a node Definition. - * - * @author Victor Berchet <victor.berchet@suumit.com> - */ -class InvalidDefinitionException extends Exception -{ -} diff --git a/lib/symfony/config/Definition/Exception/InvalidTypeException.php b/lib/symfony/config/Definition/Exception/InvalidTypeException.php deleted file mode 100644 index d7ca8c9d0..000000000 --- a/lib/symfony/config/Definition/Exception/InvalidTypeException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Exception; - -/** - * This exception is thrown if an invalid type is encountered. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class InvalidTypeException extends InvalidConfigurationException -{ -} diff --git a/lib/symfony/config/Definition/Exception/UnsetKeyException.php b/lib/symfony/config/Definition/Exception/UnsetKeyException.php deleted file mode 100644 index 863181a33..000000000 --- a/lib/symfony/config/Definition/Exception/UnsetKeyException.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Exception; - -/** - * This exception is usually not encountered by the end-user, but only used - * internally to signal the parent scope to unset a key. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class UnsetKeyException extends Exception -{ -} diff --git a/lib/symfony/config/Definition/FloatNode.php b/lib/symfony/config/Definition/FloatNode.php deleted file mode 100644 index 527f996ef..000000000 --- a/lib/symfony/config/Definition/FloatNode.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -use Symfony\Component\Config\Definition\Exception\InvalidTypeException; - -/** - * This node represents a float value in the config tree. - * - * @author Jeanmonod David <david.jeanmonod@gmail.com> - */ -class FloatNode extends NumericNode -{ - /** - * {@inheritdoc} - */ - protected function validateType($value) - { - // Integers are also accepted, we just cast them - if (\is_int($value)) { - $value = (float) $value; - } - - if (!\is_float($value)) { - $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected "float", but got "%s".', $this->getPath(), get_debug_type($value))); - if ($hint = $this->getInfo()) { - $ex->addHint($hint); - } - $ex->setPath($this->getPath()); - - throw $ex; - } - } - - /** - * {@inheritdoc} - */ - protected function getValidPlaceholderTypes(): array - { - return ['float']; - } -} diff --git a/lib/symfony/config/Definition/IntegerNode.php b/lib/symfony/config/Definition/IntegerNode.php deleted file mode 100644 index dfb4cc674..000000000 --- a/lib/symfony/config/Definition/IntegerNode.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -use Symfony\Component\Config\Definition\Exception\InvalidTypeException; - -/** - * This node represents an integer value in the config tree. - * - * @author Jeanmonod David <david.jeanmonod@gmail.com> - */ -class IntegerNode extends NumericNode -{ - /** - * {@inheritdoc} - */ - protected function validateType($value) - { - if (!\is_int($value)) { - $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected "int", but got "%s".', $this->getPath(), get_debug_type($value))); - if ($hint = $this->getInfo()) { - $ex->addHint($hint); - } - $ex->setPath($this->getPath()); - - throw $ex; - } - } - - /** - * {@inheritdoc} - */ - protected function getValidPlaceholderTypes(): array - { - return ['int']; - } -} diff --git a/lib/symfony/config/Definition/NodeInterface.php b/lib/symfony/config/Definition/NodeInterface.php deleted file mode 100644 index 9c279ae26..000000000 --- a/lib/symfony/config/Definition/NodeInterface.php +++ /dev/null @@ -1,100 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -use Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException; -use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; -use Symfony\Component\Config\Definition\Exception\InvalidTypeException; - -/** - * Common Interface among all nodes. - * - * In most cases, it is better to inherit from BaseNode instead of implementing - * this interface yourself. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -interface NodeInterface -{ - /** - * Returns the name of the node. - * - * @return string - */ - public function getName(); - - /** - * Returns the path of the node. - * - * @return string - */ - public function getPath(); - - /** - * Returns true when the node is required. - * - * @return bool - */ - public function isRequired(); - - /** - * Returns true when the node has a default value. - * - * @return bool - */ - public function hasDefaultValue(); - - /** - * Returns the default value of the node. - * - * @return mixed - * - * @throws \RuntimeException if the node has no default value - */ - public function getDefaultValue(); - - /** - * Normalizes a value. - * - * @param mixed $value The value to normalize - * - * @return mixed - * - * @throws InvalidTypeException if the value type is invalid - */ - public function normalize($value); - - /** - * Merges two values together. - * - * @param mixed $leftSide - * @param mixed $rightSide - * - * @return mixed - * - * @throws ForbiddenOverwriteException if the configuration path cannot be overwritten - * @throws InvalidTypeException if the value type is invalid - */ - public function merge($leftSide, $rightSide); - - /** - * Finalizes a value. - * - * @param mixed $value The value to finalize - * - * @return mixed - * - * @throws InvalidTypeException if the value type is invalid - * @throws InvalidConfigurationException if the value is invalid configuration - */ - public function finalize($value); -} diff --git a/lib/symfony/config/Definition/NumericNode.php b/lib/symfony/config/Definition/NumericNode.php deleted file mode 100644 index 50d137c2d..000000000 --- a/lib/symfony/config/Definition/NumericNode.php +++ /dev/null @@ -1,68 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; - -/** - * This node represents a numeric value in the config tree. - * - * @author David Jeanmonod <david.jeanmonod@gmail.com> - */ -class NumericNode extends ScalarNode -{ - protected $min; - protected $max; - - /** - * @param int|float|null $min - * @param int|float|null $max - */ - public function __construct(?string $name, NodeInterface $parent = null, $min = null, $max = null, string $pathSeparator = BaseNode::DEFAULT_PATH_SEPARATOR) - { - parent::__construct($name, $parent, $pathSeparator); - $this->min = $min; - $this->max = $max; - } - - /** - * {@inheritdoc} - */ - protected function finalizeValue($value) - { - $value = parent::finalizeValue($value); - - $errorMsg = null; - if (isset($this->min) && $value < $this->min) { - $errorMsg = sprintf('The value %s is too small for path "%s". Should be greater than or equal to %s', $value, $this->getPath(), $this->min); - } - if (isset($this->max) && $value > $this->max) { - $errorMsg = sprintf('The value %s is too big for path "%s". Should be less than or equal to %s', $value, $this->getPath(), $this->max); - } - if (isset($errorMsg)) { - $ex = new InvalidConfigurationException($errorMsg); - $ex->setPath($this->getPath()); - throw $ex; - } - - return $value; - } - - /** - * {@inheritdoc} - */ - protected function isValueEmpty($value) - { - // a numeric value cannot be empty - return false; - } -} diff --git a/lib/symfony/config/Definition/Processor.php b/lib/symfony/config/Definition/Processor.php deleted file mode 100644 index c431408e1..000000000 --- a/lib/symfony/config/Definition/Processor.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -/** - * This class is the entry point for config normalization/merging/finalization. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - * - * @final - */ -class Processor -{ - /** - * Processes an array of configurations. - * - * @param array $configs An array of configuration items to process - */ - public function process(NodeInterface $configTree, array $configs): array - { - $currentConfig = []; - foreach ($configs as $config) { - $config = $configTree->normalize($config); - $currentConfig = $configTree->merge($currentConfig, $config); - } - - return $configTree->finalize($currentConfig); - } - - /** - * Processes an array of configurations. - * - * @param array $configs An array of configuration items to process - */ - public function processConfiguration(ConfigurationInterface $configuration, array $configs): array - { - return $this->process($configuration->getConfigTreeBuilder()->buildTree(), $configs); - } - - /** - * Normalizes a configuration entry. - * - * This method returns a normalize configuration array for a given key - * to remove the differences due to the original format (YAML and XML mainly). - * - * Here is an example. - * - * The configuration in XML: - * - * <twig:extension>twig.extension.foo</twig:extension> - * <twig:extension>twig.extension.bar</twig:extension> - * - * And the same configuration in YAML: - * - * extensions: ['twig.extension.foo', 'twig.extension.bar'] - * - * @param array $config A config array - * @param string $key The key to normalize - * @param string $plural The plural form of the key if it is irregular - */ - public static function normalizeConfig(array $config, string $key, string $plural = null): array - { - if (null === $plural) { - $plural = $key.'s'; - } - - if (isset($config[$plural])) { - return $config[$plural]; - } - - if (isset($config[$key])) { - if (\is_string($config[$key]) || !\is_int(key($config[$key]))) { - // only one - return [$config[$key]]; - } - - return $config[$key]; - } - - return []; - } -} diff --git a/lib/symfony/config/Definition/PrototypeNodeInterface.php b/lib/symfony/config/Definition/PrototypeNodeInterface.php deleted file mode 100644 index b160aa94a..000000000 --- a/lib/symfony/config/Definition/PrototypeNodeInterface.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -/** - * This interface must be implemented by nodes which can be used as prototypes. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -interface PrototypeNodeInterface extends NodeInterface -{ - /** - * Sets the name of the node. - */ - public function setName(string $name); -} diff --git a/lib/symfony/config/Definition/PrototypedArrayNode.php b/lib/symfony/config/Definition/PrototypedArrayNode.php deleted file mode 100644 index e78159c9d..000000000 --- a/lib/symfony/config/Definition/PrototypedArrayNode.php +++ /dev/null @@ -1,350 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -use Symfony\Component\Config\Definition\Exception\DuplicateKeyException; -use Symfony\Component\Config\Definition\Exception\Exception; -use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; -use Symfony\Component\Config\Definition\Exception\UnsetKeyException; - -/** - * Represents a prototyped Array node in the config tree. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class PrototypedArrayNode extends ArrayNode -{ - protected $prototype; - protected $keyAttribute; - protected $removeKeyAttribute = false; - protected $minNumberOfElements = 0; - protected $defaultValue = []; - protected $defaultChildren; - /** - * @var NodeInterface[] An array of the prototypes of the simplified value children - */ - private $valuePrototypes = []; - - /** - * Sets the minimum number of elements that a prototype based node must - * contain. By default this is zero, meaning no elements. - */ - public function setMinNumberOfElements(int $number) - { - $this->minNumberOfElements = $number; - } - - /** - * Sets the attribute which value is to be used as key. - * - * This is useful when you have an indexed array that should be an - * associative array. You can select an item from within the array - * to be the key of the particular item. For example, if "id" is the - * "key", then: - * - * [ - * ['id' => 'my_name', 'foo' => 'bar'], - * ]; - * - * becomes - * - * [ - * 'my_name' => ['foo' => 'bar'], - * ]; - * - * If you'd like "'id' => 'my_name'" to still be present in the resulting - * array, then you can set the second argument of this method to false. - * - * @param string $attribute The name of the attribute which value is to be used as a key - * @param bool $remove Whether or not to remove the key - */ - public function setKeyAttribute(string $attribute, bool $remove = true) - { - $this->keyAttribute = $attribute; - $this->removeKeyAttribute = $remove; - } - - /** - * Retrieves the name of the attribute which value should be used as key. - * - * @return string|null - */ - public function getKeyAttribute() - { - return $this->keyAttribute; - } - - /** - * Sets the default value of this node. - */ - public function setDefaultValue(array $value) - { - $this->defaultValue = $value; - } - - /** - * {@inheritdoc} - */ - public function hasDefaultValue() - { - return true; - } - - /** - * Adds default children when none are set. - * - * @param int|string|array|null $children The number of children|The child name|The children names to be added - */ - public function setAddChildrenIfNoneSet($children = ['defaults']) - { - if (null === $children) { - $this->defaultChildren = ['defaults']; - } else { - $this->defaultChildren = \is_int($children) && $children > 0 ? range(1, $children) : (array) $children; - } - } - - /** - * {@inheritdoc} - * - * The default value could be either explicited or derived from the prototype - * default value. - */ - public function getDefaultValue() - { - if (null !== $this->defaultChildren) { - $default = $this->prototype->hasDefaultValue() ? $this->prototype->getDefaultValue() : []; - $defaults = []; - foreach (array_values($this->defaultChildren) as $i => $name) { - $defaults[null === $this->keyAttribute ? $i : $name] = $default; - } - - return $defaults; - } - - return $this->defaultValue; - } - - /** - * Sets the node prototype. - */ - public function setPrototype(PrototypeNodeInterface $node) - { - $this->prototype = $node; - } - - /** - * Retrieves the prototype. - * - * @return PrototypeNodeInterface - */ - public function getPrototype() - { - return $this->prototype; - } - - /** - * Disable adding concrete children for prototyped nodes. - * - * @throws Exception - */ - public function addChild(NodeInterface $node) - { - throw new Exception('A prototyped array node cannot have concrete children.'); - } - - /** - * {@inheritdoc} - */ - protected function finalizeValue($value) - { - if (false === $value) { - throw new UnsetKeyException(sprintf('Unsetting key for path "%s", value: %s.', $this->getPath(), json_encode($value))); - } - - foreach ($value as $k => $v) { - $prototype = $this->getPrototypeForChild($k); - try { - $value[$k] = $prototype->finalize($v); - } catch (UnsetKeyException $e) { - unset($value[$k]); - } - } - - if (\count($value) < $this->minNumberOfElements) { - $ex = new InvalidConfigurationException(sprintf('The path "%s" should have at least %d element(s) defined.', $this->getPath(), $this->minNumberOfElements)); - $ex->setPath($this->getPath()); - - throw $ex; - } - - return $value; - } - - /** - * {@inheritdoc} - * - * @throws DuplicateKeyException - */ - protected function normalizeValue($value) - { - if (false === $value) { - return $value; - } - - $value = $this->remapXml($value); - - $isList = array_is_list($value); - $normalized = []; - foreach ($value as $k => $v) { - if (null !== $this->keyAttribute && \is_array($v)) { - if (!isset($v[$this->keyAttribute]) && \is_int($k) && $isList) { - $ex = new InvalidConfigurationException(sprintf('The attribute "%s" must be set for path "%s".', $this->keyAttribute, $this->getPath())); - $ex->setPath($this->getPath()); - - throw $ex; - } elseif (isset($v[$this->keyAttribute])) { - $k = $v[$this->keyAttribute]; - - if (\is_float($k)) { - $k = var_export($k, true); - } - - // remove the key attribute when required - if ($this->removeKeyAttribute) { - unset($v[$this->keyAttribute]); - } - - // if only "value" is left - if (array_keys($v) === ['value']) { - $v = $v['value']; - if ($this->prototype instanceof ArrayNode && ($children = $this->prototype->getChildren()) && \array_key_exists('value', $children)) { - $valuePrototype = current($this->valuePrototypes) ?: clone $children['value']; - $valuePrototype->parent = $this; - $originalClosures = $this->prototype->normalizationClosures; - if (\is_array($originalClosures)) { - $valuePrototypeClosures = $valuePrototype->normalizationClosures; - $valuePrototype->normalizationClosures = \is_array($valuePrototypeClosures) ? array_merge($originalClosures, $valuePrototypeClosures) : $originalClosures; - } - $this->valuePrototypes[$k] = $valuePrototype; - } - } - } - - if (\array_key_exists($k, $normalized)) { - $ex = new DuplicateKeyException(sprintf('Duplicate key "%s" for path "%s".', $k, $this->getPath())); - $ex->setPath($this->getPath()); - - throw $ex; - } - } - - $prototype = $this->getPrototypeForChild($k); - if (null !== $this->keyAttribute || !$isList) { - $normalized[$k] = $prototype->normalize($v); - } else { - $normalized[] = $prototype->normalize($v); - } - } - - return $normalized; - } - - /** - * {@inheritdoc} - */ - protected function mergeValues($leftSide, $rightSide) - { - if (false === $rightSide) { - // if this is still false after the last config has been merged the - // finalization pass will take care of removing this key entirely - return false; - } - - if (false === $leftSide || !$this->performDeepMerging) { - return $rightSide; - } - - $isList = array_is_list($rightSide); - foreach ($rightSide as $k => $v) { - // prototype, and key is irrelevant there are no named keys, append the element - if (null === $this->keyAttribute && $isList) { - $leftSide[] = $v; - continue; - } - - // no conflict - if (!\array_key_exists($k, $leftSide)) { - if (!$this->allowNewKeys) { - $ex = new InvalidConfigurationException(sprintf('You are not allowed to define new elements for path "%s". Please define all elements for this path in one config file.', $this->getPath())); - $ex->setPath($this->getPath()); - - throw $ex; - } - - $leftSide[$k] = $v; - continue; - } - - $prototype = $this->getPrototypeForChild($k); - $leftSide[$k] = $prototype->merge($leftSide[$k], $v); - } - - return $leftSide; - } - - /** - * Returns a prototype for the child node that is associated to $key in the value array. - * For general child nodes, this will be $this->prototype. - * But if $this->removeKeyAttribute is true and there are only two keys in the child node: - * one is same as this->keyAttribute and the other is 'value', then the prototype will be different. - * - * For example, assume $this->keyAttribute is 'name' and the value array is as follows: - * - * [ - * [ - * 'name' => 'name001', - * 'value' => 'value001' - * ] - * ] - * - * Now, the key is 0 and the child node is: - * - * [ - * 'name' => 'name001', - * 'value' => 'value001' - * ] - * - * When normalizing the value array, the 'name' element will removed from the child node - * and its value becomes the new key of the child node: - * - * [ - * 'name001' => ['value' => 'value001'] - * ] - * - * Now only 'value' element is left in the child node which can be further simplified into a string: - * - * ['name001' => 'value001'] - * - * Now, the key becomes 'name001' and the child node becomes 'value001' and - * the prototype of child node 'name001' should be a ScalarNode instead of an ArrayNode instance. - * - * @return mixed - */ - private function getPrototypeForChild(string $key) - { - $prototype = $this->valuePrototypes[$key] ?? $this->prototype; - $prototype->setName($key); - - return $prototype; - } -} diff --git a/lib/symfony/config/Definition/ScalarNode.php b/lib/symfony/config/Definition/ScalarNode.php deleted file mode 100644 index 89ed4c3dc..000000000 --- a/lib/symfony/config/Definition/ScalarNode.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -use Symfony\Component\Config\Definition\Exception\InvalidTypeException; - -/** - * This node represents a scalar value in the config tree. - * - * The following values are considered scalars: - * * booleans - * * strings - * * null - * * integers - * * floats - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class ScalarNode extends VariableNode -{ - /** - * {@inheritdoc} - */ - protected function validateType($value) - { - if (!\is_scalar($value) && null !== $value) { - $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected "scalar", but got "%s".', $this->getPath(), get_debug_type($value))); - if ($hint = $this->getInfo()) { - $ex->addHint($hint); - } - $ex->setPath($this->getPath()); - - throw $ex; - } - } - - /** - * {@inheritdoc} - */ - protected function isValueEmpty($value) - { - // assume environment variables are never empty (which in practice is likely to be true during runtime) - // not doing so breaks many configs that are valid today - if ($this->isHandlingPlaceholder()) { - return false; - } - - return null === $value || '' === $value; - } - - /** - * {@inheritdoc} - */ - protected function getValidPlaceholderTypes(): array - { - return ['bool', 'int', 'float', 'string']; - } -} diff --git a/lib/symfony/config/Definition/VariableNode.php b/lib/symfony/config/Definition/VariableNode.php deleted file mode 100644 index e868ece13..000000000 --- a/lib/symfony/config/Definition/VariableNode.php +++ /dev/null @@ -1,142 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; - -/** - * This node represents a value of variable type in the config tree. - * - * This node is intended for values of arbitrary type. - * Any PHP type is accepted as a value. - * - * @author Jeremy Mikola <jmikola@gmail.com> - */ -class VariableNode extends BaseNode implements PrototypeNodeInterface -{ - protected $defaultValueSet = false; - protected $defaultValue; - protected $allowEmptyValue = true; - - public function setDefaultValue($value) - { - $this->defaultValueSet = true; - $this->defaultValue = $value; - } - - /** - * {@inheritdoc} - */ - public function hasDefaultValue() - { - return $this->defaultValueSet; - } - - /** - * {@inheritdoc} - */ - public function getDefaultValue() - { - $v = $this->defaultValue; - - return $v instanceof \Closure ? $v() : $v; - } - - /** - * Sets if this node is allowed to have an empty value. - * - * @param bool $boolean True if this entity will accept empty values - */ - public function setAllowEmptyValue(bool $boolean) - { - $this->allowEmptyValue = $boolean; - } - - /** - * {@inheritdoc} - */ - public function setName(string $name) - { - $this->name = $name; - } - - /** - * {@inheritdoc} - */ - protected function validateType($value) - { - } - - /** - * {@inheritdoc} - */ - protected function finalizeValue($value) - { - // deny environment variables only when using custom validators - // this avoids ever passing an empty value to final validation closures - if (!$this->allowEmptyValue && $this->isHandlingPlaceholder() && $this->finalValidationClosures) { - $e = new InvalidConfigurationException(sprintf('The path "%s" cannot contain an environment variable when empty values are not allowed by definition and are validated.', $this->getPath())); - if ($hint = $this->getInfo()) { - $e->addHint($hint); - } - $e->setPath($this->getPath()); - - throw $e; - } - - if (!$this->allowEmptyValue && $this->isValueEmpty($value)) { - $ex = new InvalidConfigurationException(sprintf('The path "%s" cannot contain an empty value, but got %s.', $this->getPath(), json_encode($value))); - if ($hint = $this->getInfo()) { - $ex->addHint($hint); - } - $ex->setPath($this->getPath()); - - throw $ex; - } - - return $value; - } - - /** - * {@inheritdoc} - */ - protected function normalizeValue($value) - { - return $value; - } - - /** - * {@inheritdoc} - */ - protected function mergeValues($leftSide, $rightSide) - { - return $rightSide; - } - - /** - * Evaluates if the given value is to be treated as empty. - * - * By default, PHP's empty() function is used to test for emptiness. This - * method may be overridden by subtypes to better match their understanding - * of empty data. - * - * @param mixed $value - * - * @return bool - * - * @see finalizeValue() - */ - protected function isValueEmpty($value) - { - return empty($value); - } -} diff --git a/lib/symfony/config/Exception/FileLoaderImportCircularReferenceException.php b/lib/symfony/config/Exception/FileLoaderImportCircularReferenceException.php deleted file mode 100644 index e235ea049..000000000 --- a/lib/symfony/config/Exception/FileLoaderImportCircularReferenceException.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Exception; - -/** - * Exception class for when a circular reference is detected when importing resources. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class FileLoaderImportCircularReferenceException extends LoaderLoadException -{ - public function __construct(array $resources, ?int $code = 0, \Throwable $previous = null) - { - if (null === $code) { - trigger_deprecation('symfony/config', '5.3', 'Passing null as $code to "%s()" is deprecated, pass 0 instead.', __METHOD__); - - $code = 0; - } - - $message = sprintf('Circular reference detected in "%s" ("%s" > "%s").', $this->varToString($resources[0]), implode('" > "', $resources), $resources[0]); - - \Exception::__construct($message, $code, $previous); - } -} diff --git a/lib/symfony/config/Exception/FileLocatorFileNotFoundException.php b/lib/symfony/config/Exception/FileLocatorFileNotFoundException.php deleted file mode 100644 index 3ee4b938f..000000000 --- a/lib/symfony/config/Exception/FileLocatorFileNotFoundException.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Exception; - -/** - * File locator exception if a file does not exist. - * - * @author Leo Feyer <https://github.com/leofeyer> - */ -class FileLocatorFileNotFoundException extends \InvalidArgumentException -{ - private $paths; - - public function __construct(string $message = '', int $code = 0, \Throwable $previous = null, array $paths = []) - { - parent::__construct($message, $code, $previous); - - $this->paths = $paths; - } - - public function getPaths() - { - return $this->paths; - } -} diff --git a/lib/symfony/config/Exception/LoaderLoadException.php b/lib/symfony/config/Exception/LoaderLoadException.php deleted file mode 100644 index b20e74db4..000000000 --- a/lib/symfony/config/Exception/LoaderLoadException.php +++ /dev/null @@ -1,115 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Exception; - -/** - * Exception class for when a resource cannot be loaded or imported. - * - * @author Ryan Weaver <ryan@thatsquality.com> - */ -class LoaderLoadException extends \Exception -{ - /** - * @param string $resource The resource that could not be imported - * @param string|null $sourceResource The original resource importing the new resource - * @param int|null $code The error code - * @param \Throwable|null $previous A previous exception - * @param string|null $type The type of resource - */ - public function __construct(string $resource, string $sourceResource = null, ?int $code = 0, \Throwable $previous = null, string $type = null) - { - if (null === $code) { - trigger_deprecation('symfony/config', '5.3', 'Passing null as $code to "%s()" is deprecated, pass 0 instead.', __METHOD__); - - $code = 0; - } - - $message = ''; - if ($previous) { - // Include the previous exception, to help the user see what might be the underlying cause - - // Trim the trailing period of the previous message. We only want 1 period remove so no rtrim... - if ('.' === substr($previous->getMessage(), -1)) { - $trimmedMessage = substr($previous->getMessage(), 0, -1); - $message .= sprintf('%s', $trimmedMessage).' in '; - } else { - $message .= sprintf('%s', $previous->getMessage()).' in '; - } - $message .= $resource.' '; - - // show tweaked trace to complete the human readable sentence - if (null === $sourceResource) { - $message .= sprintf('(which is loaded in resource "%s")', $resource); - } else { - $message .= sprintf('(which is being imported from "%s")', $sourceResource); - } - $message .= '.'; - - // if there's no previous message, present it the default way - } elseif (null === $sourceResource) { - $message .= sprintf('Cannot load resource "%s".', $resource); - } else { - $message .= sprintf('Cannot import resource "%s" from "%s".', $resource, $sourceResource); - } - - // Is the resource located inside a bundle? - if ('@' === $resource[0]) { - $parts = explode(\DIRECTORY_SEPARATOR, $resource); - $bundle = substr($parts[0], 1); - $message .= sprintf(' Make sure the "%s" bundle is correctly registered and loaded in the application kernel class.', $bundle); - $message .= sprintf(' If the bundle is registered, make sure the bundle path "%s" is not empty.', $resource); - } elseif (null !== $type) { - // maybe there is no loader for this specific type - if ('annotation' === $type) { - $message .= ' Make sure to use PHP 8+ or that annotations are installed and enabled.'; - } else { - $message .= sprintf(' Make sure there is a loader supporting the "%s" type.', $type); - } - } - - parent::__construct($message, $code, $previous); - } - - protected function varToString($var) - { - if (\is_object($var)) { - return sprintf('Object(%s)', \get_class($var)); - } - - if (\is_array($var)) { - $a = []; - foreach ($var as $k => $v) { - $a[] = sprintf('%s => %s', $k, $this->varToString($v)); - } - - return sprintf('Array(%s)', implode(', ', $a)); - } - - if (\is_resource($var)) { - return sprintf('Resource(%s)', get_resource_type($var)); - } - - if (null === $var) { - return 'null'; - } - - if (false === $var) { - return 'false'; - } - - if (true === $var) { - return 'true'; - } - - return (string) $var; - } -} diff --git a/lib/symfony/config/FileLocator.php b/lib/symfony/config/FileLocator.php deleted file mode 100644 index da350908a..000000000 --- a/lib/symfony/config/FileLocator.php +++ /dev/null @@ -1,94 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config; - -use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException; - -/** - * FileLocator uses an array of pre-defined paths to find files. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class FileLocator implements FileLocatorInterface -{ - protected $paths; - - /** - * @param string|string[] $paths A path or an array of paths where to look for resources - */ - public function __construct($paths = []) - { - $this->paths = (array) $paths; - } - - /** - * {@inheritdoc} - */ - public function locate(string $name, string $currentPath = null, bool $first = true) - { - if ('' === $name) { - throw new \InvalidArgumentException('An empty file name is not valid to be located.'); - } - - if ($this->isAbsolutePath($name)) { - if (!file_exists($name)) { - throw new FileLocatorFileNotFoundException(sprintf('The file "%s" does not exist.', $name), 0, null, [$name]); - } - - return $name; - } - - $paths = $this->paths; - - if (null !== $currentPath) { - array_unshift($paths, $currentPath); - } - - $paths = array_unique($paths); - $filepaths = $notfound = []; - - foreach ($paths as $path) { - if (@file_exists($file = $path.\DIRECTORY_SEPARATOR.$name)) { - if (true === $first) { - return $file; - } - $filepaths[] = $file; - } else { - $notfound[] = $file; - } - } - - if (!$filepaths) { - throw new FileLocatorFileNotFoundException(sprintf('The file "%s" does not exist (in: "%s").', $name, implode('", "', $paths)), 0, null, $notfound); - } - - return $filepaths; - } - - /** - * Returns whether the file path is an absolute path. - */ - private function isAbsolutePath(string $file): bool - { - if ('/' === $file[0] || '\\' === $file[0] - || (\strlen($file) > 3 && ctype_alpha($file[0]) - && ':' === $file[1] - && ('\\' === $file[2] || '/' === $file[2]) - ) - || null !== parse_url($file, \PHP_URL_SCHEME) - ) { - return true; - } - - return false; - } -} diff --git a/lib/symfony/config/FileLocatorInterface.php b/lib/symfony/config/FileLocatorInterface.php deleted file mode 100644 index e3ca1d49c..000000000 --- a/lib/symfony/config/FileLocatorInterface.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config; - -use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -interface FileLocatorInterface -{ - /** - * Returns a full path for a given file name. - * - * @param string $name The file name to locate - * @param string|null $currentPath The current path - * @param bool $first Whether to return the first occurrence or an array of filenames - * - * @return string|array The full path to the file or an array of file paths - * - * @throws \InvalidArgumentException If $name is empty - * @throws FileLocatorFileNotFoundException If a file is not found - */ - public function locate(string $name, string $currentPath = null, bool $first = true); -} diff --git a/lib/symfony/config/LICENSE b/lib/symfony/config/LICENSE deleted file mode 100644 index 88bf75bb4..000000000 --- a/lib/symfony/config/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-2022 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -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/lib/symfony/config/Loader/DelegatingLoader.php b/lib/symfony/config/Loader/DelegatingLoader.php deleted file mode 100644 index e5a74ee63..000000000 --- a/lib/symfony/config/Loader/DelegatingLoader.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Loader; - -use Symfony\Component\Config\Exception\LoaderLoadException; - -/** - * DelegatingLoader delegates loading to other loaders using a loader resolver. - * - * This loader acts as an array of LoaderInterface objects - each having - * a chance to load a given resource (handled by the resolver) - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class DelegatingLoader extends Loader -{ - public function __construct(LoaderResolverInterface $resolver) - { - $this->resolver = $resolver; - } - - /** - * {@inheritdoc} - */ - public function load($resource, string $type = null) - { - if (false === $loader = $this->resolver->resolve($resource, $type)) { - throw new LoaderLoadException($resource, null, 0, null, $type); - } - - return $loader->load($resource, $type); - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - return false !== $this->resolver->resolve($resource, $type); - } -} diff --git a/lib/symfony/config/Loader/FileLoader.php b/lib/symfony/config/Loader/FileLoader.php deleted file mode 100644 index 4e1b46c4e..000000000 --- a/lib/symfony/config/Loader/FileLoader.php +++ /dev/null @@ -1,180 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Loader; - -use Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException; -use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException; -use Symfony\Component\Config\Exception\LoaderLoadException; -use Symfony\Component\Config\FileLocatorInterface; -use Symfony\Component\Config\Resource\FileExistenceResource; -use Symfony\Component\Config\Resource\GlobResource; - -/** - * FileLoader is the abstract class used by all built-in loaders that are file based. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -abstract class FileLoader extends Loader -{ - protected static $loading = []; - - protected $locator; - - private $currentDir; - - public function __construct(FileLocatorInterface $locator, string $env = null) - { - $this->locator = $locator; - parent::__construct($env); - } - - /** - * Sets the current directory. - */ - public function setCurrentDir(string $dir) - { - $this->currentDir = $dir; - } - - /** - * Returns the file locator used by this loader. - * - * @return FileLocatorInterface - */ - public function getLocator() - { - return $this->locator; - } - - /** - * Imports a resource. - * - * @param mixed $resource A Resource - * @param string|null $type The resource type or null if unknown - * @param bool $ignoreErrors Whether to ignore import errors or not - * @param string|null $sourceResource The original resource importing the new resource - * @param string|string[]|null $exclude Glob patterns to exclude from the import - * - * @return mixed - * - * @throws LoaderLoadException - * @throws FileLoaderImportCircularReferenceException - * @throws FileLocatorFileNotFoundException - */ - public function import($resource, string $type = null, bool $ignoreErrors = false, string $sourceResource = null, $exclude = null) - { - if (\is_string($resource) && \strlen($resource) !== ($i = strcspn($resource, '*?{[')) && !str_contains($resource, "\n")) { - $excluded = []; - foreach ((array) $exclude as $pattern) { - foreach ($this->glob($pattern, true, $_, false, true) as $path => $info) { - // normalize Windows slashes and remove trailing slashes - $excluded[rtrim(str_replace('\\', '/', $path), '/')] = true; - } - } - - $ret = []; - $isSubpath = 0 !== $i && str_contains(substr($resource, 0, $i), '/'); - foreach ($this->glob($resource, false, $_, $ignoreErrors || !$isSubpath, false, $excluded) as $path => $info) { - if (null !== $res = $this->doImport($path, 'glob' === $type ? null : $type, $ignoreErrors, $sourceResource)) { - $ret[] = $res; - } - $isSubpath = true; - } - - if ($isSubpath) { - return isset($ret[1]) ? $ret : ($ret[0] ?? null); - } - } - - return $this->doImport($resource, $type, $ignoreErrors, $sourceResource); - } - - /** - * @internal - */ - protected function glob(string $pattern, bool $recursive, &$resource = null, bool $ignoreErrors = false, bool $forExclusion = false, array $excluded = []) - { - if (\strlen($pattern) === $i = strcspn($pattern, '*?{[')) { - $prefix = $pattern; - $pattern = ''; - } elseif (0 === $i || !str_contains(substr($pattern, 0, $i), '/')) { - $prefix = '.'; - $pattern = '/'.$pattern; - } else { - $prefix = \dirname(substr($pattern, 0, 1 + $i)); - $pattern = substr($pattern, \strlen($prefix)); - } - - try { - $prefix = $this->locator->locate($prefix, $this->currentDir, true); - } catch (FileLocatorFileNotFoundException $e) { - if (!$ignoreErrors) { - throw $e; - } - - $resource = []; - foreach ($e->getPaths() as $path) { - $resource[] = new FileExistenceResource($path); - } - - return; - } - $resource = new GlobResource($prefix, $pattern, $recursive, $forExclusion, $excluded); - - yield from $resource; - } - - private function doImport($resource, string $type = null, bool $ignoreErrors = false, string $sourceResource = null) - { - try { - $loader = $this->resolve($resource, $type); - - if ($loader instanceof self && null !== $this->currentDir) { - $resource = $loader->getLocator()->locate($resource, $this->currentDir, false); - } - - $resources = \is_array($resource) ? $resource : [$resource]; - for ($i = 0; $i < $resourcesCount = \count($resources); ++$i) { - if (isset(self::$loading[$resources[$i]])) { - if ($i == $resourcesCount - 1) { - throw new FileLoaderImportCircularReferenceException(array_keys(self::$loading)); - } - } else { - $resource = $resources[$i]; - break; - } - } - self::$loading[$resource] = true; - - try { - $ret = $loader->load($resource, $type); - } finally { - unset(self::$loading[$resource]); - } - - return $ret; - } catch (FileLoaderImportCircularReferenceException $e) { - throw $e; - } catch (\Exception $e) { - if (!$ignoreErrors) { - // prevent embedded imports from nesting multiple exceptions - if ($e instanceof LoaderLoadException) { - throw $e; - } - - throw new LoaderLoadException($resource, $sourceResource, 0, $e, $type); - } - } - - return null; - } -} diff --git a/lib/symfony/config/Loader/GlobFileLoader.php b/lib/symfony/config/Loader/GlobFileLoader.php deleted file mode 100644 index fecb1c5d0..000000000 --- a/lib/symfony/config/Loader/GlobFileLoader.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Loader; - -/** - * GlobFileLoader loads files from a glob pattern. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class GlobFileLoader extends FileLoader -{ - /** - * {@inheritdoc} - */ - public function load($resource, string $type = null) - { - return $this->import($resource); - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - return 'glob' === $type; - } -} diff --git a/lib/symfony/config/Loader/Loader.php b/lib/symfony/config/Loader/Loader.php deleted file mode 100644 index e7d74b5a1..000000000 --- a/lib/symfony/config/Loader/Loader.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Loader; - -use Symfony\Component\Config\Exception\LoaderLoadException; - -/** - * Loader is the abstract class used by all built-in loaders. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -abstract class Loader implements LoaderInterface -{ - protected $resolver; - protected $env; - - public function __construct(string $env = null) - { - $this->env = $env; - } - - /** - * {@inheritdoc} - */ - public function getResolver() - { - return $this->resolver; - } - - /** - * {@inheritdoc} - */ - public function setResolver(LoaderResolverInterface $resolver) - { - $this->resolver = $resolver; - } - - /** - * Imports a resource. - * - * @param mixed $resource A resource - * @param string|null $type The resource type or null if unknown - * - * @return mixed - */ - public function import($resource, string $type = null) - { - return $this->resolve($resource, $type)->load($resource, $type); - } - - /** - * Finds a loader able to load an imported resource. - * - * @param mixed $resource A resource - * @param string|null $type The resource type or null if unknown - * - * @return LoaderInterface - * - * @throws LoaderLoadException If no loader is found - */ - public function resolve($resource, string $type = null) - { - if ($this->supports($resource, $type)) { - return $this; - } - - $loader = null === $this->resolver ? false : $this->resolver->resolve($resource, $type); - - if (false === $loader) { - throw new LoaderLoadException($resource, null, 0, null, $type); - } - - return $loader; - } -} diff --git a/lib/symfony/config/Loader/LoaderInterface.php b/lib/symfony/config/Loader/LoaderInterface.php deleted file mode 100644 index 93a160b1e..000000000 --- a/lib/symfony/config/Loader/LoaderInterface.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Loader; - -/** - * LoaderInterface is the interface implemented by all loader classes. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface LoaderInterface -{ - /** - * Loads a resource. - * - * @param mixed $resource The resource - * - * @return mixed - * - * @throws \Exception If something went wrong - */ - public function load($resource, string $type = null); - - /** - * Returns whether this class supports the given resource. - * - * @param mixed $resource A resource - * - * @return bool - */ - public function supports($resource, string $type = null); - - /** - * Gets the loader resolver. - * - * @return LoaderResolverInterface - */ - public function getResolver(); - - /** - * Sets the loader resolver. - */ - public function setResolver(LoaderResolverInterface $resolver); -} diff --git a/lib/symfony/config/Loader/LoaderResolver.php b/lib/symfony/config/Loader/LoaderResolver.php deleted file mode 100644 index cce0702b7..000000000 --- a/lib/symfony/config/Loader/LoaderResolver.php +++ /dev/null @@ -1,68 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Loader; - -/** - * LoaderResolver selects a loader for a given resource. - * - * A resource can be anything (e.g. a full path to a config file or a Closure). - * Each loader determines whether it can load a resource and how. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class LoaderResolver implements LoaderResolverInterface -{ - /** - * @var LoaderInterface[] An array of LoaderInterface objects - */ - private $loaders = []; - - /** - * @param LoaderInterface[] $loaders An array of loaders - */ - public function __construct(array $loaders = []) - { - foreach ($loaders as $loader) { - $this->addLoader($loader); - } - } - - /** - * {@inheritdoc} - */ - public function resolve($resource, string $type = null) - { - foreach ($this->loaders as $loader) { - if ($loader->supports($resource, $type)) { - return $loader; - } - } - - return false; - } - - public function addLoader(LoaderInterface $loader) - { - $this->loaders[] = $loader; - $loader->setResolver($this); - } - - /** - * Returns the registered loaders. - * - * @return LoaderInterface[] - */ - public function getLoaders() - { - return $this->loaders; - } -} diff --git a/lib/symfony/config/Loader/LoaderResolverInterface.php b/lib/symfony/config/Loader/LoaderResolverInterface.php deleted file mode 100644 index 8a4841947..000000000 --- a/lib/symfony/config/Loader/LoaderResolverInterface.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Loader; - -/** - * LoaderResolverInterface selects a loader for a given resource. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface LoaderResolverInterface -{ - /** - * Returns a loader able to load the resource. - * - * @param mixed $resource A resource - * @param string|null $type The resource type or null if unknown - * - * @return LoaderInterface|false - */ - public function resolve($resource, string $type = null); -} diff --git a/lib/symfony/config/Loader/ParamConfigurator.php b/lib/symfony/config/Loader/ParamConfigurator.php deleted file mode 100644 index 70c3f79a6..000000000 --- a/lib/symfony/config/Loader/ParamConfigurator.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Loader; - -/** - * Placeholder for a parameter. - * - * @author Tobias Nyholm <tobias.nyholm@gmail.com> - */ -class ParamConfigurator -{ - private $name; - - public function __construct(string $name) - { - $this->name = $name; - } - - public function __toString(): string - { - return '%'.$this->name.'%'; - } -} diff --git a/lib/symfony/config/README.md b/lib/symfony/config/README.md deleted file mode 100644 index 10c2ddd05..000000000 --- a/lib/symfony/config/README.md +++ /dev/null @@ -1,15 +0,0 @@ -Config Component -================ - -The Config component helps find, load, combine, autofill and validate -configuration values of any kind, whatever their source may be (YAML, XML, INI -files, or for instance a database). - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/config.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/lib/symfony/config/Resource/ClassExistenceResource.php b/lib/symfony/config/Resource/ClassExistenceResource.php deleted file mode 100644 index 6aff151cc..000000000 --- a/lib/symfony/config/Resource/ClassExistenceResource.php +++ /dev/null @@ -1,232 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Resource; - -/** - * ClassExistenceResource represents a class existence. - * Freshness is only evaluated against resource existence. - * - * The resource must be a fully-qualified class name. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class ClassExistenceResource implements SelfCheckingResourceInterface -{ - private $resource; - private $exists; - - private static $autoloadLevel = 0; - private static $autoloadedClass; - private static $existsCache = []; - - /** - * @param string $resource The fully-qualified class name - * @param bool|null $exists Boolean when the existency check has already been done - */ - public function __construct(string $resource, bool $exists = null) - { - $this->resource = $resource; - if (null !== $exists) { - $this->exists = [$exists, null]; - } - } - - public function __toString(): string - { - return $this->resource; - } - - public function getResource(): string - { - return $this->resource; - } - - /** - * {@inheritdoc} - * - * @throws \ReflectionException when a parent class/interface/trait is not found - */ - public function isFresh(int $timestamp): bool - { - $loaded = class_exists($this->resource, false) || interface_exists($this->resource, false) || trait_exists($this->resource, false); - - if (null !== $exists = &self::$existsCache[$this->resource]) { - if ($loaded) { - $exists = [true, null]; - } elseif (0 >= $timestamp && !$exists[0] && null !== $exists[1]) { - throw new \ReflectionException($exists[1]); - } - } elseif ([false, null] === $exists = [$loaded, null]) { - if (!self::$autoloadLevel++) { - spl_autoload_register(__CLASS__.'::throwOnRequiredClass'); - } - $autoloadedClass = self::$autoloadedClass; - self::$autoloadedClass = ltrim($this->resource, '\\'); - - try { - $exists[0] = class_exists($this->resource) || interface_exists($this->resource, false) || trait_exists($this->resource, false); - } catch (\Exception $e) { - $exists[1] = $e->getMessage(); - - try { - self::throwOnRequiredClass($this->resource, $e); - } catch (\ReflectionException $e) { - if (0 >= $timestamp) { - throw $e; - } - } - } catch (\Throwable $e) { - $exists[1] = $e->getMessage(); - - throw $e; - } finally { - self::$autoloadedClass = $autoloadedClass; - if (!--self::$autoloadLevel) { - spl_autoload_unregister(__CLASS__.'::throwOnRequiredClass'); - } - } - } - - if (null === $this->exists) { - $this->exists = $exists; - } - - return $this->exists[0] xor !$exists[0]; - } - - /** - * @internal - */ - public function __sleep(): array - { - if (null === $this->exists) { - $this->isFresh(0); - } - - return ['resource', 'exists']; - } - - /** - * @internal - */ - public function __wakeup() - { - if (\is_bool($this->exists)) { - $this->exists = [$this->exists, null]; - } - } - - /** - * Throws a reflection exception when the passed class does not exist but is required. - * - * A class is considered "not required" when it's loaded as part of a "class_exists" or similar check. - * - * This function can be used as an autoload function to throw a reflection - * exception if the class was not found by previous autoload functions. - * - * A previous exception can be passed. In this case, the class is considered as being - * required totally, so if it doesn't exist, a reflection exception is always thrown. - * If it exists, the previous exception is rethrown. - * - * @throws \ReflectionException - * - * @internal - */ - public static function throwOnRequiredClass(string $class, \Exception $previous = null) - { - // If the passed class is the resource being checked, we shouldn't throw. - if (null === $previous && self::$autoloadedClass === $class) { - return; - } - - if (class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false)) { - if (null !== $previous) { - throw $previous; - } - - return; - } - - if ($previous instanceof \ReflectionException) { - throw $previous; - } - - $message = sprintf('Class "%s" not found.', $class); - - if (self::$autoloadedClass !== $class) { - $message = substr_replace($message, sprintf(' while loading "%s"', self::$autoloadedClass), -1, 0); - } - - if (null !== $previous) { - $message = $previous->getMessage(); - } - - $e = new \ReflectionException($message, 0, $previous); - - if (null !== $previous) { - throw $e; - } - - $trace = debug_backtrace(); - $autoloadFrame = [ - 'function' => 'spl_autoload_call', - 'args' => [$class], - ]; - - if (\PHP_VERSION_ID >= 80000 && isset($trace[1])) { - $callerFrame = $trace[1]; - $i = 2; - } elseif (false !== $i = array_search($autoloadFrame, $trace, true)) { - $callerFrame = $trace[++$i]; - } else { - throw $e; - } - - if (isset($callerFrame['function']) && !isset($callerFrame['class'])) { - switch ($callerFrame['function']) { - case 'get_class_methods': - case 'get_class_vars': - case 'get_parent_class': - case 'is_a': - case 'is_subclass_of': - case 'class_exists': - case 'class_implements': - case 'class_parents': - case 'trait_exists': - case 'defined': - case 'interface_exists': - case 'method_exists': - case 'property_exists': - case 'is_callable': - return; - } - - $props = [ - 'file' => $callerFrame['file'] ?? null, - 'line' => $callerFrame['line'] ?? null, - 'trace' => \array_slice($trace, 1 + $i), - ]; - - foreach ($props as $p => $v) { - if (null !== $v) { - $r = new \ReflectionProperty(\Exception::class, $p); - $r->setAccessible(true); - $r->setValue($e, $v); - } - } - } - - throw $e; - } -} diff --git a/lib/symfony/config/Resource/ComposerResource.php b/lib/symfony/config/Resource/ComposerResource.php deleted file mode 100644 index f552f80ac..000000000 --- a/lib/symfony/config/Resource/ComposerResource.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Resource; - -/** - * ComposerResource tracks the PHP version and Composer dependencies. - * - * @author Nicolas Grekas <p@tchwork.com> - * - * @final - */ -class ComposerResource implements SelfCheckingResourceInterface -{ - private $vendors; - - private static $runtimeVendors; - - public function __construct() - { - self::refresh(); - $this->vendors = self::$runtimeVendors; - } - - public function getVendors(): array - { - return array_keys($this->vendors); - } - - public function __toString(): string - { - return __CLASS__; - } - - /** - * {@inheritdoc} - */ - public function isFresh(int $timestamp): bool - { - self::refresh(); - - return array_values(self::$runtimeVendors) === array_values($this->vendors); - } - - private static function refresh() - { - self::$runtimeVendors = []; - - foreach (get_declared_classes() as $class) { - if ('C' === $class[0] && str_starts_with($class, 'ComposerAutoloaderInit')) { - $r = new \ReflectionClass($class); - $v = \dirname($r->getFileName(), 2); - if (is_file($v.'/composer/installed.json')) { - self::$runtimeVendors[$v] = @filemtime($v.'/composer/installed.json'); - } - } - } - } -} diff --git a/lib/symfony/config/Resource/DirectoryResource.php b/lib/symfony/config/Resource/DirectoryResource.php deleted file mode 100644 index 035814a2a..000000000 --- a/lib/symfony/config/Resource/DirectoryResource.php +++ /dev/null @@ -1,97 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Resource; - -/** - * DirectoryResource represents a resources stored in a subdirectory tree. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class DirectoryResource implements SelfCheckingResourceInterface -{ - private $resource; - private $pattern; - - /** - * @param string $resource The file path to the resource - * @param string|null $pattern A pattern to restrict monitored files - * - * @throws \InvalidArgumentException - */ - public function __construct(string $resource, string $pattern = null) - { - $this->resource = realpath($resource) ?: (file_exists($resource) ? $resource : false); - $this->pattern = $pattern; - - if (false === $this->resource || !is_dir($this->resource)) { - throw new \InvalidArgumentException(sprintf('The directory "%s" does not exist.', $resource)); - } - } - - public function __toString(): string - { - return md5(serialize([$this->resource, $this->pattern])); - } - - public function getResource(): string - { - return $this->resource; - } - - public function getPattern(): ?string - { - return $this->pattern; - } - - /** - * {@inheritdoc} - */ - public function isFresh(int $timestamp): bool - { - if (!is_dir($this->resource)) { - return false; - } - - if ($timestamp < filemtime($this->resource)) { - return false; - } - - foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->resource), \RecursiveIteratorIterator::SELF_FIRST) as $file) { - // if regex filtering is enabled only check matching files - if ($this->pattern && $file->isFile() && !preg_match($this->pattern, $file->getBasename())) { - continue; - } - - // always monitor directories for changes, except the .. entries - // (otherwise deleted files wouldn't get detected) - if ($file->isDir() && str_ends_with($file, '/..')) { - continue; - } - - // for broken links - try { - $fileMTime = $file->getMTime(); - } catch (\RuntimeException $e) { - continue; - } - - // early return if a file's mtime exceeds the passed timestamp - if ($timestamp < $fileMTime) { - return false; - } - } - - return true; - } -} diff --git a/lib/symfony/config/Resource/FileExistenceResource.php b/lib/symfony/config/Resource/FileExistenceResource.php deleted file mode 100644 index 6d79d6d1b..000000000 --- a/lib/symfony/config/Resource/FileExistenceResource.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Resource; - -/** - * FileExistenceResource represents a resource stored on the filesystem. - * Freshness is only evaluated against resource creation or deletion. - * - * The resource can be a file or a directory. - * - * @author Charles-Henri Bruyand <charleshenri.bruyand@gmail.com> - * - * @final - */ -class FileExistenceResource implements SelfCheckingResourceInterface -{ - private $resource; - - private $exists; - - /** - * @param string $resource The file path to the resource - */ - public function __construct(string $resource) - { - $this->resource = $resource; - $this->exists = file_exists($resource); - } - - public function __toString(): string - { - return $this->resource; - } - - public function getResource(): string - { - return $this->resource; - } - - /** - * {@inheritdoc} - */ - public function isFresh(int $timestamp): bool - { - return file_exists($this->resource) === $this->exists; - } -} diff --git a/lib/symfony/config/Resource/FileResource.php b/lib/symfony/config/Resource/FileResource.php deleted file mode 100644 index ee6684cdc..000000000 --- a/lib/symfony/config/Resource/FileResource.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Resource; - -/** - * FileResource represents a resource stored on the filesystem. - * - * The resource can be a file or a directory. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class FileResource implements SelfCheckingResourceInterface -{ - /** - * @var string|false - */ - private $resource; - - /** - * @param string $resource The file path to the resource - * - * @throws \InvalidArgumentException - */ - public function __construct(string $resource) - { - $this->resource = realpath($resource) ?: (file_exists($resource) ? $resource : false); - - if (false === $this->resource) { - throw new \InvalidArgumentException(sprintf('The file "%s" does not exist.', $resource)); - } - } - - public function __toString(): string - { - return $this->resource; - } - - /** - * Returns the canonicalized, absolute path to the resource. - */ - public function getResource(): string - { - return $this->resource; - } - - /** - * {@inheritdoc} - */ - public function isFresh(int $timestamp): bool - { - return false !== ($filemtime = @filemtime($this->resource)) && $filemtime <= $timestamp; - } -} diff --git a/lib/symfony/config/Resource/GlobResource.php b/lib/symfony/config/Resource/GlobResource.php deleted file mode 100644 index 2bfbe2e4b..000000000 --- a/lib/symfony/config/Resource/GlobResource.php +++ /dev/null @@ -1,246 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Resource; - -use Symfony\Component\Finder\Finder; -use Symfony\Component\Finder\Glob; - -/** - * GlobResource represents a set of resources stored on the filesystem. - * - * Only existence/removal is tracked (not mtimes.) - * - * @author Nicolas Grekas <p@tchwork.com> - * - * @final - * - * @implements \IteratorAggregate<string, \SplFileInfo> - */ -class GlobResource implements \IteratorAggregate, SelfCheckingResourceInterface -{ - private $prefix; - private $pattern; - private $recursive; - private $hash; - private $forExclusion; - private $excludedPrefixes; - private $globBrace; - - /** - * @param string $prefix A directory prefix - * @param string $pattern A glob pattern - * @param bool $recursive Whether directories should be scanned recursively or not - * - * @throws \InvalidArgumentException - */ - public function __construct(string $prefix, string $pattern, bool $recursive, bool $forExclusion = false, array $excludedPrefixes = []) - { - ksort($excludedPrefixes); - $this->prefix = realpath($prefix) ?: (file_exists($prefix) ? $prefix : false); - $this->pattern = $pattern; - $this->recursive = $recursive; - $this->forExclusion = $forExclusion; - $this->excludedPrefixes = $excludedPrefixes; - $this->globBrace = \defined('GLOB_BRACE') ? \GLOB_BRACE : 0; - - if (false === $this->prefix) { - throw new \InvalidArgumentException(sprintf('The path "%s" does not exist.', $prefix)); - } - } - - public function getPrefix(): string - { - return $this->prefix; - } - - public function __toString(): string - { - return 'glob.'.$this->prefix.(int) $this->recursive.$this->pattern.(int) $this->forExclusion.implode("\0", $this->excludedPrefixes); - } - - /** - * {@inheritdoc} - */ - public function isFresh(int $timestamp): bool - { - $hash = $this->computeHash(); - - if (null === $this->hash) { - $this->hash = $hash; - } - - return $this->hash === $hash; - } - - /** - * @internal - */ - public function __sleep(): array - { - if (null === $this->hash) { - $this->hash = $this->computeHash(); - } - - return ['prefix', 'pattern', 'recursive', 'hash', 'forExclusion', 'excludedPrefixes']; - } - - /** - * @internal - */ - public function __wakeup(): void - { - $this->globBrace = \defined('GLOB_BRACE') ? \GLOB_BRACE : 0; - } - - public function getIterator(): \Traversable - { - if (!file_exists($this->prefix) || (!$this->recursive && '' === $this->pattern)) { - return; - } - $prefix = str_replace('\\', '/', $this->prefix); - $paths = null; - - if ('' === $this->pattern && is_file($prefix)) { - $paths = [$this->prefix]; - } elseif (!str_starts_with($this->prefix, 'phar://') && !str_contains($this->pattern, '/**/')) { - if ($this->globBrace || !str_contains($this->pattern, '{')) { - $paths = glob($this->prefix.$this->pattern, \GLOB_NOSORT | $this->globBrace); - } elseif (!str_contains($this->pattern, '\\') || !preg_match('/\\\\[,{}]/', $this->pattern)) { - foreach ($this->expandGlob($this->pattern) as $p) { - $paths[] = glob($this->prefix.$p, \GLOB_NOSORT); - } - $paths = array_merge(...$paths); - } - } - - if (null !== $paths) { - natsort($paths); - foreach ($paths as $path) { - if ($this->excludedPrefixes) { - $normalizedPath = str_replace('\\', '/', $path); - do { - if (isset($this->excludedPrefixes[$dirPath = $normalizedPath])) { - continue 2; - } - } while ($prefix !== $dirPath && $dirPath !== $normalizedPath = \dirname($dirPath)); - } - - if (is_file($path)) { - yield $path => new \SplFileInfo($path); - } - if (!is_dir($path)) { - continue; - } - if ($this->forExclusion) { - yield $path => new \SplFileInfo($path); - continue; - } - if (!$this->recursive || isset($this->excludedPrefixes[str_replace('\\', '/', $path)])) { - continue; - } - $files = iterator_to_array(new \RecursiveIteratorIterator( - new \RecursiveCallbackFilterIterator( - new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS), - function (\SplFileInfo $file, $path) { - return !isset($this->excludedPrefixes[str_replace('\\', '/', $path)]) && '.' !== $file->getBasename()[0]; - } - ), - \RecursiveIteratorIterator::LEAVES_ONLY - )); - uksort($files, 'strnatcmp'); - - foreach ($files as $path => $info) { - if ($info->isFile()) { - yield $path => $info; - } - } - } - - return; - } - - if (!class_exists(Finder::class)) { - throw new \LogicException(sprintf('Extended glob pattern "%s" cannot be used as the Finder component is not installed.', $this->pattern)); - } - - if (is_file($prefix = $this->prefix)) { - $prefix = \dirname($prefix); - $pattern = basename($prefix).$this->pattern; - } else { - $pattern = $this->pattern; - } - - $finder = new Finder(); - $regex = Glob::toRegex($pattern); - if ($this->recursive) { - $regex = substr_replace($regex, '(/|$)', -2, 1); - } - - $prefixLen = \strlen($prefix); - foreach ($finder->followLinks()->sortByName()->in($prefix) as $path => $info) { - $normalizedPath = str_replace('\\', '/', $path); - if (!preg_match($regex, substr($normalizedPath, $prefixLen)) || !$info->isFile()) { - continue; - } - if ($this->excludedPrefixes) { - do { - if (isset($this->excludedPrefixes[$dirPath = $normalizedPath])) { - continue 2; - } - } while ($prefix !== $dirPath && $dirPath !== $normalizedPath = \dirname($dirPath)); - } - - yield $path => $info; - } - } - - private function computeHash(): string - { - $hash = hash_init('md5'); - - foreach ($this->getIterator() as $path => $info) { - hash_update($hash, $path."\n"); - } - - return hash_final($hash); - } - - private function expandGlob(string $pattern): array - { - $segments = preg_split('/\{([^{}]*+)\}/', $pattern, -1, \PREG_SPLIT_DELIM_CAPTURE); - $paths = [$segments[0]]; - $patterns = []; - - for ($i = 1; $i < \count($segments); $i += 2) { - $patterns = []; - - foreach (explode(',', $segments[$i]) as $s) { - foreach ($paths as $p) { - $patterns[] = $p.$s.$segments[1 + $i]; - } - } - - $paths = $patterns; - } - - $j = 0; - foreach ($patterns as $i => $p) { - if (str_contains($p, '{')) { - $p = $this->expandGlob($p); - array_splice($paths, $i + $j, 1, $p); - $j += \count($p) - 1; - } - } - - return $paths; - } -} diff --git a/lib/symfony/config/Resource/ReflectionClassResource.php b/lib/symfony/config/Resource/ReflectionClassResource.php deleted file mode 100644 index 06f1d766e..000000000 --- a/lib/symfony/config/Resource/ReflectionClassResource.php +++ /dev/null @@ -1,267 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Resource; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Messenger\Handler\MessageSubscriberInterface; -use Symfony\Contracts\Service\ServiceSubscriberInterface; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @final - */ -class ReflectionClassResource implements SelfCheckingResourceInterface -{ - private $files = []; - private $className; - private $classReflector; - private $excludedVendors = []; - private $hash; - - public function __construct(\ReflectionClass $classReflector, array $excludedVendors = []) - { - $this->className = $classReflector->name; - $this->classReflector = $classReflector; - $this->excludedVendors = $excludedVendors; - } - - /** - * {@inheritdoc} - */ - public function isFresh(int $timestamp): bool - { - if (null === $this->hash) { - $this->hash = $this->computeHash(); - $this->loadFiles($this->classReflector); - } - - foreach ($this->files as $file => $v) { - if (false === $filemtime = @filemtime($file)) { - return false; - } - - if ($filemtime > $timestamp) { - return $this->hash === $this->computeHash(); - } - } - - return true; - } - - public function __toString(): string - { - return 'reflection.'.$this->className; - } - - /** - * @internal - */ - public function __sleep(): array - { - if (null === $this->hash) { - $this->hash = $this->computeHash(); - $this->loadFiles($this->classReflector); - } - - return ['files', 'className', 'hash']; - } - - private function loadFiles(\ReflectionClass $class) - { - foreach ($class->getInterfaces() as $v) { - $this->loadFiles($v); - } - do { - $file = $class->getFileName(); - if (false !== $file && is_file($file)) { - foreach ($this->excludedVendors as $vendor) { - if (str_starts_with($file, $vendor) && false !== strpbrk(substr($file, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) { - $file = false; - break; - } - } - if ($file) { - $this->files[$file] = null; - } - } - foreach ($class->getTraits() as $v) { - $this->loadFiles($v); - } - } while ($class = $class->getParentClass()); - } - - private function computeHash(): string - { - if (null === $this->classReflector) { - try { - $this->classReflector = new \ReflectionClass($this->className); - } catch (\ReflectionException $e) { - // the class does not exist anymore - return false; - } - } - $hash = hash_init('md5'); - - foreach ($this->generateSignature($this->classReflector) as $info) { - hash_update($hash, $info); - } - - return hash_final($hash); - } - - private function generateSignature(\ReflectionClass $class): iterable - { - if (\PHP_VERSION_ID >= 80000) { - $attributes = []; - foreach ($class->getAttributes() as $a) { - $attributes[] = [$a->getName(), \PHP_VERSION_ID >= 80100 ? (string) $a : $a->getArguments()]; - } - yield print_r($attributes, true); - $attributes = []; - } - - yield $class->getDocComment(); - yield (int) $class->isFinal(); - yield (int) $class->isAbstract(); - - if ($class->isTrait()) { - yield print_r(class_uses($class->name), true); - } else { - yield print_r(class_parents($class->name), true); - yield print_r(class_implements($class->name), true); - yield print_r($class->getConstants(), true); - } - - if (!$class->isInterface()) { - $defaults = $class->getDefaultProperties(); - - foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PROTECTED) as $p) { - if (\PHP_VERSION_ID >= 80000) { - foreach ($p->getAttributes() as $a) { - $attributes[] = [$a->getName(), \PHP_VERSION_ID >= 80100 ? (string) $a : $a->getArguments()]; - } - yield print_r($attributes, true); - $attributes = []; - } - - yield $p->getDocComment(); - yield $p->isDefault() ? '<default>' : ''; - yield $p->isPublic() ? 'public' : 'protected'; - yield $p->isStatic() ? 'static' : ''; - yield '$'.$p->name; - yield print_r(isset($defaults[$p->name]) && !\is_object($defaults[$p->name]) ? $defaults[$p->name] : null, true); - } - } - - $defined = \Closure::bind(static function ($c) { return \defined($c); }, null, $class->name); - - foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $m) { - if (\PHP_VERSION_ID >= 80000) { - foreach ($m->getAttributes() as $a) { - $attributes[] = [$a->getName(), \PHP_VERSION_ID >= 80100 ? (string) $a : $a->getArguments()]; - } - yield print_r($attributes, true); - $attributes = []; - } - - $defaults = []; - $parametersWithUndefinedConstants = []; - foreach ($m->getParameters() as $p) { - if (\PHP_VERSION_ID >= 80000) { - foreach ($p->getAttributes() as $a) { - $attributes[] = [$a->getName(), \PHP_VERSION_ID >= 80100 ? (string) $a : $a->getArguments()]; - } - yield print_r($attributes, true); - $attributes = []; - } - - if (!$p->isDefaultValueAvailable()) { - $defaults[$p->name] = null; - - continue; - } - - if (\PHP_VERSION_ID >= 80100) { - $defaults[$p->name] = (string) $p; - - continue; - } - - if (!$p->isDefaultValueConstant() || $defined($p->getDefaultValueConstantName())) { - $defaults[$p->name] = $p->getDefaultValue(); - - continue; - } - - $defaults[$p->name] = $p->getDefaultValueConstantName(); - $parametersWithUndefinedConstants[$p->name] = true; - } - - if (!$parametersWithUndefinedConstants) { - yield preg_replace('/^ @@.*/m', '', $m); - } else { - $t = $m->getReturnType(); - $stack = [ - $m->getDocComment(), - $m->getName(), - $m->isAbstract(), - $m->isFinal(), - $m->isStatic(), - $m->isPublic(), - $m->isPrivate(), - $m->isProtected(), - $m->returnsReference(), - $t instanceof \ReflectionNamedType ? ((string) $t->allowsNull()).$t->getName() : (string) $t, - ]; - - foreach ($m->getParameters() as $p) { - if (!isset($parametersWithUndefinedConstants[$p->name])) { - $stack[] = (string) $p; - } else { - $t = $p->getType(); - $stack[] = $p->isOptional(); - $stack[] = $t instanceof \ReflectionNamedType ? ((string) $t->allowsNull()).$t->getName() : (string) $t; - $stack[] = $p->isPassedByReference(); - $stack[] = $p->isVariadic(); - $stack[] = $p->getName(); - } - } - - yield implode(',', $stack); - } - - yield print_r($defaults, true); - } - - if ($class->isAbstract() || $class->isInterface() || $class->isTrait()) { - return; - } - - if (interface_exists(EventSubscriberInterface::class, false) && $class->isSubclassOf(EventSubscriberInterface::class)) { - yield EventSubscriberInterface::class; - yield print_r($class->name::getSubscribedEvents(), true); - } - - if (interface_exists(MessageSubscriberInterface::class, false) && $class->isSubclassOf(MessageSubscriberInterface::class)) { - yield MessageSubscriberInterface::class; - foreach ($class->name::getHandledMessages() as $key => $value) { - yield $key.print_r($value, true); - } - } - - if (interface_exists(ServiceSubscriberInterface::class, false) && $class->isSubclassOf(ServiceSubscriberInterface::class)) { - yield ServiceSubscriberInterface::class; - yield print_r($class->name::getSubscribedServices(), true); - } - } -} diff --git a/lib/symfony/config/Resource/ResourceInterface.php b/lib/symfony/config/Resource/ResourceInterface.php deleted file mode 100644 index 9a0cd9a47..000000000 --- a/lib/symfony/config/Resource/ResourceInterface.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Resource; - -/** - * ResourceInterface is the interface that must be implemented by all Resource classes. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface ResourceInterface -{ - /** - * Returns a string representation of the Resource. - * - * This method is necessary to allow for resource de-duplication, for example by means - * of array_unique(). The string returned need not have a particular meaning, but has - * to be identical for different ResourceInterface instances referring to the same - * resource; and it should be unlikely to collide with that of other, unrelated - * resource instances. - */ - public function __toString(); -} diff --git a/lib/symfony/config/Resource/SelfCheckingResourceChecker.php b/lib/symfony/config/Resource/SelfCheckingResourceChecker.php deleted file mode 100644 index e1727b963..000000000 --- a/lib/symfony/config/Resource/SelfCheckingResourceChecker.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Resource; - -use Symfony\Component\Config\ResourceCheckerInterface; - -/** - * Resource checker for instances of SelfCheckingResourceInterface. - * - * As these resources perform the actual check themselves, we can provide - * this class as a standard way of validating them. - * - * @author Matthias Pigulla <mp@webfactory.de> - */ -class SelfCheckingResourceChecker implements ResourceCheckerInterface -{ - // Common shared cache, because this checker can be used in different - // situations. For example, when using the full stack framework, the router - // and the container have their own cache. But they may check the very same - // resources - private static $cache = []; - - public function supports(ResourceInterface $metadata) - { - return $metadata instanceof SelfCheckingResourceInterface; - } - - /** - * @param SelfCheckingResourceInterface $resource - */ - public function isFresh(ResourceInterface $resource, int $timestamp) - { - $key = "$resource:$timestamp"; - - return self::$cache[$key] ?? self::$cache[$key] = $resource->isFresh($timestamp); - } -} diff --git a/lib/symfony/config/Resource/SelfCheckingResourceInterface.php b/lib/symfony/config/Resource/SelfCheckingResourceInterface.php deleted file mode 100644 index 2c1a37846..000000000 --- a/lib/symfony/config/Resource/SelfCheckingResourceInterface.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Resource; - -/** - * Interface for Resources that can check for freshness autonomously, - * without special support from external services. - * - * @author Matthias Pigulla <mp@webfactory.de> - */ -interface SelfCheckingResourceInterface extends ResourceInterface -{ - /** - * Returns true if the resource has not been updated since the given timestamp. - * - * @param int $timestamp The last time the resource was loaded - * - * @return bool - */ - public function isFresh(int $timestamp); -} diff --git a/lib/symfony/config/ResourceCheckerConfigCache.php b/lib/symfony/config/ResourceCheckerConfigCache.php deleted file mode 100644 index ba0e180c5..000000000 --- a/lib/symfony/config/ResourceCheckerConfigCache.php +++ /dev/null @@ -1,187 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config; - -use Symfony\Component\Config\Resource\ResourceInterface; -use Symfony\Component\Filesystem\Exception\IOException; -use Symfony\Component\Filesystem\Filesystem; - -/** - * ResourceCheckerConfigCache uses instances of ResourceCheckerInterface - * to check whether cached data is still fresh. - * - * @author Matthias Pigulla <mp@webfactory.de> - */ -class ResourceCheckerConfigCache implements ConfigCacheInterface -{ - /** - * @var string - */ - private $file; - - /** - * @var iterable<mixed, ResourceCheckerInterface> - */ - private $resourceCheckers; - - /** - * @param string $file The absolute cache path - * @param iterable<mixed, ResourceCheckerInterface> $resourceCheckers The ResourceCheckers to use for the freshness check - */ - public function __construct(string $file, iterable $resourceCheckers = []) - { - $this->file = $file; - $this->resourceCheckers = $resourceCheckers; - } - - /** - * {@inheritdoc} - */ - public function getPath() - { - return $this->file; - } - - /** - * Checks if the cache is still fresh. - * - * This implementation will make a decision solely based on the ResourceCheckers - * passed in the constructor. - * - * The first ResourceChecker that supports a given resource is considered authoritative. - * Resources with no matching ResourceChecker will silently be ignored and considered fresh. - * - * @return bool - */ - public function isFresh() - { - if (!is_file($this->file)) { - return false; - } - - if ($this->resourceCheckers instanceof \Traversable && !$this->resourceCheckers instanceof \Countable) { - $this->resourceCheckers = iterator_to_array($this->resourceCheckers); - } - - if (!\count($this->resourceCheckers)) { - return true; // shortcut - if we don't have any checkers we don't need to bother with the meta file at all - } - - $metadata = $this->getMetaFile(); - - if (!is_file($metadata)) { - return false; - } - - $meta = $this->safelyUnserialize($metadata); - - if (false === $meta) { - return false; - } - - $time = filemtime($this->file); - - foreach ($meta as $resource) { - foreach ($this->resourceCheckers as $checker) { - if (!$checker->supports($resource)) { - continue; // next checker - } - if ($checker->isFresh($resource, $time)) { - break; // no need to further check this resource - } - - return false; // cache is stale - } - // no suitable checker found, ignore this resource - } - - return true; - } - - /** - * Writes cache. - * - * @param string $content The content to write in the cache - * @param ResourceInterface[] $metadata An array of metadata - * - * @throws \RuntimeException When cache file can't be written - */ - public function write(string $content, array $metadata = null) - { - $mode = 0666; - $umask = umask(); - $filesystem = new Filesystem(); - $filesystem->dumpFile($this->file, $content); - try { - $filesystem->chmod($this->file, $mode, $umask); - } catch (IOException $e) { - // discard chmod failure (some filesystem may not support it) - } - - if (null !== $metadata) { - $filesystem->dumpFile($this->getMetaFile(), serialize($metadata)); - try { - $filesystem->chmod($this->getMetaFile(), $mode, $umask); - } catch (IOException $e) { - // discard chmod failure (some filesystem may not support it) - } - } - - if (\function_exists('opcache_invalidate') && filter_var(\ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN)) { - @opcache_invalidate($this->file, true); - } - } - - /** - * Gets the meta file path. - */ - private function getMetaFile(): string - { - return $this->file.'.meta'; - } - - private function safelyUnserialize(string $file) - { - $meta = false; - $content = file_get_contents($file); - $signalingException = new \UnexpectedValueException(); - $prevUnserializeHandler = ini_set('unserialize_callback_func', self::class.'::handleUnserializeCallback'); - $prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$prevErrorHandler, $signalingException) { - if (__FILE__ === $file) { - throw $signalingException; - } - - return $prevErrorHandler ? $prevErrorHandler($type, $msg, $file, $line, $context) : false; - }); - - try { - $meta = unserialize($content); - } catch (\Throwable $e) { - if ($e !== $signalingException) { - throw $e; - } - } finally { - restore_error_handler(); - ini_set('unserialize_callback_func', $prevUnserializeHandler); - } - - return $meta; - } - - /** - * @internal - */ - public static function handleUnserializeCallback(string $class) - { - trigger_error('Class not found: '.$class); - } -} diff --git a/lib/symfony/config/ResourceCheckerConfigCacheFactory.php b/lib/symfony/config/ResourceCheckerConfigCacheFactory.php deleted file mode 100644 index 21b7433e8..000000000 --- a/lib/symfony/config/ResourceCheckerConfigCacheFactory.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config; - -/** - * A ConfigCacheFactory implementation that validates the - * cache with an arbitrary set of ResourceCheckers. - * - * @author Matthias Pigulla <mp@webfactory.de> - */ -class ResourceCheckerConfigCacheFactory implements ConfigCacheFactoryInterface -{ - private $resourceCheckers = []; - - /** - * @param iterable<int, ResourceCheckerInterface> $resourceCheckers - */ - public function __construct(iterable $resourceCheckers = []) - { - $this->resourceCheckers = $resourceCheckers; - } - - /** - * {@inheritdoc} - */ - public function cache(string $file, callable $callable) - { - $cache = new ResourceCheckerConfigCache($file, $this->resourceCheckers); - if (!$cache->isFresh()) { - $callable($cache); - } - - return $cache; - } -} diff --git a/lib/symfony/config/ResourceCheckerInterface.php b/lib/symfony/config/ResourceCheckerInterface.php deleted file mode 100644 index 6b1c6c5fb..000000000 --- a/lib/symfony/config/ResourceCheckerInterface.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config; - -use Symfony\Component\Config\Resource\ResourceInterface; - -/** - * Interface for ResourceCheckers. - * - * When a ResourceCheckerConfigCache instance is checked for freshness, all its associated - * metadata resources are passed to ResourceCheckers. The ResourceCheckers - * can then inspect the resources and decide whether the cache can be considered - * fresh or not. - * - * @author Matthias Pigulla <mp@webfactory.de> - * @author Benjamin Klotz <bk@webfactory.de> - */ -interface ResourceCheckerInterface -{ - /** - * Queries the ResourceChecker whether it can validate a given - * resource or not. - * - * @return bool - */ - public function supports(ResourceInterface $metadata); - - /** - * Validates the resource. - * - * @param int $timestamp The timestamp at which the cache associated with this resource was created - * - * @return bool - */ - public function isFresh(ResourceInterface $resource, int $timestamp); -} diff --git a/lib/symfony/config/Util/Exception/InvalidXmlException.php b/lib/symfony/config/Util/Exception/InvalidXmlException.php deleted file mode 100644 index 155571cec..000000000 --- a/lib/symfony/config/Util/Exception/InvalidXmlException.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Util\Exception; - -/** - * Exception class for when XML parsing with an XSD schema file path or a callable validator produces errors unrelated - * to the actual XML parsing. - * - * @author Ole Rößner <ole@roessner.it> - */ -class InvalidXmlException extends XmlParsingException -{ -} diff --git a/lib/symfony/config/Util/Exception/XmlParsingException.php b/lib/symfony/config/Util/Exception/XmlParsingException.php deleted file mode 100644 index 9bceed660..000000000 --- a/lib/symfony/config/Util/Exception/XmlParsingException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Util\Exception; - -/** - * Exception class for when XML cannot be parsed properly. - * - * @author Ole Rößner <ole@roessner.it> - */ -class XmlParsingException extends \InvalidArgumentException -{ -} diff --git a/lib/symfony/config/Util/XmlUtils.php b/lib/symfony/config/Util/XmlUtils.php deleted file mode 100644 index 8258a0627..000000000 --- a/lib/symfony/config/Util/XmlUtils.php +++ /dev/null @@ -1,289 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Util; - -use Symfony\Component\Config\Util\Exception\InvalidXmlException; -use Symfony\Component\Config\Util\Exception\XmlParsingException; - -/** - * XMLUtils is a bunch of utility methods to XML operations. - * - * This class contains static methods only and is not meant to be instantiated. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Martin Hasoň <martin.hason@gmail.com> - * @author Ole Rößner <ole@roessner.it> - */ -class XmlUtils -{ - /** - * This class should not be instantiated. - */ - private function __construct() - { - } - - /** - * Parses an XML string. - * - * @param string $content An XML string - * @param string|callable|null $schemaOrCallable An XSD schema file path, a callable, or null to disable validation - * - * @return \DOMDocument - * - * @throws XmlParsingException When parsing of XML file returns error - * @throws InvalidXmlException When parsing of XML with schema or callable produces any errors unrelated to the XML parsing itself - * @throws \RuntimeException When DOM extension is missing - */ - public static function parse(string $content, $schemaOrCallable = null) - { - if (!\extension_loaded('dom')) { - throw new \LogicException('Extension DOM is required.'); - } - - $internalErrors = libxml_use_internal_errors(true); - if (\LIBXML_VERSION < 20900) { - $disableEntities = libxml_disable_entity_loader(true); - } - libxml_clear_errors(); - - $dom = new \DOMDocument(); - $dom->validateOnParse = true; - if (!$dom->loadXML($content, \LIBXML_NONET | (\defined('LIBXML_COMPACT') ? \LIBXML_COMPACT : 0))) { - if (\LIBXML_VERSION < 20900) { - libxml_disable_entity_loader($disableEntities); - } - - throw new XmlParsingException(implode("\n", static::getXmlErrors($internalErrors))); - } - - $dom->normalizeDocument(); - - libxml_use_internal_errors($internalErrors); - if (\LIBXML_VERSION < 20900) { - libxml_disable_entity_loader($disableEntities); - } - - foreach ($dom->childNodes as $child) { - if (\XML_DOCUMENT_TYPE_NODE === $child->nodeType) { - throw new XmlParsingException('Document types are not allowed.'); - } - } - - if (null !== $schemaOrCallable) { - $internalErrors = libxml_use_internal_errors(true); - libxml_clear_errors(); - - $e = null; - if (\is_callable($schemaOrCallable)) { - try { - $valid = $schemaOrCallable($dom, $internalErrors); - } catch (\Exception $e) { - $valid = false; - } - } elseif (!\is_array($schemaOrCallable) && is_file((string) $schemaOrCallable)) { - $schemaSource = file_get_contents((string) $schemaOrCallable); - $valid = @$dom->schemaValidateSource($schemaSource); - } else { - libxml_use_internal_errors($internalErrors); - - throw new XmlParsingException('The schemaOrCallable argument has to be a valid path to XSD file or callable.'); - } - - if (!$valid) { - $messages = static::getXmlErrors($internalErrors); - if (empty($messages)) { - throw new InvalidXmlException('The XML is not valid.', 0, $e); - } - throw new XmlParsingException(implode("\n", $messages), 0, $e); - } - } - - libxml_clear_errors(); - libxml_use_internal_errors($internalErrors); - - return $dom; - } - - /** - * Loads an XML file. - * - * @param string $file An XML file path - * @param string|callable|null $schemaOrCallable An XSD schema file path, a callable, or null to disable validation - * - * @return \DOMDocument - * - * @throws \InvalidArgumentException When loading of XML file returns error - * @throws XmlParsingException When XML parsing returns any errors - * @throws \RuntimeException When DOM extension is missing - */ - public static function loadFile(string $file, $schemaOrCallable = null) - { - if (!is_file($file)) { - throw new \InvalidArgumentException(sprintf('Resource "%s" is not a file.', $file)); - } - - if (!is_readable($file)) { - throw new \InvalidArgumentException(sprintf('File "%s" is not readable.', $file)); - } - - $content = @file_get_contents($file); - - if ('' === trim($content)) { - throw new \InvalidArgumentException(sprintf('File "%s" does not contain valid XML, it is empty.', $file)); - } - - try { - return static::parse($content, $schemaOrCallable); - } catch (InvalidXmlException $e) { - throw new XmlParsingException(sprintf('The XML file "%s" is not valid.', $file), 0, $e->getPrevious()); - } - } - - /** - * Converts a \DOMElement object to a PHP array. - * - * The following rules applies during the conversion: - * - * * Each tag is converted to a key value or an array - * if there is more than one "value" - * - * * The content of a tag is set under a "value" key (<foo>bar</foo>) - * if the tag also has some nested tags - * - * * The attributes are converted to keys (<foo foo="bar"/>) - * - * * The nested-tags are converted to keys (<foo><foo>bar</foo></foo>) - * - * @param \DOMElement $element A \DOMElement instance - * @param bool $checkPrefix Check prefix in an element or an attribute name - * - * @return mixed - */ - public static function convertDomElementToArray(\DOMElement $element, bool $checkPrefix = true) - { - $prefix = (string) $element->prefix; - $empty = true; - $config = []; - foreach ($element->attributes as $name => $node) { - if ($checkPrefix && !\in_array((string) $node->prefix, ['', $prefix], true)) { - continue; - } - $config[$name] = static::phpize($node->value); - $empty = false; - } - - $nodeValue = false; - foreach ($element->childNodes as $node) { - if ($node instanceof \DOMText) { - if ('' !== trim($node->nodeValue)) { - $nodeValue = trim($node->nodeValue); - $empty = false; - } - } elseif ($checkPrefix && $prefix != (string) $node->prefix) { - continue; - } elseif (!$node instanceof \DOMComment) { - $value = static::convertDomElementToArray($node, $checkPrefix); - - $key = $node->localName; - if (isset($config[$key])) { - if (!\is_array($config[$key]) || !\is_int(key($config[$key]))) { - $config[$key] = [$config[$key]]; - } - $config[$key][] = $value; - } else { - $config[$key] = $value; - } - - $empty = false; - } - } - - if (false !== $nodeValue) { - $value = static::phpize($nodeValue); - if (\count($config)) { - $config['value'] = $value; - } else { - $config = $value; - } - } - - return !$empty ? $config : null; - } - - /** - * Converts an xml value to a PHP type. - * - * @param mixed $value - * - * @return mixed - */ - public static function phpize($value) - { - $value = (string) $value; - $lowercaseValue = strtolower($value); - - switch (true) { - case 'null' === $lowercaseValue: - return null; - case ctype_digit($value): - case isset($value[1]) && '-' === $value[0] && ctype_digit(substr($value, 1)): - $raw = $value; - $cast = (int) $value; - - return self::isOctal($value) ? \intval($value, 8) : (($raw === (string) $cast) ? $cast : $raw); - case 'true' === $lowercaseValue: - return true; - case 'false' === $lowercaseValue: - return false; - case isset($value[1]) && '0b' == $value[0].$value[1] && preg_match('/^0b[01]*$/', $value): - return bindec($value); - case is_numeric($value): - return '0x' === $value[0].$value[1] ? hexdec($value) : (float) $value; - case preg_match('/^0x[0-9a-f]++$/i', $value): - return hexdec($value); - case preg_match('/^[+-]?[0-9]+(\.[0-9]+)?$/', $value): - return (float) $value; - default: - return $value; - } - } - - protected static function getXmlErrors(bool $internalErrors) - { - $errors = []; - foreach (libxml_get_errors() as $error) { - $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)', - \LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR', - $error->code, - trim($error->message), - $error->file ?: 'n/a', - $error->line, - $error->column - ); - } - - libxml_clear_errors(); - libxml_use_internal_errors($internalErrors); - - return $errors; - } - - private static function isOctal(string $str): bool - { - if ('-' === $str[0]) { - $str = substr($str, 1); - } - - return $str === '0'.decoct(\intval($str, 8)); - } -} diff --git a/lib/symfony/config/composer.json b/lib/symfony/config/composer.json deleted file mode 100644 index b357ed317..000000000 --- a/lib/symfony/config/composer.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "name": "symfony/config", - "type": "library", - "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/filesystem": "^4.4|^5.0|^6.0", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-php80": "^1.16", - "symfony/polyfill-php81": "^1.22" - }, - "require-dev": { - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/finder": "^4.4|^5.0|^6.0", - "symfony/messenger": "^4.4|^5.0|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/yaml": "^4.4|^5.0|^6.0" - }, - "conflict": { - "symfony/finder": "<4.4" - }, - "suggest": { - "symfony/yaml": "To use the yaml reference dumper" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\Config\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/lib/symfony/console/Application.php b/lib/symfony/console/Application.php deleted file mode 100644 index 29951e9c1..000000000 --- a/lib/symfony/console/Application.php +++ /dev/null @@ -1,1301 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console; - -use Symfony\Component\Console\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 <fabien@symfony.com> - */ -class Application implements ResetInterface -{ - private $commands = []; - private $wantHelps = false; - private $runningCommand; - private $name; - private $version; - private $commandLoader; - private $catchExceptions = true; - private $autoExit = true; - private $definition; - private $helperSet; - private $dispatcher; - private $terminal; - private $defaultCommand; - private $singleCommand = false; - private $initialized; - private $signalRegistry; - private $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) - { - 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. - * - * @return HelperSet - */ - public function getHelperSet() - { - if (!$this->helperSet) { - $this->helperSet = $this->getDefaultHelperSet(); - } - - return $this->helperSet; - } - - public function setDefinition(InputDefinition $definition) - { - $this->definition = $definition; - } - - /** - * Gets the InputDefinition related to this Application. - * - * @return InputDefinition - */ - public function getDefinition() - { - if (!$this->definition) { - $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. - * - * @return string - */ - public function getHelp() - { - return $this->getLongVersion(); - } - - /** - * Gets whether to catch exceptions or not during commands execution. - * - * @return bool - */ - public function areExceptionsCaught() - { - 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. - * - * @return bool - */ - public function isAutoExitEnabled() - { - 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. - * - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * Sets the application name. - **/ - public function setName(string $name) - { - $this->name = $name; - } - - /** - * Gets the application version. - * - * @return string - */ - public function getVersion() - { - 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 <info>%s</info>', $this->getName(), $this->getVersion()); - } - - return $this->getName(); - } - - return 'Console Tool'; - } - - /** - * Registers a new command. - * - * @return Command - */ - public function register(string $name) - { - 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. - * - * @return bool - */ - public function has(string $name) - { - $this->init(); - - return isset($this->commands[$name]) || ($this->commandLoader && $this->commandLoader->has($name) && $this->add($this->commandLoader->get($name))); - } - - /** - * Returns an array of all unique namespaces used by currently registered commands. - * - * It does not return the global namespace which always exists. - * - * @return string[] - */ - public function getNamespaces() - { - $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. - * - * @return string - * - * @throws NamespaceNotFoundException When namespace is incorrect or ambiguous - */ - public function findNamespace(string $namespace) - { - $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) - { - $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('<info>%s</info>', 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('<comment>%s</comment>', OutputFormatter::escape(sprintf('In %s line %s:', basename($e->getFile()) ?: 'n/a', $e->getLine() ?: 'n/a'))); - } - $messages[] = $emptyLine = sprintf('<error>%s</error>', str_repeat(' ', $len)); - if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { - $messages[] = sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - Helper::width($title)))); - } - foreach ($lines as $line) { - $messages[] = sprintf('<error> %s %s</error>', 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('<comment>Exception trace:</comment>', 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 <info>%s:%s</info>', $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. - * - * @return string|null - */ - protected function getCommandName(InputInterface $input) - { - return $this->singleCommand ? $this->defaultCommand : $input->getFirstArgument(); - } - - /** - * Gets the default input definition. - * - * @return InputDefinition - */ - protected function getDefaultInputDefinition() - { - 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 <info>'.$this->defaultCommand.'</info> command'), - new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'), - new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'), - new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'), - new InputOption('--ansi', '', InputOption::VALUE_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() - { - return [new HelpCommand(), new ListCommand(), new CompleteCommand(), new DumpCompletionCommand()]; - } - - /** - * Gets the default helper set with the helpers that should always be available. - * - * @return HelperSet - */ - protected function getDefaultHelperSet() - { - 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. - * - * @return string - */ - public function extractNamespace(string $name, int $limit = null) - { - $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) - { - $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/lib/symfony/console/Attribute/AsCommand.php b/lib/symfony/console/Attribute/AsCommand.php deleted file mode 100644 index b337f548f..000000000 --- a/lib/symfony/console/Attribute/AsCommand.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\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/lib/symfony/console/CHANGELOG.md b/lib/symfony/console/CHANGELOG.md deleted file mode 100644 index 6662dd1eb..000000000 --- a/lib/symfony/console/CHANGELOG.md +++ /dev/null @@ -1,217 +0,0 @@ -CHANGELOG -========= - -5.4 ---- - - * Add `TesterTrait::assertCommandIsSuccessful()` to test command - * Deprecate `HelperSet::setCommand()` and `getCommand()` without replacement - -5.3 ---- - - * Add `GithubActionReporter` to render annotations in a Github Action - * Add `InputOption::VALUE_NEGATABLE` flag to handle `--foo`/`--no-foo` options - * Add the `Command::$defaultDescription` static property and the `description` attribute - on the `console.command` tag to allow the `list` command to instantiate commands lazily - * Add option `--short` to the `list` command - * Add support for bright colors - * Add `#[AsCommand]` attribute for declaring commands on PHP 8 - * Add `Helper::width()` and `Helper::length()` - * The `--ansi` and `--no-ansi` options now default to `null`. - -5.2.0 ------ - - * Added `SingleCommandApplication::setAutoExit()` to allow testing via `CommandTester` - * added support for multiline responses to questions through `Question::setMultiline()` - and `Question::isMultiline()` - * Added `SignalRegistry` class to stack signals handlers - * Added support for signals: - * Added `Application::getSignalRegistry()` and `Application::setSignalsToDispatchEvent()` methods - * Added `SignalableCommandInterface` interface - * Added `TableCellStyle` class to customize table cell - * Removed `php ` prefix invocation from help messages. - -5.1.0 ------ - - * `Command::setHidden()` is final since Symfony 5.1 - * Add `SingleCommandApplication` - * Add `Cursor` class - -5.0.0 ------ - - * removed support for finding hidden commands using an abbreviation, use the full name instead - * removed `TableStyle::setCrossingChar()` method in favor of `TableStyle::setDefaultCrossingChar()` - * removed `TableStyle::setHorizontalBorderChar()` method in favor of `TableStyle::setDefaultCrossingChars()` - * removed `TableStyle::getHorizontalBorderChar()` method in favor of `TableStyle::getBorderChars()` - * removed `TableStyle::setVerticalBorderChar()` method in favor of `TableStyle::setVerticalBorderChars()` - * removed `TableStyle::getVerticalBorderChar()` method in favor of `TableStyle::getBorderChars()` - * removed support for returning `null` from `Command::execute()`, return `0` instead - * `ProcessHelper::run()` accepts only `array|Symfony\Component\Process\Process` for its `command` argument - * `Application::setDispatcher` accepts only `Symfony\Contracts\EventDispatcher\EventDispatcherInterface` - for its `dispatcher` argument - * renamed `Application::renderException()` and `Application::doRenderException()` - to `renderThrowable()` and `doRenderThrowable()` respectively. - -4.4.0 ------ - - * deprecated finding hidden commands using an abbreviation, use the full name instead - * added `Question::setTrimmable` default to true to allow the answer to be trimmed - * added method `minSecondsBetweenRedraws()` and `maxSecondsBetweenRedraws()` on `ProgressBar` - * `Application` implements `ResetInterface` - * marked all dispatched event classes as `@final` - * added support for displaying table horizontally - * deprecated returning `null` from `Command::execute()`, return `0` instead - * Deprecated the `Application::renderException()` and `Application::doRenderException()` methods, - use `renderThrowable()` and `doRenderThrowable()` instead. - * added support for the `NO_COLOR` env var (https://no-color.org/) - -4.3.0 ------ - - * added support for hyperlinks - * added `ProgressBar::iterate()` method that simplify updating the progress bar when iterating - * added `Question::setAutocompleterCallback()` to provide a callback function - that dynamically generates suggestions as the user types - -4.2.0 ------ - - * allowed passing commands as `[$process, 'ENV_VAR' => 'value']` to - `ProcessHelper::run()` to pass environment variables - * deprecated passing a command as a string to `ProcessHelper::run()`, - pass it the command as an array of its arguments instead - * made the `ProcessHelper` class final - * added `WrappableOutputFormatterInterface::formatAndWrap()` (implemented in `OutputFormatter`) - * added `capture_stderr_separately` option to `CommandTester::execute()` - -4.1.0 ------ - - * added option to run suggested command if command is not found and only 1 alternative is available - * added option to modify console output and print multiple modifiable sections - * added support for iterable messages in output `write` and `writeln` methods - -4.0.0 ------ - - * `OutputFormatter` throws an exception when unknown options are used - * removed `QuestionHelper::setInputStream()/getInputStream()` - * removed `Application::getTerminalWidth()/getTerminalHeight()` and - `Application::setTerminalDimensions()/getTerminalDimensions()` - * removed `ConsoleExceptionEvent` - * removed `ConsoleEvents::EXCEPTION` - -3.4.0 ------ - - * 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/lib/symfony/console/CI/GithubActionReporter.php b/lib/symfony/console/CI/GithubActionReporter.php deleted file mode 100644 index a15c1ff18..000000000 --- a/lib/symfony/console/CI/GithubActionReporter.php +++ /dev/null @@ -1,99 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\CI; - -use Symfony\Component\Console\Output\OutputInterface; - -/** - * Utility class for Github actions. - * - * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> - */ -class GithubActionReporter -{ - private $output; - - /** - * @see https://github.com/actions/toolkit/blob/5e5e1b7aacba68a53836a34db4a288c3c1c1585b/packages/core/src/command.ts#L80-L85 - */ - private const ESCAPED_DATA = [ - '%' => '%25', - "\r" => '%0D', - "\n" => '%0A', - ]; - - /** - * @see https://github.com/actions/toolkit/blob/5e5e1b7aacba68a53836a34db4a288c3c1c1585b/packages/core/src/command.ts#L87-L94 - */ - private const ESCAPED_PROPERTIES = [ - '%' => '%25', - "\r" => '%0D', - "\n" => '%0A', - ':' => '%3A', - ',' => '%2C', - ]; - - public function __construct(OutputInterface $output) - { - $this->output = $output; - } - - public static function isGithubActionEnvironment(): bool - { - return false !== getenv('GITHUB_ACTIONS'); - } - - /** - * Output an error using the Github annotations format. - * - * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-an-error-message - */ - public function error(string $message, string $file = null, int $line = null, int $col = null): void - { - $this->log('error', $message, $file, $line, $col); - } - - /** - * Output a warning using the Github annotations format. - * - * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message - */ - public function warning(string $message, string $file = null, int $line = null, int $col = null): void - { - $this->log('warning', $message, $file, $line, $col); - } - - /** - * Output a debug log using the Github annotations format. - * - * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-a-debug-message - */ - public function debug(string $message, string $file = null, int $line = null, int $col = null): void - { - $this->log('debug', $message, $file, $line, $col); - } - - private function log(string $type, string $message, string $file = null, int $line = null, int $col = null): void - { - // Some values must be encoded. - $message = strtr($message, self::ESCAPED_DATA); - - if (!$file) { - // No file provided, output the message solely: - $this->output->writeln(sprintf('::%s::%s', $type, $message)); - - return; - } - - $this->output->writeln(sprintf('::%s file=%s,line=%s,col=%s::%s', $type, strtr($file, self::ESCAPED_PROPERTIES), strtr($line ?? 1, self::ESCAPED_PROPERTIES), strtr($col ?? 0, self::ESCAPED_PROPERTIES), $message)); - } -} diff --git a/lib/symfony/console/Color.php b/lib/symfony/console/Color.php deleted file mode 100644 index 22a4ce9ff..000000000 --- a/lib/symfony/console/Color.php +++ /dev/null @@ -1,180 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console; - -use Symfony\Component\Console\Exception\InvalidArgumentException; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -final class Color -{ - private const COLORS = [ - 'black' => 0, - 'red' => 1, - 'green' => 2, - 'yellow' => 3, - 'blue' => 4, - 'magenta' => 5, - 'cyan' => 6, - 'white' => 7, - 'default' => 9, - ]; - - private const BRIGHT_COLORS = [ - 'gray' => 0, - 'bright-red' => 1, - 'bright-green' => 2, - 'bright-yellow' => 3, - 'bright-blue' => 4, - 'bright-magenta' => 5, - 'bright-cyan' => 6, - 'bright-white' => 7, - ]; - - private const AVAILABLE_OPTIONS = [ - 'bold' => ['set' => 1, 'unset' => 22], - 'underscore' => ['set' => 4, 'unset' => 24], - 'blink' => ['set' => 5, 'unset' => 25], - 'reverse' => ['set' => 7, 'unset' => 27], - 'conceal' => ['set' => 8, 'unset' => 28], - ]; - - private $foreground; - private $background; - private $options = []; - - public function __construct(string $foreground = '', string $background = '', array $options = []) - { - $this->foreground = $this->parseColor($foreground); - $this->background = $this->parseColor($background, true); - - foreach ($options as $option) { - if (!isset(self::AVAILABLE_OPTIONS[$option])) { - throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s).', $option, implode(', ', array_keys(self::AVAILABLE_OPTIONS)))); - } - - $this->options[$option] = self::AVAILABLE_OPTIONS[$option]; - } - } - - public function apply(string $text): string - { - return $this->set().$text.$this->unset(); - } - - public function set(): string - { - $setCodes = []; - if ('' !== $this->foreground) { - $setCodes[] = $this->foreground; - } - if ('' !== $this->background) { - $setCodes[] = $this->background; - } - foreach ($this->options as $option) { - $setCodes[] = $option['set']; - } - if (0 === \count($setCodes)) { - return ''; - } - - return sprintf("\033[%sm", implode(';', $setCodes)); - } - - public function unset(): string - { - $unsetCodes = []; - if ('' !== $this->foreground) { - $unsetCodes[] = 39; - } - if ('' !== $this->background) { - $unsetCodes[] = 49; - } - foreach ($this->options as $option) { - $unsetCodes[] = $option['unset']; - } - if (0 === \count($unsetCodes)) { - return ''; - } - - return sprintf("\033[%sm", implode(';', $unsetCodes)); - } - - private function parseColor(string $color, bool $background = false): string - { - if ('' === $color) { - return ''; - } - - if ('#' === $color[0]) { - $color = substr($color, 1); - - if (3 === \strlen($color)) { - $color = $color[0].$color[0].$color[1].$color[1].$color[2].$color[2]; - } - - if (6 !== \strlen($color)) { - throw new InvalidArgumentException(sprintf('Invalid "%s" color.', $color)); - } - - return ($background ? '4' : '3').$this->convertHexColorToAnsi(hexdec($color)); - } - - if (isset(self::COLORS[$color])) { - return ($background ? '4' : '3').self::COLORS[$color]; - } - - if (isset(self::BRIGHT_COLORS[$color])) { - return ($background ? '10' : '9').self::BRIGHT_COLORS[$color]; - } - - throw new InvalidArgumentException(sprintf('Invalid "%s" color; expected one of (%s).', $color, implode(', ', array_merge(array_keys(self::COLORS), array_keys(self::BRIGHT_COLORS))))); - } - - private function convertHexColorToAnsi(int $color): string - { - $r = ($color >> 16) & 255; - $g = ($color >> 8) & 255; - $b = $color & 255; - - // see https://github.com/termstandard/colors/ for more information about true color support - if ('truecolor' !== getenv('COLORTERM')) { - return (string) $this->degradeHexColorToAnsi($r, $g, $b); - } - - return sprintf('8;2;%d;%d;%d', $r, $g, $b); - } - - private function degradeHexColorToAnsi(int $r, int $g, int $b): int - { - if (0 === round($this->getSaturation($r, $g, $b) / 50)) { - return 0; - } - - return (round($b / 255) << 2) | (round($g / 255) << 1) | round($r / 255); - } - - private function getSaturation(int $r, int $g, int $b): int - { - $r = $r / 255; - $g = $g / 255; - $b = $b / 255; - $v = max($r, $g, $b); - - if (0 === $diff = $v - min($r, $g, $b)) { - return 0; - } - - return (int) $diff * 100 / $v; - } -} diff --git a/lib/symfony/console/Command/Command.php b/lib/symfony/console/Command/Command.php deleted file mode 100644 index e0593e17a..000000000 --- a/lib/symfony/console/Command/Command.php +++ /dev/null @@ -1,710 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\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 <fabien@symfony.com> - */ -class Command -{ - // see https://tldp.org/LDP/abs/html/exitcodes.html - public const SUCCESS = 0; - public const FAILURE = 1; - public const INVALID = 2; - - /** - * @var string|null The default command name - */ - protected static $defaultName; - - /** - * @var string|null The default command description - */ - protected static $defaultDescription; - - private $application; - private $name; - private $processTitle; - private $aliases = []; - private $definition; - private $hidden = false; - private $help = ''; - private $description = ''; - private $fullDefinition; - private $ignoreValidationErrors = false; - private $code; - private $synopsis = []; - private $usages = []; - private $helperSet; - - /** - * @return string|null - */ - public static function getDefaultName() - { - $class = static::class; - - if (\PHP_VERSION_ID >= 80000 && $attribute = (new \ReflectionClass($class))->getAttributes(AsCommand::class)) { - return $attribute[0]->newInstance()->name; - } - - $r = new \ReflectionProperty($class, 'defaultName'); - - return $class === $r->class ? static::$defaultName : null; - } - - public static function getDefaultDescription(): ?string - { - $class = static::class; - - if (\PHP_VERSION_ID >= 80000 && $attribute = (new \ReflectionClass($class))->getAttributes(AsCommand::class)) { - return $attribute[0]->newInstance()->description; - } - - $r = new \ReflectionProperty($class, 'defaultDescription'); - - return $class === $r->class ? static::$defaultDescription : null; - } - - /** - * @param string|null $name The name of the command; passing null means it must be set in configure() - * - * @throws LogicException When the command name is empty - */ - public function __construct(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. - * - * @return HelperSet|null - */ - public function getHelperSet() - { - return $this->helperSet; - } - - /** - * Gets the application instance for this command. - * - * @return Application|null - */ - public function getApplication() - { - 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) - { - // 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('<comment>Running "cli_set_process_title" as an unprivileged user is not supported on MacOS.</comment>', OutputInterface::VERBOSITY_VERY_VERBOSE); - } else { - cli_set_process_title($this->processTitle); - } - } - } elseif (\function_exists('setproctitle')) { - setproctitle($this->processTitle); - } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) { - $output->writeln('<comment>Install the proctitle PECL to be able to change the process title.</comment>'); - } - } - - 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) - { - 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(); - } - } - } - - $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. - * - * @param array|InputDefinition $definition An array of argument and option instances or a definition instance - * - * @return $this - */ - public function setDefinition($definition) - { - if ($definition instanceof InputDefinition) { - $this->definition = $definition; - } else { - $this->definition->setDefinition($definition); - } - - $this->fullDefinition = null; - - return $this; - } - - /** - * Gets the InputDefinition attached to this Command. - * - * @return InputDefinition - */ - public function getDefinition() - { - 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. - * - * @return InputDefinition - */ - public function getNativeDefinition() - { - if (null === $this->definition) { - throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', static::class)); - } - - return $this->definition; - } - - /** - * Adds an argument. - * - * @param 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 = '', $default = null) - { - $this->definition->addArgument(new InputArgument($name, $mode, $description, $default)); - if (null !== $this->fullDefinition) { - $this->fullDefinition->addArgument(new InputArgument($name, $mode, $description, $default)); - } - - return $this; - } - - /** - * Adds an option. - * - * @param string|array|null $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts - * @param int|null $mode The option mode: One of the InputOption::VALUE_* constants - * @param mixed $default The default value (must be null for InputOption::VALUE_NONE) - * - * @throws InvalidArgumentException If option mode is invalid or incompatible - * - * @return $this - */ - public function addOption(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null) - { - $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) - { - $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) - { - $this->processTitle = $title; - - return $this; - } - - /** - * Returns the command name. - * - * @return string|null - */ - public function getName() - { - return $this->name; - } - - /** - * @param bool $hidden Whether or not the command should be hidden from the list of commands - * The default value will be true in Symfony 6.0 - * - * @return $this - * - * @final since Symfony 5.1 - */ - public function setHidden(bool $hidden /* = true */) - { - $this->hidden = $hidden; - - return $this; - } - - /** - * @return bool whether the command should be publicly shown or not - */ - public function isHidden() - { - return $this->hidden; - } - - /** - * Sets the description for the command. - * - * @return $this - */ - public function setDescription(string $description) - { - $this->description = $description; - - return $this; - } - - /** - * Returns the description for the command. - * - * @return string - */ - public function getDescription() - { - return $this->description; - } - - /** - * Sets the help for the command. - * - * @return $this - */ - public function setHelp(string $help) - { - $this->help = $help; - - return $this; - } - - /** - * Returns the help for the command. - * - * @return string - */ - public function getHelp() - { - return $this->help; - } - - /** - * Returns the processed help for the command replacing the %command.name% and - * %command.full_name% patterns with the real values dynamically. - * - * @return string - */ - public function getProcessedHelp() - { - $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) - { - $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. - * - * @return array - */ - public function getAliases() - { - 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 - * - * @return string - */ - public function getSynopsis(bool $short = false) - { - $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) - { - 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. - * - * @return array - */ - public function getUsages() - { - return $this->usages; - } - - /** - * Gets a helper instance by name. - * - * @return mixed - * - * @throws LogicException if no HelperSet is defined - * @throws InvalidArgumentException if the helper is not defined - */ - public function getHelper(string $name) - { - if (null === $this->helperSet) { - throw new LogicException(sprintf('Cannot retrieve helper "%s" because there is no HelperSet defined. Did you forget to add your command to the application or to set the application on the command using the setApplication() method? You can also set the HelperSet directly using the setHelperSet() method.', $name)); - } - - 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/lib/symfony/console/Command/CompleteCommand.php b/lib/symfony/console/Command/CompleteCommand.php deleted file mode 100644 index 11ada4e44..000000000 --- a/lib/symfony/console/Command/CompleteCommand.php +++ /dev/null @@ -1,205 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Command; - -use Symfony\Component\Console\Completion\CompletionInput; -use Symfony\Component\Console\Completion\CompletionSuggestions; -use Symfony\Component\Console\Completion\Output\BashCompletionOutput; -use Symfony\Component\Console\Completion\Output\CompletionOutputInterface; -use Symfony\Component\Console\Exception\CommandNotFoundException; -use Symfony\Component\Console\Exception\ExceptionInterface; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * Responsible for providing the values to the shell completion. - * - * @author Wouter de Jong <wouter@wouterj.nl> - */ -final class CompleteCommand extends Command -{ - protected static $defaultName = '|_complete'; - protected static $defaultDescription = 'Internal command to provide shell completion suggestions'; - - private $completionOutputs; - - private $isDebug = false; - - /** - * @param array<string, class-string<CompletionOutputInterface>> $completionOutputs A list of additional completion outputs, with shell name as key and FQCN as value - */ - public function __construct(array $completionOutputs = []) - { - // must be set before the parent constructor, as the property value is used in configure() - $this->completionOutputs = $completionOutputs + ['bash' => BashCompletionOutput::class]; - - parent::__construct(); - } - - protected function configure(): void - { - $this - ->addOption('shell', 's', InputOption::VALUE_REQUIRED, 'The shell type ("'.implode('", "', array_keys($this->completionOutputs)).'")') - ->addOption('input', 'i', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'An array of input tokens (e.g. COMP_WORDS or argv)') - ->addOption('current', 'c', InputOption::VALUE_REQUIRED, 'The index of the "input" array that the cursor is in (e.g. COMP_CWORD)') - ->addOption('symfony', 'S', InputOption::VALUE_REQUIRED, 'The version of the completion script') - ; - } - - protected function initialize(InputInterface $input, OutputInterface $output) - { - $this->isDebug = filter_var(getenv('SYMFONY_COMPLETION_DEBUG'), \FILTER_VALIDATE_BOOLEAN); - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - try { - // uncomment when a bugfix or BC break has been introduced in the shell completion scripts - // $version = $input->getOption('symfony'); - // if ($version && version_compare($version, 'x.y', '>=')) { - // $message = sprintf('Completion script version is not supported ("%s" given, ">=x.y" required).', $version); - // $this->log($message); - - // $output->writeln($message.' Install the Symfony completion script again by using the "completion" command.'); - - // return 126; - // } - - $shell = $input->getOption('shell'); - if (!$shell) { - throw new \RuntimeException('The "--shell" option must be set.'); - } - - if (!$completionOutput = $this->completionOutputs[$shell] ?? false) { - throw new \RuntimeException(sprintf('Shell completion is not supported for your shell: "%s" (supported: "%s").', $shell, implode('", "', array_keys($this->completionOutputs)))); - } - - $completionInput = $this->createCompletionInput($input); - $suggestions = new CompletionSuggestions(); - - $this->log([ - '', - '<comment>'.date('Y-m-d H:i:s').'</>', - '<info>Input:</> <comment>("|" indicates the cursor position)</>', - ' '.(string) $completionInput, - '<info>Command:</>', - ' '.(string) implode(' ', $_SERVER['argv']), - '<info>Messages:</>', - ]); - - $command = $this->findCommand($completionInput, $output); - if (null === $command) { - $this->log(' No command found, completing using the Application class.'); - - $this->getApplication()->complete($completionInput, $suggestions); - } elseif ( - $completionInput->mustSuggestArgumentValuesFor('command') - && $command->getName() !== $completionInput->getCompletionValue() - && !\in_array($completionInput->getCompletionValue(), $command->getAliases(), true) - ) { - $this->log(' No command found, completing using the Application class.'); - - // expand shortcut names ("cache:cl<TAB>") into their full name ("cache:clear") - $suggestions->suggestValues(array_filter(array_merge([$command->getName()], $command->getAliases()))); - } else { - $command->mergeApplicationDefinition(); - $completionInput->bind($command->getDefinition()); - - if (CompletionInput::TYPE_OPTION_NAME === $completionInput->getCompletionType()) { - $this->log(' Completing option names for the <comment>'.\get_class($command instanceof LazyCommand ? $command->getCommand() : $command).'</> command.'); - - $suggestions->suggestOptions($command->getDefinition()->getOptions()); - } else { - $this->log([ - ' Completing using the <comment>'.\get_class($command instanceof LazyCommand ? $command->getCommand() : $command).'</> class.', - ' Completing <comment>'.$completionInput->getCompletionType().'</> for <comment>'.$completionInput->getCompletionName().'</>', - ]); - if (null !== $compval = $completionInput->getCompletionValue()) { - $this->log(' Current value: <comment>'.$compval.'</>'); - } - - $command->complete($completionInput, $suggestions); - } - } - - /** @var CompletionOutputInterface $completionOutput */ - $completionOutput = new $completionOutput(); - - $this->log('<info>Suggestions:</>'); - if ($options = $suggestions->getOptionSuggestions()) { - $this->log(' --'.implode(' --', array_map(function ($o) { return $o->getName(); }, $options))); - } elseif ($values = $suggestions->getValueSuggestions()) { - $this->log(' '.implode(' ', $values)); - } else { - $this->log(' <comment>No suggestions were provided</>'); - } - - $completionOutput->write($suggestions, $output); - } catch (\Throwable $e) { - $this->log([ - '<error>Error!</error>', - (string) $e, - ]); - - if ($output->isDebug()) { - throw $e; - } - - return 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/lib/symfony/console/Command/DumpCompletionCommand.php b/lib/symfony/console/Command/DumpCompletionCommand.php deleted file mode 100644 index 518d606a0..000000000 --- a/lib/symfony/console/Command/DumpCompletionCommand.php +++ /dev/null @@ -1,139 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Command; - -use Symfony\Component\Console\Completion\CompletionInput; -use Symfony\Component\Console\Completion\CompletionSuggestions; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Process\Process; - -/** - * Dumps the completion script for the current shell. - * - * @author Wouter de Jong <wouter@wouterj.nl> - */ -final class DumpCompletionCommand extends Command -{ - protected static $defaultName = 'completion'; - protected static $defaultDescription = 'Dump the shell completion script'; - - public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void - { - if ($input->mustSuggestArgumentValuesFor('shell')) { - $suggestions->suggestValues($this->getSupportedShells()); - } - } - - protected function configure() - { - $fullCommand = $_SERVER['PHP_SELF']; - $commandName = basename($fullCommand); - $fullCommand = @realpath($fullCommand) ?: $fullCommand; - - $this - ->setHelp(<<<EOH -The <info>%command.name%</> command dumps the shell completion script required -to use shell autocompletion (currently only bash completion is supported). - -<comment>Static installation --------------------</> - -Dump the script to a global completion file and restart your shell: - - <info>%command.full_name% bash | sudo tee /etc/bash_completion.d/{$commandName}</> - -Or dump the script to a local file and source it: - - <info>%command.full_name% bash > completion.sh</> - - <comment># source the file whenever you use the project</> - <info>source completion.sh</> - - <comment># or add this line at the end of your "~/.bashrc" file:</> - <info>source /path/to/completion.sh</> - -<comment>Dynamic installation ---------------------</> - -Add this to the end of your shell configuration file (e.g. <info>"~/.bashrc"</>): - - <info>eval "$({$fullCommand} completion bash)"</> -EOH - ) - ->addArgument('shell', InputArgument::OPTIONAL, 'The shell type (e.g. "bash"), the value of the "$SHELL" env var will be used if this is not given') - ->addOption('debug', null, InputOption::VALUE_NONE, 'Tail the completion debug log') - ; - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $commandName = basename($_SERVER['argv'][0]); - - if ($input->getOption('debug')) { - $this->tailDebugLog($commandName, $output); - - return 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('<error>Detected shell "%s", which is not supported by Symfony shell completion (supported shells: "%s").</>', $shell, implode('", "', $supportedShells))); - } else { - $output->writeln(sprintf('<error>Shell not detected, Symfony shell completion only supports "%s").</>', implode('", "', $supportedShells))); - } - - return 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/lib/symfony/console/Command/HelpCommand.php b/lib/symfony/console/Command/HelpCommand.php deleted file mode 100644 index c66ef463e..000000000 --- a/lib/symfony/console/Command/HelpCommand.php +++ /dev/null @@ -1,101 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\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 <fabien@symfony.com> - */ -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 <info>%command.name%</info> command displays help for a given command: - - <info>%command.full_name% list</info> - -You can also output the help in other formats by using the <comment>--format</comment> option: - - <info>%command.full_name% --format=xml list</info> - -To display the list of available commands, please use the <info>list</info> command. -EOF - ) - ; - } - - public function setCommand(Command $command) - { - $this->command = $command; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - if (null === $this->command) { - $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'), - ]); - - $this->command = null; - - return 0; - } - - public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void - { - if ($input->mustSuggestArgumentValuesFor('command_name')) { - $descriptor = new ApplicationDescription($this->getApplication()); - $suggestions->suggestValues(array_keys($descriptor->getCommands())); - - return; - } - - if ($input->mustSuggestOptionValuesFor('format')) { - $helper = new DescriptorHelper(); - $suggestions->suggestValues($helper->getFormats()); - } - } -} diff --git a/lib/symfony/console/Command/LazyCommand.php b/lib/symfony/console/Command/LazyCommand.php deleted file mode 100644 index e576ad03f..000000000 --- a/lib/symfony/console/Command/LazyCommand.php +++ /dev/null @@ -1,218 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Command; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Completion\CompletionInput; -use Symfony\Component\Console\Completion\CompletionSuggestions; -use Symfony\Component\Console\Helper\HelperSet; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -final class LazyCommand extends Command -{ - private $command; - private $isEnabled; - - public function __construct(string $name, array $aliases, string $description, bool $isHidden, \Closure $commandFactory, ?bool $isEnabled = true) - { - $this->setName($name) - ->setAliases($aliases) - ->setHidden($isHidden) - ->setDescription($description); - - $this->command = $commandFactory; - $this->isEnabled = $isEnabled; - } - - public function ignoreValidationErrors(): void - { - $this->getCommand()->ignoreValidationErrors(); - } - - public function setApplication(Application $application = null): void - { - if ($this->command instanceof parent) { - $this->command->setApplication($application); - } - - parent::setApplication($application); - } - - public function setHelperSet(HelperSet $helperSet): void - { - if ($this->command instanceof parent) { - $this->command->setHelperSet($helperSet); - } - - parent::setHelperSet($helperSet); - } - - public function isEnabled(): bool - { - return $this->isEnabled ?? $this->getCommand()->isEnabled(); - } - - public function run(InputInterface $input, OutputInterface $output): int - { - return $this->getCommand()->run($input, $output); - } - - public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void - { - $this->getCommand()->complete($input, $suggestions); - } - - /** - * @return $this - */ - public function setCode(callable $code): self - { - $this->getCommand()->setCode($code); - - return $this; - } - - /** - * @internal - */ - public function mergeApplicationDefinition(bool $mergeArgs = true): void - { - $this->getCommand()->mergeApplicationDefinition($mergeArgs); - } - - /** - * @return $this - */ - public function setDefinition($definition): self - { - $this->getCommand()->setDefinition($definition); - - return $this; - } - - public function getDefinition(): InputDefinition - { - return $this->getCommand()->getDefinition(); - } - - public function getNativeDefinition(): InputDefinition - { - return $this->getCommand()->getNativeDefinition(); - } - - /** - * @return $this - */ - public function addArgument(string $name, int $mode = null, string $description = '', $default = null): self - { - $this->getCommand()->addArgument($name, $mode, $description, $default); - - return $this; - } - - /** - * @return $this - */ - public function addOption(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null): self - { - $this->getCommand()->addOption($name, $shortcut, $mode, $description, $default); - - return $this; - } - - /** - * @return $this - */ - public function setProcessTitle(string $title): self - { - $this->getCommand()->setProcessTitle($title); - - return $this; - } - - /** - * @return $this - */ - public function setHelp(string $help): self - { - $this->getCommand()->setHelp($help); - - return $this; - } - - public function getHelp(): string - { - return $this->getCommand()->getHelp(); - } - - public function getProcessedHelp(): string - { - return $this->getCommand()->getProcessedHelp(); - } - - public function getSynopsis(bool $short = false): string - { - return $this->getCommand()->getSynopsis($short); - } - - /** - * @return $this - */ - public function addUsage(string $usage): self - { - $this->getCommand()->addUsage($usage); - - return $this; - } - - public function getUsages(): array - { - return $this->getCommand()->getUsages(); - } - - /** - * @return mixed - */ - public function getHelper(string $name) - { - return $this->getCommand()->getHelper($name); - } - - public function getCommand(): parent - { - if (!$this->command instanceof \Closure) { - return $this->command; - } - - $command = $this->command = ($this->command)(); - $command->setApplication($this->getApplication()); - - if (null !== $this->getHelperSet()) { - $command->setHelperSet($this->getHelperSet()); - } - - $command->setName($this->getName()) - ->setAliases($this->getAliases()) - ->setHidden($this->isHidden()) - ->setDescription($this->getDescription()); - - // Will throw if the command is not correctly initialized. - $command->getDefinition(); - - return $command; - } -} diff --git a/lib/symfony/console/Command/ListCommand.php b/lib/symfony/console/Command/ListCommand.php deleted file mode 100644 index f04a4ef67..000000000 --- a/lib/symfony/console/Command/ListCommand.php +++ /dev/null @@ -1,95 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\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 <fabien@symfony.com> - */ -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 <info>%command.name%</info> command lists all commands: - - <info>%command.full_name%</info> - -You can also display the commands for a specific namespace: - - <info>%command.full_name% test</info> - -You can also output the information in other formats by using the <comment>--format</comment> option: - - <info>%command.full_name% --format=xml</info> - -It's also possible to get raw list of commands (useful for embedding command runner): - - <info>%command.full_name% --raw</info> -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $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/lib/symfony/console/Command/LockableTrait.php b/lib/symfony/console/Command/LockableTrait.php deleted file mode 100644 index b1856dca7..000000000 --- a/lib/symfony/console/Command/LockableTrait.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Command; - -use Symfony\Component\Console\Exception\LogicException; -use Symfony\Component\Lock\LockFactory; -use Symfony\Component\Lock\LockInterface; -use Symfony\Component\Lock\Store\FlockStore; -use Symfony\Component\Lock\Store\SemaphoreStore; - -/** - * Basic lock feature for commands. - * - * @author Geoffrey Brier <geoffrey.brier@gmail.com> - */ -trait LockableTrait -{ - /** @var LockInterface|null */ - private $lock; - - /** - * 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/lib/symfony/console/Command/SignalableCommandInterface.php b/lib/symfony/console/Command/SignalableCommandInterface.php deleted file mode 100644 index d439728b6..000000000 --- a/lib/symfony/console/Command/SignalableCommandInterface.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Command; - -/** - * Interface for command reacting to signal. - * - * @author Grégoire Pineau <lyrixx@lyrix.info> - */ -interface SignalableCommandInterface -{ - /** - * Returns the list of signals to subscribe. - */ - public function getSubscribedSignals(): array; - - /** - * The method will be called when the application is signaled. - */ - public function handleSignal(int $signal): void; -} diff --git a/lib/symfony/console/CommandLoader/CommandLoaderInterface.php b/lib/symfony/console/CommandLoader/CommandLoaderInterface.php deleted file mode 100644 index 0adaf886f..000000000 --- a/lib/symfony/console/CommandLoader/CommandLoaderInterface.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\CommandLoader; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Exception\CommandNotFoundException; - -/** - * @author Robin Chalas <robin.chalas@gmail.com> - */ -interface CommandLoaderInterface -{ - /** - * Loads a command. - * - * @return Command - * - * @throws CommandNotFoundException - */ - public function get(string $name); - - /** - * Checks if a command exists. - * - * @return bool - */ - public function has(string $name); - - /** - * @return string[] - */ - public function getNames(); -} diff --git a/lib/symfony/console/CommandLoader/ContainerCommandLoader.php b/lib/symfony/console/CommandLoader/ContainerCommandLoader.php deleted file mode 100644 index ddccb3d45..000000000 --- a/lib/symfony/console/CommandLoader/ContainerCommandLoader.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\CommandLoader; - -use Psr\Container\ContainerInterface; -use Symfony\Component\Console\Exception\CommandNotFoundException; - -/** - * Loads commands from a PSR-11 container. - * - * @author Robin Chalas <robin.chalas@gmail.com> - */ -class ContainerCommandLoader implements CommandLoaderInterface -{ - private $container; - private $commandMap; - - /** - * @param 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) - { - 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) - { - return isset($this->commandMap[$name]) && $this->container->has($this->commandMap[$name]); - } - - /** - * {@inheritdoc} - */ - public function getNames() - { - return array_keys($this->commandMap); - } -} diff --git a/lib/symfony/console/CommandLoader/FactoryCommandLoader.php b/lib/symfony/console/CommandLoader/FactoryCommandLoader.php deleted file mode 100644 index 7e2db3464..000000000 --- a/lib/symfony/console/CommandLoader/FactoryCommandLoader.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\CommandLoader; - -use Symfony\Component\Console\Exception\CommandNotFoundException; - -/** - * A simple command loader using factories to instantiate commands lazily. - * - * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> - */ -class FactoryCommandLoader implements CommandLoaderInterface -{ - private $factories; - - /** - * @param callable[] $factories Indexed by command names - */ - public function __construct(array $factories) - { - $this->factories = $factories; - } - - /** - * {@inheritdoc} - */ - public function has(string $name) - { - return isset($this->factories[$name]); - } - - /** - * {@inheritdoc} - */ - public function get(string $name) - { - if (!isset($this->factories[$name])) { - throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name)); - } - - $factory = $this->factories[$name]; - - return $factory(); - } - - /** - * {@inheritdoc} - */ - public function getNames() - { - return array_keys($this->factories); - } -} diff --git a/lib/symfony/console/Completion/CompletionInput.php b/lib/symfony/console/Completion/CompletionInput.php deleted file mode 100644 index 368b94507..000000000 --- a/lib/symfony/console/Completion/CompletionInput.php +++ /dev/null @@ -1,249 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Completion; - -use Symfony\Component\Console\Exception\RuntimeException; -use Symfony\Component\Console\Input\ArgvInput; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; - -/** - * An input specialized for shell completion. - * - * This input allows unfinished option names or values and exposes what kind of - * completion is expected. - * - * @author Wouter de Jong <wouter@wouterj.nl> - */ -final class CompletionInput extends ArgvInput -{ - public const TYPE_ARGUMENT_VALUE = 'argument_value'; - public const TYPE_OPTION_VALUE = 'option_value'; - public const TYPE_OPTION_NAME = 'option_name'; - public const TYPE_NONE = 'none'; - - private $tokens; - private $currentIndex; - private $completionType; - private $completionName = null; - private $completionValue = ''; - - /** - * Converts a terminal string into tokens. - * - * This is required for shell completions without COMP_WORDS support. - */ - public static function fromString(string $inputStr, int $currentIndex): self - { - preg_match_all('/(?<=^|\s)([\'"]?)(.+?)(?<!\\\\)\1(?=$|\s)/', $inputStr, $tokens); - - return self::fromTokens($tokens[0], $currentIndex); - } - - /** - * Create an input based on an COMP_WORDS token list. - * - * @param string[] $tokens the set of split tokens (e.g. COMP_WORDS or argv) - * @param $currentIndex the index of the cursor (e.g. COMP_CWORD) - */ - public static function fromTokens(array $tokens, int $currentIndex): self - { - $input = new self($tokens); - $input->tokens = $tokens; - $input->currentIndex = $currentIndex; - - return $input; - } - - /** - * {@inheritdoc} - */ - public function bind(InputDefinition $definition): void - { - parent::bind($definition); - - $relevantToken = $this->getRelevantToken(); - if ('-' === $relevantToken[0]) { - // the current token is an input option: complete either option name or option value - [$optionToken, $optionValue] = explode('=', $relevantToken, 2) + ['', '']; - - $option = $this->getOptionFromToken($optionToken); - if (null === $option && !$this->isCursorFree()) { - $this->completionType = self::TYPE_OPTION_NAME; - $this->completionValue = $relevantToken; - - return; - } - - if (null !== $option && $option->acceptValue()) { - $this->completionType = self::TYPE_OPTION_VALUE; - $this->completionName = $option->getName(); - $this->completionValue = $optionValue ?: (!str_starts_with($optionToken, '--') ? substr($optionToken, 2) : ''); - - return; - } - } - - $previousToken = $this->tokens[$this->currentIndex - 1]; - if ('-' === $previousToken[0] && '' !== trim($previousToken, '-')) { - // check if previous option accepted a value - $previousOption = $this->getOptionFromToken($previousToken); - if (null !== $previousOption && $previousOption->acceptValue()) { - $this->completionType = self::TYPE_OPTION_VALUE; - $this->completionName = $previousOption->getName(); - $this->completionValue = $relevantToken; - - return; - } - } - - // complete argument value - $this->completionType = self::TYPE_ARGUMENT_VALUE; - - foreach ($this->definition->getArguments() as $argumentName => $argument) { - if (!isset($this->arguments[$argumentName])) { - break; - } - - $argumentValue = $this->arguments[$argumentName]; - $this->completionName = $argumentName; - if (\is_array($argumentValue)) { - $this->completionValue = $argumentValue ? $argumentValue[array_key_last($argumentValue)] : null; - } else { - $this->completionValue = $argumentValue; - } - } - - if ($this->currentIndex >= \count($this->tokens)) { - if (!isset($this->arguments[$argumentName]) || $this->definition->getArgument($argumentName)->isArray()) { - $this->completionName = $argumentName; - $this->completionValue = ''; - } else { - // we've reached the end - $this->completionType = self::TYPE_NONE; - $this->completionName = null; - $this->completionValue = ''; - } - } - } - - /** - * Returns the type of completion required. - * - * TYPE_ARGUMENT_VALUE when completing the value of an input argument - * TYPE_OPTION_VALUE when completing the value of an input option - * TYPE_OPTION_NAME when completing the name of an input option - * TYPE_NONE when nothing should be completed - * - * @return string One of self::TYPE_* constants. TYPE_OPTION_NAME and TYPE_NONE are already implemented by the Console component - */ - public function getCompletionType(): string - { - return $this->completionType; - } - - /** - * The name of the input option or argument when completing a value. - * - * @return string|null returns null when completing an option name - */ - public function getCompletionName(): ?string - { - return $this->completionName; - } - - /** - * The value already typed by the user (or empty string). - */ - public function getCompletionValue(): string - { - return $this->completionValue; - } - - public function mustSuggestOptionValuesFor(string $optionName): bool - { - return self::TYPE_OPTION_VALUE === $this->getCompletionType() && $optionName === $this->getCompletionName(); - } - - public function mustSuggestArgumentValuesFor(string $argumentName): bool - { - return self::TYPE_ARGUMENT_VALUE === $this->getCompletionType() && $argumentName === $this->getCompletionName(); - } - - protected function parseToken(string $token, bool $parseOptions): bool - { - try { - return parent::parseToken($token, $parseOptions); - } catch (RuntimeException $e) { - // suppress errors, completed input is almost never valid - } - - return $parseOptions; - } - - private function getOptionFromToken(string $optionToken): ?InputOption - { - $optionName = ltrim($optionToken, '-'); - if (!$optionName) { - return null; - } - - if ('-' === ($optionToken[1] ?? ' ')) { - // long option name - return $this->definition->hasOption($optionName) ? $this->definition->getOption($optionName) : null; - } - - // short option name - return $this->definition->hasShortcut($optionName[0]) ? $this->definition->getOptionForShortcut($optionName[0]) : null; - } - - /** - * The token of the cursor, or the last token if the cursor is at the end of the input. - */ - private function getRelevantToken(): string - { - return $this->tokens[$this->isCursorFree() ? $this->currentIndex - 1 : $this->currentIndex]; - } - - /** - * Whether the cursor is "free" (i.e. at the end of the input preceded by a space). - */ - private function isCursorFree(): bool - { - $nrOfTokens = \count($this->tokens); - if ($this->currentIndex > $nrOfTokens) { - throw new \LogicException('Current index is invalid, it must be the number of input tokens or one more.'); - } - - return $this->currentIndex >= $nrOfTokens; - } - - public function __toString() - { - $str = ''; - foreach ($this->tokens as $i => $token) { - $str .= $token; - - if ($this->currentIndex === $i) { - $str .= '|'; - } - - $str .= ' '; - } - - if ($this->currentIndex > $i) { - $str .= '|'; - } - - return rtrim($str); - } -} diff --git a/lib/symfony/console/Completion/CompletionSuggestions.php b/lib/symfony/console/Completion/CompletionSuggestions.php deleted file mode 100644 index d8905e5ee..000000000 --- a/lib/symfony/console/Completion/CompletionSuggestions.php +++ /dev/null @@ -1,99 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Completion; - -use Symfony\Component\Console\Input\InputOption; - -/** - * Stores all completion suggestions for the current input. - * - * @author Wouter de Jong <wouter@wouterj.nl> - */ -final class CompletionSuggestions -{ - private $valueSuggestions = []; - private $optionSuggestions = []; - - /** - * Add a suggested value for an input option or argument. - * - * @param string|Suggestion $value - * - * @return $this - */ - public function suggestValue($value): self - { - $this->valueSuggestions[] = !$value instanceof Suggestion ? new Suggestion($value) : $value; - - return $this; - } - - /** - * Add multiple suggested values at once for an input option or argument. - * - * @param list<string|Suggestion> $values - * - * @return $this - */ - public function suggestValues(array $values): self - { - foreach ($values as $value) { - $this->suggestValue($value); - } - - return $this; - } - - /** - * Add a suggestion for an input option name. - * - * @return $this - */ - public function suggestOption(InputOption $option): self - { - $this->optionSuggestions[] = $option; - - return $this; - } - - /** - * Add multiple suggestions for input option names at once. - * - * @param InputOption[] $options - * - * @return $this - */ - public function suggestOptions(array $options): self - { - foreach ($options as $option) { - $this->suggestOption($option); - } - - return $this; - } - - /** - * @return InputOption[] - */ - public function getOptionSuggestions(): array - { - return $this->optionSuggestions; - } - - /** - * @return Suggestion[] - */ - public function getValueSuggestions(): array - { - return $this->valueSuggestions; - } -} diff --git a/lib/symfony/console/Completion/Output/BashCompletionOutput.php b/lib/symfony/console/Completion/Output/BashCompletionOutput.php deleted file mode 100644 index c6f76eb8f..000000000 --- a/lib/symfony/console/Completion/Output/BashCompletionOutput.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Completion\Output; - -use Symfony\Component\Console\Completion\CompletionSuggestions; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * @author Wouter de Jong <wouter@wouterj.nl> - */ -class BashCompletionOutput implements CompletionOutputInterface -{ - public function write(CompletionSuggestions $suggestions, OutputInterface $output): void - { - $values = $suggestions->getValueSuggestions(); - foreach ($suggestions->getOptionSuggestions() as $option) { - $values[] = '--'.$option->getName(); - if ($option->isNegatable()) { - $values[] = '--no-'.$option->getName(); - } - } - $output->writeln(implode("\n", $values)); - } -} diff --git a/lib/symfony/console/Completion/Output/CompletionOutputInterface.php b/lib/symfony/console/Completion/Output/CompletionOutputInterface.php deleted file mode 100644 index 659e59655..000000000 --- a/lib/symfony/console/Completion/Output/CompletionOutputInterface.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Completion\Output; - -use Symfony\Component\Console\Completion\CompletionSuggestions; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * Transforms the {@see CompletionSuggestions} object into output readable by the shell completion. - * - * @author Wouter de Jong <wouter@wouterj.nl> - */ -interface CompletionOutputInterface -{ - public function write(CompletionSuggestions $suggestions, OutputInterface $output): void; -} diff --git a/lib/symfony/console/Completion/Suggestion.php b/lib/symfony/console/Completion/Suggestion.php deleted file mode 100644 index 6c7bc4dc4..000000000 --- a/lib/symfony/console/Completion/Suggestion.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Completion; - -/** - * Represents a single suggested value. - * - * @author Wouter de Jong <wouter@wouterj.nl> - */ -class Suggestion -{ - private $value; - - public function __construct(string $value) - { - $this->value = $value; - } - - public function getValue(): string - { - return $this->value; - } - - public function __toString(): string - { - return $this->getValue(); - } -} diff --git a/lib/symfony/console/ConsoleEvents.php b/lib/symfony/console/ConsoleEvents.php deleted file mode 100644 index 6ae8f32b8..000000000 --- a/lib/symfony/console/ConsoleEvents.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\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 <git@flevour.net> - */ -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/lib/symfony/console/Cursor.php b/lib/symfony/console/Cursor.php deleted file mode 100644 index 0c4dafb6c..000000000 --- a/lib/symfony/console/Cursor.php +++ /dev/null @@ -1,207 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console; - -use Symfony\Component\Console\Output\OutputInterface; - -/** - * @author Pierre du Plessis <pdples@gmail.com> - */ -final class Cursor -{ - private $output; - private $input; - - /** - * @param resource|null $input - */ - public function __construct(OutputInterface $output, $input = null) - { - $this->output = $output; - $this->input = $input ?? (\defined('STDIN') ? \STDIN : fopen('php://input', 'r+')); - } - - /** - * @return $this - */ - public function moveUp(int $lines = 1): self - { - $this->output->write(sprintf("\x1b[%dA", $lines)); - - return $this; - } - - /** - * @return $this - */ - public function moveDown(int $lines = 1): self - { - $this->output->write(sprintf("\x1b[%dB", $lines)); - - return $this; - } - - /** - * @return $this - */ - public function moveRight(int $columns = 1): self - { - $this->output->write(sprintf("\x1b[%dC", $columns)); - - return $this; - } - - /** - * @return $this - */ - public function moveLeft(int $columns = 1): self - { - $this->output->write(sprintf("\x1b[%dD", $columns)); - - return $this; - } - - /** - * @return $this - */ - public function moveToColumn(int $column): self - { - $this->output->write(sprintf("\x1b[%dG", $column)); - - return $this; - } - - /** - * @return $this - */ - public function moveToPosition(int $column, int $row): self - { - $this->output->write(sprintf("\x1b[%d;%dH", $row + 1, $column)); - - return $this; - } - - /** - * @return $this - */ - public function savePosition(): self - { - $this->output->write("\x1b7"); - - return $this; - } - - /** - * @return $this - */ - public function restorePosition(): self - { - $this->output->write("\x1b8"); - - return $this; - } - - /** - * @return $this - */ - public function hide(): self - { - $this->output->write("\x1b[?25l"); - - return $this; - } - - /** - * @return $this - */ - public function show(): self - { - $this->output->write("\x1b[?25h\x1b[?0c"); - - return $this; - } - - /** - * Clears all the output from the current line. - * - * @return $this - */ - public function clearLine(): self - { - $this->output->write("\x1b[2K"); - - return $this; - } - - /** - * Clears all the output from the current line after the current position. - */ - public function clearLineAfter(): self - { - $this->output->write("\x1b[K"); - - return $this; - } - - /** - * Clears all the output from the cursors' current position to the end of the screen. - * - * @return $this - */ - public function clearOutput(): self - { - $this->output->write("\x1b[0J"); - - return $this; - } - - /** - * Clears the entire screen. - * - * @return $this - */ - public function clearScreen(): self - { - $this->output->write("\x1b[2J"); - - return $this; - } - - /** - * Returns the current cursor position as x,y coordinates. - */ - public function getCurrentPosition(): array - { - static $isTtySupported; - - if (null === $isTtySupported && \function_exists('proc_open')) { - $isTtySupported = (bool) @proc_open('echo 1 >/dev/null', [['file', '/dev/tty', 'r'], ['file', '/dev/tty', 'w'], ['file', '/dev/tty', 'w']], $pipes); - } - - if (!$isTtySupported) { - return [1, 1]; - } - - $sttyMode = shell_exec('stty -g'); - shell_exec('stty -icanon -echo'); - - @fwrite($this->input, "\033[6n"); - - $code = trim(fread($this->input, 1024)); - - shell_exec(sprintf('stty %s', $sttyMode)); - - sscanf($code, "\033[%d;%dR", $row, $col); - - return [$col, $row]; - } -} diff --git a/lib/symfony/console/DependencyInjection/AddConsoleCommandPass.php b/lib/symfony/console/DependencyInjection/AddConsoleCommandPass.php deleted file mode 100644 index 1fbb212e7..000000000 --- a/lib/symfony/console/DependencyInjection/AddConsoleCommandPass.php +++ /dev/null @@ -1,148 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\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 <lyrixx@lyrixx.info> - */ -class AddConsoleCommandPass implements CompilerPassInterface -{ - private $commandLoaderServiceId; - private $commandTag; - private $noPreloadTag; - private $privateTagName; - - public function __construct(string $commandLoaderServiceId = 'console.command_loader', string $commandTag = 'console.command', string $noPreloadTag = 'container.no_preload', string $privateTagName = 'container.private') - { - if (0 < \func_num_args()) { - trigger_deprecation('symfony/console', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->commandLoaderServiceId = $commandLoaderServiceId; - $this->commandTag = $commandTag; - $this->noPreloadTag = $noPreloadTag; - $this->privateTagName = $privateTagName; - } - - public function process(ContainerBuilder $container) - { - $commandServices = $container->findTaggedServiceIds($this->commandTag, true); - $lazyCommandMap = []; - $lazyCommandRefs = []; - $serviceIds = []; - - foreach ($commandServices as $id => $tags) { - $definition = $container->getDefinition($id); - $definition->addTag($this->noPreloadTag); - $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, $this->commandTag, 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($this->privateTagName)) { - $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, $this->commandTag, Command::class)); - } - $description = str_replace('%', '%%', $class::getDefaultDescription() ?? ''); - } - - if ($description) { - $definition->addMethodCall('setDescription', [$description]); - - $container->register('.'.$id.'.lazy', LazyCommand::class) - ->setArguments([$commandName, $aliases, $description, $isHidden, new ServiceClosureArgument($lazyCommandRefs[$id])]); - - $lazyCommandRefs[$id] = new Reference('.'.$id.'.lazy'); - } - } - - $container - ->register($this->commandLoaderServiceId, ContainerCommandLoader::class) - ->setPublic(true) - ->addTag($this->noPreloadTag) - ->setArguments([ServiceLocatorTagPass::register($container, $lazyCommandRefs), $lazyCommandMap]); - - $container->setParameter('console.command.ids', $serviceIds); - } -} diff --git a/lib/symfony/console/Descriptor/ApplicationDescription.php b/lib/symfony/console/Descriptor/ApplicationDescription.php deleted file mode 100644 index 2a3acc99b..000000000 --- a/lib/symfony/console/Descriptor/ApplicationDescription.php +++ /dev/null @@ -1,143 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Descriptor; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Exception\CommandNotFoundException; - -/** - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class ApplicationDescription -{ - public const GLOBAL_NAMESPACE = '_global'; - - private $application; - private $namespace; - private $showHidden; - - /** - * @var array - */ - private $namespaces; - - /** - * @var array<string, Command> - */ - private $commands; - - /** - * @var array<string, Command> - */ - private $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 (null === $this->namespaces) { - $this->inspectApplication(); - } - - return $this->namespaces; - } - - /** - * @return Command[] - */ - public function getCommands(): array - { - if (null === $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/lib/symfony/console/Descriptor/Descriptor.php b/lib/symfony/console/Descriptor/Descriptor.php deleted file mode 100644 index a3648301f..000000000 --- a/lib/symfony/console/Descriptor/Descriptor.php +++ /dev/null @@ -1,94 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\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 <jeanfrancois.simon@sensiolabs.com> - * - * @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/lib/symfony/console/Descriptor/DescriptorInterface.php b/lib/symfony/console/Descriptor/DescriptorInterface.php deleted file mode 100644 index ebea30367..000000000 --- a/lib/symfony/console/Descriptor/DescriptorInterface.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Descriptor; - -use Symfony\Component\Console\Output\OutputInterface; - -/** - * Descriptor interface. - * - * @author Jean-François Simon <contact@jfsimon.fr> - */ -interface DescriptorInterface -{ - public function describe(OutputInterface $output, object $object, array $options = []); -} diff --git a/lib/symfony/console/Descriptor/JsonDescriptor.php b/lib/symfony/console/Descriptor/JsonDescriptor.php deleted file mode 100644 index 1d2865941..000000000 --- a/lib/symfony/console/Descriptor/JsonDescriptor.php +++ /dev/null @@ -1,181 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\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 <contact@jfsimon.fr> - * - * @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/lib/symfony/console/Descriptor/MarkdownDescriptor.php b/lib/symfony/console/Descriptor/MarkdownDescriptor.php deleted file mode 100644 index 21ceca6c2..000000000 --- a/lib/symfony/console/Descriptor/MarkdownDescriptor.php +++ /dev/null @@ -1,206 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\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 <contact@jfsimon.fr> - * - * @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() ?: '<none>')."`\n\n" - .($argument->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $argument->getDescription())."\n\n" : '') - .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n" - .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n" - .'* 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/lib/symfony/console/Descriptor/TextDescriptor.php b/lib/symfony/console/Descriptor/TextDescriptor.php deleted file mode 100644 index fbb140ae7..000000000 --- a/lib/symfony/console/Descriptor/TextDescriptor.php +++ /dev/null @@ -1,341 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\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 <contact@jfsimon.fr> - * - * @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('<comment> [default: %s]</comment>', $this->formatDefaultValue($argument->getDefault())); - } else { - $default = ''; - } - - $totalWidth = $options['total_width'] ?? Helper::width($argument->getName()); - $spacingWidth = $totalWidth - \strlen($argument->getName()); - - $this->writeText(sprintf(' <info>%s</info> %s%s%s', - $argument->getName(), - str_repeat(' ', $spacingWidth), - // + 4 = 2 spaces before <info>, 2 spaces after </info> - 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('<comment> [default: %s]</comment>', $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(' <info>%s</info> %s%s%s%s', - $synopsis, - str_repeat(' ', $spacingWidth), - // + 4 = 2 spaces before <info>, 2 spaces after </info> - preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $option->getDescription()), - $default, - $option->isArray() ? '<comment> (multiple values allowed)</comment>' : '' - ), $options); - } - - /** - * {@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('<comment>Arguments:</comment>', $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('<comment>Options:</comment>', $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('<comment>Description:</comment>', $options); - $this->writeText("\n"); - $this->writeText(' '.$description); - $this->writeText("\n\n"); - } - - $this->writeText('<comment>Usage:</comment>', $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('<comment>Help:</comment>', $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("<comment>Usage:</comment>\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('<comment>Available commands for the "%s" namespace:</comment>', $describedNamespace), $options); - } else { - $this->writeText('<comment>Available commands:</comment>', $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(' <comment>'.$namespace['id'].'</comment>', $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(' <info>%s</info>%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. - * - * @param mixed $default - */ - private function formatDefaultValue($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<Command|string> $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/lib/symfony/console/Descriptor/XmlDescriptor.php b/lib/symfony/console/Descriptor/XmlDescriptor.php deleted file mode 100644 index 4f7cd8b3e..000000000 --- a/lib/symfony/console/Descriptor/XmlDescriptor.php +++ /dev/null @@ -1,247 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\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 <contact@jfsimon.fr> - * - * @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/lib/symfony/console/Event/ConsoleCommandEvent.php b/lib/symfony/console/Event/ConsoleCommandEvent.php deleted file mode 100644 index 08bd18fd1..000000000 --- a/lib/symfony/console/Event/ConsoleCommandEvent.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Event; - -/** - * Allows to do things before the command is executed, like skipping the command or changing the input. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -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 $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/lib/symfony/console/Event/ConsoleErrorEvent.php b/lib/symfony/console/Event/ConsoleErrorEvent.php deleted file mode 100644 index 57d9b38ba..000000000 --- a/lib/symfony/console/Event/ConsoleErrorEvent.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Event; - -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 <wouter@wouterj.nl> - */ -final class ConsoleErrorEvent extends ConsoleEvent -{ - private $error; - private $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/lib/symfony/console/Event/ConsoleEvent.php b/lib/symfony/console/Event/ConsoleEvent.php deleted file mode 100644 index be7937d51..000000000 --- a/lib/symfony/console/Event/ConsoleEvent.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\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 <git@flevour.net> - */ -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. - * - * @return Command|null - */ - public function getCommand() - { - return $this->command; - } - - /** - * Gets the input instance. - * - * @return InputInterface - */ - public function getInput() - { - return $this->input; - } - - /** - * Gets the output instance. - * - * @return OutputInterface - */ - public function getOutput() - { - return $this->output; - } -} diff --git a/lib/symfony/console/Event/ConsoleSignalEvent.php b/lib/symfony/console/Event/ConsoleSignalEvent.php deleted file mode 100644 index ef13ed2f5..000000000 --- a/lib/symfony/console/Event/ConsoleSignalEvent.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Event; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * @author marie <marie@users.noreply.github.com> - */ -final class ConsoleSignalEvent extends ConsoleEvent -{ - private $handlingSignal; - - public function __construct(Command $command, InputInterface $input, OutputInterface $output, int $handlingSignal) - { - parent::__construct($command, $input, $output); - $this->handlingSignal = $handlingSignal; - } - - public function getHandlingSignal(): int - { - return $this->handlingSignal; - } -} diff --git a/lib/symfony/console/Event/ConsoleTerminateEvent.php b/lib/symfony/console/Event/ConsoleTerminateEvent.php deleted file mode 100644 index 190038d1a..000000000 --- a/lib/symfony/console/Event/ConsoleTerminateEvent.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Event; - -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 <git@flevour.net> - */ -final class ConsoleTerminateEvent extends ConsoleEvent -{ - private $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/lib/symfony/console/EventListener/ErrorListener.php b/lib/symfony/console/EventListener/ErrorListener.php deleted file mode 100644 index 897d9853f..000000000 --- a/lib/symfony/console/EventListener/ErrorListener.php +++ /dev/null @@ -1,95 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\EventListener; - -use Psr\Log\LoggerInterface; -use Symfony\Component\Console\ConsoleEvents; -use Symfony\Component\Console\Event\ConsoleErrorEvent; -use Symfony\Component\Console\Event\ConsoleEvent; -use Symfony\Component\Console\Event\ConsoleTerminateEvent; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; - -/** - * @author James Halsall <james.t.halsall@googlemail.com> - * @author Robin Chalas <robin.chalas@gmail.com> - */ -class ErrorListener implements EventSubscriberInterface -{ - private $logger; - - public function __construct(LoggerInterface $logger = null) - { - $this->logger = $logger; - } - - public function onConsoleError(ConsoleErrorEvent $event) - { - if (null === $this->logger) { - return; - } - - $error = $event->getError(); - - if (!$inputString = $this->getInputString($event)) { - $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() - { - 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 (method_exists($input, '__toString')) { - if ($commandName) { - return str_replace(["'$commandName'", "\"$commandName\""], $commandName, (string) $input); - } - - return (string) $input; - } - - return $commandName; - } -} diff --git a/lib/symfony/console/Exception/CommandNotFoundException.php b/lib/symfony/console/Exception/CommandNotFoundException.php deleted file mode 100644 index 910ae1928..000000000 --- a/lib/symfony/console/Exception/CommandNotFoundException.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Exception; - -/** - * Represents an incorrect command name typed in the console. - * - * @author Jérôme Tamarelle <jerome@tamarelle.net> - */ -class CommandNotFoundException extends \InvalidArgumentException implements ExceptionInterface -{ - private $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() - { - return $this->alternatives; - } -} diff --git a/lib/symfony/console/Exception/ExceptionInterface.php b/lib/symfony/console/Exception/ExceptionInterface.php deleted file mode 100644 index 1624e13d0..000000000 --- a/lib/symfony/console/Exception/ExceptionInterface.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Exception; - -/** - * ExceptionInterface. - * - * @author Jérôme Tamarelle <jerome@tamarelle.net> - */ -interface ExceptionInterface extends \Throwable -{ -} diff --git a/lib/symfony/console/Exception/InvalidArgumentException.php b/lib/symfony/console/Exception/InvalidArgumentException.php deleted file mode 100644 index 07cc0b61d..000000000 --- a/lib/symfony/console/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Exception; - -/** - * @author Jérôme Tamarelle <jerome@tamarelle.net> - */ -class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/lib/symfony/console/Exception/InvalidOptionException.php b/lib/symfony/console/Exception/InvalidOptionException.php deleted file mode 100644 index 5cf62792e..000000000 --- a/lib/symfony/console/Exception/InvalidOptionException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Exception; - -/** - * Represents an incorrect option name or value typed in the console. - * - * @author Jérôme Tamarelle <jerome@tamarelle.net> - */ -class InvalidOptionException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/lib/symfony/console/Exception/LogicException.php b/lib/symfony/console/Exception/LogicException.php deleted file mode 100644 index fc37b8d8a..000000000 --- a/lib/symfony/console/Exception/LogicException.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Exception; - -/** - * @author Jérôme Tamarelle <jerome@tamarelle.net> - */ -class LogicException extends \LogicException implements ExceptionInterface -{ -} diff --git a/lib/symfony/console/Exception/MissingInputException.php b/lib/symfony/console/Exception/MissingInputException.php deleted file mode 100644 index 04f02ade4..000000000 --- a/lib/symfony/console/Exception/MissingInputException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Exception; - -/** - * Represents failure to read input from stdin. - * - * @author Gabriel Ostrolucký <gabriel.ostrolucky@gmail.com> - */ -class MissingInputException extends RuntimeException implements ExceptionInterface -{ -} diff --git a/lib/symfony/console/Exception/NamespaceNotFoundException.php b/lib/symfony/console/Exception/NamespaceNotFoundException.php deleted file mode 100644 index dd16e4508..000000000 --- a/lib/symfony/console/Exception/NamespaceNotFoundException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Exception; - -/** - * Represents an incorrect namespace typed in the console. - * - * @author Pierre du Plessis <pdples@gmail.com> - */ -class NamespaceNotFoundException extends CommandNotFoundException -{ -} diff --git a/lib/symfony/console/Exception/RuntimeException.php b/lib/symfony/console/Exception/RuntimeException.php deleted file mode 100644 index 51d7d80ac..000000000 --- a/lib/symfony/console/Exception/RuntimeException.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Exception; - -/** - * @author Jérôme Tamarelle <jerome@tamarelle.net> - */ -class RuntimeException extends \RuntimeException implements ExceptionInterface -{ -} diff --git a/lib/symfony/console/Formatter/NullOutputFormatter.php b/lib/symfony/console/Formatter/NullOutputFormatter.php deleted file mode 100644 index d770e1465..000000000 --- a/lib/symfony/console/Formatter/NullOutputFormatter.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Formatter; - -/** - * @author Tien Xuan Vo <tien.xuan.vo@gmail.com> - */ -final class NullOutputFormatter implements OutputFormatterInterface -{ - private $style; - - /** - * {@inheritdoc} - */ - public function format(?string $message): ?string - { - return null; - } - - /** - * {@inheritdoc} - */ - public function getStyle(string $name): OutputFormatterStyleInterface - { - // to comply with the interface we must return a OutputFormatterStyleInterface - return $this->style ?? $this->style = new NullOutputFormatterStyle(); - } - - /** - * {@inheritdoc} - */ - public function hasStyle(string $name): bool - { - return false; - } - - /** - * {@inheritdoc} - */ - public function isDecorated(): bool - { - return false; - } - - /** - * {@inheritdoc} - */ - public function setDecorated(bool $decorated): void - { - // do nothing - } - - /** - * {@inheritdoc} - */ - public function setStyle(string $name, OutputFormatterStyleInterface $style): void - { - // do nothing - } -} diff --git a/lib/symfony/console/Formatter/NullOutputFormatterStyle.php b/lib/symfony/console/Formatter/NullOutputFormatterStyle.php deleted file mode 100644 index 9232510f4..000000000 --- a/lib/symfony/console/Formatter/NullOutputFormatterStyle.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Formatter; - -/** - * @author Tien Xuan Vo <tien.xuan.vo@gmail.com> - */ -final class NullOutputFormatterStyle implements OutputFormatterStyleInterface -{ - /** - * {@inheritdoc} - */ - public function apply(string $text): string - { - return $text; - } - - /** - * {@inheritdoc} - */ - public function setBackground(string $color = null): void - { - // do nothing - } - - /** - * {@inheritdoc} - */ - public function setForeground(string $color = null): void - { - // do nothing - } - - /** - * {@inheritdoc} - */ - public function setOption(string $option): void - { - // do nothing - } - - /** - * {@inheritdoc} - */ - public function setOptions(array $options): void - { - // do nothing - } - - /** - * {@inheritdoc} - */ - public function unsetOption(string $option): void - { - // do nothing - } -} diff --git a/lib/symfony/console/Formatter/OutputFormatter.php b/lib/symfony/console/Formatter/OutputFormatter.php deleted file mode 100644 index 603e5dca0..000000000 --- a/lib/symfony/console/Formatter/OutputFormatter.php +++ /dev/null @@ -1,285 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Formatter; - -use Symfony\Component\Console\Exception\InvalidArgumentException; - -/** - * Formatter class for console output. - * - * @author Konstantin Kudryashov <ever.zet@gmail.com> - * @author Roland Franssen <franssen.roland@gmail.com> - */ -class OutputFormatter implements WrappableOutputFormatterInterface -{ - private $decorated; - private $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. - * - * @return string - */ - public static function escape(string $text) - { - $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() - { - return $this->decorated; - } - - /** - * {@inheritdoc} - */ - public function setStyle(string $name, OutputFormatterStyleInterface $style) - { - $this->styles[strtolower($name)] = $style; - } - - /** - * {@inheritdoc} - */ - public function hasStyle(string $name) - { - return isset($this->styles[strtolower($name)]); - } - - /** - * {@inheritdoc} - */ - public function getStyle(string $name) - { - if (!$this->hasStyle($name)) { - throw new InvalidArgumentException(sprintf('Undefined style: "%s".', $name)); - } - - return $this->styles[strtolower($name)]; - } - - /** - * {@inheritdoc} - */ - public function format(?string $message) - { - 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" => '\\', '\\<' => '<', '\\>' => '>']); - } - - /** - * @return OutputFormatterStyleStack - */ - public function getStyleStack() - { - 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/lib/symfony/console/Formatter/OutputFormatterInterface.php b/lib/symfony/console/Formatter/OutputFormatterInterface.php deleted file mode 100644 index 0b5f839a2..000000000 --- a/lib/symfony/console/Formatter/OutputFormatterInterface.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Formatter; - -/** - * Formatter interface for console output. - * - * @author Konstantin Kudryashov <ever.zet@gmail.com> - */ -interface OutputFormatterInterface -{ - /** - * Sets the decorated flag. - */ - public function setDecorated(bool $decorated); - - /** - * Whether the output will decorate messages. - * - * @return bool - */ - public function isDecorated(); - - /** - * Sets a new style. - */ - public function setStyle(string $name, OutputFormatterStyleInterface $style); - - /** - * Checks if output formatter has style with specified name. - * - * @return bool - */ - public function hasStyle(string $name); - - /** - * Gets style options from style with specified name. - * - * @return OutputFormatterStyleInterface - * - * @throws \InvalidArgumentException When style isn't defined - */ - public function getStyle(string $name); - - /** - * Formats a message according to the given styles. - * - * @return string|null - */ - public function format(?string $message); -} diff --git a/lib/symfony/console/Formatter/OutputFormatterStyle.php b/lib/symfony/console/Formatter/OutputFormatterStyle.php deleted file mode 100644 index 0fb36ac63..000000000 --- a/lib/symfony/console/Formatter/OutputFormatterStyle.php +++ /dev/null @@ -1,108 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Formatter; - -use Symfony\Component\Console\Color; - -/** - * Formatter style class for defining styles. - * - * @author Konstantin Kudryashov <ever.zet@gmail.com> - */ -class OutputFormatterStyle implements OutputFormatterStyleInterface -{ - private $color; - private $foreground; - private $background; - private $options; - private $href; - private $handlesHrefGracefully; - - /** - * Initializes output formatter style. - * - * @param string|null $foreground The style foreground color name - * @param string|null $background The style background color name - */ - 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) - { - if (null === $this->handlesHrefGracefully) { - $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/lib/symfony/console/Formatter/OutputFormatterStyleInterface.php b/lib/symfony/console/Formatter/OutputFormatterStyleInterface.php deleted file mode 100644 index b30560d22..000000000 --- a/lib/symfony/console/Formatter/OutputFormatterStyleInterface.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Formatter; - -/** - * Formatter style interface for defining styles. - * - * @author Konstantin Kudryashov <ever.zet@gmail.com> - */ -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. - * - * @return string - */ - public function apply(string $text); -} diff --git a/lib/symfony/console/Formatter/OutputFormatterStyleStack.php b/lib/symfony/console/Formatter/OutputFormatterStyleStack.php deleted file mode 100644 index fc48dc0e1..000000000 --- a/lib/symfony/console/Formatter/OutputFormatterStyleStack.php +++ /dev/null @@ -1,110 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Formatter; - -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Contracts\Service\ResetInterface; - -/** - * @author Jean-François Simon <contact@jfsimon.fr> - */ -class OutputFormatterStyleStack implements ResetInterface -{ - /** - * @var OutputFormatterStyleInterface[] - */ - private $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. - * - * @return OutputFormatterStyleInterface - * - * @throws InvalidArgumentException When style tags incorrectly nested - */ - public function pop(OutputFormatterStyleInterface $style = null) - { - 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. - * - * @return OutputFormatterStyle - */ - public function getCurrent() - { - if (empty($this->styles)) { - return $this->emptyStyle; - } - - return $this->styles[\count($this->styles) - 1]; - } - - /** - * @return $this - */ - public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle) - { - $this->emptyStyle = $emptyStyle; - - return $this; - } - - /** - * @return OutputFormatterStyleInterface - */ - public function getEmptyStyle() - { - return $this->emptyStyle; - } -} diff --git a/lib/symfony/console/Formatter/WrappableOutputFormatterInterface.php b/lib/symfony/console/Formatter/WrappableOutputFormatterInterface.php deleted file mode 100644 index 42319ee55..000000000 --- a/lib/symfony/console/Formatter/WrappableOutputFormatterInterface.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Formatter; - -/** - * Formatter interface for console output that supports word wrapping. - * - * @author Roland Franssen <franssen.roland@gmail.com> - */ -interface WrappableOutputFormatterInterface extends OutputFormatterInterface -{ - /** - * Formats a message according to the given styles, wrapping at `$width` (0 means no wrapping). - */ - public function formatAndWrap(?string $message, int $width); -} diff --git a/lib/symfony/console/Helper/DebugFormatterHelper.php b/lib/symfony/console/Helper/DebugFormatterHelper.php deleted file mode 100644 index e258ba050..000000000 --- a/lib/symfony/console/Helper/DebugFormatterHelper.php +++ /dev/null @@ -1,107 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\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 <fabien@symfony.com> - */ -class DebugFormatterHelper extends Helper -{ - private const COLORS = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default']; - private $started = []; - private $count = -1; - - /** - * Starts a debug formatting session. - * - * @return string - */ - public function start(string $id, string $message, string $prefix = 'RUN') - { - $this->started[$id] = ['border' => ++$this->count % \count(self::COLORS)]; - - return sprintf("%s<bg=blue;fg=white> %s </> <fg=blue>%s</>\n", $this->getBorder($id), $prefix, $message); - } - - /** - * Adds progress to a formatting session. - * - * @return string - */ - public function progress(string $id, string $buffer, bool $error = false, string $prefix = 'OUT', string $errorPrefix = 'ERR') - { - $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<bg=red;fg=white> %s </> ', $this->getBorder($id), $errorPrefix); - $this->started[$id]['err'] = true; - } - - $message .= str_replace("\n", sprintf("\n%s<bg=red;fg=white> %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<bg=green;fg=white> %s </> ', $this->getBorder($id), $prefix); - $this->started[$id]['out'] = true; - } - - $message .= str_replace("\n", sprintf("\n%s<bg=green;fg=white> %s </> ", $this->getBorder($id), $prefix), $buffer); - } - - return $message; - } - - /** - * Stops a formatting session. - * - * @return string - */ - public function stop(string $id, string $message, bool $successful, string $prefix = 'RES') - { - $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : ''; - - if ($successful) { - return sprintf("%s%s<bg=green;fg=white> %s </> <fg=green>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message); - } - - $message = sprintf("%s%s<bg=red;fg=white> %s </> <fg=red>%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('<bg=%s> </>', self::COLORS[$this->started[$id]['border']]); - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'debug_formatter'; - } -} diff --git a/lib/symfony/console/Helper/DescriptorHelper.php b/lib/symfony/console/Helper/DescriptorHelper.php deleted file mode 100644 index af85e9c0a..000000000 --- a/lib/symfony/console/Helper/DescriptorHelper.php +++ /dev/null @@ -1,92 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\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 <contact@jfsimon.fr> - */ -class DescriptorHelper extends Helper -{ - /** - * @var DescriptorInterface[] - */ - private $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) - { - $this->descriptors[$format] = $descriptor; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'descriptor'; - } - - public function getFormats(): array - { - return array_keys($this->descriptors); - } -} diff --git a/lib/symfony/console/Helper/Dumper.php b/lib/symfony/console/Helper/Dumper.php deleted file mode 100644 index b013b6c52..000000000 --- a/lib/symfony/console/Helper/Dumper.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\VarDumper\Cloner\ClonerInterface; -use Symfony\Component\VarDumper\Cloner\VarCloner; -use Symfony\Component\VarDumper\Dumper\CliDumper; - -/** - * @author Roland Franssen <franssen.roland@gmail.com> - */ -final class Dumper -{ - private $output; - private $dumper; - private $cloner; - private $handler; - - public function __construct(OutputInterface $output, CliDumper $dumper = null, ClonerInterface $cloner = null) - { - $this->output = $output; - $this->dumper = $dumper; - $this->cloner = $cloner; - - if (class_exists(CliDumper::class)) { - $this->handler = function ($var): string { - $dumper = $this->dumper ?? $this->dumper = new CliDumper(null, null, CliDumper::DUMP_LIGHT_ARRAY | CliDumper::DUMP_COMMA_SEPARATOR); - $dumper->setColors($this->output->isDecorated()); - - return rtrim($dumper->dump(($this->cloner ?? $this->cloner = new VarCloner())->cloneVar($var)->withRefHandles(false), true)); - }; - } else { - $this->handler = function ($var): string { - switch (true) { - case null === $var: - return 'null'; - case true === $var: - return 'true'; - case false === $var: - return 'false'; - case \is_string($var): - return '"'.$var.'"'; - default: - return rtrim(print_r($var, true)); - } - }; - } - } - - public function __invoke($var): string - { - return ($this->handler)($var); - } -} diff --git a/lib/symfony/console/Helper/FormatterHelper.php b/lib/symfony/console/Helper/FormatterHelper.php deleted file mode 100644 index 92d8dc724..000000000 --- a/lib/symfony/console/Helper/FormatterHelper.php +++ /dev/null @@ -1,92 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Formatter\OutputFormatter; - -/** - * The Formatter class provides helpers to format messages. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class FormatterHelper extends Helper -{ - /** - * Formats a message within a section. - * - * @return string - */ - public function formatSection(string $section, string $message, string $style = 'info') - { - return sprintf('<%s>[%s]</%s> %s', $style, $section, $style, $message); - } - - /** - * Formats a message as a block of text. - * - * @param string|array $messages The message to write in the block - * - * @return string - */ - public function formatBlock($messages, string $style, bool $large = false) - { - 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</%s>', $style, $messages[$i], $style); - } - - return implode("\n", $messages); - } - - /** - * Truncates a message to the given length. - * - * @return string - */ - public function truncate(string $message, int $length, string $suffix = '...') - { - $computedLength = $length - self::width($suffix); - - if ($computedLength > self::width($message)) { - return $message; - } - - return self::substr($message, 0, $length).$suffix; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'formatter'; - } -} diff --git a/lib/symfony/console/Helper/Helper.php b/lib/symfony/console/Helper/Helper.php deleted file mode 100644 index c7d3e25d0..000000000 --- a/lib/symfony/console/Helper/Helper.php +++ /dev/null @@ -1,180 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\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 <fabien@symfony.com> - */ -abstract class Helper implements HelperInterface -{ - protected $helperSet = null; - - /** - * {@inheritdoc} - */ - public function setHelperSet(HelperSet $helperSet = null) - { - $this->helperSet = $helperSet; - } - - /** - * {@inheritdoc} - */ - public function getHelperSet() - { - return $this->helperSet; - } - - /** - * Returns the length of a string, using mb_strwidth if it is available. - * - * @deprecated since Symfony 5.3 - * - * @return int - */ - public static function strlen(?string $string) - { - trigger_deprecation('symfony/console', '5.3', 'Method "%s()" is deprecated and will be removed in Symfony 6.0. Use Helper::width() or Helper::length() instead.', __METHOD__); - - return self::width($string); - } - - /** - * Returns the width of a string, using mb_strwidth if it is available. - * The width is how many characters positions the string will use. - */ - public static function width(?string $string): int - { - $string ?? $string = ''; - - if (preg_match('//u', $string)) { - return (new UnicodeString($string))->width(false); - } - - if (false === $encoding = mb_detect_encoding($string, null, true)) { - return \strlen($string); - } - - 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. - * - * @return string - */ - public static function substr(?string $string, int $from, int $length = null) - { - $string ?? $string = ''; - - if (false === $encoding = mb_detect_encoding($string, null, true)) { - return substr($string, $from, $length); - } - - return mb_substr($string, $from, $length, $encoding); - } - - public static function formatTime($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); - } - - /** - * @deprecated since Symfony 5.3 - */ - public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, ?string $string) - { - trigger_deprecation('symfony/console', '5.3', 'Method "%s()" is deprecated and will be removed in Symfony 6.0. Use Helper::removeDecoration() instead.', __METHOD__); - - return self::width(self::removeDecoration($formatter, $string)); - } - - public static function removeDecoration(OutputFormatterInterface $formatter, ?string $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/lib/symfony/console/Helper/HelperInterface.php b/lib/symfony/console/Helper/HelperInterface.php deleted file mode 100644 index fc952b486..000000000 --- a/lib/symfony/console/Helper/HelperInterface.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -/** - * HelperInterface is the interface all helpers must implement. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface HelperInterface -{ - /** - * Sets the helper set associated with this helper. - */ - public function setHelperSet(HelperSet $helperSet = null); - - /** - * Gets the helper set associated with this helper. - * - * @return HelperSet|null - */ - public function getHelperSet(); - - /** - * Returns the canonical name of this helper. - * - * @return string - */ - public function getName(); -} diff --git a/lib/symfony/console/Helper/HelperSet.php b/lib/symfony/console/Helper/HelperSet.php deleted file mode 100644 index 719762d24..000000000 --- a/lib/symfony/console/Helper/HelperSet.php +++ /dev/null @@ -1,108 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Exception\InvalidArgumentException; - -/** - * HelperSet represents a set of helpers to be used with a command. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @implements \IteratorAggregate<string, Helper> - */ -class HelperSet implements \IteratorAggregate -{ - /** @var array<string, Helper> */ - private $helpers = []; - private $command; - - /** - * @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. - * - * @return bool - */ - public function has(string $name) - { - return isset($this->helpers[$name]); - } - - /** - * Gets a helper value. - * - * @return HelperInterface - * - * @throws InvalidArgumentException if the helper is not defined - */ - public function get(string $name) - { - if (!$this->has($name)) { - throw new InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name)); - } - - return $this->helpers[$name]; - } - - /** - * @deprecated since Symfony 5.4 - */ - public function setCommand(Command $command = null) - { - trigger_deprecation('symfony/console', '5.4', 'Method "%s()" is deprecated.', __METHOD__); - - $this->command = $command; - } - - /** - * Gets the command associated with this helper set. - * - * @return Command - * - * @deprecated since Symfony 5.4 - */ - public function getCommand() - { - trigger_deprecation('symfony/console', '5.4', 'Method "%s()" is deprecated.', __METHOD__); - - return $this->command; - } - - /** - * @return \Traversable<string, Helper> - */ - #[\ReturnTypeWillChange] - public function getIterator() - { - return new \ArrayIterator($this->helpers); - } -} diff --git a/lib/symfony/console/Helper/InputAwareHelper.php b/lib/symfony/console/Helper/InputAwareHelper.php deleted file mode 100644 index 0d0dba23e..000000000 --- a/lib/symfony/console/Helper/InputAwareHelper.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Input\InputAwareInterface; -use Symfony\Component\Console\Input\InputInterface; - -/** - * An implementation of InputAwareInterface for Helpers. - * - * @author Wouter J <waldio.webdesign@gmail.com> - */ -abstract class InputAwareHelper extends Helper implements InputAwareInterface -{ - protected $input; - - /** - * {@inheritdoc} - */ - public function setInput(InputInterface $input) - { - $this->input = $input; - } -} diff --git a/lib/symfony/console/Helper/ProcessHelper.php b/lib/symfony/console/Helper/ProcessHelper.php deleted file mode 100644 index 4ea3d724d..000000000 --- a/lib/symfony/console/Helper/ProcessHelper.php +++ /dev/null @@ -1,144 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\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 <fabien@symfony.com> - * - * @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, $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_array($cmd)) { - throw new \TypeError(sprintf('The "command" argument of "%s()" must be an array or a "%s" instance, "%s" given.', __METHOD__, Process::class, get_debug_type($cmd))); - } - - if (\is_string($cmd[0] ?? null)) { - $process = new Process($cmd); - $cmd = []; - } elseif (($cmd[0] ?? null) instanceof Process) { - $process = $cmd[0]; - unset($cmd[0]); - } else { - throw new \InvalidArgumentException(sprintf('Invalid command provided to "%s()": the command should be an array whose first element is either the path to the binary to run or a "Process" object.', __METHOD__)); - } - - if ($verbosity <= $output->getVerbosity()) { - $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('<error>%s</error>', $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, $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/lib/symfony/console/Helper/ProgressBar.php b/lib/symfony/console/Helper/ProgressBar.php deleted file mode 100644 index eb6aacb1a..000000000 --- a/lib/symfony/console/Helper/ProgressBar.php +++ /dev/null @@ -1,609 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\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 <fabien@symfony.com> - * @author Chris Jones <leeked@gmail.com> - */ -final class ProgressBar -{ - public const FORMAT_VERBOSE = 'verbose'; - public const FORMAT_VERY_VERBOSE = 'very_verbose'; - public const FORMAT_DEBUG = 'debug'; - public const FORMAT_NORMAL = 'normal'; - - private const FORMAT_VERBOSE_NOMAX = 'verbose_nomax'; - private const FORMAT_VERY_VERBOSE_NOMAX = 'very_verbose_nomax'; - private const FORMAT_DEBUG_NOMAX = 'debug_nomax'; - private const FORMAT_NORMAL_NOMAX = 'normal_nomax'; - - private $barWidth = 28; - private $barChar; - private $emptyBarChar = '-'; - private $progressChar = '>'; - private $format; - private $internalFormat; - private $redrawFreq = 1; - private $writeCount; - private $lastWriteTime; - private $minSecondsBetweenRedraws = 0; - private $maxSecondsBetweenRedraws = 1; - private $output; - private $step = 0; - private $max; - private $startTime; - private $stepWidth; - private $percent = 0.0; - private $messages = []; - private $overwrite = true; - private $terminal; - private $previousMessage; - private $cursor; - - private static $formatters; - private static $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 - { - if (!self::$formatters) { - 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 - { - if (!self::$formatters) { - 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 - { - if (!self::$formats) { - 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 - { - if (!self::$formats) { - 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 - { - $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/lib/symfony/console/Helper/ProgressIndicator.php b/lib/symfony/console/Helper/ProgressIndicator.php deleted file mode 100644 index 3482343fc..000000000 --- a/lib/symfony/console/Helper/ProgressIndicator.php +++ /dev/null @@ -1,249 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Exception\LogicException; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * @author Kevin Bond <kevinbond@gmail.com> - */ -class ProgressIndicator -{ - private const FORMATS = [ - 'normal' => ' %indicator% %message%', - 'normal_no_ansi' => ' %message%', - - 'verbose' => ' %indicator% %message% (%elapsed:6s%)', - 'verbose_no_ansi' => ' %message% (%elapsed:6s%)', - - 'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)', - 'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)', - ]; - - private $output; - private $startTime; - private $format; - private $message; - private $indicatorValues; - private $indicatorCurrent; - private $indicatorChangeInterval; - private $indicatorUpdateTime; - private $started = false; - - /** - * @var array<string, callable> - */ - private static $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. - * - * @return string|null - */ - public static function getFormatDefinition(string $name) - { - 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) - { - if (!self::$formatters) { - self::$formatters = self::initPlaceholderFormatters(); - } - - self::$formatters[$name] = $callable; - } - - /** - * Gets the placeholder formatter for a given name (including the delimiter char like %). - * - * @return callable|null - */ - public static function getPlaceholderFormatterDefinition(string $name) - { - if (!self::$formatters) { - 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); - } - - 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/lib/symfony/console/Helper/QuestionHelper.php b/lib/symfony/console/Helper/QuestionHelper.php deleted file mode 100644 index 10602038c..000000000 --- a/lib/symfony/console/Helper/QuestionHelper.php +++ /dev/null @@ -1,616 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\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 <fabien@symfony.com> - */ -class QuestionHelper extends Helper -{ - /** - * @var resource|null - */ - private $inputStream; - - private static $stty = true; - private static $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) - { - 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() - { - return 'question'; - } - - /** - * Prevents usage of stty. - */ - public static function disableStty() - { - self::$stty = false; - } - - /** - * Asks the question to the user. - * - * @return mixed - * - * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden - */ - private function doAsk(OutputInterface $output, Question $question) - { - $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; - } - - /** - * @return mixed - */ - private function getDefaultAnswer(Question $question) - { - $default = $question->getDefault(); - - if (null === $default) { - return $default; - } - - if ($validator = $question->getValidator()) { - return \call_user_func($question->getValidator(), $default); - } elseif ($question instanceof ChoiceQuestion) { - $choices = $question->getChoices(); - - if (!$question->isMultiselect()) { - return $choices[$default] ?? $default; - } - - $default = explode(',', $default); - foreach ($default as $k => $v) { - $v = $question->isTrimmable() ? trim($v) : $v; - $default[$k] = $choices[$v] ?? $v; - } - } - - return $default; - } - - /** - * Outputs the question prompt. - */ - 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) - { - $messages = []; - - $maxWidth = max(array_map([__CLASS__, 'width'], array_keys($choices = $question->getChoices()))); - - foreach ($choices as $key => $value) { - $padding = str_repeat(' ', $maxWidth - self::width($key)); - - $messages[] = sprintf(" [<$tag>%s$padding</$tag>] %s", $key, $value); - } - - return $messages; - } - - /** - * Outputs an error message. - */ - 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>'.$error->getMessage().'</error>'; - } - - $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('<hl>'.OutputFormatter::escapeTrailingBackslash(substr($matches[$ofs], $charactersEntered)).'</hl>'); - $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 - * - * @return mixed The validated response - * - * @throws \Exception In case the max number of attempts has been reached and no valid response has been given - */ - private function validateAttempts(callable $interviewer, OutputInterface $output, Question $question) - { - $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 (null !== self::$stdinIsInteractive) { - return self::$stdinIsInteractive; - } - - if (\function_exists('stream_isatty')) { - return self::$stdinIsInteractive = @stream_isatty(fopen('php://stdin', 'r')); - } - - if (\function_exists('posix_isatty')) { - return self::$stdinIsInteractive = @posix_isatty(fopen('php://stdin', 'r')); - } - - if (!\function_exists('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 - * - * @return string|false The input received, false in case input could not be read - */ - private function readInput($inputStream, Question $question) - { - 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); - } - - /** - * Sets console I/O to the host code page. - * - * @return int Previous code page in IBM/EBCDIC format - */ - private function setIOCodepage(): int - { - if (\function_exists('sapi_windows_cp_set')) { - $cp = sapi_windows_cp_get(); - sapi_windows_cp_set(sapi_windows_cp_get('oem')); - - return $cp; - } - - return 0; - } - - /** - * Sets console I/O to the specified code page and converts the user input. - * - * @param string|false $input - * - * @return string|false - */ - private function resetIOCodepage(int $cp, $input) - { - if (0 !== $cp) { - sapi_windows_cp_set($cp); - - if (false !== $input && '' !== $input) { - $input = sapi_windows_cp_conv(sapi_windows_cp_get('oem'), $cp, $input); - } - } - - return $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/lib/symfony/console/Helper/SymfonyQuestionHelper.php b/lib/symfony/console/Helper/SymfonyQuestionHelper.php deleted file mode 100644 index 01f94aba4..000000000 --- a/lib/symfony/console/Helper/SymfonyQuestionHelper.php +++ /dev/null @@ -1,109 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\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 <kevinbond@gmail.com> - */ -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(' <info>%s</info>:', $text); - - break; - - case $question instanceof ConfirmationQuestion: - $text = sprintf(' <info>%s (yes/no)</info> [<comment>%s</comment>]:', $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(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape(implode(', ', $default))); - - break; - - case $question instanceof ChoiceQuestion: - $choices = $question->getChoices(); - $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($choices[$default] ?? $default)); - - break; - - default: - $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $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 '<comment>Ctrl+Z</comment> then <comment>Enter</comment>'; - } - - return '<comment>Ctrl+D</comment>'; - } -} diff --git a/lib/symfony/console/Helper/Table.php b/lib/symfony/console/Helper/Table.php deleted file mode 100644 index 3f2d99145..000000000 --- a/lib/symfony/console/Helper/Table.php +++ /dev/null @@ -1,915 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Exception\RuntimeException; -use Symfony\Component\Console\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 <fabien@symfony.com> - * @author Саша Стаменковић <umpirsky@gmail.com> - * @author Abdellatif Ait boudad <a.aitboudad@gmail.com> - * @author Max Grigorian <maxakawizard@gmail.com> - * @author Dany Maillard <danymaillard93b@gmail.com> - */ -class Table -{ - private const SEPARATOR_TOP = 0; - private const SEPARATOR_TOP_BOTTOM = 1; - private const SEPARATOR_MID = 2; - private const SEPARATOR_BOTTOM = 3; - private const BORDER_OUTSIDE = 0; - private const BORDER_INSIDE = 1; - - private $headerTitle; - private $footerTitle; - - /** - * Table headers. - */ - private $headers = []; - - /** - * Table rows. - */ - private $rows = []; - private $horizontal = false; - - /** - * Column widths cache. - */ - private $effectiveColumnWidths = []; - - /** - * Number of columns cache. - * - * @var int - */ - private $numberOfColumns; - - /** - * @var OutputInterface - */ - private $output; - - /** - * @var TableStyle - */ - private $style; - - /** - * @var array - */ - private $columnStyles = []; - - /** - * User set column widths. - * - * @var array - */ - private $columnWidths = []; - private $columnMaxWidths = []; - - /** - * @var array<string, TableStyle>|null - */ - private static $styles; - - private $rendered = false; - - public function __construct(OutputInterface $output) - { - $this->output = $output; - - if (!self::$styles) { - self::$styles = self::initStyles(); - } - - $this->setStyle('default'); - } - - /** - * Sets a style definition. - */ - public static function setStyleDefinition(string $name, TableStyle $style) - { - if (!self::$styles) { - self::$styles = self::initStyles(); - } - - self::$styles[$name] = $style; - } - - /** - * Gets a style definition by name. - * - * @return TableStyle - */ - public static function getStyleDefinition(string $name) - { - if (!self::$styles) { - self::$styles = self::initStyles(); - } - - if (isset(self::$styles[$name])) { - return self::$styles[$name]; - } - - throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name)); - } - - /** - * Sets table style. - * - * @param TableStyle|string $name The style name or a TableStyle instance - * - * @return $this - */ - public function setStyle($name) - { - $this->style = $this->resolveStyle($name); - - return $this; - } - - /** - * Gets the current table style. - * - * @return TableStyle - */ - public function getStyle() - { - 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, $name) - { - $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. - * - * @return TableStyle - */ - public function getColumnStyle(int $columnIndex) - { - return $this->columnStyles[$columnIndex] ?? $this->getStyle(); - } - - /** - * Sets the minimum width of a column. - * - * @return $this - */ - public function setColumnWidth(int $columnIndex, int $width) - { - $this->columnWidths[$columnIndex] = $width; - - return $this; - } - - /** - * Sets the minimum width of all columns. - * - * @return $this - */ - public function setColumnWidths(array $widths) - { - $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): self - { - if (!$this->output->getFormatter() instanceof WrappableOutputFormatterInterface) { - throw new \LogicException(sprintf('Setting a maximum column width is only supported when using a "%s" formatter, got "%s".', WrappableOutputFormatterInterface::class, get_debug_type($this->output->getFormatter()))); - } - - $this->columnMaxWidths[$columnIndex] = $width; - - return $this; - } - - /** - * @return $this - */ - public function setHeaders(array $headers) - { - $headers = array_values($headers); - if (!empty($headers) && !\is_array($headers[0])) { - $headers = [$headers]; - } - - $this->headers = $headers; - - return $this; - } - - public function setRows(array $rows) - { - $this->rows = []; - - return $this->addRows($rows); - } - - /** - * @return $this - */ - public function addRows(array $rows) - { - foreach ($rows as $row) { - $this->addRow($row); - } - - return $this; - } - - /** - * @return $this - */ - public function addRow($row) - { - if ($row instanceof TableSeparator) { - $this->rows[] = $row; - - return $this; - } - - if (!\is_array($row)) { - throw new InvalidArgumentException('A row must be an array or a TableSeparator instance.'); - } - - $this->rows[] = array_values($row); - - return $this; - } - - /** - * Adds a row to the table, and re-renders the table. - * - * @return $this - */ - public function appendRow($row): self - { - if (!$this->output instanceof ConsoleSectionOutput) { - throw new RuntimeException(sprintf('Output should be an instance of "%s" when calling "%s".', ConsoleSectionOutput::class, __METHOD__)); - } - - if ($this->rendered) { - $this->output->clear($this->calculateRowCount()); - } - - $this->addRow($row); - $this->render(); - - return $this; - } - - /** - * @return $this - */ - public function setRow($column, array $row) - { - $this->rows[$column] = $row; - - return $this; - } - - /** - * @return $this - */ - public function setHeaderTitle(?string $title): self - { - $this->headerTitle = $title; - - return $this; - } - - /** - * @return $this - */ - public function setFooterTitle(?string $title): self - { - $this->footerTitle = $title; - - return $this; - } - - /** - * @return $this - */ - public function setHorizontal(bool $horizontal = true): self - { - $this->horizontal = $horizontal; - - return $this; - } - - /** - * Renders table to output. - * - * Example: - * - * +---------------+-----------------------+------------------+ - * | 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, '<fg=default;bg=default>')) { - $content = str_replace('<fg=default;bg=default>', '', $content); - $width -= \strlen('<fg=default;bg=default>'); - } - } - - $padType = $cell->getStyle()->getPadByAlign(); - } - - return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $padType)); - } - - /** - * Calculate number of columns for this table. - */ - private function calculateNumberOfColumns(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", "<fg=default;bg=default></>\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) && !(\is_object($cell) && method_exists($cell, '__toString'))) { - throw new InvalidArgumentException(sprintf('A cell must be a TableCell, a scalar or an object implementing "__toString()", "%s" given.', get_debug_type($cell))); - } - if ($cell instanceof TableCell && $cell->getRowspan() > 1) { - $nbLines = $cell->getRowspan() - 1; - $lines = [$cell]; - if (strstr($cell, "\n")) { - $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell)); - $nbLines = \count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines; - - $rows[$line][$column] = new TableCell($lines[0], ['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 = []; - $this->numberOfColumns = null; - } - - /** - * @return array<string, TableStyle> - */ - 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($name): TableStyle - { - if ($name instanceof TableStyle) { - return $name; - } - - if (isset(self::$styles[$name])) { - return self::$styles[$name]; - } - - throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name)); - } -} diff --git a/lib/symfony/console/Helper/TableCell.php b/lib/symfony/console/Helper/TableCell.php deleted file mode 100644 index 1a7bc6ede..000000000 --- a/lib/symfony/console/Helper/TableCell.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Exception\InvalidArgumentException; - -/** - * @author Abdellatif Ait boudad <a.aitboudad@gmail.com> - */ -class TableCell -{ - private $value; - private $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. - * - * @return string - */ - public function __toString() - { - return $this->value; - } - - /** - * Gets number of colspan. - * - * @return int - */ - public function getColspan() - { - return (int) $this->options['colspan']; - } - - /** - * Gets number of rowspan. - * - * @return int - */ - public function getRowspan() - { - return (int) $this->options['rowspan']; - } - - public function getStyle(): ?TableCellStyle - { - return $this->options['style']; - } -} diff --git a/lib/symfony/console/Helper/TableCellStyle.php b/lib/symfony/console/Helper/TableCellStyle.php deleted file mode 100644 index 19cd0ffc6..000000000 --- a/lib/symfony/console/Helper/TableCellStyle.php +++ /dev/null @@ -1,89 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Exception\InvalidArgumentException; - -/** - * @author Yewhen Khoptynskyi <khoptynskyi@gmail.com> - */ -class TableCellStyle -{ - public const DEFAULT_ALIGN = 'left'; - - private const TAG_OPTIONS = [ - 'fg', - 'bg', - 'options', - ]; - - private const ALIGN_MAP = [ - 'left' => \STR_PAD_RIGHT, - 'center' => \STR_PAD_BOTH, - 'right' => \STR_PAD_LEFT, - ]; - - private $options = [ - 'fg' => 'default', - 'bg' => 'default', - 'options' => null, - 'align' => self::DEFAULT_ALIGN, - 'cellFormat' => null, - ]; - - public function __construct(array $options = []) - { - if ($diff = array_diff(array_keys($options), array_keys($this->options))) { - throw new InvalidArgumentException(sprintf('The TableCellStyle does not support the following options: \'%s\'.', implode('\', \'', $diff))); - } - - if (isset($options['align']) && !\array_key_exists($options['align'], self::ALIGN_MAP)) { - throw new InvalidArgumentException(sprintf('Wrong align value. Value must be following: \'%s\'.', implode('\', \'', array_keys(self::ALIGN_MAP)))); - } - - $this->options = array_merge($this->options, $options); - } - - public function getOptions(): array - { - return $this->options; - } - - /** - * Gets options we need for tag for example fg, bg. - * - * @return string[] - */ - public function getTagOptions() - { - return array_filter( - $this->getOptions(), - function ($key) { - return \in_array($key, self::TAG_OPTIONS) && isset($this->options[$key]); - }, - \ARRAY_FILTER_USE_KEY - ); - } - - /** - * @return int - */ - public function getPadByAlign() - { - return self::ALIGN_MAP[$this->getOptions()['align']]; - } - - public function getCellFormat(): ?string - { - return $this->getOptions()['cellFormat']; - } -} diff --git a/lib/symfony/console/Helper/TableRows.php b/lib/symfony/console/Helper/TableRows.php deleted file mode 100644 index cbc07d294..000000000 --- a/lib/symfony/console/Helper/TableRows.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -/** - * @internal - */ -class TableRows implements \IteratorAggregate -{ - private $generator; - - public function __construct(\Closure $generator) - { - $this->generator = $generator; - } - - public function getIterator(): \Traversable - { - return ($this->generator)(); - } -} diff --git a/lib/symfony/console/Helper/TableSeparator.php b/lib/symfony/console/Helper/TableSeparator.php deleted file mode 100644 index e541c5315..000000000 --- a/lib/symfony/console/Helper/TableSeparator.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -/** - * Marks a row as being a separator. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class TableSeparator extends TableCell -{ - public function __construct(array $options = []) - { - parent::__construct('', $options); - } -} diff --git a/lib/symfony/console/Helper/TableStyle.php b/lib/symfony/console/Helper/TableStyle.php deleted file mode 100644 index dfc41e6a4..000000000 --- a/lib/symfony/console/Helper/TableStyle.php +++ /dev/null @@ -1,376 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Exception\LogicException; - -/** - * Defines the styles for a Table. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Саша Стаменковић <umpirsky@gmail.com> - * @author Dany Maillard <danymaillard93b@gmail.com> - */ -class TableStyle -{ - private $paddingChar = ' '; - private $horizontalOutsideBorderChar = '-'; - private $horizontalInsideBorderChar = '-'; - private $verticalOutsideBorderChar = '|'; - private $verticalInsideBorderChar = '|'; - private $crossingChar = '+'; - private $crossingTopRightChar = '+'; - private $crossingTopMidChar = '+'; - private $crossingTopLeftChar = '+'; - private $crossingMidRightChar = '+'; - private $crossingBottomRightChar = '+'; - private $crossingBottomMidChar = '+'; - private $crossingBottomLeftChar = '+'; - private $crossingMidLeftChar = '+'; - private $crossingTopLeftBottomChar = '+'; - private $crossingTopMidBottomChar = '+'; - private $crossingTopRightBottomChar = '+'; - private $headerTitleFormat = '<fg=black;bg=white;options=bold> %s </>'; - private $footerTitleFormat = '<fg=black;bg=white;options=bold> %s </>'; - private $cellHeaderFormat = '<info>%s</info>'; - private $cellRowFormat = '%s'; - private $cellRowContentFormat = ' %s '; - private $borderFormat = '%s'; - private $padType = \STR_PAD_RIGHT; - - /** - * Sets padding character, used for cell padding. - * - * @return $this - */ - public function setPaddingChar(string $paddingChar) - { - if (!$paddingChar) { - throw new LogicException('The padding char must not be empty.'); - } - - $this->paddingChar = $paddingChar; - - return $this; - } - - /** - * Gets padding character, used for cell padding. - * - * @return string - */ - public function getPaddingChar() - { - return $this->paddingChar; - } - - /** - * Sets horizontal border characters. - * - * <code> - * ╔═══════════════╤══════════════════════════╤══════════════════╗ - * 1 ISBN 2 Title │ Author ║ - * ╠═══════════════╪══════════════════════════╪══════════════════╣ - * ║ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri ║ - * ║ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens ║ - * ║ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien ║ - * ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie ║ - * ╚═══════════════╧══════════════════════════╧══════════════════╝ - * </code> - * - * @return $this - */ - public function setHorizontalBorderChars(string $outside, string $inside = null): self - { - $this->horizontalOutsideBorderChar = $outside; - $this->horizontalInsideBorderChar = $inside ?? $outside; - - return $this; - } - - /** - * Sets vertical border characters. - * - * <code> - * ╔═══════════════╤══════════════════════════╤══════════════════╗ - * ║ ISBN │ Title │ Author ║ - * ╠═══════1═══════╪══════════════════════════╪══════════════════╣ - * ║ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri ║ - * ║ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens ║ - * ╟───────2───────┼──────────────────────────┼──────────────────╢ - * ║ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien ║ - * ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie ║ - * ╚═══════════════╧══════════════════════════╧══════════════════╝ - * </code> - * - * @return $this - */ - public function setVerticalBorderChars(string $outside, string $inside = null): self - { - $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: - * <code> - * 1═══════════════2══════════════════════════2══════════════════3 - * ║ ISBN │ Title │ Author ║ - * 8'══════════════0'═════════════════════════0'═════════════════4' - * ║ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri ║ - * ║ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens ║ - * 8───────────────0──────────────────────────0──────────────────4 - * ║ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien ║ - * ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie ║ - * 7═══════════════6══════════════════════════6══════════════════5 - * </code> - * - * @param string $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): self - { - $this->crossingChar = $cross; - $this->crossingTopLeftChar = $topLeft; - $this->crossingTopMidChar = $topMid; - $this->crossingTopRightChar = $topRight; - $this->crossingMidRightChar = $midRight; - $this->crossingBottomRightChar = $bottomRight; - $this->crossingBottomMidChar = $bottomMid; - $this->crossingBottomLeftChar = $bottomLeft; - $this->crossingMidLeftChar = $midLeft; - $this->crossingTopLeftBottomChar = $topLeftBottom ?? $midLeft; - $this->crossingTopMidBottomChar = $topMidBottom ?? $cross; - $this->crossingTopRightBottomChar = $topRightBottom ?? $midRight; - - return $this; - } - - /** - * Sets default crossing character used for each cross. - * - * @see {@link setCrossingChars()} for setting each crossing individually. - */ - public function setDefaultCrossingChar(string $char): self - { - return $this->setCrossingChars($char, $char, $char, $char, $char, $char, $char, $char, $char); - } - - /** - * Gets crossing character. - * - * @return string - */ - public function getCrossingChar() - { - 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) - { - $this->cellHeaderFormat = $cellHeaderFormat; - - return $this; - } - - /** - * Gets header cell format. - * - * @return string - */ - public function getCellHeaderFormat() - { - return $this->cellHeaderFormat; - } - - /** - * Sets row cell format. - * - * @return $this - */ - public function setCellRowFormat(string $cellRowFormat) - { - $this->cellRowFormat = $cellRowFormat; - - return $this; - } - - /** - * Gets row cell format. - * - * @return string - */ - public function getCellRowFormat() - { - return $this->cellRowFormat; - } - - /** - * Sets row cell content format. - * - * @return $this - */ - public function setCellRowContentFormat(string $cellRowContentFormat) - { - $this->cellRowContentFormat = $cellRowContentFormat; - - return $this; - } - - /** - * Gets row cell content format. - * - * @return string - */ - public function getCellRowContentFormat() - { - return $this->cellRowContentFormat; - } - - /** - * Sets table border format. - * - * @return $this - */ - public function setBorderFormat(string $borderFormat) - { - $this->borderFormat = $borderFormat; - - return $this; - } - - /** - * Gets table border format. - * - * @return string - */ - public function getBorderFormat() - { - return $this->borderFormat; - } - - /** - * Sets cell padding type. - * - * @return $this - */ - public function setPadType(int $padType) - { - 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. - * - * @return int - */ - public function getPadType() - { - return $this->padType; - } - - public function getHeaderTitleFormat(): string - { - return $this->headerTitleFormat; - } - - /** - * @return $this - */ - public function setHeaderTitleFormat(string $format): self - { - $this->headerTitleFormat = $format; - - return $this; - } - - public function getFooterTitleFormat(): string - { - return $this->footerTitleFormat; - } - - /** - * @return $this - */ - public function setFooterTitleFormat(string $format): self - { - $this->footerTitleFormat = $format; - - return $this; - } -} diff --git a/lib/symfony/console/Input/ArgvInput.php b/lib/symfony/console/Input/ArgvInput.php deleted file mode 100644 index 675b9ef58..000000000 --- a/lib/symfony/console/Input/ArgvInput.php +++ /dev/null @@ -1,378 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\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 <fabien@symfony.com> - * - * @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 $tokens; - private $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, $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, $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() - { - $isOption = false; - foreach ($this->tokens as $i => $token) { - if ($token && '-' === $token[0]) { - if (str_contains($token, '=') || !isset($this->tokens[$i + 1])) { - continue; - } - - // If it's a long option, consider that everything after "--" is the option name. - // Otherwise, use the last char (if it's a short option set, only the last one can take a value with space separator) - $name = '-' === $token[1] ? substr($token, 2) : substr($token, -1); - if (!isset($this->options[$name]) && !$this->definition->hasShortcut($name)) { - // noop - } elseif ((isset($this->options[$name]) || isset($this->options[$name = $this->definition->shortcutToName($name)])) && $this->tokens[$i + 1] === $this->options[$name]) { - $isOption = true; - } - - continue; - } - - if ($isOption) { - $isOption = false; - continue; - } - - return $token; - } - - return null; - } - - /** - * {@inheritdoc} - */ - public function hasParameterOption($values, bool $onlyParams = false) - { - $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($values, $default = false, bool $onlyParams = false) - { - $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. - * - * @return string - */ - public function __toString() - { - $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/lib/symfony/console/Input/ArrayInput.php b/lib/symfony/console/Input/ArrayInput.php deleted file mode 100644 index c65161484..000000000 --- a/lib/symfony/console/Input/ArrayInput.php +++ /dev/null @@ -1,210 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\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 <fabien@symfony.com> - */ -class ArrayInput extends Input -{ - private $parameters; - - public function __construct(array $parameters, InputDefinition $definition = null) - { - $this->parameters = $parameters; - - parent::__construct($definition); - } - - /** - * {@inheritdoc} - */ - public function getFirstArgument() - { - foreach ($this->parameters as $param => $value) { - if ($param && \is_string($param) && '-' === $param[0]) { - continue; - } - - return $value; - } - - return null; - } - - /** - * {@inheritdoc} - */ - public function hasParameterOption($values, bool $onlyParams = false) - { - $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($values, $default = false, bool $onlyParams = false) - { - $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. - * - * @return string - */ - public function __toString() - { - $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, $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, $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. - * - * @param string|int $name The argument name - * @param mixed $value The value for the argument - * - * @throws InvalidArgumentException When argument given doesn't exist - */ - private function addArgument($name, $value) - { - if (!$this->definition->hasArgument($name)) { - throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); - } - - $this->arguments[$name] = $value; - } -} diff --git a/lib/symfony/console/Input/Input.php b/lib/symfony/console/Input/Input.php deleted file mode 100644 index d37460ed3..000000000 --- a/lib/symfony/console/Input/Input.php +++ /dev/null @@ -1,213 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\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 <fabien@symfony.com> - */ -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() - { - return $this->interactive; - } - - /** - * {@inheritdoc} - */ - public function setInteractive(bool $interactive) - { - $this->interactive = $interactive; - } - - /** - * {@inheritdoc} - */ - public function getArguments() - { - return array_merge($this->definition->getArgumentDefaults(), $this->arguments); - } - - /** - * {@inheritdoc} - */ - public function getArgument(string $name) - { - 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, $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) - { - return $this->definition->hasArgument($name); - } - - /** - * {@inheritdoc} - */ - public function getOptions() - { - return array_merge($this->definition->getOptionDefaults(), $this->options); - } - - /** - * {@inheritdoc} - */ - public function getOption(string $name) - { - if ($this->definition->hasNegation($name)) { - if (null === $value = $this->getOption($this->definition->negationToName($name))) { - return $value; - } - - return !$value; - } - - if (!$this->definition->hasOption($name)) { - throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); - } - - return \array_key_exists($name, $this->options) ? $this->options[$name] : $this->definition->getOption($name)->getDefault(); - } - - /** - * {@inheritdoc} - */ - public function setOption(string $name, $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) - { - return $this->definition->hasOption($name) || $this->definition->hasNegation($name); - } - - /** - * Escapes a token through escapeshellarg if it contains unsafe chars. - * - * @return string - */ - public function escapeToken(string $token) - { - 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/lib/symfony/console/Input/InputArgument.php b/lib/symfony/console/Input/InputArgument.php deleted file mode 100644 index ecfcdad58..000000000 --- a/lib/symfony/console/Input/InputArgument.php +++ /dev/null @@ -1,129 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Exception\LogicException; - -/** - * Represents a command line argument. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class InputArgument -{ - public const REQUIRED = 1; - public const OPTIONAL = 2; - public const IS_ARRAY = 4; - - private $name; - private $mode; - private $default; - private $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 = '', $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. - * - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * Returns true if the argument is required. - * - * @return bool true if parameter mode is self::REQUIRED, false otherwise - */ - public function isRequired() - { - 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() - { - return self::IS_ARRAY === (self::IS_ARRAY & $this->mode); - } - - /** - * Sets the default value. - * - * @param string|bool|int|float|array|null $default - * - * @throws LogicException When incorrect default value is given - */ - public function setDefault($default = null) - { - if ($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. - * - * @return string|bool|int|float|array|null - */ - public function getDefault() - { - return $this->default; - } - - /** - * Returns the description text. - * - * @return string - */ - public function getDescription() - { - return $this->description; - } -} diff --git a/lib/symfony/console/Input/InputAwareInterface.php b/lib/symfony/console/Input/InputAwareInterface.php deleted file mode 100644 index 5a288de5d..000000000 --- a/lib/symfony/console/Input/InputAwareInterface.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -/** - * InputAwareInterface should be implemented by classes that depends on the - * Console Input. - * - * @author Wouter J <waldio.webdesign@gmail.com> - */ -interface InputAwareInterface -{ - /** - * Sets the Console Input. - */ - public function setInput(InputInterface $input); -} diff --git a/lib/symfony/console/Input/InputDefinition.php b/lib/symfony/console/Input/InputDefinition.php deleted file mode 100644 index 11f704f0e..000000000 --- a/lib/symfony/console/Input/InputDefinition.php +++ /dev/null @@ -1,424 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\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 <fabien@symfony.com> - */ -class InputDefinition -{ - private $arguments; - private $requiredCount; - private $lastArrayArgument; - private $lastOptionalArgument; - private $options; - private $negations; - private $shortcuts; - - /** - * @param array $definition An array of InputArgument and InputOption instance - */ - public function __construct(array $definition = []) - { - $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. - * - * @param string|int $name The InputArgument name or position - * - * @return InputArgument - * - * @throws InvalidArgumentException When argument given doesn't exist - */ - public function getArgument($name) - { - 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. - * - * @param string|int $name The InputArgument name or position - * - * @return bool - */ - public function hasArgument($name) - { - $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() - { - return $this->arguments; - } - - /** - * Returns the number of InputArguments. - * - * @return int - */ - public function getArgumentCount() - { - return null !== $this->lastArrayArgument ? \PHP_INT_MAX : \count($this->arguments); - } - - /** - * Returns the number of required InputArguments. - * - * @return int - */ - public function getArgumentRequiredCount() - { - return $this->requiredCount; - } - - /** - * @return array<string|bool|int|float|array|null> - */ - public function getArgumentDefaults() - { - $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. - * - * @return InputOption - * - * @throws InvalidArgumentException When option given doesn't exist - */ - public function getOption(string $name) - { - 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). - * - * @return bool - */ - public function hasOption(string $name) - { - return isset($this->options[$name]); - } - - /** - * Gets the array of InputOption objects. - * - * @return InputOption[] - */ - public function getOptions() - { - return $this->options; - } - - /** - * Returns true if an InputOption object exists by shortcut. - * - * @return bool - */ - public function hasShortcut(string $name) - { - return isset($this->shortcuts[$name]); - } - - /** - * Returns true if an InputOption object exists by negated name. - */ - public function hasNegation(string $name): bool - { - return isset($this->negations[$name]); - } - - /** - * Gets an InputOption by shortcut. - * - * @return InputOption - */ - public function getOptionForShortcut(string $shortcut) - { - return $this->getOption($this->shortcutToName($shortcut)); - } - - /** - * @return array<string|bool|int|float|array|null> - */ - public function getOptionDefaults() - { - $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. - * - * @return string - */ - public function getSynopsis(bool $short = false) - { - $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/lib/symfony/console/Input/InputInterface.php b/lib/symfony/console/Input/InputInterface.php deleted file mode 100644 index 628b6037a..000000000 --- a/lib/symfony/console/Input/InputInterface.php +++ /dev/null @@ -1,151 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\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 <fabien@symfony.com> - */ -interface InputInterface -{ - /** - * Returns the first argument from the raw parameters (not parsed). - * - * @return string|null - */ - public function getFirstArgument(); - - /** - * 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 - * - * @return bool - */ - public function hasParameterOption($values, bool $onlyParams = false); - - /** - * 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($values, $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<string|bool|int|float|array|null> - */ - public function getArguments(); - - /** - * 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. - * - * @param mixed $value The argument value - * - * @throws InvalidArgumentException When argument given doesn't exist - */ - public function setArgument(string $name, $value); - - /** - * Returns true if an InputArgument object exists by name or position. - * - * @return bool - */ - public function hasArgument(string $name); - - /** - * Returns all the given options merged with the default values. - * - * @return array<string|bool|int|float|array|null> - */ - public function getOptions(); - - /** - * 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. - * - * @param mixed $value The option value - * - * @throws InvalidArgumentException When option given doesn't exist - */ - public function setOption(string $name, $value); - - /** - * Returns true if an InputOption object exists by name. - * - * @return bool - */ - public function hasOption(string $name); - - /** - * Is this input means interactive? - * - * @return bool - */ - public function isInteractive(); - - /** - * Sets the input interactivity. - */ - public function setInteractive(bool $interactive); -} diff --git a/lib/symfony/console/Input/InputOption.php b/lib/symfony/console/Input/InputOption.php deleted file mode 100644 index 2bec34fe1..000000000 --- a/lib/symfony/console/Input/InputOption.php +++ /dev/null @@ -1,231 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Exception\LogicException; - -/** - * Represents a command line option. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -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 $name; - private $shortcut; - private $mode; - private $default; - private $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, $shortcut = null, int $mode = null, string $description = '', $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. - * - * @return string|null - */ - public function getShortcut() - { - return $this->shortcut; - } - - /** - * Returns the option name. - * - * @return string - */ - public function getName() - { - 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() - { - 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() - { - 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() - { - 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() - { - return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode); - } - - public function isNegatable(): bool - { - return self::VALUE_NEGATABLE === (self::VALUE_NEGATABLE & $this->mode); - } - - /** - * @param string|bool|int|float|array|null $default - */ - public function setDefault($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. - * - * @return string|bool|int|float|array|null - */ - public function getDefault() - { - return $this->default; - } - - /** - * Returns the description text. - * - * @return string - */ - public function getDescription() - { - return $this->description; - } - - /** - * Checks whether the given option equals this one. - * - * @return bool - */ - public function equals(self $option) - { - return $option->getName() === $this->getName() - && $option->getShortcut() === $this->getShortcut() - && $option->getDefault() === $this->getDefault() - && $option->isNegatable() === $this->isNegatable() - && $option->isArray() === $this->isArray() - && $option->isValueRequired() === $this->isValueRequired() - && $option->isValueOptional() === $this->isValueOptional() - ; - } -} diff --git a/lib/symfony/console/Input/StreamableInputInterface.php b/lib/symfony/console/Input/StreamableInputInterface.php deleted file mode 100644 index d7e462f24..000000000 --- a/lib/symfony/console/Input/StreamableInputInterface.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -/** - * StreamableInputInterface is the interface implemented by all input classes - * that have an input stream. - * - * @author Robin Chalas <robin.chalas@gmail.com> - */ -interface StreamableInputInterface extends InputInterface -{ - /** - * Sets the input stream to read from when interacting with the user. - * - * This is mainly useful for testing purpose. - * - * @param resource $stream The input stream - */ - public function setStream($stream); - - /** - * Returns the input stream. - * - * @return resource|null - */ - public function getStream(); -} diff --git a/lib/symfony/console/Input/StringInput.php b/lib/symfony/console/Input/StringInput.php deleted file mode 100644 index 56bb66cbf..000000000 --- a/lib/symfony/console/Input/StringInput.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\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 <fabien@symfony.com> - */ -class StringInput extends ArgvInput -{ - public const REGEX_STRING = '([^\s]+?)(?:\s|(?<!\\\\)"|(?<!\\\\)\'|$)'; - public const REGEX_UNQUOTED_STRING = '([^\s\\\\]+?)'; - public const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')'; - - /** - * @param string $input A string representing the parameters from the CLI - */ - public function __construct(string $input) - { - parent::__construct([]); - - $this->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/lib/symfony/console/LICENSE b/lib/symfony/console/LICENSE deleted file mode 100644 index 008370457..000000000 --- a/lib/symfony/console/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -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/lib/symfony/console/Logger/ConsoleLogger.php b/lib/symfony/console/Logger/ConsoleLogger.php deleted file mode 100644 index 4a10fa172..000000000 --- a/lib/symfony/console/Logger/ConsoleLogger.php +++ /dev/null @@ -1,126 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\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 <dunglas@gmail.com> - * - * @see https://www.php-fig.org/psr/psr-3/ - */ -class ConsoleLogger extends AbstractLogger -{ - public const INFO = 'info'; - public const ERROR = 'error'; - - private $output; - private $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 $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 $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} - * - * @return void - */ - public function log($level, $message, array $context = []) - { - 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</%1$s>', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)), $this->verbosityLevelMap[$level]); - } - } - - /** - * Returns true when any messages have been logged at error levels. - * - * @return bool - */ - public function hasErrored() - { - return $this->errored; - } - - /** - * Interpolates context values into the message placeholders. - * - * @author PHP Framework Interoperability Group - */ - 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) || (\is_object($val) && method_exists($val, '__toString'))) { - $replacements["{{$key}}"] = $val; - } elseif ($val instanceof \DateTimeInterface) { - $replacements["{{$key}}"] = $val->format(\DateTime::RFC3339); - } elseif (\is_object($val)) { - $replacements["{{$key}}"] = '[object '.\get_class($val).']'; - } else { - $replacements["{{$key}}"] = '['.\gettype($val).']'; - } - } - - return strtr($message, $replacements); - } -} diff --git a/lib/symfony/console/Output/BufferedOutput.php b/lib/symfony/console/Output/BufferedOutput.php deleted file mode 100644 index d37c6e323..000000000 --- a/lib/symfony/console/Output/BufferedOutput.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -/** - * @author Jean-François Simon <contact@jfsimon.fr> - */ -class BufferedOutput extends Output -{ - private $buffer = ''; - - /** - * Empties buffer and returns its content. - * - * @return string - */ - public function fetch() - { - $content = $this->buffer; - $this->buffer = ''; - - return $content; - } - - /** - * {@inheritdoc} - */ - protected function doWrite(string $message, bool $newline) - { - $this->buffer .= $message; - - if ($newline) { - $this->buffer .= \PHP_EOL; - } - } -} diff --git a/lib/symfony/console/Output/ConsoleOutput.php b/lib/symfony/console/Output/ConsoleOutput.php deleted file mode 100644 index f19f9ebf4..000000000 --- a/lib/symfony/console/Output/ConsoleOutput.php +++ /dev/null @@ -1,172 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\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 <fabien@symfony.com> - */ -class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface -{ - private $stderr; - private $consoleSectionOutputs = []; - - /** - * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) - * @param bool|null $decorated Whether to decorate messages (null for auto-guessing) - * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) - */ - public function __construct(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() - { - return $this->stderr; - } - - /** - * {@inheritdoc} - */ - public function setErrorOutput(OutputInterface $error) - { - $this->stderr = $error; - } - - /** - * Returns true if current environment supports writing console output to - * STDOUT. - * - * @return bool - */ - protected function hasStdoutSupport() - { - return false === $this->isRunningOS400(); - } - - /** - * Returns true if current environment supports writing console output to - * STDERR. - * - * @return bool - */ - protected function hasStderrSupport() - { - 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/lib/symfony/console/Output/ConsoleOutputInterface.php b/lib/symfony/console/Output/ConsoleOutputInterface.php deleted file mode 100644 index 6b6635f58..000000000 --- a/lib/symfony/console/Output/ConsoleOutputInterface.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -/** - * ConsoleOutputInterface is the interface implemented by ConsoleOutput class. - * This adds information about stderr and section output stream. - * - * @author Dariusz Górecki <darek.krk@gmail.com> - */ -interface ConsoleOutputInterface extends OutputInterface -{ - /** - * Gets the OutputInterface for errors. - * - * @return OutputInterface - */ - public function getErrorOutput(); - - public function setErrorOutput(OutputInterface $error); - - public function section(): ConsoleSectionOutput; -} diff --git a/lib/symfony/console/Output/ConsoleSectionOutput.php b/lib/symfony/console/Output/ConsoleSectionOutput.php deleted file mode 100644 index 8f1649758..000000000 --- a/lib/symfony/console/Output/ConsoleSectionOutput.php +++ /dev/null @@ -1,143 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -use Symfony\Component\Console\Formatter\OutputFormatterInterface; -use Symfony\Component\Console\Helper\Helper; -use Symfony\Component\Console\Terminal; - -/** - * @author Pierre du Plessis <pdples@gmail.com> - * @author Gabriel Ostrolucký <gabriel.ostrolucky@gmail.com> - */ -class ConsoleSectionOutput extends StreamOutput -{ - private $content = []; - private $lines = 0; - private $sections; - private $terminal; - - /** - * @param resource $stream - * @param ConsoleSectionOutput[] $sections - */ - public function __construct($stream, array &$sections, int $verbosity, bool $decorated, OutputFormatterInterface $formatter) - { - parent::__construct($stream, $verbosity, $decorated, $formatter); - array_unshift($sections, $this); - $this->sections = &$sections; - $this->terminal = new Terminal(); - } - - /** - * Clears previous output for this section. - * - * @param int $lines Number of lines to clear. If null, then the entire output of this section is cleared - */ - public function clear(int $lines = null) - { - if (empty($this->content) || !$this->isDecorated()) { - return; - } - - if ($lines) { - array_splice($this->content, -($lines * 2)); // Multiply lines by 2 to cater for each new line added between content - } else { - $lines = $this->lines; - $this->content = []; - } - - $this->lines -= $lines; - - parent::doWrite($this->popStreamContentUntilCurrentSection($lines), false); - } - - /** - * Overwrites the previous output with a new message. - * - * @param array|string $message - */ - public function overwrite($message) - { - $this->clear(); - $this->writeln($message); - } - - public function getContent(): string - { - return implode('', $this->content); - } - - /** - * @internal - */ - public function addContent(string $input) - { - foreach (explode(\PHP_EOL, $input) as $lineContent) { - $this->lines += ceil($this->getDisplayLength($lineContent) / $this->terminal->getWidth()) ?: 1; - $this->content[] = $lineContent; - $this->content[] = \PHP_EOL; - } - } - - /** - * {@inheritdoc} - */ - protected function doWrite(string $message, bool $newline) - { - if (!$this->isDecorated()) { - parent::doWrite($message, $newline); - - return; - } - - $erasedContent = $this->popStreamContentUntilCurrentSection(); - - $this->addContent($message); - - parent::doWrite($message, true); - parent::doWrite($erasedContent, false); - } - - /** - * At initial stage, cursor is at the end of stream output. This method makes cursor crawl upwards until it hits - * current section. Then it erases content it crawled through. Optionally, it erases part of current section too. - */ - private function popStreamContentUntilCurrentSection(int $numberOfLinesToClearFromCurrentSection = 0): string - { - $numberOfLinesToClear = $numberOfLinesToClearFromCurrentSection; - $erasedContent = []; - - foreach ($this->sections as $section) { - if ($section === $this) { - break; - } - - $numberOfLinesToClear += $section->lines; - $erasedContent[] = $section->getContent(); - } - - if ($numberOfLinesToClear > 0) { - // move cursor up n lines - parent::doWrite(sprintf("\x1b[%dA", $numberOfLinesToClear), false); - // erase to end of screen - parent::doWrite("\x1b[0J", false); - } - - return implode('', array_reverse($erasedContent)); - } - - private function getDisplayLength(string $text): int - { - return Helper::width(Helper::removeDecoration($this->getFormatter(), str_replace("\t", ' ', $text))); - } -} diff --git a/lib/symfony/console/Output/NullOutput.php b/lib/symfony/console/Output/NullOutput.php deleted file mode 100644 index 3bbe63ea0..000000000 --- a/lib/symfony/console/Output/NullOutput.php +++ /dev/null @@ -1,128 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -use Symfony\Component\Console\Formatter\NullOutputFormatter; -use Symfony\Component\Console\Formatter\OutputFormatterInterface; - -/** - * NullOutput suppresses all output. - * - * $output = new NullOutput(); - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Tobias Schultze <http://tobion.de> - */ -class NullOutput implements OutputInterface -{ - private $formatter; - - /** - * {@inheritdoc} - */ - public function setFormatter(OutputFormatterInterface $formatter) - { - // do nothing - } - - /** - * {@inheritdoc} - */ - public function getFormatter() - { - if ($this->formatter) { - return $this->formatter; - } - // 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() - { - return false; - } - - /** - * {@inheritdoc} - */ - public function setVerbosity(int $level) - { - // do nothing - } - - /** - * {@inheritdoc} - */ - public function getVerbosity() - { - return self::VERBOSITY_QUIET; - } - - /** - * {@inheritdoc} - */ - public function isQuiet() - { - return true; - } - - /** - * {@inheritdoc} - */ - public function isVerbose() - { - return false; - } - - /** - * {@inheritdoc} - */ - public function isVeryVerbose() - { - return false; - } - - /** - * {@inheritdoc} - */ - public function isDebug() - { - return false; - } - - /** - * {@inheritdoc} - */ - public function writeln($messages, int $options = self::OUTPUT_NORMAL) - { - // do nothing - } - - /** - * {@inheritdoc} - */ - public function write($messages, bool $newline = false, int $options = self::OUTPUT_NORMAL) - { - // do nothing - } -} diff --git a/lib/symfony/console/Output/Output.php b/lib/symfony/console/Output/Output.php deleted file mode 100644 index d7c5fb2d1..000000000 --- a/lib/symfony/console/Output/Output.php +++ /dev/null @@ -1,174 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\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 <fabien@symfony.com> - */ -abstract class Output implements OutputInterface -{ - private $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() - { - return $this->formatter; - } - - /** - * {@inheritdoc} - */ - public function setDecorated(bool $decorated) - { - $this->formatter->setDecorated($decorated); - } - - /** - * {@inheritdoc} - */ - public function isDecorated() - { - return $this->formatter->isDecorated(); - } - - /** - * {@inheritdoc} - */ - public function setVerbosity(int $level) - { - $this->verbosity = $level; - } - - /** - * {@inheritdoc} - */ - public function getVerbosity() - { - return $this->verbosity; - } - - /** - * {@inheritdoc} - */ - public function isQuiet() - { - return self::VERBOSITY_QUIET === $this->verbosity; - } - - /** - * {@inheritdoc} - */ - public function isVerbose() - { - return self::VERBOSITY_VERBOSE <= $this->verbosity; - } - - /** - * {@inheritdoc} - */ - public function isVeryVerbose() - { - return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity; - } - - /** - * {@inheritdoc} - */ - public function isDebug() - { - return self::VERBOSITY_DEBUG <= $this->verbosity; - } - - /** - * {@inheritdoc} - */ - public function writeln($messages, int $options = self::OUTPUT_NORMAL) - { - $this->write($messages, true, $options); - } - - /** - * {@inheritdoc} - */ - public function write($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/lib/symfony/console/Output/OutputInterface.php b/lib/symfony/console/Output/OutputInterface.php deleted file mode 100644 index 55caab80b..000000000 --- a/lib/symfony/console/Output/OutputInterface.php +++ /dev/null @@ -1,110 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -use Symfony\Component\Console\Formatter\OutputFormatterInterface; - -/** - * OutputInterface is the interface implemented by all Output classes. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -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 string|iterable $messages The message as an iterable of strings or a single string - * @param bool $newline Whether to add a newline - * @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL - */ - public function write($messages, bool $newline = false, int $options = 0); - - /** - * Writes a message to the output and adds a newline at the end. - * - * @param string|iterable $messages The message as an iterable of strings or a single string - * @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL - */ - public function writeln($messages, int $options = 0); - - /** - * Sets the verbosity of the output. - */ - public function setVerbosity(int $level); - - /** - * Gets the current verbosity of the output. - * - * @return int - */ - public function getVerbosity(); - - /** - * Returns whether verbosity is quiet (-q). - * - * @return bool - */ - public function isQuiet(); - - /** - * Returns whether verbosity is verbose (-v). - * - * @return bool - */ - public function isVerbose(); - - /** - * Returns whether verbosity is very verbose (-vv). - * - * @return bool - */ - public function isVeryVerbose(); - - /** - * Returns whether verbosity is debug (-vvv). - * - * @return bool - */ - public function isDebug(); - - /** - * Sets the decorated flag. - */ - public function setDecorated(bool $decorated); - - /** - * Gets the decorated flag. - * - * @return bool - */ - public function isDecorated(); - - public function setFormatter(OutputFormatterInterface $formatter); - - /** - * Returns current output formatter instance. - * - * @return OutputFormatterInterface - */ - public function getFormatter(); -} diff --git a/lib/symfony/console/Output/StreamOutput.php b/lib/symfony/console/Output/StreamOutput.php deleted file mode 100644 index 7f5551827..000000000 --- a/lib/symfony/console/Output/StreamOutput.php +++ /dev/null @@ -1,115 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\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 <fabien@symfony.com> - */ -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() - { - // 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/lib/symfony/console/Output/TrimmedBufferOutput.php b/lib/symfony/console/Output/TrimmedBufferOutput.php deleted file mode 100644 index 3f4d375f4..000000000 --- a/lib/symfony/console/Output/TrimmedBufferOutput.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Formatter\OutputFormatterInterface; - -/** - * A BufferedOutput that keeps only the last N chars. - * - * @author Jérémy Derussé <jeremy@derusse.com> - */ -class TrimmedBufferOutput extends Output -{ - private $maxLength; - private $buffer = ''; - - public function __construct(int $maxLength, ?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = false, OutputFormatterInterface $formatter = null) - { - if ($maxLength <= 0) { - throw new InvalidArgumentException(sprintf('"%s()" expects a strictly positive maxLength. Got %d.', __METHOD__, $maxLength)); - } - - parent::__construct($verbosity, $decorated, $formatter); - $this->maxLength = $maxLength; - } - - /** - * Empties buffer and returns its content. - * - * @return string - */ - public function fetch() - { - $content = $this->buffer; - $this->buffer = ''; - - return $content; - } - - /** - * {@inheritdoc} - */ - protected function doWrite(string $message, bool $newline) - { - $this->buffer .= $message; - - if ($newline) { - $this->buffer .= \PHP_EOL; - } - - $this->buffer = substr($this->buffer, 0 - $this->maxLength); - } -} diff --git a/lib/symfony/console/Question/ChoiceQuestion.php b/lib/symfony/console/Question/ChoiceQuestion.php deleted file mode 100644 index bf1f90487..000000000 --- a/lib/symfony/console/Question/ChoiceQuestion.php +++ /dev/null @@ -1,183 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Question; - -use Symfony\Component\Console\Exception\InvalidArgumentException; - -/** - * Represents a choice question. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class ChoiceQuestion extends Question -{ - private $choices; - private $multiselect = false; - private $prompt = ' > '; - private $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, $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. - * - * @return array - */ - public function getChoices() - { - return $this->choices; - } - - /** - * Sets multiselect option. - * - * When multiselect is set to true, multiple choices can be answered. - * - * @return $this - */ - public function setMultiselect(bool $multiselect) - { - $this->multiselect = $multiselect; - $this->setValidator($this->getDefaultValidator()); - - return $this; - } - - /** - * Returns whether the choices are multiselect. - * - * @return bool - */ - public function isMultiselect() - { - return $this->multiselect; - } - - /** - * Gets the prompt for choices. - * - * @return string - */ - public function getPrompt() - { - return $this->prompt; - } - - /** - * Sets the prompt for choices. - * - * @return $this - */ - public function setPrompt(string $prompt) - { - $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) - { - $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/lib/symfony/console/Question/ConfirmationQuestion.php b/lib/symfony/console/Question/ConfirmationQuestion.php deleted file mode 100644 index 4228521b9..000000000 --- a/lib/symfony/console/Question/ConfirmationQuestion.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Question; - -/** - * Represents a yes/no question. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class ConfirmationQuestion extends Question -{ - private $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/lib/symfony/console/Question/Question.php b/lib/symfony/console/Question/Question.php deleted file mode 100644 index 3a73f04b2..000000000 --- a/lib/symfony/console/Question/Question.php +++ /dev/null @@ -1,299 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Question; - -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Exception\LogicException; - -/** - * Represents a Question. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Question -{ - private $question; - private $attempts; - private $hidden = false; - private $hiddenFallback = true; - private $autocompleterCallback; - private $validator; - private $default; - private $normalizer; - private $trimmable = true; - private $multiline = false; - - /** - * @param string $question The question to ask to the user - * @param string|bool|int|float|null $default The default answer to return if the user enters nothing - */ - public function __construct(string $question, $default = null) - { - $this->question = $question; - $this->default = $default; - } - - /** - * Returns the question. - * - * @return string - */ - public function getQuestion() - { - return $this->question; - } - - /** - * Returns the default answer. - * - * @return string|bool|int|float|null - */ - public function getDefault() - { - return $this->default; - } - - /** - * Returns whether the user response accepts newline characters. - */ - public function isMultiline(): bool - { - return $this->multiline; - } - - /** - * Sets whether the user response should accept newline characters. - * - * @return $this - */ - public function setMultiline(bool $multiline): self - { - $this->multiline = $multiline; - - return $this; - } - - /** - * Returns whether the user response must be hidden. - * - * @return bool - */ - public function isHidden() - { - 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) - { - 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. - * - * @return bool - */ - public function isHiddenFallback() - { - return $this->hiddenFallback; - } - - /** - * Sets whether to fallback on non-hidden question if the response cannot be hidden. - * - * @return $this - */ - public function setHiddenFallback(bool $fallback) - { - $this->hiddenFallback = $fallback; - - return $this; - } - - /** - * Gets values for the autocompleter. - * - * @return iterable|null - */ - public function getAutocompleterValues() - { - $callback = $this->getAutocompleterCallback(); - - return $callback ? $callback('') : null; - } - - /** - * Sets values for the autocompleter. - * - * @return $this - * - * @throws LogicException - */ - public function setAutocompleterValues(?iterable $values) - { - 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): self - { - if ($this->hidden && null !== $callback) { - throw new LogicException('A hidden question cannot use the autocompleter.'); - } - - $this->autocompleterCallback = $callback; - - return $this; - } - - /** - * Sets a validator for the question. - * - * @return $this - */ - public function setValidator(callable $validator = null) - { - $this->validator = $validator; - - return $this; - } - - /** - * Gets the validator for the question. - * - * @return callable|null - */ - public function getValidator() - { - 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) - { - 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. - * - * @return int|null - */ - public function getMaxAttempts() - { - 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) - { - $this->normalizer = $normalizer; - - return $this; - } - - /** - * Gets the normalizer for the response. - * - * The normalizer can ba a callable (a string), a closure or a class implementing __invoke. - * - * @return callable|null - */ - public function getNormalizer() - { - 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): self - { - $this->trimmable = $trimmable; - - return $this; - } -} diff --git a/lib/symfony/console/README.md b/lib/symfony/console/README.md deleted file mode 100644 index c4c129989..000000000 --- a/lib/symfony/console/README.md +++ /dev/null @@ -1,36 +0,0 @@ -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/lib/symfony/console/Resources/bin/hiddeninput.exe b/lib/symfony/console/Resources/bin/hiddeninput.exe deleted file mode 100644 index c8cf65e8d819e6e525121cf6b21f1c2429746038..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9216 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 J0sQ~1{4brj`U(I5 diff --git a/lib/symfony/console/Resources/completion.bash b/lib/symfony/console/Resources/completion.bash deleted file mode 100644 index 64b87ccf7..000000000 --- a/lib/symfony/console/Resources/completion.bash +++ /dev/null @@ -1,84 +0,0 @@ -# This file is part of the Symfony package. -# -# (c) Fabien Potencier <fabien@symfony.com> -# -# For the full copyright and license information, please view -# https://symfony.com/doc/current/contributing/code/license.html - -_sf_{{ COMMAND_NAME }}() { - # Use newline as only separator to allow space in completion values - IFS=$'\n' - local sf_cmd="${COMP_WORDS[0]}" - - # for an alias, get the real script behind it - sf_cmd_type=$(type -t $sf_cmd) - if [[ $sf_cmd_type == "alias" ]]; then - sf_cmd=$(alias $sf_cmd | sed -E "s/alias $sf_cmd='(.*)'/\1/") - elif [[ $sf_cmd_type == "file" ]]; then - sf_cmd=$(type -p $sf_cmd) - fi - - if [[ $sf_cmd_type != "function" && ! -x $sf_cmd ]]; then - return 1 - fi - - local cur prev words cword - _get_comp_words_by_ref -n := cur prev words cword - - local completecmd=("$sf_cmd" "_complete" "--no-interaction" "-sbash" "-c$cword" "-S{{ VERSION }}") - for w in ${words[@]}; do - w=$(printf -- '%b' "$w") - # remove quotes from typed values - quote="${w:0:1}" - if [ "$quote" == \' ]; then - w="${w%\'}" - w="${w#\'}" - elif [ "$quote" == \" ]; then - w="${w%\"}" - w="${w#\"}" - fi - # empty values are ignored - if [ ! -z "$w" ]; then - completecmd+=("-i$w") - fi - done - - local sfcomplete - if sfcomplete=$(${completecmd[@]} 2>&1); then - local quote suggestions - quote=${cur:0:1} - - # Use single quotes by default if suggestions contains backslash (FQCN) - if [ "$quote" == '' ] && [[ "$sfcomplete" =~ \\ ]]; then - quote=\' - fi - - if [ "$quote" == \' ]; then - # single quotes: no additional escaping (does not accept ' in values) - suggestions=$(for s in $sfcomplete; do printf $'%q%q%q\n' "$quote" "$s" "$quote"; done) - elif [ "$quote" == \" ]; then - # double quotes: double escaping for \ $ ` " - suggestions=$(for s in $sfcomplete; do - s=${s//\\/\\\\} - s=${s//\$/\\\$} - s=${s//\`/\\\`} - s=${s//\"/\\\"} - printf $'%q%q%q\n' "$quote" "$s" "$quote"; - done) - else - # no quotes: double escaping - suggestions=$(for s in $sfcomplete; do printf $'%q\n' $(printf '%q' "$s"); done) - fi - COMPREPLY=($(IFS=$'\n' compgen -W "$suggestions" -- $(printf -- "%q" "$cur"))) - __ltrim_colon_completions "$cur" - else - if [[ "$sfcomplete" != *"Command \"_complete\" is not defined."* ]]; then - >&2 echo - >&2 echo $sfcomplete - fi - - return 1 - fi -} - -complete -F _sf_{{ COMMAND_NAME }} {{ COMMAND_NAME }} diff --git a/lib/symfony/console/SignalRegistry/SignalRegistry.php b/lib/symfony/console/SignalRegistry/SignalRegistry.php deleted file mode 100644 index 6bee24a42..000000000 --- a/lib/symfony/console/SignalRegistry/SignalRegistry.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\SignalRegistry; - -final class SignalRegistry -{ - private $signalHandlers = []; - - public function __construct() - { - if (\function_exists('pcntl_async_signals')) { - pcntl_async_signals(true); - } - } - - public function register(int $signal, callable $signalHandler): void - { - if (!isset($this->signalHandlers[$signal])) { - $previousCallback = pcntl_signal_get_handler($signal); - - if (\is_callable($previousCallback)) { - $this->signalHandlers[$signal][] = $previousCallback; - } - } - - $this->signalHandlers[$signal][] = $signalHandler; - - pcntl_signal($signal, [$this, 'handle']); - } - - public static function isSupported(): bool - { - if (!\function_exists('pcntl_signal')) { - return false; - } - - if (\in_array('pcntl_signal', explode(',', \ini_get('disable_functions')))) { - return false; - } - - return true; - } - - /** - * @internal - */ - public function handle(int $signal): void - { - $count = \count($this->signalHandlers[$signal]); - - foreach ($this->signalHandlers[$signal] as $i => $signalHandler) { - $hasNext = $i !== $count - 1; - $signalHandler($signal, $hasNext); - } - } -} diff --git a/lib/symfony/console/SingleCommandApplication.php b/lib/symfony/console/SingleCommandApplication.php deleted file mode 100644 index e93c1821b..000000000 --- a/lib/symfony/console/SingleCommandApplication.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * @author Grégoire Pineau <lyrixx@lyrixx.info> - */ -class SingleCommandApplication extends Command -{ - private $version = 'UNKNOWN'; - private $autoExit = true; - private $running = false; - - /** - * @return $this - */ - public function setVersion(string $version): self - { - $this->version = $version; - - return $this; - } - - /** - * @final - * - * @return $this - */ - public function setAutoExit(bool $autoExit): self - { - $this->autoExit = $autoExit; - - return $this; - } - - public function run(InputInterface $input = null, OutputInterface $output = null): int - { - if ($this->running) { - return parent::run($input, $output); - } - - // We use the command name as the application name - $application = new Application($this->getName() ?: 'UNKNOWN', $this->version); - $application->setAutoExit($this->autoExit); - // Fix the usage of the command displayed with "--help" - $this->setName($_SERVER['argv'][0]); - $application->add($this); - $application->setDefaultCommand($this->getName(), true); - - $this->running = true; - try { - $ret = $application->run($input, $output); - } finally { - $this->running = false; - } - - return $ret ?? 1; - } -} diff --git a/lib/symfony/console/Style/OutputStyle.php b/lib/symfony/console/Style/OutputStyle.php deleted file mode 100644 index 67a98ff07..000000000 --- a/lib/symfony/console/Style/OutputStyle.php +++ /dev/null @@ -1,153 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\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 <kevinbond@gmail.com> - */ -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)); - } - - /** - * @return ProgressBar - */ - public function createProgressBar(int $max = 0) - { - return new ProgressBar($this->output, $max); - } - - /** - * {@inheritdoc} - */ - public function write($messages, bool $newline = false, int $type = self::OUTPUT_NORMAL) - { - $this->output->write($messages, $newline, $type); - } - - /** - * {@inheritdoc} - */ - public function writeln($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() - { - return $this->output->getVerbosity(); - } - - /** - * {@inheritdoc} - */ - public function setDecorated(bool $decorated) - { - $this->output->setDecorated($decorated); - } - - /** - * {@inheritdoc} - */ - public function isDecorated() - { - return $this->output->isDecorated(); - } - - /** - * {@inheritdoc} - */ - public function setFormatter(OutputFormatterInterface $formatter) - { - $this->output->setFormatter($formatter); - } - - /** - * {@inheritdoc} - */ - public function getFormatter() - { - return $this->output->getFormatter(); - } - - /** - * {@inheritdoc} - */ - public function isQuiet() - { - return $this->output->isQuiet(); - } - - /** - * {@inheritdoc} - */ - public function isVerbose() - { - return $this->output->isVerbose(); - } - - /** - * {@inheritdoc} - */ - public function isVeryVerbose() - { - return $this->output->isVeryVerbose(); - } - - /** - * {@inheritdoc} - */ - public function isDebug() - { - return $this->output->isDebug(); - } - - protected function getErrorOutput() - { - if (!$this->output instanceof ConsoleOutputInterface) { - return $this->output; - } - - return $this->output->getErrorOutput(); - } -} diff --git a/lib/symfony/console/Style/StyleInterface.php b/lib/symfony/console/Style/StyleInterface.php deleted file mode 100644 index 38d23b77e..000000000 --- a/lib/symfony/console/Style/StyleInterface.php +++ /dev/null @@ -1,132 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Style; - -/** - * Output style helpers. - * - * @author Kevin Bond <kevinbond@gmail.com> - */ -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. - * - * @param string|array $message - */ - public function text($message); - - /** - * Formats a success result bar. - * - * @param string|array $message - */ - public function success($message); - - /** - * Formats an error result bar. - * - * @param string|array $message - */ - public function error($message); - - /** - * Formats an warning result bar. - * - * @param string|array $message - */ - public function warning($message); - - /** - * Formats a note admonition. - * - * @param string|array $message - */ - public function note($message); - - /** - * Formats a caution admonition. - * - * @param string|array $message - */ - public function caution($message); - - /** - * Formats a table. - */ - public function table(array $headers, array $rows); - - /** - * Asks a question. - * - * @return mixed - */ - public function ask(string $question, string $default = null, callable $validator = null); - - /** - * Asks a question with the user input hidden. - * - * @return mixed - */ - public function askHidden(string $question, callable $validator = null); - - /** - * Asks for confirmation. - * - * @return bool - */ - public function confirm(string $question, bool $default = true); - - /** - * Asks a choice question. - * - * @param string|int|null $default - * - * @return mixed - */ - public function choice(string $question, array $choices, $default = null); - - /** - * 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/lib/symfony/console/Style/SymfonyStyle.php b/lib/symfony/console/Style/SymfonyStyle.php deleted file mode 100644 index e3c5ac8e7..000000000 --- a/lib/symfony/console/Style/SymfonyStyle.php +++ /dev/null @@ -1,518 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\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 <kevinbond@gmail.com> - */ -class SymfonyStyle extends OutputStyle -{ - public const MAX_LINE_LENGTH = 120; - - private $input; - private $output; - private $questionHelper; - private $progressBar; - private $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. - * - * @param string|array $messages The message to write in the block - */ - public function block($messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = true) - { - $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('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)), - sprintf('<comment>%s</>', str_repeat('=', Helper::width(Helper::removeDecoration($this->getFormatter(), $message)))), - ]); - $this->newLine(); - } - - /** - * {@inheritdoc} - */ - public function section(string $message) - { - $this->autoPrependBlock(); - $this->writeln([ - sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)), - sprintf('<comment>%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($message) - { - $this->autoPrependText(); - - $messages = \is_array($message) ? array_values($message) : [$message]; - foreach ($messages as $message) { - $this->writeln(sprintf(' %s', $message)); - } - } - - /** - * Formats a command comment. - * - * @param string|array $message - */ - public function comment($message) - { - $this->block($message, null, null, '<fg=default;bg=default> // </>', false, false); - } - - /** - * {@inheritdoc} - */ - public function success($message) - { - $this->block($message, 'OK', 'fg=black;bg=green', ' ', true); - } - - /** - * {@inheritdoc} - */ - public function error($message) - { - $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', true); - } - - /** - * {@inheritdoc} - */ - public function warning($message) - { - $this->block($message, 'WARNING', 'fg=black;bg=yellow', ' ', true); - } - - /** - * {@inheritdoc} - */ - public function note($message) - { - $this->block($message, 'NOTE', 'fg=yellow', ' ! '); - } - - /** - * Formats an info message. - * - * @param string|array $message - */ - public function info($message) - { - $this->block($message, 'INFO', 'fg=green', ' ', true); - } - - /** - * {@inheritdoc} - */ - public function caution($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() - * - * @param string|array|TableSeparator ...$list - */ - public function definitionList(...$list) - { - $headers = []; - $row = []; - foreach ($list as $value) { - if ($value instanceof TableSeparator) { - $headers[] = $value; - $row[] = $value; - continue; - } - if (\is_string($value)) { - $headers[] = new TableCell($value, ['colspan' => 2]); - $row[] = null; - continue; - } - if (!\is_array($value)) { - throw new InvalidArgumentException('Value should be an array, string, or an instance of TableSeparator.'); - } - $headers[] = key($value); - $row[] = current($value); - } - - $this->horizontalTable($headers, [$row]); - } - - /** - * {@inheritdoc} - */ - public function ask(string $question, string $default = null, callable $validator = null) - { - $question = new Question($question, $default); - $question->setValidator($validator); - - return $this->askQuestion($question); - } - - /** - * {@inheritdoc} - */ - public function askHidden(string $question, callable $validator = null) - { - $question = new Question($question); - - $question->setHidden(true); - $question->setValidator($validator); - - return $this->askQuestion($question); - } - - /** - * {@inheritdoc} - */ - public function confirm(string $question, bool $default = true) - { - return $this->askQuestion(new ConfirmationQuestion($question, $default)); - } - - /** - * {@inheritdoc} - */ - public function choice(string $question, array $choices, $default = null) - { - 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); - $this->progressBar = null; - } - - /** - * {@inheritdoc} - */ - public function createProgressBar(int $max = 0) - { - $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); - } - - /** - * @return mixed - */ - public function askQuestion(Question $question) - { - if ($this->input->isInteractive()) { - $this->autoPrependBlock(); - } - - if (!$this->questionHelper) { - $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($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($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. - * - * @return self - */ - public function getErrorStyle() - { - 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('<info>%s</info>'); - - return (new Table($output))->setStyle($style); - } - - private function getProgressBar(): ProgressBar - { - if (!$this->progressBar) { - throw new RuntimeException('The ProgressBar is not started.'); - } - - return $this->progressBar; - } - - 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/lib/symfony/console/Terminal.php b/lib/symfony/console/Terminal.php deleted file mode 100644 index 08c53535b..000000000 --- a/lib/symfony/console/Terminal.php +++ /dev/null @@ -1,172 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console; - -class Terminal -{ - private static $width; - private static $height; - private static $stty; - - /** - * Gets the terminal width. - * - * @return int - */ - public function getWidth() - { - $width = getenv('COLUMNS'); - if (false !== $width) { - return (int) trim($width); - } - - if (null === self::$width) { - self::initDimensions(); - } - - return self::$width ?: 80; - } - - /** - * Gets the terminal height. - * - * @return int - */ - public function getHeight() - { - $height = getenv('LINES'); - if (false !== $height) { - return (int) trim($height); - } - - if (null === self::$height) { - self::initDimensions(); - } - - return self::$height ?: 50; - } - - /** - * @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/lib/symfony/console/Tester/ApplicationTester.php b/lib/symfony/console/Tester/ApplicationTester.php deleted file mode 100644 index 3a262e81c..000000000 --- a/lib/symfony/console/Tester/ApplicationTester.php +++ /dev/null @@ -1,85 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\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 <fabien@symfony.com> - */ -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 = []) - { - $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/lib/symfony/console/Tester/CommandCompletionTester.php b/lib/symfony/console/Tester/CommandCompletionTester.php deleted file mode 100644 index ade732752..000000000 --- a/lib/symfony/console/Tester/CommandCompletionTester.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tester; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Completion\CompletionInput; -use Symfony\Component\Console\Completion\CompletionSuggestions; - -/** - * Eases the testing of command completion. - * - * @author Jérôme Tamarelle <jerome@tamarelle.net> - */ -class CommandCompletionTester -{ - private $command; - - public function __construct(Command $command) - { - $this->command = $command; - } - - /** - * Create completion suggestions from input tokens. - */ - public function complete(array $input): array - { - $currentIndex = \count($input); - if ('' === end($input)) { - array_pop($input); - } - array_unshift($input, $this->command->getName()); - - $completionInput = CompletionInput::fromTokens($input, $currentIndex); - $completionInput->bind($this->command->getDefinition()); - $suggestions = new CompletionSuggestions(); - - $this->command->complete($completionInput, $suggestions); - - $options = []; - foreach ($suggestions->getOptionSuggestions() as $option) { - $options[] = '--'.$option->getName(); - } - - return array_map('strval', array_merge($options, $suggestions->getValueSuggestions())); - } -} diff --git a/lib/symfony/console/Tester/CommandTester.php b/lib/symfony/console/Tester/CommandTester.php deleted file mode 100644 index 6c15c25fb..000000000 --- a/lib/symfony/console/Tester/CommandTester.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tester; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\ArrayInput; - -/** - * Eases the testing of console commands. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Robin Chalas <robin.chalas@gmail.com> - */ -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 = []) - { - // 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/lib/symfony/console/Tester/Constraint/CommandIsSuccessful.php b/lib/symfony/console/Tester/Constraint/CommandIsSuccessful.php deleted file mode 100644 index a47324237..000000000 --- a/lib/symfony/console/Tester/Constraint/CommandIsSuccessful.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\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/lib/symfony/console/Tester/TesterTrait.php b/lib/symfony/console/Tester/TesterTrait.php deleted file mode 100644 index 40bc58177..000000000 --- a/lib/symfony/console/Tester/TesterTrait.php +++ /dev/null @@ -1,197 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tester; - -use PHPUnit\Framework\Assert; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\ConsoleOutput; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Output\StreamOutput; -use Symfony\Component\Console\Tester\Constraint\CommandIsSuccessful; - -/** - * @author Amrouche Hamza <hamza.simperfit@gmail.com> - */ -trait TesterTrait -{ - /** @var StreamOutput */ - private $output; - private $inputs = []; - private $captureStreamsIndependently = false; - /** @var InputInterface */ - private $input; - /** @var int */ - private $statusCode; - - /** - * Gets the display returned by the last execution of the command or application. - * - * @throws \RuntimeException If it's called before the execute method - * - * @return string - */ - public function getDisplay(bool $normalize = false) - { - if (null === $this->output) { - throw new \RuntimeException('Output not initialized, did you execute the command before requesting the display?'); - } - - rewind($this->output->getStream()); - - $display = stream_get_contents($this->output->getStream()); - - if ($normalize) { - $display = str_replace(\PHP_EOL, "\n", $display); - } - - return $display; - } - - /** - * Gets the output written to STDERR by the application. - * - * @param bool $normalize Whether to normalize end of lines to \n or not - * - * @return string - */ - public function getErrorOutput(bool $normalize = false) - { - if (!$this->captureStreamsIndependently) { - throw new \LogicException('The error output is not available when the tester is run without "capture_stderr_separately" option set.'); - } - - rewind($this->output->getErrorOutput()->getStream()); - - $display = stream_get_contents($this->output->getErrorOutput()->getStream()); - - if ($normalize) { - $display = str_replace(\PHP_EOL, "\n", $display); - } - - return $display; - } - - /** - * Gets the input instance used by the last execution of the command or application. - * - * @return InputInterface - */ - public function getInput() - { - return $this->input; - } - - /** - * Gets the output instance used by the last execution of the command or application. - * - * @return OutputInterface - */ - public function getOutput() - { - return $this->output; - } - - /** - * Gets the status code returned by the last execution of the command or application. - * - * @throws \RuntimeException If it's called before the execute method - * - * @return int - */ - public function getStatusCode() - { - if (null === $this->statusCode) { - throw new \RuntimeException('Status code not initialized, did you execute the command before requesting the status code?'); - } - - return $this->statusCode; - } - - public function assertCommandIsSuccessful(string $message = ''): void - { - Assert::assertThat($this->statusCode, new CommandIsSuccessful(), $message); - } - - /** - * Sets the user inputs. - * - * @param array $inputs An array of strings representing each input - * passed to the command input stream - * - * @return $this - */ - public function setInputs(array $inputs) - { - $this->inputs = $inputs; - - return $this; - } - - /** - * Initializes the output property. - * - * Available options: - * - * * decorated: Sets the output decorated flag - * * verbosity: Sets the output verbosity flag - * * capture_stderr_separately: Make output of stdOut and stdErr separately available - */ - private function initOutput(array $options) - { - $this->captureStreamsIndependently = \array_key_exists('capture_stderr_separately', $options) && $options['capture_stderr_separately']; - if (!$this->captureStreamsIndependently) { - $this->output = new StreamOutput(fopen('php://memory', 'w', false)); - if (isset($options['decorated'])) { - $this->output->setDecorated($options['decorated']); - } - if (isset($options['verbosity'])) { - $this->output->setVerbosity($options['verbosity']); - } - } else { - $this->output = new ConsoleOutput( - $options['verbosity'] ?? ConsoleOutput::VERBOSITY_NORMAL, - $options['decorated'] ?? null - ); - - $errorOutput = new StreamOutput(fopen('php://memory', 'w', false)); - $errorOutput->setFormatter($this->output->getFormatter()); - $errorOutput->setVerbosity($this->output->getVerbosity()); - $errorOutput->setDecorated($this->output->isDecorated()); - - $reflectedOutput = new \ReflectionObject($this->output); - $strErrProperty = $reflectedOutput->getProperty('stderr'); - $strErrProperty->setAccessible(true); - $strErrProperty->setValue($this->output, $errorOutput); - - $reflectedParent = $reflectedOutput->getParentClass(); - $streamProperty = $reflectedParent->getProperty('stream'); - $streamProperty->setAccessible(true); - $streamProperty->setValue($this->output, fopen('php://memory', 'w', false)); - } - } - - /** - * @return resource - */ - private static function createStream(array $inputs) - { - $stream = fopen('php://memory', 'r+', false); - - foreach ($inputs as $input) { - fwrite($stream, $input.\PHP_EOL); - } - - rewind($stream); - - return $stream; - } -} diff --git a/lib/symfony/console/composer.json b/lib/symfony/console/composer.json deleted file mode 100644 index 9a565068c..000000000 --- a/lib/symfony/console/composer.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "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": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.1|^6.0" - }, - "require-dev": { - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/lock": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0", - "psr/log": "^1|^2" - }, - "provide": { - "psr/log-implementation": "1.0|2.0" - }, - "suggest": { - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "", - "psr/log": "For using the console logger" - }, - "conflict": { - "psr/log": ">=3", - "symfony/dependency-injection": "<4.4", - "symfony/dotenv": "<5.1", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\Console\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/lib/symfony/css-selector/CHANGELOG.md b/lib/symfony/css-selector/CHANGELOG.md deleted file mode 100644 index de81fa2e7..000000000 --- a/lib/symfony/css-selector/CHANGELOG.md +++ /dev/null @@ -1,18 +0,0 @@ -CHANGELOG -========= - -4.4.0 ------ - - * Added support for `*:only-of-type` - -2.8.0 ------ - - * Added the `CssSelectorConverter` class as a non-static API for the component. - * Deprecated the `CssSelector` static API of the component. - -2.1.0 ------ - - * none diff --git a/lib/symfony/css-selector/CssSelectorConverter.php b/lib/symfony/css-selector/CssSelectorConverter.php deleted file mode 100644 index bbb6afe21..000000000 --- a/lib/symfony/css-selector/CssSelectorConverter.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector; - -use Symfony\Component\CssSelector\Parser\Shortcut\ClassParser; -use Symfony\Component\CssSelector\Parser\Shortcut\ElementParser; -use Symfony\Component\CssSelector\Parser\Shortcut\EmptyStringParser; -use Symfony\Component\CssSelector\Parser\Shortcut\HashParser; -use Symfony\Component\CssSelector\XPath\Extension\HtmlExtension; -use Symfony\Component\CssSelector\XPath\Translator; - -/** - * CssSelectorConverter is the main entry point of the component and can convert CSS - * selectors to XPath expressions. - * - * @author Christophe Coevoet <stof@notk.org> - */ -class CssSelectorConverter -{ - private $translator; - private $cache; - - private static $xmlCache = []; - private static $htmlCache = []; - - /** - * @param bool $html Whether HTML support should be enabled. Disable it for XML documents - */ - public function __construct(bool $html = true) - { - $this->translator = new Translator(); - - if ($html) { - $this->translator->registerExtension(new HtmlExtension($this->translator)); - $this->cache = &self::$htmlCache; - } else { - $this->cache = &self::$xmlCache; - } - - $this->translator - ->registerParserShortcut(new EmptyStringParser()) - ->registerParserShortcut(new ElementParser()) - ->registerParserShortcut(new ClassParser()) - ->registerParserShortcut(new HashParser()) - ; - } - - /** - * Translates a CSS expression to its XPath equivalent. - * - * Optionally, a prefix can be added to the resulting XPath - * expression with the $prefix parameter. - * - * @return string - */ - public function toXPath(string $cssExpr, string $prefix = 'descendant-or-self::') - { - return $this->cache[$prefix][$cssExpr] ?? $this->cache[$prefix][$cssExpr] = $this->translator->cssToXPath($cssExpr, $prefix); - } -} diff --git a/lib/symfony/css-selector/Exception/ExceptionInterface.php b/lib/symfony/css-selector/Exception/ExceptionInterface.php deleted file mode 100644 index 9e259006b..000000000 --- a/lib/symfony/css-selector/Exception/ExceptionInterface.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Exception; - -/** - * Interface for exceptions. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - */ -interface ExceptionInterface extends \Throwable -{ -} diff --git a/lib/symfony/css-selector/Exception/ExpressionErrorException.php b/lib/symfony/css-selector/Exception/ExpressionErrorException.php deleted file mode 100644 index fd5deeabe..000000000 --- a/lib/symfony/css-selector/Exception/ExpressionErrorException.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Exception; - -/** - * ParseException is thrown when a CSS selector syntax is not valid. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - */ -class ExpressionErrorException extends ParseException -{ -} diff --git a/lib/symfony/css-selector/Exception/InternalErrorException.php b/lib/symfony/css-selector/Exception/InternalErrorException.php deleted file mode 100644 index e60e5ed0f..000000000 --- a/lib/symfony/css-selector/Exception/InternalErrorException.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Exception; - -/** - * ParseException is thrown when a CSS selector syntax is not valid. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - */ -class InternalErrorException extends ParseException -{ -} diff --git a/lib/symfony/css-selector/Exception/ParseException.php b/lib/symfony/css-selector/Exception/ParseException.php deleted file mode 100644 index 3b0b0ee8f..000000000 --- a/lib/symfony/css-selector/Exception/ParseException.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Exception; - -/** - * ParseException is thrown when a CSS selector syntax is not valid. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class ParseException extends \Exception implements ExceptionInterface -{ -} diff --git a/lib/symfony/css-selector/Exception/SyntaxErrorException.php b/lib/symfony/css-selector/Exception/SyntaxErrorException.php deleted file mode 100644 index 7deacf9c5..000000000 --- a/lib/symfony/css-selector/Exception/SyntaxErrorException.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Exception; - -use Symfony\Component\CssSelector\Parser\Token; - -/** - * ParseException is thrown when a CSS selector syntax is not valid. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - */ -class SyntaxErrorException extends ParseException -{ - /** - * @return self - */ - public static function unexpectedToken(string $expectedValue, Token $foundToken) - { - return new self(sprintf('Expected %s, but %s found.', $expectedValue, $foundToken)); - } - - /** - * @return self - */ - public static function pseudoElementFound(string $pseudoElement, string $unexpectedLocation) - { - return new self(sprintf('Unexpected pseudo-element "::%s" found %s.', $pseudoElement, $unexpectedLocation)); - } - - /** - * @return self - */ - public static function unclosedString(int $position) - { - return new self(sprintf('Unclosed/invalid string at %s.', $position)); - } - - /** - * @return self - */ - public static function nestedNot() - { - return new self('Got nested ::not().'); - } - - /** - * @return self - */ - public static function stringAsFunctionArgument() - { - return new self('String not allowed as function argument.'); - } -} diff --git a/lib/symfony/css-selector/LICENSE b/lib/symfony/css-selector/LICENSE deleted file mode 100644 index 88bf75bb4..000000000 --- a/lib/symfony/css-selector/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-2022 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -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/lib/symfony/css-selector/Node/AbstractNode.php b/lib/symfony/css-selector/Node/AbstractNode.php deleted file mode 100644 index 1306aeacb..000000000 --- a/lib/symfony/css-selector/Node/AbstractNode.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Node; - -/** - * Abstract base node class. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -abstract class AbstractNode implements NodeInterface -{ - /** - * @var string - */ - private $nodeName; - - public function getNodeName(): string - { - if (null === $this->nodeName) { - $this->nodeName = preg_replace('~.*\\\\([^\\\\]+)Node$~', '$1', static::class); - } - - return $this->nodeName; - } -} diff --git a/lib/symfony/css-selector/Node/AttributeNode.php b/lib/symfony/css-selector/Node/AttributeNode.php deleted file mode 100644 index 0b6e0ee0a..000000000 --- a/lib/symfony/css-selector/Node/AttributeNode.php +++ /dev/null @@ -1,82 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Node; - -/** - * Represents a "<selector>[<namespace>|<attribute> <operator> <value>]" node. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class AttributeNode extends AbstractNode -{ - private $selector; - private $namespace; - private $attribute; - private $operator; - private $value; - - public function __construct(NodeInterface $selector, ?string $namespace, string $attribute, string $operator, ?string $value) - { - $this->selector = $selector; - $this->namespace = $namespace; - $this->attribute = $attribute; - $this->operator = $operator; - $this->value = $value; - } - - public function getSelector(): NodeInterface - { - return $this->selector; - } - - public function getNamespace(): ?string - { - return $this->namespace; - } - - public function getAttribute(): string - { - return $this->attribute; - } - - public function getOperator(): string - { - return $this->operator; - } - - public function getValue(): ?string - { - return $this->value; - } - - /** - * {@inheritdoc} - */ - public function getSpecificity(): Specificity - { - return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0)); - } - - public function __toString(): string - { - $attribute = $this->namespace ? $this->namespace.'|'.$this->attribute : $this->attribute; - - return 'exists' === $this->operator - ? sprintf('%s[%s[%s]]', $this->getNodeName(), $this->selector, $attribute) - : sprintf("%s[%s[%s %s '%s']]", $this->getNodeName(), $this->selector, $attribute, $this->operator, $this->value); - } -} diff --git a/lib/symfony/css-selector/Node/ClassNode.php b/lib/symfony/css-selector/Node/ClassNode.php deleted file mode 100644 index 1efca808d..000000000 --- a/lib/symfony/css-selector/Node/ClassNode.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Node; - -/** - * Represents a "<selector>.<name>" node. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class ClassNode extends AbstractNode -{ - private $selector; - private $name; - - public function __construct(NodeInterface $selector, string $name) - { - $this->selector = $selector; - $this->name = $name; - } - - public function getSelector(): NodeInterface - { - return $this->selector; - } - - public function getName(): string - { - return $this->name; - } - - /** - * {@inheritdoc} - */ - public function getSpecificity(): Specificity - { - return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0)); - } - - public function __toString(): string - { - return sprintf('%s[%s.%s]', $this->getNodeName(), $this->selector, $this->name); - } -} diff --git a/lib/symfony/css-selector/Node/CombinedSelectorNode.php b/lib/symfony/css-selector/Node/CombinedSelectorNode.php deleted file mode 100644 index a217a45ed..000000000 --- a/lib/symfony/css-selector/Node/CombinedSelectorNode.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Node; - -/** - * Represents a combined node. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class CombinedSelectorNode extends AbstractNode -{ - private $selector; - private $combinator; - private $subSelector; - - public function __construct(NodeInterface $selector, string $combinator, NodeInterface $subSelector) - { - $this->selector = $selector; - $this->combinator = $combinator; - $this->subSelector = $subSelector; - } - - public function getSelector(): NodeInterface - { - return $this->selector; - } - - public function getCombinator(): string - { - return $this->combinator; - } - - public function getSubSelector(): NodeInterface - { - return $this->subSelector; - } - - /** - * {@inheritdoc} - */ - public function getSpecificity(): Specificity - { - return $this->selector->getSpecificity()->plus($this->subSelector->getSpecificity()); - } - - public function __toString(): string - { - $combinator = ' ' === $this->combinator ? '<followed>' : $this->combinator; - - return sprintf('%s[%s %s %s]', $this->getNodeName(), $this->selector, $combinator, $this->subSelector); - } -} diff --git a/lib/symfony/css-selector/Node/ElementNode.php b/lib/symfony/css-selector/Node/ElementNode.php deleted file mode 100644 index fbf8ea0f9..000000000 --- a/lib/symfony/css-selector/Node/ElementNode.php +++ /dev/null @@ -1,59 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Node; - -/** - * Represents a "<namespace>|<element>" node. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class ElementNode extends AbstractNode -{ - private $namespace; - private $element; - - public function __construct(string $namespace = null, string $element = null) - { - $this->namespace = $namespace; - $this->element = $element; - } - - public function getNamespace(): ?string - { - return $this->namespace; - } - - public function getElement(): ?string - { - return $this->element; - } - - /** - * {@inheritdoc} - */ - public function getSpecificity(): Specificity - { - return new Specificity(0, 0, $this->element ? 1 : 0); - } - - public function __toString(): string - { - $element = $this->element ?: '*'; - - return sprintf('%s[%s]', $this->getNodeName(), $this->namespace ? $this->namespace.'|'.$element : $element); - } -} diff --git a/lib/symfony/css-selector/Node/FunctionNode.php b/lib/symfony/css-selector/Node/FunctionNode.php deleted file mode 100644 index c464cf7c0..000000000 --- a/lib/symfony/css-selector/Node/FunctionNode.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Node; - -use Symfony\Component\CssSelector\Parser\Token; - -/** - * Represents a "<selector>:<name>(<arguments>)" node. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class FunctionNode extends AbstractNode -{ - private $selector; - private $name; - private $arguments; - - /** - * @param Token[] $arguments - */ - public function __construct(NodeInterface $selector, string $name, array $arguments = []) - { - $this->selector = $selector; - $this->name = strtolower($name); - $this->arguments = $arguments; - } - - public function getSelector(): NodeInterface - { - return $this->selector; - } - - public function getName(): string - { - return $this->name; - } - - /** - * @return Token[] - */ - public function getArguments(): array - { - return $this->arguments; - } - - /** - * {@inheritdoc} - */ - public function getSpecificity(): Specificity - { - return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0)); - } - - public function __toString(): string - { - $arguments = implode(', ', array_map(function (Token $token) { - return "'".$token->getValue()."'"; - }, $this->arguments)); - - return sprintf('%s[%s:%s(%s)]', $this->getNodeName(), $this->selector, $this->name, $arguments ? '['.$arguments.']' : ''); - } -} diff --git a/lib/symfony/css-selector/Node/HashNode.php b/lib/symfony/css-selector/Node/HashNode.php deleted file mode 100644 index 94114c095..000000000 --- a/lib/symfony/css-selector/Node/HashNode.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Node; - -/** - * Represents a "<selector>#<id>" node. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class HashNode extends AbstractNode -{ - private $selector; - private $id; - - public function __construct(NodeInterface $selector, string $id) - { - $this->selector = $selector; - $this->id = $id; - } - - public function getSelector(): NodeInterface - { - return $this->selector; - } - - public function getId(): string - { - return $this->id; - } - - /** - * {@inheritdoc} - */ - public function getSpecificity(): Specificity - { - return $this->selector->getSpecificity()->plus(new Specificity(1, 0, 0)); - } - - public function __toString(): string - { - return sprintf('%s[%s#%s]', $this->getNodeName(), $this->selector, $this->id); - } -} diff --git a/lib/symfony/css-selector/Node/NegationNode.php b/lib/symfony/css-selector/Node/NegationNode.php deleted file mode 100644 index f00522fb9..000000000 --- a/lib/symfony/css-selector/Node/NegationNode.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Node; - -/** - * Represents a "<selector>:not(<identifier>)" node. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class NegationNode extends AbstractNode -{ - private $selector; - private $subSelector; - - public function __construct(NodeInterface $selector, NodeInterface $subSelector) - { - $this->selector = $selector; - $this->subSelector = $subSelector; - } - - public function getSelector(): NodeInterface - { - return $this->selector; - } - - public function getSubSelector(): NodeInterface - { - return $this->subSelector; - } - - /** - * {@inheritdoc} - */ - public function getSpecificity(): Specificity - { - return $this->selector->getSpecificity()->plus($this->subSelector->getSpecificity()); - } - - public function __toString(): string - { - return sprintf('%s[%s:not(%s)]', $this->getNodeName(), $this->selector, $this->subSelector); - } -} diff --git a/lib/symfony/css-selector/Node/NodeInterface.php b/lib/symfony/css-selector/Node/NodeInterface.php deleted file mode 100644 index b078d26d4..000000000 --- a/lib/symfony/css-selector/Node/NodeInterface.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Node; - -/** - * Interface for nodes. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -interface NodeInterface -{ - public function getNodeName(): string; - - public function getSpecificity(): Specificity; - - public function __toString(): string; -} diff --git a/lib/symfony/css-selector/Node/PseudoNode.php b/lib/symfony/css-selector/Node/PseudoNode.php deleted file mode 100644 index 12b7bd266..000000000 --- a/lib/symfony/css-selector/Node/PseudoNode.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Node; - -/** - * Represents a "<selector>:<identifier>" node. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class PseudoNode extends AbstractNode -{ - private $selector; - private $identifier; - - public function __construct(NodeInterface $selector, string $identifier) - { - $this->selector = $selector; - $this->identifier = strtolower($identifier); - } - - public function getSelector(): NodeInterface - { - return $this->selector; - } - - public function getIdentifier(): string - { - return $this->identifier; - } - - /** - * {@inheritdoc} - */ - public function getSpecificity(): Specificity - { - return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0)); - } - - public function __toString(): string - { - return sprintf('%s[%s:%s]', $this->getNodeName(), $this->selector, $this->identifier); - } -} diff --git a/lib/symfony/css-selector/Node/SelectorNode.php b/lib/symfony/css-selector/Node/SelectorNode.php deleted file mode 100644 index 6e52b2fa7..000000000 --- a/lib/symfony/css-selector/Node/SelectorNode.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Node; - -/** - * Represents a "<selector>(::|:)<pseudoElement>" node. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class SelectorNode extends AbstractNode -{ - private $tree; - private $pseudoElement; - - public function __construct(NodeInterface $tree, string $pseudoElement = null) - { - $this->tree = $tree; - $this->pseudoElement = $pseudoElement ? strtolower($pseudoElement) : null; - } - - public function getTree(): NodeInterface - { - return $this->tree; - } - - public function getPseudoElement(): ?string - { - return $this->pseudoElement; - } - - /** - * {@inheritdoc} - */ - public function getSpecificity(): Specificity - { - return $this->tree->getSpecificity()->plus(new Specificity(0, 0, $this->pseudoElement ? 1 : 0)); - } - - public function __toString(): string - { - return sprintf('%s[%s%s]', $this->getNodeName(), $this->tree, $this->pseudoElement ? '::'.$this->pseudoElement : ''); - } -} diff --git a/lib/symfony/css-selector/Node/Specificity.php b/lib/symfony/css-selector/Node/Specificity.php deleted file mode 100644 index b00f6d281..000000000 --- a/lib/symfony/css-selector/Node/Specificity.php +++ /dev/null @@ -1,73 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Node; - -/** - * Represents a node specificity. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @see http://www.w3.org/TR/selectors/#specificity - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class Specificity -{ - public const A_FACTOR = 100; - public const B_FACTOR = 10; - public const C_FACTOR = 1; - - private $a; - private $b; - private $c; - - public function __construct(int $a, int $b, int $c) - { - $this->a = $a; - $this->b = $b; - $this->c = $c; - } - - public function plus(self $specificity): self - { - return new self($this->a + $specificity->a, $this->b + $specificity->b, $this->c + $specificity->c); - } - - public function getValue(): int - { - return $this->a * self::A_FACTOR + $this->b * self::B_FACTOR + $this->c * self::C_FACTOR; - } - - /** - * Returns -1 if the object specificity is lower than the argument, - * 0 if they are equal, and 1 if the argument is lower. - */ - public function compareTo(self $specificity): int - { - if ($this->a !== $specificity->a) { - return $this->a > $specificity->a ? 1 : -1; - } - - if ($this->b !== $specificity->b) { - return $this->b > $specificity->b ? 1 : -1; - } - - if ($this->c !== $specificity->c) { - return $this->c > $specificity->c ? 1 : -1; - } - - return 0; - } -} diff --git a/lib/symfony/css-selector/Parser/Handler/CommentHandler.php b/lib/symfony/css-selector/Parser/Handler/CommentHandler.php deleted file mode 100644 index 93f318844..000000000 --- a/lib/symfony/css-selector/Parser/Handler/CommentHandler.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Parser\Handler; - -use Symfony\Component\CssSelector\Parser\Reader; -use Symfony\Component\CssSelector\Parser\TokenStream; - -/** - * CSS selector comment handler. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class CommentHandler implements HandlerInterface -{ - /** - * {@inheritdoc} - */ - public function handle(Reader $reader, TokenStream $stream): bool - { - if ('/*' !== $reader->getSubstring(2)) { - return false; - } - - $offset = $reader->getOffset('*/'); - - if (false === $offset) { - $reader->moveToEnd(); - } else { - $reader->moveForward($offset + 2); - } - - return true; - } -} diff --git a/lib/symfony/css-selector/Parser/Handler/HandlerInterface.php b/lib/symfony/css-selector/Parser/Handler/HandlerInterface.php deleted file mode 100644 index 9ec714d54..000000000 --- a/lib/symfony/css-selector/Parser/Handler/HandlerInterface.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Parser\Handler; - -use Symfony\Component\CssSelector\Parser\Reader; -use Symfony\Component\CssSelector\Parser\TokenStream; - -/** - * CSS selector handler interface. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -interface HandlerInterface -{ - public function handle(Reader $reader, TokenStream $stream): bool; -} diff --git a/lib/symfony/css-selector/Parser/Handler/HashHandler.php b/lib/symfony/css-selector/Parser/Handler/HashHandler.php deleted file mode 100644 index 7ae9b438c..000000000 --- a/lib/symfony/css-selector/Parser/Handler/HashHandler.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Parser\Handler; - -use Symfony\Component\CssSelector\Parser\Reader; -use Symfony\Component\CssSelector\Parser\Token; -use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping; -use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; -use Symfony\Component\CssSelector\Parser\TokenStream; - -/** - * CSS selector comment handler. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class HashHandler implements HandlerInterface -{ - private $patterns; - private $escaping; - - public function __construct(TokenizerPatterns $patterns, TokenizerEscaping $escaping) - { - $this->patterns = $patterns; - $this->escaping = $escaping; - } - - /** - * {@inheritdoc} - */ - public function handle(Reader $reader, TokenStream $stream): bool - { - $match = $reader->findPattern($this->patterns->getHashPattern()); - - if (!$match) { - return false; - } - - $value = $this->escaping->escapeUnicode($match[1]); - $stream->push(new Token(Token::TYPE_HASH, $value, $reader->getPosition())); - $reader->moveForward(\strlen($match[0])); - - return true; - } -} diff --git a/lib/symfony/css-selector/Parser/Handler/IdentifierHandler.php b/lib/symfony/css-selector/Parser/Handler/IdentifierHandler.php deleted file mode 100644 index 7b2a14e2c..000000000 --- a/lib/symfony/css-selector/Parser/Handler/IdentifierHandler.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Parser\Handler; - -use Symfony\Component\CssSelector\Parser\Reader; -use Symfony\Component\CssSelector\Parser\Token; -use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping; -use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; -use Symfony\Component\CssSelector\Parser\TokenStream; - -/** - * CSS selector comment handler. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class IdentifierHandler implements HandlerInterface -{ - private $patterns; - private $escaping; - - public function __construct(TokenizerPatterns $patterns, TokenizerEscaping $escaping) - { - $this->patterns = $patterns; - $this->escaping = $escaping; - } - - /** - * {@inheritdoc} - */ - public function handle(Reader $reader, TokenStream $stream): bool - { - $match = $reader->findPattern($this->patterns->getIdentifierPattern()); - - if (!$match) { - return false; - } - - $value = $this->escaping->escapeUnicode($match[0]); - $stream->push(new Token(Token::TYPE_IDENTIFIER, $value, $reader->getPosition())); - $reader->moveForward(\strlen($match[0])); - - return true; - } -} diff --git a/lib/symfony/css-selector/Parser/Handler/NumberHandler.php b/lib/symfony/css-selector/Parser/Handler/NumberHandler.php deleted file mode 100644 index 8291a68d1..000000000 --- a/lib/symfony/css-selector/Parser/Handler/NumberHandler.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Parser\Handler; - -use Symfony\Component\CssSelector\Parser\Reader; -use Symfony\Component\CssSelector\Parser\Token; -use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; -use Symfony\Component\CssSelector\Parser\TokenStream; - -/** - * CSS selector comment handler. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class NumberHandler implements HandlerInterface -{ - private $patterns; - - public function __construct(TokenizerPatterns $patterns) - { - $this->patterns = $patterns; - } - - /** - * {@inheritdoc} - */ - public function handle(Reader $reader, TokenStream $stream): bool - { - $match = $reader->findPattern($this->patterns->getNumberPattern()); - - if (!$match) { - return false; - } - - $stream->push(new Token(Token::TYPE_NUMBER, $match[0], $reader->getPosition())); - $reader->moveForward(\strlen($match[0])); - - return true; - } -} diff --git a/lib/symfony/css-selector/Parser/Handler/StringHandler.php b/lib/symfony/css-selector/Parser/Handler/StringHandler.php deleted file mode 100644 index 6ce83cdc9..000000000 --- a/lib/symfony/css-selector/Parser/Handler/StringHandler.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Parser\Handler; - -use Symfony\Component\CssSelector\Exception\InternalErrorException; -use Symfony\Component\CssSelector\Exception\SyntaxErrorException; -use Symfony\Component\CssSelector\Parser\Reader; -use Symfony\Component\CssSelector\Parser\Token; -use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping; -use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; -use Symfony\Component\CssSelector\Parser\TokenStream; - -/** - * CSS selector comment handler. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class StringHandler implements HandlerInterface -{ - private $patterns; - private $escaping; - - public function __construct(TokenizerPatterns $patterns, TokenizerEscaping $escaping) - { - $this->patterns = $patterns; - $this->escaping = $escaping; - } - - /** - * {@inheritdoc} - */ - public function handle(Reader $reader, TokenStream $stream): bool - { - $quote = $reader->getSubstring(1); - - if (!\in_array($quote, ["'", '"'])) { - return false; - } - - $reader->moveForward(1); - $match = $reader->findPattern($this->patterns->getQuotedStringPattern($quote)); - - if (!$match) { - throw new InternalErrorException(sprintf('Should have found at least an empty match at %d.', $reader->getPosition())); - } - - // check unclosed strings - if (\strlen($match[0]) === $reader->getRemainingLength()) { - throw SyntaxErrorException::unclosedString($reader->getPosition() - 1); - } - - // check quotes pairs validity - if ($quote !== $reader->getSubstring(1, \strlen($match[0]))) { - throw SyntaxErrorException::unclosedString($reader->getPosition() - 1); - } - - $string = $this->escaping->escapeUnicodeAndNewLine($match[0]); - $stream->push(new Token(Token::TYPE_STRING, $string, $reader->getPosition())); - $reader->moveForward(\strlen($match[0]) + 1); - - return true; - } -} diff --git a/lib/symfony/css-selector/Parser/Handler/WhitespaceHandler.php b/lib/symfony/css-selector/Parser/Handler/WhitespaceHandler.php deleted file mode 100644 index 21345e32c..000000000 --- a/lib/symfony/css-selector/Parser/Handler/WhitespaceHandler.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Parser\Handler; - -use Symfony\Component\CssSelector\Parser\Reader; -use Symfony\Component\CssSelector\Parser\Token; -use Symfony\Component\CssSelector\Parser\TokenStream; - -/** - * CSS selector whitespace handler. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class WhitespaceHandler implements HandlerInterface -{ - /** - * {@inheritdoc} - */ - public function handle(Reader $reader, TokenStream $stream): bool - { - $match = $reader->findPattern('~^[ \t\r\n\f]+~'); - - if (false === $match) { - return false; - } - - $stream->push(new Token(Token::TYPE_WHITESPACE, $match[0], $reader->getPosition())); - $reader->moveForward(\strlen($match[0])); - - return true; - } -} diff --git a/lib/symfony/css-selector/Parser/Parser.php b/lib/symfony/css-selector/Parser/Parser.php deleted file mode 100644 index d73489edf..000000000 --- a/lib/symfony/css-selector/Parser/Parser.php +++ /dev/null @@ -1,353 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Parser; - -use Symfony\Component\CssSelector\Exception\SyntaxErrorException; -use Symfony\Component\CssSelector\Node; -use Symfony\Component\CssSelector\Parser\Tokenizer\Tokenizer; - -/** - * CSS selector parser. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class Parser implements ParserInterface -{ - private $tokenizer; - - public function __construct(Tokenizer $tokenizer = null) - { - $this->tokenizer = $tokenizer ?? new Tokenizer(); - } - - /** - * {@inheritdoc} - */ - public function parse(string $source): array - { - $reader = new Reader($source); - $stream = $this->tokenizer->tokenize($reader); - - return $this->parseSelectorList($stream); - } - - /** - * Parses the arguments for ":nth-child()" and friends. - * - * @param Token[] $tokens - * - * @throws SyntaxErrorException - */ - public static function parseSeries(array $tokens): array - { - foreach ($tokens as $token) { - if ($token->isString()) { - throw SyntaxErrorException::stringAsFunctionArgument(); - } - } - - $joined = trim(implode('', array_map(function (Token $token) { - return $token->getValue(); - }, $tokens))); - - $int = function ($string) { - if (!is_numeric($string)) { - throw SyntaxErrorException::stringAsFunctionArgument(); - } - - return (int) $string; - }; - - switch (true) { - case 'odd' === $joined: - return [2, 1]; - case 'even' === $joined: - return [2, 0]; - case 'n' === $joined: - return [1, 0]; - case !str_contains($joined, 'n'): - return [0, $int($joined)]; - } - - $split = explode('n', $joined); - $first = $split[0] ?? null; - - return [ - $first ? ('-' === $first || '+' === $first ? $int($first.'1') : $int($first)) : 1, - isset($split[1]) && $split[1] ? $int($split[1]) : 0, - ]; - } - - private function parseSelectorList(TokenStream $stream): array - { - $stream->skipWhitespace(); - $selectors = []; - - while (true) { - $selectors[] = $this->parserSelectorNode($stream); - - if ($stream->getPeek()->isDelimiter([','])) { - $stream->getNext(); - $stream->skipWhitespace(); - } else { - break; - } - } - - return $selectors; - } - - private function parserSelectorNode(TokenStream $stream): Node\SelectorNode - { - [$result, $pseudoElement] = $this->parseSimpleSelector($stream); - - while (true) { - $stream->skipWhitespace(); - $peek = $stream->getPeek(); - - if ($peek->isFileEnd() || $peek->isDelimiter([','])) { - break; - } - - if (null !== $pseudoElement) { - throw SyntaxErrorException::pseudoElementFound($pseudoElement, 'not at the end of a selector'); - } - - if ($peek->isDelimiter(['+', '>', '~'])) { - $combinator = $stream->getNext()->getValue(); - $stream->skipWhitespace(); - } else { - $combinator = ' '; - } - - [$nextSelector, $pseudoElement] = $this->parseSimpleSelector($stream); - $result = new Node\CombinedSelectorNode($result, $combinator, $nextSelector); - } - - return new Node\SelectorNode($result, $pseudoElement); - } - - /** - * Parses next simple node (hash, class, pseudo, negation). - * - * @throws SyntaxErrorException - */ - private function parseSimpleSelector(TokenStream $stream, bool $insideNegation = false): array - { - $stream->skipWhitespace(); - - $selectorStart = \count($stream->getUsed()); - $result = $this->parseElementNode($stream); - $pseudoElement = null; - - while (true) { - $peek = $stream->getPeek(); - if ($peek->isWhitespace() - || $peek->isFileEnd() - || $peek->isDelimiter([',', '+', '>', '~']) - || ($insideNegation && $peek->isDelimiter([')'])) - ) { - break; - } - - if (null !== $pseudoElement) { - throw SyntaxErrorException::pseudoElementFound($pseudoElement, 'not at the end of a selector'); - } - - if ($peek->isHash()) { - $result = new Node\HashNode($result, $stream->getNext()->getValue()); - } elseif ($peek->isDelimiter(['.'])) { - $stream->getNext(); - $result = new Node\ClassNode($result, $stream->getNextIdentifier()); - } elseif ($peek->isDelimiter(['['])) { - $stream->getNext(); - $result = $this->parseAttributeNode($result, $stream); - } elseif ($peek->isDelimiter([':'])) { - $stream->getNext(); - - if ($stream->getPeek()->isDelimiter([':'])) { - $stream->getNext(); - $pseudoElement = $stream->getNextIdentifier(); - - continue; - } - - $identifier = $stream->getNextIdentifier(); - if (\in_array(strtolower($identifier), ['first-line', 'first-letter', 'before', 'after'])) { - // Special case: CSS 2.1 pseudo-elements can have a single ':'. - // Any new pseudo-element must have two. - $pseudoElement = $identifier; - - continue; - } - - if (!$stream->getPeek()->isDelimiter(['('])) { - $result = new Node\PseudoNode($result, $identifier); - - continue; - } - - $stream->getNext(); - $stream->skipWhitespace(); - - if ('not' === strtolower($identifier)) { - if ($insideNegation) { - throw SyntaxErrorException::nestedNot(); - } - - [$argument, $argumentPseudoElement] = $this->parseSimpleSelector($stream, true); - $next = $stream->getNext(); - - if (null !== $argumentPseudoElement) { - throw SyntaxErrorException::pseudoElementFound($argumentPseudoElement, 'inside ::not()'); - } - - if (!$next->isDelimiter([')'])) { - throw SyntaxErrorException::unexpectedToken('")"', $next); - } - - $result = new Node\NegationNode($result, $argument); - } else { - $arguments = []; - $next = null; - - while (true) { - $stream->skipWhitespace(); - $next = $stream->getNext(); - - if ($next->isIdentifier() - || $next->isString() - || $next->isNumber() - || $next->isDelimiter(['+', '-']) - ) { - $arguments[] = $next; - } elseif ($next->isDelimiter([')'])) { - break; - } else { - throw SyntaxErrorException::unexpectedToken('an argument', $next); - } - } - - if (empty($arguments)) { - throw SyntaxErrorException::unexpectedToken('at least one argument', $next); - } - - $result = new Node\FunctionNode($result, $identifier, $arguments); - } - } else { - throw SyntaxErrorException::unexpectedToken('selector', $peek); - } - } - - if (\count($stream->getUsed()) === $selectorStart) { - throw SyntaxErrorException::unexpectedToken('selector', $stream->getPeek()); - } - - return [$result, $pseudoElement]; - } - - private function parseElementNode(TokenStream $stream): Node\ElementNode - { - $peek = $stream->getPeek(); - - if ($peek->isIdentifier() || $peek->isDelimiter(['*'])) { - if ($peek->isIdentifier()) { - $namespace = $stream->getNext()->getValue(); - } else { - $stream->getNext(); - $namespace = null; - } - - if ($stream->getPeek()->isDelimiter(['|'])) { - $stream->getNext(); - $element = $stream->getNextIdentifierOrStar(); - } else { - $element = $namespace; - $namespace = null; - } - } else { - $element = $namespace = null; - } - - return new Node\ElementNode($namespace, $element); - } - - private function parseAttributeNode(Node\NodeInterface $selector, TokenStream $stream): Node\AttributeNode - { - $stream->skipWhitespace(); - $attribute = $stream->getNextIdentifierOrStar(); - - if (null === $attribute && !$stream->getPeek()->isDelimiter(['|'])) { - throw SyntaxErrorException::unexpectedToken('"|"', $stream->getPeek()); - } - - if ($stream->getPeek()->isDelimiter(['|'])) { - $stream->getNext(); - - if ($stream->getPeek()->isDelimiter(['='])) { - $namespace = null; - $stream->getNext(); - $operator = '|='; - } else { - $namespace = $attribute; - $attribute = $stream->getNextIdentifier(); - $operator = null; - } - } else { - $namespace = $operator = null; - } - - if (null === $operator) { - $stream->skipWhitespace(); - $next = $stream->getNext(); - - if ($next->isDelimiter([']'])) { - return new Node\AttributeNode($selector, $namespace, $attribute, 'exists', null); - } elseif ($next->isDelimiter(['='])) { - $operator = '='; - } elseif ($next->isDelimiter(['^', '$', '*', '~', '|', '!']) - && $stream->getPeek()->isDelimiter(['=']) - ) { - $operator = $next->getValue().'='; - $stream->getNext(); - } else { - throw SyntaxErrorException::unexpectedToken('operator', $next); - } - } - - $stream->skipWhitespace(); - $value = $stream->getNext(); - - if ($value->isNumber()) { - // if the value is a number, it's casted into a string - $value = new Token(Token::TYPE_STRING, (string) $value->getValue(), $value->getPosition()); - } - - if (!($value->isIdentifier() || $value->isString())) { - throw SyntaxErrorException::unexpectedToken('string or identifier', $value); - } - - $stream->skipWhitespace(); - $next = $stream->getNext(); - - if (!$next->isDelimiter([']'])) { - throw SyntaxErrorException::unexpectedToken('"]"', $next); - } - - return new Node\AttributeNode($selector, $namespace, $attribute, $operator, $value->getValue()); - } -} diff --git a/lib/symfony/css-selector/Parser/ParserInterface.php b/lib/symfony/css-selector/Parser/ParserInterface.php deleted file mode 100644 index 51c3d9350..000000000 --- a/lib/symfony/css-selector/Parser/ParserInterface.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Parser; - -use Symfony\Component\CssSelector\Node\SelectorNode; - -/** - * CSS selector parser interface. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -interface ParserInterface -{ - /** - * Parses given selector source into an array of tokens. - * - * @return SelectorNode[] - */ - public function parse(string $source): array; -} diff --git a/lib/symfony/css-selector/Parser/Reader.php b/lib/symfony/css-selector/Parser/Reader.php deleted file mode 100644 index 4b43effed..000000000 --- a/lib/symfony/css-selector/Parser/Reader.php +++ /dev/null @@ -1,86 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Parser; - -/** - * CSS selector reader. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class Reader -{ - private $source; - private $length; - private $position = 0; - - public function __construct(string $source) - { - $this->source = $source; - $this->length = \strlen($source); - } - - public function isEOF(): bool - { - return $this->position >= $this->length; - } - - public function getPosition(): int - { - return $this->position; - } - - public function getRemainingLength(): int - { - return $this->length - $this->position; - } - - public function getSubstring(int $length, int $offset = 0): string - { - return substr($this->source, $this->position + $offset, $length); - } - - public function getOffset(string $string) - { - $position = strpos($this->source, $string, $this->position); - - return false === $position ? false : $position - $this->position; - } - - /** - * @return array|false - */ - public function findPattern(string $pattern) - { - $source = substr($this->source, $this->position); - - if (preg_match($pattern, $source, $matches)) { - return $matches; - } - - return false; - } - - public function moveForward(int $length) - { - $this->position += $length; - } - - public function moveToEnd() - { - $this->position = $this->length; - } -} diff --git a/lib/symfony/css-selector/Parser/Shortcut/ClassParser.php b/lib/symfony/css-selector/Parser/Shortcut/ClassParser.php deleted file mode 100644 index 17fa8c27e..000000000 --- a/lib/symfony/css-selector/Parser/Shortcut/ClassParser.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Parser\Shortcut; - -use Symfony\Component\CssSelector\Node\ClassNode; -use Symfony\Component\CssSelector\Node\ElementNode; -use Symfony\Component\CssSelector\Node\SelectorNode; -use Symfony\Component\CssSelector\Parser\ParserInterface; - -/** - * CSS selector class parser shortcut. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class ClassParser implements ParserInterface -{ - /** - * {@inheritdoc} - */ - public function parse(string $source): array - { - // Matches an optional namespace, optional element, and required class - // $source = 'test|input.ab6bd_field'; - // $matches = array (size=4) - // 0 => string 'test|input.ab6bd_field' (length=22) - // 1 => string 'test' (length=4) - // 2 => string 'input' (length=5) - // 3 => string 'ab6bd_field' (length=11) - if (preg_match('/^(?:([a-z]++)\|)?+([\w-]++|\*)?+\.([\w-]++)$/i', trim($source), $matches)) { - return [ - new SelectorNode(new ClassNode(new ElementNode($matches[1] ?: null, $matches[2] ?: null), $matches[3])), - ]; - } - - return []; - } -} diff --git a/lib/symfony/css-selector/Parser/Shortcut/ElementParser.php b/lib/symfony/css-selector/Parser/Shortcut/ElementParser.php deleted file mode 100644 index 8b9a86386..000000000 --- a/lib/symfony/css-selector/Parser/Shortcut/ElementParser.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Parser\Shortcut; - -use Symfony\Component\CssSelector\Node\ElementNode; -use Symfony\Component\CssSelector\Node\SelectorNode; -use Symfony\Component\CssSelector\Parser\ParserInterface; - -/** - * CSS selector element parser shortcut. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class ElementParser implements ParserInterface -{ - /** - * {@inheritdoc} - */ - public function parse(string $source): array - { - // Matches an optional namespace, required element or `*` - // $source = 'testns|testel'; - // $matches = array (size=3) - // 0 => string 'testns|testel' (length=13) - // 1 => string 'testns' (length=6) - // 2 => string 'testel' (length=6) - if (preg_match('/^(?:([a-z]++)\|)?([\w-]++|\*)$/i', trim($source), $matches)) { - return [new SelectorNode(new ElementNode($matches[1] ?: null, $matches[2]))]; - } - - return []; - } -} diff --git a/lib/symfony/css-selector/Parser/Shortcut/EmptyStringParser.php b/lib/symfony/css-selector/Parser/Shortcut/EmptyStringParser.php deleted file mode 100644 index 222df5cd2..000000000 --- a/lib/symfony/css-selector/Parser/Shortcut/EmptyStringParser.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Parser\Shortcut; - -use Symfony\Component\CssSelector\Node\ElementNode; -use Symfony\Component\CssSelector\Node\SelectorNode; -use Symfony\Component\CssSelector\Parser\ParserInterface; - -/** - * CSS selector class parser shortcut. - * - * This shortcut ensure compatibility with previous version. - * - The parser fails to parse an empty string. - * - In the previous version, an empty string matches each tags. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class EmptyStringParser implements ParserInterface -{ - /** - * {@inheritdoc} - */ - public function parse(string $source): array - { - // Matches an empty string - if ('' == $source) { - return [new SelectorNode(new ElementNode(null, '*'))]; - } - - return []; - } -} diff --git a/lib/symfony/css-selector/Parser/Shortcut/HashParser.php b/lib/symfony/css-selector/Parser/Shortcut/HashParser.php deleted file mode 100644 index fb07ee6cf..000000000 --- a/lib/symfony/css-selector/Parser/Shortcut/HashParser.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Parser\Shortcut; - -use Symfony\Component\CssSelector\Node\ElementNode; -use Symfony\Component\CssSelector\Node\HashNode; -use Symfony\Component\CssSelector\Node\SelectorNode; -use Symfony\Component\CssSelector\Parser\ParserInterface; - -/** - * CSS selector hash parser shortcut. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class HashParser implements ParserInterface -{ - /** - * {@inheritdoc} - */ - public function parse(string $source): array - { - // Matches an optional namespace, optional element, and required id - // $source = 'test|input#ab6bd_field'; - // $matches = array (size=4) - // 0 => string 'test|input#ab6bd_field' (length=22) - // 1 => string 'test' (length=4) - // 2 => string 'input' (length=5) - // 3 => string 'ab6bd_field' (length=11) - if (preg_match('/^(?:([a-z]++)\|)?+([\w-]++|\*)?+#([\w-]++)$/i', trim($source), $matches)) { - return [ - new SelectorNode(new HashNode(new ElementNode($matches[1] ?: null, $matches[2] ?: null), $matches[3])), - ]; - } - - return []; - } -} diff --git a/lib/symfony/css-selector/Parser/Token.php b/lib/symfony/css-selector/Parser/Token.php deleted file mode 100644 index a053203c0..000000000 --- a/lib/symfony/css-selector/Parser/Token.php +++ /dev/null @@ -1,111 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Parser; - -/** - * CSS selector token. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class Token -{ - public const TYPE_FILE_END = 'eof'; - public const TYPE_DELIMITER = 'delimiter'; - public const TYPE_WHITESPACE = 'whitespace'; - public const TYPE_IDENTIFIER = 'identifier'; - public const TYPE_HASH = 'hash'; - public const TYPE_NUMBER = 'number'; - public const TYPE_STRING = 'string'; - - private $type; - private $value; - private $position; - - public function __construct(?string $type, ?string $value, ?int $position) - { - $this->type = $type; - $this->value = $value; - $this->position = $position; - } - - public function getType(): ?int - { - return $this->type; - } - - public function getValue(): ?string - { - return $this->value; - } - - public function getPosition(): ?int - { - return $this->position; - } - - public function isFileEnd(): bool - { - return self::TYPE_FILE_END === $this->type; - } - - public function isDelimiter(array $values = []): bool - { - if (self::TYPE_DELIMITER !== $this->type) { - return false; - } - - if (empty($values)) { - return true; - } - - return \in_array($this->value, $values); - } - - public function isWhitespace(): bool - { - return self::TYPE_WHITESPACE === $this->type; - } - - public function isIdentifier(): bool - { - return self::TYPE_IDENTIFIER === $this->type; - } - - public function isHash(): bool - { - return self::TYPE_HASH === $this->type; - } - - public function isNumber(): bool - { - return self::TYPE_NUMBER === $this->type; - } - - public function isString(): bool - { - return self::TYPE_STRING === $this->type; - } - - public function __toString(): string - { - if ($this->value) { - return sprintf('<%s "%s" at %s>', $this->type, $this->value, $this->position); - } - - return sprintf('<%s at %s>', $this->type, $this->position); - } -} diff --git a/lib/symfony/css-selector/Parser/TokenStream.php b/lib/symfony/css-selector/Parser/TokenStream.php deleted file mode 100644 index 2085f2dd7..000000000 --- a/lib/symfony/css-selector/Parser/TokenStream.php +++ /dev/null @@ -1,167 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Parser; - -use Symfony\Component\CssSelector\Exception\InternalErrorException; -use Symfony\Component\CssSelector\Exception\SyntaxErrorException; - -/** - * CSS selector token stream. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class TokenStream -{ - /** - * @var Token[] - */ - private $tokens = []; - - /** - * @var Token[] - */ - private $used = []; - - /** - * @var int - */ - private $cursor = 0; - - /** - * @var Token|null - */ - private $peeked; - - /** - * @var bool - */ - private $peeking = false; - - /** - * Pushes a token. - * - * @return $this - */ - public function push(Token $token): self - { - $this->tokens[] = $token; - - return $this; - } - - /** - * Freezes stream. - * - * @return $this - */ - public function freeze(): self - { - return $this; - } - - /** - * Returns next token. - * - * @throws InternalErrorException If there is no more token - */ - public function getNext(): Token - { - if ($this->peeking) { - $this->peeking = false; - $this->used[] = $this->peeked; - - return $this->peeked; - } - - if (!isset($this->tokens[$this->cursor])) { - throw new InternalErrorException('Unexpected token stream end.'); - } - - return $this->tokens[$this->cursor++]; - } - - /** - * Returns peeked token. - */ - public function getPeek(): Token - { - if (!$this->peeking) { - $this->peeked = $this->getNext(); - $this->peeking = true; - } - - return $this->peeked; - } - - /** - * Returns used tokens. - * - * @return Token[] - */ - public function getUsed(): array - { - return $this->used; - } - - /** - * Returns next identifier token. - * - * @throws SyntaxErrorException If next token is not an identifier - */ - public function getNextIdentifier(): string - { - $next = $this->getNext(); - - if (!$next->isIdentifier()) { - throw SyntaxErrorException::unexpectedToken('identifier', $next); - } - - return $next->getValue(); - } - - /** - * Returns next identifier or null if star delimiter token is found. - * - * @throws SyntaxErrorException If next token is not an identifier or a star delimiter - */ - public function getNextIdentifierOrStar(): ?string - { - $next = $this->getNext(); - - if ($next->isIdentifier()) { - return $next->getValue(); - } - - if ($next->isDelimiter(['*'])) { - return null; - } - - throw SyntaxErrorException::unexpectedToken('identifier or "*"', $next); - } - - /** - * Skips next whitespace if any. - */ - public function skipWhitespace() - { - $peek = $this->getPeek(); - - if ($peek->isWhitespace()) { - $this->getNext(); - } - } -} diff --git a/lib/symfony/css-selector/Parser/Tokenizer/Tokenizer.php b/lib/symfony/css-selector/Parser/Tokenizer/Tokenizer.php deleted file mode 100644 index e0dcc5bf1..000000000 --- a/lib/symfony/css-selector/Parser/Tokenizer/Tokenizer.php +++ /dev/null @@ -1,73 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Parser\Tokenizer; - -use Symfony\Component\CssSelector\Parser\Handler; -use Symfony\Component\CssSelector\Parser\Reader; -use Symfony\Component\CssSelector\Parser\Token; -use Symfony\Component\CssSelector\Parser\TokenStream; - -/** - * CSS selector tokenizer. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class Tokenizer -{ - /** - * @var Handler\HandlerInterface[] - */ - private $handlers; - - public function __construct() - { - $patterns = new TokenizerPatterns(); - $escaping = new TokenizerEscaping($patterns); - - $this->handlers = [ - new Handler\WhitespaceHandler(), - new Handler\IdentifierHandler($patterns, $escaping), - new Handler\HashHandler($patterns, $escaping), - new Handler\StringHandler($patterns, $escaping), - new Handler\NumberHandler($patterns), - new Handler\CommentHandler(), - ]; - } - - /** - * Tokenize selector source code. - */ - public function tokenize(Reader $reader): TokenStream - { - $stream = new TokenStream(); - - while (!$reader->isEOF()) { - foreach ($this->handlers as $handler) { - if ($handler->handle($reader, $stream)) { - continue 2; - } - } - - $stream->push(new Token(Token::TYPE_DELIMITER, $reader->getSubstring(1), $reader->getPosition())); - $reader->moveForward(1); - } - - return $stream - ->push(new Token(Token::TYPE_FILE_END, null, $reader->getPosition())) - ->freeze(); - } -} diff --git a/lib/symfony/css-selector/Parser/Tokenizer/TokenizerEscaping.php b/lib/symfony/css-selector/Parser/Tokenizer/TokenizerEscaping.php deleted file mode 100644 index 013e827d2..000000000 --- a/lib/symfony/css-selector/Parser/Tokenizer/TokenizerEscaping.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Parser\Tokenizer; - -/** - * CSS selector tokenizer escaping applier. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class TokenizerEscaping -{ - private $patterns; - - public function __construct(TokenizerPatterns $patterns) - { - $this->patterns = $patterns; - } - - public function escapeUnicode(string $value): string - { - $value = $this->replaceUnicodeSequences($value); - - return preg_replace($this->patterns->getSimpleEscapePattern(), '$1', $value); - } - - public function escapeUnicodeAndNewLine(string $value): string - { - $value = preg_replace($this->patterns->getNewLineEscapePattern(), '', $value); - - return $this->escapeUnicode($value); - } - - private function replaceUnicodeSequences(string $value): string - { - return preg_replace_callback($this->patterns->getUnicodeEscapePattern(), function ($match) { - $c = hexdec($match[1]); - - if (0x80 > $c %= 0x200000) { - return \chr($c); - } - if (0x800 > $c) { - return \chr(0xC0 | $c >> 6).\chr(0x80 | $c & 0x3F); - } - if (0x10000 > $c) { - return \chr(0xE0 | $c >> 12).\chr(0x80 | $c >> 6 & 0x3F).\chr(0x80 | $c & 0x3F); - } - - return ''; - }, $value); - } -} diff --git a/lib/symfony/css-selector/Parser/Tokenizer/TokenizerPatterns.php b/lib/symfony/css-selector/Parser/Tokenizer/TokenizerPatterns.php deleted file mode 100644 index 5f16ac48f..000000000 --- a/lib/symfony/css-selector/Parser/Tokenizer/TokenizerPatterns.php +++ /dev/null @@ -1,89 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\Parser\Tokenizer; - -/** - * CSS selector tokenizer patterns builder. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class TokenizerPatterns -{ - private $unicodeEscapePattern; - private $simpleEscapePattern; - private $newLineEscapePattern; - private $escapePattern; - private $stringEscapePattern; - private $nonAsciiPattern; - private $nmCharPattern; - private $nmStartPattern; - private $identifierPattern; - private $hashPattern; - private $numberPattern; - private $quotedStringPattern; - - public function __construct() - { - $this->unicodeEscapePattern = '\\\\([0-9a-f]{1,6})(?:\r\n|[ \n\r\t\f])?'; - $this->simpleEscapePattern = '\\\\(.)'; - $this->newLineEscapePattern = '\\\\(?:\n|\r\n|\r|\f)'; - $this->escapePattern = $this->unicodeEscapePattern.'|\\\\[^\n\r\f0-9a-f]'; - $this->stringEscapePattern = $this->newLineEscapePattern.'|'.$this->escapePattern; - $this->nonAsciiPattern = '[^\x00-\x7F]'; - $this->nmCharPattern = '[_a-z0-9-]|'.$this->escapePattern.'|'.$this->nonAsciiPattern; - $this->nmStartPattern = '[_a-z]|'.$this->escapePattern.'|'.$this->nonAsciiPattern; - $this->identifierPattern = '-?(?:'.$this->nmStartPattern.')(?:'.$this->nmCharPattern.')*'; - $this->hashPattern = '#((?:'.$this->nmCharPattern.')+)'; - $this->numberPattern = '[+-]?(?:[0-9]*\.[0-9]+|[0-9]+)'; - $this->quotedStringPattern = '([^\n\r\f%s]|'.$this->stringEscapePattern.')*'; - } - - public function getNewLineEscapePattern(): string - { - return '~^'.$this->newLineEscapePattern.'~'; - } - - public function getSimpleEscapePattern(): string - { - return '~^'.$this->simpleEscapePattern.'~'; - } - - public function getUnicodeEscapePattern(): string - { - return '~^'.$this->unicodeEscapePattern.'~i'; - } - - public function getIdentifierPattern(): string - { - return '~^'.$this->identifierPattern.'~i'; - } - - public function getHashPattern(): string - { - return '~^'.$this->hashPattern.'~i'; - } - - public function getNumberPattern(): string - { - return '~^'.$this->numberPattern.'~'; - } - - public function getQuotedStringPattern(string $quote): string - { - return '~^'.sprintf($this->quotedStringPattern, $quote).'~i'; - } -} diff --git a/lib/symfony/css-selector/README.md b/lib/symfony/css-selector/README.md deleted file mode 100644 index ede4a3acc..000000000 --- a/lib/symfony/css-selector/README.md +++ /dev/null @@ -1,20 +0,0 @@ -CssSelector Component -===================== - -The CssSelector component converts CSS selectors to XPath expressions. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/css_selector.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 -------- - -This component is a port of the Python cssselect library -[v0.7.1](https://github.com/SimonSapin/cssselect/releases/tag/v0.7.1), -which is distributed under the BSD license. diff --git a/lib/symfony/css-selector/XPath/Extension/AbstractExtension.php b/lib/symfony/css-selector/XPath/Extension/AbstractExtension.php deleted file mode 100644 index 44e0035a7..000000000 --- a/lib/symfony/css-selector/XPath/Extension/AbstractExtension.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\XPath\Extension; - -/** - * XPath expression translator abstract extension. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -abstract class AbstractExtension implements ExtensionInterface -{ - /** - * {@inheritdoc} - */ - public function getNodeTranslators(): array - { - return []; - } - - /** - * {@inheritdoc} - */ - public function getCombinationTranslators(): array - { - return []; - } - - /** - * {@inheritdoc} - */ - public function getFunctionTranslators(): array - { - return []; - } - - /** - * {@inheritdoc} - */ - public function getPseudoClassTranslators(): array - { - return []; - } - - /** - * {@inheritdoc} - */ - public function getAttributeMatchingTranslators(): array - { - return []; - } -} diff --git a/lib/symfony/css-selector/XPath/Extension/AttributeMatchingExtension.php b/lib/symfony/css-selector/XPath/Extension/AttributeMatchingExtension.php deleted file mode 100644 index a9879f1be..000000000 --- a/lib/symfony/css-selector/XPath/Extension/AttributeMatchingExtension.php +++ /dev/null @@ -1,119 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\XPath\Extension; - -use Symfony\Component\CssSelector\XPath\Translator; -use Symfony\Component\CssSelector\XPath\XPathExpr; - -/** - * XPath expression translator attribute extension. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class AttributeMatchingExtension extends AbstractExtension -{ - /** - * {@inheritdoc} - */ - public function getAttributeMatchingTranslators(): array - { - return [ - 'exists' => [$this, 'translateExists'], - '=' => [$this, 'translateEquals'], - '~=' => [$this, 'translateIncludes'], - '|=' => [$this, 'translateDashMatch'], - '^=' => [$this, 'translatePrefixMatch'], - '$=' => [$this, 'translateSuffixMatch'], - '*=' => [$this, 'translateSubstringMatch'], - '!=' => [$this, 'translateDifferent'], - ]; - } - - public function translateExists(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr - { - return $xpath->addCondition($attribute); - } - - public function translateEquals(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr - { - return $xpath->addCondition(sprintf('%s = %s', $attribute, Translator::getXpathLiteral($value))); - } - - public function translateIncludes(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr - { - return $xpath->addCondition($value ? sprintf( - '%1$s and contains(concat(\' \', normalize-space(%1$s), \' \'), %2$s)', - $attribute, - Translator::getXpathLiteral(' '.$value.' ') - ) : '0'); - } - - public function translateDashMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr - { - return $xpath->addCondition(sprintf( - '%1$s and (%1$s = %2$s or starts-with(%1$s, %3$s))', - $attribute, - Translator::getXpathLiteral($value), - Translator::getXpathLiteral($value.'-') - )); - } - - public function translatePrefixMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr - { - return $xpath->addCondition($value ? sprintf( - '%1$s and starts-with(%1$s, %2$s)', - $attribute, - Translator::getXpathLiteral($value) - ) : '0'); - } - - public function translateSuffixMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr - { - return $xpath->addCondition($value ? sprintf( - '%1$s and substring(%1$s, string-length(%1$s)-%2$s) = %3$s', - $attribute, - \strlen($value) - 1, - Translator::getXpathLiteral($value) - ) : '0'); - } - - public function translateSubstringMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr - { - return $xpath->addCondition($value ? sprintf( - '%1$s and contains(%1$s, %2$s)', - $attribute, - Translator::getXpathLiteral($value) - ) : '0'); - } - - public function translateDifferent(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr - { - return $xpath->addCondition(sprintf( - $value ? 'not(%1$s) or %1$s != %2$s' : '%s != %s', - $attribute, - Translator::getXpathLiteral($value) - )); - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'attribute-matching'; - } -} diff --git a/lib/symfony/css-selector/XPath/Extension/CombinationExtension.php b/lib/symfony/css-selector/XPath/Extension/CombinationExtension.php deleted file mode 100644 index aee976e94..000000000 --- a/lib/symfony/css-selector/XPath/Extension/CombinationExtension.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\XPath\Extension; - -use Symfony\Component\CssSelector\XPath\XPathExpr; - -/** - * XPath expression translator combination extension. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class CombinationExtension extends AbstractExtension -{ - /** - * {@inheritdoc} - */ - public function getCombinationTranslators(): array - { - return [ - ' ' => [$this, 'translateDescendant'], - '>' => [$this, 'translateChild'], - '+' => [$this, 'translateDirectAdjacent'], - '~' => [$this, 'translateIndirectAdjacent'], - ]; - } - - public function translateDescendant(XPathExpr $xpath, XPathExpr $combinedXpath): XPathExpr - { - return $xpath->join('/descendant-or-self::*/', $combinedXpath); - } - - public function translateChild(XPathExpr $xpath, XPathExpr $combinedXpath): XPathExpr - { - return $xpath->join('/', $combinedXpath); - } - - public function translateDirectAdjacent(XPathExpr $xpath, XPathExpr $combinedXpath): XPathExpr - { - return $xpath - ->join('/following-sibling::', $combinedXpath) - ->addNameTest() - ->addCondition('position() = 1'); - } - - public function translateIndirectAdjacent(XPathExpr $xpath, XPathExpr $combinedXpath): XPathExpr - { - return $xpath->join('/following-sibling::', $combinedXpath); - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'combination'; - } -} diff --git a/lib/symfony/css-selector/XPath/Extension/ExtensionInterface.php b/lib/symfony/css-selector/XPath/Extension/ExtensionInterface.php deleted file mode 100644 index 1a74b90ac..000000000 --- a/lib/symfony/css-selector/XPath/Extension/ExtensionInterface.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\XPath\Extension; - -/** - * XPath expression translator extension interface. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -interface ExtensionInterface -{ - /** - * Returns node translators. - * - * These callables will receive the node as first argument and the translator as second argument. - * - * @return callable[] - */ - public function getNodeTranslators(): array; - - /** - * Returns combination translators. - * - * @return callable[] - */ - public function getCombinationTranslators(): array; - - /** - * Returns function translators. - * - * @return callable[] - */ - public function getFunctionTranslators(): array; - - /** - * Returns pseudo-class translators. - * - * @return callable[] - */ - public function getPseudoClassTranslators(): array; - - /** - * Returns attribute operation translators. - * - * @return callable[] - */ - public function getAttributeMatchingTranslators(): array; - - /** - * Returns extension name. - */ - public function getName(): string; -} diff --git a/lib/symfony/css-selector/XPath/Extension/FunctionExtension.php b/lib/symfony/css-selector/XPath/Extension/FunctionExtension.php deleted file mode 100644 index d3f7222a4..000000000 --- a/lib/symfony/css-selector/XPath/Extension/FunctionExtension.php +++ /dev/null @@ -1,171 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\XPath\Extension; - -use Symfony\Component\CssSelector\Exception\ExpressionErrorException; -use Symfony\Component\CssSelector\Exception\SyntaxErrorException; -use Symfony\Component\CssSelector\Node\FunctionNode; -use Symfony\Component\CssSelector\Parser\Parser; -use Symfony\Component\CssSelector\XPath\Translator; -use Symfony\Component\CssSelector\XPath\XPathExpr; - -/** - * XPath expression translator function extension. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class FunctionExtension extends AbstractExtension -{ - /** - * {@inheritdoc} - */ - public function getFunctionTranslators(): array - { - return [ - 'nth-child' => [$this, 'translateNthChild'], - 'nth-last-child' => [$this, 'translateNthLastChild'], - 'nth-of-type' => [$this, 'translateNthOfType'], - 'nth-last-of-type' => [$this, 'translateNthLastOfType'], - 'contains' => [$this, 'translateContains'], - 'lang' => [$this, 'translateLang'], - ]; - } - - /** - * @throws ExpressionErrorException - */ - public function translateNthChild(XPathExpr $xpath, FunctionNode $function, bool $last = false, bool $addNameTest = true): XPathExpr - { - try { - [$a, $b] = Parser::parseSeries($function->getArguments()); - } catch (SyntaxErrorException $e) { - throw new ExpressionErrorException(sprintf('Invalid series: "%s".', implode('", "', $function->getArguments())), 0, $e); - } - - $xpath->addStarPrefix(); - if ($addNameTest) { - $xpath->addNameTest(); - } - - if (0 === $a) { - return $xpath->addCondition('position() = '.($last ? 'last() - '.($b - 1) : $b)); - } - - if ($a < 0) { - if ($b < 1) { - return $xpath->addCondition('false()'); - } - - $sign = '<='; - } else { - $sign = '>='; - } - - $expr = 'position()'; - - if ($last) { - $expr = 'last() - '.$expr; - --$b; - } - - if (0 !== $b) { - $expr .= ' - '.$b; - } - - $conditions = [sprintf('%s %s 0', $expr, $sign)]; - - if (1 !== $a && -1 !== $a) { - $conditions[] = sprintf('(%s) mod %d = 0', $expr, $a); - } - - return $xpath->addCondition(implode(' and ', $conditions)); - - // todo: handle an+b, odd, even - // an+b means every-a, plus b, e.g., 2n+1 means odd - // 0n+b means b - // n+0 means a=1, i.e., all elements - // an means every a elements, i.e., 2n means even - // -n means -1n - // -1n+6 means elements 6 and previous - } - - public function translateNthLastChild(XPathExpr $xpath, FunctionNode $function): XPathExpr - { - return $this->translateNthChild($xpath, $function, true); - } - - public function translateNthOfType(XPathExpr $xpath, FunctionNode $function): XPathExpr - { - return $this->translateNthChild($xpath, $function, false, false); - } - - /** - * @throws ExpressionErrorException - */ - public function translateNthLastOfType(XPathExpr $xpath, FunctionNode $function): XPathExpr - { - if ('*' === $xpath->getElement()) { - throw new ExpressionErrorException('"*:nth-of-type()" is not implemented.'); - } - - return $this->translateNthChild($xpath, $function, true, false); - } - - /** - * @throws ExpressionErrorException - */ - public function translateContains(XPathExpr $xpath, FunctionNode $function): XPathExpr - { - $arguments = $function->getArguments(); - foreach ($arguments as $token) { - if (!($token->isString() || $token->isIdentifier())) { - throw new ExpressionErrorException('Expected a single string or identifier for :contains(), got '.implode(', ', $arguments)); - } - } - - return $xpath->addCondition(sprintf( - 'contains(string(.), %s)', - Translator::getXpathLiteral($arguments[0]->getValue()) - )); - } - - /** - * @throws ExpressionErrorException - */ - public function translateLang(XPathExpr $xpath, FunctionNode $function): XPathExpr - { - $arguments = $function->getArguments(); - foreach ($arguments as $token) { - if (!($token->isString() || $token->isIdentifier())) { - throw new ExpressionErrorException('Expected a single string or identifier for :lang(), got '.implode(', ', $arguments)); - } - } - - return $xpath->addCondition(sprintf( - 'lang(%s)', - Translator::getXpathLiteral($arguments[0]->getValue()) - )); - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'function'; - } -} diff --git a/lib/symfony/css-selector/XPath/Extension/HtmlExtension.php b/lib/symfony/css-selector/XPath/Extension/HtmlExtension.php deleted file mode 100644 index 6edc08581..000000000 --- a/lib/symfony/css-selector/XPath/Extension/HtmlExtension.php +++ /dev/null @@ -1,187 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\XPath\Extension; - -use Symfony\Component\CssSelector\Exception\ExpressionErrorException; -use Symfony\Component\CssSelector\Node\FunctionNode; -use Symfony\Component\CssSelector\XPath\Translator; -use Symfony\Component\CssSelector\XPath\XPathExpr; - -/** - * XPath expression translator HTML extension. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class HtmlExtension extends AbstractExtension -{ - public function __construct(Translator $translator) - { - $translator - ->getExtension('node') - ->setFlag(NodeExtension::ELEMENT_NAME_IN_LOWER_CASE, true) - ->setFlag(NodeExtension::ATTRIBUTE_NAME_IN_LOWER_CASE, true); - } - - /** - * {@inheritdoc} - */ - public function getPseudoClassTranslators(): array - { - return [ - 'checked' => [$this, 'translateChecked'], - 'link' => [$this, 'translateLink'], - 'disabled' => [$this, 'translateDisabled'], - 'enabled' => [$this, 'translateEnabled'], - 'selected' => [$this, 'translateSelected'], - 'invalid' => [$this, 'translateInvalid'], - 'hover' => [$this, 'translateHover'], - 'visited' => [$this, 'translateVisited'], - ]; - } - - /** - * {@inheritdoc} - */ - public function getFunctionTranslators(): array - { - return [ - 'lang' => [$this, 'translateLang'], - ]; - } - - public function translateChecked(XPathExpr $xpath): XPathExpr - { - return $xpath->addCondition( - '(@checked ' - ."and (name(.) = 'input' or name(.) = 'command')" - ."and (@type = 'checkbox' or @type = 'radio'))" - ); - } - - public function translateLink(XPathExpr $xpath): XPathExpr - { - return $xpath->addCondition("@href and (name(.) = 'a' or name(.) = 'link' or name(.) = 'area')"); - } - - public function translateDisabled(XPathExpr $xpath): XPathExpr - { - return $xpath->addCondition( - '(' - .'@disabled and' - .'(' - ."(name(.) = 'input' and @type != 'hidden')" - ." or name(.) = 'button'" - ." or name(.) = 'select'" - ." or name(.) = 'textarea'" - ." or name(.) = 'command'" - ." or name(.) = 'fieldset'" - ." or name(.) = 'optgroup'" - ." or name(.) = 'option'" - .')' - .') or (' - ."(name(.) = 'input' and @type != 'hidden')" - ." or name(.) = 'button'" - ." or name(.) = 'select'" - ." or name(.) = 'textarea'" - .')' - .' and ancestor::fieldset[@disabled]' - ); - // todo: in the second half, add "and is not a descendant of that fieldset element's first legend element child, if any." - } - - public function translateEnabled(XPathExpr $xpath): XPathExpr - { - return $xpath->addCondition( - '(' - .'@href and (' - ."name(.) = 'a'" - ." or name(.) = 'link'" - ." or name(.) = 'area'" - .')' - .') or (' - .'(' - ."name(.) = 'command'" - ." or name(.) = 'fieldset'" - ." or name(.) = 'optgroup'" - .')' - .' and not(@disabled)' - .') or (' - .'(' - ."(name(.) = 'input' and @type != 'hidden')" - ." or name(.) = 'button'" - ." or name(.) = 'select'" - ." or name(.) = 'textarea'" - ." or name(.) = 'keygen'" - .')' - .' and not (@disabled or ancestor::fieldset[@disabled])' - .') or (' - ."name(.) = 'option' and not(" - .'@disabled or ancestor::optgroup[@disabled]' - .')' - .')' - ); - } - - /** - * @throws ExpressionErrorException - */ - public function translateLang(XPathExpr $xpath, FunctionNode $function): XPathExpr - { - $arguments = $function->getArguments(); - foreach ($arguments as $token) { - if (!($token->isString() || $token->isIdentifier())) { - throw new ExpressionErrorException('Expected a single string or identifier for :lang(), got '.implode(', ', $arguments)); - } - } - - return $xpath->addCondition(sprintf( - 'ancestor-or-self::*[@lang][1][starts-with(concat(' - ."translate(@%s, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '-')" - .', %s)]', - 'lang', - Translator::getXpathLiteral(strtolower($arguments[0]->getValue()).'-') - )); - } - - public function translateSelected(XPathExpr $xpath): XPathExpr - { - return $xpath->addCondition("(@selected and name(.) = 'option')"); - } - - public function translateInvalid(XPathExpr $xpath): XPathExpr - { - return $xpath->addCondition('0'); - } - - public function translateHover(XPathExpr $xpath): XPathExpr - { - return $xpath->addCondition('0'); - } - - public function translateVisited(XPathExpr $xpath): XPathExpr - { - return $xpath->addCondition('0'); - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'html'; - } -} diff --git a/lib/symfony/css-selector/XPath/Extension/NodeExtension.php b/lib/symfony/css-selector/XPath/Extension/NodeExtension.php deleted file mode 100644 index aa6f3f704..000000000 --- a/lib/symfony/css-selector/XPath/Extension/NodeExtension.php +++ /dev/null @@ -1,197 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\XPath\Extension; - -use Symfony\Component\CssSelector\Node; -use Symfony\Component\CssSelector\XPath\Translator; -use Symfony\Component\CssSelector\XPath\XPathExpr; - -/** - * XPath expression translator node extension. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class NodeExtension extends AbstractExtension -{ - public const ELEMENT_NAME_IN_LOWER_CASE = 1; - public const ATTRIBUTE_NAME_IN_LOWER_CASE = 2; - public const ATTRIBUTE_VALUE_IN_LOWER_CASE = 4; - - private $flags; - - public function __construct(int $flags = 0) - { - $this->flags = $flags; - } - - /** - * @return $this - */ - public function setFlag(int $flag, bool $on): self - { - if ($on && !$this->hasFlag($flag)) { - $this->flags += $flag; - } - - if (!$on && $this->hasFlag($flag)) { - $this->flags -= $flag; - } - - return $this; - } - - public function hasFlag(int $flag): bool - { - return (bool) ($this->flags & $flag); - } - - /** - * {@inheritdoc} - */ - public function getNodeTranslators(): array - { - return [ - 'Selector' => [$this, 'translateSelector'], - 'CombinedSelector' => [$this, 'translateCombinedSelector'], - 'Negation' => [$this, 'translateNegation'], - 'Function' => [$this, 'translateFunction'], - 'Pseudo' => [$this, 'translatePseudo'], - 'Attribute' => [$this, 'translateAttribute'], - 'Class' => [$this, 'translateClass'], - 'Hash' => [$this, 'translateHash'], - 'Element' => [$this, 'translateElement'], - ]; - } - - public function translateSelector(Node\SelectorNode $node, Translator $translator): XPathExpr - { - return $translator->nodeToXPath($node->getTree()); - } - - public function translateCombinedSelector(Node\CombinedSelectorNode $node, Translator $translator): XPathExpr - { - return $translator->addCombination($node->getCombinator(), $node->getSelector(), $node->getSubSelector()); - } - - public function translateNegation(Node\NegationNode $node, Translator $translator): XPathExpr - { - $xpath = $translator->nodeToXPath($node->getSelector()); - $subXpath = $translator->nodeToXPath($node->getSubSelector()); - $subXpath->addNameTest(); - - if ($subXpath->getCondition()) { - return $xpath->addCondition(sprintf('not(%s)', $subXpath->getCondition())); - } - - return $xpath->addCondition('0'); - } - - public function translateFunction(Node\FunctionNode $node, Translator $translator): XPathExpr - { - $xpath = $translator->nodeToXPath($node->getSelector()); - - return $translator->addFunction($xpath, $node); - } - - public function translatePseudo(Node\PseudoNode $node, Translator $translator): XPathExpr - { - $xpath = $translator->nodeToXPath($node->getSelector()); - - return $translator->addPseudoClass($xpath, $node->getIdentifier()); - } - - public function translateAttribute(Node\AttributeNode $node, Translator $translator): XPathExpr - { - $name = $node->getAttribute(); - $safe = $this->isSafeName($name); - - if ($this->hasFlag(self::ATTRIBUTE_NAME_IN_LOWER_CASE)) { - $name = strtolower($name); - } - - if ($node->getNamespace()) { - $name = sprintf('%s:%s', $node->getNamespace(), $name); - $safe = $safe && $this->isSafeName($node->getNamespace()); - } - - $attribute = $safe ? '@'.$name : sprintf('attribute::*[name() = %s]', Translator::getXpathLiteral($name)); - $value = $node->getValue(); - $xpath = $translator->nodeToXPath($node->getSelector()); - - if ($this->hasFlag(self::ATTRIBUTE_VALUE_IN_LOWER_CASE)) { - $value = strtolower($value); - } - - return $translator->addAttributeMatching($xpath, $node->getOperator(), $attribute, $value); - } - - public function translateClass(Node\ClassNode $node, Translator $translator): XPathExpr - { - $xpath = $translator->nodeToXPath($node->getSelector()); - - return $translator->addAttributeMatching($xpath, '~=', '@class', $node->getName()); - } - - public function translateHash(Node\HashNode $node, Translator $translator): XPathExpr - { - $xpath = $translator->nodeToXPath($node->getSelector()); - - return $translator->addAttributeMatching($xpath, '=', '@id', $node->getId()); - } - - public function translateElement(Node\ElementNode $node): XPathExpr - { - $element = $node->getElement(); - - if ($element && $this->hasFlag(self::ELEMENT_NAME_IN_LOWER_CASE)) { - $element = strtolower($element); - } - - if ($element) { - $safe = $this->isSafeName($element); - } else { - $element = '*'; - $safe = true; - } - - if ($node->getNamespace()) { - $element = sprintf('%s:%s', $node->getNamespace(), $element); - $safe = $safe && $this->isSafeName($node->getNamespace()); - } - - $xpath = new XPathExpr('', $element); - - if (!$safe) { - $xpath->addNameTest(); - } - - return $xpath; - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'node'; - } - - private function isSafeName(string $name): bool - { - return 0 < preg_match('~^[a-zA-Z_][a-zA-Z0-9_.-]*$~', $name); - } -} diff --git a/lib/symfony/css-selector/XPath/Extension/PseudoClassExtension.php b/lib/symfony/css-selector/XPath/Extension/PseudoClassExtension.php deleted file mode 100644 index a50b0486a..000000000 --- a/lib/symfony/css-selector/XPath/Extension/PseudoClassExtension.php +++ /dev/null @@ -1,122 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\XPath\Extension; - -use Symfony\Component\CssSelector\Exception\ExpressionErrorException; -use Symfony\Component\CssSelector\XPath\XPathExpr; - -/** - * XPath expression translator pseudo-class extension. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class PseudoClassExtension extends AbstractExtension -{ - /** - * {@inheritdoc} - */ - public function getPseudoClassTranslators(): array - { - return [ - 'root' => [$this, 'translateRoot'], - 'first-child' => [$this, 'translateFirstChild'], - 'last-child' => [$this, 'translateLastChild'], - 'first-of-type' => [$this, 'translateFirstOfType'], - 'last-of-type' => [$this, 'translateLastOfType'], - 'only-child' => [$this, 'translateOnlyChild'], - 'only-of-type' => [$this, 'translateOnlyOfType'], - 'empty' => [$this, 'translateEmpty'], - ]; - } - - public function translateRoot(XPathExpr $xpath): XPathExpr - { - return $xpath->addCondition('not(parent::*)'); - } - - public function translateFirstChild(XPathExpr $xpath): XPathExpr - { - return $xpath - ->addStarPrefix() - ->addNameTest() - ->addCondition('position() = 1'); - } - - public function translateLastChild(XPathExpr $xpath): XPathExpr - { - return $xpath - ->addStarPrefix() - ->addNameTest() - ->addCondition('position() = last()'); - } - - /** - * @throws ExpressionErrorException - */ - public function translateFirstOfType(XPathExpr $xpath): XPathExpr - { - if ('*' === $xpath->getElement()) { - throw new ExpressionErrorException('"*:first-of-type" is not implemented.'); - } - - return $xpath - ->addStarPrefix() - ->addCondition('position() = 1'); - } - - /** - * @throws ExpressionErrorException - */ - public function translateLastOfType(XPathExpr $xpath): XPathExpr - { - if ('*' === $xpath->getElement()) { - throw new ExpressionErrorException('"*:last-of-type" is not implemented.'); - } - - return $xpath - ->addStarPrefix() - ->addCondition('position() = last()'); - } - - public function translateOnlyChild(XPathExpr $xpath): XPathExpr - { - return $xpath - ->addStarPrefix() - ->addNameTest() - ->addCondition('last() = 1'); - } - - public function translateOnlyOfType(XPathExpr $xpath): XPathExpr - { - $element = $xpath->getElement(); - - return $xpath->addCondition(sprintf('count(preceding-sibling::%s)=0 and count(following-sibling::%s)=0', $element, $element)); - } - - public function translateEmpty(XPathExpr $xpath): XPathExpr - { - return $xpath->addCondition('not(*) and not(string-length())'); - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'pseudo-class'; - } -} diff --git a/lib/symfony/css-selector/XPath/Translator.php b/lib/symfony/css-selector/XPath/Translator.php deleted file mode 100644 index 8ce473036..000000000 --- a/lib/symfony/css-selector/XPath/Translator.php +++ /dev/null @@ -1,230 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\XPath; - -use Symfony\Component\CssSelector\Exception\ExpressionErrorException; -use Symfony\Component\CssSelector\Node\FunctionNode; -use Symfony\Component\CssSelector\Node\NodeInterface; -use Symfony\Component\CssSelector\Node\SelectorNode; -use Symfony\Component\CssSelector\Parser\Parser; -use Symfony\Component\CssSelector\Parser\ParserInterface; - -/** - * XPath expression translator interface. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class Translator implements TranslatorInterface -{ - private $mainParser; - - /** - * @var ParserInterface[] - */ - private $shortcutParsers = []; - - /** - * @var Extension\ExtensionInterface[] - */ - private $extensions = []; - - private $nodeTranslators = []; - private $combinationTranslators = []; - private $functionTranslators = []; - private $pseudoClassTranslators = []; - private $attributeMatchingTranslators = []; - - public function __construct(ParserInterface $parser = null) - { - $this->mainParser = $parser ?? new Parser(); - - $this - ->registerExtension(new Extension\NodeExtension()) - ->registerExtension(new Extension\CombinationExtension()) - ->registerExtension(new Extension\FunctionExtension()) - ->registerExtension(new Extension\PseudoClassExtension()) - ->registerExtension(new Extension\AttributeMatchingExtension()) - ; - } - - public static function getXpathLiteral(string $element): string - { - if (!str_contains($element, "'")) { - return "'".$element."'"; - } - - if (!str_contains($element, '"')) { - return '"'.$element.'"'; - } - - $string = $element; - $parts = []; - while (true) { - if (false !== $pos = strpos($string, "'")) { - $parts[] = sprintf("'%s'", substr($string, 0, $pos)); - $parts[] = "\"'\""; - $string = substr($string, $pos + 1); - } else { - $parts[] = "'$string'"; - break; - } - } - - return sprintf('concat(%s)', implode(', ', $parts)); - } - - /** - * {@inheritdoc} - */ - public function cssToXPath(string $cssExpr, string $prefix = 'descendant-or-self::'): string - { - $selectors = $this->parseSelectors($cssExpr); - - /** @var SelectorNode $selector */ - foreach ($selectors as $index => $selector) { - if (null !== $selector->getPseudoElement()) { - throw new ExpressionErrorException('Pseudo-elements are not supported.'); - } - - $selectors[$index] = $this->selectorToXPath($selector, $prefix); - } - - return implode(' | ', $selectors); - } - - /** - * {@inheritdoc} - */ - public function selectorToXPath(SelectorNode $selector, string $prefix = 'descendant-or-self::'): string - { - return ($prefix ?: '').$this->nodeToXPath($selector); - } - - /** - * @return $this - */ - public function registerExtension(Extension\ExtensionInterface $extension): self - { - $this->extensions[$extension->getName()] = $extension; - - $this->nodeTranslators = array_merge($this->nodeTranslators, $extension->getNodeTranslators()); - $this->combinationTranslators = array_merge($this->combinationTranslators, $extension->getCombinationTranslators()); - $this->functionTranslators = array_merge($this->functionTranslators, $extension->getFunctionTranslators()); - $this->pseudoClassTranslators = array_merge($this->pseudoClassTranslators, $extension->getPseudoClassTranslators()); - $this->attributeMatchingTranslators = array_merge($this->attributeMatchingTranslators, $extension->getAttributeMatchingTranslators()); - - return $this; - } - - /** - * @throws ExpressionErrorException - */ - public function getExtension(string $name): Extension\ExtensionInterface - { - if (!isset($this->extensions[$name])) { - throw new ExpressionErrorException(sprintf('Extension "%s" not registered.', $name)); - } - - return $this->extensions[$name]; - } - - /** - * @return $this - */ - public function registerParserShortcut(ParserInterface $shortcut): self - { - $this->shortcutParsers[] = $shortcut; - - return $this; - } - - /** - * @throws ExpressionErrorException - */ - public function nodeToXPath(NodeInterface $node): XPathExpr - { - if (!isset($this->nodeTranslators[$node->getNodeName()])) { - throw new ExpressionErrorException(sprintf('Node "%s" not supported.', $node->getNodeName())); - } - - return $this->nodeTranslators[$node->getNodeName()]($node, $this); - } - - /** - * @throws ExpressionErrorException - */ - public function addCombination(string $combiner, NodeInterface $xpath, NodeInterface $combinedXpath): XPathExpr - { - if (!isset($this->combinationTranslators[$combiner])) { - throw new ExpressionErrorException(sprintf('Combiner "%s" not supported.', $combiner)); - } - - return $this->combinationTranslators[$combiner]($this->nodeToXPath($xpath), $this->nodeToXPath($combinedXpath)); - } - - /** - * @throws ExpressionErrorException - */ - public function addFunction(XPathExpr $xpath, FunctionNode $function): XPathExpr - { - if (!isset($this->functionTranslators[$function->getName()])) { - throw new ExpressionErrorException(sprintf('Function "%s" not supported.', $function->getName())); - } - - return $this->functionTranslators[$function->getName()]($xpath, $function); - } - - /** - * @throws ExpressionErrorException - */ - public function addPseudoClass(XPathExpr $xpath, string $pseudoClass): XPathExpr - { - if (!isset($this->pseudoClassTranslators[$pseudoClass])) { - throw new ExpressionErrorException(sprintf('Pseudo-class "%s" not supported.', $pseudoClass)); - } - - return $this->pseudoClassTranslators[$pseudoClass]($xpath); - } - - /** - * @throws ExpressionErrorException - */ - public function addAttributeMatching(XPathExpr $xpath, string $operator, string $attribute, ?string $value): XPathExpr - { - if (!isset($this->attributeMatchingTranslators[$operator])) { - throw new ExpressionErrorException(sprintf('Attribute matcher operator "%s" not supported.', $operator)); - } - - return $this->attributeMatchingTranslators[$operator]($xpath, $attribute, $value); - } - - /** - * @return SelectorNode[] - */ - private function parseSelectors(string $css): array - { - foreach ($this->shortcutParsers as $shortcut) { - $tokens = $shortcut->parse($css); - - if (!empty($tokens)) { - return $tokens; - } - } - - return $this->mainParser->parse($css); - } -} diff --git a/lib/symfony/css-selector/XPath/TranslatorInterface.php b/lib/symfony/css-selector/XPath/TranslatorInterface.php deleted file mode 100644 index c19eefb9c..000000000 --- a/lib/symfony/css-selector/XPath/TranslatorInterface.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\XPath; - -use Symfony\Component\CssSelector\Node\SelectorNode; - -/** - * XPath expression translator interface. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -interface TranslatorInterface -{ - /** - * Translates a CSS selector to an XPath expression. - */ - public function cssToXPath(string $cssExpr, string $prefix = 'descendant-or-self::'): string; - - /** - * Translates a parsed selector node to an XPath expression. - */ - public function selectorToXPath(SelectorNode $selector, string $prefix = 'descendant-or-self::'): string; -} diff --git a/lib/symfony/css-selector/XPath/XPathExpr.php b/lib/symfony/css-selector/XPath/XPathExpr.php deleted file mode 100644 index e45ce7d8c..000000000 --- a/lib/symfony/css-selector/XPath/XPathExpr.php +++ /dev/null @@ -1,111 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\CssSelector\XPath; - -/** - * XPath expression translator interface. - * - * This component is a port of the Python cssselect library, - * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. - * - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class XPathExpr -{ - private $path; - private $element; - private $condition; - - public function __construct(string $path = '', string $element = '*', string $condition = '', bool $starPrefix = false) - { - $this->path = $path; - $this->element = $element; - $this->condition = $condition; - - if ($starPrefix) { - $this->addStarPrefix(); - } - } - - public function getElement(): string - { - return $this->element; - } - - /** - * @return $this - */ - public function addCondition(string $condition): self - { - $this->condition = $this->condition ? sprintf('(%s) and (%s)', $this->condition, $condition) : $condition; - - return $this; - } - - public function getCondition(): string - { - return $this->condition; - } - - /** - * @return $this - */ - public function addNameTest(): self - { - if ('*' !== $this->element) { - $this->addCondition('name() = '.Translator::getXpathLiteral($this->element)); - $this->element = '*'; - } - - return $this; - } - - /** - * @return $this - */ - public function addStarPrefix(): self - { - $this->path .= '*/'; - - return $this; - } - - /** - * Joins another XPathExpr with a combiner. - * - * @return $this - */ - public function join(string $combiner, self $expr): self - { - $path = $this->__toString().$combiner; - - if ('*/' !== $expr->path) { - $path .= $expr->path; - } - - $this->path = $path; - $this->element = $expr->element; - $this->condition = $expr->condition; - - return $this; - } - - public function __toString(): string - { - $path = $this->path.$this->element; - $condition = null === $this->condition || '' === $this->condition ? '' : '['.$this->condition.']'; - - return $path.$condition; - } -} diff --git a/lib/symfony/css-selector/composer.json b/lib/symfony/css-selector/composer.json deleted file mode 100644 index f0b712495..000000000 --- a/lib/symfony/css-selector/composer.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "symfony/css-selector", - "type": "library", - "description": "Converts CSS selectors to XPath expressions", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Jean-François Simon", - "email": "jeanfrancois.simon@sensiolabs.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\CssSelector\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/lib/symfony/dependency-injection/Alias.php b/lib/symfony/dependency-injection/Alias.php deleted file mode 100644 index 71bfef51e..000000000 --- a/lib/symfony/dependency-injection/Alias.php +++ /dev/null @@ -1,161 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -class Alias -{ - private const DEFAULT_DEPRECATION_TEMPLATE = 'The "%alias_id%" service alias is deprecated. You should stop using it, as it will be removed in the future.'; - - private $id; - private $public; - private $deprecation = []; - - public function __construct(string $id, bool $public = false) - { - $this->id = $id; - $this->public = $public; - } - - /** - * Checks if this DI Alias should be public or not. - * - * @return bool - */ - public function isPublic() - { - return $this->public; - } - - /** - * Sets if this Alias is public. - * - * @return $this - */ - public function setPublic(bool $boolean) - { - $this->public = $boolean; - - return $this; - } - - /** - * Sets if this Alias is private. - * - * @return $this - * - * @deprecated since Symfony 5.2, use setPublic() instead - */ - public function setPrivate(bool $boolean) - { - trigger_deprecation('symfony/dependency-injection', '5.2', 'The "%s()" method is deprecated, use "setPublic()" instead.', __METHOD__); - - return $this->setPublic(!$boolean); - } - - /** - * Whether this alias is private. - * - * @return bool - */ - public function isPrivate() - { - return !$this->public; - } - - /** - * Whether this alias is deprecated, that means it should not be referenced - * anymore. - * - * @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 deprecation message to use - * - * @return $this - * - * @throws InvalidArgumentException when the message template is invalid - */ - public function setDeprecated(/* string $package, string $version, string $message */) - { - $args = \func_get_args(); - - if (\func_num_args() < 3) { - trigger_deprecation('symfony/dependency-injection', '5.1', 'The signature of method "%s()" requires 3 arguments: "string $package, string $version, string $message", not defining them is deprecated.', __METHOD__); - - $status = $args[0] ?? true; - - if (!$status) { - trigger_deprecation('symfony/dependency-injection', '5.1', 'Passing a null message to un-deprecate a node is deprecated.'); - } - - $message = (string) ($args[1] ?? null); - $package = $version = ''; - } else { - $status = true; - $package = (string) $args[0]; - $version = (string) $args[1]; - $message = (string) $args[2]; - } - - if ('' !== $message) { - if (preg_match('#[\r\n]|\*/#', $message)) { - throw new InvalidArgumentException('Invalid characters found in deprecation template.'); - } - - if (!str_contains($message, '%alias_id%')) { - throw new InvalidArgumentException('The deprecation template must contain the "%alias_id%" placeholder.'); - } - } - - $this->deprecation = $status ? ['package' => $package, 'version' => $version, 'message' => $message ?: self::DEFAULT_DEPRECATION_TEMPLATE] : []; - - return $this; - } - - public function isDeprecated(): bool - { - return (bool) $this->deprecation; - } - - /** - * @deprecated since Symfony 5.1, use "getDeprecation()" instead. - */ - public function getDeprecationMessage(string $id): string - { - trigger_deprecation('symfony/dependency-injection', '5.1', 'The "%s()" method is deprecated, use "getDeprecation()" instead.', __METHOD__); - - return $this->getDeprecation($id)['message']; - } - - /** - * @param string $id Service id relying on this definition - */ - public function getDeprecation(string $id): array - { - return [ - 'package' => $this->deprecation['package'], - 'version' => $this->deprecation['version'], - 'message' => str_replace('%alias_id%', $id, $this->deprecation['message']), - ]; - } - - /** - * Returns the Id of this alias. - * - * @return string - */ - public function __toString() - { - return $this->id; - } -} diff --git a/lib/symfony/dependency-injection/Argument/AbstractArgument.php b/lib/symfony/dependency-injection/Argument/AbstractArgument.php deleted file mode 100644 index 3ba5ff33b..000000000 --- a/lib/symfony/dependency-injection/Argument/AbstractArgument.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Argument; - -/** - * Represents an abstract service argument, which have to be set by a compiler pass or a DI extension. - */ -final class AbstractArgument -{ - private $text; - private $context; - - public function __construct(string $text = '') - { - $this->text = trim($text, '. '); - } - - public function setContext(string $context): void - { - $this->context = $context.' is abstract'.('' === $this->text ? '' : ': '); - } - - public function getText(): string - { - return $this->text; - } - - public function getTextWithContext(): string - { - return $this->context.$this->text.'.'; - } -} diff --git a/lib/symfony/dependency-injection/Argument/ArgumentInterface.php b/lib/symfony/dependency-injection/Argument/ArgumentInterface.php deleted file mode 100644 index b46eb77be..000000000 --- a/lib/symfony/dependency-injection/Argument/ArgumentInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Argument; - -/** - * Represents a complex argument containing nested values. - * - * @author Titouan Galopin <galopintitouan@gmail.com> - */ -interface ArgumentInterface -{ - /** - * @return array - */ - public function getValues(); - - public function setValues(array $values); -} diff --git a/lib/symfony/dependency-injection/Argument/BoundArgument.php b/lib/symfony/dependency-injection/Argument/BoundArgument.php deleted file mode 100644 index c2afe2cfa..000000000 --- a/lib/symfony/dependency-injection/Argument/BoundArgument.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Argument; - -/** - * @author Guilhem Niot <guilhem.niot@gmail.com> - */ -final class BoundArgument implements ArgumentInterface -{ - public const SERVICE_BINDING = 0; - public const DEFAULTS_BINDING = 1; - public const INSTANCEOF_BINDING = 2; - - private static $sequence = 0; - - private $value; - private $identifier; - private $used; - private $type; - private $file; - - public function __construct($value, bool $trackUsage = true, int $type = 0, string $file = null) - { - $this->value = $value; - if ($trackUsage) { - $this->identifier = ++self::$sequence; - } else { - $this->used = true; - } - $this->type = $type; - $this->file = $file; - } - - /** - * {@inheritdoc} - */ - public function getValues(): array - { - return [$this->value, $this->identifier, $this->used, $this->type, $this->file]; - } - - /** - * {@inheritdoc} - */ - public function setValues(array $values) - { - if (5 === \count($values)) { - [$this->value, $this->identifier, $this->used, $this->type, $this->file] = $values; - } else { - [$this->value, $this->identifier, $this->used] = $values; - } - } -} diff --git a/lib/symfony/dependency-injection/Argument/IteratorArgument.php b/lib/symfony/dependency-injection/Argument/IteratorArgument.php deleted file mode 100644 index d413678a1..000000000 --- a/lib/symfony/dependency-injection/Argument/IteratorArgument.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Argument; - -/** - * Represents a collection of values to lazily iterate over. - * - * @author Titouan Galopin <galopintitouan@gmail.com> - */ -class IteratorArgument implements ArgumentInterface -{ - use ReferenceSetArgumentTrait; -} diff --git a/lib/symfony/dependency-injection/Argument/ReferenceSetArgumentTrait.php b/lib/symfony/dependency-injection/Argument/ReferenceSetArgumentTrait.php deleted file mode 100644 index 150c9bf57..000000000 --- a/lib/symfony/dependency-injection/Argument/ReferenceSetArgumentTrait.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Argument; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * @author Titouan Galopin <galopintitouan@gmail.com> - * @author Nicolas Grekas <p@tchwork.com> - */ -trait ReferenceSetArgumentTrait -{ - private $values; - - /** - * @param Reference[] $values - */ - public function __construct(array $values) - { - $this->setValues($values); - } - - /** - * @return Reference[] - */ - public function getValues() - { - return $this->values; - } - - /** - * @param Reference[] $values The service references to put in the set - */ - public function setValues(array $values) - { - foreach ($values as $k => $v) { - if (null !== $v && !$v instanceof Reference) { - throw new InvalidArgumentException(sprintf('A "%s" must hold only Reference instances, "%s" given.', __CLASS__, get_debug_type($v))); - } - } - - $this->values = $values; - } -} diff --git a/lib/symfony/dependency-injection/Argument/RewindableGenerator.php b/lib/symfony/dependency-injection/Argument/RewindableGenerator.php deleted file mode 100644 index 41fec786f..000000000 --- a/lib/symfony/dependency-injection/Argument/RewindableGenerator.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Argument; - -/** - * @internal - */ -class RewindableGenerator implements \IteratorAggregate, \Countable -{ - private $generator; - private $count; - - /** - * @param int|callable $count - */ - public function __construct(callable $generator, $count) - { - $this->generator = $generator; - $this->count = $count; - } - - public function getIterator(): \Traversable - { - $g = $this->generator; - - return $g(); - } - - public function count(): int - { - if (\is_callable($count = $this->count)) { - $this->count = $count(); - } - - return $this->count; - } -} diff --git a/lib/symfony/dependency-injection/Argument/ServiceClosureArgument.php b/lib/symfony/dependency-injection/Argument/ServiceClosureArgument.php deleted file mode 100644 index 6331affa4..000000000 --- a/lib/symfony/dependency-injection/Argument/ServiceClosureArgument.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Argument; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Represents a service wrapped in a memoizing closure. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class ServiceClosureArgument implements ArgumentInterface -{ - private $values; - - public function __construct(Reference $reference) - { - $this->values = [$reference]; - } - - /** - * {@inheritdoc} - */ - public function getValues() - { - return $this->values; - } - - /** - * {@inheritdoc} - */ - public function setValues(array $values) - { - if ([0] !== array_keys($values) || !($values[0] instanceof Reference || null === $values[0])) { - throw new InvalidArgumentException('A ServiceClosureArgument must hold one and only one Reference.'); - } - - $this->values = $values; - } -} diff --git a/lib/symfony/dependency-injection/Argument/ServiceLocator.php b/lib/symfony/dependency-injection/Argument/ServiceLocator.php deleted file mode 100644 index bc138fe23..000000000 --- a/lib/symfony/dependency-injection/Argument/ServiceLocator.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Argument; - -use Symfony\Component\DependencyInjection\ServiceLocator as BaseServiceLocator; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -class ServiceLocator extends BaseServiceLocator -{ - private $factory; - private $serviceMap; - private $serviceTypes; - - public function __construct(\Closure $factory, array $serviceMap, array $serviceTypes = null) - { - $this->factory = $factory; - $this->serviceMap = $serviceMap; - $this->serviceTypes = $serviceTypes; - parent::__construct($serviceMap); - } - - /** - * {@inheritdoc} - * - * @return mixed - */ - public function get(string $id) - { - return isset($this->serviceMap[$id]) ? ($this->factory)(...$this->serviceMap[$id]) : parent::get($id); - } - - /** - * {@inheritdoc} - */ - public function getProvidedServices(): array - { - return $this->serviceTypes ?? $this->serviceTypes = array_map(function () { return '?'; }, $this->serviceMap); - } -} diff --git a/lib/symfony/dependency-injection/Argument/ServiceLocatorArgument.php b/lib/symfony/dependency-injection/Argument/ServiceLocatorArgument.php deleted file mode 100644 index fcbf478c6..000000000 --- a/lib/symfony/dependency-injection/Argument/ServiceLocatorArgument.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Argument; - -use Symfony\Component\DependencyInjection\Reference; - -/** - * Represents a closure acting as a service locator. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class ServiceLocatorArgument implements ArgumentInterface -{ - use ReferenceSetArgumentTrait; - - private $taggedIteratorArgument; - - /** - * @param Reference[]|TaggedIteratorArgument $values - */ - public function __construct($values = []) - { - if ($values instanceof TaggedIteratorArgument) { - $this->taggedIteratorArgument = $values; - $this->values = []; - } else { - $this->setValues($values); - } - } - - public function getTaggedIteratorArgument(): ?TaggedIteratorArgument - { - return $this->taggedIteratorArgument; - } -} diff --git a/lib/symfony/dependency-injection/Argument/TaggedIteratorArgument.php b/lib/symfony/dependency-injection/Argument/TaggedIteratorArgument.php deleted file mode 100644 index 1ba8de790..000000000 --- a/lib/symfony/dependency-injection/Argument/TaggedIteratorArgument.php +++ /dev/null @@ -1,73 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Argument; - -/** - * Represents a collection of services found by tag name to lazily iterate over. - * - * @author Roland Franssen <franssen.roland@gmail.com> - */ -class TaggedIteratorArgument extends IteratorArgument -{ - private $tag; - private $indexAttribute; - private $defaultIndexMethod; - private $defaultPriorityMethod; - private $needsIndexes = false; - - /** - * @param string $tag The name of the tag identifying the target services - * @param string|null $indexAttribute The name of the attribute that defines the key referencing each service in the tagged collection - * @param string|null $defaultIndexMethod The static method that should be called to get each service's key when their tag doesn't define the previous attribute - * @param bool $needsIndexes Whether indexes are required and should be generated when computing the map - * @param string|null $defaultPriorityMethod The static method that should be called to get each service's priority when their tag doesn't define the "priority" attribute - */ - public function __construct(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null, bool $needsIndexes = false, string $defaultPriorityMethod = null) - { - parent::__construct([]); - - if (null === $indexAttribute && $needsIndexes) { - $indexAttribute = preg_match('/[^.]++$/', $tag, $m) ? $m[0] : $tag; - } - - $this->tag = $tag; - $this->indexAttribute = $indexAttribute; - $this->defaultIndexMethod = $defaultIndexMethod ?: ($indexAttribute ? 'getDefault'.str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $indexAttribute))).'Name' : null); - $this->needsIndexes = $needsIndexes; - $this->defaultPriorityMethod = $defaultPriorityMethod ?: ($indexAttribute ? 'getDefault'.str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $indexAttribute))).'Priority' : null); - } - - public function getTag() - { - return $this->tag; - } - - public function getIndexAttribute(): ?string - { - return $this->indexAttribute; - } - - public function getDefaultIndexMethod(): ?string - { - return $this->defaultIndexMethod; - } - - public function needsIndexes(): bool - { - return $this->needsIndexes; - } - - public function getDefaultPriorityMethod(): ?string - { - return $this->defaultPriorityMethod; - } -} diff --git a/lib/symfony/dependency-injection/Attribute/AsTaggedItem.php b/lib/symfony/dependency-injection/Attribute/AsTaggedItem.php deleted file mode 100644 index 232033633..000000000 --- a/lib/symfony/dependency-injection/Attribute/AsTaggedItem.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Attribute; - -/** - * An attribute to tell under which index and priority a service class should be found in tagged iterators/locators. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -#[\Attribute(\Attribute::TARGET_CLASS)] -class AsTaggedItem -{ - public function __construct( - public ?string $index = null, - public ?int $priority = null, - ) { - } -} diff --git a/lib/symfony/dependency-injection/Attribute/Autoconfigure.php b/lib/symfony/dependency-injection/Attribute/Autoconfigure.php deleted file mode 100644 index abab04010..000000000 --- a/lib/symfony/dependency-injection/Attribute/Autoconfigure.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Attribute; - -/** - * An attribute to tell how a base type should be autoconfigured. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)] -class Autoconfigure -{ - public function __construct( - public ?array $tags = null, - public ?array $calls = null, - public ?array $bind = null, - public bool|string|null $lazy = null, - public ?bool $public = null, - public ?bool $shared = null, - public ?bool $autowire = null, - public ?array $properties = null, - public array|string|null $configurator = null, - ) { - } -} diff --git a/lib/symfony/dependency-injection/Attribute/AutoconfigureTag.php b/lib/symfony/dependency-injection/Attribute/AutoconfigureTag.php deleted file mode 100644 index ed5807ca0..000000000 --- a/lib/symfony/dependency-injection/Attribute/AutoconfigureTag.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Attribute; - -/** - * An attribute to tell how a base type should be tagged. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)] -class AutoconfigureTag extends Autoconfigure -{ - public function __construct(string $name = null, array $attributes = []) - { - parent::__construct( - tags: [ - [$name ?? 0 => $attributes], - ] - ); - } -} diff --git a/lib/symfony/dependency-injection/Attribute/TaggedIterator.php b/lib/symfony/dependency-injection/Attribute/TaggedIterator.php deleted file mode 100644 index d498f4647..000000000 --- a/lib/symfony/dependency-injection/Attribute/TaggedIterator.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Attribute; - -#[\Attribute(\Attribute::TARGET_PARAMETER)] -class TaggedIterator -{ - public function __construct( - public string $tag, - public ?string $indexAttribute = null, - public ?string $defaultIndexMethod = null, - public ?string $defaultPriorityMethod = null, - ) { - } -} diff --git a/lib/symfony/dependency-injection/Attribute/TaggedLocator.php b/lib/symfony/dependency-injection/Attribute/TaggedLocator.php deleted file mode 100644 index 4617e0f51..000000000 --- a/lib/symfony/dependency-injection/Attribute/TaggedLocator.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Attribute; - -#[\Attribute(\Attribute::TARGET_PARAMETER)] -class TaggedLocator -{ - public function __construct( - public string $tag, - public ?string $indexAttribute = null, - public ?string $defaultIndexMethod = null, - public ?string $defaultPriorityMethod = null, - ) { - } -} diff --git a/lib/symfony/dependency-injection/Attribute/Target.php b/lib/symfony/dependency-injection/Attribute/Target.php deleted file mode 100644 index a7a4d8b5f..000000000 --- a/lib/symfony/dependency-injection/Attribute/Target.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Attribute; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -/** - * An attribute to tell how a dependency is used and hint named autowiring aliases. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -#[\Attribute(\Attribute::TARGET_PARAMETER)] -final class Target -{ - /** - * @var string - */ - public $name; - - public function __construct(string $name) - { - $this->name = lcfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $name)))); - } - - public static function parseName(\ReflectionParameter $parameter): string - { - if (80000 > \PHP_VERSION_ID || !$target = $parameter->getAttributes(self::class)[0] ?? null) { - return $parameter->name; - } - - $name = $target->newInstance()->name; - - if (!preg_match('/^[a-zA-Z_\x7f-\xff]/', $name)) { - if (($function = $parameter->getDeclaringFunction()) instanceof \ReflectionMethod) { - $function = $function->class.'::'.$function->name; - } else { - $function = $function->name; - } - - throw new InvalidArgumentException(sprintf('Invalid #[Target] name "%s" on parameter "$%s" of "%s()": the first character must be a letter.', $name, $parameter->name, $function)); - } - - return $name; - } -} diff --git a/lib/symfony/dependency-injection/Attribute/When.php b/lib/symfony/dependency-injection/Attribute/When.php deleted file mode 100644 index 60b7af04b..000000000 --- a/lib/symfony/dependency-injection/Attribute/When.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Attribute; - -/** - * An attribute to tell under which environement this class should be registered as a service. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::TARGET_FUNCTION | \Attribute::IS_REPEATABLE)] -class When -{ - public function __construct( - public string $env, - ) { - } -} diff --git a/lib/symfony/dependency-injection/CHANGELOG.md b/lib/symfony/dependency-injection/CHANGELOG.md deleted file mode 100644 index 88a6df8df..000000000 --- a/lib/symfony/dependency-injection/CHANGELOG.md +++ /dev/null @@ -1,302 +0,0 @@ -CHANGELOG -========= - -5.4 ---- - * Add `$defaultIndexMethod` and `$defaultPriorityMethod` to `TaggedIterator` and `TaggedLocator` attributes - * Add `service_closure()` to the PHP-DSL - * Add support for autoconfigurable attributes on methods, properties and parameters - * Make auto-aliases private by default - * Add support for autowiring union and intersection types - -5.3 ---- - - * Add `ServicesConfigurator::remove()` in the PHP-DSL - * Add `%env(not:...)%` processor to negate boolean values - * Add support for loading autoconfiguration rules via the `#[Autoconfigure]` and `#[AutoconfigureTag]` attributes on PHP 8 - * Add `#[AsTaggedItem]` attribute for defining the index and priority of classes found in tagged iterators/locators - * Add autoconfigurable attributes - * Add support for autowiring tagged iterators and locators via attributes on PHP 8 - * Add support for per-env configuration in XML and Yaml loaders - * Add `ContainerBuilder::willBeAvailable()` to help with conditional configuration - * Add support an integer return value for default_index_method - * Add `#[When(env: 'foo')]` to skip autoregistering a class when the env doesn't match - * Add `env()` and `EnvConfigurator` in the PHP-DSL - * Add support for `ConfigBuilder` in the `PhpFileLoader` - * Add `ContainerConfigurator::env()` to get the current environment - * Add `#[Target]` to tell how a dependency is used and hint named autowiring aliases - -5.2.0 ------ - - * added `param()` and `abstract_arg()` in the PHP-DSL - * deprecated `Definition::setPrivate()` and `Alias::setPrivate()`, use `setPublic()` instead - * added support for the `#[Required]` attribute - -5.1.0 ------ - - * deprecated `inline()` in favor of `inline_service()` and `ref()` in favor of `service()` when using the PHP-DSL - * allow decorators to reference their decorated service using the special `.inner` id - * added support to autowire public typed properties in php 7.4 - * added support for defining method calls, a configurator, and property setters in `InlineServiceConfigurator` - * added possibility to define abstract service arguments - * allowed mixing "parent" and instanceof-conditionals/defaults/bindings - * updated the signature of method `Definition::setDeprecated()` to `Definition::setDeprecation(string $package, string $version, string $message)` - * updated the signature of method `Alias::setDeprecated()` to `Alias::setDeprecation(string $package, string $version, string $message)` - * updated the signature of method `DeprecateTrait::deprecate()` to `DeprecateTrait::deprecation(string $package, string $version, string $message)` - * deprecated the `Psr\Container\ContainerInterface` and `Symfony\Component\DependencyInjection\ContainerInterface` aliases of the `service_container` service, - configure them explicitly instead - * added class `Symfony\Component\DependencyInjection\Dumper\Preloader` to help with preloading on PHP 7.4+ - * added tags `container.preload`/`.no_preload` to declare extra classes to preload/services to not preload - * allowed loading and dumping tags with an attribute named "name" - * deprecated `Definition::getDeprecationMessage()`, use `Definition::getDeprecation()` instead - * deprecated `Alias::getDeprecationMessage()`, use `Alias::getDeprecation()` instead - * added support of PHP8 static return type for withers - * added `AliasDeprecatedPublicServicesPass` to deprecate public services to private - -5.0.0 ------ - - * removed support for auto-discovered extension configuration class which does not implement `ConfigurationInterface` - * removed support for non-string default env() parameters - * moved `ServiceSubscriberInterface` to the `Symfony\Contracts\Service` namespace - * removed `RepeatedPass` and `RepeatablePassInterface` - * removed support for short factory/configurator syntax from `YamlFileLoader` - * removed `ResettableContainerInterface`, use `ResetInterface` instead - * added argument `$returnsClone` to `Definition::addMethodCall()` - * removed `tagged`, use `tagged_iterator` instead - -4.4.0 ------ - - * added `CheckTypeDeclarationsPass` to check injected parameters type during compilation - * added support for opcache.preload by generating a preloading script in the cache folder - * added support for dumping the container in one file instead of many files - * deprecated support for short factories and short configurators in Yaml - * added `tagged_iterator` alias for `tagged` which might be deprecated in a future version - * deprecated passing an instance of `Symfony\Component\DependencyInjection\Parameter` as class name to `Symfony\Component\DependencyInjection\Definition` - * added support for binding iterable and tagged services - * made singly-implemented interfaces detection be scoped by file - * added ability to define a static priority method for tagged service - * added support for improved syntax to define method calls in Yaml - * made the `%env(base64:...)%` processor able to decode base64url - * added ability to choose behavior of decorations on non existent decorated services - -4.3.0 ------ - - * added `%env(trim:...)%` processor to trim a string value - * added `%env(default:param_name:...)%` processor to fallback to a parameter or to null when using `%env(default::...)%` - * added `%env(url:...)%` processor to convert an URL or DNS into an array of components - * added `%env(query_string:...)%` processor to convert a query string into an array of key values - * added support for deprecating aliases - * made `ContainerParametersResource` final and not implement `Serializable` anymore - * added `ReverseContainer`: a container that turns services back to their ids - * added ability to define an index for a tagged collection - * added ability to define an index for services in an injected service locator argument - * made `ServiceLocator` implement `ServiceProviderInterface` - * deprecated support for non-string default env() parameters - * added `%env(require:...)%` processor to `require()` a PHP file and use the value returned from it - -4.2.0 ------ - - * added `ContainerBuilder::registerAliasForArgument()` to support autowiring by type+name - * added support for binding by type+name - * added `ServiceSubscriberTrait` to ease implementing `ServiceSubscriberInterface` using methods' return types - * added `ServiceLocatorArgument` and `!service_locator` config tag for creating optimized service-locators - * added support for autoconfiguring bindings - * added `%env(key:...)%` processor to fetch a specific key from an array - * deprecated `ServiceSubscriberInterface`, use the same interface from the `Symfony\Contracts\Service` namespace instead - * deprecated `ResettableContainerInterface`, use `Symfony\Contracts\Service\ResetInterface` instead - -4.1.0 ------ - - * added support for variadics in named arguments - * added PSR-11 `ContainerBagInterface` and its `ContainerBag` implementation to access parameters as-a-service - * added support for service's decorators autowiring - * deprecated the `TypedReference::canBeAutoregistered()` and `TypedReference::getRequiringClass()` methods - * environment variables are validated when used in extension configuration - * deprecated support for auto-discovered extension configuration class which does not implement `ConfigurationInterface` - -4.0.0 ------ - - * Relying on service auto-registration while autowiring is not supported anymore. - Explicitly inject your dependencies or create services whose ids are - their fully-qualified class name. - - Before: - - ```php - namespace App\Controller; - - use App\Mailer; - - class DefaultController - { - public function __construct(Mailer $mailer) { - // ... - } - - // ... - } - ``` - ```yml - services: - App\Controller\DefaultController: - autowire: true - ``` - - After: - - ```php - // same PHP code - ``` - ```yml - services: - App\Controller\DefaultController: - autowire: true - - # or - # App\Controller\DefaultController: - # arguments: { $mailer: "@App\Mailer" } - - App\Mailer: - autowire: true - ``` - * removed autowiring services based on the types they implement - * added a third `$methodName` argument to the `getProxyFactoryCode()` method - of the `DumperInterface` - * removed support for autowiring types - * removed `Container::isFrozen` - * removed support for dumping an ucompiled container in `PhpDumper` - * removed support for generating a dumped `Container` without populating the method map - * removed support for case insensitive service identifiers - * removed the `DefinitionDecorator` class, replaced by `ChildDefinition` - * removed the `AutowireServiceResource` class and related `AutowirePass::createResourceForClass()` method - * removed `LoggingFormatter`, `Compiler::getLoggingFormatter()` and `addLogMessage()` class and methods, use the `ContainerBuilder::log()` method instead - * removed `FactoryReturnTypePass` - * removed `ContainerBuilder::addClassResource()`, use the `addObjectResource()` or the `getReflectionClass()` method instead. - * removed support for top-level anonymous services - * removed silent behavior for unused attributes and elements - * removed support for setting and accessing private services in `Container` - * removed support for setting pre-defined services in `Container` - * removed support for case insensitivity of parameter names - * removed `AutowireExceptionPass` and `AutowirePass::getAutowiringExceptions()`, use `Definition::addError()` and the `DefinitionErrorExceptionPass` instead - -3.4.0 ------ - - * moved the `ExtensionCompilerPass` to before-optimization passes with priority -1000 - * deprecated "public-by-default" definitions and aliases, the new default will be "private" in 4.0 - * added `EnvVarProcessorInterface` and corresponding "container.env_var_processor" tag for processing env vars - * added support for ignore-on-uninitialized references - * deprecated service auto-registration while autowiring - * deprecated the ability to check for the initialization of a private service with the `Container::initialized()` method - * deprecated support for top-level anonymous services in XML - * deprecated case insensitivity of parameter names - * deprecated the `ResolveDefinitionTemplatesPass` class in favor of `ResolveChildDefinitionsPass` - * added `TaggedIteratorArgument` with YAML (`!tagged foo`) and XML (`<service type="tagged"/>`) support - * deprecated `AutowireExceptionPass` and `AutowirePass::getAutowiringExceptions()`, use `Definition::addError()` and the `DefinitionErrorExceptionPass` instead - -3.3.0 ------ - - * deprecated autowiring services based on the types they implement; - rename (or alias) your services to their FQCN id to make them autowirable - * added "ServiceSubscriberInterface" - to allow for per-class explicit service-locator definitions - * added "container.service_locator" tag for defining service-locator services - * added anonymous services support in YAML configuration files using the `!service` tag. - * added "TypedReference" and "ServiceClosureArgument" for creating service-locator services - * added `ServiceLocator` - a PSR-11 container holding a set of services to be lazily loaded - * added "instanceof" section for local interface-defined configs - * added prototype services for PSR4-based discovery and registration - * added `ContainerBuilder::getReflectionClass()` for retrieving and tracking reflection class info - * deprecated `ContainerBuilder::getClassResource()`, use `ContainerBuilder::getReflectionClass()` or `ContainerBuilder::addObjectResource()` instead - * added `ContainerBuilder::fileExists()` for checking and tracking file or directory existence - * deprecated autowiring-types, use aliases instead - * added support for omitting the factory class name in a service definition if the definition class is set - * deprecated case insensitivity of service identifiers - * added "iterator" argument type for lazy iteration over a set of values and services - * added file-wide configurable defaults for service attributes "public", "tags", - "autowire" and "autoconfigure" - * made the "class" attribute optional, using the "id" as fallback - * using the `PhpDumper` with an uncompiled `ContainerBuilder` is deprecated and - will not be supported anymore in 4.0 - * deprecated the `DefinitionDecorator` class in favor of `ChildDefinition` - * allow config files to be loaded using a glob pattern - * [BC BREAK] the `NullDumper` class is now final - -3.2.0 ------ - - * allowed to prioritize compiler passes by introducing a third argument to `PassConfig::addPass()`, to `Compiler::addPass` and to `ContainerBuilder::addCompilerPass()` - * added support for PHP constants in YAML configuration files - * deprecated the ability to set or unset a private service with the `Container::set()` method - * deprecated the ability to check for the existence of a private service with the `Container::has()` method - * deprecated the ability to request a private service with the `Container::get()` method - * deprecated support for generating a dumped `Container` without populating the method map - -3.0.0 ------ - - * removed all deprecated codes from 2.x versions - -2.8.0 ------ - - * deprecated the abstract ContainerAware class in favor of ContainerAwareTrait - * deprecated IntrospectableContainerInterface, to be merged with ContainerInterface in 3.0 - * allowed specifying a directory to recursively load all configuration files it contains - * deprecated the concept of scopes - * added `Definition::setShared()` and `Definition::isShared()` - * added ResettableContainerInterface to be able to reset the container to release memory on shutdown - * added a way to define the priority of service decoration - * added support for service autowiring - -2.7.0 ------ - - * deprecated synchronized services - -2.6.0 ------ - - * added new factory syntax and deprecated the old one - -2.5.0 ------ - - * added DecoratorServicePass and a way to override a service definition (Definition::setDecoratedService()) - * deprecated SimpleXMLElement class. - -2.4.0 ------ - - * added support for expressions in service definitions - * added ContainerAwareTrait to add default container aware behavior to a class - -2.2.0 ------ - - * added Extension::isConfigEnabled() to ease working with enableable configurations - * added an Extension base class with sensible defaults to be used in conjunction - with the Config component. - * added PrependExtensionInterface (to be able to allow extensions to prepend - application configuration settings for any Bundle) - -2.1.0 ------ - - * added IntrospectableContainerInterface (to be able to check if a service - has been initialized or not) - * added ConfigurationExtensionInterface - * added Definition::clearTag() - * component exceptions that inherit base SPL classes are now used exclusively - (this includes dumped containers) - * [BC BREAK] fixed unescaping of class arguments, method - ParameterBag::unescapeValue() was made public diff --git a/lib/symfony/dependency-injection/ChildDefinition.php b/lib/symfony/dependency-injection/ChildDefinition.php deleted file mode 100644 index 5c648ba61..000000000 --- a/lib/symfony/dependency-injection/ChildDefinition.php +++ /dev/null @@ -1,104 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException; - -/** - * This definition extends another definition. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class ChildDefinition extends Definition -{ - private $parent; - - /** - * @param string $parent The id of Definition instance to decorate - */ - public function __construct(string $parent) - { - $this->parent = $parent; - } - - /** - * Returns the Definition to inherit from. - * - * @return string - */ - public function getParent() - { - return $this->parent; - } - - /** - * Sets the Definition to inherit from. - * - * @return $this - */ - public function setParent(string $parent) - { - $this->parent = $parent; - - return $this; - } - - /** - * Gets an argument to pass to the service constructor/factory method. - * - * If replaceArgument() has been used to replace an argument, this method - * will return the replacement value. - * - * @param int|string $index - * - * @return mixed - * - * @throws OutOfBoundsException When the argument does not exist - */ - public function getArgument($index) - { - if (\array_key_exists('index_'.$index, $this->arguments)) { - return $this->arguments['index_'.$index]; - } - - return parent::getArgument($index); - } - - /** - * You should always use this method when overwriting existing arguments - * of the parent definition. - * - * If you directly call setArguments() keep in mind that you must follow - * certain conventions when you want to overwrite the arguments of the - * parent definition, otherwise your arguments will only be appended. - * - * @param int|string $index - * @param mixed $value - * - * @return $this - * - * @throws InvalidArgumentException when $index isn't an integer - */ - public function replaceArgument($index, $value) - { - if (\is_int($index)) { - $this->arguments['index_'.$index] = $value; - } elseif (str_starts_with($index, '$')) { - $this->arguments[$index] = $value; - } else { - throw new InvalidArgumentException('The argument must be an existing index or the name of a constructor\'s parameter.'); - } - - return $this; - } -} diff --git a/lib/symfony/dependency-injection/Compiler/AbstractRecursivePass.php b/lib/symfony/dependency-injection/Compiler/AbstractRecursivePass.php deleted file mode 100644 index 362c5f571..000000000 --- a/lib/symfony/dependency-injection/Compiler/AbstractRecursivePass.php +++ /dev/null @@ -1,242 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\LogicException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\ExpressionLanguage; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\ExpressionLanguage\Expression; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -abstract class AbstractRecursivePass implements CompilerPassInterface -{ - /** - * @var ContainerBuilder - */ - protected $container; - protected $currentId; - - private $processExpressions = false; - private $expressionLanguage; - private $inExpression = false; - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - $this->container = $container; - - try { - $this->processValue($container->getDefinitions(), true); - } finally { - $this->container = null; - } - } - - protected function enableExpressionProcessing() - { - $this->processExpressions = true; - } - - protected function inExpression(bool $reset = true): bool - { - $inExpression = $this->inExpression; - if ($reset) { - $this->inExpression = false; - } - - return $inExpression; - } - - /** - * Processes a value found in a definition tree. - * - * @param mixed $value - * - * @return mixed - */ - protected function processValue($value, bool $isRoot = false) - { - if (\is_array($value)) { - foreach ($value as $k => $v) { - if ($isRoot) { - $this->currentId = $k; - } - if ($v !== $processedValue = $this->processValue($v, $isRoot)) { - $value[$k] = $processedValue; - } - } - } elseif ($value instanceof ArgumentInterface) { - $value->setValues($this->processValue($value->getValues())); - } elseif ($value instanceof Expression && $this->processExpressions) { - $this->getExpressionLanguage()->compile((string) $value, ['this' => 'container']); - } elseif ($value instanceof Definition) { - $value->setArguments($this->processValue($value->getArguments())); - $value->setProperties($this->processValue($value->getProperties())); - $value->setMethodCalls($this->processValue($value->getMethodCalls())); - - $changes = $value->getChanges(); - if (isset($changes['factory'])) { - $value->setFactory($this->processValue($value->getFactory())); - } - if (isset($changes['configurator'])) { - $value->setConfigurator($this->processValue($value->getConfigurator())); - } - } - - return $value; - } - - /** - * @return \ReflectionFunctionAbstract|null - * - * @throws RuntimeException - */ - protected function getConstructor(Definition $definition, bool $required) - { - if ($definition->isSynthetic()) { - return null; - } - - if (\is_string($factory = $definition->getFactory())) { - if (!\function_exists($factory)) { - throw new RuntimeException(sprintf('Invalid service "%s": function "%s" does not exist.', $this->currentId, $factory)); - } - $r = new \ReflectionFunction($factory); - if (false !== $r->getFileName() && file_exists($r->getFileName())) { - $this->container->fileExists($r->getFileName()); - } - - return $r; - } - - if ($factory) { - [$class, $method] = $factory; - - if ('__construct' === $method) { - throw new RuntimeException(sprintf('Invalid service "%s": "__construct()" cannot be used as a factory method.', $this->currentId)); - } - - if ($class instanceof Reference) { - $factoryDefinition = $this->container->findDefinition((string) $class); - while ((null === $class = $factoryDefinition->getClass()) && $factoryDefinition instanceof ChildDefinition) { - $factoryDefinition = $this->container->findDefinition($factoryDefinition->getParent()); - } - } elseif ($class instanceof Definition) { - $class = $class->getClass(); - } elseif (null === $class) { - $class = $definition->getClass(); - } - - return $this->getReflectionMethod(new Definition($class), $method); - } - - while ((null === $class = $definition->getClass()) && $definition instanceof ChildDefinition) { - $definition = $this->container->findDefinition($definition->getParent()); - } - - try { - if (!$r = $this->container->getReflectionClass($class)) { - if (null === $class) { - throw new RuntimeException(sprintf('Invalid service "%s": the class is not set.', $this->currentId)); - } - - throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class)); - } - } catch (\ReflectionException $e) { - throw new RuntimeException(sprintf('Invalid service "%s": ', $this->currentId).lcfirst($e->getMessage())); - } - if (!$r = $r->getConstructor()) { - if ($required) { - throw new RuntimeException(sprintf('Invalid service "%s": class%s has no constructor.', $this->currentId, sprintf($class !== $this->currentId ? ' "%s"' : '', $class))); - } - } elseif (!$r->isPublic()) { - throw new RuntimeException(sprintf('Invalid service "%s": ', $this->currentId).sprintf($class !== $this->currentId ? 'constructor of class "%s"' : 'its constructor', $class).' must be public.'); - } - - return $r; - } - - /** - * @throws RuntimeException - * - * @return \ReflectionFunctionAbstract - */ - protected function getReflectionMethod(Definition $definition, string $method) - { - if ('__construct' === $method) { - return $this->getConstructor($definition, true); - } - - while ((null === $class = $definition->getClass()) && $definition instanceof ChildDefinition) { - $definition = $this->container->findDefinition($definition->getParent()); - } - - if (null === $class) { - throw new RuntimeException(sprintf('Invalid service "%s": the class is not set.', $this->currentId)); - } - - if (!$r = $this->container->getReflectionClass($class)) { - throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class)); - } - - if (!$r->hasMethod($method)) { - if ($r->hasMethod('__call') && ($r = $r->getMethod('__call')) && $r->isPublic()) { - return new \ReflectionMethod(static function (...$arguments) {}, '__invoke'); - } - - throw new RuntimeException(sprintf('Invalid service "%s": method "%s()" does not exist.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method)); - } - - $r = $r->getMethod($method); - if (!$r->isPublic()) { - throw new RuntimeException(sprintf('Invalid service "%s": method "%s()" must be public.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method)); - } - - return $r; - } - - private function getExpressionLanguage(): ExpressionLanguage - { - if (null === $this->expressionLanguage) { - if (!class_exists(ExpressionLanguage::class)) { - throw new LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed. Try running "composer require symfony/expression-language".'); - } - - $providers = $this->container->getExpressionLanguageProviders(); - $this->expressionLanguage = new ExpressionLanguage(null, $providers, function (string $arg): string { - if ('""' === substr_replace($arg, '', 1, -1)) { - $id = stripcslashes(substr($arg, 1, -1)); - $this->inExpression = true; - $arg = $this->processValue(new Reference($id)); - $this->inExpression = false; - if (!$arg instanceof Reference) { - throw new RuntimeException(sprintf('"%s::processValue()" must return a Reference when processing an expression, "%s" returned for service("%s").', static::class, get_debug_type($arg), $id)); - } - $arg = sprintf('"%s"', $arg); - } - - return sprintf('$this->get(%s)', $arg); - }); - } - - return $this->expressionLanguage; - } -} diff --git a/lib/symfony/dependency-injection/Compiler/AliasDeprecatedPublicServicesPass.php b/lib/symfony/dependency-injection/Compiler/AliasDeprecatedPublicServicesPass.php deleted file mode 100644 index 8d3fefe75..000000000 --- a/lib/symfony/dependency-injection/Compiler/AliasDeprecatedPublicServicesPass.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; - -final class AliasDeprecatedPublicServicesPass extends AbstractRecursivePass -{ - private $tagName; - - private $aliases = []; - - public function __construct(string $tagName = 'container.private') - { - if (0 < \func_num_args()) { - trigger_deprecation('symfony/dependency-injection', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->tagName = $tagName; - } - - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if ($value instanceof Reference && isset($this->aliases[$id = (string) $value])) { - return new Reference($this->aliases[$id], $value->getInvalidBehavior()); - } - - return parent::processValue($value, $isRoot); - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - foreach ($container->findTaggedServiceIds($this->tagName) as $id => $tags) { - if (null === $package = $tags[0]['package'] ?? null) { - throw new InvalidArgumentException(sprintf('The "package" attribute is mandatory for the "%s" tag on the "%s" service.', $this->tagName, $id)); - } - - if (null === $version = $tags[0]['version'] ?? null) { - throw new InvalidArgumentException(sprintf('The "version" attribute is mandatory for the "%s" tag on the "%s" service.', $this->tagName, $id)); - } - - $definition = $container->getDefinition($id); - if (!$definition->isPublic() || $definition->isPrivate()) { - continue; - } - - $container - ->setAlias($id, $aliasId = '.'.$this->tagName.'.'.$id) - ->setPublic(true) - ->setDeprecated($package, $version, 'Accessing the "%alias_id%" service directly from the container is deprecated, use dependency injection instead.'); - - $container->setDefinition($aliasId, $definition); - - $this->aliases[$id] = $aliasId; - } - - parent::process($container); - } -} diff --git a/lib/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php b/lib/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php deleted file mode 100644 index b23303581..000000000 --- a/lib/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php +++ /dev/null @@ -1,191 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Run this pass before passes that need to know more about the relation of - * your services. - * - * This class will populate the ServiceReferenceGraph with information. You can - * retrieve the graph in other passes from the compiler. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - * @author Nicolas Grekas <p@tchwork.com> - */ -class AnalyzeServiceReferencesPass extends AbstractRecursivePass -{ - private $graph; - private $currentDefinition; - private $onlyConstructorArguments; - private $hasProxyDumper; - private $lazy; - private $byConstructor; - private $byFactory; - private $definitions; - private $aliases; - - /** - * @param bool $onlyConstructorArguments Sets this Service Reference pass to ignore method calls - */ - public function __construct(bool $onlyConstructorArguments = false, bool $hasProxyDumper = true) - { - $this->onlyConstructorArguments = $onlyConstructorArguments; - $this->hasProxyDumper = $hasProxyDumper; - $this->enableExpressionProcessing(); - } - - /** - * Processes a ContainerBuilder object to populate the service reference graph. - */ - public function process(ContainerBuilder $container) - { - $this->container = $container; - $this->graph = $container->getCompiler()->getServiceReferenceGraph(); - $this->graph->clear(); - $this->lazy = false; - $this->byConstructor = false; - $this->byFactory = false; - $this->definitions = $container->getDefinitions(); - $this->aliases = $container->getAliases(); - - foreach ($this->aliases as $id => $alias) { - $targetId = $this->getDefinitionId((string) $alias); - $this->graph->connect($id, $alias, $targetId, null !== $targetId ? $this->container->getDefinition($targetId) : null, null); - } - - try { - parent::process($container); - } finally { - $this->aliases = $this->definitions = []; - } - } - - protected function processValue($value, bool $isRoot = false) - { - $lazy = $this->lazy; - $inExpression = $this->inExpression(); - - if ($value instanceof ArgumentInterface) { - $this->lazy = !$this->byFactory || !$value instanceof IteratorArgument; - parent::processValue($value->getValues()); - $this->lazy = $lazy; - - return $value; - } - if ($value instanceof Reference) { - $targetId = $this->getDefinitionId((string) $value); - $targetDefinition = null !== $targetId ? $this->container->getDefinition($targetId) : null; - - $this->graph->connect( - $this->currentId, - $this->currentDefinition, - $targetId, - $targetDefinition, - $value, - $this->lazy || ($this->hasProxyDumper && $targetDefinition && $targetDefinition->isLazy()), - ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior(), - $this->byConstructor - ); - - if ($inExpression) { - $this->graph->connect( - '.internal.reference_in_expression', - null, - $targetId, - $targetDefinition, - $value, - $this->lazy || ($targetDefinition && $targetDefinition->isLazy()), - true - ); - } - - return $value; - } - if (!$value instanceof Definition) { - return parent::processValue($value, $isRoot); - } - if ($isRoot) { - if ($value->isSynthetic() || $value->isAbstract()) { - return $value; - } - $this->currentDefinition = $value; - } elseif ($this->currentDefinition === $value) { - return $value; - } - $this->lazy = false; - - $byConstructor = $this->byConstructor; - $this->byConstructor = $isRoot || $byConstructor; - - $byFactory = $this->byFactory; - $this->byFactory = true; - $this->processValue($value->getFactory()); - $this->byFactory = $byFactory; - $this->processValue($value->getArguments()); - - $properties = $value->getProperties(); - $setters = $value->getMethodCalls(); - - // Any references before a "wither" are part of the constructor-instantiation graph - $lastWitherIndex = null; - foreach ($setters as $k => $call) { - if ($call[2] ?? false) { - $lastWitherIndex = $k; - } - } - - if (null !== $lastWitherIndex) { - $this->processValue($properties); - $setters = $properties = []; - - foreach ($value->getMethodCalls() as $k => $call) { - if (null === $lastWitherIndex) { - $setters[] = $call; - continue; - } - - if ($lastWitherIndex === $k) { - $lastWitherIndex = null; - } - - $this->processValue($call); - } - } - - $this->byConstructor = $byConstructor; - - if (!$this->onlyConstructorArguments) { - $this->processValue($properties); - $this->processValue($setters); - $this->processValue($value->getConfigurator()); - } - $this->lazy = $lazy; - - return $value; - } - - private function getDefinitionId(string $id): ?string - { - while (isset($this->aliases[$id])) { - $id = (string) $this->aliases[$id]; - } - - return isset($this->definitions[$id]) ? $id : null; - } -} diff --git a/lib/symfony/dependency-injection/Compiler/AttributeAutoconfigurationPass.php b/lib/symfony/dependency-injection/Compiler/AttributeAutoconfigurationPass.php deleted file mode 100644 index 4db7185cf..000000000 --- a/lib/symfony/dependency-injection/Compiler/AttributeAutoconfigurationPass.php +++ /dev/null @@ -1,168 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\LogicException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; - -/** - * @author Alexander M. Turek <me@derrabus.de> - */ -final class AttributeAutoconfigurationPass extends AbstractRecursivePass -{ - private $classAttributeConfigurators = []; - private $methodAttributeConfigurators = []; - private $propertyAttributeConfigurators = []; - private $parameterAttributeConfigurators = []; - - public function process(ContainerBuilder $container): void - { - if (80000 > \PHP_VERSION_ID || !$container->getAutoconfiguredAttributes()) { - return; - } - - foreach ($container->getAutoconfiguredAttributes() as $attributeName => $callable) { - $callableReflector = new \ReflectionFunction(\Closure::fromCallable($callable)); - if ($callableReflector->getNumberOfParameters() <= 2) { - $this->classAttributeConfigurators[$attributeName] = $callable; - continue; - } - - $reflectorParameter = $callableReflector->getParameters()[2]; - $parameterType = $reflectorParameter->getType(); - $types = []; - if ($parameterType instanceof \ReflectionUnionType) { - foreach ($parameterType->getTypes() as $type) { - $types[] = $type->getName(); - } - } elseif ($parameterType instanceof \ReflectionNamedType) { - $types[] = $parameterType->getName(); - } else { - throw new LogicException(sprintf('Argument "$%s" of attribute autoconfigurator should have a type, use one or more of "\ReflectionClass|\ReflectionMethod|\ReflectionProperty|\ReflectionParameter|\Reflector" in "%s" on line "%d".', $reflectorParameter->getName(), $callableReflector->getFileName(), $callableReflector->getStartLine())); - } - - try { - $attributeReflector = new \ReflectionClass($attributeName); - } catch (\ReflectionException $e) { - continue; - } - - $targets = $attributeReflector->getAttributes(\Attribute::class)[0] ?? 0; - $targets = $targets ? $targets->getArguments()[0] ?? -1 : 0; - - foreach (['class', 'method', 'property', 'parameter'] as $symbol) { - if (['Reflector'] !== $types) { - if (!\in_array('Reflection'.ucfirst($symbol), $types, true)) { - continue; - } - if (!($targets & \constant('Attribute::TARGET_'.strtoupper($symbol)))) { - throw new LogicException(sprintf('Invalid type "Reflection%s" on argument "$%s": attribute "%s" cannot target a '.$symbol.' in "%s" on line "%d".', ucfirst($symbol), $reflectorParameter->getName(), $attributeName, $callableReflector->getFileName(), $callableReflector->getStartLine())); - } - } - $this->{$symbol.'AttributeConfigurators'}[$attributeName] = $callable; - } - } - - parent::process($container); - } - - protected function processValue($value, bool $isRoot = false) - { - if (!$value instanceof Definition - || !$value->isAutoconfigured() - || $value->isAbstract() - || $value->hasTag('container.ignore_attributes') - || !($classReflector = $this->container->getReflectionClass($value->getClass(), false)) - ) { - return parent::processValue($value, $isRoot); - } - - $instanceof = $value->getInstanceofConditionals(); - $conditionals = $instanceof[$classReflector->getName()] ?? new ChildDefinition(''); - - if ($this->classAttributeConfigurators) { - foreach ($classReflector->getAttributes() as $attribute) { - if ($configurator = $this->classAttributeConfigurators[$attribute->getName()] ?? null) { - $configurator($conditionals, $attribute->newInstance(), $classReflector); - } - } - } - - if ($this->parameterAttributeConfigurators) { - try { - $constructorReflector = $this->getConstructor($value, false); - } catch (RuntimeException $e) { - $constructorReflector = null; - } - - if ($constructorReflector) { - foreach ($constructorReflector->getParameters() as $parameterReflector) { - foreach ($parameterReflector->getAttributes() as $attribute) { - if ($configurator = $this->parameterAttributeConfigurators[$attribute->getName()] ?? null) { - $configurator($conditionals, $attribute->newInstance(), $parameterReflector); - } - } - } - } - } - - if ($this->methodAttributeConfigurators || $this->parameterAttributeConfigurators) { - foreach ($classReflector->getMethods(\ReflectionMethod::IS_PUBLIC) as $methodReflector) { - if ($methodReflector->isStatic() || $methodReflector->isConstructor() || $methodReflector->isDestructor()) { - continue; - } - - if ($this->methodAttributeConfigurators) { - foreach ($methodReflector->getAttributes() as $attribute) { - if ($configurator = $this->methodAttributeConfigurators[$attribute->getName()] ?? null) { - $configurator($conditionals, $attribute->newInstance(), $methodReflector); - } - } - } - - if ($this->parameterAttributeConfigurators) { - foreach ($methodReflector->getParameters() as $parameterReflector) { - foreach ($parameterReflector->getAttributes() as $attribute) { - if ($configurator = $this->parameterAttributeConfigurators[$attribute->getName()] ?? null) { - $configurator($conditionals, $attribute->newInstance(), $parameterReflector); - } - } - } - } - } - } - - if ($this->propertyAttributeConfigurators) { - foreach ($classReflector->getProperties(\ReflectionProperty::IS_PUBLIC) as $propertyReflector) { - if ($propertyReflector->isStatic()) { - continue; - } - - foreach ($propertyReflector->getAttributes() as $attribute) { - if ($configurator = $this->propertyAttributeConfigurators[$attribute->getName()] ?? null) { - $configurator($conditionals, $attribute->newInstance(), $propertyReflector); - } - } - } - } - - if (!isset($instanceof[$classReflector->getName()]) && new ChildDefinition('') != $conditionals) { - $instanceof[$classReflector->getName()] = $conditionals; - $value->setInstanceofConditionals($instanceof); - } - - return parent::processValue($value, $isRoot); - } -} diff --git a/lib/symfony/dependency-injection/Compiler/AutoAliasServicePass.php b/lib/symfony/dependency-injection/Compiler/AutoAliasServicePass.php deleted file mode 100644 index b150e70e6..000000000 --- a/lib/symfony/dependency-injection/Compiler/AutoAliasServicePass.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -/** - * Sets a service to be an alias of another one, given a format pattern. - */ -class AutoAliasServicePass implements CompilerPassInterface -{ - private $privateAliases = []; - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - foreach ($container->findTaggedServiceIds('auto_alias') as $serviceId => $tags) { - foreach ($tags as $tag) { - if (!isset($tag['format'])) { - throw new InvalidArgumentException(sprintf('Missing tag information "format" on auto_alias service "%s".', $serviceId)); - } - - $aliasId = $container->getParameterBag()->resolveValue($tag['format']); - if ($container->hasDefinition($aliasId) || $container->hasAlias($aliasId)) { - $alias = new Alias($aliasId, $container->getDefinition($serviceId)->isPublic()); - $container->setAlias($serviceId, $alias); - - if (!$alias->isPublic()) { - $alias->setPublic(true); - $this->privateAliases[] = $alias; - } - } - } - } - } - - /** - * @internal to be removed in Symfony 6.0 - */ - public function getPrivateAliases(): array - { - $privateAliases = $this->privateAliases; - $this->privateAliases = []; - - return $privateAliases; - } -} diff --git a/lib/symfony/dependency-injection/Compiler/AutowirePass.php b/lib/symfony/dependency-injection/Compiler/AutowirePass.php deleted file mode 100644 index c2b80770c..000000000 --- a/lib/symfony/dependency-injection/Compiler/AutowirePass.php +++ /dev/null @@ -1,625 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\Config\Resource\ClassExistenceResource; -use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; -use Symfony\Component\DependencyInjection\Attribute\TaggedIterator; -use Symfony\Component\DependencyInjection\Attribute\TaggedLocator; -use Symfony\Component\DependencyInjection\Attribute\Target; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper; -use Symfony\Component\DependencyInjection\TypedReference; - -/** - * Inspects existing service definitions and wires the autowired ones using the type hints of their classes. - * - * @author Kévin Dunglas <dunglas@gmail.com> - * @author Nicolas Grekas <p@tchwork.com> - */ -class AutowirePass extends AbstractRecursivePass -{ - private $types; - private $ambiguousServiceTypes; - private $autowiringAliases; - private $lastFailure; - private $throwOnAutowiringException; - private $decoratedClass; - private $decoratedId; - private $methodCalls; - private $defaultArgument; - private $getPreviousValue; - private $decoratedMethodIndex; - private $decoratedMethodArgumentIndex; - private $typesClone; - private $combinedAliases; - - public function __construct(bool $throwOnAutowireException = true) - { - $this->throwOnAutowiringException = $throwOnAutowireException; - $this->defaultArgument = new class() { - public $value; - public $names; - }; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - $this->populateCombinedAliases($container); - - try { - $this->typesClone = clone $this; - parent::process($container); - } finally { - $this->decoratedClass = null; - $this->decoratedId = null; - $this->methodCalls = null; - $this->defaultArgument->names = null; - $this->getPreviousValue = null; - $this->decoratedMethodIndex = null; - $this->decoratedMethodArgumentIndex = null; - $this->typesClone = null; - $this->combinedAliases = []; - } - } - - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - try { - return $this->doProcessValue($value, $isRoot); - } catch (AutowiringFailedException $e) { - if ($this->throwOnAutowiringException) { - throw $e; - } - - $this->container->getDefinition($this->currentId)->addError($e->getMessageCallback() ?? $e->getMessage()); - - return parent::processValue($value, $isRoot); - } - } - - /** - * @return mixed - */ - private function doProcessValue($value, bool $isRoot = false) - { - if ($value instanceof TypedReference) { - if ($ref = $this->getAutowiredReference($value, true)) { - return $ref; - } - if (ContainerBuilder::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior()) { - $message = $this->createTypeNotFoundMessageCallback($value, 'it'); - - // since the error message varies by referenced id and $this->currentId, so should the id of the dummy errored definition - $this->container->register($id = sprintf('.errored.%s.%s', $this->currentId, (string) $value), $value->getType()) - ->addError($message); - - return new TypedReference($id, $value->getType(), $value->getInvalidBehavior(), $value->getName()); - } - } - $value = parent::processValue($value, $isRoot); - - if (!$value instanceof Definition || !$value->isAutowired() || $value->isAbstract() || !$value->getClass()) { - return $value; - } - if (!$reflectionClass = $this->container->getReflectionClass($value->getClass(), false)) { - $this->container->log($this, sprintf('Skipping service "%s": Class or interface "%s" cannot be loaded.', $this->currentId, $value->getClass())); - - return $value; - } - - $this->methodCalls = $value->getMethodCalls(); - - try { - $constructor = $this->getConstructor($value, false); - } catch (RuntimeException $e) { - throw new AutowiringFailedException($this->currentId, $e->getMessage(), 0, $e); - } - - if ($constructor) { - array_unshift($this->methodCalls, [$constructor, $value->getArguments()]); - } - - $checkAttributes = 80000 <= \PHP_VERSION_ID && !$value->hasTag('container.ignore_attributes'); - $this->methodCalls = $this->autowireCalls($reflectionClass, $isRoot, $checkAttributes); - - if ($constructor) { - [, $arguments] = array_shift($this->methodCalls); - - if ($arguments !== $value->getArguments()) { - $value->setArguments($arguments); - } - } - - if ($this->methodCalls !== $value->getMethodCalls()) { - $value->setMethodCalls($this->methodCalls); - } - - return $value; - } - - private function autowireCalls(\ReflectionClass $reflectionClass, bool $isRoot, bool $checkAttributes): array - { - $this->decoratedId = null; - $this->decoratedClass = null; - $this->getPreviousValue = null; - - if ($isRoot && ($definition = $this->container->getDefinition($this->currentId)) && null !== ($this->decoratedId = $definition->innerServiceId) && $this->container->has($this->decoratedId)) { - $this->decoratedClass = $this->container->findDefinition($this->decoratedId)->getClass(); - } - - $patchedIndexes = []; - - foreach ($this->methodCalls as $i => $call) { - [$method, $arguments] = $call; - - if ($method instanceof \ReflectionFunctionAbstract) { - $reflectionMethod = $method; - } else { - $definition = new Definition($reflectionClass->name); - try { - $reflectionMethod = $this->getReflectionMethod($definition, $method); - } catch (RuntimeException $e) { - if ($definition->getFactory()) { - continue; - } - throw $e; - } - } - - $arguments = $this->autowireMethod($reflectionMethod, $arguments, $checkAttributes, $i); - - if ($arguments !== $call[1]) { - $this->methodCalls[$i][1] = $arguments; - $patchedIndexes[] = $i; - } - } - - // use named arguments to skip complex default values - foreach ($patchedIndexes as $i) { - $namedArguments = null; - $arguments = $this->methodCalls[$i][1]; - - foreach ($arguments as $j => $value) { - if ($namedArguments && !$value instanceof $this->defaultArgument) { - unset($arguments[$j]); - $arguments[$namedArguments[$j]] = $value; - } - if ($namedArguments || !$value instanceof $this->defaultArgument) { - continue; - } - - if (\PHP_VERSION_ID >= 80100 && (\is_array($value->value) ? $value->value : \is_object($value->value))) { - unset($arguments[$j]); - $namedArguments = $value->names; - } else { - $arguments[$j] = $value->value; - } - } - - $this->methodCalls[$i][1] = $arguments; - } - - return $this->methodCalls; - } - - /** - * Autowires the constructor or a method. - * - * @throws AutowiringFailedException - */ - private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, array $arguments, bool $checkAttributes, int $methodIndex): array - { - $class = $reflectionMethod instanceof \ReflectionMethod ? $reflectionMethod->class : $this->currentId; - $method = $reflectionMethod->name; - $parameters = $reflectionMethod->getParameters(); - if ($reflectionMethod->isVariadic()) { - array_pop($parameters); - } - $this->defaultArgument->names = new \ArrayObject(); - - foreach ($parameters as $index => $parameter) { - $this->defaultArgument->names[$index] = $parameter->name; - - if (\array_key_exists($index, $arguments) && '' !== $arguments[$index]) { - continue; - } - - $type = ProxyHelper::getTypeHint($reflectionMethod, $parameter, true); - - if ($checkAttributes) { - foreach ($parameter->getAttributes() as $attribute) { - if (TaggedIterator::class === $attribute->getName()) { - $attribute = $attribute->newInstance(); - $arguments[$index] = new TaggedIteratorArgument($attribute->tag, $attribute->indexAttribute, $attribute->defaultIndexMethod, false, $attribute->defaultPriorityMethod); - break; - } - - if (TaggedLocator::class === $attribute->getName()) { - $attribute = $attribute->newInstance(); - $arguments[$index] = new ServiceLocatorArgument(new TaggedIteratorArgument($attribute->tag, $attribute->indexAttribute, $attribute->defaultIndexMethod, true, $attribute->defaultPriorityMethod)); - break; - } - } - - if ('' !== ($arguments[$index] ?? '')) { - continue; - } - } - - if (!$type) { - if (isset($arguments[$index])) { - continue; - } - - // no default value? Then fail - if (!$parameter->isDefaultValueAvailable()) { - // For core classes, isDefaultValueAvailable() can - // be false when isOptional() returns true. If the - // argument *is* optional, allow it to be missing - if ($parameter->isOptional()) { - --$index; - break; - } - $type = ProxyHelper::getTypeHint($reflectionMethod, $parameter, false); - $type = $type ? sprintf('is type-hinted "%s"', ltrim($type, '\\')) : 'has no type-hint'; - - throw new AutowiringFailedException($this->currentId, sprintf('Cannot autowire service "%s": argument "$%s" of method "%s()" %s, you should configure its value explicitly.', $this->currentId, $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method, $type)); - } - - // specifically pass the default value - $arguments[$index] = clone $this->defaultArgument; - $arguments[$index]->value = $parameter->getDefaultValue(); - - continue; - } - - $getValue = function () use ($type, $parameter, $class, $method) { - if (!$value = $this->getAutowiredReference($ref = new TypedReference($type, $type, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, Target::parseName($parameter)), true)) { - $failureMessage = $this->createTypeNotFoundMessageCallback($ref, sprintf('argument "$%s" of method "%s()"', $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method)); - - if ($parameter->isDefaultValueAvailable()) { - $value = clone $this->defaultArgument; - $value->value = $parameter->getDefaultValue(); - } elseif (!$parameter->allowsNull()) { - throw new AutowiringFailedException($this->currentId, $failureMessage); - } - } - - return $value; - }; - - if ($this->decoratedClass && $isDecorated = is_a($this->decoratedClass, $type, true)) { - if ($this->getPreviousValue) { - // The inner service is injected only if there is only 1 argument matching the type of the decorated class - // across all arguments of all autowired methods. - // If a second matching argument is found, the default behavior is restored. - - $getPreviousValue = $this->getPreviousValue; - $this->methodCalls[$this->decoratedMethodIndex][1][$this->decoratedMethodArgumentIndex] = $getPreviousValue(); - $this->decoratedClass = null; // Prevent further checks - } else { - $arguments[$index] = new TypedReference($this->decoratedId, $this->decoratedClass); - $this->getPreviousValue = $getValue; - $this->decoratedMethodIndex = $methodIndex; - $this->decoratedMethodArgumentIndex = $index; - - continue; - } - } - - $arguments[$index] = $getValue(); - } - - if ($parameters && !isset($arguments[++$index])) { - while (0 <= --$index) { - if (!$arguments[$index] instanceof $this->defaultArgument) { - break; - } - unset($arguments[$index]); - } - } - - // it's possible index 1 was set, then index 0, then 2, etc - // make sure that we re-order so they're injected as expected - ksort($arguments); - - return $arguments; - } - - /** - * Returns a reference to the service matching the given type, if any. - */ - private function getAutowiredReference(TypedReference $reference, bool $filterType): ?TypedReference - { - $this->lastFailure = null; - $type = $reference->getType(); - - if ($type !== (string) $reference) { - return $reference; - } - - if ($filterType && false !== $m = strpbrk($type, '&|')) { - $types = array_diff(explode($m[0], $type), ['int', 'string', 'array', 'bool', 'float', 'iterable', 'object', 'callable', 'null']); - - sort($types); - - $type = implode($m[0], $types); - } - - if (null !== $name = $reference->getName()) { - if ($this->container->has($alias = $type.' $'.$name) && !$this->container->findDefinition($alias)->isAbstract()) { - return new TypedReference($alias, $type, $reference->getInvalidBehavior()); - } - - if (null !== ($alias = $this->combinedAliases[$alias] ?? null) && !$this->container->findDefinition($alias)->isAbstract()) { - return new TypedReference($alias, $type, $reference->getInvalidBehavior()); - } - - if ($this->container->has($name) && !$this->container->findDefinition($name)->isAbstract()) { - foreach ($this->container->getAliases() + $this->combinedAliases as $id => $alias) { - if ($name === (string) $alias && str_starts_with($id, $type.' $')) { - return new TypedReference($name, $type, $reference->getInvalidBehavior()); - } - } - } - } - - if ($this->container->has($type) && !$this->container->findDefinition($type)->isAbstract()) { - return new TypedReference($type, $type, $reference->getInvalidBehavior()); - } - - if (null !== ($alias = $this->combinedAliases[$type] ?? null) && !$this->container->findDefinition($alias)->isAbstract()) { - return new TypedReference($alias, $type, $reference->getInvalidBehavior()); - } - - return null; - } - - /** - * Populates the list of available types. - */ - private function populateAvailableTypes(ContainerBuilder $container) - { - $this->types = []; - $this->ambiguousServiceTypes = []; - $this->autowiringAliases = []; - - foreach ($container->getDefinitions() as $id => $definition) { - $this->populateAvailableType($container, $id, $definition); - } - - foreach ($container->getAliases() as $id => $alias) { - $this->populateAutowiringAlias($id); - } - } - - /** - * Populates the list of available types for a given definition. - */ - private function populateAvailableType(ContainerBuilder $container, string $id, Definition $definition) - { - // Never use abstract services - if ($definition->isAbstract()) { - return; - } - - if ('' === $id || '.' === $id[0] || $definition->isDeprecated() || !$reflectionClass = $container->getReflectionClass($definition->getClass(), false)) { - return; - } - - foreach ($reflectionClass->getInterfaces() as $reflectionInterface) { - $this->set($reflectionInterface->name, $id); - } - - do { - $this->set($reflectionClass->name, $id); - } while ($reflectionClass = $reflectionClass->getParentClass()); - - $this->populateAutowiringAlias($id); - } - - /** - * Associates a type and a service id if applicable. - */ - private function set(string $type, string $id) - { - // is this already a type/class that is known to match multiple services? - if (isset($this->ambiguousServiceTypes[$type])) { - $this->ambiguousServiceTypes[$type][] = $id; - - return; - } - - // check to make sure the type doesn't match multiple services - if (!isset($this->types[$type]) || $this->types[$type] === $id) { - $this->types[$type] = $id; - - return; - } - - // keep an array of all services matching this type - if (!isset($this->ambiguousServiceTypes[$type])) { - $this->ambiguousServiceTypes[$type] = [$this->types[$type]]; - unset($this->types[$type]); - } - $this->ambiguousServiceTypes[$type][] = $id; - } - - private function createTypeNotFoundMessageCallback(TypedReference $reference, string $label): \Closure - { - if (null === $this->typesClone->container) { - $this->typesClone->container = new ContainerBuilder($this->container->getParameterBag()); - $this->typesClone->container->setAliases($this->container->getAliases()); - $this->typesClone->container->setDefinitions($this->container->getDefinitions()); - $this->typesClone->container->setResourceTracking(false); - } - $currentId = $this->currentId; - - return (function () use ($reference, $label, $currentId) { - return $this->createTypeNotFoundMessage($reference, $label, $currentId); - })->bindTo($this->typesClone); - } - - private function createTypeNotFoundMessage(TypedReference $reference, string $label, string $currentId): string - { - if (!$r = $this->container->getReflectionClass($type = $reference->getType(), false)) { - // either $type does not exist or a parent class does not exist - try { - $resource = new ClassExistenceResource($type, false); - // isFresh() will explode ONLY if a parent class/trait does not exist - $resource->isFresh(0); - $parentMsg = false; - } catch (\ReflectionException $e) { - $parentMsg = $e->getMessage(); - } - - $message = sprintf('has type "%s" but this class %s.', $type, $parentMsg ? sprintf('is missing a parent class (%s)', $parentMsg) : 'was not found'); - } else { - $alternatives = $this->createTypeAlternatives($this->container, $reference); - $message = $this->container->has($type) ? 'this service is abstract' : 'no such service exists'; - $message = sprintf('references %s "%s" but %s.%s', $r->isInterface() ? 'interface' : 'class', $type, $message, $alternatives); - - if ($r->isInterface() && !$alternatives) { - $message .= ' Did you create a class that implements this interface?'; - } - } - - $message = sprintf('Cannot autowire service "%s": %s %s', $currentId, $label, $message); - - if (null !== $this->lastFailure) { - $message = $this->lastFailure."\n".$message; - $this->lastFailure = null; - } - - return $message; - } - - private function createTypeAlternatives(ContainerBuilder $container, TypedReference $reference): string - { - // try suggesting available aliases first - if ($message = $this->getAliasesSuggestionForType($container, $type = $reference->getType())) { - return ' '.$message; - } - if (null === $this->ambiguousServiceTypes) { - $this->populateAvailableTypes($container); - } - - $servicesAndAliases = $container->getServiceIds(); - if (null !== ($autowiringAliases = $this->autowiringAliases[$type] ?? null) && !isset($autowiringAliases[''])) { - return sprintf(' Available autowiring aliases for this %s are: "$%s".', class_exists($type, false) ? 'class' : 'interface', implode('", "$', $autowiringAliases)); - } - - if (!$container->has($type) && false !== $key = array_search(strtolower($type), array_map('strtolower', $servicesAndAliases))) { - return sprintf(' Did you mean "%s"?', $servicesAndAliases[$key]); - } elseif (isset($this->ambiguousServiceTypes[$type])) { - $message = sprintf('one of these existing services: "%s"', implode('", "', $this->ambiguousServiceTypes[$type])); - } elseif (isset($this->types[$type])) { - $message = sprintf('the existing "%s" service', $this->types[$type]); - } else { - return ''; - } - - return sprintf(' You should maybe alias this %s to %s.', class_exists($type, false) ? 'class' : 'interface', $message); - } - - private function getAliasesSuggestionForType(ContainerBuilder $container, string $type): ?string - { - $aliases = []; - foreach (class_parents($type) + class_implements($type) as $parent) { - if ($container->has($parent) && !$container->findDefinition($parent)->isAbstract()) { - $aliases[] = $parent; - } - } - - if (1 < $len = \count($aliases)) { - $message = 'Try changing the type-hint to one of its parents: '; - for ($i = 0, --$len; $i < $len; ++$i) { - $message .= sprintf('%s "%s", ', class_exists($aliases[$i], false) ? 'class' : 'interface', $aliases[$i]); - } - $message .= sprintf('or %s "%s".', class_exists($aliases[$i], false) ? 'class' : 'interface', $aliases[$i]); - - return $message; - } - - if ($aliases) { - return sprintf('Try changing the type-hint to "%s" instead.', $aliases[0]); - } - - return null; - } - - private function populateAutowiringAlias(string $id): void - { - if (!preg_match('/(?(DEFINE)(?<V>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+))^((?&V)(?:\\\\(?&V))*+)(?: \$((?&V)))?$/', $id, $m)) { - return; - } - - $type = $m[2]; - $name = $m[3] ?? ''; - - if (class_exists($type, false) || interface_exists($type, false)) { - $this->autowiringAliases[$type][$name] = $name; - } - } - - private function populateCombinedAliases(ContainerBuilder $container): void - { - $this->combinedAliases = []; - $reverseAliases = []; - - foreach ($container->getAliases() as $id => $alias) { - if (!preg_match('/(?(DEFINE)(?<V>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+))^((?&V)(?:\\\\(?&V))*+)(?: \$((?&V)))?$/', $id, $m)) { - continue; - } - - $type = $m[2]; - $name = $m[3] ?? ''; - $reverseAliases[(string) $alias][$name][] = $type; - } - - foreach ($reverseAliases as $alias => $names) { - foreach ($names as $name => $types) { - if (2 > $count = \count($types)) { - continue; - } - sort($types); - $i = 1 << $count; - - // compute the powerset of the list of types - while ($i--) { - $set = []; - for ($j = 0; $j < $count; ++$j) { - if ($i & (1 << $j)) { - $set[] = $types[$j]; - } - } - - if (2 <= \count($set)) { - $this->combinedAliases[implode('&', $set).('' === $name ? '' : ' $'.$name)] = $alias; - $this->combinedAliases[implode('|', $set).('' === $name ? '' : ' $'.$name)] = $alias; - } - } - } - } - } -} diff --git a/lib/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php b/lib/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php deleted file mode 100644 index 5c255cfb6..000000000 --- a/lib/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php +++ /dev/null @@ -1,109 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Contracts\Service\Attribute\Required; - -/** - * Looks for definitions with autowiring enabled and registers their corresponding "@required" methods as setters. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class AutowireRequiredMethodsPass extends AbstractRecursivePass -{ - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - $value = parent::processValue($value, $isRoot); - - if (!$value instanceof Definition || !$value->isAutowired() || $value->isAbstract() || !$value->getClass()) { - return $value; - } - if (!$reflectionClass = $this->container->getReflectionClass($value->getClass(), false)) { - return $value; - } - - $alreadyCalledMethods = []; - $withers = []; - - foreach ($value->getMethodCalls() as [$method]) { - $alreadyCalledMethods[strtolower($method)] = true; - } - - foreach ($reflectionClass->getMethods() as $reflectionMethod) { - $r = $reflectionMethod; - - if ($r->isConstructor() || isset($alreadyCalledMethods[strtolower($r->name)])) { - continue; - } - - while (true) { - if (\PHP_VERSION_ID >= 80000 && $r->getAttributes(Required::class)) { - if ($this->isWither($r, $r->getDocComment() ?: '')) { - $withers[] = [$r->name, [], true]; - } else { - $value->addMethodCall($r->name, []); - } - break; - } - if (false !== $doc = $r->getDocComment()) { - if (false !== stripos($doc, '@required') && preg_match('#(?:^/\*\*|\n\s*+\*)\s*+@required(?:\s|\*/$)#i', $doc)) { - if ($this->isWither($reflectionMethod, $doc)) { - $withers[] = [$reflectionMethod->name, [], true]; - } else { - $value->addMethodCall($reflectionMethod->name, []); - } - break; - } - if (false === stripos($doc, '@inheritdoc') || !preg_match('#(?:^/\*\*|\n\s*+\*)\s*+(?:\{@inheritdoc\}|@inheritdoc)(?:\s|\*/$)#i', $doc)) { - break; - } - } - try { - $r = $r->getPrototype(); - } catch (\ReflectionException $e) { - break; // method has no prototype - } - } - } - - if ($withers) { - // Prepend withers to prevent creating circular loops - $setters = $value->getMethodCalls(); - $value->setMethodCalls($withers); - foreach ($setters as $call) { - $value->addMethodCall($call[0], $call[1], $call[2] ?? false); - } - } - - return $value; - } - - private function isWither(\ReflectionMethod $reflectionMethod, string $doc): bool - { - $match = preg_match('#(?:^/\*\*|\n\s*+\*)\s*+@return\s++(static|\$this)[\s\*]#i', $doc, $matches); - if ($match && 'static' === $matches[1]) { - return true; - } - - if ($match && '$this' === $matches[1]) { - return false; - } - - $reflectionType = $reflectionMethod->hasReturnType() ? $reflectionMethod->getReturnType() : null; - - return $reflectionType instanceof \ReflectionNamedType && 'static' === $reflectionType->getName(); - } -} diff --git a/lib/symfony/dependency-injection/Compiler/AutowireRequiredPropertiesPass.php b/lib/symfony/dependency-injection/Compiler/AutowireRequiredPropertiesPass.php deleted file mode 100644 index 52024b807..000000000 --- a/lib/symfony/dependency-injection/Compiler/AutowireRequiredPropertiesPass.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\TypedReference; -use Symfony\Contracts\Service\Attribute\Required; - -/** - * Looks for definitions with autowiring enabled and registers their corresponding "@required" properties. - * - * @author Sebastien Morel (Plopix) <morel.seb@gmail.com> - * @author Nicolas Grekas <p@tchwork.com> - */ -class AutowireRequiredPropertiesPass extends AbstractRecursivePass -{ - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if (\PHP_VERSION_ID < 70400) { - return $value; - } - $value = parent::processValue($value, $isRoot); - - if (!$value instanceof Definition || !$value->isAutowired() || $value->isAbstract() || !$value->getClass()) { - return $value; - } - if (!$reflectionClass = $this->container->getReflectionClass($value->getClass(), false)) { - return $value; - } - - $properties = $value->getProperties(); - foreach ($reflectionClass->getProperties() as $reflectionProperty) { - if (!($type = $reflectionProperty->getType()) instanceof \ReflectionNamedType) { - continue; - } - if ((\PHP_VERSION_ID < 80000 || !$reflectionProperty->getAttributes(Required::class)) - && ((false === $doc = $reflectionProperty->getDocComment()) || false === stripos($doc, '@required') || !preg_match('#(?:^/\*\*|\n\s*+\*)\s*+@required(?:\s|\*/$)#i', $doc)) - ) { - continue; - } - if (\array_key_exists($name = $reflectionProperty->getName(), $properties)) { - continue; - } - - $type = $type->getName(); - $value->setProperty($name, new TypedReference($type, $type, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $name)); - } - - return $value; - } -} diff --git a/lib/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php b/lib/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php deleted file mode 100644 index 93808b201..000000000 --- a/lib/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php +++ /dev/null @@ -1,119 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; - -/** - * Checks if arguments of methods are properly configured. - * - * @author Kévin Dunglas <dunglas@gmail.com> - * @author Nicolas Grekas <p@tchwork.com> - */ -class CheckArgumentsValidityPass extends AbstractRecursivePass -{ - private $throwExceptions; - - public function __construct(bool $throwExceptions = true) - { - $this->throwExceptions = $throwExceptions; - } - - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if (!$value instanceof Definition) { - return parent::processValue($value, $isRoot); - } - - $i = 0; - $hasNamedArgs = false; - foreach ($value->getArguments() as $k => $v) { - if (\PHP_VERSION_ID >= 80000 && preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $k)) { - $hasNamedArgs = true; - continue; - } - - if ($k !== $i++) { - if (!\is_int($k)) { - $msg = sprintf('Invalid constructor argument for service "%s": integer expected but found string "%s". Check your service definition.', $this->currentId, $k); - $value->addError($msg); - if ($this->throwExceptions) { - throw new RuntimeException($msg); - } - - break; - } - - $msg = sprintf('Invalid constructor argument %d for service "%s": argument %d must be defined before. Check your service definition.', 1 + $k, $this->currentId, $i); - $value->addError($msg); - if ($this->throwExceptions) { - throw new RuntimeException($msg); - } - } - - if ($hasNamedArgs) { - $msg = sprintf('Invalid constructor argument for service "%s": cannot use positional argument after named argument. Check your service definition.', $this->currentId); - $value->addError($msg); - if ($this->throwExceptions) { - throw new RuntimeException($msg); - } - - break; - } - } - - foreach ($value->getMethodCalls() as $methodCall) { - $i = 0; - $hasNamedArgs = false; - foreach ($methodCall[1] as $k => $v) { - if (\PHP_VERSION_ID >= 80000 && preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $k)) { - $hasNamedArgs = true; - continue; - } - - if ($k !== $i++) { - if (!\is_int($k)) { - $msg = sprintf('Invalid argument for method call "%s" of service "%s": integer expected but found string "%s". Check your service definition.', $methodCall[0], $this->currentId, $k); - $value->addError($msg); - if ($this->throwExceptions) { - throw new RuntimeException($msg); - } - - break; - } - - $msg = sprintf('Invalid argument %d for method call "%s" of service "%s": argument %d must be defined before. Check your service definition.', 1 + $k, $methodCall[0], $this->currentId, $i); - $value->addError($msg); - if ($this->throwExceptions) { - throw new RuntimeException($msg); - } - } - - if ($hasNamedArgs) { - $msg = sprintf('Invalid argument for method call "%s" of service "%s": cannot use positional argument after named argument. Check your service definition.', $methodCall[0], $this->currentId); - $value->addError($msg); - if ($this->throwExceptions) { - throw new RuntimeException($msg); - } - - break; - } - } - } - - return null; - } -} diff --git a/lib/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php b/lib/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php deleted file mode 100644 index 55d911c4f..000000000 --- a/lib/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; - -/** - * Checks your services for circular references. - * - * References from method calls are ignored since we might be able to resolve - * these references depending on the order in which services are called. - * - * Circular reference from method calls will only be detected at run-time. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class CheckCircularReferencesPass implements CompilerPassInterface -{ - private $currentPath; - private $checkedNodes; - - /** - * Checks the ContainerBuilder object for circular references. - */ - public function process(ContainerBuilder $container) - { - $graph = $container->getCompiler()->getServiceReferenceGraph(); - - $this->checkedNodes = []; - foreach ($graph->getNodes() as $id => $node) { - $this->currentPath = [$id]; - - $this->checkOutEdges($node->getOutEdges()); - } - } - - /** - * Checks for circular references. - * - * @param ServiceReferenceGraphEdge[] $edges An array of Edges - * - * @throws ServiceCircularReferenceException when a circular reference is found - */ - private function checkOutEdges(array $edges) - { - foreach ($edges as $edge) { - $node = $edge->getDestNode(); - $id = $node->getId(); - - if (empty($this->checkedNodes[$id])) { - // Don't check circular references for lazy edges - if (!$node->getValue() || (!$edge->isLazy() && !$edge->isWeak())) { - $searchKey = array_search($id, $this->currentPath); - $this->currentPath[] = $id; - - if (false !== $searchKey) { - throw new ServiceCircularReferenceException($id, \array_slice($this->currentPath, $searchKey)); - } - - $this->checkOutEdges($node->getOutEdges()); - } - - $this->checkedNodes[$id] = true; - array_pop($this->currentPath); - } - } - } -} diff --git a/lib/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php b/lib/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php deleted file mode 100644 index 68c42ae48..000000000 --- a/lib/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\EnvParameterException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Loader\FileLoader; - -/** - * This pass validates each definition individually only taking the information - * into account which is contained in the definition itself. - * - * Later passes can rely on the following, and specifically do not need to - * perform these checks themselves: - * - * - non synthetic, non abstract services always have a class set - * - synthetic services are always public - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class CheckDefinitionValidityPass implements CompilerPassInterface -{ - /** - * Processes the ContainerBuilder to validate the Definition. - * - * @throws RuntimeException When the Definition is invalid - */ - public function process(ContainerBuilder $container) - { - foreach ($container->getDefinitions() as $id => $definition) { - // synthetic service is public - if ($definition->isSynthetic() && !$definition->isPublic()) { - throw new RuntimeException(sprintf('A synthetic service ("%s") must be public.', $id)); - } - - // non-synthetic, non-abstract service has class - if (!$definition->isAbstract() && !$definition->isSynthetic() && !$definition->getClass() && !$definition->hasTag('container.service_locator') && (!$definition->getFactory() || !preg_match(FileLoader::ANONYMOUS_ID_REGEXP, $id))) { - if ($definition->getFactory()) { - throw new RuntimeException(sprintf('Please add the class to service "%s" even if it is constructed by a factory since we might need to add method calls based on compile-time checks.', $id)); - } - if (class_exists($id) || interface_exists($id, false)) { - if (str_starts_with($id, '\\') && 1 < substr_count($id, '\\')) { - throw new RuntimeException(sprintf('The definition for "%s" has no class attribute, and appears to reference a class or interface. Please specify the class attribute explicitly or remove the leading backslash by renaming the service to "%s" to get rid of this error.', $id, substr($id, 1))); - } - - throw new RuntimeException(sprintf('The definition for "%s" has no class attribute, and appears to reference a class or interface in the global namespace. Leaving out the "class" attribute is only allowed for namespaced classes. Please specify the class attribute explicitly to get rid of this error.', $id)); - } - - throw new RuntimeException(sprintf('The definition for "%s" has no class. If you intend to inject this service dynamically at runtime, please mark it as synthetic=true. If this is an abstract definition solely used by child definitions, please add abstract=true, otherwise specify a class to get rid of this error.', $id)); - } - - // tag attribute values must be scalars - foreach ($definition->getTags() as $name => $tags) { - foreach ($tags as $attributes) { - foreach ($attributes as $attribute => $value) { - if (!\is_scalar($value) && null !== $value) { - throw new RuntimeException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s".', $id, $name, $attribute)); - } - } - } - } - - if ($definition->isPublic() && !$definition->isPrivate()) { - $resolvedId = $container->resolveEnvPlaceholders($id, null, $usedEnvs); - if (null !== $usedEnvs) { - throw new EnvParameterException([$resolvedId], null, 'A service name ("%s") cannot contain dynamic values.'); - } - } - } - - foreach ($container->getAliases() as $id => $alias) { - if ($alias->isPublic() && !$alias->isPrivate()) { - $resolvedId = $container->resolveEnvPlaceholders($id, null, $usedEnvs); - if (null !== $usedEnvs) { - throw new EnvParameterException([$resolvedId], null, 'An alias name ("%s") cannot contain dynamic values.'); - } - } - } - } -} diff --git a/lib/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php b/lib/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php deleted file mode 100644 index fd3173831..000000000 --- a/lib/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php +++ /dev/null @@ -1,105 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Checks that all references are pointing to a valid service. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class CheckExceptionOnInvalidReferenceBehaviorPass extends AbstractRecursivePass -{ - private $serviceLocatorContextIds = []; - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - $this->serviceLocatorContextIds = []; - foreach ($container->findTaggedServiceIds('container.service_locator_context') as $id => $tags) { - $this->serviceLocatorContextIds[$id] = $tags[0]['id']; - $container->getDefinition($id)->clearTag('container.service_locator_context'); - } - - try { - return parent::process($container); - } finally { - $this->serviceLocatorContextIds = []; - } - } - - protected function processValue($value, bool $isRoot = false) - { - if (!$value instanceof Reference) { - return parent::processValue($value, $isRoot); - } - if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE < $value->getInvalidBehavior() || $this->container->has($id = (string) $value)) { - return $value; - } - - $currentId = $this->currentId; - $graph = $this->container->getCompiler()->getServiceReferenceGraph(); - - if (isset($this->serviceLocatorContextIds[$currentId])) { - $currentId = $this->serviceLocatorContextIds[$currentId]; - $locator = $this->container->getDefinition($this->currentId)->getFactory()[0]; - - foreach ($locator->getArgument(0) as $k => $v) { - if ($v->getValues()[0] === $value) { - if ($k !== $id) { - $currentId = $k.'" in the container provided to "'.$currentId; - } - throw new ServiceNotFoundException($id, $currentId, null, $this->getAlternatives($id)); - } - } - } - - if ('.' === $currentId[0] && $graph->hasNode($currentId)) { - foreach ($graph->getNode($currentId)->getInEdges() as $edge) { - if (!$edge->getValue() instanceof Reference || ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE < $edge->getValue()->getInvalidBehavior()) { - continue; - } - $sourceId = $edge->getSourceNode()->getId(); - - if ('.' !== $sourceId[0]) { - $currentId = $sourceId; - break; - } - } - } - - throw new ServiceNotFoundException($id, $currentId, null, $this->getAlternatives($id)); - } - - private function getAlternatives(string $id): array - { - $alternatives = []; - foreach ($this->container->getServiceIds() as $knownId) { - if ('' === $knownId || '.' === $knownId[0]) { - continue; - } - - $lev = levenshtein($id, $knownId); - if ($lev <= \strlen($id) / 3 || false !== strpos($knownId, $id)) { - $alternatives[] = $knownId; - } - } - - return $alternatives; - } -} diff --git a/lib/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php b/lib/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php deleted file mode 100644 index 0349ef761..000000000 --- a/lib/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Checks the validity of references. - * - * The following checks are performed by this pass: - * - target definitions are not abstract - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class CheckReferenceValidityPass extends AbstractRecursivePass -{ - protected function processValue($value, bool $isRoot = false) - { - if ($isRoot && $value instanceof Definition && ($value->isSynthetic() || $value->isAbstract())) { - return $value; - } - if ($value instanceof Reference && $this->container->hasDefinition((string) $value)) { - $targetDefinition = $this->container->getDefinition((string) $value); - - if ($targetDefinition->isAbstract()) { - throw new RuntimeException(sprintf('The definition "%s" has a reference to an abstract definition "%s". Abstract definitions cannot be the target of references.', $this->currentId, $value)); - } - } - - return parent::processValue($value, $isRoot); - } -} diff --git a/lib/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php b/lib/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php deleted file mode 100644 index b7ec85cef..000000000 --- a/lib/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php +++ /dev/null @@ -1,329 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Argument\RewindableGenerator; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\InvalidParameterTypeException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\ExpressionLanguage; -use Symfony\Component\DependencyInjection\Parameter; -use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\ServiceLocator; -use Symfony\Component\ExpressionLanguage\Expression; - -/** - * Checks whether injected parameters are compatible with type declarations. - * - * This pass should be run after all optimization passes. - * - * It can be added either: - * * before removing passes to check all services even if they are not currently used, - * * after removing passes to check only services are used in the app. - * - * @author Nicolas Grekas <p@tchwork.com> - * @author Julien Maulny <jmaulny@darkmira.fr> - */ -final class CheckTypeDeclarationsPass extends AbstractRecursivePass -{ - private const SCALAR_TYPES = [ - 'int' => true, - 'float' => true, - 'bool' => true, - 'string' => true, - ]; - - private const BUILTIN_TYPES = [ - 'array' => true, - 'bool' => true, - 'callable' => true, - 'float' => true, - 'int' => true, - 'iterable' => true, - 'object' => true, - 'string' => true, - ]; - - private $autoload; - private $skippedIds; - - private $expressionLanguage; - - /** - * @param bool $autoload Whether services who's class in not loaded should be checked or not. - * Defaults to false to save loading code during compilation. - * @param array $skippedIds An array indexed by the service ids to skip - */ - public function __construct(bool $autoload = false, array $skippedIds = []) - { - $this->autoload = $autoload; - $this->skippedIds = $skippedIds; - } - - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if (isset($this->skippedIds[$this->currentId])) { - return $value; - } - - if (!$value instanceof Definition || $value->hasErrors() || $value->isDeprecated()) { - return parent::processValue($value, $isRoot); - } - - if (!$this->autoload) { - if (!$class = $value->getClass()) { - return parent::processValue($value, $isRoot); - } - if (!class_exists($class, false) && !interface_exists($class, false)) { - return parent::processValue($value, $isRoot); - } - } - - if (ServiceLocator::class === $value->getClass()) { - return parent::processValue($value, $isRoot); - } - - if ($constructor = $this->getConstructor($value, false)) { - $this->checkTypeDeclarations($value, $constructor, $value->getArguments()); - } - - foreach ($value->getMethodCalls() as $methodCall) { - try { - $reflectionMethod = $this->getReflectionMethod($value, $methodCall[0]); - } catch (RuntimeException $e) { - if ($value->getFactory()) { - continue; - } - - throw $e; - } - - $this->checkTypeDeclarations($value, $reflectionMethod, $methodCall[1]); - } - - return parent::processValue($value, $isRoot); - } - - /** - * @throws InvalidArgumentException When not enough parameters are defined for the method - */ - private function checkTypeDeclarations(Definition $checkedDefinition, \ReflectionFunctionAbstract $reflectionFunction, array $values): void - { - $numberOfRequiredParameters = $reflectionFunction->getNumberOfRequiredParameters(); - - if (\count($values) < $numberOfRequiredParameters) { - throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": "%s::%s()" requires %d arguments, %d passed.', $this->currentId, $reflectionFunction->class, $reflectionFunction->name, $numberOfRequiredParameters, \count($values))); - } - - $reflectionParameters = $reflectionFunction->getParameters(); - $checksCount = min($reflectionFunction->getNumberOfParameters(), \count($values)); - - $envPlaceholderUniquePrefix = $this->container->getParameterBag() instanceof EnvPlaceholderParameterBag ? $this->container->getParameterBag()->getEnvPlaceholderUniquePrefix() : null; - - for ($i = 0; $i < $checksCount; ++$i) { - if (!$reflectionParameters[$i]->hasType() || $reflectionParameters[$i]->isVariadic()) { - continue; - } - - $this->checkType($checkedDefinition, $values[$i], $reflectionParameters[$i], $envPlaceholderUniquePrefix); - } - - if ($reflectionFunction->isVariadic() && ($lastParameter = end($reflectionParameters))->hasType()) { - $variadicParameters = \array_slice($values, $lastParameter->getPosition()); - - foreach ($variadicParameters as $variadicParameter) { - $this->checkType($checkedDefinition, $variadicParameter, $lastParameter, $envPlaceholderUniquePrefix); - } - } - } - - /** - * @throws InvalidParameterTypeException When a parameter is not compatible with the declared type - */ - private function checkType(Definition $checkedDefinition, $value, \ReflectionParameter $parameter, ?string $envPlaceholderUniquePrefix, \ReflectionType $reflectionType = null): void - { - $reflectionType = $reflectionType ?? $parameter->getType(); - - if ($reflectionType instanceof \ReflectionUnionType) { - foreach ($reflectionType->getTypes() as $t) { - try { - $this->checkType($checkedDefinition, $value, $parameter, $envPlaceholderUniquePrefix, $t); - - return; - } catch (InvalidParameterTypeException $e) { - } - } - - throw new InvalidParameterTypeException($this->currentId, $e->getCode(), $parameter); - } - if ($reflectionType instanceof \ReflectionIntersectionType) { - foreach ($reflectionType->getTypes() as $t) { - $this->checkType($checkedDefinition, $value, $parameter, $envPlaceholderUniquePrefix, $t); - } - - return; - } - if (!$reflectionType instanceof \ReflectionNamedType) { - return; - } - - $type = $reflectionType->getName(); - - if ($value instanceof Reference) { - if (!$this->container->has($value = (string) $value)) { - return; - } - - if ('service_container' === $value && is_a($type, Container::class, true)) { - return; - } - - $value = $this->container->findDefinition($value); - } - - if ('self' === $type) { - $type = $parameter->getDeclaringClass()->getName(); - } - - if ('static' === $type) { - $type = $checkedDefinition->getClass(); - } - - $class = null; - - if ($value instanceof Definition) { - if ($value->getFactory()) { - return; - } - - $class = $value->getClass(); - - if ($class && isset(self::BUILTIN_TYPES[strtolower($class)])) { - $class = strtolower($class); - } elseif (!$class || (!$this->autoload && !class_exists($class, false) && !interface_exists($class, false))) { - return; - } - } elseif ($value instanceof Parameter) { - $value = $this->container->getParameter($value); - } elseif ($value instanceof Expression) { - try { - $value = $this->getExpressionLanguage()->evaluate($value, ['container' => $this->container]); - } catch (\Exception $e) { - // If a service from the expression cannot be fetched from the container, we skip the validation. - return; - } - } elseif (\is_string($value)) { - if ('%' === ($value[0] ?? '') && preg_match('/^%([^%]+)%$/', $value, $match)) { - $value = $this->container->getParameter(substr($value, 1, -1)); - } - - if ($envPlaceholderUniquePrefix && \is_string($value) && str_contains($value, 'env_')) { - // If the value is an env placeholder that is either mixed with a string or with another env placeholder, then its resolved value will always be a string, so we don't need to resolve it. - // We don't need to change the value because it is already a string. - if ('' === preg_replace('/'.$envPlaceholderUniquePrefix.'_\w+_[a-f0-9]{32}/U', '', $value, -1, $c) && 1 === $c) { - try { - $value = $this->container->resolveEnvPlaceholders($value, true); - } catch (\Exception $e) { - // If an env placeholder cannot be resolved, we skip the validation. - return; - } - } - } - } - - if (null === $value && $parameter->allowsNull()) { - return; - } - - if (null === $class) { - if ($value instanceof IteratorArgument) { - $class = RewindableGenerator::class; - } elseif ($value instanceof ServiceClosureArgument) { - $class = \Closure::class; - } elseif ($value instanceof ServiceLocatorArgument) { - $class = ServiceLocator::class; - } elseif (\is_object($value)) { - $class = \get_class($value); - } else { - $class = \gettype($value); - $class = ['integer' => 'int', 'double' => 'float', 'boolean' => 'bool'][$class] ?? $class; - } - } - - if (isset(self::SCALAR_TYPES[$type]) && isset(self::SCALAR_TYPES[$class])) { - return; - } - - if ('string' === $type && method_exists($class, '__toString')) { - return; - } - - if ('callable' === $type && (\Closure::class === $class || method_exists($class, '__invoke'))) { - return; - } - - if ('callable' === $type && \is_array($value) && isset($value[0]) && ($value[0] instanceof Reference || $value[0] instanceof Definition || \is_string($value[0]))) { - return; - } - - if ('iterable' === $type && (\is_array($value) || 'array' === $class || is_subclass_of($class, \Traversable::class))) { - return; - } - - if ($type === $class) { - return; - } - - if ('object' === $type && !isset(self::BUILTIN_TYPES[$class])) { - return; - } - - if ('mixed' === $type) { - return; - } - - if (is_a($class, $type, true)) { - return; - } - - if ('false' === $type) { - if (false === $value) { - return; - } - } elseif ($reflectionType->isBuiltin()) { - $checkFunction = sprintf('is_%s', $type); - if ($checkFunction($value)) { - return; - } - } - - throw new InvalidParameterTypeException($this->currentId, \is_object($value) ? $class : get_debug_type($value), $parameter); - } - - private function getExpressionLanguage(): ExpressionLanguage - { - if (null === $this->expressionLanguage) { - $this->expressionLanguage = new ExpressionLanguage(null, $this->container->getExpressionLanguageProviders()); - } - - return $this->expressionLanguage; - } -} diff --git a/lib/symfony/dependency-injection/Compiler/Compiler.php b/lib/symfony/dependency-injection/Compiler/Compiler.php deleted file mode 100644 index 4c5d003f0..000000000 --- a/lib/symfony/dependency-injection/Compiler/Compiler.php +++ /dev/null @@ -1,107 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\EnvParameterException; - -/** - * This class is used to remove circular dependencies between individual passes. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class Compiler -{ - private $passConfig; - private $log = []; - private $serviceReferenceGraph; - - public function __construct() - { - $this->passConfig = new PassConfig(); - $this->serviceReferenceGraph = new ServiceReferenceGraph(); - } - - /** - * @return PassConfig - */ - public function getPassConfig() - { - return $this->passConfig; - } - - /** - * @return ServiceReferenceGraph - */ - public function getServiceReferenceGraph() - { - return $this->serviceReferenceGraph; - } - - public function addPass(CompilerPassInterface $pass, string $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, int $priority = 0) - { - $this->passConfig->addPass($pass, $type, $priority); - } - - /** - * @final - */ - public function log(CompilerPassInterface $pass, string $message) - { - if (str_contains($message, "\n")) { - $message = str_replace("\n", "\n".\get_class($pass).': ', trim($message)); - } - - $this->log[] = \get_class($pass).': '.$message; - } - - /** - * @return array - */ - public function getLog() - { - return $this->log; - } - - /** - * Run the Compiler and process all Passes. - */ - public function compile(ContainerBuilder $container) - { - try { - foreach ($this->passConfig->getPasses() as $pass) { - $pass->process($container); - } - } catch (\Exception $e) { - $usedEnvs = []; - $prev = $e; - - do { - $msg = $prev->getMessage(); - - if ($msg !== $resolvedMsg = $container->resolveEnvPlaceholders($msg, null, $usedEnvs)) { - $r = new \ReflectionProperty($prev, 'message'); - $r->setAccessible(true); - $r->setValue($prev, $resolvedMsg); - } - } while ($prev = $prev->getPrevious()); - - if ($usedEnvs) { - $e = new EnvParameterException($usedEnvs, $e); - } - - throw $e; - } finally { - $this->getServiceReferenceGraph()->clear(); - } - } -} diff --git a/lib/symfony/dependency-injection/Compiler/CompilerPassInterface.php b/lib/symfony/dependency-injection/Compiler/CompilerPassInterface.php deleted file mode 100644 index 308500605..000000000 --- a/lib/symfony/dependency-injection/Compiler/CompilerPassInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * Interface that must be implemented by compilation passes. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -interface CompilerPassInterface -{ - /** - * You can modify the container here before it is dumped to PHP code. - */ - public function process(ContainerBuilder $container); -} diff --git a/lib/symfony/dependency-injection/Compiler/DecoratorServicePass.php b/lib/symfony/dependency-injection/Compiler/DecoratorServicePass.php deleted file mode 100644 index 917024917..000000000 --- a/lib/symfony/dependency-injection/Compiler/DecoratorServicePass.php +++ /dev/null @@ -1,133 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Overwrites a service but keeps the overridden one. - * - * @author Christophe Coevoet <stof@notk.org> - * @author Fabien Potencier <fabien@symfony.com> - * @author Diego Saint Esteben <diego@saintesteben.me> - */ -class DecoratorServicePass extends AbstractRecursivePass -{ - private $innerId = '.inner'; - - public function __construct(?string $innerId = '.inner') - { - if (0 < \func_num_args()) { - trigger_deprecation('symfony/dependency-injection', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->innerId = $innerId; - } - - public function process(ContainerBuilder $container) - { - $definitions = new \SplPriorityQueue(); - $order = \PHP_INT_MAX; - - foreach ($container->getDefinitions() as $id => $definition) { - if (!$decorated = $definition->getDecoratedService()) { - continue; - } - $definitions->insert([$id, $definition], [$decorated[2], --$order]); - } - $decoratingDefinitions = []; - - $tagsToKeep = $container->hasParameter('container.behavior_describing_tags') - ? $container->getParameter('container.behavior_describing_tags') - : ['container.do_not_inline', 'container.service_locator', 'container.service_subscriber']; - - foreach ($definitions as [$id, $definition]) { - $decoratedService = $definition->getDecoratedService(); - [$inner, $renamedId] = $decoratedService; - $invalidBehavior = $decoratedService[3] ?? ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; - - $definition->setDecoratedService(null); - - if (!$renamedId) { - $renamedId = $id.'.inner'; - } - - $this->currentId = $renamedId; - $this->processValue($definition); - - $definition->innerServiceId = $renamedId; - $definition->decorationOnInvalid = $invalidBehavior; - - // we create a new alias/service for the service we are replacing - // to be able to reference it in the new one - if ($container->hasAlias($inner)) { - $alias = $container->getAlias($inner); - $public = $alias->isPublic(); - $container->setAlias($renamedId, new Alias((string) $alias, false)); - $decoratedDefinition = $container->findDefinition($alias); - } elseif ($container->hasDefinition($inner)) { - $decoratedDefinition = $container->getDefinition($inner); - $public = $decoratedDefinition->isPublic(); - $decoratedDefinition->setPublic(false); - $container->setDefinition($renamedId, $decoratedDefinition); - $decoratingDefinitions[$inner] = $decoratedDefinition; - } elseif (ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $invalidBehavior) { - $container->removeDefinition($id); - continue; - } elseif (ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) { - $public = $definition->isPublic(); - $decoratedDefinition = null; - } else { - throw new ServiceNotFoundException($inner, $id); - } - - if ($decoratedDefinition && $decoratedDefinition->isSynthetic()) { - throw new InvalidArgumentException(sprintf('A synthetic service cannot be decorated: service "%s" cannot decorate "%s".', $id, $inner)); - } - - if (isset($decoratingDefinitions[$inner])) { - $decoratingDefinition = $decoratingDefinitions[$inner]; - - $decoratingTags = $decoratingDefinition->getTags(); - $resetTags = []; - - // Behavior-describing tags must not be transferred out to decorators - foreach ($tagsToKeep as $containerTag) { - if (isset($decoratingTags[$containerTag])) { - $resetTags[$containerTag] = $decoratingTags[$containerTag]; - unset($decoratingTags[$containerTag]); - } - } - - $definition->setTags(array_merge($decoratingTags, $definition->getTags())); - $decoratingDefinition->setTags($resetTags); - $decoratingDefinitions[$inner] = $definition; - } - - $container->setAlias($inner, $id)->setPublic($public); - } - } - - protected function processValue($value, bool $isRoot = false) - { - if ($value instanceof Reference && $this->innerId === (string) $value) { - return new Reference($this->currentId, $value->getInvalidBehavior()); - } - - return parent::processValue($value, $isRoot); - } -} diff --git a/lib/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php b/lib/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php deleted file mode 100644 index 5e7ba3173..000000000 --- a/lib/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Throws an exception for any Definitions that have errors and still exist. - * - * @author Ryan Weaver <ryan@knpuniversity.com> - */ -class DefinitionErrorExceptionPass extends AbstractRecursivePass -{ - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if (!$value instanceof Definition || !$value->hasErrors()) { - return parent::processValue($value, $isRoot); - } - - if ($isRoot && !$value->isPublic()) { - $graph = $this->container->getCompiler()->getServiceReferenceGraph(); - $runtimeException = false; - foreach ($graph->getNode($this->currentId)->getInEdges() as $edge) { - if (!$edge->getValue() instanceof Reference || ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE !== $edge->getValue()->getInvalidBehavior()) { - $runtimeException = false; - break; - } - $runtimeException = true; - } - if ($runtimeException) { - return parent::processValue($value, $isRoot); - } - } - - // only show the first error so the user can focus on it - $errors = $value->getErrors(); - $message = reset($errors); - - throw new RuntimeException($message); - } -} diff --git a/lib/symfony/dependency-injection/Compiler/ExtensionCompilerPass.php b/lib/symfony/dependency-injection/Compiler/ExtensionCompilerPass.php deleted file mode 100644 index 27e504824..000000000 --- a/lib/symfony/dependency-injection/Compiler/ExtensionCompilerPass.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * A pass to automatically process extensions if they implement - * CompilerPassInterface. - * - * @author Wouter J <wouter@wouterj.nl> - */ -class ExtensionCompilerPass implements CompilerPassInterface -{ - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - foreach ($container->getExtensions() as $extension) { - if (!$extension instanceof CompilerPassInterface) { - continue; - } - - $extension->process($container); - } - } -} diff --git a/lib/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php b/lib/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php deleted file mode 100644 index 2285f8ea5..000000000 --- a/lib/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php +++ /dev/null @@ -1,223 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Inline service definitions where this is possible. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class InlineServiceDefinitionsPass extends AbstractRecursivePass -{ - private $analyzingPass; - private $cloningIds = []; - private $connectedIds = []; - private $notInlinedIds = []; - private $inlinedIds = []; - private $notInlinableIds = []; - private $graph; - - public function __construct(AnalyzeServiceReferencesPass $analyzingPass = null) - { - $this->analyzingPass = $analyzingPass; - } - - public function process(ContainerBuilder $container) - { - $this->container = $container; - if ($this->analyzingPass) { - $analyzedContainer = new ContainerBuilder(); - $analyzedContainer->setAliases($container->getAliases()); - $analyzedContainer->setDefinitions($container->getDefinitions()); - foreach ($container->getExpressionLanguageProviders() as $provider) { - $analyzedContainer->addExpressionLanguageProvider($provider); - } - } else { - $analyzedContainer = $container; - } - try { - $remainingInlinedIds = []; - $this->connectedIds = $this->notInlinedIds = $container->getDefinitions(); - do { - if ($this->analyzingPass) { - $analyzedContainer->setDefinitions(array_intersect_key($analyzedContainer->getDefinitions(), $this->connectedIds)); - $this->analyzingPass->process($analyzedContainer); - } - $this->graph = $analyzedContainer->getCompiler()->getServiceReferenceGraph(); - $notInlinedIds = $this->notInlinedIds; - $this->connectedIds = $this->notInlinedIds = $this->inlinedIds = []; - - foreach ($analyzedContainer->getDefinitions() as $id => $definition) { - if (!$this->graph->hasNode($id)) { - continue; - } - foreach ($this->graph->getNode($id)->getOutEdges() as $edge) { - if (isset($notInlinedIds[$edge->getSourceNode()->getId()])) { - $this->currentId = $id; - $this->processValue($definition, true); - break; - } - } - } - - foreach ($this->inlinedIds as $id => $isPublicOrNotShared) { - if ($isPublicOrNotShared) { - $remainingInlinedIds[$id] = $id; - } else { - $container->removeDefinition($id); - $analyzedContainer->removeDefinition($id); - } - } - } while ($this->inlinedIds && $this->analyzingPass); - - foreach ($remainingInlinedIds as $id) { - if (isset($this->notInlinableIds[$id])) { - continue; - } - - $definition = $container->getDefinition($id); - - if (!$definition->isShared() && !$definition->isPublic()) { - $container->removeDefinition($id); - } - } - } finally { - $this->container = null; - $this->connectedIds = $this->notInlinedIds = $this->inlinedIds = []; - $this->notInlinableIds = []; - $this->graph = null; - } - } - - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if ($value instanceof ArgumentInterface) { - // References found in ArgumentInterface::getValues() are not inlineable - return $value; - } - - if ($value instanceof Definition && $this->cloningIds) { - if ($value->isShared()) { - return $value; - } - $value = clone $value; - } - - if (!$value instanceof Reference) { - return parent::processValue($value, $isRoot); - } elseif (!$this->container->hasDefinition($id = (string) $value)) { - return $value; - } - - $definition = $this->container->getDefinition($id); - - if (!$this->isInlineableDefinition($id, $definition)) { - $this->notInlinableIds[$id] = true; - - return $value; - } - - $this->container->log($this, sprintf('Inlined service "%s" to "%s".', $id, $this->currentId)); - $this->inlinedIds[$id] = $definition->isPublic() || !$definition->isShared(); - $this->notInlinedIds[$this->currentId] = true; - - if ($definition->isShared()) { - return $definition; - } - - if (isset($this->cloningIds[$id])) { - $ids = array_keys($this->cloningIds); - $ids[] = $id; - - throw new ServiceCircularReferenceException($id, \array_slice($ids, array_search($id, $ids))); - } - - $this->cloningIds[$id] = true; - try { - return $this->processValue($definition); - } finally { - unset($this->cloningIds[$id]); - } - } - - /** - * Checks if the definition is inlineable. - */ - private function isInlineableDefinition(string $id, Definition $definition): bool - { - if ($definition->hasErrors() || $definition->isDeprecated() || $definition->isLazy() || $definition->isSynthetic() || $definition->hasTag('container.do_not_inline')) { - return false; - } - - if (!$definition->isShared()) { - if (!$this->graph->hasNode($id)) { - return true; - } - - foreach ($this->graph->getNode($id)->getInEdges() as $edge) { - $srcId = $edge->getSourceNode()->getId(); - $this->connectedIds[$srcId] = true; - if ($edge->isWeak() || $edge->isLazy()) { - return !$this->connectedIds[$id] = true; - } - } - - return true; - } - - if ($definition->isPublic()) { - return false; - } - - if (!$this->graph->hasNode($id)) { - return true; - } - - if ($this->currentId == $id) { - return false; - } - $this->connectedIds[$id] = true; - - $srcIds = []; - $srcCount = 0; - foreach ($this->graph->getNode($id)->getInEdges() as $edge) { - $srcId = $edge->getSourceNode()->getId(); - $this->connectedIds[$srcId] = true; - if ($edge->isWeak() || $edge->isLazy()) { - return false; - } - $srcIds[$srcId] = true; - ++$srcCount; - } - - if (1 !== \count($srcIds)) { - $this->notInlinedIds[$id] = true; - - return false; - } - - if ($srcCount > 1 && \is_array($factory = $definition->getFactory()) && ($factory[0] instanceof Reference || $factory[0] instanceof Definition)) { - return false; - } - - return $this->container->getDefinition($srcId)->isShared(); - } -} diff --git a/lib/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php b/lib/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php deleted file mode 100644 index 9dc39314c..000000000 --- a/lib/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php +++ /dev/null @@ -1,216 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\Config\Definition\BaseNode; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\LogicException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface; -use Symfony\Component\DependencyInjection\Extension\Extension; -use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; -use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; -use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; - -/** - * Merges extension configs into the container builder. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class MergeExtensionConfigurationPass implements CompilerPassInterface -{ - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - $parameters = $container->getParameterBag()->all(); - $definitions = $container->getDefinitions(); - $aliases = $container->getAliases(); - $exprLangProviders = $container->getExpressionLanguageProviders(); - $configAvailable = class_exists(BaseNode::class); - - foreach ($container->getExtensions() as $extension) { - if ($extension instanceof PrependExtensionInterface) { - $extension->prepend($container); - } - } - - foreach ($container->getExtensions() as $name => $extension) { - if (!$config = $container->getExtensionConfig($name)) { - // this extension was not called - continue; - } - $resolvingBag = $container->getParameterBag(); - if ($resolvingBag instanceof EnvPlaceholderParameterBag && $extension instanceof Extension) { - // create a dedicated bag so that we can track env vars per-extension - $resolvingBag = new MergeExtensionConfigurationParameterBag($resolvingBag); - if ($configAvailable) { - BaseNode::setPlaceholderUniquePrefix($resolvingBag->getEnvPlaceholderUniquePrefix()); - } - } - $config = $resolvingBag->resolveValue($config); - - try { - $tmpContainer = new MergeExtensionConfigurationContainerBuilder($extension, $resolvingBag); - $tmpContainer->setResourceTracking($container->isTrackingResources()); - $tmpContainer->addObjectResource($extension); - if ($extension instanceof ConfigurationExtensionInterface && null !== $configuration = $extension->getConfiguration($config, $tmpContainer)) { - $tmpContainer->addObjectResource($configuration); - } - - foreach ($exprLangProviders as $provider) { - $tmpContainer->addExpressionLanguageProvider($provider); - } - - $extension->load($config, $tmpContainer); - } catch (\Exception $e) { - if ($resolvingBag instanceof MergeExtensionConfigurationParameterBag) { - $container->getParameterBag()->mergeEnvPlaceholders($resolvingBag); - } - - throw $e; - } - - if ($resolvingBag instanceof MergeExtensionConfigurationParameterBag) { - // don't keep track of env vars that are *overridden* when configs are merged - $resolvingBag->freezeAfterProcessing($extension, $tmpContainer); - } - - $container->merge($tmpContainer); - $container->getParameterBag()->add($parameters); - } - - $container->addDefinitions($definitions); - $container->addAliases($aliases); - } -} - -/** - * @internal - */ -class MergeExtensionConfigurationParameterBag extends EnvPlaceholderParameterBag -{ - private $processedEnvPlaceholders; - - public function __construct(parent $parameterBag) - { - parent::__construct($parameterBag->all()); - $this->mergeEnvPlaceholders($parameterBag); - } - - public function freezeAfterProcessing(Extension $extension, ContainerBuilder $container) - { - if (!$config = $extension->getProcessedConfigs()) { - // Extension::processConfiguration() wasn't called, we cannot know how configs were merged - return; - } - $this->processedEnvPlaceholders = []; - - // serialize config and container to catch env vars nested in object graphs - $config = serialize($config).serialize($container->getDefinitions()).serialize($container->getAliases()).serialize($container->getParameterBag()->all()); - - foreach (parent::getEnvPlaceholders() as $env => $placeholders) { - foreach ($placeholders as $placeholder) { - if (false !== stripos($config, $placeholder)) { - $this->processedEnvPlaceholders[$env] = $placeholders; - break; - } - } - } - } - - /** - * {@inheritdoc} - */ - public function getEnvPlaceholders(): array - { - return $this->processedEnvPlaceholders ?? parent::getEnvPlaceholders(); - } - - public function getUnusedEnvPlaceholders(): array - { - return null === $this->processedEnvPlaceholders ? [] : array_diff_key(parent::getEnvPlaceholders(), $this->processedEnvPlaceholders); - } -} - -/** - * A container builder preventing using methods that wouldn't have any effect from extensions. - * - * @internal - */ -class MergeExtensionConfigurationContainerBuilder extends ContainerBuilder -{ - private $extensionClass; - - public function __construct(ExtensionInterface $extension, ParameterBagInterface $parameterBag = null) - { - parent::__construct($parameterBag); - - $this->extensionClass = \get_class($extension); - } - - /** - * {@inheritdoc} - */ - public function addCompilerPass(CompilerPassInterface $pass, string $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, int $priority = 0): self - { - throw new LogicException(sprintf('You cannot add compiler pass "%s" from extension "%s". Compiler passes must be registered before the container is compiled.', get_debug_type($pass), $this->extensionClass)); - } - - /** - * {@inheritdoc} - */ - public function registerExtension(ExtensionInterface $extension) - { - throw new LogicException(sprintf('You cannot register extension "%s" from "%s". Extensions must be registered before the container is compiled.', get_debug_type($extension), $this->extensionClass)); - } - - /** - * {@inheritdoc} - */ - public function compile(bool $resolveEnvPlaceholders = false) - { - throw new LogicException(sprintf('Cannot compile the container in extension "%s".', $this->extensionClass)); - } - - /** - * {@inheritdoc} - */ - public function resolveEnvPlaceholders($value, $format = null, array &$usedEnvs = null) - { - if (true !== $format || !\is_string($value)) { - return parent::resolveEnvPlaceholders($value, $format, $usedEnvs); - } - - $bag = $this->getParameterBag(); - $value = $bag->resolveValue($value); - - if (!$bag instanceof EnvPlaceholderParameterBag) { - return parent::resolveEnvPlaceholders($value, $format, $usedEnvs); - } - - foreach ($bag->getEnvPlaceholders() as $env => $placeholders) { - if (!str_contains($env, ':')) { - continue; - } - foreach ($placeholders as $placeholder) { - if (false !== stripos($value, $placeholder)) { - throw new RuntimeException(sprintf('Using a cast in "env(%s)" is incompatible with resolution at compile time in "%s". The logic in the extension should be moved to a compiler pass, or an env parameter with no cast should be used instead.', $env, $this->extensionClass)); - } - } - } - - return parent::resolveEnvPlaceholders($value, $format, $usedEnvs); - } -} diff --git a/lib/symfony/dependency-injection/Compiler/PassConfig.php b/lib/symfony/dependency-injection/Compiler/PassConfig.php deleted file mode 100644 index 9f9a56edd..000000000 --- a/lib/symfony/dependency-injection/Compiler/PassConfig.php +++ /dev/null @@ -1,269 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -/** - * Compiler Pass Configuration. - * - * This class has a default configuration embedded. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class PassConfig -{ - public const TYPE_AFTER_REMOVING = 'afterRemoving'; - public const TYPE_BEFORE_OPTIMIZATION = 'beforeOptimization'; - public const TYPE_BEFORE_REMOVING = 'beforeRemoving'; - public const TYPE_OPTIMIZE = 'optimization'; - public const TYPE_REMOVE = 'removing'; - - private $mergePass; - private $afterRemovingPasses = []; - private $beforeOptimizationPasses = []; - private $beforeRemovingPasses = []; - private $optimizationPasses; - private $removingPasses; - - public function __construct() - { - $this->mergePass = new MergeExtensionConfigurationPass(); - - $this->beforeOptimizationPasses = [ - 100 => [ - new ResolveClassPass(), - new RegisterAutoconfigureAttributesPass(), - new AttributeAutoconfigurationPass(), - new ResolveInstanceofConditionalsPass(), - new RegisterEnvVarProcessorsPass(), - ], - -1000 => [new ExtensionCompilerPass()], - ]; - - $this->optimizationPasses = [[ - $autoAliasServicePass = new AutoAliasServicePass(), - new ValidateEnvPlaceholdersPass(), - new ResolveDecoratorStackPass(), - new ResolveChildDefinitionsPass(), - new RegisterServiceSubscribersPass(), - new ResolveParameterPlaceHoldersPass(false, false), - new ResolveFactoryClassPass(), - new ResolveNamedArgumentsPass(), - new AutowireRequiredMethodsPass(), - new AutowireRequiredPropertiesPass(), - new ResolveBindingsPass(), - new ServiceLocatorTagPass(), - new DecoratorServicePass(), - new CheckDefinitionValidityPass(), - new AutowirePass(false), - new ServiceLocatorTagPass(), - new ResolveTaggedIteratorArgumentPass(), - new ResolveServiceSubscribersPass(), - new ResolveReferencesToAliasesPass(), - new ResolveInvalidReferencesPass(), - new AnalyzeServiceReferencesPass(true), - new CheckCircularReferencesPass(), - new CheckReferenceValidityPass(), - new CheckArgumentsValidityPass(false), - ]]; - - $this->removingPasses = [[ - new RemovePrivateAliasesPass(), - (new ReplaceAliasByActualDefinitionPass())->setAutoAliasServicePass($autoAliasServicePass), - new RemoveAbstractDefinitionsPass(), - new RemoveUnusedDefinitionsPass(), - new AnalyzeServiceReferencesPass(), - new CheckExceptionOnInvalidReferenceBehaviorPass(), - new InlineServiceDefinitionsPass(new AnalyzeServiceReferencesPass()), - new AnalyzeServiceReferencesPass(), - new DefinitionErrorExceptionPass(), - ]]; - - $this->afterRemovingPasses = [[ - new ResolveHotPathPass(), - new ResolveNoPreloadPass(), - new AliasDeprecatedPublicServicesPass(), - ]]; - } - - /** - * Returns all passes in order to be processed. - * - * @return CompilerPassInterface[] - */ - public function getPasses() - { - return array_merge( - [$this->mergePass], - $this->getBeforeOptimizationPasses(), - $this->getOptimizationPasses(), - $this->getBeforeRemovingPasses(), - $this->getRemovingPasses(), - $this->getAfterRemovingPasses() - ); - } - - /** - * Adds a pass. - * - * @throws InvalidArgumentException when a pass type doesn't exist - */ - public function addPass(CompilerPassInterface $pass, string $type = self::TYPE_BEFORE_OPTIMIZATION, int $priority = 0) - { - $property = $type.'Passes'; - if (!isset($this->$property)) { - throw new InvalidArgumentException(sprintf('Invalid type "%s".', $type)); - } - - $passes = &$this->$property; - - if (!isset($passes[$priority])) { - $passes[$priority] = []; - } - $passes[$priority][] = $pass; - } - - /** - * Gets all passes for the AfterRemoving pass. - * - * @return CompilerPassInterface[] - */ - public function getAfterRemovingPasses() - { - return $this->sortPasses($this->afterRemovingPasses); - } - - /** - * Gets all passes for the BeforeOptimization pass. - * - * @return CompilerPassInterface[] - */ - public function getBeforeOptimizationPasses() - { - return $this->sortPasses($this->beforeOptimizationPasses); - } - - /** - * Gets all passes for the BeforeRemoving pass. - * - * @return CompilerPassInterface[] - */ - public function getBeforeRemovingPasses() - { - return $this->sortPasses($this->beforeRemovingPasses); - } - - /** - * Gets all passes for the Optimization pass. - * - * @return CompilerPassInterface[] - */ - public function getOptimizationPasses() - { - return $this->sortPasses($this->optimizationPasses); - } - - /** - * Gets all passes for the Removing pass. - * - * @return CompilerPassInterface[] - */ - public function getRemovingPasses() - { - return $this->sortPasses($this->removingPasses); - } - - /** - * Gets the Merge pass. - * - * @return CompilerPassInterface - */ - public function getMergePass() - { - return $this->mergePass; - } - - public function setMergePass(CompilerPassInterface $pass) - { - $this->mergePass = $pass; - } - - /** - * Sets the AfterRemoving passes. - * - * @param CompilerPassInterface[] $passes - */ - public function setAfterRemovingPasses(array $passes) - { - $this->afterRemovingPasses = [$passes]; - } - - /** - * Sets the BeforeOptimization passes. - * - * @param CompilerPassInterface[] $passes - */ - public function setBeforeOptimizationPasses(array $passes) - { - $this->beforeOptimizationPasses = [$passes]; - } - - /** - * Sets the BeforeRemoving passes. - * - * @param CompilerPassInterface[] $passes - */ - public function setBeforeRemovingPasses(array $passes) - { - $this->beforeRemovingPasses = [$passes]; - } - - /** - * Sets the Optimization passes. - * - * @param CompilerPassInterface[] $passes - */ - public function setOptimizationPasses(array $passes) - { - $this->optimizationPasses = [$passes]; - } - - /** - * Sets the Removing passes. - * - * @param CompilerPassInterface[] $passes - */ - public function setRemovingPasses(array $passes) - { - $this->removingPasses = [$passes]; - } - - /** - * Sort passes by priority. - * - * @param array $passes CompilerPassInterface instances with their priority as key - * - * @return CompilerPassInterface[] - */ - private function sortPasses(array $passes): array - { - if (0 === \count($passes)) { - return []; - } - - krsort($passes); - - // Flatten the array - return array_merge(...$passes); - } -} diff --git a/lib/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php b/lib/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php deleted file mode 100644 index 8c4d841f5..000000000 --- a/lib/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php +++ /dev/null @@ -1,171 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; -use Symfony\Component\DependencyInjection\Attribute\AsTaggedItem; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\TypedReference; - -/** - * Trait that allows a generic method to find and sort service by priority option in the tag. - * - * @author Iltar van der Berg <kjarli@gmail.com> - */ -trait PriorityTaggedServiceTrait -{ - /** - * Finds all services with the given tag name and order them by their priority. - * - * The order of additions must be respected for services having the same priority, - * and knowing that the \SplPriorityQueue class does not respect the FIFO method, - * we should not use that class. - * - * @see https://bugs.php.net/53710 - * @see https://bugs.php.net/60926 - * - * @param string|TaggedIteratorArgument $tagName - * - * @return Reference[] - */ - private function findAndSortTaggedServices($tagName, ContainerBuilder $container): array - { - $indexAttribute = $defaultIndexMethod = $needsIndexes = $defaultPriorityMethod = null; - - if ($tagName instanceof TaggedIteratorArgument) { - $indexAttribute = $tagName->getIndexAttribute(); - $defaultIndexMethod = $tagName->getDefaultIndexMethod(); - $needsIndexes = $tagName->needsIndexes(); - $defaultPriorityMethod = $tagName->getDefaultPriorityMethod() ?? 'getDefaultPriority'; - $tagName = $tagName->getTag(); - } - - $i = 0; - $services = []; - - foreach ($container->findTaggedServiceIds($tagName, true) as $serviceId => $attributes) { - $defaultPriority = null; - $defaultIndex = null; - $definition = $container->getDefinition($serviceId); - $class = $definition->getClass(); - $class = $container->getParameterBag()->resolveValue($class) ?: null; - $checkTaggedItem = !$definition->hasTag(80000 <= \PHP_VERSION_ID && $definition->isAutoconfigured() ? 'container.ignore_attributes' : $tagName); - - foreach ($attributes as $attribute) { - $index = $priority = null; - - if (isset($attribute['priority'])) { - $priority = $attribute['priority']; - } elseif (null === $defaultPriority && $defaultPriorityMethod && $class) { - $defaultPriority = PriorityTaggedServiceUtil::getDefault($container, $serviceId, $class, $defaultPriorityMethod, $tagName, 'priority', $checkTaggedItem); - } - $priority = $priority ?? $defaultPriority ?? $defaultPriority = 0; - - if (null === $indexAttribute && !$defaultIndexMethod && !$needsIndexes) { - $services[] = [$priority, ++$i, null, $serviceId, null]; - continue 2; - } - - if (null !== $indexAttribute && isset($attribute[$indexAttribute])) { - $index = $attribute[$indexAttribute]; - } elseif (null === $defaultIndex && $defaultPriorityMethod && $class) { - $defaultIndex = PriorityTaggedServiceUtil::getDefault($container, $serviceId, $class, $defaultIndexMethod ?? 'getDefaultName', $tagName, $indexAttribute, $checkTaggedItem); - } - $index = $index ?? $defaultIndex ?? $defaultIndex = $serviceId; - - $services[] = [$priority, ++$i, $index, $serviceId, $class]; - } - } - - uasort($services, static function ($a, $b) { return $b[0] <=> $a[0] ?: $a[1] <=> $b[1]; }); - - $refs = []; - foreach ($services as [, , $index, $serviceId, $class]) { - if (!$class) { - $reference = new Reference($serviceId); - } elseif ($index === $serviceId) { - $reference = new TypedReference($serviceId, $class); - } else { - $reference = new TypedReference($serviceId, $class, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, $index); - } - - if (null === $index) { - $refs[] = $reference; - } else { - $refs[$index] = $reference; - } - } - - return $refs; - } -} - -/** - * @internal - */ -class PriorityTaggedServiceUtil -{ - /** - * @return string|int|null - */ - public static function getDefault(ContainerBuilder $container, string $serviceId, string $class, string $defaultMethod, string $tagName, ?string $indexAttribute, bool $checkTaggedItem) - { - if (!($r = $container->getReflectionClass($class)) || (!$checkTaggedItem && !$r->hasMethod($defaultMethod))) { - return null; - } - - if ($checkTaggedItem && !$r->hasMethod($defaultMethod)) { - foreach ($r->getAttributes(AsTaggedItem::class) as $attribute) { - return 'priority' === $indexAttribute ? $attribute->newInstance()->priority : $attribute->newInstance()->index; - } - - return null; - } - - if (null !== $indexAttribute) { - $service = $class !== $serviceId ? sprintf('service "%s"', $serviceId) : 'on the corresponding service'; - $message = [sprintf('Either method "%s::%s()" should ', $class, $defaultMethod), sprintf(' or tag "%s" on %s is missing attribute "%s".', $tagName, $service, $indexAttribute)]; - } else { - $message = [sprintf('Method "%s::%s()" should ', $class, $defaultMethod), '.']; - } - - if (!($rm = $r->getMethod($defaultMethod))->isStatic()) { - throw new InvalidArgumentException(implode('be static', $message)); - } - - if (!$rm->isPublic()) { - throw new InvalidArgumentException(implode('be public', $message)); - } - - $default = $rm->invoke(null); - - if ('priority' === $indexAttribute) { - if (!\is_int($default)) { - throw new InvalidArgumentException(implode(sprintf('return int (got "%s")', get_debug_type($default)), $message)); - } - - return $default; - } - - if (\is_int($default)) { - $default = (string) $default; - } - - if (!\is_string($default)) { - throw new InvalidArgumentException(implode(sprintf('return string|int (got "%s")', get_debug_type($default)), $message)); - } - - return $default; - } -} diff --git a/lib/symfony/dependency-injection/Compiler/RegisterAutoconfigureAttributesPass.php b/lib/symfony/dependency-injection/Compiler/RegisterAutoconfigureAttributesPass.php deleted file mode 100644 index cc3b117a4..000000000 --- a/lib/symfony/dependency-injection/Compiler/RegisterAutoconfigureAttributesPass.php +++ /dev/null @@ -1,92 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Attribute\Autoconfigure; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; - -/** - * Reads #[Autoconfigure] attributes on definitions that are autoconfigured - * and don't have the "container.ignore_attributes" tag. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -final class RegisterAutoconfigureAttributesPass implements CompilerPassInterface -{ - private static $registerForAutoconfiguration; - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - if (80000 > \PHP_VERSION_ID) { - return; - } - - foreach ($container->getDefinitions() as $id => $definition) { - if ($this->accept($definition) && $class = $container->getReflectionClass($definition->getClass(), false)) { - $this->processClass($container, $class); - } - } - } - - public function accept(Definition $definition): bool - { - return 80000 <= \PHP_VERSION_ID && $definition->isAutoconfigured() && !$definition->hasTag('container.ignore_attributes'); - } - - public function processClass(ContainerBuilder $container, \ReflectionClass $class) - { - foreach ($class->getAttributes(Autoconfigure::class, \ReflectionAttribute::IS_INSTANCEOF) as $attribute) { - self::registerForAutoconfiguration($container, $class, $attribute); - } - } - - private static function registerForAutoconfiguration(ContainerBuilder $container, \ReflectionClass $class, \ReflectionAttribute $attribute) - { - if (self::$registerForAutoconfiguration) { - return (self::$registerForAutoconfiguration)($container, $class, $attribute); - } - - $parseDefinitions = new \ReflectionMethod(YamlFileLoader::class, 'parseDefinitions'); - $parseDefinitions->setAccessible(true); - $yamlLoader = $parseDefinitions->getDeclaringClass()->newInstanceWithoutConstructor(); - - self::$registerForAutoconfiguration = static function (ContainerBuilder $container, \ReflectionClass $class, \ReflectionAttribute $attribute) use ($parseDefinitions, $yamlLoader) { - $attribute = (array) $attribute->newInstance(); - - foreach ($attribute['tags'] ?? [] as $i => $tag) { - if (\is_array($tag) && [0] === array_keys($tag)) { - $attribute['tags'][$i] = [$class->name => $tag[0]]; - } - } - - $parseDefinitions->invoke( - $yamlLoader, - [ - 'services' => [ - '_instanceof' => [ - $class->name => [$container->registerForAutoconfiguration($class->name)] + $attribute, - ], - ], - ], - $class->getFileName(), - false - ); - }; - - return (self::$registerForAutoconfiguration)($container, $class, $attribute); - } -} diff --git a/lib/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php b/lib/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php deleted file mode 100644 index 251889ebe..000000000 --- a/lib/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php +++ /dev/null @@ -1,75 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\EnvVarProcessor; -use Symfony\Component\DependencyInjection\EnvVarProcessorInterface; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Creates the container.env_var_processors_locator service. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class RegisterEnvVarProcessorsPass implements CompilerPassInterface -{ - private const ALLOWED_TYPES = ['array', 'bool', 'float', 'int', 'string']; - - public function process(ContainerBuilder $container) - { - $bag = $container->getParameterBag(); - $types = []; - $processors = []; - foreach ($container->findTaggedServiceIds('container.env_var_processor') as $id => $tags) { - if (!$r = $container->getReflectionClass($class = $container->getDefinition($id)->getClass())) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); - } elseif (!$r->isSubclassOf(EnvVarProcessorInterface::class)) { - throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, EnvVarProcessorInterface::class)); - } - foreach ($class::getProvidedTypes() as $prefix => $type) { - $processors[$prefix] = new Reference($id); - $types[$prefix] = self::validateProvidedTypes($type, $class); - } - } - - if ($bag instanceof EnvPlaceholderParameterBag) { - foreach (EnvVarProcessor::getProvidedTypes() as $prefix => $type) { - if (!isset($types[$prefix])) { - $types[$prefix] = self::validateProvidedTypes($type, EnvVarProcessor::class); - } - } - $bag->setProvidedTypes($types); - } - - if ($processors) { - $container->setAlias('container.env_var_processors_locator', (string) ServiceLocatorTagPass::register($container, $processors)) - ->setPublic(true) - ; - } - } - - private static function validateProvidedTypes(string $types, string $class): array - { - $types = explode('|', $types); - - foreach ($types as $type) { - if (!\in_array($type, self::ALLOWED_TYPES)) { - throw new InvalidArgumentException(sprintf('Invalid type "%s" returned by "%s::getProvidedTypes()", expected one of "%s".', $type, $class, implode('", "', self::ALLOWED_TYPES))); - } - } - - return $types; - } -} diff --git a/lib/symfony/dependency-injection/Compiler/RegisterReverseContainerPass.php b/lib/symfony/dependency-injection/Compiler/RegisterReverseContainerPass.php deleted file mode 100644 index c5eb9bf08..000000000 --- a/lib/symfony/dependency-injection/Compiler/RegisterReverseContainerPass.php +++ /dev/null @@ -1,70 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Reference; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class RegisterReverseContainerPass implements CompilerPassInterface -{ - private $beforeRemoving; - private $serviceId; - private $tagName; - - public function __construct(bool $beforeRemoving, string $serviceId = 'reverse_container', string $tagName = 'container.reversible') - { - if (1 < \func_num_args()) { - trigger_deprecation('symfony/dependency-injection', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->beforeRemoving = $beforeRemoving; - $this->serviceId = $serviceId; - $this->tagName = $tagName; - } - - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition($this->serviceId)) { - return; - } - - $refType = $this->beforeRemoving ? ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE : ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; - $services = []; - foreach ($container->findTaggedServiceIds($this->tagName) as $id => $tags) { - $services[$id] = new Reference($id, $refType); - } - - if ($this->beforeRemoving) { - // prevent inlining of the reverse container - $services[$this->serviceId] = new Reference($this->serviceId, $refType); - } - $locator = $container->getDefinition($this->serviceId)->getArgument(1); - - if ($locator instanceof Reference) { - $locator = $container->getDefinition((string) $locator); - } - if ($locator instanceof Definition) { - foreach ($services as $id => $ref) { - $services[$id] = new ServiceClosureArgument($ref); - } - $locator->replaceArgument(0, $services); - } else { - $locator->setValues($services); - } - } -} diff --git a/lib/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php b/lib/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php deleted file mode 100644 index 2a458ad12..000000000 --- a/lib/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php +++ /dev/null @@ -1,131 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Psr\Container\ContainerInterface as PsrContainerInterface; -use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; -use Symfony\Component\DependencyInjection\Argument\BoundArgument; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\TypedReference; -use Symfony\Component\HttpFoundation\Session\SessionInterface; -use Symfony\Contracts\Service\ServiceProviderInterface; -use Symfony\Contracts\Service\ServiceSubscriberInterface; - -/** - * Compiler pass to register tagged services that require a service locator. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class RegisterServiceSubscribersPass extends AbstractRecursivePass -{ - protected function processValue($value, bool $isRoot = false) - { - if (!$value instanceof Definition || $value->isAbstract() || $value->isSynthetic() || !$value->hasTag('container.service_subscriber')) { - return parent::processValue($value, $isRoot); - } - - $serviceMap = []; - $autowire = $value->isAutowired(); - - foreach ($value->getTag('container.service_subscriber') as $attributes) { - if (!$attributes) { - $autowire = true; - continue; - } - ksort($attributes); - if ([] !== array_diff(array_keys($attributes), ['id', 'key'])) { - throw new InvalidArgumentException(sprintf('The "container.service_subscriber" tag accepts only the "key" and "id" attributes, "%s" given for service "%s".', implode('", "', array_keys($attributes)), $this->currentId)); - } - if (!\array_key_exists('id', $attributes)) { - throw new InvalidArgumentException(sprintf('Missing "id" attribute on "container.service_subscriber" tag with key="%s" for service "%s".', $attributes['key'], $this->currentId)); - } - if (!\array_key_exists('key', $attributes)) { - $attributes['key'] = $attributes['id']; - } - if (isset($serviceMap[$attributes['key']])) { - continue; - } - $serviceMap[$attributes['key']] = new Reference($attributes['id']); - } - $class = $value->getClass(); - - if (!$r = $this->container->getReflectionClass($class)) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $this->currentId)); - } - if (!$r->isSubclassOf(ServiceSubscriberInterface::class)) { - throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $this->currentId, ServiceSubscriberInterface::class)); - } - $class = $r->name; - $replaceDeprecatedSession = $this->container->has('.session.deprecated') && $r->isSubclassOf(AbstractController::class); - $subscriberMap = []; - - foreach ($class::getSubscribedServices() as $key => $type) { - if (!\is_string($type) || !preg_match('/(?(DEFINE)(?<cn>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+))(?(DEFINE)(?<fqcn>(?&cn)(?:\\\\(?&cn))*+))^\??(?&fqcn)(?:(?:\|(?&fqcn))*+|(?:&(?&fqcn))*+)$/', $type)) { - throw new InvalidArgumentException(sprintf('"%s::getSubscribedServices()" must return valid PHP types for service "%s" key "%s", "%s" returned.', $class, $this->currentId, $key, \is_string($type) ? $type : get_debug_type($type))); - } - if ($optionalBehavior = '?' === $type[0]) { - $type = substr($type, 1); - $optionalBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; - } - if (\is_int($name = $key)) { - $key = $type; - $name = null; - } - if (!isset($serviceMap[$key])) { - if (!$autowire) { - throw new InvalidArgumentException(sprintf('Service "%s" misses a "container.service_subscriber" tag with "key"/"id" attributes corresponding to entry "%s" as returned by "%s::getSubscribedServices()".', $this->currentId, $key, $class)); - } - if ($replaceDeprecatedSession && SessionInterface::class === $type) { - // This prevents triggering the deprecation when building the container - // Should be removed in Symfony 6.0 - $type = '.session.deprecated'; - } - $serviceMap[$key] = new Reference($type); - } - - if ($name) { - if (false !== $i = strpos($name, '::get')) { - $name = lcfirst(substr($name, 5 + $i)); - } elseif (str_contains($name, '::')) { - $name = null; - } - } - - if (null !== $name && !$this->container->has($name) && !$this->container->has($type.' $'.$name)) { - $camelCaseName = lcfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $name)))); - $name = $this->container->has($type.' $'.$camelCaseName) ? $camelCaseName : $name; - } - - $subscriberMap[$key] = new TypedReference((string) $serviceMap[$key], $type, $optionalBehavior ?: ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $name); - unset($serviceMap[$key]); - } - - if ($serviceMap = array_keys($serviceMap)) { - $message = sprintf(1 < \count($serviceMap) ? 'keys "%s" do' : 'key "%s" does', str_replace('%', '%%', implode('", "', $serviceMap))); - throw new InvalidArgumentException(sprintf('Service %s not exist in the map returned by "%s::getSubscribedServices()" for service "%s".', $message, $class, $this->currentId)); - } - - $locatorRef = ServiceLocatorTagPass::register($this->container, $subscriberMap, $this->currentId); - - $value->addTag('container.service_subscriber.locator', ['id' => (string) $locatorRef]); - - $value->setBindings([ - PsrContainerInterface::class => new BoundArgument($locatorRef, false), - ServiceProviderInterface::class => new BoundArgument($locatorRef, false), - ] + $value->getBindings()); - - return parent::processValue($value); - } -} diff --git a/lib/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php b/lib/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php deleted file mode 100644 index 04b6852fa..000000000 --- a/lib/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * Removes abstract Definitions. - */ -class RemoveAbstractDefinitionsPass implements CompilerPassInterface -{ - /** - * Removes abstract definitions from the ContainerBuilder. - */ - public function process(ContainerBuilder $container) - { - foreach ($container->getDefinitions() as $id => $definition) { - if ($definition->isAbstract()) { - $container->removeDefinition($id); - $container->log($this, sprintf('Removed service "%s"; reason: abstract.', $id)); - } - } - } -} diff --git a/lib/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php b/lib/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php deleted file mode 100644 index 75b36d227..000000000 --- a/lib/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * Remove private aliases from the container. They were only used to establish - * dependencies between services, and these dependencies have been resolved in - * one of the previous passes. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class RemovePrivateAliasesPass implements CompilerPassInterface -{ - /** - * Removes private aliases from the ContainerBuilder. - */ - public function process(ContainerBuilder $container) - { - foreach ($container->getAliases() as $id => $alias) { - if ($alias->isPublic()) { - continue; - } - - $container->removeAlias($id); - $container->log($this, sprintf('Removed service "%s"; reason: private alias.', $id)); - } - } -} diff --git a/lib/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php b/lib/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php deleted file mode 100644 index cf1a3ddc7..000000000 --- a/lib/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Removes unused service definitions from the container. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - * @author Nicolas Grekas <p@tchwork.com> - */ -class RemoveUnusedDefinitionsPass extends AbstractRecursivePass -{ - private $connectedIds = []; - - /** - * Processes the ContainerBuilder to remove unused definitions. - */ - public function process(ContainerBuilder $container) - { - try { - $this->enableExpressionProcessing(); - $this->container = $container; - $connectedIds = []; - $aliases = $container->getAliases(); - - foreach ($aliases as $id => $alias) { - if ($alias->isPublic()) { - $this->connectedIds[] = (string) $aliases[$id]; - } - } - - foreach ($container->getDefinitions() as $id => $definition) { - if ($definition->isPublic()) { - $connectedIds[$id] = true; - $this->processValue($definition); - } - } - - while ($this->connectedIds) { - $ids = $this->connectedIds; - $this->connectedIds = []; - foreach ($ids as $id) { - if (!isset($connectedIds[$id]) && $container->hasDefinition($id)) { - $connectedIds[$id] = true; - $this->processValue($container->getDefinition($id)); - } - } - } - - foreach ($container->getDefinitions() as $id => $definition) { - if (!isset($connectedIds[$id])) { - $container->removeDefinition($id); - $container->resolveEnvPlaceholders(!$definition->hasErrors() ? serialize($definition) : $definition); - $container->log($this, sprintf('Removed service "%s"; reason: unused.', $id)); - } - } - } finally { - $this->container = null; - $this->connectedIds = []; - } - } - - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if (!$value instanceof Reference) { - return parent::processValue($value, $isRoot); - } - - if (ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE !== $value->getInvalidBehavior()) { - $this->connectedIds[] = (string) $value; - } - - return $value; - } -} diff --git a/lib/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php b/lib/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php deleted file mode 100644 index bb2ba0d54..000000000 --- a/lib/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php +++ /dev/null @@ -1,120 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Replaces aliases with actual service definitions, effectively removing these - * aliases. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class ReplaceAliasByActualDefinitionPass extends AbstractRecursivePass -{ - private $replacements; - private $autoAliasServicePass; - - /** - * @internal to be removed in Symfony 6.0 - * - * @return $this - */ - public function setAutoAliasServicePass(AutoAliasServicePass $autoAliasServicePass): self - { - $this->autoAliasServicePass = $autoAliasServicePass; - - return $this; - } - - /** - * Process the Container to replace aliases with service definitions. - * - * @throws InvalidArgumentException if the service definition does not exist - */ - public function process(ContainerBuilder $container) - { - // First collect all alias targets that need to be replaced - $seenAliasTargets = []; - $replacements = []; - - $privateAliases = $this->autoAliasServicePass ? $this->autoAliasServicePass->getPrivateAliases() : []; - foreach ($privateAliases as $target) { - $target->setDeprecated('symfony/dependency-injection', '5.4', 'Accessing the "%alias_id%" service directly from the container is deprecated, use dependency injection instead.'); - } - - foreach ($container->getAliases() as $definitionId => $target) { - $targetId = (string) $target; - // Special case: leave this target alone - if ('service_container' === $targetId) { - continue; - } - // Check if target needs to be replaced - if (isset($replacements[$targetId])) { - $container->setAlias($definitionId, $replacements[$targetId])->setPublic($target->isPublic()); - - if ($target->isDeprecated()) { - $container->getAlias($definitionId)->setDeprecated(...array_values($target->getDeprecation('%alias_id%'))); - } - } - // No need to process the same target twice - if (isset($seenAliasTargets[$targetId])) { - continue; - } - // Process new target - $seenAliasTargets[$targetId] = true; - try { - $definition = $container->getDefinition($targetId); - } catch (ServiceNotFoundException $e) { - if ('' !== $e->getId() && '@' === $e->getId()[0]) { - throw new ServiceNotFoundException($e->getId(), $e->getSourceId(), null, [substr($e->getId(), 1)]); - } - - throw $e; - } - if ($definition->isPublic()) { - continue; - } - // Remove private definition and schedule for replacement - $definition->setPublic($target->isPublic()); - $container->setDefinition($definitionId, $definition); - $container->removeDefinition($targetId); - $replacements[$targetId] = $definitionId; - - if ($target->isPublic() && $target->isDeprecated()) { - $definition->addTag('container.private', $target->getDeprecation('%service_id%')); - } - } - $this->replacements = $replacements; - - parent::process($container); - $this->replacements = []; - } - - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if ($value instanceof Reference && isset($this->replacements[$referenceId = (string) $value])) { - // Perform the replacement - $newId = $this->replacements[$referenceId]; - $value = new Reference($newId, $value->getInvalidBehavior()); - $this->container->log($this, sprintf('Changed reference of service "%s" previously pointing to "%s" to "%s".', $this->currentId, $referenceId, $newId)); - } - - return parent::processValue($value, $isRoot); - } -} diff --git a/lib/symfony/dependency-injection/Compiler/ResolveBindingsPass.php b/lib/symfony/dependency-injection/Compiler/ResolveBindingsPass.php deleted file mode 100644 index 5bc379153..000000000 --- a/lib/symfony/dependency-injection/Compiler/ResolveBindingsPass.php +++ /dev/null @@ -1,246 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\BoundArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; -use Symfony\Component\DependencyInjection\Attribute\Target; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\TypedReference; - -/** - * @author Guilhem Niot <guilhem.niot@gmail.com> - */ -class ResolveBindingsPass extends AbstractRecursivePass -{ - private $usedBindings = []; - private $unusedBindings = []; - private $errorMessages = []; - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - $this->usedBindings = $container->getRemovedBindingIds(); - - try { - parent::process($container); - - foreach ($this->unusedBindings as [$key, $serviceId, $bindingType, $file]) { - $argumentType = $argumentName = $message = null; - - if (str_contains($key, ' ')) { - [$argumentType, $argumentName] = explode(' ', $key, 2); - } elseif ('$' === $key[0]) { - $argumentName = $key; - } else { - $argumentType = $key; - } - - if ($argumentType) { - $message .= sprintf('of type "%s" ', $argumentType); - } - - if ($argumentName) { - $message .= sprintf('named "%s" ', $argumentName); - } - - if (BoundArgument::DEFAULTS_BINDING === $bindingType) { - $message .= 'under "_defaults"'; - } elseif (BoundArgument::INSTANCEOF_BINDING === $bindingType) { - $message .= 'under "_instanceof"'; - } else { - $message .= sprintf('for service "%s"', $serviceId); - } - - if ($file) { - $message .= sprintf(' in file "%s"', $file); - } - - $message = sprintf('A binding is configured for an argument %s, but no corresponding argument has been found. It may be unused and should be removed, or it may have a typo.', $message); - - if ($this->errorMessages) { - $message .= sprintf("\nCould be related to%s:", 1 < \count($this->errorMessages) ? ' one of' : ''); - } - foreach ($this->errorMessages as $m) { - $message .= "\n - ".$m; - } - throw new InvalidArgumentException($message); - } - } finally { - $this->usedBindings = []; - $this->unusedBindings = []; - $this->errorMessages = []; - } - } - - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if ($value instanceof TypedReference && $value->getType() === (string) $value) { - // Already checked - $bindings = $this->container->getDefinition($this->currentId)->getBindings(); - $name = $value->getName(); - - if (isset($name, $bindings[$name = $value.' $'.$name])) { - return $this->getBindingValue($bindings[$name]); - } - - if (isset($bindings[$value->getType()])) { - return $this->getBindingValue($bindings[$value->getType()]); - } - - return parent::processValue($value, $isRoot); - } - - if (!$value instanceof Definition || !$bindings = $value->getBindings()) { - return parent::processValue($value, $isRoot); - } - - $bindingNames = []; - - foreach ($bindings as $key => $binding) { - [$bindingValue, $bindingId, $used, $bindingType, $file] = $binding->getValues(); - if ($used) { - $this->usedBindings[$bindingId] = true; - unset($this->unusedBindings[$bindingId]); - } elseif (!isset($this->usedBindings[$bindingId])) { - $this->unusedBindings[$bindingId] = [$key, $this->currentId, $bindingType, $file]; - } - - if (preg_match('/^(?:(?:array|bool|float|int|string|iterable|([^ $]++)) )\$/', $key, $m)) { - $bindingNames[substr($key, \strlen($m[0]))] = $binding; - } - - if (!isset($m[1])) { - continue; - } - - if (is_subclass_of($m[1], \UnitEnum::class)) { - $bindingNames[substr($key, \strlen($m[0]))] = $binding; - continue; - } - - if (null !== $bindingValue && !$bindingValue instanceof Reference && !$bindingValue instanceof Definition && !$bindingValue instanceof TaggedIteratorArgument && !$bindingValue instanceof ServiceLocatorArgument) { - throw new InvalidArgumentException(sprintf('Invalid value for binding key "%s" for service "%s": expected "%s", "%s", "%s", "%s" or null, "%s" given.', $key, $this->currentId, Reference::class, Definition::class, TaggedIteratorArgument::class, ServiceLocatorArgument::class, get_debug_type($bindingValue))); - } - } - - if ($value->isAbstract()) { - return parent::processValue($value, $isRoot); - } - - $calls = $value->getMethodCalls(); - - try { - if ($constructor = $this->getConstructor($value, false)) { - $calls[] = [$constructor, $value->getArguments()]; - } - } catch (RuntimeException $e) { - $this->errorMessages[] = $e->getMessage(); - $this->container->getDefinition($this->currentId)->addError($e->getMessage()); - - return parent::processValue($value, $isRoot); - } - - foreach ($calls as $i => $call) { - [$method, $arguments] = $call; - - if ($method instanceof \ReflectionFunctionAbstract) { - $reflectionMethod = $method; - } else { - try { - $reflectionMethod = $this->getReflectionMethod($value, $method); - } catch (RuntimeException $e) { - if ($value->getFactory()) { - continue; - } - throw $e; - } - } - - foreach ($reflectionMethod->getParameters() as $key => $parameter) { - if (\array_key_exists($key, $arguments) && '' !== $arguments[$key]) { - continue; - } - - $typeHint = ProxyHelper::getTypeHint($reflectionMethod, $parameter); - $name = Target::parseName($parameter); - - if ($typeHint && \array_key_exists($k = ltrim($typeHint, '\\').' $'.$name, $bindings)) { - $arguments[$key] = $this->getBindingValue($bindings[$k]); - - continue; - } - - if (\array_key_exists('$'.$name, $bindings)) { - $arguments[$key] = $this->getBindingValue($bindings['$'.$name]); - - continue; - } - - if ($typeHint && '\\' === $typeHint[0] && isset($bindings[$typeHint = substr($typeHint, 1)])) { - $arguments[$key] = $this->getBindingValue($bindings[$typeHint]); - - continue; - } - - if (isset($bindingNames[$name]) || isset($bindingNames[$parameter->name])) { - $bindingKey = array_search($binding, $bindings, true); - $argumentType = substr($bindingKey, 0, strpos($bindingKey, ' ')); - $this->errorMessages[] = sprintf('Did you forget to add the type "%s" to argument "$%s" of method "%s::%s()"?', $argumentType, $parameter->name, $reflectionMethod->class, $reflectionMethod->name); - } - } - - if ($arguments !== $call[1]) { - ksort($arguments); - $calls[$i][1] = $arguments; - } - } - - if ($constructor) { - [, $arguments] = array_pop($calls); - - if ($arguments !== $value->getArguments()) { - $value->setArguments($arguments); - } - } - - if ($calls !== $value->getMethodCalls()) { - $value->setMethodCalls($calls); - } - - return parent::processValue($value, $isRoot); - } - - /** - * @return mixed - */ - private function getBindingValue(BoundArgument $binding) - { - [$bindingValue, $bindingId] = $binding->getValues(); - - $this->usedBindings[$bindingId] = true; - unset($this->unusedBindings[$bindingId]); - - return $bindingValue; - } -} diff --git a/lib/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php b/lib/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php deleted file mode 100644 index aefd2294a..000000000 --- a/lib/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php +++ /dev/null @@ -1,204 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\ExceptionInterface; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; - -/** - * This replaces all ChildDefinition instances with their equivalent fully - * merged Definition instance. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - * @author Nicolas Grekas <p@tchwork.com> - */ -class ResolveChildDefinitionsPass extends AbstractRecursivePass -{ - private $currentPath; - - protected function processValue($value, bool $isRoot = false) - { - if (!$value instanceof Definition) { - return parent::processValue($value, $isRoot); - } - if ($isRoot) { - // yes, we are specifically fetching the definition from the - // container to ensure we are not operating on stale data - $value = $this->container->getDefinition($this->currentId); - } - if ($value instanceof ChildDefinition) { - $this->currentPath = []; - $value = $this->resolveDefinition($value); - if ($isRoot) { - $this->container->setDefinition($this->currentId, $value); - } - } - - return parent::processValue($value, $isRoot); - } - - /** - * Resolves the definition. - * - * @throws RuntimeException When the definition is invalid - */ - private function resolveDefinition(ChildDefinition $definition): Definition - { - try { - return $this->doResolveDefinition($definition); - } catch (ServiceCircularReferenceException $e) { - throw $e; - } catch (ExceptionInterface $e) { - $r = new \ReflectionProperty($e, 'message'); - $r->setAccessible(true); - $r->setValue($e, sprintf('Service "%s": %s', $this->currentId, $e->getMessage())); - - throw $e; - } - } - - private function doResolveDefinition(ChildDefinition $definition): Definition - { - if (!$this->container->has($parent = $definition->getParent())) { - throw new RuntimeException(sprintf('Parent definition "%s" does not exist.', $parent)); - } - - $searchKey = array_search($parent, $this->currentPath); - $this->currentPath[] = $parent; - - if (false !== $searchKey) { - throw new ServiceCircularReferenceException($parent, \array_slice($this->currentPath, $searchKey)); - } - - $parentDef = $this->container->findDefinition($parent); - if ($parentDef instanceof ChildDefinition) { - $id = $this->currentId; - $this->currentId = $parent; - $parentDef = $this->resolveDefinition($parentDef); - $this->container->setDefinition($parent, $parentDef); - $this->currentId = $id; - } - - $this->container->log($this, sprintf('Resolving inheritance for "%s" (parent: %s).', $this->currentId, $parent)); - $def = new Definition(); - - // merge in parent definition - // purposely ignored attributes: abstract, shared, tags, autoconfigured - $def->setClass($parentDef->getClass()); - $def->setArguments($parentDef->getArguments()); - $def->setMethodCalls($parentDef->getMethodCalls()); - $def->setProperties($parentDef->getProperties()); - if ($parentDef->isDeprecated()) { - $deprecation = $parentDef->getDeprecation('%service_id%'); - $def->setDeprecated($deprecation['package'], $deprecation['version'], $deprecation['message']); - } - $def->setFactory($parentDef->getFactory()); - $def->setConfigurator($parentDef->getConfigurator()); - $def->setFile($parentDef->getFile()); - $def->setPublic($parentDef->isPublic()); - $def->setLazy($parentDef->isLazy()); - $def->setAutowired($parentDef->isAutowired()); - $def->setChanges($parentDef->getChanges()); - - $def->setBindings($definition->getBindings() + $parentDef->getBindings()); - - $def->setSynthetic($definition->isSynthetic()); - - // overwrite with values specified in the decorator - $changes = $definition->getChanges(); - if (isset($changes['class'])) { - $def->setClass($definition->getClass()); - } - if (isset($changes['factory'])) { - $def->setFactory($definition->getFactory()); - } - if (isset($changes['configurator'])) { - $def->setConfigurator($definition->getConfigurator()); - } - if (isset($changes['file'])) { - $def->setFile($definition->getFile()); - } - if (isset($changes['public'])) { - $def->setPublic($definition->isPublic()); - } else { - $def->setPublic($parentDef->isPublic()); - } - if (isset($changes['lazy'])) { - $def->setLazy($definition->isLazy()); - } - if (isset($changes['deprecated'])) { - if ($definition->isDeprecated()) { - $deprecation = $definition->getDeprecation('%service_id%'); - $def->setDeprecated($deprecation['package'], $deprecation['version'], $deprecation['message']); - } else { - $def->setDeprecated(false); - } - } - if (isset($changes['autowired'])) { - $def->setAutowired($definition->isAutowired()); - } - if (isset($changes['shared'])) { - $def->setShared($definition->isShared()); - } - if (isset($changes['decorated_service'])) { - $decoratedService = $definition->getDecoratedService(); - if (null === $decoratedService) { - $def->setDecoratedService($decoratedService); - } else { - $def->setDecoratedService($decoratedService[0], $decoratedService[1], $decoratedService[2], $decoratedService[3] ?? ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE); - } - } - - // merge arguments - foreach ($definition->getArguments() as $k => $v) { - if (is_numeric($k)) { - $def->addArgument($v); - } elseif (str_starts_with($k, 'index_')) { - $def->replaceArgument((int) substr($k, \strlen('index_')), $v); - } else { - $def->setArgument($k, $v); - } - } - - // merge properties - foreach ($definition->getProperties() as $k => $v) { - $def->setProperty($k, $v); - } - - // append method calls - if ($calls = $definition->getMethodCalls()) { - $def->setMethodCalls(array_merge($def->getMethodCalls(), $calls)); - } - - $def->addError($parentDef); - $def->addError($definition); - - // these attributes are always taken from the child - $def->setAbstract($definition->isAbstract()); - $def->setTags($definition->getTags()); - // autoconfigure is never taken from parent (on purpose) - // and it's not legal on an instanceof - $def->setAutoconfigured($definition->isAutoconfigured()); - - if (!$def->hasTag('proxy')) { - foreach ($parentDef->getTag('proxy') as $v) { - $def->addTag('proxy', $v); - } - } - - return $def; - } -} diff --git a/lib/symfony/dependency-injection/Compiler/ResolveClassPass.php b/lib/symfony/dependency-injection/Compiler/ResolveClassPass.php deleted file mode 100644 index e67a2a8ed..000000000 --- a/lib/symfony/dependency-injection/Compiler/ResolveClassPass.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class ResolveClassPass implements CompilerPassInterface -{ - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - foreach ($container->getDefinitions() as $id => $definition) { - if ($definition->isSynthetic() || null !== $definition->getClass()) { - continue; - } - if (preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)++$/', $id)) { - if ($definition instanceof ChildDefinition && !class_exists($id)) { - throw new InvalidArgumentException(sprintf('Service definition "%s" has a parent but no class, and its name looks like an FQCN. Either the class is missing or you want to inherit it from the parent service. To resolve this ambiguity, please rename this service to a non-FQCN (e.g. using dots), or create the missing class.', $id)); - } - $definition->setClass($id); - } - } - } -} diff --git a/lib/symfony/dependency-injection/Compiler/ResolveDecoratorStackPass.php b/lib/symfony/dependency-injection/Compiler/ResolveDecoratorStackPass.php deleted file mode 100644 index 4914b3ac9..000000000 --- a/lib/symfony/dependency-injection/Compiler/ResolveDecoratorStackPass.php +++ /dev/null @@ -1,131 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class ResolveDecoratorStackPass implements CompilerPassInterface -{ - private $tag; - - public function __construct(string $tag = 'container.stack') - { - if (0 < \func_num_args()) { - trigger_deprecation('symfony/dependency-injection', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->tag = $tag; - } - - public function process(ContainerBuilder $container) - { - $stacks = []; - - foreach ($container->findTaggedServiceIds($this->tag) as $id => $tags) { - $definition = $container->getDefinition($id); - - if (!$definition instanceof ChildDefinition) { - throw new InvalidArgumentException(sprintf('Invalid service "%s": only definitions with a "parent" can have the "%s" tag.', $id, $this->tag)); - } - - if (!$stack = $definition->getArguments()) { - throw new InvalidArgumentException(sprintf('Invalid service "%s": the stack of decorators is empty.', $id)); - } - - $stacks[$id] = $stack; - } - - if (!$stacks) { - return; - } - - $resolvedDefinitions = []; - - foreach ($container->getDefinitions() as $id => $definition) { - if (!isset($stacks[$id])) { - $resolvedDefinitions[$id] = $definition; - continue; - } - - foreach (array_reverse($this->resolveStack($stacks, [$id]), true) as $k => $v) { - $resolvedDefinitions[$k] = $v; - } - - $alias = $container->setAlias($id, $k); - - if ($definition->getChanges()['public'] ?? false) { - $alias->setPublic($definition->isPublic()); - } - - if ($definition->isDeprecated()) { - $alias->setDeprecated(...array_values($definition->getDeprecation('%alias_id%'))); - } - } - - $container->setDefinitions($resolvedDefinitions); - } - - private function resolveStack(array $stacks, array $path): array - { - $definitions = []; - $id = end($path); - $prefix = '.'.$id.'.'; - - if (!isset($stacks[$id])) { - return [$id => new ChildDefinition($id)]; - } - - if (key($path) !== $searchKey = array_search($id, $path)) { - throw new ServiceCircularReferenceException($id, \array_slice($path, $searchKey)); - } - - foreach ($stacks[$id] as $k => $definition) { - if ($definition instanceof ChildDefinition && isset($stacks[$definition->getParent()])) { - $path[] = $definition->getParent(); - $definition = unserialize(serialize($definition)); // deep clone - } elseif ($definition instanceof Definition) { - $definitions[$decoratedId = $prefix.$k] = $definition; - continue; - } elseif ($definition instanceof Reference || $definition instanceof Alias) { - $path[] = (string) $definition; - } else { - throw new InvalidArgumentException(sprintf('Invalid service "%s": unexpected value of type "%s" found in the stack of decorators.', $id, get_debug_type($definition))); - } - - $p = $prefix.$k; - - foreach ($this->resolveStack($stacks, $path) as $k => $v) { - $definitions[$decoratedId = $p.$k] = $definition instanceof ChildDefinition ? $definition->setParent($k) : new ChildDefinition($k); - $definition = null; - } - array_pop($path); - } - - if (1 === \count($path)) { - foreach ($definitions as $k => $definition) { - $definition->setPublic(false)->setTags([])->setDecoratedService($decoratedId); - } - $definition->setDecoratedService(null); - } - - return $definitions; - } -} diff --git a/lib/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php b/lib/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php deleted file mode 100644 index ea52b1459..000000000 --- a/lib/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Definition; - -/** - * Replaces env var placeholders by their current values. - */ -class ResolveEnvPlaceholdersPass extends AbstractRecursivePass -{ - protected function processValue($value, bool $isRoot = false) - { - if (\is_string($value)) { - return $this->container->resolveEnvPlaceholders($value, true); - } - if ($value instanceof Definition) { - $changes = $value->getChanges(); - if (isset($changes['class'])) { - $value->setClass($this->container->resolveEnvPlaceholders($value->getClass(), true)); - } - if (isset($changes['file'])) { - $value->setFile($this->container->resolveEnvPlaceholders($value->getFile(), true)); - } - } - - $value = parent::processValue($value, $isRoot); - - if ($value && \is_array($value) && !$isRoot) { - $value = array_combine($this->container->resolveEnvPlaceholders(array_keys($value), true), $value); - } - - return $value; - } -} diff --git a/lib/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php b/lib/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php deleted file mode 100644 index 23f535b71..000000000 --- a/lib/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; - -/** - * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> - */ -class ResolveFactoryClassPass extends AbstractRecursivePass -{ - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if ($value instanceof Definition && \is_array($factory = $value->getFactory()) && null === $factory[0]) { - if (null === $class = $value->getClass()) { - throw new RuntimeException(sprintf('The "%s" service is defined to be created by a factory, but is missing the factory class. Did you forget to define the factory or service class?', $this->currentId)); - } - - $factory[0] = $class; - $value->setFactory($factory); - } - - return parent::processValue($value, $isRoot); - } -} diff --git a/lib/symfony/dependency-injection/Compiler/ResolveHotPathPass.php b/lib/symfony/dependency-injection/Compiler/ResolveHotPathPass.php deleted file mode 100644 index dee2dc6be..000000000 --- a/lib/symfony/dependency-injection/Compiler/ResolveHotPathPass.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Propagate "container.hot_path" tags to referenced services. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class ResolveHotPathPass extends AbstractRecursivePass -{ - private $tagName; - private $resolvedIds = []; - - public function __construct(string $tagName = 'container.hot_path') - { - if (0 < \func_num_args()) { - trigger_deprecation('symfony/dependency-injection', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->tagName = $tagName; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - try { - parent::process($container); - $container->getDefinition('service_container')->clearTag($this->tagName); - } finally { - $this->resolvedIds = []; - } - } - - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if ($value instanceof ArgumentInterface) { - return $value; - } - - if ($value instanceof Definition && $isRoot) { - if ($value->isDeprecated()) { - return $value->clearTag($this->tagName); - } - - $this->resolvedIds[$this->currentId] = true; - - if (!$value->hasTag($this->tagName)) { - return $value; - } - } - - if ($value instanceof Reference && ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE !== $value->getInvalidBehavior() && $this->container->hasDefinition($id = (string) $value)) { - $definition = $this->container->getDefinition($id); - - if ($definition->isDeprecated() || $definition->hasTag($this->tagName)) { - return $value; - } - - $definition->addTag($this->tagName); - - if (isset($this->resolvedIds[$id])) { - parent::processValue($definition, false); - } - - return $value; - } - - return parent::processValue($value, $isRoot); - } -} diff --git a/lib/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php b/lib/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php deleted file mode 100644 index b211b84e1..000000000 --- a/lib/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php +++ /dev/null @@ -1,177 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; - -/** - * Applies instanceof conditionals to definitions. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class ResolveInstanceofConditionalsPass implements CompilerPassInterface -{ - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - foreach ($container->getAutoconfiguredInstanceof() as $interface => $definition) { - if ($definition->getArguments()) { - throw new InvalidArgumentException(sprintf('Autoconfigured instanceof for type "%s" defines arguments but these are not supported and should be removed.', $interface)); - } - } - - $tagsToKeep = []; - - if ($container->hasParameter('container.behavior_describing_tags')) { - $tagsToKeep = $container->getParameter('container.behavior_describing_tags'); - } - - foreach ($container->getDefinitions() as $id => $definition) { - $container->setDefinition($id, $this->processDefinition($container, $id, $definition, $tagsToKeep)); - } - - if ($container->hasParameter('container.behavior_describing_tags')) { - $container->getParameterBag()->remove('container.behavior_describing_tags'); - } - } - - private function processDefinition(ContainerBuilder $container, string $id, Definition $definition, array $tagsToKeep): Definition - { - $instanceofConditionals = $definition->getInstanceofConditionals(); - $autoconfiguredInstanceof = $definition->isAutoconfigured() ? $container->getAutoconfiguredInstanceof() : []; - if (!$instanceofConditionals && !$autoconfiguredInstanceof) { - return $definition; - } - - if (!$class = $container->getParameterBag()->resolveValue($definition->getClass())) { - return $definition; - } - - $conditionals = $this->mergeConditionals($autoconfiguredInstanceof, $instanceofConditionals, $container); - - $definition->setInstanceofConditionals([]); - $shared = null; - $instanceofTags = []; - $instanceofCalls = []; - $instanceofBindings = []; - $reflectionClass = null; - $parent = $definition instanceof ChildDefinition ? $definition->getParent() : null; - - foreach ($conditionals as $interface => $instanceofDefs) { - if ($interface !== $class && !($reflectionClass ?? $reflectionClass = $container->getReflectionClass($class, false) ?: false)) { - continue; - } - - if ($interface !== $class && !is_subclass_of($class, $interface)) { - continue; - } - - foreach ($instanceofDefs as $key => $instanceofDef) { - /** @var ChildDefinition $instanceofDef */ - $instanceofDef = clone $instanceofDef; - $instanceofDef->setAbstract(true)->setParent($parent ?: '.abstract.instanceof.'.$id); - $parent = '.instanceof.'.$interface.'.'.$key.'.'.$id; - $container->setDefinition($parent, $instanceofDef); - $instanceofTags[] = $instanceofDef->getTags(); - $instanceofBindings = $instanceofDef->getBindings() + $instanceofBindings; - - foreach ($instanceofDef->getMethodCalls() as $methodCall) { - $instanceofCalls[] = $methodCall; - } - - $instanceofDef->setTags([]); - $instanceofDef->setMethodCalls([]); - $instanceofDef->setBindings([]); - - if (isset($instanceofDef->getChanges()['shared'])) { - $shared = $instanceofDef->isShared(); - } - } - } - - if ($parent) { - $bindings = $definition->getBindings(); - $abstract = $container->setDefinition('.abstract.instanceof.'.$id, $definition); - $definition->setBindings([]); - $definition = serialize($definition); - - if (Definition::class === \get_class($abstract)) { - // cast Definition to ChildDefinition - $definition = substr_replace($definition, '53', 2, 2); - $definition = substr_replace($definition, 'Child', 44, 0); - } - /** @var ChildDefinition $definition */ - $definition = unserialize($definition); - $definition->setParent($parent); - - if (null !== $shared && !isset($definition->getChanges()['shared'])) { - $definition->setShared($shared); - } - - // Don't add tags to service decorators - $i = \count($instanceofTags); - while (0 <= --$i) { - foreach ($instanceofTags[$i] as $k => $v) { - if (null === $definition->getDecoratedService() || \in_array($k, $tagsToKeep, true)) { - foreach ($v as $v) { - if ($definition->hasTag($k) && \in_array($v, $definition->getTag($k))) { - continue; - } - $definition->addTag($k, $v); - } - } - } - } - - $definition->setMethodCalls(array_merge($instanceofCalls, $definition->getMethodCalls())); - $definition->setBindings($bindings + $instanceofBindings); - - // reset fields with "merge" behavior - $abstract - ->setBindings([]) - ->setArguments([]) - ->setMethodCalls([]) - ->setDecoratedService(null) - ->setTags([]) - ->setAbstract(true); - } - - return $definition; - } - - private function mergeConditionals(array $autoconfiguredInstanceof, array $instanceofConditionals, ContainerBuilder $container): array - { - // make each value an array of ChildDefinition - $conditionals = array_map(function ($childDef) { return [$childDef]; }, $autoconfiguredInstanceof); - - foreach ($instanceofConditionals as $interface => $instanceofDef) { - // make sure the interface/class exists (but don't validate automaticInstanceofConditionals) - if (!$container->getReflectionClass($interface)) { - throw new RuntimeException(sprintf('"%s" is set as an "instanceof" conditional, but it does not exist.', $interface)); - } - - if (!isset($autoconfiguredInstanceof[$interface])) { - $conditionals[$interface] = []; - } - - $conditionals[$interface][] = $instanceofDef; - } - - return $conditionals; - } -} diff --git a/lib/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php b/lib/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php deleted file mode 100644 index 948de421f..000000000 --- a/lib/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php +++ /dev/null @@ -1,136 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\TypedReference; - -/** - * Emulates the invalid behavior if the reference is not found within the - * container. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class ResolveInvalidReferencesPass implements CompilerPassInterface -{ - private $container; - private $signalingException; - private $currentId; - - /** - * Process the ContainerBuilder to resolve invalid references. - */ - public function process(ContainerBuilder $container) - { - $this->container = $container; - $this->signalingException = new RuntimeException('Invalid reference.'); - - try { - foreach ($container->getDefinitions() as $this->currentId => $definition) { - $this->processValue($definition); - } - } finally { - $this->container = $this->signalingException = null; - } - } - - /** - * Processes arguments to determine invalid references. - * - * @return mixed - * - * @throws RuntimeException When an invalid reference is found - */ - private function processValue($value, int $rootLevel = 0, int $level = 0) - { - if ($value instanceof ServiceClosureArgument) { - $value->setValues($this->processValue($value->getValues(), 1, 1)); - } elseif ($value instanceof ArgumentInterface) { - $value->setValues($this->processValue($value->getValues(), $rootLevel, 1 + $level)); - } elseif ($value instanceof Definition) { - if ($value->isSynthetic() || $value->isAbstract()) { - return $value; - } - $value->setArguments($this->processValue($value->getArguments(), 0)); - $value->setProperties($this->processValue($value->getProperties(), 1)); - $value->setMethodCalls($this->processValue($value->getMethodCalls(), 2)); - } elseif (\is_array($value)) { - $i = 0; - - foreach ($value as $k => $v) { - try { - if (false !== $i && $k !== $i++) { - $i = false; - } - if ($v !== $processedValue = $this->processValue($v, $rootLevel, 1 + $level)) { - $value[$k] = $processedValue; - } - } catch (RuntimeException $e) { - if ($rootLevel < $level || ($rootLevel && !$level)) { - unset($value[$k]); - } elseif ($rootLevel) { - throw $e; - } else { - $value[$k] = null; - } - } - } - - // Ensure numerically indexed arguments have sequential numeric keys. - if (false !== $i) { - $value = array_values($value); - } - } elseif ($value instanceof Reference) { - if ($this->container->has($id = (string) $value)) { - return $value; - } - - $currentDefinition = $this->container->getDefinition($this->currentId); - - // resolve decorated service behavior depending on decorator service - if ($currentDefinition->innerServiceId === $id && ContainerInterface::NULL_ON_INVALID_REFERENCE === $currentDefinition->decorationOnInvalid) { - return null; - } - - $invalidBehavior = $value->getInvalidBehavior(); - - if (ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior && $value instanceof TypedReference && !$this->container->has($id)) { - $e = new ServiceNotFoundException($id, $this->currentId); - - // since the error message varies by $id and $this->currentId, so should the id of the dummy errored definition - $this->container->register($id = sprintf('.errored.%s.%s', $this->currentId, $id), $value->getType()) - ->addError($e->getMessage()); - - return new TypedReference($id, $value->getType(), $value->getInvalidBehavior()); - } - - // resolve invalid behavior - if (ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) { - $value = null; - } elseif (ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $invalidBehavior) { - if (0 < $level || $rootLevel) { - throw $this->signalingException; - } - $value = null; - } - } - - return $value; - } -} diff --git a/lib/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php b/lib/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php deleted file mode 100644 index c1c5748e8..000000000 --- a/lib/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php +++ /dev/null @@ -1,127 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\AbstractArgument; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Resolves named arguments to their corresponding numeric index. - * - * @author Kévin Dunglas <dunglas@gmail.com> - */ -class ResolveNamedArgumentsPass extends AbstractRecursivePass -{ - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if ($value instanceof AbstractArgument && $value->getText().'.' === $value->getTextWithContext()) { - $value->setContext(sprintf('A value found in service "%s"', $this->currentId)); - } - - if (!$value instanceof Definition) { - return parent::processValue($value, $isRoot); - } - - $calls = $value->getMethodCalls(); - $calls[] = ['__construct', $value->getArguments()]; - - foreach ($calls as $i => $call) { - [$method, $arguments] = $call; - $parameters = null; - $resolvedArguments = []; - - foreach ($arguments as $key => $argument) { - if ($argument instanceof AbstractArgument && $argument->getText().'.' === $argument->getTextWithContext()) { - $argument->setContext(sprintf('Argument '.(\is_int($key) ? 1 + $key : '"%3$s"').' of '.('__construct' === $method ? 'service "%s"' : 'method call "%s::%s()"'), $this->currentId, $method, $key)); - } - - if (\is_int($key)) { - $resolvedArguments[$key] = $argument; - continue; - } - - if (null === $parameters) { - $r = $this->getReflectionMethod($value, $method); - $class = $r instanceof \ReflectionMethod ? $r->class : $this->currentId; - $method = $r->getName(); - $parameters = $r->getParameters(); - } - - if (isset($key[0]) && '$' !== $key[0] && !class_exists($key) && !interface_exists($key, false)) { - throw new InvalidArgumentException(sprintf('Invalid service "%s": did you forget to add the "$" prefix to argument "%s"?', $this->currentId, $key)); - } - - if (isset($key[0]) && '$' === $key[0]) { - foreach ($parameters as $j => $p) { - if ($key === '$'.$p->name) { - if ($p->isVariadic() && \is_array($argument)) { - foreach ($argument as $variadicArgument) { - $resolvedArguments[$j++] = $variadicArgument; - } - } else { - $resolvedArguments[$j] = $argument; - } - - continue 2; - } - } - - throw new InvalidArgumentException(sprintf('Invalid service "%s": method "%s()" has no argument named "%s". Check your service definition.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method, $key)); - } - - if (null !== $argument && !$argument instanceof Reference && !$argument instanceof Definition) { - throw new InvalidArgumentException(sprintf('Invalid service "%s": the value of argument "%s" of method "%s()" must be null, an instance of "%s" or an instance of "%s", "%s" given.', $this->currentId, $key, $class !== $this->currentId ? $class.'::'.$method : $method, Reference::class, Definition::class, get_debug_type($argument))); - } - - $typeFound = false; - foreach ($parameters as $j => $p) { - if (!\array_key_exists($j, $resolvedArguments) && ProxyHelper::getTypeHint($r, $p, true) === $key) { - $resolvedArguments[$j] = $argument; - $typeFound = true; - } - } - - if (!$typeFound) { - throw new InvalidArgumentException(sprintf('Invalid service "%s": method "%s()" has no argument type-hinted as "%s". Check your service definition.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method, $key)); - } - } - - if ($resolvedArguments !== $call[1]) { - ksort($resolvedArguments); - $calls[$i][1] = $resolvedArguments; - } - } - - [, $arguments] = array_pop($calls); - - if ($arguments !== $value->getArguments()) { - $value->setArguments($arguments); - } - if ($calls !== $value->getMethodCalls()) { - $value->setMethodCalls($calls); - } - - foreach ($value->getProperties() as $key => $argument) { - if ($argument instanceof AbstractArgument && $argument->getText().'.' === $argument->getTextWithContext()) { - $argument->setContext(sprintf('Property "%s" of service "%s"', $key, $this->currentId)); - } - } - - return parent::processValue($value, $isRoot); - } -} diff --git a/lib/symfony/dependency-injection/Compiler/ResolveNoPreloadPass.php b/lib/symfony/dependency-injection/Compiler/ResolveNoPreloadPass.php deleted file mode 100644 index 016be55b3..000000000 --- a/lib/symfony/dependency-injection/Compiler/ResolveNoPreloadPass.php +++ /dev/null @@ -1,104 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Propagate the "container.no_preload" tag. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class ResolveNoPreloadPass extends AbstractRecursivePass -{ - private const DO_PRELOAD_TAG = '.container.do_preload'; - - private $tagName; - private $resolvedIds = []; - - public function __construct(string $tagName = 'container.no_preload') - { - if (0 < \func_num_args()) { - trigger_deprecation('symfony/dependency-injection', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->tagName = $tagName; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - $this->container = $container; - - try { - foreach ($container->getDefinitions() as $id => $definition) { - if ($definition->isPublic() && !$definition->isPrivate() && !isset($this->resolvedIds[$id])) { - $this->resolvedIds[$id] = true; - $this->processValue($definition, true); - } - } - - foreach ($container->getAliases() as $alias) { - if ($alias->isPublic() && !$alias->isPrivate() && !isset($this->resolvedIds[$id = (string) $alias]) && $container->hasDefinition($id)) { - $this->resolvedIds[$id] = true; - $this->processValue($container->getDefinition($id), true); - } - } - } finally { - $this->resolvedIds = []; - $this->container = null; - } - - foreach ($container->getDefinitions() as $definition) { - if ($definition->hasTag(self::DO_PRELOAD_TAG)) { - $definition->clearTag(self::DO_PRELOAD_TAG); - } elseif (!$definition->isDeprecated() && !$definition->hasErrors()) { - $definition->addTag($this->tagName); - } - } - } - - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if ($value instanceof Reference && ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE !== $value->getInvalidBehavior() && $this->container->hasDefinition($id = (string) $value)) { - $definition = $this->container->getDefinition($id); - - if (!isset($this->resolvedIds[$id]) && (!$definition->isPublic() || $definition->isPrivate())) { - $this->resolvedIds[$id] = true; - $this->processValue($definition, true); - } - - return $value; - } - - if (!$value instanceof Definition) { - return parent::processValue($value, $isRoot); - } - - if ($value->hasTag($this->tagName) || $value->isDeprecated() || $value->hasErrors()) { - return $value; - } - - if ($isRoot) { - $value->addTag(self::DO_PRELOAD_TAG); - } - - return parent::processValue($value, $isRoot); - } -} diff --git a/lib/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php b/lib/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php deleted file mode 100644 index 0099a3bbc..000000000 --- a/lib/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php +++ /dev/null @@ -1,103 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; - -/** - * Resolves all parameter placeholders "%somevalue%" to their real values. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class ResolveParameterPlaceHoldersPass extends AbstractRecursivePass -{ - private $bag; - private $resolveArrays; - private $throwOnResolveException; - - public function __construct($resolveArrays = true, $throwOnResolveException = true) - { - $this->resolveArrays = $resolveArrays; - $this->throwOnResolveException = $throwOnResolveException; - } - - /** - * {@inheritdoc} - * - * @throws ParameterNotFoundException - */ - public function process(ContainerBuilder $container) - { - $this->bag = $container->getParameterBag(); - - try { - parent::process($container); - - $aliases = []; - foreach ($container->getAliases() as $name => $target) { - $this->currentId = $name; - $aliases[$this->bag->resolveValue($name)] = $target; - } - $container->setAliases($aliases); - } catch (ParameterNotFoundException $e) { - $e->setSourceId($this->currentId); - - throw $e; - } - - $this->bag->resolve(); - $this->bag = null; - } - - protected function processValue($value, bool $isRoot = false) - { - if (\is_string($value)) { - try { - $v = $this->bag->resolveValue($value); - } catch (ParameterNotFoundException $e) { - if ($this->throwOnResolveException) { - throw $e; - } - - $v = null; - $this->container->getDefinition($this->currentId)->addError($e->getMessage()); - } - - return $this->resolveArrays || !$v || !\is_array($v) ? $v : $value; - } - if ($value instanceof Definition) { - $value->setBindings($this->processValue($value->getBindings())); - $changes = $value->getChanges(); - if (isset($changes['class'])) { - $value->setClass($this->bag->resolveValue($value->getClass())); - } - if (isset($changes['file'])) { - $value->setFile($this->bag->resolveValue($value->getFile())); - } - $tags = $value->getTags(); - if (isset($tags['proxy'])) { - $tags['proxy'] = $this->bag->resolveValue($tags['proxy']); - $value->setTags($tags); - } - } - - $value = parent::processValue($value, $isRoot); - - if ($value && \is_array($value)) { - $value = array_combine($this->bag->resolveValue(array_keys($value)), $value); - } - - return $value; - } -} diff --git a/lib/symfony/dependency-injection/Compiler/ResolvePrivatesPass.php b/lib/symfony/dependency-injection/Compiler/ResolvePrivatesPass.php deleted file mode 100644 index b63e3f5c2..000000000 --- a/lib/symfony/dependency-injection/Compiler/ResolvePrivatesPass.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -trigger_deprecation('symfony/dependency-injection', '5.2', 'The "%s" class is deprecated.', ResolvePrivatesPass::class); - -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @deprecated since Symfony 5.2 - */ -class ResolvePrivatesPass implements CompilerPassInterface -{ - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - foreach ($container->getDefinitions() as $id => $definition) { - if ($definition->isPrivate()) { - $definition->setPublic(false); - $definition->setPrivate(true); - } - } - - foreach ($container->getAliases() as $id => $alias) { - if ($alias->isPrivate()) { - $alias->setPublic(false); - $alias->setPrivate(true); - } - } - } -} diff --git a/lib/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php b/lib/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php deleted file mode 100644 index e59893ff7..000000000 --- a/lib/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Replaces all references to aliases with references to the actual service. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class ResolveReferencesToAliasesPass extends AbstractRecursivePass -{ - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - parent::process($container); - - foreach ($container->getAliases() as $id => $alias) { - $aliasId = (string) $alias; - $this->currentId = $id; - - if ($aliasId !== $defId = $this->getDefinitionId($aliasId, $container)) { - $container->setAlias($id, $defId)->setPublic($alias->isPublic()); - } - } - } - - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if (!$value instanceof Reference) { - return parent::processValue($value, $isRoot); - } - - $defId = $this->getDefinitionId($id = (string) $value, $this->container); - - return $defId !== $id ? new Reference($defId, $value->getInvalidBehavior()) : $value; - } - - private function getDefinitionId(string $id, ContainerBuilder $container): string - { - if (!$container->hasAlias($id)) { - return $id; - } - - $alias = $container->getAlias($id); - - if ($alias->isDeprecated()) { - $referencingDefinition = $container->hasDefinition($this->currentId) ? $container->getDefinition($this->currentId) : $container->getAlias($this->currentId); - if (!$referencingDefinition->isDeprecated()) { - $deprecation = $alias->getDeprecation($id); - trigger_deprecation($deprecation['package'], $deprecation['version'], rtrim($deprecation['message'], '. ').'. It is being referenced by the "%s" '.($container->hasDefinition($this->currentId) ? 'service.' : 'alias.'), $this->currentId); - } - } - - $seen = []; - do { - if (isset($seen[$id])) { - throw new ServiceCircularReferenceException($id, array_merge(array_keys($seen), [$id])); - } - - $seen[$id] = true; - $id = (string) $container->getAlias($id); - } while ($container->hasAlias($id)); - - return $id; - } -} diff --git a/lib/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php b/lib/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php deleted file mode 100644 index 518c03d7e..000000000 --- a/lib/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Psr\Container\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Contracts\Service\ServiceProviderInterface; - -/** - * Compiler pass to inject their service locator to service subscribers. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class ResolveServiceSubscribersPass extends AbstractRecursivePass -{ - private $serviceLocator; - - protected function processValue($value, bool $isRoot = false) - { - if ($value instanceof Reference && $this->serviceLocator && \in_array((string) $value, [ContainerInterface::class, ServiceProviderInterface::class], true)) { - return new Reference($this->serviceLocator); - } - - if (!$value instanceof Definition) { - return parent::processValue($value, $isRoot); - } - - $serviceLocator = $this->serviceLocator; - $this->serviceLocator = null; - - if ($value->hasTag('container.service_subscriber.locator')) { - $this->serviceLocator = $value->getTag('container.service_subscriber.locator')[0]['id']; - $value->clearTag('container.service_subscriber.locator'); - } - - try { - return parent::processValue($value); - } finally { - $this->serviceLocator = $serviceLocator; - } - } -} diff --git a/lib/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php b/lib/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php deleted file mode 100644 index 48a034a84..000000000 --- a/lib/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; - -/** - * Resolves all TaggedIteratorArgument arguments. - * - * @author Roland Franssen <franssen.roland@gmail.com> - */ -class ResolveTaggedIteratorArgumentPass extends AbstractRecursivePass -{ - use PriorityTaggedServiceTrait; - - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if (!$value instanceof TaggedIteratorArgument) { - return parent::processValue($value, $isRoot); - } - - $value->setValues($this->findAndSortTaggedServices($value, $this->container)); - - return $value; - } -} diff --git a/lib/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php b/lib/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php deleted file mode 100644 index faa7b57e4..000000000 --- a/lib/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php +++ /dev/null @@ -1,138 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\ServiceLocator; - -/** - * Applies the "container.service_locator" tag by wrapping references into ServiceClosureArgument instances. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -final class ServiceLocatorTagPass extends AbstractRecursivePass -{ - use PriorityTaggedServiceTrait; - - protected function processValue($value, bool $isRoot = false) - { - if ($value instanceof ServiceLocatorArgument) { - if ($value->getTaggedIteratorArgument()) { - $value->setValues($this->findAndSortTaggedServices($value->getTaggedIteratorArgument(), $this->container)); - } - - return self::register($this->container, $value->getValues()); - } - - if (!$value instanceof Definition || !$value->hasTag('container.service_locator')) { - return parent::processValue($value, $isRoot); - } - - if (!$value->getClass()) { - $value->setClass(ServiceLocator::class); - } - - $services = $value->getArguments()[0] ?? null; - - if ($services instanceof TaggedIteratorArgument) { - $services = $this->findAndSortTaggedServices($services, $this->container); - } - - if (!\is_array($services)) { - throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": an array of references is expected as first argument when the "container.service_locator" tag is set.', $this->currentId)); - } - - $i = 0; - - foreach ($services as $k => $v) { - if ($v instanceof ServiceClosureArgument) { - continue; - } - if (!$v instanceof Reference) { - throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": an array of references is expected as first argument when the "container.service_locator" tag is set, "%s" found for key "%s".', $this->currentId, get_debug_type($v), $k)); - } - - if ($i === $k) { - unset($services[$k]); - - $k = (string) $v; - ++$i; - } elseif (\is_int($k)) { - $i = null; - } - $services[$k] = new ServiceClosureArgument($v); - } - ksort($services); - - $value->setArgument(0, $services); - - $id = '.service_locator.'.ContainerBuilder::hash($value); - - if ($isRoot) { - if ($id !== $this->currentId) { - $this->container->setAlias($id, new Alias($this->currentId, false)); - } - - return $value; - } - - $this->container->setDefinition($id, $value->setPublic(false)); - - return new Reference($id); - } - - /** - * @param Reference[] $refMap - */ - public static function register(ContainerBuilder $container, array $refMap, string $callerId = null): Reference - { - foreach ($refMap as $id => $ref) { - if (!$ref instanceof Reference) { - throw new InvalidArgumentException(sprintf('Invalid service locator definition: only services can be referenced, "%s" found for key "%s". Inject parameter values using constructors instead.', get_debug_type($ref), $id)); - } - $refMap[$id] = new ServiceClosureArgument($ref); - } - - $locator = (new Definition(ServiceLocator::class)) - ->addArgument($refMap) - ->addTag('container.service_locator'); - - if (null !== $callerId && $container->hasDefinition($callerId)) { - $locator->setBindings($container->getDefinition($callerId)->getBindings()); - } - - if (!$container->hasDefinition($id = '.service_locator.'.ContainerBuilder::hash($locator))) { - $container->setDefinition($id, $locator); - } - - if (null !== $callerId) { - $locatorId = $id; - // Locators are shared when they hold the exact same list of factories; - // to have them specialized per consumer service, we use a cloning factory - // to derivate customized instances from the prototype one. - $container->register($id .= '.'.$callerId, ServiceLocator::class) - ->setFactory([new Reference($locatorId), 'withContext']) - ->addTag('container.service_locator_context', ['id' => $callerId]) - ->addArgument($callerId) - ->addArgument(new Reference('service_container')); - } - - return new Reference($id); - } -} diff --git a/lib/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php b/lib/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php deleted file mode 100644 index 1225514c2..000000000 --- a/lib/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php +++ /dev/null @@ -1,99 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * This is a directed graph of your services. - * - * This information can be used by your compiler passes instead of collecting - * it themselves which improves performance quite a lot. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - * - * @final - */ -class ServiceReferenceGraph -{ - /** - * @var ServiceReferenceGraphNode[] - */ - private $nodes = []; - - public function hasNode(string $id): bool - { - return isset($this->nodes[$id]); - } - - /** - * Gets a node by identifier. - * - * @throws InvalidArgumentException if no node matches the supplied identifier - */ - public function getNode(string $id): ServiceReferenceGraphNode - { - if (!isset($this->nodes[$id])) { - throw new InvalidArgumentException(sprintf('There is no node with id "%s".', $id)); - } - - return $this->nodes[$id]; - } - - /** - * Returns all nodes. - * - * @return ServiceReferenceGraphNode[] - */ - public function getNodes(): array - { - return $this->nodes; - } - - /** - * Clears all nodes. - */ - public function clear() - { - foreach ($this->nodes as $node) { - $node->clear(); - } - $this->nodes = []; - } - - /** - * Connects 2 nodes together in the Graph. - */ - public function connect(?string $sourceId, $sourceValue, ?string $destId, $destValue = null, Reference $reference = null, bool $lazy = false, bool $weak = false, bool $byConstructor = false) - { - if (null === $sourceId || null === $destId) { - return; - } - - $sourceNode = $this->createNode($sourceId, $sourceValue); - $destNode = $this->createNode($destId, $destValue); - $edge = new ServiceReferenceGraphEdge($sourceNode, $destNode, $reference, $lazy, $weak, $byConstructor); - - $sourceNode->addOutEdge($edge); - $destNode->addInEdge($edge); - } - - private function createNode(string $id, $value): ServiceReferenceGraphNode - { - if (isset($this->nodes[$id]) && $this->nodes[$id]->getValue() === $value) { - return $this->nodes[$id]; - } - - return $this->nodes[$id] = new ServiceReferenceGraphNode($id, $value); - } -} diff --git a/lib/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php b/lib/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php deleted file mode 100644 index 986145606..000000000 --- a/lib/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php +++ /dev/null @@ -1,99 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -/** - * Represents an edge in your service graph. - * - * Value is typically a reference. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class ServiceReferenceGraphEdge -{ - private $sourceNode; - private $destNode; - private $value; - private $lazy; - private $weak; - private $byConstructor; - - public function __construct(ServiceReferenceGraphNode $sourceNode, ServiceReferenceGraphNode $destNode, $value = null, bool $lazy = false, bool $weak = false, bool $byConstructor = false) - { - $this->sourceNode = $sourceNode; - $this->destNode = $destNode; - $this->value = $value; - $this->lazy = $lazy; - $this->weak = $weak; - $this->byConstructor = $byConstructor; - } - - /** - * Returns the value of the edge. - * - * @return mixed - */ - public function getValue() - { - return $this->value; - } - - /** - * Returns the source node. - * - * @return ServiceReferenceGraphNode - */ - public function getSourceNode() - { - return $this->sourceNode; - } - - /** - * Returns the destination node. - * - * @return ServiceReferenceGraphNode - */ - public function getDestNode() - { - return $this->destNode; - } - - /** - * Returns true if the edge is lazy, meaning it's a dependency not requiring direct instantiation. - * - * @return bool - */ - public function isLazy() - { - return $this->lazy; - } - - /** - * Returns true if the edge is weak, meaning it shouldn't prevent removing the target service. - * - * @return bool - */ - public function isWeak() - { - return $this->weak; - } - - /** - * Returns true if the edge links with a constructor argument. - * - * @return bool - */ - public function isReferencedByConstructor() - { - return $this->byConstructor; - } -} diff --git a/lib/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php b/lib/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php deleted file mode 100644 index ba96da233..000000000 --- a/lib/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php +++ /dev/null @@ -1,118 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Definition; - -/** - * Represents a node in your service graph. - * - * Value is typically a definition, or an alias. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class ServiceReferenceGraphNode -{ - private $id; - private $inEdges = []; - private $outEdges = []; - private $value; - - /** - * @param string $id The node identifier - * @param mixed $value The node value - */ - public function __construct(string $id, $value) - { - $this->id = $id; - $this->value = $value; - } - - public function addInEdge(ServiceReferenceGraphEdge $edge) - { - $this->inEdges[] = $edge; - } - - public function addOutEdge(ServiceReferenceGraphEdge $edge) - { - $this->outEdges[] = $edge; - } - - /** - * Checks if the value of this node is an Alias. - * - * @return bool - */ - public function isAlias() - { - return $this->value instanceof Alias; - } - - /** - * Checks if the value of this node is a Definition. - * - * @return bool - */ - public function isDefinition() - { - return $this->value instanceof Definition; - } - - /** - * Returns the identifier. - * - * @return string - */ - public function getId() - { - return $this->id; - } - - /** - * Returns the in edges. - * - * @return ServiceReferenceGraphEdge[] - */ - public function getInEdges() - { - return $this->inEdges; - } - - /** - * Returns the out edges. - * - * @return ServiceReferenceGraphEdge[] - */ - public function getOutEdges() - { - return $this->outEdges; - } - - /** - * Returns the value of this Node. - * - * @return mixed - */ - public function getValue() - { - return $this->value; - } - - /** - * Clears all edges. - */ - public function clear() - { - $this->inEdges = $this->outEdges = []; - } -} diff --git a/lib/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php b/lib/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php deleted file mode 100644 index 23bfe59b0..000000000 --- a/lib/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php +++ /dev/null @@ -1,103 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\Config\Definition\BaseNode; -use Symfony\Component\Config\Definition\ConfigurationInterface; -use Symfony\Component\Config\Definition\Processor; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface; -use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; - -/** - * Validates environment variable placeholders used in extension configuration with dummy values. - * - * @author Roland Franssen <franssen.roland@gmail.com> - */ -class ValidateEnvPlaceholdersPass implements CompilerPassInterface -{ - private const TYPE_FIXTURES = ['array' => [], 'bool' => false, 'float' => 0.0, 'int' => 0, 'string' => '']; - - private $extensionConfig = []; - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - $this->extensionConfig = []; - - if (!class_exists(BaseNode::class) || !$extensions = $container->getExtensions()) { - return; - } - - $resolvingBag = $container->getParameterBag(); - if (!$resolvingBag instanceof EnvPlaceholderParameterBag) { - return; - } - - $defaultBag = new ParameterBag($resolvingBag->all()); - $envTypes = $resolvingBag->getProvidedTypes(); - foreach ($resolvingBag->getEnvPlaceholders() + $resolvingBag->getUnusedEnvPlaceholders() as $env => $placeholders) { - $values = []; - if (false === $i = strpos($env, ':')) { - $default = $defaultBag->has("env($env)") ? $defaultBag->get("env($env)") : self::TYPE_FIXTURES['string']; - $defaultType = null !== $default ? get_debug_type($default) : 'string'; - $values[$defaultType] = $default; - } else { - $prefix = substr($env, 0, $i); - foreach ($envTypes[$prefix] ?? ['string'] as $type) { - $values[$type] = self::TYPE_FIXTURES[$type] ?? null; - } - } - foreach ($placeholders as $placeholder) { - BaseNode::setPlaceholder($placeholder, $values); - } - } - - $processor = new Processor(); - - foreach ($extensions as $name => $extension) { - if (!($extension instanceof ConfigurationExtensionInterface || $extension instanceof ConfigurationInterface) - || !$config = array_filter($container->getExtensionConfig($name)) - ) { - // this extension has no semantic configuration or was not called - continue; - } - - $config = $resolvingBag->resolveValue($config); - - if ($extension instanceof ConfigurationInterface) { - $configuration = $extension; - } elseif (null === $configuration = $extension->getConfiguration($config, $container)) { - continue; - } - - $this->extensionConfig[$name] = $processor->processConfiguration($configuration, $config); - } - - $resolvingBag->clearUnusedEnvPlaceholders(); - } - - /** - * @internal - */ - public function getExtensionConfig(): array - { - try { - return $this->extensionConfig; - } finally { - $this->extensionConfig = []; - } - } -} diff --git a/lib/symfony/dependency-injection/Config/ContainerParametersResource.php b/lib/symfony/dependency-injection/Config/ContainerParametersResource.php deleted file mode 100644 index c10398bcb..000000000 --- a/lib/symfony/dependency-injection/Config/ContainerParametersResource.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Config; - -use Symfony\Component\Config\Resource\ResourceInterface; - -/** - * Tracks container parameters. - * - * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> - * - * @final - */ -class ContainerParametersResource implements ResourceInterface -{ - private $parameters; - - /** - * @param array $parameters The container parameters to track - */ - public function __construct(array $parameters) - { - $this->parameters = $parameters; - } - - public function __toString(): string - { - return 'container_parameters_'.md5(serialize($this->parameters)); - } - - public function getParameters(): array - { - return $this->parameters; - } -} diff --git a/lib/symfony/dependency-injection/Config/ContainerParametersResourceChecker.php b/lib/symfony/dependency-injection/Config/ContainerParametersResourceChecker.php deleted file mode 100644 index 2f2affaa5..000000000 --- a/lib/symfony/dependency-injection/Config/ContainerParametersResourceChecker.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Config; - -use Symfony\Component\Config\Resource\ResourceInterface; -use Symfony\Component\Config\ResourceCheckerInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> - */ -class ContainerParametersResourceChecker implements ResourceCheckerInterface -{ - /** @var ContainerInterface */ - private $container; - - public function __construct(ContainerInterface $container) - { - $this->container = $container; - } - - /** - * {@inheritdoc} - */ - public function supports(ResourceInterface $metadata) - { - return $metadata instanceof ContainerParametersResource; - } - - /** - * {@inheritdoc} - */ - public function isFresh(ResourceInterface $resource, int $timestamp) - { - foreach ($resource->getParameters() as $key => $value) { - if (!$this->container->hasParameter($key) || $this->container->getParameter($key) !== $value) { - return false; - } - } - - return true; - } -} diff --git a/lib/symfony/dependency-injection/Container.php b/lib/symfony/dependency-injection/Container.php deleted file mode 100644 index 6f61eb869..000000000 --- a/lib/symfony/dependency-injection/Container.php +++ /dev/null @@ -1,434 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -use Symfony\Component\DependencyInjection\Argument\RewindableGenerator; -use Symfony\Component\DependencyInjection\Argument\ServiceLocator as ArgumentServiceLocator; -use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; -use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; -use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; -use Symfony\Contracts\Service\ResetInterface; - -// Help opcache.preload discover always-needed symbols -class_exists(RewindableGenerator::class); -class_exists(ArgumentServiceLocator::class); - -/** - * Container is a dependency injection container. - * - * It gives access to object instances (services). - * Services and parameters are simple key/pair stores. - * The container can have four possible behaviors when a service - * does not exist (or is not initialized for the last case): - * - * * EXCEPTION_ON_INVALID_REFERENCE: Throws an exception (the default) - * * NULL_ON_INVALID_REFERENCE: Returns null - * * IGNORE_ON_INVALID_REFERENCE: Ignores the wrapping command asking for the reference - * (for instance, ignore a setter if the service does not exist) - * * IGNORE_ON_UNINITIALIZED_REFERENCE: Ignores/returns null for uninitialized services or invalid references - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class Container implements ContainerInterface, ResetInterface -{ - protected $parameterBag; - protected $services = []; - protected $privates = []; - protected $fileMap = []; - protected $methodMap = []; - protected $factories = []; - protected $aliases = []; - protected $loading = []; - protected $resolving = []; - protected $syntheticIds = []; - - private $envCache = []; - private $compiled = false; - private $getEnv; - - public function __construct(ParameterBagInterface $parameterBag = null) - { - $this->parameterBag = $parameterBag ?? new EnvPlaceholderParameterBag(); - } - - /** - * Compiles the container. - * - * This method does two things: - * - * * Parameter values are resolved; - * * The parameter bag is frozen. - */ - public function compile() - { - $this->parameterBag->resolve(); - - $this->parameterBag = new FrozenParameterBag($this->parameterBag->all()); - - $this->compiled = true; - } - - /** - * Returns true if the container is compiled. - * - * @return bool - */ - public function isCompiled() - { - return $this->compiled; - } - - /** - * Gets the service container parameter bag. - * - * @return ParameterBagInterface - */ - public function getParameterBag() - { - return $this->parameterBag; - } - - /** - * Gets a parameter. - * - * @return array|bool|string|int|float|\UnitEnum|null - * - * @throws InvalidArgumentException if the parameter is not defined - */ - public function getParameter(string $name) - { - return $this->parameterBag->get($name); - } - - /** - * @return bool - */ - public function hasParameter(string $name) - { - return $this->parameterBag->has($name); - } - - /** - * Sets a parameter. - * - * @param string $name The parameter name - * @param array|bool|string|int|float|\UnitEnum|null $value The parameter value - */ - public function setParameter(string $name, $value) - { - $this->parameterBag->set($name, $value); - } - - /** - * Sets a service. - * - * Setting a synthetic service to null resets it: has() returns false and get() - * behaves in the same way as if the service was never created. - */ - public function set(string $id, ?object $service) - { - // Runs the internal initializer; used by the dumped container to include always-needed files - if (isset($this->privates['service_container']) && $this->privates['service_container'] instanceof \Closure) { - $initialize = $this->privates['service_container']; - unset($this->privates['service_container']); - $initialize(); - } - - if ('service_container' === $id) { - throw new InvalidArgumentException('You cannot set service "service_container".'); - } - - if (!(isset($this->fileMap[$id]) || isset($this->methodMap[$id]))) { - if (isset($this->syntheticIds[$id]) || !isset($this->getRemovedIds()[$id])) { - // no-op - } elseif (null === $service) { - throw new InvalidArgumentException(sprintf('The "%s" service is private, you cannot unset it.', $id)); - } else { - throw new InvalidArgumentException(sprintf('The "%s" service is private, you cannot replace it.', $id)); - } - } elseif (isset($this->services[$id])) { - throw new InvalidArgumentException(sprintf('The "%s" service is already initialized, you cannot replace it.', $id)); - } - - if (isset($this->aliases[$id])) { - unset($this->aliases[$id]); - } - - if (null === $service) { - unset($this->services[$id]); - - return; - } - - $this->services[$id] = $service; - } - - /** - * Returns true if the given service is defined. - * - * @param string $id The service identifier - * - * @return bool - */ - public function has(string $id) - { - if (isset($this->aliases[$id])) { - $id = $this->aliases[$id]; - } - if (isset($this->services[$id])) { - return true; - } - if ('service_container' === $id) { - return true; - } - - return isset($this->fileMap[$id]) || isset($this->methodMap[$id]); - } - - /** - * Gets a service. - * - * @return object|null - * - * @throws ServiceCircularReferenceException When a circular reference is detected - * @throws ServiceNotFoundException When the service is not defined - * @throws \Exception if an exception has been thrown when the service has been resolved - * - * @see Reference - */ - public function get(string $id, int $invalidBehavior = /* self::EXCEPTION_ON_INVALID_REFERENCE */ 1) - { - return $this->services[$id] - ?? $this->services[$id = $this->aliases[$id] ?? $id] - ?? ('service_container' === $id ? $this : ($this->factories[$id] ?? [$this, 'make'])($id, $invalidBehavior)); - } - - /** - * Creates a service. - * - * As a separate method to allow "get()" to use the really fast `??` operator. - */ - private function make(string $id, int $invalidBehavior) - { - if (isset($this->loading[$id])) { - throw new ServiceCircularReferenceException($id, array_merge(array_keys($this->loading), [$id])); - } - - $this->loading[$id] = true; - - try { - if (isset($this->fileMap[$id])) { - return /* self::IGNORE_ON_UNINITIALIZED_REFERENCE */ 4 === $invalidBehavior ? null : $this->load($this->fileMap[$id]); - } elseif (isset($this->methodMap[$id])) { - return /* self::IGNORE_ON_UNINITIALIZED_REFERENCE */ 4 === $invalidBehavior ? null : $this->{$this->methodMap[$id]}(); - } - } catch (\Exception $e) { - unset($this->services[$id]); - - throw $e; - } finally { - unset($this->loading[$id]); - } - - if (/* self::EXCEPTION_ON_INVALID_REFERENCE */ 1 === $invalidBehavior) { - if (!$id) { - throw new ServiceNotFoundException($id); - } - if (isset($this->syntheticIds[$id])) { - throw new ServiceNotFoundException($id, null, null, [], sprintf('The "%s" service is synthetic, it needs to be set at boot time before it can be used.', $id)); - } - if (isset($this->getRemovedIds()[$id])) { - throw new ServiceNotFoundException($id, null, null, [], sprintf('The "%s" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.', $id)); - } - - $alternatives = []; - foreach ($this->getServiceIds() as $knownId) { - if ('' === $knownId || '.' === $knownId[0]) { - continue; - } - $lev = levenshtein($id, $knownId); - if ($lev <= \strlen($id) / 3 || str_contains($knownId, $id)) { - $alternatives[] = $knownId; - } - } - - throw new ServiceNotFoundException($id, null, null, $alternatives); - } - - return null; - } - - /** - * Returns true if the given service has actually been initialized. - * - * @return bool - */ - public function initialized(string $id) - { - if (isset($this->aliases[$id])) { - $id = $this->aliases[$id]; - } - - if ('service_container' === $id) { - return false; - } - - return isset($this->services[$id]); - } - - /** - * {@inheritdoc} - */ - public function reset() - { - $services = $this->services + $this->privates; - $this->services = $this->factories = $this->privates = []; - - foreach ($services as $service) { - try { - if ($service instanceof ResetInterface) { - $service->reset(); - } - } catch (\Throwable $e) { - continue; - } - } - } - - /** - * Gets all service ids. - * - * @return string[] - */ - public function getServiceIds() - { - return array_map('strval', array_unique(array_merge(['service_container'], array_keys($this->fileMap), array_keys($this->methodMap), array_keys($this->aliases), array_keys($this->services)))); - } - - /** - * Gets service ids that existed at compile time. - * - * @return array - */ - public function getRemovedIds() - { - return []; - } - - /** - * Camelizes a string. - * - * @return string - */ - public static function camelize(string $id) - { - return strtr(ucwords(strtr($id, ['_' => ' ', '.' => '_ ', '\\' => '_ '])), [' ' => '']); - } - - /** - * A string to underscore. - * - * @return string - */ - public static function underscore(string $id) - { - return strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], ['\\1_\\2', '\\1_\\2'], str_replace('_', '.', $id))); - } - - /** - * Creates a service by requiring its factory file. - */ - protected function load(string $file) - { - return require $file; - } - - /** - * Fetches a variable from the environment. - * - * @return mixed - * - * @throws EnvNotFoundException When the environment variable is not found and has no default value - */ - protected function getEnv(string $name) - { - if (isset($this->resolving[$envName = "env($name)"])) { - throw new ParameterCircularReferenceException(array_keys($this->resolving)); - } - if (isset($this->envCache[$name]) || \array_key_exists($name, $this->envCache)) { - return $this->envCache[$name]; - } - if (!$this->has($id = 'container.env_var_processors_locator')) { - $this->set($id, new ServiceLocator([])); - } - if (!$this->getEnv) { - $this->getEnv = \Closure::fromCallable([$this, 'getEnv']); - } - $processors = $this->get($id); - - if (false !== $i = strpos($name, ':')) { - $prefix = substr($name, 0, $i); - $localName = substr($name, 1 + $i); - } else { - $prefix = 'string'; - $localName = $name; - } - $processor = $processors->has($prefix) ? $processors->get($prefix) : new EnvVarProcessor($this); - - $this->resolving[$envName] = true; - try { - return $this->envCache[$name] = $processor->getEnv($prefix, $localName, $this->getEnv); - } finally { - unset($this->resolving[$envName]); - } - } - - /** - * @param string|false $registry - * @param string|bool $load - * - * @return mixed - * - * @internal - */ - final protected function getService($registry, string $id, ?string $method, $load) - { - if ('service_container' === $id) { - return $this; - } - if (\is_string($load)) { - throw new RuntimeException($load); - } - if (null === $method) { - return false !== $registry ? $this->{$registry}[$id] ?? null : null; - } - if (false !== $registry) { - return $this->{$registry}[$id] ?? $this->{$registry}[$id] = $load ? $this->load($method) : $this->{$method}(); - } - if (!$load) { - return $this->{$method}(); - } - - return ($factory = $this->factories[$id] ?? $this->factories['service_container'][$id] ?? null) ? $factory() : $this->load($method); - } - - private function __clone() - { - } -} diff --git a/lib/symfony/dependency-injection/ContainerAwareInterface.php b/lib/symfony/dependency-injection/ContainerAwareInterface.php deleted file mode 100644 index e7b9d575e..000000000 --- a/lib/symfony/dependency-injection/ContainerAwareInterface.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -/** - * ContainerAwareInterface should be implemented by classes that depends on a Container. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface ContainerAwareInterface -{ - /** - * Sets the container. - */ - public function setContainer(ContainerInterface $container = null); -} diff --git a/lib/symfony/dependency-injection/ContainerAwareTrait.php b/lib/symfony/dependency-injection/ContainerAwareTrait.php deleted file mode 100644 index ee1ea2cb3..000000000 --- a/lib/symfony/dependency-injection/ContainerAwareTrait.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -/** - * ContainerAware trait. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -trait ContainerAwareTrait -{ - /** - * @var ContainerInterface - */ - protected $container; - - public function setContainer(ContainerInterface $container = null) - { - $this->container = $container; - } -} diff --git a/lib/symfony/dependency-injection/ContainerBuilder.php b/lib/symfony/dependency-injection/ContainerBuilder.php deleted file mode 100644 index 485630a74..000000000 --- a/lib/symfony/dependency-injection/ContainerBuilder.php +++ /dev/null @@ -1,1702 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -use Composer\InstalledVersions; -use Psr\Container\ContainerInterface as PsrContainerInterface; -use Symfony\Component\Config\Resource\ClassExistenceResource; -use Symfony\Component\Config\Resource\ComposerResource; -use Symfony\Component\Config\Resource\DirectoryResource; -use Symfony\Component\Config\Resource\FileExistenceResource; -use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\Config\Resource\GlobResource; -use Symfony\Component\Config\Resource\ReflectionClassResource; -use Symfony\Component\Config\Resource\ResourceInterface; -use Symfony\Component\DependencyInjection\Argument\AbstractArgument; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Argument\RewindableGenerator; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceLocator; -use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\Attribute\Target; -use Symfony\Component\DependencyInjection\Compiler\Compiler; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Compiler\PassConfig; -use Symfony\Component\DependencyInjection\Compiler\ResolveEnvPlaceholdersPass; -use Symfony\Component\DependencyInjection\Exception\BadMethodCallException; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\LogicException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; -use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; -use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface; -use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator; -use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; -use Symfony\Component\ExpressionLanguage\Expression; -use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; - -/** - * ContainerBuilder is a DI container that provides an API to easily describe services. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class ContainerBuilder extends Container implements TaggedContainerInterface -{ - /** - * @var array<string, ExtensionInterface> - */ - private $extensions = []; - - /** - * @var array<string, ExtensionInterface> - */ - private $extensionsByNs = []; - - /** - * @var array<string, Definition> - */ - private $definitions = []; - - /** - * @var array<string, Alias> - */ - private $aliasDefinitions = []; - - /** - * @var array<string, ResourceInterface> - */ - private $resources = []; - - /** - * @var array<string, array<array<string, mixed>>> - */ - private $extensionConfigs = []; - - /** - * @var Compiler - */ - private $compiler; - - /** - * @var bool - */ - private $trackResources; - - /** - * @var InstantiatorInterface|null - */ - private $proxyInstantiator; - - /** - * @var ExpressionLanguage|null - */ - private $expressionLanguage; - - /** - * @var ExpressionFunctionProviderInterface[] - */ - private $expressionLanguageProviders = []; - - /** - * @var string[] with tag names used by findTaggedServiceIds - */ - private $usedTags = []; - - /** - * @var string[][] a map of env var names to their placeholders - */ - private $envPlaceholders = []; - - /** - * @var int[] a map of env vars to their resolution counter - */ - private $envCounters = []; - - /** - * @var string[] the list of vendor directories - */ - private $vendors; - - /** - * @var array<string, ChildDefinition> - */ - private $autoconfiguredInstanceof = []; - - /** - * @var array<string, callable> - */ - private $autoconfiguredAttributes = []; - - /** - * @var array<string, bool> - */ - private $removedIds = []; - - /** - * @var array<int, bool> - */ - private $removedBindingIds = []; - - private const INTERNAL_TYPES = [ - 'int' => true, - 'float' => true, - 'string' => true, - 'bool' => true, - 'resource' => true, - 'object' => true, - 'array' => true, - 'null' => true, - 'callable' => true, - 'iterable' => true, - 'mixed' => true, - ]; - - public function __construct(ParameterBagInterface $parameterBag = null) - { - parent::__construct($parameterBag); - - $this->trackResources = interface_exists(ResourceInterface::class); - $this->setDefinition('service_container', (new Definition(ContainerInterface::class))->setSynthetic(true)->setPublic(true)); - $this->setAlias(PsrContainerInterface::class, new Alias('service_container', false))->setDeprecated('symfony/dependency-injection', '5.1', $deprecationMessage = 'The "%alias_id%" autowiring alias is deprecated. Define it explicitly in your app if you want to keep using it.'); - $this->setAlias(ContainerInterface::class, new Alias('service_container', false))->setDeprecated('symfony/dependency-injection', '5.1', $deprecationMessage); - } - - /** - * @var array<string, \ReflectionClass> - */ - private $classReflectors; - - /** - * Sets the track resources flag. - * - * If you are not using the loaders and therefore don't want - * to depend on the Config component, set this flag to false. - */ - public function setResourceTracking(bool $track) - { - $this->trackResources = $track; - } - - /** - * Checks if resources are tracked. - * - * @return bool - */ - public function isTrackingResources() - { - return $this->trackResources; - } - - /** - * Sets the instantiator to be used when fetching proxies. - */ - public function setProxyInstantiator(InstantiatorInterface $proxyInstantiator) - { - $this->proxyInstantiator = $proxyInstantiator; - } - - public function registerExtension(ExtensionInterface $extension) - { - $this->extensions[$extension->getAlias()] = $extension; - - if (false !== $extension->getNamespace()) { - $this->extensionsByNs[$extension->getNamespace()] = $extension; - } - } - - /** - * Returns an extension by alias or namespace. - * - * @return ExtensionInterface - * - * @throws LogicException if the extension is not registered - */ - public function getExtension(string $name) - { - if (isset($this->extensions[$name])) { - return $this->extensions[$name]; - } - - if (isset($this->extensionsByNs[$name])) { - return $this->extensionsByNs[$name]; - } - - throw new LogicException(sprintf('Container extension "%s" is not registered.', $name)); - } - - /** - * Returns all registered extensions. - * - * @return array<string, ExtensionInterface> - */ - public function getExtensions() - { - return $this->extensions; - } - - /** - * Checks if we have an extension. - * - * @return bool - */ - public function hasExtension(string $name) - { - return isset($this->extensions[$name]) || isset($this->extensionsByNs[$name]); - } - - /** - * Returns an array of resources loaded to build this configuration. - * - * @return ResourceInterface[] - */ - public function getResources() - { - return array_values($this->resources); - } - - /** - * @return $this - */ - public function addResource(ResourceInterface $resource) - { - if (!$this->trackResources) { - return $this; - } - - if ($resource instanceof GlobResource && $this->inVendors($resource->getPrefix())) { - return $this; - } - - $this->resources[(string) $resource] = $resource; - - return $this; - } - - /** - * Sets the resources for this configuration. - * - * @param array<string, ResourceInterface> $resources - * - * @return $this - */ - public function setResources(array $resources) - { - if (!$this->trackResources) { - return $this; - } - - $this->resources = $resources; - - return $this; - } - - /** - * Adds the object class hierarchy as resources. - * - * @param object|string $object An object instance or class name - * - * @return $this - */ - public function addObjectResource($object) - { - if ($this->trackResources) { - if (\is_object($object)) { - $object = \get_class($object); - } - if (!isset($this->classReflectors[$object])) { - $this->classReflectors[$object] = new \ReflectionClass($object); - } - $class = $this->classReflectors[$object]; - - foreach ($class->getInterfaceNames() as $name) { - if (null === $interface = &$this->classReflectors[$name]) { - $interface = new \ReflectionClass($name); - } - $file = $interface->getFileName(); - if (false !== $file && file_exists($file)) { - $this->fileExists($file); - } - } - do { - $file = $class->getFileName(); - if (false !== $file && file_exists($file)) { - $this->fileExists($file); - } - foreach ($class->getTraitNames() as $name) { - $this->addObjectResource($name); - } - } while ($class = $class->getParentClass()); - } - - return $this; - } - - /** - * Retrieves the requested reflection class and registers it for resource tracking. - * - * @throws \ReflectionException when a parent class/interface/trait is not found and $throw is true - * - * @final - */ - public function getReflectionClass(?string $class, bool $throw = true): ?\ReflectionClass - { - if (!$class = $this->getParameterBag()->resolveValue($class)) { - return null; - } - - if (isset(self::INTERNAL_TYPES[$class])) { - return null; - } - - $resource = $classReflector = null; - - try { - if (isset($this->classReflectors[$class])) { - $classReflector = $this->classReflectors[$class]; - } elseif (class_exists(ClassExistenceResource::class)) { - $resource = new ClassExistenceResource($class, false); - $classReflector = $resource->isFresh(0) ? false : new \ReflectionClass($class); - } else { - $classReflector = class_exists($class) ? new \ReflectionClass($class) : false; - } - } catch (\ReflectionException $e) { - if ($throw) { - throw $e; - } - } - - if ($this->trackResources) { - if (!$classReflector) { - $this->addResource($resource ?? new ClassExistenceResource($class, false)); - } elseif (!$classReflector->isInternal()) { - $path = $classReflector->getFileName(); - - if (!$this->inVendors($path)) { - $this->addResource(new ReflectionClassResource($classReflector, $this->vendors)); - } - } - $this->classReflectors[$class] = $classReflector; - } - - return $classReflector ?: null; - } - - /** - * Checks whether the requested file or directory exists and registers the result for resource tracking. - * - * @param string $path The file or directory path for which to check the existence - * @param bool|string $trackContents Whether to track contents of the given resource. If a string is passed, - * it will be used as pattern for tracking contents of the requested directory - * - * @final - */ - public function fileExists(string $path, $trackContents = true): bool - { - $exists = file_exists($path); - - if (!$this->trackResources || $this->inVendors($path)) { - return $exists; - } - - if (!$exists) { - $this->addResource(new FileExistenceResource($path)); - - return $exists; - } - - if (is_dir($path)) { - if ($trackContents) { - $this->addResource(new DirectoryResource($path, \is_string($trackContents) ? $trackContents : null)); - } else { - $this->addResource(new GlobResource($path, '/*', false)); - } - } elseif ($trackContents) { - $this->addResource(new FileResource($path)); - } - - return $exists; - } - - /** - * Loads the configuration for an extension. - * - * @param string $extension The extension alias or namespace - * @param array<string, mixed>|null $values An array of values that customizes the extension - * - * @return $this - * - * @throws BadMethodCallException When this ContainerBuilder is compiled - * @throws \LogicException if the extension is not registered - */ - public function loadFromExtension(string $extension, array $values = null) - { - if ($this->isCompiled()) { - throw new BadMethodCallException('Cannot load from an extension on a compiled container.'); - } - - $namespace = $this->getExtension($extension)->getAlias(); - - $this->extensionConfigs[$namespace][] = $values ?? []; - - return $this; - } - - /** - * Adds a compiler pass. - * - * @param string $type The type of compiler pass - * @param int $priority Used to sort the passes - * - * @return $this - */ - public function addCompilerPass(CompilerPassInterface $pass, string $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, int $priority = 0) - { - $this->getCompiler()->addPass($pass, $type, $priority); - - $this->addObjectResource($pass); - - return $this; - } - - /** - * Returns the compiler pass config which can then be modified. - * - * @return PassConfig - */ - public function getCompilerPassConfig() - { - return $this->getCompiler()->getPassConfig(); - } - - /** - * Returns the compiler. - * - * @return Compiler - */ - public function getCompiler() - { - if (null === $this->compiler) { - $this->compiler = new Compiler(); - } - - return $this->compiler; - } - - /** - * Sets a service. - * - * @throws BadMethodCallException When this ContainerBuilder is compiled - */ - public function set(string $id, ?object $service) - { - if ($this->isCompiled() && (isset($this->definitions[$id]) && !$this->definitions[$id]->isSynthetic())) { - // setting a synthetic service on a compiled container is alright - throw new BadMethodCallException(sprintf('Setting service "%s" for an unknown or non-synthetic service definition on a compiled container is not allowed.', $id)); - } - - unset($this->definitions[$id], $this->aliasDefinitions[$id], $this->removedIds[$id]); - - parent::set($id, $service); - } - - /** - * Removes a service definition. - */ - public function removeDefinition(string $id) - { - if (isset($this->definitions[$id])) { - unset($this->definitions[$id]); - $this->removedIds[$id] = true; - } - } - - /** - * Returns true if the given service is defined. - * - * @param string $id The service identifier - * - * @return bool - */ - public function has(string $id) - { - return isset($this->definitions[$id]) || isset($this->aliasDefinitions[$id]) || parent::has($id); - } - - /** - * @return object|null - * - * @throws InvalidArgumentException when no definitions are available - * @throws ServiceCircularReferenceException When a circular reference is detected - * @throws ServiceNotFoundException When the service is not defined - * @throws \Exception - * - * @see Reference - */ - public function get(string $id, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) - { - if ($this->isCompiled() && isset($this->removedIds[$id]) && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $invalidBehavior) { - return parent::get($id); - } - - return $this->doGet($id, $invalidBehavior); - } - - private function doGet(string $id, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, array &$inlineServices = null, bool $isConstructorArgument = false) - { - if (isset($inlineServices[$id])) { - return $inlineServices[$id]; - } - if (null === $inlineServices) { - $isConstructorArgument = true; - $inlineServices = []; - } - try { - if (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $invalidBehavior) { - return parent::get($id, $invalidBehavior); - } - if ($service = parent::get($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)) { - return $service; - } - } catch (ServiceCircularReferenceException $e) { - if ($isConstructorArgument) { - throw $e; - } - } - - if (!isset($this->definitions[$id]) && isset($this->aliasDefinitions[$id])) { - $alias = $this->aliasDefinitions[$id]; - - if ($alias->isDeprecated()) { - $deprecation = $alias->getDeprecation($id); - trigger_deprecation($deprecation['package'], $deprecation['version'], $deprecation['message']); - } - - return $this->doGet((string) $alias, $invalidBehavior, $inlineServices, $isConstructorArgument); - } - - try { - $definition = $this->getDefinition($id); - } catch (ServiceNotFoundException $e) { - if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE < $invalidBehavior) { - return null; - } - - throw $e; - } - - if ($definition->hasErrors() && $e = $definition->getErrors()) { - throw new RuntimeException(reset($e)); - } - - if ($isConstructorArgument) { - $this->loading[$id] = true; - } - - try { - return $this->createService($definition, $inlineServices, $isConstructorArgument, $id); - } finally { - if ($isConstructorArgument) { - unset($this->loading[$id]); - } - } - } - - /** - * Merges a ContainerBuilder with the current ContainerBuilder configuration. - * - * Service definitions overrides the current defined ones. - * - * But for parameters, they are overridden by the current ones. It allows - * the parameters passed to the container constructor to have precedence - * over the loaded ones. - * - * $container = new ContainerBuilder(new ParameterBag(['foo' => 'bar'])); - * $loader = new LoaderXXX($container); - * $loader->load('resource_name'); - * $container->register('foo', 'stdClass'); - * - * In the above example, even if the loaded resource defines a foo - * parameter, the value will still be 'bar' as defined in the ContainerBuilder - * constructor. - * - * @throws BadMethodCallException When this ContainerBuilder is compiled - */ - public function merge(self $container) - { - if ($this->isCompiled()) { - throw new BadMethodCallException('Cannot merge on a compiled container.'); - } - - $this->addDefinitions($container->getDefinitions()); - $this->addAliases($container->getAliases()); - $this->getParameterBag()->add($container->getParameterBag()->all()); - - if ($this->trackResources) { - foreach ($container->getResources() as $resource) { - $this->addResource($resource); - } - } - - foreach ($this->extensions as $name => $extension) { - if (!isset($this->extensionConfigs[$name])) { - $this->extensionConfigs[$name] = []; - } - - $this->extensionConfigs[$name] = array_merge($this->extensionConfigs[$name], $container->getExtensionConfig($name)); - } - - if ($this->getParameterBag() instanceof EnvPlaceholderParameterBag && $container->getParameterBag() instanceof EnvPlaceholderParameterBag) { - $envPlaceholders = $container->getParameterBag()->getEnvPlaceholders(); - $this->getParameterBag()->mergeEnvPlaceholders($container->getParameterBag()); - } else { - $envPlaceholders = []; - } - - foreach ($container->envCounters as $env => $count) { - if (!$count && !isset($envPlaceholders[$env])) { - continue; - } - if (!isset($this->envCounters[$env])) { - $this->envCounters[$env] = $count; - } else { - $this->envCounters[$env] += $count; - } - } - - foreach ($container->getAutoconfiguredInstanceof() as $interface => $childDefinition) { - if (isset($this->autoconfiguredInstanceof[$interface])) { - throw new InvalidArgumentException(sprintf('"%s" has already been autoconfigured and merge() does not support merging autoconfiguration for the same class/interface.', $interface)); - } - - $this->autoconfiguredInstanceof[$interface] = $childDefinition; - } - - foreach ($container->getAutoconfiguredAttributes() as $attribute => $configurator) { - if (isset($this->autoconfiguredAttributes[$attribute])) { - throw new InvalidArgumentException(sprintf('"%s" has already been autoconfigured and merge() does not support merging autoconfiguration for the same attribute.', $attribute)); - } - - $this->autoconfiguredAttributes[$attribute] = $configurator; - } - } - - /** - * Returns the configuration array for the given extension. - * - * @return array<array<string, mixed>> - */ - public function getExtensionConfig(string $name) - { - if (!isset($this->extensionConfigs[$name])) { - $this->extensionConfigs[$name] = []; - } - - return $this->extensionConfigs[$name]; - } - - /** - * Prepends a config array to the configs of the given extension. - * - * @param array<string, mixed> $config - */ - public function prependExtensionConfig(string $name, array $config) - { - if (!isset($this->extensionConfigs[$name])) { - $this->extensionConfigs[$name] = []; - } - - array_unshift($this->extensionConfigs[$name], $config); - } - - /** - * Compiles the container. - * - * This method passes the container to compiler - * passes whose job is to manipulate and optimize - * the container. - * - * The main compiler passes roughly do four things: - * - * * The extension configurations are merged; - * * Parameter values are resolved; - * * The parameter bag is frozen; - * * Extension loading is disabled. - * - * @param bool $resolveEnvPlaceholders Whether %env()% parameters should be resolved using the current - * env vars or be replaced by uniquely identifiable placeholders. - * Set to "true" when you want to use the current ContainerBuilder - * directly, keep to "false" when the container is dumped instead. - */ - public function compile(bool $resolveEnvPlaceholders = false) - { - $compiler = $this->getCompiler(); - - if ($this->trackResources) { - foreach ($compiler->getPassConfig()->getPasses() as $pass) { - $this->addObjectResource($pass); - } - } - $bag = $this->getParameterBag(); - - if ($resolveEnvPlaceholders && $bag instanceof EnvPlaceholderParameterBag) { - $compiler->addPass(new ResolveEnvPlaceholdersPass(), PassConfig::TYPE_AFTER_REMOVING, -1000); - } - - $compiler->compile($this); - - foreach ($this->definitions as $id => $definition) { - if ($this->trackResources && $definition->isLazy()) { - $this->getReflectionClass($definition->getClass()); - } - } - - $this->extensionConfigs = []; - - if ($bag instanceof EnvPlaceholderParameterBag) { - if ($resolveEnvPlaceholders) { - $this->parameterBag = new ParameterBag($this->resolveEnvPlaceholders($bag->all(), true)); - } - - $this->envPlaceholders = $bag->getEnvPlaceholders(); - } - - parent::compile(); - - foreach ($this->definitions + $this->aliasDefinitions as $id => $definition) { - if (!$definition->isPublic() || $definition->isPrivate()) { - $this->removedIds[$id] = true; - } - } - } - - /** - * {@inheritdoc} - */ - public function getServiceIds() - { - return array_map('strval', array_unique(array_merge(array_keys($this->getDefinitions()), array_keys($this->aliasDefinitions), parent::getServiceIds()))); - } - - /** - * Gets removed service or alias ids. - * - * @return array<string, bool> - */ - public function getRemovedIds() - { - return $this->removedIds; - } - - /** - * Adds the service aliases. - * - * @param array<string, string|Alias> $aliases - */ - public function addAliases(array $aliases) - { - foreach ($aliases as $alias => $id) { - $this->setAlias($alias, $id); - } - } - - /** - * Sets the service aliases. - * - * @param array<string, string|Alias> $aliases - */ - public function setAliases(array $aliases) - { - $this->aliasDefinitions = []; - $this->addAliases($aliases); - } - - /** - * Sets an alias for an existing service. - * - * @param string $alias The alias to create - * @param string|Alias $id The service to alias - * - * @return Alias - * - * @throws InvalidArgumentException if the id is not a string or an Alias - * @throws InvalidArgumentException if the alias is for itself - */ - public function setAlias(string $alias, $id) - { - if ('' === $alias || '\\' === $alias[-1] || \strlen($alias) !== strcspn($alias, "\0\r\n'")) { - throw new InvalidArgumentException(sprintf('Invalid alias id: "%s".', $alias)); - } - - if (\is_string($id)) { - $id = new Alias($id); - } elseif (!$id instanceof Alias) { - throw new InvalidArgumentException('$id must be a string, or an Alias object.'); - } - - if ($alias === (string) $id) { - throw new InvalidArgumentException(sprintf('An alias cannot reference itself, got a circular reference on "%s".', $alias)); - } - - unset($this->definitions[$alias], $this->removedIds[$alias]); - - return $this->aliasDefinitions[$alias] = $id; - } - - public function removeAlias(string $alias) - { - if (isset($this->aliasDefinitions[$alias])) { - unset($this->aliasDefinitions[$alias]); - $this->removedIds[$alias] = true; - } - } - - /** - * @return bool - */ - public function hasAlias(string $id) - { - return isset($this->aliasDefinitions[$id]); - } - - /** - * @return array<string, Alias> - */ - public function getAliases() - { - return $this->aliasDefinitions; - } - - /** - * @return Alias - * - * @throws InvalidArgumentException if the alias does not exist - */ - public function getAlias(string $id) - { - if (!isset($this->aliasDefinitions[$id])) { - throw new InvalidArgumentException(sprintf('The service alias "%s" does not exist.', $id)); - } - - return $this->aliasDefinitions[$id]; - } - - /** - * Registers a service definition. - * - * This methods allows for simple registration of service definition - * with a fluid interface. - * - * @return Definition - */ - public function register(string $id, string $class = null) - { - return $this->setDefinition($id, new Definition($class)); - } - - /** - * Registers an autowired service definition. - * - * This method implements a shortcut for using setDefinition() with - * an autowired definition. - * - * @return Definition - */ - public function autowire(string $id, string $class = null) - { - return $this->setDefinition($id, (new Definition($class))->setAutowired(true)); - } - - /** - * Adds the service definitions. - * - * @param array<string, Definition> $definitions - */ - public function addDefinitions(array $definitions) - { - foreach ($definitions as $id => $definition) { - $this->setDefinition($id, $definition); - } - } - - /** - * Sets the service definitions. - * - * @param array<string, Definition> $definitions - */ - public function setDefinitions(array $definitions) - { - $this->definitions = []; - $this->addDefinitions($definitions); - } - - /** - * Gets all service definitions. - * - * @return array<string, Definition> - */ - public function getDefinitions() - { - return $this->definitions; - } - - /** - * Sets a service definition. - * - * @return Definition - * - * @throws BadMethodCallException When this ContainerBuilder is compiled - */ - public function setDefinition(string $id, Definition $definition) - { - if ($this->isCompiled()) { - throw new BadMethodCallException('Adding definition to a compiled container is not allowed.'); - } - - if ('' === $id || '\\' === $id[-1] || \strlen($id) !== strcspn($id, "\0\r\n'")) { - throw new InvalidArgumentException(sprintf('Invalid service id: "%s".', $id)); - } - - unset($this->aliasDefinitions[$id], $this->removedIds[$id]); - - return $this->definitions[$id] = $definition; - } - - /** - * Returns true if a service definition exists under the given identifier. - * - * @return bool - */ - public function hasDefinition(string $id) - { - return isset($this->definitions[$id]); - } - - /** - * Gets a service definition. - * - * @return Definition - * - * @throws ServiceNotFoundException if the service definition does not exist - */ - public function getDefinition(string $id) - { - if (!isset($this->definitions[$id])) { - throw new ServiceNotFoundException($id); - } - - return $this->definitions[$id]; - } - - /** - * Gets a service definition by id or alias. - * - * The method "unaliases" recursively to return a Definition instance. - * - * @return Definition - * - * @throws ServiceNotFoundException if the service definition does not exist - */ - public function findDefinition(string $id) - { - $seen = []; - while (isset($this->aliasDefinitions[$id])) { - $id = (string) $this->aliasDefinitions[$id]; - - if (isset($seen[$id])) { - $seen = array_values($seen); - $seen = \array_slice($seen, array_search($id, $seen)); - $seen[] = $id; - - throw new ServiceCircularReferenceException($id, $seen); - } - - $seen[$id] = $id; - } - - return $this->getDefinition($id); - } - - /** - * Creates a service for a service definition. - * - * @return mixed - * - * @throws RuntimeException When the factory definition is incomplete - * @throws RuntimeException When the service is a synthetic service - * @throws InvalidArgumentException When configure callable is not callable - */ - private function createService(Definition $definition, array &$inlineServices, bool $isConstructorArgument = false, string $id = null, bool $tryProxy = true) - { - if (null === $id && isset($inlineServices[$h = spl_object_hash($definition)])) { - return $inlineServices[$h]; - } - - if ($definition instanceof ChildDefinition) { - throw new RuntimeException(sprintf('Constructing service "%s" from a parent definition is not supported at build time.', $id)); - } - - if ($definition->isSynthetic()) { - throw new RuntimeException(sprintf('You have requested a synthetic service ("%s"). The DIC does not know how to construct this service.', $id)); - } - - if ($definition->isDeprecated()) { - $deprecation = $definition->getDeprecation($id); - trigger_deprecation($deprecation['package'], $deprecation['version'], $deprecation['message']); - } - - if ($tryProxy && $definition->isLazy() && !$tryProxy = !($proxy = $this->proxyInstantiator) || $proxy instanceof RealServiceInstantiator) { - $proxy = $proxy->instantiateProxy( - $this, - $definition, - $id, function () use ($definition, &$inlineServices, $id) { - return $this->createService($definition, $inlineServices, true, $id, false); - } - ); - $this->shareService($definition, $proxy, $id, $inlineServices); - - return $proxy; - } - - $parameterBag = $this->getParameterBag(); - - if (null !== $definition->getFile()) { - require_once $parameterBag->resolveValue($definition->getFile()); - } - - $arguments = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments())), $inlineServices, $isConstructorArgument); - - if (null !== $factory = $definition->getFactory()) { - if (\is_array($factory)) { - $factory = [$this->doResolveServices($parameterBag->resolveValue($factory[0]), $inlineServices, $isConstructorArgument), $factory[1]]; - } elseif (!\is_string($factory)) { - throw new RuntimeException(sprintf('Cannot create service "%s" because of invalid factory.', $id)); - } - } - - if (null !== $id && $definition->isShared() && isset($this->services[$id]) && ($tryProxy || !$definition->isLazy())) { - return $this->services[$id]; - } - - if (null !== $factory) { - $service = $factory(...$arguments); - - if (!$definition->isDeprecated() && \is_array($factory) && \is_string($factory[0])) { - $r = new \ReflectionClass($factory[0]); - - if (0 < strpos($r->getDocComment(), "\n * @deprecated ")) { - trigger_deprecation('', '', 'The "%s" service relies on the deprecated "%s" factory class. It should either be deprecated or its factory upgraded.', $id, $r->name); - } - } - } else { - $r = new \ReflectionClass($parameterBag->resolveValue($definition->getClass())); - - $service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs(array_values($arguments)); - - if (!$definition->isDeprecated() && 0 < strpos($r->getDocComment(), "\n * @deprecated ")) { - trigger_deprecation('', '', 'The "%s" service relies on the deprecated "%s" class. It should either be deprecated or its implementation upgraded.', $id, $r->name); - } - } - - $lastWitherIndex = null; - foreach ($definition->getMethodCalls() as $k => $call) { - if ($call[2] ?? false) { - $lastWitherIndex = $k; - } - } - - if (null === $lastWitherIndex && ($tryProxy || !$definition->isLazy())) { - // share only if proxying failed, or if not a proxy, and if no withers are found - $this->shareService($definition, $service, $id, $inlineServices); - } - - $properties = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getProperties())), $inlineServices); - foreach ($properties as $name => $value) { - $service->$name = $value; - } - - foreach ($definition->getMethodCalls() as $k => $call) { - $service = $this->callMethod($service, $call, $inlineServices); - - if ($lastWitherIndex === $k && ($tryProxy || !$definition->isLazy())) { - // share only if proxying failed, or if not a proxy, and this is the last wither - $this->shareService($definition, $service, $id, $inlineServices); - } - } - - if ($callable = $definition->getConfigurator()) { - if (\is_array($callable)) { - $callable[0] = $parameterBag->resolveValue($callable[0]); - - if ($callable[0] instanceof Reference) { - $callable[0] = $this->doGet((string) $callable[0], $callable[0]->getInvalidBehavior(), $inlineServices); - } elseif ($callable[0] instanceof Definition) { - $callable[0] = $this->createService($callable[0], $inlineServices); - } - } - - if (!\is_callable($callable)) { - throw new InvalidArgumentException(sprintf('The configure callable for class "%s" is not a callable.', get_debug_type($service))); - } - - $callable($service); - } - - return $service; - } - - /** - * Replaces service references by the real service instance and evaluates expressions. - * - * @param mixed $value - * - * @return mixed The same value with all service references replaced by - * the real service instances and all expressions evaluated - */ - public function resolveServices($value) - { - return $this->doResolveServices($value); - } - - private function doResolveServices($value, array &$inlineServices = [], bool $isConstructorArgument = false) - { - if (\is_array($value)) { - foreach ($value as $k => $v) { - $value[$k] = $this->doResolveServices($v, $inlineServices, $isConstructorArgument); - } - } elseif ($value instanceof ServiceClosureArgument) { - $reference = $value->getValues()[0]; - $value = function () use ($reference) { - return $this->resolveServices($reference); - }; - } elseif ($value instanceof IteratorArgument) { - $value = new RewindableGenerator(function () use ($value, &$inlineServices) { - foreach ($value->getValues() as $k => $v) { - foreach (self::getServiceConditionals($v) as $s) { - if (!$this->has($s)) { - continue 2; - } - } - foreach (self::getInitializedConditionals($v) as $s) { - if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE, $inlineServices)) { - continue 2; - } - } - - yield $k => $this->doResolveServices($v, $inlineServices); - } - }, function () use ($value): int { - $count = 0; - foreach ($value->getValues() as $v) { - foreach (self::getServiceConditionals($v) as $s) { - if (!$this->has($s)) { - continue 2; - } - } - foreach (self::getInitializedConditionals($v) as $s) { - if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) { - continue 2; - } - } - - ++$count; - } - - return $count; - }); - } elseif ($value instanceof ServiceLocatorArgument) { - $refs = $types = []; - foreach ($value->getValues() as $k => $v) { - if ($v) { - $refs[$k] = [$v]; - $types[$k] = $v instanceof TypedReference ? $v->getType() : '?'; - } - } - $value = new ServiceLocator(\Closure::fromCallable([$this, 'resolveServices']), $refs, $types); - } elseif ($value instanceof Reference) { - $value = $this->doGet((string) $value, $value->getInvalidBehavior(), $inlineServices, $isConstructorArgument); - } elseif ($value instanceof Definition) { - $value = $this->createService($value, $inlineServices, $isConstructorArgument); - } elseif ($value instanceof Parameter) { - $value = $this->getParameter((string) $value); - } elseif ($value instanceof Expression) { - $value = $this->getExpressionLanguage()->evaluate($value, ['container' => $this]); - } elseif ($value instanceof AbstractArgument) { - throw new RuntimeException($value->getTextWithContext()); - } - - return $value; - } - - /** - * Returns service ids for a given tag. - * - * Example: - * - * $container->register('foo')->addTag('my.tag', ['hello' => 'world']); - * - * $serviceIds = $container->findTaggedServiceIds('my.tag'); - * foreach ($serviceIds as $serviceId => $tags) { - * foreach ($tags as $tag) { - * echo $tag['hello']; - * } - * } - * - * @return array<string, array> An array of tags with the tagged service as key, holding a list of attribute arrays - */ - public function findTaggedServiceIds(string $name, bool $throwOnAbstract = false) - { - $this->usedTags[] = $name; - $tags = []; - foreach ($this->getDefinitions() as $id => $definition) { - if ($definition->hasTag($name)) { - if ($throwOnAbstract && $definition->isAbstract()) { - throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must not be abstract.', $id, $name)); - } - $tags[$id] = $definition->getTag($name); - } - } - - return $tags; - } - - /** - * Returns all tags the defined services use. - * - * @return string[] - */ - public function findTags() - { - $tags = []; - foreach ($this->getDefinitions() as $id => $definition) { - $tags[] = array_keys($definition->getTags()); - } - - return array_unique(array_merge([], ...$tags)); - } - - /** - * Returns all tags not queried by findTaggedServiceIds. - * - * @return string[] - */ - public function findUnusedTags() - { - return array_values(array_diff($this->findTags(), $this->usedTags)); - } - - public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) - { - $this->expressionLanguageProviders[] = $provider; - } - - /** - * @return ExpressionFunctionProviderInterface[] - */ - public function getExpressionLanguageProviders() - { - return $this->expressionLanguageProviders; - } - - /** - * Returns a ChildDefinition that will be used for autoconfiguring the interface/class. - * - * @return ChildDefinition - */ - public function registerForAutoconfiguration(string $interface) - { - if (!isset($this->autoconfiguredInstanceof[$interface])) { - $this->autoconfiguredInstanceof[$interface] = new ChildDefinition(''); - } - - return $this->autoconfiguredInstanceof[$interface]; - } - - /** - * Registers an attribute that will be used for autoconfiguring annotated classes. - * - * The third argument passed to the callable is the reflector of the - * class/method/property/parameter that the attribute targets. Using one or many of - * \ReflectionClass|\ReflectionMethod|\ReflectionProperty|\ReflectionParameter as a type-hint - * for this argument allows filtering which attributes should be passed to the callable. - * - * @template T - * - * @param class-string<T> $attributeClass - * @param callable(ChildDefinition, T, \Reflector): void $configurator - */ - public function registerAttributeForAutoconfiguration(string $attributeClass, callable $configurator): void - { - $this->autoconfiguredAttributes[$attributeClass] = $configurator; - } - - /** - * Registers an autowiring alias that only binds to a specific argument name. - * - * The argument name is derived from $name if provided (from $id otherwise) - * using camel case: "foo.bar" or "foo_bar" creates an alias bound to - * "$fooBar"-named arguments with $type as type-hint. Such arguments will - * receive the service $id when autowiring is used. - */ - public function registerAliasForArgument(string $id, string $type, string $name = null): Alias - { - $name = (new Target($name ?? $id))->name; - - if (!preg_match('/^[a-zA-Z_\x7f-\xff]/', $name)) { - throw new InvalidArgumentException(sprintf('Invalid argument name "%s" for service "%s": the first character must be a letter.', $name, $id)); - } - - return $this->setAlias($type.' $'.$name, $id); - } - - /** - * Returns an array of ChildDefinition[] keyed by interface. - * - * @return array<string, ChildDefinition> - */ - public function getAutoconfiguredInstanceof() - { - return $this->autoconfiguredInstanceof; - } - - /** - * @return array<string, callable> - */ - public function getAutoconfiguredAttributes(): array - { - return $this->autoconfiguredAttributes; - } - - /** - * Resolves env parameter placeholders in a string or an array. - * - * @param mixed $value The value to resolve - * @param string|true|null $format A sprintf() format returning the replacement for each env var name or - * null to resolve back to the original "%env(VAR)%" format or - * true to resolve to the actual values of the referenced env vars - * @param array &$usedEnvs Env vars found while resolving are added to this array - * - * @return mixed The value with env parameters resolved if a string or an array is passed - */ - public function resolveEnvPlaceholders($value, $format = null, array &$usedEnvs = null) - { - if (null === $format) { - $format = '%%env(%s)%%'; - } - - $bag = $this->getParameterBag(); - if (true === $format) { - $value = $bag->resolveValue($value); - } - - if ($value instanceof Definition) { - $value = (array) $value; - } - - if (\is_array($value)) { - $result = []; - foreach ($value as $k => $v) { - $result[\is_string($k) ? $this->resolveEnvPlaceholders($k, $format, $usedEnvs) : $k] = $this->resolveEnvPlaceholders($v, $format, $usedEnvs); - } - - return $result; - } - - if (!\is_string($value) || 38 > \strlen($value) || !preg_match('/env[_(]/i', $value)) { - return $value; - } - $envPlaceholders = $bag instanceof EnvPlaceholderParameterBag ? $bag->getEnvPlaceholders() : $this->envPlaceholders; - - $completed = false; - foreach ($envPlaceholders as $env => $placeholders) { - foreach ($placeholders as $placeholder) { - if (false !== stripos($value, $placeholder)) { - if (true === $format) { - $resolved = $bag->escapeValue($this->getEnv($env)); - } else { - $resolved = sprintf($format, $env); - } - if ($placeholder === $value) { - $value = $resolved; - $completed = true; - } else { - if (!\is_string($resolved) && !is_numeric($resolved)) { - throw new RuntimeException(sprintf('A string value must be composed of strings and/or numbers, but found parameter "env(%s)" of type "%s" inside string value "%s".', $env, get_debug_type($resolved), $this->resolveEnvPlaceholders($value))); - } - $value = str_ireplace($placeholder, $resolved, $value); - } - $usedEnvs[$env] = $env; - $this->envCounters[$env] = isset($this->envCounters[$env]) ? 1 + $this->envCounters[$env] : 1; - - if ($completed) { - break 2; - } - } - } - } - - return $value; - } - - /** - * Get statistics about env usage. - * - * @return int[] The number of time each env vars has been resolved - */ - public function getEnvCounters() - { - $bag = $this->getParameterBag(); - $envPlaceholders = $bag instanceof EnvPlaceholderParameterBag ? $bag->getEnvPlaceholders() : $this->envPlaceholders; - - foreach ($envPlaceholders as $env => $placeholders) { - if (!isset($this->envCounters[$env])) { - $this->envCounters[$env] = 0; - } - } - - return $this->envCounters; - } - - /** - * @final - */ - public function log(CompilerPassInterface $pass, string $message) - { - $this->getCompiler()->log($pass, $this->resolveEnvPlaceholders($message)); - } - - /** - * Checks whether a class is available and will remain available in the "no-dev" mode of Composer. - * - * When parent packages are provided and if any of them is in dev-only mode, - * the class will be considered available even if it is also in dev-only mode. - */ - final public static function willBeAvailable(string $package, string $class, array $parentPackages): bool - { - $skipDeprecation = 3 < \func_num_args() && func_get_arg(3); - $hasRuntimeApi = class_exists(InstalledVersions::class); - - if (!$hasRuntimeApi && !$skipDeprecation) { - trigger_deprecation('symfony/dependency-injection', '5.4', 'Calling "%s" when dependencies have been installed with Composer 1 is deprecated. Consider upgrading to Composer 2.', __METHOD__); - } - - if (!class_exists($class) && !interface_exists($class, false) && !trait_exists($class, false)) { - return false; - } - - if (!$hasRuntimeApi || !InstalledVersions::isInstalled($package) || InstalledVersions::isInstalled($package, false)) { - return true; - } - - // the package is installed but in dev-mode only, check if this applies to one of the parent packages too - - $rootPackage = InstalledVersions::getRootPackage()['name'] ?? ''; - - if ('symfony/symfony' === $rootPackage) { - return true; - } - - foreach ($parentPackages as $parentPackage) { - if ($rootPackage === $parentPackage || (InstalledVersions::isInstalled($parentPackage) && !InstalledVersions::isInstalled($parentPackage, false))) { - return true; - } - } - - return false; - } - - /** - * Gets removed binding ids. - * - * @return array<int, bool> - * - * @internal - */ - public function getRemovedBindingIds(): array - { - return $this->removedBindingIds; - } - - /** - * Removes bindings for a service. - * - * @internal - */ - public function removeBindings(string $id) - { - if ($this->hasDefinition($id)) { - foreach ($this->getDefinition($id)->getBindings() as $key => $binding) { - [, $bindingId] = $binding->getValues(); - $this->removedBindingIds[(int) $bindingId] = true; - } - } - } - - /** - * Returns the Service Conditionals. - * - * @param mixed $value An array of conditionals to return - * - * @return string[] - * - * @internal - */ - public static function getServiceConditionals($value): array - { - $services = []; - - if (\is_array($value)) { - foreach ($value as $v) { - $services = array_unique(array_merge($services, self::getServiceConditionals($v))); - } - } elseif ($value instanceof Reference && ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $value->getInvalidBehavior()) { - $services[] = (string) $value; - } - - return $services; - } - - /** - * Returns the initialized conditionals. - * - * @param mixed $value An array of conditionals to return - * - * @return string[] - * - * @internal - */ - public static function getInitializedConditionals($value): array - { - $services = []; - - if (\is_array($value)) { - foreach ($value as $v) { - $services = array_unique(array_merge($services, self::getInitializedConditionals($v))); - } - } elseif ($value instanceof Reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior()) { - $services[] = (string) $value; - } - - return $services; - } - - /** - * Computes a reasonably unique hash of a value. - * - * @param mixed $value A serializable value - * - * @return string - */ - public static function hash($value) - { - $hash = substr(base64_encode(hash('sha256', serialize($value), true)), 0, 7); - - return str_replace(['/', '+'], ['.', '_'], $hash); - } - - /** - * {@inheritdoc} - */ - protected function getEnv(string $name) - { - $value = parent::getEnv($name); - $bag = $this->getParameterBag(); - - if (!\is_string($value) || !$bag instanceof EnvPlaceholderParameterBag) { - return $value; - } - - $envPlaceholders = $bag->getEnvPlaceholders(); - if (isset($envPlaceholders[$name][$value])) { - $bag = new ParameterBag($bag->all()); - - return $bag->unescapeValue($bag->get("env($name)")); - } - foreach ($envPlaceholders as $env => $placeholders) { - if (isset($placeholders[$value])) { - return $this->getEnv($env); - } - } - - $this->resolving["env($name)"] = true; - try { - return $bag->unescapeValue($this->resolveEnvPlaceholders($bag->escapeValue($value), true)); - } finally { - unset($this->resolving["env($name)"]); - } - } - - private function callMethod(object $service, array $call, array &$inlineServices) - { - foreach (self::getServiceConditionals($call[1]) as $s) { - if (!$this->has($s)) { - return $service; - } - } - foreach (self::getInitializedConditionals($call[1]) as $s) { - if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE, $inlineServices)) { - return $service; - } - } - - $result = $service->{$call[0]}(...$this->doResolveServices($this->getParameterBag()->unescapeValue($this->getParameterBag()->resolveValue($call[1])), $inlineServices)); - - return empty($call[2]) ? $service : $result; - } - - /** - * Shares a given service in the container. - * - * @param mixed $service - */ - private function shareService(Definition $definition, $service, ?string $id, array &$inlineServices) - { - $inlineServices[$id ?? spl_object_hash($definition)] = $service; - - if (null !== $id && $definition->isShared()) { - $this->services[$id] = $service; - unset($this->loading[$id]); - } - } - - private function getExpressionLanguage(): ExpressionLanguage - { - if (null === $this->expressionLanguage) { - if (!class_exists(\Symfony\Component\ExpressionLanguage\ExpressionLanguage::class)) { - throw new LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); - } - $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders); - } - - return $this->expressionLanguage; - } - - private function inVendors(string $path): bool - { - if (null === $this->vendors) { - $this->vendors = (new ComposerResource())->getVendors(); - } - $path = realpath($path) ?: $path; - - foreach ($this->vendors as $vendor) { - if (str_starts_with($path, $vendor) && false !== strpbrk(substr($path, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) { - $this->addResource(new FileResource($vendor.'/composer/installed.json')); - - return true; - } - } - - return false; - } -} diff --git a/lib/symfony/dependency-injection/ContainerInterface.php b/lib/symfony/dependency-injection/ContainerInterface.php deleted file mode 100644 index 3a44b9967..000000000 --- a/lib/symfony/dependency-injection/ContainerInterface.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -use Psr\Container\ContainerInterface as PsrContainerInterface; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; - -/** - * ContainerInterface is the interface implemented by service container classes. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -interface ContainerInterface extends PsrContainerInterface -{ - public const RUNTIME_EXCEPTION_ON_INVALID_REFERENCE = 0; - public const EXCEPTION_ON_INVALID_REFERENCE = 1; - public const NULL_ON_INVALID_REFERENCE = 2; - public const IGNORE_ON_INVALID_REFERENCE = 3; - public const IGNORE_ON_UNINITIALIZED_REFERENCE = 4; - - /** - * Sets a service. - */ - public function set(string $id, ?object $service); - - /** - * Gets a service. - * - * @param string $id The service identifier - * @param int $invalidBehavior The behavior when the service does not exist - * - * @return object|null - * - * @throws ServiceCircularReferenceException When a circular reference is detected - * @throws ServiceNotFoundException When the service is not defined - * - * @see Reference - */ - public function get(string $id, int $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE); - - /** - * @return bool - */ - public function has(string $id); - - /** - * Check for whether or not a service has been initialized. - * - * @return bool - */ - public function initialized(string $id); - - /** - * @return array|bool|string|int|float|\UnitEnum|null - * - * @throws InvalidArgumentException if the parameter is not defined - */ - public function getParameter(string $name); - - /** - * @return bool - */ - public function hasParameter(string $name); - - /** - * Sets a parameter. - * - * @param string $name The parameter name - * @param array|bool|string|int|float|\UnitEnum|null $value The parameter value - */ - public function setParameter(string $name, $value); -} diff --git a/lib/symfony/dependency-injection/Definition.php b/lib/symfony/dependency-injection/Definition.php deleted file mode 100644 index 7fc675255..000000000 --- a/lib/symfony/dependency-injection/Definition.php +++ /dev/null @@ -1,922 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -use Symfony\Component\DependencyInjection\Argument\BoundArgument; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException; - -/** - * Definition represents a service definition. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Definition -{ - private const DEFAULT_DEPRECATION_TEMPLATE = 'The "%service_id%" service is deprecated. You should stop using it, as it will be removed in the future.'; - - private $class; - private $file; - private $factory; - private $shared = true; - private $deprecation = []; - private $properties = []; - private $calls = []; - private $instanceof = []; - private $autoconfigured = false; - private $configurator; - private $tags = []; - private $public = false; - private $synthetic = false; - private $abstract = false; - private $lazy = false; - private $decoratedService; - private $autowired = false; - private $changes = []; - private $bindings = []; - private $errors = []; - - protected $arguments = []; - - /** - * @internal - * - * Used to store the name of the inner id when using service decoration together with autowiring - */ - public $innerServiceId; - - /** - * @internal - * - * Used to store the behavior to follow when using service decoration and the decorated service is invalid - */ - public $decorationOnInvalid; - - public function __construct(string $class = null, array $arguments = []) - { - if (null !== $class) { - $this->setClass($class); - } - $this->arguments = $arguments; - } - - /** - * Returns all changes tracked for the Definition object. - * - * @return array - */ - public function getChanges() - { - return $this->changes; - } - - /** - * Sets the tracked changes for the Definition object. - * - * @param array $changes An array of changes for this Definition - * - * @return $this - */ - public function setChanges(array $changes) - { - $this->changes = $changes; - - return $this; - } - - /** - * Sets a factory. - * - * @param string|array|Reference|null $factory A PHP function, reference or an array containing a class/Reference and a method to call - * - * @return $this - */ - public function setFactory($factory) - { - $this->changes['factory'] = true; - - if (\is_string($factory) && str_contains($factory, '::')) { - $factory = explode('::', $factory, 2); - } elseif ($factory instanceof Reference) { - $factory = [$factory, '__invoke']; - } - - $this->factory = $factory; - - return $this; - } - - /** - * Gets the factory. - * - * @return string|array|null The PHP function or an array containing a class/Reference and a method to call - */ - public function getFactory() - { - return $this->factory; - } - - /** - * Sets the service that this service is decorating. - * - * @param string|null $id The decorated service id, use null to remove decoration - * @param string|null $renamedId The new decorated service id - * - * @return $this - * - * @throws InvalidArgumentException in case the decorated service id and the new decorated service id are equals - */ - public function setDecoratedService(?string $id, string $renamedId = null, int $priority = 0, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) - { - if ($renamedId && $id === $renamedId) { - throw new InvalidArgumentException(sprintf('The decorated service inner name for "%s" must be different than the service name itself.', $id)); - } - - $this->changes['decorated_service'] = true; - - if (null === $id) { - $this->decoratedService = null; - } else { - $this->decoratedService = [$id, $renamedId, $priority]; - - if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) { - $this->decoratedService[] = $invalidBehavior; - } - } - - return $this; - } - - /** - * Gets the service that this service is decorating. - * - * @return array|null An array composed of the decorated service id, the new id for it and the priority of decoration, null if no service is decorated - */ - public function getDecoratedService() - { - return $this->decoratedService; - } - - /** - * Sets the service class. - * - * @return $this - */ - public function setClass(?string $class) - { - $this->changes['class'] = true; - - $this->class = $class; - - return $this; - } - - /** - * Gets the service class. - * - * @return string|null - */ - public function getClass() - { - return $this->class; - } - - /** - * Sets the arguments to pass to the service constructor/factory method. - * - * @return $this - */ - public function setArguments(array $arguments) - { - $this->arguments = $arguments; - - return $this; - } - - /** - * Sets the properties to define when creating the service. - * - * @return $this - */ - public function setProperties(array $properties) - { - $this->properties = $properties; - - return $this; - } - - /** - * Gets the properties to define when creating the service. - * - * @return array - */ - public function getProperties() - { - return $this->properties; - } - - /** - * Sets a specific property. - * - * @param mixed $value - * - * @return $this - */ - public function setProperty(string $name, $value) - { - $this->properties[$name] = $value; - - return $this; - } - - /** - * Adds an argument to pass to the service constructor/factory method. - * - * @param mixed $argument An argument - * - * @return $this - */ - public function addArgument($argument) - { - $this->arguments[] = $argument; - - return $this; - } - - /** - * Replaces a specific argument. - * - * @param int|string $index - * @param mixed $argument - * - * @return $this - * - * @throws OutOfBoundsException When the replaced argument does not exist - */ - public function replaceArgument($index, $argument) - { - if (0 === \count($this->arguments)) { - throw new OutOfBoundsException(sprintf('Cannot replace arguments for class "%s" if none have been configured yet.', $this->class)); - } - - if (\is_int($index) && ($index < 0 || $index > \count($this->arguments) - 1)) { - throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d] of the arguments of class "%s".', $index, \count($this->arguments) - 1, $this->class)); - } - - if (!\array_key_exists($index, $this->arguments)) { - throw new OutOfBoundsException(sprintf('The argument "%s" doesn\'t exist in class "%s".', $index, $this->class)); - } - - $this->arguments[$index] = $argument; - - return $this; - } - - /** - * Sets a specific argument. - * - * @param int|string $key - * @param mixed $value - * - * @return $this - */ - public function setArgument($key, $value) - { - $this->arguments[$key] = $value; - - return $this; - } - - /** - * Gets the arguments to pass to the service constructor/factory method. - * - * @return array - */ - public function getArguments() - { - return $this->arguments; - } - - /** - * Gets an argument to pass to the service constructor/factory method. - * - * @param int|string $index - * - * @return mixed - * - * @throws OutOfBoundsException When the argument does not exist - */ - public function getArgument($index) - { - if (!\array_key_exists($index, $this->arguments)) { - throw new OutOfBoundsException(sprintf('The argument "%s" doesn\'t exist in class "%s".', $index, $this->class)); - } - - return $this->arguments[$index]; - } - - /** - * Sets the methods to call after service initialization. - * - * @return $this - */ - public function setMethodCalls(array $calls = []) - { - $this->calls = []; - foreach ($calls as $call) { - $this->addMethodCall($call[0], $call[1], $call[2] ?? false); - } - - return $this; - } - - /** - * Adds a method to call after service initialization. - * - * @param string $method The method name to call - * @param array $arguments An array of arguments to pass to the method call - * @param bool $returnsClone Whether the call returns the service instance or not - * - * @return $this - * - * @throws InvalidArgumentException on empty $method param - */ - public function addMethodCall(string $method, array $arguments = [], bool $returnsClone = false) - { - if (empty($method)) { - throw new InvalidArgumentException('Method name cannot be empty.'); - } - $this->calls[] = $returnsClone ? [$method, $arguments, true] : [$method, $arguments]; - - return $this; - } - - /** - * Removes a method to call after service initialization. - * - * @return $this - */ - public function removeMethodCall(string $method) - { - foreach ($this->calls as $i => $call) { - if ($call[0] === $method) { - unset($this->calls[$i]); - } - } - - return $this; - } - - /** - * Check if the current definition has a given method to call after service initialization. - * - * @return bool - */ - public function hasMethodCall(string $method) - { - foreach ($this->calls as $call) { - if ($call[0] === $method) { - return true; - } - } - - return false; - } - - /** - * Gets the methods to call after service initialization. - * - * @return array - */ - public function getMethodCalls() - { - return $this->calls; - } - - /** - * Sets the definition templates to conditionally apply on the current definition, keyed by parent interface/class. - * - * @param ChildDefinition[] $instanceof - * - * @return $this - */ - public function setInstanceofConditionals(array $instanceof) - { - $this->instanceof = $instanceof; - - return $this; - } - - /** - * Gets the definition templates to conditionally apply on the current definition, keyed by parent interface/class. - * - * @return ChildDefinition[] - */ - public function getInstanceofConditionals() - { - return $this->instanceof; - } - - /** - * Sets whether or not instanceof conditionals should be prepended with a global set. - * - * @return $this - */ - public function setAutoconfigured(bool $autoconfigured) - { - $this->changes['autoconfigured'] = true; - - $this->autoconfigured = $autoconfigured; - - return $this; - } - - /** - * @return bool - */ - public function isAutoconfigured() - { - return $this->autoconfigured; - } - - /** - * Sets tags for this definition. - * - * @return $this - */ - public function setTags(array $tags) - { - $this->tags = $tags; - - return $this; - } - - /** - * Returns all tags. - * - * @return array - */ - public function getTags() - { - return $this->tags; - } - - /** - * Gets a tag by name. - * - * @return array - */ - public function getTag(string $name) - { - return $this->tags[$name] ?? []; - } - - /** - * Adds a tag for this definition. - * - * @return $this - */ - public function addTag(string $name, array $attributes = []) - { - $this->tags[$name][] = $attributes; - - return $this; - } - - /** - * Whether this definition has a tag with the given name. - * - * @return bool - */ - public function hasTag(string $name) - { - return isset($this->tags[$name]); - } - - /** - * Clears all tags for a given name. - * - * @return $this - */ - public function clearTag(string $name) - { - unset($this->tags[$name]); - - return $this; - } - - /** - * Clears the tags for this definition. - * - * @return $this - */ - public function clearTags() - { - $this->tags = []; - - return $this; - } - - /** - * Sets a file to require before creating the service. - * - * @return $this - */ - public function setFile(?string $file) - { - $this->changes['file'] = true; - - $this->file = $file; - - return $this; - } - - /** - * Gets the file to require before creating the service. - * - * @return string|null - */ - public function getFile() - { - return $this->file; - } - - /** - * Sets if the service must be shared or not. - * - * @return $this - */ - public function setShared(bool $shared) - { - $this->changes['shared'] = true; - - $this->shared = $shared; - - return $this; - } - - /** - * Whether this service is shared. - * - * @return bool - */ - public function isShared() - { - return $this->shared; - } - - /** - * Sets the visibility of this service. - * - * @return $this - */ - public function setPublic(bool $boolean) - { - $this->changes['public'] = true; - - $this->public = $boolean; - - return $this; - } - - /** - * Whether this service is public facing. - * - * @return bool - */ - public function isPublic() - { - return $this->public; - } - - /** - * Sets if this service is private. - * - * @return $this - * - * @deprecated since Symfony 5.2, use setPublic() instead - */ - public function setPrivate(bool $boolean) - { - trigger_deprecation('symfony/dependency-injection', '5.2', 'The "%s()" method is deprecated, use "setPublic()" instead.', __METHOD__); - - return $this->setPublic(!$boolean); - } - - /** - * Whether this service is private. - * - * @return bool - */ - public function isPrivate() - { - return !$this->public; - } - - /** - * Sets the lazy flag of this service. - * - * @return $this - */ - public function setLazy(bool $lazy) - { - $this->changes['lazy'] = true; - - $this->lazy = $lazy; - - return $this; - } - - /** - * Whether this service is lazy. - * - * @return bool - */ - public function isLazy() - { - return $this->lazy; - } - - /** - * Sets whether this definition is synthetic, that is not constructed by the - * container, but dynamically injected. - * - * @return $this - */ - public function setSynthetic(bool $boolean) - { - $this->synthetic = $boolean; - - if (!isset($this->changes['public'])) { - $this->setPublic(true); - } - - return $this; - } - - /** - * Whether this definition is synthetic, that is not constructed by the - * container, but dynamically injected. - * - * @return bool - */ - public function isSynthetic() - { - return $this->synthetic; - } - - /** - * Whether this definition is abstract, that means it merely serves as a - * template for other definitions. - * - * @return $this - */ - public function setAbstract(bool $boolean) - { - $this->abstract = $boolean; - - return $this; - } - - /** - * Whether this definition is abstract, that means it merely serves as a - * template for other definitions. - * - * @return bool - */ - public function isAbstract() - { - return $this->abstract; - } - - /** - * Whether this definition is deprecated, that means it should not be called - * anymore. - * - * @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 deprecation message to use - * - * @return $this - * - * @throws InvalidArgumentException when the message template is invalid - */ - public function setDeprecated(/* string $package, string $version, string $message */) - { - $args = \func_get_args(); - - if (\func_num_args() < 3) { - trigger_deprecation('symfony/dependency-injection', '5.1', 'The signature of method "%s()" requires 3 arguments: "string $package, string $version, string $message", not defining them is deprecated.', __METHOD__); - - $status = $args[0] ?? true; - - if (!$status) { - trigger_deprecation('symfony/dependency-injection', '5.1', 'Passing a null message to un-deprecate a node is deprecated.'); - } - - $message = (string) ($args[1] ?? null); - $package = $version = ''; - } else { - $status = true; - $package = (string) $args[0]; - $version = (string) $args[1]; - $message = (string) $args[2]; - } - - if ('' !== $message) { - if (preg_match('#[\r\n]|\*/#', $message)) { - throw new InvalidArgumentException('Invalid characters found in deprecation template.'); - } - - if (!str_contains($message, '%service_id%')) { - throw new InvalidArgumentException('The deprecation template must contain the "%service_id%" placeholder.'); - } - } - - $this->changes['deprecated'] = true; - $this->deprecation = $status ? ['package' => $package, 'version' => $version, 'message' => $message ?: self::DEFAULT_DEPRECATION_TEMPLATE] : []; - - return $this; - } - - /** - * Whether this definition is deprecated, that means it should not be called - * anymore. - * - * @return bool - */ - public function isDeprecated() - { - return (bool) $this->deprecation; - } - - /** - * Message to use if this definition is deprecated. - * - * @deprecated since Symfony 5.1, use "getDeprecation()" instead. - * - * @param string $id Service id relying on this definition - * - * @return string - */ - public function getDeprecationMessage(string $id) - { - trigger_deprecation('symfony/dependency-injection', '5.1', 'The "%s()" method is deprecated, use "getDeprecation()" instead.', __METHOD__); - - return $this->getDeprecation($id)['message']; - } - - /** - * @param string $id Service id relying on this definition - */ - public function getDeprecation(string $id): array - { - return [ - 'package' => $this->deprecation['package'], - 'version' => $this->deprecation['version'], - 'message' => str_replace('%service_id%', $id, $this->deprecation['message']), - ]; - } - - /** - * Sets a configurator to call after the service is fully initialized. - * - * @param string|array|Reference|null $configurator A PHP function, reference or an array containing a class/Reference and a method to call - * - * @return $this - */ - public function setConfigurator($configurator) - { - $this->changes['configurator'] = true; - - if (\is_string($configurator) && str_contains($configurator, '::')) { - $configurator = explode('::', $configurator, 2); - } elseif ($configurator instanceof Reference) { - $configurator = [$configurator, '__invoke']; - } - - $this->configurator = $configurator; - - return $this; - } - - /** - * Gets the configurator to call after the service is fully initialized. - * - * @return string|array|null - */ - public function getConfigurator() - { - return $this->configurator; - } - - /** - * Is the definition autowired? - * - * @return bool - */ - public function isAutowired() - { - return $this->autowired; - } - - /** - * Enables/disables autowiring. - * - * @return $this - */ - public function setAutowired(bool $autowired) - { - $this->changes['autowired'] = true; - - $this->autowired = $autowired; - - return $this; - } - - /** - * Gets bindings. - * - * @return BoundArgument[] - */ - public function getBindings() - { - return $this->bindings; - } - - /** - * Sets bindings. - * - * Bindings map $named or FQCN arguments to values that should be - * injected in the matching parameters (of the constructor, of methods - * called and of controller actions). - * - * @return $this - */ - public function setBindings(array $bindings) - { - foreach ($bindings as $key => $binding) { - if (0 < strpos($key, '$') && $key !== $k = preg_replace('/[ \t]*\$/', ' $', $key)) { - unset($bindings[$key]); - $bindings[$key = $k] = $binding; - } - if (!$binding instanceof BoundArgument) { - $bindings[$key] = new BoundArgument($binding); - } - } - - $this->bindings = $bindings; - - return $this; - } - - /** - * Add an error that occurred when building this Definition. - * - * @param string|\Closure|self $error - * - * @return $this - */ - public function addError($error) - { - if ($error instanceof self) { - $this->errors = array_merge($this->errors, $error->errors); - } else { - $this->errors[] = $error; - } - - return $this; - } - - /** - * Returns any errors that occurred while building this Definition. - * - * @return array - */ - public function getErrors() - { - foreach ($this->errors as $i => $error) { - if ($error instanceof \Closure) { - $this->errors[$i] = (string) $error(); - } elseif (!\is_string($error)) { - $this->errors[$i] = (string) $error; - } - } - - return $this->errors; - } - - public function hasErrors(): bool - { - return (bool) $this->errors; - } -} diff --git a/lib/symfony/dependency-injection/Dumper/Dumper.php b/lib/symfony/dependency-injection/Dumper/Dumper.php deleted file mode 100644 index e7407b0e2..000000000 --- a/lib/symfony/dependency-injection/Dumper/Dumper.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Dumper; - -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * Dumper is the abstract class for all built-in dumpers. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -abstract class Dumper implements DumperInterface -{ - protected $container; - - public function __construct(ContainerBuilder $container) - { - $this->container = $container; - } -} diff --git a/lib/symfony/dependency-injection/Dumper/DumperInterface.php b/lib/symfony/dependency-injection/Dumper/DumperInterface.php deleted file mode 100644 index a00f30bf1..000000000 --- a/lib/symfony/dependency-injection/Dumper/DumperInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Dumper; - -/** - * DumperInterface is the interface implemented by service container dumper classes. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface DumperInterface -{ - /** - * Dumps the service container. - * - * @return string|array - */ - public function dump(array $options = []); -} diff --git a/lib/symfony/dependency-injection/Dumper/GraphvizDumper.php b/lib/symfony/dependency-injection/Dumper/GraphvizDumper.php deleted file mode 100644 index e8ca83834..000000000 --- a/lib/symfony/dependency-injection/Dumper/GraphvizDumper.php +++ /dev/null @@ -1,251 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Dumper; - -use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; -use Symfony\Component\DependencyInjection\Parameter; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; -use Symfony\Component\DependencyInjection\Reference; - -/** - * GraphvizDumper dumps a service container as a graphviz file. - * - * You can convert the generated dot file with the dot utility (http://www.graphviz.org/): - * - * dot -Tpng container.dot > foo.png - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class GraphvizDumper extends Dumper -{ - private $nodes; - private $edges; - // All values should be strings - private $options = [ - 'graph' => ['ratio' => 'compress'], - 'node' => ['fontsize' => '11', 'fontname' => 'Arial', 'shape' => 'record'], - 'edge' => ['fontsize' => '9', 'fontname' => 'Arial', 'color' => 'grey', 'arrowhead' => 'open', 'arrowsize' => '0.5'], - 'node.instance' => ['fillcolor' => '#9999ff', 'style' => 'filled'], - 'node.definition' => ['fillcolor' => '#eeeeee'], - 'node.missing' => ['fillcolor' => '#ff9999', 'style' => 'filled'], - ]; - - /** - * Dumps the service container as a graphviz graph. - * - * Available options: - * - * * graph: The default options for the whole graph - * * node: The default options for nodes - * * edge: The default options for edges - * * node.instance: The default options for services that are defined directly by object instances - * * node.definition: The default options for services that are defined via service definition instances - * * node.missing: The default options for missing services - * - * @return string - */ - public function dump(array $options = []) - { - foreach (['graph', 'node', 'edge', 'node.instance', 'node.definition', 'node.missing'] as $key) { - if (isset($options[$key])) { - $this->options[$key] = array_merge($this->options[$key], $options[$key]); - } - } - - $this->nodes = $this->findNodes(); - - $this->edges = []; - foreach ($this->container->getDefinitions() as $id => $definition) { - $this->edges[$id] = array_merge( - $this->findEdges($id, $definition->getArguments(), true, ''), - $this->findEdges($id, $definition->getProperties(), false, '') - ); - - foreach ($definition->getMethodCalls() as $call) { - $this->edges[$id] = array_merge( - $this->edges[$id], - $this->findEdges($id, $call[1], false, $call[0].'()') - ); - } - } - - return $this->container->resolveEnvPlaceholders($this->startDot().$this->addNodes().$this->addEdges().$this->endDot(), '__ENV_%s__'); - } - - private function addNodes(): string - { - $code = ''; - foreach ($this->nodes as $id => $node) { - $aliases = $this->getAliases($id); - - $code .= sprintf(" node_%s [label=\"%s\\n%s\\n\", shape=%s%s];\n", $this->dotize($id), $id.($aliases ? ' ('.implode(', ', $aliases).')' : ''), $node['class'], $this->options['node']['shape'], $this->addAttributes($node['attributes'])); - } - - return $code; - } - - private function addEdges(): string - { - $code = ''; - foreach ($this->edges as $id => $edges) { - foreach ($edges as $edge) { - $code .= sprintf(" node_%s -> node_%s [label=\"%s\" style=\"%s\"%s];\n", $this->dotize($id), $this->dotize($edge['to']), $edge['name'], $edge['required'] ? 'filled' : 'dashed', $edge['lazy'] ? ' color="#9999ff"' : ''); - } - } - - return $code; - } - - /** - * Finds all edges belonging to a specific service id. - */ - private function findEdges(string $id, array $arguments, bool $required, string $name, bool $lazy = false): array - { - $edges = []; - foreach ($arguments as $argument) { - if ($argument instanceof Parameter) { - $argument = $this->container->hasParameter($argument) ? $this->container->getParameter($argument) : null; - } elseif (\is_string($argument) && preg_match('/^%([^%]+)%$/', $argument, $match)) { - $argument = $this->container->hasParameter($match[1]) ? $this->container->getParameter($match[1]) : null; - } - - if ($argument instanceof Reference) { - $lazyEdge = $lazy; - - if (!$this->container->has((string) $argument)) { - $this->nodes[(string) $argument] = ['name' => $name, 'required' => $required, 'class' => '', 'attributes' => $this->options['node.missing']]; - } elseif ('service_container' !== (string) $argument) { - $lazyEdge = $lazy || $this->container->getDefinition((string) $argument)->isLazy(); - } - - $edges[] = [['name' => $name, 'required' => $required, 'to' => $argument, 'lazy' => $lazyEdge]]; - } elseif ($argument instanceof ArgumentInterface) { - $edges[] = $this->findEdges($id, $argument->getValues(), $required, $name, true); - } elseif ($argument instanceof Definition) { - $edges[] = $this->findEdges($id, $argument->getArguments(), $required, ''); - $edges[] = $this->findEdges($id, $argument->getProperties(), false, ''); - - foreach ($argument->getMethodCalls() as $call) { - $edges[] = $this->findEdges($id, $call[1], false, $call[0].'()'); - } - } elseif (\is_array($argument)) { - $edges[] = $this->findEdges($id, $argument, $required, $name, $lazy); - } - } - - return array_merge([], ...$edges); - } - - private function findNodes(): array - { - $nodes = []; - - $container = $this->cloneContainer(); - - foreach ($container->getDefinitions() as $id => $definition) { - $class = $definition->getClass(); - - if ('\\' === substr($class, 0, 1)) { - $class = substr($class, 1); - } - - try { - $class = $this->container->getParameterBag()->resolveValue($class); - } catch (ParameterNotFoundException $e) { - } - - $nodes[$id] = ['class' => str_replace('\\', '\\\\', $class), 'attributes' => array_merge($this->options['node.definition'], ['style' => $definition->isShared() ? 'filled' : 'dotted'])]; - $container->setDefinition($id, new Definition('stdClass')); - } - - foreach ($container->getServiceIds() as $id) { - if (\array_key_exists($id, $container->getAliases())) { - continue; - } - - if (!$container->hasDefinition($id)) { - $nodes[$id] = ['class' => str_replace('\\', '\\\\', \get_class($container->get($id))), 'attributes' => $this->options['node.instance']]; - } - } - - return $nodes; - } - - private function cloneContainer(): ContainerBuilder - { - $parameterBag = new ParameterBag($this->container->getParameterBag()->all()); - - $container = new ContainerBuilder($parameterBag); - $container->setDefinitions($this->container->getDefinitions()); - $container->setAliases($this->container->getAliases()); - $container->setResources($this->container->getResources()); - foreach ($this->container->getExtensions() as $extension) { - $container->registerExtension($extension); - } - - return $container; - } - - private function startDot(): string - { - return sprintf("digraph sc {\n %s\n node [%s];\n edge [%s];\n\n", - $this->addOptions($this->options['graph']), - $this->addOptions($this->options['node']), - $this->addOptions($this->options['edge']) - ); - } - - private function endDot(): string - { - return "}\n"; - } - - private function addAttributes(array $attributes): string - { - $code = []; - foreach ($attributes as $k => $v) { - $code[] = sprintf('%s="%s"', $k, $v); - } - - return $code ? ', '.implode(', ', $code) : ''; - } - - private function addOptions(array $options): string - { - $code = []; - foreach ($options as $k => $v) { - $code[] = sprintf('%s="%s"', $k, $v); - } - - return implode(' ', $code); - } - - private function dotize(string $id): string - { - return preg_replace('/\W/i', '_', $id); - } - - private function getAliases(string $id): array - { - $aliases = []; - foreach ($this->container->getAliases() as $alias => $origin) { - if ($id == $origin) { - $aliases[] = $alias; - } - } - - return $aliases; - } -} diff --git a/lib/symfony/dependency-injection/Dumper/PhpDumper.php b/lib/symfony/dependency-injection/Dumper/PhpDumper.php deleted file mode 100644 index bd63d0689..000000000 --- a/lib/symfony/dependency-injection/Dumper/PhpDumper.php +++ /dev/null @@ -1,2261 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Dumper; - -use Composer\Autoload\ClassLoader; -use Symfony\Component\Debug\DebugClassLoader as LegacyDebugClassLoader; -use Symfony\Component\DependencyInjection\Argument\AbstractArgument; -use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceLocator; -use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass; -use Symfony\Component\DependencyInjection\Compiler\CheckCircularReferencesPass; -use Symfony\Component\DependencyInjection\Compiler\ServiceReferenceGraphNode; -use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\EnvParameterException; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\LogicException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; -use Symfony\Component\DependencyInjection\ExpressionLanguage; -use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface as ProxyDumper; -use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper; -use Symfony\Component\DependencyInjection\Loader\FileLoader; -use Symfony\Component\DependencyInjection\Parameter; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\ServiceLocator as BaseServiceLocator; -use Symfony\Component\DependencyInjection\TypedReference; -use Symfony\Component\DependencyInjection\Variable; -use Symfony\Component\ErrorHandler\DebugClassLoader; -use Symfony\Component\ExpressionLanguage\Expression; -use Symfony\Component\HttpKernel\Kernel; - -/** - * PhpDumper dumps a service container as a PHP class. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class PhpDumper extends Dumper -{ - /** - * Characters that might appear in the generated variable name as first character. - */ - public const FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz'; - - /** - * Characters that might appear in the generated variable name as any but the first character. - */ - public const NON_FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz0123456789_'; - - /** - * @var \SplObjectStorage<Definition, Variable>|null - */ - private $definitionVariables; - private $referenceVariables; - private $variableCount; - private $inlinedDefinitions; - private $serviceCalls; - private $reservedVariables = ['instance', 'class', 'this', 'container']; - private $expressionLanguage; - private $targetDirRegex; - private $targetDirMaxMatches; - private $docStar; - private $serviceIdToMethodNameMap; - private $usedMethodNames; - private $namespace; - private $asFiles; - private $hotPathTag; - private $preloadTags; - private $inlineFactories; - private $inlineRequires; - private $inlinedRequires = []; - private $circularReferences = []; - private $singleUsePrivateIds = []; - private $preload = []; - private $addThrow = false; - private $addGetService = false; - private $locatedIds = []; - private $serviceLocatorTag; - private $exportedVariables = []; - private $baseClass; - - /** - * @var ProxyDumper - */ - private $proxyDumper; - - /** - * {@inheritdoc} - */ - public function __construct(ContainerBuilder $container) - { - if (!$container->isCompiled()) { - throw new LogicException('Cannot dump an uncompiled container.'); - } - - parent::__construct($container); - } - - /** - * Sets the dumper to be used when dumping proxies in the generated container. - */ - public function setProxyDumper(ProxyDumper $proxyDumper) - { - $this->proxyDumper = $proxyDumper; - } - - /** - * Dumps the service container as a PHP class. - * - * Available options: - * - * * class: The class name - * * base_class: The base class name - * * namespace: The class namespace - * * as_files: To split the container in several files - * - * @return string|array A PHP class representing the service container or an array of PHP files if the "as_files" option is set - * - * @throws EnvParameterException When an env var exists but has not been dumped - */ - public function dump(array $options = []) - { - $this->locatedIds = []; - $this->targetDirRegex = null; - $this->inlinedRequires = []; - $this->exportedVariables = []; - $options = array_merge([ - 'class' => 'ProjectServiceContainer', - 'base_class' => 'Container', - 'namespace' => '', - 'as_files' => false, - 'debug' => true, - 'hot_path_tag' => 'container.hot_path', - 'preload_tags' => ['container.preload', 'container.no_preload'], - 'inline_factories_parameter' => 'container.dumper.inline_factories', - 'inline_class_loader_parameter' => 'container.dumper.inline_class_loader', - 'preload_classes' => [], - 'service_locator_tag' => 'container.service_locator', - 'build_time' => time(), - ], $options); - - $this->addThrow = $this->addGetService = false; - $this->namespace = $options['namespace']; - $this->asFiles = $options['as_files']; - $this->hotPathTag = $options['hot_path_tag']; - $this->preloadTags = $options['preload_tags']; - $this->inlineFactories = $this->asFiles && $options['inline_factories_parameter'] && $this->container->hasParameter($options['inline_factories_parameter']) && $this->container->getParameter($options['inline_factories_parameter']); - $this->inlineRequires = $options['inline_class_loader_parameter'] && ($this->container->hasParameter($options['inline_class_loader_parameter']) ? $this->container->getParameter($options['inline_class_loader_parameter']) : (\PHP_VERSION_ID < 70400 || $options['debug'])); - $this->serviceLocatorTag = $options['service_locator_tag']; - - if (!str_starts_with($baseClass = $options['base_class'], '\\') && 'Container' !== $baseClass) { - $baseClass = sprintf('%s\%s', $options['namespace'] ? '\\'.$options['namespace'] : '', $baseClass); - $this->baseClass = $baseClass; - } elseif ('Container' === $baseClass) { - $this->baseClass = Container::class; - } else { - $this->baseClass = $baseClass; - } - - $this->initializeMethodNamesMap('Container' === $baseClass ? Container::class : $baseClass); - - if ($this->getProxyDumper() instanceof NullDumper) { - (new AnalyzeServiceReferencesPass(true, false))->process($this->container); - try { - (new CheckCircularReferencesPass())->process($this->container); - } catch (ServiceCircularReferenceException $e) { - $path = $e->getPath(); - end($path); - $path[key($path)] .= '". Try running "composer require symfony/proxy-manager-bridge'; - - throw new ServiceCircularReferenceException($e->getServiceId(), $path); - } - } - - $this->analyzeReferences(); - $this->docStar = $options['debug'] ? '*' : ''; - - if (!empty($options['file']) && is_dir($dir = \dirname($options['file']))) { - // Build a regexp where the first root dirs are mandatory, - // but every other sub-dir is optional up to the full path in $dir - // Mandate at least 1 root dir and not more than 5 optional dirs. - - $dir = explode(\DIRECTORY_SEPARATOR, realpath($dir)); - $i = \count($dir); - - if (2 + (int) ('\\' === \DIRECTORY_SEPARATOR) <= $i) { - $regex = ''; - $lastOptionalDir = $i > 8 ? $i - 5 : (2 + (int) ('\\' === \DIRECTORY_SEPARATOR)); - $this->targetDirMaxMatches = $i - $lastOptionalDir; - - while (--$i >= $lastOptionalDir) { - $regex = sprintf('(%s%s)?', preg_quote(\DIRECTORY_SEPARATOR.$dir[$i], '#'), $regex); - } - - do { - $regex = preg_quote(\DIRECTORY_SEPARATOR.$dir[$i], '#').$regex; - } while (0 < --$i); - - $this->targetDirRegex = '#(^|file://|[:;, \|\r\n])'.preg_quote($dir[0], '#').$regex.'#'; - } - } - - $proxyClasses = $this->inlineFactories ? $this->generateProxyClasses() : null; - - if ($options['preload_classes']) { - $this->preload = array_combine($options['preload_classes'], $options['preload_classes']); - } - - $code = - $this->startClass($options['class'], $baseClass, $this->inlineFactories && $proxyClasses). - $this->addServices($services). - $this->addDeprecatedAliases(). - $this->addDefaultParametersMethod() - ; - - $proxyClasses = $proxyClasses ?? $this->generateProxyClasses(); - - if ($this->addGetService) { - $code = preg_replace( - "/(\r?\n\r?\n public function __construct.+?\\{\r?\n)/s", - "\n protected \$getService;$1 \$this->getService = \\Closure::fromCallable([\$this, 'getService']);\n", - $code, - 1 - ); - } - - if ($this->asFiles) { - $fileTemplate = <<<EOF -<?php - -use Symfony\Component\DependencyInjection\Argument\RewindableGenerator; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; - -/*{$this->docStar} - * @internal This class has been auto-generated by the Symfony Dependency Injection Component. - */ -class %s extends {$options['class']} -{%s} - -EOF; - $files = []; - $preloadedFiles = []; - $ids = $this->container->getRemovedIds(); - foreach ($this->container->getDefinitions() as $id => $definition) { - if (!$definition->isPublic()) { - $ids[$id] = true; - } - } - if ($ids = array_keys($ids)) { - sort($ids); - $c = "<?php\n\nreturn [\n"; - foreach ($ids as $id) { - $c .= ' '.$this->doExport($id)." => true,\n"; - } - $files['removed-ids.php'] = $c."];\n"; - } - - if (!$this->inlineFactories) { - foreach ($this->generateServiceFiles($services) as $file => [$c, $preload]) { - $files[$file] = sprintf($fileTemplate, substr($file, 0, -4), $c); - - if ($preload) { - $preloadedFiles[$file] = $file; - } - } - foreach ($proxyClasses as $file => $c) { - $files[$file] = "<?php\n".$c; - $preloadedFiles[$file] = $file; - } - } - - $code .= $this->endClass(); - - if ($this->inlineFactories && $proxyClasses) { - $files['proxy-classes.php'] = "<?php\n\n"; - - foreach ($proxyClasses as $c) { - $files['proxy-classes.php'] .= $c; - } - } - - $files[$options['class'].'.php'] = $code; - $hash = ucfirst(strtr(ContainerBuilder::hash($files), '._', 'xx')); - $code = []; - - foreach ($files as $file => $c) { - $code["Container{$hash}/{$file}"] = substr_replace($c, "<?php\n\nnamespace Container{$hash};\n", 0, 6); - - if (isset($preloadedFiles[$file])) { - $preloadedFiles[$file] = "Container{$hash}/{$file}"; - } - } - $namespaceLine = $this->namespace ? "\nnamespace {$this->namespace};\n" : ''; - $time = $options['build_time']; - $id = hash('crc32', $hash.$time); - $this->asFiles = false; - - if ($this->preload && null !== $autoloadFile = $this->getAutoloadFile()) { - $autoloadFile = trim($this->export($autoloadFile), '()\\'); - - $preloadedFiles = array_reverse($preloadedFiles); - if ('' !== $preloadedFiles = implode("';\nrequire __DIR__.'/", $preloadedFiles)) { - $preloadedFiles = "require __DIR__.'/$preloadedFiles';\n"; - } - - $code[$options['class'].'.preload.php'] = <<<EOF -<?php - -// This file has been auto-generated by the Symfony Dependency Injection Component -// You can reference it in the "opcache.preload" php.ini setting on PHP >= 7.4 when preloading is desired - -use Symfony\Component\DependencyInjection\Dumper\Preloader; - -if (in_array(PHP_SAPI, ['cli', 'phpdbg'], true)) { - return; -} - -require $autoloadFile; -(require __DIR__.'/{$options['class']}.php')->set(\\Container{$hash}\\{$options['class']}::class, null); -$preloadedFiles -\$classes = []; - -EOF; - - foreach ($this->preload as $class) { - if (!$class || str_contains($class, '$') || \in_array($class, ['int', 'float', 'string', 'bool', 'resource', 'object', 'array', 'null', 'callable', 'iterable', 'mixed', 'void'], true)) { - continue; - } - if (!(class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false)) || ((new \ReflectionClass($class))->isUserDefined() && !\in_array($class, ['Attribute', 'JsonException', 'ReturnTypeWillChange', 'Stringable', 'UnhandledMatchError', 'ValueError'], true))) { - $code[$options['class'].'.preload.php'] .= sprintf("\$classes[] = '%s';\n", $class); - } - } - - $code[$options['class'].'.preload.php'] .= <<<'EOF' - -$preloaded = Preloader::preload($classes); - -EOF; - } - - $code[$options['class'].'.php'] = <<<EOF -<?php -{$namespaceLine} -// This file has been auto-generated by the Symfony Dependency Injection Component for internal use. - -if (\\class_exists(\\Container{$hash}\\{$options['class']}::class, false)) { - // no-op -} elseif (!include __DIR__.'/Container{$hash}/{$options['class']}.php') { - touch(__DIR__.'/Container{$hash}.legacy'); - - return; -} - -if (!\\class_exists({$options['class']}::class, false)) { - \\class_alias(\\Container{$hash}\\{$options['class']}::class, {$options['class']}::class, false); -} - -return new \\Container{$hash}\\{$options['class']}([ - 'container.build_hash' => '$hash', - 'container.build_id' => '$id', - 'container.build_time' => $time, -], __DIR__.\\DIRECTORY_SEPARATOR.'Container{$hash}'); - -EOF; - } else { - $code .= $this->endClass(); - foreach ($proxyClasses as $c) { - $code .= $c; - } - } - - $this->targetDirRegex = null; - $this->inlinedRequires = []; - $this->circularReferences = []; - $this->locatedIds = []; - $this->exportedVariables = []; - $this->preload = []; - - $unusedEnvs = []; - foreach ($this->container->getEnvCounters() as $env => $use) { - if (!$use) { - $unusedEnvs[] = $env; - } - } - if ($unusedEnvs) { - throw new EnvParameterException($unusedEnvs, null, 'Environment variables "%s" are never used. Please, check your container\'s configuration.'); - } - - return $code; - } - - /** - * Retrieves the currently set proxy dumper or instantiates one. - */ - private function getProxyDumper(): ProxyDumper - { - if (!$this->proxyDumper) { - $this->proxyDumper = new NullDumper(); - } - - return $this->proxyDumper; - } - - private function analyzeReferences() - { - (new AnalyzeServiceReferencesPass(false, !$this->getProxyDumper() instanceof NullDumper))->process($this->container); - $checkedNodes = []; - $this->circularReferences = []; - $this->singleUsePrivateIds = []; - foreach ($this->container->getCompiler()->getServiceReferenceGraph()->getNodes() as $id => $node) { - if (!$node->getValue() instanceof Definition) { - continue; - } - - if ($this->isSingleUsePrivateNode($node)) { - $this->singleUsePrivateIds[$id] = $id; - } - - $this->collectCircularReferences($id, $node->getOutEdges(), $checkedNodes); - } - - $this->container->getCompiler()->getServiceReferenceGraph()->clear(); - $this->singleUsePrivateIds = array_diff_key($this->singleUsePrivateIds, $this->circularReferences); - } - - private function collectCircularReferences(string $sourceId, array $edges, array &$checkedNodes, array &$loops = [], array $path = [], bool $byConstructor = true): void - { - $path[$sourceId] = $byConstructor; - $checkedNodes[$sourceId] = true; - foreach ($edges as $edge) { - $node = $edge->getDestNode(); - $id = $node->getId(); - if ($sourceId === $id || !$node->getValue() instanceof Definition || $edge->isLazy() || $edge->isWeak()) { - continue; - } - - if (isset($path[$id])) { - $loop = null; - $loopByConstructor = $edge->isReferencedByConstructor(); - $pathInLoop = [$id, []]; - foreach ($path as $k => $pathByConstructor) { - if (null !== $loop) { - $loop[] = $k; - $pathInLoop[1][$k] = $pathByConstructor; - $loops[$k][] = &$pathInLoop; - $loopByConstructor = $loopByConstructor && $pathByConstructor; - } elseif ($k === $id) { - $loop = []; - } - } - $this->addCircularReferences($id, $loop, $loopByConstructor); - } elseif (!isset($checkedNodes[$id])) { - $this->collectCircularReferences($id, $node->getOutEdges(), $checkedNodes, $loops, $path, $edge->isReferencedByConstructor()); - } elseif (isset($loops[$id])) { - // we already had detected loops for this edge - // let's check if we have a common ancestor in one of the detected loops - foreach ($loops[$id] as [$first, $loopPath]) { - if (!isset($path[$first])) { - continue; - } - // We have a common ancestor, let's fill the current path - $fillPath = null; - foreach ($loopPath as $k => $pathByConstructor) { - if (null !== $fillPath) { - $fillPath[$k] = $pathByConstructor; - } elseif ($k === $id) { - $fillPath = $path; - $fillPath[$k] = $pathByConstructor; - } - } - - // we can now build the loop - $loop = null; - $loopByConstructor = $edge->isReferencedByConstructor(); - foreach ($fillPath as $k => $pathByConstructor) { - if (null !== $loop) { - $loop[] = $k; - $loopByConstructor = $loopByConstructor && $pathByConstructor; - } elseif ($k === $first) { - $loop = []; - } - } - $this->addCircularReferences($first, $loop, true); - break; - } - } - } - unset($path[$sourceId]); - } - - private function addCircularReferences(string $sourceId, array $currentPath, bool $byConstructor) - { - $currentId = $sourceId; - $currentPath = array_reverse($currentPath); - $currentPath[] = $currentId; - foreach ($currentPath as $parentId) { - if (empty($this->circularReferences[$parentId][$currentId])) { - $this->circularReferences[$parentId][$currentId] = $byConstructor; - } - - $currentId = $parentId; - } - } - - private function collectLineage(string $class, array &$lineage) - { - if (isset($lineage[$class])) { - return; - } - if (!$r = $this->container->getReflectionClass($class, false)) { - return; - } - if (is_a($class, $this->baseClass, true)) { - return; - } - $file = $r->getFileName(); - if (str_ends_with($file, ') : eval()\'d code')) { - $file = substr($file, 0, strrpos($file, '(', -17)); - } - if (!$file || $this->doExport($file) === $exportedFile = $this->export($file)) { - return; - } - - $lineage[$class] = substr($exportedFile, 1, -1); - - if ($parent = $r->getParentClass()) { - $this->collectLineage($parent->name, $lineage); - } - - foreach ($r->getInterfaces() as $parent) { - $this->collectLineage($parent->name, $lineage); - } - - foreach ($r->getTraits() as $parent) { - $this->collectLineage($parent->name, $lineage); - } - - unset($lineage[$class]); - $lineage[$class] = substr($exportedFile, 1, -1); - } - - private function generateProxyClasses(): array - { - $proxyClasses = []; - $alreadyGenerated = []; - $definitions = $this->container->getDefinitions(); - $strip = '' === $this->docStar && method_exists(Kernel::class, 'stripComments'); - $proxyDumper = $this->getProxyDumper(); - ksort($definitions); - foreach ($definitions as $definition) { - if (!$proxyDumper->isProxyCandidate($definition)) { - continue; - } - if (isset($alreadyGenerated[$class = $definition->getClass()])) { - continue; - } - $alreadyGenerated[$class] = true; - // register class' reflector for resource tracking - $this->container->getReflectionClass($class); - if ("\n" === $proxyCode = "\n".$proxyDumper->getProxyCode($definition)) { - continue; - } - - if ($this->inlineRequires) { - $lineage = []; - $this->collectLineage($class, $lineage); - - $code = ''; - foreach (array_diff_key(array_flip($lineage), $this->inlinedRequires) as $file => $class) { - if ($this->inlineFactories) { - $this->inlinedRequires[$file] = true; - } - $code .= sprintf("include_once %s;\n", $file); - } - - $proxyCode = $code.$proxyCode; - } - - if ($strip) { - $proxyCode = "<?php\n".$proxyCode; - $proxyCode = substr(Kernel::stripComments($proxyCode), 5); - } - - $proxyClass = explode(' ', $this->inlineRequires ? substr($proxyCode, \strlen($code)) : $proxyCode, 3)[1]; - - if ($this->asFiles || $this->namespace) { - $proxyCode .= "\nif (!\\class_exists('$proxyClass', false)) {\n \\class_alias(__NAMESPACE__.'\\\\$proxyClass', '$proxyClass', false);\n}\n"; - } - - $proxyClasses[$proxyClass.'.php'] = $proxyCode; - } - - return $proxyClasses; - } - - private function addServiceInclude(string $cId, Definition $definition): string - { - $code = ''; - - if ($this->inlineRequires && (!$this->isHotPath($definition) || $this->getProxyDumper()->isProxyCandidate($definition))) { - $lineage = []; - foreach ($this->inlinedDefinitions as $def) { - if (!$def->isDeprecated()) { - foreach ($this->getClasses($def, $cId) as $class) { - $this->collectLineage($class, $lineage); - } - } - } - - foreach ($this->serviceCalls as $id => [$callCount, $behavior]) { - if ('service_container' !== $id && $id !== $cId - && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE !== $behavior - && $this->container->has($id) - && $this->isTrivialInstance($def = $this->container->findDefinition($id)) - ) { - foreach ($this->getClasses($def, $cId) as $class) { - $this->collectLineage($class, $lineage); - } - } - } - - foreach (array_diff_key(array_flip($lineage), $this->inlinedRequires) as $file => $class) { - $code .= sprintf(" include_once %s;\n", $file); - } - } - - foreach ($this->inlinedDefinitions as $def) { - if ($file = $def->getFile()) { - $file = $this->dumpValue($file); - $file = '(' === $file[0] ? substr($file, 1, -1) : $file; - $code .= sprintf(" include_once %s;\n", $file); - } - } - - if ('' !== $code) { - $code .= "\n"; - } - - return $code; - } - - /** - * @throws InvalidArgumentException - * @throws RuntimeException - */ - private function addServiceInstance(string $id, Definition $definition, bool $isSimpleInstance): string - { - $class = $this->dumpValue($definition->getClass()); - - if (str_starts_with($class, "'") && !str_contains($class, '$') && !preg_match('/^\'(?:\\\{2})?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) { - throw new InvalidArgumentException(sprintf('"%s" is not a valid class name for the "%s" service.', $class, $id)); - } - - $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition); - $instantiation = ''; - - $lastWitherIndex = null; - foreach ($definition->getMethodCalls() as $k => $call) { - if ($call[2] ?? false) { - $lastWitherIndex = $k; - } - } - - if (!$isProxyCandidate && $definition->isShared() && !isset($this->singleUsePrivateIds[$id]) && null === $lastWitherIndex) { - $instantiation = sprintf('$this->%s[%s] = %s', $this->container->getDefinition($id)->isPublic() ? 'services' : 'privates', $this->doExport($id), $isSimpleInstance ? '' : '$instance'); - } elseif (!$isSimpleInstance) { - $instantiation = '$instance'; - } - - $return = ''; - if ($isSimpleInstance) { - $return = 'return '; - } else { - $instantiation .= ' = '; - } - - return $this->addNewInstance($definition, ' '.$return.$instantiation, $id); - } - - private function isTrivialInstance(Definition $definition): bool - { - if ($definition->hasErrors()) { - return true; - } - if ($definition->isSynthetic() || $definition->getFile() || $definition->getMethodCalls() || $definition->getProperties() || $definition->getConfigurator()) { - return false; - } - if ($definition->isDeprecated() || $definition->isLazy() || $definition->getFactory() || 3 < \count($definition->getArguments())) { - return false; - } - - foreach ($definition->getArguments() as $arg) { - if (!$arg || $arg instanceof Parameter) { - continue; - } - if (\is_array($arg) && 3 >= \count($arg)) { - foreach ($arg as $k => $v) { - if ($this->dumpValue($k) !== $this->dumpValue($k, false)) { - return false; - } - if (!$v || $v instanceof Parameter) { - continue; - } - if ($v instanceof Reference && $this->container->has($id = (string) $v) && $this->container->findDefinition($id)->isSynthetic()) { - continue; - } - if (!\is_scalar($v) || $this->dumpValue($v) !== $this->dumpValue($v, false)) { - return false; - } - } - } elseif ($arg instanceof Reference && $this->container->has($id = (string) $arg) && $this->container->findDefinition($id)->isSynthetic()) { - continue; - } elseif (!\is_scalar($arg) || $this->dumpValue($arg) !== $this->dumpValue($arg, false)) { - return false; - } - } - - return true; - } - - private function addServiceMethodCalls(Definition $definition, string $variableName, ?string $sharedNonLazyId): string - { - $lastWitherIndex = null; - foreach ($definition->getMethodCalls() as $k => $call) { - if ($call[2] ?? false) { - $lastWitherIndex = $k; - } - } - - $calls = ''; - foreach ($definition->getMethodCalls() as $k => $call) { - $arguments = []; - foreach ($call[1] as $i => $value) { - $arguments[] = (\is_string($i) ? $i.': ' : '').$this->dumpValue($value); - } - - $witherAssignation = ''; - - if ($call[2] ?? false) { - if (null !== $sharedNonLazyId && $lastWitherIndex === $k) { - $witherAssignation = sprintf('$this->%s[\'%s\'] = ', $definition->isPublic() ? 'services' : 'privates', $sharedNonLazyId); - } - $witherAssignation .= sprintf('$%s = ', $variableName); - } - - $calls .= $this->wrapServiceConditionals($call[1], sprintf(" %s\$%s->%s(%s);\n", $witherAssignation, $variableName, $call[0], implode(', ', $arguments))); - } - - return $calls; - } - - private function addServiceProperties(Definition $definition, string $variableName = 'instance'): string - { - $code = ''; - foreach ($definition->getProperties() as $name => $value) { - $code .= sprintf(" \$%s->%s = %s;\n", $variableName, $name, $this->dumpValue($value)); - } - - return $code; - } - - private function addServiceConfigurator(Definition $definition, string $variableName = 'instance'): string - { - if (!$callable = $definition->getConfigurator()) { - return ''; - } - - if (\is_array($callable)) { - if ($callable[0] instanceof Reference - || ($callable[0] instanceof Definition && $this->definitionVariables->contains($callable[0])) - ) { - return sprintf(" %s->%s(\$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName); - } - - $class = $this->dumpValue($callable[0]); - // If the class is a string we can optimize away - if (str_starts_with($class, "'") && !str_contains($class, '$')) { - return sprintf(" %s::%s(\$%s);\n", $this->dumpLiteralClass($class), $callable[1], $variableName); - } - - if (str_starts_with($class, 'new ')) { - return sprintf(" (%s)->%s(\$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName); - } - - return sprintf(" [%s, '%s'](\$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName); - } - - return sprintf(" %s(\$%s);\n", $callable, $variableName); - } - - private function addService(string $id, Definition $definition): array - { - $this->definitionVariables = new \SplObjectStorage(); - $this->referenceVariables = []; - $this->variableCount = 0; - $this->referenceVariables[$id] = new Variable('instance'); - - $return = []; - - if ($class = $definition->getClass()) { - $class = $class instanceof Parameter ? '%'.$class.'%' : $this->container->resolveEnvPlaceholders($class); - $return[] = sprintf(str_starts_with($class, '%') ? '@return object A %1$s instance' : '@return \%s', ltrim($class, '\\')); - } elseif ($definition->getFactory()) { - $factory = $definition->getFactory(); - if (\is_string($factory)) { - $return[] = sprintf('@return object An instance returned by %s()', $factory); - } elseif (\is_array($factory) && (\is_string($factory[0]) || $factory[0] instanceof Definition || $factory[0] instanceof Reference)) { - $class = $factory[0] instanceof Definition ? $factory[0]->getClass() : (string) $factory[0]; - $class = $class instanceof Parameter ? '%'.$class.'%' : $this->container->resolveEnvPlaceholders($class); - $return[] = sprintf('@return object An instance returned by %s::%s()', $class, $factory[1]); - } - } - - if ($definition->isDeprecated()) { - if ($return && str_starts_with($return[\count($return) - 1], '@return')) { - $return[] = ''; - } - - $deprecation = $definition->getDeprecation($id); - $return[] = sprintf('@deprecated %s', ($deprecation['package'] || $deprecation['version'] ? "Since {$deprecation['package']} {$deprecation['version']}: " : '').$deprecation['message']); - } - - $return = str_replace("\n * \n", "\n *\n", implode("\n * ", $return)); - $return = $this->container->resolveEnvPlaceholders($return); - - $shared = $definition->isShared() ? ' shared' : ''; - $public = $definition->isPublic() ? 'public' : 'private'; - $autowired = $definition->isAutowired() ? ' autowired' : ''; - $asFile = $this->asFiles && !$this->inlineFactories && !$this->isHotPath($definition); - $methodName = $this->generateMethodName($id); - - if ($asFile || $definition->isLazy()) { - $lazyInitialization = '$lazyLoad = true'; - } else { - $lazyInitialization = ''; - } - - $code = <<<EOF - - /*{$this->docStar} - * Gets the $public '$id'$shared$autowired service. - * - * $return -EOF; - $code = str_replace('*/', ' ', $code).<<<EOF - - */ - protected function {$methodName}($lazyInitialization) - { - -EOF; - - if ($asFile) { - $file = $methodName.'.php'; - $code = str_replace("protected function {$methodName}(", 'public static function do($container, ', $code); - } else { - $file = null; - } - - if ($definition->hasErrors() && $e = $definition->getErrors()) { - $this->addThrow = true; - - $code .= sprintf(" \$this->throw(%s);\n", $this->export(reset($e))); - } else { - $this->serviceCalls = []; - $this->inlinedDefinitions = $this->getDefinitionsFromArguments([$definition], null, $this->serviceCalls); - - if ($definition->isDeprecated()) { - $deprecation = $definition->getDeprecation($id); - $code .= sprintf(" trigger_deprecation(%s, %s, %s);\n\n", $this->export($deprecation['package']), $this->export($deprecation['version']), $this->export($deprecation['message'])); - } elseif ($definition->hasTag($this->hotPathTag) || !$definition->hasTag($this->preloadTags[1])) { - foreach ($this->inlinedDefinitions as $def) { - foreach ($this->getClasses($def, $id) as $class) { - $this->preload[$class] = $class; - } - } - } - - if (!$definition->isShared()) { - $factory = sprintf('$this->factories%s[%s]', $definition->isPublic() ? '' : "['service_container']", $this->doExport($id)); - } - - if ($isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition)) { - if (!$definition->isShared()) { - $code .= sprintf(' %s = %1$s ?? ', $factory); - - if ($asFile) { - $code .= "function () {\n"; - $code .= " return self::do(\$container);\n"; - $code .= " };\n\n"; - } else { - $code .= sprintf("\\Closure::fromCallable([\$this, '%s']);\n\n", $methodName); - } - } - - $factoryCode = $asFile ? 'self::do($container, false)' : sprintf('$this->%s(false)', $methodName); - $factoryCode = $this->getProxyDumper()->getProxyFactoryCode($definition, $id, $factoryCode); - $code .= $asFile ? preg_replace('/function \(([^)]*+)\)( {|:)/', 'function (\1) use ($container)\2', $factoryCode) : $factoryCode; - } - - $c = $this->addServiceInclude($id, $definition); - - if ('' !== $c && $isProxyCandidate && !$definition->isShared()) { - $c = implode("\n", array_map(function ($line) { return $line ? ' '.$line : $line; }, explode("\n", $c))); - $code .= " static \$include = true;\n\n"; - $code .= " if (\$include) {\n"; - $code .= $c; - $code .= " \$include = false;\n"; - $code .= " }\n\n"; - } else { - $code .= $c; - } - - $c = $this->addInlineService($id, $definition); - - if (!$isProxyCandidate && !$definition->isShared()) { - $c = implode("\n", array_map(function ($line) { return $line ? ' '.$line : $line; }, explode("\n", $c))); - $lazyloadInitialization = $definition->isLazy() ? '$lazyLoad = true' : ''; - - $c = sprintf(" %s = function (%s) {\n%s };\n\n return %1\$s();\n", $factory, $lazyloadInitialization, $c); - } - - $code .= $c; - } - - if ($asFile) { - $code = str_replace('$this', '$container', $code); - $code = preg_replace('/function \(([^)]*+)\)( {|:)/', 'function (\1) use ($container)\2', $code); - } - - $code .= " }\n"; - - $this->definitionVariables = $this->inlinedDefinitions = null; - $this->referenceVariables = $this->serviceCalls = null; - - return [$file, $code]; - } - - private function addInlineVariables(string $id, Definition $definition, array $arguments, bool $forConstructor): string - { - $code = ''; - - foreach ($arguments as $argument) { - if (\is_array($argument)) { - $code .= $this->addInlineVariables($id, $definition, $argument, $forConstructor); - } elseif ($argument instanceof Reference) { - $code .= $this->addInlineReference($id, $definition, $argument, $forConstructor); - } elseif ($argument instanceof Definition) { - $code .= $this->addInlineService($id, $definition, $argument, $forConstructor); - } - } - - return $code; - } - - private function addInlineReference(string $id, Definition $definition, string $targetId, bool $forConstructor): string - { - while ($this->container->hasAlias($targetId)) { - $targetId = (string) $this->container->getAlias($targetId); - } - - [$callCount, $behavior] = $this->serviceCalls[$targetId]; - - if ($id === $targetId) { - return $this->addInlineService($id, $definition, $definition); - } - - if ('service_container' === $targetId || isset($this->referenceVariables[$targetId])) { - return ''; - } - - if ($this->container->hasDefinition($targetId) && ($def = $this->container->getDefinition($targetId)) && !$def->isShared()) { - return ''; - } - - $hasSelfRef = isset($this->circularReferences[$id][$targetId]) && !isset($this->definitionVariables[$definition]); - - if ($hasSelfRef && !$forConstructor && !$forConstructor = !$this->circularReferences[$id][$targetId]) { - $code = $this->addInlineService($id, $definition, $definition); - } else { - $code = ''; - } - - if (isset($this->referenceVariables[$targetId]) || (2 > $callCount && (!$hasSelfRef || !$forConstructor))) { - return $code; - } - - $name = $this->getNextVariableName(); - $this->referenceVariables[$targetId] = new Variable($name); - - $reference = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $behavior ? new Reference($targetId, $behavior) : null; - $code .= sprintf(" \$%s = %s;\n", $name, $this->getServiceCall($targetId, $reference)); - - if (!$hasSelfRef || !$forConstructor) { - return $code; - } - - $code .= sprintf(<<<'EOTXT' - - if (isset($this->%s[%s])) { - return $this->%1$s[%2$s]; - } - -EOTXT - , - $this->container->getDefinition($id)->isPublic() ? 'services' : 'privates', - $this->doExport($id) - ); - - return $code; - } - - private function addInlineService(string $id, Definition $definition, Definition $inlineDef = null, bool $forConstructor = true): string - { - $code = ''; - - if ($isSimpleInstance = $isRootInstance = null === $inlineDef) { - foreach ($this->serviceCalls as $targetId => [$callCount, $behavior, $byConstructor]) { - if ($byConstructor && isset($this->circularReferences[$id][$targetId]) && !$this->circularReferences[$id][$targetId]) { - $code .= $this->addInlineReference($id, $definition, $targetId, $forConstructor); - } - } - } - - if (isset($this->definitionVariables[$inlineDef = $inlineDef ?: $definition])) { - return $code; - } - - $arguments = [$inlineDef->getArguments(), $inlineDef->getFactory()]; - - $code .= $this->addInlineVariables($id, $definition, $arguments, $forConstructor); - - if ($arguments = array_filter([$inlineDef->getProperties(), $inlineDef->getMethodCalls(), $inlineDef->getConfigurator()])) { - $isSimpleInstance = false; - } elseif ($definition !== $inlineDef && 2 > $this->inlinedDefinitions[$inlineDef]) { - return $code; - } - - if (isset($this->definitionVariables[$inlineDef])) { - $isSimpleInstance = false; - } else { - $name = $definition === $inlineDef ? 'instance' : $this->getNextVariableName(); - $this->definitionVariables[$inlineDef] = new Variable($name); - $code .= '' !== $code ? "\n" : ''; - - if ('instance' === $name) { - $code .= $this->addServiceInstance($id, $definition, $isSimpleInstance); - } else { - $code .= $this->addNewInstance($inlineDef, ' $'.$name.' = ', $id); - } - - if ('' !== $inline = $this->addInlineVariables($id, $definition, $arguments, false)) { - $code .= "\n".$inline."\n"; - } elseif ($arguments && 'instance' === $name) { - $code .= "\n"; - } - - $code .= $this->addServiceProperties($inlineDef, $name); - $code .= $this->addServiceMethodCalls($inlineDef, $name, !$this->getProxyDumper()->isProxyCandidate($inlineDef) && $inlineDef->isShared() && !isset($this->singleUsePrivateIds[$id]) ? $id : null); - $code .= $this->addServiceConfigurator($inlineDef, $name); - } - - if ($isRootInstance && !$isSimpleInstance) { - $code .= "\n return \$instance;\n"; - } - - return $code; - } - - private function addServices(array &$services = null): string - { - $publicServices = $privateServices = ''; - $definitions = $this->container->getDefinitions(); - ksort($definitions); - foreach ($definitions as $id => $definition) { - if (!$definition->isSynthetic()) { - $services[$id] = $this->addService($id, $definition); - } elseif ($definition->hasTag($this->hotPathTag) || !$definition->hasTag($this->preloadTags[1])) { - $services[$id] = null; - - foreach ($this->getClasses($definition, $id) as $class) { - $this->preload[$class] = $class; - } - } - } - - foreach ($definitions as $id => $definition) { - if (!([$file, $code] = $services[$id]) || null !== $file) { - continue; - } - if ($definition->isPublic()) { - $publicServices .= $code; - } elseif (!$this->isTrivialInstance($definition) || isset($this->locatedIds[$id])) { - $privateServices .= $code; - } - } - - return $publicServices.$privateServices; - } - - private function generateServiceFiles(array $services): iterable - { - $definitions = $this->container->getDefinitions(); - ksort($definitions); - foreach ($definitions as $id => $definition) { - if (([$file, $code] = $services[$id]) && null !== $file && ($definition->isPublic() || !$this->isTrivialInstance($definition) || isset($this->locatedIds[$id]))) { - yield $file => [$code, $definition->hasTag($this->hotPathTag) || !$definition->hasTag($this->preloadTags[1]) && !$definition->isDeprecated() && !$definition->hasErrors()]; - } - } - } - - private function addNewInstance(Definition $definition, string $return = '', string $id = null): string - { - $tail = $return ? ";\n" : ''; - - if (BaseServiceLocator::class === $definition->getClass() && $definition->hasTag($this->serviceLocatorTag)) { - $arguments = []; - foreach ($definition->getArgument(0) as $k => $argument) { - $arguments[$k] = $argument->getValues()[0]; - } - - return $return.$this->dumpValue(new ServiceLocatorArgument($arguments)).$tail; - } - - $arguments = []; - foreach ($definition->getArguments() as $i => $value) { - $arguments[] = (\is_string($i) ? $i.': ' : '').$this->dumpValue($value); - } - - if (null !== $definition->getFactory()) { - $callable = $definition->getFactory(); - - if (\is_array($callable)) { - if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $callable[1])) { - throw new RuntimeException(sprintf('Cannot dump definition because of invalid factory method (%s).', $callable[1] ?: 'n/a')); - } - - if ($callable[0] instanceof Reference - || ($callable[0] instanceof Definition && $this->definitionVariables->contains($callable[0]))) { - return $return.sprintf('%s->%s(%s)', $this->dumpValue($callable[0]), $callable[1], $arguments ? implode(', ', $arguments) : '').$tail; - } - - $class = $this->dumpValue($callable[0]); - // If the class is a string we can optimize away - if (str_starts_with($class, "'") && !str_contains($class, '$')) { - if ("''" === $class) { - throw new RuntimeException(sprintf('Cannot dump definition: "%s" service is defined to be created by a factory but is missing the service reference, did you forget to define the factory service id or class?', $id ? 'The "'.$id.'"' : 'inline')); - } - - return $return.sprintf('%s::%s(%s)', $this->dumpLiteralClass($class), $callable[1], $arguments ? implode(', ', $arguments) : '').$tail; - } - - if (str_starts_with($class, 'new ')) { - return $return.sprintf('(%s)->%s(%s)', $class, $callable[1], $arguments ? implode(', ', $arguments) : '').$tail; - } - - return $return.sprintf("[%s, '%s'](%s)", $class, $callable[1], $arguments ? implode(', ', $arguments) : '').$tail; - } - - return $return.sprintf('%s(%s)', $this->dumpLiteralClass($this->dumpValue($callable)), $arguments ? implode(', ', $arguments) : '').$tail; - } - - if (null === $class = $definition->getClass()) { - throw new RuntimeException('Cannot dump definitions which have no class nor factory.'); - } - - return $return.sprintf('new %s(%s)', $this->dumpLiteralClass($this->dumpValue($class)), implode(', ', $arguments)).$tail; - } - - private function startClass(string $class, string $baseClass, bool $hasProxyClasses): string - { - $namespaceLine = !$this->asFiles && $this->namespace ? "\nnamespace {$this->namespace};\n" : ''; - - $code = <<<EOF -<?php -$namespaceLine -use Symfony\Component\DependencyInjection\Argument\RewindableGenerator; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\LogicException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; - -/*{$this->docStar} - * @internal This class has been auto-generated by the Symfony Dependency Injection Component. - */ -class $class extends $baseClass -{ - protected \$parameters = []; - - public function __construct() - { - -EOF; - if ($this->asFiles) { - $code = str_replace('$parameters = []', "\$containerDir;\n protected \$parameters = [];\n private \$buildParameters", $code); - $code = str_replace('__construct()', '__construct(array $buildParameters = [], $containerDir = __DIR__)', $code); - $code .= " \$this->buildParameters = \$buildParameters;\n"; - $code .= " \$this->containerDir = \$containerDir;\n"; - - if (null !== $this->targetDirRegex) { - $code = str_replace('$parameters = []', "\$targetDir;\n protected \$parameters = []", $code); - $code .= ' $this->targetDir = \\dirname($containerDir);'."\n"; - } - } - - if (Container::class !== $this->baseClass) { - $r = $this->container->getReflectionClass($this->baseClass, false); - if (null !== $r - && (null !== $constructor = $r->getConstructor()) - && 0 === $constructor->getNumberOfRequiredParameters() - && Container::class !== $constructor->getDeclaringClass()->name - ) { - $code .= " parent::__construct();\n"; - $code .= " \$this->parameterBag = null;\n\n"; - } - } - - if ($this->container->getParameterBag()->all()) { - $code .= " \$this->parameters = \$this->getDefaultParameters();\n\n"; - } - $code .= " \$this->services = \$this->privates = [];\n"; - - $code .= $this->addSyntheticIds(); - $code .= $this->addMethodMap(); - $code .= $this->asFiles && !$this->inlineFactories ? $this->addFileMap() : ''; - $code .= $this->addAliases(); - $code .= $this->addInlineRequires($hasProxyClasses); - $code .= <<<EOF - } - - public function compile(): void - { - throw new LogicException('You cannot compile a dumped container that was already compiled.'); - } - - public function isCompiled(): bool - { - return true; - } - -EOF; - $code .= $this->addRemovedIds(); - - if ($this->asFiles && !$this->inlineFactories) { - $code .= <<<'EOF' - - protected function load($file, $lazyLoad = true) - { - if (class_exists($class = __NAMESPACE__.'\\'.$file, false)) { - return $class::do($this, $lazyLoad); - } - - if ('.' === $file[-4]) { - $class = substr($class, 0, -4); - } else { - $file .= '.php'; - } - - $service = require $this->containerDir.\DIRECTORY_SEPARATOR.$file; - - return class_exists($class, false) ? $class::do($this, $lazyLoad) : $service; - } - -EOF; - } - - $proxyDumper = $this->getProxyDumper(); - foreach ($this->container->getDefinitions() as $definition) { - if (!$proxyDumper->isProxyCandidate($definition)) { - continue; - } - - if ($this->asFiles && !$this->inlineFactories) { - $proxyLoader = "class_exists(\$class, false) || require __DIR__.'/'.\$class.'.php';\n\n "; - } else { - $proxyLoader = ''; - } - - $code .= <<<EOF - - protected function createProxy(\$class, \Closure \$factory) - { - {$proxyLoader}return \$factory(); - } - -EOF; - break; - } - - return $code; - } - - private function addSyntheticIds(): string - { - $code = ''; - $definitions = $this->container->getDefinitions(); - ksort($definitions); - foreach ($definitions as $id => $definition) { - if ($definition->isSynthetic() && 'service_container' !== $id) { - $code .= ' '.$this->doExport($id)." => true,\n"; - } - } - - return $code ? " \$this->syntheticIds = [\n{$code} ];\n" : ''; - } - - private function addRemovedIds(): string - { - $ids = $this->container->getRemovedIds(); - foreach ($this->container->getDefinitions() as $id => $definition) { - if (!$definition->isPublic()) { - $ids[$id] = true; - } - } - if (!$ids) { - return ''; - } - if ($this->asFiles) { - $code = "require \$this->containerDir.\\DIRECTORY_SEPARATOR.'removed-ids.php'"; - } else { - $code = ''; - $ids = array_keys($ids); - sort($ids); - foreach ($ids as $id) { - if (preg_match(FileLoader::ANONYMOUS_ID_REGEXP, $id)) { - continue; - } - $code .= ' '.$this->doExport($id)." => true,\n"; - } - - $code = "[\n{$code} ]"; - } - - return <<<EOF - - public function getRemovedIds(): array - { - return {$code}; - } - -EOF; - } - - private function addMethodMap(): string - { - $code = ''; - $definitions = $this->container->getDefinitions(); - ksort($definitions); - foreach ($definitions as $id => $definition) { - if (!$definition->isSynthetic() && $definition->isPublic() && (!$this->asFiles || $this->inlineFactories || $this->isHotPath($definition))) { - $code .= ' '.$this->doExport($id).' => '.$this->doExport($this->generateMethodName($id)).",\n"; - } - } - - $aliases = $this->container->getAliases(); - foreach ($aliases as $alias => $id) { - if (!$id->isDeprecated()) { - continue; - } - $code .= ' '.$this->doExport($alias).' => '.$this->doExport($this->generateMethodName($alias)).",\n"; - } - - return $code ? " \$this->methodMap = [\n{$code} ];\n" : ''; - } - - private function addFileMap(): string - { - $code = ''; - $definitions = $this->container->getDefinitions(); - ksort($definitions); - foreach ($definitions as $id => $definition) { - if (!$definition->isSynthetic() && $definition->isPublic() && !$this->isHotPath($definition)) { - $code .= sprintf(" %s => '%s',\n", $this->doExport($id), $this->generateMethodName($id)); - } - } - - return $code ? " \$this->fileMap = [\n{$code} ];\n" : ''; - } - - private function addAliases(): string - { - if (!$aliases = $this->container->getAliases()) { - return "\n \$this->aliases = [];\n"; - } - - $code = " \$this->aliases = [\n"; - ksort($aliases); - foreach ($aliases as $alias => $id) { - if ($id->isDeprecated()) { - continue; - } - - $id = (string) $id; - while (isset($aliases[$id])) { - $id = (string) $aliases[$id]; - } - $code .= ' '.$this->doExport($alias).' => '.$this->doExport($id).",\n"; - } - - return $code." ];\n"; - } - - private function addDeprecatedAliases(): string - { - $code = ''; - $aliases = $this->container->getAliases(); - foreach ($aliases as $alias => $definition) { - if (!$definition->isDeprecated()) { - continue; - } - $public = $definition->isPublic() ? 'public' : 'private'; - $id = (string) $definition; - $methodNameAlias = $this->generateMethodName($alias); - $idExported = $this->export($id); - $deprecation = $definition->getDeprecation($alias); - $packageExported = $this->export($deprecation['package']); - $versionExported = $this->export($deprecation['version']); - $messageExported = $this->export($deprecation['message']); - $code .= <<<EOF - - /*{$this->docStar} - * Gets the $public '$alias' alias. - * - * @return object The "$id" service. - */ - protected function {$methodNameAlias}() - { - trigger_deprecation($packageExported, $versionExported, $messageExported); - - return \$this->get($idExported); - } - -EOF; - } - - return $code; - } - - private function addInlineRequires(bool $hasProxyClasses): string - { - $lineage = []; - $hotPathServices = $this->hotPathTag && $this->inlineRequires ? $this->container->findTaggedServiceIds($this->hotPathTag) : []; - - foreach ($hotPathServices as $id => $tags) { - $definition = $this->container->getDefinition($id); - - if ($this->getProxyDumper()->isProxyCandidate($definition)) { - continue; - } - - $inlinedDefinitions = $this->getDefinitionsFromArguments([$definition]); - - foreach ($inlinedDefinitions as $def) { - foreach ($this->getClasses($def, $id) as $class) { - $this->collectLineage($class, $lineage); - } - } - } - - $code = ''; - - foreach ($lineage as $file) { - if (!isset($this->inlinedRequires[$file])) { - $this->inlinedRequires[$file] = true; - $code .= sprintf("\n include_once %s;", $file); - } - } - - if ($hasProxyClasses) { - $code .= "\n include_once __DIR__.'/proxy-classes.php';"; - } - - return $code ? sprintf("\n \$this->privates['service_container'] = function () {%s\n };\n", $code) : ''; - } - - private function addDefaultParametersMethod(): string - { - if (!$this->container->getParameterBag()->all()) { - return ''; - } - - $php = []; - $dynamicPhp = []; - - foreach ($this->container->getParameterBag()->all() as $key => $value) { - if ($key !== $resolvedKey = $this->container->resolveEnvPlaceholders($key)) { - throw new InvalidArgumentException(sprintf('Parameter name cannot use env parameters: "%s".', $resolvedKey)); - } - $hasEnum = false; - $export = $this->exportParameters([$value], '', 12, $hasEnum); - $export = explode('0 => ', substr(rtrim($export, " ]\n"), 2, -1), 2); - - if ($hasEnum || preg_match("/\\\$this->(?:getEnv\('(?:[-.\w]*+:)*+\w++'\)|targetDir\.'')/", $export[1])) { - $dynamicPhp[$key] = sprintf('%scase %s: $value = %s; break;', $export[0], $this->export($key), $export[1]); - } else { - $php[] = sprintf('%s%s => %s,', $export[0], $this->export($key), $export[1]); - } - } - $parameters = sprintf("[\n%s\n%s]", implode("\n", $php), str_repeat(' ', 8)); - - $code = <<<'EOF' - - /** - * @return array|bool|float|int|string|\UnitEnum|null - */ - public function getParameter(string $name) - { - if (isset($this->buildParameters[$name])) { - return $this->buildParameters[$name]; - } - - if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || \array_key_exists($name, $this->parameters))) { - throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); - } - if (isset($this->loadedDynamicParameters[$name])) { - return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); - } - - return $this->parameters[$name]; - } - - public function hasParameter(string $name): bool - { - if (isset($this->buildParameters[$name])) { - return true; - } - - return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || \array_key_exists($name, $this->parameters); - } - - public function setParameter(string $name, $value): void - { - throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); - } - - public function getParameterBag(): ParameterBagInterface - { - if (null === $this->parameterBag) { - $parameters = $this->parameters; - foreach ($this->loadedDynamicParameters as $name => $loaded) { - $parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); - } - foreach ($this->buildParameters as $name => $value) { - $parameters[$name] = $value; - } - $this->parameterBag = new FrozenParameterBag($parameters); - } - - return $this->parameterBag; - } - -EOF; - if (!$this->asFiles) { - $code = preg_replace('/^.*buildParameters.*\n.*\n.*\n\n?/m', '', $code); - } - - if ($dynamicPhp) { - $loadedDynamicParameters = $this->exportParameters(array_combine(array_keys($dynamicPhp), array_fill(0, \count($dynamicPhp), false)), '', 8); - $getDynamicParameter = <<<'EOF' - switch ($name) { -%s - default: throw new InvalidArgumentException(sprintf('The dynamic parameter "%%s" must be defined.', $name)); - } - $this->loadedDynamicParameters[$name] = true; - - return $this->dynamicParameters[$name] = $value; -EOF; - $getDynamicParameter = sprintf($getDynamicParameter, implode("\n", $dynamicPhp)); - } else { - $loadedDynamicParameters = '[]'; - $getDynamicParameter = str_repeat(' ', 8).'throw new InvalidArgumentException(sprintf(\'The dynamic parameter "%s" must be defined.\', $name));'; - } - - $code .= <<<EOF - - private \$loadedDynamicParameters = {$loadedDynamicParameters}; - private \$dynamicParameters = []; - - private function getDynamicParameter(string \$name) - { -{$getDynamicParameter} - } - - protected function getDefaultParameters(): array - { - return $parameters; - } - -EOF; - - return $code; - } - - /** - * @throws InvalidArgumentException - */ - private function exportParameters(array $parameters, string $path = '', int $indent = 12, bool &$hasEnum = false): string - { - $php = []; - foreach ($parameters as $key => $value) { - if (\is_array($value)) { - $value = $this->exportParameters($value, $path.'/'.$key, $indent + 4, $hasEnum); - } elseif ($value instanceof ArgumentInterface) { - throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain special arguments. "%s" found in "%s".', get_debug_type($value), $path.'/'.$key)); - } elseif ($value instanceof Variable) { - throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain variable references. Variable "%s" found in "%s".', $value, $path.'/'.$key)); - } elseif ($value instanceof Definition) { - throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain service definitions. Definition for "%s" found in "%s".', $value->getClass(), $path.'/'.$key)); - } elseif ($value instanceof Reference) { - throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain references to other services (reference to service "%s" found in "%s").', $value, $path.'/'.$key)); - } elseif ($value instanceof Expression) { - throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain expressions. Expression "%s" found in "%s".', $value, $path.'/'.$key)); - } elseif ($value instanceof \UnitEnum) { - $hasEnum = true; - $value = sprintf('\%s::%s', \get_class($value), $value->name); - } else { - $value = $this->export($value); - } - - $php[] = sprintf('%s%s => %s,', str_repeat(' ', $indent), $this->export($key), $value); - } - - return sprintf("[\n%s\n%s]", implode("\n", $php), str_repeat(' ', $indent - 4)); - } - - private function endClass(): string - { - if ($this->addThrow) { - return <<<'EOF' - - protected function throw($message) - { - throw new RuntimeException($message); - } -} - -EOF; - } - - return <<<'EOF' -} - -EOF; - } - - private function wrapServiceConditionals($value, string $code): string - { - if (!$condition = $this->getServiceConditionals($value)) { - return $code; - } - - // re-indent the wrapped code - $code = implode("\n", array_map(function ($line) { return $line ? ' '.$line : $line; }, explode("\n", $code))); - - return sprintf(" if (%s) {\n%s }\n", $condition, $code); - } - - private function getServiceConditionals($value): string - { - $conditions = []; - foreach (ContainerBuilder::getInitializedConditionals($value) as $service) { - if (!$this->container->hasDefinition($service)) { - return 'false'; - } - $conditions[] = sprintf('isset($this->%s[%s])', $this->container->getDefinition($service)->isPublic() ? 'services' : 'privates', $this->doExport($service)); - } - foreach (ContainerBuilder::getServiceConditionals($value) as $service) { - if ($this->container->hasDefinition($service) && !$this->container->getDefinition($service)->isPublic()) { - continue; - } - - $conditions[] = sprintf('$this->has(%s)', $this->doExport($service)); - } - - if (!$conditions) { - return ''; - } - - return implode(' && ', $conditions); - } - - private function getDefinitionsFromArguments(array $arguments, \SplObjectStorage $definitions = null, array &$calls = [], bool $byConstructor = null): \SplObjectStorage - { - if (null === $definitions) { - $definitions = new \SplObjectStorage(); - } - - foreach ($arguments as $argument) { - if (\is_array($argument)) { - $this->getDefinitionsFromArguments($argument, $definitions, $calls, $byConstructor); - } elseif ($argument instanceof Reference) { - $id = (string) $argument; - - while ($this->container->hasAlias($id)) { - $id = (string) $this->container->getAlias($id); - } - - if (!isset($calls[$id])) { - $calls[$id] = [0, $argument->getInvalidBehavior(), $byConstructor]; - } else { - $calls[$id][1] = min($calls[$id][1], $argument->getInvalidBehavior()); - } - - ++$calls[$id][0]; - } elseif (!$argument instanceof Definition) { - // no-op - } elseif (isset($definitions[$argument])) { - $definitions[$argument] = 1 + $definitions[$argument]; - } else { - $definitions[$argument] = 1; - $arguments = [$argument->getArguments(), $argument->getFactory()]; - $this->getDefinitionsFromArguments($arguments, $definitions, $calls, null === $byConstructor || $byConstructor); - $arguments = [$argument->getProperties(), $argument->getMethodCalls(), $argument->getConfigurator()]; - $this->getDefinitionsFromArguments($arguments, $definitions, $calls, null !== $byConstructor && $byConstructor); - } - } - - return $definitions; - } - - /** - * @throws RuntimeException - */ - private function dumpValue($value, bool $interpolate = true): string - { - if (\is_array($value)) { - if ($value && $interpolate && false !== $param = array_search($value, $this->container->getParameterBag()->all(), true)) { - return $this->dumpValue("%$param%"); - } - $code = []; - foreach ($value as $k => $v) { - $code[] = sprintf('%s => %s', $this->dumpValue($k, $interpolate), $this->dumpValue($v, $interpolate)); - } - - return sprintf('[%s]', implode(', ', $code)); - } elseif ($value instanceof ArgumentInterface) { - $scope = [$this->definitionVariables, $this->referenceVariables]; - $this->definitionVariables = $this->referenceVariables = null; - - try { - if ($value instanceof ServiceClosureArgument) { - $value = $value->getValues()[0]; - $code = $this->dumpValue($value, $interpolate); - - $returnedType = ''; - if ($value instanceof TypedReference) { - $returnedType = sprintf(': %s\%s', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $value->getInvalidBehavior() ? '' : '?', str_replace(['|', '&'], ['|\\', '&\\'], $value->getType())); - } - - $code = sprintf('return %s;', $code); - - return sprintf("function ()%s {\n %s\n }", $returnedType, $code); - } - - if ($value instanceof IteratorArgument) { - $operands = [0]; - $code = []; - $code[] = 'new RewindableGenerator(function () {'; - - if (!$values = $value->getValues()) { - $code[] = ' return new \EmptyIterator();'; - } else { - $countCode = []; - $countCode[] = 'function () {'; - - foreach ($values as $k => $v) { - ($c = $this->getServiceConditionals($v)) ? $operands[] = "(int) ($c)" : ++$operands[0]; - $v = $this->wrapServiceConditionals($v, sprintf(" yield %s => %s;\n", $this->dumpValue($k, $interpolate), $this->dumpValue($v, $interpolate))); - foreach (explode("\n", $v) as $v) { - if ($v) { - $code[] = ' '.$v; - } - } - } - - $countCode[] = sprintf(' return %s;', implode(' + ', $operands)); - $countCode[] = ' }'; - } - - $code[] = sprintf(' }, %s)', \count($operands) > 1 ? implode("\n", $countCode) : $operands[0]); - - return implode("\n", $code); - } - - if ($value instanceof ServiceLocatorArgument) { - $serviceMap = ''; - $serviceTypes = ''; - foreach ($value->getValues() as $k => $v) { - if (!$v) { - continue; - } - $id = (string) $v; - while ($this->container->hasAlias($id)) { - $id = (string) $this->container->getAlias($id); - } - $definition = $this->container->getDefinition($id); - $load = !($definition->hasErrors() && $e = $definition->getErrors()) ? $this->asFiles && !$this->inlineFactories && !$this->isHotPath($definition) : reset($e); - $serviceMap .= sprintf("\n %s => [%s, %s, %s, %s],", - $this->export($k), - $this->export($definition->isShared() ? ($definition->isPublic() ? 'services' : 'privates') : false), - $this->doExport($id), - $this->export(ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE !== $v->getInvalidBehavior() && !\is_string($load) ? $this->generateMethodName($id) : null), - $this->export($load) - ); - $serviceTypes .= sprintf("\n %s => %s,", $this->export($k), $this->export($v instanceof TypedReference ? $v->getType() : '?')); - $this->locatedIds[$id] = true; - } - $this->addGetService = true; - - return sprintf('new \%s($this->getService, [%s%s], [%s%s])', ServiceLocator::class, $serviceMap, $serviceMap ? "\n " : '', $serviceTypes, $serviceTypes ? "\n " : ''); - } - } finally { - [$this->definitionVariables, $this->referenceVariables] = $scope; - } - } elseif ($value instanceof Definition) { - if ($value->hasErrors() && $e = $value->getErrors()) { - $this->addThrow = true; - - return sprintf('$this->throw(%s)', $this->export(reset($e))); - } - if (null !== $this->definitionVariables && $this->definitionVariables->contains($value)) { - return $this->dumpValue($this->definitionVariables[$value], $interpolate); - } - if ($value->getMethodCalls()) { - throw new RuntimeException('Cannot dump definitions which have method calls.'); - } - if ($value->getProperties()) { - throw new RuntimeException('Cannot dump definitions which have properties.'); - } - if (null !== $value->getConfigurator()) { - throw new RuntimeException('Cannot dump definitions which have a configurator.'); - } - - return $this->addNewInstance($value); - } elseif ($value instanceof Variable) { - return '$'.$value; - } elseif ($value instanceof Reference) { - $id = (string) $value; - - while ($this->container->hasAlias($id)) { - $id = (string) $this->container->getAlias($id); - } - - if (null !== $this->referenceVariables && isset($this->referenceVariables[$id])) { - return $this->dumpValue($this->referenceVariables[$id], $interpolate); - } - - return $this->getServiceCall($id, $value); - } elseif ($value instanceof Expression) { - return $this->getExpressionLanguage()->compile((string) $value, ['this' => 'container']); - } elseif ($value instanceof Parameter) { - return $this->dumpParameter($value); - } elseif (true === $interpolate && \is_string($value)) { - if (preg_match('/^%([^%]+)%$/', $value, $match)) { - // we do this to deal with non string values (Boolean, integer, ...) - // the preg_replace_callback converts them to strings - return $this->dumpParameter($match[1]); - } else { - $replaceParameters = function ($match) { - return "'.".$this->dumpParameter($match[2]).".'"; - }; - - $code = str_replace('%%', '%', preg_replace_callback('/(?<!%)(%)([^%]+)\1/', $replaceParameters, $this->export($value))); - - return $code; - } - } elseif ($value instanceof \UnitEnum) { - return sprintf('\%s::%s', \get_class($value), $value->name); - } elseif ($value instanceof AbstractArgument) { - throw new RuntimeException($value->getTextWithContext()); - } elseif (\is_object($value) || \is_resource($value)) { - throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.'); - } - - return $this->export($value); - } - - /** - * Dumps a string to a literal (aka PHP Code) class value. - * - * @throws RuntimeException - */ - private function dumpLiteralClass(string $class): string - { - if (str_contains($class, '$')) { - return sprintf('${($_ = %s) && false ?: "_"}', $class); - } - if (!str_starts_with($class, "'") || !preg_match('/^\'(?:\\\{2})?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) { - throw new RuntimeException(sprintf('Cannot dump definition because of invalid class name (%s).', $class ?: 'n/a')); - } - - $class = substr(str_replace('\\\\', '\\', $class), 1, -1); - - return str_starts_with($class, '\\') ? $class : '\\'.$class; - } - - private function dumpParameter(string $name): string - { - if ($this->container->hasParameter($name)) { - $value = $this->container->getParameter($name); - $dumpedValue = $this->dumpValue($value, false); - - if (!$value || !\is_array($value)) { - return $dumpedValue; - } - - if (!preg_match("/\\\$this->(?:getEnv\('(?:[-.\w]*+:)*+\w++'\)|targetDir\.'')/", $dumpedValue)) { - return sprintf('$this->parameters[%s]', $this->doExport($name)); - } - } - - return sprintf('$this->getParameter(%s)', $this->doExport($name)); - } - - private function getServiceCall(string $id, Reference $reference = null): string - { - while ($this->container->hasAlias($id)) { - $id = (string) $this->container->getAlias($id); - } - - if ('service_container' === $id) { - return '$this'; - } - - if ($this->container->hasDefinition($id) && $definition = $this->container->getDefinition($id)) { - if ($definition->isSynthetic()) { - $code = sprintf('$this->get(%s%s)', $this->doExport($id), null !== $reference ? ', '.$reference->getInvalidBehavior() : ''); - } elseif (null !== $reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $reference->getInvalidBehavior()) { - $code = 'null'; - if (!$definition->isShared()) { - return $code; - } - } elseif ($this->isTrivialInstance($definition)) { - if ($definition->hasErrors() && $e = $definition->getErrors()) { - $this->addThrow = true; - - return sprintf('$this->throw(%s)', $this->export(reset($e))); - } - $code = $this->addNewInstance($definition, '', $id); - if ($definition->isShared() && !isset($this->singleUsePrivateIds[$id])) { - $code = sprintf('$this->%s[%s] = %s', $definition->isPublic() ? 'services' : 'privates', $this->doExport($id), $code); - } - $code = "($code)"; - } else { - $code = $this->asFiles && !$this->inlineFactories && !$this->isHotPath($definition) ? "\$this->load('%s')" : '$this->%s()'; - $code = sprintf($code, $this->generateMethodName($id)); - - if (!$definition->isShared()) { - $factory = sprintf('$this->factories%s[%s]', $definition->isPublic() ? '' : "['service_container']", $this->doExport($id)); - $code = sprintf('(isset(%s) ? %1$s() : %s)', $factory, $code); - } - } - if ($definition->isShared() && !isset($this->singleUsePrivateIds[$id])) { - $code = sprintf('($this->%s[%s] ?? %s)', $definition->isPublic() ? 'services' : 'privates', $this->doExport($id), $code); - } - - return $code; - } - if (null !== $reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $reference->getInvalidBehavior()) { - return 'null'; - } - if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE < $reference->getInvalidBehavior()) { - $code = sprintf('$this->get(%s, /* ContainerInterface::NULL_ON_INVALID_REFERENCE */ %d)', $this->doExport($id), ContainerInterface::NULL_ON_INVALID_REFERENCE); - } else { - $code = sprintf('$this->get(%s)', $this->doExport($id)); - } - - return sprintf('($this->services[%s] ?? %s)', $this->doExport($id), $code); - } - - /** - * Initializes the method names map to avoid conflicts with the Container methods. - */ - private function initializeMethodNamesMap(string $class) - { - $this->serviceIdToMethodNameMap = []; - $this->usedMethodNames = []; - - if ($reflectionClass = $this->container->getReflectionClass($class)) { - foreach ($reflectionClass->getMethods() as $method) { - $this->usedMethodNames[strtolower($method->getName())] = true; - } - } - } - - /** - * @throws InvalidArgumentException - */ - private function generateMethodName(string $id): string - { - if (isset($this->serviceIdToMethodNameMap[$id])) { - return $this->serviceIdToMethodNameMap[$id]; - } - - $i = strrpos($id, '\\'); - $name = Container::camelize(false !== $i && isset($id[1 + $i]) ? substr($id, 1 + $i) : $id); - $name = preg_replace('/[^a-zA-Z0-9_\x7f-\xff]/', '', $name); - $methodName = 'get'.$name.'Service'; - $suffix = 1; - - while (isset($this->usedMethodNames[strtolower($methodName)])) { - ++$suffix; - $methodName = 'get'.$name.$suffix.'Service'; - } - - $this->serviceIdToMethodNameMap[$id] = $methodName; - $this->usedMethodNames[strtolower($methodName)] = true; - - return $methodName; - } - - private function getNextVariableName(): string - { - $firstChars = self::FIRST_CHARS; - $firstCharsLength = \strlen($firstChars); - $nonFirstChars = self::NON_FIRST_CHARS; - $nonFirstCharsLength = \strlen($nonFirstChars); - - while (true) { - $name = ''; - $i = $this->variableCount; - - if ('' === $name) { - $name .= $firstChars[$i % $firstCharsLength]; - $i = (int) ($i / $firstCharsLength); - } - - while ($i > 0) { - --$i; - $name .= $nonFirstChars[$i % $nonFirstCharsLength]; - $i = (int) ($i / $nonFirstCharsLength); - } - - ++$this->variableCount; - - // check that the name is not reserved - if (\in_array($name, $this->reservedVariables, true)) { - continue; - } - - return $name; - } - } - - private function getExpressionLanguage(): ExpressionLanguage - { - if (null === $this->expressionLanguage) { - if (!class_exists(\Symfony\Component\ExpressionLanguage\ExpressionLanguage::class)) { - throw new LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); - } - $providers = $this->container->getExpressionLanguageProviders(); - $this->expressionLanguage = new ExpressionLanguage(null, $providers, function ($arg) { - $id = '""' === substr_replace($arg, '', 1, -1) ? stripcslashes(substr($arg, 1, -1)) : null; - - if (null !== $id && ($this->container->hasAlias($id) || $this->container->hasDefinition($id))) { - return $this->getServiceCall($id); - } - - return sprintf('$this->get(%s)', $arg); - }); - - if ($this->container->isTrackingResources()) { - foreach ($providers as $provider) { - $this->container->addObjectResource($provider); - } - } - } - - return $this->expressionLanguage; - } - - private function isHotPath(Definition $definition): bool - { - return $this->hotPathTag && $definition->hasTag($this->hotPathTag) && !$definition->isDeprecated(); - } - - private function isSingleUsePrivateNode(ServiceReferenceGraphNode $node): bool - { - if ($node->getValue()->isPublic()) { - return false; - } - $ids = []; - foreach ($node->getInEdges() as $edge) { - if (!$value = $edge->getSourceNode()->getValue()) { - continue; - } - if ($edge->isLazy() || !$value instanceof Definition || !$value->isShared()) { - return false; - } - $ids[$edge->getSourceNode()->getId()] = true; - } - - return 1 === \count($ids); - } - - /** - * @return mixed - */ - private function export($value) - { - if (null !== $this->targetDirRegex && \is_string($value) && preg_match($this->targetDirRegex, $value, $matches, \PREG_OFFSET_CAPTURE)) { - $suffix = $matches[0][1] + \strlen($matches[0][0]); - $matches[0][1] += \strlen($matches[1][0]); - $prefix = $matches[0][1] ? $this->doExport(substr($value, 0, $matches[0][1]), true).'.' : ''; - - if ('\\' === \DIRECTORY_SEPARATOR && isset($value[$suffix])) { - $cookie = '\\'.random_int(100000, \PHP_INT_MAX); - $suffix = '.'.$this->doExport(str_replace('\\', $cookie, substr($value, $suffix)), true); - $suffix = str_replace('\\'.$cookie, "'.\\DIRECTORY_SEPARATOR.'", $suffix); - } else { - $suffix = isset($value[$suffix]) ? '.'.$this->doExport(substr($value, $suffix), true) : ''; - } - - $dirname = $this->asFiles ? '$this->containerDir' : '__DIR__'; - $offset = 2 + $this->targetDirMaxMatches - \count($matches); - - if (0 < $offset) { - $dirname = sprintf('\dirname(__DIR__, %d)', $offset + (int) $this->asFiles); - } elseif ($this->asFiles) { - $dirname = "\$this->targetDir.''"; // empty string concatenation on purpose - } - - if ($prefix || $suffix) { - return sprintf('(%s%s%s)', $prefix, $dirname, $suffix); - } - - return $dirname; - } - - return $this->doExport($value, true); - } - - /** - * @return mixed - */ - private function doExport($value, bool $resolveEnv = false) - { - $shouldCacheValue = $resolveEnv && \is_string($value); - if ($shouldCacheValue && isset($this->exportedVariables[$value])) { - return $this->exportedVariables[$value]; - } - if (\is_string($value) && str_contains($value, "\n")) { - $cleanParts = explode("\n", $value); - $cleanParts = array_map(function ($part) { return var_export($part, true); }, $cleanParts); - $export = implode('."\n".', $cleanParts); - } else { - $export = var_export($value, true); - } - if ($this->asFiles) { - if (false !== strpos($export, '$this')) { - $export = str_replace('$this', "$'.'this", $export); - } - if (false !== strpos($export, 'function () {')) { - $export = str_replace('function () {', "function ('.') {", $export); - } - } - - if ($resolveEnv && "'" === $export[0] && $export !== $resolvedExport = $this->container->resolveEnvPlaceholders($export, "'.\$this->getEnv('string:%s').'")) { - $export = $resolvedExport; - if (str_ends_with($export, ".''")) { - $export = substr($export, 0, -3); - if ("'" === $export[1]) { - $export = substr_replace($export, '', 18, 7); - } - } - if ("'" === $export[1]) { - $export = substr($export, 3); - } - } - - if ($shouldCacheValue) { - $this->exportedVariables[$value] = $export; - } - - return $export; - } - - private function getAutoloadFile(): ?string - { - $file = null; - - foreach (spl_autoload_functions() as $autoloader) { - if (!\is_array($autoloader)) { - continue; - } - - if ($autoloader[0] instanceof DebugClassLoader || $autoloader[0] instanceof LegacyDebugClassLoader) { - $autoloader = $autoloader[0]->getClassLoader(); - } - - if (!\is_array($autoloader) || !$autoloader[0] instanceof ClassLoader || !$autoloader[0]->findFile(__CLASS__)) { - continue; - } - - foreach (get_declared_classes() as $class) { - if (str_starts_with($class, 'ComposerAutoloaderInit') && $class::getLoader() === $autoloader[0]) { - $file = \dirname((new \ReflectionClass($class))->getFileName(), 2).'/autoload.php'; - - if (null !== $this->targetDirRegex && preg_match($this->targetDirRegex.'A', $file)) { - return $file; - } - } - } - } - - return $file; - } - - private function getClasses(Definition $definition, string $id): array - { - $classes = []; - - while ($definition instanceof Definition) { - foreach ($definition->getTag($this->preloadTags[0]) as $tag) { - if (!isset($tag['class'])) { - throw new InvalidArgumentException(sprintf('Missing attribute "class" on tag "%s" for service "%s".', $this->preloadTags[0], $id)); - } - - $classes[] = trim($tag['class'], '\\'); - } - - if ($class = $definition->getClass()) { - $classes[] = trim($class, '\\'); - } - $factory = $definition->getFactory(); - - if (!\is_array($factory)) { - $factory = [$factory]; - } - - if (\is_string($factory[0])) { - if (false !== $i = strrpos($factory[0], '::')) { - $factory[0] = substr($factory[0], 0, $i); - } - $classes[] = trim($factory[0], '\\'); - } - - $definition = $factory[0]; - } - - return $classes; - } -} diff --git a/lib/symfony/dependency-injection/Dumper/Preloader.php b/lib/symfony/dependency-injection/Dumper/Preloader.php deleted file mode 100644 index c61b08ebc..000000000 --- a/lib/symfony/dependency-injection/Dumper/Preloader.php +++ /dev/null @@ -1,131 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Dumper; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -final class Preloader -{ - public static function append(string $file, array $list): void - { - if (!file_exists($file)) { - throw new \LogicException(sprintf('File "%s" does not exist.', $file)); - } - - $cacheDir = \dirname($file); - $classes = []; - - foreach ($list as $item) { - if (0 === strpos($item, $cacheDir)) { - file_put_contents($file, sprintf("require_once __DIR__.%s;\n", var_export(strtr(substr($item, \strlen($cacheDir)), \DIRECTORY_SEPARATOR, '/'), true)), \FILE_APPEND); - continue; - } - - $classes[] = sprintf("\$classes[] = %s;\n", var_export($item, true)); - } - - file_put_contents($file, sprintf("\n\$classes = [];\n%s\$preloaded = Preloader::preload(\$classes, \$preloaded);\n", implode('', $classes)), \FILE_APPEND); - } - - public static function preload(array $classes, array $preloaded = []): array - { - set_error_handler(function ($t, $m, $f, $l) { - if (error_reporting() & $t) { - if (__FILE__ !== $f) { - throw new \ErrorException($m, 0, $t, $f, $l); - } - - throw new \ReflectionException($m); - } - }); - - $prev = []; - - try { - while ($prev !== $classes) { - $prev = $classes; - foreach ($classes as $c) { - if (!isset($preloaded[$c])) { - self::doPreload($c, $preloaded); - } - } - $classes = array_merge(get_declared_classes(), get_declared_interfaces(), get_declared_traits()); - } - } finally { - restore_error_handler(); - } - - return $preloaded; - } - - private static function doPreload(string $class, array &$preloaded): void - { - if (isset($preloaded[$class]) || \in_array($class, ['self', 'static', 'parent'], true)) { - return; - } - - $preloaded[$class] = true; - - try { - if (!class_exists($class) && !interface_exists($class, false) && !trait_exists($class, false)) { - return; - } - - $r = new \ReflectionClass($class); - - if ($r->isInternal()) { - return; - } - - $r->getConstants(); - $r->getDefaultProperties(); - - if (\PHP_VERSION_ID >= 70400) { - foreach ($r->getProperties(\ReflectionProperty::IS_PUBLIC) as $p) { - self::preloadType($p->getType(), $preloaded); - } - } - - foreach ($r->getMethods(\ReflectionMethod::IS_PUBLIC) as $m) { - foreach ($m->getParameters() as $p) { - if ($p->isDefaultValueAvailable() && $p->isDefaultValueConstant()) { - $c = $p->getDefaultValueConstantName(); - - if ($i = strpos($c, '::')) { - self::doPreload(substr($c, 0, $i), $preloaded); - } - } - - self::preloadType($p->getType(), $preloaded); - } - - self::preloadType($m->getReturnType(), $preloaded); - } - } catch (\Throwable $e) { - // ignore missing classes - } - } - - private static function preloadType(?\ReflectionType $t, array &$preloaded): void - { - if (!$t) { - return; - } - - foreach (($t instanceof \ReflectionUnionType || $t instanceof \ReflectionIntersectionType) ? $t->getTypes() : [$t] as $t) { - if (!$t->isBuiltin()) { - self::doPreload($t instanceof \ReflectionNamedType ? $t->getName() : $t, $preloaded); - } - } - } -} diff --git a/lib/symfony/dependency-injection/Dumper/XmlDumper.php b/lib/symfony/dependency-injection/Dumper/XmlDumper.php deleted file mode 100644 index 4f7b16d5f..000000000 --- a/lib/symfony/dependency-injection/Dumper/XmlDumper.php +++ /dev/null @@ -1,395 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Dumper; - -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\AbstractArgument; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Parameter; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\ExpressionLanguage\Expression; - -/** - * XmlDumper dumps a service container as an XML string. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Martin Hasoň <martin.hason@gmail.com> - */ -class XmlDumper extends Dumper -{ - /** - * @var \DOMDocument - */ - private $document; - - /** - * Dumps the service container as an XML string. - * - * @return string - */ - public function dump(array $options = []) - { - $this->document = new \DOMDocument('1.0', 'utf-8'); - $this->document->formatOutput = true; - - $container = $this->document->createElementNS('http://symfony.com/schema/dic/services', 'container'); - $container->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); - $container->setAttribute('xsi:schemaLocation', 'http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd'); - - $this->addParameters($container); - $this->addServices($container); - - $this->document->appendChild($container); - $xml = $this->document->saveXML(); - $this->document = null; - - return $this->container->resolveEnvPlaceholders($xml); - } - - private function addParameters(\DOMElement $parent) - { - $data = $this->container->getParameterBag()->all(); - if (!$data) { - return; - } - - if ($this->container->isCompiled()) { - $data = $this->escape($data); - } - - $parameters = $this->document->createElement('parameters'); - $parent->appendChild($parameters); - $this->convertParameters($data, 'parameter', $parameters); - } - - private function addMethodCalls(array $methodcalls, \DOMElement $parent) - { - foreach ($methodcalls as $methodcall) { - $call = $this->document->createElement('call'); - $call->setAttribute('method', $methodcall[0]); - if (\count($methodcall[1])) { - $this->convertParameters($methodcall[1], 'argument', $call); - } - if ($methodcall[2] ?? false) { - $call->setAttribute('returns-clone', 'true'); - } - $parent->appendChild($call); - } - } - - private function addService(Definition $definition, ?string $id, \DOMElement $parent) - { - $service = $this->document->createElement('service'); - if (null !== $id) { - $service->setAttribute('id', $id); - } - if ($class = $definition->getClass()) { - if ('\\' === substr($class, 0, 1)) { - $class = substr($class, 1); - } - - $service->setAttribute('class', $class); - } - if (!$definition->isShared()) { - $service->setAttribute('shared', 'false'); - } - if ($definition->isPublic()) { - $service->setAttribute('public', 'true'); - } - if ($definition->isSynthetic()) { - $service->setAttribute('synthetic', 'true'); - } - if ($definition->isLazy()) { - $service->setAttribute('lazy', 'true'); - } - if (null !== $decoratedService = $definition->getDecoratedService()) { - [$decorated, $renamedId, $priority] = $decoratedService; - $service->setAttribute('decorates', $decorated); - - $decorationOnInvalid = $decoratedService[3] ?? ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; - if (\in_array($decorationOnInvalid, [ContainerInterface::IGNORE_ON_INVALID_REFERENCE, ContainerInterface::NULL_ON_INVALID_REFERENCE], true)) { - $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE === $decorationOnInvalid ? 'null' : 'ignore'; - $service->setAttribute('decoration-on-invalid', $invalidBehavior); - } - if (null !== $renamedId) { - $service->setAttribute('decoration-inner-name', $renamedId); - } - if (0 !== $priority) { - $service->setAttribute('decoration-priority', $priority); - } - } - - foreach ($definition->getTags() as $name => $tags) { - foreach ($tags as $attributes) { - $tag = $this->document->createElement('tag'); - if (!\array_key_exists('name', $attributes)) { - $tag->setAttribute('name', $name); - } else { - $tag->appendChild($this->document->createTextNode($name)); - } - foreach ($attributes as $key => $value) { - $tag->setAttribute($key, $value ?? ''); - } - $service->appendChild($tag); - } - } - - if ($definition->getFile()) { - $file = $this->document->createElement('file'); - $file->appendChild($this->document->createTextNode($definition->getFile())); - $service->appendChild($file); - } - - if ($parameters = $definition->getArguments()) { - $this->convertParameters($parameters, 'argument', $service); - } - - if ($parameters = $definition->getProperties()) { - $this->convertParameters($parameters, 'property', $service, 'name'); - } - - $this->addMethodCalls($definition->getMethodCalls(), $service); - - if ($callable = $definition->getFactory()) { - $factory = $this->document->createElement('factory'); - - if (\is_array($callable) && $callable[0] instanceof Definition) { - $this->addService($callable[0], null, $factory); - $factory->setAttribute('method', $callable[1]); - } elseif (\is_array($callable)) { - if (null !== $callable[0]) { - $factory->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]); - } - $factory->setAttribute('method', $callable[1]); - } else { - $factory->setAttribute('function', $callable); - } - $service->appendChild($factory); - } - - if ($definition->isDeprecated()) { - $deprecation = $definition->getDeprecation('%service_id%'); - $deprecated = $this->document->createElement('deprecated'); - $deprecated->appendChild($this->document->createTextNode($definition->getDeprecation('%service_id%')['message'])); - $deprecated->setAttribute('package', $deprecation['package']); - $deprecated->setAttribute('version', $deprecation['version']); - - $service->appendChild($deprecated); - } - - if ($definition->isAutowired()) { - $service->setAttribute('autowire', 'true'); - } - - if ($definition->isAutoconfigured()) { - $service->setAttribute('autoconfigure', 'true'); - } - - if ($definition->isAbstract()) { - $service->setAttribute('abstract', 'true'); - } - - if ($callable = $definition->getConfigurator()) { - $configurator = $this->document->createElement('configurator'); - - if (\is_array($callable) && $callable[0] instanceof Definition) { - $this->addService($callable[0], null, $configurator); - $configurator->setAttribute('method', $callable[1]); - } elseif (\is_array($callable)) { - $configurator->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]); - $configurator->setAttribute('method', $callable[1]); - } else { - $configurator->setAttribute('function', $callable); - } - $service->appendChild($configurator); - } - - $parent->appendChild($service); - } - - private function addServiceAlias(string $alias, Alias $id, \DOMElement $parent) - { - $service = $this->document->createElement('service'); - $service->setAttribute('id', $alias); - $service->setAttribute('alias', $id); - if ($id->isPublic()) { - $service->setAttribute('public', 'true'); - } - - if ($id->isDeprecated()) { - $deprecation = $id->getDeprecation('%alias_id%'); - $deprecated = $this->document->createElement('deprecated'); - $deprecated->appendChild($this->document->createTextNode($deprecation['message'])); - $deprecated->setAttribute('package', $deprecation['package']); - $deprecated->setAttribute('version', $deprecation['version']); - - $service->appendChild($deprecated); - } - - $parent->appendChild($service); - } - - private function addServices(\DOMElement $parent) - { - $definitions = $this->container->getDefinitions(); - if (!$definitions) { - return; - } - - $services = $this->document->createElement('services'); - foreach ($definitions as $id => $definition) { - $this->addService($definition, $id, $services); - } - - $aliases = $this->container->getAliases(); - foreach ($aliases as $alias => $id) { - while (isset($aliases[(string) $id])) { - $id = $aliases[(string) $id]; - } - $this->addServiceAlias($alias, $id, $services); - } - $parent->appendChild($services); - } - - private function convertParameters(array $parameters, string $type, \DOMElement $parent, string $keyAttribute = 'key') - { - $withKeys = !array_is_list($parameters); - foreach ($parameters as $key => $value) { - $element = $this->document->createElement($type); - if ($withKeys) { - $element->setAttribute($keyAttribute, $key); - } - - if (\is_array($tag = $value)) { - $element->setAttribute('type', 'collection'); - $this->convertParameters($value, $type, $element, 'key'); - } elseif ($value instanceof TaggedIteratorArgument || ($value instanceof ServiceLocatorArgument && $tag = $value->getTaggedIteratorArgument())) { - $element->setAttribute('type', $value instanceof TaggedIteratorArgument ? 'tagged_iterator' : 'tagged_locator'); - $element->setAttribute('tag', $tag->getTag()); - - if (null !== $tag->getIndexAttribute()) { - $element->setAttribute('index-by', $tag->getIndexAttribute()); - - if (null !== $tag->getDefaultIndexMethod()) { - $element->setAttribute('default-index-method', $tag->getDefaultIndexMethod()); - } - if (null !== $tag->getDefaultPriorityMethod()) { - $element->setAttribute('default-priority-method', $tag->getDefaultPriorityMethod()); - } - } - } elseif ($value instanceof IteratorArgument) { - $element->setAttribute('type', 'iterator'); - $this->convertParameters($value->getValues(), $type, $element, 'key'); - } elseif ($value instanceof ServiceLocatorArgument) { - $element->setAttribute('type', 'service_locator'); - $this->convertParameters($value->getValues(), $type, $element, 'key'); - } elseif ($value instanceof Reference || $value instanceof ServiceClosureArgument) { - $element->setAttribute('type', 'service'); - if ($value instanceof ServiceClosureArgument) { - $element->setAttribute('type', 'service_closure'); - $value = $value->getValues()[0]; - } - $element->setAttribute('id', (string) $value); - $behavior = $value->getInvalidBehavior(); - if (ContainerInterface::NULL_ON_INVALID_REFERENCE == $behavior) { - $element->setAttribute('on-invalid', 'null'); - } elseif (ContainerInterface::IGNORE_ON_INVALID_REFERENCE == $behavior) { - $element->setAttribute('on-invalid', 'ignore'); - } elseif (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE == $behavior) { - $element->setAttribute('on-invalid', 'ignore_uninitialized'); - } - } elseif ($value instanceof Definition) { - $element->setAttribute('type', 'service'); - $this->addService($value, null, $element); - } elseif ($value instanceof Expression) { - $element->setAttribute('type', 'expression'); - $text = $this->document->createTextNode(self::phpToXml((string) $value)); - $element->appendChild($text); - } elseif (\is_string($value) && !preg_match('/^[^\x00-\x08\x0B\x0E-\x1A\x1C-\x1F\x7F]*+$/u', $value)) { - $element->setAttribute('type', 'binary'); - $text = $this->document->createTextNode(self::phpToXml(base64_encode($value))); - $element->appendChild($text); - } elseif ($value instanceof \UnitEnum) { - $element->setAttribute('type', 'constant'); - $element->appendChild($this->document->createTextNode(self::phpToXml($value))); - } elseif ($value instanceof AbstractArgument) { - $element->setAttribute('type', 'abstract'); - $text = $this->document->createTextNode(self::phpToXml($value->getText())); - $element->appendChild($text); - } else { - if (\in_array($value, ['null', 'true', 'false'], true)) { - $element->setAttribute('type', 'string'); - } - - if (\is_string($value) && (is_numeric($value) || preg_match('/^0b[01]*$/', $value) || preg_match('/^0x[0-9a-f]++$/i', $value))) { - $element->setAttribute('type', 'string'); - } - - $text = $this->document->createTextNode(self::phpToXml($value)); - $element->appendChild($text); - } - $parent->appendChild($element); - } - } - - /** - * Escapes arguments. - */ - private function escape(array $arguments): array - { - $args = []; - foreach ($arguments as $k => $v) { - if (\is_array($v)) { - $args[$k] = $this->escape($v); - } elseif (\is_string($v)) { - $args[$k] = str_replace('%', '%%', $v); - } else { - $args[$k] = $v; - } - } - - return $args; - } - - /** - * Converts php types to xml types. - * - * @param mixed $value Value to convert - * - * @throws RuntimeException When trying to dump object or resource - */ - public static function phpToXml($value): string - { - switch (true) { - case null === $value: - return 'null'; - case true === $value: - return 'true'; - case false === $value: - return 'false'; - case $value instanceof Parameter: - return '%'.$value.'%'; - case $value instanceof \UnitEnum: - return sprintf('%s::%s', \get_class($value), $value->name); - case \is_object($value) || \is_resource($value): - throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.'); - default: - return (string) $value; - } - } -} diff --git a/lib/symfony/dependency-injection/Dumper/YamlDumper.php b/lib/symfony/dependency-injection/Dumper/YamlDumper.php deleted file mode 100644 index 823eb97b0..000000000 --- a/lib/symfony/dependency-injection/Dumper/YamlDumper.php +++ /dev/null @@ -1,375 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Dumper; - -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\AbstractArgument; -use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\LogicException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Parameter; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\ExpressionLanguage\Expression; -use Symfony\Component\Yaml\Dumper as YmlDumper; -use Symfony\Component\Yaml\Parser; -use Symfony\Component\Yaml\Tag\TaggedValue; -use Symfony\Component\Yaml\Yaml; - -/** - * YamlDumper dumps a service container as a YAML string. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class YamlDumper extends Dumper -{ - private $dumper; - - /** - * Dumps the service container as an YAML string. - * - * @return string - */ - public function dump(array $options = []) - { - if (!class_exists(\Symfony\Component\Yaml\Dumper::class)) { - throw new LogicException('Unable to dump the container as the Symfony Yaml Component is not installed.'); - } - - if (null === $this->dumper) { - $this->dumper = new YmlDumper(); - } - - return $this->container->resolveEnvPlaceholders($this->addParameters()."\n".$this->addServices()); - } - - private function addService(string $id, Definition $definition): string - { - $code = " $id:\n"; - if ($class = $definition->getClass()) { - if ('\\' === substr($class, 0, 1)) { - $class = substr($class, 1); - } - - $code .= sprintf(" class: %s\n", $this->dumper->dump($class)); - } - - if (!$definition->isPrivate()) { - $code .= sprintf(" public: %s\n", $definition->isPublic() ? 'true' : 'false'); - } - - $tagsCode = ''; - foreach ($definition->getTags() as $name => $tags) { - foreach ($tags as $attributes) { - $att = []; - foreach ($attributes as $key => $value) { - $att[] = sprintf('%s: %s', $this->dumper->dump($key), $this->dumper->dump($value)); - } - $att = $att ? ': { '.implode(', ', $att).' }' : ''; - - $tagsCode .= sprintf(" - %s%s\n", $this->dumper->dump($name), $att); - } - } - if ($tagsCode) { - $code .= " tags:\n".$tagsCode; - } - - if ($definition->getFile()) { - $code .= sprintf(" file: %s\n", $this->dumper->dump($definition->getFile())); - } - - if ($definition->isSynthetic()) { - $code .= " synthetic: true\n"; - } - - if ($definition->isDeprecated()) { - $code .= " deprecated:\n"; - foreach ($definition->getDeprecation('%service_id%') as $key => $value) { - if ('' !== $value) { - $code .= sprintf(" %s: %s\n", $key, $this->dumper->dump($value)); - } - } - } - - if ($definition->isAutowired()) { - $code .= " autowire: true\n"; - } - - if ($definition->isAutoconfigured()) { - $code .= " autoconfigure: true\n"; - } - - if ($definition->isAbstract()) { - $code .= " abstract: true\n"; - } - - if ($definition->isLazy()) { - $code .= " lazy: true\n"; - } - - if ($definition->getArguments()) { - $code .= sprintf(" arguments: %s\n", $this->dumper->dump($this->dumpValue($definition->getArguments()), 0)); - } - - if ($definition->getProperties()) { - $code .= sprintf(" properties: %s\n", $this->dumper->dump($this->dumpValue($definition->getProperties()), 0)); - } - - if ($definition->getMethodCalls()) { - $code .= sprintf(" calls:\n%s\n", $this->dumper->dump($this->dumpValue($definition->getMethodCalls()), 1, 12)); - } - - if (!$definition->isShared()) { - $code .= " shared: false\n"; - } - - if (null !== $decoratedService = $definition->getDecoratedService()) { - [$decorated, $renamedId, $priority] = $decoratedService; - $code .= sprintf(" decorates: %s\n", $decorated); - if (null !== $renamedId) { - $code .= sprintf(" decoration_inner_name: %s\n", $renamedId); - } - if (0 !== $priority) { - $code .= sprintf(" decoration_priority: %s\n", $priority); - } - - $decorationOnInvalid = $decoratedService[3] ?? ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; - if (\in_array($decorationOnInvalid, [ContainerInterface::IGNORE_ON_INVALID_REFERENCE, ContainerInterface::NULL_ON_INVALID_REFERENCE])) { - $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE === $decorationOnInvalid ? 'null' : 'ignore'; - $code .= sprintf(" decoration_on_invalid: %s\n", $invalidBehavior); - } - } - - if ($callable = $definition->getFactory()) { - $code .= sprintf(" factory: %s\n", $this->dumper->dump($this->dumpCallable($callable), 0)); - } - - if ($callable = $definition->getConfigurator()) { - $code .= sprintf(" configurator: %s\n", $this->dumper->dump($this->dumpCallable($callable), 0)); - } - - return $code; - } - - private function addServiceAlias(string $alias, Alias $id): string - { - $deprecated = ''; - - if ($id->isDeprecated()) { - $deprecated = " deprecated:\n"; - - foreach ($id->getDeprecation('%alias_id%') as $key => $value) { - if ('' !== $value) { - $deprecated .= sprintf(" %s: %s\n", $key, $value); - } - } - } - - if (!$id->isDeprecated() && $id->isPrivate()) { - return sprintf(" %s: '@%s'\n", $alias, $id); - } - - if ($id->isPublic()) { - $deprecated = " public: true\n".$deprecated; - } - - return sprintf(" %s:\n alias: %s\n%s", $alias, $id, $deprecated); - } - - private function addServices(): string - { - if (!$this->container->getDefinitions()) { - return ''; - } - - $code = "services:\n"; - foreach ($this->container->getDefinitions() as $id => $definition) { - $code .= $this->addService($id, $definition); - } - - $aliases = $this->container->getAliases(); - foreach ($aliases as $alias => $id) { - while (isset($aliases[(string) $id])) { - $id = $aliases[(string) $id]; - } - $code .= $this->addServiceAlias($alias, $id); - } - - return $code; - } - - private function addParameters(): string - { - if (!$this->container->getParameterBag()->all()) { - return ''; - } - - $parameters = $this->prepareParameters($this->container->getParameterBag()->all(), $this->container->isCompiled()); - - return $this->dumper->dump(['parameters' => $parameters], 2); - } - - /** - * Dumps callable to YAML format. - * - * @param mixed $callable - * - * @return mixed - */ - private function dumpCallable($callable) - { - if (\is_array($callable)) { - if ($callable[0] instanceof Reference) { - $callable = [$this->getServiceCall((string) $callable[0], $callable[0]), $callable[1]]; - } else { - $callable = [$callable[0], $callable[1]]; - } - } - - return $callable; - } - - /** - * Dumps the value to YAML format. - * - * @return mixed - * - * @throws RuntimeException When trying to dump object or resource - */ - private function dumpValue($value) - { - if ($value instanceof ServiceClosureArgument) { - $value = $value->getValues()[0]; - - return new TaggedValue('service_closure', $this->getServiceCall((string) $value, $value)); - } - if ($value instanceof ArgumentInterface) { - $tag = $value; - - if ($value instanceof TaggedIteratorArgument || ($value instanceof ServiceLocatorArgument && $tag = $value->getTaggedIteratorArgument())) { - if (null === $tag->getIndexAttribute()) { - $content = $tag->getTag(); - } else { - $content = [ - 'tag' => $tag->getTag(), - 'index_by' => $tag->getIndexAttribute(), - ]; - - if (null !== $tag->getDefaultIndexMethod()) { - $content['default_index_method'] = $tag->getDefaultIndexMethod(); - } - if (null !== $tag->getDefaultPriorityMethod()) { - $content['default_priority_method'] = $tag->getDefaultPriorityMethod(); - } - } - - return new TaggedValue($value instanceof TaggedIteratorArgument ? 'tagged_iterator' : 'tagged_locator', $content); - } - - if ($value instanceof IteratorArgument) { - $tag = 'iterator'; - } elseif ($value instanceof ServiceLocatorArgument) { - $tag = 'service_locator'; - } else { - throw new RuntimeException(sprintf('Unspecified Yaml tag for type "%s".', get_debug_type($value))); - } - - return new TaggedValue($tag, $this->dumpValue($value->getValues())); - } - - if (\is_array($value)) { - $code = []; - foreach ($value as $k => $v) { - $code[$k] = $this->dumpValue($v); - } - - return $code; - } elseif ($value instanceof Reference) { - return $this->getServiceCall((string) $value, $value); - } elseif ($value instanceof Parameter) { - return $this->getParameterCall((string) $value); - } elseif ($value instanceof Expression) { - return $this->getExpressionCall((string) $value); - } elseif ($value instanceof Definition) { - return new TaggedValue('service', (new Parser())->parse("_:\n".$this->addService('_', $value), Yaml::PARSE_CUSTOM_TAGS)['_']['_']); - } elseif ($value instanceof \UnitEnum) { - return new TaggedValue('php/const', sprintf('%s::%s', \get_class($value), $value->name)); - } elseif ($value instanceof AbstractArgument) { - return new TaggedValue('abstract', $value->getText()); - } elseif (\is_object($value) || \is_resource($value)) { - throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.'); - } - - return $value; - } - - private function getServiceCall(string $id, Reference $reference = null): string - { - if (null !== $reference) { - switch ($reference->getInvalidBehavior()) { - case ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE: break; - case ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE: break; - case ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE: return sprintf('@!%s', $id); - default: return sprintf('@?%s', $id); - } - } - - return sprintf('@%s', $id); - } - - private function getParameterCall(string $id): string - { - return sprintf('%%%s%%', $id); - } - - private function getExpressionCall(string $expression): string - { - return sprintf('@=%s', $expression); - } - - private function prepareParameters(array $parameters, bool $escape = true): array - { - $filtered = []; - foreach ($parameters as $key => $value) { - if (\is_array($value)) { - $value = $this->prepareParameters($value, $escape); - } elseif ($value instanceof Reference || \is_string($value) && str_starts_with($value, '@')) { - $value = '@'.$value; - } - - $filtered[$key] = $value; - } - - return $escape ? $this->escape($filtered) : $filtered; - } - - private function escape(array $arguments): array - { - $args = []; - foreach ($arguments as $k => $v) { - if (\is_array($v)) { - $args[$k] = $this->escape($v); - } elseif (\is_string($v)) { - $args[$k] = str_replace('%', '%%', $v); - } else { - $args[$k] = $v; - } - } - - return $args; - } -} diff --git a/lib/symfony/dependency-injection/EnvVarLoaderInterface.php b/lib/symfony/dependency-injection/EnvVarLoaderInterface.php deleted file mode 100644 index 0c547f8a5..000000000 --- a/lib/symfony/dependency-injection/EnvVarLoaderInterface.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -/** - * EnvVarLoaderInterface objects return key/value pairs that are added to the list of available env vars. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -interface EnvVarLoaderInterface -{ - /** - * @return string[] Key/value pairs that can be accessed using the regular "%env()%" syntax - */ - public function loadEnvVars(): array; -} diff --git a/lib/symfony/dependency-injection/EnvVarProcessor.php b/lib/symfony/dependency-injection/EnvVarProcessor.php deleted file mode 100644 index feb51fff3..000000000 --- a/lib/symfony/dependency-injection/EnvVarProcessor.php +++ /dev/null @@ -1,304 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException; -use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class EnvVarProcessor implements EnvVarProcessorInterface -{ - private $container; - private $loaders; - private $loadedVars = []; - - /** - * @param EnvVarLoaderInterface[] $loaders - */ - public function __construct(ContainerInterface $container, \Traversable $loaders = null) - { - $this->container = $container; - $this->loaders = $loaders ?? new \ArrayIterator(); - } - - /** - * {@inheritdoc} - */ - public static function getProvidedTypes() - { - return [ - 'base64' => 'string', - 'bool' => 'bool', - 'not' => 'bool', - 'const' => 'bool|int|float|string|array', - 'csv' => 'array', - 'file' => 'string', - 'float' => 'float', - 'int' => 'int', - 'json' => 'array', - 'key' => 'bool|int|float|string|array', - 'url' => 'array', - 'query_string' => 'array', - 'resolve' => 'string', - 'default' => 'bool|int|float|string|array', - 'string' => 'string', - 'trim' => 'string', - 'require' => 'bool|int|float|string|array', - ]; - } - - /** - * {@inheritdoc} - */ - public function getEnv(string $prefix, string $name, \Closure $getEnv) - { - $i = strpos($name, ':'); - - if ('key' === $prefix) { - if (false === $i) { - throw new RuntimeException(sprintf('Invalid env "key:%s": a key specifier should be provided.', $name)); - } - - $next = substr($name, $i + 1); - $key = substr($name, 0, $i); - $array = $getEnv($next); - - if (!\is_array($array)) { - throw new RuntimeException(sprintf('Resolved value of "%s" did not result in an array value.', $next)); - } - - if (!isset($array[$key]) && !\array_key_exists($key, $array)) { - throw new EnvNotFoundException(sprintf('Key "%s" not found in %s (resolved from "%s").', $key, json_encode($array), $next)); - } - - return $array[$key]; - } - - if ('default' === $prefix) { - if (false === $i) { - throw new RuntimeException(sprintf('Invalid env "default:%s": a fallback parameter should be provided.', $name)); - } - - $next = substr($name, $i + 1); - $default = substr($name, 0, $i); - - if ('' !== $default && !$this->container->hasParameter($default)) { - throw new RuntimeException(sprintf('Invalid env fallback in "default:%s": parameter "%s" not found.', $name, $default)); - } - - try { - $env = $getEnv($next); - - if ('' !== $env && null !== $env) { - return $env; - } - } catch (EnvNotFoundException $e) { - // no-op - } - - return '' === $default ? null : $this->container->getParameter($default); - } - - if ('file' === $prefix || 'require' === $prefix) { - if (!\is_scalar($file = $getEnv($name))) { - throw new RuntimeException(sprintf('Invalid file name: env var "%s" is non-scalar.', $name)); - } - if (!is_file($file)) { - throw new EnvNotFoundException(sprintf('File "%s" not found (resolved from "%s").', $file, $name)); - } - - if ('file' === $prefix) { - return file_get_contents($file); - } else { - return require $file; - } - } - - if (false !== $i || 'string' !== $prefix) { - $env = $getEnv($name); - } elseif (isset($_ENV[$name])) { - $env = $_ENV[$name]; - } elseif (isset($_SERVER[$name]) && !str_starts_with($name, 'HTTP_')) { - $env = $_SERVER[$name]; - } elseif (false === ($env = getenv($name)) || null === $env) { // null is a possible value because of thread safety issues - foreach ($this->loadedVars as $vars) { - if (false !== $env = ($vars[$name] ?? false)) { - break; - } - } - - if (false === $env || null === $env) { - $loaders = $this->loaders; - $this->loaders = new \ArrayIterator(); - - try { - $i = 0; - $ended = true; - $count = $loaders instanceof \Countable ? $loaders->count() : 0; - foreach ($loaders as $loader) { - if (\count($this->loadedVars) > $i++) { - continue; - } - $this->loadedVars[] = $vars = $loader->loadEnvVars(); - if (false !== $env = $vars[$name] ?? false) { - $ended = false; - break; - } - } - if ($ended || $count === $i) { - $loaders = $this->loaders; - } - } catch (ParameterCircularReferenceException $e) { - // skip loaders that need an env var that is not defined - } finally { - $this->loaders = $loaders; - } - } - - if (false === $env || null === $env) { - if (!$this->container->hasParameter("env($name)")) { - throw new EnvNotFoundException(sprintf('Environment variable not found: "%s".', $name)); - } - - $env = $this->container->getParameter("env($name)"); - } - } - - if (null === $env) { - if (!isset($this->getProvidedTypes()[$prefix])) { - throw new RuntimeException(sprintf('Unsupported env var prefix "%s".', $prefix)); - } - - return null; - } - - if (!\is_scalar($env)) { - throw new RuntimeException(sprintf('Non-scalar env var "%s" cannot be cast to "%s".', $name, $prefix)); - } - - if ('string' === $prefix) { - return (string) $env; - } - - if (\in_array($prefix, ['bool', 'not'], true)) { - $env = (bool) (filter_var($env, \FILTER_VALIDATE_BOOLEAN) ?: filter_var($env, \FILTER_VALIDATE_INT) ?: filter_var($env, \FILTER_VALIDATE_FLOAT)); - - return 'not' === $prefix ? !$env : $env; - } - - if ('int' === $prefix) { - if (false === $env = filter_var($env, \FILTER_VALIDATE_INT) ?: filter_var($env, \FILTER_VALIDATE_FLOAT)) { - throw new RuntimeException(sprintf('Non-numeric env var "%s" cannot be cast to int.', $name)); - } - - return (int) $env; - } - - if ('float' === $prefix) { - if (false === $env = filter_var($env, \FILTER_VALIDATE_FLOAT)) { - throw new RuntimeException(sprintf('Non-numeric env var "%s" cannot be cast to float.', $name)); - } - - return (float) $env; - } - - if ('const' === $prefix) { - if (!\defined($env)) { - throw new RuntimeException(sprintf('Env var "%s" maps to undefined constant "%s".', $name, $env)); - } - - return \constant($env); - } - - if ('base64' === $prefix) { - return base64_decode(strtr($env, '-_', '+/')); - } - - if ('json' === $prefix) { - $env = json_decode($env, true); - - if (\JSON_ERROR_NONE !== json_last_error()) { - throw new RuntimeException(sprintf('Invalid JSON in env var "%s": ', $name).json_last_error_msg()); - } - - if (null !== $env && !\is_array($env)) { - throw new RuntimeException(sprintf('Invalid JSON env var "%s": array or null expected, "%s" given.', $name, get_debug_type($env))); - } - - return $env; - } - - if ('url' === $prefix) { - $parsedEnv = parse_url($env); - - if (false === $parsedEnv) { - throw new RuntimeException(sprintf('Invalid URL in env var "%s".', $name)); - } - if (!isset($parsedEnv['scheme'], $parsedEnv['host'])) { - throw new RuntimeException(sprintf('Invalid URL env var "%s": schema and host expected, "%s" given.', $name, $env)); - } - $parsedEnv += [ - 'port' => null, - 'user' => null, - 'pass' => null, - 'path' => null, - 'query' => null, - 'fragment' => null, - ]; - - // remove the '/' separator - $parsedEnv['path'] = '/' === ($parsedEnv['path'] ?? '/') ? '' : substr($parsedEnv['path'], 1); - - return $parsedEnv; - } - - if ('query_string' === $prefix) { - $queryString = parse_url($env, \PHP_URL_QUERY) ?: $env; - parse_str($queryString, $result); - - return $result; - } - - if ('resolve' === $prefix) { - return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($name, $getEnv) { - if (!isset($match[1])) { - return '%'; - } - - if (str_starts_with($match[1], 'env(') && str_ends_with($match[1], ')') && 'env()' !== $match[1]) { - $value = $getEnv(substr($match[1], 4, -1)); - } else { - $value = $this->container->getParameter($match[1]); - } - - if (!\is_scalar($value)) { - throw new RuntimeException(sprintf('Parameter "%s" found when resolving env var "%s" must be scalar, "%s" given.', $match[1], $name, get_debug_type($value))); - } - - return $value; - }, $env); - } - - if ('csv' === $prefix) { - return str_getcsv($env, ',', '"', \PHP_VERSION_ID >= 70400 ? '' : '\\'); - } - - if ('trim' === $prefix) { - return trim($env); - } - - throw new RuntimeException(sprintf('Unsupported env var prefix "%s" for env name "%s".', $prefix, $name)); - } -} diff --git a/lib/symfony/dependency-injection/EnvVarProcessorInterface.php b/lib/symfony/dependency-injection/EnvVarProcessorInterface.php deleted file mode 100644 index d3275fe29..000000000 --- a/lib/symfony/dependency-injection/EnvVarProcessorInterface.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -use Symfony\Component\DependencyInjection\Exception\RuntimeException; - -/** - * The EnvVarProcessorInterface is implemented by objects that manage environment-like variables. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -interface EnvVarProcessorInterface -{ - /** - * Returns the value of the given variable as managed by the current instance. - * - * @param string $prefix The namespace of the variable - * @param string $name The name of the variable within the namespace - * @param \Closure $getEnv A closure that allows fetching more env vars - * - * @return mixed - * - * @throws RuntimeException on error - */ - public function getEnv(string $prefix, string $name, \Closure $getEnv); - - /** - * @return string[] The PHP-types managed by getEnv(), keyed by prefixes - */ - public static function getProvidedTypes(); -} diff --git a/lib/symfony/dependency-injection/Exception/AutowiringFailedException.php b/lib/symfony/dependency-injection/Exception/AutowiringFailedException.php deleted file mode 100644 index 0006f5621..000000000 --- a/lib/symfony/dependency-injection/Exception/AutowiringFailedException.php +++ /dev/null @@ -1,74 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -/** - * Thrown when a definition cannot be autowired. - */ -class AutowiringFailedException extends RuntimeException -{ - private $serviceId; - private $messageCallback; - - public function __construct(string $serviceId, $message = '', int $code = 0, \Throwable $previous = null) - { - $this->serviceId = $serviceId; - - if ($message instanceof \Closure - && (\function_exists('xdebug_is_enabled') ? xdebug_is_enabled() : \function_exists('xdebug_info')) - ) { - $message = $message(); - } - - if (!$message instanceof \Closure) { - parent::__construct($message, $code, $previous); - - return; - } - - $this->messageCallback = $message; - parent::__construct('', $code, $previous); - - $this->message = new class($this->message, $this->messageCallback) { - private $message; - private $messageCallback; - - public function __construct(&$message, &$messageCallback) - { - $this->message = &$message; - $this->messageCallback = &$messageCallback; - } - - public function __toString(): string - { - $messageCallback = $this->messageCallback; - $this->messageCallback = null; - - try { - return $this->message = $messageCallback(); - } catch (\Throwable $e) { - return $this->message = $e->getMessage(); - } - } - }; - } - - public function getMessageCallback(): ?\Closure - { - return $this->messageCallback; - } - - public function getServiceId() - { - return $this->serviceId; - } -} diff --git a/lib/symfony/dependency-injection/Exception/BadMethodCallException.php b/lib/symfony/dependency-injection/Exception/BadMethodCallException.php deleted file mode 100644 index 959238e93..000000000 --- a/lib/symfony/dependency-injection/Exception/BadMethodCallException.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -/** - * Base BadMethodCallException for Dependency Injection component. - */ -class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface -{ -} diff --git a/lib/symfony/dependency-injection/Exception/EnvNotFoundException.php b/lib/symfony/dependency-injection/Exception/EnvNotFoundException.php deleted file mode 100644 index 04ac84800..000000000 --- a/lib/symfony/dependency-injection/Exception/EnvNotFoundException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -/** - * This exception is thrown when an environment variable is not found. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class EnvNotFoundException extends InvalidArgumentException -{ -} diff --git a/lib/symfony/dependency-injection/Exception/EnvParameterException.php b/lib/symfony/dependency-injection/Exception/EnvParameterException.php deleted file mode 100644 index 48b5e486a..000000000 --- a/lib/symfony/dependency-injection/Exception/EnvParameterException.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -/** - * This exception wraps exceptions whose messages contain a reference to an env parameter. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class EnvParameterException extends InvalidArgumentException -{ - public function __construct(array $envs, \Throwable $previous = null, string $message = 'Incompatible use of dynamic environment variables "%s" found in parameters.') - { - parent::__construct(sprintf($message, implode('", "', $envs)), 0, $previous); - } -} diff --git a/lib/symfony/dependency-injection/Exception/ExceptionInterface.php b/lib/symfony/dependency-injection/Exception/ExceptionInterface.php deleted file mode 100644 index 6202df76e..000000000 --- a/lib/symfony/dependency-injection/Exception/ExceptionInterface.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -use Psr\Container\ContainerExceptionInterface; - -/** - * Base ExceptionInterface for Dependency Injection component. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Bulat Shakirzyanov <bulat@theopenskyproject.com> - */ -interface ExceptionInterface extends ContainerExceptionInterface, \Throwable -{ -} diff --git a/lib/symfony/dependency-injection/Exception/InvalidArgumentException.php b/lib/symfony/dependency-injection/Exception/InvalidArgumentException.php deleted file mode 100644 index 119bb7d19..000000000 --- a/lib/symfony/dependency-injection/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -/** - * Base InvalidArgumentException for Dependency Injection component. - * - * @author Bulat Shakirzyanov <bulat@theopenskyproject.com> - */ -class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/lib/symfony/dependency-injection/Exception/InvalidParameterTypeException.php b/lib/symfony/dependency-injection/Exception/InvalidParameterTypeException.php deleted file mode 100644 index 2a11626fe..000000000 --- a/lib/symfony/dependency-injection/Exception/InvalidParameterTypeException.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -/** - * Thrown when trying to inject a parameter into a constructor/method with an incompatible type. - * - * @author Nicolas Grekas <p@tchwork.com> - * @author Julien Maulny <jmaulny@darkmira.fr> - */ -class InvalidParameterTypeException extends InvalidArgumentException -{ - public function __construct(string $serviceId, string $type, \ReflectionParameter $parameter) - { - $acceptedType = $parameter->getType(); - $acceptedType = $acceptedType instanceof \ReflectionNamedType ? $acceptedType->getName() : (string) $acceptedType; - $this->code = $type; - - $function = $parameter->getDeclaringFunction(); - $functionName = $function instanceof \ReflectionMethod - ? sprintf('%s::%s', $function->getDeclaringClass()->getName(), $function->getName()) - : $function->getName(); - - parent::__construct(sprintf('Invalid definition for service "%s": argument %d of "%s()" accepts "%s", "%s" passed.', $serviceId, 1 + $parameter->getPosition(), $functionName, $acceptedType, $type)); - } -} diff --git a/lib/symfony/dependency-injection/Exception/LogicException.php b/lib/symfony/dependency-injection/Exception/LogicException.php deleted file mode 100644 index 17a070ca8..000000000 --- a/lib/symfony/dependency-injection/Exception/LogicException.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -/** - * Base LogicException for Dependency Injection component. - */ -class LogicException extends \LogicException implements ExceptionInterface -{ -} diff --git a/lib/symfony/dependency-injection/Exception/OutOfBoundsException.php b/lib/symfony/dependency-injection/Exception/OutOfBoundsException.php deleted file mode 100644 index a61f143b3..000000000 --- a/lib/symfony/dependency-injection/Exception/OutOfBoundsException.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -/** - * Base OutOfBoundsException for Dependency Injection component. - */ -class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface -{ -} diff --git a/lib/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php b/lib/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php deleted file mode 100644 index 2450ccb5c..000000000 --- a/lib/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -/** - * This exception is thrown when a circular reference in a parameter is detected. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class ParameterCircularReferenceException extends RuntimeException -{ - private $parameters; - - public function __construct(array $parameters, \Throwable $previous = null) - { - parent::__construct(sprintf('Circular reference detected for parameter "%s" ("%s" > "%s").', $parameters[0], implode('" > "', $parameters), $parameters[0]), 0, $previous); - - $this->parameters = $parameters; - } - - public function getParameters() - { - return $this->parameters; - } -} diff --git a/lib/symfony/dependency-injection/Exception/ParameterNotFoundException.php b/lib/symfony/dependency-injection/Exception/ParameterNotFoundException.php deleted file mode 100644 index 5d3831014..000000000 --- a/lib/symfony/dependency-injection/Exception/ParameterNotFoundException.php +++ /dev/null @@ -1,100 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -use Psr\Container\NotFoundExceptionInterface; - -/** - * This exception is thrown when a non-existent parameter is used. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class ParameterNotFoundException extends InvalidArgumentException implements NotFoundExceptionInterface -{ - private $key; - private $sourceId; - private $sourceKey; - private $alternatives; - private $nonNestedAlternative; - - /** - * @param string $key The requested parameter key - * @param string|null $sourceId The service id that references the non-existent parameter - * @param string|null $sourceKey The parameter key that references the non-existent parameter - * @param \Throwable|null $previous The previous exception - * @param string[] $alternatives Some parameter name alternatives - * @param string|null $nonNestedAlternative The alternative parameter name when the user expected dot notation for nested parameters - */ - public function __construct(string $key, string $sourceId = null, string $sourceKey = null, \Throwable $previous = null, array $alternatives = [], string $nonNestedAlternative = null) - { - $this->key = $key; - $this->sourceId = $sourceId; - $this->sourceKey = $sourceKey; - $this->alternatives = $alternatives; - $this->nonNestedAlternative = $nonNestedAlternative; - - parent::__construct('', 0, $previous); - - $this->updateRepr(); - } - - public function updateRepr() - { - if (null !== $this->sourceId) { - $this->message = sprintf('The service "%s" has a dependency on a non-existent parameter "%s".', $this->sourceId, $this->key); - } elseif (null !== $this->sourceKey) { - $this->message = sprintf('The parameter "%s" has a dependency on a non-existent parameter "%s".', $this->sourceKey, $this->key); - } else { - $this->message = sprintf('You have requested a non-existent parameter "%s".', $this->key); - } - - if ($this->alternatives) { - if (1 == \count($this->alternatives)) { - $this->message .= ' Did you mean this: "'; - } else { - $this->message .= ' Did you mean one of these: "'; - } - $this->message .= implode('", "', $this->alternatives).'"?'; - } elseif (null !== $this->nonNestedAlternative) { - $this->message .= ' You cannot access nested array items, do you want to inject "'.$this->nonNestedAlternative.'" instead?'; - } - } - - public function getKey() - { - return $this->key; - } - - public function getSourceId() - { - return $this->sourceId; - } - - public function getSourceKey() - { - return $this->sourceKey; - } - - public function setSourceId(?string $sourceId) - { - $this->sourceId = $sourceId; - - $this->updateRepr(); - } - - public function setSourceKey(?string $sourceKey) - { - $this->sourceKey = $sourceKey; - - $this->updateRepr(); - } -} diff --git a/lib/symfony/dependency-injection/Exception/RuntimeException.php b/lib/symfony/dependency-injection/Exception/RuntimeException.php deleted file mode 100644 index 5c2454120..000000000 --- a/lib/symfony/dependency-injection/Exception/RuntimeException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -/** - * Base RuntimeException for Dependency Injection component. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class RuntimeException extends \RuntimeException implements ExceptionInterface -{ -} diff --git a/lib/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php b/lib/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php deleted file mode 100644 index a38671bcf..000000000 --- a/lib/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -/** - * This exception is thrown when a circular reference is detected. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class ServiceCircularReferenceException extends RuntimeException -{ - private $serviceId; - private $path; - - public function __construct(string $serviceId, array $path, \Throwable $previous = null) - { - parent::__construct(sprintf('Circular reference detected for service "%s", path: "%s".', $serviceId, implode(' -> ', $path)), 0, $previous); - - $this->serviceId = $serviceId; - $this->path = $path; - } - - public function getServiceId() - { - return $this->serviceId; - } - - public function getPath() - { - return $this->path; - } -} diff --git a/lib/symfony/dependency-injection/Exception/ServiceNotFoundException.php b/lib/symfony/dependency-injection/Exception/ServiceNotFoundException.php deleted file mode 100644 index f91afae39..000000000 --- a/lib/symfony/dependency-injection/Exception/ServiceNotFoundException.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -use Psr\Container\NotFoundExceptionInterface; - -/** - * This exception is thrown when a non-existent service is requested. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class ServiceNotFoundException extends InvalidArgumentException implements NotFoundExceptionInterface -{ - private $id; - private $sourceId; - private $alternatives; - - public function __construct(string $id, string $sourceId = null, \Throwable $previous = null, array $alternatives = [], string $msg = null) - { - if (null !== $msg) { - // no-op - } elseif (null === $sourceId) { - $msg = sprintf('You have requested a non-existent service "%s".', $id); - } else { - $msg = sprintf('The service "%s" has a dependency on a non-existent service "%s".', $sourceId, $id); - } - - if ($alternatives) { - if (1 == \count($alternatives)) { - $msg .= ' Did you mean this: "'; - } else { - $msg .= ' Did you mean one of these: "'; - } - $msg .= implode('", "', $alternatives).'"?'; - } - - parent::__construct($msg, 0, $previous); - - $this->id = $id; - $this->sourceId = $sourceId; - $this->alternatives = $alternatives; - } - - public function getId() - { - return $this->id; - } - - public function getSourceId() - { - return $this->sourceId; - } - - public function getAlternatives() - { - return $this->alternatives; - } -} diff --git a/lib/symfony/dependency-injection/ExpressionLanguage.php b/lib/symfony/dependency-injection/ExpressionLanguage.php deleted file mode 100644 index 961c737e8..000000000 --- a/lib/symfony/dependency-injection/ExpressionLanguage.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage; - -if (!class_exists(BaseExpressionLanguage::class)) { - return; -} - -/** - * Adds some function to the default ExpressionLanguage. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @see ExpressionLanguageProvider - */ -class ExpressionLanguage extends BaseExpressionLanguage -{ - /** - * {@inheritdoc} - */ - public function __construct(CacheItemPoolInterface $cache = null, array $providers = [], callable $serviceCompiler = null) - { - // prepend the default provider to let users override it easily - array_unshift($providers, new ExpressionLanguageProvider($serviceCompiler)); - - parent::__construct($cache, $providers); - } -} diff --git a/lib/symfony/dependency-injection/ExpressionLanguageProvider.php b/lib/symfony/dependency-injection/ExpressionLanguageProvider.php deleted file mode 100644 index 9198ca0a4..000000000 --- a/lib/symfony/dependency-injection/ExpressionLanguageProvider.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -use Symfony\Component\ExpressionLanguage\ExpressionFunction; -use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; - -/** - * Define some ExpressionLanguage functions. - * - * To get a service, use service('request'). - * To get a parameter, use parameter('kernel.debug'). - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class ExpressionLanguageProvider implements ExpressionFunctionProviderInterface -{ - private $serviceCompiler; - - public function __construct(callable $serviceCompiler = null) - { - $this->serviceCompiler = $serviceCompiler; - } - - public function getFunctions() - { - return [ - new ExpressionFunction('service', $this->serviceCompiler ?: function ($arg) { - return sprintf('$this->get(%s)', $arg); - }, function (array $variables, $value) { - return $variables['container']->get($value); - }), - - new ExpressionFunction('parameter', function ($arg) { - return sprintf('$this->getParameter(%s)', $arg); - }, function (array $variables, $value) { - return $variables['container']->getParameter($value); - }), - ]; - } -} diff --git a/lib/symfony/dependency-injection/Extension/ConfigurationExtensionInterface.php b/lib/symfony/dependency-injection/Extension/ConfigurationExtensionInterface.php deleted file mode 100644 index a42967f4d..000000000 --- a/lib/symfony/dependency-injection/Extension/ConfigurationExtensionInterface.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Extension; - -use Symfony\Component\Config\Definition\ConfigurationInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * ConfigurationExtensionInterface is the interface implemented by container extension classes. - * - * @author Kevin Bond <kevinbond@gmail.com> - */ -interface ConfigurationExtensionInterface -{ - /** - * Returns extension configuration. - * - * @return ConfigurationInterface|null - */ - public function getConfiguration(array $config, ContainerBuilder $container); -} diff --git a/lib/symfony/dependency-injection/Extension/Extension.php b/lib/symfony/dependency-injection/Extension/Extension.php deleted file mode 100644 index ef6c1aaa3..000000000 --- a/lib/symfony/dependency-injection/Extension/Extension.php +++ /dev/null @@ -1,139 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Extension; - -use Symfony\Component\Config\Definition\ConfigurationInterface; -use Symfony\Component\Config\Definition\Processor; -use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\BadMethodCallException; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\LogicException; - -/** - * Provides useful features shared by many extensions. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -abstract class Extension implements ExtensionInterface, ConfigurationExtensionInterface -{ - private $processedConfigs = []; - - /** - * {@inheritdoc} - */ - public function getXsdValidationBasePath() - { - return false; - } - - /** - * {@inheritdoc} - */ - public function getNamespace() - { - return 'http://example.org/schema/dic/'.$this->getAlias(); - } - - /** - * Returns the recommended alias to use in XML. - * - * This alias is also the mandatory prefix to use when using YAML. - * - * This convention is to remove the "Extension" postfix from the class - * name and then lowercase and underscore the result. So: - * - * AcmeHelloExtension - * - * becomes - * - * acme_hello - * - * This can be overridden in a sub-class to specify the alias manually. - * - * @return string - * - * @throws BadMethodCallException When the extension name does not follow conventions - */ - public function getAlias() - { - $className = static::class; - if (!str_ends_with($className, 'Extension')) { - throw new BadMethodCallException('This extension does not follow the naming convention; you must overwrite the getAlias() method.'); - } - $classBaseName = substr(strrchr($className, '\\'), 1, -9); - - return Container::underscore($classBaseName); - } - - /** - * {@inheritdoc} - */ - public function getConfiguration(array $config, ContainerBuilder $container) - { - $class = static::class; - - if (str_contains($class, "\0")) { - return null; // ignore anonymous classes - } - - $class = substr_replace($class, '\Configuration', strrpos($class, '\\')); - $class = $container->getReflectionClass($class); - - if (!$class) { - return null; - } - - if (!$class->implementsInterface(ConfigurationInterface::class)) { - throw new LogicException(sprintf('The extension configuration class "%s" must implement "%s".', $class->getName(), ConfigurationInterface::class)); - } - - if (!($constructor = $class->getConstructor()) || !$constructor->getNumberOfRequiredParameters()) { - return $class->newInstance(); - } - - return null; - } - - final protected function processConfiguration(ConfigurationInterface $configuration, array $configs): array - { - $processor = new Processor(); - - return $this->processedConfigs[] = $processor->processConfiguration($configuration, $configs); - } - - /** - * @internal - */ - final public function getProcessedConfigs(): array - { - try { - return $this->processedConfigs; - } finally { - $this->processedConfigs = []; - } - } - - /** - * @return bool - * - * @throws InvalidArgumentException When the config is not enableable - */ - protected function isConfigEnabled(ContainerBuilder $container, array $config) - { - if (!\array_key_exists('enabled', $config)) { - throw new InvalidArgumentException("The config array has no 'enabled' key."); - } - - return (bool) $container->getParameterBag()->resolveValue($config['enabled']); - } -} diff --git a/lib/symfony/dependency-injection/Extension/ExtensionInterface.php b/lib/symfony/dependency-injection/Extension/ExtensionInterface.php deleted file mode 100644 index f2373ed5e..000000000 --- a/lib/symfony/dependency-injection/Extension/ExtensionInterface.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Extension; - -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * ExtensionInterface is the interface implemented by container extension classes. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface ExtensionInterface -{ - /** - * Loads a specific configuration. - * - * @throws \InvalidArgumentException When provided tag is not defined in this extension - */ - public function load(array $configs, ContainerBuilder $container); - - /** - * Returns the namespace to be used for this extension (XML namespace). - * - * @return string - */ - public function getNamespace(); - - /** - * Returns the base path for the XSD files. - * - * @return string|false - */ - public function getXsdValidationBasePath(); - - /** - * Returns the recommended alias to use in XML. - * - * This alias is also the mandatory prefix to use when using YAML. - * - * @return string - */ - public function getAlias(); -} diff --git a/lib/symfony/dependency-injection/Extension/PrependExtensionInterface.php b/lib/symfony/dependency-injection/Extension/PrependExtensionInterface.php deleted file mode 100644 index 5bd18d79f..000000000 --- a/lib/symfony/dependency-injection/Extension/PrependExtensionInterface.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Extension; - -use Symfony\Component\DependencyInjection\ContainerBuilder; - -interface PrependExtensionInterface -{ - /** - * Allow an extension to prepend the extension configurations. - */ - public function prepend(ContainerBuilder $container); -} diff --git a/lib/symfony/dependency-injection/LICENSE b/lib/symfony/dependency-injection/LICENSE deleted file mode 100644 index 88bf75bb4..000000000 --- a/lib/symfony/dependency-injection/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-2022 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -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/lib/symfony/dependency-injection/LazyProxy/Instantiator/InstantiatorInterface.php b/lib/symfony/dependency-injection/LazyProxy/Instantiator/InstantiatorInterface.php deleted file mode 100644 index a9d78115d..000000000 --- a/lib/symfony/dependency-injection/LazyProxy/Instantiator/InstantiatorInterface.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\LazyProxy\Instantiator; - -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; - -/** - * Lazy proxy instantiator, capable of instantiating a proxy given a container, the - * service definitions and a callback that produces the real service instance. - * - * @author Marco Pivetta <ocramius@gmail.com> - */ -interface InstantiatorInterface -{ - /** - * Instantiates a proxy object. - * - * @param string $id Identifier of the requested service - * @param callable $realInstantiator Zero-argument callback that is capable of producing the real service instance - * - * @return object - */ - public function instantiateProxy(ContainerInterface $container, Definition $definition, string $id, callable $realInstantiator); -} diff --git a/lib/symfony/dependency-injection/LazyProxy/Instantiator/RealServiceInstantiator.php b/lib/symfony/dependency-injection/LazyProxy/Instantiator/RealServiceInstantiator.php deleted file mode 100644 index 1696e7a90..000000000 --- a/lib/symfony/dependency-injection/LazyProxy/Instantiator/RealServiceInstantiator.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\LazyProxy\Instantiator; - -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; - -/** - * {@inheritdoc} - * - * Noop proxy instantiator - produces the real service instead of a proxy instance. - * - * @author Marco Pivetta <ocramius@gmail.com> - */ -class RealServiceInstantiator implements InstantiatorInterface -{ - /** - * {@inheritdoc} - */ - public function instantiateProxy(ContainerInterface $container, Definition $definition, string $id, callable $realInstantiator) - { - return $realInstantiator(); - } -} diff --git a/lib/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php b/lib/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php deleted file mode 100644 index 351560d29..000000000 --- a/lib/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\LazyProxy\PhpDumper; - -use Symfony\Component\DependencyInjection\Definition; - -/** - * Lazy proxy dumper capable of generating the instantiation logic PHP code for proxied services. - * - * @author Marco Pivetta <ocramius@gmail.com> - */ -interface DumperInterface -{ - /** - * Inspects whether the given definitions should produce proxy instantiation logic in the dumped container. - * - * @return bool - */ - public function isProxyCandidate(Definition $definition); - - /** - * Generates the code to be used to instantiate a proxy in the dumped factory code. - * - * @return string - */ - public function getProxyFactoryCode(Definition $definition, string $id, string $factoryCode); - - /** - * Generates the code for the lazy proxy. - * - * @return string - */ - public function getProxyCode(Definition $definition); -} diff --git a/lib/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php b/lib/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php deleted file mode 100644 index 7e0f14c32..000000000 --- a/lib/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\LazyProxy\PhpDumper; - -use Symfony\Component\DependencyInjection\Definition; - -/** - * Null dumper, negates any proxy code generation for any given service definition. - * - * @author Marco Pivetta <ocramius@gmail.com> - * - * @final - */ -class NullDumper implements DumperInterface -{ - /** - * {@inheritdoc} - */ - public function isProxyCandidate(Definition $definition): bool - { - return false; - } - - /** - * {@inheritdoc} - */ - public function getProxyFactoryCode(Definition $definition, string $id, string $factoryCode): string - { - return ''; - } - - /** - * {@inheritdoc} - */ - public function getProxyCode(Definition $definition): string - { - return ''; - } -} diff --git a/lib/symfony/dependency-injection/LazyProxy/ProxyHelper.php b/lib/symfony/dependency-injection/LazyProxy/ProxyHelper.php deleted file mode 100644 index f33011ad1..000000000 --- a/lib/symfony/dependency-injection/LazyProxy/ProxyHelper.php +++ /dev/null @@ -1,93 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\LazyProxy; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -class ProxyHelper -{ - /** - * @return string|null The FQCN or builtin name of the type hint, or null when the type hint references an invalid self|parent context - */ - public static function getTypeHint(\ReflectionFunctionAbstract $r, \ReflectionParameter $p = null, bool $noBuiltin = false): ?string - { - if ($p instanceof \ReflectionParameter) { - $type = $p->getType(); - } else { - $type = $r->getReturnType(); - } - if (!$type) { - return null; - } - - return self::getTypeHintForType($type, $r, $noBuiltin); - } - - private static function getTypeHintForType(\ReflectionType $type, \ReflectionFunctionAbstract $r, bool $noBuiltin): ?string - { - $types = []; - $glue = '|'; - if ($type instanceof \ReflectionUnionType) { - $reflectionTypes = $type->getTypes(); - } elseif ($type instanceof \ReflectionIntersectionType) { - $reflectionTypes = $type->getTypes(); - $glue = '&'; - } elseif ($type instanceof \ReflectionNamedType) { - $reflectionTypes = [$type]; - } else { - return null; - } - - foreach ($reflectionTypes as $type) { - if ($type instanceof \ReflectionIntersectionType) { - $typeHint = self::getTypeHintForType($type, $r, $noBuiltin); - if (null === $typeHint) { - return null; - } - - $types[] = sprintf('(%s)', $typeHint); - - continue; - } - - if ($type->isBuiltin()) { - if (!$noBuiltin) { - $types[] = $type->getName(); - } - continue; - } - - $lcName = strtolower($type->getName()); - $prefix = $noBuiltin ? '' : '\\'; - - if ('self' !== $lcName && 'parent' !== $lcName) { - $types[] = $prefix.$type->getName(); - continue; - } - if (!$r instanceof \ReflectionMethod) { - continue; - } - if ('self' === $lcName) { - $types[] = $prefix.$r->getDeclaringClass()->name; - } else { - $types[] = ($parent = $r->getDeclaringClass()->getParentClass()) ? $prefix.$parent->name : null; - } - } - - sort($types); - - return $types ? implode($glue, $types) : null; - } -} diff --git a/lib/symfony/dependency-injection/Loader/ClosureLoader.php b/lib/symfony/dependency-injection/Loader/ClosureLoader.php deleted file mode 100644 index fe2b91a2a..000000000 --- a/lib/symfony/dependency-injection/Loader/ClosureLoader.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader; - -use Symfony\Component\Config\Loader\Loader; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * ClosureLoader loads service definitions from a PHP closure. - * - * The Closure has access to the container as its first argument. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class ClosureLoader extends Loader -{ - private $container; - - public function __construct(ContainerBuilder $container, string $env = null) - { - $this->container = $container; - parent::__construct($env); - } - - /** - * {@inheritdoc} - */ - public function load($resource, string $type = null) - { - return $resource($this->container, $this->env); - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - return $resource instanceof \Closure; - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php b/lib/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php deleted file mode 100644 index 6de2d6764..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php +++ /dev/null @@ -1,119 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\Config\Loader\ParamConfigurator; -use Symfony\Component\DependencyInjection\Argument\AbstractArgument; -use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Parameter; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\ExpressionLanguage\Expression; - -abstract class AbstractConfigurator -{ - public const FACTORY = 'unknown'; - - /** - * @var callable(mixed, bool)|null - */ - public static $valuePreProcessor; - - /** @internal */ - protected $definition; - - public function __call(string $method, array $args) - { - if (method_exists($this, 'set'.$method)) { - return $this->{'set'.$method}(...$args); - } - - throw new \BadMethodCallException(sprintf('Call to undefined method "%s::%s()".', static::class, $method)); - } - - /** - * @return array - */ - public function __sleep() - { - throw new \BadMethodCallException('Cannot serialize '.__CLASS__); - } - - public function __wakeup() - { - throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); - } - - /** - * Checks that a value is valid, optionally replacing Definition and Reference configurators by their configure value. - * - * @param mixed $value - * @param bool $allowServices whether Definition and Reference are allowed; by default, only scalars and arrays are - * - * @return mixed the value, optionally cast to a Definition/Reference - */ - public static function processValue($value, $allowServices = false) - { - if (\is_array($value)) { - foreach ($value as $k => $v) { - $value[$k] = static::processValue($v, $allowServices); - } - - return self::$valuePreProcessor ? (self::$valuePreProcessor)($value, $allowServices) : $value; - } - - if (self::$valuePreProcessor) { - $value = (self::$valuePreProcessor)($value, $allowServices); - } - - if ($value instanceof ReferenceConfigurator) { - $reference = new Reference($value->id, $value->invalidBehavior); - - return $value instanceof ClosureReferenceConfigurator ? new ServiceClosureArgument($reference) : $reference; - } - - if ($value instanceof InlineServiceConfigurator) { - $def = $value->definition; - $value->definition = null; - - return $def; - } - - if ($value instanceof ParamConfigurator) { - return (string) $value; - } - - if ($value instanceof self) { - throw new InvalidArgumentException(sprintf('"%s()" can be used only at the root of service configuration files.', $value::FACTORY)); - } - - switch (true) { - case null === $value: - case \is_scalar($value): - return $value; - - case $value instanceof ArgumentInterface: - case $value instanceof Definition: - case $value instanceof Expression: - case $value instanceof Parameter: - case $value instanceof AbstractArgument: - case $value instanceof Reference: - if ($allowServices) { - return $value; - } - } - - throw new InvalidArgumentException(sprintf('Cannot use values of type "%s" in service configuration files.', get_debug_type($value))); - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php b/lib/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php deleted file mode 100644 index 96d6fd75a..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php +++ /dev/null @@ -1,115 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; - -abstract class AbstractServiceConfigurator extends AbstractConfigurator -{ - protected $parent; - protected $id; - private $defaultTags = []; - - public function __construct(ServicesConfigurator $parent, Definition $definition, string $id = null, array $defaultTags = []) - { - $this->parent = $parent; - $this->definition = $definition; - $this->id = $id; - $this->defaultTags = $defaultTags; - } - - public function __destruct() - { - // default tags should be added last - foreach ($this->defaultTags as $name => $attributes) { - foreach ($attributes as $attribute) { - $this->definition->addTag($name, $attribute); - } - } - $this->defaultTags = []; - } - - /** - * Registers a service. - */ - final public function set(?string $id, string $class = null): ServiceConfigurator - { - $this->__destruct(); - - return $this->parent->set($id, $class); - } - - /** - * Creates an alias. - */ - final public function alias(string $id, string $referencedId): AliasConfigurator - { - $this->__destruct(); - - return $this->parent->alias($id, $referencedId); - } - - /** - * Registers a PSR-4 namespace using a glob pattern. - */ - final public function load(string $namespace, string $resource): PrototypeConfigurator - { - $this->__destruct(); - - return $this->parent->load($namespace, $resource); - } - - /** - * Gets an already defined service definition. - * - * @throws ServiceNotFoundException if the service definition does not exist - */ - final public function get(string $id): ServiceConfigurator - { - $this->__destruct(); - - return $this->parent->get($id); - } - - /** - * Removes an already defined service definition or alias. - */ - final public function remove(string $id): ServicesConfigurator - { - $this->__destruct(); - - return $this->parent->remove($id); - } - - /** - * Registers a stack of decorator services. - * - * @param InlineServiceConfigurator[]|ReferenceConfigurator[] $services - */ - final public function stack(string $id, array $services): AliasConfigurator - { - $this->__destruct(); - - return $this->parent->stack($id, $services); - } - - /** - * Registers a service. - */ - final public function __invoke(string $id, string $class = null): ServiceConfigurator - { - $this->__destruct(); - - return $this->parent->set($id, $class); - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/AliasConfigurator.php b/lib/symfony/dependency-injection/Loader/Configurator/AliasConfigurator.php deleted file mode 100644 index 650a9568d..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/AliasConfigurator.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\DependencyInjection\Alias; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class AliasConfigurator extends AbstractServiceConfigurator -{ - use Traits\DeprecateTrait; - use Traits\PublicTrait; - - public const FACTORY = 'alias'; - - public function __construct(ServicesConfigurator $parent, Alias $alias) - { - $this->parent = $parent; - $this->definition = $alias; - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/ClosureReferenceConfigurator.php b/lib/symfony/dependency-injection/Loader/Configurator/ClosureReferenceConfigurator.php deleted file mode 100644 index ba83d91ef..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/ClosureReferenceConfigurator.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -class ClosureReferenceConfigurator extends ReferenceConfigurator -{ -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php b/lib/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php deleted file mode 100644 index ac6fdb6d0..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php +++ /dev/null @@ -1,212 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\Config\Loader\ParamConfigurator; -use Symfony\Component\DependencyInjection\Argument\AbstractArgument; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; -use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; -use Symfony\Component\ExpressionLanguage\Expression; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class ContainerConfigurator extends AbstractConfigurator -{ - public const FACTORY = 'container'; - - private $container; - private $loader; - private $instanceof; - private $path; - private $file; - private $anonymousCount = 0; - private $env; - - public function __construct(ContainerBuilder $container, PhpFileLoader $loader, array &$instanceof, string $path, string $file, string $env = null) - { - $this->container = $container; - $this->loader = $loader; - $this->instanceof = &$instanceof; - $this->path = $path; - $this->file = $file; - $this->env = $env; - } - - final public function extension(string $namespace, array $config) - { - if (!$this->container->hasExtension($namespace)) { - $extensions = array_filter(array_map(function (ExtensionInterface $ext) { return $ext->getAlias(); }, $this->container->getExtensions())); - throw new InvalidArgumentException(sprintf('There is no extension able to load the configuration for "%s" (in "%s"). Looked for namespace "%s", found "%s".', $namespace, $this->file, $namespace, $extensions ? implode('", "', $extensions) : 'none')); - } - - $this->container->loadFromExtension($namespace, static::processValue($config)); - } - - final public function import(string $resource, string $type = null, $ignoreErrors = false) - { - $this->loader->setCurrentDir(\dirname($this->path)); - $this->loader->import($resource, $type, $ignoreErrors, $this->file); - } - - final public function parameters(): ParametersConfigurator - { - return new ParametersConfigurator($this->container); - } - - final public function services(): ServicesConfigurator - { - return new ServicesConfigurator($this->container, $this->loader, $this->instanceof, $this->path, $this->anonymousCount); - } - - /** - * Get the current environment to be able to write conditional configuration. - */ - final public function env(): ?string - { - return $this->env; - } - - /** - * @return static - */ - final public function withPath(string $path): self - { - $clone = clone $this; - $clone->path = $clone->file = $path; - $clone->loader->setCurrentDir(\dirname($path)); - - return $clone; - } -} - -/** - * Creates a parameter. - */ -function param(string $name): ParamConfigurator -{ - return new ParamConfigurator($name); -} - -/** - * Creates a service reference. - * - * @deprecated since Symfony 5.1, use service() instead. - */ -function ref(string $id): ReferenceConfigurator -{ - trigger_deprecation('symfony/dependency-injection', '5.1', '"%s()" is deprecated, use "service()" instead.', __FUNCTION__); - - return new ReferenceConfigurator($id); -} - -/** - * Creates a reference to a service. - */ -function service(string $serviceId): ReferenceConfigurator -{ - return new ReferenceConfigurator($serviceId); -} - -/** - * Creates an inline service. - * - * @deprecated since Symfony 5.1, use inline_service() instead. - */ -function inline(string $class = null): InlineServiceConfigurator -{ - trigger_deprecation('symfony/dependency-injection', '5.1', '"%s()" is deprecated, use "inline_service()" instead.', __FUNCTION__); - - return new InlineServiceConfigurator(new Definition($class)); -} - -/** - * Creates an inline service. - */ -function inline_service(string $class = null): InlineServiceConfigurator -{ - return new InlineServiceConfigurator(new Definition($class)); -} - -/** - * Creates a service locator. - * - * @param ReferenceConfigurator[] $values - */ -function service_locator(array $values): ServiceLocatorArgument -{ - return new ServiceLocatorArgument(AbstractConfigurator::processValue($values, true)); -} - -/** - * Creates a lazy iterator. - * - * @param ReferenceConfigurator[] $values - */ -function iterator(array $values): IteratorArgument -{ - return new IteratorArgument(AbstractConfigurator::processValue($values, true)); -} - -/** - * Creates a lazy iterator by tag name. - */ -function tagged_iterator(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null, string $defaultPriorityMethod = null): TaggedIteratorArgument -{ - return new TaggedIteratorArgument($tag, $indexAttribute, $defaultIndexMethod, false, $defaultPriorityMethod); -} - -/** - * Creates a service locator by tag name. - */ -function tagged_locator(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null, string $defaultPriorityMethod = null): ServiceLocatorArgument -{ - return new ServiceLocatorArgument(new TaggedIteratorArgument($tag, $indexAttribute, $defaultIndexMethod, true, $defaultPriorityMethod)); -} - -/** - * Creates an expression. - */ -function expr(string $expression): Expression -{ - return new Expression($expression); -} - -/** - * Creates an abstract argument. - */ -function abstract_arg(string $description): AbstractArgument -{ - return new AbstractArgument($description); -} - -/** - * Creates an environment variable reference. - */ -function env(string $name): EnvConfigurator -{ - return new EnvConfigurator($name); -} - -/** - * Creates a closure service reference. - */ -function service_closure(string $serviceId): ClosureReferenceConfigurator -{ - return new ClosureReferenceConfigurator($serviceId); -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php b/lib/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php deleted file mode 100644 index e0b42750d..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class DefaultsConfigurator extends AbstractServiceConfigurator -{ - use Traits\AutoconfigureTrait; - use Traits\AutowireTrait; - use Traits\BindTrait; - use Traits\PublicTrait; - - public const FACTORY = 'defaults'; - - private $path; - - public function __construct(ServicesConfigurator $parent, Definition $definition, string $path = null) - { - parent::__construct($parent, $definition, null, []); - - $this->path = $path; - } - - /** - * Adds a tag for this definition. - * - * @return $this - * - * @throws InvalidArgumentException when an invalid tag name or attribute is provided - */ - final public function tag(string $name, array $attributes = []): self - { - if ('' === $name) { - throw new InvalidArgumentException('The tag name in "_defaults" must be a non-empty string.'); - } - - foreach ($attributes as $attribute => $value) { - if (null !== $value && !\is_scalar($value)) { - throw new InvalidArgumentException(sprintf('Tag "%s", attribute "%s" in "_defaults" must be of a scalar-type.', $name, $attribute)); - } - } - - $this->definition->addTag($name, $attributes); - - return $this; - } - - /** - * Defines an instanceof-conditional to be applied to following service definitions. - */ - final public function instanceof(string $fqcn): InstanceofConfigurator - { - return $this->parent->instanceof($fqcn); - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/EnvConfigurator.php b/lib/symfony/dependency-injection/Loader/Configurator/EnvConfigurator.php deleted file mode 100644 index d1864f564..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/EnvConfigurator.php +++ /dev/null @@ -1,224 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\Config\Loader\ParamConfigurator; - -class EnvConfigurator extends ParamConfigurator -{ - /** - * @var string[] - */ - private $stack; - - public function __construct(string $name) - { - $this->stack = explode(':', $name); - } - - public function __toString(): string - { - return '%env('.implode(':', $this->stack).')%'; - } - - /** - * @return $this - */ - public function __call(string $name, array $arguments): self - { - $processor = strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], '\1_\2', $name)); - - $this->custom($processor, ...$arguments); - - return $this; - } - - /** - * @return $this - */ - public function custom(string $processor, ...$args): self - { - array_unshift($this->stack, $processor, ...$args); - - return $this; - } - - /** - * @return $this - */ - public function base64(): self - { - array_unshift($this->stack, 'base64'); - - return $this; - } - - /** - * @return $this - */ - public function bool(): self - { - array_unshift($this->stack, 'bool'); - - return $this; - } - - /** - * @return $this - */ - public function not(): self - { - array_unshift($this->stack, 'not'); - - return $this; - } - - /** - * @return $this - */ - public function const(): self - { - array_unshift($this->stack, 'const'); - - return $this; - } - - /** - * @return $this - */ - public function csv(): self - { - array_unshift($this->stack, 'csv'); - - return $this; - } - - /** - * @return $this - */ - public function file(): self - { - array_unshift($this->stack, 'file'); - - return $this; - } - - /** - * @return $this - */ - public function float(): self - { - array_unshift($this->stack, 'float'); - - return $this; - } - - /** - * @return $this - */ - public function int(): self - { - array_unshift($this->stack, 'int'); - - return $this; - } - - /** - * @return $this - */ - public function json(): self - { - array_unshift($this->stack, 'json'); - - return $this; - } - - /** - * @return $this - */ - public function key(string $key): self - { - array_unshift($this->stack, 'key', $key); - - return $this; - } - - /** - * @return $this - */ - public function url(): self - { - array_unshift($this->stack, 'url'); - - return $this; - } - - /** - * @return $this - */ - public function queryString(): self - { - array_unshift($this->stack, 'query_string'); - - return $this; - } - - /** - * @return $this - */ - public function resolve(): self - { - array_unshift($this->stack, 'resolve'); - - return $this; - } - - /** - * @return $this - */ - public function default(string $fallbackParam): self - { - array_unshift($this->stack, 'default', $fallbackParam); - - return $this; - } - - /** - * @return $this - */ - public function string(): self - { - array_unshift($this->stack, 'string'); - - return $this; - } - - /** - * @return $this - */ - public function trim(): self - { - array_unshift($this->stack, 'trim'); - - return $this; - } - - /** - * @return $this - */ - public function require(): self - { - array_unshift($this->stack, 'require'); - - return $this; - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/InlineServiceConfigurator.php b/lib/symfony/dependency-injection/Loader/Configurator/InlineServiceConfigurator.php deleted file mode 100644 index da90a0a4c..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/InlineServiceConfigurator.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\DependencyInjection\Definition; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class InlineServiceConfigurator extends AbstractConfigurator -{ - use Traits\ArgumentTrait; - use Traits\AutowireTrait; - use Traits\BindTrait; - use Traits\CallTrait; - use Traits\ConfiguratorTrait; - use Traits\FactoryTrait; - use Traits\FileTrait; - use Traits\LazyTrait; - use Traits\ParentTrait; - use Traits\PropertyTrait; - use Traits\TagTrait; - - public const FACTORY = 'service'; - - private $id = '[inline]'; - private $allowParent = true; - private $path = null; - - public function __construct(Definition $definition) - { - $this->definition = $definition; - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php b/lib/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php deleted file mode 100644 index fbba62304..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\DependencyInjection\Definition; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class InstanceofConfigurator extends AbstractServiceConfigurator -{ - use Traits\AutowireTrait; - use Traits\BindTrait; - use Traits\CallTrait; - use Traits\ConfiguratorTrait; - use Traits\LazyTrait; - use Traits\PropertyTrait; - use Traits\PublicTrait; - use Traits\ShareTrait; - use Traits\TagTrait; - - public const FACTORY = 'instanceof'; - - private $path; - - public function __construct(ServicesConfigurator $parent, Definition $definition, string $id, string $path = null) - { - parent::__construct($parent, $definition, $id, []); - - $this->path = $path; - } - - /** - * Defines an instanceof-conditional to be applied to following service definitions. - */ - final public function instanceof(string $fqcn): self - { - return $this->parent->instanceof($fqcn); - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/ParametersConfigurator.php b/lib/symfony/dependency-injection/Loader/Configurator/ParametersConfigurator.php deleted file mode 100644 index f0cf177d7..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/ParametersConfigurator.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\ExpressionLanguage\Expression; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class ParametersConfigurator extends AbstractConfigurator -{ - public const FACTORY = 'parameters'; - - private $container; - - public function __construct(ContainerBuilder $container) - { - $this->container = $container; - } - - /** - * Creates a parameter. - * - * @return $this - */ - final public function set(string $name, $value): self - { - if ($value instanceof Expression) { - throw new InvalidArgumentException(sprintf('Using an expression in parameter "%s" is not allowed.', $name)); - } - - $this->container->setParameter($name, static::processValue($value, true)); - - return $this; - } - - /** - * Creates a parameter. - * - * @return $this - */ - final public function __invoke(string $name, $value): self - { - return $this->set($name, $value); - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php b/lib/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php deleted file mode 100644 index e1b3702aa..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class PrototypeConfigurator extends AbstractServiceConfigurator -{ - use Traits\AbstractTrait; - use Traits\ArgumentTrait; - use Traits\AutoconfigureTrait; - use Traits\AutowireTrait; - use Traits\BindTrait; - use Traits\CallTrait; - use Traits\ConfiguratorTrait; - use Traits\DeprecateTrait; - use Traits\FactoryTrait; - use Traits\LazyTrait; - use Traits\ParentTrait; - use Traits\PropertyTrait; - use Traits\PublicTrait; - use Traits\ShareTrait; - use Traits\TagTrait; - - public const FACTORY = 'load'; - - private $loader; - private $resource; - private $excludes; - private $allowParent; - - public function __construct(ServicesConfigurator $parent, PhpFileLoader $loader, Definition $defaults, string $namespace, string $resource, bool $allowParent) - { - $definition = new Definition(); - if (!$defaults->isPublic() || !$defaults->isPrivate()) { - $definition->setPublic($defaults->isPublic()); - } - $definition->setAutowired($defaults->isAutowired()); - $definition->setAutoconfigured($defaults->isAutoconfigured()); - // deep clone, to avoid multiple process of the same instance in the passes - $definition->setBindings(unserialize(serialize($defaults->getBindings()))); - $definition->setChanges([]); - - $this->loader = $loader; - $this->resource = $resource; - $this->allowParent = $allowParent; - - parent::__construct($parent, $definition, $namespace, $defaults->getTags()); - } - - public function __destruct() - { - parent::__destruct(); - - if ($this->loader) { - $this->loader->registerClasses($this->definition, $this->id, $this->resource, $this->excludes); - } - $this->loader = null; - } - - /** - * Excludes files from registration using glob patterns. - * - * @param string[]|string $excludes - * - * @return $this - */ - final public function exclude($excludes): self - { - $this->excludes = (array) $excludes; - - return $this; - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/ReferenceConfigurator.php b/lib/symfony/dependency-injection/Loader/Configurator/ReferenceConfigurator.php deleted file mode 100644 index fa042538c..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/ReferenceConfigurator.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class ReferenceConfigurator extends AbstractConfigurator -{ - /** @internal */ - protected $id; - - /** @internal */ - protected $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; - - public function __construct(string $id) - { - $this->id = $id; - } - - /** - * @return $this - */ - final public function ignoreOnInvalid(): self - { - $this->invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; - - return $this; - } - - /** - * @return $this - */ - final public function nullOnInvalid(): self - { - $this->invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; - - return $this; - } - - /** - * @return $this - */ - final public function ignoreOnUninitialized(): self - { - $this->invalidBehavior = ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE; - - return $this; - } - - /** - * @return string - */ - public function __toString() - { - return $this->id; - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php b/lib/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php deleted file mode 100644 index 932ecd351..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class ServiceConfigurator extends AbstractServiceConfigurator -{ - use Traits\AbstractTrait; - use Traits\ArgumentTrait; - use Traits\AutoconfigureTrait; - use Traits\AutowireTrait; - use Traits\BindTrait; - use Traits\CallTrait; - use Traits\ClassTrait; - use Traits\ConfiguratorTrait; - use Traits\DecorateTrait; - use Traits\DeprecateTrait; - use Traits\FactoryTrait; - use Traits\FileTrait; - use Traits\LazyTrait; - use Traits\ParentTrait; - use Traits\PropertyTrait; - use Traits\PublicTrait; - use Traits\ShareTrait; - use Traits\SyntheticTrait; - use Traits\TagTrait; - - public const FACTORY = 'services'; - - private $container; - private $instanceof; - private $allowParent; - private $path; - private $destructed = false; - - public function __construct(ContainerBuilder $container, array $instanceof, bool $allowParent, ServicesConfigurator $parent, Definition $definition, ?string $id, array $defaultTags, string $path = null) - { - $this->container = $container; - $this->instanceof = $instanceof; - $this->allowParent = $allowParent; - $this->path = $path; - - parent::__construct($parent, $definition, $id, $defaultTags); - } - - public function __destruct() - { - if ($this->destructed) { - return; - } - $this->destructed = true; - - parent::__destruct(); - - $this->container->removeBindings($this->id); - $this->container->setDefinition($this->id, $this->definition->setInstanceofConditionals($this->instanceof)); - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php b/lib/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php deleted file mode 100644 index 388251e26..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php +++ /dev/null @@ -1,192 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; -use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class ServicesConfigurator extends AbstractConfigurator -{ - public const FACTORY = 'services'; - - private $defaults; - private $container; - private $loader; - private $instanceof; - private $path; - private $anonymousHash; - private $anonymousCount; - - public function __construct(ContainerBuilder $container, PhpFileLoader $loader, array &$instanceof, string $path = null, int &$anonymousCount = 0) - { - $this->defaults = new Definition(); - $this->container = $container; - $this->loader = $loader; - $this->instanceof = &$instanceof; - $this->path = $path; - $this->anonymousHash = ContainerBuilder::hash($path ?: mt_rand()); - $this->anonymousCount = &$anonymousCount; - $instanceof = []; - } - - /** - * Defines a set of defaults for following service definitions. - */ - final public function defaults(): DefaultsConfigurator - { - return new DefaultsConfigurator($this, $this->defaults = new Definition(), $this->path); - } - - /** - * Defines an instanceof-conditional to be applied to following service definitions. - */ - final public function instanceof(string $fqcn): InstanceofConfigurator - { - $this->instanceof[$fqcn] = $definition = new ChildDefinition(''); - - return new InstanceofConfigurator($this, $definition, $fqcn, $this->path); - } - - /** - * Registers a service. - * - * @param string|null $id The service id, or null to create an anonymous service - * @param string|null $class The class of the service, or null when $id is also the class name - */ - final public function set(?string $id, string $class = null): ServiceConfigurator - { - $defaults = $this->defaults; - $definition = new Definition(); - - if (null === $id) { - if (!$class) { - throw new \LogicException('Anonymous services must have a class name.'); - } - - $id = sprintf('.%d_%s', ++$this->anonymousCount, preg_replace('/^.*\\\\/', '', $class).'~'.$this->anonymousHash); - } elseif (!$defaults->isPublic() || !$defaults->isPrivate()) { - $definition->setPublic($defaults->isPublic() && !$defaults->isPrivate()); - } - - $definition->setAutowired($defaults->isAutowired()); - $definition->setAutoconfigured($defaults->isAutoconfigured()); - // deep clone, to avoid multiple process of the same instance in the passes - $definition->setBindings(unserialize(serialize($defaults->getBindings()))); - $definition->setChanges([]); - - $configurator = new ServiceConfigurator($this->container, $this->instanceof, true, $this, $definition, $id, $defaults->getTags(), $this->path); - - return null !== $class ? $configurator->class($class) : $configurator; - } - - /** - * Removes an already defined service definition or alias. - * - * @return $this - */ - final public function remove(string $id): self - { - $this->container->removeDefinition($id); - $this->container->removeAlias($id); - - return $this; - } - - /** - * Creates an alias. - */ - final public function alias(string $id, string $referencedId): AliasConfigurator - { - $ref = static::processValue($referencedId, true); - $alias = new Alias((string) $ref); - if (!$this->defaults->isPublic() || !$this->defaults->isPrivate()) { - $alias->setPublic($this->defaults->isPublic()); - } - $this->container->setAlias($id, $alias); - - return new AliasConfigurator($this, $alias); - } - - /** - * Registers a PSR-4 namespace using a glob pattern. - */ - final public function load(string $namespace, string $resource): PrototypeConfigurator - { - return new PrototypeConfigurator($this, $this->loader, $this->defaults, $namespace, $resource, true); - } - - /** - * Gets an already defined service definition. - * - * @throws ServiceNotFoundException if the service definition does not exist - */ - final public function get(string $id): ServiceConfigurator - { - $definition = $this->container->getDefinition($id); - - return new ServiceConfigurator($this->container, $definition->getInstanceofConditionals(), true, $this, $definition, $id, []); - } - - /** - * Registers a stack of decorator services. - * - * @param InlineServiceConfigurator[]|ReferenceConfigurator[] $services - */ - final public function stack(string $id, array $services): AliasConfigurator - { - foreach ($services as $i => $service) { - if ($service instanceof InlineServiceConfigurator) { - $definition = $service->definition->setInstanceofConditionals($this->instanceof); - - $changes = $definition->getChanges(); - $definition->setAutowired((isset($changes['autowired']) ? $definition : $this->defaults)->isAutowired()); - $definition->setAutoconfigured((isset($changes['autoconfigured']) ? $definition : $this->defaults)->isAutoconfigured()); - $definition->setBindings(array_merge($this->defaults->getBindings(), $definition->getBindings())); - $definition->setChanges($changes); - - $services[$i] = $definition; - } elseif (!$service instanceof ReferenceConfigurator) { - throw new InvalidArgumentException(sprintf('"%s()" expects a list of definitions as returned by "%s()" or "%s()", "%s" given at index "%s" for service "%s".', __METHOD__, InlineServiceConfigurator::FACTORY, ReferenceConfigurator::FACTORY, $service instanceof AbstractConfigurator ? $service::FACTORY.'()' : get_debug_type($service), $i, $id)); - } - } - - $alias = $this->alias($id, ''); - $alias->definition = $this->set($id) - ->parent('') - ->args($services) - ->tag('container.stack') - ->definition; - - return $alias; - } - - /** - * Registers a service. - */ - final public function __invoke(string $id, string $class = null): ServiceConfigurator - { - return $this->set($id, $class); - } - - public function __destruct() - { - $this->loader->registerAliasesForSinglyImplementedInterfaces(); - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/Traits/AbstractTrait.php b/lib/symfony/dependency-injection/Loader/Configurator/Traits/AbstractTrait.php deleted file mode 100644 index 82ba21d7b..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/Traits/AbstractTrait.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -trait AbstractTrait -{ - /** - * Whether this definition is abstract, that means it merely serves as a - * template for other definitions. - * - * @return $this - */ - final public function abstract(bool $abstract = true): self - { - $this->definition->setAbstract($abstract); - - return $this; - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/Traits/ArgumentTrait.php b/lib/symfony/dependency-injection/Loader/Configurator/Traits/ArgumentTrait.php deleted file mode 100644 index 5c9a47560..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/Traits/ArgumentTrait.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -trait ArgumentTrait -{ - /** - * Sets the arguments to pass to the service constructor/factory method. - * - * @return $this - */ - final public function args(array $arguments): self - { - $this->definition->setArguments(static::processValue($arguments, true)); - - return $this; - } - - /** - * Sets one argument to pass to the service constructor/factory method. - * - * @param string|int $key - * @param mixed $value - * - * @return $this - */ - final public function arg($key, $value): self - { - $this->definition->setArgument($key, static::processValue($value, true)); - - return $this; - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/Traits/AutoconfigureTrait.php b/lib/symfony/dependency-injection/Loader/Configurator/Traits/AutoconfigureTrait.php deleted file mode 100644 index 9eab22cfe..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/Traits/AutoconfigureTrait.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -trait AutoconfigureTrait -{ - /** - * Sets whether or not instanceof conditionals should be prepended with a global set. - * - * @return $this - * - * @throws InvalidArgumentException when a parent is already set - */ - final public function autoconfigure(bool $autoconfigured = true): self - { - $this->definition->setAutoconfigured($autoconfigured); - - return $this; - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/Traits/AutowireTrait.php b/lib/symfony/dependency-injection/Loader/Configurator/Traits/AutowireTrait.php deleted file mode 100644 index 2837a0201..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/Traits/AutowireTrait.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -trait AutowireTrait -{ - /** - * Enables/disables autowiring. - * - * @return $this - */ - final public function autowire(bool $autowired = true): self - { - $this->definition->setAutowired($autowired); - - return $this; - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/Traits/BindTrait.php b/lib/symfony/dependency-injection/Loader/Configurator/Traits/BindTrait.php deleted file mode 100644 index 3021e0708..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/Traits/BindTrait.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -use Symfony\Component\DependencyInjection\Argument\BoundArgument; -use Symfony\Component\DependencyInjection\Loader\Configurator\DefaultsConfigurator; -use Symfony\Component\DependencyInjection\Loader\Configurator\InstanceofConfigurator; - -trait BindTrait -{ - /** - * Sets bindings. - * - * Bindings map $named or FQCN arguments to values that should be - * injected in the matching parameters (of the constructor, of methods - * called and of controller actions). - * - * @param string $nameOrFqcn A parameter name with its "$" prefix, or an FQCN - * @param mixed $valueOrRef The value or reference to bind - * - * @return $this - */ - final public function bind(string $nameOrFqcn, $valueOrRef): self - { - $valueOrRef = static::processValue($valueOrRef, true); - $bindings = $this->definition->getBindings(); - $type = $this instanceof DefaultsConfigurator ? BoundArgument::DEFAULTS_BINDING : ($this instanceof InstanceofConfigurator ? BoundArgument::INSTANCEOF_BINDING : BoundArgument::SERVICE_BINDING); - $bindings[$nameOrFqcn] = new BoundArgument($valueOrRef, true, $type, $this->path ?? null); - $this->definition->setBindings($bindings); - - return $this; - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/Traits/CallTrait.php b/lib/symfony/dependency-injection/Loader/Configurator/Traits/CallTrait.php deleted file mode 100644 index 28f92d274..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/Traits/CallTrait.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -trait CallTrait -{ - /** - * Adds a method to call after service initialization. - * - * @param string $method The method name to call - * @param array $arguments An array of arguments to pass to the method call - * @param bool $returnsClone Whether the call returns the service instance or not - * - * @return $this - * - * @throws InvalidArgumentException on empty $method param - */ - final public function call(string $method, array $arguments = [], bool $returnsClone = false): self - { - $this->definition->addMethodCall($method, static::processValue($arguments, true), $returnsClone); - - return $this; - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/Traits/ClassTrait.php b/lib/symfony/dependency-injection/Loader/Configurator/Traits/ClassTrait.php deleted file mode 100644 index 20da791aa..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/Traits/ClassTrait.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -trait ClassTrait -{ - /** - * Sets the service class. - * - * @return $this - */ - final public function class(?string $class): self - { - $this->definition->setClass($class); - - return $this; - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/Traits/ConfiguratorTrait.php b/lib/symfony/dependency-injection/Loader/Configurator/Traits/ConfiguratorTrait.php deleted file mode 100644 index 25d363c9a..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/Traits/ConfiguratorTrait.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -trait ConfiguratorTrait -{ - /** - * Sets a configurator to call after the service is fully initialized. - * - * @param string|array $configurator A PHP callable reference - * - * @return $this - */ - final public function configurator($configurator): self - { - $this->definition->setConfigurator(static::processValue($configurator, true)); - - return $this; - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php b/lib/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php deleted file mode 100644 index b3a1ae1b5..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -trait DecorateTrait -{ - /** - * Sets the service that this service is decorating. - * - * @param string|null $id The decorated service id, use null to remove decoration - * - * @return $this - * - * @throws InvalidArgumentException in case the decorated service id and the new decorated service id are equals - */ - final public function decorate(?string $id, string $renamedId = null, int $priority = 0, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE): self - { - $this->definition->setDecoratedService($id, $renamedId, $priority, $invalidBehavior); - - return $this; - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/Traits/DeprecateTrait.php b/lib/symfony/dependency-injection/Loader/Configurator/Traits/DeprecateTrait.php deleted file mode 100644 index ea77e456d..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/Traits/DeprecateTrait.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -trait DeprecateTrait -{ - /** - * Whether this definition is deprecated, that means it should not be called anymore. - * - * @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 deprecation message to use - * - * @return $this - * - * @throws InvalidArgumentException when the message template is invalid - */ - final public function deprecate(/* string $package, string $version, string $message */): self - { - $args = \func_get_args(); - $package = $version = $message = ''; - - if (\func_num_args() < 3) { - trigger_deprecation('symfony/dependency-injection', '5.1', 'The signature of method "%s()" requires 3 arguments: "string $package, string $version, string $message", not defining them is deprecated.', __METHOD__); - - $message = (string) ($args[0] ?? null); - } else { - $package = (string) $args[0]; - $version = (string) $args[1]; - $message = (string) $args[2]; - } - - $this->definition->setDeprecated($package, $version, $message); - - return $this; - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/Traits/FactoryTrait.php b/lib/symfony/dependency-injection/Loader/Configurator/Traits/FactoryTrait.php deleted file mode 100644 index 1286ba4c1..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/Traits/FactoryTrait.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Loader\Configurator\ReferenceConfigurator; - -trait FactoryTrait -{ - /** - * Sets a factory. - * - * @param string|array|ReferenceConfigurator $factory A PHP callable reference - * - * @return $this - */ - final public function factory($factory): self - { - if (\is_string($factory) && 1 === substr_count($factory, ':')) { - $factoryParts = explode(':', $factory); - - throw new InvalidArgumentException(sprintf('Invalid factory "%s": the "service:method" notation is not available when using PHP-based DI configuration. Use "[service(\'%s\'), \'%s\']" instead.', $factory, $factoryParts[0], $factoryParts[1])); - } - - $this->definition->setFactory(static::processValue($factory, true)); - - return $this; - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/Traits/FileTrait.php b/lib/symfony/dependency-injection/Loader/Configurator/Traits/FileTrait.php deleted file mode 100644 index 5f42aef8f..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/Traits/FileTrait.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -trait FileTrait -{ - /** - * Sets a file to require before creating the service. - * - * @return $this - */ - final public function file(string $file): self - { - $this->definition->setFile($file); - - return $this; - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/Traits/LazyTrait.php b/lib/symfony/dependency-injection/Loader/Configurator/Traits/LazyTrait.php deleted file mode 100644 index 2829defb5..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/Traits/LazyTrait.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -trait LazyTrait -{ - /** - * Sets the lazy flag of this service. - * - * @param bool|string $lazy A FQCN to derivate the lazy proxy from or `true` to make it extend from the definition's class - * - * @return $this - */ - final public function lazy($lazy = true): self - { - $this->definition->setLazy((bool) $lazy); - if (\is_string($lazy)) { - $this->definition->addTag('proxy', ['interface' => $lazy]); - } - - return $this; - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/Traits/ParentTrait.php b/lib/symfony/dependency-injection/Loader/Configurator/Traits/ParentTrait.php deleted file mode 100644 index 37194e50e..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/Traits/ParentTrait.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -trait ParentTrait -{ - /** - * Sets the Definition to inherit from. - * - * @return $this - * - * @throws InvalidArgumentException when parent cannot be set - */ - final public function parent(string $parent): self - { - if (!$this->allowParent) { - throw new InvalidArgumentException(sprintf('A parent cannot be defined when either "_instanceof" or "_defaults" are also defined for service prototype "%s".', $this->id)); - } - - if ($this->definition instanceof ChildDefinition) { - $this->definition->setParent($parent); - } else { - // cast Definition to ChildDefinition - $definition = serialize($this->definition); - $definition = substr_replace($definition, '53', 2, 2); - $definition = substr_replace($definition, 'Child', 44, 0); - $definition = unserialize($definition); - - $this->definition = $definition->setParent($parent); - } - - return $this; - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/Traits/PropertyTrait.php b/lib/symfony/dependency-injection/Loader/Configurator/Traits/PropertyTrait.php deleted file mode 100644 index 10fdcfb82..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/Traits/PropertyTrait.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -trait PropertyTrait -{ - /** - * Sets a specific property. - * - * @return $this - */ - final public function property(string $name, $value): self - { - $this->definition->setProperty($name, static::processValue($value, true)); - - return $this; - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/Traits/PublicTrait.php b/lib/symfony/dependency-injection/Loader/Configurator/Traits/PublicTrait.php deleted file mode 100644 index f15756c1b..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/Traits/PublicTrait.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -trait PublicTrait -{ - /** - * @return $this - */ - final public function public(): self - { - $this->definition->setPublic(true); - - return $this; - } - - /** - * @return $this - */ - final public function private(): self - { - $this->definition->setPublic(false); - - return $this; - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/Traits/ShareTrait.php b/lib/symfony/dependency-injection/Loader/Configurator/Traits/ShareTrait.php deleted file mode 100644 index 16fde0f29..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/Traits/ShareTrait.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -trait ShareTrait -{ - /** - * Sets if the service must be shared or not. - * - * @return $this - */ - final public function share(bool $shared = true): self - { - $this->definition->setShared($shared); - - return $this; - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/Traits/SyntheticTrait.php b/lib/symfony/dependency-injection/Loader/Configurator/Traits/SyntheticTrait.php deleted file mode 100644 index cb08b1133..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/Traits/SyntheticTrait.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -trait SyntheticTrait -{ - /** - * Sets whether this definition is synthetic, that is not constructed by the - * container, but dynamically injected. - * - * @return $this - */ - final public function synthetic(bool $synthetic = true): self - { - $this->definition->setSynthetic($synthetic); - - return $this; - } -} diff --git a/lib/symfony/dependency-injection/Loader/Configurator/Traits/TagTrait.php b/lib/symfony/dependency-injection/Loader/Configurator/Traits/TagTrait.php deleted file mode 100644 index ba9f8afa9..000000000 --- a/lib/symfony/dependency-injection/Loader/Configurator/Traits/TagTrait.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -trait TagTrait -{ - /** - * Adds a tag for this definition. - * - * @return $this - */ - final public function tag(string $name, array $attributes = []): self - { - if ('' === $name) { - throw new InvalidArgumentException(sprintf('The tag name for service "%s" must be a non-empty string.', $this->id)); - } - - foreach ($attributes as $attribute => $value) { - if (!\is_scalar($value) && null !== $value) { - throw new InvalidArgumentException(sprintf('A tag attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s".', $this->id, $name, $attribute)); - } - } - - $this->definition->addTag($name, $attributes); - - return $this; - } -} diff --git a/lib/symfony/dependency-injection/Loader/DirectoryLoader.php b/lib/symfony/dependency-injection/Loader/DirectoryLoader.php deleted file mode 100644 index b4e9a5917..000000000 --- a/lib/symfony/dependency-injection/Loader/DirectoryLoader.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader; - -/** - * DirectoryLoader is a recursive loader to go through directories. - * - * @author Sebastien Lavoie <seb@wemakecustom.com> - */ -class DirectoryLoader extends FileLoader -{ - /** - * {@inheritdoc} - */ - public function load($file, string $type = null) - { - $file = rtrim($file, '/'); - $path = $this->locator->locate($file); - $this->container->fileExists($path, false); - - foreach (scandir($path) as $dir) { - if ('.' !== $dir[0]) { - if (is_dir($path.'/'.$dir)) { - $dir .= '/'; // append / to allow recursion - } - - $this->setCurrentDir($path); - - $this->import($dir, null, false, $path); - } - } - - return null; - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - if ('directory' === $type) { - return true; - } - - return null === $type && \is_string($resource) && str_ends_with($resource, '/'); - } -} diff --git a/lib/symfony/dependency-injection/Loader/FileLoader.php b/lib/symfony/dependency-injection/Loader/FileLoader.php deleted file mode 100644 index f5f78e30f..000000000 --- a/lib/symfony/dependency-injection/Loader/FileLoader.php +++ /dev/null @@ -1,247 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader; - -use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException; -use Symfony\Component\Config\Exception\LoaderLoadException; -use Symfony\Component\Config\FileLocatorInterface; -use Symfony\Component\Config\Loader\FileLoader as BaseFileLoader; -use Symfony\Component\Config\Loader\Loader; -use Symfony\Component\Config\Resource\GlobResource; -use Symfony\Component\DependencyInjection\Attribute\When; -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\Compiler\RegisterAutoconfigureAttributesPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -/** - * FileLoader is the abstract class used by all built-in loaders that are file based. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -abstract class FileLoader extends BaseFileLoader -{ - public const ANONYMOUS_ID_REGEXP = '/^\.\d+_[^~]*+~[._a-zA-Z\d]{7}$/'; - - protected $container; - protected $isLoadingInstanceof = false; - protected $instanceof = []; - protected $interfaces = []; - protected $singlyImplemented = []; - protected $autoRegisterAliasesForSinglyImplementedInterfaces = true; - - public function __construct(ContainerBuilder $container, FileLocatorInterface $locator, string $env = null) - { - $this->container = $container; - - parent::__construct($locator, $env); - } - - /** - * {@inheritdoc} - * - * @param bool|string $ignoreErrors Whether errors should be ignored; pass "not_found" to ignore only when the loaded resource is not found - */ - public function import($resource, string $type = null, $ignoreErrors = false, string $sourceResource = null, $exclude = null) - { - $args = \func_get_args(); - - if ($ignoreNotFound = 'not_found' === $ignoreErrors) { - $args[2] = false; - } elseif (!\is_bool($ignoreErrors)) { - throw new \TypeError(sprintf('Invalid argument $ignoreErrors provided to "%s::import()": boolean or "not_found" expected, "%s" given.', static::class, get_debug_type($ignoreErrors))); - } - - try { - return parent::import(...$args); - } catch (LoaderLoadException $e) { - if (!$ignoreNotFound || !($prev = $e->getPrevious()) instanceof FileLocatorFileNotFoundException) { - throw $e; - } - - foreach ($prev->getTrace() as $frame) { - if ('import' === ($frame['function'] ?? null) && is_a($frame['class'] ?? '', Loader::class, true)) { - break; - } - } - - if (__FILE__ !== $frame['file']) { - throw $e; - } - } - - return null; - } - - /** - * Registers a set of classes as services using PSR-4 for discovery. - * - * @param Definition $prototype A definition to use as template - * @param string $namespace The namespace prefix of classes in the scanned directory - * @param string $resource The directory to look for classes, glob-patterns allowed - * @param string|string[]|null $exclude A globbed path of files to exclude or an array of globbed paths of files to exclude - */ - public function registerClasses(Definition $prototype, string $namespace, string $resource, $exclude = null) - { - if (!str_ends_with($namespace, '\\')) { - throw new InvalidArgumentException(sprintf('Namespace prefix must end with a "\\": "%s".', $namespace)); - } - if (!preg_match('/^(?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+\\\\)++$/', $namespace)) { - throw new InvalidArgumentException(sprintf('Namespace is not a valid PSR-4 prefix: "%s".', $namespace)); - } - - $autoconfigureAttributes = new RegisterAutoconfigureAttributesPass(); - $autoconfigureAttributes = $autoconfigureAttributes->accept($prototype) ? $autoconfigureAttributes : null; - $classes = $this->findClasses($namespace, $resource, (array) $exclude, $autoconfigureAttributes); - // prepare for deep cloning - $serializedPrototype = serialize($prototype); - - foreach ($classes as $class => $errorMessage) { - if (null === $errorMessage && $autoconfigureAttributes && $this->env) { - $r = $this->container->getReflectionClass($class); - $attribute = null; - foreach ($r->getAttributes(When::class) as $attribute) { - if ($this->env === $attribute->newInstance()->env) { - $attribute = null; - break; - } - } - if (null !== $attribute) { - continue; - } - } - - if (interface_exists($class, false)) { - $this->interfaces[] = $class; - } else { - $this->setDefinition($class, $definition = unserialize($serializedPrototype)); - if (null !== $errorMessage) { - $definition->addError($errorMessage); - - continue; - } - foreach (class_implements($class, false) as $interface) { - $this->singlyImplemented[$interface] = ($this->singlyImplemented[$interface] ?? $class) !== $class ? false : $class; - } - } - } - - if ($this->autoRegisterAliasesForSinglyImplementedInterfaces) { - $this->registerAliasesForSinglyImplementedInterfaces(); - } - } - - public function registerAliasesForSinglyImplementedInterfaces() - { - foreach ($this->interfaces as $interface) { - if (!empty($this->singlyImplemented[$interface]) && !$this->container->has($interface)) { - $this->container->setAlias($interface, $this->singlyImplemented[$interface]); - } - } - - $this->interfaces = $this->singlyImplemented = []; - } - - /** - * Registers a definition in the container with its instanceof-conditionals. - */ - protected function setDefinition(string $id, Definition $definition) - { - $this->container->removeBindings($id); - - if ($this->isLoadingInstanceof) { - if (!$definition instanceof ChildDefinition) { - throw new InvalidArgumentException(sprintf('Invalid type definition "%s": ChildDefinition expected, "%s" given.', $id, get_debug_type($definition))); - } - $this->instanceof[$id] = $definition; - } else { - $this->container->setDefinition($id, $definition->setInstanceofConditionals($this->instanceof)); - } - } - - private function findClasses(string $namespace, string $pattern, array $excludePatterns, ?RegisterAutoconfigureAttributesPass $autoconfigureAttributes): array - { - $parameterBag = $this->container->getParameterBag(); - - $excludePaths = []; - $excludePrefix = null; - $excludePatterns = $parameterBag->unescapeValue($parameterBag->resolveValue($excludePatterns)); - foreach ($excludePatterns as $excludePattern) { - foreach ($this->glob($excludePattern, true, $resource, true, true) as $path => $info) { - if (null === $excludePrefix) { - $excludePrefix = $resource->getPrefix(); - } - - // normalize Windows slashes and remove trailing slashes - $excludePaths[rtrim(str_replace('\\', '/', $path), '/')] = true; - } - } - - $pattern = $parameterBag->unescapeValue($parameterBag->resolveValue($pattern)); - $classes = []; - $extRegexp = '/\\.php$/'; - $prefixLen = null; - foreach ($this->glob($pattern, true, $resource, false, false, $excludePaths) as $path => $info) { - if (null === $prefixLen) { - $prefixLen = \strlen($resource->getPrefix()); - - if ($excludePrefix && !str_starts_with($excludePrefix, $resource->getPrefix())) { - throw new InvalidArgumentException(sprintf('Invalid "exclude" pattern when importing classes for "%s": make sure your "exclude" pattern (%s) is a subset of the "resource" pattern (%s).', $namespace, $excludePattern, $pattern)); - } - } - - if (isset($excludePaths[str_replace('\\', '/', $path)])) { - continue; - } - - if (!preg_match($extRegexp, $path, $m) || !$info->isReadable()) { - continue; - } - $class = $namespace.ltrim(str_replace('/', '\\', substr($path, $prefixLen, -\strlen($m[0]))), '\\'); - - if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+$/', $class)) { - continue; - } - - try { - $r = $this->container->getReflectionClass($class); - } catch (\ReflectionException $e) { - $classes[$class] = $e->getMessage(); - continue; - } - // check to make sure the expected class exists - if (!$r) { - throw new InvalidArgumentException(sprintf('Expected to find class "%s" in file "%s" while importing services from resource "%s", but it was not found! Check the namespace prefix used with the resource.', $class, $path, $pattern)); - } - - if ($r->isInstantiable() || $r->isInterface()) { - $classes[$class] = null; - } - - if ($autoconfigureAttributes && !$r->isInstantiable()) { - $autoconfigureAttributes->processClass($this->container, $r); - } - } - - // track only for new & removed files - if ($resource instanceof GlobResource) { - $this->container->addResource($resource); - } else { - foreach ($resource as $path) { - $this->container->fileExists($path, false); - } - } - - return $classes; - } -} diff --git a/lib/symfony/dependency-injection/Loader/GlobFileLoader.php b/lib/symfony/dependency-injection/Loader/GlobFileLoader.php deleted file mode 100644 index e38aaf43b..000000000 --- a/lib/symfony/dependency-injection/Loader/GlobFileLoader.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader; - -/** - * GlobFileLoader loads files from a glob pattern. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class GlobFileLoader extends FileLoader -{ - /** - * {@inheritdoc} - */ - public function load($resource, string $type = null) - { - foreach ($this->glob($resource, false, $globResource) as $path => $info) { - $this->import($path); - } - - $this->container->addResource($globResource); - - return null; - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - return 'glob' === $type; - } -} diff --git a/lib/symfony/dependency-injection/Loader/IniFileLoader.php b/lib/symfony/dependency-injection/Loader/IniFileLoader.php deleted file mode 100644 index d88d7a630..000000000 --- a/lib/symfony/dependency-injection/Loader/IniFileLoader.php +++ /dev/null @@ -1,105 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader; - -use Symfony\Component\Config\Util\XmlUtils; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -/** - * IniFileLoader loads parameters from INI files. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class IniFileLoader extends FileLoader -{ - /** - * {@inheritdoc} - */ - public function load($resource, string $type = null) - { - $path = $this->locator->locate($resource); - - $this->container->fileExists($path); - - // first pass to catch parsing errors - $result = parse_ini_file($path, true); - if (false === $result || [] === $result) { - throw new InvalidArgumentException(sprintf('The "%s" file is not valid.', $resource)); - } - - // real raw parsing - $result = parse_ini_file($path, true, \INI_SCANNER_RAW); - - if (isset($result['parameters']) && \is_array($result['parameters'])) { - foreach ($result['parameters'] as $key => $value) { - $this->container->setParameter($key, $this->phpize($value)); - } - } - - if ($this->env && \is_array($result['parameters@'.$this->env] ?? null)) { - foreach ($result['parameters@'.$this->env] as $key => $value) { - $this->container->setParameter($key, $this->phpize($value)); - } - } - - return null; - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - if (!\is_string($resource)) { - return false; - } - - if (null === $type && 'ini' === pathinfo($resource, \PATHINFO_EXTENSION)) { - return true; - } - - return 'ini' === $type; - } - - /** - * Note that the following features are not supported: - * * strings with escaped quotes are not supported "foo\"bar"; - * * string concatenation ("foo" "bar"). - * - * @return mixed - */ - private function phpize(string $value) - { - // trim on the right as comments removal keep whitespaces - if ($value !== $v = rtrim($value)) { - $value = '""' === substr_replace($v, '', 1, -1) ? substr($v, 1, -1) : $v; - } - $lowercaseValue = strtolower($value); - - switch (true) { - case \defined($value): - return \constant($value); - case 'yes' === $lowercaseValue || 'on' === $lowercaseValue: - return true; - case 'no' === $lowercaseValue || 'off' === $lowercaseValue || 'none' === $lowercaseValue: - return false; - case isset($value[1]) && ( - ("'" === $value[0] && "'" === $value[\strlen($value) - 1]) || - ('"' === $value[0] && '"' === $value[\strlen($value) - 1]) - ): - // quoted string - return substr($value, 1, -1); - default: - return XmlUtils::phpize($value); - } - } -} diff --git a/lib/symfony/dependency-injection/Loader/PhpFileLoader.php b/lib/symfony/dependency-injection/Loader/PhpFileLoader.php deleted file mode 100644 index 3815b28f0..000000000 --- a/lib/symfony/dependency-injection/Loader/PhpFileLoader.php +++ /dev/null @@ -1,211 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader; - -use Symfony\Component\Config\Builder\ConfigBuilderGenerator; -use Symfony\Component\Config\Builder\ConfigBuilderGeneratorInterface; -use Symfony\Component\Config\Builder\ConfigBuilderInterface; -use Symfony\Component\Config\FileLocatorInterface; -use Symfony\Component\DependencyInjection\Attribute\When; -use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface; -use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; -use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; - -/** - * PhpFileLoader loads service definitions from a PHP file. - * - * The PHP file is required and the $container variable can be - * used within the file to change the container. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class PhpFileLoader extends FileLoader -{ - protected $autoRegisterAliasesForSinglyImplementedInterfaces = false; - private $generator; - - public function __construct(ContainerBuilder $container, FileLocatorInterface $locator, string $env = null, ConfigBuilderGeneratorInterface $generator = null) - { - parent::__construct($container, $locator, $env); - $this->generator = $generator; - } - - /** - * {@inheritdoc} - */ - public function load($resource, string $type = null) - { - // the container and loader variables are exposed to the included file below - $container = $this->container; - $loader = $this; - - $path = $this->locator->locate($resource); - $this->setCurrentDir(\dirname($path)); - $this->container->fileExists($path); - - // the closure forbids access to the private scope in the included file - $load = \Closure::bind(function ($path, $env) use ($container, $loader, $resource, $type) { - return include $path; - }, $this, ProtectedPhpFileLoader::class); - - try { - $callback = $load($path, $this->env); - - if (\is_object($callback) && \is_callable($callback)) { - $this->executeCallback($callback, new ContainerConfigurator($this->container, $this, $this->instanceof, $path, $resource, $this->env), $path); - } - } finally { - $this->instanceof = []; - $this->registerAliasesForSinglyImplementedInterfaces(); - } - - return null; - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - if (!\is_string($resource)) { - return false; - } - - if (null === $type && 'php' === pathinfo($resource, \PATHINFO_EXTENSION)) { - return true; - } - - return 'php' === $type; - } - - /** - * Resolve the parameters to the $callback and execute it. - */ - private function executeCallback(callable $callback, ContainerConfigurator $containerConfigurator, string $path) - { - if (!$callback instanceof \Closure) { - $callback = \Closure::fromCallable($callback); - } - - $arguments = []; - $configBuilders = []; - $r = new \ReflectionFunction($callback); - - if (\PHP_VERSION_ID >= 80000) { - $attribute = null; - foreach ($r->getAttributes(When::class) as $attribute) { - if ($this->env === $attribute->newInstance()->env) { - $attribute = null; - break; - } - } - if (null !== $attribute) { - return; - } - } - - foreach ($r->getParameters() as $parameter) { - $reflectionType = $parameter->getType(); - if (!$reflectionType instanceof \ReflectionNamedType) { - throw new \InvalidArgumentException(sprintf('Could not resolve argument "$%s" for "%s". You must typehint it (for example with "%s" or "%s").', $parameter->getName(), $path, ContainerConfigurator::class, ContainerBuilder::class)); - } - $type = $reflectionType->getName(); - - switch ($type) { - case ContainerConfigurator::class: - $arguments[] = $containerConfigurator; - break; - case ContainerBuilder::class: - $arguments[] = $this->container; - break; - case FileLoader::class: - case self::class: - $arguments[] = $this; - break; - default: - try { - $configBuilder = $this->configBuilder($type); - } catch (InvalidArgumentException|\LogicException $e) { - throw new \InvalidArgumentException(sprintf('Could not resolve argument "%s" for "%s".', $type.' $'.$parameter->getName(), $path), 0, $e); - } - $configBuilders[] = $configBuilder; - $arguments[] = $configBuilder; - } - } - - // Force load ContainerConfigurator to make env(), param() etc available. - class_exists(ContainerConfigurator::class); - - $callback(...$arguments); - - /** @var ConfigBuilderInterface $configBuilder */ - foreach ($configBuilders as $configBuilder) { - $containerConfigurator->extension($configBuilder->getExtensionAlias(), $configBuilder->toArray()); - } - } - - /** - * @param string $namespace FQCN string for a class implementing ConfigBuilderInterface - */ - private function configBuilder(string $namespace): ConfigBuilderInterface - { - if (!class_exists(ConfigBuilderGenerator::class)) { - throw new \LogicException('You cannot use the config builder as the Config component is not installed. Try running "composer require symfony/config".'); - } - - if (null === $this->generator) { - throw new \LogicException('You cannot use the ConfigBuilders without providing a class implementing ConfigBuilderGeneratorInterface.'); - } - - // If class exists and implements ConfigBuilderInterface - if (class_exists($namespace) && is_subclass_of($namespace, ConfigBuilderInterface::class)) { - return new $namespace(); - } - - // If it does not start with Symfony\Config\ we dont know how to handle this - if ('Symfony\\Config\\' !== substr($namespace, 0, 15)) { - throw new InvalidArgumentException(sprintf('Could not find or generate class "%s".', $namespace)); - } - - // Try to get the extension alias - $alias = Container::underscore(substr($namespace, 15, -6)); - - if (false !== strpos($alias, '\\')) { - throw new InvalidArgumentException('You can only use "root" ConfigBuilders from "Symfony\\Config\\" namespace. Nested classes like "Symfony\\Config\\Framework\\CacheConfig" cannot be used.'); - } - - if (!$this->container->hasExtension($alias)) { - $extensions = array_filter(array_map(function (ExtensionInterface $ext) { return $ext->getAlias(); }, $this->container->getExtensions())); - throw new InvalidArgumentException(sprintf('There is no extension able to load the configuration for "%s". Looked for namespace "%s", found "%s".', $namespace, $alias, $extensions ? implode('", "', $extensions) : 'none')); - } - - $extension = $this->container->getExtension($alias); - if (!$extension instanceof ConfigurationExtensionInterface) { - throw new \LogicException(sprintf('You cannot use the config builder for "%s" because the extension does not implement "%s".', $namespace, ConfigurationExtensionInterface::class)); - } - - $configuration = $extension->getConfiguration([], $this->container); - $loader = $this->generator->build($configuration); - - return $loader(); - } -} - -/** - * @internal - */ -final class ProtectedPhpFileLoader extends PhpFileLoader -{ -} diff --git a/lib/symfony/dependency-injection/Loader/XmlFileLoader.php b/lib/symfony/dependency-injection/Loader/XmlFileLoader.php deleted file mode 100644 index 73b0f0deb..000000000 --- a/lib/symfony/dependency-injection/Loader/XmlFileLoader.php +++ /dev/null @@ -1,782 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader; - -use Symfony\Component\Config\Util\XmlUtils; -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\AbstractArgument; -use Symfony\Component\DependencyInjection\Argument\BoundArgument; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\ExpressionLanguage\Expression; - -/** - * XmlFileLoader loads XML files service definitions. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class XmlFileLoader extends FileLoader -{ - public const NS = 'http://symfony.com/schema/dic/services'; - - protected $autoRegisterAliasesForSinglyImplementedInterfaces = false; - - /** - * {@inheritdoc} - */ - public function load($resource, string $type = null) - { - $path = $this->locator->locate($resource); - - $xml = $this->parseFileToDOM($path); - - $this->container->fileExists($path); - - $this->loadXml($xml, $path); - - if ($this->env) { - $xpath = new \DOMXPath($xml); - $xpath->registerNamespace('container', self::NS); - foreach ($xpath->query(sprintf('//container:when[@env="%s"]', $this->env)) ?: [] as $root) { - $env = $this->env; - $this->env = null; - try { - $this->loadXml($xml, $path, $root); - } finally { - $this->env = $env; - } - } - } - - return null; - } - - private function loadXml(\DOMDocument $xml, string $path, \DOMNode $root = null): void - { - $defaults = $this->getServiceDefaults($xml, $path, $root); - - // anonymous services - $this->processAnonymousServices($xml, $path, $root); - - // imports - $this->parseImports($xml, $path, $root); - - // parameters - $this->parseParameters($xml, $path, $root); - - // extensions - $this->loadFromExtensions($xml, $root); - - // services - try { - $this->parseDefinitions($xml, $path, $defaults, $root); - } finally { - $this->instanceof = []; - $this->registerAliasesForSinglyImplementedInterfaces(); - } - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - if (!\is_string($resource)) { - return false; - } - - if (null === $type && 'xml' === pathinfo($resource, \PATHINFO_EXTENSION)) { - return true; - } - - return 'xml' === $type; - } - - private function parseParameters(\DOMDocument $xml, string $file, \DOMNode $root = null) - { - if ($parameters = $this->getChildren($root ?? $xml->documentElement, 'parameters')) { - $this->container->getParameterBag()->add($this->getArgumentsAsPhp($parameters[0], 'parameter', $file)); - } - } - - private function parseImports(\DOMDocument $xml, string $file, \DOMNode $root = null) - { - $xpath = new \DOMXPath($xml); - $xpath->registerNamespace('container', self::NS); - - if (false === $imports = $xpath->query('.//container:imports/container:import', $root)) { - return; - } - - $defaultDirectory = \dirname($file); - foreach ($imports as $import) { - $this->setCurrentDir($defaultDirectory); - $this->import($import->getAttribute('resource'), XmlUtils::phpize($import->getAttribute('type')) ?: null, XmlUtils::phpize($import->getAttribute('ignore-errors')) ?: false, $file); - } - } - - private function parseDefinitions(\DOMDocument $xml, string $file, Definition $defaults, \DOMNode $root = null) - { - $xpath = new \DOMXPath($xml); - $xpath->registerNamespace('container', self::NS); - - if (false === $services = $xpath->query('.//container:services/container:service|.//container:services/container:prototype|.//container:services/container:stack', $root)) { - return; - } - $this->setCurrentDir(\dirname($file)); - - $this->instanceof = []; - $this->isLoadingInstanceof = true; - $instanceof = $xpath->query('.//container:services/container:instanceof', $root); - foreach ($instanceof as $service) { - $this->setDefinition((string) $service->getAttribute('id'), $this->parseDefinition($service, $file, new Definition())); - } - - $this->isLoadingInstanceof = false; - foreach ($services as $service) { - if ('stack' === $service->tagName) { - $service->setAttribute('parent', '-'); - $definition = $this->parseDefinition($service, $file, $defaults) - ->setTags(array_merge_recursive(['container.stack' => [[]]], $defaults->getTags())) - ; - $this->setDefinition($id = (string) $service->getAttribute('id'), $definition); - $stack = []; - - foreach ($this->getChildren($service, 'service') as $k => $frame) { - $k = $frame->getAttribute('id') ?: $k; - $frame->setAttribute('id', $id.'" at index "'.$k); - - if ($alias = $frame->getAttribute('alias')) { - $this->validateAlias($frame, $file); - $stack[$k] = new Reference($alias); - } else { - $stack[$k] = $this->parseDefinition($frame, $file, $defaults) - ->setInstanceofConditionals($this->instanceof); - } - } - - $definition->setArguments($stack); - } elseif (null !== $definition = $this->parseDefinition($service, $file, $defaults)) { - if ('prototype' === $service->tagName) { - $excludes = array_column($this->getChildren($service, 'exclude'), 'nodeValue'); - if ($service->hasAttribute('exclude')) { - if (\count($excludes) > 0) { - throw new InvalidArgumentException('You cannot use both the attribute "exclude" and <exclude> tags at the same time.'); - } - $excludes = [$service->getAttribute('exclude')]; - } - $this->registerClasses($definition, (string) $service->getAttribute('namespace'), (string) $service->getAttribute('resource'), $excludes); - } else { - $this->setDefinition((string) $service->getAttribute('id'), $definition); - } - } - } - } - - private function getServiceDefaults(\DOMDocument $xml, string $file, \DOMNode $root = null): Definition - { - $xpath = new \DOMXPath($xml); - $xpath->registerNamespace('container', self::NS); - - if (null === $defaultsNode = $xpath->query('.//container:services/container:defaults', $root)->item(0)) { - return new Definition(); - } - - $defaultsNode->setAttribute('id', '<defaults>'); - - return $this->parseDefinition($defaultsNode, $file, new Definition()); - } - - /** - * Parses an individual Definition. - */ - private function parseDefinition(\DOMElement $service, string $file, Definition $defaults): ?Definition - { - if ($alias = $service->getAttribute('alias')) { - $this->validateAlias($service, $file); - - $this->container->setAlias($service->getAttribute('id'), $alias = new Alias($alias)); - if ($publicAttr = $service->getAttribute('public')) { - $alias->setPublic(XmlUtils::phpize($publicAttr)); - } elseif ($defaults->getChanges()['public'] ?? false) { - $alias->setPublic($defaults->isPublic()); - } - - if ($deprecated = $this->getChildren($service, 'deprecated')) { - $message = $deprecated[0]->nodeValue ?: ''; - $package = $deprecated[0]->getAttribute('package') ?: ''; - $version = $deprecated[0]->getAttribute('version') ?: ''; - - if (!$deprecated[0]->hasAttribute('package')) { - trigger_deprecation('symfony/dependency-injection', '5.1', 'Not setting the attribute "package" of the node "deprecated" in "%s" is deprecated.', $file); - } - - if (!$deprecated[0]->hasAttribute('version')) { - trigger_deprecation('symfony/dependency-injection', '5.1', 'Not setting the attribute "version" of the node "deprecated" in "%s" is deprecated.', $file); - } - - $alias->setDeprecated($package, $version, $message); - } - - return null; - } - - if ($this->isLoadingInstanceof) { - $definition = new ChildDefinition(''); - } elseif ($parent = $service->getAttribute('parent')) { - $definition = new ChildDefinition($parent); - } else { - $definition = new Definition(); - } - - if ($defaults->getChanges()['public'] ?? false) { - $definition->setPublic($defaults->isPublic()); - } - $definition->setAutowired($defaults->isAutowired()); - $definition->setAutoconfigured($defaults->isAutoconfigured()); - $definition->setChanges([]); - - foreach (['class', 'public', 'shared', 'synthetic', 'abstract'] as $key) { - if ($value = $service->getAttribute($key)) { - $method = 'set'.$key; - $definition->$method($value = XmlUtils::phpize($value)); - } - } - - if ($value = $service->getAttribute('lazy')) { - $definition->setLazy((bool) $value = XmlUtils::phpize($value)); - if (\is_string($value)) { - $definition->addTag('proxy', ['interface' => $value]); - } - } - - if ($value = $service->getAttribute('autowire')) { - $definition->setAutowired(XmlUtils::phpize($value)); - } - - if ($value = $service->getAttribute('autoconfigure')) { - $definition->setAutoconfigured(XmlUtils::phpize($value)); - } - - if ($files = $this->getChildren($service, 'file')) { - $definition->setFile($files[0]->nodeValue); - } - - if ($deprecated = $this->getChildren($service, 'deprecated')) { - $message = $deprecated[0]->nodeValue ?: ''; - $package = $deprecated[0]->getAttribute('package') ?: ''; - $version = $deprecated[0]->getAttribute('version') ?: ''; - - if ('' === $package) { - trigger_deprecation('symfony/dependency-injection', '5.1', 'Not setting the attribute "package" of the node "deprecated" in "%s" is deprecated.', $file); - } - - if ('' === $version) { - trigger_deprecation('symfony/dependency-injection', '5.1', 'Not setting the attribute "version" of the node "deprecated" in "%s" is deprecated.', $file); - } - - $definition->setDeprecated($package, $version, $message); - } - - $definition->setArguments($this->getArgumentsAsPhp($service, 'argument', $file, $definition instanceof ChildDefinition)); - $definition->setProperties($this->getArgumentsAsPhp($service, 'property', $file)); - - if ($factories = $this->getChildren($service, 'factory')) { - $factory = $factories[0]; - if ($function = $factory->getAttribute('function')) { - $definition->setFactory($function); - } else { - if ($childService = $factory->getAttribute('service')) { - $class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE); - } else { - $class = $factory->hasAttribute('class') ? $factory->getAttribute('class') : null; - } - - $definition->setFactory([$class, $factory->getAttribute('method') ?: '__invoke']); - } - } - - if ($configurators = $this->getChildren($service, 'configurator')) { - $configurator = $configurators[0]; - if ($function = $configurator->getAttribute('function')) { - $definition->setConfigurator($function); - } else { - if ($childService = $configurator->getAttribute('service')) { - $class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE); - } else { - $class = $configurator->getAttribute('class'); - } - - $definition->setConfigurator([$class, $configurator->getAttribute('method') ?: '__invoke']); - } - } - - foreach ($this->getChildren($service, 'call') as $call) { - $definition->addMethodCall($call->getAttribute('method'), $this->getArgumentsAsPhp($call, 'argument', $file), XmlUtils::phpize($call->getAttribute('returns-clone'))); - } - - $tags = $this->getChildren($service, 'tag'); - - foreach ($tags as $tag) { - $parameters = []; - $tagName = $tag->nodeValue; - foreach ($tag->attributes as $name => $node) { - if ('name' === $name && '' === $tagName) { - continue; - } - - if (str_contains($name, '-') && !str_contains($name, '_') && !\array_key_exists($normalizedName = str_replace('-', '_', $name), $parameters)) { - $parameters[$normalizedName] = XmlUtils::phpize($node->nodeValue); - } - // keep not normalized key - $parameters[$name] = XmlUtils::phpize($node->nodeValue); - } - - if ('' === $tagName && '' === $tagName = $tag->getAttribute('name')) { - throw new InvalidArgumentException(sprintf('The tag name for service "%s" in "%s" must be a non-empty string.', $service->getAttribute('id'), $file)); - } - - $definition->addTag($tagName, $parameters); - } - - $definition->setTags(array_merge_recursive($definition->getTags(), $defaults->getTags())); - - $bindings = $this->getArgumentsAsPhp($service, 'bind', $file); - $bindingType = $this->isLoadingInstanceof ? BoundArgument::INSTANCEOF_BINDING : BoundArgument::SERVICE_BINDING; - foreach ($bindings as $argument => $value) { - $bindings[$argument] = new BoundArgument($value, true, $bindingType, $file); - } - - // deep clone, to avoid multiple process of the same instance in the passes - $bindings = array_merge(unserialize(serialize($defaults->getBindings())), $bindings); - - if ($bindings) { - $definition->setBindings($bindings); - } - - if ($decorates = $service->getAttribute('decorates')) { - $decorationOnInvalid = $service->getAttribute('decoration-on-invalid') ?: 'exception'; - if ('exception' === $decorationOnInvalid) { - $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; - } elseif ('ignore' === $decorationOnInvalid) { - $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; - } elseif ('null' === $decorationOnInvalid) { - $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; - } else { - throw new InvalidArgumentException(sprintf('Invalid value "%s" for attribute "decoration-on-invalid" on service "%s". Did you mean "exception", "ignore" or "null" in "%s"?', $decorationOnInvalid, $service->getAttribute('id'), $file)); - } - - $renameId = $service->hasAttribute('decoration-inner-name') ? $service->getAttribute('decoration-inner-name') : null; - $priority = $service->hasAttribute('decoration-priority') ? $service->getAttribute('decoration-priority') : 0; - - $definition->setDecoratedService($decorates, $renameId, $priority, $invalidBehavior); - } - - return $definition; - } - - /** - * Parses an XML file to a \DOMDocument. - * - * @throws InvalidArgumentException When loading of XML file returns error - */ - private function parseFileToDOM(string $file): \DOMDocument - { - try { - $dom = XmlUtils::loadFile($file, [$this, 'validateSchema']); - } catch (\InvalidArgumentException $e) { - throw new InvalidArgumentException(sprintf('Unable to parse file "%s": ', $file).$e->getMessage(), $e->getCode(), $e); - } - - $this->validateExtensions($dom, $file); - - return $dom; - } - - /** - * Processes anonymous services. - */ - private function processAnonymousServices(\DOMDocument $xml, string $file, \DOMNode $root = null) - { - $definitions = []; - $count = 0; - $suffix = '~'.ContainerBuilder::hash($file); - - $xpath = new \DOMXPath($xml); - $xpath->registerNamespace('container', self::NS); - - // anonymous services as arguments/properties - if (false !== $nodes = $xpath->query('.//container:argument[@type="service"][not(@id)]|.//container:property[@type="service"][not(@id)]|.//container:bind[not(@id)]|.//container:factory[not(@service)]|.//container:configurator[not(@service)]', $root)) { - foreach ($nodes as $node) { - if ($services = $this->getChildren($node, 'service')) { - // give it a unique name - $id = sprintf('.%d_%s', ++$count, preg_replace('/^.*\\\\/', '', $services[0]->getAttribute('class')).$suffix); - $node->setAttribute('id', $id); - $node->setAttribute('service', $id); - - $definitions[$id] = [$services[0], $file]; - $services[0]->setAttribute('id', $id); - - // anonymous services are always private - // we could not use the constant false here, because of XML parsing - $services[0]->setAttribute('public', 'false'); - } - } - } - - // anonymous services "in the wild" - if (false !== $nodes = $xpath->query('.//container:services/container:service[not(@id)]', $root)) { - foreach ($nodes as $node) { - throw new InvalidArgumentException(sprintf('Top-level services must have "id" attribute, none found in "%s" at line %d.', $file, $node->getLineNo())); - } - } - - // resolve definitions - uksort($definitions, 'strnatcmp'); - foreach (array_reverse($definitions) as $id => [$domElement, $file]) { - if (null !== $definition = $this->parseDefinition($domElement, $file, new Definition())) { - $this->setDefinition($id, $definition); - } - } - } - - private function getArgumentsAsPhp(\DOMElement $node, string $name, string $file, bool $isChildDefinition = false): array - { - $arguments = []; - foreach ($this->getChildren($node, $name) as $arg) { - if ($arg->hasAttribute('name')) { - $arg->setAttribute('key', $arg->getAttribute('name')); - } - - // this is used by ChildDefinition to overwrite a specific - // argument of the parent definition - if ($arg->hasAttribute('index')) { - $key = ($isChildDefinition ? 'index_' : '').$arg->getAttribute('index'); - } elseif (!$arg->hasAttribute('key')) { - // Append an empty argument, then fetch its key to overwrite it later - $arguments[] = null; - $keys = array_keys($arguments); - $key = array_pop($keys); - } else { - $key = $arg->getAttribute('key'); - } - - $onInvalid = $arg->getAttribute('on-invalid'); - $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; - if ('ignore' == $onInvalid) { - $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; - } elseif ('ignore_uninitialized' == $onInvalid) { - $invalidBehavior = ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE; - } elseif ('null' == $onInvalid) { - $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; - } - - switch ($arg->getAttribute('type')) { - case 'service': - if ('' === $arg->getAttribute('id')) { - throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="service" has no or empty "id" attribute in "%s".', $name, $file)); - } - - $arguments[$key] = new Reference($arg->getAttribute('id'), $invalidBehavior); - break; - case 'expression': - if (!class_exists(Expression::class)) { - throw new \LogicException('The type="expression" attribute cannot be used without the ExpressionLanguage component. Try running "composer require symfony/expression-language".'); - } - - $arguments[$key] = new Expression($arg->nodeValue); - break; - case 'collection': - $arguments[$key] = $this->getArgumentsAsPhp($arg, $name, $file); - break; - case 'iterator': - $arg = $this->getArgumentsAsPhp($arg, $name, $file); - try { - $arguments[$key] = new IteratorArgument($arg); - } catch (InvalidArgumentException $e) { - throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="iterator" only accepts collections of type="service" references in "%s".', $name, $file)); - } - break; - case 'service_closure': - if ('' === $arg->getAttribute('id')) { - throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="service_closure" has no or empty "id" attribute in "%s".', $name, $file)); - } - - $arguments[$key] = new ServiceClosureArgument(new Reference($arg->getAttribute('id'), $invalidBehavior)); - break; - case 'service_locator': - $arg = $this->getArgumentsAsPhp($arg, $name, $file); - try { - $arguments[$key] = new ServiceLocatorArgument($arg); - } catch (InvalidArgumentException $e) { - throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="service_locator" only accepts maps of type="service" references in "%s".', $name, $file)); - } - break; - case 'tagged': - case 'tagged_iterator': - case 'tagged_locator': - $type = $arg->getAttribute('type'); - $forLocator = 'tagged_locator' === $type; - - if (!$arg->getAttribute('tag')) { - throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="%s" has no or empty "tag" attribute in "%s".', $name, $type, $file)); - } - - $arguments[$key] = new TaggedIteratorArgument($arg->getAttribute('tag'), $arg->getAttribute('index-by') ?: null, $arg->getAttribute('default-index-method') ?: null, $forLocator, $arg->getAttribute('default-priority-method') ?: null); - - if ($forLocator) { - $arguments[$key] = new ServiceLocatorArgument($arguments[$key]); - } - break; - case 'binary': - if (false === $value = base64_decode($arg->nodeValue)) { - throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="binary" is not a valid base64 encoded string.', $name)); - } - $arguments[$key] = $value; - break; - case 'abstract': - $arguments[$key] = new AbstractArgument($arg->nodeValue); - break; - case 'string': - $arguments[$key] = $arg->nodeValue; - break; - case 'constant': - $arguments[$key] = \constant(trim($arg->nodeValue)); - break; - default: - $arguments[$key] = XmlUtils::phpize($arg->nodeValue); - } - } - - return $arguments; - } - - /** - * Get child elements by name. - * - * @return \DOMElement[] - */ - private function getChildren(\DOMNode $node, string $name): array - { - $children = []; - foreach ($node->childNodes as $child) { - if ($child instanceof \DOMElement && $child->localName === $name && self::NS === $child->namespaceURI) { - $children[] = $child; - } - } - - return $children; - } - - /** - * Validates a documents XML schema. - * - * @return bool - * - * @throws RuntimeException When extension references a non-existent XSD file - */ - public function validateSchema(\DOMDocument $dom) - { - $schemaLocations = ['http://symfony.com/schema/dic/services' => str_replace('\\', '/', __DIR__.'/schema/dic/services/services-1.0.xsd')]; - - if ($element = $dom->documentElement->getAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'schemaLocation')) { - $items = preg_split('/\s+/', $element); - for ($i = 0, $nb = \count($items); $i < $nb; $i += 2) { - if (!$this->container->hasExtension($items[$i])) { - continue; - } - - if (($extension = $this->container->getExtension($items[$i])) && false !== $extension->getXsdValidationBasePath()) { - $ns = $extension->getNamespace(); - $path = str_replace([$ns, str_replace('http://', 'https://', $ns)], str_replace('\\', '/', $extension->getXsdValidationBasePath()).'/', $items[$i + 1]); - - if (!is_file($path)) { - throw new RuntimeException(sprintf('Extension "%s" references a non-existent XSD file "%s".', get_debug_type($extension), $path)); - } - - $schemaLocations[$items[$i]] = $path; - } - } - } - - $tmpfiles = []; - $imports = ''; - foreach ($schemaLocations as $namespace => $location) { - $parts = explode('/', $location); - $locationstart = 'file:///'; - if (0 === stripos($location, 'phar://')) { - $tmpfile = tempnam(sys_get_temp_dir(), 'symfony'); - if ($tmpfile) { - copy($location, $tmpfile); - $tmpfiles[] = $tmpfile; - $parts = explode('/', str_replace('\\', '/', $tmpfile)); - } else { - array_shift($parts); - $locationstart = 'phar:///'; - } - } elseif ('\\' === \DIRECTORY_SEPARATOR && str_starts_with($location, '\\\\')) { - $locationstart = ''; - } - $drive = '\\' === \DIRECTORY_SEPARATOR ? array_shift($parts).'/' : ''; - $location = $locationstart.$drive.implode('/', array_map('rawurlencode', $parts)); - - $imports .= sprintf(' <xsd:import namespace="%s" schemaLocation="%s" />'."\n", $namespace, $location); - } - - $source = <<<EOF -<?xml version="1.0" encoding="utf-8" ?> -<xsd:schema xmlns="http://symfony.com/schema" - xmlns:xsd="http://www.w3.org/2001/XMLSchema" - targetNamespace="http://symfony.com/schema" - elementFormDefault="qualified"> - - <xsd:import namespace="http://www.w3.org/XML/1998/namespace"/> -$imports -</xsd:schema> -EOF - ; - - if ($this->shouldEnableEntityLoader()) { - $disableEntities = libxml_disable_entity_loader(false); - $valid = @$dom->schemaValidateSource($source); - libxml_disable_entity_loader($disableEntities); - } else { - $valid = @$dom->schemaValidateSource($source); - } - foreach ($tmpfiles as $tmpfile) { - @unlink($tmpfile); - } - - return $valid; - } - - private function shouldEnableEntityLoader(): bool - { - // Version prior to 8.0 can be enabled without deprecation - if (\PHP_VERSION_ID < 80000) { - return true; - } - - static $dom, $schema; - if (null === $dom) { - $dom = new \DOMDocument(); - $dom->loadXML('<?xml version="1.0"?><test/>'); - - $tmpfile = tempnam(sys_get_temp_dir(), 'symfony'); - register_shutdown_function(static function () use ($tmpfile) { - @unlink($tmpfile); - }); - $schema = '<?xml version="1.0" encoding="utf-8"?> -<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> - <xsd:include schemaLocation="file:///'.rawurlencode(str_replace('\\', '/', $tmpfile)).'" /> -</xsd:schema>'; - file_put_contents($tmpfile, '<?xml version="1.0" encoding="utf-8"?> -<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> - <xsd:element name="test" type="testType" /> - <xsd:complexType name="testType"/> -</xsd:schema>'); - } - - return !@$dom->schemaValidateSource($schema); - } - - private function validateAlias(\DOMElement $alias, string $file) - { - foreach ($alias->attributes as $name => $node) { - if (!\in_array($name, ['alias', 'id', 'public'])) { - throw new InvalidArgumentException(sprintf('Invalid attribute "%s" defined for alias "%s" in "%s".', $name, $alias->getAttribute('id'), $file)); - } - } - - foreach ($alias->childNodes as $child) { - if (!$child instanceof \DOMElement || self::NS !== $child->namespaceURI) { - continue; - } - if (!\in_array($child->localName, ['deprecated'], true)) { - throw new InvalidArgumentException(sprintf('Invalid child element "%s" defined for alias "%s" in "%s".', $child->localName, $alias->getAttribute('id'), $file)); - } - } - } - - /** - * Validates an extension. - * - * @throws InvalidArgumentException When no extension is found corresponding to a tag - */ - private function validateExtensions(\DOMDocument $dom, string $file) - { - foreach ($dom->documentElement->childNodes as $node) { - if (!$node instanceof \DOMElement || 'http://symfony.com/schema/dic/services' === $node->namespaceURI) { - continue; - } - - // can it be handled by an extension? - if (!$this->container->hasExtension($node->namespaceURI)) { - $extensionNamespaces = array_filter(array_map(function (ExtensionInterface $ext) { return $ext->getNamespace(); }, $this->container->getExtensions())); - throw new InvalidArgumentException(sprintf('There is no extension able to load the configuration for "%s" (in "%s"). Looked for namespace "%s", found "%s".', $node->tagName, $file, $node->namespaceURI, $extensionNamespaces ? implode('", "', $extensionNamespaces) : 'none')); - } - } - } - - /** - * Loads from an extension. - */ - private function loadFromExtensions(\DOMDocument $xml) - { - foreach ($xml->documentElement->childNodes as $node) { - if (!$node instanceof \DOMElement || self::NS === $node->namespaceURI) { - continue; - } - - $values = static::convertDomElementToArray($node); - if (!\is_array($values)) { - $values = []; - } - - $this->container->loadFromExtension($node->namespaceURI, $values); - } - } - - /** - * Converts a \DOMElement object to a PHP array. - * - * The following rules applies during the conversion: - * - * * Each tag is converted to a key value or an array - * if there is more than one "value" - * - * * The content of a tag is set under a "value" key (<foo>bar</foo>) - * if the tag also has some nested tags - * - * * The attributes are converted to keys (<foo foo="bar"/>) - * - * * The nested-tags are converted to keys (<foo><foo>bar</foo></foo>) - * - * @param \DOMElement $element A \DOMElement instance - * - * @return mixed - */ - public static function convertDomElementToArray(\DOMElement $element) - { - return XmlUtils::convertDomElementToArray($element); - } -} diff --git a/lib/symfony/dependency-injection/Loader/YamlFileLoader.php b/lib/symfony/dependency-injection/Loader/YamlFileLoader.php deleted file mode 100644 index 8756e89ed..000000000 --- a/lib/symfony/dependency-injection/Loader/YamlFileLoader.php +++ /dev/null @@ -1,966 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader; - -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\AbstractArgument; -use Symfony\Component\DependencyInjection\Argument\BoundArgument; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\ExpressionLanguage\Expression; -use Symfony\Component\Yaml\Exception\ParseException; -use Symfony\Component\Yaml\Parser as YamlParser; -use Symfony\Component\Yaml\Tag\TaggedValue; -use Symfony\Component\Yaml\Yaml; - -/** - * YamlFileLoader loads YAML files service definitions. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class YamlFileLoader extends FileLoader -{ - private const SERVICE_KEYWORDS = [ - 'alias' => 'alias', - 'parent' => 'parent', - 'class' => 'class', - 'shared' => 'shared', - 'synthetic' => 'synthetic', - 'lazy' => 'lazy', - 'public' => 'public', - 'abstract' => 'abstract', - 'deprecated' => 'deprecated', - 'factory' => 'factory', - 'file' => 'file', - 'arguments' => 'arguments', - 'properties' => 'properties', - 'configurator' => 'configurator', - 'calls' => 'calls', - 'tags' => 'tags', - 'decorates' => 'decorates', - 'decoration_inner_name' => 'decoration_inner_name', - 'decoration_priority' => 'decoration_priority', - 'decoration_on_invalid' => 'decoration_on_invalid', - 'autowire' => 'autowire', - 'autoconfigure' => 'autoconfigure', - 'bind' => 'bind', - ]; - - private const PROTOTYPE_KEYWORDS = [ - 'resource' => 'resource', - 'namespace' => 'namespace', - 'exclude' => 'exclude', - 'parent' => 'parent', - 'shared' => 'shared', - 'lazy' => 'lazy', - 'public' => 'public', - 'abstract' => 'abstract', - 'deprecated' => 'deprecated', - 'factory' => 'factory', - 'arguments' => 'arguments', - 'properties' => 'properties', - 'configurator' => 'configurator', - 'calls' => 'calls', - 'tags' => 'tags', - 'autowire' => 'autowire', - 'autoconfigure' => 'autoconfigure', - 'bind' => 'bind', - ]; - - private const INSTANCEOF_KEYWORDS = [ - 'shared' => 'shared', - 'lazy' => 'lazy', - 'public' => 'public', - 'properties' => 'properties', - 'configurator' => 'configurator', - 'calls' => 'calls', - 'tags' => 'tags', - 'autowire' => 'autowire', - 'bind' => 'bind', - ]; - - private const DEFAULTS_KEYWORDS = [ - 'public' => 'public', - 'tags' => 'tags', - 'autowire' => 'autowire', - 'autoconfigure' => 'autoconfigure', - 'bind' => 'bind', - ]; - - private $yamlParser; - - private $anonymousServicesCount; - private $anonymousServicesSuffix; - - protected $autoRegisterAliasesForSinglyImplementedInterfaces = false; - - /** - * {@inheritdoc} - */ - public function load($resource, string $type = null) - { - $path = $this->locator->locate($resource); - - $content = $this->loadFile($path); - - $this->container->fileExists($path); - - // empty file - if (null === $content) { - return null; - } - - $this->loadContent($content, $path); - - // per-env configuration - if ($this->env && isset($content['when@'.$this->env])) { - if (!\is_array($content['when@'.$this->env])) { - throw new InvalidArgumentException(sprintf('The "when@%s" key should contain an array in "%s". Check your YAML syntax.', $this->env, $path)); - } - - $env = $this->env; - $this->env = null; - try { - $this->loadContent($content['when@'.$env], $path); - } finally { - $this->env = $env; - } - } - - return null; - } - - private function loadContent(array $content, string $path) - { - // imports - $this->parseImports($content, $path); - - // parameters - if (isset($content['parameters'])) { - if (!\is_array($content['parameters'])) { - throw new InvalidArgumentException(sprintf('The "parameters" key should contain an array in "%s". Check your YAML syntax.', $path)); - } - - foreach ($content['parameters'] as $key => $value) { - $this->container->setParameter($key, $this->resolveServices($value, $path, true)); - } - } - - // extensions - $this->loadFromExtensions($content); - - // services - $this->anonymousServicesCount = 0; - $this->anonymousServicesSuffix = '~'.ContainerBuilder::hash($path); - $this->setCurrentDir(\dirname($path)); - try { - $this->parseDefinitions($content, $path); - } finally { - $this->instanceof = []; - $this->registerAliasesForSinglyImplementedInterfaces(); - } - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - if (!\is_string($resource)) { - return false; - } - - if (null === $type && \in_array(pathinfo($resource, \PATHINFO_EXTENSION), ['yaml', 'yml'], true)) { - return true; - } - - return \in_array($type, ['yaml', 'yml'], true); - } - - private function parseImports(array $content, string $file) - { - if (!isset($content['imports'])) { - return; - } - - if (!\is_array($content['imports'])) { - throw new InvalidArgumentException(sprintf('The "imports" key should contain an array in "%s". Check your YAML syntax.', $file)); - } - - $defaultDirectory = \dirname($file); - foreach ($content['imports'] as $import) { - if (!\is_array($import)) { - $import = ['resource' => $import]; - } - if (!isset($import['resource'])) { - throw new InvalidArgumentException(sprintf('An import should provide a resource in "%s". Check your YAML syntax.', $file)); - } - - $this->setCurrentDir($defaultDirectory); - $this->import($import['resource'], $import['type'] ?? null, $import['ignore_errors'] ?? false, $file); - } - } - - private function parseDefinitions(array $content, string $file, bool $trackBindings = true) - { - if (!isset($content['services'])) { - return; - } - - if (!\is_array($content['services'])) { - throw new InvalidArgumentException(sprintf('The "services" key should contain an array in "%s". Check your YAML syntax.', $file)); - } - - if (\array_key_exists('_instanceof', $content['services'])) { - $instanceof = $content['services']['_instanceof']; - unset($content['services']['_instanceof']); - - if (!\is_array($instanceof)) { - throw new InvalidArgumentException(sprintf('Service "_instanceof" key must be an array, "%s" given in "%s".', get_debug_type($instanceof), $file)); - } - $this->instanceof = []; - $this->isLoadingInstanceof = true; - foreach ($instanceof as $id => $service) { - if (!$service || !\is_array($service)) { - throw new InvalidArgumentException(sprintf('Type definition "%s" must be a non-empty array within "_instanceof" in "%s". Check your YAML syntax.', $id, $file)); - } - if (\is_string($service) && str_starts_with($service, '@')) { - throw new InvalidArgumentException(sprintf('Type definition "%s" cannot be an alias within "_instanceof" in "%s". Check your YAML syntax.', $id, $file)); - } - $this->parseDefinition($id, $service, $file, [], false, $trackBindings); - } - } - - $this->isLoadingInstanceof = false; - $defaults = $this->parseDefaults($content, $file); - foreach ($content['services'] as $id => $service) { - $this->parseDefinition($id, $service, $file, $defaults, false, $trackBindings); - } - } - - /** - * @throws InvalidArgumentException - */ - private function parseDefaults(array &$content, string $file): array - { - if (!\array_key_exists('_defaults', $content['services'])) { - return []; - } - $defaults = $content['services']['_defaults']; - unset($content['services']['_defaults']); - - if (!\is_array($defaults)) { - throw new InvalidArgumentException(sprintf('Service "_defaults" key must be an array, "%s" given in "%s".', get_debug_type($defaults), $file)); - } - - foreach ($defaults as $key => $default) { - if (!isset(self::DEFAULTS_KEYWORDS[$key])) { - throw new InvalidArgumentException(sprintf('The configuration key "%s" cannot be used to define a default value in "%s". Allowed keys are "%s".', $key, $file, implode('", "', self::DEFAULTS_KEYWORDS))); - } - } - - if (isset($defaults['tags'])) { - if (!\is_array($tags = $defaults['tags'])) { - throw new InvalidArgumentException(sprintf('Parameter "tags" in "_defaults" must be an array in "%s". Check your YAML syntax.', $file)); - } - - foreach ($tags as $tag) { - if (!\is_array($tag)) { - $tag = ['name' => $tag]; - } - - if (1 === \count($tag) && \is_array(current($tag))) { - $name = key($tag); - $tag = current($tag); - } else { - if (!isset($tag['name'])) { - throw new InvalidArgumentException(sprintf('A "tags" entry in "_defaults" is missing a "name" key in "%s".', $file)); - } - $name = $tag['name']; - unset($tag['name']); - } - - if (!\is_string($name) || '' === $name) { - throw new InvalidArgumentException(sprintf('The tag name in "_defaults" must be a non-empty string in "%s".', $file)); - } - - foreach ($tag as $attribute => $value) { - if (!\is_scalar($value) && null !== $value) { - throw new InvalidArgumentException(sprintf('Tag "%s", attribute "%s" in "_defaults" must be of a scalar-type in "%s". Check your YAML syntax.', $name, $attribute, $file)); - } - } - } - } - - if (isset($defaults['bind'])) { - if (!\is_array($defaults['bind'])) { - throw new InvalidArgumentException(sprintf('Parameter "bind" in "_defaults" must be an array in "%s". Check your YAML syntax.', $file)); - } - - foreach ($this->resolveServices($defaults['bind'], $file) as $argument => $value) { - $defaults['bind'][$argument] = new BoundArgument($value, true, BoundArgument::DEFAULTS_BINDING, $file); - } - } - - return $defaults; - } - - private function isUsingShortSyntax(array $service): bool - { - foreach ($service as $key => $value) { - if (\is_string($key) && ('' === $key || ('$' !== $key[0] && !str_contains($key, '\\')))) { - return false; - } - } - - return true; - } - - /** - * Parses a definition. - * - * @param array|string|null $service - * - * @throws InvalidArgumentException When tags are invalid - */ - private function parseDefinition(string $id, $service, string $file, array $defaults, bool $return = false, bool $trackBindings = true) - { - if (preg_match('/^_[a-zA-Z0-9_]*$/', $id)) { - throw new InvalidArgumentException(sprintf('Service names that start with an underscore are reserved. Rename the "%s" service or define it in XML instead.', $id)); - } - - if (\is_string($service) && str_starts_with($service, '@')) { - $alias = new Alias(substr($service, 1)); - - if (isset($defaults['public'])) { - $alias->setPublic($defaults['public']); - } - - return $return ? $alias : $this->container->setAlias($id, $alias); - } - - if (\is_array($service) && $this->isUsingShortSyntax($service)) { - $service = ['arguments' => $service]; - } - - if (null === $service) { - $service = []; - } - - if (!\is_array($service)) { - throw new InvalidArgumentException(sprintf('A service definition must be an array or a string starting with "@" but "%s" found for service "%s" in "%s". Check your YAML syntax.', get_debug_type($service), $id, $file)); - } - - if (isset($service['stack'])) { - if (!\is_array($service['stack'])) { - throw new InvalidArgumentException(sprintf('A stack must be an array of definitions, "%s" given for service "%s" in "%s". Check your YAML syntax.', get_debug_type($service), $id, $file)); - } - - $stack = []; - - foreach ($service['stack'] as $k => $frame) { - if (\is_array($frame) && 1 === \count($frame) && !isset(self::SERVICE_KEYWORDS[key($frame)])) { - $frame = [ - 'class' => key($frame), - 'arguments' => current($frame), - ]; - } - - if (\is_array($frame) && isset($frame['stack'])) { - throw new InvalidArgumentException(sprintf('Service stack "%s" cannot contain another stack in "%s".', $id, $file)); - } - - $definition = $this->parseDefinition($id.'" at index "'.$k, $frame, $file, $defaults, true); - - if ($definition instanceof Definition) { - $definition->setInstanceofConditionals($this->instanceof); - } - - $stack[$k] = $definition; - } - - if ($diff = array_diff(array_keys($service), ['stack', 'public', 'deprecated'])) { - throw new InvalidArgumentException(sprintf('Invalid attribute "%s"; supported ones are "public" and "deprecated" for service "%s" in "%s". Check your YAML syntax.', implode('", "', $diff), $id, $file)); - } - - $service = [ - 'parent' => '', - 'arguments' => $stack, - 'tags' => ['container.stack'], - 'public' => $service['public'] ?? null, - 'deprecated' => $service['deprecated'] ?? null, - ]; - } - - $definition = isset($service[0]) && $service[0] instanceof Definition ? array_shift($service) : null; - $return = null === $definition ? $return : true; - - $this->checkDefinition($id, $service, $file); - - if (isset($service['alias'])) { - $alias = new Alias($service['alias']); - - if (isset($service['public'])) { - $alias->setPublic($service['public']); - } elseif (isset($defaults['public'])) { - $alias->setPublic($defaults['public']); - } - - foreach ($service as $key => $value) { - if (!\in_array($key, ['alias', 'public', 'deprecated'])) { - throw new InvalidArgumentException(sprintf('The configuration key "%s" is unsupported for the service "%s" which is defined as an alias in "%s". Allowed configuration keys for service aliases are "alias", "public" and "deprecated".', $key, $id, $file)); - } - - if ('deprecated' === $key) { - $deprecation = \is_array($value) ? $value : ['message' => $value]; - - if (!isset($deprecation['package'])) { - trigger_deprecation('symfony/dependency-injection', '5.1', 'Not setting the attribute "package" of the "deprecated" option in "%s" is deprecated.', $file); - } - - if (!isset($deprecation['version'])) { - trigger_deprecation('symfony/dependency-injection', '5.1', 'Not setting the attribute "version" of the "deprecated" option in "%s" is deprecated.', $file); - } - - $alias->setDeprecated($deprecation['package'] ?? '', $deprecation['version'] ?? '', $deprecation['message'] ?? ''); - } - } - - return $return ? $alias : $this->container->setAlias($id, $alias); - } - - if (null !== $definition) { - // no-op - } elseif ($this->isLoadingInstanceof) { - $definition = new ChildDefinition(''); - } elseif (isset($service['parent'])) { - if ('' !== $service['parent'] && '@' === $service['parent'][0]) { - throw new InvalidArgumentException(sprintf('The value of the "parent" option for the "%s" service must be the id of the service without the "@" prefix (replace "%s" with "%s").', $id, $service['parent'], substr($service['parent'], 1))); - } - - $definition = new ChildDefinition($service['parent']); - } else { - $definition = new Definition(); - } - - if (isset($defaults['public'])) { - $definition->setPublic($defaults['public']); - } - if (isset($defaults['autowire'])) { - $definition->setAutowired($defaults['autowire']); - } - if (isset($defaults['autoconfigure'])) { - $definition->setAutoconfigured($defaults['autoconfigure']); - } - - $definition->setChanges([]); - - if (isset($service['class'])) { - $definition->setClass($service['class']); - } - - if (isset($service['shared'])) { - $definition->setShared($service['shared']); - } - - if (isset($service['synthetic'])) { - $definition->setSynthetic($service['synthetic']); - } - - if (isset($service['lazy'])) { - $definition->setLazy((bool) $service['lazy']); - if (\is_string($service['lazy'])) { - $definition->addTag('proxy', ['interface' => $service['lazy']]); - } - } - - if (isset($service['public'])) { - $definition->setPublic($service['public']); - } - - if (isset($service['abstract'])) { - $definition->setAbstract($service['abstract']); - } - - if (isset($service['deprecated'])) { - $deprecation = \is_array($service['deprecated']) ? $service['deprecated'] : ['message' => $service['deprecated']]; - - if (!isset($deprecation['package'])) { - trigger_deprecation('symfony/dependency-injection', '5.1', 'Not setting the attribute "package" of the "deprecated" option in "%s" is deprecated.', $file); - } - - if (!isset($deprecation['version'])) { - trigger_deprecation('symfony/dependency-injection', '5.1', 'Not setting the attribute "version" of the "deprecated" option in "%s" is deprecated.', $file); - } - - $definition->setDeprecated($deprecation['package'] ?? '', $deprecation['version'] ?? '', $deprecation['message'] ?? ''); - } - - if (isset($service['factory'])) { - $definition->setFactory($this->parseCallable($service['factory'], 'factory', $id, $file)); - } - - if (isset($service['file'])) { - $definition->setFile($service['file']); - } - - if (isset($service['arguments'])) { - $definition->setArguments($this->resolveServices($service['arguments'], $file)); - } - - if (isset($service['properties'])) { - $definition->setProperties($this->resolveServices($service['properties'], $file)); - } - - if (isset($service['configurator'])) { - $definition->setConfigurator($this->parseCallable($service['configurator'], 'configurator', $id, $file)); - } - - if (isset($service['calls'])) { - if (!\is_array($service['calls'])) { - throw new InvalidArgumentException(sprintf('Parameter "calls" must be an array for service "%s" in "%s". Check your YAML syntax.', $id, $file)); - } - - foreach ($service['calls'] as $k => $call) { - if (!\is_array($call) && (!\is_string($k) || !$call instanceof TaggedValue)) { - throw new InvalidArgumentException(sprintf('Invalid method call for service "%s": expected map or array, "%s" given in "%s".', $id, $call instanceof TaggedValue ? '!'.$call->getTag() : get_debug_type($call), $file)); - } - - if (\is_string($k)) { - throw new InvalidArgumentException(sprintf('Invalid method call for service "%s", did you forgot a leading dash before "%s: ..." in "%s"?', $id, $k, $file)); - } - - if (isset($call['method']) && \is_string($call['method'])) { - $method = $call['method']; - $args = $call['arguments'] ?? []; - $returnsClone = $call['returns_clone'] ?? false; - } else { - if (1 === \count($call) && \is_string(key($call))) { - $method = key($call); - $args = $call[$method]; - - if ($args instanceof TaggedValue) { - if ('returns_clone' !== $args->getTag()) { - throw new InvalidArgumentException(sprintf('Unsupported tag "!%s", did you mean "!returns_clone" for service "%s" in "%s"?', $args->getTag(), $id, $file)); - } - - $returnsClone = true; - $args = $args->getValue(); - } else { - $returnsClone = false; - } - } elseif (empty($call[0])) { - throw new InvalidArgumentException(sprintf('Invalid call for service "%s": the method must be defined as the first index of an array or as the only key of a map in "%s".', $id, $file)); - } else { - $method = $call[0]; - $args = $call[1] ?? []; - $returnsClone = $call[2] ?? false; - } - } - - if (!\is_array($args)) { - throw new InvalidArgumentException(sprintf('The second parameter for function call "%s" must be an array of its arguments for service "%s" in "%s". Check your YAML syntax.', $method, $id, $file)); - } - - $args = $this->resolveServices($args, $file); - $definition->addMethodCall($method, $args, $returnsClone); - } - } - - $tags = $service['tags'] ?? []; - if (!\is_array($tags)) { - throw new InvalidArgumentException(sprintf('Parameter "tags" must be an array for service "%s" in "%s". Check your YAML syntax.', $id, $file)); - } - - if (isset($defaults['tags'])) { - $tags = array_merge($tags, $defaults['tags']); - } - - foreach ($tags as $tag) { - if (!\is_array($tag)) { - $tag = ['name' => $tag]; - } - - if (1 === \count($tag) && \is_array(current($tag))) { - $name = key($tag); - $tag = current($tag); - } else { - if (!isset($tag['name'])) { - throw new InvalidArgumentException(sprintf('A "tags" entry is missing a "name" key for service "%s" in "%s".', $id, $file)); - } - $name = $tag['name']; - unset($tag['name']); - } - - if (!\is_string($name) || '' === $name) { - throw new InvalidArgumentException(sprintf('The tag name for service "%s" in "%s" must be a non-empty string.', $id, $file)); - } - - foreach ($tag as $attribute => $value) { - if (!\is_scalar($value) && null !== $value) { - throw new InvalidArgumentException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s" in "%s". Check your YAML syntax.', $id, $name, $attribute, $file)); - } - } - - $definition->addTag($name, $tag); - } - - if (null !== $decorates = $service['decorates'] ?? null) { - if ('' !== $decorates && '@' === $decorates[0]) { - throw new InvalidArgumentException(sprintf('The value of the "decorates" option for the "%s" service must be the id of the service without the "@" prefix (replace "%s" with "%s").', $id, $service['decorates'], substr($decorates, 1))); - } - - $decorationOnInvalid = \array_key_exists('decoration_on_invalid', $service) ? $service['decoration_on_invalid'] : 'exception'; - if ('exception' === $decorationOnInvalid) { - $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; - } elseif ('ignore' === $decorationOnInvalid) { - $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; - } elseif (null === $decorationOnInvalid) { - $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; - } elseif ('null' === $decorationOnInvalid) { - throw new InvalidArgumentException(sprintf('Invalid value "%s" for attribute "decoration_on_invalid" on service "%s". Did you mean null (without quotes) in "%s"?', $decorationOnInvalid, $id, $file)); - } else { - throw new InvalidArgumentException(sprintf('Invalid value "%s" for attribute "decoration_on_invalid" on service "%s". Did you mean "exception", "ignore" or null in "%s"?', $decorationOnInvalid, $id, $file)); - } - - $renameId = $service['decoration_inner_name'] ?? null; - $priority = $service['decoration_priority'] ?? 0; - - $definition->setDecoratedService($decorates, $renameId, $priority, $invalidBehavior); - } - - if (isset($service['autowire'])) { - $definition->setAutowired($service['autowire']); - } - - if (isset($defaults['bind']) || isset($service['bind'])) { - // deep clone, to avoid multiple process of the same instance in the passes - $bindings = $definition->getBindings(); - $bindings += isset($defaults['bind']) ? unserialize(serialize($defaults['bind'])) : []; - - if (isset($service['bind'])) { - if (!\is_array($service['bind'])) { - throw new InvalidArgumentException(sprintf('Parameter "bind" must be an array for service "%s" in "%s". Check your YAML syntax.', $id, $file)); - } - - $bindings = array_merge($bindings, $this->resolveServices($service['bind'], $file)); - $bindingType = $this->isLoadingInstanceof ? BoundArgument::INSTANCEOF_BINDING : BoundArgument::SERVICE_BINDING; - foreach ($bindings as $argument => $value) { - if (!$value instanceof BoundArgument) { - $bindings[$argument] = new BoundArgument($value, $trackBindings, $bindingType, $file); - } - } - } - - $definition->setBindings($bindings); - } - - if (isset($service['autoconfigure'])) { - $definition->setAutoconfigured($service['autoconfigure']); - } - - if (\array_key_exists('namespace', $service) && !\array_key_exists('resource', $service)) { - throw new InvalidArgumentException(sprintf('A "resource" attribute must be set when the "namespace" attribute is set for service "%s" in "%s". Check your YAML syntax.', $id, $file)); - } - - if ($return) { - if (\array_key_exists('resource', $service)) { - throw new InvalidArgumentException(sprintf('Invalid "resource" attribute found for service "%s" in "%s". Check your YAML syntax.', $id, $file)); - } - - return $definition; - } - - if (\array_key_exists('resource', $service)) { - if (!\is_string($service['resource'])) { - throw new InvalidArgumentException(sprintf('A "resource" attribute must be of type string for service "%s" in "%s". Check your YAML syntax.', $id, $file)); - } - $exclude = $service['exclude'] ?? null; - $namespace = $service['namespace'] ?? $id; - $this->registerClasses($definition, $namespace, $service['resource'], $exclude); - } else { - $this->setDefinition($id, $definition); - } - } - - /** - * Parses a callable. - * - * @param string|array $callable A callable reference - * - * @throws InvalidArgumentException When errors occur - * - * @return string|array|Reference - */ - private function parseCallable($callable, string $parameter, string $id, string $file) - { - if (\is_string($callable)) { - if ('' !== $callable && '@' === $callable[0]) { - if (!str_contains($callable, ':')) { - return [$this->resolveServices($callable, $file), '__invoke']; - } - - throw new InvalidArgumentException(sprintf('The value of the "%s" option for the "%s" service must be the id of the service without the "@" prefix (replace "%s" with "%s" in "%s").', $parameter, $id, $callable, substr($callable, 1), $file)); - } - - return $callable; - } - - if (\is_array($callable)) { - if (isset($callable[0]) && isset($callable[1])) { - return [$this->resolveServices($callable[0], $file), $callable[1]]; - } - - if ('factory' === $parameter && isset($callable[1]) && null === $callable[0]) { - return $callable; - } - - throw new InvalidArgumentException(sprintf('Parameter "%s" must contain an array with two elements for service "%s" in "%s". Check your YAML syntax.', $parameter, $id, $file)); - } - - throw new InvalidArgumentException(sprintf('Parameter "%s" must be a string or an array for service "%s" in "%s". Check your YAML syntax.', $parameter, $id, $file)); - } - - /** - * Loads a YAML file. - * - * @return array|null - * - * @throws InvalidArgumentException when the given file is not a local file or when it does not exist - */ - protected function loadFile(string $file) - { - if (!class_exists(\Symfony\Component\Yaml\Parser::class)) { - throw new RuntimeException('Unable to load YAML config files as the Symfony Yaml Component is not installed.'); - } - - if (!stream_is_local($file)) { - throw new InvalidArgumentException(sprintf('This is not a local file "%s".', $file)); - } - - if (!is_file($file)) { - throw new InvalidArgumentException(sprintf('The file "%s" does not exist.', $file)); - } - - if (null === $this->yamlParser) { - $this->yamlParser = new YamlParser(); - } - - try { - $configuration = $this->yamlParser->parseFile($file, Yaml::PARSE_CONSTANT | Yaml::PARSE_CUSTOM_TAGS); - } catch (ParseException $e) { - throw new InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML: ', $file).$e->getMessage(), 0, $e); - } - - return $this->validate($configuration, $file); - } - - /** - * Validates a YAML file. - * - * @throws InvalidArgumentException When service file is not valid - */ - private function validate($content, string $file): ?array - { - if (null === $content) { - return $content; - } - - if (!\is_array($content)) { - throw new InvalidArgumentException(sprintf('The service file "%s" is not valid. It should contain an array. Check your YAML syntax.', $file)); - } - - foreach ($content as $namespace => $data) { - if (\in_array($namespace, ['imports', 'parameters', 'services']) || 0 === strpos($namespace, 'when@')) { - continue; - } - - if (!$this->container->hasExtension($namespace)) { - $extensionNamespaces = array_filter(array_map(function (ExtensionInterface $ext) { return $ext->getAlias(); }, $this->container->getExtensions())); - throw new InvalidArgumentException(sprintf('There is no extension able to load the configuration for "%s" (in "%s"). Looked for namespace "%s", found "%s".', $namespace, $file, $namespace, $extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none')); - } - } - - return $content; - } - - /** - * @return mixed - */ - private function resolveServices($value, string $file, bool $isParameter = false) - { - if ($value instanceof TaggedValue) { - $argument = $value->getValue(); - if ('iterator' === $value->getTag()) { - if (!\is_array($argument)) { - throw new InvalidArgumentException(sprintf('"!iterator" tag only accepts sequences in "%s".', $file)); - } - $argument = $this->resolveServices($argument, $file, $isParameter); - try { - return new IteratorArgument($argument); - } catch (InvalidArgumentException $e) { - throw new InvalidArgumentException(sprintf('"!iterator" tag only accepts arrays of "@service" references in "%s".', $file)); - } - } - if ('service_closure' === $value->getTag()) { - $argument = $this->resolveServices($argument, $file, $isParameter); - - if (!$argument instanceof Reference) { - throw new InvalidArgumentException(sprintf('"!service_closure" tag only accepts service references in "%s".', $file)); - } - - return new ServiceClosureArgument($argument); - } - if ('service_locator' === $value->getTag()) { - if (!\is_array($argument)) { - throw new InvalidArgumentException(sprintf('"!service_locator" tag only accepts maps in "%s".', $file)); - } - - $argument = $this->resolveServices($argument, $file, $isParameter); - - try { - return new ServiceLocatorArgument($argument); - } catch (InvalidArgumentException $e) { - throw new InvalidArgumentException(sprintf('"!service_locator" tag only accepts maps of "@service" references in "%s".', $file)); - } - } - if (\in_array($value->getTag(), ['tagged', 'tagged_iterator', 'tagged_locator'], true)) { - $forLocator = 'tagged_locator' === $value->getTag(); - - if (\is_array($argument) && isset($argument['tag']) && $argument['tag']) { - if ($diff = array_diff(array_keys($argument), ['tag', 'index_by', 'default_index_method', 'default_priority_method'])) { - throw new InvalidArgumentException(sprintf('"!%s" tag contains unsupported key "%s"; supported ones are "tag", "index_by", "default_index_method", and "default_priority_method".', $value->getTag(), implode('", "', $diff))); - } - - $argument = new TaggedIteratorArgument($argument['tag'], $argument['index_by'] ?? null, $argument['default_index_method'] ?? null, $forLocator, $argument['default_priority_method'] ?? null); - } elseif (\is_string($argument) && $argument) { - $argument = new TaggedIteratorArgument($argument, null, null, $forLocator); - } else { - throw new InvalidArgumentException(sprintf('"!%s" tags only accept a non empty string or an array with a key "tag" in "%s".', $value->getTag(), $file)); - } - - if ($forLocator) { - $argument = new ServiceLocatorArgument($argument); - } - - return $argument; - } - if ('service' === $value->getTag()) { - if ($isParameter) { - throw new InvalidArgumentException(sprintf('Using an anonymous service in a parameter is not allowed in "%s".', $file)); - } - - $isLoadingInstanceof = $this->isLoadingInstanceof; - $this->isLoadingInstanceof = false; - $instanceof = $this->instanceof; - $this->instanceof = []; - - $id = sprintf('.%d_%s', ++$this->anonymousServicesCount, preg_replace('/^.*\\\\/', '', $argument['class'] ?? '').$this->anonymousServicesSuffix); - $this->parseDefinition($id, $argument, $file, []); - - if (!$this->container->hasDefinition($id)) { - throw new InvalidArgumentException(sprintf('Creating an alias using the tag "!service" is not allowed in "%s".', $file)); - } - - $this->container->getDefinition($id); - - $this->isLoadingInstanceof = $isLoadingInstanceof; - $this->instanceof = $instanceof; - - return new Reference($id); - } - if ('abstract' === $value->getTag()) { - return new AbstractArgument($value->getValue()); - } - - throw new InvalidArgumentException(sprintf('Unsupported tag "!%s".', $value->getTag())); - } - - if (\is_array($value)) { - foreach ($value as $k => $v) { - $value[$k] = $this->resolveServices($v, $file, $isParameter); - } - } elseif (\is_string($value) && str_starts_with($value, '@=')) { - if ($isParameter) { - throw new InvalidArgumentException(sprintf('Using expressions in parameters is not allowed in "%s".', $file)); - } - - if (!class_exists(Expression::class)) { - throw new \LogicException('The "@=" expression syntax cannot be used without the ExpressionLanguage component. Try running "composer require symfony/expression-language".'); - } - - return new Expression(substr($value, 2)); - } elseif (\is_string($value) && str_starts_with($value, '@')) { - if (str_starts_with($value, '@@')) { - $value = substr($value, 1); - $invalidBehavior = null; - } elseif (str_starts_with($value, '@!')) { - $value = substr($value, 2); - $invalidBehavior = ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE; - } elseif (str_starts_with($value, '@?')) { - $value = substr($value, 2); - $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; - } else { - $value = substr($value, 1); - $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; - } - - if (null !== $invalidBehavior) { - $value = new Reference($value, $invalidBehavior); - } - } - - return $value; - } - - private function loadFromExtensions(array $content) - { - foreach ($content as $namespace => $values) { - if (\in_array($namespace, ['imports', 'parameters', 'services']) || 0 === strpos($namespace, 'when@')) { - continue; - } - - if (!\is_array($values) && null !== $values) { - $values = []; - } - - $this->container->loadFromExtension($namespace, $values); - } - } - - private function checkDefinition(string $id, array $definition, string $file) - { - if ($this->isLoadingInstanceof) { - $keywords = self::INSTANCEOF_KEYWORDS; - } elseif (isset($definition['resource']) || isset($definition['namespace'])) { - $keywords = self::PROTOTYPE_KEYWORDS; - } else { - $keywords = self::SERVICE_KEYWORDS; - } - - foreach ($definition as $key => $value) { - if (!isset($keywords[$key])) { - throw new InvalidArgumentException(sprintf('The configuration key "%s" is unsupported for definition "%s" in "%s". Allowed configuration keys are "%s".', $key, $id, $file, implode('", "', $keywords))); - } - } - } -} diff --git a/lib/symfony/dependency-injection/Loader/schema/dic/services/services-1.0.xsd b/lib/symfony/dependency-injection/Loader/schema/dic/services/services-1.0.xsd deleted file mode 100644 index 3c3000254..000000000 --- a/lib/symfony/dependency-injection/Loader/schema/dic/services/services-1.0.xsd +++ /dev/null @@ -1,353 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> - -<xsd:schema xmlns="http://symfony.com/schema/dic/services" - xmlns:xsd="http://www.w3.org/2001/XMLSchema" - targetNamespace="http://symfony.com/schema/dic/services" - elementFormDefault="qualified"> - - <xsd:annotation> - <xsd:documentation><![CDATA[ - Symfony XML Services Schema, version 1.0 - Authors: Fabien Potencier - - This defines a way to describe PHP objects (services) and their - dependencies. - ]]></xsd:documentation> - </xsd:annotation> - - <xsd:element name="container" type="container" /> - - <xsd:complexType name="container"> - <xsd:annotation> - <xsd:documentation><![CDATA[ - The root element of a service file. - ]]></xsd:documentation> - </xsd:annotation> - <xsd:sequence> - <xsd:group ref="foreign" /> - <xsd:sequence minOccurs="0"> - <xsd:element name="imports" type="imports" /> - <xsd:group ref="foreign" /> - </xsd:sequence> - <xsd:sequence minOccurs="0"> - <xsd:element name="parameters" type="parameters" /> - <xsd:group ref="foreign" /> - </xsd:sequence> - <xsd:sequence minOccurs="0"> - <xsd:element name="services" type="services" /> - <xsd:group ref="foreign" /> - </xsd:sequence> - <xsd:sequence minOccurs="0" maxOccurs="unbounded"> - <xsd:element name="when" type="when" /> - </xsd:sequence> - </xsd:sequence> - </xsd:complexType> - - <xsd:complexType name="when"> - <xsd:sequence> - <xsd:group ref="foreign" /> - <xsd:sequence minOccurs="0"> - <xsd:element name="imports" type="imports" /> - <xsd:group ref="foreign" /> - </xsd:sequence> - <xsd:sequence minOccurs="0"> - <xsd:element name="parameters" type="parameters" /> - <xsd:group ref="foreign" /> - </xsd:sequence> - <xsd:sequence minOccurs="0"> - <xsd:element name="services" type="services" /> - <xsd:group ref="foreign" /> - </xsd:sequence> - </xsd:sequence> - <xsd:attribute name="env" type="xsd:string" use="required" /> - </xsd:complexType> - - <xsd:group name="foreign"> - <xsd:sequence> - <xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - </xsd:group> - - <xsd:complexType name="services"> - <xsd:annotation> - <xsd:documentation><![CDATA[ - Enclosing element for the definition of all services - ]]></xsd:documentation> - </xsd:annotation> - <xsd:choice maxOccurs="unbounded"> - <xsd:element name="service" type="service" minOccurs="1" /> - <xsd:element name="prototype" type="prototype" minOccurs="0" /> - <xsd:element name="defaults" type="defaults" minOccurs="0" maxOccurs="1" /> - <xsd:element name="instanceof" type="instanceof" minOccurs="0" /> - <xsd:element name="stack" type="stack" minOccurs="0" /> - </xsd:choice> - </xsd:complexType> - - <xsd:complexType name="imports"> - <xsd:annotation> - <xsd:documentation><![CDATA[ - Enclosing element for the import elements - ]]></xsd:documentation> - </xsd:annotation> - <xsd:choice minOccurs="1" maxOccurs="unbounded"> - <xsd:element name="import" type="import" /> - </xsd:choice> - </xsd:complexType> - - <xsd:complexType name="import"> - <xsd:annotation> - <xsd:documentation><![CDATA[ - Import an external resource defining other services or parameters - ]]></xsd:documentation> - </xsd:annotation> - <xsd:attribute name="resource" type="xsd:string" use="required" /> - <xsd:attribute name="ignore-errors" type="ignore_errors" /> - <xsd:attribute name="type" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="callable"> - <xsd:choice minOccurs="0" maxOccurs="1"> - <xsd:element name="service" type="service" minOccurs="0" maxOccurs="1" /> - </xsd:choice> - <xsd:attribute name="service" type="xsd:string" /> - <xsd:attribute name="class" type="xsd:string" /> - <xsd:attribute name="method" type="xsd:string" /> - <xsd:attribute name="function" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="defaults"> - <xsd:annotation> - <xsd:documentation><![CDATA[ - Enclosing element for the service definitions' defaults for the current file - ]]></xsd:documentation> - </xsd:annotation> - <xsd:choice maxOccurs="unbounded"> - <xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="bind" type="bind" minOccurs="0" maxOccurs="unbounded" /> - </xsd:choice> - <xsd:attribute name="public" type="boolean" /> - <xsd:attribute name="autowire" type="boolean" /> - <xsd:attribute name="autoconfigure" type="boolean" /> - </xsd:complexType> - - <xsd:complexType name="service"> - <xsd:choice maxOccurs="unbounded"> - <xsd:element name="file" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="argument" type="argument" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="configurator" type="callable" minOccurs="0" maxOccurs="1" /> - <xsd:element name="factory" type="callable" minOccurs="0" maxOccurs="1" /> - <xsd:element name="deprecated" type="deprecated" minOccurs="0" maxOccurs="1" /> - <xsd:element name="call" type="call" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="bind" type="bind" minOccurs="0" maxOccurs="unbounded" /> - </xsd:choice> - <xsd:attribute name="id" type="xsd:string" /> - <xsd:attribute name="class" type="xsd:string" /> - <xsd:attribute name="shared" type="boolean" /> - <xsd:attribute name="public" type="boolean" /> - <xsd:attribute name="synthetic" type="boolean" /> - <xsd:attribute name="lazy" type="xsd:string" /> - <xsd:attribute name="abstract" type="boolean" /> - <xsd:attribute name="alias" type="xsd:string" /> - <xsd:attribute name="parent" type="xsd:string" /> - <xsd:attribute name="decorates" type="xsd:string" /> - <xsd:attribute name="decoration-on-invalid" type="invalid_decorated_service_sequence" /> - <xsd:attribute name="decoration-inner-name" type="xsd:string" /> - <xsd:attribute name="decoration-priority" type="xsd:integer" /> - <xsd:attribute name="autowire" type="boolean" /> - <xsd:attribute name="autoconfigure" type="boolean" /> - </xsd:complexType> - - <xsd:complexType name="instanceof"> - <xsd:choice maxOccurs="unbounded"> - <xsd:element name="configurator" type="callable" minOccurs="0" maxOccurs="1" /> - <xsd:element name="call" type="call" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="bind" type="bind" minOccurs="0" maxOccurs="unbounded" /> - </xsd:choice> - <xsd:attribute name="id" type="xsd:string" use="required" /> - <xsd:attribute name="shared" type="boolean" /> - <xsd:attribute name="public" type="boolean" /> - <xsd:attribute name="lazy" type="xsd:string" /> - <xsd:attribute name="autowire" type="boolean" /> - <xsd:attribute name="autoconfigure" type="boolean" /> - </xsd:complexType> - - <xsd:complexType name="prototype"> - <xsd:choice maxOccurs="unbounded"> - <xsd:element name="argument" type="argument" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="configurator" type="callable" minOccurs="0" maxOccurs="1" /> - <xsd:element name="factory" type="callable" minOccurs="0" maxOccurs="1" /> - <xsd:element name="deprecated" type="deprecated" minOccurs="0" maxOccurs="1" /> - <xsd:element name="call" type="call" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="bind" type="bind" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="exclude" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /> - </xsd:choice> - <xsd:attribute name="namespace" type="xsd:string" use="required" /> - <xsd:attribute name="resource" type="xsd:string" use="required" /> - <xsd:attribute name="exclude" type="xsd:string" /> - <xsd:attribute name="shared" type="boolean" /> - <xsd:attribute name="public" type="boolean" /> - <xsd:attribute name="lazy" type="xsd:string" /> - <xsd:attribute name="abstract" type="boolean" /> - <xsd:attribute name="parent" type="xsd:string" /> - <xsd:attribute name="autowire" type="boolean" /> - <xsd:attribute name="autoconfigure" type="boolean" /> - </xsd:complexType> - - <xsd:complexType name="stack"> - <xsd:choice maxOccurs="unbounded"> - <xsd:element name="service" type="service" minOccurs="1" /> - <xsd:element name="deprecated" type="deprecated" minOccurs="0" maxOccurs="1" /> - </xsd:choice> - <xsd:attribute name="id" type="xsd:string" use="required" /> - <xsd:attribute name="public" type="boolean" /> - </xsd:complexType> - - <xsd:complexType name="tag"> - <xsd:simpleContent> - <xsd:extension base="xsd:string"> - <xsd:anyAttribute namespace="##any" processContents="lax" /> - </xsd:extension> - </xsd:simpleContent> - </xsd:complexType> - - <xsd:complexType name="deprecated"> - <xsd:simpleContent> - <xsd:extension base="xsd:string"> - <!-- In Symfony 6, make these attributes required --> - <xsd:attribute name="package" type="xsd:string" /> - <xsd:attribute name="version" type="xsd:string" /> - </xsd:extension> - </xsd:simpleContent> - </xsd:complexType> - - <xsd:complexType name="parameters"> - <xsd:choice minOccurs="1" maxOccurs="unbounded"> - <xsd:element name="parameter" type="parameter" /> - </xsd:choice> - <xsd:attribute name="type" type="parameter_type" /> - <xsd:attribute name="key" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="parameter" mixed="true"> - <xsd:choice minOccurs="0" maxOccurs="unbounded"> - <xsd:element name="parameter" type="parameter" /> - </xsd:choice> - <xsd:attribute name="type" type="parameter_type" /> - <xsd:attribute name="id" type="xsd:string" /> - <xsd:attribute name="key" type="xsd:string" /> - <xsd:attribute name="on-invalid" type="invalid_sequence" /> - </xsd:complexType> - - <xsd:complexType name="property" mixed="true"> - <xsd:choice minOccurs="0"> - <xsd:element name="property" type="property" maxOccurs="unbounded" /> - <xsd:element name="service" type="service" /> - </xsd:choice> - <xsd:attribute name="type" type="argument_type" /> - <xsd:attribute name="id" type="xsd:string" /> - <xsd:attribute name="key" type="xsd:string" /> - <xsd:attribute name="name" type="xsd:string" /> - <xsd:attribute name="on-invalid" type="invalid_sequence" /> - <xsd:attribute name="tag" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="bind" mixed="true"> - <xsd:choice maxOccurs="unbounded"> - <xsd:element name="bind" type="argument" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="service" type="service" /> - </xsd:choice> - <xsd:attribute name="type" type="argument_type" /> - <xsd:attribute name="id" type="xsd:string" /> - <xsd:attribute name="key" type="xsd:string" use="required" /> - <xsd:attribute name="on-invalid" type="invalid_sequence" /> - <xsd:attribute name="method" type="xsd:string" /> - <xsd:attribute name="tag" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="argument" mixed="true"> - <xsd:choice minOccurs="0"> - <xsd:element name="argument" type="argument" maxOccurs="unbounded" /> - <xsd:element name="service" type="service" /> - </xsd:choice> - <xsd:attribute name="type" type="argument_type" /> - <xsd:attribute name="id" type="xsd:string" /> - <xsd:attribute name="key" type="xsd:string" /> - <xsd:attribute name="index" type="xsd:integer" /> - <xsd:attribute name="on-invalid" type="invalid_sequence" /> - <xsd:attribute name="tag" type="xsd:string" /> - <xsd:attribute name="index-by" type="xsd:string" /> - <xsd:attribute name="default-index-method" type="xsd:string" /> - <xsd:attribute name="default-priority-method" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="call"> - <xsd:choice minOccurs="0"> - <xsd:element name="argument" type="argument" maxOccurs="unbounded" /> - </xsd:choice> - <xsd:attribute name="method" type="xsd:string" /> - <xsd:attribute name="returns-clone" type="boolean" /> - </xsd:complexType> - - <xsd:simpleType name="parameter_type"> - <xsd:restriction base="xsd:string"> - <xsd:enumeration value="collection" /> - <xsd:enumeration value="string" /> - <xsd:enumeration value="constant" /> - <xsd:enumeration value="binary" /> - </xsd:restriction> - </xsd:simpleType> - - <xsd:simpleType name="argument_type"> - <xsd:restriction base="xsd:string"> - <xsd:enumeration value="abstract" /> - <xsd:enumeration value="collection" /> - <xsd:enumeration value="service" /> - <xsd:enumeration value="expression" /> - <xsd:enumeration value="string" /> - <xsd:enumeration value="constant" /> - <xsd:enumeration value="binary" /> - <xsd:enumeration value="iterator" /> - <xsd:enumeration value="service_closure" /> - <xsd:enumeration value="service_locator" /> - <!-- "tagged" is an alias of "tagged_iterator", using "tagged_iterator" is preferred. --> - <xsd:enumeration value="tagged" /> - <xsd:enumeration value="tagged_iterator" /> - <xsd:enumeration value="tagged_locator" /> - </xsd:restriction> - </xsd:simpleType> - - <xsd:simpleType name="ignore_errors"> - <xsd:restriction base="xsd:string"> - <xsd:pattern value="(true|false|not_found)" /> - </xsd:restriction> - </xsd:simpleType> - - <xsd:simpleType name="invalid_sequence"> - <xsd:restriction base="xsd:string"> - <xsd:enumeration value="null" /> - <xsd:enumeration value="ignore" /> - <xsd:enumeration value="exception" /> - <xsd:enumeration value="ignore_uninitialized" /> - </xsd:restriction> - </xsd:simpleType> - - <xsd:simpleType name="invalid_decorated_service_sequence"> - <xsd:restriction base="xsd:string"> - <xsd:enumeration value="null" /> - <xsd:enumeration value="ignore" /> - <xsd:enumeration value="exception" /> - </xsd:restriction> - </xsd:simpleType> - - <xsd:simpleType name="boolean"> - <xsd:restriction base="xsd:string"> - <xsd:pattern value="(%.+%|true|false)" /> - </xsd:restriction> - </xsd:simpleType> -</xsd:schema> diff --git a/lib/symfony/dependency-injection/Parameter.php b/lib/symfony/dependency-injection/Parameter.php deleted file mode 100644 index e182e1240..000000000 --- a/lib/symfony/dependency-injection/Parameter.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -/** - * Parameter represents a parameter reference. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Parameter -{ - private $id; - - public function __construct(string $id) - { - $this->id = $id; - } - - /** - * @return string - */ - public function __toString() - { - return $this->id; - } -} diff --git a/lib/symfony/dependency-injection/ParameterBag/ContainerBag.php b/lib/symfony/dependency-injection/ParameterBag/ContainerBag.php deleted file mode 100644 index 54aaa556b..000000000 --- a/lib/symfony/dependency-injection/ParameterBag/ContainerBag.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\ParameterBag; - -use Symfony\Component\DependencyInjection\Container; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class ContainerBag extends FrozenParameterBag implements ContainerBagInterface -{ - private $container; - - public function __construct(Container $container) - { - $this->container = $container; - } - - /** - * {@inheritdoc} - */ - public function all() - { - return $this->container->getParameterBag()->all(); - } - - /** - * {@inheritdoc} - * - * @return array|bool|string|int|float|\UnitEnum|null - */ - public function get(string $name) - { - return $this->container->getParameter($name); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function has(string $name) - { - return $this->container->hasParameter($name); - } -} diff --git a/lib/symfony/dependency-injection/ParameterBag/ContainerBagInterface.php b/lib/symfony/dependency-injection/ParameterBag/ContainerBagInterface.php deleted file mode 100644 index f8380ac97..000000000 --- a/lib/symfony/dependency-injection/ParameterBag/ContainerBagInterface.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\ParameterBag; - -use Psr\Container\ContainerInterface; -use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; - -/** - * ContainerBagInterface is the interface implemented by objects that manage service container parameters. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -interface ContainerBagInterface extends ContainerInterface -{ - /** - * Gets the service container parameters. - * - * @return array - */ - public function all(); - - /** - * Replaces parameter placeholders (%name%) by their values. - * - * @param mixed $value A value - * - * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist - */ - public function resolveValue($value); - - /** - * Escape parameter placeholders %. - * - * @param mixed $value - * - * @return mixed - */ - public function escapeValue($value); - - /** - * Unescape parameter placeholders %. - * - * @param mixed $value - * - * @return mixed - */ - public function unescapeValue($value); -} diff --git a/lib/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php b/lib/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php deleted file mode 100644 index 67b8aeeb1..000000000 --- a/lib/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php +++ /dev/null @@ -1,154 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\ParameterBag; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class EnvPlaceholderParameterBag extends ParameterBag -{ - private $envPlaceholderUniquePrefix; - private $envPlaceholders = []; - private $unusedEnvPlaceholders = []; - private $providedTypes = []; - - private static $counter = 0; - - /** - * {@inheritdoc} - */ - public function get(string $name) - { - if (str_starts_with($name, 'env(') && str_ends_with($name, ')') && 'env()' !== $name) { - $env = substr($name, 4, -1); - - if (isset($this->envPlaceholders[$env])) { - foreach ($this->envPlaceholders[$env] as $placeholder) { - return $placeholder; // return first result - } - } - if (isset($this->unusedEnvPlaceholders[$env])) { - foreach ($this->unusedEnvPlaceholders[$env] as $placeholder) { - return $placeholder; // return first result - } - } - if (!preg_match('/^(?:[-.\w]*+:)*+\w++$/', $env)) { - throw new InvalidArgumentException(sprintf('Invalid %s name: only "word" characters are allowed.', $name)); - } - if ($this->has($name) && null !== ($defaultValue = parent::get($name)) && !\is_string($defaultValue)) { - throw new RuntimeException(sprintf('The default value of an env() parameter must be a string or null, but "%s" given to "%s".', get_debug_type($defaultValue), $name)); - } - - $uniqueName = md5($name.'_'.self::$counter++); - $placeholder = sprintf('%s_%s_%s', $this->getEnvPlaceholderUniquePrefix(), strtr($env, ':-.', '___'), $uniqueName); - $this->envPlaceholders[$env][$placeholder] = $placeholder; - - return $placeholder; - } - - return parent::get($name); - } - - /** - * Gets the common env placeholder prefix for env vars created by this bag. - */ - public function getEnvPlaceholderUniquePrefix(): string - { - if (null === $this->envPlaceholderUniquePrefix) { - $reproducibleEntropy = unserialize(serialize($this->parameters)); - array_walk_recursive($reproducibleEntropy, function (&$v) { $v = null; }); - $this->envPlaceholderUniquePrefix = 'env_'.substr(md5(serialize($reproducibleEntropy)), -16); - } - - return $this->envPlaceholderUniquePrefix; - } - - /** - * Returns the map of env vars used in the resolved parameter values to their placeholders. - * - * @return string[][] A map of env var names to their placeholders - */ - public function getEnvPlaceholders() - { - return $this->envPlaceholders; - } - - public function getUnusedEnvPlaceholders(): array - { - return $this->unusedEnvPlaceholders; - } - - public function clearUnusedEnvPlaceholders() - { - $this->unusedEnvPlaceholders = []; - } - - /** - * Merges the env placeholders of another EnvPlaceholderParameterBag. - */ - public function mergeEnvPlaceholders(self $bag) - { - if ($newPlaceholders = $bag->getEnvPlaceholders()) { - $this->envPlaceholders += $newPlaceholders; - - foreach ($newPlaceholders as $env => $placeholders) { - $this->envPlaceholders[$env] += $placeholders; - } - } - - if ($newUnusedPlaceholders = $bag->getUnusedEnvPlaceholders()) { - $this->unusedEnvPlaceholders += $newUnusedPlaceholders; - - foreach ($newUnusedPlaceholders as $env => $placeholders) { - $this->unusedEnvPlaceholders[$env] += $placeholders; - } - } - } - - /** - * Maps env prefixes to their corresponding PHP types. - */ - public function setProvidedTypes(array $providedTypes) - { - $this->providedTypes = $providedTypes; - } - - /** - * Gets the PHP types corresponding to env() parameter prefixes. - * - * @return string[][] - */ - public function getProvidedTypes() - { - return $this->providedTypes; - } - - /** - * {@inheritdoc} - */ - public function resolve() - { - if ($this->resolved) { - return; - } - parent::resolve(); - - foreach ($this->envPlaceholders as $env => $placeholders) { - if ($this->has($name = "env($env)") && null !== ($default = $this->parameters[$name]) && !\is_string($default)) { - throw new RuntimeException(sprintf('The default value of env parameter "%s" must be a string or null, "%s" given.', $env, get_debug_type($default))); - } - } - } -} diff --git a/lib/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php b/lib/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php deleted file mode 100644 index 5a4aaf8b2..000000000 --- a/lib/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php +++ /dev/null @@ -1,68 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\ParameterBag; - -use Symfony\Component\DependencyInjection\Exception\LogicException; - -/** - * Holds read-only parameters. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class FrozenParameterBag extends ParameterBag -{ - /** - * For performance reasons, the constructor assumes that - * all keys are already lowercased. - * - * This is always the case when used internally. - * - * @param array $parameters An array of parameters - */ - public function __construct(array $parameters = []) - { - $this->parameters = $parameters; - $this->resolved = true; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - throw new LogicException('Impossible to call clear() on a frozen ParameterBag.'); - } - - /** - * {@inheritdoc} - */ - public function add(array $parameters) - { - throw new LogicException('Impossible to call add() on a frozen ParameterBag.'); - } - - /** - * {@inheritdoc} - */ - public function set(string $name, $value) - { - throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); - } - - /** - * {@inheritdoc} - */ - public function remove(string $name) - { - throw new LogicException('Impossible to call remove() on a frozen ParameterBag.'); - } -} diff --git a/lib/symfony/dependency-injection/ParameterBag/ParameterBag.php b/lib/symfony/dependency-injection/ParameterBag/ParameterBag.php deleted file mode 100644 index b1bf77568..000000000 --- a/lib/symfony/dependency-injection/ParameterBag/ParameterBag.php +++ /dev/null @@ -1,276 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\ParameterBag; - -use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException; -use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; - -/** - * Holds parameters. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class ParameterBag implements ParameterBagInterface -{ - protected $parameters = []; - protected $resolved = false; - - public function __construct(array $parameters = []) - { - $this->add($parameters); - } - - /** - * {@inheritdoc} - */ - public function clear() - { - $this->parameters = []; - } - - /** - * {@inheritdoc} - */ - public function add(array $parameters) - { - foreach ($parameters as $key => $value) { - $this->set($key, $value); - } - } - - /** - * {@inheritdoc} - */ - public function all() - { - return $this->parameters; - } - - /** - * {@inheritdoc} - */ - public function get(string $name) - { - if (!\array_key_exists($name, $this->parameters)) { - if (!$name) { - throw new ParameterNotFoundException($name); - } - - $alternatives = []; - foreach ($this->parameters as $key => $parameterValue) { - $lev = levenshtein($name, $key); - if ($lev <= \strlen($name) / 3 || str_contains($key, $name)) { - $alternatives[] = $key; - } - } - - $nonNestedAlternative = null; - if (!\count($alternatives) && str_contains($name, '.')) { - $namePartsLength = array_map('strlen', explode('.', $name)); - $key = substr($name, 0, -1 * (1 + array_pop($namePartsLength))); - while (\count($namePartsLength)) { - if ($this->has($key)) { - if (\is_array($this->get($key))) { - $nonNestedAlternative = $key; - } - break; - } - - $key = substr($key, 0, -1 * (1 + array_pop($namePartsLength))); - } - } - - throw new ParameterNotFoundException($name, null, null, null, $alternatives, $nonNestedAlternative); - } - - return $this->parameters[$name]; - } - - /** - * {@inheritdoc} - */ - public function set(string $name, $value) - { - $this->parameters[$name] = $value; - } - - /** - * {@inheritdoc} - */ - public function has(string $name) - { - return \array_key_exists($name, $this->parameters); - } - - /** - * {@inheritdoc} - */ - public function remove(string $name) - { - unset($this->parameters[$name]); - } - - /** - * {@inheritdoc} - */ - public function resolve() - { - if ($this->resolved) { - return; - } - - $parameters = []; - foreach ($this->parameters as $key => $value) { - try { - $value = $this->resolveValue($value); - $parameters[$key] = $this->unescapeValue($value); - } catch (ParameterNotFoundException $e) { - $e->setSourceKey($key); - - throw $e; - } - } - - $this->parameters = $parameters; - $this->resolved = true; - } - - /** - * Replaces parameter placeholders (%name%) by their values. - * - * @param mixed $value A value - * @param array $resolving An array of keys that are being resolved (used internally to detect circular references) - * - * @return mixed - * - * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist - * @throws ParameterCircularReferenceException if a circular reference if detected - * @throws RuntimeException when a given parameter has a type problem - */ - public function resolveValue($value, array $resolving = []) - { - if (\is_array($value)) { - $args = []; - foreach ($value as $k => $v) { - $args[\is_string($k) ? $this->resolveValue($k, $resolving) : $k] = $this->resolveValue($v, $resolving); - } - - return $args; - } - - if (!\is_string($value) || 2 > \strlen($value)) { - return $value; - } - - return $this->resolveString($value, $resolving); - } - - /** - * Resolves parameters inside a string. - * - * @param array $resolving An array of keys that are being resolved (used internally to detect circular references) - * - * @return mixed - * - * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist - * @throws ParameterCircularReferenceException if a circular reference if detected - * @throws RuntimeException when a given parameter has a type problem - */ - public function resolveString(string $value, array $resolving = []) - { - // we do this to deal with non string values (Boolean, integer, ...) - // as the preg_replace_callback throw an exception when trying - // a non-string in a parameter value - if (preg_match('/^%([^%\s]+)%$/', $value, $match)) { - $key = $match[1]; - - if (isset($resolving[$key])) { - throw new ParameterCircularReferenceException(array_keys($resolving)); - } - - $resolving[$key] = true; - - return $this->resolved ? $this->get($key) : $this->resolveValue($this->get($key), $resolving); - } - - return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($resolving, $value) { - // skip %% - if (!isset($match[1])) { - return '%%'; - } - - $key = $match[1]; - if (isset($resolving[$key])) { - throw new ParameterCircularReferenceException(array_keys($resolving)); - } - - $resolved = $this->get($key); - - if (!\is_string($resolved) && !is_numeric($resolved)) { - throw new RuntimeException(sprintf('A string value must be composed of strings and/or numbers, but found parameter "%s" of type "%s" inside string value "%s".', $key, get_debug_type($resolved), $value)); - } - - $resolved = (string) $resolved; - $resolving[$key] = true; - - return $this->isResolved() ? $resolved : $this->resolveString($resolved, $resolving); - }, $value); - } - - public function isResolved() - { - return $this->resolved; - } - - /** - * {@inheritdoc} - */ - public function escapeValue($value) - { - if (\is_string($value)) { - return str_replace('%', '%%', $value); - } - - if (\is_array($value)) { - $result = []; - foreach ($value as $k => $v) { - $result[$k] = $this->escapeValue($v); - } - - return $result; - } - - return $value; - } - - /** - * {@inheritdoc} - */ - public function unescapeValue($value) - { - if (\is_string($value)) { - return str_replace('%%', '%', $value); - } - - if (\is_array($value)) { - $result = []; - foreach ($value as $k => $v) { - $result[$k] = $this->unescapeValue($v); - } - - return $result; - } - - return $value; - } -} diff --git a/lib/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php b/lib/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php deleted file mode 100644 index 808a0fa42..000000000 --- a/lib/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php +++ /dev/null @@ -1,106 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\ParameterBag; - -use Symfony\Component\DependencyInjection\Exception\LogicException; -use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; - -/** - * ParameterBagInterface is the interface implemented by objects that manage service container parameters. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface ParameterBagInterface -{ - /** - * Clears all parameters. - * - * @throws LogicException if the ParameterBagInterface cannot be cleared - */ - public function clear(); - - /** - * Adds parameters to the service container parameters. - * - * @throws LogicException if the parameter cannot be added - */ - public function add(array $parameters); - - /** - * Gets the service container parameters. - * - * @return array - */ - public function all(); - - /** - * Gets a service container parameter. - * - * @return array|bool|string|int|float|\UnitEnum|null - * - * @throws ParameterNotFoundException if the parameter is not defined - */ - public function get(string $name); - - /** - * Removes a parameter. - */ - public function remove(string $name); - - /** - * Sets a service container parameter. - * - * @param array|bool|string|int|float|\UnitEnum|null $value The parameter value - * - * @throws LogicException if the parameter cannot be set - */ - public function set(string $name, $value); - - /** - * Returns true if a parameter name is defined. - * - * @return bool - */ - public function has(string $name); - - /** - * Replaces parameter placeholders (%name%) by their values for all parameters. - */ - public function resolve(); - - /** - * Replaces parameter placeholders (%name%) by their values. - * - * @param mixed $value A value - * - * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist - */ - public function resolveValue($value); - - /** - * Escape parameter placeholders %. - * - * @param mixed $value - * - * @return mixed - */ - public function escapeValue($value); - - /** - * Unescape parameter placeholders %. - * - * @param mixed $value - * - * @return mixed - */ - public function unescapeValue($value); -} diff --git a/lib/symfony/dependency-injection/README.md b/lib/symfony/dependency-injection/README.md deleted file mode 100644 index fa6719a79..000000000 --- a/lib/symfony/dependency-injection/README.md +++ /dev/null @@ -1,14 +0,0 @@ -DependencyInjection Component -============================= - -The DependencyInjection component allows you to standardize and centralize the -way objects are constructed in your application. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/dependency_injection.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/lib/symfony/dependency-injection/Reference.php b/lib/symfony/dependency-injection/Reference.php deleted file mode 100644 index 7f7b32cc6..000000000 --- a/lib/symfony/dependency-injection/Reference.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -/** - * Reference represents a service reference. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Reference -{ - private $id; - private $invalidBehavior; - - public function __construct(string $id, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) - { - $this->id = $id; - $this->invalidBehavior = $invalidBehavior; - } - - /** - * @return string - */ - public function __toString() - { - return $this->id; - } - - /** - * Returns the behavior to be used when the service does not exist. - * - * @return int - */ - public function getInvalidBehavior() - { - return $this->invalidBehavior; - } -} diff --git a/lib/symfony/dependency-injection/ReverseContainer.php b/lib/symfony/dependency-injection/ReverseContainer.php deleted file mode 100644 index 280e9e2dd..000000000 --- a/lib/symfony/dependency-injection/ReverseContainer.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -use Psr\Container\ContainerInterface; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; - -/** - * Turns public and "container.reversible" services back to their ids. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -final class ReverseContainer -{ - private $serviceContainer; - private $reversibleLocator; - private $tagName; - private $getServiceId; - - public function __construct(Container $serviceContainer, ContainerInterface $reversibleLocator, string $tagName = 'container.reversible') - { - $this->serviceContainer = $serviceContainer; - $this->reversibleLocator = $reversibleLocator; - $this->tagName = $tagName; - $this->getServiceId = \Closure::bind(function (object $service): ?string { - return array_search($service, $this->services, true) ?: array_search($service, $this->privates, true) ?: null; - }, $serviceContainer, Container::class); - } - - /** - * Returns the id of the passed object when it exists as a service. - * - * To be reversible, services need to be either public or be tagged with "container.reversible". - */ - public function getId(object $service): ?string - { - if ($this->serviceContainer === $service) { - return 'service_container'; - } - - if (null === $id = ($this->getServiceId)($service)) { - return null; - } - - if ($this->serviceContainer->has($id) || $this->reversibleLocator->has($id)) { - return $id; - } - - return null; - } - - /** - * @throws ServiceNotFoundException When the service is not reversible - */ - public function getService(string $id): object - { - if ($this->serviceContainer->has($id)) { - return $this->serviceContainer->get($id); - } - - if ($this->reversibleLocator->has($id)) { - return $this->reversibleLocator->get($id); - } - - if (isset($this->serviceContainer->getRemovedIds()[$id])) { - throw new ServiceNotFoundException($id, null, null, [], sprintf('The "%s" service is private and cannot be accessed by reference. You should either make it public, or tag it as "%s".', $id, $this->tagName)); - } - - // will throw a ServiceNotFoundException - $this->serviceContainer->get($id); - } -} diff --git a/lib/symfony/dependency-injection/ServiceLocator.php b/lib/symfony/dependency-injection/ServiceLocator.php deleted file mode 100644 index 4be0d6f72..000000000 --- a/lib/symfony/dependency-injection/ServiceLocator.php +++ /dev/null @@ -1,150 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -use Psr\Container\ContainerExceptionInterface; -use Psr\Container\NotFoundExceptionInterface; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; -use Symfony\Contracts\Service\ServiceLocatorTrait; -use Symfony\Contracts\Service\ServiceProviderInterface; -use Symfony\Contracts\Service\ServiceSubscriberInterface; - -/** - * @author Robin Chalas <robin.chalas@gmail.com> - * @author Nicolas Grekas <p@tchwork.com> - */ -class ServiceLocator implements ServiceProviderInterface -{ - use ServiceLocatorTrait { - get as private doGet; - } - - private $externalId; - private $container; - - /** - * {@inheritdoc} - * - * @return mixed - */ - public function get(string $id) - { - if (!$this->externalId) { - return $this->doGet($id); - } - - try { - return $this->doGet($id); - } catch (RuntimeException $e) { - $what = sprintf('service "%s" required by "%s"', $id, $this->externalId); - $message = preg_replace('/service "\.service_locator\.[^"]++"/', $what, $e->getMessage()); - - if ($e->getMessage() === $message) { - $message = sprintf('Cannot resolve %s: %s', $what, $message); - } - - $r = new \ReflectionProperty($e, 'message'); - $r->setAccessible(true); - $r->setValue($e, $message); - - throw $e; - } - } - - public function __invoke(string $id) - { - return isset($this->factories[$id]) ? $this->get($id) : null; - } - - /** - * @internal - * - * @return static - */ - public function withContext(string $externalId, Container $container): self - { - $locator = clone $this; - $locator->externalId = $externalId; - $locator->container = $container; - - return $locator; - } - - private function createNotFoundException(string $id): NotFoundExceptionInterface - { - if ($this->loading) { - $msg = sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', end($this->loading), $id, $this->formatAlternatives()); - - return new ServiceNotFoundException($id, end($this->loading) ?: null, null, [], $msg); - } - - $class = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT | \DEBUG_BACKTRACE_IGNORE_ARGS, 4); - $class = isset($class[3]['object']) ? \get_class($class[3]['object']) : null; - $externalId = $this->externalId ?: $class; - - $msg = []; - $msg[] = sprintf('Service "%s" not found:', $id); - - if (!$this->container) { - $class = null; - } elseif ($this->container->has($id) || isset($this->container->getRemovedIds()[$id])) { - $msg[] = 'even though it exists in the app\'s container,'; - } else { - try { - $this->container->get($id); - $class = null; - } catch (ServiceNotFoundException $e) { - if ($e->getAlternatives()) { - $msg[] = sprintf('did you mean %s? Anyway,', $this->formatAlternatives($e->getAlternatives(), 'or')); - } else { - $class = null; - } - } - } - if ($externalId) { - $msg[] = sprintf('the container inside "%s" is a smaller service locator that %s', $externalId, $this->formatAlternatives()); - } else { - $msg[] = sprintf('the current service locator %s', $this->formatAlternatives()); - } - - if (!$class) { - // no-op - } elseif (is_subclass_of($class, ServiceSubscriberInterface::class)) { - $msg[] = sprintf('Unless you need extra laziness, try using dependency injection instead. Otherwise, you need to declare it using "%s::getSubscribedServices()".', preg_replace('/([^\\\\]++\\\\)++/', '', $class)); - } else { - $msg[] = 'Try using dependency injection instead.'; - } - - return new ServiceNotFoundException($id, end($this->loading) ?: null, null, [], implode(' ', $msg)); - } - - private function createCircularReferenceException(string $id, array $path): ContainerExceptionInterface - { - return new ServiceCircularReferenceException($id, $path); - } - - private function formatAlternatives(array $alternatives = null, string $separator = 'and'): string - { - $format = '"%s"%s'; - if (null === $alternatives) { - if (!$alternatives = array_keys($this->factories)) { - return 'is empty...'; - } - $format = sprintf('only knows about the %s service%s.', $format, 1 < \count($alternatives) ? 's' : ''); - } - $last = array_pop($alternatives); - - return sprintf($format, $alternatives ? implode('", "', $alternatives) : $last, $alternatives ? sprintf(' %s "%s"', $separator, $last) : ''); - } -} diff --git a/lib/symfony/dependency-injection/TaggedContainerInterface.php b/lib/symfony/dependency-injection/TaggedContainerInterface.php deleted file mode 100644 index 25d5a098f..000000000 --- a/lib/symfony/dependency-injection/TaggedContainerInterface.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -/** - * TaggedContainerInterface is the interface implemented when a container knows how to deals with tags. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface TaggedContainerInterface extends ContainerInterface -{ - /** - * Returns service ids for a given tag. - * - * @param string $name The tag name - * - * @return array - */ - public function findTaggedServiceIds(string $name); -} diff --git a/lib/symfony/dependency-injection/TypedReference.php b/lib/symfony/dependency-injection/TypedReference.php deleted file mode 100644 index 4099a0059..000000000 --- a/lib/symfony/dependency-injection/TypedReference.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -/** - * Represents a PHP type-hinted service reference. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class TypedReference extends Reference -{ - private $type; - private $name; - - /** - * @param string $id The service identifier - * @param string $type The PHP type of the identified service - * @param int $invalidBehavior The behavior when the service does not exist - * @param string|null $name The name of the argument targeting the service - */ - public function __construct(string $id, string $type, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, string $name = null) - { - $this->name = $type === $id ? $name : null; - parent::__construct($id, $invalidBehavior); - $this->type = $type; - } - - public function getType() - { - return $this->type; - } - - public function getName(): ?string - { - return $this->name; - } -} diff --git a/lib/symfony/dependency-injection/Variable.php b/lib/symfony/dependency-injection/Variable.php deleted file mode 100644 index 21d33ebb2..000000000 --- a/lib/symfony/dependency-injection/Variable.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -/** - * Represents a variable. - * - * $var = new Variable('a'); - * - * will be dumped as - * - * $a - * - * by the PHP dumper. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class Variable -{ - private $name; - - public function __construct(string $name) - { - $this->name = $name; - } - - /** - * @return string - */ - public function __toString() - { - return $this->name; - } -} diff --git a/lib/symfony/dependency-injection/composer.json b/lib/symfony/dependency-injection/composer.json deleted file mode 100644 index cb891c790..000000000 --- a/lib/symfony/dependency-injection/composer.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "name": "symfony/dependency-injection", - "type": "library", - "description": "Allows you to standardize and centralize the way objects are constructed in your application", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "psr/container": "^1.1.1", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16", - "symfony/polyfill-php81": "^1.22", - "symfony/service-contracts": "^1.1.6|^2" - }, - "require-dev": { - "symfony/yaml": "^4.4.26|^5.0|^6.0", - "symfony/config": "^5.3|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0" - }, - "suggest": { - "symfony/yaml": "", - "symfony/config": "", - "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", - "symfony/expression-language": "For using expressions in service container configuration", - "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them" - }, - "conflict": { - "ext-psr": "<1.1|>=2", - "symfony/config": "<5.3", - "symfony/finder": "<4.4", - "symfony/proxy-manager-bridge": "<4.4", - "symfony/yaml": "<4.4.26" - }, - "provide": { - "psr/container-implementation": "1.0", - "symfony/service-implementation": "1.0|2.0" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\DependencyInjection\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/lib/symfony/deprecation-contracts/.gitignore b/lib/symfony/deprecation-contracts/.gitignore deleted file mode 100644 index c49a5d8df..000000000 --- a/lib/symfony/deprecation-contracts/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -vendor/ -composer.lock -phpunit.xml diff --git a/lib/symfony/deprecation-contracts/CHANGELOG.md b/lib/symfony/deprecation-contracts/CHANGELOG.md deleted file mode 100644 index 7932e2613..000000000 --- a/lib/symfony/deprecation-contracts/CHANGELOG.md +++ /dev/null @@ -1,5 +0,0 @@ -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/lib/symfony/deprecation-contracts/LICENSE b/lib/symfony/deprecation-contracts/LICENSE deleted file mode 100644 index 406242ff2..000000000 --- a/lib/symfony/deprecation-contracts/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -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/lib/symfony/deprecation-contracts/README.md b/lib/symfony/deprecation-contracts/README.md deleted file mode 100644 index 4957933a6..000000000 --- a/lib/symfony/deprecation-contracts/README.md +++ /dev/null @@ -1,26 +0,0 @@ -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/lib/symfony/deprecation-contracts/composer.json b/lib/symfony/deprecation-contracts/composer.json deleted file mode 100644 index cc7cc1237..000000000 --- a/lib/symfony/deprecation-contracts/composer.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "symfony/deprecation-contracts", - "type": "library", - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.1" - }, - "autoload": { - "files": [ - "function.php" - ] - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - } -} diff --git a/lib/symfony/deprecation-contracts/function.php b/lib/symfony/deprecation-contracts/function.php deleted file mode 100644 index d4371504a..000000000 --- a/lib/symfony/deprecation-contracts/function.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -if (!function_exists('trigger_deprecation')) { - /** - * Triggers a silenced deprecation notice. - * - * @param string $package The name of the Composer package that is triggering the deprecation - * @param string $version The version of the package that introduced the deprecation - * @param string $message The message of the deprecation - * @param mixed ...$args Values to insert in the message using printf() formatting - * - * @author Nicolas Grekas <p@tchwork.com> - */ - function trigger_deprecation(string $package, string $version, string $message, ...$args): void - { - @trigger_error(($package || $version ? "Since $package $version: " : '').($args ? vsprintf($message, $args) : $message), \E_USER_DEPRECATED); - } -} diff --git a/lib/symfony/dotenv/CHANGELOG.md b/lib/symfony/dotenv/CHANGELOG.md deleted file mode 100644 index 3cf07eecc..000000000 --- a/lib/symfony/dotenv/CHANGELOG.md +++ /dev/null @@ -1,40 +0,0 @@ -CHANGELOG -========= - -5.4 ---- - - * Add `dotenv:dump` command to compile the contents of the .env files into a PHP-optimized file called `.env.local.php` - * Add `debug:dotenv` command to list all dotenv files with variables and values - * Add `$overrideExistingVars` on `Dotenv::bootEnv()` and `Dotenv::loadEnv()` - -5.1.0 ------ - - * added `Dotenv::bootEnv()` to check for `.env.local.php` before calling `Dotenv::loadEnv()` - * added `Dotenv::setProdEnvs()` and `Dotenv::usePutenv()` - * made Dotenv's constructor accept `$envKey` and `$debugKey` arguments, to define - the name of the env vars that configure the env name and debug settings - * deprecated passing `$usePutenv` argument to Dotenv's constructor - -5.0.0 ------ - - * using `putenv()` is disabled by default - -4.3.0 ------ - - * deprecated use of `putenv()` by default. This feature will be opted-in with a constructor argument to `Dotenv` - -4.2.0 ------ - - * added `Dotenv::overload()` and `$overrideExistingVars` as optional parameter of `Dotenv::populate()` - * added `Dotenv::loadEnv()` to load a .env file and its corresponding .env.local, .env.$env and .env.$env.local files if they exist - -3.3.0 ------ - - * [BC BREAK] Since v3.3.7, the latest Dotenv files override the previous ones. Real env vars are not affected and are not overridden. - * added the component diff --git a/lib/symfony/dotenv/Command/DebugCommand.php b/lib/symfony/dotenv/Command/DebugCommand.php deleted file mode 100644 index 8ceb1fd48..000000000 --- a/lib/symfony/dotenv/Command/DebugCommand.php +++ /dev/null @@ -1,143 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Dotenv\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\Dotenv\Dotenv; - -/** - * A console command to debug current dotenv files with variables and values. - * - * @author Christopher Hertel <mail@christopher-hertel.de> - */ -final class DebugCommand extends Command -{ - protected static $defaultName = 'debug:dotenv'; - protected static $defaultDescription = 'Lists all dotenv files with variables and values'; - - private $kernelEnvironment; - private $projectDirectory; - - public function __construct(string $kernelEnvironment, string $projectDirectory) - { - $this->kernelEnvironment = $kernelEnvironment; - $this->projectDirectory = $projectDirectory; - - parent::__construct(); - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - $io->title('Dotenv Variables & Files'); - - if (!\array_key_exists('SYMFONY_DOTENV_VARS', $_SERVER)) { - $io->error('Dotenv component is not initialized.'); - - return 1; - } - - $envFiles = $this->getEnvFiles(); - $availableFiles = array_filter($envFiles, function (string $file) { - return is_file($this->getFilePath($file)); - }); - - if (\in_array('.env.local.php', $availableFiles, true)) { - $io->warning('Due to existing dump file (.env.local.php) all other dotenv files are skipped.'); - } - - if (is_file($this->getFilePath('.env')) && is_file($this->getFilePath('.env.dist'))) { - $io->warning('The file .env.dist gets skipped due to the existence of .env.'); - } - - $io->section('Scanned Files (in descending priority)'); - $io->listing(array_map(static function (string $envFile) use ($availableFiles) { - return \in_array($envFile, $availableFiles, true) - ? sprintf('<fg=green>✓</> %s', $envFile) - : sprintf('<fg=red>⨯</> %s', $envFile); - }, $envFiles)); - - $io->section('Variables'); - $io->table( - array_merge(['Variable', 'Value'], $availableFiles), - $this->getVariables($availableFiles) - ); - - $io->comment('Note real values might be different between web and CLI.'); - - return 0; - } - - private function getVariables(array $envFiles): array - { - $vars = explode(',', $_SERVER['SYMFONY_DOTENV_VARS'] ?? ''); - sort($vars); - - $output = []; - $fileValues = []; - foreach ($vars as $var) { - $realValue = $_SERVER[$var]; - $varDetails = [$var, $realValue]; - foreach ($envFiles as $envFile) { - $values = $fileValues[$envFile] ?? $fileValues[$envFile] = $this->loadValues($envFile); - - $varString = $values[$var] ?? '<fg=yellow>n/a</>'; - $shortenedVar = $this->getHelper('formatter')->truncate($varString, 30); - $varDetails[] = $varString === $realValue ? '<fg=green>'.$shortenedVar.'</>' : $shortenedVar; - } - - $output[] = $varDetails; - } - - return $output; - } - - private function getEnvFiles(): array - { - $files = [ - '.env.local.php', - sprintf('.env.%s.local', $this->kernelEnvironment), - sprintf('.env.%s', $this->kernelEnvironment), - ]; - - if ('test' !== $this->kernelEnvironment) { - $files[] = '.env.local'; - } - - if (!is_file($this->getFilePath('.env')) && is_file($this->getFilePath('.env.dist'))) { - $files[] = '.env.dist'; - } else { - $files[] = '.env'; - } - - return $files; - } - - private function getFilePath(string $file): string - { - return $this->projectDirectory.\DIRECTORY_SEPARATOR.$file; - } - - private function loadValues(string $file): array - { - $filePath = $this->getFilePath($file); - - if (str_ends_with($filePath, '.php')) { - return include $filePath; - } - - return (new Dotenv())->parse(file_get_contents($filePath)); - } -} diff --git a/lib/symfony/dotenv/Command/DotenvDumpCommand.php b/lib/symfony/dotenv/Command/DotenvDumpCommand.php deleted file mode 100644 index 44110543f..000000000 --- a/lib/symfony/dotenv/Command/DotenvDumpCommand.php +++ /dev/null @@ -1,123 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Dotenv\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\DependencyInjection\Attribute\Autoconfigure; -use Symfony\Component\Dotenv\Dotenv; - -/** - * A console command to compile .env files into a PHP-optimized file called .env.local.php. - * - * @internal - */ -#[Autoconfigure(bind: ['$projectDir' => '%kernel.project_dir%', '$defaultEnv' => '%kernel.environment%'])] -final class DotenvDumpCommand extends Command -{ - protected static $defaultName = 'dotenv:dump'; - protected static $defaultDescription = 'Compiles .env files to .env.local.php'; - - private $projectDir; - private $defaultEnv; - - public function __construct(string $projectDir, string $defaultEnv = null) - { - $this->projectDir = $projectDir; - $this->defaultEnv = $defaultEnv; - - parent::__construct(); - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('env', null === $this->defaultEnv ? InputArgument::REQUIRED : InputArgument::OPTIONAL, 'The application environment to dump .env files for - e.g. "prod".'), - ]) - ->addOption('empty', null, InputOption::VALUE_NONE, 'Ignore the content of .env files') - ->setHelp(<<<'EOT' -The <info>%command.name%</info> command compiles .env files into a PHP-optimized file called .env.local.php. - - <info>%command.full_name%</info> -EOT - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $config = []; - if (is_file($projectDir = $this->projectDir)) { - $config = ['dotenv_path' => basename($projectDir)]; - $projectDir = \dirname($projectDir); - } - - $composerFile = $projectDir.'/composer.json'; - $config += (is_file($composerFile) ? json_decode(file_get_contents($composerFile), true) : [])['extra']['runtime'] ?? []; - $dotenvPath = $projectDir.'/'.($config['dotenv_path'] ?? '.env'); - $env = $input->getArgument('env') ?? $this->defaultEnv; - $envKey = $config['env_var_name'] ?? 'APP_ENV'; - - if ($input->getOption('empty')) { - $vars = [$envKey => $env]; - } else { - $vars = $this->loadEnv($dotenvPath, $env, $config); - $env = $vars[$envKey]; - } - - $vars = var_export($vars, true); - $vars = <<<EOF -<?php - -// This file was generated by running "php bin/console dotenv:dump $env" - -return $vars; - -EOF; - file_put_contents($dotenvPath.'.local.php', $vars, \LOCK_EX); - - $output->writeln(sprintf('Successfully dumped .env files in <info>.env.local.php</> for the <info>%s</> environment.', $env)); - - return 0; - } - - private function loadEnv(string $dotenvPath, string $env, array $config): array - { - $dotenv = new Dotenv(); - $envKey = $config['env_var_name'] ?? 'APP_ENV'; - $testEnvs = $config['test_envs'] ?? ['test']; - - $globalsBackup = [$_SERVER, $_ENV]; - unset($_SERVER[$envKey]); - $_ENV = [$envKey => $env]; - $_SERVER['SYMFONY_DOTENV_VARS'] = implode(',', array_keys($_SERVER)); - - try { - $dotenv->loadEnv($dotenvPath, null, 'dev', $testEnvs); - unset($_ENV['SYMFONY_DOTENV_VARS']); - - return $_ENV; - } finally { - [$_SERVER, $_ENV] = $globalsBackup; - } - } -} diff --git a/lib/symfony/dotenv/Dotenv.php b/lib/symfony/dotenv/Dotenv.php deleted file mode 100644 index 2c76d52c8..000000000 --- a/lib/symfony/dotenv/Dotenv.php +++ /dev/null @@ -1,573 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Dotenv; - -use Symfony\Component\Dotenv\Exception\FormatException; -use Symfony\Component\Dotenv\Exception\FormatExceptionContext; -use Symfony\Component\Dotenv\Exception\PathException; -use Symfony\Component\Process\Exception\ExceptionInterface as ProcessException; -use Symfony\Component\Process\Process; - -/** - * Manages .env files. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Kévin Dunglas <dunglas@gmail.com> - */ -final class Dotenv -{ - public const VARNAME_REGEX = '(?i:[A-Z][A-Z0-9_]*+)'; - public const STATE_VARNAME = 0; - public const STATE_VALUE = 1; - - private $path; - private $cursor; - private $lineno; - private $data; - private $end; - private $values; - private $envKey; - private $debugKey; - private $prodEnvs = ['prod']; - private $usePutenv = false; - - /** - * @param string $envKey - */ - public function __construct($envKey = 'APP_ENV', string $debugKey = 'APP_DEBUG') - { - if (\in_array($envKey = (string) $envKey, ['1', ''], true)) { - trigger_deprecation('symfony/dotenv', '5.1', 'Passing a boolean to the constructor of "%s" is deprecated, use "Dotenv::usePutenv()".', __CLASS__); - $this->usePutenv = (bool) $envKey; - $envKey = 'APP_ENV'; - } - - $this->envKey = $envKey; - $this->debugKey = $debugKey; - } - - /** - * @return $this - */ - public function setProdEnvs(array $prodEnvs): self - { - $this->prodEnvs = $prodEnvs; - - return $this; - } - - /** - * @param bool $usePutenv If `putenv()` should be used to define environment variables or not. - * Beware that `putenv()` is not thread safe, that's why this setting defaults to false - * - * @return $this - */ - public function usePutenv(bool $usePutenv = true): self - { - $this->usePutenv = $usePutenv; - - return $this; - } - - /** - * Loads one or several .env files. - * - * @param string $path A file to load - * @param string[] ...$extraPaths A list of additional files to load - * - * @throws FormatException when a file has a syntax error - * @throws PathException when a file does not exist or is not readable - */ - public function load(string $path, string ...$extraPaths): void - { - $this->doLoad(false, \func_get_args()); - } - - /** - * Loads a .env file and the corresponding .env.local, .env.$env and .env.$env.local files if they exist. - * - * .env.local is always ignored in test env because tests should produce the same results for everyone. - * .env.dist is loaded when it exists and .env is not found. - * - * @param string $path A file to load - * @param string $envKey|null The name of the env vars that defines the app env - * @param string $defaultEnv The app env to use when none is defined - * @param array $testEnvs A list of app envs for which .env.local should be ignored - * - * @throws FormatException when a file has a syntax error - * @throws PathException when a file does not exist or is not readable - */ - public function loadEnv(string $path, string $envKey = null, string $defaultEnv = 'dev', array $testEnvs = ['test'], bool $overrideExistingVars = false): void - { - $k = $envKey ?? $this->envKey; - - if (is_file($path) || !is_file($p = "$path.dist")) { - $this->doLoad($overrideExistingVars, [$path]); - } else { - $this->doLoad($overrideExistingVars, [$p]); - } - - if (null === $env = $_SERVER[$k] ?? $_ENV[$k] ?? null) { - $this->populate([$k => $env = $defaultEnv], $overrideExistingVars); - } - - if (!\in_array($env, $testEnvs, true) && is_file($p = "$path.local")) { - $this->doLoad($overrideExistingVars, [$p]); - $env = $_SERVER[$k] ?? $_ENV[$k] ?? $env; - } - - if ('local' === $env) { - return; - } - - if (is_file($p = "$path.$env")) { - $this->doLoad($overrideExistingVars, [$p]); - } - - if (is_file($p = "$path.$env.local")) { - $this->doLoad($overrideExistingVars, [$p]); - } - } - - /** - * Loads env vars from .env.local.php if the file exists or from the other .env files otherwise. - * - * This method also configures the APP_DEBUG env var according to the current APP_ENV. - * - * See method loadEnv() for rules related to .env files. - */ - public function bootEnv(string $path, string $defaultEnv = 'dev', array $testEnvs = ['test'], bool $overrideExistingVars = false): void - { - $p = $path.'.local.php'; - $env = is_file($p) ? include $p : null; - $k = $this->envKey; - - if (\is_array($env) && ($overrideExistingVars || !isset($env[$k]) || ($_SERVER[$k] ?? $_ENV[$k] ?? $env[$k]) === $env[$k])) { - $this->populate($env, $overrideExistingVars); - } else { - $this->loadEnv($path, $k, $defaultEnv, $testEnvs, $overrideExistingVars); - } - - $_SERVER += $_ENV; - - $k = $this->debugKey; - $debug = $_SERVER[$k] ?? !\in_array($_SERVER[$this->envKey], $this->prodEnvs, true); - $_SERVER[$k] = $_ENV[$k] = (int) $debug || (!\is_bool($debug) && filter_var($debug, \FILTER_VALIDATE_BOOLEAN)) ? '1' : '0'; - } - - /** - * Loads one or several .env files and enables override existing vars. - * - * @param string $path A file to load - * @param string[] ...$extraPaths A list of additional files to load - * - * @throws FormatException when a file has a syntax error - * @throws PathException when a file does not exist or is not readable - */ - public function overload(string $path, string ...$extraPaths): void - { - $this->doLoad(true, \func_get_args()); - } - - /** - * Sets values as environment variables (via putenv, $_ENV, and $_SERVER). - * - * @param array $values An array of env variables - * @param bool $overrideExistingVars true when existing environment variables must be overridden - */ - public function populate(array $values, bool $overrideExistingVars = false): void - { - $updateLoadedVars = false; - $loadedVars = array_flip(explode(',', $_SERVER['SYMFONY_DOTENV_VARS'] ?? $_ENV['SYMFONY_DOTENV_VARS'] ?? '')); - - foreach ($values as $name => $value) { - $notHttpName = 0 !== strpos($name, 'HTTP_'); - if (isset($_SERVER[$name]) && $notHttpName && !isset($_ENV[$name])) { - $_ENV[$name] = $_SERVER[$name]; - } - - // don't check existence with getenv() because of thread safety issues - if (!isset($loadedVars[$name]) && !$overrideExistingVars && isset($_ENV[$name])) { - continue; - } - - if ($this->usePutenv) { - putenv("$name=$value"); - } - - $_ENV[$name] = $value; - if ($notHttpName) { - $_SERVER[$name] = $value; - } - - if (!isset($loadedVars[$name])) { - $loadedVars[$name] = $updateLoadedVars = true; - } - } - - if ($updateLoadedVars) { - unset($loadedVars['']); - $loadedVars = implode(',', array_keys($loadedVars)); - $_ENV['SYMFONY_DOTENV_VARS'] = $_SERVER['SYMFONY_DOTENV_VARS'] = $loadedVars; - - if ($this->usePutenv) { - putenv('SYMFONY_DOTENV_VARS='.$loadedVars); - } - } - } - - /** - * Parses the contents of an .env file. - * - * @param string $data The data to be parsed - * @param string $path The original file name where data where stored (used for more meaningful error messages) - * - * @throws FormatException when a file has a syntax error - */ - public function parse(string $data, string $path = '.env'): array - { - $this->path = $path; - $this->data = str_replace(["\r\n", "\r"], "\n", $data); - $this->lineno = 1; - $this->cursor = 0; - $this->end = \strlen($this->data); - $state = self::STATE_VARNAME; - $this->values = []; - $name = ''; - - $this->skipEmptyLines(); - - while ($this->cursor < $this->end) { - switch ($state) { - case self::STATE_VARNAME: - $name = $this->lexVarname(); - $state = self::STATE_VALUE; - break; - - case self::STATE_VALUE: - $this->values[$name] = $this->lexValue(); - $state = self::STATE_VARNAME; - break; - } - } - - if (self::STATE_VALUE === $state) { - $this->values[$name] = ''; - } - - try { - return $this->values; - } finally { - $this->values = []; - $this->data = null; - $this->path = null; - } - } - - private function lexVarname(): string - { - // var name + optional export - if (!preg_match('/(export[ \t]++)?('.self::VARNAME_REGEX.')/A', $this->data, $matches, 0, $this->cursor)) { - throw $this->createFormatException('Invalid character in variable name'); - } - $this->moveCursor($matches[0]); - - if ($this->cursor === $this->end || "\n" === $this->data[$this->cursor] || '#' === $this->data[$this->cursor]) { - if ($matches[1]) { - throw $this->createFormatException('Unable to unset an environment variable'); - } - - throw $this->createFormatException('Missing = in the environment variable declaration'); - } - - if (' ' === $this->data[$this->cursor] || "\t" === $this->data[$this->cursor]) { - throw $this->createFormatException('Whitespace characters are not supported after the variable name'); - } - - if ('=' !== $this->data[$this->cursor]) { - throw $this->createFormatException('Missing = in the environment variable declaration'); - } - ++$this->cursor; - - return $matches[2]; - } - - private function lexValue(): string - { - if (preg_match('/[ \t]*+(?:#.*)?$/Am', $this->data, $matches, 0, $this->cursor)) { - $this->moveCursor($matches[0]); - $this->skipEmptyLines(); - - return ''; - } - - if (' ' === $this->data[$this->cursor] || "\t" === $this->data[$this->cursor]) { - throw $this->createFormatException('Whitespace are not supported before the value'); - } - - $loadedVars = array_flip(explode(',', $_SERVER['SYMFONY_DOTENV_VARS'] ?? ($_ENV['SYMFONY_DOTENV_VARS'] ?? ''))); - unset($loadedVars['']); - $v = ''; - - do { - if ("'" === $this->data[$this->cursor]) { - $len = 0; - - do { - if ($this->cursor + ++$len === $this->end) { - $this->cursor += $len; - - throw $this->createFormatException('Missing quote to end the value'); - } - } while ("'" !== $this->data[$this->cursor + $len]); - - $v .= substr($this->data, 1 + $this->cursor, $len - 1); - $this->cursor += 1 + $len; - } elseif ('"' === $this->data[$this->cursor]) { - $value = ''; - - if (++$this->cursor === $this->end) { - throw $this->createFormatException('Missing quote to end the value'); - } - - while ('"' !== $this->data[$this->cursor] || ('\\' === $this->data[$this->cursor - 1] && '\\' !== $this->data[$this->cursor - 2])) { - $value .= $this->data[$this->cursor]; - ++$this->cursor; - - if ($this->cursor === $this->end) { - throw $this->createFormatException('Missing quote to end the value'); - } - } - ++$this->cursor; - $value = str_replace(['\\"', '\r', '\n'], ['"', "\r", "\n"], $value); - $resolvedValue = $value; - $resolvedValue = $this->resolveVariables($resolvedValue, $loadedVars); - $resolvedValue = $this->resolveCommands($resolvedValue, $loadedVars); - $resolvedValue = str_replace('\\\\', '\\', $resolvedValue); - $v .= $resolvedValue; - } else { - $value = ''; - $prevChr = $this->data[$this->cursor - 1]; - while ($this->cursor < $this->end && !\in_array($this->data[$this->cursor], ["\n", '"', "'"], true) && !((' ' === $prevChr || "\t" === $prevChr) && '#' === $this->data[$this->cursor])) { - if ('\\' === $this->data[$this->cursor] && isset($this->data[$this->cursor + 1]) && ('"' === $this->data[$this->cursor + 1] || "'" === $this->data[$this->cursor + 1])) { - ++$this->cursor; - } - - $value .= $prevChr = $this->data[$this->cursor]; - - if ('$' === $this->data[$this->cursor] && isset($this->data[$this->cursor + 1]) && '(' === $this->data[$this->cursor + 1]) { - ++$this->cursor; - $value .= '('.$this->lexNestedExpression().')'; - } - - ++$this->cursor; - } - $value = rtrim($value); - $resolvedValue = $value; - $resolvedValue = $this->resolveVariables($resolvedValue, $loadedVars); - $resolvedValue = $this->resolveCommands($resolvedValue, $loadedVars); - $resolvedValue = str_replace('\\\\', '\\', $resolvedValue); - - if ($resolvedValue === $value && preg_match('/\s+/', $value)) { - throw $this->createFormatException('A value containing spaces must be surrounded by quotes'); - } - - $v .= $resolvedValue; - - if ($this->cursor < $this->end && '#' === $this->data[$this->cursor]) { - break; - } - } - } while ($this->cursor < $this->end && "\n" !== $this->data[$this->cursor]); - - $this->skipEmptyLines(); - - return $v; - } - - private function lexNestedExpression(): string - { - ++$this->cursor; - $value = ''; - - while ("\n" !== $this->data[$this->cursor] && ')' !== $this->data[$this->cursor]) { - $value .= $this->data[$this->cursor]; - - if ('(' === $this->data[$this->cursor]) { - $value .= $this->lexNestedExpression().')'; - } - - ++$this->cursor; - - if ($this->cursor === $this->end) { - throw $this->createFormatException('Missing closing parenthesis.'); - } - } - - if ("\n" === $this->data[$this->cursor]) { - throw $this->createFormatException('Missing closing parenthesis.'); - } - - return $value; - } - - private function skipEmptyLines() - { - if (preg_match('/(?:\s*+(?:#[^\n]*+)?+)++/A', $this->data, $match, 0, $this->cursor)) { - $this->moveCursor($match[0]); - } - } - - private function resolveCommands(string $value, array $loadedVars): string - { - if (false === strpos($value, '$')) { - return $value; - } - - $regex = '/ - (\\\\)? # escaped with a backslash? - \$ - (?<cmd> - \( # require opening parenthesis - ([^()]|\g<cmd>)+ # allow any number of non-parens, or balanced parens (by nesting the <cmd> expression recursively) - \) # require closing paren - ) - /x'; - - return preg_replace_callback($regex, function ($matches) use ($loadedVars) { - if ('\\' === $matches[1]) { - return substr($matches[0], 1); - } - - if ('\\' === \DIRECTORY_SEPARATOR) { - throw new \LogicException('Resolving commands is not supported on Windows.'); - } - - if (!class_exists(Process::class)) { - throw new \LogicException('Resolving commands requires the Symfony Process component.'); - } - - $process = method_exists(Process::class, 'fromShellCommandline') ? Process::fromShellCommandline('echo '.$matches[0]) : new Process('echo '.$matches[0]); - - if (!method_exists(Process::class, 'fromShellCommandline') && method_exists(Process::class, 'inheritEnvironmentVariables')) { - // Symfony 3.4 does not inherit env vars by default: - $process->inheritEnvironmentVariables(); - } - - $env = []; - foreach ($this->values as $name => $value) { - if (isset($loadedVars[$name]) || (!isset($_ENV[$name]) && !(isset($_SERVER[$name]) && 0 !== strpos($name, 'HTTP_')))) { - $env[$name] = $value; - } - } - $process->setEnv($env); - - try { - $process->mustRun(); - } catch (ProcessException $e) { - throw $this->createFormatException(sprintf('Issue expanding a command (%s)', $process->getErrorOutput())); - } - - return preg_replace('/[\r\n]+$/', '', $process->getOutput()); - }, $value); - } - - private function resolveVariables(string $value, array $loadedVars): string - { - if (false === strpos($value, '$')) { - return $value; - } - - $regex = '/ - (?<!\\\\) - (?P<backslashes>\\\\*) # escaped with a backslash? - \$ - (?!\() # no opening parenthesis - (?P<opening_brace>\{)? # optional brace - (?P<name>'.self::VARNAME_REGEX.')? # var name - (?P<default_value>:[-=][^\}]++)? # optional default value - (?P<closing_brace>\})? # optional closing brace - /x'; - - $value = preg_replace_callback($regex, function ($matches) use ($loadedVars) { - // odd number of backslashes means the $ character is escaped - if (1 === \strlen($matches['backslashes']) % 2) { - return substr($matches[0], 1); - } - - // unescaped $ not followed by variable name - if (!isset($matches['name'])) { - return $matches[0]; - } - - if ('{' === $matches['opening_brace'] && !isset($matches['closing_brace'])) { - throw $this->createFormatException('Unclosed braces on variable expansion'); - } - - $name = $matches['name']; - if (isset($loadedVars[$name]) && isset($this->values[$name])) { - $value = $this->values[$name]; - } elseif (isset($_ENV[$name])) { - $value = $_ENV[$name]; - } elseif (isset($_SERVER[$name]) && 0 !== strpos($name, 'HTTP_')) { - $value = $_SERVER[$name]; - } elseif (isset($this->values[$name])) { - $value = $this->values[$name]; - } else { - $value = (string) getenv($name); - } - - if ('' === $value && isset($matches['default_value']) && '' !== $matches['default_value']) { - $unsupportedChars = strpbrk($matches['default_value'], '\'"{$'); - if (false !== $unsupportedChars) { - throw $this->createFormatException(sprintf('Unsupported character "%s" found in the default value of variable "$%s".', $unsupportedChars[0], $name)); - } - - $value = substr($matches['default_value'], 2); - - if ('=' === $matches['default_value'][1]) { - $this->values[$name] = $value; - } - } - - if (!$matches['opening_brace'] && isset($matches['closing_brace'])) { - $value .= '}'; - } - - return $matches['backslashes'].$value; - }, $value); - - return $value; - } - - private function moveCursor(string $text) - { - $this->cursor += \strlen($text); - $this->lineno += substr_count($text, "\n"); - } - - private function createFormatException(string $message): FormatException - { - return new FormatException($message, new FormatExceptionContext($this->data, $this->path, $this->lineno, $this->cursor)); - } - - private function doLoad(bool $overrideExistingVars, array $paths): void - { - foreach ($paths as $path) { - if (!is_readable($path) || is_dir($path)) { - throw new PathException($path); - } - - $this->populate($this->parse(file_get_contents($path), $path), $overrideExistingVars); - } - } -} diff --git a/lib/symfony/dotenv/Exception/ExceptionInterface.php b/lib/symfony/dotenv/Exception/ExceptionInterface.php deleted file mode 100644 index 140a93f96..000000000 --- a/lib/symfony/dotenv/Exception/ExceptionInterface.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Dotenv\Exception; - -/** - * Interface for exceptions. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface ExceptionInterface extends \Throwable -{ -} diff --git a/lib/symfony/dotenv/Exception/FormatException.php b/lib/symfony/dotenv/Exception/FormatException.php deleted file mode 100644 index 3ac77e592..000000000 --- a/lib/symfony/dotenv/Exception/FormatException.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Dotenv\Exception; - -/** - * Thrown when a file has a syntax error. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class FormatException extends \LogicException implements ExceptionInterface -{ - private $context; - - public function __construct(string $message, FormatExceptionContext $context, int $code = 0, \Throwable $previous = null) - { - $this->context = $context; - - parent::__construct(sprintf("%s in \"%s\" at line %d.\n%s", $message, $context->getPath(), $context->getLineno(), $context->getDetails()), $code, $previous); - } - - public function getContext(): FormatExceptionContext - { - return $this->context; - } -} diff --git a/lib/symfony/dotenv/Exception/FormatExceptionContext.php b/lib/symfony/dotenv/Exception/FormatExceptionContext.php deleted file mode 100644 index 96d902fc8..000000000 --- a/lib/symfony/dotenv/Exception/FormatExceptionContext.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Dotenv\Exception; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -final class FormatExceptionContext -{ - private $data; - private $path; - private $lineno; - private $cursor; - - public function __construct(string $data, string $path, int $lineno, int $cursor) - { - $this->data = $data; - $this->path = $path; - $this->lineno = $lineno; - $this->cursor = $cursor; - } - - public function getPath(): string - { - return $this->path; - } - - public function getLineno(): int - { - return $this->lineno; - } - - public function getDetails(): string - { - $before = str_replace("\n", '\n', substr($this->data, max(0, $this->cursor - 20), min(20, $this->cursor))); - $after = str_replace("\n", '\n', substr($this->data, $this->cursor, 20)); - - return '...'.$before.$after."...\n".str_repeat(' ', \strlen($before) + 2).'^ line '.$this->lineno.' offset '.$this->cursor; - } -} diff --git a/lib/symfony/dotenv/Exception/PathException.php b/lib/symfony/dotenv/Exception/PathException.php deleted file mode 100644 index 4a4d71722..000000000 --- a/lib/symfony/dotenv/Exception/PathException.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Dotenv\Exception; - -/** - * Thrown when a file does not exist or is not readable. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class PathException extends \RuntimeException implements ExceptionInterface -{ - public function __construct(string $path, int $code = 0, \Throwable $previous = null) - { - parent::__construct(sprintf('Unable to read the "%s" environment file.', $path), $code, $previous); - } -} diff --git a/lib/symfony/dotenv/LICENSE b/lib/symfony/dotenv/LICENSE deleted file mode 100644 index f2345234a..000000000 --- a/lib/symfony/dotenv/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2016-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/lib/symfony/dotenv/README.md b/lib/symfony/dotenv/README.md deleted file mode 100644 index 08c90fcc8..000000000 --- a/lib/symfony/dotenv/README.md +++ /dev/null @@ -1,36 +0,0 @@ -Dotenv Component -================ - -Symfony Dotenv parses `.env` files to make environment variables stored in them -accessible via `$_SERVER` or `$_ENV`. - -Getting Started ---------------- - -``` -$ composer require symfony/dotenv -``` - -```php -use Symfony\Component\Dotenv\Dotenv; - -$dotenv = new Dotenv(); -$dotenv->load(__DIR__.'/.env'); - -// you can also load several files -$dotenv->load(__DIR__.'/.env', __DIR__.'/.env.dev'); - -// overwrites existing env variables -$dotenv->overload(__DIR__.'/.env'); - -// loads .env, .env.local, and .env.$APP_ENV.local or .env.$APP_ENV -$dotenv->loadEnv(__DIR__.'/.env'); -``` - -Resources ---------- - - * [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/lib/symfony/dotenv/composer.json b/lib/symfony/dotenv/composer.json deleted file mode 100644 index bec034f87..000000000 --- a/lib/symfony/dotenv/composer.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "symfony/dotenv", - "type": "library", - "description": "Registers environment variables from a .env file", - "keywords": ["environment", "env", "dotenv"], - "homepage": "https://symfony.com", - "license" : "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3" - }, - "require-dev": { - "symfony/console": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\Dotenv\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/lib/symfony/error-handler/BufferingLogger.php b/lib/symfony/error-handler/BufferingLogger.php deleted file mode 100644 index cfd55c61f..000000000 --- a/lib/symfony/error-handler/BufferingLogger.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler; - -use Psr\Log\AbstractLogger; - -/** - * A buffering logger that stacks logs for later. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class BufferingLogger extends AbstractLogger -{ - private $logs = []; - - public function log($level, $message, array $context = []): void - { - $this->logs[] = [$level, $message, $context]; - } - - public function cleanLogs(): array - { - $logs = $this->logs; - $this->logs = []; - - return $logs; - } - - /** - * @return array - */ - public function __sleep() - { - throw new \BadMethodCallException('Cannot serialize '.__CLASS__); - } - - public function __wakeup() - { - throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); - } - - public function __destruct() - { - foreach ($this->logs as [$level, $message, $context]) { - if (false !== strpos($message, '{')) { - foreach ($context as $key => $val) { - if (null === $val || \is_scalar($val) || (\is_object($val) && \is_callable([$val, '__toString']))) { - $message = str_replace("{{$key}}", $val, $message); - } elseif ($val instanceof \DateTimeInterface) { - $message = str_replace("{{$key}}", $val->format(\DateTime::RFC3339), $message); - } elseif (\is_object($val)) { - $message = str_replace("{{$key}}", '[object '.\get_class($val).']', $message); - } else { - $message = str_replace("{{$key}}", '['.\gettype($val).']', $message); - } - } - } - - error_log(sprintf('%s [%s] %s', date(\DateTime::RFC3339), $level, $message)); - } - } -} diff --git a/lib/symfony/error-handler/CHANGELOG.md b/lib/symfony/error-handler/CHANGELOG.md deleted file mode 100644 index 2976566a1..000000000 --- a/lib/symfony/error-handler/CHANGELOG.md +++ /dev/null @@ -1,24 +0,0 @@ -CHANGELOG -========= - -5.4 ---- - - * Make `DebugClassLoader` trigger deprecation notices on missing return types - * Add `SYMFONY_PATCH_TYPE_DECLARATIONS='force=2'` mode to `DebugClassLoader` to turn annotations into native return types - -5.2.0 ------ - - * added the ability to set `HtmlErrorRenderer::$template` to a custom template to render when not in debug mode. - -5.1.0 ------ - - * The `HtmlErrorRenderer` and `SerializerErrorRenderer` add `X-Debug-Exception` and `X-Debug-Exception-File` headers in debug mode. - -4.4.0 ------ - - * added the component - * added `ErrorHandler::call()` method utility to turn any PHP error into `\ErrorException` diff --git a/lib/symfony/error-handler/Debug.php b/lib/symfony/error-handler/Debug.php deleted file mode 100644 index 343a35a77..000000000 --- a/lib/symfony/error-handler/Debug.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler; - -/** - * Registers all the debug tools. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Debug -{ - public static function enable(): ErrorHandler - { - error_reporting(-1); - - if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { - ini_set('display_errors', 0); - } elseif (!filter_var(\ini_get('log_errors'), \FILTER_VALIDATE_BOOLEAN) || \ini_get('error_log')) { - // CLI - display errors only if they're not already logged to STDERR - ini_set('display_errors', 1); - } - - @ini_set('zend.assertions', 1); - ini_set('assert.active', 1); - ini_set('assert.warning', 0); - ini_set('assert.exception', 1); - - DebugClassLoader::enable(); - - return ErrorHandler::register(new ErrorHandler(new BufferingLogger(), true)); - } -} diff --git a/lib/symfony/error-handler/DebugClassLoader.php b/lib/symfony/error-handler/DebugClassLoader.php deleted file mode 100644 index 6e4adeab0..000000000 --- a/lib/symfony/error-handler/DebugClassLoader.php +++ /dev/null @@ -1,1211 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler; - -use Composer\InstalledVersions; -use Doctrine\Common\Persistence\Proxy as LegacyProxy; -use Doctrine\Persistence\Proxy; -use Mockery\MockInterface; -use Phake\IMock; -use PHPUnit\Framework\MockObject\Matcher\StatelessInvocation; -use PHPUnit\Framework\MockObject\MockObject; -use Prophecy\Prophecy\ProphecySubjectInterface; -use ProxyManager\Proxy\ProxyInterface; -use Symfony\Component\ErrorHandler\Internal\TentativeTypes; - -/** - * Autoloader checking if the class is really defined in the file found. - * - * The ClassLoader will wrap all registered autoloaders - * and will throw an exception if a file is found but does - * not declare the class. - * - * It can also patch classes to turn docblocks into actual return types. - * This behavior is controlled by the SYMFONY_PATCH_TYPE_DECLARATIONS env var, - * which is a url-encoded array with the follow parameters: - * - "force": any value enables deprecation notices - can be any of: - * - "phpdoc" to patch only docblock annotations - * - "2" to add all possible return types - * - "1" to add return types but only to tests/final/internal/private methods - * - "php": the target version of PHP - e.g. "7.1" doesn't generate "object" types - * - "deprecations": "1" to trigger a deprecation notice when a child class misses a - * return type while the parent declares an "@return" annotation - * - * Note that patching doesn't care about any coding style so you'd better to run - * php-cs-fixer after, with rules "phpdoc_trim_consecutive_blank_line_separation" - * and "no_superfluous_phpdoc_tags" enabled typically. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Christophe Coevoet <stof@notk.org> - * @author Nicolas Grekas <p@tchwork.com> - * @author Guilhem Niot <guilhem.niot@gmail.com> - */ -class DebugClassLoader -{ - private const SPECIAL_RETURN_TYPES = [ - 'void' => 'void', - 'null' => 'null', - 'resource' => 'resource', - 'boolean' => 'bool', - 'true' => 'bool', - 'false' => 'false', - 'integer' => 'int', - 'array' => 'array', - 'bool' => 'bool', - 'callable' => 'callable', - 'float' => 'float', - 'int' => 'int', - 'iterable' => 'iterable', - 'object' => 'object', - 'string' => 'string', - 'self' => 'self', - 'parent' => 'parent', - 'mixed' => 'mixed', - 'static' => 'static', - '$this' => 'static', - 'list' => 'array', - 'class-string' => 'string', - ]; - - private const BUILTIN_RETURN_TYPES = [ - 'void' => true, - 'array' => true, - 'false' => true, - 'bool' => true, - 'callable' => true, - 'float' => true, - 'int' => true, - 'iterable' => true, - 'object' => true, - 'string' => true, - 'self' => true, - 'parent' => true, - 'mixed' => true, - 'static' => true, - ]; - - private const MAGIC_METHODS = [ - '__isset' => 'bool', - '__sleep' => 'array', - '__toString' => 'string', - '__debugInfo' => 'array', - '__serialize' => 'array', - ]; - - private $classLoader; - private $isFinder; - private $loaded = []; - private $patchTypes; - - private static $caseCheck; - private static $checkedClasses = []; - private static $final = []; - private static $finalMethods = []; - private static $deprecated = []; - private static $internal = []; - private static $internalMethods = []; - private static $annotatedParameters = []; - private static $darwinCache = ['/' => ['/', []]]; - private static $method = []; - private static $returnTypes = []; - private static $methodTraits = []; - private static $fileOffsets = []; - - public function __construct(callable $classLoader) - { - $this->classLoader = $classLoader; - $this->isFinder = \is_array($classLoader) && method_exists($classLoader[0], 'findFile'); - parse_str(getenv('SYMFONY_PATCH_TYPE_DECLARATIONS') ?: '', $this->patchTypes); - $this->patchTypes += [ - 'force' => null, - 'php' => \PHP_MAJOR_VERSION.'.'.\PHP_MINOR_VERSION, - 'deprecations' => \PHP_VERSION_ID >= 70400, - ]; - - if ('phpdoc' === $this->patchTypes['force']) { - $this->patchTypes['force'] = 'docblock'; - } - - if (!isset(self::$caseCheck)) { - $file = is_file(__FILE__) ? __FILE__ : rtrim(realpath('.'), \DIRECTORY_SEPARATOR); - $i = strrpos($file, \DIRECTORY_SEPARATOR); - $dir = substr($file, 0, 1 + $i); - $file = substr($file, 1 + $i); - $test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file); - $test = realpath($dir.$test); - - if (false === $test || false === $i) { - // filesystem is case sensitive - self::$caseCheck = 0; - } elseif (substr($test, -\strlen($file)) === $file) { - // filesystem is case insensitive and realpath() normalizes the case of characters - self::$caseCheck = 1; - } elseif ('Darwin' === \PHP_OS_FAMILY) { - // on MacOSX, HFS+ is case insensitive but realpath() doesn't normalize the case of characters - self::$caseCheck = 2; - } else { - // filesystem case checks failed, fallback to disabling them - self::$caseCheck = 0; - } - } - } - - public function getClassLoader(): callable - { - return $this->classLoader; - } - - /** - * Wraps all autoloaders. - */ - public static function enable(): void - { - // Ensures we don't hit https://bugs.php.net/42098 - class_exists(\Symfony\Component\ErrorHandler\ErrorHandler::class); - class_exists(\Psr\Log\LogLevel::class); - - if (!\is_array($functions = spl_autoload_functions())) { - return; - } - - foreach ($functions as $function) { - spl_autoload_unregister($function); - } - - foreach ($functions as $function) { - if (!\is_array($function) || !$function[0] instanceof self) { - $function = [new static($function), 'loadClass']; - } - - spl_autoload_register($function); - } - } - - /** - * Disables the wrapping. - */ - public static function disable(): void - { - if (!\is_array($functions = spl_autoload_functions())) { - return; - } - - foreach ($functions as $function) { - spl_autoload_unregister($function); - } - - foreach ($functions as $function) { - if (\is_array($function) && $function[0] instanceof self) { - $function = $function[0]->getClassLoader(); - } - - spl_autoload_register($function); - } - } - - public static function checkClasses(): bool - { - if (!\is_array($functions = spl_autoload_functions())) { - return false; - } - - $loader = null; - - foreach ($functions as $function) { - if (\is_array($function) && $function[0] instanceof self) { - $loader = $function[0]; - break; - } - } - - if (null === $loader) { - return false; - } - - static $offsets = [ - 'get_declared_interfaces' => 0, - 'get_declared_traits' => 0, - 'get_declared_classes' => 0, - ]; - - foreach ($offsets as $getSymbols => $i) { - $symbols = $getSymbols(); - - for (; $i < \count($symbols); ++$i) { - if (!is_subclass_of($symbols[$i], MockObject::class) - && !is_subclass_of($symbols[$i], ProphecySubjectInterface::class) - && !is_subclass_of($symbols[$i], Proxy::class) - && !is_subclass_of($symbols[$i], ProxyInterface::class) - && !is_subclass_of($symbols[$i], LegacyProxy::class) - && !is_subclass_of($symbols[$i], MockInterface::class) - && !is_subclass_of($symbols[$i], IMock::class) - ) { - $loader->checkClass($symbols[$i]); - } - } - - $offsets[$getSymbols] = $i; - } - - return true; - } - - public function findFile(string $class): ?string - { - return $this->isFinder ? ($this->classLoader[0]->findFile($class) ?: null) : null; - } - - /** - * Loads the given class or interface. - * - * @throws \RuntimeException - */ - public function loadClass(string $class): void - { - $e = error_reporting(error_reporting() | \E_PARSE | \E_ERROR | \E_CORE_ERROR | \E_COMPILE_ERROR); - - try { - if ($this->isFinder && !isset($this->loaded[$class])) { - $this->loaded[$class] = true; - if (!$file = $this->classLoader[0]->findFile($class) ?: '') { - // no-op - } elseif (\function_exists('opcache_is_script_cached') && @opcache_is_script_cached($file)) { - include $file; - - return; - } elseif (false === include $file) { - return; - } - } else { - ($this->classLoader)($class); - $file = ''; - } - } finally { - error_reporting($e); - } - - $this->checkClass($class, $file); - } - - private function checkClass(string $class, string $file = null): void - { - $exists = null === $file || class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false); - - if (null !== $file && $class && '\\' === $class[0]) { - $class = substr($class, 1); - } - - if ($exists) { - if (isset(self::$checkedClasses[$class])) { - return; - } - self::$checkedClasses[$class] = true; - - $refl = new \ReflectionClass($class); - if (null === $file && $refl->isInternal()) { - return; - } - $name = $refl->getName(); - - if ($name !== $class && 0 === strcasecmp($name, $class)) { - throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: "%s" vs "%s".', $class, $name)); - } - - $deprecations = $this->checkAnnotations($refl, $name); - - foreach ($deprecations as $message) { - @trigger_error($message, \E_USER_DEPRECATED); - } - } - - if (!$file) { - return; - } - - if (!$exists) { - if (false !== strpos($class, '/')) { - throw new \RuntimeException(sprintf('Trying to autoload a class with an invalid name "%s". Be careful that the namespace separator is "\" in PHP, not "/".', $class)); - } - - throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file)); - } - - if (self::$caseCheck && $message = $this->checkCase($refl, $file, $class)) { - throw new \RuntimeException(sprintf('Case mismatch between class and real file names: "%s" vs "%s" in "%s".', $message[0], $message[1], $message[2])); - } - } - - public function checkAnnotations(\ReflectionClass $refl, string $class): array - { - if ( - 'Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerForV7' === $class - || 'Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerForV6' === $class - ) { - return []; - } - $deprecations = []; - - $className = false !== strpos($class, "@anonymous\0") ? (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous' : $class; - - // Don't trigger deprecations for classes in the same vendor - if ($class !== $className) { - $vendor = preg_match('/^namespace ([^;\\\\\s]++)[;\\\\]/m', @file_get_contents($refl->getFileName()), $vendor) ? $vendor[1].'\\' : ''; - $vendorLen = \strlen($vendor); - } elseif (2 > $vendorLen = 1 + (strpos($class, '\\') ?: strpos($class, '_'))) { - $vendorLen = 0; - $vendor = ''; - } else { - $vendor = str_replace('_', '\\', substr($class, 0, $vendorLen)); - } - - $parent = get_parent_class($class) ?: null; - self::$returnTypes[$class] = []; - $classIsTemplate = false; - - // Detect annotations on the class - if ($doc = $this->parsePhpDoc($refl)) { - $classIsTemplate = isset($doc['template']); - - foreach (['final', 'deprecated', 'internal'] as $annotation) { - if (null !== $description = $doc[$annotation][0] ?? null) { - self::${$annotation}[$class] = '' !== $description ? ' '.$description.(preg_match('/[.!]$/', $description) ? '' : '.') : '.'; - } - } - - if ($refl->isInterface() && isset($doc['method'])) { - foreach ($doc['method'] as $name => [$static, $returnType, $signature, $description]) { - self::$method[$class][] = [$class, $static, $returnType, $name.$signature, $description]; - - if ('' !== $returnType) { - $this->setReturnType($returnType, $refl->name, $name, $refl->getFileName(), $parent); - } - } - } - } - - $parentAndOwnInterfaces = $this->getOwnInterfaces($class, $parent); - if ($parent) { - $parentAndOwnInterfaces[$parent] = $parent; - - if (!isset(self::$checkedClasses[$parent])) { - $this->checkClass($parent); - } - - if (isset(self::$final[$parent])) { - $deprecations[] = sprintf('The "%s" class is considered final%s It may change without further notice as of its next major version. You should not extend it from "%s".', $parent, self::$final[$parent], $className); - } - } - - // Detect if the parent is annotated - foreach ($parentAndOwnInterfaces + class_uses($class, false) as $use) { - if (!isset(self::$checkedClasses[$use])) { - $this->checkClass($use); - } - if (isset(self::$deprecated[$use]) && strncmp($vendor, str_replace('_', '\\', $use), $vendorLen) && !isset(self::$deprecated[$class])) { - $type = class_exists($class, false) ? 'class' : (interface_exists($class, false) ? 'interface' : 'trait'); - $verb = class_exists($use, false) || interface_exists($class, false) ? 'extends' : (interface_exists($use, false) ? 'implements' : 'uses'); - - $deprecations[] = sprintf('The "%s" %s %s "%s" that is deprecated%s', $className, $type, $verb, $use, self::$deprecated[$use]); - } - if (isset(self::$internal[$use]) && strncmp($vendor, str_replace('_', '\\', $use), $vendorLen)) { - $deprecations[] = sprintf('The "%s" %s is considered internal%s It may change without further notice. You should not use it from "%s".', $use, class_exists($use, false) ? 'class' : (interface_exists($use, false) ? 'interface' : 'trait'), self::$internal[$use], $className); - } - if (isset(self::$method[$use])) { - if ($refl->isAbstract()) { - if (isset(self::$method[$class])) { - self::$method[$class] = array_merge(self::$method[$class], self::$method[$use]); - } else { - self::$method[$class] = self::$method[$use]; - } - } elseif (!$refl->isInterface()) { - if (!strncmp($vendor, str_replace('_', '\\', $use), $vendorLen) - && 0 === strpos($className, 'Symfony\\') - && (!class_exists(InstalledVersions::class) - || 'symfony/symfony' !== InstalledVersions::getRootPackage()['name']) - ) { - // skip "same vendor" @method deprecations for Symfony\* classes unless symfony/symfony is being tested - continue; - } - $hasCall = $refl->hasMethod('__call'); - $hasStaticCall = $refl->hasMethod('__callStatic'); - foreach (self::$method[$use] as [$interface, $static, $returnType, $name, $description]) { - if ($static ? $hasStaticCall : $hasCall) { - continue; - } - $realName = substr($name, 0, strpos($name, '(')); - if (!$refl->hasMethod($realName) || !($methodRefl = $refl->getMethod($realName))->isPublic() || ($static && !$methodRefl->isStatic()) || (!$static && $methodRefl->isStatic())) { - $deprecations[] = sprintf('Class "%s" should implement method "%s::%s%s"%s', $className, ($static ? 'static ' : '').$interface, $name, $returnType ? ': '.$returnType : '', null === $description ? '.' : ': '.$description); - } - } - } - } - } - - if (trait_exists($class)) { - $file = $refl->getFileName(); - - foreach ($refl->getMethods() as $method) { - if ($method->getFileName() === $file) { - self::$methodTraits[$file][$method->getStartLine()] = $class; - } - } - - return $deprecations; - } - - // Inherit @final, @internal, @param and @return annotations for methods - self::$finalMethods[$class] = []; - self::$internalMethods[$class] = []; - self::$annotatedParameters[$class] = []; - foreach ($parentAndOwnInterfaces as $use) { - foreach (['finalMethods', 'internalMethods', 'annotatedParameters', 'returnTypes'] as $property) { - if (isset(self::${$property}[$use])) { - self::${$property}[$class] = self::${$property}[$class] ? self::${$property}[$use] + self::${$property}[$class] : self::${$property}[$use]; - } - } - - if (null !== (TentativeTypes::RETURN_TYPES[$use] ?? null)) { - foreach (TentativeTypes::RETURN_TYPES[$use] as $method => $returnType) { - $returnType = explode('|', $returnType); - foreach ($returnType as $i => $t) { - if ('?' !== $t && !isset(self::BUILTIN_RETURN_TYPES[$t])) { - $returnType[$i] = '\\'.$t; - } - } - $returnType = implode('|', $returnType); - - self::$returnTypes[$class] += [$method => [$returnType, 0 === strpos($returnType, '?') ? substr($returnType, 1).'|null' : $returnType, $use, '']]; - } - } - } - - foreach ($refl->getMethods() as $method) { - if ($method->class !== $class) { - continue; - } - - if (null === $ns = self::$methodTraits[$method->getFileName()][$method->getStartLine()] ?? null) { - $ns = $vendor; - $len = $vendorLen; - } elseif (2 > $len = 1 + (strpos($ns, '\\') ?: strpos($ns, '_'))) { - $len = 0; - $ns = ''; - } else { - $ns = str_replace('_', '\\', substr($ns, 0, $len)); - } - - if ($parent && isset(self::$finalMethods[$parent][$method->name])) { - [$declaringClass, $message] = self::$finalMethods[$parent][$method->name]; - $deprecations[] = sprintf('The "%s::%s()" method is considered final%s It may change without further notice as of its next major version. You should not extend it from "%s".', $declaringClass, $method->name, $message, $className); - } - - if (isset(self::$internalMethods[$class][$method->name])) { - [$declaringClass, $message] = self::$internalMethods[$class][$method->name]; - if (strncmp($ns, $declaringClass, $len)) { - $deprecations[] = sprintf('The "%s::%s()" method is considered internal%s It may change without further notice. You should not extend it from "%s".', $declaringClass, $method->name, $message, $className); - } - } - - // To read method annotations - $doc = $this->parsePhpDoc($method); - - if (($classIsTemplate || isset($doc['template'])) && $method->hasReturnType()) { - unset($doc['return']); - } - - if (isset(self::$annotatedParameters[$class][$method->name])) { - $definedParameters = []; - foreach ($method->getParameters() as $parameter) { - $definedParameters[$parameter->name] = true; - } - - foreach (self::$annotatedParameters[$class][$method->name] as $parameterName => $deprecation) { - if (!isset($definedParameters[$parameterName]) && !isset($doc['param'][$parameterName])) { - $deprecations[] = sprintf($deprecation, $className); - } - } - } - - $forcePatchTypes = $this->patchTypes['force']; - - if ($canAddReturnType = null !== $forcePatchTypes && false === strpos($method->getFileName(), \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR)) { - if ('void' !== (self::MAGIC_METHODS[$method->name] ?? 'void')) { - $this->patchTypes['force'] = $forcePatchTypes ?: 'docblock'; - } - - $canAddReturnType = 2 === (int) $forcePatchTypes - || false !== stripos($method->getFileName(), \DIRECTORY_SEPARATOR.'Tests'.\DIRECTORY_SEPARATOR) - || $refl->isFinal() - || $method->isFinal() - || $method->isPrivate() - || ('.' === (self::$internal[$class] ?? null) && !$refl->isAbstract()) - || '.' === (self::$final[$class] ?? null) - || '' === ($doc['final'][0] ?? null) - || '' === ($doc['internal'][0] ?? null) - ; - } - - if (null !== ($returnType = self::$returnTypes[$class][$method->name] ?? null) && 'docblock' === $this->patchTypes['force'] && !$method->hasReturnType() && isset(TentativeTypes::RETURN_TYPES[$returnType[2]][$method->name])) { - $this->patchReturnTypeWillChange($method); - } - - if (null !== ($returnType ?? $returnType = self::MAGIC_METHODS[$method->name] ?? null) && !$method->hasReturnType() && !isset($doc['return'])) { - [$normalizedType, $returnType, $declaringClass, $declaringFile] = \is_string($returnType) ? [$returnType, $returnType, '', ''] : $returnType; - - if ($canAddReturnType && 'docblock' !== $this->patchTypes['force']) { - $this->patchMethod($method, $returnType, $declaringFile, $normalizedType); - } - if (!isset($doc['deprecated']) && strncmp($ns, $declaringClass, $len)) { - if ('docblock' === $this->patchTypes['force']) { - $this->patchMethod($method, $returnType, $declaringFile, $normalizedType); - } elseif ('' !== $declaringClass && $this->patchTypes['deprecations']) { - $deprecations[] = sprintf('Method "%s::%s()" might add "%s" as a native return type declaration in the future. Do the same in %s "%s" now to avoid errors or add an explicit @return annotation to suppress this message.', $declaringClass, $method->name, $normalizedType, interface_exists($declaringClass) ? 'implementation' : 'child class', $className); - } - } - } - - if (!$doc) { - $this->patchTypes['force'] = $forcePatchTypes; - - continue; - } - - if (isset($doc['return']) || 'void' !== (self::MAGIC_METHODS[$method->name] ?? 'void')) { - $this->setReturnType($doc['return'] ?? self::MAGIC_METHODS[$method->name], $method->class, $method->name, $method->getFileName(), $parent, $method->getReturnType()); - - if (isset(self::$returnTypes[$class][$method->name][0]) && $canAddReturnType) { - $this->fixReturnStatements($method, self::$returnTypes[$class][$method->name][0]); - } - - if ($method->isPrivate()) { - unset(self::$returnTypes[$class][$method->name]); - } - } - - $this->patchTypes['force'] = $forcePatchTypes; - - if ($method->isPrivate()) { - continue; - } - - $finalOrInternal = false; - - foreach (['final', 'internal'] as $annotation) { - if (null !== $description = $doc[$annotation][0] ?? null) { - self::${$annotation.'Methods'}[$class][$method->name] = [$class, '' !== $description ? ' '.$description.(preg_match('/[[:punct:]]$/', $description) ? '' : '.') : '.']; - $finalOrInternal = true; - } - } - - if ($finalOrInternal || $method->isConstructor() || !isset($doc['param']) || StatelessInvocation::class === $class) { - continue; - } - if (!isset(self::$annotatedParameters[$class][$method->name])) { - $definedParameters = []; - foreach ($method->getParameters() as $parameter) { - $definedParameters[$parameter->name] = true; - } - } - foreach ($doc['param'] as $parameterName => $parameterType) { - if (!isset($definedParameters[$parameterName])) { - self::$annotatedParameters[$class][$method->name][$parameterName] = sprintf('The "%%s::%s()" method will require a new "%s$%s" argument in the next major version of its %s "%s", not defining it is deprecated.', $method->name, $parameterType ? $parameterType.' ' : '', $parameterName, interface_exists($className) ? 'interface' : 'parent class', $className); - } - } - } - - return $deprecations; - } - - public function checkCase(\ReflectionClass $refl, string $file, string $class): ?array - { - $real = explode('\\', $class.strrchr($file, '.')); - $tail = explode(\DIRECTORY_SEPARATOR, str_replace('/', \DIRECTORY_SEPARATOR, $file)); - - $i = \count($tail) - 1; - $j = \count($real) - 1; - - while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) { - --$i; - --$j; - } - - array_splice($tail, 0, $i + 1); - - if (!$tail) { - return null; - } - - $tail = \DIRECTORY_SEPARATOR.implode(\DIRECTORY_SEPARATOR, $tail); - $tailLen = \strlen($tail); - $real = $refl->getFileName(); - - if (2 === self::$caseCheck) { - $real = $this->darwinRealpath($real); - } - - if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true) - && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false) - ) { - return [substr($tail, -$tailLen + 1), substr($real, -$tailLen + 1), substr($real, 0, -$tailLen + 1)]; - } - - return null; - } - - /** - * `realpath` on MacOSX doesn't normalize the case of characters. - */ - private function darwinRealpath(string $real): string - { - $i = 1 + strrpos($real, '/'); - $file = substr($real, $i); - $real = substr($real, 0, $i); - - if (isset(self::$darwinCache[$real])) { - $kDir = $real; - } else { - $kDir = strtolower($real); - - if (isset(self::$darwinCache[$kDir])) { - $real = self::$darwinCache[$kDir][0]; - } else { - $dir = getcwd(); - - if (!@chdir($real)) { - return $real.$file; - } - - $real = getcwd().'/'; - chdir($dir); - - $dir = $real; - $k = $kDir; - $i = \strlen($dir) - 1; - while (!isset(self::$darwinCache[$k])) { - self::$darwinCache[$k] = [$dir, []]; - self::$darwinCache[$dir] = &self::$darwinCache[$k]; - - while ('/' !== $dir[--$i]) { - } - $k = substr($k, 0, ++$i); - $dir = substr($dir, 0, $i--); - } - } - } - - $dirFiles = self::$darwinCache[$kDir][1]; - - if (!isset($dirFiles[$file]) && ') : eval()\'d code' === substr($file, -17)) { - // Get the file name from "file_name.php(123) : eval()'d code" - $file = substr($file, 0, strrpos($file, '(', -17)); - } - - if (isset($dirFiles[$file])) { - return $real.$dirFiles[$file]; - } - - $kFile = strtolower($file); - - if (!isset($dirFiles[$kFile])) { - foreach (scandir($real, 2) as $f) { - if ('.' !== $f[0]) { - $dirFiles[$f] = $f; - if ($f === $file) { - $kFile = $k = $file; - } elseif ($f !== $k = strtolower($f)) { - $dirFiles[$k] = $f; - } - } - } - self::$darwinCache[$kDir][1] = $dirFiles; - } - - return $real.$dirFiles[$kFile]; - } - - /** - * `class_implements` includes interfaces from the parents so we have to manually exclude them. - * - * @return string[] - */ - private function getOwnInterfaces(string $class, ?string $parent): array - { - $ownInterfaces = class_implements($class, false); - - if ($parent) { - foreach (class_implements($parent, false) as $interface) { - unset($ownInterfaces[$interface]); - } - } - - foreach ($ownInterfaces as $interface) { - foreach (class_implements($interface) as $interface) { - unset($ownInterfaces[$interface]); - } - } - - return $ownInterfaces; - } - - private function setReturnType(string $types, string $class, string $method, string $filename, ?string $parent, \ReflectionType $returnType = null): void - { - if ('__construct' === $method) { - return; - } - - if ($nullable = 0 === strpos($types, 'null|')) { - $types = substr($types, 5); - } elseif ($nullable = '|null' === substr($types, -5)) { - $types = substr($types, 0, -5); - } - $arrayType = ['array' => 'array']; - $typesMap = []; - $glue = false !== strpos($types, '&') ? '&' : '|'; - foreach (explode($glue, $types) as $t) { - $t = self::SPECIAL_RETURN_TYPES[strtolower($t)] ?? $t; - $typesMap[$this->normalizeType($t, $class, $parent, $returnType)][$t] = $t; - } - - if (isset($typesMap['array'])) { - if (isset($typesMap['Traversable']) || isset($typesMap['\Traversable'])) { - $typesMap['iterable'] = $arrayType !== $typesMap['array'] ? $typesMap['array'] : ['iterable']; - unset($typesMap['array'], $typesMap['Traversable'], $typesMap['\Traversable']); - } elseif ($arrayType !== $typesMap['array'] && isset(self::$returnTypes[$class][$method]) && !$returnType) { - return; - } - } - - if (isset($typesMap['array']) && isset($typesMap['iterable'])) { - if ($arrayType !== $typesMap['array']) { - $typesMap['iterable'] = $typesMap['array']; - } - unset($typesMap['array']); - } - - $iterable = $object = true; - foreach ($typesMap as $n => $t) { - if ('null' !== $n) { - $iterable = $iterable && (\in_array($n, ['array', 'iterable']) || false !== strpos($n, 'Iterator')); - $object = $object && (\in_array($n, ['callable', 'object', '$this', 'static']) || !isset(self::SPECIAL_RETURN_TYPES[$n])); - } - } - - $phpTypes = []; - $docTypes = []; - - foreach ($typesMap as $n => $t) { - if ('null' === $n) { - $nullable = true; - continue; - } - - $docTypes[] = $t; - - if ('mixed' === $n || 'void' === $n) { - $nullable = false; - $phpTypes = ['' => $n]; - continue; - } - - if ('resource' === $n) { - // there is no native type for "resource" - return; - } - - if (!isset($phpTypes[''])) { - $phpTypes[] = $n; - } - } - $docTypes = array_merge([], ...$docTypes); - - if (!$phpTypes) { - return; - } - - if (1 < \count($phpTypes)) { - if ($iterable && '8.0' > $this->patchTypes['php']) { - $phpTypes = $docTypes = ['iterable']; - } elseif ($object && 'object' === $this->patchTypes['force']) { - $phpTypes = $docTypes = ['object']; - } elseif ('8.0' > $this->patchTypes['php']) { - // ignore multi-types return declarations - return; - } - } - - $phpType = sprintf($nullable ? (1 < \count($phpTypes) ? '%s|null' : '?%s') : '%s', implode($glue, $phpTypes)); - $docType = sprintf($nullable ? '%s|null' : '%s', implode($glue, $docTypes)); - - self::$returnTypes[$class][$method] = [$phpType, $docType, $class, $filename]; - } - - private function normalizeType(string $type, string $class, ?string $parent, ?\ReflectionType $returnType): string - { - if (isset(self::SPECIAL_RETURN_TYPES[$lcType = strtolower($type)])) { - if ('parent' === $lcType = self::SPECIAL_RETURN_TYPES[$lcType]) { - $lcType = null !== $parent ? '\\'.$parent : 'parent'; - } elseif ('self' === $lcType) { - $lcType = '\\'.$class; - } - - return $lcType; - } - - // We could resolve "use" statements to return the FQDN - // but this would be too expensive for a runtime checker - - if ('[]' !== substr($type, -2)) { - return $type; - } - - if ($returnType instanceof \ReflectionNamedType) { - $type = $returnType->getName(); - - if ('mixed' !== $type) { - return isset(self::SPECIAL_RETURN_TYPES[$type]) ? $type : '\\'.$type; - } - } - - return 'array'; - } - - /** - * Utility method to add #[ReturnTypeWillChange] where php triggers deprecations. - */ - private function patchReturnTypeWillChange(\ReflectionMethod $method) - { - if (\PHP_VERSION_ID >= 80000 && \count($method->getAttributes(\ReturnTypeWillChange::class))) { - return; - } - - if (!is_file($file = $method->getFileName())) { - return; - } - - $fileOffset = self::$fileOffsets[$file] ?? 0; - - $code = file($file); - - $startLine = $method->getStartLine() + $fileOffset - 2; - - if (false !== stripos($code[$startLine], 'ReturnTypeWillChange')) { - return; - } - - $code[$startLine] .= " #[\\ReturnTypeWillChange]\n"; - self::$fileOffsets[$file] = 1 + $fileOffset; - file_put_contents($file, $code); - } - - /** - * Utility method to add @return annotations to the Symfony code-base where it triggers self-deprecations. - */ - private function patchMethod(\ReflectionMethod $method, string $returnType, string $declaringFile, string $normalizedType) - { - static $patchedMethods = []; - static $useStatements = []; - - if (!is_file($file = $method->getFileName()) || isset($patchedMethods[$file][$startLine = $method->getStartLine()])) { - return; - } - - $patchedMethods[$file][$startLine] = true; - $fileOffset = self::$fileOffsets[$file] ?? 0; - $startLine += $fileOffset - 2; - if ($nullable = '|null' === substr($returnType, -5)) { - $returnType = substr($returnType, 0, -5); - } - $glue = false !== strpos($returnType, '&') ? '&' : '|'; - $returnType = explode($glue, $returnType); - $code = file($file); - - foreach ($returnType as $i => $type) { - if (preg_match('/((?:\[\])+)$/', $type, $m)) { - $type = substr($type, 0, -\strlen($m[1])); - $format = '%s'.$m[1]; - } else { - $format = null; - } - - if (isset(self::SPECIAL_RETURN_TYPES[$type]) || ('\\' === $type[0] && !$p = strrpos($type, '\\', 1))) { - continue; - } - - [$namespace, $useOffset, $useMap] = $useStatements[$file] ?? $useStatements[$file] = self::getUseStatements($file); - - if ('\\' !== $type[0]) { - [$declaringNamespace, , $declaringUseMap] = $useStatements[$declaringFile] ?? $useStatements[$declaringFile] = self::getUseStatements($declaringFile); - - $p = strpos($type, '\\', 1); - $alias = $p ? substr($type, 0, $p) : $type; - - if (isset($declaringUseMap[$alias])) { - $type = '\\'.$declaringUseMap[$alias].($p ? substr($type, $p) : ''); - } else { - $type = '\\'.$declaringNamespace.$type; - } - - $p = strrpos($type, '\\', 1); - } - - $alias = substr($type, 1 + $p); - $type = substr($type, 1); - - if (!isset($useMap[$alias]) && (class_exists($c = $namespace.$alias) || interface_exists($c) || trait_exists($c))) { - $useMap[$alias] = $c; - } - - if (!isset($useMap[$alias])) { - $useStatements[$file][2][$alias] = $type; - $code[$useOffset] = "use $type;\n".$code[$useOffset]; - ++$fileOffset; - } elseif ($useMap[$alias] !== $type) { - $alias .= 'FIXME'; - $useStatements[$file][2][$alias] = $type; - $code[$useOffset] = "use $type as $alias;\n".$code[$useOffset]; - ++$fileOffset; - } - - $returnType[$i] = null !== $format ? sprintf($format, $alias) : $alias; - } - - if ('docblock' === $this->patchTypes['force'] || ('object' === $normalizedType && '7.1' === $this->patchTypes['php'])) { - $returnType = implode($glue, $returnType).($nullable ? '|null' : ''); - - if (false !== strpos($code[$startLine], '#[')) { - --$startLine; - } - - if ($method->getDocComment()) { - $code[$startLine] = " * @return $returnType\n".$code[$startLine]; - } else { - $code[$startLine] .= <<<EOTXT - /** - * @return $returnType - */ - -EOTXT; - } - - $fileOffset += substr_count($code[$startLine], "\n") - 1; - } - - self::$fileOffsets[$file] = $fileOffset; - file_put_contents($file, $code); - - $this->fixReturnStatements($method, $normalizedType); - } - - private static function getUseStatements(string $file): array - { - $namespace = ''; - $useMap = []; - $useOffset = 0; - - if (!is_file($file)) { - return [$namespace, $useOffset, $useMap]; - } - - $file = file($file); - - for ($i = 0; $i < \count($file); ++$i) { - if (preg_match('/^(class|interface|trait|abstract) /', $file[$i])) { - break; - } - - if (0 === strpos($file[$i], 'namespace ')) { - $namespace = substr($file[$i], \strlen('namespace '), -2).'\\'; - $useOffset = $i + 2; - } - - if (0 === strpos($file[$i], 'use ')) { - $useOffset = $i; - - for (; 0 === strpos($file[$i], 'use '); ++$i) { - $u = explode(' as ', substr($file[$i], 4, -2), 2); - - if (1 === \count($u)) { - $p = strrpos($u[0], '\\'); - $useMap[substr($u[0], false !== $p ? 1 + $p : 0)] = $u[0]; - } else { - $useMap[$u[1]] = $u[0]; - } - } - - break; - } - } - - return [$namespace, $useOffset, $useMap]; - } - - private function fixReturnStatements(\ReflectionMethod $method, string $returnType) - { - if ('docblock' !== $this->patchTypes['force']) { - if ('7.1' === $this->patchTypes['php'] && 'object' === ltrim($returnType, '?')) { - return; - } - - if ('7.4' > $this->patchTypes['php'] && $method->hasReturnType()) { - return; - } - - if ('8.0' > $this->patchTypes['php'] && (false !== strpos($returnType, '|') || \in_array($returnType, ['mixed', 'static'], true))) { - return; - } - - if ('8.1' > $this->patchTypes['php'] && false !== strpos($returnType, '&')) { - return; - } - } - - if (!is_file($file = $method->getFileName())) { - return; - } - - $fixedCode = $code = file($file); - $i = (self::$fileOffsets[$file] ?? 0) + $method->getStartLine(); - - if ('?' !== $returnType && 'docblock' !== $this->patchTypes['force']) { - $fixedCode[$i - 1] = preg_replace('/\)(?::[^;\n]++)?(;?\n)/', "): $returnType\\1", $code[$i - 1]); - } - - $end = $method->isGenerator() ? $i : $method->getEndLine(); - for (; $i < $end; ++$i) { - if ('void' === $returnType) { - $fixedCode[$i] = str_replace(' return null;', ' return;', $code[$i]); - } elseif ('mixed' === $returnType || '?' === $returnType[0]) { - $fixedCode[$i] = str_replace(' return;', ' return null;', $code[$i]); - } else { - $fixedCode[$i] = str_replace(' return;', " return $returnType!?;", $code[$i]); - } - } - - if ($fixedCode !== $code) { - file_put_contents($file, $fixedCode); - } - } - - /** - * @param \ReflectionClass|\ReflectionMethod|\ReflectionProperty $reflector - */ - private function parsePhpDoc(\Reflector $reflector): array - { - if (!$doc = $reflector->getDocComment()) { - return []; - } - - $tagName = ''; - $tagContent = ''; - - $tags = []; - - foreach (explode("\n", substr($doc, 3, -2)) as $line) { - $line = ltrim($line); - $line = ltrim($line, '*'); - - if ('' === $line = trim($line)) { - if ('' !== $tagName) { - $tags[$tagName][] = $tagContent; - } - $tagName = $tagContent = ''; - continue; - } - - if ('@' === $line[0]) { - if ('' !== $tagName) { - $tags[$tagName][] = $tagContent; - $tagContent = ''; - } - - if (preg_match('{^@([-a-zA-Z0-9_:]++)(\s|$)}', $line, $m)) { - $tagName = $m[1]; - $tagContent = str_replace("\t", ' ', ltrim(substr($line, 2 + \strlen($tagName)))); - } else { - $tagName = ''; - } - } elseif ('' !== $tagName) { - $tagContent .= ' '.str_replace("\t", ' ', $line); - } - } - - if ('' !== $tagName) { - $tags[$tagName][] = $tagContent; - } - - foreach ($tags['method'] ?? [] as $i => $method) { - unset($tags['method'][$i]); - - $parts = preg_split('{(\s++|\((?:[^()]*+|(?R))*\)(?: *: *[^ ]++)?|<(?:[^<>]*+|(?R))*>|\{(?:[^{}]*+|(?R))*\})}', $method, -1, \PREG_SPLIT_DELIM_CAPTURE); - $returnType = ''; - $static = 'static' === $parts[0]; - - for ($i = $static ? 2 : 0; null !== $p = $parts[$i] ?? null; $i += 2) { - if (\in_array($p, ['', '|', '&', 'callable'], true) || \in_array(substr($returnType, -1), ['|', '&'], true)) { - $returnType .= trim($parts[$i - 1] ?? '').$p; - continue; - } - - $signature = '(' === ($parts[$i + 1][0] ?? '(') ? $parts[$i + 1] ?? '()' : null; - - if (null === $signature && '' === $returnType) { - $returnType = $p; - continue; - } - - if ($static && 2 === $i) { - $static = false; - $returnType = 'static'; - } - - if (\in_array($description = trim(implode('', \array_slice($parts, 2 + $i))), ['', '.'], true)) { - $description = null; - } elseif (!preg_match('/[.!]$/', $description)) { - $description .= '.'; - } - - $tags['method'][$p] = [$static, $returnType, $signature ?? '()', $description]; - break; - } - } - - foreach ($tags['param'] ?? [] as $i => $param) { - unset($tags['param'][$i]); - - if (\strlen($param) !== strcspn($param, '<{(')) { - $param = preg_replace('{\(([^()]*+|(?R))*\)(?: *: *[^ ]++)?|<([^<>]*+|(?R))*>|\{([^{}]*+|(?R))*\}}', '', $param); - } - - if (false === $i = strpos($param, '$')) { - continue; - } - - $type = 0 === $i ? '' : rtrim(substr($param, 0, $i), ' &'); - $param = substr($param, 1 + $i, (strpos($param, ' ', $i) ?: (1 + $i + \strlen($param))) - $i - 1); - - $tags['param'][$param] = $type; - } - - foreach (['var', 'return'] as $k) { - if (null === $v = $tags[$k][0] ?? null) { - continue; - } - if (\strlen($v) !== strcspn($v, '<{(')) { - $v = preg_replace('{\(([^()]*+|(?R))*\)(?: *: *[^ ]++)?|<([^<>]*+|(?R))*>|\{([^{}]*+|(?R))*\}}', '', $v); - } - - $tags[$k] = substr($v, 0, strpos($v, ' ') ?: \strlen($v)) ?: null; - } - - return $tags; - } -} diff --git a/lib/symfony/error-handler/Error/ClassNotFoundError.php b/lib/symfony/error-handler/Error/ClassNotFoundError.php deleted file mode 100644 index 443fba2c3..000000000 --- a/lib/symfony/error-handler/Error/ClassNotFoundError.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\Error; - -class ClassNotFoundError extends \Error -{ - /** - * {@inheritdoc} - */ - public function __construct(string $message, \Throwable $previous) - { - parent::__construct($message, $previous->getCode(), $previous->getPrevious()); - - foreach ([ - 'file' => $previous->getFile(), - 'line' => $previous->getLine(), - 'trace' => $previous->getTrace(), - ] as $property => $value) { - $refl = new \ReflectionProperty(\Error::class, $property); - $refl->setAccessible(true); - $refl->setValue($this, $value); - } - } -} diff --git a/lib/symfony/error-handler/Error/FatalError.php b/lib/symfony/error-handler/Error/FatalError.php deleted file mode 100644 index 57fc690e2..000000000 --- a/lib/symfony/error-handler/Error/FatalError.php +++ /dev/null @@ -1,89 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\Error; - -class FatalError extends \Error -{ - private $error; - - /** - * {@inheritdoc} - * - * @param array $error An array as returned by error_get_last() - */ - public function __construct(string $message, int $code, array $error, int $traceOffset = null, bool $traceArgs = true, array $trace = null) - { - parent::__construct($message, $code); - - $this->error = $error; - - if (null !== $trace) { - if (!$traceArgs) { - foreach ($trace as &$frame) { - unset($frame['args'], $frame['this'], $frame); - } - } - } elseif (null !== $traceOffset) { - if (\function_exists('xdebug_get_function_stack') && $trace = @xdebug_get_function_stack()) { - if (0 < $traceOffset) { - array_splice($trace, -$traceOffset); - } - - foreach ($trace as &$frame) { - if (!isset($frame['type'])) { - // XDebug pre 2.1.1 doesn't currently set the call type key http://bugs.xdebug.org/view.php?id=695 - if (isset($frame['class'])) { - $frame['type'] = '::'; - } - } elseif ('dynamic' === $frame['type']) { - $frame['type'] = '->'; - } elseif ('static' === $frame['type']) { - $frame['type'] = '::'; - } - - // XDebug also has a different name for the parameters array - if (!$traceArgs) { - unset($frame['params'], $frame['args']); - } elseif (isset($frame['params']) && !isset($frame['args'])) { - $frame['args'] = $frame['params']; - unset($frame['params']); - } - } - - unset($frame); - $trace = array_reverse($trace); - } else { - $trace = []; - } - } - - foreach ([ - 'file' => $error['file'], - 'line' => $error['line'], - 'trace' => $trace, - ] as $property => $value) { - if (null !== $value) { - $refl = new \ReflectionProperty(\Error::class, $property); - $refl->setAccessible(true); - $refl->setValue($this, $value); - } - } - } - - /** - * {@inheritdoc} - */ - public function getError(): array - { - return $this->error; - } -} diff --git a/lib/symfony/error-handler/Error/OutOfMemoryError.php b/lib/symfony/error-handler/Error/OutOfMemoryError.php deleted file mode 100644 index d685c3d36..000000000 --- a/lib/symfony/error-handler/Error/OutOfMemoryError.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\Error; - -class OutOfMemoryError extends FatalError -{ -} diff --git a/lib/symfony/error-handler/Error/UndefinedFunctionError.php b/lib/symfony/error-handler/Error/UndefinedFunctionError.php deleted file mode 100644 index b57dd1579..000000000 --- a/lib/symfony/error-handler/Error/UndefinedFunctionError.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\Error; - -class UndefinedFunctionError extends \Error -{ - /** - * {@inheritdoc} - */ - public function __construct(string $message, \Throwable $previous) - { - parent::__construct($message, $previous->getCode(), $previous->getPrevious()); - - foreach ([ - 'file' => $previous->getFile(), - 'line' => $previous->getLine(), - 'trace' => $previous->getTrace(), - ] as $property => $value) { - $refl = new \ReflectionProperty(\Error::class, $property); - $refl->setAccessible(true); - $refl->setValue($this, $value); - } - } -} diff --git a/lib/symfony/error-handler/Error/UndefinedMethodError.php b/lib/symfony/error-handler/Error/UndefinedMethodError.php deleted file mode 100644 index adc8731f3..000000000 --- a/lib/symfony/error-handler/Error/UndefinedMethodError.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\Error; - -class UndefinedMethodError extends \Error -{ - /** - * {@inheritdoc} - */ - public function __construct(string $message, \Throwable $previous) - { - parent::__construct($message, $previous->getCode(), $previous->getPrevious()); - - foreach ([ - 'file' => $previous->getFile(), - 'line' => $previous->getLine(), - 'trace' => $previous->getTrace(), - ] as $property => $value) { - $refl = new \ReflectionProperty(\Error::class, $property); - $refl->setAccessible(true); - $refl->setValue($this, $value); - } - } -} diff --git a/lib/symfony/error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php b/lib/symfony/error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php deleted file mode 100644 index f85d27515..000000000 --- a/lib/symfony/error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php +++ /dev/null @@ -1,177 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\ErrorEnhancer; - -use Composer\Autoload\ClassLoader; -use Symfony\Component\ErrorHandler\DebugClassLoader; -use Symfony\Component\ErrorHandler\Error\ClassNotFoundError; -use Symfony\Component\ErrorHandler\Error\FatalError; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -class ClassNotFoundErrorEnhancer implements ErrorEnhancerInterface -{ - /** - * {@inheritdoc} - */ - public function enhance(\Throwable $error): ?\Throwable - { - // Some specific versions of PHP produce a fatal error when extending a not found class. - $message = !$error instanceof FatalError ? $error->getMessage() : $error->getError()['message']; - if (!preg_match('/^(Class|Interface|Trait) [\'"]([^\'"]+)[\'"] not found$/', $message, $matches)) { - return null; - } - $typeName = strtolower($matches[1]); - $fullyQualifiedClassName = $matches[2]; - - if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedClassName, '\\')) { - $className = substr($fullyQualifiedClassName, $namespaceSeparatorIndex + 1); - $namespacePrefix = substr($fullyQualifiedClassName, 0, $namespaceSeparatorIndex); - $message = sprintf('Attempted to load %s "%s" from namespace "%s".', $typeName, $className, $namespacePrefix); - $tail = ' for another namespace?'; - } else { - $className = $fullyQualifiedClassName; - $message = sprintf('Attempted to load %s "%s" from the global namespace.', $typeName, $className); - $tail = '?'; - } - - if ($candidates = $this->getClassCandidates($className)) { - $tail = array_pop($candidates).'"?'; - if ($candidates) { - $tail = ' for e.g. "'.implode('", "', $candidates).'" or "'.$tail; - } else { - $tail = ' for "'.$tail; - } - } - $message .= "\nDid you forget a \"use\" statement".$tail; - - return new ClassNotFoundError($message, $error); - } - - /** - * Tries to guess the full namespace for a given class name. - * - * By default, it looks for PSR-0 and PSR-4 classes registered via a Symfony or a Composer - * autoloader (that should cover all common cases). - * - * @param string $class A class name (without its namespace) - * - * Returns an array of possible fully qualified class names - */ - private function getClassCandidates(string $class): array - { - if (!\is_array($functions = spl_autoload_functions())) { - return []; - } - - // find Symfony and Composer autoloaders - $classes = []; - - foreach ($functions as $function) { - if (!\is_array($function)) { - continue; - } - // get class loaders wrapped by DebugClassLoader - if ($function[0] instanceof DebugClassLoader) { - $function = $function[0]->getClassLoader(); - - if (!\is_array($function)) { - continue; - } - } - - if ($function[0] instanceof ClassLoader) { - foreach ($function[0]->getPrefixes() as $prefix => $paths) { - foreach ($paths as $path) { - $classes[] = $this->findClassInPath($path, $class, $prefix); - } - } - - foreach ($function[0]->getPrefixesPsr4() as $prefix => $paths) { - foreach ($paths as $path) { - $classes[] = $this->findClassInPath($path, $class, $prefix); - } - } - } - } - - return array_unique(array_merge([], ...$classes)); - } - - private function findClassInPath(string $path, string $class, string $prefix): array - { - if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.\dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) { - return []; - } - - $classes = []; - $filename = $class.'.php'; - foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) { - if ($filename == $file->getFileName() && $class = $this->convertFileToClass($path, $file->getPathName(), $prefix)) { - $classes[] = $class; - } - } - - return $classes; - } - - private function convertFileToClass(string $path, string $file, string $prefix): ?string - { - $candidates = [ - // namespaced class - $namespacedClass = str_replace([$path.\DIRECTORY_SEPARATOR, '.php', '/'], ['', '', '\\'], $file), - // namespaced class (with target dir) - $prefix.$namespacedClass, - // namespaced class (with target dir and separator) - $prefix.'\\'.$namespacedClass, - // PEAR class - str_replace('\\', '_', $namespacedClass), - // PEAR class (with target dir) - str_replace('\\', '_', $prefix.$namespacedClass), - // PEAR class (with target dir and separator) - str_replace('\\', '_', $prefix.'\\'.$namespacedClass), - ]; - - if ($prefix) { - $candidates = array_filter($candidates, function ($candidate) use ($prefix) { return 0 === strpos($candidate, $prefix); }); - } - - // We cannot use the autoloader here as most of them use require; but if the class - // is not found, the new autoloader call will require the file again leading to a - // "cannot redeclare class" error. - foreach ($candidates as $candidate) { - if ($this->classExists($candidate)) { - return $candidate; - } - } - - try { - require_once $file; - } catch (\Throwable $e) { - return null; - } - - foreach ($candidates as $candidate) { - if ($this->classExists($candidate)) { - return $candidate; - } - } - - return null; - } - - private function classExists(string $class): bool - { - return class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false); - } -} diff --git a/lib/symfony/error-handler/ErrorEnhancer/ErrorEnhancerInterface.php b/lib/symfony/error-handler/ErrorEnhancer/ErrorEnhancerInterface.php deleted file mode 100644 index 7c3f4ef94..000000000 --- a/lib/symfony/error-handler/ErrorEnhancer/ErrorEnhancerInterface.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\ErrorEnhancer; - -interface ErrorEnhancerInterface -{ - /** - * Returns an \Throwable instance if the class is able to improve the error, null otherwise. - */ - public function enhance(\Throwable $error): ?\Throwable; -} diff --git a/lib/symfony/error-handler/ErrorEnhancer/UndefinedFunctionErrorEnhancer.php b/lib/symfony/error-handler/ErrorEnhancer/UndefinedFunctionErrorEnhancer.php deleted file mode 100644 index f4c49c285..000000000 --- a/lib/symfony/error-handler/ErrorEnhancer/UndefinedFunctionErrorEnhancer.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\ErrorEnhancer; - -use Symfony\Component\ErrorHandler\Error\FatalError; -use Symfony\Component\ErrorHandler\Error\UndefinedFunctionError; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -class UndefinedFunctionErrorEnhancer implements ErrorEnhancerInterface -{ - /** - * {@inheritdoc} - */ - public function enhance(\Throwable $error): ?\Throwable - { - if ($error instanceof FatalError) { - return null; - } - - $message = $error->getMessage(); - $messageLen = \strlen($message); - $notFoundSuffix = '()'; - $notFoundSuffixLen = \strlen($notFoundSuffix); - if ($notFoundSuffixLen > $messageLen) { - return null; - } - - if (0 !== substr_compare($message, $notFoundSuffix, -$notFoundSuffixLen)) { - return null; - } - - $prefix = 'Call to undefined function '; - $prefixLen = \strlen($prefix); - if (0 !== strpos($message, $prefix)) { - return null; - } - - $fullyQualifiedFunctionName = substr($message, $prefixLen, -$notFoundSuffixLen); - if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedFunctionName, '\\')) { - $functionName = substr($fullyQualifiedFunctionName, $namespaceSeparatorIndex + 1); - $namespacePrefix = substr($fullyQualifiedFunctionName, 0, $namespaceSeparatorIndex); - $message = sprintf('Attempted to call function "%s" from namespace "%s".', $functionName, $namespacePrefix); - } else { - $functionName = $fullyQualifiedFunctionName; - $message = sprintf('Attempted to call function "%s" from the global namespace.', $functionName); - } - - $candidates = []; - foreach (get_defined_functions() as $type => $definedFunctionNames) { - foreach ($definedFunctionNames as $definedFunctionName) { - if (false !== $namespaceSeparatorIndex = strrpos($definedFunctionName, '\\')) { - $definedFunctionNameBasename = substr($definedFunctionName, $namespaceSeparatorIndex + 1); - } else { - $definedFunctionNameBasename = $definedFunctionName; - } - - if ($definedFunctionNameBasename === $functionName) { - $candidates[] = '\\'.$definedFunctionName; - } - } - } - - if ($candidates) { - sort($candidates); - $last = array_pop($candidates).'"?'; - if ($candidates) { - $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last; - } else { - $candidates = '"'.$last; - } - $message .= "\nDid you mean to call ".$candidates; - } - - return new UndefinedFunctionError($message, $error); - } -} diff --git a/lib/symfony/error-handler/ErrorEnhancer/UndefinedMethodErrorEnhancer.php b/lib/symfony/error-handler/ErrorEnhancer/UndefinedMethodErrorEnhancer.php deleted file mode 100644 index c4355f92c..000000000 --- a/lib/symfony/error-handler/ErrorEnhancer/UndefinedMethodErrorEnhancer.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\ErrorEnhancer; - -use Symfony\Component\ErrorHandler\Error\FatalError; -use Symfony\Component\ErrorHandler\Error\UndefinedMethodError; - -/** - * @author Grégoire Pineau <lyrixx@lyrixx.info> - */ -class UndefinedMethodErrorEnhancer implements ErrorEnhancerInterface -{ - /** - * {@inheritdoc} - */ - public function enhance(\Throwable $error): ?\Throwable - { - if ($error instanceof FatalError) { - return null; - } - - $message = $error->getMessage(); - preg_match('/^Call to undefined method (.*)::(.*)\(\)$/', $message, $matches); - if (!$matches) { - return null; - } - - $className = $matches[1]; - $methodName = $matches[2]; - - $message = sprintf('Attempted to call an undefined method named "%s" of class "%s".', $methodName, $className); - - if ('' === $methodName || !class_exists($className) || null === $methods = get_class_methods($className)) { - // failed to get the class or its methods on which an unknown method was called (for example on an anonymous class) - return new UndefinedMethodError($message, $error); - } - - $candidates = []; - foreach ($methods as $definedMethodName) { - $lev = levenshtein($methodName, $definedMethodName); - if ($lev <= \strlen($methodName) / 3 || false !== strpos($definedMethodName, $methodName)) { - $candidates[] = $definedMethodName; - } - } - - if ($candidates) { - sort($candidates); - $last = array_pop($candidates).'"?'; - if ($candidates) { - $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last; - } else { - $candidates = '"'.$last; - } - - $message .= "\nDid you mean to call ".$candidates; - } - - return new UndefinedMethodError($message, $error); - } -} diff --git a/lib/symfony/error-handler/ErrorHandler.php b/lib/symfony/error-handler/ErrorHandler.php deleted file mode 100644 index 003040242..000000000 --- a/lib/symfony/error-handler/ErrorHandler.php +++ /dev/null @@ -1,798 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler; - -use Psr\Log\LoggerInterface; -use Psr\Log\LogLevel; -use Symfony\Component\ErrorHandler\Error\FatalError; -use Symfony\Component\ErrorHandler\Error\OutOfMemoryError; -use Symfony\Component\ErrorHandler\ErrorEnhancer\ClassNotFoundErrorEnhancer; -use Symfony\Component\ErrorHandler\ErrorEnhancer\ErrorEnhancerInterface; -use Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedFunctionErrorEnhancer; -use Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedMethodErrorEnhancer; -use Symfony\Component\ErrorHandler\ErrorRenderer\CliErrorRenderer; -use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer; -use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext; - -/** - * A generic ErrorHandler for the PHP engine. - * - * Provides five bit fields that control how errors are handled: - * - thrownErrors: errors thrown as \ErrorException - * - loggedErrors: logged errors, when not @-silenced - * - scopedErrors: errors thrown or logged with their local context - * - tracedErrors: errors logged with their stack trace - * - screamedErrors: never @-silenced errors - * - * Each error level can be logged by a dedicated PSR-3 logger object. - * Screaming only applies to logging. - * Throwing takes precedence over logging. - * Uncaught exceptions are logged as E_ERROR. - * E_DEPRECATED and E_USER_DEPRECATED levels never throw. - * E_RECOVERABLE_ERROR and E_USER_ERROR levels always throw. - * Non catchable errors that can be detected at shutdown time are logged when the scream bit field allows so. - * As errors have a performance cost, repeated errors are all logged, so that the developer - * can see them and weight them as more important to fix than others of the same level. - * - * @author Nicolas Grekas <p@tchwork.com> - * @author Grégoire Pineau <lyrixx@lyrixx.info> - * - * @final - */ -class ErrorHandler -{ - private $levels = [ - \E_DEPRECATED => 'Deprecated', - \E_USER_DEPRECATED => 'User Deprecated', - \E_NOTICE => 'Notice', - \E_USER_NOTICE => 'User Notice', - \E_STRICT => 'Runtime Notice', - \E_WARNING => 'Warning', - \E_USER_WARNING => 'User Warning', - \E_COMPILE_WARNING => 'Compile Warning', - \E_CORE_WARNING => 'Core Warning', - \E_USER_ERROR => 'User Error', - \E_RECOVERABLE_ERROR => 'Catchable Fatal Error', - \E_COMPILE_ERROR => 'Compile Error', - \E_PARSE => 'Parse Error', - \E_ERROR => 'Error', - \E_CORE_ERROR => 'Core Error', - ]; - - private $loggers = [ - \E_DEPRECATED => [null, LogLevel::INFO], - \E_USER_DEPRECATED => [null, LogLevel::INFO], - \E_NOTICE => [null, LogLevel::WARNING], - \E_USER_NOTICE => [null, LogLevel::WARNING], - \E_STRICT => [null, LogLevel::WARNING], - \E_WARNING => [null, LogLevel::WARNING], - \E_USER_WARNING => [null, LogLevel::WARNING], - \E_COMPILE_WARNING => [null, LogLevel::WARNING], - \E_CORE_WARNING => [null, LogLevel::WARNING], - \E_USER_ERROR => [null, LogLevel::CRITICAL], - \E_RECOVERABLE_ERROR => [null, LogLevel::CRITICAL], - \E_COMPILE_ERROR => [null, LogLevel::CRITICAL], - \E_PARSE => [null, LogLevel::CRITICAL], - \E_ERROR => [null, LogLevel::CRITICAL], - \E_CORE_ERROR => [null, LogLevel::CRITICAL], - ]; - - private $thrownErrors = 0x1FFF; // E_ALL - E_DEPRECATED - E_USER_DEPRECATED - private $scopedErrors = 0x1FFF; // E_ALL - E_DEPRECATED - E_USER_DEPRECATED - private $tracedErrors = 0x77FB; // E_ALL - E_STRICT - E_PARSE - private $screamedErrors = 0x55; // E_ERROR + E_CORE_ERROR + E_COMPILE_ERROR + E_PARSE - private $loggedErrors = 0; - private $configureException; - private $debug; - - private $isRecursive = 0; - private $isRoot = false; - private $exceptionHandler; - private $bootstrappingLogger; - - private static $reservedMemory; - private static $toStringException; - private static $silencedErrorCache = []; - private static $silencedErrorCount = 0; - private static $exitCode = 0; - - /** - * Registers the error handler. - */ - public static function register(self $handler = null, bool $replace = true): self - { - if (null === self::$reservedMemory) { - self::$reservedMemory = str_repeat('x', 32768); - register_shutdown_function(__CLASS__.'::handleFatalError'); - } - - if ($handlerIsNew = null === $handler) { - $handler = new static(); - } - - if (null === $prev = set_error_handler([$handler, 'handleError'])) { - restore_error_handler(); - // Specifying the error types earlier would expose us to https://bugs.php.net/63206 - set_error_handler([$handler, 'handleError'], $handler->thrownErrors | $handler->loggedErrors); - $handler->isRoot = true; - } - - if ($handlerIsNew && \is_array($prev) && $prev[0] instanceof self) { - $handler = $prev[0]; - $replace = false; - } - if (!$replace && $prev) { - restore_error_handler(); - $handlerIsRegistered = \is_array($prev) && $handler === $prev[0]; - } else { - $handlerIsRegistered = true; - } - if (\is_array($prev = set_exception_handler([$handler, 'handleException'])) && $prev[0] instanceof self) { - restore_exception_handler(); - if (!$handlerIsRegistered) { - $handler = $prev[0]; - } elseif ($handler !== $prev[0] && $replace) { - set_exception_handler([$handler, 'handleException']); - $p = $prev[0]->setExceptionHandler(null); - $handler->setExceptionHandler($p); - $prev[0]->setExceptionHandler($p); - } - } else { - $handler->setExceptionHandler($prev ?? [$handler, 'renderException']); - } - - $handler->throwAt(\E_ALL & $handler->thrownErrors, true); - - return $handler; - } - - /** - * Calls a function and turns any PHP error into \ErrorException. - * - * @return mixed What $function(...$arguments) returns - * - * @throws \ErrorException When $function(...$arguments) triggers a PHP error - */ - public static function call(callable $function, ...$arguments) - { - set_error_handler(static function (int $type, string $message, string $file, int $line) { - if (__FILE__ === $file) { - $trace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 3); - $file = $trace[2]['file'] ?? $file; - $line = $trace[2]['line'] ?? $line; - } - - throw new \ErrorException($message, 0, $type, $file, $line); - }); - - try { - return $function(...$arguments); - } finally { - restore_error_handler(); - } - } - - public function __construct(BufferingLogger $bootstrappingLogger = null, bool $debug = false) - { - if ($bootstrappingLogger) { - $this->bootstrappingLogger = $bootstrappingLogger; - $this->setDefaultLogger($bootstrappingLogger); - } - $traceReflector = new \ReflectionProperty(\Exception::class, 'trace'); - $traceReflector->setAccessible(true); - $this->configureException = \Closure::bind(static function ($e, $trace, $file = null, $line = null) use ($traceReflector) { - $traceReflector->setValue($e, $trace); - $e->file = $file ?? $e->file; - $e->line = $line ?? $e->line; - }, null, new class() extends \Exception { - }); - $this->debug = $debug; - } - - /** - * Sets a logger to non assigned errors levels. - * - * @param LoggerInterface $logger A PSR-3 logger to put as default for the given levels - * @param array|int|null $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants - * @param bool $replace Whether to replace or not any existing logger - */ - public function setDefaultLogger(LoggerInterface $logger, $levels = \E_ALL, bool $replace = false): void - { - $loggers = []; - - if (\is_array($levels)) { - foreach ($levels as $type => $logLevel) { - if (empty($this->loggers[$type][0]) || $replace || $this->loggers[$type][0] === $this->bootstrappingLogger) { - $loggers[$type] = [$logger, $logLevel]; - } - } - } else { - if (null === $levels) { - $levels = \E_ALL; - } - foreach ($this->loggers as $type => $log) { - if (($type & $levels) && (empty($log[0]) || $replace || $log[0] === $this->bootstrappingLogger)) { - $log[0] = $logger; - $loggers[$type] = $log; - } - } - } - - $this->setLoggers($loggers); - } - - /** - * Sets a logger for each error level. - * - * @param array $loggers Error levels to [LoggerInterface|null, LogLevel::*] map - * - * @return array The previous map - * - * @throws \InvalidArgumentException - */ - public function setLoggers(array $loggers): array - { - $prevLogged = $this->loggedErrors; - $prev = $this->loggers; - $flush = []; - - foreach ($loggers as $type => $log) { - if (!isset($prev[$type])) { - throw new \InvalidArgumentException('Unknown error type: '.$type); - } - if (!\is_array($log)) { - $log = [$log]; - } elseif (!\array_key_exists(0, $log)) { - throw new \InvalidArgumentException('No logger provided.'); - } - if (null === $log[0]) { - $this->loggedErrors &= ~$type; - } elseif ($log[0] instanceof LoggerInterface) { - $this->loggedErrors |= $type; - } else { - throw new \InvalidArgumentException('Invalid logger provided.'); - } - $this->loggers[$type] = $log + $prev[$type]; - - if ($this->bootstrappingLogger && $prev[$type][0] === $this->bootstrappingLogger) { - $flush[$type] = $type; - } - } - $this->reRegister($prevLogged | $this->thrownErrors); - - if ($flush) { - foreach ($this->bootstrappingLogger->cleanLogs() as $log) { - $type = ThrowableUtils::getSeverity($log[2]['exception']); - if (!isset($flush[$type])) { - $this->bootstrappingLogger->log($log[0], $log[1], $log[2]); - } elseif ($this->loggers[$type][0]) { - $this->loggers[$type][0]->log($this->loggers[$type][1], $log[1], $log[2]); - } - } - } - - return $prev; - } - - /** - * Sets a user exception handler. - * - * @param callable(\Throwable $e)|null $handler - * - * @return callable|null The previous exception handler - */ - public function setExceptionHandler(?callable $handler): ?callable - { - $prev = $this->exceptionHandler; - $this->exceptionHandler = $handler; - - return $prev; - } - - /** - * Sets the PHP error levels that throw an exception when a PHP error occurs. - * - * @param int $levels A bit field of E_* constants for thrown errors - * @param bool $replace Replace or amend the previous value - * - * @return int The previous value - */ - public function throwAt(int $levels, bool $replace = false): int - { - $prev = $this->thrownErrors; - $this->thrownErrors = ($levels | \E_RECOVERABLE_ERROR | \E_USER_ERROR) & ~\E_USER_DEPRECATED & ~\E_DEPRECATED; - if (!$replace) { - $this->thrownErrors |= $prev; - } - $this->reRegister($prev | $this->loggedErrors); - - return $prev; - } - - /** - * Sets the PHP error levels for which local variables are preserved. - * - * @param int $levels A bit field of E_* constants for scoped errors - * @param bool $replace Replace or amend the previous value - * - * @return int The previous value - */ - public function scopeAt(int $levels, bool $replace = false): int - { - $prev = $this->scopedErrors; - $this->scopedErrors = $levels; - if (!$replace) { - $this->scopedErrors |= $prev; - } - - return $prev; - } - - /** - * Sets the PHP error levels for which the stack trace is preserved. - * - * @param int $levels A bit field of E_* constants for traced errors - * @param bool $replace Replace or amend the previous value - * - * @return int The previous value - */ - public function traceAt(int $levels, bool $replace = false): int - { - $prev = $this->tracedErrors; - $this->tracedErrors = $levels; - if (!$replace) { - $this->tracedErrors |= $prev; - } - - return $prev; - } - - /** - * Sets the error levels where the @-operator is ignored. - * - * @param int $levels A bit field of E_* constants for screamed errors - * @param bool $replace Replace or amend the previous value - * - * @return int The previous value - */ - public function screamAt(int $levels, bool $replace = false): int - { - $prev = $this->screamedErrors; - $this->screamedErrors = $levels; - if (!$replace) { - $this->screamedErrors |= $prev; - } - - return $prev; - } - - /** - * Re-registers as a PHP error handler if levels changed. - */ - private function reRegister(int $prev): void - { - if ($prev !== ($this->thrownErrors | $this->loggedErrors)) { - $handler = set_error_handler('is_int'); - $handler = \is_array($handler) ? $handler[0] : null; - restore_error_handler(); - if ($handler === $this) { - restore_error_handler(); - if ($this->isRoot) { - set_error_handler([$this, 'handleError'], $this->thrownErrors | $this->loggedErrors); - } else { - set_error_handler([$this, 'handleError']); - } - } - } - } - - /** - * Handles errors by filtering then logging them according to the configured bit fields. - * - * @return bool Returns false when no handling happens so that the PHP engine can handle the error itself - * - * @throws \ErrorException When $this->thrownErrors requests so - * - * @internal - */ - public function handleError(int $type, string $message, string $file, int $line): bool - { - if (\PHP_VERSION_ID >= 70300 && \E_WARNING === $type && '"' === $message[0] && false !== strpos($message, '" targeting switch is equivalent to "break')) { - $type = \E_DEPRECATED; - } - - // Level is the current error reporting level to manage silent error. - $level = error_reporting(); - $silenced = 0 === ($level & $type); - // Strong errors are not authorized to be silenced. - $level |= \E_RECOVERABLE_ERROR | \E_USER_ERROR | \E_DEPRECATED | \E_USER_DEPRECATED; - $log = $this->loggedErrors & $type; - $throw = $this->thrownErrors & $type & $level; - $type &= $level | $this->screamedErrors; - - // Never throw on warnings triggered by assert() - if (\E_WARNING === $type && 'a' === $message[0] && 0 === strncmp($message, 'assert(): ', 10)) { - $throw = 0; - } - - if (!$type || (!$log && !$throw)) { - return false; - } - - $logMessage = $this->levels[$type].': '.$message; - - if (null !== self::$toStringException) { - $errorAsException = self::$toStringException; - self::$toStringException = null; - } elseif (!$throw && !($type & $level)) { - if (!isset(self::$silencedErrorCache[$id = $file.':'.$line])) { - $lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 5), $type, $file, $line, false) : []; - $errorAsException = new SilencedErrorContext($type, $file, $line, isset($lightTrace[1]) ? [$lightTrace[0]] : $lightTrace); - } elseif (isset(self::$silencedErrorCache[$id][$message])) { - $lightTrace = null; - $errorAsException = self::$silencedErrorCache[$id][$message]; - ++$errorAsException->count; - } else { - $lightTrace = []; - $errorAsException = null; - } - - if (100 < ++self::$silencedErrorCount) { - self::$silencedErrorCache = $lightTrace = []; - self::$silencedErrorCount = 1; - } - if ($errorAsException) { - self::$silencedErrorCache[$id][$message] = $errorAsException; - } - if (null === $lightTrace) { - return true; - } - } else { - if (false !== strpos($message, '@anonymous')) { - $backtrace = debug_backtrace(false, 5); - - for ($i = 1; isset($backtrace[$i]); ++$i) { - if (isset($backtrace[$i]['function'], $backtrace[$i]['args'][0]) - && ('trigger_error' === $backtrace[$i]['function'] || 'user_error' === $backtrace[$i]['function']) - ) { - if ($backtrace[$i]['args'][0] !== $message) { - $message = $this->parseAnonymousClass($backtrace[$i]['args'][0]); - $logMessage = $this->levels[$type].': '.$message; - } - - break; - } - } - } - - $errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line); - - if ($throw || $this->tracedErrors & $type) { - $backtrace = $errorAsException->getTrace(); - $lightTrace = $this->cleanTrace($backtrace, $type, $file, $line, $throw); - ($this->configureException)($errorAsException, $lightTrace, $file, $line); - } else { - ($this->configureException)($errorAsException, []); - $backtrace = []; - } - } - - if ($throw) { - if (\PHP_VERSION_ID < 70400 && \E_USER_ERROR & $type) { - for ($i = 1; isset($backtrace[$i]); ++$i) { - if (isset($backtrace[$i]['function'], $backtrace[$i]['type'], $backtrace[$i - 1]['function']) - && '__toString' === $backtrace[$i]['function'] - && '->' === $backtrace[$i]['type'] - && !isset($backtrace[$i - 1]['class']) - && ('trigger_error' === $backtrace[$i - 1]['function'] || 'user_error' === $backtrace[$i - 1]['function']) - ) { - // Here, we know trigger_error() has been called from __toString(). - // PHP triggers a fatal error when throwing from __toString(). - // A small convention allows working around the limitation: - // given a caught $e exception in __toString(), quitting the method with - // `return trigger_error($e, E_USER_ERROR);` allows this error handler - // to make $e get through the __toString() barrier. - - $context = 4 < \func_num_args() ? (func_get_arg(4) ?: []) : []; - - foreach ($context as $e) { - if ($e instanceof \Throwable && $e->__toString() === $message) { - self::$toStringException = $e; - - return true; - } - } - - // Display the original error message instead of the default one. - $this->handleException($errorAsException); - - // Stop the process by giving back the error to the native handler. - return false; - } - } - } - - throw $errorAsException; - } - - if ($this->isRecursive) { - $log = 0; - } else { - if (\PHP_VERSION_ID < (\PHP_VERSION_ID < 70400 ? 70316 : 70404)) { - $currentErrorHandler = set_error_handler('is_int'); - restore_error_handler(); - } - - try { - $this->isRecursive = true; - $level = ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG; - $this->loggers[$type][0]->log($level, $logMessage, $errorAsException ? ['exception' => $errorAsException] : []); - } finally { - $this->isRecursive = false; - - if (\PHP_VERSION_ID < (\PHP_VERSION_ID < 70400 ? 70316 : 70404)) { - set_error_handler($currentErrorHandler); - } - } - } - - return !$silenced && $type && $log; - } - - /** - * Handles an exception by logging then forwarding it to another handler. - * - * @internal - */ - public function handleException(\Throwable $exception) - { - $handlerException = null; - - if (!$exception instanceof FatalError) { - self::$exitCode = 255; - - $type = ThrowableUtils::getSeverity($exception); - } else { - $type = $exception->getError()['type']; - } - - if ($this->loggedErrors & $type) { - if (false !== strpos($message = $exception->getMessage(), "@anonymous\0")) { - $message = $this->parseAnonymousClass($message); - } - - if ($exception instanceof FatalError) { - $message = 'Fatal '.$message; - } elseif ($exception instanceof \Error) { - $message = 'Uncaught Error: '.$message; - } elseif ($exception instanceof \ErrorException) { - $message = 'Uncaught '.$message; - } else { - $message = 'Uncaught Exception: '.$message; - } - - try { - $this->loggers[$type][0]->log($this->loggers[$type][1], $message, ['exception' => $exception]); - } catch (\Throwable $handlerException) { - } - } - - if (!$exception instanceof OutOfMemoryError) { - foreach ($this->getErrorEnhancers() as $errorEnhancer) { - if ($e = $errorEnhancer->enhance($exception)) { - $exception = $e; - break; - } - } - } - - $exceptionHandler = $this->exceptionHandler; - $this->exceptionHandler = [$this, 'renderException']; - - if (null === $exceptionHandler || $exceptionHandler === $this->exceptionHandler) { - $this->exceptionHandler = null; - } - - try { - if (null !== $exceptionHandler) { - return $exceptionHandler($exception); - } - $handlerException = $handlerException ?: $exception; - } catch (\Throwable $handlerException) { - } - if ($exception === $handlerException && null === $this->exceptionHandler) { - self::$reservedMemory = null; // Disable the fatal error handler - throw $exception; // Give back $exception to the native handler - } - - $loggedErrors = $this->loggedErrors; - if ($exception === $handlerException) { - $this->loggedErrors &= ~$type; - } - - try { - $this->handleException($handlerException); - } finally { - $this->loggedErrors = $loggedErrors; - } - } - - /** - * Shutdown registered function for handling PHP fatal errors. - * - * @param array|null $error An array as returned by error_get_last() - * - * @internal - */ - public static function handleFatalError(array $error = null): void - { - if (null === self::$reservedMemory) { - return; - } - - $handler = self::$reservedMemory = null; - $handlers = []; - $previousHandler = null; - $sameHandlerLimit = 10; - - while (!\is_array($handler) || !$handler[0] instanceof self) { - $handler = set_exception_handler('is_int'); - restore_exception_handler(); - - if (!$handler) { - break; - } - restore_exception_handler(); - - if ($handler !== $previousHandler) { - array_unshift($handlers, $handler); - $previousHandler = $handler; - } elseif (0 === --$sameHandlerLimit) { - $handler = null; - break; - } - } - foreach ($handlers as $h) { - set_exception_handler($h); - } - if (!$handler) { - return; - } - if ($handler !== $h) { - $handler[0]->setExceptionHandler($h); - } - $handler = $handler[0]; - $handlers = []; - - if ($exit = null === $error) { - $error = error_get_last(); - } - - if ($error && $error['type'] &= \E_PARSE | \E_ERROR | \E_CORE_ERROR | \E_COMPILE_ERROR) { - // Let's not throw anymore but keep logging - $handler->throwAt(0, true); - $trace = $error['backtrace'] ?? null; - - if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) { - $fatalError = new OutOfMemoryError($handler->levels[$error['type']].': '.$error['message'], 0, $error, 2, false, $trace); - } else { - $fatalError = new FatalError($handler->levels[$error['type']].': '.$error['message'], 0, $error, 2, true, $trace); - } - } else { - $fatalError = null; - } - - try { - if (null !== $fatalError) { - self::$exitCode = 255; - $handler->handleException($fatalError); - } - } catch (FatalError $e) { - // Ignore this re-throw - } - - if ($exit && self::$exitCode) { - $exitCode = self::$exitCode; - register_shutdown_function('register_shutdown_function', function () use ($exitCode) { exit($exitCode); }); - } - } - - /** - * Renders the given exception. - * - * As this method is mainly called during boot where nothing is yet available, - * the output is always either HTML or CLI depending where PHP runs. - */ - private function renderException(\Throwable $exception): void - { - $renderer = \in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? new CliErrorRenderer() : new HtmlErrorRenderer($this->debug); - - $exception = $renderer->render($exception); - - if (!headers_sent()) { - http_response_code($exception->getStatusCode()); - - foreach ($exception->getHeaders() as $name => $value) { - header($name.': '.$value, false); - } - } - - echo $exception->getAsString(); - } - - /** - * Override this method if you want to define more error enhancers. - * - * @return ErrorEnhancerInterface[] - */ - protected function getErrorEnhancers(): iterable - { - return [ - new UndefinedFunctionErrorEnhancer(), - new UndefinedMethodErrorEnhancer(), - new ClassNotFoundErrorEnhancer(), - ]; - } - - /** - * Cleans the trace by removing function arguments and the frames added by the error handler and DebugClassLoader. - */ - private function cleanTrace(array $backtrace, int $type, string &$file, int &$line, bool $throw): array - { - $lightTrace = $backtrace; - - for ($i = 0; isset($backtrace[$i]); ++$i) { - if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { - $lightTrace = \array_slice($lightTrace, 1 + $i); - break; - } - } - if (\E_USER_DEPRECATED === $type) { - for ($i = 0; isset($lightTrace[$i]); ++$i) { - if (!isset($lightTrace[$i]['file'], $lightTrace[$i]['line'], $lightTrace[$i]['function'])) { - continue; - } - if (!isset($lightTrace[$i]['class']) && 'trigger_deprecation' === $lightTrace[$i]['function']) { - $file = $lightTrace[$i]['file']; - $line = $lightTrace[$i]['line']; - $lightTrace = \array_slice($lightTrace, 1 + $i); - break; - } - } - } - if (class_exists(DebugClassLoader::class, false)) { - for ($i = \count($lightTrace) - 2; 0 < $i; --$i) { - if (DebugClassLoader::class === ($lightTrace[$i]['class'] ?? null)) { - array_splice($lightTrace, --$i, 2); - } - } - } - if (!($throw || $this->scopedErrors & $type)) { - for ($i = 0; isset($lightTrace[$i]); ++$i) { - unset($lightTrace[$i]['args'], $lightTrace[$i]['object']); - } - } - - return $lightTrace; - } - - /** - * Parse the error message by removing the anonymous class notation - * and using the parent class instead if possible. - */ - private function parseAnonymousClass(string $message): string - { - return preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', static function ($m) { - return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0]; - }, $message); - } -} diff --git a/lib/symfony/error-handler/ErrorRenderer/CliErrorRenderer.php b/lib/symfony/error-handler/ErrorRenderer/CliErrorRenderer.php deleted file mode 100644 index 5c0f6a7dc..000000000 --- a/lib/symfony/error-handler/ErrorRenderer/CliErrorRenderer.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\ErrorRenderer; - -use Symfony\Component\ErrorHandler\Exception\FlattenException; -use Symfony\Component\VarDumper\Cloner\VarCloner; -use Symfony\Component\VarDumper\Dumper\CliDumper; - -// Help opcache.preload discover always-needed symbols -class_exists(CliDumper::class); - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class CliErrorRenderer implements ErrorRendererInterface -{ - /** - * {@inheritdoc} - */ - public function render(\Throwable $exception): FlattenException - { - $cloner = new VarCloner(); - $dumper = new class() extends CliDumper { - protected function supportsColors(): bool - { - $outputStream = $this->outputStream; - $this->outputStream = fopen('php://stdout', 'w'); - - try { - return parent::supportsColors(); - } finally { - $this->outputStream = $outputStream; - } - } - }; - - return FlattenException::createFromThrowable($exception) - ->setAsString($dumper->dump($cloner->cloneVar($exception), true)); - } -} diff --git a/lib/symfony/error-handler/ErrorRenderer/ErrorRendererInterface.php b/lib/symfony/error-handler/ErrorRenderer/ErrorRendererInterface.php deleted file mode 100644 index aba196603..000000000 --- a/lib/symfony/error-handler/ErrorRenderer/ErrorRendererInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\ErrorRenderer; - -use Symfony\Component\ErrorHandler\Exception\FlattenException; - -/** - * Formats an exception to be used as response content. - * - * @author Yonel Ceruto <yonelceruto@gmail.com> - */ -interface ErrorRendererInterface -{ - /** - * Renders a Throwable as a FlattenException. - */ - public function render(\Throwable $exception): FlattenException; -} diff --git a/lib/symfony/error-handler/ErrorRenderer/HtmlErrorRenderer.php b/lib/symfony/error-handler/ErrorRenderer/HtmlErrorRenderer.php deleted file mode 100644 index b8a9aeda6..000000000 --- a/lib/symfony/error-handler/ErrorRenderer/HtmlErrorRenderer.php +++ /dev/null @@ -1,367 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\ErrorRenderer; - -use Psr\Log\LoggerInterface; -use Symfony\Component\ErrorHandler\Exception\FlattenException; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; -use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; - -/** - * @author Yonel Ceruto <yonelceruto@gmail.com> - */ -class HtmlErrorRenderer implements ErrorRendererInterface -{ - private const GHOST_ADDONS = [ - '02-14' => self::GHOST_HEART, - '02-29' => self::GHOST_PLUS, - '10-18' => self::GHOST_GIFT, - ]; - - private const GHOST_GIFT = 'M124.00534057617188,5.3606138080358505 C124.40059661865234,4.644828304648399 125.1237564086914,3.712414965033531 123.88127899169922,3.487462028861046 C123.53517150878906,3.3097832053899765 123.18894958496094,2.9953975528478622 122.8432846069336,3.345616325736046 C122.07421112060547,3.649444565176964 121.40750122070312,4.074306473135948 122.2164306640625,4.869479164481163 C122.57514953613281,5.3830065578222275 122.90142822265625,6.503447040915489 123.3077621459961,6.626829609274864 C123.55027770996094,6.210384353995323 123.7774658203125,5.785196766257286 124.00534057617188,5.3606138080358505 zM122.30630493164062,7.336987480521202 C121.60028076171875,6.076864704489708 121.03211975097656,4.72498320043087 120.16796875,3.562500938773155 C119.11695098876953,2.44033907353878 117.04605865478516,2.940566048026085 116.57544708251953,4.387995228171349 C115.95028686523438,5.819030746817589 117.2991714477539,7.527640804648399 118.826171875,7.348545059561729 C119.98493194580078,7.367936596274376 121.15027618408203,7.420116886496544 122.30630493164062,7.336987480521202 zM128.1732177734375,7.379541382193565 C129.67486572265625,7.17823551595211 130.53842163085938,5.287807449698448 129.68344116210938,4.032590612769127 C128.92578125,2.693056806921959 126.74605560302734,2.6463639587163925 125.98509216308594,4.007616028189659 C125.32617950439453,5.108129009604454 124.75428009033203,6.258124336600304 124.14962768554688,7.388818249106407 C125.48638916015625,7.465229496359825 126.8357162475586,7.447416767477989 128.1732177734375,7.379541382193565 zM130.6601104736328,8.991325363516808 C131.17202758789062,8.540884003043175 133.1543731689453,8.009847149252892 131.65304565429688,7.582054600119591 C131.2811279296875,7.476506695151329 130.84751892089844,6.99234913289547 130.5132598876953,7.124847874045372 C129.78744506835938,8.02728746831417 128.67140197753906,8.55669592320919 127.50616455078125,8.501235947012901 C127.27806091308594,8.576229080557823 126.11459350585938,8.38720129430294 126.428955078125,8.601900085806847 C127.25099182128906,9.070617660880089 128.0523223876953,9.579657539725304 128.902587890625,9.995706543326378 C129.49813842773438,9.678531631827354 130.0761260986328,9.329126343131065 130.6601104736328,8.991325363516808 zM118.96446990966797,9.246344551444054 C119.4022445678711,8.991325363516808 119.84001922607422,8.736305221915245 120.27779388427734,8.481284126639366 C118.93965911865234,8.414779648184776 117.40827941894531,8.607666000723839 116.39698791503906,7.531384453177452 C116.11186981201172,7.212117180228233 115.83845520019531,6.846597656607628 115.44329071044922,7.248530372977257 C114.96995544433594,7.574637398123741 113.5140609741211,7.908811077475548 114.63501739501953,8.306883797049522 C115.61112976074219,8.883499130606651 116.58037567138672,9.474181160330772 117.58061218261719,10.008124336600304 C118.05723571777344,9.784612640738487 118.50651550292969,9.5052699893713 118.96446990966797,9.246344551444054 zM125.38018035888672,12.091858848929405 C125.9474868774414,11.636047348380089 127.32159423828125,11.201767906546593 127.36749267578125,10.712632164359093 C126.08487701416016,9.974547371268272 124.83960723876953,9.152772888541222 123.49772644042969,8.528907760977745 C123.03594207763672,8.353693947196007 122.66152954101562,8.623294815421104 122.28982543945312,8.857431396842003 C121.19065856933594,9.51122473180294 120.06505584716797,10.12446115911007 119.00167083740234,10.835315689444542 C120.39238739013672,11.69529627263546 121.79983520507812,12.529837593436241 123.22095489501953,13.338589653372765 C123.94580841064453,12.932025894522667 124.66128540039062,12.508862480521202 125.38018035888672,12.091858848929405 zM131.07164001464844,13.514615997672081 C131.66018676757812,13.143282875418663 132.2487335205078,12.771927818655968 132.8372802734375,12.400571808218956 C132.8324737548828,11.156818374991417 132.8523406982422,9.912529930472374 132.81829833984375,8.669195160269737 C131.63046264648438,9.332009300589561 130.45948791503906,10.027913078665733 129.30828857421875,10.752535805106163 C129.182373046875,12.035354599356651 129.24623107910156,13.33940313756466 129.27359008789062,14.628684982657433 C129.88104248046875,14.27079389989376 130.4737548828125,13.888019546866417 131.07164001464844,13.514640793204308 zM117.26847839355469,12.731024727225304 C117.32825469970703,11.67083452641964 117.45709991455078,10.46224020421505 116.17853546142578,10.148179039359093 C115.37110900878906,9.77159021794796 114.25194549560547,8.806716904044151 113.62991333007812,8.81639002263546 C113.61052703857422,10.0110072940588 113.62078857421875,11.20585821568966 113.61869049072266,12.400571808218956 C114.81139373779297,13.144886955618858 115.98292541503906,13.925040230154991 117.20137023925781,14.626662239432335 C117.31951141357422,14.010867103934288 117.24227905273438,13.35805033147335 117.26847839355469,12.731024727225304 zM125.80937957763672,16.836034759879112 C126.51483917236328,16.390663132071495 127.22030639648438,15.945291504263878 127.92576599121094,15.49991987645626 C127.92250061035156,14.215868934988976 127.97560119628906,12.929980263113976 127.91757202148438,11.647302612662315 C127.14225769042969,11.869626984000206 126.25550079345703,12.556857094168663 125.43866729736328,12.983742699027061 C124.82704162597656,13.342005714774132 124.21542358398438,13.700271591544151 123.60379028320312,14.05853746831417 C123.61585235595703,15.429577812552452 123.57081604003906,16.803131088614464 123.64839172363281,18.172149643301964 C124.37957000732422,17.744937881827354 125.09130859375,17.284801468253136 125.80937957763672,16.836034759879112 zM122.8521499633789,16.115344032645226 C122.8521499633789,15.429741844534874 122.8521499633789,14.744139656424522 122.8521499633789,14.05853746831417 C121.43595123291016,13.230924591422081 120.02428436279297,12.395455345511436 118.60256958007812,11.577354416251183 C118.52394104003906,12.888403877615929 118.56887817382812,14.204405769705772 118.55702209472656,15.517732605338097 C119.97289276123047,16.4041957706213 121.37410736083984,17.314891800284386 122.80789947509766,18.172149643301964 C122.86368560791016,17.488990768790245 122.84332275390625,16.800363525748253 122.8521499633789,16.115344032645226 zM131.10684204101562,18.871450409293175 C131.68399047851562,18.48711584508419 132.2611541748047,18.10278509557247 132.8383026123047,17.718475326895714 C132.81423950195312,16.499977096915245 132.89776611328125,15.264989838004112 132.77627563476562,14.05993078649044 C131.5760040283203,14.744719490408897 130.41763305664062,15.524359688162804 129.23875427246094,16.255397781729698 C129.26707458496094,17.516149505972862 129.18060302734375,18.791316971182823 129.3108367919922,20.041303619742393 C129.91973876953125,19.667551025748253 130.51010131835938,19.264152511954308 131.10684204101562,18.871450409293175 zM117.2557373046875,18.188333496451378 C117.25104522705078,17.549470886588097 117.24633026123047,16.91058538854122 117.24163055419922,16.271720871329308 C116.04924774169922,15.525708183646202 114.87187957763672,14.75476549565792 113.66158294677734,14.038097366690636 C113.5858383178711,15.262084946036339 113.62901306152344,16.49083898961544 113.61761474609375,17.717010483145714 C114.82051086425781,18.513254150748253 116.00987243652344,19.330610260367393 117.22888946533203,20.101993545889854 C117.27559661865234,19.466014847159386 117.25241088867188,18.825733169913292 117.2557373046875,18.188333496451378 zM125.8398666381836,22.38675306737423 C126.54049682617188,21.921453461050987 127.24110412597656,21.456151947379112 127.94172668457031,20.99083136022091 C127.94009399414062,19.693386062979698 127.96646118164062,18.395381912589073 127.93160247802734,17.098379120230675 C126.50540924072266,17.97775076329708 125.08877563476562,18.873308166861534 123.68258666992188,19.78428266942501 C123.52366638183594,21.03710363805294 123.626708984375,22.32878302037716 123.62647247314453,23.595300659537315 C124.06291198730469,23.86113165318966 125.1788101196289,22.68297766149044 125.8398666381836,22.38675306737423 zM122.8521499633789,21.83134649693966 C122.76741790771484,20.936696991324425 123.21651458740234,19.67745779454708 122.0794677734375,19.330633148550987 C120.93280029296875,18.604360565543175 119.7907485961914,17.870157226920128 118.62899780273438,17.16818617284298 C118.45966339111328,18.396427139639854 118.63676452636719,19.675991043448448 118.50668334960938,20.919256195425987 C119.89984130859375,21.92635916173458 121.32942199707031,22.88914106786251 122.78502655029297,23.803510650992393 C122.90177917480469,23.1627406924963 122.82917022705078,22.48402212560177 122.8521499633789,21.83134649693966 zM117.9798355102539,21.59483526647091 C116.28416442871094,20.46288488805294 114.58848571777344,19.330957397818565 112.892822265625,18.199007019400597 C112.89473724365234,14.705654129385948 112.84647369384766,11.211485847830772 112.90847778320312,7.718807205557823 C113.7575912475586,7.194885239005089 114.66117858886719,6.765397056937218 115.5350341796875,6.284702762961388 C114.97061157226562,4.668964847922325 115.78496551513672,2.7054970115423203 117.42159271240234,2.1007001250982285 C118.79354095458984,1.537783369421959 120.44731903076172,2.0457767099142075 121.32200622558594,3.23083733022213 C121.95732116699219,2.9050118774175644 122.59264373779297,2.5791852325201035 123.22796630859375,2.253336176276207 C123.86669921875,2.5821153968572617 124.50543975830078,2.9108948558568954 125.1441650390625,3.23967407643795 C126.05941009521484,2.154020771384239 127.62747192382812,1.5344576686620712 128.986328125,2.1429056972265244 C130.61741638183594,2.716217741370201 131.50650024414062,4.675290569663048 130.9215545654297,6.2884936183691025 C131.8018341064453,6.78548763692379 132.7589111328125,7.1738648265600204 133.5660400390625,7.780336365103722 C133.60182189941406,11.252970680594444 133.56637573242188,14.726140961050987 133.5631103515625,18.199007019400597 C130.18914794921875,20.431867584586143 126.86984252929688,22.74994657933712 123.44108581542969,24.897907242178917 C122.44406127929688,24.897628769278526 121.5834732055664,23.815067276358604 120.65831756591797,23.37616156041622 C119.76387023925781,22.784828171133995 118.87168884277344,22.19007681310177 117.9798355102539,21.59483526647091 z'; - private const GHOST_HEART = 'M125.91386369681868,8.305165958366445 C128.95033202169043,-0.40540639102854037 140.8469835342744,8.305165958366445 125.91386369681868,19.504526138305664 C110.98208663272044,8.305165958366445 122.87795231771452,-0.40540639102854037 125.91386369681868,8.305165958366445 z'; - private const GHOST_PLUS = 'M111.36824226379395,8.969108581542969 L118.69175148010254,8.969108581542969 L118.69175148010254,1.6455793380737305 L126.20429420471191,1.6455793380737305 L126.20429420471191,8.969108581542969 L133.52781105041504,8.969108581542969 L133.52781105041504,16.481630325317383 L126.20429420471191,16.481630325317383 L126.20429420471191,23.805158615112305 L118.69175148010254,23.805158615112305 L118.69175148010254,16.481630325317383 L111.36824226379395,16.481630325317383 z'; - - private $debug; - private $charset; - private $fileLinkFormat; - private $projectDir; - private $outputBuffer; - private $logger; - - private static $template = 'views/error.html.php'; - - /** - * @param bool|callable $debug The debugging mode as a boolean or a callable that should return it - * @param string|FileLinkFormatter|null $fileLinkFormat - * @param bool|callable $outputBuffer The output buffer as a string or a callable that should return it - */ - public function __construct($debug = false, string $charset = null, $fileLinkFormat = null, string $projectDir = null, $outputBuffer = '', LoggerInterface $logger = null) - { - if (!\is_bool($debug) && !\is_callable($debug)) { - throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a boolean or a callable, "%s" given.', __METHOD__, \gettype($debug))); - } - - if (!\is_string($outputBuffer) && !\is_callable($outputBuffer)) { - throw new \TypeError(sprintf('Argument 5 passed to "%s()" must be a string or a callable, "%s" given.', __METHOD__, \gettype($outputBuffer))); - } - - $this->debug = $debug; - $this->charset = $charset ?: (\ini_get('default_charset') ?: 'UTF-8'); - $this->fileLinkFormat = $fileLinkFormat ?: (\ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format')); - $this->projectDir = $projectDir; - $this->outputBuffer = $outputBuffer; - $this->logger = $logger; - } - - /** - * {@inheritdoc} - */ - public function render(\Throwable $exception): FlattenException - { - $headers = ['Content-Type' => 'text/html; charset='.$this->charset]; - if (\is_bool($this->debug) ? $this->debug : ($this->debug)($exception)) { - $headers['X-Debug-Exception'] = rawurlencode($exception->getMessage()); - $headers['X-Debug-Exception-File'] = rawurlencode($exception->getFile()).':'.$exception->getLine(); - } - - $exception = FlattenException::createFromThrowable($exception, null, $headers); - - return $exception->setAsString($this->renderException($exception)); - } - - /** - * Gets the HTML content associated with the given exception. - */ - public function getBody(FlattenException $exception): string - { - return $this->renderException($exception, 'views/exception.html.php'); - } - - /** - * Gets the stylesheet associated with the given exception. - */ - public function getStylesheet(): string - { - if (!$this->debug) { - return $this->include('assets/css/error.css'); - } - - return $this->include('assets/css/exception.css'); - } - - public static function isDebug(RequestStack $requestStack, bool $debug): \Closure - { - return static function () use ($requestStack, $debug): bool { - if (!$request = $requestStack->getCurrentRequest()) { - return $debug; - } - - return $debug && $request->attributes->getBoolean('showException', true); - }; - } - - public static function getAndCleanOutputBuffer(RequestStack $requestStack): \Closure - { - return static function () use ($requestStack): string { - if (!$request = $requestStack->getCurrentRequest()) { - return ''; - } - - $startObLevel = $request->headers->get('X-Php-Ob-Level', -1); - - if (ob_get_level() <= $startObLevel) { - return ''; - } - - Response::closeOutputBuffers($startObLevel + 1, true); - - return ob_get_clean(); - }; - } - - private function renderException(FlattenException $exception, string $debugTemplate = 'views/exception_full.html.php'): string - { - $debug = \is_bool($this->debug) ? $this->debug : ($this->debug)($exception); - $statusText = $this->escape($exception->getStatusText()); - $statusCode = $this->escape($exception->getStatusCode()); - - if (!$debug) { - return $this->include(self::$template, [ - 'statusText' => $statusText, - 'statusCode' => $statusCode, - ]); - } - - $exceptionMessage = $this->escape($exception->getMessage()); - - return $this->include($debugTemplate, [ - 'exception' => $exception, - 'exceptionMessage' => $exceptionMessage, - 'statusText' => $statusText, - 'statusCode' => $statusCode, - 'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null, - 'currentContent' => \is_string($this->outputBuffer) ? $this->outputBuffer : ($this->outputBuffer)(), - ]); - } - - /** - * Formats an array as a string. - */ - private function formatArgs(array $args): string - { - $result = []; - foreach ($args as $key => $item) { - if ('object' === $item[0]) { - $formattedValue = sprintf('<em>object</em>(%s)', $this->abbrClass($item[1])); - } elseif ('array' === $item[0]) { - $formattedValue = sprintf('<em>array</em>(%s)', \is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]); - } elseif ('null' === $item[0]) { - $formattedValue = '<em>null</em>'; - } elseif ('boolean' === $item[0]) { - $formattedValue = '<em>'.strtolower(var_export($item[1], true)).'</em>'; - } elseif ('resource' === $item[0]) { - $formattedValue = '<em>resource</em>'; - } else { - $formattedValue = str_replace("\n", '', $this->escape(var_export($item[1], true))); - } - - $result[] = \is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escape($key), $formattedValue); - } - - return implode(', ', $result); - } - - private function formatArgsAsText(array $args) - { - return strip_tags($this->formatArgs($args)); - } - - private function escape(string $string): string - { - return htmlspecialchars($string, \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset); - } - - private function abbrClass(string $class): string - { - $parts = explode('\\', $class); - $short = array_pop($parts); - - return sprintf('<abbr title="%s">%s</abbr>', $class, $short); - } - - private function getFileRelative(string $file): ?string - { - $file = str_replace('\\', '/', $file); - - if (null !== $this->projectDir && 0 === strpos($file, $this->projectDir)) { - return ltrim(substr($file, \strlen($this->projectDir)), '/'); - } - - return null; - } - - /** - * Returns the link for a given file/line pair. - * - * @return string|false - */ - private function getFileLink(string $file, int $line) - { - if ($fmt = $this->fileLinkFormat) { - return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line); - } - - return false; - } - - /** - * Formats a file path. - * - * @param string $file An absolute file path - * @param int $line The line number - * @param string $text Use this text for the link rather than the file path - */ - private function formatFile(string $file, int $line, string $text = null): string - { - $file = trim($file); - - if (null === $text) { - $text = $file; - if (null !== $rel = $this->getFileRelative($text)) { - $rel = explode('/', $rel, 2); - $text = sprintf('<abbr title="%s%2$s">%s</abbr>%s', $this->projectDir, $rel[0], '/'.($rel[1] ?? '')); - } - } - - if (0 < $line) { - $text .= ' at line '.$line; - } - - if (false !== $link = $this->getFileLink($file, $line)) { - return sprintf('<a href="%s" title="Click to open this file" class="file_link">%s</a>', $this->escape($link), $text); - } - - return $text; - } - - /** - * Returns an excerpt of a code file around the given line number. - * - * @param string $file A file path - * @param int $line The selected line number - * @param int $srcContext The number of displayed lines around or -1 for the whole file - */ - private function fileExcerpt(string $file, int $line, int $srcContext = 3): string - { - if (is_file($file) && is_readable($file)) { - // highlight_file could throw warnings - // see https://bugs.php.net/25725 - $code = @highlight_file($file, true); - // remove main code/span tags - $code = preg_replace('#^<code.*?>\s*<span.*?>(.*)</span>\s*</code>#s', '\\1', $code); - // split multiline spans - $code = preg_replace_callback('#<span ([^>]++)>((?:[^<]*+<br \/>)++[^<]*+)</span>#', function ($m) { - return "<span $m[1]>".str_replace('<br />', "</span><br /><span $m[1]>", $m[2]).'</span>'; - }, $code); - $content = explode('<br />', $code); - - $lines = []; - if (0 > $srcContext) { - $srcContext = \count($content); - } - - for ($i = max($line - $srcContext, 1), $max = min($line + $srcContext, \count($content)); $i <= $max; ++$i) { - $lines[] = '<li'.($i == $line ? ' class="selected"' : '').'><code>'.$this->fixCodeMarkup($content[$i - 1]).'</code></li>'; - } - - return '<ol start="'.max($line - $srcContext, 1).'">'.implode("\n", $lines).'</ol>'; - } - - return ''; - } - - private function fixCodeMarkup(string $line) - { - // </span> ending tag from previous line - $opening = strpos($line, '<span'); - $closing = strpos($line, '</span>'); - if (false !== $closing && (false === $opening || $closing < $opening)) { - $line = substr_replace($line, '', $closing, 7); - } - - // missing </span> tag at the end of line - $opening = strrpos($line, '<span'); - $closing = strrpos($line, '</span>'); - if (false !== $opening && (false === $closing || $closing < $opening)) { - $line .= '</span>'; - } - - return trim($line); - } - - private function formatFileFromText(string $text) - { - return preg_replace_callback('/in ("|&quot;)?(.+?)\1(?: +(?:on|at))? +line (\d+)/s', function ($match) { - return 'in '.$this->formatFile($match[2], $match[3]); - }, $text); - } - - private function formatLogMessage(string $message, array $context) - { - if ($context && false !== strpos($message, '{')) { - $replacements = []; - foreach ($context as $key => $val) { - if (\is_scalar($val)) { - $replacements['{'.$key.'}'] = $val; - } - } - - if ($replacements) { - $message = strtr($message, $replacements); - } - } - - return $this->escape($message); - } - - private function addElementToGhost(): string - { - if (!isset(self::GHOST_ADDONS[date('m-d')])) { - return ''; - } - - return '<path d="'.self::GHOST_ADDONS[date('m-d')].'" fill="#fff" fill-opacity="0.6"></path>'; - } - - private function include(string $name, array $context = []): string - { - extract($context, \EXTR_SKIP); - ob_start(); - - include is_file(\dirname(__DIR__).'/Resources/'.$name) ? \dirname(__DIR__).'/Resources/'.$name : $name; - - return trim(ob_get_clean()); - } - - /** - * Allows overriding the default non-debug template. - * - * @param string $template path to the custom template file to render - */ - public static function setTemplate(string $template): void - { - self::$template = $template; - } -} diff --git a/lib/symfony/error-handler/ErrorRenderer/SerializerErrorRenderer.php b/lib/symfony/error-handler/ErrorRenderer/SerializerErrorRenderer.php deleted file mode 100644 index cec8e4d41..000000000 --- a/lib/symfony/error-handler/ErrorRenderer/SerializerErrorRenderer.php +++ /dev/null @@ -1,94 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\ErrorRenderer; - -use Symfony\Component\ErrorHandler\Exception\FlattenException; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\Serializer\Exception\NotEncodableValueException; -use Symfony\Component\Serializer\SerializerInterface; - -/** - * Formats an exception using Serializer for rendering. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class SerializerErrorRenderer implements ErrorRendererInterface -{ - private $serializer; - private $format; - private $fallbackErrorRenderer; - private $debug; - - /** - * @param string|callable(FlattenException) $format The format as a string or a callable that should return it - * formats not supported by Request::getMimeTypes() should be given as mime types - * @param bool|callable $debug The debugging mode as a boolean or a callable that should return it - */ - public function __construct(SerializerInterface $serializer, $format, ErrorRendererInterface $fallbackErrorRenderer = null, $debug = false) - { - if (!\is_string($format) && !\is_callable($format)) { - throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be a string or a callable, "%s" given.', __METHOD__, \gettype($format))); - } - - if (!\is_bool($debug) && !\is_callable($debug)) { - throw new \TypeError(sprintf('Argument 4 passed to "%s()" must be a boolean or a callable, "%s" given.', __METHOD__, \gettype($debug))); - } - - $this->serializer = $serializer; - $this->format = $format; - $this->fallbackErrorRenderer = $fallbackErrorRenderer ?? new HtmlErrorRenderer(); - $this->debug = $debug; - } - - /** - * {@inheritdoc} - */ - public function render(\Throwable $exception): FlattenException - { - $headers = []; - $debug = \is_bool($this->debug) ? $this->debug : ($this->debug)($exception); - if ($debug) { - $headers['X-Debug-Exception'] = rawurlencode($exception->getMessage()); - $headers['X-Debug-Exception-File'] = rawurlencode($exception->getFile()).':'.$exception->getLine(); - } - - $flattenException = FlattenException::createFromThrowable($exception, null, $headers); - - try { - $format = \is_string($this->format) ? $this->format : ($this->format)($flattenException); - $headers = [ - 'Content-Type' => Request::getMimeTypes($format)[0] ?? $format, - 'Vary' => 'Accept', - ]; - - return $flattenException->setAsString($this->serializer->serialize($flattenException, $format, [ - 'exception' => $exception, - 'debug' => $debug, - ])) - ->setHeaders($flattenException->getHeaders() + $headers); - } catch (NotEncodableValueException $e) { - return $this->fallbackErrorRenderer->render($exception); - } - } - - public static function getPreferredFormat(RequestStack $requestStack): \Closure - { - return static function () use ($requestStack) { - if (!$request = $requestStack->getCurrentRequest()) { - throw new NotEncodableValueException(); - } - - return $request->getPreferredFormat(); - }; - } -} diff --git a/lib/symfony/error-handler/Exception/FlattenException.php b/lib/symfony/error-handler/Exception/FlattenException.php deleted file mode 100644 index 262dae62b..000000000 --- a/lib/symfony/error-handler/Exception/FlattenException.php +++ /dev/null @@ -1,427 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\Exception; - -use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; - -/** - * FlattenException wraps a PHP Error or Exception to be able to serialize it. - * - * Basically, this class removes all objects from the trace. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class FlattenException -{ - /** @var string */ - private $message; - - /** @var int|string */ - private $code; - - /** @var self|null */ - private $previous; - - /** @var array */ - private $trace; - - /** @var string */ - private $traceAsString; - - /** @var string */ - private $class; - - /** @var int */ - private $statusCode; - - /** @var string */ - private $statusText; - - /** @var array */ - private $headers; - - /** @var string */ - private $file; - - /** @var int */ - private $line; - - /** @var string|null */ - private $asString; - - /** - * @return static - */ - public static function create(\Exception $exception, int $statusCode = null, array $headers = []): self - { - return static::createFromThrowable($exception, $statusCode, $headers); - } - - /** - * @return static - */ - public static function createFromThrowable(\Throwable $exception, int $statusCode = null, array $headers = []): self - { - $e = new static(); - $e->setMessage($exception->getMessage()); - $e->setCode($exception->getCode()); - - if ($exception instanceof HttpExceptionInterface) { - $statusCode = $exception->getStatusCode(); - $headers = array_merge($headers, $exception->getHeaders()); - } elseif ($exception instanceof RequestExceptionInterface) { - $statusCode = 400; - } - - if (null === $statusCode) { - $statusCode = 500; - } - - if (class_exists(Response::class) && isset(Response::$statusTexts[$statusCode])) { - $statusText = Response::$statusTexts[$statusCode]; - } else { - $statusText = 'Whoops, looks like something went wrong.'; - } - - $e->setStatusText($statusText); - $e->setStatusCode($statusCode); - $e->setHeaders($headers); - $e->setTraceFromThrowable($exception); - $e->setClass(\get_class($exception)); - $e->setFile($exception->getFile()); - $e->setLine($exception->getLine()); - - $previous = $exception->getPrevious(); - - if ($previous instanceof \Throwable) { - $e->setPrevious(static::createFromThrowable($previous)); - } - - return $e; - } - - public function toArray(): array - { - $exceptions = []; - foreach (array_merge([$this], $this->getAllPrevious()) as $exception) { - $exceptions[] = [ - 'message' => $exception->getMessage(), - 'class' => $exception->getClass(), - 'trace' => $exception->getTrace(), - ]; - } - - return $exceptions; - } - - public function getStatusCode(): int - { - return $this->statusCode; - } - - /** - * @return $this - */ - public function setStatusCode(int $code): self - { - $this->statusCode = $code; - - return $this; - } - - public function getHeaders(): array - { - return $this->headers; - } - - /** - * @return $this - */ - public function setHeaders(array $headers): self - { - $this->headers = $headers; - - return $this; - } - - public function getClass(): string - { - return $this->class; - } - - /** - * @return $this - */ - public function setClass(string $class): self - { - $this->class = false !== strpos($class, "@anonymous\0") ? (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous' : $class; - - return $this; - } - - public function getFile(): string - { - return $this->file; - } - - /** - * @return $this - */ - public function setFile(string $file): self - { - $this->file = $file; - - return $this; - } - - public function getLine(): int - { - return $this->line; - } - - /** - * @return $this - */ - public function setLine(int $line): self - { - $this->line = $line; - - return $this; - } - - public function getStatusText(): string - { - return $this->statusText; - } - - /** - * @return $this - */ - public function setStatusText(string $statusText): self - { - $this->statusText = $statusText; - - return $this; - } - - public function getMessage(): string - { - return $this->message; - } - - /** - * @return $this - */ - public function setMessage(string $message): self - { - if (false !== strpos($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); - } - - $this->message = $message; - - return $this; - } - - /** - * @return int|string int most of the time (might be a string with PDOException) - */ - public function getCode() - { - return $this->code; - } - - /** - * @param int|string $code - * - * @return $this - */ - public function setCode($code): self - { - $this->code = $code; - - return $this; - } - - public function getPrevious(): ?self - { - return $this->previous; - } - - /** - * @return $this - */ - public function setPrevious(?self $previous): self - { - $this->previous = $previous; - - return $this; - } - - /** - * @return self[] - */ - public function getAllPrevious(): array - { - $exceptions = []; - $e = $this; - while ($e = $e->getPrevious()) { - $exceptions[] = $e; - } - - return $exceptions; - } - - public function getTrace(): array - { - return $this->trace; - } - - /** - * @return $this - */ - public function setTraceFromThrowable(\Throwable $throwable): self - { - $this->traceAsString = $throwable->getTraceAsString(); - - return $this->setTrace($throwable->getTrace(), $throwable->getFile(), $throwable->getLine()); - } - - /** - * @return $this - */ - public function setTrace(array $trace, ?string $file, ?int $line): self - { - $this->trace = []; - $this->trace[] = [ - 'namespace' => '', - 'short_class' => '', - 'class' => '', - 'type' => '', - 'function' => '', - 'file' => $file, - 'line' => $line, - 'args' => [], - ]; - foreach ($trace as $entry) { - $class = ''; - $namespace = ''; - if (isset($entry['class'])) { - $parts = explode('\\', $entry['class']); - $class = array_pop($parts); - $namespace = implode('\\', $parts); - } - - $this->trace[] = [ - 'namespace' => $namespace, - 'short_class' => $class, - 'class' => $entry['class'] ?? '', - 'type' => $entry['type'] ?? '', - 'function' => $entry['function'] ?? null, - 'file' => $entry['file'] ?? null, - 'line' => $entry['line'] ?? null, - 'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : [], - ]; - } - - return $this; - } - - private function flattenArgs(array $args, int $level = 0, int &$count = 0): array - { - $result = []; - foreach ($args as $key => $value) { - if (++$count > 1e4) { - return ['array', '*SKIPPED over 10000 entries*']; - } - if ($value instanceof \__PHP_Incomplete_Class) { - $result[$key] = ['incomplete-object', $this->getClassNameFromIncomplete($value)]; - } elseif (\is_object($value)) { - $result[$key] = ['object', \get_class($value)]; - } elseif (\is_array($value)) { - if ($level > 10) { - $result[$key] = ['array', '*DEEP NESTED ARRAY*']; - } else { - $result[$key] = ['array', $this->flattenArgs($value, $level + 1, $count)]; - } - } elseif (null === $value) { - $result[$key] = ['null', null]; - } elseif (\is_bool($value)) { - $result[$key] = ['boolean', $value]; - } elseif (\is_int($value)) { - $result[$key] = ['integer', $value]; - } elseif (\is_float($value)) { - $result[$key] = ['float', $value]; - } elseif (\is_resource($value)) { - $result[$key] = ['resource', get_resource_type($value)]; - } else { - $result[$key] = ['string', (string) $value]; - } - } - - return $result; - } - - private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value): string - { - $array = new \ArrayObject($value); - - return $array['__PHP_Incomplete_Class_Name']; - } - - public function getTraceAsString(): string - { - return $this->traceAsString; - } - - /** - * @return $this - */ - public function setAsString(?string $asString): self - { - $this->asString = $asString; - - return $this; - } - - public function getAsString(): string - { - if (null !== $this->asString) { - return $this->asString; - } - - $message = ''; - $next = false; - - foreach (array_reverse(array_merge([$this], $this->getAllPrevious())) as $exception) { - if ($next) { - $message .= 'Next '; - } else { - $next = true; - } - $message .= $exception->getClass(); - - if ('' != $exception->getMessage()) { - $message .= ': '.$exception->getMessage(); - } - - $message .= ' in '.$exception->getFile().':'.$exception->getLine(). - "\nStack trace:\n".$exception->getTraceAsString()."\n\n"; - } - - return rtrim($message); - } -} diff --git a/lib/symfony/error-handler/Exception/SilencedErrorContext.php b/lib/symfony/error-handler/Exception/SilencedErrorContext.php deleted file mode 100644 index 18defc72c..000000000 --- a/lib/symfony/error-handler/Exception/SilencedErrorContext.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\Exception; - -/** - * Data Object that represents a Silenced Error. - * - * @author Grégoire Pineau <lyrixx@lyrixx.info> - */ -class SilencedErrorContext implements \JsonSerializable -{ - public $count = 1; - - private $severity; - private $file; - private $line; - private $trace; - - public function __construct(int $severity, string $file, int $line, array $trace = [], int $count = 1) - { - $this->severity = $severity; - $this->file = $file; - $this->line = $line; - $this->trace = $trace; - $this->count = $count; - } - - public function getSeverity(): int - { - return $this->severity; - } - - public function getFile(): string - { - return $this->file; - } - - public function getLine(): int - { - return $this->line; - } - - public function getTrace(): array - { - return $this->trace; - } - - public function jsonSerialize(): array - { - return [ - 'severity' => $this->severity, - 'file' => $this->file, - 'line' => $this->line, - 'trace' => $this->trace, - 'count' => $this->count, - ]; - } -} diff --git a/lib/symfony/error-handler/Internal/TentativeTypes.php b/lib/symfony/error-handler/Internal/TentativeTypes.php deleted file mode 100644 index 2168a1c07..000000000 --- a/lib/symfony/error-handler/Internal/TentativeTypes.php +++ /dev/null @@ -1,1642 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\Internal; - -/** - * This class has been generated by extract-tentative-return-types.php. - * - * @internal - */ -class TentativeTypes -{ - public const RETURN_TYPES = [ - 'CURLFile' => [ - 'getFilename' => 'string', - 'getMimeType' => 'string', - 'getPostFilename' => 'string', - 'setMimeType' => 'void', - 'setPostFilename' => 'void', - ], - 'DateTimeInterface' => [ - 'format' => 'string', - 'getTimezone' => 'DateTimeZone|false', - 'getOffset' => 'int', - 'getTimestamp' => 'int', - 'diff' => 'DateInterval', - '__wakeup' => 'void', - ], - 'DateTime' => [ - '__wakeup' => 'void', - '__set_state' => 'DateTime', - 'createFromImmutable' => 'static', - 'createFromFormat' => 'DateTime|false', - 'getLastErrors' => 'array|false', - 'format' => 'string', - 'modify' => 'DateTime|false', - 'add' => 'DateTime', - 'sub' => 'DateTime', - 'getTimezone' => 'DateTimeZone|false', - 'setTimezone' => 'DateTime', - 'getOffset' => 'int', - 'setTime' => 'DateTime', - 'setDate' => 'DateTime', - 'setISODate' => 'DateTime', - 'setTimestamp' => 'DateTime', - 'getTimestamp' => 'int', - 'diff' => 'DateInterval', - ], - 'DateTimeImmutable' => [ - '__wakeup' => 'void', - '__set_state' => 'DateTimeImmutable', - 'createFromFormat' => 'DateTimeImmutable|false', - 'getLastErrors' => 'array|false', - 'format' => 'string', - 'getTimezone' => 'DateTimeZone|false', - 'getOffset' => 'int', - 'getTimestamp' => 'int', - 'diff' => 'DateInterval', - 'modify' => 'DateTimeImmutable|false', - 'add' => 'DateTimeImmutable', - 'sub' => 'DateTimeImmutable', - 'setTimezone' => 'DateTimeImmutable', - 'setTime' => 'DateTimeImmutable', - 'setDate' => 'DateTimeImmutable', - 'setISODate' => 'DateTimeImmutable', - 'setTimestamp' => 'DateTimeImmutable', - 'createFromMutable' => 'static', - ], - 'DateTimeZone' => [ - 'getName' => 'string', - 'getOffset' => 'int', - 'getTransitions' => 'array|false', - 'getLocation' => 'array|false', - 'listAbbreviations' => 'array', - 'listIdentifiers' => 'array', - '__wakeup' => 'void', - '__set_state' => 'DateTimeZone', - ], - 'DateInterval' => [ - 'createFromDateString' => 'DateInterval|false', - 'format' => 'string', - '__wakeup' => 'void', - '__set_state' => 'DateInterval', - ], - 'DatePeriod' => [ - 'getStartDate' => 'DateTimeInterface', - 'getEndDate' => '?DateTimeInterface', - 'getDateInterval' => 'DateInterval', - 'getRecurrences' => '?int', - '__wakeup' => 'void', - '__set_state' => 'DatePeriod', - ], - 'DOMNode' => [ - 'C14N' => 'string|false', - 'C14NFile' => 'int|false', - 'getLineNo' => 'int', - 'getNodePath' => '?string', - 'hasAttributes' => 'bool', - 'hasChildNodes' => 'bool', - 'isDefaultNamespace' => 'bool', - 'isSameNode' => 'bool', - 'isSupported' => 'bool', - 'lookupNamespaceURI' => '?string', - 'lookupPrefix' => '?string', - 'normalize' => 'void', - ], - 'DOMImplementation' => [ - 'getFeature' => 'never', - 'hasFeature' => 'bool', - ], - 'DOMDocumentFragment' => [ - 'appendXML' => 'bool', - ], - 'DOMNodeList' => [ - 'count' => 'int', - ], - 'DOMCharacterData' => [ - 'appendData' => 'bool', - 'insertData' => 'bool', - 'deleteData' => 'bool', - 'replaceData' => 'bool', - ], - 'DOMAttr' => [ - 'isId' => 'bool', - ], - 'DOMElement' => [ - 'getAttribute' => 'string', - 'getAttributeNS' => 'string', - 'getElementsByTagName' => 'DOMNodeList', - 'getElementsByTagNameNS' => 'DOMNodeList', - 'hasAttribute' => 'bool', - 'hasAttributeNS' => 'bool', - 'removeAttribute' => 'bool', - 'removeAttributeNS' => 'void', - 'setAttributeNS' => 'void', - 'setIdAttribute' => 'void', - 'setIdAttributeNS' => 'void', - 'setIdAttributeNode' => 'void', - ], - 'DOMDocument' => [ - 'createComment' => 'DOMComment', - 'createDocumentFragment' => 'DOMDocumentFragment', - 'createTextNode' => 'DOMText', - 'getElementById' => '?DOMElement', - 'getElementsByTagName' => 'DOMNodeList', - 'getElementsByTagNameNS' => 'DOMNodeList', - 'normalizeDocument' => 'void', - 'registerNodeClass' => 'bool', - 'save' => 'int|false', - 'saveHTML' => 'string|false', - 'saveHTMLFile' => 'int|false', - 'saveXML' => 'string|false', - 'schemaValidate' => 'bool', - 'schemaValidateSource' => 'bool', - 'relaxNGValidate' => 'bool', - 'relaxNGValidateSource' => 'bool', - 'validate' => 'bool', - 'xinclude' => 'int|false', - ], - 'DOMText' => [ - 'isWhitespaceInElementContent' => 'bool', - 'isElementContentWhitespace' => 'bool', - ], - 'DOMNamedNodeMap' => [ - 'getNamedItem' => '?DOMNode', - 'getNamedItemNS' => '?DOMNode', - 'item' => '?DOMNode', - 'count' => 'int', - ], - 'DOMXPath' => [ - 'evaluate' => 'mixed', - 'query' => 'mixed', - 'registerNamespace' => 'bool', - 'registerPhpFunctions' => 'void', - ], - 'finfo' => [ - 'file' => 'string|false', - 'buffer' => 'string|false', - ], - 'IntlPartsIterator' => [ - 'getBreakIterator' => 'IntlBreakIterator', - 'getRuleStatus' => 'int', - ], - 'IntlBreakIterator' => [ - 'createCharacterInstance' => '?IntlBreakIterator', - 'createCodePointInstance' => 'IntlCodePointBreakIterator', - 'createLineInstance' => '?IntlBreakIterator', - 'createSentenceInstance' => '?IntlBreakIterator', - 'createTitleInstance' => '?IntlBreakIterator', - 'createWordInstance' => '?IntlBreakIterator', - 'current' => 'int', - 'first' => 'int', - 'following' => 'int', - 'getErrorCode' => 'int', - 'getErrorMessage' => 'string', - 'getLocale' => 'string|false', - 'getPartsIterator' => 'IntlPartsIterator', - 'getText' => '?string', - 'isBoundary' => 'bool', - 'last' => 'int', - 'next' => 'int', - 'preceding' => 'int', - 'previous' => 'int', - 'setText' => '?bool', - ], - 'IntlRuleBasedBreakIterator' => [ - 'getBinaryRules' => 'string|false', - 'getRules' => 'string|false', - 'getRuleStatus' => 'int', - 'getRuleStatusVec' => 'array|false', - ], - 'IntlCodePointBreakIterator' => [ - 'getLastCodePoint' => 'int', - ], - 'IntlCalendar' => [ - 'createInstance' => '?IntlCalendar', - 'equals' => 'bool', - 'fieldDifference' => 'int|false', - 'add' => 'bool', - 'after' => 'bool', - 'before' => 'bool', - 'fromDateTime' => '?IntlCalendar', - 'get' => 'int|false', - 'getActualMaximum' => 'int|false', - 'getActualMinimum' => 'int|false', - 'getAvailableLocales' => 'array', - 'getDayOfWeekType' => 'int|false', - 'getErrorCode' => 'int|false', - 'getErrorMessage' => 'string|false', - 'getFirstDayOfWeek' => 'int|false', - 'getGreatestMinimum' => 'int|false', - 'getKeywordValuesForLocale' => 'IntlIterator|false', - 'getLeastMaximum' => 'int|false', - 'getLocale' => 'string|false', - 'getMaximum' => 'int|false', - 'getMinimalDaysInFirstWeek' => 'int|false', - 'getMinimum' => 'int|false', - 'getNow' => 'float', - 'getRepeatedWallTimeOption' => 'int', - 'getSkippedWallTimeOption' => 'int', - 'getTime' => 'float|false', - 'getTimeZone' => 'IntlTimeZone|false', - 'getType' => 'string', - 'getWeekendTransition' => 'int|false', - 'inDaylightTime' => 'bool', - 'isEquivalentTo' => 'bool', - 'isLenient' => 'bool', - 'isWeekend' => 'bool', - 'roll' => 'bool', - 'isSet' => 'bool', - 'setTime' => 'bool', - 'setTimeZone' => 'bool', - 'toDateTime' => 'DateTime|false', - ], - 'IntlGregorianCalendar' => [ - 'setGregorianChange' => 'bool', - 'getGregorianChange' => 'float', - 'isLeapYear' => 'bool', - ], - 'Collator' => [ - 'create' => '?Collator', - 'compare' => 'int|false', - 'sort' => 'bool', - 'sortWithSortKeys' => 'bool', - 'asort' => 'bool', - 'getAttribute' => 'int|false', - 'setAttribute' => 'bool', - 'getStrength' => 'int', - 'getLocale' => 'string|false', - 'getErrorCode' => 'int|false', - 'getErrorMessage' => 'string|false', - 'getSortKey' => 'string|false', - ], - 'IntlIterator' => [ - 'current' => 'mixed', - 'key' => 'mixed', - 'next' => 'void', - 'rewind' => 'void', - 'valid' => 'bool', - ], - 'UConverter' => [ - 'convert' => 'string|false', - 'fromUCallback' => 'string|int|array|null', - 'getAliases' => 'array|false|null', - 'getAvailable' => 'array', - 'getDestinationEncoding' => 'string|false|null', - 'getDestinationType' => 'int|false|null', - 'getErrorCode' => 'int', - 'getErrorMessage' => '?string', - 'getSourceEncoding' => 'string|false|null', - 'getSourceType' => 'int|false|null', - 'getStandards' => '?array', - 'getSubstChars' => 'string|false|null', - 'reasonText' => 'string', - 'setDestinationEncoding' => 'bool', - 'setSourceEncoding' => 'bool', - 'setSubstChars' => 'bool', - 'toUCallback' => 'string|int|array|null', - 'transcode' => 'string|false', - ], - 'IntlDateFormatter' => [ - 'create' => '?IntlDateFormatter', - 'getDateType' => 'int|false', - 'getTimeType' => 'int|false', - 'getCalendar' => 'int|false', - 'setCalendar' => 'bool', - 'getTimeZoneId' => 'string|false', - 'getCalendarObject' => 'IntlCalendar|false|null', - 'getTimeZone' => 'IntlTimeZone|false', - 'setTimeZone' => '?bool', - 'setPattern' => 'bool', - 'getPattern' => 'string|false', - 'getLocale' => 'string|false', - 'setLenient' => 'void', - 'isLenient' => 'bool', - 'format' => 'string|false', - 'formatObject' => 'string|false', - 'parse' => 'int|float|false', - 'localtime' => 'array|false', - 'getErrorCode' => 'int', - 'getErrorMessage' => 'string', - ], - 'NumberFormatter' => [ - 'create' => '?NumberFormatter', - 'format' => 'string|false', - 'parse' => 'int|float|false', - 'formatCurrency' => 'string|false', - 'parseCurrency' => 'float|false', - 'setAttribute' => 'bool', - 'getAttribute' => 'int|float|false', - 'setTextAttribute' => 'bool', - 'getTextAttribute' => 'string|false', - 'setSymbol' => 'bool', - 'getSymbol' => 'string|false', - 'setPattern' => 'bool', - 'getPattern' => 'string|false', - 'getLocale' => 'string|false', - 'getErrorCode' => 'int', - 'getErrorMessage' => 'string', - ], - 'Locale' => [ - 'getDefault' => 'string', - 'getPrimaryLanguage' => '?string', - 'getScript' => '?string', - 'getRegion' => '?string', - 'getKeywords' => 'array|false|null', - 'getDisplayScript' => 'string|false', - 'getDisplayRegion' => 'string|false', - 'getDisplayName' => 'string|false', - 'getDisplayLanguage' => 'string|false', - 'getDisplayVariant' => 'string|false', - 'composeLocale' => 'string|false', - 'parseLocale' => '?array', - 'getAllVariants' => '?array', - 'filterMatches' => '?bool', - 'lookup' => '?string', - 'canonicalize' => '?string', - 'acceptFromHttp' => 'string|false', - ], - 'MessageFormatter' => [ - 'create' => '?MessageFormatter', - 'format' => 'string|false', - 'formatMessage' => 'string|false', - 'parse' => 'array|false', - 'parseMessage' => 'array|false', - 'setPattern' => 'bool', - 'getPattern' => 'string|false', - 'getLocale' => 'string', - 'getErrorCode' => 'int', - 'getErrorMessage' => 'string', - ], - 'Normalizer' => [ - 'normalize' => 'string|false', - 'isNormalized' => 'bool', - 'getRawDecomposition' => '?string', - ], - 'ResourceBundle' => [ - 'create' => '?ResourceBundle', - 'get' => 'mixed', - 'count' => 'int', - 'getLocales' => 'array|false', - 'getErrorCode' => 'int', - 'getErrorMessage' => 'string', - ], - 'Spoofchecker' => [ - 'isSuspicious' => 'bool', - 'areConfusable' => 'bool', - 'setAllowedLocales' => 'void', - 'setChecks' => 'void', - 'setRestrictionLevel' => 'void', - ], - 'IntlTimeZone' => [ - 'countEquivalentIDs' => 'int|false', - 'createDefault' => 'IntlTimeZone', - 'createEnumeration' => 'IntlIterator|false', - 'createTimeZone' => '?IntlTimeZone', - 'createTimeZoneIDEnumeration' => 'IntlIterator|false', - 'fromDateTimeZone' => '?IntlTimeZone', - 'getCanonicalID' => 'string|false', - 'getDisplayName' => 'string|false', - 'getDSTSavings' => 'int', - 'getEquivalentID' => 'string|false', - 'getErrorCode' => 'int|false', - 'getErrorMessage' => 'string|false', - 'getGMT' => 'IntlTimeZone', - 'getID' => 'string|false', - 'getOffset' => 'bool', - 'getRawOffset' => 'int', - 'getRegion' => 'string|false', - 'getTZDataVersion' => 'string|false', - 'getUnknown' => 'IntlTimeZone', - 'getWindowsID' => 'string|false', - 'getIDForWindowsID' => 'string|false', - 'hasSameRules' => 'bool', - 'toDateTimeZone' => 'DateTimeZone|false', - 'useDaylightTime' => 'bool', - ], - 'Transliterator' => [ - 'create' => '?Transliterator', - 'createFromRules' => '?Transliterator', - 'createInverse' => '?Transliterator', - 'listIDs' => 'array|false', - 'transliterate' => 'string|false', - 'getErrorCode' => 'int|false', - 'getErrorMessage' => 'string|false', - ], - 'IntlChar' => [ - 'hasBinaryProperty' => '?bool', - 'charAge' => '?array', - 'charDigitValue' => '?int', - 'charDirection' => '?int', - 'charFromName' => '?int', - 'charMirror' => 'int|string|null', - 'charName' => '?string', - 'charType' => '?int', - 'chr' => '?string', - 'digit' => 'int|false|null', - 'enumCharNames' => '?bool', - 'enumCharTypes' => 'void', - 'foldCase' => 'int|string|null', - 'forDigit' => 'int', - 'getBidiPairedBracket' => 'int|string|null', - 'getBlockCode' => '?int', - 'getCombiningClass' => '?int', - 'getFC_NFKC_Closure' => 'string|false|null', - 'getIntPropertyMaxValue' => 'int', - 'getIntPropertyMinValue' => 'int', - 'getIntPropertyValue' => '?int', - 'getNumericValue' => '?float', - 'getPropertyEnum' => 'int', - 'getPropertyName' => 'string|false', - 'getPropertyValueEnum' => 'int', - 'getPropertyValueName' => 'string|false', - 'getUnicodeVersion' => 'array', - 'isalnum' => '?bool', - 'isalpha' => '?bool', - 'isbase' => '?bool', - 'isblank' => '?bool', - 'iscntrl' => '?bool', - 'isdefined' => '?bool', - 'isdigit' => '?bool', - 'isgraph' => '?bool', - 'isIDIgnorable' => '?bool', - 'isIDPart' => '?bool', - 'isIDStart' => '?bool', - 'isISOControl' => '?bool', - 'isJavaIDPart' => '?bool', - 'isJavaIDStart' => '?bool', - 'isJavaSpaceChar' => '?bool', - 'islower' => '?bool', - 'isMirrored' => '?bool', - 'isprint' => '?bool', - 'ispunct' => '?bool', - 'isspace' => '?bool', - 'istitle' => '?bool', - 'isUAlphabetic' => '?bool', - 'isULowercase' => '?bool', - 'isupper' => '?bool', - 'isUUppercase' => '?bool', - 'isUWhiteSpace' => '?bool', - 'isWhitespace' => '?bool', - 'isxdigit' => '?bool', - 'ord' => '?int', - 'tolower' => 'int|string|null', - 'totitle' => 'int|string|null', - 'toupper' => 'int|string|null', - ], - 'JsonSerializable' => [ - 'jsonSerialize' => 'mixed', - ], - 'mysqli' => [ - 'autocommit' => 'bool', - 'begin_transaction' => 'bool', - 'change_user' => 'bool', - 'character_set_name' => 'string', - 'commit' => 'bool', - 'connect' => 'bool', - 'dump_debug_info' => 'bool', - 'get_charset' => '?object', - 'get_client_info' => 'string', - 'get_connection_stats' => 'array', - 'get_server_info' => 'string', - 'get_warnings' => 'mysqli_warning|false', - 'kill' => 'bool', - 'multi_query' => 'bool', - 'more_results' => 'bool', - 'next_result' => 'bool', - 'ping' => 'bool', - 'poll' => 'int|false', - 'prepare' => 'mysqli_stmt|false', - 'query' => 'mysqli_result|bool', - 'real_connect' => 'bool', - 'real_escape_string' => 'string', - 'reap_async_query' => 'mysqli_result|bool', - 'escape_string' => 'string', - 'real_query' => 'bool', - 'release_savepoint' => 'bool', - 'rollback' => 'bool', - 'savepoint' => 'bool', - 'select_db' => 'bool', - 'set_charset' => 'bool', - 'options' => 'bool', - 'set_opt' => 'bool', - 'stat' => 'string|false', - 'stmt_init' => 'mysqli_stmt|false', - 'store_result' => 'mysqli_result|false', - 'thread_safe' => 'bool', - 'use_result' => 'mysqli_result|false', - 'refresh' => 'bool', - ], - 'mysqli_result' => [ - 'close' => 'void', - 'free' => 'void', - 'data_seek' => 'bool', - 'fetch_field' => 'object|false', - 'fetch_fields' => 'array', - 'fetch_field_direct' => 'object|false', - 'fetch_all' => 'array', - 'fetch_array' => 'array|null|false', - 'fetch_assoc' => 'array|null|false', - 'fetch_object' => 'object|null|false', - 'fetch_row' => 'array|null|false', - 'field_seek' => 'bool', - 'free_result' => 'void', - ], - 'mysqli_stmt' => [ - 'attr_get' => 'int', - 'attr_set' => 'bool', - 'bind_param' => 'bool', - 'bind_result' => 'bool', - 'data_seek' => 'void', - 'execute' => 'bool', - 'fetch' => '?bool', - 'get_warnings' => 'mysqli_warning|false', - 'result_metadata' => 'mysqli_result|false', - 'more_results' => 'bool', - 'next_result' => 'bool', - 'num_rows' => 'int|string', - 'send_long_data' => 'bool', - 'free_result' => 'void', - 'reset' => 'bool', - 'prepare' => 'bool', - 'store_result' => 'bool', - 'get_result' => 'mysqli_result|false', - ], - 'OCILob' => [ - 'save' => 'bool', - 'import' => 'bool', - 'saveFile' => 'bool', - 'load' => 'string|false', - 'read' => 'string|false', - 'eof' => 'bool', - 'tell' => 'int|false', - 'rewind' => 'bool', - 'seek' => 'bool', - 'size' => 'int|false', - 'write' => 'int|false', - 'append' => 'bool', - 'truncate' => 'bool', - 'erase' => 'int|false', - 'flush' => 'bool', - 'setBuffering' => 'bool', - 'getBuffering' => 'bool', - 'writeToFile' => 'bool', - 'export' => 'bool', - 'writeTemporary' => 'bool', - 'close' => 'bool', - 'free' => 'bool', - ], - 'OCICollection' => [ - 'free' => 'bool', - 'append' => 'bool', - 'getElem' => 'string|float|null|false', - 'assign' => 'bool', - 'assignElem' => 'bool', - 'size' => 'int|false', - 'max' => 'int|false', - 'trim' => 'bool', - ], - 'PDO' => [ - 'beginTransaction' => 'bool', - 'commit' => 'bool', - 'errorCode' => '?string', - 'errorInfo' => 'array', - 'exec' => 'int|false', - 'getAttribute' => 'mixed', - 'getAvailableDrivers' => 'array', - 'inTransaction' => 'bool', - 'lastInsertId' => 'string|false', - 'prepare' => 'PDOStatement|false', - 'query' => 'PDOStatement|false', - 'quote' => 'string|false', - 'rollBack' => 'bool', - 'setAttribute' => 'bool', - ], - 'PDOStatement' => [ - 'bindColumn' => 'bool', - 'bindParam' => 'bool', - 'bindValue' => 'bool', - 'closeCursor' => 'bool', - 'columnCount' => 'int', - 'debugDumpParams' => '?bool', - 'errorCode' => '?string', - 'errorInfo' => 'array', - 'execute' => 'bool', - 'fetch' => 'mixed', - 'fetchAll' => 'array', - 'fetchColumn' => 'mixed', - 'fetchObject' => 'object|false', - 'getAttribute' => 'mixed', - 'getColumnMeta' => 'array|false', - 'nextRowset' => 'bool', - 'rowCount' => 'int', - 'setAttribute' => 'bool', - ], - 'PDO_PGSql_Ext' => [ - 'pgsqlCopyFromArray' => 'bool', - 'pgsqlCopyFromFile' => 'bool', - 'pgsqlCopyToArray' => 'array|false', - 'pgsqlCopyToFile' => 'bool', - 'pgsqlLOBCreate' => 'string|false', - 'pgsqlLOBUnlink' => 'bool', - 'pgsqlGetNotify' => 'array|false', - 'pgsqlGetPid' => 'int', - ], - 'PDO_SQLite_Ext' => [ - 'sqliteCreateFunction' => 'bool', - 'sqliteCreateAggregate' => 'bool', - 'sqliteCreateCollation' => 'bool', - ], - 'Phar' => [ - 'addEmptyDir' => 'void', - 'addFile' => 'void', - 'addFromString' => 'void', - 'buildFromDirectory' => 'array', - 'buildFromIterator' => 'array', - 'compressFiles' => 'void', - 'compress' => '?Phar', - 'decompress' => '?Phar', - 'convertToExecutable' => '?Phar', - 'convertToData' => '?PharData', - 'count' => 'int', - 'extractTo' => 'bool', - 'getAlias' => '?string', - 'getPath' => 'string', - 'getMetadata' => 'mixed', - 'getModified' => 'bool', - 'getSignature' => 'array|false', - 'getStub' => 'string', - 'getVersion' => 'string', - 'hasMetadata' => 'bool', - 'isBuffering' => 'bool', - 'isCompressed' => 'int|false', - 'isFileFormat' => 'bool', - 'isWritable' => 'bool', - 'offsetExists' => 'bool', - 'offsetGet' => 'SplFileInfo', - 'offsetSet' => 'void', - 'offsetUnset' => 'void', - 'setAlias' => 'bool', - 'setDefaultStub' => 'bool', - 'setMetadata' => 'void', - 'setSignatureAlgorithm' => 'void', - 'startBuffering' => 'void', - 'stopBuffering' => 'void', - ], - 'PharData' => [ - 'addEmptyDir' => 'void', - 'addFile' => 'void', - 'addFromString' => 'void', - 'buildFromDirectory' => 'array', - 'buildFromIterator' => 'array', - 'compressFiles' => 'void', - 'compress' => '?PharData', - 'decompress' => '?PharData', - 'convertToExecutable' => '?Phar', - 'convertToData' => '?PharData', - 'count' => 'int', - 'extractTo' => 'bool', - 'getAlias' => '?string', - 'getPath' => 'string', - 'getMetadata' => 'mixed', - 'getModified' => 'bool', - 'getSignature' => 'array|false', - 'getStub' => 'string', - 'getVersion' => 'string', - 'hasMetadata' => 'bool', - 'isBuffering' => 'bool', - 'isCompressed' => 'int|false', - 'isFileFormat' => 'bool', - 'isWritable' => 'bool', - 'offsetExists' => 'bool', - 'offsetGet' => 'SplFileInfo', - 'offsetSet' => 'void', - 'offsetUnset' => 'void', - 'setAlias' => 'bool', - 'setDefaultStub' => 'bool', - 'setMetadata' => 'void', - 'setSignatureAlgorithm' => 'void', - 'startBuffering' => 'void', - 'stopBuffering' => 'void', - ], - 'PharFileInfo' => [ - 'chmod' => 'void', - 'getCompressedSize' => 'int', - 'getCRC32' => 'int', - 'getContent' => 'string', - 'getMetadata' => 'mixed', - 'getPharFlags' => 'int', - 'hasMetadata' => 'bool', - 'isCompressed' => 'bool', - 'isCRCChecked' => 'bool', - 'setMetadata' => 'void', - ], - 'Reflection' => [ - 'getModifierNames' => 'array', - ], - 'ReflectionFunctionAbstract' => [ - 'inNamespace' => 'bool', - 'isClosure' => 'bool', - 'isDeprecated' => 'bool', - 'isInternal' => 'bool', - 'isUserDefined' => 'bool', - 'isGenerator' => 'bool', - 'isVariadic' => 'bool', - 'isStatic' => 'bool', - 'getClosureThis' => '?object', - 'getClosureScopeClass' => '?ReflectionClass', - 'getDocComment' => 'string|false', - 'getEndLine' => 'int|false', - 'getExtension' => '?ReflectionExtension', - 'getExtensionName' => 'string|false', - 'getFileName' => 'string|false', - 'getName' => 'string', - 'getNamespaceName' => 'string', - 'getNumberOfParameters' => 'int', - 'getNumberOfRequiredParameters' => 'int', - 'getParameters' => 'array', - 'getShortName' => 'string', - 'getStartLine' => 'int|false', - 'getStaticVariables' => 'array', - 'returnsReference' => 'bool', - 'hasReturnType' => 'bool', - 'getReturnType' => '?ReflectionType', - ], - 'ReflectionFunction' => [ - 'isDisabled' => 'bool', - 'invoke' => 'mixed', - 'invokeArgs' => 'mixed', - 'getClosure' => 'Closure', - 'getExecutingLine' => 'int', - 'getExecutingFile' => 'string', - 'getTrace' => 'array', - 'getFunction' => 'ReflectionFunctionAbstract', - 'getThis' => '?object', - 'getExecutingGenerator' => 'Generator', - ], - 'ReflectionMethod' => [ - 'isPublic' => 'bool', - 'isPrivate' => 'bool', - 'isProtected' => 'bool', - 'isAbstract' => 'bool', - 'isFinal' => 'bool', - 'isConstructor' => 'bool', - 'isDestructor' => 'bool', - 'getClosure' => 'Closure', - 'getModifiers' => 'int', - 'invoke' => 'mixed', - 'invokeArgs' => 'mixed', - 'getDeclaringClass' => 'ReflectionClass', - 'getPrototype' => 'ReflectionMethod', - 'setAccessible' => 'void', - ], - 'ReflectionClass' => [ - 'getName' => 'string', - 'isInternal' => 'bool', - 'isUserDefined' => 'bool', - 'isAnonymous' => 'bool', - 'isInstantiable' => 'bool', - 'isCloneable' => 'bool', - 'getFileName' => 'string|false', - 'getStartLine' => 'int|false', - 'getEndLine' => 'int|false', - 'getDocComment' => 'string|false', - 'getConstructor' => '?ReflectionMethod', - 'hasMethod' => 'bool', - 'getMethod' => 'ReflectionMethod', - 'getMethods' => 'array', - 'hasProperty' => 'bool', - 'getProperty' => 'ReflectionProperty', - 'getProperties' => 'array', - 'hasConstant' => 'bool', - 'getConstants' => 'array', - 'getReflectionConstants' => 'array', - 'getConstant' => 'mixed', - 'getReflectionConstant' => 'ReflectionClassConstant|false', - 'getInterfaces' => 'array', - 'getInterfaceNames' => 'array', - 'isInterface' => 'bool', - 'getTraits' => 'array', - 'getTraitNames' => 'array', - 'getTraitAliases' => 'array', - 'isTrait' => 'bool', - 'isAbstract' => 'bool', - 'isFinal' => 'bool', - 'getModifiers' => 'int', - 'isInstance' => 'bool', - 'newInstance' => 'object', - 'newInstanceWithoutConstructor' => 'object', - 'newInstanceArgs' => '?object', - 'getParentClass' => 'ReflectionClass|false', - 'isSubclassOf' => 'bool', - 'getStaticProperties' => '?array', - 'getStaticPropertyValue' => 'mixed', - 'setStaticPropertyValue' => 'void', - 'getDefaultProperties' => 'array', - 'isIterable' => 'bool', - 'isIterateable' => 'bool', - 'implementsInterface' => 'bool', - 'getExtension' => '?ReflectionExtension', - 'getExtensionName' => 'string|false', - 'inNamespace' => 'bool', - 'getNamespaceName' => 'string', - 'getShortName' => 'string', - ], - 'ReflectionProperty' => [ - 'getName' => 'string', - 'getValue' => 'mixed', - 'setValue' => 'void', - 'isInitialized' => 'bool', - 'isPublic' => 'bool', - 'isPrivate' => 'bool', - 'isProtected' => 'bool', - 'isStatic' => 'bool', - 'isDefault' => 'bool', - 'getModifiers' => 'int', - 'getDeclaringClass' => 'ReflectionClass', - 'getDocComment' => 'string|false', - 'setAccessible' => 'void', - 'getType' => '?ReflectionType', - 'hasType' => 'bool', - 'getDefaultValue' => 'mixed', - ], - 'ReflectionClassConstant' => [ - 'getName' => 'string', - 'getValue' => 'mixed', - 'isPublic' => 'bool', - 'isPrivate' => 'bool', - 'isProtected' => 'bool', - 'getModifiers' => 'int', - 'getDeclaringClass' => 'ReflectionClass', - 'getDocComment' => 'string|false', - ], - 'ReflectionParameter' => [ - 'getName' => 'string', - 'isPassedByReference' => 'bool', - 'canBePassedByValue' => 'bool', - 'getDeclaringFunction' => 'ReflectionFunctionAbstract', - 'getDeclaringClass' => '?ReflectionClass', - 'getClass' => '?ReflectionClass', - 'hasType' => 'bool', - 'getType' => '?ReflectionType', - 'isArray' => 'bool', - 'isCallable' => 'bool', - 'allowsNull' => 'bool', - 'getPosition' => 'int', - 'isOptional' => 'bool', - 'isDefaultValueAvailable' => 'bool', - 'getDefaultValue' => 'mixed', - 'isDefaultValueConstant' => 'bool', - 'getDefaultValueConstantName' => '?string', - 'isVariadic' => 'bool', - ], - 'ReflectionType' => [ - 'allowsNull' => 'bool', - ], - 'ReflectionNamedType' => [ - 'getName' => 'string', - 'isBuiltin' => 'bool', - ], - 'ReflectionExtension' => [ - 'getName' => 'string', - 'getVersion' => '?string', - 'getFunctions' => 'array', - 'getConstants' => 'array', - 'getINIEntries' => 'array', - 'getClasses' => 'array', - 'getClassNames' => 'array', - 'getDependencies' => 'array', - 'info' => 'void', - 'isPersistent' => 'bool', - 'isTemporary' => 'bool', - ], - 'ReflectionZendExtension' => [ - 'getName' => 'string', - 'getVersion' => 'string', - 'getAuthor' => 'string', - 'getURL' => 'string', - 'getCopyright' => 'string', - ], - 'SessionHandlerInterface' => [ - 'open' => 'bool', - 'close' => 'bool', - 'read' => 'string|false', - 'write' => 'bool', - 'destroy' => 'bool', - 'gc' => 'int|false', - ], - 'SessionIdInterface' => [ - 'create_sid' => 'string', - ], - 'SessionUpdateTimestampHandlerInterface' => [ - 'validateId' => 'bool', - 'updateTimestamp' => 'bool', - ], - 'SessionHandler' => [ - 'open' => 'bool', - 'close' => 'bool', - 'read' => 'string|false', - 'write' => 'bool', - 'destroy' => 'bool', - 'gc' => 'int|false', - 'create_sid' => 'string', - ], - 'SimpleXMLElement' => [ - 'xpath' => 'array|null|false', - 'registerXPathNamespace' => 'bool', - 'asXML' => 'string|bool', - 'saveXML' => 'string|bool', - 'getNamespaces' => 'array', - 'getDocNamespaces' => 'array|false', - 'children' => '?SimpleXMLElement', - 'attributes' => '?SimpleXMLElement', - 'addChild' => '?SimpleXMLElement', - 'addAttribute' => 'void', - 'getName' => 'string', - 'count' => 'int', - 'rewind' => 'void', - 'valid' => 'bool', - 'current' => 'SimpleXMLElement', - 'key' => 'string', - 'next' => 'void', - 'hasChildren' => 'bool', - 'getChildren' => '?SimpleXMLElement', - ], - 'SNMP' => [ - 'close' => 'bool', - 'setSecurity' => 'bool', - 'get' => 'mixed', - 'getnext' => 'mixed', - 'walk' => 'array|false', - 'set' => 'bool', - 'getErrno' => 'int', - 'getError' => 'string', - ], - 'SoapServer' => [ - 'fault' => 'void', - 'addSoapHeader' => 'void', - 'setPersistence' => 'void', - 'setClass' => 'void', - 'setObject' => 'void', - 'getFunctions' => 'array', - 'addFunction' => 'void', - 'handle' => 'void', - ], - 'SoapClient' => [ - '__call' => 'mixed', - '__soapCall' => 'mixed', - '__getFunctions' => '?array', - '__getTypes' => '?array', - '__getLastRequest' => '?string', - '__getLastResponse' => '?string', - '__getLastRequestHeaders' => '?string', - '__getLastResponseHeaders' => '?string', - '__doRequest' => '?string', - '__setCookie' => 'void', - '__getCookies' => 'array', - '__setSoapHeaders' => 'bool', - '__setLocation' => '?string', - ], - 'ArrayObject' => [ - 'offsetExists' => 'bool', - 'offsetGet' => 'mixed', - 'offsetSet' => 'void', - 'offsetUnset' => 'void', - 'append' => 'void', - 'getArrayCopy' => 'array', - 'count' => 'int', - 'getFlags' => 'int', - 'setFlags' => 'void', - 'asort' => 'bool', - 'ksort' => 'bool', - 'uasort' => 'bool', - 'uksort' => 'bool', - 'natsort' => 'bool', - 'natcasesort' => 'bool', - 'unserialize' => 'void', - 'serialize' => 'string', - '__serialize' => 'array', - '__unserialize' => 'void', - 'getIterator' => 'Iterator', - 'exchangeArray' => 'array', - 'setIteratorClass' => 'void', - 'getIteratorClass' => 'string', - '__debugInfo' => 'array', - ], - 'ArrayIterator' => [ - 'offsetExists' => 'bool', - 'offsetGet' => 'mixed', - 'offsetSet' => 'void', - 'offsetUnset' => 'void', - 'append' => 'void', - 'getArrayCopy' => 'array', - 'count' => 'int', - 'getFlags' => 'int', - 'setFlags' => 'void', - 'asort' => 'bool', - 'ksort' => 'bool', - 'uasort' => 'bool', - 'uksort' => 'bool', - 'natsort' => 'bool', - 'natcasesort' => 'bool', - 'unserialize' => 'void', - 'serialize' => 'string', - '__serialize' => 'array', - '__unserialize' => 'void', - 'rewind' => 'void', - 'current' => 'mixed', - 'key' => 'string|int|null', - 'next' => 'void', - 'valid' => 'bool', - 'seek' => 'void', - '__debugInfo' => 'array', - ], - 'RecursiveArrayIterator' => [ - 'hasChildren' => 'bool', - 'getChildren' => '?RecursiveArrayIterator', - ], - 'SplFileInfo' => [ - 'getPath' => 'string', - 'getFilename' => 'string', - 'getExtension' => 'string', - 'getBasename' => 'string', - 'getPathname' => 'string', - 'getPerms' => 'int|false', - 'getInode' => 'int|false', - 'getSize' => 'int|false', - 'getOwner' => 'int|false', - 'getGroup' => 'int|false', - 'getATime' => 'int|false', - 'getMTime' => 'int|false', - 'getCTime' => 'int|false', - 'getType' => 'string|false', - 'isWritable' => 'bool', - 'isReadable' => 'bool', - 'isExecutable' => 'bool', - 'isFile' => 'bool', - 'isDir' => 'bool', - 'isLink' => 'bool', - 'getLinkTarget' => 'string|false', - 'getRealPath' => 'string|false', - 'getFileInfo' => 'SplFileInfo', - 'getPathInfo' => '?SplFileInfo', - 'openFile' => 'SplFileObject', - 'setFileClass' => 'void', - 'setInfoClass' => 'void', - '__debugInfo' => 'array', - '_bad_state_ex' => 'void', - ], - 'DirectoryIterator' => [ - 'getFilename' => 'string', - 'getExtension' => 'string', - 'getBasename' => 'string', - 'isDot' => 'bool', - 'rewind' => 'void', - 'valid' => 'bool', - 'key' => 'mixed', - 'current' => 'mixed', - 'next' => 'void', - 'seek' => 'void', - ], - 'FilesystemIterator' => [ - 'rewind' => 'void', - 'key' => 'string', - 'current' => 'string|SplFileInfo|FilesystemIterator', - 'getFlags' => 'int', - 'setFlags' => 'void', - ], - 'RecursiveDirectoryIterator' => [ - 'hasChildren' => 'bool', - 'getChildren' => 'RecursiveDirectoryIterator', - 'getSubPath' => 'string', - 'getSubPathname' => 'string', - ], - 'GlobIterator' => [ - 'count' => 'int', - ], - 'SplFileObject' => [ - 'rewind' => 'void', - 'eof' => 'bool', - 'valid' => 'bool', - 'fgets' => 'string', - 'fread' => 'string|false', - 'fgetcsv' => 'array|false', - 'fputcsv' => 'int|false', - 'setCsvControl' => 'void', - 'getCsvControl' => 'array', - 'flock' => 'bool', - 'fflush' => 'bool', - 'ftell' => 'int|false', - 'fseek' => 'int', - 'fgetc' => 'string|false', - 'fpassthru' => 'int', - 'fscanf' => 'array|int|null', - 'fwrite' => 'int|false', - 'fstat' => 'array', - 'ftruncate' => 'bool', - 'current' => 'string|array|false', - 'key' => 'int', - 'next' => 'void', - 'setFlags' => 'void', - 'getFlags' => 'int', - 'setMaxLineLen' => 'void', - 'getMaxLineLen' => 'int', - 'hasChildren' => 'false', - 'getChildren' => 'null', - 'seek' => 'void', - 'getCurrentLine' => 'string', - ], - 'SplDoublyLinkedList' => [ - 'add' => 'void', - 'pop' => 'mixed', - 'shift' => 'mixed', - 'push' => 'void', - 'unshift' => 'void', - 'top' => 'mixed', - 'bottom' => 'mixed', - '__debugInfo' => 'array', - 'count' => 'int', - 'isEmpty' => 'bool', - 'setIteratorMode' => 'int', - 'getIteratorMode' => 'int', - 'offsetExists' => 'bool', - 'offsetGet' => 'mixed', - 'offsetSet' => 'void', - 'offsetUnset' => 'void', - 'rewind' => 'void', - 'current' => 'mixed', - 'key' => 'int', - 'prev' => 'void', - 'next' => 'void', - 'valid' => 'bool', - 'unserialize' => 'void', - 'serialize' => 'string', - '__serialize' => 'array', - '__unserialize' => 'void', - ], - 'SplQueue' => [ - 'enqueue' => 'void', - 'dequeue' => 'mixed', - ], - 'SplFixedArray' => [ - '__wakeup' => 'void', - 'count' => 'int', - 'toArray' => 'array', - 'fromArray' => 'SplFixedArray', - 'getSize' => 'int', - 'offsetExists' => 'bool', - 'offsetGet' => 'mixed', - 'offsetSet' => 'void', - 'offsetUnset' => 'void', - ], - 'SplPriorityQueue' => [ - 'compare' => 'int', - 'setExtractFlags' => 'int', - 'top' => 'mixed', - 'extract' => 'mixed', - 'count' => 'int', - 'isEmpty' => 'bool', - 'rewind' => 'void', - 'current' => 'mixed', - 'key' => 'int', - 'next' => 'void', - 'valid' => 'bool', - 'isCorrupted' => 'bool', - 'getExtractFlags' => 'int', - '__debugInfo' => 'array', - ], - 'SplHeap' => [ - 'extract' => 'mixed', - 'insert' => 'bool', - 'top' => 'mixed', - 'count' => 'int', - 'isEmpty' => 'bool', - 'rewind' => 'void', - 'current' => 'mixed', - 'key' => 'int', - 'next' => 'void', - 'valid' => 'bool', - 'recoverFromCorruption' => 'bool', - 'compare' => 'int', - 'isCorrupted' => 'bool', - '__debugInfo' => 'array', - ], - 'SplMinHeap' => [ - 'compare' => 'int', - ], - 'SplMaxHeap' => [ - 'compare' => 'int', - ], - 'EmptyIterator' => [ - 'current' => 'never', - 'next' => 'void', - 'key' => 'never', - 'valid' => 'false', - 'rewind' => 'void', - ], - 'CallbackFilterIterator' => [ - 'accept' => 'bool', - ], - 'RecursiveCallbackFilterIterator' => [ - 'hasChildren' => 'bool', - 'getChildren' => 'RecursiveCallbackFilterIterator', - ], - 'RecursiveIterator' => [ - 'hasChildren' => 'bool', - 'getChildren' => '?RecursiveIterator', - ], - 'RecursiveIteratorIterator' => [ - 'rewind' => 'void', - 'valid' => 'bool', - 'key' => 'mixed', - 'current' => 'mixed', - 'next' => 'void', - 'getDepth' => 'int', - 'getSubIterator' => '?RecursiveIterator', - 'getInnerIterator' => 'RecursiveIterator', - 'beginIteration' => 'void', - 'endIteration' => 'void', - 'callHasChildren' => 'bool', - 'callGetChildren' => '?RecursiveIterator', - 'beginChildren' => 'void', - 'endChildren' => 'void', - 'nextElement' => 'void', - 'setMaxDepth' => 'void', - 'getMaxDepth' => 'int|false', - ], - 'OuterIterator' => [ - 'getInnerIterator' => '?Iterator', - ], - 'IteratorIterator' => [ - 'getInnerIterator' => '?Iterator', - 'rewind' => 'void', - 'valid' => 'bool', - 'key' => 'mixed', - 'current' => 'mixed', - 'next' => 'void', - ], - 'FilterIterator' => [ - 'accept' => 'bool', - 'rewind' => 'void', - 'next' => 'void', - ], - 'RecursiveFilterIterator' => [ - 'hasChildren' => 'bool', - 'getChildren' => '?RecursiveFilterIterator', - ], - 'ParentIterator' => [ - 'accept' => 'bool', - ], - 'SeekableIterator' => [ - 'seek' => 'void', - ], - 'LimitIterator' => [ - 'rewind' => 'void', - 'valid' => 'bool', - 'next' => 'void', - 'seek' => 'int', - 'getPosition' => 'int', - ], - 'CachingIterator' => [ - 'rewind' => 'void', - 'valid' => 'bool', - 'next' => 'void', - 'hasNext' => 'bool', - 'getFlags' => 'int', - 'setFlags' => 'void', - 'offsetGet' => 'mixed', - 'offsetSet' => 'void', - 'offsetUnset' => 'void', - 'offsetExists' => 'bool', - 'getCache' => 'array', - 'count' => 'int', - ], - 'RecursiveCachingIterator' => [ - 'hasChildren' => 'bool', - 'getChildren' => '?RecursiveCachingIterator', - ], - 'NoRewindIterator' => [ - 'rewind' => 'void', - 'valid' => 'bool', - 'key' => 'mixed', - 'current' => 'mixed', - 'next' => 'void', - ], - 'AppendIterator' => [ - 'append' => 'void', - 'rewind' => 'void', - 'valid' => 'bool', - 'current' => 'mixed', - 'next' => 'void', - 'getIteratorIndex' => '?int', - 'getArrayIterator' => 'ArrayIterator', - ], - 'InfiniteIterator' => [ - 'next' => 'void', - ], - 'RegexIterator' => [ - 'accept' => 'bool', - 'getMode' => 'int', - 'setMode' => 'void', - 'getFlags' => 'int', - 'setFlags' => 'void', - 'getRegex' => 'string', - 'getPregFlags' => 'int', - 'setPregFlags' => 'void', - ], - 'RecursiveRegexIterator' => [ - 'accept' => 'bool', - 'hasChildren' => 'bool', - 'getChildren' => 'RecursiveRegexIterator', - ], - 'RecursiveTreeIterator' => [ - 'key' => 'mixed', - 'current' => 'mixed', - 'getPrefix' => 'string', - 'setPostfix' => 'void', - 'setPrefixPart' => 'void', - 'getEntry' => 'string', - 'getPostfix' => 'string', - ], - 'SplObserver' => [ - 'update' => 'void', - ], - 'SplSubject' => [ - 'attach' => 'void', - 'detach' => 'void', - 'notify' => 'void', - ], - 'SplObjectStorage' => [ - 'attach' => 'void', - 'detach' => 'void', - 'contains' => 'bool', - 'addAll' => 'int', - 'removeAll' => 'int', - 'removeAllExcept' => 'int', - 'getInfo' => 'mixed', - 'setInfo' => 'void', - 'count' => 'int', - 'rewind' => 'void', - 'valid' => 'bool', - 'key' => 'int', - 'current' => 'object', - 'next' => 'void', - 'unserialize' => 'void', - 'serialize' => 'string', - 'offsetExists' => 'bool', - 'offsetGet' => 'mixed', - 'offsetSet' => 'void', - 'offsetUnset' => 'void', - 'getHash' => 'string', - '__serialize' => 'array', - '__unserialize' => 'void', - '__debugInfo' => 'array', - ], - 'MultipleIterator' => [ - 'getFlags' => 'int', - 'setFlags' => 'void', - 'attachIterator' => 'void', - 'detachIterator' => 'void', - 'containsIterator' => 'bool', - 'countIterators' => 'int', - 'rewind' => 'void', - 'valid' => 'bool', - 'key' => 'array', - 'current' => 'array', - 'next' => 'void', - '__debugInfo' => 'array', - ], - 'SQLite3' => [ - 'open' => 'void', - 'version' => 'array', - 'lastInsertRowID' => 'int', - 'lastErrorCode' => 'int', - 'lastExtendedErrorCode' => 'int', - 'lastErrorMsg' => 'string', - 'changes' => 'int', - 'busyTimeout' => 'bool', - 'loadExtension' => 'bool', - 'backup' => 'bool', - 'escapeString' => 'string', - 'prepare' => 'SQLite3Stmt|false', - 'exec' => 'bool', - 'query' => 'SQLite3Result|false', - 'querySingle' => 'mixed', - 'createFunction' => 'bool', - 'createAggregate' => 'bool', - 'createCollation' => 'bool', - 'enableExceptions' => 'bool', - 'enableExtendedResultCodes' => 'bool', - 'setAuthorizer' => 'bool', - ], - 'SQLite3Stmt' => [ - 'bindParam' => 'bool', - 'bindValue' => 'bool', - 'clear' => 'bool', - 'close' => 'bool', - 'execute' => 'SQLite3Result|false', - 'getSQL' => 'string|false', - 'paramCount' => 'int', - 'readOnly' => 'bool', - 'reset' => 'bool', - ], - 'SQLite3Result' => [ - 'numColumns' => 'int', - 'columnName' => 'string|false', - 'columnType' => 'int|false', - 'fetchArray' => 'array|false', - 'reset' => 'bool', - ], - 'Directory' => [ - 'close' => 'void', - 'rewind' => 'void', - 'read' => 'string|false', - ], - 'php_user_filter' => [ - 'filter' => 'int', - 'onCreate' => 'bool', - 'onClose' => 'void', - ], - 'tidy' => [ - 'getOpt' => 'string|int|bool', - 'cleanRepair' => 'bool', - 'parseFile' => 'bool', - 'parseString' => 'bool', - 'repairString' => 'string|false', - 'repairFile' => 'string|false', - 'diagnose' => 'bool', - 'getRelease' => 'string', - 'getConfig' => 'array', - 'getStatus' => 'int', - 'getHtmlVer' => 'int', - 'getOptDoc' => 'string|false', - 'isXhtml' => 'bool', - 'isXml' => 'bool', - 'root' => '?tidyNode', - 'head' => '?tidyNode', - 'html' => '?tidyNode', - 'body' => '?tidyNode', - ], - 'XMLReader' => [ - 'getAttribute' => '?string', - 'getAttributeNo' => '?string', - 'getAttributeNs' => '?string', - 'getParserProperty' => 'bool', - 'isValid' => 'bool', - 'lookupNamespace' => '?string', - 'moveToAttribute' => 'bool', - 'moveToAttributeNo' => 'bool', - 'moveToAttributeNs' => 'bool', - 'moveToElement' => 'bool', - 'moveToFirstAttribute' => 'bool', - 'moveToNextAttribute' => 'bool', - 'read' => 'bool', - 'next' => 'bool', - 'readInnerXml' => 'string', - 'readOuterXml' => 'string', - 'readString' => 'string', - 'setSchema' => 'bool', - 'setParserProperty' => 'bool', - 'setRelaxNGSchema' => 'bool', - 'setRelaxNGSchemaSource' => 'bool', - 'expand' => 'DOMNode|false', - ], - 'XMLWriter' => [ - 'openUri' => 'bool', - 'openMemory' => 'bool', - 'setIndent' => 'bool', - 'setIndentString' => 'bool', - 'startComment' => 'bool', - 'endComment' => 'bool', - 'startAttribute' => 'bool', - 'endAttribute' => 'bool', - 'writeAttribute' => 'bool', - 'startAttributeNs' => 'bool', - 'writeAttributeNs' => 'bool', - 'startElement' => 'bool', - 'endElement' => 'bool', - 'fullEndElement' => 'bool', - 'startElementNs' => 'bool', - 'writeElement' => 'bool', - 'writeElementNs' => 'bool', - 'startPi' => 'bool', - 'endPi' => 'bool', - 'writePi' => 'bool', - 'startCdata' => 'bool', - 'endCdata' => 'bool', - 'writeCdata' => 'bool', - 'text' => 'bool', - 'writeRaw' => 'bool', - 'startDocument' => 'bool', - 'endDocument' => 'bool', - 'writeComment' => 'bool', - 'startDtd' => 'bool', - 'endDtd' => 'bool', - 'writeDtd' => 'bool', - 'startDtdElement' => 'bool', - 'endDtdElement' => 'bool', - 'writeDtdElement' => 'bool', - 'startDtdAttlist' => 'bool', - 'endDtdAttlist' => 'bool', - 'writeDtdAttlist' => 'bool', - 'startDtdEntity' => 'bool', - 'endDtdEntity' => 'bool', - 'writeDtdEntity' => 'bool', - 'outputMemory' => 'string', - 'flush' => 'string|int', - ], - 'XSLTProcessor' => [ - 'importStylesheet' => 'bool', - 'transformToDoc' => 'DOMDocument|false', - 'transformToUri' => 'int', - 'transformToXml' => 'string|null|false', - 'setParameter' => 'bool', - 'getParameter' => 'string|false', - 'removeParameter' => 'bool', - 'hasExsltSupport' => 'bool', - 'registerPHPFunctions' => 'void', - 'setSecurityPrefs' => 'int', - 'getSecurityPrefs' => 'int', - ], - 'ZipArchive' => [ - 'open' => 'bool|int', - 'setPassword' => 'bool', - 'close' => 'bool', - 'count' => 'int', - 'getStatusString' => 'string', - 'addEmptyDir' => 'bool', - 'addFromString' => 'bool', - 'addFile' => 'bool', - 'replaceFile' => 'bool', - 'addGlob' => 'array|false', - 'addPattern' => 'array|false', - 'renameIndex' => 'bool', - 'renameName' => 'bool', - 'setArchiveComment' => 'bool', - 'getArchiveComment' => 'string|false', - 'setCommentIndex' => 'bool', - 'setCommentName' => 'bool', - 'setMtimeIndex' => 'bool', - 'setMtimeName' => 'bool', - 'getCommentIndex' => 'string|false', - 'getCommentName' => 'string|false', - 'deleteIndex' => 'bool', - 'deleteName' => 'bool', - 'statName' => 'array|false', - 'statIndex' => 'array|false', - 'locateName' => 'int|false', - 'getNameIndex' => 'string|false', - 'unchangeArchive' => 'bool', - 'unchangeAll' => 'bool', - 'unchangeIndex' => 'bool', - 'unchangeName' => 'bool', - 'extractTo' => 'bool', - 'getFromName' => 'string|false', - 'getFromIndex' => 'string|false', - 'setExternalAttributesName' => 'bool', - 'setExternalAttributesIndex' => 'bool', - 'getExternalAttributesName' => 'bool', - 'getExternalAttributesIndex' => 'bool', - 'setCompressionName' => 'bool', - 'setCompressionIndex' => 'bool', - 'setEncryptionName' => 'bool', - 'setEncryptionIndex' => 'bool', - 'registerProgressCallback' => 'bool', - 'registerCancelCallback' => 'bool', - ], - 'Exception' => [ - '__wakeup' => 'void', - ], - 'Error' => [ - '__wakeup' => 'void', - ], - 'IteratorAggregate' => [ - 'getIterator' => 'Traversable', - ], - 'Iterator' => [ - 'current' => 'mixed', - 'next' => 'void', - 'key' => 'mixed', - 'valid' => 'bool', - 'rewind' => 'void', - ], - 'ArrayAccess' => [ - 'offsetExists' => 'bool', - 'offsetGet' => 'mixed', - 'offsetSet' => 'void', - 'offsetUnset' => 'void', - ], - 'Countable' => [ - 'count' => 'int', - ], - ]; -} diff --git a/lib/symfony/error-handler/LICENSE b/lib/symfony/error-handler/LICENSE deleted file mode 100644 index 9c907a46a..000000000 --- a/lib/symfony/error-handler/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2019-2022 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -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/lib/symfony/error-handler/README.md b/lib/symfony/error-handler/README.md deleted file mode 100644 index 12c0bfa6d..000000000 --- a/lib/symfony/error-handler/README.md +++ /dev/null @@ -1,44 +0,0 @@ -ErrorHandler Component -====================== - -The ErrorHandler component provides tools to manage errors and ease debugging PHP code. - -Getting Started ---------------- - -``` -$ composer require symfony/error-handler -``` - -```php -use Symfony\Component\ErrorHandler\Debug; -use Symfony\Component\ErrorHandler\ErrorHandler; -use Symfony\Component\ErrorHandler\DebugClassLoader; - -Debug::enable(); - -// or enable only one feature -//ErrorHandler::register(); -//DebugClassLoader::enable(); - -// If you want a custom generic template when debug is not enabled -// HtmlErrorRenderer::setTemplate('/path/to/custom/error.html.php'); - -$data = ErrorHandler::call(static function () use ($filename, $datetimeFormat) { - // if any code executed inside this anonymous function fails, a PHP exception - // will be thrown, even if the code uses the '@' PHP silence operator - $data = json_decode(file_get_contents($filename), true); - $data['read_at'] = date($datetimeFormat); - file_put_contents($filename, json_encode($data)); - - return $data; -}); -``` - -Resources ---------- - - * [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/lib/symfony/error-handler/Resources/assets/css/error.css b/lib/symfony/error-handler/Resources/assets/css/error.css deleted file mode 100644 index 332d81876..000000000 --- a/lib/symfony/error-handler/Resources/assets/css/error.css +++ /dev/null @@ -1,4 +0,0 @@ -body { background-color: #fff; color: #222; font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; margin: 0; } -.container { margin: 30px; max-width: 600px; } -h1 { color: #dc3545; font-size: 24px; } -h2 { font-size: 18px; } diff --git a/lib/symfony/error-handler/Resources/assets/css/exception.css b/lib/symfony/error-handler/Resources/assets/css/exception.css deleted file mode 100644 index 7cb3206da..000000000 --- a/lib/symfony/error-handler/Resources/assets/css/exception.css +++ /dev/null @@ -1,252 +0,0 @@ -/* This file is based on WebProfilerBundle/Resources/views/Profiler/profiler.css.twig. - If you make any change in this file, verify the same change is needed in the other file. */ -:root { - --font-sans-serif: Helvetica, Arial, sans-serif; - --page-background: #f9f9f9; - --color-text: #222; - /* when updating any of these colors, do the same in toolbar.css.twig */ - --color-success: #4f805d; - --color-warning: #a46a1f; - --color-error: #b0413e; - --color-muted: #999; - --tab-background: #fff; - --tab-color: #444; - --tab-active-background: #666; - --tab-active-color: #fafafa; - --tab-disabled-background: #f5f5f5; - --tab-disabled-color: #999; - --metric-value-background: #fff; - --metric-value-color: inherit; - --metric-unit-color: #999; - --metric-label-background: #e0e0e0; - --metric-label-color: inherit; - --table-border: #e0e0e0; - --table-background: #fff; - --table-header: #e0e0e0; - --trace-selected-background: #F7E5A1; - --tree-active-background: #F7E5A1; - --exception-title-color: var(--base-2); - --shadow: 0px 0px 1px rgba(128, 128, 128, .2); - --border: 1px solid #e0e0e0; - --background-error: var(--color-error); - --highlight-comment: #969896; - --highlight-default: #222222; - --highlight-keyword: #a71d5d; - --highlight-string: #183691; - --base-0: #fff; - --base-1: #f5f5f5; - --base-2: #e0e0e0; - --base-3: #ccc; - --base-4: #666; - --base-5: #444; - --base-6: #222; -} - -.theme-dark { - --page-background: #36393e; - --color-text: #e0e0e0; - --color-muted: #777; - --color-error: #d43934; - --tab-background: #555; - --tab-color: #ccc; - --tab-active-background: #888; - --tab-active-color: #fafafa; - --tab-disabled-background: var(--page-background); - --tab-disabled-color: #777; - --metric-value-background: #555; - --metric-value-color: inherit; - --metric-unit-color: #999; - --metric-label-background: #777; - --metric-label-color: #e0e0e0; - --trace-selected-background: #71663acc; - --table-border: #444; - --table-background: #333; - --table-header: #555; - --info-background: rgba(79, 148, 195, 0.5); - --tree-active-background: var(--metric-label-background); - --exception-title-color: var(--base-2); - --shadow: 0px 0px 1px rgba(32, 32, 32, .2); - --border: 1px solid #666; - --background-error: #b0413e; - --highlight-comment: #dedede; - --highlight-default: var(--base-6); - --highlight-keyword: #ff413c; - --highlight-string: #70a6fd; - --base-0: #2e3136; - --base-1: #444; - --base-2: #666; - --base-3: #666; - --base-4: #666; - --base-5: #e0e0e0; - --base-6: #f5f5f5; - --card-label-background: var(--tab-active-background); - --card-label-color: var(--tab-active-color); -} - -html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0} - -html { - /* always display the vertical scrollbar to avoid jumps when toggling contents */ - overflow-y: scroll; -} -body { background-color: var(--page-background); color: var(--base-6); font: 14px/1.4 Helvetica, Arial, sans-serif; padding-bottom: 45px; } - -a { cursor: pointer; text-decoration: none; } -a:hover { text-decoration: underline; } -abbr[title] { border-bottom: none; cursor: help; text-decoration: none; } - -code, pre { font: 13px/1.5 Consolas, Monaco, Menlo, "Ubuntu Mono", "Liberation Mono", monospace; } - -table, tr, th, td { background: var(--base-0); border-collapse: collapse; vertical-align: top; } -table { background: var(--base-0); border: var(--border); box-shadow: 0px 0px 1px rgba(128, 128, 128, .2); margin: 1em 0; width: 100%; } -table th, table td { border: solid var(--base-2); border-width: 1px 0; padding: 8px 10px; } -table th { background-color: var(--base-2); font-weight: bold; text-align: left; } - -.m-t-5 { margin-top: 5px; } -.hidden-xs-down { display: none; } -.block { display: block; } -.full-width { width: 100%; } -.hidden { display: none; } -.prewrap { white-space: pre-wrap; } -.nowrap { white-space: nowrap; } -.newline { display: block; } -.break-long-words { word-wrap: break-word; overflow-wrap: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; min-width: 0; } -.text-small { font-size: 12px !important; } -.text-muted { color: #999; } -.text-bold { font-weight: bold; } -.empty { border: 4px dashed var(--base-2); color: #999; margin: 1em 0; padding: .5em 2em; } - -.status-success { background: rgba(94, 151, 110, 0.3); } -.status-warning { background: rgba(240, 181, 24, 0.3); } -.status-error { background: rgba(176, 65, 62, 0.2); } -.status-success td, .status-warning td, .status-error td { background: transparent; } -tr.status-error td, tr.status-warning td { border-bottom: 1px solid var(--base-2); border-top: 1px solid var(--base-2); } -.status-warning .colored { color: #A46A1F; } -.status-error .colored { color: var(--color-error); } - -.sf-toggle { cursor: pointer; position: relative; } -.sf-toggle-content { -moz-transition: display .25s ease; -webkit-transition: display .25s ease; transition: display .25s ease; } -.sf-toggle-content.sf-toggle-hidden { display: none; } -.sf-toggle-content.sf-toggle-visible { display: block; } -thead.sf-toggle-content.sf-toggle-visible, tbody.sf-toggle-content.sf-toggle-visible { display: table-row-group; } -.sf-toggle-off .icon-close, .sf-toggle-on .icon-open { display: none; } -.sf-toggle-off .icon-open, .sf-toggle-on .icon-close { display: block; } - -.tab-navigation { margin: 0 0 1em 0; padding: 0; } -.tab-navigation li { background: var(--tab-background); border: 1px solid var(--table-border); color: var(--tab-color); cursor: pointer; display: inline-block; font-size: 16px; margin: 0 0 0 -1px; padding: .5em .75em; z-index: 1; } -.tab-navigation li .badge { background-color: var(--base-1); color: var(--base-4); display: inline-block; font-size: 14px; font-weight: bold; margin-left: 8px; min-width: 10px; padding: 1px 6px; text-align: center; white-space: nowrap; } -.tab-navigation li.disabled { background: var(--tab-disabled-background); color: var(--tab-disabled-color); } -.tab-navigation li.active { background: var(--tab-active-background); color: var(--tab-active-color); z-index: 1100; } -.tab-navigation li.active .badge { background-color: var(--base-5); color: var(--base-2); } -.tab-content > *:first-child { margin-top: 0; } -.tab-navigation li .badge.status-warning { background: var(--color-warning); color: #FFF; } -.tab-navigation li .badge.status-error { background: var(--background-error); color: #FFF; } -.sf-tabs .tab:not(:first-child) { display: none; } - -[data-filters] { position: relative; } -[data-filtered] { cursor: pointer; } -[data-filtered]:after { content: '\00a0\25BE'; } -[data-filtered]:hover .filter-list li { display: inline-flex; } -[class*="filter-hidden-"] { display: none; } -.filter-list { position: absolute; border: var(--border); box-shadow: var(--shadow); margin: 0; padding: 0; display: flex; flex-direction: column; } -.filter-list :after { content: ''; } -.filter-list li { - background: var(--tab-disabled-background); - border-bottom: var(--border); - color: var(--tab-disabled-color); - display: none; - list-style: none; - margin: 0; - padding: 5px 10px; - text-align: left; - font-weight: normal; -} -.filter-list li.active { - background: var(--tab-background); - color: var(--tab-color); -} -.filter-list li.last-active { - background: var(--tab-active-background); - color: var(--tab-active-color); -} - -.filter-list-level li { cursor: s-resize; } -.filter-list-level li.active { cursor: n-resize; } -.filter-list-level li.last-active { cursor: default; } -.filter-list-level li.last-active:before { content: '\2714\00a0'; } -.filter-list-choice li:before { content: '\2714\00a0'; color: transparent; } -.filter-list-choice li.active:before { color: unset; } - -.container { max-width: 1024px; margin: 0 auto; padding: 0 15px; } -.container::after { content: ""; display: table; clear: both; } - -header { background-color: #222; color: rgba(255, 255, 255, 0.75); font-size: 13px; height: 33px; line-height: 33px; padding: 0; } -header .container { display: flex; justify-content: space-between; } -.logo { flex: 1; font-size: 13px; font-weight: normal; margin: 0; padding: 0; } -.logo svg { height: 18px; width: 18px; opacity: .8; vertical-align: -5px; } - -.help-link { margin-left: 15px; } -.help-link a { color: inherit; } -.help-link .icon svg { height: 15px; width: 15px; opacity: .7; vertical-align: -2px; } -.help-link a:hover { color: #EEE; text-decoration: none; } -.help-link a:hover svg { opacity: .9; } - -.exception-summary { background: var(--background-error); border-bottom: 2px solid rgba(0, 0, 0, 0.1); border-top: 1px solid rgba(0, 0, 0, .3); flex: 0 0 auto; margin-bottom: 15px; } -.exception-metadata { background: rgba(0, 0, 0, 0.1); padding: 7px 0; } -.exception-metadata .container { display: flex; flex-direction: row; justify-content: space-between; } -.exception-metadata h2, .exception-metadata h2 > a { color: rgba(255, 255, 255, 0.8); font-size: 13px; font-weight: 400; margin: 0; } -.exception-http small { font-size: 13px; opacity: .7; } -.exception-hierarchy { flex: 1; } -.exception-hierarchy .icon { margin: 0 3px; opacity: .7; } -.exception-hierarchy .icon svg { height: 13px; width: 13px; vertical-align: -2px; } - -.exception-without-message .exception-message-wrapper { display: none; } -.exception-message-wrapper .container { display: flex; align-items: flex-start; min-height: 70px; padding: 10px 15px 8px; } -.exception-message { flex-grow: 1; } -.exception-message, .exception-message a { color: #FFF; font-size: 21px; font-weight: 400; margin: 0; } -.exception-message.long { font-size: 18px; } -.exception-message a { border-bottom: 1px solid rgba(255, 255, 255, 0.5); font-size: inherit; text-decoration: none; } -.exception-message a:hover { border-bottom-color: #ffffff; } - -.exception-illustration { flex-basis: 111px; flex-shrink: 0; height: 66px; margin-left: 15px; opacity: .7; } - -.trace + .trace { margin-top: 30px; } -.trace-head { background-color: var(--base-2); padding: 10px; position: relative; } -.trace-head .trace-class { color: var(--base-6); font-size: 18px; font-weight: bold; line-height: 1.3; margin: 0; position: relative; } -.trace-head .trace-namespace { color: #999; display: block; font-size: 13px; } -.trace-head .icon { position: absolute; right: 0; top: 0; } -.trace-head .icon svg { fill: var(--base-5); height: 24px; width: 24px; } - -.trace-details { background: var(--base-0); border: var(--border); box-shadow: 0px 0px 1px rgba(128, 128, 128, .2); margin: 1em 0; table-layout: fixed; } - -.trace-message { font-size: 14px; font-weight: normal; margin: .5em 0 0; } - -.trace-line { position: relative; padding-top: 8px; padding-bottom: 8px; } -.trace-line + .trace-line { border-top: var(--border); } -.trace-line:hover { background: var(--base-1); } -.trace-line a { color: var(--base-6); } -.trace-line .icon { opacity: .4; position: absolute; left: 10px; } -.trace-line .icon svg { fill: var(--base-5); height: 16px; width: 16px; } -.trace-line .icon.icon-copy { left: auto; top: auto; padding-left: 5px; display: none } -.trace-line:hover .icon.icon-copy:not(.hidden) { display: inline-block } -.trace-line-header { padding-left: 36px; padding-right: 10px; } - -.trace-file-path, .trace-file-path a { color: var(--base-6); font-size: 13px; } -.trace-class { color: var(--color-error); } -.trace-type { padding: 0 2px; } -.trace-method { color: var(--color-error); font-weight: bold; } -.trace-arguments { color: #777; font-weight: normal; padding-left: 2px; } - -.trace-code { background: var(--base-0); font-size: 12px; margin: 10px 10px 2px 10px; padding: 10px; overflow-x: auto; white-space: nowrap; } -.trace-code ol { margin: 0; float: left; } -.trace-code li { color: #969896; margin: 0; padding-left: 10px; float: left; width: 100%; } -.trace-code li + li { margin-top: 5px; } -.trace-code li.selected { background: var(--trace-selected-background); margin-top: 2px; } -.trace-code li code { color: var(--base-6); white-space: nowrap; } - -.trace-as-text .stacktrace { line-height: 1.8; margin: 0 0 15px; white-space: pre-wrap; } - -@media (min-width: 575px) { - .hidden-xs-down { display: initial; } - .help-link { margin-left: 30px; } -} diff --git a/lib/symfony/error-handler/Resources/assets/css/exception_full.css b/lib/symfony/error-handler/Resources/assets/css/exception_full.css deleted file mode 100644 index fa77cb324..000000000 --- a/lib/symfony/error-handler/Resources/assets/css/exception_full.css +++ /dev/null @@ -1,128 +0,0 @@ -.sf-reset .traces { - padding-bottom: 14px; -} -.sf-reset .traces li { - font-size: 12px; - color: #868686; - padding: 5px 4px; - list-style-type: decimal; - margin-left: 20px; -} -.sf-reset #logs .traces li.error { - font-style: normal; - color: #AA3333; - background: #f9ecec; -} -.sf-reset #logs .traces li.warning { - font-style: normal; - background: #ffcc00; -} -/* fix for Opera not liking empty <li> */ -.sf-reset .traces li:after { - content: "\00A0"; -} -.sf-reset .trace { - border: 1px solid #D3D3D3; - padding: 10px; - overflow: auto; - margin: 10px 0 20px; -} -.sf-reset .block-exception { - -moz-border-radius: 16px; - -webkit-border-radius: 16px; - border-radius: 16px; - margin-bottom: 20px; - background-color: #f6f6f6; - border: 1px solid #dfdfdf; - padding: 30px 28px; - word-wrap: break-word; - overflow: hidden; -} -.sf-reset .block-exception div { - color: #313131; - font-size: 10px; -} -.sf-reset .block-exception-detected .illustration-exception, -.sf-reset .block-exception-detected .text-exception { - float: left; -} -.sf-reset .block-exception-detected .illustration-exception { - width: 152px; -} -.sf-reset .block-exception-detected .text-exception { - width: 670px; - padding: 30px 44px 24px 46px; - position: relative; -} -.sf-reset .text-exception .open-quote, -.sf-reset .text-exception .close-quote { - font-family: Arial, Helvetica, sans-serif; - position: absolute; - color: #C9C9C9; - font-size: 8em; -} -.sf-reset .open-quote { - top: 0; - left: 0; -} -.sf-reset .close-quote { - bottom: -0.5em; - right: 50px; -} -.sf-reset .block-exception p { - font-family: Arial, Helvetica, sans-serif; -} -.sf-reset .block-exception p a, -.sf-reset .block-exception p a:hover { - color: #565656; -} -.sf-reset .logs h2 { - float: left; - width: 654px; -} -.sf-reset .error-count, .sf-reset .support { - float: right; - width: 170px; - text-align: right; -} -.sf-reset .error-count span { - display: inline-block; - background-color: #aacd4e; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; - padding: 4px; - color: white; - margin-right: 2px; - font-size: 11px; - font-weight: bold; -} - -.sf-reset .support a { - display: inline-block; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; - padding: 4px; - color: #000000; - margin-right: 2px; - font-size: 11px; - font-weight: bold; -} - -.sf-reset .toggle { - vertical-align: middle; -} -.sf-reset .linked ul, -.sf-reset .linked li { - display: inline; -} -.sf-reset #output-content { - color: #000; - font-size: 12px; -} -.sf-reset #traces-text pre { - white-space: pre; - font-size: 12px; - font-family: monospace; -} diff --git a/lib/symfony/error-handler/Resources/assets/images/chevron-right.svg b/lib/symfony/error-handler/Resources/assets/images/chevron-right.svg deleted file mode 100644 index 6837aff18..000000000 --- a/lib/symfony/error-handler/Resources/assets/images/chevron-right.svg +++ /dev/null @@ -1 +0,0 @@ -<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path fill="#FFF" d="M1363 877l-742 742q-19 19-45 19t-45-19l-166-166q-19-19-19-45t19-45l531-531-531-531q-19-19-19-45t19-45L531 45q19-19 45-19t45 19l742 742q19 19 19 45t-19 45z"/></svg> diff --git a/lib/symfony/error-handler/Resources/assets/images/favicon.png.base64 b/lib/symfony/error-handler/Resources/assets/images/favicon.png.base64 deleted file mode 100644 index fb076ed16..000000000 --- a/lib/symfony/error-handler/Resources/assets/images/favicon.png.base64 +++ /dev/null @@ -1 +0,0 @@ -data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAgCAYAAAABtRhCAAADVUlEQVRIx82XX0jTURTHLYPyqZdefQx66CEo80+aYpoIkqzUikz6Z5klQoWUWYRIJYEUGpQ+lIr9U5dOTLdCtkmWZis3rbnC5fw/neYW002307mX/cZvP3/7o1PwwOdh95x7vnf39zvnd29AgBer2xO6DclAXiMqZAqxIiNIN/IYSUS2BPhjmGATchUxI+ADWiRhpWK7HKuHFVBFdmU5YvnI4grFGCaReF/EBH4KsZlGgj2JBTuCYBWRIYF8YoEOJ6wBt/gEs7mBbyOjQXruPLSdOgPCiEiPSUUHDoL8Ug5IUo9B/d5wrt+G7OAKNrODPuVdB6vRCIzN6SdBlpW9RIgk/1FeAXabzRlrUPVCS/JhbmwudztnGeeH9AyXBIwtmM3wLinZJZHifjHw2V+NBoRh+9ixQrbgbnaSIcl7cGea6hoXQbNe7za241oeO5Z0p42M4BV2EqP2D50wo+6HzvwC6C4sApNOR8cmOrtcnhtj2kYRyC9eBvXzKrBZrXSs72kFd1t3MoKVbMekQkEnSNKOO8fac3LpmK6l1TlGtsxmsdKFsecPYgwxst0cwROMYDXboSotg0WLBRqjY51jLYcENElXwW2XJKPydvoI2GN9T8rBtrAArYIUruBJXkFheCQYlCpQP6uk5dAQFQNaUROMSGVQFxLmkoQsxDJrhLbTZ+nvVsERME9MgPJRKV/58AsyomTSzE813WLFvWK++qI0xSfQl8k8Pg46sYRuv5t6dS+4RqxDwaa4BGjYH+NTQvKScIp9+YL/hoZh3jDtLRHtt2C3g6bmhX+CpsFBWg7ilDSPgj0lD2ncr5ev/BP8VvyAJhqVyZeUhPOrEhEFxgEtjft846Z/guQTNT89Q5P9flMLoth4F7808wKtWWKzAwNQHxrh/1vaid2F+XpYTSbQf1XA2McOmOpROnvpvMEA4tSjq1cW0sws2gCYxswY6TKkvzYnJq1NHZLnRU4BX+4U0uburvusu8Kv8iHY7qefkM4IFngJHEOUXmLEPgiGsI8YnlZILit3vSSLRTQe/MPIZva5pshNIEmyFQlCvruJKXPkCEfmePzkphXHdzZNQdoRI9KPlBAxlj/I8U97ERPS5bjGbWDFbEdqHVe5caTBeZZx2H/IMvzeN15yoQAAAABJRU5ErkJggg== diff --git a/lib/symfony/error-handler/Resources/assets/images/icon-book.svg b/lib/symfony/error-handler/Resources/assets/images/icon-book.svg deleted file mode 100644 index 498a74f40..000000000 --- a/lib/symfony/error-handler/Resources/assets/images/icon-book.svg +++ /dev/null @@ -1 +0,0 @@ -<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path fill="#FFF" d="M1703 478q40 57 18 129l-275 906q-19 64-76.5 107.5T1247 1664H324q-77 0-148.5-53.5T76 1479q-24-67-2-127 0-4 3-27t4-37q1-8-3-21.5t-3-19.5q2-11 8-21t16.5-23.5T116 1179q23-38 45-91.5t30-91.5q3-10 .5-30t-.5-28q3-11 17-28t17-23q21-36 42-92t25-90q1-9-2.5-32t.5-28q4-13 22-30.5t22-22.5q19-26 42.5-84.5T404 411q1-8-3-25.5t-2-26.5q2-8 9-18t18-23 17-21q8-12 16.5-30.5t15-35 16-36 19.5-32 26.5-23.5 36-11.5T620 134l-1 3q38-9 51-9h761q74 0 114 56t18 130l-274 906q-36 119-71.5 153.5T1089 1408H220q-27 0-38 15-11 16-1 43 24 70 144 70h923q29 0 56-15.5t35-41.5l300-987q7-22 5-57 38 15 59 43zm-1064 2q-4 13 2 22.5t20 9.5h608q13 0 25.5-9.5T1311 480l21-64q4-13-2-22.5t-20-9.5H702q-13 0-25.5 9.5T660 416zm-83 256q-4 13 2 22.5t20 9.5h608q13 0 25.5-9.5T1228 736l21-64q4-13-2-22.5t-20-9.5H619q-13 0-25.5 9.5T577 672z"/></svg> diff --git a/lib/symfony/error-handler/Resources/assets/images/icon-copy.svg b/lib/symfony/error-handler/Resources/assets/images/icon-copy.svg deleted file mode 100644 index 844a4f99e..000000000 --- a/lib/symfony/error-handler/Resources/assets/images/icon-copy.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg> \ No newline at end of file diff --git a/lib/symfony/error-handler/Resources/assets/images/icon-minus-square-o.svg b/lib/symfony/error-handler/Resources/assets/images/icon-minus-square-o.svg deleted file mode 100644 index be534ad44..000000000 --- a/lib/symfony/error-handler/Resources/assets/images/icon-minus-square-o.svg +++ /dev/null @@ -1 +0,0 @@ -<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1344 800v64q0 14-9 23t-23 9H480q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h832q14 0 23 9t9 23zm128 448V416q0-66-47-113t-113-47H480q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113zm128-832v832q0 119-84.5 203.5T1312 1536H480q-119 0-203.5-84.5T192 1248V416q0-119 84.5-203.5T480 128h832q119 0 203.5 84.5T1600 416z"/></svg> diff --git a/lib/symfony/error-handler/Resources/assets/images/icon-minus-square.svg b/lib/symfony/error-handler/Resources/assets/images/icon-minus-square.svg deleted file mode 100644 index 471c2741c..000000000 --- a/lib/symfony/error-handler/Resources/assets/images/icon-minus-square.svg +++ /dev/null @@ -1 +0,0 @@ -<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1408 960V832q0-26-19-45t-45-19H448q-26 0-45 19t-19 45v128q0 26 19 45t45 19h896q26 0 45-19t19-45zm256-544v960q0 119-84.5 203.5T1376 1664H416q-119 0-203.5-84.5T128 1376V416q0-119 84.5-203.5T416 128h960q119 0 203.5 84.5T1664 416z"/></svg> diff --git a/lib/symfony/error-handler/Resources/assets/images/icon-plus-square-o.svg b/lib/symfony/error-handler/Resources/assets/images/icon-plus-square-o.svg deleted file mode 100644 index b2593a9fe..000000000 --- a/lib/symfony/error-handler/Resources/assets/images/icon-plus-square-o.svg +++ /dev/null @@ -1 +0,0 @@ -<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1344 800v64q0 14-9 23t-23 9H960v352q0 14-9 23t-23 9h-64q-14 0-23-9t-9-23V896H480q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h352V416q0-14 9-23t23-9h64q14 0 23 9t9 23v352h352q14 0 23 9t9 23zm128 448V416q0-66-47-113t-113-47H480q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113zm128-832v832q0 119-84.5 203.5T1312 1536H480q-119 0-203.5-84.5T192 1248V416q0-119 84.5-203.5T480 128h832q119 0 203.5 84.5T1600 416z"/></svg> diff --git a/lib/symfony/error-handler/Resources/assets/images/icon-plus-square.svg b/lib/symfony/error-handler/Resources/assets/images/icon-plus-square.svg deleted file mode 100644 index 2f5c3b358..000000000 --- a/lib/symfony/error-handler/Resources/assets/images/icon-plus-square.svg +++ /dev/null @@ -1 +0,0 @@ -<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1408 960V832q0-26-19-45t-45-19h-320V448q0-26-19-45t-45-19H832q-26 0-45 19t-19 45v320H448q-26 0-45 19t-19 45v128q0 26 19 45t45 19h320v320q0 26 19 45t45 19h128q26 0 45-19t19-45v-320h320q26 0 45-19t19-45zm256-544v960q0 119-84.5 203.5T1376 1664H416q-119 0-203.5-84.5T128 1376V416q0-119 84.5-203.5T416 128h960q119 0 203.5 84.5T1664 416z"/></svg> diff --git a/lib/symfony/error-handler/Resources/assets/images/icon-support.svg b/lib/symfony/error-handler/Resources/assets/images/icon-support.svg deleted file mode 100644 index 03fd8e767..000000000 --- a/lib/symfony/error-handler/Resources/assets/images/icon-support.svg +++ /dev/null @@ -1 +0,0 @@ -<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path fill="#FFF" d="M896 0q182 0 348 71t286 191 191 286 71 348-71 348-191 286-286 191-348 71-348-71-286-191-191-286T0 896t71-348 191-286T548 71 896 0zm0 128q-190 0-361 90l194 194q82-28 167-28t167 28l194-194q-171-90-361-90zM218 1257l194-194q-28-82-28-167t28-167L218 535q-90 171-90 361t90 361zm678 407q190 0 361-90l-194-194q-82 28-167 28t-167-28l-194 194q171 90 361 90zm0-384q159 0 271.5-112.5T1280 896t-112.5-271.5T896 512 624.5 624.5 512 896t112.5 271.5T896 1280zm484-217l194 194q90-171 90-361t-90-361l-194 194q28 82 28 167t-28 167z"/></svg> diff --git a/lib/symfony/error-handler/Resources/assets/images/symfony-ghost.svg.php b/lib/symfony/error-handler/Resources/assets/images/symfony-ghost.svg.php deleted file mode 100644 index 4b2f9c1b9..000000000 --- a/lib/symfony/error-handler/Resources/assets/images/symfony-ghost.svg.php +++ /dev/null @@ -1 +0,0 @@ -<svg viewBox="0 0 136 81" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.4"><path d="M92.4 20.4a23.2 23.2 0 0 1 9 1.9 23.7 23.7 0 0 1 5.2 3 24.3 24.3 0 0 1 3.4 3.4 24.8 24.8 0 0 1 5 9.4c.5 1.7.8 3.4 1 5.2v14.5h.4l.5.2a7.4 7.4 0 0 0 2.5.2l.2-.2.6-.8.8-1.3-.2-.1a5.5 5.5 0 0 1-.8-.3 5.6 5.6 0 0 1-2.3-1.8 5.7 5.7 0 0 1-.9-1.6 6.5 6.5 0 0 1-.2-2.8 7.3 7.3 0 0 1 .5-2l.3-.3.8-.9.3-.3c.2-.2.5-.3.8-.3H120.7c.2 0 .3-.1.4 0h.4l.2.1.3.2.2-.4.3-.4.1-.1 1.2-1 .3-.2.4-.1.4-.1h.3l1.5.1.4.1.8.5.1.2 1 1.1v.2H129.4l.4-.2 1.4-.5h1.1c.3 0 .7.2 1 .4.2 0 .3.2.5.3l.2.2.5.3.4.6.1.3.4 1.4.1.4v.6a7.8 7.8 0 0 1-.1.6 9.9 9.9 0 0 1-.8 2.4 7.8 7.8 0 0 1-3 3.3 6.4 6.4 0 0 1-1 .5 6.1 6.1 0 0 1-.6.2l-.7.1h-.1a23.4 23.4 0 0 1-.2 1.7 14.3 14.3 0 0 1-.6 2.1l-.8 2a9.2 9.2 0 0 1-.4.6l-.7 1a9.1 9.1 0 0 1-2.3 2.2c-.9.5-2 .6-3 .7l-1.4.1h-.5l-.4.1a15.8 15.8 0 0 1-2.8-.1v4.2a9.7 9.7 0 0 1-.7 3.5 9.6 9.6 0 0 1-1.7 2.8 9.3 9.3 0 0 1-3 2.3 9 9 0 0 1-5.4.7 9 9 0 0 1-3-1 9.4 9.4 0 0 1-2.7-2.5 10 10 0 0 1-1 1.2 9.3 9.3 0 0 1-2 1.3 9 9 0 0 1-2.4 1 9 9 0 0 1-6.5-1.1A9.4 9.4 0 0 1 85 77V77a10.9 10.9 0 0 1-.6.6 9.3 9.3 0 0 1-2.7 2 9 9 0 0 1-6 .8 9 9 0 0 1-2.4-1 9.3 9.3 0 0 1-2.3-1.7 9.6 9.6 0 0 1-1.8-2.8 9.7 9.7 0 0 1-.8-3.7v-4a18.5 18.5 0 0 1-2.9.2l-1.2-.1c-1.9-.3-3.7-1-5.1-2.2a8.2 8.2 0 0 1-1.1-1 10.2 10.2 0 0 1-.9-1.2 15.3 15.3 0 0 1-.7-1.3 20.8 20.8 0 0 1-1.9-6.2v-.2a6.5 6.5 0 0 1-1-.3 6.1 6.1 0 0 1-.6-.3 6.6 6.6 0 0 1-.9-.6 8.2 8.2 0 0 1-2.7-3.7 10 10 0 0 1-.3-1 10.3 10.3 0 0 1-.3-1.9V47v-.4l.1-.4.6-1.4.1-.2a2 2 0 0 1 .8-.8l.3-.2.3-.2a3.2 3.2 0 0 1 1.8-.5h.4l.3.2 1.4.6.2.2.4.3.3.4.7-.7.2-.2.4-.2.6-.2h2.1l.4.2.4.2.3.2.8 1 .2-.1h.1v-.1H63l1.1.1h.3l.8.5.3.4.7 1 .2.3.1.5a11 11 0 0 1 .2 1.5c0 .8 0 1.6-.3 2.3a6 6 0 0 1-.5 1.2 5.5 5.5 0 0 1-3.3 2.5 12.3 12.3 0 0 0 1.4 3h.1l.2.1 1 .2h1.5l.5-.2H67.8l.5-.2h.1V44v-.4a26.7 26.7 0 0 1 .3-2.3 24.7 24.7 0 0 1 5.7-12.5 24.2 24.2 0 0 1 3.5-3.3 23.7 23.7 0 0 1 4.9-3 23.2 23.2 0 0 1 5.6-1.7 23.7 23.7 0 0 1 4-.3zm-.3 2a21.2 21.2 0 0 0-8 1.7 21.6 21.6 0 0 0-4.8 2.7 22.2 22.2 0 0 0-3.2 3 22.7 22.7 0 0 0-5 9.2 23.4 23.4 0 0 0-.7 4.9v15.7l-.5.1a34.3 34.3 0 0 1-1.5.3h-.2l-.4.1h-.4l-.9.2a10 10 0 0 1-1.9 0c-.5 0-1-.2-1.5-.4a1.8 1.8 0 0 1-.3-.2 2 2 0 0 1-.3-.3 5.2 5.2 0 0 1-.1-.2 9 9 0 0 1-.6-.9 13.8 13.8 0 0 1-1-2 14.3 14.3 0 0 1-.6-2 14 14 0 0 1-.1-.8v-.2h.3a12.8 12.8 0 0 0 1.4-.2 4.4 4.4 0 0 0 .3 0 3.6 3.6 0 0 0 1.1-.7 3.4 3.4 0 0 0 1.2-1.7l.2-1.2a5.1 5.1 0 0 0 0-.8 7.2 7.2 0 0 0-.1-.8l-.7-1-1.2-.2-1 .7-.1 1.3a5 5 0 0 1 .1.4v.6a1 1 0 0 1 0 .3c-.1.3-.4.4-.7.5l-1.2.4v-.7A9.9 9.9 0 0 1 60 49l.3-.6v-.2l.1-.1v-1.6l-1-1.2h-1.5l-1 1.1v.4a5.3 5.3 0 0 0-.2.6 5.5 5.5 0 0 0 0 .5c0 .7 0 1.4.3 2 0 .4.2.8.4 1.2L57 51a9.5 9.5 0 0 1-1.1-.5h-.2a2 2 0 0 1-.4-.3c-.4-.4-.5-1-.6-1.6a5.6 5.6 0 0 1 0-.5v-.5-.5l-.6-1.5-1.4-.6-.9.3s-.2 0-.3.2a2 2 0 0 1-.1 0l-.6 1.4v.7a8.5 8.5 0 0 0 .5 2c.4 1.1 1 2.1 2 2.8a4.7 4.7 0 0 0 2.1.9h1a22.8 22.8 0 0 0 .1 1 18.1 18.1 0 0 0 .8 3.8 18.2 18.2 0 0 0 1.6 3.7l1 1.3c1 1 2.3 1.6 3.7 2a11.7 11.7 0 0 0 4.8 0h.4l.5-.2.5-.1.6-.2v6.6a8 8 0 0 0 .1 1.3 7.5 7.5 0 0 0 2.4 4.3 7.2 7.2 0 0 0 2.3 1.3 7 7 0 0 0 7-1.1 7.5 7.5 0 0 0 2-2.6A7.7 7.7 0 0 0 85 72V71a8.2 8.2 0 0 0 .2 1.3c0 .7.3 1.4.6 2a7.5 7.5 0 0 0 1.7 2.3 7.3 7.3 0 0 0 2.2 1.4 7.1 7.1 0 0 0 4.6.2 7.2 7.2 0 0 0 2.4-1.2 7.5 7.5 0 0 0 2.1-2.7 7.8 7.8 0 0 0 .7-2.4V71a9.3 9.3 0 0 0 .1.6 7.6 7.6 0 0 0 .6 2.5 7.5 7.5 0 0 0 2.4 3 7.1 7.1 0 0 0 7 .8 7.3 7.3 0 0 0 2.3-1.5 7.5 7.5 0 0 0 1.6-2.3 7.6 7.6 0 0 0 .5-2l.1-1.1v-6.7l.4.1a12.2 12.2 0 0 0 2 .5 11.1 11.1 0 0 0 2.5 0h.8l1.2-.1a9.5 9.5 0 0 0 1.4-.2l.9-.3a3.5 3.5 0 0 0 .6-.4l1.2-1.4a12.2 12.2 0 0 0 .8-1.2c0-.3.2-.5.3-.7a15.9 15.9 0 0 0 .7-2l.3-1.6v-1.3l.2-.9V54.6a15.5 15.5 0 0 0 1.8 0 4.5 4.5 0 0 0 1.4-.5 5.7 5.7 0 0 0 2.5-3.2 7.6 7.6 0 0 0 .4-1.5v-.3l-.4-1.4a5.2 5.2 0 0 1-.2-.1l-.4-.4a3.8 3.8 0 0 0-.2 0 1.4 1.4 0 0 0-.5-.2l-1.4.4-.7 1.3v.7a5.7 5.7 0 0 1-.1.8l-.7 1.4a1.9 1.9 0 0 1-.5.3h-.3a9.6 9.6 0 0 1-.8.3 8.8 8.8 0 0 1-.6 0l.2-.4.2-.5.2-.3v-.4l.1-.2V50l.1-1 .1-.6v-.6a4.8 4.8 0 0 0 0-.8v-.2l-1-1.1-1.5-.2-1.1 1-.2 1.4v.1l.2.4.2.3v.4l.1 1.1v.3l.1.5v.8a9.6 9.6 0 0 1-.8-.3l-.2-.1h-.3l-.8-.1h-.2a1.6 1.6 0 0 1-.2-.2.9.9 0 0 1-.2-.2 1 1 0 0 1-.1-.5l.2-.9v-1.2l-.9-.8h-1.2l-.8.9v.3a4.8 4.8 0 0 0-.3 2l.3.9a3.5 3.5 0 0 0 1.2 1.6l1 .5.8.2 1.4.1h.4l.2.1a12.1 12.1 0 0 1-1 2.6 13.2 13.2 0 0 1-.8 1.5 9.5 9.5 0 0 1-1 1.2l-.2.3a1.7 1.7 0 0 1-.4.3 2.4 2.4 0 0 1-.7.2h-2.5a7.8 7.8 0 0 1-.6-.2l-.7-.2h-.2a14.8 14.8 0 0 1-.6-.2 23.4 23.4 0 0 1-.4-.1l-.4-.1-.3-.1V43.9a34.6 34.6 0 0 0 0-.6 23.6 23.6 0 0 0-.4-3 22.7 22.7 0 0 0-1.5-4.7 22.6 22.6 0 0 0-4.6-6.7 21.9 21.9 0 0 0-6.9-4.7 21.2 21.2 0 0 0-8.1-1.8H92zm9.1 33.7l.3.1a1 1 0 0 1 .6.8v.4a8.4 8.4 0 0 1 0 .5 8.8 8.8 0 0 1-1.6 4.2l-1 1.3A10 10 0 0 1 95 66c-1.3.3-2.7.4-4 .3a10.4 10.4 0 0 1-2.7-.8 10 10 0 0 1-3.6-2.5 9.3 9.3 0 0 1-.8-1 9 9 0 0 1-.7-1.2 8.6 8.6 0 0 1-.8-3.4V57a1 1 0 0 1 .3-.6 1 1 0 0 1 1.3-.2 1 1 0 0 1 .4.8v.4a6.5 6.5 0 0 0 .5 2.2 7 7 0 0 0 2.1 2.8l1 .6c2.6 1.6 6 1.6 8.5 0a8 8 0 0 0 1.1-.6 7.6 7.6 0 0 0 1.2-1.2 7 7 0 0 0 1-1.7 6.5 6.5 0 0 0 .4-2.5 1 1 0 0 1 .7-1h.4zM30.7 43.7c-15.5 1-28.5-6-30.1-16.4C-1.2 15.7 11.6 4 29 1.3 46.6-1.7 62.3 5.5 64 17.1c1.6 10.4-8.7 21-23.7 25a31.2 31.2 0 0 0 0 .9v.3a19 19 0 0 0 .1 1l.1.4.1.9a4.7 4.7 0 0 0 .5 1l.7 1a9.2 9.2 0 0 0 1.2 1l1.5.8.6.8-.7.6-1.1.3a11.2 11.2 0 0 1-2.6.4 8.6 8.6 0 0 1-3-.5 8.5 8.5 0 0 1-1-.4 11.2 11.2 0 0 1-1.8-1.2 13.3 13.3 0 0 1-1-1 18 18 0 0 1-.7-.6l-.4-.4a23.4 23.4 0 0 1-1.3-1.8l-.1-.1-.3-.5V45l-.3-.6v-.7zM83.1 36c3.6 0 6.5 3.2 6.5 7.1 0 4-3 7.2-6.5 7.2S76.7 47 76.7 43 79.6 36 83 36zm18 0c3.6 0 6.5 3.2 6.5 7.1 0 4-2.9 7.2-6.4 7.2S94.7 47 94.7 43s3-7.1 6.5-7.1zm-18 6.1c2 0 3.5 1.6 3.5 3.6S85 49.2 83 49.2s-3.4-1.6-3.4-3.6S81.2 42 83 42zm17.9 0c1.9 0 3.4 1.6 3.4 3.6s-1.5 3.6-3.4 3.6c-2 0-3.5-1.6-3.5-3.6S99.1 42 101 42zM17 28c-.3 1.6-1.8 5-5.2 5.8-2.5.6-4.1-.8-4.5-2.6-.4-1.9.7-3.5 2.1-4.5A3.5 3.5 0 0 1 8 24.6c-.4-2 .8-3.7 3.2-4.2 1.9-.5 3.1.2 3.4 1.5.3 1.1-.5 2.2-1.8 2.5-.9.3-1.6 0-1.7-.6a1.4 1.4 0 0 1 0-.7s.3.2 1 0c.7-.1 1-.7.9-1.2-.2-.6-1-.8-1.8-.6-1 .2-2 1-1.7 2.6.3 1 .9 1.6 1.5 1.8l.7-.2c1-.2 1.5 0 1.6.5 0 .4-.2 1-1.2 1.2a3.3 3.3 0 0 1-1.5 0c-.9.7-1.6 1.9-1.3 3.2.3 1.3 1.3 2.2 3 1.8 2.5-.7 3.8-3.7 4.2-5-.3-.5-.6-1-.7-1.6-.1-.5.1-1 .9-1.2.4 0 .7.2.8.8a2.8 2.8 0 0 1 0 1l.7 1c.6-2 1.4-4 1.7-4 .6-.2 1.5.6 1.5.6-.8.7-1.7 2.4-2.3 4.2.8.6 1.6 1 2.1 1 .5-.1.8-.6 1-1.2-.3-2.2 1-4.3 2.3-4.6.7-.2 1.3.2 1.4.8.1.5 0 1.3-.9 1.7-.2-1-.6-1.3-1-1.3-.4.1-.7 1.4-.4 2.8.2 1 .7 1.5 1.3 1.4.8-.2 1.3-1.2 1.7-2.1-.3-2.1.9-4.2 2.2-4.5.7-.2 1.2.1 1.4 1 .4 1.4-1 2.8-2.2 3.4.3.7.7 1 1.3.9 1-.3 1.6-1.5 2-2.5l-.5-3v-.3s1.6-.3 1.8.6v.1c.2-.6.7-1.2 1.3-1.4.8-.1 1.5.6 1.7 1.6.5 2.2-.5 4.4-1.8 4.7H33a31.9 31.9 0 0 0 1 5.2c-.4.1-1.8.4-2-.4l-.5-5.6c-.5 1-1.3 2.2-2.5 2.4-1 .3-1.6-.3-2-1.1-.5 1-1.3 2.1-2.4 2.4-.8.2-1.5-.1-2-1-.3.8-.9 1.5-1.5 1.7-.7.1-1.5-.3-2.4-1-.3.8-.4 1.6-.4 2.2 0 0-.7 0-.8-.4-.1-.5 0-1.5.3-2.7a10.3 10.3 0 0 1-.7-.8zm38.2-17.8l.2.9c.5 1.9.4 4.4.8 6.4 0 .6-.4 3-1.4 3.3-.2 0-.3 0-.4-.4-.1-.7 0-1.6-.3-2.6-.2-1.1-.8-1.6-1.5-1.5-.8.2-1.3 1-1.6 2l-.1-.5c-.2-1-1.8-.6-1.8-.6a6.2 6.2 0 0 1 .4 1.3l.2 1c-.2.5-.6 1-1.2 1l-.2.1a7 7 0 0 0-.1-.8c-.3-1.1-1-2-1.6-1.8a.7.7 0 0 0-.4.3c-1.3.3-2.4 2-2.1 3.9-.2.9-.6 1.7-1 1.9-.5 0-.8-.5-1.1-1.8l-.1-1.2a4 4 0 0 0 0-1.7c0-.4-.4-.7-.8-.6-.7.2-.9 1.7-.5 3.8-.2 1-.6 2-1.3 2-.4.2-.8-.2-1-1l-.2-3c1.2-.5 2-1 1.8-1.7-.1-.5-.8-.7-.8-.7s0 .7-1 1.2l-.2-1.4c-.1-.6-.4-1-1.7-.6l.4 1 .2 1.5h-1v.8c0 .3.4.3 1 .2 0 1.3 0 2.7.2 3.6.3 1.4 1.2 2 2 1.7 1-.2 1.6-1.3 2-2.3.3 1.2 1 2 1.9 1.7.7-.2 1.2-1.1 1.6-2.2.4.8 1.1 1.1 2 1 1.2-.4 1.7-1.6 1.8-2.8h.2c.6-.2 1-.6 1.3-1 0 .8 0 1.5.2 2.1.1.5.3.7.6.6.5-.1 1-.9 1-.9a4 4 0 0 1-.3-1c-.3-1.3.3-3.6 1-3.7.2 0 .3.2.5.7v.8l.2 1.5v.7c.2.7.7 1.3 1.5 1 1.3-.2 2-2.6 2.1-3.9.3.2.6.2 1 .1-.6-2.2 0-6.1-.3-7.9-.1-.4-1-.5-1.7-.5h-.4zm-21.5 12c.4 0 .7.3 1 1.1.2 1.3-.3 2.6-.9 2.8-.2 0-.7 0-1-1.2v-.4c0-1.3.4-2 1-2.2zm-5.2 1c.3 0 .6.2.6.5.2.6-.3 1.3-1.2 2-.3-1.4.1-2.3.6-2.5zm18-.4c-.5.2-1-.4-1.2-1.2-.2-1 0-2.1.7-2.5v.5c.2.7.6 1.5 1.3 1.9 0 .7-.2 1.2-.7 1.3zm10-1.6c0 .5.4.7 1 .6.8-.2 1-1 .8-1.6 0-.5-.4-1-1-.8-.5.1-1 .9-.8 1.8zm-14.3-5.5c0-.4-.5-.7-1-.5-.8.2-1 1-.9 1.5.2.6.5 1 1 .8.5 0 1.1-1 1-1.8z" fill="#fff" fill-opacity=".6"/><?= $this->addElementToGhost(); ?></svg> diff --git a/lib/symfony/error-handler/Resources/assets/images/symfony-logo.svg b/lib/symfony/error-handler/Resources/assets/images/symfony-logo.svg deleted file mode 100644 index f10824ae9..000000000 --- a/lib/symfony/error-handler/Resources/assets/images/symfony-logo.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#FFF" d="M12 .9C5.8.9.9 5.8.9 12a11 11 0 1 0 22.2 0A11 11 0 0 0 12 .9zm6.5 6c-.6 0-.9-.3-.9-.8 0-.2 0-.4.2-.6l.2-.4c0-.3-.5-.4-.6-.4-1.8.1-2.3 2.5-2.7 4.4l-.2 1c1 .2 1.8 0 2.2-.3.6-.4-.2-.7-.1-1.2.1-.3.5-.5.7-.6.5 0 .7.5.7.9 0 .7-1 1.8-3 1.8l-.6-.1-.6 2.4c-.4 1.6-.8 3.8-2.4 5.7-1.4 1.7-2.9 1.9-3.5 1.9-1.2 0-1.9-.6-2-1.5 0-.8.7-1.3 1.2-1.3.6 0 1.1.5 1.1 1s-.2.6-.4.6c-.1.1-.3.2-.3.4 0 .1.1.3.4.3.5 0 .8-.3 1.1-.5 1.2-.9 1.6-2.7 2.2-5.7l.1-.7.7-3.2c-.8-.6-1.3-1.4-2.4-1.7-.6-.1-1.1.1-1.5.5-.4.5-.2 1.1.2 1.5l.7.6c.7.8 1.2 1.6 1 2.5-.3 1.5-2 2.6-4 1.9-1.8-.6-2-1.8-1.8-2.5.2-.6.6-.7 1.1-.6.5.2.6.7.6 1.2l-.1.3c-.2.1-.3.3-.3.4-.1.4.4.6.7.7.7.3 1.6-.2 1.8-.8a1 1 0 0 0-.4-1.1l-.7-.8c-.4-.4-1.1-1.4-.7-2.6.1-.5.4-.9.7-1.3a4 4 0 0 1 2.8-.6c1.2.4 1.8 1.1 2.6 1.8.5-1.2 1-2.4 1.8-3.5.9-.9 1.9-1.6 3.1-1.7 1.3.2 2.2.7 2.2 1.6 0 .4-.2 1.1-.9 1.1z"/></svg> diff --git a/lib/symfony/error-handler/Resources/assets/js/exception.js b/lib/symfony/error-handler/Resources/assets/js/exception.js deleted file mode 100644 index a85409da3..000000000 --- a/lib/symfony/error-handler/Resources/assets/js/exception.js +++ /dev/null @@ -1,297 +0,0 @@ -/* This file is based on WebProfilerBundle/Resources/views/Profiler/base_js.html.twig. - If you make any change in this file, verify the same change is needed in the other file. */ -/*<![CDATA[*/ -if (typeof Sfjs === 'undefined') { - Sfjs = (function() { - "use strict"; - - if ('classList' in document.documentElement) { - var hasClass = function (el, cssClass) { return el.classList.contains(cssClass); }; - var removeClass = function(el, cssClass) { el.classList.remove(cssClass); }; - var addClass = function(el, cssClass) { el.classList.add(cssClass); }; - var toggleClass = function(el, cssClass) { el.classList.toggle(cssClass); }; - } else { - var hasClass = function (el, cssClass) { return el.className.match(new RegExp('\\b' + cssClass + '\\b')); }; - var removeClass = function(el, cssClass) { el.className = el.className.replace(new RegExp('\\b' + cssClass + '\\b'), ' '); }; - var addClass = function(el, cssClass) { if (!hasClass(el, cssClass)) { el.className += " " + cssClass; } }; - var toggleClass = function(el, cssClass) { hasClass(el, cssClass) ? removeClass(el, cssClass) : addClass(el, cssClass); }; - } - - var addEventListener; - - var el = document.createElement('div'); - if (!('addEventListener' in el)) { - addEventListener = function (element, eventName, callback) { - element.attachEvent('on' + eventName, callback); - }; - } else { - addEventListener = function (element, eventName, callback) { - element.addEventListener(eventName, callback, false); - }; - } - - if (navigator.clipboard) { - document.querySelectorAll('[data-clipboard-text]').forEach(function(element) { - removeClass(element, 'hidden'); - element.addEventListener('click', function() { - navigator.clipboard.writeText(element.getAttribute('data-clipboard-text')); - }) - }); - } - - return { - addEventListener: addEventListener, - - createTabs: function() { - var tabGroups = document.querySelectorAll('.sf-tabs:not([data-processed=true])'); - - /* create the tab navigation for each group of tabs */ - for (var i = 0; i < tabGroups.length; i++) { - var tabs = tabGroups[i].querySelectorAll(':scope > .tab'); - var tabNavigation = document.createElement('ul'); - tabNavigation.className = 'tab-navigation'; - - var selectedTabId = 'tab-' + i + '-0'; /* select the first tab by default */ - for (var j = 0; j < tabs.length; j++) { - var tabId = 'tab-' + i + '-' + j; - var tabTitle = tabs[j].querySelector('.tab-title').innerHTML; - - var tabNavigationItem = document.createElement('li'); - tabNavigationItem.setAttribute('data-tab-id', tabId); - if (hasClass(tabs[j], 'active')) { selectedTabId = tabId; } - if (hasClass(tabs[j], 'disabled')) { addClass(tabNavigationItem, 'disabled'); } - tabNavigationItem.innerHTML = tabTitle; - tabNavigation.appendChild(tabNavigationItem); - - var tabContent = tabs[j].querySelector('.tab-content'); - tabContent.parentElement.setAttribute('id', tabId); - } - - tabGroups[i].insertBefore(tabNavigation, tabGroups[i].firstChild); - addClass(document.querySelector('[data-tab-id="' + selectedTabId + '"]'), 'active'); - } - - /* display the active tab and add the 'click' event listeners */ - for (i = 0; i < tabGroups.length; i++) { - tabNavigation = tabGroups[i].querySelectorAll(':scope >.tab-navigation li'); - - for (j = 0; j < tabNavigation.length; j++) { - tabId = tabNavigation[j].getAttribute('data-tab-id'); - document.getElementById(tabId).querySelector('.tab-title').className = 'hidden'; - - if (hasClass(tabNavigation[j], 'active')) { - document.getElementById(tabId).className = 'block'; - } else { - document.getElementById(tabId).className = 'hidden'; - } - - tabNavigation[j].addEventListener('click', function(e) { - var activeTab = e.target || e.srcElement; - - /* needed because when the tab contains HTML contents, user can click */ - /* on any of those elements instead of their parent '<li>' element */ - while (activeTab.tagName.toLowerCase() !== 'li') { - activeTab = activeTab.parentNode; - } - - /* get the full list of tabs through the parent of the active tab element */ - var tabNavigation = activeTab.parentNode.children; - for (var k = 0; k < tabNavigation.length; k++) { - var tabId = tabNavigation[k].getAttribute('data-tab-id'); - document.getElementById(tabId).className = 'hidden'; - removeClass(tabNavigation[k], 'active'); - } - - addClass(activeTab, 'active'); - var activeTabId = activeTab.getAttribute('data-tab-id'); - document.getElementById(activeTabId).className = 'block'; - }); - } - - tabGroups[i].setAttribute('data-processed', 'true'); - } - }, - - createToggles: function() { - var toggles = document.querySelectorAll('.sf-toggle:not([data-processed=true])'); - - for (var i = 0; i < toggles.length; i++) { - var elementSelector = toggles[i].getAttribute('data-toggle-selector'); - var element = document.querySelector(elementSelector); - - addClass(element, 'sf-toggle-content'); - - if (toggles[i].hasAttribute('data-toggle-initial') && toggles[i].getAttribute('data-toggle-initial') == 'display') { - addClass(toggles[i], 'sf-toggle-on'); - addClass(element, 'sf-toggle-visible'); - } else { - addClass(toggles[i], 'sf-toggle-off'); - addClass(element, 'sf-toggle-hidden'); - } - - addEventListener(toggles[i], 'click', function(e) { - e.preventDefault(); - - if ('' !== window.getSelection().toString()) { - /* Don't do anything on text selection */ - return; - } - - var toggle = e.target || e.srcElement; - - /* needed because when the toggle contains HTML contents, user can click */ - /* on any of those elements instead of their parent '.sf-toggle' element */ - while (!hasClass(toggle, 'sf-toggle')) { - toggle = toggle.parentNode; - } - - var element = document.querySelector(toggle.getAttribute('data-toggle-selector')); - - toggleClass(toggle, 'sf-toggle-on'); - toggleClass(toggle, 'sf-toggle-off'); - toggleClass(element, 'sf-toggle-hidden'); - toggleClass(element, 'sf-toggle-visible'); - - /* the toggle doesn't change its contents when clicking on it */ - if (!toggle.hasAttribute('data-toggle-alt-content')) { - return; - } - - if (!toggle.hasAttribute('data-toggle-original-content')) { - toggle.setAttribute('data-toggle-original-content', toggle.innerHTML); - } - - var currentContent = toggle.innerHTML; - var originalContent = toggle.getAttribute('data-toggle-original-content'); - var altContent = toggle.getAttribute('data-toggle-alt-content'); - toggle.innerHTML = currentContent !== altContent ? altContent : originalContent; - }); - - /* Prevents from disallowing clicks on links inside toggles */ - var toggleLinks = toggles[i].querySelectorAll('a'); - for (var j = 0; j < toggleLinks.length; j++) { - addEventListener(toggleLinks[j], 'click', function(e) { - e.stopPropagation(); - }); - } - - /* Prevents from disallowing clicks on "copy to clipboard" elements inside toggles */ - var copyToClipboardElements = toggles[i].querySelectorAll('span[data-clipboard-text]'); - for (var k = 0; k < copyToClipboardElements.length; k++) { - addEventListener(copyToClipboardElements[k], 'click', function(e) { - e.stopPropagation(); - }); - } - - toggles[i].setAttribute('data-processed', 'true'); - } - }, - - createFilters: function() { - document.querySelectorAll('[data-filters] [data-filter]').forEach(function (filter) { - var filters = filter.closest('[data-filters]'), - type = 'choice', - name = filter.dataset.filter, - ucName = name.charAt(0).toUpperCase()+name.slice(1), - list = document.createElement('ul'), - values = filters.dataset['filter'+ucName] || filters.querySelectorAll('[data-filter-'+name+']'), - labels = {}, - defaults = null, - indexed = {}, - processed = {}; - if (typeof values === 'string') { - type = 'level'; - labels = values.split(','); - values = values.toLowerCase().split(','); - defaults = values.length - 1; - } - addClass(list, 'filter-list'); - addClass(list, 'filter-list-'+type); - values.forEach(function (value, i) { - if (value instanceof HTMLElement) { - value = value.dataset['filter'+ucName]; - } - if (value in processed) { - return; - } - var option = document.createElement('li'), - label = i in labels ? labels[i] : value, - active = false, - matches; - if ('' === label) { - option.innerHTML = '<em>(none)</em>'; - } else { - option.innerText = label; - } - option.dataset.filter = value; - option.setAttribute('title', 1 === (matches = filters.querySelectorAll('[data-filter-'+name+'="'+value+'"]').length) ? 'Matches 1 row' : 'Matches '+matches+' rows'); - indexed[value] = i; - list.appendChild(option); - addEventListener(option, 'click', function () { - if ('choice' === type) { - filters.querySelectorAll('[data-filter-'+name+']').forEach(function (row) { - if (option.dataset.filter === row.dataset['filter'+ucName]) { - toggleClass(row, 'filter-hidden-'+name); - } - }); - toggleClass(option, 'active'); - } else if ('level' === type) { - if (i === this.parentNode.querySelectorAll('.active').length - 1) { - return; - } - this.parentNode.querySelectorAll('li').forEach(function (currentOption, j) { - if (j <= i) { - addClass(currentOption, 'active'); - if (i === j) { - addClass(currentOption, 'last-active'); - } else { - removeClass(currentOption, 'last-active'); - } - } else { - removeClass(currentOption, 'active'); - removeClass(currentOption, 'last-active'); - } - }); - filters.querySelectorAll('[data-filter-'+name+']').forEach(function (row) { - if (i < indexed[row.dataset['filter'+ucName]]) { - addClass(row, 'filter-hidden-'+name); - } else { - removeClass(row, 'filter-hidden-'+name); - } - }); - } - }); - if ('choice' === type) { - active = null === defaults || 0 <= defaults.indexOf(value); - } else if ('level' === type) { - active = i <= defaults; - if (active && i === defaults) { - addClass(option, 'last-active'); - } - } - if (active) { - addClass(option, 'active'); - } else { - filters.querySelectorAll('[data-filter-'+name+'="'+value+'"]').forEach(function (row) { - toggleClass(row, 'filter-hidden-'+name); - }); - } - processed[value] = true; - }); - - if (1 < list.childNodes.length) { - filter.appendChild(list); - filter.dataset.filtered = ''; - } - }); - } - }; - })(); - - Sfjs.addEventListener(document, 'DOMContentLoaded', function() { - Sfjs.createTabs(); - Sfjs.createToggles(); - Sfjs.createFilters(); - }); -} -/*]]>*/ diff --git a/lib/symfony/error-handler/Resources/bin/extract-tentative-return-types.php b/lib/symfony/error-handler/Resources/bin/extract-tentative-return-types.php deleted file mode 100644 index cc98f58b5..000000000 --- a/lib/symfony/error-handler/Resources/bin/extract-tentative-return-types.php +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env php -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -// Run from the root of the php-src repository, this script generates -// a table with all the methods that have a tentative return type. -// -// Usage: find -name *.stub.php | sort | /path/to/extract-tentative-return-types.php > /path/to/TentativeTypes.php - -echo <<<EOPHP -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\Internal; - -/** - * This class has been generated by extract-tentative-return-types.php. - * - * @internal - */ -class TentativeTypes -{ - public const RETURN_TYPES = [ - -EOPHP; - -while (false !== $file = fgets(\STDIN)) { - $code = file_get_contents(substr($file, 0, -1)); - - if (!str_contains($code, '@tentative-return-type')) { - continue; - } - - $code = preg_split('{^\s*(?:(?:abstract )?class|interface|trait) ([^\s]++)}m', $code, -1, \PREG_SPLIT_DELIM_CAPTURE); - - if (1 === count($code)) { - continue; - } - - for ($i = 1; null !== $class = $code[$i] ?? null; $i += 2) { - $methods = $code[1 + $i]; - - if (!str_contains($methods, '@tentative-return-type')) { - continue; - } - - echo " '$class' => [\n"; - - preg_replace_callback('{@tentative-return-type.*?[\s]function ([^(]++)[^)]++\)\s*+:\s*+([^\n;\{]++)}s', function ($m) { - $m[2] = str_replace(' ', '', $m[2]); - echo " '$m[1]' => '$m[2]',\n"; - - return ''; - }, $methods); - - echo " ],\n"; - } -} - -echo <<<EOPHP - ]; -} - -EOPHP; diff --git a/lib/symfony/error-handler/Resources/bin/patch-type-declarations b/lib/symfony/error-handler/Resources/bin/patch-type-declarations deleted file mode 100644 index efcfcb25d..000000000 --- a/lib/symfony/error-handler/Resources/bin/patch-type-declarations +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/env php -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -if (\in_array('-h', $argv) || \in_array('--help', $argv)) { - echo implode(PHP_EOL, [ - ' Patches type declarations based on "@return" PHPDoc and triggers deprecations for', - ' incompatible method declarations.', - '', - ' This assists you to make your package compatible with Symfony 6, but it can be used', - ' for any class/package.', - '', - ' Available configuration via environment variables:', - ' SYMFONY_PATCH_TYPE_DECLARATIONS', - ' An url-encoded string to change the behavior of the script. Available parameters:', - ' - "force": any value enables deprecation notices - can be any of:', - ' - "phpdoc" to patch only docblock annotations', - ' - "2" to add all possible return types', - ' - "1" to add return types but only to tests/final/internal/private methods', - ' - "php": the target version of PHP - e.g. "7.1" doesn\'t generate "object" types', - ' - "deprecations": "1" to trigger a deprecation notice when a child class misses a', - ' return type while the parent declares an "@return" annotation', - '', - ' SYMFONY_PATCH_TYPE_EXCLUDE', - ' A regex matched against the full path to the class - any match will be excluded', - '', - ' Example: "SYMFONY_PATCH_TYPE_DECLARATIONS=php=7.4 ./patch-type-declarations"', - ]); - exit; -} - -if (false === getenv('SYMFONY_PATCH_TYPE_DECLARATIONS')) { - putenv('SYMFONY_PATCH_TYPE_DECLARATIONS=force=2'); - echo 'No SYMFONY_PATCH_TYPE_DECLARATIONS env var set, patching type declarations in all methods (run the command with "-h" for more information).'.PHP_EOL; -} - -if (is_file($autoload = __DIR__.'/../../../../autoload.php')) { - // noop -} elseif (is_file($autoload = __DIR__.'/../../../../../../../autoload.php')) { - // noop -} else { - echo PHP_EOL.' /!\ Cannot find the Composer autoloader, did you forget to run "composer install"?'.PHP_EOL; - exit(1); -} - -if (is_file($phpunitAutoload = dirname($autoload).'/bin/.phpunit/phpunit/vendor/autoload.php')) { - require $phpunitAutoload; -} - -$loader = require $autoload; - -Symfony\Component\ErrorHandler\DebugClassLoader::enable(); - -$deprecations = []; -set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$deprecations) { - if (\E_USER_DEPRECATED !== $type) { - return; - } - - [,,,,, $class,] = explode('"', $msg); - $deprecations[$class][] = $msg; -}); - -$exclude = getenv('SYMFONY_PATCH_TYPE_EXCLUDE') ?: null; -foreach ($loader->getClassMap() as $class => $file) { - if (false !== strpos($file = realpath($file), \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR)) { - continue; - } - - if ($exclude && preg_match($exclude, $file)) { - continue; - } - - class_exists($class); -} - -Symfony\Component\ErrorHandler\DebugClassLoader::checkClasses(); - -foreach ($deprecations as $class => $classDeprecations) { - echo $class.' ('.\count($classDeprecations).')'.PHP_EOL; - echo implode(PHP_EOL, $classDeprecations).PHP_EOL.PHP_EOL; -} - -if ($deprecations && false !== strpos(getenv('SYMFONY_PATCH_TYPE_DECLARATIONS') ?? '', 'force')) { - echo 'These deprecations might be fixed by the patch script, run this again to check for type deprecations.'.PHP_EOL; -} diff --git a/lib/symfony/error-handler/Resources/views/error.html.php b/lib/symfony/error-handler/Resources/views/error.html.php deleted file mode 100644 index 5416d03c8..000000000 --- a/lib/symfony/error-handler/Resources/views/error.html.php +++ /dev/null @@ -1,20 +0,0 @@ -<!DOCTYPE html> -<html> -<head> - <meta charset="<?= $this->charset; ?>" /> - <meta name="robots" content="noindex,nofollow,noarchive" /> - <title>An Error Occurred: <?= $statusText; ?></title> - <style><?= $this->include('assets/css/error.css'); ?></style> -</head> -<body> -<div class="container"> - <h1>Oops! An Error Occurred</h1> - <h2>The server returned a "<?= $statusCode; ?> <?= $statusText; ?>".</h2> - - <p> - Something is broken. Please let us know what you were doing when this error occurred. - We will fix it as soon as possible. Sorry for any inconvenience caused. - </p> -</div> -</body> -</html> diff --git a/lib/symfony/error-handler/Resources/views/exception.html.php b/lib/symfony/error-handler/Resources/views/exception.html.php deleted file mode 100644 index c3e7a8674..000000000 --- a/lib/symfony/error-handler/Resources/views/exception.html.php +++ /dev/null @@ -1,116 +0,0 @@ -<div class="exception-summary <?= !$exceptionMessage ? 'exception-without-message' : ''; ?>"> - <div class="exception-metadata"> - <div class="container"> - <h2 class="exception-hierarchy"> - <?php foreach (array_reverse($exception->getAllPrevious(), true) as $index => $previousException) { ?> - <a href="#trace-box-<?= $index + 2; ?>"><?= $this->abbrClass($previousException->getClass()); ?></a> - <span class="icon"><?= $this->include('assets/images/chevron-right.svg'); ?></span> - <?php } ?> - <a href="#trace-box-1"><?= $this->abbrClass($exception->getClass()); ?></a> - </h2> - <h2 class="exception-http"> - HTTP <?= $statusCode; ?> <small><?= $statusText; ?></small> - </h2> - </div> - </div> - - <div class="exception-message-wrapper"> - <div class="container"> - <h1 class="break-long-words exception-message<?= mb_strlen($exceptionMessage) > 180 ? ' long' : ''; ?>"><?= $this->formatFileFromText(nl2br($exceptionMessage)); ?></h1> - - <div class="exception-illustration hidden-xs-down"> - <?= $this->include('assets/images/symfony-ghost.svg.php'); ?> - </div> - </div> - </div> -</div> - -<div class="container"> - <div class="sf-tabs"> - <div class="tab"> - <?php - $exceptionAsArray = $exception->toArray(); - $exceptionWithUserCode = []; - $exceptionAsArrayCount = count($exceptionAsArray); - $last = $exceptionAsArrayCount - 1; - foreach ($exceptionAsArray as $i => $e) { - foreach ($e['trace'] as $trace) { - if ($trace['file'] && false === mb_strpos($trace['file'], '/vendor/') && false === mb_strpos($trace['file'], '/var/cache/') && $i < $last) { - $exceptionWithUserCode[] = $i; - } - } - } - ?> - <h3 class="tab-title"> - <?php if ($exceptionAsArrayCount > 1) { ?> - Exceptions <span class="badge"><?= $exceptionAsArrayCount; ?></span> - <?php } else { ?> - Exception - <?php } ?> - </h3> - - <div class="tab-content"> - <?php - foreach ($exceptionAsArray as $i => $e) { - echo $this->include('views/traces.html.php', [ - 'exception' => $e, - 'index' => $i + 1, - 'expand' => in_array($i, $exceptionWithUserCode, true) || ([] === $exceptionWithUserCode && 0 === $i), - ]); - } - ?> - </div> - </div> - - <?php if ($logger) { ?> - <div class="tab <?= !$logger->getLogs() ? 'disabled' : ''; ?>"> - <h3 class="tab-title"> - Logs - <?php if ($logger->countErrors()) { ?><span class="badge status-error"><?= $logger->countErrors(); ?></span><?php } ?> - </h3> - - <div class="tab-content"> - <?php if ($logger->getLogs()) { ?> - <?= $this->include('views/logs.html.php', ['logs' => $logger->getLogs()]); ?> - <?php } else { ?> - <div class="empty"> - <p>No log messages</p> - </div> - <?php } ?> - </div> - </div> - <?php } ?> - - <div class="tab"> - <h3 class="tab-title"> - <?php if ($exceptionAsArrayCount > 1) { ?> - Stack Traces <span class="badge"><?= $exceptionAsArrayCount; ?></span> - <?php } else { ?> - Stack Trace - <?php } ?> - </h3> - - <div class="tab-content"> - <?php - foreach ($exceptionAsArray as $i => $e) { - echo $this->include('views/traces_text.html.php', [ - 'exception' => $e, - 'index' => $i + 1, - 'numExceptions' => $exceptionAsArrayCount, - ]); - } - ?> - </div> - </div> - - <?php if ($currentContent) { ?> - <div class="tab"> - <h3 class="tab-title">Output content</h3> - - <div class="tab-content"> - <?= $currentContent; ?> - </div> - </div> - <?php } ?> - </div> -</div> diff --git a/lib/symfony/error-handler/Resources/views/exception_full.html.php b/lib/symfony/error-handler/Resources/views/exception_full.html.php deleted file mode 100644 index 04f0fd579..000000000 --- a/lib/symfony/error-handler/Resources/views/exception_full.html.php +++ /dev/null @@ -1,42 +0,0 @@ -<!-- <?= $_message = sprintf('%s (%d %s)', $exceptionMessage, $statusCode, $statusText); ?> --> -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="<?= $this->charset; ?>" /> - <meta name="robots" content="noindex,nofollow" /> - <meta name="viewport" content="width=device-width,initial-scale=1" /> - <title><?= $_message; ?></title> - <link rel="icon" type="image/png" href="<?= $this->include('assets/images/favicon.png.base64'); ?>"> - <style><?= $this->include('assets/css/exception.css'); ?></style> - <style><?= $this->include('assets/css/exception_full.css'); ?></style> - </head> - <body> - <script> - document.body.classList.add( - localStorage.getItem('symfony/profiler/theme') || (matchMedia('(prefers-color-scheme: dark)').matches ? 'theme-dark' : 'theme-light') - ); - </script> - - <?php if (class_exists(\Symfony\Component\HttpKernel\Kernel::class)) { ?> - <header> - <div class="container"> - <h1 class="logo"><?= $this->include('assets/images/symfony-logo.svg'); ?> Symfony Exception</h1> - - <div class="help-link"> - <a href="https://symfony.com/doc/<?= Symfony\Component\HttpKernel\Kernel::VERSION; ?>/index.html"> - <span class="icon"><?= $this->include('assets/images/icon-book.svg'); ?></span> - <span class="hidden-xs-down">Symfony</span> Docs - </a> - </div> - </div> - </header> - <?php } ?> - - <?= $this->include('views/exception.html.php', $context); ?> - - <script> - <?= $this->include('assets/js/exception.js'); ?> - </script> - </body> -</html> -<!-- <?= $_message; ?> --> diff --git a/lib/symfony/error-handler/Resources/views/logs.html.php b/lib/symfony/error-handler/Resources/views/logs.html.php deleted file mode 100644 index ea6e727b8..000000000 --- a/lib/symfony/error-handler/Resources/views/logs.html.php +++ /dev/null @@ -1,45 +0,0 @@ -<table class="logs" data-filter-level="Emergency,Alert,Critical,Error,Warning,Notice,Info,Debug" data-filters> -<?php $channelIsDefined = isset($logs[0]['channel']); ?> - <thead> - <tr> - <th data-filter="level">Level</th> - <?php if ($channelIsDefined) { ?><th data-filter="channel">Channel</th><?php } ?> - <th class="full-width">Message</th> - </tr> - </thead> - - <tbody> - <?php - foreach ($logs as $log) { - if ($log['priority'] >= 400) { - $status = 'error'; - } elseif ($log['priority'] >= 300) { - $status = 'warning'; - } else { - $severity = 0; - if (($exception = $log['context']['exception'] ?? null) instanceof \ErrorException || $exception instanceof \Symfony\Component\ErrorHandler\Exception\SilencedErrorContext) { - $severity = $exception->getSeverity(); - } - $status = \E_DEPRECATED === $severity || \E_USER_DEPRECATED === $severity ? 'warning' : 'normal'; - } ?> - <tr class="status-<?= $status; ?>" data-filter-level="<?= strtolower($this->escape($log['priorityName'])); ?>"<?php if ($channelIsDefined) { ?> data-filter-channel="<?= $this->escape($log['channel']); ?>"<?php } ?>> - <td class="text-small nowrap"> - <span class="colored text-bold"><?= $this->escape($log['priorityName']); ?></span> - <span class="text-muted newline"><?= date('H:i:s', $log['timestamp']); ?></span> - </td> - <?php if ($channelIsDefined) { ?> - <td class="text-small text-bold nowrap"> - <?= $this->escape($log['channel']); ?> - </td> - <?php } ?> - <td> - <?= $this->formatLogMessage($log['message'], $log['context']); ?> - <?php if ($log['context']) { ?> - <pre class="text-muted prewrap m-t-5"><?= $this->escape(json_encode($log['context'], \JSON_PRETTY_PRINT | \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES)); ?></pre> - <?php } ?> - </td> - </tr> - <?php - } ?> - </tbody> -</table> diff --git a/lib/symfony/error-handler/Resources/views/trace.html.php b/lib/symfony/error-handler/Resources/views/trace.html.php deleted file mode 100644 index 8dfdb4ec8..000000000 --- a/lib/symfony/error-handler/Resources/views/trace.html.php +++ /dev/null @@ -1,43 +0,0 @@ -<div class="trace-line-header break-long-words <?= $trace['file'] ? 'sf-toggle' : ''; ?>" data-toggle-selector="#trace-html-<?= $prefix; ?>-<?= $i; ?>" data-toggle-initial="<?= 'expanded' === $style ? 'display' : ''; ?>"> - <?php if ($trace['file']) { ?> - <span class="icon icon-close"><?= $this->include('assets/images/icon-minus-square.svg'); ?></span> - <span class="icon icon-open"><?= $this->include('assets/images/icon-plus-square.svg'); ?></span> - <?php } ?> - - <?php if ('compact' !== $style && $trace['function']) { ?> - <span class="trace-class"><?= $this->abbrClass($trace['class']); ?></span><?php if ($trace['type']) { ?><span class="trace-type"><?= $trace['type']; ?></span><?php } ?><span class="trace-method"><?= $trace['function']; ?></span><?php if (isset($trace['args'])) { ?><span class="trace-arguments">(<?= $this->formatArgs($trace['args']); ?>)</span><?php } ?> - <?php } ?> - - <?php if ($trace['file']) { ?> - <?php - $lineNumber = $trace['line'] ?: 1; - $fileLink = $this->getFileLink($trace['file'], $lineNumber); - $filePath = strtr(strip_tags($this->formatFile($trace['file'], $lineNumber)), [' at line '.$lineNumber => '']); - $filePathParts = explode(\DIRECTORY_SEPARATOR, $filePath); - ?> - <span class="block trace-file-path"> - in - <a href="<?= $fileLink; ?>"> - <?= implode(\DIRECTORY_SEPARATOR, array_slice($filePathParts, 0, -1)).\DIRECTORY_SEPARATOR; ?><strong><?= end($filePathParts); ?></strong> - </a> - <?php if ('compact' === $style && $trace['function']) { ?> - <span class="trace-type"><?= $trace['type']; ?></span> - <span class="trace-method"><?= $trace['function']; ?></span> - <?php } ?> - (line <?= $lineNumber; ?>) - <span class="icon icon-copy hidden" data-clipboard-text="<?php echo implode(\DIRECTORY_SEPARATOR, $filePathParts).':'.$lineNumber; ?>"> - <?php echo $this->include('assets/images/icon-copy.svg'); ?> - </span> - </span> - <?php } ?> -</div> -<?php if ($trace['file']) { ?> - <div id="trace-html-<?= $prefix.'-'.$i; ?>" class="trace-code sf-toggle-content"> - <?= strtr($this->fileExcerpt($trace['file'], $trace['line'], 5), [ - '#DD0000' => 'var(--highlight-string)', - '#007700' => 'var(--highlight-keyword)', - '#0000BB' => 'var(--highlight-default)', - '#FF8000' => 'var(--highlight-comment)', - ]); ?> - </div> -<?php } ?> diff --git a/lib/symfony/error-handler/Resources/views/traces.html.php b/lib/symfony/error-handler/Resources/views/traces.html.php deleted file mode 100644 index f64d91713..000000000 --- a/lib/symfony/error-handler/Resources/views/traces.html.php +++ /dev/null @@ -1,51 +0,0 @@ -<div class="trace trace-as-html" id="trace-box-<?= $index; ?>"> - <div class="trace-details"> - <div class="trace-head"> - <div class="sf-toggle" data-toggle-selector="#trace-html-<?= $index; ?>" data-toggle-initial="<?= $expand ? 'display' : ''; ?>"> - <span class="icon icon-close"><?= $this->include('assets/images/icon-minus-square-o.svg'); ?></span> - <span class="icon icon-open"><?= $this->include('assets/images/icon-plus-square-o.svg'); ?></span> - <?php - $separator = strrpos($exception['class'], '\\'); - $separator = false === $separator ? 0 : $separator + 1; - - $namespace = substr($exception['class'], 0, $separator); - $class = substr($exception['class'], $separator); - ?> - <?php if ('' === $class) { ?> - </br> - <?php } else { ?> - <h3 class="trace-class"> - <?php if ('' !== $namespace) { ?> - <span class="trace-namespace"><?= $namespace; ?></span> - <?php } ?> - <?= $class; ?> - </h3> - <?php } ?> - <?php if ($exception['message'] && $index > 1) { ?> - <p class="break-long-words trace-message"><?= $this->escape($exception['message']); ?></p> - <?php } ?> - </div> - </div> - - <div id="trace-html-<?= $index; ?>" class="sf-toggle-content"> - <?php - $isFirstUserCode = true; - foreach ($exception['trace'] as $i => $trace) { - $isVendorTrace = $trace['file'] && (false !== mb_strpos($trace['file'], '/vendor/') || false !== mb_strpos($trace['file'], '/var/cache/')); - $displayCodeSnippet = $isFirstUserCode && !$isVendorTrace; - if ($displayCodeSnippet) { - $isFirstUserCode = false; - } ?> - <div class="trace-line <?= $isVendorTrace ? 'trace-from-vendor' : ''; ?>"> - <?= $this->include('views/trace.html.php', [ - 'prefix' => $index, - 'i' => $i, - 'trace' => $trace, - 'style' => $isVendorTrace ? 'compact' : ($displayCodeSnippet ? 'expanded' : ''), - ]); ?> - </div> - <?php - } ?> - </div> - </div> -</div> diff --git a/lib/symfony/error-handler/Resources/views/traces_text.html.php b/lib/symfony/error-handler/Resources/views/traces_text.html.php deleted file mode 100644 index 6b478402c..000000000 --- a/lib/symfony/error-handler/Resources/views/traces_text.html.php +++ /dev/null @@ -1,43 +0,0 @@ -<table class="trace trace-as-text"> - <thead class="trace-head"> - <tr> - <th class="sf-toggle" data-toggle-selector="#trace-text-<?= $index; ?>" data-toggle-initial="<?= 1 === $index ? 'display' : ''; ?>"> - <div class="trace-class"> - <?php if ($numExceptions > 1) { ?> - <span class="text-muted">[<?= $numExceptions - $index + 1; ?>/<?= $numExceptions; ?>]</span> - <?php } ?> - <?= ($parts = explode('\\', $exception['class'])) ? end($parts) : ''; ?> - <span class="icon icon-close"><?= $this->include('assets/images/icon-minus-square-o.svg'); ?></span> - <span class="icon icon-open"><?= $this->include('assets/images/icon-plus-square-o.svg'); ?></span> - </div> - </th> - </tr> - </thead> - - <tbody id="trace-text-<?= $index; ?>"> - <tr> - <td> - <?php if ($exception['trace']) { ?> - <pre class="stacktrace"> -<?php - echo $this->escape($exception['class']).":\n"; - if ($exception['message']) { - echo $this->escape($exception['message'])."\n"; - } - - foreach ($exception['trace'] as $trace) { - echo "\n "; - if ($trace['function']) { - echo $this->escape('at '.$trace['class'].$trace['type'].$trace['function']).'('.(isset($trace['args']) ? $this->formatArgsAsText($trace['args']) : '').')'; - } - if ($trace['file'] && $trace['line']) { - echo($trace['function'] ? "\n (" : 'at ').strtr(strip_tags($this->formatFile($trace['file'], $trace['line'])), [' at line '.$trace['line'] => '']).':'.$trace['line'].($trace['function'] ? ')' : ''); - } - } -?> - </pre> - <?php } ?> - </td> - </tr> - </tbody> -</table> diff --git a/lib/symfony/error-handler/ThrowableUtils.php b/lib/symfony/error-handler/ThrowableUtils.php deleted file mode 100644 index 18d04988a..000000000 --- a/lib/symfony/error-handler/ThrowableUtils.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler; - -use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext; - -/** - * @internal - */ -class ThrowableUtils -{ - /** - * @param SilencedErrorContext|\Throwable - */ - public static function getSeverity($throwable): int - { - if ($throwable instanceof \ErrorException || $throwable instanceof SilencedErrorContext) { - return $throwable->getSeverity(); - } - - if ($throwable instanceof \ParseError) { - return \E_PARSE; - } - - if ($throwable instanceof \TypeError) { - return \E_RECOVERABLE_ERROR; - } - - return \E_ERROR; - } -} diff --git a/lib/symfony/error-handler/composer.json b/lib/symfony/error-handler/composer.json deleted file mode 100644 index bc0d88e9d..000000000 --- a/lib/symfony/error-handler/composer.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "symfony/error-handler", - "type": "library", - "description": "Provides tools to manage errors and ease debugging PHP code", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^4.4|^5.0|^6.0" - }, - "require-dev": { - "symfony/http-kernel": "^4.4|^5.0|^6.0", - "symfony/serializer": "^4.4|^5.0|^6.0", - "symfony/deprecation-contracts": "^2.1|^3" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\ErrorHandler\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "bin": [ - "Resources/bin/patch-type-declarations" - ], - "minimum-stability": "dev" -} diff --git a/lib/symfony/event-dispatcher-contracts/.gitignore b/lib/symfony/event-dispatcher-contracts/.gitignore deleted file mode 100644 index c49a5d8df..000000000 --- a/lib/symfony/event-dispatcher-contracts/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -vendor/ -composer.lock -phpunit.xml diff --git a/lib/symfony/event-dispatcher-contracts/CHANGELOG.md b/lib/symfony/event-dispatcher-contracts/CHANGELOG.md deleted file mode 100644 index 7932e2613..000000000 --- a/lib/symfony/event-dispatcher-contracts/CHANGELOG.md +++ /dev/null @@ -1,5 +0,0 @@ -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/lib/symfony/event-dispatcher-contracts/Event.php b/lib/symfony/event-dispatcher-contracts/Event.php deleted file mode 100644 index 46dcb2ba0..000000000 --- a/lib/symfony/event-dispatcher-contracts/Event.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\EventDispatcher; - -use Psr\EventDispatcher\StoppableEventInterface; - -/** - * Event is the base class for classes containing event data. - * - * This class contains no event data. It is used by events that do not pass - * state information to an event handler when an event is raised. - * - * You can call the method stopPropagation() to abort the execution of - * further listeners in your event listener. - * - * @author Guilherme Blanco <guilhermeblanco@hotmail.com> - * @author Jonathan Wage <jonwage@gmail.com> - * @author Roman Borschel <roman@code-factory.org> - * @author Bernhard Schussek <bschussek@gmail.com> - * @author Nicolas Grekas <p@tchwork.com> - */ -class Event implements StoppableEventInterface -{ - private $propagationStopped = false; - - /** - * {@inheritdoc} - */ - public function isPropagationStopped(): bool - { - return $this->propagationStopped; - } - - /** - * Stops the propagation of the event to further event listeners. - * - * If multiple event listeners are connected to the same event, no - * further event listener will be triggered once any trigger calls - * stopPropagation(). - */ - public function stopPropagation(): void - { - $this->propagationStopped = true; - } -} diff --git a/lib/symfony/event-dispatcher-contracts/EventDispatcherInterface.php b/lib/symfony/event-dispatcher-contracts/EventDispatcherInterface.php deleted file mode 100644 index 351dc5131..000000000 --- a/lib/symfony/event-dispatcher-contracts/EventDispatcherInterface.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\EventDispatcher; - -use Psr\EventDispatcher\EventDispatcherInterface as PsrEventDispatcherInterface; - -/** - * Allows providing hooks on domain-specific lifecycles by dispatching events. - */ -interface EventDispatcherInterface extends PsrEventDispatcherInterface -{ - /** - * Dispatches an event to all registered listeners. - * - * @param object $event The event to pass to the event handlers/listeners - * @param string|null $eventName The name of the event to dispatch. If not supplied, - * the class of $event should be used instead. - * - * @return object The passed $event MUST be returned - */ - public function dispatch(object $event, string $eventName = null): object; -} diff --git a/lib/symfony/event-dispatcher-contracts/LICENSE b/lib/symfony/event-dispatcher-contracts/LICENSE deleted file mode 100644 index 74cdc2dbf..000000000 --- a/lib/symfony/event-dispatcher-contracts/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -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/lib/symfony/event-dispatcher-contracts/README.md b/lib/symfony/event-dispatcher-contracts/README.md deleted file mode 100644 index b1ab4c00c..000000000 --- a/lib/symfony/event-dispatcher-contracts/README.md +++ /dev/null @@ -1,9 +0,0 @@ -Symfony EventDispatcher Contracts -================================= - -A set of abstractions extracted out of the Symfony components. - -Can be used to build on semantics that the Symfony components proved useful - and -that already have battle tested implementations. - -See https://github.com/symfony/contracts/blob/main/README.md for more information. diff --git a/lib/symfony/event-dispatcher-contracts/composer.json b/lib/symfony/event-dispatcher-contracts/composer.json deleted file mode 100644 index 660df81a0..000000000 --- a/lib/symfony/event-dispatcher-contracts/composer.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "symfony/event-dispatcher-contracts", - "type": "library", - "description": "Generic abstractions related to dispatching event", - "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "psr/event-dispatcher": "^1" - }, - "suggest": { - "symfony/event-dispatcher-implementation": "" - }, - "autoload": { - "psr-4": { "Symfony\\Contracts\\EventDispatcher\\": "" } - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - } -} diff --git a/lib/symfony/event-dispatcher/Attribute/AsEventListener.php b/lib/symfony/event-dispatcher/Attribute/AsEventListener.php deleted file mode 100644 index bb931b82d..000000000 --- a/lib/symfony/event-dispatcher/Attribute/AsEventListener.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher\Attribute; - -/** - * Service tag to autoconfigure event listeners. - * - * @author Alexander M. Turek <me@derrabus.de> - */ -#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] -class AsEventListener -{ - public function __construct( - public ?string $event = null, - public ?string $method = null, - public int $priority = 0, - public ?string $dispatcher = null, - ) { - } -} diff --git a/lib/symfony/event-dispatcher/CHANGELOG.md b/lib/symfony/event-dispatcher/CHANGELOG.md deleted file mode 100644 index 0f9859895..000000000 --- a/lib/symfony/event-dispatcher/CHANGELOG.md +++ /dev/null @@ -1,91 +0,0 @@ -CHANGELOG -========= - -5.4 ---- - - * Allow `#[AsEventListener]` attribute on methods - -5.3 ---- - - * Add `#[AsEventListener]` attribute for declaring listeners on PHP 8 - -5.1.0 ------ - - * The `LegacyEventDispatcherProxy` class has been deprecated. - * Added an optional `dispatcher` attribute to the listener and subscriber tags in `RegisterListenerPass`. - -5.0.0 ------ - - * The signature of the `EventDispatcherInterface::dispatch()` method has been changed to `dispatch($event, string $eventName = null): object`. - * The `Event` class has been removed in favor of `Symfony\Contracts\EventDispatcher\Event`. - * The `TraceableEventDispatcherInterface` has been removed. - * The `WrappedListener` class is now final. - -4.4.0 ------ - - * `AddEventAliasesPass` has been added, allowing applications and bundles to extend the event alias mapping used by `RegisterListenersPass`. - * Made the `event` attribute of the `kernel.event_listener` tag optional for FQCN events. - -4.3.0 ------ - - * The signature of the `EventDispatcherInterface::dispatch()` method should be updated to `dispatch($event, string $eventName = null)`, not doing so is deprecated - * deprecated the `Event` class, use `Symfony\Contracts\EventDispatcher\Event` instead - -4.1.0 ------ - - * added support for invokable event listeners tagged with `kernel.event_listener` by default - * The `TraceableEventDispatcher::getOrphanedEvents()` method has been added. - * The `TraceableEventDispatcherInterface` has been deprecated. - -4.0.0 ------ - - * removed the `ContainerAwareEventDispatcher` class - * added the `reset()` method to the `TraceableEventDispatcherInterface` - -3.4.0 ------ - - * Implementing `TraceableEventDispatcherInterface` without the `reset()` method has been deprecated. - -3.3.0 ------ - - * The ContainerAwareEventDispatcher class has been deprecated. Use EventDispatcher with closure factories instead. - -3.0.0 ------ - - * The method `getListenerPriority($eventName, $listener)` has been added to the - `EventDispatcherInterface`. - * The methods `Event::setDispatcher()`, `Event::getDispatcher()`, `Event::setName()` - and `Event::getName()` have been removed. - The event dispatcher and the event name are passed to the listener call. - -2.5.0 ------ - - * added Debug\TraceableEventDispatcher (originally in HttpKernel) - * changed Debug\TraceableEventDispatcherInterface to extend EventDispatcherInterface - * added RegisterListenersPass (originally in HttpKernel) - -2.1.0 ------ - - * added TraceableEventDispatcherInterface - * added ContainerAwareEventDispatcher - * added a reference to the EventDispatcher on the Event - * added a reference to the Event name on the event - * added fluid interface to the dispatch() method which now returns the Event - object - * added GenericEvent event class - * added the possibility for subscribers to subscribe several times for the - same event - * added ImmutableEventDispatcher diff --git a/lib/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php b/lib/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php deleted file mode 100644 index acfbf619c..000000000 --- a/lib/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php +++ /dev/null @@ -1,366 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher\Debug; - -use Psr\EventDispatcher\StoppableEventInterface; -use Psr\Log\LoggerInterface; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\Stopwatch\Stopwatch; -use Symfony\Contracts\Service\ResetInterface; - -/** - * Collects some data about event listeners. - * - * This event dispatcher delegates the dispatching to another one. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterface -{ - protected $logger; - protected $stopwatch; - - /** - * @var \SplObjectStorage<WrappedListener, array{string, string}> - */ - private $callStack; - private $dispatcher; - private $wrappedListeners; - private $orphanedEvents; - private $requestStack; - private $currentRequestHash = ''; - - public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null, RequestStack $requestStack = null) - { - $this->dispatcher = $dispatcher; - $this->stopwatch = $stopwatch; - $this->logger = $logger; - $this->wrappedListeners = []; - $this->orphanedEvents = []; - $this->requestStack = $requestStack; - } - - /** - * {@inheritdoc} - */ - public function addListener(string $eventName, $listener, int $priority = 0) - { - $this->dispatcher->addListener($eventName, $listener, $priority); - } - - /** - * {@inheritdoc} - */ - public function addSubscriber(EventSubscriberInterface $subscriber) - { - $this->dispatcher->addSubscriber($subscriber); - } - - /** - * {@inheritdoc} - */ - public function removeListener(string $eventName, $listener) - { - if (isset($this->wrappedListeners[$eventName])) { - foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) { - if ($wrappedListener->getWrappedListener() === $listener || ($listener instanceof \Closure && $wrappedListener->getWrappedListener() == $listener)) { - $listener = $wrappedListener; - unset($this->wrappedListeners[$eventName][$index]); - break; - } - } - } - - return $this->dispatcher->removeListener($eventName, $listener); - } - - /** - * {@inheritdoc} - */ - public function removeSubscriber(EventSubscriberInterface $subscriber) - { - return $this->dispatcher->removeSubscriber($subscriber); - } - - /** - * {@inheritdoc} - */ - public function getListeners(string $eventName = null) - { - return $this->dispatcher->getListeners($eventName); - } - - /** - * {@inheritdoc} - */ - public function getListenerPriority(string $eventName, $listener) - { - // we might have wrapped listeners for the event (if called while dispatching) - // in that case get the priority by wrapper - if (isset($this->wrappedListeners[$eventName])) { - foreach ($this->wrappedListeners[$eventName] as $wrappedListener) { - if ($wrappedListener->getWrappedListener() === $listener || ($listener instanceof \Closure && $wrappedListener->getWrappedListener() == $listener)) { - return $this->dispatcher->getListenerPriority($eventName, $wrappedListener); - } - } - } - - return $this->dispatcher->getListenerPriority($eventName, $listener); - } - - /** - * {@inheritdoc} - */ - public function hasListeners(string $eventName = null) - { - return $this->dispatcher->hasListeners($eventName); - } - - /** - * {@inheritdoc} - */ - public function dispatch(object $event, string $eventName = null): object - { - $eventName = $eventName ?? \get_class($event); - - if (null === $this->callStack) { - $this->callStack = new \SplObjectStorage(); - } - - $currentRequestHash = $this->currentRequestHash = $this->requestStack && ($request = $this->requestStack->getCurrentRequest()) ? spl_object_hash($request) : ''; - - if (null !== $this->logger && $event instanceof StoppableEventInterface && $event->isPropagationStopped()) { - $this->logger->debug(sprintf('The "%s" event is already stopped. No listeners have been called.', $eventName)); - } - - $this->preProcess($eventName); - try { - $this->beforeDispatch($eventName, $event); - try { - $e = $this->stopwatch->start($eventName, 'section'); - try { - $this->dispatcher->dispatch($event, $eventName); - } finally { - if ($e->isStarted()) { - $e->stop(); - } - } - } finally { - $this->afterDispatch($eventName, $event); - } - } finally { - $this->currentRequestHash = $currentRequestHash; - $this->postProcess($eventName); - } - - return $event; - } - - /** - * @return array - */ - public function getCalledListeners(Request $request = null) - { - if (null === $this->callStack) { - return []; - } - - $hash = $request ? spl_object_hash($request) : null; - $called = []; - foreach ($this->callStack as $listener) { - [$eventName, $requestHash] = $this->callStack->getInfo(); - if (null === $hash || $hash === $requestHash) { - $called[] = $listener->getInfo($eventName); - } - } - - return $called; - } - - /** - * @return array - */ - public function getNotCalledListeners(Request $request = null) - { - try { - $allListeners = $this->getListeners(); - } catch (\Exception $e) { - if (null !== $this->logger) { - $this->logger->info('An exception was thrown while getting the uncalled listeners.', ['exception' => $e]); - } - - // unable to retrieve the uncalled listeners - return []; - } - - $hash = $request ? spl_object_hash($request) : null; - $calledListeners = []; - - if (null !== $this->callStack) { - foreach ($this->callStack as $calledListener) { - [, $requestHash] = $this->callStack->getInfo(); - - if (null === $hash || $hash === $requestHash) { - $calledListeners[] = $calledListener->getWrappedListener(); - } - } - } - - $notCalled = []; - foreach ($allListeners as $eventName => $listeners) { - foreach ($listeners as $listener) { - if (!\in_array($listener, $calledListeners, true)) { - if (!$listener instanceof WrappedListener) { - $listener = new WrappedListener($listener, null, $this->stopwatch, $this); - } - $notCalled[] = $listener->getInfo($eventName); - } - } - } - - uasort($notCalled, [$this, 'sortNotCalledListeners']); - - return $notCalled; - } - - public function getOrphanedEvents(Request $request = null): array - { - if ($request) { - return $this->orphanedEvents[spl_object_hash($request)] ?? []; - } - - if (!$this->orphanedEvents) { - return []; - } - - return array_merge(...array_values($this->orphanedEvents)); - } - - public function reset() - { - $this->callStack = null; - $this->orphanedEvents = []; - $this->currentRequestHash = ''; - } - - /** - * Proxies all method calls to the original event dispatcher. - * - * @param string $method The method name - * @param array $arguments The method arguments - * - * @return mixed - */ - public function __call(string $method, array $arguments) - { - return $this->dispatcher->{$method}(...$arguments); - } - - /** - * Called before dispatching the event. - */ - protected function beforeDispatch(string $eventName, object $event) - { - } - - /** - * Called after dispatching the event. - */ - protected function afterDispatch(string $eventName, object $event) - { - } - - private function preProcess(string $eventName): void - { - if (!$this->dispatcher->hasListeners($eventName)) { - $this->orphanedEvents[$this->currentRequestHash][] = $eventName; - - return; - } - - foreach ($this->dispatcher->getListeners($eventName) as $listener) { - $priority = $this->getListenerPriority($eventName, $listener); - $wrappedListener = new WrappedListener($listener instanceof WrappedListener ? $listener->getWrappedListener() : $listener, null, $this->stopwatch, $this); - $this->wrappedListeners[$eventName][] = $wrappedListener; - $this->dispatcher->removeListener($eventName, $listener); - $this->dispatcher->addListener($eventName, $wrappedListener, $priority); - $this->callStack->attach($wrappedListener, [$eventName, $this->currentRequestHash]); - } - } - - private function postProcess(string $eventName): void - { - unset($this->wrappedListeners[$eventName]); - $skipped = false; - foreach ($this->dispatcher->getListeners($eventName) as $listener) { - if (!$listener instanceof WrappedListener) { // #12845: a new listener was added during dispatch. - continue; - } - // Unwrap listener - $priority = $this->getListenerPriority($eventName, $listener); - $this->dispatcher->removeListener($eventName, $listener); - $this->dispatcher->addListener($eventName, $listener->getWrappedListener(), $priority); - - if (null !== $this->logger) { - $context = ['event' => $eventName, 'listener' => $listener->getPretty()]; - } - - if ($listener->wasCalled()) { - if (null !== $this->logger) { - $this->logger->debug('Notified event "{event}" to listener "{listener}".', $context); - } - } else { - $this->callStack->detach($listener); - } - - if (null !== $this->logger && $skipped) { - $this->logger->debug('Listener "{listener}" was not called for event "{event}".', $context); - } - - if ($listener->stoppedPropagation()) { - if (null !== $this->logger) { - $this->logger->debug('Listener "{listener}" stopped propagation of the event "{event}".', $context); - } - - $skipped = true; - } - } - } - - private function sortNotCalledListeners(array $a, array $b) - { - if (0 !== $cmp = strcmp($a['event'], $b['event'])) { - return $cmp; - } - - if (\is_int($a['priority']) && !\is_int($b['priority'])) { - return 1; - } - - if (!\is_int($a['priority']) && \is_int($b['priority'])) { - return -1; - } - - if ($a['priority'] === $b['priority']) { - return 0; - } - - if ($a['priority'] > $b['priority']) { - return -1; - } - - return 1; - } -} diff --git a/lib/symfony/event-dispatcher/Debug/WrappedListener.php b/lib/symfony/event-dispatcher/Debug/WrappedListener.php deleted file mode 100644 index 3916716ec..000000000 --- a/lib/symfony/event-dispatcher/Debug/WrappedListener.php +++ /dev/null @@ -1,127 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher\Debug; - -use Psr\EventDispatcher\StoppableEventInterface; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\Stopwatch\Stopwatch; -use Symfony\Component\VarDumper\Caster\ClassStub; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -final class WrappedListener -{ - private $listener; - private $optimizedListener; - private $name; - private $called; - private $stoppedPropagation; - private $stopwatch; - private $dispatcher; - private $pretty; - private $stub; - private $priority; - private static $hasClassStub; - - public function __construct($listener, ?string $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null) - { - $this->listener = $listener; - $this->optimizedListener = $listener instanceof \Closure ? $listener : (\is_callable($listener) ? \Closure::fromCallable($listener) : null); - $this->stopwatch = $stopwatch; - $this->dispatcher = $dispatcher; - $this->called = false; - $this->stoppedPropagation = false; - - if (\is_array($listener)) { - $this->name = \is_object($listener[0]) ? get_debug_type($listener[0]) : $listener[0]; - $this->pretty = $this->name.'::'.$listener[1]; - } elseif ($listener instanceof \Closure) { - $r = new \ReflectionFunction($listener); - if (str_contains($r->name, '{closure}')) { - $this->pretty = $this->name = 'closure'; - } elseif ($class = $r->getClosureScopeClass()) { - $this->name = $class->name; - $this->pretty = $this->name.'::'.$r->name; - } else { - $this->pretty = $this->name = $r->name; - } - } elseif (\is_string($listener)) { - $this->pretty = $this->name = $listener; - } else { - $this->name = get_debug_type($listener); - $this->pretty = $this->name.'::__invoke'; - } - - if (null !== $name) { - $this->name = $name; - } - - if (null === self::$hasClassStub) { - self::$hasClassStub = class_exists(ClassStub::class); - } - } - - public function getWrappedListener() - { - return $this->listener; - } - - public function wasCalled(): bool - { - return $this->called; - } - - public function stoppedPropagation(): bool - { - return $this->stoppedPropagation; - } - - public function getPretty(): string - { - return $this->pretty; - } - - public function getInfo(string $eventName): array - { - if (null === $this->stub) { - $this->stub = self::$hasClassStub ? new ClassStub($this->pretty.'()', $this->listener) : $this->pretty.'()'; - } - - return [ - 'event' => $eventName, - 'priority' => null !== $this->priority ? $this->priority : (null !== $this->dispatcher ? $this->dispatcher->getListenerPriority($eventName, $this->listener) : null), - 'pretty' => $this->pretty, - 'stub' => $this->stub, - ]; - } - - public function __invoke(object $event, string $eventName, EventDispatcherInterface $dispatcher): void - { - $dispatcher = $this->dispatcher ?: $dispatcher; - - $this->called = true; - $this->priority = $dispatcher->getListenerPriority($eventName, $this->listener); - - $e = $this->stopwatch->start($this->name, 'event_listener'); - - ($this->optimizedListener ?? $this->listener)($event, $eventName, $dispatcher); - - if ($e->isStarted()) { - $e->stop(); - } - - if ($event instanceof StoppableEventInterface && $event->isPropagationStopped()) { - $this->stoppedPropagation = true; - } - } -} diff --git a/lib/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php b/lib/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php deleted file mode 100644 index 6e7292b4a..000000000 --- a/lib/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher\DependencyInjection; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * This pass allows bundles to extend the list of event aliases. - * - * @author Alexander M. Turek <me@derrabus.de> - */ -class AddEventAliasesPass implements CompilerPassInterface -{ - private $eventAliases; - private $eventAliasesParameter; - - public function __construct(array $eventAliases, string $eventAliasesParameter = 'event_dispatcher.event_aliases') - { - if (1 < \func_num_args()) { - trigger_deprecation('symfony/event-dispatcher', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->eventAliases = $eventAliases; - $this->eventAliasesParameter = $eventAliasesParameter; - } - - public function process(ContainerBuilder $container): void - { - $eventAliases = $container->hasParameter($this->eventAliasesParameter) ? $container->getParameter($this->eventAliasesParameter) : []; - - $container->setParameter( - $this->eventAliasesParameter, - array_merge($eventAliases, $this->eventAliases) - ); - } -} diff --git a/lib/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php b/lib/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php deleted file mode 100644 index 8eabe7d74..000000000 --- a/lib/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php +++ /dev/null @@ -1,238 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher\DependencyInjection; - -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\EventDispatcher\EventDispatcher; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Contracts\EventDispatcher\Event; - -/** - * Compiler pass to register tagged services for an event dispatcher. - */ -class RegisterListenersPass implements CompilerPassInterface -{ - protected $dispatcherService; - protected $listenerTag; - protected $subscriberTag; - protected $eventAliasesParameter; - - private $hotPathEvents = []; - private $hotPathTagName = 'container.hot_path'; - private $noPreloadEvents = []; - private $noPreloadTagName = 'container.no_preload'; - - public function __construct(string $dispatcherService = 'event_dispatcher', string $listenerTag = 'kernel.event_listener', string $subscriberTag = 'kernel.event_subscriber', string $eventAliasesParameter = 'event_dispatcher.event_aliases') - { - if (0 < \func_num_args()) { - trigger_deprecation('symfony/event-dispatcher', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->dispatcherService = $dispatcherService; - $this->listenerTag = $listenerTag; - $this->subscriberTag = $subscriberTag; - $this->eventAliasesParameter = $eventAliasesParameter; - } - - /** - * @return $this - */ - public function setHotPathEvents(array $hotPathEvents) - { - $this->hotPathEvents = array_flip($hotPathEvents); - - if (1 < \func_num_args()) { - trigger_deprecation('symfony/event-dispatcher', '5.4', 'Configuring "$tagName" in "%s" is deprecated.', __METHOD__); - $this->hotPathTagName = func_get_arg(1); - } - - return $this; - } - - /** - * @return $this - */ - public function setNoPreloadEvents(array $noPreloadEvents): self - { - $this->noPreloadEvents = array_flip($noPreloadEvents); - - if (1 < \func_num_args()) { - trigger_deprecation('symfony/event-dispatcher', '5.4', 'Configuring "$tagName" in "%s" is deprecated.', __METHOD__); - $this->noPreloadTagName = func_get_arg(1); - } - - return $this; - } - - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition($this->dispatcherService) && !$container->hasAlias($this->dispatcherService)) { - return; - } - - $aliases = []; - - if ($container->hasParameter($this->eventAliasesParameter)) { - $aliases = $container->getParameter($this->eventAliasesParameter); - } - - $globalDispatcherDefinition = $container->findDefinition($this->dispatcherService); - - foreach ($container->findTaggedServiceIds($this->listenerTag, true) as $id => $events) { - $noPreload = 0; - - foreach ($events as $event) { - $priority = $event['priority'] ?? 0; - - if (!isset($event['event'])) { - if ($container->getDefinition($id)->hasTag($this->subscriberTag)) { - continue; - } - - $event['method'] = $event['method'] ?? '__invoke'; - $event['event'] = $this->getEventFromTypeDeclaration($container, $id, $event['method']); - } - - $event['event'] = $aliases[$event['event']] ?? $event['event']; - - if (!isset($event['method'])) { - $event['method'] = 'on'.preg_replace_callback([ - '/(?<=\b|_)[a-z]/i', - '/[^a-z0-9]/i', - ], function ($matches) { return strtoupper($matches[0]); }, $event['event']); - $event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']); - - if (null !== ($class = $container->getDefinition($id)->getClass()) && ($r = $container->getReflectionClass($class, false)) && !$r->hasMethod($event['method']) && $r->hasMethod('__invoke')) { - $event['method'] = '__invoke'; - } - } - - $dispatcherDefinition = $globalDispatcherDefinition; - if (isset($event['dispatcher'])) { - $dispatcherDefinition = $container->getDefinition($event['dispatcher']); - } - - $dispatcherDefinition->addMethodCall('addListener', [$event['event'], [new ServiceClosureArgument(new Reference($id)), $event['method']], $priority]); - - if (isset($this->hotPathEvents[$event['event']])) { - $container->getDefinition($id)->addTag($this->hotPathTagName); - } elseif (isset($this->noPreloadEvents[$event['event']])) { - ++$noPreload; - } - } - - if ($noPreload && \count($events) === $noPreload) { - $container->getDefinition($id)->addTag($this->noPreloadTagName); - } - } - - $extractingDispatcher = new ExtractingEventDispatcher(); - - foreach ($container->findTaggedServiceIds($this->subscriberTag, true) as $id => $tags) { - $def = $container->getDefinition($id); - - // We must assume that the class value has been correctly filled, even if the service is created by a factory - $class = $def->getClass(); - - if (!$r = $container->getReflectionClass($class)) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); - } - if (!$r->isSubclassOf(EventSubscriberInterface::class)) { - throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, EventSubscriberInterface::class)); - } - $class = $r->name; - - $dispatcherDefinitions = []; - foreach ($tags as $attributes) { - if (!isset($attributes['dispatcher']) || isset($dispatcherDefinitions[$attributes['dispatcher']])) { - continue; - } - - $dispatcherDefinitions[$attributes['dispatcher']] = $container->getDefinition($attributes['dispatcher']); - } - - if (!$dispatcherDefinitions) { - $dispatcherDefinitions = [$globalDispatcherDefinition]; - } - - $noPreload = 0; - ExtractingEventDispatcher::$aliases = $aliases; - ExtractingEventDispatcher::$subscriber = $class; - $extractingDispatcher->addSubscriber($extractingDispatcher); - foreach ($extractingDispatcher->listeners as $args) { - $args[1] = [new ServiceClosureArgument(new Reference($id)), $args[1]]; - foreach ($dispatcherDefinitions as $dispatcherDefinition) { - $dispatcherDefinition->addMethodCall('addListener', $args); - } - - if (isset($this->hotPathEvents[$args[0]])) { - $container->getDefinition($id)->addTag($this->hotPathTagName); - } elseif (isset($this->noPreloadEvents[$args[0]])) { - ++$noPreload; - } - } - if ($noPreload && \count($extractingDispatcher->listeners) === $noPreload) { - $container->getDefinition($id)->addTag($this->noPreloadTagName); - } - $extractingDispatcher->listeners = []; - ExtractingEventDispatcher::$aliases = []; - } - } - - private function getEventFromTypeDeclaration(ContainerBuilder $container, string $id, string $method): string - { - if ( - null === ($class = $container->getDefinition($id)->getClass()) - || !($r = $container->getReflectionClass($class, false)) - || !$r->hasMethod($method) - || 1 > ($m = $r->getMethod($method))->getNumberOfParameters() - || !($type = $m->getParameters()[0]->getType()) instanceof \ReflectionNamedType - || $type->isBuiltin() - || Event::class === ($name = $type->getName()) - ) { - throw new InvalidArgumentException(sprintf('Service "%s" must define the "event" attribute on "%s" tags.', $id, $this->listenerTag)); - } - - return $name; - } -} - -/** - * @internal - */ -class ExtractingEventDispatcher extends EventDispatcher implements EventSubscriberInterface -{ - public $listeners = []; - - public static $aliases = []; - public static $subscriber; - - public function addListener(string $eventName, $listener, int $priority = 0) - { - $this->listeners[] = [$eventName, $listener[1], $priority]; - } - - public static function getSubscribedEvents(): array - { - $events = []; - - foreach ([self::$subscriber, 'getSubscribedEvents']() as $eventName => $params) { - $events[self::$aliases[$eventName] ?? $eventName] = $params; - } - - return $events; - } -} diff --git a/lib/symfony/event-dispatcher/EventDispatcher.php b/lib/symfony/event-dispatcher/EventDispatcher.php deleted file mode 100644 index 8fe8fb5c2..000000000 --- a/lib/symfony/event-dispatcher/EventDispatcher.php +++ /dev/null @@ -1,280 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher; - -use Psr\EventDispatcher\StoppableEventInterface; -use Symfony\Component\EventDispatcher\Debug\WrappedListener; - -/** - * The EventDispatcherInterface is the central point of Symfony's event listener system. - * - * Listeners are registered on the manager and events are dispatched through the - * manager. - * - * @author Guilherme Blanco <guilhermeblanco@hotmail.com> - * @author Jonathan Wage <jonwage@gmail.com> - * @author Roman Borschel <roman@code-factory.org> - * @author Bernhard Schussek <bschussek@gmail.com> - * @author Fabien Potencier <fabien@symfony.com> - * @author Jordi Boggiano <j.boggiano@seld.be> - * @author Jordan Alliot <jordan.alliot@gmail.com> - * @author Nicolas Grekas <p@tchwork.com> - */ -class EventDispatcher implements EventDispatcherInterface -{ - private $listeners = []; - private $sorted = []; - private $optimized; - - public function __construct() - { - if (__CLASS__ === static::class) { - $this->optimized = []; - } - } - - /** - * {@inheritdoc} - */ - public function dispatch(object $event, string $eventName = null): object - { - $eventName = $eventName ?? \get_class($event); - - if (null !== $this->optimized) { - $listeners = $this->optimized[$eventName] ?? (empty($this->listeners[$eventName]) ? [] : $this->optimizeListeners($eventName)); - } else { - $listeners = $this->getListeners($eventName); - } - - if ($listeners) { - $this->callListeners($listeners, $eventName, $event); - } - - return $event; - } - - /** - * {@inheritdoc} - */ - public function getListeners(string $eventName = null) - { - if (null !== $eventName) { - if (empty($this->listeners[$eventName])) { - return []; - } - - if (!isset($this->sorted[$eventName])) { - $this->sortListeners($eventName); - } - - return $this->sorted[$eventName]; - } - - foreach ($this->listeners as $eventName => $eventListeners) { - if (!isset($this->sorted[$eventName])) { - $this->sortListeners($eventName); - } - } - - return array_filter($this->sorted); - } - - /** - * {@inheritdoc} - */ - public function getListenerPriority(string $eventName, $listener) - { - if (empty($this->listeners[$eventName])) { - return null; - } - - if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) { - $listener[0] = $listener[0](); - $listener[1] = $listener[1] ?? '__invoke'; - } - - foreach ($this->listeners[$eventName] as $priority => &$listeners) { - foreach ($listeners as &$v) { - if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure && 2 >= \count($v)) { - $v[0] = $v[0](); - $v[1] = $v[1] ?? '__invoke'; - } - if ($v === $listener || ($listener instanceof \Closure && $v == $listener)) { - return $priority; - } - } - } - - return null; - } - - /** - * {@inheritdoc} - */ - public function hasListeners(string $eventName = null) - { - if (null !== $eventName) { - return !empty($this->listeners[$eventName]); - } - - foreach ($this->listeners as $eventListeners) { - if ($eventListeners) { - return true; - } - } - - return false; - } - - /** - * {@inheritdoc} - */ - public function addListener(string $eventName, $listener, int $priority = 0) - { - $this->listeners[$eventName][$priority][] = $listener; - unset($this->sorted[$eventName], $this->optimized[$eventName]); - } - - /** - * {@inheritdoc} - */ - public function removeListener(string $eventName, $listener) - { - if (empty($this->listeners[$eventName])) { - return; - } - - if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) { - $listener[0] = $listener[0](); - $listener[1] = $listener[1] ?? '__invoke'; - } - - foreach ($this->listeners[$eventName] as $priority => &$listeners) { - foreach ($listeners as $k => &$v) { - if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure && 2 >= \count($v)) { - $v[0] = $v[0](); - $v[1] = $v[1] ?? '__invoke'; - } - if ($v === $listener || ($listener instanceof \Closure && $v == $listener)) { - unset($listeners[$k], $this->sorted[$eventName], $this->optimized[$eventName]); - } - } - - if (!$listeners) { - unset($this->listeners[$eventName][$priority]); - } - } - } - - /** - * {@inheritdoc} - */ - public function addSubscriber(EventSubscriberInterface $subscriber) - { - foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { - if (\is_string($params)) { - $this->addListener($eventName, [$subscriber, $params]); - } elseif (\is_string($params[0])) { - $this->addListener($eventName, [$subscriber, $params[0]], $params[1] ?? 0); - } else { - foreach ($params as $listener) { - $this->addListener($eventName, [$subscriber, $listener[0]], $listener[1] ?? 0); - } - } - } - } - - /** - * {@inheritdoc} - */ - public function removeSubscriber(EventSubscriberInterface $subscriber) - { - foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { - if (\is_array($params) && \is_array($params[0])) { - foreach ($params as $listener) { - $this->removeListener($eventName, [$subscriber, $listener[0]]); - } - } else { - $this->removeListener($eventName, [$subscriber, \is_string($params) ? $params : $params[0]]); - } - } - } - - /** - * Triggers the listeners of an event. - * - * This method can be overridden to add functionality that is executed - * for each listener. - * - * @param callable[] $listeners The event listeners - * @param string $eventName The name of the event to dispatch - * @param object $event The event object to pass to the event handlers/listeners - */ - protected function callListeners(iterable $listeners, string $eventName, object $event) - { - $stoppable = $event instanceof StoppableEventInterface; - - foreach ($listeners as $listener) { - if ($stoppable && $event->isPropagationStopped()) { - break; - } - $listener($event, $eventName, $this); - } - } - - /** - * Sorts the internal list of listeners for the given event by priority. - */ - private function sortListeners(string $eventName) - { - krsort($this->listeners[$eventName]); - $this->sorted[$eventName] = []; - - foreach ($this->listeners[$eventName] as &$listeners) { - foreach ($listeners as $k => &$listener) { - if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) { - $listener[0] = $listener[0](); - $listener[1] = $listener[1] ?? '__invoke'; - } - $this->sorted[$eventName][] = $listener; - } - } - } - - /** - * Optimizes the internal list of listeners for the given event by priority. - */ - private function optimizeListeners(string $eventName): array - { - krsort($this->listeners[$eventName]); - $this->optimized[$eventName] = []; - - foreach ($this->listeners[$eventName] as &$listeners) { - foreach ($listeners as &$listener) { - $closure = &$this->optimized[$eventName][]; - if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) { - $closure = static function (...$args) use (&$listener, &$closure) { - if ($listener[0] instanceof \Closure) { - $listener[0] = $listener[0](); - $listener[1] = $listener[1] ?? '__invoke'; - } - ($closure = \Closure::fromCallable($listener))(...$args); - }; - } else { - $closure = $listener instanceof \Closure || $listener instanceof WrappedListener ? $listener : \Closure::fromCallable($listener); - } - } - } - - return $this->optimized[$eventName]; - } -} diff --git a/lib/symfony/event-dispatcher/EventDispatcherInterface.php b/lib/symfony/event-dispatcher/EventDispatcherInterface.php deleted file mode 100644 index cc324e1c6..000000000 --- a/lib/symfony/event-dispatcher/EventDispatcherInterface.php +++ /dev/null @@ -1,70 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher; - -use Symfony\Contracts\EventDispatcher\EventDispatcherInterface as ContractsEventDispatcherInterface; - -/** - * The EventDispatcherInterface is the central point of Symfony's event listener system. - * Listeners are registered on the manager and events are dispatched through the - * manager. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface EventDispatcherInterface extends ContractsEventDispatcherInterface -{ - /** - * Adds an event listener that listens on the specified events. - * - * @param int $priority The higher this value, the earlier an event - * listener will be triggered in the chain (defaults to 0) - */ - public function addListener(string $eventName, callable $listener, int $priority = 0); - - /** - * Adds an event subscriber. - * - * The subscriber is asked for all the events it is - * interested in and added as a listener for these events. - */ - public function addSubscriber(EventSubscriberInterface $subscriber); - - /** - * Removes an event listener from the specified events. - */ - public function removeListener(string $eventName, callable $listener); - - public function removeSubscriber(EventSubscriberInterface $subscriber); - - /** - * Gets the listeners of a specific event or all listeners sorted by descending priority. - * - * @return array<callable[]|callable> - */ - public function getListeners(string $eventName = null); - - /** - * Gets the listener priority for a specific event. - * - * Returns null if the event or the listener does not exist. - * - * @return int|null - */ - public function getListenerPriority(string $eventName, callable $listener); - - /** - * Checks whether an event has any registered listeners. - * - * @return bool - */ - public function hasListeners(string $eventName = null); -} diff --git a/lib/symfony/event-dispatcher/EventSubscriberInterface.php b/lib/symfony/event-dispatcher/EventSubscriberInterface.php deleted file mode 100644 index 2085e428e..000000000 --- a/lib/symfony/event-dispatcher/EventSubscriberInterface.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher; - -/** - * An EventSubscriber knows itself what events it is interested in. - * If an EventSubscriber is added to an EventDispatcherInterface, the manager invokes - * {@link getSubscribedEvents} and registers the subscriber as a listener for all - * returned events. - * - * @author Guilherme Blanco <guilhermeblanco@hotmail.com> - * @author Jonathan Wage <jonwage@gmail.com> - * @author Roman Borschel <roman@code-factory.org> - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface EventSubscriberInterface -{ - /** - * Returns an array of event names this subscriber wants to listen to. - * - * The array keys are event names and the value can be: - * - * * The method name to call (priority defaults to 0) - * * An array composed of the method name to call and the priority - * * An array of arrays composed of the method names to call and respective - * priorities, or 0 if unset - * - * For instance: - * - * * ['eventName' => 'methodName'] - * * ['eventName' => ['methodName', $priority]] - * * ['eventName' => [['methodName1', $priority], ['methodName2']]] - * - * The code must not depend on runtime state as it will only be called at compile time. - * All logic depending on runtime state must be put into the individual methods handling the events. - * - * @return array<string, string|array{0: string, 1: int}|list<array{0: string, 1?: int}>> - */ - public static function getSubscribedEvents(); -} diff --git a/lib/symfony/event-dispatcher/GenericEvent.php b/lib/symfony/event-dispatcher/GenericEvent.php deleted file mode 100644 index b32a301ae..000000000 --- a/lib/symfony/event-dispatcher/GenericEvent.php +++ /dev/null @@ -1,182 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher; - -use Symfony\Contracts\EventDispatcher\Event; - -/** - * Event encapsulation class. - * - * Encapsulates events thus decoupling the observer from the subject they encapsulate. - * - * @author Drak <drak@zikula.org> - * - * @implements \ArrayAccess<string, mixed> - * @implements \IteratorAggregate<string, mixed> - */ -class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate -{ - protected $subject; - protected $arguments; - - /** - * Encapsulate an event with $subject and $args. - * - * @param mixed $subject The subject of the event, usually an object or a callable - * @param array $arguments Arguments to store in the event - */ - public function __construct($subject = null, array $arguments = []) - { - $this->subject = $subject; - $this->arguments = $arguments; - } - - /** - * Getter for subject property. - * - * @return mixed - */ - public function getSubject() - { - return $this->subject; - } - - /** - * Get argument by key. - * - * @return mixed - * - * @throws \InvalidArgumentException if key is not found - */ - public function getArgument(string $key) - { - if ($this->hasArgument($key)) { - return $this->arguments[$key]; - } - - throw new \InvalidArgumentException(sprintf('Argument "%s" not found.', $key)); - } - - /** - * Add argument to event. - * - * @param mixed $value Value - * - * @return $this - */ - public function setArgument(string $key, $value) - { - $this->arguments[$key] = $value; - - return $this; - } - - /** - * Getter for all arguments. - * - * @return array - */ - public function getArguments() - { - return $this->arguments; - } - - /** - * Set args property. - * - * @return $this - */ - public function setArguments(array $args = []) - { - $this->arguments = $args; - - return $this; - } - - /** - * Has argument. - * - * @return bool - */ - public function hasArgument(string $key) - { - return \array_key_exists($key, $this->arguments); - } - - /** - * ArrayAccess for argument getter. - * - * @param string $key Array key - * - * @return mixed - * - * @throws \InvalidArgumentException if key does not exist in $this->args - */ - #[\ReturnTypeWillChange] - public function offsetGet($key) - { - return $this->getArgument($key); - } - - /** - * ArrayAccess for argument setter. - * - * @param string $key Array key to set - * @param mixed $value Value - * - * @return void - */ - #[\ReturnTypeWillChange] - public function offsetSet($key, $value) - { - $this->setArgument($key, $value); - } - - /** - * ArrayAccess for unset argument. - * - * @param string $key Array key - * - * @return void - */ - #[\ReturnTypeWillChange] - public function offsetUnset($key) - { - if ($this->hasArgument($key)) { - unset($this->arguments[$key]); - } - } - - /** - * ArrayAccess has argument. - * - * @param string $key Array key - * - * @return bool - */ - #[\ReturnTypeWillChange] - public function offsetExists($key) - { - return $this->hasArgument($key); - } - - /** - * IteratorAggregate for iterating over the object like an array. - * - * @return \ArrayIterator<string, mixed> - */ - #[\ReturnTypeWillChange] - public function getIterator() - { - return new \ArrayIterator($this->arguments); - } -} diff --git a/lib/symfony/event-dispatcher/ImmutableEventDispatcher.php b/lib/symfony/event-dispatcher/ImmutableEventDispatcher.php deleted file mode 100644 index 568d79c3a..000000000 --- a/lib/symfony/event-dispatcher/ImmutableEventDispatcher.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher; - -/** - * A read-only proxy for an event dispatcher. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class ImmutableEventDispatcher implements EventDispatcherInterface -{ - private $dispatcher; - - public function __construct(EventDispatcherInterface $dispatcher) - { - $this->dispatcher = $dispatcher; - } - - /** - * {@inheritdoc} - */ - public function dispatch(object $event, string $eventName = null): object - { - return $this->dispatcher->dispatch($event, $eventName); - } - - /** - * {@inheritdoc} - */ - public function addListener(string $eventName, $listener, int $priority = 0) - { - throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); - } - - /** - * {@inheritdoc} - */ - public function addSubscriber(EventSubscriberInterface $subscriber) - { - throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); - } - - /** - * {@inheritdoc} - */ - public function removeListener(string $eventName, $listener) - { - throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); - } - - /** - * {@inheritdoc} - */ - public function removeSubscriber(EventSubscriberInterface $subscriber) - { - throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); - } - - /** - * {@inheritdoc} - */ - public function getListeners(string $eventName = null) - { - return $this->dispatcher->getListeners($eventName); - } - - /** - * {@inheritdoc} - */ - public function getListenerPriority(string $eventName, $listener) - { - return $this->dispatcher->getListenerPriority($eventName, $listener); - } - - /** - * {@inheritdoc} - */ - public function hasListeners(string $eventName = null) - { - return $this->dispatcher->hasListeners($eventName); - } -} diff --git a/lib/symfony/event-dispatcher/LICENSE b/lib/symfony/event-dispatcher/LICENSE deleted file mode 100644 index 88bf75bb4..000000000 --- a/lib/symfony/event-dispatcher/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-2022 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -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/lib/symfony/event-dispatcher/LegacyEventDispatcherProxy.php b/lib/symfony/event-dispatcher/LegacyEventDispatcherProxy.php deleted file mode 100644 index 6e17c8fcc..000000000 --- a/lib/symfony/event-dispatcher/LegacyEventDispatcherProxy.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher; - -use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; - -trigger_deprecation('symfony/event-dispatcher', '5.1', '%s is deprecated, use the event dispatcher without the proxy.', LegacyEventDispatcherProxy::class); - -/** - * A helper class to provide BC/FC with the legacy signature of EventDispatcherInterface::dispatch(). - * - * @author Nicolas Grekas <p@tchwork.com> - * - * @deprecated since Symfony 5.1 - */ -final class LegacyEventDispatcherProxy -{ - public static function decorate(?EventDispatcherInterface $dispatcher): ?EventDispatcherInterface - { - return $dispatcher; - } -} diff --git a/lib/symfony/event-dispatcher/README.md b/lib/symfony/event-dispatcher/README.md deleted file mode 100644 index dcdb68d21..000000000 --- a/lib/symfony/event-dispatcher/README.md +++ /dev/null @@ -1,15 +0,0 @@ -EventDispatcher Component -========================= - -The EventDispatcher component provides tools that allow your application -components to communicate with each other by dispatching events and listening to -them. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/event_dispatcher.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/lib/symfony/event-dispatcher/composer.json b/lib/symfony/event-dispatcher/composer.json deleted file mode 100644 index 32b42e408..000000000 --- a/lib/symfony/event-dispatcher/composer.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "name": "symfony/event-dispatcher", - "type": "library", - "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/event-dispatcher-contracts": "^2|^3", - "symfony/polyfill-php80": "^1.16" - }, - "require-dev": { - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/stopwatch": "^4.4|^5.0|^6.0", - "psr/log": "^1|^2|^3" - }, - "conflict": { - "symfony/dependency-injection": "<4.4" - }, - "provide": { - "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\EventDispatcher\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/lib/symfony/filesystem/CHANGELOG.md b/lib/symfony/filesystem/CHANGELOG.md deleted file mode 100644 index fcb7170ca..000000000 --- a/lib/symfony/filesystem/CHANGELOG.md +++ /dev/null @@ -1,82 +0,0 @@ -CHANGELOG -========= - -5.4 ---- - - * Add `Path` class - * Add `$lock` argument to `Filesystem::appendToFile()` - -5.0.0 ------ - - * `Filesystem::dumpFile()` and `appendToFile()` don't accept arrays anymore - -4.4.0 ------ - - * support for passing a `null` value to `Filesystem::isAbsolutePath()` is deprecated and will be removed in 5.0 - * `tempnam()` now accepts a third argument `$suffix`. - -4.3.0 ------ - - * support for passing arrays to `Filesystem::dumpFile()` is deprecated and will be removed in 5.0 - * support for passing arrays to `Filesystem::appendToFile()` is deprecated and will be removed in 5.0 - -4.0.0 ------ - - * removed `LockHandler` - * Support for passing relative paths to `Filesystem::makePathRelative()` has been removed. - -3.4.0 ------ - - * support for passing relative paths to `Filesystem::makePathRelative()` is deprecated and will be removed in 4.0 - -3.3.0 ------ - - * added `appendToFile()` to append contents to existing files - -3.2.0 ------ - - * added `readlink()` as a platform independent method to read links - -3.0.0 ------ - - * removed `$mode` argument from `Filesystem::dumpFile()` - -2.8.0 ------ - - * added tempnam() a stream aware version of PHP's native tempnam() - -2.6.0 ------ - - * added LockHandler - -2.3.12 ------- - - * deprecated dumpFile() file mode argument. - -2.3.0 ------ - - * added the dumpFile() method to atomically write files - -2.2.0 ------ - - * added a delete option for the mirror() method - -2.1.0 ------ - - * 24eb396 : BC Break : mkdir() function now throws exception in case of failure instead of returning Boolean value - * created the component diff --git a/lib/symfony/filesystem/Exception/ExceptionInterface.php b/lib/symfony/filesystem/Exception/ExceptionInterface.php deleted file mode 100644 index fc438d9f3..000000000 --- a/lib/symfony/filesystem/Exception/ExceptionInterface.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem\Exception; - -/** - * Exception interface for all exceptions thrown by the component. - * - * @author Romain Neutron <imprec@gmail.com> - */ -interface ExceptionInterface extends \Throwable -{ -} diff --git a/lib/symfony/filesystem/Exception/FileNotFoundException.php b/lib/symfony/filesystem/Exception/FileNotFoundException.php deleted file mode 100644 index 48b640809..000000000 --- a/lib/symfony/filesystem/Exception/FileNotFoundException.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem\Exception; - -/** - * Exception class thrown when a file couldn't be found. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Christian Gärtner <christiangaertner.film@googlemail.com> - */ -class FileNotFoundException extends IOException -{ - public function __construct(string $message = null, int $code = 0, \Throwable $previous = null, string $path = null) - { - if (null === $message) { - if (null === $path) { - $message = 'File could not be found.'; - } else { - $message = sprintf('File "%s" could not be found.', $path); - } - } - - parent::__construct($message, $code, $previous, $path); - } -} diff --git a/lib/symfony/filesystem/Exception/IOException.php b/lib/symfony/filesystem/Exception/IOException.php deleted file mode 100644 index fea26e4dd..000000000 --- a/lib/symfony/filesystem/Exception/IOException.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem\Exception; - -/** - * Exception class thrown when a filesystem operation failure happens. - * - * @author Romain Neutron <imprec@gmail.com> - * @author Christian Gärtner <christiangaertner.film@googlemail.com> - * @author Fabien Potencier <fabien@symfony.com> - */ -class IOException extends \RuntimeException implements IOExceptionInterface -{ - private $path; - - public function __construct(string $message, int $code = 0, \Throwable $previous = null, string $path = null) - { - $this->path = $path; - - parent::__construct($message, $code, $previous); - } - - /** - * {@inheritdoc} - */ - public function getPath() - { - return $this->path; - } -} diff --git a/lib/symfony/filesystem/Exception/IOExceptionInterface.php b/lib/symfony/filesystem/Exception/IOExceptionInterface.php deleted file mode 100644 index 42829ab6c..000000000 --- a/lib/symfony/filesystem/Exception/IOExceptionInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem\Exception; - -/** - * IOException interface for file and input/output stream related exceptions thrown by the component. - * - * @author Christian Gärtner <christiangaertner.film@googlemail.com> - */ -interface IOExceptionInterface extends ExceptionInterface -{ - /** - * Returns the associated path for the exception. - * - * @return string|null - */ - public function getPath(); -} diff --git a/lib/symfony/filesystem/Exception/InvalidArgumentException.php b/lib/symfony/filesystem/Exception/InvalidArgumentException.php deleted file mode 100644 index abadc2002..000000000 --- a/lib/symfony/filesystem/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem\Exception; - -/** - * @author Christian Flothmann <christian.flothmann@sensiolabs.de> - */ -class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/lib/symfony/filesystem/Exception/RuntimeException.php b/lib/symfony/filesystem/Exception/RuntimeException.php deleted file mode 100644 index a7512dca7..000000000 --- a/lib/symfony/filesystem/Exception/RuntimeException.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem\Exception; - -/** - * @author Théo Fidry <theo.fidry@gmail.com> - */ -class RuntimeException extends \RuntimeException implements ExceptionInterface -{ -} diff --git a/lib/symfony/filesystem/Filesystem.php b/lib/symfony/filesystem/Filesystem.php deleted file mode 100644 index fafd36492..000000000 --- a/lib/symfony/filesystem/Filesystem.php +++ /dev/null @@ -1,769 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem; - -use Symfony\Component\Filesystem\Exception\FileNotFoundException; -use Symfony\Component\Filesystem\Exception\InvalidArgumentException; -use Symfony\Component\Filesystem\Exception\IOException; - -/** - * Provides basic utility to manipulate the file system. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Filesystem -{ - private static $lastError; - - /** - * Copies a file. - * - * If the target file is older than the origin file, it's always overwritten. - * If the target file is newer, it is overwritten only when the - * $overwriteNewerFiles option is set to true. - * - * @throws FileNotFoundException When originFile doesn't exist - * @throws IOException When copy fails - */ - public function copy(string $originFile, string $targetFile, bool $overwriteNewerFiles = false) - { - $originIsLocal = stream_is_local($originFile) || 0 === stripos($originFile, 'file://'); - if ($originIsLocal && !is_file($originFile)) { - throw new FileNotFoundException(sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile); - } - - $this->mkdir(\dirname($targetFile)); - - $doCopy = true; - if (!$overwriteNewerFiles && null === parse_url($originFile, \PHP_URL_HOST) && is_file($targetFile)) { - $doCopy = filemtime($originFile) > filemtime($targetFile); - } - - if ($doCopy) { - // https://bugs.php.net/64634 - if (!$source = self::box('fopen', $originFile, 'r')) { - throw new IOException(sprintf('Failed to copy "%s" to "%s" because source file could not be opened for reading: ', $originFile, $targetFile).self::$lastError, 0, null, $originFile); - } - - // Stream context created to allow files overwrite when using FTP stream wrapper - disabled by default - if (!$target = self::box('fopen', $targetFile, 'w', false, stream_context_create(['ftp' => ['overwrite' => true]]))) { - throw new IOException(sprintf('Failed to copy "%s" to "%s" because target file could not be opened for writing: ', $originFile, $targetFile).self::$lastError, 0, null, $originFile); - } - - $bytesCopied = stream_copy_to_stream($source, $target); - fclose($source); - fclose($target); - unset($source, $target); - - if (!is_file($targetFile)) { - throw new IOException(sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile); - } - - if ($originIsLocal) { - // Like `cp`, preserve executable permission bits - self::box('chmod', $targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111)); - - if ($bytesCopied !== $bytesOrigin = filesize($originFile)) { - throw new IOException(sprintf('Failed to copy the whole content of "%s" to "%s" (%g of %g bytes copied).', $originFile, $targetFile, $bytesCopied, $bytesOrigin), 0, null, $originFile); - } - } - } - } - - /** - * Creates a directory recursively. - * - * @param string|iterable $dirs The directory path - * - * @throws IOException On any directory creation failure - */ - public function mkdir($dirs, int $mode = 0777) - { - foreach ($this->toIterable($dirs) as $dir) { - if (is_dir($dir)) { - continue; - } - - if (!self::box('mkdir', $dir, $mode, true) && !is_dir($dir)) { - throw new IOException(sprintf('Failed to create "%s": ', $dir).self::$lastError, 0, null, $dir); - } - } - } - - /** - * Checks the existence of files or directories. - * - * @param string|iterable $files A filename, an array of files, or a \Traversable instance to check - * - * @return bool - */ - public function exists($files) - { - $maxPathLength = \PHP_MAXPATHLEN - 2; - - foreach ($this->toIterable($files) as $file) { - if (\strlen($file) > $maxPathLength) { - throw new IOException(sprintf('Could not check if file exist because path length exceeds %d characters.', $maxPathLength), 0, null, $file); - } - - if (!file_exists($file)) { - return false; - } - } - - return true; - } - - /** - * Sets access and modification time of file. - * - * @param string|iterable $files A filename, an array of files, or a \Traversable instance to create - * @param int|null $time The touch time as a Unix timestamp, if not supplied the current system time is used - * @param int|null $atime The access time as a Unix timestamp, if not supplied the current system time is used - * - * @throws IOException When touch fails - */ - public function touch($files, int $time = null, int $atime = null) - { - foreach ($this->toIterable($files) as $file) { - if (!($time ? self::box('touch', $file, $time, $atime) : self::box('touch', $file))) { - throw new IOException(sprintf('Failed to touch "%s": ', $file).self::$lastError, 0, null, $file); - } - } - } - - /** - * Removes files or directories. - * - * @param string|iterable $files A filename, an array of files, or a \Traversable instance to remove - * - * @throws IOException When removal fails - */ - public function remove($files) - { - if ($files instanceof \Traversable) { - $files = iterator_to_array($files, false); - } elseif (!\is_array($files)) { - $files = [$files]; - } - - self::doRemove($files, false); - } - - private static function doRemove(array $files, bool $isRecursive): void - { - $files = array_reverse($files); - foreach ($files as $file) { - if (is_link($file)) { - // See https://bugs.php.net/52176 - if (!(self::box('unlink', $file) || '\\' !== \DIRECTORY_SEPARATOR || self::box('rmdir', $file)) && file_exists($file)) { - throw new IOException(sprintf('Failed to remove symlink "%s": ', $file).self::$lastError); - } - } elseif (is_dir($file)) { - if (!$isRecursive) { - $tmpName = \dirname(realpath($file)).'/.'.strrev(strtr(base64_encode(random_bytes(2)), '/=', '-.')); - - if (file_exists($tmpName)) { - try { - self::doRemove([$tmpName], true); - } catch (IOException $e) { - } - } - - if (!file_exists($tmpName) && self::box('rename', $file, $tmpName)) { - $origFile = $file; - $file = $tmpName; - } else { - $origFile = null; - } - } - - $files = new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS); - self::doRemove(iterator_to_array($files, true), true); - - if (!self::box('rmdir', $file) && file_exists($file) && !$isRecursive) { - $lastError = self::$lastError; - - if (null !== $origFile && self::box('rename', $file, $origFile)) { - $file = $origFile; - } - - throw new IOException(sprintf('Failed to remove directory "%s": ', $file).$lastError); - } - } elseif (!self::box('unlink', $file) && (str_contains(self::$lastError, 'Permission denied') || file_exists($file))) { - throw new IOException(sprintf('Failed to remove file "%s": ', $file).self::$lastError); - } - } - } - - /** - * Change mode for an array of files or directories. - * - * @param string|iterable $files A filename, an array of files, or a \Traversable instance to change mode - * @param int $mode The new mode (octal) - * @param int $umask The mode mask (octal) - * @param bool $recursive Whether change the mod recursively or not - * - * @throws IOException When the change fails - */ - public function chmod($files, int $mode, int $umask = 0000, bool $recursive = false) - { - foreach ($this->toIterable($files) as $file) { - if ((\PHP_VERSION_ID < 80000 || \is_int($mode)) && !self::box('chmod', $file, $mode & ~$umask)) { - throw new IOException(sprintf('Failed to chmod file "%s": ', $file).self::$lastError, 0, null, $file); - } - if ($recursive && is_dir($file) && !is_link($file)) { - $this->chmod(new \FilesystemIterator($file), $mode, $umask, true); - } - } - } - - /** - * Change the owner of an array of files or directories. - * - * @param string|iterable $files A filename, an array of files, or a \Traversable instance to change owner - * @param string|int $user A user name or number - * @param bool $recursive Whether change the owner recursively or not - * - * @throws IOException When the change fails - */ - public function chown($files, $user, bool $recursive = false) - { - foreach ($this->toIterable($files) as $file) { - if ($recursive && is_dir($file) && !is_link($file)) { - $this->chown(new \FilesystemIterator($file), $user, true); - } - if (is_link($file) && \function_exists('lchown')) { - if (!self::box('lchown', $file, $user)) { - throw new IOException(sprintf('Failed to chown file "%s": ', $file).self::$lastError, 0, null, $file); - } - } else { - if (!self::box('chown', $file, $user)) { - throw new IOException(sprintf('Failed to chown file "%s": ', $file).self::$lastError, 0, null, $file); - } - } - } - } - - /** - * Change the group of an array of files or directories. - * - * @param string|iterable $files A filename, an array of files, or a \Traversable instance to change group - * @param string|int $group A group name or number - * @param bool $recursive Whether change the group recursively or not - * - * @throws IOException When the change fails - */ - public function chgrp($files, $group, bool $recursive = false) - { - foreach ($this->toIterable($files) as $file) { - if ($recursive && is_dir($file) && !is_link($file)) { - $this->chgrp(new \FilesystemIterator($file), $group, true); - } - if (is_link($file) && \function_exists('lchgrp')) { - if (!self::box('lchgrp', $file, $group)) { - throw new IOException(sprintf('Failed to chgrp file "%s": ', $file).self::$lastError, 0, null, $file); - } - } else { - if (!self::box('chgrp', $file, $group)) { - throw new IOException(sprintf('Failed to chgrp file "%s": ', $file).self::$lastError, 0, null, $file); - } - } - } - } - - /** - * Renames a file or a directory. - * - * @throws IOException When target file or directory already exists - * @throws IOException When origin cannot be renamed - */ - public function rename(string $origin, string $target, bool $overwrite = false) - { - // we check that target does not exist - if (!$overwrite && $this->isReadable($target)) { - throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target); - } - - if (!self::box('rename', $origin, $target)) { - if (is_dir($origin)) { - // See https://bugs.php.net/54097 & https://php.net/rename#113943 - $this->mirror($origin, $target, null, ['override' => $overwrite, 'delete' => $overwrite]); - $this->remove($origin); - - return; - } - throw new IOException(sprintf('Cannot rename "%s" to "%s": ', $origin, $target).self::$lastError, 0, null, $target); - } - } - - /** - * Tells whether a file exists and is readable. - * - * @throws IOException When windows path is longer than 258 characters - */ - private function isReadable(string $filename): bool - { - $maxPathLength = \PHP_MAXPATHLEN - 2; - - if (\strlen($filename) > $maxPathLength) { - throw new IOException(sprintf('Could not check if file is readable because path length exceeds %d characters.', $maxPathLength), 0, null, $filename); - } - - return is_readable($filename); - } - - /** - * Creates a symbolic link or copy a directory. - * - * @throws IOException When symlink fails - */ - public function symlink(string $originDir, string $targetDir, bool $copyOnWindows = false) - { - self::assertFunctionExists('symlink'); - - if ('\\' === \DIRECTORY_SEPARATOR) { - $originDir = strtr($originDir, '/', '\\'); - $targetDir = strtr($targetDir, '/', '\\'); - - if ($copyOnWindows) { - $this->mirror($originDir, $targetDir); - - return; - } - } - - $this->mkdir(\dirname($targetDir)); - - if (is_link($targetDir)) { - if (readlink($targetDir) === $originDir) { - return; - } - $this->remove($targetDir); - } - - if (!self::box('symlink', $originDir, $targetDir)) { - $this->linkException($originDir, $targetDir, 'symbolic'); - } - } - - /** - * Creates a hard link, or several hard links to a file. - * - * @param string|string[] $targetFiles The target file(s) - * - * @throws FileNotFoundException When original file is missing or not a file - * @throws IOException When link fails, including if link already exists - */ - public function hardlink(string $originFile, $targetFiles) - { - self::assertFunctionExists('link'); - - if (!$this->exists($originFile)) { - throw new FileNotFoundException(null, 0, null, $originFile); - } - - if (!is_file($originFile)) { - throw new FileNotFoundException(sprintf('Origin file "%s" is not a file.', $originFile)); - } - - foreach ($this->toIterable($targetFiles) as $targetFile) { - if (is_file($targetFile)) { - if (fileinode($originFile) === fileinode($targetFile)) { - continue; - } - $this->remove($targetFile); - } - - if (!self::box('link', $originFile, $targetFile)) { - $this->linkException($originFile, $targetFile, 'hard'); - } - } - } - - /** - * @param string $linkType Name of the link type, typically 'symbolic' or 'hard' - */ - private function linkException(string $origin, string $target, string $linkType) - { - if (self::$lastError) { - if ('\\' === \DIRECTORY_SEPARATOR && str_contains(self::$lastError, 'error code(1314)')) { - throw new IOException(sprintf('Unable to create "%s" link due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?', $linkType), 0, null, $target); - } - } - throw new IOException(sprintf('Failed to create "%s" link from "%s" to "%s": ', $linkType, $origin, $target).self::$lastError, 0, null, $target); - } - - /** - * Resolves links in paths. - * - * With $canonicalize = false (default) - * - if $path does not exist or is not a link, returns null - * - if $path is a link, returns the next direct target of the link without considering the existence of the target - * - * With $canonicalize = true - * - if $path does not exist, returns null - * - if $path exists, returns its absolute fully resolved final version - * - * @return string|null - */ - public function readlink(string $path, bool $canonicalize = false) - { - if (!$canonicalize && !is_link($path)) { - return null; - } - - if ($canonicalize) { - if (!$this->exists($path)) { - return null; - } - - if ('\\' === \DIRECTORY_SEPARATOR && \PHP_VERSION_ID < 70410) { - $path = readlink($path); - } - - return realpath($path); - } - - if ('\\' === \DIRECTORY_SEPARATOR && \PHP_VERSION_ID < 70400) { - return realpath($path); - } - - return readlink($path); - } - - /** - * Given an existing path, convert it to a path relative to a given starting path. - * - * @return string - */ - public function makePathRelative(string $endPath, string $startPath) - { - if (!$this->isAbsolutePath($startPath)) { - throw new InvalidArgumentException(sprintf('The start path "%s" is not absolute.', $startPath)); - } - - if (!$this->isAbsolutePath($endPath)) { - throw new InvalidArgumentException(sprintf('The end path "%s" is not absolute.', $endPath)); - } - - // Normalize separators on Windows - if ('\\' === \DIRECTORY_SEPARATOR) { - $endPath = str_replace('\\', '/', $endPath); - $startPath = str_replace('\\', '/', $startPath); - } - - $splitDriveLetter = function ($path) { - return (\strlen($path) > 2 && ':' === $path[1] && '/' === $path[2] && ctype_alpha($path[0])) - ? [substr($path, 2), strtoupper($path[0])] - : [$path, null]; - }; - - $splitPath = function ($path) { - $result = []; - - foreach (explode('/', trim($path, '/')) as $segment) { - if ('..' === $segment) { - array_pop($result); - } elseif ('.' !== $segment && '' !== $segment) { - $result[] = $segment; - } - } - - return $result; - }; - - [$endPath, $endDriveLetter] = $splitDriveLetter($endPath); - [$startPath, $startDriveLetter] = $splitDriveLetter($startPath); - - $startPathArr = $splitPath($startPath); - $endPathArr = $splitPath($endPath); - - if ($endDriveLetter && $startDriveLetter && $endDriveLetter != $startDriveLetter) { - // End path is on another drive, so no relative path exists - return $endDriveLetter.':/'.($endPathArr ? implode('/', $endPathArr).'/' : ''); - } - - // Find for which directory the common path stops - $index = 0; - while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) { - ++$index; - } - - // Determine how deep the start path is relative to the common path (ie, "web/bundles" = 2 levels) - if (1 === \count($startPathArr) && '' === $startPathArr[0]) { - $depth = 0; - } else { - $depth = \count($startPathArr) - $index; - } - - // Repeated "../" for each level need to reach the common path - $traverser = str_repeat('../', $depth); - - $endPathRemainder = implode('/', \array_slice($endPathArr, $index)); - - // Construct $endPath from traversing to the common path, then to the remaining $endPath - $relativePath = $traverser.('' !== $endPathRemainder ? $endPathRemainder.'/' : ''); - - return '' === $relativePath ? './' : $relativePath; - } - - /** - * Mirrors a directory to another. - * - * Copies files and directories from the origin directory into the target directory. By default: - * - * - existing files in the target directory will be overwritten, except if they are newer (see the `override` option) - * - files in the target directory that do not exist in the source directory will not be deleted (see the `delete` option) - * - * @param \Traversable|null $iterator Iterator that filters which files and directories to copy, if null a recursive iterator is created - * @param array $options An array of boolean options - * Valid options are: - * - $options['override'] If true, target files newer than origin files are overwritten (see copy(), defaults to false) - * - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink(), defaults to false) - * - $options['delete'] Whether to delete files that are not in the source directory (defaults to false) - * - * @throws IOException When file type is unknown - */ - public function mirror(string $originDir, string $targetDir, \Traversable $iterator = null, array $options = []) - { - $targetDir = rtrim($targetDir, '/\\'); - $originDir = rtrim($originDir, '/\\'); - $originDirLen = \strlen($originDir); - - if (!$this->exists($originDir)) { - throw new IOException(sprintf('The origin directory specified "%s" was not found.', $originDir), 0, null, $originDir); - } - - // Iterate in destination folder to remove obsolete entries - if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) { - $deleteIterator = $iterator; - if (null === $deleteIterator) { - $flags = \FilesystemIterator::SKIP_DOTS; - $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST); - } - $targetDirLen = \strlen($targetDir); - foreach ($deleteIterator as $file) { - $origin = $originDir.substr($file->getPathname(), $targetDirLen); - if (!$this->exists($origin)) { - $this->remove($file); - } - } - } - - $copyOnWindows = $options['copy_on_windows'] ?? false; - - if (null === $iterator) { - $flags = $copyOnWindows ? \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS : \FilesystemIterator::SKIP_DOTS; - $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST); - } - - $this->mkdir($targetDir); - $filesCreatedWhileMirroring = []; - - foreach ($iterator as $file) { - if ($file->getPathname() === $targetDir || $file->getRealPath() === $targetDir || isset($filesCreatedWhileMirroring[$file->getRealPath()])) { - continue; - } - - $target = $targetDir.substr($file->getPathname(), $originDirLen); - $filesCreatedWhileMirroring[$target] = true; - - if (!$copyOnWindows && is_link($file)) { - $this->symlink($file->getLinkTarget(), $target); - } elseif (is_dir($file)) { - $this->mkdir($target); - } elseif (is_file($file)) { - $this->copy($file, $target, $options['override'] ?? false); - } else { - throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file); - } - } - } - - /** - * Returns whether the file path is an absolute path. - * - * @return bool - */ - public function isAbsolutePath(string $file) - { - return '' !== $file && (strspn($file, '/\\', 0, 1) - || (\strlen($file) > 3 && ctype_alpha($file[0]) - && ':' === $file[1] - && strspn($file, '/\\', 2, 1) - ) - || null !== parse_url($file, \PHP_URL_SCHEME) - ); - } - - /** - * Creates a temporary file with support for custom stream wrappers. - * - * @param string $prefix The prefix of the generated temporary filename - * Note: Windows uses only the first three characters of prefix - * @param string $suffix The suffix of the generated temporary filename - * - * @return string The new temporary filename (with path), or throw an exception on failure - */ - public function tempnam(string $dir, string $prefix/* , string $suffix = '' */) - { - $suffix = \func_num_args() > 2 ? func_get_arg(2) : ''; - [$scheme, $hierarchy] = $this->getSchemeAndHierarchy($dir); - - // If no scheme or scheme is "file" or "gs" (Google Cloud) create temp file in local filesystem - if ((null === $scheme || 'file' === $scheme || 'gs' === $scheme) && '' === $suffix) { - // If tempnam failed or no scheme return the filename otherwise prepend the scheme - if ($tmpFile = self::box('tempnam', $hierarchy, $prefix)) { - if (null !== $scheme && 'gs' !== $scheme) { - return $scheme.'://'.$tmpFile; - } - - return $tmpFile; - } - - throw new IOException('A temporary file could not be created: '.self::$lastError); - } - - // Loop until we create a valid temp file or have reached 10 attempts - for ($i = 0; $i < 10; ++$i) { - // Create a unique filename - $tmpFile = $dir.'/'.$prefix.uniqid(mt_rand(), true).$suffix; - - // Use fopen instead of file_exists as some streams do not support stat - // Use mode 'x+' to atomically check existence and create to avoid a TOCTOU vulnerability - if (!$handle = self::box('fopen', $tmpFile, 'x+')) { - continue; - } - - // Close the file if it was successfully opened - self::box('fclose', $handle); - - return $tmpFile; - } - - throw new IOException('A temporary file could not be created: '.self::$lastError); - } - - /** - * Atomically dumps content into a file. - * - * @param string|resource $content The data to write into the file - * - * @throws IOException if the file cannot be written to - */ - public function dumpFile(string $filename, $content) - { - if (\is_array($content)) { - throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be string or resource, array given.', __METHOD__)); - } - - $dir = \dirname($filename); - - if (!is_dir($dir)) { - $this->mkdir($dir); - } - - // Will create a temp file with 0600 access rights - // when the filesystem supports chmod. - $tmpFile = $this->tempnam($dir, basename($filename)); - - try { - if (false === self::box('file_put_contents', $tmpFile, $content)) { - throw new IOException(sprintf('Failed to write file "%s": ', $filename).self::$lastError, 0, null, $filename); - } - - self::box('chmod', $tmpFile, file_exists($filename) ? fileperms($filename) : 0666 & ~umask()); - - $this->rename($tmpFile, $filename, true); - } finally { - if (file_exists($tmpFile)) { - self::box('unlink', $tmpFile); - } - } - } - - /** - * Appends content to an existing file. - * - * @param string|resource $content The content to append - * @param bool $lock Whether the file should be locked when writing to it - * - * @throws IOException If the file is not writable - */ - public function appendToFile(string $filename, $content/* , bool $lock = false */) - { - if (\is_array($content)) { - throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be string or resource, array given.', __METHOD__)); - } - - $dir = \dirname($filename); - - if (!is_dir($dir)) { - $this->mkdir($dir); - } - - $lock = \func_num_args() > 2 && func_get_arg(2); - - if (false === self::box('file_put_contents', $filename, $content, \FILE_APPEND | ($lock ? \LOCK_EX : 0))) { - throw new IOException(sprintf('Failed to write file "%s": ', $filename).self::$lastError, 0, null, $filename); - } - } - - private function toIterable($files): iterable - { - return is_iterable($files) ? $files : [$files]; - } - - /** - * Gets a 2-tuple of scheme (may be null) and hierarchical part of a filename (e.g. file:///tmp -> [file, tmp]). - */ - private function getSchemeAndHierarchy(string $filename): array - { - $components = explode('://', $filename, 2); - - return 2 === \count($components) ? [$components[0], $components[1]] : [null, $components[0]]; - } - - private static function assertFunctionExists(string $func): void - { - if (!\function_exists($func)) { - throw new IOException(sprintf('Unable to perform filesystem operation because the "%s()" function has been disabled.', $func)); - } - } - - /** - * @param mixed ...$args - * - * @return mixed - */ - private static function box(string $func, ...$args) - { - self::assertFunctionExists($func); - - self::$lastError = null; - set_error_handler(__CLASS__.'::handleError'); - try { - return $func(...$args); - } finally { - restore_error_handler(); - } - } - - /** - * @internal - */ - public static function handleError(int $type, string $msg) - { - self::$lastError = $msg; - } -} diff --git a/lib/symfony/filesystem/LICENSE b/lib/symfony/filesystem/LICENSE deleted file mode 100644 index 88bf75bb4..000000000 --- a/lib/symfony/filesystem/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-2022 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -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/lib/symfony/filesystem/Path.php b/lib/symfony/filesystem/Path.php deleted file mode 100644 index 0bbd5b477..000000000 --- a/lib/symfony/filesystem/Path.php +++ /dev/null @@ -1,819 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem; - -use Symfony\Component\Filesystem\Exception\InvalidArgumentException; -use Symfony\Component\Filesystem\Exception\RuntimeException; - -/** - * Contains utility methods for handling path strings. - * - * The methods in this class are able to deal with both UNIX and Windows paths - * with both forward and backward slashes. All methods return normalized parts - * containing only forward slashes and no excess "." and ".." segments. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * @author Thomas Schulz <mail@king2500.net> - * @author Théo Fidry <theo.fidry@gmail.com> - */ -final class Path -{ - /** - * The number of buffer entries that triggers a cleanup operation. - */ - private const CLEANUP_THRESHOLD = 1250; - - /** - * The buffer size after the cleanup operation. - */ - private const CLEANUP_SIZE = 1000; - - /** - * Buffers input/output of {@link canonicalize()}. - * - * @var array<string, string> - */ - private static $buffer = []; - - /** - * @var int - */ - private static $bufferSize = 0; - - /** - * Canonicalizes the given path. - * - * During normalization, all slashes are replaced by forward slashes ("/"). - * Furthermore, all "." and ".." segments are removed as far as possible. - * ".." segments at the beginning of relative paths are not removed. - * - * ```php - * echo Path::canonicalize("\symfony\puli\..\css\style.css"); - * // => /symfony/css/style.css - * - * echo Path::canonicalize("../css/./style.css"); - * // => ../css/style.css - * ``` - * - * This method is able to deal with both UNIX and Windows paths. - */ - public static function canonicalize(string $path): string - { - if ('' === $path) { - return ''; - } - - // This method is called by many other methods in this class. Buffer - // the canonicalized paths to make up for the severe performance - // decrease. - if (isset(self::$buffer[$path])) { - return self::$buffer[$path]; - } - - // Replace "~" with user's home directory. - if ('~' === $path[0]) { - $path = self::getHomeDirectory().mb_substr($path, 1); - } - - $path = self::normalize($path); - - [$root, $pathWithoutRoot] = self::split($path); - - $canonicalParts = self::findCanonicalParts($root, $pathWithoutRoot); - - // Add the root directory again - self::$buffer[$path] = $canonicalPath = $root.implode('/', $canonicalParts); - ++self::$bufferSize; - - // Clean up regularly to prevent memory leaks - if (self::$bufferSize > self::CLEANUP_THRESHOLD) { - self::$buffer = \array_slice(self::$buffer, -self::CLEANUP_SIZE, null, true); - self::$bufferSize = self::CLEANUP_SIZE; - } - - return $canonicalPath; - } - - /** - * Normalizes the given path. - * - * During normalization, all slashes are replaced by forward slashes ("/"). - * Contrary to {@link canonicalize()}, this method does not remove invalid - * or dot path segments. Consequently, it is much more efficient and should - * be used whenever the given path is known to be a valid, absolute system - * path. - * - * This method is able to deal with both UNIX and Windows paths. - */ - public static function normalize(string $path): string - { - return str_replace('\\', '/', $path); - } - - /** - * Returns the directory part of the path. - * - * This method is similar to PHP's dirname(), but handles various cases - * where dirname() returns a weird result: - * - * - dirname() does not accept backslashes on UNIX - * - dirname("C:/symfony") returns "C:", not "C:/" - * - dirname("C:/") returns ".", not "C:/" - * - dirname("C:") returns ".", not "C:/" - * - dirname("symfony") returns ".", not "" - * - dirname() does not canonicalize the result - * - * This method fixes these shortcomings and behaves like dirname() - * otherwise. - * - * The result is a canonical path. - * - * @return string The canonical directory part. Returns the root directory - * if the root directory is passed. Returns an empty string - * if a relative path is passed that contains no slashes. - * Returns an empty string if an empty string is passed. - */ - public static function getDirectory(string $path): string - { - if ('' === $path) { - return ''; - } - - $path = self::canonicalize($path); - - // Maintain scheme - if (false !== ($schemeSeparatorPosition = mb_strpos($path, '://'))) { - $scheme = mb_substr($path, 0, $schemeSeparatorPosition + 3); - $path = mb_substr($path, $schemeSeparatorPosition + 3); - } else { - $scheme = ''; - } - - if (false === ($dirSeparatorPosition = strrpos($path, '/'))) { - return ''; - } - - // Directory equals root directory "/" - if (0 === $dirSeparatorPosition) { - return $scheme.'/'; - } - - // Directory equals Windows root "C:/" - if (2 === $dirSeparatorPosition && ctype_alpha($path[0]) && ':' === $path[1]) { - return $scheme.mb_substr($path, 0, 3); - } - - return $scheme.mb_substr($path, 0, $dirSeparatorPosition); - } - - /** - * Returns canonical path of the user's home directory. - * - * Supported operating systems: - * - * - UNIX - * - Windows8 and upper - * - * If your operating system or environment isn't supported, an exception is thrown. - * - * The result is a canonical path. - * - * @throws RuntimeException If your operating system or environment isn't supported - */ - public static function getHomeDirectory(): string - { - // For UNIX support - if (getenv('HOME')) { - return self::canonicalize(getenv('HOME')); - } - - // For >= Windows8 support - if (getenv('HOMEDRIVE') && getenv('HOMEPATH')) { - return self::canonicalize(getenv('HOMEDRIVE').getenv('HOMEPATH')); - } - - throw new RuntimeException("Cannot find the home directory path: Your environment or operating system isn't supported."); - } - - /** - * Returns the root directory of a path. - * - * The result is a canonical path. - * - * @return string The canonical root directory. Returns an empty string if - * the given path is relative or empty. - */ - public static function getRoot(string $path): string - { - if ('' === $path) { - return ''; - } - - // Maintain scheme - if (false !== ($schemeSeparatorPosition = strpos($path, '://'))) { - $scheme = substr($path, 0, $schemeSeparatorPosition + 3); - $path = substr($path, $schemeSeparatorPosition + 3); - } else { - $scheme = ''; - } - - $firstCharacter = $path[0]; - - // UNIX root "/" or "\" (Windows style) - if ('/' === $firstCharacter || '\\' === $firstCharacter) { - return $scheme.'/'; - } - - $length = mb_strlen($path); - - // Windows root - if ($length > 1 && ':' === $path[1] && ctype_alpha($firstCharacter)) { - // Special case: "C:" - if (2 === $length) { - return $scheme.$path.'/'; - } - - // Normal case: "C:/ or "C:\" - if ('/' === $path[2] || '\\' === $path[2]) { - return $scheme.$firstCharacter.$path[1].'/'; - } - } - - return ''; - } - - /** - * Returns the file name without the extension from a file path. - * - * @param string|null $extension if specified, only that extension is cut - * off (may contain leading dot) - */ - public static function getFilenameWithoutExtension(string $path, string $extension = null): string - { - if ('' === $path) { - return ''; - } - - if (null !== $extension) { - // remove extension and trailing dot - return rtrim(basename($path, $extension), '.'); - } - - return pathinfo($path, \PATHINFO_FILENAME); - } - - /** - * Returns the extension from a file path (without leading dot). - * - * @param bool $forceLowerCase forces the extension to be lower-case - */ - public static function getExtension(string $path, bool $forceLowerCase = false): string - { - if ('' === $path) { - return ''; - } - - $extension = pathinfo($path, \PATHINFO_EXTENSION); - - if ($forceLowerCase) { - $extension = self::toLower($extension); - } - - return $extension; - } - - /** - * Returns whether the path has an (or the specified) extension. - * - * @param string $path the path string - * @param string|string[]|null $extensions if null or not provided, checks if - * an extension exists, otherwise - * checks for the specified extension - * or array of extensions (with or - * without leading dot) - * @param bool $ignoreCase whether to ignore case-sensitivity - */ - public static function hasExtension(string $path, $extensions = null, bool $ignoreCase = false): bool - { - if ('' === $path) { - return false; - } - - $actualExtension = self::getExtension($path, $ignoreCase); - - // Only check if path has any extension - if ([] === $extensions || null === $extensions) { - return '' !== $actualExtension; - } - - if (\is_string($extensions)) { - $extensions = [$extensions]; - } - - foreach ($extensions as $key => $extension) { - if ($ignoreCase) { - $extension = self::toLower($extension); - } - - // remove leading '.' in extensions array - $extensions[$key] = ltrim($extension, '.'); - } - - return \in_array($actualExtension, $extensions, true); - } - - /** - * Changes the extension of a path string. - * - * @param string $path The path string with filename.ext to change. - * @param string $extension new extension (with or without leading dot) - * - * @return string the path string with new file extension - */ - public static function changeExtension(string $path, string $extension): string - { - if ('' === $path) { - return ''; - } - - $actualExtension = self::getExtension($path); - $extension = ltrim($extension, '.'); - - // No extension for paths - if ('/' === mb_substr($path, -1)) { - return $path; - } - - // No actual extension in path - if (empty($actualExtension)) { - return $path.('.' === mb_substr($path, -1) ? '' : '.').$extension; - } - - return mb_substr($path, 0, -mb_strlen($actualExtension)).$extension; - } - - public static function isAbsolute(string $path): bool - { - if ('' === $path) { - return false; - } - - // Strip scheme - if (false !== ($schemeSeparatorPosition = mb_strpos($path, '://'))) { - $path = mb_substr($path, $schemeSeparatorPosition + 3); - } - - $firstCharacter = $path[0]; - - // UNIX root "/" or "\" (Windows style) - if ('/' === $firstCharacter || '\\' === $firstCharacter) { - return true; - } - - // Windows root - if (mb_strlen($path) > 1 && ctype_alpha($firstCharacter) && ':' === $path[1]) { - // Special case: "C:" - if (2 === mb_strlen($path)) { - return true; - } - - // Normal case: "C:/ or "C:\" - if ('/' === $path[2] || '\\' === $path[2]) { - return true; - } - } - - return false; - } - - public static function isRelative(string $path): bool - { - return !self::isAbsolute($path); - } - - /** - * Turns a relative path into an absolute path in canonical form. - * - * Usually, the relative path is appended to the given base path. Dot - * segments ("." and "..") are removed/collapsed and all slashes turned - * into forward slashes. - * - * ```php - * echo Path::makeAbsolute("../style.css", "/symfony/puli/css"); - * // => /symfony/puli/style.css - * ``` - * - * If an absolute path is passed, that path is returned unless its root - * directory is different than the one of the base path. In that case, an - * exception is thrown. - * - * ```php - * Path::makeAbsolute("/style.css", "/symfony/puli/css"); - * // => /style.css - * - * Path::makeAbsolute("C:/style.css", "C:/symfony/puli/css"); - * // => C:/style.css - * - * Path::makeAbsolute("C:/style.css", "/symfony/puli/css"); - * // InvalidArgumentException - * ``` - * - * If the base path is not an absolute path, an exception is thrown. - * - * The result is a canonical path. - * - * @param string $basePath an absolute base path - * - * @throws InvalidArgumentException if the base path is not absolute or if - * the given path is an absolute path with - * a different root than the base path - */ - public static function makeAbsolute(string $path, string $basePath): string - { - if ('' === $basePath) { - throw new InvalidArgumentException(sprintf('The base path must be a non-empty string. Got: "%s".', $basePath)); - } - - if (!self::isAbsolute($basePath)) { - throw new InvalidArgumentException(sprintf('The base path "%s" is not an absolute path.', $basePath)); - } - - if (self::isAbsolute($path)) { - return self::canonicalize($path); - } - - if (false !== ($schemeSeparatorPosition = mb_strpos($basePath, '://'))) { - $scheme = mb_substr($basePath, 0, $schemeSeparatorPosition + 3); - $basePath = mb_substr($basePath, $schemeSeparatorPosition + 3); - } else { - $scheme = ''; - } - - return $scheme.self::canonicalize(rtrim($basePath, '/\\').'/'.$path); - } - - /** - * Turns a path into a relative path. - * - * The relative path is created relative to the given base path: - * - * ```php - * echo Path::makeRelative("/symfony/style.css", "/symfony/puli"); - * // => ../style.css - * ``` - * - * If a relative path is passed and the base path is absolute, the relative - * path is returned unchanged: - * - * ```php - * Path::makeRelative("style.css", "/symfony/puli/css"); - * // => style.css - * ``` - * - * If both paths are relative, the relative path is created with the - * assumption that both paths are relative to the same directory: - * - * ```php - * Path::makeRelative("style.css", "symfony/puli/css"); - * // => ../../../style.css - * ``` - * - * If both paths are absolute, their root directory must be the same, - * otherwise an exception is thrown: - * - * ```php - * Path::makeRelative("C:/symfony/style.css", "/symfony/puli"); - * // InvalidArgumentException - * ``` - * - * If the passed path is absolute, but the base path is not, an exception - * is thrown as well: - * - * ```php - * Path::makeRelative("/symfony/style.css", "symfony/puli"); - * // InvalidArgumentException - * ``` - * - * If the base path is not an absolute path, an exception is thrown. - * - * The result is a canonical path. - * - * @throws InvalidArgumentException if the base path is not absolute or if - * the given path has a different root - * than the base path - */ - public static function makeRelative(string $path, string $basePath): string - { - $path = self::canonicalize($path); - $basePath = self::canonicalize($basePath); - - [$root, $relativePath] = self::split($path); - [$baseRoot, $relativeBasePath] = self::split($basePath); - - // If the base path is given as absolute path and the path is already - // relative, consider it to be relative to the given absolute path - // already - if ('' === $root && '' !== $baseRoot) { - // If base path is already in its root - if ('' === $relativeBasePath) { - $relativePath = ltrim($relativePath, './\\'); - } - - return $relativePath; - } - - // If the passed path is absolute, but the base path is not, we - // cannot generate a relative path - if ('' !== $root && '' === $baseRoot) { - throw new InvalidArgumentException(sprintf('The absolute path "%s" cannot be made relative to the relative path "%s". You should provide an absolute base path instead.', $path, $basePath)); - } - - // Fail if the roots of the two paths are different - if ($baseRoot && $root !== $baseRoot) { - throw new InvalidArgumentException(sprintf('The path "%s" cannot be made relative to "%s", because they have different roots ("%s" and "%s").', $path, $basePath, $root, $baseRoot)); - } - - if ('' === $relativeBasePath) { - return $relativePath; - } - - // Build a "../../" prefix with as many "../" parts as necessary - $parts = explode('/', $relativePath); - $baseParts = explode('/', $relativeBasePath); - $dotDotPrefix = ''; - - // Once we found a non-matching part in the prefix, we need to add - // "../" parts for all remaining parts - $match = true; - - foreach ($baseParts as $index => $basePart) { - if ($match && isset($parts[$index]) && $basePart === $parts[$index]) { - unset($parts[$index]); - - continue; - } - - $match = false; - $dotDotPrefix .= '../'; - } - - return rtrim($dotDotPrefix.implode('/', $parts), '/'); - } - - /** - * Returns whether the given path is on the local filesystem. - */ - public static function isLocal(string $path): bool - { - return '' !== $path && false === mb_strpos($path, '://'); - } - - /** - * Returns the longest common base path in canonical form of a set of paths or - * `null` if the paths are on different Windows partitions. - * - * Dot segments ("." and "..") are removed/collapsed and all slashes turned - * into forward slashes. - * - * ```php - * $basePath = Path::getLongestCommonBasePath( - * '/symfony/css/style.css', - * '/symfony/css/..' - * ); - * // => /symfony - * ``` - * - * The root is returned if no common base path can be found: - * - * ```php - * $basePath = Path::getLongestCommonBasePath( - * '/symfony/css/style.css', - * '/puli/css/..' - * ); - * // => / - * ``` - * - * If the paths are located on different Windows partitions, `null` is - * returned. - * - * ```php - * $basePath = Path::getLongestCommonBasePath( - * 'C:/symfony/css/style.css', - * 'D:/symfony/css/..' - * ); - * // => null - * ``` - */ - public static function getLongestCommonBasePath(string ...$paths): ?string - { - [$bpRoot, $basePath] = self::split(self::canonicalize(reset($paths))); - - for (next($paths); null !== key($paths) && '' !== $basePath; next($paths)) { - [$root, $path] = self::split(self::canonicalize(current($paths))); - - // If we deal with different roots (e.g. C:/ vs. D:/), it's time - // to quit - if ($root !== $bpRoot) { - return null; - } - - // Make the base path shorter until it fits into path - while (true) { - if ('.' === $basePath) { - // No more base paths - $basePath = ''; - - // next path - continue 2; - } - - // Prevent false positives for common prefixes - // see isBasePath() - if (0 === mb_strpos($path.'/', $basePath.'/')) { - // next path - continue 2; - } - - $basePath = \dirname($basePath); - } - } - - return $bpRoot.$basePath; - } - - /** - * Joins two or more path strings into a canonical path. - */ - public static function join(string ...$paths): string - { - $finalPath = null; - $wasScheme = false; - - foreach ($paths as $path) { - if ('' === $path) { - continue; - } - - if (null === $finalPath) { - // For first part we keep slashes, like '/top', 'C:\' or 'phar://' - $finalPath = $path; - $wasScheme = (false !== mb_strpos($path, '://')); - continue; - } - - // Only add slash if previous part didn't end with '/' or '\' - if (!\in_array(mb_substr($finalPath, -1), ['/', '\\'])) { - $finalPath .= '/'; - } - - // If first part included a scheme like 'phar://' we allow \current part to start with '/', otherwise trim - $finalPath .= $wasScheme ? $path : ltrim($path, '/'); - $wasScheme = false; - } - - if (null === $finalPath) { - return ''; - } - - return self::canonicalize($finalPath); - } - - /** - * Returns whether a path is a base path of another path. - * - * Dot segments ("." and "..") are removed/collapsed and all slashes turned - * into forward slashes. - * - * ```php - * Path::isBasePath('/symfony', '/symfony/css'); - * // => true - * - * Path::isBasePath('/symfony', '/symfony'); - * // => true - * - * Path::isBasePath('/symfony', '/symfony/..'); - * // => false - * - * Path::isBasePath('/symfony', '/puli'); - * // => false - * ``` - */ - public static function isBasePath(string $basePath, string $ofPath): bool - { - $basePath = self::canonicalize($basePath); - $ofPath = self::canonicalize($ofPath); - - // Append slashes to prevent false positives when two paths have - // a common prefix, for example /base/foo and /base/foobar. - // Don't append a slash for the root "/", because then that root - // won't be discovered as common prefix ("//" is not a prefix of - // "/foobar/"). - return 0 === mb_strpos($ofPath.'/', rtrim($basePath, '/').'/'); - } - - /** - * @return non-empty-string[] - */ - private static function findCanonicalParts(string $root, string $pathWithoutRoot): array - { - $parts = explode('/', $pathWithoutRoot); - - $canonicalParts = []; - - // Collapse "." and "..", if possible - foreach ($parts as $part) { - if ('.' === $part || '' === $part) { - continue; - } - - // Collapse ".." with the previous part, if one exists - // Don't collapse ".." if the previous part is also ".." - if ('..' === $part && \count($canonicalParts) > 0 && '..' !== $canonicalParts[\count($canonicalParts) - 1]) { - array_pop($canonicalParts); - - continue; - } - - // Only add ".." prefixes for relative paths - if ('..' !== $part || '' === $root) { - $canonicalParts[] = $part; - } - } - - return $canonicalParts; - } - - /** - * Splits a canonical path into its root directory and the remainder. - * - * If the path has no root directory, an empty root directory will be - * returned. - * - * If the root directory is a Windows style partition, the resulting root - * will always contain a trailing slash. - * - * list ($root, $path) = Path::split("C:/symfony") - * // => ["C:/", "symfony"] - * - * list ($root, $path) = Path::split("C:") - * // => ["C:/", ""] - * - * @return array{string, string} an array with the root directory and the remaining relative path - */ - private static function split(string $path): array - { - if ('' === $path) { - return ['', '']; - } - - // Remember scheme as part of the root, if any - if (false !== ($schemeSeparatorPosition = mb_strpos($path, '://'))) { - $root = mb_substr($path, 0, $schemeSeparatorPosition + 3); - $path = mb_substr($path, $schemeSeparatorPosition + 3); - } else { - $root = ''; - } - - $length = mb_strlen($path); - - // Remove and remember root directory - if (0 === mb_strpos($path, '/')) { - $root .= '/'; - $path = $length > 1 ? mb_substr($path, 1) : ''; - } elseif ($length > 1 && ctype_alpha($path[0]) && ':' === $path[1]) { - if (2 === $length) { - // Windows special case: "C:" - $root .= $path.'/'; - $path = ''; - } elseif ('/' === $path[2]) { - // Windows normal case: "C:/".. - $root .= mb_substr($path, 0, 3); - $path = $length > 3 ? mb_substr($path, 3) : ''; - } - } - - return [$root, $path]; - } - - private static function toLower(string $string): string - { - if (false !== $encoding = mb_detect_encoding($string)) { - return mb_strtolower($string, $encoding); - } - - return strtolower($string, $encoding); - } - - private function __construct() - { - } -} diff --git a/lib/symfony/filesystem/README.md b/lib/symfony/filesystem/README.md deleted file mode 100644 index f2f6d45f7..000000000 --- a/lib/symfony/filesystem/README.md +++ /dev/null @@ -1,13 +0,0 @@ -Filesystem Component -==================== - -The Filesystem component provides basic utilities for the filesystem. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/filesystem.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/lib/symfony/filesystem/composer.json b/lib/symfony/filesystem/composer.json deleted file mode 100644 index e756104cd..000000000 --- a/lib/symfony/filesystem/composer.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "symfony/filesystem", - "type": "library", - "description": "Provides basic utilities for the filesystem", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8", - "symfony/polyfill-php80": "^1.16" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\Filesystem\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/lib/symfony/finder/CHANGELOG.md b/lib/symfony/finder/CHANGELOG.md deleted file mode 100644 index 6a44e87c2..000000000 --- a/lib/symfony/finder/CHANGELOG.md +++ /dev/null @@ -1,87 +0,0 @@ -CHANGELOG -========= - -5.4.0 ------ - - * Deprecate `Comparator::setTarget()` and `Comparator::setOperator()` - * Add a constructor to `Comparator` that allows setting target and operator - * Finder's iterator has now `Symfony\Component\Finder\SplFileInfo` inner type specified - * Add recursive .gitignore files support - -5.0.0 ------ - - * added `$useNaturalSort` argument to `Finder::sortByName()` - -4.3.0 ------ - - * added Finder::ignoreVCSIgnored() to ignore files based on rules listed in .gitignore - -4.2.0 ------ - - * added $useNaturalSort option to Finder::sortByName() method - * the `Finder::sortByName()` method will have a new `$useNaturalSort` - argument in version 5.0, not defining it is deprecated - * added `Finder::reverseSorting()` to reverse the sorting - -4.0.0 ------ - - * removed `ExceptionInterface` - * removed `Symfony\Component\Finder\Iterator\FilterIterator` - -3.4.0 ------ - - * deprecated `Symfony\Component\Finder\Iterator\FilterIterator` - * added Finder::hasResults() method to check if any results were found - -3.3.0 ------ - - * added double-star matching to Glob::toRegex() - -3.0.0 ------ - - * removed deprecated classes - -2.8.0 ------ - - * deprecated adapters and related classes - -2.5.0 ------ - * added support for GLOB_BRACE in the paths passed to Finder::in() - -2.3.0 ------ - - * added a way to ignore unreadable directories (via Finder::ignoreUnreadableDirs()) - * unified the way subfolders that are not executable are handled by always throwing an AccessDeniedException exception - -2.2.0 ------ - - * added Finder::path() and Finder::notPath() methods - * added finder adapters to improve performance on specific platforms - * added support for wildcard characters (glob patterns) in the paths passed - to Finder::in() - -2.1.0 ------ - - * added Finder::sortByAccessedTime(), Finder::sortByChangedTime(), and - Finder::sortByModifiedTime() - * added Countable to Finder - * added support for an array of directories as an argument to - Finder::exclude() - * added searching based on the file content via Finder::contains() and - Finder::notContains() - * added support for the != operator in the Comparator - * [BC BREAK] filter expressions (used for file name and content) are no more - considered as regexps but glob patterns when they are enclosed in '*' or '?' diff --git a/lib/symfony/finder/Comparator/Comparator.php b/lib/symfony/finder/Comparator/Comparator.php deleted file mode 100644 index 3af551f4c..000000000 --- a/lib/symfony/finder/Comparator/Comparator.php +++ /dev/null @@ -1,117 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Comparator; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -class Comparator -{ - private $target; - private $operator = '=='; - - public function __construct(string $target = null, string $operator = '==') - { - if (null === $target) { - trigger_deprecation('symfony/finder', '5.4', 'Constructing a "%s" without setting "$target" is deprecated.', __CLASS__); - } - - $this->target = $target; - $this->doSetOperator($operator); - } - - /** - * Gets the target value. - * - * @return string - */ - public function getTarget() - { - if (null === $this->target) { - trigger_deprecation('symfony/finder', '5.4', 'Calling "%s" without initializing the target is deprecated.', __METHOD__); - } - - return $this->target; - } - - /** - * @deprecated set the target via the constructor instead - */ - public function setTarget(string $target) - { - trigger_deprecation('symfony/finder', '5.4', '"%s" is deprecated. Set the target via the constructor instead.', __METHOD__); - - $this->target = $target; - } - - /** - * Gets the comparison operator. - * - * @return string - */ - public function getOperator() - { - return $this->operator; - } - - /** - * Sets the comparison operator. - * - * @throws \InvalidArgumentException - * - * @deprecated set the operator via the constructor instead - */ - public function setOperator(string $operator) - { - trigger_deprecation('symfony/finder', '5.4', '"%s" is deprecated. Set the operator via the constructor instead.', __METHOD__); - - $this->doSetOperator('' === $operator ? '==' : $operator); - } - - /** - * Tests against the target. - * - * @param mixed $test A test value - * - * @return bool - */ - public function test($test) - { - if (null === $this->target) { - trigger_deprecation('symfony/finder', '5.4', 'Calling "%s" without initializing the target is deprecated.', __METHOD__); - } - - switch ($this->operator) { - case '>': - return $test > $this->target; - case '>=': - return $test >= $this->target; - case '<': - return $test < $this->target; - case '<=': - return $test <= $this->target; - case '!=': - return $test != $this->target; - } - - return $test == $this->target; - } - - private function doSetOperator(string $operator): void - { - if (!\in_array($operator, ['>', '<', '>=', '<=', '==', '!='])) { - throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator)); - } - - $this->operator = $operator; - } -} diff --git a/lib/symfony/finder/Comparator/DateComparator.php b/lib/symfony/finder/Comparator/DateComparator.php deleted file mode 100644 index 8f651e148..000000000 --- a/lib/symfony/finder/Comparator/DateComparator.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Comparator; - -/** - * DateCompare compiles date comparisons. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class DateComparator extends Comparator -{ - /** - * @param string $test A comparison string - * - * @throws \InvalidArgumentException If the test is not understood - */ - public function __construct(string $test) - { - if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) { - throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test)); - } - - try { - $date = new \DateTime($matches[2]); - $target = $date->format('U'); - } catch (\Exception $e) { - throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2])); - } - - $operator = $matches[1] ?? '=='; - if ('since' === $operator || 'after' === $operator) { - $operator = '>'; - } - - if ('until' === $operator || 'before' === $operator) { - $operator = '<'; - } - - parent::__construct($target, $operator); - } -} diff --git a/lib/symfony/finder/Comparator/NumberComparator.php b/lib/symfony/finder/Comparator/NumberComparator.php deleted file mode 100644 index ff85d9677..000000000 --- a/lib/symfony/finder/Comparator/NumberComparator.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Comparator; - -/** - * NumberComparator compiles a simple comparison to an anonymous - * subroutine, which you can call with a value to be tested again. - * - * Now this would be very pointless, if NumberCompare didn't understand - * magnitudes. - * - * The target value may use magnitudes of kilobytes (k, ki), - * megabytes (m, mi), or gigabytes (g, gi). Those suffixed - * with an i use the appropriate 2**n version in accordance with the - * IEC standard: http://physics.nist.gov/cuu/Units/binary.html - * - * Based on the Perl Number::Compare module. - * - * @author Fabien Potencier <fabien@symfony.com> PHP port - * @author Richard Clamp <richardc@unixbeard.net> Perl version - * @copyright 2004-2005 Fabien Potencier <fabien@symfony.com> - * @copyright 2002 Richard Clamp <richardc@unixbeard.net> - * - * @see http://physics.nist.gov/cuu/Units/binary.html - */ -class NumberComparator extends Comparator -{ - /** - * @param string|int $test A comparison string or an integer - * - * @throws \InvalidArgumentException If the test is not understood - */ - public function __construct(?string $test) - { - if (null === $test || !preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) { - throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test ?? 'null')); - } - - $target = $matches[2]; - if (!is_numeric($target)) { - throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target)); - } - if (isset($matches[3])) { - // magnitude - switch (strtolower($matches[3])) { - case 'k': - $target *= 1000; - break; - case 'ki': - $target *= 1024; - break; - case 'm': - $target *= 1000000; - break; - case 'mi': - $target *= 1024 * 1024; - break; - case 'g': - $target *= 1000000000; - break; - case 'gi': - $target *= 1024 * 1024 * 1024; - break; - } - } - - parent::__construct($target, $matches[1] ?: '=='); - } -} diff --git a/lib/symfony/finder/Exception/AccessDeniedException.php b/lib/symfony/finder/Exception/AccessDeniedException.php deleted file mode 100644 index ee195ea8d..000000000 --- a/lib/symfony/finder/Exception/AccessDeniedException.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Exception; - -/** - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - */ -class AccessDeniedException extends \UnexpectedValueException -{ -} diff --git a/lib/symfony/finder/Exception/DirectoryNotFoundException.php b/lib/symfony/finder/Exception/DirectoryNotFoundException.php deleted file mode 100644 index c6cc0f273..000000000 --- a/lib/symfony/finder/Exception/DirectoryNotFoundException.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Exception; - -/** - * @author Andreas Erhard <andreas.erhard@i-med.ac.at> - */ -class DirectoryNotFoundException extends \InvalidArgumentException -{ -} diff --git a/lib/symfony/finder/Finder.php b/lib/symfony/finder/Finder.php deleted file mode 100644 index 8cc564cd6..000000000 --- a/lib/symfony/finder/Finder.php +++ /dev/null @@ -1,806 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder; - -use Symfony\Component\Finder\Comparator\DateComparator; -use Symfony\Component\Finder\Comparator\NumberComparator; -use Symfony\Component\Finder\Exception\DirectoryNotFoundException; -use Symfony\Component\Finder\Iterator\CustomFilterIterator; -use Symfony\Component\Finder\Iterator\DateRangeFilterIterator; -use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator; -use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator; -use Symfony\Component\Finder\Iterator\FilecontentFilterIterator; -use Symfony\Component\Finder\Iterator\FilenameFilterIterator; -use Symfony\Component\Finder\Iterator\LazyIterator; -use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator; -use Symfony\Component\Finder\Iterator\SortableIterator; - -/** - * Finder allows to build rules to find files and directories. - * - * It is a thin wrapper around several specialized iterator classes. - * - * All rules may be invoked several times. - * - * All methods return the current Finder object to allow chaining: - * - * $finder = Finder::create()->files()->name('*.php')->in(__DIR__); - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @implements \IteratorAggregate<string, SplFileInfo> - */ -class Finder implements \IteratorAggregate, \Countable -{ - public const IGNORE_VCS_FILES = 1; - public const IGNORE_DOT_FILES = 2; - public const IGNORE_VCS_IGNORED_FILES = 4; - - private $mode = 0; - private $names = []; - private $notNames = []; - private $exclude = []; - private $filters = []; - private $depths = []; - private $sizes = []; - private $followLinks = false; - private $reverseSorting = false; - private $sort = false; - private $ignore = 0; - private $dirs = []; - private $dates = []; - private $iterators = []; - private $contains = []; - private $notContains = []; - private $paths = []; - private $notPaths = []; - private $ignoreUnreadableDirs = false; - - private static $vcsPatterns = ['.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg']; - - public function __construct() - { - $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES; - } - - /** - * Creates a new Finder. - * - * @return static - */ - public static function create() - { - return new static(); - } - - /** - * Restricts the matching to directories only. - * - * @return $this - */ - public function directories() - { - $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES; - - return $this; - } - - /** - * Restricts the matching to files only. - * - * @return $this - */ - public function files() - { - $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES; - - return $this; - } - - /** - * Adds tests for the directory depth. - * - * Usage: - * - * $finder->depth('> 1') // the Finder will start matching at level 1. - * $finder->depth('< 3') // the Finder will descend at most 3 levels of directories below the starting point. - * $finder->depth(['>= 1', '< 3']) - * - * @param string|int|string[]|int[] $levels The depth level expression or an array of depth levels - * - * @return $this - * - * @see DepthRangeFilterIterator - * @see NumberComparator - */ - public function depth($levels) - { - foreach ((array) $levels as $level) { - $this->depths[] = new Comparator\NumberComparator($level); - } - - return $this; - } - - /** - * Adds tests for file dates (last modified). - * - * The date must be something that strtotime() is able to parse: - * - * $finder->date('since yesterday'); - * $finder->date('until 2 days ago'); - * $finder->date('> now - 2 hours'); - * $finder->date('>= 2005-10-15'); - * $finder->date(['>= 2005-10-15', '<= 2006-05-27']); - * - * @param string|string[] $dates A date range string or an array of date ranges - * - * @return $this - * - * @see strtotime - * @see DateRangeFilterIterator - * @see DateComparator - */ - public function date($dates) - { - foreach ((array) $dates as $date) { - $this->dates[] = new Comparator\DateComparator($date); - } - - return $this; - } - - /** - * Adds rules that files must match. - * - * You can use patterns (delimited with / sign), globs or simple strings. - * - * $finder->name('*.php') - * $finder->name('/\.php$/') // same as above - * $finder->name('test.php') - * $finder->name(['test.py', 'test.php']) - * - * @param string|string[] $patterns A pattern (a regexp, a glob, or a string) or an array of patterns - * - * @return $this - * - * @see FilenameFilterIterator - */ - public function name($patterns) - { - $this->names = array_merge($this->names, (array) $patterns); - - return $this; - } - - /** - * Adds rules that files must not match. - * - * @param string|string[] $patterns A pattern (a regexp, a glob, or a string) or an array of patterns - * - * @return $this - * - * @see FilenameFilterIterator - */ - public function notName($patterns) - { - $this->notNames = array_merge($this->notNames, (array) $patterns); - - return $this; - } - - /** - * Adds tests that file contents must match. - * - * Strings or PCRE patterns can be used: - * - * $finder->contains('Lorem ipsum') - * $finder->contains('/Lorem ipsum/i') - * $finder->contains(['dolor', '/ipsum/i']) - * - * @param string|string[] $patterns A pattern (string or regexp) or an array of patterns - * - * @return $this - * - * @see FilecontentFilterIterator - */ - public function contains($patterns) - { - $this->contains = array_merge($this->contains, (array) $patterns); - - return $this; - } - - /** - * Adds tests that file contents must not match. - * - * Strings or PCRE patterns can be used: - * - * $finder->notContains('Lorem ipsum') - * $finder->notContains('/Lorem ipsum/i') - * $finder->notContains(['lorem', '/dolor/i']) - * - * @param string|string[] $patterns A pattern (string or regexp) or an array of patterns - * - * @return $this - * - * @see FilecontentFilterIterator - */ - public function notContains($patterns) - { - $this->notContains = array_merge($this->notContains, (array) $patterns); - - return $this; - } - - /** - * Adds rules that filenames must match. - * - * You can use patterns (delimited with / sign) or simple strings. - * - * $finder->path('some/special/dir') - * $finder->path('/some\/special\/dir/') // same as above - * $finder->path(['some dir', 'another/dir']) - * - * Use only / as dirname separator. - * - * @param string|string[] $patterns A pattern (a regexp or a string) or an array of patterns - * - * @return $this - * - * @see FilenameFilterIterator - */ - public function path($patterns) - { - $this->paths = array_merge($this->paths, (array) $patterns); - - return $this; - } - - /** - * Adds rules that filenames must not match. - * - * You can use patterns (delimited with / sign) or simple strings. - * - * $finder->notPath('some/special/dir') - * $finder->notPath('/some\/special\/dir/') // same as above - * $finder->notPath(['some/file.txt', 'another/file.log']) - * - * Use only / as dirname separator. - * - * @param string|string[] $patterns A pattern (a regexp or a string) or an array of patterns - * - * @return $this - * - * @see FilenameFilterIterator - */ - public function notPath($patterns) - { - $this->notPaths = array_merge($this->notPaths, (array) $patterns); - - return $this; - } - - /** - * Adds tests for file sizes. - * - * $finder->size('> 10K'); - * $finder->size('<= 1Ki'); - * $finder->size(4); - * $finder->size(['> 10K', '< 20K']) - * - * @param string|int|string[]|int[] $sizes A size range string or an integer or an array of size ranges - * - * @return $this - * - * @see SizeRangeFilterIterator - * @see NumberComparator - */ - public function size($sizes) - { - foreach ((array) $sizes as $size) { - $this->sizes[] = new Comparator\NumberComparator($size); - } - - return $this; - } - - /** - * Excludes directories. - * - * Directories passed as argument must be relative to the ones defined with the `in()` method. For example: - * - * $finder->in(__DIR__)->exclude('ruby'); - * - * @param string|array $dirs A directory path or an array of directories - * - * @return $this - * - * @see ExcludeDirectoryFilterIterator - */ - public function exclude($dirs) - { - $this->exclude = array_merge($this->exclude, (array) $dirs); - - return $this; - } - - /** - * Excludes "hidden" directories and files (starting with a dot). - * - * This option is enabled by default. - * - * @return $this - * - * @see ExcludeDirectoryFilterIterator - */ - public function ignoreDotFiles(bool $ignoreDotFiles) - { - if ($ignoreDotFiles) { - $this->ignore |= static::IGNORE_DOT_FILES; - } else { - $this->ignore &= ~static::IGNORE_DOT_FILES; - } - - return $this; - } - - /** - * Forces the finder to ignore version control directories. - * - * This option is enabled by default. - * - * @return $this - * - * @see ExcludeDirectoryFilterIterator - */ - public function ignoreVCS(bool $ignoreVCS) - { - if ($ignoreVCS) { - $this->ignore |= static::IGNORE_VCS_FILES; - } else { - $this->ignore &= ~static::IGNORE_VCS_FILES; - } - - return $this; - } - - /** - * Forces Finder to obey .gitignore and ignore files based on rules listed there. - * - * This option is disabled by default. - * - * @return $this - */ - public function ignoreVCSIgnored(bool $ignoreVCSIgnored) - { - if ($ignoreVCSIgnored) { - $this->ignore |= static::IGNORE_VCS_IGNORED_FILES; - } else { - $this->ignore &= ~static::IGNORE_VCS_IGNORED_FILES; - } - - return $this; - } - - /** - * Adds VCS patterns. - * - * @see ignoreVCS() - * - * @param string|string[] $pattern VCS patterns to ignore - */ - public static function addVCSPattern($pattern) - { - foreach ((array) $pattern as $p) { - self::$vcsPatterns[] = $p; - } - - self::$vcsPatterns = array_unique(self::$vcsPatterns); - } - - /** - * Sorts files and directories by an anonymous function. - * - * The anonymous function receives two \SplFileInfo instances to compare. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return $this - * - * @see SortableIterator - */ - public function sort(\Closure $closure) - { - $this->sort = $closure; - - return $this; - } - - /** - * Sorts files and directories by name. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return $this - * - * @see SortableIterator - */ - public function sortByName(bool $useNaturalSort = false) - { - $this->sort = $useNaturalSort ? Iterator\SortableIterator::SORT_BY_NAME_NATURAL : Iterator\SortableIterator::SORT_BY_NAME; - - return $this; - } - - /** - * Sorts files and directories by type (directories before files), then by name. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return $this - * - * @see SortableIterator - */ - public function sortByType() - { - $this->sort = Iterator\SortableIterator::SORT_BY_TYPE; - - return $this; - } - - /** - * Sorts files and directories by the last accessed time. - * - * This is the time that the file was last accessed, read or written to. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return $this - * - * @see SortableIterator - */ - public function sortByAccessedTime() - { - $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME; - - return $this; - } - - /** - * Reverses the sorting. - * - * @return $this - */ - public function reverseSorting() - { - $this->reverseSorting = true; - - return $this; - } - - /** - * Sorts files and directories by the last inode changed time. - * - * This is the time that the inode information was last modified (permissions, owner, group or other metadata). - * - * On Windows, since inode is not available, changed time is actually the file creation time. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return $this - * - * @see SortableIterator - */ - public function sortByChangedTime() - { - $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME; - - return $this; - } - - /** - * Sorts files and directories by the last modified time. - * - * This is the last time the actual contents of the file were last modified. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return $this - * - * @see SortableIterator - */ - public function sortByModifiedTime() - { - $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME; - - return $this; - } - - /** - * Filters the iterator with an anonymous function. - * - * The anonymous function receives a \SplFileInfo and must return false - * to remove files. - * - * @return $this - * - * @see CustomFilterIterator - */ - public function filter(\Closure $closure) - { - $this->filters[] = $closure; - - return $this; - } - - /** - * Forces the following of symlinks. - * - * @return $this - */ - public function followLinks() - { - $this->followLinks = true; - - return $this; - } - - /** - * Tells finder to ignore unreadable directories. - * - * By default, scanning unreadable directories content throws an AccessDeniedException. - * - * @return $this - */ - public function ignoreUnreadableDirs(bool $ignore = true) - { - $this->ignoreUnreadableDirs = $ignore; - - return $this; - } - - /** - * Searches files and directories which match defined rules. - * - * @param string|string[] $dirs A directory path or an array of directories - * - * @return $this - * - * @throws DirectoryNotFoundException if one of the directories does not exist - */ - public function in($dirs) - { - $resolvedDirs = []; - - foreach ((array) $dirs as $dir) { - if (is_dir($dir)) { - $resolvedDirs[] = [$this->normalizeDir($dir)]; - } elseif ($glob = glob($dir, (\defined('GLOB_BRACE') ? \GLOB_BRACE : 0) | \GLOB_ONLYDIR | \GLOB_NOSORT)) { - sort($glob); - $resolvedDirs[] = array_map([$this, 'normalizeDir'], $glob); - } else { - throw new DirectoryNotFoundException(sprintf('The "%s" directory does not exist.', $dir)); - } - } - - $this->dirs = array_merge($this->dirs, ...$resolvedDirs); - - return $this; - } - - /** - * Returns an Iterator for the current Finder configuration. - * - * This method implements the IteratorAggregate interface. - * - * @return \Iterator<string, SplFileInfo> - * - * @throws \LogicException if the in() method has not been called - */ - #[\ReturnTypeWillChange] - public function getIterator() - { - if (0 === \count($this->dirs) && 0 === \count($this->iterators)) { - throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.'); - } - - if (1 === \count($this->dirs) && 0 === \count($this->iterators)) { - $iterator = $this->searchInDirectory($this->dirs[0]); - - if ($this->sort || $this->reverseSorting) { - $iterator = (new Iterator\SortableIterator($iterator, $this->sort, $this->reverseSorting))->getIterator(); - } - - return $iterator; - } - - $iterator = new \AppendIterator(); - foreach ($this->dirs as $dir) { - $iterator->append(new \IteratorIterator(new LazyIterator(function () use ($dir) { - return $this->searchInDirectory($dir); - }))); - } - - foreach ($this->iterators as $it) { - $iterator->append($it); - } - - if ($this->sort || $this->reverseSorting) { - $iterator = (new Iterator\SortableIterator($iterator, $this->sort, $this->reverseSorting))->getIterator(); - } - - return $iterator; - } - - /** - * Appends an existing set of files/directories to the finder. - * - * The set can be another Finder, an Iterator, an IteratorAggregate, or even a plain array. - * - * @return $this - * - * @throws \InvalidArgumentException when the given argument is not iterable - */ - public function append(iterable $iterator) - { - if ($iterator instanceof \IteratorAggregate) { - $this->iterators[] = $iterator->getIterator(); - } elseif ($iterator instanceof \Iterator) { - $this->iterators[] = $iterator; - } elseif (is_iterable($iterator)) { - $it = new \ArrayIterator(); - foreach ($iterator as $file) { - $file = $file instanceof \SplFileInfo ? $file : new \SplFileInfo($file); - $it[$file->getPathname()] = $file; - } - $this->iterators[] = $it; - } else { - throw new \InvalidArgumentException('Finder::append() method wrong argument type.'); - } - - return $this; - } - - /** - * Check if any results were found. - * - * @return bool - */ - public function hasResults() - { - foreach ($this->getIterator() as $_) { - return true; - } - - return false; - } - - /** - * Counts all the results collected by the iterators. - * - * @return int - */ - #[\ReturnTypeWillChange] - public function count() - { - return iterator_count($this->getIterator()); - } - - private function searchInDirectory(string $dir): \Iterator - { - $exclude = $this->exclude; - $notPaths = $this->notPaths; - - if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) { - $exclude = array_merge($exclude, self::$vcsPatterns); - } - - if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) { - $notPaths[] = '#(^|/)\..+(/|$)#'; - } - - $minDepth = 0; - $maxDepth = \PHP_INT_MAX; - - foreach ($this->depths as $comparator) { - switch ($comparator->getOperator()) { - case '>': - $minDepth = $comparator->getTarget() + 1; - break; - case '>=': - $minDepth = $comparator->getTarget(); - break; - case '<': - $maxDepth = $comparator->getTarget() - 1; - break; - case '<=': - $maxDepth = $comparator->getTarget(); - break; - default: - $minDepth = $maxDepth = $comparator->getTarget(); - } - } - - $flags = \RecursiveDirectoryIterator::SKIP_DOTS; - - if ($this->followLinks) { - $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS; - } - - $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs); - - if ($exclude) { - $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $exclude); - } - - $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST); - - if ($minDepth > 0 || $maxDepth < \PHP_INT_MAX) { - $iterator = new Iterator\DepthRangeFilterIterator($iterator, $minDepth, $maxDepth); - } - - if ($this->mode) { - $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode); - } - - if ($this->names || $this->notNames) { - $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames); - } - - if ($this->contains || $this->notContains) { - $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains); - } - - if ($this->sizes) { - $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes); - } - - if ($this->dates) { - $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates); - } - - if ($this->filters) { - $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters); - } - - if ($this->paths || $notPaths) { - $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $notPaths); - } - - if (static::IGNORE_VCS_IGNORED_FILES === (static::IGNORE_VCS_IGNORED_FILES & $this->ignore)) { - $iterator = new Iterator\VcsIgnoredFilterIterator($iterator, $dir); - } - - return $iterator; - } - - /** - * Normalizes given directory names by removing trailing slashes. - * - * Excluding: (s)ftp:// or ssh2.(s)ftp:// wrapper - */ - private function normalizeDir(string $dir): string - { - if ('/' === $dir) { - return $dir; - } - - $dir = rtrim($dir, '/'.\DIRECTORY_SEPARATOR); - - if (preg_match('#^(ssh2\.)?s?ftp://#', $dir)) { - $dir .= '/'; - } - - return $dir; - } -} diff --git a/lib/symfony/finder/Gitignore.php b/lib/symfony/finder/Gitignore.php deleted file mode 100644 index d42cca1dc..000000000 --- a/lib/symfony/finder/Gitignore.php +++ /dev/null @@ -1,93 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder; - -/** - * Gitignore matches against text. - * - * @author Michael Voříšek <vorismi3@fel.cvut.cz> - * @author Ahmed Abdou <mail@ahmd.io> - */ -class Gitignore -{ - /** - * Returns a regexp which is the equivalent of the gitignore pattern. - * - * Format specification: https://git-scm.com/docs/gitignore#_pattern_format - */ - public static function toRegex(string $gitignoreFileContent): string - { - return self::buildRegex($gitignoreFileContent, false); - } - - public static function toRegexMatchingNegatedPatterns(string $gitignoreFileContent): string - { - return self::buildRegex($gitignoreFileContent, true); - } - - private static function buildRegex(string $gitignoreFileContent, bool $inverted): string - { - $gitignoreFileContent = preg_replace('~(?<!\\\\)#[^\n\r]*~', '', $gitignoreFileContent); - $gitignoreLines = preg_split('~\r\n?|\n~', $gitignoreFileContent); - - $res = self::lineToRegex(''); - foreach ($gitignoreLines as $line) { - $line = preg_replace('~(?<!\\\\)[ \t]+$~', '', $line); - - if ('!' === substr($line, 0, 1)) { - $line = substr($line, 1); - $isNegative = true; - } else { - $isNegative = false; - } - - if ('' !== $line) { - if ($isNegative xor $inverted) { - $res = '(?!'.self::lineToRegex($line).'$)'.$res; - } else { - $res = '(?:'.$res.'|'.self::lineToRegex($line).')'; - } - } - } - - return '~^(?:'.$res.')~s'; - } - - private static function lineToRegex(string $gitignoreLine): string - { - if ('' === $gitignoreLine) { - return '$f'; // always false - } - - $slashPos = strpos($gitignoreLine, '/'); - if (false !== $slashPos && \strlen($gitignoreLine) - 1 !== $slashPos) { - if (0 === $slashPos) { - $gitignoreLine = substr($gitignoreLine, 1); - } - $isAbsolute = true; - } else { - $isAbsolute = false; - } - - $regex = preg_quote(str_replace('\\', '', $gitignoreLine), '~'); - $regex = preg_replace_callback('~\\\\\[((?:\\\\!)?)([^\[\]]*)\\\\\]~', function (array $matches): string { - return '['.('' !== $matches[1] ? '^' : '').str_replace('\\-', '-', $matches[2]).']'; - }, $regex); - $regex = preg_replace('~(?:(?:\\\\\*){2,}(/?))+~', '(?:(?:(?!//).(?<!//))+$1)?', $regex); - $regex = preg_replace('~\\\\\*~', '[^/]*', $regex); - $regex = preg_replace('~\\\\\?~', '[^/]', $regex); - - return ($isAbsolute ? '' : '(?:[^/]+/)*') - .$regex - .(!str_ends_with($gitignoreLine, '/') ? '(?:$|/)' : ''); - } -} diff --git a/lib/symfony/finder/Glob.php b/lib/symfony/finder/Glob.php deleted file mode 100644 index 8447932e5..000000000 --- a/lib/symfony/finder/Glob.php +++ /dev/null @@ -1,111 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder; - -/** - * Glob matches globbing patterns against text. - * - * if match_glob("foo.*", "foo.bar") echo "matched\n"; - * - * // prints foo.bar and foo.baz - * $regex = glob_to_regex("foo.*"); - * for (['foo.bar', 'foo.baz', 'foo', 'bar'] as $t) - * { - * if (/$regex/) echo "matched: $car\n"; - * } - * - * Glob implements glob(3) style matching that can be used to match - * against text, rather than fetching names from a filesystem. - * - * Based on the Perl Text::Glob module. - * - * @author Fabien Potencier <fabien@symfony.com> PHP port - * @author Richard Clamp <richardc@unixbeard.net> Perl version - * @copyright 2004-2005 Fabien Potencier <fabien@symfony.com> - * @copyright 2002 Richard Clamp <richardc@unixbeard.net> - */ -class Glob -{ - /** - * Returns a regexp which is the equivalent of the glob pattern. - * - * @return string - */ - public static function toRegex(string $glob, bool $strictLeadingDot = true, bool $strictWildcardSlash = true, string $delimiter = '#') - { - $firstByte = true; - $escaping = false; - $inCurlies = 0; - $regex = ''; - $sizeGlob = \strlen($glob); - for ($i = 0; $i < $sizeGlob; ++$i) { - $car = $glob[$i]; - if ($firstByte && $strictLeadingDot && '.' !== $car) { - $regex .= '(?=[^\.])'; - } - - $firstByte = '/' === $car; - - if ($firstByte && $strictWildcardSlash && isset($glob[$i + 2]) && '**' === $glob[$i + 1].$glob[$i + 2] && (!isset($glob[$i + 3]) || '/' === $glob[$i + 3])) { - $car = '[^/]++/'; - if (!isset($glob[$i + 3])) { - $car .= '?'; - } - - if ($strictLeadingDot) { - $car = '(?=[^\.])'.$car; - } - - $car = '/(?:'.$car.')*'; - $i += 2 + isset($glob[$i + 3]); - - if ('/' === $delimiter) { - $car = str_replace('/', '\\/', $car); - } - } - - if ($delimiter === $car || '.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) { - $regex .= "\\$car"; - } elseif ('*' === $car) { - $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*'); - } elseif ('?' === $car) { - $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.'); - } elseif ('{' === $car) { - $regex .= $escaping ? '\\{' : '('; - if (!$escaping) { - ++$inCurlies; - } - } elseif ('}' === $car && $inCurlies) { - $regex .= $escaping ? '}' : ')'; - if (!$escaping) { - --$inCurlies; - } - } elseif (',' === $car && $inCurlies) { - $regex .= $escaping ? ',' : '|'; - } elseif ('\\' === $car) { - if ($escaping) { - $regex .= '\\\\'; - $escaping = false; - } else { - $escaping = true; - } - - continue; - } else { - $regex .= $car; - } - $escaping = false; - } - - return $delimiter.'^'.$regex.'$'.$delimiter; - } -} diff --git a/lib/symfony/finder/Iterator/CustomFilterIterator.php b/lib/symfony/finder/Iterator/CustomFilterIterator.php deleted file mode 100644 index f7bf19b87..000000000 --- a/lib/symfony/finder/Iterator/CustomFilterIterator.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * CustomFilterIterator filters files by applying anonymous functions. - * - * The anonymous function receives a \SplFileInfo and must return false - * to remove files. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @extends \FilterIterator<string, \SplFileInfo> - */ -class CustomFilterIterator extends \FilterIterator -{ - private $filters = []; - - /** - * @param \Iterator<string, \SplFileInfo> $iterator The Iterator to filter - * @param callable[] $filters An array of PHP callbacks - * - * @throws \InvalidArgumentException - */ - public function __construct(\Iterator $iterator, array $filters) - { - foreach ($filters as $filter) { - if (!\is_callable($filter)) { - throw new \InvalidArgumentException('Invalid PHP callback.'); - } - } - $this->filters = $filters; - - parent::__construct($iterator); - } - - /** - * Filters the iterator values. - * - * @return bool - */ - #[\ReturnTypeWillChange] - public function accept() - { - $fileinfo = $this->current(); - - foreach ($this->filters as $filter) { - if (false === $filter($fileinfo)) { - return false; - } - } - - return true; - } -} diff --git a/lib/symfony/finder/Iterator/DateRangeFilterIterator.php b/lib/symfony/finder/Iterator/DateRangeFilterIterator.php deleted file mode 100644 index f592e1913..000000000 --- a/lib/symfony/finder/Iterator/DateRangeFilterIterator.php +++ /dev/null @@ -1,61 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -use Symfony\Component\Finder\Comparator\DateComparator; - -/** - * DateRangeFilterIterator filters out files that are not in the given date range (last modified dates). - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @extends \FilterIterator<string, \SplFileInfo> - */ -class DateRangeFilterIterator extends \FilterIterator -{ - private $comparators = []; - - /** - * @param \Iterator<string, \SplFileInfo> $iterator - * @param DateComparator[] $comparators - */ - public function __construct(\Iterator $iterator, array $comparators) - { - $this->comparators = $comparators; - - parent::__construct($iterator); - } - - /** - * Filters the iterator values. - * - * @return bool - */ - #[\ReturnTypeWillChange] - public function accept() - { - $fileinfo = $this->current(); - - if (!file_exists($fileinfo->getPathname())) { - return false; - } - - $filedate = $fileinfo->getMTime(); - foreach ($this->comparators as $compare) { - if (!$compare->test($filedate)) { - return false; - } - } - - return true; - } -} diff --git a/lib/symfony/finder/Iterator/DepthRangeFilterIterator.php b/lib/symfony/finder/Iterator/DepthRangeFilterIterator.php deleted file mode 100644 index f593a3f08..000000000 --- a/lib/symfony/finder/Iterator/DepthRangeFilterIterator.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * DepthRangeFilterIterator limits the directory depth. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @template-covariant TKey - * @template-covariant TValue - * - * @extends \FilterIterator<TKey, TValue> - */ -class DepthRangeFilterIterator extends \FilterIterator -{ - private $minDepth = 0; - - /** - * @param \RecursiveIteratorIterator<\RecursiveIterator<TKey, TValue>> $iterator The Iterator to filter - * @param int $minDepth The min depth - * @param int $maxDepth The max depth - */ - public function __construct(\RecursiveIteratorIterator $iterator, int $minDepth = 0, int $maxDepth = \PHP_INT_MAX) - { - $this->minDepth = $minDepth; - $iterator->setMaxDepth(\PHP_INT_MAX === $maxDepth ? -1 : $maxDepth); - - parent::__construct($iterator); - } - - /** - * Filters the iterator values. - * - * @return bool - */ - #[\ReturnTypeWillChange] - public function accept() - { - return $this->getInnerIterator()->getDepth() >= $this->minDepth; - } -} diff --git a/lib/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php b/lib/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php deleted file mode 100644 index d9e182c17..000000000 --- a/lib/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php +++ /dev/null @@ -1,96 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * ExcludeDirectoryFilterIterator filters out directories. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @extends \FilterIterator<string, \SplFileInfo> - * @implements \RecursiveIterator<string, \SplFileInfo> - */ -class ExcludeDirectoryFilterIterator extends \FilterIterator implements \RecursiveIterator -{ - private $iterator; - private $isRecursive; - private $excludedDirs = []; - private $excludedPattern; - - /** - * @param \Iterator $iterator The Iterator to filter - * @param string[] $directories An array of directories to exclude - */ - public function __construct(\Iterator $iterator, array $directories) - { - $this->iterator = $iterator; - $this->isRecursive = $iterator instanceof \RecursiveIterator; - $patterns = []; - foreach ($directories as $directory) { - $directory = rtrim($directory, '/'); - if (!$this->isRecursive || str_contains($directory, '/')) { - $patterns[] = preg_quote($directory, '#'); - } else { - $this->excludedDirs[$directory] = true; - } - } - if ($patterns) { - $this->excludedPattern = '#(?:^|/)(?:'.implode('|', $patterns).')(?:/|$)#'; - } - - parent::__construct($iterator); - } - - /** - * Filters the iterator values. - * - * @return bool - */ - #[\ReturnTypeWillChange] - public function accept() - { - if ($this->isRecursive && isset($this->excludedDirs[$this->getFilename()]) && $this->isDir()) { - return false; - } - - if ($this->excludedPattern) { - $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath(); - $path = str_replace('\\', '/', $path); - - return !preg_match($this->excludedPattern, $path); - } - - return true; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function hasChildren() - { - return $this->isRecursive && $this->iterator->hasChildren(); - } - - /** - * @return self - */ - #[\ReturnTypeWillChange] - public function getChildren() - { - $children = new self($this->iterator->getChildren(), []); - $children->excludedDirs = $this->excludedDirs; - $children->excludedPattern = $this->excludedPattern; - - return $children; - } -} diff --git a/lib/symfony/finder/Iterator/FileTypeFilterIterator.php b/lib/symfony/finder/Iterator/FileTypeFilterIterator.php deleted file mode 100644 index 793ae3509..000000000 --- a/lib/symfony/finder/Iterator/FileTypeFilterIterator.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * FileTypeFilterIterator only keeps files, directories, or both. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @extends \FilterIterator<string, \SplFileInfo> - */ -class FileTypeFilterIterator extends \FilterIterator -{ - public const ONLY_FILES = 1; - public const ONLY_DIRECTORIES = 2; - - private $mode; - - /** - * @param \Iterator $iterator The Iterator to filter - * @param int $mode The mode (self::ONLY_FILES or self::ONLY_DIRECTORIES) - */ - public function __construct(\Iterator $iterator, int $mode) - { - $this->mode = $mode; - - parent::__construct($iterator); - } - - /** - * Filters the iterator values. - * - * @return bool - */ - #[\ReturnTypeWillChange] - public function accept() - { - $fileinfo = $this->current(); - if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) { - return false; - } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) { - return false; - } - - return true; - } -} diff --git a/lib/symfony/finder/Iterator/FilecontentFilterIterator.php b/lib/symfony/finder/Iterator/FilecontentFilterIterator.php deleted file mode 100644 index 79f8c29d3..000000000 --- a/lib/symfony/finder/Iterator/FilecontentFilterIterator.php +++ /dev/null @@ -1,61 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * FilecontentFilterIterator filters files by their contents using patterns (regexps or strings). - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Włodzimierz Gajda <gajdaw@gajdaw.pl> - * - * @extends MultiplePcreFilterIterator<string, \SplFileInfo> - */ -class FilecontentFilterIterator extends MultiplePcreFilterIterator -{ - /** - * Filters the iterator values. - * - * @return bool - */ - #[\ReturnTypeWillChange] - public function accept() - { - if (!$this->matchRegexps && !$this->noMatchRegexps) { - return true; - } - - $fileinfo = $this->current(); - - if ($fileinfo->isDir() || !$fileinfo->isReadable()) { - return false; - } - - $content = $fileinfo->getContents(); - if (!$content) { - return false; - } - - return $this->isAccepted($content); - } - - /** - * Converts string to regexp if necessary. - * - * @param string $str Pattern: string or regexp - * - * @return string - */ - protected function toRegex(string $str) - { - return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/'; - } -} diff --git a/lib/symfony/finder/Iterator/FilenameFilterIterator.php b/lib/symfony/finder/Iterator/FilenameFilterIterator.php deleted file mode 100644 index 77b3b2419..000000000 --- a/lib/symfony/finder/Iterator/FilenameFilterIterator.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -use Symfony\Component\Finder\Glob; - -/** - * FilenameFilterIterator filters files by patterns (a regexp, a glob, or a string). - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @extends MultiplePcreFilterIterator<string, \SplFileInfo> - */ -class FilenameFilterIterator extends MultiplePcreFilterIterator -{ - /** - * Filters the iterator values. - * - * @return bool - */ - #[\ReturnTypeWillChange] - public function accept() - { - return $this->isAccepted($this->current()->getFilename()); - } - - /** - * Converts glob to regexp. - * - * PCRE patterns are left unchanged. - * Glob strings are transformed with Glob::toRegex(). - * - * @param string $str Pattern: glob or regexp - * - * @return string - */ - protected function toRegex(string $str) - { - return $this->isRegex($str) ? $str : Glob::toRegex($str); - } -} diff --git a/lib/symfony/finder/Iterator/LazyIterator.php b/lib/symfony/finder/Iterator/LazyIterator.php deleted file mode 100644 index 32cc37ff1..000000000 --- a/lib/symfony/finder/Iterator/LazyIterator.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * @author Jérémy Derussé <jeremy@derusse.com> - * - * @internal - */ -class LazyIterator implements \IteratorAggregate -{ - private $iteratorFactory; - - public function __construct(callable $iteratorFactory) - { - $this->iteratorFactory = $iteratorFactory; - } - - public function getIterator(): \Traversable - { - yield from ($this->iteratorFactory)(); - } -} diff --git a/lib/symfony/finder/Iterator/MultiplePcreFilterIterator.php b/lib/symfony/finder/Iterator/MultiplePcreFilterIterator.php deleted file mode 100644 index 564765d8f..000000000 --- a/lib/symfony/finder/Iterator/MultiplePcreFilterIterator.php +++ /dev/null @@ -1,117 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * MultiplePcreFilterIterator filters files using patterns (regexps, globs or strings). - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @template-covariant TKey - * @template-covariant TValue - * - * @extends \FilterIterator<TKey, TValue> - */ -abstract class MultiplePcreFilterIterator extends \FilterIterator -{ - protected $matchRegexps = []; - protected $noMatchRegexps = []; - - /** - * @param \Iterator $iterator The Iterator to filter - * @param string[] $matchPatterns An array of patterns that need to match - * @param string[] $noMatchPatterns An array of patterns that need to not match - */ - public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns) - { - foreach ($matchPatterns as $pattern) { - $this->matchRegexps[] = $this->toRegex($pattern); - } - - foreach ($noMatchPatterns as $pattern) { - $this->noMatchRegexps[] = $this->toRegex($pattern); - } - - parent::__construct($iterator); - } - - /** - * Checks whether the string is accepted by the regex filters. - * - * If there is no regexps defined in the class, this method will accept the string. - * Such case can be handled by child classes before calling the method if they want to - * apply a different behavior. - * - * @return bool - */ - protected function isAccepted(string $string) - { - // should at least not match one rule to exclude - foreach ($this->noMatchRegexps as $regex) { - if (preg_match($regex, $string)) { - return false; - } - } - - // should at least match one rule - if ($this->matchRegexps) { - foreach ($this->matchRegexps as $regex) { - if (preg_match($regex, $string)) { - return true; - } - } - - return false; - } - - // If there is no match rules, the file is accepted - return true; - } - - /** - * Checks whether the string is a regex. - * - * @return bool - */ - protected function isRegex(string $str) - { - $availableModifiers = 'imsxuADU'; - - if (\PHP_VERSION_ID >= 80200) { - $availableModifiers .= 'n'; - } - - if (preg_match('/^(.{3,}?)['.$availableModifiers.']*$/', $str, $m)) { - $start = substr($m[1], 0, 1); - $end = substr($m[1], -1); - - if ($start === $end) { - return !preg_match('/[*?[:alnum:] \\\\]/', $start); - } - - foreach ([['{', '}'], ['(', ')'], ['[', ']'], ['<', '>']] as $delimiters) { - if ($start === $delimiters[0] && $end === $delimiters[1]) { - return true; - } - } - } - - return false; - } - - /** - * Converts string into regexp. - * - * @return string - */ - abstract protected function toRegex(string $str); -} diff --git a/lib/symfony/finder/Iterator/PathFilterIterator.php b/lib/symfony/finder/Iterator/PathFilterIterator.php deleted file mode 100644 index 7974c4ee3..000000000 --- a/lib/symfony/finder/Iterator/PathFilterIterator.php +++ /dev/null @@ -1,59 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * PathFilterIterator filters files by path patterns (e.g. some/special/dir). - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Włodzimierz Gajda <gajdaw@gajdaw.pl> - * - * @extends MultiplePcreFilterIterator<string, \SplFileInfo> - */ -class PathFilterIterator extends MultiplePcreFilterIterator -{ - /** - * Filters the iterator values. - * - * @return bool - */ - #[\ReturnTypeWillChange] - public function accept() - { - $filename = $this->current()->getRelativePathname(); - - if ('\\' === \DIRECTORY_SEPARATOR) { - $filename = str_replace('\\', '/', $filename); - } - - return $this->isAccepted($filename); - } - - /** - * Converts strings to regexp. - * - * PCRE patterns are left unchanged. - * - * Default conversion: - * 'lorem/ipsum/dolor' ==> 'lorem\/ipsum\/dolor/' - * - * Use only / as directory separator (on Windows also). - * - * @param string $str Pattern: regexp or dirname - * - * @return string - */ - protected function toRegex(string $str) - { - return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/'; - } -} diff --git a/lib/symfony/finder/Iterator/RecursiveDirectoryIterator.php b/lib/symfony/finder/Iterator/RecursiveDirectoryIterator.php deleted file mode 100644 index 27589cdd5..000000000 --- a/lib/symfony/finder/Iterator/RecursiveDirectoryIterator.php +++ /dev/null @@ -1,168 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -use Symfony\Component\Finder\Exception\AccessDeniedException; -use Symfony\Component\Finder\SplFileInfo; - -/** - * Extends the \RecursiveDirectoryIterator to support relative paths. - * - * @author Victor Berchet <victor@suumit.com> - */ -class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator -{ - /** - * @var bool - */ - private $ignoreUnreadableDirs; - - /** - * @var bool - */ - private $rewindable; - - // these 3 properties take part of the performance optimization to avoid redoing the same work in all iterations - private $rootPath; - private $subPath; - private $directorySeparator = '/'; - - /** - * @throws \RuntimeException - */ - public function __construct(string $path, int $flags, bool $ignoreUnreadableDirs = false) - { - if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) { - throw new \RuntimeException('This iterator only support returning current as fileinfo.'); - } - - parent::__construct($path, $flags); - $this->ignoreUnreadableDirs = $ignoreUnreadableDirs; - $this->rootPath = $path; - if ('/' !== \DIRECTORY_SEPARATOR && !($flags & self::UNIX_PATHS)) { - $this->directorySeparator = \DIRECTORY_SEPARATOR; - } - } - - /** - * Return an instance of SplFileInfo with support for relative paths. - * - * @return SplFileInfo - */ - #[\ReturnTypeWillChange] - public function current() - { - // the logic here avoids redoing the same work in all iterations - - if (null === $subPathname = $this->subPath) { - $subPathname = $this->subPath = $this->getSubPath(); - } - if ('' !== $subPathname) { - $subPathname .= $this->directorySeparator; - } - $subPathname .= $this->getFilename(); - - if ('/' !== $basePath = $this->rootPath) { - $basePath .= $this->directorySeparator; - } - - return new SplFileInfo($basePath.$subPathname, $this->subPath, $subPathname); - } - - /** - * @param bool $allowLinks - * - * @return bool - */ - #[\ReturnTypeWillChange] - public function hasChildren($allowLinks = false) - { - $hasChildren = parent::hasChildren($allowLinks); - - if (!$hasChildren || !$this->ignoreUnreadableDirs) { - return $hasChildren; - } - - try { - parent::getChildren(); - - return true; - } catch (\UnexpectedValueException $e) { - // If directory is unreadable and finder is set to ignore it, skip children - return false; - } - } - - /** - * @return \RecursiveDirectoryIterator - * - * @throws AccessDeniedException - */ - #[\ReturnTypeWillChange] - public function getChildren() - { - try { - $children = parent::getChildren(); - - if ($children instanceof self) { - // parent method will call the constructor with default arguments, so unreadable dirs won't be ignored anymore - $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs; - - // performance optimization to avoid redoing the same work in all children - $children->rewindable = &$this->rewindable; - $children->rootPath = $this->rootPath; - } - - return $children; - } catch (\UnexpectedValueException $e) { - throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e); - } - } - - /** - * Do nothing for non rewindable stream. - * - * @return void - */ - #[\ReturnTypeWillChange] - public function rewind() - { - if (false === $this->isRewindable()) { - return; - } - - parent::rewind(); - } - - /** - * Checks if the stream is rewindable. - * - * @return bool - */ - public function isRewindable() - { - if (null !== $this->rewindable) { - return $this->rewindable; - } - - if (false !== $stream = @opendir($this->getPath())) { - $infos = stream_get_meta_data($stream); - closedir($stream); - - if ($infos['seekable']) { - return $this->rewindable = true; - } - } - - return $this->rewindable = false; - } -} diff --git a/lib/symfony/finder/Iterator/SizeRangeFilterIterator.php b/lib/symfony/finder/Iterator/SizeRangeFilterIterator.php deleted file mode 100644 index 575bf29b7..000000000 --- a/lib/symfony/finder/Iterator/SizeRangeFilterIterator.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -use Symfony\Component\Finder\Comparator\NumberComparator; - -/** - * SizeRangeFilterIterator filters out files that are not in the given size range. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @extends \FilterIterator<string, \SplFileInfo> - */ -class SizeRangeFilterIterator extends \FilterIterator -{ - private $comparators = []; - - /** - * @param \Iterator<string, \SplFileInfo> $iterator - * @param NumberComparator[] $comparators - */ - public function __construct(\Iterator $iterator, array $comparators) - { - $this->comparators = $comparators; - - parent::__construct($iterator); - } - - /** - * Filters the iterator values. - * - * @return bool - */ - #[\ReturnTypeWillChange] - public function accept() - { - $fileinfo = $this->current(); - if (!$fileinfo->isFile()) { - return true; - } - - $filesize = $fileinfo->getSize(); - foreach ($this->comparators as $compare) { - if (!$compare->test($filesize)) { - return false; - } - } - - return true; - } -} diff --git a/lib/symfony/finder/Iterator/SortableIterator.php b/lib/symfony/finder/Iterator/SortableIterator.php deleted file mode 100644 index 9afde5c25..000000000 --- a/lib/symfony/finder/Iterator/SortableIterator.php +++ /dev/null @@ -1,104 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * SortableIterator applies a sort on a given Iterator. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @implements \IteratorAggregate<string, \SplFileInfo> - */ -class SortableIterator implements \IteratorAggregate -{ - public const SORT_BY_NONE = 0; - public const SORT_BY_NAME = 1; - public const SORT_BY_TYPE = 2; - public const SORT_BY_ACCESSED_TIME = 3; - public const SORT_BY_CHANGED_TIME = 4; - public const SORT_BY_MODIFIED_TIME = 5; - public const SORT_BY_NAME_NATURAL = 6; - - private $iterator; - private $sort; - - /** - * @param \Traversable<string, \SplFileInfo> $iterator - * @param int|callable $sort The sort type (SORT_BY_NAME, SORT_BY_TYPE, or a PHP callback) - * - * @throws \InvalidArgumentException - */ - public function __construct(\Traversable $iterator, $sort, bool $reverseOrder = false) - { - $this->iterator = $iterator; - $order = $reverseOrder ? -1 : 1; - - if (self::SORT_BY_NAME === $sort) { - $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { - return $order * strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname()); - }; - } elseif (self::SORT_BY_NAME_NATURAL === $sort) { - $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { - return $order * strnatcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname()); - }; - } elseif (self::SORT_BY_TYPE === $sort) { - $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { - if ($a->isDir() && $b->isFile()) { - return -$order; - } elseif ($a->isFile() && $b->isDir()) { - return $order; - } - - return $order * strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname()); - }; - } elseif (self::SORT_BY_ACCESSED_TIME === $sort) { - $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { - return $order * ($a->getATime() - $b->getATime()); - }; - } elseif (self::SORT_BY_CHANGED_TIME === $sort) { - $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { - return $order * ($a->getCTime() - $b->getCTime()); - }; - } elseif (self::SORT_BY_MODIFIED_TIME === $sort) { - $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { - return $order * ($a->getMTime() - $b->getMTime()); - }; - } elseif (self::SORT_BY_NONE === $sort) { - $this->sort = $order; - } elseif (\is_callable($sort)) { - $this->sort = $reverseOrder ? static function (\SplFileInfo $a, \SplFileInfo $b) use ($sort) { return -$sort($a, $b); } : $sort; - } else { - throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.'); - } - } - - /** - * @return \Traversable<string, \SplFileInfo> - */ - #[\ReturnTypeWillChange] - public function getIterator() - { - if (1 === $this->sort) { - return $this->iterator; - } - - $array = iterator_to_array($this->iterator, true); - - if (-1 === $this->sort) { - $array = array_reverse($array); - } else { - uasort($array, $this->sort); - } - - return new \ArrayIterator($array); - } -} diff --git a/lib/symfony/finder/Iterator/VcsIgnoredFilterIterator.php b/lib/symfony/finder/Iterator/VcsIgnoredFilterIterator.php deleted file mode 100644 index e27158cbd..000000000 --- a/lib/symfony/finder/Iterator/VcsIgnoredFilterIterator.php +++ /dev/null @@ -1,151 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -use Symfony\Component\Finder\Gitignore; - -final class VcsIgnoredFilterIterator extends \FilterIterator -{ - /** - * @var string - */ - private $baseDir; - - /** - * @var array<string, array{0: string, 1: string}|null> - */ - private $gitignoreFilesCache = []; - - /** - * @var array<string, bool> - */ - private $ignoredPathsCache = []; - - public function __construct(\Iterator $iterator, string $baseDir) - { - $this->baseDir = $this->normalizePath($baseDir); - - parent::__construct($iterator); - } - - public function accept(): bool - { - $file = $this->current(); - - $fileRealPath = $this->normalizePath($file->getRealPath()); - - return !$this->isIgnored($fileRealPath); - } - - private function isIgnored(string $fileRealPath): bool - { - if (is_dir($fileRealPath) && !str_ends_with($fileRealPath, '/')) { - $fileRealPath .= '/'; - } - - if (isset($this->ignoredPathsCache[$fileRealPath])) { - return $this->ignoredPathsCache[$fileRealPath]; - } - - $ignored = false; - - foreach ($this->parentsDirectoryDownward($fileRealPath) as $parentDirectory) { - if ($this->isIgnored($parentDirectory)) { - // rules in ignored directories are ignored, no need to check further. - break; - } - - $fileRelativePath = substr($fileRealPath, \strlen($parentDirectory) + 1); - - if (null === $regexps = $this->readGitignoreFile("{$parentDirectory}/.gitignore")) { - continue; - } - - [$exclusionRegex, $inclusionRegex] = $regexps; - - if (preg_match($exclusionRegex, $fileRelativePath)) { - $ignored = true; - - continue; - } - - if (preg_match($inclusionRegex, $fileRelativePath)) { - $ignored = false; - } - } - - return $this->ignoredPathsCache[$fileRealPath] = $ignored; - } - - /** - * @return list<string> - */ - private function parentsDirectoryDownward(string $fileRealPath): array - { - $parentDirectories = []; - - $parentDirectory = $fileRealPath; - - while (true) { - $newParentDirectory = \dirname($parentDirectory); - - // dirname('/') = '/' - if ($newParentDirectory === $parentDirectory) { - break; - } - - $parentDirectory = $newParentDirectory; - - if (0 !== strpos($parentDirectory, $this->baseDir)) { - break; - } - - $parentDirectories[] = $parentDirectory; - } - - return array_reverse($parentDirectories); - } - - /** - * @return array{0: string, 1: string}|null - */ - private function readGitignoreFile(string $path): ?array - { - if (\array_key_exists($path, $this->gitignoreFilesCache)) { - return $this->gitignoreFilesCache[$path]; - } - - if (!file_exists($path)) { - return $this->gitignoreFilesCache[$path] = null; - } - - if (!is_file($path) || !is_readable($path)) { - throw new \RuntimeException("The \"ignoreVCSIgnored\" option cannot be used by the Finder as the \"{$path}\" file is not readable."); - } - - $gitignoreFileContent = file_get_contents($path); - - return $this->gitignoreFilesCache[$path] = [ - Gitignore::toRegex($gitignoreFileContent), - Gitignore::toRegexMatchingNegatedPatterns($gitignoreFileContent), - ]; - } - - private function normalizePath(string $path): string - { - if ('\\' === \DIRECTORY_SEPARATOR) { - return str_replace('\\', '/', $path); - } - - return $path; - } -} diff --git a/lib/symfony/finder/LICENSE b/lib/symfony/finder/LICENSE deleted file mode 100644 index 88bf75bb4..000000000 --- a/lib/symfony/finder/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-2022 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -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/lib/symfony/finder/README.md b/lib/symfony/finder/README.md deleted file mode 100644 index 22bdeb9bc..000000000 --- a/lib/symfony/finder/README.md +++ /dev/null @@ -1,14 +0,0 @@ -Finder Component -================ - -The Finder component finds files and directories via an intuitive fluent -interface. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/finder.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/lib/symfony/finder/SplFileInfo.php b/lib/symfony/finder/SplFileInfo.php deleted file mode 100644 index 11604a2ef..000000000 --- a/lib/symfony/finder/SplFileInfo.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder; - -/** - * Extends \SplFileInfo to support relative paths. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class SplFileInfo extends \SplFileInfo -{ - private $relativePath; - private $relativePathname; - - /** - * @param string $file The file name - * @param string $relativePath The relative path - * @param string $relativePathname The relative path name - */ - public function __construct(string $file, string $relativePath, string $relativePathname) - { - parent::__construct($file); - $this->relativePath = $relativePath; - $this->relativePathname = $relativePathname; - } - - /** - * Returns the relative path. - * - * This path does not contain the file name. - * - * @return string - */ - public function getRelativePath() - { - return $this->relativePath; - } - - /** - * Returns the relative path name. - * - * This path contains the file name. - * - * @return string - */ - public function getRelativePathname() - { - return $this->relativePathname; - } - - public function getFilenameWithoutExtension(): string - { - $filename = $this->getFilename(); - - return pathinfo($filename, \PATHINFO_FILENAME); - } - - /** - * Returns the contents of the file. - * - * @return string - * - * @throws \RuntimeException - */ - public function getContents() - { - set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); - try { - $content = file_get_contents($this->getPathname()); - } finally { - restore_error_handler(); - } - if (false === $content) { - throw new \RuntimeException($error); - } - - return $content; - } -} diff --git a/lib/symfony/finder/composer.json b/lib/symfony/finder/composer.json deleted file mode 100644 index ef19911da..000000000 --- a/lib/symfony/finder/composer.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "symfony/finder", - "type": "library", - "description": "Finds files and directories via an intuitive fluent interface", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\Finder\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/lib/symfony/form/AbstractExtension.php b/lib/symfony/form/AbstractExtension.php deleted file mode 100644 index ca2790021..000000000 --- a/lib/symfony/form/AbstractExtension.php +++ /dev/null @@ -1,198 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\Form\Exception\InvalidArgumentException; -use Symfony\Component\Form\Exception\UnexpectedTypeException; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -abstract class AbstractExtension implements FormExtensionInterface -{ - /** - * The types provided by this extension. - * - * @var FormTypeInterface[] - */ - private $types; - - /** - * The type extensions provided by this extension. - * - * @var FormTypeExtensionInterface[][] - */ - private $typeExtensions; - - /** - * The type guesser provided by this extension. - * - * @var FormTypeGuesserInterface|null - */ - private $typeGuesser; - - /** - * Whether the type guesser has been loaded. - * - * @var bool - */ - private $typeGuesserLoaded = false; - - /** - * {@inheritdoc} - */ - public function getType(string $name) - { - if (null === $this->types) { - $this->initTypes(); - } - - if (!isset($this->types[$name])) { - throw new InvalidArgumentException(sprintf('The type "%s" cannot be loaded by this extension.', $name)); - } - - return $this->types[$name]; - } - - /** - * {@inheritdoc} - */ - public function hasType(string $name) - { - if (null === $this->types) { - $this->initTypes(); - } - - return isset($this->types[$name]); - } - - /** - * {@inheritdoc} - */ - public function getTypeExtensions(string $name) - { - if (null === $this->typeExtensions) { - $this->initTypeExtensions(); - } - - return $this->typeExtensions[$name] - ?? []; - } - - /** - * {@inheritdoc} - */ - public function hasTypeExtensions(string $name) - { - if (null === $this->typeExtensions) { - $this->initTypeExtensions(); - } - - return isset($this->typeExtensions[$name]) && \count($this->typeExtensions[$name]) > 0; - } - - /** - * {@inheritdoc} - */ - public function getTypeGuesser() - { - if (!$this->typeGuesserLoaded) { - $this->initTypeGuesser(); - } - - return $this->typeGuesser; - } - - /** - * Registers the types. - * - * @return FormTypeInterface[] - */ - protected function loadTypes() - { - return []; - } - - /** - * Registers the type extensions. - * - * @return FormTypeExtensionInterface[] - */ - protected function loadTypeExtensions() - { - return []; - } - - /** - * Registers the type guesser. - * - * @return FormTypeGuesserInterface|null - */ - protected function loadTypeGuesser() - { - return null; - } - - /** - * Initializes the types. - * - * @throws UnexpectedTypeException if any registered type is not an instance of FormTypeInterface - */ - private function initTypes() - { - $this->types = []; - - foreach ($this->loadTypes() as $type) { - if (!$type instanceof FormTypeInterface) { - throw new UnexpectedTypeException($type, FormTypeInterface::class); - } - - $this->types[\get_class($type)] = $type; - } - } - - /** - * Initializes the type extensions. - * - * @throws UnexpectedTypeException if any registered type extension is not - * an instance of FormTypeExtensionInterface - */ - private function initTypeExtensions() - { - $this->typeExtensions = []; - - foreach ($this->loadTypeExtensions() as $extension) { - if (!$extension instanceof FormTypeExtensionInterface) { - throw new UnexpectedTypeException($extension, FormTypeExtensionInterface::class); - } - - foreach ($extension::getExtendedTypes() as $extendedType) { - $this->typeExtensions[$extendedType][] = $extension; - } - } - } - - /** - * Initializes the type guesser. - * - * @throws UnexpectedTypeException if the type guesser is not an instance of FormTypeGuesserInterface - */ - private function initTypeGuesser() - { - $this->typeGuesserLoaded = true; - - $this->typeGuesser = $this->loadTypeGuesser(); - if (null !== $this->typeGuesser && !$this->typeGuesser instanceof FormTypeGuesserInterface) { - throw new UnexpectedTypeException($this->typeGuesser, FormTypeGuesserInterface::class); - } - } -} diff --git a/lib/symfony/form/AbstractRendererEngine.php b/lib/symfony/form/AbstractRendererEngine.php deleted file mode 100644 index 07bf28c88..000000000 --- a/lib/symfony/form/AbstractRendererEngine.php +++ /dev/null @@ -1,206 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Contracts\Service\ResetInterface; - -/** - * Default implementation of {@link FormRendererEngineInterface}. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -abstract class AbstractRendererEngine implements FormRendererEngineInterface, ResetInterface -{ - /** - * The variable in {@link FormView} used as cache key. - */ - public const CACHE_KEY_VAR = 'cache_key'; - - /** - * @var array - */ - protected $defaultThemes; - - /** - * @var array[] - */ - protected $themes = []; - - /** - * @var bool[] - */ - protected $useDefaultThemes = []; - - /** - * @var array[] - */ - protected $resources = []; - - /** - * @var array<array<int|false>> - */ - private $resourceHierarchyLevels = []; - - /** - * Creates a new renderer engine. - * - * @param array $defaultThemes The default themes. The type of these - * themes is open to the implementation. - */ - public function __construct(array $defaultThemes = []) - { - $this->defaultThemes = $defaultThemes; - } - - /** - * {@inheritdoc} - */ - public function setTheme(FormView $view, $themes, bool $useDefaultThemes = true) - { - $cacheKey = $view->vars[self::CACHE_KEY_VAR]; - - // Do not cast, as casting turns objects into arrays of properties - $this->themes[$cacheKey] = \is_array($themes) ? $themes : [$themes]; - $this->useDefaultThemes[$cacheKey] = $useDefaultThemes; - - // Unset instead of resetting to an empty array, in order to allow - // implementations (like TwigRendererEngine) to check whether $cacheKey - // is set at all. - unset($this->resources[$cacheKey], $this->resourceHierarchyLevels[$cacheKey]); - } - - /** - * {@inheritdoc} - */ - public function getResourceForBlockName(FormView $view, string $blockName) - { - $cacheKey = $view->vars[self::CACHE_KEY_VAR]; - - if (!isset($this->resources[$cacheKey][$blockName])) { - $this->loadResourceForBlockName($cacheKey, $view, $blockName); - } - - return $this->resources[$cacheKey][$blockName]; - } - - /** - * {@inheritdoc} - */ - public function getResourceForBlockNameHierarchy(FormView $view, array $blockNameHierarchy, int $hierarchyLevel) - { - $cacheKey = $view->vars[self::CACHE_KEY_VAR]; - $blockName = $blockNameHierarchy[$hierarchyLevel]; - - if (!isset($this->resources[$cacheKey][$blockName])) { - $this->loadResourceForBlockNameHierarchy($cacheKey, $view, $blockNameHierarchy, $hierarchyLevel); - } - - return $this->resources[$cacheKey][$blockName]; - } - - /** - * {@inheritdoc} - */ - public function getResourceHierarchyLevel(FormView $view, array $blockNameHierarchy, int $hierarchyLevel) - { - $cacheKey = $view->vars[self::CACHE_KEY_VAR]; - $blockName = $blockNameHierarchy[$hierarchyLevel]; - - if (!isset($this->resources[$cacheKey][$blockName])) { - $this->loadResourceForBlockNameHierarchy($cacheKey, $view, $blockNameHierarchy, $hierarchyLevel); - } - - // If $block was previously rendered loaded with loadTemplateForBlock(), the template - // is cached but the hierarchy level is not. In this case, we know that the block - // exists at this very hierarchy level, so we can just set it. - if (!isset($this->resourceHierarchyLevels[$cacheKey][$blockName])) { - $this->resourceHierarchyLevels[$cacheKey][$blockName] = $hierarchyLevel; - } - - return $this->resourceHierarchyLevels[$cacheKey][$blockName]; - } - - /** - * Loads the cache with the resource for a given block name. - * - * @see getResourceForBlock() - * - * @return bool - */ - abstract protected function loadResourceForBlockName(string $cacheKey, FormView $view, string $blockName); - - /** - * Loads the cache with the resource for a specific level of a block hierarchy. - * - * @see getResourceForBlockHierarchy() - */ - private function loadResourceForBlockNameHierarchy(string $cacheKey, FormView $view, array $blockNameHierarchy, int $hierarchyLevel): bool - { - $blockName = $blockNameHierarchy[$hierarchyLevel]; - - // Try to find a template for that block - if ($this->loadResourceForBlockName($cacheKey, $view, $blockName)) { - // If loadTemplateForBlock() returns true, it was able to populate the - // cache. The only missing thing is to set the hierarchy level at which - // the template was found. - $this->resourceHierarchyLevels[$cacheKey][$blockName] = $hierarchyLevel; - - return true; - } - - if ($hierarchyLevel > 0) { - $parentLevel = $hierarchyLevel - 1; - $parentBlockName = $blockNameHierarchy[$parentLevel]; - - // The next two if statements contain slightly duplicated code. This is by intention - // and tries to avoid execution of unnecessary checks in order to increase performance. - - if (isset($this->resources[$cacheKey][$parentBlockName])) { - // It may happen that the parent block is already loaded, but its level is not. - // In this case, the parent block must have been loaded by loadResourceForBlock(), - // which does not check the hierarchy of the block. Subsequently the block must have - // been found directly on the parent level. - if (!isset($this->resourceHierarchyLevels[$cacheKey][$parentBlockName])) { - $this->resourceHierarchyLevels[$cacheKey][$parentBlockName] = $parentLevel; - } - - // Cache the shortcuts for further accesses - $this->resources[$cacheKey][$blockName] = $this->resources[$cacheKey][$parentBlockName]; - $this->resourceHierarchyLevels[$cacheKey][$blockName] = $this->resourceHierarchyLevels[$cacheKey][$parentBlockName]; - - return true; - } - - if ($this->loadResourceForBlockNameHierarchy($cacheKey, $view, $blockNameHierarchy, $parentLevel)) { - // Cache the shortcuts for further accesses - $this->resources[$cacheKey][$blockName] = $this->resources[$cacheKey][$parentBlockName]; - $this->resourceHierarchyLevels[$cacheKey][$blockName] = $this->resourceHierarchyLevels[$cacheKey][$parentBlockName]; - - return true; - } - } - - // Cache the result for further accesses - $this->resources[$cacheKey][$blockName] = false; - $this->resourceHierarchyLevels[$cacheKey][$blockName] = false; - - return false; - } - - public function reset(): void - { - $this->themes = []; - $this->useDefaultThemes = []; - $this->resources = []; - $this->resourceHierarchyLevels = []; - } -} diff --git a/lib/symfony/form/AbstractType.php b/lib/symfony/form/AbstractType.php deleted file mode 100644 index 3325b8bc2..000000000 --- a/lib/symfony/form/AbstractType.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\Form\Extension\Core\Type\FormType; -use Symfony\Component\Form\Util\StringUtil; -use Symfony\Component\OptionsResolver\OptionsResolver; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -abstract class AbstractType implements FormTypeInterface -{ - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - } - - /** - * {@inheritdoc} - */ - public function buildView(FormView $view, FormInterface $form, array $options) - { - } - - /** - * {@inheritdoc} - */ - public function finishView(FormView $view, FormInterface $form, array $options) - { - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return StringUtil::fqcnToBlockPrefix(static::class) ?: ''; - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - return FormType::class; - } -} diff --git a/lib/symfony/form/AbstractTypeExtension.php b/lib/symfony/form/AbstractTypeExtension.php deleted file mode 100644 index 9d369bf29..000000000 --- a/lib/symfony/form/AbstractTypeExtension.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\OptionsResolver\OptionsResolver; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -abstract class AbstractTypeExtension implements FormTypeExtensionInterface -{ - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - } - - /** - * {@inheritdoc} - */ - public function buildView(FormView $view, FormInterface $form, array $options) - { - } - - /** - * {@inheritdoc} - */ - public function finishView(FormView $view, FormInterface $form, array $options) - { - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - } -} diff --git a/lib/symfony/form/Button.php b/lib/symfony/form/Button.php deleted file mode 100644 index 1ffdd469f..000000000 --- a/lib/symfony/form/Button.php +++ /dev/null @@ -1,455 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\Form\Exception\AlreadySubmittedException; -use Symfony\Component\Form\Exception\BadMethodCallException; - -/** - * A form button. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @implements \IteratorAggregate<string, FormInterface> - */ -class Button implements \IteratorAggregate, FormInterface -{ - /** - * @var FormInterface|null - */ - private $parent; - - /** - * @var FormConfigInterface - */ - private $config; - - /** - * @var bool - */ - private $submitted = false; - - /** - * Creates a new button from a form configuration. - */ - public function __construct(FormConfigInterface $config) - { - $this->config = $config; - } - - /** - * Unsupported method. - * - * @param string $offset - * - * @return bool - */ - #[\ReturnTypeWillChange] - public function offsetExists($offset) - { - return false; - } - - /** - * Unsupported method. - * - * This method should not be invoked. - * - * @param string $offset - * - * @return FormInterface - * - * @throws BadMethodCallException - */ - #[\ReturnTypeWillChange] - public function offsetGet($offset) - { - throw new BadMethodCallException('Buttons cannot have children.'); - } - - /** - * Unsupported method. - * - * This method should not be invoked. - * - * @param string $offset - * @param FormInterface $value - * - * @return void - * - * @throws BadMethodCallException - */ - #[\ReturnTypeWillChange] - public function offsetSet($offset, $value) - { - throw new BadMethodCallException('Buttons cannot have children.'); - } - - /** - * Unsupported method. - * - * This method should not be invoked. - * - * @param string $offset - * - * @return void - * - * @throws BadMethodCallException - */ - #[\ReturnTypeWillChange] - public function offsetUnset($offset) - { - throw new BadMethodCallException('Buttons cannot have children.'); - } - - /** - * {@inheritdoc} - */ - public function setParent(FormInterface $parent = null) - { - if ($this->submitted) { - throw new AlreadySubmittedException('You cannot set the parent of a submitted button.'); - } - - $this->parent = $parent; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - return $this->parent; - } - - /** - * Unsupported method. - * - * This method should not be invoked. - * - * @throws BadMethodCallException - */ - public function add($child, string $type = null, array $options = []) - { - throw new BadMethodCallException('Buttons cannot have children.'); - } - - /** - * Unsupported method. - * - * This method should not be invoked. - * - * @throws BadMethodCallException - */ - public function get(string $name) - { - throw new BadMethodCallException('Buttons cannot have children.'); - } - - /** - * Unsupported method. - * - * @return bool - */ - public function has(string $name) - { - return false; - } - - /** - * Unsupported method. - * - * This method should not be invoked. - * - * @throws BadMethodCallException - */ - public function remove(string $name) - { - throw new BadMethodCallException('Buttons cannot have children.'); - } - - /** - * {@inheritdoc} - */ - public function all() - { - return []; - } - - /** - * {@inheritdoc} - */ - public function getErrors(bool $deep = false, bool $flatten = true) - { - return new FormErrorIterator($this, []); - } - - /** - * Unsupported method. - * - * This method should not be invoked. - * - * @param mixed $modelData - * - * @return $this - */ - public function setData($modelData) - { - // no-op, called during initialization of the form tree - return $this; - } - - /** - * Unsupported method. - */ - public function getData() - { - return null; - } - - /** - * Unsupported method. - */ - public function getNormData() - { - return null; - } - - /** - * Unsupported method. - */ - public function getViewData() - { - return null; - } - - /** - * Unsupported method. - * - * @return array - */ - public function getExtraData() - { - return []; - } - - /** - * Returns the button's configuration. - * - * @return FormConfigInterface - */ - public function getConfig() - { - return $this->config; - } - - /** - * Returns whether the button is submitted. - * - * @return bool - */ - public function isSubmitted() - { - return $this->submitted; - } - - /** - * Returns the name by which the button is identified in forms. - * - * @return string - */ - public function getName() - { - return $this->config->getName(); - } - - /** - * Unsupported method. - */ - public function getPropertyPath() - { - return null; - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function addError(FormError $error) - { - throw new BadMethodCallException('Buttons cannot have errors.'); - } - - /** - * Unsupported method. - * - * @return bool - */ - public function isValid() - { - return true; - } - - /** - * Unsupported method. - * - * @return bool - */ - public function isRequired() - { - return false; - } - - /** - * {@inheritdoc} - */ - public function isDisabled() - { - if ($this->parent && $this->parent->isDisabled()) { - return true; - } - - return $this->config->getDisabled(); - } - - /** - * Unsupported method. - * - * @return bool - */ - public function isEmpty() - { - return true; - } - - /** - * Unsupported method. - * - * @return bool - */ - public function isSynchronized() - { - return true; - } - - /** - * Unsupported method. - */ - public function getTransformationFailure() - { - return null; - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function initialize() - { - throw new BadMethodCallException('Buttons cannot be initialized. Call initialize() on the root form instead.'); - } - - /** - * Unsupported method. - * - * @param mixed $request - * - * @throws BadMethodCallException - */ - public function handleRequest($request = null) - { - throw new BadMethodCallException('Buttons cannot handle requests. Call handleRequest() on the root form instead.'); - } - - /** - * Submits data to the button. - * - * @param array|string|null $submittedData Not used - * @param bool $clearMissing Not used - * - * @return $this - * - * @throws Exception\AlreadySubmittedException if the button has already been submitted - */ - public function submit($submittedData, bool $clearMissing = true) - { - if ($this->submitted) { - throw new AlreadySubmittedException('A form can only be submitted once.'); - } - - $this->submitted = true; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getRoot() - { - return $this->parent ? $this->parent->getRoot() : $this; - } - - /** - * {@inheritdoc} - */ - public function isRoot() - { - return null === $this->parent; - } - - /** - * {@inheritdoc} - */ - public function createView(FormView $parent = null) - { - if (null === $parent && $this->parent) { - $parent = $this->parent->createView(); - } - - $type = $this->config->getType(); - $options = $this->config->getOptions(); - - $view = $type->createView($this, $parent); - - $type->buildView($view, $this, $options); - $type->finishView($view, $this, $options); - - return $view; - } - - /** - * Unsupported method. - * - * @return int - */ - #[\ReturnTypeWillChange] - public function count() - { - return 0; - } - - /** - * Unsupported method. - * - * @return \EmptyIterator - */ - #[\ReturnTypeWillChange] - public function getIterator() - { - return new \EmptyIterator(); - } -} diff --git a/lib/symfony/form/ButtonBuilder.php b/lib/symfony/form/ButtonBuilder.php deleted file mode 100644 index c85bcc0d9..000000000 --- a/lib/symfony/form/ButtonBuilder.php +++ /dev/null @@ -1,744 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Form\Exception\BadMethodCallException; -use Symfony\Component\Form\Exception\InvalidArgumentException; - -/** - * A builder for {@link Button} instances. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @implements \IteratorAggregate<string, FormBuilderInterface> - */ -class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface -{ - protected $locked = false; - - /** - * @var bool - */ - private $disabled = false; - - /** - * @var ResolvedFormTypeInterface - */ - private $type; - - /** - * @var string - */ - private $name; - - /** - * @var array - */ - private $attributes = []; - - /** - * @var array - */ - private $options; - - /** - * @throws InvalidArgumentException if the name is empty - */ - public function __construct(?string $name, array $options = []) - { - if ('' === $name || null === $name) { - throw new InvalidArgumentException('Buttons cannot have empty names.'); - } - - $this->name = $name; - $this->options = $options; - - FormConfigBuilder::validateName($name); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function add($child, string $type = null, array $options = []) - { - throw new BadMethodCallException('Buttons cannot have children.'); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function create(string $name, string $type = null, array $options = []) - { - throw new BadMethodCallException('Buttons cannot have children.'); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function get(string $name) - { - throw new BadMethodCallException('Buttons cannot have children.'); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function remove(string $name) - { - throw new BadMethodCallException('Buttons cannot have children.'); - } - - /** - * Unsupported method. - * - * @return bool - */ - public function has(string $name) - { - return false; - } - - /** - * Returns the children. - * - * @return array - */ - public function all() - { - return []; - } - - /** - * Creates the button. - * - * @return Button - */ - public function getForm() - { - return new Button($this->getFormConfig()); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function addEventListener(string $eventName, callable $listener, int $priority = 0) - { - throw new BadMethodCallException('Buttons do not support event listeners.'); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function addEventSubscriber(EventSubscriberInterface $subscriber) - { - throw new BadMethodCallException('Buttons do not support event subscribers.'); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function addViewTransformer(DataTransformerInterface $viewTransformer, bool $forcePrepend = false) - { - throw new BadMethodCallException('Buttons do not support data transformers.'); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function resetViewTransformers() - { - throw new BadMethodCallException('Buttons do not support data transformers.'); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function addModelTransformer(DataTransformerInterface $modelTransformer, bool $forceAppend = false) - { - throw new BadMethodCallException('Buttons do not support data transformers.'); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function resetModelTransformers() - { - throw new BadMethodCallException('Buttons do not support data transformers.'); - } - - /** - * {@inheritdoc} - */ - public function setAttribute(string $name, $value) - { - $this->attributes[$name] = $value; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setAttributes(array $attributes) - { - $this->attributes = $attributes; - - return $this; - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function setDataMapper(DataMapperInterface $dataMapper = null) - { - throw new BadMethodCallException('Buttons do not support data mappers.'); - } - - /** - * Set whether the button is disabled. - * - * @return $this - */ - public function setDisabled(bool $disabled) - { - $this->disabled = $disabled; - - return $this; - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function setEmptyData($emptyData) - { - throw new BadMethodCallException('Buttons do not support empty data.'); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function setErrorBubbling(bool $errorBubbling) - { - throw new BadMethodCallException('Buttons do not support error bubbling.'); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function setRequired(bool $required) - { - throw new BadMethodCallException('Buttons cannot be required.'); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function setPropertyPath($propertyPath) - { - throw new BadMethodCallException('Buttons do not support property paths.'); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function setMapped(bool $mapped) - { - throw new BadMethodCallException('Buttons do not support data mapping.'); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function setByReference(bool $byReference) - { - throw new BadMethodCallException('Buttons do not support data mapping.'); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function setCompound(bool $compound) - { - throw new BadMethodCallException('Buttons cannot be compound.'); - } - - /** - * Sets the type of the button. - * - * @return $this - */ - public function setType(ResolvedFormTypeInterface $type) - { - $this->type = $type; - - return $this; - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function setData($data) - { - throw new BadMethodCallException('Buttons do not support data.'); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function setDataLocked(bool $locked) - { - throw new BadMethodCallException('Buttons do not support data locking.'); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function setFormFactory(FormFactoryInterface $formFactory) - { - throw new BadMethodCallException('Buttons do not support form factories.'); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function setAction(string $action) - { - throw new BadMethodCallException('Buttons do not support actions.'); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function setMethod(string $method) - { - throw new BadMethodCallException('Buttons do not support methods.'); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function setRequestHandler(RequestHandlerInterface $requestHandler) - { - throw new BadMethodCallException('Buttons do not support request handlers.'); - } - - /** - * Unsupported method. - * - * @return $this - * - * @throws BadMethodCallException - */ - public function setAutoInitialize(bool $initialize) - { - if (true === $initialize) { - throw new BadMethodCallException('Buttons do not support automatic initialization.'); - } - - return $this; - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function setInheritData(bool $inheritData) - { - throw new BadMethodCallException('Buttons do not support data inheritance.'); - } - - /** - * Builds and returns the button configuration. - * - * @return FormConfigInterface - */ - public function getFormConfig() - { - // This method should be idempotent, so clone the builder - $config = clone $this; - $config->locked = true; - - return $config; - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function setIsEmptyCallback(?callable $isEmptyCallback) - { - throw new BadMethodCallException('Buttons do not support "is empty" callback.'); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function getEventDispatcher() - { - throw new BadMethodCallException('Buttons do not support event dispatching.'); - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->name; - } - - /** - * Unsupported method. - */ - public function getPropertyPath() - { - return null; - } - - /** - * Unsupported method. - * - * @return bool - */ - public function getMapped() - { - return false; - } - - /** - * Unsupported method. - * - * @return bool - */ - public function getByReference() - { - return false; - } - - /** - * Unsupported method. - * - * @return bool - */ - public function getCompound() - { - return false; - } - - /** - * Returns the form type used to construct the button. - * - * @return ResolvedFormTypeInterface - */ - public function getType() - { - return $this->type; - } - - /** - * Unsupported method. - * - * @return array - */ - public function getViewTransformers() - { - return []; - } - - /** - * Unsupported method. - * - * @return array - */ - public function getModelTransformers() - { - return []; - } - - /** - * Unsupported method. - */ - public function getDataMapper() - { - return null; - } - - /** - * Unsupported method. - * - * @return bool - */ - public function getRequired() - { - return false; - } - - /** - * Returns whether the button is disabled. - * - * @return bool - */ - public function getDisabled() - { - return $this->disabled; - } - - /** - * Unsupported method. - * - * @return bool - */ - public function getErrorBubbling() - { - return false; - } - - /** - * Unsupported method. - */ - public function getEmptyData() - { - return null; - } - - /** - * Returns additional attributes of the button. - * - * @return array - */ - public function getAttributes() - { - return $this->attributes; - } - - /** - * Returns whether the attribute with the given name exists. - * - * @return bool - */ - public function hasAttribute(string $name) - { - return \array_key_exists($name, $this->attributes); - } - - /** - * Returns the value of the given attribute. - * - * @param mixed $default The value returned if the attribute does not exist - * - * @return mixed - */ - public function getAttribute(string $name, $default = null) - { - return \array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; - } - - /** - * Unsupported method. - */ - public function getData() - { - return null; - } - - /** - * Unsupported method. - */ - public function getDataClass() - { - return null; - } - - /** - * Unsupported method. - * - * @return bool - */ - public function getDataLocked() - { - return false; - } - - /** - * Unsupported method. - */ - public function getFormFactory() - { - throw new BadMethodCallException('Buttons do not support adding children.'); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function getAction() - { - throw new BadMethodCallException('Buttons do not support actions.'); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function getMethod() - { - throw new BadMethodCallException('Buttons do not support methods.'); - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function getRequestHandler() - { - throw new BadMethodCallException('Buttons do not support request handlers.'); - } - - /** - * Unsupported method. - * - * @return bool - */ - public function getAutoInitialize() - { - return false; - } - - /** - * Unsupported method. - * - * @return bool - */ - public function getInheritData() - { - return false; - } - - /** - * Returns all options passed during the construction of the button. - * - * @return array - */ - public function getOptions() - { - return $this->options; - } - - /** - * Returns whether a specific option exists. - * - * @return bool - */ - public function hasOption(string $name) - { - return \array_key_exists($name, $this->options); - } - - /** - * Returns the value of a specific option. - * - * @param mixed $default The value returned if the option does not exist - * - * @return mixed - */ - public function getOption(string $name, $default = null) - { - return \array_key_exists($name, $this->options) ? $this->options[$name] : $default; - } - - /** - * Unsupported method. - * - * @throws BadMethodCallException - */ - public function getIsEmptyCallback(): ?callable - { - throw new BadMethodCallException('Buttons do not support "is empty" callback.'); - } - - /** - * Unsupported method. - * - * @return int - */ - #[\ReturnTypeWillChange] - public function count() - { - return 0; - } - - /** - * Unsupported method. - * - * @return \EmptyIterator - */ - #[\ReturnTypeWillChange] - public function getIterator() - { - return new \EmptyIterator(); - } -} diff --git a/lib/symfony/form/ButtonTypeInterface.php b/lib/symfony/form/ButtonTypeInterface.php deleted file mode 100644 index dd5117c4d..000000000 --- a/lib/symfony/form/ButtonTypeInterface.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -/** - * A type that should be converted into a {@link Button} instance. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface ButtonTypeInterface extends FormTypeInterface -{ -} diff --git a/lib/symfony/form/CHANGELOG.md b/lib/symfony/form/CHANGELOG.md deleted file mode 100644 index 9d7e76445..000000000 --- a/lib/symfony/form/CHANGELOG.md +++ /dev/null @@ -1,567 +0,0 @@ -CHANGELOG -========= - -5.4 ---- - - * Deprecate calling `FormErrorIterator::children()` if the current element is not iterable. - * Allow to pass `TranslatableMessage` objects to the `help` option - * Add the `EnumType` - -5.3 ---- - - * Changed `$forms` parameter type of the `DataMapperInterface::mapDataToForms()` method from `iterable` to `\Traversable`. - * Changed `$forms` parameter type of the `DataMapperInterface::mapFormsToData()` method from `iterable` to `\Traversable`. - * Deprecated passing an array as the second argument of the `DataMapper::mapDataToForms()` method, pass `\Traversable` instead. - * Deprecated passing an array as the first argument of the `DataMapper::mapFormsToData()` method, pass `\Traversable` instead. - * Deprecated passing an array as the second argument of the `CheckboxListMapper::mapDataToForms()` method, pass `\Traversable` instead. - * Deprecated passing an array as the first argument of the `CheckboxListMapper::mapFormsToData()` method, pass `\Traversable` instead. - * Deprecated passing an array as the second argument of the `RadioListMapper::mapDataToForms()` method, pass `\Traversable` instead. - * Deprecated passing an array as the first argument of the `RadioListMapper::mapFormsToData()` method, pass `\Traversable` instead. - * Added a `choice_translation_parameters` option to `ChoiceType` - * Add `UuidType` and `UlidType` - * Dependency on `symfony/intl` was removed. Install `symfony/intl` if you are using `LocaleType`, `CountryType`, `CurrencyType`, `LanguageType` or `TimezoneType`. - * Add `priority` option to `BaseType` and sorting view fields - -5.2.0 ------ - - * Added support for using the `{{ label }}` placeholder in constraint messages, which is replaced in the `ViolationMapper` by the corresponding field form label. - * Added `DataMapper`, `ChainAccessor`, `PropertyPathAccessor` and `CallbackAccessor` with new callable `getter` and `setter` options for each form type - * Deprecated `PropertyPathMapper` in favor of `DataMapper` and `PropertyPathAccessor` - * Added an `html5` option to `MoneyType` and `PercentType`, to use `<input type="number" />` - -5.1.0 ------ - - * Deprecated not configuring the `rounding_mode` option of the `PercentType`. It will default to `\NumberFormatter::ROUND_HALFUP` in Symfony 6. - * Deprecated not passing a rounding mode to the constructor of `PercentToLocalizedStringTransformer`. It will default to `\NumberFormatter::ROUND_HALFUP` in Symfony 6. - * Added `collection_entry` block prefix to `CollectionType` entries - * Added a `choice_filter` option to `ChoiceType` - * Added argument `callable|null $filter` to `ChoiceListFactoryInterface::createListFromChoices()` and `createListFromLoader()` - not defining them is deprecated. - * Added a `ChoiceList` facade to leverage explicit choice list caching based on options - * Added an `AbstractChoiceLoader` to simplify implementations and handle global optimizations - * The `view_timezone` option defaults to the `model_timezone` if no `reference_date` is configured. - * Implementing the `FormConfigInterface` without implementing the `getIsEmptyCallback()` method - is deprecated. The method will be added to the interface in 6.0. - * Implementing the `FormConfigBuilderInterface` without implementing the `setIsEmptyCallback()` method - is deprecated. The method will be added to the interface in 6.0. - * Added a `rounding_mode` option for the PercentType and correctly round the value when submitted - * Deprecated `Symfony\Component\Form\Extension\Validator\Util\ServerParams` in favor of its parent class `Symfony\Component\Form\Util\ServerParams` - * Added the `html5` option to the `ColorType` to validate the input - * Deprecated `NumberToLocalizedStringTransformer::ROUND_*` constants, use `\NumberFormatter::ROUND_*` instead - -5.0.0 ------ - - * Removed support for using different values for the "model_timezone" and "view_timezone" options of the `TimeType` - without configuring a reference date. - * Removed the `scale` option of the `IntegerType`. - * Using the `date_format`, `date_widget`, and `time_widget` options of the `DateTimeType` when the `widget` option is - set to `single_text` is not supported anymore. - * The `format` option of `DateType` and `DateTimeType` cannot be used when the `html5` option is enabled. - * Using names for buttons that do not start with a letter, a digit, or an underscore throw an exception - * Using names for buttons that do not contain only letters, digits, underscores, hyphens, and colons throw an exception. - * removed the `ChoiceLoaderInterface` implementation in `CountryType`, `LanguageType`, `LocaleType` and `CurrencyType` - * removed `getExtendedType()` method of the `FormTypeExtensionInterface` - * added static `getExtendedTypes()` method to the `FormTypeExtensionInterface` - * calling to `FormRenderer::searchAndRenderBlock()` method for fields which were already rendered throw a `BadMethodCallException` - * removed the `regions` option of the `TimezoneType` - * removed the `$scale` argument of the `IntegerToLocalizedStringTransformer` - * removed `TemplatingExtension` and `TemplatingRendererEngine` classes, use Twig instead - * passing a null message when instantiating a `Symfony\Component\Form\FormError` is not allowed - * removed support for using `int` or `float` as data for the `NumberType` when the `input` option is set to `string` - -4.4.0 ------ - - * add new `WeekType` - * using different values for the "model_timezone" and "view_timezone" options of the `TimeType` without configuring a - reference date is deprecated - * preferred choices are repeated in the list of all choices - * deprecated using `int` or `float` as data for the `NumberType` when the `input` option is set to `string` - * The type guesser guesses the HTML accept attribute when a mime type is configured in the File or Image constraint. - * Overriding the methods `FormIntegrationTestCase::setUp()`, `TypeTestCase::setUp()` and `TypeTestCase::tearDown()` without the `void` return-type is deprecated. - * marked all dispatched event classes as `@final` - * Added the `validate` option to `SubmitType` to toggle the browser built-in form validation. - * Added the `alpha3` option to `LanguageType` and `CountryType` to use alpha3 instead of alpha2 codes - -4.3.0 ------ - - * added a `symbol` option to the `PercentType` that allows to disable or customize the output of the percent character - * Using the `format` option of `DateType` and `DateTimeType` when the `html5` option is enabled is deprecated. - * Using names for buttons that do not start with a letter, a digit, or an underscore is deprecated and will lead to an - exception in 5.0. - * Using names for buttons that do not contain only letters, digits, underscores, hyphens, and colons is deprecated and - will lead to an exception in 5.0. - * added `html5` option to `NumberType` that allows to render `type="number"` input fields - * deprecated using the `date_format`, `date_widget`, and `time_widget` options of the `DateTimeType` when the `widget` - option is set to `single_text` - * added `block_prefix` option to `BaseType`. - * added `help_html` option to display the `help` text as HTML. - * `FormError` doesn't implement `Serializable` anymore - * `FormDataCollector` has been marked as `final` - * added `label_translation_parameters`, `attr_translation_parameters`, `help_translation_parameters` options - to `FormType` to pass translation parameters to form labels, attributes (`placeholder` and `title`) and help text respectively. - The passed parameters will replace placeholders in translation messages. - - ```php - class OrderType extends AbstractType - { - public function buildForm(FormBuilderInterface $builder, array $options) - { - $builder->add('comment', TextType::class, [ - 'label' => 'Comment to the order to %company%', - 'label_translation_parameters' => [ - '%company%' => 'Acme', - ], - 'help' => 'The address of the %company% is %address%', - 'help_translation_parameters' => [ - '%company%' => 'Acme Ltd.', - '%address%' => '4 Form street, Symfonyville', - ], - ]) - } - } - ``` - * added the `input_format` option to `DateType`, `DateTimeType`, and `TimeType` to specify the input format when setting - the `input` option to `string` - * dispatch `PreSubmitEvent` on `form.pre_submit` - * dispatch `SubmitEvent` on `form.submit` - * dispatch `PostSubmitEvent` on `form.post_submit` - * dispatch `PreSetDataEvent` on `form.pre_set_data` - * dispatch `PostSetDataEvent` on `form.post_set_data` - * added an `input` option to `NumberType` - * removed default option grouping in `TimezoneType`, use `group_by` instead - -4.2.0 ------ - - * The `getExtendedType()` method of the `FormTypeExtensionInterface` is deprecated and will be removed in 5.0. Type - extensions must implement the static `getExtendedTypes()` method instead and return an iterable of extended types. - - Before: - - ```php - class FooTypeExtension extends AbstractTypeExtension - { - public function getExtendedType() - { - return FormType::class; - } - - // ... - } - ``` - - After: - - ```php - class FooTypeExtension extends AbstractTypeExtension - { - public static function getExtendedTypes(): iterable - { - return [FormType::class]; - } - - // ... - } - ``` - * deprecated the `$scale` argument of the `IntegerToLocalizedStringTransformer` - * added `Symfony\Component\Form\ClearableErrorsInterface` - * deprecated calling `FormRenderer::searchAndRenderBlock` for fields which were already rendered - * added a cause when a CSRF error has occurred - * deprecated the `scale` option of the `IntegerType` - * removed restriction on allowed HTTP methods - * deprecated the `regions` option of the `TimezoneType` - -4.1.0 ------ - - * added `input=datetime_immutable` to `DateType`, `TimeType`, `DateTimeType` - * added `rounding_mode` option to `MoneyType` - * added `choice_translation_locale` option to `CountryType`, `LanguageType`, `LocaleType` and `CurrencyType` - * deprecated the `ChoiceLoaderInterface` implementation in `CountryType`, `LanguageType`, `LocaleType` and `CurrencyType` - * added `input=datetime_immutable` to DateType, TimeType, DateTimeType - * added `rounding_mode` option to MoneyType - -4.0.0 ------ - - * using the `choices` option in `CountryType`, `CurrencyType`, `LanguageType`, - `LocaleType`, and `TimezoneType` when the `choice_loader` option is not `null` - is not supported anymore and the configured choices will be ignored - * callable strings that are passed to the options of the `ChoiceType` are - treated as property paths - * the `choices_as_values` option of the `ChoiceType` has been removed - * removed the support for caching loaded choice lists in `LazyChoiceList`, - cache the choice list in the used `ChoiceLoaderInterface` implementation - instead - * removed the support for objects implementing both `\Traversable` and `\ArrayAccess` in `ResizeFormListener::preSubmit()` - * removed the ability to use `FormDataCollector` without the `symfony/var-dumper` component - * removed passing a `ValueExporter` instance to the `FormDataExtractor::__construct()` method - * removed passing guesser services ids as the fourth argument of `DependencyInjectionExtension::__construct()` - * removed the ability to validate an unsubmitted form. - * removed `ChoiceLoaderInterface` implementation in `TimezoneType` - * added the `false_values` option to the `CheckboxType` which allows to configure custom values which will be treated as `false` during submission - -3.4.0 ------ - - * added `DebugCommand` - * deprecated `ChoiceLoaderInterface` implementation in `TimezoneType` - * added options "input" and "regions" to `TimezoneType` - * added an option to ``Symfony\Component\Form\FormRendererEngineInterface::setTheme()`` and - ``Symfony\Component\Form\FormRendererInterface::setTheme()`` to disable usage of default themes when rendering a form - -3.3.0 ------ - - * deprecated using "choices" option in ``CountryType``, ``CurrencyType``, ``LanguageType``, ``LocaleType``, and - ``TimezoneType`` when "choice_loader" is not ``null`` - * added `Symfony\Component\Form\FormErrorIterator::findByCodes()` - * added `getTypedExtensions`, `getTypes`, and `getTypeGuessers` to `Symfony\Component\Form\Test\FormIntegrationTestCase` - * added `FormPass` - -3.2.0 ------ - - * added `CallbackChoiceLoader` - * implemented `ChoiceLoaderInterface` in children of `ChoiceType` - -3.1.0 ------ - - * deprecated the "choices_as_values" option of ChoiceType - * deprecated support for data objects that implements both `Traversable` and - `ArrayAccess` in `ResizeFormListener::preSubmit` method - * Using callable strings as choice options in `ChoiceType` has been deprecated - and will be used as `PropertyPath` instead of callable in Symfony 4.0. - * implemented `DataTransformerInterface` in `TextType` - * deprecated caching loaded choice list in `LazyChoiceList::$loadedList` - -3.0.0 ------ - - * removed `FormTypeInterface::setDefaultOptions()` method - * removed `AbstractType::setDefaultOptions()` method - * removed `FormTypeExtensionInterface::setDefaultOptions()` method - * removed `AbstractTypeExtension::setDefaultOptions()` method - * added `FormTypeInterface::configureOptions()` method - * added `FormTypeExtensionInterface::configureOptions()` method - -2.8.0 ------ - - * added option "choice_translation_domain" to DateType, TimeType and DateTimeType. - * deprecated option "read_only" in favor of "attr['readonly']" - * added the html5 "range" FormType - * deprecated the "cascade_validation" option in favor of setting "constraints" - with the Valid constraint - * moved data trimming logic of TrimListener into StringUtil - * [BC BREAK] When registering a type extension through the DI extension, the tag alias has to match the actual extended type. - -2.7.38 ------- - - * [BC BREAK] the `isFileUpload()` method was added to the `RequestHandlerInterface` - -2.7.0 ------ - - * added option "choice_translation_domain" to ChoiceType. - * deprecated option "precision" in favor of "scale" - * deprecated the overwriting of AbstractType::setDefaultOptions() in favor of overwriting AbstractType::configureOptions(). - * deprecated the overwriting of AbstractTypeExtension::setDefaultOptions() in favor of overwriting AbstractTypeExtension::configureOptions(). - * added new ChoiceList interface and implementations in the Symfony\Component\Form\ChoiceList namespace - * added new ChoiceView in the Symfony\Component\Form\ChoiceList\View namespace - * choice groups are now represented by ChoiceGroupView objects in the view - * deprecated the old ChoiceList interface and implementations - * deprecated the old ChoiceView class - * added CheckboxListMapper and RadioListMapper - * deprecated ChoiceToBooleanArrayTransformer and ChoicesToBooleanArrayTransformer - * deprecated FixCheckboxInputListener and FixRadioInputListener - * deprecated the "choice_list" option of ChoiceType - * added new options to ChoiceType: - * "choices_as_values" - * "choice_loader" - * "choice_label" - * "choice_name" - * "choice_value" - * "choice_attr" - * "group_by" - -2.6.2 ------ - - * Added back the `model_timezone` and `view_timezone` options for `TimeType`, `DateType` - and `BirthdayType` - -2.6.0 ------ - - * added "html5" option to Date, Time and DateTimeFormType to be able to - enable/disable HTML5 input date when widget option is "single_text" - * added "label_format" option with possible placeholders "%name%" and "%id%" - * [BC BREAK] drop support for model_timezone and view_timezone options in TimeType, DateType and BirthdayType, - update to 2.6.2 to get back support for these options - -2.5.0 ------- - - * deprecated options "max_length" and "pattern" in favor of putting these values in "attr" option - * added an option for multiple files upload - * form errors now reference their cause (constraint violation, exception, ...) - * form errors now remember which form they were originally added to - * [BC BREAK] added two optional parameters to FormInterface::getErrors() and - changed the method to return a Symfony\Component\Form\FormErrorIterator - instance instead of an array - * errors mapped to unsubmitted forms are discarded now - * ObjectChoiceList now compares choices by their value, if a value path is - given - * you can now pass interface names in the "data_class" option - * [BC BREAK] added `FormInterface::getTransformationFailure()` - -2.4.0 ------ - - * moved CSRF implementation to the new Security CSRF sub-component - * deprecated CsrfProviderInterface and its implementations - * deprecated options "csrf_provider" and "intention" in favor of the new options "csrf_token_manager" and "csrf_token_id" - -2.3.0 ------ - - * deprecated FormPerformanceTestCase and FormIntegrationTestCase in the Symfony\Component\Form\Tests namespace and moved them to the Symfony\Component\Form\Test namespace - * deprecated TypeTestCase in the Symfony\Component\Form\Tests\Extension\Core\Type namespace and moved it to the Symfony\Component\Form\Test namespace - * changed FormRenderer::humanize() to humanize also camel cased field name - * added RequestHandlerInterface and FormInterface::handleRequest() - * deprecated passing a Request instance to FormInterface::bind() - * added options "method" and "action" to FormType - * deprecated option "virtual" in favor "inherit_data" - * deprecated VirtualFormAwareIterator in favor of InheritDataAwareIterator - * [BC BREAK] removed the "array" type hint from DataMapperInterface - * improved forms inheriting their parent data to actually return that data from getData(), getNormData() and getViewData() - * added component-level exceptions for various SPL exceptions - changed all uses of the deprecated Exception class to use more specialized exceptions instead - removed NotInitializedException, NotValidException, TypeDefinitionException, TypeLoaderException, CreationException - * added events PRE_SUBMIT, SUBMIT and POST_SUBMIT - * deprecated events PRE_BIND, BIND and POST_BIND - * [BC BREAK] renamed bind() and isBound() in FormInterface to submit() and isSubmitted() - * added methods submit() and isSubmitted() to Form - * deprecated bind() and isBound() in Form - * deprecated AlreadyBoundException in favor of AlreadySubmittedException - * added support for PATCH requests - * [BC BREAK] added initialize() to FormInterface - * [BC BREAK] added getAutoInitialize() to FormConfigInterface - * [BC BREAK] added setAutoInitialize() to FormConfigBuilderInterface - * [BC BREAK] initialization for Form instances added to a form tree must be manually disabled - * PRE_SET_DATA is now guaranteed to be called after children were added by the form builder, - unless FormInterface::setData() is called manually - * fixed CSRF error message to be translated - * custom CSRF error messages can now be set through the "csrf_message" option - * fixed: expanded single-choice fields now show a radio button for the empty value - -2.2.0 ------ - - * TrimListener now removes unicode whitespaces - * deprecated getParent(), setParent() and hasParent() in FormBuilderInterface - * FormInterface::add() now accepts a FormInterface instance OR a field's name, type and options - * removed special characters between the choice or text fields of DateType unless - the option "format" is set to a custom value - * deprecated FormException and introduced ExceptionInterface instead - * [BC BREAK] FormException is now an interface - * protected FormBuilder methods from being called when it is turned into a FormConfigInterface with getFormConfig() - * [BC BREAK] inserted argument `$message` in the constructor of `FormError` - * the PropertyPath class and related classes were moved to a dedicated - PropertyAccess component. During the move, InvalidPropertyException was - renamed to NoSuchPropertyException. FormUtil was split: FormUtil::singularify() - can now be found in Symfony\Component\PropertyAccess\StringUtil. The methods - getValue() and setValue() from PropertyPath were extracted into a new class - PropertyAccessor. - * added an optional PropertyAccessorInterface parameter to FormType, - ObjectChoiceList and PropertyPathMapper - * [BC BREAK] PropertyPathMapper and FormType now have a constructor - * [BC BREAK] setting the option "validation_groups" to ``false`` now disables validation - instead of assuming group "Default" - -2.1.0 ------ - - * [BC BREAK] ``read_only`` field attribute now renders as ``readonly="readonly"``, use ``disabled`` instead - * [BC BREAK] child forms now aren't validated anymore by default - * made validation of form children configurable (new option: cascade_validation) - * added support for validation groups as callbacks - * made the translation catalogue configurable via the "translation_domain" option - * added Form::getErrorsAsString() to help debugging forms - * allowed setting different options for RepeatedType fields (like the label) - * added support for empty form name at root level, this enables rendering forms - without form name prefix in field names - * [BC BREAK] form and field names must start with a letter, digit or underscore - and only contain letters, digits, underscores, hyphens and colons - * [BC BREAK] changed default name of the prototype in the "collection" type - from "$$name$$" to "\__name\__". No dollars are appended/prepended to custom - names anymore. - * [BC BREAK] improved ChoiceListInterface - * [BC BREAK] added SimpleChoiceList and LazyChoiceList as replacement of - ArrayChoiceList - * added ChoiceList and ObjectChoiceList to use objects as choices - * [BC BREAK] removed EntitiesToArrayTransformer and EntityToIdTransformer. - The former has been replaced by CollectionToArrayTransformer in combination - with EntityChoiceList, the latter is not required in the core anymore. - * [BC BREAK] renamed - * ArrayToBooleanChoicesTransformer to ChoicesToBooleanArrayTransformer - * ScalarToBooleanChoicesTransformer to ChoiceToBooleanArrayTransformer - * ArrayToChoicesTransformer to ChoicesToValuesTransformer - * ScalarToChoiceTransformer to ChoiceToValueTransformer - to be consistent with the naming in ChoiceListInterface. - They were merged into ChoiceList and have no public equivalent anymore. - * choice fields now throw a FormException if neither the "choices" nor the - "choice_list" option is set - * the radio type is now a child of the checkbox type - * the collection, choice (with multiple selection) and entity (with multiple - selection) types now make use of addXxx() and removeXxx() methods in your - model if you set "by_reference" to false. For a custom, non-recognized - singular form, set the "property_path" option like this: "plural|singular" - * forms now don't create an empty object anymore if they are completely - empty and not required. The empty value for such forms is null. - * added constant Guess::VERY_HIGH_CONFIDENCE - * [BC BREAK] The methods `add`, `remove`, `setParent`, `bind` and `setData` - in class Form now throw an exception if the form is already bound - * fields of constrained classes without a NotBlank or NotNull constraint are - set to not required now, as stated in the docs - * fixed TimeType and DateTimeType to not display seconds when "widget" is - "single_text" unless "with_seconds" is set to true - * checkboxes of in an expanded multiple-choice field don't include the choice - in their name anymore. Their names terminate with "[]" now. - * deprecated FormValidatorInterface and substituted its implementations - by event subscribers - * simplified CSRF protection and removed the csrf type - * deprecated FieldType and merged it into FormType - * added new option "compound" that lets you switch between field and form behavior - * [BC BREAK] renamed theme blocks - * "field_*" to "form_*" - * "field_widget" to "form_widget_simple" - * "widget_choice_options" to "choice_widget_options" - * "generic_label" to "form_label" - * added theme blocks "form_widget_compound", "choice_widget_expanded" and - "choice_widget_collapsed" to make theming more modular - * ValidatorTypeGuesser now guesses "collection" for array type constraint - * added method `guessPattern` to FormTypeGuesserInterface to guess which pattern to use in the HTML5 attribute "pattern" - * deprecated method `guessMinLength` in favor of `guessPattern` - * labels don't display field attributes anymore. Label attributes can be - passed in the "label_attr" option/variable - * added option "mapped" which should be used instead of setting "property_path" to false - * [BC BREAK] "data_class" now *must* be set if a form maps to an object and should be left empty otherwise - * improved error mapping on forms - * dot (".") rules are now allowed to map errors assigned to a form to - one of its children - * errors are not mapped to unsynchronized forms anymore - * [BC BREAK] changed Form constructor to accept a single `FormConfigInterface` object - * [BC BREAK] changed argument order in the FormBuilder constructor - * added Form method `getViewData` - * deprecated Form methods - * `getTypes` - * `getErrorBubbling` - * `getNormTransformers` - * `getClientTransformers` - * `getAttribute` - * `hasAttribute` - * `getClientData` - * added FormBuilder methods - * `getTypes` - * `addViewTransformer` - * `getViewTransformers` - * `resetViewTransformers` - * `addModelTransformer` - * `getModelTransformers` - * `resetModelTransformers` - * deprecated FormBuilder methods - * `prependClientTransformer` - * `appendClientTransformer` - * `getClientTransformers` - * `resetClientTransformers` - * `prependNormTransformer` - * `appendNormTransformer` - * `getNormTransformers` - * `resetNormTransformers` - * deprecated the option "validation_constraint" in favor of the new - option "constraints" - * removed superfluous methods from DataMapperInterface - * `mapFormToData` - * `mapDataToForm` - * added `setDefaultOptions` to FormTypeInterface and FormTypeExtensionInterface - which accepts an OptionsResolverInterface instance - * deprecated the methods `getDefaultOptions` and `getAllowedOptionValues` - in FormTypeInterface and FormTypeExtensionInterface - * options passed during construction can now be accessed from FormConfigInterface - * added FormBuilderInterface and FormConfigEditorInterface - * [BC BREAK] the method `buildForm` in FormTypeInterface and FormTypeExtensionInterface - now receives a FormBuilderInterface instead of a FormBuilder instance - * [BC BREAK] the method `buildViewBottomUp` was renamed to `finishView` in - FormTypeInterface and FormTypeExtensionInterface - * [BC BREAK] the options array is now passed as last argument of the - methods - * `buildView` - * `finishView` - in FormTypeInterface and FormTypeExtensionInterface - * [BC BREAK] no options are passed to `getParent` of FormTypeInterface anymore - * deprecated DataEvent and FilterDataEvent in favor of the new FormEvent which is - now passed to all events thrown by the component - * FormEvents::BIND now replaces FormEvents::BIND_NORM_DATA - * FormEvents::PRE_SET_DATA now replaces FormEvents::SET_DATA - * FormEvents::PRE_BIND now replaces FormEvents::BIND_CLIENT_DATA - * deprecated FormEvents::SET_DATA, FormEvents::BIND_CLIENT_DATA and - FormEvents::BIND_NORM_DATA - * [BC BREAK] reversed the order of the first two arguments to `createNamed` - and `createNamedBuilder` in `FormFactoryInterface` - * deprecated `getChildren` in Form and FormBuilder in favor of `all` - * deprecated `hasChildren` in Form and FormBuilder in favor of `count` - * FormBuilder now implements \IteratorAggregate - * [BC BREAK] compound forms now always need a data mapper - * FormBuilder now maintains the order when explicitly adding form builders as children - * ChoiceType now doesn't add the empty value anymore if the choices already contain an empty element - * DateType, TimeType and DateTimeType now show empty values again if not required - * [BC BREAK] fixed rendering of errors for DateType, BirthdayType and similar ones - * [BC BREAK] fixed: form constraints are only validated if they belong to the validated group - * deprecated `bindRequest` in `Form` and replaced it by a listener to FormEvents::PRE_BIND - * fixed: the "data" option supersedes default values from the model - * changed DateType to refer to the "format" option for calculating the year and day choices instead - of padding them automatically - * [BC BREAK] DateType defaults to the format "yyyy-MM-dd" now if the widget is - "single_text", in order to support the HTML 5 date field out of the box - * added the option "format" to DateTimeType - * [BC BREAK] DateTimeType now outputs RFC 3339 dates by default, as generated and - consumed by HTML5 browsers, if the widget is "single_text" - * deprecated the options "data_timezone" and "user_timezone" in DateType, DateTimeType and TimeType - and renamed them to "model_timezone" and "view_timezone" - * fixed: TransformationFailedExceptions thrown in the model transformer are now caught by the form - * added FormRegistryInterface, ResolvedFormTypeInterface and ResolvedFormTypeFactoryInterface - * deprecated FormFactory methods - * `addType` - * `hasType` - * `getType` - * [BC BREAK] FormFactory now expects a FormRegistryInterface and a ResolvedFormTypeFactoryInterface as constructor argument - * [BC BREAK] The method `createBuilder` in FormTypeInterface is not supported anymore for performance reasons - * [BC BREAK] Removed `setTypes` from FormBuilder - * deprecated AbstractType methods - * `getExtensions` - * `setExtensions` - * ChoiceType now caches its created choice lists to improve performance - * [BC BREAK] Rows of a collection field cannot be themed individually anymore. All rows in the collection - field now have the same block names, which contains "entry" where it previously contained the row index. - * [BC BREAK] When registering a type through the DI extension, the tag alias has to match the actual type name. - * added FormRendererInterface, FormRendererEngineInterface and implementations of these interfaces - * [BC BREAK] removed the following methods from FormUtil: - * `toArrayKey` - * `toArrayKeys` - * `isChoiceGroup` - * `isChoiceSelected` - * [BC BREAK] renamed method `renderBlock` in FormHelper to `block` and changed its signature - * made FormView properties public and deprecated their accessor methods - * made the normalized data of a form accessible in the template through the variable "form.vars.data" - * made the original data of a choice accessible in the template through the property "choice.data" - * added convenience class Forms and FormFactoryBuilderInterface diff --git a/lib/symfony/form/CallbackTransformer.php b/lib/symfony/form/CallbackTransformer.php deleted file mode 100644 index 5125214ff..000000000 --- a/lib/symfony/form/CallbackTransformer.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -class CallbackTransformer implements DataTransformerInterface -{ - private $transform; - private $reverseTransform; - - /** - * @param callable $transform The forward transform callback - * @param callable $reverseTransform The reverse transform callback - */ - public function __construct(callable $transform, callable $reverseTransform) - { - $this->transform = $transform; - $this->reverseTransform = $reverseTransform; - } - - /** - * {@inheritdoc} - */ - public function transform($data) - { - return ($this->transform)($data); - } - - /** - * {@inheritdoc} - */ - public function reverseTransform($data) - { - return ($this->reverseTransform)($data); - } -} diff --git a/lib/symfony/form/ChoiceList/ArrayChoiceList.php b/lib/symfony/form/ChoiceList/ArrayChoiceList.php deleted file mode 100644 index e5056d897..000000000 --- a/lib/symfony/form/ChoiceList/ArrayChoiceList.php +++ /dev/null @@ -1,238 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList; - -/** - * A list of choices with arbitrary data types. - * - * The user of this class is responsible for assigning string values to the - * choices and for their uniqueness. - * Both the choices and their values are passed to the constructor. - * Each choice must have a corresponding value (with the same key) in - * the values array. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class ArrayChoiceList implements ChoiceListInterface -{ - /** - * The choices in the list. - * - * @var array - */ - protected $choices; - - /** - * The values indexed by the original keys. - * - * @var array - */ - protected $structuredValues; - - /** - * The original keys of the choices array. - * - * @var int[]|string[] - */ - protected $originalKeys; - protected $valueCallback; - - /** - * Creates a list with the given choices and values. - * - * The given choice array must have the same array keys as the value array. - * - * @param iterable $choices The selectable choices - * @param callable|null $value The callable for creating the value - * for a choice. If `null` is passed, - * incrementing integers are used as - * values - */ - public function __construct(iterable $choices, callable $value = null) - { - if ($choices instanceof \Traversable) { - $choices = iterator_to_array($choices); - } - - if (null === $value && $this->castableToString($choices)) { - $value = function ($choice) { - return false === $choice ? '0' : (string) $choice; - }; - } - - if (null !== $value) { - // If a deterministic value generator was passed, use it later - $this->valueCallback = $value; - } else { - // Otherwise generate incrementing integers as values - $i = 0; - $value = function () use (&$i) { - return $i++; - }; - } - - // If the choices are given as recursive array (i.e. with explicit - // choice groups), flatten the array. The grouping information is needed - // in the view only. - $this->flatten($choices, $value, $choicesByValues, $keysByValues, $structuredValues); - - $this->choices = $choicesByValues; - $this->originalKeys = $keysByValues; - $this->structuredValues = $structuredValues; - } - - /** - * {@inheritdoc} - */ - public function getChoices() - { - return $this->choices; - } - - /** - * {@inheritdoc} - */ - public function getValues() - { - return array_map('strval', array_keys($this->choices)); - } - - /** - * {@inheritdoc} - */ - public function getStructuredValues() - { - return $this->structuredValues; - } - - /** - * {@inheritdoc} - */ - public function getOriginalKeys() - { - return $this->originalKeys; - } - - /** - * {@inheritdoc} - */ - public function getChoicesForValues(array $values) - { - $choices = []; - - foreach ($values as $i => $givenValue) { - if (\array_key_exists($givenValue, $this->choices)) { - $choices[$i] = $this->choices[$givenValue]; - } - } - - return $choices; - } - - /** - * {@inheritdoc} - */ - public function getValuesForChoices(array $choices) - { - $values = []; - - // Use the value callback to compare choices by their values, if present - if ($this->valueCallback) { - $givenValues = []; - - foreach ($choices as $i => $givenChoice) { - $givenValues[$i] = (string) ($this->valueCallback)($givenChoice); - } - - return array_intersect($givenValues, array_keys($this->choices)); - } - - // Otherwise compare choices by identity - foreach ($choices as $i => $givenChoice) { - foreach ($this->choices as $value => $choice) { - if ($choice === $givenChoice) { - $values[$i] = (string) $value; - break; - } - } - } - - return $values; - } - - /** - * Flattens an array into the given output variables. - * - * @param array $choices The array to flatten - * @param callable $value The callable for generating choice values - * @param array|null $choicesByValues The flattened choices indexed by the - * corresponding values - * @param array|null $keysByValues The original keys indexed by the - * corresponding values - * @param array|null $structuredValues The values indexed by the original keys - * - * @internal - */ - protected function flatten(array $choices, callable $value, ?array &$choicesByValues, ?array &$keysByValues, ?array &$structuredValues) - { - if (null === $choicesByValues) { - $choicesByValues = []; - $keysByValues = []; - $structuredValues = []; - } - - foreach ($choices as $key => $choice) { - if (\is_array($choice)) { - $this->flatten($choice, $value, $choicesByValues, $keysByValues, $structuredValues[$key]); - - continue; - } - - $choiceValue = (string) $value($choice); - $choicesByValues[$choiceValue] = $choice; - $keysByValues[$choiceValue] = $key; - $structuredValues[$key] = $choiceValue; - } - } - - /** - * Checks whether the given choices can be cast to strings without - * generating duplicates. - * This method is responsible for preventing conflict between scalar values - * and the empty value. - */ - private function castableToString(array $choices, array &$cache = []): bool - { - foreach ($choices as $choice) { - if (\is_array($choice)) { - if (!$this->castableToString($choice, $cache)) { - return false; - } - - continue; - } elseif (!\is_scalar($choice)) { - return false; - } - - // prevent having false casted to the empty string by isset() - $choice = false === $choice ? '0' : (string) $choice; - - if (isset($cache[$choice])) { - return false; - } - - $cache[$choice] = true; - } - - return true; - } -} diff --git a/lib/symfony/form/ChoiceList/ChoiceList.php b/lib/symfony/form/ChoiceList/ChoiceList.php deleted file mode 100644 index df63c83d8..000000000 --- a/lib/symfony/form/ChoiceList/ChoiceList.php +++ /dev/null @@ -1,159 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList; - -use Symfony\Component\Form\ChoiceList\Factory\Cache\ChoiceAttr; -use Symfony\Component\Form\ChoiceList\Factory\Cache\ChoiceFieldName; -use Symfony\Component\Form\ChoiceList\Factory\Cache\ChoiceFilter; -use Symfony\Component\Form\ChoiceList\Factory\Cache\ChoiceLabel; -use Symfony\Component\Form\ChoiceList\Factory\Cache\ChoiceLoader; -use Symfony\Component\Form\ChoiceList\Factory\Cache\ChoiceTranslationParameters; -use Symfony\Component\Form\ChoiceList\Factory\Cache\ChoiceValue; -use Symfony\Component\Form\ChoiceList\Factory\Cache\GroupBy; -use Symfony\Component\Form\ChoiceList\Factory\Cache\PreferredChoice; -use Symfony\Component\Form\ChoiceList\Loader\CallbackChoiceLoader; -use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; -use Symfony\Component\Form\FormTypeExtensionInterface; -use Symfony\Component\Form\FormTypeInterface; - -/** - * A set of convenient static methods to create cacheable choice list options. - * - * @author Jules Pietri <jules@heahprod.com> - */ -final class ChoiceList -{ - /** - * Creates a cacheable loader from any callable providing iterable choices. - * - * @param FormTypeInterface|FormTypeExtensionInterface $formType A form type or type extension configuring a cacheable choice list - * @param callable $choices A callable that must return iterable choices or grouped choices - * @param mixed|null $vary Dynamic data used to compute a unique hash when caching the loader - */ - public static function lazy($formType, callable $choices, $vary = null): ChoiceLoader - { - return self::loader($formType, new CallbackChoiceLoader($choices), $vary); - } - - /** - * Decorates a loader to make it cacheable. - * - * @param FormTypeInterface|FormTypeExtensionInterface $formType A form type or type extension configuring a cacheable choice list - * @param ChoiceLoaderInterface $loader A loader responsible for creating loading choices or grouped choices - * @param mixed|null $vary Dynamic data used to compute a unique hash when caching the loader - */ - public static function loader($formType, ChoiceLoaderInterface $loader, $vary = null): ChoiceLoader - { - return new ChoiceLoader($formType, $loader, $vary); - } - - /** - * Decorates a "choice_value" callback to make it cacheable. - * - * @param FormTypeInterface|FormTypeExtensionInterface $formType A form type or type extension configuring a cacheable choice list - * @param callable $value Any pseudo callable to create a unique string value from a choice - * @param mixed|null $vary Dynamic data used to compute a unique hash when caching the callback - */ - public static function value($formType, $value, $vary = null): ChoiceValue - { - return new ChoiceValue($formType, $value, $vary); - } - - /** - * @param FormTypeInterface|FormTypeExtensionInterface $formType A form type or type extension configuring a cacheable choice list - * @param callable $filter Any pseudo callable to filter a choice list - * @param mixed|null $vary Dynamic data used to compute a unique hash when caching the callback - */ - public static function filter($formType, $filter, $vary = null): ChoiceFilter - { - return new ChoiceFilter($formType, $filter, $vary); - } - - /** - * Decorates a "choice_label" option to make it cacheable. - * - * @param FormTypeInterface|FormTypeExtensionInterface $formType A form type or type extension configuring a cacheable choice list - * @param callable|false $label Any pseudo callable to create a label from a choice or false to discard it - * @param mixed|null $vary Dynamic data used to compute a unique hash when caching the option - */ - public static function label($formType, $label, $vary = null): ChoiceLabel - { - return new ChoiceLabel($formType, $label, $vary); - } - - /** - * Decorates a "choice_name" callback to make it cacheable. - * - * @param FormTypeInterface|FormTypeExtensionInterface $formType A form type or type extension configuring a cacheable choice list - * @param callable $fieldName Any pseudo callable to create a field name from a choice - * @param mixed|null $vary Dynamic data used to compute a unique hash when caching the callback - */ - public static function fieldName($formType, $fieldName, $vary = null): ChoiceFieldName - { - return new ChoiceFieldName($formType, $fieldName, $vary); - } - - /** - * Decorates a "choice_attr" option to make it cacheable. - * - * @param FormTypeInterface|FormTypeExtensionInterface $formType A form type or type extension configuring a cacheable choice list - * @param callable|array $attr Any pseudo callable or array to create html attributes from a choice - * @param mixed|null $vary Dynamic data used to compute a unique hash when caching the option - */ - public static function attr($formType, $attr, $vary = null): ChoiceAttr - { - return new ChoiceAttr($formType, $attr, $vary); - } - - /** - * Decorates a "choice_translation_parameters" option to make it cacheable. - * - * @param FormTypeInterface|FormTypeExtensionInterface $formType A form type or type extension configuring a cacheable choice list - * @param callable|array $translationParameters Any pseudo callable or array to create translation parameters from a choice - * @param mixed|null $vary Dynamic data used to compute a unique hash when caching the option - */ - public static function translationParameters($formType, $translationParameters, $vary = null): ChoiceTranslationParameters - { - return new ChoiceTranslationParameters($formType, $translationParameters, $vary); - } - - /** - * Decorates a "group_by" callback to make it cacheable. - * - * @param FormTypeInterface|FormTypeExtensionInterface $formType A form type or type extension configuring a cacheable choice list - * @param callable $groupBy Any pseudo callable to return a group name from a choice - * @param mixed|null $vary Dynamic data used to compute a unique hash when caching the callback - */ - public static function groupBy($formType, $groupBy, $vary = null): GroupBy - { - return new GroupBy($formType, $groupBy, $vary); - } - - /** - * Decorates a "preferred_choices" option to make it cacheable. - * - * @param FormTypeInterface|FormTypeExtensionInterface $formType A form type or type extension configuring a cacheable choice list - * @param callable|array $preferred Any pseudo callable or array to return a group name from a choice - * @param mixed|null $vary Dynamic data used to compute a unique hash when caching the option - */ - public static function preferred($formType, $preferred, $vary = null): PreferredChoice - { - return new PreferredChoice($formType, $preferred, $vary); - } - - /** - * Should not be instantiated. - */ - private function __construct() - { - } -} diff --git a/lib/symfony/form/ChoiceList/ChoiceListInterface.php b/lib/symfony/form/ChoiceList/ChoiceListInterface.php deleted file mode 100644 index 8bf6f95d7..000000000 --- a/lib/symfony/form/ChoiceList/ChoiceListInterface.php +++ /dev/null @@ -1,140 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList; - -/** - * A list of choices that can be selected in a choice field. - * - * A choice list assigns unique string values to each of a list of choices. - * These string values are displayed in the "value" attributes in HTML and - * submitted back to the server. - * - * The acceptable data types for the choices depend on the implementation. - * Values must always be strings and (within the list) free of duplicates. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface ChoiceListInterface -{ - /** - * Returns all selectable choices. - * - * @return array The selectable choices indexed by the corresponding values - */ - public function getChoices(); - - /** - * Returns the values for the choices. - * - * The values are strings that do not contain duplicates: - * - * $form->add('field', 'choice', [ - * 'choices' => [ - * 'Decided' => ['Yes' => true, 'No' => false], - * 'Undecided' => ['Maybe' => null], - * ], - * ]); - * - * In this example, the result of this method is: - * - * [ - * 'Yes' => '0', - * 'No' => '1', - * 'Maybe' => '2', - * ] - * - * Null and false MUST NOT conflict when being casted to string. - * For this some default incremented values SHOULD be computed. - * - * @return string[] - */ - public function getValues(); - - /** - * Returns the values in the structure originally passed to the list. - * - * Contrary to {@link getValues()}, the result is indexed by the original - * keys of the choices. If the original array contained nested arrays, these - * nested arrays are represented here as well: - * - * $form->add('field', 'choice', [ - * 'choices' => [ - * 'Decided' => ['Yes' => true, 'No' => false], - * 'Undecided' => ['Maybe' => null], - * ], - * ]); - * - * In this example, the result of this method is: - * - * [ - * 'Decided' => ['Yes' => '0', 'No' => '1'], - * 'Undecided' => ['Maybe' => '2'], - * ] - * - * Nested arrays do not make sense in a view format unless - * they are used as a convenient way of grouping. - * If the implementation does not intend to support grouped choices, - * this method SHOULD be equivalent to {@link getValues()}. - * The $groupBy callback parameter SHOULD be used instead. - * - * @return string[] - */ - public function getStructuredValues(); - - /** - * Returns the original keys of the choices. - * - * The original keys are the keys of the choice array that was passed in the - * "choice" option of the choice type. Note that this array may contain - * duplicates if the "choice" option contained choice groups: - * - * $form->add('field', 'choice', [ - * 'choices' => [ - * 'Decided' => [true, false], - * 'Undecided' => [null], - * ], - * ]); - * - * In this example, the original key 0 appears twice, once for `true` and - * once for `null`. - * - * @return int[]|string[] The original choice keys indexed by the - * corresponding choice values - */ - public function getOriginalKeys(); - - /** - * Returns the choices corresponding to the given values. - * - * The choices are returned with the same keys and in the same order as the - * corresponding values in the given array. - * - * @param string[] $values An array of choice values. Non-existing values in - * this array are ignored - * - * @return array - */ - public function getChoicesForValues(array $values); - - /** - * Returns the values corresponding to the given choices. - * - * The values are returned with the same keys and in the same order as the - * corresponding choices in the given array. - * - * @param array $choices An array of choices. Non-existing choices in this - * array are ignored - * - * @return string[] - */ - public function getValuesForChoices(array $choices); -} diff --git a/lib/symfony/form/ChoiceList/Factory/Cache/AbstractStaticOption.php b/lib/symfony/form/ChoiceList/Factory/Cache/AbstractStaticOption.php deleted file mode 100644 index 42b31e027..000000000 --- a/lib/symfony/form/ChoiceList/Factory/Cache/AbstractStaticOption.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList\Factory\Cache; - -use Symfony\Component\Form\ChoiceList\Factory\CachingFactoryDecorator; -use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; -use Symfony\Component\Form\Extension\Core\Type\ChoiceType; -use Symfony\Component\Form\FormTypeExtensionInterface; -use Symfony\Component\Form\FormTypeInterface; - -/** - * A template decorator for static {@see ChoiceType} options. - * - * Used as fly weight for {@see CachingFactoryDecorator}. - * - * @internal - * - * @author Jules Pietri <jules@heahprod.com> - */ -abstract class AbstractStaticOption -{ - private static $options = []; - - /** @var bool|callable|string|array|\Closure|ChoiceLoaderInterface */ - private $option; - - /** - * @param FormTypeInterface|FormTypeExtensionInterface $formType A form type or type extension configuring a cacheable choice list - * @param mixed $option Any pseudo callable, array, string or bool to define a choice list option - * @param mixed|null $vary Dynamic data used to compute a unique hash when caching the option - */ - final public function __construct($formType, $option, $vary = null) - { - if (!$formType instanceof FormTypeInterface && !$formType instanceof FormTypeExtensionInterface) { - throw new \TypeError(sprintf('Expected an instance of "%s" or "%s", but got "%s".', FormTypeInterface::class, FormTypeExtensionInterface::class, get_debug_type($formType))); - } - - $hash = CachingFactoryDecorator::generateHash([static::class, $formType, $vary]); - - $this->option = self::$options[$hash] ?? self::$options[$hash] = $option; - } - - /** - * @return mixed - */ - final public function getOption() - { - return $this->option; - } - - final public static function reset(): void - { - self::$options = []; - } -} diff --git a/lib/symfony/form/ChoiceList/Factory/Cache/ChoiceAttr.php b/lib/symfony/form/ChoiceList/Factory/Cache/ChoiceAttr.php deleted file mode 100644 index 8de6956d1..000000000 --- a/lib/symfony/form/ChoiceList/Factory/Cache/ChoiceAttr.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList\Factory\Cache; - -use Symfony\Component\Form\FormTypeExtensionInterface; -use Symfony\Component\Form\FormTypeInterface; - -/** - * A cacheable wrapper for any {@see FormTypeInterface} or {@see FormTypeExtensionInterface} - * which configures a "choice_attr" option. - * - * @internal - * - * @author Jules Pietri <jules@heahprod.com> - */ -final class ChoiceAttr extends AbstractStaticOption -{ -} diff --git a/lib/symfony/form/ChoiceList/Factory/Cache/ChoiceFieldName.php b/lib/symfony/form/ChoiceList/Factory/Cache/ChoiceFieldName.php deleted file mode 100644 index 0c71e2050..000000000 --- a/lib/symfony/form/ChoiceList/Factory/Cache/ChoiceFieldName.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList\Factory\Cache; - -use Symfony\Component\Form\FormTypeExtensionInterface; -use Symfony\Component\Form\FormTypeInterface; - -/** - * A cacheable wrapper for any {@see FormTypeInterface} or {@see FormTypeExtensionInterface} - * which configures a "choice_name" callback. - * - * @internal - * - * @author Jules Pietri <jules@heahprod.com> - */ -final class ChoiceFieldName extends AbstractStaticOption -{ -} diff --git a/lib/symfony/form/ChoiceList/Factory/Cache/ChoiceFilter.php b/lib/symfony/form/ChoiceList/Factory/Cache/ChoiceFilter.php deleted file mode 100644 index 13b8cd8ed..000000000 --- a/lib/symfony/form/ChoiceList/Factory/Cache/ChoiceFilter.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList\Factory\Cache; - -use Symfony\Component\Form\FormTypeExtensionInterface; -use Symfony\Component\Form\FormTypeInterface; - -/** - * A cacheable wrapper for any {@see FormTypeInterface} or {@see FormTypeExtensionInterface} - * which configures a "choice_filter" option. - * - * @internal - * - * @author Jules Pietri <jules@heahprod.com> - */ -final class ChoiceFilter extends AbstractStaticOption -{ -} diff --git a/lib/symfony/form/ChoiceList/Factory/Cache/ChoiceLabel.php b/lib/symfony/form/ChoiceList/Factory/Cache/ChoiceLabel.php deleted file mode 100644 index 664a09081..000000000 --- a/lib/symfony/form/ChoiceList/Factory/Cache/ChoiceLabel.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList\Factory\Cache; - -use Symfony\Component\Form\FormTypeExtensionInterface; -use Symfony\Component\Form\FormTypeInterface; - -/** - * A cacheable wrapper for any {@see FormTypeInterface} or {@see FormTypeExtensionInterface} - * which configures a "choice_label" option. - * - * @internal - * - * @author Jules Pietri <jules@heahprod.com> - */ -final class ChoiceLabel extends AbstractStaticOption -{ -} diff --git a/lib/symfony/form/ChoiceList/Factory/Cache/ChoiceLoader.php b/lib/symfony/form/ChoiceList/Factory/Cache/ChoiceLoader.php deleted file mode 100644 index 83b2ca0aa..000000000 --- a/lib/symfony/form/ChoiceList/Factory/Cache/ChoiceLoader.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList\Factory\Cache; - -use Symfony\Component\Form\ChoiceList\ChoiceListInterface; -use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; -use Symfony\Component\Form\FormTypeExtensionInterface; -use Symfony\Component\Form\FormTypeInterface; - -/** - * A cacheable wrapper for {@see FormTypeInterface} or {@see FormTypeExtensionInterface} - * which configures a "choice_loader" option. - * - * @internal - * - * @author Jules Pietri <jules@heahprod.com> - */ -final class ChoiceLoader extends AbstractStaticOption implements ChoiceLoaderInterface -{ - /** - * {@inheritdoc} - */ - public function loadChoiceList(callable $value = null): ChoiceListInterface - { - return $this->getOption()->loadChoiceList($value); - } - - /** - * {@inheritdoc} - */ - public function loadChoicesForValues(array $values, callable $value = null): array - { - return $this->getOption()->loadChoicesForValues($values, $value); - } - - /** - * {@inheritdoc} - */ - public function loadValuesForChoices(array $choices, callable $value = null): array - { - return $this->getOption()->loadValuesForChoices($choices, $value); - } -} diff --git a/lib/symfony/form/ChoiceList/Factory/Cache/ChoiceTranslationParameters.php b/lib/symfony/form/ChoiceList/Factory/Cache/ChoiceTranslationParameters.php deleted file mode 100644 index e9ab5c711..000000000 --- a/lib/symfony/form/ChoiceList/Factory/Cache/ChoiceTranslationParameters.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList\Factory\Cache; - -use Symfony\Component\Form\FormTypeExtensionInterface; -use Symfony\Component\Form\FormTypeInterface; - -/** - * A cacheable wrapper for any {@see FormTypeInterface} or {@see FormTypeExtensionInterface} - * which configures a "choice_translation_parameters" option. - * - * @internal - * - * @author Vincent Langlet <vincentlanglet@users.noreply.github.com> - */ -final class ChoiceTranslationParameters extends AbstractStaticOption -{ -} diff --git a/lib/symfony/form/ChoiceList/Factory/Cache/ChoiceValue.php b/lib/symfony/form/ChoiceList/Factory/Cache/ChoiceValue.php deleted file mode 100644 index d96f1e9e8..000000000 --- a/lib/symfony/form/ChoiceList/Factory/Cache/ChoiceValue.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList\Factory\Cache; - -use Symfony\Component\Form\FormTypeExtensionInterface; -use Symfony\Component\Form\FormTypeInterface; - -/** - * A cacheable wrapper for any {@see FormTypeInterface} or {@see FormTypeExtensionInterface} - * which configures a "choice_value" callback. - * - * @internal - * - * @author Jules Pietri <jules@heahprod.com> - */ -final class ChoiceValue extends AbstractStaticOption -{ -} diff --git a/lib/symfony/form/ChoiceList/Factory/Cache/GroupBy.php b/lib/symfony/form/ChoiceList/Factory/Cache/GroupBy.php deleted file mode 100644 index 2ad492caf..000000000 --- a/lib/symfony/form/ChoiceList/Factory/Cache/GroupBy.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList\Factory\Cache; - -use Symfony\Component\Form\FormTypeExtensionInterface; -use Symfony\Component\Form\FormTypeInterface; - -/** - * A cacheable wrapper for any {@see FormTypeInterface} or {@see FormTypeExtensionInterface} - * which configures a "group_by" callback. - * - * @internal - * - * @author Jules Pietri <jules@heahprod.com> - */ -final class GroupBy extends AbstractStaticOption -{ -} diff --git a/lib/symfony/form/ChoiceList/Factory/Cache/PreferredChoice.php b/lib/symfony/form/ChoiceList/Factory/Cache/PreferredChoice.php deleted file mode 100644 index 4aefd69ab..000000000 --- a/lib/symfony/form/ChoiceList/Factory/Cache/PreferredChoice.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList\Factory\Cache; - -use Symfony\Component\Form\FormTypeExtensionInterface; -use Symfony\Component\Form\FormTypeInterface; - -/** - * A cacheable wrapper for any {@see FormTypeInterface} or {@see FormTypeExtensionInterface} - * which configures a "preferred_choices" option. - * - * @internal - * - * @author Jules Pietri <jules@heahprod.com> - */ -final class PreferredChoice extends AbstractStaticOption -{ -} diff --git a/lib/symfony/form/ChoiceList/Factory/CachingFactoryDecorator.php b/lib/symfony/form/ChoiceList/Factory/CachingFactoryDecorator.php deleted file mode 100644 index 912cab4e2..000000000 --- a/lib/symfony/form/ChoiceList/Factory/CachingFactoryDecorator.php +++ /dev/null @@ -1,254 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList\Factory; - -use Symfony\Component\Form\ChoiceList\ChoiceListInterface; -use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; -use Symfony\Component\Form\ChoiceList\View\ChoiceListView; -use Symfony\Contracts\Service\ResetInterface; - -/** - * Caches the choice lists created by the decorated factory. - * - * To cache a list based on its options, arguments must be decorated - * by a {@see Cache\AbstractStaticOption} implementation. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * @author Jules Pietri <jules@heahprod.com> - */ -class CachingFactoryDecorator implements ChoiceListFactoryInterface, ResetInterface -{ - private $decoratedFactory; - - /** - * @var ChoiceListInterface[] - */ - private $lists = []; - - /** - * @var ChoiceListView[] - */ - private $views = []; - - /** - * Generates a SHA-256 hash for the given value. - * - * Optionally, a namespace string can be passed. Calling this method will - * the same values, but different namespaces, will return different hashes. - * - * @param mixed $value The value to hash - * - * @return string The SHA-256 hash - * - * @internal - */ - public static function generateHash($value, string $namespace = ''): string - { - if (\is_object($value)) { - $value = spl_object_hash($value); - } elseif (\is_array($value)) { - array_walk_recursive($value, function (&$v) { - if (\is_object($v)) { - $v = spl_object_hash($v); - } - }); - } - - return hash('sha256', $namespace.':'.serialize($value)); - } - - public function __construct(ChoiceListFactoryInterface $decoratedFactory) - { - $this->decoratedFactory = $decoratedFactory; - } - - /** - * Returns the decorated factory. - * - * @return ChoiceListFactoryInterface - */ - public function getDecoratedFactory() - { - return $this->decoratedFactory; - } - - /** - * {@inheritdoc} - * - * @param mixed $value - * @param mixed $filter - */ - public function createListFromChoices(iterable $choices, $value = null/* , $filter = null */) - { - $filter = \func_num_args() > 2 ? func_get_arg(2) : null; - - if ($choices instanceof \Traversable) { - $choices = iterator_to_array($choices); - } - - $cache = true; - // Only cache per value and filter when needed. The value is not validated on purpose. - // The decorated factory may decide which values to accept and which not. - if ($value instanceof Cache\ChoiceValue) { - $value = $value->getOption(); - } elseif ($value) { - $cache = false; - } - if ($filter instanceof Cache\ChoiceFilter) { - $filter = $filter->getOption(); - } elseif ($filter) { - $cache = false; - } - - if (!$cache) { - return $this->decoratedFactory->createListFromChoices($choices, $value, $filter); - } - - $hash = self::generateHash([$choices, $value, $filter], 'fromChoices'); - - if (!isset($this->lists[$hash])) { - $this->lists[$hash] = $this->decoratedFactory->createListFromChoices($choices, $value, $filter); - } - - return $this->lists[$hash]; - } - - /** - * {@inheritdoc} - * - * @param mixed $value - * @param mixed $filter - */ - public function createListFromLoader(ChoiceLoaderInterface $loader, $value = null/* , $filter = null */) - { - $filter = \func_num_args() > 2 ? func_get_arg(2) : null; - - $cache = true; - - if ($loader instanceof Cache\ChoiceLoader) { - $loader = $loader->getOption(); - } else { - $cache = false; - } - - if ($value instanceof Cache\ChoiceValue) { - $value = $value->getOption(); - } elseif ($value) { - $cache = false; - } - - if ($filter instanceof Cache\ChoiceFilter) { - $filter = $filter->getOption(); - } elseif ($filter) { - $cache = false; - } - - if (!$cache) { - return $this->decoratedFactory->createListFromLoader($loader, $value, $filter); - } - - $hash = self::generateHash([$loader, $value, $filter], 'fromLoader'); - - if (!isset($this->lists[$hash])) { - $this->lists[$hash] = $this->decoratedFactory->createListFromLoader($loader, $value, $filter); - } - - return $this->lists[$hash]; - } - - /** - * {@inheritdoc} - * - * @param mixed $preferredChoices - * @param mixed $label - * @param mixed $index - * @param mixed $groupBy - * @param mixed $attr - * @param mixed $labelTranslationParameters - */ - public function createView(ChoiceListInterface $list, $preferredChoices = null, $label = null, $index = null, $groupBy = null, $attr = null/* , $labelTranslationParameters = [] */) - { - $labelTranslationParameters = \func_num_args() > 6 ? func_get_arg(6) : []; - $cache = true; - - if ($preferredChoices instanceof Cache\PreferredChoice) { - $preferredChoices = $preferredChoices->getOption(); - } elseif ($preferredChoices) { - $cache = false; - } - - if ($label instanceof Cache\ChoiceLabel) { - $label = $label->getOption(); - } elseif (null !== $label) { - $cache = false; - } - - if ($index instanceof Cache\ChoiceFieldName) { - $index = $index->getOption(); - } elseif ($index) { - $cache = false; - } - - if ($groupBy instanceof Cache\GroupBy) { - $groupBy = $groupBy->getOption(); - } elseif ($groupBy) { - $cache = false; - } - - if ($attr instanceof Cache\ChoiceAttr) { - $attr = $attr->getOption(); - } elseif ($attr) { - $cache = false; - } - - if ($labelTranslationParameters instanceof Cache\ChoiceTranslationParameters) { - $labelTranslationParameters = $labelTranslationParameters->getOption(); - } elseif ([] !== $labelTranslationParameters) { - $cache = false; - } - - if (!$cache) { - return $this->decoratedFactory->createView( - $list, - $preferredChoices, - $label, - $index, - $groupBy, - $attr, - $labelTranslationParameters - ); - } - - $hash = self::generateHash([$list, $preferredChoices, $label, $index, $groupBy, $attr, $labelTranslationParameters]); - - if (!isset($this->views[$hash])) { - $this->views[$hash] = $this->decoratedFactory->createView( - $list, - $preferredChoices, - $label, - $index, - $groupBy, - $attr, - $labelTranslationParameters - ); - } - - return $this->views[$hash]; - } - - public function reset() - { - $this->lists = []; - $this->views = []; - Cache\AbstractStaticOption::reset(); - } -} diff --git a/lib/symfony/form/ChoiceList/Factory/ChoiceListFactoryInterface.php b/lib/symfony/form/ChoiceList/Factory/ChoiceListFactoryInterface.php deleted file mode 100644 index 1c08d812a..000000000 --- a/lib/symfony/form/ChoiceList/Factory/ChoiceListFactoryInterface.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList\Factory; - -use Symfony\Component\Form\ChoiceList\ChoiceListInterface; -use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; -use Symfony\Component\Form\ChoiceList\View\ChoiceListView; - -/** - * Creates {@link ChoiceListInterface} instances. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface ChoiceListFactoryInterface -{ - /** - * Creates a choice list for the given choices. - * - * The choices should be passed in the values of the choices array. - * - * Optionally, a callable can be passed for generating the choice values. - * The callable receives the choice as only argument. - * Null may be passed when the choice list contains the empty value. - * - * @param callable|null $filter The callable filtering the choices - * - * @return ChoiceListInterface - */ - public function createListFromChoices(iterable $choices, callable $value = null/* , callable $filter = null */); - - /** - * Creates a choice list that is loaded with the given loader. - * - * Optionally, a callable can be passed for generating the choice values. - * The callable receives the choice as only argument. - * Null may be passed when the choice list contains the empty value. - * - * @param callable|null $filter The callable filtering the choices - * - * @return ChoiceListInterface - */ - public function createListFromLoader(ChoiceLoaderInterface $loader, callable $value = null/* , callable $filter = null */); - - /** - * Creates a view for the given choice list. - * - * Callables may be passed for all optional arguments. The callables receive - * the choice as first and the array key as the second argument. - * - * * The callable for the label and the name should return the generated - * label/choice name. - * * The callable for the preferred choices should return true or false, - * depending on whether the choice should be preferred or not. - * * The callable for the grouping should return the group name or null if - * a choice should not be grouped. - * * The callable for the attributes should return an array of HTML - * attributes that will be inserted in the tag of the choice. - * - * If no callable is passed, the labels will be generated from the choice - * keys. The view indices will be generated using an incrementing integer - * by default. - * - * The preferred choices can also be passed as array. Each choice that is - * contained in that array will be marked as preferred. - * - * The attributes can be passed as multi-dimensional array. The keys should - * match the keys of the choices. The values should be arrays of HTML - * attributes that should be added to the respective choice. - * - * @param array|callable|null $preferredChoices The preferred choices - * @param callable|false|null $label The callable generating the choice labels; - * pass false to discard the label - * @param array|callable|null $attr The callable generating the HTML attributes - * @param array|callable $labelTranslationParameters The parameters used to translate the choice labels - * - * @return ChoiceListView - */ - public function createView(ChoiceListInterface $list, $preferredChoices = null, $label = null, callable $index = null, callable $groupBy = null, $attr = null/* , $labelTranslationParameters = [] */); -} diff --git a/lib/symfony/form/ChoiceList/Factory/DefaultChoiceListFactory.php b/lib/symfony/form/ChoiceList/Factory/DefaultChoiceListFactory.php deleted file mode 100644 index 9a244e542..000000000 --- a/lib/symfony/form/ChoiceList/Factory/DefaultChoiceListFactory.php +++ /dev/null @@ -1,322 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList\Factory; - -use Symfony\Component\Form\ChoiceList\ArrayChoiceList; -use Symfony\Component\Form\ChoiceList\ChoiceListInterface; -use Symfony\Component\Form\ChoiceList\LazyChoiceList; -use Symfony\Component\Form\ChoiceList\Loader\CallbackChoiceLoader; -use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; -use Symfony\Component\Form\ChoiceList\Loader\FilterChoiceLoaderDecorator; -use Symfony\Component\Form\ChoiceList\View\ChoiceGroupView; -use Symfony\Component\Form\ChoiceList\View\ChoiceListView; -use Symfony\Component\Form\ChoiceList\View\ChoiceView; -use Symfony\Component\Translation\TranslatableMessage; - -/** - * Default implementation of {@link ChoiceListFactoryInterface}. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * @author Jules Pietri <jules@heahprod.com> - */ -class DefaultChoiceListFactory implements ChoiceListFactoryInterface -{ - /** - * {@inheritdoc} - * - * @param callable|null $filter - */ - public function createListFromChoices(iterable $choices, callable $value = null/* , callable $filter = null */) - { - $filter = \func_num_args() > 2 ? func_get_arg(2) : null; - - if ($filter) { - // filter the choice list lazily - return $this->createListFromLoader(new FilterChoiceLoaderDecorator( - new CallbackChoiceLoader(static function () use ($choices) { - return $choices; - } - ), $filter), $value); - } - - return new ArrayChoiceList($choices, $value); - } - - /** - * {@inheritdoc} - * - * @param callable|null $filter - */ - public function createListFromLoader(ChoiceLoaderInterface $loader, callable $value = null/* , callable $filter = null */) - { - $filter = \func_num_args() > 2 ? func_get_arg(2) : null; - - if ($filter) { - $loader = new FilterChoiceLoaderDecorator($loader, $filter); - } - - return new LazyChoiceList($loader, $value); - } - - /** - * {@inheritdoc} - * - * @param array|callable $labelTranslationParameters The parameters used to translate the choice labels - */ - public function createView(ChoiceListInterface $list, $preferredChoices = null, $label = null, callable $index = null, callable $groupBy = null, $attr = null/* , $labelTranslationParameters = [] */) - { - $labelTranslationParameters = \func_num_args() > 6 ? func_get_arg(6) : []; - $preferredViews = []; - $preferredViewsOrder = []; - $otherViews = []; - $choices = $list->getChoices(); - $keys = $list->getOriginalKeys(); - - if (!\is_callable($preferredChoices)) { - if (empty($preferredChoices)) { - $preferredChoices = null; - } else { - // make sure we have keys that reflect order - $preferredChoices = array_values($preferredChoices); - $preferredChoices = static function ($choice) use ($preferredChoices) { - return array_search($choice, $preferredChoices, true); - }; - } - } - - // The names are generated from an incrementing integer by default - if (null === $index) { - $index = 0; - } - - // If $groupBy is a callable returning a string - // choices are added to the group with the name returned by the callable. - // If $groupBy is a callable returning an array - // choices are added to the groups with names returned by the callable - // If the callable returns null, the choice is not added to any group - if (\is_callable($groupBy)) { - foreach ($choices as $value => $choice) { - self::addChoiceViewsGroupedByCallable( - $groupBy, - $choice, - $value, - $label, - $keys, - $index, - $attr, - $labelTranslationParameters, - $preferredChoices, - $preferredViews, - $preferredViewsOrder, - $otherViews - ); - } - - // Remove empty group views that may have been created by - // addChoiceViewsGroupedByCallable() - foreach ($preferredViews as $key => $view) { - if ($view instanceof ChoiceGroupView && 0 === \count($view->choices)) { - unset($preferredViews[$key]); - } - } - - foreach ($otherViews as $key => $view) { - if ($view instanceof ChoiceGroupView && 0 === \count($view->choices)) { - unset($otherViews[$key]); - } - } - - foreach ($preferredViewsOrder as $key => $groupViewsOrder) { - if ($groupViewsOrder) { - $preferredViewsOrder[$key] = min($groupViewsOrder); - } else { - unset($preferredViewsOrder[$key]); - } - } - } else { - // Otherwise use the original structure of the choices - self::addChoiceViewsFromStructuredValues( - $list->getStructuredValues(), - $label, - $choices, - $keys, - $index, - $attr, - $labelTranslationParameters, - $preferredChoices, - $preferredViews, - $preferredViewsOrder, - $otherViews - ); - } - - uksort($preferredViews, static function ($a, $b) use ($preferredViewsOrder): int { - return isset($preferredViewsOrder[$a], $preferredViewsOrder[$b]) - ? $preferredViewsOrder[$a] <=> $preferredViewsOrder[$b] - : 0; - }); - - return new ChoiceListView($otherViews, $preferredViews); - } - - private static function addChoiceView($choice, string $value, $label, array $keys, &$index, $attr, $labelTranslationParameters, ?callable $isPreferred, array &$preferredViews, array &$preferredViewsOrder, array &$otherViews) - { - // $value may be an integer or a string, since it's stored in the array - // keys. We want to guarantee it's a string though. - $key = $keys[$value]; - $nextIndex = \is_int($index) ? $index++ : $index($choice, $key, $value); - - // BC normalize label to accept a false value - if (null === $label) { - // If the labels are null, use the original choice key by default - $label = (string) $key; - } elseif (false !== $label) { - // If "choice_label" is set to false and "expanded" is true, the value false - // should be passed on to the "label" option of the checkboxes/radio buttons - $dynamicLabel = $label($choice, $key, $value); - - if (false === $dynamicLabel) { - $label = false; - } elseif ($dynamicLabel instanceof TranslatableMessage) { - $label = $dynamicLabel; - } else { - $label = (string) $dynamicLabel; - } - } - - $view = new ChoiceView( - $choice, - $value, - $label, - // The attributes may be a callable or a mapping from choice indices - // to nested arrays - \is_callable($attr) ? $attr($choice, $key, $value) : ($attr[$key] ?? []), - // The label translation parameters may be a callable or a mapping from choice indices - // to nested arrays - \is_callable($labelTranslationParameters) ? $labelTranslationParameters($choice, $key, $value) : ($labelTranslationParameters[$key] ?? []) - ); - - // $isPreferred may be null if no choices are preferred - if (null !== $isPreferred && false !== $preferredKey = $isPreferred($choice, $key, $value)) { - $preferredViews[$nextIndex] = $view; - $preferredViewsOrder[$nextIndex] = $preferredKey; - } - - $otherViews[$nextIndex] = $view; - } - - private static function addChoiceViewsFromStructuredValues(array $values, $label, array $choices, array $keys, &$index, $attr, $labelTranslationParameters, ?callable $isPreferred, array &$preferredViews, array &$preferredViewsOrder, array &$otherViews) - { - foreach ($values as $key => $value) { - if (null === $value) { - continue; - } - - // Add the contents of groups to new ChoiceGroupView instances - if (\is_array($value)) { - $preferredViewsForGroup = []; - $otherViewsForGroup = []; - - self::addChoiceViewsFromStructuredValues( - $value, - $label, - $choices, - $keys, - $index, - $attr, - $labelTranslationParameters, - $isPreferred, - $preferredViewsForGroup, - $preferredViewsOrder, - $otherViewsForGroup - ); - - if (\count($preferredViewsForGroup) > 0) { - $preferredViews[$key] = new ChoiceGroupView($key, $preferredViewsForGroup); - } - - if (\count($otherViewsForGroup) > 0) { - $otherViews[$key] = new ChoiceGroupView($key, $otherViewsForGroup); - } - - continue; - } - - // Add ungrouped items directly - self::addChoiceView( - $choices[$value], - $value, - $label, - $keys, - $index, - $attr, - $labelTranslationParameters, - $isPreferred, - $preferredViews, - $preferredViewsOrder, - $otherViews - ); - } - } - - private static function addChoiceViewsGroupedByCallable(callable $groupBy, $choice, string $value, $label, array $keys, &$index, $attr, $labelTranslationParameters, ?callable $isPreferred, array &$preferredViews, array &$preferredViewsOrder, array &$otherViews) - { - $groupLabels = $groupBy($choice, $keys[$value], $value); - - if (null === $groupLabels) { - // If the callable returns null, don't group the choice - self::addChoiceView( - $choice, - $value, - $label, - $keys, - $index, - $attr, - $labelTranslationParameters, - $isPreferred, - $preferredViews, - $preferredViewsOrder, - $otherViews - ); - - return; - } - - $groupLabels = \is_array($groupLabels) ? array_map('strval', $groupLabels) : [(string) $groupLabels]; - - foreach ($groupLabels as $groupLabel) { - // Initialize the group views if necessary. Unnecessarily built group - // views will be cleaned up at the end of createView() - if (!isset($preferredViews[$groupLabel])) { - $preferredViews[$groupLabel] = new ChoiceGroupView($groupLabel); - $otherViews[$groupLabel] = new ChoiceGroupView($groupLabel); - } - if (!isset($preferredViewsOrder[$groupLabel])) { - $preferredViewsOrder[$groupLabel] = []; - } - - self::addChoiceView( - $choice, - $value, - $label, - $keys, - $index, - $attr, - $labelTranslationParameters, - $isPreferred, - $preferredViews[$groupLabel]->choices, - $preferredViewsOrder[$groupLabel], - $otherViews[$groupLabel]->choices - ); - } - } -} diff --git a/lib/symfony/form/ChoiceList/Factory/PropertyAccessDecorator.php b/lib/symfony/form/ChoiceList/Factory/PropertyAccessDecorator.php deleted file mode 100644 index 2f1ec6475..000000000 --- a/lib/symfony/form/ChoiceList/Factory/PropertyAccessDecorator.php +++ /dev/null @@ -1,239 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList\Factory; - -use Symfony\Component\Form\ChoiceList\ChoiceListInterface; -use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; -use Symfony\Component\Form\ChoiceList\View\ChoiceListView; -use Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException; -use Symfony\Component\PropertyAccess\PropertyAccess; -use Symfony\Component\PropertyAccess\PropertyAccessorInterface; -use Symfony\Component\PropertyAccess\PropertyPath; -use Symfony\Component\PropertyAccess\PropertyPathInterface; - -/** - * Adds property path support to a choice list factory. - * - * Pass the decorated factory to the constructor: - * - * $decorator = new PropertyAccessDecorator($factory); - * - * You can now pass property paths for generating choice values, labels, view - * indices, HTML attributes and for determining the preferred choices and the - * choice groups: - * - * // extract values from the $value property - * $list = $createListFromChoices($objects, 'value'); - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class PropertyAccessDecorator implements ChoiceListFactoryInterface -{ - private $decoratedFactory; - private $propertyAccessor; - - public function __construct(ChoiceListFactoryInterface $decoratedFactory, PropertyAccessorInterface $propertyAccessor = null) - { - $this->decoratedFactory = $decoratedFactory; - $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); - } - - /** - * Returns the decorated factory. - * - * @return ChoiceListFactoryInterface - */ - public function getDecoratedFactory() - { - return $this->decoratedFactory; - } - - /** - * {@inheritdoc} - * - * @param mixed $value - * @param mixed $filter - * - * @return ChoiceListInterface - */ - public function createListFromChoices(iterable $choices, $value = null/* , $filter = null */) - { - $filter = \func_num_args() > 2 ? func_get_arg(2) : null; - - if (\is_string($value)) { - $value = new PropertyPath($value); - } - - if ($value instanceof PropertyPathInterface) { - $accessor = $this->propertyAccessor; - $value = function ($choice) use ($accessor, $value) { - // The callable may be invoked with a non-object/array value - // when such values are passed to - // ChoiceListInterface::getValuesForChoices(). Handle this case - // so that the call to getValue() doesn't break. - return \is_object($choice) || \is_array($choice) ? $accessor->getValue($choice, $value) : null; - }; - } - - if (\is_string($filter)) { - $filter = new PropertyPath($filter); - } - - if ($filter instanceof PropertyPath) { - $accessor = $this->propertyAccessor; - $filter = static function ($choice) use ($accessor, $filter) { - return (\is_object($choice) || \is_array($choice)) && $accessor->getValue($choice, $filter); - }; - } - - return $this->decoratedFactory->createListFromChoices($choices, $value, $filter); - } - - /** - * {@inheritdoc} - * - * @param mixed $value - * @param mixed $filter - * - * @return ChoiceListInterface - */ - public function createListFromLoader(ChoiceLoaderInterface $loader, $value = null/* , $filter = null */) - { - $filter = \func_num_args() > 2 ? func_get_arg(2) : null; - - if (\is_string($value)) { - $value = new PropertyPath($value); - } - - if ($value instanceof PropertyPathInterface) { - $accessor = $this->propertyAccessor; - $value = function ($choice) use ($accessor, $value) { - // The callable may be invoked with a non-object/array value - // when such values are passed to - // ChoiceListInterface::getValuesForChoices(). Handle this case - // so that the call to getValue() doesn't break. - return \is_object($choice) || \is_array($choice) ? $accessor->getValue($choice, $value) : null; - }; - } - - if (\is_string($filter)) { - $filter = new PropertyPath($filter); - } - - if ($filter instanceof PropertyPath) { - $accessor = $this->propertyAccessor; - $filter = static function ($choice) use ($accessor, $filter) { - return (\is_object($choice) || \is_array($choice)) && $accessor->getValue($choice, $filter); - }; - } - - return $this->decoratedFactory->createListFromLoader($loader, $value, $filter); - } - - /** - * {@inheritdoc} - * - * @param mixed $preferredChoices - * @param mixed $label - * @param mixed $index - * @param mixed $groupBy - * @param mixed $attr - * @param mixed $labelTranslationParameters - * - * @return ChoiceListView - */ - public function createView(ChoiceListInterface $list, $preferredChoices = null, $label = null, $index = null, $groupBy = null, $attr = null/* , $labelTranslationParameters = [] */) - { - $labelTranslationParameters = \func_num_args() > 6 ? func_get_arg(6) : []; - $accessor = $this->propertyAccessor; - - if (\is_string($label)) { - $label = new PropertyPath($label); - } - - if ($label instanceof PropertyPathInterface) { - $label = function ($choice) use ($accessor, $label) { - return $accessor->getValue($choice, $label); - }; - } - - if (\is_string($preferredChoices)) { - $preferredChoices = new PropertyPath($preferredChoices); - } - - if ($preferredChoices instanceof PropertyPathInterface) { - $preferredChoices = function ($choice) use ($accessor, $preferredChoices) { - try { - return $accessor->getValue($choice, $preferredChoices); - } catch (UnexpectedTypeException $e) { - // Assume not preferred if not readable - return false; - } - }; - } - - if (\is_string($index)) { - $index = new PropertyPath($index); - } - - if ($index instanceof PropertyPathInterface) { - $index = function ($choice) use ($accessor, $index) { - return $accessor->getValue($choice, $index); - }; - } - - if (\is_string($groupBy)) { - $groupBy = new PropertyPath($groupBy); - } - - if ($groupBy instanceof PropertyPathInterface) { - $groupBy = function ($choice) use ($accessor, $groupBy) { - try { - return $accessor->getValue($choice, $groupBy); - } catch (UnexpectedTypeException $e) { - // Don't group if path is not readable - return null; - } - }; - } - - if (\is_string($attr)) { - $attr = new PropertyPath($attr); - } - - if ($attr instanceof PropertyPathInterface) { - $attr = function ($choice) use ($accessor, $attr) { - return $accessor->getValue($choice, $attr); - }; - } - - if (\is_string($labelTranslationParameters)) { - $labelTranslationParameters = new PropertyPath($labelTranslationParameters); - } - - if ($labelTranslationParameters instanceof PropertyPath) { - $labelTranslationParameters = static function ($choice) use ($accessor, $labelTranslationParameters) { - return $accessor->getValue($choice, $labelTranslationParameters); - }; - } - - return $this->decoratedFactory->createView( - $list, - $preferredChoices, - $label, - $index, - $groupBy, - $attr, - $labelTranslationParameters - ); - } -} diff --git a/lib/symfony/form/ChoiceList/LazyChoiceList.php b/lib/symfony/form/ChoiceList/LazyChoiceList.php deleted file mode 100644 index ab4c103e8..000000000 --- a/lib/symfony/form/ChoiceList/LazyChoiceList.php +++ /dev/null @@ -1,103 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList; - -use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; - -/** - * A choice list that loads its choices lazily. - * - * The choices are fetched using a {@link ChoiceLoaderInterface} instance. - * If only {@link getChoicesForValues()} or {@link getValuesForChoices()} is - * called, the choice list is only loaded partially for improved performance. - * - * Once {@link getChoices()} or {@link getValues()} is called, the list is - * loaded fully. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class LazyChoiceList implements ChoiceListInterface -{ - private $loader; - - /** - * The callable creating string values for each choice. - * - * If null, choices are cast to strings. - * - * @var callable|null - */ - private $value; - - /** - * Creates a lazily-loaded list using the given loader. - * - * Optionally, a callable can be passed for generating the choice values. - * The callable receives the choice as first and the array key as the second - * argument. - * - * @param callable|null $value The callable generating the choice values - */ - public function __construct(ChoiceLoaderInterface $loader, callable $value = null) - { - $this->loader = $loader; - $this->value = $value; - } - - /** - * {@inheritdoc} - */ - public function getChoices() - { - return $this->loader->loadChoiceList($this->value)->getChoices(); - } - - /** - * {@inheritdoc} - */ - public function getValues() - { - return $this->loader->loadChoiceList($this->value)->getValues(); - } - - /** - * {@inheritdoc} - */ - public function getStructuredValues() - { - return $this->loader->loadChoiceList($this->value)->getStructuredValues(); - } - - /** - * {@inheritdoc} - */ - public function getOriginalKeys() - { - return $this->loader->loadChoiceList($this->value)->getOriginalKeys(); - } - - /** - * {@inheritdoc} - */ - public function getChoicesForValues(array $values) - { - return $this->loader->loadChoicesForValues($values, $this->value); - } - - /** - * {@inheritdoc} - */ - public function getValuesForChoices(array $choices) - { - return $this->loader->loadValuesForChoices($choices, $this->value); - } -} diff --git a/lib/symfony/form/ChoiceList/Loader/AbstractChoiceLoader.php b/lib/symfony/form/ChoiceList/Loader/AbstractChoiceLoader.php deleted file mode 100644 index a98cc239f..000000000 --- a/lib/symfony/form/ChoiceList/Loader/AbstractChoiceLoader.php +++ /dev/null @@ -1,79 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList\Loader; - -use Symfony\Component\Form\ChoiceList\ArrayChoiceList; -use Symfony\Component\Form\ChoiceList\ChoiceListInterface; - -/** - * @author Jules Pietri <jules@heahprod.com> - */ -abstract class AbstractChoiceLoader implements ChoiceLoaderInterface -{ - /** - * The loaded choices. - * - * @var iterable|null - */ - private $choices; - - /** - * @final - * - * {@inheritdoc} - */ - public function loadChoiceList(callable $value = null): ChoiceListInterface - { - return new ArrayChoiceList($this->choices ?? $this->choices = $this->loadChoices(), $value); - } - - /** - * {@inheritdoc} - */ - public function loadChoicesForValues(array $values, callable $value = null) - { - if (!$values) { - return []; - } - - return $this->doLoadChoicesForValues($values, $value); - } - - /** - * {@inheritdoc} - */ - public function loadValuesForChoices(array $choices, callable $value = null) - { - if (!$choices) { - return []; - } - - if ($value) { - // if a value callback exists, use it - return array_map($value, $choices); - } - - return $this->doLoadValuesForChoices($choices); - } - - abstract protected function loadChoices(): iterable; - - protected function doLoadChoicesForValues(array $values, ?callable $value): array - { - return $this->loadChoiceList($value)->getChoicesForValues($values); - } - - protected function doLoadValuesForChoices(array $choices): array - { - return $this->loadChoiceList()->getValuesForChoices($choices); - } -} diff --git a/lib/symfony/form/ChoiceList/Loader/CallbackChoiceLoader.php b/lib/symfony/form/ChoiceList/Loader/CallbackChoiceLoader.php deleted file mode 100644 index 1811d434e..000000000 --- a/lib/symfony/form/ChoiceList/Loader/CallbackChoiceLoader.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList\Loader; - -/** - * Loads an {@link ArrayChoiceList} instance from a callable returning iterable choices. - * - * @author Jules Pietri <jules@heahprod.com> - */ -class CallbackChoiceLoader extends AbstractChoiceLoader -{ - private $callback; - - /** - * @param callable $callback The callable returning iterable choices - */ - public function __construct(callable $callback) - { - $this->callback = $callback; - } - - protected function loadChoices(): iterable - { - return ($this->callback)(); - } -} diff --git a/lib/symfony/form/ChoiceList/Loader/ChoiceLoaderInterface.php b/lib/symfony/form/ChoiceList/Loader/ChoiceLoaderInterface.php deleted file mode 100644 index 98e03bbe3..000000000 --- a/lib/symfony/form/ChoiceList/Loader/ChoiceLoaderInterface.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList\Loader; - -use Symfony\Component\Form\ChoiceList\ChoiceListInterface; - -/** - * Loads a choice list. - * - * The methods {@link loadChoicesForValues()} and {@link loadValuesForChoices()} - * can be used to load the list only partially in cases where a fully-loaded - * list is not necessary. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface ChoiceLoaderInterface -{ - /** - * Loads a list of choices. - * - * Optionally, a callable can be passed for generating the choice values. - * The callable receives the choice as only argument. - * Null may be passed when the choice list contains the empty value. - * - * @param callable|null $value The callable which generates the values - * from choices - * - * @return ChoiceListInterface - */ - public function loadChoiceList(callable $value = null); - - /** - * Loads the choices corresponding to the given values. - * - * The choices are returned with the same keys and in the same order as the - * corresponding values in the given array. - * - * Optionally, a callable can be passed for generating the choice values. - * The callable receives the choice as only argument. - * Null may be passed when the choice list contains the empty value. - * - * @param string[] $values An array of choice values. Non-existing - * values in this array are ignored - * @param callable|null $value The callable generating the choice values - * - * @return array - */ - public function loadChoicesForValues(array $values, callable $value = null); - - /** - * Loads the values corresponding to the given choices. - * - * The values are returned with the same keys and in the same order as the - * corresponding choices in the given array. - * - * Optionally, a callable can be passed for generating the choice values. - * The callable receives the choice as only argument. - * Null may be passed when the choice list contains the empty value. - * - * @param array $choices An array of choices. Non-existing choices in - * this array are ignored - * @param callable|null $value The callable generating the choice values - * - * @return string[] - */ - public function loadValuesForChoices(array $choices, callable $value = null); -} diff --git a/lib/symfony/form/ChoiceList/Loader/FilterChoiceLoaderDecorator.php b/lib/symfony/form/ChoiceList/Loader/FilterChoiceLoaderDecorator.php deleted file mode 100644 index 5e9314e2b..000000000 --- a/lib/symfony/form/ChoiceList/Loader/FilterChoiceLoaderDecorator.php +++ /dev/null @@ -1,70 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList\Loader; - -/** - * A decorator to filter choices only when they are loaded or partially loaded. - * - * @author Jules Pietri <jules@heahprod.com> - */ -class FilterChoiceLoaderDecorator extends AbstractChoiceLoader -{ - private $decoratedLoader; - private $filter; - - public function __construct(ChoiceLoaderInterface $loader, callable $filter) - { - $this->decoratedLoader = $loader; - $this->filter = $filter; - } - - protected function loadChoices(): iterable - { - $list = $this->decoratedLoader->loadChoiceList(); - - if (array_values($list->getValues()) === array_values($structuredValues = $list->getStructuredValues())) { - return array_filter(array_combine($list->getOriginalKeys(), $list->getChoices()), $this->filter); - } - - foreach ($structuredValues as $group => $values) { - if (\is_array($values)) { - if ($values && $filtered = array_filter($list->getChoicesForValues($values), $this->filter)) { - $choices[$group] = $filtered; - } - continue; - // filter empty groups - } - - if ($filtered = array_filter($list->getChoicesForValues([$values]), $this->filter)) { - $choices[$group] = $filtered[0]; - } - } - - return $choices ?? []; - } - - /** - * {@inheritdoc} - */ - public function loadChoicesForValues(array $values, callable $value = null): array - { - return array_filter($this->decoratedLoader->loadChoicesForValues($values, $value), $this->filter); - } - - /** - * {@inheritdoc} - */ - public function loadValuesForChoices(array $choices, callable $value = null): array - { - return $this->decoratedLoader->loadValuesForChoices(array_filter($choices, $this->filter), $value); - } -} diff --git a/lib/symfony/form/ChoiceList/Loader/IntlCallbackChoiceLoader.php b/lib/symfony/form/ChoiceList/Loader/IntlCallbackChoiceLoader.php deleted file mode 100644 index 546937b90..000000000 --- a/lib/symfony/form/ChoiceList/Loader/IntlCallbackChoiceLoader.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList\Loader; - -/** - * Callback choice loader optimized for Intl choice types. - * - * @author Jules Pietri <jules@heahprod.com> - * @author Yonel Ceruto <yonelceruto@gmail.com> - */ -class IntlCallbackChoiceLoader extends CallbackChoiceLoader -{ - /** - * {@inheritdoc} - */ - public function loadChoicesForValues(array $values, callable $value = null) - { - return parent::loadChoicesForValues(array_filter($values), $value); - } - - /** - * {@inheritdoc} - */ - public function loadValuesForChoices(array $choices, callable $value = null) - { - $choices = array_filter($choices); - - // If no callable is set, choices are the same as values - if (null === $value) { - return $choices; - } - - return parent::loadValuesForChoices($choices, $value); - } -} diff --git a/lib/symfony/form/ChoiceList/View/ChoiceGroupView.php b/lib/symfony/form/ChoiceList/View/ChoiceGroupView.php deleted file mode 100644 index 46b7d19e7..000000000 --- a/lib/symfony/form/ChoiceList/View/ChoiceGroupView.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList\View; - -/** - * Represents a group of choices in templates. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @implements \IteratorAggregate<array-key, ChoiceGroupView|ChoiceView> - */ -class ChoiceGroupView implements \IteratorAggregate -{ - public $label; - public $choices; - - /** - * Creates a new choice group view. - * - * @param array<array-key, ChoiceGroupView|ChoiceView> $choices the choice views in the group - */ - public function __construct(string $label, array $choices = []) - { - $this->label = $label; - $this->choices = $choices; - } - - /** - * {@inheritdoc} - * - * @return \Traversable<array-key, ChoiceGroupView|ChoiceView> - */ - #[\ReturnTypeWillChange] - public function getIterator() - { - return new \ArrayIterator($this->choices); - } -} diff --git a/lib/symfony/form/ChoiceList/View/ChoiceListView.php b/lib/symfony/form/ChoiceList/View/ChoiceListView.php deleted file mode 100644 index 586269b51..000000000 --- a/lib/symfony/form/ChoiceList/View/ChoiceListView.php +++ /dev/null @@ -1,59 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList\View; - -/** - * Represents a choice list in templates. - * - * A choice list contains choices and optionally preferred choices which are - * displayed in the very beginning of the list. Both choices and preferred - * choices may be grouped in {@link ChoiceGroupView} instances. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class ChoiceListView -{ - public $choices; - public $preferredChoices; - - /** - * Creates a new choice list view. - * - * @param ChoiceGroupView[]|ChoiceView[] $choices The choice views - * @param ChoiceGroupView[]|ChoiceView[] $preferredChoices the preferred choice views - */ - public function __construct(array $choices = [], array $preferredChoices = []) - { - $this->choices = $choices; - $this->preferredChoices = $preferredChoices; - } - - /** - * Returns whether a placeholder is in the choices. - * - * A placeholder must be the first child element, not be in a group and have an empty value. - * - * @return bool - */ - public function hasPlaceholder() - { - if ($this->preferredChoices) { - $firstChoice = reset($this->preferredChoices); - - return $firstChoice instanceof ChoiceView && '' === $firstChoice->value; - } - - $firstChoice = reset($this->choices); - - return $firstChoice instanceof ChoiceView && '' === $firstChoice->value; - } -} diff --git a/lib/symfony/form/ChoiceList/View/ChoiceView.php b/lib/symfony/form/ChoiceList/View/ChoiceView.php deleted file mode 100644 index e1d8ac92d..000000000 --- a/lib/symfony/form/ChoiceList/View/ChoiceView.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\ChoiceList\View; - -use Symfony\Component\Translation\TranslatableMessage; - -/** - * Represents a choice in templates. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class ChoiceView -{ - public $label; - public $value; - public $data; - - /** - * Additional attributes for the HTML tag. - */ - public $attr; - - /** - * Additional parameters used to translate the label. - */ - public $labelTranslationParameters; - - /** - * Creates a new choice view. - * - * @param mixed $data The original choice - * @param string $value The view representation of the choice - * @param string|TranslatableMessage|false $label The label displayed to humans; pass false to discard the label - * @param array $attr Additional attributes for the HTML tag - * @param array $labelTranslationParameters Additional parameters used to translate the label - */ - public function __construct($data, string $value, $label, array $attr = [], array $labelTranslationParameters = []) - { - $this->data = $data; - $this->value = $value; - $this->label = $label; - $this->attr = $attr; - $this->labelTranslationParameters = $labelTranslationParameters; - } -} diff --git a/lib/symfony/form/ClearableErrorsInterface.php b/lib/symfony/form/ClearableErrorsInterface.php deleted file mode 100644 index e609bed02..000000000 --- a/lib/symfony/form/ClearableErrorsInterface.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -/** - * A form element whose errors can be cleared. - * - * @author Colin O'Dell <colinodell@gmail.com> - */ -interface ClearableErrorsInterface -{ - /** - * Removes all the errors of this form. - * - * @param bool $deep Whether to remove errors from child forms as well - * - * @return $this - */ - public function clearErrors(bool $deep = false); -} diff --git a/lib/symfony/form/ClickableInterface.php b/lib/symfony/form/ClickableInterface.php deleted file mode 100644 index 8b02d36e9..000000000 --- a/lib/symfony/form/ClickableInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -/** - * A clickable form element. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface ClickableInterface -{ - /** - * Returns whether this element was clicked. - * - * @return bool - */ - public function isClicked(); -} diff --git a/lib/symfony/form/Command/DebugCommand.php b/lib/symfony/form/Command/DebugCommand.php deleted file mode 100644 index 6979831c3..000000000 --- a/lib/symfony/form/Command/DebugCommand.php +++ /dev/null @@ -1,292 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Completion\CompletionInput; -use Symfony\Component\Console\Completion\CompletionSuggestions; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\Form\Console\Helper\DescriptorHelper; -use Symfony\Component\Form\Extension\Core\CoreExtension; -use Symfony\Component\Form\FormRegistryInterface; -use Symfony\Component\Form\FormTypeInterface; -use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; - -/** - * A console command for retrieving information about form types. - * - * @author Yonel Ceruto <yonelceruto@gmail.com> - */ -class DebugCommand extends Command -{ - protected static $defaultName = 'debug:form'; - protected static $defaultDescription = 'Display form type information'; - - private $formRegistry; - private $namespaces; - private $types; - private $extensions; - private $guessers; - private $fileLinkFormatter; - - public function __construct(FormRegistryInterface $formRegistry, array $namespaces = ['Symfony\Component\Form\Extension\Core\Type'], array $types = [], array $extensions = [], array $guessers = [], FileLinkFormatter $fileLinkFormatter = null) - { - parent::__construct(); - - $this->formRegistry = $formRegistry; - $this->namespaces = $namespaces; - $this->types = $types; - $this->extensions = $extensions; - $this->guessers = $guessers; - $this->fileLinkFormatter = $fileLinkFormatter; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('class', InputArgument::OPTIONAL, 'The form type class'), - new InputArgument('option', InputArgument::OPTIONAL, 'The form type option'), - new InputOption('show-deprecated', null, InputOption::VALUE_NONE, 'Display deprecated options in form types'), - new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt or json)', 'txt'), - ]) - ->setDescription(self::$defaultDescription) - ->setHelp(<<<'EOF' -The <info>%command.name%</info> command displays information about form types. - - <info>php %command.full_name%</info> - -The command lists all built-in types, services types, type extensions and -guessers currently available. - - <info>php %command.full_name% Symfony\Component\Form\Extension\Core\Type\ChoiceType</info> - <info>php %command.full_name% ChoiceType</info> - -The command lists all defined options that contains the given form type, -as well as their parents and type extensions. - - <info>php %command.full_name% ChoiceType choice_value</info> - -Use the <info>--show-deprecated</info> option to display form types with -deprecated options or the deprecated options of the given form type: - - <info>php %command.full_name% --show-deprecated</info> - <info>php %command.full_name% ChoiceType --show-deprecated</info> - -The command displays the definition of the given option name. - - <info>php %command.full_name% --format=json</info> - -The command lists everything in a machine readable json format. -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $io = new SymfonyStyle($input, $output); - - if (null === $class = $input->getArgument('class')) { - $object = null; - $options['core_types'] = $this->getCoreTypes(); - $options['service_types'] = array_values(array_diff($this->types, $options['core_types'])); - if ($input->getOption('show-deprecated')) { - $options['core_types'] = $this->filterTypesByDeprecated($options['core_types']); - $options['service_types'] = $this->filterTypesByDeprecated($options['service_types']); - } - $options['extensions'] = $this->extensions; - $options['guessers'] = $this->guessers; - foreach ($options as $k => $list) { - sort($options[$k]); - } - } else { - if (!class_exists($class) || !is_subclass_of($class, FormTypeInterface::class)) { - $class = $this->getFqcnTypeClass($input, $io, $class); - } - $resolvedType = $this->formRegistry->getType($class); - - if ($option = $input->getArgument('option')) { - $object = $resolvedType->getOptionsResolver(); - - if (!$object->isDefined($option)) { - $message = sprintf('Option "%s" is not defined in "%s".', $option, \get_class($resolvedType->getInnerType())); - - if ($alternatives = $this->findAlternatives($option, $object->getDefinedOptions())) { - 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 InvalidArgumentException($message); - } - - $options['type'] = $resolvedType->getInnerType(); - $options['option'] = $option; - } else { - $object = $resolvedType; - } - } - - $helper = new DescriptorHelper($this->fileLinkFormatter); - $options['format'] = $input->getOption('format'); - $options['show_deprecated'] = $input->getOption('show-deprecated'); - $helper->describe($io, $object, $options); - - return 0; - } - - private function getFqcnTypeClass(InputInterface $input, SymfonyStyle $io, string $shortClassName): string - { - $classes = $this->getFqcnTypeClasses($shortClassName); - - if (0 === $count = \count($classes)) { - $message = sprintf("Could not find type \"%s\" into the following namespaces:\n %s", $shortClassName, implode("\n ", $this->namespaces)); - - $allTypes = array_merge($this->getCoreTypes(), $this->types); - if ($alternatives = $this->findAlternatives($shortClassName, $allTypes)) { - 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 InvalidArgumentException($message); - } - if (1 === $count) { - return $classes[0]; - } - if (!$input->isInteractive()) { - throw new InvalidArgumentException(sprintf("The type \"%s\" is ambiguous.\n\nDid you mean one of these?\n %s.", $shortClassName, implode("\n ", $classes))); - } - - return $io->choice(sprintf("The type \"%s\" is ambiguous.\n\nSelect one of the following form types to display its information:", $shortClassName), $classes, $classes[0]); - } - - private function getFqcnTypeClasses(string $shortClassName): array - { - $classes = []; - sort($this->namespaces); - foreach ($this->namespaces as $namespace) { - if (class_exists($fqcn = $namespace.'\\'.$shortClassName)) { - $classes[] = $fqcn; - } elseif (class_exists($fqcn = $namespace.'\\'.ucfirst($shortClassName))) { - $classes[] = $fqcn; - } elseif (class_exists($fqcn = $namespace.'\\'.ucfirst($shortClassName).'Type')) { - $classes[] = $fqcn; - } elseif (str_ends_with($shortClassName, 'type') && class_exists($fqcn = $namespace.'\\'.ucfirst(substr($shortClassName, 0, -4).'Type'))) { - $classes[] = $fqcn; - } - } - - return $classes; - } - - private function getCoreTypes(): array - { - $coreExtension = new CoreExtension(); - $loadTypesRefMethod = (new \ReflectionObject($coreExtension))->getMethod('loadTypes'); - $loadTypesRefMethod->setAccessible(true); - $coreTypes = $loadTypesRefMethod->invoke($coreExtension); - $coreTypes = array_map(function (FormTypeInterface $type) { return \get_class($type); }, $coreTypes); - sort($coreTypes); - - return $coreTypes; - } - - private function filterTypesByDeprecated(array $types): array - { - $typesWithDeprecatedOptions = []; - foreach ($types as $class) { - $optionsResolver = $this->formRegistry->getType($class)->getOptionsResolver(); - foreach ($optionsResolver->getDefinedOptions() as $option) { - if ($optionsResolver->isDeprecated($option)) { - $typesWithDeprecatedOptions[] = $class; - break; - } - } - } - - return $typesWithDeprecatedOptions; - } - - private function findAlternatives(string $name, array $collection): array - { - $alternatives = []; - 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; - } - } - - $threshold = 1e3; - $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; }); - ksort($alternatives, \SORT_NATURAL | \SORT_FLAG_CASE); - - return array_keys($alternatives); - } - - public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void - { - if ($input->mustSuggestArgumentValuesFor('class')) { - $suggestions->suggestValues(array_merge($this->getCoreTypes(), $this->types)); - - return; - } - - if ($input->mustSuggestArgumentValuesFor('option') && null !== $class = $input->getArgument('class')) { - $this->completeOptions($class, $suggestions); - - return; - } - - if ($input->mustSuggestOptionValuesFor('format')) { - $helper = new DescriptorHelper(); - $suggestions->suggestValues($helper->getFormats()); - } - } - - private function completeOptions(string $class, CompletionSuggestions $suggestions): void - { - if (!class_exists($class) || !is_subclass_of($class, FormTypeInterface::class)) { - $classes = $this->getFqcnTypeClasses($class); - - if (1 === \count($classes)) { - $class = $classes[0]; - } - } - - if (!$this->formRegistry->hasType($class)) { - return; - } - - $resolvedType = $this->formRegistry->getType($class); - $suggestions->suggestValues($resolvedType->getOptionsResolver()->getDefinedOptions()); - } -} diff --git a/lib/symfony/form/Console/Descriptor/Descriptor.php b/lib/symfony/form/Console/Descriptor/Descriptor.php deleted file mode 100644 index 4aceafbe6..000000000 --- a/lib/symfony/form/Console/Descriptor/Descriptor.php +++ /dev/null @@ -1,207 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Console\Descriptor; - -use Symfony\Component\Console\Descriptor\DescriptorInterface; -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\OutputStyle; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\Form\ResolvedFormTypeInterface; -use Symfony\Component\Form\Util\OptionsResolverWrapper; -use Symfony\Component\OptionsResolver\Debug\OptionsResolverIntrospector; -use Symfony\Component\OptionsResolver\Exception\NoConfigurationException; -use Symfony\Component\OptionsResolver\OptionsResolver; - -/** - * @author Yonel Ceruto <yonelceruto@gmail.com> - * - * @internal - */ -abstract class Descriptor implements DescriptorInterface -{ - /** @var OutputStyle */ - protected $output; - protected $type; - protected $ownOptions = []; - protected $overriddenOptions = []; - protected $parentOptions = []; - protected $extensionOptions = []; - protected $requiredOptions = []; - protected $parents = []; - protected $extensions = []; - - /** - * {@inheritdoc} - */ - public function describe(OutputInterface $output, $object, array $options = []) - { - $this->output = $output instanceof OutputStyle ? $output : new SymfonyStyle(new ArrayInput([]), $output); - - switch (true) { - case null === $object: - $this->describeDefaults($options); - break; - case $object instanceof ResolvedFormTypeInterface: - $this->describeResolvedFormType($object, $options); - break; - case $object instanceof OptionsResolver: - $this->describeOption($object, $options); - break; - default: - throw new \InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_debug_type($object))); - } - } - - abstract protected function describeDefaults(array $options); - - abstract protected function describeResolvedFormType(ResolvedFormTypeInterface $resolvedFormType, array $options = []); - - abstract protected function describeOption(OptionsResolver $optionsResolver, array $options); - - protected function collectOptions(ResolvedFormTypeInterface $type) - { - $this->parents = []; - $this->extensions = []; - - if (null !== $type->getParent()) { - $optionsResolver = clone $this->getParentOptionsResolver($type->getParent()); - } else { - $optionsResolver = new OptionsResolver(); - } - - $type->getInnerType()->configureOptions($ownOptionsResolver = new OptionsResolverWrapper()); - $this->ownOptions = array_diff($ownOptionsResolver->getDefinedOptions(), $optionsResolver->getDefinedOptions()); - $overriddenOptions = array_intersect(array_merge($ownOptionsResolver->getDefinedOptions(), $ownOptionsResolver->getUndefinedOptions()), $optionsResolver->getDefinedOptions()); - - $this->parentOptions = []; - foreach ($this->parents as $class => $parentOptions) { - $this->overriddenOptions[$class] = array_intersect($overriddenOptions, $parentOptions); - $this->parentOptions[$class] = array_diff($parentOptions, $overriddenOptions); - } - - $type->getInnerType()->configureOptions($optionsResolver); - $this->collectTypeExtensionsOptions($type, $optionsResolver); - $this->extensionOptions = []; - foreach ($this->extensions as $class => $extensionOptions) { - $this->overriddenOptions[$class] = array_intersect($overriddenOptions, $extensionOptions); - $this->extensionOptions[$class] = array_diff($extensionOptions, $overriddenOptions); - } - - $this->overriddenOptions = array_filter($this->overriddenOptions); - $this->parentOptions = array_filter($this->parentOptions); - $this->extensionOptions = array_filter($this->extensionOptions); - $this->requiredOptions = $optionsResolver->getRequiredOptions(); - - $this->parents = array_keys($this->parents); - $this->extensions = array_keys($this->extensions); - } - - protected function getOptionDefinition(OptionsResolver $optionsResolver, string $option) - { - $definition = []; - - if ($info = $optionsResolver->getInfo($option)) { - $definition = [ - 'info' => $info, - ]; - } - - $definition += [ - 'required' => $optionsResolver->isRequired($option), - 'deprecated' => $optionsResolver->isDeprecated($option), - ]; - - $introspector = new OptionsResolverIntrospector($optionsResolver); - - $map = [ - 'default' => 'getDefault', - 'lazy' => 'getLazyClosures', - 'allowedTypes' => 'getAllowedTypes', - 'allowedValues' => 'getAllowedValues', - 'normalizers' => 'getNormalizers', - 'deprecation' => 'getDeprecation', - ]; - - foreach ($map as $key => $method) { - try { - $definition[$key] = $introspector->{$method}($option); - } catch (NoConfigurationException $e) { - // noop - } - } - - if (isset($definition['deprecation']) && isset($definition['deprecation']['message']) && \is_string($definition['deprecation']['message'])) { - $definition['deprecationMessage'] = strtr($definition['deprecation']['message'], ['%name%' => $option]); - $definition['deprecationPackage'] = $definition['deprecation']['package']; - $definition['deprecationVersion'] = $definition['deprecation']['version']; - } - - return $definition; - } - - protected function filterOptionsByDeprecated(ResolvedFormTypeInterface $type) - { - $deprecatedOptions = []; - $resolver = $type->getOptionsResolver(); - foreach ($resolver->getDefinedOptions() as $option) { - if ($resolver->isDeprecated($option)) { - $deprecatedOptions[] = $option; - } - } - - $filterByDeprecated = function (array $options) use ($deprecatedOptions) { - foreach ($options as $class => $opts) { - if ($deprecated = array_intersect($deprecatedOptions, $opts)) { - $options[$class] = $deprecated; - } else { - unset($options[$class]); - } - } - - return $options; - }; - - $this->ownOptions = array_intersect($deprecatedOptions, $this->ownOptions); - $this->overriddenOptions = $filterByDeprecated($this->overriddenOptions); - $this->parentOptions = $filterByDeprecated($this->parentOptions); - $this->extensionOptions = $filterByDeprecated($this->extensionOptions); - } - - private function getParentOptionsResolver(ResolvedFormTypeInterface $type): OptionsResolver - { - $this->parents[$class = \get_class($type->getInnerType())] = []; - - if (null !== $type->getParent()) { - $optionsResolver = clone $this->getParentOptionsResolver($type->getParent()); - } else { - $optionsResolver = new OptionsResolver(); - } - - $inheritedOptions = $optionsResolver->getDefinedOptions(); - $type->getInnerType()->configureOptions($optionsResolver); - $this->parents[$class] = array_diff($optionsResolver->getDefinedOptions(), $inheritedOptions); - - $this->collectTypeExtensionsOptions($type, $optionsResolver); - - return $optionsResolver; - } - - private function collectTypeExtensionsOptions(ResolvedFormTypeInterface $type, OptionsResolver $optionsResolver) - { - foreach ($type->getTypeExtensions() as $extension) { - $inheritedOptions = $optionsResolver->getDefinedOptions(); - $extension->configureOptions($optionsResolver); - $this->extensions[\get_class($extension)] = array_diff($optionsResolver->getDefinedOptions(), $inheritedOptions); - } - } -} diff --git a/lib/symfony/form/Console/Descriptor/JsonDescriptor.php b/lib/symfony/form/Console/Descriptor/JsonDescriptor.php deleted file mode 100644 index d40561e46..000000000 --- a/lib/symfony/form/Console/Descriptor/JsonDescriptor.php +++ /dev/null @@ -1,118 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Console\Descriptor; - -use Symfony\Component\Form\ResolvedFormTypeInterface; -use Symfony\Component\OptionsResolver\OptionsResolver; - -/** - * @author Yonel Ceruto <yonelceruto@gmail.com> - * - * @internal - */ -class JsonDescriptor extends Descriptor -{ - protected function describeDefaults(array $options) - { - $data['builtin_form_types'] = $options['core_types']; - $data['service_form_types'] = $options['service_types']; - if (!$options['show_deprecated']) { - $data['type_extensions'] = $options['extensions']; - $data['type_guessers'] = $options['guessers']; - } - - $this->writeData($data, $options); - } - - protected function describeResolvedFormType(ResolvedFormTypeInterface $resolvedFormType, array $options = []) - { - $this->collectOptions($resolvedFormType); - - if ($options['show_deprecated']) { - $this->filterOptionsByDeprecated($resolvedFormType); - } - - $formOptions = [ - 'own' => $this->ownOptions, - 'overridden' => $this->overriddenOptions, - 'parent' => $this->parentOptions, - 'extension' => $this->extensionOptions, - 'required' => $this->requiredOptions, - ]; - $this->sortOptions($formOptions); - - $data = [ - 'class' => \get_class($resolvedFormType->getInnerType()), - 'block_prefix' => $resolvedFormType->getInnerType()->getBlockPrefix(), - 'options' => $formOptions, - 'parent_types' => $this->parents, - 'type_extensions' => $this->extensions, - ]; - - $this->writeData($data, $options); - } - - protected function describeOption(OptionsResolver $optionsResolver, array $options) - { - $definition = $this->getOptionDefinition($optionsResolver, $options['option']); - - $map = []; - if ($definition['deprecated']) { - $map['deprecated'] = 'deprecated'; - if (\is_string($definition['deprecationMessage'])) { - $map['deprecation_message'] = 'deprecationMessage'; - } - } - $map += [ - 'info' => 'info', - 'required' => 'required', - 'default' => 'default', - 'allowed_types' => 'allowedTypes', - 'allowed_values' => 'allowedValues', - ]; - foreach ($map as $label => $name) { - if (\array_key_exists($name, $definition)) { - $data[$label] = $definition[$name]; - - if ('default' === $name) { - $data['is_lazy'] = isset($definition['lazy']); - } - } - } - $data['has_normalizer'] = isset($definition['normalizers']); - - $this->writeData($data, $options); - } - - private function writeData(array $data, array $options) - { - $flags = $options['json_encoding'] ?? 0; - - $this->output->write(json_encode($data, $flags | \JSON_PRETTY_PRINT)."\n"); - } - - private function sortOptions(array &$options) - { - foreach ($options as &$opts) { - $sorted = false; - foreach ($opts as &$opt) { - if (\is_array($opt)) { - sort($opt); - $sorted = true; - } - } - if (!$sorted) { - sort($opts); - } - } - } -} diff --git a/lib/symfony/form/Console/Descriptor/TextDescriptor.php b/lib/symfony/form/Console/Descriptor/TextDescriptor.php deleted file mode 100644 index 4862a674c..000000000 --- a/lib/symfony/form/Console/Descriptor/TextDescriptor.php +++ /dev/null @@ -1,222 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Console\Descriptor; - -use Symfony\Component\Console\Helper\Dumper; -use Symfony\Component\Console\Helper\TableSeparator; -use Symfony\Component\Form\ResolvedFormTypeInterface; -use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; -use Symfony\Component\OptionsResolver\OptionsResolver; - -/** - * @author Yonel Ceruto <yonelceruto@gmail.com> - * - * @internal - */ -class TextDescriptor extends Descriptor -{ - private $fileLinkFormatter; - - public function __construct(FileLinkFormatter $fileLinkFormatter = null) - { - $this->fileLinkFormatter = $fileLinkFormatter; - } - - protected function describeDefaults(array $options) - { - if ($options['core_types']) { - $this->output->section('Built-in form types (Symfony\Component\Form\Extension\Core\Type)'); - $shortClassNames = array_map(function ($fqcn) { - return $this->formatClassLink($fqcn, \array_slice(explode('\\', $fqcn), -1)[0]); - }, $options['core_types']); - for ($i = 0, $loopsMax = \count($shortClassNames); $i * 5 < $loopsMax; ++$i) { - $this->output->writeln(' '.implode(', ', \array_slice($shortClassNames, $i * 5, 5))); - } - } - - if ($options['service_types']) { - $this->output->section('Service form types'); - $this->output->listing(array_map([$this, 'formatClassLink'], $options['service_types'])); - } - - if (!$options['show_deprecated']) { - if ($options['extensions']) { - $this->output->section('Type extensions'); - $this->output->listing(array_map([$this, 'formatClassLink'], $options['extensions'])); - } - - if ($options['guessers']) { - $this->output->section('Type guessers'); - $this->output->listing(array_map([$this, 'formatClassLink'], $options['guessers'])); - } - } - } - - protected function describeResolvedFormType(ResolvedFormTypeInterface $resolvedFormType, array $options = []) - { - $this->collectOptions($resolvedFormType); - - if ($options['show_deprecated']) { - $this->filterOptionsByDeprecated($resolvedFormType); - } - - $formOptions = $this->normalizeAndSortOptionsColumns(array_filter([ - 'own' => $this->ownOptions, - 'overridden' => $this->overriddenOptions, - 'parent' => $this->parentOptions, - 'extension' => $this->extensionOptions, - ])); - - // setting headers and column order - $tableHeaders = array_intersect_key([ - 'own' => 'Options', - 'overridden' => 'Overridden options', - 'parent' => 'Parent options', - 'extension' => 'Extension options', - ], $formOptions); - - $this->output->title(sprintf('%s (Block prefix: "%s")', \get_class($resolvedFormType->getInnerType()), $resolvedFormType->getInnerType()->getBlockPrefix())); - - if ($formOptions) { - $this->output->table($tableHeaders, $this->buildTableRows($tableHeaders, $formOptions)); - } - - if ($this->parents) { - $this->output->section('Parent types'); - $this->output->listing(array_map([$this, 'formatClassLink'], $this->parents)); - } - - if ($this->extensions) { - $this->output->section('Type extensions'); - $this->output->listing(array_map([$this, 'formatClassLink'], $this->extensions)); - } - } - - protected function describeOption(OptionsResolver $optionsResolver, array $options) - { - $definition = $this->getOptionDefinition($optionsResolver, $options['option']); - - $dump = new Dumper($this->output); - $map = []; - if ($definition['deprecated']) { - $map = [ - 'Deprecated' => 'deprecated', - 'Deprecation package' => 'deprecationPackage', - 'Deprecation version' => 'deprecationVersion', - 'Deprecation message' => 'deprecationMessage', - ]; - } - $map += [ - 'Info' => 'info', - 'Required' => 'required', - 'Default' => 'default', - 'Allowed types' => 'allowedTypes', - 'Allowed values' => 'allowedValues', - 'Normalizers' => 'normalizers', - ]; - $rows = []; - foreach ($map as $label => $name) { - $value = \array_key_exists($name, $definition) ? $dump($definition[$name]) : '-'; - if ('default' === $name && isset($definition['lazy'])) { - $value = "Value: $value\n\nClosure(s): ".$dump($definition['lazy']); - } - - $rows[] = ["<info>$label</info>", $value]; - $rows[] = new TableSeparator(); - } - array_pop($rows); - - $this->output->title(sprintf('%s (%s)', \get_class($options['type']), $options['option'])); - $this->output->table([], $rows); - } - - private function buildTableRows(array $headers, array $options): array - { - $tableRows = []; - $count = \count(max($options)); - for ($i = 0; $i < $count; ++$i) { - $cells = []; - foreach (array_keys($headers) as $group) { - $option = $options[$group][$i] ?? null; - if (\is_string($option) && \in_array($option, $this->requiredOptions, true)) { - $option .= ' <info>(required)</info>'; - } - $cells[] = $option; - } - $tableRows[] = $cells; - } - - return $tableRows; - } - - private function normalizeAndSortOptionsColumns(array $options): array - { - foreach ($options as $group => $opts) { - $sorted = false; - foreach ($opts as $class => $opt) { - if (\is_string($class)) { - unset($options[$group][$class]); - } - - if (!\is_array($opt) || 0 === \count($opt)) { - continue; - } - - if (!$sorted) { - $options[$group] = []; - } else { - $options[$group][] = null; - } - $options[$group][] = sprintf('<info>%s</info>', (new \ReflectionClass($class))->getShortName()); - $options[$group][] = new TableSeparator(); - - sort($opt); - $sorted = true; - $options[$group] = array_merge($options[$group], $opt); - } - - if (!$sorted) { - sort($options[$group]); - } - } - - return $options; - } - - private function formatClassLink(string $class, string $text = null): string - { - if (null === $text) { - $text = $class; - } - - if ('' === $fileLink = $this->getFileLink($class)) { - return $text; - } - - return sprintf('<href=%s>%s</>', $fileLink, $text); - } - - private function getFileLink(string $class): string - { - if (null === $this->fileLinkFormatter) { - return ''; - } - - try { - $r = new \ReflectionClass($class); - } catch (\ReflectionException $e) { - return ''; - } - - return (string) $this->fileLinkFormatter->format($r->getFileName(), $r->getStartLine()); - } -} diff --git a/lib/symfony/form/Console/Helper/DescriptorHelper.php b/lib/symfony/form/Console/Helper/DescriptorHelper.php deleted file mode 100644 index 355fb9598..000000000 --- a/lib/symfony/form/Console/Helper/DescriptorHelper.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Console\Helper; - -use Symfony\Component\Console\Helper\DescriptorHelper as BaseDescriptorHelper; -use Symfony\Component\Form\Console\Descriptor\JsonDescriptor; -use Symfony\Component\Form\Console\Descriptor\TextDescriptor; -use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; - -/** - * @author Yonel Ceruto <yonelceruto@gmail.com> - * - * @internal - */ -class DescriptorHelper extends BaseDescriptorHelper -{ - public function __construct(FileLinkFormatter $fileLinkFormatter = null) - { - $this - ->register('txt', new TextDescriptor($fileLinkFormatter)) - ->register('json', new JsonDescriptor()) - ; - } -} diff --git a/lib/symfony/form/DataAccessorInterface.php b/lib/symfony/form/DataAccessorInterface.php deleted file mode 100644 index a5b4bc817..000000000 --- a/lib/symfony/form/DataAccessorInterface.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -/** - * Writes and reads values to/from an object or array bound to a form. - * - * @author Yonel Ceruto <yonelceruto@gmail.com> - */ -interface DataAccessorInterface -{ - /** - * Returns the value at the end of the property of the object graph. - * - * @param object|array $viewData The view data of the compound form - * @param FormInterface $form The {@link FormInterface()} instance to check - * - * @return mixed - * - * @throws Exception\AccessException If unable to read from the given form data - */ - public function getValue($viewData, FormInterface $form); - - /** - * Sets the value at the end of the property of the object graph. - * - * @param object|array $viewData The view data of the compound form - * @param mixed $value The value to set at the end of the object graph - * @param FormInterface $form The {@link FormInterface()} instance to check - * - * @throws Exception\AccessException If unable to write the given value - */ - public function setValue(&$viewData, $value, FormInterface $form): void; - - /** - * Returns whether a value can be read from an object graph. - * - * Whenever this method returns true, {@link getValue()} is guaranteed not - * to throw an exception when called with the same arguments. - * - * @param object|array $viewData The view data of the compound form - * @param FormInterface $form The {@link FormInterface()} instance to check - */ - public function isReadable($viewData, FormInterface $form): bool; - - /** - * Returns whether a value can be written at a given object graph. - * - * Whenever this method returns true, {@link setValue()} is guaranteed not - * to throw an exception when called with the same arguments. - * - * @param object|array $viewData The view data of the compound form - * @param FormInterface $form The {@link FormInterface()} instance to check - */ - public function isWritable($viewData, FormInterface $form): bool; -} diff --git a/lib/symfony/form/DataMapperInterface.php b/lib/symfony/form/DataMapperInterface.php deleted file mode 100644 index c2cd3601e..000000000 --- a/lib/symfony/form/DataMapperInterface.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface DataMapperInterface -{ - /** - * Maps the view data of a compound form to its children. - * - * The method is responsible for calling {@link FormInterface::setData()} - * on the children of compound forms, defining their underlying model data. - * - * @param mixed $viewData View data of the compound form being initialized - * @param FormInterface[]|\Traversable $forms A list of {@link FormInterface} instances - * - * @throws Exception\UnexpectedTypeException if the type of the data parameter is not supported - */ - public function mapDataToForms($viewData, \Traversable $forms); - - /** - * Maps the model data of a list of children forms into the view data of their parent. - * - * This is the internal cascade call of FormInterface::submit for compound forms, since they - * cannot be bound to any input nor the request as scalar, but their children may: - * - * $compoundForm->submit($arrayOfChildrenViewData) - * // inside: - * $childForm->submit($childViewData); - * // for each entry, do the same and/or reverse transform - * $this->dataMapper->mapFormsToData($compoundForm, $compoundInitialViewData) - * // then reverse transform - * - * When a simple form is submitted the following is happening: - * - * $simpleForm->submit($submittedViewData) - * // inside: - * $this->viewData = $submittedViewData - * // then reverse transform - * - * The model data can be an array or an object, so this second argument is always passed - * by reference. - * - * @param FormInterface[]|\Traversable $forms A list of {@link FormInterface} instances - * @param mixed $viewData The compound form's view data that get mapped - * its children model data - * - * @throws Exception\UnexpectedTypeException if the type of the data parameter is not supported - */ - public function mapFormsToData(\Traversable $forms, &$viewData); -} diff --git a/lib/symfony/form/DataTransformerInterface.php b/lib/symfony/form/DataTransformerInterface.php deleted file mode 100644 index 5f4842847..000000000 --- a/lib/symfony/form/DataTransformerInterface.php +++ /dev/null @@ -1,92 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\Form\Exception\TransformationFailedException; - -/** - * Transforms a value between different representations. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface DataTransformerInterface -{ - /** - * Transforms a value from the original representation to a transformed representation. - * - * This method is called when the form field is initialized with its default data, on - * two occasions for two types of transformers: - * - * 1. Model transformers which normalize the model data. - * This is mainly useful when the same form type (the same configuration) - * has to handle different kind of underlying data, e.g The DateType can - * deal with strings or \DateTime objects as input. - * - * 2. View transformers which adapt the normalized data to the view format. - * a/ When the form is simple, the value returned by convention is used - * directly in the view and thus can only be a string or an array. In - * this case the data class should be null. - * - * b/ When the form is compound the returned value should be an array or - * an object to be mapped to the children. Each property of the compound - * data will be used as model data by each child and will be transformed - * too. In this case data class should be the class of the object, or null - * when it is an array. - * - * All transformers are called in a configured order from model data to view value. - * At the end of this chain the view data will be validated against the data class - * setting. - * - * This method must be able to deal with empty values. Usually this will - * be NULL, but depending on your implementation other empty values are - * possible as well (such as empty strings). The reasoning behind this is - * that data transformers must be chainable. If the transform() method - * of the first data transformer outputs NULL, the second must be able to - * process that value. - * - * @param mixed $value The value in the original representation - * - * @return mixed - * - * @throws TransformationFailedException when the transformation fails - */ - public function transform($value); - - /** - * Transforms a value from the transformed representation to its original - * representation. - * - * This method is called when {@link Form::submit()} is called to transform the requests tainted data - * into an acceptable format. - * - * The same transformers are called in the reverse order so the responsibility is to - * return one of the types that would be expected as input of transform(). - * - * This method must be able to deal with empty values. Usually this will - * be an empty string, but depending on your implementation other empty - * values are possible as well (such as NULL). The reasoning behind - * this is that value transformers must be chainable. If the - * reverseTransform() method of the first value transformer outputs an - * empty string, the second value transformer must be able to process that - * value. - * - * By convention, reverseTransform() should return NULL if an empty string - * is passed. - * - * @param mixed $value The value in the transformed representation - * - * @return mixed - * - * @throws TransformationFailedException when the transformation fails - */ - public function reverseTransform($value); -} diff --git a/lib/symfony/form/DependencyInjection/FormPass.php b/lib/symfony/form/DependencyInjection/FormPass.php deleted file mode 100644 index 0ba46117c..000000000 --- a/lib/symfony/form/DependencyInjection/FormPass.php +++ /dev/null @@ -1,146 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\DependencyInjection; - -use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; -use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Adds all services with the tags "form.type", "form.type_extension" and - * "form.type_guesser" as arguments of the "form.extension" service. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class FormPass implements CompilerPassInterface -{ - use PriorityTaggedServiceTrait; - - private $formExtensionService; - private $formTypeTag; - private $formTypeExtensionTag; - private $formTypeGuesserTag; - private $formDebugCommandService; - - public function __construct(string $formExtensionService = 'form.extension', string $formTypeTag = 'form.type', string $formTypeExtensionTag = 'form.type_extension', string $formTypeGuesserTag = 'form.type_guesser', string $formDebugCommandService = 'console.command.form_debug') - { - if (0 < \func_num_args()) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->formExtensionService = $formExtensionService; - $this->formTypeTag = $formTypeTag; - $this->formTypeExtensionTag = $formTypeExtensionTag; - $this->formTypeGuesserTag = $formTypeGuesserTag; - $this->formDebugCommandService = $formDebugCommandService; - } - - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition($this->formExtensionService)) { - return; - } - - $definition = $container->getDefinition($this->formExtensionService); - $definition->replaceArgument(0, $this->processFormTypes($container)); - $definition->replaceArgument(1, $this->processFormTypeExtensions($container)); - $definition->replaceArgument(2, $this->processFormTypeGuessers($container)); - } - - private function processFormTypes(ContainerBuilder $container): Reference - { - // Get service locator argument - $servicesMap = []; - $namespaces = ['Symfony\Component\Form\Extension\Core\Type' => true]; - - // Builds an array with fully-qualified type class names as keys and service IDs as values - foreach ($container->findTaggedServiceIds($this->formTypeTag, true) as $serviceId => $tag) { - // Add form type service to the service locator - $serviceDefinition = $container->getDefinition($serviceId); - $servicesMap[$formType = $serviceDefinition->getClass()] = new Reference($serviceId); - $namespaces[substr($formType, 0, strrpos($formType, '\\'))] = true; - } - - if ($container->hasDefinition($this->formDebugCommandService)) { - $commandDefinition = $container->getDefinition($this->formDebugCommandService); - $commandDefinition->setArgument(1, array_keys($namespaces)); - $commandDefinition->setArgument(2, array_keys($servicesMap)); - } - - return ServiceLocatorTagPass::register($container, $servicesMap); - } - - private function processFormTypeExtensions(ContainerBuilder $container): array - { - $typeExtensions = []; - $typeExtensionsClasses = []; - foreach ($this->findAndSortTaggedServices($this->formTypeExtensionTag, $container) as $reference) { - $serviceId = (string) $reference; - $serviceDefinition = $container->getDefinition($serviceId); - - $tag = $serviceDefinition->getTag($this->formTypeExtensionTag); - $typeExtensionClass = $container->getParameterBag()->resolveValue($serviceDefinition->getClass()); - - if (isset($tag[0]['extended_type'])) { - $typeExtensions[$tag[0]['extended_type']][] = new Reference($serviceId); - $typeExtensionsClasses[] = $typeExtensionClass; - } else { - $extendsTypes = false; - - $typeExtensionsClasses[] = $typeExtensionClass; - foreach ($typeExtensionClass::getExtendedTypes() as $extendedType) { - $typeExtensions[$extendedType][] = new Reference($serviceId); - $extendsTypes = true; - } - - if (!$extendsTypes) { - throw new InvalidArgumentException(sprintf('The getExtendedTypes() method for service "%s" does not return any extended types.', $serviceId)); - } - } - } - - foreach ($typeExtensions as $extendedType => $extensions) { - $typeExtensions[$extendedType] = new IteratorArgument($extensions); - } - - if ($container->hasDefinition($this->formDebugCommandService)) { - $commandDefinition = $container->getDefinition($this->formDebugCommandService); - $commandDefinition->setArgument(3, $typeExtensionsClasses); - } - - return $typeExtensions; - } - - private function processFormTypeGuessers(ContainerBuilder $container): ArgumentInterface - { - $guessers = []; - $guessersClasses = []; - foreach ($container->findTaggedServiceIds($this->formTypeGuesserTag, true) as $serviceId => $tags) { - $guessers[] = new Reference($serviceId); - - $serviceDefinition = $container->getDefinition($serviceId); - $guessersClasses[] = $serviceDefinition->getClass(); - } - - if ($container->hasDefinition($this->formDebugCommandService)) { - $commandDefinition = $container->getDefinition($this->formDebugCommandService); - $commandDefinition->setArgument(4, $guessersClasses); - } - - return new IteratorArgument($guessers); - } -} diff --git a/lib/symfony/form/Event/PostSetDataEvent.php b/lib/symfony/form/Event/PostSetDataEvent.php deleted file mode 100644 index eef537452..000000000 --- a/lib/symfony/form/Event/PostSetDataEvent.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Event; - -use Symfony\Component\Form\FormEvent; - -/** - * This event is dispatched at the end of the Form::setData() method. - * - * This event is mostly here for reading data after having pre-populated the form. - */ -final class PostSetDataEvent extends FormEvent -{ -} diff --git a/lib/symfony/form/Event/PostSubmitEvent.php b/lib/symfony/form/Event/PostSubmitEvent.php deleted file mode 100644 index aa3775f5c..000000000 --- a/lib/symfony/form/Event/PostSubmitEvent.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Event; - -use Symfony\Component\Form\FormEvent; - -/** - * This event is dispatched after the Form::submit() - * once the model and view data have been denormalized. - * - * It can be used to fetch data after denormalization. - */ -final class PostSubmitEvent extends FormEvent -{ -} diff --git a/lib/symfony/form/Event/PreSetDataEvent.php b/lib/symfony/form/Event/PreSetDataEvent.php deleted file mode 100644 index 5450400e0..000000000 --- a/lib/symfony/form/Event/PreSetDataEvent.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Event; - -use Symfony\Component\Form\FormEvent; - -/** - * This event is dispatched at the beginning of the Form::setData() method. - * - * It can be used to: - * - Modify the data given during pre-population; - * - Modify a form depending on the pre-populated data (adding or removing fields dynamically). - */ -final class PreSetDataEvent extends FormEvent -{ -} diff --git a/lib/symfony/form/Event/PreSubmitEvent.php b/lib/symfony/form/Event/PreSubmitEvent.php deleted file mode 100644 index a72ac5d16..000000000 --- a/lib/symfony/form/Event/PreSubmitEvent.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Event; - -use Symfony\Component\Form\FormEvent; - -/** - * This event is dispatched at the beginning of the Form::submit() method. - * - * It can be used to: - * - Change data from the request, before submitting the data to the form. - * - Add or remove form fields, before submitting the data to the form. - */ -final class PreSubmitEvent extends FormEvent -{ -} diff --git a/lib/symfony/form/Event/SubmitEvent.php b/lib/symfony/form/Event/SubmitEvent.php deleted file mode 100644 index 71d3b06d4..000000000 --- a/lib/symfony/form/Event/SubmitEvent.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Event; - -use Symfony\Component\Form\FormEvent; - -/** - * This event is dispatched just before the Form::submit() method - * transforms back the normalized data to the model and view data. - * - * It can be used to change data from the normalized representation of the data. - */ -final class SubmitEvent extends FormEvent -{ -} diff --git a/lib/symfony/form/Exception/AccessException.php b/lib/symfony/form/Exception/AccessException.php deleted file mode 100644 index ac712cc3d..000000000 --- a/lib/symfony/form/Exception/AccessException.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Exception; - -class AccessException extends RuntimeException -{ -} diff --git a/lib/symfony/form/Exception/AlreadySubmittedException.php b/lib/symfony/form/Exception/AlreadySubmittedException.php deleted file mode 100644 index 5e8c30526..000000000 --- a/lib/symfony/form/Exception/AlreadySubmittedException.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Exception; - -/** - * Thrown when an operation is called that is not acceptable after submitting - * a form. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class AlreadySubmittedException extends LogicException -{ -} diff --git a/lib/symfony/form/Exception/BadMethodCallException.php b/lib/symfony/form/Exception/BadMethodCallException.php deleted file mode 100644 index 27649dd02..000000000 --- a/lib/symfony/form/Exception/BadMethodCallException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Exception; - -/** - * Base BadMethodCallException for the Form component. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface -{ -} diff --git a/lib/symfony/form/Exception/ErrorMappingException.php b/lib/symfony/form/Exception/ErrorMappingException.php deleted file mode 100644 index a69684926..000000000 --- a/lib/symfony/form/Exception/ErrorMappingException.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Exception; - -class ErrorMappingException extends RuntimeException -{ -} diff --git a/lib/symfony/form/Exception/ExceptionInterface.php b/lib/symfony/form/Exception/ExceptionInterface.php deleted file mode 100644 index 69145f0bc..000000000 --- a/lib/symfony/form/Exception/ExceptionInterface.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Exception; - -/** - * Base ExceptionInterface for the Form component. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface ExceptionInterface extends \Throwable -{ -} diff --git a/lib/symfony/form/Exception/InvalidArgumentException.php b/lib/symfony/form/Exception/InvalidArgumentException.php deleted file mode 100644 index a270e0ce9..000000000 --- a/lib/symfony/form/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Exception; - -/** - * Base InvalidArgumentException for the Form component. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/lib/symfony/form/Exception/InvalidConfigurationException.php b/lib/symfony/form/Exception/InvalidConfigurationException.php deleted file mode 100644 index daa0c42f5..000000000 --- a/lib/symfony/form/Exception/InvalidConfigurationException.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Exception; - -class InvalidConfigurationException extends InvalidArgumentException -{ -} diff --git a/lib/symfony/form/Exception/LogicException.php b/lib/symfony/form/Exception/LogicException.php deleted file mode 100644 index 848780215..000000000 --- a/lib/symfony/form/Exception/LogicException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Exception; - -/** - * Base LogicException for Form component. - * - * @author Alexander Kotynia <aleksander.kot@gmail.com> - */ -class LogicException extends \LogicException implements ExceptionInterface -{ -} diff --git a/lib/symfony/form/Exception/OutOfBoundsException.php b/lib/symfony/form/Exception/OutOfBoundsException.php deleted file mode 100644 index 44d311663..000000000 --- a/lib/symfony/form/Exception/OutOfBoundsException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Exception; - -/** - * Base OutOfBoundsException for Form component. - * - * @author Alexander Kotynia <aleksander.kot@gmail.com> - */ -class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface -{ -} diff --git a/lib/symfony/form/Exception/RuntimeException.php b/lib/symfony/form/Exception/RuntimeException.php deleted file mode 100644 index 0af48a4a2..000000000 --- a/lib/symfony/form/Exception/RuntimeException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Exception; - -/** - * Base RuntimeException for the Form component. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class RuntimeException extends \RuntimeException implements ExceptionInterface -{ -} diff --git a/lib/symfony/form/Exception/StringCastException.php b/lib/symfony/form/Exception/StringCastException.php deleted file mode 100644 index f9b51d604..000000000 --- a/lib/symfony/form/Exception/StringCastException.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Exception; - -class StringCastException extends RuntimeException -{ -} diff --git a/lib/symfony/form/Exception/TransformationFailedException.php b/lib/symfony/form/Exception/TransformationFailedException.php deleted file mode 100644 index 89eba088e..000000000 --- a/lib/symfony/form/Exception/TransformationFailedException.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Exception; - -/** - * Indicates a value transformation error. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class TransformationFailedException extends RuntimeException -{ - private $invalidMessage; - private $invalidMessageParameters; - - public function __construct(string $message = '', int $code = 0, \Throwable $previous = null, string $invalidMessage = null, array $invalidMessageParameters = []) - { - parent::__construct($message, $code, $previous); - - $this->setInvalidMessage($invalidMessage, $invalidMessageParameters); - } - - /** - * Sets the message that will be shown to the user. - * - * @param string|null $invalidMessage The message or message key - * @param array $invalidMessageParameters Data to be passed into the translator - */ - public function setInvalidMessage(string $invalidMessage = null, array $invalidMessageParameters = []): void - { - $this->invalidMessage = $invalidMessage; - $this->invalidMessageParameters = $invalidMessageParameters; - } - - public function getInvalidMessage(): ?string - { - return $this->invalidMessage; - } - - public function getInvalidMessageParameters(): array - { - return $this->invalidMessageParameters; - } -} diff --git a/lib/symfony/form/Exception/UnexpectedTypeException.php b/lib/symfony/form/Exception/UnexpectedTypeException.php deleted file mode 100644 index d25d4705f..000000000 --- a/lib/symfony/form/Exception/UnexpectedTypeException.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Exception; - -class UnexpectedTypeException extends InvalidArgumentException -{ - public function __construct($value, string $expectedType) - { - parent::__construct(sprintf('Expected argument of type "%s", "%s" given', $expectedType, get_debug_type($value))); - } -} diff --git a/lib/symfony/form/Extension/Core/CoreExtension.php b/lib/symfony/form/Extension/Core/CoreExtension.php deleted file mode 100644 index c6768b86b..000000000 --- a/lib/symfony/form/Extension/Core/CoreExtension.php +++ /dev/null @@ -1,89 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core; - -use Symfony\Component\Form\AbstractExtension; -use Symfony\Component\Form\ChoiceList\Factory\CachingFactoryDecorator; -use Symfony\Component\Form\ChoiceList\Factory\ChoiceListFactoryInterface; -use Symfony\Component\Form\ChoiceList\Factory\DefaultChoiceListFactory; -use Symfony\Component\Form\ChoiceList\Factory\PropertyAccessDecorator; -use Symfony\Component\Form\Extension\Core\Type\TransformationFailureExtension; -use Symfony\Component\PropertyAccess\PropertyAccess; -use Symfony\Component\PropertyAccess\PropertyAccessorInterface; -use Symfony\Contracts\Translation\TranslatorInterface; - -/** - * Represents the main form extension, which loads the core functionality. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class CoreExtension extends AbstractExtension -{ - private $propertyAccessor; - private $choiceListFactory; - private $translator; - - public function __construct(PropertyAccessorInterface $propertyAccessor = null, ChoiceListFactoryInterface $choiceListFactory = null, TranslatorInterface $translator = null) - { - $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); - $this->choiceListFactory = $choiceListFactory ?? new CachingFactoryDecorator(new PropertyAccessDecorator(new DefaultChoiceListFactory(), $this->propertyAccessor)); - $this->translator = $translator; - } - - protected function loadTypes() - { - return [ - new Type\FormType($this->propertyAccessor), - new Type\BirthdayType(), - new Type\CheckboxType(), - new Type\ChoiceType($this->choiceListFactory, $this->translator), - new Type\CollectionType(), - new Type\CountryType(), - new Type\DateIntervalType(), - new Type\DateType(), - new Type\DateTimeType(), - new Type\EmailType(), - new Type\HiddenType(), - new Type\IntegerType(), - new Type\LanguageType(), - new Type\LocaleType(), - new Type\MoneyType(), - new Type\NumberType(), - new Type\PasswordType(), - new Type\PercentType(), - new Type\RadioType(), - new Type\RangeType(), - new Type\RepeatedType(), - new Type\SearchType(), - new Type\TextareaType(), - new Type\TextType(), - new Type\TimeType(), - new Type\TimezoneType(), - new Type\UrlType(), - new Type\FileType($this->translator), - new Type\ButtonType(), - new Type\SubmitType(), - new Type\ResetType(), - new Type\CurrencyType(), - new Type\TelType(), - new Type\ColorType($this->translator), - new Type\WeekType(), - ]; - } - - protected function loadTypeExtensions() - { - return [ - new TransformationFailureExtension($this->translator), - ]; - } -} diff --git a/lib/symfony/form/Extension/Core/DataAccessor/CallbackAccessor.php b/lib/symfony/form/Extension/Core/DataAccessor/CallbackAccessor.php deleted file mode 100644 index fb121450a..000000000 --- a/lib/symfony/form/Extension/Core/DataAccessor/CallbackAccessor.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataAccessor; - -use Symfony\Component\Form\DataAccessorInterface; -use Symfony\Component\Form\Exception\AccessException; -use Symfony\Component\Form\FormInterface; - -/** - * Writes and reads values to/from an object or array using callback functions. - * - * @author Yonel Ceruto <yonelceruto@gmail.com> - */ -class CallbackAccessor implements DataAccessorInterface -{ - /** - * {@inheritdoc} - */ - public function getValue($data, FormInterface $form) - { - if (null === $getter = $form->getConfig()->getOption('getter')) { - throw new AccessException('Unable to read from the given form data as no getter is defined.'); - } - - return ($getter)($data, $form); - } - - /** - * {@inheritdoc} - */ - public function setValue(&$data, $value, FormInterface $form): void - { - if (null === $setter = $form->getConfig()->getOption('setter')) { - throw new AccessException('Unable to write the given value as no setter is defined.'); - } - - ($setter)($data, $form->getData(), $form); - } - - /** - * {@inheritdoc} - */ - public function isReadable($data, FormInterface $form): bool - { - return null !== $form->getConfig()->getOption('getter'); - } - - /** - * {@inheritdoc} - */ - public function isWritable($data, FormInterface $form): bool - { - return null !== $form->getConfig()->getOption('setter'); - } -} diff --git a/lib/symfony/form/Extension/Core/DataAccessor/ChainAccessor.php b/lib/symfony/form/Extension/Core/DataAccessor/ChainAccessor.php deleted file mode 100644 index 39e444bb7..000000000 --- a/lib/symfony/form/Extension/Core/DataAccessor/ChainAccessor.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataAccessor; - -use Symfony\Component\Form\DataAccessorInterface; -use Symfony\Component\Form\Exception\AccessException; -use Symfony\Component\Form\FormInterface; - -/** - * @author Yonel Ceruto <yonelceruto@gmail.com> - */ -class ChainAccessor implements DataAccessorInterface -{ - private $accessors; - - /** - * @param DataAccessorInterface[]|iterable $accessors - */ - public function __construct(iterable $accessors) - { - $this->accessors = $accessors; - } - - /** - * {@inheritdoc} - */ - public function getValue($data, FormInterface $form) - { - foreach ($this->accessors as $accessor) { - if ($accessor->isReadable($data, $form)) { - return $accessor->getValue($data, $form); - } - } - - throw new AccessException('Unable to read from the given form data as no accessor in the chain is able to read the data.'); - } - - /** - * {@inheritdoc} - */ - public function setValue(&$data, $value, FormInterface $form): void - { - foreach ($this->accessors as $accessor) { - if ($accessor->isWritable($data, $form)) { - $accessor->setValue($data, $value, $form); - - return; - } - } - - throw new AccessException('Unable to write the given value as no accessor in the chain is able to set the data.'); - } - - /** - * {@inheritdoc} - */ - public function isReadable($data, FormInterface $form): bool - { - foreach ($this->accessors as $accessor) { - if ($accessor->isReadable($data, $form)) { - return true; - } - } - - return false; - } - - /** - * {@inheritdoc} - */ - public function isWritable($data, FormInterface $form): bool - { - foreach ($this->accessors as $accessor) { - if ($accessor->isWritable($data, $form)) { - return true; - } - } - - return false; - } -} diff --git a/lib/symfony/form/Extension/Core/DataAccessor/PropertyPathAccessor.php b/lib/symfony/form/Extension/Core/DataAccessor/PropertyPathAccessor.php deleted file mode 100644 index 3c97075e5..000000000 --- a/lib/symfony/form/Extension/Core/DataAccessor/PropertyPathAccessor.php +++ /dev/null @@ -1,108 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataAccessor; - -use Symfony\Component\Form\DataAccessorInterface; -use Symfony\Component\Form\Exception\AccessException; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\PropertyAccess\Exception\AccessException as PropertyAccessException; -use Symfony\Component\PropertyAccess\Exception\NoSuchIndexException; -use Symfony\Component\PropertyAccess\Exception\UninitializedPropertyException; -use Symfony\Component\PropertyAccess\PropertyAccess; -use Symfony\Component\PropertyAccess\PropertyAccessorInterface; -use Symfony\Component\PropertyAccess\PropertyPathInterface; - -/** - * Writes and reads values to/from an object or array using property path. - * - * @author Yonel Ceruto <yonelceruto@gmail.com> - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class PropertyPathAccessor implements DataAccessorInterface -{ - private $propertyAccessor; - - public function __construct(PropertyAccessorInterface $propertyAccessor = null) - { - $this->propertyAccessor = $propertyAccessor ?? PropertyAccess::createPropertyAccessor(); - } - - /** - * {@inheritdoc} - */ - public function getValue($data, FormInterface $form) - { - if (null === $propertyPath = $form->getPropertyPath()) { - throw new AccessException('Unable to read from the given form data as no property path is defined.'); - } - - return $this->getPropertyValue($data, $propertyPath); - } - - /** - * {@inheritdoc} - */ - public function setValue(&$data, $propertyValue, FormInterface $form): void - { - if (null === $propertyPath = $form->getPropertyPath()) { - throw new AccessException('Unable to write the given value as no property path is defined.'); - } - - // If the field is of type DateTimeInterface and the data is the same skip the update to - // keep the original object hash - if ($propertyValue instanceof \DateTimeInterface && $propertyValue == $this->getPropertyValue($data, $propertyPath)) { - return; - } - - // If the data is identical to the value in $data, we are - // dealing with a reference - if (!\is_object($data) || !$form->getConfig()->getByReference() || $propertyValue !== $this->getPropertyValue($data, $propertyPath)) { - $this->propertyAccessor->setValue($data, $propertyPath, $propertyValue); - } - } - - /** - * {@inheritdoc} - */ - public function isReadable($data, FormInterface $form): bool - { - return null !== $form->getPropertyPath(); - } - - /** - * {@inheritdoc} - */ - public function isWritable($data, FormInterface $form): bool - { - return null !== $form->getPropertyPath(); - } - - private function getPropertyValue($data, PropertyPathInterface $propertyPath) - { - try { - return $this->propertyAccessor->getValue($data, $propertyPath); - } catch (PropertyAccessException $e) { - if (\is_array($data) && $e instanceof NoSuchIndexException) { - return null; - } - - if (!$e instanceof UninitializedPropertyException - // For versions without UninitializedPropertyException check the exception message - && (class_exists(UninitializedPropertyException::class) || false === strpos($e->getMessage(), 'You should initialize it')) - ) { - throw $e; - } - - return null; - } - } -} diff --git a/lib/symfony/form/Extension/Core/DataMapper/CheckboxListMapper.php b/lib/symfony/form/Extension/Core/DataMapper/CheckboxListMapper.php deleted file mode 100644 index ecfd83a06..000000000 --- a/lib/symfony/form/Extension/Core/DataMapper/CheckboxListMapper.php +++ /dev/null @@ -1,75 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataMapper; - -use Symfony\Component\Form\DataMapperInterface; -use Symfony\Component\Form\Exception\UnexpectedTypeException; - -/** - * Maps choices to/from checkbox forms. - * - * A {@link ChoiceListInterface} implementation is used to find the - * corresponding string values for the choices. Each checkbox form whose "value" - * option corresponds to any of the selected values is marked as selected. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class CheckboxListMapper implements DataMapperInterface -{ - /** - * {@inheritdoc} - */ - public function mapDataToForms($choices, iterable $checkboxes) - { - if (\is_array($checkboxes)) { - trigger_deprecation('symfony/form', '5.3', 'Passing an array as the second argument of the "%s()" method is deprecated, pass "\Traversable" instead.', __METHOD__); - } - - if (null === $choices) { - $choices = []; - } - - if (!\is_array($choices)) { - throw new UnexpectedTypeException($choices, 'array'); - } - - foreach ($checkboxes as $checkbox) { - $value = $checkbox->getConfig()->getOption('value'); - $checkbox->setData(\in_array($value, $choices, true)); - } - } - - /** - * {@inheritdoc} - */ - public function mapFormsToData(iterable $checkboxes, &$choices) - { - if (\is_array($checkboxes)) { - trigger_deprecation('symfony/form', '5.3', 'Passing an array as the first argument of the "%s()" method is deprecated, pass "\Traversable" instead.', __METHOD__); - } - - if (!\is_array($choices)) { - throw new UnexpectedTypeException($choices, 'array'); - } - - $values = []; - - foreach ($checkboxes as $checkbox) { - if ($checkbox->getData()) { - // construct an array of choice values - $values[] = $checkbox->getConfig()->getOption('value'); - } - } - - $choices = $values; - } -} diff --git a/lib/symfony/form/Extension/Core/DataMapper/DataMapper.php b/lib/symfony/form/Extension/Core/DataMapper/DataMapper.php deleted file mode 100644 index 5f4c498a3..000000000 --- a/lib/symfony/form/Extension/Core/DataMapper/DataMapper.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataMapper; - -use Symfony\Component\Form\DataAccessorInterface; -use Symfony\Component\Form\DataMapperInterface; -use Symfony\Component\Form\Exception\UnexpectedTypeException; -use Symfony\Component\Form\Extension\Core\DataAccessor\CallbackAccessor; -use Symfony\Component\Form\Extension\Core\DataAccessor\ChainAccessor; -use Symfony\Component\Form\Extension\Core\DataAccessor\PropertyPathAccessor; - -/** - * Maps arrays/objects to/from forms using data accessors. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class DataMapper implements DataMapperInterface -{ - private $dataAccessor; - - public function __construct(DataAccessorInterface $dataAccessor = null) - { - $this->dataAccessor = $dataAccessor ?? new ChainAccessor([ - new CallbackAccessor(), - new PropertyPathAccessor(), - ]); - } - - /** - * {@inheritdoc} - */ - public function mapDataToForms($data, iterable $forms): void - { - if (\is_array($forms)) { - trigger_deprecation('symfony/form', '5.3', 'Passing an array as the second argument of the "%s()" method is deprecated, pass "\Traversable" instead.', __METHOD__); - } - - $empty = null === $data || [] === $data; - - if (!$empty && !\is_array($data) && !\is_object($data)) { - throw new UnexpectedTypeException($data, 'object, array or empty'); - } - - foreach ($forms as $form) { - $config = $form->getConfig(); - - if (!$empty && $config->getMapped() && $this->dataAccessor->isReadable($data, $form)) { - $form->setData($this->dataAccessor->getValue($data, $form)); - } else { - $form->setData($config->getData()); - } - } - } - - /** - * {@inheritdoc} - */ - public function mapFormsToData(iterable $forms, &$data): void - { - if (\is_array($forms)) { - trigger_deprecation('symfony/form', '5.3', 'Passing an array as the first argument of the "%s()" method is deprecated, pass "\Traversable" instead.', __METHOD__); - } - - if (null === $data) { - return; - } - - if (!\is_array($data) && !\is_object($data)) { - throw new UnexpectedTypeException($data, 'object, array or empty'); - } - - foreach ($forms as $form) { - $config = $form->getConfig(); - - // Write-back is disabled if the form is not synchronized (transformation failed), - // if the form was not submitted and if the form is disabled (modification not allowed) - if ($config->getMapped() && $form->isSubmitted() && $form->isSynchronized() && !$form->isDisabled() && $this->dataAccessor->isWritable($data, $form)) { - $this->dataAccessor->setValue($data, $form->getData(), $form); - } - } - } -} diff --git a/lib/symfony/form/Extension/Core/DataMapper/PropertyPathMapper.php b/lib/symfony/form/Extension/Core/DataMapper/PropertyPathMapper.php deleted file mode 100644 index 4c4257cfb..000000000 --- a/lib/symfony/form/Extension/Core/DataMapper/PropertyPathMapper.php +++ /dev/null @@ -1,118 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataMapper; - -use Symfony\Component\Form\DataMapperInterface; -use Symfony\Component\Form\Exception\UnexpectedTypeException; -use Symfony\Component\PropertyAccess\Exception\AccessException; -use Symfony\Component\PropertyAccess\Exception\NoSuchIndexException; -use Symfony\Component\PropertyAccess\Exception\UninitializedPropertyException; -use Symfony\Component\PropertyAccess\PropertyAccess; -use Symfony\Component\PropertyAccess\PropertyAccessorInterface; - -trigger_deprecation('symfony/form', '5.2', 'The "%s" class is deprecated. Use "%s" instead.', PropertyPathMapper::class, DataMapper::class); - -/** - * Maps arrays/objects to/from forms using property paths. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @deprecated since symfony/form 5.2. Use {@see DataMapper} instead. - */ -class PropertyPathMapper implements DataMapperInterface -{ - private $propertyAccessor; - - public function __construct(PropertyAccessorInterface $propertyAccessor = null) - { - $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); - } - - /** - * {@inheritdoc} - */ - public function mapDataToForms($data, iterable $forms) - { - $empty = null === $data || [] === $data; - - if (!$empty && !\is_array($data) && !\is_object($data)) { - throw new UnexpectedTypeException($data, 'object, array or empty'); - } - - foreach ($forms as $form) { - $propertyPath = $form->getPropertyPath(); - $config = $form->getConfig(); - - if (!$empty && null !== $propertyPath && $config->getMapped()) { - $form->setData($this->getPropertyValue($data, $propertyPath)); - } else { - $form->setData($config->getData()); - } - } - } - - /** - * {@inheritdoc} - */ - public function mapFormsToData(iterable $forms, &$data) - { - if (null === $data) { - return; - } - - if (!\is_array($data) && !\is_object($data)) { - throw new UnexpectedTypeException($data, 'object, array or empty'); - } - - foreach ($forms as $form) { - $propertyPath = $form->getPropertyPath(); - $config = $form->getConfig(); - - // Write-back is disabled if the form is not synchronized (transformation failed), - // if the form was not submitted and if the form is disabled (modification not allowed) - if (null !== $propertyPath && $config->getMapped() && $form->isSubmitted() && $form->isSynchronized() && !$form->isDisabled()) { - $propertyValue = $form->getData(); - // If the field is of type DateTimeInterface and the data is the same skip the update to - // keep the original object hash - if ($propertyValue instanceof \DateTimeInterface && $propertyValue == $this->getPropertyValue($data, $propertyPath)) { - continue; - } - - // If the data is identical to the value in $data, we are - // dealing with a reference - if (!\is_object($data) || !$config->getByReference() || $propertyValue !== $this->getPropertyValue($data, $propertyPath)) { - $this->propertyAccessor->setValue($data, $propertyPath, $propertyValue); - } - } - } - } - - private function getPropertyValue($data, $propertyPath) - { - try { - return $this->propertyAccessor->getValue($data, $propertyPath); - } catch (AccessException $e) { - if (\is_array($data) && $e instanceof NoSuchIndexException) { - return null; - } - - if (!$e instanceof UninitializedPropertyException - // For versions without UninitializedPropertyException check the exception message - && (class_exists(UninitializedPropertyException::class) || !str_contains($e->getMessage(), 'You should initialize it')) - ) { - throw $e; - } - - return null; - } - } -} diff --git a/lib/symfony/form/Extension/Core/DataMapper/RadioListMapper.php b/lib/symfony/form/Extension/Core/DataMapper/RadioListMapper.php deleted file mode 100644 index b54adfa5d..000000000 --- a/lib/symfony/form/Extension/Core/DataMapper/RadioListMapper.php +++ /dev/null @@ -1,74 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataMapper; - -use Symfony\Component\Form\DataMapperInterface; -use Symfony\Component\Form\Exception\UnexpectedTypeException; - -/** - * Maps choices to/from radio forms. - * - * A {@link ChoiceListInterface} implementation is used to find the - * corresponding string values for the choices. The radio form whose "value" - * option corresponds to the selected value is marked as selected. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class RadioListMapper implements DataMapperInterface -{ - /** - * {@inheritdoc} - */ - public function mapDataToForms($choice, iterable $radios) - { - if (\is_array($radios)) { - trigger_deprecation('symfony/form', '5.3', 'Passing an array as the second argument of the "%s()" method is deprecated, pass "\Traversable" instead.', __METHOD__); - } - - if (!\is_string($choice)) { - throw new UnexpectedTypeException($choice, 'string'); - } - - foreach ($radios as $radio) { - $value = $radio->getConfig()->getOption('value'); - $radio->setData($choice === $value); - } - } - - /** - * {@inheritdoc} - */ - public function mapFormsToData(iterable $radios, &$choice) - { - if (\is_array($radios)) { - trigger_deprecation('symfony/form', '5.3', 'Passing an array as the first argument of the "%s()" method is deprecated, pass "\Traversable" instead.', __METHOD__); - } - - if (null !== $choice && !\is_string($choice)) { - throw new UnexpectedTypeException($choice, 'null or string'); - } - - $choice = null; - - foreach ($radios as $radio) { - if ($radio->getData()) { - if ('placeholder' === $radio->getName()) { - return; - } - - $choice = $radio->getConfig()->getOption('value'); - - return; - } - } - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/ArrayToPartsTransformer.php b/lib/symfony/form/Extension/Core/DataTransformer/ArrayToPartsTransformer.php deleted file mode 100644 index f79920971..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/ArrayToPartsTransformer.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\DataTransformerInterface; -use Symfony\Component\Form\Exception\TransformationFailedException; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class ArrayToPartsTransformer implements DataTransformerInterface -{ - private $partMapping; - - public function __construct(array $partMapping) - { - $this->partMapping = $partMapping; - } - - public function transform($array) - { - if (null === $array) { - $array = []; - } - - if (!\is_array($array)) { - throw new TransformationFailedException('Expected an array.'); - } - - $result = []; - - foreach ($this->partMapping as $partKey => $originalKeys) { - if (empty($array)) { - $result[$partKey] = null; - } else { - $result[$partKey] = array_intersect_key($array, array_flip($originalKeys)); - } - } - - return $result; - } - - public function reverseTransform($array) - { - if (!\is_array($array)) { - throw new TransformationFailedException('Expected an array.'); - } - - $result = []; - $emptyKeys = []; - - foreach ($this->partMapping as $partKey => $originalKeys) { - if (!empty($array[$partKey])) { - foreach ($originalKeys as $originalKey) { - if (isset($array[$partKey][$originalKey])) { - $result[$originalKey] = $array[$partKey][$originalKey]; - } - } - } else { - $emptyKeys[] = $partKey; - } - } - - if (\count($emptyKeys) > 0) { - if (\count($emptyKeys) === \count($this->partMapping)) { - // All parts empty - return null; - } - - throw new TransformationFailedException(sprintf('The keys "%s" should not be empty.', implode('", "', $emptyKeys))); - } - - return $result; - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/BaseDateTimeTransformer.php b/lib/symfony/form/Extension/Core/DataTransformer/BaseDateTimeTransformer.php deleted file mode 100644 index 142f4894e..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/BaseDateTimeTransformer.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\DataTransformerInterface; -use Symfony\Component\Form\Exception\InvalidArgumentException; - -abstract class BaseDateTimeTransformer implements DataTransformerInterface -{ - protected static $formats = [ - \IntlDateFormatter::NONE, - \IntlDateFormatter::FULL, - \IntlDateFormatter::LONG, - \IntlDateFormatter::MEDIUM, - \IntlDateFormatter::SHORT, - ]; - - protected $inputTimezone; - - protected $outputTimezone; - - /** - * @param string|null $inputTimezone The name of the input timezone - * @param string|null $outputTimezone The name of the output timezone - * - * @throws InvalidArgumentException if a timezone is not valid - */ - public function __construct(string $inputTimezone = null, string $outputTimezone = null) - { - $this->inputTimezone = $inputTimezone ?: date_default_timezone_get(); - $this->outputTimezone = $outputTimezone ?: date_default_timezone_get(); - - // Check if input and output timezones are valid - try { - new \DateTimeZone($this->inputTimezone); - } catch (\Exception $e) { - throw new InvalidArgumentException(sprintf('Input timezone is invalid: "%s".', $this->inputTimezone), $e->getCode(), $e); - } - - try { - new \DateTimeZone($this->outputTimezone); - } catch (\Exception $e) { - throw new InvalidArgumentException(sprintf('Output timezone is invalid: "%s".', $this->outputTimezone), $e->getCode(), $e); - } - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/BooleanToStringTransformer.php b/lib/symfony/form/Extension/Core/DataTransformer/BooleanToStringTransformer.php deleted file mode 100644 index b2d574599..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/BooleanToStringTransformer.php +++ /dev/null @@ -1,85 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\DataTransformerInterface; -use Symfony\Component\Form\Exception\InvalidArgumentException; -use Symfony\Component\Form\Exception\TransformationFailedException; - -/** - * Transforms between a Boolean and a string. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * @author Florian Eckerstorfer <florian@eckerstorfer.org> - */ -class BooleanToStringTransformer implements DataTransformerInterface -{ - private $trueValue; - - private $falseValues; - - /** - * @param string $trueValue The value emitted upon transform if the input is true - */ - public function __construct(string $trueValue, array $falseValues = [null]) - { - $this->trueValue = $trueValue; - $this->falseValues = $falseValues; - if (\in_array($this->trueValue, $this->falseValues, true)) { - throw new InvalidArgumentException('The specified "true" value is contained in the false-values.'); - } - } - - /** - * Transforms a Boolean into a string. - * - * @param bool $value Boolean value - * - * @return string|null - * - * @throws TransformationFailedException if the given value is not a Boolean - */ - public function transform($value) - { - if (null === $value) { - return null; - } - - if (!\is_bool($value)) { - throw new TransformationFailedException('Expected a Boolean.'); - } - - return $value ? $this->trueValue : null; - } - - /** - * Transforms a string into a Boolean. - * - * @param string $value String value - * - * @return bool - * - * @throws TransformationFailedException if the given value is not a string - */ - public function reverseTransform($value) - { - if (\in_array($value, $this->falseValues, true)) { - return false; - } - - if (!\is_string($value)) { - throw new TransformationFailedException('Expected a string.'); - } - - return true; - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php b/lib/symfony/form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php deleted file mode 100644 index e1feafe62..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\ChoiceList\ChoiceListInterface; -use Symfony\Component\Form\DataTransformerInterface; -use Symfony\Component\Form\Exception\TransformationFailedException; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class ChoiceToValueTransformer implements DataTransformerInterface -{ - private $choiceList; - - public function __construct(ChoiceListInterface $choiceList) - { - $this->choiceList = $choiceList; - } - - public function transform($choice) - { - return (string) current($this->choiceList->getValuesForChoices([$choice])); - } - - public function reverseTransform($value) - { - if (null !== $value && !\is_string($value)) { - throw new TransformationFailedException('Expected a string or null.'); - } - - $choices = $this->choiceList->getChoicesForValues([(string) $value]); - - if (1 !== \count($choices)) { - if (null === $value || '' === $value) { - return null; - } - - throw new TransformationFailedException(sprintf('The choice "%s" does not exist or is not unique.', $value)); - } - - return current($choices); - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php b/lib/symfony/form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php deleted file mode 100644 index 6c9e4fe9d..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php +++ /dev/null @@ -1,73 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\ChoiceList\ChoiceListInterface; -use Symfony\Component\Form\DataTransformerInterface; -use Symfony\Component\Form\Exception\TransformationFailedException; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class ChoicesToValuesTransformer implements DataTransformerInterface -{ - private $choiceList; - - public function __construct(ChoiceListInterface $choiceList) - { - $this->choiceList = $choiceList; - } - - /** - * @return array - * - * @throws TransformationFailedException if the given value is not an array - */ - public function transform($array) - { - if (null === $array) { - return []; - } - - if (!\is_array($array)) { - throw new TransformationFailedException('Expected an array.'); - } - - return $this->choiceList->getValuesForChoices($array); - } - - /** - * @return array - * - * @throws TransformationFailedException if the given value is not an array - * or if no matching choice could be - * found for some given value - */ - public function reverseTransform($array) - { - if (null === $array) { - return []; - } - - if (!\is_array($array)) { - throw new TransformationFailedException('Expected an array.'); - } - - $choices = $this->choiceList->getChoicesForValues($array); - - if (\count($choices) !== \count($array)) { - throw new TransformationFailedException('Could not find all matching choices for the given values.'); - } - - return $choices; - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/DataTransformerChain.php b/lib/symfony/form/Extension/Core/DataTransformer/DataTransformerChain.php deleted file mode 100644 index e3107a889..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/DataTransformerChain.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\DataTransformerInterface; -use Symfony\Component\Form\Exception\TransformationFailedException; - -/** - * Passes a value through multiple value transformers. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class DataTransformerChain implements DataTransformerInterface -{ - protected $transformers; - - /** - * Uses the given value transformers to transform values. - * - * @param DataTransformerInterface[] $transformers - */ - public function __construct(array $transformers) - { - $this->transformers = $transformers; - } - - /** - * Passes the value through the transform() method of all nested transformers. - * - * The transformers receive the value in the same order as they were passed - * to the constructor. Each transformer receives the result of the previous - * transformer as input. The output of the last transformer is returned - * by this method. - * - * @param mixed $value The original value - * - * @return mixed - * - * @throws TransformationFailedException - */ - public function transform($value) - { - foreach ($this->transformers as $transformer) { - $value = $transformer->transform($value); - } - - return $value; - } - - /** - * Passes the value through the reverseTransform() method of all nested - * transformers. - * - * The transformers receive the value in the reverse order as they were passed - * to the constructor. Each transformer receives the result of the previous - * transformer as input. The output of the last transformer is returned - * by this method. - * - * @param mixed $value The transformed value - * - * @return mixed - * - * @throws TransformationFailedException - */ - public function reverseTransform($value) - { - for ($i = \count($this->transformers) - 1; $i >= 0; --$i) { - $value = $this->transformers[$i]->reverseTransform($value); - } - - return $value; - } - - /** - * @return DataTransformerInterface[] - */ - public function getTransformers() - { - return $this->transformers; - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/DateIntervalToArrayTransformer.php b/lib/symfony/form/Extension/Core/DataTransformer/DateIntervalToArrayTransformer.php deleted file mode 100644 index 5a37d4c70..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/DateIntervalToArrayTransformer.php +++ /dev/null @@ -1,171 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\DataTransformerInterface; -use Symfony\Component\Form\Exception\TransformationFailedException; -use Symfony\Component\Form\Exception\UnexpectedTypeException; - -/** - * Transforms between a normalized date interval and an interval string/array. - * - * @author Steffen Roßkamp <steffen.rosskamp@gimmickmedia.de> - */ -class DateIntervalToArrayTransformer implements DataTransformerInterface -{ - public const YEARS = 'years'; - public const MONTHS = 'months'; - public const DAYS = 'days'; - public const HOURS = 'hours'; - public const MINUTES = 'minutes'; - public const SECONDS = 'seconds'; - public const INVERT = 'invert'; - - private const AVAILABLE_FIELDS = [ - self::YEARS => 'y', - self::MONTHS => 'm', - self::DAYS => 'd', - self::HOURS => 'h', - self::MINUTES => 'i', - self::SECONDS => 's', - self::INVERT => 'r', - ]; - private $fields; - private $pad; - - /** - * @param string[]|null $fields The date fields - * @param bool $pad Whether to use padding - */ - public function __construct(array $fields = null, bool $pad = false) - { - $this->fields = $fields ?? ['years', 'months', 'days', 'hours', 'minutes', 'seconds', 'invert']; - $this->pad = $pad; - } - - /** - * Transforms a normalized date interval into an interval array. - * - * @param \DateInterval $dateInterval Normalized date interval - * - * @return array - * - * @throws UnexpectedTypeException if the given value is not a \DateInterval instance - */ - public function transform($dateInterval) - { - if (null === $dateInterval) { - return array_intersect_key( - [ - 'years' => '', - 'months' => '', - 'weeks' => '', - 'days' => '', - 'hours' => '', - 'minutes' => '', - 'seconds' => '', - 'invert' => false, - ], - array_flip($this->fields) - ); - } - if (!$dateInterval instanceof \DateInterval) { - throw new UnexpectedTypeException($dateInterval, \DateInterval::class); - } - $result = []; - foreach (self::AVAILABLE_FIELDS as $field => $char) { - $result[$field] = $dateInterval->format('%'.($this->pad ? strtoupper($char) : $char)); - } - if (\in_array('weeks', $this->fields, true)) { - $result['weeks'] = '0'; - if (isset($result['days']) && (int) $result['days'] >= 7) { - $result['weeks'] = (string) floor($result['days'] / 7); - $result['days'] = (string) ($result['days'] % 7); - } - } - $result['invert'] = '-' === $result['invert']; - $result = array_intersect_key($result, array_flip($this->fields)); - - return $result; - } - - /** - * Transforms an interval array into a normalized date interval. - * - * @param array $value Interval array - * - * @return \DateInterval|null - * - * @throws UnexpectedTypeException if the given value is not an array - * @throws TransformationFailedException if the value could not be transformed - */ - public function reverseTransform($value) - { - if (null === $value) { - return null; - } - if (!\is_array($value)) { - throw new UnexpectedTypeException($value, 'array'); - } - if ('' === implode('', $value)) { - return null; - } - $emptyFields = []; - foreach ($this->fields as $field) { - if (!isset($value[$field])) { - $emptyFields[] = $field; - } - } - if (\count($emptyFields) > 0) { - throw new TransformationFailedException(sprintf('The fields "%s" should not be empty.', implode('", "', $emptyFields))); - } - if (isset($value['invert']) && !\is_bool($value['invert'])) { - throw new TransformationFailedException('The value of "invert" must be boolean.'); - } - foreach (self::AVAILABLE_FIELDS as $field => $char) { - if ('invert' !== $field && isset($value[$field]) && !ctype_digit((string) $value[$field])) { - throw new TransformationFailedException(sprintf('This amount of "%s" is invalid.', $field)); - } - } - try { - if (!empty($value['weeks'])) { - $interval = sprintf( - 'P%sY%sM%sWT%sH%sM%sS', - empty($value['years']) ? '0' : $value['years'], - empty($value['months']) ? '0' : $value['months'], - empty($value['weeks']) ? '0' : $value['weeks'], - empty($value['hours']) ? '0' : $value['hours'], - empty($value['minutes']) ? '0' : $value['minutes'], - empty($value['seconds']) ? '0' : $value['seconds'] - ); - } else { - $interval = sprintf( - 'P%sY%sM%sDT%sH%sM%sS', - empty($value['years']) ? '0' : $value['years'], - empty($value['months']) ? '0' : $value['months'], - empty($value['days']) ? '0' : $value['days'], - empty($value['hours']) ? '0' : $value['hours'], - empty($value['minutes']) ? '0' : $value['minutes'], - empty($value['seconds']) ? '0' : $value['seconds'] - ); - } - $dateInterval = new \DateInterval($interval); - if (isset($value['invert'])) { - $dateInterval->invert = $value['invert'] ? 1 : 0; - } - } catch (\Exception $e) { - throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); - } - - return $dateInterval; - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/DateIntervalToStringTransformer.php b/lib/symfony/form/Extension/Core/DataTransformer/DateIntervalToStringTransformer.php deleted file mode 100644 index 723c344f9..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/DateIntervalToStringTransformer.php +++ /dev/null @@ -1,101 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\DataTransformerInterface; -use Symfony\Component\Form\Exception\TransformationFailedException; -use Symfony\Component\Form\Exception\UnexpectedTypeException; - -/** - * Transforms between a date string and a DateInterval object. - * - * @author Steffen Roßkamp <steffen.rosskamp@gimmickmedia.de> - */ -class DateIntervalToStringTransformer implements DataTransformerInterface -{ - private $format; - - /** - * Transforms a \DateInterval instance to a string. - * - * @see \DateInterval::format() for supported formats - * - * @param string $format The date format - */ - public function __construct(string $format = 'P%yY%mM%dDT%hH%iM%sS') - { - $this->format = $format; - } - - /** - * Transforms a DateInterval object into a date string with the configured format. - * - * @param \DateInterval|null $value A DateInterval object - * - * @return string - * - * @throws UnexpectedTypeException if the given value is not a \DateInterval instance - */ - public function transform($value) - { - if (null === $value) { - return ''; - } - if (!$value instanceof \DateInterval) { - throw new UnexpectedTypeException($value, \DateInterval::class); - } - - return $value->format($this->format); - } - - /** - * Transforms a date string in the configured format into a DateInterval object. - * - * @param string $value An ISO 8601 or date string like date interval presentation - * - * @return \DateInterval|null - * - * @throws UnexpectedTypeException if the given value is not a string - * @throws TransformationFailedException if the date interval could not be parsed - */ - public function reverseTransform($value) - { - if (null === $value) { - return null; - } - if (!\is_string($value)) { - throw new UnexpectedTypeException($value, 'string'); - } - if ('' === $value) { - return null; - } - if (!$this->isISO8601($value)) { - throw new TransformationFailedException('Non ISO 8601 date strings are not supported yet.'); - } - $valuePattern = '/^'.preg_replace('/%([yYmMdDhHiIsSwW])(\w)/', '(?P<$1>\d+)$2', $this->format).'$/'; - if (!preg_match($valuePattern, $value)) { - throw new TransformationFailedException(sprintf('Value "%s" contains intervals not accepted by format "%s".', $value, $this->format)); - } - try { - $dateInterval = new \DateInterval($value); - } catch (\Exception $e) { - throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); - } - - return $dateInterval; - } - - private function isISO8601(string $string): bool - { - return preg_match('/^P(?=\w*(?:\d|%\w))(?:\d+Y|%[yY]Y)?(?:\d+M|%[mM]M)?(?:(?:\d+D|%[dD]D)|(?:\d+W|%[wW]W))?(?:T(?:\d+H|[hH]H)?(?:\d+M|[iI]M)?(?:\d+S|[sS]S)?)?$/', $string); - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/DateTimeImmutableToDateTimeTransformer.php b/lib/symfony/form/Extension/Core/DataTransformer/DateTimeImmutableToDateTimeTransformer.php deleted file mode 100644 index 6eb40af9d..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/DateTimeImmutableToDateTimeTransformer.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\DataTransformerInterface; -use Symfony\Component\Form\Exception\TransformationFailedException; - -/** - * Transforms between a DateTimeImmutable object and a DateTime object. - * - * @author Valentin Udaltsov <udaltsov.valentin@gmail.com> - */ -final class DateTimeImmutableToDateTimeTransformer implements DataTransformerInterface -{ - /** - * Transforms a DateTimeImmutable into a DateTime object. - * - * @param \DateTimeImmutable|null $value A DateTimeImmutable object - * - * @throws TransformationFailedException If the given value is not a \DateTimeImmutable - */ - public function transform($value): ?\DateTime - { - if (null === $value) { - return null; - } - - if (!$value instanceof \DateTimeImmutable) { - throw new TransformationFailedException('Expected a \DateTimeImmutable.'); - } - - if (\PHP_VERSION_ID >= 70300) { - return \DateTime::createFromImmutable($value); - } - - return \DateTime::createFromFormat('U.u', $value->format('U.u'))->setTimezone($value->getTimezone()); - } - - /** - * Transforms a DateTime object into a DateTimeImmutable object. - * - * @param \DateTime|null $value A DateTime object - * - * @throws TransformationFailedException If the given value is not a \DateTime - */ - public function reverseTransform($value): ?\DateTimeImmutable - { - if (null === $value) { - return null; - } - - if (!$value instanceof \DateTime) { - throw new TransformationFailedException('Expected a \DateTime.'); - } - - return \DateTimeImmutable::createFromMutable($value); - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php b/lib/symfony/form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php deleted file mode 100644 index 710dfb596..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php +++ /dev/null @@ -1,184 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\Exception\TransformationFailedException; - -/** - * Transforms between a normalized time and a localized time string/array. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * @author Florian Eckerstorfer <florian@eckerstorfer.org> - */ -class DateTimeToArrayTransformer extends BaseDateTimeTransformer -{ - private $pad; - private $fields; - private $referenceDate; - - /** - * @param string|null $inputTimezone The input timezone - * @param string|null $outputTimezone The output timezone - * @param string[]|null $fields The date fields - * @param bool $pad Whether to use padding - */ - public function __construct(string $inputTimezone = null, string $outputTimezone = null, array $fields = null, bool $pad = false, \DateTimeInterface $referenceDate = null) - { - parent::__construct($inputTimezone, $outputTimezone); - - $this->fields = $fields ?? ['year', 'month', 'day', 'hour', 'minute', 'second']; - $this->pad = $pad; - $this->referenceDate = $referenceDate ?? new \DateTimeImmutable('1970-01-01 00:00:00'); - } - - /** - * Transforms a normalized date into a localized date. - * - * @param \DateTimeInterface $dateTime A DateTimeInterface object - * - * @return array - * - * @throws TransformationFailedException If the given value is not a \DateTimeInterface - */ - public function transform($dateTime) - { - if (null === $dateTime) { - return array_intersect_key([ - 'year' => '', - 'month' => '', - 'day' => '', - 'hour' => '', - 'minute' => '', - 'second' => '', - ], array_flip($this->fields)); - } - - if (!$dateTime instanceof \DateTimeInterface) { - throw new TransformationFailedException('Expected a \DateTimeInterface.'); - } - - if ($this->inputTimezone !== $this->outputTimezone) { - if (!$dateTime instanceof \DateTimeImmutable) { - $dateTime = clone $dateTime; - } - - $dateTime = $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone)); - } - - $result = array_intersect_key([ - 'year' => $dateTime->format('Y'), - 'month' => $dateTime->format('m'), - 'day' => $dateTime->format('d'), - 'hour' => $dateTime->format('H'), - 'minute' => $dateTime->format('i'), - 'second' => $dateTime->format('s'), - ], array_flip($this->fields)); - - if (!$this->pad) { - foreach ($result as &$entry) { - // remove leading zeros - $entry = (string) (int) $entry; - } - // unset reference to keep scope clear - unset($entry); - } - - return $result; - } - - /** - * Transforms a localized date into a normalized date. - * - * @param array $value Localized date - * - * @return \DateTime|null - * - * @throws TransformationFailedException If the given value is not an array, - * if the value could not be transformed - */ - public function reverseTransform($value) - { - if (null === $value) { - return null; - } - - if (!\is_array($value)) { - throw new TransformationFailedException('Expected an array.'); - } - - if ('' === implode('', $value)) { - return null; - } - - $emptyFields = []; - - foreach ($this->fields as $field) { - if (!isset($value[$field])) { - $emptyFields[] = $field; - } - } - - if (\count($emptyFields) > 0) { - throw new TransformationFailedException(sprintf('The fields "%s" should not be empty.', implode('", "', $emptyFields))); - } - - if (isset($value['month']) && !ctype_digit((string) $value['month'])) { - throw new TransformationFailedException('This month is invalid.'); - } - - if (isset($value['day']) && !ctype_digit((string) $value['day'])) { - throw new TransformationFailedException('This day is invalid.'); - } - - if (isset($value['year']) && !ctype_digit((string) $value['year'])) { - throw new TransformationFailedException('This year is invalid.'); - } - - if (!empty($value['month']) && !empty($value['day']) && !empty($value['year']) && false === checkdate($value['month'], $value['day'], $value['year'])) { - throw new TransformationFailedException('This is an invalid date.'); - } - - if (isset($value['hour']) && !ctype_digit((string) $value['hour'])) { - throw new TransformationFailedException('This hour is invalid.'); - } - - if (isset($value['minute']) && !ctype_digit((string) $value['minute'])) { - throw new TransformationFailedException('This minute is invalid.'); - } - - if (isset($value['second']) && !ctype_digit((string) $value['second'])) { - throw new TransformationFailedException('This second is invalid.'); - } - - try { - $dateTime = new \DateTime(sprintf( - '%s-%s-%s %s:%s:%s', - empty($value['year']) ? $this->referenceDate->format('Y') : $value['year'], - empty($value['month']) ? $this->referenceDate->format('m') : $value['month'], - empty($value['day']) ? $this->referenceDate->format('d') : $value['day'], - $value['hour'] ?? $this->referenceDate->format('H'), - $value['minute'] ?? $this->referenceDate->format('i'), - $value['second'] ?? $this->referenceDate->format('s') - ), - new \DateTimeZone($this->outputTimezone) - ); - - if ($this->inputTimezone !== $this->outputTimezone) { - $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone)); - } - } catch (\Exception $e) { - throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); - } - - return $dateTime; - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/DateTimeToHtml5LocalDateTimeTransformer.php b/lib/symfony/form/Extension/Core/DataTransformer/DateTimeToHtml5LocalDateTimeTransformer.php deleted file mode 100644 index ebbc76b71..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/DateTimeToHtml5LocalDateTimeTransformer.php +++ /dev/null @@ -1,106 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\Exception\TransformationFailedException; - -/** - * @author Franz Wilding <franz.wilding@me.com> - * @author Bernhard Schussek <bschussek@gmail.com> - * @author Fred Cox <mcfedr@gmail.com> - */ -class DateTimeToHtml5LocalDateTimeTransformer extends BaseDateTimeTransformer -{ - public const HTML5_FORMAT = 'Y-m-d\\TH:i:s'; - - /** - * Transforms a \DateTime into a local date and time string. - * - * According to the HTML standard, the input string of a datetime-local - * input is an RFC3339 date followed by 'T', followed by an RFC3339 time. - * https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-local-date-and-time-string - * - * @param \DateTime|\DateTimeInterface $dateTime A DateTime object - * - * @return string - * - * @throws TransformationFailedException If the given value is not an - * instance of \DateTime or \DateTimeInterface - */ - public function transform($dateTime) - { - if (null === $dateTime) { - return ''; - } - - if (!$dateTime instanceof \DateTime && !$dateTime instanceof \DateTimeInterface) { - throw new TransformationFailedException('Expected a \DateTime or \DateTimeInterface.'); - } - - if ($this->inputTimezone !== $this->outputTimezone) { - if (!$dateTime instanceof \DateTimeImmutable) { - $dateTime = clone $dateTime; - } - - $dateTime = $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone)); - } - - return $dateTime->format(self::HTML5_FORMAT); - } - - /** - * Transforms a local date and time string into a \DateTime. - * - * When transforming back to DateTime the regex is slightly laxer, taking into - * account rules for parsing a local date and time string - * https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#parse-a-local-date-and-time-string - * - * @param string $dateTimeLocal Formatted string - * - * @return \DateTime|null - * - * @throws TransformationFailedException If the given value is not a string, - * if the value could not be transformed - */ - public function reverseTransform($dateTimeLocal) - { - if (!\is_string($dateTimeLocal)) { - throw new TransformationFailedException('Expected a string.'); - } - - if ('' === $dateTimeLocal) { - return null; - } - - // to maintain backwards compatibility we do not strictly validate the submitted date - // see https://github.com/symfony/symfony/issues/28699 - if (!preg_match('/^(\d{4})-(\d{2})-(\d{2})[T ]\d{2}:\d{2}(?::\d{2})?/', $dateTimeLocal, $matches)) { - throw new TransformationFailedException(sprintf('The date "%s" is not a valid date.', $dateTimeLocal)); - } - - try { - $dateTime = new \DateTime($dateTimeLocal, new \DateTimeZone($this->outputTimezone)); - } catch (\Exception $e) { - throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); - } - - if ($this->inputTimezone !== $dateTime->getTimezone()->getName()) { - $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone)); - } - - if (!checkdate($matches[2], $matches[3], $matches[1])) { - throw new TransformationFailedException(sprintf('The date "%s-%s-%s" is not a valid date.', $matches[1], $matches[2], $matches[3])); - } - - return $dateTime; - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php b/lib/symfony/form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php deleted file mode 100644 index 7c8a4bcb2..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php +++ /dev/null @@ -1,208 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\Exception\TransformationFailedException; -use Symfony\Component\Form\Exception\UnexpectedTypeException; - -/** - * Transforms between a normalized time and a localized time string. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * @author Florian Eckerstorfer <florian@eckerstorfer.org> - */ -class DateTimeToLocalizedStringTransformer extends BaseDateTimeTransformer -{ - private $dateFormat; - private $timeFormat; - private $pattern; - private $calendar; - - /** - * @see BaseDateTimeTransformer::formats for available format options - * - * @param string|null $inputTimezone The name of the input timezone - * @param string|null $outputTimezone The name of the output timezone - * @param int|null $dateFormat The date format - * @param int|null $timeFormat The time format - * @param int $calendar One of the \IntlDateFormatter calendar constants - * @param string|null $pattern A pattern to pass to \IntlDateFormatter - * - * @throws UnexpectedTypeException If a format is not supported or if a timezone is not a string - */ - public function __construct(string $inputTimezone = null, string $outputTimezone = null, int $dateFormat = null, int $timeFormat = null, int $calendar = \IntlDateFormatter::GREGORIAN, string $pattern = null) - { - parent::__construct($inputTimezone, $outputTimezone); - - if (null === $dateFormat) { - $dateFormat = \IntlDateFormatter::MEDIUM; - } - - if (null === $timeFormat) { - $timeFormat = \IntlDateFormatter::SHORT; - } - - if (!\in_array($dateFormat, self::$formats, true)) { - throw new UnexpectedTypeException($dateFormat, implode('", "', self::$formats)); - } - - if (!\in_array($timeFormat, self::$formats, true)) { - throw new UnexpectedTypeException($timeFormat, implode('", "', self::$formats)); - } - - $this->dateFormat = $dateFormat; - $this->timeFormat = $timeFormat; - $this->calendar = $calendar; - $this->pattern = $pattern; - } - - /** - * Transforms a normalized date into a localized date string/array. - * - * @param \DateTimeInterface $dateTime A DateTimeInterface object - * - * @return string - * - * @throws TransformationFailedException if the given value is not a \DateTimeInterface - * or if the date could not be transformed - */ - public function transform($dateTime) - { - if (null === $dateTime) { - return ''; - } - - if (!$dateTime instanceof \DateTimeInterface) { - throw new TransformationFailedException('Expected a \DateTimeInterface.'); - } - - $value = $this->getIntlDateFormatter()->format($dateTime->getTimestamp()); - - if (0 != intl_get_error_code()) { - throw new TransformationFailedException(intl_get_error_message()); - } - - return $value; - } - - /** - * Transforms a localized date string/array into a normalized date. - * - * @param string|array $value Localized date string/array - * - * @return \DateTime|null - * - * @throws TransformationFailedException if the given value is not a string, - * if the date could not be parsed - */ - public function reverseTransform($value) - { - if (!\is_string($value)) { - throw new TransformationFailedException('Expected a string.'); - } - - if ('' === $value) { - return null; - } - - // date-only patterns require parsing to be done in UTC, as midnight might not exist in the local timezone due - // to DST changes - $dateOnly = $this->isPatternDateOnly(); - $dateFormatter = $this->getIntlDateFormatter($dateOnly); - - try { - $timestamp = @$dateFormatter->parse($value); - } catch (\IntlException $e) { - throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); - } - - if (0 != intl_get_error_code()) { - throw new TransformationFailedException(intl_get_error_message(), intl_get_error_code()); - } elseif ($timestamp > 253402214400) { - // This timestamp represents UTC midnight of 9999-12-31 to prevent 5+ digit years - throw new TransformationFailedException('Years beyond 9999 are not supported.'); - } elseif (false === $timestamp) { - // the value couldn't be parsed but the Intl extension didn't report an error code, this - // could be the case when the Intl polyfill is used which always returns 0 as the error code - throw new TransformationFailedException(sprintf('"%s" could not be parsed as a date.', $value)); - } - - try { - if ($dateOnly) { - // we only care about year-month-date, which has been delivered as a timestamp pointing to UTC midnight - $dateTime = new \DateTime(gmdate('Y-m-d', $timestamp), new \DateTimeZone($this->outputTimezone)); - } else { - // read timestamp into DateTime object - the formatter delivers a timestamp - $dateTime = new \DateTime(sprintf('@%s', $timestamp)); - } - // set timezone separately, as it would be ignored if set via the constructor, - // see https://php.net/datetime.construct - $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone)); - } catch (\Exception $e) { - throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); - } - - if ($this->outputTimezone !== $this->inputTimezone) { - $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone)); - } - - return $dateTime; - } - - /** - * Returns a preconfigured IntlDateFormatter instance. - * - * @param bool $ignoreTimezone Use UTC regardless of the configured timezone - * - * @return \IntlDateFormatter - * - * @throws TransformationFailedException in case the date formatter cannot be constructed - */ - protected function getIntlDateFormatter(bool $ignoreTimezone = false) - { - $dateFormat = $this->dateFormat; - $timeFormat = $this->timeFormat; - $timezone = new \DateTimeZone($ignoreTimezone ? 'UTC' : $this->outputTimezone); - - $calendar = $this->calendar; - $pattern = $this->pattern; - - $intlDateFormatter = new \IntlDateFormatter(\Locale::getDefault(), $dateFormat, $timeFormat, $timezone, $calendar, $pattern ?? ''); - - // new \intlDateFormatter may return null instead of false in case of failure, see https://bugs.php.net/66323 - if (!$intlDateFormatter) { - throw new TransformationFailedException(intl_get_error_message(), intl_get_error_code()); - } - - $intlDateFormatter->setLenient(false); - - return $intlDateFormatter; - } - - /** - * Checks if the pattern contains only a date. - * - * @return bool - */ - protected function isPatternDateOnly() - { - if (null === $this->pattern) { - return false; - } - - // strip escaped text - $pattern = preg_replace("#'(.*?)'#", '', $this->pattern); - - // check for the absence of time-related placeholders - return 0 === preg_match('#[ahHkKmsSAzZOvVxX]#', $pattern); - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php b/lib/symfony/form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php deleted file mode 100644 index e0cdbcfac..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\Exception\TransformationFailedException; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class DateTimeToRfc3339Transformer extends BaseDateTimeTransformer -{ - /** - * Transforms a normalized date into a localized date. - * - * @param \DateTimeInterface $dateTime A DateTimeInterface object - * - * @return string - * - * @throws TransformationFailedException If the given value is not a \DateTimeInterface - */ - public function transform($dateTime) - { - if (null === $dateTime) { - return ''; - } - - if (!$dateTime instanceof \DateTimeInterface) { - throw new TransformationFailedException('Expected a \DateTimeInterface.'); - } - - if ($this->inputTimezone !== $this->outputTimezone) { - if (!$dateTime instanceof \DateTimeImmutable) { - $dateTime = clone $dateTime; - } - - $dateTime = $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone)); - } - - return preg_replace('/\+00:00$/', 'Z', $dateTime->format('c')); - } - - /** - * Transforms a formatted string following RFC 3339 into a normalized date. - * - * @param string $rfc3339 Formatted string - * - * @return \DateTime|null - * - * @throws TransformationFailedException If the given value is not a string, - * if the value could not be transformed - */ - public function reverseTransform($rfc3339) - { - if (!\is_string($rfc3339)) { - throw new TransformationFailedException('Expected a string.'); - } - - if ('' === $rfc3339) { - return null; - } - - if (!preg_match('/^(\d{4})-(\d{2})-(\d{2})T\d{2}:\d{2}(?::\d{2})?(?:\.\d+)?(?:Z|(?:(?:\+|-)\d{2}:\d{2}))$/', $rfc3339, $matches)) { - throw new TransformationFailedException(sprintf('The date "%s" is not a valid date.', $rfc3339)); - } - - try { - $dateTime = new \DateTime($rfc3339); - } catch (\Exception $e) { - throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); - } - - if ($this->inputTimezone !== $dateTime->getTimezone()->getName()) { - $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone)); - } - - if (!checkdate($matches[2], $matches[3], $matches[1])) { - throw new TransformationFailedException(sprintf('The date "%s-%s-%s" is not a valid date.', $matches[1], $matches[2], $matches[3])); - } - - return $dateTime; - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php b/lib/symfony/form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php deleted file mode 100644 index 9e680b1c7..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php +++ /dev/null @@ -1,140 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\Exception\TransformationFailedException; - -/** - * Transforms between a date string and a DateTime object. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * @author Florian Eckerstorfer <florian@eckerstorfer.org> - */ -class DateTimeToStringTransformer extends BaseDateTimeTransformer -{ - /** - * Format used for generating strings. - * - * @var string - */ - private $generateFormat; - - /** - * Format used for parsing strings. - * - * Different than the {@link $generateFormat} because formats for parsing - * support additional characters in PHP that are not supported for - * generating strings. - * - * @var string - */ - private $parseFormat; - - /** - * Transforms a \DateTime instance to a string. - * - * @see \DateTime::format() for supported formats - * - * @param string|null $inputTimezone The name of the input timezone - * @param string|null $outputTimezone The name of the output timezone - * @param string $format The date format - * @param string|null $parseFormat The parse format when different from $format - */ - public function __construct(string $inputTimezone = null, string $outputTimezone = null, string $format = 'Y-m-d H:i:s', string $parseFormat = null) - { - parent::__construct($inputTimezone, $outputTimezone); - - $this->generateFormat = $format; - $this->parseFormat = $parseFormat ?? $format; - - // See https://php.net/datetime.createfromformat - // The character "|" in the format makes sure that the parts of a date - // that are *not* specified in the format are reset to the corresponding - // values from 1970-01-01 00:00:00 instead of the current time. - // Without "|" and "Y-m-d", "2010-02-03" becomes "2010-02-03 12:32:47", - // where the time corresponds to the current server time. - // With "|" and "Y-m-d", "2010-02-03" becomes "2010-02-03 00:00:00", - // which is at least deterministic and thus used here. - if (!str_contains($this->parseFormat, '|')) { - $this->parseFormat .= '|'; - } - } - - /** - * Transforms a DateTime object into a date string with the configured format - * and timezone. - * - * @param \DateTimeInterface $dateTime A DateTimeInterface object - * - * @return string - * - * @throws TransformationFailedException If the given value is not a \DateTimeInterface - */ - public function transform($dateTime) - { - if (null === $dateTime) { - return ''; - } - - if (!$dateTime instanceof \DateTimeInterface) { - throw new TransformationFailedException('Expected a \DateTimeInterface.'); - } - - if (!$dateTime instanceof \DateTimeImmutable) { - $dateTime = clone $dateTime; - } - - $dateTime = $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone)); - - return $dateTime->format($this->generateFormat); - } - - /** - * Transforms a date string in the configured timezone into a DateTime object. - * - * @param string $value A value as produced by PHP's date() function - * - * @return \DateTime|null - * - * @throws TransformationFailedException If the given value is not a string, - * or could not be transformed - */ - public function reverseTransform($value) - { - if (empty($value)) { - return null; - } - - if (!\is_string($value)) { - throw new TransformationFailedException('Expected a string.'); - } - - $outputTz = new \DateTimeZone($this->outputTimezone); - $dateTime = \DateTime::createFromFormat($this->parseFormat, $value, $outputTz); - - $lastErrors = \DateTime::getLastErrors() ?: ['error_count' => 0, 'warning_count' => 0]; - - if (0 < $lastErrors['warning_count'] || 0 < $lastErrors['error_count']) { - throw new TransformationFailedException(implode(', ', array_merge(array_values($lastErrors['warnings']), array_values($lastErrors['errors'])))); - } - - try { - if ($this->inputTimezone !== $this->outputTimezone) { - $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone)); - } - } catch (\Exception $e) { - throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); - } - - return $dateTime; - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php b/lib/symfony/form/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php deleted file mode 100644 index f6c38ba4d..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\Exception\TransformationFailedException; - -/** - * Transforms between a timestamp and a DateTime object. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * @author Florian Eckerstorfer <florian@eckerstorfer.org> - */ -class DateTimeToTimestampTransformer extends BaseDateTimeTransformer -{ - /** - * Transforms a DateTime object into a timestamp in the configured timezone. - * - * @param \DateTimeInterface $dateTime A DateTimeInterface object - * - * @return int|null - * - * @throws TransformationFailedException If the given value is not a \DateTimeInterface - */ - public function transform($dateTime) - { - if (null === $dateTime) { - return null; - } - - if (!$dateTime instanceof \DateTimeInterface) { - throw new TransformationFailedException('Expected a \DateTimeInterface.'); - } - - return $dateTime->getTimestamp(); - } - - /** - * Transforms a timestamp in the configured timezone into a DateTime object. - * - * @param string $value A timestamp - * - * @return \DateTime|null - * - * @throws TransformationFailedException If the given value is not a timestamp - * or if the given timestamp is invalid - */ - public function reverseTransform($value) - { - if (null === $value) { - return null; - } - - if (!is_numeric($value)) { - throw new TransformationFailedException('Expected a numeric.'); - } - - try { - $dateTime = new \DateTime(); - $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone)); - $dateTime->setTimestamp($value); - - if ($this->inputTimezone !== $this->outputTimezone) { - $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone)); - } - } catch (\Exception $e) { - throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); - } - - return $dateTime; - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/DateTimeZoneToStringTransformer.php b/lib/symfony/form/Extension/Core/DataTransformer/DateTimeZoneToStringTransformer.php deleted file mode 100644 index 6dfccdfd3..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/DateTimeZoneToStringTransformer.php +++ /dev/null @@ -1,82 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\DataTransformerInterface; -use Symfony\Component\Form\Exception\TransformationFailedException; - -/** - * Transforms between a timezone identifier string and a DateTimeZone object. - * - * @author Roland Franssen <franssen.roland@gmail.com> - */ -class DateTimeZoneToStringTransformer implements DataTransformerInterface -{ - private $multiple; - - public function __construct(bool $multiple = false) - { - $this->multiple = $multiple; - } - - /** - * {@inheritdoc} - */ - public function transform($dateTimeZone) - { - if (null === $dateTimeZone) { - return null; - } - - if ($this->multiple) { - if (!\is_array($dateTimeZone)) { - throw new TransformationFailedException('Expected an array of \DateTimeZone objects.'); - } - - return array_map([new self(), 'transform'], $dateTimeZone); - } - - if (!$dateTimeZone instanceof \DateTimeZone) { - throw new TransformationFailedException('Expected a \DateTimeZone object.'); - } - - return $dateTimeZone->getName(); - } - - /** - * {@inheritdoc} - */ - public function reverseTransform($value) - { - if (null === $value) { - return null; - } - - if ($this->multiple) { - if (!\is_array($value)) { - throw new TransformationFailedException('Expected an array of timezone identifier strings.'); - } - - return array_map([new self(), 'reverseTransform'], $value); - } - - if (!\is_string($value)) { - throw new TransformationFailedException('Expected a timezone identifier string.'); - } - - try { - return new \DateTimeZone($value); - } catch (\Exception $e) { - throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); - } - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php b/lib/symfony/form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php deleted file mode 100644 index 1ba914062..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php +++ /dev/null @@ -1,59 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\Exception\TransformationFailedException; - -/** - * Transforms between an integer and a localized number with grouping - * (each thousand) and comma separators. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class IntegerToLocalizedStringTransformer extends NumberToLocalizedStringTransformer -{ - /** - * Constructs a transformer. - * - * @param bool $grouping Whether thousands should be grouped - * @param int $roundingMode One of the ROUND_ constants in this class - * @param string|null $locale locale used for transforming - */ - public function __construct(?bool $grouping = false, ?int $roundingMode = \NumberFormatter::ROUND_DOWN, string $locale = null) - { - parent::__construct(0, $grouping, $roundingMode, $locale); - } - - /** - * {@inheritdoc} - */ - public function reverseTransform($value) - { - $decimalSeparator = $this->getNumberFormatter()->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL); - - if (\is_string($value) && str_contains($value, $decimalSeparator)) { - throw new TransformationFailedException(sprintf('The value "%s" is not a valid integer.', $value)); - } - - $result = parent::reverseTransform($value); - - return null !== $result ? (int) $result : null; - } - - /** - * @internal - */ - protected function castParsedValue($value) - { - return $value; - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/IntlTimeZoneToStringTransformer.php b/lib/symfony/form/Extension/Core/DataTransformer/IntlTimeZoneToStringTransformer.php deleted file mode 100644 index aa4629f2e..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/IntlTimeZoneToStringTransformer.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\DataTransformerInterface; -use Symfony\Component\Form\Exception\TransformationFailedException; - -/** - * Transforms between a timezone identifier string and a IntlTimeZone object. - * - * @author Roland Franssen <franssen.roland@gmail.com> - */ -class IntlTimeZoneToStringTransformer implements DataTransformerInterface -{ - private $multiple; - - public function __construct(bool $multiple = false) - { - $this->multiple = $multiple; - } - - /** - * {@inheritdoc} - */ - public function transform($intlTimeZone) - { - if (null === $intlTimeZone) { - return null; - } - - if ($this->multiple) { - if (!\is_array($intlTimeZone)) { - throw new TransformationFailedException('Expected an array of \IntlTimeZone objects.'); - } - - return array_map([new self(), 'transform'], $intlTimeZone); - } - - if (!$intlTimeZone instanceof \IntlTimeZone) { - throw new TransformationFailedException('Expected a \IntlTimeZone object.'); - } - - return $intlTimeZone->getID(); - } - - /** - * {@inheritdoc} - */ - public function reverseTransform($value) - { - if (null === $value) { - return; - } - - if ($this->multiple) { - if (!\is_array($value)) { - throw new TransformationFailedException('Expected an array of timezone identifier strings.'); - } - - return array_map([new self(), 'reverseTransform'], $value); - } - - if (!\is_string($value)) { - throw new TransformationFailedException('Expected a timezone identifier string.'); - } - - $intlTimeZone = \IntlTimeZone::createTimeZone($value); - - if ('Etc/Unknown' === $intlTimeZone->getID()) { - throw new TransformationFailedException(sprintf('Unknown timezone identifier "%s".', $value)); - } - - return $intlTimeZone; - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php b/lib/symfony/form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php deleted file mode 100644 index 9784fe673..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php +++ /dev/null @@ -1,74 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\Exception\TransformationFailedException; - -/** - * Transforms between a normalized format and a localized money string. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * @author Florian Eckerstorfer <florian@eckerstorfer.org> - */ -class MoneyToLocalizedStringTransformer extends NumberToLocalizedStringTransformer -{ - private $divisor; - - public function __construct(?int $scale = 2, ?bool $grouping = true, ?int $roundingMode = \NumberFormatter::ROUND_HALFUP, ?int $divisor = 1, string $locale = null) - { - parent::__construct($scale ?? 2, $grouping ?? true, $roundingMode, $locale); - - $this->divisor = $divisor ?? 1; - } - - /** - * Transforms a normalized format into a localized money string. - * - * @param int|float|null $value Normalized number - * - * @return string - * - * @throws TransformationFailedException if the given value is not numeric or - * if the value cannot be transformed - */ - public function transform($value) - { - if (null !== $value && 1 !== $this->divisor) { - if (!is_numeric($value)) { - throw new TransformationFailedException('Expected a numeric.'); - } - $value /= $this->divisor; - } - - return parent::transform($value); - } - - /** - * Transforms a localized money string into a normalized format. - * - * @param string $value Localized money string - * - * @return int|float|null - * - * @throws TransformationFailedException if the given value is not a string - * or if the value cannot be transformed - */ - public function reverseTransform($value) - { - $value = parent::reverseTransform($value); - if (null !== $value && 1 !== $this->divisor) { - $value = (float) (string) ($value * $this->divisor); - } - - return $value; - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php b/lib/symfony/form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php deleted file mode 100644 index 53e564b13..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php +++ /dev/null @@ -1,265 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\DataTransformerInterface; -use Symfony\Component\Form\Exception\TransformationFailedException; - -/** - * Transforms between a number type and a localized number with grouping - * (each thousand) and comma separators. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * @author Florian Eckerstorfer <florian@eckerstorfer.org> - */ -class NumberToLocalizedStringTransformer implements DataTransformerInterface -{ - /** - * @deprecated since Symfony 5.1, use \NumberFormatter::ROUND_CEILING instead. - */ - public const ROUND_CEILING = \NumberFormatter::ROUND_CEILING; - - /** - * @deprecated since Symfony 5.1, use \NumberFormatter::ROUND_FLOOR instead. - */ - public const ROUND_FLOOR = \NumberFormatter::ROUND_FLOOR; - - /** - * @deprecated since Symfony 5.1, use \NumberFormatter::ROUND_UP instead. - */ - public const ROUND_UP = \NumberFormatter::ROUND_UP; - - /** - * @deprecated since Symfony 5.1, use \NumberFormatter::ROUND_DOWN instead. - */ - public const ROUND_DOWN = \NumberFormatter::ROUND_DOWN; - - /** - * @deprecated since Symfony 5.1, use \NumberFormatter::ROUND_HALFEVEN instead. - */ - public const ROUND_HALF_EVEN = \NumberFormatter::ROUND_HALFEVEN; - - /** - * @deprecated since Symfony 5.1, use \NumberFormatter::ROUND_HALFUP instead. - */ - public const ROUND_HALF_UP = \NumberFormatter::ROUND_HALFUP; - - /** - * @deprecated since Symfony 5.1, use \NumberFormatter::ROUND_HALFDOWN instead. - */ - public const ROUND_HALF_DOWN = \NumberFormatter::ROUND_HALFDOWN; - - protected $grouping; - - protected $roundingMode; - - private $scale; - private $locale; - - public function __construct(int $scale = null, ?bool $grouping = false, ?int $roundingMode = \NumberFormatter::ROUND_HALFUP, string $locale = null) - { - $this->scale = $scale; - $this->grouping = $grouping ?? false; - $this->roundingMode = $roundingMode ?? \NumberFormatter::ROUND_HALFUP; - $this->locale = $locale; - } - - /** - * Transforms a number type into localized number. - * - * @param int|float|null $value Number value - * - * @return string - * - * @throws TransformationFailedException if the given value is not numeric - * or if the value cannot be transformed - */ - public function transform($value) - { - if (null === $value) { - return ''; - } - - if (!is_numeric($value)) { - throw new TransformationFailedException('Expected a numeric.'); - } - - $formatter = $this->getNumberFormatter(); - $value = $formatter->format($value); - - if (intl_is_failure($formatter->getErrorCode())) { - throw new TransformationFailedException($formatter->getErrorMessage()); - } - - // Convert non-breaking and narrow non-breaking spaces to normal ones - $value = str_replace(["\xc2\xa0", "\xe2\x80\xaf"], ' ', $value); - - return $value; - } - - /** - * Transforms a localized number into an integer or float. - * - * @param string $value The localized value - * - * @return int|float|null - * - * @throws TransformationFailedException if the given value is not a string - * or if the value cannot be transformed - */ - public function reverseTransform($value) - { - if (null !== $value && !\is_string($value)) { - throw new TransformationFailedException('Expected a string.'); - } - - if (null === $value || '' === $value) { - return null; - } - - if (\in_array($value, ['NaN', 'NAN', 'nan'], true)) { - throw new TransformationFailedException('"NaN" is not a valid number.'); - } - - $position = 0; - $formatter = $this->getNumberFormatter(); - $groupSep = $formatter->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL); - $decSep = $formatter->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL); - - if ('.' !== $decSep && (!$this->grouping || '.' !== $groupSep)) { - $value = str_replace('.', $decSep, $value); - } - - if (',' !== $decSep && (!$this->grouping || ',' !== $groupSep)) { - $value = str_replace(',', $decSep, $value); - } - - if (str_contains($value, $decSep)) { - $type = \NumberFormatter::TYPE_DOUBLE; - } else { - $type = \PHP_INT_SIZE === 8 - ? \NumberFormatter::TYPE_INT64 - : \NumberFormatter::TYPE_INT32; - } - - $result = $formatter->parse($value, $type, $position); - - if (intl_is_failure($formatter->getErrorCode())) { - throw new TransformationFailedException($formatter->getErrorMessage()); - } - - if ($result >= \PHP_INT_MAX || $result <= -\PHP_INT_MAX) { - throw new TransformationFailedException('I don\'t have a clear idea what infinity looks like.'); - } - - $result = $this->castParsedValue($result); - - if (false !== $encoding = mb_detect_encoding($value, null, true)) { - $length = mb_strlen($value, $encoding); - $remainder = mb_substr($value, $position, $length, $encoding); - } else { - $length = \strlen($value); - $remainder = substr($value, $position, $length); - } - - // After parsing, position holds the index of the character where the - // parsing stopped - if ($position < $length) { - // Check if there are unrecognized characters at the end of the - // number (excluding whitespace characters) - $remainder = trim($remainder, " \t\n\r\0\x0b\xc2\xa0"); - - if ('' !== $remainder) { - throw new TransformationFailedException(sprintf('The number contains unrecognized characters: "%s".', $remainder)); - } - } - - // NumberFormatter::parse() does not round - return $this->round($result); - } - - /** - * Returns a preconfigured \NumberFormatter instance. - * - * @return \NumberFormatter - */ - protected function getNumberFormatter() - { - $formatter = new \NumberFormatter($this->locale ?? \Locale::getDefault(), \NumberFormatter::DECIMAL); - - if (null !== $this->scale) { - $formatter->setAttribute(\NumberFormatter::FRACTION_DIGITS, $this->scale); - $formatter->setAttribute(\NumberFormatter::ROUNDING_MODE, $this->roundingMode); - } - - $formatter->setAttribute(\NumberFormatter::GROUPING_USED, $this->grouping); - - return $formatter; - } - - /** - * @internal - */ - protected function castParsedValue($value) - { - if (\is_int($value) && $value === (int) $float = (float) $value) { - return $float; - } - - return $value; - } - - /** - * Rounds a number according to the configured scale and rounding mode. - * - * @param int|float $number A number - * - * @return int|float - */ - private function round($number) - { - if (null !== $this->scale && null !== $this->roundingMode) { - // shift number to maintain the correct scale during rounding - $roundingCoef = 10 ** $this->scale; - // string representation to avoid rounding errors, similar to bcmul() - $number = (string) ($number * $roundingCoef); - - switch ($this->roundingMode) { - case \NumberFormatter::ROUND_CEILING: - $number = ceil($number); - break; - case \NumberFormatter::ROUND_FLOOR: - $number = floor($number); - break; - case \NumberFormatter::ROUND_UP: - $number = $number > 0 ? ceil($number) : floor($number); - break; - case \NumberFormatter::ROUND_DOWN: - $number = $number > 0 ? floor($number) : ceil($number); - break; - case \NumberFormatter::ROUND_HALFEVEN: - $number = round($number, 0, \PHP_ROUND_HALF_EVEN); - break; - case \NumberFormatter::ROUND_HALFUP: - $number = round($number, 0, \PHP_ROUND_HALF_UP); - break; - case \NumberFormatter::ROUND_HALFDOWN: - $number = round($number, 0, \PHP_ROUND_HALF_DOWN); - break; - } - - $number = 1 === $roundingCoef ? (int) $number : $number / $roundingCoef; - } - - return $number; - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php b/lib/symfony/form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php deleted file mode 100644 index 5b97f0190..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php +++ /dev/null @@ -1,249 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\DataTransformerInterface; -use Symfony\Component\Form\Exception\TransformationFailedException; -use Symfony\Component\Form\Exception\UnexpectedTypeException; - -/** - * Transforms between a normalized format (integer or float) and a percentage value. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * @author Florian Eckerstorfer <florian@eckerstorfer.org> - */ -class PercentToLocalizedStringTransformer implements DataTransformerInterface -{ - public const FRACTIONAL = 'fractional'; - public const INTEGER = 'integer'; - - protected static $types = [ - self::FRACTIONAL, - self::INTEGER, - ]; - - private $roundingMode; - private $type; - private $scale; - private $html5Format; - - /** - * @see self::$types for a list of supported types - * - * @param int|null $roundingMode A value from \NumberFormatter, such as \NumberFormatter::ROUND_HALFUP - * @param bool $html5Format Use an HTML5 specific format, see https://www.w3.org/TR/html51/sec-forms.html#date-time-and-number-formats - * - * @throws UnexpectedTypeException if the given value of type is unknown - */ - public function __construct(int $scale = null, string $type = null, int $roundingMode = null, bool $html5Format = false) - { - if (null === $type) { - $type = self::FRACTIONAL; - } - - if (null === $roundingMode && (\func_num_args() < 4 || func_get_arg(3))) { - trigger_deprecation('symfony/form', '5.1', 'Not passing a rounding mode to "%s()" is deprecated. Starting with Symfony 6.0 it will default to "\NumberFormatter::ROUND_HALFUP".', __METHOD__); - } - - if (!\in_array($type, self::$types, true)) { - throw new UnexpectedTypeException($type, implode('", "', self::$types)); - } - - $this->type = $type; - $this->scale = $scale ?? 0; - $this->roundingMode = $roundingMode; - $this->html5Format = $html5Format; - } - - /** - * Transforms between a normalized format (integer or float) into a percentage value. - * - * @param int|float $value Normalized value - * - * @return string - * - * @throws TransformationFailedException if the given value is not numeric or - * if the value could not be transformed - */ - public function transform($value) - { - if (null === $value) { - return ''; - } - - if (!is_numeric($value)) { - throw new TransformationFailedException('Expected a numeric.'); - } - - if (self::FRACTIONAL == $this->type) { - $value *= 100; - } - - $formatter = $this->getNumberFormatter(); - $value = $formatter->format($value); - - if (intl_is_failure($formatter->getErrorCode())) { - throw new TransformationFailedException($formatter->getErrorMessage()); - } - - // replace the UTF-8 non break spaces - return $value; - } - - /** - * Transforms between a percentage value into a normalized format (integer or float). - * - * @param string $value Percentage value - * - * @return int|float|null - * - * @throws TransformationFailedException if the given value is not a string or - * if the value could not be transformed - */ - public function reverseTransform($value) - { - if (!\is_string($value)) { - throw new TransformationFailedException('Expected a string.'); - } - - if ('' === $value) { - return null; - } - - $position = 0; - $formatter = $this->getNumberFormatter(); - $groupSep = $formatter->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL); - $decSep = $formatter->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL); - $grouping = $formatter->getAttribute(\NumberFormatter::GROUPING_USED); - - if ('.' !== $decSep && (!$grouping || '.' !== $groupSep)) { - $value = str_replace('.', $decSep, $value); - } - - if (',' !== $decSep && (!$grouping || ',' !== $groupSep)) { - $value = str_replace(',', $decSep, $value); - } - - if (str_contains($value, $decSep)) { - $type = \NumberFormatter::TYPE_DOUBLE; - } else { - $type = \PHP_INT_SIZE === 8 ? \NumberFormatter::TYPE_INT64 : \NumberFormatter::TYPE_INT32; - } - - // replace normal spaces so that the formatter can read them - $result = $formatter->parse(str_replace(' ', "\xc2\xa0", $value), $type, $position); - - if (intl_is_failure($formatter->getErrorCode())) { - throw new TransformationFailedException($formatter->getErrorMessage()); - } - - if (self::FRACTIONAL == $this->type) { - $result /= 100; - } - - if (\function_exists('mb_detect_encoding') && false !== $encoding = mb_detect_encoding($value, null, true)) { - $length = mb_strlen($value, $encoding); - $remainder = mb_substr($value, $position, $length, $encoding); - } else { - $length = \strlen($value); - $remainder = substr($value, $position, $length); - } - - // After parsing, position holds the index of the character where the - // parsing stopped - if ($position < $length) { - // Check if there are unrecognized characters at the end of the - // number (excluding whitespace characters) - $remainder = trim($remainder, " \t\n\r\0\x0b\xc2\xa0"); - - if ('' !== $remainder) { - throw new TransformationFailedException(sprintf('The number contains unrecognized characters: "%s".', $remainder)); - } - } - - return $this->round($result); - } - - /** - * Returns a preconfigured \NumberFormatter instance. - * - * @return \NumberFormatter - */ - protected function getNumberFormatter() - { - // Values used in HTML5 number inputs should be formatted as in "1234.5", ie. 'en' format without grouping, - // according to https://www.w3.org/TR/html51/sec-forms.html#date-time-and-number-formats - $formatter = new \NumberFormatter($this->html5Format ? 'en' : \Locale::getDefault(), \NumberFormatter::DECIMAL); - - if ($this->html5Format) { - $formatter->setAttribute(\NumberFormatter::GROUPING_USED, 0); - } - - $formatter->setAttribute(\NumberFormatter::FRACTION_DIGITS, $this->scale); - - if (null !== $this->roundingMode) { - $formatter->setAttribute(\NumberFormatter::ROUNDING_MODE, $this->roundingMode); - } - - return $formatter; - } - - /** - * Rounds a number according to the configured scale and rounding mode. - * - * @param int|float $number A number - * - * @return int|float - */ - private function round($number) - { - if (null !== $this->scale && null !== $this->roundingMode) { - // shift number to maintain the correct scale during rounding - $roundingCoef = 10 ** $this->scale; - - if (self::FRACTIONAL == $this->type) { - $roundingCoef *= 100; - } - - // string representation to avoid rounding errors, similar to bcmul() - $number = (string) ($number * $roundingCoef); - - switch ($this->roundingMode) { - case \NumberFormatter::ROUND_CEILING: - $number = ceil($number); - break; - case \NumberFormatter::ROUND_FLOOR: - $number = floor($number); - break; - case \NumberFormatter::ROUND_UP: - $number = $number > 0 ? ceil($number) : floor($number); - break; - case \NumberFormatter::ROUND_DOWN: - $number = $number > 0 ? floor($number) : ceil($number); - break; - case \NumberFormatter::ROUND_HALFEVEN: - $number = round($number, 0, \PHP_ROUND_HALF_EVEN); - break; - case \NumberFormatter::ROUND_HALFUP: - $number = round($number, 0, \PHP_ROUND_HALF_UP); - break; - case \NumberFormatter::ROUND_HALFDOWN: - $number = round($number, 0, \PHP_ROUND_HALF_DOWN); - break; - } - - $number = 1 === $roundingCoef ? (int) $number : $number / $roundingCoef; - } - - return $number; - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/StringToFloatTransformer.php b/lib/symfony/form/Extension/Core/DataTransformer/StringToFloatTransformer.php deleted file mode 100644 index 27e60b430..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/StringToFloatTransformer.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\DataTransformerInterface; -use Symfony\Component\Form\Exception\TransformationFailedException; - -class StringToFloatTransformer implements DataTransformerInterface -{ - private $scale; - - public function __construct(int $scale = null) - { - $this->scale = $scale; - } - - /** - * @param mixed $value - * - * @return float|null - */ - public function transform($value) - { - if (null === $value) { - return null; - } - - if (!\is_string($value) || !is_numeric($value)) { - throw new TransformationFailedException('Expected a numeric string.'); - } - - return (float) $value; - } - - /** - * @param mixed $value - * - * @return string|null - */ - public function reverseTransform($value) - { - if (null === $value) { - return null; - } - - if (!\is_int($value) && !\is_float($value)) { - throw new TransformationFailedException('Expected a numeric.'); - } - - if ($this->scale > 0) { - return number_format((float) $value, $this->scale, '.', ''); - } - - return (string) $value; - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/UlidToStringTransformer.php b/lib/symfony/form/Extension/Core/DataTransformer/UlidToStringTransformer.php deleted file mode 100644 index 33b57db73..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/UlidToStringTransformer.php +++ /dev/null @@ -1,75 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\DataTransformerInterface; -use Symfony\Component\Form\Exception\TransformationFailedException; -use Symfony\Component\Uid\Ulid; - -/** - * Transforms between a ULID string and a Ulid object. - * - * @author Pavel Dyakonov <wapinet@mail.ru> - */ -class UlidToStringTransformer implements DataTransformerInterface -{ - /** - * Transforms a Ulid object into a string. - * - * @param Ulid $value A Ulid object - * - * @return string|null - * - * @throws TransformationFailedException If the given value is not a Ulid object - */ - public function transform($value) - { - if (null === $value) { - return null; - } - - if (!$value instanceof Ulid) { - throw new TransformationFailedException('Expected a Ulid.'); - } - - return (string) $value; - } - - /** - * Transforms a ULID string into a Ulid object. - * - * @param string $value A ULID string - * - * @return Ulid|null - * - * @throws TransformationFailedException If the given value is not a string, - * or could not be transformed - */ - public function reverseTransform($value) - { - if (null === $value || '' === $value) { - return null; - } - - if (!\is_string($value)) { - throw new TransformationFailedException('Expected a string.'); - } - - try { - $ulid = new Ulid($value); - } catch (\InvalidArgumentException $e) { - throw new TransformationFailedException(sprintf('The value "%s" is not a valid ULID.', $value), $e->getCode(), $e); - } - - return $ulid; - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/UuidToStringTransformer.php b/lib/symfony/form/Extension/Core/DataTransformer/UuidToStringTransformer.php deleted file mode 100644 index c4775bb12..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/UuidToStringTransformer.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\DataTransformerInterface; -use Symfony\Component\Form\Exception\TransformationFailedException; -use Symfony\Component\Uid\Uuid; - -/** - * Transforms between a UUID string and a Uuid object. - * - * @author Pavel Dyakonov <wapinet@mail.ru> - */ -class UuidToStringTransformer implements DataTransformerInterface -{ - /** - * Transforms a Uuid object into a string. - * - * @param Uuid $value A Uuid object - * - * @return string|null - * - * @throws TransformationFailedException If the given value is not a Uuid object - */ - public function transform($value) - { - if (null === $value) { - return null; - } - - if (!$value instanceof Uuid) { - throw new TransformationFailedException('Expected a Uuid.'); - } - - return (string) $value; - } - - /** - * Transforms a UUID string into a Uuid object. - * - * @param string $value A UUID string - * - * @return Uuid|null - * - * @throws TransformationFailedException If the given value is not a string, - * or could not be transformed - */ - public function reverseTransform($value) - { - if (null === $value || '' === $value) { - return null; - } - - if (!\is_string($value)) { - throw new TransformationFailedException('Expected a string.'); - } - - if (!Uuid::isValid($value)) { - throw new TransformationFailedException(sprintf('The value "%s" is not a valid UUID.', $value)); - } - - try { - return Uuid::fromString($value); - } catch (\InvalidArgumentException $e) { - throw new TransformationFailedException(sprintf('The value "%s" is not a valid UUID.', $value), $e->getCode(), $e); - } - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php b/lib/symfony/form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php deleted file mode 100644 index 5249e3b36..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php +++ /dev/null @@ -1,85 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\DataTransformerInterface; -use Symfony\Component\Form\Exception\TransformationFailedException; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class ValueToDuplicatesTransformer implements DataTransformerInterface -{ - private $keys; - - public function __construct(array $keys) - { - $this->keys = $keys; - } - - /** - * Duplicates the given value through the array. - * - * @param mixed $value The value - * - * @return array - */ - public function transform($value) - { - $result = []; - - foreach ($this->keys as $key) { - $result[$key] = $value; - } - - return $result; - } - - /** - * Extracts the duplicated value from an array. - * - * @return mixed - * - * @throws TransformationFailedException if the given value is not an array or - * if the given array cannot be transformed - */ - public function reverseTransform($array) - { - if (!\is_array($array)) { - throw new TransformationFailedException('Expected an array.'); - } - - $result = current($array); - $emptyKeys = []; - - foreach ($this->keys as $key) { - if (isset($array[$key]) && '' !== $array[$key] && false !== $array[$key] && [] !== $array[$key]) { - if ($array[$key] !== $result) { - throw new TransformationFailedException('All values in the array should be the same.'); - } - } else { - $emptyKeys[] = $key; - } - } - - if (\count($emptyKeys) > 0) { - if (\count($emptyKeys) == \count($this->keys)) { - // All keys empty - return null; - } - - throw new TransformationFailedException(sprintf('The keys "%s" should not be empty.', implode('", "', $emptyKeys))); - } - - return $result; - } -} diff --git a/lib/symfony/form/Extension/Core/DataTransformer/WeekToArrayTransformer.php b/lib/symfony/form/Extension/Core/DataTransformer/WeekToArrayTransformer.php deleted file mode 100644 index d7349bbc9..000000000 --- a/lib/symfony/form/Extension/Core/DataTransformer/WeekToArrayTransformer.php +++ /dev/null @@ -1,105 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\DataTransformer; - -use Symfony\Component\Form\DataTransformerInterface; -use Symfony\Component\Form\Exception\TransformationFailedException; - -/** - * Transforms between an ISO 8601 week date string and an array. - * - * @author Damien Fayet <damienf1521@gmail.com> - */ -class WeekToArrayTransformer implements DataTransformerInterface -{ - /** - * Transforms a string containing an ISO 8601 week date into an array. - * - * @param string|null $value A week date string - * - * @return array{year: int|null, week: int|null} - * - * @throws TransformationFailedException If the given value is not a string, - * or if the given value does not follow the right format - */ - public function transform($value) - { - if (null === $value) { - return ['year' => null, 'week' => null]; - } - - if (!\is_string($value)) { - throw new TransformationFailedException(sprintf('Value is expected to be a string but was "%s".', get_debug_type($value))); - } - - if (0 === preg_match('/^(?P<year>\d{4})-W(?P<week>\d{2})$/', $value, $matches)) { - throw new TransformationFailedException('Given data does not follow the date format "Y-\WW".'); - } - - return [ - 'year' => (int) $matches['year'], - 'week' => (int) $matches['week'], - ]; - } - - /** - * Transforms an array into a week date string. - * - * @param array{year: int|null, week: int|null} $value - * - * @return string|null A week date string following the format Y-\WW - * - * @throws TransformationFailedException If the given value cannot be merged in a valid week date string, - * or if the obtained week date does not exists - */ - public function reverseTransform($value) - { - if (null === $value || [] === $value) { - return null; - } - - if (!\is_array($value)) { - throw new TransformationFailedException(sprintf('Value is expected to be an array, but was "%s".', get_debug_type($value))); - } - - if (!\array_key_exists('year', $value)) { - throw new TransformationFailedException('Key "year" is missing.'); - } - - if (!\array_key_exists('week', $value)) { - throw new TransformationFailedException('Key "week" is missing.'); - } - - if ($additionalKeys = array_diff(array_keys($value), ['year', 'week'])) { - throw new TransformationFailedException(sprintf('Expected only keys "year" and "week" to be present, but also got ["%s"].', implode('", "', $additionalKeys))); - } - - if (null === $value['year'] && null === $value['week']) { - return null; - } - - if (!\is_int($value['year'])) { - throw new TransformationFailedException(sprintf('Year is expected to be an integer, but was "%s".', get_debug_type($value['year']))); - } - - if (!\is_int($value['week'])) { - throw new TransformationFailedException(sprintf('Week is expected to be an integer, but was "%s".', get_debug_type($value['week']))); - } - - // The 28th December is always in the last week of the year - if (date('W', strtotime('28th December '.$value['year'])) < $value['week']) { - throw new TransformationFailedException(sprintf('Week "%d" does not exist for year "%d".', $value['week'], $value['year'])); - } - - return sprintf('%d-W%02d', $value['year'], $value['week']); - } -} diff --git a/lib/symfony/form/Extension/Core/EventListener/FixUrlProtocolListener.php b/lib/symfony/form/Extension/Core/EventListener/FixUrlProtocolListener.php deleted file mode 100644 index c49721228..000000000 --- a/lib/symfony/form/Extension/Core/EventListener/FixUrlProtocolListener.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Form\FormEvent; -use Symfony\Component\Form\FormEvents; - -/** - * Adds a protocol to a URL if it doesn't already have one. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class FixUrlProtocolListener implements EventSubscriberInterface -{ - private $defaultProtocol; - - /** - * @param string|null $defaultProtocol The URL scheme to add when there is none or null to not modify the data - */ - public function __construct(?string $defaultProtocol = 'http') - { - $this->defaultProtocol = $defaultProtocol; - } - - public function onSubmit(FormEvent $event) - { - $data = $event->getData(); - - if ($this->defaultProtocol && $data && \is_string($data) && !preg_match('~^(?:[/.]|[\w+.-]+://|[^:/?@#]++@)~', $data)) { - $event->setData($this->defaultProtocol.'://'.$data); - } - } - - public static function getSubscribedEvents() - { - return [FormEvents::SUBMIT => 'onSubmit']; - } -} diff --git a/lib/symfony/form/Extension/Core/EventListener/MergeCollectionListener.php b/lib/symfony/form/Extension/Core/EventListener/MergeCollectionListener.php deleted file mode 100644 index cd4a3b543..000000000 --- a/lib/symfony/form/Extension/Core/EventListener/MergeCollectionListener.php +++ /dev/null @@ -1,113 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Form\Exception\UnexpectedTypeException; -use Symfony\Component\Form\FormEvent; -use Symfony\Component\Form\FormEvents; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class MergeCollectionListener implements EventSubscriberInterface -{ - private $allowAdd; - private $allowDelete; - - /** - * @param bool $allowAdd Whether values might be added to the collection - * @param bool $allowDelete Whether values might be removed from the collection - */ - public function __construct(bool $allowAdd = false, bool $allowDelete = false) - { - $this->allowAdd = $allowAdd; - $this->allowDelete = $allowDelete; - } - - public static function getSubscribedEvents() - { - return [ - FormEvents::SUBMIT => 'onSubmit', - ]; - } - - public function onSubmit(FormEvent $event) - { - $dataToMergeInto = $event->getForm()->getNormData(); - $data = $event->getData(); - - if (null === $data) { - $data = []; - } - - if (!\is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) { - throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)'); - } - - if (null !== $dataToMergeInto && !\is_array($dataToMergeInto) && !($dataToMergeInto instanceof \Traversable && $dataToMergeInto instanceof \ArrayAccess)) { - throw new UnexpectedTypeException($dataToMergeInto, 'array or (\Traversable and \ArrayAccess)'); - } - - // If we are not allowed to change anything, return immediately - if ($data === $dataToMergeInto || (!$this->allowAdd && !$this->allowDelete)) { - $event->setData($dataToMergeInto); - - return; - } - - if (null === $dataToMergeInto) { - // No original data was set. Set it if allowed - if ($this->allowAdd) { - $dataToMergeInto = $data; - } - } else { - // Calculate delta - $itemsToAdd = \is_object($data) ? clone $data : $data; - $itemsToDelete = []; - - foreach ($dataToMergeInto as $beforeKey => $beforeItem) { - foreach ($data as $afterKey => $afterItem) { - if ($afterItem === $beforeItem) { - // Item found, next original item - unset($itemsToAdd[$afterKey]); - continue 2; - } - } - - // Item not found, remember for deletion - $itemsToDelete[] = $beforeKey; - } - - // Remove deleted items before adding to free keys that are to be - // replaced - if ($this->allowDelete) { - foreach ($itemsToDelete as $key) { - unset($dataToMergeInto[$key]); - } - } - - // Add remaining items - if ($this->allowAdd) { - foreach ($itemsToAdd as $key => $item) { - if (!isset($dataToMergeInto[$key])) { - $dataToMergeInto[$key] = $item; - } else { - $dataToMergeInto[] = $item; - } - } - } - } - - $event->setData($dataToMergeInto); - } -} diff --git a/lib/symfony/form/Extension/Core/EventListener/ResizeFormListener.php b/lib/symfony/form/Extension/Core/EventListener/ResizeFormListener.php deleted file mode 100644 index 813456b95..000000000 --- a/lib/symfony/form/Extension/Core/EventListener/ResizeFormListener.php +++ /dev/null @@ -1,169 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Form\Exception\UnexpectedTypeException; -use Symfony\Component\Form\FormEvent; -use Symfony\Component\Form\FormEvents; -use Symfony\Component\Form\FormInterface; - -/** - * Resize a collection form element based on the data sent from the client. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class ResizeFormListener implements EventSubscriberInterface -{ - protected $type; - protected $options; - protected $allowAdd; - protected $allowDelete; - - private $deleteEmpty; - - /** - * @param bool $allowAdd Whether children could be added to the group - * @param bool $allowDelete Whether children could be removed from the group - * @param bool|callable $deleteEmpty - */ - public function __construct(string $type, array $options = [], bool $allowAdd = false, bool $allowDelete = false, $deleteEmpty = false) - { - $this->type = $type; - $this->allowAdd = $allowAdd; - $this->allowDelete = $allowDelete; - $this->options = $options; - $this->deleteEmpty = $deleteEmpty; - } - - public static function getSubscribedEvents() - { - return [ - FormEvents::PRE_SET_DATA => 'preSetData', - FormEvents::PRE_SUBMIT => 'preSubmit', - // (MergeCollectionListener, MergeDoctrineCollectionListener) - FormEvents::SUBMIT => ['onSubmit', 50], - ]; - } - - public function preSetData(FormEvent $event) - { - $form = $event->getForm(); - $data = $event->getData(); - - if (null === $data) { - $data = []; - } - - if (!\is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) { - throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)'); - } - - // First remove all rows - foreach ($form as $name => $child) { - $form->remove($name); - } - - // Then add all rows again in the correct order - foreach ($data as $name => $value) { - $form->add($name, $this->type, array_replace([ - 'property_path' => '['.$name.']', - ], $this->options)); - } - } - - public function preSubmit(FormEvent $event) - { - $form = $event->getForm(); - $data = $event->getData(); - - if (!\is_array($data)) { - $data = []; - } - - // Remove all empty rows - if ($this->allowDelete) { - foreach ($form as $name => $child) { - if (!isset($data[$name])) { - $form->remove($name); - } - } - } - - // Add all additional rows - if ($this->allowAdd) { - foreach ($data as $name => $value) { - if (!$form->has($name)) { - $form->add($name, $this->type, array_replace([ - 'property_path' => '['.$name.']', - ], $this->options)); - } - } - } - } - - public function onSubmit(FormEvent $event) - { - $form = $event->getForm(); - $data = $event->getData(); - - // At this point, $data is an array or an array-like object that already contains the - // new entries, which were added by the data mapper. The data mapper ignores existing - // entries, so we need to manually unset removed entries in the collection. - - if (null === $data) { - $data = []; - } - - if (!\is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) { - throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)'); - } - - if ($this->deleteEmpty) { - $previousData = $form->getData(); - /** @var FormInterface $child */ - foreach ($form as $name => $child) { - if (!$child->isValid() || !$child->isSynchronized()) { - continue; - } - - $isNew = !isset($previousData[$name]); - $isEmpty = \is_callable($this->deleteEmpty) ? ($this->deleteEmpty)($child->getData()) : $child->isEmpty(); - - // $isNew can only be true if allowAdd is true, so we don't - // need to check allowAdd again - if ($isEmpty && ($isNew || $this->allowDelete)) { - unset($data[$name]); - $form->remove($name); - } - } - } - - // The data mapper only adds, but does not remove items, so do this - // here - if ($this->allowDelete) { - $toDelete = []; - - foreach ($data as $name => $child) { - if (!$form->has($name)) { - $toDelete[] = $name; - } - } - - foreach ($toDelete as $name) { - unset($data[$name]); - } - } - - $event->setData($data); - } -} diff --git a/lib/symfony/form/Extension/Core/EventListener/TransformationFailureListener.php b/lib/symfony/form/Extension/Core/EventListener/TransformationFailureListener.php deleted file mode 100644 index 70a7c19c2..000000000 --- a/lib/symfony/form/Extension/Core/EventListener/TransformationFailureListener.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Form\FormError; -use Symfony\Component\Form\FormEvent; -use Symfony\Component\Form\FormEvents; -use Symfony\Contracts\Translation\TranslatorInterface; - -/** - * @author Christian Flothmann <christian.flothmann@sensiolabs.de> - */ -class TransformationFailureListener implements EventSubscriberInterface -{ - private $translator; - - public function __construct(TranslatorInterface $translator = null) - { - $this->translator = $translator; - } - - public static function getSubscribedEvents() - { - return [ - FormEvents::POST_SUBMIT => ['convertTransformationFailureToFormError', -1024], - ]; - } - - public function convertTransformationFailureToFormError(FormEvent $event) - { - $form = $event->getForm(); - - if (null === $form->getTransformationFailure() || !$form->isValid()) { - return; - } - - foreach ($form as $child) { - if (!$child->isSynchronized()) { - return; - } - } - - $clientDataAsString = \is_scalar($form->getViewData()) ? (string) $form->getViewData() : get_debug_type($form->getViewData()); - $messageTemplate = $form->getConfig()->getOption('invalid_message', 'The value {{ value }} is not valid.'); - $messageParameters = array_replace(['{{ value }}' => $clientDataAsString], $form->getConfig()->getOption('invalid_message_parameters', [])); - - if (null !== $this->translator) { - $message = $this->translator->trans($messageTemplate, $messageParameters); - } else { - $message = strtr($messageTemplate, $messageParameters); - } - - $form->addError(new FormError($message, $messageTemplate, $messageParameters, null, $form->getTransformationFailure())); - } -} diff --git a/lib/symfony/form/Extension/Core/EventListener/TrimListener.php b/lib/symfony/form/Extension/Core/EventListener/TrimListener.php deleted file mode 100644 index be8c38a85..000000000 --- a/lib/symfony/form/Extension/Core/EventListener/TrimListener.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Form\FormEvent; -use Symfony\Component\Form\FormEvents; -use Symfony\Component\Form\Util\StringUtil; - -/** - * Trims string data. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class TrimListener implements EventSubscriberInterface -{ - public function preSubmit(FormEvent $event) - { - $data = $event->getData(); - - if (!\is_string($data)) { - return; - } - - $event->setData(StringUtil::trim($data)); - } - - public static function getSubscribedEvents() - { - return [FormEvents::PRE_SUBMIT => 'preSubmit']; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/BaseType.php b/lib/symfony/form/Extension/Core/Type/BaseType.php deleted file mode 100644 index 55efb652d..000000000 --- a/lib/symfony/form/Extension/Core/Type/BaseType.php +++ /dev/null @@ -1,161 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractRendererEngine; -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Exception\LogicException; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; -use Symfony\Component\OptionsResolver\OptionsResolver; - -/** - * Encapsulates common logic of {@link FormType} and {@link ButtonType}. - * - * This type does not appear in the form's type inheritance chain and as such - * cannot be extended (via {@link \Symfony\Component\Form\FormExtensionInterface}) nor themed. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -abstract class BaseType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - $builder->setDisabled($options['disabled']); - $builder->setAutoInitialize($options['auto_initialize']); - } - - /** - * {@inheritdoc} - */ - public function buildView(FormView $view, FormInterface $form, array $options) - { - $name = $form->getName(); - $blockName = $options['block_name'] ?: $form->getName(); - $translationDomain = $options['translation_domain']; - $labelTranslationParameters = $options['label_translation_parameters']; - $attrTranslationParameters = $options['attr_translation_parameters']; - $labelFormat = $options['label_format']; - - if ($view->parent) { - if ('' !== ($parentFullName = $view->parent->vars['full_name'])) { - $id = sprintf('%s_%s', $view->parent->vars['id'], $name); - $fullName = sprintf('%s[%s]', $parentFullName, $name); - $uniqueBlockPrefix = sprintf('%s_%s', $view->parent->vars['unique_block_prefix'], $blockName); - } else { - $id = $name; - $fullName = $name; - $uniqueBlockPrefix = '_'.$blockName; - } - - if (null === $translationDomain) { - $translationDomain = $view->parent->vars['translation_domain']; - } - - $labelTranslationParameters = array_merge($view->parent->vars['label_translation_parameters'], $labelTranslationParameters); - $attrTranslationParameters = array_merge($view->parent->vars['attr_translation_parameters'], $attrTranslationParameters); - - if (!$labelFormat) { - $labelFormat = $view->parent->vars['label_format']; - } - - $rootFormAttrOption = $form->getRoot()->getConfig()->getOption('form_attr'); - if ($options['form_attr'] || $rootFormAttrOption) { - $options['attr']['form'] = \is_string($rootFormAttrOption) ? $rootFormAttrOption : $form->getRoot()->getName(); - if (empty($options['attr']['form'])) { - throw new LogicException('"form_attr" option must be a string identifier on root form when it has no id.'); - } - } - } else { - $id = \is_string($options['form_attr']) ? $options['form_attr'] : $name; - $fullName = $name; - $uniqueBlockPrefix = '_'.$blockName; - - // Strip leading underscores and digits. These are allowed in - // form names, but not in HTML4 ID attributes. - // https://www.w3.org/TR/html401/struct/global#adef-id - $id = ltrim($id, '_0123456789'); - } - - $blockPrefixes = []; - for ($type = $form->getConfig()->getType(); null !== $type; $type = $type->getParent()) { - array_unshift($blockPrefixes, $type->getBlockPrefix()); - } - if (null !== $options['block_prefix']) { - $blockPrefixes[] = $options['block_prefix']; - } - $blockPrefixes[] = $uniqueBlockPrefix; - - $view->vars = array_replace($view->vars, [ - 'form' => $view, - 'id' => $id, - 'name' => $name, - 'full_name' => $fullName, - 'disabled' => $form->isDisabled(), - 'label' => $options['label'], - 'label_format' => $labelFormat, - 'label_html' => $options['label_html'], - 'multipart' => false, - 'attr' => $options['attr'], - 'block_prefixes' => $blockPrefixes, - 'unique_block_prefix' => $uniqueBlockPrefix, - 'row_attr' => $options['row_attr'], - 'translation_domain' => $translationDomain, - 'label_translation_parameters' => $labelTranslationParameters, - 'attr_translation_parameters' => $attrTranslationParameters, - 'priority' => $options['priority'], - // Using the block name here speeds up performance in collection - // forms, where each entry has the same full block name. - // Including the type is important too, because if rows of a - // collection form have different types (dynamically), they should - // be rendered differently. - // https://github.com/symfony/symfony/issues/5038 - AbstractRendererEngine::CACHE_KEY_VAR => $uniqueBlockPrefix.'_'.$form->getConfig()->getType()->getBlockPrefix(), - ]); - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - 'block_name' => null, - 'block_prefix' => null, - 'disabled' => false, - 'label' => null, - 'label_format' => null, - 'row_attr' => [], - 'label_html' => false, - 'label_translation_parameters' => [], - 'attr_translation_parameters' => [], - 'attr' => [], - 'translation_domain' => null, - 'auto_initialize' => true, - 'priority' => 0, - 'form_attr' => false, - ]); - - $resolver->setAllowedTypes('block_prefix', ['null', 'string']); - $resolver->setAllowedTypes('attr', 'array'); - $resolver->setAllowedTypes('row_attr', 'array'); - $resolver->setAllowedTypes('label_html', 'bool'); - $resolver->setAllowedTypes('priority', 'int'); - $resolver->setAllowedTypes('form_attr', ['bool', 'string']); - - $resolver->setInfo('priority', 'The form rendering priority (higher priorities will be rendered first)'); - } -} diff --git a/lib/symfony/form/Extension/Core/Type/BirthdayType.php b/lib/symfony/form/Extension/Core/Type/BirthdayType.php deleted file mode 100644 index 50d8b1e21..000000000 --- a/lib/symfony/form/Extension/Core/Type/BirthdayType.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class BirthdayType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - 'years' => range((int) date('Y') - 120, date('Y')), - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'Please enter a valid birthdate.'; - }, - ]); - - $resolver->setAllowedTypes('years', 'array'); - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - return DateType::class; - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'birthday'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/ButtonType.php b/lib/symfony/form/Extension/Core/Type/ButtonType.php deleted file mode 100644 index ba2f8dfe0..000000000 --- a/lib/symfony/form/Extension/Core/Type/ButtonType.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\ButtonTypeInterface; -use Symfony\Component\OptionsResolver\OptionsResolver; - -/** - * A form button. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class ButtonType extends BaseType implements ButtonTypeInterface -{ - /** - * {@inheritdoc} - */ - public function getParent() - { - return null; - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'button'; - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - parent::configureOptions($resolver); - - $resolver->setDefault('auto_initialize', false); - } -} diff --git a/lib/symfony/form/Extension/Core/Type/CheckboxType.php b/lib/symfony/form/Extension/Core/Type/CheckboxType.php deleted file mode 100644 index 6de35b9d4..000000000 --- a/lib/symfony/form/Extension/Core/Type/CheckboxType.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Extension\Core\DataTransformer\BooleanToStringTransformer; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class CheckboxType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - // Unlike in other types, where the data is NULL by default, it - // needs to be a Boolean here. setData(null) is not acceptable - // for checkboxes and radio buttons (unless a custom model - // transformer handles this case). - // We cannot solve this case via overriding the "data" option, because - // doing so also calls setDataLocked(true). - $builder->setData($options['data'] ?? false); - $builder->addViewTransformer(new BooleanToStringTransformer($options['value'], $options['false_values'])); - } - - /** - * {@inheritdoc} - */ - public function buildView(FormView $view, FormInterface $form, array $options) - { - $view->vars = array_replace($view->vars, [ - 'value' => $options['value'], - 'checked' => null !== $form->getViewData(), - ]); - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $emptyData = function (FormInterface $form, $viewData) { - return $viewData; - }; - - $resolver->setDefaults([ - 'value' => '1', - 'empty_data' => $emptyData, - 'compound' => false, - 'false_values' => [null], - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'The checkbox has an invalid value.'; - }, - 'is_empty_callback' => static function ($modelData): bool { - return false === $modelData; - }, - ]); - - $resolver->setAllowedTypes('false_values', 'array'); - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'checkbox'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/ChoiceType.php b/lib/symfony/form/Extension/Core/Type/ChoiceType.php deleted file mode 100644 index 3881d1fb8..000000000 --- a/lib/symfony/form/Extension/Core/Type/ChoiceType.php +++ /dev/null @@ -1,501 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\ChoiceList\ChoiceListInterface; -use Symfony\Component\Form\ChoiceList\Factory\Cache\ChoiceAttr; -use Symfony\Component\Form\ChoiceList\Factory\Cache\ChoiceFieldName; -use Symfony\Component\Form\ChoiceList\Factory\Cache\ChoiceFilter; -use Symfony\Component\Form\ChoiceList\Factory\Cache\ChoiceLabel; -use Symfony\Component\Form\ChoiceList\Factory\Cache\ChoiceLoader; -use Symfony\Component\Form\ChoiceList\Factory\Cache\ChoiceTranslationParameters; -use Symfony\Component\Form\ChoiceList\Factory\Cache\ChoiceValue; -use Symfony\Component\Form\ChoiceList\Factory\Cache\GroupBy; -use Symfony\Component\Form\ChoiceList\Factory\Cache\PreferredChoice; -use Symfony\Component\Form\ChoiceList\Factory\CachingFactoryDecorator; -use Symfony\Component\Form\ChoiceList\Factory\ChoiceListFactoryInterface; -use Symfony\Component\Form\ChoiceList\Factory\DefaultChoiceListFactory; -use Symfony\Component\Form\ChoiceList\Factory\PropertyAccessDecorator; -use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; -use Symfony\Component\Form\ChoiceList\View\ChoiceGroupView; -use Symfony\Component\Form\ChoiceList\View\ChoiceListView; -use Symfony\Component\Form\ChoiceList\View\ChoiceView; -use Symfony\Component\Form\Exception\TransformationFailedException; -use Symfony\Component\Form\Extension\Core\DataMapper\CheckboxListMapper; -use Symfony\Component\Form\Extension\Core\DataMapper\RadioListMapper; -use Symfony\Component\Form\Extension\Core\DataTransformer\ChoicesToValuesTransformer; -use Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToValueTransformer; -use Symfony\Component\Form\Extension\Core\EventListener\MergeCollectionListener; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormError; -use Symfony\Component\Form\FormEvent; -use Symfony\Component\Form\FormEvents; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; -use Symfony\Component\PropertyAccess\PropertyPath; -use Symfony\Contracts\Translation\TranslatorInterface; - -class ChoiceType extends AbstractType -{ - private $choiceListFactory; - private $translator; - - /** - * @param TranslatorInterface $translator - */ - public function __construct(ChoiceListFactoryInterface $choiceListFactory = null, $translator = null) - { - $this->choiceListFactory = $choiceListFactory ?? new CachingFactoryDecorator( - new PropertyAccessDecorator( - new DefaultChoiceListFactory() - ) - ); - - if (null !== $translator && !$translator instanceof TranslatorInterface) { - throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be han instance of "%s", "%s" given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator))); - } - $this->translator = $translator; - - // BC, to be removed in 6.0 - if ($this->choiceListFactory instanceof CachingFactoryDecorator) { - return; - } - - $ref = new \ReflectionMethod($this->choiceListFactory, 'createListFromChoices'); - - if ($ref->getNumberOfParameters() < 3) { - trigger_deprecation('symfony/form', '5.1', 'Not defining a third parameter "callable|null $filter" in "%s::%s()" is deprecated.', $ref->class, $ref->name); - } - } - - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - $unknownValues = []; - $choiceList = $this->createChoiceList($options); - $builder->setAttribute('choice_list', $choiceList); - - if ($options['expanded']) { - $builder->setDataMapper($options['multiple'] ? new CheckboxListMapper() : new RadioListMapper()); - - // Initialize all choices before doing the index check below. - // This helps in cases where index checks are optimized for non - // initialized choice lists. For example, when using an SQL driver, - // the index check would read in one SQL query and the initialization - // requires another SQL query. When the initialization is done first, - // one SQL query is sufficient. - - $choiceListView = $this->createChoiceListView($choiceList, $options); - $builder->setAttribute('choice_list_view', $choiceListView); - - // Check if the choices already contain the empty value - // Only add the placeholder option if this is not the case - if (null !== $options['placeholder'] && 0 === \count($choiceList->getChoicesForValues(['']))) { - $placeholderView = new ChoiceView(null, '', $options['placeholder']); - - // "placeholder" is a reserved name - $this->addSubForm($builder, 'placeholder', $placeholderView, $options); - } - - $this->addSubForms($builder, $choiceListView->preferredChoices, $options); - $this->addSubForms($builder, $choiceListView->choices, $options); - } - - if ($options['expanded'] || $options['multiple']) { - // Make sure that scalar, submitted values are converted to arrays - // which can be submitted to the checkboxes/radio buttons - $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use ($choiceList, $options, &$unknownValues) { - $form = $event->getForm(); - $data = $event->getData(); - - // Since the type always use mapper an empty array will not be - // considered as empty in Form::submit(), we need to evaluate - // empty data here so its value is submitted to sub forms - if (null === $data) { - $emptyData = $form->getConfig()->getEmptyData(); - $data = $emptyData instanceof \Closure ? $emptyData($form, $data) : $emptyData; - } - - // Convert the submitted data to a string, if scalar, before - // casting it to an array - if (!\is_array($data)) { - if ($options['multiple']) { - throw new TransformationFailedException('Expected an array.'); - } - - $data = (array) (string) $data; - } - - // A map from submitted values to integers - $valueMap = array_flip($data); - - // Make a copy of the value map to determine whether any unknown - // values were submitted - $unknownValues = $valueMap; - - // Reconstruct the data as mapping from child names to values - $knownValues = []; - - if ($options['expanded']) { - /** @var FormInterface $child */ - foreach ($form as $child) { - $value = $child->getConfig()->getOption('value'); - - // Add the value to $data with the child's name as key - if (isset($valueMap[$value])) { - $knownValues[$child->getName()] = $value; - unset($unknownValues[$value]); - continue; - } else { - $knownValues[$child->getName()] = null; - } - } - } else { - foreach ($data as $value) { - if ($choiceList->getChoicesForValues([$value])) { - $knownValues[] = $value; - unset($unknownValues[$value]); - } - } - } - - // The empty value is always known, independent of whether a - // field exists for it or not - unset($unknownValues['']); - - // Throw exception if unknown values were submitted (multiple choices will be handled in a different event listener below) - if (\count($unknownValues) > 0 && !$options['multiple']) { - throw new TransformationFailedException(sprintf('The choices "%s" do not exist in the choice list.', implode('", "', array_keys($unknownValues)))); - } - - $event->setData($knownValues); - }); - } - - if ($options['multiple']) { - $messageTemplate = $options['invalid_message'] ?? 'The value {{ value }} is not valid.'; - - $builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) use (&$unknownValues, $messageTemplate) { - // Throw exception if unknown values were submitted - if (\count($unknownValues) > 0) { - $form = $event->getForm(); - - $clientDataAsString = \is_scalar($form->getViewData()) ? (string) $form->getViewData() : (\is_array($form->getViewData()) ? implode('", "', array_keys($unknownValues)) : \gettype($form->getViewData())); - - if (null !== $this->translator) { - $message = $this->translator->trans($messageTemplate, ['{{ value }}' => $clientDataAsString], 'validators'); - } else { - $message = strtr($messageTemplate, ['{{ value }}' => $clientDataAsString]); - } - - $form->addError(new FormError($message, $messageTemplate, ['{{ value }}' => $clientDataAsString], null, new TransformationFailedException(sprintf('The choices "%s" do not exist in the choice list.', $clientDataAsString)))); - } - }); - - // <select> tag with "multiple" option or list of checkbox inputs - $builder->addViewTransformer(new ChoicesToValuesTransformer($choiceList)); - } else { - // <select> tag without "multiple" option or list of radio inputs - $builder->addViewTransformer(new ChoiceToValueTransformer($choiceList)); - } - - if ($options['multiple'] && $options['by_reference']) { - // Make sure the collection created during the client->norm - // transformation is merged back into the original collection - $builder->addEventSubscriber(new MergeCollectionListener(true, true)); - } - - // To avoid issues when the submitted choices are arrays (i.e. array to string conversions), - // we have to ensure that all elements of the submitted choice data are NULL, strings or ints. - $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) { - $data = $event->getData(); - - if (!\is_array($data)) { - return; - } - - foreach ($data as $v) { - if (null !== $v && !\is_string($v) && !\is_int($v)) { - throw new TransformationFailedException('All choices submitted must be NULL, strings or ints.'); - } - } - }, 256); - } - - /** - * {@inheritdoc} - */ - public function buildView(FormView $view, FormInterface $form, array $options) - { - $choiceTranslationDomain = $options['choice_translation_domain']; - if ($view->parent && null === $choiceTranslationDomain) { - $choiceTranslationDomain = $view->vars['translation_domain']; - } - - /** @var ChoiceListInterface $choiceList */ - $choiceList = $form->getConfig()->getAttribute('choice_list'); - - /** @var ChoiceListView $choiceListView */ - $choiceListView = $form->getConfig()->hasAttribute('choice_list_view') - ? $form->getConfig()->getAttribute('choice_list_view') - : $this->createChoiceListView($choiceList, $options); - - $view->vars = array_replace($view->vars, [ - 'multiple' => $options['multiple'], - 'expanded' => $options['expanded'], - 'preferred_choices' => $choiceListView->preferredChoices, - 'choices' => $choiceListView->choices, - 'separator' => '-------------------', - 'placeholder' => null, - 'choice_translation_domain' => $choiceTranslationDomain, - 'choice_translation_parameters' => $options['choice_translation_parameters'], - ]); - - // The decision, whether a choice is selected, is potentially done - // thousand of times during the rendering of a template. Provide a - // closure here that is optimized for the value of the form, to - // avoid making the type check inside the closure. - if ($options['multiple']) { - $view->vars['is_selected'] = function ($choice, array $values) { - return \in_array($choice, $values, true); - }; - } else { - $view->vars['is_selected'] = function ($choice, $value) { - return $choice === $value; - }; - } - - // Check if the choices already contain the empty value - $view->vars['placeholder_in_choices'] = $choiceListView->hasPlaceholder(); - - // Only add the empty value option if this is not the case - if (null !== $options['placeholder'] && !$view->vars['placeholder_in_choices']) { - $view->vars['placeholder'] = $options['placeholder']; - } - - if ($options['multiple'] && !$options['expanded']) { - // Add "[]" to the name in case a select tag with multiple options is - // displayed. Otherwise only one of the selected options is sent in the - // POST request. - $view->vars['full_name'] .= '[]'; - } - } - - /** - * {@inheritdoc} - */ - public function finishView(FormView $view, FormInterface $form, array $options) - { - if ($options['expanded']) { - // Radio buttons should have the same name as the parent - $childName = $view->vars['full_name']; - - // Checkboxes should append "[]" to allow multiple selection - if ($options['multiple']) { - $childName .= '[]'; - } - - foreach ($view as $childView) { - $childView->vars['full_name'] = $childName; - } - } - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $emptyData = function (Options $options) { - if ($options['expanded'] && !$options['multiple']) { - return null; - } - - if ($options['multiple']) { - return []; - } - - return ''; - }; - - $placeholderDefault = function (Options $options) { - return $options['required'] ? null : ''; - }; - - $placeholderNormalizer = function (Options $options, $placeholder) { - if ($options['multiple']) { - // never use an empty value for this case - return null; - } elseif ($options['required'] && ($options['expanded'] || isset($options['attr']['size']) && $options['attr']['size'] > 1)) { - // placeholder for required radio buttons or a select with size > 1 does not make sense - return null; - } elseif (false === $placeholder) { - // an empty value should be added but the user decided otherwise - return null; - } elseif ($options['expanded'] && '' === $placeholder) { - // never use an empty label for radio buttons - return 'None'; - } - - // empty value has been set explicitly - return $placeholder; - }; - - $compound = function (Options $options) { - return $options['expanded']; - }; - - $choiceTranslationDomainNormalizer = function (Options $options, $choiceTranslationDomain) { - if (true === $choiceTranslationDomain) { - return $options['translation_domain']; - } - - return $choiceTranslationDomain; - }; - - $resolver->setDefaults([ - 'multiple' => false, - 'expanded' => false, - 'choices' => [], - 'choice_filter' => null, - 'choice_loader' => null, - 'choice_label' => null, - 'choice_name' => null, - 'choice_value' => null, - 'choice_attr' => null, - 'choice_translation_parameters' => [], - 'preferred_choices' => [], - 'group_by' => null, - 'empty_data' => $emptyData, - 'placeholder' => $placeholderDefault, - 'error_bubbling' => false, - 'compound' => $compound, - // The view data is always a string or an array of strings, - // even if the "data" option is manually set to an object. - // See https://github.com/symfony/symfony/pull/5582 - 'data_class' => null, - 'choice_translation_domain' => true, - 'trim' => false, - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'The selected choice is invalid.'; - }, - ]); - - $resolver->setNormalizer('placeholder', $placeholderNormalizer); - $resolver->setNormalizer('choice_translation_domain', $choiceTranslationDomainNormalizer); - - $resolver->setAllowedTypes('choices', ['null', 'array', \Traversable::class]); - $resolver->setAllowedTypes('choice_translation_domain', ['null', 'bool', 'string']); - $resolver->setAllowedTypes('choice_loader', ['null', ChoiceLoaderInterface::class, ChoiceLoader::class]); - $resolver->setAllowedTypes('choice_filter', ['null', 'callable', 'string', PropertyPath::class, ChoiceFilter::class]); - $resolver->setAllowedTypes('choice_label', ['null', 'bool', 'callable', 'string', PropertyPath::class, ChoiceLabel::class]); - $resolver->setAllowedTypes('choice_name', ['null', 'callable', 'string', PropertyPath::class, ChoiceFieldName::class]); - $resolver->setAllowedTypes('choice_value', ['null', 'callable', 'string', PropertyPath::class, ChoiceValue::class]); - $resolver->setAllowedTypes('choice_attr', ['null', 'array', 'callable', 'string', PropertyPath::class, ChoiceAttr::class]); - $resolver->setAllowedTypes('choice_translation_parameters', ['null', 'array', 'callable', ChoiceTranslationParameters::class]); - $resolver->setAllowedTypes('preferred_choices', ['array', \Traversable::class, 'callable', 'string', PropertyPath::class, PreferredChoice::class]); - $resolver->setAllowedTypes('group_by', ['null', 'callable', 'string', PropertyPath::class, GroupBy::class]); - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'choice'; - } - - /** - * Adds the sub fields for an expanded choice field. - */ - private function addSubForms(FormBuilderInterface $builder, array $choiceViews, array $options) - { - foreach ($choiceViews as $name => $choiceView) { - // Flatten groups - if (\is_array($choiceView)) { - $this->addSubForms($builder, $choiceView, $options); - continue; - } - - if ($choiceView instanceof ChoiceGroupView) { - $this->addSubForms($builder, $choiceView->choices, $options); - continue; - } - - $this->addSubForm($builder, $name, $choiceView, $options); - } - } - - private function addSubForm(FormBuilderInterface $builder, string $name, ChoiceView $choiceView, array $options) - { - $choiceOpts = [ - 'value' => $choiceView->value, - 'label' => $choiceView->label, - 'label_html' => $options['label_html'], - 'attr' => $choiceView->attr, - 'label_translation_parameters' => $choiceView->labelTranslationParameters, - 'translation_domain' => $options['choice_translation_domain'], - 'block_name' => 'entry', - ]; - - if ($options['multiple']) { - $choiceType = CheckboxType::class; - // The user can check 0 or more checkboxes. If required - // is true, they are required to check all of them. - $choiceOpts['required'] = false; - } else { - $choiceType = RadioType::class; - } - - $builder->add($name, $choiceType, $choiceOpts); - } - - private function createChoiceList(array $options) - { - if (null !== $options['choice_loader']) { - return $this->choiceListFactory->createListFromLoader( - $options['choice_loader'], - $options['choice_value'], - $options['choice_filter'] - ); - } - - // Harden against NULL values (like in EntityType and ModelType) - $choices = null !== $options['choices'] ? $options['choices'] : []; - - return $this->choiceListFactory->createListFromChoices( - $choices, - $options['choice_value'], - $options['choice_filter'] - ); - } - - private function createChoiceListView(ChoiceListInterface $choiceList, array $options) - { - return $this->choiceListFactory->createView( - $choiceList, - $options['preferred_choices'], - $options['choice_label'], - $options['choice_name'], - $options['group_by'], - $options['choice_attr'], - $options['choice_translation_parameters'] - ); - } -} diff --git a/lib/symfony/form/Extension/Core/Type/CollectionType.php b/lib/symfony/form/Extension/Core/Type/CollectionType.php deleted file mode 100644 index 5cabf1665..000000000 --- a/lib/symfony/form/Extension/Core/Type/CollectionType.php +++ /dev/null @@ -1,142 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class CollectionType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - if ($options['allow_add'] && $options['prototype']) { - $prototypeOptions = array_replace([ - 'required' => $options['required'], - 'label' => $options['prototype_name'].'label__', - ], $options['entry_options']); - - if (null !== $options['prototype_data']) { - $prototypeOptions['data'] = $options['prototype_data']; - } - - $prototype = $builder->create($options['prototype_name'], $options['entry_type'], $prototypeOptions); - $builder->setAttribute('prototype', $prototype->getForm()); - } - - $resizeListener = new ResizeFormListener( - $options['entry_type'], - $options['entry_options'], - $options['allow_add'], - $options['allow_delete'], - $options['delete_empty'] - ); - - $builder->addEventSubscriber($resizeListener); - } - - /** - * {@inheritdoc} - */ - public function buildView(FormView $view, FormInterface $form, array $options) - { - $view->vars = array_replace($view->vars, [ - 'allow_add' => $options['allow_add'], - 'allow_delete' => $options['allow_delete'], - ]); - - if ($form->getConfig()->hasAttribute('prototype')) { - $prototype = $form->getConfig()->getAttribute('prototype'); - $view->vars['prototype'] = $prototype->setParent($form)->createView($view); - } - } - - /** - * {@inheritdoc} - */ - public function finishView(FormView $view, FormInterface $form, array $options) - { - $prefixOffset = -2; - // check if the entry type also defines a block prefix - /** @var FormInterface $entry */ - foreach ($form as $entry) { - if ($entry->getConfig()->getOption('block_prefix')) { - --$prefixOffset; - } - - break; - } - - foreach ($view as $entryView) { - array_splice($entryView->vars['block_prefixes'], $prefixOffset, 0, 'collection_entry'); - } - - /** @var FormInterface $prototype */ - if ($prototype = $form->getConfig()->getAttribute('prototype')) { - if ($view->vars['prototype']->vars['multipart']) { - $view->vars['multipart'] = true; - } - - if ($prefixOffset > -3 && $prototype->getConfig()->getOption('block_prefix')) { - --$prefixOffset; - } - - array_splice($view->vars['prototype']->vars['block_prefixes'], $prefixOffset, 0, 'collection_entry'); - } - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $entryOptionsNormalizer = function (Options $options, $value) { - $value['block_name'] = 'entry'; - - return $value; - }; - - $resolver->setDefaults([ - 'allow_add' => false, - 'allow_delete' => false, - 'prototype' => true, - 'prototype_data' => null, - 'prototype_name' => '__name__', - 'entry_type' => TextType::class, - 'entry_options' => [], - 'delete_empty' => false, - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'The collection is invalid.'; - }, - ]); - - $resolver->setNormalizer('entry_options', $entryOptionsNormalizer); - $resolver->setAllowedTypes('delete_empty', ['bool', 'callable']); - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'collection'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/ColorType.php b/lib/symfony/form/Extension/Core/Type/ColorType.php deleted file mode 100644 index 4609a1aff..000000000 --- a/lib/symfony/form/Extension/Core/Type/ColorType.php +++ /dev/null @@ -1,98 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormError; -use Symfony\Component\Form\FormEvent; -use Symfony\Component\Form\FormEvents; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; -use Symfony\Contracts\Translation\TranslatorInterface; - -class ColorType extends AbstractType -{ - /** - * @see https://www.w3.org/TR/html52/sec-forms.html#color-state-typecolor - */ - private const HTML5_PATTERN = '/^#[0-9a-f]{6}$/i'; - - private $translator; - - public function __construct(TranslatorInterface $translator = null) - { - $this->translator = $translator; - } - - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - if (!$options['html5']) { - return; - } - - $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event): void { - $value = $event->getData(); - if (null === $value || '' === $value) { - return; - } - - if (\is_string($value) && preg_match(self::HTML5_PATTERN, $value)) { - return; - } - - $messageTemplate = 'This value is not a valid HTML5 color.'; - $messageParameters = [ - '{{ value }}' => \is_scalar($value) ? (string) $value : \gettype($value), - ]; - $message = $this->translator ? $this->translator->trans($messageTemplate, $messageParameters, 'validators') : $messageTemplate; - - $event->getForm()->addError(new FormError($message, $messageTemplate, $messageParameters)); - }); - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - 'html5' => false, - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'Please select a valid color.'; - }, - ]); - - $resolver->setAllowedTypes('html5', 'bool'); - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - return TextType::class; - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'color'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/CountryType.php b/lib/symfony/form/Extension/Core/Type/CountryType.php deleted file mode 100644 index 85293bc28..000000000 --- a/lib/symfony/form/Extension/Core/Type/CountryType.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\ChoiceList\ChoiceList; -use Symfony\Component\Form\ChoiceList\Loader\IntlCallbackChoiceLoader; -use Symfony\Component\Form\Exception\LogicException; -use Symfony\Component\Intl\Countries; -use Symfony\Component\Intl\Intl; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class CountryType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - 'choice_loader' => function (Options $options) { - if (!class_exists(Intl::class)) { - throw new LogicException(sprintf('The "symfony/intl" component is required to use "%s". Try running "composer require symfony/intl".', static::class)); - } - - $choiceTranslationLocale = $options['choice_translation_locale']; - $alpha3 = $options['alpha3']; - - return ChoiceList::loader($this, new IntlCallbackChoiceLoader(function () use ($choiceTranslationLocale, $alpha3) { - return array_flip($alpha3 ? Countries::getAlpha3Names($choiceTranslationLocale) : Countries::getNames($choiceTranslationLocale)); - }), [$choiceTranslationLocale, $alpha3]); - }, - 'choice_translation_domain' => false, - 'choice_translation_locale' => null, - 'alpha3' => false, - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'Please select a valid country.'; - }, - ]); - - $resolver->setAllowedTypes('choice_translation_locale', ['null', 'string']); - $resolver->setAllowedTypes('alpha3', 'bool'); - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - return ChoiceType::class; - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'country'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/CurrencyType.php b/lib/symfony/form/Extension/Core/Type/CurrencyType.php deleted file mode 100644 index 427b493f7..000000000 --- a/lib/symfony/form/Extension/Core/Type/CurrencyType.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\ChoiceList\ChoiceList; -use Symfony\Component\Form\ChoiceList\Loader\IntlCallbackChoiceLoader; -use Symfony\Component\Form\Exception\LogicException; -use Symfony\Component\Intl\Currencies; -use Symfony\Component\Intl\Intl; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class CurrencyType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - 'choice_loader' => function (Options $options) { - if (!class_exists(Intl::class)) { - throw new LogicException(sprintf('The "symfony/intl" component is required to use "%s". Try running "composer require symfony/intl".', static::class)); - } - - $choiceTranslationLocale = $options['choice_translation_locale']; - - return ChoiceList::loader($this, new IntlCallbackChoiceLoader(function () use ($choiceTranslationLocale) { - return array_flip(Currencies::getNames($choiceTranslationLocale)); - }), $choiceTranslationLocale); - }, - 'choice_translation_domain' => false, - 'choice_translation_locale' => null, - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'Please select a valid currency.'; - }, - ]); - - $resolver->setAllowedTypes('choice_translation_locale', ['null', 'string']); - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - return ChoiceType::class; - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'currency'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/DateIntervalType.php b/lib/symfony/form/Extension/Core/Type/DateIntervalType.php deleted file mode 100644 index 4c05557fa..000000000 --- a/lib/symfony/form/Extension/Core/Type/DateIntervalType.php +++ /dev/null @@ -1,291 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Exception\InvalidConfigurationException; -use Symfony\Component\Form\Extension\Core\DataTransformer\DateIntervalToArrayTransformer; -use Symfony\Component\Form\Extension\Core\DataTransformer\DateIntervalToStringTransformer; -use Symfony\Component\Form\Extension\Core\DataTransformer\IntegerToLocalizedStringTransformer; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; -use Symfony\Component\Form\ReversedTransformer; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -/** - * @author Steffen Roßkamp <steffen.rosskamp@gimmickmedia.de> - */ -class DateIntervalType extends AbstractType -{ - private const TIME_PARTS = [ - 'years', - 'months', - 'weeks', - 'days', - 'hours', - 'minutes', - 'seconds', - ]; - private const WIDGETS = [ - 'text' => TextType::class, - 'integer' => IntegerType::class, - 'choice' => ChoiceType::class, - ]; - - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - if (!$options['with_years'] && !$options['with_months'] && !$options['with_weeks'] && !$options['with_days'] && !$options['with_hours'] && !$options['with_minutes'] && !$options['with_seconds']) { - throw new InvalidConfigurationException('You must enable at least one interval field.'); - } - if ($options['with_invert'] && 'single_text' === $options['widget']) { - throw new InvalidConfigurationException('The single_text widget does not support invertible intervals.'); - } - if ($options['with_weeks'] && $options['with_days']) { - throw new InvalidConfigurationException('You cannot enable weeks and days fields together.'); - } - $format = 'P'; - $parts = []; - if ($options['with_years']) { - $format .= '%yY'; - $parts[] = 'years'; - } - if ($options['with_months']) { - $format .= '%mM'; - $parts[] = 'months'; - } - if ($options['with_weeks']) { - $format .= '%wW'; - $parts[] = 'weeks'; - } - if ($options['with_days']) { - $format .= '%dD'; - $parts[] = 'days'; - } - if ($options['with_hours'] || $options['with_minutes'] || $options['with_seconds']) { - $format .= 'T'; - } - if ($options['with_hours']) { - $format .= '%hH'; - $parts[] = 'hours'; - } - if ($options['with_minutes']) { - $format .= '%iM'; - $parts[] = 'minutes'; - } - if ($options['with_seconds']) { - $format .= '%sS'; - $parts[] = 'seconds'; - } - if ($options['with_invert']) { - $parts[] = 'invert'; - } - if ('single_text' === $options['widget']) { - $builder->addViewTransformer(new DateIntervalToStringTransformer($format)); - } else { - foreach (self::TIME_PARTS as $part) { - if ($options['with_'.$part]) { - $childOptions = [ - 'error_bubbling' => true, - 'label' => $options['labels'][$part], - // Append generic carry-along options - 'required' => $options['required'], - 'translation_domain' => $options['translation_domain'], - // when compound the array entries are ignored, we need to cascade the configuration here - 'empty_data' => $options['empty_data'][$part] ?? null, - ]; - if ('choice' === $options['widget']) { - $childOptions['choice_translation_domain'] = false; - $childOptions['choices'] = $options[$part]; - $childOptions['placeholder'] = $options['placeholder'][$part]; - } - $childForm = $builder->create($part, self::WIDGETS[$options['widget']], $childOptions); - if ('integer' === $options['widget']) { - $childForm->addModelTransformer( - new ReversedTransformer( - new IntegerToLocalizedStringTransformer() - ) - ); - } - $builder->add($childForm); - } - } - if ($options['with_invert']) { - $builder->add('invert', CheckboxType::class, [ - 'label' => $options['labels']['invert'], - 'error_bubbling' => true, - 'required' => false, - 'translation_domain' => $options['translation_domain'], - ]); - } - $builder->addViewTransformer(new DateIntervalToArrayTransformer($parts, 'text' === $options['widget'])); - } - if ('string' === $options['input']) { - $builder->addModelTransformer( - new ReversedTransformer( - new DateIntervalToStringTransformer($format) - ) - ); - } elseif ('array' === $options['input']) { - $builder->addModelTransformer( - new ReversedTransformer( - new DateIntervalToArrayTransformer($parts) - ) - ); - } - } - - /** - * {@inheritdoc} - */ - public function buildView(FormView $view, FormInterface $form, array $options) - { - $vars = [ - 'widget' => $options['widget'], - 'with_invert' => $options['with_invert'], - ]; - foreach (self::TIME_PARTS as $part) { - $vars['with_'.$part] = $options['with_'.$part]; - } - $view->vars = array_replace($view->vars, $vars); - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $compound = function (Options $options) { - return 'single_text' !== $options['widget']; - }; - $emptyData = function (Options $options) { - return 'single_text' === $options['widget'] ? '' : []; - }; - - $placeholderDefault = function (Options $options) { - return $options['required'] ? null : ''; - }; - - $placeholderNormalizer = function (Options $options, $placeholder) use ($placeholderDefault) { - if (\is_array($placeholder)) { - $default = $placeholderDefault($options); - - return array_merge(array_fill_keys(self::TIME_PARTS, $default), $placeholder); - } - - return array_fill_keys(self::TIME_PARTS, $placeholder); - }; - - $labelsNormalizer = function (Options $options, array $labels) { - return array_replace([ - 'years' => null, - 'months' => null, - 'days' => null, - 'weeks' => null, - 'hours' => null, - 'minutes' => null, - 'seconds' => null, - 'invert' => 'Negative interval', - ], array_filter($labels, function ($label) { - return null !== $label; - })); - }; - - $resolver->setDefaults([ - 'with_years' => true, - 'with_months' => true, - 'with_days' => true, - 'with_weeks' => false, - 'with_hours' => false, - 'with_minutes' => false, - 'with_seconds' => false, - 'with_invert' => false, - 'years' => range(0, 100), - 'months' => range(0, 12), - 'weeks' => range(0, 52), - 'days' => range(0, 31), - 'hours' => range(0, 24), - 'minutes' => range(0, 60), - 'seconds' => range(0, 60), - 'widget' => 'choice', - 'input' => 'dateinterval', - 'placeholder' => $placeholderDefault, - 'by_reference' => true, - 'error_bubbling' => false, - // If initialized with a \DateInterval object, FormType initializes - // this option to "\DateInterval". Since the internal, normalized - // representation is not \DateInterval, but an array, we need to unset - // this option. - 'data_class' => null, - 'compound' => $compound, - 'empty_data' => $emptyData, - 'labels' => [], - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'Please choose a valid date interval.'; - }, - ]); - $resolver->setNormalizer('placeholder', $placeholderNormalizer); - $resolver->setNormalizer('labels', $labelsNormalizer); - - $resolver->setAllowedValues( - 'input', - [ - 'dateinterval', - 'string', - 'array', - ] - ); - $resolver->setAllowedValues( - 'widget', - [ - 'single_text', - 'text', - 'integer', - 'choice', - ] - ); - // Don't clone \DateInterval classes, as i.e. format() - // does not work after that - $resolver->setAllowedValues('by_reference', true); - - $resolver->setAllowedTypes('years', 'array'); - $resolver->setAllowedTypes('months', 'array'); - $resolver->setAllowedTypes('weeks', 'array'); - $resolver->setAllowedTypes('days', 'array'); - $resolver->setAllowedTypes('hours', 'array'); - $resolver->setAllowedTypes('minutes', 'array'); - $resolver->setAllowedTypes('seconds', 'array'); - $resolver->setAllowedTypes('with_years', 'bool'); - $resolver->setAllowedTypes('with_months', 'bool'); - $resolver->setAllowedTypes('with_weeks', 'bool'); - $resolver->setAllowedTypes('with_days', 'bool'); - $resolver->setAllowedTypes('with_hours', 'bool'); - $resolver->setAllowedTypes('with_minutes', 'bool'); - $resolver->setAllowedTypes('with_seconds', 'bool'); - $resolver->setAllowedTypes('with_invert', 'bool'); - $resolver->setAllowedTypes('labels', 'array'); - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'dateinterval'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/DateTimeType.php b/lib/symfony/form/Extension/Core/Type/DateTimeType.php deleted file mode 100644 index 2f397f8ed..000000000 --- a/lib/symfony/form/Extension/Core/Type/DateTimeType.php +++ /dev/null @@ -1,362 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Exception\LogicException; -use Symfony\Component\Form\Extension\Core\DataTransformer\ArrayToPartsTransformer; -use Symfony\Component\Form\Extension\Core\DataTransformer\DataTransformerChain; -use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeImmutableToDateTimeTransformer; -use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer; -use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToHtml5LocalDateTimeTransformer; -use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer; -use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer; -use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; -use Symfony\Component\Form\ReversedTransformer; -use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class DateTimeType extends AbstractType -{ - public const DEFAULT_DATE_FORMAT = \IntlDateFormatter::MEDIUM; - public const DEFAULT_TIME_FORMAT = \IntlDateFormatter::MEDIUM; - - /** - * The HTML5 datetime-local format as defined in - * http://w3c.github.io/html-reference/datatypes.html#form.data.datetime-local. - */ - public const HTML5_FORMAT = "yyyy-MM-dd'T'HH:mm:ss"; - - private const ACCEPTED_FORMATS = [ - \IntlDateFormatter::FULL, - \IntlDateFormatter::LONG, - \IntlDateFormatter::MEDIUM, - \IntlDateFormatter::SHORT, - ]; - - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - $parts = ['year', 'month', 'day', 'hour']; - $dateParts = ['year', 'month', 'day']; - $timeParts = ['hour']; - - if ($options['with_minutes']) { - $parts[] = 'minute'; - $timeParts[] = 'minute'; - } - - if ($options['with_seconds']) { - $parts[] = 'second'; - $timeParts[] = 'second'; - } - - $dateFormat = \is_int($options['date_format']) ? $options['date_format'] : self::DEFAULT_DATE_FORMAT; - $timeFormat = self::DEFAULT_TIME_FORMAT; - $calendar = \IntlDateFormatter::GREGORIAN; - $pattern = \is_string($options['format']) ? $options['format'] : null; - - if (!\in_array($dateFormat, self::ACCEPTED_FORMATS, true)) { - throw new InvalidOptionsException('The "date_format" option must be one of the IntlDateFormatter constants (FULL, LONG, MEDIUM, SHORT) or a string representing a custom format.'); - } - - if ('single_text' === $options['widget']) { - if (self::HTML5_FORMAT === $pattern) { - $builder->addViewTransformer(new DateTimeToHtml5LocalDateTimeTransformer( - $options['model_timezone'], - $options['view_timezone'] - )); - } else { - $builder->addViewTransformer(new DateTimeToLocalizedStringTransformer( - $options['model_timezone'], - $options['view_timezone'], - $dateFormat, - $timeFormat, - $calendar, - $pattern - )); - } - } else { - // when the form is compound the entries of the array are ignored in favor of children data - // so we need to handle the cascade setting here - $emptyData = $builder->getEmptyData() ?: []; - // Only pass a subset of the options to children - $dateOptions = array_intersect_key($options, array_flip([ - 'years', - 'months', - 'days', - 'placeholder', - 'choice_translation_domain', - 'required', - 'translation_domain', - 'html5', - 'invalid_message', - 'invalid_message_parameters', - ])); - - if ($emptyData instanceof \Closure) { - $lazyEmptyData = static function ($option) use ($emptyData) { - return static function (FormInterface $form) use ($emptyData, $option) { - $emptyData = $emptyData($form->getParent()); - - return $emptyData[$option] ?? ''; - }; - }; - - $dateOptions['empty_data'] = $lazyEmptyData('date'); - } elseif (isset($emptyData['date'])) { - $dateOptions['empty_data'] = $emptyData['date']; - } - - $timeOptions = array_intersect_key($options, array_flip([ - 'hours', - 'minutes', - 'seconds', - 'with_minutes', - 'with_seconds', - 'placeholder', - 'choice_translation_domain', - 'required', - 'translation_domain', - 'html5', - 'invalid_message', - 'invalid_message_parameters', - ])); - - if ($emptyData instanceof \Closure) { - $timeOptions['empty_data'] = $lazyEmptyData('time'); - } elseif (isset($emptyData['time'])) { - $timeOptions['empty_data'] = $emptyData['time']; - } - - if (false === $options['label']) { - $dateOptions['label'] = false; - $timeOptions['label'] = false; - } - - if (null !== $options['date_widget']) { - $dateOptions['widget'] = $options['date_widget']; - } - - if (null !== $options['date_label']) { - $dateOptions['label'] = $options['date_label']; - } - - if (null !== $options['time_widget']) { - $timeOptions['widget'] = $options['time_widget']; - } - - if (null !== $options['time_label']) { - $timeOptions['label'] = $options['time_label']; - } - - if (null !== $options['date_format']) { - $dateOptions['format'] = $options['date_format']; - } - - $dateOptions['input'] = $timeOptions['input'] = 'array'; - $dateOptions['error_bubbling'] = $timeOptions['error_bubbling'] = true; - - $builder - ->addViewTransformer(new DataTransformerChain([ - new DateTimeToArrayTransformer($options['model_timezone'], $options['view_timezone'], $parts), - new ArrayToPartsTransformer([ - 'date' => $dateParts, - 'time' => $timeParts, - ]), - ])) - ->add('date', DateType::class, $dateOptions) - ->add('time', TimeType::class, $timeOptions) - ; - } - - if ('datetime_immutable' === $options['input']) { - $builder->addModelTransformer(new DateTimeImmutableToDateTimeTransformer()); - } elseif ('string' === $options['input']) { - $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone'], $options['input_format']) - )); - } elseif ('timestamp' === $options['input']) { - $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToTimestampTransformer($options['model_timezone'], $options['model_timezone']) - )); - } elseif ('array' === $options['input']) { - $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], $parts) - )); - } - } - - /** - * {@inheritdoc} - */ - public function buildView(FormView $view, FormInterface $form, array $options) - { - $view->vars['widget'] = $options['widget']; - - // Change the input to an HTML5 datetime input if - // * the widget is set to "single_text" - // * the format matches the one expected by HTML5 - // * the html5 is set to true - if ($options['html5'] && 'single_text' === $options['widget'] && self::HTML5_FORMAT === $options['format']) { - $view->vars['type'] = 'datetime-local'; - - // we need to force the browser to display the seconds by - // adding the HTML attribute step if not already defined. - // Otherwise the browser will not display and so not send the seconds - // therefore the value will always be considered as invalid. - if ($options['with_seconds'] && !isset($view->vars['attr']['step'])) { - $view->vars['attr']['step'] = 1; - } - } - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $compound = function (Options $options) { - return 'single_text' !== $options['widget']; - }; - - // Defaults to the value of "widget" - $dateWidget = function (Options $options) { - return 'single_text' === $options['widget'] ? null : $options['widget']; - }; - - // Defaults to the value of "widget" - $timeWidget = function (Options $options) { - return 'single_text' === $options['widget'] ? null : $options['widget']; - }; - - $resolver->setDefaults([ - 'input' => 'datetime', - 'model_timezone' => null, - 'view_timezone' => null, - 'format' => self::HTML5_FORMAT, - 'date_format' => null, - 'widget' => null, - 'date_widget' => $dateWidget, - 'time_widget' => $timeWidget, - 'with_minutes' => true, - 'with_seconds' => false, - 'html5' => true, - // Don't modify \DateTime classes by reference, we treat - // them like immutable value objects - 'by_reference' => false, - 'error_bubbling' => false, - // If initialized with a \DateTime object, FormType initializes - // this option to "\DateTime". Since the internal, normalized - // representation is not \DateTime, but an array, we need to unset - // this option. - 'data_class' => null, - 'compound' => $compound, - 'date_label' => null, - 'time_label' => null, - 'empty_data' => function (Options $options) { - return $options['compound'] ? [] : ''; - }, - 'input_format' => 'Y-m-d H:i:s', - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'Please enter a valid date and time.'; - }, - ]); - - // Don't add some defaults in order to preserve the defaults - // set in DateType and TimeType - $resolver->setDefined([ - 'placeholder', - 'choice_translation_domain', - 'years', - 'months', - 'days', - 'hours', - 'minutes', - 'seconds', - ]); - - $resolver->setAllowedValues('input', [ - 'datetime', - 'datetime_immutable', - 'string', - 'timestamp', - 'array', - ]); - $resolver->setAllowedValues('date_widget', [ - null, // inherit default from DateType - 'single_text', - 'text', - 'choice', - ]); - $resolver->setAllowedValues('time_widget', [ - null, // inherit default from TimeType - 'single_text', - 'text', - 'choice', - ]); - // This option will overwrite "date_widget" and "time_widget" options - $resolver->setAllowedValues('widget', [ - null, // default, don't overwrite options - 'single_text', - 'text', - 'choice', - ]); - - $resolver->setAllowedTypes('input_format', 'string'); - - $resolver->setNormalizer('date_format', function (Options $options, $dateFormat) { - if (null !== $dateFormat && 'single_text' === $options['widget'] && self::HTML5_FORMAT === $options['format']) { - throw new LogicException(sprintf('Cannot use the "date_format" option of the "%s" with an HTML5 date.', self::class)); - } - - return $dateFormat; - }); - $resolver->setNormalizer('date_widget', function (Options $options, $dateWidget) { - if (null !== $dateWidget && 'single_text' === $options['widget']) { - throw new LogicException(sprintf('Cannot use the "date_widget" option of the "%s" when the "widget" option is set to "single_text".', self::class)); - } - - return $dateWidget; - }); - $resolver->setNormalizer('time_widget', function (Options $options, $timeWidget) { - if (null !== $timeWidget && 'single_text' === $options['widget']) { - throw new LogicException(sprintf('Cannot use the "time_widget" option of the "%s" when the "widget" option is set to "single_text".', self::class)); - } - - return $timeWidget; - }); - $resolver->setNormalizer('html5', function (Options $options, $html5) { - if ($html5 && self::HTML5_FORMAT !== $options['format']) { - throw new LogicException(sprintf('Cannot use the "format" option of "%s" when the "html5" option is enabled.', self::class)); - } - - return $html5; - }); - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'datetime'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/DateType.php b/lib/symfony/form/Extension/Core/Type/DateType.php deleted file mode 100644 index 1a46a8084..000000000 --- a/lib/symfony/form/Extension/Core/Type/DateType.php +++ /dev/null @@ -1,405 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Exception\LogicException; -use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeImmutableToDateTimeTransformer; -use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer; -use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer; -use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer; -use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; -use Symfony\Component\Form\ReversedTransformer; -use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class DateType extends AbstractType -{ - public const DEFAULT_FORMAT = \IntlDateFormatter::MEDIUM; - public const HTML5_FORMAT = 'yyyy-MM-dd'; - - private const ACCEPTED_FORMATS = [ - \IntlDateFormatter::FULL, - \IntlDateFormatter::LONG, - \IntlDateFormatter::MEDIUM, - \IntlDateFormatter::SHORT, - ]; - - private const WIDGETS = [ - 'text' => TextType::class, - 'choice' => ChoiceType::class, - ]; - - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - $dateFormat = \is_int($options['format']) ? $options['format'] : self::DEFAULT_FORMAT; - $timeFormat = \IntlDateFormatter::NONE; - $calendar = \IntlDateFormatter::GREGORIAN; - $pattern = \is_string($options['format']) ? $options['format'] : ''; - - if (!\in_array($dateFormat, self::ACCEPTED_FORMATS, true)) { - throw new InvalidOptionsException('The "format" option must be one of the IntlDateFormatter constants (FULL, LONG, MEDIUM, SHORT) or a string representing a custom format.'); - } - - if ('single_text' === $options['widget']) { - if ('' !== $pattern && !str_contains($pattern, 'y') && !str_contains($pattern, 'M') && !str_contains($pattern, 'd')) { - throw new InvalidOptionsException(sprintf('The "format" option should contain the letters "y", "M" or "d". Its current value is "%s".', $pattern)); - } - - $builder->addViewTransformer(new DateTimeToLocalizedStringTransformer( - $options['model_timezone'], - $options['view_timezone'], - $dateFormat, - $timeFormat, - $calendar, - $pattern - )); - } else { - if ('' !== $pattern && (!str_contains($pattern, 'y') || !str_contains($pattern, 'M') || !str_contains($pattern, 'd'))) { - throw new InvalidOptionsException(sprintf('The "format" option should contain the letters "y", "M" and "d". Its current value is "%s".', $pattern)); - } - - $yearOptions = $monthOptions = $dayOptions = [ - 'error_bubbling' => true, - 'empty_data' => '', - ]; - // when the form is compound the entries of the array are ignored in favor of children data - // so we need to handle the cascade setting here - $emptyData = $builder->getEmptyData() ?: []; - - if ($emptyData instanceof \Closure) { - $lazyEmptyData = static function ($option) use ($emptyData) { - return static function (FormInterface $form) use ($emptyData, $option) { - $emptyData = $emptyData($form->getParent()); - - return $emptyData[$option] ?? ''; - }; - }; - - $yearOptions['empty_data'] = $lazyEmptyData('year'); - $monthOptions['empty_data'] = $lazyEmptyData('month'); - $dayOptions['empty_data'] = $lazyEmptyData('day'); - } else { - if (isset($emptyData['year'])) { - $yearOptions['empty_data'] = $emptyData['year']; - } - if (isset($emptyData['month'])) { - $monthOptions['empty_data'] = $emptyData['month']; - } - if (isset($emptyData['day'])) { - $dayOptions['empty_data'] = $emptyData['day']; - } - } - - if (isset($options['invalid_message'])) { - $dayOptions['invalid_message'] = $options['invalid_message']; - $monthOptions['invalid_message'] = $options['invalid_message']; - $yearOptions['invalid_message'] = $options['invalid_message']; - } - - if (isset($options['invalid_message_parameters'])) { - $dayOptions['invalid_message_parameters'] = $options['invalid_message_parameters']; - $monthOptions['invalid_message_parameters'] = $options['invalid_message_parameters']; - $yearOptions['invalid_message_parameters'] = $options['invalid_message_parameters']; - } - - $formatter = new \IntlDateFormatter( - \Locale::getDefault(), - $dateFormat, - $timeFormat, - // see https://bugs.php.net/66323 - class_exists(\IntlTimeZone::class, false) ? \IntlTimeZone::createDefault() : null, - $calendar, - $pattern - ); - - // new \IntlDateFormatter may return null instead of false in case of failure, see https://bugs.php.net/66323 - if (!$formatter) { - throw new InvalidOptionsException(intl_get_error_message(), intl_get_error_code()); - } - - $formatter->setLenient(false); - - if ('choice' === $options['widget']) { - // Only pass a subset of the options to children - $yearOptions['choices'] = $this->formatTimestamps($formatter, '/y+/', $this->listYears($options['years'])); - $yearOptions['placeholder'] = $options['placeholder']['year']; - $yearOptions['choice_translation_domain'] = $options['choice_translation_domain']['year']; - $monthOptions['choices'] = $this->formatTimestamps($formatter, '/[M|L]+/', $this->listMonths($options['months'])); - $monthOptions['placeholder'] = $options['placeholder']['month']; - $monthOptions['choice_translation_domain'] = $options['choice_translation_domain']['month']; - $dayOptions['choices'] = $this->formatTimestamps($formatter, '/d+/', $this->listDays($options['days'])); - $dayOptions['placeholder'] = $options['placeholder']['day']; - $dayOptions['choice_translation_domain'] = $options['choice_translation_domain']['day']; - } - - // Append generic carry-along options - foreach (['required', 'translation_domain'] as $passOpt) { - $yearOptions[$passOpt] = $monthOptions[$passOpt] = $dayOptions[$passOpt] = $options[$passOpt]; - } - - $builder - ->add('year', self::WIDGETS[$options['widget']], $yearOptions) - ->add('month', self::WIDGETS[$options['widget']], $monthOptions) - ->add('day', self::WIDGETS[$options['widget']], $dayOptions) - ->addViewTransformer(new DateTimeToArrayTransformer( - $options['model_timezone'], $options['view_timezone'], ['year', 'month', 'day'] - )) - ->setAttribute('formatter', $formatter) - ; - } - - if ('datetime_immutable' === $options['input']) { - $builder->addModelTransformer(new DateTimeImmutableToDateTimeTransformer()); - } elseif ('string' === $options['input']) { - $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone'], $options['input_format']) - )); - } elseif ('timestamp' === $options['input']) { - $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToTimestampTransformer($options['model_timezone'], $options['model_timezone']) - )); - } elseif ('array' === $options['input']) { - $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], ['year', 'month', 'day']) - )); - } - } - - /** - * {@inheritdoc} - */ - public function finishView(FormView $view, FormInterface $form, array $options) - { - $view->vars['widget'] = $options['widget']; - - // Change the input to an HTML5 date input if - // * the widget is set to "single_text" - // * the format matches the one expected by HTML5 - // * the html5 is set to true - if ($options['html5'] && 'single_text' === $options['widget'] && self::HTML5_FORMAT === $options['format']) { - $view->vars['type'] = 'date'; - } - - if ($form->getConfig()->hasAttribute('formatter')) { - $pattern = $form->getConfig()->getAttribute('formatter')->getPattern(); - - // remove special characters unless the format was explicitly specified - if (!\is_string($options['format'])) { - // remove quoted strings first - $pattern = preg_replace('/\'[^\']+\'/', '', $pattern); - - // remove remaining special chars - $pattern = preg_replace('/[^yMd]+/', '', $pattern); - } - - // set right order with respect to locale (e.g.: de_DE=dd.MM.yy; en_US=M/d/yy) - // lookup various formats at http://userguide.icu-project.org/formatparse/datetime - if (preg_match('/^([yMd]+)[^yMd]*([yMd]+)[^yMd]*([yMd]+)$/', $pattern)) { - $pattern = preg_replace(['/y+/', '/M+/', '/d+/'], ['{{ year }}', '{{ month }}', '{{ day }}'], $pattern); - } else { - // default fallback - $pattern = '{{ year }}{{ month }}{{ day }}'; - } - - $view->vars['date_pattern'] = $pattern; - } - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $compound = function (Options $options) { - return 'single_text' !== $options['widget']; - }; - - $placeholderDefault = function (Options $options) { - return $options['required'] ? null : ''; - }; - - $placeholderNormalizer = function (Options $options, $placeholder) use ($placeholderDefault) { - if (\is_array($placeholder)) { - $default = $placeholderDefault($options); - - return array_merge( - ['year' => $default, 'month' => $default, 'day' => $default], - $placeholder - ); - } - - return [ - 'year' => $placeholder, - 'month' => $placeholder, - 'day' => $placeholder, - ]; - }; - - $choiceTranslationDomainNormalizer = function (Options $options, $choiceTranslationDomain) { - if (\is_array($choiceTranslationDomain)) { - $default = false; - - return array_replace( - ['year' => $default, 'month' => $default, 'day' => $default], - $choiceTranslationDomain - ); - } - - return [ - 'year' => $choiceTranslationDomain, - 'month' => $choiceTranslationDomain, - 'day' => $choiceTranslationDomain, - ]; - }; - - $format = function (Options $options) { - return 'single_text' === $options['widget'] ? self::HTML5_FORMAT : self::DEFAULT_FORMAT; - }; - - $resolver->setDefaults([ - 'years' => range((int) date('Y') - 5, (int) date('Y') + 5), - 'months' => range(1, 12), - 'days' => range(1, 31), - 'widget' => 'choice', - 'input' => 'datetime', - 'format' => $format, - 'model_timezone' => null, - 'view_timezone' => null, - 'placeholder' => $placeholderDefault, - 'html5' => true, - // Don't modify \DateTime classes by reference, we treat - // them like immutable value objects - 'by_reference' => false, - 'error_bubbling' => false, - // If initialized with a \DateTime object, FormType initializes - // this option to "\DateTime". Since the internal, normalized - // representation is not \DateTime, but an array, we need to unset - // this option. - 'data_class' => null, - 'compound' => $compound, - 'empty_data' => function (Options $options) { - return $options['compound'] ? [] : ''; - }, - 'choice_translation_domain' => false, - 'input_format' => 'Y-m-d', - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'Please enter a valid date.'; - }, - ]); - - $resolver->setNormalizer('placeholder', $placeholderNormalizer); - $resolver->setNormalizer('choice_translation_domain', $choiceTranslationDomainNormalizer); - - $resolver->setAllowedValues('input', [ - 'datetime', - 'datetime_immutable', - 'string', - 'timestamp', - 'array', - ]); - $resolver->setAllowedValues('widget', [ - 'single_text', - 'text', - 'choice', - ]); - - $resolver->setAllowedTypes('format', ['int', 'string']); - $resolver->setAllowedTypes('years', 'array'); - $resolver->setAllowedTypes('months', 'array'); - $resolver->setAllowedTypes('days', 'array'); - $resolver->setAllowedTypes('input_format', 'string'); - - $resolver->setNormalizer('html5', function (Options $options, $html5) { - if ($html5 && 'single_text' === $options['widget'] && self::HTML5_FORMAT !== $options['format']) { - throw new LogicException(sprintf('Cannot use the "format" option of "%s" when the "html5" option is enabled.', self::class)); - } - - return $html5; - }); - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'date'; - } - - private function formatTimestamps(\IntlDateFormatter $formatter, string $regex, array $timestamps) - { - $pattern = $formatter->getPattern(); - $timezone = $formatter->getTimeZoneId(); - $formattedTimestamps = []; - - $formatter->setTimeZone('UTC'); - - if (preg_match($regex, $pattern, $matches)) { - $formatter->setPattern($matches[0]); - - foreach ($timestamps as $timestamp => $choice) { - $formattedTimestamps[$formatter->format($timestamp)] = $choice; - } - - // I'd like to clone the formatter above, but then we get a - // segmentation fault, so let's restore the old state instead - $formatter->setPattern($pattern); - } - - $formatter->setTimeZone($timezone); - - return $formattedTimestamps; - } - - private function listYears(array $years) - { - $result = []; - - foreach ($years as $year) { - $result[\PHP_INT_SIZE === 4 ? \DateTime::createFromFormat('Y e', $year.' UTC')->format('U') : gmmktime(0, 0, 0, 6, 15, $year)] = $year; - } - - return $result; - } - - private function listMonths(array $months) - { - $result = []; - - foreach ($months as $month) { - $result[gmmktime(0, 0, 0, $month, 15)] = $month; - } - - return $result; - } - - private function listDays(array $days) - { - $result = []; - - foreach ($days as $day) { - $result[gmmktime(0, 0, 0, 5, $day)] = $day; - } - - return $result; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/EmailType.php b/lib/symfony/form/Extension/Core/Type/EmailType.php deleted file mode 100644 index 486bc0217..000000000 --- a/lib/symfony/form/Extension/Core/Type/EmailType.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class EmailType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'Please enter a valid email address.'; - }, - ]); - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - return TextType::class; - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'email'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/EnumType.php b/lib/symfony/form/Extension/Core/Type/EnumType.php deleted file mode 100644 index c251cdbd0..000000000 --- a/lib/symfony/form/Extension/Core/Type/EnumType.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -/** - * A choice type for native PHP enums. - * - * @author Alexander M. Turek <me@derrabus.de> - */ -final class EnumType extends AbstractType -{ - public function configureOptions(OptionsResolver $resolver): void - { - $resolver - ->setRequired(['class']) - ->setAllowedTypes('class', 'string') - ->setAllowedValues('class', \Closure::fromCallable('enum_exists')) - ->setDefault('choices', static function (Options $options): array { - return $options['class']::cases(); - }) - ->setDefault('choice_label', static function (\UnitEnum $choice): string { - return $choice->name; - }) - ->setDefault('choice_value', static function (Options $options): ?\Closure { - if (!is_a($options['class'], \BackedEnum::class, true)) { - return null; - } - - return static function (?\BackedEnum $choice): ?string { - if (null === $choice) { - return null; - } - - return (string) $choice->value; - }; - }) - ; - } - - public function getParent(): string - { - return ChoiceType::class; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/FileType.php b/lib/symfony/form/Extension/Core/Type/FileType.php deleted file mode 100644 index b66b7ff5d..000000000 --- a/lib/symfony/form/Extension/Core/Type/FileType.php +++ /dev/null @@ -1,255 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\FileUploadError; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormEvent; -use Symfony\Component\Form\FormEvents; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; -use Symfony\Contracts\Translation\TranslatorInterface; - -class FileType extends AbstractType -{ - public const KIB_BYTES = 1024; - public const MIB_BYTES = 1048576; - - private const SUFFIXES = [ - 1 => 'bytes', - self::KIB_BYTES => 'KiB', - self::MIB_BYTES => 'MiB', - ]; - - private $translator; - - public function __construct(TranslatorInterface $translator = null) - { - $this->translator = $translator; - } - - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - // Ensure that submitted data is always an uploaded file or an array of some - $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use ($options) { - $form = $event->getForm(); - $requestHandler = $form->getConfig()->getRequestHandler(); - - if ($options['multiple']) { - $data = []; - $files = $event->getData(); - - if (!\is_array($files)) { - $files = []; - } - - foreach ($files as $file) { - if ($requestHandler->isFileUpload($file)) { - $data[] = $file; - - if (method_exists($requestHandler, 'getUploadFileError') && null !== $errorCode = $requestHandler->getUploadFileError($file)) { - $form->addError($this->getFileUploadError($errorCode)); - } - } - } - - // Since the array is never considered empty in the view data format - // on submission, we need to evaluate the configured empty data here - if ([] === $data) { - $emptyData = $form->getConfig()->getEmptyData(); - $data = $emptyData instanceof \Closure ? $emptyData($form, $data) : $emptyData; - } - - $event->setData($data); - } elseif ($requestHandler->isFileUpload($event->getData()) && method_exists($requestHandler, 'getUploadFileError') && null !== $errorCode = $requestHandler->getUploadFileError($event->getData())) { - $form->addError($this->getFileUploadError($errorCode)); - } elseif (!$requestHandler->isFileUpload($event->getData())) { - $event->setData(null); - } - }); - } - - /** - * {@inheritdoc} - */ - public function buildView(FormView $view, FormInterface $form, array $options) - { - if ($options['multiple']) { - $view->vars['full_name'] .= '[]'; - $view->vars['attr']['multiple'] = 'multiple'; - } - - $view->vars = array_replace($view->vars, [ - 'type' => 'file', - 'value' => '', - ]); - } - - /** - * {@inheritdoc} - */ - public function finishView(FormView $view, FormInterface $form, array $options) - { - $view->vars['multipart'] = true; - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $dataClass = null; - if (class_exists(\Symfony\Component\HttpFoundation\File\File::class)) { - $dataClass = function (Options $options) { - return $options['multiple'] ? null : 'Symfony\Component\HttpFoundation\File\File'; - }; - } - - $emptyData = function (Options $options) { - return $options['multiple'] ? [] : null; - }; - - $resolver->setDefaults([ - 'compound' => false, - 'data_class' => $dataClass, - 'empty_data' => $emptyData, - 'multiple' => false, - 'allow_file_upload' => true, - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'Please select a valid file.'; - }, - ]); - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'file'; - } - - private function getFileUploadError(int $errorCode) - { - $messageParameters = []; - - if (\UPLOAD_ERR_INI_SIZE === $errorCode) { - [$limitAsString, $suffix] = $this->factorizeSizes(0, self::getMaxFilesize()); - $messageTemplate = 'The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.'; - $messageParameters = [ - '{{ limit }}' => $limitAsString, - '{{ suffix }}' => $suffix, - ]; - } elseif (\UPLOAD_ERR_FORM_SIZE === $errorCode) { - $messageTemplate = 'The file is too large.'; - } else { - $messageTemplate = 'The file could not be uploaded.'; - } - - if (null !== $this->translator) { - $message = $this->translator->trans($messageTemplate, $messageParameters, 'validators'); - } else { - $message = strtr($messageTemplate, $messageParameters); - } - - return new FileUploadError($message, $messageTemplate, $messageParameters); - } - - /** - * Returns the maximum size of an uploaded file as configured in php.ini. - * - * This method should be kept in sync with Symfony\Component\HttpFoundation\File\UploadedFile::getMaxFilesize(). - * - * @return int|float The maximum size of an uploaded file in bytes (returns float if size > PHP_INT_MAX) - */ - private static function getMaxFilesize() - { - $iniMax = strtolower(\ini_get('upload_max_filesize')); - - if ('' === $iniMax) { - return \PHP_INT_MAX; - } - - $max = ltrim($iniMax, '+'); - if (str_starts_with($max, '0x')) { - $max = \intval($max, 16); - } elseif (str_starts_with($max, '0')) { - $max = \intval($max, 8); - } else { - $max = (int) $max; - } - - switch (substr($iniMax, -1)) { - case 't': $max *= 1024; - // no break - case 'g': $max *= 1024; - // no break - case 'm': $max *= 1024; - // no break - case 'k': $max *= 1024; - } - - return $max; - } - - /** - * Converts the limit to the smallest possible number - * (i.e. try "MB", then "kB", then "bytes"). - * - * This method should be kept in sync with Symfony\Component\Validator\Constraints\FileValidator::factorizeSizes(). - * - * @param int|float $limit - */ - private function factorizeSizes(int $size, $limit) - { - $coef = self::MIB_BYTES; - $coefFactor = self::KIB_BYTES; - - $limitAsString = (string) ($limit / $coef); - - // Restrict the limit to 2 decimals (without rounding! we - // need the precise value) - while (self::moreDecimalsThan($limitAsString, 2)) { - $coef /= $coefFactor; - $limitAsString = (string) ($limit / $coef); - } - - // Convert size to the same measure, but round to 2 decimals - $sizeAsString = (string) round($size / $coef, 2); - - // If the size and limit produce the same string output - // (due to rounding), reduce the coefficient - while ($sizeAsString === $limitAsString) { - $coef /= $coefFactor; - $limitAsString = (string) ($limit / $coef); - $sizeAsString = (string) round($size / $coef, 2); - } - - return [$limitAsString, self::SUFFIXES[$coef]]; - } - - /** - * This method should be kept in sync with Symfony\Component\Validator\Constraints\FileValidator::moreDecimalsThan(). - */ - private static function moreDecimalsThan(string $double, int $numberOfDecimals): bool - { - return \strlen($double) > \strlen(round($double, $numberOfDecimals)); - } -} diff --git a/lib/symfony/form/Extension/Core/Type/FormType.php b/lib/symfony/form/Extension/Core/Type/FormType.php deleted file mode 100644 index bd8ba13a3..000000000 --- a/lib/symfony/form/Extension/Core/Type/FormType.php +++ /dev/null @@ -1,245 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\Exception\LogicException; -use Symfony\Component\Form\Extension\Core\DataAccessor\CallbackAccessor; -use Symfony\Component\Form\Extension\Core\DataAccessor\ChainAccessor; -use Symfony\Component\Form\Extension\Core\DataAccessor\PropertyPathAccessor; -use Symfony\Component\Form\Extension\Core\DataMapper\DataMapper; -use Symfony\Component\Form\Extension\Core\EventListener\TrimListener; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormConfigBuilderInterface; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; -use Symfony\Component\PropertyAccess\PropertyAccess; -use Symfony\Component\PropertyAccess\PropertyAccessorInterface; -use Symfony\Component\Translation\TranslatableMessage; - -class FormType extends BaseType -{ - private $dataMapper; - - public function __construct(PropertyAccessorInterface $propertyAccessor = null) - { - $this->dataMapper = new DataMapper(new ChainAccessor([ - new CallbackAccessor(), - new PropertyPathAccessor($propertyAccessor ?? PropertyAccess::createPropertyAccessor()), - ])); - } - - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - parent::buildForm($builder, $options); - - $isDataOptionSet = \array_key_exists('data', $options); - - $builder - ->setRequired($options['required']) - ->setErrorBubbling($options['error_bubbling']) - ->setEmptyData($options['empty_data']) - ->setPropertyPath($options['property_path']) - ->setMapped($options['mapped']) - ->setByReference($options['by_reference']) - ->setInheritData($options['inherit_data']) - ->setCompound($options['compound']) - ->setData($isDataOptionSet ? $options['data'] : null) - ->setDataLocked($isDataOptionSet) - ->setDataMapper($options['compound'] ? $this->dataMapper : null) - ->setMethod($options['method']) - ->setAction($options['action']); - - if ($options['trim']) { - $builder->addEventSubscriber(new TrimListener()); - } - - if (!method_exists($builder, 'setIsEmptyCallback')) { - trigger_deprecation('symfony/form', '5.1', 'Not implementing the "%s::setIsEmptyCallback()" method in "%s" is deprecated.', FormConfigBuilderInterface::class, get_debug_type($builder)); - - return; - } - - $builder->setIsEmptyCallback($options['is_empty_callback']); - } - - /** - * {@inheritdoc} - */ - public function buildView(FormView $view, FormInterface $form, array $options) - { - parent::buildView($view, $form, $options); - - $name = $form->getName(); - $helpTranslationParameters = $options['help_translation_parameters']; - - if ($view->parent) { - if ('' === $name) { - throw new LogicException('Form node with empty name can be used only as root form node.'); - } - - // Complex fields are read-only if they themselves or their parents are. - if (!isset($view->vars['attr']['readonly']) && isset($view->parent->vars['attr']['readonly']) && false !== $view->parent->vars['attr']['readonly']) { - $view->vars['attr']['readonly'] = true; - } - - $helpTranslationParameters = array_merge($view->parent->vars['help_translation_parameters'], $helpTranslationParameters); - } - - $formConfig = $form->getConfig(); - $view->vars = array_replace($view->vars, [ - 'errors' => $form->getErrors(), - 'valid' => $form->isSubmitted() ? $form->isValid() : true, - 'value' => $form->getViewData(), - 'data' => $form->getNormData(), - 'required' => $form->isRequired(), - 'size' => null, - 'label_attr' => $options['label_attr'], - 'help' => $options['help'], - 'help_attr' => $options['help_attr'], - 'help_html' => $options['help_html'], - 'help_translation_parameters' => $helpTranslationParameters, - 'compound' => $formConfig->getCompound(), - 'method' => $formConfig->getMethod(), - 'action' => $formConfig->getAction(), - 'submitted' => $form->isSubmitted(), - ]); - } - - /** - * {@inheritdoc} - */ - public function finishView(FormView $view, FormInterface $form, array $options) - { - $multipart = false; - - foreach ($view->children as $child) { - if ($child->vars['multipart']) { - $multipart = true; - break; - } - } - - $view->vars['multipart'] = $multipart; - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - parent::configureOptions($resolver); - - // Derive "data_class" option from passed "data" object - $dataClass = function (Options $options) { - return isset($options['data']) && \is_object($options['data']) ? \get_class($options['data']) : null; - }; - - // Derive "empty_data" closure from "data_class" option - $emptyData = function (Options $options) { - $class = $options['data_class']; - - if (null !== $class) { - return function (FormInterface $form) use ($class) { - return $form->isEmpty() && !$form->isRequired() ? null : new $class(); - }; - } - - return function (FormInterface $form) { - return $form->getConfig()->getCompound() ? [] : ''; - }; - }; - - // Wrap "post_max_size_message" in a closure to translate it lazily - $uploadMaxSizeMessage = function (Options $options) { - return function () use ($options) { - return $options['post_max_size_message']; - }; - }; - - // For any form that is not represented by a single HTML control, - // errors should bubble up by default - $errorBubbling = function (Options $options) { - return $options['compound'] && !$options['inherit_data']; - }; - - // If data is given, the form is locked to that data - // (independent of its value) - $resolver->setDefined([ - 'data', - ]); - - $resolver->setDefaults([ - 'data_class' => $dataClass, - 'empty_data' => $emptyData, - 'trim' => true, - 'required' => true, - 'property_path' => null, - 'mapped' => true, - 'by_reference' => true, - 'error_bubbling' => $errorBubbling, - 'label_attr' => [], - 'inherit_data' => false, - 'compound' => true, - 'method' => 'POST', - // According to RFC 2396 (http://www.ietf.org/rfc/rfc2396.txt) - // section 4.2., empty URIs are considered same-document references - 'action' => '', - 'attr' => [], - 'post_max_size_message' => 'The uploaded file was too large. Please try to upload a smaller file.', - 'upload_max_size_message' => $uploadMaxSizeMessage, // internal - 'allow_file_upload' => false, - 'help' => null, - 'help_attr' => [], - 'help_html' => false, - 'help_translation_parameters' => [], - 'invalid_message' => 'This value is not valid.', - 'invalid_message_parameters' => [], - 'is_empty_callback' => null, - 'getter' => null, - 'setter' => null, - ]); - - $resolver->setAllowedTypes('label_attr', 'array'); - $resolver->setAllowedTypes('action', 'string'); - $resolver->setAllowedTypes('upload_max_size_message', ['callable']); - $resolver->setAllowedTypes('help', ['string', 'null', TranslatableMessage::class]); - $resolver->setAllowedTypes('help_attr', 'array'); - $resolver->setAllowedTypes('help_html', 'bool'); - $resolver->setAllowedTypes('is_empty_callback', ['null', 'callable']); - $resolver->setAllowedTypes('getter', ['null', 'callable']); - $resolver->setAllowedTypes('setter', ['null', 'callable']); - - $resolver->setInfo('getter', 'A callable that accepts two arguments (the view data and the current form field) and must return a value.'); - $resolver->setInfo('setter', 'A callable that accepts three arguments (a reference to the view data, the submitted value and the current form field).'); - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - return null; - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'form'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/HiddenType.php b/lib/symfony/form/Extension/Core/Type/HiddenType.php deleted file mode 100644 index f4258ec01..000000000 --- a/lib/symfony/form/Extension/Core/Type/HiddenType.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class HiddenType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - // hidden fields cannot have a required attribute - 'required' => false, - // Pass errors to the parent - 'error_bubbling' => true, - 'compound' => false, - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'The hidden field is invalid.'; - }, - ]); - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'hidden'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/IntegerType.php b/lib/symfony/form/Extension/Core/Type/IntegerType.php deleted file mode 100644 index a1cd058a9..000000000 --- a/lib/symfony/form/Extension/Core/Type/IntegerType.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Extension\Core\DataTransformer\IntegerToLocalizedStringTransformer; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class IntegerType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - $builder->addViewTransformer(new IntegerToLocalizedStringTransformer($options['grouping'], $options['rounding_mode'], !$options['grouping'] ? 'en' : null)); - } - - /** - * {@inheritdoc} - */ - public function buildView(FormView $view, FormInterface $form, array $options) - { - if ($options['grouping']) { - $view->vars['type'] = 'text'; - } - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - 'grouping' => false, - // Integer cast rounds towards 0, so do the same when displaying fractions - 'rounding_mode' => \NumberFormatter::ROUND_DOWN, - 'compound' => false, - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'Please enter an integer.'; - }, - ]); - - $resolver->setAllowedValues('rounding_mode', [ - \NumberFormatter::ROUND_FLOOR, - \NumberFormatter::ROUND_DOWN, - \NumberFormatter::ROUND_HALFDOWN, - \NumberFormatter::ROUND_HALFEVEN, - \NumberFormatter::ROUND_HALFUP, - \NumberFormatter::ROUND_UP, - \NumberFormatter::ROUND_CEILING, - ]); - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'integer'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/LanguageType.php b/lib/symfony/form/Extension/Core/Type/LanguageType.php deleted file mode 100644 index 7bcbda207..000000000 --- a/lib/symfony/form/Extension/Core/Type/LanguageType.php +++ /dev/null @@ -1,96 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\ChoiceList\ChoiceList; -use Symfony\Component\Form\ChoiceList\Loader\IntlCallbackChoiceLoader; -use Symfony\Component\Form\Exception\LogicException; -use Symfony\Component\Intl\Exception\MissingResourceException; -use Symfony\Component\Intl\Intl; -use Symfony\Component\Intl\Languages; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class LanguageType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - 'choice_loader' => function (Options $options) { - if (!class_exists(Intl::class)) { - throw new LogicException(sprintf('The "symfony/intl" component is required to use "%s". Try running "composer require symfony/intl".', static::class)); - } - $choiceTranslationLocale = $options['choice_translation_locale']; - $useAlpha3Codes = $options['alpha3']; - $choiceSelfTranslation = $options['choice_self_translation']; - - return ChoiceList::loader($this, new IntlCallbackChoiceLoader(function () use ($choiceTranslationLocale, $useAlpha3Codes, $choiceSelfTranslation) { - if (true === $choiceSelfTranslation) { - foreach (Languages::getLanguageCodes() as $alpha2Code) { - try { - $languageCode = $useAlpha3Codes ? Languages::getAlpha3Code($alpha2Code) : $alpha2Code; - $languagesList[$languageCode] = Languages::getName($alpha2Code, $alpha2Code); - } catch (MissingResourceException $e) { - // ignore errors like "Couldn't read the indices for the locale 'meta'" - } - } - } else { - $languagesList = $useAlpha3Codes ? Languages::getAlpha3Names($choiceTranslationLocale) : Languages::getNames($choiceTranslationLocale); - } - - return array_flip($languagesList); - }), [$choiceTranslationLocale, $useAlpha3Codes, $choiceSelfTranslation]); - }, - 'choice_translation_domain' => false, - 'choice_translation_locale' => null, - 'alpha3' => false, - 'choice_self_translation' => false, - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'Please select a valid language.'; - }, - ]); - - $resolver->setAllowedTypes('choice_self_translation', ['bool']); - $resolver->setAllowedTypes('choice_translation_locale', ['null', 'string']); - $resolver->setAllowedTypes('alpha3', 'bool'); - - $resolver->setNormalizer('choice_self_translation', function (Options $options, $value) { - if (true === $value && $options['choice_translation_locale']) { - throw new LogicException('Cannot use the "choice_self_translation" and "choice_translation_locale" options at the same time. Remove one of them.'); - } - - return $value; - }); - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - return ChoiceType::class; - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'language'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/LocaleType.php b/lib/symfony/form/Extension/Core/Type/LocaleType.php deleted file mode 100644 index 14113e4ac..000000000 --- a/lib/symfony/form/Extension/Core/Type/LocaleType.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\ChoiceList\ChoiceList; -use Symfony\Component\Form\ChoiceList\Loader\IntlCallbackChoiceLoader; -use Symfony\Component\Form\Exception\LogicException; -use Symfony\Component\Intl\Intl; -use Symfony\Component\Intl\Locales; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class LocaleType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - 'choice_loader' => function (Options $options) { - if (!class_exists(Intl::class)) { - throw new LogicException(sprintf('The "symfony/intl" component is required to use "%s". Try running "composer require symfony/intl".', static::class)); - } - - $choiceTranslationLocale = $options['choice_translation_locale']; - - return ChoiceList::loader($this, new IntlCallbackChoiceLoader(function () use ($choiceTranslationLocale) { - return array_flip(Locales::getNames($choiceTranslationLocale)); - }), $choiceTranslationLocale); - }, - 'choice_translation_domain' => false, - 'choice_translation_locale' => null, - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'Please select a valid locale.'; - }, - ]); - - $resolver->setAllowedTypes('choice_translation_locale', ['null', 'string']); - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - return ChoiceType::class; - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'locale'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/MoneyType.php b/lib/symfony/form/Extension/Core/Type/MoneyType.php deleted file mode 100644 index 6bf7a201f..000000000 --- a/lib/symfony/form/Extension/Core/Type/MoneyType.php +++ /dev/null @@ -1,149 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Exception\LogicException; -use Symfony\Component\Form\Extension\Core\DataTransformer\MoneyToLocalizedStringTransformer; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class MoneyType extends AbstractType -{ - protected static $patterns = []; - - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - // Values used in HTML5 number inputs should be formatted as in "1234.5", ie. 'en' format without grouping, - // according to https://www.w3.org/TR/html51/sec-forms.html#date-time-and-number-formats - $builder - ->addViewTransformer(new MoneyToLocalizedStringTransformer( - $options['scale'], - $options['grouping'], - $options['rounding_mode'], - $options['divisor'], - $options['html5'] ? 'en' : null - )) - ; - } - - /** - * {@inheritdoc} - */ - public function buildView(FormView $view, FormInterface $form, array $options) - { - $view->vars['money_pattern'] = self::getPattern($options['currency']); - - if ($options['html5']) { - $view->vars['type'] = 'number'; - } - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - 'scale' => 2, - 'grouping' => false, - 'rounding_mode' => \NumberFormatter::ROUND_HALFUP, - 'divisor' => 1, - 'currency' => 'EUR', - 'compound' => false, - 'html5' => false, - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'Please enter a valid money amount.'; - }, - ]); - - $resolver->setAllowedValues('rounding_mode', [ - \NumberFormatter::ROUND_FLOOR, - \NumberFormatter::ROUND_DOWN, - \NumberFormatter::ROUND_HALFDOWN, - \NumberFormatter::ROUND_HALFEVEN, - \NumberFormatter::ROUND_HALFUP, - \NumberFormatter::ROUND_UP, - \NumberFormatter::ROUND_CEILING, - ]); - - $resolver->setAllowedTypes('scale', 'int'); - - $resolver->setAllowedTypes('html5', 'bool'); - - $resolver->setNormalizer('grouping', function (Options $options, $value) { - if ($value && $options['html5']) { - throw new LogicException('Cannot use the "grouping" option when the "html5" option is enabled.'); - } - - return $value; - }); - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'money'; - } - - /** - * Returns the pattern for this locale in UTF-8. - * - * The pattern contains the placeholder "{{ widget }}" where the HTML tag should - * be inserted - */ - protected static function getPattern(?string $currency) - { - if (!$currency) { - return '{{ widget }}'; - } - - $locale = \Locale::getDefault(); - - if (!isset(self::$patterns[$locale])) { - self::$patterns[$locale] = []; - } - - if (!isset(self::$patterns[$locale][$currency])) { - $format = new \NumberFormatter($locale, \NumberFormatter::CURRENCY); - $pattern = $format->formatCurrency('123', $currency); - - // the spacings between currency symbol and number are ignored, because - // a single space leads to better readability in combination with input - // fields - - // the regex also considers non-break spaces (0xC2 or 0xA0 in UTF-8) - - preg_match('/^([^\s\xc2\xa0]*)[\s\xc2\xa0]*123(?:[,.]0+)?[\s\xc2\xa0]*([^\s\xc2\xa0]*)$/u', $pattern, $matches); - - if (!empty($matches[1])) { - self::$patterns[$locale][$currency] = $matches[1].' {{ widget }}'; - } elseif (!empty($matches[2])) { - self::$patterns[$locale][$currency] = '{{ widget }} '.$matches[2]; - } else { - self::$patterns[$locale][$currency] = '{{ widget }}'; - } - } - - return self::$patterns[$locale][$currency]; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/NumberType.php b/lib/symfony/form/Extension/Core/Type/NumberType.php deleted file mode 100644 index 2f6ac6cc2..000000000 --- a/lib/symfony/form/Extension/Core/Type/NumberType.php +++ /dev/null @@ -1,102 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Exception\LogicException; -use Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer; -use Symfony\Component\Form\Extension\Core\DataTransformer\StringToFloatTransformer; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class NumberType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - $builder->addViewTransformer(new NumberToLocalizedStringTransformer( - $options['scale'], - $options['grouping'], - $options['rounding_mode'], - $options['html5'] ? 'en' : null - )); - - if ('string' === $options['input']) { - $builder->addModelTransformer(new StringToFloatTransformer($options['scale'])); - } - } - - /** - * {@inheritdoc} - */ - public function buildView(FormView $view, FormInterface $form, array $options) - { - if ($options['html5']) { - $view->vars['type'] = 'number'; - } - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - // default scale is locale specific (usually around 3) - 'scale' => null, - 'grouping' => false, - 'rounding_mode' => \NumberFormatter::ROUND_HALFUP, - 'compound' => false, - 'input' => 'number', - 'html5' => false, - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'Please enter a number.'; - }, - ]); - - $resolver->setAllowedValues('rounding_mode', [ - \NumberFormatter::ROUND_FLOOR, - \NumberFormatter::ROUND_DOWN, - \NumberFormatter::ROUND_HALFDOWN, - \NumberFormatter::ROUND_HALFEVEN, - \NumberFormatter::ROUND_HALFUP, - \NumberFormatter::ROUND_UP, - \NumberFormatter::ROUND_CEILING, - ]); - $resolver->setAllowedValues('input', ['number', 'string']); - $resolver->setAllowedTypes('scale', ['null', 'int']); - $resolver->setAllowedTypes('html5', 'bool'); - - $resolver->setNormalizer('grouping', function (Options $options, $value) { - if (true === $value && $options['html5']) { - throw new LogicException('Cannot use the "grouping" option when the "html5" option is enabled.'); - } - - return $value; - }); - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'number'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/PasswordType.php b/lib/symfony/form/Extension/Core/Type/PasswordType.php deleted file mode 100644 index 779f94d43..000000000 --- a/lib/symfony/form/Extension/Core/Type/PasswordType.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class PasswordType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function buildView(FormView $view, FormInterface $form, array $options) - { - if ($options['always_empty'] || !$form->isSubmitted()) { - $view->vars['value'] = ''; - } - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - 'always_empty' => true, - 'trim' => false, - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'The password is invalid.'; - }, - ]); - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - return TextType::class; - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'password'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/PercentType.php b/lib/symfony/form/Extension/Core/Type/PercentType.php deleted file mode 100644 index 90e8fa6e1..000000000 --- a/lib/symfony/form/Extension/Core/Type/PercentType.php +++ /dev/null @@ -1,105 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Extension\Core\DataTransformer\PercentToLocalizedStringTransformer; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class PercentType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - $builder->addViewTransformer(new PercentToLocalizedStringTransformer( - $options['scale'], - $options['type'], - $options['rounding_mode'], - $options['html5'] - )); - } - - /** - * {@inheritdoc} - */ - public function buildView(FormView $view, FormInterface $form, array $options) - { - $view->vars['symbol'] = $options['symbol']; - - if ($options['html5']) { - $view->vars['type'] = 'number'; - } - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - 'scale' => 0, - 'rounding_mode' => function (Options $options) { - trigger_deprecation('symfony/form', '5.1', 'Not configuring the "rounding_mode" option is deprecated. It will default to "\NumberFormatter::ROUND_HALFUP" in Symfony 6.0.'); - - return null; - }, - 'symbol' => '%', - 'type' => 'fractional', - 'compound' => false, - 'html5' => false, - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'Please enter a percentage value.'; - }, - ]); - - $resolver->setAllowedValues('type', [ - 'fractional', - 'integer', - ]); - $resolver->setAllowedValues('rounding_mode', [ - null, - \NumberFormatter::ROUND_FLOOR, - \NumberFormatter::ROUND_DOWN, - \NumberFormatter::ROUND_HALFDOWN, - \NumberFormatter::ROUND_HALFEVEN, - \NumberFormatter::ROUND_HALFUP, - \NumberFormatter::ROUND_UP, - \NumberFormatter::ROUND_CEILING, - ]); - $resolver->setAllowedTypes('scale', 'int'); - $resolver->setAllowedTypes('symbol', ['bool', 'string']); - $resolver->setDeprecated('rounding_mode', 'symfony/form', '5.1', function (Options $options, $roundingMode) { - if (null === $roundingMode) { - return 'Not configuring the "rounding_mode" option is deprecated. It will default to "\NumberFormatter::ROUND_HALFUP" in Symfony 6.0.'; - } - - return ''; - }); - $resolver->setAllowedTypes('html5', 'bool'); - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'percent'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/RadioType.php b/lib/symfony/form/Extension/Core/Type/RadioType.php deleted file mode 100644 index ed999f52b..000000000 --- a/lib/symfony/form/Extension/Core/Type/RadioType.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class RadioType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'Please select a valid option.'; - }, - ]); - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - return CheckboxType::class; - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'radio'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/RangeType.php b/lib/symfony/form/Extension/Core/Type/RangeType.php deleted file mode 100644 index 73ec6e163..000000000 --- a/lib/symfony/form/Extension/Core/Type/RangeType.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class RangeType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'Please choose a valid range.'; - }, - ]); - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - return TextType::class; - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'range'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/RepeatedType.php b/lib/symfony/form/Extension/Core/Type/RepeatedType.php deleted file mode 100644 index 16fa1a7bb..000000000 --- a/lib/symfony/form/Extension/Core/Type/RepeatedType.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Extension\Core\DataTransformer\ValueToDuplicatesTransformer; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class RepeatedType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - // Overwrite required option for child fields - $options['first_options']['required'] = $options['required']; - $options['second_options']['required'] = $options['required']; - - if (!isset($options['options']['error_bubbling'])) { - $options['options']['error_bubbling'] = $options['error_bubbling']; - } - - // children fields must always be mapped - $defaultOptions = ['mapped' => true]; - - $builder - ->addViewTransformer(new ValueToDuplicatesTransformer([ - $options['first_name'], - $options['second_name'], - ])) - ->add($options['first_name'], $options['type'], array_merge($options['options'], $options['first_options'], $defaultOptions)) - ->add($options['second_name'], $options['type'], array_merge($options['options'], $options['second_options'], $defaultOptions)) - ; - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - 'type' => TextType::class, - 'options' => [], - 'first_options' => [], - 'second_options' => [], - 'first_name' => 'first', - 'second_name' => 'second', - 'error_bubbling' => false, - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'The values do not match.'; - }, - ]); - - $resolver->setAllowedTypes('options', 'array'); - $resolver->setAllowedTypes('first_options', 'array'); - $resolver->setAllowedTypes('second_options', 'array'); - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'repeated'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/ResetType.php b/lib/symfony/form/Extension/Core/Type/ResetType.php deleted file mode 100644 index ce8013d1b..000000000 --- a/lib/symfony/form/Extension/Core/Type/ResetType.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\ButtonTypeInterface; - -/** - * A reset button. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class ResetType extends AbstractType implements ButtonTypeInterface -{ - /** - * {@inheritdoc} - */ - public function getParent() - { - return ButtonType::class; - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'reset'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/SearchType.php b/lib/symfony/form/Extension/Core/Type/SearchType.php deleted file mode 100644 index 682277e61..000000000 --- a/lib/symfony/form/Extension/Core/Type/SearchType.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class SearchType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'Please enter a valid search term.'; - }, - ]); - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - return TextType::class; - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'search'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/SubmitType.php b/lib/symfony/form/Extension/Core/Type/SubmitType.php deleted file mode 100644 index 945156efc..000000000 --- a/lib/symfony/form/Extension/Core/Type/SubmitType.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; -use Symfony\Component\Form\SubmitButtonTypeInterface; -use Symfony\Component\OptionsResolver\OptionsResolver; - -/** - * A submit button. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class SubmitType extends AbstractType implements SubmitButtonTypeInterface -{ - public function buildView(FormView $view, FormInterface $form, array $options) - { - $view->vars['clicked'] = $form->isClicked(); - - if (!$options['validate']) { - $view->vars['attr']['formnovalidate'] = true; - } - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefault('validate', true); - $resolver->setAllowedTypes('validate', 'bool'); - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - return ButtonType::class; - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'submit'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/TelType.php b/lib/symfony/form/Extension/Core/Type/TelType.php deleted file mode 100644 index bc25fd94c..000000000 --- a/lib/symfony/form/Extension/Core/Type/TelType.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class TelType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'Please provide a valid phone number.'; - }, - ]); - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - return TextType::class; - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'tel'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/TextType.php b/lib/symfony/form/Extension/Core/Type/TextType.php deleted file mode 100644 index 72d21c3dd..000000000 --- a/lib/symfony/form/Extension/Core/Type/TextType.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\DataTransformerInterface; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class TextType extends AbstractType implements DataTransformerInterface -{ - public function buildForm(FormBuilderInterface $builder, array $options) - { - // When empty_data is explicitly set to an empty string, - // a string should always be returned when NULL is submitted - // This gives more control and thus helps preventing some issues - // with PHP 7 which allows type hinting strings in functions - // See https://github.com/symfony/symfony/issues/5906#issuecomment-203189375 - if ('' === $options['empty_data']) { - $builder->addViewTransformer($this); - } - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - 'compound' => false, - ]); - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'text'; - } - - /** - * {@inheritdoc} - */ - public function transform($data) - { - // Model data should not be transformed - return $data; - } - - /** - * {@inheritdoc} - */ - public function reverseTransform($data) - { - return $data ?? ''; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/TextareaType.php b/lib/symfony/form/Extension/Core/Type/TextareaType.php deleted file mode 100644 index 173b7ef53..000000000 --- a/lib/symfony/form/Extension/Core/Type/TextareaType.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; - -class TextareaType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function buildView(FormView $view, FormInterface $form, array $options) - { - $view->vars['pattern'] = null; - unset($view->vars['attr']['pattern']); - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - return TextType::class; - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'textarea'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/TimeType.php b/lib/symfony/form/Extension/Core/Type/TimeType.php deleted file mode 100644 index 6b56a120e..000000000 --- a/lib/symfony/form/Extension/Core/Type/TimeType.php +++ /dev/null @@ -1,388 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Exception\InvalidConfigurationException; -use Symfony\Component\Form\Exception\LogicException; -use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeImmutableToDateTimeTransformer; -use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer; -use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer; -use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormEvent; -use Symfony\Component\Form\FormEvents; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; -use Symfony\Component\Form\ReversedTransformer; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class TimeType extends AbstractType -{ - private const WIDGETS = [ - 'text' => TextType::class, - 'choice' => ChoiceType::class, - ]; - - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - $parts = ['hour']; - $format = 'H'; - - if ($options['with_seconds'] && !$options['with_minutes']) { - throw new InvalidConfigurationException('You cannot disable minutes if you have enabled seconds.'); - } - - if (null !== $options['reference_date'] && $options['reference_date']->getTimezone()->getName() !== $options['model_timezone']) { - throw new InvalidConfigurationException(sprintf('The configured "model_timezone" (%s) must match the timezone of the "reference_date" (%s).', $options['model_timezone'], $options['reference_date']->getTimezone()->getName())); - } - - if ($options['with_minutes']) { - $format .= ':i'; - $parts[] = 'minute'; - } - - if ($options['with_seconds']) { - $format .= ':s'; - $parts[] = 'second'; - } - - if ('single_text' === $options['widget']) { - $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $e) use ($options) { - $data = $e->getData(); - if ($data && preg_match('/^(?P<hours>\d{2}):(?P<minutes>\d{2})(?::(?P<seconds>\d{2})(?:\.\d+)?)?$/', $data, $matches)) { - if ($options['with_seconds']) { - // handle seconds ignored by user's browser when with_seconds enabled - // https://codereview.chromium.org/450533009/ - $e->setData(sprintf('%s:%s:%s', $matches['hours'], $matches['minutes'], $matches['seconds'] ?? '00')); - } else { - $e->setData(sprintf('%s:%s', $matches['hours'], $matches['minutes'])); - } - } - }); - - $parseFormat = null; - - if (null !== $options['reference_date']) { - $parseFormat = 'Y-m-d '.$format; - - $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use ($options) { - $data = $event->getData(); - - if (preg_match('/^\d{2}:\d{2}(:\d{2})?$/', $data)) { - $event->setData($options['reference_date']->format('Y-m-d ').$data); - } - }); - } - - $builder->addViewTransformer(new DateTimeToStringTransformer($options['model_timezone'], $options['view_timezone'], $format, $parseFormat)); - } else { - $hourOptions = $minuteOptions = $secondOptions = [ - 'error_bubbling' => true, - 'empty_data' => '', - ]; - // when the form is compound the entries of the array are ignored in favor of children data - // so we need to handle the cascade setting here - $emptyData = $builder->getEmptyData() ?: []; - - if ($emptyData instanceof \Closure) { - $lazyEmptyData = static function ($option) use ($emptyData) { - return static function (FormInterface $form) use ($emptyData, $option) { - $emptyData = $emptyData($form->getParent()); - - return $emptyData[$option] ?? ''; - }; - }; - - $hourOptions['empty_data'] = $lazyEmptyData('hour'); - } elseif (isset($emptyData['hour'])) { - $hourOptions['empty_data'] = $emptyData['hour']; - } - - if (isset($options['invalid_message'])) { - $hourOptions['invalid_message'] = $options['invalid_message']; - $minuteOptions['invalid_message'] = $options['invalid_message']; - $secondOptions['invalid_message'] = $options['invalid_message']; - } - - if (isset($options['invalid_message_parameters'])) { - $hourOptions['invalid_message_parameters'] = $options['invalid_message_parameters']; - $minuteOptions['invalid_message_parameters'] = $options['invalid_message_parameters']; - $secondOptions['invalid_message_parameters'] = $options['invalid_message_parameters']; - } - - if ('choice' === $options['widget']) { - $hours = $minutes = []; - - foreach ($options['hours'] as $hour) { - $hours[str_pad($hour, 2, '0', \STR_PAD_LEFT)] = $hour; - } - - // Only pass a subset of the options to children - $hourOptions['choices'] = $hours; - $hourOptions['placeholder'] = $options['placeholder']['hour']; - $hourOptions['choice_translation_domain'] = $options['choice_translation_domain']['hour']; - - if ($options['with_minutes']) { - foreach ($options['minutes'] as $minute) { - $minutes[str_pad($minute, 2, '0', \STR_PAD_LEFT)] = $minute; - } - - $minuteOptions['choices'] = $minutes; - $minuteOptions['placeholder'] = $options['placeholder']['minute']; - $minuteOptions['choice_translation_domain'] = $options['choice_translation_domain']['minute']; - } - - if ($options['with_seconds']) { - $seconds = []; - - foreach ($options['seconds'] as $second) { - $seconds[str_pad($second, 2, '0', \STR_PAD_LEFT)] = $second; - } - - $secondOptions['choices'] = $seconds; - $secondOptions['placeholder'] = $options['placeholder']['second']; - $secondOptions['choice_translation_domain'] = $options['choice_translation_domain']['second']; - } - - // Append generic carry-along options - foreach (['required', 'translation_domain'] as $passOpt) { - $hourOptions[$passOpt] = $options[$passOpt]; - - if ($options['with_minutes']) { - $minuteOptions[$passOpt] = $options[$passOpt]; - } - - if ($options['with_seconds']) { - $secondOptions[$passOpt] = $options[$passOpt]; - } - } - } - - $builder->add('hour', self::WIDGETS[$options['widget']], $hourOptions); - - if ($options['with_minutes']) { - if ($emptyData instanceof \Closure) { - $minuteOptions['empty_data'] = $lazyEmptyData('minute'); - } elseif (isset($emptyData['minute'])) { - $minuteOptions['empty_data'] = $emptyData['minute']; - } - $builder->add('minute', self::WIDGETS[$options['widget']], $minuteOptions); - } - - if ($options['with_seconds']) { - if ($emptyData instanceof \Closure) { - $secondOptions['empty_data'] = $lazyEmptyData('second'); - } elseif (isset($emptyData['second'])) { - $secondOptions['empty_data'] = $emptyData['second']; - } - $builder->add('second', self::WIDGETS[$options['widget']], $secondOptions); - } - - $builder->addViewTransformer(new DateTimeToArrayTransformer($options['model_timezone'], $options['view_timezone'], $parts, 'text' === $options['widget'], $options['reference_date'])); - } - - if ('datetime_immutable' === $options['input']) { - $builder->addModelTransformer(new DateTimeImmutableToDateTimeTransformer()); - } elseif ('string' === $options['input']) { - $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone'], $options['input_format']) - )); - } elseif ('timestamp' === $options['input']) { - $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToTimestampTransformer($options['model_timezone'], $options['model_timezone']) - )); - } elseif ('array' === $options['input']) { - $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], $parts, 'text' === $options['widget'], $options['reference_date']) - )); - } - } - - /** - * {@inheritdoc} - */ - public function buildView(FormView $view, FormInterface $form, array $options) - { - $view->vars = array_replace($view->vars, [ - 'widget' => $options['widget'], - 'with_minutes' => $options['with_minutes'], - 'with_seconds' => $options['with_seconds'], - ]); - - // Change the input to an HTML5 time input if - // * the widget is set to "single_text" - // * the html5 is set to true - if ($options['html5'] && 'single_text' === $options['widget']) { - $view->vars['type'] = 'time'; - - // we need to force the browser to display the seconds by - // adding the HTML attribute step if not already defined. - // Otherwise the browser will not display and so not send the seconds - // therefore the value will always be considered as invalid. - if ($options['with_seconds'] && !isset($view->vars['attr']['step'])) { - $view->vars['attr']['step'] = 1; - } - } - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $compound = function (Options $options) { - return 'single_text' !== $options['widget']; - }; - - $placeholderDefault = function (Options $options) { - return $options['required'] ? null : ''; - }; - - $placeholderNormalizer = function (Options $options, $placeholder) use ($placeholderDefault) { - if (\is_array($placeholder)) { - $default = $placeholderDefault($options); - - return array_merge( - ['hour' => $default, 'minute' => $default, 'second' => $default], - $placeholder - ); - } - - return [ - 'hour' => $placeholder, - 'minute' => $placeholder, - 'second' => $placeholder, - ]; - }; - - $choiceTranslationDomainNormalizer = function (Options $options, $choiceTranslationDomain) { - if (\is_array($choiceTranslationDomain)) { - $default = false; - - return array_replace( - ['hour' => $default, 'minute' => $default, 'second' => $default], - $choiceTranslationDomain - ); - } - - return [ - 'hour' => $choiceTranslationDomain, - 'minute' => $choiceTranslationDomain, - 'second' => $choiceTranslationDomain, - ]; - }; - - $modelTimezone = static function (Options $options, $value): ?string { - if (null !== $value) { - return $value; - } - - if (null !== $options['reference_date']) { - return $options['reference_date']->getTimezone()->getName(); - } - - return null; - }; - - $viewTimezone = static function (Options $options, $value): ?string { - if (null !== $value) { - return $value; - } - - if (null !== $options['model_timezone'] && null === $options['reference_date']) { - return $options['model_timezone']; - } - - return null; - }; - - $resolver->setDefaults([ - 'hours' => range(0, 23), - 'minutes' => range(0, 59), - 'seconds' => range(0, 59), - 'widget' => 'choice', - 'input' => 'datetime', - 'input_format' => 'H:i:s', - 'with_minutes' => true, - 'with_seconds' => false, - 'model_timezone' => $modelTimezone, - 'view_timezone' => $viewTimezone, - 'reference_date' => null, - 'placeholder' => $placeholderDefault, - 'html5' => true, - // Don't modify \DateTime classes by reference, we treat - // them like immutable value objects - 'by_reference' => false, - 'error_bubbling' => false, - // If initialized with a \DateTime object, FormType initializes - // this option to "\DateTime". Since the internal, normalized - // representation is not \DateTime, but an array, we need to unset - // this option. - 'data_class' => null, - 'empty_data' => function (Options $options) { - return $options['compound'] ? [] : ''; - }, - 'compound' => $compound, - 'choice_translation_domain' => false, - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'Please enter a valid time.'; - }, - ]); - - $resolver->setNormalizer('view_timezone', function (Options $options, $viewTimezone): ?string { - if (null !== $options['model_timezone'] && $viewTimezone !== $options['model_timezone'] && null === $options['reference_date']) { - throw new LogicException('Using different values for the "model_timezone" and "view_timezone" options without configuring a reference date is not supported.'); - } - - return $viewTimezone; - }); - - $resolver->setNormalizer('placeholder', $placeholderNormalizer); - $resolver->setNormalizer('choice_translation_domain', $choiceTranslationDomainNormalizer); - - $resolver->setAllowedValues('input', [ - 'datetime', - 'datetime_immutable', - 'string', - 'timestamp', - 'array', - ]); - $resolver->setAllowedValues('widget', [ - 'single_text', - 'text', - 'choice', - ]); - - $resolver->setAllowedTypes('hours', 'array'); - $resolver->setAllowedTypes('minutes', 'array'); - $resolver->setAllowedTypes('seconds', 'array'); - $resolver->setAllowedTypes('input_format', 'string'); - $resolver->setAllowedTypes('model_timezone', ['null', 'string']); - $resolver->setAllowedTypes('view_timezone', ['null', 'string']); - $resolver->setAllowedTypes('reference_date', ['null', \DateTimeInterface::class]); - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'time'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/TimezoneType.php b/lib/symfony/form/Extension/Core/Type/TimezoneType.php deleted file mode 100644 index 31b5df5c3..000000000 --- a/lib/symfony/form/Extension/Core/Type/TimezoneType.php +++ /dev/null @@ -1,143 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\ChoiceList\ChoiceList; -use Symfony\Component\Form\ChoiceList\Loader\IntlCallbackChoiceLoader; -use Symfony\Component\Form\Exception\LogicException; -use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeZoneToStringTransformer; -use Symfony\Component\Form\Extension\Core\DataTransformer\IntlTimeZoneToStringTransformer; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Intl\Intl; -use Symfony\Component\Intl\Timezones; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class TimezoneType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - if ('datetimezone' === $options['input']) { - $builder->addModelTransformer(new DateTimeZoneToStringTransformer($options['multiple'])); - } elseif ('intltimezone' === $options['input']) { - $builder->addModelTransformer(new IntlTimeZoneToStringTransformer($options['multiple'])); - } - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - 'intl' => false, - 'choice_loader' => function (Options $options) { - $input = $options['input']; - - if ($options['intl']) { - if (!class_exists(Intl::class)) { - throw new LogicException(sprintf('The "symfony/intl" component is required to use "%s" with option "intl=true". Try running "composer require symfony/intl".', static::class)); - } - - $choiceTranslationLocale = $options['choice_translation_locale']; - - return ChoiceList::loader($this, new IntlCallbackChoiceLoader(function () use ($input, $choiceTranslationLocale) { - return self::getIntlTimezones($input, $choiceTranslationLocale); - }), [$input, $choiceTranslationLocale]); - } - - return ChoiceList::lazy($this, function () use ($input) { - return self::getPhpTimezones($input); - }, $input); - }, - 'choice_translation_domain' => false, - 'choice_translation_locale' => null, - 'input' => 'string', - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'Please select a valid timezone.'; - }, - 'regions' => \DateTimeZone::ALL, - ]); - - $resolver->setAllowedTypes('intl', ['bool']); - - $resolver->setAllowedTypes('choice_translation_locale', ['null', 'string']); - $resolver->setNormalizer('choice_translation_locale', function (Options $options, $value) { - if (null !== $value && !$options['intl']) { - throw new LogicException('The "choice_translation_locale" option can only be used if the "intl" option is set to true.'); - } - - return $value; - }); - - $resolver->setAllowedValues('input', ['string', 'datetimezone', 'intltimezone']); - $resolver->setNormalizer('input', function (Options $options, $value) { - if ('intltimezone' === $value && !class_exists(\IntlTimeZone::class)) { - throw new LogicException('Cannot use "intltimezone" input because the PHP intl extension is not available.'); - } - - return $value; - }); - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - return ChoiceType::class; - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'timezone'; - } - - private static function getPhpTimezones(string $input): array - { - $timezones = []; - - foreach (\DateTimeZone::listIdentifiers(\DateTimeZone::ALL) as $timezone) { - if ('intltimezone' === $input && 'Etc/Unknown' === \IntlTimeZone::createTimeZone($timezone)->getID()) { - continue; - } - - $timezones[str_replace(['/', '_'], [' / ', ' '], $timezone)] = $timezone; - } - - return $timezones; - } - - private static function getIntlTimezones(string $input, string $locale = null): array - { - $timezones = array_flip(Timezones::getNames($locale)); - - if ('intltimezone' === $input) { - foreach ($timezones as $name => $timezone) { - if ('Etc/Unknown' === \IntlTimeZone::createTimeZone($timezone)->getID()) { - unset($timezones[$name]); - } - } - } - - return $timezones; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/TransformationFailureExtension.php b/lib/symfony/form/Extension/Core/Type/TransformationFailureExtension.php deleted file mode 100644 index f766633c9..000000000 --- a/lib/symfony/form/Extension/Core/Type/TransformationFailureExtension.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractTypeExtension; -use Symfony\Component\Form\Extension\Core\EventListener\TransformationFailureListener; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Contracts\Translation\TranslatorInterface; - -/** - * @author Christian Flothmann <christian.flothmann@sensiolabs.de> - */ -class TransformationFailureExtension extends AbstractTypeExtension -{ - private $translator; - - public function __construct(TranslatorInterface $translator = null) - { - $this->translator = $translator; - } - - public function buildForm(FormBuilderInterface $builder, array $options) - { - if (!isset($options['constraints'])) { - $builder->addEventSubscriber(new TransformationFailureListener($this->translator)); - } - } - - /** - * {@inheritdoc} - */ - public static function getExtendedTypes(): iterable - { - return [FormType::class]; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/UlidType.php b/lib/symfony/form/Extension/Core/Type/UlidType.php deleted file mode 100644 index 640d38ffa..000000000 --- a/lib/symfony/form/Extension/Core/Type/UlidType.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Extension\Core\DataTransformer\UlidToStringTransformer; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -/** - * @author Pavel Dyakonov <wapinet@mail.ru> - */ -class UlidType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - $builder - ->addViewTransformer(new UlidToStringTransformer()) - ; - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - 'compound' => false, - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'Please enter a valid ULID.'; - }, - ]); - } -} diff --git a/lib/symfony/form/Extension/Core/Type/UrlType.php b/lib/symfony/form/Extension/Core/Type/UrlType.php deleted file mode 100644 index f294a10ac..000000000 --- a/lib/symfony/form/Extension/Core/Type/UrlType.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Extension\Core\EventListener\FixUrlProtocolListener; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class UrlType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - if (null !== $options['default_protocol']) { - $builder->addEventSubscriber(new FixUrlProtocolListener($options['default_protocol'])); - } - } - - /** - * {@inheritdoc} - */ - public function buildView(FormView $view, FormInterface $form, array $options) - { - if ($options['default_protocol']) { - $view->vars['attr']['inputmode'] = 'url'; - $view->vars['type'] = 'text'; - } - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - 'default_protocol' => 'http', - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'Please enter a valid URL.'; - }, - ]); - - $resolver->setAllowedTypes('default_protocol', ['null', 'string']); - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - return TextType::class; - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'url'; - } -} diff --git a/lib/symfony/form/Extension/Core/Type/UuidType.php b/lib/symfony/form/Extension/Core/Type/UuidType.php deleted file mode 100644 index 0c27802b3..000000000 --- a/lib/symfony/form/Extension/Core/Type/UuidType.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Extension\Core\DataTransformer\UuidToStringTransformer; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -/** - * @author Pavel Dyakonov <wapinet@mail.ru> - */ -class UuidType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - $builder - ->addViewTransformer(new UuidToStringTransformer()) - ; - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - 'compound' => false, - 'invalid_message' => function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) - ? $previousValue - : 'Please enter a valid UUID.'; - }, - ]); - } -} diff --git a/lib/symfony/form/Extension/Core/Type/WeekType.php b/lib/symfony/form/Extension/Core/Type/WeekType.php deleted file mode 100644 index b7f8887d9..000000000 --- a/lib/symfony/form/Extension/Core/Type/WeekType.php +++ /dev/null @@ -1,195 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Exception\LogicException; -use Symfony\Component\Form\Extension\Core\DataTransformer\WeekToArrayTransformer; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; -use Symfony\Component\Form\ReversedTransformer; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class WeekType extends AbstractType -{ - private const WIDGETS = [ - 'text' => IntegerType::class, - 'choice' => ChoiceType::class, - ]; - - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - if ('string' === $options['input']) { - $builder->addModelTransformer(new WeekToArrayTransformer()); - } - - if ('single_text' === $options['widget']) { - $builder->addViewTransformer(new ReversedTransformer(new WeekToArrayTransformer())); - } else { - $yearOptions = $weekOptions = [ - 'error_bubbling' => true, - 'empty_data' => '', - ]; - // when the form is compound the entries of the array are ignored in favor of children data - // so we need to handle the cascade setting here - $emptyData = $builder->getEmptyData() ?: []; - - $yearOptions['empty_data'] = $emptyData['year'] ?? ''; - $weekOptions['empty_data'] = $emptyData['week'] ?? ''; - - if (isset($options['invalid_message'])) { - $yearOptions['invalid_message'] = $options['invalid_message']; - $weekOptions['invalid_message'] = $options['invalid_message']; - } - - if (isset($options['invalid_message_parameters'])) { - $yearOptions['invalid_message_parameters'] = $options['invalid_message_parameters']; - $weekOptions['invalid_message_parameters'] = $options['invalid_message_parameters']; - } - - if ('choice' === $options['widget']) { - // Only pass a subset of the options to children - $yearOptions['choices'] = array_combine($options['years'], $options['years']); - $yearOptions['placeholder'] = $options['placeholder']['year']; - $yearOptions['choice_translation_domain'] = $options['choice_translation_domain']['year']; - - $weekOptions['choices'] = array_combine($options['weeks'], $options['weeks']); - $weekOptions['placeholder'] = $options['placeholder']['week']; - $weekOptions['choice_translation_domain'] = $options['choice_translation_domain']['week']; - - // Append generic carry-along options - foreach (['required', 'translation_domain'] as $passOpt) { - $yearOptions[$passOpt] = $options[$passOpt]; - $weekOptions[$passOpt] = $options[$passOpt]; - } - } - - $builder->add('year', self::WIDGETS[$options['widget']], $yearOptions); - $builder->add('week', self::WIDGETS[$options['widget']], $weekOptions); - } - } - - /** - * {@inheritdoc} - */ - public function buildView(FormView $view, FormInterface $form, array $options) - { - $view->vars['widget'] = $options['widget']; - - if ($options['html5']) { - $view->vars['type'] = 'week'; - } - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $compound = function (Options $options) { - return 'single_text' !== $options['widget']; - }; - - $placeholderDefault = function (Options $options) { - return $options['required'] ? null : ''; - }; - - $placeholderNormalizer = function (Options $options, $placeholder) use ($placeholderDefault) { - if (\is_array($placeholder)) { - $default = $placeholderDefault($options); - - return array_merge( - ['year' => $default, 'week' => $default], - $placeholder - ); - } - - return [ - 'year' => $placeholder, - 'week' => $placeholder, - ]; - }; - - $choiceTranslationDomainNormalizer = function (Options $options, $choiceTranslationDomain) { - if (\is_array($choiceTranslationDomain)) { - $default = false; - - return array_replace( - ['year' => $default, 'week' => $default], - $choiceTranslationDomain - ); - } - - return [ - 'year' => $choiceTranslationDomain, - 'week' => $choiceTranslationDomain, - ]; - }; - - $resolver->setDefaults([ - 'years' => range(date('Y') - 10, date('Y') + 10), - 'weeks' => array_combine(range(1, 53), range(1, 53)), - 'widget' => 'single_text', - 'input' => 'array', - 'placeholder' => $placeholderDefault, - 'html5' => static function (Options $options) { - return 'single_text' === $options['widget']; - }, - 'error_bubbling' => false, - 'empty_data' => function (Options $options) { - return $options['compound'] ? [] : ''; - }, - 'compound' => $compound, - 'choice_translation_domain' => false, - 'invalid_message' => static function (Options $options, $previousValue) { - return ($options['legacy_error_messages'] ?? true) ? $previousValue : 'Please enter a valid week.'; - }, - ]); - - $resolver->setNormalizer('placeholder', $placeholderNormalizer); - $resolver->setNormalizer('choice_translation_domain', $choiceTranslationDomainNormalizer); - $resolver->setNormalizer('html5', function (Options $options, $html5) { - if ($html5 && 'single_text' !== $options['widget']) { - throw new LogicException(sprintf('The "widget" option of "%s" must be set to "single_text" when the "html5" option is enabled.', self::class)); - } - - return $html5; - }); - - $resolver->setAllowedValues('input', [ - 'string', - 'array', - ]); - - $resolver->setAllowedValues('widget', [ - 'single_text', - 'text', - 'choice', - ]); - - $resolver->setAllowedTypes('years', 'int[]'); - $resolver->setAllowedTypes('weeks', 'int[]'); - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'week'; - } -} diff --git a/lib/symfony/form/Extension/Csrf/CsrfExtension.php b/lib/symfony/form/Extension/Csrf/CsrfExtension.php deleted file mode 100644 index 609a371ea..000000000 --- a/lib/symfony/form/Extension/Csrf/CsrfExtension.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Csrf; - -use Symfony\Component\Form\AbstractExtension; -use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; -use Symfony\Contracts\Translation\TranslatorInterface; - -/** - * This extension protects forms by using a CSRF token. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class CsrfExtension extends AbstractExtension -{ - private $tokenManager; - private $translator; - private $translationDomain; - - public function __construct(CsrfTokenManagerInterface $tokenManager, TranslatorInterface $translator = null, string $translationDomain = null) - { - $this->tokenManager = $tokenManager; - $this->translator = $translator; - $this->translationDomain = $translationDomain; - } - - /** - * {@inheritdoc} - */ - protected function loadTypeExtensions() - { - return [ - new Type\FormTypeCsrfExtension($this->tokenManager, true, '_token', $this->translator, $this->translationDomain), - ]; - } -} diff --git a/lib/symfony/form/Extension/Csrf/EventListener/CsrfValidationListener.php b/lib/symfony/form/Extension/Csrf/EventListener/CsrfValidationListener.php deleted file mode 100644 index 37548ef55..000000000 --- a/lib/symfony/form/Extension/Csrf/EventListener/CsrfValidationListener.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Csrf\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Form\FormError; -use Symfony\Component\Form\FormEvent; -use Symfony\Component\Form\FormEvents; -use Symfony\Component\Form\Util\ServerParams; -use Symfony\Component\Security\Csrf\CsrfToken; -use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; -use Symfony\Contracts\Translation\TranslatorInterface; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class CsrfValidationListener implements EventSubscriberInterface -{ - private $fieldName; - private $tokenManager; - private $tokenId; - private $errorMessage; - private $translator; - private $translationDomain; - private $serverParams; - - public static function getSubscribedEvents() - { - return [ - FormEvents::PRE_SUBMIT => 'preSubmit', - ]; - } - - public function __construct(string $fieldName, CsrfTokenManagerInterface $tokenManager, string $tokenId, string $errorMessage, TranslatorInterface $translator = null, string $translationDomain = null, ServerParams $serverParams = null) - { - $this->fieldName = $fieldName; - $this->tokenManager = $tokenManager; - $this->tokenId = $tokenId; - $this->errorMessage = $errorMessage; - $this->translator = $translator; - $this->translationDomain = $translationDomain; - $this->serverParams = $serverParams ?? new ServerParams(); - } - - public function preSubmit(FormEvent $event) - { - $form = $event->getForm(); - $postRequestSizeExceeded = 'POST' === $form->getConfig()->getMethod() && $this->serverParams->hasPostMaxSizeBeenExceeded(); - - if ($form->isRoot() && $form->getConfig()->getOption('compound') && !$postRequestSizeExceeded) { - $data = $event->getData(); - - $csrfValue = \is_string($data[$this->fieldName] ?? null) ? $data[$this->fieldName] : null; - $csrfToken = new CsrfToken($this->tokenId, $csrfValue); - - if (null === $csrfValue || !$this->tokenManager->isTokenValid($csrfToken)) { - $errorMessage = $this->errorMessage; - - if (null !== $this->translator) { - $errorMessage = $this->translator->trans($errorMessage, [], $this->translationDomain); - } - - $form->addError(new FormError($errorMessage, $errorMessage, [], null, $csrfToken)); - } - - if (\is_array($data)) { - unset($data[$this->fieldName]); - $event->setData($data); - } - } - } -} diff --git a/lib/symfony/form/Extension/Csrf/Type/FormTypeCsrfExtension.php b/lib/symfony/form/Extension/Csrf/Type/FormTypeCsrfExtension.php deleted file mode 100644 index cd17b8e94..000000000 --- a/lib/symfony/form/Extension/Csrf/Type/FormTypeCsrfExtension.php +++ /dev/null @@ -1,110 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Csrf\Type; - -use Symfony\Component\Form\AbstractTypeExtension; -use Symfony\Component\Form\Extension\Core\Type\FormType; -use Symfony\Component\Form\Extension\Core\Type\HiddenType; -use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; -use Symfony\Component\Form\Util\ServerParams; -use Symfony\Component\OptionsResolver\OptionsResolver; -use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; -use Symfony\Contracts\Translation\TranslatorInterface; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class FormTypeCsrfExtension extends AbstractTypeExtension -{ - private $defaultTokenManager; - private $defaultEnabled; - private $defaultFieldName; - private $translator; - private $translationDomain; - private $serverParams; - - public function __construct(CsrfTokenManagerInterface $defaultTokenManager, bool $defaultEnabled = true, string $defaultFieldName = '_token', TranslatorInterface $translator = null, string $translationDomain = null, ServerParams $serverParams = null) - { - $this->defaultTokenManager = $defaultTokenManager; - $this->defaultEnabled = $defaultEnabled; - $this->defaultFieldName = $defaultFieldName; - $this->translator = $translator; - $this->translationDomain = $translationDomain; - $this->serverParams = $serverParams; - } - - /** - * Adds a CSRF field to the form when the CSRF protection is enabled. - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - if (!$options['csrf_protection']) { - return; - } - - $builder - ->addEventSubscriber(new CsrfValidationListener( - $options['csrf_field_name'], - $options['csrf_token_manager'], - $options['csrf_token_id'] ?: ($builder->getName() ?: \get_class($builder->getType()->getInnerType())), - $options['csrf_message'], - $this->translator, - $this->translationDomain, - $this->serverParams - )) - ; - } - - /** - * Adds a CSRF field to the root form view. - */ - public function finishView(FormView $view, FormInterface $form, array $options) - { - if ($options['csrf_protection'] && !$view->parent && $options['compound']) { - $factory = $form->getConfig()->getFormFactory(); - $tokenId = $options['csrf_token_id'] ?: ($form->getName() ?: \get_class($form->getConfig()->getType()->getInnerType())); - $data = (string) $options['csrf_token_manager']->getToken($tokenId); - - $csrfForm = $factory->createNamed($options['csrf_field_name'], HiddenType::class, $data, [ - 'block_prefix' => 'csrf_token', - 'mapped' => false, - ]); - - $view->children[$options['csrf_field_name']] = $csrfForm->createView($view); - } - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults([ - 'csrf_protection' => $this->defaultEnabled, - 'csrf_field_name' => $this->defaultFieldName, - 'csrf_message' => 'The CSRF token is invalid. Please try to resubmit the form.', - 'csrf_token_manager' => $this->defaultTokenManager, - 'csrf_token_id' => null, - ]); - } - - /** - * {@inheritdoc} - */ - public static function getExtendedTypes(): iterable - { - return [FormType::class]; - } -} diff --git a/lib/symfony/form/Extension/DataCollector/DataCollectorExtension.php b/lib/symfony/form/Extension/DataCollector/DataCollectorExtension.php deleted file mode 100644 index 4b23513b7..000000000 --- a/lib/symfony/form/Extension/DataCollector/DataCollectorExtension.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\DataCollector; - -use Symfony\Component\Form\AbstractExtension; - -/** - * Extension for collecting data of the forms on a page. - * - * @author Robert Schönthal <robert.schoenthal@gmail.com> - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class DataCollectorExtension extends AbstractExtension -{ - private $dataCollector; - - public function __construct(FormDataCollectorInterface $dataCollector) - { - $this->dataCollector = $dataCollector; - } - - /** - * {@inheritdoc} - */ - protected function loadTypeExtensions() - { - return [ - new Type\DataCollectorTypeExtension($this->dataCollector), - ]; - } -} diff --git a/lib/symfony/form/Extension/DataCollector/EventListener/DataCollectorListener.php b/lib/symfony/form/Extension/DataCollector/EventListener/DataCollectorListener.php deleted file mode 100644 index 77595ab38..000000000 --- a/lib/symfony/form/Extension/DataCollector/EventListener/DataCollectorListener.php +++ /dev/null @@ -1,75 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\DataCollector\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface; -use Symfony\Component\Form\FormEvent; -use Symfony\Component\Form\FormEvents; - -/** - * Listener that invokes a data collector for the {@link FormEvents::POST_SET_DATA} - * and {@link FormEvents::POST_SUBMIT} events. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class DataCollectorListener implements EventSubscriberInterface -{ - private $dataCollector; - - public function __construct(FormDataCollectorInterface $dataCollector) - { - $this->dataCollector = $dataCollector; - } - - /** - * {@inheritdoc} - */ - public static function getSubscribedEvents() - { - return [ - // High priority in order to be called as soon as possible - FormEvents::POST_SET_DATA => ['postSetData', 255], - // Low priority in order to be called as late as possible - FormEvents::POST_SUBMIT => ['postSubmit', -255], - ]; - } - - /** - * Listener for the {@link FormEvents::POST_SET_DATA} event. - */ - public function postSetData(FormEvent $event) - { - if ($event->getForm()->isRoot()) { - // Collect basic information about each form - $this->dataCollector->collectConfiguration($event->getForm()); - - // Collect the default data - $this->dataCollector->collectDefaultData($event->getForm()); - } - } - - /** - * Listener for the {@link FormEvents::POST_SUBMIT} event. - */ - public function postSubmit(FormEvent $event) - { - if ($event->getForm()->isRoot()) { - // Collect the submitted data of each form - $this->dataCollector->collectSubmittedData($event->getForm()); - - // Assemble a form tree - // This is done again after the view is built, but we need it here as the view is not always created. - $this->dataCollector->buildPreliminaryFormTree($event->getForm()); - } - } -} diff --git a/lib/symfony/form/Extension/DataCollector/FormDataCollector.php b/lib/symfony/form/Extension/DataCollector/FormDataCollector.php deleted file mode 100644 index 2fe2fbed1..000000000 --- a/lib/symfony/form/Extension/DataCollector/FormDataCollector.php +++ /dev/null @@ -1,343 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\DataCollector; - -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\DataCollector\DataCollector; -use Symfony\Component\Validator\ConstraintViolationInterface; -use Symfony\Component\VarDumper\Caster\Caster; -use Symfony\Component\VarDumper\Caster\ClassStub; -use Symfony\Component\VarDumper\Caster\StubCaster; -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Data collector for {@link FormInterface} instances. - * - * @author Robert Schönthal <robert.schoenthal@gmail.com> - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @final - */ -class FormDataCollector extends DataCollector implements FormDataCollectorInterface -{ - private $dataExtractor; - - /** - * Stores the collected data per {@link FormInterface} instance. - * - * Uses the hashes of the forms as keys. This is preferable over using - * {@link \SplObjectStorage}, because in this way no references are kept - * to the {@link FormInterface} instances. - * - * @var array - */ - private $dataByForm; - - /** - * Stores the collected data per {@link FormView} instance. - * - * Uses the hashes of the views as keys. This is preferable over using - * {@link \SplObjectStorage}, because in this way no references are kept - * to the {@link FormView} instances. - * - * @var array - */ - private $dataByView; - - /** - * Connects {@link FormView} with {@link FormInterface} instances. - * - * Uses the hashes of the views as keys and the hashes of the forms as - * values. This is preferable over storing the objects directly, because - * this way they can safely be discarded by the GC. - * - * @var array - */ - private $formsByView; - - public function __construct(FormDataExtractorInterface $dataExtractor) - { - if (!class_exists(ClassStub::class)) { - throw new \LogicException(sprintf('The VarDumper component is needed for using the "%s" class. Install symfony/var-dumper version 3.4 or above.', __CLASS__)); - } - - $this->dataExtractor = $dataExtractor; - - $this->reset(); - } - - /** - * Does nothing. The data is collected during the form event listeners. - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - } - - public function reset() - { - $this->data = [ - 'forms' => [], - 'forms_by_hash' => [], - 'nb_errors' => 0, - ]; - } - - /** - * {@inheritdoc} - */ - public function associateFormWithView(FormInterface $form, FormView $view) - { - $this->formsByView[spl_object_hash($view)] = spl_object_hash($form); - } - - /** - * {@inheritdoc} - */ - public function collectConfiguration(FormInterface $form) - { - $hash = spl_object_hash($form); - - if (!isset($this->dataByForm[$hash])) { - $this->dataByForm[$hash] = []; - } - - $this->dataByForm[$hash] = array_replace( - $this->dataByForm[$hash], - $this->dataExtractor->extractConfiguration($form) - ); - - foreach ($form as $child) { - $this->collectConfiguration($child); - } - } - - /** - * {@inheritdoc} - */ - public function collectDefaultData(FormInterface $form) - { - $hash = spl_object_hash($form); - - if (!isset($this->dataByForm[$hash])) { - // field was created by form event - $this->collectConfiguration($form); - } - - $this->dataByForm[$hash] = array_replace( - $this->dataByForm[$hash], - $this->dataExtractor->extractDefaultData($form) - ); - - foreach ($form as $child) { - $this->collectDefaultData($child); - } - } - - /** - * {@inheritdoc} - */ - public function collectSubmittedData(FormInterface $form) - { - $hash = spl_object_hash($form); - - if (!isset($this->dataByForm[$hash])) { - // field was created by form event - $this->collectConfiguration($form); - $this->collectDefaultData($form); - } - - $this->dataByForm[$hash] = array_replace( - $this->dataByForm[$hash], - $this->dataExtractor->extractSubmittedData($form) - ); - - // Count errors - if (isset($this->dataByForm[$hash]['errors'])) { - $this->data['nb_errors'] += \count($this->dataByForm[$hash]['errors']); - } - - foreach ($form as $child) { - $this->collectSubmittedData($child); - - // Expand current form if there are children with errors - if (empty($this->dataByForm[$hash]['has_children_error'])) { - $childData = $this->dataByForm[spl_object_hash($child)]; - $this->dataByForm[$hash]['has_children_error'] = !empty($childData['has_children_error']) || !empty($childData['errors']); - } - } - } - - /** - * {@inheritdoc} - */ - public function collectViewVariables(FormView $view) - { - $hash = spl_object_hash($view); - - if (!isset($this->dataByView[$hash])) { - $this->dataByView[$hash] = []; - } - - $this->dataByView[$hash] = array_replace( - $this->dataByView[$hash], - $this->dataExtractor->extractViewVariables($view) - ); - - foreach ($view->children as $child) { - $this->collectViewVariables($child); - } - } - - /** - * {@inheritdoc} - */ - public function buildPreliminaryFormTree(FormInterface $form) - { - $this->data['forms'][$form->getName()] = &$this->recursiveBuildPreliminaryFormTree($form, $this->data['forms_by_hash']); - } - - /** - * {@inheritdoc} - */ - public function buildFinalFormTree(FormInterface $form, FormView $view) - { - $this->data['forms'][$form->getName()] = &$this->recursiveBuildFinalFormTree($form, $view, $this->data['forms_by_hash']); - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'form'; - } - - /** - * {@inheritdoc} - */ - public function getData() - { - return $this->data; - } - - /** - * @internal - */ - public function __sleep(): array - { - foreach ($this->data['forms_by_hash'] as &$form) { - if (isset($form['type_class']) && !$form['type_class'] instanceof ClassStub) { - $form['type_class'] = new ClassStub($form['type_class']); - } - } - - $this->data = $this->cloneVar($this->data); - - return parent::__sleep(); - } - - /** - * {@inheritdoc} - */ - protected function getCasters(): array - { - return parent::getCasters() + [ - \Exception::class => function (\Exception $e, array $a, Stub $s) { - foreach (["\0Exception\0previous", "\0Exception\0trace"] as $k) { - if (isset($a[$k])) { - unset($a[$k]); - ++$s->cut; - } - } - - return $a; - }, - FormInterface::class => function (FormInterface $f, array $a) { - return [ - Caster::PREFIX_VIRTUAL.'name' => $f->getName(), - Caster::PREFIX_VIRTUAL.'type_class' => new ClassStub(\get_class($f->getConfig()->getType()->getInnerType())), - ]; - }, - FormView::class => [StubCaster::class, 'cutInternals'], - ConstraintViolationInterface::class => function (ConstraintViolationInterface $v, array $a) { - return [ - Caster::PREFIX_VIRTUAL.'root' => $v->getRoot(), - Caster::PREFIX_VIRTUAL.'path' => $v->getPropertyPath(), - Caster::PREFIX_VIRTUAL.'value' => $v->getInvalidValue(), - ]; - }, - ]; - } - - private function &recursiveBuildPreliminaryFormTree(FormInterface $form, array &$outputByHash) - { - $hash = spl_object_hash($form); - - $output = &$outputByHash[$hash]; - $output = $this->dataByForm[$hash] - ?? []; - - $output['children'] = []; - - foreach ($form as $name => $child) { - $output['children'][$name] = &$this->recursiveBuildPreliminaryFormTree($child, $outputByHash); - } - - return $output; - } - - private function &recursiveBuildFinalFormTree(FormInterface $form = null, FormView $view, array &$outputByHash) - { - $viewHash = spl_object_hash($view); - $formHash = null; - - if (null !== $form) { - $formHash = spl_object_hash($form); - } elseif (isset($this->formsByView[$viewHash])) { - // The FormInterface instance of the CSRF token is never contained in - // the FormInterface tree of the form, so we need to get the - // corresponding FormInterface instance for its view in a different way - $formHash = $this->formsByView[$viewHash]; - } - if (null !== $formHash) { - $output = &$outputByHash[$formHash]; - } - - $output = $this->dataByView[$viewHash] - ?? []; - - if (null !== $formHash) { - $output = array_replace( - $output, - $this->dataByForm[$formHash] - ?? [] - ); - } - - $output['children'] = []; - - foreach ($view->children as $name => $childView) { - // The CSRF token, for example, is never added to the form tree. - // It is only present in the view. - $childForm = null !== $form && $form->has($name) - ? $form->get($name) - : null; - - $output['children'][$name] = &$this->recursiveBuildFinalFormTree($childForm, $childView, $outputByHash); - } - - return $output; - } -} diff --git a/lib/symfony/form/Extension/DataCollector/FormDataCollectorInterface.php b/lib/symfony/form/Extension/DataCollector/FormDataCollectorInterface.php deleted file mode 100644 index 64b8f83c4..000000000 --- a/lib/symfony/form/Extension/DataCollector/FormDataCollectorInterface.php +++ /dev/null @@ -1,85 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\DataCollector; - -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; -use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; -use Symfony\Component\VarDumper\Cloner\Data; - -/** - * Collects and structures information about forms. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface FormDataCollectorInterface extends DataCollectorInterface -{ - /** - * Stores configuration data of the given form and its children. - */ - public function collectConfiguration(FormInterface $form); - - /** - * Stores the default data of the given form and its children. - */ - public function collectDefaultData(FormInterface $form); - - /** - * Stores the submitted data of the given form and its children. - */ - public function collectSubmittedData(FormInterface $form); - - /** - * Stores the view variables of the given form view and its children. - */ - public function collectViewVariables(FormView $view); - - /** - * Specifies that the given objects represent the same conceptual form. - */ - public function associateFormWithView(FormInterface $form, FormView $view); - - /** - * Assembles the data collected about the given form and its children as - * a tree-like data structure. - * - * The result can be queried using {@link getData()}. - */ - public function buildPreliminaryFormTree(FormInterface $form); - - /** - * Assembles the data collected about the given form and its children as - * a tree-like data structure. - * - * The result can be queried using {@link getData()}. - * - * Contrary to {@link buildPreliminaryFormTree()}, a {@link FormView} - * object has to be passed. The tree structure of this view object will be - * used for structuring the resulting data. That means, if a child is - * present in the view, but not in the form, it will be present in the final - * data array anyway. - * - * When {@link FormView} instances are present in the view tree, for which - * no corresponding {@link FormInterface} objects can be found in the form - * tree, only the view data will be included in the result. If a - * corresponding {@link FormInterface} exists otherwise, call - * {@link associateFormWithView()} before calling this method. - */ - public function buildFinalFormTree(FormInterface $form, FormView $view); - - /** - * Returns all collected data. - * - * @return array|Data - */ - public function getData(); -} diff --git a/lib/symfony/form/Extension/DataCollector/FormDataExtractor.php b/lib/symfony/form/Extension/DataCollector/FormDataExtractor.php deleted file mode 100644 index 9cecc720e..000000000 --- a/lib/symfony/form/Extension/DataCollector/FormDataExtractor.php +++ /dev/null @@ -1,168 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\DataCollector; - -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; -use Symfony\Component\Validator\ConstraintViolationInterface; - -/** - * Default implementation of {@link FormDataExtractorInterface}. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class FormDataExtractor implements FormDataExtractorInterface -{ - /** - * {@inheritdoc} - */ - public function extractConfiguration(FormInterface $form) - { - $data = [ - 'id' => $this->buildId($form), - 'name' => $form->getName(), - 'type_class' => \get_class($form->getConfig()->getType()->getInnerType()), - 'synchronized' => $form->isSynchronized(), - 'passed_options' => [], - 'resolved_options' => [], - ]; - - foreach ($form->getConfig()->getAttribute('data_collector/passed_options', []) as $option => $value) { - $data['passed_options'][$option] = $value; - } - - foreach ($form->getConfig()->getOptions() as $option => $value) { - $data['resolved_options'][$option] = $value; - } - - ksort($data['passed_options']); - ksort($data['resolved_options']); - - return $data; - } - - /** - * {@inheritdoc} - */ - public function extractDefaultData(FormInterface $form) - { - $data = [ - 'default_data' => [ - 'norm' => $form->getNormData(), - ], - 'submitted_data' => [], - ]; - - if ($form->getData() !== $form->getNormData()) { - $data['default_data']['model'] = $form->getData(); - } - - if ($form->getViewData() !== $form->getNormData()) { - $data['default_data']['view'] = $form->getViewData(); - } - - return $data; - } - - /** - * {@inheritdoc} - */ - public function extractSubmittedData(FormInterface $form) - { - $data = [ - 'submitted_data' => [ - 'norm' => $form->getNormData(), - ], - 'errors' => [], - ]; - - if ($form->getViewData() !== $form->getNormData()) { - $data['submitted_data']['view'] = $form->getViewData(); - } - - if ($form->getData() !== $form->getNormData()) { - $data['submitted_data']['model'] = $form->getData(); - } - - foreach ($form->getErrors() as $error) { - $errorData = [ - 'message' => $error->getMessage(), - 'origin' => \is_object($error->getOrigin()) - ? spl_object_hash($error->getOrigin()) - : null, - 'trace' => [], - ]; - - $cause = $error->getCause(); - - while (null !== $cause) { - if ($cause instanceof ConstraintViolationInterface) { - $errorData['trace'][] = $cause; - $cause = method_exists($cause, 'getCause') ? $cause->getCause() : null; - - continue; - } - - if ($cause instanceof \Exception) { - $errorData['trace'][] = $cause; - $cause = $cause->getPrevious(); - - continue; - } - - $errorData['trace'][] = $cause; - - break; - } - - $data['errors'][] = $errorData; - } - - $data['synchronized'] = $form->isSynchronized(); - - return $data; - } - - /** - * {@inheritdoc} - */ - public function extractViewVariables(FormView $view) - { - $data = [ - 'id' => $view->vars['id'] ?? null, - 'name' => $view->vars['name'] ?? null, - 'view_vars' => [], - ]; - - foreach ($view->vars as $varName => $value) { - $data['view_vars'][$varName] = $value; - } - - ksort($data['view_vars']); - - return $data; - } - - /** - * Recursively builds an HTML ID for a form. - */ - private function buildId(FormInterface $form): string - { - $id = $form->getName(); - - if (null !== $form->getParent()) { - $id = $this->buildId($form->getParent()).'_'.$id; - } - - return $id; - } -} diff --git a/lib/symfony/form/Extension/DataCollector/FormDataExtractorInterface.php b/lib/symfony/form/Extension/DataCollector/FormDataExtractorInterface.php deleted file mode 100644 index 7e82286ad..000000000 --- a/lib/symfony/form/Extension/DataCollector/FormDataExtractorInterface.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\DataCollector; - -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; - -/** - * Extracts arrays of information out of forms. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface FormDataExtractorInterface -{ - /** - * Extracts the configuration data of a form. - * - * @return array - */ - public function extractConfiguration(FormInterface $form); - - /** - * Extracts the default data of a form. - * - * @return array - */ - public function extractDefaultData(FormInterface $form); - - /** - * Extracts the submitted data of a form. - * - * @return array - */ - public function extractSubmittedData(FormInterface $form); - - /** - * Extracts the view variables of a form. - * - * @return array - */ - public function extractViewVariables(FormView $view); -} diff --git a/lib/symfony/form/Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.php b/lib/symfony/form/Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.php deleted file mode 100644 index 54358d5d4..000000000 --- a/lib/symfony/form/Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.php +++ /dev/null @@ -1,140 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\DataCollector\Proxy; - -use Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormFactoryInterface; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; -use Symfony\Component\Form\ResolvedFormTypeInterface; - -/** - * Proxy that invokes a data collector when creating a form and its view. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class ResolvedTypeDataCollectorProxy implements ResolvedFormTypeInterface -{ - private $proxiedType; - private $dataCollector; - - public function __construct(ResolvedFormTypeInterface $proxiedType, FormDataCollectorInterface $dataCollector) - { - $this->proxiedType = $proxiedType; - $this->dataCollector = $dataCollector; - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return $this->proxiedType->getBlockPrefix(); - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - return $this->proxiedType->getParent(); - } - - /** - * {@inheritdoc} - */ - public function getInnerType() - { - return $this->proxiedType->getInnerType(); - } - - /** - * {@inheritdoc} - */ - public function getTypeExtensions() - { - return $this->proxiedType->getTypeExtensions(); - } - - /** - * {@inheritdoc} - */ - public function createBuilder(FormFactoryInterface $factory, string $name, array $options = []) - { - $builder = $this->proxiedType->createBuilder($factory, $name, $options); - - $builder->setAttribute('data_collector/passed_options', $options); - $builder->setType($this); - - return $builder; - } - - /** - * {@inheritdoc} - */ - public function createView(FormInterface $form, FormView $parent = null) - { - return $this->proxiedType->createView($form, $parent); - } - - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - $this->proxiedType->buildForm($builder, $options); - } - - /** - * {@inheritdoc} - */ - public function buildView(FormView $view, FormInterface $form, array $options) - { - $this->proxiedType->buildView($view, $form, $options); - } - - /** - * {@inheritdoc} - */ - public function finishView(FormView $view, FormInterface $form, array $options) - { - $this->proxiedType->finishView($view, $form, $options); - - // Remember which view belongs to which form instance, so that we can - // get the collected data for a view when its form instance is not - // available (e.g. CSRF token) - $this->dataCollector->associateFormWithView($form, $view); - - // Since the CSRF token is only present in the FormView tree, we also - // need to check the FormView tree instead of calling isRoot() on the - // FormInterface tree - if (null === $view->parent) { - $this->dataCollector->collectViewVariables($view); - - // Re-assemble data, in case FormView instances were added, for - // which no FormInterface instances were present (e.g. CSRF token). - // Since finishView() is called after finishing the views of all - // children, we can safely assume that information has been - // collected about the complete form tree. - $this->dataCollector->buildFinalFormTree($form, $view); - } - } - - /** - * {@inheritdoc} - */ - public function getOptionsResolver() - { - return $this->proxiedType->getOptionsResolver(); - } -} diff --git a/lib/symfony/form/Extension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.php b/lib/symfony/form/Extension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.php deleted file mode 100644 index 068d5cc0b..000000000 --- a/lib/symfony/form/Extension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\DataCollector\Proxy; - -use Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface; -use Symfony\Component\Form\FormTypeInterface; -use Symfony\Component\Form\ResolvedFormTypeFactoryInterface; -use Symfony\Component\Form\ResolvedFormTypeInterface; - -/** - * Proxy that wraps resolved types into {@link ResolvedTypeDataCollectorProxy} - * instances. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class ResolvedTypeFactoryDataCollectorProxy implements ResolvedFormTypeFactoryInterface -{ - private $proxiedFactory; - private $dataCollector; - - public function __construct(ResolvedFormTypeFactoryInterface $proxiedFactory, FormDataCollectorInterface $dataCollector) - { - $this->proxiedFactory = $proxiedFactory; - $this->dataCollector = $dataCollector; - } - - /** - * {@inheritdoc} - */ - public function createResolvedType(FormTypeInterface $type, array $typeExtensions, ResolvedFormTypeInterface $parent = null) - { - return new ResolvedTypeDataCollectorProxy( - $this->proxiedFactory->createResolvedType($type, $typeExtensions, $parent), - $this->dataCollector - ); - } -} diff --git a/lib/symfony/form/Extension/DataCollector/Type/DataCollectorTypeExtension.php b/lib/symfony/form/Extension/DataCollector/Type/DataCollectorTypeExtension.php deleted file mode 100644 index d25fd132c..000000000 --- a/lib/symfony/form/Extension/DataCollector/Type/DataCollectorTypeExtension.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\DataCollector\Type; - -use Symfony\Component\Form\AbstractTypeExtension; -use Symfony\Component\Form\Extension\Core\Type\FormType; -use Symfony\Component\Form\Extension\DataCollector\EventListener\DataCollectorListener; -use Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface; -use Symfony\Component\Form\FormBuilderInterface; - -/** - * Type extension for collecting data of a form with this type. - * - * @author Robert Schönthal <robert.schoenthal@gmail.com> - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class DataCollectorTypeExtension extends AbstractTypeExtension -{ - /** - * @var DataCollectorListener - */ - private $listener; - - public function __construct(FormDataCollectorInterface $dataCollector) - { - $this->listener = new DataCollectorListener($dataCollector); - } - - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - $builder->addEventSubscriber($this->listener); - } - - /** - * {@inheritdoc} - */ - public static function getExtendedTypes(): iterable - { - return [FormType::class]; - } -} diff --git a/lib/symfony/form/Extension/DependencyInjection/DependencyInjectionExtension.php b/lib/symfony/form/Extension/DependencyInjection/DependencyInjectionExtension.php deleted file mode 100644 index 5d61a0693..000000000 --- a/lib/symfony/form/Extension/DependencyInjection/DependencyInjectionExtension.php +++ /dev/null @@ -1,111 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\DependencyInjection; - -use Psr\Container\ContainerInterface; -use Symfony\Component\Form\Exception\InvalidArgumentException; -use Symfony\Component\Form\FormExtensionInterface; -use Symfony\Component\Form\FormTypeGuesserChain; - -class DependencyInjectionExtension implements FormExtensionInterface -{ - private $guesser; - private $guesserLoaded = false; - private $typeContainer; - private $typeExtensionServices; - private $guesserServices; - - /** - * @param iterable[] $typeExtensionServices - */ - public function __construct(ContainerInterface $typeContainer, array $typeExtensionServices, iterable $guesserServices) - { - $this->typeContainer = $typeContainer; - $this->typeExtensionServices = $typeExtensionServices; - $this->guesserServices = $guesserServices; - } - - /** - * {@inheritdoc} - */ - public function getType(string $name) - { - if (!$this->typeContainer->has($name)) { - throw new InvalidArgumentException(sprintf('The field type "%s" is not registered in the service container.', $name)); - } - - return $this->typeContainer->get($name); - } - - /** - * {@inheritdoc} - */ - public function hasType(string $name) - { - return $this->typeContainer->has($name); - } - - /** - * {@inheritdoc} - */ - public function getTypeExtensions(string $name) - { - $extensions = []; - - if (isset($this->typeExtensionServices[$name])) { - foreach ($this->typeExtensionServices[$name] as $extension) { - $extensions[] = $extension; - - $extendedTypes = []; - foreach ($extension::getExtendedTypes() as $extendedType) { - $extendedTypes[] = $extendedType; - } - - // validate the result of getExtendedTypes() to ensure it is consistent with the service definition - if (!\in_array($name, $extendedTypes, true)) { - throw new InvalidArgumentException(sprintf('The extended type "%s" specified for the type extension class "%s" does not match any of the actual extended types (["%s"]).', $name, \get_class($extension), implode('", "', $extendedTypes))); - } - } - } - - return $extensions; - } - - /** - * {@inheritdoc} - */ - public function hasTypeExtensions(string $name) - { - return isset($this->typeExtensionServices[$name]); - } - - /** - * {@inheritdoc} - */ - public function getTypeGuesser() - { - if (!$this->guesserLoaded) { - $this->guesserLoaded = true; - $guessers = []; - - foreach ($this->guesserServices as $serviceId => $service) { - $guessers[] = $service; - } - - if ($guessers) { - $this->guesser = new FormTypeGuesserChain($guessers); - } - } - - return $this->guesser; - } -} diff --git a/lib/symfony/form/Extension/HttpFoundation/HttpFoundationExtension.php b/lib/symfony/form/Extension/HttpFoundation/HttpFoundationExtension.php deleted file mode 100644 index 27305ada4..000000000 --- a/lib/symfony/form/Extension/HttpFoundation/HttpFoundationExtension.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\HttpFoundation; - -use Symfony\Component\Form\AbstractExtension; - -/** - * Integrates the HttpFoundation component with the Form library. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class HttpFoundationExtension extends AbstractExtension -{ - protected function loadTypeExtensions() - { - return [ - new Type\FormTypeHttpFoundationExtension(), - ]; - } -} diff --git a/lib/symfony/form/Extension/HttpFoundation/HttpFoundationRequestHandler.php b/lib/symfony/form/Extension/HttpFoundation/HttpFoundationRequestHandler.php deleted file mode 100644 index 05503ff52..000000000 --- a/lib/symfony/form/Extension/HttpFoundation/HttpFoundationRequestHandler.php +++ /dev/null @@ -1,131 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\HttpFoundation; - -use Symfony\Component\Form\Exception\UnexpectedTypeException; -use Symfony\Component\Form\FormError; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\RequestHandlerInterface; -use Symfony\Component\Form\Util\ServerParams; -use Symfony\Component\HttpFoundation\File\File; -use Symfony\Component\HttpFoundation\File\UploadedFile; -use Symfony\Component\HttpFoundation\Request; - -/** - * A request processor using the {@link Request} class of the HttpFoundation - * component. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class HttpFoundationRequestHandler implements RequestHandlerInterface -{ - private $serverParams; - - public function __construct(ServerParams $serverParams = null) - { - $this->serverParams = $serverParams ?? new ServerParams(); - } - - /** - * {@inheritdoc} - */ - public function handleRequest(FormInterface $form, $request = null) - { - if (!$request instanceof Request) { - throw new UnexpectedTypeException($request, 'Symfony\Component\HttpFoundation\Request'); - } - - $name = $form->getName(); - $method = $form->getConfig()->getMethod(); - - if ($method !== $request->getMethod()) { - return; - } - - // For request methods that must not have a request body we fetch data - // from the query string. Otherwise we look for data in the request body. - if ('GET' === $method || 'HEAD' === $method || 'TRACE' === $method) { - if ('' === $name) { - $data = $request->query->all(); - } else { - // Don't submit GET requests if the form's name does not exist - // in the request - if (!$request->query->has($name)) { - return; - } - - $data = $request->query->all()[$name]; - } - } else { - // Mark the form with an error if the uploaded size was too large - // This is done here and not in FormValidator because $_POST is - // empty when that error occurs. Hence the form is never submitted. - if ($this->serverParams->hasPostMaxSizeBeenExceeded()) { - // Submit the form, but don't clear the default values - $form->submit(null, false); - - $form->addError(new FormError( - $form->getConfig()->getOption('upload_max_size_message')(), - null, - ['{{ max }}' => $this->serverParams->getNormalizedIniPostMaxSize()] - )); - - return; - } - - if ('' === $name) { - $params = $request->request->all(); - $files = $request->files->all(); - } elseif ($request->request->has($name) || $request->files->has($name)) { - $default = $form->getConfig()->getCompound() ? [] : null; - $params = $request->request->all()[$name] ?? $default; - $files = $request->files->get($name, $default); - } else { - // Don't submit the form if it is not present in the request - return; - } - - if (\is_array($params) && \is_array($files)) { - $data = array_replace_recursive($params, $files); - } else { - $data = $params ?: $files; - } - } - - // Don't auto-submit the form unless at least one field is present. - if ('' === $name && \count(array_intersect_key($data, $form->all())) <= 0) { - return; - } - - $form->submit($data, 'PATCH' !== $method); - } - - /** - * {@inheritdoc} - */ - public function isFileUpload($data) - { - return $data instanceof File; - } - - /** - * @return int|null - */ - public function getUploadFileError($data) - { - if (!$data instanceof UploadedFile || $data->isValid()) { - return null; - } - - return $data->getError(); - } -} diff --git a/lib/symfony/form/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php b/lib/symfony/form/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php deleted file mode 100644 index 0d77f06ce..000000000 --- a/lib/symfony/form/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\HttpFoundation\Type; - -use Symfony\Component\Form\AbstractTypeExtension; -use Symfony\Component\Form\Extension\Core\Type\FormType; -use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\RequestHandlerInterface; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class FormTypeHttpFoundationExtension extends AbstractTypeExtension -{ - private $requestHandler; - - public function __construct(RequestHandlerInterface $requestHandler = null) - { - $this->requestHandler = $requestHandler ?? new HttpFoundationRequestHandler(); - } - - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - $builder->setRequestHandler($this->requestHandler); - } - - /** - * {@inheritdoc} - */ - public static function getExtendedTypes(): iterable - { - return [FormType::class]; - } -} diff --git a/lib/symfony/form/Extension/Validator/Constraints/Form.php b/lib/symfony/form/Extension/Validator/Constraints/Form.php deleted file mode 100644 index 49291e671..000000000 --- a/lib/symfony/form/Extension/Validator/Constraints/Form.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Validator\Constraints; - -use Symfony\Component\Validator\Constraint; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class Form extends Constraint -{ - public const NOT_SYNCHRONIZED_ERROR = '1dafa156-89e1-4736-b832-419c2e501fca'; - public const NO_SUCH_FIELD_ERROR = '6e5212ed-a197-4339-99aa-5654798a4854'; - - protected static $errorNames = [ - self::NOT_SYNCHRONIZED_ERROR => 'NOT_SYNCHRONIZED_ERROR', - self::NO_SUCH_FIELD_ERROR => 'NO_SUCH_FIELD_ERROR', - ]; - - /** - * {@inheritdoc} - */ - public function getTargets() - { - return self::CLASS_CONSTRAINT; - } -} diff --git a/lib/symfony/form/Extension/Validator/Constraints/FormValidator.php b/lib/symfony/form/Extension/Validator/Constraints/FormValidator.php deleted file mode 100644 index 47982f3fc..000000000 --- a/lib/symfony/form/Extension/Validator/Constraints/FormValidator.php +++ /dev/null @@ -1,279 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Validator\Constraints; - -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Constraints\Composite; -use Symfony\Component\Validator\Constraints\GroupSequence; -use Symfony\Component\Validator\Constraints\Valid; -use Symfony\Component\Validator\ConstraintValidator; -use Symfony\Component\Validator\Exception\UnexpectedTypeException; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class FormValidator extends ConstraintValidator -{ - /** - * @var \SplObjectStorage<FormInterface, array<int, string|string[]|GroupSequence>> - */ - private $resolvedGroups; - - /** - * {@inheritdoc} - */ - public function validate($form, Constraint $formConstraint) - { - if (!$formConstraint instanceof Form) { - throw new UnexpectedTypeException($formConstraint, Form::class); - } - - if (!$form instanceof FormInterface) { - return; - } - - /* @var FormInterface $form */ - $config = $form->getConfig(); - - $validator = $this->context->getValidator()->inContext($this->context); - - if ($form->isSubmitted() && $form->isSynchronized()) { - // Validate the form data only if transformation succeeded - $groups = $this->getValidationGroups($form); - - if (!$groups) { - return; - } - - $data = $form->getData(); - // Validate the data against its own constraints - $validateDataGraph = $form->isRoot() - && (\is_object($data) || \is_array($data)) - && (($groups && \is_array($groups)) || ($groups instanceof GroupSequence && $groups->groups)) - ; - - // Validate the data against the constraints defined in the form - /** @var Constraint[] $constraints */ - $constraints = $config->getOption('constraints', []); - - $hasChildren = $form->count() > 0; - - if ($hasChildren && $form->isRoot()) { - $this->resolvedGroups = new \SplObjectStorage(); - } - - if ($groups instanceof GroupSequence) { - // Validate the data, the form AND nested fields in sequence - $violationsCount = $this->context->getViolations()->count(); - - foreach ($groups->groups as $group) { - if ($validateDataGraph) { - $validator->atPath('data')->validate($data, null, $group); - } - - if ($groupedConstraints = self::getConstraintsInGroups($constraints, $group)) { - $validator->atPath('data')->validate($data, $groupedConstraints, $group); - } - - foreach ($form->all() as $field) { - if ($field->isSubmitted()) { - // remember to validate this field in one group only - // otherwise resolving the groups would reuse the same - // sequence recursively, thus some fields could fail - // in different steps without breaking early enough - $this->resolvedGroups[$field] = (array) $group; - $fieldFormConstraint = new Form(); - $fieldFormConstraint->groups = $group; - $this->context->setNode($this->context->getValue(), $field, $this->context->getMetadata(), $this->context->getPropertyPath()); - $validator->atPath(sprintf('children[%s]', $field->getName()))->validate($field, $fieldFormConstraint, $group); - } - } - - if ($violationsCount < $this->context->getViolations()->count()) { - break; - } - } - } else { - if ($validateDataGraph) { - $validator->atPath('data')->validate($data, null, $groups); - } - - $groupedConstraints = []; - - foreach ($constraints as $constraint) { - // For the "Valid" constraint, validate the data in all groups - if ($constraint instanceof Valid) { - if (\is_object($data) || \is_array($data)) { - $validator->atPath('data')->validate($data, $constraint, $groups); - } - - continue; - } - - // Otherwise validate a constraint only once for the first - // matching group - foreach ($groups as $group) { - if (\in_array($group, $constraint->groups)) { - $groupedConstraints[$group][] = $constraint; - - // Prevent duplicate validation - if (!$constraint instanceof Composite) { - continue 2; - } - } - } - } - - foreach ($groupedConstraints as $group => $constraint) { - $validator->atPath('data')->validate($data, $constraint, $group); - } - - foreach ($form->all() as $field) { - if ($field->isSubmitted()) { - $this->resolvedGroups[$field] = $groups; - $this->context->setNode($this->context->getValue(), $field, $this->context->getMetadata(), $this->context->getPropertyPath()); - $validator->atPath(sprintf('children[%s]', $field->getName()))->validate($field, $formConstraint); - } - } - } - - if ($hasChildren && $form->isRoot()) { - // destroy storage to avoid memory leaks - $this->resolvedGroups = new \SplObjectStorage(); - } - } elseif (!$form->isSynchronized()) { - $childrenSynchronized = true; - - /** @var FormInterface $child */ - foreach ($form as $child) { - if (!$child->isSynchronized()) { - $childrenSynchronized = false; - $this->context->setNode($this->context->getValue(), $child, $this->context->getMetadata(), $this->context->getPropertyPath()); - $validator->atPath(sprintf('children[%s]', $child->getName()))->validate($child, $formConstraint); - } - } - - // Mark the form with an error if it is not synchronized BUT all - // of its children are synchronized. If any child is not - // synchronized, an error is displayed there already and showing - // a second error in its parent form is pointless, or worse, may - // lead to duplicate errors if error bubbling is enabled on the - // child. - // See also https://github.com/symfony/symfony/issues/4359 - if ($childrenSynchronized) { - $clientDataAsString = \is_scalar($form->getViewData()) - ? (string) $form->getViewData() - : get_debug_type($form->getViewData()); - - $failure = $form->getTransformationFailure(); - - $this->context->setConstraint($formConstraint); - $this->context->buildViolation($failure->getInvalidMessage() ?? $config->getOption('invalid_message')) - ->setParameters(array_replace( - ['{{ value }}' => $clientDataAsString], - $config->getOption('invalid_message_parameters'), - $failure->getInvalidMessageParameters() - )) - ->setInvalidValue($form->getViewData()) - ->setCode(Form::NOT_SYNCHRONIZED_ERROR) - ->setCause($failure) - ->addViolation(); - } - } - - // Mark the form with an error if it contains extra fields - if (!$config->getOption('allow_extra_fields') && \count($form->getExtraData()) > 0) { - $this->context->setConstraint($formConstraint); - $this->context->buildViolation($config->getOption('extra_fields_message', '')) - ->setParameter('{{ extra_fields }}', '"'.implode('", "', array_keys($form->getExtraData())).'"') - ->setPlural(\count($form->getExtraData())) - ->setInvalidValue($form->getExtraData()) - ->setCode(Form::NO_SUCH_FIELD_ERROR) - ->addViolation(); - } - } - - /** - * Returns the validation groups of the given form. - * - * @return string|GroupSequence|array<string|GroupSequence> - */ - private function getValidationGroups(FormInterface $form) - { - // Determine the clicked button of the complete form tree - $clickedButton = null; - - if (method_exists($form, 'getClickedButton')) { - $clickedButton = $form->getClickedButton(); - } - - if (null !== $clickedButton) { - $groups = $clickedButton->getConfig()->getOption('validation_groups'); - - if (null !== $groups) { - return self::resolveValidationGroups($groups, $form); - } - } - - do { - $groups = $form->getConfig()->getOption('validation_groups'); - - if (null !== $groups) { - return self::resolveValidationGroups($groups, $form); - } - - if (isset($this->resolvedGroups[$form])) { - return $this->resolvedGroups[$form]; - } - - $form = $form->getParent(); - } while (null !== $form); - - return [Constraint::DEFAULT_GROUP]; - } - - /** - * Post-processes the validation groups option for a given form. - * - * @param string|GroupSequence|array<string|GroupSequence>|callable $groups The validation groups - * - * @return GroupSequence|array<string|GroupSequence> - */ - private static function resolveValidationGroups($groups, FormInterface $form) - { - if (!\is_string($groups) && \is_callable($groups)) { - $groups = $groups($form); - } - - if ($groups instanceof GroupSequence) { - return $groups; - } - - return (array) $groups; - } - - private static function getConstraintsInGroups($constraints, $group) - { - $groups = (array) $group; - - return array_filter($constraints, static function (Constraint $constraint) use ($groups) { - foreach ($groups as $group) { - if (\in_array($group, $constraint->groups, true)) { - return true; - } - } - - return false; - }); - } -} diff --git a/lib/symfony/form/Extension/Validator/EventListener/ValidationListener.php b/lib/symfony/form/Extension/Validator/EventListener/ValidationListener.php deleted file mode 100644 index 867a5768a..000000000 --- a/lib/symfony/form/Extension/Validator/EventListener/ValidationListener.php +++ /dev/null @@ -1,59 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Validator\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Form\Extension\Validator\Constraints\Form; -use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapperInterface; -use Symfony\Component\Form\FormEvent; -use Symfony\Component\Form\FormEvents; -use Symfony\Component\Validator\Validator\ValidatorInterface; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class ValidationListener implements EventSubscriberInterface -{ - private $validator; - - private $violationMapper; - - /** - * {@inheritdoc} - */ - public static function getSubscribedEvents() - { - return [FormEvents::POST_SUBMIT => 'validateForm']; - } - - public function __construct(ValidatorInterface $validator, ViolationMapperInterface $violationMapper) - { - $this->validator = $validator; - $this->violationMapper = $violationMapper; - } - - public function validateForm(FormEvent $event) - { - $form = $event->getForm(); - - if ($form->isRoot()) { - // Form groups are validated internally (FormValidator). Here we don't set groups as they are retrieved into the validator. - foreach ($this->validator->validate($form) as $violation) { - // Allow the "invalid" constraint to be put onto - // non-synchronized forms - $allowNonSynchronized = $violation->getConstraint() instanceof Form && Form::NOT_SYNCHRONIZED_ERROR === $violation->getCode(); - - $this->violationMapper->mapViolation($violation, $form, $allowNonSynchronized); - } - } - } -} diff --git a/lib/symfony/form/Extension/Validator/Type/BaseValidatorExtension.php b/lib/symfony/form/Extension/Validator/Type/BaseValidatorExtension.php deleted file mode 100644 index 0e9e2a9d7..000000000 --- a/lib/symfony/form/Extension/Validator/Type/BaseValidatorExtension.php +++ /dev/null @@ -1,59 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Validator\Type; - -use Symfony\Component\Form\AbstractTypeExtension; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; -use Symfony\Component\Validator\Constraints\GroupSequence; - -/** - * Encapsulates common logic of {@link FormTypeValidatorExtension} and - * {@link SubmitTypeValidatorExtension}. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -abstract class BaseValidatorExtension extends AbstractTypeExtension -{ - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - // Make sure that validation groups end up as null, closure or array - $validationGroupsNormalizer = function (Options $options, $groups) { - if (false === $groups) { - return []; - } - - if (empty($groups)) { - return null; - } - - if (\is_callable($groups)) { - return $groups; - } - - if ($groups instanceof GroupSequence) { - return $groups; - } - - return (array) $groups; - }; - - $resolver->setDefaults([ - 'validation_groups' => null, - ]); - - $resolver->setNormalizer('validation_groups', $validationGroupsNormalizer); - } -} diff --git a/lib/symfony/form/Extension/Validator/Type/FormTypeValidatorExtension.php b/lib/symfony/form/Extension/Validator/Type/FormTypeValidatorExtension.php deleted file mode 100644 index d4c520ce8..000000000 --- a/lib/symfony/form/Extension/Validator/Type/FormTypeValidatorExtension.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Validator\Type; - -use Symfony\Component\Form\Extension\Core\Type\FormType; -use Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener; -use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapper; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormRendererInterface; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Validator\ValidatorInterface; -use Symfony\Contracts\Translation\TranslatorInterface; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class FormTypeValidatorExtension extends BaseValidatorExtension -{ - private $validator; - private $violationMapper; - private $legacyErrorMessages; - - public function __construct(ValidatorInterface $validator, bool $legacyErrorMessages = true, FormRendererInterface $formRenderer = null, TranslatorInterface $translator = null) - { - $this->validator = $validator; - $this->violationMapper = new ViolationMapper($formRenderer, $translator); - $this->legacyErrorMessages = $legacyErrorMessages; - } - - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - $builder->addEventSubscriber(new ValidationListener($this->validator, $this->violationMapper)); - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - parent::configureOptions($resolver); - - // Constraint should always be converted to an array - $constraintsNormalizer = function (Options $options, $constraints) { - return \is_object($constraints) ? [$constraints] : (array) $constraints; - }; - - $resolver->setDefaults([ - 'error_mapping' => [], - 'constraints' => [], - 'invalid_message' => 'This value is not valid.', - 'invalid_message_parameters' => [], - 'legacy_error_messages' => $this->legacyErrorMessages, - 'allow_extra_fields' => false, - 'extra_fields_message' => 'This form should not contain extra fields.', - ]); - $resolver->setAllowedTypes('constraints', [Constraint::class, Constraint::class.'[]']); - $resolver->setAllowedTypes('legacy_error_messages', 'bool'); - $resolver->setDeprecated('legacy_error_messages', 'symfony/form', '5.2', function (Options $options, $value) { - if (true === $value) { - return 'Setting the "legacy_error_messages" option to "true" is deprecated. It will be disabled in Symfony 6.0.'; - } - - return ''; - }); - - $resolver->setNormalizer('constraints', $constraintsNormalizer); - } - - /** - * {@inheritdoc} - */ - public static function getExtendedTypes(): iterable - { - return [FormType::class]; - } -} diff --git a/lib/symfony/form/Extension/Validator/Type/RepeatedTypeValidatorExtension.php b/lib/symfony/form/Extension/Validator/Type/RepeatedTypeValidatorExtension.php deleted file mode 100644 index 4bda0b27d..000000000 --- a/lib/symfony/form/Extension/Validator/Type/RepeatedTypeValidatorExtension.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Validator\Type; - -use Symfony\Component\Form\AbstractTypeExtension; -use Symfony\Component\Form\Extension\Core\Type\RepeatedType; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class RepeatedTypeValidatorExtension extends AbstractTypeExtension -{ - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - // Map errors to the first field - $errorMapping = function (Options $options) { - return ['.' => $options['first_name']]; - }; - - $resolver->setDefaults([ - 'error_mapping' => $errorMapping, - ]); - } - - /** - * {@inheritdoc} - */ - public static function getExtendedTypes(): iterable - { - return [RepeatedType::class]; - } -} diff --git a/lib/symfony/form/Extension/Validator/Type/SubmitTypeValidatorExtension.php b/lib/symfony/form/Extension/Validator/Type/SubmitTypeValidatorExtension.php deleted file mode 100644 index ea273d0ad..000000000 --- a/lib/symfony/form/Extension/Validator/Type/SubmitTypeValidatorExtension.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Validator\Type; - -use Symfony\Component\Form\Extension\Core\Type\SubmitType; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class SubmitTypeValidatorExtension extends BaseValidatorExtension -{ - /** - * {@inheritdoc} - */ - public static function getExtendedTypes(): iterable - { - return [SubmitType::class]; - } -} diff --git a/lib/symfony/form/Extension/Validator/Type/UploadValidatorExtension.php b/lib/symfony/form/Extension/Validator/Type/UploadValidatorExtension.php deleted file mode 100644 index 21e4fe20e..000000000 --- a/lib/symfony/form/Extension/Validator/Type/UploadValidatorExtension.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Validator\Type; - -use Symfony\Component\Form\AbstractTypeExtension; -use Symfony\Component\Form\Extension\Core\Type\FormType; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; -use Symfony\Contracts\Translation\TranslatorInterface; - -/** - * @author Abdellatif Ait boudad <a.aitboudad@gmail.com> - * @author David Badura <d.a.badura@gmail.com> - */ -class UploadValidatorExtension extends AbstractTypeExtension -{ - private $translator; - private $translationDomain; - - public function __construct(TranslatorInterface $translator, string $translationDomain = null) - { - $this->translator = $translator; - $this->translationDomain = $translationDomain; - } - - /** - * {@inheritdoc} - */ - public function configureOptions(OptionsResolver $resolver) - { - $translator = $this->translator; - $translationDomain = $this->translationDomain; - $resolver->setNormalizer('upload_max_size_message', function (Options $options, $message) use ($translator, $translationDomain) { - return function () use ($translator, $translationDomain, $message) { - return $translator->trans($message(), [], $translationDomain); - }; - }); - } - - /** - * {@inheritdoc} - */ - public static function getExtendedTypes(): iterable - { - return [FormType::class]; - } -} diff --git a/lib/symfony/form/Extension/Validator/Util/ServerParams.php b/lib/symfony/form/Extension/Validator/Util/ServerParams.php deleted file mode 100644 index 98e9f0c98..000000000 --- a/lib/symfony/form/Extension/Validator/Util/ServerParams.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Validator\Util; - -use Symfony\Component\Form\Util\ServerParams as BaseServerParams; - -trigger_deprecation('symfony/form', '5.1', 'The "%s" class is deprecated. Use "%s" instead.', ServerParams::class, BaseServerParams::class); - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @deprecated since Symfony 5.1. Use {@see BaseServerParams} instead. - */ -class ServerParams extends BaseServerParams -{ -} diff --git a/lib/symfony/form/Extension/Validator/ValidatorExtension.php b/lib/symfony/form/Extension/Validator/ValidatorExtension.php deleted file mode 100644 index 3a5728a82..000000000 --- a/lib/symfony/form/Extension/Validator/ValidatorExtension.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Validator; - -use Symfony\Component\Form\AbstractExtension; -use Symfony\Component\Form\Extension\Validator\Constraints\Form; -use Symfony\Component\Form\FormRendererInterface; -use Symfony\Component\Validator\Constraints\Traverse; -use Symfony\Component\Validator\Mapping\ClassMetadata; -use Symfony\Component\Validator\Validator\ValidatorInterface; -use Symfony\Contracts\Translation\TranslatorInterface; - -/** - * Extension supporting the Symfony Validator component in forms. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class ValidatorExtension extends AbstractExtension -{ - private $validator; - private $formRenderer; - private $translator; - private $legacyErrorMessages; - - public function __construct(ValidatorInterface $validator, bool $legacyErrorMessages = true, FormRendererInterface $formRenderer = null, TranslatorInterface $translator = null) - { - $this->legacyErrorMessages = $legacyErrorMessages; - - $metadata = $validator->getMetadataFor('Symfony\Component\Form\Form'); - - // Register the form constraints in the validator programmatically. - // This functionality is required when using the Form component without - // the DIC, where the XML file is loaded automatically. Thus the following - // code must be kept synchronized with validation.xml - - /* @var $metadata ClassMetadata */ - $metadata->addConstraint(new Form()); - $metadata->addConstraint(new Traverse(false)); - - $this->validator = $validator; - $this->formRenderer = $formRenderer; - $this->translator = $translator; - } - - public function loadTypeGuesser() - { - return new ValidatorTypeGuesser($this->validator); - } - - protected function loadTypeExtensions() - { - return [ - new Type\FormTypeValidatorExtension($this->validator, $this->legacyErrorMessages, $this->formRenderer, $this->translator), - new Type\RepeatedTypeValidatorExtension(), - new Type\SubmitTypeValidatorExtension(), - ]; - } -} diff --git a/lib/symfony/form/Extension/Validator/ValidatorTypeGuesser.php b/lib/symfony/form/Extension/Validator/ValidatorTypeGuesser.php deleted file mode 100644 index 24470bad5..000000000 --- a/lib/symfony/form/Extension/Validator/ValidatorTypeGuesser.php +++ /dev/null @@ -1,283 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Validator; - -use Symfony\Component\Form\FormTypeGuesserInterface; -use Symfony\Component\Form\Guess\Guess; -use Symfony\Component\Form\Guess\TypeGuess; -use Symfony\Component\Form\Guess\ValueGuess; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Mapping\ClassMetadataInterface; -use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface; - -class ValidatorTypeGuesser implements FormTypeGuesserInterface -{ - private $metadataFactory; - - public function __construct(MetadataFactoryInterface $metadataFactory) - { - $this->metadataFactory = $metadataFactory; - } - - /** - * {@inheritdoc} - */ - public function guessType(string $class, string $property) - { - return $this->guess($class, $property, function (Constraint $constraint) { - return $this->guessTypeForConstraint($constraint); - }); - } - - /** - * {@inheritdoc} - */ - public function guessRequired(string $class, string $property) - { - return $this->guess($class, $property, function (Constraint $constraint) { - return $this->guessRequiredForConstraint($constraint); - // If we don't find any constraint telling otherwise, we can assume - // that a field is not required (with LOW_CONFIDENCE) - }, false); - } - - /** - * {@inheritdoc} - */ - public function guessMaxLength(string $class, string $property) - { - return $this->guess($class, $property, function (Constraint $constraint) { - return $this->guessMaxLengthForConstraint($constraint); - }); - } - - /** - * {@inheritdoc} - */ - public function guessPattern(string $class, string $property) - { - return $this->guess($class, $property, function (Constraint $constraint) { - return $this->guessPatternForConstraint($constraint); - }); - } - - /** - * Guesses a field class name for a given constraint. - * - * @return TypeGuess|null - */ - public function guessTypeForConstraint(Constraint $constraint) - { - switch (\get_class($constraint)) { - case 'Symfony\Component\Validator\Constraints\Type': - switch ($constraint->type) { - case 'array': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\CollectionType', [], Guess::MEDIUM_CONFIDENCE); - case 'boolean': - case 'bool': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\CheckboxType', [], Guess::MEDIUM_CONFIDENCE); - - case 'double': - case 'float': - case 'numeric': - case 'real': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\NumberType', [], Guess::MEDIUM_CONFIDENCE); - - case 'integer': - case 'int': - case 'long': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\IntegerType', [], Guess::MEDIUM_CONFIDENCE); - - case \DateTime::class: - case '\DateTime': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateType', [], Guess::MEDIUM_CONFIDENCE); - - case 'string': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextType', [], Guess::LOW_CONFIDENCE); - } - break; - - case 'Symfony\Component\Validator\Constraints\Country': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\CountryType', [], Guess::HIGH_CONFIDENCE); - - case 'Symfony\Component\Validator\Constraints\Currency': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\CurrencyType', [], Guess::HIGH_CONFIDENCE); - - case 'Symfony\Component\Validator\Constraints\Date': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateType', ['input' => 'string'], Guess::HIGH_CONFIDENCE); - - case 'Symfony\Component\Validator\Constraints\DateTime': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateTimeType', ['input' => 'string'], Guess::HIGH_CONFIDENCE); - - case 'Symfony\Component\Validator\Constraints\Email': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\EmailType', [], Guess::HIGH_CONFIDENCE); - - case 'Symfony\Component\Validator\Constraints\File': - case 'Symfony\Component\Validator\Constraints\Image': - $options = []; - if ($constraint->mimeTypes) { - $options = ['attr' => ['accept' => implode(',', (array) $constraint->mimeTypes)]]; - } - - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\FileType', $options, Guess::HIGH_CONFIDENCE); - - case 'Symfony\Component\Validator\Constraints\Language': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\LanguageType', [], Guess::HIGH_CONFIDENCE); - - case 'Symfony\Component\Validator\Constraints\Locale': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\LocaleType', [], Guess::HIGH_CONFIDENCE); - - case 'Symfony\Component\Validator\Constraints\Time': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TimeType', ['input' => 'string'], Guess::HIGH_CONFIDENCE); - - case 'Symfony\Component\Validator\Constraints\Url': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\UrlType', [], Guess::HIGH_CONFIDENCE); - - case 'Symfony\Component\Validator\Constraints\Ip': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextType', [], Guess::MEDIUM_CONFIDENCE); - - case 'Symfony\Component\Validator\Constraints\Length': - case 'Symfony\Component\Validator\Constraints\Regex': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextType', [], Guess::LOW_CONFIDENCE); - - case 'Symfony\Component\Validator\Constraints\Range': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\NumberType', [], Guess::LOW_CONFIDENCE); - - case 'Symfony\Component\Validator\Constraints\Count': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\CollectionType', [], Guess::LOW_CONFIDENCE); - - case 'Symfony\Component\Validator\Constraints\IsTrue': - case 'Symfony\Component\Validator\Constraints\IsFalse': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\CheckboxType', [], Guess::MEDIUM_CONFIDENCE); - } - - return null; - } - - /** - * Guesses whether a field is required based on the given constraint. - * - * @return ValueGuess|null - */ - public function guessRequiredForConstraint(Constraint $constraint) - { - switch (\get_class($constraint)) { - case 'Symfony\Component\Validator\Constraints\NotNull': - case 'Symfony\Component\Validator\Constraints\NotBlank': - case 'Symfony\Component\Validator\Constraints\IsTrue': - return new ValueGuess(true, Guess::HIGH_CONFIDENCE); - } - - return null; - } - - /** - * Guesses a field's maximum length based on the given constraint. - * - * @return ValueGuess|null - */ - public function guessMaxLengthForConstraint(Constraint $constraint) - { - switch (\get_class($constraint)) { - case 'Symfony\Component\Validator\Constraints\Length': - if (is_numeric($constraint->max)) { - return new ValueGuess($constraint->max, Guess::HIGH_CONFIDENCE); - } - break; - - case 'Symfony\Component\Validator\Constraints\Type': - if (\in_array($constraint->type, ['double', 'float', 'numeric', 'real'])) { - return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); - } - break; - - case 'Symfony\Component\Validator\Constraints\Range': - if (is_numeric($constraint->max)) { - return new ValueGuess(\strlen((string) $constraint->max), Guess::LOW_CONFIDENCE); - } - break; - } - - return null; - } - - /** - * Guesses a field's pattern based on the given constraint. - * - * @return ValueGuess|null - */ - public function guessPatternForConstraint(Constraint $constraint) - { - switch (\get_class($constraint)) { - case 'Symfony\Component\Validator\Constraints\Length': - if (is_numeric($constraint->min)) { - return new ValueGuess(sprintf('.{%s,}', (string) $constraint->min), Guess::LOW_CONFIDENCE); - } - break; - - case 'Symfony\Component\Validator\Constraints\Regex': - $htmlPattern = $constraint->getHtmlPattern(); - - if (null !== $htmlPattern) { - return new ValueGuess($htmlPattern, Guess::HIGH_CONFIDENCE); - } - break; - - case 'Symfony\Component\Validator\Constraints\Range': - if (is_numeric($constraint->min)) { - return new ValueGuess(sprintf('.{%s,}', \strlen((string) $constraint->min)), Guess::LOW_CONFIDENCE); - } - break; - - case 'Symfony\Component\Validator\Constraints\Type': - if (\in_array($constraint->type, ['double', 'float', 'numeric', 'real'])) { - return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); - } - break; - } - - return null; - } - - /** - * Iterates over the constraints of a property, executes a constraints on - * them and returns the best guess. - * - * @param \Closure $closure The closure that returns a guess - * for a given constraint - * @param mixed $defaultValue The default value assumed if no other value - * can be guessed - * - * @return Guess|null - */ - protected function guess(string $class, string $property, \Closure $closure, $defaultValue = null) - { - $guesses = []; - $classMetadata = $this->metadataFactory->getMetadataFor($class); - - if ($classMetadata instanceof ClassMetadataInterface && $classMetadata->hasPropertyMetadata($property)) { - foreach ($classMetadata->getPropertyMetadata($property) as $memberMetadata) { - foreach ($memberMetadata->getConstraints() as $constraint) { - if ($guess = $closure($constraint)) { - $guesses[] = $guess; - } - } - } - } - - if (null !== $defaultValue) { - $guesses[] = new ValueGuess($defaultValue, Guess::LOW_CONFIDENCE); - } - - return Guess::getBestGuess($guesses); - } -} diff --git a/lib/symfony/form/Extension/Validator/ViolationMapper/MappingRule.php b/lib/symfony/form/Extension/Validator/ViolationMapper/MappingRule.php deleted file mode 100644 index d9342de6e..000000000 --- a/lib/symfony/form/Extension/Validator/ViolationMapper/MappingRule.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; - -use Symfony\Component\Form\Exception\ErrorMappingException; -use Symfony\Component\Form\FormInterface; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class MappingRule -{ - private $origin; - private $propertyPath; - private $targetPath; - - public function __construct(FormInterface $origin, string $propertyPath, string $targetPath) - { - $this->origin = $origin; - $this->propertyPath = $propertyPath; - $this->targetPath = $targetPath; - } - - /** - * @return FormInterface - */ - public function getOrigin() - { - return $this->origin; - } - - /** - * Matches a property path against the rule path. - * - * If the rule matches, the form mapped by the rule is returned. - * Otherwise this method returns false. - * - * @return FormInterface|null - */ - public function match(string $propertyPath) - { - return $propertyPath === $this->propertyPath ? $this->getTarget() : null; - } - - /** - * Matches a property path against a prefix of the rule path. - * - * @return bool - */ - public function isPrefix(string $propertyPath) - { - $length = \strlen($propertyPath); - $prefix = substr($this->propertyPath, 0, $length); - $next = $this->propertyPath[$length] ?? null; - - return $prefix === $propertyPath && ('[' === $next || '.' === $next); - } - - /** - * @return FormInterface - * - * @throws ErrorMappingException - */ - public function getTarget() - { - $childNames = explode('.', $this->targetPath); - $target = $this->origin; - - foreach ($childNames as $childName) { - if (!$target->has($childName)) { - throw new ErrorMappingException(sprintf('The child "%s" of "%s" mapped by the rule "%s" in "%s" does not exist.', $childName, $target->getName(), $this->targetPath, $this->origin->getName())); - } - $target = $target->get($childName); - } - - return $target; - } -} diff --git a/lib/symfony/form/Extension/Validator/ViolationMapper/RelativePath.php b/lib/symfony/form/Extension/Validator/ViolationMapper/RelativePath.php deleted file mode 100644 index 0efd168e3..000000000 --- a/lib/symfony/form/Extension/Validator/ViolationMapper/RelativePath.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; - -use Symfony\Component\Form\FormInterface; -use Symfony\Component\PropertyAccess\PropertyPath; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class RelativePath extends PropertyPath -{ - private $root; - - public function __construct(FormInterface $root, string $propertyPath) - { - parent::__construct($propertyPath); - - $this->root = $root; - } - - /** - * @return FormInterface - */ - public function getRoot() - { - return $this->root; - } -} diff --git a/lib/symfony/form/Extension/Validator/ViolationMapper/ViolationMapper.php b/lib/symfony/form/Extension/Validator/ViolationMapper/ViolationMapper.php deleted file mode 100644 index 1fb1d1fb0..000000000 --- a/lib/symfony/form/Extension/Validator/ViolationMapper/ViolationMapper.php +++ /dev/null @@ -1,343 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; - -use Symfony\Component\Form\FileUploadError; -use Symfony\Component\Form\FormError; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormRendererInterface; -use Symfony\Component\Form\Util\InheritDataAwareIterator; -use Symfony\Component\PropertyAccess\PropertyPathBuilder; -use Symfony\Component\PropertyAccess\PropertyPathIterator; -use Symfony\Component\PropertyAccess\PropertyPathIteratorInterface; -use Symfony\Component\Validator\Constraints\File; -use Symfony\Component\Validator\ConstraintViolation; -use Symfony\Contracts\Translation\TranslatorInterface; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class ViolationMapper implements ViolationMapperInterface -{ - private $formRenderer; - private $translator; - private $allowNonSynchronized = false; - - public function __construct(FormRendererInterface $formRenderer = null, TranslatorInterface $translator = null) - { - $this->formRenderer = $formRenderer; - $this->translator = $translator; - } - - /** - * {@inheritdoc} - */ - public function mapViolation(ConstraintViolation $violation, FormInterface $form, bool $allowNonSynchronized = false) - { - $this->allowNonSynchronized = $allowNonSynchronized; - - // The scope is the currently found most specific form that - // an error should be mapped to. After setting the scope, the - // mapper will try to continue to find more specific matches in - // the children of scope. If it cannot, the error will be - // mapped to this scope. - $scope = null; - - $violationPath = null; - $relativePath = null; - $match = false; - - // Don't create a ViolationPath instance for empty property paths - if ('' !== $violation->getPropertyPath()) { - $violationPath = new ViolationPath($violation->getPropertyPath()); - $relativePath = $this->reconstructPath($violationPath, $form); - } - - // This case happens if the violation path is empty and thus - // the violation should be mapped to the root form - if (null === $violationPath) { - $scope = $form; - } - - // In general, mapping happens from the root form to the leaf forms - // First, the rules of the root form are applied to determine - // the subsequent descendant. The rules of this descendant are then - // applied to find the next and so on, until we have found the - // most specific form that matches the violation. - - // If any of the forms found in this process is not synchronized, - // mapping is aborted. Non-synchronized forms could not reverse - // transform the value entered by the user, thus any further violations - // caused by the (invalid) reverse transformed value should be - // ignored. - - if (null !== $relativePath) { - // Set the scope to the root of the relative path - // This root will usually be $form. If the path contains - // an unmapped form though, the last unmapped form found - // will be the root of the path. - $scope = $relativePath->getRoot(); - $it = new PropertyPathIterator($relativePath); - - while ($this->acceptsErrors($scope) && null !== ($child = $this->matchChild($scope, $it))) { - $scope = $child; - $it->next(); - $match = true; - } - } - - // This case happens if an error happened in the data under a - // form inheriting its parent data that does not match any of the - // children of that form. - if (null !== $violationPath && !$match) { - // If we could not map the error to anything more specific - // than the root element, map it to the innermost directly - // mapped form of the violation path - // e.g. "children[foo].children[bar].data.baz" - // Here the innermost directly mapped child is "bar" - - $scope = $form; - $it = new ViolationPathIterator($violationPath); - - // Note: acceptsErrors() will always return true for forms inheriting - // their parent data, because these forms can never be non-synchronized - // (they don't do any data transformation on their own) - while ($this->acceptsErrors($scope) && $it->valid() && $it->mapsForm()) { - if (!$scope->has($it->current())) { - // Break if we find a reference to a non-existing child - break; - } - - $scope = $scope->get($it->current()); - $it->next(); - } - } - - // Follow dot rules until we have the final target - $mapping = $scope->getConfig()->getOption('error_mapping'); - - while ($this->acceptsErrors($scope) && isset($mapping['.'])) { - $dotRule = new MappingRule($scope, '.', $mapping['.']); - $scope = $dotRule->getTarget(); - $mapping = $scope->getConfig()->getOption('error_mapping'); - } - - // Only add the error if the form is synchronized - if ($this->acceptsErrors($scope)) { - if ($violation->getConstraint() instanceof File && (string) \UPLOAD_ERR_INI_SIZE === $violation->getCode()) { - $errorsTarget = $scope; - - while (null !== $errorsTarget->getParent() && $errorsTarget->getConfig()->getErrorBubbling()) { - $errorsTarget = $errorsTarget->getParent(); - } - - $errors = $errorsTarget->getErrors(); - $errorsTarget->clearErrors(); - - foreach ($errors as $error) { - if (!$error instanceof FileUploadError) { - $errorsTarget->addError($error); - } - } - } - - $message = $violation->getMessage(); - $messageTemplate = $violation->getMessageTemplate(); - - if (false !== strpos($message, '{{ label }}') || false !== strpos($messageTemplate, '{{ label }}')) { - $form = $scope; - - do { - $labelFormat = $form->getConfig()->getOption('label_format'); - } while (null === $labelFormat && null !== $form = $form->getParent()); - - if (null !== $labelFormat) { - $label = str_replace( - [ - '%name%', - '%id%', - ], - [ - $scope->getName(), - (string) $scope->getPropertyPath(), - ], - $labelFormat - ); - } else { - $label = $scope->getConfig()->getOption('label'); - } - - if (false !== $label) { - if (null === $label && null !== $this->formRenderer) { - $label = $this->formRenderer->humanize($scope->getName()); - } elseif (null === $label) { - $label = $scope->getName(); - } - - if (null !== $this->translator) { - $form = $scope; - $translationParameters[] = $form->getConfig()->getOption('label_translation_parameters', []); - - do { - $translationDomain = $form->getConfig()->getOption('translation_domain'); - array_unshift( - $translationParameters, - $form->getConfig()->getOption('label_translation_parameters', []) - ); - } while (null === $translationDomain && null !== $form = $form->getParent()); - - $translationParameters = array_merge([], ...$translationParameters); - - $label = $this->translator->trans( - $label, - $translationParameters, - $translationDomain - ); - } - - $message = str_replace('{{ label }}', $label, $message); - $messageTemplate = str_replace('{{ label }}', $label, $messageTemplate); - } - } - - $scope->addError(new FormError( - $message, - $messageTemplate, - $violation->getParameters(), - $violation->getPlural(), - $violation - )); - } - } - - /** - * Tries to match the beginning of the property path at the - * current position against the children of the scope. - * - * If a matching child is found, it is returned. Otherwise - * null is returned. - */ - private function matchChild(FormInterface $form, PropertyPathIteratorInterface $it): ?FormInterface - { - $target = null; - $chunk = ''; - $foundAtIndex = null; - - // Construct mapping rules for the given form - $rules = []; - - foreach ($form->getConfig()->getOption('error_mapping') as $propertyPath => $targetPath) { - // Dot rules are considered at the very end - if ('.' !== $propertyPath) { - $rules[] = new MappingRule($form, $propertyPath, $targetPath); - } - } - - $children = iterator_to_array(new \RecursiveIteratorIterator(new InheritDataAwareIterator($form)), false); - - while ($it->valid()) { - if ($it->isIndex()) { - $chunk .= '['.$it->current().']'; - } else { - $chunk .= ('' === $chunk ? '' : '.').$it->current(); - } - - // Test mapping rules as long as we have any - foreach ($rules as $key => $rule) { - /* @var MappingRule $rule */ - - // Mapping rule matches completely, terminate. - if (null !== ($form = $rule->match($chunk))) { - return $form; - } - - // Keep only rules that have $chunk as prefix - if (!$rule->isPrefix($chunk)) { - unset($rules[$key]); - } - } - - /** @var FormInterface $child */ - foreach ($children as $i => $child) { - $childPath = (string) $child->getPropertyPath(); - if ($childPath === $chunk) { - $target = $child; - $foundAtIndex = $it->key(); - } elseif (str_starts_with($childPath, $chunk)) { - continue; - } - - unset($children[$i]); - } - - $it->next(); - } - - if (null !== $foundAtIndex) { - $it->seek($foundAtIndex); - } - - return $target; - } - - /** - * Reconstructs a property path from a violation path and a form tree. - */ - private function reconstructPath(ViolationPath $violationPath, FormInterface $origin): ?RelativePath - { - $propertyPathBuilder = new PropertyPathBuilder($violationPath); - $it = $violationPath->getIterator(); - $scope = $origin; - - // Remember the current index in the builder - $i = 0; - - // Expand elements that map to a form (like "children[address]") - for ($it->rewind(); $it->valid() && $it->mapsForm(); $it->next()) { - if (!$scope->has($it->current())) { - // Scope relates to a form that does not exist - // Bail out - break; - } - - // Process child form - $scope = $scope->get($it->current()); - - if ($scope->getConfig()->getInheritData()) { - // Form inherits its parent data - // Cut the piece out of the property path and proceed - $propertyPathBuilder->remove($i); - } else { - /* @var \Symfony\Component\PropertyAccess\PropertyPathInterface $propertyPath */ - $propertyPath = $scope->getPropertyPath(); - - if (null === $propertyPath) { - // Property path of a mapped form is null - // Should not happen, bail out - break; - } - - $propertyPathBuilder->replace($i, 1, $propertyPath); - $i += $propertyPath->getLength(); - } - } - - $finalPath = $propertyPathBuilder->getPropertyPath(); - - return null !== $finalPath ? new RelativePath($origin, $finalPath) : null; - } - - private function acceptsErrors(FormInterface $form): bool - { - return $this->allowNonSynchronized || $form->isSynchronized(); - } -} diff --git a/lib/symfony/form/Extension/Validator/ViolationMapper/ViolationMapperInterface.php b/lib/symfony/form/Extension/Validator/ViolationMapper/ViolationMapperInterface.php deleted file mode 100644 index 57ed1c84c..000000000 --- a/lib/symfony/form/Extension/Validator/ViolationMapper/ViolationMapperInterface.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; - -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Validator\ConstraintViolation; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface ViolationMapperInterface -{ - /** - * Maps a constraint violation to a form in the form tree under - * the given form. - * - * @param bool $allowNonSynchronized Whether to allow mapping to non-synchronized forms - */ - public function mapViolation(ConstraintViolation $violation, FormInterface $form, bool $allowNonSynchronized = false); -} diff --git a/lib/symfony/form/Extension/Validator/ViolationMapper/ViolationPath.php b/lib/symfony/form/Extension/Validator/ViolationMapper/ViolationPath.php deleted file mode 100644 index 625c0b99f..000000000 --- a/lib/symfony/form/Extension/Validator/ViolationMapper/ViolationPath.php +++ /dev/null @@ -1,256 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; - -use Symfony\Component\Form\Exception\OutOfBoundsException; -use Symfony\Component\PropertyAccess\PropertyPath; -use Symfony\Component\PropertyAccess\PropertyPathInterface; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @implements \IteratorAggregate<int, string> - */ -class ViolationPath implements \IteratorAggregate, PropertyPathInterface -{ - /** - * @var list<string> - */ - private $elements = []; - - /** - * @var array - */ - private $isIndex = []; - - /** - * @var array - */ - private $mapsForm = []; - - /** - * @var string - */ - private $pathAsString = ''; - - /** - * @var int - */ - private $length = 0; - - /** - * Creates a new violation path from a string. - * - * @param string $violationPath The property path of a {@link \Symfony\Component\Validator\ConstraintViolation} object - */ - public function __construct(string $violationPath) - { - $path = new PropertyPath($violationPath); - $elements = $path->getElements(); - $data = false; - - for ($i = 0, $l = \count($elements); $i < $l; ++$i) { - if (!$data) { - // The element "data" has not yet been passed - if ('children' === $elements[$i] && $path->isProperty($i)) { - // Skip element "children" - ++$i; - - // Next element must exist and must be an index - // Otherwise consider this the end of the path - if ($i >= $l || !$path->isIndex($i)) { - break; - } - - // All the following index items (regardless if .children is - // explicitly used) are children and grand-children - for (; $i < $l && $path->isIndex($i); ++$i) { - $this->elements[] = $elements[$i]; - $this->isIndex[] = true; - $this->mapsForm[] = true; - } - - // Rewind the pointer as the last element above didn't match - // (even if the pointer was moved forward) - --$i; - } elseif ('data' === $elements[$i] && $path->isProperty($i)) { - // Skip element "data" - ++$i; - - // End of path - if ($i >= $l) { - break; - } - - $this->elements[] = $elements[$i]; - $this->isIndex[] = $path->isIndex($i); - $this->mapsForm[] = false; - $data = true; - } else { - // Neither "children" nor "data" property found - // Consider this the end of the path - break; - } - } else { - // Already after the "data" element - // Pick everything as is - $this->elements[] = $elements[$i]; - $this->isIndex[] = $path->isIndex($i); - $this->mapsForm[] = false; - } - } - - $this->length = \count($this->elements); - - $this->buildString(); - } - - /** - * {@inheritdoc} - */ - public function __toString() - { - return $this->pathAsString; - } - - /** - * {@inheritdoc} - */ - public function getLength() - { - return $this->length; - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - if ($this->length <= 1) { - return null; - } - - $parent = clone $this; - - --$parent->length; - array_pop($parent->elements); - array_pop($parent->isIndex); - array_pop($parent->mapsForm); - - $parent->buildString(); - - return $parent; - } - - /** - * {@inheritdoc} - */ - public function getElements() - { - return $this->elements; - } - - /** - * {@inheritdoc} - */ - public function getElement(int $index) - { - if (!isset($this->elements[$index])) { - throw new OutOfBoundsException(sprintf('The index "%s" is not within the violation path.', $index)); - } - - return $this->elements[$index]; - } - - /** - * {@inheritdoc} - */ - public function isProperty(int $index) - { - if (!isset($this->isIndex[$index])) { - throw new OutOfBoundsException(sprintf('The index "%s" is not within the violation path.', $index)); - } - - return !$this->isIndex[$index]; - } - - /** - * {@inheritdoc} - */ - public function isIndex(int $index) - { - if (!isset($this->isIndex[$index])) { - throw new OutOfBoundsException(sprintf('The index "%s" is not within the violation path.', $index)); - } - - return $this->isIndex[$index]; - } - - /** - * Returns whether an element maps directly to a form. - * - * Consider the following violation path: - * - * children[address].children[office].data.street - * - * In this example, "address" and "office" map to forms, while - * "street does not. - * - * @return bool - * - * @throws OutOfBoundsException if the offset is invalid - */ - public function mapsForm(int $index) - { - if (!isset($this->mapsForm[$index])) { - throw new OutOfBoundsException(sprintf('The index "%s" is not within the violation path.', $index)); - } - - return $this->mapsForm[$index]; - } - - /** - * Returns a new iterator for this path. - * - * @return ViolationPathIterator - */ - #[\ReturnTypeWillChange] - public function getIterator() - { - return new ViolationPathIterator($this); - } - - /** - * Builds the string representation from the elements. - */ - private function buildString() - { - $this->pathAsString = ''; - $data = false; - - foreach ($this->elements as $index => $element) { - if ($this->mapsForm[$index]) { - $this->pathAsString .= ".children[$element]"; - } elseif (!$data) { - $this->pathAsString .= '.data'.($this->isIndex[$index] ? "[$element]" : ".$element"); - $data = true; - } else { - $this->pathAsString .= $this->isIndex[$index] ? "[$element]" : ".$element"; - } - } - - if ('' !== $this->pathAsString) { - // remove leading dot - $this->pathAsString = substr($this->pathAsString, 1); - } - } -} diff --git a/lib/symfony/form/Extension/Validator/ViolationMapper/ViolationPathIterator.php b/lib/symfony/form/Extension/Validator/ViolationMapper/ViolationPathIterator.php deleted file mode 100644 index 50baa4533..000000000 --- a/lib/symfony/form/Extension/Validator/ViolationMapper/ViolationPathIterator.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; - -use Symfony\Component\PropertyAccess\PropertyPathIterator; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class ViolationPathIterator extends PropertyPathIterator -{ - public function __construct(ViolationPath $violationPath) - { - parent::__construct($violationPath); - } - - public function mapsForm() - { - return $this->path->mapsForm($this->key()); - } -} diff --git a/lib/symfony/form/FileUploadError.php b/lib/symfony/form/FileUploadError.php deleted file mode 100644 index 20142b203..000000000 --- a/lib/symfony/form/FileUploadError.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -/** - * @internal - */ -class FileUploadError extends FormError -{ -} diff --git a/lib/symfony/form/Form.php b/lib/symfony/form/Form.php deleted file mode 100644 index 0c36032f1..000000000 --- a/lib/symfony/form/Form.php +++ /dev/null @@ -1,1194 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\Form\Event\PostSetDataEvent; -use Symfony\Component\Form\Event\PostSubmitEvent; -use Symfony\Component\Form\Event\PreSetDataEvent; -use Symfony\Component\Form\Event\PreSubmitEvent; -use Symfony\Component\Form\Event\SubmitEvent; -use Symfony\Component\Form\Exception\AlreadySubmittedException; -use Symfony\Component\Form\Exception\LogicException; -use Symfony\Component\Form\Exception\OutOfBoundsException; -use Symfony\Component\Form\Exception\RuntimeException; -use Symfony\Component\Form\Exception\TransformationFailedException; -use Symfony\Component\Form\Exception\UnexpectedTypeException; -use Symfony\Component\Form\Extension\Core\Type\TextType; -use Symfony\Component\Form\Util\FormUtil; -use Symfony\Component\Form\Util\InheritDataAwareIterator; -use Symfony\Component\Form\Util\OrderedHashMap; -use Symfony\Component\PropertyAccess\PropertyPath; -use Symfony\Component\PropertyAccess\PropertyPathInterface; - -/** - * Form represents a form. - * - * To implement your own form fields, you need to have a thorough understanding - * of the data flow within a form. A form stores its data in three different - * representations: - * - * (1) the "model" format required by the form's object - * (2) the "normalized" format for internal processing - * (3) the "view" format used for display simple fields - * or map children model data for compound fields - * - * A date field, for example, may store a date as "Y-m-d" string (1) in the - * object. To facilitate processing in the field, this value is normalized - * to a DateTime object (2). In the HTML representation of your form, a - * localized string (3) may be presented to and modified by the user, or it could be an array of values - * to be mapped to choices fields. - * - * In most cases, format (1) and format (2) will be the same. For example, - * a checkbox field uses a Boolean value for both internal processing and - * storage in the object. In these cases you need to set a view transformer - * to convert between formats (2) and (3). You can do this by calling - * addViewTransformer(). - * - * In some cases though it makes sense to make format (1) configurable. To - * demonstrate this, let's extend our above date field to store the value - * either as "Y-m-d" string or as timestamp. Internally we still want to - * use a DateTime object for processing. To convert the data from string/integer - * to DateTime you can set a model transformer by calling - * addModelTransformer(). The normalized data is then converted to the displayed - * data as described before. - * - * The conversions (1) -> (2) -> (3) use the transform methods of the transformers. - * The conversions (3) -> (2) -> (1) use the reverseTransform methods of the transformers. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @implements \IteratorAggregate<string, FormInterface> - */ -class Form implements \IteratorAggregate, FormInterface, ClearableErrorsInterface -{ - /** - * @var FormConfigInterface - */ - private $config; - - /** - * @var FormInterface|null - */ - private $parent; - - /** - * A map of FormInterface instances. - * - * @var OrderedHashMap<string, FormInterface> - */ - private $children; - - /** - * @var FormError[] - */ - private $errors = []; - - /** - * @var bool - */ - private $submitted = false; - - /** - * The button that was used to submit the form. - * - * @var FormInterface|ClickableInterface|null - */ - private $clickedButton; - - /** - * @var mixed - */ - private $modelData; - - /** - * @var mixed - */ - private $normData; - - /** - * @var mixed - */ - private $viewData; - - /** - * The submitted values that don't belong to any children. - * - * @var array - */ - private $extraData = []; - - /** - * The transformation failure generated during submission, if any. - * - * @var TransformationFailedException|null - */ - private $transformationFailure; - - /** - * Whether the form's data has been initialized. - * - * When the data is initialized with its default value, that default value - * is passed through the transformer chain in order to synchronize the - * model, normalized and view format for the first time. This is done - * lazily in order to save performance when {@link setData()} is called - * manually, making the initialization with the configured default value - * superfluous. - * - * @var bool - */ - private $defaultDataSet = false; - - /** - * Whether setData() is currently being called. - * - * @var bool - */ - private $lockSetData = false; - - /** - * @var string - */ - private $name = ''; - - /** - * Whether the form inherits its underlying data from its parent. - * - * @var bool - */ - private $inheritData; - - /** - * @var PropertyPathInterface|null - */ - private $propertyPath; - - /** - * @throws LogicException if a data mapper is not provided for a compound form - */ - public function __construct(FormConfigInterface $config) - { - // Compound forms always need a data mapper, otherwise calls to - // `setData` and `add` will not lead to the correct population of - // the child forms. - if ($config->getCompound() && !$config->getDataMapper()) { - throw new LogicException('Compound forms need a data mapper.'); - } - - // If the form inherits the data from its parent, it is not necessary - // to call setData() with the default data. - if ($this->inheritData = $config->getInheritData()) { - $this->defaultDataSet = true; - } - - $this->config = $config; - $this->children = new OrderedHashMap(); - $this->name = $config->getName(); - } - - public function __clone() - { - $this->children = clone $this->children; - - foreach ($this->children as $key => $child) { - $this->children[$key] = clone $child; - } - } - - /** - * {@inheritdoc} - */ - public function getConfig() - { - return $this->config; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->name; - } - - /** - * {@inheritdoc} - */ - public function getPropertyPath() - { - if ($this->propertyPath || $this->propertyPath = $this->config->getPropertyPath()) { - return $this->propertyPath; - } - - if ('' === $this->name) { - return null; - } - - $parent = $this->parent; - - while ($parent && $parent->getConfig()->getInheritData()) { - $parent = $parent->getParent(); - } - - if ($parent && null === $parent->getConfig()->getDataClass()) { - $this->propertyPath = new PropertyPath('['.$this->name.']'); - } else { - $this->propertyPath = new PropertyPath($this->name); - } - - return $this->propertyPath; - } - - /** - * {@inheritdoc} - */ - public function isRequired() - { - if (null === $this->parent || $this->parent->isRequired()) { - return $this->config->getRequired(); - } - - return false; - } - - /** - * {@inheritdoc} - */ - public function isDisabled() - { - if (null === $this->parent || !$this->parent->isDisabled()) { - return $this->config->getDisabled(); - } - - return true; - } - - /** - * {@inheritdoc} - */ - public function setParent(FormInterface $parent = null) - { - if ($this->submitted) { - throw new AlreadySubmittedException('You cannot set the parent of a submitted form.'); - } - - if (null !== $parent && '' === $this->name) { - throw new LogicException('A form with an empty name cannot have a parent form.'); - } - - $this->parent = $parent; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - return $this->parent; - } - - /** - * {@inheritdoc} - */ - public function getRoot() - { - return $this->parent ? $this->parent->getRoot() : $this; - } - - /** - * {@inheritdoc} - */ - public function isRoot() - { - return null === $this->parent; - } - - /** - * {@inheritdoc} - */ - public function setData($modelData) - { - // If the form is submitted while disabled, it is set to submitted, but the data is not - // changed. In such cases (i.e. when the form is not initialized yet) don't - // abort this method. - if ($this->submitted && $this->defaultDataSet) { - throw new AlreadySubmittedException('You cannot change the data of a submitted form.'); - } - - // If the form inherits its parent's data, disallow data setting to - // prevent merge conflicts - if ($this->inheritData) { - throw new RuntimeException('You cannot change the data of a form inheriting its parent data.'); - } - - // Don't allow modifications of the configured data if the data is locked - if ($this->config->getDataLocked() && $modelData !== $this->config->getData()) { - return $this; - } - - if (\is_object($modelData) && !$this->config->getByReference()) { - $modelData = clone $modelData; - } - - if ($this->lockSetData) { - throw new RuntimeException('A cycle was detected. Listeners to the PRE_SET_DATA event must not call setData(). You should call setData() on the FormEvent object instead.'); - } - - $this->lockSetData = true; - $dispatcher = $this->config->getEventDispatcher(); - - // Hook to change content of the model data before transformation and mapping children - if ($dispatcher->hasListeners(FormEvents::PRE_SET_DATA)) { - $event = new PreSetDataEvent($this, $modelData); - $dispatcher->dispatch($event, FormEvents::PRE_SET_DATA); - $modelData = $event->getData(); - } - - // Treat data as strings unless a transformer exists - if (\is_scalar($modelData) && !$this->config->getViewTransformers() && !$this->config->getModelTransformers()) { - $modelData = (string) $modelData; - } - - // Synchronize representations - must not change the content! - // Transformation exceptions are not caught on initialization - $normData = $this->modelToNorm($modelData); - $viewData = $this->normToView($normData); - - // Validate if view data matches data class (unless empty) - if (!FormUtil::isEmpty($viewData)) { - $dataClass = $this->config->getDataClass(); - - if (null !== $dataClass && !$viewData instanceof $dataClass) { - $actualType = get_debug_type($viewData); - - throw new LogicException('The form\'s view data is expected to be a "'.$dataClass.'", but it is a "'.$actualType.'". You can avoid this error by setting the "data_class" option to null or by adding a view transformer that transforms "'.$actualType.'" to an instance of "'.$dataClass.'".'); - } - } - - $this->modelData = $modelData; - $this->normData = $normData; - $this->viewData = $viewData; - $this->defaultDataSet = true; - $this->lockSetData = false; - - // Compound forms don't need to invoke this method if they don't have children - if (\count($this->children) > 0) { - // Update child forms from the data (unless their config data is locked) - $this->config->getDataMapper()->mapDataToForms($viewData, new \RecursiveIteratorIterator(new InheritDataAwareIterator($this->children))); - } - - if ($dispatcher->hasListeners(FormEvents::POST_SET_DATA)) { - $event = new PostSetDataEvent($this, $modelData); - $dispatcher->dispatch($event, FormEvents::POST_SET_DATA); - } - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getData() - { - if ($this->inheritData) { - if (!$this->parent) { - throw new RuntimeException('The form is configured to inherit its parent\'s data, but does not have a parent.'); - } - - return $this->parent->getData(); - } - - if (!$this->defaultDataSet) { - if ($this->lockSetData) { - throw new RuntimeException('A cycle was detected. Listeners to the PRE_SET_DATA event must not call getData() if the form data has not already been set. You should call getData() on the FormEvent object instead.'); - } - - $this->setData($this->config->getData()); - } - - return $this->modelData; - } - - /** - * {@inheritdoc} - */ - public function getNormData() - { - if ($this->inheritData) { - if (!$this->parent) { - throw new RuntimeException('The form is configured to inherit its parent\'s data, but does not have a parent.'); - } - - return $this->parent->getNormData(); - } - - if (!$this->defaultDataSet) { - if ($this->lockSetData) { - throw new RuntimeException('A cycle was detected. Listeners to the PRE_SET_DATA event must not call getNormData() if the form data has not already been set.'); - } - - $this->setData($this->config->getData()); - } - - return $this->normData; - } - - /** - * {@inheritdoc} - */ - public function getViewData() - { - if ($this->inheritData) { - if (!$this->parent) { - throw new RuntimeException('The form is configured to inherit its parent\'s data, but does not have a parent.'); - } - - return $this->parent->getViewData(); - } - - if (!$this->defaultDataSet) { - if ($this->lockSetData) { - throw new RuntimeException('A cycle was detected. Listeners to the PRE_SET_DATA event must not call getViewData() if the form data has not already been set.'); - } - - $this->setData($this->config->getData()); - } - - return $this->viewData; - } - - /** - * {@inheritdoc} - */ - public function getExtraData() - { - return $this->extraData; - } - - /** - * {@inheritdoc} - */ - public function initialize() - { - if (null !== $this->parent) { - throw new RuntimeException('Only root forms should be initialized.'); - } - - // Guarantee that the *_SET_DATA events have been triggered once the - // form is initialized. This makes sure that dynamically added or - // removed fields are already visible after initialization. - if (!$this->defaultDataSet) { - $this->setData($this->config->getData()); - } - - return $this; - } - - /** - * {@inheritdoc} - */ - public function handleRequest($request = null) - { - $this->config->getRequestHandler()->handleRequest($this, $request); - - return $this; - } - - /** - * {@inheritdoc} - */ - public function submit($submittedData, bool $clearMissing = true) - { - if ($this->submitted) { - throw new AlreadySubmittedException('A form can only be submitted once.'); - } - - // Initialize errors in the very beginning so we're sure - // they are collectable during submission only - $this->errors = []; - - // Obviously, a disabled form should not change its data upon submission. - if ($this->isDisabled()) { - $this->submitted = true; - - return $this; - } - - // The data must be initialized if it was not initialized yet. - // This is necessary to guarantee that the *_SET_DATA listeners - // are always invoked before submit() takes place. - if (!$this->defaultDataSet) { - $this->setData($this->config->getData()); - } - - // Treat false as NULL to support binding false to checkboxes. - // Don't convert NULL to a string here in order to determine later - // whether an empty value has been submitted or whether no value has - // been submitted at all. This is important for processing checkboxes - // and radio buttons with empty values. - if (false === $submittedData) { - $submittedData = null; - } elseif (\is_scalar($submittedData)) { - $submittedData = (string) $submittedData; - } elseif ($this->config->getRequestHandler()->isFileUpload($submittedData)) { - if (!$this->config->getOption('allow_file_upload')) { - $submittedData = null; - $this->transformationFailure = new TransformationFailedException('Submitted data was expected to be text or number, file upload given.'); - } - } elseif (\is_array($submittedData) && !$this->config->getCompound() && !$this->config->getOption('multiple', false)) { - $submittedData = null; - $this->transformationFailure = new TransformationFailedException('Submitted data was expected to be text or number, array given.'); - } - - $dispatcher = $this->config->getEventDispatcher(); - - $modelData = null; - $normData = null; - $viewData = null; - - try { - if (null !== $this->transformationFailure) { - throw $this->transformationFailure; - } - - // Hook to change content of the data submitted by the browser - if ($dispatcher->hasListeners(FormEvents::PRE_SUBMIT)) { - $event = new PreSubmitEvent($this, $submittedData); - $dispatcher->dispatch($event, FormEvents::PRE_SUBMIT); - $submittedData = $event->getData(); - } - - // Check whether the form is compound. - // This check is preferable over checking the number of children, - // since forms without children may also be compound. - // (think of empty collection forms) - if ($this->config->getCompound()) { - if (null === $submittedData) { - $submittedData = []; - } - - if (!\is_array($submittedData)) { - throw new TransformationFailedException('Compound forms expect an array or NULL on submission.'); - } - - foreach ($this->children as $name => $child) { - $isSubmitted = \array_key_exists($name, $submittedData); - - if ($isSubmitted || $clearMissing) { - $child->submit($isSubmitted ? $submittedData[$name] : null, $clearMissing); - unset($submittedData[$name]); - - if (null !== $this->clickedButton) { - continue; - } - - if ($child instanceof ClickableInterface && $child->isClicked()) { - $this->clickedButton = $child; - - continue; - } - - if (method_exists($child, 'getClickedButton') && null !== $child->getClickedButton()) { - $this->clickedButton = $child->getClickedButton(); - } - } - } - - $this->extraData = $submittedData; - } - - // Forms that inherit their parents' data also are not processed, - // because then it would be too difficult to merge the changes in - // the child and the parent form. Instead, the parent form also takes - // changes in the grandchildren (i.e. children of the form that inherits - // its parent's data) into account. - // (see InheritDataAwareIterator below) - if (!$this->inheritData) { - // If the form is compound, the view data is merged with the data - // of the children using the data mapper. - // If the form is not compound, the view data is assigned to the submitted data. - $viewData = $this->config->getCompound() ? $this->viewData : $submittedData; - - if (FormUtil::isEmpty($viewData)) { - $emptyData = $this->config->getEmptyData(); - - if ($emptyData instanceof \Closure) { - $emptyData = $emptyData($this, $viewData); - } - - $viewData = $emptyData; - } - - // Merge form data from children into existing view data - // It is not necessary to invoke this method if the form has no children, - // even if it is compound. - if (\count($this->children) > 0) { - // Use InheritDataAwareIterator to process children of - // descendants that inherit this form's data. - // These descendants will not be submitted normally (see the check - // for $this->config->getInheritData() above) - $this->config->getDataMapper()->mapFormsToData( - new \RecursiveIteratorIterator(new InheritDataAwareIterator($this->children)), - $viewData - ); - } - - // Normalize data to unified representation - $normData = $this->viewToNorm($viewData); - - // Hook to change content of the data in the normalized - // representation - if ($dispatcher->hasListeners(FormEvents::SUBMIT)) { - $event = new SubmitEvent($this, $normData); - $dispatcher->dispatch($event, FormEvents::SUBMIT); - $normData = $event->getData(); - } - - // Synchronize representations - must not change the content! - $modelData = $this->normToModel($normData); - $viewData = $this->normToView($normData); - } - } catch (TransformationFailedException $e) { - $this->transformationFailure = $e; - - // If $viewData was not yet set, set it to $submittedData so that - // the erroneous data is accessible on the form. - // Forms that inherit data never set any data, because the getters - // forward to the parent form's getters anyway. - if (null === $viewData && !$this->inheritData) { - $viewData = $submittedData; - } - } - - $this->submitted = true; - $this->modelData = $modelData; - $this->normData = $normData; - $this->viewData = $viewData; - - if ($dispatcher->hasListeners(FormEvents::POST_SUBMIT)) { - $event = new PostSubmitEvent($this, $viewData); - $dispatcher->dispatch($event, FormEvents::POST_SUBMIT); - } - - return $this; - } - - /** - * {@inheritdoc} - */ - public function addError(FormError $error) - { - if (null === $error->getOrigin()) { - $error->setOrigin($this); - } - - if ($this->parent && $this->config->getErrorBubbling()) { - $this->parent->addError($error); - } else { - $this->errors[] = $error; - } - - return $this; - } - - /** - * {@inheritdoc} - */ - public function isSubmitted() - { - return $this->submitted; - } - - /** - * {@inheritdoc} - */ - public function isSynchronized() - { - return null === $this->transformationFailure; - } - - /** - * {@inheritdoc} - */ - public function getTransformationFailure() - { - return $this->transformationFailure; - } - - /** - * {@inheritdoc} - */ - public function isEmpty() - { - foreach ($this->children as $child) { - if (!$child->isEmpty()) { - return false; - } - } - - if (!method_exists($this->config, 'getIsEmptyCallback')) { - trigger_deprecation('symfony/form', '5.1', 'Not implementing the "%s::getIsEmptyCallback()" method in "%s" is deprecated.', FormConfigInterface::class, \get_class($this->config)); - - $isEmptyCallback = null; - } else { - $isEmptyCallback = $this->config->getIsEmptyCallback(); - } - - if (null !== $isEmptyCallback) { - return $isEmptyCallback($this->modelData); - } - - return FormUtil::isEmpty($this->modelData) || - // arrays, countables - ((\is_array($this->modelData) || $this->modelData instanceof \Countable) && 0 === \count($this->modelData)) || - // traversables that are not countable - ($this->modelData instanceof \Traversable && 0 === iterator_count($this->modelData)); - } - - /** - * {@inheritdoc} - */ - public function isValid() - { - if (!$this->submitted) { - throw new LogicException('Cannot check if an unsubmitted form is valid. Call Form::isSubmitted() before Form::isValid().'); - } - - if ($this->isDisabled()) { - return true; - } - - return 0 === \count($this->getErrors(true)); - } - - /** - * Returns the button that was used to submit the form. - * - * @return FormInterface|ClickableInterface|null - */ - public function getClickedButton() - { - if ($this->clickedButton) { - return $this->clickedButton; - } - - return $this->parent && method_exists($this->parent, 'getClickedButton') ? $this->parent->getClickedButton() : null; - } - - /** - * {@inheritdoc} - */ - public function getErrors(bool $deep = false, bool $flatten = true) - { - $errors = $this->errors; - - // Copy the errors of nested forms to the $errors array - if ($deep) { - foreach ($this as $child) { - /** @var FormInterface $child */ - if ($child->isSubmitted() && $child->isValid()) { - continue; - } - - $iterator = $child->getErrors(true, $flatten); - - if (0 === \count($iterator)) { - continue; - } - - if ($flatten) { - foreach ($iterator as $error) { - $errors[] = $error; - } - } else { - $errors[] = $iterator; - } - } - } - - return new FormErrorIterator($this, $errors); - } - - /** - * {@inheritdoc} - */ - public function clearErrors(bool $deep = false): self - { - $this->errors = []; - - if ($deep) { - // Clear errors from children - foreach ($this as $child) { - if ($child instanceof ClearableErrorsInterface) { - $child->clearErrors(true); - } - } - } - - return $this; - } - - /** - * {@inheritdoc} - */ - public function all() - { - return iterator_to_array($this->children); - } - - /** - * {@inheritdoc} - */ - public function add($child, string $type = null, array $options = []) - { - if ($this->submitted) { - throw new AlreadySubmittedException('You cannot add children to a submitted form.'); - } - - if (!$this->config->getCompound()) { - throw new LogicException('You cannot add children to a simple form. Maybe you should set the option "compound" to true?'); - } - - if (!$child instanceof FormInterface) { - if (!\is_string($child) && !\is_int($child)) { - throw new UnexpectedTypeException($child, 'string or Symfony\Component\Form\FormInterface'); - } - - $child = (string) $child; - - if (null !== $type && !\is_string($type)) { - throw new UnexpectedTypeException($type, 'string or null'); - } - - // Never initialize child forms automatically - $options['auto_initialize'] = false; - - if (null === $type && null === $this->config->getDataClass()) { - $type = TextType::class; - } - - if (null === $type) { - $child = $this->config->getFormFactory()->createForProperty($this->config->getDataClass(), $child, null, $options); - } else { - $child = $this->config->getFormFactory()->createNamed($child, $type, null, $options); - } - } elseif ($child->getConfig()->getAutoInitialize()) { - throw new RuntimeException(sprintf('Automatic initialization is only supported on root forms. You should set the "auto_initialize" option to false on the field "%s".', $child->getName())); - } - - $this->children[$child->getName()] = $child; - - $child->setParent($this); - - // If setData() is currently being called, there is no need to call - // mapDataToForms() here, as mapDataToForms() is called at the end - // of setData() anyway. Not doing this check leads to an endless - // recursion when initializing the form lazily and an event listener - // (such as ResizeFormListener) adds fields depending on the data: - // - // * setData() is called, the form is not initialized yet - // * add() is called by the listener (setData() is not complete, so - // the form is still not initialized) - // * getViewData() is called - // * setData() is called since the form is not initialized yet - // * ... endless recursion ... - // - // Also skip data mapping if setData() has not been called yet. - // setData() will be called upon form initialization and data mapping - // will take place by then. - if (!$this->lockSetData && $this->defaultDataSet && !$this->inheritData) { - $viewData = $this->getViewData(); - $this->config->getDataMapper()->mapDataToForms( - $viewData, - new \RecursiveIteratorIterator(new InheritDataAwareIterator(new \ArrayIterator([$child->getName() => $child]))) - ); - } - - return $this; - } - - /** - * {@inheritdoc} - */ - public function remove(string $name) - { - if ($this->submitted) { - throw new AlreadySubmittedException('You cannot remove children from a submitted form.'); - } - - if (isset($this->children[$name])) { - if (!$this->children[$name]->isSubmitted()) { - $this->children[$name]->setParent(null); - } - - unset($this->children[$name]); - } - - return $this; - } - - /** - * {@inheritdoc} - */ - public function has(string $name) - { - return isset($this->children[$name]); - } - - /** - * {@inheritdoc} - */ - public function get(string $name) - { - if (isset($this->children[$name])) { - return $this->children[$name]; - } - - throw new OutOfBoundsException(sprintf('Child "%s" does not exist.', $name)); - } - - /** - * Returns whether a child with the given name exists (implements the \ArrayAccess interface). - * - * @param string $name The name of the child - * - * @return bool - */ - #[\ReturnTypeWillChange] - public function offsetExists($name) - { - return $this->has($name); - } - - /** - * Returns the child with the given name (implements the \ArrayAccess interface). - * - * @param string $name The name of the child - * - * @return FormInterface - * - * @throws OutOfBoundsException if the named child does not exist - */ - #[\ReturnTypeWillChange] - public function offsetGet($name) - { - return $this->get($name); - } - - /** - * Adds a child to the form (implements the \ArrayAccess interface). - * - * @param string $name Ignored. The name of the child is used - * @param FormInterface $child The child to be added - * - * @return void - * - * @throws AlreadySubmittedException if the form has already been submitted - * @throws LogicException when trying to add a child to a non-compound form - * - * @see self::add() - */ - #[\ReturnTypeWillChange] - public function offsetSet($name, $child) - { - $this->add($child); - } - - /** - * Removes the child with the given name from the form (implements the \ArrayAccess interface). - * - * @param string $name The name of the child to remove - * - * @return void - * - * @throws AlreadySubmittedException if the form has already been submitted - */ - #[\ReturnTypeWillChange] - public function offsetUnset($name) - { - $this->remove($name); - } - - /** - * Returns the iterator for this group. - * - * @return \Traversable<string, FormInterface> - */ - #[\ReturnTypeWillChange] - public function getIterator() - { - return $this->children; - } - - /** - * Returns the number of form children (implements the \Countable interface). - * - * @return int - */ - #[\ReturnTypeWillChange] - public function count() - { - return \count($this->children); - } - - /** - * {@inheritdoc} - */ - public function createView(FormView $parent = null) - { - if (null === $parent && $this->parent) { - $parent = $this->parent->createView(); - } - - $type = $this->config->getType(); - $options = $this->config->getOptions(); - - // The methods createView(), buildView() and finishView() are called - // explicitly here in order to be able to override either of them - // in a custom resolved form type. - $view = $type->createView($this, $parent); - - $type->buildView($view, $this, $options); - - foreach ($this->children as $name => $child) { - $view->children[$name] = $child->createView($view); - } - - $this->sort($view->children); - - $type->finishView($view, $this, $options); - - return $view; - } - - /** - * Sorts view fields based on their priority value. - */ - private function sort(array &$children): void - { - $c = []; - $i = 0; - $needsSorting = false; - foreach ($children as $name => $child) { - $c[$name] = ['p' => $child->vars['priority'] ?? 0, 'i' => $i++]; - - if (0 !== $c[$name]['p']) { - $needsSorting = true; - } - } - - if (!$needsSorting) { - return; - } - - uksort($children, static function ($a, $b) use ($c): int { - return [$c[$b]['p'], $c[$a]['i']] <=> [$c[$a]['p'], $c[$b]['i']]; - }); - } - - /** - * Normalizes the underlying data if a model transformer is set. - * - * @return mixed - * - * @throws TransformationFailedException If the underlying data cannot be transformed to "normalized" format - */ - private function modelToNorm($value) - { - try { - foreach ($this->config->getModelTransformers() as $transformer) { - $value = $transformer->transform($value); - } - } catch (TransformationFailedException $exception) { - throw new TransformationFailedException(sprintf('Unable to transform data for property path "%s": ', $this->getPropertyPath()).$exception->getMessage(), $exception->getCode(), $exception, $exception->getInvalidMessage(), $exception->getInvalidMessageParameters()); - } - - return $value; - } - - /** - * Reverse transforms a value if a model transformer is set. - * - * @return mixed - * - * @throws TransformationFailedException If the value cannot be transformed to "model" format - */ - private function normToModel($value) - { - try { - $transformers = $this->config->getModelTransformers(); - - for ($i = \count($transformers) - 1; $i >= 0; --$i) { - $value = $transformers[$i]->reverseTransform($value); - } - } catch (TransformationFailedException $exception) { - throw new TransformationFailedException(sprintf('Unable to reverse value for property path "%s": ', $this->getPropertyPath()).$exception->getMessage(), $exception->getCode(), $exception, $exception->getInvalidMessage(), $exception->getInvalidMessageParameters()); - } - - return $value; - } - - /** - * Transforms the value if a view transformer is set. - * - * @return mixed - * - * @throws TransformationFailedException If the normalized value cannot be transformed to "view" format - */ - private function normToView($value) - { - // Scalar values should be converted to strings to - // facilitate differentiation between empty ("") and zero (0). - // Only do this for simple forms, as the resulting value in - // compound forms is passed to the data mapper and thus should - // not be converted to a string before. - if (!($transformers = $this->config->getViewTransformers()) && !$this->config->getCompound()) { - return null === $value || \is_scalar($value) ? (string) $value : $value; - } - - try { - foreach ($transformers as $transformer) { - $value = $transformer->transform($value); - } - } catch (TransformationFailedException $exception) { - throw new TransformationFailedException(sprintf('Unable to transform value for property path "%s": ', $this->getPropertyPath()).$exception->getMessage(), $exception->getCode(), $exception, $exception->getInvalidMessage(), $exception->getInvalidMessageParameters()); - } - - return $value; - } - - /** - * Reverse transforms a value if a view transformer is set. - * - * @return mixed - * - * @throws TransformationFailedException If the submitted value cannot be transformed to "normalized" format - */ - private function viewToNorm($value) - { - if (!$transformers = $this->config->getViewTransformers()) { - return '' === $value ? null : $value; - } - - try { - for ($i = \count($transformers) - 1; $i >= 0; --$i) { - $value = $transformers[$i]->reverseTransform($value); - } - } catch (TransformationFailedException $exception) { - throw new TransformationFailedException(sprintf('Unable to reverse value for property path "%s": ', $this->getPropertyPath()).$exception->getMessage(), $exception->getCode(), $exception, $exception->getInvalidMessage(), $exception->getInvalidMessageParameters()); - } - - return $value; - } -} diff --git a/lib/symfony/form/FormBuilder.php b/lib/symfony/form/FormBuilder.php deleted file mode 100644 index 37fca950a..000000000 --- a/lib/symfony/form/FormBuilder.php +++ /dev/null @@ -1,254 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\Form\Exception\BadMethodCallException; -use Symfony\Component\Form\Exception\InvalidArgumentException; -use Symfony\Component\Form\Exception\UnexpectedTypeException; -use Symfony\Component\Form\Extension\Core\Type\TextType; - -/** - * A builder for creating {@link Form} instances. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @implements \IteratorAggregate<string, FormBuilderInterface> - */ -class FormBuilder extends FormConfigBuilder implements \IteratorAggregate, FormBuilderInterface -{ - /** - * The children of the form builder. - * - * @var FormBuilderInterface[] - */ - private $children = []; - - /** - * The data of children who haven't been converted to form builders yet. - * - * @var array - */ - private $unresolvedChildren = []; - - public function __construct(?string $name, ?string $dataClass, EventDispatcherInterface $dispatcher, FormFactoryInterface $factory, array $options = []) - { - parent::__construct($name, $dataClass, $dispatcher, $options); - - $this->setFormFactory($factory); - } - - /** - * {@inheritdoc} - */ - public function add($child, string $type = null, array $options = []) - { - if ($this->locked) { - throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - if ($child instanceof FormBuilderInterface) { - $this->children[$child->getName()] = $child; - - // In case an unresolved child with the same name exists - unset($this->unresolvedChildren[$child->getName()]); - - return $this; - } - - if (!\is_string($child) && !\is_int($child)) { - throw new UnexpectedTypeException($child, 'string or Symfony\Component\Form\FormBuilderInterface'); - } - - if (null !== $type && !\is_string($type)) { - throw new UnexpectedTypeException($type, 'string or null'); - } - - // Add to "children" to maintain order - $this->children[$child] = null; - $this->unresolvedChildren[$child] = [$type, $options]; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function create($name, string $type = null, array $options = []) - { - if ($this->locked) { - throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - if (null === $type && null === $this->getDataClass()) { - $type = TextType::class; - } - - if (null !== $type) { - return $this->getFormFactory()->createNamedBuilder($name, $type, null, $options); - } - - return $this->getFormFactory()->createBuilderForProperty($this->getDataClass(), $name, null, $options); - } - - /** - * {@inheritdoc} - */ - public function get($name) - { - if ($this->locked) { - throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - if (isset($this->unresolvedChildren[$name])) { - return $this->resolveChild($name); - } - - if (isset($this->children[$name])) { - return $this->children[$name]; - } - - throw new InvalidArgumentException(sprintf('The child with the name "%s" does not exist.', $name)); - } - - /** - * {@inheritdoc} - */ - public function remove($name) - { - if ($this->locked) { - throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - unset($this->unresolvedChildren[$name], $this->children[$name]); - - return $this; - } - - /** - * {@inheritdoc} - */ - public function has($name) - { - if ($this->locked) { - throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - return isset($this->unresolvedChildren[$name]) || isset($this->children[$name]); - } - - /** - * {@inheritdoc} - */ - public function all() - { - if ($this->locked) { - throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $this->resolveChildren(); - - return $this->children; - } - - /** - * @return int - */ - #[\ReturnTypeWillChange] - public function count() - { - if ($this->locked) { - throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - return \count($this->children); - } - - /** - * {@inheritdoc} - */ - public function getFormConfig() - { - /** @var $config self */ - $config = parent::getFormConfig(); - - $config->children = []; - $config->unresolvedChildren = []; - - return $config; - } - - /** - * {@inheritdoc} - */ - public function getForm() - { - if ($this->locked) { - throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $this->resolveChildren(); - - $form = new Form($this->getFormConfig()); - - foreach ($this->children as $child) { - // Automatic initialization is only supported on root forms - $form->add($child->setAutoInitialize(false)->getForm()); - } - - if ($this->getAutoInitialize()) { - // Automatically initialize the form if it is configured so - $form->initialize(); - } - - return $form; - } - - /** - * {@inheritdoc} - * - * @return \Traversable<string, FormBuilderInterface> - */ - #[\ReturnTypeWillChange] - public function getIterator() - { - if ($this->locked) { - throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - return new \ArrayIterator($this->all()); - } - - /** - * Converts an unresolved child into a {@link FormBuilderInterface} instance. - */ - private function resolveChild(string $name): FormBuilderInterface - { - [$type, $options] = $this->unresolvedChildren[$name]; - - unset($this->unresolvedChildren[$name]); - - return $this->children[$name] = $this->create($name, $type, $options); - } - - /** - * Converts all unresolved children into {@link FormBuilder} instances. - */ - private function resolveChildren() - { - foreach ($this->unresolvedChildren as $name => $info) { - $this->children[$name] = $this->create($name, $info[0], $info[1]); - } - - $this->unresolvedChildren = []; - } -} diff --git a/lib/symfony/form/FormBuilderInterface.php b/lib/symfony/form/FormBuilderInterface.php deleted file mode 100644 index 52bf5b679..000000000 --- a/lib/symfony/form/FormBuilderInterface.php +++ /dev/null @@ -1,82 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @extends \Traversable<string, FormBuilderInterface> - */ -interface FormBuilderInterface extends \Traversable, \Countable, FormConfigBuilderInterface -{ - /** - * Adds a new field to this group. A field must have a unique name within - * the group. Otherwise the existing field is overwritten. - * - * If you add a nested group, this group should also be represented in the - * object hierarchy. - * - * @param string|FormBuilderInterface $child - * @param array<string, mixed> $options - * - * @return static - */ - public function add($child, string $type = null, array $options = []); - - /** - * Creates a form builder. - * - * @param string $name The name of the form or the name of the property - * @param string|null $type The type of the form or null if name is a property - * @param array<string, mixed> $options - * - * @return self - */ - public function create(string $name, string $type = null, array $options = []); - - /** - * Returns a child by name. - * - * @return self - * - * @throws Exception\InvalidArgumentException if the given child does not exist - */ - public function get(string $name); - - /** - * Removes the field with the given name. - * - * @return static - */ - public function remove(string $name); - - /** - * Returns whether a field with the given name exists. - * - * @return bool - */ - public function has(string $name); - - /** - * Returns the children. - * - * @return array<string, self> - */ - public function all(); - - /** - * Creates the form. - * - * @return FormInterface - */ - public function getForm(); -} diff --git a/lib/symfony/form/FormConfigBuilder.php b/lib/symfony/form/FormConfigBuilder.php deleted file mode 100644 index b511c2f13..000000000 --- a/lib/symfony/form/FormConfigBuilder.php +++ /dev/null @@ -1,811 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\EventDispatcher\ImmutableEventDispatcher; -use Symfony\Component\Form\Exception\BadMethodCallException; -use Symfony\Component\Form\Exception\InvalidArgumentException; -use Symfony\Component\PropertyAccess\PropertyPath; -use Symfony\Component\PropertyAccess\PropertyPathInterface; - -/** - * A basic form configuration. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class FormConfigBuilder implements FormConfigBuilderInterface -{ - /** - * Caches a globally unique {@link NativeRequestHandler} instance. - * - * @var NativeRequestHandler - */ - private static $nativeRequestHandler; - - protected $locked = false; - private $dispatcher; - private $name; - - /** - * @var PropertyPathInterface|string|null - */ - private $propertyPath; - - private $mapped = true; - private $byReference = true; - private $inheritData = false; - private $compound = false; - - /** - * @var ResolvedFormTypeInterface - */ - private $type; - - private $viewTransformers = []; - private $modelTransformers = []; - - /** - * @var DataMapperInterface|null - */ - private $dataMapper; - - private $required = true; - private $disabled = false; - private $errorBubbling = false; - - /** - * @var mixed - */ - private $emptyData; - - private $attributes = []; - - /** - * @var mixed - */ - private $data; - - /** - * @var string|null - */ - private $dataClass; - - private $dataLocked = false; - - /** - * @var FormFactoryInterface|null - */ - private $formFactory; - - private $action = ''; - private $method = 'POST'; - - /** - * @var RequestHandlerInterface|null - */ - private $requestHandler; - - private $autoInitialize = false; - private $options; - private $isEmptyCallback; - - /** - * Creates an empty form configuration. - * - * @param string|null $name The form name - * @param string|null $dataClass The class of the form's data - * - * @throws InvalidArgumentException if the data class is not a valid class or if - * the name contains invalid characters - */ - public function __construct(?string $name, ?string $dataClass, EventDispatcherInterface $dispatcher, array $options = []) - { - self::validateName($name); - - if (null !== $dataClass && !class_exists($dataClass) && !interface_exists($dataClass, false)) { - throw new InvalidArgumentException(sprintf('Class "%s" not found. Is the "data_class" form option set correctly?', $dataClass)); - } - - $this->name = (string) $name; - $this->dataClass = $dataClass; - $this->dispatcher = $dispatcher; - $this->options = $options; - } - - /** - * {@inheritdoc} - */ - public function addEventListener(string $eventName, callable $listener, int $priority = 0) - { - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $this->dispatcher->addListener($eventName, $listener, $priority); - - return $this; - } - - /** - * {@inheritdoc} - */ - public function addEventSubscriber(EventSubscriberInterface $subscriber) - { - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $this->dispatcher->addSubscriber($subscriber); - - return $this; - } - - /** - * {@inheritdoc} - */ - public function addViewTransformer(DataTransformerInterface $viewTransformer, bool $forcePrepend = false) - { - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - if ($forcePrepend) { - array_unshift($this->viewTransformers, $viewTransformer); - } else { - $this->viewTransformers[] = $viewTransformer; - } - - return $this; - } - - /** - * {@inheritdoc} - */ - public function resetViewTransformers() - { - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $this->viewTransformers = []; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function addModelTransformer(DataTransformerInterface $modelTransformer, bool $forceAppend = false) - { - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - if ($forceAppend) { - $this->modelTransformers[] = $modelTransformer; - } else { - array_unshift($this->modelTransformers, $modelTransformer); - } - - return $this; - } - - /** - * {@inheritdoc} - */ - public function resetModelTransformers() - { - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $this->modelTransformers = []; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getEventDispatcher() - { - if ($this->locked && !$this->dispatcher instanceof ImmutableEventDispatcher) { - $this->dispatcher = new ImmutableEventDispatcher($this->dispatcher); - } - - return $this->dispatcher; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->name; - } - - /** - * {@inheritdoc} - */ - public function getPropertyPath() - { - return $this->propertyPath; - } - - /** - * {@inheritdoc} - */ - public function getMapped() - { - return $this->mapped; - } - - /** - * {@inheritdoc} - */ - public function getByReference() - { - return $this->byReference; - } - - /** - * {@inheritdoc} - */ - public function getInheritData() - { - return $this->inheritData; - } - - /** - * {@inheritdoc} - */ - public function getCompound() - { - return $this->compound; - } - - /** - * {@inheritdoc} - */ - public function getType() - { - return $this->type; - } - - /** - * {@inheritdoc} - */ - public function getViewTransformers() - { - return $this->viewTransformers; - } - - /** - * {@inheritdoc} - */ - public function getModelTransformers() - { - return $this->modelTransformers; - } - - /** - * {@inheritdoc} - */ - public function getDataMapper() - { - return $this->dataMapper; - } - - /** - * {@inheritdoc} - */ - public function getRequired() - { - return $this->required; - } - - /** - * {@inheritdoc} - */ - public function getDisabled() - { - return $this->disabled; - } - - /** - * {@inheritdoc} - */ - public function getErrorBubbling() - { - return $this->errorBubbling; - } - - /** - * {@inheritdoc} - */ - public function getEmptyData() - { - return $this->emptyData; - } - - /** - * {@inheritdoc} - */ - public function getAttributes() - { - return $this->attributes; - } - - /** - * {@inheritdoc} - */ - public function hasAttribute(string $name) - { - return \array_key_exists($name, $this->attributes); - } - - /** - * {@inheritdoc} - */ - public function getAttribute(string $name, $default = null) - { - return \array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; - } - - /** - * {@inheritdoc} - */ - public function getData() - { - return $this->data; - } - - /** - * {@inheritdoc} - */ - public function getDataClass() - { - return $this->dataClass; - } - - /** - * {@inheritdoc} - */ - public function getDataLocked() - { - return $this->dataLocked; - } - - /** - * {@inheritdoc} - */ - public function getFormFactory() - { - if (!isset($this->formFactory)) { - throw new BadMethodCallException('The form factory must be set before retrieving it.'); - } - - return $this->formFactory; - } - - /** - * {@inheritdoc} - */ - public function getAction() - { - return $this->action; - } - - /** - * {@inheritdoc} - */ - public function getMethod() - { - return $this->method; - } - - /** - * {@inheritdoc} - */ - public function getRequestHandler() - { - if (null === $this->requestHandler) { - if (null === self::$nativeRequestHandler) { - self::$nativeRequestHandler = new NativeRequestHandler(); - } - $this->requestHandler = self::$nativeRequestHandler; - } - - return $this->requestHandler; - } - - /** - * {@inheritdoc} - */ - public function getAutoInitialize() - { - return $this->autoInitialize; - } - - /** - * {@inheritdoc} - */ - public function getOptions() - { - return $this->options; - } - - /** - * {@inheritdoc} - */ - public function hasOption(string $name) - { - return \array_key_exists($name, $this->options); - } - - /** - * {@inheritdoc} - */ - public function getOption(string $name, $default = null) - { - return \array_key_exists($name, $this->options) ? $this->options[$name] : $default; - } - - /** - * {@inheritdoc} - */ - public function getIsEmptyCallback(): ?callable - { - return $this->isEmptyCallback; - } - - /** - * {@inheritdoc} - */ - public function setAttribute(string $name, $value) - { - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $this->attributes[$name] = $value; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setAttributes(array $attributes) - { - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $this->attributes = $attributes; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setDataMapper(DataMapperInterface $dataMapper = null) - { - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $this->dataMapper = $dataMapper; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setDisabled(bool $disabled) - { - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $this->disabled = $disabled; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setEmptyData($emptyData) - { - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $this->emptyData = $emptyData; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setErrorBubbling(bool $errorBubbling) - { - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $this->errorBubbling = $errorBubbling; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setRequired(bool $required) - { - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $this->required = $required; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setPropertyPath($propertyPath) - { - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - if (null !== $propertyPath && !$propertyPath instanceof PropertyPathInterface) { - $propertyPath = new PropertyPath($propertyPath); - } - - $this->propertyPath = $propertyPath; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setMapped(bool $mapped) - { - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $this->mapped = $mapped; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setByReference(bool $byReference) - { - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $this->byReference = $byReference; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setInheritData(bool $inheritData) - { - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $this->inheritData = $inheritData; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setCompound(bool $compound) - { - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $this->compound = $compound; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setType(ResolvedFormTypeInterface $type) - { - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $this->type = $type; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setData($data) - { - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $this->data = $data; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setDataLocked(bool $locked) - { - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $this->dataLocked = $locked; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setFormFactory(FormFactoryInterface $formFactory) - { - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $this->formFactory = $formFactory; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setAction(string $action) - { - if ($this->locked) { - throw new BadMethodCallException('The config builder cannot be modified anymore.'); - } - - $this->action = $action; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setMethod(string $method) - { - if ($this->locked) { - throw new BadMethodCallException('The config builder cannot be modified anymore.'); - } - - $this->method = strtoupper($method); - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setRequestHandler(RequestHandlerInterface $requestHandler) - { - if ($this->locked) { - throw new BadMethodCallException('The config builder cannot be modified anymore.'); - } - - $this->requestHandler = $requestHandler; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function setAutoInitialize(bool $initialize) - { - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $this->autoInitialize = $initialize; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getFormConfig() - { - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - // This method should be idempotent, so clone the builder - $config = clone $this; - $config->locked = true; - - return $config; - } - - /** - * {@inheritdoc} - */ - public function setIsEmptyCallback(?callable $isEmptyCallback) - { - $this->isEmptyCallback = $isEmptyCallback; - - return $this; - } - - /** - * Validates whether the given variable is a valid form name. - * - * @throws InvalidArgumentException if the name contains invalid characters - * - * @internal - */ - final public static function validateName(?string $name) - { - if (!self::isValidName($name)) { - throw new InvalidArgumentException(sprintf('The name "%s" contains illegal characters. Names should start with a letter, digit or underscore and only contain letters, digits, numbers, underscores ("_"), hyphens ("-") and colons (":").', $name)); - } - } - - /** - * Returns whether the given variable contains a valid form name. - * - * A name is accepted if it - * - * * is empty - * * starts with a letter, digit or underscore - * * contains only letters, digits, numbers, underscores ("_"), - * hyphens ("-") and colons (":") - */ - final public static function isValidName(?string $name): bool - { - return '' === $name || null === $name || preg_match('/^[a-zA-Z0-9_][a-zA-Z0-9_\-:]*$/D', $name); - } -} diff --git a/lib/symfony/form/FormConfigBuilderInterface.php b/lib/symfony/form/FormConfigBuilderInterface.php deleted file mode 100644 index 757fa2584..000000000 --- a/lib/symfony/form/FormConfigBuilderInterface.php +++ /dev/null @@ -1,254 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\PropertyAccess\PropertyPathInterface; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @method $this setIsEmptyCallback(callable|null $isEmptyCallback) Sets the callback that will be called to determine if the model data of the form is empty or not - not implementing it is deprecated since Symfony 5.1 - */ -interface FormConfigBuilderInterface extends FormConfigInterface -{ - /** - * Adds an event listener to an event on this form. - * - * @param int $priority The priority of the listener. Listeners - * with a higher priority are called before - * listeners with a lower priority. - * - * @return $this - */ - public function addEventListener(string $eventName, callable $listener, int $priority = 0); - - /** - * Adds an event subscriber for events on this form. - * - * @return $this - */ - public function addEventSubscriber(EventSubscriberInterface $subscriber); - - /** - * Appends / prepends a transformer to the view transformer chain. - * - * The transform method of the transformer is used to convert data from the - * normalized to the view format. - * The reverseTransform method of the transformer is used to convert from the - * view to the normalized format. - * - * @param bool $forcePrepend If set to true, prepend instead of appending - * - * @return $this - */ - public function addViewTransformer(DataTransformerInterface $viewTransformer, bool $forcePrepend = false); - - /** - * Clears the view transformers. - * - * @return $this - */ - public function resetViewTransformers(); - - /** - * Prepends / appends a transformer to the normalization transformer chain. - * - * The transform method of the transformer is used to convert data from the - * model to the normalized format. - * The reverseTransform method of the transformer is used to convert from the - * normalized to the model format. - * - * @param bool $forceAppend If set to true, append instead of prepending - * - * @return $this - */ - public function addModelTransformer(DataTransformerInterface $modelTransformer, bool $forceAppend = false); - - /** - * Clears the normalization transformers. - * - * @return $this - */ - public function resetModelTransformers(); - - /** - * Sets the value for an attribute. - * - * @param mixed $value The value of the attribute - * - * @return $this - */ - public function setAttribute(string $name, $value); - - /** - * Sets the attributes. - * - * @return $this - */ - public function setAttributes(array $attributes); - - /** - * Sets the data mapper used by the form. - * - * @return $this - */ - public function setDataMapper(DataMapperInterface $dataMapper = null); - - /** - * Sets whether the form is disabled. - * - * @return $this - */ - public function setDisabled(bool $disabled); - - /** - * Sets the data used for the client data when no value is submitted. - * - * @param mixed $emptyData The empty data - * - * @return $this - */ - public function setEmptyData($emptyData); - - /** - * Sets whether errors bubble up to the parent. - * - * @return $this - */ - public function setErrorBubbling(bool $errorBubbling); - - /** - * Sets whether this field is required to be filled out when submitted. - * - * @return $this - */ - public function setRequired(bool $required); - - /** - * Sets the property path that the form should be mapped to. - * - * @param string|PropertyPathInterface|null $propertyPath The property path or null if the path should be set - * automatically based on the form's name - * - * @return $this - */ - public function setPropertyPath($propertyPath); - - /** - * Sets whether the form should be mapped to an element of its - * parent's data. - * - * @return $this - */ - public function setMapped(bool $mapped); - - /** - * Sets whether the form's data should be modified by reference. - * - * @return $this - */ - public function setByReference(bool $byReference); - - /** - * Sets whether the form should read and write the data of its parent. - * - * @return $this - */ - public function setInheritData(bool $inheritData); - - /** - * Sets whether the form should be compound. - * - * @return $this - * - * @see FormConfigInterface::getCompound() - */ - public function setCompound(bool $compound); - - /** - * Sets the resolved type. - * - * @return $this - */ - public function setType(ResolvedFormTypeInterface $type); - - /** - * Sets the initial data of the form. - * - * @param mixed $data The data of the form in model format - * - * @return $this - */ - public function setData($data); - - /** - * Locks the form's data to the data passed in the configuration. - * - * A form with locked data is restricted to the data passed in - * this configuration. The data can only be modified then by - * submitting the form or using PRE_SET_DATA event. - * - * It means data passed to a factory method or mapped from the - * parent will be ignored. - * - * @return $this - */ - public function setDataLocked(bool $locked); - - /** - * Sets the form factory used for creating new forms. - */ - public function setFormFactory(FormFactoryInterface $formFactory); - - /** - * Sets the target URL of the form. - * - * @return $this - */ - public function setAction(string $action); - - /** - * Sets the HTTP method used by the form. - * - * @return $this - */ - public function setMethod(string $method); - - /** - * Sets the request handler used by the form. - * - * @return $this - */ - public function setRequestHandler(RequestHandlerInterface $requestHandler); - - /** - * Sets whether the form should be initialized automatically. - * - * Should be set to true only for root forms. - * - * @param bool $initialize True to initialize the form automatically, - * false to suppress automatic initialization. - * In the second case, you need to call - * {@link FormInterface::initialize()} manually. - * - * @return $this - */ - public function setAutoInitialize(bool $initialize); - - /** - * Builds and returns the form configuration. - * - * @return FormConfigInterface - */ - public function getFormConfig(); -} diff --git a/lib/symfony/form/FormConfigInterface.php b/lib/symfony/form/FormConfigInterface.php deleted file mode 100644 index e332feb1e..000000000 --- a/lib/symfony/form/FormConfigInterface.php +++ /dev/null @@ -1,249 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\PropertyAccess\PropertyPathInterface; - -/** - * The configuration of a {@link Form} object. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @method callable|null getIsEmptyCallback() Returns a callable that takes the model data as argument and that returns if it is empty or not - not implementing it is deprecated since Symfony 5.1 - */ -interface FormConfigInterface -{ - /** - * Returns the event dispatcher used to dispatch form events. - * - * @return EventDispatcherInterface - */ - public function getEventDispatcher(); - - /** - * Returns the name of the form used as HTTP parameter. - * - * @return string - */ - public function getName(); - - /** - * Returns the property path that the form should be mapped to. - * - * @return PropertyPathInterface|null - */ - public function getPropertyPath(); - - /** - * Returns whether the form should be mapped to an element of its - * parent's data. - * - * @return bool - */ - public function getMapped(); - - /** - * Returns whether the form's data should be modified by reference. - * - * @return bool - */ - public function getByReference(); - - /** - * Returns whether the form should read and write the data of its parent. - * - * @return bool - */ - public function getInheritData(); - - /** - * Returns whether the form is compound. - * - * This property is independent of whether the form actually has - * children. A form can be compound and have no children at all, like - * for example an empty collection form. - * The contrary is not possible, a form which is not compound - * cannot have any children. - * - * @return bool - */ - public function getCompound(); - - /** - * Returns the resolved form type used to construct the form. - * - * @return ResolvedFormTypeInterface - */ - public function getType(); - - /** - * Returns the view transformers of the form. - * - * @return DataTransformerInterface[] - */ - public function getViewTransformers(); - - /** - * Returns the model transformers of the form. - * - * @return DataTransformerInterface[] - */ - public function getModelTransformers(); - - /** - * Returns the data mapper of the compound form or null for a simple form. - * - * @return DataMapperInterface|null - */ - public function getDataMapper(); - - /** - * Returns whether the form is required. - * - * @return bool - */ - public function getRequired(); - - /** - * Returns whether the form is disabled. - * - * @return bool - */ - public function getDisabled(); - - /** - * Returns whether errors attached to the form will bubble to its parent. - * - * @return bool - */ - public function getErrorBubbling(); - - /** - * Used when the view data is empty on submission. - * - * When the form is compound it will also be used to map the - * children data. - * - * The empty data must match the view format as it will passed to the first view transformer's - * "reverseTransform" method. - * - * @return mixed - */ - public function getEmptyData(); - - /** - * Returns additional attributes of the form. - * - * @return array - */ - public function getAttributes(); - - /** - * Returns whether the attribute with the given name exists. - * - * @return bool - */ - public function hasAttribute(string $name); - - /** - * Returns the value of the given attribute. - * - * @param mixed $default The value returned if the attribute does not exist - * - * @return mixed - */ - public function getAttribute(string $name, $default = null); - - /** - * Returns the initial data of the form. - * - * @return mixed - */ - public function getData(); - - /** - * Returns the class of the view data or null if the data is scalar or an array. - * - * @return string|null - */ - public function getDataClass(); - - /** - * Returns whether the form's data is locked. - * - * A form with locked data is restricted to the data passed in - * this configuration. The data can only be modified then by - * submitting the form. - * - * @return bool - */ - public function getDataLocked(); - - /** - * Returns the form factory used for creating new forms. - * - * @return FormFactoryInterface - */ - public function getFormFactory(); - - /** - * Returns the target URL of the form. - * - * @return string - */ - public function getAction(); - - /** - * Returns the HTTP method used by the form. - * - * @return string - */ - public function getMethod(); - - /** - * Returns the request handler used by the form. - * - * @return RequestHandlerInterface - */ - public function getRequestHandler(); - - /** - * Returns whether the form should be initialized upon creation. - * - * @return bool - */ - public function getAutoInitialize(); - - /** - * Returns all options passed during the construction of the form. - * - * @return array<string, mixed> The passed options - */ - public function getOptions(); - - /** - * Returns whether a specific option exists. - * - * @return bool - */ - public function hasOption(string $name); - - /** - * Returns the value of a specific option. - * - * @param mixed $default The value returned if the option does not exist - * - * @return mixed - */ - public function getOption(string $name, $default = null); -} diff --git a/lib/symfony/form/FormError.php b/lib/symfony/form/FormError.php deleted file mode 100644 index e03f3eef5..000000000 --- a/lib/symfony/form/FormError.php +++ /dev/null @@ -1,134 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\Form\Exception\BadMethodCallException; - -/** - * Wraps errors in forms. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class FormError -{ - protected $messageTemplate; - protected $messageParameters; - protected $messagePluralization; - - private $message; - private $cause; - - /** - * The form that spawned this error. - * - * @var FormInterface - */ - private $origin; - - /** - * Any array key in $messageParameters will be used as a placeholder in - * $messageTemplate. - * - * @param string $message The translated error message - * @param string|null $messageTemplate The template for the error message - * @param array $messageParameters The parameters that should be - * substituted in the message template - * @param int|null $messagePluralization The value for error message pluralization - * @param mixed $cause The cause of the error - * - * @see \Symfony\Component\Translation\Translator - */ - public function __construct(string $message, string $messageTemplate = null, array $messageParameters = [], int $messagePluralization = null, $cause = null) - { - $this->message = $message; - $this->messageTemplate = $messageTemplate ?: $message; - $this->messageParameters = $messageParameters; - $this->messagePluralization = $messagePluralization; - $this->cause = $cause; - } - - /** - * Returns the error message. - * - * @return string - */ - public function getMessage() - { - return $this->message; - } - - /** - * Returns the error message template. - * - * @return string - */ - public function getMessageTemplate() - { - return $this->messageTemplate; - } - - /** - * Returns the parameters to be inserted in the message template. - * - * @return array - */ - public function getMessageParameters() - { - return $this->messageParameters; - } - - /** - * Returns the value for error message pluralization. - * - * @return int|null - */ - public function getMessagePluralization() - { - return $this->messagePluralization; - } - - /** - * Returns the cause of this error. - * - * @return mixed - */ - public function getCause() - { - return $this->cause; - } - - /** - * Sets the form that caused this error. - * - * This method must only be called once. - * - * @throws BadMethodCallException If the method is called more than once - */ - public function setOrigin(FormInterface $origin) - { - if (null !== $this->origin) { - throw new BadMethodCallException('setOrigin() must only be called once.'); - } - - $this->origin = $origin; - } - - /** - * Returns the form that caused this error. - * - * @return FormInterface|null - */ - public function getOrigin() - { - return $this->origin; - } -} diff --git a/lib/symfony/form/FormErrorIterator.php b/lib/symfony/form/FormErrorIterator.php deleted file mode 100644 index 9ee2f0e8f..000000000 --- a/lib/symfony/form/FormErrorIterator.php +++ /dev/null @@ -1,316 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\Form\Exception\BadMethodCallException; -use Symfony\Component\Form\Exception\InvalidArgumentException; -use Symfony\Component\Form\Exception\LogicException; -use Symfony\Component\Form\Exception\OutOfBoundsException; -use Symfony\Component\Validator\ConstraintViolation; - -/** - * Iterates over the errors of a form. - * - * This class supports recursive iteration. In order to iterate recursively, - * pass a structure of {@link FormError} and {@link FormErrorIterator} objects - * to the $errors constructor argument. - * - * You can also wrap the iterator into a {@link \RecursiveIteratorIterator} to - * flatten the recursive structure into a flat list of errors. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @template T of FormError|FormErrorIterator - * - * @implements \ArrayAccess<int, T> - * @implements \RecursiveIterator<int, T> - * @implements \SeekableIterator<int, T> - */ -class FormErrorIterator implements \RecursiveIterator, \SeekableIterator, \ArrayAccess, \Countable -{ - /** - * The prefix used for indenting nested error messages. - */ - public const INDENTATION = ' '; - - private $form; - - /** - * @var list<T> - */ - private $errors; - - /** - * @param list<T> $errors - * - * @throws InvalidArgumentException If the errors are invalid - */ - public function __construct(FormInterface $form, array $errors) - { - foreach ($errors as $error) { - if (!($error instanceof FormError || $error instanceof self)) { - throw new InvalidArgumentException(sprintf('The errors must be instances of "Symfony\Component\Form\FormError" or "%s". Got: "%s".', __CLASS__, get_debug_type($error))); - } - } - - $this->form = $form; - $this->errors = $errors; - } - - /** - * Returns all iterated error messages as string. - * - * @return string - */ - public function __toString() - { - $string = ''; - - foreach ($this->errors as $error) { - if ($error instanceof FormError) { - $string .= 'ERROR: '.$error->getMessage()."\n"; - } else { - /* @var self $error */ - $string .= $error->getForm()->getName().":\n"; - $string .= self::indent((string) $error); - } - } - - return $string; - } - - /** - * Returns the iterated form. - * - * @return FormInterface - */ - public function getForm() - { - return $this->form; - } - - /** - * Returns the current element of the iterator. - * - * @return T An error or an iterator containing nested errors - */ - #[\ReturnTypeWillChange] - public function current() - { - return current($this->errors); - } - - /** - * Advances the iterator to the next position. - */ - #[\ReturnTypeWillChange] - public function next() - { - next($this->errors); - } - - /** - * Returns the current position of the iterator. - * - * @return int - */ - #[\ReturnTypeWillChange] - public function key() - { - return key($this->errors); - } - - /** - * Returns whether the iterator's position is valid. - * - * @return bool - */ - #[\ReturnTypeWillChange] - public function valid() - { - return null !== key($this->errors); - } - - /** - * Sets the iterator's position to the beginning. - * - * This method detects if errors have been added to the form since the - * construction of the iterator. - */ - #[\ReturnTypeWillChange] - public function rewind() - { - reset($this->errors); - } - - /** - * Returns whether a position exists in the iterator. - * - * @param int $position The position - * - * @return bool - */ - #[\ReturnTypeWillChange] - public function offsetExists($position) - { - return isset($this->errors[$position]); - } - - /** - * Returns the element at a position in the iterator. - * - * @param int $position The position - * - * @return T - * - * @throws OutOfBoundsException If the given position does not exist - */ - #[\ReturnTypeWillChange] - public function offsetGet($position) - { - if (!isset($this->errors[$position])) { - throw new OutOfBoundsException('The offset '.$position.' does not exist.'); - } - - return $this->errors[$position]; - } - - /** - * Unsupported method. - * - * @return void - * - * @throws BadMethodCallException - */ - #[\ReturnTypeWillChange] - public function offsetSet($position, $value) - { - throw new BadMethodCallException('The iterator doesn\'t support modification of elements.'); - } - - /** - * Unsupported method. - * - * @return void - * - * @throws BadMethodCallException - */ - #[\ReturnTypeWillChange] - public function offsetUnset($position) - { - throw new BadMethodCallException('The iterator doesn\'t support modification of elements.'); - } - - /** - * Returns whether the current element of the iterator can be recursed - * into. - * - * @return bool - */ - #[\ReturnTypeWillChange] - public function hasChildren() - { - return current($this->errors) instanceof self; - } - - /** - * @return self - */ - #[\ReturnTypeWillChange] - public function getChildren() - { - if (!$this->hasChildren()) { - trigger_deprecation('symfony/form', '5.4', 'Calling "%s()" if the current element is not iterable is deprecated, call "%s" to get the current element.', __METHOD__, self::class.'::current()'); - // throw new LogicException(sprintf('The current element is not iterable. Use "%s" to get the current element.', self::class.'::current()')); - } - - /** @var self $children */ - $children = current($this->errors); - - return $children; - } - - /** - * Returns the number of elements in the iterator. - * - * Note that this is not the total number of errors, if the constructor - * parameter $deep was set to true! In that case, you should wrap the - * iterator into a {@link \RecursiveIteratorIterator} with the standard mode - * {@link \RecursiveIteratorIterator::LEAVES_ONLY} and count the result. - * - * $iterator = new \RecursiveIteratorIterator($form->getErrors(true)); - * $count = count(iterator_to_array($iterator)); - * - * Alternatively, set the constructor argument $flatten to true as well. - * - * $count = count($form->getErrors(true, true)); - * - * @return int - */ - #[\ReturnTypeWillChange] - public function count() - { - return \count($this->errors); - } - - /** - * Sets the position of the iterator. - * - * @param int $position The new position - * - * @return void - * - * @throws OutOfBoundsException If the position is invalid - */ - #[\ReturnTypeWillChange] - public function seek($position) - { - if (!isset($this->errors[$position])) { - throw new OutOfBoundsException('The offset '.$position.' does not exist.'); - } - - reset($this->errors); - - while ($position !== key($this->errors)) { - next($this->errors); - } - } - - /** - * Creates iterator for errors with specific codes. - * - * @param string|string[] $codes The codes to find - * - * @return static - */ - public function findByCodes($codes) - { - $codes = (array) $codes; - $errors = []; - foreach ($this as $error) { - $cause = $error->getCause(); - if ($cause instanceof ConstraintViolation && \in_array($cause->getCode(), $codes, true)) { - $errors[] = $error; - } - } - - return new static($this->form, $errors); - } - - /** - * Utility function for indenting multi-line strings. - */ - private static function indent(string $string): string - { - return rtrim(self::INDENTATION.str_replace("\n", "\n".self::INDENTATION, $string), ' '); - } -} diff --git a/lib/symfony/form/FormEvent.php b/lib/symfony/form/FormEvent.php deleted file mode 100644 index c466fafdc..000000000 --- a/lib/symfony/form/FormEvent.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Contracts\EventDispatcher\Event; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class FormEvent extends Event -{ - private $form; - protected $data; - - /** - * @param mixed $data The data - */ - public function __construct(FormInterface $form, $data) - { - $this->form = $form; - $this->data = $data; - } - - /** - * Returns the form at the source of the event. - * - * @return FormInterface - */ - public function getForm() - { - return $this->form; - } - - /** - * Returns the data associated with this event. - * - * @return mixed - */ - public function getData() - { - return $this->data; - } - - /** - * Allows updating with some filtered data. - * - * @param mixed $data - */ - public function setData($data) - { - $this->data = $data; - } -} diff --git a/lib/symfony/form/FormEvents.php b/lib/symfony/form/FormEvents.php deleted file mode 100644 index cf4d97f55..000000000 --- a/lib/symfony/form/FormEvents.php +++ /dev/null @@ -1,113 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\Form\Event\PostSetDataEvent; -use Symfony\Component\Form\Event\PostSubmitEvent; -use Symfony\Component\Form\Event\PreSetDataEvent; -use Symfony\Component\Form\Event\PreSubmitEvent; -use Symfony\Component\Form\Event\SubmitEvent; - -/** - * To learn more about how form events work check the documentation - * entry at {@link https://symfony.com/doc/any/components/form/form_events.html}. - * - * To learn how to dynamically modify forms using events check the cookbook - * entry at {@link https://symfony.com/doc/any/cookbook/form/dynamic_form_modification.html}. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -final class FormEvents -{ - /** - * The PRE_SUBMIT event is dispatched at the beginning of the Form::submit() method. - * - * It can be used to: - * - Change data from the request, before submitting the data to the form. - * - Add or remove form fields, before submitting the data to the form. - * - * @Event("Symfony\Component\Form\Event\PreSubmitEvent") - */ - public const PRE_SUBMIT = 'form.pre_submit'; - - /** - * The SUBMIT event is dispatched after the Form::submit() method - * has changed the view data by the request data, or submitted and mapped - * the children if the form is compound, and after reverse transformation - * to normalized representation. - * - * It's also dispatched just before the Form::submit() method transforms back - * the normalized data to the model and view data. - * - * So at this stage children of compound forms are submitted and synchronized, unless - * their transformation failed, but a parent would still be at the PRE_SUBMIT level. - * - * Since the current form is not synchronized yet, it is still possible to add and - * remove fields. - * - * @Event("Symfony\Component\Form\Event\SubmitEvent") - */ - public const SUBMIT = 'form.submit'; - - /** - * The FormEvents::POST_SUBMIT event is dispatched at the very end of the Form::submit(). - * - * It this stage the model and view data may have been denormalized. Otherwise the form - * is desynchronized because transformation failed during submission. - * - * It can be used to fetch data after denormalization. - * - * The event attaches the current view data. To know whether this is the renormalized data - * or the invalid request data, call Form::isSynchronized() first. - * - * @Event("Symfony\Component\Form\Event\PostSubmitEvent") - */ - public const POST_SUBMIT = 'form.post_submit'; - - /** - * The FormEvents::PRE_SET_DATA event is dispatched at the beginning of the Form::setData() method. - * - * It can be used to: - * - Modify the data given during pre-population; - * - Keep synchronized the form depending on the data (adding or removing fields dynamically). - * - * @Event("Symfony\Component\Form\Event\PreSetDataEvent") - */ - public const PRE_SET_DATA = 'form.pre_set_data'; - - /** - * The FormEvents::POST_SET_DATA event is dispatched at the end of the Form::setData() method. - * - * This event can be used to modify the form depending on the final state of the underlying data - * accessible in every representation: model, normalized and view. - * - * @Event("Symfony\Component\Form\Event\PostSetDataEvent") - */ - public const POST_SET_DATA = 'form.post_set_data'; - - /** - * Event aliases. - * - * These aliases can be consumed by RegisterListenersPass. - */ - public const ALIASES = [ - PreSubmitEvent::class => self::PRE_SUBMIT, - SubmitEvent::class => self::SUBMIT, - PostSubmitEvent::class => self::POST_SUBMIT, - PreSetDataEvent::class => self::PRE_SET_DATA, - PostSetDataEvent::class => self::POST_SET_DATA, - ]; - - private function __construct() - { - } -} diff --git a/lib/symfony/form/FormExtensionInterface.php b/lib/symfony/form/FormExtensionInterface.php deleted file mode 100644 index 8fafcee2a..000000000 --- a/lib/symfony/form/FormExtensionInterface.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -/** - * Interface for extensions which provide types, type extensions and a guesser. - */ -interface FormExtensionInterface -{ - /** - * Returns a type by name. - * - * @param string $name The name of the type - * - * @return FormTypeInterface - * - * @throws Exception\InvalidArgumentException if the given type is not supported by this extension - */ - public function getType(string $name); - - /** - * Returns whether the given type is supported. - * - * @param string $name The name of the type - * - * @return bool - */ - public function hasType(string $name); - - /** - * Returns the extensions for the given type. - * - * @param string $name The name of the type - * - * @return FormTypeExtensionInterface[] - */ - public function getTypeExtensions(string $name); - - /** - * Returns whether this extension provides type extensions for the given type. - * - * @param string $name The name of the type - * - * @return bool - */ - public function hasTypeExtensions(string $name); - - /** - * Returns the type guesser provided by this extension. - * - * @return FormTypeGuesserInterface|null - */ - public function getTypeGuesser(); -} diff --git a/lib/symfony/form/FormFactory.php b/lib/symfony/form/FormFactory.php deleted file mode 100644 index b3185d1a3..000000000 --- a/lib/symfony/form/FormFactory.php +++ /dev/null @@ -1,122 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\Form\Extension\Core\Type\FormType; -use Symfony\Component\Form\Extension\Core\Type\TextType; - -class FormFactory implements FormFactoryInterface -{ - private $registry; - - public function __construct(FormRegistryInterface $registry) - { - $this->registry = $registry; - } - - /** - * {@inheritdoc} - */ - public function create(string $type = FormType::class, $data = null, array $options = []) - { - return $this->createBuilder($type, $data, $options)->getForm(); - } - - /** - * {@inheritdoc} - */ - public function createNamed(string $name, string $type = FormType::class, $data = null, array $options = []) - { - return $this->createNamedBuilder($name, $type, $data, $options)->getForm(); - } - - /** - * {@inheritdoc} - */ - public function createForProperty(string $class, string $property, $data = null, array $options = []) - { - return $this->createBuilderForProperty($class, $property, $data, $options)->getForm(); - } - - /** - * {@inheritdoc} - */ - public function createBuilder(string $type = FormType::class, $data = null, array $options = []) - { - return $this->createNamedBuilder($this->registry->getType($type)->getBlockPrefix(), $type, $data, $options); - } - - /** - * {@inheritdoc} - */ - public function createNamedBuilder(string $name, string $type = FormType::class, $data = null, array $options = []) - { - if (null !== $data && !\array_key_exists('data', $options)) { - $options['data'] = $data; - } - - $type = $this->registry->getType($type); - - $builder = $type->createBuilder($this, $name, $options); - - // Explicitly call buildForm() in order to be able to override either - // createBuilder() or buildForm() in the resolved form type - $type->buildForm($builder, $builder->getOptions()); - - return $builder; - } - - /** - * {@inheritdoc} - */ - public function createBuilderForProperty(string $class, string $property, $data = null, array $options = []) - { - if (null === $guesser = $this->registry->getTypeGuesser()) { - return $this->createNamedBuilder($property, TextType::class, $data, $options); - } - - $typeGuess = $guesser->guessType($class, $property); - $maxLengthGuess = $guesser->guessMaxLength($class, $property); - $requiredGuess = $guesser->guessRequired($class, $property); - $patternGuess = $guesser->guessPattern($class, $property); - - $type = $typeGuess ? $typeGuess->getType() : TextType::class; - - $maxLength = $maxLengthGuess ? $maxLengthGuess->getValue() : null; - $pattern = $patternGuess ? $patternGuess->getValue() : null; - - if (null !== $pattern) { - $options = array_replace_recursive(['attr' => ['pattern' => $pattern]], $options); - } - - if (null !== $maxLength) { - $options = array_replace_recursive(['attr' => ['maxlength' => $maxLength]], $options); - } - - if ($requiredGuess) { - $options = array_merge(['required' => $requiredGuess->getValue()], $options); - } - - // user options may override guessed options - if ($typeGuess) { - $attrs = []; - $typeGuessOptions = $typeGuess->getOptions(); - if (isset($typeGuessOptions['attr']) && isset($options['attr'])) { - $attrs = ['attr' => array_merge($typeGuessOptions['attr'], $options['attr'])]; - } - - $options = array_merge($typeGuessOptions, $options, $attrs); - } - - return $this->createNamedBuilder($property, $type, $data, $options); - } -} diff --git a/lib/symfony/form/FormFactoryBuilder.php b/lib/symfony/form/FormFactoryBuilder.php deleted file mode 100644 index 735a17e8e..000000000 --- a/lib/symfony/form/FormFactoryBuilder.php +++ /dev/null @@ -1,187 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\Form\Extension\Core\CoreExtension; - -/** - * The default implementation of FormFactoryBuilderInterface. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class FormFactoryBuilder implements FormFactoryBuilderInterface -{ - private $forceCoreExtension; - - /** - * @var ResolvedFormTypeFactoryInterface - */ - private $resolvedTypeFactory; - - /** - * @var FormExtensionInterface[] - */ - private $extensions = []; - - /** - * @var FormTypeInterface[] - */ - private $types = []; - - /** - * @var FormTypeExtensionInterface[][] - */ - private $typeExtensions = []; - - /** - * @var FormTypeGuesserInterface[] - */ - private $typeGuessers = []; - - public function __construct(bool $forceCoreExtension = false) - { - $this->forceCoreExtension = $forceCoreExtension; - } - - /** - * {@inheritdoc} - */ - public function setResolvedTypeFactory(ResolvedFormTypeFactoryInterface $resolvedTypeFactory) - { - $this->resolvedTypeFactory = $resolvedTypeFactory; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function addExtension(FormExtensionInterface $extension) - { - $this->extensions[] = $extension; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function addExtensions(array $extensions) - { - $this->extensions = array_merge($this->extensions, $extensions); - - return $this; - } - - /** - * {@inheritdoc} - */ - public function addType(FormTypeInterface $type) - { - $this->types[] = $type; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function addTypes(array $types) - { - foreach ($types as $type) { - $this->types[] = $type; - } - - return $this; - } - - /** - * {@inheritdoc} - */ - public function addTypeExtension(FormTypeExtensionInterface $typeExtension) - { - foreach ($typeExtension::getExtendedTypes() as $extendedType) { - $this->typeExtensions[$extendedType][] = $typeExtension; - } - - return $this; - } - - /** - * {@inheritdoc} - */ - public function addTypeExtensions(array $typeExtensions) - { - foreach ($typeExtensions as $typeExtension) { - $this->addTypeExtension($typeExtension); - } - - return $this; - } - - /** - * {@inheritdoc} - */ - public function addTypeGuesser(FormTypeGuesserInterface $typeGuesser) - { - $this->typeGuessers[] = $typeGuesser; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function addTypeGuessers(array $typeGuessers) - { - $this->typeGuessers = array_merge($this->typeGuessers, $typeGuessers); - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getFormFactory() - { - $extensions = $this->extensions; - - if ($this->forceCoreExtension) { - $hasCoreExtension = false; - - foreach ($extensions as $extension) { - if ($extension instanceof CoreExtension) { - $hasCoreExtension = true; - break; - } - } - - if (!$hasCoreExtension) { - array_unshift($extensions, new CoreExtension()); - } - } - - if (\count($this->types) > 0 || \count($this->typeExtensions) > 0 || \count($this->typeGuessers) > 0) { - if (\count($this->typeGuessers) > 1) { - $typeGuesser = new FormTypeGuesserChain($this->typeGuessers); - } else { - $typeGuesser = $this->typeGuessers[0] ?? null; - } - - $extensions[] = new PreloadedExtension($this->types, $this->typeExtensions, $typeGuesser); - } - - $registry = new FormRegistry($extensions, $this->resolvedTypeFactory ?? new ResolvedFormTypeFactory()); - - return new FormFactory($registry); - } -} diff --git a/lib/symfony/form/FormFactoryBuilderInterface.php b/lib/symfony/form/FormFactoryBuilderInterface.php deleted file mode 100644 index e3b0a7b3e..000000000 --- a/lib/symfony/form/FormFactoryBuilderInterface.php +++ /dev/null @@ -1,98 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -/** - * A builder for FormFactoryInterface objects. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface FormFactoryBuilderInterface -{ - /** - * Sets the factory for creating ResolvedFormTypeInterface instances. - * - * @return $this - */ - public function setResolvedTypeFactory(ResolvedFormTypeFactoryInterface $resolvedTypeFactory); - - /** - * Adds an extension to be loaded by the factory. - * - * @return $this - */ - public function addExtension(FormExtensionInterface $extension); - - /** - * Adds a list of extensions to be loaded by the factory. - * - * @param FormExtensionInterface[] $extensions The extensions - * - * @return $this - */ - public function addExtensions(array $extensions); - - /** - * Adds a form type to the factory. - * - * @return $this - */ - public function addType(FormTypeInterface $type); - - /** - * Adds a list of form types to the factory. - * - * @param FormTypeInterface[] $types The form types - * - * @return $this - */ - public function addTypes(array $types); - - /** - * Adds a form type extension to the factory. - * - * @return $this - */ - public function addTypeExtension(FormTypeExtensionInterface $typeExtension); - - /** - * Adds a list of form type extensions to the factory. - * - * @param FormTypeExtensionInterface[] $typeExtensions The form type extensions - * - * @return $this - */ - public function addTypeExtensions(array $typeExtensions); - - /** - * Adds a type guesser to the factory. - * - * @return $this - */ - public function addTypeGuesser(FormTypeGuesserInterface $typeGuesser); - - /** - * Adds a list of type guessers to the factory. - * - * @param FormTypeGuesserInterface[] $typeGuessers The type guessers - * - * @return $this - */ - public function addTypeGuessers(array $typeGuessers); - - /** - * Builds and returns the factory. - * - * @return FormFactoryInterface - */ - public function getFormFactory(); -} diff --git a/lib/symfony/form/FormFactoryInterface.php b/lib/symfony/form/FormFactoryInterface.php deleted file mode 100644 index c5f2485fd..000000000 --- a/lib/symfony/form/FormFactoryInterface.php +++ /dev/null @@ -1,102 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\Form\Extension\Core\Type\FormType; -use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; - -/** - * Allows creating a form based on a name, a class or a property. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface FormFactoryInterface -{ - /** - * Returns a form. - * - * @see createBuilder() - * - * @param mixed $data The initial data - * - * @return FormInterface - * - * @throws InvalidOptionsException if any given option is not applicable to the given type - */ - public function create(string $type = FormType::class, $data = null, array $options = []); - - /** - * Returns a form. - * - * @see createNamedBuilder() - * - * @param mixed $data The initial data - * - * @return FormInterface - * - * @throws InvalidOptionsException if any given option is not applicable to the given type - */ - public function createNamed(string $name, string $type = FormType::class, $data = null, array $options = []); - - /** - * Returns a form for a property of a class. - * - * @see createBuilderForProperty() - * - * @param string $class The fully qualified class name - * @param string $property The name of the property to guess for - * @param mixed $data The initial data - * - * @return FormInterface - * - * @throws InvalidOptionsException if any given option is not applicable to the form type - */ - public function createForProperty(string $class, string $property, $data = null, array $options = []); - - /** - * Returns a form builder. - * - * @param mixed $data The initial data - * - * @return FormBuilderInterface - * - * @throws InvalidOptionsException if any given option is not applicable to the given type - */ - public function createBuilder(string $type = FormType::class, $data = null, array $options = []); - - /** - * Returns a form builder. - * - * @param mixed $data The initial data - * - * @return FormBuilderInterface - * - * @throws InvalidOptionsException if any given option is not applicable to the given type - */ - public function createNamedBuilder(string $name, string $type = FormType::class, $data = null, array $options = []); - - /** - * Returns a form builder for a property of a class. - * - * If any of the 'required' and type options can be guessed, - * and are not provided in the options argument, the guessed value is used. - * - * @param string $class The fully qualified class name - * @param string $property The name of the property to guess for - * @param mixed $data The initial data - * - * @return FormBuilderInterface - * - * @throws InvalidOptionsException if any given option is not applicable to the form type - */ - public function createBuilderForProperty(string $class, string $property, $data = null, array $options = []); -} diff --git a/lib/symfony/form/FormInterface.php b/lib/symfony/form/FormInterface.php deleted file mode 100644 index 6cc6b4ed7..000000000 --- a/lib/symfony/form/FormInterface.php +++ /dev/null @@ -1,328 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\PropertyAccess\PropertyPathInterface; - -/** - * A form group bundling multiple forms in a hierarchical structure. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @extends \ArrayAccess<string, FormInterface> - * @extends \Traversable<string, FormInterface> - */ -interface FormInterface extends \ArrayAccess, \Traversable, \Countable -{ - /** - * Sets the parent form. - * - * @param FormInterface|null $parent The parent form or null if it's the root - * - * @return $this - * - * @throws Exception\AlreadySubmittedException if the form has already been submitted - * @throws Exception\LogicException when trying to set a parent for a form with - * an empty name - */ - public function setParent(self $parent = null); - - /** - * Returns the parent form. - * - * @return self|null - */ - public function getParent(); - - /** - * Adds or replaces a child to the form. - * - * @param FormInterface|string $child The FormInterface instance or the name of the child - * @param string|null $type The child's type, if a name was passed - * @param array $options The child's options, if a name was passed - * - * @return $this - * - * @throws Exception\AlreadySubmittedException if the form has already been submitted - * @throws Exception\LogicException when trying to add a child to a non-compound form - * @throws Exception\UnexpectedTypeException if $child or $type has an unexpected type - */ - public function add($child, string $type = null, array $options = []); - - /** - * Returns the child with the given name. - * - * @return self - * - * @throws Exception\OutOfBoundsException if the named child does not exist - */ - public function get(string $name); - - /** - * Returns whether a child with the given name exists. - * - * @return bool - */ - public function has(string $name); - - /** - * Removes a child from the form. - * - * @return $this - * - * @throws Exception\AlreadySubmittedException if the form has already been submitted - */ - public function remove(string $name); - - /** - * Returns all children in this group. - * - * @return self[] - */ - public function all(); - - /** - * Returns the errors of this form. - * - * @param bool $deep Whether to include errors of child forms as well - * @param bool $flatten Whether to flatten the list of errors in case - * $deep is set to true - * - * @return FormErrorIterator - */ - public function getErrors(bool $deep = false, bool $flatten = true); - - /** - * Updates the form with default model data. - * - * @param mixed $modelData The data formatted as expected for the underlying object - * - * @return $this - * - * @throws Exception\AlreadySubmittedException If the form has already been submitted - * @throws Exception\LogicException if the view data does not match the expected type - * according to {@link FormConfigInterface::getDataClass} - * @throws Exception\RuntimeException If listeners try to call setData in a cycle or if - * the form inherits data from its parent - * @throws Exception\TransformationFailedException if the synchronization failed - */ - public function setData($modelData); - - /** - * Returns the model data in the format needed for the underlying object. - * - * @return mixed When the field is not submitted, the default data is returned. - * When the field is submitted, the default data has been bound - * to the submitted view data. - * - * @throws Exception\RuntimeException If the form inherits data but has no parent - */ - public function getData(); - - /** - * Returns the normalized data of the field, used as internal bridge - * between model data and view data. - * - * @return mixed When the field is not submitted, the default data is returned. - * When the field is submitted, the normalized submitted data - * is returned if the field is synchronized with the view data, - * null otherwise. - * - * @throws Exception\RuntimeException If the form inherits data but has no parent - */ - public function getNormData(); - - /** - * Returns the view data of the field. - * - * It may be defined by {@link FormConfigInterface::getDataClass}. - * - * There are two cases: - * - * - When the form is compound the view data is mapped to the children. - * Each child will use its mapped data as model data. - * It can be an array, an object or null. - * - * - When the form is simple its view data is used to be bound - * to the submitted data. - * It can be a string or an array. - * - * In both cases the view data is the actual altered data on submission. - * - * @return mixed - * - * @throws Exception\RuntimeException If the form inherits data but has no parent - */ - public function getViewData(); - - /** - * Returns the extra submitted data. - * - * @return array The submitted data which do not belong to a child - */ - public function getExtraData(); - - /** - * Returns the form's configuration. - * - * @return FormConfigInterface - */ - public function getConfig(); - - /** - * Returns whether the form is submitted. - * - * @return bool - */ - public function isSubmitted(); - - /** - * Returns the name by which the form is identified in forms. - * - * Only root forms are allowed to have an empty name. - * - * @return string - */ - public function getName(); - - /** - * Returns the property path that the form is mapped to. - * - * @return PropertyPathInterface|null - */ - public function getPropertyPath(); - - /** - * Adds an error to this form. - * - * @return $this - */ - public function addError(FormError $error); - - /** - * Returns whether the form and all children are valid. - * - * @throws Exception\LogicException if the form is not submitted - * - * @return bool - */ - public function isValid(); - - /** - * Returns whether the form is required to be filled out. - * - * If the form has a parent and the parent is not required, this method - * will always return false. Otherwise the value set with setRequired() - * is returned. - * - * @return bool - */ - public function isRequired(); - - /** - * Returns whether this form is disabled. - * - * The content of a disabled form is displayed, but not allowed to be - * modified. The validation of modified disabled forms should fail. - * - * Forms whose parents are disabled are considered disabled regardless of - * their own state. - * - * @return bool - */ - public function isDisabled(); - - /** - * Returns whether the form is empty. - * - * @return bool - */ - public function isEmpty(); - - /** - * Returns whether the data in the different formats is synchronized. - * - * If the data is not synchronized, you can get the transformation failure - * by calling {@link getTransformationFailure()}. - * - * If the form is not submitted, this method always returns true. - * - * @return bool - */ - public function isSynchronized(); - - /** - * Returns the data transformation failure, if any, during submission. - * - * @return Exception\TransformationFailedException|null - */ - public function getTransformationFailure(); - - /** - * Initializes the form tree. - * - * Should be called on the root form after constructing the tree. - * - * @return $this - * - * @throws Exception\RuntimeException If the form is not the root - */ - public function initialize(); - - /** - * Inspects the given request and calls {@link submit()} if the form was - * submitted. - * - * Internally, the request is forwarded to the configured - * {@link RequestHandlerInterface} instance, which determines whether to - * submit the form or not. - * - * @param mixed $request The request to handle - * - * @return $this - */ - public function handleRequest($request = null); - - /** - * Submits data to the form. - * - * @param string|array|null $submittedData The submitted data - * @param bool $clearMissing Whether to set fields to NULL - * when they are missing in the - * submitted data. This argument - * is only used in compound form - * - * @return $this - * - * @throws Exception\AlreadySubmittedException if the form has already been submitted - */ - public function submit($submittedData, bool $clearMissing = true); - - /** - * Returns the root of the form tree. - * - * @return self - */ - public function getRoot(); - - /** - * Returns whether the field is the root of the form tree. - * - * @return bool - */ - public function isRoot(); - - /** - * @return FormView - */ - public function createView(FormView $parent = null); -} diff --git a/lib/symfony/form/FormRegistry.php b/lib/symfony/form/FormRegistry.php deleted file mode 100644 index 90087a6a8..000000000 --- a/lib/symfony/form/FormRegistry.php +++ /dev/null @@ -1,176 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\Form\Exception\ExceptionInterface; -use Symfony\Component\Form\Exception\InvalidArgumentException; -use Symfony\Component\Form\Exception\LogicException; -use Symfony\Component\Form\Exception\UnexpectedTypeException; - -/** - * The central registry of the Form component. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class FormRegistry implements FormRegistryInterface -{ - /** - * @var FormExtensionInterface[] - */ - private $extensions = []; - - /** - * @var ResolvedFormTypeInterface[] - */ - private $types = []; - - /** - * @var FormTypeGuesserInterface|false|null - */ - private $guesser = false; - - /** - * @var ResolvedFormTypeFactoryInterface - */ - private $resolvedTypeFactory; - - private $checkedTypes = []; - - /** - * @param FormExtensionInterface[] $extensions - * - * @throws UnexpectedTypeException if any extension does not implement FormExtensionInterface - */ - public function __construct(array $extensions, ResolvedFormTypeFactoryInterface $resolvedTypeFactory) - { - foreach ($extensions as $extension) { - if (!$extension instanceof FormExtensionInterface) { - throw new UnexpectedTypeException($extension, FormExtensionInterface::class); - } - } - - $this->extensions = $extensions; - $this->resolvedTypeFactory = $resolvedTypeFactory; - } - - /** - * {@inheritdoc} - */ - public function getType(string $name) - { - if (!isset($this->types[$name])) { - $type = null; - - foreach ($this->extensions as $extension) { - if ($extension->hasType($name)) { - $type = $extension->getType($name); - break; - } - } - - if (!$type) { - // Support fully-qualified class names - if (!class_exists($name)) { - throw new InvalidArgumentException(sprintf('Could not load type "%s": class does not exist.', $name)); - } - if (!is_subclass_of($name, FormTypeInterface::class)) { - throw new InvalidArgumentException(sprintf('Could not load type "%s": class does not implement "Symfony\Component\Form\FormTypeInterface".', $name)); - } - - $type = new $name(); - } - - $this->types[$name] = $this->resolveType($type); - } - - return $this->types[$name]; - } - - /** - * Wraps a type into a ResolvedFormTypeInterface implementation and connects it with its parent type. - */ - private function resolveType(FormTypeInterface $type): ResolvedFormTypeInterface - { - $parentType = $type->getParent(); - $fqcn = \get_class($type); - - if (isset($this->checkedTypes[$fqcn])) { - $types = implode(' > ', array_merge(array_keys($this->checkedTypes), [$fqcn])); - throw new LogicException(sprintf('Circular reference detected for form type "%s" (%s).', $fqcn, $types)); - } - - $this->checkedTypes[$fqcn] = true; - - $typeExtensions = []; - try { - foreach ($this->extensions as $extension) { - $typeExtensions[] = $extension->getTypeExtensions($fqcn); - } - - return $this->resolvedTypeFactory->createResolvedType( - $type, - array_merge([], ...$typeExtensions), - $parentType ? $this->getType($parentType) : null - ); - } finally { - unset($this->checkedTypes[$fqcn]); - } - } - - /** - * {@inheritdoc} - */ - public function hasType(string $name) - { - if (isset($this->types[$name])) { - return true; - } - - try { - $this->getType($name); - } catch (ExceptionInterface $e) { - return false; - } - - return true; - } - - /** - * {@inheritdoc} - */ - public function getTypeGuesser() - { - if (false === $this->guesser) { - $guessers = []; - - foreach ($this->extensions as $extension) { - $guesser = $extension->getTypeGuesser(); - - if ($guesser) { - $guessers[] = $guesser; - } - } - - $this->guesser = !empty($guessers) ? new FormTypeGuesserChain($guessers) : null; - } - - return $this->guesser; - } - - /** - * {@inheritdoc} - */ - public function getExtensions() - { - return $this->extensions; - } -} diff --git a/lib/symfony/form/FormRegistryInterface.php b/lib/symfony/form/FormRegistryInterface.php deleted file mode 100644 index f39174b19..000000000 --- a/lib/symfony/form/FormRegistryInterface.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -/** - * The central registry of the Form component. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface FormRegistryInterface -{ - /** - * Returns a form type by name. - * - * This methods registers the type extensions from the form extensions. - * - * @return ResolvedFormTypeInterface - * - * @throws Exception\InvalidArgumentException if the type cannot be retrieved from any extension - */ - public function getType(string $name); - - /** - * Returns whether the given form type is supported. - * - * @return bool - */ - public function hasType(string $name); - - /** - * Returns the guesser responsible for guessing types. - * - * @return FormTypeGuesserInterface|null - */ - public function getTypeGuesser(); - - /** - * Returns the extensions loaded by the framework. - * - * @return FormExtensionInterface[] - */ - public function getExtensions(); -} diff --git a/lib/symfony/form/FormRenderer.php b/lib/symfony/form/FormRenderer.php deleted file mode 100644 index 2f8f35199..000000000 --- a/lib/symfony/form/FormRenderer.php +++ /dev/null @@ -1,303 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\Form\Exception\BadMethodCallException; -use Symfony\Component\Form\Exception\LogicException; -use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; -use Twig\Environment; - -/** - * Renders a form into HTML using a rendering engine. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class FormRenderer implements FormRendererInterface -{ - public const CACHE_KEY_VAR = 'unique_block_prefix'; - - private $engine; - private $csrfTokenManager; - private $blockNameHierarchyMap = []; - private $hierarchyLevelMap = []; - private $variableStack = []; - - public function __construct(FormRendererEngineInterface $engine, CsrfTokenManagerInterface $csrfTokenManager = null) - { - $this->engine = $engine; - $this->csrfTokenManager = $csrfTokenManager; - } - - /** - * {@inheritdoc} - */ - public function getEngine() - { - return $this->engine; - } - - /** - * {@inheritdoc} - */ - public function setTheme(FormView $view, $themes, bool $useDefaultThemes = true) - { - $this->engine->setTheme($view, $themes, $useDefaultThemes); - } - - /** - * {@inheritdoc} - */ - public function renderCsrfToken(string $tokenId) - { - if (null === $this->csrfTokenManager) { - throw new BadMethodCallException('CSRF tokens can only be generated if a CsrfTokenManagerInterface is injected in FormRenderer::__construct(). Try running "composer require symfony/security-csrf".'); - } - - return $this->csrfTokenManager->getToken($tokenId)->getValue(); - } - - /** - * {@inheritdoc} - */ - public function renderBlock(FormView $view, string $blockName, array $variables = []) - { - $resource = $this->engine->getResourceForBlockName($view, $blockName); - - if (!$resource) { - throw new LogicException(sprintf('No block "%s" found while rendering the form.', $blockName)); - } - - $viewCacheKey = $view->vars[self::CACHE_KEY_VAR]; - - // The variables are cached globally for a view (instead of for the - // current suffix) - if (!isset($this->variableStack[$viewCacheKey])) { - $this->variableStack[$viewCacheKey] = []; - - // The default variable scope contains all view variables, merged with - // the variables passed explicitly to the helper - $scopeVariables = $view->vars; - - $varInit = true; - } else { - // Reuse the current scope and merge it with the explicitly passed variables - $scopeVariables = end($this->variableStack[$viewCacheKey]); - - $varInit = false; - } - - // Merge the passed with the existing attributes - if (isset($variables['attr']) && isset($scopeVariables['attr'])) { - $variables['attr'] = array_replace($scopeVariables['attr'], $variables['attr']); - } - - // Merge the passed with the exist *label* attributes - if (isset($variables['label_attr']) && isset($scopeVariables['label_attr'])) { - $variables['label_attr'] = array_replace($scopeVariables['label_attr'], $variables['label_attr']); - } - - // Do not use array_replace_recursive(), otherwise array variables - // cannot be overwritten - $variables = array_replace($scopeVariables, $variables); - - $this->variableStack[$viewCacheKey][] = $variables; - - // Do the rendering - $html = $this->engine->renderBlock($view, $resource, $blockName, $variables); - - // Clear the stack - array_pop($this->variableStack[$viewCacheKey]); - - if ($varInit) { - unset($this->variableStack[$viewCacheKey]); - } - - return $html; - } - - /** - * {@inheritdoc} - */ - public function searchAndRenderBlock(FormView $view, string $blockNameSuffix, array $variables = []) - { - $renderOnlyOnce = 'row' === $blockNameSuffix || 'widget' === $blockNameSuffix; - - if ($renderOnlyOnce && $view->isRendered()) { - // This is not allowed, because it would result in rendering same IDs multiple times, which is not valid. - throw new BadMethodCallException(sprintf('Field "%s" has already been rendered, save the result of previous render call to a variable and output that instead.', $view->vars['name'])); - } - - // The cache key for storing the variables and types - $viewCacheKey = $view->vars[self::CACHE_KEY_VAR]; - $viewAndSuffixCacheKey = $viewCacheKey.$blockNameSuffix; - - // In templates, we have to deal with two kinds of block hierarchies: - // - // +---------+ +---------+ - // | Theme B | -------> | Theme A | - // +---------+ +---------+ - // - // form_widget -------> form_widget - // ^ - // | - // choice_widget -----> choice_widget - // - // The first kind of hierarchy is the theme hierarchy. This allows to - // override the block "choice_widget" from Theme A in the extending - // Theme B. This kind of inheritance needs to be supported by the - // template engine and, for example, offers "parent()" or similar - // functions to fall back from the custom to the parent implementation. - // - // The second kind of hierarchy is the form type hierarchy. This allows - // to implement a custom "choice_widget" block (no matter in which theme), - // or to fallback to the block of the parent type, which would be - // "form_widget" in this example (again, no matter in which theme). - // If the designer wants to explicitly fallback to "form_widget" in their - // custom "choice_widget", for example because they only want to wrap - // a <div> around the original implementation, they can call the - // widget() function again to render the block for the parent type. - // - // The second kind is implemented in the following blocks. - if (!isset($this->blockNameHierarchyMap[$viewAndSuffixCacheKey])) { - // INITIAL CALL - // Calculate the hierarchy of template blocks and start on - // the bottom level of the hierarchy (= "_<id>_<section>" block) - $blockNameHierarchy = []; - foreach ($view->vars['block_prefixes'] as $blockNamePrefix) { - $blockNameHierarchy[] = $blockNamePrefix.'_'.$blockNameSuffix; - } - $hierarchyLevel = \count($blockNameHierarchy) - 1; - - $hierarchyInit = true; - } else { - // RECURSIVE CALL - // If a block recursively calls searchAndRenderBlock() again, resume rendering - // using the parent type in the hierarchy. - $blockNameHierarchy = $this->blockNameHierarchyMap[$viewAndSuffixCacheKey]; - $hierarchyLevel = $this->hierarchyLevelMap[$viewAndSuffixCacheKey] - 1; - - $hierarchyInit = false; - } - - // The variables are cached globally for a view (instead of for the - // current suffix) - if (!isset($this->variableStack[$viewCacheKey])) { - $this->variableStack[$viewCacheKey] = []; - - // The default variable scope contains all view variables, merged with - // the variables passed explicitly to the helper - $scopeVariables = $view->vars; - - $varInit = true; - } else { - // Reuse the current scope and merge it with the explicitly passed variables - $scopeVariables = end($this->variableStack[$viewCacheKey]); - - $varInit = false; - } - - // Load the resource where this block can be found - $resource = $this->engine->getResourceForBlockNameHierarchy($view, $blockNameHierarchy, $hierarchyLevel); - - // Update the current hierarchy level to the one at which the resource was - // found. For example, if looking for "choice_widget", but only a resource - // is found for its parent "form_widget", then the level is updated here - // to the parent level. - $hierarchyLevel = $this->engine->getResourceHierarchyLevel($view, $blockNameHierarchy, $hierarchyLevel); - - // The actually existing block name in $resource - $blockName = $blockNameHierarchy[$hierarchyLevel]; - - // Escape if no resource exists for this block - if (!$resource) { - if (\count($blockNameHierarchy) !== \count(array_unique($blockNameHierarchy))) { - throw new LogicException(sprintf('Unable to render the form because the block names array contains duplicates: "%s".', implode('", "', array_reverse($blockNameHierarchy)))); - } - - throw new LogicException(sprintf('Unable to render the form as none of the following blocks exist: "%s".', implode('", "', array_reverse($blockNameHierarchy)))); - } - - // Merge the passed with the existing attributes - if (isset($variables['attr']) && isset($scopeVariables['attr'])) { - $variables['attr'] = array_replace($scopeVariables['attr'], $variables['attr']); - } - - // Merge the passed with the exist *label* attributes - if (isset($variables['label_attr']) && isset($scopeVariables['label_attr'])) { - $variables['label_attr'] = array_replace($scopeVariables['label_attr'], $variables['label_attr']); - } - - // Do not use array_replace_recursive(), otherwise array variables - // cannot be overwritten - $variables = array_replace($scopeVariables, $variables); - - // In order to make recursive calls possible, we need to store the block hierarchy, - // the current level of the hierarchy and the variables so that this method can - // resume rendering one level higher of the hierarchy when it is called recursively. - // - // We need to store these values in maps (associative arrays) because within a - // call to widget() another call to widget() can be made, but for a different view - // object. These nested calls should not override each other. - $this->blockNameHierarchyMap[$viewAndSuffixCacheKey] = $blockNameHierarchy; - $this->hierarchyLevelMap[$viewAndSuffixCacheKey] = $hierarchyLevel; - - // We also need to store the variables for the view so that we can render other - // blocks for the same view using the same variables as in the outer block. - $this->variableStack[$viewCacheKey][] = $variables; - - // Do the rendering - $html = $this->engine->renderBlock($view, $resource, $blockName, $variables); - - // Clear the stack - array_pop($this->variableStack[$viewCacheKey]); - - // Clear the caches if they were filled for the first time within - // this function call - if ($hierarchyInit) { - unset($this->blockNameHierarchyMap[$viewAndSuffixCacheKey], $this->hierarchyLevelMap[$viewAndSuffixCacheKey]); - } - - if ($varInit) { - unset($this->variableStack[$viewCacheKey]); - } - - if ($renderOnlyOnce) { - $view->setRendered(); - } - - return $html; - } - - /** - * {@inheritdoc} - */ - public function humanize(string $text) - { - return ucfirst(strtolower(trim(preg_replace(['/([A-Z])/', '/[_\s]+/'], ['_$1', ' '], $text)))); - } - - /** - * @internal - */ - public function encodeCurrency(Environment $environment, string $text, string $widget = ''): string - { - if ('UTF-8' === $charset = $environment->getCharset()) { - $text = htmlspecialchars($text, \ENT_QUOTES | \ENT_SUBSTITUTE, 'UTF-8'); - } else { - $text = htmlentities($text, \ENT_QUOTES | \ENT_SUBSTITUTE, 'UTF-8'); - $text = iconv('UTF-8', $charset, $text); - $widget = iconv('UTF-8', $charset, $widget); - } - - return str_replace('{{ widget }}', $widget, $text); - } -} diff --git a/lib/symfony/form/FormRendererEngineInterface.php b/lib/symfony/form/FormRendererEngineInterface.php deleted file mode 100644 index 67b88c90c..000000000 --- a/lib/symfony/form/FormRendererEngineInterface.php +++ /dev/null @@ -1,136 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -/** - * Adapter for rendering form templates with a specific templating engine. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface FormRendererEngineInterface -{ - /** - * Sets the theme(s) to be used for rendering a view and its children. - * - * @param FormView $view The view to assign the theme(s) to - * @param mixed $themes The theme(s). The type of these themes - * is open to the implementation. - */ - public function setTheme(FormView $view, $themes, bool $useDefaultThemes = true); - - /** - * Returns the resource for a block name. - * - * The resource is first searched in the themes attached to $view, then - * in the themes of its parent view and so on, until a resource was found. - * - * The type of the resource is decided by the implementation. The resource - * is later passed to {@link renderBlock()} by the rendering algorithm. - * - * @param FormView $view The view for determining the used themes. - * First the themes attached directly to the - * view with {@link setTheme()} are considered, - * then the ones of its parent etc. - * - * @return mixed the renderer resource or false, if none was found - */ - public function getResourceForBlockName(FormView $view, string $blockName); - - /** - * Returns the resource for a block hierarchy. - * - * A block hierarchy is an array which starts with the root of the hierarchy - * and continues with the child of that root, the child of that child etc. - * The following is an example for a block hierarchy: - * - * form_widget - * text_widget - * url_widget - * - * In this example, "url_widget" is the most specific block, while the other - * blocks are its ancestors in the hierarchy. - * - * The second parameter $hierarchyLevel determines the level of the hierarchy - * that should be rendered. For example, if $hierarchyLevel is 2 for the - * above hierarchy, the engine will first look for the block "url_widget", - * then, if that does not exist, for the block "text_widget" etc. - * - * The type of the resource is decided by the implementation. The resource - * is later passed to {@link renderBlock()} by the rendering algorithm. - * - * @param FormView $view The view for determining the used themes. - * First the themes attached directly to - * the view with {@link setTheme()} are - * considered, then the ones of its parent etc. - * @param string[] $blockNameHierarchy The block name hierarchy, with the root block - * at the beginning - * @param int $hierarchyLevel The level in the hierarchy at which to start - * looking. Level 0 indicates the root block, i.e. - * the first element of $blockNameHierarchy. - * - * @return mixed The renderer resource or false, if none was found - */ - public function getResourceForBlockNameHierarchy(FormView $view, array $blockNameHierarchy, int $hierarchyLevel); - - /** - * Returns the hierarchy level at which a resource can be found. - * - * A block hierarchy is an array which starts with the root of the hierarchy - * and continues with the child of that root, the child of that child etc. - * The following is an example for a block hierarchy: - * - * form_widget - * text_widget - * url_widget - * - * The second parameter $hierarchyLevel determines the level of the hierarchy - * that should be rendered. - * - * If we call this method with the hierarchy level 2, the engine will first - * look for a resource for block "url_widget". If such a resource exists, - * the method returns 2. Otherwise it tries to find a resource for block - * "text_widget" (at level 1) and, again, returns 1 if a resource was found. - * The method continues to look for resources until the root level was - * reached and nothing was found. In this case false is returned. - * - * The type of the resource is decided by the implementation. The resource - * is later passed to {@link renderBlock()} by the rendering algorithm. - * - * @param FormView $view The view for determining the used themes. - * First the themes attached directly to - * the view with {@link setTheme()} are - * considered, then the ones of its parent etc. - * @param string[] $blockNameHierarchy The block name hierarchy, with the root block - * at the beginning - * @param int $hierarchyLevel The level in the hierarchy at which to start - * looking. Level 0 indicates the root block, i.e. - * the first element of $blockNameHierarchy. - * - * @return int|false - */ - public function getResourceHierarchyLevel(FormView $view, array $blockNameHierarchy, int $hierarchyLevel); - - /** - * Renders a block in the given renderer resource. - * - * The resource can be obtained by calling {@link getResourceForBlock()} - * or {@link getResourceForBlockHierarchy()}. The type of the resource is - * decided by the implementation. - * - * @param FormView $view The view to render - * @param mixed $resource The renderer resource - * @param array $variables The variables to pass to the template - * - * @return string - */ - public function renderBlock(FormView $view, $resource, string $blockName, array $variables = []); -} diff --git a/lib/symfony/form/FormRendererInterface.php b/lib/symfony/form/FormRendererInterface.php deleted file mode 100644 index 04af58baf..000000000 --- a/lib/symfony/form/FormRendererInterface.php +++ /dev/null @@ -1,95 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -/** - * Renders a form into HTML. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface FormRendererInterface -{ - /** - * Returns the engine used by this renderer. - * - * @return FormRendererEngineInterface - */ - public function getEngine(); - - /** - * Sets the theme(s) to be used for rendering a view and its children. - * - * @param FormView $view The view to assign the theme(s) to - * @param mixed $themes The theme(s). The type of these themes - * is open to the implementation. - * @param bool $useDefaultThemes If true, will use default themes specified - * in the renderer - */ - public function setTheme(FormView $view, $themes, bool $useDefaultThemes = true); - - /** - * Renders a named block of the form theme. - * - * @param FormView $view The view for which to render the block - * @param array $variables The variables to pass to the template - * - * @return string - */ - public function renderBlock(FormView $view, string $blockName, array $variables = []); - - /** - * Searches and renders a block for a given name suffix. - * - * The block is searched by combining the block names stored in the - * form view with the given suffix. If a block name is found, that - * block is rendered. - * - * If this method is called recursively, the block search is continued - * where a block was found before. - * - * @param FormView $view The view for which to render the block - * @param array $variables The variables to pass to the template - * - * @return string - */ - public function searchAndRenderBlock(FormView $view, string $blockNameSuffix, array $variables = []); - - /** - * Renders a CSRF token. - * - * Use this helper for CSRF protection without the overhead of creating a - * form. - * - * <input type="hidden" name="token" value="<?php $renderer->renderCsrfToken('rm_user_'.$user->getId()) ?>"> - * - * Check the token in your action using the same token ID. - * - * // $csrfProvider being an instance of Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface - * if (!$csrfProvider->isCsrfTokenValid('rm_user_'.$user->getId(), $token)) { - * throw new \RuntimeException('CSRF attack detected.'); - * } - * - * @return string - */ - public function renderCsrfToken(string $tokenId); - - /** - * Makes a technical name human readable. - * - * Sequences of underscores are replaced by single spaces. The first letter - * of the resulting string is capitalized, while all other letters are - * turned to lowercase. - * - * @return string - */ - public function humanize(string $text); -} diff --git a/lib/symfony/form/FormTypeExtensionInterface.php b/lib/symfony/form/FormTypeExtensionInterface.php deleted file mode 100644 index 6810f0ae9..000000000 --- a/lib/symfony/form/FormTypeExtensionInterface.php +++ /dev/null @@ -1,59 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\OptionsResolver\OptionsResolver; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface FormTypeExtensionInterface -{ - /** - * Builds the form. - * - * This method is called after the extended type has built the form to - * further modify it. - * - * @see FormTypeInterface::buildForm() - */ - public function buildForm(FormBuilderInterface $builder, array $options); - - /** - * Builds the view. - * - * This method is called after the extended type has built the view to - * further modify it. - * - * @see FormTypeInterface::buildView() - */ - public function buildView(FormView $view, FormInterface $form, array $options); - - /** - * Finishes the view. - * - * This method is called after the extended type has finished the view to - * further modify it. - * - * @see FormTypeInterface::finishView() - */ - public function finishView(FormView $view, FormInterface $form, array $options); - - public function configureOptions(OptionsResolver $resolver); - - /** - * Gets the extended types. - * - * @return string[] - */ - public static function getExtendedTypes(): iterable; -} diff --git a/lib/symfony/form/FormTypeGuesserChain.php b/lib/symfony/form/FormTypeGuesserChain.php deleted file mode 100644 index 2763d9081..000000000 --- a/lib/symfony/form/FormTypeGuesserChain.php +++ /dev/null @@ -1,103 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\Form\Exception\UnexpectedTypeException; -use Symfony\Component\Form\Guess\Guess; - -class FormTypeGuesserChain implements FormTypeGuesserInterface -{ - private $guessers = []; - - /** - * @param FormTypeGuesserInterface[] $guessers - * - * @throws UnexpectedTypeException if any guesser does not implement FormTypeGuesserInterface - */ - public function __construct(iterable $guessers) - { - $tmpGuessers = []; - foreach ($guessers as $guesser) { - if (!$guesser instanceof FormTypeGuesserInterface) { - throw new UnexpectedTypeException($guesser, FormTypeGuesserInterface::class); - } - - if ($guesser instanceof self) { - $tmpGuessers[] = $guesser->guessers; - } else { - $tmpGuessers[] = [$guesser]; - } - } - - $this->guessers = array_merge([], ...$tmpGuessers); - } - - /** - * {@inheritdoc} - */ - public function guessType(string $class, string $property) - { - return $this->guess(function ($guesser) use ($class, $property) { - return $guesser->guessType($class, $property); - }); - } - - /** - * {@inheritdoc} - */ - public function guessRequired(string $class, string $property) - { - return $this->guess(function ($guesser) use ($class, $property) { - return $guesser->guessRequired($class, $property); - }); - } - - /** - * {@inheritdoc} - */ - public function guessMaxLength(string $class, string $property) - { - return $this->guess(function ($guesser) use ($class, $property) { - return $guesser->guessMaxLength($class, $property); - }); - } - - /** - * {@inheritdoc} - */ - public function guessPattern(string $class, string $property) - { - return $this->guess(function ($guesser) use ($class, $property) { - return $guesser->guessPattern($class, $property); - }); - } - - /** - * Executes a closure for each guesser and returns the best guess from the - * return values. - * - * @param \Closure $closure The closure to execute. Accepts a guesser - * as argument and should return a Guess instance - */ - private function guess(\Closure $closure): ?Guess - { - $guesses = []; - - foreach ($this->guessers as $guesser) { - if ($guess = $closure($guesser)) { - $guesses[] = $guess; - } - } - - return Guess::getBestGuess($guesses); - } -} diff --git a/lib/symfony/form/FormTypeGuesserInterface.php b/lib/symfony/form/FormTypeGuesserInterface.php deleted file mode 100644 index 61e2c5f80..000000000 --- a/lib/symfony/form/FormTypeGuesserInterface.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface FormTypeGuesserInterface -{ - /** - * Returns a field guess for a property name of a class. - * - * @return Guess\TypeGuess|null - */ - public function guessType(string $class, string $property); - - /** - * Returns a guess whether a property of a class is required. - * - * @return Guess\ValueGuess|null - */ - public function guessRequired(string $class, string $property); - - /** - * Returns a guess about the field's maximum length. - * - * @return Guess\ValueGuess|null - */ - public function guessMaxLength(string $class, string $property); - - /** - * Returns a guess about the field's pattern. - * - * - When you have a min value, you guess a min length of this min (LOW_CONFIDENCE) - * - Then line below, if this value is a float type, this is wrong so you guess null with MEDIUM_CONFIDENCE to override the previous guess. - * Example: - * You want a float greater than 5, 4.512313 is not valid but length(4.512314) > length(5) - * - * @see https://github.com/symfony/symfony/pull/3927 - * - * @return Guess\ValueGuess|null - */ - public function guessPattern(string $class, string $property); -} diff --git a/lib/symfony/form/FormTypeInterface.php b/lib/symfony/form/FormTypeInterface.php deleted file mode 100644 index 2b9066a51..000000000 --- a/lib/symfony/form/FormTypeInterface.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\OptionsResolver\OptionsResolver; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface FormTypeInterface -{ - /** - * Builds the form. - * - * This method is called for each type in the hierarchy starting from the - * top most type. Type extensions can further modify the form. - * - * @param array<string, mixed> $options - * - * @see FormTypeExtensionInterface::buildForm() - */ - public function buildForm(FormBuilderInterface $builder, array $options); - - /** - * Builds the form view. - * - * This method is called for each type in the hierarchy starting from the - * top most type. Type extensions can further modify the view. - * - * A view of a form is built before the views of the child forms are built. - * This means that you cannot access child views in this method. If you need - * to do so, move your logic to {@link finishView()} instead. - * - * @param array<string, mixed> $options - * - * @see FormTypeExtensionInterface::buildView() - */ - public function buildView(FormView $view, FormInterface $form, array $options); - - /** - * Finishes the form view. - * - * This method gets called for each type in the hierarchy starting from the - * top most type. Type extensions can further modify the view. - * - * When this method is called, views of the form's children have already - * been built and finished and can be accessed. You should only implement - * such logic in this method that actually accesses child views. For everything - * else you are recommended to implement {@link buildView()} instead. - * - * @param array<string, mixed> $options - * - * @see FormTypeExtensionInterface::finishView() - */ - public function finishView(FormView $view, FormInterface $form, array $options); - - /** - * Configures the options for this type. - */ - public function configureOptions(OptionsResolver $resolver); - - /** - * Returns the prefix of the template block name for this type. - * - * The block prefix defaults to the underscored short class name with - * the "Type" suffix removed (e.g. "UserProfileType" => "user_profile"). - * - * @return string - */ - public function getBlockPrefix(); - - /** - * Returns the name of the parent type. - * - * @return string|null - */ - public function getParent(); -} diff --git a/lib/symfony/form/FormView.php b/lib/symfony/form/FormView.php deleted file mode 100644 index 0162208e6..000000000 --- a/lib/symfony/form/FormView.php +++ /dev/null @@ -1,180 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\Form\Exception\BadMethodCallException; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @implements \ArrayAccess<int|string, FormView> - * @implements \IteratorAggregate<int|string, FormView> - */ -class FormView implements \ArrayAccess, \IteratorAggregate, \Countable -{ - /** - * The variables assigned to this view. - */ - public $vars = [ - 'value' => null, - 'attr' => [], - ]; - - /** - * The parent view. - */ - public $parent; - - /** - * The child views. - * - * @var array<int|string, FormView> - */ - public $children = []; - - /** - * Is the form attached to this renderer rendered? - * - * Rendering happens when either the widget or the row method was called. - * Row implicitly includes widget, however certain rendering mechanisms - * have to skip widget rendering when a row is rendered. - * - * @var bool - */ - private $rendered = false; - - private $methodRendered = false; - - public function __construct(self $parent = null) - { - $this->parent = $parent; - } - - /** - * Returns whether the view was already rendered. - * - * @return bool - */ - public function isRendered() - { - if (true === $this->rendered || 0 === \count($this->children)) { - return $this->rendered; - } - - foreach ($this->children as $child) { - if (!$child->isRendered()) { - return false; - } - } - - return $this->rendered = true; - } - - /** - * Marks the view as rendered. - * - * @return $this - */ - public function setRendered() - { - $this->rendered = true; - - return $this; - } - - /** - * @return bool - */ - public function isMethodRendered() - { - return $this->methodRendered; - } - - public function setMethodRendered() - { - $this->methodRendered = true; - } - - /** - * Returns a child by name (implements \ArrayAccess). - * - * @param int|string $name The child name - * - * @return self - */ - #[\ReturnTypeWillChange] - public function offsetGet($name) - { - return $this->children[$name]; - } - - /** - * Returns whether the given child exists (implements \ArrayAccess). - * - * @param int|string $name The child name - * - * @return bool - */ - #[\ReturnTypeWillChange] - public function offsetExists($name) - { - return isset($this->children[$name]); - } - - /** - * Implements \ArrayAccess. - * - * @return void - * - * @throws BadMethodCallException always as setting a child by name is not allowed - */ - #[\ReturnTypeWillChange] - public function offsetSet($name, $value) - { - throw new BadMethodCallException('Not supported.'); - } - - /** - * Removes a child (implements \ArrayAccess). - * - * @param int|string $name The child name - * - * @return void - */ - #[\ReturnTypeWillChange] - public function offsetUnset($name) - { - unset($this->children[$name]); - } - - /** - * Returns an iterator to iterate over children (implements \IteratorAggregate). - * - * @return \ArrayIterator<int|string, FormView> - */ - #[\ReturnTypeWillChange] - public function getIterator() - { - return new \ArrayIterator($this->children); - } - - /** - * Implements \Countable. - * - * @return int - */ - #[\ReturnTypeWillChange] - public function count() - { - return \count($this->children); - } -} diff --git a/lib/symfony/form/Forms.php b/lib/symfony/form/Forms.php deleted file mode 100644 index 020e75eff..000000000 --- a/lib/symfony/form/Forms.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -/** - * Entry point of the Form component. - * - * Use this class to conveniently create new form factories: - * - * use Symfony\Component\Form\Forms; - * - * $formFactory = Forms::createFormFactory(); - * - * $form = $formFactory->createBuilder() - * ->add('firstName', 'Symfony\Component\Form\Extension\Core\Type\TextType') - * ->add('lastName', 'Symfony\Component\Form\Extension\Core\Type\TextType') - * ->add('age', 'Symfony\Component\Form\Extension\Core\Type\IntegerType') - * ->add('color', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', [ - * 'choices' => ['Red' => 'r', 'Blue' => 'b'], - * ]) - * ->getForm(); - * - * You can also add custom extensions to the form factory: - * - * $formFactory = Forms::createFormFactoryBuilder() - * ->addExtension(new AcmeExtension()) - * ->getFormFactory(); - * - * If you create custom form types or type extensions, it is - * generally recommended to create your own extensions that lazily - * load these types and type extensions. In projects where performance - * does not matter that much, you can also pass them directly to the - * form factory: - * - * $formFactory = Forms::createFormFactoryBuilder() - * ->addType(new PersonType()) - * ->addType(new PhoneNumberType()) - * ->addTypeExtension(new FormTypeHelpTextExtension()) - * ->getFormFactory(); - * - * Support for the Validator component is provided by ValidatorExtension. - * This extension needs a validator object to function properly: - * - * use Symfony\Component\Validator\Validation; - * use Symfony\Component\Form\Extension\Validator\ValidatorExtension; - * - * $validator = Validation::createValidator(); - * $formFactory = Forms::createFormFactoryBuilder() - * ->addExtension(new ValidatorExtension($validator)) - * ->getFormFactory(); - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -final class Forms -{ - /** - * Creates a form factory with the default configuration. - */ - public static function createFormFactory(): FormFactoryInterface - { - return self::createFormFactoryBuilder()->getFormFactory(); - } - - /** - * Creates a form factory builder with the default configuration. - */ - public static function createFormFactoryBuilder(): FormFactoryBuilderInterface - { - return new FormFactoryBuilder(true); - } - - /** - * This class cannot be instantiated. - */ - private function __construct() - { - } -} diff --git a/lib/symfony/form/Guess/Guess.php b/lib/symfony/form/Guess/Guess.php deleted file mode 100644 index 935bbfea1..000000000 --- a/lib/symfony/form/Guess/Guess.php +++ /dev/null @@ -1,105 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Guess; - -use Symfony\Component\Form\Exception\InvalidArgumentException; - -/** - * Base class for guesses made by TypeGuesserInterface implementation. - * - * Each instance contains a confidence value about the correctness of the guess. - * Thus an instance with confidence HIGH_CONFIDENCE is more likely to be - * correct than an instance with confidence LOW_CONFIDENCE. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -abstract class Guess -{ - /** - * Marks an instance with a value that is extremely likely to be correct. - */ - public const VERY_HIGH_CONFIDENCE = 3; - - /** - * Marks an instance with a value that is very likely to be correct. - */ - public const HIGH_CONFIDENCE = 2; - - /** - * Marks an instance with a value that is likely to be correct. - */ - public const MEDIUM_CONFIDENCE = 1; - - /** - * Marks an instance with a value that may be correct. - */ - public const LOW_CONFIDENCE = 0; - - /** - * The confidence about the correctness of the value. - * - * One of VERY_HIGH_CONFIDENCE, HIGH_CONFIDENCE, MEDIUM_CONFIDENCE - * and LOW_CONFIDENCE. - * - * @var int - */ - private $confidence; - - /** - * Returns the guess most likely to be correct from a list of guesses. - * - * If there are multiple guesses with the same, highest confidence, the - * returned guess is any of them. - * - * @param static[] $guesses An array of guesses - * - * @return static|null - */ - public static function getBestGuess(array $guesses) - { - $result = null; - $maxConfidence = -1; - - foreach ($guesses as $guess) { - if ($maxConfidence < $confidence = $guess->getConfidence()) { - $maxConfidence = $confidence; - $result = $guess; - } - } - - return $result; - } - - /** - * @throws InvalidArgumentException if the given value of confidence is unknown - */ - public function __construct(int $confidence) - { - if (self::VERY_HIGH_CONFIDENCE !== $confidence && self::HIGH_CONFIDENCE !== $confidence && - self::MEDIUM_CONFIDENCE !== $confidence && self::LOW_CONFIDENCE !== $confidence) { - throw new InvalidArgumentException('The confidence should be one of the constants defined in Guess.'); - } - - $this->confidence = $confidence; - } - - /** - * Returns the confidence that the guessed value is correct. - * - * @return int One of the constants VERY_HIGH_CONFIDENCE, HIGH_CONFIDENCE, - * MEDIUM_CONFIDENCE and LOW_CONFIDENCE - */ - public function getConfidence() - { - return $this->confidence; - } -} diff --git a/lib/symfony/form/Guess/TypeGuess.php b/lib/symfony/form/Guess/TypeGuess.php deleted file mode 100644 index ff0c6a749..000000000 --- a/lib/symfony/form/Guess/TypeGuess.php +++ /dev/null @@ -1,59 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Guess; - -/** - * Contains a guessed class name and a list of options for creating an instance - * of that class. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class TypeGuess extends Guess -{ - private $type; - private $options; - - /** - * @param string $type The guessed field type - * @param array $options The options for creating instances of the - * guessed class - * @param int $confidence The confidence that the guessed class name - * is correct - */ - public function __construct(string $type, array $options, int $confidence) - { - parent::__construct($confidence); - - $this->type = $type; - $this->options = $options; - } - - /** - * Returns the guessed field type. - * - * @return string - */ - public function getType() - { - return $this->type; - } - - /** - * Returns the guessed options for creating instances of the guessed type. - * - * @return array - */ - public function getOptions() - { - return $this->options; - } -} diff --git a/lib/symfony/form/Guess/ValueGuess.php b/lib/symfony/form/Guess/ValueGuess.php deleted file mode 100644 index fe19dfeb0..000000000 --- a/lib/symfony/form/Guess/ValueGuess.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Guess; - -/** - * Contains a guessed value. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class ValueGuess extends Guess -{ - private $value; - - /** - * @param string|int|bool|null $value The guessed value - * @param int $confidence The confidence that the guessed class name - * is correct - */ - public function __construct($value, int $confidence) - { - parent::__construct($confidence); - - $this->value = $value; - } - - /** - * Returns the guessed value. - * - * @return string|int|bool|null - */ - public function getValue() - { - return $this->value; - } -} diff --git a/lib/symfony/form/LICENSE b/lib/symfony/form/LICENSE deleted file mode 100644 index 008370457..000000000 --- a/lib/symfony/form/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -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/lib/symfony/form/NativeRequestHandler.php b/lib/symfony/form/NativeRequestHandler.php deleted file mode 100644 index 7b39ad3a1..000000000 --- a/lib/symfony/form/NativeRequestHandler.php +++ /dev/null @@ -1,256 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\Form\Exception\UnexpectedTypeException; -use Symfony\Component\Form\Util\ServerParams; - -/** - * A request handler using PHP super globals $_GET, $_POST and $_SERVER. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class NativeRequestHandler implements RequestHandlerInterface -{ - private $serverParams; - - /** - * The allowed keys of the $_FILES array. - */ - private const FILE_KEYS = [ - 'error', - 'name', - 'size', - 'tmp_name', - 'type', - ]; - - public function __construct(ServerParams $params = null) - { - $this->serverParams = $params ?? new ServerParams(); - } - - /** - * {@inheritdoc} - * - * @throws Exception\UnexpectedTypeException If the $request is not null - */ - public function handleRequest(FormInterface $form, $request = null) - { - if (null !== $request) { - throw new UnexpectedTypeException($request, 'null'); - } - - $name = $form->getName(); - $method = $form->getConfig()->getMethod(); - - if ($method !== self::getRequestMethod()) { - return; - } - - // For request methods that must not have a request body we fetch data - // from the query string. Otherwise we look for data in the request body. - if ('GET' === $method || 'HEAD' === $method || 'TRACE' === $method) { - if ('' === $name) { - $data = $_GET; - } else { - // Don't submit GET requests if the form's name does not exist - // in the request - if (!isset($_GET[$name])) { - return; - } - - $data = $_GET[$name]; - } - } else { - // Mark the form with an error if the uploaded size was too large - // This is done here and not in FormValidator because $_POST is - // empty when that error occurs. Hence the form is never submitted. - if ($this->serverParams->hasPostMaxSizeBeenExceeded()) { - // Submit the form, but don't clear the default values - $form->submit(null, false); - - $form->addError(new FormError( - $form->getConfig()->getOption('upload_max_size_message')(), - null, - ['{{ max }}' => $this->serverParams->getNormalizedIniPostMaxSize()] - )); - - return; - } - - $fixedFiles = []; - foreach ($_FILES as $fileKey => $file) { - $fixedFiles[$fileKey] = self::stripEmptyFiles(self::fixPhpFilesArray($file)); - } - - if ('' === $name) { - $params = $_POST; - $files = $fixedFiles; - } elseif (\array_key_exists($name, $_POST) || \array_key_exists($name, $fixedFiles)) { - $default = $form->getConfig()->getCompound() ? [] : null; - $params = \array_key_exists($name, $_POST) ? $_POST[$name] : $default; - $files = \array_key_exists($name, $fixedFiles) ? $fixedFiles[$name] : $default; - } else { - // Don't submit the form if it is not present in the request - return; - } - - if (\is_array($params) && \is_array($files)) { - $data = array_replace_recursive($params, $files); - } else { - $data = $params ?: $files; - } - } - - // Don't auto-submit the form unless at least one field is present. - if ('' === $name && \count(array_intersect_key($data, $form->all())) <= 0) { - return; - } - - if (\is_array($data) && \array_key_exists('_method', $data) && $method === $data['_method'] && !$form->has('_method')) { - unset($data['_method']); - } - - $form->submit($data, 'PATCH' !== $method); - } - - /** - * {@inheritdoc} - */ - public function isFileUpload($data) - { - // POST data will always be strings or arrays of strings. Thus, we can be sure - // that the submitted data is a file upload if the "error" value is an integer - // (this value must have been injected by PHP itself). - return \is_array($data) && isset($data['error']) && \is_int($data['error']); - } - - /** - * @return int|null - */ - public function getUploadFileError($data) - { - if (!\is_array($data)) { - return null; - } - - if (!isset($data['error'])) { - return null; - } - - if (!\is_int($data['error'])) { - return null; - } - - if (\UPLOAD_ERR_OK === $data['error']) { - return null; - } - - return $data['error']; - } - - /** - * Returns the method used to submit the request to the server. - */ - private static function getRequestMethod(): string - { - $method = isset($_SERVER['REQUEST_METHOD']) - ? strtoupper($_SERVER['REQUEST_METHOD']) - : 'GET'; - - if ('POST' === $method && isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) { - $method = strtoupper($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']); - } - - return $method; - } - - /** - * Fixes a malformed PHP $_FILES array. - * - * PHP has a bug that the format of the $_FILES array differs, depending on - * whether the uploaded file fields had normal field names or array-like - * field names ("normal" vs. "parent[child]"). - * - * This method fixes the array to look like the "normal" $_FILES array. - * - * It's safe to pass an already converted array, in which case this method - * just returns the original array unmodified. - * - * This method is identical to {@link \Symfony\Component\HttpFoundation\FileBag::fixPhpFilesArray} - * and should be kept as such in order to port fixes quickly and easily. - * - * @return mixed - */ - private static function fixPhpFilesArray($data) - { - if (!\is_array($data)) { - return $data; - } - - // Remove extra key added by PHP 8.1. - unset($data['full_path']); - $keys = array_keys($data); - sort($keys); - - if (self::FILE_KEYS !== $keys || !isset($data['name']) || !\is_array($data['name'])) { - return $data; - } - - $files = $data; - foreach (self::FILE_KEYS as $k) { - unset($files[$k]); - } - - foreach ($data['name'] as $key => $name) { - $files[$key] = self::fixPhpFilesArray([ - 'error' => $data['error'][$key], - 'name' => $name, - 'type' => $data['type'][$key], - 'tmp_name' => $data['tmp_name'][$key], - 'size' => $data['size'][$key], - ]); - } - - return $files; - } - - /** - * Sets empty uploaded files to NULL in the given uploaded files array. - * - * @return mixed - */ - private static function stripEmptyFiles($data) - { - if (!\is_array($data)) { - return $data; - } - - $keys = array_keys($data); - sort($keys); - - if (self::FILE_KEYS === $keys) { - if (\UPLOAD_ERR_NO_FILE === $data['error']) { - return null; - } - - return $data; - } - - foreach ($data as $key => $value) { - $data[$key] = self::stripEmptyFiles($value); - } - - return $data; - } -} diff --git a/lib/symfony/form/PreloadedExtension.php b/lib/symfony/form/PreloadedExtension.php deleted file mode 100644 index c6767dc3e..000000000 --- a/lib/symfony/form/PreloadedExtension.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\Form\Exception\InvalidArgumentException; - -/** - * A form extension with preloaded types, type extensions and type guessers. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class PreloadedExtension implements FormExtensionInterface -{ - private $types = []; - private $typeExtensions = []; - private $typeGuesser; - - /** - * Creates a new preloaded extension. - * - * @param FormTypeInterface[] $types The types that the extension should support - * @param FormTypeExtensionInterface[][] $typeExtensions The type extensions that the extension should support - */ - public function __construct(array $types, array $typeExtensions, FormTypeGuesserInterface $typeGuesser = null) - { - $this->typeExtensions = $typeExtensions; - $this->typeGuesser = $typeGuesser; - - foreach ($types as $type) { - $this->types[\get_class($type)] = $type; - } - } - - /** - * {@inheritdoc} - */ - public function getType(string $name) - { - if (!isset($this->types[$name])) { - throw new InvalidArgumentException(sprintf('The type "%s" cannot be loaded by this extension.', $name)); - } - - return $this->types[$name]; - } - - /** - * {@inheritdoc} - */ - public function hasType(string $name) - { - return isset($this->types[$name]); - } - - /** - * {@inheritdoc} - */ - public function getTypeExtensions(string $name) - { - return $this->typeExtensions[$name] - ?? []; - } - - /** - * {@inheritdoc} - */ - public function hasTypeExtensions(string $name) - { - return !empty($this->typeExtensions[$name]); - } - - /** - * {@inheritdoc} - */ - public function getTypeGuesser() - { - return $this->typeGuesser; - } -} diff --git a/lib/symfony/form/README.md b/lib/symfony/form/README.md deleted file mode 100644 index 0cda654d7..000000000 --- a/lib/symfony/form/README.md +++ /dev/null @@ -1,13 +0,0 @@ -Form Component -============== - -The Form component allows you to easily create, process and reuse HTML forms. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/form.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/lib/symfony/form/RequestHandlerInterface.php b/lib/symfony/form/RequestHandlerInterface.php deleted file mode 100644 index 65d86e224..000000000 --- a/lib/symfony/form/RequestHandlerInterface.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -/** - * Submits forms if they were submitted. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface RequestHandlerInterface -{ - /** - * Submits a form if it was submitted. - * - * @param mixed $request The current request - */ - public function handleRequest(FormInterface $form, $request = null); - - /** - * Returns true if the given data is a file upload. - * - * @param mixed $data The form field data - * - * @return bool - */ - public function isFileUpload($data); -} diff --git a/lib/symfony/form/ResolvedFormType.php b/lib/symfony/form/ResolvedFormType.php deleted file mode 100644 index b484c9149..000000000 --- a/lib/symfony/form/ResolvedFormType.php +++ /dev/null @@ -1,224 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\EventDispatcher\EventDispatcher; -use Symfony\Component\Form\Exception\UnexpectedTypeException; -use Symfony\Component\OptionsResolver\Exception\ExceptionInterface; -use Symfony\Component\OptionsResolver\OptionsResolver; - -/** - * A wrapper for a form type and its extensions. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class ResolvedFormType implements ResolvedFormTypeInterface -{ - /** - * @var FormTypeInterface - */ - private $innerType; - - /** - * @var FormTypeExtensionInterface[] - */ - private $typeExtensions; - - /** - * @var ResolvedFormTypeInterface|null - */ - private $parent; - - /** - * @var OptionsResolver - */ - private $optionsResolver; - - /** - * @param FormTypeExtensionInterface[] $typeExtensions - */ - public function __construct(FormTypeInterface $innerType, array $typeExtensions = [], ResolvedFormTypeInterface $parent = null) - { - foreach ($typeExtensions as $extension) { - if (!$extension instanceof FormTypeExtensionInterface) { - throw new UnexpectedTypeException($extension, FormTypeExtensionInterface::class); - } - } - - $this->innerType = $innerType; - $this->typeExtensions = $typeExtensions; - $this->parent = $parent; - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return $this->innerType->getBlockPrefix(); - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - return $this->parent; - } - - /** - * {@inheritdoc} - */ - public function getInnerType() - { - return $this->innerType; - } - - /** - * {@inheritdoc} - */ - public function getTypeExtensions() - { - return $this->typeExtensions; - } - - /** - * {@inheritdoc} - */ - public function createBuilder(FormFactoryInterface $factory, string $name, array $options = []) - { - try { - $options = $this->getOptionsResolver()->resolve($options); - } catch (ExceptionInterface $e) { - throw new $e(sprintf('An error has occurred resolving the options of the form "%s": ', get_debug_type($this->getInnerType())).$e->getMessage(), $e->getCode(), $e); - } - - // Should be decoupled from the specific option at some point - $dataClass = $options['data_class'] ?? null; - - $builder = $this->newBuilder($name, $dataClass, $factory, $options); - $builder->setType($this); - - return $builder; - } - - /** - * {@inheritdoc} - */ - public function createView(FormInterface $form, FormView $parent = null) - { - return $this->newView($parent); - } - - /** - * {@inheritdoc} - */ - public function buildForm(FormBuilderInterface $builder, array $options) - { - if (null !== $this->parent) { - $this->parent->buildForm($builder, $options); - } - - $this->innerType->buildForm($builder, $options); - - foreach ($this->typeExtensions as $extension) { - $extension->buildForm($builder, $options); - } - } - - /** - * {@inheritdoc} - */ - public function buildView(FormView $view, FormInterface $form, array $options) - { - if (null !== $this->parent) { - $this->parent->buildView($view, $form, $options); - } - - $this->innerType->buildView($view, $form, $options); - - foreach ($this->typeExtensions as $extension) { - $extension->buildView($view, $form, $options); - } - } - - /** - * {@inheritdoc} - */ - public function finishView(FormView $view, FormInterface $form, array $options) - { - if (null !== $this->parent) { - $this->parent->finishView($view, $form, $options); - } - - $this->innerType->finishView($view, $form, $options); - - foreach ($this->typeExtensions as $extension) { - /* @var FormTypeExtensionInterface $extension */ - $extension->finishView($view, $form, $options); - } - } - - /** - * {@inheritdoc} - */ - public function getOptionsResolver() - { - if (null === $this->optionsResolver) { - if (null !== $this->parent) { - $this->optionsResolver = clone $this->parent->getOptionsResolver(); - } else { - $this->optionsResolver = new OptionsResolver(); - } - - $this->innerType->configureOptions($this->optionsResolver); - - foreach ($this->typeExtensions as $extension) { - $extension->configureOptions($this->optionsResolver); - } - } - - return $this->optionsResolver; - } - - /** - * Creates a new builder instance. - * - * Override this method if you want to customize the builder class. - * - * @return FormBuilderInterface - */ - protected function newBuilder(string $name, ?string $dataClass, FormFactoryInterface $factory, array $options) - { - if ($this->innerType instanceof ButtonTypeInterface) { - return new ButtonBuilder($name, $options); - } - - if ($this->innerType instanceof SubmitButtonTypeInterface) { - return new SubmitButtonBuilder($name, $options); - } - - return new FormBuilder($name, $dataClass, new EventDispatcher(), $factory, $options); - } - - /** - * Creates a new view instance. - * - * Override this method if you want to customize the view class. - * - * @return FormView - */ - protected function newView(FormView $parent = null) - { - return new FormView($parent); - } -} diff --git a/lib/symfony/form/ResolvedFormTypeFactory.php b/lib/symfony/form/ResolvedFormTypeFactory.php deleted file mode 100644 index d93d1c06d..000000000 --- a/lib/symfony/form/ResolvedFormTypeFactory.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class ResolvedFormTypeFactory implements ResolvedFormTypeFactoryInterface -{ - /** - * {@inheritdoc} - */ - public function createResolvedType(FormTypeInterface $type, array $typeExtensions, ResolvedFormTypeInterface $parent = null) - { - return new ResolvedFormType($type, $typeExtensions, $parent); - } -} diff --git a/lib/symfony/form/ResolvedFormTypeFactoryInterface.php b/lib/symfony/form/ResolvedFormTypeFactoryInterface.php deleted file mode 100644 index 4f133e039..000000000 --- a/lib/symfony/form/ResolvedFormTypeFactoryInterface.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -/** - * Creates ResolvedFormTypeInterface instances. - * - * This interface allows you to use your custom ResolvedFormTypeInterface - * implementation, within which you can customize the concrete FormBuilderInterface - * implementations or FormView subclasses that are used by the framework. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface ResolvedFormTypeFactoryInterface -{ - /** - * Resolves a form type. - * - * @param FormTypeExtensionInterface[] $typeExtensions - * - * @return ResolvedFormTypeInterface - * - * @throws Exception\UnexpectedTypeException if the types parent {@link FormTypeInterface::getParent()} is not a string - * @throws Exception\InvalidArgumentException if the types parent cannot be retrieved from any extension - */ - public function createResolvedType(FormTypeInterface $type, array $typeExtensions, ResolvedFormTypeInterface $parent = null); -} diff --git a/lib/symfony/form/ResolvedFormTypeInterface.php b/lib/symfony/form/ResolvedFormTypeInterface.php deleted file mode 100644 index 6074af9cb..000000000 --- a/lib/symfony/form/ResolvedFormTypeInterface.php +++ /dev/null @@ -1,92 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -use Symfony\Component\OptionsResolver\OptionsResolver; - -/** - * A wrapper for a form type and its extensions. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface ResolvedFormTypeInterface -{ - /** - * Returns the prefix of the template block name for this type. - * - * @return string - */ - public function getBlockPrefix(); - - /** - * Returns the parent type. - * - * @return self|null - */ - public function getParent(); - - /** - * Returns the wrapped form type. - * - * @return FormTypeInterface - */ - public function getInnerType(); - - /** - * Returns the extensions of the wrapped form type. - * - * @return FormTypeExtensionInterface[] - */ - public function getTypeExtensions(); - - /** - * Creates a new form builder for this type. - * - * @param string $name The name for the builder - * - * @return FormBuilderInterface - */ - public function createBuilder(FormFactoryInterface $factory, string $name, array $options = []); - - /** - * Creates a new form view for a form of this type. - * - * @return FormView - */ - public function createView(FormInterface $form, FormView $parent = null); - - /** - * Configures a form builder for the type hierarchy. - */ - public function buildForm(FormBuilderInterface $builder, array $options); - - /** - * Configures a form view for the type hierarchy. - * - * It is called before the children of the view are built. - */ - public function buildView(FormView $view, FormInterface $form, array $options); - - /** - * Finishes a form view for the type hierarchy. - * - * It is called after the children of the view have been built. - */ - public function finishView(FormView $view, FormInterface $form, array $options); - - /** - * Returns the configured options resolver used for this type. - * - * @return OptionsResolver - */ - public function getOptionsResolver(); -} diff --git a/lib/symfony/form/Resources/config/validation.xml b/lib/symfony/form/Resources/config/validation.xml deleted file mode 100644 index 918f101f4..000000000 --- a/lib/symfony/form/Resources/config/validation.xml +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" ?> - -<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping https://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd"> - - <class name="Symfony\Component\Form\Form"> - <constraint name="Symfony\Component\Form\Extension\Validator\Constraints\Form" /> - <constraint name="Symfony\Component\Validator\Constraints\Traverse"> - <option name="traverse">false</option> - </constraint> - </class> -</constraint-mapping> diff --git a/lib/symfony/form/Resources/translations/validators.af.xlf b/lib/symfony/form/Resources/translations/validators.af.xlf deleted file mode 100644 index 58cd939cf..000000000 --- a/lib/symfony/form/Resources/translations/validators.af.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Hierdie vorm moet nie ekstra velde bevat nie.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Die opgelaaide lêer was te groot. Probeer asseblief 'n kleiner lêer.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>Die CSRF-teken is ongeldig. Probeer asseblief om die vorm weer in te dien.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Hierdie waarde is nie 'n geldige HTML5 kleur nie.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Voer asseblief 'n geldige geboortedatum in.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Die gekiesde opsie is nie geldig nie.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Die versameling is nie geldig nie.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Kies asseblief 'n geldige kleur.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Kies asseblief 'n geldige land.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Kies asseblief 'n geldige geldeenheid.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Kies asseblief 'n geldige datum interval.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Voer asseblilef 'n geldige datum en tyd in.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Voer asseblief 'n geldige datum in.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Kies asseblief 'n geldige lêer.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Die versteekte veld is nie geldig nie.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Voer asseblief 'n geldige heeltal in.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Kies assblief 'n geldige taal.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Voer assebliefn 'n geldige locale in.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Voer asseblief 'n geldige bedrag in.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Voer asseblief 'n nommer in.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Die wagwoord is ongeldig.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Voer asseblief 'n geldige persentasie waarde in.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Die waardes is nie dieselfde nie.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Voer asseblief 'n geldige tyd in time.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Kies asseblief 'n geldige tydsone.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Voer asseblief 'n geldige URL in.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Voer asseblief 'n geldige soek term in.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Verskaf asseblief 'n geldige telefoonnommer.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Die blokkie het 'n ongeldige waarde.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Voer asseblief 'n geldige e-pos adres in.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Kies asseblief 'n geldige opsie.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Kies asseblief 'n geldige reeks.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Voer assblief 'n geldige week in.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.ar.xlf b/lib/symfony/form/Resources/translations/validators.ar.xlf deleted file mode 100644 index e30daaf1d..000000000 --- a/lib/symfony/form/Resources/translations/validators.ar.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>هذا النموذج يجب الا يحتوى على اى حقول اضافية.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>مساحة الملف المرسل كبيرة. من فضلك حاول ارسال ملف اصغر.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>قيمة رمز الموقع غير صحيحة. من فضلك اعد ارسال النموذج.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>هذه القيمة ليست لون HTML5 صالحًا.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>الرجاء ادخال تاريخ ميلاد صالح.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>الاختيار المحدد غير صالح.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>المجموعة غير صالحة.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>الرجاء اختيار لون صالح.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>الرجاء اختيار بلد صالح.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>الرجاء اختيار عملة صالحة.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>الرجاء اختيار فاصل زمني صالح.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>الرجاء إدخال تاريخ ووقت صالحين.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>الرجاء إدخال تاريخ صالح.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>الرجاء اختيار ملف صالح.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>الحقل المخفي غير صالح.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>الرجاء إدخال عدد صحيح.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>الرجاء اختيار لغة صالحة.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>الرجاء اختيار لغة صالحة.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>الرجاء إدخال مبلغ مالي صالح.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>الرجاء إدخال رقم.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>كلمة المرور غير صحيحة.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>الرجاء إدخال قيمة النسبة المئوية.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>القيم لا تتطابق.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>الرجاء إدخال وقت صالح.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>الرجاء تحديد منطقة زمنية صالحة.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>أدخل عنوان الرابط صحيح من فضلك.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>الرجاء إدخال مصطلح البحث ساري المفعول.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>يرجى تقديم رقم هاتف صالح.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>خانة الاختيار لها قيمة غير صالحة.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>رجاء قم بإدخال بريد الكتروني صحيح</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>الرجاء تحديد خيار صالح.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>يرجى تحديد نطاق صالح.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>الرجاء إدخال أسبوع صالح.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.az.xlf b/lib/symfony/form/Resources/translations/validators.az.xlf deleted file mode 100644 index b9269706d..000000000 --- a/lib/symfony/form/Resources/translations/validators.az.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Bu formada əlavə sahə olmamalıdır.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Yüklənən fayl çox böyükdür. Lütfən daha kiçik fayl yükləyin.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF nişanı yanlışdır. Lütfen formanı yenidən göndərin.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Bu dəyər doğru bir HTML5 rəngi deyil.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Zəhmət olmasa doğru bir doğum günü daxil edin.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Seçilmiş seçim doğru deyil.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Kolleksiya doğru deyil.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Zəhmət olmasa doğru bir rəng seçin.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Zəhmət olmasa doğru bir ölkə seçin.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Zəhmət olmasa doğru bir valyuta seçin.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Zəhmət olmasa doğru bir tarix aralığı seçin.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Zəhmət olmasa doğru bir tarix ve saat daxil edin.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Zəhmət olmasa doğru bir tarix daxil edin.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Zəhmət olmasa doğru bir fayl seçin.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Gizli sahə doğru deyil.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Zəhmət olmasa bir tam ədəd daxil edin.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Zəhmət olmasa doğru bir dil seçin.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Zəhmət olmasa doğru bir yer seçin.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Zəhmət olmasa doğru bir pul miqdarı daxil edin.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Zəhmət olmasa doğru bir rəqəm daxil edin.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Parol doğru deyil.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Zəhmət olmasa doğru bir faiz dəyəri daxil edin.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Dəyərlər örtüşmür.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Zəhmət olmasa doğru bir saat daxil edin.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Zəhmət olmasa doğru bir saat qurşağı seçin.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Zəhmət olmasa doğru bir URL daxil edin.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Zəhmət olmasa doğru bir axtarış termini daxil edin.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Zəhmət olmasa doğru bir telefon nömrəsi seçin.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Seçim qutusunda doğru olmayan dəyər var.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Zəhmət olmasa doğru bir e-poçt seçin.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Zəhmət olmasa doğru bir variant seçin.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Zəhmət olmasa doğru bir aralıq seçin.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Zəhmət olmasa doğru bir həftə seçin.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.be.xlf b/lib/symfony/form/Resources/translations/validators.be.xlf deleted file mode 100644 index 0513ca1dc..000000000 --- a/lib/symfony/form/Resources/translations/validators.be.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Гэта форма не павінна мець дадатковых палей.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Запампаваны файл быў занадта вялікім. Калі ласка, паспрабуйце запампаваць файл меншага памеру.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF-токен не сапраўдны. Калі ласка, паспрабуйце яшчэ раз адправіць форму.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Значэнне не з'яўляецца карэктным HTML5 колерам.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Калі ласка, увядзіце карэктную дату нараджэння.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Выбраны варыянт некарэктны.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Калекцыя некарэктна.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Калі ласка, выберыце карэктны колер.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Калі ласка, выберыце карэктную краіну.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Калі ласка, выберыце карэктную валюту.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Калі ласка, выберыце карэктны інтэрвал дат.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Калі ласка, увядзіце карэктныя дату і час.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Калі ласка, увядзіце карэктную дату.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Калі ласка, выберыце карэктны файл.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Значэнне схаванага поля некарэктна.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Калі ласка, увядзіце цэлы лік.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Калі ласка, выберыце карэктную мову.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Калі ласка, выберыце карэктную лакаль.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Калі ласка, увядзіце карэктную колькасць грошай.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Калі ласка, увядзіце нумар.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Няправільны пароль.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Калі ласка, увядзіце працэнтнае значэнне.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Значэнні не супадаюць.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Калі ласка, увядзіце карэктны час.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Калі ласка, выберыце карэктны гадзінны пояс.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Калі ласка, увядзіце карэктны URL.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Калі ласка, увядзіце карэктны пошукавы запыт.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Калі ласка, увядзіце карэктны нумар тэлефона.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Флажок мае некарэктнае значэнне.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Калі ласка, увядзіце карэктны адрас электроннай пошты.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Калі ласка, выберыце карэктны варыянт.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Калі ласка, выберыце карэктны дыяпазон.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Калі ласка, увядзіце карэктны тыдзень.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.bg.xlf b/lib/symfony/form/Resources/translations/validators.bg.xlf deleted file mode 100644 index 32fa94331..000000000 --- a/lib/symfony/form/Resources/translations/validators.bg.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Тази форма не трябва да съдържа допълнителни полета.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Каченият файл е твърде голям. Моля, опитайте да качите по-малък файл.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>Невалиден CSRF токен. Моля, опитайте да изпратите формата отново.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Стойността не е валиден HTML5 цвят.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Моля въведете валидна дата на раждане.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Избраните стойности не са валидни.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Колекцията не е валидна.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Моля изберете валиден цвят.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Моля изберете валидна държава.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Моля изберете валидна валута.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Моля изберете валиден интервал от дати.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Моля въведете валидни дата и час.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Моля въведете валидна дата.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Моля изберете валиден файл.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Скритото поле е невалидно.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Моля попълнете цяло число.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Моля изберете валиден език.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Моля изберете валиден език.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Моля въведете валидна парична сума.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Моля въведете число.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Паролата е невалидна.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Моля въведете процентна стойност.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Стойностите не съвпадат.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Моля въведете валидно време.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Моля изберете валидна часова зона.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Моля въведете валиден URL.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Моля въведете валидно търсене.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Моля осигурете валиден телефонен номер.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Отметката има невалидна стойност.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Моля въведете валидна ел. поща.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Моля изберете валидна опция.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Моля изберете валиден обхват.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Моля въведете валидна седмица.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.bs.xlf b/lib/symfony/form/Resources/translations/validators.bs.xlf deleted file mode 100644 index 319f91544..000000000 --- a/lib/symfony/form/Resources/translations/validators.bs.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Ovaj obrazac ne bi trebalo da sadrži dodatna polja.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Prenijeta (uploaded) datoteka je prevelika. Molim pokušajte prenijeti manju datoteku.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF vrijednost nije ispravna. Molim pokušajte ponovo da pošaljete obrazac.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Ova vrijednost nije važeća HTML5 boja.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Molim upišite ispravan datum rođenja.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Odabrani izbor nije ispravan.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Ova kolekcija nije ispravna.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Molim izaberite ispravnu boju.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Molim izaberite ispravnu državu.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Molim izaberite ispravnu valutu.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Molim izaberite ispravan datumski interval.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Molim upišite ispravan datum i vrijeme.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Molim upišite ispravan datum.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Molim izaberite ispravnu datoteku.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Skriveno polje nije ispravno.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Molim upišite cijeli broj (integer).</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Molim izaberite ispravan jezik.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Molim izaberite ispravnu lokalizaciju.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Molim upišite ispravnu količinu novca.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Molim upišite broj.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Ova lozinka nije ispravna.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Molim upišite procentualnu vrijednost.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Date vrijednosti se ne poklapaju.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Molim upišite ispravno vrijeme.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Molim izaberite ispravnu vremensku zonu.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Molim upišite ispravan URL.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Molim upišite ispravan termin za pretragu.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Molim navedite ispravan broj telefona.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Polje za potvrdu sadrži neispravnu vrijednost.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Molim upišite ispravnu email adresu.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Molim izaberite ispravnu opciju.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Molim izaberite ispravan opseg.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Molim upišite ispravnu sedmicu.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.ca.xlf b/lib/symfony/form/Resources/translations/validators.ca.xlf deleted file mode 100644 index 693796080..000000000 --- a/lib/symfony/form/Resources/translations/validators.ca.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Aquest formulari no hauria de contenir camps addicionals.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>L'arxiu pujat és massa gran. Per favor, pugi un arxiu més petit.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>El token CSRF no és vàlid. Per favor, provi d'enviar novament el formulari.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Aquest valor no és un color HTML5 valid.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Per favor introdueix una data d'aniversari valida.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>L'opció escollida és invalida.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>La col·lecció és invalida.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Per favor selecciona un color vàlid.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Per favor selecciona una ciutat vàlida.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Per favor selecciona una moneda vàlida.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Per favor escull un interval de dates vàlides.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Per favor introdueix una data i temps vàlid.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Per favor introdueix una data vàlida.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Per favor selecciona un arxiu vàlid.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>El camp ocult és invàlid.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Per favor introdueix un enter.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Per favor selecciona un idioma vàlid.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Per favor seleccioneu una configuració regional vàlida</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Per favor introdueix una quantitat de diners vàlids.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Per favor introdueix un número.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>La contrasenya es invàlida.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Per favor introdueix un valor percentual.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Els valors no coincideixen.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Per favor introdueix un temps vàlid.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Per favor selecciona una zona horària vàlida.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Per favor introdueix una URL vàlida.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Per favor introdueix un concepte de cerca vàlid.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Per favor introdueix un número de telèfon vàlid.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>La casella de selecció te un valor invàlid.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Per favor introdueix un correu electrònic vàlid.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Per favor selecciona una opció vàlida.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Per favor selecciona un rang vàlid.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Per favor introdueix una setmana vàlida.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.cs.xlf b/lib/symfony/form/Resources/translations/validators.cs.xlf deleted file mode 100644 index 3c4052b1c..000000000 --- a/lib/symfony/form/Resources/translations/validators.cs.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Tato skupina polí nesmí obsahovat další pole.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Nahraný soubor je příliš velký. Nahrajte prosím menší soubor.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF token je neplatný. Zkuste prosím znovu odeslat formulář.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Tato hodnota není platná HTML5 barva.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Prosím zadejte platný datum narození.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Vybraná možnost není platná.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Kolekce není platná.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Prosím vyberte platnou barvu.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Prosím vyberte platnou zemi.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Prosím vyberte platnou měnu.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Prosím vyberte platné rozpětí dat.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Prosím zadejte platný datum a čas.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Prosím zadejte platný datum.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Prosím vyberte platný soubor.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Skryté pole není platné.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Prosím zadejte číslo.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Prosím zadejte platný jazyk.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Prosím zadejte platný jazyk.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Prosím zadejte platnou částku.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Prosím zadejte číslo.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Heslo není platné.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Prosím zadejte procentuální hodnotu.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Hodnoty se neshodují.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Prosím zadejte platný čas.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Prosím vyberte platné časové pásmo.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Prosím zadejte platnou URL.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Prosím zadejte platný výraz k vyhledání.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Prosím zadejte platné telefonní číslo.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Zaškrtávací políčko má neplatnou hodnotu.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Prosím zadejte platnou emailovou adresu.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Prosím vyberte platnou možnost.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Prosím vyberte platný rozsah.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Prosím zadejte platný týden.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.da.xlf b/lib/symfony/form/Resources/translations/validators.da.xlf deleted file mode 100644 index b4f078ff3..000000000 --- a/lib/symfony/form/Resources/translations/validators.da.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Feltgruppen må ikke indeholde ekstra felter.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Den uploadede fil var for stor. Upload venligst en mindre fil.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF-token er ugyldig. Prøv venligst at genindsende.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Værdien er ikke en gyldig HTML5 farve.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Indtast venligst en gyldig fødselsdato.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Den valgte mulighed er ugyldig .</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Samlingen er ugyldig.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Vælg venligst en gyldig farve.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Vælg venligst et gyldigt land.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Vælg venligst en gyldig valuta.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Vælg venligst et gyldigt datointerval.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Vælg venligst en gyldig dato og tid.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Vælg venligst en gyldig dato.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Vælg venligst en gyldig fil.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Det skjulte felt er ugyldigt.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Indsæt veligst et heltal.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Vælg venligst et gyldigt sprog.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Vælg venligst en gyldigt sprogkode.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Vælg venligst et gyldigt beløb.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Indtast venligst et nummer.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Passwordet er ugyldigt.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Indtast venligst en procentværdi.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Værdierne er ikke ens.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Indtast venligst en gyldig tid.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Vælg venligst en gyldig tidszone.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Indtast venligst en gyldig URL.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Indtast venligst et gyldigt søgeord.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Giv venligst et gyldigt telefonnummer.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Checkboxen har en ugyldigt værdi.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Indtast venligst en gyldig e-mailadresse.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Vælg venligst en gyldig mulighed.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Vælg venligst et gyldigt interval .</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Indtast venligst en gyldig uge.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.de.xlf b/lib/symfony/form/Resources/translations/validators.de.xlf deleted file mode 100644 index 7b30839f9..000000000 --- a/lib/symfony/form/Resources/translations/validators.de.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Dieses Formular sollte keine zusätzlichen Felder enthalten.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Die hochgeladene Datei ist zu groß. Versuchen Sie bitte eine kleinere Datei hochzuladen.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>Der CSRF-Token ist ungültig. Versuchen Sie bitte, das Formular erneut zu senden.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Dieser Wert ist keine gültige HTML5 Farbe.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Bitte geben Sie ein gültiges Geburtsdatum ein.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Die Auswahl ist ungültig.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Diese Gruppe von Feldern ist ungültig.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Bitte geben Sie eine gültige Farbe ein.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Bitte wählen Sie ein gültiges Land aus.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Bitte wählen Sie eine gültige Währung aus.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Bitte wählen Sie ein gültiges Datumsintervall.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Bitte geben Sie ein gültiges Datum samt Uhrzeit ein.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Bitte geben Sie ein gültiges Datum ein.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Bitte wählen Sie eine gültige Datei.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Das versteckte Feld ist ungültig.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Bitte geben Sie eine ganze Zahl ein.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Bitte wählen Sie eine gültige Sprache.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Bitte wählen Sie eine gültige Locale-Einstellung aus.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Bitte geben Sie einen gültigen Geldbetrag ein.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Bitte geben Sie eine gültige Zahl ein.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Das Kennwort ist ungültig.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Bitte geben Sie einen gültigen Prozentwert ein.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Die Werte stimmen nicht überein.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Bitte geben Sie eine gültige Uhrzeit ein.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Bitte wählen Sie eine gültige Zeitzone.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Bitte geben Sie eine gültige URL ein.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Bitte geben Sie einen gültigen Suchbegriff ein.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Bitte geben Sie eine gültige Telefonnummer ein.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Das Kontrollkästchen hat einen ungültigen Wert.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Bitte geben Sie eine gültige E-Mail-Adresse ein.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Bitte wählen Sie eine gültige Option.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Bitte wählen Sie einen gültigen Bereich.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Bitte geben Sie eine gültige Woche ein.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.el.xlf b/lib/symfony/form/Resources/translations/validators.el.xlf deleted file mode 100644 index 595630e76..000000000 --- a/lib/symfony/form/Resources/translations/validators.el.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Αυτή η φόρμα δεν πρέπει να περιέχει επιπλέον πεδία.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Το αρχείο είναι πολύ μεγάλο. Παρακαλούμε προσπαθήστε να ανεβάσετε ένα μικρότερο αρχείο.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>Το CSRF token δεν είναι έγκυρο. Παρακαλούμε δοκιμάστε να υποβάλετε τη φόρμα ξανά.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Αυτή η τιμή δέν έναι έγκυρο χρώμα HTML5.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Παρακαλόυμε ειχάγεται μία έγκυρη ημερομηνία γέννησης.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Η επιλεγμένη επιλογή δέν είναι έγκυρη.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Η συλλογή δέν είναι έγκυρη.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Παρακαλούμε επιλέξτε ένα έγκυρο χρώμα.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Παρακαλούμε επιλέξτε μία έγκυρη χώρα.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Παρακαλούμε επιλέξτε ένα έγυρο νόμισμα.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Παρακαλούμε επιλέξτε ένα έγκυρο διάστημα ημερομηνίας.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Παρακαλούμε εισαγάγετε μια έγκυρη ημερομηνία και ώρα.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Παρακαλούμε εισάγετε μία έγκυρη ημερομηνία.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Παρακαλούμε επιλέξτε ένα έγκυρο αρχείο.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Το κρυφό πεδίο δέν είναι έγκυρο.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Παρακαλούμε εισάγετε έναν ακέραιο αριθμό.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Παρακαλούμε επιλέξτε μία έγκυρη γλώσσα.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Παρακαλούμε επιλέξτε μία έγκυρη τοπικοποίηση.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Παρακαλούμε εισάγετε ένα έγκυρο χρηματικό ποσό.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Παρακαλούμε εισάγετε έναν αριθμό.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Ο κωδικός δέν είναι έγκυρος.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Παρακαλούμε εισάγετε μία ποσοστιαία τιμή.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Οι τιμές δέν ταιριάζουν.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Παρακαλούμε εισάγετε μία έγκυρη ώρα.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Παρακαλούμε επιλέξτε μία έγυρη ζώνη ώρας.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Παρακαλούμε εισάγετε μια έγκυρη διεύθυνση URL.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Παρακαλούμε εισάγετε έναν έγκυρο όρο αναζήτησης.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Παρακαλούμε καταχωρίστε έναν έγκυρο αριθμό τηλεφώνου.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Το πλαίσιο ελέγχου έχει μή έγκυρη τιμή.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Παρακαλούμε εισάγετε μία έγκυρη ηλεκτρονική διεύθυνση.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Παρακαλούμε επιλέξτε μία έγκυρη επιλογή.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Παρακαλούμε επιλέξτε ένα έγυρο εύρος.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Παρακαλούμε εισάγετε μία έγκυρη εβδομάδα.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.en.xlf b/lib/symfony/form/Resources/translations/validators.en.xlf deleted file mode 100644 index e556c40b6..000000000 --- a/lib/symfony/form/Resources/translations/validators.en.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>This form should not contain extra fields.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>The uploaded file was too large. Please try to upload a smaller file.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>The CSRF token is invalid. Please try to resubmit the form.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>This value is not a valid HTML5 color.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Please enter a valid birthdate.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>The selected choice is invalid.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>The collection is invalid.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Please select a valid color.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Please select a valid country.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Please select a valid currency.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Please choose a valid date interval.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Please enter a valid date and time.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Please enter a valid date.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Please select a valid file.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>The hidden field is invalid.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Please enter an integer.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Please select a valid language.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Please select a valid locale.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Please enter a valid money amount.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Please enter a number.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>The password is invalid.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Please enter a percentage value.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>The values do not match.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Please enter a valid time.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Please select a valid timezone.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Please enter a valid URL.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Please enter a valid search term.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Please provide a valid phone number.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>The checkbox has an invalid value.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Please enter a valid email address.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Please select a valid option.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Please select a valid range.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Please enter a valid week.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.es.xlf b/lib/symfony/form/Resources/translations/validators.es.xlf deleted file mode 100644 index c143e009e..000000000 --- a/lib/symfony/form/Resources/translations/validators.es.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Este formulario no debería contener campos adicionales.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>El archivo subido es demasiado grande. Por favor, suba un archivo más pequeño.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>El token CSRF no es válido. Por favor, pruebe a enviar nuevamente el formulario.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Este valor no es un color HTML5 válido.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Por favor, ingrese una fecha de cumpleaños válida.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>La opción seleccionada no es válida.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>La colección no es válida.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Por favor, seleccione un color válido.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Por favor, seleccione un país válido.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Por favor, seleccione una moneda válida.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Por favor, elija un intervalo de fechas válido.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Por favor, ingrese una fecha y hora válidas.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Por favor, ingrese una fecha valida.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Por favor, seleccione un archivo válido.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>El campo oculto no es válido.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Por favor, ingrese un número entero.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Por favor, seleccione un idioma válido.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Por favor, seleccione una configuración regional válida.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Por favor, ingrese una cantidad de dinero válida.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Por favor, ingrese un número.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>La contraseña no es válida.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Por favor, ingrese un valor porcentual.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Los valores no coinciden.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Por favor, ingrese una hora válida.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Por favor, seleccione una zona horaria válida.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Por favor, ingrese una URL válida.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Por favor, ingrese un término de búsqueda válido.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Por favor, proporcione un número de teléfono válido.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>La casilla de verificación tiene un valor inválido.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Por favor, ingrese una dirección de correo electrónico válida.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Por favor, seleccione una opción válida.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Por favor, seleccione un rango válido.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Por favor, ingrese una semana válida.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.et.xlf b/lib/symfony/form/Resources/translations/validators.et.xlf deleted file mode 100644 index 6524c86b1..000000000 --- a/lib/symfony/form/Resources/translations/validators.et.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version='1.0'?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Väljade grupp ei tohiks sisalda lisaväljasid.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Üleslaaditud fail oli liiga suur. Palun proovi uuesti väiksema failiga.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF-märgis on vigane. Palun proovi vormi uuesti esitada.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>See väärtus ei ole korrektne HTML5 värv.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Palun sisesta korrektne sünnikuupäev.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Tehtud valik on vigane.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Kogum on vigane.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Palun vali korrektne värv.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Palun vali korrektne riik.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Palun vali korrektne valuuta.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Palun vali korrektne kuupäevade vahemik.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Palun sisesta korrektne kuupäev ja kellaaeg.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Palun sisesta korrektne kuupäev.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Palun vali korrektne fail.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Peidetud väli on vigane.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Palun sisesta täisarv.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Palun vali korrektne keel.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Palun vali korrektne keelekood.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Palun sisesta korrektne rahaline väärtus.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Palun sisesta number.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Vigane parool.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Palun sisesta protsendiline väärtus.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Väärtused ei klapi.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Palun sisesta korrektne aeg.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Palun vali korrektne ajavöönd.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Palun sisesta korrektne URL.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Palun sisesta korrektne otsingutermin.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Palun sisesta korrektne telefoninumber.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Märkeruudu väärtus on vigane.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Palun sisesta korrektne e-posti aadress.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Palun tee korrektne valik.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Palun vali korrektne vahemik.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Palun sisesta korrektne nädal.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.eu.xlf b/lib/symfony/form/Resources/translations/validators.eu.xlf deleted file mode 100644 index f43ab35a4..000000000 --- a/lib/symfony/form/Resources/translations/validators.eu.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Formulario honek ez luke aparteko eremurik eduki behar.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Igotako fitxategia handiegia da. Mesedez saiatu fitxategi txikiago bat igotzen.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid.</source> - <target>CSRF tokena ez da egokia.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Balio hori ez da HTML5 kolore onargarria.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Mesedez, sartu baliozko urtebetetze-eguna.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Hautatutako aukera ez da egokia.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Bilduma ez da baliozkoa.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Mesedez, hautatu baliozko kolore bat.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Mesedez, hautatu baliozko herrialde bat.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Mesedez, hautatu baliozko moneta bat.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Mesedez, hautatu baliozko data-tarte bat.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Mesedez, sartu baliozko data eta ordua.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Mesedez, sartu baliozko data bat.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Mesedez, hautatu baliozko fitxategi bat.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Eremu ezkutua ez da baliozkoa.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Mesedez, sartu zenbaki oso bat.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Mesedez, hautatu baliozko hizkuntza bat.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Mesedez, hautatu baliozko eskualde-konfigurazio bat.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Mesedez, sartu baliozko diru-kopuru bat.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Mesedez, sartu zenbaki bat.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Pasahitza ez da zuzena.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Mesedez, sartu portzentajezko balio bat.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Balioak ez datoz bat.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Mesedez, sartu baliozko ordu bat.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Mesedez, hautatu baliozko ordu-eremua.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Mesedez, sartu baliozko URL bat.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Mesedez, sartu bilaketa-termino onargarri bat.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Mesedez, eman baliozko telefono-zenbaki bat.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Egiaztatze-laukiak balio baliogabea du.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Mesedez, sartu baliozko helbide elektroniko bat.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Mesedez, hautatu baliozko aukera bat.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Mesedez, hautatu baliozko tarte bat.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Mesedez, sartu baliozko aste bat.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.fa.xlf b/lib/symfony/form/Resources/translations/validators.fa.xlf deleted file mode 100644 index 4a98eea8e..000000000 --- a/lib/symfony/form/Resources/translations/validators.fa.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>این فرم نباید شامل فیلدهای اضافی باشد.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>فایل بارگذاری‌شده بسیار بزرگ است. لطفاً فایل کوچک‌تری را بارگذاری نمایید.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>توکن CSRF نامعتبر است. لطفاً فرم را مجدداً ارسال نمایید.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>این مقدار یک رنگ معتبر HTML5 نیست.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>لطفاً یک تاریخ تولد معتبر وارد نمایید.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>گزینه‌ انتخاب‌ شده نامعتبر است.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>این مجموعه نامعتبر است.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>لطفاً یک رنگ معتبر انتخاب کنید.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>لطفاً یک کشور معتبر انتخاب کنید.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>لطفاً یک واحد پول معتبر انتخاب کنید.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>لطفاً یک بازه‌ زمانی معتبر انتخاب کنید.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>لطفاً یک تاریخ و زمان معتبر وارد کنید.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>لطفاً یک تاریخ معتبر وارد کنید.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>لطفاً یک فایل معتبر انتخاب کنید.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>فیلد مخفی نامعتبر است.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>لطفاً یک عدد صحیح وارد کنید.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>لطفاً یک زبان معتبر انتخاب کنید.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>لطفاً یک منطقه‌جغرافیایی (locale) معتبر انتخاب کنید.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>لطفاً یک مقدار پول معتبر وارد کنید.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>لطفاً یک عدد وارد کنید.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>رمزعبور نامعتبر است.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>لطفاً یک درصد معتبر وارد کنید.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>مقادیر تطابق ندارند.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>لطفاً یک زمان معتبر وارد کنید.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>لطفاً یک منطقه‌زمانی معتبر وارد کنید.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>لطفاً یک URL معتبر وارد کنید.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>لطفاً یک عبارت جستجوی معتبر وارد کنید.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>لطفاً یک شماره تلفن معتبر وارد کنید.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>کادر انتخاب (checkbox) دارای مقداری نامعتبر است.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>لطفاً یک آدرس رایانامه (ایمیل) معتبر وارد کنید.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>لطفاً یک گزینه‌ معتبر انتخاب کنید.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>لطفاً یک محدوده‌ معتبر انتخاب کنید.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>لطفاً یک هفته‌ معتبر وارد کنید.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.fi.xlf b/lib/symfony/form/Resources/translations/validators.fi.xlf deleted file mode 100644 index 7ad87b546..000000000 --- a/lib/symfony/form/Resources/translations/validators.fi.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Tämä lomake ei voi sisältää ylimääräisiä kenttiä.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Ladattu tiedosto on liian iso. Ole hyvä ja lataa pienempi tiedosto.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF-tarkiste on virheellinen. Ole hyvä ja yritä lähettää lomake uudestaan.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Tämä arvo ei ole kelvollinen HTML5-väri.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Syötä kelvollinen syntymäaika.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Valittu vaihtoehto ei kelpaa.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Ryhmä ei kelpaa.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Valitse kelvollinen väri.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Valitse kelvollinen maa.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Valitse kelvollinen valuutta.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Valitse kelvollinen aikaväli.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Syötä kelvolliset päivä ja aika.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Syötä kelvollinen päivä.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Valitse kelvollinen tiedosto.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Piilotettu kenttä ei ole kelvollinen.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Syötä kokonaisluku.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Valitse kelvollinen kieli.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Valitse kelvollinen kielikoodi.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Syötä kelvollinen rahasumma.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Syötä numero.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Salasana ei kelpaa.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Syötä prosenttiluku.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Arvot eivät vastaa toisiaan.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Syötä kelvollinen kellonaika.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Valitse kelvollinen aikavyöhyke.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Syötä kelvollinen URL.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Syötä kelvollinen hakusana.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Anna kelvollinen puhelinnumero.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Valintaruudun arvo ei kelpaa.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Syötä kelvollinen sähköpostiosoite.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Valitse kelvollinen vaihtoehto.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Valitse kelvollinen väli.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Syötä kelvollinen viikko.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.fr.xlf b/lib/symfony/form/Resources/translations/validators.fr.xlf deleted file mode 100644 index d65826467..000000000 --- a/lib/symfony/form/Resources/translations/validators.fr.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Ce formulaire ne doit pas contenir de champs supplémentaires.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Le fichier téléchargé est trop volumineux. Merci d'essayer d'envoyer un fichier plus petit.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>Le jeton CSRF est invalide. Veuillez renvoyer le formulaire.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Cette valeur n'est pas une couleur HTML5 valide.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Veuillez entrer une date de naissance valide.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Le choix sélectionné est invalide.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>La collection est invalide.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Veuillez sélectionner une couleur valide.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Veuillez sélectionner un pays valide.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Veuillez sélectionner une devise valide.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Veuillez choisir un intervalle de dates valide.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Veuillez saisir une date et une heure valides.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Veuillez entrer une date valide.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Veuillez sélectionner un fichier valide.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Le champ masqué n'est pas valide.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Veuillez saisir un entier.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Veuillez sélectionner une langue valide.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Veuillez sélectionner une langue valide.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Veuillez saisir un montant valide.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Veuillez saisir un nombre.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Le mot de passe est invalide.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Veuillez saisir un pourcentage valide.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Les valeurs ne correspondent pas.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Veuillez saisir une heure valide.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Veuillez sélectionner un fuseau horaire valide.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Veuillez saisir une URL valide.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Veuillez saisir un terme de recherche valide.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Veuillez fournir un numéro de téléphone valide.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>La case à cocher a une valeur non valide.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Veuillez saisir une adresse email valide.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Veuillez sélectionner une option valide.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Veuillez sélectionner une plage valide.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Veuillez entrer une semaine valide.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.gl.xlf b/lib/symfony/form/Resources/translations/validators.gl.xlf deleted file mode 100644 index 5ef404a48..000000000 --- a/lib/symfony/form/Resources/translations/validators.gl.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Este formulario non debería conter campos adicionais.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>O arquivo subido é demasiado grande. Por favor, suba un arquivo máis pequeno.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>O token CSRF non é válido. Por favor, probe a enviar novamente o formulario.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Este valor non é unha cor HTML5 válida.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Insire unha data de aniversario válida.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>A opción seleccionada non é válida.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>A colección non é válida.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Por favor, seleccione unha cor válida.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Por favor, seleccione un país válido.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Por favor, seleccione unha moeda válida.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Por favor, escolla un intervalo de datas válido.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Por favor, introduza unha data e hora válidas.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Por favor, introduce unha data válida.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Por favor, seleccione un ficheiro válido.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>O campo oculto non é válido.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Por favor, introduza un número enteiro.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Por favor, selecciona un idioma válido.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Por favor, seleccione unha configuración rexional válida.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Por favor, introduza unha cantidade de diñeiro válida.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Por favor, introduza un número.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>O contrasinal non é válido.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Por favor, introduza un valor porcentual.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Os valores non coinciden.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Por favor, introduza unha hora válida.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Por favor, selecciona unha zona horaria válida.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Por favor, introduce un URL válido.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Por favor, introduce un termo de busca válido.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Por favor, fornecer un número de teléfono válido.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>A caixa de verificación ten un valor non válido.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Por favor, introduce un enderezo de correo electrónico válido.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Por favor, seleccione unha opción válida.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Por favor, seleccione un intervalo válido.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Por favor, introduce unha semana válida.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.he.xlf b/lib/symfony/form/Resources/translations/validators.he.xlf deleted file mode 100644 index efd68b880..000000000 --- a/lib/symfony/form/Resources/translations/validators.he.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>הטופס לא צריך להכיל שדות נוספים.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>הקובץ שהועלה גדול מדי. נסה להעלות קובץ קטן יותר.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>אסימון CSRF אינו חוקי. אנא נסה לשלוח שוב את הטופס.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>ערך זה אינו צבע HTML5 חוקי.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>נא להזין את תאריך לידה תקני.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>הבחירה שנבחרה אינה חוקית.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>האוסף אינו חוקי.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>אנא בחר צבע חוקי.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>אנא בחר מדינה חוקית.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>אנא בחר מטבע חוקי.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>אנא בחר מרווח תאריכים חוקי.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>אנא הזן תאריך ושעה תקנים.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>נא להזין תאריך חוקי.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>אנא בחר קובץ חוקי.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>השדה הנסתר אינו חוקי.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>אנא הזן מספר שלם.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>אנא בחר שפה חוקי.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>אנא בחר שפה מקומית.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>אנא הזן סכום כסף חוקי.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>אנא הזן מספר.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>הסיסמה אינה חוקית.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>אנא הזן ערך באחוזים.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>הערכים אינם תואמים.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>אנא הזן שעה חוקי.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>אנא בחר אזור זמן חוקי.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>נא להזין את כתובת אתר חוקית.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>אנא הזן מונח חיפוש חוקי.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>אנא ספק מספר טלפון חוקי.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>לתיבת הסימון יש ערך לא חוקי.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>אנא הזן כתובת דוא"ל תקנית.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>אנא בחר אפשרות חוקית.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>אנא בחר טווח חוקי.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>אנא הזן שבוע תקף.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.hr.xlf b/lib/symfony/form/Resources/translations/validators.hr.xlf deleted file mode 100644 index 9f17b5ea1..000000000 --- a/lib/symfony/form/Resources/translations/validators.hr.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Ovaj obrazac ne smije sadržavati dodatna polja.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Prenesena datoteka je prevelika. Molim pokušajte prenijeti manju datoteku.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF vrijednost nije ispravna. Pokušajte ponovo poslati obrazac.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Ova vrijednost nije važeća HTML5 boja.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Molim upišite ispravan datum rođenja.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Odabrani izbor nije ispravan.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Kolekcija nije ispravna.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Molim odaberite ispravnu boju.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Molim odaberite ispravnu državu.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Molim odaberite ispravnu valutu.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Molim odaberite ispravni vremenski interval.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Molim unesite ispravni datum i vrijeme.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Molim odaberite ispravan datum.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Molim odaberite ispravnu datoteku.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Skriveno polje nije ispravno.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Molim unesite cijeli broj.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Molim odaberite ispravan jezik.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Molim odaberite ispravnu lokalizaciju.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Molim unesite ispravan iznos novca.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Molim unesite broj.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Ova lozinka nije ispravna.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Molim unesite vrijednost postotka.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Ove vrijednosti se ne poklapaju.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Molim unesite ispravno vrijeme.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Molim odaberite ispravnu vremensku zonu.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Molim unesite ispravan URL.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Molim unesite ispravan pojam za pretraživanje.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Molim navedite ispravan telefonski broj.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Polje za potvrdu sadrži neispravnu vrijednost.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Molim unesite valjanu adresu elektronske pošte.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Molim odaberite ispravnu opciju.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Molim odaberite ispravan raspon.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Molim unesite ispravni tjedan.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.hu.xlf b/lib/symfony/form/Resources/translations/validators.hu.xlf deleted file mode 100644 index 3b70461d3..000000000 --- a/lib/symfony/form/Resources/translations/validators.hu.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Ez a mezőcsoport nem tartalmazhat extra mezőket.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>A feltöltött fájl túl nagy. Kérem, próbáljon egy kisebb fájlt feltölteni.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>Érvénytelen CSRF token. Kérem, próbálja újra elküldeni az űrlapot.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Ez az érték nem egy érvényes HTML5 szín.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Kérjük, adjon meg egy valós születési dátumot.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>A kiválasztott opció érvénytelen.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>A gyűjtemény érvénytelen.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Kérjük, válasszon egy érvényes színt.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Kérjük, válasszon egy érvényes országot.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Kérjük, válasszon egy érvényes pénznemet.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Kérjük, válasszon egy érvényes dátumintervallumot.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Kérjük, adjon meg egy érvényes dátumot és időpontot.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Kérjük, adjon meg egy érvényes dátumot.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Kérjük, válasszon egy érvényes fájlt.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>A rejtett mező érvénytelen.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Kérjük, adjon meg egy egész számot.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Kérjük, válasszon egy érvényes nyelvet.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Kérjük, válasszon egy érvényes területi beállítást.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Kérjük, adjon meg egy érvényes pénzösszeget.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Kérjük, adjon meg egy számot.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>A jelszó érvénytelen.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Kérjük, adjon meg egy százalékos értéket.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Az értékek nem egyeznek.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Kérjük, adjon meg egy érvényes időpontot.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Kérjük, válasszon érvényes időzónát.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Kérjük, adjon meg egy érvényes URL-t.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Kérjük, adjon meg egy érvényes keresési kifejezést.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Kérjük, adjon egy érvényes telefonszámot</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>A jelölőnégyzet értéke érvénytelen.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Kérjük valós e-mail címet adjon meg.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Kérjük, válasszon egy érvényes beállítást.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Kérjük, válasszon egy érvényes tartományt.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Kérjük, adjon meg egy érvényes hetet.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.hy.xlf b/lib/symfony/form/Resources/translations/validators.hy.xlf deleted file mode 100644 index 10ac326fb..000000000 --- a/lib/symfony/form/Resources/translations/validators.hy.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Այս ձևը չպետք է պարունակի լրացուցիչ տողեր։</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Վերբեռնված ֆայլը չափազանց մեծ է. Խնդրվում է վերբեռնել ավելի փոքր չափսի ֆայլ։</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF արժեքը անթույլատրելի է. Փորձեք նորից ուղարկել ձևը։</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Այս արժեքը վավեր HTML5 գույն չէ։</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Խնդրում ենք մուտքագրել վավեր ծննդյան ամսաթիվ։</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Ընտրված ընտրությունն անվավեր է։</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Համախումբն անվավեր է։</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Խնդրում ենք ընտրել վավեր գույն։</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Խնդրում ենք ընտրել վավեր երկիր։</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Խնդրում ենք ընտրել վավեր արժույթ։</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Խնդրում ենք ընտրել ճիշտ ամսաթվերի միջակայք։</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Խնդրում ենք մուտքագրել վավեր ամսաթիվ և ժամ։</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Խնդրում ենք մուտքագրել վավեր ամսաթիվ։</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Խնդրում ենք ընտրել վավեր ֆայլ։</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Թաքնված դաշտը անվավեր է։</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Խնդրում ենք մուտքագրել ամբողջ թիվ։</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Խնդրում ենք ընտրել վավեր լեզու։</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Խնդրում ենք ընտրել վավեր տեղայնացում։</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Խնդրում ենք մուտքագրել վավեր գումար։</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Խնդրում ենք մուտքագրել համար։</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Գաղտնաբառն անվավեր է։</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Խնդրում ենք մուտքագրել տոկոսային արժեք։</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Արժեքները չեն համընկնում։</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Մուտքագրեք վավեր ժամանակ։</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Խնդրում ենք ընտրել վավեր ժամային գոտի։</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Խնդրում ենք մուտքագրել վավեր URL։</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Խնդրում ենք մուտքագրել վավեր որոնման տերմին։</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Խնդրում ենք տրամադրել վավեր հեռախոսահամար։</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Նշման վանդակը անվավեր արժեք ունի։</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Խնդրում ենք մուտքագրել վավեր էլ-հասցե։</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Խնդրում ենք ընտրել ճիշտ տարբերակ։</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Խնդրում ենք ընտրել վավեր տիրույթ։</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Մուտքագրեք վավեր շաբաթ։</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.id.xlf b/lib/symfony/form/Resources/translations/validators.id.xlf deleted file mode 100644 index 535f9e6b1..000000000 --- a/lib/symfony/form/Resources/translations/validators.id.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Gabungan kolom tidak boleh mengandung kolom tambahan.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Berkas yang di unggah terlalu besar. Silahkan coba unggah berkas yang lebih kecil.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF-Token tidak sah. Silahkan coba kirim ulang formulir.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Nilai ini bukan merupakan HTML5 color yang sah.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Silahkan masukkan tanggal lahir yang sah.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Pilihan yang dipilih tidak sah.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Koleksi tidak sah.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Silahkan pilih warna yang sah.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Silahkan pilih negara yang sah.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Silahkan pilih mata uang yang sah.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Silahkan pilih interval tanggal yang sah.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Silahkan masukkan tanggal dan waktu yang sah.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Silahkan masukkan tanggal yang sah.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Silahkan pilih berkas yang sah.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Ruas yang tersembunyi tidak sah.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Silahkan masukkan angka.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Silahlan pilih bahasa yang sah.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Silahkan pilih local yang sah.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Silahkan masukkan nilai uang yang sah.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Silahkan masukkan sebuah angka</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Kata sandi tidak sah.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Silahkan masukkan sebuah nilai persentase.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Nilainya tidak cocok.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Silahkan masukkan waktu yang sah.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Silahkan pilih zona waktu yang sah.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Silahkan masukkan URL yang sah.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Silahkan masukkan kata pencarian yang sah.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Silahkan sediakan nomor telepon yang sah.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Nilai dari checkbox tidak sah.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Silahkan masukkan alamat surel yang sah.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Silahkan pilih opsi yang sah.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Silahkan pilih rentang yang sah.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Silahkan masukkan minggu yang sah.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.it.xlf b/lib/symfony/form/Resources/translations/validators.it.xlf deleted file mode 100644 index 1a8eee3ac..000000000 --- a/lib/symfony/form/Resources/translations/validators.it.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Questo form non dovrebbe contenere nessun campo extra.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Il file caricato è troppo grande. Per favore, carica un file più piccolo.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>Il token CSRF non è valido. Prova a reinviare il form.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Il valore non è un colore HTML5 valido.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Per favore, inserisci una data di compleanno valida.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>La scelta selezionata non è valida.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>La collezione non è valida.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Per favore, seleziona un colore valido.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Per favore, seleziona un paese valido.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Per favore, seleziona una valuta valida.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Per favore, scegli un intervallo di date valido.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Per favore, inserisci una data e ora valida.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Per favore, inserisci una data valida.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Per favore, seleziona un file valido.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Il campo nascosto non è valido.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Per favore, inserisci un numero intero.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Per favore, seleziona una lingua valida.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Per favore, seleziona una lingua valida.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Per favore, inserisci un importo valido.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Per favore, inserisci un numero.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>La password non è valida.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Per favore, inserisci un valore percentuale.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>I valori non corrispondono.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Per favore, inserisci un orario valido.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Per favore, seleziona un fuso orario valido.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Per favore, inserisci un URL valido.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Per favore, inserisci un termine di ricerca valido.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Per favore, indica un numero di telefono valido.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>La casella di selezione non ha un valore valido.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Per favore, indica un indirizzo email valido.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Per favore, seleziona un'opzione valida.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Per favore, seleziona un intervallo valido.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Per favore, inserisci una settimana valida.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.ja.xlf b/lib/symfony/form/Resources/translations/validators.ja.xlf deleted file mode 100644 index ea2226ce4..000000000 --- a/lib/symfony/form/Resources/translations/validators.ja.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>フィールドグループに追加のフィールドを含んではなりません。</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>アップロードされたファイルが大きすぎます。小さなファイルで再度アップロードしてください。</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRFトークンが無効です、再送信してください。</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>有効なHTML5の色ではありません。</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>有効な生年月日を入力してください。</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>選択した値は無効です。</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>コレクションは無効です。</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>有効な色を選択してください。</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>有効な国を選択してください。</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>有効な通貨を選択してください。</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>有効な日付間隔を選択してください。</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>有効な日時を入力してください。</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>有効な日付を入力してください。</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>有効なファイルを選択してください。</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>隠しフィールドが無効です。</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>整数で入力してください。</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>有効な言語を選択してください。</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>有効なロケールを選択してください。</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>有効な金額を入力してください。</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>数値で入力してください。</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>パスワードが無効です。</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>パーセント値で入力してください。</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>値が一致しません。</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>有効な時間を入力してください。</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>有効なタイムゾーンを選択してください。</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>有効なURLを入力してください。</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>有効な検索語を入力してください。</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>有効な電話番号を入力してください。</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>チェックボックスの値が無効です。</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>有効なメールアドレスを入力してください。</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>有効な値を選択してください。</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>有効な範囲を選択してください。</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>有効な週を入力してください。</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.lb.xlf b/lib/symfony/form/Resources/translations/validators.lb.xlf deleted file mode 100644 index e989264f9..000000000 --- a/lib/symfony/form/Resources/translations/validators.lb.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Dës Feldergrupp sollt keng zousätzlech Felder enthalen.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>De geschécktene Fichier ass ze grouss. Versicht wann ech gelift ee méi klenge Fichier eropzelueden.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>Den CSRF-Token ass ongëlteg. Versicht wann ech gelift de Formulaire nach eng Kéier ze schécken.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Dëse Wäert ass keng gëlteg HTML5-Faarf.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>W.e.g. e gëltege Gebuertsdatum aginn.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Den ausgewielte Choix ass ongëlteg.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>D'Kollektioun ass ongëlteg.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>W.e.g. eng gëlteg Faarf auswielen.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>W.e.g. e gëltegt Land auswielen.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>W.e.g. eng gëlteg Wärung auswielen.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>W.e.g. e gëltegen Datumsinterval aginn.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>W.e.g. eng gëlteg Datum an Zäit aginn.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>W.e.g. eng gëltegen Datum aginn.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>W.e.g. e gëltege Fichier auswielen.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Dat verstoppte Feld ass ongëlteg.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>W.e.g. eng ganz Zuel aginn.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>W.e.g. e gëltegt Sprooch auswielen.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>W.e.g. e gëltegt Regionalschema auswielen.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>W.e.g. eng gëlteg Geldzomm aginn.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>W.e.g. eng Zuel aginn.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>D'Passwuert ass ongëlteg.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>W.e.g. e Prozentwäert aginn.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>D'Wäerter stëmmen net iwwereneen.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>W.e.g. eng gëlteg Zäit aginn.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>W.e.g. eng gëlteg Zäitzon auswielen.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>W.e.g. eng gëlteg URL aginn.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>W.e.g. e gëltege Sichbegrëff aginn.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>W.e.g. eng gëlteg Telefonsnummer uginn.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>D'Ukräizfeld huet en ongëltege Wäert.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>W.e.g. eng gëlteg E-Mail-Adress aginn.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>W.e.g. eng gëlteg Optioun auswielen.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>W.e.g. eng gëlteg Spannbreet auswielen.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>W.e.g. eng gëlteg Woch aginn.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.lt.xlf b/lib/symfony/form/Resources/translations/validators.lt.xlf deleted file mode 100644 index 5613c42b5..000000000 --- a/lib/symfony/form/Resources/translations/validators.lt.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Forma negali turėti papildomų laukų.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Įkelta byla yra per didelė. bandykite įkelti mažesnę.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF kodas nepriimtinas. Bandykite siųsti formos užklausą dar kartą.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Ši reikšmė nėra HTML5 spalva.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Prašome įvesti tinkamą gimimo datą.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Pasirinktas pasirinkimas yra neteisingas.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Neteisingas sąrašas.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Prašome pasirinkti tinkamą spalvą.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Prašome pasirinkti tinkamą šalį.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Prašome pasirinkti tinkamą valiutą.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Prašome pasirinkti tinkamą datos intervalą.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Prašome įvesti tinkamą datą ir laiką.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Prašome įvesti tinkamą datą.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Prašome pasirinkti tinkamą bylą.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Klaidingas paslėptasis laukas.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Prašome įvesti sveiką skaičių.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Prašome pasirinkti tinkamą kalbą.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Prašome pasirinkti tinkamą lokalę.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Prašome įvesti tinkamą pinigų sumą.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Prašome įvesti numerį.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Klaidingas slaptažodis.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Prašome įvesti procentinę reikšmę.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Reikšmės nesutampa.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Prašome įvesti tinkamą laiką.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Prašome pasirinkti tinkamą laiko zoną.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Prašome įvesti tinkamą URL.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Prašome įvesti tinkamą paieškos terminą.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Prašome pateikti tinkamą telefono numerį.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Klaidinga žymimajo langelio reikšmė.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Prašome įvesti tinkamą el. pašto adresą.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Prašome pasirinkti tinkamą parinktį.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Prašome pasirinkti tinkamą diapozoną.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Prašome įvesti tinkamą savaitę.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.lv.xlf b/lib/symfony/form/Resources/translations/validators.lv.xlf deleted file mode 100644 index 54711cb5f..000000000 --- a/lib/symfony/form/Resources/translations/validators.lv.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Šajā veidlapā nevajadzētu būt papildus ievades laukiem.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Augšupielādētā faila izmērs bija par lielu. Lūdzu mēģiniet augšupielādēt mazāka izmēra failu.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>Dotais CSRF talons nav derīgs. Lūdzu mēģiniet vēlreiz iesniegt veidlapu.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Šī vertība nav derīga HTML5 krāsa.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Lūdzu, ievadiet derīgu dzimšanas datumu.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Iezīmētā izvēle nav derīga.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Kolekcija nav derīga.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Lūdzu, izvēlieties derīgu krāsu.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Lūdzu, izvēlieties derīgu valsti.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Lūdzu, izvēlieties derīgu valūtu.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Lūdzu, izvēlieties derīgu datumu intervālu.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Lūdzu, ievadiet derīgu datumu un laiku.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Lūdzu, ievadiet derīgu datumu.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Lūdzu, izvēlieties derīgu failu.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Slēptā lauka vērtība ir nederīga.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Lūdzu, ievadiet veselu skaitli.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Lūdzu, izvēlieties derīgu valodu.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Lūdzu, izvēlieties derīgu lokalizāciju.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Lūdzu, ievadiet derīgu naudas lielumu.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Lūdzu, ievadiet skaitli.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Parole ir nederīga.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Lūdzu, ievadiet procentuālo lielumu.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Vērtības nesakrīt.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Lūdzu, ievadiet derīgu laiku.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Lūdzu, izvēlieties derīgu laika zonu.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Lūdzu, ievadiet derīgu URL.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Lūdzu, ievadiet derīgu meklēšanas nosacījumu.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Lūdzu, ievadiet derīgu tālruņa numuru.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Izvēles rūtiņai ir nederīga vērtība.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Lūdzu, ievadiet derīgu e-pasta adresi.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Lūdzu, izvēlieties derīgu opciju.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Lūdzu, izvēlieties derīgu diapazonu.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Lūdzu, ievadiet derīgu nedēļu.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.mn.xlf b/lib/symfony/form/Resources/translations/validators.mn.xlf deleted file mode 100644 index 620112d88..000000000 --- a/lib/symfony/form/Resources/translations/validators.mn.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Форм нэмэлт талбар багтаах боломжгүй.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Upload хийсэн файл хэтэрхий том байна. Бага хэмжээтэй файл оруулна уу.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF token буруу байна. Формоо дахин илгээнэ үү.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Энэ утга зөв HTML5 өнгө биш байна.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Зөв төрсөн он сар оруулна уу.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Сонгосон утга буруу байна.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Цуглуулга буруу байна.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Үнэн зөв өнгө сонгоно уу.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Үнэн зөв улс сонгоно уу.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Үнэн зөв мөнгөн тэмдэгт сонгоно уу.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Үнэн зөв цагын зай сонгоно уу.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Үнэн зөв он цаг оруулна уу.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Үнэн зөв он цаг өдөр оруулна уу.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Үнэн зөв файл сонгоно уу.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Нууц талбарын утга буруу байна.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Бүхэл тоо оруулна уу.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Үнэн зөв хэл сонгоно уу.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Үнэн зөв бүс сонгоно уу.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Үнэн зөв мөнгөний хэмжээ сонгоно уу.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Тоо оруулна уу.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Нууц үг буруу байна.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Хувь утга оруулна уу.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Утга хоорондоо таарахгүй байна.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Үнэн зөв цаг оруулна уу.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Үнэн зөв цагын бүс оруулна уу.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Үнэн зөв URL оруулна уу.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Үнэн зөв хайх утга оруулна уу.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Үнэн зөв утасны дугаар оруулна уу.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Сонгох хайрцаг буруу утгатай байна.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Үнэн зөв и-мэйл хаяг оруулна уу.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Үнэн зөв сонголт сонгоно уу.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Үнэн зөв хязгаарын утга сонгоно уу.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Үнэн зөв долоо хоног сонгоно уу.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.my.xlf b/lib/symfony/form/Resources/translations/validators.my.xlf deleted file mode 100644 index b0180c551..000000000 --- a/lib/symfony/form/Resources/translations/validators.my.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>ဤ ဖောင်သည် field အပိုများ မပါ၀င်သင့်ပါ။</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Upload တင်သောဖိုင်သည်အလွန်ကြီးလွန်းသည်။ ကျေးဇူးပြု၍ သေးငယ်သည့်ဖိုင်ကိုတင်ရန်ကြိုးစားပါ။</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>သင့်လျှော်သော် CSRF တိုကင် မဟုတ်ပါ။ ကျေးဇူးပြု၍ဖောင်ကိုပြန်တင်ပါ။</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>ဤတန်ဖိုးသည် သင့်လျှော်သော် HTML5 အရောင်မဟုတ်ပါ။</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>ကျေးဇူးပြု၍ မှန်ကန်သောမွေးနေ့ကိုထည့်ပါ။</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>သင့် ရွေးချယ်မှုသည်မမှန်ကန်ပါ။</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>ဤ collection သည်သင့်လျှော်သော် collection မဟုတ်ပါ။</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>ကျေးဇူးပြု၍ မှန်ကန်သောအရောင်ကိုရွေးပါ။</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>ကျေးဇူးပြု၍ မှန်ကန်သောနိုင်ငံကိုရွေးပါ။</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>ကျေးဇူးပြု၍ မှန်ကန်သောငွေကြေးကိုရွေးပါ။</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>ကျေးဇူးပြု၍ မှန်ကန်သောနေ ရက်စွဲကိုရွေးပါ။</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>ကျေးဇူးပြု၍ မှန်ကန်သောနေ ရက်စွဲနှင့်အချိန် ကိုထည့်ပါ။</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>ကျေးဇူးပြု၍ မှန်ကန်သောနေ ရက်စွဲကိုထည့်ပါ။</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>ကျေးဇူးပြု၍ မှန်ကန်သောနေ ဖိုင်ကိုရွေးချယ်ပါ။</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>မသင့် လျှော်သော် hidden field ဖြစ်နေသည်။</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>ကျေးဇူးပြု၍ Integer တန်ဖိုးသာထည့်ပါ။</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>ကျေးဇူးပြု၍ မှန်ကန်သော ဘာသာစကားကိုရွေးချယ်ပါ။</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>ကျေးဇူးပြု၍ မှန်ကန်သော locale ကိုရွေးချယ်ပါ။</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>ကျေးဇူးပြု၍ မှန်ကန်သော ပိုက်ဆံပမာဏ ကိုထည့်ပါ။</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>ကျေးဇူးပြု၍ မှန်ကန်သော နံပါတ် ကိုရွေးချယ်ပါ။</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>မှန်ကန်သောစကား၀ှက်မဟုတ်ပါ။</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>ကျေးဇူးပြု၍ ရာခိုင်နှုန်းတန်ဖိုးထည့်ပါ။</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>တန်ဖိုးများကိုက်ညီမှုမရှိပါ။</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>ကျေးဇူးပြု၍ မှန်ကန်သောအချိန်ကိုထည့်ပါ။</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>ကျေးဇူးပြု၍ မှန်ကန်သောအချိန်ဇုန်ကိုရွေးပါ။</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>ကျေးဇူးပြု၍ သင့်လျှော်သော် URL ကိုရွေးပါ။</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>ကျေးဇူးပြု၍ သင့် လျှော်သော်ရှာဖွေမှု term များထည့်ပါ။</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>ကျေးဇူးပြု၍ သင့် လျှော်သော်ရှာဖွေမှု ဖုန်းနံပါတ်ထည့်ပါ။</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Checkbox တန်ဖိုးသည် မှန်ကန်မှုမရှိပါ။</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>ကျေးဇူးပြု၍ မှန်ကန်သော် email လိပ်စာထည့်ပါ။</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>ကျေးဇူးပြု၍ မှန်ကန်သော် ရွေးချယ်မှု ကိုရွေးပါ။</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>ကျေးဇူးပြု၍ မှန်ကန်သော အပိုင်းအခြား ကိုရွေးပါ။</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>ကျေးဇူးပြု၍ မှန်ကန်သောရက်သတ္တပတ်ကိုထည့်ပါ။</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.nb.xlf b/lib/symfony/form/Resources/translations/validators.nb.xlf deleted file mode 100644 index 1d8385086..000000000 --- a/lib/symfony/form/Resources/translations/validators.nb.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Feltgruppen må ikke inneholde ekstra felter.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Den opplastede filen var for stor. Vennligst last opp en mindre fil.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid.</source> - <target>CSRF nøkkelen er ugyldig.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Denne verdien er ikke en gyldig HTML5-farge.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Vennligst oppgi gyldig fødselsdato.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Det valgte valget er ugyldig.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Samlingen er ugyldig.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Velg en gyldig farge.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Vennligst velg et gyldig land.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Vennligst velg en gyldig valuta.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Vennligst velg et gyldig datointervall.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Vennligst angi en gyldig dato og tid.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Vennligst oppgi en gyldig dato.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Vennligst velg en gyldig fil.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Det skjulte feltet er ugyldig.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Vennligst skriv inn et heltall.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Vennligst velg et gyldig språk.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Vennligst velg et gyldig sted.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Vennligst angi et gyldig pengebeløp.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Vennligst skriv inn et nummer.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Passordet er ugyldig.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Vennligst angi en prosentverdi.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Verdiene stemmer ikke overens.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Vennligst angi et gyldig tidspunkt.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Vennligst velg en gyldig tidssone.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Vennligst skriv inn en gyldig URL.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Vennligst angi et gyldig søketerm.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Vennligst oppgi et gyldig telefonnummer.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Avkrysningsboksen har en ugyldig verdi.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Vennligst skriv inn en gyldig e-post adresse.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Vennligst velg et gyldig alternativ.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Vennligst velg et gyldig område.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Vennligst skriv inn en gyldig uke.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.nl.xlf b/lib/symfony/form/Resources/translations/validators.nl.xlf deleted file mode 100644 index 7aa56ebf1..000000000 --- a/lib/symfony/form/Resources/translations/validators.nl.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Dit formulier mag geen extra velden bevatten.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Het geüploade bestand is te groot. Probeer een kleiner bestand te uploaden.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>De CSRF-token is ongeldig. Probeer het formulier opnieuw te versturen.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Dit is geen geldige HTML5 kleur.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Vul een geldige geboortedatum in.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Deze keuze is ongeldig.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Deze collectie is ongeldig.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Kies een geldige kleur.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Kies een geldige landnaam.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Kies een geldige valuta.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Kies een geldig tijdinterval.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Vul een geldige datum en tijd in.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Vul een geldige datum in.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Kies een geldig bestand.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Het verborgen veld is incorrect.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Vul een geldig getal in.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Kies een geldige taal.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Kies een geldige locale.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Vul een geldig bedrag in.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Vul een geldig getal in.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Het wachtwoord is incorrect.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Vul een geldig percentage in.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>De waardes komen niet overeen.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Vul een geldige tijd in.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Vul een geldige tijdzone in.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Vul een geldige URL in.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Vul een geldige zoekterm in.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Vul een geldig telefoonnummer in.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>De checkbox heeft een incorrecte waarde.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Vul een geldig e-mailadres in.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Kies een geldige optie.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Kies een geldig bereik.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Vul een geldige week in.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.nn.xlf b/lib/symfony/form/Resources/translations/validators.nn.xlf deleted file mode 100644 index 9fac1bf34..000000000 --- a/lib/symfony/form/Resources/translations/validators.nn.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Feltgruppa kan ikkje innehalde ekstra felt.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Fila du lasta opp var for stor. Last opp ei mindre fil.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid.</source> - <target>CSRF-nøkkelen er ikkje gyldig.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Verdien er ikkje ein gyldig HTML5-farge.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Gje opp ein gyldig fødselsdato.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Valget du gjorde er ikkje gyldig.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Samlinga er ikkje gyldig.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Gje opp ein gyldig farge.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Gje opp eit gyldig land.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Gje opp ein gyldig valuta.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Gje opp eit gyldig datointervall.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Gje opp ein gyldig dato og tid.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Gje opp ein gyldig dato.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Velg ei gyldig fil.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Det skjulte feltet er ikkje gyldig.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Gje opp eit heiltal.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Gje opp eit gyldig språk.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Gje opp eit gyldig locale.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Gje opp ein gyldig sum pengar.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Gje opp eit nummer.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Passordet er ikkje gyldig.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Gje opp ein prosentverdi.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Verdiane er ikkje eins.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Gje opp ei gyldig tid.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Gje opp ei gyldig tidssone.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Gje opp ein gyldig URL.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Gje opp gyldige søkjeord.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Gje opp eit gyldig telefonnummer.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Sjekkboksen har ein ugyldig verdi.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Gje opp ei gyldig e-postadresse.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Velg eit gyldig vilkår.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Velg eit gyldig spenn.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Gje opp ei gyldig veke.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.no.xlf b/lib/symfony/form/Resources/translations/validators.no.xlf deleted file mode 100644 index 1d8385086..000000000 --- a/lib/symfony/form/Resources/translations/validators.no.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Feltgruppen må ikke inneholde ekstra felter.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Den opplastede filen var for stor. Vennligst last opp en mindre fil.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid.</source> - <target>CSRF nøkkelen er ugyldig.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Denne verdien er ikke en gyldig HTML5-farge.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Vennligst oppgi gyldig fødselsdato.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Det valgte valget er ugyldig.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Samlingen er ugyldig.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Velg en gyldig farge.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Vennligst velg et gyldig land.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Vennligst velg en gyldig valuta.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Vennligst velg et gyldig datointervall.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Vennligst angi en gyldig dato og tid.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Vennligst oppgi en gyldig dato.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Vennligst velg en gyldig fil.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Det skjulte feltet er ugyldig.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Vennligst skriv inn et heltall.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Vennligst velg et gyldig språk.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Vennligst velg et gyldig sted.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Vennligst angi et gyldig pengebeløp.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Vennligst skriv inn et nummer.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Passordet er ugyldig.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Vennligst angi en prosentverdi.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Verdiene stemmer ikke overens.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Vennligst angi et gyldig tidspunkt.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Vennligst velg en gyldig tidssone.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Vennligst skriv inn en gyldig URL.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Vennligst angi et gyldig søketerm.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Vennligst oppgi et gyldig telefonnummer.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Avkrysningsboksen har en ugyldig verdi.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Vennligst skriv inn en gyldig e-post adresse.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Vennligst velg et gyldig alternativ.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Vennligst velg et gyldig område.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Vennligst skriv inn en gyldig uke.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.pl.xlf b/lib/symfony/form/Resources/translations/validators.pl.xlf deleted file mode 100644 index d553f2a17..000000000 --- a/lib/symfony/form/Resources/translations/validators.pl.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Ten formularz nie powinien zawierać dodatkowych pól.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Wgrany plik był za duży. Proszę spróbować wgrać mniejszy plik.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>Token CSRF jest nieprawidłowy. Proszę spróbować wysłać formularz ponownie.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Ta wartość nie jest prawidłowym kolorem HTML5.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Proszę wprowadzić prawidłową datę urodzenia.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Wybrana wartość jest nieprawidłowa.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Zbiór jest nieprawidłowy.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Proszę wybrać prawidłowy kolor.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Proszę wybrać prawidłowy kraj.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Proszę wybrać prawidłową walutę.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Proszę wybrać prawidłowy przedział czasowy.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Proszę wprowadzić prawidłową datę i czas.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Proszę wprowadzić prawidłową datę.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Proszę wybrać prawidłowy plik.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Ukryte pole jest nieprawidłowe.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Proszę wprowadzić liczbę całkowitą.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Proszę wybrać prawidłowy język.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Proszę wybrać prawidłową lokalizację.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Proszę wybrać prawidłową ilość pieniędzy.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Proszę wprowadzić liczbę.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Hasło jest nieprawidłowe.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Proszę wprowadzić wartość procentową.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Wartości się nie zgadzają.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Proszę wprowadzić prawidłowy czas.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Proszę wybrać prawidłową strefę czasową.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Proszę wprowadzić prawidłowy adres URL.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Proszę wprowadzić prawidłowy termin wyszukiwania.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Proszę wprowadzić prawidłowy numer telefonu.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Pole wyboru posiada nieprawidłową wartość.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Proszę wprowadzić prawidłowy adres email.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Proszę wybrać prawidłową opcję.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Proszę wybrać prawidłowy zakres.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Proszę wybrać prawidłowy tydzień.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.pt.xlf b/lib/symfony/form/Resources/translations/validators.pt.xlf deleted file mode 100644 index 6ce1c3242..000000000 --- a/lib/symfony/form/Resources/translations/validators.pt.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Este formulário não deveria possuir mais campos.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>O ficheiro enviado é muito grande. Por favor, tente enviar um ficheiro menor.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>O token CSRF está inválido. Por favor, tente enviar o formulário novamente.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Este valor não é uma cor HTML5 válida.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Por favor, informe uma data de nascimento válida.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>A escolha seleccionada é inválida.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>A coleção é inválida.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Por favor, selecione uma cor válida.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Por favor, selecione um país válido.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Por favor, selecione uma moeda válida.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Por favor, escolha um intervalo de datas válido.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Por favor, informe uma data e horário válidos.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Por favor, informe uma data válida.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Por favor, selecione um ficheiro válido.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>O campo oculto é inválido.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Por favor, informe um inteiro.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Por favor selecione um idioma válido.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Por favor, selecione um locale válido.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Por favor, informe um valor monetário válido.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Por favor, informe um número.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>A palavra-passe é inválida.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Por favor, informe um valor percentual.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Os valores não correspondem.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Por favor, informe uma hora válida.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Por favor, selecione um fuso horário válido.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Por favor, informe uma URL válida.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Por favor, informe um termo de busca válido.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Por favor, infome um número de telefone válido.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>O checkbox possui um valor inválido.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Por favor, informe um endereço de email válido.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Por favor, selecione uma opção válida.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Por favor, selecione um intervalo válido.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Por favor, selecione uma semana válida.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.pt_BR.xlf b/lib/symfony/form/Resources/translations/validators.pt_BR.xlf deleted file mode 100644 index 37717fe98..000000000 --- a/lib/symfony/form/Resources/translations/validators.pt_BR.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Este formulário não deve conter campos adicionais.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>O arquivo enviado é muito grande. Por favor, tente enviar um arquivo menor.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>O token CSRF é inválido. Por favor, tente reenviar o formulário.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Este valor não é uma cor HTML5 válida.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Por favor, informe uma data de nascimento válida.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>A escolha selecionada é inválida.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>A coleção é inválida.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Por favor, selecione uma cor válida.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Por favor, selecione um país válido.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Por favor, selecione uma moeda válida.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Por favor, escolha um intervalo de datas válido.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Por favor, informe uma data e horário válidos.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Por favor, informe uma data válida.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Por favor, selecione um arquivo válido.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>O campo oculto é inválido.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Por favor, informe um número inteiro.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Por favor, selecione um idioma válido.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Por favor, selecione uma configuração de local válida.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Por favor, informe um valor monetário válido.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Por favor, informe um número.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>A senha é inválida.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Por favor, informe um valor percentual.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Os valores não conferem.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Por favor, informe um horário válido.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Por favor, selecione um fuso horário válido.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Por favor, informe uma URL válida.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Por favor, informe um termo de busca válido.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Por favor, informe um telefone válido.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>A caixa de seleção possui um valor inválido.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Por favor, informe um endereço de e-mail válido.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Por favor, selecione uma opção válida.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Por favor, selecione um intervalo válido.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Por favor, informe uma semana válida.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.ro.xlf b/lib/symfony/form/Resources/translations/validators.ro.xlf deleted file mode 100644 index a7dc62b57..000000000 --- a/lib/symfony/form/Resources/translations/validators.ro.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Acest formular nu ar trebui să conțină câmpuri suplimentare.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Fișierul încărcat a fost prea mare. Vă rugăm sa încărcați un fișier mai mic.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>Token-ul CSRF este invalid. Vă rugăm să retrimiteți formularul.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Această valoare nu este un cod de culoare HTML5 valid.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Vă rugăm să introduceți o dată de naștere validă.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Valoarea selectată este invalidă.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Colecția nu este validă.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Vă rugăm să selectați o culoare validă.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Vă rugăm să selectați o țară validă.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Vă rugăm să selectați o monedă validă.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Vă rugăm să selectați un interval de zile valid.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Vă rugăm să introduceți o dată și o oră validă.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Vă rugăm să introduceți o dată validă.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Vă rugăm să selectați un fișier valid.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Câmpul ascuns este invalid.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Vă rugăm să introduceți un număr întreg.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Vă rugăm să selectați o limbă validă.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Vă rugăm să selectați o setare locală validă.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Vă rugăm să introduceți o valoare monetară corectă.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Vă rugăm să introduceți un număr.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Parola nu este validă.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Vă rugăm să introduceți o valoare procentuală.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Valorile nu coincid.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Vă rugăm să introduceți o oră validă.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Vă rugăm să selectați un fus orar valid.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Vă rugăm să introduceți un URL valid.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Vă rugăm să introduceți un termen de căutare valid.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Vă rugăm să introduceți un număr de telefon valid.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Bifa nu are o valoare validă.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Vă rugăm să introduceți o adresă de email validă.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Vă rugăm să selectați o opțiune validă.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Vă rugăm să selectați un interval valid.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Vă rugăm să introduceți o săptămână validă.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.ru.xlf b/lib/symfony/form/Resources/translations/validators.ru.xlf deleted file mode 100644 index b11b7cef5..000000000 --- a/lib/symfony/form/Resources/translations/validators.ru.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Эта форма не должна содержать дополнительных полей.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Загруженный файл слишком большой. Пожалуйста, попробуйте загрузить файл меньшего размера.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF значение недопустимо. Пожалуйста, попробуйте повторить отправку формы.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Значение не является допустимым HTML5 цветом.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Пожалуйста, введите действительную дату рождения.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Выбранный вариант недопустим.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Коллекция недопустима.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Пожалуйста, выберите допустимый цвет.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Пожалуйста, выберите действительную страну.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Пожалуйста, выберите действительную валюту.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Пожалуйста, выберите действительный период.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Пожалуйста, введите действительные дату и время.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Пожалуйста, введите действительную дату.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Пожалуйста, выберите допустимый файл.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Значение скрытого поля недопустимо.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Пожалуйста, введите целое число.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Пожалуйста, выберите допустимый язык.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Пожалуйста, выберите допустимую локаль.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Пожалуйста, введите допустимое количество денег.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Пожалуйста, введите номер.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Пароль недействителен.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Пожалуйста, введите процентное значение.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Значения не совпадают.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Пожалуйста, введите действительное время.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Пожалуйста, выберите действительный часовой пояс.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Пожалуйста, введите действительный URL.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Пожалуйста, введите действительный поисковый запрос.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Пожалуйста, введите действительный номер телефона.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Флажок имеет недопустимое значение.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Пожалуйста, введите допустимый email адрес.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Пожалуйста, выберите допустимый вариант.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Пожалуйста, выберите допустимый диапазон.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Пожалуйста, введите действительную неделю.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.sk.xlf b/lib/symfony/form/Resources/translations/validators.sk.xlf deleted file mode 100644 index 06b2bbdbe..000000000 --- a/lib/symfony/form/Resources/translations/validators.sk.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Polia by nemali obsahovať ďalšie prvky.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Odoslaný súbor je príliš veľký. Prosím odošlite súbor s menšou veľkosťou.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF token je neplatný. Prosím skúste znovu odoslať formulár.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Táto hodnota nie je platná HTML5 farba.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Prosím zadajte platný dátum narodenia.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Vybraná možnosť je neplatná.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Kolekcia je neplatná.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Prosím vyberte platnú farbu.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Prosím vyberte platnú krajinu.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Prosím vyberte platnú menu.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Prosím vyberte platný rozsah dát.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Prosím zadajte platný dátum a čas.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Prosím zadajte platný dátum.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Prosím vyberte platný súbor.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Skryté pole je neplatné.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Prosím zadajte celé číslo.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Prosím vyberte platný jazyk.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Prosím vyberte platné miestne nastavenia.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Prosím zadajte platnú čiastku.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Prosím zadajte číslo.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Heslo je neprávne.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Prosím zadajte percentuálnu hodnotu.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Hodnoty nie sú zhodné.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Prosím zadajte platný čas.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Prosím vyberte platné časové pásmo.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Prosím zadajte platnú URL.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Prosím zadajte platný vyhľadávací výraz.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Prosím zadajte platné telefónne číslo.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Zaškrtávacie políčko má neplatnú hodnotu.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Prosím zadajte platnú emailovú adresu.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Prosím vyberte platnú možnosť.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Prosím vyberte platný rozsah.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Prosím zadajte platný týždeň.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.sl.xlf b/lib/symfony/form/Resources/translations/validators.sl.xlf deleted file mode 100644 index 7e6a3fb85..000000000 --- a/lib/symfony/form/Resources/translations/validators.sl.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Ta obrazec ne sme vsebovati dodatnih polj.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Naložena datoteka je prevelika. Prosimo, poizkusite naložiti manjšo.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF vrednost je napačna. Prosimo, ponovno pošljite obrazec.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Ta vrednost ni veljavna barva HTML5.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Prosimo, vnesite veljaven rojstni datum.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Izbira ni veljavna.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Zbirka ni veljavna.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Prosimo, izberite veljavno barvo.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Prosimo, izberite veljavno državo.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Prosimo, izberite veljavno valuto.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Prosimo, izberite veljaven datumski interval.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Prosimo, vnesite veljaven datum in čas.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Prosimo, izberite veljaven datum.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Prosimo, izberite veljavno datoteko.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Skrito polje ni veljavno.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Prosimo, vnesite celo število.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Prosimo, izberite veljaven jezik.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Prosimo, izberite veljavne področne nastavitve.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Prosimo, vnesite veljaven denarni znesek.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Prosimo, vnesite številko.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Geslo ni veljavno.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Prosimo, vnesite odstotno vrednost.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Vrednosti se ne ujemajo.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Prosimo, vnesite veljaven čas.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Prosimo, izberite veljaven časovni pas.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Prosimo, vnesite veljaven URL.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Prosimo, vnesite veljaven iskalni izraz.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Prosimo, podajte veljavno telefonsko številko.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Potrditveno polje vsebuje neveljavno vrednost.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Prosimo, vnesite veljaven e-poštni naslov.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Prosimo, izberite veljavno možnost.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Prosimo, izberite veljaven obseg.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Prosimo, vnesite veljaven teden.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.sq.xlf b/lib/symfony/form/Resources/translations/validators.sq.xlf deleted file mode 100644 index 3224f6e38..000000000 --- a/lib/symfony/form/Resources/translations/validators.sq.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Kjo formë nuk duhet të përmbajë fusha shtesë.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Skedari i ngarkuar ishte shumë i madh. Ju lutemi provoni të ngarkoni një skedar më të vogël.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>Vlera CSRF është e pavlefshme. Ju lutemi provoni të ridërgoni formën.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Kjo vlerë nuk është një ngjyrë e vlefshme HTML5.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Ju lutemi shkruani një datëlindje të vlefshme.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Opsioni i zgjedhur është i pavlefshëm.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Koleksioni është i pavlefshëm.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Ju lutemi zgjidhni një ngjyrë të vlefshme.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Ju lutemi zgjidhni një shtet të vlefshëm.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Ju lutemi zgjidhni një monedhë të vlefshme.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Ju lutemi zgjidhni një interval të vlefshëm të datës.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Ju lutemi shkruani një datë dhe orë të vlefshme.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Ju lutemi shkruani një datë të vlefshme.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Ju lutemi zgjidhni një skedar të vlefshëm.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Fusha e fshehur është e pavlefshme.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Ju lutemi shkruani një numër të plotë.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Please select a valid language.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Ju lutemi zgjidhni një lokale të vlefshme.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Ju lutemi shkruani një shumë të vlefshme parash.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Ju lutemi shkruani një numër.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Fjalëkalimi është i pavlefshëm.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Ju lutemi shkruani një vlerë përqindjeje.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Vlerat nuk përputhen.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Ju lutemi shkruani një kohë të vlefshme.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Ju lutemi zgjidhni një zonë kohore të vlefshme.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Ju lutemi shkruani një URL të vlefshme.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Ju lutemi shkruani një term të vlefshëm kërkimi.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Ju lutemi jepni një numër telefoni të vlefshëm.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Kutia e zgjedhjes ka një vlerë të pavlefshme.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Ju lutemi shkruani një adresë të vlefshme emaili.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Ju lutemi zgjidhni një opsion të vlefshëm.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Ju lutemi zgjidhni një diapazon të vlefshëm.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Ju lutemi shkruani një javë të vlefshme.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.sr_Cyrl.xlf b/lib/symfony/form/Resources/translations/validators.sr_Cyrl.xlf deleted file mode 100644 index a5610e0ea..000000000 --- a/lib/symfony/form/Resources/translations/validators.sr_Cyrl.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Овај формулар не треба да садржи додатна поља.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Отпремљена датотека је била превелика. Молим покушајте отпремање мање датотеке.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF вредност није исправна. Покушајте поново.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Ова вредност није исправна HTML5 боја.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Молим упишите исправан датум рођења.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Одабрани избор није исправан.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Ова колекција није исправна.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Молим изаберите исправну боју.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Молим изаберите исправну државу.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Молим изаберите исправну валуту.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Молим изаберите исправан датумски интервал.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Молим упишите исправан датум и време.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Молим упишите исправан датум.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Молим изаберите исправну датотеку.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Скривено поље није исправно.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Молим упишите цео број (integer).</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Молим изаберите исправан језик.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Молим изаберите исправну локализацију.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Молим упишите исправну количину новца.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Молим упишите број.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Ова лозинка није исправна.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Молим упишите процентуалну вредност.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Дате вредности се не поклапају.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Молим упишите исправно време.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Молим изаберите исправну временску зону.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Молим упишите исправан URL.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Молим упишите исправан термин за претрагу.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Молим наведите исправан број телефона.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Поље за потврду садржи неисправну вредност.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Молим упишите исправну email адресу.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Молим изаберите исправну опцију.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Молим изаберите исправан опсег.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Молим упишите исправну седмицу.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.sr_Latn.xlf b/lib/symfony/form/Resources/translations/validators.sr_Latn.xlf deleted file mode 100644 index 02fb5aa56..000000000 --- a/lib/symfony/form/Resources/translations/validators.sr_Latn.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Ovaj formular ne treba da sadrži dodatna polja.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Otpremljena datoteka je bila prevelika. Molim pokušajte otpremanje manje datoteke.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF vrednost nije ispravna. Pokušajte ponovo.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Ova vrednost nije ispravna HTML5 boja.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Molim upišite ispravan datum rođenja.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Odabrani izbor nije ispravan.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Ova kolekcija nije ispravna.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Molim izaberite ispravnu boju.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Molim izaberite ispravnu državu.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Molim izaberite ispravnu valutu.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Molim izaberite ispravan datumski interval.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Molim upišite ispravan datum i vreme.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Molim upišite ispravan datum.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Molim izaberite ispravnu datoteku.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Skriveno polje nije ispravno.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Molim upišite ceo broj (integer).</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Molim izaberite ispravan jezik.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Molim izaberite ispravnu lokalizaciju.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Molim upišite ispravnu količinu novca.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Molim upišite broj.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Ova lozinka nije ispravna.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Molim upišite procentualnu vrednost.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Date vrednosti se ne poklapaju.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Molim upišite ispravno vreme.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Molim izaberite ispravnu vremensku zonu.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Molim upišite ispravan URL.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Molim upišite ispravan termin za pretragu.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Molim navedite ispravan broj telefona.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Polje za potvrdu sadrži neispravnu vrednost.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Molim upišite ispravnu email adresu.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Molim izaberite ispravnu opciju.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Molim izaberite ispravan opseg.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Molim upišite ispravnu sedmicu.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.sv.xlf b/lib/symfony/form/Resources/translations/validators.sv.xlf deleted file mode 100644 index 43e925628..000000000 --- a/lib/symfony/form/Resources/translations/validators.sv.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Formuläret kan inte innehålla extra fält.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Den uppladdade filen var för stor. Försök ladda upp en mindre fil.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF-elementet är inte giltigt. Försök att skicka formuläret igen.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Värdet är inte en giltig HTML5-färg.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Ange ett giltigt födelsedatum.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Det valda alternativet är ogiltigt.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Den här samlingen är ogiltig.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Välj en giltig färg.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Välj ett land.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Välj en valuta.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Välj ett giltigt datumintervall.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Ange ett giltigt datum och tid.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Ange ett giltigt datum.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Välj en fil.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Det dolda fältet är ogiltigt.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Ange ett heltal.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Välj språk.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Välj plats.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Ange en giltig summa pengar.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Ange en siffra.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Lösenordet är ogiltigt.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Ange ett procentuellt värde.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>De angivna värdena stämmer inte överens.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Ange en giltig tid.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Välj en tidszon.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Ange en giltig URL.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Ange ett giltigt sökbegrepp.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Ange ett giltigt telefonnummer.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Kryssrutan har ett ogiltigt värde.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Ange en giltig e-postadress.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Välj ett alternativ.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Välj ett intervall.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Ange en giltig vecka.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.th.xlf b/lib/symfony/form/Resources/translations/validators.th.xlf deleted file mode 100644 index 060dc9ec4..000000000 --- a/lib/symfony/form/Resources/translations/validators.th.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="th" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>ฟอร์มนี้ไม่ควรมี extra fields</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>ไฟล์ที่อัพโหลดมีขนาดใหญ่เกินไป กรุณาลองอัพโหลดใหม่อีกครั้งด้วยไฟล์ที่มีขนาดเล็กลง</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF token ไม่ถูกต้อง กรุณาลองส่งแบบฟอร์มใหม่</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>ค่านี้ไม่ใช่ค่าที่ถูกต้องของค่าสี HTML5</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>กรุณากรอกวันเดือนปีเกิดที่ถูกต้อง</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>ตัวเลือกที่เลิอกไม่ถูกต้อง</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>คอเล็กชั่นไม่ถูกต้อง</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>กรุณาเลือกค่าสีที่ถูกต้อง</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>กรุณาเลือกประเทศที่ถูกต้อง</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>กรุุณาเลิอกค่าสกุลเงินที่ถูกต้อง</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>กรุณณากรอกช่วงวันที่ที่ถูกต้อง</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>กรุณณากรอกค่าเวลาและวันที่ที่ถูกต้อง</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>กรุณณากรอกค่าวันที่ที่ถูกต้อง</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>กรุณาเลือกไฟล์ที่ถูกต้อง</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>ค่า Hidden field ไม่ถูกต้อง</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>กรุณากรอกตัวเลขจำนวนเต็ม</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>กรุณาเลือกภาษาที่ถูกต้อง</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>กรุณาเลือกท้องถิ่นที่ถูกต้อง</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>กรุณากรอกจำนวนเงินที่ถูกต้อง</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>กรุณากรอกตัวเลข</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>รหัสผ่านไม่ถูกต้อง</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>กรุณากรอกค่าเปอร์เซ็นต์</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>ค่าทั้งสองไม่ตรงกัน</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>กรุณากรอกค่าเวลาที่ถูกต้อง</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>กรุณาเลือกค่าเขตเวลาที่ถูกต้อง</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>กรุณากรอก URL ที่ถูกต้อง</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>กรุณากรอกคำค้นหาที่ถูกต้อง</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>กรุณากรอกเบอร์โทรศัพท์ที่ถูกต้อง</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Checkbox มีค่าที่ไม่ถูกต้อง</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>กรุณากรอกที่อยู่อีเมล์ที่ถูกต้อง</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>กรุณาเลือกตัวเลือกที่ถูกต้อง</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>กรุณาเลือกค่าช่วงที่ถูกต้อง</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>กรุณากรอกค่าสัปดาห์ที่ถูกต้อง</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.tl.xlf b/lib/symfony/form/Resources/translations/validators.tl.xlf deleted file mode 100644 index 272e33129..000000000 --- a/lib/symfony/form/Resources/translations/validators.tl.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Ang pormang itong ay hindi dapat magkarron ng dagdag na mga patlang.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Ang ini-upload na file ay masyadong malaki. Pakiulit muling mag-upload ng mas maliit na file.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>Hindi balido ang CSRF token. Maagpasa muli ng isang pang porma.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Ang halagang ito ay hindi wastong HTML5 color.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Pakilagay ang tamang petsa ng kapanganakan.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Ang pinagpiliang sagot ay hindi tama.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Hindi balido ang koleksyon.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Pakipiliin ang nararapat na kulay.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Pakipiliin ang nararapat na bansa.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Pakipiliin ang tamang pananalapi.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Piliin ang wastong agwat ng petsa.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Piliin ang wastong petsa at oras.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Ilagay ang wastong petsa.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Piliin ang balidong file.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Hindi balido ang field na nakatago.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Pakilagay ang integer.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Piliin ang nararapat na lengguwahe.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Pakipili ang nararapat na locale.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Pakilagay ang tamang halaga ng pera.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Ilagay ang numero.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Hindi balido ang password.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Pakilagay ang tamang porsyento ng halaga.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Hindi tugma ang mga halaga.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Pakilagay ang tamang oras.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Pakilagay ang tamang sona ng oras.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Pakilagay ang balidong URL.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Pakilagay ang balidong katagang sinasaliksik.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Pakilagay ang balidong numero ng telepono.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Ang checkbox ay mayroon hindi balidong halaga.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Pakilagay ang balidong email address.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Pakipiliin ang balidong pagpipilian.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Pakipilian ang balidong layo.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Pakilagay ang balidong linggo.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.tr.xlf b/lib/symfony/form/Resources/translations/validators.tr.xlf deleted file mode 100644 index d1ddc1d0e..000000000 --- a/lib/symfony/form/Resources/translations/validators.tr.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Form ekstra alanlar içeremez.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Yüklenen dosya boyutu çok yüksek. Lütfen daha küçük bir dosya yüklemeyi deneyin.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF fişi geçersiz. Formu tekrar göndermeyi deneyin.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Bu değer, geçerli bir HTML5 rengi değil.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Lütfen geçerli bir doğum tarihi girin.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Seçilen seçim geçersiz.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Koleksiyon geçersiz.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Lütfen geçerli bir renk seçin.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Lütfen geçerli bir ülke seçin.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Lütfen geçerli bir para birimi seçin.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Lütfen geçerli bir tarih aralığı seçin.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Lütfen geçerli bir tarih ve saat girin.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Lütfen geçerli bir tarih giriniz.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Lütfen geçerli bir dosya seçin.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Gizli alan geçersiz.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Lütfen bir tam sayı girin.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Lütfen geçerli bir dil seçin.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Lütfen geçerli bir yerel ayar seçin.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Lütfen geçerli bir para tutarı girin.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Lütfen bir numara giriniz.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Şifre geçersiz.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Lütfen bir yüzde değeri girin.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Değerler eşleşmiyor.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Lütfen geçerli bir zaman girin.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Lütfen geçerli bir saat dilimi seçin.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Lütfen geçerli bir giriniz URL.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Lütfen geçerli bir arama terimi girin.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>lütfen geçerli bir telefon numarası sağlayın.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Onay kutusunda geçersiz bir değer var.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Lütfen geçerli bir e-posta adresi girin.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Lütfen geçerli bir seçenek seçin.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Lütfen geçerli bir aralık seçin.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Lütfen geçerli bir hafta girin.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.uk.xlf b/lib/symfony/form/Resources/translations/validators.uk.xlf deleted file mode 100644 index ca707bcff..000000000 --- a/lib/symfony/form/Resources/translations/validators.uk.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Ця форма не повинна містити додаткових полів.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Завантажений файл занадто великий. Будь ласка, спробуйте завантажити файл меншого розміру.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF значення недопустиме. Будь ласка, спробуйте відправити форму знову.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Це значення не є допустимим кольором HTML5.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Будь ласка, введіть дійсну дату народження.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Обраний варіант недійсний.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Колекція недійсна.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Будь ласка, оберіть дійсний колір.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Будь ласка, оберіть дійсну країну.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Будь ласка, оберіть дійсну валюту.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Будь ласка, оберіть дійсний інтервал дати.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Будь ласка, введіть дійсну дату та час.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Будь ласка, введіть дійсну дату.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Будь ласка, оберіть дійсний файл.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Приховане поле недійсне.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Будь ласка, введіть ціле число.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Будь ласка, оберіть дійсну мову.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Будь ласка, оберіть дійсну локаль.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Будь ласка, введіть дійсну суму грошей.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Будь ласка, введіть число.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Пароль недійсний.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Будь ласка, введіть процентне значення.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Значення не збігаються.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Будь ласка, введіть дійсний час.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Будь ласка, оберіть дійсний часовий пояс.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Будь ласка, введіть дійсну URL-адресу.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Будь ласка, введіть дійсний пошуковий термін.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Будь ласка, введіть дійсний номер телефону.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Прапорець має недійсне значення.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Будь ласка, введіть дійсну адресу електронної пошти.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Будь ласка, оберіть дійсний варіант.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Будь ласка, оберіть дійсний діапазон.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Будь ласка, введіть дійсний тиждень.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.ur.xlf b/lib/symfony/form/Resources/translations/validators.ur.xlf deleted file mode 100644 index 1ec61be6d..000000000 --- a/lib/symfony/form/Resources/translations/validators.ur.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="ur" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>اس فارم میں اضافی فیلڈز نہیں ہونی چاہئیں</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>اپ لوڈ کردھ فائل بہت بڑی تھی۔ براہ کرم ایک چھوٹی فائل اپ لوڈ کرنے کی کوشش کریں</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>ٹوکن غلط ہے۔ براۓ کرم فارم کو دوبارہ جمع کرانے کی کوشش کریں CSRF</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>ر نگ نھیں ھےHTML یھ ولیو در ست</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>براۓ کرم درست تاریخ پیدائش درج کریں</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>منتخب کردہ انتخاب غلط ہے</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>یھ مجموعہ غلط ہے</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>براۓ کرم ایک درست رنگ منتخب کریں</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>براۓ کرم ایک درست ملک منتخب کریں</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>براۓ کرم ایک درست کرنسی منتخب کریں</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>براۓ کرم ایک درست تاریخی وقفھہ منتخب کریں</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>براۓ کرم ایک درست تاریخ اور وقت درج کریں</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>براۓ کرم ایک درست تاریخ درج کریں</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>براۓ کرم ایک درست فائل منتخب کریں</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>پوشیدھہ فیلڈ غلط ہے</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>براۓ کرم ایک عدد درج کریں</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>براۓ کرم ایک درست زبان منتخب کریں</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>براۓ کرم ایک درست مقام منتخب کریں</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>براۓ کرم ایک درست رقم درج کریں</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>براۓ کرم ایک نمبر درج کریں</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>پاس ورڈ غلط ہے</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>براہ کرم فیصد کی ويلو درج کریں</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>ويليوذ ٹھيک نہیں ہیں</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>براۓ کرم ایک درست وقت درج کریں</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>براۓ کرم ایک درست ٹائم زون منتخب کریں</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>براۓ کرم ایک درست ادريس درج کریں</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>براۓ کرم ایک درست ويلو تلاش کيلۓ درج کریں</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>براۓ کرم ایک درست فون نمبر فراہم کریں</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>چیک باکس میں ایک غلط ويلو ہے</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>براۓ مہربانی قابل قبول ای میل ایڈریس لکھیں</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>براۓ کرم ایک درست آپشن منتخب کریں</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>براۓ کرم ایک درست رینج منتخب کریں</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>براۓ کرم ایک درست ہفتہ درج کریں</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.uz.xlf b/lib/symfony/form/Resources/translations/validators.uz.xlf deleted file mode 100644 index 58591d69e..000000000 --- a/lib/symfony/form/Resources/translations/validators.uz.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Ushbu fo'rmada qo'shimcha maydonlar bo'lmasligi kerak.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Yuklab olingan fayl juda katta. Iltimos, kichikroq faylni yuklashga harakat qiling.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF qiymati yaroqsiz. Fo'rmani qayta yuborishga harakat qiling.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Qiymat noto'g'ri, HTML5 rangi emas.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Iltimos, tug'ilgan kuningizni to'g'ri kiriting.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Tanlangan parametr noto'g'ri.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Kolleksiya noto'g'ri</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Iltimos, to'g'ri rang tanlang.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Iltimos, to'g'ri mamlakatni tanlang.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Iltimos, to'g'ri valyutani tanlang.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Iltimos, to'g'ri sana oralig'ini tanlang.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Iltimos, to'g'ri sana va vaqtni kiriting.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Iltimos, to'g'ri sanani kiriting.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Iltimos, to'g'ri faylni tanlang.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Yashirin maydon qiymati yaroqsiz.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Iltimos, butun son kiriting.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Iltimos, to'g'ri tilni tanlang.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Iltimos, to'g'ri localni tanlang.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Iltimos, tegishli miqdordagi pulni kiriting.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Iltimos, raqam kiriting.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Parol noto'g'ri.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Iltimos, foyizli qiymat kiriting.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Qiymatlar mos kelmaydi.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Iltimos, to'g'ri vaqtni tanlang.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Iltimos, to'g'ri vaqt zonasini tanlang.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Iltimos, to'g'ri URL kiriting.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Iltimos, to'g'ri qidiruv so'zini kiriting.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Iltimos, to'g'ri telefon raqamini kiriting.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Belgilash katagida yaroqsiz qiymat mavjud.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Iltimos, to'g'ri email kiriting.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Iltimos, yaroqli variantni tanlang.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Iltimos, yaroqli oraliqni tanlang.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Iltimos, haqiqiy haftani kiriting.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.vi.xlf b/lib/symfony/form/Resources/translations/validators.vi.xlf deleted file mode 100644 index 6a8f2bd86..000000000 --- a/lib/symfony/form/Resources/translations/validators.vi.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>Mẫu này không nên chứa trường mở rộng.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>Tập tin tải lên quá lớn. Vui lòng thử lại với tập tin nhỏ hơn.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF token không hợp lệ. Vui lòng thử lại.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>Giá trị này không phải là màu HTML5 hợp lệ.</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>Vui lòng nhập ngày sinh hợp lệ.</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>Lựa chọn không hợp lệ.</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>Danh sách không hợp lệ.</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>Vui lòng chọn một màu hợp lệ.</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>Vui lòng chọn đất nước hợp lệ.</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>Vui lòng chọn tiền tệ hợp lệ.</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>Vui lòng chọn một khoảng thời gian hợp lệ.</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>Vui lòng nhập ngày và thời gian hợp lệ.</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>Vui lòng nhập ngày hợp lệ.</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>Vui lòng chọn tệp hợp lệ.</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>Phạm vi ẩn không hợp lệ.</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>Vui lòng nhập một số nguyên.</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>Vui lòng chọn ngôn ngữ hợp lệ.</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>Vui lòng chọn miền hợp lệ.</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>Vui lòng nhập một khoảng tiền hợp lệ.</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>Vui lòng nhập một con số.</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>Mật khẩu không hợp lệ.</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>Vui lòng nhập một giá trị phần trăm.</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>Các giá trị không phù hợp.</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>Vui lòng nhập thời gian hợp lệ.</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>Vui lòng chọn múi giờ hợp lệ.</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>Vui lòng nhập một URL hợp lệ.</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>Vui lòng nhập chuỗi tìm kiếm hợp lệ.</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>Vui lòng cung cấp số điện thoại hợp lệ.</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>Hộp kiểm có một giá trị không hợp lệ.</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>Vui lòng nhập địa chỉ email hợp lệ.</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>Vui lòng chọn một phương án hợp lệ.</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>Vui lòng nhập một phạm vi hợp lệ.</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>Vui lòng nhập một tuần hợp lệ.</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.zh_CN.xlf b/lib/symfony/form/Resources/translations/validators.zh_CN.xlf deleted file mode 100644 index 3106db2bd..000000000 --- a/lib/symfony/form/Resources/translations/validators.zh_CN.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>该表单中不可有额外字段.</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>上传文件太大, 请重新尝试上传一个较小的文件.</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF 验证符无效, 请重新提交.</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>该数值不是个有效的 HTML5 颜色。</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>请输入有效的生日日期。</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>所选的选项无效。</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>集合无效。</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>请选择有效的颜色。</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>请选择有效的国家。</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>请选择有效的货币。</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>请选择有效的日期间隔。</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>请输入有效的日期与时间。</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>请输入有效的日期。</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>请选择有效的文件。</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>隐藏字段无效。</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>请输入整数。</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>请选择有效的语言。</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>请选择有效的语言环境。</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>请输入正确的金额。</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>请输入数字。</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>密码无效。</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>请输入百分比值。</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>数值不匹配。</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>请输入有效的时间。</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>请选择有效的时区。</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>请输入有效的网址。</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>请输入有效的搜索词。</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>请提供有效的手机号码。</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>无效的选框值。</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>请输入有效的电子邮件地址。</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>请选择有效的选项。</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>请选择有效的范围。</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>请输入有效的星期。</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/Resources/translations/validators.zh_TW.xlf b/lib/symfony/form/Resources/translations/validators.zh_TW.xlf deleted file mode 100644 index 858b9db42..000000000 --- a/lib/symfony/form/Resources/translations/validators.zh_TW.xlf +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="file.ext"> - <body> - <trans-unit id="28"> - <source>This form should not contain extra fields.</source> - <target>該表單中不可有額外字段。</target> - </trans-unit> - <trans-unit id="29"> - <source>The uploaded file was too large. Please try to upload a smaller file.</source> - <target>上傳文件太大, 請重新嘗試上傳一個較小的文件。</target> - </trans-unit> - <trans-unit id="30"> - <source>The CSRF token is invalid. Please try to resubmit the form.</source> - <target>CSRF 驗證符無效, 請重新提交。</target> - </trans-unit> - <trans-unit id="99"> - <source>This value is not a valid HTML5 color.</source> - <target>該數值不是個有效的 HTML5 顏色。</target> - </trans-unit> - <trans-unit id="100"> - <source>Please enter a valid birthdate.</source> - <target>請輸入有效的生日日期。</target> - </trans-unit> - <trans-unit id="101"> - <source>The selected choice is invalid.</source> - <target>所選的選項無效。</target> - </trans-unit> - <trans-unit id="102"> - <source>The collection is invalid.</source> - <target>集合無效。</target> - </trans-unit> - <trans-unit id="103"> - <source>Please select a valid color.</source> - <target>請選擇有效的顏色。</target> - </trans-unit> - <trans-unit id="104"> - <source>Please select a valid country.</source> - <target>請選擇有效的國家。</target> - </trans-unit> - <trans-unit id="105"> - <source>Please select a valid currency.</source> - <target>請選擇有效的貨幣。</target> - </trans-unit> - <trans-unit id="106"> - <source>Please choose a valid date interval.</source> - <target>請選擇有效的日期間隔。</target> - </trans-unit> - <trans-unit id="107"> - <source>Please enter a valid date and time.</source> - <target>請輸入有效的日期與時間。</target> - </trans-unit> - <trans-unit id="108"> - <source>Please enter a valid date.</source> - <target>請輸入有效的日期。</target> - </trans-unit> - <trans-unit id="109"> - <source>Please select a valid file.</source> - <target>請選擇有效的文件。</target> - </trans-unit> - <trans-unit id="110"> - <source>The hidden field is invalid.</source> - <target>隱藏字段無效。</target> - </trans-unit> - <trans-unit id="111"> - <source>Please enter an integer.</source> - <target>請輸入整數。</target> - </trans-unit> - <trans-unit id="112"> - <source>Please select a valid language.</source> - <target>請選擇有效的語言。</target> - </trans-unit> - <trans-unit id="113"> - <source>Please select a valid locale.</source> - <target>請選擇有效的語言環境。</target> - </trans-unit> - <trans-unit id="114"> - <source>Please enter a valid money amount.</source> - <target>請輸入正確的金額。</target> - </trans-unit> - <trans-unit id="115"> - <source>Please enter a number.</source> - <target>請輸入數字。</target> - </trans-unit> - <trans-unit id="116"> - <source>The password is invalid.</source> - <target>密碼無效。</target> - </trans-unit> - <trans-unit id="117"> - <source>Please enter a percentage value.</source> - <target>請輸入百分比值。</target> - </trans-unit> - <trans-unit id="118"> - <source>The values do not match.</source> - <target>數值不匹配。</target> - </trans-unit> - <trans-unit id="119"> - <source>Please enter a valid time.</source> - <target>請輸入有效的時間。</target> - </trans-unit> - <trans-unit id="120"> - <source>Please select a valid timezone.</source> - <target>請選擇有效的時區。</target> - </trans-unit> - <trans-unit id="121"> - <source>Please enter a valid URL.</source> - <target>請輸入有效的網址。</target> - </trans-unit> - <trans-unit id="122"> - <source>Please enter a valid search term.</source> - <target>請輸入有效的搜索詞。</target> - </trans-unit> - <trans-unit id="123"> - <source>Please provide a valid phone number.</source> - <target>請提供有效的手機號碼。</target> - </trans-unit> - <trans-unit id="124"> - <source>The checkbox has an invalid value.</source> - <target>無效的選框值。</target> - </trans-unit> - <trans-unit id="125"> - <source>Please enter a valid email address.</source> - <target>請輸入有效的電子郵件地址。</target> - </trans-unit> - <trans-unit id="126"> - <source>Please select a valid option.</source> - <target>請選擇有效的選項。</target> - </trans-unit> - <trans-unit id="127"> - <source>Please select a valid range.</source> - <target>請選擇有效的範圍。</target> - </trans-unit> - <trans-unit id="128"> - <source>Please enter a valid week.</source> - <target>請輸入有效的星期。</target> - </trans-unit> - </body> - </file> -</xliff> diff --git a/lib/symfony/form/ReversedTransformer.php b/lib/symfony/form/ReversedTransformer.php deleted file mode 100644 index 8089e47bf..000000000 --- a/lib/symfony/form/ReversedTransformer.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -/** - * Reverses a transformer. - * - * When the transform() method is called, the reversed transformer's - * reverseTransform() method is called and vice versa. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class ReversedTransformer implements DataTransformerInterface -{ - protected $reversedTransformer; - - public function __construct(DataTransformerInterface $reversedTransformer) - { - $this->reversedTransformer = $reversedTransformer; - } - - /** - * {@inheritdoc} - */ - public function transform($value) - { - return $this->reversedTransformer->reverseTransform($value); - } - - /** - * {@inheritdoc} - */ - public function reverseTransform($value) - { - return $this->reversedTransformer->transform($value); - } -} diff --git a/lib/symfony/form/SubmitButton.php b/lib/symfony/form/SubmitButton.php deleted file mode 100644 index 520f223e2..000000000 --- a/lib/symfony/form/SubmitButton.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -/** - * A button that submits the form. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class SubmitButton extends Button implements ClickableInterface -{ - private $clicked = false; - - /** - * {@inheritdoc} - */ - public function isClicked() - { - return $this->clicked; - } - - /** - * Submits data to the button. - * - * @param array|string|null $submittedData The data - * @param bool $clearMissing Not used - * - * @return $this - * - * @throws Exception\AlreadySubmittedException if the form has already been submitted - */ - public function submit($submittedData, bool $clearMissing = true) - { - if ($this->getConfig()->getDisabled()) { - $this->clicked = false; - - return $this; - } - - parent::submit($submittedData, $clearMissing); - - $this->clicked = null !== $submittedData; - - return $this; - } -} diff --git a/lib/symfony/form/SubmitButtonBuilder.php b/lib/symfony/form/SubmitButtonBuilder.php deleted file mode 100644 index 3045e0ddd..000000000 --- a/lib/symfony/form/SubmitButtonBuilder.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -/** - * A builder for {@link SubmitButton} instances. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class SubmitButtonBuilder extends ButtonBuilder -{ - /** - * Creates the button. - * - * @return SubmitButton - */ - public function getForm() - { - return new SubmitButton($this->getFormConfig()); - } -} diff --git a/lib/symfony/form/SubmitButtonTypeInterface.php b/lib/symfony/form/SubmitButtonTypeInterface.php deleted file mode 100644 index f7ac13f7e..000000000 --- a/lib/symfony/form/SubmitButtonTypeInterface.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -/** - * A type that should be converted into a {@link SubmitButton} instance. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface SubmitButtonTypeInterface extends FormTypeInterface -{ -} diff --git a/lib/symfony/form/Test/FormBuilderInterface.php b/lib/symfony/form/Test/FormBuilderInterface.php deleted file mode 100644 index 185a8a12d..000000000 --- a/lib/symfony/form/Test/FormBuilderInterface.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Test; - -use Symfony\Component\Form\FormBuilderInterface as BaseFormBuilderInterface; - -interface FormBuilderInterface extends \Iterator, BaseFormBuilderInterface -{ -} diff --git a/lib/symfony/form/Test/FormIntegrationTestCase.php b/lib/symfony/form/Test/FormIntegrationTestCase.php deleted file mode 100644 index 4feb8df5a..000000000 --- a/lib/symfony/form/Test/FormIntegrationTestCase.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Test; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Form\FormFactoryInterface; -use Symfony\Component\Form\Forms; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -abstract class FormIntegrationTestCase extends TestCase -{ - /** - * @var FormFactoryInterface - */ - protected $factory; - - protected function setUp(): void - { - $this->factory = Forms::createFormFactoryBuilder() - ->addExtensions($this->getExtensions()) - ->addTypeExtensions($this->getTypeExtensions()) - ->addTypes($this->getTypes()) - ->addTypeGuessers($this->getTypeGuessers()) - ->getFormFactory(); - } - - protected function getExtensions() - { - return []; - } - - protected function getTypeExtensions() - { - return []; - } - - protected function getTypes() - { - return []; - } - - protected function getTypeGuessers() - { - return []; - } -} diff --git a/lib/symfony/form/Test/FormInterface.php b/lib/symfony/form/Test/FormInterface.php deleted file mode 100644 index 4af460308..000000000 --- a/lib/symfony/form/Test/FormInterface.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Test; - -use Symfony\Component\Form\FormInterface as BaseFormInterface; - -interface FormInterface extends \Iterator, BaseFormInterface -{ -} diff --git a/lib/symfony/form/Test/FormPerformanceTestCase.php b/lib/symfony/form/Test/FormPerformanceTestCase.php deleted file mode 100644 index 732f9ec3d..000000000 --- a/lib/symfony/form/Test/FormPerformanceTestCase.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Test; - -use Symfony\Component\Form\Tests\VersionAwareTest; - -/** - * Base class for performance tests. - * - * Copied from Doctrine 2's OrmPerformanceTestCase. - * - * @author robo - * @author Bernhard Schussek <bschussek@gmail.com> - */ -abstract class FormPerformanceTestCase extends FormIntegrationTestCase -{ - use VersionAwareTest; - - /** - * @var int - */ - protected $maxRunningTime = 0; - - /** - * {@inheritdoc} - */ - protected function runTest() - { - $s = microtime(true); - parent::runTest(); - $time = microtime(true) - $s; - - if (0 != $this->maxRunningTime && $time > $this->maxRunningTime) { - $this->fail(sprintf('expected running time: <= %s but was: %s', $this->maxRunningTime, $time)); - } - } - - /** - * @throws \InvalidArgumentException - */ - public function setMaxRunningTime(int $maxRunningTime) - { - if ($maxRunningTime < 0) { - throw new \InvalidArgumentException(); - } - - $this->maxRunningTime = $maxRunningTime; - } - - /** - * @return int - */ - public function getMaxRunningTime() - { - return $this->maxRunningTime; - } -} diff --git a/lib/symfony/form/Test/Traits/ValidatorExtensionTrait.php b/lib/symfony/form/Test/Traits/ValidatorExtensionTrait.php deleted file mode 100644 index b4b35fadf..000000000 --- a/lib/symfony/form/Test/Traits/ValidatorExtensionTrait.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Test\Traits; - -use Symfony\Component\Form\Extension\Validator\ValidatorExtension; -use Symfony\Component\Form\Test\TypeTestCase; -use Symfony\Component\Validator\ConstraintViolationList; -use Symfony\Component\Validator\Mapping\ClassMetadata; -use Symfony\Component\Validator\Validator\ValidatorInterface; - -trait ValidatorExtensionTrait -{ - /** - * @var ValidatorInterface|null - */ - protected $validator; - - protected function getValidatorExtension(): ValidatorExtension - { - if (!interface_exists(ValidatorInterface::class)) { - throw new \Exception('In order to use the "ValidatorExtensionTrait", the symfony/validator component must be installed.'); - } - - if (!$this instanceof TypeTestCase) { - throw new \Exception(sprintf('The trait "ValidatorExtensionTrait" can only be added to a class that extends "%s".', TypeTestCase::class)); - } - - $this->validator = $this->createMock(ValidatorInterface::class); - $metadata = $this->getMockBuilder(ClassMetadata::class)->setConstructorArgs([''])->setMethods(['addPropertyConstraint'])->getMock(); - $this->validator->expects($this->any())->method('getMetadataFor')->will($this->returnValue($metadata)); - $this->validator->expects($this->any())->method('validate')->will($this->returnValue(new ConstraintViolationList())); - - return new ValidatorExtension($this->validator, false); - } -} diff --git a/lib/symfony/form/Test/TypeTestCase.php b/lib/symfony/form/Test/TypeTestCase.php deleted file mode 100644 index a925c555e..000000000 --- a/lib/symfony/form/Test/TypeTestCase.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Test; - -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\Form\FormBuilder; -use Symfony\Component\Form\Test\Traits\ValidatorExtensionTrait; - -abstract class TypeTestCase extends FormIntegrationTestCase -{ - /** - * @var FormBuilder - */ - protected $builder; - - /** - * @var EventDispatcherInterface - */ - protected $dispatcher; - - protected function setUp(): void - { - parent::setUp(); - - $this->dispatcher = $this->createMock(EventDispatcherInterface::class); - $this->builder = new FormBuilder('', null, $this->dispatcher, $this->factory); - } - - protected function tearDown(): void - { - if (\in_array(ValidatorExtensionTrait::class, class_uses($this))) { - $this->validator = null; - } - } - - protected function getExtensions() - { - $extensions = []; - - if (\in_array(ValidatorExtensionTrait::class, class_uses($this))) { - $extensions[] = $this->getValidatorExtension(); - } - - return $extensions; - } - - public static function assertDateTimeEquals(\DateTime $expected, \DateTime $actual) - { - self::assertEquals($expected->format('c'), $actual->format('c')); - } - - public static function assertDateIntervalEquals(\DateInterval $expected, \DateInterval $actual) - { - self::assertEquals($expected->format('%RP%yY%mM%dDT%hH%iM%sS'), $actual->format('%RP%yY%mM%dDT%hH%iM%sS')); - } -} diff --git a/lib/symfony/form/Util/FormUtil.php b/lib/symfony/form/Util/FormUtil.php deleted file mode 100644 index fed96de4f..000000000 --- a/lib/symfony/form/Util/FormUtil.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Util; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class FormUtil -{ - /** - * This class should not be instantiated. - */ - private function __construct() - { - } - - /** - * Returns whether the given data is empty. - * - * This logic is reused multiple times throughout the processing of - * a form and needs to be consistent. PHP keyword `empty` cannot - * be used as it also considers 0 and "0" to be empty. - * - * @param mixed $data - * - * @return bool - */ - public static function isEmpty($data) - { - // Should not do a check for [] === $data!!! - // This method is used in occurrences where arrays are - // not considered to be empty, ever. - return null === $data || '' === $data; - } -} diff --git a/lib/symfony/form/Util/InheritDataAwareIterator.php b/lib/symfony/form/Util/InheritDataAwareIterator.php deleted file mode 100644 index 7cba17dbe..000000000 --- a/lib/symfony/form/Util/InheritDataAwareIterator.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Util; - -/** - * Iterator that traverses an array of forms. - * - * Contrary to \ArrayIterator, this iterator recognizes changes in the original - * array during iteration. - * - * You can wrap the iterator into a {@link \RecursiveIteratorIterator} in order to - * enter any child form that inherits its parent's data and iterate the children - * of that form as well. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class InheritDataAwareIterator extends \IteratorIterator implements \RecursiveIterator -{ - /** - * {@inheritdoc} - * - * @return static - */ - #[\ReturnTypeWillChange] - public function getChildren() - { - return new static($this->current()); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function hasChildren() - { - return (bool) $this->current()->getConfig()->getInheritData(); - } -} diff --git a/lib/symfony/form/Util/OptionsResolverWrapper.php b/lib/symfony/form/Util/OptionsResolverWrapper.php deleted file mode 100644 index 078f93dd9..000000000 --- a/lib/symfony/form/Util/OptionsResolverWrapper.php +++ /dev/null @@ -1,110 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Util; - -use Symfony\Component\OptionsResolver\Exception\AccessException; -use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException; -use Symfony\Component\OptionsResolver\OptionsResolver; - -/** - * @author Yonel Ceruto <yonelceruto@gmail.com> - * - * @internal - */ -class OptionsResolverWrapper extends OptionsResolver -{ - private $undefined = []; - - /** - * @return $this - */ - public function setNormalizer(string $option, \Closure $normalizer): self - { - try { - parent::setNormalizer($option, $normalizer); - } catch (UndefinedOptionsException $e) { - $this->undefined[$option] = true; - } - - return $this; - } - - /** - * @return $this - */ - public function setAllowedValues(string $option, $allowedValues): self - { - try { - parent::setAllowedValues($option, $allowedValues); - } catch (UndefinedOptionsException $e) { - $this->undefined[$option] = true; - } - - return $this; - } - - /** - * @return $this - */ - public function addAllowedValues(string $option, $allowedValues): self - { - try { - parent::addAllowedValues($option, $allowedValues); - } catch (UndefinedOptionsException $e) { - $this->undefined[$option] = true; - } - - return $this; - } - - /** - * @param string|array $allowedTypes - * - * @return $this - */ - public function setAllowedTypes(string $option, $allowedTypes): self - { - try { - parent::setAllowedTypes($option, $allowedTypes); - } catch (UndefinedOptionsException $e) { - $this->undefined[$option] = true; - } - - return $this; - } - - /** - * @param string|array $allowedTypes - * - * @return $this - */ - public function addAllowedTypes(string $option, $allowedTypes): self - { - try { - parent::addAllowedTypes($option, $allowedTypes); - } catch (UndefinedOptionsException $e) { - $this->undefined[$option] = true; - } - - return $this; - } - - public function resolve(array $options = []): array - { - throw new AccessException('Resolve options is not supported.'); - } - - public function getUndefinedOptions(): array - { - return array_keys($this->undefined); - } -} diff --git a/lib/symfony/form/Util/OrderedHashMap.php b/lib/symfony/form/Util/OrderedHashMap.php deleted file mode 100644 index 7d84cbe22..000000000 --- a/lib/symfony/form/Util/OrderedHashMap.php +++ /dev/null @@ -1,192 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Util; - -/** - * A hash map which keeps track of deletions and additions. - * - * Like in associative arrays, elements can be mapped to integer or string keys. - * Unlike associative arrays, the map keeps track of the order in which keys - * were added and removed. This order is reflected during iteration. - * - * The map supports concurrent modification during iteration. That means that - * you can insert and remove elements from within a foreach loop and the - * iterator will reflect those changes accordingly. - * - * While elements that are added during the loop are recognized by the iterator, - * changed elements are not. Otherwise the loop could be infinite if each loop - * changes the current element: - * - * $map = new OrderedHashMap(); - * $map[1] = 1; - * $map[2] = 2; - * $map[3] = 3; - * - * foreach ($map as $index => $value) { - * echo "$index: $value\n" - * if (1 === $index) { - * $map[1] = 4; - * $map[] = 5; - * } - * } - * - * print_r(iterator_to_array($map)); - * - * // => 1: 1 - * // 2: 2 - * // 3: 3 - * // 4: 5 - * // Array - * // ( - * // [1] => 4 - * // [2] => 2 - * // [3] => 3 - * // [4] => 5 - * // ) - * - * The map also supports multiple parallel iterators. That means that you can - * nest foreach loops without affecting each other's iteration: - * - * foreach ($map as $index => $value) { - * foreach ($map as $index2 => $value2) { - * // ... - * } - * } - * - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @template TKey of array-key - * @template TValue - * - * @implements \ArrayAccess<TKey, TValue> - * @implements \IteratorAggregate<TKey, TValue> - */ -class OrderedHashMap implements \ArrayAccess, \IteratorAggregate, \Countable -{ - /** - * The elements of the map, indexed by their keys. - * - * @var array<TKey, TValue> - */ - private $elements = []; - - /** - * The keys of the map in the order in which they were inserted or changed. - * - * @var list<TKey> - */ - private $orderedKeys = []; - - /** - * References to the cursors of all open iterators. - * - * @var array<int, int> - */ - private $managedCursors = []; - - /** - * Creates a new map. - * - * @param array<TKey, TValue> $elements The elements to insert initially - */ - public function __construct(array $elements = []) - { - $this->elements = $elements; - $this->orderedKeys = array_keys($elements); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function offsetExists($key) - { - return isset($this->elements[$key]); - } - - /** - * {@inheritdoc} - * - * @return TValue - */ - #[\ReturnTypeWillChange] - public function offsetGet($key) - { - if (!isset($this->elements[$key])) { - throw new \OutOfBoundsException(sprintf('The offset "%s" does not exist.', $key)); - } - - return $this->elements[$key]; - } - - /** - * {@inheritdoc} - * - * @return void - */ - #[\ReturnTypeWillChange] - public function offsetSet($key, $value) - { - if (null === $key || !isset($this->elements[$key])) { - if (null === $key) { - $key = [] === $this->orderedKeys - // If the array is empty, use 0 as key - ? 0 - // Imitate PHP behavior of generating a key that equals - // the highest existing integer key + 1 - : 1 + (int) max($this->orderedKeys); - } - - $this->orderedKeys[] = (string) $key; - } - - $this->elements[$key] = $value; - } - - /** - * {@inheritdoc} - * - * @return void - */ - #[\ReturnTypeWillChange] - public function offsetUnset($key) - { - if (false !== ($position = array_search((string) $key, $this->orderedKeys))) { - array_splice($this->orderedKeys, $position, 1); - unset($this->elements[$key]); - - foreach ($this->managedCursors as $i => $cursor) { - if ($cursor >= $position) { - --$this->managedCursors[$i]; - } - } - } - } - - /** - * @return \Traversable<TKey, TValue> - */ - #[\ReturnTypeWillChange] - public function getIterator() - { - return new OrderedHashMapIterator($this->elements, $this->orderedKeys, $this->managedCursors); - } - - /** - * @return int - */ - #[\ReturnTypeWillChange] - public function count() - { - return \count($this->elements); - } -} diff --git a/lib/symfony/form/Util/OrderedHashMapIterator.php b/lib/symfony/form/Util/OrderedHashMapIterator.php deleted file mode 100644 index e91e33301..000000000 --- a/lib/symfony/form/Util/OrderedHashMapIterator.php +++ /dev/null @@ -1,172 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Util; - -/** - * Iterator for {@link OrderedHashMap} objects. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @internal - * - * @template-covariant TKey of array-key - * @template-covariant TValue - * - * @implements \Iterator<TKey, TValue> - */ -class OrderedHashMapIterator implements \Iterator -{ - /** - * @var array<TKey, TValue> - */ - private $elements; - - /** - * @var list<TKey> - */ - private $orderedKeys; - - /** - * @var int - */ - private $cursor = 0; - - /** - * @var int - */ - private $cursorId; - - /** - * @var array<int, int> - */ - private $managedCursors; - - /** - * @var TKey|null - */ - private $key; - - /** - * @var TValue|null - */ - private $current; - - /** - * @param array<TKey, TValue> $elements The elements of the map, indexed by their - * keys - * @param list<TKey> $orderedKeys The keys of the map in the order in which - * they should be iterated - * @param array<int, int> $managedCursors An array from which to reference the - * iterator's cursor as long as it is alive. - * This array is managed by the corresponding - * {@link OrderedHashMap} instance to support - * recognizing the deletion of elements. - */ - public function __construct(array &$elements, array &$orderedKeys, array &$managedCursors) - { - $this->elements = &$elements; - $this->orderedKeys = &$orderedKeys; - $this->managedCursors = &$managedCursors; - $this->cursorId = \count($managedCursors); - - $this->managedCursors[$this->cursorId] = &$this->cursor; - } - - public function __sleep(): array - { - throw new \BadMethodCallException('Cannot serialize '.__CLASS__); - } - - public function __wakeup() - { - throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); - } - - /** - * Removes the iterator's cursors from the managed cursors of the - * corresponding {@link OrderedHashMap} instance. - */ - public function __destruct() - { - // Use array_splice() instead of unset() to prevent holes in the - // array indices, which would break the initialization of $cursorId - array_splice($this->managedCursors, $this->cursorId, 1); - } - - /** - * {@inheritdoc} - * - * @return mixed - */ - #[\ReturnTypeWillChange] - public function current() - { - return $this->current; - } - - /** - * {@inheritdoc} - */ - public function next(): void - { - ++$this->cursor; - - if (isset($this->orderedKeys[$this->cursor])) { - $this->key = $this->orderedKeys[$this->cursor]; - $this->current = $this->elements[$this->key]; - } else { - $this->key = null; - $this->current = null; - } - } - - /** - * {@inheritdoc} - * - * @return mixed - */ - #[\ReturnTypeWillChange] - public function key() - { - if (null === $this->key) { - return null; - } - - $array = [$this->key => null]; - - return key($array); - } - - /** - * {@inheritdoc} - */ - public function valid(): bool - { - return null !== $this->key; - } - - /** - * {@inheritdoc} - */ - public function rewind(): void - { - $this->cursor = 0; - - if (isset($this->orderedKeys[0])) { - $this->key = $this->orderedKeys[0]; - $this->current = $this->elements[$this->key]; - } else { - $this->key = null; - $this->current = null; - } - } -} diff --git a/lib/symfony/form/Util/ServerParams.php b/lib/symfony/form/Util/ServerParams.php deleted file mode 100644 index ebe09f60e..000000000 --- a/lib/symfony/form/Util/ServerParams.php +++ /dev/null @@ -1,101 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Util; - -use Symfony\Component\HttpFoundation\RequestStack; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class ServerParams -{ - private $requestStack; - - public function __construct(RequestStack $requestStack = null) - { - $this->requestStack = $requestStack; - } - - /** - * Returns true if the POST max size has been exceeded in the request. - * - * @return bool - */ - public function hasPostMaxSizeBeenExceeded() - { - $contentLength = $this->getContentLength(); - $maxContentLength = $this->getPostMaxSize(); - - return $maxContentLength && $contentLength > $maxContentLength; - } - - /** - * Returns maximum post size in bytes. - * - * @return int|float|null - */ - public function getPostMaxSize() - { - $iniMax = strtolower($this->getNormalizedIniPostMaxSize()); - - if ('' === $iniMax) { - return null; - } - - $max = ltrim($iniMax, '+'); - if (str_starts_with($max, '0x')) { - $max = \intval($max, 16); - } elseif (str_starts_with($max, '0')) { - $max = \intval($max, 8); - } else { - $max = (int) $max; - } - - switch (substr($iniMax, -1)) { - case 't': $max *= 1024; - // no break - case 'g': $max *= 1024; - // no break - case 'm': $max *= 1024; - // no break - case 'k': $max *= 1024; - } - - return $max; - } - - /** - * Returns the normalized "post_max_size" ini setting. - * - * @return string - */ - public function getNormalizedIniPostMaxSize() - { - return strtoupper(trim(\ini_get('post_max_size'))); - } - - /** - * Returns the content length of the request. - * - * @return mixed - */ - public function getContentLength() - { - if (null !== $this->requestStack && null !== $request = $this->requestStack->getCurrentRequest()) { - return $request->server->get('CONTENT_LENGTH'); - } - - return isset($_SERVER['CONTENT_LENGTH']) - ? (int) $_SERVER['CONTENT_LENGTH'] - : null; - } -} diff --git a/lib/symfony/form/Util/StringUtil.php b/lib/symfony/form/Util/StringUtil.php deleted file mode 100644 index db60f95d1..000000000 --- a/lib/symfony/form/Util/StringUtil.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Util; - -/** - * @author Issei Murasawa <issei.m7@gmail.com> - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class StringUtil -{ - /** - * This class should not be instantiated. - */ - private function __construct() - { - } - - /** - * Returns the trimmed data. - * - * @return string - */ - public static function trim(string $string) - { - if (null !== $result = @preg_replace('/^[\pZ\p{Cc}\p{Cf}]+|[\pZ\p{Cc}\p{Cf}]+$/u', '', $string)) { - return $result; - } - - return trim($string); - } - - /** - * Converts a fully-qualified class name to a block prefix. - * - * @param string $fqcn The fully-qualified class name - * - * @return string|null - */ - public static function fqcnToBlockPrefix(string $fqcn) - { - // Non-greedy ("+?") to match "type" suffix, if present - if (preg_match('~([^\\\\]+?)(type)?$~i', $fqcn, $matches)) { - return strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], ['\\1_\\2', '\\1_\\2'], $matches[1])); - } - - return null; - } -} diff --git a/lib/symfony/form/composer.json b/lib/symfony/form/composer.json deleted file mode 100644 index e6be770b8..000000000 --- a/lib/symfony/form/composer.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "name": "symfony/form", - "type": "library", - "description": "Allows to easily create, process and reuse HTML forms", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/options-resolver": "^5.1|^6.0", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-icu": "^1.21", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "^1.16", - "symfony/polyfill-php81": "^1.23", - "symfony/property-access": "^5.0.8|^6.0", - "symfony/service-contracts": "^1.1|^2|^3" - }, - "require-dev": { - "doctrine/collections": "^1.0|^2.0", - "symfony/validator": "^4.4.17|^5.1.9|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/console": "^5.4|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", - "symfony/http-kernel": "^4.4|^5.0|^6.0", - "symfony/intl": "^4.4|^5.0|^6.0", - "symfony/security-csrf": "^4.4|^5.0|^6.0", - "symfony/translation": "^4.4|^5.0|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0", - "symfony/uid": "^5.1|^6.0" - }, - "conflict": { - "phpunit/phpunit": "<5.4.3", - "symfony/console": "<4.4", - "symfony/dependency-injection": "<4.4", - "symfony/doctrine-bridge": "<4.4", - "symfony/error-handler": "<4.4.5", - "symfony/framework-bundle": "<4.4", - "symfony/http-kernel": "<4.4", - "symfony/translation": "<4.4", - "symfony/translation-contracts": "<1.1.7", - "symfony/twig-bridge": "<4.4" - }, - "suggest": { - "symfony/validator": "For form validation.", - "symfony/security-csrf": "For protecting forms against CSRF attacks.", - "symfony/twig-bridge": "For templating with Twig." - }, - "autoload": { - "psr-4": { "Symfony\\Component\\Form\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/lib/symfony/framework-bundle/CHANGELOG.md b/lib/symfony/framework-bundle/CHANGELOG.md deleted file mode 100644 index ea913ef98..000000000 --- a/lib/symfony/framework-bundle/CHANGELOG.md +++ /dev/null @@ -1,492 +0,0 @@ -CHANGELOG -========= - -5.4 ---- - - * Add `set_locale_from_accept_language` config option to automatically set the request locale based on the `Accept-Language` - HTTP request header and the `framework.enabled_locales` config option - * Add `set_content_language_from_locale` config option to automatically set the `Content-Language` HTTP response header based on the Request locale - * Deprecate the `framework.translator.enabled_locales`, use `framework.enabled_locales` instead - * Add autowiring alias for `HttpCache\StoreInterface` - * Add the ability to enable the profiler using a request query parameter, body parameter or attribute - * Deprecate the `AdapterInterface` autowiring alias, use `CacheItemPoolInterface` instead - * Deprecate the public `profiler` service to private - * Deprecate `get()`, `has()`, `getDoctrine()`, and `dispatchMessage()` in `AbstractController`, use method/constructor injection instead - * Deprecate the `cache.adapter.doctrine` service - * Add support for resetting container services after each messenger message - * Add `configureContainer()`, `configureRoutes()`, `getConfigDir()` and `getBundlesPath()` to `MicroKernelTrait` - * Add support for configuring log level, and status code by exception class - * Bind the `default_context` parameter onto serializer's encoders and normalizers - * Add support for `statusCode` default parameter when loading a template directly from route using the `Symfony\Bundle\FrameworkBundle\Controller\TemplateController` controller - * Deprecate `translation:update` command, use `translation:extract` instead - * Add `PhpStanExtractor` support for the PropertyInfo component - * Add `cache.adapter.doctrine_dbal` service to replace `cache.adapter.pdo` when a Doctrine DBAL connection is used. - -5.3 ---- - - * Deprecate the `session.storage` alias and `session.storage.*` services, use the `session.storage.factory` alias and `session.storage.factory.*` services instead - * Deprecate the `framework.session.storage_id` configuration option, use the `framework.session.storage_factory_id` configuration option instead - * Deprecate the `session` service and the `SessionInterface` alias, use the `Request::getSession()` or the new `RequestStack::getSession()` methods instead - * Add `AbstractController::renderForm()` to render a form and set the appropriate HTTP status code - * Add support for configuring PHP error level to log levels - * Add the `dispatcher` option to `debug:event-dispatcher` - * Add the `event_dispatcher.dispatcher` tag - * Add `assertResponseFormatSame()` in `BrowserKitAssertionsTrait` - * Add support for configuring UUID factory services - * Add tag `assets.package` to register asset packages - * Add support to use a PSR-6 compatible cache for Doctrine annotations - * Deprecate all other values than "none", "php_array" and "file" for `framework.annotation.cache` - * Add `KernelTestCase::getContainer()` as the best way to get a container in tests - * Rename the container parameter `profiler_listener.only_master_requests` to `profiler_listener.only_main_requests` - * Add service `fragment.uri_generator` to generate the URI of a fragment - * Deprecate registering workflow services as public - * Deprecate option `--xliff-version` of the `translation:update` command, use e.g. `--format=xlf20` instead - * Deprecate option `--output-format` of the `translation:update` command, use e.g. `--format=xlf20` instead - -5.2.0 ------ - - * Added `framework.http_cache` configuration tree - * Added `framework.trusted_proxies` and `framework.trusted_headers` configuration options - * Deprecated the public `form.factory`, `form.type.file`, `translator`, `security.csrf.token_manager`, `serializer`, - `cache_clearer`, `filesystem` and `validator` services to private. - * Added `TemplateAwareDataCollectorInterface` and `AbstractDataCollector` to simplify custom data collector creation and leverage autoconfiguration - * Add `cache.adapter.redis_tag_aware` tag to use `RedisCacheAwareAdapter` - * added `framework.http_client.retry_failing` configuration tree - * added `assertCheckboxChecked()` and `assertCheckboxNotChecked()` in `WebTestCase` - * added `assertFormValue()` and `assertNoFormValue()` in `WebTestCase` - * Added "--as-tree=3" option to `translation:update` command to dump messages as a tree-like structure. The given value defines the level where to switch to inline YAML - * Deprecated the `lock.RESOURCE_NAME` and `lock.RESOURCE_NAME.store` services and the `lock`, `LockInterface`, `lock.store` and `PersistingStoreInterface` aliases, use `lock.RESOURCE_NAME.factory`, `lock.factory` or `LockFactory` instead. - -5.1.0 ------ - * Removed `--no-backup` option from `translation:update` command (broken since `5.0.0`) - * Added link to source for controllers registered as named services - * Added link to source on controller on `router:match`/`debug:router` (when `framework.ide` is configured) - * Added the `framework.router.default_uri` configuration option to configure the default `RequestContext` - * Made `MicroKernelTrait::configureContainer()` compatible with `ContainerConfigurator` - * Added a new `mailer.message_bus` option to configure or disable the message bus to use to send mails. - * Added flex-compatible default implementation for `MicroKernelTrait::registerBundles()` - * Deprecated passing a `RouteCollectionBuilder` to `MicroKernelTrait::configureRoutes()`, type-hint `RoutingConfigurator` instead - * The `TemplateController` now accepts context argument - * Deprecated *not* setting the "framework.router.utf8" configuration option as it will default to `true` in Symfony 6.0 - * Added tag `routing.expression_language_function` to define functions available in route conditions - * Added `debug:container --deprecations` option to see compile-time deprecations. - * Made `BrowserKitAssertionsTrait` report the original error message in case of a failure - * Added ability for `config:dump-reference` and `debug:config` to dump and debug kernel container extension configuration. - * Deprecated `session.attribute_bag` service and `session.flash_bag` service. - -5.0.0 ------ - - * Removed support to load translation resources from the legacy directories `src/Resources/translations/` and `src/Resources/<BundleName>/translations/` - * Removed `ControllerNameParser`. - * Removed `ResolveControllerNameSubscriber` - * Removed support for `bundle:controller:action` to reference controllers. Use `serviceOrFqcn::method` instead - * Removed support for PHP templating, use Twig instead - * Removed `Controller`, use `AbstractController` instead - * Removed `Client`, use `KernelBrowser` instead - * Removed `ContainerAwareCommand`, use dependency injection instead - * Removed the `validation.strict_email` option, use `validation.email_validation_mode` instead - * Removed the `cache.app.simple` service and its corresponding PSR-16 autowiring alias - * Removed cache-related compiler passes and `RequestDataCollector` - * Removed the `translator.selector` and `session.save_listener` services - * Removed `SecurityUserValueResolver`, use `UserValueResolver` instead - * Removed `routing.loader.service`. - * Service route loaders must be tagged with `routing.route_loader`. - * Added `slugger` service and `SluggerInterface` alias - * Removed the `lock.store.flock`, `lock.store.semaphore`, `lock.store.memcached.abstract` and `lock.store.redis.abstract` services. - * Removed the `router.cache_class_prefix` parameter. - -4.4.0 ------ - - * Added `lint:container` command to check that services wiring matches type declarations - * Added `MailerAssertionsTrait` - * Deprecated support for `templating` engine in `TemplateController`, use Twig instead - * Deprecated the `$parser` argument of `ControllerResolver::__construct()` and `DelegatingLoader::__construct()` - * Deprecated the `controller_name_converter` and `resolve_controller_name_subscriber` services - * The `ControllerResolver` and `DelegatingLoader` classes have been marked as `final` - * Added support for configuring chained cache pools - * Deprecated calling `WebTestCase::createClient()` while a kernel has been booted, ensure the kernel is shut down before calling the method - * Deprecated `routing.loader.service`, use `routing.loader.container` instead. - * Not tagging service route loaders with `routing.route_loader` has been deprecated. - * Overriding the methods `KernelTestCase::tearDown()` and `WebTestCase::tearDown()` without the `void` return-type is deprecated. - * Added new `error_controller` configuration to handle system exceptions - * Added sort option for `translation:update` command. - * [BC Break] The `framework.messenger.routing.senders` config key is not deeply merged anymore. - * Added `secrets:*` commands to deal with secrets seamlessly. - * Made `framework.session.handler_id` accept a DSN - * Marked the `RouterDataCollector` class as `@final`. - * [BC Break] The `framework.messenger.buses.<name>.middleware` config key is not deeply merged anymore. - * Moved `MailerAssertionsTrait` in `KernelTestCase` - -4.3.0 ------ - - * Deprecated the `framework.templating` option, configure the Twig bundle instead. - * Added `WebTestAssertionsTrait` (included by default in `WebTestCase`) - * Renamed `Client` to `KernelBrowser` - * Not passing the project directory to the constructor of the `AssetsInstallCommand` is deprecated. This argument will - be mandatory in 5.0. - * Deprecated the "Psr\SimpleCache\CacheInterface" / "cache.app.simple" service, use "Symfony\Contracts\Cache\CacheInterface" / "cache.app" instead - * Added the ability to specify a custom `serializer` option for each - transport under`framework.messenger.transports`. - * Added the `RegisterLocaleAwareServicesPass` and configured the `LocaleAwareListener` - * [BC Break] When using Messenger, the default transport changed from - using Symfony's serializer service to use `PhpSerializer`, which uses - PHP's native `serialize()` and `unserialize()` functions. To use the - original serialization method, set the `framework.messenger.default_serializer` - config option to `messenger.transport.symfony_serializer`. Or set the - `serializer` option under one specific `transport`. - * [BC Break] The `framework.messenger.serializer` config key changed to - `framework.messenger.default_serializer`, which holds the string service - id and `framework.messenger.symfony_serializer`, which configures the - options if you're using Symfony's serializer. - * [BC Break] Removed the `framework.messenger.routing.send_and_handle` configuration. - Instead of setting it to true, configure a `SyncTransport` and route messages to it. - * Added information about deprecated aliases in `debug:autowiring` - * Added php ini session options `sid_length` and `sid_bits_per_character` - to the `session` section of the configuration - * Added support for Translator paths, Twig paths in translation commands. - * Added support for PHP files with translations in translation commands. - * Added support for boolean container parameters within routes. - * Added the `messenger:setup-transports` command to setup messenger transports - * Added a `InMemoryTransport` to Messenger. Use it with a DSN starting with `in-memory://`. - * Added `framework.property_access.throw_exception_on_invalid_property_path` config option. - * Added `cache:pool:list` command to list all available cache pools. - -4.2.0 ------ - - * Added a `AbstractController::addLink()` method to add Link headers to the current response - * Allowed configuring taggable cache pools via a new `framework.cache.pools.tags` option (bool|service-id) - * Allowed configuring PDO-based cache pools via a new `cache.adapter.pdo` abstract service - * Deprecated auto-injection of the container in AbstractController instances, register them as service subscribers instead - * Deprecated processing of services tagged `security.expression_language_provider` in favor of a new `AddExpressionLanguageProvidersPass` in SecurityBundle. - * Deprecated the `Symfony\Bundle\FrameworkBundle\Controller\Controller` class in favor of `Symfony\Bundle\FrameworkBundle\Controller\AbstractController`. - * Enabled autoconfiguration for `Psr\Log\LoggerAwareInterface` - * Added new "auto" mode for `framework.session.cookie_secure` to turn it on when HTTPS is used - * Removed the `framework.messenger.encoder` and `framework.messenger.decoder` options. Use the `framework.messenger.serializer.id` option to replace the Messenger serializer. - * Deprecated the `ContainerAwareCommand` class in favor of `Symfony\Component\Console\Command\Command` - * Made `debug:container` and `debug:autowiring` ignore backslashes in service ids - * Deprecated the `Templating\Helper\TranslatorHelper::transChoice()` method, use the `trans()` one instead with a `%count%` parameter - * Deprecated `CacheCollectorPass`. Use `Symfony\Component\Cache\DependencyInjection\CacheCollectorPass` instead. - * Deprecated `CachePoolClearerPass`. Use `Symfony\Component\Cache\DependencyInjection\CachePoolClearerPass` instead. - * Deprecated `CachePoolPass`. Use `Symfony\Component\Cache\DependencyInjection\CachePoolPass` instead. - * Deprecated `CachePoolPrunerPass`. Use `Symfony\Component\Cache\DependencyInjection\CachePoolPrunerPass` instead. - * Deprecated support for legacy translations directories `src/Resources/translations/` and `src/Resources/<BundleName>/translations/`, use `translations/` instead. - * Deprecated support for the legacy directory structure in `translation:update` and `debug:translation` commands. - -4.1.0 ------ - - * Allowed to pass an optional `LoggerInterface $logger` instance to the `Router` - * Added a new `parameter_bag` service with related autowiring aliases to access parameters as-a-service - * Allowed the `Router` to work with any PSR-11 container - * Added option in workflow dump command to label graph with a custom label - * Using a `RouterInterface` that does not implement the `WarmableInterface` is deprecated. - * Warming up a router in `RouterCacheWarmer` that does not implement the `WarmableInterface` is deprecated and will not - be supported anymore in 5.0. - * The `RequestDataCollector` class has been deprecated. Use the `Symfony\Component\HttpKernel\DataCollector\RequestDataCollector` class instead. - * The `RedirectController` class allows for 307/308 HTTP status codes - * Deprecated `bundle:controller:action` syntax to reference controllers. Use `serviceOrFqcn::method` instead where `serviceOrFqcn` - is either the service ID or the FQCN of the controller. - * Deprecated `Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser` - * The `container.service_locator` tag of `ServiceLocator`s is now autoconfigured. - * Add the ability to search a route in `debug:router`. - * Add the ability to use SameSite cookies for sessions. - -4.0.0 ------ - - * The default `type` option of the `framework.workflows.*` configuration entries is `state_machine` - * removed `AddConsoleCommandPass`, `AddConstraintValidatorsPass`, - `AddValidatorInitializersPass`, `CompilerDebugDumpPass`, `ConfigCachePass`, - `ControllerArgumentValueResolverPass`, `FormPass`, `PropertyInfoPass`, - `RoutingResolverPass`, `SerializerPass`, `ValidateWorkflowsPass` - * made `Translator::__construct()` `$defaultLocale` argument required - * removed `SessionListener`, `TestSessionListener` - * Removed `cache:clear` warmup part along with the `--no-optional-warmers` option - * Removed core form types services registration when unnecessary - * Removed `framework.serializer.cache` option and `serializer.mapping.cache.apc`, `serializer.mapping.cache.doctrine.apc` services - * Removed `ConstraintValidatorFactory` - * Removed class parameters related to routing - * Removed absolute template paths support in the template name parser - * Removed support of the `KERNEL_DIR` environment variable with `KernelTestCase::getKernelClass()`. - * Removed the `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` methods. - * Removed the "framework.validation.cache" configuration option. Configure the "cache.validator" service under "framework.cache.pools" instead. - * Removed `PhpStringTokenParser`, use `Symfony\Component\Translation\Extractor\PhpStringTokenParser` instead. - * Removed `PhpExtractor`, use `Symfony\Component\Translation\Extractor\PhpExtractor` instead. - * Removed the `use_strict_mode` session option, it's is now enabled by default - -3.4.0 ------ - - * Added `translator.default_path` option and parameter - * Session `use_strict_mode` is now enabled by default and the corresponding option has been deprecated - * Made the `cache:clear` command to *not* clear "app" PSR-6 cache pools anymore, - but to still clear "system" ones; use the `cache:pool:clear` command to clear "app" pools instead - * Always register a minimalist logger that writes in `stderr` - * Deprecated `profiler.matcher` option - * Added support for `EventSubscriberInterface` on `MicroKernelTrait` - * Removed `doctrine/cache` from the list of required dependencies in `composer.json` - * Deprecated `validator.mapping.cache.doctrine.apc` service - * The `symfony/stopwatch` dependency has been removed, require it via `composer - require symfony/stopwatch` in your `dev` environment. - * Deprecated using the `KERNEL_DIR` environment variable with `KernelTestCase::getKernelClass()`. - * Deprecated the `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` methods. - * Deprecated `AddCacheClearerPass`, use tagged iterator arguments instead. - * Deprecated `AddCacheWarmerPass`, use tagged iterator arguments instead. - * Deprecated `TranslationDumperPass`, use - `Symfony\Component\Translation\DependencyInjection\TranslationDumperPass` instead - * Deprecated `TranslationExtractorPass`, use - `Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass` instead - * Deprecated `TranslatorPass`, use - `Symfony\Component\Translation\DependencyInjection\TranslatorPass` instead - * Added `command` attribute to the `console.command` tag which takes the command - name as value, using it makes the command lazy - * Added `cache:pool:prune` command to allow manual stale cache item pruning of supported PSR-6 and PSR-16 cache pool - implementations - * Deprecated `Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader`, use - `Symfony\Component\Translation\Reader\TranslationReader` instead - * Deprecated `translation.loader` service, use `translation.reader` instead - * `AssetsInstallCommand::__construct()` now takes an instance of - `Symfony\Component\Filesystem\Filesystem` as first argument - * `CacheClearCommand::__construct()` now takes an instance of - `Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface` as - first argument - * `CachePoolClearCommand::__construct()` now takes an instance of - `Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer` as - first argument - * `EventDispatcherDebugCommand::__construct()` now takes an instance of - `Symfony\Component\EventDispatcher\EventDispatcherInterface` as - first argument - * `RouterDebugCommand::__construct()` now takes an instance of - `Symfony\Component\Routing\RouterInterface` as - first argument - * `RouterMatchCommand::__construct()` now takes an instance of - `Symfony\Component\Routing\RouterInterface` as - first argument - * `TranslationDebugCommand::__construct()` now takes an instance of - `Symfony\Component\Translation\TranslatorInterface` as - first argument - * `TranslationUpdateCommand::__construct()` now takes an instance of - `Symfony\Component\Translation\TranslatorInterface` as - first argument - * `AssetsInstallCommand`, `CacheClearCommand`, `CachePoolClearCommand`, - `EventDispatcherDebugCommand`, `RouterDebugCommand`, `RouterMatchCommand`, - `TranslationDebugCommand`, `TranslationUpdateCommand`, `XliffLintCommand` - and `YamlLintCommand` classes have been marked as final - * Added `asset.request_context.base_path` and `asset.request_context.secure` parameters - to provide a default request context in case the stack is empty (similar to `router.request_context.*` parameters) - * Display environment variables managed by `Dotenv` in `AboutCommand` - -3.3.0 ------ - - * Not defining the `type` option of the `framework.workflows.*` configuration entries is deprecated. - The default value will be `state_machine` in Symfony 4.0. - * Deprecated the `CompilerDebugDumpPass` class - * Deprecated the "framework.trusted_proxies" configuration option and the corresponding "kernel.trusted_proxies" parameter - * Added a new version strategy option called "json_manifest_path" - that allows you to use the `JsonManifestVersionStrategy`. - * Added `Symfony\Bundle\FrameworkBundle\Controller\AbstractController`. It provides - the same helpers as the `Controller` class, but does not allow accessing the dependency - injection container, in order to encourage explicit dependency declarations. - * Added support for the `controller.service_arguments` tag, for injecting services into controllers' actions - * Changed default configuration for - assets/forms/validation/translation/serialization/csrf from `canBeEnabled()` to - `canBeDisabled()` when Flex is used - * The server:* commands and their associated router files were moved to WebServerBundle - * Translation related services are not loaded anymore when the `framework.translator` option - is disabled. - * Added `GlobalVariables::getToken()` - * Deprecated `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConsoleCommandPass`. Use `Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass` instead. - * Added configurable paths for validation files - * Deprecated `SerializerPass`, use `Symfony\Component\Serializer\DependencyInjection\SerializerPass` instead - * Deprecated `FormPass`, use `Symfony\Component\Form\DependencyInjection\FormPass` instead - * Deprecated `SessionListener` - * Deprecated `TestSessionListener` - * Deprecated `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigCachePass`. - Use tagged iterator arguments instead. - * Deprecated `PropertyInfoPass`, use `Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass` instead - * Deprecated `ControllerArgumentValueResolverPass`. Use - `Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass` instead - * Deprecated `RoutingResolverPass`, use `Symfony\Component\Routing\DependencyInjection\RoutingResolverPass` instead - * [BC BREAK] The `server:run`, `server:start`, `server:stop` and - `server:status` console commands have been moved to a dedicated bundle. - Require `symfony/web-server-bundle` in your composer.json and register - `Symfony\Bundle\WebServerBundle\WebServerBundle` in your AppKernel to use them. - * Added `$defaultLocale` as 3rd argument of `Translator::__construct()` - making `Translator` works with any PSR-11 container - * Added `framework.serializer.mapping` config option allowing to define custom - serialization mapping files and directories - * Deprecated `AddValidatorInitializersPass`, use - `Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass` instead - * Deprecated `AddConstraintValidatorsPass`, use - `Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass` instead - * Deprecated `ValidateWorkflowsPass`, use - `Symfony\Component\Workflow\DependencyInjection\ValidateWorkflowsPass` instead - * Deprecated `ConstraintValidatorFactory`, use - `Symfony\Component\Validator\ContainerConstraintValidatorFactory` instead. - * Deprecated `PhpStringTokenParser`, use - `Symfony\Component\Translation\Extractor\PhpStringTokenParser` instead. - * Deprecated `PhpExtractor`, use - `Symfony\Component\Translation\Extractor\PhpExtractor` instead. - -3.2.0 ------ - - * Removed `doctrine/annotations` from the list of required dependencies in `composer.json` - * Removed `symfony/security-core` and `symfony/security-csrf` from the list of required dependencies in `composer.json` - * Removed `symfony/templating` from the list of required dependencies in `composer.json` - * Removed `symfony/translation` from the list of required dependencies in `composer.json` - * Removed `symfony/asset` from the list of required dependencies in `composer.json` - * The `Resources/public/images/*` files have been removed. - * The `Resources/public/css/*.css` files have been removed (they are now inlined in TwigBundle). - * Added possibility to prioritize form type extensions with `'priority'` attribute on tags `form.type_extension` - -3.1.0 ------ - - * Added `Controller::json` to simplify creating JSON responses when using the Serializer component - * Deprecated absolute template paths support in the template name parser - * Deprecated using core form types without dependencies as services - * Added `Symfony\Component\HttpHernel\DataCollector\RequestDataCollector::onKernelResponse()` - * Added `Symfony\Bundle\FrameworkBundle\DataCollector\RequestDataCollector` - * The `framework.serializer.cache` option and the service `serializer.mapping.cache.apc` have been - deprecated. APCu should now be automatically used when available. - -3.0.0 ------ - - * removed `validator.api` parameter - * removed `alias` option of the `form.type` tag - -2.8.0 ------ - - * Deprecated the `alias` option of the `form.type_extension` tag in favor of the - `extended_type`/`extended-type` option - * Deprecated the `alias` option of the `form.type` tag - * Deprecated the Shell - -2.7.0 ------ - - * Added possibility to extract translation messages from a file or files besides extracting from a directory - * Added `TranslationsCacheWarmer` to create catalogues at warmup - -2.6.0 ------ - - * Added helper commands (`server:start`, `server:stop` and `server:status`) to control the built-in web - server in the background - * Added `Controller::isCsrfTokenValid` helper - * Added configuration for the PropertyAccess component - * Added `Controller::redirectToRoute` helper - * Added `Controller::addFlash` helper - * Added `Controller::isGranted` helper - * Added `Controller::denyAccessUnlessGranted` helper - * Deprecated `app.security` in twig as `app.user` and `is_granted()` are already available - -2.5.0 ------ - - * Added `translation:debug` command - * Added `--no-backup` option to `translation:update` command - * Added `config:debug` command - * Added `yaml:lint` command - * Deprecated the `RouterApacheDumperCommand` which will be removed in Symfony 3.0. - -2.4.0 ------ - - * allowed multiple IP addresses in profiler matcher settings - * added stopwatch helper to time templates with the WebProfilerBundle - * added service definition for "security.secure_random" service - * added service definitions for the new Security CSRF sub-component - -2.3.0 ------ - - * [BC BREAK] added a way to disable the profiler (when disabling the profiler, it is now completely removed) - To get the same "disabled" behavior as before, set `enabled` to `true` and `collect` to `false` - * [BC BREAK] the `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\RegisterKernelListenersPass` was moved - to `Component\HttpKernel\DependencyInjection\RegisterListenersPass` - * added ControllerNameParser::build() which converts a controller short notation (a:b:c) to a class::method notation - * added possibility to run PHP built-in server in production environment - * added possibility to load the serializer component in the service container - * added route debug information when using the `router:match` command - * added `TimedPhpEngine` - * added `--clean` option to the `translation:update` command - * added `http_method_override` option - * added support for default templates per render tag - * added FormHelper::form(), FormHelper::start() and FormHelper::end() - * deprecated FormHelper::enctype() in favor of FormHelper::start() - * RedirectController actions now receive the Request instance via the method signature. - -2.2.0 ------ - - * added a new `uri_signer` service to help sign URIs - * deprecated `Symfony\Bundle\FrameworkBundle\HttpKernel::render()` and `Symfony\Bundle\FrameworkBundle\HttpKernel::forward()` - * deprecated the `Symfony\Bundle\FrameworkBundle\HttpKernel` class in favor of `Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel` - * added support for adding new HTTP content rendering strategies (like ESI and Hinclude) - in the DIC via the `kernel.fragment_renderer` tag - * [BC BREAK] restricted the `Symfony\Bundle\FrameworkBundle\HttpKernel::render()` method to only accept URIs or ControllerReference instances - * `Symfony\Bundle\FrameworkBundle\HttpKernel::render()` method signature changed and the first argument - must now be a URI or a ControllerReference instance (the `generateInternalUri()` method was removed) - * The internal routes (`Resources/config/routing/internal.xml`) have been removed and replaced with a listener (`Symfony\Component\HttpKernel\EventListener\FragmentListener`) - * The `render` method of the `actions` templating helper signature and arguments changed - * replaced Symfony\Bundle\FrameworkBundle\Controller\TraceableControllerResolver by Symfony\Component\HttpKernel\Controller\TraceableControllerResolver - * replaced Symfony\Component\HttpKernel\Debug\ContainerAwareTraceableEventDispatcher by Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher - * added Client::enableProfiler() - * a new parameter has been added to the DIC: `router.request_context.base_url` - You can customize it for your functional tests or for generating URLs with - the right base URL when your are in the CLI context. - * added support for default templates per render tag - -2.1.0 ------ - - * moved the translation files to the Form and Validator components - * changed the default extension for XLIFF files from .xliff to .xlf - * moved Symfony\Bundle\FrameworkBundle\ContainerAwareEventDispatcher to Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher - * moved Symfony\Bundle\FrameworkBundle\Debug\TraceableEventDispatcher to Symfony\Component\EventDispatcher\ContainerAwareTraceableEventDispatcher - * added a router:match command - * added a config:dump-reference command - * added a server:run command - * added kernel.event_subscriber tag - * added a way to create relative symlinks when running assets:install command (--relative option) - * added Controller::getUser() - * [BC BREAK] assets_base_urls and base_urls merging strategy has changed - * changed the default profiler storage to use the filesystem instead of SQLite - * added support for placeholders in route defaults and requirements (replaced - by the value set in the service container) - * added Filesystem component as a dependency - * added support for hinclude (use ``standalone: 'js'`` in render tag) - * session options: lifetime, path, domain, secure, httponly were deprecated. - Prefixed versions should now be used instead: cookie_lifetime, cookie_path, - cookie_domain, cookie_secure, cookie_httponly - * [BC BREAK] following session options: 'lifetime', 'path', 'domain', 'secure', - 'httponly' are now prefixed with cookie_ when dumped to the container - * Added `handler_id` configuration under `session` key to represent `session.handler` - service, defaults to `session.handler.native_file`. - * Added `gc_maxlifetime`, `gc_probability`, and `gc_divisor` to session - configuration. This means session garbage collection has a - `gc_probability`/`gc_divisor` chance of being run. The `gc_maxlifetime` defines - how long a session can idle for. It is different from cookie lifetime which - declares how long a cookie can be stored on the remote client. - * Removed 'auto_start' configuration parameter from session config. The session will - start on demand. - * [BC BREAK] TemplateNameParser::parseFromFilename() has been moved to a dedicated - parser: TemplateFilenameParser::parse(). - * [BC BREAK] Kernel parameters are replaced by their value wherever they appear - in Route patterns, requirements and defaults. Use '%%' as the escaped value for '%'. - * [BC BREAK] Switched behavior of flash messages to expire flash messages on retrieval - using Symfony\Component\HttpFoundation\Session\Flash\FlashBag as opposed to on - next pageload regardless of whether they are displayed or not. diff --git a/lib/symfony/framework-bundle/CacheWarmer/AbstractPhpFileCacheWarmer.php b/lib/symfony/framework-bundle/CacheWarmer/AbstractPhpFileCacheWarmer.php deleted file mode 100644 index 17e066045..000000000 --- a/lib/symfony/framework-bundle/CacheWarmer/AbstractPhpFileCacheWarmer.php +++ /dev/null @@ -1,89 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; - -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\NullAdapter; -use Symfony\Component\Cache\Adapter\PhpArrayAdapter; -use Symfony\Component\Config\Resource\ClassExistenceResource; -use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; - -abstract class AbstractPhpFileCacheWarmer implements CacheWarmerInterface -{ - private $phpArrayFile; - - /** - * @param string $phpArrayFile The PHP file where metadata are cached - */ - public function __construct(string $phpArrayFile) - { - $this->phpArrayFile = $phpArrayFile; - } - - /** - * {@inheritdoc} - */ - public function isOptional() - { - return true; - } - - /** - * {@inheritdoc} - * - * @return string[] A list of classes to preload on PHP 7.4+ - */ - public function warmUp(string $cacheDir) - { - $arrayAdapter = new ArrayAdapter(); - - spl_autoload_register([ClassExistenceResource::class, 'throwOnRequiredClass']); - try { - if (!$this->doWarmUp($cacheDir, $arrayAdapter)) { - return []; - } - } finally { - spl_autoload_unregister([ClassExistenceResource::class, 'throwOnRequiredClass']); - } - - // the ArrayAdapter stores the values serialized - // to avoid mutation of the data after it was written to the cache - // so here we un-serialize the values first - $values = array_map(function ($val) { return null !== $val ? unserialize($val) : null; }, $arrayAdapter->getValues()); - - return $this->warmUpPhpArrayAdapter(new PhpArrayAdapter($this->phpArrayFile, new NullAdapter()), $values); - } - - /** - * @return string[] A list of classes to preload on PHP 7.4+ - */ - protected function warmUpPhpArrayAdapter(PhpArrayAdapter $phpArrayAdapter, array $values) - { - return (array) $phpArrayAdapter->warmUp($values); - } - - /** - * @internal - */ - final protected function ignoreAutoloadException(string $class, \Exception $exception): void - { - try { - ClassExistenceResource::throwOnRequiredClass($class, $exception); - } catch (\ReflectionException $e) { - } - } - - /** - * @return bool false if there is nothing to warm-up - */ - abstract protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter); -} diff --git a/lib/symfony/framework-bundle/CacheWarmer/AnnotationsCacheWarmer.php b/lib/symfony/framework-bundle/CacheWarmer/AnnotationsCacheWarmer.php deleted file mode 100644 index 550440017..000000000 --- a/lib/symfony/framework-bundle/CacheWarmer/AnnotationsCacheWarmer.php +++ /dev/null @@ -1,113 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; - -use Doctrine\Common\Annotations\AnnotationException; -use Doctrine\Common\Annotations\PsrCachedReader; -use Doctrine\Common\Annotations\Reader; -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\PhpArrayAdapter; - -/** - * Warms up annotation caches for classes found in composer's autoload class map - * and declared in DI bundle extensions using the addAnnotatedClassesToCache method. - * - * @author Titouan Galopin <galopintitouan@gmail.com> - */ -class AnnotationsCacheWarmer extends AbstractPhpFileCacheWarmer -{ - private $annotationReader; - private $excludeRegexp; - private $debug; - - /** - * @param string $phpArrayFile The PHP file where annotations are cached - */ - public function __construct(Reader $annotationReader, string $phpArrayFile, string $excludeRegexp = null, bool $debug = false) - { - parent::__construct($phpArrayFile); - $this->annotationReader = $annotationReader; - $this->excludeRegexp = $excludeRegexp; - $this->debug = $debug; - } - - /** - * {@inheritdoc} - */ - protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter) - { - $annotatedClassPatterns = $cacheDir.'/annotations.map'; - - if (!is_file($annotatedClassPatterns)) { - return true; - } - - $annotatedClasses = include $annotatedClassPatterns; - $reader = new PsrCachedReader($this->annotationReader, $arrayAdapter, $this->debug); - - foreach ($annotatedClasses as $class) { - if (null !== $this->excludeRegexp && preg_match($this->excludeRegexp, $class)) { - continue; - } - try { - $this->readAllComponents($reader, $class); - } catch (\Exception $e) { - $this->ignoreAutoloadException($class, $e); - } - } - - return true; - } - - /** - * @return string[] A list of classes to preload on PHP 7.4+ - */ - protected function warmUpPhpArrayAdapter(PhpArrayAdapter $phpArrayAdapter, array $values) - { - // make sure we don't cache null values - $values = array_filter($values, function ($val) { return null !== $val; }); - - return parent::warmUpPhpArrayAdapter($phpArrayAdapter, $values); - } - - private function readAllComponents(Reader $reader, string $class) - { - $reflectionClass = new \ReflectionClass($class); - - try { - $reader->getClassAnnotations($reflectionClass); - } catch (AnnotationException $e) { - /* - * Ignore any AnnotationException to not break the cache warming process if an Annotation is badly - * configured or could not be found / read / etc. - * - * In particular cases, an Annotation in your code can be used and defined only for a specific - * environment but is always added to the annotations.map file by some Symfony default behaviors, - * and you always end up with a not found Annotation. - */ - } - - foreach ($reflectionClass->getMethods() as $reflectionMethod) { - try { - $reader->getMethodAnnotations($reflectionMethod); - } catch (AnnotationException $e) { - } - } - - foreach ($reflectionClass->getProperties() as $reflectionProperty) { - try { - $reader->getPropertyAnnotations($reflectionProperty); - } catch (AnnotationException $e) { - } - } - } -} diff --git a/lib/symfony/framework-bundle/CacheWarmer/CachePoolClearerCacheWarmer.php b/lib/symfony/framework-bundle/CacheWarmer/CachePoolClearerCacheWarmer.php deleted file mode 100644 index 79bca2403..000000000 --- a/lib/symfony/framework-bundle/CacheWarmer/CachePoolClearerCacheWarmer.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; - -use Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer; -use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; - -/** - * Clears the cache pools when warming up the cache. - * - * Do not use in production! - * - * @author Teoh Han Hui <teohhanhui@gmail.com> - * - * @internal - */ -final class CachePoolClearerCacheWarmer implements CacheWarmerInterface -{ - private $poolClearer; - private $pools; - - /** - * @param string[] $pools - */ - public function __construct(Psr6CacheClearer $poolClearer, array $pools = []) - { - $this->poolClearer = $poolClearer; - $this->pools = $pools; - } - - /** - * {@inheritdoc} - * - * @return string[] - */ - public function warmUp(string $cacheDirectory): array - { - foreach ($this->pools as $pool) { - if ($this->poolClearer->hasPool($pool)) { - $this->poolClearer->clearPool($pool); - } - } - - return []; - } - - /** - * {@inheritdoc} - */ - public function isOptional(): bool - { - // optional cache warmers are not run when handling the request - return false; - } -} diff --git a/lib/symfony/framework-bundle/CacheWarmer/ConfigBuilderCacheWarmer.php b/lib/symfony/framework-bundle/CacheWarmer/ConfigBuilderCacheWarmer.php deleted file mode 100644 index ed20bbcb6..000000000 --- a/lib/symfony/framework-bundle/CacheWarmer/ConfigBuilderCacheWarmer.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; - -use Psr\Log\LoggerInterface; -use Symfony\Component\Config\Builder\ConfigBuilderGenerator; -use Symfony\Component\Config\Builder\ConfigBuilderGeneratorInterface; -use Symfony\Component\Config\Definition\ConfigurationInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface; -use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; -use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; -use Symfony\Component\HttpKernel\KernelInterface; - -/** - * Generate all config builders. - * - * @author Tobias Nyholm <tobias.nyholm@gmail.com> - */ -class ConfigBuilderCacheWarmer implements CacheWarmerInterface -{ - private $kernel; - private $logger; - - public function __construct(KernelInterface $kernel, LoggerInterface $logger = null) - { - $this->kernel = $kernel; - $this->logger = $logger; - } - - /** - * {@inheritdoc} - * - * @return string[] - */ - public function warmUp(string $cacheDir) - { - $generator = new ConfigBuilderGenerator($cacheDir); - - foreach ($this->kernel->getBundles() as $bundle) { - $extension = $bundle->getContainerExtension(); - if (null === $extension) { - continue; - } - - try { - $this->dumpExtension($extension, $generator); - } catch (\Exception $e) { - if ($this->logger) { - $this->logger->warning('Failed to generate ConfigBuilder for extension {extensionClass}.', ['exception' => $e, 'extensionClass' => \get_class($extension)]); - } - } - } - - // No need to preload anything - return []; - } - - private function dumpExtension(ExtensionInterface $extension, ConfigBuilderGeneratorInterface $generator): void - { - $configuration = null; - if ($extension instanceof ConfigurationInterface) { - $configuration = $extension; - } elseif ($extension instanceof ConfigurationExtensionInterface) { - $configuration = $extension->getConfiguration([], new ContainerBuilder($this->kernel->getContainer()->getParameterBag())); - } - - if (!$configuration) { - return; - } - - $generator->build($configuration); - } - - /** - * {@inheritdoc} - */ - public function isOptional() - { - return true; - } -} diff --git a/lib/symfony/framework-bundle/CacheWarmer/RouterCacheWarmer.php b/lib/symfony/framework-bundle/CacheWarmer/RouterCacheWarmer.php deleted file mode 100644 index 6cdf176bb..000000000 --- a/lib/symfony/framework-bundle/CacheWarmer/RouterCacheWarmer.php +++ /dev/null @@ -1,68 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; - -use Psr\Container\ContainerInterface; -use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; -use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; -use Symfony\Component\Routing\RouterInterface; -use Symfony\Contracts\Service\ServiceSubscriberInterface; - -/** - * Generates the router matcher and generator classes. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class RouterCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInterface -{ - private $container; - - public function __construct(ContainerInterface $container) - { - // As this cache warmer is optional, dependencies should be lazy-loaded, that's why a container should be injected. - $this->container = $container; - } - - /** - * {@inheritdoc} - */ - public function warmUp(string $cacheDir): array - { - $router = $this->container->get('router'); - - if ($router instanceof WarmableInterface) { - return (array) $router->warmUp($cacheDir); - } - - throw new \LogicException(sprintf('The router "%s" cannot be warmed up because it does not implement "%s".', get_debug_type($router), WarmableInterface::class)); - } - - /** - * {@inheritdoc} - */ - public function isOptional(): bool - { - return true; - } - - /** - * {@inheritdoc} - */ - public static function getSubscribedServices(): array - { - return [ - 'router' => RouterInterface::class, - ]; - } -} diff --git a/lib/symfony/framework-bundle/CacheWarmer/SerializerCacheWarmer.php b/lib/symfony/framework-bundle/CacheWarmer/SerializerCacheWarmer.php deleted file mode 100644 index 0ada0ffc9..000000000 --- a/lib/symfony/framework-bundle/CacheWarmer/SerializerCacheWarmer.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; - -use Doctrine\Common\Annotations\AnnotationException; -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory; -use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; -use Symfony\Component\Serializer\Mapping\Loader\LoaderChain; -use Symfony\Component\Serializer\Mapping\Loader\LoaderInterface; -use Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader; -use Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader; - -/** - * Warms up XML and YAML serializer metadata. - * - * @author Titouan Galopin <galopintitouan@gmail.com> - */ -class SerializerCacheWarmer extends AbstractPhpFileCacheWarmer -{ - private $loaders; - - /** - * @param LoaderInterface[] $loaders The serializer metadata loaders - * @param string $phpArrayFile The PHP file where metadata are cached - */ - public function __construct(array $loaders, string $phpArrayFile) - { - parent::__construct($phpArrayFile); - $this->loaders = $loaders; - } - - /** - * {@inheritdoc} - */ - protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter) - { - if (!class_exists(CacheClassMetadataFactory::class) || !method_exists(XmlFileLoader::class, 'getMappedClasses') || !method_exists(YamlFileLoader::class, 'getMappedClasses')) { - return false; - } - - $metadataFactory = new CacheClassMetadataFactory(new ClassMetadataFactory(new LoaderChain($this->loaders)), $arrayAdapter); - - foreach ($this->extractSupportedLoaders($this->loaders) as $loader) { - foreach ($loader->getMappedClasses() as $mappedClass) { - try { - $metadataFactory->getMetadataFor($mappedClass); - } catch (AnnotationException $e) { - // ignore failing annotations - } catch (\Exception $e) { - $this->ignoreAutoloadException($mappedClass, $e); - } - } - } - - return true; - } - - /** - * @param LoaderInterface[] $loaders - * - * @return XmlFileLoader[]|YamlFileLoader[] - */ - private function extractSupportedLoaders(array $loaders): array - { - $supportedLoaders = []; - - foreach ($loaders as $loader) { - if ($loader instanceof XmlFileLoader || $loader instanceof YamlFileLoader) { - $supportedLoaders[] = $loader; - } elseif ($loader instanceof LoaderChain) { - $supportedLoaders = array_merge($supportedLoaders, $this->extractSupportedLoaders($loader->getLoaders())); - } - } - - return $supportedLoaders; - } -} diff --git a/lib/symfony/framework-bundle/CacheWarmer/TranslationsCacheWarmer.php b/lib/symfony/framework-bundle/CacheWarmer/TranslationsCacheWarmer.php deleted file mode 100644 index e3efc8090..000000000 --- a/lib/symfony/framework-bundle/CacheWarmer/TranslationsCacheWarmer.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; - -use Psr\Container\ContainerInterface; -use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; -use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; -use Symfony\Contracts\Service\ServiceSubscriberInterface; -use Symfony\Contracts\Translation\TranslatorInterface; - -/** - * Generates the catalogues for translations. - * - * @author Xavier Leune <xavier.leune@gmail.com> - */ -class TranslationsCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInterface -{ - private $container; - private $translator; - - public function __construct(ContainerInterface $container) - { - // As this cache warmer is optional, dependencies should be lazy-loaded, that's why a container should be injected. - $this->container = $container; - } - - /** - * {@inheritdoc} - * - * @return string[] - */ - public function warmUp(string $cacheDir) - { - if (null === $this->translator) { - $this->translator = $this->container->get('translator'); - } - - if ($this->translator instanceof WarmableInterface) { - return (array) $this->translator->warmUp($cacheDir); - } - - return []; - } - - /** - * {@inheritdoc} - */ - public function isOptional() - { - return true; - } - - /** - * {@inheritdoc} - */ - public static function getSubscribedServices() - { - return [ - 'translator' => TranslatorInterface::class, - ]; - } -} diff --git a/lib/symfony/framework-bundle/CacheWarmer/ValidatorCacheWarmer.php b/lib/symfony/framework-bundle/CacheWarmer/ValidatorCacheWarmer.php deleted file mode 100644 index 3c6d582c4..000000000 --- a/lib/symfony/framework-bundle/CacheWarmer/ValidatorCacheWarmer.php +++ /dev/null @@ -1,101 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; - -use Doctrine\Common\Annotations\AnnotationException; -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\PhpArrayAdapter; -use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory; -use Symfony\Component\Validator\Mapping\Loader\LoaderChain; -use Symfony\Component\Validator\Mapping\Loader\LoaderInterface; -use Symfony\Component\Validator\Mapping\Loader\XmlFileLoader; -use Symfony\Component\Validator\Mapping\Loader\YamlFileLoader; -use Symfony\Component\Validator\ValidatorBuilder; - -/** - * Warms up XML and YAML validator metadata. - * - * @author Titouan Galopin <galopintitouan@gmail.com> - */ -class ValidatorCacheWarmer extends AbstractPhpFileCacheWarmer -{ - private $validatorBuilder; - - /** - * @param string $phpArrayFile The PHP file where metadata are cached - */ - public function __construct(ValidatorBuilder $validatorBuilder, string $phpArrayFile) - { - parent::__construct($phpArrayFile); - $this->validatorBuilder = $validatorBuilder; - } - - /** - * {@inheritdoc} - */ - protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter) - { - if (!method_exists($this->validatorBuilder, 'getLoaders')) { - return false; - } - - $loaders = $this->validatorBuilder->getLoaders(); - $metadataFactory = new LazyLoadingMetadataFactory(new LoaderChain($loaders), $arrayAdapter); - - foreach ($this->extractSupportedLoaders($loaders) as $loader) { - foreach ($loader->getMappedClasses() as $mappedClass) { - try { - if ($metadataFactory->hasMetadataFor($mappedClass)) { - $metadataFactory->getMetadataFor($mappedClass); - } - } catch (AnnotationException $e) { - // ignore failing annotations - } catch (\Exception $e) { - $this->ignoreAutoloadException($mappedClass, $e); - } - } - } - - return true; - } - - /** - * @return string[] A list of classes to preload on PHP 7.4+ - */ - protected function warmUpPhpArrayAdapter(PhpArrayAdapter $phpArrayAdapter, array $values) - { - // make sure we don't cache null values - $values = array_filter($values, function ($val) { return null !== $val; }); - - return parent::warmUpPhpArrayAdapter($phpArrayAdapter, $values); - } - - /** - * @param LoaderInterface[] $loaders - * - * @return XmlFileLoader[]|YamlFileLoader[] - */ - private function extractSupportedLoaders(array $loaders): array - { - $supportedLoaders = []; - - foreach ($loaders as $loader) { - if ($loader instanceof XmlFileLoader || $loader instanceof YamlFileLoader) { - $supportedLoaders[] = $loader; - } elseif ($loader instanceof LoaderChain) { - $supportedLoaders = array_merge($supportedLoaders, $this->extractSupportedLoaders($loader->getLoaders())); - } - } - - return $supportedLoaders; - } -} diff --git a/lib/symfony/framework-bundle/Command/AboutCommand.php b/lib/symfony/framework-bundle/Command/AboutCommand.php deleted file mode 100644 index e9660e55b..000000000 --- a/lib/symfony/framework-bundle/Command/AboutCommand.php +++ /dev/null @@ -1,136 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Helper\Helper; -use Symfony\Component\Console\Helper\TableSeparator; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\HttpKernel\Kernel; -use Symfony\Component\HttpKernel\KernelInterface; - -/** - * A console command to display information about the current installation. - * - * @author Roland Franssen <franssen.roland@gmail.com> - * - * @final - */ -class AboutCommand extends Command -{ - protected static $defaultName = 'about'; - protected static $defaultDescription = 'Display information about the current project'; - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDescription(self::$defaultDescription) - ->setHelp(<<<'EOT' -The <info>%command.name%</info> command displays information about the current Symfony project. - -The <info>PHP</info> section displays important configuration that could affect your application. The values might -be different between web and CLI. -EOT - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - - /** @var KernelInterface $kernel */ - $kernel = $this->getApplication()->getKernel(); - - if (method_exists($kernel, 'getBuildDir')) { - $buildDir = $kernel->getBuildDir(); - } else { - $buildDir = $kernel->getCacheDir(); - } - - $rows = [ - ['<info>Symfony</>'], - new TableSeparator(), - ['Version', Kernel::VERSION], - ['Long-Term Support', 4 === Kernel::MINOR_VERSION ? 'Yes' : 'No'], - ['End of maintenance', Kernel::END_OF_MAINTENANCE.(self::isExpired(Kernel::END_OF_MAINTENANCE) ? ' <error>Expired</>' : ' (<comment>'.self::daysBeforeExpiration(Kernel::END_OF_MAINTENANCE).'</>)')], - ['End of life', Kernel::END_OF_LIFE.(self::isExpired(Kernel::END_OF_LIFE) ? ' <error>Expired</>' : ' (<comment>'.self::daysBeforeExpiration(Kernel::END_OF_LIFE).'</>)')], - new TableSeparator(), - ['<info>Kernel</>'], - new TableSeparator(), - ['Type', \get_class($kernel)], - ['Environment', $kernel->getEnvironment()], - ['Debug', $kernel->isDebug() ? 'true' : 'false'], - ['Charset', $kernel->getCharset()], - ['Cache directory', self::formatPath($kernel->getCacheDir(), $kernel->getProjectDir()).' (<comment>'.self::formatFileSize($kernel->getCacheDir()).'</>)'], - ['Build directory', self::formatPath($buildDir, $kernel->getProjectDir()).' (<comment>'.self::formatFileSize($buildDir).'</>)'], - ['Log directory', self::formatPath($kernel->getLogDir(), $kernel->getProjectDir()).' (<comment>'.self::formatFileSize($kernel->getLogDir()).'</>)'], - new TableSeparator(), - ['<info>PHP</>'], - new TableSeparator(), - ['Version', \PHP_VERSION], - ['Architecture', (\PHP_INT_SIZE * 8).' bits'], - ['Intl locale', class_exists(\Locale::class, false) && \Locale::getDefault() ? \Locale::getDefault() : 'n/a'], - ['Timezone', date_default_timezone_get().' (<comment>'.(new \DateTime())->format(\DateTime::W3C).'</>)'], - ['OPcache', \extension_loaded('Zend OPcache') && filter_var(\ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN) ? 'true' : 'false'], - ['APCu', \extension_loaded('apcu') && filter_var(\ini_get('apc.enabled'), \FILTER_VALIDATE_BOOLEAN) ? 'true' : 'false'], - ['Xdebug', \extension_loaded('xdebug') ? 'true' : 'false'], - ]; - - $io->table([], $rows); - - return 0; - } - - private static function formatPath(string $path, string $baseDir): string - { - return preg_replace('~^'.preg_quote($baseDir, '~').'~', '.', $path); - } - - private static function formatFileSize(string $path): string - { - if (is_file($path)) { - $size = filesize($path) ?: 0; - } else { - $size = 0; - foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS | \RecursiveDirectoryIterator::FOLLOW_SYMLINKS)) as $file) { - if ($file->isReadable()) { - $size += $file->getSize(); - } - } - } - - return Helper::formatMemory($size); - } - - private static function isExpired(string $date): bool - { - $date = \DateTime::createFromFormat('d/m/Y', '01/'.$date); - - return false !== $date && new \DateTime() > $date->modify('last day of this month 23:59:59'); - } - - private static function daysBeforeExpiration(string $date): string - { - $date = \DateTime::createFromFormat('d/m/Y', '01/'.$date); - - return (new \DateTime())->diff($date->modify('last day of this month 23:59:59'))->format('in %R%a days'); - } -} diff --git a/lib/symfony/framework-bundle/Command/AbstractConfigCommand.php b/lib/symfony/framework-bundle/Command/AbstractConfigCommand.php deleted file mode 100644 index f0d5a9814..000000000 --- a/lib/symfony/framework-bundle/Command/AbstractConfigCommand.php +++ /dev/null @@ -1,159 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Config\Definition\ConfigurationInterface; -use Symfony\Component\Console\Exception\LogicException; -use Symfony\Component\Console\Helper\Table; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\StyleInterface; -use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface; -use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; - -/** - * A console command for dumping available configuration reference. - * - * @author Kevin Bond <kevinbond@gmail.com> - * @author Wouter J <waldio.webdesign@gmail.com> - * @author Grégoire Pineau <lyrixx@lyrixx.info> - */ -abstract class AbstractConfigCommand extends ContainerDebugCommand -{ - /** - * @param OutputInterface|StyleInterface $output - */ - protected function listBundles($output) - { - $title = 'Available registered bundles with their extension alias if available'; - $headers = ['Bundle name', 'Extension alias']; - $rows = []; - - $bundles = $this->getApplication()->getKernel()->getBundles(); - usort($bundles, function ($bundleA, $bundleB) { - return strcmp($bundleA->getName(), $bundleB->getName()); - }); - - foreach ($bundles as $bundle) { - $extension = $bundle->getContainerExtension(); - $rows[] = [$bundle->getName(), $extension ? $extension->getAlias() : '']; - } - - if ($output instanceof StyleInterface) { - $output->title($title); - $output->table($headers, $rows); - } else { - $output->writeln($title); - $table = new Table($output); - $table->setHeaders($headers)->setRows($rows)->render(); - } - } - - /** - * @return ExtensionInterface - */ - protected function findExtension(string $name) - { - $bundles = $this->initializeBundles(); - $minScore = \INF; - - $kernel = $this->getApplication()->getKernel(); - if ($kernel instanceof ExtensionInterface && ($kernel instanceof ConfigurationInterface || $kernel instanceof ConfigurationExtensionInterface)) { - if ($name === $kernel->getAlias()) { - return $kernel; - } - - if ($kernel->getAlias()) { - $distance = levenshtein($name, $kernel->getAlias()); - - if ($distance < $minScore) { - $guess = $kernel->getAlias(); - $minScore = $distance; - } - } - } - - foreach ($bundles as $bundle) { - if ($name === $bundle->getName()) { - if (!$bundle->getContainerExtension()) { - throw new \LogicException(sprintf('Bundle "%s" does not have a container extension.', $name)); - } - - return $bundle->getContainerExtension(); - } - - $distance = levenshtein($name, $bundle->getName()); - - if ($distance < $minScore) { - $guess = $bundle->getName(); - $minScore = $distance; - } - } - - $container = $this->getContainerBuilder($kernel); - - if ($container->hasExtension($name)) { - return $container->getExtension($name); - } - - foreach ($container->getExtensions() as $extension) { - $distance = levenshtein($name, $extension->getAlias()); - - if ($distance < $minScore) { - $guess = $extension->getAlias(); - $minScore = $distance; - } - } - - if (!str_ends_with($name, 'Bundle')) { - $message = sprintf('No extensions with configuration available for "%s".', $name); - } else { - $message = sprintf('No extension with alias "%s" is enabled.', $name); - } - - if (isset($guess) && $minScore < 3) { - $message .= sprintf("\n\nDid you mean \"%s\"?", $guess); - } - - throw new LogicException($message); - } - - public function validateConfiguration(ExtensionInterface $extension, $configuration) - { - if (!$configuration) { - throw new \LogicException(sprintf('The extension with alias "%s" does not have its getConfiguration() method setup.', $extension->getAlias())); - } - - if (!$configuration instanceof ConfigurationInterface) { - throw new \LogicException(sprintf('Configuration class "%s" should implement ConfigurationInterface in order to be dumpable.', get_debug_type($configuration))); - } - } - - private function initializeBundles() - { - // Re-build bundle manually to initialize DI extensions that can be extended by other bundles in their build() method - // as this method is not called when the container is loaded from the cache. - $kernel = $this->getApplication()->getKernel(); - $container = $this->getContainerBuilder($kernel); - $bundles = $kernel->getBundles(); - foreach ($bundles as $bundle) { - if ($extension = $bundle->getContainerExtension()) { - $container->registerExtension($extension); - } - } - - foreach ($bundles as $bundle) { - $bundle->build($container); - } - - return $bundles; - } -} diff --git a/lib/symfony/framework-bundle/Command/AssetsInstallCommand.php b/lib/symfony/framework-bundle/Command/AssetsInstallCommand.php deleted file mode 100644 index 870e686de..000000000 --- a/lib/symfony/framework-bundle/Command/AssetsInstallCommand.php +++ /dev/null @@ -1,279 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\Filesystem\Exception\IOException; -use Symfony\Component\Filesystem\Filesystem; -use Symfony\Component\Finder\Finder; -use Symfony\Component\HttpKernel\Bundle\BundleInterface; -use Symfony\Component\HttpKernel\KernelInterface; - -/** - * Command that places bundle web assets into a given directory. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Gábor Egyed <gabor.egyed@gmail.com> - * - * @final - */ -class AssetsInstallCommand extends Command -{ - public const METHOD_COPY = 'copy'; - public const METHOD_ABSOLUTE_SYMLINK = 'absolute symlink'; - public const METHOD_RELATIVE_SYMLINK = 'relative symlink'; - - protected static $defaultName = 'assets:install'; - protected static $defaultDescription = 'Install bundle\'s web assets under a public directory'; - - private $filesystem; - private $projectDir; - - public function __construct(Filesystem $filesystem, string $projectDir) - { - parent::__construct(); - - $this->filesystem = $filesystem; - $this->projectDir = $projectDir; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('target', InputArgument::OPTIONAL, 'The target directory', null), - ]) - ->addOption('symlink', null, InputOption::VALUE_NONE, 'Symlink the assets instead of copying them') - ->addOption('relative', null, InputOption::VALUE_NONE, 'Make relative symlinks') - ->addOption('no-cleanup', null, InputOption::VALUE_NONE, 'Do not remove the assets of the bundles that no longer exist') - ->setDescription(self::$defaultDescription) - ->setHelp(<<<'EOT' -The <info>%command.name%</info> command installs bundle assets into a given -directory (e.g. the <comment>public</comment> directory). - - <info>php %command.full_name% public</info> - -A "bundles" directory will be created inside the target directory and the -"Resources/public" directory of each bundle will be copied into it. - -To create a symlink to each bundle instead of copying its assets, use the -<info>--symlink</info> option (will fall back to hard copies when symbolic links aren't possible: - - <info>php %command.full_name% public --symlink</info> - -To make symlink relative, add the <info>--relative</info> option: - - <info>php %command.full_name% public --symlink --relative</info> - -EOT - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - /** @var KernelInterface $kernel */ - $kernel = $this->getApplication()->getKernel(); - $targetArg = rtrim($input->getArgument('target') ?? '', '/'); - if (!$targetArg) { - $targetArg = $this->getPublicDirectory($kernel->getContainer()); - } - - if (!is_dir($targetArg)) { - $targetArg = $kernel->getProjectDir().'/'.$targetArg; - - if (!is_dir($targetArg)) { - throw new InvalidArgumentException(sprintf('The target directory "%s" does not exist.', $targetArg)); - } - } - - $bundlesDir = $targetArg.'/bundles/'; - - $io = new SymfonyStyle($input, $output); - $io->newLine(); - - if ($input->getOption('relative')) { - $expectedMethod = self::METHOD_RELATIVE_SYMLINK; - $io->text('Trying to install assets as <info>relative symbolic links</info>.'); - } elseif ($input->getOption('symlink')) { - $expectedMethod = self::METHOD_ABSOLUTE_SYMLINK; - $io->text('Trying to install assets as <info>absolute symbolic links</info>.'); - } else { - $expectedMethod = self::METHOD_COPY; - $io->text('Installing assets as <info>hard copies</info>.'); - } - - $io->newLine(); - - $rows = []; - $copyUsed = false; - $exitCode = 0; - $validAssetDirs = []; - /** @var BundleInterface $bundle */ - foreach ($kernel->getBundles() as $bundle) { - if (!is_dir($originDir = $bundle->getPath().'/Resources/public') && !is_dir($originDir = $bundle->getPath().'/public')) { - continue; - } - - $assetDir = preg_replace('/bundle$/', '', strtolower($bundle->getName())); - $targetDir = $bundlesDir.$assetDir; - $validAssetDirs[] = $assetDir; - - if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { - $message = sprintf("%s\n-> %s", $bundle->getName(), $targetDir); - } else { - $message = $bundle->getName(); - } - - try { - $this->filesystem->remove($targetDir); - - if (self::METHOD_RELATIVE_SYMLINK === $expectedMethod) { - $method = $this->relativeSymlinkWithFallback($originDir, $targetDir); - } elseif (self::METHOD_ABSOLUTE_SYMLINK === $expectedMethod) { - $method = $this->absoluteSymlinkWithFallback($originDir, $targetDir); - } else { - $method = $this->hardCopy($originDir, $targetDir); - } - - if (self::METHOD_COPY === $method) { - $copyUsed = true; - } - - if ($method === $expectedMethod) { - $rows[] = [sprintf('<fg=green;options=bold>%s</>', '\\' === \DIRECTORY_SEPARATOR ? 'OK' : "\xE2\x9C\x94" /* HEAVY CHECK MARK (U+2714) */), $message, $method]; - } else { - $rows[] = [sprintf('<fg=yellow;options=bold>%s</>', '\\' === \DIRECTORY_SEPARATOR ? 'WARNING' : '!'), $message, $method]; - } - } catch (\Exception $e) { - $exitCode = 1; - $rows[] = [sprintf('<fg=red;options=bold>%s</>', '\\' === \DIRECTORY_SEPARATOR ? 'ERROR' : "\xE2\x9C\x98" /* HEAVY BALLOT X (U+2718) */), $message, $e->getMessage()]; - } - } - // remove the assets of the bundles that no longer exist - if (!$input->getOption('no-cleanup') && is_dir($bundlesDir)) { - $dirsToRemove = Finder::create()->depth(0)->directories()->exclude($validAssetDirs)->in($bundlesDir); - $this->filesystem->remove($dirsToRemove); - } - - if ($rows) { - $io->table(['', 'Bundle', 'Method / Error'], $rows); - } - - if (0 !== $exitCode) { - $io->error('Some errors occurred while installing assets.'); - } else { - if ($copyUsed) { - $io->note('Some assets were installed via copy. If you make changes to these assets you have to run this command again.'); - } - $io->success($rows ? 'All assets were successfully installed.' : 'No assets were provided by any bundle.'); - } - - return $exitCode; - } - - /** - * Try to create relative symlink. - * - * Falling back to absolute symlink and finally hard copy. - */ - private function relativeSymlinkWithFallback(string $originDir, string $targetDir): string - { - try { - $this->symlink($originDir, $targetDir, true); - $method = self::METHOD_RELATIVE_SYMLINK; - } catch (IOException $e) { - $method = $this->absoluteSymlinkWithFallback($originDir, $targetDir); - } - - return $method; - } - - /** - * Try to create absolute symlink. - * - * Falling back to hard copy. - */ - private function absoluteSymlinkWithFallback(string $originDir, string $targetDir): string - { - try { - $this->symlink($originDir, $targetDir); - $method = self::METHOD_ABSOLUTE_SYMLINK; - } catch (IOException $e) { - // fall back to copy - $method = $this->hardCopy($originDir, $targetDir); - } - - return $method; - } - - /** - * Creates symbolic link. - * - * @throws IOException if link cannot be created - */ - private function symlink(string $originDir, string $targetDir, bool $relative = false) - { - if ($relative) { - $this->filesystem->mkdir(\dirname($targetDir)); - $originDir = $this->filesystem->makePathRelative($originDir, realpath(\dirname($targetDir))); - } - $this->filesystem->symlink($originDir, $targetDir); - if (!file_exists($targetDir)) { - throw new IOException(sprintf('Symbolic link "%s" was created but appears to be broken.', $targetDir), 0, null, $targetDir); - } - } - - /** - * Copies origin to target. - */ - private function hardCopy(string $originDir, string $targetDir): string - { - $this->filesystem->mkdir($targetDir, 0777); - // We use a custom iterator to ignore VCS files - $this->filesystem->mirror($originDir, $targetDir, Finder::create()->ignoreDotFiles(false)->in($originDir)); - - return self::METHOD_COPY; - } - - private function getPublicDirectory(ContainerInterface $container): string - { - $defaultPublicDir = 'public'; - - if (null === $this->projectDir && !$container->hasParameter('kernel.project_dir')) { - return $defaultPublicDir; - } - - $composerFilePath = ($this->projectDir ?? $container->getParameter('kernel.project_dir')).'/composer.json'; - - if (!file_exists($composerFilePath)) { - return $defaultPublicDir; - } - - $composerConfig = json_decode(file_get_contents($composerFilePath), true); - - return $composerConfig['extra']['public-dir'] ?? $defaultPublicDir; - } -} diff --git a/lib/symfony/framework-bundle/Command/BuildDebugContainerTrait.php b/lib/symfony/framework-bundle/Command/BuildDebugContainerTrait.php deleted file mode 100644 index 785027dbc..000000000 --- a/lib/symfony/framework-bundle/Command/BuildDebugContainerTrait.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Config\ConfigCache; -use Symfony\Component\Config\FileLocator; -use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; -use Symfony\Component\HttpKernel\KernelInterface; - -/** - * @internal - * - * @author Robin Chalas <robin.chalas@gmail.com> - * @author Nicolas Grekas <p@tchwork.com> - */ -trait BuildDebugContainerTrait -{ - protected $containerBuilder; - - /** - * Loads the ContainerBuilder from the cache. - * - * @throws \LogicException - */ - protected function getContainerBuilder(KernelInterface $kernel): ContainerBuilder - { - if ($this->containerBuilder) { - return $this->containerBuilder; - } - - if (!$kernel->isDebug() || !(new ConfigCache($kernel->getContainer()->getParameter('debug.container.dump'), true))->isFresh()) { - $buildContainer = \Closure::bind(function () { - $this->initializeBundles(); - - return $this->buildContainer(); - }, $kernel, \get_class($kernel)); - $container = $buildContainer(); - $container->getCompilerPassConfig()->setRemovingPasses([]); - $container->getCompilerPassConfig()->setAfterRemovingPasses([]); - $container->compile(); - } else { - (new XmlFileLoader($container = new ContainerBuilder(), new FileLocator()))->load($kernel->getContainer()->getParameter('debug.container.dump')); - $locatorPass = new ServiceLocatorTagPass(); - $locatorPass->process($container); - - $container->getCompilerPassConfig()->setBeforeOptimizationPasses([]); - $container->getCompilerPassConfig()->setOptimizationPasses([]); - $container->getCompilerPassConfig()->setBeforeRemovingPasses([]); - } - - return $this->containerBuilder = $container; - } -} diff --git a/lib/symfony/framework-bundle/Command/CacheClearCommand.php b/lib/symfony/framework-bundle/Command/CacheClearCommand.php deleted file mode 100644 index b0d556539..000000000 --- a/lib/symfony/framework-bundle/Command/CacheClearCommand.php +++ /dev/null @@ -1,261 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Exception\RuntimeException; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\DependencyInjection\Dumper\Preloader; -use Symfony\Component\EventDispatcher\EventDispatcher; -use Symfony\Component\Filesystem\Exception\IOException; -use Symfony\Component\Filesystem\Filesystem; -use Symfony\Component\Finder\Finder; -use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface; -use Symfony\Component\HttpKernel\RebootableInterface; - -/** - * Clear and Warmup the cache. - * - * @author Francis Besset <francis.besset@gmail.com> - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class CacheClearCommand extends Command -{ - protected static $defaultName = 'cache:clear'; - protected static $defaultDescription = 'Clear the cache'; - - private $cacheClearer; - private $filesystem; - - public function __construct(CacheClearerInterface $cacheClearer, Filesystem $filesystem = null) - { - parent::__construct(); - - $this->cacheClearer = $cacheClearer; - $this->filesystem = $filesystem ?? new Filesystem(); - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputOption('no-warmup', '', InputOption::VALUE_NONE, 'Do not warm up the cache'), - new InputOption('no-optional-warmers', '', InputOption::VALUE_NONE, 'Skip optional cache warmers (faster)'), - ]) - ->setDescription(self::$defaultDescription) - ->setHelp(<<<'EOF' -The <info>%command.name%</info> command clears and warms up the application cache for a given environment -and debug mode: - - <info>php %command.full_name% --env=dev</info> - <info>php %command.full_name% --env=prod --no-debug</info> -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $fs = $this->filesystem; - $io = new SymfonyStyle($input, $output); - - $kernel = $this->getApplication()->getKernel(); - $realCacheDir = $kernel->getContainer()->getParameter('kernel.cache_dir'); - $realBuildDir = $kernel->getContainer()->hasParameter('kernel.build_dir') ? $kernel->getContainer()->getParameter('kernel.build_dir') : $realCacheDir; - // the old cache dir name must not be longer than the real one to avoid exceeding - // the maximum length of a directory or file path within it (esp. Windows MAX_PATH) - $oldCacheDir = substr($realCacheDir, 0, -1).(str_ends_with($realCacheDir, '~') ? '+' : '~'); - $fs->remove($oldCacheDir); - - if (!is_writable($realCacheDir)) { - throw new RuntimeException(sprintf('Unable to write in the "%s" directory.', $realCacheDir)); - } - - $useBuildDir = $realBuildDir !== $realCacheDir; - $oldBuildDir = substr($realBuildDir, 0, -1).('~' === substr($realBuildDir, -1) ? '+' : '~'); - if ($useBuildDir) { - $fs->remove($oldBuildDir); - - if (!is_writable($realBuildDir)) { - throw new RuntimeException(sprintf('Unable to write in the "%s" directory.', $realBuildDir)); - } - - if ($this->isNfs($realCacheDir)) { - $fs->remove($realCacheDir); - } else { - $fs->rename($realCacheDir, $oldCacheDir); - } - $fs->mkdir($realCacheDir); - } - - $io->comment(sprintf('Clearing the cache for the <info>%s</info> environment with debug <info>%s</info>', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); - if ($useBuildDir) { - $this->cacheClearer->clear($realBuildDir); - } - $this->cacheClearer->clear($realCacheDir); - - // The current event dispatcher is stale, let's not use it anymore - $this->getApplication()->setDispatcher(new EventDispatcher()); - - $containerFile = (new \ReflectionObject($kernel->getContainer()))->getFileName(); - $containerDir = basename(\dirname($containerFile)); - - // the warmup cache dir name must have the same length as the real one - // to avoid the many problems in serialized resources files - $warmupDir = substr($realBuildDir, 0, -1).('_' === substr($realBuildDir, -1) ? '-' : '_'); - - if ($output->isVerbose() && $fs->exists($warmupDir)) { - $io->comment('Clearing outdated warmup directory...'); - } - $fs->remove($warmupDir); - - if ($_SERVER['REQUEST_TIME'] <= filemtime($containerFile) && filemtime($containerFile) <= time()) { - if ($output->isVerbose()) { - $io->comment('Cache is fresh.'); - } - if (!$input->getOption('no-warmup') && !$input->getOption('no-optional-warmers')) { - if ($output->isVerbose()) { - $io->comment('Warming up optional cache...'); - } - $warmer = $kernel->getContainer()->get('cache_warmer'); - // non optional warmers already ran during container compilation - $warmer->enableOnlyOptionalWarmers(); - $preload = (array) $warmer->warmUp($realCacheDir); - - if ($preload && file_exists($preloadFile = $realCacheDir.'/'.$kernel->getContainer()->getParameter('kernel.container_class').'.preload.php')) { - Preloader::append($preloadFile, $preload); - } - } - } else { - $fs->mkdir($warmupDir); - - if (!$input->getOption('no-warmup')) { - if ($output->isVerbose()) { - $io->comment('Warming up cache...'); - } - $this->warmup($warmupDir, $realCacheDir, !$input->getOption('no-optional-warmers')); - } - - if (!$fs->exists($warmupDir.'/'.$containerDir)) { - $fs->rename($realBuildDir.'/'.$containerDir, $warmupDir.'/'.$containerDir); - touch($warmupDir.'/'.$containerDir.'.legacy'); - } - - if ($this->isNfs($realBuildDir)) { - $io->note('For better performances, you should move the cache and log directories to a non-shared folder of the VM.'); - $fs->remove($realBuildDir); - } else { - $fs->rename($realBuildDir, $oldBuildDir); - } - - $fs->rename($warmupDir, $realBuildDir); - - if ($output->isVerbose()) { - $io->comment('Removing old build and cache directory...'); - } - - if ($useBuildDir) { - try { - $fs->remove($oldBuildDir); - } catch (IOException $e) { - if ($output->isVerbose()) { - $io->warning($e->getMessage()); - } - } - } - - try { - $fs->remove($oldCacheDir); - } catch (IOException $e) { - if ($output->isVerbose()) { - $io->warning($e->getMessage()); - } - } - } - - if ($output->isVerbose()) { - $io->comment('Finished'); - } - - $io->success(sprintf('Cache for the "%s" environment (debug=%s) was successfully cleared.', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); - - return 0; - } - - private function isNfs(string $dir): bool - { - static $mounts = null; - - if (null === $mounts) { - $mounts = []; - if ('/' === \DIRECTORY_SEPARATOR && $files = @file('/proc/mounts')) { - foreach ($files as $mount) { - $mount = \array_slice(explode(' ', $mount), 1, -3); - if (!\in_array(array_pop($mount), ['vboxsf', 'nfs'])) { - continue; - } - $mounts[] = implode(' ', $mount).'/'; - } - } - } - foreach ($mounts as $mount) { - if (0 === strpos($dir, $mount)) { - return true; - } - } - - return false; - } - - private function warmup(string $warmupDir, string $realBuildDir, bool $enableOptionalWarmers = true) - { - // create a temporary kernel - $kernel = $this->getApplication()->getKernel(); - if (!$kernel instanceof RebootableInterface) { - throw new \LogicException('Calling "cache:clear" with a kernel that does not implement "Symfony\Component\HttpKernel\RebootableInterface" is not supported.'); - } - $kernel->reboot($warmupDir); - - // warmup temporary dir - if ($enableOptionalWarmers) { - $warmer = $kernel->getContainer()->get('cache_warmer'); - // non optional warmers already ran during container compilation - $warmer->enableOnlyOptionalWarmers(); - $preload = (array) $warmer->warmUp($warmupDir); - - if ($preload && file_exists($preloadFile = $warmupDir.'/'.$kernel->getContainer()->getParameter('kernel.container_class').'.preload.php')) { - Preloader::append($preloadFile, $preload); - } - } - - // fix references to cached files with the real cache directory name - $search = [$warmupDir, str_replace('\\', '\\\\', $warmupDir)]; - $replace = str_replace('\\', '/', $realBuildDir); - foreach (Finder::create()->files()->in($warmupDir) as $file) { - $content = str_replace($search, $replace, file_get_contents($file), $count); - if ($count) { - file_put_contents($file, $content); - } - } - } -} diff --git a/lib/symfony/framework-bundle/Command/CachePoolClearCommand.php b/lib/symfony/framework-bundle/Command/CachePoolClearCommand.php deleted file mode 100644 index b72924dfa..000000000 --- a/lib/symfony/framework-bundle/Command/CachePoolClearCommand.php +++ /dev/null @@ -1,131 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Completion\CompletionInput; -use Symfony\Component\Console\Completion\CompletionSuggestions; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer; - -/** - * Clear cache pools. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -final class CachePoolClearCommand extends Command -{ - protected static $defaultName = 'cache:pool:clear'; - protected static $defaultDescription = 'Clear cache pools'; - - private $poolClearer; - private $poolNames; - - /** - * @param string[]|null $poolNames - */ - public function __construct(Psr6CacheClearer $poolClearer, array $poolNames = null) - { - parent::__construct(); - - $this->poolClearer = $poolClearer; - $this->poolNames = $poolNames; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('pools', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'A list of cache pools or cache pool clearers'), - ]) - ->setDescription(self::$defaultDescription) - ->setHelp(<<<'EOF' -The <info>%command.name%</info> command clears the given cache pools or cache pool clearers. - - %command.full_name% <cache pool or clearer 1> [...<cache pool or clearer N>] -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - $kernel = $this->getApplication()->getKernel(); - $pools = []; - $clearers = []; - - foreach ($input->getArgument('pools') as $id) { - if ($this->poolClearer->hasPool($id)) { - $pools[$id] = $id; - } else { - $pool = $kernel->getContainer()->get($id); - - if ($pool instanceof CacheItemPoolInterface) { - $pools[$id] = $pool; - } elseif ($pool instanceof Psr6CacheClearer) { - $clearers[$id] = $pool; - } else { - throw new InvalidArgumentException(sprintf('"%s" is not a cache pool nor a cache clearer.', $id)); - } - } - } - - foreach ($clearers as $id => $clearer) { - $io->comment(sprintf('Calling cache clearer: <info>%s</info>', $id)); - $clearer->clear($kernel->getContainer()->getParameter('kernel.cache_dir')); - } - - $failure = false; - foreach ($pools as $id => $pool) { - $io->comment(sprintf('Clearing cache pool: <info>%s</info>', $id)); - - if ($pool instanceof CacheItemPoolInterface) { - if (!$pool->clear()) { - $io->warning(sprintf('Cache pool "%s" could not be cleared.', $pool)); - $failure = true; - } - } else { - if (false === $this->poolClearer->clearPool($id)) { - $io->warning(sprintf('Cache pool "%s" could not be cleared.', $pool)); - $failure = true; - } - } - } - - if ($failure) { - return 1; - } - - $io->success('Cache was successfully cleared.'); - - return 0; - } - - public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void - { - if (\is_array($this->poolNames) && $input->mustSuggestArgumentValuesFor('pools')) { - $suggestions->suggestValues($this->poolNames); - } - } -} diff --git a/lib/symfony/framework-bundle/Command/CachePoolDeleteCommand.php b/lib/symfony/framework-bundle/Command/CachePoolDeleteCommand.php deleted file mode 100644 index b36d48cfe..000000000 --- a/lib/symfony/framework-bundle/Command/CachePoolDeleteCommand.php +++ /dev/null @@ -1,98 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Completion\CompletionInput; -use Symfony\Component\Console\Completion\CompletionSuggestions; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer; - -/** - * Delete an item from a cache pool. - * - * @author Pierre du Plessis <pdples@gmail.com> - */ -final class CachePoolDeleteCommand extends Command -{ - protected static $defaultName = 'cache:pool:delete'; - protected static $defaultDescription = 'Delete an item from a cache pool'; - - private $poolClearer; - private $poolNames; - - /** - * @param string[]|null $poolNames - */ - public function __construct(Psr6CacheClearer $poolClearer, array $poolNames = null) - { - parent::__construct(); - - $this->poolClearer = $poolClearer; - $this->poolNames = $poolNames; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('pool', InputArgument::REQUIRED, 'The cache pool from which to delete an item'), - new InputArgument('key', InputArgument::REQUIRED, 'The cache key to delete from the pool'), - ]) - ->setDescription(self::$defaultDescription) - ->setHelp(<<<'EOF' -The <info>%command.name%</info> deletes an item from a given cache pool. - - %command.full_name% <pool> <key> -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - $pool = $input->getArgument('pool'); - $key = $input->getArgument('key'); - $cachePool = $this->poolClearer->getPool($pool); - - if (!$cachePool->hasItem($key)) { - $io->note(sprintf('Cache item "%s" does not exist in cache pool "%s".', $key, $pool)); - - return 0; - } - - if (!$cachePool->deleteItem($key)) { - throw new \Exception(sprintf('Cache item "%s" could not be deleted.', $key)); - } - - $io->success(sprintf('Cache item "%s" was successfully deleted.', $key)); - - return 0; - } - - public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void - { - if (\is_array($this->poolNames) && $input->mustSuggestArgumentValuesFor('pool')) { - $suggestions->suggestValues($this->poolNames); - } - } -} diff --git a/lib/symfony/framework-bundle/Command/CachePoolListCommand.php b/lib/symfony/framework-bundle/Command/CachePoolListCommand.php deleted file mode 100644 index 0ad33241d..000000000 --- a/lib/symfony/framework-bundle/Command/CachePoolListCommand.php +++ /dev/null @@ -1,68 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * List available cache pools. - * - * @author Tobias Nyholm <tobias.nyholm@gmail.com> - */ -final class CachePoolListCommand extends Command -{ - protected static $defaultName = 'cache:pool:list'; - protected static $defaultDescription = 'List available cache pools'; - - private $poolNames; - - /** - * @param string[] $poolNames - */ - public function __construct(array $poolNames) - { - parent::__construct(); - - $this->poolNames = $poolNames; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDescription(self::$defaultDescription) - ->setHelp(<<<'EOF' -The <info>%command.name%</info> command lists all available cache pools. -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - - $io->table(['Pool name'], array_map(function ($pool) { - return [$pool]; - }, $this->poolNames)); - - return 0; - } -} diff --git a/lib/symfony/framework-bundle/Command/CachePoolPruneCommand.php b/lib/symfony/framework-bundle/Command/CachePoolPruneCommand.php deleted file mode 100644 index 8d1035294..000000000 --- a/lib/symfony/framework-bundle/Command/CachePoolPruneCommand.php +++ /dev/null @@ -1,74 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * Cache pool pruner command. - * - * @author Rob Frawley 2nd <rmf@src.run> - */ -final class CachePoolPruneCommand extends Command -{ - protected static $defaultName = 'cache:pool:prune'; - protected static $defaultDescription = 'Prune cache pools'; - - private $pools; - - /** - * @param iterable<mixed, PruneableInterface> $pools - */ - public function __construct(iterable $pools) - { - parent::__construct(); - - $this->pools = $pools; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDescription(self::$defaultDescription) - ->setHelp(<<<'EOF' -The <info>%command.name%</info> command deletes all expired items from all pruneable pools. - - %command.full_name% -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - - foreach ($this->pools as $name => $pool) { - $io->comment(sprintf('Pruning cache pool: <info>%s</info>', $name)); - $pool->prune(); - } - - $io->success('Successfully pruned cache pool(s).'); - - return 0; - } -} diff --git a/lib/symfony/framework-bundle/Command/CacheWarmupCommand.php b/lib/symfony/framework-bundle/Command/CacheWarmupCommand.php deleted file mode 100644 index ddaf9eb63..000000000 --- a/lib/symfony/framework-bundle/Command/CacheWarmupCommand.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\DependencyInjection\Dumper\Preloader; -use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate; - -/** - * Warmup the cache. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class CacheWarmupCommand extends Command -{ - protected static $defaultName = 'cache:warmup'; - protected static $defaultDescription = 'Warm up an empty cache'; - - private $cacheWarmer; - - public function __construct(CacheWarmerAggregate $cacheWarmer) - { - parent::__construct(); - - $this->cacheWarmer = $cacheWarmer; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputOption('no-optional-warmers', '', InputOption::VALUE_NONE, 'Skip optional cache warmers (faster)'), - ]) - ->setDescription(self::$defaultDescription) - ->setHelp(<<<'EOF' -The <info>%command.name%</info> command warms up the cache. - -Before running this command, the cache must be empty. - -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - - $kernel = $this->getApplication()->getKernel(); - $io->comment(sprintf('Warming up the cache for the <info>%s</info> environment with debug <info>%s</info>', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); - - if (!$input->getOption('no-optional-warmers')) { - $this->cacheWarmer->enableOptionalWarmers(); - } - - $preload = $this->cacheWarmer->warmUp($cacheDir = $kernel->getContainer()->getParameter('kernel.cache_dir')); - - if ($preload && file_exists($preloadFile = $cacheDir.'/'.$kernel->getContainer()->getParameter('kernel.container_class').'.preload.php')) { - Preloader::append($preloadFile, $preload); - } - - $io->success(sprintf('Cache for the "%s" environment (debug=%s) was successfully warmed.', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); - - return 0; - } -} diff --git a/lib/symfony/framework-bundle/Command/ConfigDebugCommand.php b/lib/symfony/framework-bundle/Command/ConfigDebugCommand.php deleted file mode 100644 index 12e501baa..000000000 --- a/lib/symfony/framework-bundle/Command/ConfigDebugCommand.php +++ /dev/null @@ -1,240 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Config\Definition\ConfigurationInterface; -use Symfony\Component\Config\Definition\Processor; -use Symfony\Component\Console\Completion\CompletionInput; -use Symfony\Component\Console\Completion\CompletionSuggestions; -use Symfony\Component\Console\Exception\LogicException; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\DependencyInjection\Compiler\ValidateEnvPlaceholdersPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface; -use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; -use Symfony\Component\Yaml\Yaml; - -/** - * A console command for dumping available configuration reference. - * - * @author Grégoire Pineau <lyrixx@lyrixx.info> - * - * @final - */ -class ConfigDebugCommand extends AbstractConfigCommand -{ - protected static $defaultName = 'debug:config'; - protected static $defaultDescription = 'Dump the current configuration for an extension'; - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('name', InputArgument::OPTIONAL, 'The bundle name or the extension alias'), - new InputArgument('path', InputArgument::OPTIONAL, 'The configuration option path'), - ]) - ->setDescription(self::$defaultDescription) - ->setHelp(<<<'EOF' -The <info>%command.name%</info> command dumps the current configuration for an -extension/bundle. - -Either the extension alias or bundle name can be used: - - <info>php %command.full_name% framework</info> - <info>php %command.full_name% FrameworkBundle</info> - -For dumping a specific option, add its path as second argument: - - <info>php %command.full_name% framework serializer.enabled</info> - -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - $errorIo = $io->getErrorStyle(); - - if (null === $name = $input->getArgument('name')) { - $this->listBundles($errorIo); - - $kernel = $this->getApplication()->getKernel(); - if ($kernel instanceof ExtensionInterface - && ($kernel instanceof ConfigurationInterface || $kernel instanceof ConfigurationExtensionInterface) - && $kernel->getAlias() - ) { - $errorIo->table(['Kernel Extension'], [[$kernel->getAlias()]]); - } - - $errorIo->comment('Provide the name of a bundle as the first argument of this command to dump its configuration. (e.g. <comment>debug:config FrameworkBundle</comment>)'); - $errorIo->comment('For dumping a specific option, add its path as the second argument of this command. (e.g. <comment>debug:config FrameworkBundle serializer</comment> to dump the <comment>framework.serializer</comment> configuration)'); - - return 0; - } - - $extension = $this->findExtension($name); - $extensionAlias = $extension->getAlias(); - $container = $this->compileContainer(); - - $config = $this->getConfig($extension, $container); - - if (null === $path = $input->getArgument('path')) { - $io->title( - sprintf('Current configuration for %s', $name === $extensionAlias ? sprintf('extension with alias "%s"', $extensionAlias) : sprintf('"%s"', $name)) - ); - - $io->writeln(Yaml::dump([$extensionAlias => $config], 10)); - - return 0; - } - - try { - $config = $this->getConfigForPath($config, $path, $extensionAlias); - } catch (LogicException $e) { - $errorIo->error($e->getMessage()); - - return 1; - } - - $io->title(sprintf('Current configuration for "%s.%s"', $extensionAlias, $path)); - - $io->writeln(Yaml::dump($config, 10)); - - return 0; - } - - private function compileContainer(): ContainerBuilder - { - $kernel = clone $this->getApplication()->getKernel(); - $kernel->boot(); - - $method = new \ReflectionMethod($kernel, 'buildContainer'); - $method->setAccessible(true); - $container = $method->invoke($kernel); - $container->getCompiler()->compile($container); - - return $container; - } - - /** - * Iterate over configuration until the last step of the given path. - * - * @throws LogicException If the configuration does not exist - * - * @return mixed - */ - private function getConfigForPath(array $config, string $path, string $alias) - { - $steps = explode('.', $path); - - foreach ($steps as $step) { - if (!\array_key_exists($step, $config)) { - throw new LogicException(sprintf('Unable to find configuration for "%s.%s".', $alias, $path)); - } - - $config = $config[$step]; - } - - return $config; - } - - private function getConfigForExtension(ExtensionInterface $extension, ContainerBuilder $container): array - { - $extensionAlias = $extension->getAlias(); - - $extensionConfig = []; - foreach ($container->getCompilerPassConfig()->getPasses() as $pass) { - if ($pass instanceof ValidateEnvPlaceholdersPass) { - $extensionConfig = $pass->getExtensionConfig(); - break; - } - } - - if (isset($extensionConfig[$extensionAlias])) { - return $extensionConfig[$extensionAlias]; - } - - // Fall back to default config if the extension has one - - if (!$extension instanceof ConfigurationExtensionInterface) { - throw new \LogicException(sprintf('The extension with alias "%s" does not have configuration.', $extensionAlias)); - } - - $configs = $container->getExtensionConfig($extensionAlias); - $configuration = $extension->getConfiguration($configs, $container); - $this->validateConfiguration($extension, $configuration); - - return (new Processor())->processConfiguration($configuration, $configs); - } - - public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void - { - if ($input->mustSuggestArgumentValuesFor('name')) { - $suggestions->suggestValues($this->getAvailableBundles(!preg_match('/^[A-Z]/', $input->getCompletionValue()))); - - return; - } - - if ($input->mustSuggestArgumentValuesFor('path') && null !== $name = $input->getArgument('name')) { - try { - $config = $this->getConfig($this->findExtension($name), $this->compileContainer()); - $paths = array_keys(self::buildPathsCompletion($config)); - $suggestions->suggestValues($paths); - } catch (LogicException $e) { - } - } - } - - private function getAvailableBundles(bool $alias): array - { - $availableBundles = []; - foreach ($this->getApplication()->getKernel()->getBundles() as $bundle) { - $availableBundles[] = $alias ? $bundle->getContainerExtension()->getAlias() : $bundle->getName(); - } - - return $availableBundles; - } - - private function getConfig(ExtensionInterface $extension, ContainerBuilder $container) - { - return $container->resolveEnvPlaceholders( - $container->getParameterBag()->resolveValue( - $this->getConfigForExtension($extension, $container) - ) - ); - } - - private static function buildPathsCompletion(array $paths, string $prefix = ''): array - { - $completionPaths = []; - foreach ($paths as $key => $values) { - if (\is_array($values)) { - $completionPaths = $completionPaths + self::buildPathsCompletion($values, $prefix.$key.'.'); - } else { - $completionPaths[$prefix.$key] = null; - } - } - - return $completionPaths; - } -} diff --git a/lib/symfony/framework-bundle/Command/ConfigDumpReferenceCommand.php b/lib/symfony/framework-bundle/Command/ConfigDumpReferenceCommand.php deleted file mode 100644 index 63e6496bd..000000000 --- a/lib/symfony/framework-bundle/Command/ConfigDumpReferenceCommand.php +++ /dev/null @@ -1,190 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Config\Definition\ConfigurationInterface; -use Symfony\Component\Config\Definition\Dumper\XmlReferenceDumper; -use Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper; -use Symfony\Component\Console\Completion\CompletionInput; -use Symfony\Component\Console\Completion\CompletionSuggestions; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface; -use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; -use Symfony\Component\Yaml\Yaml; - -/** - * A console command for dumping available configuration reference. - * - * @author Kevin Bond <kevinbond@gmail.com> - * @author Wouter J <waldio.webdesign@gmail.com> - * @author Grégoire Pineau <lyrixx@lyrixx.info> - * - * @final - */ -class ConfigDumpReferenceCommand extends AbstractConfigCommand -{ - protected static $defaultName = 'config:dump-reference'; - protected static $defaultDescription = 'Dump the default configuration for an extension'; - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('name', InputArgument::OPTIONAL, 'The Bundle name or the extension alias'), - new InputArgument('path', InputArgument::OPTIONAL, 'The configuration option path'), - new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (yaml or xml)', 'yaml'), - ]) - ->setDescription(self::$defaultDescription) - ->setHelp(<<<'EOF' -The <info>%command.name%</info> command dumps the default configuration for an -extension/bundle. - -Either the extension alias or bundle name can be used: - - <info>php %command.full_name% framework</info> - <info>php %command.full_name% FrameworkBundle</info> - -With the <info>--format</info> option specifies the format of the configuration, -this is either <comment>yaml</comment> or <comment>xml</comment>. -When the option is not provided, <comment>yaml</comment> is used. - - <info>php %command.full_name% FrameworkBundle --format=xml</info> - -For dumping a specific option, add its path as second argument (only available for the yaml format): - - <info>php %command.full_name% framework http_client.default_options</info> - -EOF - ) - ; - } - - /** - * {@inheritdoc} - * - * @throws \LogicException - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - $errorIo = $io->getErrorStyle(); - - if (null === $name = $input->getArgument('name')) { - $this->listBundles($errorIo); - - $kernel = $this->getApplication()->getKernel(); - if ($kernel instanceof ExtensionInterface - && ($kernel instanceof ConfigurationInterface || $kernel instanceof ConfigurationExtensionInterface) - && $kernel->getAlias() - ) { - $errorIo->table(['Kernel Extension'], [[$kernel->getAlias()]]); - } - - $errorIo->comment([ - 'Provide the name of a bundle as the first argument of this command to dump its default configuration. (e.g. <comment>config:dump-reference FrameworkBundle</comment>)', - 'For dumping a specific option, add its path as the second argument of this command. (e.g. <comment>config:dump-reference FrameworkBundle http_client.default_options</comment> to dump the <comment>framework.http_client.default_options</comment> configuration)', - ]); - - return 0; - } - - $extension = $this->findExtension($name); - - if ($extension instanceof ConfigurationInterface) { - $configuration = $extension; - } else { - $configuration = $extension->getConfiguration([], $this->getContainerBuilder($this->getApplication()->getKernel())); - } - - $this->validateConfiguration($extension, $configuration); - - $format = $input->getOption('format'); - - if ('yaml' === $format && !class_exists(Yaml::class)) { - $errorIo->error('Setting the "format" option to "yaml" requires the Symfony Yaml component. Try running "composer install symfony/yaml" or use "--format=xml" instead.'); - - return 1; - } - - $path = $input->getArgument('path'); - - if (null !== $path && 'yaml' !== $format) { - $errorIo->error('The "path" option is only available for the "yaml" format.'); - - return 1; - } - - if ($name === $extension->getAlias()) { - $message = sprintf('Default configuration for extension with alias: "%s"', $name); - } else { - $message = sprintf('Default configuration for "%s"', $name); - } - - if (null !== $path) { - $message .= sprintf(' at path "%s"', $path); - } - - switch ($format) { - case 'yaml': - $io->writeln(sprintf('# %s', $message)); - $dumper = new YamlReferenceDumper(); - break; - case 'xml': - $io->writeln(sprintf('<!-- %s -->', $message)); - $dumper = new XmlReferenceDumper(); - break; - default: - $io->writeln($message); - throw new InvalidArgumentException('Only the yaml and xml formats are supported.'); - } - - $io->writeln(null === $path ? $dumper->dump($configuration, $extension->getNamespace()) : $dumper->dumpAtPath($configuration, $path)); - - return 0; - } - - public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void - { - if ($input->mustSuggestArgumentValuesFor('name')) { - $suggestions->suggestValues($this->getAvailableBundles()); - } - - if ($input->mustSuggestOptionValuesFor('format')) { - $suggestions->suggestValues($this->getAvailableFormatOptions()); - } - } - - private function getAvailableBundles(): array - { - $bundles = []; - - foreach ($this->getApplication()->getKernel()->getBundles() as $bundle) { - $bundles[] = $bundle->getName(); - $bundles[] = $bundle->getContainerExtension()->getAlias(); - } - - return $bundles; - } - - private function getAvailableFormatOptions(): array - { - return ['yaml', 'xml']; - } -} diff --git a/lib/symfony/framework-bundle/Command/ContainerDebugCommand.php b/lib/symfony/framework-bundle/Command/ContainerDebugCommand.php deleted file mode 100644 index 8dfebe4ae..000000000 --- a/lib/symfony/framework-bundle/Command/ContainerDebugCommand.php +++ /dev/null @@ -1,313 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Completion\CompletionInput; -use Symfony\Component\Console\Completion\CompletionSuggestions; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; - -/** - * A console command for retrieving information about services. - * - * @author Ryan Weaver <ryan@thatsquality.com> - * - * @internal - */ -class ContainerDebugCommand extends Command -{ - use BuildDebugContainerTrait; - - protected static $defaultName = 'debug:container'; - protected static $defaultDescription = 'Display current services for an application'; - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('name', InputArgument::OPTIONAL, 'A service name (foo)'), - new InputOption('show-arguments', null, InputOption::VALUE_NONE, 'Show arguments in services'), - new InputOption('show-hidden', null, InputOption::VALUE_NONE, 'Show hidden (internal) services'), - new InputOption('tag', null, InputOption::VALUE_REQUIRED, 'Show all services with a specific tag'), - new InputOption('tags', null, InputOption::VALUE_NONE, 'Display tagged services for an application'), - new InputOption('parameter', null, InputOption::VALUE_REQUIRED, 'Display a specific parameter for an application'), - new InputOption('parameters', null, InputOption::VALUE_NONE, 'Display parameters for an application'), - new InputOption('types', null, InputOption::VALUE_NONE, 'Display types (classes/interfaces) available in the container'), - new InputOption('env-var', null, InputOption::VALUE_REQUIRED, 'Display a specific environment variable used in the container'), - new InputOption('env-vars', null, InputOption::VALUE_NONE, 'Display environment variables used in the container'), - 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 description'), - new InputOption('deprecations', null, InputOption::VALUE_NONE, 'Display deprecations generated when compiling and warming up the container'), - ]) - ->setDescription(self::$defaultDescription) - ->setHelp(<<<'EOF' -The <info>%command.name%</info> command displays all configured <comment>public</comment> services: - - <info>php %command.full_name%</info> - -To see deprecations generated during container compilation and cache warmup, use the <info>--deprecations</info> option: - - <info>php %command.full_name% --deprecations</info> - -To get specific information about a service, specify its name: - - <info>php %command.full_name% validator</info> - -To get specific information about a service including all its arguments, use the <info>--show-arguments</info> flag: - - <info>php %command.full_name% validator --show-arguments</info> - -To see available types that can be used for autowiring, use the <info>--types</info> flag: - - <info>php %command.full_name% --types</info> - -To see environment variables used by the container, use the <info>--env-vars</info> flag: - - <info>php %command.full_name% --env-vars</info> - -Display a specific environment variable by specifying its name with the <info>--env-var</info> option: - - <info>php %command.full_name% --env-var=APP_ENV</info> - -Use the --tags option to display tagged <comment>public</comment> services grouped by tag: - - <info>php %command.full_name% --tags</info> - -Find all services with a specific tag by specifying the tag name with the <info>--tag</info> option: - - <info>php %command.full_name% --tag=form.type</info> - -Use the <info>--parameters</info> option to display all parameters: - - <info>php %command.full_name% --parameters</info> - -Display a specific parameter by specifying its name with the <info>--parameter</info> option: - - <info>php %command.full_name% --parameter=kernel.debug</info> - -By default, internal services are hidden. You can display them -using the <info>--show-hidden</info> flag: - - <info>php %command.full_name% --show-hidden</info> - -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - $errorIo = $io->getErrorStyle(); - - $this->validateInput($input); - $kernel = $this->getApplication()->getKernel(); - $object = $this->getContainerBuilder($kernel); - - if ($input->getOption('env-vars')) { - $options = ['env-vars' => true]; - } elseif ($envVar = $input->getOption('env-var')) { - $options = ['env-vars' => true, 'name' => $envVar]; - } elseif ($input->getOption('types')) { - $options = []; - $options['filter'] = [$this, 'filterToServiceTypes']; - } elseif ($input->getOption('parameters')) { - $parameters = []; - foreach ($object->getParameterBag()->all() as $k => $v) { - $parameters[$k] = $object->resolveEnvPlaceholders($v); - } - $object = new ParameterBag($parameters); - $options = []; - } elseif ($parameter = $input->getOption('parameter')) { - $options = ['parameter' => $parameter]; - } elseif ($input->getOption('tags')) { - $options = ['group_by' => 'tags']; - } elseif ($tag = $input->getOption('tag')) { - $options = ['tag' => $tag]; - } elseif ($name = $input->getArgument('name')) { - $name = $this->findProperServiceName($input, $errorIo, $object, $name, $input->getOption('show-hidden')); - $options = ['id' => $name]; - } elseif ($input->getOption('deprecations')) { - $options = ['deprecations' => true]; - } else { - $options = []; - } - - $helper = new DescriptorHelper(); - $options['format'] = $input->getOption('format'); - $options['show_arguments'] = $input->getOption('show-arguments'); - $options['show_hidden'] = $input->getOption('show-hidden'); - $options['raw_text'] = $input->getOption('raw'); - $options['output'] = $io; - $options['is_debug'] = $kernel->isDebug(); - - try { - $helper->describe($io, $object, $options); - - if (isset($options['id']) && isset($kernel->getContainer()->getRemovedIds()[$options['id']])) { - $errorIo->note(sprintf('The "%s" service or alias has been removed or inlined when the container was compiled.', $options['id'])); - } - } catch (ServiceNotFoundException $e) { - if ('' !== $e->getId() && '@' === $e->getId()[0]) { - throw new ServiceNotFoundException($e->getId(), $e->getSourceId(), null, [substr($e->getId(), 1)]); - } - - throw $e; - } - - if (!$input->getArgument('name') && !$input->getOption('tag') && !$input->getOption('parameter') && !$input->getOption('env-vars') && !$input->getOption('env-var') && $input->isInteractive()) { - if ($input->getOption('tags')) { - $errorIo->comment('To search for a specific tag, re-run this command with a search term. (e.g. <comment>debug:container --tag=form.type</comment>)'); - } elseif ($input->getOption('parameters')) { - $errorIo->comment('To search for a specific parameter, re-run this command with a search term. (e.g. <comment>debug:container --parameter=kernel.debug</comment>)'); - } elseif (!$input->getOption('deprecations')) { - $errorIo->comment('To search for a specific service, re-run this command with a search term. (e.g. <comment>debug:container log</comment>)'); - } - } - - return 0; - } - - public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void - { - if ($input->mustSuggestOptionValuesFor('format')) { - $helper = new DescriptorHelper(); - $suggestions->suggestValues($helper->getFormats()); - - return; - } - - $kernel = $this->getApplication()->getKernel(); - $object = $this->getContainerBuilder($kernel); - - if ($input->mustSuggestArgumentValuesFor('name') - && !$input->getOption('tag') && !$input->getOption('tags') - && !$input->getOption('parameter') && !$input->getOption('parameters') - && !$input->getOption('env-var') && !$input->getOption('env-vars') - && !$input->getOption('types') && !$input->getOption('deprecations') - ) { - $suggestions->suggestValues($this->findServiceIdsContaining( - $object, - $input->getCompletionValue(), - (bool) $input->getOption('show-hidden') - )); - - return; - } - - if ($input->mustSuggestOptionValuesFor('tag')) { - $suggestions->suggestValues($object->findTags()); - - return; - } - - if ($input->mustSuggestOptionValuesFor('parameter')) { - $suggestions->suggestValues(array_keys($object->getParameterBag()->all())); - } - } - - /** - * Validates input arguments and options. - * - * @throws \InvalidArgumentException - */ - protected function validateInput(InputInterface $input) - { - $options = ['tags', 'tag', 'parameters', 'parameter']; - - $optionsCount = 0; - foreach ($options as $option) { - if ($input->getOption($option)) { - ++$optionsCount; - } - } - - $name = $input->getArgument('name'); - if ((null !== $name) && ($optionsCount > 0)) { - throw new InvalidArgumentException('The options tags, tag, parameters & parameter cannot be combined with the service name argument.'); - } elseif ((null === $name) && $optionsCount > 1) { - throw new InvalidArgumentException('The options tags, tag, parameters & parameter cannot be combined together.'); - } - } - - private function findProperServiceName(InputInterface $input, SymfonyStyle $io, ContainerBuilder $builder, string $name, bool $showHidden): string - { - $name = ltrim($name, '\\'); - - if ($builder->has($name) || !$input->isInteractive()) { - return $name; - } - - $matchingServices = $this->findServiceIdsContaining($builder, $name, $showHidden); - if (empty($matchingServices)) { - throw new InvalidArgumentException(sprintf('No services found that match "%s".', $name)); - } - - if (1 === \count($matchingServices)) { - return $matchingServices[0]; - } - - return $io->choice('Select one of the following services to display its information', $matchingServices); - } - - private function findServiceIdsContaining(ContainerBuilder $builder, string $name, bool $showHidden): array - { - $serviceIds = $builder->getServiceIds(); - $foundServiceIds = $foundServiceIdsIgnoringBackslashes = []; - foreach ($serviceIds as $serviceId) { - if (!$showHidden && str_starts_with($serviceId, '.')) { - continue; - } - if (false !== stripos(str_replace('\\', '', $serviceId), $name)) { - $foundServiceIdsIgnoringBackslashes[] = $serviceId; - } - if ('' === $name || false !== stripos($serviceId, $name)) { - $foundServiceIds[] = $serviceId; - } - } - - return $foundServiceIds ?: $foundServiceIdsIgnoringBackslashes; - } - - /** - * @internal - */ - public function filterToServiceTypes(string $serviceId): bool - { - // filter out things that could not be valid class names - if (!preg_match('/(?(DEFINE)(?<V>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+))^(?&V)(?:\\\\(?&V))*+(?: \$(?&V))?$/', $serviceId)) { - return false; - } - - // if the id has a \, assume it is a class - if (str_contains($serviceId, '\\')) { - return true; - } - - return class_exists($serviceId) || interface_exists($serviceId, false); - } -} diff --git a/lib/symfony/framework-bundle/Command/ContainerLintCommand.php b/lib/symfony/framework-bundle/Command/ContainerLintCommand.php deleted file mode 100644 index 337f1f420..000000000 --- a/lib/symfony/framework-bundle/Command/ContainerLintCommand.php +++ /dev/null @@ -1,134 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Config\ConfigCache; -use Symfony\Component\Config\FileLocator; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Exception\RuntimeException; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\DependencyInjection\Compiler\CheckTypeDeclarationsPass; -use Symfony\Component\DependencyInjection\Compiler\PassConfig; -use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; -use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; -use Symfony\Component\HttpKernel\Kernel; - -final class ContainerLintCommand extends Command -{ - protected static $defaultName = 'lint:container'; - protected static $defaultDescription = 'Ensure that arguments injected into services match type declarations'; - - /** - * @var ContainerBuilder - */ - private $containerBuilder; - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDescription(self::$defaultDescription) - ->setHelp('This command parses service definitions and ensures that injected values match the type declarations of each services\' class.') - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - $errorIo = $io->getErrorStyle(); - - try { - $container = $this->getContainerBuilder(); - } catch (RuntimeException $e) { - $errorIo->error($e->getMessage()); - - return 2; - } - - $container->setParameter('container.build_time', time()); - - try { - $container->compile(); - } catch (InvalidArgumentException $e) { - $errorIo->error($e->getMessage()); - - return 1; - } - - $io->success('The container was linted successfully: all services are injected with values that are compatible with their type declarations.'); - - return 0; - } - - private function getContainerBuilder(): ContainerBuilder - { - if ($this->containerBuilder) { - return $this->containerBuilder; - } - - $kernel = $this->getApplication()->getKernel(); - $kernelContainer = $kernel->getContainer(); - - if (!$kernel->isDebug() || !(new ConfigCache($kernelContainer->getParameter('debug.container.dump'), true))->isFresh()) { - if (!$kernel instanceof Kernel) { - throw new RuntimeException(sprintf('This command does not support the application kernel: "%s" does not extend "%s".', get_debug_type($kernel), Kernel::class)); - } - - $buildContainer = \Closure::bind(function (): ContainerBuilder { - $this->initializeBundles(); - - return $this->buildContainer(); - }, $kernel, \get_class($kernel)); - $container = $buildContainer(); - - $skippedIds = []; - } else { - if (!$kernelContainer instanceof Container) { - throw new RuntimeException(sprintf('This command does not support the application container: "%s" does not extend "%s".', get_debug_type($kernelContainer), Container::class)); - } - - (new XmlFileLoader($container = new ContainerBuilder($parameterBag = new EnvPlaceholderParameterBag()), new FileLocator()))->load($kernelContainer->getParameter('debug.container.dump')); - - $refl = new \ReflectionProperty($parameterBag, 'resolved'); - $refl->setAccessible(true); - $refl->setValue($parameterBag, true); - - $skippedIds = []; - foreach ($container->getServiceIds() as $serviceId) { - if (str_starts_with($serviceId, '.errored.')) { - $skippedIds[$serviceId] = true; - } - } - - $container->getCompilerPassConfig()->setBeforeOptimizationPasses([]); - $container->getCompilerPassConfig()->setOptimizationPasses([]); - $container->getCompilerPassConfig()->setBeforeRemovingPasses([]); - } - - $container->setParameter('container.build_hash', 'lint_container'); - $container->setParameter('container.build_id', 'lint_container'); - - $container->addCompilerPass(new CheckTypeDeclarationsPass(true, $skippedIds), PassConfig::TYPE_AFTER_REMOVING, -100); - - return $this->containerBuilder = $container; - } -} diff --git a/lib/symfony/framework-bundle/Command/DebugAutowiringCommand.php b/lib/symfony/framework-bundle/Command/DebugAutowiringCommand.php deleted file mode 100644 index e1e3c9534..000000000 --- a/lib/symfony/framework-bundle/Command/DebugAutowiringCommand.php +++ /dev/null @@ -1,177 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Bundle\FrameworkBundle\Console\Descriptor\Descriptor; -use Symfony\Component\Console\Completion\CompletionInput; -use Symfony\Component\Console\Completion\CompletionSuggestions; -use Symfony\Component\Console\Formatter\OutputFormatterStyle; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; - -/** - * A console command for autowiring information. - * - * @author Ryan Weaver <ryan@knpuniversity.com> - * - * @internal - */ -class DebugAutowiringCommand extends ContainerDebugCommand -{ - protected static $defaultName = 'debug:autowiring'; - protected static $defaultDescription = 'List classes/interfaces you can use for autowiring'; - - private $supportsHref; - private $fileLinkFormatter; - - public function __construct(string $name = null, FileLinkFormatter $fileLinkFormatter = null) - { - $this->supportsHref = method_exists(OutputFormatterStyle::class, 'setHref'); - $this->fileLinkFormatter = $fileLinkFormatter; - parent::__construct($name); - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('search', InputArgument::OPTIONAL, 'A search filter'), - new InputOption('all', null, InputOption::VALUE_NONE, 'Show also services that are not aliased'), - ]) - ->setDescription(self::$defaultDescription) - ->setHelp(<<<'EOF' -The <info>%command.name%</info> command displays the classes and interfaces that -you can use as type-hints for autowiring: - - <info>php %command.full_name%</info> - -You can also pass a search term to filter the list: - - <info>php %command.full_name% log</info> - -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - $errorIo = $io->getErrorStyle(); - - $builder = $this->getContainerBuilder($this->getApplication()->getKernel()); - $serviceIds = $builder->getServiceIds(); - $serviceIds = array_filter($serviceIds, [$this, 'filterToServiceTypes']); - - if ($search = $input->getArgument('search')) { - $searchNormalized = preg_replace('/[^a-zA-Z0-9\x7f-\xff $]++/', '', $search); - - $serviceIds = array_filter($serviceIds, function ($serviceId) use ($searchNormalized) { - return false !== stripos(str_replace('\\', '', $serviceId), $searchNormalized) && !str_starts_with($serviceId, '.'); - }); - - if (empty($serviceIds)) { - $errorIo->error(sprintf('No autowirable classes or interfaces found matching "%s"', $search)); - - return 1; - } - } - - uasort($serviceIds, 'strnatcmp'); - - $io->title('Autowirable Types'); - $io->text('The following classes & interfaces can be used as type-hints when autowiring:'); - if ($search) { - $io->text(sprintf('(only showing classes/interfaces matching <comment>%s</comment>)', $search)); - } - $hasAlias = []; - $all = $input->getOption('all'); - $previousId = '-'; - $serviceIdsNb = 0; - foreach ($serviceIds as $serviceId) { - $text = []; - $resolvedServiceId = $serviceId; - if (!str_starts_with($serviceId, $previousId)) { - $text[] = ''; - if ('' !== $description = Descriptor::getClassDescription($serviceId, $resolvedServiceId)) { - if (isset($hasAlias[$serviceId])) { - continue; - } - $text[] = $description; - } - $previousId = $serviceId.' $'; - } - - $serviceLine = sprintf('<fg=yellow>%s</>', $serviceId); - if ($this->supportsHref && '' !== $fileLink = $this->getFileLink($serviceId)) { - $serviceLine = sprintf('<fg=yellow;href=%s>%s</>', $fileLink, $serviceId); - } - - if ($builder->hasAlias($serviceId)) { - $hasAlias[$serviceId] = true; - $serviceAlias = $builder->getAlias($serviceId); - $serviceLine .= ' <fg=cyan>('.$serviceAlias.')</>'; - - if ($serviceAlias->isDeprecated()) { - $serviceLine .= ' - <fg=magenta>deprecated</>'; - } - } elseif (!$all) { - ++$serviceIdsNb; - continue; - } - $text[] = $serviceLine; - $io->text($text); - } - - $io->newLine(); - - if (0 < $serviceIdsNb) { - $io->text(sprintf('%s more concrete service%s would be displayed when adding the "--all" option.', $serviceIdsNb, $serviceIdsNb > 1 ? 's' : '')); - } - if ($all) { - $io->text('Pro-tip: use interfaces in your type-hints instead of classes to benefit from the dependency inversion principle.'); - } - - $io->newLine(); - - return 0; - } - - private function getFileLink(string $class): string - { - if (null === $this->fileLinkFormatter - || (null === $r = $this->getContainerBuilder($this->getApplication()->getKernel())->getReflectionClass($class, false))) { - return ''; - } - - return (string) $this->fileLinkFormatter->format($r->getFileName(), $r->getStartLine()); - } - - public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void - { - if ($input->mustSuggestArgumentValuesFor('search')) { - $builder = $this->getContainerBuilder($this->getApplication()->getKernel()); - - $suggestions->suggestValues(array_filter($builder->getServiceIds(), [$this, 'filterToServiceTypes'])); - } - } -} diff --git a/lib/symfony/framework-bundle/Command/EventDispatcherDebugCommand.php b/lib/symfony/framework-bundle/Command/EventDispatcherDebugCommand.php deleted file mode 100644 index cfc9ae2fb..000000000 --- a/lib/symfony/framework-bundle/Command/EventDispatcherDebugCommand.php +++ /dev/null @@ -1,164 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Psr\Container\ContainerInterface; -use Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Completion\CompletionInput; -use Symfony\Component\Console\Completion\CompletionSuggestions; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Contracts\Service\ServiceProviderInterface; - -/** - * A console command for retrieving information about event dispatcher. - * - * @author Matthieu Auger <mail@matthieuauger.com> - * - * @final - */ -class EventDispatcherDebugCommand extends Command -{ - private const DEFAULT_DISPATCHER = 'event_dispatcher'; - - protected static $defaultName = 'debug:event-dispatcher'; - protected static $defaultDescription = 'Display configured listeners for an application'; - private $dispatchers; - - public function __construct(ContainerInterface $dispatchers) - { - parent::__construct(); - - $this->dispatchers = $dispatchers; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('event', InputArgument::OPTIONAL, 'An event name or a part of the event name'), - new InputOption('dispatcher', null, InputOption::VALUE_REQUIRED, 'To view events of a specific event dispatcher', self::DEFAULT_DISPATCHER), - 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 description'), - ]) - ->setDescription(self::$defaultDescription) - ->setHelp(<<<'EOF' -The <info>%command.name%</info> command displays all configured listeners: - - <info>php %command.full_name%</info> - -To get specific listeners for an event, specify its name: - - <info>php %command.full_name% kernel.request</info> -EOF - ) - ; - } - - /** - * {@inheritdoc} - * - * @throws \LogicException - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - - $options = []; - $dispatcherServiceName = $input->getOption('dispatcher'); - if (!$this->dispatchers->has($dispatcherServiceName)) { - $io->getErrorStyle()->error(sprintf('Event dispatcher "%s" is not available.', $dispatcherServiceName)); - - return 1; - } - - $dispatcher = $this->dispatchers->get($dispatcherServiceName); - - if ($event = $input->getArgument('event')) { - if ($dispatcher->hasListeners($event)) { - $options = ['event' => $event]; - } else { - // if there is no direct match, try find partial matches - $events = $this->searchForEvent($dispatcher, $event); - if (0 === \count($events)) { - $io->getErrorStyle()->warning(sprintf('The event "%s" does not have any registered listeners.', $event)); - - return 0; - } elseif (1 === \count($events)) { - $options = ['event' => $events[array_key_first($events)]]; - } else { - $options = ['events' => $events]; - } - } - } - - $helper = new DescriptorHelper(); - - if (self::DEFAULT_DISPATCHER !== $dispatcherServiceName) { - $options['dispatcher_service_name'] = $dispatcherServiceName; - } - - $options['format'] = $input->getOption('format'); - $options['raw_text'] = $input->getOption('raw'); - $options['output'] = $io; - $helper->describe($io, $dispatcher, $options); - - return 0; - } - - public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void - { - if ($input->mustSuggestArgumentValuesFor('event')) { - $dispatcherServiceName = $input->getOption('dispatcher'); - if ($this->dispatchers->has($dispatcherServiceName)) { - $dispatcher = $this->dispatchers->get($dispatcherServiceName); - $suggestions->suggestValues(array_keys($dispatcher->getListeners())); - } - - return; - } - - if ($input->mustSuggestOptionValuesFor('dispatcher')) { - if ($this->dispatchers instanceof ServiceProviderInterface) { - $suggestions->suggestValues(array_keys($this->dispatchers->getProvidedServices())); - } - - return; - } - - if ($input->mustSuggestOptionValuesFor('format')) { - $suggestions->suggestValues((new DescriptorHelper())->getFormats()); - } - } - - private function searchForEvent(EventDispatcherInterface $dispatcher, string $needle): array - { - $output = []; - $lcNeedle = strtolower($needle); - $allEvents = array_keys($dispatcher->getListeners()); - foreach ($allEvents as $event) { - if (str_contains(strtolower($event), $lcNeedle)) { - $output[] = $event; - } - } - - return $output; - } -} diff --git a/lib/symfony/framework-bundle/Command/RouterDebugCommand.php b/lib/symfony/framework-bundle/Command/RouterDebugCommand.php deleted file mode 100644 index cf929f987..000000000 --- a/lib/symfony/framework-bundle/Command/RouterDebugCommand.php +++ /dev/null @@ -1,176 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Completion\CompletionInput; -use Symfony\Component\Console\Completion\CompletionSuggestions; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\RouterInterface; - -/** - * A console command for retrieving information about routes. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Tobias Schultze <http://tobion.de> - * - * @final - */ -class RouterDebugCommand extends Command -{ - use BuildDebugContainerTrait; - - protected static $defaultName = 'debug:router'; - protected static $defaultDescription = 'Display current routes for an application'; - private $router; - private $fileLinkFormatter; - - public function __construct(RouterInterface $router, FileLinkFormatter $fileLinkFormatter = null) - { - parent::__construct(); - - $this->router = $router; - $this->fileLinkFormatter = $fileLinkFormatter; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('name', InputArgument::OPTIONAL, 'A route name'), - new InputOption('show-controllers', null, InputOption::VALUE_NONE, 'Show assigned controllers in overview'), - 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 route(s)'), - ]) - ->setDescription(self::$defaultDescription) - ->setHelp(<<<'EOF' -The <info>%command.name%</info> displays the configured routes: - - <info>php %command.full_name%</info> - -EOF - ) - ; - } - - /** - * {@inheritdoc} - * - * @throws InvalidArgumentException When route does not exist - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - $name = $input->getArgument('name'); - $helper = new DescriptorHelper($this->fileLinkFormatter); - $routes = $this->router->getRouteCollection(); - $container = null; - if ($this->fileLinkFormatter) { - $container = function () { - return $this->getContainerBuilder($this->getApplication()->getKernel()); - }; - } - - if ($name) { - $route = $routes->get($name); - $matchingRoutes = $this->findRouteNameContaining($name, $routes); - - if (!$input->isInteractive() && !$route && \count($matchingRoutes) > 1) { - $helper->describe($io, $this->findRouteContaining($name, $routes), [ - 'format' => $input->getOption('format'), - 'raw_text' => $input->getOption('raw'), - 'show_controllers' => $input->getOption('show-controllers'), - 'output' => $io, - ]); - - return 0; - } - - if (!$route && $matchingRoutes) { - $default = 1 === \count($matchingRoutes) ? $matchingRoutes[0] : null; - $name = $io->choice('Select one of the matching routes', $matchingRoutes, $default); - $route = $routes->get($name); - } - - if (!$route) { - throw new InvalidArgumentException(sprintf('The route "%s" does not exist.', $name)); - } - - $helper->describe($io, $route, [ - 'format' => $input->getOption('format'), - 'raw_text' => $input->getOption('raw'), - 'name' => $name, - 'output' => $io, - 'container' => $container, - ]); - } else { - $helper->describe($io, $routes, [ - 'format' => $input->getOption('format'), - 'raw_text' => $input->getOption('raw'), - 'show_controllers' => $input->getOption('show-controllers'), - 'output' => $io, - 'container' => $container, - ]); - } - - return 0; - } - - private function findRouteNameContaining(string $name, RouteCollection $routes): array - { - $foundRoutesNames = []; - foreach ($routes as $routeName => $route) { - if (false !== stripos($routeName, $name)) { - $foundRoutesNames[] = $routeName; - } - } - - return $foundRoutesNames; - } - - public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void - { - if ($input->mustSuggestArgumentValuesFor('name')) { - $suggestions->suggestValues(array_keys($this->router->getRouteCollection()->all())); - - return; - } - - if ($input->mustSuggestOptionValuesFor('format')) { - $helper = new DescriptorHelper(); - $suggestions->suggestValues($helper->getFormats()); - } - } - - private function findRouteContaining(string $name, RouteCollection $routes): RouteCollection - { - $foundRoutes = new RouteCollection(); - foreach ($routes as $routeName => $route) { - if (false !== stripos($routeName, $name)) { - $foundRoutes->add($routeName, $route); - } - } - - return $foundRoutes; - } -} diff --git a/lib/symfony/framework-bundle/Command/RouterMatchCommand.php b/lib/symfony/framework-bundle/Command/RouterMatchCommand.php deleted file mode 100644 index 6cceb945d..000000000 --- a/lib/symfony/framework-bundle/Command/RouterMatchCommand.php +++ /dev/null @@ -1,129 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; -use Symfony\Component\Routing\Matcher\TraceableUrlMatcher; -use Symfony\Component\Routing\RouterInterface; - -/** - * A console command to test route matching. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class RouterMatchCommand extends Command -{ - protected static $defaultName = 'router:match'; - protected static $defaultDescription = 'Help debug routes by simulating a path info match'; - - private $router; - private $expressionLanguageProviders; - - /** - * @param iterable<mixed, ExpressionFunctionProviderInterface> $expressionLanguageProviders - */ - public function __construct(RouterInterface $router, iterable $expressionLanguageProviders = []) - { - parent::__construct(); - - $this->router = $router; - $this->expressionLanguageProviders = $expressionLanguageProviders; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('path_info', InputArgument::REQUIRED, 'A path info'), - new InputOption('method', null, InputOption::VALUE_REQUIRED, 'Set the HTTP method'), - new InputOption('scheme', null, InputOption::VALUE_REQUIRED, 'Set the URI scheme (usually http or https)'), - new InputOption('host', null, InputOption::VALUE_REQUIRED, 'Set the URI host'), - ]) - ->setDescription(self::$defaultDescription) - ->setHelp(<<<'EOF' -The <info>%command.name%</info> shows which routes match a given request and which don't and for what reason: - - <info>php %command.full_name% /foo</info> - -or - - <info>php %command.full_name% /foo --method POST --scheme https --host symfony.com --verbose</info> - -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - - $context = $this->router->getContext(); - if (null !== $method = $input->getOption('method')) { - $context->setMethod($method); - } - if (null !== $scheme = $input->getOption('scheme')) { - $context->setScheme($scheme); - } - if (null !== $host = $input->getOption('host')) { - $context->setHost($host); - } - - $matcher = new TraceableUrlMatcher($this->router->getRouteCollection(), $context); - foreach ($this->expressionLanguageProviders as $provider) { - $matcher->addExpressionLanguageProvider($provider); - } - - $traces = $matcher->getTraces($input->getArgument('path_info')); - - $io->newLine(); - - $matches = false; - foreach ($traces as $trace) { - if (TraceableUrlMatcher::ROUTE_ALMOST_MATCHES == $trace['level']) { - $io->text(sprintf('Route <info>"%s"</> almost matches but %s', $trace['name'], lcfirst($trace['log']))); - } elseif (TraceableUrlMatcher::ROUTE_MATCHES == $trace['level']) { - $io->success(sprintf('Route "%s" matches', $trace['name'])); - - $routerDebugCommand = $this->getApplication()->find('debug:router'); - $routerDebugCommand->run(new ArrayInput(['name' => $trace['name']]), $output); - - $matches = true; - } elseif ($input->getOption('verbose')) { - $io->text(sprintf('Route "%s" does not match: %s', $trace['name'], $trace['log'])); - } - } - - if (!$matches) { - $io->error(sprintf('None of the routes match the path "%s"', $input->getArgument('path_info'))); - - return 1; - } - - return 0; - } -} diff --git a/lib/symfony/framework-bundle/Command/SecretsDecryptToLocalCommand.php b/lib/symfony/framework-bundle/Command/SecretsDecryptToLocalCommand.php deleted file mode 100644 index 0e07d88fa..000000000 --- a/lib/symfony/framework-bundle/Command/SecretsDecryptToLocalCommand.php +++ /dev/null @@ -1,104 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -final class SecretsDecryptToLocalCommand extends Command -{ - protected static $defaultName = 'secrets:decrypt-to-local'; - protected static $defaultDescription = 'Decrypt all secrets and stores them in the local vault'; - - private $vault; - private $localVault; - - public function __construct(AbstractVault $vault, AbstractVault $localVault = null) - { - $this->vault = $vault; - $this->localVault = $localVault; - - parent::__construct(); - } - - protected function configure() - { - $this - ->setDescription(self::$defaultDescription) - ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force overriding of secrets that already exist in the local vault') - ->setHelp(<<<'EOF' -The <info>%command.name%</info> command decrypts all secrets and copies them in the local vault. - - <info>%command.full_name%</info> - -When the option <info>--force</info> is provided, secrets that already exist in the local vault are overriden. - - <info>%command.full_name% --force</info> -EOF - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output); - - if (null === $this->localVault) { - $io->error('The local vault is disabled.'); - - return 1; - } - - $secrets = $this->vault->list(true); - - $io->comment(sprintf('%d secret%s found in the vault.', \count($secrets), 1 !== \count($secrets) ? 's' : '')); - - $skipped = 0; - if (!$input->getOption('force')) { - foreach ($this->localVault->list() as $k => $v) { - if (isset($secrets[$k])) { - ++$skipped; - unset($secrets[$k]); - } - } - } - - if ($skipped > 0) { - $io->warning([ - sprintf('%d secret%s already overridden in the local vault and will be skipped.', $skipped, 1 !== $skipped ? 's are' : ' is'), - 'Use the --force flag to override these.', - ]); - } - - foreach ($secrets as $k => $v) { - if (null === $v) { - $io->error($this->vault->getLastMessage() ?? sprintf('Secret "%s" has been skipped as there was an error reading it.', $k)); - continue; - } - - $this->localVault->seal($k, $v); - $io->note($this->localVault->getLastMessage()); - } - - return 0; - } -} diff --git a/lib/symfony/framework-bundle/Command/SecretsEncryptFromLocalCommand.php b/lib/symfony/framework-bundle/Command/SecretsEncryptFromLocalCommand.php deleted file mode 100644 index 79f51c51a..000000000 --- a/lib/symfony/framework-bundle/Command/SecretsEncryptFromLocalCommand.php +++ /dev/null @@ -1,79 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -final class SecretsEncryptFromLocalCommand extends Command -{ - protected static $defaultName = 'secrets:encrypt-from-local'; - protected static $defaultDescription = 'Encrypt all local secrets to the vault'; - - private $vault; - private $localVault; - - public function __construct(AbstractVault $vault, AbstractVault $localVault = null) - { - $this->vault = $vault; - $this->localVault = $localVault; - - parent::__construct(); - } - - protected function configure() - { - $this - ->setDescription(self::$defaultDescription) - ->setHelp(<<<'EOF' -The <info>%command.name%</info> command encrypts all locally overridden secrets to the vault. - - <info>%command.full_name%</info> -EOF - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output); - - if (null === $this->localVault) { - $io->error('The local vault is disabled.'); - - return 1; - } - - foreach ($this->vault->list(true) as $name => $value) { - $localValue = $this->localVault->reveal($name); - - if (null !== $localValue && $value !== $localValue) { - $this->vault->seal($name, $localValue); - } elseif (null !== $message = $this->localVault->getLastMessage()) { - $io->error($message); - - return 1; - } - } - - return 0; - } -} diff --git a/lib/symfony/framework-bundle/Command/SecretsGenerateKeysCommand.php b/lib/symfony/framework-bundle/Command/SecretsGenerateKeysCommand.php deleted file mode 100644 index a9440b4c8..000000000 --- a/lib/symfony/framework-bundle/Command/SecretsGenerateKeysCommand.php +++ /dev/null @@ -1,126 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * @author Tobias Schultze <http://tobion.de> - * @author Jérémy Derussé <jeremy@derusse.com> - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -final class SecretsGenerateKeysCommand extends Command -{ - protected static $defaultName = 'secrets:generate-keys'; - protected static $defaultDescription = 'Generate new encryption keys'; - - private $vault; - private $localVault; - - public function __construct(AbstractVault $vault, AbstractVault $localVault = null) - { - $this->vault = $vault; - $this->localVault = $localVault; - - parent::__construct(); - } - - protected function configure() - { - $this - ->setDescription(self::$defaultDescription) - ->addOption('local', 'l', InputOption::VALUE_NONE, 'Update the local vault.') - ->addOption('rotate', 'r', InputOption::VALUE_NONE, 'Re-encrypt existing secrets with the newly generated keys.') - ->setHelp(<<<'EOF' -The <info>%command.name%</info> command generates a new encryption key. - - <info>%command.full_name%</info> - -If encryption keys already exist, the command must be called with -the <info>--rotate</info> option in order to override those keys and re-encrypt -existing secrets. - - <info>%command.full_name% --rotate</info> -EOF - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output); - $vault = $input->getOption('local') ? $this->localVault : $this->vault; - - if (null === $vault) { - $io->success('The local vault is disabled.'); - - return 1; - } - - if (!$input->getOption('rotate')) { - if ($vault->generateKeys()) { - $io->success($vault->getLastMessage()); - - if ($this->vault === $vault) { - $io->caution('DO NOT COMMIT THE DECRYPTION KEY FOR THE PROD ENVIRONMENT⚠️'); - } - - return 0; - } - - $io->warning($vault->getLastMessage()); - - return 1; - } - - $secrets = []; - foreach ($vault->list(true) as $name => $value) { - if (null === $value) { - $io->error($vault->getLastMessage()); - - return 1; - } - - $secrets[$name] = $value; - } - - if (!$vault->generateKeys(true)) { - $io->warning($vault->getLastMessage()); - - return 1; - } - - $io->success($vault->getLastMessage()); - - if ($secrets) { - foreach ($secrets as $name => $value) { - $vault->seal($name, $value); - } - - $io->comment('Existing secrets have been rotated to the new keys.'); - } - - if ($this->vault === $vault) { - $io->caution('DO NOT COMMIT THE DECRYPTION KEY FOR THE PROD ENVIRONMENT⚠️'); - } - - return 0; - } -} diff --git a/lib/symfony/framework-bundle/Command/SecretsListCommand.php b/lib/symfony/framework-bundle/Command/SecretsListCommand.php deleted file mode 100644 index 0b13e0cf2..000000000 --- a/lib/symfony/framework-bundle/Command/SecretsListCommand.php +++ /dev/null @@ -1,109 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Helper\Dumper; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * @author Tobias Schultze <http://tobion.de> - * @author Jérémy Derussé <jeremy@derusse.com> - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -final class SecretsListCommand extends Command -{ - protected static $defaultName = 'secrets:list'; - protected static $defaultDescription = 'List all secrets'; - - private $vault; - private $localVault; - - public function __construct(AbstractVault $vault, AbstractVault $localVault = null) - { - $this->vault = $vault; - $this->localVault = $localVault; - - parent::__construct(); - } - - protected function configure() - { - $this - ->setDescription(self::$defaultDescription) - ->addOption('reveal', 'r', InputOption::VALUE_NONE, 'Display decrypted values alongside names') - ->setHelp(<<<'EOF' -The <info>%command.name%</info> command list all stored secrets. - - <info>%command.full_name%</info> - -When the option <info>--reveal</info> is provided, the decrypted secrets are also displayed. - - <info>%command.full_name% --reveal</info> -EOF - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output); - - $io->comment('Use <info>"%env(<name>)%"</info> to reference a secret in a config file.'); - - if (!$reveal = $input->getOption('reveal')) { - $io->comment(sprintf('To reveal the secrets run <info>php %s %s --reveal</info>', $_SERVER['PHP_SELF'], $this->getName())); - } - - $secrets = $this->vault->list($reveal); - $localSecrets = null !== $this->localVault ? $this->localVault->list($reveal) : null; - - $rows = []; - - $dump = new Dumper($output); - $dump = static function (?string $v) use ($dump) { - return null === $v ? '******' : $dump($v); - }; - - foreach ($secrets as $name => $value) { - $rows[$name] = [$name, $dump($value)]; - } - - if (null !== $message = $this->vault->getLastMessage()) { - $io->comment($message); - } - - foreach ($localSecrets ?? [] as $name => $value) { - if (isset($rows[$name])) { - $rows[$name][] = $dump($value); - } - } - - if (null !== $this->localVault && null !== $message = $this->localVault->getLastMessage()) { - $io->comment($message); - } - - (new SymfonyStyle($input, $output)) - ->table(['Secret', 'Value'] + (null !== $localSecrets ? [2 => 'Local Value'] : []), $rows); - - $io->comment("Local values override secret values.\nUse <info>secrets:set --local</info> to define them."); - - return 0; - } -} diff --git a/lib/symfony/framework-bundle/Command/SecretsRemoveCommand.php b/lib/symfony/framework-bundle/Command/SecretsRemoveCommand.php deleted file mode 100644 index 0451ef300..000000000 --- a/lib/symfony/framework-bundle/Command/SecretsRemoveCommand.php +++ /dev/null @@ -1,102 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Completion\CompletionInput; -use Symfony\Component\Console\Completion\CompletionSuggestions; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * @author Jérémy Derussé <jeremy@derusse.com> - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -final class SecretsRemoveCommand extends Command -{ - protected static $defaultName = 'secrets:remove'; - protected static $defaultDescription = 'Remove a secret from the vault'; - - private $vault; - private $localVault; - - public function __construct(AbstractVault $vault, AbstractVault $localVault = null) - { - $this->vault = $vault; - $this->localVault = $localVault; - - parent::__construct(); - } - - protected function configure() - { - $this - ->setDescription(self::$defaultDescription) - ->addArgument('name', InputArgument::REQUIRED, 'The name of the secret') - ->addOption('local', 'l', InputOption::VALUE_NONE, 'Update the local vault.') - ->setHelp(<<<'EOF' -The <info>%command.name%</info> command removes a secret from the vault. - - <info>%command.full_name% <name></info> -EOF - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output); - $vault = $input->getOption('local') ? $this->localVault : $this->vault; - - if (null === $vault) { - $io->success('The local vault is disabled.'); - - return 1; - } - - if ($vault->remove($name = $input->getArgument('name'))) { - $io->success($vault->getLastMessage() ?? 'Secret was removed from the vault.'); - } else { - $io->comment($vault->getLastMessage() ?? 'Secret was not found in the vault.'); - } - - if ($this->vault === $vault && null !== $this->localVault->reveal($name)) { - $io->comment('Note that this secret is overridden in the local vault.'); - } - - return 0; - } - - public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void - { - if (!$input->mustSuggestArgumentValuesFor('name')) { - return; - } - - $vaultKeys = array_keys($this->vault->list(false)); - if ($input->getOption('local')) { - if (null === $this->localVault) { - return; - } - $vaultKeys = array_intersect($vaultKeys, array_keys($this->localVault->list(false))); - } - - $suggestions->suggestValues($vaultKeys); - } -} diff --git a/lib/symfony/framework-bundle/Command/SecretsSetCommand.php b/lib/symfony/framework-bundle/Command/SecretsSetCommand.php deleted file mode 100644 index 412247da7..000000000 --- a/lib/symfony/framework-bundle/Command/SecretsSetCommand.php +++ /dev/null @@ -1,149 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Completion\CompletionInput; -use Symfony\Component\Console\Completion\CompletionSuggestions; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * @author Tobias Schultze <http://tobion.de> - * @author Jérémy Derussé <jeremy@derusse.com> - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -final class SecretsSetCommand extends Command -{ - protected static $defaultName = 'secrets:set'; - protected static $defaultDescription = 'Set a secret in the vault'; - - private $vault; - private $localVault; - - public function __construct(AbstractVault $vault, AbstractVault $localVault = null) - { - $this->vault = $vault; - $this->localVault = $localVault; - - parent::__construct(); - } - - protected function configure() - { - $this - ->setDescription(self::$defaultDescription) - ->addArgument('name', InputArgument::REQUIRED, 'The name of the secret') - ->addArgument('file', InputArgument::OPTIONAL, 'A file where to read the secret from or "-" for reading from STDIN') - ->addOption('local', 'l', InputOption::VALUE_NONE, 'Update the local vault.') - ->addOption('random', 'r', InputOption::VALUE_OPTIONAL, 'Generate a random value.', false) - ->setHelp(<<<'EOF' -The <info>%command.name%</info> command stores a secret in the vault. - - <info>%command.full_name% <name></info> - -To reference secrets in services.yaml or any other config -files, use <info>"%env(<name>)%"</info>. - -By default, the secret value should be entered interactively. -Alternatively, provide a file where to read the secret from: - - <info>php %command.full_name% <name> filename</info> - -Use "-" as a file name to read from STDIN: - - <info>cat filename | php %command.full_name% <name> -</info> - -Use <info>--local</info> to override secrets for local needs. -EOF - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $errOutput = $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output; - $io = new SymfonyStyle($input, $errOutput); - $name = $input->getArgument('name'); - $vault = $input->getOption('local') ? $this->localVault : $this->vault; - - if (null === $vault) { - $io->error('The local vault is disabled.'); - - return 1; - } - - if ($this->localVault === $vault && !\array_key_exists($name, $this->vault->list())) { - $io->error(sprintf('Secret "%s" does not exist in the vault, you cannot override it locally.', $name)); - - return 1; - } - - if (0 < $random = $input->getOption('random') ?? 16) { - $value = strtr(substr(base64_encode(random_bytes($random)), 0, $random), '+/', '-_'); - } elseif (!$file = $input->getArgument('file')) { - $value = $io->askHidden('Please type the secret value'); - - if (null === $value) { - $io->warning('No value provided: using empty string'); - $value = ''; - } - } elseif ('-' === $file) { - $value = file_get_contents('php://stdin'); - } elseif (is_file($file) && is_readable($file)) { - $value = file_get_contents($file); - } elseif (!is_file($file)) { - throw new \InvalidArgumentException(sprintf('File not found: "%s".', $file)); - } elseif (!is_readable($file)) { - throw new \InvalidArgumentException(sprintf('File is not readable: "%s".', $file)); - } - - if ($vault->generateKeys()) { - $io->success($vault->getLastMessage()); - - if ($this->vault === $vault) { - $io->caution('DO NOT COMMIT THE DECRYPTION KEY FOR THE PROD ENVIRONMENT⚠️'); - } - } - - $vault->seal($name, $value); - - $io->success($vault->getLastMessage() ?? 'Secret was successfully stored in the vault.'); - - if (0 < $random) { - $errOutput->write(' // The generated random value is: <comment>'); - $output->write($value); - $errOutput->writeln('</comment>'); - $io->newLine(); - } - - if ($this->vault === $vault && null !== $this->localVault->reveal($name)) { - $io->comment('Note that this secret is overridden in the local vault.'); - } - - return 0; - } - - public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void - { - if ($input->mustSuggestArgumentValuesFor('name')) { - $suggestions->suggestValues(array_keys($this->vault->list(false))); - } - } -} diff --git a/lib/symfony/framework-bundle/Command/TranslationDebugCommand.php b/lib/symfony/framework-bundle/Command/TranslationDebugCommand.php deleted file mode 100644 index 006fd2505..000000000 --- a/lib/symfony/framework-bundle/Command/TranslationDebugCommand.php +++ /dev/null @@ -1,418 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Completion\CompletionInput; -use Symfony\Component\Console\Completion\CompletionSuggestions; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\HttpKernel\KernelInterface; -use Symfony\Component\Translation\Catalogue\MergeOperation; -use Symfony\Component\Translation\DataCollectorTranslator; -use Symfony\Component\Translation\Extractor\ExtractorInterface; -use Symfony\Component\Translation\LoggingTranslator; -use Symfony\Component\Translation\MessageCatalogue; -use Symfony\Component\Translation\Reader\TranslationReaderInterface; -use Symfony\Component\Translation\Translator; -use Symfony\Contracts\Translation\TranslatorInterface; - -/** - * Helps finding unused or missing translation messages in a given locale - * and comparing them with the fallback ones. - * - * @author Florian Voutzinos <florian@voutzinos.com> - * - * @final - */ -class TranslationDebugCommand extends Command -{ - public const EXIT_CODE_GENERAL_ERROR = 64; - public const EXIT_CODE_MISSING = 65; - public const EXIT_CODE_UNUSED = 66; - public const EXIT_CODE_FALLBACK = 68; - public const MESSAGE_MISSING = 0; - public const MESSAGE_UNUSED = 1; - public const MESSAGE_EQUALS_FALLBACK = 2; - - protected static $defaultName = 'debug:translation'; - protected static $defaultDescription = 'Display translation messages information'; - - private $translator; - private $reader; - private $extractor; - private $defaultTransPath; - private $defaultViewsPath; - private $transPaths; - private $codePaths; - private $enabledLocales; - - public function __construct(TranslatorInterface $translator, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultTransPath = null, string $defaultViewsPath = null, array $transPaths = [], array $codePaths = [], array $enabledLocales = []) - { - parent::__construct(); - - $this->translator = $translator; - $this->reader = $reader; - $this->extractor = $extractor; - $this->defaultTransPath = $defaultTransPath; - $this->defaultViewsPath = $defaultViewsPath; - $this->transPaths = $transPaths; - $this->codePaths = $codePaths; - $this->enabledLocales = $enabledLocales; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('locale', InputArgument::REQUIRED, 'The locale'), - new InputArgument('bundle', InputArgument::OPTIONAL, 'The bundle name or directory where to load the messages'), - new InputOption('domain', null, InputOption::VALUE_OPTIONAL, 'The messages domain'), - new InputOption('only-missing', null, InputOption::VALUE_NONE, 'Display only missing messages'), - new InputOption('only-unused', null, InputOption::VALUE_NONE, 'Display only unused messages'), - new InputOption('all', null, InputOption::VALUE_NONE, 'Load messages from all registered bundles'), - ]) - ->setDescription(self::$defaultDescription) - ->setHelp(<<<'EOF' -The <info>%command.name%</info> command helps finding unused or missing translation -messages and comparing them with the fallback ones by inspecting the -templates and translation files of a given bundle or the default translations directory. - -You can display information about bundle translations in a specific locale: - - <info>php %command.full_name% en AcmeDemoBundle</info> - -You can also specify a translation domain for the search: - - <info>php %command.full_name% --domain=messages en AcmeDemoBundle</info> - -You can only display missing messages: - - <info>php %command.full_name% --only-missing en AcmeDemoBundle</info> - -You can only display unused messages: - - <info>php %command.full_name% --only-unused en AcmeDemoBundle</info> - -You can display information about application translations in a specific locale: - - <info>php %command.full_name% en</info> - -You can display information about translations in all registered bundles in a specific locale: - - <info>php %command.full_name% --all en</info> - -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - - $locale = $input->getArgument('locale'); - $domain = $input->getOption('domain'); - - $exitCode = self::SUCCESS; - - /** @var KernelInterface $kernel */ - $kernel = $this->getApplication()->getKernel(); - - // Define Root Paths - $transPaths = $this->getRootTransPaths(); - $codePaths = $this->getRootCodePaths($kernel); - - // Override with provided Bundle info - if (null !== $input->getArgument('bundle')) { - try { - $bundle = $kernel->getBundle($input->getArgument('bundle')); - $bundleDir = $bundle->getPath(); - $transPaths = [is_dir($bundleDir.'/Resources/translations') ? $bundleDir.'/Resources/translations' : $bundleDir.'/translations']; - $codePaths = [is_dir($bundleDir.'/Resources/views') ? $bundleDir.'/Resources/views' : $bundleDir.'/templates']; - if ($this->defaultTransPath) { - $transPaths[] = $this->defaultTransPath; - } - if ($this->defaultViewsPath) { - $codePaths[] = $this->defaultViewsPath; - } - } catch (\InvalidArgumentException $e) { - // such a bundle does not exist, so treat the argument as path - $path = $input->getArgument('bundle'); - - $transPaths = [$path.'/translations']; - $codePaths = [$path.'/templates']; - - if (!is_dir($transPaths[0])) { - throw new InvalidArgumentException(sprintf('"%s" is neither an enabled bundle nor a directory.', $transPaths[0])); - } - } - } elseif ($input->getOption('all')) { - foreach ($kernel->getBundles() as $bundle) { - $bundleDir = $bundle->getPath(); - $transPaths[] = is_dir($bundleDir.'/Resources/translations') ? $bundleDir.'/Resources/translations' : $bundle->getPath().'/translations'; - $codePaths[] = is_dir($bundleDir.'/Resources/views') ? $bundleDir.'/Resources/views' : $bundle->getPath().'/templates'; - } - } - - // Extract used messages - $extractedCatalogue = $this->extractMessages($locale, $codePaths); - - // Load defined messages - $currentCatalogue = $this->loadCurrentMessages($locale, $transPaths); - - // Merge defined and extracted messages to get all message ids - $mergeOperation = new MergeOperation($extractedCatalogue, $currentCatalogue); - $allMessages = $mergeOperation->getResult()->all($domain); - if (null !== $domain) { - $allMessages = [$domain => $allMessages]; - } - - // No defined or extracted messages - if (empty($allMessages) || null !== $domain && empty($allMessages[$domain])) { - $outputMessage = sprintf('No defined or extracted messages for locale "%s"', $locale); - - if (null !== $domain) { - $outputMessage .= sprintf(' and domain "%s"', $domain); - } - - $io->getErrorStyle()->warning($outputMessage); - - return self::EXIT_CODE_GENERAL_ERROR; - } - - // Load the fallback catalogues - $fallbackCatalogues = $this->loadFallbackCatalogues($locale, $transPaths); - - // Display header line - $headers = ['State', 'Domain', 'Id', sprintf('Message Preview (%s)', $locale)]; - foreach ($fallbackCatalogues as $fallbackCatalogue) { - $headers[] = sprintf('Fallback Message Preview (%s)', $fallbackCatalogue->getLocale()); - } - $rows = []; - // Iterate all message ids and determine their state - foreach ($allMessages as $domain => $messages) { - foreach (array_keys($messages) as $messageId) { - $value = $currentCatalogue->get($messageId, $domain); - $states = []; - - if ($extractedCatalogue->defines($messageId, $domain)) { - if (!$currentCatalogue->defines($messageId, $domain)) { - $states[] = self::MESSAGE_MISSING; - - if (!$input->getOption('only-unused')) { - $exitCode = $exitCode | self::EXIT_CODE_MISSING; - } - } - } elseif ($currentCatalogue->defines($messageId, $domain)) { - $states[] = self::MESSAGE_UNUSED; - - if (!$input->getOption('only-missing')) { - $exitCode = $exitCode | self::EXIT_CODE_UNUSED; - } - } - - if (!\in_array(self::MESSAGE_UNUSED, $states) && $input->getOption('only-unused') - || !\in_array(self::MESSAGE_MISSING, $states) && $input->getOption('only-missing') - ) { - continue; - } - - foreach ($fallbackCatalogues as $fallbackCatalogue) { - if ($fallbackCatalogue->defines($messageId, $domain) && $value === $fallbackCatalogue->get($messageId, $domain)) { - $states[] = self::MESSAGE_EQUALS_FALLBACK; - - $exitCode = $exitCode | self::EXIT_CODE_FALLBACK; - - break; - } - } - - $row = [$this->formatStates($states), $domain, $this->formatId($messageId), $this->sanitizeString($value)]; - foreach ($fallbackCatalogues as $fallbackCatalogue) { - $row[] = $this->sanitizeString($fallbackCatalogue->get($messageId, $domain)); - } - - $rows[] = $row; - } - } - - $io->table($headers, $rows); - - return $exitCode; - } - - public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void - { - if ($input->mustSuggestArgumentValuesFor('locale')) { - $suggestions->suggestValues($this->enabledLocales); - - return; - } - - /** @var KernelInterface $kernel */ - $kernel = $this->getApplication()->getKernel(); - - if ($input->mustSuggestArgumentValuesFor('bundle')) { - $availableBundles = []; - foreach ($kernel->getBundles() as $bundle) { - $availableBundles[] = $bundle->getName(); - - if ($extension = $bundle->getContainerExtension()) { - $availableBundles[] = $extension->getAlias(); - } - } - - $suggestions->suggestValues($availableBundles); - - return; - } - - if ($input->mustSuggestOptionValuesFor('domain')) { - $locale = $input->getArgument('locale'); - - $mergeOperation = new MergeOperation( - $this->extractMessages($locale, $this->getRootCodePaths($kernel)), - $this->loadCurrentMessages($locale, $this->getRootTransPaths()) - ); - - $suggestions->suggestValues($mergeOperation->getDomains()); - } - } - - private function formatState(int $state): string - { - if (self::MESSAGE_MISSING === $state) { - return '<error> missing </error>'; - } - - if (self::MESSAGE_UNUSED === $state) { - return '<comment> unused </comment>'; - } - - if (self::MESSAGE_EQUALS_FALLBACK === $state) { - return '<info> fallback </info>'; - } - - return $state; - } - - private function formatStates(array $states): string - { - $result = []; - foreach ($states as $state) { - $result[] = $this->formatState($state); - } - - return implode(' ', $result); - } - - private function formatId(string $id): string - { - return sprintf('<fg=cyan;options=bold>%s</>', $id); - } - - private function sanitizeString(string $string, int $length = 40): string - { - $string = trim(preg_replace('/\s+/', ' ', $string)); - - if (false !== $encoding = mb_detect_encoding($string, null, true)) { - if (mb_strlen($string, $encoding) > $length) { - return mb_substr($string, 0, $length - 3, $encoding).'...'; - } - } elseif (\strlen($string) > $length) { - return substr($string, 0, $length - 3).'...'; - } - - return $string; - } - - private function extractMessages(string $locale, array $transPaths): MessageCatalogue - { - $extractedCatalogue = new MessageCatalogue($locale); - foreach ($transPaths as $path) { - if (is_dir($path) || is_file($path)) { - $this->extractor->extract($path, $extractedCatalogue); - } - } - - return $extractedCatalogue; - } - - private function loadCurrentMessages(string $locale, array $transPaths): MessageCatalogue - { - $currentCatalogue = new MessageCatalogue($locale); - foreach ($transPaths as $path) { - if (is_dir($path)) { - $this->reader->read($path, $currentCatalogue); - } - } - - return $currentCatalogue; - } - - /** - * @return MessageCatalogue[] - */ - private function loadFallbackCatalogues(string $locale, array $transPaths): array - { - $fallbackCatalogues = []; - if ($this->translator instanceof Translator || $this->translator instanceof DataCollectorTranslator || $this->translator instanceof LoggingTranslator) { - foreach ($this->translator->getFallbackLocales() as $fallbackLocale) { - if ($fallbackLocale === $locale) { - continue; - } - - $fallbackCatalogue = new MessageCatalogue($fallbackLocale); - foreach ($transPaths as $path) { - if (is_dir($path)) { - $this->reader->read($path, $fallbackCatalogue); - } - } - $fallbackCatalogues[] = $fallbackCatalogue; - } - } - - return $fallbackCatalogues; - } - - private function getRootTransPaths(): array - { - $transPaths = $this->transPaths; - if ($this->defaultTransPath) { - $transPaths[] = $this->defaultTransPath; - } - - return $transPaths; - } - - private function getRootCodePaths(KernelInterface $kernel): array - { - $codePaths = $this->codePaths; - $codePaths[] = $kernel->getProjectDir().'/src'; - if ($this->defaultViewsPath) { - $codePaths[] = $this->defaultViewsPath; - } - - return $codePaths; - } -} diff --git a/lib/symfony/framework-bundle/Command/TranslationUpdateCommand.php b/lib/symfony/framework-bundle/Command/TranslationUpdateCommand.php deleted file mode 100644 index f0e1dc887..000000000 --- a/lib/symfony/framework-bundle/Command/TranslationUpdateCommand.php +++ /dev/null @@ -1,473 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Completion\CompletionInput; -use Symfony\Component\Console\Completion\CompletionSuggestions; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\HttpKernel\KernelInterface; -use Symfony\Component\Translation\Catalogue\MergeOperation; -use Symfony\Component\Translation\Catalogue\TargetOperation; -use Symfony\Component\Translation\Extractor\ExtractorInterface; -use Symfony\Component\Translation\MessageCatalogue; -use Symfony\Component\Translation\MessageCatalogueInterface; -use Symfony\Component\Translation\Reader\TranslationReaderInterface; -use Symfony\Component\Translation\Writer\TranslationWriterInterface; - -/** - * A command that parses templates to extract translation messages and adds them - * into the translation files. - * - * @author Michel Salib <michelsalib@hotmail.com> - * - * @final - */ -class TranslationUpdateCommand extends Command -{ - private const ASC = 'asc'; - private const DESC = 'desc'; - private const SORT_ORDERS = [self::ASC, self::DESC]; - private const FORMATS = [ - 'xlf12' => ['xlf', '1.2'], - 'xlf20' => ['xlf', '2.0'], - ]; - - protected static $defaultName = 'translation:extract|translation:update'; - protected static $defaultDescription = 'Extract missing translations keys from code to translation files.'; - - private $writer; - private $reader; - private $extractor; - private $defaultLocale; - private $defaultTransPath; - private $defaultViewsPath; - private $transPaths; - private $codePaths; - private $enabledLocales; - - public function __construct(TranslationWriterInterface $writer, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultLocale, string $defaultTransPath = null, string $defaultViewsPath = null, array $transPaths = [], array $codePaths = [], array $enabledLocales = []) - { - parent::__construct(); - - $this->writer = $writer; - $this->reader = $reader; - $this->extractor = $extractor; - $this->defaultLocale = $defaultLocale; - $this->defaultTransPath = $defaultTransPath; - $this->defaultViewsPath = $defaultViewsPath; - $this->transPaths = $transPaths; - $this->codePaths = $codePaths; - $this->enabledLocales = $enabledLocales; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('locale', InputArgument::REQUIRED, 'The locale'), - new InputArgument('bundle', InputArgument::OPTIONAL, 'The bundle name or directory where to load the messages'), - new InputOption('prefix', null, InputOption::VALUE_OPTIONAL, 'Override the default prefix', '__'), - new InputOption('output-format', null, InputOption::VALUE_OPTIONAL, 'Override the default output format (deprecated)'), - new InputOption('format', null, InputOption::VALUE_OPTIONAL, 'Override the default output format', 'xlf12'), - new InputOption('dump-messages', null, InputOption::VALUE_NONE, 'Should the messages be dumped in the console'), - new InputOption('force', null, InputOption::VALUE_NONE, 'Should the extract be done'), - new InputOption('clean', null, InputOption::VALUE_NONE, 'Should clean not found messages'), - new InputOption('domain', null, InputOption::VALUE_OPTIONAL, 'Specify the domain to extract'), - new InputOption('xliff-version', null, InputOption::VALUE_OPTIONAL, 'Override the default xliff version (deprecated)'), - new InputOption('sort', null, InputOption::VALUE_OPTIONAL, 'Return list of messages sorted alphabetically', 'asc'), - new InputOption('as-tree', null, InputOption::VALUE_OPTIONAL, 'Dump the messages as a tree-like structure: The given value defines the level where to switch to inline YAML'), - ]) - ->setDescription(self::$defaultDescription) - ->setHelp(<<<'EOF' -The <info>%command.name%</info> command extracts translation strings from templates -of a given bundle or the default translations directory. It can display them or merge -the new ones into the translation files. - -When new translation strings are found it can automatically add a prefix to the translation -message. - -Example running against a Bundle (AcmeBundle) - - <info>php %command.full_name% --dump-messages en AcmeBundle</info> - <info>php %command.full_name% --force --prefix="new_" fr AcmeBundle</info> - -Example running against default messages directory - - <info>php %command.full_name% --dump-messages en</info> - <info>php %command.full_name% --force --prefix="new_" fr</info> - -You can sort the output with the <comment>--sort</> flag: - - <info>php %command.full_name% --dump-messages --sort=asc en AcmeBundle</info> - <info>php %command.full_name% --dump-messages --sort=desc fr</info> - -You can dump a tree-like structure using the yaml format with <comment>--as-tree</> flag: - - <info>php %command.full_name% --force --format=yaml --as-tree=3 en AcmeBundle</info> - <info>php %command.full_name% --force --format=yaml --sort=asc --as-tree=3 fr</info> - -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - $errorIo = $output instanceof ConsoleOutputInterface ? new SymfonyStyle($input, $output->getErrorOutput()) : $io; - - if ('translation:update' === $input->getFirstArgument()) { - $errorIo->caution('Command "translation:update" is deprecated since version 5.4 and will be removed in Symfony 6.0. Use "translation:extract" instead.'); - } - - $io = new SymfonyStyle($input, $output); - $errorIo = $io->getErrorStyle(); - - // check presence of force or dump-message - if (true !== $input->getOption('force') && true !== $input->getOption('dump-messages')) { - $errorIo->error('You must choose one of --force or --dump-messages'); - - return 1; - } - - $format = $input->getOption('output-format') ?: $input->getOption('format'); - $xliffVersion = $input->getOption('xliff-version') ?? '1.2'; - - if ($input->getOption('xliff-version')) { - $errorIo->warning(sprintf('The "--xliff-version" option is deprecated since version 5.3, use "--format=xlf%d" instead.', 10 * $xliffVersion)); - } - - if ($input->getOption('output-format')) { - $errorIo->warning(sprintf('The "--output-format" option is deprecated since version 5.3, use "--format=xlf%d" instead.', 10 * $xliffVersion)); - } - - if (\in_array($format, array_keys(self::FORMATS), true)) { - [$format, $xliffVersion] = self::FORMATS[$format]; - } - - // check format - $supportedFormats = $this->writer->getFormats(); - if (!\in_array($format, $supportedFormats, true)) { - $errorIo->error(['Wrong output format', 'Supported formats are: '.implode(', ', $supportedFormats).', xlf12 and xlf20.']); - - return 1; - } - - /** @var KernelInterface $kernel */ - $kernel = $this->getApplication()->getKernel(); - - // Define Root Paths - $transPaths = $this->getRootTransPaths(); - $codePaths = $this->getRootCodePaths($kernel); - - $currentName = 'default directory'; - - // Override with provided Bundle info - if (null !== $input->getArgument('bundle')) { - try { - $foundBundle = $kernel->getBundle($input->getArgument('bundle')); - $bundleDir = $foundBundle->getPath(); - $transPaths = [is_dir($bundleDir.'/Resources/translations') ? $bundleDir.'/Resources/translations' : $bundleDir.'/translations']; - $codePaths = [is_dir($bundleDir.'/Resources/views') ? $bundleDir.'/Resources/views' : $bundleDir.'/templates']; - if ($this->defaultTransPath) { - $transPaths[] = $this->defaultTransPath; - } - if ($this->defaultViewsPath) { - $codePaths[] = $this->defaultViewsPath; - } - $currentName = $foundBundle->getName(); - } catch (\InvalidArgumentException $e) { - // such a bundle does not exist, so treat the argument as path - $path = $input->getArgument('bundle'); - - $transPaths = [$path.'/translations']; - $codePaths = [$path.'/templates']; - - if (!is_dir($transPaths[0])) { - throw new InvalidArgumentException(sprintf('"%s" is neither an enabled bundle nor a directory.', $transPaths[0])); - } - } - } - - $io->title('Translation Messages Extractor and Dumper'); - $io->comment(sprintf('Generating "<info>%s</info>" translation files for "<info>%s</info>"', $input->getArgument('locale'), $currentName)); - - $io->comment('Parsing templates...'); - $extractedCatalogue = $this->extractMessages($input->getArgument('locale'), $codePaths, $input->getOption('prefix')); - - $io->comment('Loading translation files...'); - $currentCatalogue = $this->loadCurrentMessages($input->getArgument('locale'), $transPaths); - - if (null !== $domain = $input->getOption('domain')) { - $currentCatalogue = $this->filterCatalogue($currentCatalogue, $domain); - $extractedCatalogue = $this->filterCatalogue($extractedCatalogue, $domain); - } - - // process catalogues - $operation = $input->getOption('clean') - ? new TargetOperation($currentCatalogue, $extractedCatalogue) - : new MergeOperation($currentCatalogue, $extractedCatalogue); - - // Exit if no messages found. - if (!\count($operation->getDomains())) { - $errorIo->warning('No translation messages were found.'); - - return 0; - } - - $resultMessage = 'Translation files were successfully updated'; - - $operation->moveMessagesToIntlDomainsIfPossible('new'); - - // show compiled list of messages - if (true === $input->getOption('dump-messages')) { - $extractedMessagesCount = 0; - $io->newLine(); - foreach ($operation->getDomains() as $domain) { - $newKeys = array_keys($operation->getNewMessages($domain)); - $allKeys = array_keys($operation->getMessages($domain)); - - $list = array_merge( - array_diff($allKeys, $newKeys), - array_map(function ($id) { - return sprintf('<fg=green>%s</>', $id); - }, $newKeys), - array_map(function ($id) { - return sprintf('<fg=red>%s</>', $id); - }, array_keys($operation->getObsoleteMessages($domain))) - ); - - $domainMessagesCount = \count($list); - - if ($sort = $input->getOption('sort')) { - $sort = strtolower($sort); - if (!\in_array($sort, self::SORT_ORDERS, true)) { - $errorIo->error(['Wrong sort order', 'Supported formats are: '.implode(', ', self::SORT_ORDERS).'.']); - - return 1; - } - - if (self::DESC === $sort) { - rsort($list); - } else { - sort($list); - } - } - - $io->section(sprintf('Messages extracted for domain "<info>%s</info>" (%d message%s)', $domain, $domainMessagesCount, $domainMessagesCount > 1 ? 's' : '')); - $io->listing($list); - - $extractedMessagesCount += $domainMessagesCount; - } - - if ('xlf' === $format) { - $io->comment(sprintf('Xliff output version is <info>%s</info>', $xliffVersion)); - } - - $resultMessage = sprintf('%d message%s successfully extracted', $extractedMessagesCount, $extractedMessagesCount > 1 ? 's were' : ' was'); - } - - // save the files - if (true === $input->getOption('force')) { - $io->comment('Writing files...'); - - $bundleTransPath = false; - foreach ($transPaths as $path) { - if (is_dir($path)) { - $bundleTransPath = $path; - } - } - - if (!$bundleTransPath) { - $bundleTransPath = end($transPaths); - } - - $this->writer->write($operation->getResult(), $format, ['path' => $bundleTransPath, 'default_locale' => $this->defaultLocale, 'xliff_version' => $xliffVersion, 'as_tree' => $input->getOption('as-tree'), 'inline' => $input->getOption('as-tree') ?? 0]); - - if (true === $input->getOption('dump-messages')) { - $resultMessage .= ' and translation files were updated'; - } - } - - $io->success($resultMessage.'.'); - - return 0; - } - - public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void - { - if ($input->mustSuggestArgumentValuesFor('locale')) { - $suggestions->suggestValues($this->enabledLocales); - - return; - } - - /** @var KernelInterface $kernel */ - $kernel = $this->getApplication()->getKernel(); - if ($input->mustSuggestArgumentValuesFor('bundle')) { - $bundles = []; - - foreach ($kernel->getBundles() as $bundle) { - $bundles[] = $bundle->getName(); - if ($bundle->getContainerExtension()) { - $bundles[] = $bundle->getContainerExtension()->getAlias(); - } - } - - $suggestions->suggestValues($bundles); - - return; - } - - if ($input->mustSuggestOptionValuesFor('format')) { - $suggestions->suggestValues(array_merge( - $this->writer->getFormats(), - array_keys(self::FORMATS) - )); - - return; - } - - if ($input->mustSuggestOptionValuesFor('domain') && $locale = $input->getArgument('locale')) { - $extractedCatalogue = $this->extractMessages($locale, $this->getRootCodePaths($kernel), $input->getOption('prefix')); - - $currentCatalogue = $this->loadCurrentMessages($locale, $this->getRootTransPaths()); - - // process catalogues - $operation = $input->getOption('clean') - ? new TargetOperation($currentCatalogue, $extractedCatalogue) - : new MergeOperation($currentCatalogue, $extractedCatalogue); - - $suggestions->suggestValues($operation->getDomains()); - - return; - } - - if ($input->mustSuggestOptionValuesFor('sort')) { - $suggestions->suggestValues(self::SORT_ORDERS); - } - } - - private function filterCatalogue(MessageCatalogue $catalogue, string $domain): MessageCatalogue - { - $filteredCatalogue = new MessageCatalogue($catalogue->getLocale()); - - // extract intl-icu messages only - $intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX; - if ($intlMessages = $catalogue->all($intlDomain)) { - $filteredCatalogue->add($intlMessages, $intlDomain); - } - - // extract all messages and subtract intl-icu messages - if ($messages = array_diff($catalogue->all($domain), $intlMessages)) { - $filteredCatalogue->add($messages, $domain); - } - foreach ($catalogue->getResources() as $resource) { - $filteredCatalogue->addResource($resource); - } - - if ($metadata = $catalogue->getMetadata('', $intlDomain)) { - foreach ($metadata as $k => $v) { - $filteredCatalogue->setMetadata($k, $v, $intlDomain); - } - } - - if ($metadata = $catalogue->getMetadata('', $domain)) { - foreach ($metadata as $k => $v) { - $filteredCatalogue->setMetadata($k, $v, $domain); - } - } - - return $filteredCatalogue; - } - - private function extractMessages(string $locale, array $transPaths, string $prefix): MessageCatalogue - { - $extractedCatalogue = new MessageCatalogue($locale); - $this->extractor->setPrefix($prefix); - $transPaths = $this->filterDuplicateTransPaths($transPaths); - foreach ($transPaths as $path) { - if (is_dir($path) || is_file($path)) { - $this->extractor->extract($path, $extractedCatalogue); - } - } - - return $extractedCatalogue; - } - - private function filterDuplicateTransPaths(array $transPaths): array - { - $transPaths = array_filter(array_map('realpath', $transPaths)); - - sort($transPaths); - - $filteredPaths = []; - - foreach ($transPaths as $path) { - foreach ($filteredPaths as $filteredPath) { - if (str_starts_with($path, $filteredPath.\DIRECTORY_SEPARATOR)) { - continue 2; - } - } - - $filteredPaths[] = $path; - } - - return $filteredPaths; - } - - private function loadCurrentMessages(string $locale, array $transPaths): MessageCatalogue - { - $currentCatalogue = new MessageCatalogue($locale); - foreach ($transPaths as $path) { - if (is_dir($path)) { - $this->reader->read($path, $currentCatalogue); - } - } - - return $currentCatalogue; - } - - private function getRootTransPaths(): array - { - $transPaths = $this->transPaths; - if ($this->defaultTransPath) { - $transPaths[] = $this->defaultTransPath; - } - - return $transPaths; - } - - private function getRootCodePaths(KernelInterface $kernel): array - { - $codePaths = $this->codePaths; - $codePaths[] = $kernel->getProjectDir().'/src'; - if ($this->defaultViewsPath) { - $codePaths[] = $this->defaultViewsPath; - } - - return $codePaths; - } -} diff --git a/lib/symfony/framework-bundle/Command/WorkflowDumpCommand.php b/lib/symfony/framework-bundle/Command/WorkflowDumpCommand.php deleted file mode 100644 index 89d29b981..000000000 --- a/lib/symfony/framework-bundle/Command/WorkflowDumpCommand.php +++ /dev/null @@ -1,148 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Completion\CompletionInput; -use Symfony\Component\Console\Completion\CompletionSuggestions; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Workflow\Definition; -use Symfony\Component\Workflow\Dumper\GraphvizDumper; -use Symfony\Component\Workflow\Dumper\MermaidDumper; -use Symfony\Component\Workflow\Dumper\PlantUmlDumper; -use Symfony\Component\Workflow\Dumper\StateMachineGraphvizDumper; -use Symfony\Component\Workflow\Marking; - -/** - * @author Grégoire Pineau <lyrixx@lyrixx.info> - * - * @final - */ -class WorkflowDumpCommand extends Command -{ - protected static $defaultName = 'workflow:dump'; - protected static $defaultDescription = 'Dump a workflow'; - /** - * string is the service id. - * - * @var array<string, Definition> - */ - private $workflows = []; - - private const DUMP_FORMAT_OPTIONS = [ - 'puml', - 'mermaid', - 'dot', - ]; - - public function __construct(array $workflows) - { - parent::__construct(); - - $this->workflows = $workflows; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('name', InputArgument::REQUIRED, 'A workflow name'), - new InputArgument('marking', InputArgument::IS_ARRAY, 'A marking (a list of places)'), - new InputOption('label', 'l', InputOption::VALUE_REQUIRED, 'Label a graph'), - new InputOption('dump-format', null, InputOption::VALUE_REQUIRED, 'The dump format ['.implode('|', self::DUMP_FORMAT_OPTIONS).']', 'dot'), - ]) - ->setDescription(self::$defaultDescription) - ->setHelp(<<<'EOF' -The <info>%command.name%</info> command dumps the graphical representation of a -workflow in different formats - -<info>DOT</info>: %command.full_name% <workflow name> | dot -Tpng > workflow.png -<info>PUML</info>: %command.full_name% <workflow name> --dump-format=puml | java -jar plantuml.jar -p > workflow.png -<info>MERMAID</info>: %command.full_name% <workflow name> --dump-format=mermaid | mmdc -o workflow.svg -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $workflowName = $input->getArgument('name'); - - $workflow = null; - - if (isset($this->workflows['workflow.'.$workflowName])) { - $workflow = $this->workflows['workflow.'.$workflowName]; - $type = 'workflow'; - } elseif (isset($this->workflows['state_machine.'.$workflowName])) { - $workflow = $this->workflows['state_machine.'.$workflowName]; - $type = 'state_machine'; - } - - if (null === $workflow) { - throw new InvalidArgumentException(sprintf('No service found for "workflow.%1$s" nor "state_machine.%1$s".', $workflowName)); - } - - switch ($input->getOption('dump-format')) { - case 'puml': - $transitionType = 'workflow' === $type ? PlantUmlDumper::WORKFLOW_TRANSITION : PlantUmlDumper::STATEMACHINE_TRANSITION; - $dumper = new PlantUmlDumper($transitionType); - break; - - case 'mermaid': - $transitionType = 'workflow' === $type ? MermaidDumper::TRANSITION_TYPE_WORKFLOW : MermaidDumper::TRANSITION_TYPE_STATEMACHINE; - $dumper = new MermaidDumper($transitionType); - break; - - case 'dot': - default: - $dumper = ('workflow' === $type) ? new GraphvizDumper() : new StateMachineGraphvizDumper(); - } - - $marking = new Marking(); - - foreach ($input->getArgument('marking') as $place) { - $marking->mark($place); - } - - $options = [ - 'name' => $workflowName, - 'nofooter' => true, - 'graph' => [ - 'label' => $input->getOption('label'), - ], - ]; - $output->writeln($dumper->dump($workflow, $marking, $options)); - - return 0; - } - - public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void - { - if ($input->mustSuggestArgumentValuesFor('name')) { - $suggestions->suggestValues(array_keys($this->workflows)); - } - - if ($input->mustSuggestOptionValuesFor('dump-format')) { - $suggestions->suggestValues(self::DUMP_FORMAT_OPTIONS); - } - } -} diff --git a/lib/symfony/framework-bundle/Command/XliffLintCommand.php b/lib/symfony/framework-bundle/Command/XliffLintCommand.php deleted file mode 100644 index b1f631739..000000000 --- a/lib/symfony/framework-bundle/Command/XliffLintCommand.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Translation\Command\XliffLintCommand as BaseLintCommand; - -/** - * Validates XLIFF files syntax and outputs encountered errors. - * - * @author Grégoire Pineau <lyrixx@lyrixx.info> - * @author Robin Chalas <robin.chalas@gmail.com> - * @author Javier Eguiluz <javier.eguiluz@gmail.com> - * - * @final - */ -class XliffLintCommand extends BaseLintCommand -{ - protected static $defaultName = 'lint:xliff'; - protected static $defaultDescription = 'Lints an XLIFF file and outputs encountered errors'; - - public function __construct() - { - $directoryIteratorProvider = function ($directory, $default) { - if (!is_dir($directory)) { - $directory = $this->getApplication()->getKernel()->locateResource($directory); - } - - return $default($directory); - }; - - $isReadableProvider = function ($fileOrDirectory, $default) { - return str_starts_with($fileOrDirectory, '@') || $default($fileOrDirectory); - }; - - parent::__construct(null, $directoryIteratorProvider, $isReadableProvider); - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - parent::configure(); - - $this->setHelp($this->getHelp().<<<'EOF' - -Or find all files in a bundle: - - <info>php %command.full_name% @AcmeDemoBundle</info> - -EOF - ); - } -} diff --git a/lib/symfony/framework-bundle/Command/YamlLintCommand.php b/lib/symfony/framework-bundle/Command/YamlLintCommand.php deleted file mode 100644 index 3a432f275..000000000 --- a/lib/symfony/framework-bundle/Command/YamlLintCommand.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Yaml\Command\LintCommand as BaseLintCommand; - -/** - * Validates YAML files syntax and outputs encountered errors. - * - * @author Grégoire Pineau <lyrixx@lyrixx.info> - * @author Robin Chalas <robin.chalas@gmail.com> - * - * @final - */ -class YamlLintCommand extends BaseLintCommand -{ - protected static $defaultName = 'lint:yaml'; - protected static $defaultDescription = 'Lint a YAML file and outputs encountered errors'; - - public function __construct() - { - $directoryIteratorProvider = function ($directory, $default) { - if (!is_dir($directory)) { - $directory = $this->getApplication()->getKernel()->locateResource($directory); - } - - return $default($directory); - }; - - $isReadableProvider = function ($fileOrDirectory, $default) { - return str_starts_with($fileOrDirectory, '@') || $default($fileOrDirectory); - }; - - parent::__construct(null, $directoryIteratorProvider, $isReadableProvider); - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - parent::configure(); - - $this->setHelp($this->getHelp().<<<'EOF' - -Or find all files in a bundle: - - <info>php %command.full_name% @AcmeDemoBundle</info> - -EOF - ); - } -} diff --git a/lib/symfony/framework-bundle/Console/Application.php b/lib/symfony/framework-bundle/Console/Application.php deleted file mode 100644 index 55510b9d5..000000000 --- a/lib/symfony/framework-bundle/Console/Application.php +++ /dev/null @@ -1,212 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Console; - -use Symfony\Component\Console\Application as BaseApplication; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Command\ListCommand; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\HttpKernel\Bundle\Bundle; -use Symfony\Component\HttpKernel\Kernel; -use Symfony\Component\HttpKernel\KernelInterface; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -class Application extends BaseApplication -{ - private $kernel; - private $commandsRegistered = false; - private $registrationErrors = []; - - public function __construct(KernelInterface $kernel) - { - $this->kernel = $kernel; - - parent::__construct('Symfony', Kernel::VERSION); - - $inputDefinition = $this->getDefinition(); - $inputDefinition->addOption(new InputOption('--env', '-e', InputOption::VALUE_REQUIRED, 'The Environment name.', $kernel->getEnvironment())); - $inputDefinition->addOption(new InputOption('--no-debug', null, InputOption::VALUE_NONE, 'Switch off debug mode.')); - } - - /** - * Gets the Kernel associated with this Console. - * - * @return KernelInterface - */ - public function getKernel() - { - return $this->kernel; - } - - /** - * {@inheritdoc} - */ - public function reset() - { - if ($this->kernel->getContainer()->has('services_resetter')) { - $this->kernel->getContainer()->get('services_resetter')->reset(); - } - } - - /** - * Runs the current application. - * - * @return int 0 if everything went fine, or an error code - */ - public function doRun(InputInterface $input, OutputInterface $output) - { - $this->registerCommands(); - - if ($this->registrationErrors) { - $this->renderRegistrationErrors($input, $output); - } - - $this->setDispatcher($this->kernel->getContainer()->get('event_dispatcher')); - - return parent::doRun($input, $output); - } - - /** - * {@inheritdoc} - */ - protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output) - { - if (!$command instanceof ListCommand) { - if ($this->registrationErrors) { - $this->renderRegistrationErrors($input, $output); - $this->registrationErrors = []; - } - - return parent::doRunCommand($command, $input, $output); - } - - $returnCode = parent::doRunCommand($command, $input, $output); - - if ($this->registrationErrors) { - $this->renderRegistrationErrors($input, $output); - $this->registrationErrors = []; - } - - return $returnCode; - } - - /** - * {@inheritdoc} - */ - public function find(string $name) - { - $this->registerCommands(); - - return parent::find($name); - } - - /** - * {@inheritdoc} - */ - public function get(string $name) - { - $this->registerCommands(); - - $command = parent::get($name); - - if ($command instanceof ContainerAwareInterface) { - $command->setContainer($this->kernel->getContainer()); - } - - return $command; - } - - /** - * {@inheritdoc} - */ - public function all(string $namespace = null) - { - $this->registerCommands(); - - return parent::all($namespace); - } - - /** - * {@inheritdoc} - */ - public function getLongVersion() - { - return parent::getLongVersion().sprintf(' (env: <comment>%s</>, debug: <comment>%s</>) <bg=#0057B7;fg=#FFDD00>#StandWith</><bg=#FFDD00;fg=#0057B7>Ukraine</> <href=https://sf.to/ukraine>https://sf.to/ukraine</>', $this->kernel->getEnvironment(), $this->kernel->isDebug() ? 'true' : 'false'); - } - - public function add(Command $command) - { - $this->registerCommands(); - - return parent::add($command); - } - - protected function registerCommands() - { - if ($this->commandsRegistered) { - return; - } - - $this->commandsRegistered = true; - - $this->kernel->boot(); - - $container = $this->kernel->getContainer(); - - foreach ($this->kernel->getBundles() as $bundle) { - if ($bundle instanceof Bundle) { - try { - $bundle->registerCommands($this); - } catch (\Throwable $e) { - $this->registrationErrors[] = $e; - } - } - } - - if ($container->has('console.command_loader')) { - $this->setCommandLoader($container->get('console.command_loader')); - } - - if ($container->hasParameter('console.command.ids')) { - $lazyCommandIds = $container->hasParameter('console.lazy_command.ids') ? $container->getParameter('console.lazy_command.ids') : []; - foreach ($container->getParameter('console.command.ids') as $id) { - if (!isset($lazyCommandIds[$id])) { - try { - $this->add($container->get($id)); - } catch (\Throwable $e) { - $this->registrationErrors[] = $e; - } - } - } - } - } - - private function renderRegistrationErrors(InputInterface $input, OutputInterface $output) - { - if ($output instanceof ConsoleOutputInterface) { - $output = $output->getErrorOutput(); - } - - (new SymfonyStyle($input, $output))->warning('Some commands could not be registered:'); - - foreach ($this->registrationErrors as $error) { - $this->doRenderThrowable($error, $output); - } - } -} diff --git a/lib/symfony/framework-bundle/Console/Descriptor/Descriptor.php b/lib/symfony/framework-bundle/Console/Descriptor/Descriptor.php deleted file mode 100644 index 537d6d08c..000000000 --- a/lib/symfony/framework-bundle/Console/Descriptor/Descriptor.php +++ /dev/null @@ -1,380 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Console\Descriptor; - -use Symfony\Component\Config\Resource\ClassExistenceResource; -use Symfony\Component\Console\Descriptor\DescriptorInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -abstract class Descriptor implements DescriptorInterface -{ - /** - * @var OutputInterface - */ - protected $output; - - /** - * {@inheritdoc} - */ - public function describe(OutputInterface $output, $object, array $options = []) - { - $this->output = $output; - - switch (true) { - case $object instanceof RouteCollection: - $this->describeRouteCollection($object, $options); - break; - case $object instanceof Route: - $this->describeRoute($object, $options); - break; - case $object instanceof ParameterBag: - $this->describeContainerParameters($object, $options); - break; - case $object instanceof ContainerBuilder && !empty($options['env-vars']): - $this->describeContainerEnvVars($this->getContainerEnvVars($object), $options); - break; - case $object instanceof ContainerBuilder && isset($options['group_by']) && 'tags' === $options['group_by']: - $this->describeContainerTags($object, $options); - break; - case $object instanceof ContainerBuilder && isset($options['id']): - $this->describeContainerService($this->resolveServiceDefinition($object, $options['id']), $options, $object); - break; - case $object instanceof ContainerBuilder && isset($options['parameter']): - $this->describeContainerParameter($object->resolveEnvPlaceholders($object->getParameter($options['parameter'])), $options); - break; - case $object instanceof ContainerBuilder && isset($options['deprecations']): - $this->describeContainerDeprecations($object, $options); - break; - case $object instanceof ContainerBuilder: - $this->describeContainerServices($object, $options); - break; - case $object instanceof Definition: - $this->describeContainerDefinition($object, $options); - break; - case $object instanceof Alias: - $this->describeContainerAlias($object, $options); - break; - case $object instanceof EventDispatcherInterface: - $this->describeEventDispatcherListeners($object, $options); - break; - case \is_callable($object): - $this->describeCallable($object, $options); - break; - default: - throw new \InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_debug_type($object))); - } - } - - protected function getOutput(): OutputInterface - { - return $this->output; - } - - protected function write(string $content, bool $decorated = false) - { - $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW); - } - - abstract protected function describeRouteCollection(RouteCollection $routes, array $options = []); - - abstract protected function describeRoute(Route $route, array $options = []); - - abstract protected function describeContainerParameters(ParameterBag $parameters, array $options = []); - - abstract protected function describeContainerTags(ContainerBuilder $builder, array $options = []); - - /** - * Describes a container service by its name. - * - * Common options are: - * * name: name of described service - * - * @param Definition|Alias|object $service - */ - abstract protected function describeContainerService(object $service, array $options = [], ContainerBuilder $builder = null); - - /** - * Describes container services. - * - * Common options are: - * * tag: filters described services by given tag - */ - abstract protected function describeContainerServices(ContainerBuilder $builder, array $options = []); - - abstract protected function describeContainerDeprecations(ContainerBuilder $builder, array $options = []): void; - - abstract protected function describeContainerDefinition(Definition $definition, array $options = []); - - abstract protected function describeContainerAlias(Alias $alias, array $options = [], ContainerBuilder $builder = null); - - abstract protected function describeContainerParameter($parameter, array $options = []); - - abstract protected function describeContainerEnvVars(array $envs, array $options = []); - - /** - * Describes event dispatcher listeners. - * - * Common options are: - * * name: name of listened event - */ - abstract protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = []); - - /** - * Describes a callable. - * - * @param mixed $callable - */ - abstract protected function describeCallable($callable, array $options = []); - - /** - * Formats a value as string. - * - * @param mixed $value - */ - protected function formatValue($value): string - { - if ($value instanceof \UnitEnum) { - return ltrim(var_export($value, true), '\\'); - } - - if (\is_object($value)) { - return sprintf('object(%s)', \get_class($value)); - } - - if (\is_string($value)) { - return $value; - } - - return preg_replace("/\n\s*/s", '', var_export($value, true)); - } - - /** - * Formats a parameter. - * - * @param mixed $value - */ - protected function formatParameter($value): string - { - if ($value instanceof \UnitEnum) { - return ltrim(var_export($value, true), '\\'); - } - - // Recursively search for enum values, so we can replace it - // before json_encode (which will not display anything for \UnitEnum otherwise) - if (\is_array($value)) { - array_walk_recursive($value, static function (&$value) { - if ($value instanceof \UnitEnum) { - $value = ltrim(var_export($value, true), '\\'); - } - }); - } - - if (\is_bool($value) || \is_array($value) || (null === $value)) { - $jsonString = json_encode($value); - - if (preg_match('/^(.{60})./us', $jsonString, $matches)) { - return $matches[1].'...'; - } - - return $jsonString; - } - - return (string) $value; - } - - /** - * @return mixed - */ - protected function resolveServiceDefinition(ContainerBuilder $builder, string $serviceId) - { - if ($builder->hasDefinition($serviceId)) { - return $builder->getDefinition($serviceId); - } - - // Some service IDs don't have a Definition, they're aliases - if ($builder->hasAlias($serviceId)) { - return $builder->getAlias($serviceId); - } - - if ('service_container' === $serviceId) { - return (new Definition(ContainerInterface::class))->setPublic(true)->setSynthetic(true); - } - - // the service has been injected in some special way, just return the service - return $builder->get($serviceId); - } - - protected function findDefinitionsByTag(ContainerBuilder $builder, bool $showHidden): array - { - $definitions = []; - $tags = $builder->findTags(); - asort($tags); - - foreach ($tags as $tag) { - foreach ($builder->findTaggedServiceIds($tag) as $serviceId => $attributes) { - $definition = $this->resolveServiceDefinition($builder, $serviceId); - - if ($showHidden xor '.' === ($serviceId[0] ?? null)) { - continue; - } - - if (!isset($definitions[$tag])) { - $definitions[$tag] = []; - } - - $definitions[$tag][$serviceId] = $definition; - } - } - - return $definitions; - } - - protected function sortParameters(ParameterBag $parameters) - { - $parameters = $parameters->all(); - ksort($parameters); - - return $parameters; - } - - protected function sortServiceIds(array $serviceIds) - { - asort($serviceIds); - - return $serviceIds; - } - - protected function sortTaggedServicesByPriority(array $services): array - { - $maxPriority = []; - foreach ($services as $service => $tags) { - $maxPriority[$service] = \PHP_INT_MIN; - foreach ($tags as $tag) { - $currentPriority = $tag['priority'] ?? 0; - if ($maxPriority[$service] < $currentPriority) { - $maxPriority[$service] = $currentPriority; - } - } - } - uasort($maxPriority, function ($a, $b) { - return $b <=> $a; - }); - - return array_keys($maxPriority); - } - - protected function sortTagsByPriority(array $tags): array - { - $sortedTags = []; - foreach ($tags as $tagName => $tag) { - $sortedTags[$tagName] = $this->sortByPriority($tag); - } - - return $sortedTags; - } - - protected function sortByPriority(array $tag): array - { - usort($tag, function ($a, $b) { - return ($b['priority'] ?? 0) <=> ($a['priority'] ?? 0); - }); - - return $tag; - } - - public static function getClassDescription(string $class, string &$resolvedClass = null): string - { - $resolvedClass = $class; - try { - $resource = new ClassExistenceResource($class, false); - - // isFresh() will explode ONLY if a parent class/trait does not exist - $resource->isFresh(0); - - $r = new \ReflectionClass($class); - $resolvedClass = $r->name; - - if ($docComment = $r->getDocComment()) { - $docComment = preg_split('#\n\s*\*\s*[\n@]#', substr($docComment, 3, -2), 2)[0]; - - return trim(preg_replace('#\s*\n\s*\*\s*#', ' ', $docComment)); - } - } catch (\ReflectionException $e) { - } - - return ''; - } - - private function getContainerEnvVars(ContainerBuilder $container): array - { - if (!$container->hasParameter('debug.container.dump')) { - return []; - } - - if (!is_file($container->getParameter('debug.container.dump'))) { - return []; - } - - $file = file_get_contents($container->getParameter('debug.container.dump')); - preg_match_all('{%env\(((?:\w++:)*+\w++)\)%}', $file, $envVars); - $envVars = array_unique($envVars[1]); - - $bag = $container->getParameterBag(); - $getDefaultParameter = function (string $name) { - return parent::get($name); - }; - $getDefaultParameter = $getDefaultParameter->bindTo($bag, \get_class($bag)); - - $getEnvReflection = new \ReflectionMethod($container, 'getEnv'); - $getEnvReflection->setAccessible(true); - - $envs = []; - - foreach ($envVars as $env) { - $processor = 'string'; - if (false !== $i = strrpos($name = $env, ':')) { - $name = substr($env, $i + 1); - $processor = substr($env, 0, $i); - } - $defaultValue = ($hasDefault = $container->hasParameter("env($name)")) ? $getDefaultParameter("env($name)") : null; - if (false === ($runtimeValue = $_ENV[$name] ?? $_SERVER[$name] ?? getenv($name))) { - $runtimeValue = null; - } - $processedValue = ($hasRuntime = null !== $runtimeValue) || $hasDefault ? $getEnvReflection->invoke($container, $env) : null; - $envs["$name$processor"] = [ - 'name' => $name, - 'processor' => $processor, - 'default_available' => $hasDefault, - 'default_value' => $defaultValue, - 'runtime_available' => $hasRuntime, - 'runtime_value' => $runtimeValue, - 'processed_value' => $processedValue, - ]; - } - ksort($envs); - - return array_values($envs); - } -} diff --git a/lib/symfony/framework-bundle/Console/Descriptor/JsonDescriptor.php b/lib/symfony/framework-bundle/Console/Descriptor/JsonDescriptor.php deleted file mode 100644 index 0ad063343..000000000 --- a/lib/symfony/framework-bundle/Console/Descriptor/JsonDescriptor.php +++ /dev/null @@ -1,420 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Console\Descriptor; - -use Symfony\Component\Console\Exception\LogicException; -use Symfony\Component\Console\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\AbstractArgument; -use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class JsonDescriptor extends Descriptor -{ - protected function describeRouteCollection(RouteCollection $routes, array $options = []) - { - $data = []; - foreach ($routes->all() as $name => $route) { - $data[$name] = $this->getRouteData($route); - } - - $this->writeData($data, $options); - } - - protected function describeRoute(Route $route, array $options = []) - { - $this->writeData($this->getRouteData($route), $options); - } - - protected function describeContainerParameters(ParameterBag $parameters, array $options = []) - { - $this->writeData($this->sortParameters($parameters), $options); - } - - protected function describeContainerTags(ContainerBuilder $builder, array $options = []) - { - $showHidden = isset($options['show_hidden']) && $options['show_hidden']; - $data = []; - - foreach ($this->findDefinitionsByTag($builder, $showHidden) as $tag => $definitions) { - $data[$tag] = []; - foreach ($definitions as $definition) { - $data[$tag][] = $this->getContainerDefinitionData($definition, true); - } - } - - $this->writeData($data, $options); - } - - protected function describeContainerService(object $service, array $options = [], ContainerBuilder $builder = null) - { - if (!isset($options['id'])) { - throw new \InvalidArgumentException('An "id" option must be provided.'); - } - - if ($service instanceof Alias) { - $this->describeContainerAlias($service, $options, $builder); - } elseif ($service instanceof Definition) { - $this->writeData($this->getContainerDefinitionData($service, isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments']), $options); - } else { - $this->writeData(\get_class($service), $options); - } - } - - protected function describeContainerServices(ContainerBuilder $builder, array $options = []) - { - $serviceIds = isset($options['tag']) && $options['tag'] - ? $this->sortTaggedServicesByPriority($builder->findTaggedServiceIds($options['tag'])) - : $this->sortServiceIds($builder->getServiceIds()); - $showHidden = isset($options['show_hidden']) && $options['show_hidden']; - $omitTags = isset($options['omit_tags']) && $options['omit_tags']; - $showArguments = isset($options['show_arguments']) && $options['show_arguments']; - $data = ['definitions' => [], 'aliases' => [], 'services' => []]; - - if (isset($options['filter'])) { - $serviceIds = array_filter($serviceIds, $options['filter']); - } - - foreach ($serviceIds as $serviceId) { - $service = $this->resolveServiceDefinition($builder, $serviceId); - - if ($showHidden xor '.' === ($serviceId[0] ?? null)) { - continue; - } - - if ($service instanceof Alias) { - $data['aliases'][$serviceId] = $this->getContainerAliasData($service); - } elseif ($service instanceof Definition) { - $data['definitions'][$serviceId] = $this->getContainerDefinitionData($service, $omitTags, $showArguments); - } else { - $data['services'][$serviceId] = \get_class($service); - } - } - - $this->writeData($data, $options); - } - - protected function describeContainerDefinition(Definition $definition, array $options = []) - { - $this->writeData($this->getContainerDefinitionData($definition, isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments']), $options); - } - - protected function describeContainerAlias(Alias $alias, array $options = [], ContainerBuilder $builder = null) - { - if (!$builder) { - $this->writeData($this->getContainerAliasData($alias), $options); - - return; - } - - $this->writeData( - [$this->getContainerAliasData($alias), $this->getContainerDefinitionData($builder->getDefinition((string) $alias), isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments'])], - array_merge($options, ['id' => (string) $alias]) - ); - } - - protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = []) - { - $this->writeData($this->getEventDispatcherListenersData($eventDispatcher, $options), $options); - } - - protected function describeCallable($callable, array $options = []) - { - $this->writeData($this->getCallableData($callable), $options); - } - - protected function describeContainerParameter($parameter, array $options = []) - { - $key = $options['parameter'] ?? ''; - - $this->writeData([$key => $parameter], $options); - } - - protected function describeContainerEnvVars(array $envs, array $options = []) - { - throw new LogicException('Using the JSON format to debug environment variables is not supported.'); - } - - protected function describeContainerDeprecations(ContainerBuilder $builder, array $options = []): void - { - $containerDeprecationFilePath = sprintf('%s/%sDeprecations.log', $builder->getParameter('kernel.build_dir'), $builder->getParameter('kernel.container_class')); - if (!file_exists($containerDeprecationFilePath)) { - throw new RuntimeException('The deprecation file does not exist, please try warming the cache first.'); - } - - $logs = unserialize(file_get_contents($containerDeprecationFilePath)); - - $formattedLogs = []; - $remainingCount = 0; - foreach ($logs as $log) { - $formattedLogs[] = [ - 'message' => $log['message'], - 'file' => $log['file'], - 'line' => $log['line'], - 'count' => $log['count'], - ]; - $remainingCount += $log['count']; - } - - $this->writeData(['remainingCount' => $remainingCount, 'deprecations' => $formattedLogs], $options); - } - - private function writeData(array $data, array $options) - { - $flags = $options['json_encoding'] ?? 0; - - // Recursively search for enum values, so we can replace it - // before json_encode (which will not display anything for \UnitEnum otherwise) - array_walk_recursive($data, static function (&$value) { - if ($value instanceof \UnitEnum) { - $value = ltrim(var_export($value, true), '\\'); - } - }); - - $this->write(json_encode($data, $flags | \JSON_PRETTY_PRINT)."\n"); - } - - protected function getRouteData(Route $route): array - { - $data = [ - 'path' => $route->getPath(), - 'pathRegex' => $route->compile()->getRegex(), - 'host' => '' !== $route->getHost() ? $route->getHost() : 'ANY', - 'hostRegex' => '' !== $route->getHost() ? $route->compile()->getHostRegex() : '', - 'scheme' => $route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY', - 'method' => $route->getMethods() ? implode('|', $route->getMethods()) : 'ANY', - 'class' => \get_class($route), - 'defaults' => $route->getDefaults(), - 'requirements' => $route->getRequirements() ?: 'NO CUSTOM', - 'options' => $route->getOptions(), - ]; - - if ('' !== $route->getCondition()) { - $data['condition'] = $route->getCondition(); - } - - return $data; - } - - private function getContainerDefinitionData(Definition $definition, bool $omitTags = false, bool $showArguments = false): array - { - $data = [ - 'class' => (string) $definition->getClass(), - 'public' => $definition->isPublic() && !$definition->isPrivate(), - 'synthetic' => $definition->isSynthetic(), - 'lazy' => $definition->isLazy(), - 'shared' => $definition->isShared(), - 'abstract' => $definition->isAbstract(), - 'autowire' => $definition->isAutowired(), - 'autoconfigure' => $definition->isAutoconfigured(), - ]; - - if ('' !== $classDescription = $this->getClassDescription((string) $definition->getClass())) { - $data['description'] = $classDescription; - } - - if ($showArguments) { - $data['arguments'] = $this->describeValue($definition->getArguments(), $omitTags, $showArguments); - } - - $data['file'] = $definition->getFile(); - - if ($factory = $definition->getFactory()) { - if (\is_array($factory)) { - if ($factory[0] instanceof Reference) { - $data['factory_service'] = (string) $factory[0]; - } elseif ($factory[0] instanceof Definition) { - $data['factory_service'] = sprintf('inline factory service (%s)', $factory[0]->getClass() ?? 'class not configured'); - } else { - $data['factory_class'] = $factory[0]; - } - $data['factory_method'] = $factory[1]; - } else { - $data['factory_function'] = $factory; - } - } - - $calls = $definition->getMethodCalls(); - if (\count($calls) > 0) { - $data['calls'] = []; - foreach ($calls as $callData) { - $data['calls'][] = $callData[0]; - } - } - - if (!$omitTags) { - $data['tags'] = []; - foreach ($this->sortTagsByPriority($definition->getTags()) as $tagName => $tagData) { - foreach ($tagData as $parameters) { - $data['tags'][] = ['name' => $tagName, 'parameters' => $parameters]; - } - } - } - - return $data; - } - - private function getContainerAliasData(Alias $alias): array - { - return [ - 'service' => (string) $alias, - 'public' => $alias->isPublic() && !$alias->isPrivate(), - ]; - } - - private function getEventDispatcherListenersData(EventDispatcherInterface $eventDispatcher, array $options): array - { - $data = []; - $event = \array_key_exists('event', $options) ? $options['event'] : null; - - if (null !== $event) { - foreach ($eventDispatcher->getListeners($event) as $listener) { - $l = $this->getCallableData($listener); - $l['priority'] = $eventDispatcher->getListenerPriority($event, $listener); - $data[] = $l; - } - } else { - $registeredListeners = \array_key_exists('events', $options) ? array_combine($options['events'], array_map(function ($event) use ($eventDispatcher) { return $eventDispatcher->getListeners($event); }, $options['events'])) : $eventDispatcher->getListeners(); - ksort($registeredListeners); - - foreach ($registeredListeners as $eventListened => $eventListeners) { - foreach ($eventListeners as $eventListener) { - $l = $this->getCallableData($eventListener); - $l['priority'] = $eventDispatcher->getListenerPriority($eventListened, $eventListener); - $data[$eventListened][] = $l; - } - } - } - - return $data; - } - - private function getCallableData($callable): array - { - $data = []; - - if (\is_array($callable)) { - $data['type'] = 'function'; - - if (\is_object($callable[0])) { - $data['name'] = $callable[1]; - $data['class'] = \get_class($callable[0]); - } else { - if (!str_starts_with($callable[1], 'parent::')) { - $data['name'] = $callable[1]; - $data['class'] = $callable[0]; - $data['static'] = true; - } else { - $data['name'] = substr($callable[1], 8); - $data['class'] = $callable[0]; - $data['static'] = true; - $data['parent'] = true; - } - } - - return $data; - } - - if (\is_string($callable)) { - $data['type'] = 'function'; - - if (!str_contains($callable, '::')) { - $data['name'] = $callable; - } else { - $callableParts = explode('::', $callable); - - $data['name'] = $callableParts[1]; - $data['class'] = $callableParts[0]; - $data['static'] = true; - } - - return $data; - } - - if ($callable instanceof \Closure) { - $data['type'] = 'closure'; - - $r = new \ReflectionFunction($callable); - if (str_contains($r->name, '{closure}')) { - return $data; - } - $data['name'] = $r->name; - - if ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) { - $data['class'] = $class->name; - if (!$r->getClosureThis()) { - $data['static'] = true; - } - } - - return $data; - } - - if (method_exists($callable, '__invoke')) { - $data['type'] = 'object'; - $data['name'] = \get_class($callable); - - return $data; - } - - throw new \InvalidArgumentException('Callable is not describable.'); - } - - private function describeValue($value, bool $omitTags, bool $showArguments) - { - if (\is_array($value)) { - $data = []; - foreach ($value as $k => $v) { - $data[$k] = $this->describeValue($v, $omitTags, $showArguments); - } - - return $data; - } - - if ($value instanceof ServiceClosureArgument) { - $value = $value->getValues()[0]; - } - - if ($value instanceof Reference) { - return [ - 'type' => 'service', - 'id' => (string) $value, - ]; - } - - if ($value instanceof AbstractArgument) { - return ['type' => 'abstract', 'text' => $value->getText()]; - } - - if ($value instanceof ArgumentInterface) { - return $this->describeValue($value->getValues(), $omitTags, $showArguments); - } - - if ($value instanceof Definition) { - return $this->getContainerDefinitionData($value, $omitTags, $showArguments); - } - - return $value; - } -} diff --git a/lib/symfony/framework-bundle/Console/Descriptor/MarkdownDescriptor.php b/lib/symfony/framework-bundle/Console/Descriptor/MarkdownDescriptor.php deleted file mode 100644 index a3fbabc6d..000000000 --- a/lib/symfony/framework-bundle/Console/Descriptor/MarkdownDescriptor.php +++ /dev/null @@ -1,414 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Console\Descriptor; - -use Symfony\Component\Console\Exception\LogicException; -use Symfony\Component\Console\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class MarkdownDescriptor extends Descriptor -{ - protected function describeRouteCollection(RouteCollection $routes, array $options = []) - { - $first = true; - foreach ($routes->all() as $name => $route) { - if ($first) { - $first = false; - } else { - $this->write("\n\n"); - } - $this->describeRoute($route, ['name' => $name]); - } - $this->write("\n"); - } - - protected function describeRoute(Route $route, array $options = []) - { - $output = '- Path: '.$route->getPath() - ."\n".'- Path Regex: '.$route->compile()->getRegex() - ."\n".'- Host: '.('' !== $route->getHost() ? $route->getHost() : 'ANY') - ."\n".'- Host Regex: '.('' !== $route->getHost() ? $route->compile()->getHostRegex() : '') - ."\n".'- Scheme: '.($route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY') - ."\n".'- Method: '.($route->getMethods() ? implode('|', $route->getMethods()) : 'ANY') - ."\n".'- Class: '.\get_class($route) - ."\n".'- Defaults: '.$this->formatRouterConfig($route->getDefaults()) - ."\n".'- Requirements: '.($route->getRequirements() ? $this->formatRouterConfig($route->getRequirements()) : 'NO CUSTOM') - ."\n".'- Options: '.$this->formatRouterConfig($route->getOptions()); - - if ('' !== $route->getCondition()) { - $output .= "\n".'- Condition: '.$route->getCondition(); - } - - $this->write(isset($options['name']) - ? $options['name']."\n".str_repeat('-', \strlen($options['name']))."\n\n".$output - : $output); - $this->write("\n"); - } - - protected function describeContainerParameters(ParameterBag $parameters, array $options = []) - { - $this->write("Container parameters\n====================\n"); - foreach ($this->sortParameters($parameters) as $key => $value) { - $this->write(sprintf("\n- `%s`: `%s`", $key, $this->formatParameter($value))); - } - } - - protected function describeContainerTags(ContainerBuilder $builder, array $options = []) - { - $showHidden = isset($options['show_hidden']) && $options['show_hidden']; - $this->write("Container tags\n=============="); - - foreach ($this->findDefinitionsByTag($builder, $showHidden) as $tag => $definitions) { - $this->write("\n\n".$tag."\n".str_repeat('-', \strlen($tag))); - foreach ($definitions as $serviceId => $definition) { - $this->write("\n\n"); - $this->describeContainerDefinition($definition, ['omit_tags' => true, 'id' => $serviceId]); - } - } - } - - protected function describeContainerService(object $service, array $options = [], ContainerBuilder $builder = null) - { - if (!isset($options['id'])) { - throw new \InvalidArgumentException('An "id" option must be provided.'); - } - - $childOptions = array_merge($options, ['id' => $options['id'], 'as_array' => true]); - - if ($service instanceof Alias) { - $this->describeContainerAlias($service, $childOptions, $builder); - } elseif ($service instanceof Definition) { - $this->describeContainerDefinition($service, $childOptions); - } else { - $this->write(sprintf('**`%s`:** `%s`', $options['id'], \get_class($service))); - } - } - - protected function describeContainerDeprecations(ContainerBuilder $builder, array $options = []): void - { - $containerDeprecationFilePath = sprintf('%s/%sDeprecations.log', $builder->getParameter('kernel.build_dir'), $builder->getParameter('kernel.container_class')); - if (!file_exists($containerDeprecationFilePath)) { - throw new RuntimeException('The deprecation file does not exist, please try warming the cache first.'); - } - - $logs = unserialize(file_get_contents($containerDeprecationFilePath)); - if (0 === \count($logs)) { - $this->write("## There are no deprecations in the logs!\n"); - - return; - } - - $formattedLogs = []; - $remainingCount = 0; - foreach ($logs as $log) { - $formattedLogs[] = sprintf("- %sx: \"%s\" in %s:%s\n", $log['count'], $log['message'], $log['file'], $log['line']); - $remainingCount += $log['count']; - } - - $this->write(sprintf("## Remaining deprecations (%s)\n\n", $remainingCount)); - foreach ($formattedLogs as $formattedLog) { - $this->write($formattedLog); - } - } - - protected function describeContainerServices(ContainerBuilder $builder, array $options = []) - { - $showHidden = isset($options['show_hidden']) && $options['show_hidden']; - - $title = $showHidden ? 'Hidden services' : 'Services'; - if (isset($options['tag'])) { - $title .= ' with tag `'.$options['tag'].'`'; - } - $this->write($title."\n".str_repeat('=', \strlen($title))); - - $serviceIds = isset($options['tag']) && $options['tag'] - ? $this->sortTaggedServicesByPriority($builder->findTaggedServiceIds($options['tag'])) - : $this->sortServiceIds($builder->getServiceIds()); - $showArguments = isset($options['show_arguments']) && $options['show_arguments']; - $services = ['definitions' => [], 'aliases' => [], 'services' => []]; - - if (isset($options['filter'])) { - $serviceIds = array_filter($serviceIds, $options['filter']); - } - - foreach ($serviceIds as $serviceId) { - $service = $this->resolveServiceDefinition($builder, $serviceId); - - if ($showHidden xor '.' === ($serviceId[0] ?? null)) { - continue; - } - - if ($service instanceof Alias) { - $services['aliases'][$serviceId] = $service; - } elseif ($service instanceof Definition) { - $services['definitions'][$serviceId] = $service; - } else { - $services['services'][$serviceId] = $service; - } - } - - if (!empty($services['definitions'])) { - $this->write("\n\nDefinitions\n-----------\n"); - foreach ($services['definitions'] as $id => $service) { - $this->write("\n"); - $this->describeContainerDefinition($service, ['id' => $id, 'show_arguments' => $showArguments]); - } - } - - if (!empty($services['aliases'])) { - $this->write("\n\nAliases\n-------\n"); - foreach ($services['aliases'] as $id => $service) { - $this->write("\n"); - $this->describeContainerAlias($service, ['id' => $id]); - } - } - - if (!empty($services['services'])) { - $this->write("\n\nServices\n--------\n"); - foreach ($services['services'] as $id => $service) { - $this->write("\n"); - $this->write(sprintf('- `%s`: `%s`', $id, \get_class($service))); - } - } - } - - protected function describeContainerDefinition(Definition $definition, array $options = []) - { - $output = ''; - - if ('' !== $classDescription = $this->getClassDescription((string) $definition->getClass())) { - $output .= '- Description: `'.$classDescription.'`'."\n"; - } - - $output .= '- Class: `'.$definition->getClass().'`' - ."\n".'- Public: '.($definition->isPublic() && !$definition->isPrivate() ? 'yes' : 'no') - ."\n".'- Synthetic: '.($definition->isSynthetic() ? 'yes' : 'no') - ."\n".'- Lazy: '.($definition->isLazy() ? 'yes' : 'no') - ."\n".'- Shared: '.($definition->isShared() ? 'yes' : 'no') - ."\n".'- Abstract: '.($definition->isAbstract() ? 'yes' : 'no') - ."\n".'- Autowired: '.($definition->isAutowired() ? 'yes' : 'no') - ."\n".'- Autoconfigured: '.($definition->isAutoconfigured() ? 'yes' : 'no') - ; - - if (isset($options['show_arguments']) && $options['show_arguments']) { - $output .= "\n".'- Arguments: '.($definition->getArguments() ? 'yes' : 'no'); - } - - if ($definition->getFile()) { - $output .= "\n".'- File: `'.$definition->getFile().'`'; - } - - if ($factory = $definition->getFactory()) { - if (\is_array($factory)) { - if ($factory[0] instanceof Reference) { - $output .= "\n".'- Factory Service: `'.$factory[0].'`'; - } elseif ($factory[0] instanceof Definition) { - $output .= "\n".sprintf('- Factory Service: inline factory service (%s)', $factory[0]->getClass() ? sprintf('`%s`', $factory[0]->getClass()) : 'not configured'); - } else { - $output .= "\n".'- Factory Class: `'.$factory[0].'`'; - } - $output .= "\n".'- Factory Method: `'.$factory[1].'`'; - } else { - $output .= "\n".'- Factory Function: `'.$factory.'`'; - } - } - - $calls = $definition->getMethodCalls(); - foreach ($calls as $callData) { - $output .= "\n".'- Call: `'.$callData[0].'`'; - } - - if (!(isset($options['omit_tags']) && $options['omit_tags'])) { - foreach ($this->sortTagsByPriority($definition->getTags()) as $tagName => $tagData) { - foreach ($tagData as $parameters) { - $output .= "\n".'- Tag: `'.$tagName.'`'; - foreach ($parameters as $name => $value) { - $output .= "\n".' - '.ucfirst($name).': '.$value; - } - } - } - } - - $this->write(isset($options['id']) ? sprintf("### %s\n\n%s\n", $options['id'], $output) : $output); - } - - protected function describeContainerAlias(Alias $alias, array $options = [], ContainerBuilder $builder = null) - { - $output = '- Service: `'.$alias.'`' - ."\n".'- Public: '.($alias->isPublic() && !$alias->isPrivate() ? 'yes' : 'no'); - - if (!isset($options['id'])) { - $this->write($output); - - return; - } - - $this->write(sprintf("### %s\n\n%s\n", $options['id'], $output)); - - if (!$builder) { - return; - } - - $this->write("\n"); - $this->describeContainerDefinition($builder->getDefinition((string) $alias), array_merge($options, ['id' => (string) $alias])); - } - - protected function describeContainerParameter($parameter, array $options = []) - { - $this->write(isset($options['parameter']) ? sprintf("%s\n%s\n\n%s", $options['parameter'], str_repeat('=', \strlen($options['parameter'])), $this->formatParameter($parameter)) : $parameter); - } - - protected function describeContainerEnvVars(array $envs, array $options = []) - { - throw new LogicException('Using the markdown format to debug environment variables is not supported.'); - } - - protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = []) - { - $event = $options['event'] ?? null; - $dispatcherServiceName = $options['dispatcher_service_name'] ?? null; - - $title = 'Registered listeners'; - - if (null !== $dispatcherServiceName) { - $title .= sprintf(' of event dispatcher "%s"', $dispatcherServiceName); - } - - if (null !== $event) { - $title .= sprintf(' for event `%s` ordered by descending priority', $event); - $registeredListeners = $eventDispatcher->getListeners($event); - } else { - // Try to see if "events" exists - $registeredListeners = \array_key_exists('events', $options) ? array_combine($options['events'], array_map(function ($event) use ($eventDispatcher) { return $eventDispatcher->getListeners($event); }, $options['events'])) : $eventDispatcher->getListeners(); - } - - $this->write(sprintf('# %s', $title)."\n"); - - if (null !== $event) { - foreach ($registeredListeners as $order => $listener) { - $this->write("\n".sprintf('## Listener %d', $order + 1)."\n"); - $this->describeCallable($listener); - $this->write(sprintf('- Priority: `%d`', $eventDispatcher->getListenerPriority($event, $listener))."\n"); - } - } else { - ksort($registeredListeners); - - foreach ($registeredListeners as $eventListened => $eventListeners) { - $this->write("\n".sprintf('## %s', $eventListened)."\n"); - - foreach ($eventListeners as $order => $eventListener) { - $this->write("\n".sprintf('### Listener %d', $order + 1)."\n"); - $this->describeCallable($eventListener); - $this->write(sprintf('- Priority: `%d`', $eventDispatcher->getListenerPriority($eventListened, $eventListener))."\n"); - } - } - } - } - - protected function describeCallable($callable, array $options = []) - { - $string = ''; - - if (\is_array($callable)) { - $string .= "\n- Type: `function`"; - - if (\is_object($callable[0])) { - $string .= "\n".sprintf('- Name: `%s`', $callable[1]); - $string .= "\n".sprintf('- Class: `%s`', \get_class($callable[0])); - } else { - if (!str_starts_with($callable[1], 'parent::')) { - $string .= "\n".sprintf('- Name: `%s`', $callable[1]); - $string .= "\n".sprintf('- Class: `%s`', $callable[0]); - $string .= "\n- Static: yes"; - } else { - $string .= "\n".sprintf('- Name: `%s`', substr($callable[1], 8)); - $string .= "\n".sprintf('- Class: `%s`', $callable[0]); - $string .= "\n- Static: yes"; - $string .= "\n- Parent: yes"; - } - } - - return $this->write($string."\n"); - } - - if (\is_string($callable)) { - $string .= "\n- Type: `function`"; - - if (!str_contains($callable, '::')) { - $string .= "\n".sprintf('- Name: `%s`', $callable); - } else { - $callableParts = explode('::', $callable); - - $string .= "\n".sprintf('- Name: `%s`', $callableParts[1]); - $string .= "\n".sprintf('- Class: `%s`', $callableParts[0]); - $string .= "\n- Static: yes"; - } - - return $this->write($string."\n"); - } - - if ($callable instanceof \Closure) { - $string .= "\n- Type: `closure`"; - - $r = new \ReflectionFunction($callable); - if (str_contains($r->name, '{closure}')) { - return $this->write($string."\n"); - } - $string .= "\n".sprintf('- Name: `%s`', $r->name); - - if ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) { - $string .= "\n".sprintf('- Class: `%s`', $class->name); - if (!$r->getClosureThis()) { - $string .= "\n- Static: yes"; - } - } - - return $this->write($string."\n"); - } - - if (method_exists($callable, '__invoke')) { - $string .= "\n- Type: `object`"; - $string .= "\n".sprintf('- Name: `%s`', \get_class($callable)); - - return $this->write($string."\n"); - } - - throw new \InvalidArgumentException('Callable is not describable.'); - } - - private function formatRouterConfig(array $array): string - { - if (!$array) { - return 'NONE'; - } - - $string = ''; - ksort($array); - foreach ($array as $name => $value) { - $string .= "\n".' - `'.$name.'`: '.$this->formatValue($value); - } - - return $string; - } -} diff --git a/lib/symfony/framework-bundle/Console/Descriptor/TextDescriptor.php b/lib/symfony/framework-bundle/Console/Descriptor/TextDescriptor.php deleted file mode 100644 index e7eb18762..000000000 --- a/lib/symfony/framework-bundle/Console/Descriptor/TextDescriptor.php +++ /dev/null @@ -1,638 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Console\Descriptor; - -use Symfony\Component\Console\Formatter\OutputFormatter; -use Symfony\Component\Console\Helper\Dumper; -use Symfony\Component\Console\Helper\Table; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\AbstractArgument; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class TextDescriptor extends Descriptor -{ - private $fileLinkFormatter; - - public function __construct(FileLinkFormatter $fileLinkFormatter = null) - { - $this->fileLinkFormatter = $fileLinkFormatter; - } - - protected function describeRouteCollection(RouteCollection $routes, array $options = []) - { - $showControllers = isset($options['show_controllers']) && $options['show_controllers']; - - $tableHeaders = ['Name', 'Method', 'Scheme', 'Host', 'Path']; - if ($showControllers) { - $tableHeaders[] = 'Controller'; - } - - $tableRows = []; - foreach ($routes->all() as $name => $route) { - $controller = $route->getDefault('_controller'); - - $row = [ - $name, - $route->getMethods() ? implode('|', $route->getMethods()) : 'ANY', - $route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY', - '' !== $route->getHost() ? $route->getHost() : 'ANY', - $this->formatControllerLink($controller, $route->getPath(), $options['container'] ?? null), - ]; - - if ($showControllers) { - $row[] = $controller ? $this->formatControllerLink($controller, $this->formatCallable($controller), $options['container'] ?? null) : ''; - } - - $tableRows[] = $row; - } - - if (isset($options['output'])) { - $options['output']->table($tableHeaders, $tableRows); - } else { - $table = new Table($this->getOutput()); - $table->setHeaders($tableHeaders)->setRows($tableRows); - $table->render(); - } - } - - protected function describeRoute(Route $route, array $options = []) - { - $defaults = $route->getDefaults(); - if (isset($defaults['_controller'])) { - $defaults['_controller'] = $this->formatControllerLink($defaults['_controller'], $this->formatCallable($defaults['_controller']), $options['container'] ?? null); - } - - $tableHeaders = ['Property', 'Value']; - $tableRows = [ - ['Route Name', $options['name'] ?? ''], - ['Path', $route->getPath()], - ['Path Regex', $route->compile()->getRegex()], - ['Host', '' !== $route->getHost() ? $route->getHost() : 'ANY'], - ['Host Regex', '' !== $route->getHost() ? $route->compile()->getHostRegex() : ''], - ['Scheme', $route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY'], - ['Method', $route->getMethods() ? implode('|', $route->getMethods()) : 'ANY'], - ['Requirements', $route->getRequirements() ? $this->formatRouterConfig($route->getRequirements()) : 'NO CUSTOM'], - ['Class', \get_class($route)], - ['Defaults', $this->formatRouterConfig($defaults)], - ['Options', $this->formatRouterConfig($route->getOptions())], - ]; - - if ('' !== $route->getCondition()) { - $tableRows[] = ['Condition', $route->getCondition()]; - } - - $table = new Table($this->getOutput()); - $table->setHeaders($tableHeaders)->setRows($tableRows); - $table->render(); - } - - protected function describeContainerParameters(ParameterBag $parameters, array $options = []) - { - $tableHeaders = ['Parameter', 'Value']; - - $tableRows = []; - foreach ($this->sortParameters($parameters) as $parameter => $value) { - $tableRows[] = [$parameter, $this->formatParameter($value)]; - } - - $options['output']->title('Symfony Container Parameters'); - $options['output']->table($tableHeaders, $tableRows); - } - - protected function describeContainerTags(ContainerBuilder $builder, array $options = []) - { - $showHidden = isset($options['show_hidden']) && $options['show_hidden']; - - if ($showHidden) { - $options['output']->title('Symfony Container Hidden Tags'); - } else { - $options['output']->title('Symfony Container Tags'); - } - - foreach ($this->findDefinitionsByTag($builder, $showHidden) as $tag => $definitions) { - $options['output']->section(sprintf('"%s" tag', $tag)); - $options['output']->listing(array_keys($definitions)); - } - } - - protected function describeContainerService(object $service, array $options = [], ContainerBuilder $builder = null) - { - if (!isset($options['id'])) { - throw new \InvalidArgumentException('An "id" option must be provided.'); - } - - if ($service instanceof Alias) { - $this->describeContainerAlias($service, $options, $builder); - } elseif ($service instanceof Definition) { - $this->describeContainerDefinition($service, $options); - } else { - $options['output']->title(sprintf('Information for Service "<info>%s</info>"', $options['id'])); - $options['output']->table( - ['Service ID', 'Class'], - [ - [$options['id'] ?? '-', \get_class($service)], - ] - ); - } - } - - protected function describeContainerServices(ContainerBuilder $builder, array $options = []) - { - $showHidden = isset($options['show_hidden']) && $options['show_hidden']; - $showTag = $options['tag'] ?? null; - - if ($showHidden) { - $title = 'Symfony Container Hidden Services'; - } else { - $title = 'Symfony Container Services'; - } - - if ($showTag) { - $title .= sprintf(' Tagged with "%s" Tag', $options['tag']); - } - - $options['output']->title($title); - - $serviceIds = isset($options['tag']) && $options['tag'] - ? $this->sortTaggedServicesByPriority($builder->findTaggedServiceIds($options['tag'])) - : $this->sortServiceIds($builder->getServiceIds()); - $maxTags = []; - - if (isset($options['filter'])) { - $serviceIds = array_filter($serviceIds, $options['filter']); - } - - foreach ($serviceIds as $key => $serviceId) { - $definition = $this->resolveServiceDefinition($builder, $serviceId); - - // filter out hidden services unless shown explicitly - if ($showHidden xor '.' === ($serviceId[0] ?? null)) { - unset($serviceIds[$key]); - continue; - } - - if ($definition instanceof Definition) { - if ($showTag) { - $tags = $definition->getTag($showTag); - foreach ($tags as $tag) { - foreach ($tag as $key => $value) { - if (!isset($maxTags[$key])) { - $maxTags[$key] = \strlen($key); - } - if (\strlen($value) > $maxTags[$key]) { - $maxTags[$key] = \strlen($value); - } - } - } - } - } - } - - $tagsCount = \count($maxTags); - $tagsNames = array_keys($maxTags); - - $tableHeaders = array_merge(['Service ID'], $tagsNames, ['Class name']); - $tableRows = []; - $rawOutput = isset($options['raw_text']) && $options['raw_text']; - foreach ($serviceIds as $serviceId) { - $definition = $this->resolveServiceDefinition($builder, $serviceId); - - $styledServiceId = $rawOutput ? $serviceId : sprintf('<fg=cyan>%s</fg=cyan>', OutputFormatter::escape($serviceId)); - if ($definition instanceof Definition) { - if ($showTag) { - foreach ($this->sortByPriority($definition->getTag($showTag)) as $key => $tag) { - $tagValues = []; - foreach ($tagsNames as $tagName) { - $tagValues[] = $tag[$tagName] ?? ''; - } - if (0 === $key) { - $tableRows[] = array_merge([$serviceId], $tagValues, [$definition->getClass()]); - } else { - $tableRows[] = array_merge([' (same service as previous, another tag)'], $tagValues, ['']); - } - } - } else { - $tableRows[] = [$styledServiceId, $definition->getClass()]; - } - } elseif ($definition instanceof Alias) { - $alias = $definition; - $tableRows[] = array_merge([$styledServiceId, sprintf('alias for "%s"', $alias)], $tagsCount ? array_fill(0, $tagsCount, '') : []); - } else { - $tableRows[] = array_merge([$styledServiceId, \get_class($definition)], $tagsCount ? array_fill(0, $tagsCount, '') : []); - } - } - - $options['output']->table($tableHeaders, $tableRows); - } - - protected function describeContainerDefinition(Definition $definition, array $options = []) - { - if (isset($options['id'])) { - $options['output']->title(sprintf('Information for Service "<info>%s</info>"', $options['id'])); - } - - if ('' !== $classDescription = $this->getClassDescription((string) $definition->getClass())) { - $options['output']->text($classDescription."\n"); - } - - $tableHeaders = ['Option', 'Value']; - - $tableRows[] = ['Service ID', $options['id'] ?? '-']; - $tableRows[] = ['Class', $definition->getClass() ?: '-']; - - $omitTags = isset($options['omit_tags']) && $options['omit_tags']; - if (!$omitTags && ($tags = $definition->getTags())) { - $tagInformation = []; - foreach ($tags as $tagName => $tagData) { - foreach ($tagData as $tagParameters) { - $parameters = array_map(function ($key, $value) { - return sprintf('<info>%s</info>: %s', $key, $value); - }, array_keys($tagParameters), array_values($tagParameters)); - $parameters = implode(', ', $parameters); - - if ('' === $parameters) { - $tagInformation[] = sprintf('%s', $tagName); - } else { - $tagInformation[] = sprintf('%s (%s)', $tagName, $parameters); - } - } - } - $tagInformation = implode("\n", $tagInformation); - } else { - $tagInformation = '-'; - } - $tableRows[] = ['Tags', $tagInformation]; - - $calls = $definition->getMethodCalls(); - if (\count($calls) > 0) { - $callInformation = []; - foreach ($calls as $call) { - $callInformation[] = $call[0]; - } - $tableRows[] = ['Calls', implode(', ', $callInformation)]; - } - - $tableRows[] = ['Public', $definition->isPublic() && !$definition->isPrivate() ? 'yes' : 'no']; - $tableRows[] = ['Synthetic', $definition->isSynthetic() ? 'yes' : 'no']; - $tableRows[] = ['Lazy', $definition->isLazy() ? 'yes' : 'no']; - $tableRows[] = ['Shared', $definition->isShared() ? 'yes' : 'no']; - $tableRows[] = ['Abstract', $definition->isAbstract() ? 'yes' : 'no']; - $tableRows[] = ['Autowired', $definition->isAutowired() ? 'yes' : 'no']; - $tableRows[] = ['Autoconfigured', $definition->isAutoconfigured() ? 'yes' : 'no']; - - if ($definition->getFile()) { - $tableRows[] = ['Required File', $definition->getFile() ?: '-']; - } - - if ($factory = $definition->getFactory()) { - if (\is_array($factory)) { - if ($factory[0] instanceof Reference) { - $tableRows[] = ['Factory Service', $factory[0]]; - } elseif ($factory[0] instanceof Definition) { - $tableRows[] = ['Factory Service', sprintf('inline factory service (%s)', $factory[0]->getClass() ?? 'class not configured')]; - } else { - $tableRows[] = ['Factory Class', $factory[0]]; - } - $tableRows[] = ['Factory Method', $factory[1]]; - } else { - $tableRows[] = ['Factory Function', $factory]; - } - } - - $showArguments = isset($options['show_arguments']) && $options['show_arguments']; - $argumentsInformation = []; - if ($showArguments && ($arguments = $definition->getArguments())) { - foreach ($arguments as $argument) { - if ($argument instanceof ServiceClosureArgument) { - $argument = $argument->getValues()[0]; - } - if ($argument instanceof Reference) { - $argumentsInformation[] = sprintf('Service(%s)', (string) $argument); - } elseif ($argument instanceof IteratorArgument) { - if ($argument instanceof TaggedIteratorArgument) { - $argumentsInformation[] = sprintf('Tagged Iterator for "%s"%s', $argument->getTag(), $options['is_debug'] ? '' : sprintf(' (%d element(s))', \count($argument->getValues()))); - } else { - $argumentsInformation[] = sprintf('Iterator (%d element(s))', \count($argument->getValues())); - } - - foreach ($argument->getValues() as $ref) { - $argumentsInformation[] = sprintf('- Service(%s)', $ref); - } - } elseif ($argument instanceof ServiceLocatorArgument) { - $argumentsInformation[] = sprintf('Service locator (%d element(s))', \count($argument->getValues())); - } elseif ($argument instanceof Definition) { - $argumentsInformation[] = 'Inlined Service'; - } elseif ($argument instanceof \UnitEnum) { - $argumentsInformation[] = ltrim(var_export($argument, true), '\\'); - } elseif ($argument instanceof AbstractArgument) { - $argumentsInformation[] = sprintf('Abstract argument (%s)', $argument->getText()); - } else { - $argumentsInformation[] = \is_array($argument) ? sprintf('Array (%d element(s))', \count($argument)) : $argument; - } - } - - $tableRows[] = ['Arguments', implode("\n", $argumentsInformation)]; - } - - $options['output']->table($tableHeaders, $tableRows); - } - - protected function describeContainerDeprecations(ContainerBuilder $builder, array $options = []): void - { - $containerDeprecationFilePath = sprintf('%s/%sDeprecations.log', $builder->getParameter('kernel.build_dir'), $builder->getParameter('kernel.container_class')); - if (!file_exists($containerDeprecationFilePath)) { - $options['output']->warning('The deprecation file does not exist, please try warming the cache first.'); - - return; - } - - $logs = unserialize(file_get_contents($containerDeprecationFilePath)); - if (0 === \count($logs)) { - $options['output']->success('There are no deprecations in the logs!'); - - return; - } - - $formattedLogs = []; - $remainingCount = 0; - foreach ($logs as $log) { - $formattedLogs[] = sprintf("%sx: %s\n in %s:%s", $log['count'], $log['message'], $log['file'], $log['line']); - $remainingCount += $log['count']; - } - $options['output']->title(sprintf('Remaining deprecations (%s)', $remainingCount)); - $options['output']->listing($formattedLogs); - } - - protected function describeContainerAlias(Alias $alias, array $options = [], ContainerBuilder $builder = null) - { - if ($alias->isPublic() && !$alias->isPrivate()) { - $options['output']->comment(sprintf('This service is a <info>public</info> alias for the service <info>%s</info>', (string) $alias)); - } else { - $options['output']->comment(sprintf('This service is a <comment>private</comment> alias for the service <info>%s</info>', (string) $alias)); - } - - if (!$builder) { - return; - } - - $this->describeContainerDefinition($builder->getDefinition((string) $alias), array_merge($options, ['id' => (string) $alias])); - } - - protected function describeContainerParameter($parameter, array $options = []) - { - $options['output']->table( - ['Parameter', 'Value'], - [ - [$options['parameter'], $this->formatParameter($parameter), - ], - ]); - } - - protected function describeContainerEnvVars(array $envs, array $options = []) - { - $dump = new Dumper($this->output); - $options['output']->title('Symfony Container Environment Variables'); - - if (null !== $name = $options['name'] ?? null) { - $options['output']->comment('Displaying detailed environment variable usage matching '.$name); - - $matches = false; - foreach ($envs as $env) { - if ($name === $env['name'] || false !== stripos($env['name'], $name)) { - $matches = true; - $options['output']->section('%env('.$env['processor'].':'.$env['name'].')%'); - $options['output']->table([], [ - ['<info>Default value</>', $env['default_available'] ? $dump($env['default_value']) : 'n/a'], - ['<info>Real value</>', $env['runtime_available'] ? $dump($env['runtime_value']) : 'n/a'], - ['<info>Processed value</>', $env['default_available'] || $env['runtime_available'] ? $dump($env['processed_value']) : 'n/a'], - ]); - } - } - - if (!$matches) { - $options['output']->block('None of the environment variables match this name.'); - } else { - $options['output']->comment('Note real values might be different between web and CLI.'); - } - - return; - } - - if (!$envs) { - $options['output']->block('No environment variables are being used.'); - - return; - } - - $rows = []; - $missing = []; - foreach ($envs as $env) { - if (isset($rows[$env['name']])) { - continue; - } - - $rows[$env['name']] = [ - $env['name'], - $env['default_available'] ? $dump($env['default_value']) : 'n/a', - $env['runtime_available'] ? $dump($env['runtime_value']) : 'n/a', - ]; - if (!$env['default_available'] && !$env['runtime_available']) { - $missing[$env['name']] = true; - } - } - - $options['output']->table(['Name', 'Default value', 'Real value'], $rows); - $options['output']->comment('Note real values might be different between web and CLI.'); - - if ($missing) { - $options['output']->warning('The following variables are missing:'); - $options['output']->listing(array_keys($missing)); - } - } - - protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = []) - { - $event = $options['event'] ?? null; - $dispatcherServiceName = $options['dispatcher_service_name'] ?? null; - - $title = 'Registered Listeners'; - - if (null !== $dispatcherServiceName) { - $title .= sprintf(' of Event Dispatcher "%s"', $dispatcherServiceName); - } - - if (null !== $event) { - $title .= sprintf(' for "%s" Event', $event); - $registeredListeners = $eventDispatcher->getListeners($event); - } else { - $title .= ' Grouped by Event'; - // Try to see if "events" exists - $registeredListeners = \array_key_exists('events', $options) ? array_combine($options['events'], array_map(function ($event) use ($eventDispatcher) { return $eventDispatcher->getListeners($event); }, $options['events'])) : $eventDispatcher->getListeners(); - } - - $options['output']->title($title); - if (null !== $event) { - $this->renderEventListenerTable($eventDispatcher, $event, $registeredListeners, $options['output']); - } else { - ksort($registeredListeners); - foreach ($registeredListeners as $eventListened => $eventListeners) { - $options['output']->section(sprintf('"%s" event', $eventListened)); - $this->renderEventListenerTable($eventDispatcher, $eventListened, $eventListeners, $options['output']); - } - } - } - - protected function describeCallable($callable, array $options = []) - { - $this->writeText($this->formatCallable($callable), $options); - } - - private function renderEventListenerTable(EventDispatcherInterface $eventDispatcher, string $event, array $eventListeners, SymfonyStyle $io) - { - $tableHeaders = ['Order', 'Callable', 'Priority']; - $tableRows = []; - - foreach ($eventListeners as $order => $listener) { - $tableRows[] = [sprintf('#%d', $order + 1), $this->formatCallable($listener), $eventDispatcher->getListenerPriority($event, $listener)]; - } - - $io->table($tableHeaders, $tableRows); - } - - private function formatRouterConfig(array $config): string - { - if (empty($config)) { - return 'NONE'; - } - - ksort($config); - - $configAsString = ''; - foreach ($config as $key => $value) { - $configAsString .= sprintf("\n%s: %s", $key, $this->formatValue($value)); - } - - return trim($configAsString); - } - - private function formatControllerLink($controller, string $anchorText, callable $getContainer = null): string - { - if (null === $this->fileLinkFormatter) { - return $anchorText; - } - - try { - if (null === $controller) { - return $anchorText; - } elseif (\is_array($controller)) { - $r = new \ReflectionMethod($controller[0], $controller[1]); - } elseif ($controller instanceof \Closure) { - $r = new \ReflectionFunction($controller); - } elseif (method_exists($controller, '__invoke')) { - $r = new \ReflectionMethod($controller, '__invoke'); - } elseif (!\is_string($controller)) { - return $anchorText; - } elseif (str_contains($controller, '::')) { - $r = new \ReflectionMethod($controller); - } else { - $r = new \ReflectionFunction($controller); - } - } catch (\ReflectionException $e) { - if (\is_array($controller)) { - $controller = implode('::', $controller); - } - - $id = $controller; - $method = '__invoke'; - - if ($pos = strpos($controller, '::')) { - $id = substr($controller, 0, $pos); - $method = substr($controller, $pos + 2); - } - - if (!$getContainer || !($container = $getContainer()) || !$container->has($id)) { - return $anchorText; - } - - try { - $r = new \ReflectionMethod($container->findDefinition($id)->getClass(), $method); - } catch (\ReflectionException $e) { - return $anchorText; - } - } - - $fileLink = $this->fileLinkFormatter->format($r->getFileName(), $r->getStartLine()); - if ($fileLink) { - return sprintf('<href=%s>%s</>', $fileLink, $anchorText); - } - - return $anchorText; - } - - private function formatCallable($callable): string - { - if (\is_array($callable)) { - if (\is_object($callable[0])) { - return sprintf('%s::%s()', \get_class($callable[0]), $callable[1]); - } - - return sprintf('%s::%s()', $callable[0], $callable[1]); - } - - if (\is_string($callable)) { - return sprintf('%s()', $callable); - } - - if ($callable instanceof \Closure) { - $r = new \ReflectionFunction($callable); - if (str_contains($r->name, '{closure}')) { - return 'Closure()'; - } - if ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) { - return sprintf('%s::%s()', $class->name, $r->name); - } - - return $r->name.'()'; - } - - if (method_exists($callable, '__invoke')) { - return sprintf('%s::__invoke()', \get_class($callable)); - } - - throw new \InvalidArgumentException('Callable is not describable.'); - } - - 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 - ); - } -} diff --git a/lib/symfony/framework-bundle/Console/Descriptor/XmlDescriptor.php b/lib/symfony/framework-bundle/Console/Descriptor/XmlDescriptor.php deleted file mode 100644 index 350452f33..000000000 --- a/lib/symfony/framework-bundle/Console/Descriptor/XmlDescriptor.php +++ /dev/null @@ -1,570 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Console\Descriptor; - -use Symfony\Component\Console\Exception\LogicException; -use Symfony\Component\Console\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\AbstractArgument; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class XmlDescriptor extends Descriptor -{ - protected function describeRouteCollection(RouteCollection $routes, array $options = []) - { - $this->writeDocument($this->getRouteCollectionDocument($routes)); - } - - protected function describeRoute(Route $route, array $options = []) - { - $this->writeDocument($this->getRouteDocument($route, $options['name'] ?? null)); - } - - protected function describeContainerParameters(ParameterBag $parameters, array $options = []) - { - $this->writeDocument($this->getContainerParametersDocument($parameters)); - } - - protected function describeContainerTags(ContainerBuilder $builder, array $options = []) - { - $this->writeDocument($this->getContainerTagsDocument($builder, isset($options['show_hidden']) && $options['show_hidden'])); - } - - protected function describeContainerService(object $service, array $options = [], ContainerBuilder $builder = null) - { - if (!isset($options['id'])) { - throw new \InvalidArgumentException('An "id" option must be provided.'); - } - - $this->writeDocument($this->getContainerServiceDocument($service, $options['id'], $builder, isset($options['show_arguments']) && $options['show_arguments'])); - } - - protected function describeContainerServices(ContainerBuilder $builder, array $options = []) - { - $this->writeDocument($this->getContainerServicesDocument($builder, $options['tag'] ?? null, isset($options['show_hidden']) && $options['show_hidden'], isset($options['show_arguments']) && $options['show_arguments'], $options['filter'] ?? null)); - } - - protected function describeContainerDefinition(Definition $definition, array $options = []) - { - $this->writeDocument($this->getContainerDefinitionDocument($definition, $options['id'] ?? null, isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments'])); - } - - protected function describeContainerAlias(Alias $alias, array $options = [], ContainerBuilder $builder = null) - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($dom->importNode($this->getContainerAliasDocument($alias, $options['id'] ?? null)->childNodes->item(0), true)); - - if (!$builder) { - $this->writeDocument($dom); - - return; - } - - $dom->appendChild($dom->importNode($this->getContainerDefinitionDocument($builder->getDefinition((string) $alias), (string) $alias)->childNodes->item(0), true)); - - $this->writeDocument($dom); - } - - protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = []) - { - $this->writeDocument($this->getEventDispatcherListenersDocument($eventDispatcher, $options)); - } - - protected function describeCallable($callable, array $options = []) - { - $this->writeDocument($this->getCallableDocument($callable)); - } - - protected function describeContainerParameter($parameter, array $options = []) - { - $this->writeDocument($this->getContainerParameterDocument($parameter, $options)); - } - - protected function describeContainerEnvVars(array $envs, array $options = []) - { - throw new LogicException('Using the XML format to debug environment variables is not supported.'); - } - - protected function describeContainerDeprecations(ContainerBuilder $builder, array $options = []): void - { - $containerDeprecationFilePath = sprintf('%s/%sDeprecations.log', $builder->getParameter('kernel.build_dir'), $builder->getParameter('kernel.container_class')); - if (!file_exists($containerDeprecationFilePath)) { - throw new RuntimeException('The deprecation file does not exist, please try warming the cache first.'); - } - - $logs = unserialize(file_get_contents($containerDeprecationFilePath)); - - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($deprecationsXML = $dom->createElement('deprecations')); - - $formattedLogs = []; - $remainingCount = 0; - foreach ($logs as $log) { - $deprecationsXML->appendChild($deprecationXML = $dom->createElement('deprecation')); - $deprecationXML->setAttribute('count', $log['count']); - $deprecationXML->appendChild($dom->createElement('message', $log['message'])); - $deprecationXML->appendChild($dom->createElement('file', $log['file'])); - $deprecationXML->appendChild($dom->createElement('line', $log['line'])); - $remainingCount += $log['count']; - } - - $deprecationsXML->setAttribute('remainingCount', $remainingCount); - - $this->writeDocument($dom); - } - - private function writeDocument(\DOMDocument $dom) - { - $dom->formatOutput = true; - $this->write($dom->saveXML()); - } - - private function getRouteCollectionDocument(RouteCollection $routes): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($routesXML = $dom->createElement('routes')); - - foreach ($routes->all() as $name => $route) { - $routeXML = $this->getRouteDocument($route, $name); - $routesXML->appendChild($routesXML->ownerDocument->importNode($routeXML->childNodes->item(0), true)); - } - - return $dom; - } - - private function getRouteDocument(Route $route, string $name = null): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($routeXML = $dom->createElement('route')); - - if ($name) { - $routeXML->setAttribute('name', $name); - } - - $routeXML->setAttribute('class', \get_class($route)); - - $routeXML->appendChild($pathXML = $dom->createElement('path')); - $pathXML->setAttribute('regex', $route->compile()->getRegex()); - $pathXML->appendChild(new \DOMText($route->getPath())); - - if ('' !== $route->getHost()) { - $routeXML->appendChild($hostXML = $dom->createElement('host')); - $hostXML->setAttribute('regex', $route->compile()->getHostRegex()); - $hostXML->appendChild(new \DOMText($route->getHost())); - } - - foreach ($route->getSchemes() as $scheme) { - $routeXML->appendChild($schemeXML = $dom->createElement('scheme')); - $schemeXML->appendChild(new \DOMText($scheme)); - } - - foreach ($route->getMethods() as $method) { - $routeXML->appendChild($methodXML = $dom->createElement('method')); - $methodXML->appendChild(new \DOMText($method)); - } - - if ($route->getDefaults()) { - $routeXML->appendChild($defaultsXML = $dom->createElement('defaults')); - foreach ($route->getDefaults() as $attribute => $value) { - $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); - $defaultXML->setAttribute('key', $attribute); - $defaultXML->appendChild(new \DOMText($this->formatValue($value))); - } - } - - $originRequirements = $requirements = $route->getRequirements(); - unset($requirements['_scheme'], $requirements['_method']); - if ($requirements) { - $routeXML->appendChild($requirementsXML = $dom->createElement('requirements')); - foreach ($originRequirements as $attribute => $pattern) { - $requirementsXML->appendChild($requirementXML = $dom->createElement('requirement')); - $requirementXML->setAttribute('key', $attribute); - $requirementXML->appendChild(new \DOMText($pattern)); - } - } - - if ($route->getOptions()) { - $routeXML->appendChild($optionsXML = $dom->createElement('options')); - foreach ($route->getOptions() as $name => $value) { - $optionsXML->appendChild($optionXML = $dom->createElement('option')); - $optionXML->setAttribute('key', $name); - $optionXML->appendChild(new \DOMText($this->formatValue($value))); - } - } - - if ('' !== $route->getCondition()) { - $routeXML->appendChild($conditionXML = $dom->createElement('condition')); - $conditionXML->appendChild(new \DOMText($route->getCondition())); - } - - return $dom; - } - - private function getContainerParametersDocument(ParameterBag $parameters): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($parametersXML = $dom->createElement('parameters')); - - foreach ($this->sortParameters($parameters) as $key => $value) { - $parametersXML->appendChild($parameterXML = $dom->createElement('parameter')); - $parameterXML->setAttribute('key', $key); - $parameterXML->appendChild(new \DOMText($this->formatParameter($value))); - } - - return $dom; - } - - private function getContainerTagsDocument(ContainerBuilder $builder, bool $showHidden = false): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($containerXML = $dom->createElement('container')); - - foreach ($this->findDefinitionsByTag($builder, $showHidden) as $tag => $definitions) { - $containerXML->appendChild($tagXML = $dom->createElement('tag')); - $tagXML->setAttribute('name', $tag); - - foreach ($definitions as $serviceId => $definition) { - $definitionXML = $this->getContainerDefinitionDocument($definition, $serviceId, true); - $tagXML->appendChild($dom->importNode($definitionXML->childNodes->item(0), true)); - } - } - - return $dom; - } - - private function getContainerServiceDocument(object $service, string $id, ContainerBuilder $builder = null, bool $showArguments = false): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - - if ($service instanceof Alias) { - $dom->appendChild($dom->importNode($this->getContainerAliasDocument($service, $id)->childNodes->item(0), true)); - if ($builder) { - $dom->appendChild($dom->importNode($this->getContainerDefinitionDocument($builder->getDefinition((string) $service), (string) $service, false, $showArguments)->childNodes->item(0), true)); - } - } elseif ($service instanceof Definition) { - $dom->appendChild($dom->importNode($this->getContainerDefinitionDocument($service, $id, false, $showArguments)->childNodes->item(0), true)); - } else { - $dom->appendChild($serviceXML = $dom->createElement('service')); - $serviceXML->setAttribute('id', $id); - $serviceXML->setAttribute('class', \get_class($service)); - } - - return $dom; - } - - private function getContainerServicesDocument(ContainerBuilder $builder, string $tag = null, bool $showHidden = false, bool $showArguments = false, callable $filter = null): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($containerXML = $dom->createElement('container')); - - $serviceIds = $tag - ? $this->sortTaggedServicesByPriority($builder->findTaggedServiceIds($tag)) - : $this->sortServiceIds($builder->getServiceIds()); - if ($filter) { - $serviceIds = array_filter($serviceIds, $filter); - } - - foreach ($serviceIds as $serviceId) { - $service = $this->resolveServiceDefinition($builder, $serviceId); - - if ($showHidden xor '.' === ($serviceId[0] ?? null)) { - continue; - } - - $serviceXML = $this->getContainerServiceDocument($service, $serviceId, null, $showArguments); - $containerXML->appendChild($containerXML->ownerDocument->importNode($serviceXML->childNodes->item(0), true)); - } - - return $dom; - } - - private function getContainerDefinitionDocument(Definition $definition, string $id = null, bool $omitTags = false, bool $showArguments = false): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($serviceXML = $dom->createElement('definition')); - - if ($id) { - $serviceXML->setAttribute('id', $id); - } - - if ('' !== $classDescription = $this->getClassDescription((string) $definition->getClass())) { - $serviceXML->appendChild($descriptionXML = $dom->createElement('description')); - $descriptionXML->appendChild($dom->createCDATASection($classDescription)); - } - - $serviceXML->setAttribute('class', $definition->getClass() ?? ''); - - if ($factory = $definition->getFactory()) { - $serviceXML->appendChild($factoryXML = $dom->createElement('factory')); - - if (\is_array($factory)) { - if ($factory[0] instanceof Reference) { - $factoryXML->setAttribute('service', (string) $factory[0]); - } elseif ($factory[0] instanceof Definition) { - $factoryXML->setAttribute('service', sprintf('inline factory service (%s)', $factory[0]->getClass() ?? 'not configured')); - } else { - $factoryXML->setAttribute('class', $factory[0]); - } - $factoryXML->setAttribute('method', $factory[1]); - } else { - $factoryXML->setAttribute('function', $factory); - } - } - - $serviceXML->setAttribute('public', $definition->isPublic() && !$definition->isPrivate() ? 'true' : 'false'); - $serviceXML->setAttribute('synthetic', $definition->isSynthetic() ? 'true' : 'false'); - $serviceXML->setAttribute('lazy', $definition->isLazy() ? 'true' : 'false'); - $serviceXML->setAttribute('shared', $definition->isShared() ? 'true' : 'false'); - $serviceXML->setAttribute('abstract', $definition->isAbstract() ? 'true' : 'false'); - $serviceXML->setAttribute('autowired', $definition->isAutowired() ? 'true' : 'false'); - $serviceXML->setAttribute('autoconfigured', $definition->isAutoconfigured() ? 'true' : 'false'); - $serviceXML->setAttribute('file', $definition->getFile() ?? ''); - - $calls = $definition->getMethodCalls(); - if (\count($calls) > 0) { - $serviceXML->appendChild($callsXML = $dom->createElement('calls')); - foreach ($calls as $callData) { - $callsXML->appendChild($callXML = $dom->createElement('call')); - $callXML->setAttribute('method', $callData[0]); - if ($callData[2] ?? false) { - $callXML->setAttribute('returns-clone', 'true'); - } - } - } - - if ($showArguments) { - foreach ($this->getArgumentNodes($definition->getArguments(), $dom) as $node) { - $serviceXML->appendChild($node); - } - } - - if (!$omitTags) { - if ($tags = $this->sortTagsByPriority($definition->getTags())) { - $serviceXML->appendChild($tagsXML = $dom->createElement('tags')); - foreach ($tags as $tagName => $tagData) { - foreach ($tagData as $parameters) { - $tagsXML->appendChild($tagXML = $dom->createElement('tag')); - $tagXML->setAttribute('name', $tagName); - foreach ($parameters as $name => $value) { - $tagXML->appendChild($parameterXML = $dom->createElement('parameter')); - $parameterXML->setAttribute('name', $name); - $parameterXML->appendChild(new \DOMText($this->formatParameter($value))); - } - } - } - } - } - - return $dom; - } - - /** - * @return \DOMNode[] - */ - private function getArgumentNodes(array $arguments, \DOMDocument $dom): array - { - $nodes = []; - - foreach ($arguments as $argumentKey => $argument) { - $argumentXML = $dom->createElement('argument'); - - if (\is_string($argumentKey)) { - $argumentXML->setAttribute('key', $argumentKey); - } - - if ($argument instanceof ServiceClosureArgument) { - $argument = $argument->getValues()[0]; - } - - if ($argument instanceof Reference) { - $argumentXML->setAttribute('type', 'service'); - $argumentXML->setAttribute('id', (string) $argument); - } elseif ($argument instanceof IteratorArgument || $argument instanceof ServiceLocatorArgument) { - $argumentXML->setAttribute('type', $argument instanceof IteratorArgument ? 'iterator' : 'service_locator'); - - foreach ($this->getArgumentNodes($argument->getValues(), $dom) as $childArgumentXML) { - $argumentXML->appendChild($childArgumentXML); - } - } elseif ($argument instanceof Definition) { - $argumentXML->appendChild($dom->importNode($this->getContainerDefinitionDocument($argument, null, false, true)->childNodes->item(0), true)); - } elseif ($argument instanceof AbstractArgument) { - $argumentXML->setAttribute('type', 'abstract'); - $argumentXML->appendChild(new \DOMText($argument->getText())); - } elseif (\is_array($argument)) { - $argumentXML->setAttribute('type', 'collection'); - - foreach ($this->getArgumentNodes($argument, $dom) as $childArgumentXML) { - $argumentXML->appendChild($childArgumentXML); - } - } elseif ($argument instanceof \UnitEnum) { - $argumentXML->setAttribute('type', 'constant'); - $argumentXML->appendChild(new \DOMText(ltrim(var_export($argument, true), '\\'))); - } else { - $argumentXML->appendChild(new \DOMText($argument)); - } - - $nodes[] = $argumentXML; - } - - return $nodes; - } - - private function getContainerAliasDocument(Alias $alias, string $id = null): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($aliasXML = $dom->createElement('alias')); - - if ($id) { - $aliasXML->setAttribute('id', $id); - } - - $aliasXML->setAttribute('service', (string) $alias); - $aliasXML->setAttribute('public', $alias->isPublic() && !$alias->isPrivate() ? 'true' : 'false'); - - return $dom; - } - - private function getContainerParameterDocument($parameter, array $options = []): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($parameterXML = $dom->createElement('parameter')); - - if (isset($options['parameter'])) { - $parameterXML->setAttribute('key', $options['parameter']); - } - - $parameterXML->appendChild(new \DOMText($this->formatParameter($parameter))); - - return $dom; - } - - private function getEventDispatcherListenersDocument(EventDispatcherInterface $eventDispatcher, array $options): \DOMDocument - { - $event = \array_key_exists('event', $options) ? $options['event'] : null; - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($eventDispatcherXML = $dom->createElement('event-dispatcher')); - - if (null !== $event) { - $registeredListeners = $eventDispatcher->getListeners($event); - $this->appendEventListenerDocument($eventDispatcher, $event, $eventDispatcherXML, $registeredListeners); - } else { - // Try to see if "events" exists - $registeredListeners = \array_key_exists('events', $options) ? array_combine($options['events'], array_map(function ($event) use ($eventDispatcher) { return $eventDispatcher->getListeners($event); }, $options['events'])) : $eventDispatcher->getListeners(); - ksort($registeredListeners); - - foreach ($registeredListeners as $eventListened => $eventListeners) { - $eventDispatcherXML->appendChild($eventXML = $dom->createElement('event')); - $eventXML->setAttribute('name', $eventListened); - - $this->appendEventListenerDocument($eventDispatcher, $eventListened, $eventXML, $eventListeners); - } - } - - return $dom; - } - - private function appendEventListenerDocument(EventDispatcherInterface $eventDispatcher, string $event, \DOMElement $element, array $eventListeners) - { - foreach ($eventListeners as $listener) { - $callableXML = $this->getCallableDocument($listener); - $callableXML->childNodes->item(0)->setAttribute('priority', $eventDispatcher->getListenerPriority($event, $listener)); - - $element->appendChild($element->ownerDocument->importNode($callableXML->childNodes->item(0), true)); - } - } - - private function getCallableDocument($callable): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($callableXML = $dom->createElement('callable')); - - if (\is_array($callable)) { - $callableXML->setAttribute('type', 'function'); - - if (\is_object($callable[0])) { - $callableXML->setAttribute('name', $callable[1]); - $callableXML->setAttribute('class', \get_class($callable[0])); - } else { - if (!str_starts_with($callable[1], 'parent::')) { - $callableXML->setAttribute('name', $callable[1]); - $callableXML->setAttribute('class', $callable[0]); - $callableXML->setAttribute('static', 'true'); - } else { - $callableXML->setAttribute('name', substr($callable[1], 8)); - $callableXML->setAttribute('class', $callable[0]); - $callableXML->setAttribute('static', 'true'); - $callableXML->setAttribute('parent', 'true'); - } - } - - return $dom; - } - - if (\is_string($callable)) { - $callableXML->setAttribute('type', 'function'); - - if (!str_contains($callable, '::')) { - $callableXML->setAttribute('name', $callable); - } else { - $callableParts = explode('::', $callable); - - $callableXML->setAttribute('name', $callableParts[1]); - $callableXML->setAttribute('class', $callableParts[0]); - $callableXML->setAttribute('static', 'true'); - } - - return $dom; - } - - if ($callable instanceof \Closure) { - $callableXML->setAttribute('type', 'closure'); - - $r = new \ReflectionFunction($callable); - if (str_contains($r->name, '{closure}')) { - return $dom; - } - $callableXML->setAttribute('name', $r->name); - - if ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) { - $callableXML->setAttribute('class', $class->name); - if (!$r->getClosureThis()) { - $callableXML->setAttribute('static', 'true'); - } - } - - return $dom; - } - - if (method_exists($callable, '__invoke')) { - $callableXML->setAttribute('type', 'object'); - $callableXML->setAttribute('name', \get_class($callable)); - - return $dom; - } - - throw new \InvalidArgumentException('Callable is not describable.'); - } -} diff --git a/lib/symfony/framework-bundle/Console/Helper/DescriptorHelper.php b/lib/symfony/framework-bundle/Console/Helper/DescriptorHelper.php deleted file mode 100644 index 1f17c9994..000000000 --- a/lib/symfony/framework-bundle/Console/Helper/DescriptorHelper.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Console\Helper; - -use Symfony\Bundle\FrameworkBundle\Console\Descriptor\JsonDescriptor; -use Symfony\Bundle\FrameworkBundle\Console\Descriptor\MarkdownDescriptor; -use Symfony\Bundle\FrameworkBundle\Console\Descriptor\TextDescriptor; -use Symfony\Bundle\FrameworkBundle\Console\Descriptor\XmlDescriptor; -use Symfony\Component\Console\Helper\DescriptorHelper as BaseDescriptorHelper; -use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; - -/** - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - * - * @internal - */ -class DescriptorHelper extends BaseDescriptorHelper -{ - public function __construct(FileLinkFormatter $fileLinkFormatter = null) - { - $this - ->register('txt', new TextDescriptor($fileLinkFormatter)) - ->register('xml', new XmlDescriptor()) - ->register('json', new JsonDescriptor()) - ->register('md', new MarkdownDescriptor()) - ; - } -} diff --git a/lib/symfony/framework-bundle/Controller/AbstractController.php b/lib/symfony/framework-bundle/Controller/AbstractController.php deleted file mode 100644 index f6eff3f61..000000000 --- a/lib/symfony/framework-bundle/Controller/AbstractController.php +++ /dev/null @@ -1,476 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Controller; - -use Doctrine\Persistence\ManagerRegistry; -use Psr\Container\ContainerInterface; -use Psr\Link\LinkInterface; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; -use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface; -use Symfony\Component\Form\Extension\Core\Type\FormType; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormFactoryInterface; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormView; -use Symfony\Component\HttpFoundation\BinaryFileResponse; -use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException; -use Symfony\Component\HttpFoundation\JsonResponse; -use Symfony\Component\HttpFoundation\RedirectResponse; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpFoundation\ResponseHeaderBag; -use Symfony\Component\HttpFoundation\Session\SessionInterface; -use Symfony\Component\HttpFoundation\StreamedResponse; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Component\Messenger\Envelope; -use Symfony\Component\Messenger\MessageBusInterface; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; -use Symfony\Component\Routing\RouterInterface; -use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; -use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; -use Symfony\Component\Security\Core\Exception\AccessDeniedException; -use Symfony\Component\Security\Core\User\UserInterface; -use Symfony\Component\Security\Csrf\CsrfToken; -use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; -use Symfony\Component\Serializer\SerializerInterface; -use Symfony\Component\WebLink\EventListener\AddLinkHeaderListener; -use Symfony\Component\WebLink\GenericLinkProvider; -use Symfony\Contracts\Service\ServiceSubscriberInterface; -use Twig\Environment; - -/** - * Provides shortcuts for HTTP-related features in controllers. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -abstract class AbstractController implements ServiceSubscriberInterface -{ - /** - * @var ContainerInterface - */ - protected $container; - - /** - * @required - */ - public function setContainer(ContainerInterface $container): ?ContainerInterface - { - $previous = $this->container; - $this->container = $container; - - return $previous; - } - - /** - * Gets a container parameter by its name. - * - * @return array|bool|float|int|string|\UnitEnum|null - */ - protected function getParameter(string $name) - { - if (!$this->container->has('parameter_bag')) { - throw new ServiceNotFoundException('parameter_bag.', null, null, [], sprintf('The "%s::getParameter()" method is missing a parameter bag to work properly. Did you forget to register your controller as a service subscriber? This can be fixed either by using autoconfiguration or by manually wiring a "parameter_bag" in the service locator passed to the controller.', static::class)); - } - - return $this->container->get('parameter_bag')->get($name); - } - - public static function getSubscribedServices() - { - return [ - 'router' => '?'.RouterInterface::class, - 'request_stack' => '?'.RequestStack::class, - 'http_kernel' => '?'.HttpKernelInterface::class, - 'serializer' => '?'.SerializerInterface::class, - 'session' => '?'.SessionInterface::class, - 'security.authorization_checker' => '?'.AuthorizationCheckerInterface::class, - 'twig' => '?'.Environment::class, - 'doctrine' => '?'.ManagerRegistry::class, // to be removed in 6.0 - 'form.factory' => '?'.FormFactoryInterface::class, - 'security.token_storage' => '?'.TokenStorageInterface::class, - 'security.csrf.token_manager' => '?'.CsrfTokenManagerInterface::class, - 'parameter_bag' => '?'.ContainerBagInterface::class, - 'message_bus' => '?'.MessageBusInterface::class, // to be removed in 6.0 - 'messenger.default_bus' => '?'.MessageBusInterface::class, // to be removed in 6.0 - ]; - } - - /** - * Returns true if the service id is defined. - * - * @deprecated since Symfony 5.4, use method or constructor injection in your controller instead - */ - protected function has(string $id): bool - { - trigger_deprecation('symfony/framework-bundle', '5.4', 'Method "%s()" is deprecated, use method or constructor injection in your controller instead.', __METHOD__); - - return $this->container->has($id); - } - - /** - * Gets a container service by its id. - * - * @return object The service - * - * @deprecated since Symfony 5.4, use method or constructor injection in your controller instead - */ - protected function get(string $id): object - { - trigger_deprecation('symfony/framework-bundle', '5.4', 'Method "%s()" is deprecated, use method or constructor injection in your controller instead.', __METHOD__); - - return $this->container->get($id); - } - - /** - * Generates a URL from the given parameters. - * - * @see UrlGeneratorInterface - */ - protected function generateUrl(string $route, array $parameters = [], int $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH): string - { - return $this->container->get('router')->generate($route, $parameters, $referenceType); - } - - /** - * Forwards the request to another controller. - * - * @param string $controller The controller name (a string like Bundle\BlogBundle\Controller\PostController::indexAction) - */ - protected function forward(string $controller, array $path = [], array $query = []): Response - { - $request = $this->container->get('request_stack')->getCurrentRequest(); - $path['_controller'] = $controller; - $subRequest = $request->duplicate($query, null, $path); - - return $this->container->get('http_kernel')->handle($subRequest, HttpKernelInterface::SUB_REQUEST); - } - - /** - * Returns a RedirectResponse to the given URL. - */ - protected function redirect(string $url, int $status = 302): RedirectResponse - { - return new RedirectResponse($url, $status); - } - - /** - * Returns a RedirectResponse to the given route with the given parameters. - */ - protected function redirectToRoute(string $route, array $parameters = [], int $status = 302): RedirectResponse - { - return $this->redirect($this->generateUrl($route, $parameters), $status); - } - - /** - * Returns a JsonResponse that uses the serializer component if enabled, or json_encode. - */ - protected function json($data, int $status = 200, array $headers = [], array $context = []): JsonResponse - { - if ($this->container->has('serializer')) { - $json = $this->container->get('serializer')->serialize($data, 'json', array_merge([ - 'json_encode_options' => JsonResponse::DEFAULT_ENCODING_OPTIONS, - ], $context)); - - return new JsonResponse($json, $status, $headers, true); - } - - return new JsonResponse($data, $status, $headers); - } - - /** - * Returns a BinaryFileResponse object with original or customized file name and disposition header. - * - * @param \SplFileInfo|string $file File object or path to file to be sent as response - */ - protected function file($file, string $fileName = null, string $disposition = ResponseHeaderBag::DISPOSITION_ATTACHMENT): BinaryFileResponse - { - $response = new BinaryFileResponse($file); - $response->setContentDisposition($disposition, null === $fileName ? $response->getFile()->getFilename() : $fileName); - - return $response; - } - - /** - * Adds a flash message to the current session for type. - * - * @throws \LogicException - */ - protected function addFlash(string $type, $message): void - { - try { - $this->container->get('request_stack')->getSession()->getFlashBag()->add($type, $message); - } catch (SessionNotFoundException $e) { - throw new \LogicException('You cannot use the addFlash method if sessions are disabled. Enable them in "config/packages/framework.yaml".', 0, $e); - } - } - - /** - * Checks if the attribute is granted against the current authentication token and optionally supplied subject. - * - * @throws \LogicException - */ - protected function isGranted($attribute, $subject = null): bool - { - if (!$this->container->has('security.authorization_checker')) { - throw new \LogicException('The SecurityBundle is not registered in your application. Try running "composer require symfony/security-bundle".'); - } - - return $this->container->get('security.authorization_checker')->isGranted($attribute, $subject); - } - - /** - * Throws an exception unless the attribute is granted against the current authentication token and optionally - * supplied subject. - * - * @throws AccessDeniedException - */ - protected function denyAccessUnlessGranted($attribute, $subject = null, string $message = 'Access Denied.'): void - { - if (!$this->isGranted($attribute, $subject)) { - $exception = $this->createAccessDeniedException($message); - $exception->setAttributes($attribute); - $exception->setSubject($subject); - - throw $exception; - } - } - - /** - * Returns a rendered view. - */ - protected function renderView(string $view, array $parameters = []): string - { - if (!$this->container->has('twig')) { - throw new \LogicException('You cannot use the "renderView" method if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".'); - } - - return $this->container->get('twig')->render($view, $parameters); - } - - /** - * Renders a view. - */ - protected function render(string $view, array $parameters = [], Response $response = null): Response - { - $content = $this->renderView($view, $parameters); - - if (null === $response) { - $response = new Response(); - } - - $response->setContent($content); - - return $response; - } - - /** - * Renders a view and sets the appropriate status code when a form is listed in parameters. - * - * If an invalid form is found in the list of parameters, a 422 status code is returned. - */ - protected function renderForm(string $view, array $parameters = [], Response $response = null): Response - { - if (null === $response) { - $response = new Response(); - } - - foreach ($parameters as $k => $v) { - if ($v instanceof FormView) { - throw new \LogicException(sprintf('Passing a FormView to "%s::renderForm()" is not supported, pass directly the form instead for parameter "%s".', get_debug_type($this), $k)); - } - - if (!$v instanceof FormInterface) { - continue; - } - - $parameters[$k] = $v->createView(); - - if (200 === $response->getStatusCode() && $v->isSubmitted() && !$v->isValid()) { - $response->setStatusCode(422); - } - } - - return $this->render($view, $parameters, $response); - } - - /** - * Streams a view. - */ - protected function stream(string $view, array $parameters = [], StreamedResponse $response = null): StreamedResponse - { - if (!$this->container->has('twig')) { - throw new \LogicException('You cannot use the "stream" method if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".'); - } - - $twig = $this->container->get('twig'); - - $callback = function () use ($twig, $view, $parameters) { - $twig->display($view, $parameters); - }; - - if (null === $response) { - return new StreamedResponse($callback); - } - - $response->setCallback($callback); - - return $response; - } - - /** - * Returns a NotFoundHttpException. - * - * This will result in a 404 response code. Usage example: - * - * throw $this->createNotFoundException('Page not found!'); - */ - protected function createNotFoundException(string $message = 'Not Found', \Throwable $previous = null): NotFoundHttpException - { - return new NotFoundHttpException($message, $previous); - } - - /** - * Returns an AccessDeniedException. - * - * This will result in a 403 response code. Usage example: - * - * throw $this->createAccessDeniedException('Unable to access this page!'); - * - * @throws \LogicException If the Security component is not available - */ - protected function createAccessDeniedException(string $message = 'Access Denied.', \Throwable $previous = null): AccessDeniedException - { - if (!class_exists(AccessDeniedException::class)) { - throw new \LogicException('You cannot use the "createAccessDeniedException" method if the Security component is not available. Try running "composer require symfony/security-bundle".'); - } - - return new AccessDeniedException($message, $previous); - } - - /** - * Creates and returns a Form instance from the type of the form. - */ - protected function createForm(string $type, $data = null, array $options = []): FormInterface - { - return $this->container->get('form.factory')->create($type, $data, $options); - } - - /** - * Creates and returns a form builder instance. - */ - protected function createFormBuilder($data = null, array $options = []): FormBuilderInterface - { - return $this->container->get('form.factory')->createBuilder(FormType::class, $data, $options); - } - - /** - * Shortcut to return the Doctrine Registry service. - * - * @throws \LogicException If DoctrineBundle is not available - * - * @deprecated since Symfony 5.4, inject an instance of ManagerRegistry in your controller instead - */ - protected function getDoctrine(): ManagerRegistry - { - trigger_deprecation('symfony/framework-bundle', '5.4', 'Method "%s()" is deprecated, inject an instance of ManagerRegistry in your controller instead.', __METHOD__); - - if (!$this->container->has('doctrine')) { - throw new \LogicException('The DoctrineBundle is not registered in your application. Try running "composer require symfony/orm-pack".'); - } - - return $this->container->get('doctrine'); - } - - /** - * Get a user from the Security Token Storage. - * - * @return UserInterface|null - * - * @throws \LogicException If SecurityBundle is not available - * - * @see TokenInterface::getUser() - */ - protected function getUser() - { - if (!$this->container->has('security.token_storage')) { - throw new \LogicException('The SecurityBundle is not registered in your application. Try running "composer require symfony/security-bundle".'); - } - - if (null === $token = $this->container->get('security.token_storage')->getToken()) { - return null; - } - - // @deprecated since 5.4, $user will always be a UserInterface instance - if (!\is_object($user = $token->getUser())) { - // e.g. anonymous authentication - return null; - } - - return $user; - } - - /** - * Checks the validity of a CSRF token. - * - * @param string $id The id used when generating the token - * @param string|null $token The actual token sent with the request that should be validated - */ - protected function isCsrfTokenValid(string $id, ?string $token): bool - { - if (!$this->container->has('security.csrf.token_manager')) { - throw new \LogicException('CSRF protection is not enabled in your application. Enable it with the "csrf_protection" key in "config/packages/framework.yaml".'); - } - - return $this->container->get('security.csrf.token_manager')->isTokenValid(new CsrfToken($id, $token)); - } - - /** - * Dispatches a message to the bus. - * - * @param object|Envelope $message The message or the message pre-wrapped in an envelope - * - * @deprecated since Symfony 5.4, inject an instance of MessageBusInterface in your controller instead - */ - protected function dispatchMessage(object $message, array $stamps = []): Envelope - { - trigger_deprecation('symfony/framework-bundle', '5.4', 'Method "%s()" is deprecated, inject an instance of MessageBusInterface in your controller instead.', __METHOD__); - - if (!$this->container->has('messenger.default_bus')) { - $message = class_exists(Envelope::class) ? 'You need to define the "messenger.default_bus" configuration option.' : 'Try running "composer require symfony/messenger".'; - throw new \LogicException('The message bus is not enabled in your application. '.$message); - } - - return $this->container->get('messenger.default_bus')->dispatch($message, $stamps); - } - - /** - * Adds a Link HTTP header to the current response. - * - * @see https://tools.ietf.org/html/rfc5988 - */ - protected function addLink(Request $request, LinkInterface $link): void - { - if (!class_exists(AddLinkHeaderListener::class)) { - throw new \LogicException('You cannot use the "addLink" method if the WebLink component is not available. Try running "composer require symfony/web-link".'); - } - - if (null === $linkProvider = $request->attributes->get('_links')) { - $request->attributes->set('_links', new GenericLinkProvider([$link])); - - return; - } - - $request->attributes->set('_links', $linkProvider->withLink($link)); - } -} diff --git a/lib/symfony/framework-bundle/Controller/ControllerResolver.php b/lib/symfony/framework-bundle/Controller/ControllerResolver.php deleted file mode 100644 index 0539c1ee7..000000000 --- a/lib/symfony/framework-bundle/Controller/ControllerResolver.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Controller; - -use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\HttpKernel\Controller\ContainerControllerResolver; - -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class ControllerResolver extends ContainerControllerResolver -{ - /** - * {@inheritdoc} - */ - protected function instantiateController(string $class): object - { - $controller = parent::instantiateController($class); - - if ($controller instanceof ContainerAwareInterface) { - $controller->setContainer($this->container); - } - if ($controller instanceof AbstractController) { - if (null === $previousContainer = $controller->setContainer($this->container)) { - throw new \LogicException(sprintf('"%s" has no container set, did you forget to define it as a service subscriber?', $class)); - } else { - $controller->setContainer($previousContainer); - } - } - - return $controller; - } -} diff --git a/lib/symfony/framework-bundle/Controller/RedirectController.php b/lib/symfony/framework-bundle/Controller/RedirectController.php deleted file mode 100644 index 6a0fed64f..000000000 --- a/lib/symfony/framework-bundle/Controller/RedirectController.php +++ /dev/null @@ -1,189 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Controller; - -use Symfony\Component\HttpFoundation\HeaderUtils; -use Symfony\Component\HttpFoundation\RedirectResponse; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Exception\HttpException; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; - -/** - * Redirects a request to another URL. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class RedirectController -{ - private $router; - private $httpPort; - private $httpsPort; - - public function __construct(UrlGeneratorInterface $router = null, int $httpPort = null, int $httpsPort = null) - { - $this->router = $router; - $this->httpPort = $httpPort; - $this->httpsPort = $httpsPort; - } - - /** - * Redirects to another route with the given name. - * - * The response status code is 302 if the permanent parameter is false (default), - * and 301 if the redirection is permanent. - * - * In case the route name is empty, the status code will be 404 when permanent is false - * and 410 otherwise. - * - * @param string $route The route name to redirect to - * @param bool $permanent Whether the redirection is permanent - * @param bool|array $ignoreAttributes Whether to ignore attributes or an array of attributes to ignore - * @param bool $keepRequestMethod Whether redirect action should keep HTTP request method - * - * @throws HttpException In case the route name is empty - */ - public function redirectAction(Request $request, string $route, bool $permanent = false, $ignoreAttributes = false, bool $keepRequestMethod = false, bool $keepQueryParams = false): Response - { - if ('' == $route) { - throw new HttpException($permanent ? 410 : 404); - } - - $attributes = []; - if (false === $ignoreAttributes || \is_array($ignoreAttributes)) { - $attributes = $request->attributes->get('_route_params'); - - if ($keepQueryParams) { - if ($query = $request->server->get('QUERY_STRING')) { - $query = HeaderUtils::parseQuery($query); - } else { - $query = $request->query->all(); - } - - $attributes = array_merge($query, $attributes); - } - - unset($attributes['route'], $attributes['permanent'], $attributes['ignoreAttributes'], $attributes['keepRequestMethod'], $attributes['keepQueryParams']); - if ($ignoreAttributes) { - $attributes = array_diff_key($attributes, array_flip($ignoreAttributes)); - } - } - - if ($keepRequestMethod) { - $statusCode = $permanent ? 308 : 307; - } else { - $statusCode = $permanent ? 301 : 302; - } - - return new RedirectResponse($this->router->generate($route, $attributes, UrlGeneratorInterface::ABSOLUTE_URL), $statusCode); - } - - /** - * Redirects to a URL. - * - * The response status code is 302 if the permanent parameter is false (default), - * and 301 if the redirection is permanent. - * - * In case the path is empty, the status code will be 404 when permanent is false - * and 410 otherwise. - * - * @param string $path The absolute path or URL to redirect to - * @param bool $permanent Whether the redirect is permanent or not - * @param string|null $scheme The URL scheme (null to keep the current one) - * @param int|null $httpPort The HTTP port (null to keep the current one for the same scheme or the default configured port) - * @param int|null $httpsPort The HTTPS port (null to keep the current one for the same scheme or the default configured port) - * @param bool $keepRequestMethod Whether redirect action should keep HTTP request method - * - * @throws HttpException In case the path is empty - */ - public function urlRedirectAction(Request $request, string $path, bool $permanent = false, string $scheme = null, int $httpPort = null, int $httpsPort = null, bool $keepRequestMethod = false): Response - { - if ('' == $path) { - throw new HttpException($permanent ? 410 : 404); - } - - if ($keepRequestMethod) { - $statusCode = $permanent ? 308 : 307; - } else { - $statusCode = $permanent ? 301 : 302; - } - - // redirect if the path is a full URL - if (parse_url($path, \PHP_URL_SCHEME)) { - return new RedirectResponse($path, $statusCode); - } - - if (null === $scheme) { - $scheme = $request->getScheme(); - } - - if ($qs = $request->server->get('QUERY_STRING') ?: $request->getQueryString()) { - if (!str_contains($path, '?')) { - $qs = '?'.$qs; - } else { - $qs = '&'.$qs; - } - } - - $port = ''; - if ('http' === $scheme) { - if (null === $httpPort) { - if ('http' === $request->getScheme()) { - $httpPort = $request->getPort(); - } else { - $httpPort = $this->httpPort; - } - } - - if (null !== $httpPort && 80 != $httpPort) { - $port = ":$httpPort"; - } - } elseif ('https' === $scheme) { - if (null === $httpsPort) { - if ('https' === $request->getScheme()) { - $httpsPort = $request->getPort(); - } else { - $httpsPort = $this->httpsPort; - } - } - - if (null !== $httpsPort && 443 != $httpsPort) { - $port = ":$httpsPort"; - } - } - - $url = $scheme.'://'.$request->getHost().$port.$request->getBaseUrl().$path.$qs; - - return new RedirectResponse($url, $statusCode); - } - - public function __invoke(Request $request): Response - { - $p = $request->attributes->get('_route_params', []); - - if (\array_key_exists('route', $p)) { - if (\array_key_exists('path', $p)) { - throw new \RuntimeException(sprintf('Ambiguous redirection settings, use the "path" or "route" parameter, not both: "%s" and "%s" found respectively in "%s" routing configuration.', $p['path'], $p['route'], $request->attributes->get('_route'))); - } - - return $this->redirectAction($request, $p['route'], $p['permanent'] ?? false, $p['ignoreAttributes'] ?? false, $p['keepRequestMethod'] ?? false, $p['keepQueryParams'] ?? false); - } - - if (\array_key_exists('path', $p)) { - return $this->urlRedirectAction($request, $p['path'], $p['permanent'] ?? false, $p['scheme'] ?? null, $p['httpPort'] ?? null, $p['httpsPort'] ?? null, $p['keepRequestMethod'] ?? false); - } - - throw new \RuntimeException(sprintf('The parameter "path" or "route" is required to configure the redirect action in "%s" routing configuration.', $request->attributes->get('_route'))); - } -} diff --git a/lib/symfony/framework-bundle/Controller/TemplateController.php b/lib/symfony/framework-bundle/Controller/TemplateController.php deleted file mode 100644 index 2283dbc91..000000000 --- a/lib/symfony/framework-bundle/Controller/TemplateController.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Controller; - -use Symfony\Component\HttpFoundation\Response; -use Twig\Environment; - -/** - * TemplateController. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class TemplateController -{ - private $twig; - - public function __construct(Environment $twig = null) - { - $this->twig = $twig; - } - - /** - * Renders a template. - * - * @param string $template The template name - * @param int|null $maxAge Max age for client caching - * @param int|null $sharedAge Max age for shared (proxy) caching - * @param bool|null $private Whether or not caching should apply for client caches only - * @param array $context The context (arguments) of the template - * @param int $statusCode The HTTP status code to return with the response. Defaults to 200 - */ - public function templateAction(string $template, int $maxAge = null, int $sharedAge = null, bool $private = null, array $context = [], int $statusCode = 200): Response - { - if (null === $this->twig) { - throw new \LogicException('You cannot use the TemplateController if the Twig Bundle is not available.'); - } - - $response = new Response($this->twig->render($template, $context), $statusCode); - - if ($maxAge) { - $response->setMaxAge($maxAge); - } - - if (null !== $sharedAge) { - $response->setSharedMaxAge($sharedAge); - } - - if ($private) { - $response->setPrivate(); - } elseif (false === $private || (null === $private && (null !== $maxAge || null !== $sharedAge))) { - $response->setPublic(); - } - - return $response; - } - - public function __invoke(string $template, int $maxAge = null, int $sharedAge = null, bool $private = null, array $context = [], int $statusCode = 200): Response - { - return $this->templateAction($template, $maxAge, $sharedAge, $private, $context, $statusCode); - } -} diff --git a/lib/symfony/framework-bundle/DataCollector/AbstractDataCollector.php b/lib/symfony/framework-bundle/DataCollector/AbstractDataCollector.php deleted file mode 100644 index 7fa1ee2d3..000000000 --- a/lib/symfony/framework-bundle/DataCollector/AbstractDataCollector.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DataCollector; - -use Symfony\Component\HttpKernel\DataCollector\DataCollector; - -/** - * @author Laurent VOULLEMIER <laurent.voullemier@gmail.com> - */ -abstract class AbstractDataCollector extends DataCollector implements TemplateAwareDataCollectorInterface -{ - public function getName(): string - { - return static::class; - } - - public function reset(): void - { - $this->data = []; - } - - public static function getTemplate(): ?string - { - return null; - } -} diff --git a/lib/symfony/framework-bundle/DataCollector/RouterDataCollector.php b/lib/symfony/framework-bundle/DataCollector/RouterDataCollector.php deleted file mode 100644 index c5d0673de..000000000 --- a/lib/symfony/framework-bundle/DataCollector/RouterDataCollector.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DataCollector; - -use Symfony\Bundle\FrameworkBundle\Controller\RedirectController; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\DataCollector\RouterDataCollector as BaseRouterDataCollector; - -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class RouterDataCollector extends BaseRouterDataCollector -{ - public function guessRoute(Request $request, $controller) - { - if (\is_array($controller)) { - $controller = $controller[0]; - } - - if ($controller instanceof RedirectController) { - return $request->attributes->get('_route'); - } - - return parent::guessRoute($request, $controller); - } -} diff --git a/lib/symfony/framework-bundle/DataCollector/TemplateAwareDataCollectorInterface.php b/lib/symfony/framework-bundle/DataCollector/TemplateAwareDataCollectorInterface.php deleted file mode 100644 index 5ef17abc5..000000000 --- a/lib/symfony/framework-bundle/DataCollector/TemplateAwareDataCollectorInterface.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DataCollector; - -use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; - -/** - * @author Laurent VOULLEMIER <laurent.voullemier@gmail.com> - */ -interface TemplateAwareDataCollectorInterface extends DataCollectorInterface -{ - public static function getTemplate(): ?string; -} diff --git a/lib/symfony/framework-bundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php b/lib/symfony/framework-bundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php deleted file mode 100644 index d7db6ebf0..000000000 --- a/lib/symfony/framework-bundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * @internal - */ -class AddAnnotationsCachedReaderPass implements CompilerPassInterface -{ - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - // "annotations.cached_reader" is wired late so that any passes using - // "annotation_reader" at build time don't get any cache - foreach ($container->findTaggedServiceIds('annotations.cached_reader') as $id => $tags) { - $reader = $container->getDefinition($id); - $properties = $reader->getProperties(); - - if (isset($properties['cacheProviderBackup'])) { - $provider = $properties['cacheProviderBackup']->getValues()[0]; - unset($properties['cacheProviderBackup']); - $reader->setProperties($properties); - $reader->replaceArgument(1, $provider); - } elseif (4 <= \count($arguments = $reader->getArguments()) && $arguments[3] instanceof ServiceClosureArgument) { - $arguments[1] = $arguments[3]->getValues()[0]; - unset($arguments[3]); - $reader->setArguments($arguments); - } - } - } -} diff --git a/lib/symfony/framework-bundle/DependencyInjection/Compiler/AddDebugLogProcessorPass.php b/lib/symfony/framework-bundle/DependencyInjection/Compiler/AddDebugLogProcessorPass.php deleted file mode 100644 index 51b297554..000000000 --- a/lib/symfony/framework-bundle/DependencyInjection/Compiler/AddDebugLogProcessorPass.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; - -class AddDebugLogProcessorPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition('profiler')) { - return; - } - if (!$container->hasDefinition('monolog.logger_prototype')) { - return; - } - if (!$container->hasDefinition('debug.log_processor')) { - return; - } - - $definition = $container->getDefinition('monolog.logger_prototype'); - $definition->setConfigurator([__CLASS__, 'configureLogger']); - $definition->addMethodCall('pushProcessor', [new Reference('debug.log_processor')]); - } - - public static function configureLogger($logger) - { - if (\is_object($logger) && method_exists($logger, 'removeDebugLogger') && \in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { - $logger->removeDebugLogger(); - } - } -} diff --git a/lib/symfony/framework-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php b/lib/symfony/framework-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php deleted file mode 100644 index 3e2f2768e..000000000 --- a/lib/symfony/framework-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Registers the expression language providers. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class AddExpressionLanguageProvidersPass implements CompilerPassInterface -{ - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - // routing - if ($container->has('router.default')) { - $definition = $container->findDefinition('router.default'); - foreach ($container->findTaggedServiceIds('routing.expression_language_provider', true) as $id => $attributes) { - $definition->addMethodCall('addExpressionLanguageProvider', [new Reference($id)]); - } - } - } -} diff --git a/lib/symfony/framework-bundle/DependencyInjection/Compiler/AssetsContextPass.php b/lib/symfony/framework-bundle/DependencyInjection/Compiler/AssetsContextPass.php deleted file mode 100644 index 3fc79f0ee..000000000 --- a/lib/symfony/framework-bundle/DependencyInjection/Compiler/AssetsContextPass.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Reference; - -class AssetsContextPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition('assets.context')) { - return; - } - - if (!$container->hasDefinition('router.request_context')) { - $container->setParameter('asset.request_context.base_path', $container->getParameter('asset.request_context.base_path') ?? ''); - $container->setParameter('asset.request_context.secure', $container->getParameter('asset.request_context.secure') ?? false); - - return; - } - - $context = $container->getDefinition('assets.context'); - - if (null === $container->getParameter('asset.request_context.base_path')) { - $context->replaceArgument(1, (new Definition('string'))->setFactory([new Reference('router.request_context'), 'getBaseUrl'])); - } - - if (null === $container->getParameter('asset.request_context.secure')) { - $context->replaceArgument(2, (new Definition('bool'))->setFactory([new Reference('router.request_context'), 'isSecure'])); - } - } -} diff --git a/lib/symfony/framework-bundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php b/lib/symfony/framework-bundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php deleted file mode 100644 index 0df5420c7..000000000 --- a/lib/symfony/framework-bundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\Config\ConfigCache; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Dumper\XmlDumper; - -/** - * Dumps the ContainerBuilder to a cache file so that it can be used by - * debugging tools such as the debug:container console command. - * - * @author Ryan Weaver <ryan@thatsquality.com> - * @author Fabien Potencier <fabien@symfony.com> - */ -class ContainerBuilderDebugDumpPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container) - { - $cache = new ConfigCache($container->getParameter('debug.container.dump'), true); - if (!$cache->isFresh()) { - $cache->write((new XmlDumper($container))->dump(), $container->getResources()); - } - } -} diff --git a/lib/symfony/framework-bundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php b/lib/symfony/framework-bundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php deleted file mode 100644 index ee2bbb652..000000000 --- a/lib/symfony/framework-bundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * @author Christian Flothmann <christian.flothmann@sensiolabs.de> - */ -class DataCollectorTranslatorPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container) - { - if (!$container->has('translator')) { - return; - } - - $translatorClass = $container->getParameterBag()->resolveValue($container->findDefinition('translator')->getClass()); - - if (!is_subclass_of($translatorClass, 'Symfony\Component\Translation\TranslatorBagInterface')) { - $container->removeDefinition('translator.data_collector'); - $container->removeDefinition('data_collector.translation'); - } - } -} diff --git a/lib/symfony/framework-bundle/DependencyInjection/Compiler/LoggingTranslatorPass.php b/lib/symfony/framework-bundle/DependencyInjection/Compiler/LoggingTranslatorPass.php deleted file mode 100644 index 80cbe52e6..000000000 --- a/lib/symfony/framework-bundle/DependencyInjection/Compiler/LoggingTranslatorPass.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\Translation\TranslatorBagInterface; -use Symfony\Contracts\Translation\TranslatorInterface; - -/** - * @author Abdellatif Ait boudad <a.aitboudad@gmail.com> - */ -class LoggingTranslatorPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container) - { - if (!$container->hasAlias('logger') || !$container->hasAlias('translator')) { - return; - } - - if ($container->hasParameter('translator.logging') && $container->getParameter('translator.logging')) { - $translatorAlias = $container->getAlias('translator'); - $definition = $container->getDefinition((string) $translatorAlias); - $class = $container->getParameterBag()->resolveValue($definition->getClass()); - - if (!$r = $container->getReflectionClass($class)) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $translatorAlias)); - } - if ($r->isSubclassOf(TranslatorInterface::class) && $r->isSubclassOf(TranslatorBagInterface::class)) { - $container->getDefinition('translator.logging')->setDecoratedService('translator'); - $warmer = $container->getDefinition('translation.warmer'); - $subscriberAttributes = $warmer->getTag('container.service_subscriber'); - $warmer->clearTag('container.service_subscriber'); - - foreach ($subscriberAttributes as $k => $v) { - if ((!isset($v['id']) || 'translator' !== $v['id']) && (!isset($v['key']) || 'translator' !== $v['key'])) { - $warmer->addTag('container.service_subscriber', $v); - } - } - $warmer->addTag('container.service_subscriber', ['key' => 'translator', 'id' => 'translator.logging.inner']); - } - } - } -} diff --git a/lib/symfony/framework-bundle/DependencyInjection/Compiler/ProfilerPass.php b/lib/symfony/framework-bundle/DependencyInjection/Compiler/ProfilerPass.php deleted file mode 100644 index 7200b12b9..000000000 --- a/lib/symfony/framework-bundle/DependencyInjection/Compiler/ProfilerPass.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Bundle\FrameworkBundle\DataCollector\TemplateAwareDataCollectorInterface; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Adds tagged data_collector services to profiler service. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class ProfilerPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container) - { - if (false === $container->hasDefinition('profiler')) { - return; - } - - $definition = $container->getDefinition('profiler'); - - $collectors = new \SplPriorityQueue(); - $order = \PHP_INT_MAX; - foreach ($container->findTaggedServiceIds('data_collector', true) as $id => $attributes) { - $priority = $attributes[0]['priority'] ?? 0; - $template = null; - - $collectorClass = $container->findDefinition($id)->getClass(); - $isTemplateAware = is_subclass_of($collectorClass, TemplateAwareDataCollectorInterface::class); - if (isset($attributes[0]['template']) || $isTemplateAware) { - $idForTemplate = $attributes[0]['id'] ?? $collectorClass; - if (!$idForTemplate) { - throw new InvalidArgumentException(sprintf('Data collector service "%s" must have an id attribute in order to specify a template.', $id)); - } - $template = [$idForTemplate, $attributes[0]['template'] ?? $collectorClass::getTemplate()]; - } - - $collectors->insert([$id, $template], [$priority, --$order]); - } - - $templates = []; - foreach ($collectors as $collector) { - $definition->addMethodCall('add', [new Reference($collector[0])]); - $templates[$collector[0]] = $collector[1]; - } - - $container->setParameter('data_collector.templates', $templates); - } -} diff --git a/lib/symfony/framework-bundle/DependencyInjection/Compiler/RemoveUnusedSessionMarshallingHandlerPass.php b/lib/symfony/framework-bundle/DependencyInjection/Compiler/RemoveUnusedSessionMarshallingHandlerPass.php deleted file mode 100644 index 8b6479c4f..000000000 --- a/lib/symfony/framework-bundle/DependencyInjection/Compiler/RemoveUnusedSessionMarshallingHandlerPass.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * @author Ahmed TAILOULOUTE <ahmed.tailouloute@gmail.com> - */ -class RemoveUnusedSessionMarshallingHandlerPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition('session.marshalling_handler')) { - return; - } - - $isMarshallerDecorated = false; - - foreach ($container->getDefinitions() as $definition) { - $decorated = $definition->getDecoratedService(); - if (null !== $decorated && 'session.marshaller' === $decorated[0]) { - $isMarshallerDecorated = true; - - break; - } - } - - if (!$isMarshallerDecorated) { - $container->removeDefinition('session.marshalling_handler'); - } - } -} diff --git a/lib/symfony/framework-bundle/DependencyInjection/Compiler/SessionPass.php b/lib/symfony/framework-bundle/DependencyInjection/Compiler/SessionPass.php deleted file mode 100644 index 7230fc9fb..000000000 --- a/lib/symfony/framework-bundle/DependencyInjection/Compiler/SessionPass.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; - -/** - * @internal to be removed in 6.0 - */ -class SessionPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container) - { - if (!$container->has('session.factory')) { - return; - } - - // BC layer: Make "session" an alias of ".session.do-not-use" when not overridden by the user - if (!$container->has('session')) { - $alias = $container->setAlias('session', '.session.do-not-use'); - $alias->setDeprecated('symfony/framework-bundle', '5.3', 'The "%alias_id%" service and "SessionInterface" alias are deprecated, use "$requestStack->getSession()" instead.'); - // restore previous behavior - $alias->setPublic(true); - - return; - } - - if ($container->hasDefinition('session')) { - $definition = $container->getDefinition('session'); - $definition->setDeprecated('symfony/framework-bundle', '5.3', 'The "%service_id%" service and "SessionInterface" alias are deprecated, use "$requestStack->getSession()" instead.'); - } else { - $alias = $container->getAlias('session'); - $alias->setDeprecated('symfony/framework-bundle', '5.3', 'The "%alias_id%" and "SessionInterface" aliases are deprecated, use "$requestStack->getSession()" instead.'); - $definition = $container->findDefinition('session'); - } - - // Convert internal service `.session.do-not-use` into alias of `session`. - $container->setAlias('.session.do-not-use', 'session'); - - $bags = [ - 'session.flash_bag' => $container->hasDefinition('session.flash_bag') ? $container->getDefinition('session.flash_bag') : null, - 'session.attribute_bag' => $container->hasDefinition('session.attribute_bag') ? $container->getDefinition('session.attribute_bag') : null, - ]; - - foreach ($definition->getArguments() as $v) { - if (!$v instanceof Reference || !isset($bags[$bag = (string) $v]) || !\is_array($factory = $bags[$bag]->getFactory())) { - continue; - } - - if ([0, 1] !== array_keys($factory) || !$factory[0] instanceof Reference || !\in_array((string) $factory[0], ['session', '.session.do-not-use'], true)) { - continue; - } - - if ('get'.ucfirst(substr($bag, 8, -4)).'Bag' !== $factory[1]) { - continue; - } - - $bags[$bag]->setFactory(null); - } - } -} diff --git a/lib/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php b/lib/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php deleted file mode 100644 index 942eb635b..000000000 --- a/lib/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class TestServiceContainerRealRefPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition('test.private_services_locator')) { - return; - } - - $privateContainer = $container->getDefinition('test.private_services_locator'); - $definitions = $container->getDefinitions(); - $privateServices = $privateContainer->getArgument(0); - - foreach ($privateServices as $id => $argument) { - if (isset($definitions[$target = (string) $argument->getValues()[0]])) { - $argument->setValues([new Reference($target)]); - } else { - unset($privateServices[$id]); - } - } - - foreach ($container->getAliases() as $id => $target) { - while ($container->hasAlias($target = (string) $target)) { - $target = $container->getAlias($target); - } - - if ($definitions[$target]->hasTag('container.private')) { - $privateServices[$id] = new ServiceClosureArgument(new Reference($target)); - } - } - - $privateContainer->replaceArgument(0, $privateServices); - } -} diff --git a/lib/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php b/lib/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php deleted file mode 100644 index bc1e5a936..000000000 --- a/lib/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Reference; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class TestServiceContainerWeakRefPass implements CompilerPassInterface -{ - private $privateTagName; - - public function __construct(string $privateTagName = 'container.private') - { - if (0 < \func_num_args()) { - trigger_deprecation('symfony/framework-bundle', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->privateTagName = $privateTagName; - } - - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition('test.private_services_locator')) { - return; - } - - $privateServices = []; - $definitions = $container->getDefinitions(); - $hasErrors = method_exists(Definition::class, 'hasErrors') ? 'hasErrors' : 'getErrors'; - - foreach ($definitions as $id => $definition) { - if ($id && '.' !== $id[0] && (!$definition->isPublic() || $definition->isPrivate() || $definition->hasTag($this->privateTagName)) && !$definition->$hasErrors() && !$definition->isAbstract()) { - $privateServices[$id] = new Reference($id, ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE); - } - } - - $aliases = $container->getAliases(); - - foreach ($aliases as $id => $alias) { - if ($id && '.' !== $id[0] && (!$alias->isPublic() || $alias->isPrivate())) { - while (isset($aliases[$target = (string) $alias])) { - $alias = $aliases[$target]; - } - if (isset($definitions[$target]) && !$definitions[$target]->$hasErrors() && !$definitions[$target]->isAbstract()) { - $privateServices[$id] = new Reference($target, ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE); - } - } - } - - if ($privateServices) { - $id = (string) ServiceLocatorTagPass::register($container, $privateServices); - $container->setDefinition('test.private_services_locator', $container->getDefinition($id))->setPublic(true); - $container->removeDefinition($id); - } - } -} diff --git a/lib/symfony/framework-bundle/DependencyInjection/Compiler/UnusedTagsPass.php b/lib/symfony/framework-bundle/DependencyInjection/Compiler/UnusedTagsPass.php deleted file mode 100644 index 386ee7d0c..000000000 --- a/lib/symfony/framework-bundle/DependencyInjection/Compiler/UnusedTagsPass.php +++ /dev/null @@ -1,129 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * Find all service tags which are defined, but not used and yield a warning log message. - * - * @author Florian Pfitzer <pfitzer@wurzel3.de> - */ -class UnusedTagsPass implements CompilerPassInterface -{ - private const KNOWN_TAGS = [ - 'annotations.cached_reader', - 'assets.package', - 'auto_alias', - 'cache.pool', - 'cache.pool.clearer', - 'chatter.transport_factory', - 'config_cache.resource_checker', - 'console.command', - 'container.do_not_inline', - 'container.env_var_loader', - 'container.env_var_processor', - 'container.hot_path', - 'container.no_preload', - 'container.preload', - 'container.private', - 'container.reversible', - 'container.service_locator', - 'container.service_locator_context', - 'container.service_subscriber', - 'container.stack', - 'controller.argument_value_resolver', - 'controller.service_arguments', - 'data_collector', - 'event_dispatcher.dispatcher', - 'form.type', - 'form.type_extension', - 'form.type_guesser', - 'http_client.client', - 'kernel.cache_clearer', - 'kernel.cache_warmer', - 'kernel.event_listener', - 'kernel.event_subscriber', - 'kernel.fragment_renderer', - 'kernel.locale_aware', - 'kernel.reset', - 'ldap', - 'mailer.transport_factory', - 'messenger.bus', - 'messenger.message_handler', - 'messenger.receiver', - 'messenger.transport_factory', - 'mime.mime_type_guesser', - 'monolog.logger', - 'notifier.channel', - 'property_info.access_extractor', - 'property_info.initializable_extractor', - 'property_info.list_extractor', - 'property_info.type_extractor', - 'proxy', - 'routing.expression_language_function', - 'routing.expression_language_provider', - 'routing.loader', - 'routing.route_loader', - 'security.authenticator.login_linker', - 'security.expression_language_provider', - 'security.remember_me_aware', - 'security.remember_me_handler', - 'security.voter', - 'serializer.encoder', - 'serializer.normalizer', - 'texter.transport_factory', - 'translation.dumper', - 'translation.extractor', - 'translation.loader', - 'translation.provider_factory', - 'twig.extension', - 'twig.loader', - 'twig.runtime', - 'validator.auto_mapper', - 'validator.constraint_validator', - 'validator.initializer', - ]; - - public function process(ContainerBuilder $container) - { - $tags = array_unique(array_merge($container->findTags(), self::KNOWN_TAGS)); - - foreach ($container->findUnusedTags() as $tag) { - // skip known tags - if (\in_array($tag, self::KNOWN_TAGS)) { - continue; - } - - // check for typos - $candidates = []; - foreach ($tags as $definedTag) { - if ($definedTag === $tag) { - continue; - } - - if (str_contains($definedTag, $tag) || levenshtein($tag, $definedTag) <= \strlen($tag) / 3) { - $candidates[] = $definedTag; - } - } - - $services = array_keys($container->findTaggedServiceIds($tag)); - $message = sprintf('Tag "%s" was defined on service(s) "%s", but was never used.', $tag, implode('", "', $services)); - if (!empty($candidates)) { - $message .= sprintf(' Did you mean "%s"?', implode('", "', $candidates)); - } - - $container->log($this, $message); - } - } -} diff --git a/lib/symfony/framework-bundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php b/lib/symfony/framework-bundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php deleted file mode 100644 index ad62e1938..000000000 --- a/lib/symfony/framework-bundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\LogicException; - -/** - * @author Christian Flothmann <christian.flothmann@sensiolabs.de> - * @author Grégoire Pineau <lyrixx@lyrixx.info> - */ -class WorkflowGuardListenerPass implements CompilerPassInterface -{ - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - if (!$container->hasParameter('workflow.has_guard_listeners')) { - return; - } - - $container->getParameterBag()->remove('workflow.has_guard_listeners'); - - $servicesNeeded = [ - 'security.token_storage', - 'security.authorization_checker', - 'security.authentication.trust_resolver', - 'security.role_hierarchy', - ]; - - foreach ($servicesNeeded as $service) { - if (!$container->has($service)) { - throw new LogicException(sprintf('The "%s" service is needed to be able to use the workflow guard listener.', $service)); - } - } - } -} diff --git a/lib/symfony/framework-bundle/DependencyInjection/Configuration.php b/lib/symfony/framework-bundle/DependencyInjection/Configuration.php deleted file mode 100644 index c70a07635..000000000 --- a/lib/symfony/framework-bundle/DependencyInjection/Configuration.php +++ /dev/null @@ -1,2075 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection; - -use Doctrine\Common\Annotations\Annotation; -use Doctrine\Common\Annotations\PsrCachedReader; -use Doctrine\Common\Cache\Cache; -use Doctrine\DBAL\Connection; -use Psr\Log\LogLevel; -use Symfony\Bundle\FullStack; -use Symfony\Component\Asset\Package; -use Symfony\Component\Cache\Adapter\DoctrineAdapter; -use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; -use Symfony\Component\Config\Definition\Builder\NodeBuilder; -use Symfony\Component\Config\Definition\Builder\TreeBuilder; -use Symfony\Component\Config\Definition\ConfigurationInterface; -use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\LogicException; -use Symfony\Component\Form\Form; -use Symfony\Component\HttpClient\HttpClient; -use Symfony\Component\HttpFoundation\Cookie; -use Symfony\Component\Lock\Lock; -use Symfony\Component\Lock\Store\SemaphoreStore; -use Symfony\Component\Mailer\Mailer; -use Symfony\Component\Messenger\MessageBusInterface; -use Symfony\Component\Notifier\Notifier; -use Symfony\Component\PropertyAccess\PropertyAccessor; -use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface; -use Symfony\Component\RateLimiter\Policy\TokenBucketLimiter; -use Symfony\Component\Serializer\Serializer; -use Symfony\Component\Translation\Translator; -use Symfony\Component\Uid\Factory\UuidFactory; -use Symfony\Component\Validator\Validation; -use Symfony\Component\WebLink\HttpHeaderSerializer; -use Symfony\Component\Workflow\WorkflowEvents; - -/** - * FrameworkExtension configuration structure. - */ -class Configuration implements ConfigurationInterface -{ - private $debug; - - /** - * @param bool $debug Whether debugging is enabled or not - */ - public function __construct(bool $debug) - { - $this->debug = $debug; - } - - /** - * Generates the configuration tree builder. - * - * @return TreeBuilder - */ - public function getConfigTreeBuilder() - { - $treeBuilder = new TreeBuilder('framework'); - $rootNode = $treeBuilder->getRootNode(); - - $rootNode - ->beforeNormalization() - ->ifTrue(function ($v) { return !isset($v['assets']) && isset($v['templating']) && class_exists(Package::class); }) - ->then(function ($v) { - $v['assets'] = []; - - return $v; - }) - ->end() - ->fixXmlConfig('enabled_locale') - ->children() - ->scalarNode('secret')->end() - ->scalarNode('http_method_override') - ->info("Set true to enable support for the '_method' request parameter to determine the intended HTTP method on POST requests. Note: When using the HttpCache, you need to call the method in your front controller instead") - ->defaultTrue() - ->end() - ->scalarNode('ide')->defaultNull()->end() - ->booleanNode('test')->end() - ->scalarNode('default_locale')->defaultValue('en')->end() - ->booleanNode('set_locale_from_accept_language') - ->info('Whether to use the Accept-Language HTTP header to set the Request locale (only when the "_locale" request attribute is not passed).') - ->defaultFalse() - ->end() - ->booleanNode('set_content_language_from_locale') - ->info('Whether to set the Content-Language HTTP header on the Response using the Request locale.') - ->defaultFalse() - ->end() - ->arrayNode('enabled_locales') - ->info('Defines the possible locales for the application. This list is used for generating translations files, but also to restrict which locales are allowed when it is set from Accept-Language header (using "set_locale_from_accept_language").') - ->prototype('scalar')->end() - ->end() - ->arrayNode('trusted_hosts') - ->beforeNormalization()->ifString()->then(function ($v) { return [$v]; })->end() - ->prototype('scalar')->end() - ->end() - ->scalarNode('trusted_proxies')->end() - ->arrayNode('trusted_headers') - ->fixXmlConfig('trusted_header') - ->performNoDeepMerging() - ->defaultValue(['x-forwarded-for', 'x-forwarded-port', 'x-forwarded-proto']) - ->beforeNormalization()->ifString()->then(function ($v) { return $v ? array_map('trim', explode(',', $v)) : []; })->end() - ->enumPrototype() - ->values([ - 'forwarded', - 'x-forwarded-for', 'x-forwarded-host', 'x-forwarded-proto', 'x-forwarded-port', 'x-forwarded-prefix', - ]) - ->end() - ->end() - ->scalarNode('error_controller') - ->defaultValue('error_controller') - ->end() - ->end() - ; - - $willBeAvailable = static function (string $package, string $class, string $parentPackage = null) { - $parentPackages = (array) $parentPackage; - $parentPackages[] = 'symfony/framework-bundle'; - - return ContainerBuilder::willBeAvailable($package, $class, $parentPackages, true); - }; - - $enableIfStandalone = static function (string $package, string $class) use ($willBeAvailable) { - return !class_exists(FullStack::class) && $willBeAvailable($package, $class) ? 'canBeDisabled' : 'canBeEnabled'; - }; - - $this->addCsrfSection($rootNode); - $this->addFormSection($rootNode, $enableIfStandalone); - $this->addHttpCacheSection($rootNode); - $this->addEsiSection($rootNode); - $this->addSsiSection($rootNode); - $this->addFragmentsSection($rootNode); - $this->addProfilerSection($rootNode); - $this->addWorkflowSection($rootNode); - $this->addRouterSection($rootNode); - $this->addSessionSection($rootNode); - $this->addRequestSection($rootNode); - $this->addAssetsSection($rootNode, $enableIfStandalone); - $this->addTranslatorSection($rootNode, $enableIfStandalone); - $this->addValidationSection($rootNode, $enableIfStandalone, $willBeAvailable); - $this->addAnnotationsSection($rootNode, $willBeAvailable); - $this->addSerializerSection($rootNode, $enableIfStandalone, $willBeAvailable); - $this->addPropertyAccessSection($rootNode, $willBeAvailable); - $this->addPropertyInfoSection($rootNode, $enableIfStandalone); - $this->addCacheSection($rootNode, $willBeAvailable); - $this->addPhpErrorsSection($rootNode); - $this->addExceptionsSection($rootNode); - $this->addWebLinkSection($rootNode, $enableIfStandalone); - $this->addLockSection($rootNode, $enableIfStandalone); - $this->addMessengerSection($rootNode, $enableIfStandalone); - $this->addRobotsIndexSection($rootNode); - $this->addHttpClientSection($rootNode, $enableIfStandalone); - $this->addMailerSection($rootNode, $enableIfStandalone); - $this->addSecretsSection($rootNode); - $this->addNotifierSection($rootNode, $enableIfStandalone); - $this->addRateLimiterSection($rootNode, $enableIfStandalone); - $this->addUidSection($rootNode, $enableIfStandalone); - - return $treeBuilder; - } - - private function addSecretsSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('secrets') - ->canBeDisabled() - ->children() - ->scalarNode('vault_directory')->defaultValue('%kernel.project_dir%/config/secrets/%kernel.runtime_environment%')->cannotBeEmpty()->end() - ->scalarNode('local_dotenv_file')->defaultValue('%kernel.project_dir%/.env.%kernel.environment%.local')->end() - ->scalarNode('decryption_env_var')->defaultValue('base64:default::SYMFONY_DECRYPTION_SECRET')->end() - ->end() - ->end() - ->end() - ; - } - - private function addCsrfSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('csrf_protection') - ->treatFalseLike(['enabled' => false]) - ->treatTrueLike(['enabled' => true]) - ->treatNullLike(['enabled' => true]) - ->addDefaultsIfNotSet() - ->children() - // defaults to framework.session.enabled && !class_exists(FullStack::class) && interface_exists(CsrfTokenManagerInterface::class) - ->booleanNode('enabled')->defaultNull()->end() - ->end() - ->end() - ->end() - ; - } - - private function addFormSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone) - { - $rootNode - ->children() - ->arrayNode('form') - ->info('form configuration') - ->{$enableIfStandalone('symfony/form', Form::class)}() - ->children() - ->arrayNode('csrf_protection') - ->treatFalseLike(['enabled' => false]) - ->treatTrueLike(['enabled' => true]) - ->treatNullLike(['enabled' => true]) - ->addDefaultsIfNotSet() - ->children() - ->booleanNode('enabled')->defaultNull()->end() // defaults to framework.csrf_protection.enabled - ->scalarNode('field_name')->defaultValue('_token')->end() - ->end() - ->end() - // to be set to false in Symfony 6.0 - ->booleanNode('legacy_error_messages') - ->defaultTrue() - ->validate() - ->ifTrue() - ->then(function ($v) { - trigger_deprecation('symfony/framework-bundle', '5.2', 'Setting the "framework.form.legacy_error_messages" option to "true" is deprecated. It will have no effect as of Symfony 6.0.'); - - return $v; - }) - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addHttpCacheSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('http_cache') - ->info('HTTP cache configuration') - ->canBeEnabled() - ->fixXmlConfig('private_header') - ->children() - ->booleanNode('debug')->defaultValue('%kernel.debug%')->end() - ->enumNode('trace_level') - ->values(['none', 'short', 'full']) - ->end() - ->scalarNode('trace_header')->end() - ->integerNode('default_ttl')->end() - ->arrayNode('private_headers') - ->performNoDeepMerging() - ->scalarPrototype()->end() - ->end() - ->booleanNode('allow_reload')->end() - ->booleanNode('allow_revalidate')->end() - ->integerNode('stale_while_revalidate')->end() - ->integerNode('stale_if_error')->end() - ->end() - ->end() - ->end() - ; - } - - private function addEsiSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('esi') - ->info('esi configuration') - ->canBeEnabled() - ->end() - ->end() - ; - } - - private function addSsiSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('ssi') - ->info('ssi configuration') - ->canBeEnabled() - ->end() - ->end(); - } - - private function addFragmentsSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('fragments') - ->info('fragments configuration') - ->canBeEnabled() - ->children() - ->scalarNode('hinclude_default_template')->defaultNull()->end() - ->scalarNode('path')->defaultValue('/_fragment')->end() - ->end() - ->end() - ->end() - ; - } - - private function addProfilerSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('profiler') - ->info('profiler configuration') - ->canBeEnabled() - ->children() - ->booleanNode('collect')->defaultTrue()->end() - ->scalarNode('collect_parameter')->defaultNull()->info('The name of the parameter to use to enable or disable collection on a per request basis')->end() - ->booleanNode('only_exceptions')->defaultFalse()->end() - ->booleanNode('only_main_requests')->defaultFalse()->end() - ->booleanNode('only_master_requests')->setDeprecated('symfony/framework-bundle', '5.3', 'Option "%node%" at "%path%" is deprecated, use "only_main_requests" instead.')->defaultFalse()->end() - ->scalarNode('dsn')->defaultValue('file:%kernel.cache_dir%/profiler')->end() - ->end() - ->end() - ->end() - ; - } - - private function addWorkflowSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->fixXmlConfig('workflow') - ->children() - ->arrayNode('workflows') - ->canBeEnabled() - ->beforeNormalization() - ->always(function ($v) { - if (\is_array($v) && true === $v['enabled']) { - $workflows = $v; - unset($workflows['enabled']); - - if (1 === \count($workflows) && isset($workflows[0]['enabled']) && 1 === \count($workflows[0])) { - $workflows = []; - } - - if (1 === \count($workflows) && isset($workflows['workflows']) && !array_is_list($workflows['workflows']) && !empty(array_diff(array_keys($workflows['workflows']), ['audit_trail', 'type', 'marking_store', 'supports', 'support_strategy', 'initial_marking', 'places', 'transitions']))) { - $workflows = $workflows['workflows']; - } - - foreach ($workflows as $key => $workflow) { - if (isset($workflow['enabled']) && false === $workflow['enabled']) { - throw new LogicException(sprintf('Cannot disable a single workflow. Remove the configuration for the workflow "%s" instead.', $workflow['name'])); - } - - unset($workflows[$key]['enabled']); - } - - $v = [ - 'enabled' => true, - 'workflows' => $workflows, - ]; - } - - return $v; - }) - ->end() - ->children() - ->arrayNode('workflows') - ->useAttributeAsKey('name') - ->prototype('array') - ->fixXmlConfig('support') - ->fixXmlConfig('place') - ->fixXmlConfig('transition') - ->fixXmlConfig('event_to_dispatch', 'events_to_dispatch') - ->children() - ->arrayNode('audit_trail') - ->canBeEnabled() - ->end() - ->enumNode('type') - ->values(['workflow', 'state_machine']) - ->defaultValue('state_machine') - ->end() - ->arrayNode('marking_store') - ->children() - ->enumNode('type') - ->values(['method']) - ->end() - ->scalarNode('property') - ->defaultValue('marking') - ->end() - ->scalarNode('service') - ->cannotBeEmpty() - ->end() - ->end() - ->end() - ->arrayNode('supports') - ->beforeNormalization() - ->ifString() - ->then(function ($v) { return [$v]; }) - ->end() - ->prototype('scalar') - ->cannotBeEmpty() - ->validate() - ->ifTrue(function ($v) { return !class_exists($v) && !interface_exists($v, false); }) - ->thenInvalid('The supported class or interface "%s" does not exist.') - ->end() - ->end() - ->end() - ->scalarNode('support_strategy') - ->cannotBeEmpty() - ->end() - ->arrayNode('initial_marking') - ->beforeNormalization()->castToArray()->end() - ->defaultValue([]) - ->prototype('scalar')->end() - ->end() - ->variableNode('events_to_dispatch') - ->defaultValue(null) - ->validate() - ->ifTrue(function ($v) { - if (null === $v) { - return false; - } - if (!\is_array($v)) { - return true; - } - - foreach ($v as $value) { - if (!\is_string($value)) { - return true; - } - if (class_exists(WorkflowEvents::class) && !\in_array($value, WorkflowEvents::ALIASES)) { - return true; - } - } - - return false; - }) - ->thenInvalid('The value must be "null" or an array of workflow events (like ["workflow.enter"]).') - ->end() - ->info('Select which Transition events should be dispatched for this Workflow') - ->example(['workflow.enter', 'workflow.transition']) - ->end() - ->arrayNode('places') - ->beforeNormalization() - ->always() - ->then(function ($places) { - // It's an indexed array of shape ['place1', 'place2'] - if (isset($places[0]) && \is_string($places[0])) { - return array_map(function (string $place) { - return ['name' => $place]; - }, $places); - } - - // It's an indexed array, we let the validation occur - if (isset($places[0]) && \is_array($places[0])) { - return $places; - } - - foreach ($places as $name => $place) { - if (\is_array($place) && \array_key_exists('name', $place)) { - continue; - } - $place['name'] = $name; - $places[$name] = $place; - } - - return array_values($places); - }) - ->end() - ->isRequired() - ->requiresAtLeastOneElement() - ->prototype('array') - ->children() - ->scalarNode('name') - ->isRequired() - ->cannotBeEmpty() - ->end() - ->arrayNode('metadata') - ->normalizeKeys(false) - ->defaultValue([]) - ->example(['color' => 'blue', 'description' => 'Workflow to manage article.']) - ->prototype('variable') - ->end() - ->end() - ->end() - ->end() - ->end() - ->arrayNode('transitions') - ->beforeNormalization() - ->always() - ->then(function ($transitions) { - // It's an indexed array, we let the validation occur - if (isset($transitions[0]) && \is_array($transitions[0])) { - return $transitions; - } - - foreach ($transitions as $name => $transition) { - if (\is_array($transition) && \array_key_exists('name', $transition)) { - continue; - } - $transition['name'] = $name; - $transitions[$name] = $transition; - } - - return $transitions; - }) - ->end() - ->isRequired() - ->requiresAtLeastOneElement() - ->prototype('array') - ->children() - ->scalarNode('name') - ->isRequired() - ->cannotBeEmpty() - ->end() - ->scalarNode('guard') - ->cannotBeEmpty() - ->info('An expression to block the transition') - ->example('is_fully_authenticated() and is_granted(\'ROLE_JOURNALIST\') and subject.getTitle() == \'My first article\'') - ->end() - ->arrayNode('from') - ->beforeNormalization() - ->ifString() - ->then(function ($v) { return [$v]; }) - ->end() - ->requiresAtLeastOneElement() - ->prototype('scalar') - ->cannotBeEmpty() - ->end() - ->end() - ->arrayNode('to') - ->beforeNormalization() - ->ifString() - ->then(function ($v) { return [$v]; }) - ->end() - ->requiresAtLeastOneElement() - ->prototype('scalar') - ->cannotBeEmpty() - ->end() - ->end() - ->arrayNode('metadata') - ->normalizeKeys(false) - ->defaultValue([]) - ->example(['color' => 'blue', 'description' => 'Workflow to manage article.']) - ->prototype('variable') - ->end() - ->end() - ->end() - ->end() - ->end() - ->arrayNode('metadata') - ->normalizeKeys(false) - ->defaultValue([]) - ->example(['color' => 'blue', 'description' => 'Workflow to manage article.']) - ->prototype('variable') - ->end() - ->end() - ->end() - ->validate() - ->ifTrue(function ($v) { - return $v['supports'] && isset($v['support_strategy']); - }) - ->thenInvalid('"supports" and "support_strategy" cannot be used together.') - ->end() - ->validate() - ->ifTrue(function ($v) { - return !$v['supports'] && !isset($v['support_strategy']); - }) - ->thenInvalid('"supports" or "support_strategy" should be configured.') - ->end() - ->beforeNormalization() - ->always() - ->then(function ($values) { - // Special case to deal with XML when the user wants an empty array - if (\array_key_exists('event_to_dispatch', $values) && null === $values['event_to_dispatch']) { - $values['events_to_dispatch'] = []; - unset($values['event_to_dispatch']); - } - - return $values; - }) - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addRouterSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('router') - ->info('router configuration') - ->canBeEnabled() - ->children() - ->scalarNode('resource')->isRequired()->end() - ->scalarNode('type')->end() - ->scalarNode('default_uri') - ->info('The default URI used to generate URLs in a non-HTTP context') - ->defaultNull() - ->end() - ->scalarNode('http_port')->defaultValue(80)->end() - ->scalarNode('https_port')->defaultValue(443)->end() - ->scalarNode('strict_requirements') - ->info( - "set to true to throw an exception when a parameter does not match the requirements\n". - "set to false to disable exceptions when a parameter does not match the requirements (and return null instead)\n". - "set to null to disable parameter checks against requirements\n". - "'true' is the preferred configuration in development mode, while 'false' or 'null' might be preferred in production" - ) - ->defaultTrue() - ->end() - ->booleanNode('utf8')->defaultNull()->end() - ->end() - ->end() - ->end() - ; - } - - private function addSessionSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('session') - ->info('session configuration') - ->canBeEnabled() - ->beforeNormalization() - ->ifTrue(function ($v) { - return \is_array($v) && isset($v['storage_id']) && isset($v['storage_factory_id']); - }) - ->thenInvalid('You cannot use both "storage_id" and "storage_factory_id" at the same time under "framework.session"') - ->end() - ->children() - ->scalarNode('storage_id')->defaultValue('session.storage.native')->end() - ->scalarNode('storage_factory_id')->defaultNull()->end() - ->scalarNode('handler_id')->defaultValue('session.handler.native_file')->end() - ->scalarNode('name') - ->validate() - ->ifTrue(function ($v) { - parse_str($v, $parsed); - - return implode('&', array_keys($parsed)) !== (string) $v; - }) - ->thenInvalid('Session name %s contains illegal character(s)') - ->end() - ->end() - ->scalarNode('cookie_lifetime')->end() - ->scalarNode('cookie_path')->end() - ->scalarNode('cookie_domain')->end() - ->enumNode('cookie_secure')->values([true, false, 'auto'])->end() - ->booleanNode('cookie_httponly')->defaultTrue()->end() - ->enumNode('cookie_samesite')->values([null, Cookie::SAMESITE_LAX, Cookie::SAMESITE_STRICT, Cookie::SAMESITE_NONE])->defaultNull()->end() - ->booleanNode('use_cookies')->end() - ->scalarNode('gc_divisor')->end() - ->scalarNode('gc_probability')->defaultValue(1)->end() - ->scalarNode('gc_maxlifetime')->end() - ->scalarNode('save_path')->defaultValue('%kernel.cache_dir%/sessions')->end() - ->integerNode('metadata_update_threshold') - ->defaultValue(0) - ->info('seconds to wait between 2 session metadata updates') - ->end() - ->integerNode('sid_length') - ->min(22) - ->max(256) - ->end() - ->integerNode('sid_bits_per_character') - ->min(4) - ->max(6) - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addRequestSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('request') - ->info('request configuration') - ->canBeEnabled() - ->fixXmlConfig('format') - ->children() - ->arrayNode('formats') - ->useAttributeAsKey('name') - ->prototype('array') - ->beforeNormalization() - ->ifTrue(function ($v) { return \is_array($v) && isset($v['mime_type']); }) - ->then(function ($v) { return $v['mime_type']; }) - ->end() - ->beforeNormalization()->castToArray()->end() - ->prototype('scalar')->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addAssetsSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone) - { - $rootNode - ->children() - ->arrayNode('assets') - ->info('assets configuration') - ->{$enableIfStandalone('symfony/asset', Package::class)}() - ->fixXmlConfig('base_url') - ->children() - ->booleanNode('strict_mode') - ->info('Throw an exception if an entry is missing from the manifest.json') - ->defaultFalse() - ->end() - ->scalarNode('version_strategy')->defaultNull()->end() - ->scalarNode('version')->defaultNull()->end() - ->scalarNode('version_format')->defaultValue('%%s?%%s')->end() - ->scalarNode('json_manifest_path')->defaultNull()->end() - ->scalarNode('base_path')->defaultValue('')->end() - ->arrayNode('base_urls') - ->requiresAtLeastOneElement() - ->beforeNormalization()->castToArray()->end() - ->prototype('scalar')->end() - ->end() - ->end() - ->validate() - ->ifTrue(function ($v) { - return isset($v['version_strategy']) && isset($v['version']); - }) - ->thenInvalid('You cannot use both "version_strategy" and "version" at the same time under "assets".') - ->end() - ->validate() - ->ifTrue(function ($v) { - return isset($v['version_strategy']) && isset($v['json_manifest_path']); - }) - ->thenInvalid('You cannot use both "version_strategy" and "json_manifest_path" at the same time under "assets".') - ->end() - ->validate() - ->ifTrue(function ($v) { - return isset($v['version']) && isset($v['json_manifest_path']); - }) - ->thenInvalid('You cannot use both "version" and "json_manifest_path" at the same time under "assets".') - ->end() - ->fixXmlConfig('package') - ->children() - ->arrayNode('packages') - ->normalizeKeys(false) - ->useAttributeAsKey('name') - ->prototype('array') - ->fixXmlConfig('base_url') - ->children() - ->booleanNode('strict_mode') - ->info('Throw an exception if an entry is missing from the manifest.json') - ->defaultFalse() - ->end() - ->scalarNode('version_strategy')->defaultNull()->end() - ->scalarNode('version') - ->beforeNormalization() - ->ifTrue(function ($v) { return '' === $v; }) - ->then(function ($v) { return; }) - ->end() - ->end() - ->scalarNode('version_format')->defaultNull()->end() - ->scalarNode('json_manifest_path')->defaultNull()->end() - ->scalarNode('base_path')->defaultValue('')->end() - ->arrayNode('base_urls') - ->requiresAtLeastOneElement() - ->beforeNormalization()->castToArray()->end() - ->prototype('scalar')->end() - ->end() - ->end() - ->validate() - ->ifTrue(function ($v) { - return isset($v['version_strategy']) && isset($v['version']); - }) - ->thenInvalid('You cannot use both "version_strategy" and "version" at the same time under "assets" packages.') - ->end() - ->validate() - ->ifTrue(function ($v) { - return isset($v['version_strategy']) && isset($v['json_manifest_path']); - }) - ->thenInvalid('You cannot use both "version_strategy" and "json_manifest_path" at the same time under "assets" packages.') - ->end() - ->validate() - ->ifTrue(function ($v) { - return isset($v['version']) && isset($v['json_manifest_path']); - }) - ->thenInvalid('You cannot use both "version" and "json_manifest_path" at the same time under "assets" packages.') - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addTranslatorSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone) - { - $rootNode - ->children() - ->arrayNode('translator') - ->info('translator configuration') - ->{$enableIfStandalone('symfony/translation', Translator::class)}() - ->fixXmlConfig('fallback') - ->fixXmlConfig('path') - ->fixXmlConfig('enabled_locale') - ->fixXmlConfig('provider') - ->children() - ->arrayNode('fallbacks') - ->info('Defaults to the value of "default_locale".') - ->beforeNormalization()->ifString()->then(function ($v) { return [$v]; })->end() - ->prototype('scalar')->end() - ->defaultValue([]) - ->end() - ->booleanNode('logging')->defaultValue(false)->end() - ->scalarNode('formatter')->defaultValue('translator.formatter.default')->end() - ->scalarNode('cache_dir')->defaultValue('%kernel.cache_dir%/translations')->end() - ->scalarNode('default_path') - ->info('The default path used to load translations') - ->defaultValue('%kernel.project_dir%/translations') - ->end() - ->arrayNode('paths') - ->prototype('scalar')->end() - ->end() - ->arrayNode('enabled_locales') - ->setDeprecated('symfony/framework-bundle', '5.3', 'Option "%node%" at "%path%" is deprecated, set the "framework.enabled_locales" option instead.') - ->prototype('scalar')->end() - ->defaultValue([]) - ->end() - ->arrayNode('pseudo_localization') - ->canBeEnabled() - ->fixXmlConfig('localizable_html_attribute') - ->children() - ->booleanNode('accents')->defaultTrue()->end() - ->floatNode('expansion_factor') - ->min(1.0) - ->defaultValue(1.0) - ->end() - ->booleanNode('brackets')->defaultTrue()->end() - ->booleanNode('parse_html')->defaultFalse()->end() - ->arrayNode('localizable_html_attributes') - ->prototype('scalar')->end() - ->end() - ->end() - ->end() - ->arrayNode('providers') - ->info('Translation providers you can read/write your translations from') - ->useAttributeAsKey('name') - ->prototype('array') - ->fixXmlConfig('domain') - ->fixXmlConfig('locale') - ->children() - ->scalarNode('dsn')->end() - ->arrayNode('domains') - ->prototype('scalar')->end() - ->defaultValue([]) - ->end() - ->arrayNode('locales') - ->prototype('scalar')->end() - ->defaultValue([]) - ->info('If not set, all locales listed under framework.enabled_locales are used.') - ->end() - ->end() - ->end() - ->defaultValue([]) - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addValidationSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone, callable $willBeAvailable) - { - $rootNode - ->children() - ->arrayNode('validation') - ->info('validation configuration') - ->{$enableIfStandalone('symfony/validator', Validation::class)}() - ->children() - ->scalarNode('cache')->end() - ->booleanNode('enable_annotations')->{!class_exists(FullStack::class) && (\PHP_VERSION_ID >= 80000 || $willBeAvailable('doctrine/annotations', Annotation::class, 'symfony/validator')) ? 'defaultTrue' : 'defaultFalse'}()->end() - ->arrayNode('static_method') - ->defaultValue(['loadValidatorMetadata']) - ->prototype('scalar')->end() - ->treatFalseLike([]) - ->validate()->castToArray()->end() - ->end() - ->scalarNode('translation_domain')->defaultValue('validators')->end() - ->enumNode('email_validation_mode')->values(['html5', 'loose', 'strict'])->end() - ->arrayNode('mapping') - ->addDefaultsIfNotSet() - ->fixXmlConfig('path') - ->children() - ->arrayNode('paths') - ->prototype('scalar')->end() - ->end() - ->end() - ->end() - ->arrayNode('not_compromised_password') - ->canBeDisabled() - ->children() - ->booleanNode('enabled') - ->defaultTrue() - ->info('When disabled, compromised passwords will be accepted as valid.') - ->end() - ->scalarNode('endpoint') - ->defaultNull() - ->info('API endpoint for the NotCompromisedPassword Validator.') - ->end() - ->end() - ->end() - ->arrayNode('auto_mapping') - ->info('A collection of namespaces for which auto-mapping will be enabled by default, or null to opt-in with the EnableAutoMapping constraint.') - ->example([ - 'App\\Entity\\' => [], - 'App\\WithSpecificLoaders\\' => ['validator.property_info_loader'], - ]) - ->useAttributeAsKey('namespace') - ->normalizeKeys(false) - ->beforeNormalization() - ->ifArray() - ->then(function (array $values): array { - foreach ($values as $k => $v) { - if (isset($v['service'])) { - continue; - } - - if (isset($v['namespace'])) { - $values[$k]['services'] = []; - continue; - } - - if (!\is_array($v)) { - $values[$v]['services'] = []; - unset($values[$k]); - continue; - } - - $tmp = $v; - unset($values[$k]); - $values[$k]['services'] = $tmp; - } - - return $values; - }) - ->end() - ->arrayPrototype() - ->fixXmlConfig('service') - ->children() - ->arrayNode('services') - ->prototype('scalar')->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addAnnotationsSection(ArrayNodeDefinition $rootNode, callable $willBeAvailable) - { - $doctrineCache = $willBeAvailable('doctrine/cache', Cache::class, 'doctrine/annotations'); - $psr6Cache = $willBeAvailable('symfony/cache', PsrCachedReader::class, 'doctrine/annotations'); - - $rootNode - ->children() - ->arrayNode('annotations') - ->info('annotation configuration') - ->{$willBeAvailable('doctrine/annotations', Annotation::class) ? 'canBeDisabled' : 'canBeEnabled'}() - ->children() - ->scalarNode('cache')->defaultValue(($doctrineCache || $psr6Cache) ? 'php_array' : 'none')->end() - ->scalarNode('file_cache_dir')->defaultValue('%kernel.cache_dir%/annotations')->end() - ->booleanNode('debug')->defaultValue($this->debug)->end() - ->end() - ->end() - ->end() - ; - } - - private function addSerializerSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone, callable $willBeAvailable) - { - $rootNode - ->children() - ->arrayNode('serializer') - ->info('serializer configuration') - ->{$enableIfStandalone('symfony/serializer', Serializer::class)}() - ->children() - ->booleanNode('enable_annotations')->{!class_exists(FullStack::class) && (\PHP_VERSION_ID >= 80000 || $willBeAvailable('doctrine/annotations', Annotation::class, 'symfony/serializer')) ? 'defaultTrue' : 'defaultFalse'}()->end() - ->scalarNode('name_converter')->end() - ->scalarNode('circular_reference_handler')->end() - ->scalarNode('max_depth_handler')->end() - ->arrayNode('mapping') - ->addDefaultsIfNotSet() - ->fixXmlConfig('path') - ->children() - ->arrayNode('paths') - ->prototype('scalar')->end() - ->end() - ->end() - ->end() - ->arrayNode('default_context') - ->normalizeKeys(false) - ->useAttributeAsKey('name') - ->defaultValue([]) - ->prototype('variable')->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addPropertyAccessSection(ArrayNodeDefinition $rootNode, callable $willBeAvailable) - { - $rootNode - ->children() - ->arrayNode('property_access') - ->addDefaultsIfNotSet() - ->info('Property access configuration') - ->{$willBeAvailable('symfony/property-access', PropertyAccessor::class) ? 'canBeDisabled' : 'canBeEnabled'}() - ->children() - ->booleanNode('magic_call')->defaultFalse()->end() - ->booleanNode('magic_get')->defaultTrue()->end() - ->booleanNode('magic_set')->defaultTrue()->end() - ->booleanNode('throw_exception_on_invalid_index')->defaultFalse()->end() - ->booleanNode('throw_exception_on_invalid_property_path')->defaultTrue()->end() - ->end() - ->end() - ->end() - ; - } - - private function addPropertyInfoSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone) - { - $rootNode - ->children() - ->arrayNode('property_info') - ->info('Property info configuration') - ->{$enableIfStandalone('symfony/property-info', PropertyInfoExtractorInterface::class)}() - ->end() - ->end() - ; - } - - private function addCacheSection(ArrayNodeDefinition $rootNode, callable $willBeAvailable) - { - $rootNode - ->children() - ->arrayNode('cache') - ->info('Cache configuration') - ->addDefaultsIfNotSet() - ->fixXmlConfig('pool') - ->children() - ->scalarNode('prefix_seed') - ->info('Used to namespace cache keys when using several apps with the same shared backend') - ->defaultValue('_%kernel.project_dir%.%kernel.container_class%') - ->example('my-application-name/%kernel.environment%') - ->end() - ->scalarNode('app') - ->info('App related cache pools configuration') - ->defaultValue('cache.adapter.filesystem') - ->end() - ->scalarNode('system') - ->info('System related cache pools configuration') - ->defaultValue('cache.adapter.system') - ->end() - ->scalarNode('directory')->defaultValue('%kernel.cache_dir%/pools/app')->end() - ->scalarNode('default_doctrine_provider')->end() - ->scalarNode('default_psr6_provider')->end() - ->scalarNode('default_redis_provider')->defaultValue('redis://localhost')->end() - ->scalarNode('default_memcached_provider')->defaultValue('memcached://localhost')->end() - ->scalarNode('default_doctrine_dbal_provider')->defaultValue('database_connection')->end() - ->scalarNode('default_pdo_provider')->defaultValue($willBeAvailable('doctrine/dbal', Connection::class) && class_exists(DoctrineAdapter::class) ? 'database_connection' : null)->end() - ->arrayNode('pools') - ->useAttributeAsKey('name') - ->prototype('array') - ->fixXmlConfig('adapter') - ->beforeNormalization() - ->ifTrue(function ($v) { return isset($v['provider']) && \is_array($v['adapters'] ?? $v['adapter'] ?? null) && 1 < \count($v['adapters'] ?? $v['adapter']); }) - ->thenInvalid('Pool cannot have a "provider" while more than one adapter is defined') - ->end() - ->children() - ->arrayNode('adapters') - ->performNoDeepMerging() - ->info('One or more adapters to chain for creating the pool, defaults to "cache.app".') - ->beforeNormalization()->castToArray()->end() - ->beforeNormalization() - ->always()->then(function ($values) { - if ([0] === array_keys($values) && \is_array($values[0])) { - return $values[0]; - } - $adapters = []; - - foreach ($values as $k => $v) { - if (\is_int($k) && \is_string($v)) { - $adapters[] = $v; - } elseif (!\is_array($v)) { - $adapters[$k] = $v; - } elseif (isset($v['provider'])) { - $adapters[$v['provider']] = $v['name'] ?? $v; - } else { - $adapters[] = $v['name'] ?? $v; - } - } - - return $adapters; - }) - ->end() - ->prototype('scalar')->end() - ->end() - ->scalarNode('tags')->defaultNull()->end() - ->booleanNode('public')->defaultFalse()->end() - ->scalarNode('default_lifetime') - ->info('Default lifetime of the pool') - ->example('"300" for 5 minutes expressed in seconds, "PT5M" for five minutes expressed as ISO 8601 time interval, or "5 minutes" as a date expression') - ->end() - ->scalarNode('provider') - ->info('Overwrite the setting from the default provider for this adapter.') - ->end() - ->scalarNode('early_expiration_message_bus') - ->example('"messenger.default_bus" to send early expiration events to the default Messenger bus.') - ->end() - ->scalarNode('clearer')->end() - ->end() - ->end() - ->validate() - ->ifTrue(function ($v) { return isset($v['cache.app']) || isset($v['cache.system']); }) - ->thenInvalid('"cache.app" and "cache.system" are reserved names') - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addPhpErrorsSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('php_errors') - ->info('PHP errors handling configuration') - ->addDefaultsIfNotSet() - ->children() - ->variableNode('log') - ->info('Use the application logger instead of the PHP logger for logging PHP errors.') - ->example('"true" to use the default configuration: log all errors. "false" to disable. An integer bit field of E_* constants, or an array mapping E_* constants to log levels.') - ->defaultValue($this->debug) - ->treatNullLike($this->debug) - ->beforeNormalization() - ->ifArray() - ->then(function (array $v): array { - if (!($v[0]['type'] ?? false)) { - return $v; - } - - // Fix XML normalization - - $ret = []; - foreach ($v as ['type' => $type, 'logLevel' => $logLevel]) { - $ret[$type] = $logLevel; - } - - return $ret; - }) - ->end() - ->validate() - ->ifTrue(function ($v) { return !(\is_int($v) || \is_bool($v) || \is_array($v)); }) - ->thenInvalid('The "php_errors.log" parameter should be either an integer, a boolean, or an array') - ->end() - ->end() - ->booleanNode('throw') - ->info('Throw PHP errors as \ErrorException instances.') - ->defaultValue($this->debug) - ->treatNullLike($this->debug) - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addExceptionsSection(ArrayNodeDefinition $rootNode) - { - $logLevels = (new \ReflectionClass(LogLevel::class))->getConstants(); - - $rootNode - ->fixXmlConfig('exception') - ->children() - ->arrayNode('exceptions') - ->info('Exception handling configuration') - ->useAttributeAsKey('class') - ->beforeNormalization() - // Handle legacy XML configuration - ->ifArray() - ->then(function (array $v): array { - if (!\array_key_exists('exception', $v)) { - return $v; - } - - $v = $v['exception']; - unset($v['exception']); - - foreach ($v as &$exception) { - $exception['class'] = $exception['name']; - unset($exception['name']); - } - - return $v; - }) - ->end() - ->prototype('array') - ->children() - ->scalarNode('log_level') - ->info('The level of log message. Null to let Symfony decide.') - ->validate() - ->ifTrue(function ($v) use ($logLevels) { return null !== $v && !\in_array($v, $logLevels, true); }) - ->thenInvalid(sprintf('The log level is not valid. Pick one among "%s".', implode('", "', $logLevels))) - ->end() - ->defaultNull() - ->end() - ->scalarNode('status_code') - ->info('The status code of the response. Null or 0 to let Symfony decide.') - ->beforeNormalization() - ->ifTrue(function ($v) { return 0 === $v; }) - ->then(function ($v) { return null; }) - ->end() - ->validate() - ->ifTrue(function ($v) { return null !== $v && ($v < 100 || $v > 599); }) - ->thenInvalid('The status code is not valid. Pick a value between 100 and 599.') - ->end() - ->defaultNull() - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addLockSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone) - { - $rootNode - ->children() - ->arrayNode('lock') - ->info('Lock configuration') - ->{$enableIfStandalone('symfony/lock', Lock::class)}() - ->beforeNormalization() - ->ifString()->then(function ($v) { return ['enabled' => true, 'resources' => $v]; }) - ->end() - ->beforeNormalization() - ->ifTrue(function ($v) { return \is_array($v) && !isset($v['enabled']); }) - ->then(function ($v) { return $v + ['enabled' => true]; }) - ->end() - ->beforeNormalization() - ->ifTrue(function ($v) { return \is_array($v) && !isset($v['resources']) && !isset($v['resource']); }) - ->then(function ($v) { - $e = $v['enabled']; - unset($v['enabled']); - - return ['enabled' => $e, 'resources' => $v]; - }) - ->end() - ->addDefaultsIfNotSet() - ->validate() - ->ifTrue(static function (array $config) { return $config['enabled'] && !$config['resources']; }) - ->thenInvalid('At least one resource must be defined.') - ->end() - ->fixXmlConfig('resource') - ->children() - ->arrayNode('resources') - ->normalizeKeys(false) - ->useAttributeAsKey('name') - ->defaultValue(['default' => [class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphore' : 'flock']]) - ->beforeNormalization() - ->ifString()->then(function ($v) { return ['default' => $v]; }) - ->end() - ->beforeNormalization() - ->ifTrue(function ($v) { return \is_array($v) && array_is_list($v); }) - ->then(function ($v) { - $resources = []; - foreach ($v as $resource) { - $resources[] = \is_array($resource) && isset($resource['name']) - ? [$resource['name'] => $resource['value']] - : ['default' => $resource] - ; - } - - return array_merge_recursive([], ...$resources); - }) - ->end() - ->prototype('array') - ->performNoDeepMerging() - ->beforeNormalization()->ifString()->then(function ($v) { return [$v]; })->end() - ->prototype('scalar')->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addWebLinkSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone) - { - $rootNode - ->children() - ->arrayNode('web_link') - ->info('web links configuration') - ->{$enableIfStandalone('symfony/weblink', HttpHeaderSerializer::class)}() - ->end() - ->end() - ; - } - - private function addMessengerSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone) - { - $rootNode - ->children() - ->arrayNode('messenger') - ->info('Messenger configuration') - ->{$enableIfStandalone('symfony/messenger', MessageBusInterface::class)}() - ->fixXmlConfig('transport') - ->fixXmlConfig('bus', 'buses') - ->validate() - ->ifTrue(function ($v) { return isset($v['buses']) && \count($v['buses']) > 1 && null === $v['default_bus']; }) - ->thenInvalid('You must specify the "default_bus" if you define more than one bus.') - ->end() - ->validate() - ->ifTrue(static function ($v): bool { return isset($v['buses']) && null !== $v['default_bus'] && !isset($v['buses'][$v['default_bus']]); }) - ->then(static function (array $v): void { throw new InvalidConfigurationException(sprintf('The specified default bus "%s" is not configured. Available buses are "%s".', $v['default_bus'], implode('", "', array_keys($v['buses'])))); }) - ->end() - ->children() - ->arrayNode('routing') - ->normalizeKeys(false) - ->useAttributeAsKey('message_class') - ->beforeNormalization() - ->always() - ->then(function ($config) { - if (!\is_array($config)) { - return []; - } - // If XML config with only one routing attribute - if (2 === \count($config) && isset($config['message-class']) && isset($config['sender'])) { - $config = [0 => $config]; - } - - $newConfig = []; - foreach ($config as $k => $v) { - if (!\is_int($k)) { - $newConfig[$k] = [ - 'senders' => $v['senders'] ?? (\is_array($v) ? array_values($v) : [$v]), - ]; - } else { - $newConfig[$v['message-class']]['senders'] = array_map( - function ($a) { - return \is_string($a) ? $a : $a['service']; - }, - array_values($v['sender']) - ); - } - } - - return $newConfig; - }) - ->end() - ->prototype('array') - ->performNoDeepMerging() - ->children() - ->arrayNode('senders') - ->requiresAtLeastOneElement() - ->prototype('scalar')->end() - ->end() - ->end() - ->end() - ->end() - ->arrayNode('serializer') - ->addDefaultsIfNotSet() - ->children() - ->scalarNode('default_serializer') - ->defaultValue('messenger.transport.native_php_serializer') - ->info('Service id to use as the default serializer for the transports.') - ->end() - ->arrayNode('symfony_serializer') - ->addDefaultsIfNotSet() - ->children() - ->scalarNode('format')->defaultValue('json')->info('Serialization format for the messenger.transport.symfony_serializer service (which is not the serializer used by default).')->end() - ->arrayNode('context') - ->normalizeKeys(false) - ->useAttributeAsKey('name') - ->defaultValue([]) - ->info('Context array for the messenger.transport.symfony_serializer service (which is not the serializer used by default).') - ->prototype('variable')->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->arrayNode('transports') - ->normalizeKeys(false) - ->useAttributeAsKey('name') - ->arrayPrototype() - ->beforeNormalization() - ->ifString() - ->then(function (string $dsn) { - return ['dsn' => $dsn]; - }) - ->end() - ->fixXmlConfig('option') - ->children() - ->scalarNode('dsn')->end() - ->scalarNode('serializer')->defaultNull()->info('Service id of a custom serializer to use.')->end() - ->arrayNode('options') - ->normalizeKeys(false) - ->defaultValue([]) - ->prototype('variable') - ->end() - ->end() - ->scalarNode('failure_transport') - ->defaultNull() - ->info('Transport name to send failed messages to (after all retries have failed).') - ->end() - ->arrayNode('retry_strategy') - ->addDefaultsIfNotSet() - ->beforeNormalization() - ->always(function ($v) { - if (isset($v['service']) && (isset($v['max_retries']) || isset($v['delay']) || isset($v['multiplier']) || isset($v['max_delay']))) { - throw new \InvalidArgumentException('The "service" cannot be used along with the other "retry_strategy" options.'); - } - - return $v; - }) - ->end() - ->children() - ->scalarNode('service')->defaultNull()->info('Service id to override the retry strategy entirely')->end() - ->integerNode('max_retries')->defaultValue(3)->min(0)->end() - ->integerNode('delay')->defaultValue(1000)->min(0)->info('Time in ms to delay (or the initial value when multiplier is used)')->end() - ->floatNode('multiplier')->defaultValue(2)->min(1)->info('If greater than 1, delay will grow exponentially for each retry: this delay = (delay * (multiple ^ retries))')->end() - ->integerNode('max_delay')->defaultValue(0)->min(0)->info('Max time in ms that a retry should ever be delayed (0 = infinite)')->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->scalarNode('failure_transport') - ->defaultNull() - ->info('Transport name to send failed messages to (after all retries have failed).') - ->end() - ->booleanNode('reset_on_message') - ->defaultNull() - ->info('Reset container services after each message.') - ->end() - ->scalarNode('default_bus')->defaultNull()->end() - ->arrayNode('buses') - ->defaultValue(['messenger.bus.default' => ['default_middleware' => true, 'middleware' => []]]) - ->normalizeKeys(false) - ->useAttributeAsKey('name') - ->arrayPrototype() - ->addDefaultsIfNotSet() - ->children() - ->enumNode('default_middleware') - ->values([true, false, 'allow_no_handlers']) - ->defaultTrue() - ->end() - ->arrayNode('middleware') - ->performNoDeepMerging() - ->beforeNormalization() - ->ifTrue(function ($v) { return \is_string($v) || (\is_array($v) && !\is_int(key($v))); }) - ->then(function ($v) { return [$v]; }) - ->end() - ->defaultValue([]) - ->arrayPrototype() - ->beforeNormalization() - ->always() - ->then(function ($middleware): array { - if (!\is_array($middleware)) { - return ['id' => $middleware]; - } - if (isset($middleware['id'])) { - return $middleware; - } - if (1 < \count($middleware)) { - throw new \InvalidArgumentException('Invalid middleware at path "framework.messenger": a map with a single factory id as key and its arguments as value was expected, '.json_encode($middleware).' given.'); - } - - return [ - 'id' => key($middleware), - 'arguments' => current($middleware), - ]; - }) - ->end() - ->fixXmlConfig('argument') - ->children() - ->scalarNode('id')->isRequired()->cannotBeEmpty()->end() - ->arrayNode('arguments') - ->normalizeKeys(false) - ->defaultValue([]) - ->prototype('variable') - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addRobotsIndexSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->booleanNode('disallow_search_engine_index') - ->info('Enabled by default when debug is enabled.') - ->defaultValue($this->debug) - ->treatNullLike($this->debug) - ->end() - ->end() - ; - } - - private function addHttpClientSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone) - { - $rootNode - ->children() - ->arrayNode('http_client') - ->info('HTTP Client configuration') - ->{$enableIfStandalone('symfony/http-client', HttpClient::class)}() - ->fixXmlConfig('scoped_client') - ->beforeNormalization() - ->always(function ($config) { - if (empty($config['scoped_clients']) || !\is_array($config['default_options']['retry_failed'] ?? null)) { - return $config; - } - - foreach ($config['scoped_clients'] as &$scopedConfig) { - if (!isset($scopedConfig['retry_failed']) || true === $scopedConfig['retry_failed']) { - $scopedConfig['retry_failed'] = $config['default_options']['retry_failed']; - continue; - } - if (\is_array($scopedConfig['retry_failed'])) { - $scopedConfig['retry_failed'] = $scopedConfig['retry_failed'] + $config['default_options']['retry_failed']; - } - } - - return $config; - }) - ->end() - ->children() - ->integerNode('max_host_connections') - ->info('The maximum number of connections to a single host.') - ->end() - ->arrayNode('default_options') - ->fixXmlConfig('header') - ->children() - ->arrayNode('headers') - ->info('Associative array: header => value(s).') - ->useAttributeAsKey('name') - ->normalizeKeys(false) - ->variablePrototype()->end() - ->end() - ->integerNode('max_redirects') - ->info('The maximum number of redirects to follow.') - ->end() - ->scalarNode('http_version') - ->info('The default HTTP version, typically 1.1 or 2.0, leave to null for the best version.') - ->end() - ->arrayNode('resolve') - ->info('Associative array: domain => IP.') - ->useAttributeAsKey('host') - ->beforeNormalization() - ->always(function ($config) { - if (!\is_array($config)) { - return []; - } - if (!isset($config['host'], $config['value']) || \count($config) > 2) { - return $config; - } - - return [$config['host'] => $config['value']]; - }) - ->end() - ->normalizeKeys(false) - ->scalarPrototype()->end() - ->end() - ->scalarNode('proxy') - ->info('The URL of the proxy to pass requests through or null for automatic detection.') - ->end() - ->scalarNode('no_proxy') - ->info('A comma separated list of hosts that do not require a proxy to be reached.') - ->end() - ->floatNode('timeout') - ->info('The idle timeout, defaults to the "default_socket_timeout" ini parameter.') - ->end() - ->floatNode('max_duration') - ->info('The maximum execution time for the request+response as a whole.') - ->end() - ->scalarNode('bindto') - ->info('A network interface name, IP address, a host name or a UNIX socket to bind to.') - ->end() - ->booleanNode('verify_peer') - ->info('Indicates if the peer should be verified in an SSL/TLS context.') - ->end() - ->booleanNode('verify_host') - ->info('Indicates if the host should exist as a certificate common name.') - ->end() - ->scalarNode('cafile') - ->info('A certificate authority file.') - ->end() - ->scalarNode('capath') - ->info('A directory that contains multiple certificate authority files.') - ->end() - ->scalarNode('local_cert') - ->info('A PEM formatted certificate file.') - ->end() - ->scalarNode('local_pk') - ->info('A private key file.') - ->end() - ->scalarNode('passphrase') - ->info('The passphrase used to encrypt the "local_pk" file.') - ->end() - ->scalarNode('ciphers') - ->info('A list of SSL/TLS ciphers separated by colons, commas or spaces (e.g. "RC3-SHA:TLS13-AES-128-GCM-SHA256"...)') - ->end() - ->arrayNode('peer_fingerprint') - ->info('Associative array: hashing algorithm => hash(es).') - ->normalizeKeys(false) - ->children() - ->variableNode('sha1')->end() - ->variableNode('pin-sha256')->end() - ->variableNode('md5')->end() - ->end() - ->end() - ->append($this->addHttpClientRetrySection()) - ->end() - ->end() - ->scalarNode('mock_response_factory') - ->info('The id of the service that should generate mock responses. It should be either an invokable or an iterable.') - ->end() - ->arrayNode('scoped_clients') - ->useAttributeAsKey('name') - ->normalizeKeys(false) - ->arrayPrototype() - ->fixXmlConfig('header') - ->beforeNormalization() - ->always() - ->then(function ($config) { - if (!class_exists(HttpClient::class)) { - throw new LogicException('HttpClient support cannot be enabled as the component is not installed. Try running "composer require symfony/http-client".'); - } - - return \is_array($config) ? $config : ['base_uri' => $config]; - }) - ->end() - ->validate() - ->ifTrue(function ($v) { return !isset($v['scope']) && !isset($v['base_uri']); }) - ->thenInvalid('Either "scope" or "base_uri" should be defined.') - ->end() - ->validate() - ->ifTrue(function ($v) { return !empty($v['query']) && !isset($v['base_uri']); }) - ->thenInvalid('"query" applies to "base_uri" but no base URI is defined.') - ->end() - ->children() - ->scalarNode('scope') - ->info('The regular expression that the request URL must match before adding the other options. When none is provided, the base URI is used instead.') - ->cannotBeEmpty() - ->end() - ->scalarNode('base_uri') - ->info('The URI to resolve relative URLs, following rules in RFC 3985, section 2.') - ->cannotBeEmpty() - ->end() - ->scalarNode('auth_basic') - ->info('An HTTP Basic authentication "username:password".') - ->end() - ->scalarNode('auth_bearer') - ->info('A token enabling HTTP Bearer authorization.') - ->end() - ->scalarNode('auth_ntlm') - ->info('A "username:password" pair to use Microsoft NTLM authentication (requires the cURL extension).') - ->end() - ->arrayNode('query') - ->info('Associative array of query string values merged with the base URI.') - ->useAttributeAsKey('key') - ->beforeNormalization() - ->always(function ($config) { - if (!\is_array($config)) { - return []; - } - if (!isset($config['key'], $config['value']) || \count($config) > 2) { - return $config; - } - - return [$config['key'] => $config['value']]; - }) - ->end() - ->normalizeKeys(false) - ->scalarPrototype()->end() - ->end() - ->arrayNode('headers') - ->info('Associative array: header => value(s).') - ->useAttributeAsKey('name') - ->normalizeKeys(false) - ->variablePrototype()->end() - ->end() - ->integerNode('max_redirects') - ->info('The maximum number of redirects to follow.') - ->end() - ->scalarNode('http_version') - ->info('The default HTTP version, typically 1.1 or 2.0, leave to null for the best version.') - ->end() - ->arrayNode('resolve') - ->info('Associative array: domain => IP.') - ->useAttributeAsKey('host') - ->beforeNormalization() - ->always(function ($config) { - if (!\is_array($config)) { - return []; - } - if (!isset($config['host'], $config['value']) || \count($config) > 2) { - return $config; - } - - return [$config['host'] => $config['value']]; - }) - ->end() - ->normalizeKeys(false) - ->scalarPrototype()->end() - ->end() - ->scalarNode('proxy') - ->info('The URL of the proxy to pass requests through or null for automatic detection.') - ->end() - ->scalarNode('no_proxy') - ->info('A comma separated list of hosts that do not require a proxy to be reached.') - ->end() - ->floatNode('timeout') - ->info('The idle timeout, defaults to the "default_socket_timeout" ini parameter.') - ->end() - ->floatNode('max_duration') - ->info('The maximum execution time for the request+response as a whole.') - ->end() - ->scalarNode('bindto') - ->info('A network interface name, IP address, a host name or a UNIX socket to bind to.') - ->end() - ->booleanNode('verify_peer') - ->info('Indicates if the peer should be verified in an SSL/TLS context.') - ->end() - ->booleanNode('verify_host') - ->info('Indicates if the host should exist as a certificate common name.') - ->end() - ->scalarNode('cafile') - ->info('A certificate authority file.') - ->end() - ->scalarNode('capath') - ->info('A directory that contains multiple certificate authority files.') - ->end() - ->scalarNode('local_cert') - ->info('A PEM formatted certificate file.') - ->end() - ->scalarNode('local_pk') - ->info('A private key file.') - ->end() - ->scalarNode('passphrase') - ->info('The passphrase used to encrypt the "local_pk" file.') - ->end() - ->scalarNode('ciphers') - ->info('A list of SSL/TLS ciphers separated by colons, commas or spaces (e.g. "RC3-SHA:TLS13-AES-128-GCM-SHA256"...)') - ->end() - ->arrayNode('peer_fingerprint') - ->info('Associative array: hashing algorithm => hash(es).') - ->normalizeKeys(false) - ->children() - ->variableNode('sha1')->end() - ->variableNode('pin-sha256')->end() - ->variableNode('md5')->end() - ->end() - ->end() - ->append($this->addHttpClientRetrySection()) - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addHttpClientRetrySection() - { - $root = new NodeBuilder(); - - return $root - ->arrayNode('retry_failed') - ->fixXmlConfig('http_code') - ->canBeEnabled() - ->addDefaultsIfNotSet() - ->beforeNormalization() - ->always(function ($v) { - if (isset($v['retry_strategy']) && (isset($v['http_codes']) || isset($v['delay']) || isset($v['multiplier']) || isset($v['max_delay']) || isset($v['jitter']))) { - throw new \InvalidArgumentException('The "retry_strategy" option cannot be used along with the "http_codes", "delay", "multiplier", "max_delay" or "jitter" options.'); - } - - return $v; - }) - ->end() - ->children() - ->scalarNode('retry_strategy')->defaultNull()->info('service id to override the retry strategy')->end() - ->arrayNode('http_codes') - ->performNoDeepMerging() - ->beforeNormalization() - ->ifArray() - ->then(static function ($v) { - $list = []; - foreach ($v as $key => $val) { - if (is_numeric($val)) { - $list[] = ['code' => $val]; - } elseif (\is_array($val)) { - if (isset($val['code']) || isset($val['methods'])) { - $list[] = $val; - } else { - $list[] = ['code' => $key, 'methods' => $val]; - } - } elseif (true === $val || null === $val) { - $list[] = ['code' => $key]; - } - } - - return $list; - }) - ->end() - ->useAttributeAsKey('code') - ->arrayPrototype() - ->fixXmlConfig('method') - ->children() - ->integerNode('code')->end() - ->arrayNode('methods') - ->beforeNormalization() - ->ifArray() - ->then(function ($v) { - return array_map('strtoupper', $v); - }) - ->end() - ->prototype('scalar')->end() - ->info('A list of HTTP methods that triggers a retry for this status code. When empty, all methods are retried') - ->end() - ->end() - ->end() - ->info('A list of HTTP status code that triggers a retry') - ->end() - ->integerNode('max_retries')->defaultValue(3)->min(0)->end() - ->integerNode('delay')->defaultValue(1000)->min(0)->info('Time in ms to delay (or the initial value when multiplier is used)')->end() - ->floatNode('multiplier')->defaultValue(2)->min(1)->info('If greater than 1, delay will grow exponentially for each retry: delay * (multiple ^ retries)')->end() - ->integerNode('max_delay')->defaultValue(0)->min(0)->info('Max time in ms that a retry should ever be delayed (0 = infinite)')->end() - ->floatNode('jitter')->defaultValue(0.1)->min(0)->max(1)->info('Randomness in percent (between 0 and 1) to apply to the delay')->end() - ->end() - ; - } - - private function addMailerSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone) - { - $rootNode - ->children() - ->arrayNode('mailer') - ->info('Mailer configuration') - ->{$enableIfStandalone('symfony/mailer', Mailer::class)}() - ->validate() - ->ifTrue(function ($v) { return isset($v['dsn']) && \count($v['transports']); }) - ->thenInvalid('"dsn" and "transports" cannot be used together.') - ->end() - ->fixXmlConfig('transport') - ->fixXmlConfig('header') - ->children() - ->scalarNode('message_bus')->defaultNull()->info('The message bus to use. Defaults to the default bus if the Messenger component is installed.')->end() - ->scalarNode('dsn')->defaultNull()->end() - ->arrayNode('transports') - ->useAttributeAsKey('name') - ->prototype('scalar')->end() - ->end() - ->arrayNode('envelope') - ->info('Mailer Envelope configuration') - ->children() - ->scalarNode('sender')->end() - ->arrayNode('recipients') - ->performNoDeepMerging() - ->beforeNormalization() - ->ifArray() - ->then(function ($v) { - return array_filter(array_values($v)); - }) - ->end() - ->prototype('scalar')->end() - ->end() - ->end() - ->end() - ->arrayNode('headers') - ->normalizeKeys(false) - ->useAttributeAsKey('name') - ->prototype('array') - ->normalizeKeys(false) - ->beforeNormalization() - ->ifTrue(function ($v) { return !\is_array($v) || array_keys($v) !== ['value']; }) - ->then(function ($v) { return ['value' => $v]; }) - ->end() - ->children() - ->variableNode('value')->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addNotifierSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone) - { - $rootNode - ->children() - ->arrayNode('notifier') - ->info('Notifier configuration') - ->{$enableIfStandalone('symfony/notifier', Notifier::class)}() - ->fixXmlConfig('chatter_transport') - ->children() - ->arrayNode('chatter_transports') - ->useAttributeAsKey('name') - ->prototype('scalar')->end() - ->end() - ->end() - ->fixXmlConfig('texter_transport') - ->children() - ->arrayNode('texter_transports') - ->useAttributeAsKey('name') - ->prototype('scalar')->end() - ->end() - ->end() - ->children() - ->booleanNode('notification_on_failed_messages')->defaultFalse()->end() - ->end() - ->children() - ->arrayNode('channel_policy') - ->useAttributeAsKey('name') - ->prototype('array') - ->beforeNormalization()->ifString()->then(function (string $v) { return [$v]; })->end() - ->prototype('scalar')->end() - ->end() - ->end() - ->end() - ->fixXmlConfig('admin_recipient') - ->children() - ->arrayNode('admin_recipients') - ->prototype('array') - ->children() - ->scalarNode('email')->cannotBeEmpty()->end() - ->scalarNode('phone')->defaultValue('')->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addRateLimiterSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone) - { - $rootNode - ->children() - ->arrayNode('rate_limiter') - ->info('Rate limiter configuration') - ->{$enableIfStandalone('symfony/rate-limiter', TokenBucketLimiter::class)}() - ->fixXmlConfig('limiter') - ->beforeNormalization() - ->ifTrue(function ($v) { return \is_array($v) && !isset($v['limiters']) && !isset($v['limiter']); }) - ->then(function (array $v) { - $newV = [ - 'enabled' => $v['enabled'] ?? true, - ]; - unset($v['enabled']); - - $newV['limiters'] = $v; - - return $newV; - }) - ->end() - ->children() - ->arrayNode('limiters') - ->useAttributeAsKey('name') - ->arrayPrototype() - ->children() - ->scalarNode('lock_factory') - ->info('The service ID of the lock factory used by this limiter (or null to disable locking)') - ->defaultValue('lock.factory') - ->end() - ->scalarNode('cache_pool') - ->info('The cache pool to use for storing the current limiter state') - ->defaultValue('cache.rate_limiter') - ->end() - ->scalarNode('storage_service') - ->info('The service ID of a custom storage implementation, this precedes any configured "cache_pool"') - ->defaultNull() - ->end() - ->enumNode('policy') - ->info('The algorithm to be used by this limiter') - ->isRequired() - ->values(['fixed_window', 'token_bucket', 'sliding_window', 'no_limit']) - ->end() - ->integerNode('limit') - ->info('The maximum allowed hits in a fixed interval or burst') - ->isRequired() - ->end() - ->scalarNode('interval') - ->info('Configures the fixed interval if "policy" is set to "fixed_window" or "sliding_window". The value must be a number followed by "second", "minute", "hour", "day", "week" or "month" (or their plural equivalent).') - ->end() - ->arrayNode('rate') - ->info('Configures the fill rate if "policy" is set to "token_bucket"') - ->children() - ->scalarNode('interval') - ->info('Configures the rate interval. The value must be a number followed by "second", "minute", "hour", "day", "week" or "month" (or their plural equivalent).') - ->end() - ->integerNode('amount')->info('Amount of tokens to add each interval')->defaultValue(1)->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addUidSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone) - { - $rootNode - ->children() - ->arrayNode('uid') - ->info('Uid configuration') - ->{$enableIfStandalone('symfony/uid', UuidFactory::class)}() - ->addDefaultsIfNotSet() - ->children() - ->enumNode('default_uuid_version') - ->defaultValue(6) - ->values([6, 4, 1]) - ->end() - ->enumNode('name_based_uuid_version') - ->defaultValue(5) - ->values([5, 3]) - ->end() - ->scalarNode('name_based_uuid_namespace') - ->cannotBeEmpty() - ->end() - ->enumNode('time_based_uuid_version') - ->defaultValue(6) - ->values([6, 1]) - ->end() - ->scalarNode('time_based_uuid_node') - ->cannotBeEmpty() - ->end() - ->end() - ->end() - ->end() - ; - } -} diff --git a/lib/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php b/lib/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php deleted file mode 100644 index 00412e5c6..000000000 --- a/lib/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php +++ /dev/null @@ -1,2717 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection; - -use Composer\InstalledVersions; -use Doctrine\Common\Annotations\AnnotationRegistry; -use Doctrine\Common\Annotations\Reader; -use Http\Client\HttpClient; -use phpDocumentor\Reflection\DocBlockFactoryInterface; -use phpDocumentor\Reflection\Types\ContextFactory; -use PHPStan\PhpDocParser\Parser\PhpDocParser; -use Psr\Cache\CacheItemPoolInterface; -use Psr\Container\ContainerInterface as PsrContainerInterface; -use Psr\EventDispatcher\EventDispatcherInterface as PsrEventDispatcherInterface; -use Psr\Http\Client\ClientInterface; -use Psr\Log\LoggerAwareInterface; -use Symfony\Bridge\Monolog\Processor\DebugProcessor; -use Symfony\Bridge\Twig\Extension\CsrfExtension; -use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; -use Symfony\Bundle\FrameworkBundle\Routing\AnnotatedRouteControllerLoader; -use Symfony\Bundle\FrameworkBundle\Routing\RouteLoaderInterface; -use Symfony\Bundle\FullStack; -use Symfony\Bundle\MercureBundle\MercureBundle; -use Symfony\Component\Asset\PackageInterface; -use Symfony\Component\BrowserKit\AbstractBrowser; -use Symfony\Component\Cache\Adapter\AdapterInterface; -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\ChainAdapter; -use Symfony\Component\Cache\Adapter\DoctrineAdapter; -use Symfony\Component\Cache\Adapter\DoctrineDbalAdapter; -use Symfony\Component\Cache\Adapter\TagAwareAdapter; -use Symfony\Component\Cache\DependencyInjection\CachePoolPass; -use Symfony\Component\Cache\Marshaller\DefaultMarshaller; -use Symfony\Component\Cache\Marshaller\MarshallerInterface; -use Symfony\Component\Cache\ResettableInterface; -use Symfony\Component\Config\FileLocator; -use Symfony\Component\Config\Loader\LoaderInterface; -use Symfony\Component\Config\Resource\DirectoryResource; -use Symfony\Component\Config\ResourceCheckerInterface; -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\EnvVarLoaderInterface; -use Symfony\Component\DependencyInjection\EnvVarProcessorInterface; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\LogicException; -use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; -use Symfony\Component\DependencyInjection\Parameter; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\ServiceLocator; -use Symfony\Component\Dotenv\Command\DebugCommand; -use Symfony\Component\EventDispatcher\Attribute\AsEventListener; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\ExpressionLanguage\ExpressionLanguage; -use Symfony\Component\Finder\Finder; -use Symfony\Component\Form\ChoiceList\Factory\CachingFactoryDecorator; -use Symfony\Component\Form\Form; -use Symfony\Component\Form\FormTypeExtensionInterface; -use Symfony\Component\Form\FormTypeGuesserInterface; -use Symfony\Component\Form\FormTypeInterface; -use Symfony\Component\HttpClient\MockHttpClient; -use Symfony\Component\HttpClient\Retry\GenericRetryStrategy; -use Symfony\Component\HttpClient\RetryableHttpClient; -use Symfony\Component\HttpClient\ScopingHttpClient; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface; -use Symfony\Component\HttpKernel\Attribute\AsController; -use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface; -use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; -use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; -use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; -use Symfony\Component\HttpKernel\DependencyInjection\Extension; -use Symfony\Component\Lock\Lock; -use Symfony\Component\Lock\LockFactory; -use Symfony\Component\Lock\LockInterface; -use Symfony\Component\Lock\PersistingStoreInterface; -use Symfony\Component\Lock\Store\StoreFactory; -use Symfony\Component\Lock\StoreInterface; -use Symfony\Component\Mailer\Bridge\Amazon\Transport\SesTransportFactory; -use Symfony\Component\Mailer\Bridge\Google\Transport\GmailTransportFactory; -use Symfony\Component\Mailer\Bridge\Mailchimp\Transport\MandrillTransportFactory; -use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory; -use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory; -use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory; -use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; -use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; -use Symfony\Component\Mailer\Bridge\Sendinblue\Transport\SendinblueTransportFactory; -use Symfony\Component\Mailer\Mailer; -use Symfony\Component\Mercure\HubRegistry; -use Symfony\Component\Messenger\Attribute\AsMessageHandler; -use Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\AmazonSqsTransportFactory; -use Symfony\Component\Messenger\Bridge\Amqp\Transport\AmqpTransportFactory; -use Symfony\Component\Messenger\Bridge\Beanstalkd\Transport\BeanstalkdTransportFactory; -use Symfony\Component\Messenger\Bridge\Redis\Transport\RedisTransportFactory; -use Symfony\Component\Messenger\Handler\BatchHandlerInterface; -use Symfony\Component\Messenger\Handler\MessageHandlerInterface; -use Symfony\Component\Messenger\MessageBus; -use Symfony\Component\Messenger\MessageBusInterface; -use Symfony\Component\Messenger\Middleware\RouterContextMiddleware; -use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface; -use Symfony\Component\Messenger\Transport\TransportFactoryInterface; -use Symfony\Component\Messenger\Transport\TransportInterface; -use Symfony\Component\Mime\Header\Headers; -use Symfony\Component\Mime\MimeTypeGuesserInterface; -use Symfony\Component\Mime\MimeTypes; -use Symfony\Component\Notifier\Bridge\AllMySms\AllMySmsTransportFactory; -use Symfony\Component\Notifier\Bridge\AmazonSns\AmazonSnsTransportFactory; -use Symfony\Component\Notifier\Bridge\Clickatell\ClickatellTransportFactory; -use Symfony\Component\Notifier\Bridge\Discord\DiscordTransportFactory; -use Symfony\Component\Notifier\Bridge\Esendex\EsendexTransportFactory; -use Symfony\Component\Notifier\Bridge\Expo\ExpoTransportFactory; -use Symfony\Component\Notifier\Bridge\FakeChat\FakeChatTransportFactory; -use Symfony\Component\Notifier\Bridge\FakeSms\FakeSmsTransportFactory; -use Symfony\Component\Notifier\Bridge\Firebase\FirebaseTransportFactory; -use Symfony\Component\Notifier\Bridge\FreeMobile\FreeMobileTransportFactory; -use Symfony\Component\Notifier\Bridge\GatewayApi\GatewayApiTransportFactory; -use Symfony\Component\Notifier\Bridge\Gitter\GitterTransportFactory; -use Symfony\Component\Notifier\Bridge\GoogleChat\GoogleChatTransportFactory; -use Symfony\Component\Notifier\Bridge\Infobip\InfobipTransportFactory; -use Symfony\Component\Notifier\Bridge\Iqsms\IqsmsTransportFactory; -use Symfony\Component\Notifier\Bridge\LightSms\LightSmsTransportFactory; -use Symfony\Component\Notifier\Bridge\LinkedIn\LinkedInTransportFactory; -use Symfony\Component\Notifier\Bridge\Mailjet\MailjetTransportFactory as MailjetNotifierTransportFactory; -use Symfony\Component\Notifier\Bridge\Mattermost\MattermostTransportFactory; -use Symfony\Component\Notifier\Bridge\Mercure\MercureTransportFactory; -use Symfony\Component\Notifier\Bridge\MessageBird\MessageBirdTransport; -use Symfony\Component\Notifier\Bridge\MessageMedia\MessageMediaTransportFactory; -use Symfony\Component\Notifier\Bridge\MicrosoftTeams\MicrosoftTeamsTransportFactory; -use Symfony\Component\Notifier\Bridge\Mobyt\MobytTransportFactory; -use Symfony\Component\Notifier\Bridge\Nexmo\NexmoTransportFactory; -use Symfony\Component\Notifier\Bridge\Octopush\OctopushTransportFactory; -use Symfony\Component\Notifier\Bridge\OneSignal\OneSignalTransportFactory; -use Symfony\Component\Notifier\Bridge\OvhCloud\OvhCloudTransportFactory; -use Symfony\Component\Notifier\Bridge\RocketChat\RocketChatTransportFactory; -use Symfony\Component\Notifier\Bridge\Sendinblue\SendinblueTransportFactory as SendinblueNotifierTransportFactory; -use Symfony\Component\Notifier\Bridge\Sinch\SinchTransportFactory; -use Symfony\Component\Notifier\Bridge\Slack\SlackTransportFactory; -use Symfony\Component\Notifier\Bridge\Sms77\Sms77TransportFactory; -use Symfony\Component\Notifier\Bridge\Smsapi\SmsapiTransportFactory; -use Symfony\Component\Notifier\Bridge\SmsBiuras\SmsBiurasTransportFactory; -use Symfony\Component\Notifier\Bridge\Smsc\SmscTransportFactory; -use Symfony\Component\Notifier\Bridge\SpotHit\SpotHitTransportFactory; -use Symfony\Component\Notifier\Bridge\Telegram\TelegramTransportFactory; -use Symfony\Component\Notifier\Bridge\Telnyx\TelnyxTransportFactory; -use Symfony\Component\Notifier\Bridge\TurboSms\TurboSmsTransport; -use Symfony\Component\Notifier\Bridge\Twilio\TwilioTransportFactory; -use Symfony\Component\Notifier\Bridge\Vonage\VonageTransportFactory; -use Symfony\Component\Notifier\Bridge\Yunpian\YunpianTransportFactory; -use Symfony\Component\Notifier\Bridge\Zulip\ZulipTransportFactory; -use Symfony\Component\Notifier\ChatterInterface; -use Symfony\Component\Notifier\Notifier; -use Symfony\Component\Notifier\Recipient\Recipient; -use Symfony\Component\Notifier\TexterInterface; -use Symfony\Component\Notifier\Transport\TransportFactoryInterface as NotifierTransportFactoryInterface; -use Symfony\Component\PropertyAccess\PropertyAccessor; -use Symfony\Component\PropertyInfo\Extractor\PhpStanExtractor; -use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyInitializableExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyListExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyReadInfoExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyWriteInfoExtractorInterface; -use Symfony\Component\RateLimiter\LimiterInterface; -use Symfony\Component\RateLimiter\RateLimiterFactory; -use Symfony\Component\RateLimiter\Storage\CacheStorage; -use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader; -use Symfony\Component\Routing\Loader\AnnotationFileLoader; -use Symfony\Component\Security\Core\Exception\AuthenticationException; -use Symfony\Component\Security\Core\Security; -use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; -use Symfony\Component\Serializer\Encoder\DecoderInterface; -use Symfony\Component\Serializer\Encoder\EncoderInterface; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; -use Symfony\Component\Serializer\Normalizer\UnwrappingDenormalizer; -use Symfony\Component\Stopwatch\Stopwatch; -use Symfony\Component\String\LazyString; -use Symfony\Component\String\Slugger\SluggerInterface; -use Symfony\Component\Translation\Bridge\Crowdin\CrowdinProviderFactory; -use Symfony\Component\Translation\Bridge\Loco\LocoProviderFactory; -use Symfony\Component\Translation\Bridge\Lokalise\LokaliseProviderFactory; -use Symfony\Component\Translation\Command\XliffLintCommand as BaseXliffLintCommand; -use Symfony\Component\Translation\PseudoLocalizationTranslator; -use Symfony\Component\Translation\Translator; -use Symfony\Component\Uid\Factory\UuidFactory; -use Symfony\Component\Uid\UuidV4; -use Symfony\Component\Validator\ConstraintValidatorInterface; -use Symfony\Component\Validator\Mapping\Loader\PropertyInfoLoader; -use Symfony\Component\Validator\ObjectInitializerInterface; -use Symfony\Component\Validator\Validation; -use Symfony\Component\WebLink\HttpHeaderSerializer; -use Symfony\Component\Workflow; -use Symfony\Component\Workflow\WorkflowInterface; -use Symfony\Component\Yaml\Command\LintCommand as BaseYamlLintCommand; -use Symfony\Component\Yaml\Yaml; -use Symfony\Contracts\Cache\CacheInterface; -use Symfony\Contracts\Cache\CallbackInterface; -use Symfony\Contracts\Cache\TagAwareCacheInterface; -use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; -use Symfony\Contracts\HttpClient\HttpClientInterface; -use Symfony\Contracts\Service\ResetInterface; -use Symfony\Contracts\Service\ServiceSubscriberInterface; -use Symfony\Contracts\Translation\LocaleAwareInterface; - -/** - * Process the configuration and prepare the dependency injection container with - * parameters and services. - */ -class FrameworkExtension extends Extension -{ - private $formConfigEnabled = false; - private $translationConfigEnabled = false; - private $sessionConfigEnabled = false; - private $annotationsConfigEnabled = false; - private $validatorConfigEnabled = false; - private $messengerConfigEnabled = false; - private $mailerConfigEnabled = false; - private $httpClientConfigEnabled = false; - private $notifierConfigEnabled = false; - private $propertyAccessConfigEnabled = false; - private static $lockConfigEnabled = false; - - /** - * Responds to the app.config configuration parameter. - * - * @throws LogicException - */ - public function load(array $configs, ContainerBuilder $container) - { - if (!class_exists(InstalledVersions::class)) { - trigger_deprecation('symfony/framework-bundle', '5.4', 'Configuring Symfony without the Composer Runtime API is deprecated. Consider upgrading to Composer 2.1 or later.'); - } - - $loader = new PhpFileLoader($container, new FileLocator(\dirname(__DIR__).'/Resources/config')); - - $loader->load('web.php'); - $loader->load('services.php'); - $loader->load('fragment_renderer.php'); - $loader->load('error_renderer.php'); - - if (ContainerBuilder::willBeAvailable('psr/event-dispatcher', PsrEventDispatcherInterface::class, ['symfony/framework-bundle'], true)) { - $container->setAlias(PsrEventDispatcherInterface::class, 'event_dispatcher'); - } - - $container->registerAliasForArgument('parameter_bag', PsrContainerInterface::class); - - if ($this->hasConsole()) { - $loader->load('console.php'); - - if (!class_exists(BaseXliffLintCommand::class)) { - $container->removeDefinition('console.command.xliff_lint'); - } - if (!class_exists(BaseYamlLintCommand::class)) { - $container->removeDefinition('console.command.yaml_lint'); - } - - if (!class_exists(DebugCommand::class)) { - $container->removeDefinition('console.command.dotenv_debug'); - } - } - - // Load Cache configuration first as it is used by other components - $loader->load('cache.php'); - - $configuration = $this->getConfiguration($configs, $container); - $config = $this->processConfiguration($configuration, $configs); - - $this->annotationsConfigEnabled = $this->isConfigEnabled($container, $config['annotations']); - $this->translationConfigEnabled = $this->isConfigEnabled($container, $config['translator']); - - // A translator must always be registered (as support is included by - // default in the Form and Validator component). If disabled, an identity - // translator will be used and everything will still work as expected. - if ($this->isConfigEnabled($container, $config['translator']) || $this->isConfigEnabled($container, $config['form']) || $this->isConfigEnabled($container, $config['validation'])) { - if (!class_exists(Translator::class) && $this->isConfigEnabled($container, $config['translator'])) { - throw new LogicException('Translation support cannot be enabled as the Translation component is not installed. Try running "composer require symfony/translation".'); - } - - if (class_exists(Translator::class)) { - $loader->load('identity_translator.php'); - } - } - - $container->getDefinition('locale_listener')->replaceArgument(3, $config['set_locale_from_accept_language']); - $container->getDefinition('response_listener')->replaceArgument(1, $config['set_content_language_from_locale']); - - // If the slugger is used but the String component is not available, we should throw an error - if (!ContainerBuilder::willBeAvailable('symfony/string', SluggerInterface::class, ['symfony/framework-bundle'], true)) { - $container->register('slugger', 'stdClass') - ->addError('You cannot use the "slugger" service since the String component is not installed. Try running "composer require symfony/string".'); - } else { - if (!ContainerBuilder::willBeAvailable('symfony/translation', LocaleAwareInterface::class, ['symfony/framework-bundle'], true)) { - $container->register('slugger', 'stdClass') - ->addError('You cannot use the "slugger" service since the Translation contracts are not installed. Try running "composer require symfony/translation".'); - } - - if (!\extension_loaded('intl') && !\defined('PHPUNIT_COMPOSER_INSTALL')) { - trigger_deprecation('', '', 'Please install the "intl" PHP extension for best performance.'); - } - } - - if (isset($config['secret'])) { - $container->setParameter('kernel.secret', $config['secret']); - } - - $container->setParameter('kernel.http_method_override', $config['http_method_override']); - $container->setParameter('kernel.trusted_hosts', $config['trusted_hosts']); - $container->setParameter('kernel.default_locale', $config['default_locale']); - $container->setParameter('kernel.enabled_locales', $config['enabled_locales']); - $container->setParameter('kernel.error_controller', $config['error_controller']); - - if (($config['trusted_proxies'] ?? false) && ($config['trusted_headers'] ?? false)) { - $container->setParameter('kernel.trusted_proxies', $config['trusted_proxies']); - $container->setParameter('kernel.trusted_headers', $this->resolveTrustedHeaders($config['trusted_headers'])); - } - - if (!$container->hasParameter('debug.file_link_format')) { - $container->setParameter('debug.file_link_format', $config['ide']); - } - - if (!empty($config['test'])) { - $loader->load('test.php'); - - if (!class_exists(AbstractBrowser::class)) { - $container->removeDefinition('test.client'); - } - } - - if ($this->isConfigEnabled($container, $config['request'])) { - $this->registerRequestConfiguration($config['request'], $container, $loader); - } - - if ($this->isConfigEnabled($container, $config['assets'])) { - if (!class_exists(\Symfony\Component\Asset\Package::class)) { - throw new LogicException('Asset support cannot be enabled as the Asset component is not installed. Try running "composer require symfony/asset".'); - } - - $this->registerAssetsConfiguration($config['assets'], $container, $loader); - } - - if ($this->httpClientConfigEnabled = $this->isConfigEnabled($container, $config['http_client'])) { - $this->registerHttpClientConfiguration($config['http_client'], $container, $loader, $config['profiler']); - } - - if ($this->mailerConfigEnabled = $this->isConfigEnabled($container, $config['mailer'])) { - $this->registerMailerConfiguration($config['mailer'], $container, $loader); - } - - $propertyInfoEnabled = $this->isConfigEnabled($container, $config['property_info']); - $this->registerHttpCacheConfiguration($config['http_cache'], $container, $config['http_method_override']); - $this->registerEsiConfiguration($config['esi'], $container, $loader); - $this->registerSsiConfiguration($config['ssi'], $container, $loader); - $this->registerFragmentsConfiguration($config['fragments'], $container, $loader); - $this->registerTranslatorConfiguration($config['translator'], $container, $loader, $config['default_locale'], $config['enabled_locales']); - $this->registerWorkflowConfiguration($config['workflows'], $container, $loader); - $this->registerDebugConfiguration($config['php_errors'], $container, $loader); - // @deprecated since Symfony 5.4, in 6.0 change to: - // $this->registerRouterConfiguration($config['router'], $container, $loader, $config['enabled_locales']); - $this->registerRouterConfiguration($config['router'], $container, $loader, $config['translator']['enabled_locales'] ?: $config['enabled_locales']); - $this->registerAnnotationsConfiguration($config['annotations'], $container, $loader); - $this->registerPropertyAccessConfiguration($config['property_access'], $container, $loader); - $this->registerSecretsConfiguration($config['secrets'], $container, $loader); - - $container->getDefinition('exception_listener')->replaceArgument(3, $config['exceptions']); - - if ($this->isConfigEnabled($container, $config['serializer'])) { - if (!class_exists(\Symfony\Component\Serializer\Serializer::class)) { - throw new LogicException('Serializer support cannot be enabled as the Serializer component is not installed. Try running "composer require symfony/serializer-pack".'); - } - - $this->registerSerializerConfiguration($config['serializer'], $container, $loader); - } - - if ($propertyInfoEnabled) { - $this->registerPropertyInfoConfiguration($container, $loader); - } - - if (self::$lockConfigEnabled = $this->isConfigEnabled($container, $config['lock'])) { - $this->registerLockConfiguration($config['lock'], $container, $loader); - } - - if ($this->isConfigEnabled($container, $config['rate_limiter'])) { - if (!interface_exists(LimiterInterface::class)) { - throw new LogicException('Rate limiter support cannot be enabled as the RateLimiter component is not installed. Try running "composer require symfony/rate-limiter".'); - } - - $this->registerRateLimiterConfiguration($config['rate_limiter'], $container, $loader); - } - - if ($this->isConfigEnabled($container, $config['web_link'])) { - if (!class_exists(HttpHeaderSerializer::class)) { - throw new LogicException('WebLink support cannot be enabled as the WebLink component is not installed. Try running "composer require symfony/weblink".'); - } - - $loader->load('web_link.php'); - } - - if ($this->isConfigEnabled($container, $config['uid'])) { - if (!class_exists(UuidFactory::class)) { - throw new LogicException('Uid support cannot be enabled as the Uid component is not installed. Try running "composer require symfony/uid".'); - } - - $this->registerUidConfiguration($config['uid'], $container, $loader); - } - - // register cache before session so both can share the connection services - $this->registerCacheConfiguration($config['cache'], $container); - - if ($this->isConfigEnabled($container, $config['session'])) { - if (!\extension_loaded('session')) { - throw new LogicException('Session support cannot be enabled as the session extension is not installed. See https://php.net/session.installation for instructions.'); - } - - $this->sessionConfigEnabled = true; - $this->registerSessionConfiguration($config['session'], $container, $loader); - if (!empty($config['test'])) { - // test listener will replace the existing session listener - // as we are aliasing to avoid duplicated registered events - $container->setAlias('session_listener', 'test.session.listener'); - } - } elseif (!empty($config['test'])) { - $container->removeDefinition('test.session.listener'); - } - - // csrf depends on session being registered - if (null === $config['csrf_protection']['enabled']) { - $config['csrf_protection']['enabled'] = $this->sessionConfigEnabled && !class_exists(FullStack::class) && ContainerBuilder::willBeAvailable('symfony/security-csrf', CsrfTokenManagerInterface::class, ['symfony/framework-bundle'], true); - } - $this->registerSecurityCsrfConfiguration($config['csrf_protection'], $container, $loader); - - // form depends on csrf being registered - if ($this->isConfigEnabled($container, $config['form'])) { - if (!class_exists(Form::class)) { - throw new LogicException('Form support cannot be enabled as the Form component is not installed. Try running "composer require symfony/form".'); - } - - $this->formConfigEnabled = true; - $this->registerFormConfiguration($config, $container, $loader); - - if (ContainerBuilder::willBeAvailable('symfony/validator', Validation::class, ['symfony/framework-bundle', 'symfony/form'], true)) { - $config['validation']['enabled'] = true; - } else { - $container->setParameter('validator.translation_domain', 'validators'); - - $container->removeDefinition('form.type_extension.form.validator'); - $container->removeDefinition('form.type_guesser.validator'); - } - } else { - $container->removeDefinition('console.command.form_debug'); - } - - // validation depends on form, annotations being registered - $this->registerValidationConfiguration($config['validation'], $container, $loader, $propertyInfoEnabled); - - // messenger depends on validation being registered - if ($this->messengerConfigEnabled = $this->isConfigEnabled($container, $config['messenger'])) { - $this->registerMessengerConfiguration($config['messenger'], $container, $loader, $config['validation']); - } else { - $container->removeDefinition('console.command.messenger_consume_messages'); - $container->removeDefinition('console.command.messenger_debug'); - $container->removeDefinition('console.command.messenger_stop_workers'); - $container->removeDefinition('console.command.messenger_setup_transports'); - $container->removeDefinition('console.command.messenger_failed_messages_retry'); - $container->removeDefinition('console.command.messenger_failed_messages_show'); - $container->removeDefinition('console.command.messenger_failed_messages_remove'); - $container->removeDefinition('cache.messenger.restart_workers_signal'); - - if ($container->hasDefinition('messenger.transport.amqp.factory') && !class_exists(AmqpTransportFactory::class)) { - if (class_exists(\Symfony\Component\Messenger\Transport\AmqpExt\AmqpTransportFactory::class)) { - $container->getDefinition('messenger.transport.amqp.factory') - ->setClass(\Symfony\Component\Messenger\Transport\AmqpExt\AmqpTransportFactory::class) - ->addTag('messenger.transport_factory'); - } else { - $container->removeDefinition('messenger.transport.amqp.factory'); - } - } - - if ($container->hasDefinition('messenger.transport.redis.factory') && !class_exists(RedisTransportFactory::class)) { - if (class_exists(\Symfony\Component\Messenger\Transport\RedisExt\RedisTransportFactory::class)) { - $container->getDefinition('messenger.transport.redis.factory') - ->setClass(\Symfony\Component\Messenger\Transport\RedisExt\RedisTransportFactory::class) - ->addTag('messenger.transport_factory'); - } else { - $container->removeDefinition('messenger.transport.redis.factory'); - } - } - } - - // notifier depends on messenger, mailer being registered - if ($this->notifierConfigEnabled = $this->isConfigEnabled($container, $config['notifier'])) { - $this->registerNotifierConfiguration($config['notifier'], $container, $loader); - } - - // profiler depends on form, validation, translation, messenger, mailer, http-client, notifier being registered - $this->registerProfilerConfiguration($config['profiler'], $container, $loader); - - $this->addAnnotatedClassesToCompile([ - '**\\Controller\\', - '**\\Entity\\', - - // Added explicitly so that we don't rely on the class map being dumped to make it work - 'Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController', - ]); - - if (ContainerBuilder::willBeAvailable('symfony/mime', MimeTypes::class, ['symfony/framework-bundle'], true)) { - $loader->load('mime_type.php'); - } - - $container->registerForAutoconfiguration(PackageInterface::class) - ->addTag('assets.package'); - $container->registerForAutoconfiguration(Command::class) - ->addTag('console.command'); - $container->registerForAutoconfiguration(ResourceCheckerInterface::class) - ->addTag('config_cache.resource_checker'); - $container->registerForAutoconfiguration(EnvVarLoaderInterface::class) - ->addTag('container.env_var_loader'); - $container->registerForAutoconfiguration(EnvVarProcessorInterface::class) - ->addTag('container.env_var_processor'); - $container->registerForAutoconfiguration(CallbackInterface::class) - ->addTag('container.reversible'); - $container->registerForAutoconfiguration(ServiceLocator::class) - ->addTag('container.service_locator'); - $container->registerForAutoconfiguration(ServiceSubscriberInterface::class) - ->addTag('container.service_subscriber'); - $container->registerForAutoconfiguration(ArgumentValueResolverInterface::class) - ->addTag('controller.argument_value_resolver'); - $container->registerForAutoconfiguration(AbstractController::class) - ->addTag('controller.service_arguments'); - $container->registerForAutoconfiguration(DataCollectorInterface::class) - ->addTag('data_collector'); - $container->registerForAutoconfiguration(FormTypeInterface::class) - ->addTag('form.type'); - $container->registerForAutoconfiguration(FormTypeGuesserInterface::class) - ->addTag('form.type_guesser'); - $container->registerForAutoconfiguration(FormTypeExtensionInterface::class) - ->addTag('form.type_extension'); - $container->registerForAutoconfiguration(CacheClearerInterface::class) - ->addTag('kernel.cache_clearer'); - $container->registerForAutoconfiguration(CacheWarmerInterface::class) - ->addTag('kernel.cache_warmer'); - $container->registerForAutoconfiguration(EventDispatcherInterface::class) - ->addTag('event_dispatcher.dispatcher'); - $container->registerForAutoconfiguration(EventSubscriberInterface::class) - ->addTag('kernel.event_subscriber'); - $container->registerForAutoconfiguration(LocaleAwareInterface::class) - ->addTag('kernel.locale_aware'); - $container->registerForAutoconfiguration(ResetInterface::class) - ->addTag('kernel.reset', ['method' => 'reset']); - - if (!interface_exists(MarshallerInterface::class)) { - $container->registerForAutoconfiguration(ResettableInterface::class) - ->addTag('kernel.reset', ['method' => 'reset']); - } - - $container->registerForAutoconfiguration(PropertyListExtractorInterface::class) - ->addTag('property_info.list_extractor'); - $container->registerForAutoconfiguration(PropertyTypeExtractorInterface::class) - ->addTag('property_info.type_extractor'); - $container->registerForAutoconfiguration(PropertyDescriptionExtractorInterface::class) - ->addTag('property_info.description_extractor'); - $container->registerForAutoconfiguration(PropertyAccessExtractorInterface::class) - ->addTag('property_info.access_extractor'); - $container->registerForAutoconfiguration(PropertyInitializableExtractorInterface::class) - ->addTag('property_info.initializable_extractor'); - $container->registerForAutoconfiguration(EncoderInterface::class) - ->addTag('serializer.encoder'); - $container->registerForAutoconfiguration(DecoderInterface::class) - ->addTag('serializer.encoder'); - $container->registerForAutoconfiguration(NormalizerInterface::class) - ->addTag('serializer.normalizer'); - $container->registerForAutoconfiguration(DenormalizerInterface::class) - ->addTag('serializer.normalizer'); - $container->registerForAutoconfiguration(ConstraintValidatorInterface::class) - ->addTag('validator.constraint_validator'); - $container->registerForAutoconfiguration(ObjectInitializerInterface::class) - ->addTag('validator.initializer'); - $container->registerForAutoconfiguration(MessageHandlerInterface::class) - ->addTag('messenger.message_handler'); - $container->registerForAutoconfiguration(BatchHandlerInterface::class) - ->addTag('messenger.message_handler'); - $container->registerForAutoconfiguration(TransportFactoryInterface::class) - ->addTag('messenger.transport_factory'); - $container->registerForAutoconfiguration(MimeTypeGuesserInterface::class) - ->addTag('mime.mime_type_guesser'); - $container->registerForAutoconfiguration(LoggerAwareInterface::class) - ->addMethodCall('setLogger', [new Reference('logger')]); - - $container->registerAttributeForAutoconfiguration(AsEventListener::class, static function (ChildDefinition $definition, AsEventListener $attribute, \Reflector $reflector) { - $tagAttributes = get_object_vars($attribute); - if ($reflector instanceof \ReflectionMethod) { - if (isset($tagAttributes['method'])) { - throw new LogicException(sprintf('AsEventListener attribute cannot declare a method on "%s::%s()".', $reflector->class, $reflector->name)); - } - $tagAttributes['method'] = $reflector->getName(); - } - $definition->addTag('kernel.event_listener', $tagAttributes); - }); - $container->registerAttributeForAutoconfiguration(AsController::class, static function (ChildDefinition $definition, AsController $attribute): void { - $definition->addTag('controller.service_arguments'); - }); - $container->registerAttributeForAutoconfiguration(AsMessageHandler::class, static function (ChildDefinition $definition, AsMessageHandler $attribute): void { - $tagAttributes = get_object_vars($attribute); - $tagAttributes['from_transport'] = $tagAttributes['fromTransport']; - unset($tagAttributes['fromTransport']); - - $definition->addTag('messenger.message_handler', $tagAttributes); - }); - - if (!$container->getParameter('kernel.debug')) { - // remove tagged iterator argument for resource checkers - $container->getDefinition('config_cache_factory')->setArguments([]); - } - - if (!$config['disallow_search_engine_index'] ?? false) { - $container->removeDefinition('disallow_search_engine_index_response_listener'); - } - - $container->registerForAutoconfiguration(RouteLoaderInterface::class) - ->addTag('routing.route_loader'); - - $container->setParameter('container.behavior_describing_tags', [ - 'annotations.cached_reader', - 'container.do_not_inline', - 'container.service_locator', - 'container.service_subscriber', - 'kernel.event_subscriber', - 'kernel.event_listener', - 'kernel.locale_aware', - 'kernel.reset', - ]); - } - - /** - * {@inheritdoc} - */ - public function getConfiguration(array $config, ContainerBuilder $container) - { - return new Configuration($container->getParameter('kernel.debug')); - } - - protected function hasConsole(): bool - { - return class_exists(Application::class); - } - - private function registerFormConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader) - { - $loader->load('form.php'); - - $container->getDefinition('form.type_extension.form.validator')->setArgument(1, $config['form']['legacy_error_messages']); - - if (null === $config['form']['csrf_protection']['enabled']) { - $config['form']['csrf_protection']['enabled'] = $config['csrf_protection']['enabled']; - } - - if ($this->isConfigEnabled($container, $config['form']['csrf_protection'])) { - if (!$container->hasDefinition('security.csrf.token_generator')) { - throw new \LogicException('To use form CSRF protection, "framework.csrf_protection" must be enabled.'); - } - - $loader->load('form_csrf.php'); - - $container->setParameter('form.type_extension.csrf.enabled', true); - $container->setParameter('form.type_extension.csrf.field_name', $config['form']['csrf_protection']['field_name']); - } else { - $container->setParameter('form.type_extension.csrf.enabled', false); - } - - if (!ContainerBuilder::willBeAvailable('symfony/translation', Translator::class, ['symfony/framework-bundle', 'symfony/form'], true)) { - $container->removeDefinition('form.type_extension.upload.validator'); - } - if (!method_exists(CachingFactoryDecorator::class, 'reset')) { - $container->getDefinition('form.choice_list_factory.cached') - ->clearTag('kernel.reset') - ; - } - } - - private function registerHttpCacheConfiguration(array $config, ContainerBuilder $container, bool $httpMethodOverride) - { - $options = $config; - unset($options['enabled']); - - if (!$options['private_headers']) { - unset($options['private_headers']); - } - - $container->getDefinition('http_cache') - ->setPublic($config['enabled']) - ->replaceArgument(3, $options); - - if ($httpMethodOverride) { - $container->getDefinition('http_cache') - ->addArgument((new Definition('void')) - ->setFactory([Request::class, 'enableHttpMethodParameterOverride']) - ); - } - } - - private function registerEsiConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader) - { - if (!$this->isConfigEnabled($container, $config)) { - $container->removeDefinition('fragment.renderer.esi'); - - return; - } - - $loader->load('esi.php'); - } - - private function registerSsiConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader) - { - if (!$this->isConfigEnabled($container, $config)) { - $container->removeDefinition('fragment.renderer.ssi'); - - return; - } - - $loader->load('ssi.php'); - } - - private function registerFragmentsConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader) - { - if (!$this->isConfigEnabled($container, $config)) { - $container->removeDefinition('fragment.renderer.hinclude'); - - return; - } - - $container->setParameter('fragment.renderer.hinclude.global_template', $config['hinclude_default_template']); - - $loader->load('fragment_listener.php'); - $container->setParameter('fragment.path', $config['path']); - } - - private function registerProfilerConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader) - { - if (!$this->isConfigEnabled($container, $config)) { - // this is needed for the WebProfiler to work even if the profiler is disabled - $container->setParameter('data_collector.templates', []); - - return; - } - - $loader->load('profiling.php'); - $loader->load('collectors.php'); - $loader->load('cache_debug.php'); - - if ($this->formConfigEnabled) { - $loader->load('form_debug.php'); - } - - if ($this->validatorConfigEnabled) { - $loader->load('validator_debug.php'); - } - - if ($this->translationConfigEnabled) { - $loader->load('translation_debug.php'); - - $container->getDefinition('translator.data_collector')->setDecoratedService('translator'); - } - - if ($this->messengerConfigEnabled) { - $loader->load('messenger_debug.php'); - } - - if ($this->mailerConfigEnabled) { - $loader->load('mailer_debug.php'); - } - - if ($this->httpClientConfigEnabled) { - $loader->load('http_client_debug.php'); - } - - if ($this->notifierConfigEnabled) { - $loader->load('notifier_debug.php'); - } - - $container->setParameter('profiler_listener.only_exceptions', $config['only_exceptions']); - $container->setParameter('profiler_listener.only_main_requests', $config['only_main_requests'] || $config['only_master_requests']); - - // Choose storage class based on the DSN - [$class] = explode(':', $config['dsn'], 2); - if ('file' !== $class) { - throw new \LogicException(sprintf('Driver "%s" is not supported for the profiler.', $class)); - } - - $container->setParameter('profiler.storage.dsn', $config['dsn']); - - $container->getDefinition('profiler') - ->addArgument($config['collect']) - ->addTag('kernel.reset', ['method' => 'reset']); - - $container->getDefinition('profiler_listener') - ->addArgument($config['collect_parameter']); - } - - private function registerWorkflowConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader) - { - if (!$config['enabled']) { - $container->removeDefinition('console.command.workflow_dump'); - - return; - } - - if (!class_exists(Workflow\Workflow::class)) { - throw new LogicException('Workflow support cannot be enabled as the Workflow component is not installed. Try running "composer require symfony/workflow".'); - } - - $loader->load('workflow.php'); - - $registryDefinition = $container->getDefinition('workflow.registry'); - - $workflows = []; - - foreach ($config['workflows'] as $name => $workflow) { - $type = $workflow['type']; - $workflowId = sprintf('%s.%s', $type, $name); - - // Process Metadata (workflow + places (transition is done in the "create transition" block)) - $metadataStoreDefinition = new Definition(Workflow\Metadata\InMemoryMetadataStore::class, [[], [], null]); - if ($workflow['metadata']) { - $metadataStoreDefinition->replaceArgument(0, $workflow['metadata']); - } - $placesMetadata = []; - foreach ($workflow['places'] as $place) { - if ($place['metadata']) { - $placesMetadata[$place['name']] = $place['metadata']; - } - } - if ($placesMetadata) { - $metadataStoreDefinition->replaceArgument(1, $placesMetadata); - } - - // Create transitions - $transitions = []; - $guardsConfiguration = []; - $transitionsMetadataDefinition = new Definition(\SplObjectStorage::class); - // Global transition counter per workflow - $transitionCounter = 0; - foreach ($workflow['transitions'] as $transition) { - if ('workflow' === $type) { - $transitionDefinition = new Definition(Workflow\Transition::class, [$transition['name'], $transition['from'], $transition['to']]); - $transitionDefinition->setPublic(false); - $transitionId = sprintf('.%s.transition.%s', $workflowId, $transitionCounter++); - $container->setDefinition($transitionId, $transitionDefinition); - $transitions[] = new Reference($transitionId); - if (isset($transition['guard'])) { - $configuration = new Definition(Workflow\EventListener\GuardExpression::class); - $configuration->addArgument(new Reference($transitionId)); - $configuration->addArgument($transition['guard']); - $configuration->setPublic(false); - $eventName = sprintf('workflow.%s.guard.%s', $name, $transition['name']); - $guardsConfiguration[$eventName][] = $configuration; - } - if ($transition['metadata']) { - $transitionsMetadataDefinition->addMethodCall('attach', [ - new Reference($transitionId), - $transition['metadata'], - ]); - } - } elseif ('state_machine' === $type) { - foreach ($transition['from'] as $from) { - foreach ($transition['to'] as $to) { - $transitionDefinition = new Definition(Workflow\Transition::class, [$transition['name'], $from, $to]); - $transitionDefinition->setPublic(false); - $transitionId = sprintf('.%s.transition.%s', $workflowId, $transitionCounter++); - $container->setDefinition($transitionId, $transitionDefinition); - $transitions[] = new Reference($transitionId); - if (isset($transition['guard'])) { - $configuration = new Definition(Workflow\EventListener\GuardExpression::class); - $configuration->addArgument(new Reference($transitionId)); - $configuration->addArgument($transition['guard']); - $configuration->setPublic(false); - $eventName = sprintf('workflow.%s.guard.%s', $name, $transition['name']); - $guardsConfiguration[$eventName][] = $configuration; - } - if ($transition['metadata']) { - $transitionsMetadataDefinition->addMethodCall('attach', [ - new Reference($transitionId), - $transition['metadata'], - ]); - } - } - } - } - } - $metadataStoreDefinition->replaceArgument(2, $transitionsMetadataDefinition); - $container->setDefinition(sprintf('%s.metadata_store', $workflowId), $metadataStoreDefinition); - - // Create places - $places = array_column($workflow['places'], 'name'); - $initialMarking = $workflow['initial_marking'] ?? []; - - // Create a Definition - $definitionDefinition = new Definition(Workflow\Definition::class); - $definitionDefinition->setPublic(false); - $definitionDefinition->addArgument($places); - $definitionDefinition->addArgument($transitions); - $definitionDefinition->addArgument($initialMarking); - $definitionDefinition->addArgument(new Reference(sprintf('%s.metadata_store', $workflowId))); - - $workflows[$workflowId] = $definitionDefinition; - - // Create MarkingStore - if (isset($workflow['marking_store']['type'])) { - $markingStoreDefinition = new ChildDefinition('workflow.marking_store.method'); - $markingStoreDefinition->setArguments([ - 'state_machine' === $type, // single state - $workflow['marking_store']['property'], - ]); - } elseif (isset($workflow['marking_store']['service'])) { - $markingStoreDefinition = new Reference($workflow['marking_store']['service']); - } - - // Create Workflow - $workflowDefinition = new ChildDefinition(sprintf('%s.abstract', $type)); - $workflowDefinition->replaceArgument(0, new Reference(sprintf('%s.definition', $workflowId))); - $workflowDefinition->replaceArgument(1, $markingStoreDefinition ?? null); - $workflowDefinition->replaceArgument(3, $name); - $workflowDefinition->replaceArgument(4, $workflow['events_to_dispatch']); - $workflowDefinition->addTag('container.private', [ - 'package' => 'symfony/framework-bundle', - 'version' => '5.3', - ]); - - // Store to container - $container->setDefinition($workflowId, $workflowDefinition); - $container->setDefinition(sprintf('%s.definition', $workflowId), $definitionDefinition); - $container->registerAliasForArgument($workflowId, WorkflowInterface::class, $name.'.'.$type); - - // Validate Workflow - if ('state_machine' === $workflow['type']) { - $validator = new Workflow\Validator\StateMachineValidator(); - } else { - $validator = new Workflow\Validator\WorkflowValidator(); - } - - $trs = array_map(function (Reference $ref) use ($container): Workflow\Transition { - return $container->get((string) $ref); - }, $transitions); - $realDefinition = new Workflow\Definition($places, $trs, $initialMarking); - $validator->validate($realDefinition, $name); - - // Add workflow to Registry - if ($workflow['supports']) { - foreach ($workflow['supports'] as $supportedClassName) { - $strategyDefinition = new Definition(Workflow\SupportStrategy\InstanceOfSupportStrategy::class, [$supportedClassName]); - $strategyDefinition->setPublic(false); - $registryDefinition->addMethodCall('addWorkflow', [new Reference($workflowId), $strategyDefinition]); - } - } elseif (isset($workflow['support_strategy'])) { - $registryDefinition->addMethodCall('addWorkflow', [new Reference($workflowId), new Reference($workflow['support_strategy'])]); - } - - // Enable the AuditTrail - if ($workflow['audit_trail']['enabled']) { - $listener = new Definition(Workflow\EventListener\AuditTrailListener::class); - $listener->addTag('monolog.logger', ['channel' => 'workflow']); - $listener->addTag('kernel.event_listener', ['event' => sprintf('workflow.%s.leave', $name), 'method' => 'onLeave']); - $listener->addTag('kernel.event_listener', ['event' => sprintf('workflow.%s.transition', $name), 'method' => 'onTransition']); - $listener->addTag('kernel.event_listener', ['event' => sprintf('workflow.%s.enter', $name), 'method' => 'onEnter']); - $listener->addArgument(new Reference('logger')); - $container->setDefinition(sprintf('.%s.listener.audit_trail', $workflowId), $listener); - } - - // Add Guard Listener - if ($guardsConfiguration) { - if (!class_exists(ExpressionLanguage::class)) { - throw new LogicException('Cannot guard workflows as the ExpressionLanguage component is not installed. Try running "composer require symfony/expression-language".'); - } - - if (!class_exists(Security::class)) { - throw new LogicException('Cannot guard workflows as the Security component is not installed. Try running "composer require symfony/security-core".'); - } - - $guard = new Definition(Workflow\EventListener\GuardListener::class); - - $guard->setArguments([ - $guardsConfiguration, - new Reference('workflow.security.expression_language'), - new Reference('security.token_storage'), - new Reference('security.authorization_checker'), - new Reference('security.authentication.trust_resolver'), - new Reference('security.role_hierarchy'), - new Reference('validator', ContainerInterface::NULL_ON_INVALID_REFERENCE), - ]); - foreach ($guardsConfiguration as $eventName => $config) { - $guard->addTag('kernel.event_listener', ['event' => $eventName, 'method' => 'onTransition']); - } - - $container->setDefinition(sprintf('.%s.listener.guard', $workflowId), $guard); - $container->setParameter('workflow.has_guard_listeners', true); - } - } - - $commandDumpDefinition = $container->getDefinition('console.command.workflow_dump'); - $commandDumpDefinition->setArgument(0, $workflows); - } - - private function registerDebugConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader) - { - $loader->load('debug_prod.php'); - - if (class_exists(Stopwatch::class)) { - $container->register('debug.stopwatch', Stopwatch::class) - ->addArgument(true) - ->addTag('kernel.reset', ['method' => 'reset']); - $container->setAlias(Stopwatch::class, new Alias('debug.stopwatch', false)); - } - - $debug = $container->getParameter('kernel.debug'); - - if ($debug) { - $container->setParameter('debug.container.dump', '%kernel.build_dir%/%kernel.container_class%.xml'); - } - - if ($debug && class_exists(Stopwatch::class)) { - $loader->load('debug.php'); - } - - $definition = $container->findDefinition('debug.debug_handlers_listener'); - - if (false === $config['log']) { - $definition->replaceArgument(1, null); - } elseif (true !== $config['log']) { - $definition->replaceArgument(2, $config['log']); - } - - if (!$config['throw']) { - $container->setParameter('debug.error_handler.throw_at', 0); - } - - if ($debug && class_exists(DebugProcessor::class)) { - $definition = new Definition(DebugProcessor::class); - $definition->setPublic(false); - $definition->addArgument(new Reference('request_stack')); - $container->setDefinition('debug.log_processor', $definition); - } - } - - private function registerRouterConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader, array $enabledLocales = []) - { - if (!$this->isConfigEnabled($container, $config)) { - $container->removeDefinition('console.command.router_debug'); - $container->removeDefinition('console.command.router_match'); - $container->removeDefinition('messenger.middleware.router_context'); - - return; - } - if (!class_exists(RouterContextMiddleware::class)) { - $container->removeDefinition('messenger.middleware.router_context'); - } - - $loader->load('routing.php'); - - if (null === $config['utf8']) { - trigger_deprecation('symfony/framework-bundle', '5.1', 'Not setting the "framework.router.utf8" configuration option is deprecated, it will default to "true" in version 6.0.'); - } - - if ($config['utf8']) { - $container->getDefinition('routing.loader')->replaceArgument(1, ['utf8' => true]); - } - - if ($enabledLocales) { - $enabledLocales = implode('|', array_map('preg_quote', $enabledLocales)); - $container->getDefinition('routing.loader')->replaceArgument(2, ['_locale' => $enabledLocales]); - } - - if (!ContainerBuilder::willBeAvailable('symfony/expression-language', ExpressionLanguage::class, ['symfony/framework-bundle', 'symfony/routing'], true)) { - $container->removeDefinition('router.expression_language_provider'); - } - - $container->setParameter('router.resource', $config['resource']); - $router = $container->findDefinition('router.default'); - $argument = $router->getArgument(2); - $argument['strict_requirements'] = $config['strict_requirements']; - if (isset($config['type'])) { - $argument['resource_type'] = $config['type']; - } - $router->replaceArgument(2, $argument); - - $container->setParameter('request_listener.http_port', $config['http_port']); - $container->setParameter('request_listener.https_port', $config['https_port']); - - if (null !== $config['default_uri']) { - $container->getDefinition('router.request_context') - ->replaceArgument(0, $config['default_uri']); - } - - if (\PHP_VERSION_ID < 80000 && !$this->annotationsConfigEnabled) { - return; - } - - $container->register('routing.loader.annotation', AnnotatedRouteControllerLoader::class) - ->setPublic(false) - ->addTag('routing.loader', ['priority' => -10]) - ->setArguments([ - new Reference('annotation_reader', ContainerInterface::NULL_ON_INVALID_REFERENCE), - '%kernel.environment%', - ]); - - $container->register('routing.loader.annotation.directory', AnnotationDirectoryLoader::class) - ->setPublic(false) - ->addTag('routing.loader', ['priority' => -10]) - ->setArguments([ - new Reference('file_locator'), - new Reference('routing.loader.annotation'), - ]); - - $container->register('routing.loader.annotation.file', AnnotationFileLoader::class) - ->setPublic(false) - ->addTag('routing.loader', ['priority' => -10]) - ->setArguments([ - new Reference('file_locator'), - new Reference('routing.loader.annotation'), - ]); - } - - private function registerSessionConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader) - { - $loader->load('session.php'); - - // session storage - if (null === $config['storage_factory_id']) { - trigger_deprecation('symfony/framework-bundle', '5.3', 'Not setting the "framework.session.storage_factory_id" configuration option is deprecated, it will default to "session.storage.factory.native" and will replace the "framework.session.storage_id" configuration option in version 6.0.'); - $container->setAlias('session.storage', $config['storage_id']); - $container->setAlias('session.storage.factory', 'session.storage.factory.service'); - } else { - $container->setAlias('session.storage.factory', $config['storage_factory_id']); - - $container->removeAlias(SessionStorageInterface::class); - $container->removeDefinition('session.storage.metadata_bag'); - $container->removeDefinition('session.storage.native'); - $container->removeDefinition('session.storage.php_bridge'); - $container->removeDefinition('session.storage.mock_file'); - $container->removeAlias('session.storage.filesystem'); - } - - $options = ['cache_limiter' => '0']; - foreach (['name', 'cookie_lifetime', 'cookie_path', 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'cookie_samesite', 'use_cookies', 'gc_maxlifetime', 'gc_probability', 'gc_divisor', 'sid_length', 'sid_bits_per_character'] as $key) { - if (isset($config[$key])) { - $options[$key] = $config[$key]; - } - } - - if ('auto' === ($options['cookie_secure'] ?? null)) { - if (null === $config['storage_factory_id']) { - $locator = $container->getDefinition('session_listener')->getArgument(0); - $locator->setValues($locator->getValues() + [ - 'session_storage' => new Reference('session.storage', ContainerInterface::IGNORE_ON_INVALID_REFERENCE), - 'request_stack' => new Reference('request_stack'), - ]); - } else { - $container->getDefinition('session.storage.factory.native')->replaceArgument(3, true); - $container->getDefinition('session.storage.factory.php_bridge')->replaceArgument(2, true); - } - } - - $container->setParameter('session.storage.options', $options); - - // session handler (the internal callback registered with PHP session management) - if (null === $config['handler_id']) { - // Set the handler class to be null - if ($container->hasDefinition('session.storage.native')) { - $container->getDefinition('session.storage.native')->replaceArgument(1, null); - $container->getDefinition('session.storage.php_bridge')->replaceArgument(0, null); - } else { - $container->getDefinition('session.storage.factory.native')->replaceArgument(1, null); - $container->getDefinition('session.storage.factory.php_bridge')->replaceArgument(0, null); - } - - $container->setAlias('session.handler', 'session.handler.native_file'); - } else { - $container->resolveEnvPlaceholders($config['handler_id'], null, $usedEnvs); - - if ($usedEnvs || preg_match('#^[a-z]++://#', $config['handler_id'])) { - $id = '.cache_connection.'.ContainerBuilder::hash($config['handler_id']); - - $container->getDefinition('session.abstract_handler') - ->replaceArgument(0, $container->hasDefinition($id) ? new Reference($id) : $config['handler_id']); - - $container->setAlias('session.handler', 'session.abstract_handler'); - } else { - $container->setAlias('session.handler', $config['handler_id']); - } - } - - $container->setParameter('session.save_path', $config['save_path']); - - $container->setParameter('session.metadata.update_threshold', $config['metadata_update_threshold']); - } - - private function registerRequestConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader) - { - if ($config['formats']) { - $loader->load('request.php'); - - $listener = $container->getDefinition('request.add_request_formats_listener'); - $listener->replaceArgument(0, $config['formats']); - } - } - - private function registerAssetsConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader) - { - $loader->load('assets.php'); - - if ($config['version_strategy']) { - $defaultVersion = new Reference($config['version_strategy']); - } else { - $defaultVersion = $this->createVersion($container, $config['version'], $config['version_format'], $config['json_manifest_path'], '_default', $config['strict_mode']); - } - - $defaultPackage = $this->createPackageDefinition($config['base_path'], $config['base_urls'], $defaultVersion); - $container->setDefinition('assets._default_package', $defaultPackage); - - foreach ($config['packages'] as $name => $package) { - if (null !== $package['version_strategy']) { - $version = new Reference($package['version_strategy']); - } elseif (!\array_key_exists('version', $package) && null === $package['json_manifest_path']) { - // if neither version nor json_manifest_path are specified, use the default - $version = $defaultVersion; - } else { - // let format fallback to main version_format - $format = $package['version_format'] ?: $config['version_format']; - $version = $package['version'] ?? null; - $version = $this->createVersion($container, $version, $format, $package['json_manifest_path'], $name, $package['strict_mode']); - } - - $packageDefinition = $this->createPackageDefinition($package['base_path'], $package['base_urls'], $version) - ->addTag('assets.package', ['package' => $name]); - $container->setDefinition('assets._package_'.$name, $packageDefinition); - $container->registerAliasForArgument('assets._package_'.$name, PackageInterface::class, $name.'.package'); - } - } - - /** - * Returns a definition for an asset package. - */ - private function createPackageDefinition(?string $basePath, array $baseUrls, Reference $version): Definition - { - if ($basePath && $baseUrls) { - throw new \LogicException('An asset package cannot have base URLs and base paths.'); - } - - $package = new ChildDefinition($baseUrls ? 'assets.url_package' : 'assets.path_package'); - $package - ->setPublic(false) - ->replaceArgument(0, $baseUrls ?: $basePath) - ->replaceArgument(1, $version) - ; - - return $package; - } - - private function createVersion(ContainerBuilder $container, ?string $version, ?string $format, ?string $jsonManifestPath, string $name, bool $strictMode): Reference - { - // Configuration prevents $version and $jsonManifestPath from being set - if (null !== $version) { - $def = new ChildDefinition('assets.static_version_strategy'); - $def - ->replaceArgument(0, $version) - ->replaceArgument(1, $format) - ; - $container->setDefinition('assets._version_'.$name, $def); - - return new Reference('assets._version_'.$name); - } - - if (null !== $jsonManifestPath) { - $def = new ChildDefinition('assets.json_manifest_version_strategy'); - $def->replaceArgument(0, $jsonManifestPath); - $def->replaceArgument(2, $strictMode); - $container->setDefinition('assets._version_'.$name, $def); - - return new Reference('assets._version_'.$name); - } - - return new Reference('assets.empty_version_strategy'); - } - - private function registerTranslatorConfiguration(array $config, ContainerBuilder $container, LoaderInterface $loader, string $defaultLocale, array $enabledLocales) - { - if (!$this->isConfigEnabled($container, $config)) { - $container->removeDefinition('console.command.translation_debug'); - $container->removeDefinition('console.command.translation_extract'); - $container->removeDefinition('console.command.translation_pull'); - $container->removeDefinition('console.command.translation_push'); - - return; - } - - $loader->load('translation.php'); - $loader->load('translation_providers.php'); - - // Use the "real" translator instead of the identity default - $container->setAlias('translator', 'translator.default')->setPublic(true); - $container->setAlias('translator.formatter', new Alias($config['formatter'], false)); - $translator = $container->findDefinition('translator.default'); - $translator->addMethodCall('setFallbackLocales', [$config['fallbacks'] ?: [$defaultLocale]]); - - $defaultOptions = $translator->getArgument(4); - $defaultOptions['cache_dir'] = $config['cache_dir']; - $translator->setArgument(4, $defaultOptions); - - // @deprecated since Symfony 5.4, in 6.0 change to: - // $translator->setArgument(5, $enabledLocales); - $translator->setArgument(5, $config['enabled_locales'] ?: $enabledLocales); - - $container->setParameter('translator.logging', $config['logging']); - $container->setParameter('translator.default_path', $config['default_path']); - - // Discover translation directories - $dirs = []; - $transPaths = []; - $nonExistingDirs = []; - if (ContainerBuilder::willBeAvailable('symfony/validator', Validation::class, ['symfony/framework-bundle', 'symfony/translation'], true)) { - $r = new \ReflectionClass(Validation::class); - - $dirs[] = $transPaths[] = \dirname($r->getFileName()).'/Resources/translations'; - } - if (ContainerBuilder::willBeAvailable('symfony/form', Form::class, ['symfony/framework-bundle', 'symfony/translation'], true)) { - $r = new \ReflectionClass(Form::class); - - $dirs[] = $transPaths[] = \dirname($r->getFileName()).'/Resources/translations'; - } - if (ContainerBuilder::willBeAvailable('symfony/security-core', AuthenticationException::class, ['symfony/framework-bundle', 'symfony/translation'], true)) { - $r = new \ReflectionClass(AuthenticationException::class); - - $dirs[] = $transPaths[] = \dirname($r->getFileName(), 2).'/Resources/translations'; - } - $defaultDir = $container->getParameterBag()->resolveValue($config['default_path']); - foreach ($container->getParameter('kernel.bundles_metadata') as $name => $bundle) { - if ($container->fileExists($dir = $bundle['path'].'/Resources/translations') || $container->fileExists($dir = $bundle['path'].'/translations')) { - $dirs[] = $dir; - } else { - $nonExistingDirs[] = $dir; - } - } - - foreach ($config['paths'] as $dir) { - if ($container->fileExists($dir)) { - $dirs[] = $transPaths[] = $dir; - } else { - throw new \UnexpectedValueException(sprintf('"%s" defined in translator.paths does not exist or is not a directory.', $dir)); - } - } - - if ($container->hasDefinition('console.command.translation_debug')) { - $container->getDefinition('console.command.translation_debug')->replaceArgument(5, $transPaths); - } - - if ($container->hasDefinition('console.command.translation_extract')) { - $container->getDefinition('console.command.translation_extract')->replaceArgument(6, $transPaths); - } - - if (null === $defaultDir) { - // allow null - } elseif ($container->fileExists($defaultDir)) { - $dirs[] = $defaultDir; - } else { - $nonExistingDirs[] = $defaultDir; - } - - // Register translation resources - if ($dirs) { - $files = []; - - foreach ($dirs as $dir) { - $finder = Finder::create() - ->followLinks() - ->files() - ->filter(function (\SplFileInfo $file) { - return 2 <= substr_count($file->getBasename(), '.') && preg_match('/\.\w+$/', $file->getBasename()); - }) - ->in($dir) - ->sortByName() - ; - foreach ($finder as $file) { - $fileNameParts = explode('.', basename($file)); - $locale = $fileNameParts[\count($fileNameParts) - 2]; - if (!isset($files[$locale])) { - $files[$locale] = []; - } - - $files[$locale][] = (string) $file; - } - } - - $projectDir = $container->getParameter('kernel.project_dir'); - - $options = array_merge( - $translator->getArgument(4), - [ - 'resource_files' => $files, - 'scanned_directories' => $scannedDirectories = array_merge($dirs, $nonExistingDirs), - 'cache_vary' => [ - 'scanned_directories' => array_map(static function (string $dir) use ($projectDir): string { - return str_starts_with($dir, $projectDir.'/') ? substr($dir, 1 + \strlen($projectDir)) : $dir; - }, $scannedDirectories), - ], - ] - ); - - $translator->replaceArgument(4, $options); - } - - if ($config['pseudo_localization']['enabled']) { - $options = $config['pseudo_localization']; - unset($options['enabled']); - - $container - ->register('translator.pseudo', PseudoLocalizationTranslator::class) - ->setDecoratedService('translator', null, -1) // Lower priority than "translator.data_collector" - ->setArguments([ - new Reference('translator.pseudo.inner'), - $options, - ]); - } - - $classToServices = [ - CrowdinProviderFactory::class => 'translation.provider_factory.crowdin', - LocoProviderFactory::class => 'translation.provider_factory.loco', - LokaliseProviderFactory::class => 'translation.provider_factory.lokalise', - ]; - - $parentPackages = ['symfony/framework-bundle', 'symfony/translation', 'symfony/http-client']; - - foreach ($classToServices as $class => $service) { - $package = substr($service, \strlen('translation.provider_factory.')); - - if (!$container->hasDefinition('http_client') || !ContainerBuilder::willBeAvailable(sprintf('symfony/%s-translation-provider', $package), $class, $parentPackages, true)) { - $container->removeDefinition($service); - } - } - - if (!$config['providers']) { - return; - } - - // @deprecated since Symfony 5.4, in 6.0 change to: - // $locales = $enabledLocales; - $locales = $config['enabled_locales'] ?: $enabledLocales; - - foreach ($config['providers'] as $provider) { - if ($provider['locales']) { - $locales += $provider['locales']; - } - } - - $locales = array_unique($locales); - - $container->getDefinition('console.command.translation_pull') - ->replaceArgument(4, array_merge($transPaths, [$config['default_path']])) - ->replaceArgument(5, $locales) - ; - - $container->getDefinition('console.command.translation_push') - ->replaceArgument(2, array_merge($transPaths, [$config['default_path']])) - ->replaceArgument(3, $locales) - ; - - $container->getDefinition('translation.provider_collection_factory') - ->replaceArgument(1, $locales) - ; - - $container->getDefinition('translation.provider_collection')->setArgument(0, $config['providers']); - } - - private function registerValidationConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader, bool $propertyInfoEnabled) - { - if (!$this->validatorConfigEnabled = $this->isConfigEnabled($container, $config)) { - $container->removeDefinition('console.command.validator_debug'); - - return; - } - - if (!class_exists(Validation::class)) { - throw new LogicException('Validation support cannot be enabled as the Validator component is not installed. Try running "composer require symfony/validator".'); - } - - if (!isset($config['email_validation_mode'])) { - $config['email_validation_mode'] = 'loose'; - } - - $loader->load('validator.php'); - - $validatorBuilder = $container->getDefinition('validator.builder'); - - $container->setParameter('validator.translation_domain', $config['translation_domain']); - - $files = ['xml' => [], 'yml' => []]; - $this->registerValidatorMapping($container, $config, $files); - - if (!empty($files['xml'])) { - $validatorBuilder->addMethodCall('addXmlMappings', [$files['xml']]); - } - - if (!empty($files['yml'])) { - $validatorBuilder->addMethodCall('addYamlMappings', [$files['yml']]); - } - - $definition = $container->findDefinition('validator.email'); - $definition->replaceArgument(0, $config['email_validation_mode']); - - if (\array_key_exists('enable_annotations', $config) && $config['enable_annotations']) { - if (!$this->annotationsConfigEnabled && \PHP_VERSION_ID < 80000) { - throw new \LogicException('"enable_annotations" on the validator cannot be set as the PHP version is lower than 8 and Doctrine Annotations support is disabled. Consider upgrading PHP.'); - } - - $validatorBuilder->addMethodCall('enableAnnotationMapping', [true]); - if ($this->annotationsConfigEnabled) { - $validatorBuilder->addMethodCall('setDoctrineAnnotationReader', [new Reference('annotation_reader')]); - } - } - - if (\array_key_exists('static_method', $config) && $config['static_method']) { - foreach ($config['static_method'] as $methodName) { - $validatorBuilder->addMethodCall('addMethodMapping', [$methodName]); - } - } - - if (!$container->getParameter('kernel.debug')) { - $validatorBuilder->addMethodCall('setMappingCache', [new Reference('validator.mapping.cache.adapter')]); - } - - $container->setParameter('validator.auto_mapping', $config['auto_mapping']); - if (!$propertyInfoEnabled || !class_exists(PropertyInfoLoader::class)) { - $container->removeDefinition('validator.property_info_loader'); - } - - $container - ->getDefinition('validator.not_compromised_password') - ->setArgument(2, $config['not_compromised_password']['enabled']) - ->setArgument(3, $config['not_compromised_password']['endpoint']) - ; - - if (!class_exists(ExpressionLanguage::class)) { - $container->removeDefinition('validator.expression_language'); - } - } - - private function registerValidatorMapping(ContainerBuilder $container, array $config, array &$files) - { - $fileRecorder = function ($extension, $path) use (&$files) { - $files['yaml' === $extension ? 'yml' : $extension][] = $path; - }; - - if (ContainerBuilder::willBeAvailable('symfony/form', Form::class, ['symfony/framework-bundle', 'symfony/validator'], true)) { - $reflClass = new \ReflectionClass(Form::class); - $fileRecorder('xml', \dirname($reflClass->getFileName()).'/Resources/config/validation.xml'); - } - - foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) { - $configDir = is_dir($bundle['path'].'/Resources/config') ? $bundle['path'].'/Resources/config' : $bundle['path'].'/config'; - - if ( - $container->fileExists($file = $configDir.'/validation.yaml', false) || - $container->fileExists($file = $configDir.'/validation.yml', false) - ) { - $fileRecorder('yml', $file); - } - - if ($container->fileExists($file = $configDir.'/validation.xml', false)) { - $fileRecorder('xml', $file); - } - - if ($container->fileExists($dir = $configDir.'/validation', '/^$/')) { - $this->registerMappingFilesFromDir($dir, $fileRecorder); - } - } - - $projectDir = $container->getParameter('kernel.project_dir'); - if ($container->fileExists($dir = $projectDir.'/config/validator', '/^$/')) { - $this->registerMappingFilesFromDir($dir, $fileRecorder); - } - - $this->registerMappingFilesFromConfig($container, $config, $fileRecorder); - } - - private function registerMappingFilesFromDir(string $dir, callable $fileRecorder) - { - foreach (Finder::create()->followLinks()->files()->in($dir)->name('/\.(xml|ya?ml)$/')->sortByName() as $file) { - $fileRecorder($file->getExtension(), $file->getRealPath()); - } - } - - private function registerMappingFilesFromConfig(ContainerBuilder $container, array $config, callable $fileRecorder) - { - foreach ($config['mapping']['paths'] as $path) { - if (is_dir($path)) { - $this->registerMappingFilesFromDir($path, $fileRecorder); - $container->addResource(new DirectoryResource($path, '/^$/')); - } elseif ($container->fileExists($path, false)) { - if (!preg_match('/\.(xml|ya?ml)$/', $path, $matches)) { - throw new \RuntimeException(sprintf('Unsupported mapping type in "%s", supported types are XML & Yaml.', $path)); - } - $fileRecorder($matches[1], $path); - } else { - throw new \RuntimeException(sprintf('Could not open file or directory "%s".', $path)); - } - } - } - - private function registerAnnotationsConfiguration(array $config, ContainerBuilder $container, LoaderInterface $loader) - { - if (!$this->annotationsConfigEnabled) { - return; - } - - if (!class_exists(\Doctrine\Common\Annotations\Annotation::class)) { - throw new LogicException('Annotations cannot be enabled as the Doctrine Annotation library is not installed. Try running "composer require doctrine/annotations".'); - } - - $loader->load('annotations.php'); - - // registerUniqueLoader exists since doctrine/annotations v1.6 - if (!method_exists(AnnotationRegistry::class, 'registerUniqueLoader')) { - // registerLoader exists only in doctrine/annotations v1 - if (method_exists(AnnotationRegistry::class, 'registerLoader')) { - $container->getDefinition('annotations.dummy_registry') - ->setMethodCalls([['registerLoader', ['class_exists']]]); - } else { - // remove the dummy registry when doctrine/annotations v2 is used - $container->removeDefinition('annotations.dummy_registry'); - } - } - - if ('none' === $config['cache']) { - $container->removeDefinition('annotations.cached_reader'); - - return; - } - - $cacheService = $config['cache']; - if (\in_array($config['cache'], ['php_array', 'file'])) { - if ('php_array' === $config['cache']) { - $cacheService = 'annotations.cache_adapter'; - - // Enable warmer only if PHP array is used for cache - $definition = $container->findDefinition('annotations.cache_warmer'); - $definition->addTag('kernel.cache_warmer'); - } elseif ('file' === $config['cache']) { - $cacheService = 'annotations.filesystem_cache_adapter'; - $cacheDir = $container->getParameterBag()->resolveValue($config['file_cache_dir']); - - if (!is_dir($cacheDir) && false === @mkdir($cacheDir, 0777, true) && !is_dir($cacheDir)) { - throw new \RuntimeException(sprintf('Could not create cache directory "%s".', $cacheDir)); - } - - $container - ->getDefinition('annotations.filesystem_cache_adapter') - ->replaceArgument(2, $cacheDir) - ; - } - } else { - trigger_deprecation('symfony/framework-bundle', '5.3', 'Using a custom service for "framework.annotation.cache" is deprecated, only values "none", "php_array" and "file" are valid in version 6.0.'); - } - - $container - ->getDefinition('annotations.cached_reader') - ->replaceArgument(2, $config['debug']) - // reference the cache provider without using it until AddAnnotationsCachedReaderPass runs - ->addArgument(new ServiceClosureArgument(new Reference($cacheService))) - ; - - $container->setAlias('annotation_reader', 'annotations.cached_reader'); - $container->setAlias(Reader::class, new Alias('annotations.cached_reader', false)); - $container->removeDefinition('annotations.psr_cached_reader'); - } - - private function registerPropertyAccessConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader) - { - if (!$this->propertyAccessConfigEnabled = $this->isConfigEnabled($container, $config)) { - return; - } - - $loader->load('property_access.php'); - - $magicMethods = PropertyAccessor::DISALLOW_MAGIC_METHODS; - $magicMethods |= $config['magic_call'] ? PropertyAccessor::MAGIC_CALL : 0; - $magicMethods |= $config['magic_get'] ? PropertyAccessor::MAGIC_GET : 0; - $magicMethods |= $config['magic_set'] ? PropertyAccessor::MAGIC_SET : 0; - - $throw = PropertyAccessor::DO_NOT_THROW; - $throw |= $config['throw_exception_on_invalid_index'] ? PropertyAccessor::THROW_ON_INVALID_INDEX : 0; - $throw |= $config['throw_exception_on_invalid_property_path'] ? PropertyAccessor::THROW_ON_INVALID_PROPERTY_PATH : 0; - - $container - ->getDefinition('property_accessor') - ->replaceArgument(0, $magicMethods) - ->replaceArgument(1, $throw) - ->replaceArgument(3, new Reference(PropertyReadInfoExtractorInterface::class, ContainerInterface::NULL_ON_INVALID_REFERENCE)) - ->replaceArgument(4, new Reference(PropertyWriteInfoExtractorInterface::class, ContainerInterface::NULL_ON_INVALID_REFERENCE)) - ; - } - - private function registerSecretsConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader) - { - if (!$this->isConfigEnabled($container, $config)) { - $container->removeDefinition('console.command.secrets_set'); - $container->removeDefinition('console.command.secrets_list'); - $container->removeDefinition('console.command.secrets_remove'); - $container->removeDefinition('console.command.secrets_generate_key'); - $container->removeDefinition('console.command.secrets_decrypt_to_local'); - $container->removeDefinition('console.command.secrets_encrypt_from_local'); - - return; - } - - $loader->load('secrets.php'); - - $container->getDefinition('secrets.vault')->replaceArgument(0, $config['vault_directory']); - - if ($config['local_dotenv_file']) { - $container->getDefinition('secrets.local_vault')->replaceArgument(0, $config['local_dotenv_file']); - } else { - $container->removeDefinition('secrets.local_vault'); - } - - if ($config['decryption_env_var']) { - if (!preg_match('/^(?:[-.\w]*+:)*+\w++$/', $config['decryption_env_var'])) { - throw new InvalidArgumentException(sprintf('Invalid value "%s" set as "decryption_env_var": only "word" characters are allowed.', $config['decryption_env_var'])); - } - - if (ContainerBuilder::willBeAvailable('symfony/string', LazyString::class, ['symfony/framework-bundle'], true)) { - $container->getDefinition('secrets.decryption_key')->replaceArgument(1, $config['decryption_env_var']); - } else { - $container->getDefinition('secrets.vault')->replaceArgument(1, "%env({$config['decryption_env_var']})%"); - $container->removeDefinition('secrets.decryption_key'); - } - } else { - $container->getDefinition('secrets.vault')->replaceArgument(1, null); - $container->removeDefinition('secrets.decryption_key'); - } - } - - private function registerSecurityCsrfConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader) - { - if (!$this->isConfigEnabled($container, $config)) { - return; - } - - if (!class_exists(\Symfony\Component\Security\Csrf\CsrfToken::class)) { - throw new LogicException('CSRF support cannot be enabled as the Security CSRF component is not installed. Try running "composer require symfony/security-csrf".'); - } - - if (!$this->sessionConfigEnabled) { - throw new \LogicException('CSRF protection needs sessions to be enabled.'); - } - - // Enable services for CSRF protection (even without forms) - $loader->load('security_csrf.php'); - - if (!class_exists(CsrfExtension::class)) { - $container->removeDefinition('twig.extension.security_csrf'); - } - } - - private function registerSerializerConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader) - { - $loader->load('serializer.php'); - if ($container->getParameter('kernel.debug')) { - $container->removeDefinition('serializer.mapping.cache_class_metadata_factory'); - } - - $chainLoader = $container->getDefinition('serializer.mapping.chain_loader'); - - if (!$this->propertyAccessConfigEnabled) { - $container->removeAlias('serializer.property_accessor'); - $container->removeDefinition('serializer.normalizer.object'); - } - - if (!class_exists(Yaml::class)) { - $container->removeDefinition('serializer.encoder.yaml'); - } - - if (!class_exists(UnwrappingDenormalizer::class) || !$this->propertyAccessConfigEnabled) { - $container->removeDefinition('serializer.denormalizer.unwrapping'); - } - - if (!class_exists(Headers::class)) { - $container->removeDefinition('serializer.normalizer.mime_message'); - } - - $serializerLoaders = []; - if (isset($config['enable_annotations']) && $config['enable_annotations']) { - if (\PHP_VERSION_ID < 80000 && !$this->annotationsConfigEnabled) { - throw new \LogicException('"enable_annotations" on the serializer cannot be set as the PHP version is lower than 8 and Annotations support is disabled. Consider upgrading PHP.'); - } - - $annotationLoader = new Definition( - 'Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader', - [new Reference('annotation_reader', ContainerInterface::NULL_ON_INVALID_REFERENCE)] - ); - $annotationLoader->setPublic(false); - - $serializerLoaders[] = $annotationLoader; - } - - $fileRecorder = function ($extension, $path) use (&$serializerLoaders) { - $definition = new Definition(\in_array($extension, ['yaml', 'yml']) ? 'Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader' : 'Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader', [$path]); - $definition->setPublic(false); - $serializerLoaders[] = $definition; - }; - - foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) { - $configDir = is_dir($bundle['path'].'/Resources/config') ? $bundle['path'].'/Resources/config' : $bundle['path'].'/config'; - - if ($container->fileExists($file = $configDir.'/serialization.xml', false)) { - $fileRecorder('xml', $file); - } - - if ( - $container->fileExists($file = $configDir.'/serialization.yaml', false) || - $container->fileExists($file = $configDir.'/serialization.yml', false) - ) { - $fileRecorder('yml', $file); - } - - if ($container->fileExists($dir = $configDir.'/serialization', '/^$/')) { - $this->registerMappingFilesFromDir($dir, $fileRecorder); - } - } - - $projectDir = $container->getParameter('kernel.project_dir'); - if ($container->fileExists($dir = $projectDir.'/config/serializer', '/^$/')) { - $this->registerMappingFilesFromDir($dir, $fileRecorder); - } - - $this->registerMappingFilesFromConfig($container, $config, $fileRecorder); - - $chainLoader->replaceArgument(0, $serializerLoaders); - $container->getDefinition('serializer.mapping.cache_warmer')->replaceArgument(0, $serializerLoaders); - - if (isset($config['name_converter']) && $config['name_converter']) { - $container->getDefinition('serializer.name_converter.metadata_aware')->setArgument(1, new Reference($config['name_converter'])); - } - - if (isset($config['circular_reference_handler']) && $config['circular_reference_handler']) { - $arguments = $container->getDefinition('serializer.normalizer.object')->getArguments(); - $context = ($arguments[6] ?? []) + ['circular_reference_handler' => new Reference($config['circular_reference_handler'])]; - $container->getDefinition('serializer.normalizer.object')->setArgument(5, null); - $container->getDefinition('serializer.normalizer.object')->setArgument(6, $context); - } - - if ($config['max_depth_handler'] ?? false) { - $defaultContext = $container->getDefinition('serializer.normalizer.object')->getArgument(6); - $defaultContext += ['max_depth_handler' => new Reference($config['max_depth_handler'])]; - $container->getDefinition('serializer.normalizer.object')->replaceArgument(6, $defaultContext); - } - - if (isset($config['default_context']) && $config['default_context']) { - $container->setParameter('serializer.default_context', $config['default_context']); - } - } - - private function registerPropertyInfoConfiguration(ContainerBuilder $container, PhpFileLoader $loader) - { - if (!interface_exists(PropertyInfoExtractorInterface::class)) { - throw new LogicException('PropertyInfo support cannot be enabled as the PropertyInfo component is not installed. Try running "composer require symfony/property-info".'); - } - - $loader->load('property_info.php'); - - if ( - ContainerBuilder::willBeAvailable('phpstan/phpdoc-parser', PhpDocParser::class, ['symfony/framework-bundle', 'symfony/property-info'], true) - && ContainerBuilder::willBeAvailable('phpdocumentor/type-resolver', ContextFactory::class, ['symfony/framework-bundle', 'symfony/property-info'], true) - ) { - $definition = $container->register('property_info.phpstan_extractor', PhpStanExtractor::class); - $definition->addTag('property_info.type_extractor', ['priority' => -1000]); - } - - if (ContainerBuilder::willBeAvailable('phpdocumentor/reflection-docblock', DocBlockFactoryInterface::class, ['symfony/framework-bundle', 'symfony/property-info'], true)) { - $definition = $container->register('property_info.php_doc_extractor', 'Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor'); - $definition->addTag('property_info.description_extractor', ['priority' => -1000]); - $definition->addTag('property_info.type_extractor', ['priority' => -1001]); - } - - if ($container->getParameter('kernel.debug')) { - $container->removeDefinition('property_info.cache'); - } - } - - private function registerLockConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader) - { - $loader->load('lock.php'); - - foreach ($config['resources'] as $resourceName => $resourceStores) { - if (0 === \count($resourceStores)) { - continue; - } - - // Generate stores - $storeDefinitions = []; - foreach ($resourceStores as $resourceStore) { - $storeDsn = $container->resolveEnvPlaceholders($resourceStore, null, $usedEnvs); - $storeDefinition = new Definition(interface_exists(StoreInterface::class) ? StoreInterface::class : PersistingStoreInterface::class); - $storeDefinition->setFactory([StoreFactory::class, 'createStore']); - $storeDefinition->setArguments([$resourceStore]); - - $container->setDefinition($storeDefinitionId = '.lock.'.$resourceName.'.store.'.$container->hash($storeDsn), $storeDefinition); - - $storeDefinition = new Reference($storeDefinitionId); - - $storeDefinitions[] = $storeDefinition; - } - - // Wrap array of stores with CombinedStore - if (\count($storeDefinitions) > 1) { - $combinedDefinition = new ChildDefinition('lock.store.combined.abstract'); - $combinedDefinition->replaceArgument(0, $storeDefinitions); - $container->setDefinition('lock.'.$resourceName.'.store', $combinedDefinition)->setDeprecated('symfony/framework-bundle', '5.2', 'The "%service_id%" service is deprecated, use "lock.'.$resourceName.'.factory" instead.'); - $container->setDefinition($storeDefinitionId = '.lock.'.$resourceName.'.store.'.$container->hash($resourceStores), $combinedDefinition); - } else { - $container->setAlias('lock.'.$resourceName.'.store', (new Alias($storeDefinitionId, false))->setDeprecated('symfony/framework-bundle', '5.2', 'The "%alias_id%" alias is deprecated, use "lock.'.$resourceName.'.factory" instead.')); - } - - // Generate factories for each resource - $factoryDefinition = new ChildDefinition('lock.factory.abstract'); - $factoryDefinition->replaceArgument(0, new Reference($storeDefinitionId)); - $container->setDefinition('lock.'.$resourceName.'.factory', $factoryDefinition); - - // Generate services for lock instances - $lockDefinition = new Definition(Lock::class); - $lockDefinition->setPublic(false); - $lockDefinition->setFactory([new Reference('lock.'.$resourceName.'.factory'), 'createLock']); - $lockDefinition->setArguments([$resourceName]); - $container->setDefinition('lock.'.$resourceName, $lockDefinition)->setDeprecated('symfony/framework-bundle', '5.2', 'The "%service_id%" service is deprecated, use "lock.'.$resourceName.'.factory" instead.'); - - // provide alias for default resource - if ('default' === $resourceName) { - $container->setAlias('lock.store', (new Alias($storeDefinitionId, false))->setDeprecated('symfony/framework-bundle', '5.2', 'The "%alias_id%" alias is deprecated, use "lock.factory" instead.')); - $container->setAlias('lock.factory', new Alias('lock.'.$resourceName.'.factory', false)); - $container->setAlias('lock', (new Alias('lock.'.$resourceName, false))->setDeprecated('symfony/framework-bundle', '5.2', 'The "%alias_id%" alias is deprecated, use "lock.factory" instead.')); - $container->setAlias(PersistingStoreInterface::class, (new Alias($storeDefinitionId, false))->setDeprecated('symfony/framework-bundle', '5.2', 'The "%alias_id%" alias is deprecated, use "'.LockFactory::class.'" instead.')); - $container->setAlias(LockFactory::class, new Alias('lock.factory', false)); - $container->setAlias(LockInterface::class, (new Alias('lock.'.$resourceName, false))->setDeprecated('symfony/framework-bundle', '5.2', 'The "%alias_id%" alias is deprecated, use "'.LockFactory::class.'" instead.')); - } else { - $container->registerAliasForArgument($storeDefinitionId, PersistingStoreInterface::class, $resourceName.'.lock.store')->setDeprecated('symfony/framework-bundle', '5.2', 'The "%alias_id%" alias is deprecated, use "'.LockFactory::class.' '.$resourceName.'LockFactory" instead.'); - $container->registerAliasForArgument('lock.'.$resourceName.'.factory', LockFactory::class, $resourceName.'.lock.factory'); - $container->registerAliasForArgument('lock.'.$resourceName, LockInterface::class, $resourceName.'.lock')->setDeprecated('symfony/framework-bundle', '5.2', 'The "%alias_id%" alias is deprecated, use "'.LockFactory::class.' $'.$resourceName.'LockFactory" instead.'); - } - } - } - - private function registerMessengerConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader, array $validationConfig) - { - if (!interface_exists(MessageBusInterface::class)) { - throw new LogicException('Messenger support cannot be enabled as the Messenger component is not installed. Try running "composer require symfony/messenger".'); - } - - $loader->load('messenger.php'); - - if (!interface_exists(DenormalizerInterface::class)) { - $container->removeDefinition('serializer.normalizer.flatten_exception'); - } - - if (ContainerBuilder::willBeAvailable('symfony/amqp-messenger', AmqpTransportFactory::class, ['symfony/framework-bundle', 'symfony/messenger'], true)) { - $container->getDefinition('messenger.transport.amqp.factory')->addTag('messenger.transport_factory'); - } - - if (ContainerBuilder::willBeAvailable('symfony/redis-messenger', RedisTransportFactory::class, ['symfony/framework-bundle', 'symfony/messenger'], true)) { - $container->getDefinition('messenger.transport.redis.factory')->addTag('messenger.transport_factory'); - } - - if (ContainerBuilder::willBeAvailable('symfony/amazon-sqs-messenger', AmazonSqsTransportFactory::class, ['symfony/framework-bundle', 'symfony/messenger'], true)) { - $container->getDefinition('messenger.transport.sqs.factory')->addTag('messenger.transport_factory'); - } - - if (ContainerBuilder::willBeAvailable('symfony/beanstalkd-messenger', BeanstalkdTransportFactory::class, ['symfony/framework-bundle', 'symfony/messenger'], true)) { - $container->getDefinition('messenger.transport.beanstalkd.factory')->addTag('messenger.transport_factory'); - } - - if (null === $config['default_bus'] && 1 === \count($config['buses'])) { - $config['default_bus'] = key($config['buses']); - } - - $defaultMiddleware = [ - 'before' => [ - ['id' => 'add_bus_name_stamp_middleware'], - ['id' => 'reject_redelivered_message_middleware'], - ['id' => 'dispatch_after_current_bus'], - ['id' => 'failed_message_processing_middleware'], - ], - 'after' => [ - ['id' => 'send_message'], - ['id' => 'handle_message'], - ], - ]; - foreach ($config['buses'] as $busId => $bus) { - $middleware = $bus['middleware']; - - if ($bus['default_middleware']) { - if ('allow_no_handlers' === $bus['default_middleware']) { - $defaultMiddleware['after'][1]['arguments'] = [true]; - } else { - unset($defaultMiddleware['after'][1]['arguments']); - } - - // argument to add_bus_name_stamp_middleware - $defaultMiddleware['before'][0]['arguments'] = [$busId]; - - $middleware = array_merge($defaultMiddleware['before'], $middleware, $defaultMiddleware['after']); - } - - foreach ($middleware as $middlewareItem) { - if (!$validationConfig['enabled'] && \in_array($middlewareItem['id'], ['validation', 'messenger.middleware.validation'], true)) { - throw new LogicException('The Validation middleware is only available when the Validator component is installed and enabled. Try running "composer require symfony/validator".'); - } - } - - if ($container->getParameter('kernel.debug') && class_exists(Stopwatch::class)) { - array_unshift($middleware, ['id' => 'traceable', 'arguments' => [$busId]]); - } - - $container->setParameter($busId.'.middleware', $middleware); - $container->register($busId, MessageBus::class)->addArgument([])->addTag('messenger.bus'); - - if ($busId === $config['default_bus']) { - $container->setAlias('messenger.default_bus', $busId)->setPublic(true); - $container->setAlias(MessageBusInterface::class, $busId); - } else { - $container->registerAliasForArgument($busId, MessageBusInterface::class); - } - } - - if (empty($config['transports'])) { - $container->removeDefinition('messenger.transport.symfony_serializer'); - $container->removeDefinition('messenger.transport.amqp.factory'); - $container->removeDefinition('messenger.transport.redis.factory'); - $container->removeDefinition('messenger.transport.sqs.factory'); - $container->removeDefinition('messenger.transport.beanstalkd.factory'); - $container->removeAlias(SerializerInterface::class); - } else { - $container->getDefinition('messenger.transport.symfony_serializer') - ->replaceArgument(1, $config['serializer']['symfony_serializer']['format']) - ->replaceArgument(2, $config['serializer']['symfony_serializer']['context']); - $container->setAlias('messenger.default_serializer', $config['serializer']['default_serializer']); - } - - $failureTransports = []; - if ($config['failure_transport']) { - if (!isset($config['transports'][$config['failure_transport']])) { - throw new LogicException(sprintf('Invalid Messenger configuration: the failure transport "%s" is not a valid transport or service id.', $config['failure_transport'])); - } - - $container->setAlias('messenger.failure_transports.default', 'messenger.transport.'.$config['failure_transport']); - $failureTransports[] = $config['failure_transport']; - } - - $failureTransportsByName = []; - foreach ($config['transports'] as $name => $transport) { - if ($transport['failure_transport']) { - $failureTransports[] = $transport['failure_transport']; - $failureTransportsByName[$name] = $transport['failure_transport']; - } elseif ($config['failure_transport']) { - $failureTransportsByName[$name] = $config['failure_transport']; - } - } - - $senderAliases = []; - $transportRetryReferences = []; - foreach ($config['transports'] as $name => $transport) { - $serializerId = $transport['serializer'] ?? 'messenger.default_serializer'; - $transportDefinition = (new Definition(TransportInterface::class)) - ->setFactory([new Reference('messenger.transport_factory'), 'createTransport']) - ->setArguments([$transport['dsn'], $transport['options'] + ['transport_name' => $name], new Reference($serializerId)]) - ->addTag('messenger.receiver', [ - 'alias' => $name, - 'is_failure_transport' => \in_array($name, $failureTransports), - ] - ) - ; - $container->setDefinition($transportId = 'messenger.transport.'.$name, $transportDefinition); - $senderAliases[$name] = $transportId; - - if (null !== $transport['retry_strategy']['service']) { - $transportRetryReferences[$name] = new Reference($transport['retry_strategy']['service']); - } else { - $retryServiceId = sprintf('messenger.retry.multiplier_retry_strategy.%s', $name); - $retryDefinition = new ChildDefinition('messenger.retry.abstract_multiplier_retry_strategy'); - $retryDefinition - ->replaceArgument(0, $transport['retry_strategy']['max_retries']) - ->replaceArgument(1, $transport['retry_strategy']['delay']) - ->replaceArgument(2, $transport['retry_strategy']['multiplier']) - ->replaceArgument(3, $transport['retry_strategy']['max_delay']); - $container->setDefinition($retryServiceId, $retryDefinition); - - $transportRetryReferences[$name] = new Reference($retryServiceId); - } - } - - $senderReferences = []; - // alias => service_id - foreach ($senderAliases as $alias => $serviceId) { - $senderReferences[$alias] = new Reference($serviceId); - } - // service_id => service_id - foreach ($senderAliases as $serviceId) { - $senderReferences[$serviceId] = new Reference($serviceId); - } - - foreach ($config['transports'] as $name => $transport) { - if ($transport['failure_transport']) { - if (!isset($senderReferences[$transport['failure_transport']])) { - throw new LogicException(sprintf('Invalid Messenger configuration: the failure transport "%s" is not a valid transport or service id.', $transport['failure_transport'])); - } - } - } - - $failureTransportReferencesByTransportName = array_map(function ($failureTransportName) use ($senderReferences) { - return $senderReferences[$failureTransportName]; - }, $failureTransportsByName); - - $messageToSendersMapping = []; - foreach ($config['routing'] as $message => $messageConfiguration) { - if ('*' !== $message && !class_exists($message) && !interface_exists($message, false)) { - throw new LogicException(sprintf('Invalid Messenger routing configuration: class or interface "%s" not found.', $message)); - } - - // make sure senderAliases contains all senders - foreach ($messageConfiguration['senders'] as $sender) { - if (!isset($senderReferences[$sender])) { - throw new LogicException(sprintf('Invalid Messenger routing configuration: the "%s" class is being routed to a sender called "%s". This is not a valid transport or service id.', $message, $sender)); - } - } - - $messageToSendersMapping[$message] = $messageConfiguration['senders']; - } - - $sendersServiceLocator = ServiceLocatorTagPass::register($container, $senderReferences); - - $container->getDefinition('messenger.senders_locator') - ->replaceArgument(0, $messageToSendersMapping) - ->replaceArgument(1, $sendersServiceLocator) - ; - - $container->getDefinition('messenger.retry.send_failed_message_for_retry_listener') - ->replaceArgument(0, $sendersServiceLocator) - ; - - $container->getDefinition('messenger.retry_strategy_locator') - ->replaceArgument(0, $transportRetryReferences); - - if (\count($failureTransports) > 0) { - $container->getDefinition('console.command.messenger_failed_messages_retry') - ->replaceArgument(0, $config['failure_transport']); - $container->getDefinition('console.command.messenger_failed_messages_show') - ->replaceArgument(0, $config['failure_transport']); - $container->getDefinition('console.command.messenger_failed_messages_remove') - ->replaceArgument(0, $config['failure_transport']); - - $failureTransportsByTransportNameServiceLocator = ServiceLocatorTagPass::register($container, $failureTransportReferencesByTransportName); - $container->getDefinition('messenger.failure.send_failed_message_to_failure_transport_listener') - ->replaceArgument(0, $failureTransportsByTransportNameServiceLocator); - } else { - $container->removeDefinition('messenger.failure.send_failed_message_to_failure_transport_listener'); - $container->removeDefinition('console.command.messenger_failed_messages_retry'); - $container->removeDefinition('console.command.messenger_failed_messages_show'); - $container->removeDefinition('console.command.messenger_failed_messages_remove'); - } - - if (false === $config['reset_on_message']) { - throw new LogicException('The "framework.messenger.reset_on_message" configuration option can be set to "true" only. To prevent services resetting after each message you can set the "--no-reset" option in "messenger:consume" command.'); - } - - if (!$container->hasDefinition('console.command.messenger_consume_messages')) { - $container->removeDefinition('messenger.listener.reset_services'); - } elseif (null === $config['reset_on_message']) { - trigger_deprecation('symfony/framework-bundle', '5.4', 'Not setting the "framework.messenger.reset_on_message" configuration option is deprecated, it will default to "true" in version 6.0.'); - - $container->getDefinition('console.command.messenger_consume_messages')->replaceArgument(5, null); - $container->removeDefinition('messenger.listener.reset_services'); - } - } - - private function registerCacheConfiguration(array $config, ContainerBuilder $container) - { - if (!class_exists(DefaultMarshaller::class)) { - $container->removeDefinition('cache.default_marshaller'); - } - - if (!class_exists(DoctrineAdapter::class)) { - $container->removeDefinition('cache.adapter.doctrine'); - } - - if (!class_exists(DoctrineDbalAdapter::class)) { - $container->removeDefinition('cache.adapter.doctrine_dbal'); - } - - $version = new Parameter('container.build_id'); - $container->getDefinition('cache.adapter.apcu')->replaceArgument(2, $version); - $container->getDefinition('cache.adapter.system')->replaceArgument(2, $version); - $container->getDefinition('cache.adapter.filesystem')->replaceArgument(2, $config['directory']); - - if (isset($config['prefix_seed'])) { - $container->setParameter('cache.prefix.seed', $config['prefix_seed']); - } - if ($container->hasParameter('cache.prefix.seed')) { - // Inline any env vars referenced in the parameter - $container->setParameter('cache.prefix.seed', $container->resolveEnvPlaceholders($container->getParameter('cache.prefix.seed'), true)); - } - foreach (['doctrine', 'psr6', 'redis', 'memcached', 'doctrine_dbal', 'pdo'] as $name) { - if (isset($config[$name = 'default_'.$name.'_provider'])) { - $container->setAlias('cache.'.$name, new Alias(CachePoolPass::getServiceProvider($container, $config[$name]), false)); - } - } - foreach (['app', 'system'] as $name) { - $config['pools']['cache.'.$name] = [ - 'adapters' => [$config[$name]], - 'public' => true, - 'tags' => false, - ]; - } - foreach ($config['pools'] as $name => $pool) { - $pool['adapters'] = $pool['adapters'] ?: ['cache.app']; - - $isRedisTagAware = ['cache.adapter.redis_tag_aware'] === $pool['adapters']; - foreach ($pool['adapters'] as $provider => $adapter) { - if (($config['pools'][$adapter]['adapters'] ?? null) === ['cache.adapter.redis_tag_aware']) { - $isRedisTagAware = true; - } elseif ($config['pools'][$adapter]['tags'] ?? false) { - $pool['adapters'][$provider] = $adapter = '.'.$adapter.'.inner'; - } - } - - if (1 === \count($pool['adapters'])) { - if (!isset($pool['provider']) && !\is_int($provider)) { - $pool['provider'] = $provider; - } - $definition = new ChildDefinition($adapter); - } else { - $definition = new Definition(ChainAdapter::class, [$pool['adapters'], 0]); - $pool['reset'] = 'reset'; - } - - if ($isRedisTagAware && 'cache.app' === $name) { - $container->setAlias('cache.app.taggable', $name); - } elseif ($isRedisTagAware) { - $tagAwareId = $name; - $container->setAlias('.'.$name.'.inner', $name); - } elseif ($pool['tags']) { - if (true !== $pool['tags'] && ($config['pools'][$pool['tags']]['tags'] ?? false)) { - $pool['tags'] = '.'.$pool['tags'].'.inner'; - } - $container->register($name, TagAwareAdapter::class) - ->addArgument(new Reference('.'.$name.'.inner')) - ->addArgument(true !== $pool['tags'] ? new Reference($pool['tags']) : null) - ->setPublic($pool['public']) - ; - - if (method_exists(TagAwareAdapter::class, 'setLogger')) { - $container - ->getDefinition($name) - ->addMethodCall('setLogger', [new Reference('logger', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)]) - ->addTag('monolog.logger', ['channel' => 'cache']); - } - - $pool['name'] = $tagAwareId = $name; - $pool['public'] = false; - $name = '.'.$name.'.inner'; - } elseif (!\in_array($name, ['cache.app', 'cache.system'], true)) { - $tagAwareId = '.'.$name.'.taggable'; - $container->register($tagAwareId, TagAwareAdapter::class) - ->addArgument(new Reference($name)) - ; - } - - if (!\in_array($name, ['cache.app', 'cache.system'], true)) { - $container->registerAliasForArgument($tagAwareId, TagAwareCacheInterface::class, $pool['name'] ?? $name); - $container->registerAliasForArgument($name, CacheInterface::class, $pool['name'] ?? $name); - $container->registerAliasForArgument($name, CacheItemPoolInterface::class, $pool['name'] ?? $name); - } - - $definition->setPublic($pool['public']); - unset($pool['adapters'], $pool['public'], $pool['tags']); - - $definition->addTag('cache.pool', $pool); - $container->setDefinition($name, $definition); - } - - if (method_exists(PropertyAccessor::class, 'createCache')) { - $propertyAccessDefinition = $container->register('cache.property_access', AdapterInterface::class); - $propertyAccessDefinition->setPublic(false); - - if (!$container->getParameter('kernel.debug')) { - $propertyAccessDefinition->setFactory([PropertyAccessor::class, 'createCache']); - $propertyAccessDefinition->setArguments(['', 0, $version, new Reference('logger', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)]); - $propertyAccessDefinition->addTag('cache.pool', ['clearer' => 'cache.system_clearer']); - $propertyAccessDefinition->addTag('monolog.logger', ['channel' => 'cache']); - } else { - $propertyAccessDefinition->setClass(ArrayAdapter::class); - $propertyAccessDefinition->setArguments([0, false]); - } - } - } - - private function registerHttpClientConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader, array $profilerConfig) - { - $loader->load('http_client.php'); - - $options = $config['default_options'] ?? []; - $retryOptions = $options['retry_failed'] ?? ['enabled' => false]; - unset($options['retry_failed']); - $container->getDefinition('http_client')->setArguments([$options, $config['max_host_connections'] ?? 6]); - - if (!$hasPsr18 = ContainerBuilder::willBeAvailable('psr/http-client', ClientInterface::class, ['symfony/framework-bundle', 'symfony/http-client'], true)) { - $container->removeDefinition('psr18.http_client'); - $container->removeAlias(ClientInterface::class); - } - - if (!ContainerBuilder::willBeAvailable('php-http/httplug', HttpClient::class, ['symfony/framework-bundle', 'symfony/http-client'], true)) { - $container->removeDefinition(HttpClient::class); - } - - if ($this->isConfigEnabled($container, $retryOptions)) { - $this->registerRetryableHttpClient($retryOptions, 'http_client', $container); - } - - $httpClientId = ($retryOptions['enabled'] ?? false) ? 'http_client.retryable.inner' : ($this->isConfigEnabled($container, $profilerConfig) ? '.debug.http_client.inner' : 'http_client'); - foreach ($config['scoped_clients'] as $name => $scopeConfig) { - if ('http_client' === $name) { - throw new InvalidArgumentException(sprintf('Invalid scope name: "%s" is reserved.', $name)); - } - - $scope = $scopeConfig['scope'] ?? null; - unset($scopeConfig['scope']); - $retryOptions = $scopeConfig['retry_failed'] ?? ['enabled' => false]; - unset($scopeConfig['retry_failed']); - - if (null === $scope) { - $baseUri = $scopeConfig['base_uri']; - unset($scopeConfig['base_uri']); - - $container->register($name, ScopingHttpClient::class) - ->setFactory([ScopingHttpClient::class, 'forBaseUri']) - ->setArguments([new Reference($httpClientId), $baseUri, $scopeConfig]) - ->addTag('http_client.client') - ; - } else { - $container->register($name, ScopingHttpClient::class) - ->setArguments([new Reference($httpClientId), [$scope => $scopeConfig], $scope]) - ->addTag('http_client.client') - ; - } - - if ($this->isConfigEnabled($container, $retryOptions)) { - $this->registerRetryableHttpClient($retryOptions, $name, $container); - } - - $container->registerAliasForArgument($name, HttpClientInterface::class); - - if ($hasPsr18) { - $container->setDefinition('psr18.'.$name, new ChildDefinition('psr18.http_client')) - ->replaceArgument(0, new Reference($name)); - - $container->registerAliasForArgument('psr18.'.$name, ClientInterface::class, $name); - } - } - - if ($responseFactoryId = $config['mock_response_factory'] ?? null) { - $container->register($httpClientId.'.mock_client', MockHttpClient::class) - ->setDecoratedService($httpClientId, null, -10) // lower priority than TraceableHttpClient - ->setArguments([new Reference($responseFactoryId)]); - } - } - - private function registerRetryableHttpClient(array $options, string $name, ContainerBuilder $container) - { - if (!class_exists(RetryableHttpClient::class)) { - throw new LogicException('Support for retrying failed requests requires symfony/http-client 5.2 or higher, try upgrading.'); - } - - if (null !== $options['retry_strategy']) { - $retryStrategy = new Reference($options['retry_strategy']); - } else { - $retryStrategy = new ChildDefinition('http_client.abstract_retry_strategy'); - $codes = []; - foreach ($options['http_codes'] as $code => $codeOptions) { - if ($codeOptions['methods']) { - $codes[$code] = $codeOptions['methods']; - } else { - $codes[] = $code; - } - } - - $retryStrategy - ->replaceArgument(0, $codes ?: GenericRetryStrategy::DEFAULT_RETRY_STATUS_CODES) - ->replaceArgument(1, $options['delay']) - ->replaceArgument(2, $options['multiplier']) - ->replaceArgument(3, $options['max_delay']) - ->replaceArgument(4, $options['jitter']); - $container->setDefinition($name.'.retry_strategy', $retryStrategy); - - $retryStrategy = new Reference($name.'.retry_strategy'); - } - - $container - ->register($name.'.retryable', RetryableHttpClient::class) - ->setDecoratedService($name, null, 10) // higher priority than TraceableHttpClient - ->setArguments([new Reference($name.'.retryable.inner'), $retryStrategy, $options['max_retries'], new Reference('logger')]) - ->addTag('monolog.logger', ['channel' => 'http_client']); - } - - private function registerMailerConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader) - { - if (!class_exists(Mailer::class)) { - throw new LogicException('Mailer support cannot be enabled as the component is not installed. Try running "composer require symfony/mailer".'); - } - - $loader->load('mailer.php'); - $loader->load('mailer_transports.php'); - if (!\count($config['transports']) && null === $config['dsn']) { - $config['dsn'] = 'smtp://null'; - } - $transports = $config['dsn'] ? ['main' => $config['dsn']] : $config['transports']; - $container->getDefinition('mailer.transports')->setArgument(0, $transports); - $container->getDefinition('mailer.default_transport')->setArgument(0, current($transports)); - - $container->removeDefinition('mailer.logger_message_listener'); - $container->setAlias('mailer.logger_message_listener', (new Alias('mailer.message_logger_listener'))->setDeprecated('symfony/framework-bundle', '5.2', 'The "%alias_id%" alias is deprecated, use "mailer.message_logger_listener" instead.')); - - $mailer = $container->getDefinition('mailer.mailer'); - if (false === $messageBus = $config['message_bus']) { - $mailer->replaceArgument(1, null); - } else { - $mailer->replaceArgument(1, $messageBus ? new Reference($messageBus) : new Reference('messenger.default_bus', ContainerInterface::NULL_ON_INVALID_REFERENCE)); - } - - $classToServices = [ - GmailTransportFactory::class => 'mailer.transport_factory.gmail', - MailgunTransportFactory::class => 'mailer.transport_factory.mailgun', - MailjetTransportFactory::class => 'mailer.transport_factory.mailjet', - MandrillTransportFactory::class => 'mailer.transport_factory.mailchimp', - OhMySmtpTransportFactory::class => 'mailer.transport_factory.ohmysmtp', - PostmarkTransportFactory::class => 'mailer.transport_factory.postmark', - SendgridTransportFactory::class => 'mailer.transport_factory.sendgrid', - SendinblueTransportFactory::class => 'mailer.transport_factory.sendinblue', - SesTransportFactory::class => 'mailer.transport_factory.amazon', - ]; - - foreach ($classToServices as $class => $service) { - $package = substr($service, \strlen('mailer.transport_factory.')); - - if (!ContainerBuilder::willBeAvailable(sprintf('symfony/%s-mailer', 'gmail' === $package ? 'google' : $package), $class, ['symfony/framework-bundle', 'symfony/mailer'], true)) { - $container->removeDefinition($service); - } - } - - $envelopeListener = $container->getDefinition('mailer.envelope_listener'); - $envelopeListener->setArgument(0, $config['envelope']['sender'] ?? null); - $envelopeListener->setArgument(1, $config['envelope']['recipients'] ?? null); - - if ($config['headers']) { - $headers = new Definition(Headers::class); - foreach ($config['headers'] as $name => $data) { - $value = $data['value']; - if (\in_array(strtolower($name), ['from', 'to', 'cc', 'bcc', 'reply-to'])) { - $value = (array) $value; - } - $headers->addMethodCall('addHeader', [$name, $value]); - } - $messageListener = $container->getDefinition('mailer.message_listener'); - $messageListener->setArgument(0, $headers); - } else { - $container->removeDefinition('mailer.message_listener'); - } - } - - private function registerNotifierConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader) - { - if (!class_exists(Notifier::class)) { - throw new LogicException('Notifier support cannot be enabled as the component is not installed. Try running "composer require symfony/notifier".'); - } - - $loader->load('notifier.php'); - $loader->load('notifier_transports.php'); - - if ($config['chatter_transports']) { - $container->getDefinition('chatter.transports')->setArgument(0, $config['chatter_transports']); - } else { - $container->removeDefinition('chatter'); - $container->removeAlias(ChatterInterface::class); - } - if ($config['texter_transports']) { - $container->getDefinition('texter.transports')->setArgument(0, $config['texter_transports']); - } else { - $container->removeDefinition('texter'); - $container->removeAlias(TexterInterface::class); - } - - if ($this->mailerConfigEnabled) { - $sender = $container->getDefinition('mailer.envelope_listener')->getArgument(0); - $container->getDefinition('notifier.channel.email')->setArgument(2, $sender); - } else { - $container->removeDefinition('notifier.channel.email'); - } - - if ($this->messengerConfigEnabled) { - if ($config['notification_on_failed_messages']) { - $container->getDefinition('notifier.failed_message_listener')->addTag('kernel.event_subscriber'); - } - - // as we have a bus, the channels don't need the transports - $container->getDefinition('notifier.channel.chat')->setArgument(0, null); - if ($container->hasDefinition('notifier.channel.email')) { - $container->getDefinition('notifier.channel.email')->setArgument(0, null); - } - $container->getDefinition('notifier.channel.sms')->setArgument(0, null); - $container->getDefinition('notifier.channel.push')->setArgument(0, null); - } - - $container->getDefinition('notifier.channel_policy')->setArgument(0, $config['channel_policy']); - - $container->registerForAutoconfiguration(NotifierTransportFactoryInterface::class) - ->addTag('chatter.transport_factory'); - - $container->registerForAutoconfiguration(NotifierTransportFactoryInterface::class) - ->addTag('texter.transport_factory'); - - $classToServices = [ - AllMySmsTransportFactory::class => 'notifier.transport_factory.all-my-sms', - AmazonSnsTransportFactory::class => 'notifier.transport_factory.amazon-sns', - ClickatellTransportFactory::class => 'notifier.transport_factory.clickatell', - DiscordTransportFactory::class => 'notifier.transport_factory.discord', - EsendexTransportFactory::class => 'notifier.transport_factory.esendex', - ExpoTransportFactory::class => 'notifier.transport_factory.expo', - FakeChatTransportFactory::class => 'notifier.transport_factory.fake-chat', - FakeSmsTransportFactory::class => 'notifier.transport_factory.fake-sms', - FirebaseTransportFactory::class => 'notifier.transport_factory.firebase', - FreeMobileTransportFactory::class => 'notifier.transport_factory.free-mobile', - GatewayApiTransportFactory::class => 'notifier.transport_factory.gateway-api', - GitterTransportFactory::class => 'notifier.transport_factory.gitter', - GoogleChatTransportFactory::class => 'notifier.transport_factory.google-chat', - InfobipTransportFactory::class => 'notifier.transport_factory.infobip', - IqsmsTransportFactory::class => 'notifier.transport_factory.iqsms', - LightSmsTransportFactory::class => 'notifier.transport_factory.light-sms', - LinkedInTransportFactory::class => 'notifier.transport_factory.linked-in', - MailjetNotifierTransportFactory::class => 'notifier.transport_factory.mailjet', - MattermostTransportFactory::class => 'notifier.transport_factory.mattermost', - MercureTransportFactory::class => 'notifier.transport_factory.mercure', - MessageBirdTransport::class => 'notifier.transport_factory.message-bird', - MessageMediaTransportFactory::class => 'notifier.transport_factory.message-media', - MicrosoftTeamsTransportFactory::class => 'notifier.transport_factory.microsoft-teams', - MobytTransportFactory::class => 'notifier.transport_factory.mobyt', - NexmoTransportFactory::class => 'notifier.transport_factory.nexmo', - OctopushTransportFactory::class => 'notifier.transport_factory.octopush', - OneSignalTransportFactory::class => 'notifier.transport_factory.one-signal', - OvhCloudTransportFactory::class => 'notifier.transport_factory.ovh-cloud', - RocketChatTransportFactory::class => 'notifier.transport_factory.rocket-chat', - SendinblueNotifierTransportFactory::class => 'notifier.transport_factory.sendinblue', - SinchTransportFactory::class => 'notifier.transport_factory.sinch', - SlackTransportFactory::class => 'notifier.transport_factory.slack', - Sms77TransportFactory::class => 'notifier.transport_factory.sms77', - SmsapiTransportFactory::class => 'notifier.transport_factory.smsapi', - SmsBiurasTransportFactory::class => 'notifier.transport_factory.sms-biuras', - SmscTransportFactory::class => 'notifier.transport_factory.smsc', - SpotHitTransportFactory::class => 'notifier.transport_factory.spot-hit', - TelegramTransportFactory::class => 'notifier.transport_factory.telegram', - TelnyxTransportFactory::class => 'notifier.transport_factory.telnyx', - TurboSmsTransport::class => 'notifier.transport_factory.turbo-sms', - TwilioTransportFactory::class => 'notifier.transport_factory.twilio', - VonageTransportFactory::class => 'notifier.transport_factory.vonage', - YunpianTransportFactory::class => 'notifier.transport_factory.yunpian', - ZulipTransportFactory::class => 'notifier.transport_factory.zulip', - ]; - - $parentPackages = ['symfony/framework-bundle', 'symfony/notifier']; - - foreach ($classToServices as $class => $service) { - $package = substr($service, \strlen('notifier.transport_factory.')); - - if (!ContainerBuilder::willBeAvailable(sprintf('symfony/%s-notifier', $package), $class, $parentPackages, true)) { - $container->removeDefinition($service); - $container->removeAlias(str_replace('-', '', $service)); // @deprecated to be removed in 6.0 - } - } - - if (ContainerBuilder::willBeAvailable('symfony/mercure-notifier', MercureTransportFactory::class, $parentPackages, true) && ContainerBuilder::willBeAvailable('symfony/mercure-bundle', MercureBundle::class, $parentPackages, true) && \in_array(MercureBundle::class, $container->getParameter('kernel.bundles'), true)) { - $container->getDefinition($classToServices[MercureTransportFactory::class]) - ->replaceArgument('$registry', new Reference(HubRegistry::class)); - } elseif (ContainerBuilder::willBeAvailable('symfony/mercure-notifier', MercureTransportFactory::class, $parentPackages, true)) { - $container->removeDefinition($classToServices[MercureTransportFactory::class]); - } - - if (ContainerBuilder::willBeAvailable('symfony/fake-chat-notifier', FakeChatTransportFactory::class, ['symfony/framework-bundle', 'symfony/notifier', 'symfony/mailer'], true)) { - $container->getDefinition($classToServices[FakeChatTransportFactory::class]) - ->replaceArgument('$mailer', new Reference('mailer')) - ->replaceArgument('$logger', new Reference('logger')); - } - - if (ContainerBuilder::willBeAvailable('symfony/fake-sms-notifier', FakeSmsTransportFactory::class, ['symfony/framework-bundle', 'symfony/notifier', 'symfony/mailer'], true)) { - $container->getDefinition($classToServices[FakeSmsTransportFactory::class]) - ->replaceArgument('$mailer', new Reference('mailer')) - ->replaceArgument('$logger', new Reference('logger')); - } - - if (isset($config['admin_recipients'])) { - $notifier = $container->getDefinition('notifier'); - foreach ($config['admin_recipients'] as $i => $recipient) { - $id = 'notifier.admin_recipient.'.$i; - $container->setDefinition($id, new Definition(Recipient::class, [$recipient['email'], $recipient['phone']])); - $notifier->addMethodCall('addAdminRecipient', [new Reference($id)]); - } - } - } - - private function registerRateLimiterConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader) - { - $loader->load('rate_limiter.php'); - - foreach ($config['limiters'] as $name => $limiterConfig) { - self::registerRateLimiter($container, $name, $limiterConfig); - } - } - - public static function registerRateLimiter(ContainerBuilder $container, string $name, array $limiterConfig) - { - // default configuration (when used by other DI extensions) - $limiterConfig += ['lock_factory' => 'lock.factory', 'cache_pool' => 'cache.rate_limiter']; - - $limiter = $container->setDefinition($limiterId = 'limiter.'.$name, new ChildDefinition('limiter')); - - if (null !== $limiterConfig['lock_factory']) { - if (!self::$lockConfigEnabled) { - throw new LogicException(sprintf('Rate limiter "%s" requires the Lock component to be installed and configured.', $name)); - } - - $limiter->replaceArgument(2, new Reference($limiterConfig['lock_factory'])); - } - unset($limiterConfig['lock_factory']); - - $storageId = $limiterConfig['storage_service'] ?? null; - if (null === $storageId) { - $container->register($storageId = 'limiter.storage.'.$name, CacheStorage::class)->addArgument(new Reference($limiterConfig['cache_pool'])); - } - - $limiter->replaceArgument(1, new Reference($storageId)); - unset($limiterConfig['storage_service']); - unset($limiterConfig['cache_pool']); - - $limiterConfig['id'] = $name; - $limiter->replaceArgument(0, $limiterConfig); - - $container->registerAliasForArgument($limiterId, RateLimiterFactory::class, $name.'.limiter'); - } - - private function registerUidConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader) - { - $loader->load('uid.php'); - - $container->getDefinition('uuid.factory') - ->setArguments([ - $config['default_uuid_version'], - $config['time_based_uuid_version'], - $config['name_based_uuid_version'], - UuidV4::class, - $config['time_based_uuid_node'] ?? null, - $config['name_based_uuid_namespace'] ?? null, - ]) - ; - - if (isset($config['name_based_uuid_namespace'])) { - $container->getDefinition('name_based_uuid.factory') - ->setArguments([$config['name_based_uuid_namespace']]); - } - } - - private function resolveTrustedHeaders(array $headers): int - { - $trustedHeaders = 0; - - foreach ($headers as $h) { - switch ($h) { - case 'forwarded': $trustedHeaders |= Request::HEADER_FORWARDED; break; - case 'x-forwarded-for': $trustedHeaders |= Request::HEADER_X_FORWARDED_FOR; break; - case 'x-forwarded-host': $trustedHeaders |= Request::HEADER_X_FORWARDED_HOST; break; - case 'x-forwarded-proto': $trustedHeaders |= Request::HEADER_X_FORWARDED_PROTO; break; - case 'x-forwarded-port': $trustedHeaders |= Request::HEADER_X_FORWARDED_PORT; break; - case 'x-forwarded-prefix': $trustedHeaders |= Request::HEADER_X_FORWARDED_PREFIX; break; - } - } - - return $trustedHeaders; - } - - /** - * {@inheritdoc} - */ - public function getXsdValidationBasePath() - { - return \dirname(__DIR__).'/Resources/config/schema'; - } - - public function getNamespace() - { - return 'http://symfony.com/schema/dic/symfony'; - } -} diff --git a/lib/symfony/framework-bundle/EventListener/SuggestMissingPackageSubscriber.php b/lib/symfony/framework-bundle/EventListener/SuggestMissingPackageSubscriber.php deleted file mode 100644 index 53cae12eb..000000000 --- a/lib/symfony/framework-bundle/EventListener/SuggestMissingPackageSubscriber.php +++ /dev/null @@ -1,82 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\EventListener; - -use Symfony\Component\Console\ConsoleEvents; -use Symfony\Component\Console\Event\ConsoleErrorEvent; -use Symfony\Component\Console\Exception\CommandNotFoundException; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; - -/** - * Suggests a package, that should be installed (via composer), - * if the package is missing, and the input command namespace can be mapped to a Symfony bundle. - * - * @author Przemysław Bogusz <przemyslaw.bogusz@tubotax.pl> - * - * @internal - */ -final class SuggestMissingPackageSubscriber implements EventSubscriberInterface -{ - private const PACKAGES = [ - 'doctrine' => [ - 'fixtures' => ['DoctrineFixturesBundle', 'doctrine/doctrine-fixtures-bundle --dev'], - 'mongodb' => ['DoctrineMongoDBBundle', 'doctrine/mongodb-odm-bundle'], - '_default' => ['Doctrine ORM', 'symfony/orm-pack'], - ], - 'generate' => [ - '_default' => ['SensioGeneratorBundle', 'sensio/generator-bundle'], - ], - 'make' => [ - '_default' => ['MakerBundle', 'symfony/maker-bundle --dev'], - ], - 'server' => [ - '_default' => ['Debug Bundle', 'symfony/debug-bundle --dev'], - ], - ]; - - public function onConsoleError(ConsoleErrorEvent $event): void - { - if (!$event->getError() instanceof CommandNotFoundException) { - return; - } - - [$namespace, $command] = explode(':', $event->getInput()->getFirstArgument()) + [1 => '']; - - if (!isset(self::PACKAGES[$namespace])) { - return; - } - - if (isset(self::PACKAGES[$namespace][$command])) { - $suggestion = self::PACKAGES[$namespace][$command]; - $exact = true; - } else { - $suggestion = self::PACKAGES[$namespace]['_default']; - $exact = false; - } - - $error = $event->getError(); - - if ($error->getAlternatives() && !$exact) { - return; - } - - $message = sprintf("%s\n\nYou may be looking for a command provided by the \"%s\" which is currently not installed. Try running \"composer require %s\".", $error->getMessage(), $suggestion[0], $suggestion[1]); - $event->setError(new CommandNotFoundException($message)); - } - - public static function getSubscribedEvents(): array - { - return [ - ConsoleEvents::ERROR => ['onConsoleError', 0], - ]; - } -} diff --git a/lib/symfony/framework-bundle/FrameworkBundle.php b/lib/symfony/framework-bundle/FrameworkBundle.php deleted file mode 100644 index 4ec54eccf..000000000 --- a/lib/symfony/framework-bundle/FrameworkBundle.php +++ /dev/null @@ -1,180 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle; - -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddAnnotationsCachedReaderPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddDebugLogProcessorPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddExpressionLanguageProvidersPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AssetsContextPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ContainerBuilderDebugDumpPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\DataCollectorTranslatorPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggingTranslatorPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\RemoveUnusedSessionMarshallingHandlerPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SessionPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TestServiceContainerRealRefPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TestServiceContainerWeakRefPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\WorkflowGuardListenerPass; -use Symfony\Component\Cache\Adapter\ApcuAdapter; -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\ChainAdapter; -use Symfony\Component\Cache\Adapter\PhpArrayAdapter; -use Symfony\Component\Cache\Adapter\PhpFilesAdapter; -use Symfony\Component\Cache\DependencyInjection\CacheCollectorPass; -use Symfony\Component\Cache\DependencyInjection\CachePoolClearerPass; -use Symfony\Component\Cache\DependencyInjection\CachePoolPass; -use Symfony\Component\Cache\DependencyInjection\CachePoolPrunerPass; -use Symfony\Component\Config\Resource\ClassExistenceResource; -use Symfony\Component\Console\ConsoleEvents; -use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass; -use Symfony\Component\DependencyInjection\Compiler\PassConfig; -use Symfony\Component\DependencyInjection\Compiler\RegisterReverseContainerPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\Dotenv\Dotenv; -use Symfony\Component\ErrorHandler\ErrorHandler; -use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass; -use Symfony\Component\Form\DependencyInjection\FormPass; -use Symfony\Component\HttpClient\DependencyInjection\HttpClientPass; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Bundle\Bundle; -use Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass; -use Symfony\Component\HttpKernel\DependencyInjection\FragmentRendererPass; -use Symfony\Component\HttpKernel\DependencyInjection\LoggerPass; -use Symfony\Component\HttpKernel\DependencyInjection\RegisterControllerArgumentLocatorsPass; -use Symfony\Component\HttpKernel\DependencyInjection\RegisterLocaleAwareServicesPass; -use Symfony\Component\HttpKernel\DependencyInjection\RemoveEmptyControllerArgumentLocatorsPass; -use Symfony\Component\HttpKernel\DependencyInjection\ResettableServicePass; -use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\Messenger\DependencyInjection\MessengerPass; -use Symfony\Component\Mime\DependencyInjection\AddMimeTypeGuesserPass; -use Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass; -use Symfony\Component\Routing\DependencyInjection\RoutingResolverPass; -use Symfony\Component\Serializer\DependencyInjection\SerializerPass; -use Symfony\Component\Translation\DependencyInjection\TranslationDumperPass; -use Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass; -use Symfony\Component\Translation\DependencyInjection\TranslatorPass; -use Symfony\Component\Translation\DependencyInjection\TranslatorPathsPass; -use Symfony\Component\Validator\DependencyInjection\AddAutoMappingConfigurationPass; -use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass; -use Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass; -use Symfony\Component\VarExporter\Internal\Hydrator; -use Symfony\Component\VarExporter\Internal\Registry; - -// Help opcache.preload discover always-needed symbols -class_exists(ApcuAdapter::class); -class_exists(ArrayAdapter::class); -class_exists(ChainAdapter::class); -class_exists(PhpArrayAdapter::class); -class_exists(PhpFilesAdapter::class); -class_exists(Dotenv::class); -class_exists(ErrorHandler::class); -class_exists(Hydrator::class); -class_exists(Registry::class); - -/** - * Bundle. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class FrameworkBundle extends Bundle -{ - public function boot() - { - ErrorHandler::register(null, false)->throwAt($this->container->getParameter('debug.error_handler.throw_at'), true); - - if ($this->container->getParameter('kernel.http_method_override')) { - Request::enableHttpMethodParameterOverride(); - } - } - - public function build(ContainerBuilder $container) - { - parent::build($container); - - $registerListenersPass = new RegisterListenersPass(); - $registerListenersPass->setHotPathEvents([ - KernelEvents::REQUEST, - KernelEvents::CONTROLLER, - KernelEvents::CONTROLLER_ARGUMENTS, - KernelEvents::RESPONSE, - KernelEvents::FINISH_REQUEST, - ]); - if (class_exists(ConsoleEvents::class)) { - $registerListenersPass->setNoPreloadEvents([ - ConsoleEvents::COMMAND, - ConsoleEvents::TERMINATE, - ConsoleEvents::ERROR, - ]); - } - - $container->addCompilerPass(new AssetsContextPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION); - $container->addCompilerPass(new LoggerPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32); - $container->addCompilerPass(new RegisterControllerArgumentLocatorsPass()); - $container->addCompilerPass(new RemoveEmptyControllerArgumentLocatorsPass(), PassConfig::TYPE_BEFORE_REMOVING); - $container->addCompilerPass(new RoutingResolverPass()); - $container->addCompilerPass(new DataCollectorTranslatorPass()); - $container->addCompilerPass(new ProfilerPass()); - // must be registered before removing private services as some might be listeners/subscribers - // but as late as possible to get resolved parameters - $container->addCompilerPass($registerListenersPass, PassConfig::TYPE_BEFORE_REMOVING); - $this->addCompilerPassIfExists($container, AddConstraintValidatorsPass::class); - $container->addCompilerPass(new AddAnnotationsCachedReaderPass(), PassConfig::TYPE_AFTER_REMOVING, -255); - $this->addCompilerPassIfExists($container, AddValidatorInitializersPass::class); - $this->addCompilerPassIfExists($container, AddConsoleCommandPass::class, PassConfig::TYPE_BEFORE_REMOVING); - // must be registered as late as possible to get access to all Twig paths registered in - // twig.template_iterator definition - $this->addCompilerPassIfExists($container, TranslatorPass::class, PassConfig::TYPE_BEFORE_OPTIMIZATION, -32); - $this->addCompilerPassIfExists($container, TranslatorPathsPass::class, PassConfig::TYPE_AFTER_REMOVING); - $container->addCompilerPass(new LoggingTranslatorPass()); - $container->addCompilerPass(new AddExpressionLanguageProvidersPass(false)); - $this->addCompilerPassIfExists($container, TranslationExtractorPass::class); - $this->addCompilerPassIfExists($container, TranslationDumperPass::class); - $container->addCompilerPass(new FragmentRendererPass()); - $this->addCompilerPassIfExists($container, SerializerPass::class); - $this->addCompilerPassIfExists($container, PropertyInfoPass::class); - $container->addCompilerPass(new ControllerArgumentValueResolverPass()); - $container->addCompilerPass(new CachePoolPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 32); - $container->addCompilerPass(new CachePoolClearerPass(), PassConfig::TYPE_AFTER_REMOVING); - $container->addCompilerPass(new CachePoolPrunerPass(), PassConfig::TYPE_AFTER_REMOVING); - $this->addCompilerPassIfExists($container, FormPass::class); - $container->addCompilerPass(new WorkflowGuardListenerPass()); - $container->addCompilerPass(new ResettableServicePass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32); - $container->addCompilerPass(new RegisterLocaleAwareServicesPass()); - $container->addCompilerPass(new TestServiceContainerWeakRefPass(), PassConfig::TYPE_BEFORE_REMOVING, -32); - $container->addCompilerPass(new TestServiceContainerRealRefPass(), PassConfig::TYPE_AFTER_REMOVING); - $this->addCompilerPassIfExists($container, AddMimeTypeGuesserPass::class); - $this->addCompilerPassIfExists($container, MessengerPass::class); - $this->addCompilerPassIfExists($container, HttpClientPass::class); - $this->addCompilerPassIfExists($container, AddAutoMappingConfigurationPass::class); - $container->addCompilerPass(new RegisterReverseContainerPass(true)); - $container->addCompilerPass(new RegisterReverseContainerPass(false), PassConfig::TYPE_AFTER_REMOVING); - $container->addCompilerPass(new RemoveUnusedSessionMarshallingHandlerPass()); - $container->addCompilerPass(new SessionPass()); - - if ($container->getParameter('kernel.debug')) { - $container->addCompilerPass(new AddDebugLogProcessorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 2); - $container->addCompilerPass(new UnusedTagsPass(), PassConfig::TYPE_AFTER_REMOVING); - $container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_BEFORE_REMOVING, -255); - $container->addCompilerPass(new CacheCollectorPass(), PassConfig::TYPE_BEFORE_REMOVING); - } - } - - private function addCompilerPassIfExists(ContainerBuilder $container, string $class, string $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, int $priority = 0) - { - $container->addResource(new ClassExistenceResource($class)); - - if (class_exists($class)) { - $container->addCompilerPass(new $class(), $type, $priority); - } - } -} diff --git a/lib/symfony/framework-bundle/HttpCache/HttpCache.php b/lib/symfony/framework-bundle/HttpCache/HttpCache.php deleted file mode 100644 index fe38c4adc..000000000 --- a/lib/symfony/framework-bundle/HttpCache/HttpCache.php +++ /dev/null @@ -1,101 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\HttpCache; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\HttpCache\Esi; -use Symfony\Component\HttpKernel\HttpCache\HttpCache as BaseHttpCache; -use Symfony\Component\HttpKernel\HttpCache\Store; -use Symfony\Component\HttpKernel\HttpCache\StoreInterface; -use Symfony\Component\HttpKernel\HttpCache\SurrogateInterface; -use Symfony\Component\HttpKernel\KernelInterface; - -/** - * Manages HTTP cache objects in a Container. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class HttpCache extends BaseHttpCache -{ - protected $cacheDir; - protected $kernel; - - private $store; - private $surrogate; - private $options; - - /** - * @param string|StoreInterface $cache The cache directory (default used if null) or the storage instance - */ - public function __construct(KernelInterface $kernel, $cache = null, SurrogateInterface $surrogate = null, array $options = null) - { - $this->kernel = $kernel; - $this->surrogate = $surrogate; - $this->options = $options ?? []; - - if ($cache instanceof StoreInterface) { - $this->store = $cache; - } elseif (null !== $cache && !\is_string($cache)) { - throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be a string or a SurrogateInterface, "%s" given.', __METHOD__, get_debug_type($cache))); - } else { - $this->cacheDir = $cache; - } - - if (null === $options && $kernel->isDebug()) { - $this->options = ['debug' => true]; - } - - if ($this->options['debug'] ?? false) { - $this->options += ['stale_if_error' => 0]; - } - - parent::__construct($kernel, $this->createStore(), $this->createSurrogate(), array_merge($this->options, $this->getOptions())); - } - - /** - * {@inheritdoc} - */ - protected function forward(Request $request, bool $catch = false, Response $entry = null) - { - $this->getKernel()->boot(); - $this->getKernel()->getContainer()->set('cache', $this); - - return parent::forward($request, $catch, $entry); - } - - /** - * Returns an array of options to customize the Cache configuration. - * - * @return array - */ - protected function getOptions() - { - return []; - } - - /** - * @return SurrogateInterface - */ - protected function createSurrogate() - { - return $this->surrogate ?? new Esi(); - } - - /** - * @return StoreInterface - */ - protected function createStore() - { - return $this->store ?? new Store($this->cacheDir ?: $this->kernel->getCacheDir().'/http_cache'); - } -} diff --git a/lib/symfony/framework-bundle/Kernel/MicroKernelTrait.php b/lib/symfony/framework-bundle/Kernel/MicroKernelTrait.php deleted file mode 100644 index c25f90d63..000000000 --- a/lib/symfony/framework-bundle/Kernel/MicroKernelTrait.php +++ /dev/null @@ -1,234 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Kernel; - -use Symfony\Component\Config\Loader\LoaderInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Loader\Configurator\AbstractConfigurator; -use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; -use Symfony\Component\DependencyInjection\Loader\PhpFileLoader as ContainerPhpFileLoader; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; -use Symfony\Component\Routing\Loader\PhpFileLoader as RoutingPhpFileLoader; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\RouteCollectionBuilder; - -/** - * A Kernel that provides configuration hooks. - * - * @author Ryan Weaver <ryan@knpuniversity.com> - * @author Fabien Potencier <fabien@symfony.com> - */ -trait MicroKernelTrait -{ - /** - * Configures the container. - * - * You can register extensions: - * - * $container->extension('framework', [ - * 'secret' => '%secret%' - * ]); - * - * Or services: - * - * $container->services()->set('halloween', 'FooBundle\HalloweenProvider'); - * - * Or parameters: - * - * $container->parameters()->set('halloween', 'lot of fun'); - */ - private function configureContainer(ContainerConfigurator $container, LoaderInterface $loader, ContainerBuilder $builder): void - { - $configDir = $this->getConfigDir(); - - $container->import($configDir.'/{packages}/*.yaml'); - $container->import($configDir.'/{packages}/'.$this->environment.'/*.yaml'); - - if (is_file($configDir.'/services.yaml')) { - $container->import($configDir.'/services.yaml'); - $container->import($configDir.'/{services}_'.$this->environment.'.yaml'); - } else { - $container->import($configDir.'/{services}.php'); - } - } - - /** - * Adds or imports routes into your application. - * - * $routes->import($this->getConfigDir().'/*.{yaml,php}'); - * $routes - * ->add('admin_dashboard', '/admin') - * ->controller('App\Controller\AdminController::dashboard') - * ; - */ - private function configureRoutes(RoutingConfigurator $routes): void - { - $configDir = $this->getConfigDir(); - - $routes->import($configDir.'/{routes}/'.$this->environment.'/*.yaml'); - $routes->import($configDir.'/{routes}/*.yaml'); - - if (is_file($configDir.'/routes.yaml')) { - $routes->import($configDir.'/routes.yaml'); - } else { - $routes->import($configDir.'/{routes}.php'); - } - } - - /** - * Gets the path to the configuration directory. - */ - private function getConfigDir(): string - { - return $this->getProjectDir().'/config'; - } - - /** - * Gets the path to the bundles configuration file. - */ - private function getBundlesPath(): string - { - return $this->getConfigDir().'/bundles.php'; - } - - /** - * {@inheritdoc} - */ - public function getCacheDir(): string - { - if (isset($_SERVER['APP_CACHE_DIR'])) { - return $_SERVER['APP_CACHE_DIR'].'/'.$this->environment; - } - - return parent::getCacheDir(); - } - - /** - * {@inheritdoc} - */ - public function getLogDir(): string - { - return $_SERVER['APP_LOG_DIR'] ?? parent::getLogDir(); - } - - /** - * {@inheritdoc} - */ - public function registerBundles(): iterable - { - $contents = require $this->getBundlesPath(); - foreach ($contents as $class => $envs) { - if ($envs[$this->environment] ?? $envs['all'] ?? false) { - yield new $class(); - } - } - } - - /** - * {@inheritdoc} - */ - public function registerContainerConfiguration(LoaderInterface $loader) - { - $loader->load(function (ContainerBuilder $container) use ($loader) { - $container->loadFromExtension('framework', [ - 'router' => [ - 'resource' => 'kernel::loadRoutes', - 'type' => 'service', - ], - ]); - - $kernelClass = false !== strpos(static::class, "@anonymous\0") ? parent::class : static::class; - - if (!$container->hasDefinition('kernel')) { - $container->register('kernel', $kernelClass) - ->addTag('controller.service_arguments') - ->setAutoconfigured(true) - ->setSynthetic(true) - ->setPublic(true) - ; - } - - $kernelDefinition = $container->getDefinition('kernel'); - $kernelDefinition->addTag('routing.route_loader'); - - $container->addObjectResource($this); - $container->fileExists($this->getBundlesPath()); - - $configureContainer = new \ReflectionMethod($this, 'configureContainer'); - $configuratorClass = $configureContainer->getNumberOfParameters() > 0 && ($type = $configureContainer->getParameters()[0]->getType()) instanceof \ReflectionNamedType && !$type->isBuiltin() ? $type->getName() : null; - - if ($configuratorClass && !is_a(ContainerConfigurator::class, $configuratorClass, true)) { - $configureContainer->getClosure($this)($container, $loader); - - return; - } - - $file = (new \ReflectionObject($this))->getFileName(); - /* @var ContainerPhpFileLoader $kernelLoader */ - $kernelLoader = $loader->getResolver()->resolve($file); - $kernelLoader->setCurrentDir(\dirname($file)); - $instanceof = &\Closure::bind(function &() { return $this->instanceof; }, $kernelLoader, $kernelLoader)(); - - $valuePreProcessor = AbstractConfigurator::$valuePreProcessor; - AbstractConfigurator::$valuePreProcessor = function ($value) { - return $this === $value ? new Reference('kernel') : $value; - }; - - try { - $configureContainer->getClosure($this)(new ContainerConfigurator($container, $kernelLoader, $instanceof, $file, $file, $this->getEnvironment()), $loader, $container); - } finally { - $instanceof = []; - $kernelLoader->registerAliasesForSinglyImplementedInterfaces(); - AbstractConfigurator::$valuePreProcessor = $valuePreProcessor; - } - - $container->setAlias($kernelClass, 'kernel')->setPublic(true); - }); - } - - /** - * @internal - */ - public function loadRoutes(LoaderInterface $loader): RouteCollection - { - $file = (new \ReflectionObject($this))->getFileName(); - /* @var RoutingPhpFileLoader $kernelLoader */ - $kernelLoader = $loader->getResolver()->resolve($file, 'php'); - $kernelLoader->setCurrentDir(\dirname($file)); - $collection = new RouteCollection(); - - $configureRoutes = new \ReflectionMethod($this, 'configureRoutes'); - $configuratorClass = $configureRoutes->getNumberOfParameters() > 0 && ($type = $configureRoutes->getParameters()[0]->getType()) instanceof \ReflectionNamedType && !$type->isBuiltin() ? $type->getName() : null; - - if ($configuratorClass && !is_a(RoutingConfigurator::class, $configuratorClass, true)) { - trigger_deprecation('symfony/framework-bundle', '5.1', 'Using type "%s" for argument 1 of method "%s:configureRoutes()" is deprecated, use "%s" instead.', RouteCollectionBuilder::class, self::class, RoutingConfigurator::class); - - $routes = new RouteCollectionBuilder($loader); - $this->configureRoutes($routes); - - return $routes->build(); - } - - $configureRoutes->getClosure($this)(new RoutingConfigurator($collection, $kernelLoader, $file, $file, $this->getEnvironment())); - - foreach ($collection as $route) { - $controller = $route->getDefault('_controller'); - - if (\is_array($controller) && [0, 1] === array_keys($controller) && $this === $controller[0]) { - $route->setDefault('_controller', ['kernel', $controller[1]]); - } - } - - return $collection; - } -} diff --git a/lib/symfony/framework-bundle/KernelBrowser.php b/lib/symfony/framework-bundle/KernelBrowser.php deleted file mode 100644 index a02853012..000000000 --- a/lib/symfony/framework-bundle/KernelBrowser.php +++ /dev/null @@ -1,262 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle; - -use Symfony\Bundle\FrameworkBundle\Test\TestBrowserToken; -use Symfony\Component\BrowserKit\Cookie; -use Symfony\Component\BrowserKit\CookieJar; -use Symfony\Component\BrowserKit\History; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\HttpKernelBrowser; -use Symfony\Component\HttpKernel\KernelInterface; -use Symfony\Component\HttpKernel\Profiler\Profile as HttpProfile; -use Symfony\Component\Security\Core\User\UserInterface; - -/** - * Simulates a browser and makes requests to a Kernel object. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class KernelBrowser extends HttpKernelBrowser -{ - private $hasPerformedRequest = false; - private $profiler = false; - private $reboot = true; - - /** - * {@inheritdoc} - */ - public function __construct(KernelInterface $kernel, array $server = [], History $history = null, CookieJar $cookieJar = null) - { - parent::__construct($kernel, $server, $history, $cookieJar); - } - - /** - * Returns the container. - * - * @return ContainerInterface - */ - public function getContainer() - { - $container = $this->kernel->getContainer(); - - return $container->has('test.service_container') ? $container->get('test.service_container') : $container; - } - - /** - * Returns the kernel. - * - * @return KernelInterface - */ - public function getKernel() - { - return $this->kernel; - } - - /** - * Gets the profile associated with the current Response. - * - * @return HttpProfile|false|null - */ - public function getProfile() - { - if (null === $this->response || !$this->getContainer()->has('profiler')) { - return false; - } - - return $this->getContainer()->get('profiler')->loadProfileFromResponse($this->response); - } - - /** - * Enables the profiler for the very next request. - * - * If the profiler is not enabled, the call to this method does nothing. - */ - public function enableProfiler() - { - if ($this->getContainer()->has('profiler')) { - $this->profiler = true; - } - } - - /** - * Disables kernel reboot between requests. - * - * By default, the Client reboots the Kernel for each request. This method - * allows to keep the same kernel across requests. - */ - public function disableReboot() - { - $this->reboot = false; - } - - /** - * Enables kernel reboot between requests. - */ - public function enableReboot() - { - $this->reboot = true; - } - - /** - * @param UserInterface $user - * - * @return $this - */ - public function loginUser(object $user, string $firewallContext = 'main'): self - { - if (!interface_exists(UserInterface::class)) { - throw new \LogicException(sprintf('"%s" requires symfony/security-core to be installed.', __METHOD__)); - } - - if (!$user instanceof UserInterface) { - throw new \LogicException(sprintf('The first argument of "%s" must be instance of "%s", "%s" provided.', __METHOD__, UserInterface::class, \is_object($user) ? \get_class($user) : \gettype($user))); - } - - $token = new TestBrowserToken($user->getRoles(), $user, $firewallContext); - // @deprecated since Symfony 5.4 - if (method_exists($token, 'setAuthenticated')) { - $token->setAuthenticated(true, false); - } - - $container = $this->getContainer(); - $container->get('security.untracked_token_storage')->setToken($token); - - if ($container->has('session.factory')) { - $session = $container->get('session.factory')->createSession(); - } elseif ($container->has('session')) { - $session = $container->get('session'); - } else { - return $this; - } - - $session->set('_security_'.$firewallContext, serialize($token)); - $session->save(); - - $domains = array_unique(array_map(function (Cookie $cookie) use ($session) { - return $cookie->getName() === $session->getName() ? $cookie->getDomain() : ''; - }, $this->getCookieJar()->all())) ?: ['']; - foreach ($domains as $domain) { - $cookie = new Cookie($session->getName(), $session->getId(), null, null, $domain); - $this->getCookieJar()->set($cookie); - } - - return $this; - } - - /** - * {@inheritdoc} - * - * @param Request $request - * - * @return Response - */ - protected function doRequest(object $request) - { - // avoid shutting down the Kernel if no request has been performed yet - // WebTestCase::createClient() boots the Kernel but do not handle a request - if ($this->hasPerformedRequest && $this->reboot) { - $this->kernel->boot(); - $this->kernel->shutdown(); - } else { - $this->hasPerformedRequest = true; - } - - if ($this->profiler) { - $this->profiler = false; - - $this->kernel->boot(); - $this->getContainer()->get('profiler')->enable(); - } - - return parent::doRequest($request); - } - - /** - * {@inheritdoc} - * - * @param Request $request - * - * @return Response - */ - protected function doRequestInProcess(object $request) - { - $response = parent::doRequestInProcess($request); - - $this->profiler = false; - - return $response; - } - - /** - * Returns the script to execute when the request must be insulated. - * - * It assumes that the autoloader is named 'autoload.php' and that it is - * stored in the same directory as the kernel (this is the case for the - * Symfony Standard Edition). If this is not your case, create your own - * client and override this method. - * - * @param Request $request - * - * @return string - */ - protected function getScript(object $request) - { - $kernel = var_export(serialize($this->kernel), true); - $request = var_export(serialize($request), true); - $errorReporting = error_reporting(); - - $requires = ''; - foreach (get_declared_classes() as $class) { - if (str_starts_with($class, 'ComposerAutoloaderInit')) { - $r = new \ReflectionClass($class); - $file = \dirname($r->getFileName(), 2).'/autoload.php'; - if (is_file($file)) { - $requires .= 'require_once '.var_export($file, true).";\n"; - } - } - } - - if (!$requires) { - throw new \RuntimeException('Composer autoloader not found.'); - } - - $requires .= 'require_once '.var_export((new \ReflectionObject($this->kernel))->getFileName(), true).";\n"; - - $profilerCode = ''; - if ($this->profiler) { - $profilerCode = <<<'EOF' -$container = $kernel->getContainer(); -$container = $container->has('test.service_container') ? $container->get('test.service_container') : $container; -$container->get('profiler')->enable(); -EOF; - } - - $code = <<<EOF -<?php - -error_reporting($errorReporting); - -$requires - -\$kernel = unserialize($kernel); -\$kernel->boot(); -$profilerCode - -\$request = unserialize($request); -EOF; - - return $code.$this->getHandleScript(); - } -} diff --git a/lib/symfony/framework-bundle/LICENSE b/lib/symfony/framework-bundle/LICENSE deleted file mode 100644 index 008370457..000000000 --- a/lib/symfony/framework-bundle/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -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/lib/symfony/framework-bundle/README.md b/lib/symfony/framework-bundle/README.md deleted file mode 100644 index 76c7700fa..000000000 --- a/lib/symfony/framework-bundle/README.md +++ /dev/null @@ -1,13 +0,0 @@ -FrameworkBundle -=============== - -FrameworkBundle provides a tight integration between Symfony components and the -Symfony full-stack framework. - -Resources ---------- - - * [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/lib/symfony/framework-bundle/Resources/bin/check-unused-known-tags.php b/lib/symfony/framework-bundle/Resources/bin/check-unused-known-tags.php deleted file mode 100644 index 55658f5b1..000000000 --- a/lib/symfony/framework-bundle/Resources/bin/check-unused-known-tags.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -if ('cli' !== \PHP_SAPI) { - throw new Exception('This script must be run from the command line.'); -} - -require dirname(__DIR__, 6).'/vendor/autoload.php'; - -use Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\UnusedTagsPassUtils; - -$target = dirname(__DIR__, 2).'/DependencyInjection/Compiler/UnusedTagsPass.php'; -$contents = file_get_contents($target); -$contents = preg_replace('{private const KNOWN_TAGS = \[(.+?)\];}sm', "private const KNOWN_TAGS = [\n '".implode("',\n '", UnusedTagsPassUtils::getDefinedTags())."',\n ];", $contents); -file_put_contents($target, $contents); diff --git a/lib/symfony/framework-bundle/Resources/config/annotations.php b/lib/symfony/framework-bundle/Resources/config/annotations.php deleted file mode 100644 index 33a2f4698..000000000 --- a/lib/symfony/framework-bundle/Resources/config/annotations.php +++ /dev/null @@ -1,83 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Doctrine\Common\Annotations\AnnotationReader; -use Doctrine\Common\Annotations\AnnotationRegistry; -use Doctrine\Common\Annotations\PsrCachedReader; -use Doctrine\Common\Annotations\Reader; -use Doctrine\Common\Cache\Psr6\DoctrineProvider; -use Symfony\Bundle\FrameworkBundle\CacheWarmer\AnnotationsCacheWarmer; -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\FilesystemAdapter; -use Symfony\Component\Cache\Adapter\PhpArrayAdapter; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('annotations.reader', AnnotationReader::class) - ->call('addGlobalIgnoredName', [ - 'required', - service('annotations.dummy_registry')->nullOnInvalid(), // dummy arg to register class_exists as annotation loader only when required - ]) - - ->set('annotations.dummy_registry', AnnotationRegistry::class) - ->call('registerUniqueLoader', ['class_exists']) - - ->set('annotations.cached_reader', PsrCachedReader::class) - ->args([ - service('annotations.reader'), - inline_service(ArrayAdapter::class), - abstract_arg('Debug-Flag'), - ]) - ->tag('annotations.cached_reader') - ->tag('container.do_not_inline') - - ->set('annotations.filesystem_cache_adapter', FilesystemAdapter::class) - ->args([ - '', - 0, - abstract_arg('Cache-Directory'), - ]) - - ->set('annotations.filesystem_cache', DoctrineProvider::class) - ->factory([DoctrineProvider::class, 'wrap']) - ->args([ - service('annotations.filesystem_cache_adapter'), - ]) - ->deprecate('symfony/framework-bundle', '5.4', '"%service_id% is deprecated"') - - ->set('annotations.cache_warmer', AnnotationsCacheWarmer::class) - ->args([ - service('annotations.reader'), - param('kernel.cache_dir').'/annotations.php', - '#^Symfony\\\\(?:Component\\\\HttpKernel\\\\|Bundle\\\\FrameworkBundle\\\\Controller\\\\(?!.*Controller$))#', - param('kernel.debug'), - ]) - - ->set('annotations.cache_adapter', PhpArrayAdapter::class) - ->factory([PhpArrayAdapter::class, 'create']) - ->args([ - param('kernel.cache_dir').'/annotations.php', - service('cache.annotations'), - ]) - ->tag('container.hot_path') - - ->set('annotations.cache', DoctrineProvider::class) - ->factory([DoctrineProvider::class, 'wrap']) - ->args([ - service('annotations.cache_adapter'), - ]) - ->deprecate('symfony/framework-bundle', '5.4', '"%service_id% is deprecated"') - - ->alias('annotation_reader', 'annotations.reader') - ->alias(Reader::class, 'annotation_reader'); -}; diff --git a/lib/symfony/framework-bundle/Resources/config/assets.php b/lib/symfony/framework-bundle/Resources/config/assets.php deleted file mode 100644 index 1e250aab4..000000000 --- a/lib/symfony/framework-bundle/Resources/config/assets.php +++ /dev/null @@ -1,94 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\Asset\Context\RequestStackContext; -use Symfony\Component\Asset\Package; -use Symfony\Component\Asset\Packages; -use Symfony\Component\Asset\PathPackage; -use Symfony\Component\Asset\UrlPackage; -use Symfony\Component\Asset\VersionStrategy\EmptyVersionStrategy; -use Symfony\Component\Asset\VersionStrategy\JsonManifestVersionStrategy; -use Symfony\Component\Asset\VersionStrategy\RemoteJsonManifestVersionStrategy; -use Symfony\Component\Asset\VersionStrategy\StaticVersionStrategy; - -return static function (ContainerConfigurator $container) { - $container->parameters() - ->set('asset.request_context.base_path', null) - ->set('asset.request_context.secure', null) - ; - - $container->services() - ->set('assets.packages', Packages::class) - ->args([ - service('assets._default_package'), - tagged_iterator('assets.package', 'package'), - ]) - - ->alias(Packages::class, 'assets.packages') - - ->set('assets.empty_package', Package::class) - ->args([ - service('assets.empty_version_strategy'), - ]) - - ->alias('assets._default_package', 'assets.empty_package') - - ->set('assets.context', RequestStackContext::class) - ->args([ - service('request_stack'), - param('asset.request_context.base_path'), - param('asset.request_context.secure'), - ]) - - ->set('assets.path_package', PathPackage::class) - ->abstract() - ->args([ - abstract_arg('base path'), - abstract_arg('version strategy'), - service('assets.context'), - ]) - - ->set('assets.url_package', UrlPackage::class) - ->abstract() - ->args([ - abstract_arg('base URLs'), - abstract_arg('version strategy'), - service('assets.context'), - ]) - - ->set('assets.static_version_strategy', StaticVersionStrategy::class) - ->abstract() - ->args([ - abstract_arg('version'), - abstract_arg('format'), - ]) - - ->set('assets.empty_version_strategy', EmptyVersionStrategy::class) - - ->set('assets.json_manifest_version_strategy', JsonManifestVersionStrategy::class) - ->abstract() - ->args([ - abstract_arg('manifest path'), - service('http_client')->nullOnInvalid(), - false, - ]) - - ->set('assets.remote_json_manifest_version_strategy', RemoteJsonManifestVersionStrategy::class) - ->abstract() - ->deprecate('symfony/framework-bundle', '5.3', 'The "%service_id%" service is deprecated, use "assets.json_manifest_version_strategy" instead.') - ->args([ - abstract_arg('manifest url'), - service('http_client'), - ]) - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/cache.php b/lib/symfony/framework-bundle/Resources/config/cache.php deleted file mode 100644 index e333e5f54..000000000 --- a/lib/symfony/framework-bundle/Resources/config/cache.php +++ /dev/null @@ -1,267 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Cache\Adapter\AbstractAdapter; -use Symfony\Component\Cache\Adapter\AdapterInterface; -use Symfony\Component\Cache\Adapter\ApcuAdapter; -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\DoctrineAdapter; -use Symfony\Component\Cache\Adapter\DoctrineDbalAdapter; -use Symfony\Component\Cache\Adapter\FilesystemAdapter; -use Symfony\Component\Cache\Adapter\MemcachedAdapter; -use Symfony\Component\Cache\Adapter\PdoAdapter; -use Symfony\Component\Cache\Adapter\ProxyAdapter; -use Symfony\Component\Cache\Adapter\RedisAdapter; -use Symfony\Component\Cache\Adapter\RedisTagAwareAdapter; -use Symfony\Component\Cache\Adapter\TagAwareAdapter; -use Symfony\Component\Cache\Marshaller\DefaultMarshaller; -use Symfony\Component\Cache\Messenger\EarlyExpirationHandler; -use Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer; -use Symfony\Contracts\Cache\CacheInterface; -use Symfony\Contracts\Cache\TagAwareCacheInterface; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('cache.app') - ->parent('cache.adapter.filesystem') - ->public() - ->tag('cache.pool', ['clearer' => 'cache.app_clearer']) - - ->set('cache.app.taggable', TagAwareAdapter::class) - ->args([service('cache.app')]) - - ->set('cache.system') - ->parent('cache.adapter.system') - ->public() - ->tag('cache.pool') - - ->set('cache.validator') - ->parent('cache.system') - ->private() - ->tag('cache.pool') - - ->set('cache.serializer') - ->parent('cache.system') - ->private() - ->tag('cache.pool') - - ->set('cache.annotations') - ->parent('cache.system') - ->private() - ->tag('cache.pool') - - ->set('cache.property_info') - ->parent('cache.system') - ->private() - ->tag('cache.pool') - - ->set('cache.messenger.restart_workers_signal') - ->parent('cache.app') - ->private() - ->tag('cache.pool') - - ->set('cache.adapter.system', AdapterInterface::class) - ->abstract() - ->factory([AbstractAdapter::class, 'createSystemCache']) - ->args([ - '', // namespace - 0, // default lifetime - abstract_arg('version'), - sprintf('%s/pools/system', param('kernel.cache_dir')), - service('logger')->ignoreOnInvalid(), - ]) - ->tag('cache.pool', ['clearer' => 'cache.system_clearer', 'reset' => 'reset']) - ->tag('monolog.logger', ['channel' => 'cache']) - - ->set('cache.adapter.apcu', ApcuAdapter::class) - ->abstract() - ->args([ - '', // namespace - 0, // default lifetime - abstract_arg('version'), - ]) - ->call('setLogger', [service('logger')->ignoreOnInvalid()]) - ->tag('cache.pool', ['clearer' => 'cache.default_clearer', 'reset' => 'reset']) - ->tag('monolog.logger', ['channel' => 'cache']) - - ->set('cache.adapter.doctrine', DoctrineAdapter::class) - ->abstract() - ->args([ - abstract_arg('Doctrine provider service'), - '', // namespace - 0, // default lifetime - ]) - ->call('setLogger', [service('logger')->ignoreOnInvalid()]) - ->tag('cache.pool', [ - 'provider' => 'cache.default_doctrine_provider', - 'clearer' => 'cache.default_clearer', - 'reset' => 'reset', - ]) - ->tag('monolog.logger', ['channel' => 'cache']) - ->deprecate('symfony/framework-bundle', '5.4', 'The "%service_id%" service inherits from "cache.adapter.doctrine" which is deprecated.') - - ->set('cache.adapter.filesystem', FilesystemAdapter::class) - ->abstract() - ->args([ - '', // namespace - 0, // default lifetime - sprintf('%s/pools/app', param('kernel.cache_dir')), - service('cache.default_marshaller')->ignoreOnInvalid(), - ]) - ->call('setLogger', [service('logger')->ignoreOnInvalid()]) - ->tag('cache.pool', ['clearer' => 'cache.default_clearer', 'reset' => 'reset']) - ->tag('monolog.logger', ['channel' => 'cache']) - - ->set('cache.adapter.psr6', ProxyAdapter::class) - ->abstract() - ->args([ - abstract_arg('PSR-6 provider service'), - '', // namespace - 0, // default lifetime - ]) - ->tag('cache.pool', [ - 'provider' => 'cache.default_psr6_provider', - 'clearer' => 'cache.default_clearer', - 'reset' => 'reset', - ]) - - ->set('cache.adapter.redis', RedisAdapter::class) - ->abstract() - ->args([ - abstract_arg('Redis connection service'), - '', // namespace - 0, // default lifetime - service('cache.default_marshaller')->ignoreOnInvalid(), - ]) - ->call('setLogger', [service('logger')->ignoreOnInvalid()]) - ->tag('cache.pool', [ - 'provider' => 'cache.default_redis_provider', - 'clearer' => 'cache.default_clearer', - 'reset' => 'reset', - ]) - ->tag('monolog.logger', ['channel' => 'cache']) - - ->set('cache.adapter.redis_tag_aware', RedisTagAwareAdapter::class) - ->abstract() - ->args([ - abstract_arg('Redis connection service'), - '', // namespace - 0, // default lifetime - service('cache.default_marshaller')->ignoreOnInvalid(), - ]) - ->call('setLogger', [service('logger')->ignoreOnInvalid()]) - ->tag('cache.pool', [ - 'provider' => 'cache.default_redis_provider', - 'clearer' => 'cache.default_clearer', - 'reset' => 'reset', - ]) - ->tag('monolog.logger', ['channel' => 'cache']) - - ->set('cache.adapter.memcached', MemcachedAdapter::class) - ->abstract() - ->args([ - abstract_arg('Memcached connection service'), - '', // namespace - 0, // default lifetime - service('cache.default_marshaller')->ignoreOnInvalid(), - ]) - ->call('setLogger', [service('logger')->ignoreOnInvalid()]) - ->tag('cache.pool', [ - 'provider' => 'cache.default_memcached_provider', - 'clearer' => 'cache.default_clearer', - 'reset' => 'reset', - ]) - ->tag('monolog.logger', ['channel' => 'cache']) - - ->set('cache.adapter.doctrine_dbal', DoctrineDbalAdapter::class) - ->abstract() - ->args([ - abstract_arg('DBAL connection service'), - '', // namespace - 0, // default lifetime - [], // table options - service('cache.default_marshaller')->ignoreOnInvalid(), - ]) - ->call('setLogger', [service('logger')->ignoreOnInvalid()]) - ->tag('cache.pool', [ - 'provider' => 'cache.default_doctrine_dbal_provider', - 'clearer' => 'cache.default_clearer', - 'reset' => 'reset', - ]) - ->tag('monolog.logger', ['channel' => 'cache']) - - ->set('cache.adapter.pdo', PdoAdapter::class) - ->abstract() - ->args([ - abstract_arg('PDO connection service'), - '', // namespace - 0, // default lifetime - [], // table options - service('cache.default_marshaller')->ignoreOnInvalid(), - ]) - ->call('setLogger', [service('logger')->ignoreOnInvalid()]) - ->tag('cache.pool', [ - 'provider' => 'cache.default_pdo_provider', - 'clearer' => 'cache.default_clearer', - 'reset' => 'reset', - ]) - ->tag('monolog.logger', ['channel' => 'cache']) - - ->set('cache.adapter.array', ArrayAdapter::class) - ->abstract() - ->args([ - 0, // default lifetime - ]) - ->call('setLogger', [service('logger')->ignoreOnInvalid()]) - ->tag('cache.pool', ['clearer' => 'cache.default_clearer', 'reset' => 'reset']) - ->tag('monolog.logger', ['channel' => 'cache']) - - ->set('cache.default_marshaller', DefaultMarshaller::class) - ->args([ - null, // use igbinary_serialize() when available - '%kernel.debug%', - ]) - - ->set('cache.early_expiration_handler', EarlyExpirationHandler::class) - ->args([ - service('reverse_container'), - ]) - ->tag('messenger.message_handler') - - ->set('cache.default_clearer', Psr6CacheClearer::class) - ->args([ - [], - ]) - - ->set('cache.system_clearer') - ->parent('cache.default_clearer') - ->public() - - ->set('cache.global_clearer') - ->parent('cache.default_clearer') - ->public() - - ->alias('cache.app_clearer', 'cache.default_clearer') - ->public() - - ->alias(CacheItemPoolInterface::class, 'cache.app') - - ->alias(AdapterInterface::class, 'cache.app') - ->deprecate('symfony/framework-bundle', '5.4', sprintf('The "%%alias_id%%" alias is deprecated, use "%s" instead.', CacheItemPoolInterface::class)) - - ->alias(CacheInterface::class, 'cache.app') - - ->alias(TagAwareCacheInterface::class, 'cache.app.taggable') - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/cache_debug.php b/lib/symfony/framework-bundle/Resources/config/cache_debug.php deleted file mode 100644 index 8f29d9f1d..000000000 --- a/lib/symfony/framework-bundle/Resources/config/cache_debug.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Bundle\FrameworkBundle\CacheWarmer\CachePoolClearerCacheWarmer; -use Symfony\Component\Cache\DataCollector\CacheDataCollector; - -return static function (ContainerConfigurator $container) { - $container->services() - // DataCollector (public to prevent inlining, made private in CacheCollectorPass) - ->set('data_collector.cache', CacheDataCollector::class) - ->public() - ->tag('data_collector', [ - 'template' => '@WebProfiler/Collector/cache.html.twig', - 'id' => 'cache', - 'priority' => 275, - ]) - - // CacheWarmer used in dev to clear cache pool - ->set('cache_pool_clearer.cache_warmer', CachePoolClearerCacheWarmer::class) - ->args([ - service('cache.system_clearer'), - [ - 'cache.validator', - 'cache.serializer', - ], - ]) - ->tag('kernel.cache_warmer', ['priority' => 64]) - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/collectors.php b/lib/symfony/framework-bundle/Resources/config/collectors.php deleted file mode 100644 index abf9ded5e..000000000 --- a/lib/symfony/framework-bundle/Resources/config/collectors.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Bundle\FrameworkBundle\DataCollector\RouterDataCollector; -use Symfony\Component\HttpKernel\DataCollector\AjaxDataCollector; -use Symfony\Component\HttpKernel\DataCollector\ConfigDataCollector; -use Symfony\Component\HttpKernel\DataCollector\EventDataCollector; -use Symfony\Component\HttpKernel\DataCollector\ExceptionDataCollector; -use Symfony\Component\HttpKernel\DataCollector\LoggerDataCollector; -use Symfony\Component\HttpKernel\DataCollector\MemoryDataCollector; -use Symfony\Component\HttpKernel\DataCollector\RequestDataCollector; -use Symfony\Component\HttpKernel\DataCollector\TimeDataCollector; -use Symfony\Component\HttpKernel\KernelEvents; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('data_collector.config', ConfigDataCollector::class) - ->call('setKernel', [service('kernel')->ignoreOnInvalid()]) - ->tag('data_collector', ['template' => '@WebProfiler/Collector/config.html.twig', 'id' => 'config', 'priority' => -255]) - - ->set('data_collector.request', RequestDataCollector::class) - ->args([ - service('request_stack')->ignoreOnInvalid(), - ]) - ->tag('kernel.event_subscriber') - ->tag('data_collector', ['template' => '@WebProfiler/Collector/request.html.twig', 'id' => 'request', 'priority' => 335]) - - ->set('data_collector.request.session_collector', \Closure::class) - ->factory([\Closure::class, 'fromCallable']) - ->args([[service('data_collector.request'), 'collectSessionUsage']]) - - ->set('data_collector.ajax', AjaxDataCollector::class) - ->tag('data_collector', ['template' => '@WebProfiler/Collector/ajax.html.twig', 'id' => 'ajax', 'priority' => 315]) - - ->set('data_collector.exception', ExceptionDataCollector::class) - ->tag('data_collector', ['template' => '@WebProfiler/Collector/exception.html.twig', 'id' => 'exception', 'priority' => 305]) - - ->set('data_collector.events', EventDataCollector::class) - ->args([ - service('debug.event_dispatcher')->ignoreOnInvalid(), - service('request_stack')->ignoreOnInvalid(), - ]) - ->tag('data_collector', ['template' => '@WebProfiler/Collector/events.html.twig', 'id' => 'events', 'priority' => 290]) - - ->set('data_collector.logger', LoggerDataCollector::class) - ->args([ - service('logger')->ignoreOnInvalid(), - sprintf('%s/%s', param('kernel.build_dir'), param('kernel.container_class')), - service('request_stack')->ignoreOnInvalid(), - ]) - ->tag('monolog.logger', ['channel' => 'profiler']) - ->tag('data_collector', ['template' => '@WebProfiler/Collector/logger.html.twig', 'id' => 'logger', 'priority' => 300]) - - ->set('data_collector.time', TimeDataCollector::class) - ->args([ - service('kernel')->ignoreOnInvalid(), - service('debug.stopwatch')->ignoreOnInvalid(), - ]) - ->tag('data_collector', ['template' => '@WebProfiler/Collector/time.html.twig', 'id' => 'time', 'priority' => 330]) - - ->set('data_collector.memory', MemoryDataCollector::class) - ->tag('data_collector', ['template' => '@WebProfiler/Collector/memory.html.twig', 'id' => 'memory', 'priority' => 325]) - - ->set('data_collector.router', RouterDataCollector::class) - ->tag('kernel.event_listener', ['event' => KernelEvents::CONTROLLER, 'method' => 'onKernelController']) - ->tag('data_collector', ['template' => '@WebProfiler/Collector/router.html.twig', 'id' => 'router', 'priority' => 285]) - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/console.php b/lib/symfony/framework-bundle/Resources/config/console.php deleted file mode 100644 index 610a83add..000000000 --- a/lib/symfony/framework-bundle/Resources/config/console.php +++ /dev/null @@ -1,331 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Bundle\FrameworkBundle\Command\AboutCommand; -use Symfony\Bundle\FrameworkBundle\Command\AssetsInstallCommand; -use Symfony\Bundle\FrameworkBundle\Command\CacheClearCommand; -use Symfony\Bundle\FrameworkBundle\Command\CachePoolClearCommand; -use Symfony\Bundle\FrameworkBundle\Command\CachePoolDeleteCommand; -use Symfony\Bundle\FrameworkBundle\Command\CachePoolListCommand; -use Symfony\Bundle\FrameworkBundle\Command\CachePoolPruneCommand; -use Symfony\Bundle\FrameworkBundle\Command\CacheWarmupCommand; -use Symfony\Bundle\FrameworkBundle\Command\ConfigDebugCommand; -use Symfony\Bundle\FrameworkBundle\Command\ConfigDumpReferenceCommand; -use Symfony\Bundle\FrameworkBundle\Command\ContainerDebugCommand; -use Symfony\Bundle\FrameworkBundle\Command\ContainerLintCommand; -use Symfony\Bundle\FrameworkBundle\Command\DebugAutowiringCommand; -use Symfony\Bundle\FrameworkBundle\Command\EventDispatcherDebugCommand; -use Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand; -use Symfony\Bundle\FrameworkBundle\Command\RouterMatchCommand; -use Symfony\Bundle\FrameworkBundle\Command\SecretsDecryptToLocalCommand; -use Symfony\Bundle\FrameworkBundle\Command\SecretsEncryptFromLocalCommand; -use Symfony\Bundle\FrameworkBundle\Command\SecretsGenerateKeysCommand; -use Symfony\Bundle\FrameworkBundle\Command\SecretsListCommand; -use Symfony\Bundle\FrameworkBundle\Command\SecretsRemoveCommand; -use Symfony\Bundle\FrameworkBundle\Command\SecretsSetCommand; -use Symfony\Bundle\FrameworkBundle\Command\TranslationDebugCommand; -use Symfony\Bundle\FrameworkBundle\Command\TranslationUpdateCommand; -use Symfony\Bundle\FrameworkBundle\Command\WorkflowDumpCommand; -use Symfony\Bundle\FrameworkBundle\Command\YamlLintCommand; -use Symfony\Bundle\FrameworkBundle\EventListener\SuggestMissingPackageSubscriber; -use Symfony\Component\Console\EventListener\ErrorListener; -use Symfony\Component\Dotenv\Command\DebugCommand as DotenvDebugCommand; -use Symfony\Component\Messenger\Command\ConsumeMessagesCommand; -use Symfony\Component\Messenger\Command\DebugCommand; -use Symfony\Component\Messenger\Command\FailedMessagesRemoveCommand; -use Symfony\Component\Messenger\Command\FailedMessagesRetryCommand; -use Symfony\Component\Messenger\Command\FailedMessagesShowCommand; -use Symfony\Component\Messenger\Command\SetupTransportsCommand; -use Symfony\Component\Messenger\Command\StopWorkersCommand; -use Symfony\Component\Translation\Command\TranslationPullCommand; -use Symfony\Component\Translation\Command\TranslationPushCommand; -use Symfony\Component\Translation\Command\XliffLintCommand; -use Symfony\Component\Validator\Command\DebugCommand as ValidatorDebugCommand; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('console.error_listener', ErrorListener::class) - ->args([ - service('logger')->nullOnInvalid(), - ]) - ->tag('kernel.event_subscriber') - ->tag('monolog.logger', ['channel' => 'console']) - - ->set('console.suggest_missing_package_subscriber', SuggestMissingPackageSubscriber::class) - ->tag('kernel.event_subscriber') - - ->set('console.command.about', AboutCommand::class) - ->tag('console.command') - - ->set('console.command.assets_install', AssetsInstallCommand::class) - ->args([ - service('filesystem'), - param('kernel.project_dir'), - ]) - ->tag('console.command') - - ->set('console.command.cache_clear', CacheClearCommand::class) - ->args([ - service('cache_clearer'), - service('filesystem'), - ]) - ->tag('console.command') - - ->set('console.command.cache_pool_clear', CachePoolClearCommand::class) - ->args([ - service('cache.global_clearer'), - ]) - ->tag('console.command') - - ->set('console.command.cache_pool_prune', CachePoolPruneCommand::class) - ->args([ - [], - ]) - ->tag('console.command') - - ->set('console.command.cache_pool_delete', CachePoolDeleteCommand::class) - ->args([ - service('cache.global_clearer'), - ]) - ->tag('console.command') - - ->set('console.command.cache_pool_list', CachePoolListCommand::class) - ->args([ - null, - ]) - ->tag('console.command') - - ->set('console.command.cache_warmup', CacheWarmupCommand::class) - ->args([ - service('cache_warmer'), - ]) - ->tag('console.command') - - ->set('console.command.config_debug', ConfigDebugCommand::class) - ->tag('console.command') - - ->set('console.command.config_dump_reference', ConfigDumpReferenceCommand::class) - ->tag('console.command') - - ->set('console.command.container_debug', ContainerDebugCommand::class) - ->tag('console.command') - - ->set('console.command.container_lint', ContainerLintCommand::class) - ->tag('console.command') - - ->set('console.command.debug_autowiring', DebugAutowiringCommand::class) - ->args([ - null, - service('debug.file_link_formatter')->nullOnInvalid(), - ]) - ->tag('console.command') - - ->set('console.command.dotenv_debug', DotenvDebugCommand::class) - ->args([ - param('kernel.environment'), - param('kernel.project_dir'), - ]) - ->tag('console.command') - - ->set('console.command.event_dispatcher_debug', EventDispatcherDebugCommand::class) - ->args([ - tagged_locator('event_dispatcher.dispatcher', 'name'), - ]) - ->tag('console.command') - - ->set('console.command.messenger_consume_messages', ConsumeMessagesCommand::class) - ->args([ - abstract_arg('Routable message bus'), - service('messenger.receiver_locator'), - service('event_dispatcher'), - service('logger')->nullOnInvalid(), - [], // Receiver names - service('messenger.listener.reset_services')->nullOnInvalid(), - [], // Bus names - ]) - ->tag('console.command') - ->tag('monolog.logger', ['channel' => 'messenger']) - - ->set('console.command.messenger_setup_transports', SetupTransportsCommand::class) - ->args([ - service('messenger.receiver_locator'), - [], // Receiver names - ]) - ->tag('console.command') - - ->set('console.command.messenger_debug', DebugCommand::class) - ->args([ - [], // Message to handlers mapping - ]) - ->tag('console.command') - - ->set('console.command.messenger_stop_workers', StopWorkersCommand::class) - ->args([ - service('cache.messenger.restart_workers_signal'), - ]) - ->tag('console.command') - - ->set('console.command.messenger_failed_messages_retry', FailedMessagesRetryCommand::class) - ->args([ - abstract_arg('Default failure receiver name'), - abstract_arg('Receivers'), - service('messenger.routable_message_bus'), - service('event_dispatcher'), - service('logger'), - ]) - ->tag('console.command') - - ->set('console.command.messenger_failed_messages_show', FailedMessagesShowCommand::class) - ->args([ - abstract_arg('Default failure receiver name'), - abstract_arg('Receivers'), - ]) - ->tag('console.command') - - ->set('console.command.messenger_failed_messages_remove', FailedMessagesRemoveCommand::class) - ->args([ - abstract_arg('Default failure receiver name'), - abstract_arg('Receivers'), - ]) - ->tag('console.command') - - ->set('console.command.router_debug', RouterDebugCommand::class) - ->args([ - service('router'), - service('debug.file_link_formatter')->nullOnInvalid(), - ]) - ->tag('console.command') - - ->set('console.command.router_match', RouterMatchCommand::class) - ->args([ - service('router'), - tagged_iterator('routing.expression_language_provider'), - ]) - ->tag('console.command') - - ->set('console.command.translation_debug', TranslationDebugCommand::class) - ->args([ - service('translator'), - service('translation.reader'), - service('translation.extractor'), - param('translator.default_path'), - null, // twig.default_path - [], // Translator paths - [], // Twig paths - param('kernel.enabled_locales'), - ]) - ->tag('console.command') - - ->set('console.command.translation_extract', TranslationUpdateCommand::class) - ->args([ - service('translation.writer'), - service('translation.reader'), - service('translation.extractor'), - param('kernel.default_locale'), - param('translator.default_path'), - null, // twig.default_path - [], // Translator paths - [], // Twig paths - param('kernel.enabled_locales'), - ]) - ->tag('console.command') - - ->set('console.command.validator_debug', ValidatorDebugCommand::class) - ->args([ - service('validator'), - ]) - ->tag('console.command') - - ->set('console.command.translation_pull', TranslationPullCommand::class) - ->args([ - service('translation.provider_collection'), - service('translation.writer'), - service('translation.reader'), - param('kernel.default_locale'), - [], // Translator paths - [], // Enabled locales - ]) - ->tag('console.command', ['command' => 'translation:pull']) - - ->set('console.command.translation_push', TranslationPushCommand::class) - ->args([ - service('translation.provider_collection'), - service('translation.reader'), - [], // Translator paths - [], // Enabled locales - ]) - ->tag('console.command', ['command' => 'translation:push']) - - ->set('console.command.workflow_dump', WorkflowDumpCommand::class) - ->tag('console.command') - - ->set('console.command.xliff_lint', XliffLintCommand::class) - ->tag('console.command') - - ->set('console.command.yaml_lint', YamlLintCommand::class) - ->tag('console.command') - - ->set('console.command.form_debug', \Symfony\Component\Form\Command\DebugCommand::class) - ->args([ - service('form.registry'), - [], // All form types namespaces are stored here by FormPass - [], // All services form types are stored here by FormPass - [], // All type extensions are stored here by FormPass - [], // All type guessers are stored here by FormPass - service('debug.file_link_formatter')->nullOnInvalid(), - ]) - ->tag('console.command') - - ->set('console.command.secrets_set', SecretsSetCommand::class) - ->args([ - service('secrets.vault'), - service('secrets.local_vault')->nullOnInvalid(), - ]) - ->tag('console.command') - - ->set('console.command.secrets_remove', SecretsRemoveCommand::class) - ->args([ - service('secrets.vault'), - service('secrets.local_vault')->nullOnInvalid(), - ]) - ->tag('console.command') - - ->set('console.command.secrets_generate_key', SecretsGenerateKeysCommand::class) - ->args([ - service('secrets.vault'), - service('secrets.local_vault')->ignoreOnInvalid(), - ]) - ->tag('console.command') - - ->set('console.command.secrets_list', SecretsListCommand::class) - ->args([ - service('secrets.vault'), - service('secrets.local_vault')->ignoreOnInvalid(), - ]) - ->tag('console.command') - - ->set('console.command.secrets_decrypt_to_local', SecretsDecryptToLocalCommand::class) - ->args([ - service('secrets.vault'), - service('secrets.local_vault')->ignoreOnInvalid(), - ]) - ->tag('console.command') - - ->set('console.command.secrets_encrypt_from_local', SecretsEncryptFromLocalCommand::class) - ->args([ - service('secrets.vault'), - service('secrets.local_vault')->ignoreOnInvalid(), - ]) - ->tag('console.command') - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/debug.php b/lib/symfony/framework-bundle/Resources/config/debug.php deleted file mode 100644 index cfaad8c1d..000000000 --- a/lib/symfony/framework-bundle/Resources/config/debug.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\HttpKernel\Controller\ArgumentResolver\NotTaggedControllerValueResolver; -use Symfony\Component\HttpKernel\Controller\TraceableArgumentResolver; -use Symfony\Component\HttpKernel\Controller\TraceableControllerResolver; -use Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('debug.event_dispatcher', TraceableEventDispatcher::class) - ->decorate('event_dispatcher') - ->args([ - service('debug.event_dispatcher.inner'), - service('debug.stopwatch'), - service('logger')->nullOnInvalid(), - service('request_stack')->nullOnInvalid(), - ]) - ->tag('monolog.logger', ['channel' => 'event']) - ->tag('kernel.reset', ['method' => 'reset']) - - ->set('debug.controller_resolver', TraceableControllerResolver::class) - ->decorate('controller_resolver') - ->args([ - service('debug.controller_resolver.inner'), - service('debug.stopwatch'), - ]) - - ->set('debug.argument_resolver', TraceableArgumentResolver::class) - ->decorate('argument_resolver') - ->args([ - service('debug.argument_resolver.inner'), - service('debug.stopwatch'), - ]) - - ->set('argument_resolver.not_tagged_controller', NotTaggedControllerValueResolver::class) - ->args([abstract_arg('Controller argument, set in FrameworkExtension')]) - ->tag('controller.argument_value_resolver', ['priority' => -200]) - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/debug_prod.php b/lib/symfony/framework-bundle/Resources/config/debug_prod.php deleted file mode 100644 index f381b018f..000000000 --- a/lib/symfony/framework-bundle/Resources/config/debug_prod.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; -use Symfony\Component\HttpKernel\EventListener\DebugHandlersListener; - -return static function (ContainerConfigurator $container) { - $container->parameters()->set('debug.error_handler.throw_at', -1); - - $container->services() - ->set('debug.debug_handlers_listener', DebugHandlersListener::class) - ->args([ - null, // Exception handler - service('monolog.logger.php')->nullOnInvalid(), - null, // Log levels map for enabled error levels - param('debug.error_handler.throw_at'), - param('kernel.debug'), - param('kernel.debug'), - service('monolog.logger.deprecation')->nullOnInvalid(), - ]) - ->tag('kernel.event_subscriber') - ->tag('monolog.logger', ['channel' => 'php']) - - ->set('debug.file_link_formatter', FileLinkFormatter::class) - ->args([param('debug.file_link_format')]) - - ->alias(FileLinkFormatter::class, 'debug.file_link_formatter') - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/error_renderer.php b/lib/symfony/framework-bundle/Resources/config/error_renderer.php deleted file mode 100644 index 67f28ce44..000000000 --- a/lib/symfony/framework-bundle/Resources/config/error_renderer.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('error_handler.error_renderer.html', HtmlErrorRenderer::class) - ->args([ - inline_service() - ->factory([HtmlErrorRenderer::class, 'isDebug']) - ->args([ - service('request_stack'), - param('kernel.debug'), - ]), - param('kernel.charset'), - service('debug.file_link_formatter')->nullOnInvalid(), - param('kernel.project_dir'), - inline_service() - ->factory([HtmlErrorRenderer::class, 'getAndCleanOutputBuffer']) - ->args([service('request_stack')]), - service('logger')->nullOnInvalid(), - ]) - - ->alias('error_renderer.html', 'error_handler.error_renderer.html') - ->alias('error_renderer', 'error_renderer.html') - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/esi.php b/lib/symfony/framework-bundle/Resources/config/esi.php deleted file mode 100644 index 7ac9f9053..000000000 --- a/lib/symfony/framework-bundle/Resources/config/esi.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\HttpKernel\EventListener\SurrogateListener; -use Symfony\Component\HttpKernel\HttpCache\Esi; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('esi', Esi::class) - - ->set('esi_listener', SurrogateListener::class) - ->args([service('esi')->ignoreOnInvalid()]) - ->tag('kernel.event_subscriber') - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/form.php b/lib/symfony/framework-bundle/Resources/config/form.php deleted file mode 100644 index e4c0745c6..000000000 --- a/lib/symfony/framework-bundle/Resources/config/form.php +++ /dev/null @@ -1,152 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\Form\ChoiceList\Factory\CachingFactoryDecorator; -use Symfony\Component\Form\ChoiceList\Factory\DefaultChoiceListFactory; -use Symfony\Component\Form\ChoiceList\Factory\PropertyAccessDecorator; -use Symfony\Component\Form\Extension\Core\Type\ChoiceType; -use Symfony\Component\Form\Extension\Core\Type\ColorType; -use Symfony\Component\Form\Extension\Core\Type\FileType; -use Symfony\Component\Form\Extension\Core\Type\FormType; -use Symfony\Component\Form\Extension\Core\Type\SubmitType; -use Symfony\Component\Form\Extension\Core\Type\TransformationFailureExtension; -use Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension; -use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; -use Symfony\Component\Form\Extension\HttpFoundation\Type\FormTypeHttpFoundationExtension; -use Symfony\Component\Form\Extension\Validator\Type\FormTypeValidatorExtension; -use Symfony\Component\Form\Extension\Validator\Type\RepeatedTypeValidatorExtension; -use Symfony\Component\Form\Extension\Validator\Type\SubmitTypeValidatorExtension; -use Symfony\Component\Form\Extension\Validator\Type\UploadValidatorExtension; -use Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser; -use Symfony\Component\Form\FormFactory; -use Symfony\Component\Form\FormFactoryInterface; -use Symfony\Component\Form\FormRegistry; -use Symfony\Component\Form\FormRegistryInterface; -use Symfony\Component\Form\ResolvedFormTypeFactory; -use Symfony\Component\Form\ResolvedFormTypeFactoryInterface; -use Symfony\Component\Form\Util\ServerParams; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('form.resolved_type_factory', ResolvedFormTypeFactory::class) - - ->alias(ResolvedFormTypeFactoryInterface::class, 'form.resolved_type_factory') - - ->set('form.registry', FormRegistry::class) - ->args([ - [ - /* - * We don't need to be able to add more extensions. - * more types can be registered with the form.type tag - * more type extensions can be registered with the form.type_extension tag - * more type_guessers can be registered with the form.type_guesser tag - */ - service('form.extension'), - ], - service('form.resolved_type_factory'), - ]) - - ->alias(FormRegistryInterface::class, 'form.registry') - - ->set('form.factory', FormFactory::class) - ->public() - ->args([service('form.registry')]) - ->tag('container.private', ['package' => 'symfony/framework-bundle', 'version' => '5.2']) - - ->alias(FormFactoryInterface::class, 'form.factory') - - ->set('form.extension', DependencyInjectionExtension::class) - ->args([ - abstract_arg('All services with tag "form.type" are stored in a service locator by FormPass'), - abstract_arg('All services with tag "form.type_extension" are stored here by FormPass'), - abstract_arg('All services with tag "form.type_guesser" are stored here by FormPass'), - ]) - - ->set('form.type_guesser.validator', ValidatorTypeGuesser::class) - ->args([service('validator.mapping.class_metadata_factory')]) - ->tag('form.type_guesser') - - ->alias('form.property_accessor', 'property_accessor') - - ->set('form.choice_list_factory.default', DefaultChoiceListFactory::class) - - ->set('form.choice_list_factory.property_access', PropertyAccessDecorator::class) - ->args([ - service('form.choice_list_factory.default'), - service('form.property_accessor'), - ]) - - ->set('form.choice_list_factory.cached', CachingFactoryDecorator::class) - ->args([service('form.choice_list_factory.property_access')]) - ->tag('kernel.reset', ['method' => 'reset']) - - ->alias('form.choice_list_factory', 'form.choice_list_factory.cached') - - ->set('form.type.form', FormType::class) - ->args([service('form.property_accessor')]) - ->tag('form.type') - - ->set('form.type.choice', ChoiceType::class) - ->args([ - service('form.choice_list_factory'), - service('translator')->ignoreOnInvalid(), - ]) - ->tag('form.type') - - ->set('form.type.file', FileType::class) - ->public() - ->args([service('translator')->ignoreOnInvalid()]) - ->tag('form.type') - ->tag('container.private', ['package' => 'symfony/framework-bundle', 'version' => '5.2']) - - ->set('form.type.color', ColorType::class) - ->args([service('translator')->ignoreOnInvalid()]) - ->tag('form.type') - - ->set('form.type_extension.form.transformation_failure_handling', TransformationFailureExtension::class) - ->args([service('translator')->ignoreOnInvalid()]) - ->tag('form.type_extension', ['extended-type' => FormType::class]) - - ->set('form.type_extension.form.http_foundation', FormTypeHttpFoundationExtension::class) - ->args([service('form.type_extension.form.request_handler')]) - ->tag('form.type_extension') - - ->set('form.type_extension.form.request_handler', HttpFoundationRequestHandler::class) - ->args([service('form.server_params')]) - - ->set('form.server_params', ServerParams::class) - ->args([service('request_stack')]) - - ->set('form.type_extension.form.validator', FormTypeValidatorExtension::class) - ->args([ - service('validator'), - true, - service('twig.form.renderer')->ignoreOnInvalid(), - service('translator')->ignoreOnInvalid(), - ]) - ->tag('form.type_extension', ['extended-type' => FormType::class]) - - ->set('form.type_extension.repeated.validator', RepeatedTypeValidatorExtension::class) - ->tag('form.type_extension') - - ->set('form.type_extension.submit.validator', SubmitTypeValidatorExtension::class) - ->tag('form.type_extension', ['extended-type' => SubmitType::class]) - - ->set('form.type_extension.upload.validator', UploadValidatorExtension::class) - ->args([ - service('translator'), - param('validator.translation_domain'), - ]) - ->tag('form.type_extension') - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/form_csrf.php b/lib/symfony/framework-bundle/Resources/config/form_csrf.php deleted file mode 100644 index c8e5e973e..000000000 --- a/lib/symfony/framework-bundle/Resources/config/form_csrf.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\Form\Extension\Csrf\Type\FormTypeCsrfExtension; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('form.type_extension.csrf', FormTypeCsrfExtension::class) - ->args([ - service('security.csrf.token_manager'), - param('form.type_extension.csrf.enabled'), - param('form.type_extension.csrf.field_name'), - service('translator')->nullOnInvalid(), - param('validator.translation_domain'), - service('form.server_params'), - ]) - ->tag('form.type_extension') - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/form_debug.php b/lib/symfony/framework-bundle/Resources/config/form_debug.php deleted file mode 100644 index f5e2c3ecd..000000000 --- a/lib/symfony/framework-bundle/Resources/config/form_debug.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\Form\Extension\DataCollector\FormDataCollector; -use Symfony\Component\Form\Extension\DataCollector\FormDataExtractor; -use Symfony\Component\Form\Extension\DataCollector\Proxy\ResolvedTypeFactoryDataCollectorProxy; -use Symfony\Component\Form\Extension\DataCollector\Type\DataCollectorTypeExtension; -use Symfony\Component\Form\ResolvedFormTypeFactory; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('form.resolved_type_factory', ResolvedTypeFactoryDataCollectorProxy::class) - ->args([ - inline_service(ResolvedFormTypeFactory::class), - service('data_collector.form'), - ]) - - ->set('form.type_extension.form.data_collector', DataCollectorTypeExtension::class) - ->args([service('data_collector.form')]) - ->tag('form.type_extension') - - ->set('data_collector.form.extractor', FormDataExtractor::class) - - ->set('data_collector.form', FormDataCollector::class) - ->args([service('data_collector.form.extractor')]) - ->tag('data_collector', ['template' => '@WebProfiler/Collector/form.html.twig', 'id' => 'form', 'priority' => 310]) - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/fragment_listener.php b/lib/symfony/framework-bundle/Resources/config/fragment_listener.php deleted file mode 100644 index 465c30426..000000000 --- a/lib/symfony/framework-bundle/Resources/config/fragment_listener.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\HttpKernel\EventListener\FragmentListener; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('fragment.listener', FragmentListener::class) - ->args([service('uri_signer'), param('fragment.path')]) - ->tag('kernel.event_subscriber') - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/fragment_renderer.php b/lib/symfony/framework-bundle/Resources/config/fragment_renderer.php deleted file mode 100644 index 76f49c633..000000000 --- a/lib/symfony/framework-bundle/Resources/config/fragment_renderer.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\HttpKernel\DependencyInjection\LazyLoadingFragmentHandler; -use Symfony\Component\HttpKernel\Fragment\EsiFragmentRenderer; -use Symfony\Component\HttpKernel\Fragment\FragmentUriGenerator; -use Symfony\Component\HttpKernel\Fragment\FragmentUriGeneratorInterface; -use Symfony\Component\HttpKernel\Fragment\HIncludeFragmentRenderer; -use Symfony\Component\HttpKernel\Fragment\InlineFragmentRenderer; -use Symfony\Component\HttpKernel\Fragment\SsiFragmentRenderer; - -return static function (ContainerConfigurator $container) { - $container->parameters() - ->set('fragment.renderer.hinclude.global_template', null) - ->set('fragment.path', '/_fragment') - ; - - $container->services() - ->set('fragment.handler', LazyLoadingFragmentHandler::class) - ->args([ - abstract_arg('fragment renderer locator'), - service('request_stack'), - param('kernel.debug'), - ]) - - ->set('fragment.uri_generator', FragmentUriGenerator::class) - ->args([param('fragment.path'), service('uri_signer'), service('request_stack')]) - ->alias(FragmentUriGeneratorInterface::class, 'fragment.uri_generator') - - ->set('fragment.renderer.inline', InlineFragmentRenderer::class) - ->args([service('http_kernel'), service('event_dispatcher')]) - ->call('setFragmentPath', [param('fragment.path')]) - ->tag('kernel.fragment_renderer', ['alias' => 'inline']) - - ->set('fragment.renderer.hinclude', HIncludeFragmentRenderer::class) - ->args([ - service('twig')->nullOnInvalid(), - service('uri_signer'), - param('fragment.renderer.hinclude.global_template'), - ]) - ->call('setFragmentPath', [param('fragment.path')]) - - ->set('fragment.renderer.esi', EsiFragmentRenderer::class) - ->args([ - service('esi')->nullOnInvalid(), - service('fragment.renderer.inline'), - service('uri_signer'), - ]) - ->call('setFragmentPath', [param('fragment.path')]) - ->tag('kernel.fragment_renderer', ['alias' => 'esi']) - - ->set('fragment.renderer.ssi', SsiFragmentRenderer::class) - ->args([ - service('ssi')->nullOnInvalid(), - service('fragment.renderer.inline'), - service('uri_signer'), - ]) - ->call('setFragmentPath', [param('fragment.path')]) - ->tag('kernel.fragment_renderer', ['alias' => 'ssi']) - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/http_client.php b/lib/symfony/framework-bundle/Resources/config/http_client.php deleted file mode 100644 index ba70b90ad..000000000 --- a/lib/symfony/framework-bundle/Resources/config/http_client.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Psr\Http\Client\ClientInterface; -use Psr\Http\Message\ResponseFactoryInterface; -use Psr\Http\Message\StreamFactoryInterface; -use Symfony\Component\HttpClient\HttpClient; -use Symfony\Component\HttpClient\HttplugClient; -use Symfony\Component\HttpClient\Psr18Client; -use Symfony\Component\HttpClient\Retry\GenericRetryStrategy; -use Symfony\Contracts\HttpClient\HttpClientInterface; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('http_client', HttpClientInterface::class) - ->factory([HttpClient::class, 'create']) - ->args([ - [], // default options - abstract_arg('max host connections'), - ]) - ->call('setLogger', [service('logger')->ignoreOnInvalid()]) - ->tag('monolog.logger', ['channel' => 'http_client']) - ->tag('kernel.reset', ['method' => 'reset', 'on_invalid' => 'ignore']) - ->tag('http_client.client') - - ->alias(HttpClientInterface::class, 'http_client') - - ->set('psr18.http_client', Psr18Client::class) - ->args([ - service('http_client'), - service(ResponseFactoryInterface::class)->ignoreOnInvalid(), - service(StreamFactoryInterface::class)->ignoreOnInvalid(), - ]) - - ->alias(ClientInterface::class, 'psr18.http_client') - - ->set(\Http\Client\HttpClient::class, HttplugClient::class) - ->args([ - service('http_client'), - service(ResponseFactoryInterface::class)->ignoreOnInvalid(), - service(StreamFactoryInterface::class)->ignoreOnInvalid(), - ]) - - ->set('http_client.abstract_retry_strategy', GenericRetryStrategy::class) - ->abstract() - ->args([ - abstract_arg('http codes'), - abstract_arg('delay ms'), - abstract_arg('multiplier'), - abstract_arg('max delay ms'), - abstract_arg('jitter'), - ]) - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/http_client_debug.php b/lib/symfony/framework-bundle/Resources/config/http_client_debug.php deleted file mode 100644 index 44031eb5f..000000000 --- a/lib/symfony/framework-bundle/Resources/config/http_client_debug.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\HttpClient\DataCollector\HttpClientDataCollector; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('data_collector.http_client', HttpClientDataCollector::class) - ->tag('data_collector', [ - 'template' => '@WebProfiler/Collector/http_client.html.twig', - 'id' => 'http_client', - 'priority' => 250, - ]) - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/identity_translator.php b/lib/symfony/framework-bundle/Resources/config/identity_translator.php deleted file mode 100644 index a9066e1f0..000000000 --- a/lib/symfony/framework-bundle/Resources/config/identity_translator.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\Translation\IdentityTranslator; -use Symfony\Contracts\Translation\TranslatorInterface; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('translator', IdentityTranslator::class) - ->public() - ->tag('container.private', ['package' => 'symfony/framework-bundle', 'version' => '5.2']) - ->alias(TranslatorInterface::class, 'translator') - - ->set('identity_translator', IdentityTranslator::class) - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/lock.php b/lib/symfony/framework-bundle/Resources/config/lock.php deleted file mode 100644 index 4e1463621..000000000 --- a/lib/symfony/framework-bundle/Resources/config/lock.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\Lock\LockFactory; -use Symfony\Component\Lock\Store\CombinedStore; -use Symfony\Component\Lock\Strategy\ConsensusStrategy; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('lock.store.combined.abstract', CombinedStore::class)->abstract() - ->args([abstract_arg('List of stores'), service('lock.strategy.majority')]) - - ->set('lock.strategy.majority', ConsensusStrategy::class) - - ->set('lock.factory.abstract', LockFactory::class)->abstract() - ->args([abstract_arg('Store')]) - ->call('setLogger', [service('logger')->ignoreOnInvalid()]) - ->tag('monolog.logger', ['channel' => 'lock']) - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/mailer.php b/lib/symfony/framework-bundle/Resources/config/mailer.php deleted file mode 100644 index b15b29270..000000000 --- a/lib/symfony/framework-bundle/Resources/config/mailer.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\Mailer\EventListener\EnvelopeListener; -use Symfony\Component\Mailer\EventListener\MessageListener; -use Symfony\Component\Mailer\EventListener\MessageLoggerListener; -use Symfony\Component\Mailer\Mailer; -use Symfony\Component\Mailer\MailerInterface; -use Symfony\Component\Mailer\Messenger\MessageHandler; -use Symfony\Component\Mailer\Transport; -use Symfony\Component\Mailer\Transport\TransportInterface; -use Symfony\Component\Mailer\Transport\Transports; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('mailer.mailer', Mailer::class) - ->args([ - service('mailer.transports'), - abstract_arg('message bus'), - service('event_dispatcher')->ignoreOnInvalid(), - ]) - ->alias('mailer', 'mailer.mailer') - ->alias(MailerInterface::class, 'mailer.mailer') - - ->set('mailer.transports', Transports::class) - ->factory([service('mailer.transport_factory'), 'fromStrings']) - ->args([ - abstract_arg('transports'), - ]) - - ->set('mailer.transport_factory', Transport::class) - ->args([ - tagged_iterator('mailer.transport_factory'), - ]) - - ->set('mailer.default_transport', TransportInterface::class) - ->factory([service('mailer.transport_factory'), 'fromString']) - ->args([ - abstract_arg('env(MAILER_DSN)'), - ]) - ->alias(TransportInterface::class, 'mailer.default_transport') - - ->set('mailer.messenger.message_handler', MessageHandler::class) - ->args([ - service('mailer.transports'), - ]) - ->tag('messenger.message_handler') - - ->set('mailer.envelope_listener', EnvelopeListener::class) - ->args([ - abstract_arg('sender'), - abstract_arg('recipients'), - ]) - ->tag('kernel.event_subscriber') - - ->set('mailer.message_listener', MessageListener::class) - ->args([ - abstract_arg('headers'), - ]) - ->tag('kernel.event_subscriber') - - ->set('mailer.logger_message_listener', MessageLoggerListener::class) - ->tag('kernel.event_subscriber') - ->tag('kernel.reset', ['method' => 'reset']) - ->deprecate('symfony/framework-bundle', '5.2', 'The "%service_id%" service is deprecated, use "mailer.message_logger_listener" instead.') - - ->set('mailer.message_logger_listener', MessageLoggerListener::class) - ->tag('kernel.event_subscriber') - ->tag('kernel.reset', ['method' => 'reset']) - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/mailer_debug.php b/lib/symfony/framework-bundle/Resources/config/mailer_debug.php deleted file mode 100644 index cdb205750..000000000 --- a/lib/symfony/framework-bundle/Resources/config/mailer_debug.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\Mailer\DataCollector\MessageDataCollector; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('mailer.data_collector', MessageDataCollector::class) - ->args([ - service('mailer.message_logger_listener'), - ]) - ->tag('data_collector', [ - 'template' => '@WebProfiler/Collector/mailer.html.twig', - 'id' => 'mailer', - ]) - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/mailer_transports.php b/lib/symfony/framework-bundle/Resources/config/mailer_transports.php deleted file mode 100644 index 7bddfa756..000000000 --- a/lib/symfony/framework-bundle/Resources/config/mailer_transports.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\Mailer\Bridge\Amazon\Transport\SesTransportFactory; -use Symfony\Component\Mailer\Bridge\Google\Transport\GmailTransportFactory; -use Symfony\Component\Mailer\Bridge\Mailchimp\Transport\MandrillTransportFactory; -use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory; -use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory; -use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory; -use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; -use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; -use Symfony\Component\Mailer\Bridge\Sendinblue\Transport\SendinblueTransportFactory; -use Symfony\Component\Mailer\Transport\AbstractTransportFactory; -use Symfony\Component\Mailer\Transport\NativeTransportFactory; -use Symfony\Component\Mailer\Transport\NullTransportFactory; -use Symfony\Component\Mailer\Transport\SendmailTransportFactory; -use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransportFactory; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('mailer.transport_factory.abstract', AbstractTransportFactory::class) - ->abstract() - ->args([ - service('event_dispatcher'), - service('http_client')->ignoreOnInvalid(), - service('logger')->ignoreOnInvalid(), - ]) - ->tag('monolog.logger', ['channel' => 'mailer']) - - ->set('mailer.transport_factory.amazon', SesTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.gmail', GmailTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.mailchimp', MandrillTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.mailjet', MailjetTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.mailgun', MailgunTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.postmark', PostmarkTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.sendgrid', SendgridTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.null', NullTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.sendmail', SendmailTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.sendinblue', SendinblueTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.ohmysmtp', OhMySmtpTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory') - - ->set('mailer.transport_factory.smtp', EsmtpTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory', ['priority' => -100]) - - ->set('mailer.transport_factory.native', NativeTransportFactory::class) - ->parent('mailer.transport_factory.abstract') - ->tag('mailer.transport_factory'); -}; diff --git a/lib/symfony/framework-bundle/Resources/config/messenger.php b/lib/symfony/framework-bundle/Resources/config/messenger.php deleted file mode 100644 index 813d50300..000000000 --- a/lib/symfony/framework-bundle/Resources/config/messenger.php +++ /dev/null @@ -1,215 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\DependencyInjection\ServiceLocator; -use Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\AmazonSqsTransportFactory; -use Symfony\Component\Messenger\Bridge\Amqp\Transport\AmqpTransportFactory; -use Symfony\Component\Messenger\Bridge\Beanstalkd\Transport\BeanstalkdTransportFactory; -use Symfony\Component\Messenger\Bridge\Redis\Transport\RedisTransportFactory; -use Symfony\Component\Messenger\EventListener\AddErrorDetailsStampListener; -use Symfony\Component\Messenger\EventListener\DispatchPcntlSignalListener; -use Symfony\Component\Messenger\EventListener\ResetServicesListener; -use Symfony\Component\Messenger\EventListener\SendFailedMessageForRetryListener; -use Symfony\Component\Messenger\EventListener\SendFailedMessageToFailureTransportListener; -use Symfony\Component\Messenger\EventListener\StopWorkerOnCustomStopExceptionListener; -use Symfony\Component\Messenger\EventListener\StopWorkerOnRestartSignalListener; -use Symfony\Component\Messenger\EventListener\StopWorkerOnSigtermSignalListener; -use Symfony\Component\Messenger\Middleware\AddBusNameStampMiddleware; -use Symfony\Component\Messenger\Middleware\DispatchAfterCurrentBusMiddleware; -use Symfony\Component\Messenger\Middleware\FailedMessageProcessingMiddleware; -use Symfony\Component\Messenger\Middleware\HandleMessageMiddleware; -use Symfony\Component\Messenger\Middleware\RejectRedeliveredMessageMiddleware; -use Symfony\Component\Messenger\Middleware\RouterContextMiddleware; -use Symfony\Component\Messenger\Middleware\SendMessageMiddleware; -use Symfony\Component\Messenger\Middleware\TraceableMiddleware; -use Symfony\Component\Messenger\Middleware\ValidationMiddleware; -use Symfony\Component\Messenger\Retry\MultiplierRetryStrategy; -use Symfony\Component\Messenger\RoutableMessageBus; -use Symfony\Component\Messenger\Transport\InMemoryTransportFactory; -use Symfony\Component\Messenger\Transport\Sender\SendersLocator; -use Symfony\Component\Messenger\Transport\Serialization\Normalizer\FlattenExceptionNormalizer; -use Symfony\Component\Messenger\Transport\Serialization\PhpSerializer; -use Symfony\Component\Messenger\Transport\Serialization\Serializer; -use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface; -use Symfony\Component\Messenger\Transport\Sync\SyncTransportFactory; -use Symfony\Component\Messenger\Transport\TransportFactory; - -return static function (ContainerConfigurator $container) { - $container->services() - ->alias(SerializerInterface::class, 'messenger.default_serializer') - - // Asynchronous - ->set('messenger.senders_locator', SendersLocator::class) - ->args([ - abstract_arg('per message senders map'), - abstract_arg('senders service locator'), - ]) - ->set('messenger.middleware.send_message', SendMessageMiddleware::class) - ->args([ - service('messenger.senders_locator'), - service('event_dispatcher'), - ]) - ->call('setLogger', [service('logger')->ignoreOnInvalid()]) - ->tag('monolog.logger', ['channel' => 'messenger']) - - // Message encoding/decoding - ->set('messenger.transport.symfony_serializer', Serializer::class) - ->args([ - service('serializer'), - abstract_arg('format'), - abstract_arg('context'), - ]) - - ->set('serializer.normalizer.flatten_exception', FlattenExceptionNormalizer::class) - ->tag('serializer.normalizer', ['priority' => -880]) - - ->set('messenger.transport.native_php_serializer', PhpSerializer::class) - - // Middleware - ->set('messenger.middleware.handle_message', HandleMessageMiddleware::class) - ->abstract() - ->args([ - abstract_arg('bus handler resolver'), - ]) - ->tag('monolog.logger', ['channel' => 'messenger']) - ->call('setLogger', [service('logger')->ignoreOnInvalid()]) - - ->set('messenger.middleware.add_bus_name_stamp_middleware', AddBusNameStampMiddleware::class) - ->abstract() - - ->set('messenger.middleware.dispatch_after_current_bus', DispatchAfterCurrentBusMiddleware::class) - - ->set('messenger.middleware.validation', ValidationMiddleware::class) - ->args([ - service('validator'), - ]) - - ->set('messenger.middleware.reject_redelivered_message_middleware', RejectRedeliveredMessageMiddleware::class) - - ->set('messenger.middleware.failed_message_processing_middleware', FailedMessageProcessingMiddleware::class) - - ->set('messenger.middleware.traceable', TraceableMiddleware::class) - ->abstract() - ->args([ - service('debug.stopwatch'), - ]) - - ->set('messenger.middleware.router_context', RouterContextMiddleware::class) - ->args([ - service('router'), - ]) - - // Discovery - ->set('messenger.receiver_locator', ServiceLocator::class) - ->args([ - [], - ]) - ->tag('container.service_locator') - - // Transports - ->set('messenger.transport_factory', TransportFactory::class) - ->args([ - tagged_iterator('messenger.transport_factory'), - ]) - - ->set('messenger.transport.amqp.factory', AmqpTransportFactory::class) - - ->set('messenger.transport.redis.factory', RedisTransportFactory::class) - - ->set('messenger.transport.sync.factory', SyncTransportFactory::class) - ->args([ - service('messenger.routable_message_bus'), - ]) - ->tag('messenger.transport_factory') - - ->set('messenger.transport.in_memory.factory', InMemoryTransportFactory::class) - ->tag('messenger.transport_factory') - ->tag('kernel.reset', ['method' => 'reset']) - - ->set('messenger.transport.sqs.factory', AmazonSqsTransportFactory::class) - ->args([ - service('logger')->ignoreOnInvalid(), - ]) - - ->set('messenger.transport.beanstalkd.factory', BeanstalkdTransportFactory::class) - - // retry - ->set('messenger.retry_strategy_locator', ServiceLocator::class) - ->args([ - [], - ]) - ->tag('container.service_locator') - - ->set('messenger.retry.abstract_multiplier_retry_strategy', MultiplierRetryStrategy::class) - ->abstract() - ->args([ - abstract_arg('max retries'), - abstract_arg('delay ms'), - abstract_arg('multiplier'), - abstract_arg('max delay ms'), - ]) - - // worker event listener - ->set('messenger.retry.send_failed_message_for_retry_listener', SendFailedMessageForRetryListener::class) - ->args([ - abstract_arg('senders service locator'), - service('messenger.retry_strategy_locator'), - service('logger')->ignoreOnInvalid(), - service('event_dispatcher'), - ]) - ->tag('kernel.event_subscriber') - ->tag('monolog.logger', ['channel' => 'messenger']) - - ->set('messenger.failure.add_error_details_stamp_listener', AddErrorDetailsStampListener::class) - ->tag('kernel.event_subscriber') - - ->set('messenger.failure.send_failed_message_to_failure_transport_listener', SendFailedMessageToFailureTransportListener::class) - ->args([ - abstract_arg('failure transports'), - service('logger')->ignoreOnInvalid(), - ]) - ->tag('kernel.event_subscriber') - ->tag('monolog.logger', ['channel' => 'messenger']) - - ->set('messenger.listener.dispatch_pcntl_signal_listener', DispatchPcntlSignalListener::class) - ->tag('kernel.event_subscriber') - - ->set('messenger.listener.stop_worker_on_restart_signal_listener', StopWorkerOnRestartSignalListener::class) - ->args([ - service('cache.messenger.restart_workers_signal'), - service('logger')->ignoreOnInvalid(), - ]) - ->tag('kernel.event_subscriber') - ->tag('monolog.logger', ['channel' => 'messenger']) - - ->set('messenger.listener.stop_worker_on_sigterm_signal_listener', StopWorkerOnSigtermSignalListener::class) - ->args([ - service('logger')->ignoreOnInvalid(), - ]) - ->tag('kernel.event_subscriber') - - ->set('messenger.listener.stop_worker_on_stop_exception_listener', StopWorkerOnCustomStopExceptionListener::class) - ->tag('kernel.event_subscriber') - - ->set('messenger.listener.reset_services', ResetServicesListener::class) - ->args([ - service('services_resetter'), - ]) - - ->set('messenger.routable_message_bus', RoutableMessageBus::class) - ->args([ - abstract_arg('message bus locator'), - service('messenger.default_bus'), - ]) - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/messenger_debug.php b/lib/symfony/framework-bundle/Resources/config/messenger_debug.php deleted file mode 100644 index 58f9be1f9..000000000 --- a/lib/symfony/framework-bundle/Resources/config/messenger_debug.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\Messenger\DataCollector\MessengerDataCollector; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('data_collector.messenger', MessengerDataCollector::class) - ->tag('data_collector', [ - 'template' => '@WebProfiler/Collector/messenger.html.twig', - 'id' => 'messenger', - 'priority' => 100, - ]) - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/mime_type.php b/lib/symfony/framework-bundle/Resources/config/mime_type.php deleted file mode 100644 index a7e9bbd91..000000000 --- a/lib/symfony/framework-bundle/Resources/config/mime_type.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\Mime\MimeTypeGuesserInterface; -use Symfony\Component\Mime\MimeTypes; -use Symfony\Component\Mime\MimeTypesInterface; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('mime_types', MimeTypes::class) - ->call('setDefault', [service('mime_types')]) - - ->alias(MimeTypesInterface::class, 'mime_types') - ->alias(MimeTypeGuesserInterface::class, 'mime_types') - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/notifier.php b/lib/symfony/framework-bundle/Resources/config/notifier.php deleted file mode 100644 index 73beb2c34..000000000 --- a/lib/symfony/framework-bundle/Resources/config/notifier.php +++ /dev/null @@ -1,119 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Bridge\Monolog\Handler\NotifierHandler; -use Symfony\Component\Notifier\Channel\BrowserChannel; -use Symfony\Component\Notifier\Channel\ChannelPolicy; -use Symfony\Component\Notifier\Channel\ChatChannel; -use Symfony\Component\Notifier\Channel\EmailChannel; -use Symfony\Component\Notifier\Channel\PushChannel; -use Symfony\Component\Notifier\Channel\SmsChannel; -use Symfony\Component\Notifier\Chatter; -use Symfony\Component\Notifier\ChatterInterface; -use Symfony\Component\Notifier\EventListener\NotificationLoggerListener; -use Symfony\Component\Notifier\EventListener\SendFailedMessageToNotifierListener; -use Symfony\Component\Notifier\Message\ChatMessage; -use Symfony\Component\Notifier\Message\PushMessage; -use Symfony\Component\Notifier\Message\SmsMessage; -use Symfony\Component\Notifier\Messenger\MessageHandler; -use Symfony\Component\Notifier\Notifier; -use Symfony\Component\Notifier\NotifierInterface; -use Symfony\Component\Notifier\Texter; -use Symfony\Component\Notifier\TexterInterface; -use Symfony\Component\Notifier\Transport; -use Symfony\Component\Notifier\Transport\Transports; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('notifier', Notifier::class) - ->args([tagged_locator('notifier.channel', 'channel'), service('notifier.channel_policy')->ignoreOnInvalid()]) - - ->alias(NotifierInterface::class, 'notifier') - - ->set('notifier.channel_policy', ChannelPolicy::class) - ->args([[]]) - - ->set('notifier.channel.browser', BrowserChannel::class) - ->args([service('request_stack')]) - ->tag('notifier.channel', ['channel' => 'browser']) - - ->set('notifier.channel.chat', ChatChannel::class) - ->args([service('chatter.transports'), service('messenger.default_bus')->ignoreOnInvalid()]) - ->tag('notifier.channel', ['channel' => 'chat']) - - ->set('notifier.channel.sms', SmsChannel::class) - ->args([service('texter.transports'), service('messenger.default_bus')->ignoreOnInvalid()]) - ->tag('notifier.channel', ['channel' => 'sms']) - - ->set('notifier.channel.email', EmailChannel::class) - ->args([service('mailer.transports'), service('messenger.default_bus')->ignoreOnInvalid()]) - ->tag('notifier.channel', ['channel' => 'email']) - - ->set('notifier.channel.push', PushChannel::class) - ->args([service('texter.transports'), service('messenger.default_bus')->ignoreOnInvalid()]) - ->tag('notifier.channel', ['channel' => 'push']) - - ->set('notifier.monolog_handler', NotifierHandler::class) - ->args([service('notifier')]) - - ->set('notifier.failed_message_listener', SendFailedMessageToNotifierListener::class) - ->args([service('notifier')]) - - ->set('chatter', Chatter::class) - ->args([ - service('chatter.transports'), - service('messenger.default_bus')->ignoreOnInvalid(), - service('event_dispatcher')->ignoreOnInvalid(), - ]) - - ->alias(ChatterInterface::class, 'chatter') - - ->set('chatter.transports', Transports::class) - ->factory([service('chatter.transport_factory'), 'fromStrings']) - ->args([[]]) - - ->set('chatter.transport_factory', Transport::class) - ->args([tagged_iterator('chatter.transport_factory')]) - - ->set('chatter.messenger.chat_handler', MessageHandler::class) - ->args([service('chatter.transports')]) - ->tag('messenger.message_handler', ['handles' => ChatMessage::class]) - - ->set('texter', Texter::class) - ->args([ - service('texter.transports'), - service('messenger.default_bus')->ignoreOnInvalid(), - service('event_dispatcher')->ignoreOnInvalid(), - ]) - - ->alias(TexterInterface::class, 'texter') - - ->set('texter.transports', Transports::class) - ->factory([service('texter.transport_factory'), 'fromStrings']) - ->args([[]]) - - ->set('texter.transport_factory', Transport::class) - ->args([tagged_iterator('texter.transport_factory')]) - - ->set('texter.messenger.sms_handler', MessageHandler::class) - ->args([service('texter.transports')]) - ->tag('messenger.message_handler', ['handles' => SmsMessage::class]) - - ->set('texter.messenger.push_handler', MessageHandler::class) - ->args([service('texter.transports')]) - ->tag('messenger.message_handler', ['handles' => PushMessage::class]) - - ->set('notifier.logger_notification_listener', NotificationLoggerListener::class) - ->tag('kernel.event_subscriber') - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/notifier_debug.php b/lib/symfony/framework-bundle/Resources/config/notifier_debug.php deleted file mode 100644 index 6147d34e4..000000000 --- a/lib/symfony/framework-bundle/Resources/config/notifier_debug.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\Notifier\DataCollector\NotificationDataCollector; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('notifier.data_collector', NotificationDataCollector::class) - ->args([service('notifier.logger_notification_listener')]) - ->tag('data_collector', ['template' => '@WebProfiler/Collector/notifier.html.twig', 'id' => 'notifier']) - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/notifier_transports.php b/lib/symfony/framework-bundle/Resources/config/notifier_transports.php deleted file mode 100644 index c07028847..000000000 --- a/lib/symfony/framework-bundle/Resources/config/notifier_transports.php +++ /dev/null @@ -1,277 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\Notifier\Bridge\AllMySms\AllMySmsTransportFactory; -use Symfony\Component\Notifier\Bridge\AmazonSns\AmazonSnsTransportFactory; -use Symfony\Component\Notifier\Bridge\Clickatell\ClickatellTransportFactory; -use Symfony\Component\Notifier\Bridge\Discord\DiscordTransportFactory; -use Symfony\Component\Notifier\Bridge\Esendex\EsendexTransportFactory; -use Symfony\Component\Notifier\Bridge\Expo\ExpoTransportFactory; -use Symfony\Component\Notifier\Bridge\FakeChat\FakeChatTransportFactory; -use Symfony\Component\Notifier\Bridge\FakeSms\FakeSmsTransportFactory; -use Symfony\Component\Notifier\Bridge\Firebase\FirebaseTransportFactory; -use Symfony\Component\Notifier\Bridge\FreeMobile\FreeMobileTransportFactory; -use Symfony\Component\Notifier\Bridge\GatewayApi\GatewayApiTransportFactory; -use Symfony\Component\Notifier\Bridge\Gitter\GitterTransportFactory; -use Symfony\Component\Notifier\Bridge\GoogleChat\GoogleChatTransportFactory; -use Symfony\Component\Notifier\Bridge\Infobip\InfobipTransportFactory; -use Symfony\Component\Notifier\Bridge\Iqsms\IqsmsTransportFactory; -use Symfony\Component\Notifier\Bridge\LightSms\LightSmsTransportFactory; -use Symfony\Component\Notifier\Bridge\LinkedIn\LinkedInTransportFactory; -use Symfony\Component\Notifier\Bridge\Mailjet\MailjetTransportFactory; -use Symfony\Component\Notifier\Bridge\Mattermost\MattermostTransportFactory; -use Symfony\Component\Notifier\Bridge\Mercure\MercureTransportFactory; -use Symfony\Component\Notifier\Bridge\MessageBird\MessageBirdTransportFactory; -use Symfony\Component\Notifier\Bridge\MessageMedia\MessageMediaTransportFactory; -use Symfony\Component\Notifier\Bridge\MicrosoftTeams\MicrosoftTeamsTransportFactory; -use Symfony\Component\Notifier\Bridge\Mobyt\MobytTransportFactory; -use Symfony\Component\Notifier\Bridge\Nexmo\NexmoTransportFactory; -use Symfony\Component\Notifier\Bridge\Octopush\OctopushTransportFactory; -use Symfony\Component\Notifier\Bridge\OneSignal\OneSignalTransportFactory; -use Symfony\Component\Notifier\Bridge\OvhCloud\OvhCloudTransportFactory; -use Symfony\Component\Notifier\Bridge\RocketChat\RocketChatTransportFactory; -use Symfony\Component\Notifier\Bridge\Sendinblue\SendinblueTransportFactory; -use Symfony\Component\Notifier\Bridge\Sinch\SinchTransportFactory; -use Symfony\Component\Notifier\Bridge\Slack\SlackTransportFactory; -use Symfony\Component\Notifier\Bridge\Sms77\Sms77TransportFactory; -use Symfony\Component\Notifier\Bridge\Smsapi\SmsapiTransportFactory; -use Symfony\Component\Notifier\Bridge\SmsBiuras\SmsBiurasTransportFactory; -use Symfony\Component\Notifier\Bridge\Smsc\SmscTransportFactory; -use Symfony\Component\Notifier\Bridge\SpotHit\SpotHitTransportFactory; -use Symfony\Component\Notifier\Bridge\Telegram\TelegramTransportFactory; -use Symfony\Component\Notifier\Bridge\Telnyx\TelnyxTransportFactory; -use Symfony\Component\Notifier\Bridge\TurboSms\TurboSmsTransportFactory; -use Symfony\Component\Notifier\Bridge\Twilio\TwilioTransportFactory; -use Symfony\Component\Notifier\Bridge\Vonage\VonageTransportFactory; -use Symfony\Component\Notifier\Bridge\Yunpian\YunpianTransportFactory; -use Symfony\Component\Notifier\Bridge\Zulip\ZulipTransportFactory; -use Symfony\Component\Notifier\Transport\AbstractTransportFactory; -use Symfony\Component\Notifier\Transport\NullTransportFactory; - -return static function (ContainerConfigurator $container) { - $container->services() - ->alias('notifier.transport_factory.allmysms', 'notifier.transport_factory.all-my-sms') - ->deprecate('symfony/framework-bundle', '5.4', 'The "%alias_id% service is deprecated, use "notifier.transport_factory.all-my-sms" instead.') - ->alias('notifier.transport_factory.fakechat', 'notifier.transport_factory.fake-chat') - ->deprecate('symfony/framework-bundle', '5.4', 'The "%alias_id% service is deprecated, use "notifier.transport_factory.fake-chat" instead.') - ->alias('notifier.transport_factory.fakesms', 'notifier.transport_factory.fake-sms') - ->deprecate('symfony/framework-bundle', '5.4', 'The "%alias_id% service is deprecated, use "notifier.transport_factory.fake-sms" instead.') - ->alias('notifier.transport_factory.freemobile', 'notifier.transport_factory.free-mobile') - ->deprecate('symfony/framework-bundle', '5.4', 'The "%alias_id% service is deprecated, use "notifier.transport_factory.free-mobile" instead.') - ->alias('notifier.transport_factory.gatewayapi', 'notifier.transport_factory.gateway-api') - ->deprecate('symfony/framework-bundle', '5.4', 'The "%alias_id% service is deprecated, use "notifier.transport_factory.gateway-api" instead.') - ->alias('notifier.transport_factory.googlechat', 'notifier.transport_factory.google-chat') - ->deprecate('symfony/framework-bundle', '5.4', 'The "%alias_id% service is deprecated, use "notifier.transport_factory.google-chat" instead.') - ->alias('notifier.transport_factory.lightsms', 'notifier.transport_factory.light-sms') - ->deprecate('symfony/framework-bundle', '5.4', 'The "%alias_id% service is deprecated, use "notifier.transport_factory.light-sms" instead.') - ->alias('notifier.transport_factory.linkedin', 'notifier.transport_factory.linked-in') - ->deprecate('symfony/framework-bundle', '5.4', 'The "%alias_id% service is deprecated, use "notifier.transport_factory.linked-in" instead.') - ->alias('notifier.transport_factory.microsoftteams', 'notifier.transport_factory.microsoft-teams') - ->deprecate('symfony/framework-bundle', '5.4', 'The "%alias_id% service is deprecated, use "notifier.transport_factory.microsoft-teams" instead.') - ->alias('notifier.transport_factory.onesignal', 'notifier.transport_factory.one-signal') - ->deprecate('symfony/framework-bundle', '5.4', 'The "%alias_id% service is deprecated, use "notifier.transport_factory.one-signal" instead.') - ->alias('notifier.transport_factory.ovhcloud', 'notifier.transport_factory.ovh-cloud') - ->deprecate('symfony/framework-bundle', '5.4', 'The "%alias_id% service is deprecated, use "notifier.transport_factory.ovh-cloud" instead.') - ->alias('notifier.transport_factory.rocketchat', 'notifier.transport_factory.rocket-chat') - ->deprecate('symfony/framework-bundle', '5.4', 'The "%alias_id% service is deprecated, use "notifier.transport_factory.rocket-chat" instead.') - ->alias('notifier.transport_factory.spothit', 'notifier.transport_factory.spot-hit') - ->deprecate('symfony/framework-bundle', '5.4', 'The "%alias_id% service is deprecated, use "notifier.transport_factory.spot-hit" instead.') - - ->set('notifier.transport_factory.abstract', AbstractTransportFactory::class) - ->abstract() - ->args([service('event_dispatcher'), service('http_client')->ignoreOnInvalid()]) - - ->set('notifier.transport_factory.slack', SlackTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.linked-in', LinkedInTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.telegram', TelegramTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.mattermost', MattermostTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.nexmo', NexmoTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - ->deprecate('symfony/framework-bundle', '5.4', 'The "%service_id% service is deprecated, use "notifier.transport_factory.vonage" instead.') - - ->set('notifier.transport_factory.vonage', VonageTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.rocket-chat', RocketChatTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.google-chat', GoogleChatTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.twilio', TwilioTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.all-my-sms', AllMySmsTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.firebase', FirebaseTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.free-mobile', FreeMobileTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.spot-hit', SpotHitTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.fake-chat', FakeChatTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.fake-sms', FakeSmsTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.ovh-cloud', OvhCloudTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.sinch', SinchTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.zulip', ZulipTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.infobip', InfobipTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.mobyt', MobytTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.smsapi', SmsapiTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.esendex', EsendexTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.sendinblue', SendinblueTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.iqsms', IqsmsTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.octopush', OctopushTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.discord', DiscordTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.microsoft-teams', MicrosoftTeamsTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.gateway-api', GatewayApiTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.mercure', MercureTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.gitter', GitterTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.clickatell', ClickatellTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.amazon-sns', AmazonSnsTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - ->tag('chatter.transport_factory') - - ->set('notifier.transport_factory.null', NullTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('chatter.transport_factory') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.light-sms', LightSmsTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.sms-biuras', SmsBiurasTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.smsc', SmscTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.message-bird', MessageBirdTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.message-media', MessageMediaTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.telnyx', TelnyxTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.mailjet', MailjetTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.yunpian', YunpianTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.turbo-sms', TurboSmsTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.sms77', Sms77TransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.one-signal', OneSignalTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - - ->set('notifier.transport_factory.expo', ExpoTransportFactory::class) - ->parent('notifier.transport_factory.abstract') - ->tag('texter.transport_factory') - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/profiling.php b/lib/symfony/framework-bundle/Resources/config/profiling.php deleted file mode 100644 index 221217896..000000000 --- a/lib/symfony/framework-bundle/Resources/config/profiling.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\HttpKernel\EventListener\ProfilerListener; -use Symfony\Component\HttpKernel\Profiler\FileProfilerStorage; -use Symfony\Component\HttpKernel\Profiler\Profiler; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('profiler', Profiler::class) - ->public() - ->args([service('profiler.storage'), service('logger')->nullOnInvalid()]) - ->tag('monolog.logger', ['channel' => 'profiler']) - ->tag('container.private', ['package' => 'symfony/framework-bundle', 'version' => '5.4']) - - ->set('profiler.storage', FileProfilerStorage::class) - ->args([param('profiler.storage.dsn')]) - - ->set('profiler_listener', ProfilerListener::class) - ->args([ - service('profiler'), - service('request_stack'), - null, - param('profiler_listener.only_exceptions'), - param('profiler_listener.only_main_requests'), - ]) - ->tag('kernel.event_subscriber') - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/property_access.php b/lib/symfony/framework-bundle/Resources/config/property_access.php deleted file mode 100644 index 85ab9f18e..000000000 --- a/lib/symfony/framework-bundle/Resources/config/property_access.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\PropertyAccess\PropertyAccessor; -use Symfony\Component\PropertyAccess\PropertyAccessorInterface; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('property_accessor', PropertyAccessor::class) - ->args([ - abstract_arg('magic methods allowed, set by the extension'), - abstract_arg('throw exceptions, set by the extension'), - service('cache.property_access')->ignoreOnInvalid(), - abstract_arg('propertyReadInfoExtractor, set by the extension'), - abstract_arg('propertyWriteInfoExtractor, set by the extension'), - ]) - - ->alias(PropertyAccessorInterface::class, 'property_accessor') - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/property_info.php b/lib/symfony/framework-bundle/Resources/config/property_info.php deleted file mode 100644 index 90587839d..000000000 --- a/lib/symfony/framework-bundle/Resources/config/property_info.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor; -use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyInfoCacheExtractor; -use Symfony\Component\PropertyInfo\PropertyInfoExtractor; -use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyInitializableExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyListExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyReadInfoExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyWriteInfoExtractorInterface; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('property_info', PropertyInfoExtractor::class) - ->args([[], [], [], [], []]) - - ->alias(PropertyAccessExtractorInterface::class, 'property_info') - ->alias(PropertyDescriptionExtractorInterface::class, 'property_info') - ->alias(PropertyInfoExtractorInterface::class, 'property_info') - ->alias(PropertyTypeExtractorInterface::class, 'property_info') - ->alias(PropertyListExtractorInterface::class, 'property_info') - ->alias(PropertyInitializableExtractorInterface::class, 'property_info') - - ->set('property_info.cache', PropertyInfoCacheExtractor::class) - ->decorate('property_info') - ->args([service('property_info.cache.inner'), service('cache.property_info')]) - - // Extractor - ->set('property_info.reflection_extractor', ReflectionExtractor::class) - ->tag('property_info.list_extractor', ['priority' => -1000]) - ->tag('property_info.type_extractor', ['priority' => -1002]) - ->tag('property_info.access_extractor', ['priority' => -1000]) - ->tag('property_info.initializable_extractor', ['priority' => -1000]) - - ->alias(PropertyReadInfoExtractorInterface::class, 'property_info.reflection_extractor') - ->alias(PropertyWriteInfoExtractorInterface::class, 'property_info.reflection_extractor') - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/rate_limiter.php b/lib/symfony/framework-bundle/Resources/config/rate_limiter.php deleted file mode 100644 index 727a1f636..000000000 --- a/lib/symfony/framework-bundle/Resources/config/rate_limiter.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\RateLimiter\RateLimiterFactory; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('cache.rate_limiter') - ->parent('cache.app') - ->tag('cache.pool') - - ->set('limiter', RateLimiterFactory::class) - ->abstract() - ->args([ - abstract_arg('config'), - abstract_arg('storage'), - null, - ]) - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/request.php b/lib/symfony/framework-bundle/Resources/config/request.php deleted file mode 100644 index ef8fc9a5e..000000000 --- a/lib/symfony/framework-bundle/Resources/config/request.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\HttpKernel\EventListener\AddRequestFormatsListener; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('request.add_request_formats_listener', AddRequestFormatsListener::class) - ->args([abstract_arg('formats')]) - ->tag('kernel.event_subscriber') - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/routing.php b/lib/symfony/framework-bundle/Resources/config/routing.php deleted file mode 100644 index 09e340ff8..000000000 --- a/lib/symfony/framework-bundle/Resources/config/routing.php +++ /dev/null @@ -1,182 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Psr\Container\ContainerInterface; -use Symfony\Bundle\FrameworkBundle\CacheWarmer\RouterCacheWarmer; -use Symfony\Bundle\FrameworkBundle\Controller\RedirectController; -use Symfony\Bundle\FrameworkBundle\Controller\TemplateController; -use Symfony\Bundle\FrameworkBundle\Routing\DelegatingLoader; -use Symfony\Bundle\FrameworkBundle\Routing\RedirectableCompiledUrlMatcher; -use Symfony\Bundle\FrameworkBundle\Routing\Router; -use Symfony\Component\Config\Loader\LoaderResolver; -use Symfony\Component\HttpKernel\EventListener\RouterListener; -use Symfony\Component\Routing\Generator\CompiledUrlGenerator; -use Symfony\Component\Routing\Generator\Dumper\CompiledUrlGeneratorDumper; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; -use Symfony\Component\Routing\Loader\ContainerLoader; -use Symfony\Component\Routing\Loader\DirectoryLoader; -use Symfony\Component\Routing\Loader\GlobFileLoader; -use Symfony\Component\Routing\Loader\PhpFileLoader; -use Symfony\Component\Routing\Loader\XmlFileLoader; -use Symfony\Component\Routing\Loader\YamlFileLoader; -use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; -use Symfony\Component\Routing\Matcher\ExpressionLanguageProvider; -use Symfony\Component\Routing\Matcher\UrlMatcherInterface; -use Symfony\Component\Routing\RequestContext; -use Symfony\Component\Routing\RequestContextAwareInterface; -use Symfony\Component\Routing\RouterInterface; - -return static function (ContainerConfigurator $container) { - $container->parameters() - ->set('router.request_context.host', 'localhost') - ->set('router.request_context.scheme', 'http') - ->set('router.request_context.base_url', '') - ; - - $container->services() - ->set('routing.resolver', LoaderResolver::class) - - ->set('routing.loader.xml', XmlFileLoader::class) - ->args([ - service('file_locator'), - '%kernel.environment%', - ]) - ->tag('routing.loader') - - ->set('routing.loader.yml', YamlFileLoader::class) - ->args([ - service('file_locator'), - '%kernel.environment%', - ]) - ->tag('routing.loader') - - ->set('routing.loader.php', PhpFileLoader::class) - ->args([ - service('file_locator'), - '%kernel.environment%', - ]) - ->tag('routing.loader') - - ->set('routing.loader.glob', GlobFileLoader::class) - ->args([ - service('file_locator'), - '%kernel.environment%', - ]) - ->tag('routing.loader') - - ->set('routing.loader.directory', DirectoryLoader::class) - ->args([ - service('file_locator'), - '%kernel.environment%', - ]) - ->tag('routing.loader') - - ->set('routing.loader.container', ContainerLoader::class) - ->args([ - tagged_locator('routing.route_loader'), - '%kernel.environment%', - ]) - ->tag('routing.loader') - - ->set('routing.loader', DelegatingLoader::class) - ->public() - ->args([ - service('routing.resolver'), - [], // Default options - [], // Default requirements - ]) - - ->set('router.default', Router::class) - ->args([ - service(ContainerInterface::class), - param('router.resource'), - [ - 'cache_dir' => param('kernel.cache_dir'), - 'debug' => param('kernel.debug'), - 'generator_class' => CompiledUrlGenerator::class, - 'generator_dumper_class' => CompiledUrlGeneratorDumper::class, - 'matcher_class' => RedirectableCompiledUrlMatcher::class, - 'matcher_dumper_class' => CompiledUrlMatcherDumper::class, - ], - service('router.request_context')->ignoreOnInvalid(), - service('parameter_bag')->ignoreOnInvalid(), - service('logger')->ignoreOnInvalid(), - param('kernel.default_locale'), - ]) - ->call('setConfigCacheFactory', [ - service('config_cache_factory'), - ]) - ->tag('monolog.logger', ['channel' => 'router']) - ->tag('container.service_subscriber', ['id' => 'routing.loader']) - ->alias('router', 'router.default') - ->public() - ->alias(RouterInterface::class, 'router') - ->alias(UrlGeneratorInterface::class, 'router') - ->alias(UrlMatcherInterface::class, 'router') - ->alias(RequestContextAwareInterface::class, 'router') - - ->set('router.request_context', RequestContext::class) - ->factory([RequestContext::class, 'fromUri']) - ->args([ - param('router.request_context.base_url'), - param('router.request_context.host'), - param('router.request_context.scheme'), - param('request_listener.http_port'), - param('request_listener.https_port'), - ]) - ->call('setParameter', [ - '_functions', - service('router.expression_language_provider')->ignoreOnInvalid(), - ]) - ->alias(RequestContext::class, 'router.request_context') - - ->set('router.expression_language_provider', ExpressionLanguageProvider::class) - ->args([ - tagged_locator('routing.expression_language_function', 'function'), - ]) - ->tag('routing.expression_language_provider') - - ->set('router.cache_warmer', RouterCacheWarmer::class) - ->args([service(ContainerInterface::class)]) - ->tag('container.service_subscriber', ['id' => 'router']) - ->tag('kernel.cache_warmer') - - ->set('router_listener', RouterListener::class) - ->args([ - service('router'), - service('request_stack'), - service('router.request_context')->ignoreOnInvalid(), - service('logger')->ignoreOnInvalid(), - param('kernel.project_dir'), - param('kernel.debug'), - ]) - ->tag('kernel.event_subscriber') - ->tag('monolog.logger', ['channel' => 'request']) - - ->set(RedirectController::class) - ->public() - ->args([ - service('router'), - inline_service('int') - ->factory([service('router.request_context'), 'getHttpPort']), - inline_service('int') - ->factory([service('router.request_context'), 'getHttpsPort']), - ]) - - ->set(TemplateController::class) - ->args([ - service('twig')->ignoreOnInvalid(), - ]) - ->public() - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/routing/errors.xml b/lib/symfony/framework-bundle/Resources/config/routing/errors.xml deleted file mode 100644 index 13a9cc407..000000000 --- a/lib/symfony/framework-bundle/Resources/config/routing/errors.xml +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> - -<routes xmlns="http://symfony.com/schema/routing" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd"> - - <route id="_preview_error" path="/{code}.{_format}"> - <default key="_controller">error_controller::preview</default> - <default key="_format">html</default> - <requirement key="code">\d+</requirement> - </route> -</routes> diff --git a/lib/symfony/framework-bundle/Resources/config/schema/symfony-1.0.xsd b/lib/symfony/framework-bundle/Resources/config/schema/symfony-1.0.xsd deleted file mode 100644 index d4be9fb6f..000000000 --- a/lib/symfony/framework-bundle/Resources/config/schema/symfony-1.0.xsd +++ /dev/null @@ -1,829 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> - -<xsd:schema xmlns="http://symfony.com/schema/dic/symfony" - xmlns:xsd="http://www.w3.org/2001/XMLSchema" - targetNamespace="http://symfony.com/schema/dic/symfony" - elementFormDefault="qualified"> - - <xsd:element name="config" type="config" /> - - <xsd:complexType name="config"> - <xsd:choice maxOccurs="unbounded"> - <xsd:element name="assets" type="assets" minOccurs="0" maxOccurs="1" /> - <xsd:element name="form" type="form" minOccurs="0" maxOccurs="1" /> - <xsd:element name="csrf-protection" type="csrf_protection" minOccurs="0" maxOccurs="1" /> - <xsd:element name="esi" type="esi" minOccurs="0" maxOccurs="1" /> - <xsd:element name="ssi" type="ssi" minOccurs="0" maxOccurs="1" /> - <xsd:element name="fragments" type="fragments" minOccurs="0" maxOccurs="1" /> - <xsd:element name="web-link" type="web_link" minOccurs="0" maxOccurs="1" /> - <xsd:element name="profiler" type="profiler" minOccurs="0" maxOccurs="1" /> - <xsd:element name="router" type="router" minOccurs="0" maxOccurs="1" /> - <xsd:element name="session" type="session" minOccurs="0" maxOccurs="1" /> - <xsd:element name="request" type="request" minOccurs="0" maxOccurs="1" /> - <xsd:element name="translator" type="translator" minOccurs="0" maxOccurs="1" /> - <xsd:element name="validation" type="validation" minOccurs="0" maxOccurs="1" /> - <xsd:element name="annotations" type="annotations" minOccurs="0" maxOccurs="1" /> - <xsd:element name="property-access" type="property_access" minOccurs="0" maxOccurs="1" /> - <xsd:element name="serializer" type="serializer" minOccurs="0" maxOccurs="1" /> - <xsd:element name="property-info" type="property_info" minOccurs="0" maxOccurs="1" /> - <xsd:element name="cache" type="cache" minOccurs="0" maxOccurs="1" /> - <xsd:element name="workflow" type="workflow" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="php-errors" type="php-errors" minOccurs="0" maxOccurs="1" /> - <xsd:element name="exceptions" type="exceptions" minOccurs="0" maxOccurs="1" /> - <xsd:element name="exception" type="new-exception" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="lock" type="lock" minOccurs="0" maxOccurs="1" /> - <xsd:element name="messenger" type="messenger" minOccurs="0" maxOccurs="1" /> - <xsd:element name="http-client" type="http_client" minOccurs="0" maxOccurs="1" /> - <xsd:element name="mailer" type="mailer" minOccurs="0" maxOccurs="1" /> - <xsd:element name="http-cache" type="http_cache" minOccurs="0" maxOccurs="1" /> - <xsd:element name="rate-limiter" type="rate_limiter" minOccurs="0" maxOccurs="1" /> - <xsd:element name="uid" type="uid" minOccurs="0" maxOccurs="1" /> - <xsd:element name="notifier" type="notifier" minOccurs="0" maxOccurs="1" /> - <xsd:element name="enabled-locale" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /> - </xsd:choice> - - <xsd:attribute name="http-method-override" type="xsd:boolean" /> - <xsd:attribute name="ide" type="xsd:string" /> - <xsd:attribute name="secret" type="xsd:string" /> - <xsd:attribute name="default-locale" type="xsd:string" /> - <xsd:attribute name="set_locale_from_accept_language" type="xsd:boolean" /> - <xsd:attribute name="set_content_language_from_locale" type="xsd:boolean" /> - <xsd:attribute name="test" type="xsd:boolean" /> - <xsd:attribute name="error-controller" type="xsd:string" /> - <xsd:attribute name="trusted-hosts" type="xsd:string" /> - <xsd:attribute name="trusted-proxies" type="xsd:string" /> - <xsd:attribute name="trusted-headers" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="form"> - <xsd:all> - <xsd:element name="csrf-protection" type="form_csrf_protection" minOccurs="0" maxOccurs="1" /> - </xsd:all> - <xsd:attribute name="enabled" type="xsd:boolean" /> - <xsd:attribute name="legacy-error-messages" type="xsd:boolean" /> - </xsd:complexType> - - <xsd:complexType name="form_csrf_protection"> - <xsd:attribute name="enabled" type="xsd:boolean" /> - <xsd:attribute name="field-name" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="csrf_protection"> - <xsd:attribute name="enabled" type="xsd:boolean" /> - </xsd:complexType> - - <xsd:complexType name="esi"> - <xsd:attribute name="enabled" type="xsd:boolean" /> - </xsd:complexType> - - <xsd:complexType name="ssi"> - <xsd:attribute name="enabled" type="xsd:boolean" /> - </xsd:complexType> - - <xsd:complexType name="fragments"> - <xsd:attribute name="enabled" type="xsd:boolean" /> - <xsd:attribute name="path" type="xsd:string" /> - <xsd:attribute name="hinclude-default-template" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="web_link"> - <xsd:attribute name="enabled" type="xsd:boolean" /> - </xsd:complexType> - - <xsd:complexType name="profiler"> - <xsd:attribute name="collect" type="xsd:string" /> - <xsd:attribute name="collect-parameter" type="xsd:string" /> - <xsd:attribute name="only-exceptions" type="xsd:string" /> - <xsd:attribute name="only-main-requests" type="xsd:string" /> - <xsd:attribute name="only-master-requests" type="xsd:string" /> - <xsd:attribute name="enabled" type="xsd:string" /> - <xsd:attribute name="dsn" type="xsd:string" /> - <xsd:attribute name="username" type="xsd:string" /> - <xsd:attribute name="password" type="xsd:string" /> - <xsd:attribute name="lifetime" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="router"> - <xsd:attribute name="resource" type="xsd:string" /> - <xsd:attribute name="type" type="xsd:string" /> - <xsd:attribute name="http-port" type="xsd:string" /> - <xsd:attribute name="https-port" type="xsd:string" /> - <xsd:attribute name="strict-requirements" type="xsd:string" /> - <xsd:attribute name="utf8" type="xsd:boolean" /> - <xsd:attribute name="default-uri" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="session"> - <xsd:attribute name="enabled" type="xsd:boolean" /> - <xsd:attribute name="storage-factory-id" type="xsd:string" /> - <xsd:attribute name="storage-id" type="xsd:string" /> - <xsd:attribute name="handler-id" type="xsd:string" /> - <xsd:attribute name="name" type="xsd:string" /> - <xsd:attribute name="cookie-lifetime" type="xsd:string" /> - <xsd:attribute name="cookie-path" type="xsd:string" /> - <xsd:attribute name="cookie-domain" type="xsd:string" /> - <xsd:attribute name="cookie-secure" type="cookie_secure" /> - <xsd:attribute name="cookie-httponly" type="xsd:boolean" /> - <xsd:attribute name="cookie-samesite" type="cookie_samesite" /> - <xsd:attribute name="use-cookies" type="xsd:boolean" /> - <xsd:attribute name="cache-limiter" type="xsd:string" /> - <xsd:attribute name="gc-maxlifetime" type="xsd:string" /> - <xsd:attribute name="gc-divisor" type="xsd:string" /> - <xsd:attribute name="gc-probability" type="xsd:string" /> - <xsd:attribute name="save-path" type="xsd:string" /> - <xsd:attribute name="metadata-update-threshold" type="xsd:nonNegativeInteger" /> - <xsd:attribute name="sid-length" type="sid_length" /> - <xsd:attribute name="sid-bits-per-character" type="sid_bits_per_character" /> - </xsd:complexType> - - <xsd:complexType name="request"> - <xsd:sequence> - <xsd:element name="format" type="format" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - </xsd:complexType> - - <xsd:complexType name="format"> - <xsd:choice minOccurs="1" maxOccurs="unbounded"> - <xsd:element name="mime-type" type="xsd:string" /> - </xsd:choice> - <xsd:attribute name="name" type="xsd:string" use="required"/> - </xsd:complexType> - - <xsd:complexType name="assets"> - <xsd:sequence> - <xsd:element name="base-url" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="package" type="package" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - - <xsd:attribute name="enabled" type="xsd:boolean" /> - <xsd:attribute name="base-path" type="xsd:string" /> - <xsd:attribute name="version-strategy" type="xsd:string" /> - <xsd:attribute name="version" type="xsd:string" /> - <xsd:attribute name="version-format" type="xsd:string" /> - <xsd:attribute name="json-manifest-path" type="xsd:string" /> - <xsd:attribute name="strict-mode" type="xsd:boolean" /> - </xsd:complexType> - - <xsd:complexType name="package"> - <xsd:sequence> - <xsd:element name="base-url" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - - <xsd:attribute name="name" type="xsd:string" use="required" /> - <xsd:attribute name="base-path" type="xsd:string" /> - <xsd:attribute name="version-strategy" type="xsd:string" /> - <xsd:attribute name="version" type="xsd:string" /> - <xsd:attribute name="version-format" type="xsd:string" /> - <xsd:attribute name="json-manifest-path" type="xsd:string" /> - <xsd:attribute name="strict-mode" type="xsd:boolean" /> - </xsd:complexType> - - <xsd:complexType name="translator"> - <xsd:sequence> - <xsd:element name="fallback" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="path" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="enabled-locale" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="pseudo-localization" type="pseudo_localization" minOccurs="0" maxOccurs="1" /> - <xsd:element name="provider" type="translation_provider" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - <xsd:attribute name="enabled" type="xsd:boolean" /> - <xsd:attribute name="fallback" type="xsd:string" /> - <xsd:attribute name="logging" type="xsd:boolean" /> - <xsd:attribute name="formatter" type="xsd:string" /> - <xsd:attribute name="cache-dir" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="pseudo_localization"> - <xsd:sequence> - <xsd:element name="localizable-html-attribute" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - <xsd:attribute name="enabled" type="xsd:boolean" /> - <xsd:attribute name="accents" type="xsd:boolean" /> - <xsd:attribute name="expansion_factor" type="xsd:float" /> - <xsd:attribute name="brackets" type="xsd:boolean" /> - <xsd:attribute name="parse_html" type="xsd:boolean" /> - </xsd:complexType> - - <xsd:complexType name="translation_provider"> - <xsd:sequence> - <xsd:element name="domain" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="locale" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - <xsd:attribute name="name" type="xsd:string" /> - <xsd:attribute name="dsn" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="validation"> - <xsd:choice minOccurs="0" maxOccurs="unbounded"> - <xsd:element name="static-method" type="xsd:string" /> - <xsd:element name="mapping" type="file_mapping" /> - <xsd:element name="auto-mapping" type="auto_mapping" /> - </xsd:choice> - - <xsd:attribute name="enabled" type="xsd:boolean" /> - <xsd:attribute name="cache" type="xsd:string" /> - <xsd:attribute name="enable-annotations" type="xsd:boolean" /> - <xsd:attribute name="static-method" type="xsd:boolean" /> - <xsd:attribute name="translation-domain" type="xsd:string" /> - <xsd:attribute name="strict-email" type="xsd:boolean" /> - <xsd:attribute name="email-validation-mode" type="email-validation-mode" /> - </xsd:complexType> - - <xsd:complexType name="file_mapping"> - <xsd:sequence> - <xsd:element name="path" type="xsd:string" minOccurs="1" maxOccurs="unbounded" /> - </xsd:sequence> - </xsd:complexType> - - <xsd:complexType name="auto_mapping"> - <xsd:sequence> - <xsd:element name="service" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - <xsd:attribute name="namespace" type="xsd:string" use="required" /> - </xsd:complexType> - - <xsd:simpleType name="email-validation-mode"> - <xsd:restriction base="xsd:string"> - <xsd:enumeration value="html5" /> - <xsd:enumeration value="loose" /> - <xsd:enumeration value="strict" /> - </xsd:restriction> - </xsd:simpleType> - - <xsd:complexType name="annotations"> - <xsd:attribute name="cache" type="xsd:string" /> - <xsd:attribute name="debug" type="xsd:string" /> - <xsd:attribute name="file-cache-dir" type="xsd:string" /> - <xsd:attribute name="enabled" type="xsd:boolean" /> - </xsd:complexType> - - <xsd:complexType name="property_access"> - <xsd:attribute name="magic-call" type="xsd:boolean" /> - <xsd:attribute name="magic-get" type="xsd:boolean" /> - <xsd:attribute name="magic-set" type="xsd:boolean" /> - <xsd:attribute name="throw-exception-on-invalid-index" type="xsd:boolean" /> - <xsd:attribute name="throw-exception-on-invalid-property-path" type="xsd:boolean" /> - </xsd:complexType> - - <xsd:complexType name="serializer"> - <xsd:choice minOccurs="0" maxOccurs="unbounded"> - <xsd:element name="mapping" type="file_mapping" /> - <xsd:element name="default-context" type="metadata" minOccurs="0" maxOccurs="1" /> - </xsd:choice> - <xsd:attribute name="enabled" type="xsd:boolean" /> - <xsd:attribute name="enable-annotations" type="xsd:boolean" /> - <xsd:attribute name="name-converter" type="xsd:string" /> - <xsd:attribute name="circular-reference-handler" type="xsd:string" /> - <xsd:attribute name="max-depth-handler" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="property_info"> - <xsd:attribute name="enabled" type="xsd:boolean" /> - </xsd:complexType> - - <xsd:complexType name="cache"> - <xsd:sequence> - <xsd:element name="app" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="system" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="directory" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="default-doctrine-provider" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="default-psr6-provider" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="default-redis-provider" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="default-memcached-provider" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="default-pdo-provider" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="pool" type="cache_pool" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - <xsd:attribute name="app" type="xsd:string" /> - <xsd:attribute name="system" type="xsd:string" /> - <xsd:attribute name="directory" type="xsd:string" /> - <xsd:attribute name="default-doctrine-provider" type="xsd:string" /> - <xsd:attribute name="default-psr6-provider" type="xsd:string" /> - <xsd:attribute name="default-redis-provider" type="xsd:string" /> - <xsd:attribute name="default-memcached-provider" type="xsd:string" /> - <xsd:attribute name="default-pdo-provider" type="xsd:string" /> - <xsd:attribute name="prefix-seed" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="cache_pool"> - <xsd:sequence> - <xsd:element name="adapter" type="cache_pool_adapter" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - - <xsd:attribute name="name" type="xsd:string" use="required" /> - <xsd:attribute name="adapter" type="xsd:string" /> - <xsd:attribute name="tags" type="xsd:string" /> - <xsd:attribute name="public" type="xsd:boolean" /> - <xsd:attribute name="default-lifetime" type="xsd:string" /> - <xsd:attribute name="provider" type="xsd:string" /> - <xsd:attribute name="early-expiration-message-bus" type="xsd:string" /> - <xsd:attribute name="clearer" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="cache_pool_adapter"> - <xsd:attribute name="name" type="xsd:string" use="required" /> - <xsd:attribute name="provider" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="workflow"> - <xsd:sequence> - <xsd:element name="audit-trail" type="audit_trail" minOccurs="0" maxOccurs="1" /> - <xsd:element name="initial-marking" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="marking-store" type="marking_store" minOccurs="0" maxOccurs="1" /> - <xsd:element name="support" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="event-to-dispatch" type="event_to_dispatch" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="place" type="place" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="transition" type="transition" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="metadata" type="metadata" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - <xsd:attribute name="name" type="xsd:string" /> - <xsd:attribute name="type" type="workflow_type" /> - <xsd:attribute name="initial-place" type="xsd:string" /> - <xsd:attribute name="initial-marking" type="xsd:string" /> - <xsd:attribute name="support-strategy" type="xsd:string" /> - <xsd:attribute name="enabled" type="xsd:boolean" /> - </xsd:complexType> - - <xsd:complexType name="php-errors"> - <xsd:sequence> - <xsd:element name="log" type="logLevel" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - <xsd:attribute name="log" type="xsd:string" /> - <xsd:attribute name="throw" type="xsd:boolean" /> - </xsd:complexType> - - <xsd:complexType name="logLevel" mixed="true"> - <xsd:attribute name="type" type="xsd:string" use="required" /> - <xsd:attribute name="logLevel" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="audit_trail"> - <xsd:attribute name="enabled" type="xsd:boolean" /> - </xsd:complexType> - - <xsd:complexType name="exceptions"> - <xsd:sequence> - <xsd:element name="exception" type="old-exception" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - </xsd:complexType> - - <xsd:complexType name="exception" abstract="true"> - <xsd:attribute name="log-level" type="xsd:string" /> - <xsd:attribute name="status-code" type="xsd:integer" /> - </xsd:complexType> - - <xsd:complexType name="old-exception"> - <xsd:complexContent> - <xsd:extension base="exception"> - <xsd:attribute name="name" type="xsd:string" use="required" /> - </xsd:extension> - </xsd:complexContent> - </xsd:complexType> - - <xsd:complexType name="new-exception"> - <xsd:complexContent> - <xsd:extension base="exception"> - <xsd:attribute name="class" type="xsd:string" use="required" /> - </xsd:extension> - </xsd:complexContent> - </xsd:complexType> - - <xsd:complexType name="marking_store"> - <xsd:sequence> - <xsd:element name="argument" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - <xsd:attribute name="type" type="marking_store_type" /> - <xsd:attribute name="service" type="xsd:string" /> - <xsd:attribute name="property" type="xsd:string" /> - </xsd:complexType> - - <xsd:simpleType name="marking_store_type"> - <xsd:restriction base="xsd:string"> - <xsd:enumeration value="multiple_state" /> - <xsd:enumeration value="single_state" /> - <xsd:enumeration value="method" /> - </xsd:restriction> - </xsd:simpleType> - - <xsd:complexType name="transition"> - <xsd:sequence> - <xsd:element name="from" type="xsd:string" minOccurs="1" maxOccurs="unbounded" /> - <xsd:element name="to" type="xsd:string" minOccurs="1" maxOccurs="unbounded" /> - <xsd:element name="metadata" type="metadata" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="guard" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - <xsd:attribute name="name" type="xsd:string" use="required" /> - </xsd:complexType> - - <xsd:complexType name="place" mixed="true"> - <xsd:sequence> - <xsd:element name="metadata" type="metadata" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - <xsd:attribute name="name" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="metadata"> - <xsd:sequence> - <xsd:any minOccurs="0" maxOccurs="unbounded" processContents="lax"/> - </xsd:sequence> - </xsd:complexType> - - <xsd:simpleType name="event_to_dispatch"> - <xsd:restriction base="xsd:string"> - <xsd:enumeration value="" /> - <xsd:enumeration value="workflow.leave" /> - <xsd:enumeration value="workflow.transition" /> - <xsd:enumeration value="workflow.enter" /> - <xsd:enumeration value="workflow.entered" /> - <xsd:enumeration value="workflow.completed" /> - <xsd:enumeration value="workflow.announce" /> - </xsd:restriction> - </xsd:simpleType> - - <xsd:simpleType name="default_middleware"> - <xsd:restriction base="xsd:string"> - <xsd:enumeration value="true" /> - <xsd:enumeration value="false" /> - <xsd:enumeration value="1" /> - <xsd:enumeration value="0" /> - <xsd:enumeration value="allow_no_handlers" /> - </xsd:restriction> - </xsd:simpleType> - - <xsd:simpleType name="cookie_secure"> - <xsd:restriction base="xsd:string"> - <xsd:enumeration value="true" /> - <xsd:enumeration value="false" /> - <xsd:enumeration value="1" /> - <xsd:enumeration value="0" /> - <xsd:enumeration value="auto" /> - </xsd:restriction> - </xsd:simpleType> - - <xsd:simpleType name="cookie_samesite"> - <xsd:restriction base="xsd:string"> - <xsd:enumeration value="" /> - <xsd:enumeration value="none" /> - <xsd:enumeration value="lax" /> - <xsd:enumeration value="strict" /> - </xsd:restriction> - </xsd:simpleType> - - <xsd:simpleType name="sid_bits_per_character"> - <xsd:restriction base="xsd:positiveInteger"> - <xsd:enumeration value="4" /> - <xsd:enumeration value="5" /> - <xsd:enumeration value="6" /> - </xsd:restriction> - </xsd:simpleType> - - <xsd:simpleType name="sid_length"> - <xsd:restriction base="xsd:positiveInteger"> - <xsd:minInclusive value="22" /> - <xsd:maxInclusive value="256" /> - </xsd:restriction> - </xsd:simpleType> - - <xsd:simpleType name="workflow_type"> - <xsd:restriction base="xsd:string"> - <xsd:enumeration value="state_machine" /> - <xsd:enumeration value="workflow" /> - </xsd:restriction> - </xsd:simpleType> - - <xsd:complexType name="lock"> - <xsd:sequence> - <xsd:element name="resource" type="lock_resource" minOccurs="1" maxOccurs="unbounded" /> - </xsd:sequence> - <xsd:attribute name="enabled" type="xsd:boolean" /> - </xsd:complexType> - - <xsd:complexType name="lock_resource"> - <xsd:simpleContent> - <xsd:extension base="xsd:string"> - <xsd:attribute name="name" type="xsd:string" /> - </xsd:extension> - </xsd:simpleContent> - </xsd:complexType> - - <xsd:complexType name="messenger"> - <xsd:sequence> - <xsd:element name="serializer" type="messenger_serializer" minOccurs="0" /> - <xsd:element name="routing" type="messenger_routing" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="transport" type="messenger_transport" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="bus" type="messenger_bus" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - <xsd:attribute name="default-bus" type="xsd:string" /> - <xsd:attribute name="enabled" type="xsd:boolean" /> - <xsd:attribute name="failure-transport" type="xsd:string" /> - <xsd:attribute name="reset-on-message" type="xsd:boolean" /> - </xsd:complexType> - - <xsd:complexType name="messenger_serializer"> - <xsd:sequence> - <xsd:element name="symfony-serializer" type="messenger_symfony_serializer" minOccurs="0" /> - </xsd:sequence> - <xsd:attribute name="default-serializer" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="messenger_symfony_serializer"> - <xsd:sequence> - <xsd:element name="context" type="metadata" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - <xsd:attribute name="format" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="messenger_routing"> - <xsd:choice minOccurs="0" maxOccurs="unbounded"> - <xsd:element name="sender" type="messenger_routing_sender" /> - </xsd:choice> - <xsd:attribute name="message-class" type="xsd:string" use="required"/> - </xsd:complexType> - - <xsd:complexType name="messenger_routing_sender"> - <xsd:attribute name="service" type="xsd:string" use="required"/> - </xsd:complexType> - - <xsd:complexType name="messenger_transport"> - <xsd:sequence> - <xsd:element name="options" type="metadata" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="retry-strategy" type="messenger_retry_strategy" minOccurs="0" maxOccurs="1" /> - </xsd:sequence> - <xsd:attribute name="name" type="xsd:string" /> - <xsd:attribute name="serializer" type="xsd:string" /> - <xsd:attribute name="dsn" type="xsd:string" /> - <xsd:attribute name="failure-transport" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="messenger_retry_strategy"> - <xsd:attribute name="service" type="xsd:string" /> - <xsd:attribute name="max-retries" type="xsd:integer" /> - <xsd:attribute name="delay" type="xsd:integer" /> - <xsd:attribute name="multiplier" type="xsd:float" /> - <xsd:attribute name="max-delay" type="xsd:float" /> - </xsd:complexType> - - <xsd:complexType name="messenger_bus"> - <xsd:sequence> - <xsd:element name="middleware" type="messenger_middleware" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - <xsd:attribute name="name" type="xsd:string" use="required"/> - <xsd:attribute name="default-middleware" type="default_middleware"/> - </xsd:complexType> - - <xsd:complexType name="messenger_middleware"> - <xsd:sequence> - <xsd:element name="argument" type="xsd:anyType" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - <xsd:attribute name="id" type="xsd:string" use="required"/> - </xsd:complexType> - - <xsd:complexType name="http_client"> - <xsd:sequence> - <xsd:element name="default-options" type="http_client_default_options" minOccurs="0" /> - <xsd:element name="scoped-client" type="http_client_scope_options" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - <xsd:attribute name="enabled" type="xsd:boolean" /> - <xsd:attribute name="max-host-connections" type="xsd:integer" /> - <xsd:attribute name="mock-response-factory" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="http_client_default_options" mixed="true"> - <xsd:choice maxOccurs="unbounded"> - <xsd:element name="resolve" type="http_resolve" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="header" type="http_header" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="peer-fingerprint" type="fingerprint" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="retry-failed" type="http_client_retry_failed" minOccurs="0" maxOccurs="1" /> - </xsd:choice> - <xsd:attribute name="max-redirects" type="xsd:integer" /> - <xsd:attribute name="http-version" type="xsd:string" /> - <xsd:attribute name="proxy" type="xsd:string" /> - <xsd:attribute name="no-proxy" type="xsd:string" /> - <xsd:attribute name="timeout" type="xsd:float" /> - <xsd:attribute name="max-duration" type="xsd:float" /> - <xsd:attribute name="bindto" type="xsd:string" /> - <xsd:attribute name="verify-peer" type="xsd:boolean" /> - <xsd:attribute name="verify-host" type="xsd:boolean" /> - <xsd:attribute name="cafile" type="xsd:string" /> - <xsd:attribute name="capath" type="xsd:string" /> - <xsd:attribute name="local-cert" type="xsd:string" /> - <xsd:attribute name="local-pk" type="xsd:string" /> - <xsd:attribute name="passphrase" type="xsd:string" /> - <xsd:attribute name="ciphers" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="http_client_scope_options" mixed="true"> - <xsd:choice maxOccurs="unbounded"> - <xsd:element name="query" type="http_query" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="resolve" type="http_resolve" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="header" type="http_header" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="peer-fingerprint" type="fingerprint" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="retry-failed" type="http_client_retry_failed" minOccurs="0" maxOccurs="1" /> - </xsd:choice> - <xsd:attribute name="name" type="xsd:string" /> - <xsd:attribute name="scope" type="xsd:string" /> - <xsd:attribute name="base-uri" type="xsd:string" /> - <xsd:attribute name="auth-basic" type="xsd:string" /> - <xsd:attribute name="auth-bearer" type="xsd:string" /> - <xsd:attribute name="max-redirects" type="xsd:integer" /> - <xsd:attribute name="http-version" type="xsd:string" /> - <xsd:attribute name="proxy" type="xsd:string" /> - <xsd:attribute name="no-proxy" type="xsd:string" /> - <xsd:attribute name="timeout" type="xsd:float" /> - <xsd:attribute name="bindto" type="xsd:string" /> - <xsd:attribute name="verify-peer" type="xsd:boolean" /> - <xsd:attribute name="verify-host" type="xsd:boolean" /> - <xsd:attribute name="cafile" type="xsd:string" /> - <xsd:attribute name="capath" type="xsd:string" /> - <xsd:attribute name="local-cert" type="xsd:string" /> - <xsd:attribute name="local-pk" type="xsd:string" /> - <xsd:attribute name="passphrase" type="xsd:string" /> - <xsd:attribute name="ciphers" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="fingerprint"> - <xsd:choice maxOccurs="unbounded"> - <xsd:element name="pin-sha256" type="xsd:string" minOccurs="0" /> - <xsd:element name="sha1" type="xsd:string" minOccurs="0" /> - <xsd:element name="md5" type="xsd:string" minOccurs="0" /> - </xsd:choice> - </xsd:complexType> - - <xsd:complexType name="http_client_retry_failed"> - <xsd:sequence> - <xsd:element name="http-code" type="http_client_retry_code" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - <xsd:attribute name="enabled" type="xsd:boolean" /> - <xsd:attribute name="retry-strategy" type="xsd:string" /> - <xsd:attribute name="max-retries" type="xsd:integer" /> - <xsd:attribute name="delay" type="xsd:integer" /> - <xsd:attribute name="multiplier" type="xsd:float" /> - <xsd:attribute name="max-delay" type="xsd:float" /> - <xsd:attribute name="jitter" type="xsd:float" /> - <xsd:attribute name="response_header" type="xsd:boolean" /> - </xsd:complexType> - - <xsd:complexType name="http_client_retry_code"> - <xsd:sequence> - <xsd:element name="method" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - <xsd:attribute name="code" type="xsd:integer" /> - </xsd:complexType> - - <xsd:complexType name="http_query" mixed="true"> - <xsd:attribute name="key" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="http_resolve" mixed="true"> - <xsd:attribute name="host" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="http_header" mixed="true"> - <xsd:attribute name="name" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="mailer"> - <xsd:sequence> - <xsd:element name="transport" type="mailer_transport" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="envelope" type="mailer_envelope" minOccurs="0" maxOccurs="1" /> - <xsd:element name="header" type="header" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - <xsd:attribute name="enabled" type="xsd:boolean" /> - <xsd:attribute name="dsn" type="xsd:string" /> - <xsd:attribute name="message-bus" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="header" mixed="true"> - <xsd:attribute name="name" type="xsd:string" use="required" /> - </xsd:complexType> - - <xsd:complexType name="mailer_transport" mixed="true"> - <xsd:attribute name="name" type="xsd:string" use="required" /> - </xsd:complexType> - - <xsd:complexType name="mailer_envelope"> - <xsd:sequence> - <xsd:element name="sender" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="recipients" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - </xsd:complexType> - - <xsd:complexType name="http_cache"> - <xsd:sequence> - <xsd:element name="private-header" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - - <xsd:attribute name="enabled" type="xsd:boolean" /> - <xsd:attribute name="debug" type="xsd:boolean" /> - <xsd:attribute name="trace-level" type="http_cache_trace_levels" /> - <xsd:attribute name="trace-header" type="xsd:string" /> - <xsd:attribute name="default-ttl" type="xsd:integer" /> - <xsd:attribute name="allow-reload" type="xsd:boolean" /> - <xsd:attribute name="allow-revalidate" type="xsd:boolean" /> - <xsd:attribute name="stale-while-revalidate" type="xsd:integer" /> - <xsd:attribute name="stale-if-error" type="xsd:integer" /> - </xsd:complexType> - - <xsd:simpleType name="http_cache_trace_levels"> - <xsd:restriction base="xsd:string"> - <xsd:enumeration value="none" /> - <xsd:enumeration value="short" /> - <xsd:enumeration value="full" /> - </xsd:restriction> - </xsd:simpleType> - - <xsd:complexType name="rate_limiter"> - <xsd:sequence> - <xsd:element name="limiter" type="rate_limiter_limiter" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - <xsd:attribute name="enabled" type="xsd:boolean" /> - <xsd:attribute name="max-host-connections" type="xsd:integer" /> - <xsd:attribute name="mock-response-factory" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="rate_limiter_limiter"> - <xsd:sequence> - <xsd:element name="rate" type="rate_limiter_rate" minOccurs="0" /> - </xsd:sequence> - <xsd:attribute name="name" type="xsd:string" /> - <xsd:attribute name="lock-factory" type="xsd:string" /> - <xsd:attribute name="storage-service" type="xsd:string" /> - <xsd:attribute name="cache-pool" type="xsd:string" /> - <xsd:attribute name="strategy" type="xsd:string" /> - <xsd:attribute name="limit" type="xsd:int" /> - <xsd:attribute name="interval" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="rate_limiter_rate"> - <xsd:attribute name="interval" type="xsd:string" /> - <xsd:attribute name="amount" type="xsd:int" /> - </xsd:complexType> - - <xsd:complexType name="uid"> - <xsd:attribute name="enabled" type="xsd:boolean" /> - <xsd:attribute name="default_uuid_version" type="default_uuid_version" /> - <xsd:attribute name="name_based_uuid_version" type="name_based_uuid_version" /> - <xsd:attribute name="time_based_uuid_version" type="time_based_uuid_version" /> - <xsd:attribute name="name_based_uuid_namespace" type="xsd:string" /> - <xsd:attribute name="time_based_uuid_node" type="xsd:string" /> - </xsd:complexType> - - <xsd:simpleType name="default_uuid_version"> - <xsd:restriction base="xsd:int"> - <xsd:enumeration value="6" /> - <xsd:enumeration value="4" /> - <xsd:enumeration value="1" /> - </xsd:restriction> - </xsd:simpleType> - - <xsd:simpleType name="name_based_uuid_version"> - <xsd:restriction base="xsd:int"> - <xsd:enumeration value="5" /> - <xsd:enumeration value="3" /> - </xsd:restriction> - </xsd:simpleType> - - <xsd:simpleType name="time_based_uuid_version"> - <xsd:restriction base="xsd:int"> - <xsd:enumeration value="6" /> - <xsd:enumeration value="1" /> - </xsd:restriction> - </xsd:simpleType> - - <xsd:complexType name="notifier"> - <xsd:sequence> - <xsd:element name="chatter-transport" type="chatter-transport" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="texter-transport" type="texter-transport" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="channel-policy" type="channel-policy" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="admin-recipients" type="admin-recipients" minOccurs="0" maxOccurs="1" /> - </xsd:sequence> - <xsd:attribute name="enabled" type="xsd:boolean" /> - <xsd:attribute name="notification-on-failed-messages" type="xsd:boolean" /> - <xsd:attribute name="message-bus" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="chatter-transport" mixed="true"> - <xsd:attribute name="name" type="xsd:string" use="required"/> - </xsd:complexType> - - <xsd:complexType name="texter-transport" mixed="true"> - <xsd:attribute name="name" type="xsd:string" use="required"/> - </xsd:complexType> - - <xsd:complexType name="channel-policy" mixed="true"> - <xsd:sequence> - <xsd:element name="channel" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - <xsd:attribute name="name" type="xsd:string" use="required" /> - </xsd:complexType> - - <xsd:complexType name="admin-recipients" mixed="true"> - <xsd:sequence> - <xsd:element name="admin-recipient" type="admin-recipient" minOccurs="1" maxOccurs="unbounded" /> - </xsd:sequence> - </xsd:complexType> - - <xsd:complexType name="admin-recipient" mixed="true"> - <xsd:attribute name="email" type="xsd:string" use="required" /> - <xsd:attribute name="phone" type="xsd:string" /> - </xsd:complexType> -</xsd:schema> diff --git a/lib/symfony/framework-bundle/Resources/config/secrets.php b/lib/symfony/framework-bundle/Resources/config/secrets.php deleted file mode 100644 index a21d28270..000000000 --- a/lib/symfony/framework-bundle/Resources/config/secrets.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Bundle\FrameworkBundle\Secrets\DotenvVault; -use Symfony\Bundle\FrameworkBundle\Secrets\SodiumVault; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('secrets.vault', SodiumVault::class) - ->args([ - abstract_arg('Secret dir, set in FrameworkExtension'), - service('secrets.decryption_key')->ignoreOnInvalid(), - ]) - ->tag('container.env_var_loader') - - ->set('secrets.decryption_key') - ->parent('container.env') - ->args([abstract_arg('Decryption env var, set in FrameworkExtension')]) - - ->set('secrets.local_vault', DotenvVault::class) - ->args([abstract_arg('.env file path, set in FrameworkExtension')]) - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/security_csrf.php b/lib/symfony/framework-bundle/Resources/config/security_csrf.php deleted file mode 100644 index 9644d5b44..000000000 --- a/lib/symfony/framework-bundle/Resources/config/security_csrf.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Bridge\Twig\Extension\CsrfExtension; -use Symfony\Bridge\Twig\Extension\CsrfRuntime; -use Symfony\Component\Security\Csrf\CsrfTokenManager; -use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; -use Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface; -use Symfony\Component\Security\Csrf\TokenGenerator\UriSafeTokenGenerator; -use Symfony\Component\Security\Csrf\TokenStorage\SessionTokenStorage; -use Symfony\Component\Security\Csrf\TokenStorage\TokenStorageInterface; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('security.csrf.token_generator', UriSafeTokenGenerator::class) - - ->alias(TokenGeneratorInterface::class, 'security.csrf.token_generator') - - ->set('security.csrf.token_storage', SessionTokenStorage::class) - ->args([service('request_stack')]) - - ->alias(TokenStorageInterface::class, 'security.csrf.token_storage') - - ->set('security.csrf.token_manager', CsrfTokenManager::class) - ->public() - ->args([ - service('security.csrf.token_generator'), - service('security.csrf.token_storage'), - service('request_stack')->ignoreOnInvalid(), - ]) - ->tag('container.private', ['package' => 'symfony/framework-bundle', 'version' => '5.2']) - - ->alias(CsrfTokenManagerInterface::class, 'security.csrf.token_manager') - - ->set('twig.runtime.security_csrf', CsrfRuntime::class) - ->args([service('security.csrf.token_manager')]) - ->tag('twig.runtime') - - ->set('twig.extension.security_csrf', CsrfExtension::class) - ->tag('twig.extension') - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/serializer.php b/lib/symfony/framework-bundle/Resources/config/serializer.php deleted file mode 100644 index ca0cf9b53..000000000 --- a/lib/symfony/framework-bundle/Resources/config/serializer.php +++ /dev/null @@ -1,222 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Bundle\FrameworkBundle\CacheWarmer\SerializerCacheWarmer; -use Symfony\Component\Cache\Adapter\PhpArrayAdapter; -use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer; -use Symfony\Component\ErrorHandler\ErrorRenderer\SerializerErrorRenderer; -use Symfony\Component\PropertyInfo\Extractor\SerializerExtractor; -use Symfony\Component\Serializer\Encoder\CsvEncoder; -use Symfony\Component\Serializer\Encoder\DecoderInterface; -use Symfony\Component\Serializer\Encoder\EncoderInterface; -use Symfony\Component\Serializer\Encoder\JsonEncoder; -use Symfony\Component\Serializer\Encoder\XmlEncoder; -use Symfony\Component\Serializer\Encoder\YamlEncoder; -use Symfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata; -use Symfony\Component\Serializer\Mapping\ClassDiscriminatorResolverInterface; -use Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory; -use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; -use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; -use Symfony\Component\Serializer\Mapping\Loader\LoaderChain; -use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; -use Symfony\Component\Serializer\NameConverter\MetadataAwareNameConverter; -use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer; -use Symfony\Component\Serializer\Normalizer\BackedEnumNormalizer; -use Symfony\Component\Serializer\Normalizer\ConstraintViolationListNormalizer; -use Symfony\Component\Serializer\Normalizer\DataUriNormalizer; -use Symfony\Component\Serializer\Normalizer\DateIntervalNormalizer; -use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; -use Symfony\Component\Serializer\Normalizer\DateTimeZoneNormalizer; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; -use Symfony\Component\Serializer\Normalizer\FormErrorNormalizer; -use Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer; -use Symfony\Component\Serializer\Normalizer\MimeMessageNormalizer; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; -use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; -use Symfony\Component\Serializer\Normalizer\ProblemNormalizer; -use Symfony\Component\Serializer\Normalizer\PropertyNormalizer; -use Symfony\Component\Serializer\Normalizer\UidNormalizer; -use Symfony\Component\Serializer\Normalizer\UnwrappingDenormalizer; -use Symfony\Component\Serializer\Serializer; -use Symfony\Component\Serializer\SerializerInterface; - -return static function (ContainerConfigurator $container) { - $container->parameters() - ->set('serializer.mapping.cache.file', '%kernel.cache_dir%/serialization.php') - ; - - $container->services() - ->set('serializer', Serializer::class) - ->public() - ->args([[], []]) - ->tag('container.private', ['package' => 'symfony/framework-bundle', 'version' => '5.2']) - - ->alias(SerializerInterface::class, 'serializer') - ->alias(NormalizerInterface::class, 'serializer') - ->alias(DenormalizerInterface::class, 'serializer') - ->alias(EncoderInterface::class, 'serializer') - ->alias(DecoderInterface::class, 'serializer') - - ->alias('serializer.property_accessor', 'property_accessor') - - // Discriminator Map - ->set('serializer.mapping.class_discriminator_resolver', ClassDiscriminatorFromClassMetadata::class) - ->args([service('serializer.mapping.class_metadata_factory')]) - - ->alias(ClassDiscriminatorResolverInterface::class, 'serializer.mapping.class_discriminator_resolver') - - // Normalizer - ->set('serializer.normalizer.constraint_violation_list', ConstraintViolationListNormalizer::class) - ->args([1 => service('serializer.name_converter.metadata_aware')]) - ->autowire(true) - ->tag('serializer.normalizer', ['priority' => -915]) - - ->set('serializer.normalizer.mime_message', MimeMessageNormalizer::class) - ->args([service('serializer.normalizer.property')]) - ->tag('serializer.normalizer', ['priority' => -915]) - - ->set('serializer.normalizer.datetimezone', DateTimeZoneNormalizer::class) - ->tag('serializer.normalizer', ['priority' => -915]) - - ->set('serializer.normalizer.dateinterval', DateIntervalNormalizer::class) - ->tag('serializer.normalizer', ['priority' => -915]) - - ->set('serializer.normalizer.data_uri', DataUriNormalizer::class) - ->args([service('mime_types')->nullOnInvalid()]) - ->tag('serializer.normalizer', ['priority' => -920]) - - ->set('serializer.normalizer.datetime', DateTimeNormalizer::class) - ->tag('serializer.normalizer', ['priority' => -910]) - - ->set('serializer.normalizer.json_serializable', JsonSerializableNormalizer::class) - ->args([null, null]) - ->tag('serializer.normalizer', ['priority' => -950]) - - ->set('serializer.normalizer.problem', ProblemNormalizer::class) - ->args([param('kernel.debug')]) - ->tag('serializer.normalizer', ['priority' => -890]) - - ->set('serializer.denormalizer.unwrapping', UnwrappingDenormalizer::class) - ->args([service('serializer.property_accessor')]) - ->tag('serializer.normalizer', ['priority' => 1000]) - - ->set('serializer.normalizer.uid', UidNormalizer::class) - ->tag('serializer.normalizer', ['priority' => -890]) - - ->set('serializer.normalizer.form_error', FormErrorNormalizer::class) - ->tag('serializer.normalizer', ['priority' => -915]) - - ->set('serializer.normalizer.object', ObjectNormalizer::class) - ->args([ - service('serializer.mapping.class_metadata_factory'), - service('serializer.name_converter.metadata_aware'), - service('serializer.property_accessor'), - service('property_info')->ignoreOnInvalid(), - service('serializer.mapping.class_discriminator_resolver')->ignoreOnInvalid(), - null, - ]) - ->tag('serializer.normalizer', ['priority' => -1000]) - - ->alias(ObjectNormalizer::class, 'serializer.normalizer.object') - - ->set('serializer.normalizer.property', PropertyNormalizer::class) - ->args([ - service('serializer.mapping.class_metadata_factory'), - service('serializer.name_converter.metadata_aware'), - service('property_info')->ignoreOnInvalid(), - service('serializer.mapping.class_discriminator_resolver')->ignoreOnInvalid(), - null, - ]) - - ->alias(PropertyNormalizer::class, 'serializer.normalizer.property') - - ->set('serializer.denormalizer.array', ArrayDenormalizer::class) - ->tag('serializer.normalizer', ['priority' => -990]) - - // Loader - ->set('serializer.mapping.chain_loader', LoaderChain::class) - ->args([[]]) - - // Class Metadata Factory - ->set('serializer.mapping.class_metadata_factory', ClassMetadataFactory::class) - ->args([service('serializer.mapping.chain_loader')]) - - ->alias(ClassMetadataFactoryInterface::class, 'serializer.mapping.class_metadata_factory') - - // Cache - ->set('serializer.mapping.cache_warmer', SerializerCacheWarmer::class) - ->args([abstract_arg('The serializer metadata loaders'), param('serializer.mapping.cache.file')]) - ->tag('kernel.cache_warmer') - - ->set('serializer.mapping.cache.symfony', CacheItemPoolInterface::class) - ->factory([PhpArrayAdapter::class, 'create']) - ->args([param('serializer.mapping.cache.file'), service('cache.serializer')]) - - ->set('serializer.mapping.cache_class_metadata_factory', CacheClassMetadataFactory::class) - ->decorate('serializer.mapping.class_metadata_factory') - ->args([ - service('serializer.mapping.cache_class_metadata_factory.inner'), - service('serializer.mapping.cache.symfony'), - ]) - - // Encoders - ->set('serializer.encoder.xml', XmlEncoder::class) - ->tag('serializer.encoder') - - ->set('serializer.encoder.json', JsonEncoder::class) - ->args([null, null]) - ->tag('serializer.encoder') - - ->set('serializer.encoder.yaml', YamlEncoder::class) - ->args([null, null]) - ->tag('serializer.encoder') - - ->set('serializer.encoder.csv', CsvEncoder::class) - ->tag('serializer.encoder') - - // Name converter - ->set('serializer.name_converter.camel_case_to_snake_case', CamelCaseToSnakeCaseNameConverter::class) - - ->set('serializer.name_converter.metadata_aware', MetadataAwareNameConverter::class) - ->args([service('serializer.mapping.class_metadata_factory')]) - - // PropertyInfo extractor - ->set('property_info.serializer_extractor', SerializerExtractor::class) - ->args([service('serializer.mapping.class_metadata_factory')]) - ->tag('property_info.list_extractor', ['priority' => -999]) - - // ErrorRenderer integration - ->alias('error_renderer', 'error_renderer.serializer') - ->alias('error_renderer.serializer', 'error_handler.error_renderer.serializer') - - ->set('error_handler.error_renderer.serializer', SerializerErrorRenderer::class) - ->args([ - service('serializer'), - inline_service() - ->factory([SerializerErrorRenderer::class, 'getPreferredFormat']) - ->args([service('request_stack')]), - service('error_renderer.html'), - inline_service() - ->factory([HtmlErrorRenderer::class, 'isDebug']) - ->args([service('request_stack'), param('kernel.debug')]), - ]) - ; - - if (interface_exists(\BackedEnum::class)) { - $container->services() - ->set('serializer.normalizer.backed_enum', BackedEnumNormalizer::class) - ->tag('serializer.normalizer', ['priority' => -915]) - ; - } -}; diff --git a/lib/symfony/framework-bundle/Resources/config/services.php b/lib/symfony/framework-bundle/Resources/config/services.php deleted file mode 100644 index a26dfb5ad..000000000 --- a/lib/symfony/framework-bundle/Resources/config/services.php +++ /dev/null @@ -1,218 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Bundle\FrameworkBundle\CacheWarmer\ConfigBuilderCacheWarmer; -use Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache; -use Symfony\Component\Config\Resource\SelfCheckingResourceChecker; -use Symfony\Component\Config\ResourceCheckerConfigCacheFactory; -use Symfony\Component\Console\ConsoleEvents; -use Symfony\Component\DependencyInjection\Config\ContainerParametersResourceChecker; -use Symfony\Component\DependencyInjection\EnvVarProcessor; -use Symfony\Component\DependencyInjection\ParameterBag\ContainerBag; -use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; -use Symfony\Component\DependencyInjection\ReverseContainer; -use Symfony\Component\EventDispatcher\EventDispatcher; -use Symfony\Component\EventDispatcher\EventDispatcherInterface as EventDispatcherInterfaceComponentAlias; -use Symfony\Component\Filesystem\Filesystem; -use Symfony\Component\Form\FormEvents; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\UrlHelper; -use Symfony\Component\HttpKernel\CacheClearer\ChainCacheClearer; -use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate; -use Symfony\Component\HttpKernel\Config\FileLocator; -use Symfony\Component\HttpKernel\DependencyInjection\ServicesResetter; -use Symfony\Component\HttpKernel\EventListener\LocaleAwareListener; -use Symfony\Component\HttpKernel\HttpCache\Store; -use Symfony\Component\HttpKernel\HttpCache\StoreInterface; -use Symfony\Component\HttpKernel\HttpKernel; -use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\HttpKernel\KernelInterface; -use Symfony\Component\HttpKernel\UriSigner; -use Symfony\Component\Runtime\Runner\Symfony\HttpKernelRunner; -use Symfony\Component\Runtime\Runner\Symfony\ResponseRunner; -use Symfony\Component\Runtime\SymfonyRuntime; -use Symfony\Component\String\LazyString; -use Symfony\Component\String\Slugger\AsciiSlugger; -use Symfony\Component\String\Slugger\SluggerInterface; -use Symfony\Component\Workflow\WorkflowEvents; -use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; - -return static function (ContainerConfigurator $container) { - // this parameter is used at compile time in RegisterListenersPass - $container->parameters()->set('event_dispatcher.event_aliases', array_merge( - class_exists(ConsoleEvents::class) ? ConsoleEvents::ALIASES : [], - class_exists(FormEvents::class) ? FormEvents::ALIASES : [], - KernelEvents::ALIASES, - class_exists(WorkflowEvents::class) ? WorkflowEvents::ALIASES : [] - )); - - $container->services() - - ->set('parameter_bag', ContainerBag::class) - ->args([ - service('service_container'), - ]) - ->alias(ContainerBagInterface::class, 'parameter_bag') - ->alias(ParameterBagInterface::class, 'parameter_bag') - - ->set('event_dispatcher', EventDispatcher::class) - ->public() - ->tag('container.hot_path') - ->tag('event_dispatcher.dispatcher', ['name' => 'event_dispatcher']) - ->alias(EventDispatcherInterfaceComponentAlias::class, 'event_dispatcher') - ->alias(EventDispatcherInterface::class, 'event_dispatcher') - - ->set('http_kernel', HttpKernel::class) - ->public() - ->args([ - service('event_dispatcher'), - service('controller_resolver'), - service('request_stack'), - service('argument_resolver'), - ]) - ->tag('container.hot_path') - ->tag('container.preload', ['class' => HttpKernelRunner::class]) - ->tag('container.preload', ['class' => ResponseRunner::class]) - ->tag('container.preload', ['class' => SymfonyRuntime::class]) - ->alias(HttpKernelInterface::class, 'http_kernel') - - ->set('request_stack', RequestStack::class) - ->public() - ->alias(RequestStack::class, 'request_stack') - - ->set('http_cache', HttpCache::class) - ->args([ - service('kernel'), - service('http_cache.store'), - service('esi')->nullOnInvalid(), - abstract_arg('options'), - ]) - ->tag('container.hot_path') - - ->set('http_cache.store', Store::class) - ->args([ - param('kernel.cache_dir').'/http_cache', - ]) - ->alias(StoreInterface::class, 'http_cache.store') - - ->set('url_helper', UrlHelper::class) - ->args([ - service('request_stack'), - service('router.request_context')->ignoreOnInvalid(), - ]) - ->alias(UrlHelper::class, 'url_helper') - - ->set('cache_warmer', CacheWarmerAggregate::class) - ->public() - ->args([ - tagged_iterator('kernel.cache_warmer'), - param('kernel.debug'), - sprintf('%s/%sDeprecations.log', param('kernel.build_dir'), param('kernel.container_class')), - ]) - ->tag('container.no_preload') - - ->set('cache_clearer', ChainCacheClearer::class) - ->public() - ->args([ - tagged_iterator('kernel.cache_clearer'), - ]) - ->tag('container.private', ['package' => 'symfony/framework-bundle', 'version' => '5.2']) - - ->set('kernel') - ->synthetic() - ->public() - ->alias(KernelInterface::class, 'kernel') - - ->set('filesystem', Filesystem::class) - ->public() - ->tag('container.private', ['package' => 'symfony/framework-bundle', 'version' => '5.2']) - ->alias(Filesystem::class, 'filesystem') - - ->set('file_locator', FileLocator::class) - ->args([ - service('kernel'), - ]) - ->alias(FileLocator::class, 'file_locator') - - ->set('uri_signer', UriSigner::class) - ->args([ - param('kernel.secret'), - ]) - ->alias(UriSigner::class, 'uri_signer') - - ->set('config_cache_factory', ResourceCheckerConfigCacheFactory::class) - ->args([ - tagged_iterator('config_cache.resource_checker'), - ]) - - ->set('dependency_injection.config.container_parameters_resource_checker', ContainerParametersResourceChecker::class) - ->args([ - service('service_container'), - ]) - ->tag('config_cache.resource_checker', ['priority' => -980]) - - ->set('config.resource.self_checking_resource_checker', SelfCheckingResourceChecker::class) - ->tag('config_cache.resource_checker', ['priority' => -990]) - - ->set('services_resetter', ServicesResetter::class) - ->public() - - ->set('reverse_container', ReverseContainer::class) - ->args([ - service('service_container'), - service_locator([]), - ]) - ->alias(ReverseContainer::class, 'reverse_container') - - ->set('locale_aware_listener', LocaleAwareListener::class) - ->args([ - [], // locale aware services - service('request_stack'), - ]) - ->tag('kernel.event_subscriber') - - ->set('container.env_var_processor', EnvVarProcessor::class) - ->args([ - service('service_container'), - tagged_iterator('container.env_var_loader'), - ]) - ->tag('container.env_var_processor') - - ->set('slugger', AsciiSlugger::class) - ->args([ - param('kernel.default_locale'), - ]) - ->tag('kernel.locale_aware') - ->alias(SluggerInterface::class, 'slugger') - - ->set('container.getenv', \Closure::class) - ->factory([\Closure::class, 'fromCallable']) - ->args([ - [service('service_container'), 'getEnv'], - ]) - ->tag('routing.expression_language_function', ['function' => 'env']) - - // inherit from this service to lazily access env vars - ->set('container.env', LazyString::class) - ->abstract() - ->factory([LazyString::class, 'fromCallable']) - ->args([ - service('container.getenv'), - ]) - ->set('config_builder.warmer', ConfigBuilderCacheWarmer::class) - ->args([service(KernelInterface::class), service('logger')->nullOnInvalid()]) - ->tag('kernel.cache_warmer') - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/session.php b/lib/symfony/framework-bundle/Resources/config/session.php deleted file mode 100644 index 43c0000dd..000000000 --- a/lib/symfony/framework-bundle/Resources/config/session.php +++ /dev/null @@ -1,174 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Bundle\FrameworkBundle\Session\DeprecatedSessionFactory; -use Symfony\Bundle\FrameworkBundle\Session\ServiceSessionFactory; -use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; -use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; -use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface; -use Symfony\Component\HttpFoundation\Session\Session; -use Symfony\Component\HttpFoundation\Session\SessionFactory; -use Symfony\Component\HttpFoundation\Session\SessionInterface; -use Symfony\Component\HttpFoundation\Session\Storage\Handler\AbstractSessionHandler; -use Symfony\Component\HttpFoundation\Session\Storage\Handler\IdentityMarshaller; -use Symfony\Component\HttpFoundation\Session\Storage\Handler\MarshallingSessionHandler; -use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler; -use Symfony\Component\HttpFoundation\Session\Storage\Handler\SessionHandlerFactory; -use Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler; -use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag; -use Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorage; -use Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorageFactory; -use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; -use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorageFactory; -use Symfony\Component\HttpFoundation\Session\Storage\PhpBridgeSessionStorage; -use Symfony\Component\HttpFoundation\Session\Storage\PhpBridgeSessionStorageFactory; -use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface; -use Symfony\Component\HttpKernel\EventListener\SessionListener; - -return static function (ContainerConfigurator $container) { - $container->parameters()->set('session.metadata.storage_key', '_sf2_meta'); - - $container->services() - ->set('.session.do-not-use', Session::class) // to be removed in 6.0 - ->factory([service('session.factory'), 'createSession']) - ->set('session.factory', SessionFactory::class) - ->args([ - service('request_stack'), - service('session.storage.factory'), - [service('session_listener'), 'onSessionUsage'], - ]) - - ->set('session.storage.factory.native', NativeSessionStorageFactory::class) - ->args([ - param('session.storage.options'), - service('session.handler'), - inline_service(MetadataBag::class) - ->args([ - param('session.metadata.storage_key'), - param('session.metadata.update_threshold'), - ]), - false, - ]) - ->set('session.storage.factory.php_bridge', PhpBridgeSessionStorageFactory::class) - ->args([ - service('session.handler'), - inline_service(MetadataBag::class) - ->args([ - param('session.metadata.storage_key'), - param('session.metadata.update_threshold'), - ]), - false, - ]) - ->set('session.storage.factory.mock_file', MockFileSessionStorageFactory::class) - ->args([ - param('kernel.cache_dir').'/sessions', - 'MOCKSESSID', - inline_service(MetadataBag::class) - ->args([ - param('session.metadata.storage_key'), - param('session.metadata.update_threshold'), - ]), - ]) - ->set('session.storage.factory.service', ServiceSessionFactory::class) - ->args([ - service('session.storage'), - ]) - ->deprecate('symfony/framework-bundle', '5.3', 'The "%service_id%" service is deprecated, use "session.storage.factory.native", "session.storage.factory.php_bridge" or "session.storage.factory.mock_file" instead.') - - ->set('.session.deprecated', SessionInterface::class) // to be removed in 6.0 - ->factory([inline_service(DeprecatedSessionFactory::class)->args([service('request_stack')]), 'getSession']) - ->alias(SessionInterface::class, '.session.do-not-use') - ->deprecate('symfony/framework-bundle', '5.3', 'The "%alias_id%" and "SessionInterface" aliases are deprecated, use "$requestStack->getSession()" instead.') - ->alias(SessionStorageInterface::class, 'session.storage') - ->deprecate('symfony/framework-bundle', '5.3', 'The "%alias_id%" alias is deprecated, use "session.storage.factory" instead.') - ->alias(\SessionHandlerInterface::class, 'session.handler') - - ->set('session.storage.metadata_bag', MetadataBag::class) - ->args([ - param('session.metadata.storage_key'), - param('session.metadata.update_threshold'), - ]) - ->deprecate('symfony/framework-bundle', '5.3', 'The "%service_id%" service is deprecated, create your own "session.storage.factory" instead.') - - ->set('session.storage.native', NativeSessionStorage::class) - ->args([ - param('session.storage.options'), - service('session.handler'), - service('session.storage.metadata_bag'), - ]) - ->deprecate('symfony/framework-bundle', '5.3', 'The "%service_id%" service is deprecated, use "session.storage.factory.native" instead.') - - ->set('session.storage.php_bridge', PhpBridgeSessionStorage::class) - ->args([ - service('session.handler'), - service('session.storage.metadata_bag'), - ]) - ->deprecate('symfony/framework-bundle', '5.3', 'The "%service_id%" service is deprecated, use "session.storage.factory.php_bridge" instead.') - - ->set('session.flash_bag', FlashBag::class) - ->factory([service('.session.do-not-use'), 'getFlashBag']) - ->deprecate('symfony/framework-bundle', '5.1', 'The "%service_id%" service is deprecated, use "$session->getFlashBag()" instead.') - ->alias(FlashBagInterface::class, 'session.flash_bag') - - ->set('session.attribute_bag', AttributeBag::class) - ->factory([service('.session.do-not-use'), 'getBag']) - ->args(['attributes']) - ->deprecate('symfony/framework-bundle', '5.1', 'The "%service_id%" service is deprecated, use "$session->getAttributeBag()" instead.') - - ->set('session.storage.mock_file', MockFileSessionStorage::class) - ->args([ - param('kernel.cache_dir').'/sessions', - 'MOCKSESSID', - service('session.storage.metadata_bag'), - ]) - ->deprecate('symfony/framework-bundle', '5.3', 'The "%service_id%" service is deprecated, use "session.storage.factory.mock_file" instead.') - - ->set('session.handler.native_file', StrictSessionHandler::class) - ->args([ - inline_service(NativeFileSessionHandler::class) - ->args([param('session.save_path')]), - ]) - - ->set('session.abstract_handler', AbstractSessionHandler::class) - ->factory([SessionHandlerFactory::class, 'createHandler']) - ->args([abstract_arg('A string or a connection object')]) - - ->set('session_listener', SessionListener::class) - ->args([ - service_locator([ - 'session_factory' => service('session.factory')->ignoreOnInvalid(), - 'session' => service('.session.do-not-use')->ignoreOnInvalid(), - 'initialized_session' => service('.session.do-not-use')->ignoreOnUninitialized(), - 'logger' => service('logger')->ignoreOnInvalid(), - 'session_collector' => service('data_collector.request.session_collector')->ignoreOnInvalid(), - ]), - param('kernel.debug'), - param('session.storage.options'), - ]) - ->tag('kernel.event_subscriber') - ->tag('kernel.reset', ['method' => 'reset']) - - // for BC - ->alias('session.storage.filesystem', 'session.storage.mock_file') - ->deprecate('symfony/framework-bundle', '5.3', 'The "%alias_id%" alias is deprecated, use "session.storage.factory.mock_file" instead.') - - ->set('session.marshaller', IdentityMarshaller::class) - - ->set('session.marshalling_handler', MarshallingSessionHandler::class) - ->decorate('session.handler') - ->args([ - service('session.marshalling_handler.inner'), - service('session.marshaller'), - ]) - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/ssi.php b/lib/symfony/framework-bundle/Resources/config/ssi.php deleted file mode 100644 index d41aa74d1..000000000 --- a/lib/symfony/framework-bundle/Resources/config/ssi.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\HttpKernel\EventListener\SurrogateListener; -use Symfony\Component\HttpKernel\HttpCache\Ssi; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('ssi', Ssi::class) - - ->set('ssi_listener', SurrogateListener::class) - ->args([service('ssi')->ignoreOnInvalid()]) - ->tag('kernel.event_subscriber') - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/test.php b/lib/symfony/framework-bundle/Resources/config/test.php deleted file mode 100644 index 76709595b..000000000 --- a/lib/symfony/framework-bundle/Resources/config/test.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Bundle\FrameworkBundle\KernelBrowser; -use Symfony\Bundle\FrameworkBundle\Test\TestContainer; -use Symfony\Component\BrowserKit\CookieJar; -use Symfony\Component\BrowserKit\History; -use Symfony\Component\DependencyInjection\ServiceLocator; -use Symfony\Component\HttpKernel\EventListener\SessionListener; - -return static function (ContainerConfigurator $container) { - $container->parameters()->set('test.client.parameters', []); - - $container->services() - ->set('test.client', KernelBrowser::class) - ->args([ - service('kernel'), - param('test.client.parameters'), - service('test.client.history'), - service('test.client.cookiejar'), - ]) - ->share(false) - ->public() - - ->set('test.client.history', History::class)->share(false) - ->set('test.client.cookiejar', CookieJar::class)->share(false) - - ->set('test.session.listener', SessionListener::class) - ->args([ - service_locator([ - 'session' => service('.session.do-not-use')->ignoreOnInvalid(), - 'session_factory' => service('session.factory')->ignoreOnInvalid(), - ]), - param('kernel.debug'), - param('session.storage.options'), - ]) - ->tag('kernel.event_subscriber') - - ->set('test.service_container', TestContainer::class) - ->args([ - service('kernel'), - 'test.private_services_locator', - ]) - ->public() - - ->set('test.private_services_locator', ServiceLocator::class) - ->args([abstract_arg('callable collection')]) - ->public() - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/translation.php b/lib/symfony/framework-bundle/Resources/config/translation.php deleted file mode 100644 index 706e4928e..000000000 --- a/lib/symfony/framework-bundle/Resources/config/translation.php +++ /dev/null @@ -1,162 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Psr\Container\ContainerInterface; -use Symfony\Bundle\FrameworkBundle\CacheWarmer\TranslationsCacheWarmer; -use Symfony\Bundle\FrameworkBundle\Translation\Translator; -use Symfony\Component\Translation\Dumper\CsvFileDumper; -use Symfony\Component\Translation\Dumper\IcuResFileDumper; -use Symfony\Component\Translation\Dumper\IniFileDumper; -use Symfony\Component\Translation\Dumper\JsonFileDumper; -use Symfony\Component\Translation\Dumper\MoFileDumper; -use Symfony\Component\Translation\Dumper\PhpFileDumper; -use Symfony\Component\Translation\Dumper\PoFileDumper; -use Symfony\Component\Translation\Dumper\QtFileDumper; -use Symfony\Component\Translation\Dumper\XliffFileDumper; -use Symfony\Component\Translation\Dumper\YamlFileDumper; -use Symfony\Component\Translation\Extractor\ChainExtractor; -use Symfony\Component\Translation\Extractor\ExtractorInterface; -use Symfony\Component\Translation\Extractor\PhpExtractor; -use Symfony\Component\Translation\Formatter\MessageFormatter; -use Symfony\Component\Translation\Loader\CsvFileLoader; -use Symfony\Component\Translation\Loader\IcuDatFileLoader; -use Symfony\Component\Translation\Loader\IcuResFileLoader; -use Symfony\Component\Translation\Loader\IniFileLoader; -use Symfony\Component\Translation\Loader\JsonFileLoader; -use Symfony\Component\Translation\Loader\MoFileLoader; -use Symfony\Component\Translation\Loader\PhpFileLoader; -use Symfony\Component\Translation\Loader\PoFileLoader; -use Symfony\Component\Translation\Loader\QtFileLoader; -use Symfony\Component\Translation\Loader\XliffFileLoader; -use Symfony\Component\Translation\Loader\YamlFileLoader; -use Symfony\Component\Translation\LoggingTranslator; -use Symfony\Component\Translation\Reader\TranslationReader; -use Symfony\Component\Translation\Reader\TranslationReaderInterface; -use Symfony\Component\Translation\Writer\TranslationWriter; -use Symfony\Component\Translation\Writer\TranslationWriterInterface; -use Symfony\Contracts\Translation\TranslatorInterface; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('translator.default', Translator::class) - ->args([ - abstract_arg('translation loaders locator'), - service('translator.formatter'), - param('kernel.default_locale'), - abstract_arg('translation loaders ids'), - [ - 'cache_dir' => param('kernel.cache_dir').'/translations', - 'debug' => param('kernel.debug'), - ], - abstract_arg('enabled locales'), - ]) - ->call('setConfigCacheFactory', [service('config_cache_factory')]) - ->tag('kernel.locale_aware') - - ->alias(TranslatorInterface::class, 'translator') - - ->set('translator.logging', LoggingTranslator::class) - ->args([ - service('translator.logging.inner'), - service('logger'), - ]) - ->tag('monolog.logger', ['channel' => 'translation']) - - ->set('translator.formatter.default', MessageFormatter::class) - ->args([service('identity_translator')]) - - ->set('translation.loader.php', PhpFileLoader::class) - ->tag('translation.loader', ['alias' => 'php']) - - ->set('translation.loader.yml', YamlFileLoader::class) - ->tag('translation.loader', ['alias' => 'yaml', 'legacy-alias' => 'yml']) - - ->set('translation.loader.xliff', XliffFileLoader::class) - ->tag('translation.loader', ['alias' => 'xlf', 'legacy-alias' => 'xliff']) - - ->set('translation.loader.po', PoFileLoader::class) - ->tag('translation.loader', ['alias' => 'po']) - - ->set('translation.loader.mo', MoFileLoader::class) - ->tag('translation.loader', ['alias' => 'mo']) - - ->set('translation.loader.qt', QtFileLoader::class) - ->tag('translation.loader', ['alias' => 'ts']) - - ->set('translation.loader.csv', CsvFileLoader::class) - ->tag('translation.loader', ['alias' => 'csv']) - - ->set('translation.loader.res', IcuResFileLoader::class) - ->tag('translation.loader', ['alias' => 'res']) - - ->set('translation.loader.dat', IcuDatFileLoader::class) - ->tag('translation.loader', ['alias' => 'dat']) - - ->set('translation.loader.ini', IniFileLoader::class) - ->tag('translation.loader', ['alias' => 'ini']) - - ->set('translation.loader.json', JsonFileLoader::class) - ->tag('translation.loader', ['alias' => 'json']) - - ->set('translation.dumper.php', PhpFileDumper::class) - ->tag('translation.dumper', ['alias' => 'php']) - - ->set('translation.dumper.xliff', XliffFileDumper::class) - ->tag('translation.dumper', ['alias' => 'xlf']) - - ->set('translation.dumper.po', PoFileDumper::class) - ->tag('translation.dumper', ['alias' => 'po']) - - ->set('translation.dumper.mo', MoFileDumper::class) - ->tag('translation.dumper', ['alias' => 'mo']) - - ->set('translation.dumper.yml', YamlFileDumper::class) - ->tag('translation.dumper', ['alias' => 'yml']) - - ->set('translation.dumper.yaml', YamlFileDumper::class) - ->args(['yaml']) - ->tag('translation.dumper', ['alias' => 'yaml']) - - ->set('translation.dumper.qt', QtFileDumper::class) - ->tag('translation.dumper', ['alias' => 'ts']) - - ->set('translation.dumper.csv', CsvFileDumper::class) - ->tag('translation.dumper', ['alias' => 'csv']) - - ->set('translation.dumper.ini', IniFileDumper::class) - ->tag('translation.dumper', ['alias' => 'ini']) - - ->set('translation.dumper.json', JsonFileDumper::class) - ->tag('translation.dumper', ['alias' => 'json']) - - ->set('translation.dumper.res', IcuResFileDumper::class) - ->tag('translation.dumper', ['alias' => 'res']) - - ->set('translation.extractor.php', PhpExtractor::class) - ->tag('translation.extractor', ['alias' => 'php']) - - ->set('translation.reader', TranslationReader::class) - ->alias(TranslationReaderInterface::class, 'translation.reader') - - ->set('translation.extractor', ChainExtractor::class) - ->alias(ExtractorInterface::class, 'translation.extractor') - - ->set('translation.writer', TranslationWriter::class) - ->alias(TranslationWriterInterface::class, 'translation.writer') - - ->set('translation.warmer', TranslationsCacheWarmer::class) - ->args([service(ContainerInterface::class)]) - ->tag('container.service_subscriber', ['id' => 'translator']) - ->tag('kernel.cache_warmer') - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/translation_debug.php b/lib/symfony/framework-bundle/Resources/config/translation_debug.php deleted file mode 100644 index 7a8330181..000000000 --- a/lib/symfony/framework-bundle/Resources/config/translation_debug.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\Translation\DataCollector\TranslationDataCollector; -use Symfony\Component\Translation\DataCollectorTranslator; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('translator.data_collector', DataCollectorTranslator::class) - ->args([service('translator.data_collector.inner')]) - - ->set('data_collector.translation', TranslationDataCollector::class) - ->args([service('translator.data_collector')]) - ->tag('data_collector', [ - 'template' => '@WebProfiler/Collector/translation.html.twig', - 'id' => 'translation', - 'priority' => 275, - ]) - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/translation_providers.php b/lib/symfony/framework-bundle/Resources/config/translation_providers.php deleted file mode 100644 index cd140f077..000000000 --- a/lib/symfony/framework-bundle/Resources/config/translation_providers.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\Translation\Bridge\Crowdin\CrowdinProviderFactory; -use Symfony\Component\Translation\Bridge\Loco\LocoProviderFactory; -use Symfony\Component\Translation\Bridge\Lokalise\LokaliseProviderFactory; -use Symfony\Component\Translation\Provider\NullProviderFactory; -use Symfony\Component\Translation\Provider\TranslationProviderCollection; -use Symfony\Component\Translation\Provider\TranslationProviderCollectionFactory; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('translation.provider_collection', TranslationProviderCollection::class) - ->factory([service('translation.provider_collection_factory'), 'fromConfig']) - ->args([ - [], // Providers - ]) - - ->set('translation.provider_collection_factory', TranslationProviderCollectionFactory::class) - ->args([ - tagged_iterator('translation.provider_factory'), - [], // Enabled locales - ]) - - ->set('translation.provider_factory.null', NullProviderFactory::class) - ->tag('translation.provider_factory') - - ->set('translation.provider_factory.crowdin', CrowdinProviderFactory::class) - ->args([ - service('http_client'), - service('logger'), - param('kernel.default_locale'), - service('translation.loader.xliff'), - service('translation.dumper.xliff'), - ]) - ->tag('translation.provider_factory') - - ->set('translation.provider_factory.loco', LocoProviderFactory::class) - ->args([ - service('http_client'), - service('logger'), - param('kernel.default_locale'), - service('translation.loader.xliff'), - ]) - ->tag('translation.provider_factory') - - ->set('translation.provider_factory.lokalise', LokaliseProviderFactory::class) - ->args([ - service('http_client'), - service('logger'), - param('kernel.default_locale'), - service('translation.loader.xliff'), - ]) - ->tag('translation.provider_factory') - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/uid.php b/lib/symfony/framework-bundle/Resources/config/uid.php deleted file mode 100644 index 840fb97b5..000000000 --- a/lib/symfony/framework-bundle/Resources/config/uid.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\Uid\Factory\NameBasedUuidFactory; -use Symfony\Component\Uid\Factory\RandomBasedUuidFactory; -use Symfony\Component\Uid\Factory\TimeBasedUuidFactory; -use Symfony\Component\Uid\Factory\UlidFactory; -use Symfony\Component\Uid\Factory\UuidFactory; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('ulid.factory', UlidFactory::class) - ->alias(UlidFactory::class, 'ulid.factory') - - ->set('uuid.factory', UuidFactory::class) - ->alias(UuidFactory::class, 'uuid.factory') - - ->set('name_based_uuid.factory', NameBasedUuidFactory::class) - ->factory([service('uuid.factory'), 'nameBased']) - ->args([abstract_arg('Please set the "framework.uid.name_based_uuid_namespace" configuration option to use the "name_based_uuid.factory" service')]) - ->alias(NameBasedUuidFactory::class, 'name_based_uuid.factory') - - ->set('random_based_uuid.factory', RandomBasedUuidFactory::class) - ->factory([service('uuid.factory'), 'randomBased']) - ->alias(RandomBasedUuidFactory::class, 'random_based_uuid.factory') - - ->set('time_based_uuid.factory', TimeBasedUuidFactory::class) - ->factory([service('uuid.factory'), 'timeBased']) - ->alias(TimeBasedUuidFactory::class, 'time_based_uuid.factory') - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/validator.php b/lib/symfony/framework-bundle/Resources/config/validator.php deleted file mode 100644 index 700ea69ed..000000000 --- a/lib/symfony/framework-bundle/Resources/config/validator.php +++ /dev/null @@ -1,108 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Bundle\FrameworkBundle\CacheWarmer\ValidatorCacheWarmer; -use Symfony\Component\Cache\Adapter\PhpArrayAdapter; -use Symfony\Component\ExpressionLanguage\ExpressionLanguage; -use Symfony\Component\Validator\Constraints\EmailValidator; -use Symfony\Component\Validator\Constraints\ExpressionValidator; -use Symfony\Component\Validator\Constraints\NotCompromisedPasswordValidator; -use Symfony\Component\Validator\ContainerConstraintValidatorFactory; -use Symfony\Component\Validator\Mapping\Loader\PropertyInfoLoader; -use Symfony\Component\Validator\Validation; -use Symfony\Component\Validator\Validator\ValidatorInterface; -use Symfony\Component\Validator\ValidatorBuilder; - -return static function (ContainerConfigurator $container) { - $container->parameters() - ->set('validator.mapping.cache.file', param('kernel.cache_dir').'/validation.php'); - - $container->services() - ->set('validator', ValidatorInterface::class) - ->public() - ->factory([service('validator.builder'), 'getValidator']) - ->tag('container.private', ['package' => 'symfony/framework-bundle', 'version' => '5.2']) - ->alias(ValidatorInterface::class, 'validator') - - ->set('validator.builder', ValidatorBuilder::class) - ->factory([Validation::class, 'createValidatorBuilder']) - ->call('setConstraintValidatorFactory', [ - service('validator.validator_factory'), - ]) - ->call('setTranslator', [ - service('translator')->ignoreOnInvalid(), - ]) - ->call('setTranslationDomain', [ - param('validator.translation_domain'), - ]) - ->alias('validator.mapping.class_metadata_factory', 'validator') - - ->set('validator.mapping.cache_warmer', ValidatorCacheWarmer::class) - ->args([ - service('validator.builder'), - param('validator.mapping.cache.file'), - ]) - ->tag('kernel.cache_warmer') - - ->set('validator.mapping.cache.adapter', PhpArrayAdapter::class) - ->factory([PhpArrayAdapter::class, 'create']) - ->args([ - param('validator.mapping.cache.file'), - service('cache.validator'), - ]) - - ->set('validator.validator_factory', ContainerConstraintValidatorFactory::class) - ->args([ - abstract_arg('Constraint validators locator'), - ]) - - ->set('validator.expression', ExpressionValidator::class) - ->args([service('validator.expression_language')->nullOnInvalid()]) - ->tag('validator.constraint_validator', [ - 'alias' => 'validator.expression', - ]) - - ->set('validator.expression_language', ExpressionLanguage::class) - ->args([service('cache.validator_expression_language')->nullOnInvalid()]) - - ->set('cache.validator_expression_language') - ->parent('cache.system') - ->tag('cache.pool') - - ->set('validator.email', EmailValidator::class) - ->args([ - abstract_arg('Default mode'), - ]) - ->tag('validator.constraint_validator', [ - 'alias' => EmailValidator::class, - ]) - - ->set('validator.not_compromised_password', NotCompromisedPasswordValidator::class) - ->args([ - service('http_client')->nullOnInvalid(), - param('kernel.charset'), - false, - ]) - ->tag('validator.constraint_validator', [ - 'alias' => NotCompromisedPasswordValidator::class, - ]) - - ->set('validator.property_info_loader', PropertyInfoLoader::class) - ->args([ - service('property_info'), - service('property_info'), - service('property_info'), - ]) - ->tag('validator.auto_mapper') - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/validator_debug.php b/lib/symfony/framework-bundle/Resources/config/validator_debug.php deleted file mode 100644 index e9fe44114..000000000 --- a/lib/symfony/framework-bundle/Resources/config/validator_debug.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\Validator\DataCollector\ValidatorDataCollector; -use Symfony\Component\Validator\Validator\TraceableValidator; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('debug.validator', TraceableValidator::class) - ->decorate('validator', null, 255) - ->args([ - service('debug.validator.inner'), - ]) - ->tag('kernel.reset', [ - 'method' => 'reset', - ]) - - ->set('data_collector.validator', ValidatorDataCollector::class) - ->args([ - service('debug.validator'), - ]) - ->tag('data_collector', [ - 'template' => '@WebProfiler/Collector/validator.html.twig', - 'id' => 'validator', - 'priority' => 320, - ]) - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/web.php b/lib/symfony/framework-bundle/Resources/config/web.php deleted file mode 100644 index 53613d3b5..000000000 --- a/lib/symfony/framework-bundle/Resources/config/web.php +++ /dev/null @@ -1,113 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver\ServiceValueResolver; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver; -use Symfony\Component\HttpKernel\Controller\ErrorController; -use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory; -use Symfony\Component\HttpKernel\EventListener\DisallowRobotsIndexingListener; -use Symfony\Component\HttpKernel\EventListener\ErrorListener; -use Symfony\Component\HttpKernel\EventListener\LocaleListener; -use Symfony\Component\HttpKernel\EventListener\ResponseListener; -use Symfony\Component\HttpKernel\EventListener\StreamedResponseListener; -use Symfony\Component\HttpKernel\EventListener\ValidateRequestListener; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('controller_resolver', ControllerResolver::class) - ->args([ - service('service_container'), - service('logger')->ignoreOnInvalid(), - ]) - ->tag('monolog.logger', ['channel' => 'request']) - - ->set('argument_metadata_factory', ArgumentMetadataFactory::class) - - ->set('argument_resolver', ArgumentResolver::class) - ->args([ - service('argument_metadata_factory'), - abstract_arg('argument value resolvers'), - ]) - - ->set('argument_resolver.request_attribute', RequestAttributeValueResolver::class) - ->tag('controller.argument_value_resolver', ['priority' => 100]) - - ->set('argument_resolver.request', RequestValueResolver::class) - ->tag('controller.argument_value_resolver', ['priority' => 50]) - - ->set('argument_resolver.session', SessionValueResolver::class) - ->tag('controller.argument_value_resolver', ['priority' => 50]) - - ->set('argument_resolver.service', ServiceValueResolver::class) - ->args([ - abstract_arg('service locator, set in RegisterControllerArgumentLocatorsPass'), - ]) - ->tag('controller.argument_value_resolver', ['priority' => -50]) - - ->set('argument_resolver.default', DefaultValueResolver::class) - ->tag('controller.argument_value_resolver', ['priority' => -100]) - - ->set('argument_resolver.variadic', VariadicValueResolver::class) - ->tag('controller.argument_value_resolver', ['priority' => -150]) - - ->set('response_listener', ResponseListener::class) - ->args([ - param('kernel.charset'), - abstract_arg('The "set_content_language_from_locale" config value'), - ]) - ->tag('kernel.event_subscriber') - - ->set('streamed_response_listener', StreamedResponseListener::class) - ->tag('kernel.event_subscriber') - - ->set('locale_listener', LocaleListener::class) - ->args([ - service('request_stack'), - param('kernel.default_locale'), - service('router')->ignoreOnInvalid(), - abstract_arg('The "set_locale_from_accept_language" config value'), - param('kernel.enabled_locales'), - ]) - ->tag('kernel.event_subscriber') - - ->set('validate_request_listener', ValidateRequestListener::class) - ->tag('kernel.event_subscriber') - - ->set('disallow_search_engine_index_response_listener', DisallowRobotsIndexingListener::class) - ->tag('kernel.event_subscriber') - - ->set('error_controller', ErrorController::class) - ->public() - ->args([ - service('http_kernel'), - param('kernel.error_controller'), - service('error_renderer'), - ]) - - ->set('exception_listener', ErrorListener::class) - ->args([ - param('kernel.error_controller'), - service('logger')->nullOnInvalid(), - param('kernel.debug'), - abstract_arg('an exceptions to log & status code mapping'), - ]) - ->tag('kernel.event_subscriber') - ->tag('monolog.logger', ['channel' => 'request']) - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/web_link.php b/lib/symfony/framework-bundle/Resources/config/web_link.php deleted file mode 100644 index 0b0e79db8..000000000 --- a/lib/symfony/framework-bundle/Resources/config/web_link.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\WebLink\EventListener\AddLinkHeaderListener; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('web_link.add_link_header_listener', AddLinkHeaderListener::class) - ->tag('kernel.event_subscriber') - ; -}; diff --git a/lib/symfony/framework-bundle/Resources/config/workflow.php b/lib/symfony/framework-bundle/Resources/config/workflow.php deleted file mode 100644 index 909bb5aca..000000000 --- a/lib/symfony/framework-bundle/Resources/config/workflow.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\Workflow\EventListener\ExpressionLanguage; -use Symfony\Component\Workflow\MarkingStore\MethodMarkingStore; -use Symfony\Component\Workflow\Registry; -use Symfony\Component\Workflow\StateMachine; -use Symfony\Component\Workflow\Workflow; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('workflow.abstract', Workflow::class) - ->args([ - abstract_arg('workflow definition'), - abstract_arg('marking store'), - service('event_dispatcher')->ignoreOnInvalid(), - abstract_arg('workflow name'), - abstract_arg('events to dispatch'), - ]) - ->abstract() - ->public() - ->tag('container.private', ['package' => 'symfony/framework-bundle', 'version' => '5.3']) - ->set('state_machine.abstract', StateMachine::class) - ->args([ - abstract_arg('workflow definition'), - abstract_arg('marking store'), - service('event_dispatcher')->ignoreOnInvalid(), - abstract_arg('workflow name'), - abstract_arg('events to dispatch'), - ]) - ->abstract() - ->public() - ->tag('container.private', ['package' => 'symfony/framework-bundle', 'version' => '5.3']) - ->set('workflow.marking_store.method', MethodMarkingStore::class) - ->abstract() - ->set('workflow.registry', Registry::class) - ->alias(Registry::class, 'workflow.registry') - ->set('workflow.security.expression_language', ExpressionLanguage::class) - ; -}; diff --git a/lib/symfony/framework-bundle/Routing/AnnotatedRouteControllerLoader.php b/lib/symfony/framework-bundle/Routing/AnnotatedRouteControllerLoader.php deleted file mode 100644 index 511e87058..000000000 --- a/lib/symfony/framework-bundle/Routing/AnnotatedRouteControllerLoader.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Routing; - -use Symfony\Component\Routing\Loader\AnnotationClassLoader; -use Symfony\Component\Routing\Route; - -/** - * AnnotatedRouteControllerLoader is an implementation of AnnotationClassLoader - * that sets the '_controller' default based on the class and method names. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class AnnotatedRouteControllerLoader extends AnnotationClassLoader -{ - /** - * Configures the _controller default parameter of a given Route instance. - */ - protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, object $annot) - { - if ('__invoke' === $method->getName()) { - $route->setDefault('_controller', $class->getName()); - } else { - $route->setDefault('_controller', $class->getName().'::'.$method->getName()); - } - } - - /** - * Makes the default route name more sane by removing common keywords. - * - * @return string - */ - protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method) - { - $name = preg_replace('/(bundle|controller)_/', '_', parent::getDefaultRouteName($class, $method)); - - if (str_ends_with($method->name, 'Action') || str_ends_with($method->name, '_action')) { - $name = preg_replace('/action(_\d+)?$/', '\\1', $name); - } - - return str_replace('__', '_', $name); - } -} diff --git a/lib/symfony/framework-bundle/Routing/DelegatingLoader.php b/lib/symfony/framework-bundle/Routing/DelegatingLoader.php deleted file mode 100644 index e130bd2fa..000000000 --- a/lib/symfony/framework-bundle/Routing/DelegatingLoader.php +++ /dev/null @@ -1,95 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Routing; - -use Symfony\Component\Config\Exception\LoaderLoadException; -use Symfony\Component\Config\Loader\DelegatingLoader as BaseDelegatingLoader; -use Symfony\Component\Config\Loader\LoaderResolverInterface; -use Symfony\Component\Routing\RouteCollection; - -/** - * DelegatingLoader delegates route loading to other loaders using a loader resolver. - * - * This implementation resolves the _controller attribute from the short notation - * to the fully-qualified form (from a:b:c to class::method). - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class DelegatingLoader extends BaseDelegatingLoader -{ - private $loading = false; - private $defaultOptions; - private $defaultRequirements; - - public function __construct(LoaderResolverInterface $resolver, array $defaultOptions = [], array $defaultRequirements = []) - { - $this->defaultOptions = $defaultOptions; - $this->defaultRequirements = $defaultRequirements; - - parent::__construct($resolver); - } - - /** - * {@inheritdoc} - */ - public function load($resource, string $type = null): RouteCollection - { - if ($this->loading) { - // This can happen if a fatal error occurs in parent::load(). - // Here is the scenario: - // - while routes are being loaded by parent::load() below, a fatal error - // occurs (e.g. parse error in a controller while loading annotations); - // - PHP abruptly empties the stack trace, bypassing all catch/finally blocks; - // it then calls the registered shutdown functions; - // - the ErrorHandler catches the fatal error and re-injects it for rendering - // thanks to HttpKernel->terminateWithException() (that calls handleException()); - // - at this stage, if we try to load the routes again, we must prevent - // the fatal error from occurring a second time, - // otherwise the PHP process would be killed immediately; - // - while rendering the exception page, the router can be required - // (by e.g. the web profiler that needs to generate an URL); - // - this handles the case and prevents the second fatal error - // by triggering an exception beforehand. - - throw new LoaderLoadException($resource, null, 0, null, $type); - } - $this->loading = true; - - try { - $collection = parent::load($resource, $type); - } finally { - $this->loading = false; - } - - foreach ($collection->all() as $route) { - if ($this->defaultOptions) { - $route->setOptions($route->getOptions() + $this->defaultOptions); - } - if ($this->defaultRequirements) { - $route->setRequirements($route->getRequirements() + $this->defaultRequirements); - } - if (!\is_string($controller = $route->getDefault('_controller'))) { - continue; - } - - if (str_contains($controller, '::')) { - continue; - } - - $route->setDefault('_controller', $controller); - } - - return $collection; - } -} diff --git a/lib/symfony/framework-bundle/Routing/RedirectableCompiledUrlMatcher.php b/lib/symfony/framework-bundle/Routing/RedirectableCompiledUrlMatcher.php deleted file mode 100644 index dba9d6d96..000000000 --- a/lib/symfony/framework-bundle/Routing/RedirectableCompiledUrlMatcher.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Routing; - -use Symfony\Component\Routing\Matcher\CompiledUrlMatcher; -use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface; - -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @internal - */ -class RedirectableCompiledUrlMatcher extends CompiledUrlMatcher implements RedirectableUrlMatcherInterface -{ - /** - * {@inheritdoc} - */ - public function redirect(string $path, string $route, string $scheme = null): array - { - return [ - '_controller' => 'Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController::urlRedirectAction', - 'path' => $path, - 'permanent' => true, - 'scheme' => $scheme, - 'httpPort' => $this->context->getHttpPort(), - 'httpsPort' => $this->context->getHttpsPort(), - '_route' => $route, - ]; - } -} diff --git a/lib/symfony/framework-bundle/Routing/RouteLoaderInterface.php b/lib/symfony/framework-bundle/Routing/RouteLoaderInterface.php deleted file mode 100644 index d1cb55a7a..000000000 --- a/lib/symfony/framework-bundle/Routing/RouteLoaderInterface.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Routing; - -/** - * Marker interface for service route loaders. - */ -interface RouteLoaderInterface -{ -} diff --git a/lib/symfony/framework-bundle/Routing/Router.php b/lib/symfony/framework-bundle/Routing/Router.php deleted file mode 100644 index 8e36efe0a..000000000 --- a/lib/symfony/framework-bundle/Routing/Router.php +++ /dev/null @@ -1,210 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Routing; - -use Psr\Container\ContainerInterface; -use Psr\Log\LoggerInterface; -use Symfony\Component\Config\Loader\LoaderInterface; -use Symfony\Component\Config\Resource\FileExistenceResource; -use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\DependencyInjection\Config\ContainerParametersResource; -use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface; -use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; -use Symfony\Component\Routing\RequestContext; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\Router as BaseRouter; -use Symfony\Contracts\Service\ServiceSubscriberInterface; - -/** - * This Router creates the Loader only when the cache is empty. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Router extends BaseRouter implements WarmableInterface, ServiceSubscriberInterface -{ - private $container; - private $collectedParameters = []; - private $paramFetcher; - - /** - * @param mixed $resource The main resource to load - */ - public function __construct(ContainerInterface $container, $resource, array $options = [], RequestContext $context = null, ContainerInterface $parameters = null, LoggerInterface $logger = null, string $defaultLocale = null) - { - $this->container = $container; - $this->resource = $resource; - $this->context = $context ?? new RequestContext(); - $this->logger = $logger; - $this->setOptions($options); - - if ($parameters) { - $this->paramFetcher = \Closure::fromCallable([$parameters, 'get']); - } elseif ($container instanceof SymfonyContainerInterface) { - $this->paramFetcher = \Closure::fromCallable([$container, 'getParameter']); - } else { - throw new \LogicException(sprintf('You should either pass a "%s" instance or provide the $parameters argument of the "%s" method.', SymfonyContainerInterface::class, __METHOD__)); - } - - $this->defaultLocale = $defaultLocale; - } - - /** - * {@inheritdoc} - */ - public function getRouteCollection() - { - if (null === $this->collection) { - $this->collection = $this->container->get('routing.loader')->load($this->resource, $this->options['resource_type']); - $this->resolveParameters($this->collection); - $this->collection->addResource(new ContainerParametersResource($this->collectedParameters)); - - try { - $containerFile = ($this->paramFetcher)('kernel.cache_dir').'/'.($this->paramFetcher)('kernel.container_class').'.php'; - if (file_exists($containerFile)) { - $this->collection->addResource(new FileResource($containerFile)); - } else { - $this->collection->addResource(new FileExistenceResource($containerFile)); - } - } catch (ParameterNotFoundException $exception) { - } - } - - return $this->collection; - } - - /** - * {@inheritdoc} - * - * @return string[] A list of classes to preload on PHP 7.4+ - */ - public function warmUp(string $cacheDir) - { - $currentDir = $this->getOption('cache_dir'); - - // force cache generation - $this->setOption('cache_dir', $cacheDir); - $this->getMatcher(); - $this->getGenerator(); - - $this->setOption('cache_dir', $currentDir); - - return [ - $this->getOption('generator_class'), - $this->getOption('matcher_class'), - ]; - } - - /** - * Replaces placeholders with service container parameter values in: - * - the route defaults, - * - the route requirements, - * - the route path, - * - the route host, - * - the route schemes, - * - the route methods. - */ - private function resolveParameters(RouteCollection $collection) - { - foreach ($collection as $route) { - foreach ($route->getDefaults() as $name => $value) { - $route->setDefault($name, $this->resolve($value)); - } - - foreach ($route->getRequirements() as $name => $value) { - $route->setRequirement($name, $this->resolve($value)); - } - - $route->setPath($this->resolve($route->getPath())); - $route->setHost($this->resolve($route->getHost())); - - $schemes = []; - foreach ($route->getSchemes() as $scheme) { - $schemes[] = explode('|', $this->resolve($scheme)); - } - $route->setSchemes(array_merge([], ...$schemes)); - - $methods = []; - foreach ($route->getMethods() as $method) { - $methods[] = explode('|', $this->resolve($method)); - } - $route->setMethods(array_merge([], ...$methods)); - $route->setCondition($this->resolve($route->getCondition())); - } - } - - /** - * Recursively replaces placeholders with the service container parameters. - * - * @param mixed $value The source which might contain "%placeholders%" - * - * @return mixed The source with the placeholders replaced by the container - * parameters. Arrays are resolved recursively. - * - * @throws ParameterNotFoundException When a placeholder does not exist as a container parameter - * @throws RuntimeException When a container value is not a string or a numeric value - */ - private function resolve($value) - { - if (\is_array($value)) { - foreach ($value as $key => $val) { - $value[$key] = $this->resolve($val); - } - - return $value; - } - - if (!\is_string($value)) { - return $value; - } - - $escapedValue = preg_replace_callback('/%%|%([^%\s]++)%/', function ($match) use ($value) { - // skip %% - if (!isset($match[1])) { - return '%%'; - } - - if (preg_match('/^env\((?:\w++:)*+\w++\)$/', $match[1])) { - throw new RuntimeException(sprintf('Using "%%%s%%" is not allowed in routing configuration.', $match[1])); - } - - $resolved = ($this->paramFetcher)($match[1]); - - if (\is_scalar($resolved)) { - $this->collectedParameters[$match[1]] = $resolved; - - if (\is_string($resolved)) { - $resolved = $this->resolve($resolved); - } - - if (\is_scalar($resolved)) { - return false === $resolved ? '0' : (string) $resolved; - } - } - - throw new RuntimeException(sprintf('The container parameter "%s", used in the route configuration value "%s", must be a string or numeric, but it is of type "%s".', $match[1], $value, get_debug_type($resolved))); - }, $value); - - return str_replace('%%', '%', $escapedValue); - } - - /** - * {@inheritdoc} - */ - public static function getSubscribedServices() - { - return [ - 'routing.loader' => LoaderInterface::class, - ]; - } -} diff --git a/lib/symfony/framework-bundle/Secrets/AbstractVault.php b/lib/symfony/framework-bundle/Secrets/AbstractVault.php deleted file mode 100644 index eeecbbb68..000000000 --- a/lib/symfony/framework-bundle/Secrets/AbstractVault.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Secrets; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -abstract class AbstractVault -{ - protected $lastMessage; - - public function getLastMessage(): ?string - { - return $this->lastMessage; - } - - abstract public function generateKeys(bool $override = false): bool; - - abstract public function seal(string $name, string $value): void; - - abstract public function reveal(string $name): ?string; - - abstract public function remove(string $name): bool; - - abstract public function list(bool $reveal = false): array; - - protected function validateName(string $name): void - { - if (!preg_match('/^\w++$/D', $name)) { - throw new \LogicException(sprintf('Invalid secret name "%s": only "word" characters are allowed.', $name)); - } - } - - protected function getPrettyPath(string $path) - { - return str_replace(getcwd().\DIRECTORY_SEPARATOR, '', $path); - } -} diff --git a/lib/symfony/framework-bundle/Secrets/DotenvVault.php b/lib/symfony/framework-bundle/Secrets/DotenvVault.php deleted file mode 100644 index 7c6f6987e..000000000 --- a/lib/symfony/framework-bundle/Secrets/DotenvVault.php +++ /dev/null @@ -1,107 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Secrets; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -class DotenvVault extends AbstractVault -{ - private $dotenvFile; - - public function __construct(string $dotenvFile) - { - $this->dotenvFile = strtr($dotenvFile, '/', \DIRECTORY_SEPARATOR); - } - - public function generateKeys(bool $override = false): bool - { - $this->lastMessage = 'The dotenv vault doesn\'t encrypt secrets thus doesn\'t need keys.'; - - return false; - } - - public function seal(string $name, string $value): void - { - $this->lastMessage = null; - $this->validateName($name); - $v = str_replace("'", "'\\''", $value); - - $content = is_file($this->dotenvFile) ? file_get_contents($this->dotenvFile) : ''; - $content = preg_replace("/^$name=((\\\\'|'[^']++')++|.*)/m", "$name='$v'", $content, -1, $count); - - if (!$count) { - $content .= "$name='$v'\n"; - } - - file_put_contents($this->dotenvFile, $content); - - $this->lastMessage = sprintf('Secret "%s" %s in "%s".', $name, $count ? 'added' : 'updated', $this->getPrettyPath($this->dotenvFile)); - } - - public function reveal(string $name): ?string - { - $this->lastMessage = null; - $this->validateName($name); - $v = \is_string($_SERVER[$name] ?? null) && !str_starts_with($name, 'HTTP_') ? $_SERVER[$name] : ($_ENV[$name] ?? null); - - if (null === $v) { - $this->lastMessage = sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath($this->dotenvFile)); - - return null; - } - - return $v; - } - - public function remove(string $name): bool - { - $this->lastMessage = null; - $this->validateName($name); - - $content = is_file($this->dotenvFile) ? file_get_contents($this->dotenvFile) : ''; - $content = preg_replace("/^$name=((\\\\'|'[^']++')++|.*)\n?/m", '', $content, -1, $count); - - if ($count) { - file_put_contents($this->dotenvFile, $content); - $this->lastMessage = sprintf('Secret "%s" removed from file "%s".', $name, $this->getPrettyPath($this->dotenvFile)); - - return true; - } - - $this->lastMessage = sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath($this->dotenvFile)); - - return false; - } - - public function list(bool $reveal = false): array - { - $this->lastMessage = null; - $secrets = []; - - foreach ($_ENV as $k => $v) { - if (preg_match('/^\w+$/D', $k)) { - $secrets[$k] = $reveal ? $v : null; - } - } - - foreach ($_SERVER as $k => $v) { - if (\is_string($v) && preg_match('/^\w+$/D', $k)) { - $secrets[$k] = $reveal ? $v : null; - } - } - - return $secrets; - } -} diff --git a/lib/symfony/framework-bundle/Secrets/SodiumVault.php b/lib/symfony/framework-bundle/Secrets/SodiumVault.php deleted file mode 100644 index a9c86ab04..000000000 --- a/lib/symfony/framework-bundle/Secrets/SodiumVault.php +++ /dev/null @@ -1,233 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Secrets; - -use Symfony\Component\DependencyInjection\EnvVarLoaderInterface; -use Symfony\Component\VarExporter\VarExporter; - -/** - * @author Tobias Schultze <http://tobion.de> - * @author Jérémy Derussé <jeremy@derusse.com> - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -class SodiumVault extends AbstractVault implements EnvVarLoaderInterface -{ - private $encryptionKey; - private $decryptionKey; - private $pathPrefix; - private $secretsDir; - - /** - * @param string|\Stringable|null $decryptionKey A string or a stringable object that defines the private key to use to decrypt the vault - * or null to store generated keys in the provided $secretsDir - */ - public function __construct(string $secretsDir, $decryptionKey = null) - { - if (null !== $decryptionKey && !\is_string($decryptionKey) && !(\is_object($decryptionKey) && method_exists($decryptionKey, '__toString'))) { - throw new \TypeError(sprintf('Decryption key should be a string or an object that implements the __toString() method, "%s" given.', get_debug_type($decryptionKey))); - } - - $this->pathPrefix = rtrim(strtr($secretsDir, '/', \DIRECTORY_SEPARATOR), \DIRECTORY_SEPARATOR).\DIRECTORY_SEPARATOR.basename($secretsDir).'.'; - $this->decryptionKey = $decryptionKey; - $this->secretsDir = $secretsDir; - } - - public function generateKeys(bool $override = false): bool - { - $this->lastMessage = null; - - if (null === $this->encryptionKey && '' !== $this->decryptionKey = (string) $this->decryptionKey) { - $this->lastMessage = 'Cannot generate keys when a decryption key has been provided while instantiating the vault.'; - - return false; - } - - try { - $this->loadKeys(); - } catch (\RuntimeException $e) { - // ignore failures to load keys - } - - if ('' !== $this->decryptionKey && !is_file($this->pathPrefix.'encrypt.public.php')) { - $this->export('encrypt.public', $this->encryptionKey); - } - - if (!$override && null !== $this->encryptionKey) { - $this->lastMessage = sprintf('Sodium keys already exist at "%s*.{public,private}" and won\'t be overridden.', $this->getPrettyPath($this->pathPrefix)); - - return false; - } - - $this->decryptionKey = sodium_crypto_box_keypair(); - $this->encryptionKey = sodium_crypto_box_publickey($this->decryptionKey); - - $this->export('encrypt.public', $this->encryptionKey); - $this->export('decrypt.private', $this->decryptionKey); - - $this->lastMessage = sprintf('Sodium keys have been generated at "%s*.public/private.php".', $this->getPrettyPath($this->pathPrefix)); - - return true; - } - - public function seal(string $name, string $value): void - { - $this->lastMessage = null; - $this->validateName($name); - $this->loadKeys(); - $filename = $this->getFilename($name); - $this->export($filename, sodium_crypto_box_seal($value, $this->encryptionKey ?? sodium_crypto_box_publickey($this->decryptionKey))); - - $list = $this->list(); - $list[$name] = null; - uksort($list, 'strnatcmp'); - file_put_contents($this->pathPrefix.'list.php', sprintf("<?php\n\nreturn %s;\n", VarExporter::export($list)), \LOCK_EX); - - $this->lastMessage = sprintf('Secret "%s" encrypted in "%s"; you can commit it.', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); - } - - public function reveal(string $name): ?string - { - $this->lastMessage = null; - $this->validateName($name); - - $filename = $this->getFilename($name); - if (!is_file($file = $this->pathPrefix.$filename.'.php')) { - $this->lastMessage = sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); - - return null; - } - - if (!\function_exists('sodium_crypto_box_seal')) { - $this->lastMessage = sprintf('Secret "%s" cannot be revealed as the "sodium" PHP extension missing. Try running "composer require paragonie/sodium_compat" if you cannot enable the extension."', $name); - - return null; - } - - $this->loadKeys(); - - if ('' === $this->decryptionKey) { - $this->lastMessage = sprintf('Secret "%s" cannot be revealed as no decryption key was found in "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); - - return null; - } - - if (false === $value = sodium_crypto_box_seal_open(include $file, $this->decryptionKey)) { - $this->lastMessage = sprintf('Secret "%s" cannot be revealed as the wrong decryption key was provided for "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); - - return null; - } - - return $value; - } - - public function remove(string $name): bool - { - $this->lastMessage = null; - $this->validateName($name); - - $filename = $this->getFilename($name); - if (!is_file($file = $this->pathPrefix.$filename.'.php')) { - $this->lastMessage = sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); - - return false; - } - - $list = $this->list(); - unset($list[$name]); - file_put_contents($this->pathPrefix.'list.php', sprintf("<?php\n\nreturn %s;\n", VarExporter::export($list)), \LOCK_EX); - - $this->lastMessage = sprintf('Secret "%s" removed from "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); - - return @unlink($file) || !file_exists($file); - } - - public function list(bool $reveal = false): array - { - $this->lastMessage = null; - - if (!is_file($file = $this->pathPrefix.'list.php')) { - return []; - } - - $secrets = include $file; - - if (!$reveal) { - return $secrets; - } - - foreach ($secrets as $name => $value) { - $secrets[$name] = $this->reveal($name); - } - - return $secrets; - } - - public function loadEnvVars(): array - { - return $this->list(true); - } - - private function loadKeys(): void - { - if (!\function_exists('sodium_crypto_box_seal')) { - throw new \LogicException('The "sodium" PHP extension is required to deal with secrets. Alternatively, try running "composer require paragonie/sodium_compat" if you cannot enable the extension.".'); - } - - if (null !== $this->encryptionKey || '' !== $this->decryptionKey = (string) $this->decryptionKey) { - return; - } - - if (is_file($this->pathPrefix.'decrypt.private.php')) { - $this->decryptionKey = (string) include $this->pathPrefix.'decrypt.private.php'; - } - - if (is_file($this->pathPrefix.'encrypt.public.php')) { - $this->encryptionKey = (string) include $this->pathPrefix.'encrypt.public.php'; - } elseif ('' !== $this->decryptionKey) { - $this->encryptionKey = sodium_crypto_box_publickey($this->decryptionKey); - } else { - throw new \RuntimeException(sprintf('Encryption key not found in "%s".', \dirname($this->pathPrefix))); - } - } - - private function export(string $filename, string $data): void - { - $b64 = 'decrypt.private' === $filename ? '// SYMFONY_DECRYPTION_SECRET='.base64_encode($data)."\n" : ''; - $name = basename($this->pathPrefix.$filename); - $data = str_replace('%', '\x', rawurlencode($data)); - $data = sprintf("<?php // %s on %s\n\n%sreturn \"%s\";\n", $name, date('r'), $b64, $data); - - $this->createSecretsDir(); - - if (false === file_put_contents($this->pathPrefix.$filename.'.php', $data, \LOCK_EX)) { - $e = error_get_last(); - throw new \ErrorException($e['message'] ?? 'Failed to write secrets data.', 0, $e['type'] ?? \E_USER_WARNING); - } - } - - private function createSecretsDir(): void - { - if ($this->secretsDir && !is_dir($this->secretsDir) && !@mkdir($this->secretsDir, 0777, true) && !is_dir($this->secretsDir)) { - throw new \RuntimeException(sprintf('Unable to create the secrets directory (%s).', $this->secretsDir)); - } - - $this->secretsDir = null; - } - - private function getFilename(string $name): string - { - // The MD5 hash allows making secrets case-sensitive. The filename is not enough on Windows. - return $name.'.'.substr(md5($name), 0, 6); - } -} diff --git a/lib/symfony/framework-bundle/Session/DeprecatedSessionFactory.php b/lib/symfony/framework-bundle/Session/DeprecatedSessionFactory.php deleted file mode 100644 index faa29a1c7..000000000 --- a/lib/symfony/framework-bundle/Session/DeprecatedSessionFactory.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Session; - -use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Session\SessionInterface; - -/** - * Provides session and trigger deprecation. - * - * Used by service that should trigger deprecation when accessed by the user. - * - * @author Jérémy Derussé <jeremy@derusse.com> - * - * @internal to be removed in 6.0 - */ -class DeprecatedSessionFactory -{ - private $requestStack; - - public function __construct(RequestStack $requestStack) - { - $this->requestStack = $requestStack; - } - - public function getSession(): ?SessionInterface - { - trigger_deprecation('symfony/framework-bundle', '5.3', 'The "session" service and "SessionInterface" alias are deprecated, use "$requestStack->getSession()" instead.'); - - try { - return $this->requestStack->getSession(); - } catch (SessionNotFoundException $e) { - return null; - } - } -} diff --git a/lib/symfony/framework-bundle/Session/ServiceSessionFactory.php b/lib/symfony/framework-bundle/Session/ServiceSessionFactory.php deleted file mode 100644 index c05737501..000000000 --- a/lib/symfony/framework-bundle/Session/ServiceSessionFactory.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Session; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; -use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageFactoryInterface; -use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface; - -/** - * @author Jérémy Derussé <jeremy@derusse.com> - * - * @internal to be removed in Symfony 6 - */ -final class ServiceSessionFactory implements SessionStorageFactoryInterface -{ - private $storage; - - public function __construct(SessionStorageInterface $storage) - { - $this->storage = $storage; - } - - public function createStorage(?Request $request): SessionStorageInterface - { - if ($this->storage instanceof NativeSessionStorage && $request && $request->isSecure()) { - $this->storage->setOptions(['cookie_secure' => true]); - } - - return $this->storage; - } -} diff --git a/lib/symfony/framework-bundle/Translation/Translator.php b/lib/symfony/framework-bundle/Translation/Translator.php deleted file mode 100644 index 5173f8a8e..000000000 --- a/lib/symfony/framework-bundle/Translation/Translator.php +++ /dev/null @@ -1,187 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Translation; - -use Psr\Container\ContainerInterface; -use Symfony\Component\Config\Resource\DirectoryResource; -use Symfony\Component\Config\Resource\FileExistenceResource; -use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; -use Symfony\Component\Translation\Exception\InvalidArgumentException; -use Symfony\Component\Translation\Formatter\MessageFormatterInterface; -use Symfony\Component\Translation\Translator as BaseTranslator; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -class Translator extends BaseTranslator implements WarmableInterface -{ - protected $container; - protected $loaderIds; - - protected $options = [ - 'cache_dir' => null, - 'debug' => false, - 'resource_files' => [], - 'scanned_directories' => [], - 'cache_vary' => [], - ]; - - /** - * @var list<string> - */ - private $resourceLocales; - - /** - * Holds parameters from addResource() calls so we can defer the actual - * parent::addResource() calls until initialize() is executed. - * - * @var array[] - */ - private $resources = []; - - /** - * @var string[][] - */ - private $resourceFiles; - - /** - * @var string[] - */ - private $scannedDirectories; - - /** - * @var string[] - */ - private $enabledLocales; - - /** - * Constructor. - * - * Available options: - * - * * cache_dir: The cache directory (or null to disable caching) - * * debug: Whether to enable debugging or not (false by default) - * * resource_files: List of translation resources available grouped by locale. - * * cache_vary: An array of data that is serialized to generate the cached catalogue name. - * - * @throws InvalidArgumentException - */ - public function __construct(ContainerInterface $container, MessageFormatterInterface $formatter, string $defaultLocale, array $loaderIds = [], array $options = [], array $enabledLocales = []) - { - $this->container = $container; - $this->loaderIds = $loaderIds; - $this->enabledLocales = $enabledLocales; - - // check option names - if ($diff = array_diff(array_keys($options), array_keys($this->options))) { - throw new InvalidArgumentException(sprintf('The Translator does not support the following options: \'%s\'.', implode('\', \'', $diff))); - } - - $this->options = array_merge($this->options, $options); - $this->resourceLocales = array_keys($this->options['resource_files']); - $this->resourceFiles = $this->options['resource_files']; - $this->scannedDirectories = $this->options['scanned_directories']; - - parent::__construct($defaultLocale, $formatter, $this->options['cache_dir'], $this->options['debug'], $this->options['cache_vary']); - } - - /** - * {@inheritdoc} - * - * @return string[] - */ - public function warmUp(string $cacheDir) - { - // skip warmUp when translator doesn't use cache - if (null === $this->options['cache_dir']) { - return []; - } - - $localesToWarmUp = $this->enabledLocales ?: array_merge($this->getFallbackLocales(), [$this->getLocale()], $this->resourceLocales); - - foreach (array_unique($localesToWarmUp) as $locale) { - // reset catalogue in case it's already loaded during the dump of the other locales. - if (isset($this->catalogues[$locale])) { - unset($this->catalogues[$locale]); - } - - $this->loadCatalogue($locale); - } - - return []; - } - - public function addResource(string $format, $resource, string $locale, string $domain = null) - { - if ($this->resourceFiles) { - $this->addResourceFiles(); - } - $this->resources[] = [$format, $resource, $locale, $domain]; - } - - /** - * {@inheritdoc} - */ - protected function initializeCatalogue(string $locale) - { - $this->initialize(); - parent::initializeCatalogue($locale); - } - - /** - * @internal - */ - protected function doLoadCatalogue(string $locale): void - { - parent::doLoadCatalogue($locale); - - foreach ($this->scannedDirectories as $directory) { - $resourceClass = file_exists($directory) ? DirectoryResource::class : FileExistenceResource::class; - $this->catalogues[$locale]->addResource(new $resourceClass($directory)); - } - } - - protected function initialize() - { - if ($this->resourceFiles) { - $this->addResourceFiles(); - } - foreach ($this->resources as $params) { - [$format, $resource, $locale, $domain] = $params; - parent::addResource($format, $resource, $locale, $domain); - } - $this->resources = []; - - foreach ($this->loaderIds as $id => $aliases) { - foreach ($aliases as $alias) { - $this->addLoader($alias, $this->container->get($id)); - } - } - } - - private function addResourceFiles(): void - { - $filesByLocale = $this->resourceFiles; - $this->resourceFiles = []; - - foreach ($filesByLocale as $files) { - foreach ($files as $file) { - // filename is domain.locale.format - $fileNameParts = explode('.', basename($file)); - $format = array_pop($fileNameParts); - $locale = array_pop($fileNameParts); - $domain = implode('.', $fileNameParts); - $this->addResource($format, $file, $locale, $domain); - } - } - } -} diff --git a/lib/symfony/framework-bundle/composer.json b/lib/symfony/framework-bundle/composer.json deleted file mode 100644 index 089e2e082..000000000 --- a/lib/symfony/framework-bundle/composer.json +++ /dev/null @@ -1,118 +0,0 @@ -{ - "name": "symfony/framework-bundle", - "type": "symfony-bundle", - "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "ext-xml": "*", - "symfony/cache": "^5.2|^6.0", - "symfony/config": "^5.3|^6.0", - "symfony/dependency-injection": "^5.4.5|^6.0.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/event-dispatcher": "^5.1|^6.0", - "symfony/error-handler": "^4.4.1|^5.0.1|^6.0", - "symfony/http-foundation": "^5.3|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "^1.16", - "symfony/polyfill-php81": "^1.22", - "symfony/filesystem": "^4.4|^5.0|^6.0", - "symfony/finder": "^4.4|^5.0|^6.0", - "symfony/routing": "^5.3|^6.0" - }, - "require-dev": { - "doctrine/annotations": "^1.13.1|^2", - "doctrine/cache": "^1.11|^2.0", - "doctrine/persistence": "^1.3|^2|^3", - "symfony/asset": "^5.3|^6.0", - "symfony/browser-kit": "^5.4|^6.0", - "symfony/console": "^5.4.9|^6.0.9", - "symfony/css-selector": "^4.4|^5.0|^6.0", - "symfony/dom-crawler": "^4.4.30|^5.3.7|^6.0", - "symfony/dotenv": "^5.1|^6.0", - "symfony/polyfill-intl-icu": "~1.0", - "symfony/form": "^5.2|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/lock": "^4.4|^5.0|^6.0", - "symfony/mailer": "^5.2|^6.0", - "symfony/messenger": "^5.4|^6.0", - "symfony/mime": "^4.4|^5.0|^6.0", - "symfony/notifier": "^5.4|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/rate-limiter": "^5.2|^6.0", - "symfony/security-bundle": "^5.4|^6.0", - "symfony/serializer": "^5.4|^6.0", - "symfony/stopwatch": "^4.4|^5.0|^6.0", - "symfony/string": "^5.0|^6.0", - "symfony/translation": "^5.3|^6.0", - "symfony/twig-bundle": "^4.4|^5.0|^6.0", - "symfony/validator": "^5.2|^6.0", - "symfony/workflow": "^5.2|^6.0", - "symfony/yaml": "^4.4|^5.0|^6.0", - "symfony/property-info": "^4.4|^5.0|^6.0", - "symfony/web-link": "^4.4|^5.0|^6.0", - "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "twig/twig": "^2.10|^3.0" - }, - "conflict": { - "doctrine/annotations": "<1.13.1", - "doctrine/cache": "<1.11", - "doctrine/persistence": "<1.3", - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", - "phpunit/phpunit": "<5.4.3", - "symfony/asset": "<5.3", - "symfony/console": "<5.2.5", - "symfony/dotenv": "<5.1", - "symfony/dom-crawler": "<4.4", - "symfony/http-client": "<4.4", - "symfony/form": "<5.2", - "symfony/lock": "<4.4", - "symfony/mailer": "<5.2", - "symfony/messenger": "<5.4", - "symfony/mime": "<4.4", - "symfony/property-info": "<4.4", - "symfony/property-access": "<5.3", - "symfony/serializer": "<5.2", - "symfony/service-contracts": ">=3.0", - "symfony/security-csrf": "<5.3", - "symfony/stopwatch": "<4.4", - "symfony/translation": "<5.3", - "symfony/twig-bridge": "<4.4", - "symfony/twig-bundle": "<4.4", - "symfony/validator": "<5.2", - "symfony/web-profiler-bundle": "<4.4", - "symfony/workflow": "<5.2" - }, - "suggest": { - "ext-apcu": "For best performance of the system caches", - "symfony/console": "For using the console commands", - "symfony/form": "For using forms", - "symfony/serializer": "For using the serializer service", - "symfony/validator": "For using validation", - "symfony/yaml": "For using the debug:config and lint:yaml commands", - "symfony/property-info": "For using the property_info service", - "symfony/web-link": "For using web links, features such as preloading, prefetching or prerendering" - }, - "autoload": { - "psr-4": { "Symfony\\Bundle\\FrameworkBundle\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/lib/symfony/http-foundation/AcceptHeader.php b/lib/symfony/http-foundation/AcceptHeader.php deleted file mode 100644 index 057c6b530..000000000 --- a/lib/symfony/http-foundation/AcceptHeader.php +++ /dev/null @@ -1,168 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -// Help opcache.preload discover always-needed symbols -class_exists(AcceptHeaderItem::class); - -/** - * Represents an Accept-* header. - * - * An accept header is compound with a list of items, - * sorted by descending quality. - * - * @author Jean-François Simon <contact@jfsimon.fr> - */ -class AcceptHeader -{ - /** - * @var AcceptHeaderItem[] - */ - private $items = []; - - /** - * @var bool - */ - private $sorted = true; - - /** - * @param AcceptHeaderItem[] $items - */ - public function __construct(array $items) - { - foreach ($items as $item) { - $this->add($item); - } - } - - /** - * Builds an AcceptHeader instance from a string. - * - * @return self - */ - public static function fromString(?string $headerValue) - { - $index = 0; - - $parts = HeaderUtils::split($headerValue ?? '', ',;='); - - return new self(array_map(function ($subParts) use (&$index) { - $part = array_shift($subParts); - $attributes = HeaderUtils::combine($subParts); - - $item = new AcceptHeaderItem($part[0], $attributes); - $item->setIndex($index++); - - return $item; - }, $parts)); - } - - /** - * Returns header value's string representation. - * - * @return string - */ - public function __toString() - { - return implode(',', $this->items); - } - - /** - * Tests if header has given value. - * - * @return bool - */ - public function has(string $value) - { - return isset($this->items[$value]); - } - - /** - * Returns given value's item, if exists. - * - * @return AcceptHeaderItem|null - */ - public function get(string $value) - { - return $this->items[$value] ?? $this->items[explode('/', $value)[0].'/*'] ?? $this->items['*/*'] ?? $this->items['*'] ?? null; - } - - /** - * Adds an item. - * - * @return $this - */ - public function add(AcceptHeaderItem $item) - { - $this->items[$item->getValue()] = $item; - $this->sorted = false; - - return $this; - } - - /** - * Returns all items. - * - * @return AcceptHeaderItem[] - */ - public function all() - { - $this->sort(); - - return $this->items; - } - - /** - * Filters items on their value using given regex. - * - * @return self - */ - public function filter(string $pattern) - { - return new self(array_filter($this->items, function (AcceptHeaderItem $item) use ($pattern) { - return preg_match($pattern, $item->getValue()); - })); - } - - /** - * Returns first item. - * - * @return AcceptHeaderItem|null - */ - public function first() - { - $this->sort(); - - return !empty($this->items) ? reset($this->items) : null; - } - - /** - * Sorts items by descending quality. - */ - private function sort(): void - { - if (!$this->sorted) { - uasort($this->items, function (AcceptHeaderItem $a, AcceptHeaderItem $b) { - $qA = $a->getQuality(); - $qB = $b->getQuality(); - - if ($qA === $qB) { - return $a->getIndex() > $b->getIndex() ? 1 : -1; - } - - return $qA > $qB ? -1 : 1; - }); - - $this->sorted = true; - } - } -} diff --git a/lib/symfony/http-foundation/AcceptHeaderItem.php b/lib/symfony/http-foundation/AcceptHeaderItem.php deleted file mode 100644 index 8b86eee67..000000000 --- a/lib/symfony/http-foundation/AcceptHeaderItem.php +++ /dev/null @@ -1,177 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * Represents an Accept-* header item. - * - * @author Jean-François Simon <contact@jfsimon.fr> - */ -class AcceptHeaderItem -{ - private $value; - private $quality = 1.0; - private $index = 0; - private $attributes = []; - - public function __construct(string $value, array $attributes = []) - { - $this->value = $value; - foreach ($attributes as $name => $value) { - $this->setAttribute($name, $value); - } - } - - /** - * Builds an AcceptHeaderInstance instance from a string. - * - * @return self - */ - public static function fromString(?string $itemValue) - { - $parts = HeaderUtils::split($itemValue ?? '', ';='); - - $part = array_shift($parts); - $attributes = HeaderUtils::combine($parts); - - return new self($part[0], $attributes); - } - - /** - * Returns header value's string representation. - * - * @return string - */ - public function __toString() - { - $string = $this->value.($this->quality < 1 ? ';q='.$this->quality : ''); - if (\count($this->attributes) > 0) { - $string .= '; '.HeaderUtils::toString($this->attributes, ';'); - } - - return $string; - } - - /** - * Set the item value. - * - * @return $this - */ - public function setValue(string $value) - { - $this->value = $value; - - return $this; - } - - /** - * Returns the item value. - * - * @return string - */ - public function getValue() - { - return $this->value; - } - - /** - * Set the item quality. - * - * @return $this - */ - public function setQuality(float $quality) - { - $this->quality = $quality; - - return $this; - } - - /** - * Returns the item quality. - * - * @return float - */ - public function getQuality() - { - return $this->quality; - } - - /** - * Set the item index. - * - * @return $this - */ - public function setIndex(int $index) - { - $this->index = $index; - - return $this; - } - - /** - * Returns the item index. - * - * @return int - */ - public function getIndex() - { - return $this->index; - } - - /** - * Tests if an attribute exists. - * - * @return bool - */ - public function hasAttribute(string $name) - { - return isset($this->attributes[$name]); - } - - /** - * Returns an attribute by its name. - * - * @param mixed $default - * - * @return mixed - */ - public function getAttribute(string $name, $default = null) - { - return $this->attributes[$name] ?? $default; - } - - /** - * Returns all attributes. - * - * @return array - */ - public function getAttributes() - { - return $this->attributes; - } - - /** - * Set an attribute. - * - * @return $this - */ - public function setAttribute(string $name, string $value) - { - if ('q' === $name) { - $this->quality = (float) $value; - } else { - $this->attributes[$name] = $value; - } - - return $this; - } -} diff --git a/lib/symfony/http-foundation/BinaryFileResponse.php b/lib/symfony/http-foundation/BinaryFileResponse.php deleted file mode 100644 index 6d7b80ad1..000000000 --- a/lib/symfony/http-foundation/BinaryFileResponse.php +++ /dev/null @@ -1,407 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\HttpFoundation\File\Exception\FileException; -use Symfony\Component\HttpFoundation\File\File; - -/** - * BinaryFileResponse represents an HTTP response delivering a file. - * - * @author Niklas Fiekas <niklas.fiekas@tu-clausthal.de> - * @author stealth35 <stealth35-php@live.fr> - * @author Igor Wiedler <igor@wiedler.ch> - * @author Jordan Alliot <jordan.alliot@gmail.com> - * @author Sergey Linnik <linniksa@gmail.com> - */ -class BinaryFileResponse extends Response -{ - protected static $trustXSendfileTypeHeader = false; - - /** - * @var File - */ - protected $file; - protected $offset = 0; - protected $maxlen = -1; - protected $deleteFileAfterSend = false; - protected $chunkSize = 8 * 1024; - - /** - * @param \SplFileInfo|string $file The file to stream - * @param int $status The response status code - * @param array $headers An array of response headers - * @param bool $public Files are public by default - * @param string|null $contentDisposition The type of Content-Disposition to set automatically with the filename - * @param bool $autoEtag Whether the ETag header should be automatically set - * @param bool $autoLastModified Whether the Last-Modified header should be automatically set - */ - public function __construct($file, int $status = 200, array $headers = [], bool $public = true, string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) - { - parent::__construct(null, $status, $headers); - - $this->setFile($file, $contentDisposition, $autoEtag, $autoLastModified); - - if ($public) { - $this->setPublic(); - } - } - - /** - * @param \SplFileInfo|string $file The file to stream - * @param int $status The response status code - * @param array $headers An array of response headers - * @param bool $public Files are public by default - * @param string|null $contentDisposition The type of Content-Disposition to set automatically with the filename - * @param bool $autoEtag Whether the ETag header should be automatically set - * @param bool $autoLastModified Whether the Last-Modified header should be automatically set - * - * @return static - * - * @deprecated since Symfony 5.2, use __construct() instead. - */ - public static function create($file = null, int $status = 200, array $headers = [], bool $public = true, string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) - { - trigger_deprecation('symfony/http-foundation', '5.2', 'The "%s()" method is deprecated, use "new %s()" instead.', __METHOD__, static::class); - - return new static($file, $status, $headers, $public, $contentDisposition, $autoEtag, $autoLastModified); - } - - /** - * Sets the file to stream. - * - * @param \SplFileInfo|string $file The file to stream - * - * @return $this - * - * @throws FileException - */ - public function setFile($file, string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) - { - if (!$file instanceof File) { - if ($file instanceof \SplFileInfo) { - $file = new File($file->getPathname()); - } else { - $file = new File((string) $file); - } - } - - if (!$file->isReadable()) { - throw new FileException('File must be readable.'); - } - - $this->file = $file; - - if ($autoEtag) { - $this->setAutoEtag(); - } - - if ($autoLastModified) { - $this->setAutoLastModified(); - } - - if ($contentDisposition) { - $this->setContentDisposition($contentDisposition); - } - - return $this; - } - - /** - * Gets the file. - * - * @return File - */ - public function getFile() - { - return $this->file; - } - - /** - * Sets the response stream chunk size. - * - * @return $this - */ - public function setChunkSize(int $chunkSize): self - { - if ($chunkSize < 1 || $chunkSize > \PHP_INT_MAX) { - throw new \LogicException('The chunk size of a BinaryFileResponse cannot be less than 1 or greater than PHP_INT_MAX.'); - } - - $this->chunkSize = $chunkSize; - - return $this; - } - - /** - * Automatically sets the Last-Modified header according the file modification date. - * - * @return $this - */ - public function setAutoLastModified() - { - $this->setLastModified(\DateTime::createFromFormat('U', $this->file->getMTime())); - - return $this; - } - - /** - * Automatically sets the ETag header according to the checksum of the file. - * - * @return $this - */ - public function setAutoEtag() - { - $this->setEtag(base64_encode(hash_file('sha256', $this->file->getPathname(), true))); - - return $this; - } - - /** - * Sets the Content-Disposition header with the given filename. - * - * @param string $disposition ResponseHeaderBag::DISPOSITION_INLINE or ResponseHeaderBag::DISPOSITION_ATTACHMENT - * @param string $filename Optionally use this UTF-8 encoded filename instead of the real name of the file - * @param string $filenameFallback A fallback filename, containing only ASCII characters. Defaults to an automatically encoded filename - * - * @return $this - */ - public function setContentDisposition(string $disposition, string $filename = '', string $filenameFallback = '') - { - if ('' === $filename) { - $filename = $this->file->getFilename(); - } - - if ('' === $filenameFallback && (!preg_match('/^[\x20-\x7e]*$/', $filename) || str_contains($filename, '%'))) { - $encoding = mb_detect_encoding($filename, null, true) ?: '8bit'; - - for ($i = 0, $filenameLength = mb_strlen($filename, $encoding); $i < $filenameLength; ++$i) { - $char = mb_substr($filename, $i, 1, $encoding); - - if ('%' === $char || \ord($char) < 32 || \ord($char) > 126) { - $filenameFallback .= '_'; - } else { - $filenameFallback .= $char; - } - } - } - - $dispositionHeader = $this->headers->makeDisposition($disposition, $filename, $filenameFallback); - $this->headers->set('Content-Disposition', $dispositionHeader); - - return $this; - } - - /** - * {@inheritdoc} - */ - public function prepare(Request $request) - { - if ($this->isInformational() || $this->isEmpty()) { - parent::prepare($request); - - $this->maxlen = 0; - - return $this; - } - - if (!$this->headers->has('Content-Type')) { - $this->headers->set('Content-Type', $this->file->getMimeType() ?: 'application/octet-stream'); - } - - parent::prepare($request); - - $this->offset = 0; - $this->maxlen = -1; - - if (false === $fileSize = $this->file->getSize()) { - return $this; - } - $this->headers->remove('Transfer-Encoding'); - $this->headers->set('Content-Length', $fileSize); - - if (!$this->headers->has('Accept-Ranges')) { - // Only accept ranges on safe HTTP methods - $this->headers->set('Accept-Ranges', $request->isMethodSafe() ? 'bytes' : 'none'); - } - - if (self::$trustXSendfileTypeHeader && $request->headers->has('X-Sendfile-Type')) { - // Use X-Sendfile, do not send any content. - $type = $request->headers->get('X-Sendfile-Type'); - $path = $this->file->getRealPath(); - // Fall back to scheme://path for stream wrapped locations. - if (false === $path) { - $path = $this->file->getPathname(); - } - if ('x-accel-redirect' === strtolower($type)) { - // Do X-Accel-Mapping substitutions. - // @link https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/#x-accel-redirect - $parts = HeaderUtils::split($request->headers->get('X-Accel-Mapping', ''), ',='); - foreach ($parts as $part) { - [$pathPrefix, $location] = $part; - if (substr($path, 0, \strlen($pathPrefix)) === $pathPrefix) { - $path = $location.substr($path, \strlen($pathPrefix)); - // Only set X-Accel-Redirect header if a valid URI can be produced - // as nginx does not serve arbitrary file paths. - $this->headers->set($type, $path); - $this->maxlen = 0; - break; - } - } - } else { - $this->headers->set($type, $path); - $this->maxlen = 0; - } - } elseif ($request->headers->has('Range') && $request->isMethod('GET')) { - // Process the range headers. - if (!$request->headers->has('If-Range') || $this->hasValidIfRangeHeader($request->headers->get('If-Range'))) { - $range = $request->headers->get('Range'); - - if (str_starts_with($range, 'bytes=')) { - [$start, $end] = explode('-', substr($range, 6), 2) + [0]; - - $end = ('' === $end) ? $fileSize - 1 : (int) $end; - - if ('' === $start) { - $start = $fileSize - $end; - $end = $fileSize - 1; - } else { - $start = (int) $start; - } - - if ($start <= $end) { - $end = min($end, $fileSize - 1); - if ($start < 0 || $start > $end) { - $this->setStatusCode(416); - $this->headers->set('Content-Range', sprintf('bytes */%s', $fileSize)); - } elseif ($end - $start < $fileSize - 1) { - $this->maxlen = $end < $fileSize ? $end - $start + 1 : -1; - $this->offset = $start; - - $this->setStatusCode(206); - $this->headers->set('Content-Range', sprintf('bytes %s-%s/%s', $start, $end, $fileSize)); - $this->headers->set('Content-Length', $end - $start + 1); - } - } - } - } - } - - if ($request->isMethod('HEAD')) { - $this->maxlen = 0; - } - - return $this; - } - - private function hasValidIfRangeHeader(?string $header): bool - { - if ($this->getEtag() === $header) { - return true; - } - - if (null === $lastModified = $this->getLastModified()) { - return false; - } - - return $lastModified->format('D, d M Y H:i:s').' GMT' === $header; - } - - /** - * {@inheritdoc} - */ - public function sendContent() - { - try { - if (!$this->isSuccessful()) { - return parent::sendContent(); - } - - if (0 === $this->maxlen) { - return $this; - } - - $out = fopen('php://output', 'w'); - $file = fopen($this->file->getPathname(), 'r'); - - ignore_user_abort(true); - - if (0 !== $this->offset) { - fseek($file, $this->offset); - } - - $length = $this->maxlen; - while ($length && !feof($file)) { - $read = ($length > $this->chunkSize) ? $this->chunkSize : $length; - $length -= $read; - - stream_copy_to_stream($file, $out, $read); - - if (connection_aborted()) { - break; - } - } - - fclose($out); - fclose($file); - } finally { - if ($this->deleteFileAfterSend && is_file($this->file->getPathname())) { - unlink($this->file->getPathname()); - } - } - - return $this; - } - - /** - * {@inheritdoc} - * - * @throws \LogicException when the content is not null - */ - public function setContent(?string $content) - { - if (null !== $content) { - throw new \LogicException('The content cannot be set on a BinaryFileResponse instance.'); - } - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getContent() - { - return false; - } - - /** - * Trust X-Sendfile-Type header. - */ - public static function trustXSendfileTypeHeader() - { - self::$trustXSendfileTypeHeader = true; - } - - /** - * If this is set to true, the file will be unlinked after the request is sent - * Note: If the X-Sendfile header is used, the deleteFileAfterSend setting will not be used. - * - * @return $this - */ - public function deleteFileAfterSend(bool $shouldDelete = true) - { - $this->deleteFileAfterSend = $shouldDelete; - - return $this; - } -} diff --git a/lib/symfony/http-foundation/CHANGELOG.md b/lib/symfony/http-foundation/CHANGELOG.md deleted file mode 100644 index ad7607add..000000000 --- a/lib/symfony/http-foundation/CHANGELOG.md +++ /dev/null @@ -1,296 +0,0 @@ -CHANGELOG -========= - -5.4 ---- - - * Deprecate passing `null` as `$requestIp` to `IpUtils::__checkIp()`, `IpUtils::__checkIp4()` or `IpUtils::__checkIp6()`, pass an empty string instead. - * Add the `litespeed_finish_request` method to work with Litespeed - * Deprecate `upload_progress.*` and `url_rewriter.tags` session options - * Allow setting session options via DSN - -5.3 ---- - - * Add the `SessionFactory`, `NativeSessionStorageFactory`, `PhpBridgeSessionStorageFactory` and `MockFileSessionStorageFactory` classes - * Calling `Request::getSession()` when there is no available session throws a `SessionNotFoundException` - * Add the `RequestStack::getSession` method - * Deprecate the `NamespacedAttributeBag` class - * Add `ResponseFormatSame` PHPUnit constraint - * Deprecate the `RequestStack::getMasterRequest()` method and add `getMainRequest()` as replacement - -5.2.0 ------ - - * added support for `X-Forwarded-Prefix` header - * added `HeaderUtils::parseQuery()`: it does the same as `parse_str()` but preserves dots in variable names - * added `File::getContent()` - * added ability to use comma separated ip addresses for `RequestMatcher::matchIps()` - * added `Request::toArray()` to parse a JSON request body to an array - * added `RateLimiter\RequestRateLimiterInterface` and `RateLimiter\AbstractRequestRateLimiter` - * deprecated not passing a `Closure` together with `FILTER_CALLBACK` to `ParameterBag::filter()`; wrap your filter in a closure instead. - * Deprecated the `Request::HEADER_X_FORWARDED_ALL` constant, use either `HEADER_X_FORWARDED_FOR | HEADER_X_FORWARDED_HOST | HEADER_X_FORWARDED_PORT | HEADER_X_FORWARDED_PROTO` or `HEADER_X_FORWARDED_AWS_ELB` or `HEADER_X_FORWARDED_TRAEFIK` constants instead. - * Deprecated `BinaryFileResponse::create()`, use `__construct()` instead - -5.1.0 ------ - - * added `Cookie::withValue`, `Cookie::withDomain`, `Cookie::withExpires`, - `Cookie::withPath`, `Cookie::withSecure`, `Cookie::withHttpOnly`, - `Cookie::withRaw`, `Cookie::withSameSite` - * Deprecate `Response::create()`, `JsonResponse::create()`, - `RedirectResponse::create()`, and `StreamedResponse::create()` methods (use - `__construct()` instead) - * added `Request::preferSafeContent()` and `Response::setContentSafe()` to handle "safe" HTTP preference - according to [RFC 8674](https://tools.ietf.org/html/rfc8674) - * made the Mime component an optional dependency - * added `MarshallingSessionHandler`, `IdentityMarshaller` - * made `Session` accept a callback to report when the session is being used - * Add support for all core cache control directives - * Added `Symfony\Component\HttpFoundation\InputBag` - * Deprecated retrieving non-string values using `InputBag::get()`, use `InputBag::all()` if you need access to the collection of values - -5.0.0 ------ - - * made `Cookie` auto-secure and lax by default - * removed classes in the `MimeType` namespace, use the Symfony Mime component instead - * removed method `UploadedFile::getClientSize()` and the related constructor argument - * made `Request::getSession()` throw if the session has not been set before - * removed `Response::HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL` - * passing a null url when instantiating a `RedirectResponse` is not allowed - -4.4.0 ------ - - * passing arguments to `Request::isMethodSafe()` is deprecated. - * `ApacheRequest` is deprecated, use the `Request` class instead. - * passing a third argument to `HeaderBag::get()` is deprecated, use method `all()` instead - * [BC BREAK] `PdoSessionHandler` with MySQL changed the type of the lifetime column, - make sure to run `ALTER TABLE sessions MODIFY sess_lifetime INTEGER UNSIGNED NOT NULL` to - update your database. - * `PdoSessionHandler` now precalculates the expiry timestamp in the lifetime column, - make sure to run `CREATE INDEX EXPIRY ON sessions (sess_lifetime)` to update your database - to speed up garbage collection of expired sessions. - * added `SessionHandlerFactory` to create session handlers with a DSN - * added `IpUtils::anonymize()` to help with GDPR compliance. - -4.3.0 ------ - - * added PHPUnit constraints: `RequestAttributeValueSame`, `ResponseCookieValueSame`, `ResponseHasCookie`, - `ResponseHasHeader`, `ResponseHeaderSame`, `ResponseIsRedirected`, `ResponseIsSuccessful`, and `ResponseStatusCodeSame` - * deprecated `MimeTypeGuesserInterface` and `ExtensionGuesserInterface` in favor of `Symfony\Component\Mime\MimeTypesInterface`. - * deprecated `MimeType` and `MimeTypeExtensionGuesser` in favor of `Symfony\Component\Mime\MimeTypes`. - * deprecated `FileBinaryMimeTypeGuesser` in favor of `Symfony\Component\Mime\FileBinaryMimeTypeGuesser`. - * deprecated `FileinfoMimeTypeGuesser` in favor of `Symfony\Component\Mime\FileinfoMimeTypeGuesser`. - * added `UrlHelper` that allows to get an absolute URL and a relative path for a given path - -4.2.0 ------ - - * the default value of the "$secure" and "$samesite" arguments of Cookie's constructor - will respectively change from "false" to "null" and from "null" to "lax" in Symfony - 5.0, you should define their values explicitly or use "Cookie::create()" instead. - * added `matchPort()` in RequestMatcher - -4.1.3 ------ - - * [BC BREAK] Support for the IIS-only `X_ORIGINAL_URL` and `X_REWRITE_URL` - HTTP headers has been dropped for security reasons. - -4.1.0 ------ - - * Query string normalization uses `parse_str()` instead of custom parsing logic. - * Passing the file size to the constructor of the `UploadedFile` class is deprecated. - * The `getClientSize()` method of the `UploadedFile` class is deprecated. Use `getSize()` instead. - * added `RedisSessionHandler` to use Redis as a session storage - * The `get()` method of the `AcceptHeader` class now takes into account the - `*` and `*/*` default values (if they are present in the Accept HTTP header) - when looking for items. - * deprecated `Request::getSession()` when no session has been set. Use `Request::hasSession()` instead. - * added `CannotWriteFileException`, `ExtensionFileException`, `FormSizeFileException`, - `IniSizeFileException`, `NoFileException`, `NoTmpDirFileException`, `PartialFileException` to - handle failed `UploadedFile`. - * added `MigratingSessionHandler` for migrating between two session handlers without losing sessions - * added `HeaderUtils`. - -4.0.0 ------ - - * the `Request::setTrustedHeaderName()` and `Request::getTrustedHeaderName()` - methods have been removed - * the `Request::HEADER_CLIENT_IP` constant has been removed, use - `Request::HEADER_X_FORWARDED_FOR` instead - * the `Request::HEADER_CLIENT_HOST` constant has been removed, use - `Request::HEADER_X_FORWARDED_HOST` instead - * the `Request::HEADER_CLIENT_PROTO` constant has been removed, use - `Request::HEADER_X_FORWARDED_PROTO` instead - * the `Request::HEADER_CLIENT_PORT` constant has been removed, use - `Request::HEADER_X_FORWARDED_PORT` instead - * checking for cacheable HTTP methods using the `Request::isMethodSafe()` - method (by not passing `false` as its argument) is not supported anymore and - throws a `\BadMethodCallException` - * the `WriteCheckSessionHandler`, `NativeSessionHandler` and `NativeProxy` classes have been removed - * setting session save handlers that do not implement `\SessionHandlerInterface` in - `NativeSessionStorage::setSaveHandler()` is not supported anymore and throws a - `\TypeError` - -3.4.0 ------ - - * implemented PHP 7.0's `SessionUpdateTimestampHandlerInterface` with a new - `AbstractSessionHandler` base class and a new `StrictSessionHandler` wrapper - * deprecated the `WriteCheckSessionHandler`, `NativeSessionHandler` and `NativeProxy` classes - * deprecated setting session save handlers that do not implement `\SessionHandlerInterface` in `NativeSessionStorage::setSaveHandler()` - * deprecated using `MongoDbSessionHandler` with the legacy mongo extension; use it with the mongodb/mongodb package and ext-mongodb instead - * deprecated `MemcacheSessionHandler`; use `MemcachedSessionHandler` instead - -3.3.0 ------ - - * the `Request::setTrustedProxies()` method takes a new `$trustedHeaderSet` argument, - see https://symfony.com/doc/current/deployment/proxies.html for more info, - * deprecated the `Request::setTrustedHeaderName()` and `Request::getTrustedHeaderName()` methods, - * added `File\Stream`, to be passed to `BinaryFileResponse` when the size of the served file is unknown, - disabling `Range` and `Content-Length` handling, switching to chunked encoding instead - * added the `Cookie::fromString()` method that allows to create a cookie from a - raw header string - -3.1.0 ------ - - * Added support for creating `JsonResponse` with a string of JSON data - -3.0.0 ------ - - * The precedence of parameters returned from `Request::get()` changed from "GET, PATH, BODY" to "PATH, GET, BODY" - -2.8.0 ------ - - * Finding deep items in `ParameterBag::get()` is deprecated since version 2.8 and - will be removed in 3.0. - -2.6.0 ------ - - * PdoSessionHandler changes - - implemented different session locking strategies to prevent loss of data by concurrent access to the same session - - [BC BREAK] save session data in a binary column without base64_encode - - [BC BREAK] added lifetime column to the session table which allows to have different lifetimes for each session - - implemented lazy connections that are only opened when a session is used by either passing a dsn string - explicitly or falling back to session.save_path ini setting - - added a createTable method that initializes a correctly defined table depending on the database vendor - -2.5.0 ------ - - * added `JsonResponse::setEncodingOptions()` & `JsonResponse::getEncodingOptions()` for easier manipulation - of the options used while encoding data to JSON format. - -2.4.0 ------ - - * added RequestStack - * added Request::getEncodings() - * added accessors methods to session handlers - -2.3.0 ------ - - * added support for ranges of IPs in trusted proxies - * `UploadedFile::isValid` now returns false if the file was not uploaded via HTTP (in a non-test mode) - * Improved error-handling of `\Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler` - to ensure the supplied PDO handler throws Exceptions on error (as the class expects). Added related test cases - to verify that Exceptions are properly thrown when the PDO queries fail. - -2.2.0 ------ - - * fixed the Request::create() precedence (URI information always take precedence now) - * added Request::getTrustedProxies() - * deprecated Request::isProxyTrusted() - * [BC BREAK] JsonResponse does not turn a top level empty array to an object anymore, use an ArrayObject to enforce objects - * added a IpUtils class to check if an IP belongs to a CIDR - * added Request::getRealMethod() to get the "real" HTTP method (getMethod() returns the "intended" HTTP method) - * disabled _method request parameter support by default (call Request::enableHttpMethodParameterOverride() to - enable it, and Request::getHttpMethodParameterOverride() to check if it is supported) - * Request::splitHttpAcceptHeader() method is deprecated and will be removed in 2.3 - * Deprecated Flashbag::count() and \Countable interface, will be removed in 2.3 - -2.1.0 ------ - - * added Request::getSchemeAndHttpHost() and Request::getUserInfo() - * added a fluent interface to the Response class - * added Request::isProxyTrusted() - * added JsonResponse - * added a getTargetUrl method to RedirectResponse - * added support for streamed responses - * made Response::prepare() method the place to enforce HTTP specification - * [BC BREAK] moved management of the locale from the Session class to the Request class - * added a generic access to the PHP built-in filter mechanism: ParameterBag::filter() - * made FileBinaryMimeTypeGuesser command configurable - * added Request::getUser() and Request::getPassword() - * added support for the PATCH method in Request - * removed the ContentTypeMimeTypeGuesser class as it is deprecated and never used on PHP 5.3 - * added ResponseHeaderBag::makeDisposition() (implements RFC 6266) - * made mimetype to extension conversion configurable - * [BC BREAK] Moved all session related classes and interfaces into own namespace, as - `Symfony\Component\HttpFoundation\Session` and renamed classes accordingly. - Session handlers are located in the subnamespace `Symfony\Component\HttpFoundation\Session\Handler`. - * SessionHandlers must implement `\SessionHandlerInterface` or extend from the - `Symfony\Component\HttpFoundation\Storage\Handler\NativeSessionHandler` base class. - * Added internal storage driver proxy mechanism for forward compatibility with - PHP 5.4 `\SessionHandler` class. - * Added session handlers for custom Memcache, Memcached and Null session save handlers. - * [BC BREAK] Removed `NativeSessionStorage` and replaced with `NativeFileSessionHandler`. - * [BC BREAK] `SessionStorageInterface` methods removed: `write()`, `read()` and - `remove()`. Added `getBag()`, `registerBag()`. The `NativeSessionStorage` class - is a mediator for the session storage internals including the session handlers - which do the real work of participating in the internal PHP session workflow. - * [BC BREAK] Introduced mock implementations of `SessionStorage` to enable unit - and functional testing without starting real PHP sessions. Removed - `ArraySessionStorage`, and replaced with `MockArraySessionStorage` for unit - tests; removed `FilesystemSessionStorage`, and replaced with`MockFileSessionStorage` - for functional tests. These do not interact with global session ini - configuration values, session functions or `$_SESSION` superglobal. This means - they can be configured directly allowing multiple instances to work without - conflicting in the same PHP process. - * [BC BREAK] Removed the `close()` method from the `Session` class, as this is - now redundant. - * Deprecated the following methods from the Session class: `setFlash()`, `setFlashes()` - `getFlash()`, `hasFlash()`, and `removeFlash()`. Use `getFlashBag()` instead - which returns a `FlashBagInterface`. - * `Session->clear()` now only clears session attributes as before it cleared - flash messages and attributes. `Session->getFlashBag()->all()` clears flashes now. - * Session data is now managed by `SessionBagInterface` to better encapsulate - session data. - * Refactored session attribute and flash messages system to their own - `SessionBagInterface` implementations. - * Added `FlashBag`. Flashes expire when retrieved by `get()` or `all()`. This - implementation is ESI compatible. - * Added `AutoExpireFlashBag` (default) to replicate Symfony 2.0.x auto expire - behavior of messages auto expiring after one page page load. Messages must - be retrieved by `get()` or `all()`. - * Added `Symfony\Component\HttpFoundation\Attribute\AttributeBag` to replicate - attributes storage behavior from 2.0.x (default). - * Added `Symfony\Component\HttpFoundation\Attribute\NamespacedAttributeBag` for - namespace session attributes. - * Flash API can stores messages in an array so there may be multiple messages - per flash type. The old `Session` class API remains without BC break as it - will allow single messages as before. - * Added basic session meta-data to the session to record session create time, - last updated time, and the lifetime of the session cookie that was provided - to the client. - * Request::getClientIp() method doesn't take a parameter anymore but bases - itself on the trustProxy parameter. - * Added isMethod() to Request object. - * [BC BREAK] The methods `getPathInfo()`, `getBaseUrl()` and `getBasePath()` of - a `Request` now all return a raw value (vs a urldecoded value before). Any call - to one of these methods must be checked and wrapped in a `rawurldecode()` if - needed. diff --git a/lib/symfony/http-foundation/Cookie.php b/lib/symfony/http-foundation/Cookie.php deleted file mode 100644 index b4b26c015..000000000 --- a/lib/symfony/http-foundation/Cookie.php +++ /dev/null @@ -1,422 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * Represents a cookie. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -class Cookie -{ - public const SAMESITE_NONE = 'none'; - public const SAMESITE_LAX = 'lax'; - public const SAMESITE_STRICT = 'strict'; - - protected $name; - protected $value; - protected $domain; - protected $expire; - protected $path; - protected $secure; - protected $httpOnly; - - private $raw; - private $sameSite; - private $secureDefault = false; - - private const RESERVED_CHARS_LIST = "=,; \t\r\n\v\f"; - private const RESERVED_CHARS_FROM = ['=', ',', ';', ' ', "\t", "\r", "\n", "\v", "\f"]; - private const RESERVED_CHARS_TO = ['%3D', '%2C', '%3B', '%20', '%09', '%0D', '%0A', '%0B', '%0C']; - - /** - * Creates cookie from raw header string. - * - * @return static - */ - public static function fromString(string $cookie, bool $decode = false) - { - $data = [ - 'expires' => 0, - 'path' => '/', - 'domain' => null, - 'secure' => false, - 'httponly' => false, - 'raw' => !$decode, - 'samesite' => null, - ]; - - $parts = HeaderUtils::split($cookie, ';='); - $part = array_shift($parts); - - $name = $decode ? urldecode($part[0]) : $part[0]; - $value = isset($part[1]) ? ($decode ? urldecode($part[1]) : $part[1]) : null; - - $data = HeaderUtils::combine($parts) + $data; - $data['expires'] = self::expiresTimestamp($data['expires']); - - if (isset($data['max-age']) && ($data['max-age'] > 0 || $data['expires'] > time())) { - $data['expires'] = time() + (int) $data['max-age']; - } - - return new static($name, $value, $data['expires'], $data['path'], $data['domain'], $data['secure'], $data['httponly'], $data['raw'], $data['samesite']); - } - - public static function create(string $name, string $value = null, $expire = 0, ?string $path = '/', string $domain = null, bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = self::SAMESITE_LAX): self - { - return new self($name, $value, $expire, $path, $domain, $secure, $httpOnly, $raw, $sameSite); - } - - /** - * @param string $name The name of the cookie - * @param string|null $value The value of the cookie - * @param int|string|\DateTimeInterface $expire The time the cookie expires - * @param string $path The path on the server in which the cookie will be available on - * @param string|null $domain The domain that the cookie is available to - * @param bool|null $secure Whether the client should send back the cookie only over HTTPS or null to auto-enable this when the request is already using HTTPS - * @param bool $httpOnly Whether the cookie will be made accessible only through the HTTP protocol - * @param bool $raw Whether the cookie value should be sent with no url encoding - * @param string|null $sameSite Whether the cookie will be available for cross-site requests - * - * @throws \InvalidArgumentException - */ - public function __construct(string $name, string $value = null, $expire = 0, ?string $path = '/', string $domain = null, bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = 'lax') - { - // from PHP source code - if ($raw && false !== strpbrk($name, self::RESERVED_CHARS_LIST)) { - throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $name)); - } - - if (empty($name)) { - throw new \InvalidArgumentException('The cookie name cannot be empty.'); - } - - $this->name = $name; - $this->value = $value; - $this->domain = $domain; - $this->expire = self::expiresTimestamp($expire); - $this->path = empty($path) ? '/' : $path; - $this->secure = $secure; - $this->httpOnly = $httpOnly; - $this->raw = $raw; - $this->sameSite = $this->withSameSite($sameSite)->sameSite; - } - - /** - * Creates a cookie copy with a new value. - * - * @return static - */ - public function withValue(?string $value): self - { - $cookie = clone $this; - $cookie->value = $value; - - return $cookie; - } - - /** - * Creates a cookie copy with a new domain that the cookie is available to. - * - * @return static - */ - public function withDomain(?string $domain): self - { - $cookie = clone $this; - $cookie->domain = $domain; - - return $cookie; - } - - /** - * Creates a cookie copy with a new time the cookie expires. - * - * @param int|string|\DateTimeInterface $expire - * - * @return static - */ - public function withExpires($expire = 0): self - { - $cookie = clone $this; - $cookie->expire = self::expiresTimestamp($expire); - - return $cookie; - } - - /** - * Converts expires formats to a unix timestamp. - * - * @param int|string|\DateTimeInterface $expire - */ - private static function expiresTimestamp($expire = 0): int - { - // convert expiration time to a Unix timestamp - if ($expire instanceof \DateTimeInterface) { - $expire = $expire->format('U'); - } elseif (!is_numeric($expire)) { - $expire = strtotime($expire); - - if (false === $expire) { - throw new \InvalidArgumentException('The cookie expiration time is not valid.'); - } - } - - return 0 < $expire ? (int) $expire : 0; - } - - /** - * Creates a cookie copy with a new path on the server in which the cookie will be available on. - * - * @return static - */ - public function withPath(string $path): self - { - $cookie = clone $this; - $cookie->path = '' === $path ? '/' : $path; - - return $cookie; - } - - /** - * Creates a cookie copy that only be transmitted over a secure HTTPS connection from the client. - * - * @return static - */ - public function withSecure(bool $secure = true): self - { - $cookie = clone $this; - $cookie->secure = $secure; - - return $cookie; - } - - /** - * Creates a cookie copy that be accessible only through the HTTP protocol. - * - * @return static - */ - public function withHttpOnly(bool $httpOnly = true): self - { - $cookie = clone $this; - $cookie->httpOnly = $httpOnly; - - return $cookie; - } - - /** - * Creates a cookie copy that uses no url encoding. - * - * @return static - */ - public function withRaw(bool $raw = true): self - { - if ($raw && false !== strpbrk($this->name, self::RESERVED_CHARS_LIST)) { - throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $this->name)); - } - - $cookie = clone $this; - $cookie->raw = $raw; - - return $cookie; - } - - /** - * Creates a cookie copy with SameSite attribute. - * - * @return static - */ - public function withSameSite(?string $sameSite): self - { - if ('' === $sameSite) { - $sameSite = null; - } elseif (null !== $sameSite) { - $sameSite = strtolower($sameSite); - } - - if (!\in_array($sameSite, [self::SAMESITE_LAX, self::SAMESITE_STRICT, self::SAMESITE_NONE, null], true)) { - throw new \InvalidArgumentException('The "sameSite" parameter value is not valid.'); - } - - $cookie = clone $this; - $cookie->sameSite = $sameSite; - - return $cookie; - } - - /** - * Returns the cookie as a string. - * - * @return string - */ - public function __toString() - { - if ($this->isRaw()) { - $str = $this->getName(); - } else { - $str = str_replace(self::RESERVED_CHARS_FROM, self::RESERVED_CHARS_TO, $this->getName()); - } - - $str .= '='; - - if ('' === (string) $this->getValue()) { - $str .= 'deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; Max-Age=0'; - } else { - $str .= $this->isRaw() ? $this->getValue() : rawurlencode($this->getValue()); - - if (0 !== $this->getExpiresTime()) { - $str .= '; expires='.gmdate('D, d-M-Y H:i:s T', $this->getExpiresTime()).'; Max-Age='.$this->getMaxAge(); - } - } - - if ($this->getPath()) { - $str .= '; path='.$this->getPath(); - } - - if ($this->getDomain()) { - $str .= '; domain='.$this->getDomain(); - } - - if (true === $this->isSecure()) { - $str .= '; secure'; - } - - if (true === $this->isHttpOnly()) { - $str .= '; httponly'; - } - - if (null !== $this->getSameSite()) { - $str .= '; samesite='.$this->getSameSite(); - } - - return $str; - } - - /** - * Gets the name of the cookie. - * - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * Gets the value of the cookie. - * - * @return string|null - */ - public function getValue() - { - return $this->value; - } - - /** - * Gets the domain that the cookie is available to. - * - * @return string|null - */ - public function getDomain() - { - return $this->domain; - } - - /** - * Gets the time the cookie expires. - * - * @return int - */ - public function getExpiresTime() - { - return $this->expire; - } - - /** - * Gets the max-age attribute. - * - * @return int - */ - public function getMaxAge() - { - $maxAge = $this->expire - time(); - - return 0 >= $maxAge ? 0 : $maxAge; - } - - /** - * Gets the path on the server in which the cookie will be available on. - * - * @return string - */ - public function getPath() - { - return $this->path; - } - - /** - * Checks whether the cookie should only be transmitted over a secure HTTPS connection from the client. - * - * @return bool - */ - public function isSecure() - { - return $this->secure ?? $this->secureDefault; - } - - /** - * Checks whether the cookie will be made accessible only through the HTTP protocol. - * - * @return bool - */ - public function isHttpOnly() - { - return $this->httpOnly; - } - - /** - * Whether this cookie is about to be cleared. - * - * @return bool - */ - public function isCleared() - { - return 0 !== $this->expire && $this->expire < time(); - } - - /** - * Checks if the cookie value should be sent with no url encoding. - * - * @return bool - */ - public function isRaw() - { - return $this->raw; - } - - /** - * Gets the SameSite attribute. - * - * @return string|null - */ - public function getSameSite() - { - return $this->sameSite; - } - - /** - * @param bool $default The default value of the "secure" flag when it is set to null - */ - public function setSecureDefault(bool $default): void - { - $this->secureDefault = $default; - } -} diff --git a/lib/symfony/http-foundation/Exception/BadRequestException.php b/lib/symfony/http-foundation/Exception/BadRequestException.php deleted file mode 100644 index e4bb309c4..000000000 --- a/lib/symfony/http-foundation/Exception/BadRequestException.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -/** - * Raised when a user sends a malformed request. - */ -class BadRequestException extends \UnexpectedValueException implements RequestExceptionInterface -{ -} diff --git a/lib/symfony/http-foundation/Exception/ConflictingHeadersException.php b/lib/symfony/http-foundation/Exception/ConflictingHeadersException.php deleted file mode 100644 index 5fcf5b426..000000000 --- a/lib/symfony/http-foundation/Exception/ConflictingHeadersException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -/** - * The HTTP request contains headers with conflicting information. - * - * @author Magnus Nordlander <magnus@fervo.se> - */ -class ConflictingHeadersException extends \UnexpectedValueException implements RequestExceptionInterface -{ -} diff --git a/lib/symfony/http-foundation/Exception/JsonException.php b/lib/symfony/http-foundation/Exception/JsonException.php deleted file mode 100644 index 5990e760e..000000000 --- a/lib/symfony/http-foundation/Exception/JsonException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -/** - * Thrown by Request::toArray() when the content cannot be JSON-decoded. - * - * @author Tobias Nyholm <tobias.nyholm@gmail.com> - */ -final class JsonException extends \UnexpectedValueException implements RequestExceptionInterface -{ -} diff --git a/lib/symfony/http-foundation/Exception/RequestExceptionInterface.php b/lib/symfony/http-foundation/Exception/RequestExceptionInterface.php deleted file mode 100644 index 478d0dc7e..000000000 --- a/lib/symfony/http-foundation/Exception/RequestExceptionInterface.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -/** - * Interface for Request exceptions. - * - * Exceptions implementing this interface should trigger an HTTP 400 response in the application code. - */ -interface RequestExceptionInterface -{ -} diff --git a/lib/symfony/http-foundation/Exception/SessionNotFoundException.php b/lib/symfony/http-foundation/Exception/SessionNotFoundException.php deleted file mode 100644 index 94b0cb69a..000000000 --- a/lib/symfony/http-foundation/Exception/SessionNotFoundException.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -/** - * Raised when a session does not exist. This happens in the following cases: - * - the session is not enabled - * - attempt to read a session outside a request context (ie. cli script). - * - * @author Jérémy Derussé <jeremy@derusse.com> - */ -class SessionNotFoundException extends \LogicException implements RequestExceptionInterface -{ - public function __construct(string $message = 'There is currently no session available.', int $code = 0, \Throwable $previous = null) - { - parent::__construct($message, $code, $previous); - } -} diff --git a/lib/symfony/http-foundation/Exception/SuspiciousOperationException.php b/lib/symfony/http-foundation/Exception/SuspiciousOperationException.php deleted file mode 100644 index ae7a5f133..000000000 --- a/lib/symfony/http-foundation/Exception/SuspiciousOperationException.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -/** - * Raised when a user has performed an operation that should be considered - * suspicious from a security perspective. - */ -class SuspiciousOperationException extends \UnexpectedValueException implements RequestExceptionInterface -{ -} diff --git a/lib/symfony/http-foundation/ExpressionRequestMatcher.php b/lib/symfony/http-foundation/ExpressionRequestMatcher.php deleted file mode 100644 index 26bed7d37..000000000 --- a/lib/symfony/http-foundation/ExpressionRequestMatcher.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\ExpressionLanguage\ExpressionLanguage; - -/** - * ExpressionRequestMatcher uses an expression to match a Request. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class ExpressionRequestMatcher extends RequestMatcher -{ - private $language; - private $expression; - - public function setExpression(ExpressionLanguage $language, $expression) - { - $this->language = $language; - $this->expression = $expression; - } - - public function matches(Request $request) - { - if (!$this->language) { - throw new \LogicException('Unable to match the request as the expression language is not available.'); - } - - return $this->language->evaluate($this->expression, [ - 'request' => $request, - 'method' => $request->getMethod(), - 'path' => rawurldecode($request->getPathInfo()), - 'host' => $request->getHost(), - 'ip' => $request->getClientIp(), - 'attributes' => $request->attributes->all(), - ]) && parent::matches($request); - } -} diff --git a/lib/symfony/http-foundation/File/Exception/AccessDeniedException.php b/lib/symfony/http-foundation/File/Exception/AccessDeniedException.php deleted file mode 100644 index 136d2a9f5..000000000 --- a/lib/symfony/http-foundation/File/Exception/AccessDeniedException.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when the access on a file was denied. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class AccessDeniedException extends FileException -{ - public function __construct(string $path) - { - parent::__construct(sprintf('The file %s could not be accessed', $path)); - } -} diff --git a/lib/symfony/http-foundation/File/Exception/CannotWriteFileException.php b/lib/symfony/http-foundation/File/Exception/CannotWriteFileException.php deleted file mode 100644 index c49f53a6c..000000000 --- a/lib/symfony/http-foundation/File/Exception/CannotWriteFileException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_CANT_WRITE error occurred with UploadedFile. - * - * @author Florent Mata <florentmata@gmail.com> - */ -class CannotWriteFileException extends FileException -{ -} diff --git a/lib/symfony/http-foundation/File/Exception/ExtensionFileException.php b/lib/symfony/http-foundation/File/Exception/ExtensionFileException.php deleted file mode 100644 index ed83499c0..000000000 --- a/lib/symfony/http-foundation/File/Exception/ExtensionFileException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_EXTENSION error occurred with UploadedFile. - * - * @author Florent Mata <florentmata@gmail.com> - */ -class ExtensionFileException extends FileException -{ -} diff --git a/lib/symfony/http-foundation/File/Exception/FileException.php b/lib/symfony/http-foundation/File/Exception/FileException.php deleted file mode 100644 index fad5133e1..000000000 --- a/lib/symfony/http-foundation/File/Exception/FileException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an error occurred in the component File. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class FileException extends \RuntimeException -{ -} diff --git a/lib/symfony/http-foundation/File/Exception/FileNotFoundException.php b/lib/symfony/http-foundation/File/Exception/FileNotFoundException.php deleted file mode 100644 index 31bdf68fe..000000000 --- a/lib/symfony/http-foundation/File/Exception/FileNotFoundException.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when a file was not found. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class FileNotFoundException extends FileException -{ - public function __construct(string $path) - { - parent::__construct(sprintf('The file "%s" does not exist', $path)); - } -} diff --git a/lib/symfony/http-foundation/File/Exception/FormSizeFileException.php b/lib/symfony/http-foundation/File/Exception/FormSizeFileException.php deleted file mode 100644 index 8741be088..000000000 --- a/lib/symfony/http-foundation/File/Exception/FormSizeFileException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_FORM_SIZE error occurred with UploadedFile. - * - * @author Florent Mata <florentmata@gmail.com> - */ -class FormSizeFileException extends FileException -{ -} diff --git a/lib/symfony/http-foundation/File/Exception/IniSizeFileException.php b/lib/symfony/http-foundation/File/Exception/IniSizeFileException.php deleted file mode 100644 index c8fde6103..000000000 --- a/lib/symfony/http-foundation/File/Exception/IniSizeFileException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_INI_SIZE error occurred with UploadedFile. - * - * @author Florent Mata <florentmata@gmail.com> - */ -class IniSizeFileException extends FileException -{ -} diff --git a/lib/symfony/http-foundation/File/Exception/NoFileException.php b/lib/symfony/http-foundation/File/Exception/NoFileException.php deleted file mode 100644 index 4b48cc779..000000000 --- a/lib/symfony/http-foundation/File/Exception/NoFileException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_NO_FILE error occurred with UploadedFile. - * - * @author Florent Mata <florentmata@gmail.com> - */ -class NoFileException extends FileException -{ -} diff --git a/lib/symfony/http-foundation/File/Exception/NoTmpDirFileException.php b/lib/symfony/http-foundation/File/Exception/NoTmpDirFileException.php deleted file mode 100644 index bdead2d91..000000000 --- a/lib/symfony/http-foundation/File/Exception/NoTmpDirFileException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_NO_TMP_DIR error occurred with UploadedFile. - * - * @author Florent Mata <florentmata@gmail.com> - */ -class NoTmpDirFileException extends FileException -{ -} diff --git a/lib/symfony/http-foundation/File/Exception/PartialFileException.php b/lib/symfony/http-foundation/File/Exception/PartialFileException.php deleted file mode 100644 index 4641efb55..000000000 --- a/lib/symfony/http-foundation/File/Exception/PartialFileException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_PARTIAL error occurred with UploadedFile. - * - * @author Florent Mata <florentmata@gmail.com> - */ -class PartialFileException extends FileException -{ -} diff --git a/lib/symfony/http-foundation/File/Exception/UnexpectedTypeException.php b/lib/symfony/http-foundation/File/Exception/UnexpectedTypeException.php deleted file mode 100644 index 8533f99a8..000000000 --- a/lib/symfony/http-foundation/File/Exception/UnexpectedTypeException.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -class UnexpectedTypeException extends FileException -{ - public function __construct($value, string $expectedType) - { - parent::__construct(sprintf('Expected argument of type %s, %s given', $expectedType, get_debug_type($value))); - } -} diff --git a/lib/symfony/http-foundation/File/Exception/UploadException.php b/lib/symfony/http-foundation/File/Exception/UploadException.php deleted file mode 100644 index 7074e7653..000000000 --- a/lib/symfony/http-foundation/File/Exception/UploadException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an error occurred during file upload. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class UploadException extends FileException -{ -} diff --git a/lib/symfony/http-foundation/File/File.php b/lib/symfony/http-foundation/File/File.php deleted file mode 100644 index d941577d2..000000000 --- a/lib/symfony/http-foundation/File/File.php +++ /dev/null @@ -1,152 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File; - -use Symfony\Component\HttpFoundation\File\Exception\FileException; -use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; -use Symfony\Component\Mime\MimeTypes; - -/** - * A file in the file system. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class File extends \SplFileInfo -{ - /** - * Constructs a new file from the given path. - * - * @param string $path The path to the file - * @param bool $checkPath Whether to check the path or not - * - * @throws FileNotFoundException If the given path is not a file - */ - public function __construct(string $path, bool $checkPath = true) - { - if ($checkPath && !is_file($path)) { - throw new FileNotFoundException($path); - } - - parent::__construct($path); - } - - /** - * Returns the extension based on the mime type. - * - * If the mime type is unknown, returns null. - * - * This method uses the mime type as guessed by getMimeType() - * to guess the file extension. - * - * @return string|null - * - * @see MimeTypes - * @see getMimeType() - */ - public function guessExtension() - { - if (!class_exists(MimeTypes::class)) { - throw new \LogicException('You cannot guess the extension as the Mime component is not installed. Try running "composer require symfony/mime".'); - } - - return MimeTypes::getDefault()->getExtensions($this->getMimeType())[0] ?? null; - } - - /** - * Returns the mime type of the file. - * - * The mime type is guessed using a MimeTypeGuesserInterface instance, - * which uses finfo_file() then the "file" system binary, - * depending on which of those are available. - * - * @return string|null - * - * @see MimeTypes - */ - public function getMimeType() - { - if (!class_exists(MimeTypes::class)) { - throw new \LogicException('You cannot guess the mime type as the Mime component is not installed. Try running "composer require symfony/mime".'); - } - - return MimeTypes::getDefault()->guessMimeType($this->getPathname()); - } - - /** - * Moves the file to a new location. - * - * @return self - * - * @throws FileException if the target file could not be created - */ - public function move(string $directory, string $name = null) - { - $target = $this->getTargetFile($directory, $name); - - set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); - try { - $renamed = rename($this->getPathname(), $target); - } finally { - restore_error_handler(); - } - if (!$renamed) { - throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s).', $this->getPathname(), $target, strip_tags($error))); - } - - @chmod($target, 0666 & ~umask()); - - return $target; - } - - public function getContent(): string - { - $content = file_get_contents($this->getPathname()); - - if (false === $content) { - throw new FileException(sprintf('Could not get the content of the file "%s".', $this->getPathname())); - } - - return $content; - } - - /** - * @return self - */ - protected function getTargetFile(string $directory, string $name = null) - { - if (!is_dir($directory)) { - if (false === @mkdir($directory, 0777, true) && !is_dir($directory)) { - throw new FileException(sprintf('Unable to create the "%s" directory.', $directory)); - } - } elseif (!is_writable($directory)) { - throw new FileException(sprintf('Unable to write in the "%s" directory.', $directory)); - } - - $target = rtrim($directory, '/\\').\DIRECTORY_SEPARATOR.(null === $name ? $this->getBasename() : $this->getName($name)); - - return new self($target, false); - } - - /** - * Returns locale independent base name of the given path. - * - * @return string - */ - protected function getName(string $name) - { - $originalName = str_replace('\\', '/', $name); - $pos = strrpos($originalName, '/'); - $originalName = false === $pos ? $originalName : substr($originalName, $pos + 1); - - return $originalName; - } -} diff --git a/lib/symfony/http-foundation/File/Stream.php b/lib/symfony/http-foundation/File/Stream.php deleted file mode 100644 index cef3e0397..000000000 --- a/lib/symfony/http-foundation/File/Stream.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File; - -/** - * A PHP stream of unknown size. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class Stream extends File -{ - /** - * {@inheritdoc} - * - * @return int|false - */ - #[\ReturnTypeWillChange] - public function getSize() - { - return false; - } -} diff --git a/lib/symfony/http-foundation/File/UploadedFile.php b/lib/symfony/http-foundation/File/UploadedFile.php deleted file mode 100644 index fcc629913..000000000 --- a/lib/symfony/http-foundation/File/UploadedFile.php +++ /dev/null @@ -1,290 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File; - -use Symfony\Component\HttpFoundation\File\Exception\CannotWriteFileException; -use Symfony\Component\HttpFoundation\File\Exception\ExtensionFileException; -use Symfony\Component\HttpFoundation\File\Exception\FileException; -use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; -use Symfony\Component\HttpFoundation\File\Exception\FormSizeFileException; -use Symfony\Component\HttpFoundation\File\Exception\IniSizeFileException; -use Symfony\Component\HttpFoundation\File\Exception\NoFileException; -use Symfony\Component\HttpFoundation\File\Exception\NoTmpDirFileException; -use Symfony\Component\HttpFoundation\File\Exception\PartialFileException; -use Symfony\Component\Mime\MimeTypes; - -/** - * A file uploaded through a form. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * @author Florian Eckerstorfer <florian@eckerstorfer.org> - * @author Fabien Potencier <fabien@symfony.com> - */ -class UploadedFile extends File -{ - private $test; - private $originalName; - private $mimeType; - private $error; - - /** - * Accepts the information of the uploaded file as provided by the PHP global $_FILES. - * - * The file object is only created when the uploaded file is valid (i.e. when the - * isValid() method returns true). Otherwise the only methods that could be called - * on an UploadedFile instance are: - * - * * getClientOriginalName, - * * getClientMimeType, - * * isValid, - * * getError. - * - * Calling any other method on an non-valid instance will cause an unpredictable result. - * - * @param string $path The full temporary path to the file - * @param string $originalName The original file name of the uploaded file - * @param string|null $mimeType The type of the file as provided by PHP; null defaults to application/octet-stream - * @param int|null $error The error constant of the upload (one of PHP's UPLOAD_ERR_XXX constants); null defaults to UPLOAD_ERR_OK - * @param bool $test Whether the test mode is active - * Local files are used in test mode hence the code should not enforce HTTP uploads - * - * @throws FileException If file_uploads is disabled - * @throws FileNotFoundException If the file does not exist - */ - public function __construct(string $path, string $originalName, string $mimeType = null, int $error = null, bool $test = false) - { - $this->originalName = $this->getName($originalName); - $this->mimeType = $mimeType ?: 'application/octet-stream'; - $this->error = $error ?: \UPLOAD_ERR_OK; - $this->test = $test; - - parent::__construct($path, \UPLOAD_ERR_OK === $this->error); - } - - /** - * Returns the original file name. - * - * It is extracted from the request from which the file has been uploaded. - * Then it should not be considered as a safe value. - * - * @return string - */ - public function getClientOriginalName() - { - return $this->originalName; - } - - /** - * Returns the original file extension. - * - * It is extracted from the original file name that was uploaded. - * Then it should not be considered as a safe value. - * - * @return string - */ - public function getClientOriginalExtension() - { - return pathinfo($this->originalName, \PATHINFO_EXTENSION); - } - - /** - * Returns the file mime type. - * - * The client mime type is extracted from the request from which the file - * was uploaded, so it should not be considered as a safe value. - * - * For a trusted mime type, use getMimeType() instead (which guesses the mime - * type based on the file content). - * - * @return string - * - * @see getMimeType() - */ - public function getClientMimeType() - { - return $this->mimeType; - } - - /** - * Returns the extension based on the client mime type. - * - * If the mime type is unknown, returns null. - * - * This method uses the mime type as guessed by getClientMimeType() - * to guess the file extension. As such, the extension returned - * by this method cannot be trusted. - * - * For a trusted extension, use guessExtension() instead (which guesses - * the extension based on the guessed mime type for the file). - * - * @return string|null - * - * @see guessExtension() - * @see getClientMimeType() - */ - public function guessClientExtension() - { - if (!class_exists(MimeTypes::class)) { - throw new \LogicException('You cannot guess the extension as the Mime component is not installed. Try running "composer require symfony/mime".'); - } - - return MimeTypes::getDefault()->getExtensions($this->getClientMimeType())[0] ?? null; - } - - /** - * Returns the upload error. - * - * If the upload was successful, the constant UPLOAD_ERR_OK is returned. - * Otherwise one of the other UPLOAD_ERR_XXX constants is returned. - * - * @return int - */ - public function getError() - { - return $this->error; - } - - /** - * Returns whether the file has been uploaded with HTTP and no error occurred. - * - * @return bool - */ - public function isValid() - { - $isOk = \UPLOAD_ERR_OK === $this->error; - - return $this->test ? $isOk : $isOk && is_uploaded_file($this->getPathname()); - } - - /** - * Moves the file to a new location. - * - * @return File - * - * @throws FileException if, for any reason, the file could not have been moved - */ - public function move(string $directory, string $name = null) - { - if ($this->isValid()) { - if ($this->test) { - return parent::move($directory, $name); - } - - $target = $this->getTargetFile($directory, $name); - - set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); - try { - $moved = move_uploaded_file($this->getPathname(), $target); - } finally { - restore_error_handler(); - } - if (!$moved) { - throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s).', $this->getPathname(), $target, strip_tags($error))); - } - - @chmod($target, 0666 & ~umask()); - - return $target; - } - - switch ($this->error) { - case \UPLOAD_ERR_INI_SIZE: - throw new IniSizeFileException($this->getErrorMessage()); - case \UPLOAD_ERR_FORM_SIZE: - throw new FormSizeFileException($this->getErrorMessage()); - case \UPLOAD_ERR_PARTIAL: - throw new PartialFileException($this->getErrorMessage()); - case \UPLOAD_ERR_NO_FILE: - throw new NoFileException($this->getErrorMessage()); - case \UPLOAD_ERR_CANT_WRITE: - throw new CannotWriteFileException($this->getErrorMessage()); - case \UPLOAD_ERR_NO_TMP_DIR: - throw new NoTmpDirFileException($this->getErrorMessage()); - case \UPLOAD_ERR_EXTENSION: - throw new ExtensionFileException($this->getErrorMessage()); - } - - throw new FileException($this->getErrorMessage()); - } - - /** - * Returns the maximum size of an uploaded file as configured in php.ini. - * - * @return int|float The maximum size of an uploaded file in bytes (returns float if size > PHP_INT_MAX) - */ - public static function getMaxFilesize() - { - $sizePostMax = self::parseFilesize(\ini_get('post_max_size')); - $sizeUploadMax = self::parseFilesize(\ini_get('upload_max_filesize')); - - return min($sizePostMax ?: \PHP_INT_MAX, $sizeUploadMax ?: \PHP_INT_MAX); - } - - /** - * Returns the given size from an ini value in bytes. - * - * @return int|float Returns float if size > PHP_INT_MAX - */ - private static function parseFilesize(string $size) - { - if ('' === $size) { - return 0; - } - - $size = strtolower($size); - - $max = ltrim($size, '+'); - if (str_starts_with($max, '0x')) { - $max = \intval($max, 16); - } elseif (str_starts_with($max, '0')) { - $max = \intval($max, 8); - } else { - $max = (int) $max; - } - - switch (substr($size, -1)) { - case 't': $max *= 1024; - // no break - case 'g': $max *= 1024; - // no break - case 'm': $max *= 1024; - // no break - case 'k': $max *= 1024; - } - - return $max; - } - - /** - * Returns an informative upload error message. - * - * @return string - */ - public function getErrorMessage() - { - static $errors = [ - \UPLOAD_ERR_INI_SIZE => 'The file "%s" exceeds your upload_max_filesize ini directive (limit is %d KiB).', - \UPLOAD_ERR_FORM_SIZE => 'The file "%s" exceeds the upload limit defined in your form.', - \UPLOAD_ERR_PARTIAL => 'The file "%s" was only partially uploaded.', - \UPLOAD_ERR_NO_FILE => 'No file was uploaded.', - \UPLOAD_ERR_CANT_WRITE => 'The file "%s" could not be written on disk.', - \UPLOAD_ERR_NO_TMP_DIR => 'File could not be uploaded: missing temporary directory.', - \UPLOAD_ERR_EXTENSION => 'File upload was stopped by a PHP extension.', - ]; - - $errorCode = $this->error; - $maxFilesize = \UPLOAD_ERR_INI_SIZE === $errorCode ? self::getMaxFilesize() / 1024 : 0; - $message = $errors[$errorCode] ?? 'The file "%s" was not uploaded due to an unknown error.'; - - return sprintf($message, $this->getClientOriginalName(), $maxFilesize); - } -} diff --git a/lib/symfony/http-foundation/FileBag.php b/lib/symfony/http-foundation/FileBag.php deleted file mode 100644 index ff5ab7778..000000000 --- a/lib/symfony/http-foundation/FileBag.php +++ /dev/null @@ -1,140 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\HttpFoundation\File\UploadedFile; - -/** - * FileBag is a container for uploaded files. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Bulat Shakirzyanov <mallluhuct@gmail.com> - */ -class FileBag extends ParameterBag -{ - private const FILE_KEYS = ['error', 'name', 'size', 'tmp_name', 'type']; - - /** - * @param array|UploadedFile[] $parameters An array of HTTP files - */ - public function __construct(array $parameters = []) - { - $this->replace($parameters); - } - - /** - * {@inheritdoc} - */ - public function replace(array $files = []) - { - $this->parameters = []; - $this->add($files); - } - - /** - * {@inheritdoc} - */ - public function set(string $key, $value) - { - if (!\is_array($value) && !$value instanceof UploadedFile) { - throw new \InvalidArgumentException('An uploaded file must be an array or an instance of UploadedFile.'); - } - - parent::set($key, $this->convertFileInformation($value)); - } - - /** - * {@inheritdoc} - */ - public function add(array $files = []) - { - foreach ($files as $key => $file) { - $this->set($key, $file); - } - } - - /** - * Converts uploaded files to UploadedFile instances. - * - * @param array|UploadedFile $file A (multi-dimensional) array of uploaded file information - * - * @return UploadedFile[]|UploadedFile|null - */ - protected function convertFileInformation($file) - { - if ($file instanceof UploadedFile) { - return $file; - } - - $file = $this->fixPhpFilesArray($file); - $keys = array_keys($file); - sort($keys); - - if (self::FILE_KEYS == $keys) { - if (\UPLOAD_ERR_NO_FILE == $file['error']) { - $file = null; - } else { - $file = new UploadedFile($file['tmp_name'], $file['name'], $file['type'], $file['error'], false); - } - } else { - $file = array_map(function ($v) { return $v instanceof UploadedFile || \is_array($v) ? $this->convertFileInformation($v) : $v; }, $file); - if (array_keys($keys) === $keys) { - $file = array_filter($file); - } - } - - return $file; - } - - /** - * Fixes a malformed PHP $_FILES array. - * - * PHP has a bug that the format of the $_FILES array differs, depending on - * whether the uploaded file fields had normal field names or array-like - * field names ("normal" vs. "parent[child]"). - * - * This method fixes the array to look like the "normal" $_FILES array. - * - * It's safe to pass an already converted array, in which case this method - * just returns the original array unmodified. - * - * @return array - */ - protected function fixPhpFilesArray(array $data) - { - // Remove extra key added by PHP 8.1. - unset($data['full_path']); - $keys = array_keys($data); - sort($keys); - - if (self::FILE_KEYS != $keys || !isset($data['name']) || !\is_array($data['name'])) { - return $data; - } - - $files = $data; - foreach (self::FILE_KEYS as $k) { - unset($files[$k]); - } - - foreach ($data['name'] as $key => $name) { - $files[$key] = $this->fixPhpFilesArray([ - 'error' => $data['error'][$key], - 'name' => $name, - 'type' => $data['type'][$key], - 'tmp_name' => $data['tmp_name'][$key], - 'size' => $data['size'][$key], - ]); - } - - return $files; - } -} diff --git a/lib/symfony/http-foundation/HeaderBag.php b/lib/symfony/http-foundation/HeaderBag.php deleted file mode 100644 index 4683a6840..000000000 --- a/lib/symfony/http-foundation/HeaderBag.php +++ /dev/null @@ -1,295 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * HeaderBag is a container for HTTP headers. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @implements \IteratorAggregate<string, list<string|null>> - */ -class HeaderBag implements \IteratorAggregate, \Countable -{ - protected const UPPER = '_ABCDEFGHIJKLMNOPQRSTUVWXYZ'; - protected const LOWER = '-abcdefghijklmnopqrstuvwxyz'; - - /** - * @var array<string, list<string|null>> - */ - protected $headers = []; - protected $cacheControl = []; - - public function __construct(array $headers = []) - { - foreach ($headers as $key => $values) { - $this->set($key, $values); - } - } - - /** - * Returns the headers as a string. - * - * @return string - */ - public function __toString() - { - if (!$headers = $this->all()) { - return ''; - } - - ksort($headers); - $max = max(array_map('strlen', array_keys($headers))) + 1; - $content = ''; - foreach ($headers as $name => $values) { - $name = ucwords($name, '-'); - foreach ($values as $value) { - $content .= sprintf("%-{$max}s %s\r\n", $name.':', $value); - } - } - - return $content; - } - - /** - * Returns the headers. - * - * @param string|null $key The name of the headers to return or null to get them all - * - * @return array<string, array<int, string|null>>|array<int, string|null> - */ - public function all(string $key = null) - { - if (null !== $key) { - return $this->headers[strtr($key, self::UPPER, self::LOWER)] ?? []; - } - - return $this->headers; - } - - /** - * Returns the parameter keys. - * - * @return string[] - */ - public function keys() - { - return array_keys($this->all()); - } - - /** - * Replaces the current HTTP headers by a new set. - */ - public function replace(array $headers = []) - { - $this->headers = []; - $this->add($headers); - } - - /** - * Adds new headers the current HTTP headers set. - */ - public function add(array $headers) - { - foreach ($headers as $key => $values) { - $this->set($key, $values); - } - } - - /** - * Returns the first header by name or the default one. - * - * @return string|null - */ - public function get(string $key, string $default = null) - { - $headers = $this->all($key); - - if (!$headers) { - return $default; - } - - if (null === $headers[0]) { - return null; - } - - return (string) $headers[0]; - } - - /** - * Sets a header by name. - * - * @param string|string[]|null $values The value or an array of values - * @param bool $replace Whether to replace the actual value or not (true by default) - */ - public function set(string $key, $values, bool $replace = true) - { - $key = strtr($key, self::UPPER, self::LOWER); - - if (\is_array($values)) { - $values = array_values($values); - - if (true === $replace || !isset($this->headers[$key])) { - $this->headers[$key] = $values; - } else { - $this->headers[$key] = array_merge($this->headers[$key], $values); - } - } else { - if (true === $replace || !isset($this->headers[$key])) { - $this->headers[$key] = [$values]; - } else { - $this->headers[$key][] = $values; - } - } - - if ('cache-control' === $key) { - $this->cacheControl = $this->parseCacheControl(implode(', ', $this->headers[$key])); - } - } - - /** - * Returns true if the HTTP header is defined. - * - * @return bool - */ - public function has(string $key) - { - return \array_key_exists(strtr($key, self::UPPER, self::LOWER), $this->all()); - } - - /** - * Returns true if the given HTTP header contains the given value. - * - * @return bool - */ - public function contains(string $key, string $value) - { - return \in_array($value, $this->all($key)); - } - - /** - * Removes a header. - */ - public function remove(string $key) - { - $key = strtr($key, self::UPPER, self::LOWER); - - unset($this->headers[$key]); - - if ('cache-control' === $key) { - $this->cacheControl = []; - } - } - - /** - * Returns the HTTP header value converted to a date. - * - * @return \DateTimeInterface|null - * - * @throws \RuntimeException When the HTTP header is not parseable - */ - public function getDate(string $key, \DateTime $default = null) - { - if (null === $value = $this->get($key)) { - return $default; - } - - if (false === $date = \DateTime::createFromFormat(\DATE_RFC2822, $value)) { - throw new \RuntimeException(sprintf('The "%s" HTTP header is not parseable (%s).', $key, $value)); - } - - return $date; - } - - /** - * Adds a custom Cache-Control directive. - * - * @param bool|string $value The Cache-Control directive value - */ - public function addCacheControlDirective(string $key, $value = true) - { - $this->cacheControl[$key] = $value; - - $this->set('Cache-Control', $this->getCacheControlHeader()); - } - - /** - * Returns true if the Cache-Control directive is defined. - * - * @return bool - */ - public function hasCacheControlDirective(string $key) - { - return \array_key_exists($key, $this->cacheControl); - } - - /** - * Returns a Cache-Control directive value by name. - * - * @return bool|string|null - */ - public function getCacheControlDirective(string $key) - { - return $this->cacheControl[$key] ?? null; - } - - /** - * Removes a Cache-Control directive. - */ - public function removeCacheControlDirective(string $key) - { - unset($this->cacheControl[$key]); - - $this->set('Cache-Control', $this->getCacheControlHeader()); - } - - /** - * Returns an iterator for headers. - * - * @return \ArrayIterator<string, list<string|null>> - */ - #[\ReturnTypeWillChange] - public function getIterator() - { - return new \ArrayIterator($this->headers); - } - - /** - * Returns the number of headers. - * - * @return int - */ - #[\ReturnTypeWillChange] - public function count() - { - return \count($this->headers); - } - - protected function getCacheControlHeader() - { - ksort($this->cacheControl); - - return HeaderUtils::toString($this->cacheControl, ','); - } - - /** - * Parses a Cache-Control HTTP header. - * - * @return array - */ - protected function parseCacheControl(string $header) - { - $parts = HeaderUtils::split($header, ',='); - - return HeaderUtils::combine($parts); - } -} diff --git a/lib/symfony/http-foundation/HeaderUtils.php b/lib/symfony/http-foundation/HeaderUtils.php deleted file mode 100644 index 1d56be080..000000000 --- a/lib/symfony/http-foundation/HeaderUtils.php +++ /dev/null @@ -1,293 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * HTTP header utility functions. - * - * @author Christian Schmidt <github@chsc.dk> - */ -class HeaderUtils -{ - public const DISPOSITION_ATTACHMENT = 'attachment'; - public const DISPOSITION_INLINE = 'inline'; - - /** - * This class should not be instantiated. - */ - private function __construct() - { - } - - /** - * Splits an HTTP header by one or more separators. - * - * Example: - * - * HeaderUtils::split("da, en-gb;q=0.8", ",;") - * // => ['da'], ['en-gb', 'q=0.8']] - * - * @param string $separators List of characters to split on, ordered by - * precedence, e.g. ",", ";=", or ",;=" - * - * @return array Nested array with as many levels as there are characters in - * $separators - */ - public static function split(string $header, string $separators): array - { - $quotedSeparators = preg_quote($separators, '/'); - - preg_match_all(' - / - (?!\s) - (?: - # quoted-string - "(?:[^"\\\\]|\\\\.)*(?:"|\\\\|$) - | - # token - [^"'.$quotedSeparators.']+ - )+ - (?<!\s) - | - # separator - \s* - (?<separator>['.$quotedSeparators.']) - \s* - /x', trim($header), $matches, \PREG_SET_ORDER); - - return self::groupParts($matches, $separators); - } - - /** - * Combines an array of arrays into one associative array. - * - * Each of the nested arrays should have one or two elements. The first - * value will be used as the keys in the associative array, and the second - * will be used as the values, or true if the nested array only contains one - * element. Array keys are lowercased. - * - * Example: - * - * HeaderUtils::combine([["foo", "abc"], ["bar"]]) - * // => ["foo" => "abc", "bar" => true] - */ - public static function combine(array $parts): array - { - $assoc = []; - foreach ($parts as $part) { - $name = strtolower($part[0]); - $value = $part[1] ?? true; - $assoc[$name] = $value; - } - - return $assoc; - } - - /** - * Joins an associative array into a string for use in an HTTP header. - * - * The key and value of each entry are joined with "=", and all entries - * are joined with the specified separator and an additional space (for - * readability). Values are quoted if necessary. - * - * Example: - * - * HeaderUtils::toString(["foo" => "abc", "bar" => true, "baz" => "a b c"], ",") - * // => 'foo=abc, bar, baz="a b c"' - */ - public static function toString(array $assoc, string $separator): string - { - $parts = []; - foreach ($assoc as $name => $value) { - if (true === $value) { - $parts[] = $name; - } else { - $parts[] = $name.'='.self::quote($value); - } - } - - return implode($separator.' ', $parts); - } - - /** - * Encodes a string as a quoted string, if necessary. - * - * If a string contains characters not allowed by the "token" construct in - * the HTTP specification, it is backslash-escaped and enclosed in quotes - * to match the "quoted-string" construct. - */ - public static function quote(string $s): string - { - if (preg_match('/^[a-z0-9!#$%&\'*.^_`|~-]+$/i', $s)) { - return $s; - } - - return '"'.addcslashes($s, '"\\"').'"'; - } - - /** - * Decodes a quoted string. - * - * If passed an unquoted string that matches the "token" construct (as - * defined in the HTTP specification), it is passed through verbatimly. - */ - public static function unquote(string $s): string - { - return preg_replace('/\\\\(.)|"/', '$1', $s); - } - - /** - * Generates an HTTP Content-Disposition field-value. - * - * @param string $disposition One of "inline" or "attachment" - * @param string $filename A unicode string - * @param string $filenameFallback A string containing only ASCII characters that - * is semantically equivalent to $filename. If the filename is already ASCII, - * it can be omitted, or just copied from $filename - * - * @throws \InvalidArgumentException - * - * @see RFC 6266 - */ - public static function makeDisposition(string $disposition, string $filename, string $filenameFallback = ''): string - { - if (!\in_array($disposition, [self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE])) { - throw new \InvalidArgumentException(sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE)); - } - - if ('' === $filenameFallback) { - $filenameFallback = $filename; - } - - // filenameFallback is not ASCII. - if (!preg_match('/^[\x20-\x7e]*$/', $filenameFallback)) { - throw new \InvalidArgumentException('The filename fallback must only contain ASCII characters.'); - } - - // percent characters aren't safe in fallback. - if (str_contains($filenameFallback, '%')) { - throw new \InvalidArgumentException('The filename fallback cannot contain the "%" character.'); - } - - // path separators aren't allowed in either. - if (str_contains($filename, '/') || str_contains($filename, '\\') || str_contains($filenameFallback, '/') || str_contains($filenameFallback, '\\')) { - throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.'); - } - - $params = ['filename' => $filenameFallback]; - if ($filename !== $filenameFallback) { - $params['filename*'] = "utf-8''".rawurlencode($filename); - } - - return $disposition.'; '.self::toString($params, ';'); - } - - /** - * Like parse_str(), but preserves dots in variable names. - */ - public static function parseQuery(string $query, bool $ignoreBrackets = false, string $separator = '&'): array - { - $q = []; - - foreach (explode($separator, $query) as $v) { - if (false !== $i = strpos($v, "\0")) { - $v = substr($v, 0, $i); - } - - if (false === $i = strpos($v, '=')) { - $k = urldecode($v); - $v = ''; - } else { - $k = urldecode(substr($v, 0, $i)); - $v = substr($v, $i); - } - - if (false !== $i = strpos($k, "\0")) { - $k = substr($k, 0, $i); - } - - $k = ltrim($k, ' '); - - if ($ignoreBrackets) { - $q[$k][] = urldecode(substr($v, 1)); - - continue; - } - - if (false === $i = strpos($k, '[')) { - $q[] = bin2hex($k).$v; - } else { - $q[] = bin2hex(substr($k, 0, $i)).rawurlencode(substr($k, $i)).$v; - } - } - - if ($ignoreBrackets) { - return $q; - } - - parse_str(implode('&', $q), $q); - - $query = []; - - foreach ($q as $k => $v) { - if (false !== $i = strpos($k, '_')) { - $query[substr_replace($k, hex2bin(substr($k, 0, $i)).'[', 0, 1 + $i)] = $v; - } else { - $query[hex2bin($k)] = $v; - } - } - - return $query; - } - - private static function groupParts(array $matches, string $separators, bool $first = true): array - { - $separator = $separators[0]; - $partSeparators = substr($separators, 1); - - $i = 0; - $partMatches = []; - $previousMatchWasSeparator = false; - foreach ($matches as $match) { - if (!$first && $previousMatchWasSeparator && isset($match['separator']) && $match['separator'] === $separator) { - $previousMatchWasSeparator = true; - $partMatches[$i][] = $match; - } elseif (isset($match['separator']) && $match['separator'] === $separator) { - $previousMatchWasSeparator = true; - ++$i; - } else { - $previousMatchWasSeparator = false; - $partMatches[$i][] = $match; - } - } - - $parts = []; - if ($partSeparators) { - foreach ($partMatches as $matches) { - $parts[] = self::groupParts($matches, $partSeparators, false); - } - } else { - foreach ($partMatches as $matches) { - $parts[] = self::unquote($matches[0][0]); - } - - if (!$first && 2 < \count($parts)) { - $parts = [ - $parts[0], - implode($separator, \array_slice($parts, 1)), - ]; - } - } - - return $parts; - } -} diff --git a/lib/symfony/http-foundation/InputBag.php b/lib/symfony/http-foundation/InputBag.php deleted file mode 100644 index a9d3cd82a..000000000 --- a/lib/symfony/http-foundation/InputBag.php +++ /dev/null @@ -1,113 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\HttpFoundation\Exception\BadRequestException; - -/** - * InputBag is a container for user input values such as $_GET, $_POST, $_REQUEST, and $_COOKIE. - * - * @author Saif Eddin Gmati <azjezz@protonmail.com> - */ -final class InputBag extends ParameterBag -{ - /** - * Returns a scalar input value by name. - * - * @param string|int|float|bool|null $default The default value if the input key does not exist - * - * @return string|int|float|bool|null - */ - public function get(string $key, $default = null) - { - if (null !== $default && !\is_scalar($default) && !(\is_object($default) && method_exists($default, '__toString'))) { - trigger_deprecation('symfony/http-foundation', '5.1', 'Passing a non-scalar value as 2nd argument to "%s()" is deprecated, pass a scalar or null instead.', __METHOD__); - } - - $value = parent::get($key, $this); - - if (null !== $value && $this !== $value && !\is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) { - trigger_deprecation('symfony/http-foundation', '5.1', 'Retrieving a non-scalar value from "%s()" is deprecated, and will throw a "%s" exception in Symfony 6.0, use "%s::all($key)" instead.', __METHOD__, BadRequestException::class, __CLASS__); - } - - return $this === $value ? $default : $value; - } - - /** - * {@inheritdoc} - */ - public function all(string $key = null): array - { - return parent::all($key); - } - - /** - * Replaces the current input values by a new set. - */ - public function replace(array $inputs = []) - { - $this->parameters = []; - $this->add($inputs); - } - - /** - * Adds input values. - */ - public function add(array $inputs = []) - { - foreach ($inputs as $input => $value) { - $this->set($input, $value); - } - } - - /** - * Sets an input by name. - * - * @param string|int|float|bool|array|null $value - */ - public function set(string $key, $value) - { - if (null !== $value && !\is_scalar($value) && !\is_array($value) && !method_exists($value, '__toString')) { - trigger_deprecation('symfony/http-foundation', '5.1', 'Passing "%s" as a 2nd Argument to "%s()" is deprecated, pass a scalar, array, or null instead.', get_debug_type($value), __METHOD__); - } - - $this->parameters[$key] = $value; - } - - /** - * {@inheritdoc} - */ - public function filter(string $key, $default = null, int $filter = \FILTER_DEFAULT, $options = []) - { - $value = $this->has($key) ? $this->all()[$key] : $default; - - // Always turn $options into an array - this allows filter_var option shortcuts. - if (!\is_array($options) && $options) { - $options = ['flags' => $options]; - } - - if (\is_array($value) && !(($options['flags'] ?? 0) & (\FILTER_REQUIRE_ARRAY | \FILTER_FORCE_ARRAY))) { - trigger_deprecation('symfony/http-foundation', '5.1', 'Filtering an array value with "%s()" without passing the FILTER_REQUIRE_ARRAY or FILTER_FORCE_ARRAY flag is deprecated', __METHOD__); - - if (!isset($options['flags'])) { - $options['flags'] = \FILTER_REQUIRE_ARRAY; - } - } - - if ((\FILTER_CALLBACK & $filter) && !(($options['options'] ?? null) instanceof \Closure)) { - trigger_deprecation('symfony/http-foundation', '5.2', 'Not passing a Closure together with FILTER_CALLBACK to "%s()" is deprecated. Wrap your filter in a closure instead.', __METHOD__); - // throw new \InvalidArgumentException(sprintf('A Closure must be passed to "%s()" when FILTER_CALLBACK is used, "%s" given.', __METHOD__, get_debug_type($options['options'] ?? null))); - } - - return filter_var($value, $filter, $options); - } -} diff --git a/lib/symfony/http-foundation/IpUtils.php b/lib/symfony/http-foundation/IpUtils.php deleted file mode 100644 index 2f31284e3..000000000 --- a/lib/symfony/http-foundation/IpUtils.php +++ /dev/null @@ -1,216 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * Http utility functions. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class IpUtils -{ - private static $checkedIps = []; - - /** - * This class should not be instantiated. - */ - private function __construct() - { - } - - /** - * Checks if an IPv4 or IPv6 address is contained in the list of given IPs or subnets. - * - * @param string|array $ips List of IPs or subnets (can be a string if only a single one) - * - * @return bool - */ - public static function checkIp(?string $requestIp, $ips) - { - if (null === $requestIp) { - trigger_deprecation('symfony/http-foundation', '5.4', 'Passing null as $requestIp to "%s()" is deprecated, pass an empty string instead.', __METHOD__); - - return false; - } - - if (!\is_array($ips)) { - $ips = [$ips]; - } - - $method = substr_count($requestIp, ':') > 1 ? 'checkIp6' : 'checkIp4'; - - foreach ($ips as $ip) { - if (self::$method($requestIp, $ip)) { - return true; - } - } - - return false; - } - - /** - * Compares two IPv4 addresses. - * In case a subnet is given, it checks if it contains the request IP. - * - * @param string $ip IPv4 address or subnet in CIDR notation - * - * @return bool Whether the request IP matches the IP, or whether the request IP is within the CIDR subnet - */ - public static function checkIp4(?string $requestIp, string $ip) - { - if (null === $requestIp) { - trigger_deprecation('symfony/http-foundation', '5.4', 'Passing null as $requestIp to "%s()" is deprecated, pass an empty string instead.', __METHOD__); - - return false; - } - - $cacheKey = $requestIp.'-'.$ip; - if (isset(self::$checkedIps[$cacheKey])) { - return self::$checkedIps[$cacheKey]; - } - - if (!filter_var($requestIp, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) { - return self::$checkedIps[$cacheKey] = false; - } - - if (str_contains($ip, '/')) { - [$address, $netmask] = explode('/', $ip, 2); - - if ('0' === $netmask) { - return self::$checkedIps[$cacheKey] = false !== filter_var($address, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4); - } - - if ($netmask < 0 || $netmask > 32) { - return self::$checkedIps[$cacheKey] = false; - } - } else { - $address = $ip; - $netmask = 32; - } - - if (false === ip2long($address)) { - return self::$checkedIps[$cacheKey] = false; - } - - return self::$checkedIps[$cacheKey] = 0 === substr_compare(sprintf('%032b', ip2long($requestIp)), sprintf('%032b', ip2long($address)), 0, $netmask); - } - - /** - * Compares two IPv6 addresses. - * In case a subnet is given, it checks if it contains the request IP. - * - * @author David Soria Parra <dsp at php dot net> - * - * @see https://github.com/dsp/v6tools - * - * @param string $ip IPv6 address or subnet in CIDR notation - * - * @return bool - * - * @throws \RuntimeException When IPV6 support is not enabled - */ - public static function checkIp6(?string $requestIp, string $ip) - { - if (null === $requestIp) { - trigger_deprecation('symfony/http-foundation', '5.4', 'Passing null as $requestIp to "%s()" is deprecated, pass an empty string instead.', __METHOD__); - - return false; - } - - $cacheKey = $requestIp.'-'.$ip; - if (isset(self::$checkedIps[$cacheKey])) { - return self::$checkedIps[$cacheKey]; - } - - if (!((\extension_loaded('sockets') && \defined('AF_INET6')) || @inet_pton('::1'))) { - throw new \RuntimeException('Unable to check Ipv6. Check that PHP was not compiled with option "disable-ipv6".'); - } - - // Check to see if we were given a IP4 $requestIp or $ip by mistake - if (!filter_var($requestIp, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) { - return self::$checkedIps[$cacheKey] = false; - } - - if (str_contains($ip, '/')) { - [$address, $netmask] = explode('/', $ip, 2); - - if (!filter_var($address, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) { - return self::$checkedIps[$cacheKey] = false; - } - - if ('0' === $netmask) { - return (bool) unpack('n*', @inet_pton($address)); - } - - if ($netmask < 1 || $netmask > 128) { - return self::$checkedIps[$cacheKey] = false; - } - } else { - if (!filter_var($ip, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) { - return self::$checkedIps[$cacheKey] = false; - } - - $address = $ip; - $netmask = 128; - } - - $bytesAddr = unpack('n*', @inet_pton($address)); - $bytesTest = unpack('n*', @inet_pton($requestIp)); - - if (!$bytesAddr || !$bytesTest) { - return self::$checkedIps[$cacheKey] = false; - } - - for ($i = 1, $ceil = ceil($netmask / 16); $i <= $ceil; ++$i) { - $left = $netmask - 16 * ($i - 1); - $left = ($left <= 16) ? $left : 16; - $mask = ~(0xFFFF >> $left) & 0xFFFF; - if (($bytesAddr[$i] & $mask) != ($bytesTest[$i] & $mask)) { - return self::$checkedIps[$cacheKey] = false; - } - } - - return self::$checkedIps[$cacheKey] = true; - } - - /** - * Anonymizes an IP/IPv6. - * - * Removes the last byte for v4 and the last 8 bytes for v6 IPs - */ - public static function anonymize(string $ip): string - { - $wrappedIPv6 = false; - if ('[' === substr($ip, 0, 1) && ']' === substr($ip, -1, 1)) { - $wrappedIPv6 = true; - $ip = substr($ip, 1, -1); - } - - $packedAddress = inet_pton($ip); - if (4 === \strlen($packedAddress)) { - $mask = '255.255.255.0'; - } elseif ($ip === inet_ntop($packedAddress & inet_pton('::ffff:ffff:ffff'))) { - $mask = '::ffff:ffff:ff00'; - } elseif ($ip === inet_ntop($packedAddress & inet_pton('::ffff:ffff'))) { - $mask = '::ffff:ff00'; - } else { - $mask = 'ffff:ffff:ffff:ffff:0000:0000:0000:0000'; - } - $ip = inet_ntop($packedAddress & inet_pton($mask)); - - if ($wrappedIPv6) { - $ip = '['.$ip.']'; - } - - return $ip; - } -} diff --git a/lib/symfony/http-foundation/JsonResponse.php b/lib/symfony/http-foundation/JsonResponse.php deleted file mode 100644 index 501a6387d..000000000 --- a/lib/symfony/http-foundation/JsonResponse.php +++ /dev/null @@ -1,221 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * Response represents an HTTP response in JSON format. - * - * Note that this class does not force the returned JSON content to be an - * object. It is however recommended that you do return an object as it - * protects yourself against XSSI and JSON-JavaScript Hijacking. - * - * @see https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/AJAX_Security_Cheat_Sheet.md#always-return-json-with-an-object-on-the-outside - * - * @author Igor Wiedler <igor@wiedler.ch> - */ -class JsonResponse extends Response -{ - protected $data; - protected $callback; - - // Encode <, >, ', &, and " characters in the JSON, making it also safe to be embedded into HTML. - // 15 === JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT - public const DEFAULT_ENCODING_OPTIONS = 15; - - protected $encodingOptions = self::DEFAULT_ENCODING_OPTIONS; - - /** - * @param mixed $data The response data - * @param int $status The response status code - * @param array $headers An array of response headers - * @param bool $json If the data is already a JSON string - */ - public function __construct($data = null, int $status = 200, array $headers = [], bool $json = false) - { - parent::__construct('', $status, $headers); - - if ($json && !\is_string($data) && !is_numeric($data) && !\is_callable([$data, '__toString'])) { - throw new \TypeError(sprintf('"%s": If $json is set to true, argument $data must be a string or object implementing __toString(), "%s" given.', __METHOD__, get_debug_type($data))); - } - - if (null === $data) { - $data = new \ArrayObject(); - } - - $json ? $this->setJson($data) : $this->setData($data); - } - - /** - * Factory method for chainability. - * - * Example: - * - * return JsonResponse::create(['key' => 'value']) - * ->setSharedMaxAge(300); - * - * @param mixed $data The JSON response data - * @param int $status The response status code - * @param array $headers An array of response headers - * - * @return static - * - * @deprecated since Symfony 5.1, use __construct() instead. - */ - public static function create($data = null, int $status = 200, array $headers = []) - { - trigger_deprecation('symfony/http-foundation', '5.1', 'The "%s()" method is deprecated, use "new %s()" instead.', __METHOD__, static::class); - - return new static($data, $status, $headers); - } - - /** - * Factory method for chainability. - * - * Example: - * - * return JsonResponse::fromJsonString('{"key": "value"}') - * ->setSharedMaxAge(300); - * - * @param string $data The JSON response string - * @param int $status The response status code - * @param array $headers An array of response headers - * - * @return static - */ - public static function fromJsonString(string $data, int $status = 200, array $headers = []) - { - return new static($data, $status, $headers, true); - } - - /** - * Sets the JSONP callback. - * - * @param string|null $callback The JSONP callback or null to use none - * - * @return $this - * - * @throws \InvalidArgumentException When the callback name is not valid - */ - public function setCallback(string $callback = null) - { - if (null !== $callback) { - // partially taken from https://geekality.net/2011/08/03/valid-javascript-identifier/ - // partially taken from https://github.com/willdurand/JsonpCallbackValidator - // JsonpCallbackValidator is released under the MIT License. See https://github.com/willdurand/JsonpCallbackValidator/blob/v1.1.0/LICENSE for details. - // (c) William Durand <william.durand1@gmail.com> - $pattern = '/^[$_\p{L}][$_\p{L}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*(?:\[(?:"(?:\\\.|[^"\\\])*"|\'(?:\\\.|[^\'\\\])*\'|\d+)\])*?$/u'; - $reserved = [ - 'break', 'do', 'instanceof', 'typeof', 'case', 'else', 'new', 'var', 'catch', 'finally', 'return', 'void', 'continue', 'for', 'switch', 'while', - 'debugger', 'function', 'this', 'with', 'default', 'if', 'throw', 'delete', 'in', 'try', 'class', 'enum', 'extends', 'super', 'const', 'export', - 'import', 'implements', 'let', 'private', 'public', 'yield', 'interface', 'package', 'protected', 'static', 'null', 'true', 'false', - ]; - $parts = explode('.', $callback); - foreach ($parts as $part) { - if (!preg_match($pattern, $part) || \in_array($part, $reserved, true)) { - throw new \InvalidArgumentException('The callback name is not valid.'); - } - } - } - - $this->callback = $callback; - - return $this->update(); - } - - /** - * Sets a raw string containing a JSON document to be sent. - * - * @return $this - */ - public function setJson(string $json) - { - $this->data = $json; - - return $this->update(); - } - - /** - * Sets the data to be sent as JSON. - * - * @param mixed $data - * - * @return $this - * - * @throws \InvalidArgumentException - */ - public function setData($data = []) - { - try { - $data = json_encode($data, $this->encodingOptions); - } catch (\Exception $e) { - if ('Exception' === \get_class($e) && str_starts_with($e->getMessage(), 'Failed calling ')) { - throw $e->getPrevious() ?: $e; - } - throw $e; - } - - if (\PHP_VERSION_ID >= 70300 && (\JSON_THROW_ON_ERROR & $this->encodingOptions)) { - return $this->setJson($data); - } - - if (\JSON_ERROR_NONE !== json_last_error()) { - throw new \InvalidArgumentException(json_last_error_msg()); - } - - return $this->setJson($data); - } - - /** - * Returns options used while encoding data to JSON. - * - * @return int - */ - public function getEncodingOptions() - { - return $this->encodingOptions; - } - - /** - * Sets options used while encoding data to JSON. - * - * @return $this - */ - public function setEncodingOptions(int $encodingOptions) - { - $this->encodingOptions = $encodingOptions; - - return $this->setData(json_decode($this->data)); - } - - /** - * Updates the content and headers according to the JSON data and callback. - * - * @return $this - */ - protected function update() - { - if (null !== $this->callback) { - // Not using application/javascript for compatibility reasons with older browsers. - $this->headers->set('Content-Type', 'text/javascript'); - - return $this->setContent(sprintf('/**/%s(%s);', $this->callback, $this->data)); - } - - // Only set the header when there is none or when it equals 'text/javascript' (from a previous update with callback) - // in order to not overwrite a custom definition. - if (!$this->headers->has('Content-Type') || 'text/javascript' === $this->headers->get('Content-Type')) { - $this->headers->set('Content-Type', 'application/json'); - } - - return $this->setContent($this->data); - } -} diff --git a/lib/symfony/http-foundation/LICENSE b/lib/symfony/http-foundation/LICENSE deleted file mode 100644 index 008370457..000000000 --- a/lib/symfony/http-foundation/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -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/lib/symfony/http-foundation/ParameterBag.php b/lib/symfony/http-foundation/ParameterBag.php deleted file mode 100644 index e1f89d69e..000000000 --- a/lib/symfony/http-foundation/ParameterBag.php +++ /dev/null @@ -1,228 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\HttpFoundation\Exception\BadRequestException; - -/** - * ParameterBag is a container for key/value pairs. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @implements \IteratorAggregate<string, mixed> - */ -class ParameterBag implements \IteratorAggregate, \Countable -{ - /** - * Parameter storage. - */ - protected $parameters; - - public function __construct(array $parameters = []) - { - $this->parameters = $parameters; - } - - /** - * Returns the parameters. - * - * @param string|null $key The name of the parameter to return or null to get them all - * - * @return array - */ - public function all(/* string $key = null */) - { - $key = \func_num_args() > 0 ? func_get_arg(0) : null; - - if (null === $key) { - return $this->parameters; - } - - if (!\is_array($value = $this->parameters[$key] ?? [])) { - throw new BadRequestException(sprintf('Unexpected value for parameter "%s": expecting "array", got "%s".', $key, get_debug_type($value))); - } - - return $value; - } - - /** - * Returns the parameter keys. - * - * @return array - */ - public function keys() - { - return array_keys($this->parameters); - } - - /** - * Replaces the current parameters by a new set. - */ - public function replace(array $parameters = []) - { - $this->parameters = $parameters; - } - - /** - * Adds parameters. - */ - public function add(array $parameters = []) - { - $this->parameters = array_replace($this->parameters, $parameters); - } - - /** - * Returns a parameter by name. - * - * @param mixed $default The default value if the parameter key does not exist - * - * @return mixed - */ - public function get(string $key, $default = null) - { - return \array_key_exists($key, $this->parameters) ? $this->parameters[$key] : $default; - } - - /** - * Sets a parameter by name. - * - * @param mixed $value The value - */ - public function set(string $key, $value) - { - $this->parameters[$key] = $value; - } - - /** - * Returns true if the parameter is defined. - * - * @return bool - */ - public function has(string $key) - { - return \array_key_exists($key, $this->parameters); - } - - /** - * Removes a parameter. - */ - public function remove(string $key) - { - unset($this->parameters[$key]); - } - - /** - * Returns the alphabetic characters of the parameter value. - * - * @return string - */ - public function getAlpha(string $key, string $default = '') - { - return preg_replace('/[^[:alpha:]]/', '', $this->get($key, $default)); - } - - /** - * Returns the alphabetic characters and digits of the parameter value. - * - * @return string - */ - public function getAlnum(string $key, string $default = '') - { - return preg_replace('/[^[:alnum:]]/', '', $this->get($key, $default)); - } - - /** - * Returns the digits of the parameter value. - * - * @return string - */ - public function getDigits(string $key, string $default = '') - { - // we need to remove - and + because they're allowed in the filter - return str_replace(['-', '+'], '', $this->filter($key, $default, \FILTER_SANITIZE_NUMBER_INT)); - } - - /** - * Returns the parameter value converted to integer. - * - * @return int - */ - public function getInt(string $key, int $default = 0) - { - return (int) $this->get($key, $default); - } - - /** - * Returns the parameter value converted to boolean. - * - * @return bool - */ - public function getBoolean(string $key, bool $default = false) - { - return $this->filter($key, $default, \FILTER_VALIDATE_BOOLEAN); - } - - /** - * Filter key. - * - * @param mixed $default Default = null - * @param int $filter FILTER_* constant - * @param mixed $options Filter options - * - * @see https://php.net/filter-var - * - * @return mixed - */ - public function filter(string $key, $default = null, int $filter = \FILTER_DEFAULT, $options = []) - { - $value = $this->get($key, $default); - - // Always turn $options into an array - this allows filter_var option shortcuts. - if (!\is_array($options) && $options) { - $options = ['flags' => $options]; - } - - // Add a convenience check for arrays. - if (\is_array($value) && !isset($options['flags'])) { - $options['flags'] = \FILTER_REQUIRE_ARRAY; - } - - if ((\FILTER_CALLBACK & $filter) && !(($options['options'] ?? null) instanceof \Closure)) { - trigger_deprecation('symfony/http-foundation', '5.2', 'Not passing a Closure together with FILTER_CALLBACK to "%s()" is deprecated. Wrap your filter in a closure instead.', __METHOD__); - // throw new \InvalidArgumentException(sprintf('A Closure must be passed to "%s()" when FILTER_CALLBACK is used, "%s" given.', __METHOD__, get_debug_type($options['options'] ?? null))); - } - - return filter_var($value, $filter, $options); - } - - /** - * Returns an iterator for parameters. - * - * @return \ArrayIterator<string, mixed> - */ - #[\ReturnTypeWillChange] - public function getIterator() - { - return new \ArrayIterator($this->parameters); - } - - /** - * Returns the number of parameters. - * - * @return int - */ - #[\ReturnTypeWillChange] - public function count() - { - return \count($this->parameters); - } -} diff --git a/lib/symfony/http-foundation/README.md b/lib/symfony/http-foundation/README.md deleted file mode 100644 index 424f2c4f0..000000000 --- a/lib/symfony/http-foundation/README.md +++ /dev/null @@ -1,28 +0,0 @@ -HttpFoundation Component -======================== - -The HttpFoundation component defines an object-oriented layer for the HTTP -specification. - -Sponsor -------- - -The HttpFoundation component for Symfony 5.4/6.0 is [backed][1] by [Laravel][2]. - -Laravel is a PHP web development framework that is passionate about maximum developer -happiness. Laravel is built using a variety of bespoke and Symfony based components. - -Help Symfony by [sponsoring][3] its development! - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/http_foundation.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) - -[1]: https://symfony.com/backers -[2]: https://laravel.com/ -[3]: https://symfony.com/sponsor diff --git a/lib/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php b/lib/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php deleted file mode 100644 index a6dd993b7..000000000 --- a/lib/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\RateLimiter; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\RateLimiter\LimiterInterface; -use Symfony\Component\RateLimiter\Policy\NoLimiter; -use Symfony\Component\RateLimiter\RateLimit; - -/** - * An implementation of RequestRateLimiterInterface that - * fits most use-cases. - * - * @author Wouter de Jong <wouter@wouterj.nl> - */ -abstract class AbstractRequestRateLimiter implements RequestRateLimiterInterface -{ - public function consume(Request $request): RateLimit - { - $limiters = $this->getLimiters($request); - if (0 === \count($limiters)) { - $limiters = [new NoLimiter()]; - } - - $minimalRateLimit = null; - foreach ($limiters as $limiter) { - $rateLimit = $limiter->consume(1); - - $minimalRateLimit = $minimalRateLimit ? self::getMinimalRateLimit($minimalRateLimit, $rateLimit) : $rateLimit; - } - - return $minimalRateLimit; - } - - public function reset(Request $request): void - { - foreach ($this->getLimiters($request) as $limiter) { - $limiter->reset(); - } - } - - /** - * @return LimiterInterface[] a set of limiters using keys extracted from the request - */ - abstract protected function getLimiters(Request $request): array; - - private static function getMinimalRateLimit(RateLimit $first, RateLimit $second): RateLimit - { - if ($first->isAccepted() !== $second->isAccepted()) { - return $first->isAccepted() ? $second : $first; - } - - $firstRemainingTokens = $first->getRemainingTokens(); - $secondRemainingTokens = $second->getRemainingTokens(); - - if ($firstRemainingTokens === $secondRemainingTokens) { - return $first->getRetryAfter() < $second->getRetryAfter() ? $second : $first; - } - - return $firstRemainingTokens > $secondRemainingTokens ? $second : $first; - } -} diff --git a/lib/symfony/http-foundation/RateLimiter/RequestRateLimiterInterface.php b/lib/symfony/http-foundation/RateLimiter/RequestRateLimiterInterface.php deleted file mode 100644 index 4c87a40a8..000000000 --- a/lib/symfony/http-foundation/RateLimiter/RequestRateLimiterInterface.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\RateLimiter; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\RateLimiter\RateLimit; - -/** - * A special type of limiter that deals with requests. - * - * This allows to limit on different types of information - * from the requests. - * - * @author Wouter de Jong <wouter@wouterj.nl> - */ -interface RequestRateLimiterInterface -{ - public function consume(Request $request): RateLimit; - - public function reset(Request $request): void; -} diff --git a/lib/symfony/http-foundation/RedirectResponse.php b/lib/symfony/http-foundation/RedirectResponse.php deleted file mode 100644 index 2103280c6..000000000 --- a/lib/symfony/http-foundation/RedirectResponse.php +++ /dev/null @@ -1,109 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * RedirectResponse represents an HTTP response doing a redirect. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class RedirectResponse extends Response -{ - protected $targetUrl; - - /** - * Creates a redirect response so that it conforms to the rules defined for a redirect status code. - * - * @param string $url The URL to redirect to. The URL should be a full URL, with schema etc., - * but practically every browser redirects on paths only as well - * @param int $status The status code (302 by default) - * @param array $headers The headers (Location is always set to the given URL) - * - * @throws \InvalidArgumentException - * - * @see https://tools.ietf.org/html/rfc2616#section-10.3 - */ - public function __construct(string $url, int $status = 302, array $headers = []) - { - parent::__construct('', $status, $headers); - - $this->setTargetUrl($url); - - if (!$this->isRedirect()) { - throw new \InvalidArgumentException(sprintf('The HTTP status code is not a redirect ("%s" given).', $status)); - } - - if (301 == $status && !\array_key_exists('cache-control', array_change_key_case($headers, \CASE_LOWER))) { - $this->headers->remove('cache-control'); - } - } - - /** - * Factory method for chainability. - * - * @param string $url The URL to redirect to - * - * @return static - * - * @deprecated since Symfony 5.1, use __construct() instead. - */ - public static function create($url = '', int $status = 302, array $headers = []) - { - trigger_deprecation('symfony/http-foundation', '5.1', 'The "%s()" method is deprecated, use "new %s()" instead.', __METHOD__, static::class); - - return new static($url, $status, $headers); - } - - /** - * Returns the target URL. - * - * @return string - */ - public function getTargetUrl() - { - return $this->targetUrl; - } - - /** - * Sets the redirect target of this response. - * - * @return $this - * - * @throws \InvalidArgumentException - */ - public function setTargetUrl(string $url) - { - if ('' === $url) { - throw new \InvalidArgumentException('Cannot redirect to an empty URL.'); - } - - $this->targetUrl = $url; - - $this->setContent( - sprintf('<!DOCTYPE html> -<html> - <head> - <meta charset="UTF-8" /> - <meta http-equiv="refresh" content="0;url=\'%1$s\'" /> - - <title>Redirecting to %1$s</title> - </head> - <body> - Redirecting to <a href="%1$s">%1$s</a>. - </body> -</html>', htmlspecialchars($url, \ENT_QUOTES, 'UTF-8'))); - - $this->headers->set('Location', $url); - - return $this; - } -} diff --git a/lib/symfony/http-foundation/Request.php b/lib/symfony/http-foundation/Request.php deleted file mode 100644 index 10f779d27..000000000 --- a/lib/symfony/http-foundation/Request.php +++ /dev/null @@ -1,2148 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException; -use Symfony\Component\HttpFoundation\Exception\JsonException; -use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException; -use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException; -use Symfony\Component\HttpFoundation\Session\SessionInterface; - -// Help opcache.preload discover always-needed symbols -class_exists(AcceptHeader::class); -class_exists(FileBag::class); -class_exists(HeaderBag::class); -class_exists(HeaderUtils::class); -class_exists(InputBag::class); -class_exists(ParameterBag::class); -class_exists(ServerBag::class); - -/** - * Request represents an HTTP request. - * - * The methods dealing with URL accept / return a raw path (% encoded): - * * getBasePath - * * getBaseUrl - * * getPathInfo - * * getRequestUri - * * getUri - * * getUriForPath - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Request -{ - public const HEADER_FORWARDED = 0b000001; // When using RFC 7239 - public const HEADER_X_FORWARDED_FOR = 0b000010; - public const HEADER_X_FORWARDED_HOST = 0b000100; - public const HEADER_X_FORWARDED_PROTO = 0b001000; - public const HEADER_X_FORWARDED_PORT = 0b010000; - public const HEADER_X_FORWARDED_PREFIX = 0b100000; - - /** @deprecated since Symfony 5.2, use either "HEADER_X_FORWARDED_FOR | HEADER_X_FORWARDED_HOST | HEADER_X_FORWARDED_PORT | HEADER_X_FORWARDED_PROTO" or "HEADER_X_FORWARDED_AWS_ELB" or "HEADER_X_FORWARDED_TRAEFIK" constants instead. */ - public const HEADER_X_FORWARDED_ALL = 0b1011110; // All "X-Forwarded-*" headers sent by "usual" reverse proxy - public const HEADER_X_FORWARDED_AWS_ELB = 0b0011010; // AWS ELB doesn't send X-Forwarded-Host - public const HEADER_X_FORWARDED_TRAEFIK = 0b0111110; // All "X-Forwarded-*" headers sent by Traefik reverse proxy - - public const METHOD_HEAD = 'HEAD'; - public const METHOD_GET = 'GET'; - public const METHOD_POST = 'POST'; - public const METHOD_PUT = 'PUT'; - public const METHOD_PATCH = 'PATCH'; - public const METHOD_DELETE = 'DELETE'; - public const METHOD_PURGE = 'PURGE'; - public const METHOD_OPTIONS = 'OPTIONS'; - public const METHOD_TRACE = 'TRACE'; - public const METHOD_CONNECT = 'CONNECT'; - - /** - * @var string[] - */ - protected static $trustedProxies = []; - - /** - * @var string[] - */ - protected static $trustedHostPatterns = []; - - /** - * @var string[] - */ - protected static $trustedHosts = []; - - protected static $httpMethodParameterOverride = false; - - /** - * Custom parameters. - * - * @var ParameterBag - */ - public $attributes; - - /** - * Request body parameters ($_POST). - * - * @var InputBag - */ - public $request; - - /** - * Query string parameters ($_GET). - * - * @var InputBag - */ - public $query; - - /** - * Server and execution environment parameters ($_SERVER). - * - * @var ServerBag - */ - public $server; - - /** - * Uploaded files ($_FILES). - * - * @var FileBag - */ - public $files; - - /** - * Cookies ($_COOKIE). - * - * @var InputBag - */ - public $cookies; - - /** - * Headers (taken from the $_SERVER). - * - * @var HeaderBag - */ - public $headers; - - /** - * @var string|resource|false|null - */ - protected $content; - - /** - * @var array - */ - protected $languages; - - /** - * @var array - */ - protected $charsets; - - /** - * @var array - */ - protected $encodings; - - /** - * @var array - */ - protected $acceptableContentTypes; - - /** - * @var string - */ - protected $pathInfo; - - /** - * @var string - */ - protected $requestUri; - - /** - * @var string - */ - protected $baseUrl; - - /** - * @var string - */ - protected $basePath; - - /** - * @var string - */ - protected $method; - - /** - * @var string - */ - protected $format; - - /** - * @var SessionInterface|callable(): SessionInterface - */ - protected $session; - - /** - * @var string - */ - protected $locale; - - /** - * @var string - */ - protected $defaultLocale = 'en'; - - /** - * @var array - */ - protected static $formats; - - protected static $requestFactory; - - /** - * @var string|null - */ - private $preferredFormat; - private $isHostValid = true; - private $isForwardedValid = true; - - /** - * @var bool|null - */ - private $isSafeContentPreferred; - - private static $trustedHeaderSet = -1; - - private const FORWARDED_PARAMS = [ - self::HEADER_X_FORWARDED_FOR => 'for', - self::HEADER_X_FORWARDED_HOST => 'host', - self::HEADER_X_FORWARDED_PROTO => 'proto', - self::HEADER_X_FORWARDED_PORT => 'host', - ]; - - /** - * Names for headers that can be trusted when - * using trusted proxies. - * - * The FORWARDED header is the standard as of rfc7239. - * - * The other headers are non-standard, but widely used - * by popular reverse proxies (like Apache mod_proxy or Amazon EC2). - */ - private const TRUSTED_HEADERS = [ - self::HEADER_FORWARDED => 'FORWARDED', - self::HEADER_X_FORWARDED_FOR => 'X_FORWARDED_FOR', - self::HEADER_X_FORWARDED_HOST => 'X_FORWARDED_HOST', - self::HEADER_X_FORWARDED_PROTO => 'X_FORWARDED_PROTO', - self::HEADER_X_FORWARDED_PORT => 'X_FORWARDED_PORT', - self::HEADER_X_FORWARDED_PREFIX => 'X_FORWARDED_PREFIX', - ]; - - /** - * @param array $query The GET parameters - * @param array $request The POST parameters - * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) - * @param array $cookies The COOKIE parameters - * @param array $files The FILES parameters - * @param array $server The SERVER parameters - * @param string|resource|null $content The raw body data - */ - public function __construct(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null) - { - $this->initialize($query, $request, $attributes, $cookies, $files, $server, $content); - } - - /** - * Sets the parameters for this request. - * - * This method also re-initializes all properties. - * - * @param array $query The GET parameters - * @param array $request The POST parameters - * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) - * @param array $cookies The COOKIE parameters - * @param array $files The FILES parameters - * @param array $server The SERVER parameters - * @param string|resource|null $content The raw body data - */ - public function initialize(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null) - { - $this->request = new InputBag($request); - $this->query = new InputBag($query); - $this->attributes = new ParameterBag($attributes); - $this->cookies = new InputBag($cookies); - $this->files = new FileBag($files); - $this->server = new ServerBag($server); - $this->headers = new HeaderBag($this->server->getHeaders()); - - $this->content = $content; - $this->languages = null; - $this->charsets = null; - $this->encodings = null; - $this->acceptableContentTypes = null; - $this->pathInfo = null; - $this->requestUri = null; - $this->baseUrl = null; - $this->basePath = null; - $this->method = null; - $this->format = null; - } - - /** - * Creates a new request with values from PHP's super globals. - * - * @return static - */ - public static function createFromGlobals() - { - $request = self::createRequestFromFactory($_GET, $_POST, [], $_COOKIE, $_FILES, $_SERVER); - - if (str_starts_with($request->headers->get('CONTENT_TYPE', ''), 'application/x-www-form-urlencoded') - && \in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), ['PUT', 'DELETE', 'PATCH']) - ) { - parse_str($request->getContent(), $data); - $request->request = new InputBag($data); - } - - return $request; - } - - /** - * Creates a Request based on a given URI and configuration. - * - * The information contained in the URI always take precedence - * over the other information (server and parameters). - * - * @param string $uri The URI - * @param string $method The HTTP method - * @param array $parameters The query (GET) or request (POST) parameters - * @param array $cookies The request cookies ($_COOKIE) - * @param array $files The request files ($_FILES) - * @param array $server The server parameters ($_SERVER) - * @param string|resource|null $content The raw body data - * - * @return static - */ - public static function create(string $uri, string $method = 'GET', array $parameters = [], array $cookies = [], array $files = [], array $server = [], $content = null) - { - $server = array_replace([ - 'SERVER_NAME' => 'localhost', - 'SERVER_PORT' => 80, - 'HTTP_HOST' => 'localhost', - 'HTTP_USER_AGENT' => 'Symfony', - 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', - 'HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5', - 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', - 'REMOTE_ADDR' => '127.0.0.1', - 'SCRIPT_NAME' => '', - 'SCRIPT_FILENAME' => '', - 'SERVER_PROTOCOL' => 'HTTP/1.1', - 'REQUEST_TIME' => time(), - 'REQUEST_TIME_FLOAT' => microtime(true), - ], $server); - - $server['PATH_INFO'] = ''; - $server['REQUEST_METHOD'] = strtoupper($method); - - $components = parse_url($uri); - if (isset($components['host'])) { - $server['SERVER_NAME'] = $components['host']; - $server['HTTP_HOST'] = $components['host']; - } - - if (isset($components['scheme'])) { - if ('https' === $components['scheme']) { - $server['HTTPS'] = 'on'; - $server['SERVER_PORT'] = 443; - } else { - unset($server['HTTPS']); - $server['SERVER_PORT'] = 80; - } - } - - if (isset($components['port'])) { - $server['SERVER_PORT'] = $components['port']; - $server['HTTP_HOST'] .= ':'.$components['port']; - } - - if (isset($components['user'])) { - $server['PHP_AUTH_USER'] = $components['user']; - } - - if (isset($components['pass'])) { - $server['PHP_AUTH_PW'] = $components['pass']; - } - - if (!isset($components['path'])) { - $components['path'] = '/'; - } - - switch (strtoupper($method)) { - case 'POST': - case 'PUT': - case 'DELETE': - if (!isset($server['CONTENT_TYPE'])) { - $server['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'; - } - // no break - case 'PATCH': - $request = $parameters; - $query = []; - break; - default: - $request = []; - $query = $parameters; - break; - } - - $queryString = ''; - if (isset($components['query'])) { - parse_str(html_entity_decode($components['query']), $qs); - - if ($query) { - $query = array_replace($qs, $query); - $queryString = http_build_query($query, '', '&'); - } else { - $query = $qs; - $queryString = $components['query']; - } - } elseif ($query) { - $queryString = http_build_query($query, '', '&'); - } - - $server['REQUEST_URI'] = $components['path'].('' !== $queryString ? '?'.$queryString : ''); - $server['QUERY_STRING'] = $queryString; - - return self::createRequestFromFactory($query, $request, [], $cookies, $files, $server, $content); - } - - /** - * Sets a callable able to create a Request instance. - * - * This is mainly useful when you need to override the Request class - * to keep BC with an existing system. It should not be used for any - * other purpose. - */ - public static function setFactory(?callable $callable) - { - self::$requestFactory = $callable; - } - - /** - * Clones a request and overrides some of its parameters. - * - * @param array $query The GET parameters - * @param array $request The POST parameters - * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) - * @param array $cookies The COOKIE parameters - * @param array $files The FILES parameters - * @param array $server The SERVER parameters - * - * @return static - */ - public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null) - { - $dup = clone $this; - if (null !== $query) { - $dup->query = new InputBag($query); - } - if (null !== $request) { - $dup->request = new InputBag($request); - } - if (null !== $attributes) { - $dup->attributes = new ParameterBag($attributes); - } - if (null !== $cookies) { - $dup->cookies = new InputBag($cookies); - } - if (null !== $files) { - $dup->files = new FileBag($files); - } - if (null !== $server) { - $dup->server = new ServerBag($server); - $dup->headers = new HeaderBag($dup->server->getHeaders()); - } - $dup->languages = null; - $dup->charsets = null; - $dup->encodings = null; - $dup->acceptableContentTypes = null; - $dup->pathInfo = null; - $dup->requestUri = null; - $dup->baseUrl = null; - $dup->basePath = null; - $dup->method = null; - $dup->format = null; - - if (!$dup->get('_format') && $this->get('_format')) { - $dup->attributes->set('_format', $this->get('_format')); - } - - if (!$dup->getRequestFormat(null)) { - $dup->setRequestFormat($this->getRequestFormat(null)); - } - - return $dup; - } - - /** - * Clones the current request. - * - * Note that the session is not cloned as duplicated requests - * are most of the time sub-requests of the main one. - */ - public function __clone() - { - $this->query = clone $this->query; - $this->request = clone $this->request; - $this->attributes = clone $this->attributes; - $this->cookies = clone $this->cookies; - $this->files = clone $this->files; - $this->server = clone $this->server; - $this->headers = clone $this->headers; - } - - /** - * Returns the request as a string. - * - * @return string - */ - public function __toString() - { - $content = $this->getContent(); - - $cookieHeader = ''; - $cookies = []; - - foreach ($this->cookies as $k => $v) { - $cookies[] = \is_array($v) ? http_build_query([$k => $v], '', '; ', \PHP_QUERY_RFC3986) : "$k=$v"; - } - - if ($cookies) { - $cookieHeader = 'Cookie: '.implode('; ', $cookies)."\r\n"; - } - - return - sprintf('%s %s %s', $this->getMethod(), $this->getRequestUri(), $this->server->get('SERVER_PROTOCOL'))."\r\n". - $this->headers. - $cookieHeader."\r\n". - $content; - } - - /** - * Overrides the PHP global variables according to this request instance. - * - * It overrides $_GET, $_POST, $_REQUEST, $_SERVER, $_COOKIE. - * $_FILES is never overridden, see rfc1867 - */ - public function overrideGlobals() - { - $this->server->set('QUERY_STRING', static::normalizeQueryString(http_build_query($this->query->all(), '', '&'))); - - $_GET = $this->query->all(); - $_POST = $this->request->all(); - $_SERVER = $this->server->all(); - $_COOKIE = $this->cookies->all(); - - foreach ($this->headers->all() as $key => $value) { - $key = strtoupper(str_replace('-', '_', $key)); - if (\in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH', 'CONTENT_MD5'], true)) { - $_SERVER[$key] = implode(', ', $value); - } else { - $_SERVER['HTTP_'.$key] = implode(', ', $value); - } - } - - $request = ['g' => $_GET, 'p' => $_POST, 'c' => $_COOKIE]; - - $requestOrder = \ini_get('request_order') ?: \ini_get('variables_order'); - $requestOrder = preg_replace('#[^cgp]#', '', strtolower($requestOrder)) ?: 'gp'; - - $_REQUEST = [[]]; - - foreach (str_split($requestOrder) as $order) { - $_REQUEST[] = $request[$order]; - } - - $_REQUEST = array_merge(...$_REQUEST); - } - - /** - * Sets a list of trusted proxies. - * - * You should only list the reverse proxies that you manage directly. - * - * @param array $proxies A list of trusted proxies, the string 'REMOTE_ADDR' will be replaced with $_SERVER['REMOTE_ADDR'] - * @param int $trustedHeaderSet A bit field of Request::HEADER_*, to set which headers to trust from your proxies - */ - public static function setTrustedProxies(array $proxies, int $trustedHeaderSet) - { - if (self::HEADER_X_FORWARDED_ALL === $trustedHeaderSet) { - trigger_deprecation('symfony/http-foundation', '5.2', 'The "HEADER_X_FORWARDED_ALL" constant is deprecated, use either "HEADER_X_FORWARDED_FOR | HEADER_X_FORWARDED_HOST | HEADER_X_FORWARDED_PORT | HEADER_X_FORWARDED_PROTO" or "HEADER_X_FORWARDED_AWS_ELB" or "HEADER_X_FORWARDED_TRAEFIK" constants instead.'); - } - self::$trustedProxies = array_reduce($proxies, function ($proxies, $proxy) { - if ('REMOTE_ADDR' !== $proxy) { - $proxies[] = $proxy; - } elseif (isset($_SERVER['REMOTE_ADDR'])) { - $proxies[] = $_SERVER['REMOTE_ADDR']; - } - - return $proxies; - }, []); - self::$trustedHeaderSet = $trustedHeaderSet; - } - - /** - * Gets the list of trusted proxies. - * - * @return array - */ - public static function getTrustedProxies() - { - return self::$trustedProxies; - } - - /** - * Gets the set of trusted headers from trusted proxies. - * - * @return int A bit field of Request::HEADER_* that defines which headers are trusted from your proxies - */ - public static function getTrustedHeaderSet() - { - return self::$trustedHeaderSet; - } - - /** - * Sets a list of trusted host patterns. - * - * You should only list the hosts you manage using regexs. - * - * @param array $hostPatterns A list of trusted host patterns - */ - public static function setTrustedHosts(array $hostPatterns) - { - self::$trustedHostPatterns = array_map(function ($hostPattern) { - return sprintf('{%s}i', $hostPattern); - }, $hostPatterns); - // we need to reset trusted hosts on trusted host patterns change - self::$trustedHosts = []; - } - - /** - * Gets the list of trusted host patterns. - * - * @return array - */ - public static function getTrustedHosts() - { - return self::$trustedHostPatterns; - } - - /** - * Normalizes a query string. - * - * It builds a normalized query string, where keys/value pairs are alphabetized, - * have consistent escaping and unneeded delimiters are removed. - * - * @return string - */ - public static function normalizeQueryString(?string $qs) - { - if ('' === ($qs ?? '')) { - return ''; - } - - $qs = HeaderUtils::parseQuery($qs); - ksort($qs); - - return http_build_query($qs, '', '&', \PHP_QUERY_RFC3986); - } - - /** - * Enables support for the _method request parameter to determine the intended HTTP method. - * - * Be warned that enabling this feature might lead to CSRF issues in your code. - * Check that you are using CSRF tokens when required. - * If the HTTP method parameter override is enabled, an html-form with method "POST" can be altered - * and used to send a "PUT" or "DELETE" request via the _method request parameter. - * If these methods are not protected against CSRF, this presents a possible vulnerability. - * - * The HTTP method can only be overridden when the real HTTP method is POST. - */ - public static function enableHttpMethodParameterOverride() - { - self::$httpMethodParameterOverride = true; - } - - /** - * Checks whether support for the _method request parameter is enabled. - * - * @return bool - */ - public static function getHttpMethodParameterOverride() - { - return self::$httpMethodParameterOverride; - } - - /** - * Gets a "parameter" value from any bag. - * - * This method is mainly useful for libraries that want to provide some flexibility. If you don't need the - * flexibility in controllers, it is better to explicitly get request parameters from the appropriate - * public property instead (attributes, query, request). - * - * Order of precedence: PATH (routing placeholders or custom attributes), GET, POST - * - * @param mixed $default The default value if the parameter key does not exist - * - * @return mixed - * - * @internal since Symfony 5.4, use explicit input sources instead - */ - public function get(string $key, $default = null) - { - if ($this !== $result = $this->attributes->get($key, $this)) { - return $result; - } - - if ($this->query->has($key)) { - return $this->query->all()[$key]; - } - - if ($this->request->has($key)) { - return $this->request->all()[$key]; - } - - return $default; - } - - /** - * Gets the Session. - * - * @return SessionInterface - */ - public function getSession() - { - $session = $this->session; - if (!$session instanceof SessionInterface && null !== $session) { - $this->setSession($session = $session()); - } - - if (null === $session) { - throw new SessionNotFoundException('Session has not been set.'); - } - - return $session; - } - - /** - * Whether the request contains a Session which was started in one of the - * previous requests. - * - * @return bool - */ - public function hasPreviousSession() - { - // the check for $this->session avoids malicious users trying to fake a session cookie with proper name - return $this->hasSession() && $this->cookies->has($this->getSession()->getName()); - } - - /** - * Whether the request contains a Session object. - * - * This method does not give any information about the state of the session object, - * like whether the session is started or not. It is just a way to check if this Request - * is associated with a Session instance. - * - * @param bool $skipIfUninitialized When true, ignores factories injected by `setSessionFactory` - * - * @return bool - */ - public function hasSession(/* bool $skipIfUninitialized = false */) - { - $skipIfUninitialized = \func_num_args() > 0 ? func_get_arg(0) : false; - - return null !== $this->session && (!$skipIfUninitialized || $this->session instanceof SessionInterface); - } - - public function setSession(SessionInterface $session) - { - $this->session = $session; - } - - /** - * @internal - * - * @param callable(): SessionInterface $factory - */ - public function setSessionFactory(callable $factory) - { - $this->session = $factory; - } - - /** - * Returns the client IP addresses. - * - * In the returned array the most trusted IP address is first, and the - * least trusted one last. The "real" client IP address is the last one, - * but this is also the least trusted one. Trusted proxies are stripped. - * - * Use this method carefully; you should use getClientIp() instead. - * - * @return array - * - * @see getClientIp() - */ - public function getClientIps() - { - $ip = $this->server->get('REMOTE_ADDR'); - - if (!$this->isFromTrustedProxy()) { - return [$ip]; - } - - return $this->getTrustedValues(self::HEADER_X_FORWARDED_FOR, $ip) ?: [$ip]; - } - - /** - * Returns the client IP address. - * - * This method can read the client IP address from the "X-Forwarded-For" header - * when trusted proxies were set via "setTrustedProxies()". The "X-Forwarded-For" - * header value is a comma+space separated list of IP addresses, the left-most - * being the original client, and each successive proxy that passed the request - * adding the IP address where it received the request from. - * - * If your reverse proxy uses a different header name than "X-Forwarded-For", - * ("Client-Ip" for instance), configure it via the $trustedHeaderSet - * argument of the Request::setTrustedProxies() method instead. - * - * @return string|null - * - * @see getClientIps() - * @see https://wikipedia.org/wiki/X-Forwarded-For - */ - public function getClientIp() - { - $ipAddresses = $this->getClientIps(); - - return $ipAddresses[0]; - } - - /** - * Returns current script name. - * - * @return string - */ - public function getScriptName() - { - return $this->server->get('SCRIPT_NAME', $this->server->get('ORIG_SCRIPT_NAME', '')); - } - - /** - * Returns the path being requested relative to the executed script. - * - * The path info always starts with a /. - * - * Suppose this request is instantiated from /mysite on localhost: - * - * * http://localhost/mysite returns an empty string - * * http://localhost/mysite/about returns '/about' - * * http://localhost/mysite/enco%20ded returns '/enco%20ded' - * * http://localhost/mysite/about?var=1 returns '/about' - * - * @return string The raw path (i.e. not urldecoded) - */ - public function getPathInfo() - { - if (null === $this->pathInfo) { - $this->pathInfo = $this->preparePathInfo(); - } - - return $this->pathInfo; - } - - /** - * Returns the root path from which this request is executed. - * - * Suppose that an index.php file instantiates this request object: - * - * * http://localhost/index.php returns an empty string - * * http://localhost/index.php/page returns an empty string - * * http://localhost/web/index.php returns '/web' - * * http://localhost/we%20b/index.php returns '/we%20b' - * - * @return string The raw path (i.e. not urldecoded) - */ - public function getBasePath() - { - if (null === $this->basePath) { - $this->basePath = $this->prepareBasePath(); - } - - return $this->basePath; - } - - /** - * Returns the root URL from which this request is executed. - * - * The base URL never ends with a /. - * - * This is similar to getBasePath(), except that it also includes the - * script filename (e.g. index.php) if one exists. - * - * @return string The raw URL (i.e. not urldecoded) - */ - public function getBaseUrl() - { - $trustedPrefix = ''; - - // the proxy prefix must be prepended to any prefix being needed at the webserver level - if ($this->isFromTrustedProxy() && $trustedPrefixValues = $this->getTrustedValues(self::HEADER_X_FORWARDED_PREFIX)) { - $trustedPrefix = rtrim($trustedPrefixValues[0], '/'); - } - - return $trustedPrefix.$this->getBaseUrlReal(); - } - - /** - * Returns the real base URL received by the webserver from which this request is executed. - * The URL does not include trusted reverse proxy prefix. - * - * @return string The raw URL (i.e. not urldecoded) - */ - private function getBaseUrlReal(): string - { - if (null === $this->baseUrl) { - $this->baseUrl = $this->prepareBaseUrl(); - } - - return $this->baseUrl; - } - - /** - * Gets the request's scheme. - * - * @return string - */ - public function getScheme() - { - return $this->isSecure() ? 'https' : 'http'; - } - - /** - * Returns the port on which the request is made. - * - * This method can read the client port from the "X-Forwarded-Port" header - * when trusted proxies were set via "setTrustedProxies()". - * - * The "X-Forwarded-Port" header must contain the client port. - * - * @return int|string|null Can be a string if fetched from the server bag - */ - public function getPort() - { - if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_PORT)) { - $host = $host[0]; - } elseif ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_HOST)) { - $host = $host[0]; - } elseif (!$host = $this->headers->get('HOST')) { - return $this->server->get('SERVER_PORT'); - } - - if ('[' === $host[0]) { - $pos = strpos($host, ':', strrpos($host, ']')); - } else { - $pos = strrpos($host, ':'); - } - - if (false !== $pos && $port = substr($host, $pos + 1)) { - return (int) $port; - } - - return 'https' === $this->getScheme() ? 443 : 80; - } - - /** - * Returns the user. - * - * @return string|null - */ - public function getUser() - { - return $this->headers->get('PHP_AUTH_USER'); - } - - /** - * Returns the password. - * - * @return string|null - */ - public function getPassword() - { - return $this->headers->get('PHP_AUTH_PW'); - } - - /** - * Gets the user info. - * - * @return string|null A user name if any and, optionally, scheme-specific information about how to gain authorization to access the server - */ - public function getUserInfo() - { - $userinfo = $this->getUser(); - - $pass = $this->getPassword(); - if ('' != $pass) { - $userinfo .= ":$pass"; - } - - return $userinfo; - } - - /** - * Returns the HTTP host being requested. - * - * The port name will be appended to the host if it's non-standard. - * - * @return string - */ - public function getHttpHost() - { - $scheme = $this->getScheme(); - $port = $this->getPort(); - - if (('http' == $scheme && 80 == $port) || ('https' == $scheme && 443 == $port)) { - return $this->getHost(); - } - - return $this->getHost().':'.$port; - } - - /** - * Returns the requested URI (path and query string). - * - * @return string The raw URI (i.e. not URI decoded) - */ - public function getRequestUri() - { - if (null === $this->requestUri) { - $this->requestUri = $this->prepareRequestUri(); - } - - return $this->requestUri; - } - - /** - * Gets the scheme and HTTP host. - * - * If the URL was called with basic authentication, the user - * and the password are not added to the generated string. - * - * @return string - */ - public function getSchemeAndHttpHost() - { - return $this->getScheme().'://'.$this->getHttpHost(); - } - - /** - * Generates a normalized URI (URL) for the Request. - * - * @return string - * - * @see getQueryString() - */ - public function getUri() - { - if (null !== $qs = $this->getQueryString()) { - $qs = '?'.$qs; - } - - return $this->getSchemeAndHttpHost().$this->getBaseUrl().$this->getPathInfo().$qs; - } - - /** - * Generates a normalized URI for the given path. - * - * @param string $path A path to use instead of the current one - * - * @return string - */ - public function getUriForPath(string $path) - { - return $this->getSchemeAndHttpHost().$this->getBaseUrl().$path; - } - - /** - * Returns the path as relative reference from the current Request path. - * - * Only the URIs path component (no schema, host etc.) is relevant and must be given. - * Both paths must be absolute and not contain relative parts. - * Relative URLs from one resource to another are useful when generating self-contained downloadable document archives. - * Furthermore, they can be used to reduce the link size in documents. - * - * Example target paths, given a base path of "/a/b/c/d": - * - "/a/b/c/d" -> "" - * - "/a/b/c/" -> "./" - * - "/a/b/" -> "../" - * - "/a/b/c/other" -> "other" - * - "/a/x/y" -> "../../x/y" - * - * @return string - */ - public function getRelativeUriForPath(string $path) - { - // be sure that we are dealing with an absolute path - if (!isset($path[0]) || '/' !== $path[0]) { - return $path; - } - - if ($path === $basePath = $this->getPathInfo()) { - return ''; - } - - $sourceDirs = explode('/', isset($basePath[0]) && '/' === $basePath[0] ? substr($basePath, 1) : $basePath); - $targetDirs = explode('/', substr($path, 1)); - array_pop($sourceDirs); - $targetFile = array_pop($targetDirs); - - foreach ($sourceDirs as $i => $dir) { - if (isset($targetDirs[$i]) && $dir === $targetDirs[$i]) { - unset($sourceDirs[$i], $targetDirs[$i]); - } else { - break; - } - } - - $targetDirs[] = $targetFile; - $path = str_repeat('../', \count($sourceDirs)).implode('/', $targetDirs); - - // A reference to the same base directory or an empty subdirectory must be prefixed with "./". - // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used - // as the first segment of a relative-path reference, as it would be mistaken for a scheme name - // (see https://tools.ietf.org/html/rfc3986#section-4.2). - return !isset($path[0]) || '/' === $path[0] - || false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || false === $slashPos) - ? "./$path" : $path; - } - - /** - * Generates the normalized query string for the Request. - * - * It builds a normalized query string, where keys/value pairs are alphabetized - * and have consistent escaping. - * - * @return string|null - */ - public function getQueryString() - { - $qs = static::normalizeQueryString($this->server->get('QUERY_STRING')); - - return '' === $qs ? null : $qs; - } - - /** - * Checks whether the request is secure or not. - * - * This method can read the client protocol from the "X-Forwarded-Proto" header - * when trusted proxies were set via "setTrustedProxies()". - * - * The "X-Forwarded-Proto" header must contain the protocol: "https" or "http". - * - * @return bool - */ - public function isSecure() - { - if ($this->isFromTrustedProxy() && $proto = $this->getTrustedValues(self::HEADER_X_FORWARDED_PROTO)) { - return \in_array(strtolower($proto[0]), ['https', 'on', 'ssl', '1'], true); - } - - $https = $this->server->get('HTTPS'); - - return !empty($https) && 'off' !== strtolower($https); - } - - /** - * Returns the host name. - * - * This method can read the client host name from the "X-Forwarded-Host" header - * when trusted proxies were set via "setTrustedProxies()". - * - * The "X-Forwarded-Host" header must contain the client host name. - * - * @return string - * - * @throws SuspiciousOperationException when the host name is invalid or not trusted - */ - public function getHost() - { - if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_HOST)) { - $host = $host[0]; - } elseif (!$host = $this->headers->get('HOST')) { - if (!$host = $this->server->get('SERVER_NAME')) { - $host = $this->server->get('SERVER_ADDR', ''); - } - } - - // trim and remove port number from host - // host is lowercase as per RFC 952/2181 - $host = strtolower(preg_replace('/:\d+$/', '', trim($host))); - - // as the host can come from the user (HTTP_HOST and depending on the configuration, SERVER_NAME too can come from the user) - // check that it does not contain forbidden characters (see RFC 952 and RFC 2181) - // use preg_replace() instead of preg_match() to prevent DoS attacks with long host names - if ($host && '' !== preg_replace('/(?:^\[)?[a-zA-Z0-9-:\]_]+\.?/', '', $host)) { - if (!$this->isHostValid) { - return ''; - } - $this->isHostValid = false; - - throw new SuspiciousOperationException(sprintf('Invalid Host "%s".', $host)); - } - - if (\count(self::$trustedHostPatterns) > 0) { - // to avoid host header injection attacks, you should provide a list of trusted host patterns - - if (\in_array($host, self::$trustedHosts)) { - return $host; - } - - foreach (self::$trustedHostPatterns as $pattern) { - if (preg_match($pattern, $host)) { - self::$trustedHosts[] = $host; - - return $host; - } - } - - if (!$this->isHostValid) { - return ''; - } - $this->isHostValid = false; - - throw new SuspiciousOperationException(sprintf('Untrusted Host "%s".', $host)); - } - - return $host; - } - - /** - * Sets the request method. - */ - public function setMethod(string $method) - { - $this->method = null; - $this->server->set('REQUEST_METHOD', $method); - } - - /** - * Gets the request "intended" method. - * - * If the X-HTTP-Method-Override header is set, and if the method is a POST, - * then it is used to determine the "real" intended HTTP method. - * - * The _method request parameter can also be used to determine the HTTP method, - * but only if enableHttpMethodParameterOverride() has been called. - * - * The method is always an uppercased string. - * - * @return string - * - * @see getRealMethod() - */ - public function getMethod() - { - if (null !== $this->method) { - return $this->method; - } - - $this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET')); - - if ('POST' !== $this->method) { - return $this->method; - } - - $method = $this->headers->get('X-HTTP-METHOD-OVERRIDE'); - - if (!$method && self::$httpMethodParameterOverride) { - $method = $this->request->get('_method', $this->query->get('_method', 'POST')); - } - - if (!\is_string($method)) { - return $this->method; - } - - $method = strtoupper($method); - - if (\in_array($method, ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'PATCH', 'PURGE', 'TRACE'], true)) { - return $this->method = $method; - } - - if (!preg_match('/^[A-Z]++$/D', $method)) { - throw new SuspiciousOperationException(sprintf('Invalid method override "%s".', $method)); - } - - return $this->method = $method; - } - - /** - * Gets the "real" request method. - * - * @return string - * - * @see getMethod() - */ - public function getRealMethod() - { - return strtoupper($this->server->get('REQUEST_METHOD', 'GET')); - } - - /** - * Gets the mime type associated with the format. - * - * @return string|null - */ - public function getMimeType(string $format) - { - if (null === static::$formats) { - static::initializeFormats(); - } - - return isset(static::$formats[$format]) ? static::$formats[$format][0] : null; - } - - /** - * Gets the mime types associated with the format. - * - * @return array - */ - public static function getMimeTypes(string $format) - { - if (null === static::$formats) { - static::initializeFormats(); - } - - return static::$formats[$format] ?? []; - } - - /** - * Gets the format associated with the mime type. - * - * @return string|null - */ - public function getFormat(?string $mimeType) - { - $canonicalMimeType = null; - if ($mimeType && false !== $pos = strpos($mimeType, ';')) { - $canonicalMimeType = trim(substr($mimeType, 0, $pos)); - } - - if (null === static::$formats) { - static::initializeFormats(); - } - - foreach (static::$formats as $format => $mimeTypes) { - if (\in_array($mimeType, (array) $mimeTypes)) { - return $format; - } - if (null !== $canonicalMimeType && \in_array($canonicalMimeType, (array) $mimeTypes)) { - return $format; - } - } - - return null; - } - - /** - * Associates a format with mime types. - * - * @param string|array $mimeTypes The associated mime types (the preferred one must be the first as it will be used as the content type) - */ - public function setFormat(?string $format, $mimeTypes) - { - if (null === static::$formats) { - static::initializeFormats(); - } - - static::$formats[$format] = \is_array($mimeTypes) ? $mimeTypes : [$mimeTypes]; - } - - /** - * Gets the request format. - * - * Here is the process to determine the format: - * - * * format defined by the user (with setRequestFormat()) - * * _format request attribute - * * $default - * - * @see getPreferredFormat - * - * @return string|null - */ - public function getRequestFormat(?string $default = 'html') - { - if (null === $this->format) { - $this->format = $this->attributes->get('_format'); - } - - return $this->format ?? $default; - } - - /** - * Sets the request format. - */ - public function setRequestFormat(?string $format) - { - $this->format = $format; - } - - /** - * Gets the format associated with the request. - * - * @return string|null - */ - public function getContentType() - { - return $this->getFormat($this->headers->get('CONTENT_TYPE', '')); - } - - /** - * Sets the default locale. - */ - public function setDefaultLocale(string $locale) - { - $this->defaultLocale = $locale; - - if (null === $this->locale) { - $this->setPhpDefaultLocale($locale); - } - } - - /** - * Get the default locale. - * - * @return string - */ - public function getDefaultLocale() - { - return $this->defaultLocale; - } - - /** - * Sets the locale. - */ - public function setLocale(string $locale) - { - $this->setPhpDefaultLocale($this->locale = $locale); - } - - /** - * Get the locale. - * - * @return string - */ - public function getLocale() - { - return null === $this->locale ? $this->defaultLocale : $this->locale; - } - - /** - * Checks if the request method is of specified type. - * - * @param string $method Uppercase request method (GET, POST etc) - * - * @return bool - */ - public function isMethod(string $method) - { - return $this->getMethod() === strtoupper($method); - } - - /** - * Checks whether or not the method is safe. - * - * @see https://tools.ietf.org/html/rfc7231#section-4.2.1 - * - * @return bool - */ - public function isMethodSafe() - { - return \in_array($this->getMethod(), ['GET', 'HEAD', 'OPTIONS', 'TRACE']); - } - - /** - * Checks whether or not the method is idempotent. - * - * @return bool - */ - public function isMethodIdempotent() - { - return \in_array($this->getMethod(), ['HEAD', 'GET', 'PUT', 'DELETE', 'TRACE', 'OPTIONS', 'PURGE']); - } - - /** - * Checks whether the method is cacheable or not. - * - * @see https://tools.ietf.org/html/rfc7231#section-4.2.3 - * - * @return bool - */ - public function isMethodCacheable() - { - return \in_array($this->getMethod(), ['GET', 'HEAD']); - } - - /** - * Returns the protocol version. - * - * If the application is behind a proxy, the protocol version used in the - * requests between the client and the proxy and between the proxy and the - * server might be different. This returns the former (from the "Via" header) - * if the proxy is trusted (see "setTrustedProxies()"), otherwise it returns - * the latter (from the "SERVER_PROTOCOL" server parameter). - * - * @return string|null - */ - public function getProtocolVersion() - { - if ($this->isFromTrustedProxy()) { - preg_match('~^(HTTP/)?([1-9]\.[0-9]) ~', $this->headers->get('Via') ?? '', $matches); - - if ($matches) { - return 'HTTP/'.$matches[2]; - } - } - - return $this->server->get('SERVER_PROTOCOL'); - } - - /** - * Returns the request body content. - * - * @param bool $asResource If true, a resource will be returned - * - * @return string|resource - */ - public function getContent(bool $asResource = false) - { - $currentContentIsResource = \is_resource($this->content); - - if (true === $asResource) { - if ($currentContentIsResource) { - rewind($this->content); - - return $this->content; - } - - // Content passed in parameter (test) - if (\is_string($this->content)) { - $resource = fopen('php://temp', 'r+'); - fwrite($resource, $this->content); - rewind($resource); - - return $resource; - } - - $this->content = false; - - return fopen('php://input', 'r'); - } - - if ($currentContentIsResource) { - rewind($this->content); - - return stream_get_contents($this->content); - } - - if (null === $this->content || false === $this->content) { - $this->content = file_get_contents('php://input'); - } - - return $this->content; - } - - /** - * Gets the request body decoded as array, typically from a JSON payload. - * - * @throws JsonException When the body cannot be decoded to an array - * - * @return array - */ - public function toArray() - { - if ('' === $content = $this->getContent()) { - throw new JsonException('Request body is empty.'); - } - - try { - $content = json_decode($content, true, 512, \JSON_BIGINT_AS_STRING | (\PHP_VERSION_ID >= 70300 ? \JSON_THROW_ON_ERROR : 0)); - } catch (\JsonException $e) { - throw new JsonException('Could not decode request body.', $e->getCode(), $e); - } - - if (\PHP_VERSION_ID < 70300 && \JSON_ERROR_NONE !== json_last_error()) { - throw new JsonException('Could not decode request body: '.json_last_error_msg(), json_last_error()); - } - - if (!\is_array($content)) { - throw new JsonException(sprintf('JSON content was expected to decode to an array, "%s" returned.', get_debug_type($content))); - } - - return $content; - } - - /** - * Gets the Etags. - * - * @return array - */ - public function getETags() - { - return preg_split('/\s*,\s*/', $this->headers->get('If-None-Match', ''), -1, \PREG_SPLIT_NO_EMPTY); - } - - /** - * @return bool - */ - public function isNoCache() - { - return $this->headers->hasCacheControlDirective('no-cache') || 'no-cache' == $this->headers->get('Pragma'); - } - - /** - * Gets the preferred format for the response by inspecting, in the following order: - * * the request format set using setRequestFormat; - * * the values of the Accept HTTP header. - * - * Note that if you use this method, you should send the "Vary: Accept" header - * in the response to prevent any issues with intermediary HTTP caches. - */ - public function getPreferredFormat(?string $default = 'html'): ?string - { - if (null !== $this->preferredFormat || null !== $this->preferredFormat = $this->getRequestFormat(null)) { - return $this->preferredFormat; - } - - foreach ($this->getAcceptableContentTypes() as $mimeType) { - if ($this->preferredFormat = $this->getFormat($mimeType)) { - return $this->preferredFormat; - } - } - - return $default; - } - - /** - * Returns the preferred language. - * - * @param string[] $locales An array of ordered available locales - * - * @return string|null - */ - public function getPreferredLanguage(array $locales = null) - { - $preferredLanguages = $this->getLanguages(); - - if (empty($locales)) { - return $preferredLanguages[0] ?? null; - } - - if (!$preferredLanguages) { - return $locales[0]; - } - - $extendedPreferredLanguages = []; - foreach ($preferredLanguages as $language) { - $extendedPreferredLanguages[] = $language; - if (false !== $position = strpos($language, '_')) { - $superLanguage = substr($language, 0, $position); - if (!\in_array($superLanguage, $preferredLanguages)) { - $extendedPreferredLanguages[] = $superLanguage; - } - } - } - - $preferredLanguages = array_values(array_intersect($extendedPreferredLanguages, $locales)); - - return $preferredLanguages[0] ?? $locales[0]; - } - - /** - * Gets a list of languages acceptable by the client browser ordered in the user browser preferences. - * - * @return array - */ - public function getLanguages() - { - if (null !== $this->languages) { - return $this->languages; - } - - $languages = AcceptHeader::fromString($this->headers->get('Accept-Language'))->all(); - $this->languages = []; - foreach ($languages as $acceptHeaderItem) { - $lang = $acceptHeaderItem->getValue(); - if (str_contains($lang, '-')) { - $codes = explode('-', $lang); - if ('i' === $codes[0]) { - // Language not listed in ISO 639 that are not variants - // of any listed language, which can be registered with the - // i-prefix, such as i-cherokee - if (\count($codes) > 1) { - $lang = $codes[1]; - } - } else { - for ($i = 0, $max = \count($codes); $i < $max; ++$i) { - if (0 === $i) { - $lang = strtolower($codes[0]); - } else { - $lang .= '_'.strtoupper($codes[$i]); - } - } - } - } - - $this->languages[] = $lang; - } - - return $this->languages; - } - - /** - * Gets a list of charsets acceptable by the client browser in preferable order. - * - * @return array - */ - public function getCharsets() - { - if (null !== $this->charsets) { - return $this->charsets; - } - - return $this->charsets = array_map('strval', array_keys(AcceptHeader::fromString($this->headers->get('Accept-Charset'))->all())); - } - - /** - * Gets a list of encodings acceptable by the client browser in preferable order. - * - * @return array - */ - public function getEncodings() - { - if (null !== $this->encodings) { - return $this->encodings; - } - - return $this->encodings = array_map('strval', array_keys(AcceptHeader::fromString($this->headers->get('Accept-Encoding'))->all())); - } - - /** - * Gets a list of content types acceptable by the client browser in preferable order. - * - * @return array - */ - public function getAcceptableContentTypes() - { - if (null !== $this->acceptableContentTypes) { - return $this->acceptableContentTypes; - } - - return $this->acceptableContentTypes = array_map('strval', array_keys(AcceptHeader::fromString($this->headers->get('Accept'))->all())); - } - - /** - * Returns true if the request is an XMLHttpRequest. - * - * It works if your JavaScript library sets an X-Requested-With HTTP header. - * It is known to work with common JavaScript frameworks: - * - * @see https://wikipedia.org/wiki/List_of_Ajax_frameworks#JavaScript - * - * @return bool - */ - public function isXmlHttpRequest() - { - return 'XMLHttpRequest' == $this->headers->get('X-Requested-With'); - } - - /** - * Checks whether the client browser prefers safe content or not according to RFC8674. - * - * @see https://tools.ietf.org/html/rfc8674 - */ - public function preferSafeContent(): bool - { - if (null !== $this->isSafeContentPreferred) { - return $this->isSafeContentPreferred; - } - - if (!$this->isSecure()) { - // see https://tools.ietf.org/html/rfc8674#section-3 - return $this->isSafeContentPreferred = false; - } - - return $this->isSafeContentPreferred = AcceptHeader::fromString($this->headers->get('Prefer'))->has('safe'); - } - - /* - * The following methods are derived from code of the Zend Framework (1.10dev - 2010-01-24) - * - * Code subject to the new BSD license (https://framework.zend.com/license). - * - * Copyright (c) 2005-2010 Zend Technologies USA Inc. (https://www.zend.com/) - */ - - protected function prepareRequestUri() - { - $requestUri = ''; - - if ('1' == $this->server->get('IIS_WasUrlRewritten') && '' != $this->server->get('UNENCODED_URL')) { - // IIS7 with URL Rewrite: make sure we get the unencoded URL (double slash problem) - $requestUri = $this->server->get('UNENCODED_URL'); - $this->server->remove('UNENCODED_URL'); - $this->server->remove('IIS_WasUrlRewritten'); - } elseif ($this->server->has('REQUEST_URI')) { - $requestUri = $this->server->get('REQUEST_URI'); - - if ('' !== $requestUri && '/' === $requestUri[0]) { - // To only use path and query remove the fragment. - if (false !== $pos = strpos($requestUri, '#')) { - $requestUri = substr($requestUri, 0, $pos); - } - } else { - // HTTP proxy reqs setup request URI with scheme and host [and port] + the URL path, - // only use URL path. - $uriComponents = parse_url($requestUri); - - if (isset($uriComponents['path'])) { - $requestUri = $uriComponents['path']; - } - - if (isset($uriComponents['query'])) { - $requestUri .= '?'.$uriComponents['query']; - } - } - } elseif ($this->server->has('ORIG_PATH_INFO')) { - // IIS 5.0, PHP as CGI - $requestUri = $this->server->get('ORIG_PATH_INFO'); - if ('' != $this->server->get('QUERY_STRING')) { - $requestUri .= '?'.$this->server->get('QUERY_STRING'); - } - $this->server->remove('ORIG_PATH_INFO'); - } - - // normalize the request URI to ease creating sub-requests from this request - $this->server->set('REQUEST_URI', $requestUri); - - return $requestUri; - } - - /** - * Prepares the base URL. - * - * @return string - */ - protected function prepareBaseUrl() - { - $filename = basename($this->server->get('SCRIPT_FILENAME', '')); - - if (basename($this->server->get('SCRIPT_NAME', '')) === $filename) { - $baseUrl = $this->server->get('SCRIPT_NAME'); - } elseif (basename($this->server->get('PHP_SELF', '')) === $filename) { - $baseUrl = $this->server->get('PHP_SELF'); - } elseif (basename($this->server->get('ORIG_SCRIPT_NAME', '')) === $filename) { - $baseUrl = $this->server->get('ORIG_SCRIPT_NAME'); // 1and1 shared hosting compatibility - } else { - // Backtrack up the script_filename to find the portion matching - // php_self - $path = $this->server->get('PHP_SELF', ''); - $file = $this->server->get('SCRIPT_FILENAME', ''); - $segs = explode('/', trim($file, '/')); - $segs = array_reverse($segs); - $index = 0; - $last = \count($segs); - $baseUrl = ''; - do { - $seg = $segs[$index]; - $baseUrl = '/'.$seg.$baseUrl; - ++$index; - } while ($last > $index && (false !== $pos = strpos($path, $baseUrl)) && 0 != $pos); - } - - // Does the baseUrl have anything in common with the request_uri? - $requestUri = $this->getRequestUri(); - if ('' !== $requestUri && '/' !== $requestUri[0]) { - $requestUri = '/'.$requestUri; - } - - if ($baseUrl && null !== $prefix = $this->getUrlencodedPrefix($requestUri, $baseUrl)) { - // full $baseUrl matches - return $prefix; - } - - if ($baseUrl && null !== $prefix = $this->getUrlencodedPrefix($requestUri, rtrim(\dirname($baseUrl), '/'.\DIRECTORY_SEPARATOR).'/')) { - // directory portion of $baseUrl matches - return rtrim($prefix, '/'.\DIRECTORY_SEPARATOR); - } - - $truncatedRequestUri = $requestUri; - if (false !== $pos = strpos($requestUri, '?')) { - $truncatedRequestUri = substr($requestUri, 0, $pos); - } - - $basename = basename($baseUrl ?? ''); - if (empty($basename) || !strpos(rawurldecode($truncatedRequestUri), $basename)) { - // no match whatsoever; set it blank - return ''; - } - - // If using mod_rewrite or ISAPI_Rewrite strip the script filename - // out of baseUrl. $pos !== 0 makes sure it is not matching a value - // from PATH_INFO or QUERY_STRING - if (\strlen($requestUri) >= \strlen($baseUrl) && (false !== $pos = strpos($requestUri, $baseUrl)) && 0 !== $pos) { - $baseUrl = substr($requestUri, 0, $pos + \strlen($baseUrl)); - } - - return rtrim($baseUrl, '/'.\DIRECTORY_SEPARATOR); - } - - /** - * Prepares the base path. - * - * @return string - */ - protected function prepareBasePath() - { - $baseUrl = $this->getBaseUrl(); - if (empty($baseUrl)) { - return ''; - } - - $filename = basename($this->server->get('SCRIPT_FILENAME')); - if (basename($baseUrl) === $filename) { - $basePath = \dirname($baseUrl); - } else { - $basePath = $baseUrl; - } - - if ('\\' === \DIRECTORY_SEPARATOR) { - $basePath = str_replace('\\', '/', $basePath); - } - - return rtrim($basePath, '/'); - } - - /** - * Prepares the path info. - * - * @return string - */ - protected function preparePathInfo() - { - if (null === ($requestUri = $this->getRequestUri())) { - return '/'; - } - - // Remove the query string from REQUEST_URI - if (false !== $pos = strpos($requestUri, '?')) { - $requestUri = substr($requestUri, 0, $pos); - } - if ('' !== $requestUri && '/' !== $requestUri[0]) { - $requestUri = '/'.$requestUri; - } - - if (null === ($baseUrl = $this->getBaseUrlReal())) { - return $requestUri; - } - - $pathInfo = substr($requestUri, \strlen($baseUrl)); - if (false === $pathInfo || '' === $pathInfo) { - // If substr() returns false then PATH_INFO is set to an empty string - return '/'; - } - - return $pathInfo; - } - - /** - * Initializes HTTP request formats. - */ - protected static function initializeFormats() - { - static::$formats = [ - 'html' => ['text/html', 'application/xhtml+xml'], - 'txt' => ['text/plain'], - 'js' => ['application/javascript', 'application/x-javascript', 'text/javascript'], - 'css' => ['text/css'], - 'json' => ['application/json', 'application/x-json'], - 'jsonld' => ['application/ld+json'], - 'xml' => ['text/xml', 'application/xml', 'application/x-xml'], - 'rdf' => ['application/rdf+xml'], - 'atom' => ['application/atom+xml'], - 'rss' => ['application/rss+xml'], - 'form' => ['application/x-www-form-urlencoded', 'multipart/form-data'], - ]; - } - - private function setPhpDefaultLocale(string $locale): void - { - // if either the class Locale doesn't exist, or an exception is thrown when - // setting the default locale, the intl module is not installed, and - // the call can be ignored: - try { - if (class_exists(\Locale::class, false)) { - \Locale::setDefault($locale); - } - } catch (\Exception $e) { - } - } - - /** - * Returns the prefix as encoded in the string when the string starts with - * the given prefix, null otherwise. - */ - private function getUrlencodedPrefix(string $string, string $prefix): ?string - { - if (!str_starts_with(rawurldecode($string), $prefix)) { - return null; - } - - $len = \strlen($prefix); - - if (preg_match(sprintf('#^(%%[[:xdigit:]]{2}|.){%d}#', $len), $string, $match)) { - return $match[0]; - } - - return null; - } - - private static function createRequestFromFactory(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null): self - { - if (self::$requestFactory) { - $request = (self::$requestFactory)($query, $request, $attributes, $cookies, $files, $server, $content); - - if (!$request instanceof self) { - throw new \LogicException('The Request factory must return an instance of Symfony\Component\HttpFoundation\Request.'); - } - - return $request; - } - - return new static($query, $request, $attributes, $cookies, $files, $server, $content); - } - - /** - * Indicates whether this request originated from a trusted proxy. - * - * This can be useful to determine whether or not to trust the - * contents of a proxy-specific header. - * - * @return bool - */ - public function isFromTrustedProxy() - { - return self::$trustedProxies && IpUtils::checkIp($this->server->get('REMOTE_ADDR', ''), self::$trustedProxies); - } - - private function getTrustedValues(int $type, string $ip = null): array - { - $clientValues = []; - $forwardedValues = []; - - if ((self::$trustedHeaderSet & $type) && $this->headers->has(self::TRUSTED_HEADERS[$type])) { - foreach (explode(',', $this->headers->get(self::TRUSTED_HEADERS[$type])) as $v) { - $clientValues[] = (self::HEADER_X_FORWARDED_PORT === $type ? '0.0.0.0:' : '').trim($v); - } - } - - if ((self::$trustedHeaderSet & self::HEADER_FORWARDED) && (isset(self::FORWARDED_PARAMS[$type])) && $this->headers->has(self::TRUSTED_HEADERS[self::HEADER_FORWARDED])) { - $forwarded = $this->headers->get(self::TRUSTED_HEADERS[self::HEADER_FORWARDED]); - $parts = HeaderUtils::split($forwarded, ',;='); - $forwardedValues = []; - $param = self::FORWARDED_PARAMS[$type]; - foreach ($parts as $subParts) { - if (null === $v = HeaderUtils::combine($subParts)[$param] ?? null) { - continue; - } - if (self::HEADER_X_FORWARDED_PORT === $type) { - if (str_ends_with($v, ']') || false === $v = strrchr($v, ':')) { - $v = $this->isSecure() ? ':443' : ':80'; - } - $v = '0.0.0.0'.$v; - } - $forwardedValues[] = $v; - } - } - - if (null !== $ip) { - $clientValues = $this->normalizeAndFilterClientIps($clientValues, $ip); - $forwardedValues = $this->normalizeAndFilterClientIps($forwardedValues, $ip); - } - - if ($forwardedValues === $clientValues || !$clientValues) { - return $forwardedValues; - } - - if (!$forwardedValues) { - return $clientValues; - } - - if (!$this->isForwardedValid) { - return null !== $ip ? ['0.0.0.0', $ip] : []; - } - $this->isForwardedValid = false; - - throw new ConflictingHeadersException(sprintf('The request has both a trusted "%s" header and a trusted "%s" header, conflicting with each other. You should either configure your proxy to remove one of them, or configure your project to distrust the offending one.', self::TRUSTED_HEADERS[self::HEADER_FORWARDED], self::TRUSTED_HEADERS[$type])); - } - - private function normalizeAndFilterClientIps(array $clientIps, string $ip): array - { - if (!$clientIps) { - return []; - } - $clientIps[] = $ip; // Complete the IP chain with the IP the request actually came from - $firstTrustedIp = null; - - foreach ($clientIps as $key => $clientIp) { - if (strpos($clientIp, '.')) { - // Strip :port from IPv4 addresses. This is allowed in Forwarded - // and may occur in X-Forwarded-For. - $i = strpos($clientIp, ':'); - if ($i) { - $clientIps[$key] = $clientIp = substr($clientIp, 0, $i); - } - } elseif (str_starts_with($clientIp, '[')) { - // Strip brackets and :port from IPv6 addresses. - $i = strpos($clientIp, ']', 1); - $clientIps[$key] = $clientIp = substr($clientIp, 1, $i - 1); - } - - if (!filter_var($clientIp, \FILTER_VALIDATE_IP)) { - unset($clientIps[$key]); - - continue; - } - - if (IpUtils::checkIp($clientIp, self::$trustedProxies)) { - unset($clientIps[$key]); - - // Fallback to this when the client IP falls into the range of trusted proxies - if (null === $firstTrustedIp) { - $firstTrustedIp = $clientIp; - } - } - } - - // Now the IP chain contains only untrusted proxies and the client IP - return $clientIps ? array_reverse($clientIps) : [$firstTrustedIp]; - } -} diff --git a/lib/symfony/http-foundation/RequestMatcher.php b/lib/symfony/http-foundation/RequestMatcher.php deleted file mode 100644 index f2645f9ae..000000000 --- a/lib/symfony/http-foundation/RequestMatcher.php +++ /dev/null @@ -1,196 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * RequestMatcher compares a pre-defined set of checks against a Request instance. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class RequestMatcher implements RequestMatcherInterface -{ - /** - * @var string|null - */ - private $path; - - /** - * @var string|null - */ - private $host; - - /** - * @var int|null - */ - private $port; - - /** - * @var string[] - */ - private $methods = []; - - /** - * @var string[] - */ - private $ips = []; - - /** - * @var array - */ - private $attributes = []; - - /** - * @var string[] - */ - private $schemes = []; - - /** - * @param string|string[]|null $methods - * @param string|string[]|null $ips - * @param string|string[]|null $schemes - */ - public function __construct(string $path = null, string $host = null, $methods = null, $ips = null, array $attributes = [], $schemes = null, int $port = null) - { - $this->matchPath($path); - $this->matchHost($host); - $this->matchMethod($methods); - $this->matchIps($ips); - $this->matchScheme($schemes); - $this->matchPort($port); - - foreach ($attributes as $k => $v) { - $this->matchAttribute($k, $v); - } - } - - /** - * Adds a check for the HTTP scheme. - * - * @param string|string[]|null $scheme An HTTP scheme or an array of HTTP schemes - */ - public function matchScheme($scheme) - { - $this->schemes = null !== $scheme ? array_map('strtolower', (array) $scheme) : []; - } - - /** - * Adds a check for the URL host name. - */ - public function matchHost(?string $regexp) - { - $this->host = $regexp; - } - - /** - * Adds a check for the the URL port. - * - * @param int|null $port The port number to connect to - */ - public function matchPort(?int $port) - { - $this->port = $port; - } - - /** - * Adds a check for the URL path info. - */ - public function matchPath(?string $regexp) - { - $this->path = $regexp; - } - - /** - * Adds a check for the client IP. - * - * @param string $ip A specific IP address or a range specified using IP/netmask like 192.168.1.0/24 - */ - public function matchIp(string $ip) - { - $this->matchIps($ip); - } - - /** - * Adds a check for the client IP. - * - * @param string|string[]|null $ips A specific IP address or a range specified using IP/netmask like 192.168.1.0/24 - */ - public function matchIps($ips) - { - $ips = null !== $ips ? (array) $ips : []; - - $this->ips = array_reduce($ips, static function (array $ips, string $ip) { - return array_merge($ips, preg_split('/\s*,\s*/', $ip)); - }, []); - } - - /** - * Adds a check for the HTTP method. - * - * @param string|string[]|null $method An HTTP method or an array of HTTP methods - */ - public function matchMethod($method) - { - $this->methods = null !== $method ? array_map('strtoupper', (array) $method) : []; - } - - /** - * Adds a check for request attribute. - */ - public function matchAttribute(string $key, string $regexp) - { - $this->attributes[$key] = $regexp; - } - - /** - * {@inheritdoc} - */ - public function matches(Request $request) - { - if ($this->schemes && !\in_array($request->getScheme(), $this->schemes, true)) { - return false; - } - - if ($this->methods && !\in_array($request->getMethod(), $this->methods, true)) { - return false; - } - - foreach ($this->attributes as $key => $pattern) { - $requestAttribute = $request->attributes->get($key); - if (!\is_string($requestAttribute)) { - return false; - } - if (!preg_match('{'.$pattern.'}', $requestAttribute)) { - return false; - } - } - - if (null !== $this->path && !preg_match('{'.$this->path.'}', rawurldecode($request->getPathInfo()))) { - return false; - } - - if (null !== $this->host && !preg_match('{'.$this->host.'}i', $request->getHost())) { - return false; - } - - if (null !== $this->port && 0 < $this->port && $request->getPort() !== $this->port) { - return false; - } - - if (IpUtils::checkIp($request->getClientIp() ?? '', $this->ips)) { - return true; - } - - // Note to future implementors: add additional checks above the - // foreach above or else your check might not be run! - return 0 === \count($this->ips); - } -} diff --git a/lib/symfony/http-foundation/RequestMatcherInterface.php b/lib/symfony/http-foundation/RequestMatcherInterface.php deleted file mode 100644 index c2e147858..000000000 --- a/lib/symfony/http-foundation/RequestMatcherInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * RequestMatcherInterface is an interface for strategies to match a Request. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface RequestMatcherInterface -{ - /** - * Decides whether the rule(s) implemented by the strategy matches the supplied request. - * - * @return bool - */ - public function matches(Request $request); -} diff --git a/lib/symfony/http-foundation/RequestStack.php b/lib/symfony/http-foundation/RequestStack.php deleted file mode 100644 index 855b51816..000000000 --- a/lib/symfony/http-foundation/RequestStack.php +++ /dev/null @@ -1,128 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException; -use Symfony\Component\HttpFoundation\Session\SessionInterface; - -/** - * Request stack that controls the lifecycle of requests. - * - * @author Benjamin Eberlei <kontakt@beberlei.de> - */ -class RequestStack -{ - /** - * @var Request[] - */ - private $requests = []; - - /** - * Pushes a Request on the stack. - * - * This method should generally not be called directly as the stack - * management should be taken care of by the application itself. - */ - public function push(Request $request) - { - $this->requests[] = $request; - } - - /** - * Pops the current request from the stack. - * - * This operation lets the current request go out of scope. - * - * This method should generally not be called directly as the stack - * management should be taken care of by the application itself. - * - * @return Request|null - */ - public function pop() - { - if (!$this->requests) { - return null; - } - - return array_pop($this->requests); - } - - /** - * @return Request|null - */ - public function getCurrentRequest() - { - return end($this->requests) ?: null; - } - - /** - * Gets the main request. - * - * Be warned that making your code aware of the main request - * might make it un-compatible with other features of your framework - * like ESI support. - */ - public function getMainRequest(): ?Request - { - if (!$this->requests) { - return null; - } - - return $this->requests[0]; - } - - /** - * Gets the master request. - * - * @return Request|null - * - * @deprecated since symfony/http-foundation 5.3, use getMainRequest() instead - */ - public function getMasterRequest() - { - trigger_deprecation('symfony/http-foundation', '5.3', '"%s()" is deprecated, use "getMainRequest()" instead.', __METHOD__); - - return $this->getMainRequest(); - } - - /** - * Returns the parent request of the current. - * - * Be warned that making your code aware of the parent request - * might make it un-compatible with other features of your framework - * like ESI support. - * - * If current Request is the main request, it returns null. - * - * @return Request|null - */ - public function getParentRequest() - { - $pos = \count($this->requests) - 2; - - return $this->requests[$pos] ?? null; - } - - /** - * Gets the current session. - * - * @throws SessionNotFoundException - */ - public function getSession(): SessionInterface - { - if ((null !== $request = end($this->requests) ?: null) && $request->hasSession()) { - return $request->getSession(); - } - - throw new SessionNotFoundException(); - } -} diff --git a/lib/symfony/http-foundation/Response.php b/lib/symfony/http-foundation/Response.php deleted file mode 100644 index d5c8cb45c..000000000 --- a/lib/symfony/http-foundation/Response.php +++ /dev/null @@ -1,1286 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -// Help opcache.preload discover always-needed symbols -class_exists(ResponseHeaderBag::class); - -/** - * Response represents an HTTP response. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Response -{ - public const HTTP_CONTINUE = 100; - public const HTTP_SWITCHING_PROTOCOLS = 101; - public const HTTP_PROCESSING = 102; // RFC2518 - public const HTTP_EARLY_HINTS = 103; // RFC8297 - public const HTTP_OK = 200; - public const HTTP_CREATED = 201; - public const HTTP_ACCEPTED = 202; - public const HTTP_NON_AUTHORITATIVE_INFORMATION = 203; - public const HTTP_NO_CONTENT = 204; - public const HTTP_RESET_CONTENT = 205; - public const HTTP_PARTIAL_CONTENT = 206; - public const HTTP_MULTI_STATUS = 207; // RFC4918 - public const HTTP_ALREADY_REPORTED = 208; // RFC5842 - public const HTTP_IM_USED = 226; // RFC3229 - public const HTTP_MULTIPLE_CHOICES = 300; - public const HTTP_MOVED_PERMANENTLY = 301; - public const HTTP_FOUND = 302; - public const HTTP_SEE_OTHER = 303; - public const HTTP_NOT_MODIFIED = 304; - public const HTTP_USE_PROXY = 305; - public const HTTP_RESERVED = 306; - public const HTTP_TEMPORARY_REDIRECT = 307; - public const HTTP_PERMANENTLY_REDIRECT = 308; // RFC7238 - public const HTTP_BAD_REQUEST = 400; - public const HTTP_UNAUTHORIZED = 401; - public const HTTP_PAYMENT_REQUIRED = 402; - public const HTTP_FORBIDDEN = 403; - public const HTTP_NOT_FOUND = 404; - public const HTTP_METHOD_NOT_ALLOWED = 405; - public const HTTP_NOT_ACCEPTABLE = 406; - public const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407; - public const HTTP_REQUEST_TIMEOUT = 408; - public const HTTP_CONFLICT = 409; - public const HTTP_GONE = 410; - public const HTTP_LENGTH_REQUIRED = 411; - public const HTTP_PRECONDITION_FAILED = 412; - public const HTTP_REQUEST_ENTITY_TOO_LARGE = 413; - public const HTTP_REQUEST_URI_TOO_LONG = 414; - public const HTTP_UNSUPPORTED_MEDIA_TYPE = 415; - public const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416; - public const HTTP_EXPECTATION_FAILED = 417; - public const HTTP_I_AM_A_TEAPOT = 418; // RFC2324 - public const HTTP_MISDIRECTED_REQUEST = 421; // RFC7540 - public const HTTP_UNPROCESSABLE_ENTITY = 422; // RFC4918 - public const HTTP_LOCKED = 423; // RFC4918 - public const HTTP_FAILED_DEPENDENCY = 424; // RFC4918 - public const HTTP_TOO_EARLY = 425; // RFC-ietf-httpbis-replay-04 - public const HTTP_UPGRADE_REQUIRED = 426; // RFC2817 - public const HTTP_PRECONDITION_REQUIRED = 428; // RFC6585 - public const HTTP_TOO_MANY_REQUESTS = 429; // RFC6585 - public const HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; // RFC6585 - public const HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451; // RFC7725 - public const HTTP_INTERNAL_SERVER_ERROR = 500; - public const HTTP_NOT_IMPLEMENTED = 501; - public const HTTP_BAD_GATEWAY = 502; - public const HTTP_SERVICE_UNAVAILABLE = 503; - public const HTTP_GATEWAY_TIMEOUT = 504; - public const HTTP_VERSION_NOT_SUPPORTED = 505; - public const HTTP_VARIANT_ALSO_NEGOTIATES_EXPERIMENTAL = 506; // RFC2295 - public const HTTP_INSUFFICIENT_STORAGE = 507; // RFC4918 - public const HTTP_LOOP_DETECTED = 508; // RFC5842 - public const HTTP_NOT_EXTENDED = 510; // RFC2774 - public const HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511; // RFC6585 - - /** - * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control - */ - private const HTTP_RESPONSE_CACHE_CONTROL_DIRECTIVES = [ - 'must_revalidate' => false, - 'no_cache' => false, - 'no_store' => false, - 'no_transform' => false, - 'public' => false, - 'private' => false, - 'proxy_revalidate' => false, - 'max_age' => true, - 's_maxage' => true, - 'immutable' => false, - 'last_modified' => true, - 'etag' => true, - ]; - - /** - * @var ResponseHeaderBag - */ - public $headers; - - /** - * @var string - */ - protected $content; - - /** - * @var string - */ - protected $version; - - /** - * @var int - */ - protected $statusCode; - - /** - * @var string - */ - protected $statusText; - - /** - * @var string - */ - protected $charset; - - /** - * Status codes translation table. - * - * The list of codes is complete according to the - * {@link https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml Hypertext Transfer Protocol (HTTP) Status Code Registry} - * (last updated 2021-10-01). - * - * Unless otherwise noted, the status code is defined in RFC2616. - * - * @var array - */ - public static $statusTexts = [ - 100 => 'Continue', - 101 => 'Switching Protocols', - 102 => 'Processing', // RFC2518 - 103 => 'Early Hints', - 200 => 'OK', - 201 => 'Created', - 202 => 'Accepted', - 203 => 'Non-Authoritative Information', - 204 => 'No Content', - 205 => 'Reset Content', - 206 => 'Partial Content', - 207 => 'Multi-Status', // RFC4918 - 208 => 'Already Reported', // RFC5842 - 226 => 'IM Used', // RFC3229 - 300 => 'Multiple Choices', - 301 => 'Moved Permanently', - 302 => 'Found', - 303 => 'See Other', - 304 => 'Not Modified', - 305 => 'Use Proxy', - 307 => 'Temporary Redirect', - 308 => 'Permanent Redirect', // RFC7238 - 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 Timeout', - 409 => 'Conflict', - 410 => 'Gone', - 411 => 'Length Required', - 412 => 'Precondition Failed', - 413 => 'Content Too Large', // RFC-ietf-httpbis-semantics - 414 => 'URI Too Long', - 415 => 'Unsupported Media Type', - 416 => 'Range Not Satisfiable', - 417 => 'Expectation Failed', - 418 => 'I\'m a teapot', // RFC2324 - 421 => 'Misdirected Request', // RFC7540 - 422 => 'Unprocessable Content', // RFC-ietf-httpbis-semantics - 423 => 'Locked', // RFC4918 - 424 => 'Failed Dependency', // RFC4918 - 425 => 'Too Early', // RFC-ietf-httpbis-replay-04 - 426 => 'Upgrade Required', // RFC2817 - 428 => 'Precondition Required', // RFC6585 - 429 => 'Too Many Requests', // RFC6585 - 431 => 'Request Header Fields Too Large', // RFC6585 - 451 => 'Unavailable For Legal Reasons', // RFC7725 - 500 => 'Internal Server Error', - 501 => 'Not Implemented', - 502 => 'Bad Gateway', - 503 => 'Service Unavailable', - 504 => 'Gateway Timeout', - 505 => 'HTTP Version Not Supported', - 506 => 'Variant Also Negotiates', // RFC2295 - 507 => 'Insufficient Storage', // RFC4918 - 508 => 'Loop Detected', // RFC5842 - 510 => 'Not Extended', // RFC2774 - 511 => 'Network Authentication Required', // RFC6585 - ]; - - /** - * @throws \InvalidArgumentException When the HTTP status code is not valid - */ - public function __construct(?string $content = '', int $status = 200, array $headers = []) - { - $this->headers = new ResponseHeaderBag($headers); - $this->setContent($content); - $this->setStatusCode($status); - $this->setProtocolVersion('1.0'); - } - - /** - * Factory method for chainability. - * - * Example: - * - * return Response::create($body, 200) - * ->setSharedMaxAge(300); - * - * @return static - * - * @deprecated since Symfony 5.1, use __construct() instead. - */ - public static function create(?string $content = '', int $status = 200, array $headers = []) - { - trigger_deprecation('symfony/http-foundation', '5.1', 'The "%s()" method is deprecated, use "new %s()" instead.', __METHOD__, static::class); - - return new static($content, $status, $headers); - } - - /** - * Returns the Response as an HTTP string. - * - * The string representation of the Response is the same as the - * one that will be sent to the client only if the prepare() method - * has been called before. - * - * @return string - * - * @see prepare() - */ - public function __toString() - { - return - sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText)."\r\n". - $this->headers."\r\n". - $this->getContent(); - } - - /** - * Clones the current Response instance. - */ - public function __clone() - { - $this->headers = clone $this->headers; - } - - /** - * Prepares the Response before it is sent to the client. - * - * This method tweaks the Response to ensure that it is - * compliant with RFC 2616. Most of the changes are based on - * the Request that is "associated" with this Response. - * - * @return $this - */ - public function prepare(Request $request) - { - $headers = $this->headers; - - if ($this->isInformational() || $this->isEmpty()) { - $this->setContent(null); - $headers->remove('Content-Type'); - $headers->remove('Content-Length'); - // prevent PHP from sending the Content-Type header based on default_mimetype - ini_set('default_mimetype', ''); - } else { - // Content-type based on the Request - if (!$headers->has('Content-Type')) { - $format = $request->getRequestFormat(null); - if (null !== $format && $mimeType = $request->getMimeType($format)) { - $headers->set('Content-Type', $mimeType); - } - } - - // Fix Content-Type - $charset = $this->charset ?: 'UTF-8'; - if (!$headers->has('Content-Type')) { - $headers->set('Content-Type', 'text/html; charset='.$charset); - } elseif (0 === stripos($headers->get('Content-Type'), 'text/') && false === stripos($headers->get('Content-Type'), 'charset')) { - // add the charset - $headers->set('Content-Type', $headers->get('Content-Type').'; charset='.$charset); - } - - // Fix Content-Length - if ($headers->has('Transfer-Encoding')) { - $headers->remove('Content-Length'); - } - - if ($request->isMethod('HEAD')) { - // cf. RFC2616 14.13 - $length = $headers->get('Content-Length'); - $this->setContent(null); - if ($length) { - $headers->set('Content-Length', $length); - } - } - } - - // Fix protocol - if ('HTTP/1.0' != $request->server->get('SERVER_PROTOCOL')) { - $this->setProtocolVersion('1.1'); - } - - // Check if we need to send extra expire info headers - if ('1.0' == $this->getProtocolVersion() && str_contains($headers->get('Cache-Control', ''), 'no-cache')) { - $headers->set('pragma', 'no-cache'); - $headers->set('expires', -1); - } - - $this->ensureIEOverSSLCompatibility($request); - - if ($request->isSecure()) { - foreach ($headers->getCookies() as $cookie) { - $cookie->setSecureDefault(true); - } - } - - return $this; - } - - /** - * Sends HTTP headers. - * - * @return $this - */ - public function sendHeaders() - { - // headers have already been sent by the developer - if (headers_sent()) { - return $this; - } - - // headers - foreach ($this->headers->allPreserveCaseWithoutCookies() as $name => $values) { - $replace = 0 === strcasecmp($name, 'Content-Type'); - foreach ($values as $value) { - header($name.': '.$value, $replace, $this->statusCode); - } - } - - // cookies - foreach ($this->headers->getCookies() as $cookie) { - header('Set-Cookie: '.$cookie, false, $this->statusCode); - } - - // status - header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText), true, $this->statusCode); - - return $this; - } - - /** - * Sends content for the current web response. - * - * @return $this - */ - public function sendContent() - { - echo $this->content; - - return $this; - } - - /** - * Sends HTTP headers and content. - * - * @return $this - */ - public function send() - { - $this->sendHeaders(); - $this->sendContent(); - - if (\function_exists('fastcgi_finish_request')) { - fastcgi_finish_request(); - } elseif (\function_exists('litespeed_finish_request')) { - litespeed_finish_request(); - } elseif (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { - static::closeOutputBuffers(0, true); - flush(); - } - - return $this; - } - - /** - * Sets the response content. - * - * @return $this - */ - public function setContent(?string $content) - { - $this->content = $content ?? ''; - - return $this; - } - - /** - * Gets the current response content. - * - * @return string|false - */ - public function getContent() - { - return $this->content; - } - - /** - * Sets the HTTP protocol version (1.0 or 1.1). - * - * @return $this - * - * @final - */ - public function setProtocolVersion(string $version): object - { - $this->version = $version; - - return $this; - } - - /** - * Gets the HTTP protocol version. - * - * @final - */ - public function getProtocolVersion(): string - { - return $this->version; - } - - /** - * Sets the response status code. - * - * If the status text is null it will be automatically populated for the known - * status codes and left empty otherwise. - * - * @return $this - * - * @throws \InvalidArgumentException When the HTTP status code is not valid - * - * @final - */ - public function setStatusCode(int $code, string $text = null): object - { - $this->statusCode = $code; - if ($this->isInvalid()) { - throw new \InvalidArgumentException(sprintf('The HTTP status code "%s" is not valid.', $code)); - } - - if (null === $text) { - $this->statusText = self::$statusTexts[$code] ?? 'unknown status'; - - return $this; - } - - if (false === $text) { - $this->statusText = ''; - - return $this; - } - - $this->statusText = $text; - - return $this; - } - - /** - * Retrieves the status code for the current web response. - * - * @final - */ - public function getStatusCode(): int - { - return $this->statusCode; - } - - /** - * Sets the response charset. - * - * @return $this - * - * @final - */ - public function setCharset(string $charset): object - { - $this->charset = $charset; - - return $this; - } - - /** - * Retrieves the response charset. - * - * @final - */ - public function getCharset(): ?string - { - return $this->charset; - } - - /** - * Returns true if the response may safely be kept in a shared (surrogate) cache. - * - * Responses marked "private" with an explicit Cache-Control directive are - * considered uncacheable. - * - * Responses with neither a freshness lifetime (Expires, max-age) nor cache - * validator (Last-Modified, ETag) are considered uncacheable because there is - * no way to tell when or how to remove them from the cache. - * - * Note that RFC 7231 and RFC 7234 possibly allow for a more permissive implementation, - * for example "status codes that are defined as cacheable by default [...] - * can be reused by a cache with heuristic expiration unless otherwise indicated" - * (https://tools.ietf.org/html/rfc7231#section-6.1) - * - * @final - */ - public function isCacheable(): bool - { - if (!\in_array($this->statusCode, [200, 203, 300, 301, 302, 404, 410])) { - return false; - } - - if ($this->headers->hasCacheControlDirective('no-store') || $this->headers->getCacheControlDirective('private')) { - return false; - } - - return $this->isValidateable() || $this->isFresh(); - } - - /** - * Returns true if the response is "fresh". - * - * Fresh responses may be served from cache without any interaction with the - * origin. A response is considered fresh when it includes a Cache-Control/max-age - * indicator or Expires header and the calculated age is less than the freshness lifetime. - * - * @final - */ - public function isFresh(): bool - { - return $this->getTtl() > 0; - } - - /** - * Returns true if the response includes headers that can be used to validate - * the response with the origin server using a conditional GET request. - * - * @final - */ - public function isValidateable(): bool - { - return $this->headers->has('Last-Modified') || $this->headers->has('ETag'); - } - - /** - * Marks the response as "private". - * - * It makes the response ineligible for serving other clients. - * - * @return $this - * - * @final - */ - public function setPrivate(): object - { - $this->headers->removeCacheControlDirective('public'); - $this->headers->addCacheControlDirective('private'); - - return $this; - } - - /** - * Marks the response as "public". - * - * It makes the response eligible for serving other clients. - * - * @return $this - * - * @final - */ - public function setPublic(): object - { - $this->headers->addCacheControlDirective('public'); - $this->headers->removeCacheControlDirective('private'); - - return $this; - } - - /** - * Marks the response as "immutable". - * - * @return $this - * - * @final - */ - public function setImmutable(bool $immutable = true): object - { - if ($immutable) { - $this->headers->addCacheControlDirective('immutable'); - } else { - $this->headers->removeCacheControlDirective('immutable'); - } - - return $this; - } - - /** - * Returns true if the response is marked as "immutable". - * - * @final - */ - public function isImmutable(): bool - { - return $this->headers->hasCacheControlDirective('immutable'); - } - - /** - * Returns true if the response must be revalidated by shared caches once it has become stale. - * - * This method indicates that the response must not be served stale by a - * cache in any circumstance without first revalidating with the origin. - * When present, the TTL of the response should not be overridden to be - * greater than the value provided by the origin. - * - * @final - */ - public function mustRevalidate(): bool - { - return $this->headers->hasCacheControlDirective('must-revalidate') || $this->headers->hasCacheControlDirective('proxy-revalidate'); - } - - /** - * Returns the Date header as a DateTime instance. - * - * @throws \RuntimeException When the header is not parseable - * - * @final - */ - public function getDate(): ?\DateTimeInterface - { - return $this->headers->getDate('Date'); - } - - /** - * Sets the Date header. - * - * @return $this - * - * @final - */ - public function setDate(\DateTimeInterface $date): object - { - if ($date instanceof \DateTime) { - $date = \DateTimeImmutable::createFromMutable($date); - } - - $date = $date->setTimezone(new \DateTimeZone('UTC')); - $this->headers->set('Date', $date->format('D, d M Y H:i:s').' GMT'); - - return $this; - } - - /** - * Returns the age of the response in seconds. - * - * @final - */ - public function getAge(): int - { - if (null !== $age = $this->headers->get('Age')) { - return (int) $age; - } - - return max(time() - (int) $this->getDate()->format('U'), 0); - } - - /** - * Marks the response stale by setting the Age header to be equal to the maximum age of the response. - * - * @return $this - */ - public function expire() - { - if ($this->isFresh()) { - $this->headers->set('Age', $this->getMaxAge()); - $this->headers->remove('Expires'); - } - - return $this; - } - - /** - * Returns the value of the Expires header as a DateTime instance. - * - * @final - */ - public function getExpires(): ?\DateTimeInterface - { - try { - return $this->headers->getDate('Expires'); - } catch (\RuntimeException $e) { - // according to RFC 2616 invalid date formats (e.g. "0" and "-1") must be treated as in the past - return \DateTime::createFromFormat('U', time() - 172800); - } - } - - /** - * Sets the Expires HTTP header with a DateTime instance. - * - * Passing null as value will remove the header. - * - * @return $this - * - * @final - */ - public function setExpires(\DateTimeInterface $date = null): object - { - if (null === $date) { - $this->headers->remove('Expires'); - - return $this; - } - - if ($date instanceof \DateTime) { - $date = \DateTimeImmutable::createFromMutable($date); - } - - $date = $date->setTimezone(new \DateTimeZone('UTC')); - $this->headers->set('Expires', $date->format('D, d M Y H:i:s').' GMT'); - - return $this; - } - - /** - * Returns the number of seconds after the time specified in the response's Date - * header when the response should no longer be considered fresh. - * - * First, it checks for a s-maxage directive, then a max-age directive, and then it falls - * back on an expires header. It returns null when no maximum age can be established. - * - * @final - */ - public function getMaxAge(): ?int - { - if ($this->headers->hasCacheControlDirective('s-maxage')) { - return (int) $this->headers->getCacheControlDirective('s-maxage'); - } - - if ($this->headers->hasCacheControlDirective('max-age')) { - return (int) $this->headers->getCacheControlDirective('max-age'); - } - - if (null !== $this->getExpires()) { - return (int) $this->getExpires()->format('U') - (int) $this->getDate()->format('U'); - } - - return null; - } - - /** - * Sets the number of seconds after which the response should no longer be considered fresh. - * - * This methods sets the Cache-Control max-age directive. - * - * @return $this - * - * @final - */ - public function setMaxAge(int $value): object - { - $this->headers->addCacheControlDirective('max-age', $value); - - return $this; - } - - /** - * Sets the number of seconds after which the response should no longer be considered fresh by shared caches. - * - * This methods sets the Cache-Control s-maxage directive. - * - * @return $this - * - * @final - */ - public function setSharedMaxAge(int $value): object - { - $this->setPublic(); - $this->headers->addCacheControlDirective('s-maxage', $value); - - return $this; - } - - /** - * Returns the response's time-to-live in seconds. - * - * It returns null when no freshness information is present in the response. - * - * When the responses TTL is <= 0, the response may not be served from cache without first - * revalidating with the origin. - * - * @final - */ - public function getTtl(): ?int - { - $maxAge = $this->getMaxAge(); - - return null !== $maxAge ? $maxAge - $this->getAge() : null; - } - - /** - * Sets the response's time-to-live for shared caches in seconds. - * - * This method adjusts the Cache-Control/s-maxage directive. - * - * @return $this - * - * @final - */ - public function setTtl(int $seconds): object - { - $this->setSharedMaxAge($this->getAge() + $seconds); - - return $this; - } - - /** - * Sets the response's time-to-live for private/client caches in seconds. - * - * This method adjusts the Cache-Control/max-age directive. - * - * @return $this - * - * @final - */ - public function setClientTtl(int $seconds): object - { - $this->setMaxAge($this->getAge() + $seconds); - - return $this; - } - - /** - * Returns the Last-Modified HTTP header as a DateTime instance. - * - * @throws \RuntimeException When the HTTP header is not parseable - * - * @final - */ - public function getLastModified(): ?\DateTimeInterface - { - return $this->headers->getDate('Last-Modified'); - } - - /** - * Sets the Last-Modified HTTP header with a DateTime instance. - * - * Passing null as value will remove the header. - * - * @return $this - * - * @final - */ - public function setLastModified(\DateTimeInterface $date = null): object - { - if (null === $date) { - $this->headers->remove('Last-Modified'); - - return $this; - } - - if ($date instanceof \DateTime) { - $date = \DateTimeImmutable::createFromMutable($date); - } - - $date = $date->setTimezone(new \DateTimeZone('UTC')); - $this->headers->set('Last-Modified', $date->format('D, d M Y H:i:s').' GMT'); - - return $this; - } - - /** - * Returns the literal value of the ETag HTTP header. - * - * @final - */ - public function getEtag(): ?string - { - return $this->headers->get('ETag'); - } - - /** - * Sets the ETag value. - * - * @param string|null $etag The ETag unique identifier or null to remove the header - * @param bool $weak Whether you want a weak ETag or not - * - * @return $this - * - * @final - */ - public function setEtag(string $etag = null, bool $weak = false): object - { - if (null === $etag) { - $this->headers->remove('Etag'); - } else { - if (!str_starts_with($etag, '"')) { - $etag = '"'.$etag.'"'; - } - - $this->headers->set('ETag', (true === $weak ? 'W/' : '').$etag); - } - - return $this; - } - - /** - * Sets the response's cache headers (validation and/or expiration). - * - * Available options are: must_revalidate, no_cache, no_store, no_transform, public, private, proxy_revalidate, max_age, s_maxage, immutable, last_modified and etag. - * - * @return $this - * - * @throws \InvalidArgumentException - * - * @final - */ - public function setCache(array $options): object - { - if ($diff = array_diff(array_keys($options), array_keys(self::HTTP_RESPONSE_CACHE_CONTROL_DIRECTIVES))) { - throw new \InvalidArgumentException(sprintf('Response does not support the following options: "%s".', implode('", "', $diff))); - } - - if (isset($options['etag'])) { - $this->setEtag($options['etag']); - } - - if (isset($options['last_modified'])) { - $this->setLastModified($options['last_modified']); - } - - if (isset($options['max_age'])) { - $this->setMaxAge($options['max_age']); - } - - if (isset($options['s_maxage'])) { - $this->setSharedMaxAge($options['s_maxage']); - } - - foreach (self::HTTP_RESPONSE_CACHE_CONTROL_DIRECTIVES as $directive => $hasValue) { - if (!$hasValue && isset($options[$directive])) { - if ($options[$directive]) { - $this->headers->addCacheControlDirective(str_replace('_', '-', $directive)); - } else { - $this->headers->removeCacheControlDirective(str_replace('_', '-', $directive)); - } - } - } - - if (isset($options['public'])) { - if ($options['public']) { - $this->setPublic(); - } else { - $this->setPrivate(); - } - } - - if (isset($options['private'])) { - if ($options['private']) { - $this->setPrivate(); - } else { - $this->setPublic(); - } - } - - return $this; - } - - /** - * Modifies the response so that it conforms to the rules defined for a 304 status code. - * - * This sets the status, removes the body, and discards any headers - * that MUST NOT be included in 304 responses. - * - * @return $this - * - * @see https://tools.ietf.org/html/rfc2616#section-10.3.5 - * - * @final - */ - public function setNotModified(): object - { - $this->setStatusCode(304); - $this->setContent(null); - - // remove headers that MUST NOT be included with 304 Not Modified responses - foreach (['Allow', 'Content-Encoding', 'Content-Language', 'Content-Length', 'Content-MD5', 'Content-Type', 'Last-Modified'] as $header) { - $this->headers->remove($header); - } - - return $this; - } - - /** - * Returns true if the response includes a Vary header. - * - * @final - */ - public function hasVary(): bool - { - return null !== $this->headers->get('Vary'); - } - - /** - * Returns an array of header names given in the Vary header. - * - * @final - */ - public function getVary(): array - { - if (!$vary = $this->headers->all('Vary')) { - return []; - } - - $ret = []; - foreach ($vary as $item) { - $ret[] = preg_split('/[\s,]+/', $item); - } - - return array_merge([], ...$ret); - } - - /** - * Sets the Vary header. - * - * @param string|array $headers - * @param bool $replace Whether to replace the actual value or not (true by default) - * - * @return $this - * - * @final - */ - public function setVary($headers, bool $replace = true): object - { - $this->headers->set('Vary', $headers, $replace); - - return $this; - } - - /** - * Determines if the Response validators (ETag, Last-Modified) match - * a conditional value specified in the Request. - * - * If the Response is not modified, it sets the status code to 304 and - * removes the actual content by calling the setNotModified() method. - * - * @final - */ - public function isNotModified(Request $request): bool - { - if (!$request->isMethodCacheable()) { - return false; - } - - $notModified = false; - $lastModified = $this->headers->get('Last-Modified'); - $modifiedSince = $request->headers->get('If-Modified-Since'); - - if (($ifNoneMatchEtags = $request->getETags()) && (null !== $etag = $this->getEtag())) { - if (0 == strncmp($etag, 'W/', 2)) { - $etag = substr($etag, 2); - } - - // Use weak comparison as per https://tools.ietf.org/html/rfc7232#section-3.2. - foreach ($ifNoneMatchEtags as $ifNoneMatchEtag) { - if (0 == strncmp($ifNoneMatchEtag, 'W/', 2)) { - $ifNoneMatchEtag = substr($ifNoneMatchEtag, 2); - } - - if ($ifNoneMatchEtag === $etag || '*' === $ifNoneMatchEtag) { - $notModified = true; - break; - } - } - } - // Only do If-Modified-Since date comparison when If-None-Match is not present as per https://tools.ietf.org/html/rfc7232#section-3.3. - elseif ($modifiedSince && $lastModified) { - $notModified = strtotime($modifiedSince) >= strtotime($lastModified); - } - - if ($notModified) { - $this->setNotModified(); - } - - return $notModified; - } - - /** - * Is response invalid? - * - * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html - * - * @final - */ - public function isInvalid(): bool - { - return $this->statusCode < 100 || $this->statusCode >= 600; - } - - /** - * Is response informative? - * - * @final - */ - public function isInformational(): bool - { - return $this->statusCode >= 100 && $this->statusCode < 200; - } - - /** - * Is response successful? - * - * @final - */ - public function isSuccessful(): bool - { - return $this->statusCode >= 200 && $this->statusCode < 300; - } - - /** - * Is the response a redirect? - * - * @final - */ - public function isRedirection(): bool - { - return $this->statusCode >= 300 && $this->statusCode < 400; - } - - /** - * Is there a client error? - * - * @final - */ - public function isClientError(): bool - { - return $this->statusCode >= 400 && $this->statusCode < 500; - } - - /** - * Was there a server side error? - * - * @final - */ - public function isServerError(): bool - { - return $this->statusCode >= 500 && $this->statusCode < 600; - } - - /** - * Is the response OK? - * - * @final - */ - public function isOk(): bool - { - return 200 === $this->statusCode; - } - - /** - * Is the response forbidden? - * - * @final - */ - public function isForbidden(): bool - { - return 403 === $this->statusCode; - } - - /** - * Is the response a not found error? - * - * @final - */ - public function isNotFound(): bool - { - return 404 === $this->statusCode; - } - - /** - * Is the response a redirect of some form? - * - * @final - */ - public function isRedirect(string $location = null): bool - { - return \in_array($this->statusCode, [201, 301, 302, 303, 307, 308]) && (null === $location ?: $location == $this->headers->get('Location')); - } - - /** - * Is the response empty? - * - * @final - */ - public function isEmpty(): bool - { - return \in_array($this->statusCode, [204, 304]); - } - - /** - * Cleans or flushes output buffers up to target level. - * - * Resulting level can be greater than target level if a non-removable buffer has been encountered. - * - * @final - */ - public static function closeOutputBuffers(int $targetLevel, bool $flush): void - { - $status = ob_get_status(true); - $level = \count($status); - $flags = \PHP_OUTPUT_HANDLER_REMOVABLE | ($flush ? \PHP_OUTPUT_HANDLER_FLUSHABLE : \PHP_OUTPUT_HANDLER_CLEANABLE); - - while ($level-- > $targetLevel && ($s = $status[$level]) && (!isset($s['del']) ? !isset($s['flags']) || ($s['flags'] & $flags) === $flags : $s['del'])) { - if ($flush) { - ob_end_flush(); - } else { - ob_end_clean(); - } - } - } - - /** - * Marks a response as safe according to RFC8674. - * - * @see https://tools.ietf.org/html/rfc8674 - */ - public function setContentSafe(bool $safe = true): void - { - if ($safe) { - $this->headers->set('Preference-Applied', 'safe'); - } elseif ('safe' === $this->headers->get('Preference-Applied')) { - $this->headers->remove('Preference-Applied'); - } - - $this->setVary('Prefer', false); - } - - /** - * Checks if we need to remove Cache-Control for SSL encrypted downloads when using IE < 9. - * - * @see http://support.microsoft.com/kb/323308 - * - * @final - */ - protected function ensureIEOverSSLCompatibility(Request $request): void - { - if (false !== stripos($this->headers->get('Content-Disposition') ?? '', 'attachment') && 1 == preg_match('/MSIE (.*?);/i', $request->server->get('HTTP_USER_AGENT') ?? '', $match) && true === $request->isSecure()) { - if ((int) preg_replace('/(MSIE )(.*?);/', '$2', $match[0]) < 9) { - $this->headers->remove('Cache-Control'); - } - } - } -} diff --git a/lib/symfony/http-foundation/ResponseHeaderBag.php b/lib/symfony/http-foundation/ResponseHeaderBag.php deleted file mode 100644 index 1df13fa21..000000000 --- a/lib/symfony/http-foundation/ResponseHeaderBag.php +++ /dev/null @@ -1,291 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * ResponseHeaderBag is a container for Response HTTP headers. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class ResponseHeaderBag extends HeaderBag -{ - public const COOKIES_FLAT = 'flat'; - public const COOKIES_ARRAY = 'array'; - - public const DISPOSITION_ATTACHMENT = 'attachment'; - public const DISPOSITION_INLINE = 'inline'; - - protected $computedCacheControl = []; - protected $cookies = []; - protected $headerNames = []; - - public function __construct(array $headers = []) - { - parent::__construct($headers); - - if (!isset($this->headers['cache-control'])) { - $this->set('Cache-Control', ''); - } - - /* RFC2616 - 14.18 says all Responses need to have a Date */ - if (!isset($this->headers['date'])) { - $this->initDate(); - } - } - - /** - * Returns the headers, with original capitalizations. - * - * @return array - */ - public function allPreserveCase() - { - $headers = []; - foreach ($this->all() as $name => $value) { - $headers[$this->headerNames[$name] ?? $name] = $value; - } - - return $headers; - } - - public function allPreserveCaseWithoutCookies() - { - $headers = $this->allPreserveCase(); - if (isset($this->headerNames['set-cookie'])) { - unset($headers[$this->headerNames['set-cookie']]); - } - - return $headers; - } - - /** - * {@inheritdoc} - */ - public function replace(array $headers = []) - { - $this->headerNames = []; - - parent::replace($headers); - - if (!isset($this->headers['cache-control'])) { - $this->set('Cache-Control', ''); - } - - if (!isset($this->headers['date'])) { - $this->initDate(); - } - } - - /** - * {@inheritdoc} - */ - public function all(string $key = null) - { - $headers = parent::all(); - - if (null !== $key) { - $key = strtr($key, self::UPPER, self::LOWER); - - return 'set-cookie' !== $key ? $headers[$key] ?? [] : array_map('strval', $this->getCookies()); - } - - foreach ($this->getCookies() as $cookie) { - $headers['set-cookie'][] = (string) $cookie; - } - - return $headers; - } - - /** - * {@inheritdoc} - */ - public function set(string $key, $values, bool $replace = true) - { - $uniqueKey = strtr($key, self::UPPER, self::LOWER); - - if ('set-cookie' === $uniqueKey) { - if ($replace) { - $this->cookies = []; - } - foreach ((array) $values as $cookie) { - $this->setCookie(Cookie::fromString($cookie)); - } - $this->headerNames[$uniqueKey] = $key; - - return; - } - - $this->headerNames[$uniqueKey] = $key; - - parent::set($key, $values, $replace); - - // ensure the cache-control header has sensible defaults - if (\in_array($uniqueKey, ['cache-control', 'etag', 'last-modified', 'expires'], true) && '' !== $computed = $this->computeCacheControlValue()) { - $this->headers['cache-control'] = [$computed]; - $this->headerNames['cache-control'] = 'Cache-Control'; - $this->computedCacheControl = $this->parseCacheControl($computed); - } - } - - /** - * {@inheritdoc} - */ - public function remove(string $key) - { - $uniqueKey = strtr($key, self::UPPER, self::LOWER); - unset($this->headerNames[$uniqueKey]); - - if ('set-cookie' === $uniqueKey) { - $this->cookies = []; - - return; - } - - parent::remove($key); - - if ('cache-control' === $uniqueKey) { - $this->computedCacheControl = []; - } - - if ('date' === $uniqueKey) { - $this->initDate(); - } - } - - /** - * {@inheritdoc} - */ - public function hasCacheControlDirective(string $key) - { - return \array_key_exists($key, $this->computedCacheControl); - } - - /** - * {@inheritdoc} - */ - public function getCacheControlDirective(string $key) - { - return $this->computedCacheControl[$key] ?? null; - } - - public function setCookie(Cookie $cookie) - { - $this->cookies[$cookie->getDomain()][$cookie->getPath()][$cookie->getName()] = $cookie; - $this->headerNames['set-cookie'] = 'Set-Cookie'; - } - - /** - * Removes a cookie from the array, but does not unset it in the browser. - */ - public function removeCookie(string $name, ?string $path = '/', string $domain = null) - { - if (null === $path) { - $path = '/'; - } - - unset($this->cookies[$domain][$path][$name]); - - if (empty($this->cookies[$domain][$path])) { - unset($this->cookies[$domain][$path]); - - if (empty($this->cookies[$domain])) { - unset($this->cookies[$domain]); - } - } - - if (empty($this->cookies)) { - unset($this->headerNames['set-cookie']); - } - } - - /** - * Returns an array with all cookies. - * - * @return Cookie[] - * - * @throws \InvalidArgumentException When the $format is invalid - */ - public function getCookies(string $format = self::COOKIES_FLAT) - { - if (!\in_array($format, [self::COOKIES_FLAT, self::COOKIES_ARRAY])) { - throw new \InvalidArgumentException(sprintf('Format "%s" invalid (%s).', $format, implode(', ', [self::COOKIES_FLAT, self::COOKIES_ARRAY]))); - } - - if (self::COOKIES_ARRAY === $format) { - return $this->cookies; - } - - $flattenedCookies = []; - foreach ($this->cookies as $path) { - foreach ($path as $cookies) { - foreach ($cookies as $cookie) { - $flattenedCookies[] = $cookie; - } - } - } - - return $flattenedCookies; - } - - /** - * Clears a cookie in the browser. - */ - public function clearCookie(string $name, ?string $path = '/', string $domain = null, bool $secure = false, bool $httpOnly = true, string $sameSite = null) - { - $this->setCookie(new Cookie($name, null, 1, $path, $domain, $secure, $httpOnly, false, $sameSite)); - } - - /** - * @see HeaderUtils::makeDisposition() - */ - public function makeDisposition(string $disposition, string $filename, string $filenameFallback = '') - { - return HeaderUtils::makeDisposition($disposition, $filename, $filenameFallback); - } - - /** - * Returns the calculated value of the cache-control header. - * - * This considers several other headers and calculates or modifies the - * cache-control header to a sensible, conservative value. - * - * @return string - */ - protected function computeCacheControlValue() - { - if (!$this->cacheControl) { - if ($this->has('Last-Modified') || $this->has('Expires')) { - return 'private, must-revalidate'; // allows for heuristic expiration (RFC 7234 Section 4.2.2) in the case of "Last-Modified" - } - - // conservative by default - return 'no-cache, private'; - } - - $header = $this->getCacheControlHeader(); - if (isset($this->cacheControl['public']) || isset($this->cacheControl['private'])) { - return $header; - } - - // public if s-maxage is defined, private otherwise - if (!isset($this->cacheControl['s-maxage'])) { - return $header.', private'; - } - - return $header; - } - - private function initDate(): void - { - $this->set('Date', gmdate('D, d M Y H:i:s').' GMT'); - } -} diff --git a/lib/symfony/http-foundation/ServerBag.php b/lib/symfony/http-foundation/ServerBag.php deleted file mode 100644 index 25688d523..000000000 --- a/lib/symfony/http-foundation/ServerBag.php +++ /dev/null @@ -1,99 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * ServerBag is a container for HTTP headers from the $_SERVER variable. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Bulat Shakirzyanov <mallluhuct@gmail.com> - * @author Robert Kiss <kepten@gmail.com> - */ -class ServerBag extends ParameterBag -{ - /** - * Gets the HTTP headers. - * - * @return array - */ - public function getHeaders() - { - $headers = []; - foreach ($this->parameters as $key => $value) { - if (str_starts_with($key, 'HTTP_')) { - $headers[substr($key, 5)] = $value; - } elseif (\in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH', 'CONTENT_MD5'], true)) { - $headers[$key] = $value; - } - } - - if (isset($this->parameters['PHP_AUTH_USER'])) { - $headers['PHP_AUTH_USER'] = $this->parameters['PHP_AUTH_USER']; - $headers['PHP_AUTH_PW'] = $this->parameters['PHP_AUTH_PW'] ?? ''; - } else { - /* - * php-cgi under Apache does not pass HTTP Basic user/pass to PHP by default - * For this workaround to work, add these lines to your .htaccess file: - * RewriteCond %{HTTP:Authorization} .+ - * RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0] - * - * A sample .htaccess file: - * RewriteEngine On - * RewriteCond %{HTTP:Authorization} .+ - * RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0] - * RewriteCond %{REQUEST_FILENAME} !-f - * RewriteRule ^(.*)$ app.php [QSA,L] - */ - - $authorizationHeader = null; - if (isset($this->parameters['HTTP_AUTHORIZATION'])) { - $authorizationHeader = $this->parameters['HTTP_AUTHORIZATION']; - } elseif (isset($this->parameters['REDIRECT_HTTP_AUTHORIZATION'])) { - $authorizationHeader = $this->parameters['REDIRECT_HTTP_AUTHORIZATION']; - } - - if (null !== $authorizationHeader) { - if (0 === stripos($authorizationHeader, 'basic ')) { - // Decode AUTHORIZATION header into PHP_AUTH_USER and PHP_AUTH_PW when authorization header is basic - $exploded = explode(':', base64_decode(substr($authorizationHeader, 6)), 2); - if (2 == \count($exploded)) { - [$headers['PHP_AUTH_USER'], $headers['PHP_AUTH_PW']] = $exploded; - } - } elseif (empty($this->parameters['PHP_AUTH_DIGEST']) && (0 === stripos($authorizationHeader, 'digest '))) { - // In some circumstances PHP_AUTH_DIGEST needs to be set - $headers['PHP_AUTH_DIGEST'] = $authorizationHeader; - $this->parameters['PHP_AUTH_DIGEST'] = $authorizationHeader; - } elseif (0 === stripos($authorizationHeader, 'bearer ')) { - /* - * XXX: Since there is no PHP_AUTH_BEARER in PHP predefined variables, - * I'll just set $headers['AUTHORIZATION'] here. - * https://php.net/reserved.variables.server - */ - $headers['AUTHORIZATION'] = $authorizationHeader; - } - } - } - - if (isset($headers['AUTHORIZATION'])) { - return $headers; - } - - // PHP_AUTH_USER/PHP_AUTH_PW - if (isset($headers['PHP_AUTH_USER'])) { - $headers['AUTHORIZATION'] = 'Basic '.base64_encode($headers['PHP_AUTH_USER'].':'.($headers['PHP_AUTH_PW'] ?? '')); - } elseif (isset($headers['PHP_AUTH_DIGEST'])) { - $headers['AUTHORIZATION'] = $headers['PHP_AUTH_DIGEST']; - } - - return $headers; - } -} diff --git a/lib/symfony/http-foundation/Session/Attribute/AttributeBag.php b/lib/symfony/http-foundation/Session/Attribute/AttributeBag.php deleted file mode 100644 index f4f051c7a..000000000 --- a/lib/symfony/http-foundation/Session/Attribute/AttributeBag.php +++ /dev/null @@ -1,152 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Attribute; - -/** - * This class relates to session attribute storage. - * - * @implements \IteratorAggregate<string, mixed> - */ -class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Countable -{ - private $name = 'attributes'; - private $storageKey; - - protected $attributes = []; - - /** - * @param string $storageKey The key used to store attributes in the session - */ - public function __construct(string $storageKey = '_sf2_attributes') - { - $this->storageKey = $storageKey; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->name; - } - - public function setName(string $name) - { - $this->name = $name; - } - - /** - * {@inheritdoc} - */ - public function initialize(array &$attributes) - { - $this->attributes = &$attributes; - } - - /** - * {@inheritdoc} - */ - public function getStorageKey() - { - return $this->storageKey; - } - - /** - * {@inheritdoc} - */ - public function has(string $name) - { - return \array_key_exists($name, $this->attributes); - } - - /** - * {@inheritdoc} - */ - public function get(string $name, $default = null) - { - return \array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; - } - - /** - * {@inheritdoc} - */ - public function set(string $name, $value) - { - $this->attributes[$name] = $value; - } - - /** - * {@inheritdoc} - */ - public function all() - { - return $this->attributes; - } - - /** - * {@inheritdoc} - */ - public function replace(array $attributes) - { - $this->attributes = []; - foreach ($attributes as $key => $value) { - $this->set($key, $value); - } - } - - /** - * {@inheritdoc} - */ - public function remove(string $name) - { - $retval = null; - if (\array_key_exists($name, $this->attributes)) { - $retval = $this->attributes[$name]; - unset($this->attributes[$name]); - } - - return $retval; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - $return = $this->attributes; - $this->attributes = []; - - return $return; - } - - /** - * Returns an iterator for attributes. - * - * @return \ArrayIterator<string, mixed> - */ - #[\ReturnTypeWillChange] - public function getIterator() - { - return new \ArrayIterator($this->attributes); - } - - /** - * Returns the number of attributes. - * - * @return int - */ - #[\ReturnTypeWillChange] - public function count() - { - return \count($this->attributes); - } -} diff --git a/lib/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php b/lib/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php deleted file mode 100644 index cb5069681..000000000 --- a/lib/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php +++ /dev/null @@ -1,61 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Attribute; - -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; - -/** - * Attributes store. - * - * @author Drak <drak@zikula.org> - */ -interface AttributeBagInterface extends SessionBagInterface -{ - /** - * Checks if an attribute is defined. - * - * @return bool - */ - public function has(string $name); - - /** - * Returns an attribute. - * - * @param mixed $default The default value if not found - * - * @return mixed - */ - public function get(string $name, $default = null); - - /** - * Sets an attribute. - * - * @param mixed $value - */ - public function set(string $name, $value); - - /** - * Returns attributes. - * - * @return array<string, mixed> - */ - public function all(); - - public function replace(array $attributes); - - /** - * Removes an attribute. - * - * @return mixed The removed value or null when it does not exist - */ - public function remove(string $name); -} diff --git a/lib/symfony/http-foundation/Session/Attribute/NamespacedAttributeBag.php b/lib/symfony/http-foundation/Session/Attribute/NamespacedAttributeBag.php deleted file mode 100644 index 864b35fb7..000000000 --- a/lib/symfony/http-foundation/Session/Attribute/NamespacedAttributeBag.php +++ /dev/null @@ -1,161 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Attribute; - -trigger_deprecation('symfony/http-foundation', '5.3', 'The "%s" class is deprecated.', NamespacedAttributeBag::class); - -/** - * This class provides structured storage of session attributes using - * a name spacing character in the key. - * - * @author Drak <drak@zikula.org> - * - * @deprecated since Symfony 5.3 - */ -class NamespacedAttributeBag extends AttributeBag -{ - private $namespaceCharacter; - - /** - * @param string $storageKey Session storage key - * @param string $namespaceCharacter Namespace character to use in keys - */ - public function __construct(string $storageKey = '_sf2_attributes', string $namespaceCharacter = '/') - { - $this->namespaceCharacter = $namespaceCharacter; - parent::__construct($storageKey); - } - - /** - * {@inheritdoc} - */ - public function has(string $name) - { - // reference mismatch: if fixed, re-introduced in array_key_exists; keep as it is - $attributes = $this->resolveAttributePath($name); - $name = $this->resolveKey($name); - - if (null === $attributes) { - return false; - } - - return \array_key_exists($name, $attributes); - } - - /** - * {@inheritdoc} - */ - public function get(string $name, $default = null) - { - // reference mismatch: if fixed, re-introduced in array_key_exists; keep as it is - $attributes = $this->resolveAttributePath($name); - $name = $this->resolveKey($name); - - if (null === $attributes) { - return $default; - } - - return \array_key_exists($name, $attributes) ? $attributes[$name] : $default; - } - - /** - * {@inheritdoc} - */ - public function set(string $name, $value) - { - $attributes = &$this->resolveAttributePath($name, true); - $name = $this->resolveKey($name); - $attributes[$name] = $value; - } - - /** - * {@inheritdoc} - */ - public function remove(string $name) - { - $retval = null; - $attributes = &$this->resolveAttributePath($name); - $name = $this->resolveKey($name); - if (null !== $attributes && \array_key_exists($name, $attributes)) { - $retval = $attributes[$name]; - unset($attributes[$name]); - } - - return $retval; - } - - /** - * Resolves a path in attributes property and returns it as a reference. - * - * This method allows structured namespacing of session attributes. - * - * @param string $name Key name - * @param bool $writeContext Write context, default false - * - * @return array|null - */ - protected function &resolveAttributePath(string $name, bool $writeContext = false) - { - $array = &$this->attributes; - $name = (str_starts_with($name, $this->namespaceCharacter)) ? substr($name, 1) : $name; - - // Check if there is anything to do, else return - if (!$name) { - return $array; - } - - $parts = explode($this->namespaceCharacter, $name); - if (\count($parts) < 2) { - if (!$writeContext) { - return $array; - } - - $array[$parts[0]] = []; - - return $array; - } - - unset($parts[\count($parts) - 1]); - - foreach ($parts as $part) { - if (null !== $array && !\array_key_exists($part, $array)) { - if (!$writeContext) { - $null = null; - - return $null; - } - - $array[$part] = []; - } - - $array = &$array[$part]; - } - - return $array; - } - - /** - * Resolves the key from the name. - * - * This is the last part in a dot separated string. - * - * @return string - */ - protected function resolveKey(string $name) - { - if (false !== $pos = strrpos($name, $this->namespaceCharacter)) { - $name = substr($name, $pos + 1); - } - - return $name; - } -} diff --git a/lib/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php b/lib/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php deleted file mode 100644 index 8aab3a122..000000000 --- a/lib/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php +++ /dev/null @@ -1,161 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Flash; - -/** - * AutoExpireFlashBag flash message container. - * - * @author Drak <drak@zikula.org> - */ -class AutoExpireFlashBag implements FlashBagInterface -{ - private $name = 'flashes'; - private $flashes = ['display' => [], 'new' => []]; - private $storageKey; - - /** - * @param string $storageKey The key used to store flashes in the session - */ - public function __construct(string $storageKey = '_symfony_flashes') - { - $this->storageKey = $storageKey; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->name; - } - - public function setName(string $name) - { - $this->name = $name; - } - - /** - * {@inheritdoc} - */ - public function initialize(array &$flashes) - { - $this->flashes = &$flashes; - - // The logic: messages from the last request will be stored in new, so we move them to previous - // This request we will show what is in 'display'. What is placed into 'new' this time round will - // be moved to display next time round. - $this->flashes['display'] = \array_key_exists('new', $this->flashes) ? $this->flashes['new'] : []; - $this->flashes['new'] = []; - } - - /** - * {@inheritdoc} - */ - public function add(string $type, $message) - { - $this->flashes['new'][$type][] = $message; - } - - /** - * {@inheritdoc} - */ - public function peek(string $type, array $default = []) - { - return $this->has($type) ? $this->flashes['display'][$type] : $default; - } - - /** - * {@inheritdoc} - */ - public function peekAll() - { - return \array_key_exists('display', $this->flashes) ? $this->flashes['display'] : []; - } - - /** - * {@inheritdoc} - */ - public function get(string $type, array $default = []) - { - $return = $default; - - if (!$this->has($type)) { - return $return; - } - - if (isset($this->flashes['display'][$type])) { - $return = $this->flashes['display'][$type]; - unset($this->flashes['display'][$type]); - } - - return $return; - } - - /** - * {@inheritdoc} - */ - public function all() - { - $return = $this->flashes['display']; - $this->flashes['display'] = []; - - return $return; - } - - /** - * {@inheritdoc} - */ - public function setAll(array $messages) - { - $this->flashes['new'] = $messages; - } - - /** - * {@inheritdoc} - */ - public function set(string $type, $messages) - { - $this->flashes['new'][$type] = (array) $messages; - } - - /** - * {@inheritdoc} - */ - public function has(string $type) - { - return \array_key_exists($type, $this->flashes['display']) && $this->flashes['display'][$type]; - } - - /** - * {@inheritdoc} - */ - public function keys() - { - return array_keys($this->flashes['display']); - } - - /** - * {@inheritdoc} - */ - public function getStorageKey() - { - return $this->storageKey; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - return $this->all(); - } -} diff --git a/lib/symfony/http-foundation/Session/Flash/FlashBag.php b/lib/symfony/http-foundation/Session/Flash/FlashBag.php deleted file mode 100644 index 88df7508a..000000000 --- a/lib/symfony/http-foundation/Session/Flash/FlashBag.php +++ /dev/null @@ -1,152 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Flash; - -/** - * FlashBag flash message container. - * - * @author Drak <drak@zikula.org> - */ -class FlashBag implements FlashBagInterface -{ - private $name = 'flashes'; - private $flashes = []; - private $storageKey; - - /** - * @param string $storageKey The key used to store flashes in the session - */ - public function __construct(string $storageKey = '_symfony_flashes') - { - $this->storageKey = $storageKey; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->name; - } - - public function setName(string $name) - { - $this->name = $name; - } - - /** - * {@inheritdoc} - */ - public function initialize(array &$flashes) - { - $this->flashes = &$flashes; - } - - /** - * {@inheritdoc} - */ - public function add(string $type, $message) - { - $this->flashes[$type][] = $message; - } - - /** - * {@inheritdoc} - */ - public function peek(string $type, array $default = []) - { - return $this->has($type) ? $this->flashes[$type] : $default; - } - - /** - * {@inheritdoc} - */ - public function peekAll() - { - return $this->flashes; - } - - /** - * {@inheritdoc} - */ - public function get(string $type, array $default = []) - { - if (!$this->has($type)) { - return $default; - } - - $return = $this->flashes[$type]; - - unset($this->flashes[$type]); - - return $return; - } - - /** - * {@inheritdoc} - */ - public function all() - { - $return = $this->peekAll(); - $this->flashes = []; - - return $return; - } - - /** - * {@inheritdoc} - */ - public function set(string $type, $messages) - { - $this->flashes[$type] = (array) $messages; - } - - /** - * {@inheritdoc} - */ - public function setAll(array $messages) - { - $this->flashes = $messages; - } - - /** - * {@inheritdoc} - */ - public function has(string $type) - { - return \array_key_exists($type, $this->flashes) && $this->flashes[$type]; - } - - /** - * {@inheritdoc} - */ - public function keys() - { - return array_keys($this->flashes); - } - - /** - * {@inheritdoc} - */ - public function getStorageKey() - { - return $this->storageKey; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - return $this->all(); - } -} diff --git a/lib/symfony/http-foundation/Session/Flash/FlashBagInterface.php b/lib/symfony/http-foundation/Session/Flash/FlashBagInterface.php deleted file mode 100644 index 8713e71d0..000000000 --- a/lib/symfony/http-foundation/Session/Flash/FlashBagInterface.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Flash; - -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; - -/** - * FlashBagInterface. - * - * @author Drak <drak@zikula.org> - */ -interface FlashBagInterface extends SessionBagInterface -{ - /** - * Adds a flash message for the given type. - * - * @param mixed $message - */ - public function add(string $type, $message); - - /** - * Registers one or more messages for a given type. - * - * @param string|array $messages - */ - public function set(string $type, $messages); - - /** - * Gets flash messages for a given type. - * - * @param string $type Message category type - * @param array $default Default value if $type does not exist - * - * @return array - */ - public function peek(string $type, array $default = []); - - /** - * Gets all flash messages. - * - * @return array - */ - public function peekAll(); - - /** - * Gets and clears flash from the stack. - * - * @param array $default Default value if $type does not exist - * - * @return array - */ - public function get(string $type, array $default = []); - - /** - * Gets and clears flashes from the stack. - * - * @return array - */ - public function all(); - - /** - * Sets all flash messages. - */ - public function setAll(array $messages); - - /** - * Has flash messages for a given type? - * - * @return bool - */ - public function has(string $type); - - /** - * Returns a list of all defined types. - * - * @return array - */ - public function keys(); -} diff --git a/lib/symfony/http-foundation/Session/Session.php b/lib/symfony/http-foundation/Session/Session.php deleted file mode 100644 index 022e3986f..000000000 --- a/lib/symfony/http-foundation/Session/Session.php +++ /dev/null @@ -1,285 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; -use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface; -use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; -use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface; -use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; -use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface; - -// Help opcache.preload discover always-needed symbols -class_exists(AttributeBag::class); -class_exists(FlashBag::class); -class_exists(SessionBagProxy::class); - -/** - * @author Fabien Potencier <fabien@symfony.com> - * @author Drak <drak@zikula.org> - * - * @implements \IteratorAggregate<string, mixed> - */ -class Session implements SessionInterface, \IteratorAggregate, \Countable -{ - protected $storage; - - private $flashName; - private $attributeName; - private $data = []; - private $usageIndex = 0; - private $usageReporter; - - public function __construct(SessionStorageInterface $storage = null, AttributeBagInterface $attributes = null, FlashBagInterface $flashes = null, callable $usageReporter = null) - { - $this->storage = $storage ?? new NativeSessionStorage(); - $this->usageReporter = $usageReporter; - - $attributes = $attributes ?? new AttributeBag(); - $this->attributeName = $attributes->getName(); - $this->registerBag($attributes); - - $flashes = $flashes ?? new FlashBag(); - $this->flashName = $flashes->getName(); - $this->registerBag($flashes); - } - - /** - * {@inheritdoc} - */ - public function start() - { - return $this->storage->start(); - } - - /** - * {@inheritdoc} - */ - public function has(string $name) - { - return $this->getAttributeBag()->has($name); - } - - /** - * {@inheritdoc} - */ - public function get(string $name, $default = null) - { - return $this->getAttributeBag()->get($name, $default); - } - - /** - * {@inheritdoc} - */ - public function set(string $name, $value) - { - $this->getAttributeBag()->set($name, $value); - } - - /** - * {@inheritdoc} - */ - public function all() - { - return $this->getAttributeBag()->all(); - } - - /** - * {@inheritdoc} - */ - public function replace(array $attributes) - { - $this->getAttributeBag()->replace($attributes); - } - - /** - * {@inheritdoc} - */ - public function remove(string $name) - { - return $this->getAttributeBag()->remove($name); - } - - /** - * {@inheritdoc} - */ - public function clear() - { - $this->getAttributeBag()->clear(); - } - - /** - * {@inheritdoc} - */ - public function isStarted() - { - return $this->storage->isStarted(); - } - - /** - * Returns an iterator for attributes. - * - * @return \ArrayIterator<string, mixed> - */ - #[\ReturnTypeWillChange] - public function getIterator() - { - return new \ArrayIterator($this->getAttributeBag()->all()); - } - - /** - * Returns the number of attributes. - * - * @return int - */ - #[\ReturnTypeWillChange] - public function count() - { - return \count($this->getAttributeBag()->all()); - } - - public function &getUsageIndex(): int - { - return $this->usageIndex; - } - - /** - * @internal - */ - public function isEmpty(): bool - { - if ($this->isStarted()) { - ++$this->usageIndex; - if ($this->usageReporter && 0 <= $this->usageIndex) { - ($this->usageReporter)(); - } - } - foreach ($this->data as &$data) { - if (!empty($data)) { - return false; - } - } - - return true; - } - - /** - * {@inheritdoc} - */ - public function invalidate(int $lifetime = null) - { - $this->storage->clear(); - - return $this->migrate(true, $lifetime); - } - - /** - * {@inheritdoc} - */ - public function migrate(bool $destroy = false, int $lifetime = null) - { - return $this->storage->regenerate($destroy, $lifetime); - } - - /** - * {@inheritdoc} - */ - public function save() - { - $this->storage->save(); - } - - /** - * {@inheritdoc} - */ - public function getId() - { - return $this->storage->getId(); - } - - /** - * {@inheritdoc} - */ - public function setId(string $id) - { - if ($this->storage->getId() !== $id) { - $this->storage->setId($id); - } - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->storage->getName(); - } - - /** - * {@inheritdoc} - */ - public function setName(string $name) - { - $this->storage->setName($name); - } - - /** - * {@inheritdoc} - */ - public function getMetadataBag() - { - ++$this->usageIndex; - if ($this->usageReporter && 0 <= $this->usageIndex) { - ($this->usageReporter)(); - } - - return $this->storage->getMetadataBag(); - } - - /** - * {@inheritdoc} - */ - public function registerBag(SessionBagInterface $bag) - { - $this->storage->registerBag(new SessionBagProxy($bag, $this->data, $this->usageIndex, $this->usageReporter)); - } - - /** - * {@inheritdoc} - */ - public function getBag(string $name) - { - $bag = $this->storage->getBag($name); - - return method_exists($bag, 'getBag') ? $bag->getBag() : $bag; - } - - /** - * Gets the flashbag interface. - * - * @return FlashBagInterface - */ - public function getFlashBag() - { - return $this->getBag($this->flashName); - } - - /** - * Gets the attributebag interface. - * - * Note that this method was added to help with IDE autocompletion. - */ - private function getAttributeBag(): AttributeBagInterface - { - return $this->getBag($this->attributeName); - } -} diff --git a/lib/symfony/http-foundation/Session/SessionBagInterface.php b/lib/symfony/http-foundation/Session/SessionBagInterface.php deleted file mode 100644 index 8e37d06d6..000000000 --- a/lib/symfony/http-foundation/Session/SessionBagInterface.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -/** - * Session Bag store. - * - * @author Drak <drak@zikula.org> - */ -interface SessionBagInterface -{ - /** - * Gets this bag's name. - * - * @return string - */ - public function getName(); - - /** - * Initializes the Bag. - */ - public function initialize(array &$array); - - /** - * Gets the storage key for this bag. - * - * @return string - */ - public function getStorageKey(); - - /** - * Clears out data from bag. - * - * @return mixed Whatever data was contained - */ - public function clear(); -} diff --git a/lib/symfony/http-foundation/Session/SessionBagProxy.php b/lib/symfony/http-foundation/Session/SessionBagProxy.php deleted file mode 100644 index 90aa010c9..000000000 --- a/lib/symfony/http-foundation/Session/SessionBagProxy.php +++ /dev/null @@ -1,95 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -final class SessionBagProxy implements SessionBagInterface -{ - private $bag; - private $data; - private $usageIndex; - private $usageReporter; - - public function __construct(SessionBagInterface $bag, array &$data, ?int &$usageIndex, ?callable $usageReporter) - { - $this->bag = $bag; - $this->data = &$data; - $this->usageIndex = &$usageIndex; - $this->usageReporter = $usageReporter; - } - - public function getBag(): SessionBagInterface - { - ++$this->usageIndex; - if ($this->usageReporter && 0 <= $this->usageIndex) { - ($this->usageReporter)(); - } - - return $this->bag; - } - - public function isEmpty(): bool - { - if (!isset($this->data[$this->bag->getStorageKey()])) { - return true; - } - ++$this->usageIndex; - if ($this->usageReporter && 0 <= $this->usageIndex) { - ($this->usageReporter)(); - } - - return empty($this->data[$this->bag->getStorageKey()]); - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return $this->bag->getName(); - } - - /** - * {@inheritdoc} - */ - public function initialize(array &$array): void - { - ++$this->usageIndex; - if ($this->usageReporter && 0 <= $this->usageIndex) { - ($this->usageReporter)(); - } - - $this->data[$this->bag->getStorageKey()] = &$array; - - $this->bag->initialize($array); - } - - /** - * {@inheritdoc} - */ - public function getStorageKey(): string - { - return $this->bag->getStorageKey(); - } - - /** - * {@inheritdoc} - */ - public function clear() - { - return $this->bag->clear(); - } -} diff --git a/lib/symfony/http-foundation/Session/SessionFactory.php b/lib/symfony/http-foundation/Session/SessionFactory.php deleted file mode 100644 index 04c4b06a0..000000000 --- a/lib/symfony/http-foundation/Session/SessionFactory.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageFactoryInterface; - -// Help opcache.preload discover always-needed symbols -class_exists(Session::class); - -/** - * @author Jérémy Derussé <jeremy@derusse.com> - */ -class SessionFactory implements SessionFactoryInterface -{ - private $requestStack; - private $storageFactory; - private $usageReporter; - - public function __construct(RequestStack $requestStack, SessionStorageFactoryInterface $storageFactory, callable $usageReporter = null) - { - $this->requestStack = $requestStack; - $this->storageFactory = $storageFactory; - $this->usageReporter = $usageReporter; - } - - public function createSession(): SessionInterface - { - return new Session($this->storageFactory->createStorage($this->requestStack->getMainRequest()), null, null, $this->usageReporter); - } -} diff --git a/lib/symfony/http-foundation/Session/SessionFactoryInterface.php b/lib/symfony/http-foundation/Session/SessionFactoryInterface.php deleted file mode 100644 index b24fdc495..000000000 --- a/lib/symfony/http-foundation/Session/SessionFactoryInterface.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -/** - * @author Kevin Bond <kevinbond@gmail.com> - */ -interface SessionFactoryInterface -{ - public function createSession(): SessionInterface; -} diff --git a/lib/symfony/http-foundation/Session/SessionInterface.php b/lib/symfony/http-foundation/Session/SessionInterface.php deleted file mode 100644 index b2f09fd0d..000000000 --- a/lib/symfony/http-foundation/Session/SessionInterface.php +++ /dev/null @@ -1,166 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag; - -/** - * Interface for the session. - * - * @author Drak <drak@zikula.org> - */ -interface SessionInterface -{ - /** - * Starts the session storage. - * - * @return bool - * - * @throws \RuntimeException if session fails to start - */ - public function start(); - - /** - * Returns the session ID. - * - * @return string - */ - public function getId(); - - /** - * Sets the session ID. - */ - public function setId(string $id); - - /** - * Returns the session name. - * - * @return string - */ - public function getName(); - - /** - * Sets the session name. - */ - public function setName(string $name); - - /** - * Invalidates the current session. - * - * Clears all session attributes and flashes and regenerates the - * session and deletes the old session from persistence. - * - * @param int $lifetime Sets the cookie lifetime for the session cookie. A null value - * will leave the system settings unchanged, 0 sets the cookie - * to expire with browser session. Time is in seconds, and is - * not a Unix timestamp. - * - * @return bool - */ - public function invalidate(int $lifetime = null); - - /** - * Migrates the current session to a new session id while maintaining all - * session attributes. - * - * @param bool $destroy Whether to delete the old session or leave it to garbage collection - * @param int $lifetime Sets the cookie lifetime for the session cookie. A null value - * will leave the system settings unchanged, 0 sets the cookie - * to expire with browser session. Time is in seconds, and is - * not a Unix timestamp. - * - * @return bool - */ - public function migrate(bool $destroy = false, int $lifetime = null); - - /** - * Force the session to be saved and closed. - * - * This method is generally not required for real sessions as - * the session will be automatically saved at the end of - * code execution. - */ - public function save(); - - /** - * Checks if an attribute is defined. - * - * @return bool - */ - public function has(string $name); - - /** - * Returns an attribute. - * - * @param mixed $default The default value if not found - * - * @return mixed - */ - public function get(string $name, $default = null); - - /** - * Sets an attribute. - * - * @param mixed $value - */ - public function set(string $name, $value); - - /** - * Returns attributes. - * - * @return array - */ - public function all(); - - /** - * Sets attributes. - */ - public function replace(array $attributes); - - /** - * Removes an attribute. - * - * @return mixed The removed value or null when it does not exist - */ - public function remove(string $name); - - /** - * Clears all attributes. - */ - public function clear(); - - /** - * Checks if the session was started. - * - * @return bool - */ - public function isStarted(); - - /** - * Registers a SessionBagInterface with the session. - */ - public function registerBag(SessionBagInterface $bag); - - /** - * Gets a bag instance by name. - * - * @return SessionBagInterface - */ - public function getBag(string $name); - - /** - * Gets session meta. - * - * @return MetadataBag - */ - public function getMetadataBag(); -} diff --git a/lib/symfony/http-foundation/Session/SessionUtils.php b/lib/symfony/http-foundation/Session/SessionUtils.php deleted file mode 100644 index b5bce4a88..000000000 --- a/lib/symfony/http-foundation/Session/SessionUtils.php +++ /dev/null @@ -1,59 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -/** - * Session utility functions. - * - * @author Nicolas Grekas <p@tchwork.com> - * @author Rémon van de Kamp <rpkamp@gmail.com> - * - * @internal - */ -final class SessionUtils -{ - /** - * Finds the session header amongst the headers that are to be sent, removes it, and returns - * it so the caller can process it further. - */ - public static function popSessionCookie(string $sessionName, string $sessionId): ?string - { - $sessionCookie = null; - $sessionCookiePrefix = sprintf(' %s=', urlencode($sessionName)); - $sessionCookieWithId = sprintf('%s%s;', $sessionCookiePrefix, urlencode($sessionId)); - $otherCookies = []; - foreach (headers_list() as $h) { - if (0 !== stripos($h, 'Set-Cookie:')) { - continue; - } - if (11 === strpos($h, $sessionCookiePrefix, 11)) { - $sessionCookie = $h; - - if (11 !== strpos($h, $sessionCookieWithId, 11)) { - $otherCookies[] = $h; - } - } else { - $otherCookies[] = $h; - } - } - if (null === $sessionCookie) { - return null; - } - - header_remove('Set-Cookie'); - foreach ($otherCookies as $h) { - header($h, false); - } - - return $sessionCookie; - } -} diff --git a/lib/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php b/lib/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php deleted file mode 100644 index 35d7b4b81..000000000 --- a/lib/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php +++ /dev/null @@ -1,155 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -use Symfony\Component\HttpFoundation\Session\SessionUtils; - -/** - * This abstract session handler provides a generic implementation - * of the PHP 7.0 SessionUpdateTimestampHandlerInterface, - * enabling strict and lazy session handling. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -abstract class AbstractSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface -{ - private $sessionName; - private $prefetchId; - private $prefetchData; - private $newSessionId; - private $igbinaryEmptyData; - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function open($savePath, $sessionName) - { - $this->sessionName = $sessionName; - if (!headers_sent() && !\ini_get('session.cache_limiter') && '0' !== \ini_get('session.cache_limiter')) { - header(sprintf('Cache-Control: max-age=%d, private, must-revalidate', 60 * (int) \ini_get('session.cache_expire'))); - } - - return true; - } - - /** - * @return string - */ - abstract protected function doRead(string $sessionId); - - /** - * @return bool - */ - abstract protected function doWrite(string $sessionId, string $data); - - /** - * @return bool - */ - abstract protected function doDestroy(string $sessionId); - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function validateId($sessionId) - { - $this->prefetchData = $this->read($sessionId); - $this->prefetchId = $sessionId; - - if (\PHP_VERSION_ID < 70317 || (70400 <= \PHP_VERSION_ID && \PHP_VERSION_ID < 70405)) { - // work around https://bugs.php.net/79413 - foreach (debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS) as $frame) { - if (!isset($frame['class']) && isset($frame['function']) && \in_array($frame['function'], ['session_regenerate_id', 'session_create_id'], true)) { - return '' === $this->prefetchData; - } - } - } - - return '' !== $this->prefetchData; - } - - /** - * @return string - */ - #[\ReturnTypeWillChange] - public function read($sessionId) - { - if (null !== $this->prefetchId) { - $prefetchId = $this->prefetchId; - $prefetchData = $this->prefetchData; - $this->prefetchId = $this->prefetchData = null; - - if ($prefetchId === $sessionId || '' === $prefetchData) { - $this->newSessionId = '' === $prefetchData ? $sessionId : null; - - return $prefetchData; - } - } - - $data = $this->doRead($sessionId); - $this->newSessionId = '' === $data ? $sessionId : null; - - return $data; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function write($sessionId, $data) - { - if (null === $this->igbinaryEmptyData) { - // see https://github.com/igbinary/igbinary/issues/146 - $this->igbinaryEmptyData = \function_exists('igbinary_serialize') ? igbinary_serialize([]) : ''; - } - if ('' === $data || $this->igbinaryEmptyData === $data) { - return $this->destroy($sessionId); - } - $this->newSessionId = null; - - return $this->doWrite($sessionId, $data); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function destroy($sessionId) - { - if (!headers_sent() && filter_var(\ini_get('session.use_cookies'), \FILTER_VALIDATE_BOOLEAN)) { - if (!$this->sessionName) { - throw new \LogicException(sprintf('Session name cannot be empty, did you forget to call "parent::open()" in "%s"?.', static::class)); - } - $cookie = SessionUtils::popSessionCookie($this->sessionName, $sessionId); - - /* - * We send an invalidation Set-Cookie header (zero lifetime) - * when either the session was started or a cookie with - * the session name was sent by the client (in which case - * we know it's invalid as a valid session cookie would've - * started the session). - */ - if (null === $cookie || isset($_COOKIE[$this->sessionName])) { - if (\PHP_VERSION_ID < 70300) { - setcookie($this->sessionName, '', 0, \ini_get('session.cookie_path'), \ini_get('session.cookie_domain'), filter_var(\ini_get('session.cookie_secure'), \FILTER_VALIDATE_BOOLEAN), filter_var(\ini_get('session.cookie_httponly'), \FILTER_VALIDATE_BOOLEAN)); - } else { - $params = session_get_cookie_params(); - unset($params['lifetime']); - setcookie($this->sessionName, '', $params); - } - } - } - - return $this->newSessionId === $sessionId || $this->doDestroy($sessionId); - } -} diff --git a/lib/symfony/http-foundation/Session/Storage/Handler/IdentityMarshaller.php b/lib/symfony/http-foundation/Session/Storage/Handler/IdentityMarshaller.php deleted file mode 100644 index bea3a323e..000000000 --- a/lib/symfony/http-foundation/Session/Storage/Handler/IdentityMarshaller.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -use Symfony\Component\Cache\Marshaller\MarshallerInterface; - -/** - * @author Ahmed TAILOULOUTE <ahmed.tailouloute@gmail.com> - */ -class IdentityMarshaller implements MarshallerInterface -{ - /** - * {@inheritdoc} - */ - public function marshall(array $values, ?array &$failed): array - { - foreach ($values as $key => $value) { - if (!\is_string($value)) { - throw new \LogicException(sprintf('%s accepts only string as data.', __METHOD__)); - } - } - - return $values; - } - - /** - * {@inheritdoc} - */ - public function unmarshall(string $value): string - { - return $value; - } -} diff --git a/lib/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php b/lib/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php deleted file mode 100644 index c321c8c93..000000000 --- a/lib/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php +++ /dev/null @@ -1,108 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -use Symfony\Component\Cache\Marshaller\MarshallerInterface; - -/** - * @author Ahmed TAILOULOUTE <ahmed.tailouloute@gmail.com> - */ -class MarshallingSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface -{ - private $handler; - private $marshaller; - - public function __construct(AbstractSessionHandler $handler, MarshallerInterface $marshaller) - { - $this->handler = $handler; - $this->marshaller = $marshaller; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function open($savePath, $name) - { - return $this->handler->open($savePath, $name); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function close() - { - return $this->handler->close(); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function destroy($sessionId) - { - return $this->handler->destroy($sessionId); - } - - /** - * @return int|false - */ - #[\ReturnTypeWillChange] - public function gc($maxlifetime) - { - return $this->handler->gc($maxlifetime); - } - - /** - * @return string - */ - #[\ReturnTypeWillChange] - public function read($sessionId) - { - return $this->marshaller->unmarshall($this->handler->read($sessionId)); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function write($sessionId, $data) - { - $failed = []; - $marshalledData = $this->marshaller->marshall(['data' => $data], $failed); - - if (isset($failed['data'])) { - return false; - } - - return $this->handler->write($sessionId, $marshalledData['data']); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function validateId($sessionId) - { - return $this->handler->validateId($sessionId); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function updateTimestamp($sessionId, $data) - { - return $this->handler->updateTimestamp($sessionId, $data); - } -} diff --git a/lib/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php b/lib/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php deleted file mode 100644 index e0ec4d2d9..000000000 --- a/lib/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php +++ /dev/null @@ -1,135 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * Memcached based session storage handler based on the Memcached class - * provided by the PHP memcached extension. - * - * @see https://php.net/memcached - * - * @author Drak <drak@zikula.org> - */ -class MemcachedSessionHandler extends AbstractSessionHandler -{ - private $memcached; - - /** - * @var int Time to live in seconds - */ - private $ttl; - - /** - * @var string Key prefix for shared environments - */ - private $prefix; - - /** - * Constructor. - * - * List of available options: - * * prefix: The prefix to use for the memcached keys in order to avoid collision - * * ttl: The time to live in seconds. - * - * @throws \InvalidArgumentException When unsupported options are passed - */ - public function __construct(\Memcached $memcached, array $options = []) - { - $this->memcached = $memcached; - - if ($diff = array_diff(array_keys($options), ['prefix', 'expiretime', 'ttl'])) { - throw new \InvalidArgumentException(sprintf('The following options are not supported "%s".', implode(', ', $diff))); - } - - $this->ttl = $options['expiretime'] ?? $options['ttl'] ?? null; - $this->prefix = $options['prefix'] ?? 'sf2s'; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function close() - { - return $this->memcached->quit(); - } - - /** - * {@inheritdoc} - */ - protected function doRead(string $sessionId) - { - return $this->memcached->get($this->prefix.$sessionId) ?: ''; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function updateTimestamp($sessionId, $data) - { - $this->memcached->touch($this->prefix.$sessionId, $this->getCompatibleTtl()); - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doWrite(string $sessionId, string $data) - { - return $this->memcached->set($this->prefix.$sessionId, $data, $this->getCompatibleTtl()); - } - - private function getCompatibleTtl(): int - { - $ttl = (int) ($this->ttl ?? \ini_get('session.gc_maxlifetime')); - - // If the relative TTL that is used exceeds 30 days, memcached will treat the value as Unix time. - // We have to convert it to an absolute Unix time at this point, to make sure the TTL is correct. - if ($ttl > 60 * 60 * 24 * 30) { - $ttl += time(); - } - - return $ttl; - } - - /** - * {@inheritdoc} - */ - protected function doDestroy(string $sessionId) - { - $result = $this->memcached->delete($this->prefix.$sessionId); - - return $result || \Memcached::RES_NOTFOUND == $this->memcached->getResultCode(); - } - - /** - * @return int|false - */ - #[\ReturnTypeWillChange] - public function gc($maxlifetime) - { - // not required here because memcached will auto expire the records anyhow. - return 0; - } - - /** - * Return a Memcached instance. - * - * @return \Memcached - */ - protected function getMemcached() - { - return $this->memcached; - } -} diff --git a/lib/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php b/lib/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php deleted file mode 100644 index bf27ca6cc..000000000 --- a/lib/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php +++ /dev/null @@ -1,139 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * Migrating session handler for migrating from one handler to another. It reads - * from the current handler and writes both the current and new ones. - * - * It ignores errors from the new handler. - * - * @author Ross Motley <ross.motley@amara.com> - * @author Oliver Radwell <oliver.radwell@amara.com> - */ -class MigratingSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface -{ - /** - * @var \SessionHandlerInterface&\SessionUpdateTimestampHandlerInterface - */ - private $currentHandler; - - /** - * @var \SessionHandlerInterface&\SessionUpdateTimestampHandlerInterface - */ - private $writeOnlyHandler; - - public function __construct(\SessionHandlerInterface $currentHandler, \SessionHandlerInterface $writeOnlyHandler) - { - if (!$currentHandler instanceof \SessionUpdateTimestampHandlerInterface) { - $currentHandler = new StrictSessionHandler($currentHandler); - } - if (!$writeOnlyHandler instanceof \SessionUpdateTimestampHandlerInterface) { - $writeOnlyHandler = new StrictSessionHandler($writeOnlyHandler); - } - - $this->currentHandler = $currentHandler; - $this->writeOnlyHandler = $writeOnlyHandler; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function close() - { - $result = $this->currentHandler->close(); - $this->writeOnlyHandler->close(); - - return $result; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function destroy($sessionId) - { - $result = $this->currentHandler->destroy($sessionId); - $this->writeOnlyHandler->destroy($sessionId); - - return $result; - } - - /** - * @return int|false - */ - #[\ReturnTypeWillChange] - public function gc($maxlifetime) - { - $result = $this->currentHandler->gc($maxlifetime); - $this->writeOnlyHandler->gc($maxlifetime); - - return $result; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function open($savePath, $sessionName) - { - $result = $this->currentHandler->open($savePath, $sessionName); - $this->writeOnlyHandler->open($savePath, $sessionName); - - return $result; - } - - /** - * @return string - */ - #[\ReturnTypeWillChange] - public function read($sessionId) - { - // No reading from new handler until switch-over - return $this->currentHandler->read($sessionId); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function write($sessionId, $sessionData) - { - $result = $this->currentHandler->write($sessionId, $sessionData); - $this->writeOnlyHandler->write($sessionId, $sessionData); - - return $result; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function validateId($sessionId) - { - // No reading from new handler until switch-over - return $this->currentHandler->validateId($sessionId); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function updateTimestamp($sessionId, $sessionData) - { - $result = $this->currentHandler->updateTimestamp($sessionId, $sessionData); - $this->writeOnlyHandler->updateTimestamp($sessionId, $sessionData); - - return $result; - } -} diff --git a/lib/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php b/lib/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php deleted file mode 100644 index ef8f71942..000000000 --- a/lib/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php +++ /dev/null @@ -1,193 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -use MongoDB\BSON\Binary; -use MongoDB\BSON\UTCDateTime; -use MongoDB\Client; -use MongoDB\Collection; - -/** - * Session handler using the mongodb/mongodb package and MongoDB driver extension. - * - * @author Markus Bachmann <markus.bachmann@bachi.biz> - * - * @see https://packagist.org/packages/mongodb/mongodb - * @see https://php.net/mongodb - */ -class MongoDbSessionHandler extends AbstractSessionHandler -{ - private $mongo; - - /** - * @var Collection - */ - private $collection; - - /** - * @var array - */ - private $options; - - /** - * Constructor. - * - * List of available options: - * * database: The name of the database [required] - * * collection: The name of the collection [required] - * * id_field: The field name for storing the session id [default: _id] - * * data_field: The field name for storing the session data [default: data] - * * time_field: The field name for storing the timestamp [default: time] - * * expiry_field: The field name for storing the expiry-timestamp [default: expires_at]. - * - * It is strongly recommended to put an index on the `expiry_field` for - * garbage-collection. Alternatively it's possible to automatically expire - * the sessions in the database as described below: - * - * A TTL collections can be used on MongoDB 2.2+ to cleanup expired sessions - * automatically. Such an index can for example look like this: - * - * db.<session-collection>.createIndex( - * { "<expiry-field>": 1 }, - * { "expireAfterSeconds": 0 } - * ) - * - * More details on: https://docs.mongodb.org/manual/tutorial/expire-data/ - * - * If you use such an index, you can drop `gc_probability` to 0 since - * no garbage-collection is required. - * - * @throws \InvalidArgumentException When "database" or "collection" not provided - */ - public function __construct(Client $mongo, array $options) - { - if (!isset($options['database']) || !isset($options['collection'])) { - throw new \InvalidArgumentException('You must provide the "database" and "collection" option for MongoDBSessionHandler.'); - } - - $this->mongo = $mongo; - - $this->options = array_merge([ - 'id_field' => '_id', - 'data_field' => 'data', - 'time_field' => 'time', - 'expiry_field' => 'expires_at', - ], $options); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function close() - { - return true; - } - - /** - * {@inheritdoc} - */ - protected function doDestroy(string $sessionId) - { - $this->getCollection()->deleteOne([ - $this->options['id_field'] => $sessionId, - ]); - - return true; - } - - /** - * @return int|false - */ - #[\ReturnTypeWillChange] - public function gc($maxlifetime) - { - return $this->getCollection()->deleteMany([ - $this->options['expiry_field'] => ['$lt' => new UTCDateTime()], - ])->getDeletedCount(); - } - - /** - * {@inheritdoc} - */ - protected function doWrite(string $sessionId, string $data) - { - $expiry = new UTCDateTime((time() + (int) \ini_get('session.gc_maxlifetime')) * 1000); - - $fields = [ - $this->options['time_field'] => new UTCDateTime(), - $this->options['expiry_field'] => $expiry, - $this->options['data_field'] => new Binary($data, Binary::TYPE_OLD_BINARY), - ]; - - $this->getCollection()->updateOne( - [$this->options['id_field'] => $sessionId], - ['$set' => $fields], - ['upsert' => true] - ); - - return true; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function updateTimestamp($sessionId, $data) - { - $expiry = new UTCDateTime((time() + (int) \ini_get('session.gc_maxlifetime')) * 1000); - - $this->getCollection()->updateOne( - [$this->options['id_field'] => $sessionId], - ['$set' => [ - $this->options['time_field'] => new UTCDateTime(), - $this->options['expiry_field'] => $expiry, - ]] - ); - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doRead(string $sessionId) - { - $dbData = $this->getCollection()->findOne([ - $this->options['id_field'] => $sessionId, - $this->options['expiry_field'] => ['$gte' => new UTCDateTime()], - ]); - - if (null === $dbData) { - return ''; - } - - return $dbData[$this->options['data_field']]->getData(); - } - - private function getCollection(): Collection - { - if (null === $this->collection) { - $this->collection = $this->mongo->selectCollection($this->options['database'], $this->options['collection']); - } - - return $this->collection; - } - - /** - * @return Client - */ - protected function getMongo() - { - return $this->mongo; - } -} diff --git a/lib/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php b/lib/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php deleted file mode 100644 index 1ca4bfeb0..000000000 --- a/lib/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * Native session handler using PHP's built in file storage. - * - * @author Drak <drak@zikula.org> - */ -class NativeFileSessionHandler extends \SessionHandler -{ - /** - * @param string $savePath Path of directory to save session files - * Default null will leave setting as defined by PHP. - * '/path', 'N;/path', or 'N;octal-mode;/path - * - * @see https://php.net/session.configuration#ini.session.save-path for further details. - * - * @throws \InvalidArgumentException On invalid $savePath - * @throws \RuntimeException When failing to create the save directory - */ - public function __construct(string $savePath = null) - { - if (null === $savePath) { - $savePath = \ini_get('session.save_path'); - } - - $baseDir = $savePath; - - if ($count = substr_count($savePath, ';')) { - if ($count > 2) { - throw new \InvalidArgumentException(sprintf('Invalid argument $savePath \'%s\'.', $savePath)); - } - - // characters after last ';' are the path - $baseDir = ltrim(strrchr($savePath, ';'), ';'); - } - - if ($baseDir && !is_dir($baseDir) && !@mkdir($baseDir, 0777, true) && !is_dir($baseDir)) { - throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s".', $baseDir)); - } - - ini_set('session.save_path', $savePath); - ini_set('session.save_handler', 'files'); - } -} diff --git a/lib/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php b/lib/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php deleted file mode 100644 index 4331dbe50..000000000 --- a/lib/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * Can be used in unit testing or in a situations where persisted sessions are not desired. - * - * @author Drak <drak@zikula.org> - */ -class NullSessionHandler extends AbstractSessionHandler -{ - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function close() - { - return true; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function validateId($sessionId) - { - return true; - } - - /** - * {@inheritdoc} - */ - protected function doRead(string $sessionId) - { - return ''; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function updateTimestamp($sessionId, $data) - { - return true; - } - - /** - * {@inheritdoc} - */ - protected function doWrite(string $sessionId, string $data) - { - return true; - } - - /** - * {@inheritdoc} - */ - protected function doDestroy(string $sessionId) - { - return true; - } - - /** - * @return int|false - */ - #[\ReturnTypeWillChange] - public function gc($maxlifetime) - { - return 0; - } -} diff --git a/lib/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php b/lib/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php deleted file mode 100644 index 24c98940d..000000000 --- a/lib/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php +++ /dev/null @@ -1,943 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * Session handler using a PDO connection to read and write data. - * - * It works with MySQL, PostgreSQL, Oracle, SQL Server and SQLite and implements - * different locking strategies to handle concurrent access to the same session. - * Locking is necessary to prevent loss of data due to race conditions and to keep - * the session data consistent between read() and write(). With locking, requests - * for the same session will wait until the other one finished writing. For this - * reason it's best practice to close a session as early as possible to improve - * concurrency. PHPs internal files session handler also implements locking. - * - * Attention: Since SQLite does not support row level locks but locks the whole database, - * it means only one session can be accessed at a time. Even different sessions would wait - * for another to finish. So saving session in SQLite should only be considered for - * development or prototypes. - * - * Session data is a binary string that can contain non-printable characters like the null byte. - * For this reason it must be saved in a binary column in the database like BLOB in MySQL. - * Saving it in a character column could corrupt the data. You can use createTable() - * to initialize a correctly defined table. - * - * @see https://php.net/sessionhandlerinterface - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Michael Williams <michael.williams@funsational.com> - * @author Tobias Schultze <http://tobion.de> - */ -class PdoSessionHandler extends AbstractSessionHandler -{ - /** - * No locking is done. This means sessions are prone to loss of data due to - * race conditions of concurrent requests to the same session. The last session - * write will win in this case. It might be useful when you implement your own - * logic to deal with this like an optimistic approach. - */ - public const LOCK_NONE = 0; - - /** - * Creates an application-level lock on a session. The disadvantage is that the - * lock is not enforced by the database and thus other, unaware parts of the - * application could still concurrently modify the session. The advantage is it - * does not require a transaction. - * This mode is not available for SQLite and not yet implemented for oci and sqlsrv. - */ - public const LOCK_ADVISORY = 1; - - /** - * Issues a real row lock. Since it uses a transaction between opening and - * closing a session, you have to be careful when you use same database connection - * that you also use for your application logic. This mode is the default because - * it's the only reliable solution across DBMSs. - */ - public const LOCK_TRANSACTIONAL = 2; - - private const MAX_LIFETIME = 315576000; - - /** - * @var \PDO|null PDO instance or null when not connected yet - */ - private $pdo; - - /** - * DSN string or null for session.save_path or false when lazy connection disabled. - * - * @var string|false|null - */ - private $dsn = false; - - /** - * @var string|null - */ - private $driver; - - /** - * @var string - */ - private $table = 'sessions'; - - /** - * @var string - */ - private $idCol = 'sess_id'; - - /** - * @var string - */ - private $dataCol = 'sess_data'; - - /** - * @var string - */ - private $lifetimeCol = 'sess_lifetime'; - - /** - * @var string - */ - private $timeCol = 'sess_time'; - - /** - * Username when lazy-connect. - * - * @var string - */ - private $username = ''; - - /** - * Password when lazy-connect. - * - * @var string - */ - private $password = ''; - - /** - * Connection options when lazy-connect. - * - * @var array - */ - private $connectionOptions = []; - - /** - * The strategy for locking, see constants. - * - * @var int - */ - private $lockMode = self::LOCK_TRANSACTIONAL; - - /** - * It's an array to support multiple reads before closing which is manual, non-standard usage. - * - * @var \PDOStatement[] An array of statements to release advisory locks - */ - private $unlockStatements = []; - - /** - * True when the current session exists but expired according to session.gc_maxlifetime. - * - * @var bool - */ - private $sessionExpired = false; - - /** - * Whether a transaction is active. - * - * @var bool - */ - private $inTransaction = false; - - /** - * Whether gc() has been called. - * - * @var bool - */ - private $gcCalled = false; - - /** - * You can either pass an existing database connection as PDO instance or - * pass a DSN string that will be used to lazy-connect to the database - * when the session is actually used. Furthermore it's possible to pass null - * which will then use the session.save_path ini setting as PDO DSN parameter. - * - * List of available options: - * * db_table: The name of the table [default: sessions] - * * db_id_col: The column where to store the session id [default: sess_id] - * * db_data_col: The column where to store the session data [default: sess_data] - * * db_lifetime_col: The column where to store the lifetime [default: sess_lifetime] - * * db_time_col: The column where to store the timestamp [default: sess_time] - * * db_username: The username when lazy-connect [default: ''] - * * db_password: The password when lazy-connect [default: ''] - * * db_connection_options: An array of driver-specific connection options [default: []] - * * lock_mode: The strategy for locking, see constants [default: LOCK_TRANSACTIONAL] - * - * @param \PDO|string|null $pdoOrDsn A \PDO instance or DSN string or URL string or null - * - * @throws \InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION - */ - public function __construct($pdoOrDsn = null, array $options = []) - { - if ($pdoOrDsn instanceof \PDO) { - if (\PDO::ERRMODE_EXCEPTION !== $pdoOrDsn->getAttribute(\PDO::ATTR_ERRMODE)) { - throw new \InvalidArgumentException(sprintf('"%s" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)).', __CLASS__)); - } - - $this->pdo = $pdoOrDsn; - $this->driver = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME); - } elseif (\is_string($pdoOrDsn) && str_contains($pdoOrDsn, '://')) { - $this->dsn = $this->buildDsnFromUrl($pdoOrDsn); - } else { - $this->dsn = $pdoOrDsn; - } - - $this->table = $options['db_table'] ?? $this->table; - $this->idCol = $options['db_id_col'] ?? $this->idCol; - $this->dataCol = $options['db_data_col'] ?? $this->dataCol; - $this->lifetimeCol = $options['db_lifetime_col'] ?? $this->lifetimeCol; - $this->timeCol = $options['db_time_col'] ?? $this->timeCol; - $this->username = $options['db_username'] ?? $this->username; - $this->password = $options['db_password'] ?? $this->password; - $this->connectionOptions = $options['db_connection_options'] ?? $this->connectionOptions; - $this->lockMode = $options['lock_mode'] ?? $this->lockMode; - } - - /** - * Creates the table to store sessions which can be called once for setup. - * - * Session ID is saved in a column of maximum length 128 because that is enough even - * for a 512 bit configured session.hash_function like Whirlpool. Session data is - * saved in a BLOB. One could also use a shorter inlined varbinary column - * if one was sure the data fits into it. - * - * @throws \PDOException When the table already exists - * @throws \DomainException When an unsupported PDO driver is used - */ - public function createTable() - { - // connect if we are not yet - $this->getConnection(); - - switch ($this->driver) { - case 'mysql': - // We use varbinary for the ID column because it prevents unwanted conversions: - // - character set conversions between server and client - // - trailing space removal - // - case-insensitivity - // - language processing like é == e - $sql = "CREATE TABLE $this->table ($this->idCol VARBINARY(128) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER UNSIGNED NOT NULL, $this->timeCol INTEGER UNSIGNED NOT NULL) COLLATE utf8mb4_bin, ENGINE = InnoDB"; - break; - case 'sqlite': - $sql = "CREATE TABLE $this->table ($this->idCol TEXT NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; - break; - case 'pgsql': - $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR(128) NOT NULL PRIMARY KEY, $this->dataCol BYTEA NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; - break; - case 'oci': - $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR2(128) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; - break; - case 'sqlsrv': - $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR(128) NOT NULL PRIMARY KEY, $this->dataCol VARBINARY(MAX) NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; - break; - default: - throw new \DomainException(sprintf('Creating the session table is currently not implemented for PDO driver "%s".', $this->driver)); - } - - try { - $this->pdo->exec($sql); - $this->pdo->exec("CREATE INDEX EXPIRY ON $this->table ($this->lifetimeCol)"); - } catch (\PDOException $e) { - $this->rollback(); - - throw $e; - } - } - - /** - * Returns true when the current session exists but expired according to session.gc_maxlifetime. - * - * Can be used to distinguish between a new session and one that expired due to inactivity. - * - * @return bool - */ - public function isSessionExpired() - { - return $this->sessionExpired; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function open($savePath, $sessionName) - { - $this->sessionExpired = false; - - if (null === $this->pdo) { - $this->connect($this->dsn ?: $savePath); - } - - return parent::open($savePath, $sessionName); - } - - /** - * @return string - */ - #[\ReturnTypeWillChange] - public function read($sessionId) - { - try { - return parent::read($sessionId); - } catch (\PDOException $e) { - $this->rollback(); - - throw $e; - } - } - - /** - * @return int|false - */ - #[\ReturnTypeWillChange] - public function gc($maxlifetime) - { - // We delay gc() to close() so that it is executed outside the transactional and blocking read-write process. - // This way, pruning expired sessions does not block them from being started while the current session is used. - $this->gcCalled = true; - - return 0; - } - - /** - * {@inheritdoc} - */ - protected function doDestroy(string $sessionId) - { - // delete the record associated with this id - $sql = "DELETE FROM $this->table WHERE $this->idCol = :id"; - - try { - $stmt = $this->pdo->prepare($sql); - $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $stmt->execute(); - } catch (\PDOException $e) { - $this->rollback(); - - throw $e; - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doWrite(string $sessionId, string $data) - { - $maxlifetime = (int) \ini_get('session.gc_maxlifetime'); - - try { - // We use a single MERGE SQL query when supported by the database. - $mergeStmt = $this->getMergeStatement($sessionId, $data, $maxlifetime); - if (null !== $mergeStmt) { - $mergeStmt->execute(); - - return true; - } - - $updateStmt = $this->getUpdateStatement($sessionId, $data, $maxlifetime); - $updateStmt->execute(); - - // When MERGE is not supported, like in Postgres < 9.5, we have to use this approach that can result in - // duplicate key errors when the same session is written simultaneously (given the LOCK_NONE behavior). - // We can just catch such an error and re-execute the update. This is similar to a serializable - // transaction with retry logic on serialization failures but without the overhead and without possible - // false positives due to longer gap locking. - if (!$updateStmt->rowCount()) { - try { - $insertStmt = $this->getInsertStatement($sessionId, $data, $maxlifetime); - $insertStmt->execute(); - } catch (\PDOException $e) { - // Handle integrity violation SQLSTATE 23000 (or a subclass like 23505 in Postgres) for duplicate keys - if (str_starts_with($e->getCode(), '23')) { - $updateStmt->execute(); - } else { - throw $e; - } - } - } - } catch (\PDOException $e) { - $this->rollback(); - - throw $e; - } - - return true; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function updateTimestamp($sessionId, $data) - { - $expiry = time() + (int) \ini_get('session.gc_maxlifetime'); - - try { - $updateStmt = $this->pdo->prepare( - "UPDATE $this->table SET $this->lifetimeCol = :expiry, $this->timeCol = :time WHERE $this->idCol = :id" - ); - $updateStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $updateStmt->bindParam(':expiry', $expiry, \PDO::PARAM_INT); - $updateStmt->bindValue(':time', time(), \PDO::PARAM_INT); - $updateStmt->execute(); - } catch (\PDOException $e) { - $this->rollback(); - - throw $e; - } - - return true; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function close() - { - $this->commit(); - - while ($unlockStmt = array_shift($this->unlockStatements)) { - $unlockStmt->execute(); - } - - if ($this->gcCalled) { - $this->gcCalled = false; - - // delete the session records that have expired - $sql = "DELETE FROM $this->table WHERE $this->lifetimeCol < :time AND $this->lifetimeCol > :min"; - $stmt = $this->pdo->prepare($sql); - $stmt->bindValue(':time', time(), \PDO::PARAM_INT); - $stmt->bindValue(':min', self::MAX_LIFETIME, \PDO::PARAM_INT); - $stmt->execute(); - // to be removed in 6.0 - if ('mysql' === $this->driver) { - $legacySql = "DELETE FROM $this->table WHERE $this->lifetimeCol <= :min AND $this->lifetimeCol + $this->timeCol < :time"; - } else { - $legacySql = "DELETE FROM $this->table WHERE $this->lifetimeCol <= :min AND $this->lifetimeCol < :time - $this->timeCol"; - } - - $stmt = $this->pdo->prepare($legacySql); - $stmt->bindValue(':time', time(), \PDO::PARAM_INT); - $stmt->bindValue(':min', self::MAX_LIFETIME, \PDO::PARAM_INT); - $stmt->execute(); - } - - if (false !== $this->dsn) { - $this->pdo = null; // only close lazy-connection - $this->driver = null; - } - - return true; - } - - /** - * Lazy-connects to the database. - */ - private function connect(string $dsn): void - { - $this->pdo = new \PDO($dsn, $this->username, $this->password, $this->connectionOptions); - $this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); - $this->driver = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME); - } - - /** - * Builds a PDO DSN from a URL-like connection string. - * - * @todo implement missing support for oci DSN (which look totally different from other PDO ones) - */ - private function buildDsnFromUrl(string $dsnOrUrl): string - { - // (pdo_)?sqlite3?:///... => (pdo_)?sqlite3?://localhost/... or else the URL will be invalid - $url = preg_replace('#^((?:pdo_)?sqlite3?):///#', '$1://localhost/', $dsnOrUrl); - - $params = parse_url($url); - - if (false === $params) { - return $dsnOrUrl; // If the URL is not valid, let's assume it might be a DSN already. - } - - $params = array_map('rawurldecode', $params); - - // Override the default username and password. Values passed through options will still win over these in the constructor. - if (isset($params['user'])) { - $this->username = $params['user']; - } - - if (isset($params['pass'])) { - $this->password = $params['pass']; - } - - if (!isset($params['scheme'])) { - throw new \InvalidArgumentException('URLs without scheme are not supported to configure the PdoSessionHandler.'); - } - - $driverAliasMap = [ - 'mssql' => 'sqlsrv', - 'mysql2' => 'mysql', // Amazon RDS, for some weird reason - 'postgres' => 'pgsql', - 'postgresql' => 'pgsql', - 'sqlite3' => 'sqlite', - ]; - - $driver = $driverAliasMap[$params['scheme']] ?? $params['scheme']; - - // Doctrine DBAL supports passing its internal pdo_* driver names directly too (allowing both dashes and underscores). This allows supporting the same here. - if (str_starts_with($driver, 'pdo_') || str_starts_with($driver, 'pdo-')) { - $driver = substr($driver, 4); - } - - $dsn = null; - switch ($driver) { - case 'mysql': - $dsn = 'mysql:'; - if ('' !== ($params['query'] ?? '')) { - $queryParams = []; - parse_str($params['query'], $queryParams); - if ('' !== ($queryParams['charset'] ?? '')) { - $dsn .= 'charset='.$queryParams['charset'].';'; - } - - if ('' !== ($queryParams['unix_socket'] ?? '')) { - $dsn .= 'unix_socket='.$queryParams['unix_socket'].';'; - - if (isset($params['path'])) { - $dbName = substr($params['path'], 1); // Remove the leading slash - $dsn .= 'dbname='.$dbName.';'; - } - - return $dsn; - } - } - // If "unix_socket" is not in the query, we continue with the same process as pgsql - // no break - case 'pgsql': - $dsn ?? $dsn = 'pgsql:'; - - if (isset($params['host']) && '' !== $params['host']) { - $dsn .= 'host='.$params['host'].';'; - } - - if (isset($params['port']) && '' !== $params['port']) { - $dsn .= 'port='.$params['port'].';'; - } - - if (isset($params['path'])) { - $dbName = substr($params['path'], 1); // Remove the leading slash - $dsn .= 'dbname='.$dbName.';'; - } - - return $dsn; - - case 'sqlite': - return 'sqlite:'.substr($params['path'], 1); - - case 'sqlsrv': - $dsn = 'sqlsrv:server='; - - if (isset($params['host'])) { - $dsn .= $params['host']; - } - - if (isset($params['port']) && '' !== $params['port']) { - $dsn .= ','.$params['port']; - } - - if (isset($params['path'])) { - $dbName = substr($params['path'], 1); // Remove the leading slash - $dsn .= ';Database='.$dbName; - } - - return $dsn; - - default: - throw new \InvalidArgumentException(sprintf('The scheme "%s" is not supported by the PdoSessionHandler URL configuration. Pass a PDO DSN directly.', $params['scheme'])); - } - } - - /** - * Helper method to begin a transaction. - * - * Since SQLite does not support row level locks, we have to acquire a reserved lock - * on the database immediately. Because of https://bugs.php.net/42766 we have to create - * such a transaction manually which also means we cannot use PDO::commit or - * PDO::rollback or PDO::inTransaction for SQLite. - * - * Also MySQLs default isolation, REPEATABLE READ, causes deadlock for different sessions - * due to https://percona.com/blog/2013/12/12/one-more-innodb-gap-lock-to-avoid/ . - * So we change it to READ COMMITTED. - */ - private function beginTransaction(): void - { - if (!$this->inTransaction) { - if ('sqlite' === $this->driver) { - $this->pdo->exec('BEGIN IMMEDIATE TRANSACTION'); - } else { - if ('mysql' === $this->driver) { - $this->pdo->exec('SET TRANSACTION ISOLATION LEVEL READ COMMITTED'); - } - $this->pdo->beginTransaction(); - } - $this->inTransaction = true; - } - } - - /** - * Helper method to commit a transaction. - */ - private function commit(): void - { - if ($this->inTransaction) { - try { - // commit read-write transaction which also releases the lock - if ('sqlite' === $this->driver) { - $this->pdo->exec('COMMIT'); - } else { - $this->pdo->commit(); - } - $this->inTransaction = false; - } catch (\PDOException $e) { - $this->rollback(); - - throw $e; - } - } - } - - /** - * Helper method to rollback a transaction. - */ - private function rollback(): void - { - // We only need to rollback if we are in a transaction. Otherwise the resulting - // error would hide the real problem why rollback was called. We might not be - // in a transaction when not using the transactional locking behavior or when - // two callbacks (e.g. destroy and write) are invoked that both fail. - if ($this->inTransaction) { - if ('sqlite' === $this->driver) { - $this->pdo->exec('ROLLBACK'); - } else { - $this->pdo->rollBack(); - } - $this->inTransaction = false; - } - } - - /** - * Reads the session data in respect to the different locking strategies. - * - * We need to make sure we do not return session data that is already considered garbage according - * to the session.gc_maxlifetime setting because gc() is called after read() and only sometimes. - * - * @return string - */ - protected function doRead(string $sessionId) - { - if (self::LOCK_ADVISORY === $this->lockMode) { - $this->unlockStatements[] = $this->doAdvisoryLock($sessionId); - } - - $selectSql = $this->getSelectSql(); - $selectStmt = $this->pdo->prepare($selectSql); - $selectStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $insertStmt = null; - - while (true) { - $selectStmt->execute(); - $sessionRows = $selectStmt->fetchAll(\PDO::FETCH_NUM); - - if ($sessionRows) { - $expiry = (int) $sessionRows[0][1]; - if ($expiry <= self::MAX_LIFETIME) { - $expiry += $sessionRows[0][2]; - } - - if ($expiry < time()) { - $this->sessionExpired = true; - - return ''; - } - - return \is_resource($sessionRows[0][0]) ? stream_get_contents($sessionRows[0][0]) : $sessionRows[0][0]; - } - - if (null !== $insertStmt) { - $this->rollback(); - throw new \RuntimeException('Failed to read session: INSERT reported a duplicate id but next SELECT did not return any data.'); - } - - if (!filter_var(\ini_get('session.use_strict_mode'), \FILTER_VALIDATE_BOOLEAN) && self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) { - // In strict mode, session fixation is not possible: new sessions always start with a unique - // random id, so that concurrency is not possible and this code path can be skipped. - // Exclusive-reading of non-existent rows does not block, so we need to do an insert to block - // until other connections to the session are committed. - try { - $insertStmt = $this->getInsertStatement($sessionId, '', 0); - $insertStmt->execute(); - } catch (\PDOException $e) { - // Catch duplicate key error because other connection created the session already. - // It would only not be the case when the other connection destroyed the session. - if (str_starts_with($e->getCode(), '23')) { - // Retrieve finished session data written by concurrent connection by restarting the loop. - // We have to start a new transaction as a failed query will mark the current transaction as - // aborted in PostgreSQL and disallow further queries within it. - $this->rollback(); - $this->beginTransaction(); - continue; - } - - throw $e; - } - } - - return ''; - } - } - - /** - * Executes an application-level lock on the database. - * - * @return \PDOStatement The statement that needs to be executed later to release the lock - * - * @throws \DomainException When an unsupported PDO driver is used - * - * @todo implement missing advisory locks - * - for oci using DBMS_LOCK.REQUEST - * - for sqlsrv using sp_getapplock with LockOwner = Session - */ - private function doAdvisoryLock(string $sessionId): \PDOStatement - { - switch ($this->driver) { - case 'mysql': - // MySQL 5.7.5 and later enforces a maximum length on lock names of 64 characters. Previously, no limit was enforced. - $lockId = substr($sessionId, 0, 64); - // should we handle the return value? 0 on timeout, null on error - // we use a timeout of 50 seconds which is also the default for innodb_lock_wait_timeout - $stmt = $this->pdo->prepare('SELECT GET_LOCK(:key, 50)'); - $stmt->bindValue(':key', $lockId, \PDO::PARAM_STR); - $stmt->execute(); - - $releaseStmt = $this->pdo->prepare('DO RELEASE_LOCK(:key)'); - $releaseStmt->bindValue(':key', $lockId, \PDO::PARAM_STR); - - return $releaseStmt; - case 'pgsql': - // Obtaining an exclusive session level advisory lock requires an integer key. - // When session.sid_bits_per_character > 4, the session id can contain non-hex-characters. - // So we cannot just use hexdec(). - if (4 === \PHP_INT_SIZE) { - $sessionInt1 = $this->convertStringToInt($sessionId); - $sessionInt2 = $this->convertStringToInt(substr($sessionId, 4, 4)); - - $stmt = $this->pdo->prepare('SELECT pg_advisory_lock(:key1, :key2)'); - $stmt->bindValue(':key1', $sessionInt1, \PDO::PARAM_INT); - $stmt->bindValue(':key2', $sessionInt2, \PDO::PARAM_INT); - $stmt->execute(); - - $releaseStmt = $this->pdo->prepare('SELECT pg_advisory_unlock(:key1, :key2)'); - $releaseStmt->bindValue(':key1', $sessionInt1, \PDO::PARAM_INT); - $releaseStmt->bindValue(':key2', $sessionInt2, \PDO::PARAM_INT); - } else { - $sessionBigInt = $this->convertStringToInt($sessionId); - - $stmt = $this->pdo->prepare('SELECT pg_advisory_lock(:key)'); - $stmt->bindValue(':key', $sessionBigInt, \PDO::PARAM_INT); - $stmt->execute(); - - $releaseStmt = $this->pdo->prepare('SELECT pg_advisory_unlock(:key)'); - $releaseStmt->bindValue(':key', $sessionBigInt, \PDO::PARAM_INT); - } - - return $releaseStmt; - case 'sqlite': - throw new \DomainException('SQLite does not support advisory locks.'); - default: - throw new \DomainException(sprintf('Advisory locks are currently not implemented for PDO driver "%s".', $this->driver)); - } - } - - /** - * Encodes the first 4 (when PHP_INT_SIZE == 4) or 8 characters of the string as an integer. - * - * Keep in mind, PHP integers are signed. - */ - private function convertStringToInt(string $string): int - { - if (4 === \PHP_INT_SIZE) { - return (\ord($string[3]) << 24) + (\ord($string[2]) << 16) + (\ord($string[1]) << 8) + \ord($string[0]); - } - - $int1 = (\ord($string[7]) << 24) + (\ord($string[6]) << 16) + (\ord($string[5]) << 8) + \ord($string[4]); - $int2 = (\ord($string[3]) << 24) + (\ord($string[2]) << 16) + (\ord($string[1]) << 8) + \ord($string[0]); - - return $int2 + ($int1 << 32); - } - - /** - * Return a locking or nonlocking SQL query to read session information. - * - * @throws \DomainException When an unsupported PDO driver is used - */ - private function getSelectSql(): string - { - if (self::LOCK_TRANSACTIONAL === $this->lockMode) { - $this->beginTransaction(); - - // selecting the time column should be removed in 6.0 - switch ($this->driver) { - case 'mysql': - case 'oci': - case 'pgsql': - return "SELECT $this->dataCol, $this->lifetimeCol, $this->timeCol FROM $this->table WHERE $this->idCol = :id FOR UPDATE"; - case 'sqlsrv': - return "SELECT $this->dataCol, $this->lifetimeCol, $this->timeCol FROM $this->table WITH (UPDLOCK, ROWLOCK) WHERE $this->idCol = :id"; - case 'sqlite': - // we already locked when starting transaction - break; - default: - throw new \DomainException(sprintf('Transactional locks are currently not implemented for PDO driver "%s".', $this->driver)); - } - } - - return "SELECT $this->dataCol, $this->lifetimeCol, $this->timeCol FROM $this->table WHERE $this->idCol = :id"; - } - - /** - * Returns an insert statement supported by the database for writing session data. - */ - private function getInsertStatement(string $sessionId, string $sessionData, int $maxlifetime): \PDOStatement - { - switch ($this->driver) { - case 'oci': - $data = fopen('php://memory', 'r+'); - fwrite($data, $sessionData); - rewind($data); - $sql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, EMPTY_BLOB(), :expiry, :time) RETURNING $this->dataCol into :data"; - break; - default: - $data = $sessionData; - $sql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time)"; - break; - } - - $stmt = $this->pdo->prepare($sql); - $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $stmt->bindParam(':data', $data, \PDO::PARAM_LOB); - $stmt->bindValue(':expiry', time() + $maxlifetime, \PDO::PARAM_INT); - $stmt->bindValue(':time', time(), \PDO::PARAM_INT); - - return $stmt; - } - - /** - * Returns an update statement supported by the database for writing session data. - */ - private function getUpdateStatement(string $sessionId, string $sessionData, int $maxlifetime): \PDOStatement - { - switch ($this->driver) { - case 'oci': - $data = fopen('php://memory', 'r+'); - fwrite($data, $sessionData); - rewind($data); - $sql = "UPDATE $this->table SET $this->dataCol = EMPTY_BLOB(), $this->lifetimeCol = :expiry, $this->timeCol = :time WHERE $this->idCol = :id RETURNING $this->dataCol into :data"; - break; - default: - $data = $sessionData; - $sql = "UPDATE $this->table SET $this->dataCol = :data, $this->lifetimeCol = :expiry, $this->timeCol = :time WHERE $this->idCol = :id"; - break; - } - - $stmt = $this->pdo->prepare($sql); - $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $stmt->bindParam(':data', $data, \PDO::PARAM_LOB); - $stmt->bindValue(':expiry', time() + $maxlifetime, \PDO::PARAM_INT); - $stmt->bindValue(':time', time(), \PDO::PARAM_INT); - - return $stmt; - } - - /** - * Returns a merge/upsert (i.e. insert or update) statement when supported by the database for writing session data. - */ - private function getMergeStatement(string $sessionId, string $data, int $maxlifetime): ?\PDOStatement - { - switch (true) { - case 'mysql' === $this->driver: - $mergeSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time) ". - "ON DUPLICATE KEY UPDATE $this->dataCol = VALUES($this->dataCol), $this->lifetimeCol = VALUES($this->lifetimeCol), $this->timeCol = VALUES($this->timeCol)"; - break; - case 'sqlsrv' === $this->driver && version_compare($this->pdo->getAttribute(\PDO::ATTR_SERVER_VERSION), '10', '>='): - // MERGE is only available since SQL Server 2008 and must be terminated by semicolon - // It also requires HOLDLOCK according to https://weblogs.sqlteam.com/dang/2009/01/31/upsert-race-condition-with-merge/ - $mergeSql = "MERGE INTO $this->table WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ($this->idCol = ?) ". - "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ". - "WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?;"; - break; - case 'sqlite' === $this->driver: - $mergeSql = "INSERT OR REPLACE INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time)"; - break; - case 'pgsql' === $this->driver && version_compare($this->pdo->getAttribute(\PDO::ATTR_SERVER_VERSION), '9.5', '>='): - $mergeSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time) ". - "ON CONFLICT ($this->idCol) DO UPDATE SET ($this->dataCol, $this->lifetimeCol, $this->timeCol) = (EXCLUDED.$this->dataCol, EXCLUDED.$this->lifetimeCol, EXCLUDED.$this->timeCol)"; - break; - default: - // MERGE is not supported with LOBs: https://oracle.com/technetwork/articles/fuecks-lobs-095315.html - return null; - } - - $mergeStmt = $this->pdo->prepare($mergeSql); - - if ('sqlsrv' === $this->driver) { - $mergeStmt->bindParam(1, $sessionId, \PDO::PARAM_STR); - $mergeStmt->bindParam(2, $sessionId, \PDO::PARAM_STR); - $mergeStmt->bindParam(3, $data, \PDO::PARAM_LOB); - $mergeStmt->bindValue(4, time() + $maxlifetime, \PDO::PARAM_INT); - $mergeStmt->bindValue(5, time(), \PDO::PARAM_INT); - $mergeStmt->bindParam(6, $data, \PDO::PARAM_LOB); - $mergeStmt->bindValue(7, time() + $maxlifetime, \PDO::PARAM_INT); - $mergeStmt->bindValue(8, time(), \PDO::PARAM_INT); - } else { - $mergeStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $mergeStmt->bindParam(':data', $data, \PDO::PARAM_LOB); - $mergeStmt->bindValue(':expiry', time() + $maxlifetime, \PDO::PARAM_INT); - $mergeStmt->bindValue(':time', time(), \PDO::PARAM_INT); - } - - return $mergeStmt; - } - - /** - * Return a PDO instance. - * - * @return \PDO - */ - protected function getConnection() - { - if (null === $this->pdo) { - $this->connect($this->dsn ?: \ini_get('session.save_path')); - } - - return $this->pdo; - } -} diff --git a/lib/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php b/lib/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php deleted file mode 100644 index 31954e677..000000000 --- a/lib/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php +++ /dev/null @@ -1,137 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -use Predis\Response\ErrorInterface; -use Symfony\Component\Cache\Traits\RedisClusterProxy; -use Symfony\Component\Cache\Traits\RedisProxy; - -/** - * Redis based session storage handler based on the Redis class - * provided by the PHP redis extension. - * - * @author Dalibor Karlović <dalibor@flexolabs.io> - */ -class RedisSessionHandler extends AbstractSessionHandler -{ - private $redis; - - /** - * @var string Key prefix for shared environments - */ - private $prefix; - - /** - * @var int Time to live in seconds - */ - private $ttl; - - /** - * List of available options: - * * prefix: The prefix to use for the keys in order to avoid collision on the Redis server - * * ttl: The time to live in seconds. - * - * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis - * - * @throws \InvalidArgumentException When unsupported client or options are passed - */ - public function __construct($redis, array $options = []) - { - if ( - !$redis instanceof \Redis && - !$redis instanceof \RedisArray && - !$redis instanceof \RedisCluster && - !$redis instanceof \Predis\ClientInterface && - !$redis instanceof RedisProxy && - !$redis instanceof RedisClusterProxy - ) { - throw new \InvalidArgumentException(sprintf('"%s()" expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\ClientInterface, "%s" given.', __METHOD__, get_debug_type($redis))); - } - - if ($diff = array_diff(array_keys($options), ['prefix', 'ttl'])) { - throw new \InvalidArgumentException(sprintf('The following options are not supported "%s".', implode(', ', $diff))); - } - - $this->redis = $redis; - $this->prefix = $options['prefix'] ?? 'sf_s'; - $this->ttl = $options['ttl'] ?? null; - } - - /** - * {@inheritdoc} - */ - protected function doRead(string $sessionId): string - { - return $this->redis->get($this->prefix.$sessionId) ?: ''; - } - - /** - * {@inheritdoc} - */ - protected function doWrite(string $sessionId, string $data): bool - { - $result = $this->redis->setEx($this->prefix.$sessionId, (int) ($this->ttl ?? \ini_get('session.gc_maxlifetime')), $data); - - return $result && !$result instanceof ErrorInterface; - } - - /** - * {@inheritdoc} - */ - protected function doDestroy(string $sessionId): bool - { - static $unlink = true; - - if ($unlink) { - try { - $unlink = false !== $this->redis->unlink($this->prefix.$sessionId); - } catch (\Throwable $e) { - $unlink = false; - } - } - - if (!$unlink) { - $this->redis->del($this->prefix.$sessionId); - } - - return true; - } - - /** - * {@inheritdoc} - */ - #[\ReturnTypeWillChange] - public function close(): bool - { - return true; - } - - /** - * {@inheritdoc} - * - * @return int|false - */ - #[\ReturnTypeWillChange] - public function gc($maxlifetime) - { - return 0; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function updateTimestamp($sessionId, $data) - { - return (bool) $this->redis->expire($this->prefix.$sessionId, (int) ($this->ttl ?? \ini_get('session.gc_maxlifetime'))); - } -} diff --git a/lib/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php b/lib/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php deleted file mode 100644 index f3f7b201d..000000000 --- a/lib/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -use Doctrine\DBAL\DriverManager; -use Symfony\Component\Cache\Adapter\AbstractAdapter; -use Symfony\Component\Cache\Traits\RedisClusterProxy; -use Symfony\Component\Cache\Traits\RedisProxy; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class SessionHandlerFactory -{ - /** - * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy|\Memcached|\PDO|string $connection Connection or DSN - */ - public static function createHandler($connection): AbstractSessionHandler - { - if (!\is_string($connection) && !\is_object($connection)) { - throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a string or a connection object, "%s" given.', __METHOD__, get_debug_type($connection))); - } - - if ($options = \is_string($connection) ? parse_url($connection) : false) { - parse_str($options['query'] ?? '', $options); - } - - switch (true) { - case $connection instanceof \Redis: - case $connection instanceof \RedisArray: - case $connection instanceof \RedisCluster: - case $connection instanceof \Predis\ClientInterface: - case $connection instanceof RedisProxy: - case $connection instanceof RedisClusterProxy: - return new RedisSessionHandler($connection); - - case $connection instanceof \Memcached: - return new MemcachedSessionHandler($connection); - - case $connection instanceof \PDO: - return new PdoSessionHandler($connection); - - case !\is_string($connection): - throw new \InvalidArgumentException(sprintf('Unsupported Connection: "%s".', get_debug_type($connection))); - case str_starts_with($connection, 'file://'): - $savePath = substr($connection, 7); - - return new StrictSessionHandler(new NativeFileSessionHandler('' === $savePath ? null : $savePath)); - - case str_starts_with($connection, 'redis:'): - case str_starts_with($connection, 'rediss:'): - case str_starts_with($connection, 'memcached:'): - if (!class_exists(AbstractAdapter::class)) { - throw new \InvalidArgumentException(sprintf('Unsupported DSN "%s". Try running "composer require symfony/cache".', $connection)); - } - $handlerClass = str_starts_with($connection, 'memcached:') ? MemcachedSessionHandler::class : RedisSessionHandler::class; - $connection = AbstractAdapter::createConnection($connection, ['lazy' => true]); - - return new $handlerClass($connection, array_intersect_key($options ?: [], ['prefix' => 1, 'ttl' => 1])); - - case str_starts_with($connection, 'pdo_oci://'): - if (!class_exists(DriverManager::class)) { - throw new \InvalidArgumentException(sprintf('Unsupported DSN "%s". Try running "composer require doctrine/dbal".', $connection)); - } - $connection = DriverManager::getConnection(['url' => $connection])->getWrappedConnection(); - // no break; - - case str_starts_with($connection, 'mssql://'): - case str_starts_with($connection, 'mysql://'): - case str_starts_with($connection, 'mysql2://'): - case str_starts_with($connection, 'pgsql://'): - case str_starts_with($connection, 'postgres://'): - case str_starts_with($connection, 'postgresql://'): - case str_starts_with($connection, 'sqlsrv://'): - case str_starts_with($connection, 'sqlite://'): - case str_starts_with($connection, 'sqlite3://'): - return new PdoSessionHandler($connection, $options ?: []); - } - - throw new \InvalidArgumentException(sprintf('Unsupported Connection: "%s".', $connection)); - } -} diff --git a/lib/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php b/lib/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php deleted file mode 100644 index f7c385f64..000000000 --- a/lib/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php +++ /dev/null @@ -1,118 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * Adds basic `SessionUpdateTimestampHandlerInterface` behaviors to another `SessionHandlerInterface`. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class StrictSessionHandler extends AbstractSessionHandler -{ - private $handler; - private $doDestroy; - - public function __construct(\SessionHandlerInterface $handler) - { - if ($handler instanceof \SessionUpdateTimestampHandlerInterface) { - throw new \LogicException(sprintf('"%s" is already an instance of "SessionUpdateTimestampHandlerInterface", you cannot wrap it with "%s".', get_debug_type($handler), self::class)); - } - - $this->handler = $handler; - } - - /** - * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler. - * - * @internal - */ - public function isWrapper(): bool - { - return $this->handler instanceof \SessionHandler; - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function open($savePath, $sessionName) - { - parent::open($savePath, $sessionName); - - return $this->handler->open($savePath, $sessionName); - } - - /** - * {@inheritdoc} - */ - protected function doRead(string $sessionId) - { - return $this->handler->read($sessionId); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function updateTimestamp($sessionId, $data) - { - return $this->write($sessionId, $data); - } - - /** - * {@inheritdoc} - */ - protected function doWrite(string $sessionId, string $data) - { - return $this->handler->write($sessionId, $data); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function destroy($sessionId) - { - $this->doDestroy = true; - $destroyed = parent::destroy($sessionId); - - return $this->doDestroy ? $this->doDestroy($sessionId) : $destroyed; - } - - /** - * {@inheritdoc} - */ - protected function doDestroy(string $sessionId) - { - $this->doDestroy = false; - - return $this->handler->destroy($sessionId); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function close() - { - return $this->handler->close(); - } - - /** - * @return int|false - */ - #[\ReturnTypeWillChange] - public function gc($maxlifetime) - { - return $this->handler->gc($maxlifetime); - } -} diff --git a/lib/symfony/http-foundation/Session/Storage/MetadataBag.php b/lib/symfony/http-foundation/Session/Storage/MetadataBag.php deleted file mode 100644 index 595a9e23c..000000000 --- a/lib/symfony/http-foundation/Session/Storage/MetadataBag.php +++ /dev/null @@ -1,167 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; - -/** - * Metadata container. - * - * Adds metadata to the session. - * - * @author Drak <drak@zikula.org> - */ -class MetadataBag implements SessionBagInterface -{ - public const CREATED = 'c'; - public const UPDATED = 'u'; - public const LIFETIME = 'l'; - - /** - * @var string - */ - private $name = '__metadata'; - - /** - * @var string - */ - private $storageKey; - - /** - * @var array - */ - protected $meta = [self::CREATED => 0, self::UPDATED => 0, self::LIFETIME => 0]; - - /** - * Unix timestamp. - * - * @var int - */ - private $lastUsed; - - /** - * @var int - */ - private $updateThreshold; - - /** - * @param string $storageKey The key used to store bag in the session - * @param int $updateThreshold The time to wait between two UPDATED updates - */ - public function __construct(string $storageKey = '_sf2_meta', int $updateThreshold = 0) - { - $this->storageKey = $storageKey; - $this->updateThreshold = $updateThreshold; - } - - /** - * {@inheritdoc} - */ - public function initialize(array &$array) - { - $this->meta = &$array; - - if (isset($array[self::CREATED])) { - $this->lastUsed = $this->meta[self::UPDATED]; - - $timeStamp = time(); - if ($timeStamp - $array[self::UPDATED] >= $this->updateThreshold) { - $this->meta[self::UPDATED] = $timeStamp; - } - } else { - $this->stampCreated(); - } - } - - /** - * Gets the lifetime that the session cookie was set with. - * - * @return int - */ - public function getLifetime() - { - return $this->meta[self::LIFETIME]; - } - - /** - * Stamps a new session's metadata. - * - * @param int $lifetime Sets the cookie lifetime for the session cookie. A null value - * will leave the system settings unchanged, 0 sets the cookie - * to expire with browser session. Time is in seconds, and is - * not a Unix timestamp. - */ - public function stampNew(int $lifetime = null) - { - $this->stampCreated($lifetime); - } - - /** - * {@inheritdoc} - */ - public function getStorageKey() - { - return $this->storageKey; - } - - /** - * Gets the created timestamp metadata. - * - * @return int Unix timestamp - */ - public function getCreated() - { - return $this->meta[self::CREATED]; - } - - /** - * Gets the last used metadata. - * - * @return int Unix timestamp - */ - public function getLastUsed() - { - return $this->lastUsed; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - // nothing to do - return null; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->name; - } - - /** - * Sets name. - */ - public function setName(string $name) - { - $this->name = $name; - } - - private function stampCreated(int $lifetime = null): void - { - $timeStamp = time(); - $this->meta[self::CREATED] = $this->meta[self::UPDATED] = $this->lastUsed = $timeStamp; - $this->meta[self::LIFETIME] = $lifetime ?? (int) \ini_get('session.cookie_lifetime'); - } -} diff --git a/lib/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php b/lib/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php deleted file mode 100644 index c5c2bb073..000000000 --- a/lib/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php +++ /dev/null @@ -1,252 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; - -/** - * MockArraySessionStorage mocks the session for unit tests. - * - * No PHP session is actually started since a session can be initialized - * and shutdown only once per PHP execution cycle. - * - * When doing functional testing, you should use MockFileSessionStorage instead. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Bulat Shakirzyanov <mallluhuct@gmail.com> - * @author Drak <drak@zikula.org> - */ -class MockArraySessionStorage implements SessionStorageInterface -{ - /** - * @var string - */ - protected $id = ''; - - /** - * @var string - */ - protected $name; - - /** - * @var bool - */ - protected $started = false; - - /** - * @var bool - */ - protected $closed = false; - - /** - * @var array - */ - protected $data = []; - - /** - * @var MetadataBag - */ - protected $metadataBag; - - /** - * @var array|SessionBagInterface[] - */ - protected $bags = []; - - public function __construct(string $name = 'MOCKSESSID', MetadataBag $metaBag = null) - { - $this->name = $name; - $this->setMetadataBag($metaBag); - } - - public function setSessionData(array $array) - { - $this->data = $array; - } - - /** - * {@inheritdoc} - */ - public function start() - { - if ($this->started) { - return true; - } - - if (empty($this->id)) { - $this->id = $this->generateId(); - } - - $this->loadSession(); - - return true; - } - - /** - * {@inheritdoc} - */ - public function regenerate(bool $destroy = false, int $lifetime = null) - { - if (!$this->started) { - $this->start(); - } - - $this->metadataBag->stampNew($lifetime); - $this->id = $this->generateId(); - - return true; - } - - /** - * {@inheritdoc} - */ - public function getId() - { - return $this->id; - } - - /** - * {@inheritdoc} - */ - public function setId(string $id) - { - if ($this->started) { - throw new \LogicException('Cannot set session ID after the session has started.'); - } - - $this->id = $id; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->name; - } - - /** - * {@inheritdoc} - */ - public function setName(string $name) - { - $this->name = $name; - } - - /** - * {@inheritdoc} - */ - public function save() - { - if (!$this->started || $this->closed) { - throw new \RuntimeException('Trying to save a session that was not started yet or was already closed.'); - } - // nothing to do since we don't persist the session data - $this->closed = false; - $this->started = false; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - // clear out the bags - foreach ($this->bags as $bag) { - $bag->clear(); - } - - // clear out the session - $this->data = []; - - // reconnect the bags to the session - $this->loadSession(); - } - - /** - * {@inheritdoc} - */ - public function registerBag(SessionBagInterface $bag) - { - $this->bags[$bag->getName()] = $bag; - } - - /** - * {@inheritdoc} - */ - public function getBag(string $name) - { - if (!isset($this->bags[$name])) { - throw new \InvalidArgumentException(sprintf('The SessionBagInterface "%s" is not registered.', $name)); - } - - if (!$this->started) { - $this->start(); - } - - return $this->bags[$name]; - } - - /** - * {@inheritdoc} - */ - public function isStarted() - { - return $this->started; - } - - public function setMetadataBag(MetadataBag $bag = null) - { - if (null === $bag) { - $bag = new MetadataBag(); - } - - $this->metadataBag = $bag; - } - - /** - * Gets the MetadataBag. - * - * @return MetadataBag - */ - public function getMetadataBag() - { - return $this->metadataBag; - } - - /** - * Generates a session ID. - * - * This doesn't need to be particularly cryptographically secure since this is just - * a mock. - * - * @return string - */ - protected function generateId() - { - return hash('sha256', uniqid('ss_mock_', true)); - } - - protected function loadSession() - { - $bags = array_merge($this->bags, [$this->metadataBag]); - - foreach ($bags as $bag) { - $key = $bag->getStorageKey(); - $this->data[$key] = $this->data[$key] ?? []; - $bag->initialize($this->data[$key]); - } - - $this->started = true; - $this->closed = false; - } -} diff --git a/lib/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php b/lib/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php deleted file mode 100644 index 8e32a45e3..000000000 --- a/lib/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php +++ /dev/null @@ -1,160 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -/** - * MockFileSessionStorage is used to mock sessions for - * functional testing where you may need to persist session data - * across separate PHP processes. - * - * No PHP session is actually started since a session can be initialized - * and shutdown only once per PHP execution cycle and this class does - * not pollute any session related globals, including session_*() functions - * or session.* PHP ini directives. - * - * @author Drak <drak@zikula.org> - */ -class MockFileSessionStorage extends MockArraySessionStorage -{ - private $savePath; - - /** - * @param string|null $savePath Path of directory to save session files - */ - public function __construct(string $savePath = null, string $name = 'MOCKSESSID', MetadataBag $metaBag = null) - { - if (null === $savePath) { - $savePath = sys_get_temp_dir(); - } - - if (!is_dir($savePath) && !@mkdir($savePath, 0777, true) && !is_dir($savePath)) { - throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s".', $savePath)); - } - - $this->savePath = $savePath; - - parent::__construct($name, $metaBag); - } - - /** - * {@inheritdoc} - */ - public function start() - { - if ($this->started) { - return true; - } - - if (!$this->id) { - $this->id = $this->generateId(); - } - - $this->read(); - - $this->started = true; - - return true; - } - - /** - * {@inheritdoc} - */ - public function regenerate(bool $destroy = false, int $lifetime = null) - { - if (!$this->started) { - $this->start(); - } - - if ($destroy) { - $this->destroy(); - } - - return parent::regenerate($destroy, $lifetime); - } - - /** - * {@inheritdoc} - */ - public function save() - { - if (!$this->started) { - throw new \RuntimeException('Trying to save a session that was not started yet or was already closed.'); - } - - $data = $this->data; - - foreach ($this->bags as $bag) { - if (empty($data[$key = $bag->getStorageKey()])) { - unset($data[$key]); - } - } - if ([$key = $this->metadataBag->getStorageKey()] === array_keys($data)) { - unset($data[$key]); - } - - try { - if ($data) { - $path = $this->getFilePath(); - $tmp = $path.bin2hex(random_bytes(6)); - file_put_contents($tmp, serialize($data)); - rename($tmp, $path); - } else { - $this->destroy(); - } - } finally { - $this->data = $data; - } - - // this is needed when the session object is re-used across multiple requests - // in functional tests. - $this->started = false; - } - - /** - * Deletes a session from persistent storage. - * Deliberately leaves session data in memory intact. - */ - private function destroy(): void - { - set_error_handler(static function () {}); - try { - unlink($this->getFilePath()); - } finally { - restore_error_handler(); - } - } - - /** - * Calculate path to file. - */ - private function getFilePath(): string - { - return $this->savePath.'/'.$this->id.'.mocksess'; - } - - /** - * Reads session from storage and loads session. - */ - private function read(): void - { - set_error_handler(static function () {}); - try { - $data = file_get_contents($this->getFilePath()); - } finally { - restore_error_handler(); - } - - $this->data = $data ? unserialize($data) : []; - - $this->loadSession(); - } -} diff --git a/lib/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php b/lib/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php deleted file mode 100644 index d0da1e169..000000000 --- a/lib/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Request; - -// Help opcache.preload discover always-needed symbols -class_exists(MockFileSessionStorage::class); - -/** - * @author Jérémy Derussé <jeremy@derusse.com> - */ -class MockFileSessionStorageFactory implements SessionStorageFactoryInterface -{ - private $savePath; - private $name; - private $metaBag; - - /** - * @see MockFileSessionStorage constructor. - */ - public function __construct(string $savePath = null, string $name = 'MOCKSESSID', MetadataBag $metaBag = null) - { - $this->savePath = $savePath; - $this->name = $name; - $this->metaBag = $metaBag; - } - - public function createStorage(?Request $request): SessionStorageInterface - { - return new MockFileSessionStorage($this->savePath, $this->name, $this->metaBag); - } -} diff --git a/lib/symfony/http-foundation/Session/Storage/NativeSessionStorage.php b/lib/symfony/http-foundation/Session/Storage/NativeSessionStorage.php deleted file mode 100644 index a50c8270f..000000000 --- a/lib/symfony/http-foundation/Session/Storage/NativeSessionStorage.php +++ /dev/null @@ -1,506 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; -use Symfony\Component\HttpFoundation\Session\SessionUtils; -use Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler; -use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; -use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; - -// Help opcache.preload discover always-needed symbols -class_exists(MetadataBag::class); -class_exists(StrictSessionHandler::class); -class_exists(SessionHandlerProxy::class); - -/** - * This provides a base class for session attribute storage. - * - * @author Drak <drak@zikula.org> - */ -class NativeSessionStorage implements SessionStorageInterface -{ - /** - * @var SessionBagInterface[] - */ - protected $bags = []; - - /** - * @var bool - */ - protected $started = false; - - /** - * @var bool - */ - protected $closed = false; - - /** - * @var AbstractProxy|\SessionHandlerInterface - */ - protected $saveHandler; - - /** - * @var MetadataBag - */ - protected $metadataBag; - - /** - * @var string|null - */ - private $emulateSameSite; - - /** - * Depending on how you want the storage driver to behave you probably - * want to override this constructor entirely. - * - * List of options for $options array with their defaults. - * - * @see https://php.net/session.configuration for options - * but we omit 'session.' from the beginning of the keys for convenience. - * - * ("auto_start", is not supported as it tells PHP to start a session before - * PHP starts to execute user-land code. Setting during runtime has no effect). - * - * cache_limiter, "" (use "0" to prevent headers from being sent entirely). - * cache_expire, "0" - * cookie_domain, "" - * cookie_httponly, "" - * cookie_lifetime, "0" - * cookie_path, "/" - * cookie_secure, "" - * cookie_samesite, null - * gc_divisor, "100" - * gc_maxlifetime, "1440" - * gc_probability, "1" - * lazy_write, "1" - * name, "PHPSESSID" - * referer_check, "" - * serialize_handler, "php" - * use_strict_mode, "1" - * use_cookies, "1" - * use_only_cookies, "1" - * use_trans_sid, "0" - * sid_length, "32" - * sid_bits_per_character, "5" - * trans_sid_hosts, $_SERVER['HTTP_HOST'] - * trans_sid_tags, "a=href,area=href,frame=src,form=" - * - * @param AbstractProxy|\SessionHandlerInterface|null $handler - */ - public function __construct(array $options = [], $handler = null, MetadataBag $metaBag = null) - { - if (!\extension_loaded('session')) { - throw new \LogicException('PHP extension "session" is required.'); - } - - $options += [ - 'cache_limiter' => '', - 'cache_expire' => 0, - 'use_cookies' => 1, - 'lazy_write' => 1, - 'use_strict_mode' => 1, - ]; - - session_register_shutdown(); - - $this->setMetadataBag($metaBag); - $this->setOptions($options); - $this->setSaveHandler($handler); - } - - /** - * Gets the save handler instance. - * - * @return AbstractProxy|\SessionHandlerInterface - */ - public function getSaveHandler() - { - return $this->saveHandler; - } - - /** - * {@inheritdoc} - */ - public function start() - { - if ($this->started) { - return true; - } - - if (\PHP_SESSION_ACTIVE === session_status()) { - throw new \RuntimeException('Failed to start the session: already started by PHP.'); - } - - if (filter_var(\ini_get('session.use_cookies'), \FILTER_VALIDATE_BOOLEAN) && headers_sent($file, $line)) { - throw new \RuntimeException(sprintf('Failed to start the session because headers have already been sent by "%s" at line %d.', $file, $line)); - } - - $sessionId = $_COOKIE[session_name()] ?? null; - /* - * Explanation of the session ID regular expression: `/^[a-zA-Z0-9,-]{22,250}$/`. - * - * ---------- Part 1 - * - * The part `[a-zA-Z0-9,-]` is related to the PHP ini directive `session.sid_bits_per_character` defined as 6. - * See https://www.php.net/manual/en/session.configuration.php#ini.session.sid-bits-per-character. - * Allowed values are integers such as: - * - 4 for range `a-f0-9` - * - 5 for range `a-v0-9` - * - 6 for range `a-zA-Z0-9,-` - * - * ---------- Part 2 - * - * The part `{22,250}` is related to the PHP ini directive `session.sid_length`. - * See https://www.php.net/manual/en/session.configuration.php#ini.session.sid-length. - * Allowed values are integers between 22 and 256, but we use 250 for the max. - * - * Where does the 250 come from? - * - The length of Windows and Linux filenames is limited to 255 bytes. Then the max must not exceed 255. - * - The session filename prefix is `sess_`, a 5 bytes string. Then the max must not exceed 255 - 5 = 250. - * - * ---------- Conclusion - * - * The parts 1 and 2 prevent the warning below: - * `PHP Warning: SessionHandler::read(): Session ID is too long or contains illegal characters. Only the A-Z, a-z, 0-9, "-", and "," characters are allowed.` - * - * The part 2 prevents the warning below: - * `PHP Warning: SessionHandler::read(): open(filepath, O_RDWR) failed: No such file or directory (2).` - */ - if ($sessionId && $this->saveHandler instanceof AbstractProxy && 'files' === $this->saveHandler->getSaveHandlerName() && !preg_match('/^[a-zA-Z0-9,-]{22,250}$/', $sessionId)) { - // the session ID in the header is invalid, create a new one - session_id(session_create_id()); - } - - // ok to try and start the session - if (!session_start()) { - throw new \RuntimeException('Failed to start the session.'); - } - - if (null !== $this->emulateSameSite) { - $originalCookie = SessionUtils::popSessionCookie(session_name(), session_id()); - if (null !== $originalCookie) { - header(sprintf('%s; SameSite=%s', $originalCookie, $this->emulateSameSite), false); - } - } - - $this->loadSession(); - - return true; - } - - /** - * {@inheritdoc} - */ - public function getId() - { - return $this->saveHandler->getId(); - } - - /** - * {@inheritdoc} - */ - public function setId(string $id) - { - $this->saveHandler->setId($id); - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->saveHandler->getName(); - } - - /** - * {@inheritdoc} - */ - public function setName(string $name) - { - $this->saveHandler->setName($name); - } - - /** - * {@inheritdoc} - */ - public function regenerate(bool $destroy = false, int $lifetime = null) - { - // Cannot regenerate the session ID for non-active sessions. - if (\PHP_SESSION_ACTIVE !== session_status()) { - return false; - } - - if (headers_sent()) { - return false; - } - - if (null !== $lifetime && $lifetime != \ini_get('session.cookie_lifetime')) { - $this->save(); - ini_set('session.cookie_lifetime', $lifetime); - $this->start(); - } - - if ($destroy) { - $this->metadataBag->stampNew(); - } - - $isRegenerated = session_regenerate_id($destroy); - - if (null !== $this->emulateSameSite) { - $originalCookie = SessionUtils::popSessionCookie(session_name(), session_id()); - if (null !== $originalCookie) { - header(sprintf('%s; SameSite=%s', $originalCookie, $this->emulateSameSite), false); - } - } - - return $isRegenerated; - } - - /** - * {@inheritdoc} - */ - public function save() - { - // Store a copy so we can restore the bags in case the session was not left empty - $session = $_SESSION; - - foreach ($this->bags as $bag) { - if (empty($_SESSION[$key = $bag->getStorageKey()])) { - unset($_SESSION[$key]); - } - } - if ($_SESSION && [$key = $this->metadataBag->getStorageKey()] === array_keys($_SESSION)) { - unset($_SESSION[$key]); - } - - // Register error handler to add information about the current save handler - $previousHandler = set_error_handler(function ($type, $msg, $file, $line) use (&$previousHandler) { - if (\E_WARNING === $type && str_starts_with($msg, 'session_write_close():')) { - $handler = $this->saveHandler instanceof SessionHandlerProxy ? $this->saveHandler->getHandler() : $this->saveHandler; - $msg = sprintf('session_write_close(): Failed to write session data with "%s" handler', \get_class($handler)); - } - - return $previousHandler ? $previousHandler($type, $msg, $file, $line) : false; - }); - - try { - session_write_close(); - } finally { - restore_error_handler(); - - // Restore only if not empty - if ($_SESSION) { - $_SESSION = $session; - } - } - - $this->closed = true; - $this->started = false; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - // clear out the bags - foreach ($this->bags as $bag) { - $bag->clear(); - } - - // clear out the session - $_SESSION = []; - - // reconnect the bags to the session - $this->loadSession(); - } - - /** - * {@inheritdoc} - */ - public function registerBag(SessionBagInterface $bag) - { - if ($this->started) { - throw new \LogicException('Cannot register a bag when the session is already started.'); - } - - $this->bags[$bag->getName()] = $bag; - } - - /** - * {@inheritdoc} - */ - public function getBag(string $name) - { - if (!isset($this->bags[$name])) { - throw new \InvalidArgumentException(sprintf('The SessionBagInterface "%s" is not registered.', $name)); - } - - if (!$this->started && $this->saveHandler->isActive()) { - $this->loadSession(); - } elseif (!$this->started) { - $this->start(); - } - - return $this->bags[$name]; - } - - public function setMetadataBag(MetadataBag $metaBag = null) - { - if (null === $metaBag) { - $metaBag = new MetadataBag(); - } - - $this->metadataBag = $metaBag; - } - - /** - * Gets the MetadataBag. - * - * @return MetadataBag - */ - public function getMetadataBag() - { - return $this->metadataBag; - } - - /** - * {@inheritdoc} - */ - public function isStarted() - { - return $this->started; - } - - /** - * Sets session.* ini variables. - * - * For convenience we omit 'session.' from the beginning of the keys. - * Explicitly ignores other ini keys. - * - * @param array $options Session ini directives [key => value] - * - * @see https://php.net/session.configuration - */ - public function setOptions(array $options) - { - if (headers_sent() || \PHP_SESSION_ACTIVE === session_status()) { - return; - } - - $validOptions = array_flip([ - 'cache_expire', 'cache_limiter', 'cookie_domain', 'cookie_httponly', - 'cookie_lifetime', 'cookie_path', 'cookie_secure', 'cookie_samesite', - 'gc_divisor', 'gc_maxlifetime', 'gc_probability', - 'lazy_write', 'name', 'referer_check', - 'serialize_handler', 'use_strict_mode', 'use_cookies', - 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled', - 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name', - 'upload_progress.freq', 'upload_progress.min_freq', 'url_rewriter.tags', - 'sid_length', 'sid_bits_per_character', 'trans_sid_hosts', 'trans_sid_tags', - ]); - - foreach ($options as $key => $value) { - if (isset($validOptions[$key])) { - if (str_starts_with($key, 'upload_progress.')) { - trigger_deprecation('symfony/http-foundation', '5.4', 'Support for the "%s" session option is deprecated. The settings prefixed with "session.upload_progress." can not be changed at runtime.', $key); - continue; - } - if ('url_rewriter.tags' === $key) { - trigger_deprecation('symfony/http-foundation', '5.4', 'Support for the "%s" session option is deprecated. Use "trans_sid_tags" instead.', $key); - } - if ('cookie_samesite' === $key && \PHP_VERSION_ID < 70300) { - // PHP < 7.3 does not support same_site cookies. We will emulate it in - // the start() method instead. - $this->emulateSameSite = $value; - continue; - } - if ('cookie_secure' === $key && 'auto' === $value) { - continue; - } - ini_set('url_rewriter.tags' !== $key ? 'session.'.$key : $key, $value); - } - } - } - - /** - * Registers session save handler as a PHP session handler. - * - * To use internal PHP session save handlers, override this method using ini_set with - * session.save_handler and session.save_path e.g. - * - * ini_set('session.save_handler', 'files'); - * ini_set('session.save_path', '/tmp'); - * - * or pass in a \SessionHandler instance which configures session.save_handler in the - * constructor, for a template see NativeFileSessionHandler. - * - * @see https://php.net/session-set-save-handler - * @see https://php.net/sessionhandlerinterface - * @see https://php.net/sessionhandler - * - * @param AbstractProxy|\SessionHandlerInterface|null $saveHandler - * - * @throws \InvalidArgumentException - */ - public function setSaveHandler($saveHandler = null) - { - if (!$saveHandler instanceof AbstractProxy && - !$saveHandler instanceof \SessionHandlerInterface && - null !== $saveHandler) { - throw new \InvalidArgumentException('Must be instance of AbstractProxy; implement \SessionHandlerInterface; or be null.'); - } - - // Wrap $saveHandler in proxy and prevent double wrapping of proxy - if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) { - $saveHandler = new SessionHandlerProxy($saveHandler); - } elseif (!$saveHandler instanceof AbstractProxy) { - $saveHandler = new SessionHandlerProxy(new StrictSessionHandler(new \SessionHandler())); - } - $this->saveHandler = $saveHandler; - - if (headers_sent() || \PHP_SESSION_ACTIVE === session_status()) { - return; - } - - if ($this->saveHandler instanceof SessionHandlerProxy) { - session_set_save_handler($this->saveHandler, false); - } - } - - /** - * Load the session with attributes. - * - * After starting the session, PHP retrieves the session from whatever handlers - * are set to (either PHP's internal, or a custom save handler set with session_set_save_handler()). - * PHP takes the return value from the read() handler, unserializes it - * and populates $_SESSION with the result automatically. - */ - protected function loadSession(array &$session = null) - { - if (null === $session) { - $session = &$_SESSION; - } - - $bags = array_merge($this->bags, [$this->metadataBag]); - - foreach ($bags as $bag) { - $key = $bag->getStorageKey(); - $session[$key] = isset($session[$key]) && \is_array($session[$key]) ? $session[$key] : []; - $bag->initialize($session[$key]); - } - - $this->started = true; - $this->closed = false; - } -} diff --git a/lib/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php b/lib/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php deleted file mode 100644 index a7d7411ff..000000000 --- a/lib/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Request; - -// Help opcache.preload discover always-needed symbols -class_exists(NativeSessionStorage::class); - -/** - * @author Jérémy Derussé <jeremy@derusse.com> - */ -class NativeSessionStorageFactory implements SessionStorageFactoryInterface -{ - private $options; - private $handler; - private $metaBag; - private $secure; - - /** - * @see NativeSessionStorage constructor. - */ - public function __construct(array $options = [], $handler = null, MetadataBag $metaBag = null, bool $secure = false) - { - $this->options = $options; - $this->handler = $handler; - $this->metaBag = $metaBag; - $this->secure = $secure; - } - - public function createStorage(?Request $request): SessionStorageInterface - { - $storage = new NativeSessionStorage($this->options, $this->handler, $this->metaBag); - if ($this->secure && $request && $request->isSecure()) { - $storage->setOptions(['cookie_secure' => true]); - } - - return $storage; - } -} diff --git a/lib/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php b/lib/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php deleted file mode 100644 index 72dbef134..000000000 --- a/lib/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; - -/** - * Allows session to be started by PHP and managed by Symfony. - * - * @author Drak <drak@zikula.org> - */ -class PhpBridgeSessionStorage extends NativeSessionStorage -{ - /** - * @param AbstractProxy|\SessionHandlerInterface|null $handler - */ - public function __construct($handler = null, MetadataBag $metaBag = null) - { - if (!\extension_loaded('session')) { - throw new \LogicException('PHP extension "session" is required.'); - } - - $this->setMetadataBag($metaBag); - $this->setSaveHandler($handler); - } - - /** - * {@inheritdoc} - */ - public function start() - { - if ($this->started) { - return true; - } - - $this->loadSession(); - - return true; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - // clear out the bags and nothing else that may be set - // since the purpose of this driver is to share a handler - foreach ($this->bags as $bag) { - $bag->clear(); - } - - // reconnect the bags to the session - $this->loadSession(); - } -} diff --git a/lib/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php b/lib/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php deleted file mode 100644 index 173ef71de..000000000 --- a/lib/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Request; - -// Help opcache.preload discover always-needed symbols -class_exists(PhpBridgeSessionStorage::class); - -/** - * @author Jérémy Derussé <jeremy@derusse.com> - */ -class PhpBridgeSessionStorageFactory implements SessionStorageFactoryInterface -{ - private $handler; - private $metaBag; - private $secure; - - /** - * @see PhpBridgeSessionStorage constructor. - */ - public function __construct($handler = null, MetadataBag $metaBag = null, bool $secure = false) - { - $this->handler = $handler; - $this->metaBag = $metaBag; - $this->secure = $secure; - } - - public function createStorage(?Request $request): SessionStorageInterface - { - $storage = new PhpBridgeSessionStorage($this->handler, $this->metaBag); - if ($this->secure && $request && $request->isSecure()) { - $storage->setOptions(['cookie_secure' => true]); - } - - return $storage; - } -} diff --git a/lib/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php b/lib/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php deleted file mode 100644 index edd04dff8..000000000 --- a/lib/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php +++ /dev/null @@ -1,118 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; - -/** - * @author Drak <drak@zikula.org> - */ -abstract class AbstractProxy -{ - /** - * Flag if handler wraps an internal PHP session handler (using \SessionHandler). - * - * @var bool - */ - protected $wrapper = false; - - /** - * @var string - */ - protected $saveHandlerName; - - /** - * Gets the session.save_handler name. - * - * @return string|null - */ - public function getSaveHandlerName() - { - return $this->saveHandlerName; - } - - /** - * Is this proxy handler and instance of \SessionHandlerInterface. - * - * @return bool - */ - public function isSessionHandlerInterface() - { - return $this instanceof \SessionHandlerInterface; - } - - /** - * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler. - * - * @return bool - */ - public function isWrapper() - { - return $this->wrapper; - } - - /** - * Has a session started? - * - * @return bool - */ - public function isActive() - { - return \PHP_SESSION_ACTIVE === session_status(); - } - - /** - * Gets the session ID. - * - * @return string - */ - public function getId() - { - return session_id(); - } - - /** - * Sets the session ID. - * - * @throws \LogicException - */ - public function setId(string $id) - { - if ($this->isActive()) { - throw new \LogicException('Cannot change the ID of an active session.'); - } - - session_id($id); - } - - /** - * Gets the session name. - * - * @return string - */ - public function getName() - { - return session_name(); - } - - /** - * Sets the session name. - * - * @throws \LogicException - */ - public function setName(string $name) - { - if ($this->isActive()) { - throw new \LogicException('Cannot change the name of an active session.'); - } - - session_name($name); - } -} diff --git a/lib/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php b/lib/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php deleted file mode 100644 index 0defa4a7a..000000000 --- a/lib/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php +++ /dev/null @@ -1,111 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; - -use Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler; - -/** - * @author Drak <drak@zikula.org> - */ -class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface -{ - protected $handler; - - public function __construct(\SessionHandlerInterface $handler) - { - $this->handler = $handler; - $this->wrapper = $handler instanceof \SessionHandler; - $this->saveHandlerName = $this->wrapper || ($handler instanceof StrictSessionHandler && $handler->isWrapper()) ? \ini_get('session.save_handler') : 'user'; - } - - /** - * @return \SessionHandlerInterface - */ - public function getHandler() - { - return $this->handler; - } - - // \SessionHandlerInterface - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function open($savePath, $sessionName) - { - return $this->handler->open($savePath, $sessionName); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function close() - { - return $this->handler->close(); - } - - /** - * @return string|false - */ - #[\ReturnTypeWillChange] - public function read($sessionId) - { - return $this->handler->read($sessionId); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function write($sessionId, $data) - { - return $this->handler->write($sessionId, $data); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function destroy($sessionId) - { - return $this->handler->destroy($sessionId); - } - - /** - * @return int|false - */ - #[\ReturnTypeWillChange] - public function gc($maxlifetime) - { - return $this->handler->gc($maxlifetime); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function validateId($sessionId) - { - return !$this->handler instanceof \SessionUpdateTimestampHandlerInterface || $this->handler->validateId($sessionId); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function updateTimestamp($sessionId, $data) - { - return $this->handler instanceof \SessionUpdateTimestampHandlerInterface ? $this->handler->updateTimestamp($sessionId, $data) : $this->write($sessionId, $data); - } -} diff --git a/lib/symfony/http-foundation/Session/Storage/ServiceSessionFactory.php b/lib/symfony/http-foundation/Session/Storage/ServiceSessionFactory.php deleted file mode 100644 index d17c60aeb..000000000 --- a/lib/symfony/http-foundation/Session/Storage/ServiceSessionFactory.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Request; - -/** - * @author Jérémy Derussé <jeremy@derusse.com> - * - * @internal to be removed in Symfony 6 - */ -final class ServiceSessionFactory implements SessionStorageFactoryInterface -{ - private $storage; - - public function __construct(SessionStorageInterface $storage) - { - $this->storage = $storage; - } - - public function createStorage(?Request $request): SessionStorageInterface - { - if ($this->storage instanceof NativeSessionStorage && $request && $request->isSecure()) { - $this->storage->setOptions(['cookie_secure' => true]); - } - - return $this->storage; - } -} diff --git a/lib/symfony/http-foundation/Session/Storage/SessionStorageFactoryInterface.php b/lib/symfony/http-foundation/Session/Storage/SessionStorageFactoryInterface.php deleted file mode 100644 index d03f0da4c..000000000 --- a/lib/symfony/http-foundation/Session/Storage/SessionStorageFactoryInterface.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Request; - -/** - * @author Jérémy Derussé <jeremy@derusse.com> - */ -interface SessionStorageFactoryInterface -{ - /** - * Creates a new instance of SessionStorageInterface. - */ - public function createStorage(?Request $request): SessionStorageInterface; -} diff --git a/lib/symfony/http-foundation/Session/Storage/SessionStorageInterface.php b/lib/symfony/http-foundation/Session/Storage/SessionStorageInterface.php deleted file mode 100644 index b7f66e7c7..000000000 --- a/lib/symfony/http-foundation/Session/Storage/SessionStorageInterface.php +++ /dev/null @@ -1,131 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; - -/** - * StorageInterface. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Drak <drak@zikula.org> - */ -interface SessionStorageInterface -{ - /** - * Starts the session. - * - * @return bool - * - * @throws \RuntimeException if something goes wrong starting the session - */ - public function start(); - - /** - * Checks if the session is started. - * - * @return bool - */ - public function isStarted(); - - /** - * Returns the session ID. - * - * @return string - */ - public function getId(); - - /** - * Sets the session ID. - */ - public function setId(string $id); - - /** - * Returns the session name. - * - * @return string - */ - public function getName(); - - /** - * Sets the session name. - */ - public function setName(string $name); - - /** - * Regenerates id that represents this storage. - * - * This method must invoke session_regenerate_id($destroy) unless - * this interface is used for a storage object designed for unit - * or functional testing where a real PHP session would interfere - * with testing. - * - * Note regenerate+destroy should not clear the session data in memory - * only delete the session data from persistent storage. - * - * Care: When regenerating the session ID no locking is involved in PHP's - * session design. See https://bugs.php.net/61470 for a discussion. - * So you must make sure the regenerated session is saved BEFORE sending the - * headers with the new ID. Symfony's HttpKernel offers a listener for this. - * See Symfony\Component\HttpKernel\EventListener\SaveSessionListener. - * Otherwise session data could get lost again for concurrent requests with the - * new ID. One result could be that you get logged out after just logging in. - * - * @param bool $destroy Destroy session when regenerating? - * @param int $lifetime Sets the cookie lifetime for the session cookie. A null value - * will leave the system settings unchanged, 0 sets the cookie - * to expire with browser session. Time is in seconds, and is - * not a Unix timestamp. - * - * @return bool - * - * @throws \RuntimeException If an error occurs while regenerating this storage - */ - public function regenerate(bool $destroy = false, int $lifetime = null); - - /** - * Force the session to be saved and closed. - * - * This method must invoke session_write_close() unless this interface is - * used for a storage object design for unit or functional testing where - * a real PHP session would interfere with testing, in which case - * it should actually persist the session data if required. - * - * @throws \RuntimeException if the session is saved without being started, or if the session - * is already closed - */ - public function save(); - - /** - * Clear all session data in memory. - */ - public function clear(); - - /** - * Gets a SessionBagInterface by name. - * - * @return SessionBagInterface - * - * @throws \InvalidArgumentException If the bag does not exist - */ - public function getBag(string $name); - - /** - * Registers a SessionBagInterface for use. - */ - public function registerBag(SessionBagInterface $bag); - - /** - * @return MetadataBag - */ - public function getMetadataBag(); -} diff --git a/lib/symfony/http-foundation/StreamedResponse.php b/lib/symfony/http-foundation/StreamedResponse.php deleted file mode 100644 index 676cd6687..000000000 --- a/lib/symfony/http-foundation/StreamedResponse.php +++ /dev/null @@ -1,139 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * StreamedResponse represents a streamed HTTP response. - * - * A StreamedResponse uses a callback for its content. - * - * The callback should use the standard PHP functions like echo - * to stream the response back to the client. The flush() function - * can also be used if needed. - * - * @see flush() - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class StreamedResponse extends Response -{ - protected $callback; - protected $streamed; - private $headersSent; - - public function __construct(callable $callback = null, int $status = 200, array $headers = []) - { - parent::__construct(null, $status, $headers); - - if (null !== $callback) { - $this->setCallback($callback); - } - $this->streamed = false; - $this->headersSent = false; - } - - /** - * Factory method for chainability. - * - * @param callable|null $callback A valid PHP callback or null to set it later - * - * @return static - * - * @deprecated since Symfony 5.1, use __construct() instead. - */ - public static function create($callback = null, int $status = 200, array $headers = []) - { - trigger_deprecation('symfony/http-foundation', '5.1', 'The "%s()" method is deprecated, use "new %s()" instead.', __METHOD__, static::class); - - return new static($callback, $status, $headers); - } - - /** - * Sets the PHP callback associated with this Response. - * - * @return $this - */ - public function setCallback(callable $callback) - { - $this->callback = $callback; - - return $this; - } - - /** - * {@inheritdoc} - * - * This method only sends the headers once. - * - * @return $this - */ - public function sendHeaders() - { - if ($this->headersSent) { - return $this; - } - - $this->headersSent = true; - - return parent::sendHeaders(); - } - - /** - * {@inheritdoc} - * - * This method only sends the content once. - * - * @return $this - */ - public function sendContent() - { - if ($this->streamed) { - return $this; - } - - $this->streamed = true; - - if (null === $this->callback) { - throw new \LogicException('The Response callback must not be null.'); - } - - ($this->callback)(); - - return $this; - } - - /** - * {@inheritdoc} - * - * @throws \LogicException when the content is not null - * - * @return $this - */ - public function setContent(?string $content) - { - if (null !== $content) { - throw new \LogicException('The content cannot be set on a StreamedResponse instance.'); - } - - $this->streamed = true; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getContent() - { - return false; - } -} diff --git a/lib/symfony/http-foundation/UrlHelper.php b/lib/symfony/http-foundation/UrlHelper.php deleted file mode 100644 index c15f101cd..000000000 --- a/lib/symfony/http-foundation/UrlHelper.php +++ /dev/null @@ -1,102 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\Routing\RequestContext; - -/** - * A helper service for manipulating URLs within and outside the request scope. - * - * @author Valentin Udaltsov <udaltsov.valentin@gmail.com> - */ -final class UrlHelper -{ - private $requestStack; - private $requestContext; - - public function __construct(RequestStack $requestStack, RequestContext $requestContext = null) - { - $this->requestStack = $requestStack; - $this->requestContext = $requestContext; - } - - public function getAbsoluteUrl(string $path): string - { - if (str_contains($path, '://') || '//' === substr($path, 0, 2)) { - return $path; - } - - if (null === $request = $this->requestStack->getMainRequest()) { - return $this->getAbsoluteUrlFromContext($path); - } - - if ('#' === $path[0]) { - $path = $request->getRequestUri().$path; - } elseif ('?' === $path[0]) { - $path = $request->getPathInfo().$path; - } - - if (!$path || '/' !== $path[0]) { - $prefix = $request->getPathInfo(); - $last = \strlen($prefix) - 1; - if ($last !== $pos = strrpos($prefix, '/')) { - $prefix = substr($prefix, 0, $pos).'/'; - } - - return $request->getUriForPath($prefix.$path); - } - - return $request->getSchemeAndHttpHost().$path; - } - - public function getRelativePath(string $path): string - { - if (str_contains($path, '://') || '//' === substr($path, 0, 2)) { - return $path; - } - - if (null === $request = $this->requestStack->getMainRequest()) { - return $path; - } - - return $request->getRelativeUriForPath($path); - } - - private function getAbsoluteUrlFromContext(string $path): string - { - if (null === $this->requestContext || '' === $host = $this->requestContext->getHost()) { - return $path; - } - - $scheme = $this->requestContext->getScheme(); - $port = ''; - - if ('http' === $scheme && 80 !== $this->requestContext->getHttpPort()) { - $port = ':'.$this->requestContext->getHttpPort(); - } elseif ('https' === $scheme && 443 !== $this->requestContext->getHttpsPort()) { - $port = ':'.$this->requestContext->getHttpsPort(); - } - - if ('#' === $path[0]) { - $queryString = $this->requestContext->getQueryString(); - $path = $this->requestContext->getPathInfo().($queryString ? '?'.$queryString : '').$path; - } elseif ('?' === $path[0]) { - $path = $this->requestContext->getPathInfo().$path; - } - - if ('/' !== $path[0]) { - $path = rtrim($this->requestContext->getBaseUrl(), '/').'/'.$path; - } - - return $scheme.'://'.$host.$port.$path; - } -} diff --git a/lib/symfony/http-foundation/composer.json b/lib/symfony/http-foundation/composer.json deleted file mode 100644 index cb8d59ffe..000000000 --- a/lib/symfony/http-foundation/composer.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "name": "symfony/http-foundation", - "type": "library", - "description": "Defines an object-oriented layer for the HTTP specification", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-mbstring": "~1.1", - "symfony/polyfill-php80": "^1.16" - }, - "require-dev": { - "predis/predis": "~1.0", - "symfony/cache": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4", - "symfony/mime": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/rate-limiter": "^5.2|^6.0" - }, - "suggest" : { - "symfony/mime": "To use the file extension guesser" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\HttpFoundation\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/lib/symfony/http-kernel/Attribute/ArgumentInterface.php b/lib/symfony/http-kernel/Attribute/ArgumentInterface.php deleted file mode 100644 index 78769f1ac..000000000 --- a/lib/symfony/http-kernel/Attribute/ArgumentInterface.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Attribute; - -trigger_deprecation('symfony/http-kernel', '5.3', 'The "%s" interface is deprecated.', ArgumentInterface::class); - -/** - * Marker interface for controller argument attributes. - * - * @deprecated since Symfony 5.3 - */ -interface ArgumentInterface -{ -} diff --git a/lib/symfony/http-kernel/Attribute/AsController.php b/lib/symfony/http-kernel/Attribute/AsController.php deleted file mode 100644 index ef3710451..000000000 --- a/lib/symfony/http-kernel/Attribute/AsController.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Attribute; - -/** - * Service tag to autoconfigure controllers. - */ -#[\Attribute(\Attribute::TARGET_CLASS)] -class AsController -{ - public function __construct() - { - } -} diff --git a/lib/symfony/http-kernel/Bundle/Bundle.php b/lib/symfony/http-kernel/Bundle/Bundle.php deleted file mode 100644 index 54a1d10b9..000000000 --- a/lib/symfony/http-kernel/Bundle/Bundle.php +++ /dev/null @@ -1,163 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Bundle; - -use Symfony\Component\Console\Application; -use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\DependencyInjection\ContainerAwareTrait; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; - -/** - * An implementation of BundleInterface that adds a few conventions for DependencyInjection extensions. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -abstract class Bundle implements BundleInterface -{ - use ContainerAwareTrait; - - protected $name; - protected $extension; - protected $path; - private $namespace; - - /** - * {@inheritdoc} - */ - public function boot() - { - } - - /** - * {@inheritdoc} - */ - public function shutdown() - { - } - - /** - * {@inheritdoc} - * - * This method can be overridden to register compilation passes, - * other extensions, ... - */ - public function build(ContainerBuilder $container) - { - } - - /** - * Returns the bundle's container extension. - * - * @return ExtensionInterface|null - * - * @throws \LogicException - */ - public function getContainerExtension() - { - if (null === $this->extension) { - $extension = $this->createContainerExtension(); - - if (null !== $extension) { - if (!$extension instanceof ExtensionInterface) { - throw new \LogicException(sprintf('Extension "%s" must implement Symfony\Component\DependencyInjection\Extension\ExtensionInterface.', get_debug_type($extension))); - } - - // check naming convention - $basename = preg_replace('/Bundle$/', '', $this->getName()); - $expectedAlias = Container::underscore($basename); - - if ($expectedAlias != $extension->getAlias()) { - throw new \LogicException(sprintf('Users will expect the alias of the default extension of a bundle to be the underscored version of the bundle name ("%s"). You can override "Bundle::getContainerExtension()" if you want to use "%s" or another alias.', $expectedAlias, $extension->getAlias())); - } - - $this->extension = $extension; - } else { - $this->extension = false; - } - } - - return $this->extension ?: null; - } - - /** - * {@inheritdoc} - */ - public function getNamespace() - { - if (null === $this->namespace) { - $this->parseClassName(); - } - - return $this->namespace; - } - - /** - * {@inheritdoc} - */ - public function getPath() - { - if (null === $this->path) { - $reflected = new \ReflectionObject($this); - $this->path = \dirname($reflected->getFileName()); - } - - return $this->path; - } - - /** - * Returns the bundle name (the class short name). - */ - final public function getName(): string - { - if (null === $this->name) { - $this->parseClassName(); - } - - return $this->name; - } - - public function registerCommands(Application $application) - { - } - - /** - * Returns the bundle's container extension class. - * - * @return string - */ - protected function getContainerExtensionClass() - { - $basename = preg_replace('/Bundle$/', '', $this->getName()); - - return $this->getNamespace().'\\DependencyInjection\\'.$basename.'Extension'; - } - - /** - * Creates the bundle's container extension. - * - * @return ExtensionInterface|null - */ - protected function createContainerExtension() - { - return class_exists($class = $this->getContainerExtensionClass()) ? new $class() : null; - } - - private function parseClassName() - { - $pos = strrpos(static::class, '\\'); - $this->namespace = false === $pos ? '' : substr(static::class, 0, $pos); - if (null === $this->name) { - $this->name = false === $pos ? static::class : substr(static::class, $pos + 1); - } - } -} diff --git a/lib/symfony/http-kernel/Bundle/BundleInterface.php b/lib/symfony/http-kernel/Bundle/BundleInterface.php deleted file mode 100644 index fdc13e0c8..000000000 --- a/lib/symfony/http-kernel/Bundle/BundleInterface.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Bundle; - -use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; - -/** - * BundleInterface. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface BundleInterface extends ContainerAwareInterface -{ - /** - * Boots the Bundle. - */ - public function boot(); - - /** - * Shutdowns the Bundle. - */ - public function shutdown(); - - /** - * Builds the bundle. - * - * It is only ever called once when the cache is empty. - */ - public function build(ContainerBuilder $container); - - /** - * Returns the container extension that should be implicitly loaded. - * - * @return ExtensionInterface|null - */ - public function getContainerExtension(); - - /** - * Returns the bundle name (the class short name). - * - * @return string - */ - public function getName(); - - /** - * Gets the Bundle namespace. - * - * @return string - */ - public function getNamespace(); - - /** - * Gets the Bundle directory path. - * - * The path should always be returned as a Unix path (with /). - * - * @return string - */ - public function getPath(); -} diff --git a/lib/symfony/http-kernel/CHANGELOG.md b/lib/symfony/http-kernel/CHANGELOG.md deleted file mode 100644 index d0dc2076c..000000000 --- a/lib/symfony/http-kernel/CHANGELOG.md +++ /dev/null @@ -1,317 +0,0 @@ -CHANGELOG -========= - -5.4 ---- - - * Add the ability to enable the profiler using a request query parameter, body parameter or attribute - * Deprecate `AbstractTestSessionListener` and `TestSessionListener`, use `AbstractSessionListener` and `SessionListener` instead - * Deprecate the `fileLinkFormat` parameter of `DebugHandlersListener` - * Add support for configuring log level, and status code by exception class - * Allow ignoring "kernel.reset" methods that don't exist with "on_invalid" attribute - -5.3 ---- - - * Deprecate `ArgumentInterface` - * Add `ArgumentMetadata::getAttributes()` - * Deprecate `ArgumentMetadata::getAttribute()`, use `getAttributes()` instead - * Mark the class `Symfony\Component\HttpKernel\EventListener\DebugHandlersListener` as internal - * Deprecate returning a `ContainerBuilder` from `KernelInterface::registerContainerConfiguration()` - * Deprecate `HttpKernelInterface::MASTER_REQUEST` and add `HttpKernelInterface::MAIN_REQUEST` as replacement - * Deprecate `KernelEvent::isMasterRequest()` and add `isMainRequest()` as replacement - * Add `#[AsController]` attribute for declaring standalone controllers on PHP 8 - * Add `FragmentUriGeneratorInterface` and `FragmentUriGenerator` to generate the URI of a fragment - -5.2.0 ------ - - * added session usage - * made the public `http_cache` service handle requests when available - * allowed enabling trusted hosts and proxies using new `kernel.trusted_hosts`, - `kernel.trusted_proxies` and `kernel.trusted_headers` parameters - * content of request parameter `_password` is now also hidden - in the request profiler raw content section - * Allowed adding attributes on controller arguments that will be passed to argument resolvers. - * kernels implementing the `ExtensionInterface` will now be auto-registered to the container - * added parameter `kernel.runtime_environment`, defined as `%env(default:kernel.environment:APP_RUNTIME_ENV)%` - * do not set a default `Accept` HTTP header when using `HttpKernelBrowser` - -5.1.0 ------ - - * allowed to use a specific logger channel for deprecations - * made `WarmableInterface::warmUp()` return a list of classes or files to preload on PHP 7.4+; - not returning an array is deprecated - * made kernels implementing `WarmableInterface` be part of the cache warmup stage - * deprecated support for `service:action` syntax to reference controllers, use `serviceOrFqcn::method` instead - * allowed using public aliases to reference controllers - * added session usage reporting when the `_stateless` attribute of the request is set to `true` - * added `AbstractSessionListener::onSessionUsage()` to report when the session is used while a request is stateless - -5.0.0 ------ - - * removed support for getting the container from a non-booted kernel - * removed the first and second constructor argument of `ConfigDataCollector` - * removed `ConfigDataCollector::getApplicationName()` - * removed `ConfigDataCollector::getApplicationVersion()` - * removed support for `Symfony\Component\Templating\EngineInterface` in `HIncludeFragmentRenderer`, use a `Twig\Environment` only - * removed `TranslatorListener` in favor of `LocaleAwareListener` - * removed `getRootDir()` and `getName()` from `Kernel` and `KernelInterface` - * removed `FilterControllerArgumentsEvent`, use `ControllerArgumentsEvent` instead - * removed `FilterControllerEvent`, use `ControllerEvent` instead - * removed `FilterResponseEvent`, use `ResponseEvent` instead - * removed `GetResponseEvent`, use `RequestEvent` instead - * removed `GetResponseForControllerResultEvent`, use `ViewEvent` instead - * removed `GetResponseForExceptionEvent`, use `ExceptionEvent` instead - * removed `PostResponseEvent`, use `TerminateEvent` instead - * removed `SaveSessionListener` in favor of `AbstractSessionListener` - * removed `Client`, use `HttpKernelBrowser` instead - * added method `getProjectDir()` to `KernelInterface` - * removed methods `serialize` and `unserialize` from `DataCollector`, store the serialized state in the data property instead - * made `ProfilerStorageInterface` internal - * removed the second and third argument of `KernelInterface::locateResource` - * removed the second and third argument of `FileLocator::__construct` - * removed loading resources from `%kernel.root_dir%/Resources` and `%kernel.root_dir%` as - fallback directories. - * removed class `ExceptionListener`, use `ErrorListener` instead - -4.4.0 ------ - - * The `DebugHandlersListener` class has been marked as `final` - * Added new Bundle directory convention consistent with standard skeletons - * Deprecated the second and third argument of `KernelInterface::locateResource` - * Deprecated the second and third argument of `FileLocator::__construct` - * Deprecated loading resources from `%kernel.root_dir%/Resources` and `%kernel.root_dir%` as - fallback directories. Resources like service definitions are usually loaded relative to the - current directory or with a glob pattern. The fallback directories have never been advocated - so you likely do not use those in any app based on the SF Standard or Flex edition. - * Marked all dispatched event classes as `@final` - * Added `ErrorController` to enable the preview and error rendering mechanism - * Getting the container from a non-booted kernel is deprecated. - * Marked the `AjaxDataCollector`, `ConfigDataCollector`, `EventDataCollector`, - `ExceptionDataCollector`, `LoggerDataCollector`, `MemoryDataCollector`, - `RequestDataCollector` and `TimeDataCollector` classes as `@final`. - * Marked the `RouterDataCollector::collect()` method as `@final`. - * The `DataCollectorInterface::collect()` and `Profiler::collect()` methods third parameter signature - will be `\Throwable $exception = null` instead of `\Exception $exception = null` in Symfony 5.0. - * Deprecated methods `ExceptionEvent::get/setException()`, use `get/setThrowable()` instead - * Deprecated class `ExceptionListener`, use `ErrorListener` instead - -4.3.0 ------ - - * renamed `Client` to `HttpKernelBrowser` - * `KernelInterface` doesn't extend `Serializable` anymore - * deprecated the `Kernel::serialize()` and `unserialize()` methods - * increased the priority of `Symfony\Component\HttpKernel\EventListener\AddRequestFormatsListener` - * made `Symfony\Component\HttpKernel\EventListener\LocaleListener` set the default locale early - * deprecated `TranslatorListener` in favor of `LocaleAwareListener` - * added the registration of all `LocaleAwareInterface` implementations into the `LocaleAwareListener` - * made `FileLinkFormatter` final and not implement `Serializable` anymore - * the base `DataCollector` doesn't implement `Serializable` anymore, you should - store all the serialized state in the data property instead - * `DumpDataCollector` has been marked as `final` - * added an event listener to prevent search engines from indexing applications in debug mode. - * renamed `FilterControllerArgumentsEvent` to `ControllerArgumentsEvent` - * renamed `FilterControllerEvent` to `ControllerEvent` - * renamed `FilterResponseEvent` to `ResponseEvent` - * renamed `GetResponseEvent` to `RequestEvent` - * renamed `GetResponseForControllerResultEvent` to `ViewEvent` - * renamed `GetResponseForExceptionEvent` to `ExceptionEvent` - * renamed `PostResponseEvent` to `TerminateEvent` - * added `HttpClientKernel` for handling requests with an `HttpClientInterface` instance - * added `trace_header` and `trace_level` configuration options to `HttpCache` - -4.2.0 ------ - - * deprecated `KernelInterface::getRootDir()` and the `kernel.root_dir` parameter - * deprecated `KernelInterface::getName()` and the `kernel.name` parameter - * deprecated the first and second constructor argument of `ConfigDataCollector` - * deprecated `ConfigDataCollector::getApplicationName()` - * deprecated `ConfigDataCollector::getApplicationVersion()` - -4.1.0 ------ - - * added orphaned events support to `EventDataCollector` - * `ExceptionListener` now logs exceptions at priority `0` (previously logged at `-128`) - * Added support for using `service::method` to reference controllers, making it consistent with other cases. It is recommended over the `service:action` syntax with a single colon, which will be deprecated in the future. - * Added the ability to profile individual argument value resolvers via the - `Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver` - -4.0.0 ------ - - * removed the `DataCollector::varToString()` method, use `DataCollector::cloneVar()` - instead - * using the `DataCollector::cloneVar()` method requires the VarDumper component - * removed the `ValueExporter` class - * removed `ControllerResolverInterface::getArguments()` - * removed `TraceableControllerResolver::getArguments()` - * removed `ControllerResolver::getArguments()` and the ability to resolve arguments - * removed the `argument_resolver` service dependency from the `debug.controller_resolver` - * removed `LazyLoadingFragmentHandler::addRendererService()` - * removed `Psr6CacheClearer::addPool()` - * removed `Extension::addClassesToCompile()` and `Extension::getClassesToCompile()` - * removed `Kernel::loadClassCache()`, `Kernel::doLoadClassCache()`, `Kernel::setClassCache()`, - and `Kernel::getEnvParameters()` - * support for the `X-Status-Code` when handling exceptions in the `HttpKernel` - has been dropped, use the `HttpKernel::allowCustomResponseCode()` method - instead - * removed convention-based commands registration - * removed the `ChainCacheClearer::add()` method - * removed the `CacheaWarmerAggregate::add()` and `setWarmers()` methods - * made `CacheWarmerAggregate` and `ChainCacheClearer` classes final - -3.4.0 ------ - - * added a minimalist PSR-3 `Logger` class that writes in `stderr` - * made kernels implementing `CompilerPassInterface` able to process the container - * deprecated bundle inheritance - * added `RebootableInterface` and implemented it in `Kernel` - * deprecated commands auto registration - * deprecated `EnvParametersResource` - * added `Symfony\Component\HttpKernel\Client::catchExceptions()` - * deprecated the `ChainCacheClearer::add()` method - * deprecated the `CacheaWarmerAggregate::add()` and `setWarmers()` methods - * made `CacheWarmerAggregate` and `ChainCacheClearer` classes final - * added the possibility to reset the profiler to its initial state - * deprecated data collectors without a `reset()` method - * deprecated implementing `DebugLoggerInterface` without a `clear()` method - -3.3.0 ------ - - * added `kernel.project_dir` and `Kernel::getProjectDir()` - * deprecated `kernel.root_dir` and `Kernel::getRootDir()` - * deprecated `Kernel::getEnvParameters()` - * deprecated the special `SYMFONY__` environment variables - * added the possibility to change the query string parameter used by `UriSigner` - * deprecated `LazyLoadingFragmentHandler::addRendererService()` - * deprecated `Extension::addClassesToCompile()` and `Extension::getClassesToCompile()` - * deprecated `Psr6CacheClearer::addPool()` - -3.2.0 ------ - - * deprecated `DataCollector::varToString()`, use `cloneVar()` instead - * changed surrogate capability name in `AbstractSurrogate::addSurrogateCapability` to 'symfony' - * Added `ControllerArgumentValueResolverPass` - -3.1.0 ------ - * deprecated passing objects as URI attributes to the ESI and SSI renderers - * deprecated `ControllerResolver::getArguments()` - * added `Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface` - * added `Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface` as argument to `HttpKernel` - * added `Symfony\Component\HttpKernel\Controller\ArgumentResolver` - * added `Symfony\Component\HttpKernel\DataCollector\RequestDataCollector::getMethod()` - * added `Symfony\Component\HttpKernel\DataCollector\RequestDataCollector::getRedirect()` - * added the `kernel.controller_arguments` event, triggered after controller arguments have been resolved - -3.0.0 ------ - - * removed `Symfony\Component\HttpKernel\Kernel::init()` - * removed `Symfony\Component\HttpKernel\Kernel::isClassInActiveBundle()` and `Symfony\Component\HttpKernel\KernelInterface::isClassInActiveBundle()` - * removed `Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher::setProfiler()` - * removed `Symfony\Component\HttpKernel\EventListener\FragmentListener::getLocalIpAddresses()` - * removed `Symfony\Component\HttpKernel\EventListener\LocaleListener::setRequest()` - * removed `Symfony\Component\HttpKernel\EventListener\RouterListener::setRequest()` - * removed `Symfony\Component\HttpKernel\EventListener\ProfilerListener::onKernelRequest()` - * removed `Symfony\Component\HttpKernel\Fragment\FragmentHandler::setRequest()` - * removed `Symfony\Component\HttpKernel\HttpCache\Esi::hasSurrogateEsiCapability()` - * removed `Symfony\Component\HttpKernel\HttpCache\Esi::addSurrogateEsiCapability()` - * removed `Symfony\Component\HttpKernel\HttpCache\Esi::needsEsiParsing()` - * removed `Symfony\Component\HttpKernel\HttpCache\HttpCache::getEsi()` - * removed `Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel` - * removed `Symfony\Component\HttpKernel\DependencyInjection\RegisterListenersPass` - * removed `Symfony\Component\HttpKernel\EventListener\ErrorsLoggerListener` - * removed `Symfony\Component\HttpKernel\EventListener\EsiListener` - * removed `Symfony\Component\HttpKernel\HttpCache\EsiResponseCacheStrategy` - * removed `Symfony\Component\HttpKernel\HttpCache\EsiResponseCacheStrategyInterface` - * removed `Symfony\Component\HttpKernel\Log\LoggerInterface` - * removed `Symfony\Component\HttpKernel\Log\NullLogger` - * removed `Symfony\Component\HttpKernel\Profiler::import()` - * removed `Symfony\Component\HttpKernel\Profiler::export()` - -2.8.0 ------ - - * deprecated `Profiler::import` and `Profiler::export` - -2.7.0 ------ - - * added the HTTP status code to profiles - -2.6.0 ------ - - * deprecated `Symfony\Component\HttpKernel\EventListener\ErrorsLoggerListener`, use `Symfony\Component\HttpKernel\EventListener\DebugHandlersListener` instead - * deprecated unused method `Symfony\Component\HttpKernel\Kernel::isClassInActiveBundle` and `Symfony\Component\HttpKernel\KernelInterface::isClassInActiveBundle` - -2.5.0 ------ - - * deprecated `Symfony\Component\HttpKernel\DependencyInjection\RegisterListenersPass`, use `Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass` instead - -2.4.0 ------ - - * added event listeners for the session - * added the KernelEvents::FINISH_REQUEST event - -2.3.0 ------ - - * [BC BREAK] renamed `Symfony\Component\HttpKernel\EventListener\DeprecationLoggerListener` to `Symfony\Component\HttpKernel\EventListener\ErrorsLoggerListener` and changed its constructor - * deprecated `Symfony\Component\HttpKernel\Debug\ErrorHandler`, `Symfony\Component\HttpKernel\Debug\ExceptionHandler`, - `Symfony\Component\HttpKernel\Exception\FatalErrorException` and `Symfony\Component\HttpKernel\Exception\FlattenException` - * deprecated `Symfony\Component\HttpKernel\Kernel::init()` - * added the possibility to specify an id an extra attributes to hinclude tags - * added the collect of data if a controller is a Closure in the Request collector - * pass exceptions from the ExceptionListener to the logger using the logging context to allow for more - detailed messages - -2.2.0 ------ - - * [BC BREAK] the path info for sub-request is now always _fragment (or whatever you configured instead of the default) - * added Symfony\Component\HttpKernel\EventListener\FragmentListener - * added Symfony\Component\HttpKernel\UriSigner - * added Symfony\Component\HttpKernel\FragmentRenderer and rendering strategies (in Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface) - * added Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel - * added ControllerReference to create reference of Controllers (used in the FragmentRenderer class) - * [BC BREAK] renamed TimeDataCollector::getTotalTime() to - TimeDataCollector::getDuration() - * updated the MemoryDataCollector to include the memory used in the - kernel.terminate event listeners - * moved the Stopwatch classes to a new component - * added TraceableControllerResolver - * added TraceableEventDispatcher (removed ContainerAwareTraceableEventDispatcher) - * added support for WinCache opcode cache in ConfigDataCollector - -2.1.0 ------ - - * [BC BREAK] the charset is now configured via the Kernel::getCharset() method - * [BC BREAK] the current locale for the user is not stored anymore in the session - * added the HTTP method to the profiler storage - * updated all listeners to implement EventSubscriberInterface - * added TimeDataCollector - * added ContainerAwareTraceableEventDispatcher - * moved TraceableEventDispatcherInterface to the EventDispatcher component - * added RouterListener, LocaleListener, and StreamedResponseListener - * added CacheClearerInterface (and ChainCacheClearer) - * added a kernel.terminate event (via TerminableInterface and PostResponseEvent) - * added a Stopwatch class - * added WarmableInterface - * improved extensibility between bundles - * added profiler storages for Memcache(d), File-based, MongoDB, Redis - * moved Filesystem class to its own component diff --git a/lib/symfony/http-kernel/CacheClearer/CacheClearerInterface.php b/lib/symfony/http-kernel/CacheClearer/CacheClearerInterface.php deleted file mode 100644 index 270f690e5..000000000 --- a/lib/symfony/http-kernel/CacheClearer/CacheClearerInterface.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\CacheClearer; - -/** - * CacheClearerInterface. - * - * @author Dustin Dobervich <ddobervich@gmail.com> - */ -interface CacheClearerInterface -{ - /** - * Clears any caches necessary. - */ - public function clear(string $cacheDir); -} diff --git a/lib/symfony/http-kernel/CacheClearer/ChainCacheClearer.php b/lib/symfony/http-kernel/CacheClearer/ChainCacheClearer.php deleted file mode 100644 index a875d899d..000000000 --- a/lib/symfony/http-kernel/CacheClearer/ChainCacheClearer.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\CacheClearer; - -/** - * ChainCacheClearer. - * - * @author Dustin Dobervich <ddobervich@gmail.com> - * - * @final - */ -class ChainCacheClearer implements CacheClearerInterface -{ - private $clearers; - - /** - * @param iterable<mixed, CacheClearerInterface> $clearers - */ - public function __construct(iterable $clearers = []) - { - $this->clearers = $clearers; - } - - /** - * {@inheritdoc} - */ - public function clear(string $cacheDir) - { - foreach ($this->clearers as $clearer) { - $clearer->clear($cacheDir); - } - } -} diff --git a/lib/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php b/lib/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php deleted file mode 100644 index a074060e4..000000000 --- a/lib/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\CacheClearer; - -use Psr\Cache\CacheItemPoolInterface; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class Psr6CacheClearer implements CacheClearerInterface -{ - private $pools = []; - - /** - * @param array<string, CacheItemPoolInterface> $pools - */ - public function __construct(array $pools = []) - { - $this->pools = $pools; - } - - /** - * @return bool - */ - public function hasPool(string $name) - { - return isset($this->pools[$name]); - } - - /** - * @return CacheItemPoolInterface - * - * @throws \InvalidArgumentException If the cache pool with the given name does not exist - */ - public function getPool(string $name) - { - if (!$this->hasPool($name)) { - throw new \InvalidArgumentException(sprintf('Cache pool not found: "%s".', $name)); - } - - return $this->pools[$name]; - } - - /** - * @return bool - * - * @throws \InvalidArgumentException If the cache pool with the given name does not exist - */ - public function clearPool(string $name) - { - if (!isset($this->pools[$name])) { - throw new \InvalidArgumentException(sprintf('Cache pool not found: "%s".', $name)); - } - - return $this->pools[$name]->clear(); - } - - /** - * {@inheritdoc} - */ - public function clear(string $cacheDir) - { - foreach ($this->pools as $pool) { - $pool->clear(); - } - } -} diff --git a/lib/symfony/http-kernel/CacheWarmer/CacheWarmer.php b/lib/symfony/http-kernel/CacheWarmer/CacheWarmer.php deleted file mode 100644 index aef42d62f..000000000 --- a/lib/symfony/http-kernel/CacheWarmer/CacheWarmer.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\CacheWarmer; - -/** - * Abstract cache warmer that knows how to write a file to the cache. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -abstract class CacheWarmer implements CacheWarmerInterface -{ - protected function writeCacheFile(string $file, $content) - { - $tmpFile = @tempnam(\dirname($file), basename($file)); - if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) { - @chmod($file, 0666 & ~umask()); - - return; - } - - throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $file)); - } -} diff --git a/lib/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php b/lib/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php deleted file mode 100644 index 67f9ed50b..000000000 --- a/lib/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php +++ /dev/null @@ -1,126 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\CacheWarmer; - -/** - * Aggregates several cache warmers into a single one. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class CacheWarmerAggregate implements CacheWarmerInterface -{ - private $warmers; - private $debug; - private $deprecationLogsFilepath; - private $optionalsEnabled = false; - private $onlyOptionalsEnabled = false; - - /** - * @param iterable<mixed, CacheWarmerInterface> $warmers - */ - public function __construct(iterable $warmers = [], bool $debug = false, string $deprecationLogsFilepath = null) - { - $this->warmers = $warmers; - $this->debug = $debug; - $this->deprecationLogsFilepath = $deprecationLogsFilepath; - } - - public function enableOptionalWarmers() - { - $this->optionalsEnabled = true; - } - - public function enableOnlyOptionalWarmers() - { - $this->onlyOptionalsEnabled = $this->optionalsEnabled = true; - } - - /** - * {@inheritdoc} - */ - public function warmUp(string $cacheDir): array - { - if ($collectDeprecations = $this->debug && !\defined('PHPUNIT_COMPOSER_INSTALL')) { - $collectedLogs = []; - $previousHandler = set_error_handler(function ($type, $message, $file, $line) use (&$collectedLogs, &$previousHandler) { - if (\E_USER_DEPRECATED !== $type && \E_DEPRECATED !== $type) { - return $previousHandler ? $previousHandler($type, $message, $file, $line) : false; - } - - if (isset($collectedLogs[$message])) { - ++$collectedLogs[$message]['count']; - - return null; - } - - $backtrace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 3); - // Clean the trace by removing first frames added by the error handler itself. - for ($i = 0; isset($backtrace[$i]); ++$i) { - if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { - $backtrace = \array_slice($backtrace, 1 + $i); - break; - } - } - - $collectedLogs[$message] = [ - 'type' => $type, - 'message' => $message, - 'file' => $file, - 'line' => $line, - 'trace' => $backtrace, - 'count' => 1, - ]; - - return null; - }); - } - - $preload = []; - try { - foreach ($this->warmers as $warmer) { - if (!$this->optionalsEnabled && $warmer->isOptional()) { - continue; - } - if ($this->onlyOptionalsEnabled && !$warmer->isOptional()) { - continue; - } - - $preload[] = array_values((array) $warmer->warmUp($cacheDir)); - } - } finally { - if ($collectDeprecations) { - restore_error_handler(); - - if (is_file($this->deprecationLogsFilepath)) { - $previousLogs = unserialize(file_get_contents($this->deprecationLogsFilepath)); - if (\is_array($previousLogs)) { - $collectedLogs = array_merge($previousLogs, $collectedLogs); - } - } - - file_put_contents($this->deprecationLogsFilepath, serialize(array_values($collectedLogs))); - } - } - - return array_values(array_unique(array_merge([], ...$preload))); - } - - /** - * {@inheritdoc} - */ - public function isOptional(): bool - { - return false; - } -} diff --git a/lib/symfony/http-kernel/CacheWarmer/CacheWarmerInterface.php b/lib/symfony/http-kernel/CacheWarmer/CacheWarmerInterface.php deleted file mode 100644 index 1f1740b7e..000000000 --- a/lib/symfony/http-kernel/CacheWarmer/CacheWarmerInterface.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\CacheWarmer; - -/** - * Interface for classes able to warm up the cache. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface CacheWarmerInterface extends WarmableInterface -{ - /** - * Checks whether this warmer is optional or not. - * - * Optional warmers can be ignored on certain conditions. - * - * A warmer should return true if the cache can be - * generated incrementally and on-demand. - * - * @return bool - */ - public function isOptional(); -} diff --git a/lib/symfony/http-kernel/CacheWarmer/WarmableInterface.php b/lib/symfony/http-kernel/CacheWarmer/WarmableInterface.php deleted file mode 100644 index 2f442cb53..000000000 --- a/lib/symfony/http-kernel/CacheWarmer/WarmableInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\CacheWarmer; - -/** - * Interface for classes that support warming their cache. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface WarmableInterface -{ - /** - * Warms up the cache. - * - * @return string[] A list of classes or files to preload on PHP 7.4+ - */ - public function warmUp(string $cacheDir); -} diff --git a/lib/symfony/http-kernel/Config/FileLocator.php b/lib/symfony/http-kernel/Config/FileLocator.php deleted file mode 100644 index 6eca98635..000000000 --- a/lib/symfony/http-kernel/Config/FileLocator.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Config; - -use Symfony\Component\Config\FileLocator as BaseFileLocator; -use Symfony\Component\HttpKernel\KernelInterface; - -/** - * FileLocator uses the KernelInterface to locate resources in bundles. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class FileLocator extends BaseFileLocator -{ - private $kernel; - - public function __construct(KernelInterface $kernel) - { - $this->kernel = $kernel; - - parent::__construct(); - } - - /** - * {@inheritdoc} - */ - public function locate(string $file, string $currentPath = null, bool $first = true) - { - if (isset($file[0]) && '@' === $file[0]) { - $resource = $this->kernel->locateResource($file); - - return $first ? $resource : [$resource]; - } - - return parent::locate($file, $currentPath, $first); - } -} diff --git a/lib/symfony/http-kernel/Controller/ArgumentResolver.php b/lib/symfony/http-kernel/Controller/ArgumentResolver.php deleted file mode 100644 index a54140b7e..000000000 --- a/lib/symfony/http-kernel/Controller/ArgumentResolver.php +++ /dev/null @@ -1,98 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver; -use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory; -use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactoryInterface; - -/** - * Responsible for resolving the arguments passed to an action. - * - * @author Iltar van der Berg <kjarli@gmail.com> - */ -final class ArgumentResolver implements ArgumentResolverInterface -{ - private $argumentMetadataFactory; - private $argumentValueResolvers; - - /** - * @param iterable<mixed, ArgumentValueResolverInterface> $argumentValueResolvers - */ - public function __construct(ArgumentMetadataFactoryInterface $argumentMetadataFactory = null, iterable $argumentValueResolvers = []) - { - $this->argumentMetadataFactory = $argumentMetadataFactory ?? new ArgumentMetadataFactory(); - $this->argumentValueResolvers = $argumentValueResolvers ?: self::getDefaultArgumentValueResolvers(); - } - - /** - * {@inheritdoc} - */ - public function getArguments(Request $request, callable $controller): array - { - $arguments = []; - - foreach ($this->argumentMetadataFactory->createArgumentMetadata($controller) as $metadata) { - foreach ($this->argumentValueResolvers as $resolver) { - if (!$resolver->supports($request, $metadata)) { - continue; - } - - $resolved = $resolver->resolve($request, $metadata); - - $atLeastOne = false; - foreach ($resolved as $append) { - $atLeastOne = true; - $arguments[] = $append; - } - - if (!$atLeastOne) { - throw new \InvalidArgumentException(sprintf('"%s::resolve()" must yield at least one value.', get_debug_type($resolver))); - } - - // continue to the next controller argument - continue 2; - } - - $representative = $controller; - - if (\is_array($representative)) { - $representative = sprintf('%s::%s()', \get_class($representative[0]), $representative[1]); - } elseif (\is_object($representative)) { - $representative = \get_class($representative); - } - - throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one.', $representative, $metadata->getName())); - } - - return $arguments; - } - - /** - * @return iterable<int, ArgumentValueResolverInterface> - */ - public static function getDefaultArgumentValueResolvers(): iterable - { - return [ - new RequestAttributeValueResolver(), - new RequestValueResolver(), - new SessionValueResolver(), - new DefaultValueResolver(), - new VariadicValueResolver(), - ]; - } -} diff --git a/lib/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php b/lib/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php deleted file mode 100644 index 32a0e071d..000000000 --- a/lib/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; -use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; - -/** - * Yields the default value defined in the action signature when no value has been given. - * - * @author Iltar van der Berg <kjarli@gmail.com> - */ -final class DefaultValueResolver implements ArgumentValueResolverInterface -{ - /** - * {@inheritdoc} - */ - public function supports(Request $request, ArgumentMetadata $argument): bool - { - return $argument->hasDefaultValue() || (null !== $argument->getType() && $argument->isNullable() && !$argument->isVariadic()); - } - - /** - * {@inheritdoc} - */ - public function resolve(Request $request, ArgumentMetadata $argument): iterable - { - yield $argument->hasDefaultValue() ? $argument->getDefaultValue() : null; - } -} diff --git a/lib/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php b/lib/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php deleted file mode 100644 index 48ea6e742..000000000 --- a/lib/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php +++ /dev/null @@ -1,82 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; - -use Psr\Container\ContainerInterface; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; -use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; - -/** - * Provides an intuitive error message when controller fails because it is not registered as a service. - * - * @author Simeon Kolev <simeon.kolev9@gmail.com> - */ -final class NotTaggedControllerValueResolver implements ArgumentValueResolverInterface -{ - private $container; - - public function __construct(ContainerInterface $container) - { - $this->container = $container; - } - - /** - * {@inheritdoc} - */ - public function supports(Request $request, ArgumentMetadata $argument): bool - { - $controller = $request->attributes->get('_controller'); - - if (\is_array($controller) && \is_callable($controller, true) && \is_string($controller[0])) { - $controller = $controller[0].'::'.$controller[1]; - } elseif (!\is_string($controller) || '' === $controller) { - return false; - } - - if ('\\' === $controller[0]) { - $controller = ltrim($controller, '\\'); - } - - if (!$this->container->has($controller) && false !== $i = strrpos($controller, ':')) { - $controller = substr($controller, 0, $i).strtolower(substr($controller, $i)); - } - - return false === $this->container->has($controller); - } - - /** - * {@inheritdoc} - */ - public function resolve(Request $request, ArgumentMetadata $argument): iterable - { - if (\is_array($controller = $request->attributes->get('_controller'))) { - $controller = $controller[0].'::'.$controller[1]; - } - - if ('\\' === $controller[0]) { - $controller = ltrim($controller, '\\'); - } - - if (!$this->container->has($controller)) { - $controller = (false !== $i = strrpos($controller, ':')) - ? substr($controller, 0, $i).strtolower(substr($controller, $i)) - : $controller.'::__invoke'; - } - - $what = sprintf('argument $%s of "%s()"', $argument->getName(), $controller); - $message = sprintf('Could not resolve %s, maybe you forgot to register the controller as a service or missed tagging it with the "controller.service_arguments"?', $what); - - throw new RuntimeException($message); - } -} diff --git a/lib/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php b/lib/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php deleted file mode 100644 index c62d327b6..000000000 --- a/lib/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; -use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; - -/** - * Yields a non-variadic argument's value from the request attributes. - * - * @author Iltar van der Berg <kjarli@gmail.com> - */ -final class RequestAttributeValueResolver implements ArgumentValueResolverInterface -{ - /** - * {@inheritdoc} - */ - public function supports(Request $request, ArgumentMetadata $argument): bool - { - return !$argument->isVariadic() && $request->attributes->has($argument->getName()); - } - - /** - * {@inheritdoc} - */ - public function resolve(Request $request, ArgumentMetadata $argument): iterable - { - yield $request->attributes->get($argument->getName()); - } -} diff --git a/lib/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php b/lib/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php deleted file mode 100644 index 75cbd97ed..000000000 --- a/lib/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; -use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; - -/** - * Yields the same instance as the request object passed along. - * - * @author Iltar van der Berg <kjarli@gmail.com> - */ -final class RequestValueResolver implements ArgumentValueResolverInterface -{ - /** - * {@inheritdoc} - */ - public function supports(Request $request, ArgumentMetadata $argument): bool - { - return Request::class === $argument->getType() || is_subclass_of($argument->getType(), Request::class); - } - - /** - * {@inheritdoc} - */ - public function resolve(Request $request, ArgumentMetadata $argument): iterable - { - yield $request; - } -} diff --git a/lib/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php b/lib/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php deleted file mode 100644 index 4ffb8c99e..000000000 --- a/lib/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php +++ /dev/null @@ -1,93 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; - -use Psr\Container\ContainerInterface; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; -use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; - -/** - * Yields a service keyed by _controller and argument name. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -final class ServiceValueResolver implements ArgumentValueResolverInterface -{ - private $container; - - public function __construct(ContainerInterface $container) - { - $this->container = $container; - } - - /** - * {@inheritdoc} - */ - public function supports(Request $request, ArgumentMetadata $argument): bool - { - $controller = $request->attributes->get('_controller'); - - if (\is_array($controller) && \is_callable($controller, true) && \is_string($controller[0])) { - $controller = $controller[0].'::'.$controller[1]; - } elseif (!\is_string($controller) || '' === $controller) { - return false; - } - - if ('\\' === $controller[0]) { - $controller = ltrim($controller, '\\'); - } - - if (!$this->container->has($controller) && false !== $i = strrpos($controller, ':')) { - $controller = substr($controller, 0, $i).strtolower(substr($controller, $i)); - } - - return $this->container->has($controller) && $this->container->get($controller)->has($argument->getName()); - } - - /** - * {@inheritdoc} - */ - public function resolve(Request $request, ArgumentMetadata $argument): iterable - { - if (\is_array($controller = $request->attributes->get('_controller'))) { - $controller = $controller[0].'::'.$controller[1]; - } - - if ('\\' === $controller[0]) { - $controller = ltrim($controller, '\\'); - } - - if (!$this->container->has($controller)) { - $i = strrpos($controller, ':'); - $controller = substr($controller, 0, $i).strtolower(substr($controller, $i)); - } - - try { - yield $this->container->get($controller)->get($argument->getName()); - } catch (RuntimeException $e) { - $what = sprintf('argument $%s of "%s()"', $argument->getName(), $controller); - $message = preg_replace('/service "\.service_locator\.[^"]++"/', $what, $e->getMessage()); - - if ($e->getMessage() === $message) { - $message = sprintf('Cannot resolve %s: %s', $what, $message); - } - - $r = new \ReflectionProperty($e, 'message'); - $r->setAccessible(true); - $r->setValue($e, $message); - - throw $e; - } - } -} diff --git a/lib/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php b/lib/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php deleted file mode 100644 index a1e6b4315..000000000 --- a/lib/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Session\SessionInterface; -use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; -use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; - -/** - * Yields the Session. - * - * @author Iltar van der Berg <kjarli@gmail.com> - */ -final class SessionValueResolver implements ArgumentValueResolverInterface -{ - /** - * {@inheritdoc} - */ - public function supports(Request $request, ArgumentMetadata $argument): bool - { - if (!$request->hasSession()) { - return false; - } - - $type = $argument->getType(); - if (SessionInterface::class !== $type && !is_subclass_of($type, SessionInterface::class)) { - return false; - } - - return $request->getSession() instanceof $type; - } - - /** - * {@inheritdoc} - */ - public function resolve(Request $request, ArgumentMetadata $argument): iterable - { - yield $request->getSession(); - } -} diff --git a/lib/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php b/lib/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php deleted file mode 100644 index bde3c90c1..000000000 --- a/lib/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; -use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; -use Symfony\Component\Stopwatch\Stopwatch; - -/** - * Provides timing information via the stopwatch. - * - * @author Iltar van der Berg <kjarli@gmail.com> - */ -final class TraceableValueResolver implements ArgumentValueResolverInterface -{ - private $inner; - private $stopwatch; - - public function __construct(ArgumentValueResolverInterface $inner, Stopwatch $stopwatch) - { - $this->inner = $inner; - $this->stopwatch = $stopwatch; - } - - /** - * {@inheritdoc} - */ - public function supports(Request $request, ArgumentMetadata $argument): bool - { - $method = \get_class($this->inner).'::'.__FUNCTION__; - $this->stopwatch->start($method, 'controller.argument_value_resolver'); - - $return = $this->inner->supports($request, $argument); - - $this->stopwatch->stop($method); - - return $return; - } - - /** - * {@inheritdoc} - */ - public function resolve(Request $request, ArgumentMetadata $argument): iterable - { - $method = \get_class($this->inner).'::'.__FUNCTION__; - $this->stopwatch->start($method, 'controller.argument_value_resolver'); - - yield from $this->inner->resolve($request, $argument); - - $this->stopwatch->stop($method); - } -} diff --git a/lib/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php b/lib/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php deleted file mode 100644 index a8f7e0f44..000000000 --- a/lib/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; -use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; - -/** - * Yields a variadic argument's values from the request attributes. - * - * @author Iltar van der Berg <kjarli@gmail.com> - */ -final class VariadicValueResolver implements ArgumentValueResolverInterface -{ - /** - * {@inheritdoc} - */ - public function supports(Request $request, ArgumentMetadata $argument): bool - { - return $argument->isVariadic() && $request->attributes->has($argument->getName()); - } - - /** - * {@inheritdoc} - */ - public function resolve(Request $request, ArgumentMetadata $argument): iterable - { - $values = $request->attributes->get($argument->getName()); - - if (!\is_array($values)) { - throw new \InvalidArgumentException(sprintf('The action argument "...$%1$s" is required to be an array, the request attribute "%1$s" contains a type of "%2$s" instead.', $argument->getName(), get_debug_type($values))); - } - - yield from $values; - } -} diff --git a/lib/symfony/http-kernel/Controller/ArgumentResolverInterface.php b/lib/symfony/http-kernel/Controller/ArgumentResolverInterface.php deleted file mode 100644 index 30e4783e8..000000000 --- a/lib/symfony/http-kernel/Controller/ArgumentResolverInterface.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller; - -use Symfony\Component\HttpFoundation\Request; - -/** - * An ArgumentResolverInterface instance knows how to determine the - * arguments for a specific action. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface ArgumentResolverInterface -{ - /** - * Returns the arguments to pass to the controller. - * - * @return array - * - * @throws \RuntimeException When no value could be provided for a required argument - */ - public function getArguments(Request $request, callable $controller); -} diff --git a/lib/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php b/lib/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php deleted file mode 100644 index 1317707b1..000000000 --- a/lib/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; - -/** - * Responsible for resolving the value of an argument based on its metadata. - * - * @author Iltar van der Berg <kjarli@gmail.com> - */ -interface ArgumentValueResolverInterface -{ - /** - * Whether this resolver can resolve the value for the given ArgumentMetadata. - * - * @return bool - */ - public function supports(Request $request, ArgumentMetadata $argument); - - /** - * Returns the possible value(s). - * - * @return iterable - */ - public function resolve(Request $request, ArgumentMetadata $argument); -} diff --git a/lib/symfony/http-kernel/Controller/ContainerControllerResolver.php b/lib/symfony/http-kernel/Controller/ContainerControllerResolver.php deleted file mode 100644 index 3b9468465..000000000 --- a/lib/symfony/http-kernel/Controller/ContainerControllerResolver.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller; - -use Psr\Container\ContainerInterface; -use Psr\Log\LoggerInterface; -use Symfony\Component\DependencyInjection\Container; - -/** - * A controller resolver searching for a controller in a psr-11 container when using the "service::method" notation. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> - */ -class ContainerControllerResolver extends ControllerResolver -{ - protected $container; - - public function __construct(ContainerInterface $container, LoggerInterface $logger = null) - { - $this->container = $container; - - parent::__construct($logger); - } - - protected function createController(string $controller) - { - if (1 === substr_count($controller, ':')) { - $controller = str_replace(':', '::', $controller); - trigger_deprecation('symfony/http-kernel', '5.1', 'Referencing controllers with a single colon is deprecated. Use "%s" instead.', $controller); - } - - return parent::createController($controller); - } - - /** - * {@inheritdoc} - */ - protected function instantiateController(string $class) - { - $class = ltrim($class, '\\'); - - if ($this->container->has($class)) { - return $this->container->get($class); - } - - try { - return parent::instantiateController($class); - } catch (\Error $e) { - } - - $this->throwExceptionIfControllerWasRemoved($class, $e); - - if ($e instanceof \ArgumentCountError) { - throw new \InvalidArgumentException(sprintf('Controller "%s" has required constructor arguments and does not exist in the container. Did you forget to define the controller as a service?', $class), 0, $e); - } - - throw new \InvalidArgumentException(sprintf('Controller "%s" does neither exist as service nor as class.', $class), 0, $e); - } - - private function throwExceptionIfControllerWasRemoved(string $controller, \Throwable $previous) - { - if ($this->container instanceof Container && isset($this->container->getRemovedIds()[$controller])) { - throw new \InvalidArgumentException(sprintf('Controller "%s" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?', $controller), 0, $previous); - } - } -} diff --git a/lib/symfony/http-kernel/Controller/ControllerReference.php b/lib/symfony/http-kernel/Controller/ControllerReference.php deleted file mode 100644 index b4fdadd21..000000000 --- a/lib/symfony/http-kernel/Controller/ControllerReference.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller; - -use Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface; - -/** - * Acts as a marker and a data holder for a Controller. - * - * Some methods in Symfony accept both a URI (as a string) or a controller as - * an argument. In the latter case, instead of passing an array representing - * the controller, you can use an instance of this class. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @see FragmentRendererInterface - */ -class ControllerReference -{ - public $controller; - public $attributes = []; - public $query = []; - - /** - * @param string $controller The controller name - * @param array $attributes An array of parameters to add to the Request attributes - * @param array $query An array of parameters to add to the Request query string - */ - public function __construct(string $controller, array $attributes = [], array $query = []) - { - $this->controller = $controller; - $this->attributes = $attributes; - $this->query = $query; - } -} diff --git a/lib/symfony/http-kernel/Controller/ControllerResolver.php b/lib/symfony/http-kernel/Controller/ControllerResolver.php deleted file mode 100644 index 8abbadd48..000000000 --- a/lib/symfony/http-kernel/Controller/ControllerResolver.php +++ /dev/null @@ -1,220 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller; - -use Psr\Log\LoggerInterface; -use Symfony\Component\HttpFoundation\Request; - -/** - * This implementation uses the '_controller' request attribute to determine - * the controller to execute. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Tobias Schultze <http://tobion.de> - */ -class ControllerResolver implements ControllerResolverInterface -{ - private $logger; - - public function __construct(LoggerInterface $logger = null) - { - $this->logger = $logger; - } - - /** - * {@inheritdoc} - */ - public function getController(Request $request) - { - if (!$controller = $request->attributes->get('_controller')) { - if (null !== $this->logger) { - $this->logger->warning('Unable to look for the controller as the "_controller" parameter is missing.'); - } - - return false; - } - - if (\is_array($controller)) { - if (isset($controller[0]) && \is_string($controller[0]) && isset($controller[1])) { - try { - $controller[0] = $this->instantiateController($controller[0]); - } catch (\Error|\LogicException $e) { - try { - // We cannot just check is_callable but have to use reflection because a non-static method - // can still be called statically in PHP but we don't want that. This is deprecated in PHP 7, so we - // could simplify this with PHP 8. - if ((new \ReflectionMethod($controller[0], $controller[1]))->isStatic()) { - return $controller; - } - } catch (\ReflectionException $reflectionException) { - throw $e; - } - - throw $e; - } - } - - if (!\is_callable($controller)) { - throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable: ', $request->getPathInfo()).$this->getControllerError($controller)); - } - - return $controller; - } - - if (\is_object($controller)) { - if (!\is_callable($controller)) { - throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable: ', $request->getPathInfo()).$this->getControllerError($controller)); - } - - return $controller; - } - - if (\function_exists($controller)) { - return $controller; - } - - try { - $callable = $this->createController($controller); - } catch (\InvalidArgumentException $e) { - throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable: ', $request->getPathInfo()).$e->getMessage(), 0, $e); - } - - if (!\is_callable($callable)) { - throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable: ', $request->getPathInfo()).$this->getControllerError($callable)); - } - - return $callable; - } - - /** - * Returns a callable for the given controller. - * - * @return callable - * - * @throws \InvalidArgumentException When the controller cannot be created - */ - protected function createController(string $controller) - { - if (!str_contains($controller, '::')) { - $controller = $this->instantiateController($controller); - - if (!\is_callable($controller)) { - throw new \InvalidArgumentException($this->getControllerError($controller)); - } - - return $controller; - } - - [$class, $method] = explode('::', $controller, 2); - - try { - $controller = [$this->instantiateController($class), $method]; - } catch (\Error|\LogicException $e) { - try { - if ((new \ReflectionMethod($class, $method))->isStatic()) { - return $class.'::'.$method; - } - } catch (\ReflectionException $reflectionException) { - throw $e; - } - - throw $e; - } - - if (!\is_callable($controller)) { - throw new \InvalidArgumentException($this->getControllerError($controller)); - } - - return $controller; - } - - /** - * Returns an instantiated controller. - * - * @return object - */ - protected function instantiateController(string $class) - { - return new $class(); - } - - private function getControllerError($callable): string - { - if (\is_string($callable)) { - if (str_contains($callable, '::')) { - $callable = explode('::', $callable, 2); - } else { - return sprintf('Function "%s" does not exist.', $callable); - } - } - - if (\is_object($callable)) { - $availableMethods = $this->getClassMethodsWithoutMagicMethods($callable); - $alternativeMsg = $availableMethods ? sprintf(' or use one of the available methods: "%s"', implode('", "', $availableMethods)) : ''; - - return sprintf('Controller class "%s" cannot be called without a method name. You need to implement "__invoke"%s.', get_debug_type($callable), $alternativeMsg); - } - - if (!\is_array($callable)) { - return sprintf('Invalid type for controller given, expected string, array or object, got "%s".', get_debug_type($callable)); - } - - if (!isset($callable[0]) || !isset($callable[1]) || 2 !== \count($callable)) { - return 'Invalid array callable, expected [controller, method].'; - } - - [$controller, $method] = $callable; - - if (\is_string($controller) && !class_exists($controller)) { - return sprintf('Class "%s" does not exist.', $controller); - } - - $className = \is_object($controller) ? get_debug_type($controller) : $controller; - - if (method_exists($controller, $method)) { - return sprintf('Method "%s" on class "%s" should be public and non-abstract.', $method, $className); - } - - $collection = $this->getClassMethodsWithoutMagicMethods($controller); - - $alternatives = []; - - foreach ($collection as $item) { - $lev = levenshtein($method, $item); - - if ($lev <= \strlen($method) / 3 || str_contains($item, $method)) { - $alternatives[] = $item; - } - } - - asort($alternatives); - - $message = sprintf('Expected method "%s" on class "%s"', $method, $className); - - if (\count($alternatives) > 0) { - $message .= sprintf(', did you mean "%s"?', implode('", "', $alternatives)); - } else { - $message .= sprintf('. Available methods: "%s".', implode('", "', $collection)); - } - - return $message; - } - - private function getClassMethodsWithoutMagicMethods($classOrObject): array - { - $methods = get_class_methods($classOrObject); - - return array_filter($methods, function (string $method) { - return 0 !== strncmp($method, '__', 2); - }); - } -} diff --git a/lib/symfony/http-kernel/Controller/ControllerResolverInterface.php b/lib/symfony/http-kernel/Controller/ControllerResolverInterface.php deleted file mode 100644 index 8b70a88f6..000000000 --- a/lib/symfony/http-kernel/Controller/ControllerResolverInterface.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller; - -use Symfony\Component\HttpFoundation\Request; - -/** - * A ControllerResolverInterface implementation knows how to determine the - * controller to execute based on a Request object. - * - * A Controller can be any valid PHP callable. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface ControllerResolverInterface -{ - /** - * Returns the Controller instance associated with a Request. - * - * As several resolvers can exist for a single application, a resolver must - * return false when it is not able to determine the controller. - * - * The resolver must only throw an exception when it should be able to load a - * controller but cannot because of some errors made by the developer. - * - * @return callable|false A PHP callable representing the Controller, - * or false if this resolver is not able to determine the controller - * - * @throws \LogicException If a controller was found based on the request but it is not callable - */ - public function getController(Request $request); -} diff --git a/lib/symfony/http-kernel/Controller/ErrorController.php b/lib/symfony/http-kernel/Controller/ErrorController.php deleted file mode 100644 index b6c440103..000000000 --- a/lib/symfony/http-kernel/Controller/ErrorController.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller; - -use Symfony\Component\ErrorHandler\ErrorRenderer\ErrorRendererInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Exception\HttpException; -use Symfony\Component\HttpKernel\HttpKernelInterface; - -/** - * Renders error or exception pages from a given FlattenException. - * - * @author Yonel Ceruto <yonelceruto@gmail.com> - * @author Matthias Pigulla <mp@webfactory.de> - */ -class ErrorController -{ - private $kernel; - private $controller; - private $errorRenderer; - - public function __construct(HttpKernelInterface $kernel, $controller, ErrorRendererInterface $errorRenderer) - { - $this->kernel = $kernel; - $this->controller = $controller; - $this->errorRenderer = $errorRenderer; - } - - public function __invoke(\Throwable $exception): Response - { - $exception = $this->errorRenderer->render($exception); - - return new Response($exception->getAsString(), $exception->getStatusCode(), $exception->getHeaders()); - } - - public function preview(Request $request, int $code): Response - { - /* - * This Request mimics the parameters set by - * \Symfony\Component\HttpKernel\EventListener\ErrorListener::duplicateRequest, with - * the additional "showException" flag. - */ - $subRequest = $request->duplicate(null, null, [ - '_controller' => $this->controller, - 'exception' => new HttpException($code, 'This is a sample exception.'), - 'logger' => null, - 'showException' => false, - ]); - - return $this->kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST); - } -} diff --git a/lib/symfony/http-kernel/Controller/TraceableArgumentResolver.php b/lib/symfony/http-kernel/Controller/TraceableArgumentResolver.php deleted file mode 100644 index e22cf082c..000000000 --- a/lib/symfony/http-kernel/Controller/TraceableArgumentResolver.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Stopwatch\Stopwatch; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -class TraceableArgumentResolver implements ArgumentResolverInterface -{ - private $resolver; - private $stopwatch; - - public function __construct(ArgumentResolverInterface $resolver, Stopwatch $stopwatch) - { - $this->resolver = $resolver; - $this->stopwatch = $stopwatch; - } - - /** - * {@inheritdoc} - */ - public function getArguments(Request $request, callable $controller) - { - $e = $this->stopwatch->start('controller.get_arguments'); - - $ret = $this->resolver->getArguments($request, $controller); - - $e->stop(); - - return $ret; - } -} diff --git a/lib/symfony/http-kernel/Controller/TraceableControllerResolver.php b/lib/symfony/http-kernel/Controller/TraceableControllerResolver.php deleted file mode 100644 index bf6b6aa1f..000000000 --- a/lib/symfony/http-kernel/Controller/TraceableControllerResolver.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Stopwatch\Stopwatch; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -class TraceableControllerResolver implements ControllerResolverInterface -{ - private $resolver; - private $stopwatch; - - public function __construct(ControllerResolverInterface $resolver, Stopwatch $stopwatch) - { - $this->resolver = $resolver; - $this->stopwatch = $stopwatch; - } - - /** - * {@inheritdoc} - */ - public function getController(Request $request) - { - $e = $this->stopwatch->start('controller.get_callable'); - - $ret = $this->resolver->getController($request); - - $e->stop(); - - return $ret; - } -} diff --git a/lib/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php b/lib/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php deleted file mode 100644 index 1a9ebc0c3..000000000 --- a/lib/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php +++ /dev/null @@ -1,163 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\ControllerMetadata; - -use Symfony\Component\HttpKernel\Attribute\ArgumentInterface; - -/** - * Responsible for storing metadata of an argument. - * - * @author Iltar van der Berg <kjarli@gmail.com> - */ -class ArgumentMetadata -{ - public const IS_INSTANCEOF = 2; - - private $name; - private $type; - private $isVariadic; - private $hasDefaultValue; - private $defaultValue; - private $isNullable; - private $attributes; - - /** - * @param object[] $attributes - */ - public function __construct(string $name, ?string $type, bool $isVariadic, bool $hasDefaultValue, $defaultValue, bool $isNullable = false, $attributes = []) - { - $this->name = $name; - $this->type = $type; - $this->isVariadic = $isVariadic; - $this->hasDefaultValue = $hasDefaultValue; - $this->defaultValue = $defaultValue; - $this->isNullable = $isNullable || null === $type || ($hasDefaultValue && null === $defaultValue); - - if (null === $attributes || $attributes instanceof ArgumentInterface) { - trigger_deprecation('symfony/http-kernel', '5.3', 'The "%s" constructor expects an array of PHP attributes as last argument, %s given.', __CLASS__, get_debug_type($attributes)); - $attributes = $attributes ? [$attributes] : []; - } - - $this->attributes = $attributes; - } - - /** - * Returns the name as given in PHP, $foo would yield "foo". - * - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * Returns the type of the argument. - * - * The type is the PHP class in 5.5+ and additionally the basic type in PHP 7.0+. - * - * @return string|null - */ - public function getType() - { - return $this->type; - } - - /** - * Returns whether the argument is defined as "...$variadic". - * - * @return bool - */ - public function isVariadic() - { - return $this->isVariadic; - } - - /** - * Returns whether the argument has a default value. - * - * Implies whether an argument is optional. - * - * @return bool - */ - public function hasDefaultValue() - { - return $this->hasDefaultValue; - } - - /** - * Returns whether the argument accepts null values. - * - * @return bool - */ - public function isNullable() - { - return $this->isNullable; - } - - /** - * Returns the default value of the argument. - * - * @throws \LogicException if no default value is present; {@see self::hasDefaultValue()} - * - * @return mixed - */ - public function getDefaultValue() - { - if (!$this->hasDefaultValue) { - throw new \LogicException(sprintf('Argument $%s does not have a default value. Use "%s::hasDefaultValue()" to avoid this exception.', $this->name, __CLASS__)); - } - - return $this->defaultValue; - } - - /** - * Returns the attribute (if any) that was set on the argument. - */ - public function getAttribute(): ?ArgumentInterface - { - trigger_deprecation('symfony/http-kernel', '5.3', 'Method "%s()" is deprecated, use "getAttributes()" instead.', __METHOD__); - - if (!$this->attributes) { - return null; - } - - return $this->attributes[0] instanceof ArgumentInterface ? $this->attributes[0] : null; - } - - /** - * @return object[] - */ - public function getAttributes(string $name = null, int $flags = 0): array - { - if (!$name) { - return $this->attributes; - } - - $attributes = []; - if ($flags & self::IS_INSTANCEOF) { - foreach ($this->attributes as $attribute) { - if ($attribute instanceof $name) { - $attributes[] = $attribute; - } - } - } else { - foreach ($this->attributes as $attribute) { - if (\get_class($attribute) === $name) { - $attributes[] = $attribute; - } - } - } - - return $attributes; - } -} diff --git a/lib/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php b/lib/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php deleted file mode 100644 index 85bb805f3..000000000 --- a/lib/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\ControllerMetadata; - -/** - * Builds {@see ArgumentMetadata} objects based on the given Controller. - * - * @author Iltar van der Berg <kjarli@gmail.com> - */ -final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface -{ - /** - * {@inheritdoc} - */ - public function createArgumentMetadata($controller): array - { - $arguments = []; - - if (\is_array($controller)) { - $reflection = new \ReflectionMethod($controller[0], $controller[1]); - $class = $reflection->class; - } elseif (\is_object($controller) && !$controller instanceof \Closure) { - $reflection = new \ReflectionMethod($controller, '__invoke'); - $class = $reflection->class; - } else { - $reflection = new \ReflectionFunction($controller); - if ($class = str_contains($reflection->name, '{closure}') ? null : (\PHP_VERSION_ID >= 80111 ? $reflection->getClosureCalledClass() : $reflection->getClosureScopeClass())) { - $class = $class->name; - } - } - - foreach ($reflection->getParameters() as $param) { - $attributes = []; - if (\PHP_VERSION_ID >= 80000) { - foreach ($param->getAttributes() as $reflectionAttribute) { - if (class_exists($reflectionAttribute->getName())) { - $attributes[] = $reflectionAttribute->newInstance(); - } - } - } - - $arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param, $class), $param->isVariadic(), $param->isDefaultValueAvailable(), $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null, $param->allowsNull(), $attributes); - } - - return $arguments; - } - - /** - * Returns an associated type to the given parameter if available. - */ - private function getType(\ReflectionParameter $parameter, ?string $class): ?string - { - if (!$type = $parameter->getType()) { - return null; - } - $name = $type instanceof \ReflectionNamedType ? $type->getName() : (string) $type; - - if (null !== $class) { - switch (strtolower($name)) { - case 'self': - return $class; - case 'parent': - return get_parent_class($class) ?: null; - } - } - - return $name; - } -} diff --git a/lib/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php b/lib/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php deleted file mode 100644 index a34befc22..000000000 --- a/lib/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\ControllerMetadata; - -/** - * Builds method argument data. - * - * @author Iltar van der Berg <kjarli@gmail.com> - */ -interface ArgumentMetadataFactoryInterface -{ - /** - * @param string|object|array $controller The controller to resolve the arguments for - * - * @return ArgumentMetadata[] - */ - public function createArgumentMetadata($controller); -} diff --git a/lib/symfony/http-kernel/DataCollector/AjaxDataCollector.php b/lib/symfony/http-kernel/DataCollector/AjaxDataCollector.php deleted file mode 100644 index fda6a4eaa..000000000 --- a/lib/symfony/http-kernel/DataCollector/AjaxDataCollector.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -/** - * @author Bart van den Burg <bart@burgov.nl> - * - * @final - */ -class AjaxDataCollector extends DataCollector -{ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - // all collecting is done client side - } - - public function reset() - { - // all collecting is done client side - } - - public function getName(): string - { - return 'ajax'; - } -} diff --git a/lib/symfony/http-kernel/DataCollector/ConfigDataCollector.php b/lib/symfony/http-kernel/DataCollector/ConfigDataCollector.php deleted file mode 100644 index 9819507aa..000000000 --- a/lib/symfony/http-kernel/DataCollector/ConfigDataCollector.php +++ /dev/null @@ -1,275 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Kernel; -use Symfony\Component\HttpKernel\KernelInterface; -use Symfony\Component\VarDumper\Caster\ClassStub; - -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class ConfigDataCollector extends DataCollector implements LateDataCollectorInterface -{ - /** - * @var KernelInterface - */ - private $kernel; - - /** - * Sets the Kernel associated with this Request. - */ - public function setKernel(KernelInterface $kernel = null) - { - $this->kernel = $kernel; - } - - /** - * {@inheritdoc} - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - $eom = \DateTime::createFromFormat('d/m/Y', '01/'.Kernel::END_OF_MAINTENANCE); - $eol = \DateTime::createFromFormat('d/m/Y', '01/'.Kernel::END_OF_LIFE); - - $this->data = [ - 'token' => $response->headers->get('X-Debug-Token'), - 'symfony_version' => Kernel::VERSION, - 'symfony_minor_version' => sprintf('%s.%s', Kernel::MAJOR_VERSION, Kernel::MINOR_VERSION), - 'symfony_lts' => 4 === Kernel::MINOR_VERSION, - 'symfony_state' => $this->determineSymfonyState(), - 'symfony_eom' => $eom->format('F Y'), - 'symfony_eol' => $eol->format('F Y'), - 'env' => isset($this->kernel) ? $this->kernel->getEnvironment() : 'n/a', - 'debug' => isset($this->kernel) ? $this->kernel->isDebug() : 'n/a', - 'php_version' => \PHP_VERSION, - 'php_architecture' => \PHP_INT_SIZE * 8, - 'php_intl_locale' => class_exists(\Locale::class, false) && \Locale::getDefault() ? \Locale::getDefault() : 'n/a', - 'php_timezone' => date_default_timezone_get(), - 'xdebug_enabled' => \extension_loaded('xdebug'), - 'apcu_enabled' => \extension_loaded('apcu') && filter_var(\ini_get('apc.enabled'), \FILTER_VALIDATE_BOOLEAN), - 'zend_opcache_enabled' => \extension_loaded('Zend OPcache') && filter_var(\ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN), - 'bundles' => [], - 'sapi_name' => \PHP_SAPI, - ]; - - if (isset($this->kernel)) { - foreach ($this->kernel->getBundles() as $name => $bundle) { - $this->data['bundles'][$name] = new ClassStub(\get_class($bundle)); - } - } - - if (preg_match('~^(\d+(?:\.\d+)*)(.+)?$~', $this->data['php_version'], $matches) && isset($matches[2])) { - $this->data['php_version'] = $matches[1]; - $this->data['php_version_extra'] = $matches[2]; - } - } - - /** - * {@inheritdoc} - */ - public function reset() - { - $this->data = []; - } - - public function lateCollect() - { - $this->data = $this->cloneVar($this->data); - } - - /** - * Gets the token. - */ - public function getToken(): ?string - { - return $this->data['token']; - } - - /** - * Gets the Symfony version. - */ - public function getSymfonyVersion(): string - { - return $this->data['symfony_version']; - } - - /** - * Returns the state of the current Symfony release. - * - * @return string One of: unknown, dev, stable, eom, eol - */ - public function getSymfonyState(): string - { - return $this->data['symfony_state']; - } - - /** - * Returns the minor Symfony version used (without patch numbers of extra - * suffix like "RC", "beta", etc.). - */ - public function getSymfonyMinorVersion(): string - { - return $this->data['symfony_minor_version']; - } - - /** - * Returns if the current Symfony version is a Long-Term Support one. - */ - public function isSymfonyLts(): bool - { - return $this->data['symfony_lts']; - } - - /** - * Returns the human readable date when this Symfony version ends its - * maintenance period. - */ - public function getSymfonyEom(): string - { - return $this->data['symfony_eom']; - } - - /** - * Returns the human readable date when this Symfony version reaches its - * "end of life" and won't receive bugs or security fixes. - */ - public function getSymfonyEol(): string - { - return $this->data['symfony_eol']; - } - - /** - * Gets the PHP version. - */ - public function getPhpVersion(): string - { - return $this->data['php_version']; - } - - /** - * Gets the PHP version extra part. - */ - public function getPhpVersionExtra(): ?string - { - return $this->data['php_version_extra'] ?? null; - } - - /** - * @return int The PHP architecture as number of bits (e.g. 32 or 64) - */ - public function getPhpArchitecture(): int - { - return $this->data['php_architecture']; - } - - public function getPhpIntlLocale(): string - { - return $this->data['php_intl_locale']; - } - - public function getPhpTimezone(): string - { - return $this->data['php_timezone']; - } - - /** - * Gets the environment. - */ - public function getEnv(): string - { - return $this->data['env']; - } - - /** - * Returns true if the debug is enabled. - * - * @return bool|string true if debug is enabled, false otherwise or a string if no kernel was set - */ - public function isDebug() - { - return $this->data['debug']; - } - - /** - * Returns true if the XDebug is enabled. - */ - public function hasXDebug(): bool - { - return $this->data['xdebug_enabled']; - } - - /** - * Returns true if APCu is enabled. - */ - public function hasApcu(): bool - { - return $this->data['apcu_enabled']; - } - - /** - * Returns true if Zend OPcache is enabled. - */ - public function hasZendOpcache(): bool - { - return $this->data['zend_opcache_enabled']; - } - - public function getBundles() - { - return $this->data['bundles']; - } - - /** - * Gets the PHP SAPI name. - */ - public function getSapiName(): string - { - return $this->data['sapi_name']; - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'config'; - } - - /** - * Tries to retrieve information about the current Symfony version. - * - * @return string One of: dev, stable, eom, eol - */ - private function determineSymfonyState(): string - { - $now = new \DateTime(); - $eom = \DateTime::createFromFormat('d/m/Y', '01/'.Kernel::END_OF_MAINTENANCE)->modify('last day of this month'); - $eol = \DateTime::createFromFormat('d/m/Y', '01/'.Kernel::END_OF_LIFE)->modify('last day of this month'); - - if ($now > $eol) { - $versionState = 'eol'; - } elseif ($now > $eom) { - $versionState = 'eom'; - } elseif ('' !== Kernel::EXTRA_VERSION) { - $versionState = 'dev'; - } else { - $versionState = 'stable'; - } - - return $versionState; - } -} diff --git a/lib/symfony/http-kernel/DataCollector/DataCollector.php b/lib/symfony/http-kernel/DataCollector/DataCollector.php deleted file mode 100644 index ccaf66da0..000000000 --- a/lib/symfony/http-kernel/DataCollector/DataCollector.php +++ /dev/null @@ -1,112 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -use Symfony\Component\VarDumper\Caster\CutStub; -use Symfony\Component\VarDumper\Caster\ReflectionCaster; -use Symfony\Component\VarDumper\Cloner\ClonerInterface; -use Symfony\Component\VarDumper\Cloner\Data; -use Symfony\Component\VarDumper\Cloner\Stub; -use Symfony\Component\VarDumper\Cloner\VarCloner; - -/** - * DataCollector. - * - * Children of this class must store the collected data in the data property. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Bernhard Schussek <bschussek@symfony.com> - */ -abstract class DataCollector implements DataCollectorInterface -{ - /** - * @var array|Data - */ - protected $data = []; - - /** - * @var ClonerInterface - */ - private $cloner; - - /** - * Converts the variable into a serializable Data instance. - * - * This array can be displayed in the template using - * the VarDumper component. - * - * @param mixed $var - * - * @return Data - */ - protected function cloneVar($var) - { - if ($var instanceof Data) { - return $var; - } - if (null === $this->cloner) { - $this->cloner = new VarCloner(); - $this->cloner->setMaxItems(-1); - $this->cloner->addCasters($this->getCasters()); - } - - return $this->cloner->cloneVar($var); - } - - /** - * @return callable[] The casters to add to the cloner - */ - protected function getCasters() - { - $casters = [ - '*' => function ($v, array $a, Stub $s, $isNested) { - if (!$v instanceof Stub) { - foreach ($a as $k => $v) { - if (\is_object($v) && !$v instanceof \DateTimeInterface && !$v instanceof Stub) { - $a[$k] = new CutStub($v); - } - } - } - - return $a; - }, - ] + ReflectionCaster::UNSET_CLOSURE_FILE_INFO; - - return $casters; - } - - /** - * @return array - */ - public function __sleep() - { - return ['data']; - } - - public function __wakeup() - { - } - - /** - * @internal to prevent implementing \Serializable - */ - final protected function serialize() - { - } - - /** - * @internal to prevent implementing \Serializable - */ - final protected function unserialize($data) - { - } -} diff --git a/lib/symfony/http-kernel/DataCollector/DataCollectorInterface.php b/lib/symfony/http-kernel/DataCollector/DataCollectorInterface.php deleted file mode 100644 index 1cb865fd6..000000000 --- a/lib/symfony/http-kernel/DataCollector/DataCollectorInterface.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Contracts\Service\ResetInterface; - -/** - * DataCollectorInterface. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface DataCollectorInterface extends ResetInterface -{ - /** - * Collects data for the given Request and Response. - */ - public function collect(Request $request, Response $response, \Throwable $exception = null); - - /** - * Returns the name of the collector. - * - * @return string - */ - public function getName(); -} diff --git a/lib/symfony/http-kernel/DataCollector/DumpDataCollector.php b/lib/symfony/http-kernel/DataCollector/DumpDataCollector.php deleted file mode 100644 index 08026e562..000000000 --- a/lib/symfony/http-kernel/DataCollector/DumpDataCollector.php +++ /dev/null @@ -1,292 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; -use Symfony\Component\Stopwatch\Stopwatch; -use Symfony\Component\VarDumper\Cloner\Data; -use Symfony\Component\VarDumper\Cloner\VarCloner; -use Symfony\Component\VarDumper\Dumper\CliDumper; -use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider; -use Symfony\Component\VarDumper\Dumper\DataDumperInterface; -use Symfony\Component\VarDumper\Dumper\HtmlDumper; -use Symfony\Component\VarDumper\Server\Connection; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @final - */ -class DumpDataCollector extends DataCollector implements DataDumperInterface -{ - private $stopwatch; - private $fileLinkFormat; - private $dataCount = 0; - private $isCollected = true; - private $clonesCount = 0; - private $clonesIndex = 0; - private $rootRefs; - private $charset; - private $requestStack; - private $dumper; - private $sourceContextProvider; - - /** - * @param string|FileLinkFormatter|null $fileLinkFormat - * @param DataDumperInterface|Connection|null $dumper - */ - public function __construct(Stopwatch $stopwatch = null, $fileLinkFormat = null, string $charset = null, RequestStack $requestStack = null, $dumper = null) - { - $fileLinkFormat = $fileLinkFormat ?: \ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); - $this->stopwatch = $stopwatch; - $this->fileLinkFormat = $fileLinkFormat instanceof FileLinkFormatter && false === $fileLinkFormat->format('', 0) ? false : $fileLinkFormat; - $this->charset = $charset ?: \ini_get('php.output_encoding') ?: \ini_get('default_charset') ?: 'UTF-8'; - $this->requestStack = $requestStack; - $this->dumper = $dumper; - - // All clones share these properties by reference: - $this->rootRefs = [ - &$this->data, - &$this->dataCount, - &$this->isCollected, - &$this->clonesCount, - ]; - - $this->sourceContextProvider = $dumper instanceof Connection && isset($dumper->getContextProviders()['source']) ? $dumper->getContextProviders()['source'] : new SourceContextProvider($this->charset); - } - - public function __clone() - { - $this->clonesIndex = ++$this->clonesCount; - } - - public function dump(Data $data) - { - if ($this->stopwatch) { - $this->stopwatch->start('dump'); - } - - ['name' => $name, 'file' => $file, 'line' => $line, 'file_excerpt' => $fileExcerpt] = $this->sourceContextProvider->getContext(); - - if ($this->dumper instanceof Connection) { - if (!$this->dumper->write($data)) { - $this->isCollected = false; - } - } elseif ($this->dumper) { - $this->doDump($this->dumper, $data, $name, $file, $line); - } else { - $this->isCollected = false; - } - - if (!$this->dataCount) { - $this->data = []; - } - $this->data[] = compact('data', 'name', 'file', 'line', 'fileExcerpt'); - ++$this->dataCount; - - if ($this->stopwatch) { - $this->stopwatch->stop('dump'); - } - } - - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - if (!$this->dataCount) { - $this->data = []; - } - - // Sub-requests and programmatic calls stay in the collected profile. - if ($this->dumper || ($this->requestStack && $this->requestStack->getMainRequest() !== $request) || $request->isXmlHttpRequest() || $request->headers->has('Origin')) { - return; - } - - // In all other conditions that remove the web debug toolbar, dumps are written on the output. - if (!$this->requestStack - || !$response->headers->has('X-Debug-Token') - || $response->isRedirection() - || ($response->headers->has('Content-Type') && !str_contains($response->headers->get('Content-Type'), 'html')) - || 'html' !== $request->getRequestFormat() - || false === strripos($response->getContent(), '</body>') - ) { - if ($response->headers->has('Content-Type') && str_contains($response->headers->get('Content-Type'), 'html')) { - $dumper = new HtmlDumper('php://output', $this->charset); - $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]); - } else { - $dumper = new CliDumper('php://output', $this->charset); - if (method_exists($dumper, 'setDisplayOptions')) { - $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]); - } - } - - foreach ($this->data as $dump) { - $this->doDump($dumper, $dump['data'], $dump['name'], $dump['file'], $dump['line']); - } - } - } - - public function reset() - { - if ($this->stopwatch) { - $this->stopwatch->reset(); - } - $this->data = []; - $this->dataCount = 0; - $this->isCollected = true; - $this->clonesCount = 0; - $this->clonesIndex = 0; - } - - /** - * @internal - */ - public function __sleep(): array - { - if (!$this->dataCount) { - $this->data = []; - } - - if ($this->clonesCount !== $this->clonesIndex) { - return []; - } - - $this->data[] = $this->fileLinkFormat; - $this->data[] = $this->charset; - $this->dataCount = 0; - $this->isCollected = true; - - return parent::__sleep(); - } - - /** - * @internal - */ - public function __wakeup() - { - parent::__wakeup(); - - $charset = array_pop($this->data); - $fileLinkFormat = array_pop($this->data); - $this->dataCount = \count($this->data); - foreach ($this->data as $dump) { - if (!\is_string($dump['name']) || !\is_string($dump['file']) || !\is_int($dump['line'])) { - throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); - } - } - - self::__construct($this->stopwatch, \is_string($fileLinkFormat) || $fileLinkFormat instanceof FileLinkFormatter ? $fileLinkFormat : null, \is_string($charset) ? $charset : null); - } - - public function getDumpsCount(): int - { - return $this->dataCount; - } - - public function getDumps(string $format, int $maxDepthLimit = -1, int $maxItemsPerDepth = -1): array - { - $data = fopen('php://memory', 'r+'); - - if ('html' === $format) { - $dumper = new HtmlDumper($data, $this->charset); - $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]); - } else { - throw new \InvalidArgumentException(sprintf('Invalid dump format: "%s".', $format)); - } - $dumps = []; - - if (!$this->dataCount) { - return $this->data = []; - } - - foreach ($this->data as $dump) { - $dumper->dump($dump['data']->withMaxDepth($maxDepthLimit)->withMaxItemsPerDepth($maxItemsPerDepth)); - $dump['data'] = stream_get_contents($data, -1, 0); - ftruncate($data, 0); - rewind($data); - $dumps[] = $dump; - } - - return $dumps; - } - - public function getName(): string - { - return 'dump'; - } - - public function __destruct() - { - if (0 === $this->clonesCount-- && !$this->isCollected && $this->dataCount) { - $this->clonesCount = 0; - $this->isCollected = true; - - $h = headers_list(); - $i = \count($h); - array_unshift($h, 'Content-Type: '.\ini_get('default_mimetype')); - while (0 !== stripos($h[$i], 'Content-Type:')) { - --$i; - } - - if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && stripos($h[$i], 'html')) { - $dumper = new HtmlDumper('php://output', $this->charset); - $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]); - } else { - $dumper = new CliDumper('php://output', $this->charset); - if (method_exists($dumper, 'setDisplayOptions')) { - $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]); - } - } - - foreach ($this->data as $i => $dump) { - $this->data[$i] = null; - $this->doDump($dumper, $dump['data'], $dump['name'], $dump['file'], $dump['line']); - } - - $this->data = []; - $this->dataCount = 0; - } - } - - private function doDump(DataDumperInterface $dumper, Data $data, string $name, string $file, int $line) - { - if ($dumper instanceof CliDumper) { - $contextDumper = function ($name, $file, $line, $fmt) { - if ($this instanceof HtmlDumper) { - if ($file) { - $s = $this->style('meta', '%s'); - $f = strip_tags($this->style('', $file)); - $name = strip_tags($this->style('', $name)); - if ($fmt && $link = \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line)) { - $name = sprintf('<a href="%s" title="%s">'.$s.'</a>', strip_tags($this->style('', $link)), $f, $name); - } else { - $name = sprintf('<abbr title="%s">'.$s.'</abbr>', $f, $name); - } - } else { - $name = $this->style('meta', $name); - } - $this->line = $name.' on line '.$this->style('meta', $line).':'; - } else { - $this->line = $this->style('meta', $name).' on line '.$this->style('meta', $line).':'; - } - $this->dumpLine(0); - }; - $contextDumper = $contextDumper->bindTo($dumper, $dumper); - $contextDumper($name, $file, $line, $this->fileLinkFormat); - } else { - $cloner = new VarCloner(); - $dumper->dump($cloner->cloneVar($name.' on line '.$line.':')); - } - $dumper->dump($data); - } -} diff --git a/lib/symfony/http-kernel/DataCollector/EventDataCollector.php b/lib/symfony/http-kernel/DataCollector/EventDataCollector.php deleted file mode 100644 index a81355336..000000000 --- a/lib/symfony/http-kernel/DataCollector/EventDataCollector.php +++ /dev/null @@ -1,137 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\VarDumper\Cloner\Data; -use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; -use Symfony\Contracts\Service\ResetInterface; - -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class EventDataCollector extends DataCollector implements LateDataCollectorInterface -{ - protected $dispatcher; - private $requestStack; - private $currentRequest; - - public function __construct(EventDispatcherInterface $dispatcher = null, RequestStack $requestStack = null) - { - $this->dispatcher = $dispatcher; - $this->requestStack = $requestStack; - } - - /** - * {@inheritdoc} - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - $this->currentRequest = $this->requestStack && $this->requestStack->getMainRequest() !== $request ? $request : null; - $this->data = [ - 'called_listeners' => [], - 'not_called_listeners' => [], - 'orphaned_events' => [], - ]; - } - - public function reset() - { - $this->data = []; - - if ($this->dispatcher instanceof ResetInterface) { - $this->dispatcher->reset(); - } - } - - public function lateCollect() - { - if ($this->dispatcher instanceof TraceableEventDispatcher) { - $this->setCalledListeners($this->dispatcher->getCalledListeners($this->currentRequest)); - $this->setNotCalledListeners($this->dispatcher->getNotCalledListeners($this->currentRequest)); - $this->setOrphanedEvents($this->dispatcher->getOrphanedEvents($this->currentRequest)); - } - - $this->data = $this->cloneVar($this->data); - } - - /** - * @param array $listeners An array of called listeners - * - * @see TraceableEventDispatcher - */ - public function setCalledListeners(array $listeners) - { - $this->data['called_listeners'] = $listeners; - } - - /** - * @see TraceableEventDispatcher - * - * @return array|Data - */ - public function getCalledListeners() - { - return $this->data['called_listeners']; - } - - /** - * @see TraceableEventDispatcher - */ - public function setNotCalledListeners(array $listeners) - { - $this->data['not_called_listeners'] = $listeners; - } - - /** - * @see TraceableEventDispatcher - * - * @return array|Data - */ - public function getNotCalledListeners() - { - return $this->data['not_called_listeners']; - } - - /** - * @param array $events An array of orphaned events - * - * @see TraceableEventDispatcher - */ - public function setOrphanedEvents(array $events) - { - $this->data['orphaned_events'] = $events; - } - - /** - * @see TraceableEventDispatcher - * - * @return array|Data - */ - public function getOrphanedEvents() - { - return $this->data['orphaned_events']; - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'events'; - } -} diff --git a/lib/symfony/http-kernel/DataCollector/ExceptionDataCollector.php b/lib/symfony/http-kernel/DataCollector/ExceptionDataCollector.php deleted file mode 100644 index 14bbbb364..000000000 --- a/lib/symfony/http-kernel/DataCollector/ExceptionDataCollector.php +++ /dev/null @@ -1,85 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -use Symfony\Component\ErrorHandler\Exception\FlattenException; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class ExceptionDataCollector extends DataCollector -{ - /** - * {@inheritdoc} - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - if (null !== $exception) { - $this->data = [ - 'exception' => FlattenException::createFromThrowable($exception), - ]; - } - } - - /** - * {@inheritdoc} - */ - public function reset() - { - $this->data = []; - } - - public function hasException(): bool - { - return isset($this->data['exception']); - } - - /** - * @return \Exception|FlattenException - */ - public function getException() - { - return $this->data['exception']; - } - - public function getMessage(): string - { - return $this->data['exception']->getMessage(); - } - - public function getCode(): int - { - return $this->data['exception']->getCode(); - } - - public function getStatusCode(): int - { - return $this->data['exception']->getStatusCode(); - } - - public function getTrace(): array - { - return $this->data['exception']->getTrace(); - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'exception'; - } -} diff --git a/lib/symfony/http-kernel/DataCollector/LateDataCollectorInterface.php b/lib/symfony/http-kernel/DataCollector/LateDataCollectorInterface.php deleted file mode 100644 index 012332de4..000000000 --- a/lib/symfony/http-kernel/DataCollector/LateDataCollectorInterface.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -/** - * LateDataCollectorInterface. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface LateDataCollectorInterface -{ - /** - * Collects data as late as possible. - */ - public function lateCollect(); -} diff --git a/lib/symfony/http-kernel/DataCollector/LoggerDataCollector.php b/lib/symfony/http-kernel/DataCollector/LoggerDataCollector.php deleted file mode 100644 index 2bbd2a039..000000000 --- a/lib/symfony/http-kernel/DataCollector/LoggerDataCollector.php +++ /dev/null @@ -1,358 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; - -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class LoggerDataCollector extends DataCollector implements LateDataCollectorInterface -{ - private $logger; - private $containerPathPrefix; - private $currentRequest; - private $requestStack; - private $processedLogs; - - public function __construct(object $logger = null, string $containerPathPrefix = null, RequestStack $requestStack = null) - { - if (null !== $logger && $logger instanceof DebugLoggerInterface) { - $this->logger = $logger; - } - - $this->containerPathPrefix = $containerPathPrefix; - $this->requestStack = $requestStack; - } - - /** - * {@inheritdoc} - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - $this->currentRequest = $this->requestStack && $this->requestStack->getMainRequest() !== $request ? $request : null; - } - - /** - * {@inheritdoc} - */ - public function reset() - { - if ($this->logger instanceof DebugLoggerInterface) { - $this->logger->clear(); - } - $this->data = []; - } - - /** - * {@inheritdoc} - */ - public function lateCollect() - { - if (null !== $this->logger) { - $containerDeprecationLogs = $this->getContainerDeprecationLogs(); - $this->data = $this->computeErrorsCount($containerDeprecationLogs); - // get compiler logs later (only when they are needed) to improve performance - $this->data['compiler_logs'] = []; - $this->data['compiler_logs_filepath'] = $this->containerPathPrefix.'Compiler.log'; - $this->data['logs'] = $this->sanitizeLogs(array_merge($this->logger->getLogs($this->currentRequest), $containerDeprecationLogs)); - $this->data = $this->cloneVar($this->data); - } - $this->currentRequest = null; - } - - public function getLogs() - { - return $this->data['logs'] ?? []; - } - - public function getProcessedLogs() - { - if (null !== $this->processedLogs) { - return $this->processedLogs; - } - - $rawLogs = $this->getLogs(); - if ([] === $rawLogs) { - return $this->processedLogs = $rawLogs; - } - - $logs = []; - foreach ($this->getLogs()->getValue() as $rawLog) { - $rawLogData = $rawLog->getValue(); - - if ($rawLogData['priority']->getValue() > 300) { - $logType = 'error'; - } elseif (isset($rawLogData['scream']) && false === $rawLogData['scream']->getValue()) { - $logType = 'deprecation'; - } elseif (isset($rawLogData['scream']) && true === $rawLogData['scream']->getValue()) { - $logType = 'silenced'; - } else { - $logType = 'regular'; - } - - $logs[] = [ - 'type' => $logType, - 'errorCount' => $rawLog['errorCount'] ?? 1, - 'timestamp' => $rawLogData['timestamp_rfc3339']->getValue(), - 'priority' => $rawLogData['priority']->getValue(), - 'priorityName' => $rawLogData['priorityName']->getValue(), - 'channel' => $rawLogData['channel']->getValue(), - 'message' => $rawLogData['message'], - 'context' => $rawLogData['context'], - ]; - } - - // sort logs from oldest to newest - usort($logs, static function ($logA, $logB) { - return $logA['timestamp'] <=> $logB['timestamp']; - }); - - return $this->processedLogs = $logs; - } - - public function getFilters() - { - $filters = [ - 'channel' => [], - 'priority' => [ - 'Debug' => 100, - 'Info' => 200, - 'Notice' => 250, - 'Warning' => 300, - 'Error' => 400, - 'Critical' => 500, - 'Alert' => 550, - 'Emergency' => 600, - ], - ]; - - $allChannels = []; - foreach ($this->getProcessedLogs() as $log) { - if ('' === trim($log['channel'] ?? '')) { - continue; - } - - $allChannels[] = $log['channel']; - } - $channels = array_unique($allChannels); - sort($channels); - $filters['channel'] = $channels; - - return $filters; - } - - public function getPriorities() - { - return $this->data['priorities'] ?? []; - } - - public function countErrors() - { - return $this->data['error_count'] ?? 0; - } - - public function countDeprecations() - { - return $this->data['deprecation_count'] ?? 0; - } - - public function countWarnings() - { - return $this->data['warning_count'] ?? 0; - } - - public function countScreams() - { - return $this->data['scream_count'] ?? 0; - } - - public function getCompilerLogs() - { - return $this->cloneVar($this->getContainerCompilerLogs($this->data['compiler_logs_filepath'] ?? null)); - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'logger'; - } - - private function getContainerDeprecationLogs(): array - { - if (null === $this->containerPathPrefix || !is_file($file = $this->containerPathPrefix.'Deprecations.log')) { - return []; - } - - if ('' === $logContent = trim(file_get_contents($file))) { - return []; - } - - $bootTime = filemtime($file); - $logs = []; - foreach (unserialize($logContent) as $log) { - $log['context'] = ['exception' => new SilencedErrorContext($log['type'], $log['file'], $log['line'], $log['trace'], $log['count'])]; - $log['timestamp'] = $bootTime; - $log['timestamp_rfc3339'] = (new \DateTimeImmutable())->setTimestamp($bootTime)->format(\DateTimeInterface::RFC3339_EXTENDED); - $log['priority'] = 100; - $log['priorityName'] = 'DEBUG'; - $log['channel'] = null; - $log['scream'] = false; - unset($log['type'], $log['file'], $log['line'], $log['trace'], $log['trace'], $log['count']); - $logs[] = $log; - } - - return $logs; - } - - private function getContainerCompilerLogs(string $compilerLogsFilepath = null): array - { - if (!is_file($compilerLogsFilepath)) { - return []; - } - - $logs = []; - foreach (file($compilerLogsFilepath, \FILE_IGNORE_NEW_LINES) as $log) { - $log = explode(': ', $log, 2); - if (!isset($log[1]) || !preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)++$/', $log[0])) { - $log = ['Unknown Compiler Pass', implode(': ', $log)]; - } - - $logs[$log[0]][] = ['message' => $log[1]]; - } - - return $logs; - } - - private function sanitizeLogs(array $logs) - { - $sanitizedLogs = []; - $silencedLogs = []; - - foreach ($logs as $log) { - if (!$this->isSilencedOrDeprecationErrorLog($log)) { - $sanitizedLogs[] = $log; - - continue; - } - - $message = '_'.$log['message']; - $exception = $log['context']['exception']; - - if ($exception instanceof SilencedErrorContext) { - if (isset($silencedLogs[$h = spl_object_hash($exception)])) { - continue; - } - $silencedLogs[$h] = true; - - if (!isset($sanitizedLogs[$message])) { - $sanitizedLogs[$message] = $log + [ - 'errorCount' => 0, - 'scream' => true, - ]; - } - $sanitizedLogs[$message]['errorCount'] += $exception->count; - - continue; - } - - $errorId = md5("{$exception->getSeverity()}/{$exception->getLine()}/{$exception->getFile()}\0{$message}", true); - - if (isset($sanitizedLogs[$errorId])) { - ++$sanitizedLogs[$errorId]['errorCount']; - } else { - $log += [ - 'errorCount' => 1, - 'scream' => false, - ]; - - $sanitizedLogs[$errorId] = $log; - } - } - - return array_values($sanitizedLogs); - } - - private function isSilencedOrDeprecationErrorLog(array $log): bool - { - if (!isset($log['context']['exception'])) { - return false; - } - - $exception = $log['context']['exception']; - - if ($exception instanceof SilencedErrorContext) { - return true; - } - - if ($exception instanceof \ErrorException && \in_array($exception->getSeverity(), [\E_DEPRECATED, \E_USER_DEPRECATED], true)) { - return true; - } - - return false; - } - - private function computeErrorsCount(array $containerDeprecationLogs): array - { - $silencedLogs = []; - $count = [ - 'error_count' => $this->logger->countErrors($this->currentRequest), - 'deprecation_count' => 0, - 'warning_count' => 0, - 'scream_count' => 0, - 'priorities' => [], - ]; - - foreach ($this->logger->getLogs($this->currentRequest) as $log) { - if (isset($count['priorities'][$log['priority']])) { - ++$count['priorities'][$log['priority']]['count']; - } else { - $count['priorities'][$log['priority']] = [ - 'count' => 1, - 'name' => $log['priorityName'], - ]; - } - if ('WARNING' === $log['priorityName']) { - ++$count['warning_count']; - } - - if ($this->isSilencedOrDeprecationErrorLog($log)) { - $exception = $log['context']['exception']; - if ($exception instanceof SilencedErrorContext) { - if (isset($silencedLogs[$h = spl_object_hash($exception)])) { - continue; - } - $silencedLogs[$h] = true; - $count['scream_count'] += $exception->count; - } else { - ++$count['deprecation_count']; - } - } - } - - foreach ($containerDeprecationLogs as $deprecationLog) { - $count['deprecation_count'] += $deprecationLog['context']['exception']->count; - } - - ksort($count['priorities']); - - return $count; - } -} diff --git a/lib/symfony/http-kernel/DataCollector/MemoryDataCollector.php b/lib/symfony/http-kernel/DataCollector/MemoryDataCollector.php deleted file mode 100644 index 53a1f9e44..000000000 --- a/lib/symfony/http-kernel/DataCollector/MemoryDataCollector.php +++ /dev/null @@ -1,113 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class MemoryDataCollector extends DataCollector implements LateDataCollectorInterface -{ - public function __construct() - { - $this->reset(); - } - - /** - * {@inheritdoc} - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - $this->updateMemoryUsage(); - } - - /** - * {@inheritdoc} - */ - public function reset() - { - $this->data = [ - 'memory' => 0, - 'memory_limit' => $this->convertToBytes(\ini_get('memory_limit')), - ]; - } - - /** - * {@inheritdoc} - */ - public function lateCollect() - { - $this->updateMemoryUsage(); - } - - public function getMemory(): int - { - return $this->data['memory']; - } - - /** - * @return int|float - */ - public function getMemoryLimit() - { - return $this->data['memory_limit']; - } - - public function updateMemoryUsage() - { - $this->data['memory'] = memory_get_peak_usage(true); - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'memory'; - } - - /** - * @return int|float - */ - private function convertToBytes(string $memoryLimit) - { - if ('-1' === $memoryLimit) { - return -1; - } - - $memoryLimit = strtolower($memoryLimit); - $max = strtolower(ltrim($memoryLimit, '+')); - if (str_starts_with($max, '0x')) { - $max = \intval($max, 16); - } elseif (str_starts_with($max, '0')) { - $max = \intval($max, 8); - } else { - $max = (int) $max; - } - - switch (substr($memoryLimit, -1)) { - case 't': $max *= 1024; - // no break - case 'g': $max *= 1024; - // no break - case 'm': $max *= 1024; - // no break - case 'k': $max *= 1024; - } - - return $max; - } -} diff --git a/lib/symfony/http-kernel/DataCollector/RequestDataCollector.php b/lib/symfony/http-kernel/DataCollector/RequestDataCollector.php deleted file mode 100644 index 5717000f2..000000000 --- a/lib/symfony/http-kernel/DataCollector/RequestDataCollector.php +++ /dev/null @@ -1,504 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\Cookie; -use Symfony\Component\HttpFoundation\ParameterBag; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; -use Symfony\Component\HttpFoundation\Session\SessionInterface; -use Symfony\Component\HttpKernel\Event\ControllerEvent; -use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\VarDumper\Cloner\Data; - -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class RequestDataCollector extends DataCollector implements EventSubscriberInterface, LateDataCollectorInterface -{ - /** - * @var \SplObjectStorage<Request, callable> - */ - private $controllers; - private $sessionUsages = []; - private $requestStack; - - public function __construct(RequestStack $requestStack = null) - { - $this->controllers = new \SplObjectStorage(); - $this->requestStack = $requestStack; - } - - /** - * {@inheritdoc} - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - // attributes are serialized and as they can be anything, they need to be converted to strings. - $attributes = []; - $route = ''; - foreach ($request->attributes->all() as $key => $value) { - if ('_route' === $key) { - $route = \is_object($value) ? $value->getPath() : $value; - $attributes[$key] = $route; - } else { - $attributes[$key] = $value; - } - } - - $content = $request->getContent(); - - $sessionMetadata = []; - $sessionAttributes = []; - $flashes = []; - if ($request->hasSession()) { - $session = $request->getSession(); - if ($session->isStarted()) { - $sessionMetadata['Created'] = date(\DATE_RFC822, $session->getMetadataBag()->getCreated()); - $sessionMetadata['Last used'] = date(\DATE_RFC822, $session->getMetadataBag()->getLastUsed()); - $sessionMetadata['Lifetime'] = $session->getMetadataBag()->getLifetime(); - $sessionAttributes = $session->all(); - $flashes = $session->getFlashBag()->peekAll(); - } - } - - $statusCode = $response->getStatusCode(); - - $responseCookies = []; - foreach ($response->headers->getCookies() as $cookie) { - $responseCookies[$cookie->getName()] = $cookie; - } - - $dotenvVars = []; - foreach (explode(',', $_SERVER['SYMFONY_DOTENV_VARS'] ?? $_ENV['SYMFONY_DOTENV_VARS'] ?? '') as $name) { - if ('' !== $name && isset($_ENV[$name])) { - $dotenvVars[$name] = $_ENV[$name]; - } - } - - $this->data = [ - 'method' => $request->getMethod(), - 'format' => $request->getRequestFormat(), - 'content_type' => $response->headers->get('Content-Type', 'text/html'), - 'status_text' => Response::$statusTexts[$statusCode] ?? '', - 'status_code' => $statusCode, - 'request_query' => $request->query->all(), - 'request_request' => $request->request->all(), - 'request_files' => $request->files->all(), - 'request_headers' => $request->headers->all(), - 'request_server' => $request->server->all(), - 'request_cookies' => $request->cookies->all(), - 'request_attributes' => $attributes, - 'route' => $route, - 'response_headers' => $response->headers->all(), - 'response_cookies' => $responseCookies, - 'session_metadata' => $sessionMetadata, - 'session_attributes' => $sessionAttributes, - 'session_usages' => array_values($this->sessionUsages), - 'stateless_check' => $this->requestStack && ($mainRequest = $this->requestStack->getMainRequest()) && $mainRequest->attributes->get('_stateless', false), - 'flashes' => $flashes, - 'path_info' => $request->getPathInfo(), - 'controller' => 'n/a', - 'locale' => $request->getLocale(), - 'dotenv_vars' => $dotenvVars, - ]; - - if (isset($this->data['request_headers']['php-auth-pw'])) { - $this->data['request_headers']['php-auth-pw'] = '******'; - } - - if (isset($this->data['request_server']['PHP_AUTH_PW'])) { - $this->data['request_server']['PHP_AUTH_PW'] = '******'; - } - - if (isset($this->data['request_request']['_password'])) { - $encodedPassword = rawurlencode($this->data['request_request']['_password']); - $content = str_replace('_password='.$encodedPassword, '_password=******', $content); - $this->data['request_request']['_password'] = '******'; - } - - $this->data['content'] = $content; - - foreach ($this->data as $key => $value) { - if (!\is_array($value)) { - continue; - } - if ('request_headers' === $key || 'response_headers' === $key) { - $this->data[$key] = array_map(function ($v) { return isset($v[0]) && !isset($v[1]) ? $v[0] : $v; }, $value); - } - } - - if (isset($this->controllers[$request])) { - $this->data['controller'] = $this->parseController($this->controllers[$request]); - unset($this->controllers[$request]); - } - - if ($request->attributes->has('_redirected') && $redirectCookie = $request->cookies->get('sf_redirect')) { - $this->data['redirect'] = json_decode($redirectCookie, true); - - $response->headers->clearCookie('sf_redirect'); - } - - if ($response->isRedirect()) { - $response->headers->setCookie(new Cookie( - 'sf_redirect', - json_encode([ - 'token' => $response->headers->get('x-debug-token'), - 'route' => $request->attributes->get('_route', 'n/a'), - 'method' => $request->getMethod(), - 'controller' => $this->parseController($request->attributes->get('_controller')), - 'status_code' => $statusCode, - 'status_text' => Response::$statusTexts[$statusCode], - ]), - 0, '/', null, $request->isSecure(), true, false, 'lax' - )); - } - - $this->data['identifier'] = $this->data['route'] ?: (\is_array($this->data['controller']) ? $this->data['controller']['class'].'::'.$this->data['controller']['method'].'()' : $this->data['controller']); - - if ($response->headers->has('x-previous-debug-token')) { - $this->data['forward_token'] = $response->headers->get('x-previous-debug-token'); - } - } - - public function lateCollect() - { - $this->data = $this->cloneVar($this->data); - } - - public function reset() - { - $this->data = []; - $this->controllers = new \SplObjectStorage(); - $this->sessionUsages = []; - } - - public function getMethod() - { - return $this->data['method']; - } - - public function getPathInfo() - { - return $this->data['path_info']; - } - - public function getRequestRequest() - { - return new ParameterBag($this->data['request_request']->getValue()); - } - - public function getRequestQuery() - { - return new ParameterBag($this->data['request_query']->getValue()); - } - - public function getRequestFiles() - { - return new ParameterBag($this->data['request_files']->getValue()); - } - - public function getRequestHeaders() - { - return new ParameterBag($this->data['request_headers']->getValue()); - } - - public function getRequestServer(bool $raw = false) - { - return new ParameterBag($this->data['request_server']->getValue($raw)); - } - - public function getRequestCookies(bool $raw = false) - { - return new ParameterBag($this->data['request_cookies']->getValue($raw)); - } - - public function getRequestAttributes() - { - return new ParameterBag($this->data['request_attributes']->getValue()); - } - - public function getResponseHeaders() - { - return new ParameterBag($this->data['response_headers']->getValue()); - } - - public function getResponseCookies() - { - return new ParameterBag($this->data['response_cookies']->getValue()); - } - - public function getSessionMetadata() - { - return $this->data['session_metadata']->getValue(); - } - - public function getSessionAttributes() - { - return $this->data['session_attributes']->getValue(); - } - - public function getStatelessCheck() - { - return $this->data['stateless_check']; - } - - public function getSessionUsages() - { - return $this->data['session_usages']; - } - - public function getFlashes() - { - return $this->data['flashes']->getValue(); - } - - public function getContent() - { - return $this->data['content']; - } - - public function isJsonRequest() - { - return 1 === preg_match('{^application/(?:\w+\++)*json$}i', $this->data['request_headers']['content-type']); - } - - public function getPrettyJson() - { - $decoded = json_decode($this->getContent()); - - return \JSON_ERROR_NONE === json_last_error() ? json_encode($decoded, \JSON_PRETTY_PRINT) : null; - } - - public function getContentType() - { - return $this->data['content_type']; - } - - public function getStatusText() - { - return $this->data['status_text']; - } - - public function getStatusCode() - { - return $this->data['status_code']; - } - - public function getFormat() - { - return $this->data['format']; - } - - public function getLocale() - { - return $this->data['locale']; - } - - public function getDotenvVars() - { - return new ParameterBag($this->data['dotenv_vars']->getValue()); - } - - /** - * Gets the route name. - * - * The _route request attributes is automatically set by the Router Matcher. - */ - public function getRoute(): string - { - return $this->data['route']; - } - - public function getIdentifier() - { - return $this->data['identifier']; - } - - /** - * Gets the route parameters. - * - * The _route_params request attributes is automatically set by the RouterListener. - */ - public function getRouteParams(): array - { - return isset($this->data['request_attributes']['_route_params']) ? $this->data['request_attributes']['_route_params']->getValue() : []; - } - - /** - * Gets the parsed controller. - * - * @return array|string|Data The controller as a string or array of data - * with keys 'class', 'method', 'file' and 'line' - */ - public function getController() - { - return $this->data['controller']; - } - - /** - * Gets the previous request attributes. - * - * @return array|Data|false A legacy array of data from the previous redirection response - * or false otherwise - */ - public function getRedirect() - { - return $this->data['redirect'] ?? false; - } - - public function getForwardToken() - { - return $this->data['forward_token'] ?? null; - } - - public function onKernelController(ControllerEvent $event) - { - $this->controllers[$event->getRequest()] = $event->getController(); - } - - public function onKernelResponse(ResponseEvent $event) - { - if (!$event->isMainRequest()) { - return; - } - - if ($event->getRequest()->cookies->has('sf_redirect')) { - $event->getRequest()->attributes->set('_redirected', true); - } - } - - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::CONTROLLER => 'onKernelController', - KernelEvents::RESPONSE => 'onKernelResponse', - ]; - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'request'; - } - - public function collectSessionUsage(): void - { - $trace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS); - - $traceEndIndex = \count($trace) - 1; - for ($i = $traceEndIndex; $i > 0; --$i) { - if (null !== ($class = $trace[$i]['class'] ?? null) && (is_subclass_of($class, SessionInterface::class) || is_subclass_of($class, SessionBagInterface::class))) { - $traceEndIndex = $i; - break; - } - } - - if ((\count($trace) - 1) === $traceEndIndex) { - return; - } - - // Remove part of the backtrace that belongs to session only - array_splice($trace, 0, $traceEndIndex); - - // Merge identical backtraces generated by internal call reports - $name = sprintf('%s:%s', $trace[1]['class'] ?? $trace[0]['file'], $trace[0]['line']); - if (!\array_key_exists($name, $this->sessionUsages)) { - $this->sessionUsages[$name] = [ - 'name' => $name, - 'file' => $trace[0]['file'], - 'line' => $trace[0]['line'], - 'trace' => $trace, - ]; - } - } - - /** - * @param string|object|array|null $controller The controller to parse - * - * @return array|string An array of controller data or a simple string - */ - private function parseController($controller) - { - if (\is_string($controller) && str_contains($controller, '::')) { - $controller = explode('::', $controller); - } - - if (\is_array($controller)) { - try { - $r = new \ReflectionMethod($controller[0], $controller[1]); - - return [ - 'class' => \is_object($controller[0]) ? get_debug_type($controller[0]) : $controller[0], - 'method' => $controller[1], - 'file' => $r->getFileName(), - 'line' => $r->getStartLine(), - ]; - } catch (\ReflectionException $e) { - if (\is_callable($controller)) { - // using __call or __callStatic - return [ - 'class' => \is_object($controller[0]) ? get_debug_type($controller[0]) : $controller[0], - 'method' => $controller[1], - 'file' => 'n/a', - 'line' => 'n/a', - ]; - } - } - } - - if ($controller instanceof \Closure) { - $r = new \ReflectionFunction($controller); - - $controller = [ - 'class' => $r->getName(), - 'method' => null, - 'file' => $r->getFileName(), - 'line' => $r->getStartLine(), - ]; - - if (str_contains($r->name, '{closure}')) { - return $controller; - } - $controller['method'] = $r->name; - - if ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) { - $controller['class'] = $class->name; - } else { - return $r->name; - } - - return $controller; - } - - if (\is_object($controller)) { - $r = new \ReflectionClass($controller); - - return [ - 'class' => $r->getName(), - 'method' => null, - 'file' => $r->getFileName(), - 'line' => $r->getStartLine(), - ]; - } - - return \is_string($controller) ? $controller : 'n/a'; - } -} diff --git a/lib/symfony/http-kernel/DataCollector/RouterDataCollector.php b/lib/symfony/http-kernel/DataCollector/RouterDataCollector.php deleted file mode 100644 index 372ede037..000000000 --- a/lib/symfony/http-kernel/DataCollector/RouterDataCollector.php +++ /dev/null @@ -1,108 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -use Symfony\Component\HttpFoundation\RedirectResponse; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Event\ControllerEvent; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -class RouterDataCollector extends DataCollector -{ - /** - * @var \SplObjectStorage<Request, callable> - */ - protected $controllers; - - public function __construct() - { - $this->reset(); - } - - /** - * {@inheritdoc} - * - * @final - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - if ($response instanceof RedirectResponse) { - $this->data['redirect'] = true; - $this->data['url'] = $response->getTargetUrl(); - - if ($this->controllers->contains($request)) { - $this->data['route'] = $this->guessRoute($request, $this->controllers[$request]); - } - } - - unset($this->controllers[$request]); - } - - public function reset() - { - $this->controllers = new \SplObjectStorage(); - - $this->data = [ - 'redirect' => false, - 'url' => null, - 'route' => null, - ]; - } - - protected function guessRoute(Request $request, $controller) - { - return 'n/a'; - } - - /** - * Remembers the controller associated to each request. - */ - public function onKernelController(ControllerEvent $event) - { - $this->controllers[$event->getRequest()] = $event->getController(); - } - - /** - * @return bool Whether this request will result in a redirect - */ - public function getRedirect() - { - return $this->data['redirect']; - } - - /** - * @return string|null - */ - public function getTargetUrl() - { - return $this->data['url']; - } - - /** - * @return string|null - */ - public function getTargetRoute() - { - return $this->data['route']; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'router'; - } -} diff --git a/lib/symfony/http-kernel/DataCollector/TimeDataCollector.php b/lib/symfony/http-kernel/DataCollector/TimeDataCollector.php deleted file mode 100644 index 43799060f..000000000 --- a/lib/symfony/http-kernel/DataCollector/TimeDataCollector.php +++ /dev/null @@ -1,143 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\KernelInterface; -use Symfony\Component\Stopwatch\Stopwatch; -use Symfony\Component\Stopwatch\StopwatchEvent; - -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class TimeDataCollector extends DataCollector implements LateDataCollectorInterface -{ - private $kernel; - private $stopwatch; - - public function __construct(KernelInterface $kernel = null, Stopwatch $stopwatch = null) - { - $this->kernel = $kernel; - $this->stopwatch = $stopwatch; - } - - /** - * {@inheritdoc} - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - if (null !== $this->kernel) { - $startTime = $this->kernel->getStartTime(); - } else { - $startTime = $request->server->get('REQUEST_TIME_FLOAT'); - } - - $this->data = [ - 'token' => $request->attributes->get('_stopwatch_token'), - 'start_time' => $startTime * 1000, - 'events' => [], - 'stopwatch_installed' => class_exists(Stopwatch::class, false), - ]; - } - - /** - * {@inheritdoc} - */ - public function reset() - { - $this->data = []; - - if (null !== $this->stopwatch) { - $this->stopwatch->reset(); - } - } - - /** - * {@inheritdoc} - */ - public function lateCollect() - { - if (null !== $this->stopwatch && isset($this->data['token'])) { - $this->setEvents($this->stopwatch->getSectionEvents($this->data['token'])); - } - unset($this->data['token']); - } - - /** - * @param StopwatchEvent[] $events The request events - */ - public function setEvents(array $events) - { - foreach ($events as $event) { - $event->ensureStopped(); - } - - $this->data['events'] = $events; - } - - /** - * @return StopwatchEvent[] - */ - public function getEvents(): array - { - return $this->data['events']; - } - - /** - * Gets the request elapsed time. - */ - public function getDuration(): float - { - if (!isset($this->data['events']['__section__'])) { - return 0; - } - - $lastEvent = $this->data['events']['__section__']; - - return $lastEvent->getOrigin() + $lastEvent->getDuration() - $this->getStartTime(); - } - - /** - * Gets the initialization time. - * - * This is the time spent until the beginning of the request handling. - */ - public function getInitTime(): float - { - if (!isset($this->data['events']['__section__'])) { - return 0; - } - - return $this->data['events']['__section__']->getOrigin() - $this->getStartTime(); - } - - public function getStartTime(): float - { - return $this->data['start_time']; - } - - public function isStopwatchInstalled(): bool - { - return $this->data['stopwatch_installed']; - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'time'; - } -} diff --git a/lib/symfony/http-kernel/Debug/FileLinkFormatter.php b/lib/symfony/http-kernel/Debug/FileLinkFormatter.php deleted file mode 100644 index 9ac688cc5..000000000 --- a/lib/symfony/http-kernel/Debug/FileLinkFormatter.php +++ /dev/null @@ -1,116 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Debug; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; - -/** - * Formats debug file links. - * - * @author Jérémy Romey <jeremy@free-agent.fr> - * - * @final - */ -class FileLinkFormatter -{ - private const FORMATS = [ - 'textmate' => 'txmt://open?url=file://%f&line=%l', - 'macvim' => 'mvim://open?url=file://%f&line=%l', - 'emacs' => 'emacs://open?url=file://%f&line=%l', - 'sublime' => 'subl://open?url=file://%f&line=%l', - 'phpstorm' => 'phpstorm://open?file=%f&line=%l', - 'atom' => 'atom://core/open/file?filename=%f&line=%l', - 'vscode' => 'vscode://file/%f:%l', - ]; - - private $fileLinkFormat; - private $requestStack; - private $baseDir; - private $urlFormat; - - /** - * @param string|array|null $fileLinkFormat - * @param string|\Closure $urlFormat the URL format, or a closure that returns it on-demand - */ - public function __construct($fileLinkFormat = null, RequestStack $requestStack = null, string $baseDir = null, $urlFormat = null) - { - if (!\is_array($fileLinkFormat) && $fileLinkFormat = (self::FORMATS[$fileLinkFormat] ?? $fileLinkFormat) ?: \ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format')) { - $i = strpos($f = $fileLinkFormat, '&', max(strrpos($f, '%f'), strrpos($f, '%l'))) ?: \strlen($f); - $fileLinkFormat = [substr($f, 0, $i)] + preg_split('/&([^>]++)>/', substr($f, $i), -1, \PREG_SPLIT_DELIM_CAPTURE); - } - - $this->fileLinkFormat = $fileLinkFormat; - $this->requestStack = $requestStack; - $this->baseDir = $baseDir; - $this->urlFormat = $urlFormat; - } - - public function format(string $file, int $line) - { - if ($fmt = $this->getFileLinkFormat()) { - for ($i = 1; isset($fmt[$i]); ++$i) { - if (str_starts_with($file, $k = $fmt[$i++])) { - $file = substr_replace($file, $fmt[$i], 0, \strlen($k)); - break; - } - } - - return strtr($fmt[0], ['%f' => $file, '%l' => $line]); - } - - return false; - } - - /** - * @internal - */ - public function __sleep(): array - { - $this->fileLinkFormat = $this->getFileLinkFormat(); - - return ['fileLinkFormat']; - } - - /** - * @internal - */ - public static function generateUrlFormat(UrlGeneratorInterface $router, string $routeName, string $queryString): ?string - { - try { - return $router->generate($routeName).$queryString; - } catch (\Throwable $e) { - return null; - } - } - - private function getFileLinkFormat() - { - if ($this->fileLinkFormat) { - return $this->fileLinkFormat; - } - - if ($this->requestStack && $this->baseDir && $this->urlFormat) { - $request = $this->requestStack->getMainRequest(); - - if ($request instanceof Request && (!$this->urlFormat instanceof \Closure || $this->urlFormat = ($this->urlFormat)())) { - return [ - $request->getSchemeAndHttpHost().$this->urlFormat, - $this->baseDir.\DIRECTORY_SEPARATOR, '', - ]; - } - } - - return null; - } -} diff --git a/lib/symfony/http-kernel/Debug/TraceableEventDispatcher.php b/lib/symfony/http-kernel/Debug/TraceableEventDispatcher.php deleted file mode 100644 index fd1cf9e58..000000000 --- a/lib/symfony/http-kernel/Debug/TraceableEventDispatcher.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Debug; - -use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher as BaseTraceableEventDispatcher; -use Symfony\Component\HttpKernel\KernelEvents; - -/** - * Collects some data about event listeners. - * - * This event dispatcher delegates the dispatching to another one. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class TraceableEventDispatcher extends BaseTraceableEventDispatcher -{ - /** - * {@inheritdoc} - */ - protected function beforeDispatch(string $eventName, object $event) - { - switch ($eventName) { - case KernelEvents::REQUEST: - $event->getRequest()->attributes->set('_stopwatch_token', substr(hash('sha256', uniqid(mt_rand(), true)), 0, 6)); - $this->stopwatch->openSection(); - break; - case KernelEvents::VIEW: - case KernelEvents::RESPONSE: - // stop only if a controller has been executed - if ($this->stopwatch->isStarted('controller')) { - $this->stopwatch->stop('controller'); - } - break; - case KernelEvents::TERMINATE: - $sectionId = $event->getRequest()->attributes->get('_stopwatch_token'); - if (null === $sectionId) { - break; - } - // There is a very special case when using built-in AppCache class as kernel wrapper, in the case - // of an ESI request leading to a `stale` response [B] inside a `fresh` cached response [A]. - // In this case, `$token` contains the [B] debug token, but the open `stopwatch` section ID - // is equal to the [A] debug token. Trying to reopen section with the [B] token throws an exception - // which must be caught. - try { - $this->stopwatch->openSection($sectionId); - } catch (\LogicException $e) { - } - break; - } - } - - /** - * {@inheritdoc} - */ - protected function afterDispatch(string $eventName, object $event) - { - switch ($eventName) { - case KernelEvents::CONTROLLER_ARGUMENTS: - $this->stopwatch->start('controller', 'section'); - break; - case KernelEvents::RESPONSE: - $sectionId = $event->getRequest()->attributes->get('_stopwatch_token'); - if (null === $sectionId) { - break; - } - $this->stopwatch->stopSection($sectionId); - break; - case KernelEvents::TERMINATE: - // In the special case described in the `preDispatch` method above, the `$token` section - // does not exist, then closing it throws an exception which must be caught. - $sectionId = $event->getRequest()->attributes->get('_stopwatch_token'); - if (null === $sectionId) { - break; - } - try { - $this->stopwatch->stopSection($sectionId); - } catch (\LogicException $e) { - } - break; - } - } -} diff --git a/lib/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php b/lib/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php deleted file mode 100644 index 4bb60b41f..000000000 --- a/lib/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php +++ /dev/null @@ -1,146 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Composer\Autoload\ClassLoader; -use Symfony\Component\Debug\DebugClassLoader as LegacyDebugClassLoader; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\ErrorHandler\DebugClassLoader; -use Symfony\Component\HttpKernel\Kernel; - -/** - * Sets the classes to compile in the cache for the container. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class AddAnnotatedClassesToCachePass implements CompilerPassInterface -{ - private $kernel; - - public function __construct(Kernel $kernel) - { - $this->kernel = $kernel; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - $annotatedClasses = []; - foreach ($container->getExtensions() as $extension) { - if ($extension instanceof Extension) { - $annotatedClasses[] = $extension->getAnnotatedClassesToCompile(); - } - } - - $annotatedClasses = array_merge($this->kernel->getAnnotatedClassesToCompile(), ...$annotatedClasses); - - $existingClasses = $this->getClassesInComposerClassMaps(); - - $annotatedClasses = $container->getParameterBag()->resolveValue($annotatedClasses); - $this->kernel->setAnnotatedClassCache($this->expandClasses($annotatedClasses, $existingClasses)); - } - - /** - * Expands the given class patterns using a list of existing classes. - * - * @param array $patterns The class patterns to expand - * @param array $classes The existing classes to match against the patterns - */ - private function expandClasses(array $patterns, array $classes): array - { - $expanded = []; - - // Explicit classes declared in the patterns are returned directly - foreach ($patterns as $key => $pattern) { - if (!str_ends_with($pattern, '\\') && !str_contains($pattern, '*')) { - unset($patterns[$key]); - $expanded[] = ltrim($pattern, '\\'); - } - } - - // Match patterns with the classes list - $regexps = $this->patternsToRegexps($patterns); - - foreach ($classes as $class) { - $class = ltrim($class, '\\'); - - if ($this->matchAnyRegexps($class, $regexps)) { - $expanded[] = $class; - } - } - - return array_unique($expanded); - } - - private function getClassesInComposerClassMaps(): array - { - $classes = []; - - foreach (spl_autoload_functions() as $function) { - if (!\is_array($function)) { - continue; - } - - if ($function[0] instanceof DebugClassLoader || $function[0] instanceof LegacyDebugClassLoader) { - $function = $function[0]->getClassLoader(); - } - - if (\is_array($function) && $function[0] instanceof ClassLoader) { - $classes += array_filter($function[0]->getClassMap()); - } - } - - return array_keys($classes); - } - - private function patternsToRegexps(array $patterns): array - { - $regexps = []; - - foreach ($patterns as $pattern) { - // Escape user input - $regex = preg_quote(ltrim($pattern, '\\')); - - // Wildcards * and ** - $regex = strtr($regex, ['\\*\\*' => '.*?', '\\*' => '[^\\\\]*?']); - - // If this class does not end by a slash, anchor the end - if ('\\' !== substr($regex, -1)) { - $regex .= '$'; - } - - $regexps[] = '{^\\\\'.$regex.'}'; - } - - return $regexps; - } - - private function matchAnyRegexps(string $class, array $regexps): bool - { - $isTest = str_contains($class, 'Test'); - - foreach ($regexps as $regex) { - if ($isTest && !str_contains($regex, 'Test')) { - continue; - } - - if (preg_match($regex, '\\'.$class)) { - return true; - } - } - - return false; - } -} diff --git a/lib/symfony/http-kernel/DependencyInjection/ConfigurableExtension.php b/lib/symfony/http-kernel/DependencyInjection/ConfigurableExtension.php deleted file mode 100644 index 072c35f1c..000000000 --- a/lib/symfony/http-kernel/DependencyInjection/ConfigurableExtension.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * This extension sub-class provides first-class integration with the - * Config/Definition Component. - * - * You can use this as base class if - * - * a) you use the Config/Definition component for configuration, - * b) your configuration class is named "Configuration", and - * c) the configuration class resides in the DependencyInjection sub-folder. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - */ -abstract class ConfigurableExtension extends Extension -{ - /** - * {@inheritdoc} - */ - final public function load(array $configs, ContainerBuilder $container) - { - $this->loadInternal($this->processConfiguration($this->getConfiguration($configs, $container), $configs), $container); - } - - /** - * Configures the passed container according to the merged configuration. - */ - abstract protected function loadInternal(array $mergedConfig, ContainerBuilder $container); -} diff --git a/lib/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php b/lib/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php deleted file mode 100644 index d925ed6b0..000000000 --- a/lib/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php +++ /dev/null @@ -1,68 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver; -use Symfony\Component\Stopwatch\Stopwatch; - -/** - * Gathers and configures the argument value resolvers. - * - * @author Iltar van der Berg <kjarli@gmail.com> - */ -class ControllerArgumentValueResolverPass implements CompilerPassInterface -{ - use PriorityTaggedServiceTrait; - - private $argumentResolverService; - private $argumentValueResolverTag; - private $traceableResolverStopwatch; - - public function __construct(string $argumentResolverService = 'argument_resolver', string $argumentValueResolverTag = 'controller.argument_value_resolver', string $traceableResolverStopwatch = 'debug.stopwatch') - { - if (0 < \func_num_args()) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->argumentResolverService = $argumentResolverService; - $this->argumentValueResolverTag = $argumentValueResolverTag; - $this->traceableResolverStopwatch = $traceableResolverStopwatch; - } - - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition($this->argumentResolverService)) { - return; - } - - $resolvers = $this->findAndSortTaggedServices($this->argumentValueResolverTag, $container); - - if ($container->getParameter('kernel.debug') && class_exists(Stopwatch::class) && $container->has($this->traceableResolverStopwatch)) { - foreach ($resolvers as $resolverReference) { - $id = (string) $resolverReference; - $container->register("debug.$id", TraceableValueResolver::class) - ->setDecoratedService($id) - ->setArguments([new Reference("debug.$id.inner"), new Reference($this->traceableResolverStopwatch)]); - } - } - - $container - ->getDefinition($this->argumentResolverService) - ->replaceArgument(1, new IteratorArgument($resolvers)) - ; - } -} diff --git a/lib/symfony/http-kernel/DependencyInjection/Extension.php b/lib/symfony/http-kernel/DependencyInjection/Extension.php deleted file mode 100644 index 4090fd822..000000000 --- a/lib/symfony/http-kernel/DependencyInjection/Extension.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Symfony\Component\DependencyInjection\Extension\Extension as BaseExtension; - -/** - * Allow adding classes to the class cache. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -abstract class Extension extends BaseExtension -{ - private $annotatedClasses = []; - - /** - * Gets the annotated classes to cache. - * - * @return array - */ - public function getAnnotatedClassesToCompile() - { - return $this->annotatedClasses; - } - - /** - * Adds annotated classes to the class cache. - * - * @param array $annotatedClasses An array of class patterns - */ - public function addAnnotatedClassesToCompile(array $annotatedClasses) - { - $this->annotatedClasses = array_merge($this->annotatedClasses, $annotatedClasses); - } -} diff --git a/lib/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php b/lib/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php deleted file mode 100644 index f26baeca9..000000000 --- a/lib/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -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\HttpKernel\Fragment\FragmentRendererInterface; - -/** - * Adds services tagged kernel.fragment_renderer as HTTP content rendering strategies. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class FragmentRendererPass implements CompilerPassInterface -{ - private $handlerService; - private $rendererTag; - - public function __construct(string $handlerService = 'fragment.handler', string $rendererTag = 'kernel.fragment_renderer') - { - if (0 < \func_num_args()) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->handlerService = $handlerService; - $this->rendererTag = $rendererTag; - } - - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition($this->handlerService)) { - return; - } - - $definition = $container->getDefinition($this->handlerService); - $renderers = []; - foreach ($container->findTaggedServiceIds($this->rendererTag, true) as $id => $tags) { - $def = $container->getDefinition($id); - $class = $container->getParameterBag()->resolveValue($def->getClass()); - - if (!$r = $container->getReflectionClass($class)) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); - } - if (!$r->isSubclassOf(FragmentRendererInterface::class)) { - throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, FragmentRendererInterface::class)); - } - - foreach ($tags as $tag) { - $renderers[$tag['alias']] = new Reference($id); - } - } - - $definition->replaceArgument(0, ServiceLocatorTagPass::register($container, $renderers)); - } -} diff --git a/lib/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php b/lib/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php deleted file mode 100644 index f25328704..000000000 --- a/lib/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Psr\Container\ContainerInterface; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpKernel\Fragment\FragmentHandler; - -/** - * Lazily loads fragment renderers from the dependency injection container. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class LazyLoadingFragmentHandler extends FragmentHandler -{ - private $container; - - /** - * @var array<string, bool> - */ - private $initialized = []; - - public function __construct(ContainerInterface $container, RequestStack $requestStack, bool $debug = false) - { - $this->container = $container; - - parent::__construct($requestStack, [], $debug); - } - - /** - * {@inheritdoc} - */ - public function render($uri, string $renderer = 'inline', array $options = []) - { - if (!isset($this->initialized[$renderer]) && $this->container->has($renderer)) { - $this->addRenderer($this->container->get($renderer)); - $this->initialized[$renderer] = true; - } - - return parent::render($uri, $renderer, $options); - } -} diff --git a/lib/symfony/http-kernel/DependencyInjection/LoggerPass.php b/lib/symfony/http-kernel/DependencyInjection/LoggerPass.php deleted file mode 100644 index b6df1f6e6..000000000 --- a/lib/symfony/http-kernel/DependencyInjection/LoggerPass.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Psr\Log\LoggerInterface; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\HttpKernel\Log\Logger; - -/** - * Registers the default logger if necessary. - * - * @author Kévin Dunglas <dunglas@gmail.com> - */ -class LoggerPass implements CompilerPassInterface -{ - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - $container->setAlias(LoggerInterface::class, 'logger') - ->setPublic(false); - - if ($container->has('logger')) { - return; - } - - $container->register('logger', Logger::class) - ->setPublic(false); - } -} diff --git a/lib/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php b/lib/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php deleted file mode 100644 index 5f0f0d8de..000000000 --- a/lib/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Symfony\Component\DependencyInjection\Compiler\MergeExtensionConfigurationPass as BaseMergeExtensionConfigurationPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * Ensures certain extensions are always loaded. - * - * @author Kris Wallsmith <kris@symfony.com> - */ -class MergeExtensionConfigurationPass extends BaseMergeExtensionConfigurationPass -{ - private $extensions; - - /** - * @param string[] $extensions - */ - public function __construct(array $extensions) - { - $this->extensions = $extensions; - } - - public function process(ContainerBuilder $container) - { - foreach ($this->extensions as $extension) { - if (!\count($container->getExtensionConfig($extension))) { - $container->loadFromExtension($extension, []); - } - } - - parent::process($container); - } -} diff --git a/lib/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php b/lib/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php deleted file mode 100644 index 3dbaff564..000000000 --- a/lib/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php +++ /dev/null @@ -1,224 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; -use Symfony\Component\DependencyInjection\Attribute\Target; -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\TypedReference; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpFoundation\Session\SessionInterface; - -/** - * Creates the service-locators required by ServiceValueResolver. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface -{ - private $resolverServiceId; - private $controllerTag; - private $controllerLocator; - private $notTaggedControllerResolverServiceId; - - public function __construct(string $resolverServiceId = 'argument_resolver.service', string $controllerTag = 'controller.service_arguments', string $controllerLocator = 'argument_resolver.controller_locator', string $notTaggedControllerResolverServiceId = 'argument_resolver.not_tagged_controller') - { - if (0 < \func_num_args()) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->resolverServiceId = $resolverServiceId; - $this->controllerTag = $controllerTag; - $this->controllerLocator = $controllerLocator; - $this->notTaggedControllerResolverServiceId = $notTaggedControllerResolverServiceId; - } - - public function process(ContainerBuilder $container) - { - if (false === $container->hasDefinition($this->resolverServiceId) && false === $container->hasDefinition($this->notTaggedControllerResolverServiceId)) { - return; - } - - $parameterBag = $container->getParameterBag(); - $controllers = []; - - $publicAliases = []; - foreach ($container->getAliases() as $id => $alias) { - if ($alias->isPublic() && !$alias->isPrivate()) { - $publicAliases[(string) $alias][] = $id; - } - } - - foreach ($container->findTaggedServiceIds($this->controllerTag, true) as $id => $tags) { - $def = $container->getDefinition($id); - $def->setPublic(true); - $class = $def->getClass(); - $autowire = $def->isAutowired(); - $bindings = $def->getBindings(); - - // resolve service class, taking parent definitions into account - while ($def instanceof ChildDefinition) { - $def = $container->findDefinition($def->getParent()); - $class = $class ?: $def->getClass(); - $bindings += $def->getBindings(); - } - $class = $parameterBag->resolveValue($class); - - if (!$r = $container->getReflectionClass($class)) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); - } - $isContainerAware = $r->implementsInterface(ContainerAwareInterface::class) || is_subclass_of($class, AbstractController::class); - - // get regular public methods - $methods = []; - $arguments = []; - foreach ($r->getMethods(\ReflectionMethod::IS_PUBLIC) as $r) { - if ('setContainer' === $r->name && $isContainerAware) { - continue; - } - if (!$r->isConstructor() && !$r->isDestructor() && !$r->isAbstract()) { - $methods[strtolower($r->name)] = [$r, $r->getParameters()]; - } - } - - // validate and collect explicit per-actions and per-arguments service references - foreach ($tags as $attributes) { - if (!isset($attributes['action']) && !isset($attributes['argument']) && !isset($attributes['id'])) { - $autowire = true; - continue; - } - foreach (['action', 'argument', 'id'] as $k) { - if (!isset($attributes[$k][0])) { - throw new InvalidArgumentException(sprintf('Missing "%s" attribute on tag "%s" %s for service "%s".', $k, $this->controllerTag, json_encode($attributes, \JSON_UNESCAPED_UNICODE), $id)); - } - } - if (!isset($methods[$action = strtolower($attributes['action'])])) { - throw new InvalidArgumentException(sprintf('Invalid "action" attribute on tag "%s" for service "%s": no public "%s()" method found on class "%s".', $this->controllerTag, $id, $attributes['action'], $class)); - } - [$r, $parameters] = $methods[$action]; - $found = false; - - foreach ($parameters as $p) { - if ($attributes['argument'] === $p->name) { - if (!isset($arguments[$r->name][$p->name])) { - $arguments[$r->name][$p->name] = $attributes['id']; - } - $found = true; - break; - } - } - - if (!$found) { - throw new InvalidArgumentException(sprintf('Invalid "%s" tag for service "%s": method "%s()" has no "%s" argument on class "%s".', $this->controllerTag, $id, $r->name, $attributes['argument'], $class)); - } - } - - foreach ($methods as [$r, $parameters]) { - /** @var \ReflectionMethod $r */ - - // create a per-method map of argument-names to service/type-references - $args = []; - foreach ($parameters as $p) { - /** @var \ReflectionParameter $p */ - $type = ltrim($target = (string) ProxyHelper::getTypeHint($r, $p), '\\'); - $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; - - if (isset($arguments[$r->name][$p->name])) { - $target = $arguments[$r->name][$p->name]; - if ('?' !== $target[0]) { - $invalidBehavior = ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE; - } elseif ('' === $target = (string) substr($target, 1)) { - throw new InvalidArgumentException(sprintf('A "%s" tag must have non-empty "id" attributes for service "%s".', $this->controllerTag, $id)); - } elseif ($p->allowsNull() && !$p->isOptional()) { - $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; - } - } elseif (isset($bindings[$bindingName = $type.' $'.$name = Target::parseName($p)]) || isset($bindings[$bindingName = '$'.$name]) || isset($bindings[$bindingName = $type])) { - $binding = $bindings[$bindingName]; - - [$bindingValue, $bindingId, , $bindingType, $bindingFile] = $binding->getValues(); - $binding->setValues([$bindingValue, $bindingId, true, $bindingType, $bindingFile]); - - if (!$bindingValue instanceof Reference) { - $args[$p->name] = new Reference('.value.'.$container->hash($bindingValue)); - $container->register((string) $args[$p->name], 'mixed') - ->setFactory('current') - ->addArgument([$bindingValue]); - } else { - $args[$p->name] = $bindingValue; - } - - continue; - } elseif (!$type || !$autowire || '\\' !== $target[0]) { - continue; - } elseif (is_subclass_of($type, \UnitEnum::class)) { - // do not attempt to register enum typed arguments if not already present in bindings - continue; - } elseif (!$p->allowsNull()) { - $invalidBehavior = ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE; - } - - if (Request::class === $type || SessionInterface::class === $type || Response::class === $type) { - continue; - } - - if ($type && !$p->isOptional() && !$p->allowsNull() && !class_exists($type) && !interface_exists($type, false)) { - $message = sprintf('Cannot determine controller argument for "%s::%s()": the $%s argument is type-hinted with the non-existent class or interface: "%s".', $class, $r->name, $p->name, $type); - - // see if the type-hint lives in the same namespace as the controller - if (0 === strncmp($type, $class, strrpos($class, '\\'))) { - $message .= ' Did you forget to add a use statement?'; - } - - $container->register($erroredId = '.errored.'.$container->hash($message), $type) - ->addError($message); - - $args[$p->name] = new Reference($erroredId, ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE); - } else { - $target = ltrim($target, '\\'); - $args[$p->name] = $type ? new TypedReference($target, $type, $invalidBehavior, Target::parseName($p)) : new Reference($target, $invalidBehavior); - } - } - // register the maps as a per-method service-locators - if ($args) { - $controllers[$id.'::'.$r->name] = ServiceLocatorTagPass::register($container, $args); - - foreach ($publicAliases[$id] ?? [] as $alias) { - $controllers[$alias.'::'.$r->name] = clone $controllers[$id.'::'.$r->name]; - } - } - } - } - - $controllerLocatorRef = ServiceLocatorTagPass::register($container, $controllers); - - if ($container->hasDefinition($this->resolverServiceId)) { - $container->getDefinition($this->resolverServiceId) - ->replaceArgument(0, $controllerLocatorRef); - } - - if ($container->hasDefinition($this->notTaggedControllerResolverServiceId)) { - $container->getDefinition($this->notTaggedControllerResolverServiceId) - ->replaceArgument(0, $controllerLocatorRef); - } - - $container->setAlias($this->controllerLocator, (string) $controllerLocatorRef); - } -} diff --git a/lib/symfony/http-kernel/DependencyInjection/RegisterLocaleAwareServicesPass.php b/lib/symfony/http-kernel/DependencyInjection/RegisterLocaleAwareServicesPass.php deleted file mode 100644 index f0b801b8d..000000000 --- a/lib/symfony/http-kernel/DependencyInjection/RegisterLocaleAwareServicesPass.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Register all services that have the "kernel.locale_aware" tag into the listener. - * - * @author Pierre Bobiet <pierrebobiet@gmail.com> - */ -class RegisterLocaleAwareServicesPass implements CompilerPassInterface -{ - private $listenerServiceId; - private $localeAwareTag; - - public function __construct(string $listenerServiceId = 'locale_aware_listener', string $localeAwareTag = 'kernel.locale_aware') - { - if (0 < \func_num_args()) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->listenerServiceId = $listenerServiceId; - $this->localeAwareTag = $localeAwareTag; - } - - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition($this->listenerServiceId)) { - return; - } - - $services = []; - - foreach ($container->findTaggedServiceIds($this->localeAwareTag) as $id => $tags) { - $services[] = new Reference($id); - } - - if (!$services) { - $container->removeDefinition($this->listenerServiceId); - - return; - } - - $container - ->getDefinition($this->listenerServiceId) - ->setArgument(0, new IteratorArgument($services)) - ; - } -} diff --git a/lib/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php b/lib/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php deleted file mode 100644 index 2d077a0cb..000000000 --- a/lib/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php +++ /dev/null @@ -1,79 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * Removes empty service-locators registered for ServiceValueResolver. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class RemoveEmptyControllerArgumentLocatorsPass implements CompilerPassInterface -{ - private $controllerLocator; - - public function __construct(string $controllerLocator = 'argument_resolver.controller_locator') - { - if (0 < \func_num_args()) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->controllerLocator = $controllerLocator; - } - - public function process(ContainerBuilder $container) - { - $controllerLocator = $container->findDefinition($this->controllerLocator); - $controllers = $controllerLocator->getArgument(0); - - foreach ($controllers as $controller => $argumentRef) { - $argumentLocator = $container->getDefinition((string) $argumentRef->getValues()[0]); - - if (!$argumentLocator->getArgument(0)) { - // remove empty argument locators - $reason = sprintf('Removing service-argument resolver for controller "%s": no corresponding services exist for the referenced types.', $controller); - } else { - // any methods listed for call-at-instantiation cannot be actions - $reason = false; - [$id, $action] = explode('::', $controller); - - if ($container->hasAlias($id)) { - continue; - } - - $controllerDef = $container->getDefinition($id); - foreach ($controllerDef->getMethodCalls() as [$method]) { - if (0 === strcasecmp($action, $method)) { - $reason = sprintf('Removing method "%s" of service "%s" from controller candidates: the method is called at instantiation, thus cannot be an action.', $action, $id); - break; - } - } - if (!$reason) { - // see Symfony\Component\HttpKernel\Controller\ContainerControllerResolver - $controllers[$id.':'.$action] = $argumentRef; - - if ('__invoke' === $action) { - $controllers[$id] = $argumentRef; - } - continue; - } - } - - unset($controllers[$controller]); - $container->log($this, $reason); - } - - $controllerLocator->replaceArgument(0, $controllers); - } -} diff --git a/lib/symfony/http-kernel/DependencyInjection/ResettableServicePass.php b/lib/symfony/http-kernel/DependencyInjection/ResettableServicePass.php deleted file mode 100644 index 2e4cd6927..000000000 --- a/lib/symfony/http-kernel/DependencyInjection/ResettableServicePass.php +++ /dev/null @@ -1,79 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * @author Alexander M. Turek <me@derrabus.de> - */ -class ResettableServicePass implements CompilerPassInterface -{ - private $tagName; - - public function __construct(string $tagName = 'kernel.reset') - { - if (0 < \func_num_args()) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->tagName = $tagName; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - if (!$container->has('services_resetter')) { - return; - } - - $services = $methods = []; - - foreach ($container->findTaggedServiceIds($this->tagName, true) as $id => $tags) { - $services[$id] = new Reference($id, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE); - - foreach ($tags as $attributes) { - if (!isset($attributes['method'])) { - throw new RuntimeException(sprintf('Tag "%s" requires the "method" attribute to be set.', $this->tagName)); - } - - if (!isset($methods[$id])) { - $methods[$id] = []; - } - - if ('ignore' === ($attributes['on_invalid'] ?? null)) { - $attributes['method'] = '?'.$attributes['method']; - } - - $methods[$id][] = $attributes['method']; - } - } - - if (!$services) { - $container->removeAlias('services_resetter'); - $container->removeDefinition('services_resetter'); - - return; - } - - $container->findDefinition('services_resetter') - ->setArgument(0, new IteratorArgument($services)) - ->setArgument(1, $methods); - } -} diff --git a/lib/symfony/http-kernel/DependencyInjection/ServicesResetter.php b/lib/symfony/http-kernel/DependencyInjection/ServicesResetter.php deleted file mode 100644 index 0063deca3..000000000 --- a/lib/symfony/http-kernel/DependencyInjection/ServicesResetter.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Symfony\Contracts\Service\ResetInterface; - -/** - * Resets provided services. - * - * @author Alexander M. Turek <me@derrabus.de> - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -class ServicesResetter implements ResetInterface -{ - private $resettableServices; - private $resetMethods; - - /** - * @param \Traversable<string, object> $resettableServices - * @param array<string, string|string[]> $resetMethods - */ - public function __construct(\Traversable $resettableServices, array $resetMethods) - { - $this->resettableServices = $resettableServices; - $this->resetMethods = $resetMethods; - } - - public function reset() - { - foreach ($this->resettableServices as $id => $service) { - foreach ((array) $this->resetMethods[$id] as $resetMethod) { - if ('?' === $resetMethod[0] && !method_exists($service, $resetMethod = substr($resetMethod, 1))) { - continue; - } - - $service->$resetMethod(); - } - } - } -} diff --git a/lib/symfony/http-kernel/Event/ControllerArgumentsEvent.php b/lib/symfony/http-kernel/Event/ControllerArgumentsEvent.php deleted file mode 100644 index d075ee90b..000000000 --- a/lib/symfony/http-kernel/Event/ControllerArgumentsEvent.php +++ /dev/null @@ -1,61 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Event; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\HttpKernelInterface; - -/** - * Allows filtering of controller arguments. - * - * You can call getController() to retrieve the controller and getArguments - * to retrieve the current arguments. With setArguments() you can replace - * arguments that are used to call the controller. - * - * Arguments set in the event must be compatible with the signature of the - * controller. - * - * @author Christophe Coevoet <stof@notk.org> - */ -final class ControllerArgumentsEvent extends KernelEvent -{ - private $controller; - private $arguments; - - public function __construct(HttpKernelInterface $kernel, callable $controller, array $arguments, Request $request, ?int $requestType) - { - parent::__construct($kernel, $request, $requestType); - - $this->controller = $controller; - $this->arguments = $arguments; - } - - public function getController(): callable - { - return $this->controller; - } - - public function setController(callable $controller) - { - $this->controller = $controller; - } - - public function getArguments(): array - { - return $this->arguments; - } - - public function setArguments(array $arguments) - { - $this->arguments = $arguments; - } -} diff --git a/lib/symfony/http-kernel/Event/ControllerEvent.php b/lib/symfony/http-kernel/Event/ControllerEvent.php deleted file mode 100644 index da88800e2..000000000 --- a/lib/symfony/http-kernel/Event/ControllerEvent.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Event; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\HttpKernelInterface; - -/** - * Allows filtering of a controller callable. - * - * You can call getController() to retrieve the current controller. With - * setController() you can set a new controller that is used in the processing - * of the request. - * - * Controllers should be callables. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -final class ControllerEvent extends KernelEvent -{ - private $controller; - - public function __construct(HttpKernelInterface $kernel, callable $controller, Request $request, ?int $requestType) - { - parent::__construct($kernel, $request, $requestType); - - $this->setController($controller); - } - - public function getController(): callable - { - return $this->controller; - } - - public function setController(callable $controller): void - { - $this->controller = $controller; - } -} diff --git a/lib/symfony/http-kernel/Event/ExceptionEvent.php b/lib/symfony/http-kernel/Event/ExceptionEvent.php deleted file mode 100644 index a18fbd31f..000000000 --- a/lib/symfony/http-kernel/Event/ExceptionEvent.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Event; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\HttpKernelInterface; - -/** - * Allows to create a response for a thrown exception. - * - * Call setResponse() to set the response that will be returned for the - * current request. The propagation of this event is stopped as soon as a - * response is set. - * - * You can also call setThrowable() to replace the thrown exception. This - * exception will be thrown if no response is set during processing of this - * event. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -final class ExceptionEvent extends RequestEvent -{ - private $throwable; - - /** - * @var bool - */ - private $allowCustomResponseCode = false; - - public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, \Throwable $e) - { - parent::__construct($kernel, $request, $requestType); - - $this->setThrowable($e); - } - - public function getThrowable(): \Throwable - { - return $this->throwable; - } - - /** - * Replaces the thrown exception. - * - * This exception will be thrown if no response is set in the event. - */ - public function setThrowable(\Throwable $exception): void - { - $this->throwable = $exception; - } - - /** - * Mark the event as allowing a custom response code. - */ - public function allowCustomResponseCode(): void - { - $this->allowCustomResponseCode = true; - } - - /** - * Returns true if the event allows a custom response code. - */ - public function isAllowingCustomResponseCode(): bool - { - return $this->allowCustomResponseCode; - } -} diff --git a/lib/symfony/http-kernel/Event/FinishRequestEvent.php b/lib/symfony/http-kernel/Event/FinishRequestEvent.php deleted file mode 100644 index 306a7ad1c..000000000 --- a/lib/symfony/http-kernel/Event/FinishRequestEvent.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Event; - -/** - * Triggered whenever a request is fully processed. - * - * @author Benjamin Eberlei <kontakt@beberlei.de> - */ -final class FinishRequestEvent extends KernelEvent -{ -} diff --git a/lib/symfony/http-kernel/Event/KernelEvent.php b/lib/symfony/http-kernel/Event/KernelEvent.php deleted file mode 100644 index d9d425e11..000000000 --- a/lib/symfony/http-kernel/Event/KernelEvent.php +++ /dev/null @@ -1,92 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Event; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Contracts\EventDispatcher\Event; - -/** - * Base class for events thrown in the HttpKernel component. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class KernelEvent extends Event -{ - private $kernel; - private $request; - private $requestType; - - /** - * @param int $requestType The request type the kernel is currently processing; one of - * HttpKernelInterface::MAIN_REQUEST or HttpKernelInterface::SUB_REQUEST - */ - public function __construct(HttpKernelInterface $kernel, Request $request, ?int $requestType) - { - $this->kernel = $kernel; - $this->request = $request; - $this->requestType = $requestType; - } - - /** - * Returns the kernel in which this event was thrown. - * - * @return HttpKernelInterface - */ - public function getKernel() - { - return $this->kernel; - } - - /** - * Returns the request the kernel is currently processing. - * - * @return Request - */ - public function getRequest() - { - return $this->request; - } - - /** - * Returns the request type the kernel is currently processing. - * - * @return int One of HttpKernelInterface::MAIN_REQUEST and - * HttpKernelInterface::SUB_REQUEST - */ - public function getRequestType() - { - return $this->requestType; - } - - /** - * Checks if this is the main request. - */ - public function isMainRequest(): bool - { - return HttpKernelInterface::MAIN_REQUEST === $this->requestType; - } - - /** - * Checks if this is a master request. - * - * @return bool - * - * @deprecated since symfony/http-kernel 5.3, use isMainRequest() instead - */ - public function isMasterRequest() - { - trigger_deprecation('symfony/http-kernel', '5.3', '"%s()" is deprecated, use "isMainRequest()" instead.', __METHOD__); - - return $this->isMainRequest(); - } -} diff --git a/lib/symfony/http-kernel/Event/RequestEvent.php b/lib/symfony/http-kernel/Event/RequestEvent.php deleted file mode 100644 index 30ffcdcbd..000000000 --- a/lib/symfony/http-kernel/Event/RequestEvent.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Event; - -use Symfony\Component\HttpFoundation\Response; - -/** - * Allows to create a response for a request. - * - * Call setResponse() to set the response that will be returned for the - * current request. The propagation of this event is stopped as soon as a - * response is set. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class RequestEvent extends KernelEvent -{ - private $response; - - /** - * Returns the response object. - * - * @return Response|null - */ - public function getResponse() - { - return $this->response; - } - - /** - * Sets a response and stops event propagation. - */ - public function setResponse(Response $response) - { - $this->response = $response; - - $this->stopPropagation(); - } - - /** - * Returns whether a response was set. - * - * @return bool - */ - public function hasResponse() - { - return null !== $this->response; - } -} diff --git a/lib/symfony/http-kernel/Event/ResponseEvent.php b/lib/symfony/http-kernel/Event/ResponseEvent.php deleted file mode 100644 index 1e56ebea2..000000000 --- a/lib/symfony/http-kernel/Event/ResponseEvent.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Event; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\HttpKernelInterface; - -/** - * Allows to filter a Response object. - * - * You can call getResponse() to retrieve the current response. With - * setResponse() you can set a new response that will be returned to the - * browser. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -final class ResponseEvent extends KernelEvent -{ - private $response; - - public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, Response $response) - { - parent::__construct($kernel, $request, $requestType); - - $this->setResponse($response); - } - - public function getResponse(): Response - { - return $this->response; - } - - public function setResponse(Response $response): void - { - $this->response = $response; - } -} diff --git a/lib/symfony/http-kernel/Event/TerminateEvent.php b/lib/symfony/http-kernel/Event/TerminateEvent.php deleted file mode 100644 index 014ca535f..000000000 --- a/lib/symfony/http-kernel/Event/TerminateEvent.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Event; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\HttpKernelInterface; - -/** - * Allows to execute logic after a response was sent. - * - * Since it's only triggered on main requests, the `getRequestType()` method - * will always return the value of `HttpKernelInterface::MAIN_REQUEST`. - * - * @author Jordi Boggiano <j.boggiano@seld.be> - */ -final class TerminateEvent extends KernelEvent -{ - private $response; - - public function __construct(HttpKernelInterface $kernel, Request $request, Response $response) - { - parent::__construct($kernel, $request, HttpKernelInterface::MAIN_REQUEST); - - $this->response = $response; - } - - public function getResponse(): Response - { - return $this->response; - } -} diff --git a/lib/symfony/http-kernel/Event/ViewEvent.php b/lib/symfony/http-kernel/Event/ViewEvent.php deleted file mode 100644 index 88211da41..000000000 --- a/lib/symfony/http-kernel/Event/ViewEvent.php +++ /dev/null @@ -1,61 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Event; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\HttpKernelInterface; - -/** - * Allows to create a response for the return value of a controller. - * - * Call setResponse() to set the response that will be returned for the - * current request. The propagation of this event is stopped as soon as a - * response is set. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -final class ViewEvent extends RequestEvent -{ - /** - * The return value of the controller. - * - * @var mixed - */ - private $controllerResult; - - public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, $controllerResult) - { - parent::__construct($kernel, $request, $requestType); - - $this->controllerResult = $controllerResult; - } - - /** - * Returns the return value of the controller. - * - * @return mixed - */ - public function getControllerResult() - { - return $this->controllerResult; - } - - /** - * Assigns the return value of the controller. - * - * @param mixed $controllerResult The controller return value - */ - public function setControllerResult($controllerResult): void - { - $this->controllerResult = $controllerResult; - } -} diff --git a/lib/symfony/http-kernel/EventListener/AbstractSessionListener.php b/lib/symfony/http-kernel/EventListener/AbstractSessionListener.php deleted file mode 100644 index 27749b24b..000000000 --- a/lib/symfony/http-kernel/EventListener/AbstractSessionListener.php +++ /dev/null @@ -1,315 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Psr\Container\ContainerInterface; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\Cookie; -use Symfony\Component\HttpFoundation\Session\Session; -use Symfony\Component\HttpFoundation\Session\SessionInterface; -use Symfony\Component\HttpFoundation\Session\SessionUtils; -use Symfony\Component\HttpKernel\Event\FinishRequestEvent; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Symfony\Component\HttpKernel\Exception\UnexpectedSessionUsageException; -use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Contracts\Service\ResetInterface; - -/** - * Sets the session onto the request on the "kernel.request" event and saves - * it on the "kernel.response" event. - * - * In addition, if the session has been started it overrides the Cache-Control - * header in such a way that all caching is disabled in that case. - * If you have a scenario where caching responses with session information in - * them makes sense, you can disable this behaviour by setting the header - * AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER on the response. - * - * @author Johannes M. Schmitt <schmittjoh@gmail.com> - * @author Tobias Schultze <http://tobion.de> - * - * @internal - */ -abstract class AbstractSessionListener implements EventSubscriberInterface, ResetInterface -{ - public const NO_AUTO_CACHE_CONTROL_HEADER = 'Symfony-Session-NoAutoCacheControl'; - - protected $container; - private $sessionUsageStack = []; - private $debug; - - /** - * @var array<string, mixed> - */ - private $sessionOptions; - - public function __construct(ContainerInterface $container = null, bool $debug = false, array $sessionOptions = []) - { - $this->container = $container; - $this->debug = $debug; - $this->sessionOptions = $sessionOptions; - } - - public function onKernelRequest(RequestEvent $event) - { - if (!$event->isMainRequest()) { - return; - } - - $request = $event->getRequest(); - if (!$request->hasSession()) { - // This variable prevents calling `$this->getSession()` twice in case the Request (and the below factory) is cloned - $sess = null; - $request->setSessionFactory(function () use (&$sess, $request) { - if (!$sess) { - $sess = $this->getSession(); - - /* - * For supporting sessions in php runtime with runners like roadrunner or swoole, the session - * cookie needs to be read from the cookie bag and set on the session storage. - * - * Do not set it when a native php session is active. - */ - if ($sess && !$sess->isStarted() && \PHP_SESSION_ACTIVE !== session_status()) { - $sessionId = $sess->getId() ?: $request->cookies->get($sess->getName(), ''); - $sess->setId($sessionId); - } - } - - return $sess; - }); - } - - $session = $this->container && $this->container->has('initialized_session') ? $this->container->get('initialized_session') : null; - $this->sessionUsageStack[] = $session instanceof Session ? $session->getUsageIndex() : 0; - } - - public function onKernelResponse(ResponseEvent $event) - { - if (!$event->isMainRequest() || (!$this->container->has('initialized_session') && !$event->getRequest()->hasSession())) { - return; - } - - $response = $event->getResponse(); - $autoCacheControl = !$response->headers->has(self::NO_AUTO_CACHE_CONTROL_HEADER); - // Always remove the internal header if present - $response->headers->remove(self::NO_AUTO_CACHE_CONTROL_HEADER); - - if (!$session = $this->container && $this->container->has('initialized_session') ? $this->container->get('initialized_session') : ($event->getRequest()->hasSession() ? $event->getRequest()->getSession() : null)) { - return; - } - - if ($session->isStarted()) { - /* - * Saves the session, in case it is still open, before sending the response/headers. - * - * This ensures several things in case the developer did not save the session explicitly: - * - * * If a session save handler without locking is used, it ensures the data is available - * on the next request, e.g. after a redirect. PHPs auto-save at script end via - * session_register_shutdown is executed after fastcgi_finish_request. So in this case - * the data could be missing the next request because it might not be saved the moment - * the new request is processed. - * * A locking save handler (e.g. the native 'files') circumvents concurrency problems like - * the one above. But by saving the session before long-running things in the terminate event, - * we ensure the session is not blocked longer than needed. - * * When regenerating the session ID no locking is involved in PHPs session design. See - * https://bugs.php.net/61470 for a discussion. So in this case, the session must - * be saved anyway before sending the headers with the new session ID. Otherwise session - * data could get lost again for concurrent requests with the new ID. One result could be - * that you get logged out after just logging in. - * - * This listener should be executed as one of the last listeners, so that previous listeners - * can still operate on the open session. This prevents the overhead of restarting it. - * Listeners after closing the session can still work with the session as usual because - * Symfonys session implementation starts the session on demand. So writing to it after - * it is saved will just restart it. - */ - $session->save(); - - /* - * For supporting sessions in php runtime with runners like roadrunner or swoole the session - * cookie need to be written on the response object and should not be written by PHP itself. - */ - $sessionName = $session->getName(); - $sessionId = $session->getId(); - $sessionOptions = $this->getSessionOptions($this->sessionOptions); - $sessionCookiePath = $sessionOptions['cookie_path'] ?? '/'; - $sessionCookieDomain = $sessionOptions['cookie_domain'] ?? null; - $sessionCookieSecure = $sessionOptions['cookie_secure'] ?? false; - $sessionCookieHttpOnly = $sessionOptions['cookie_httponly'] ?? true; - $sessionCookieSameSite = $sessionOptions['cookie_samesite'] ?? Cookie::SAMESITE_LAX; - $sessionUseCookies = $sessionOptions['use_cookies'] ?? true; - - SessionUtils::popSessionCookie($sessionName, $sessionId); - - if ($sessionUseCookies) { - $request = $event->getRequest(); - $requestSessionCookieId = $request->cookies->get($sessionName); - - $isSessionEmpty = $session->isEmpty() && empty($_SESSION); // checking $_SESSION to keep compatibility with native sessions - if ($requestSessionCookieId && $isSessionEmpty) { - // PHP internally sets the session cookie value to "deleted" when setcookie() is called with empty string $value argument - // which happens in \Symfony\Component\HttpFoundation\Session\Storage\Handler\AbstractSessionHandler::destroy - // when the session gets invalidated (for example on logout) so we must handle this case here too - // otherwise we would send two Set-Cookie headers back with the response - SessionUtils::popSessionCookie($sessionName, 'deleted'); - $response->headers->clearCookie( - $sessionName, - $sessionCookiePath, - $sessionCookieDomain, - $sessionCookieSecure, - $sessionCookieHttpOnly, - $sessionCookieSameSite - ); - } elseif ($sessionId !== $requestSessionCookieId && !$isSessionEmpty) { - $expire = 0; - $lifetime = $sessionOptions['cookie_lifetime'] ?? null; - if ($lifetime) { - $expire = time() + $lifetime; - } - - $response->headers->setCookie( - Cookie::create( - $sessionName, - $sessionId, - $expire, - $sessionCookiePath, - $sessionCookieDomain, - $sessionCookieSecure, - $sessionCookieHttpOnly, - false, - $sessionCookieSameSite - ) - ); - } - } - } - - if ($session instanceof Session ? $session->getUsageIndex() === end($this->sessionUsageStack) : !$session->isStarted()) { - return; - } - - if ($autoCacheControl) { - $maxAge = $response->headers->hasCacheControlDirective('public') ? 0 : (int) $response->getMaxAge(); - $response - ->setExpires(new \DateTimeImmutable('+'.$maxAge.' seconds')) - ->setPrivate() - ->setMaxAge($maxAge) - ->headers->addCacheControlDirective('must-revalidate'); - } - - if (!$event->getRequest()->attributes->get('_stateless', false)) { - return; - } - - if ($this->debug) { - throw new UnexpectedSessionUsageException('Session was used while the request was declared stateless.'); - } - - if ($this->container->has('logger')) { - $this->container->get('logger')->warning('Session was used while the request was declared stateless.'); - } - } - - public function onFinishRequest(FinishRequestEvent $event) - { - if ($event->isMainRequest()) { - array_pop($this->sessionUsageStack); - } - } - - public function onSessionUsage(): void - { - if (!$this->debug) { - return; - } - - if ($this->container && $this->container->has('session_collector')) { - $this->container->get('session_collector')(); - } - - if (!$requestStack = $this->container && $this->container->has('request_stack') ? $this->container->get('request_stack') : null) { - return; - } - - $stateless = false; - $clonedRequestStack = clone $requestStack; - while (null !== ($request = $clonedRequestStack->pop()) && !$stateless) { - $stateless = $request->attributes->get('_stateless'); - } - - if (!$stateless) { - return; - } - - if (!$session = $this->container && $this->container->has('initialized_session') ? $this->container->get('initialized_session') : $requestStack->getCurrentRequest()->getSession()) { - return; - } - - if ($session->isStarted()) { - $session->save(); - } - - throw new UnexpectedSessionUsageException('Session was used while the request was declared stateless.'); - } - - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::REQUEST => ['onKernelRequest', 128], - // low priority to come after regular response listeners, but higher than StreamedResponseListener - KernelEvents::RESPONSE => ['onKernelResponse', -1000], - KernelEvents::FINISH_REQUEST => ['onFinishRequest'], - ]; - } - - public function reset(): void - { - if (\PHP_SESSION_ACTIVE === session_status()) { - session_abort(); - } - - session_unset(); - $_SESSION = []; - - if (!headers_sent()) { // session id can only be reset when no headers were so we check for headers_sent first - session_id(''); - } - } - - /** - * Gets the session object. - * - * @return SessionInterface|null - */ - abstract protected function getSession(); - - private function getSessionOptions(array $sessionOptions): array - { - $mergedSessionOptions = []; - - foreach (session_get_cookie_params() as $key => $value) { - $mergedSessionOptions['cookie_'.$key] = $value; - } - - foreach ($sessionOptions as $key => $value) { - // do the same logic as in the NativeSessionStorage - if ('cookie_secure' === $key && 'auto' === $value) { - continue; - } - $mergedSessionOptions[$key] = $value; - } - - return $mergedSessionOptions; - } -} diff --git a/lib/symfony/http-kernel/EventListener/AbstractTestSessionListener.php b/lib/symfony/http-kernel/EventListener/AbstractTestSessionListener.php deleted file mode 100644 index 838c2944b..000000000 --- a/lib/symfony/http-kernel/EventListener/AbstractTestSessionListener.php +++ /dev/null @@ -1,120 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\Cookie; -use Symfony\Component\HttpFoundation\Session\Session; -use Symfony\Component\HttpFoundation\Session\SessionInterface; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Symfony\Component\HttpKernel\KernelEvents; - -trigger_deprecation('symfony/http-kernel', '5.4', '"%s" is deprecated use "%s" instead.', AbstractTestSessionListener::class, AbstractSessionListener::class); - -/** - * TestSessionListener. - * - * Saves session in test environment. - * - * @author Bulat Shakirzyanov <mallluhuct@gmail.com> - * @author Fabien Potencier <fabien@symfony.com> - * - * @internal - * - * @deprecated since Symfony 5.4, use AbstractSessionListener instead - */ -abstract class AbstractTestSessionListener implements EventSubscriberInterface -{ - private $sessionId; - private $sessionOptions; - - public function __construct(array $sessionOptions = []) - { - $this->sessionOptions = $sessionOptions; - } - - public function onKernelRequest(RequestEvent $event) - { - if (!$event->isMainRequest()) { - return; - } - - // bootstrap the session - if ($event->getRequest()->hasSession()) { - $session = $event->getRequest()->getSession(); - } elseif (!$session = $this->getSession()) { - return; - } - - $cookies = $event->getRequest()->cookies; - - if ($cookies->has($session->getName())) { - $this->sessionId = $cookies->get($session->getName()); - $session->setId($this->sessionId); - } - } - - /** - * Checks if session was initialized and saves if current request is the main request - * Runs on 'kernel.response' in test environment. - */ - public function onKernelResponse(ResponseEvent $event) - { - if (!$event->isMainRequest()) { - return; - } - - $request = $event->getRequest(); - if (!$request->hasSession()) { - return; - } - - $session = $request->getSession(); - if ($wasStarted = $session->isStarted()) { - $session->save(); - } - - if ($session instanceof Session ? !$session->isEmpty() || (null !== $this->sessionId && $session->getId() !== $this->sessionId) : $wasStarted) { - $params = session_get_cookie_params() + ['samesite' => null]; - foreach ($this->sessionOptions as $k => $v) { - if (str_starts_with($k, 'cookie_')) { - $params[substr($k, 7)] = $v; - } - } - - foreach ($event->getResponse()->headers->getCookies() as $cookie) { - if ($session->getName() === $cookie->getName() && $params['path'] === $cookie->getPath() && $params['domain'] == $cookie->getDomain()) { - return; - } - } - - $event->getResponse()->headers->setCookie(new Cookie($session->getName(), $session->getId(), 0 === $params['lifetime'] ? 0 : time() + $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly'], false, $params['samesite'] ?: null)); - $this->sessionId = $session->getId(); - } - } - - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::REQUEST => ['onKernelRequest', 127], // AFTER SessionListener - KernelEvents::RESPONSE => ['onKernelResponse', -128], - ]; - } - - /** - * Gets the session object. - * - * @return SessionInterface|null - */ - abstract protected function getSession(); -} diff --git a/lib/symfony/http-kernel/EventListener/AddRequestFormatsListener.php b/lib/symfony/http-kernel/EventListener/AddRequestFormatsListener.php deleted file mode 100644 index 9e896adb3..000000000 --- a/lib/symfony/http-kernel/EventListener/AddRequestFormatsListener.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\KernelEvents; - -/** - * Adds configured formats to each request. - * - * @author Gildas Quemener <gildas.quemener@gmail.com> - * - * @final - */ -class AddRequestFormatsListener implements EventSubscriberInterface -{ - protected $formats; - - public function __construct(array $formats) - { - $this->formats = $formats; - } - - /** - * Adds request formats. - */ - public function onKernelRequest(RequestEvent $event) - { - $request = $event->getRequest(); - foreach ($this->formats as $format => $mimeTypes) { - $request->setFormat($format, $mimeTypes); - } - } - - /** - * {@inheritdoc} - */ - public static function getSubscribedEvents(): array - { - return [KernelEvents::REQUEST => ['onKernelRequest', 100]]; - } -} diff --git a/lib/symfony/http-kernel/EventListener/DebugHandlersListener.php b/lib/symfony/http-kernel/EventListener/DebugHandlersListener.php deleted file mode 100644 index bd124f94d..000000000 --- a/lib/symfony/http-kernel/EventListener/DebugHandlersListener.php +++ /dev/null @@ -1,190 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Psr\Log\LoggerInterface; -use Symfony\Component\Console\ConsoleEvents; -use Symfony\Component\Console\Event\ConsoleEvent; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\ErrorHandler\ErrorHandler; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpKernel\Event\KernelEvent; -use Symfony\Component\HttpKernel\KernelEvents; - -/** - * Configures errors and exceptions handlers. - * - * @author Nicolas Grekas <p@tchwork.com> - * - * @final - * - * @internal since Symfony 5.3 - */ -class DebugHandlersListener implements EventSubscriberInterface -{ - private $earlyHandler; - private $exceptionHandler; - private $logger; - private $deprecationLogger; - private $levels; - private $throwAt; - private $scream; - private $scope; - private $firstCall = true; - private $hasTerminatedWithException; - - /** - * @param callable|null $exceptionHandler A handler that must support \Throwable instances that will be called on Exception - * @param array|int|null $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants - * @param int|null $throwAt Thrown errors in a bit field of E_* constants, or null to keep the current value - * @param bool $scream Enables/disables screaming mode, where even silenced errors are logged - * @param bool $scope Enables/disables scoping mode - */ - public function __construct(callable $exceptionHandler = null, LoggerInterface $logger = null, $levels = \E_ALL, ?int $throwAt = \E_ALL, bool $scream = true, $scope = true, $deprecationLogger = null, $fileLinkFormat = null) - { - if (!\is_bool($scope)) { - trigger_deprecation('symfony/http-kernel', '5.4', 'Passing a $fileLinkFormat is deprecated.'); - $scope = $deprecationLogger; - $deprecationLogger = $fileLinkFormat; - } - - $handler = set_exception_handler('is_int'); - $this->earlyHandler = \is_array($handler) ? $handler[0] : null; - restore_exception_handler(); - - $this->exceptionHandler = $exceptionHandler; - $this->logger = $logger; - $this->levels = $levels ?? \E_ALL; - $this->throwAt = \is_int($throwAt) ? $throwAt : (null === $throwAt ? null : ($throwAt ? \E_ALL : null)); - $this->scream = $scream; - $this->scope = $scope; - $this->deprecationLogger = $deprecationLogger; - } - - /** - * Configures the error handler. - */ - public function configure(object $event = null) - { - if ($event instanceof ConsoleEvent && !\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { - return; - } - if (!$event instanceof KernelEvent ? !$this->firstCall : !$event->isMainRequest()) { - return; - } - $this->firstCall = $this->hasTerminatedWithException = false; - - $handler = set_exception_handler('is_int'); - $handler = \is_array($handler) ? $handler[0] : null; - restore_exception_handler(); - - if (!$handler instanceof ErrorHandler) { - $handler = $this->earlyHandler; - } - - if ($handler instanceof ErrorHandler) { - if ($this->logger || $this->deprecationLogger) { - $this->setDefaultLoggers($handler); - if (\is_array($this->levels)) { - $levels = 0; - foreach ($this->levels as $type => $log) { - $levels |= $type; - } - } else { - $levels = $this->levels; - } - - if ($this->scream) { - $handler->screamAt($levels); - } - if ($this->scope) { - $handler->scopeAt($levels & ~\E_USER_DEPRECATED & ~\E_DEPRECATED); - } else { - $handler->scopeAt(0, true); - } - $this->logger = $this->deprecationLogger = $this->levels = null; - } - if (null !== $this->throwAt) { - $handler->throwAt($this->throwAt, true); - } - } - if (!$this->exceptionHandler) { - if ($event instanceof KernelEvent) { - if (method_exists($kernel = $event->getKernel(), 'terminateWithException')) { - $request = $event->getRequest(); - $hasRun = &$this->hasTerminatedWithException; - $this->exceptionHandler = static function (\Throwable $e) use ($kernel, $request, &$hasRun) { - if ($hasRun) { - throw $e; - } - - $hasRun = true; - $kernel->terminateWithException($e, $request); - }; - } - } elseif ($event instanceof ConsoleEvent && $app = $event->getCommand()->getApplication()) { - $output = $event->getOutput(); - if ($output instanceof ConsoleOutputInterface) { - $output = $output->getErrorOutput(); - } - $this->exceptionHandler = static function (\Throwable $e) use ($app, $output) { - $app->renderThrowable($e, $output); - }; - } - } - if ($this->exceptionHandler) { - if ($handler instanceof ErrorHandler) { - $handler->setExceptionHandler($this->exceptionHandler); - } - $this->exceptionHandler = null; - } - } - - private function setDefaultLoggers(ErrorHandler $handler): void - { - if (\is_array($this->levels)) { - $levelsDeprecatedOnly = []; - $levelsWithoutDeprecated = []; - foreach ($this->levels as $type => $log) { - if (\E_DEPRECATED == $type || \E_USER_DEPRECATED == $type) { - $levelsDeprecatedOnly[$type] = $log; - } else { - $levelsWithoutDeprecated[$type] = $log; - } - } - } else { - $levelsDeprecatedOnly = $this->levels & (\E_DEPRECATED | \E_USER_DEPRECATED); - $levelsWithoutDeprecated = $this->levels & ~\E_DEPRECATED & ~\E_USER_DEPRECATED; - } - - $defaultLoggerLevels = $this->levels; - if ($this->deprecationLogger && $levelsDeprecatedOnly) { - $handler->setDefaultLogger($this->deprecationLogger, $levelsDeprecatedOnly); - $defaultLoggerLevels = $levelsWithoutDeprecated; - } - - if ($this->logger && $defaultLoggerLevels) { - $handler->setDefaultLogger($this->logger, $defaultLoggerLevels); - } - } - - public static function getSubscribedEvents(): array - { - $events = [KernelEvents::REQUEST => ['configure', 2048]]; - - if (\defined('Symfony\Component\Console\ConsoleEvents::COMMAND')) { - $events[ConsoleEvents::COMMAND] = ['configure', 2048]; - } - - return $events; - } -} diff --git a/lib/symfony/http-kernel/EventListener/DisallowRobotsIndexingListener.php b/lib/symfony/http-kernel/EventListener/DisallowRobotsIndexingListener.php deleted file mode 100644 index 6607e49e9..000000000 --- a/lib/symfony/http-kernel/EventListener/DisallowRobotsIndexingListener.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Symfony\Component\HttpKernel\KernelEvents; - -/** - * Ensures that the application is not indexed by search engines. - * - * @author Gary PEGEOT <garypegeot@gmail.com> - */ -class DisallowRobotsIndexingListener implements EventSubscriberInterface -{ - private const HEADER_NAME = 'X-Robots-Tag'; - - public function onResponse(ResponseEvent $event): void - { - if (!$event->getResponse()->headers->has(static::HEADER_NAME)) { - $event->getResponse()->headers->set(static::HEADER_NAME, 'noindex'); - } - } - - /** - * {@inheritdoc} - */ - public static function getSubscribedEvents() - { - return [ - KernelEvents::RESPONSE => ['onResponse', -255], - ]; - } -} diff --git a/lib/symfony/http-kernel/EventListener/DumpListener.php b/lib/symfony/http-kernel/EventListener/DumpListener.php deleted file mode 100644 index 30908a4f4..000000000 --- a/lib/symfony/http-kernel/EventListener/DumpListener.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\Console\ConsoleEvents; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\VarDumper\Cloner\ClonerInterface; -use Symfony\Component\VarDumper\Dumper\DataDumperInterface; -use Symfony\Component\VarDumper\Server\Connection; -use Symfony\Component\VarDumper\VarDumper; - -/** - * Configures dump() handler. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class DumpListener implements EventSubscriberInterface -{ - private $cloner; - private $dumper; - private $connection; - - public function __construct(ClonerInterface $cloner, DataDumperInterface $dumper, Connection $connection = null) - { - $this->cloner = $cloner; - $this->dumper = $dumper; - $this->connection = $connection; - } - - public function configure() - { - $cloner = $this->cloner; - $dumper = $this->dumper; - $connection = $this->connection; - - VarDumper::setHandler(static function ($var) use ($cloner, $dumper, $connection) { - $data = $cloner->cloneVar($var); - - if (!$connection || !$connection->write($data)) { - $dumper->dump($data); - } - }); - } - - public static function getSubscribedEvents() - { - if (!class_exists(ConsoleEvents::class)) { - return []; - } - - // Register early to have a working dump() as early as possible - return [ConsoleEvents::COMMAND => ['configure', 1024]]; - } -} diff --git a/lib/symfony/http-kernel/EventListener/ErrorListener.php b/lib/symfony/http-kernel/EventListener/ErrorListener.php deleted file mode 100644 index b6fd0a357..000000000 --- a/lib/symfony/http-kernel/EventListener/ErrorListener.php +++ /dev/null @@ -1,186 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Psr\Log\LoggerInterface; -use Symfony\Component\Debug\Exception\FlattenException as LegacyFlattenException; -use Symfony\Component\ErrorHandler\Exception\FlattenException; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent; -use Symfony\Component\HttpKernel\Event\ExceptionEvent; -use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Symfony\Component\HttpKernel\Exception\HttpException; -use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; -use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -class ErrorListener implements EventSubscriberInterface -{ - protected $controller; - protected $logger; - protected $debug; - /** - * @var array<class-string, array{log_level: string|null, status_code: int<100,599>|null}> - */ - protected $exceptionsMapping; - - /** - * @param array<class-string, array{log_level: string|null, status_code: int<100,599>|null}> $exceptionsMapping - */ - public function __construct($controller, LoggerInterface $logger = null, bool $debug = false, array $exceptionsMapping = []) - { - $this->controller = $controller; - $this->logger = $logger; - $this->debug = $debug; - $this->exceptionsMapping = $exceptionsMapping; - } - - public function logKernelException(ExceptionEvent $event) - { - $throwable = $event->getThrowable(); - $logLevel = null; - - foreach ($this->exceptionsMapping as $class => $config) { - if ($throwable instanceof $class && $config['log_level']) { - $logLevel = $config['log_level']; - break; - } - } - - foreach ($this->exceptionsMapping as $class => $config) { - if (!$throwable instanceof $class || !$config['status_code']) { - continue; - } - if (!$throwable instanceof HttpExceptionInterface || $throwable->getStatusCode() !== $config['status_code']) { - $headers = $throwable instanceof HttpExceptionInterface ? $throwable->getHeaders() : []; - $throwable = new HttpException($config['status_code'], $throwable->getMessage(), $throwable, $headers); - $event->setThrowable($throwable); - } - break; - } - - $e = FlattenException::createFromThrowable($throwable); - - $this->logException($throwable, sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', $e->getClass(), $e->getMessage(), $e->getFile(), $e->getLine()), $logLevel); - } - - public function onKernelException(ExceptionEvent $event) - { - if (null === $this->controller) { - return; - } - - $throwable = $event->getThrowable(); - $request = $this->duplicateRequest($throwable, $event->getRequest()); - - try { - $response = $event->getKernel()->handle($request, HttpKernelInterface::SUB_REQUEST, false); - } catch (\Exception $e) { - $f = FlattenException::createFromThrowable($e); - - $this->logException($e, sprintf('Exception thrown when handling an exception (%s: %s at %s line %s)', $f->getClass(), $f->getMessage(), $e->getFile(), $e->getLine())); - - $prev = $e; - do { - if ($throwable === $wrapper = $prev) { - throw $e; - } - } while ($prev = $wrapper->getPrevious()); - - $prev = new \ReflectionProperty($wrapper instanceof \Exception ? \Exception::class : \Error::class, 'previous'); - $prev->setAccessible(true); - $prev->setValue($wrapper, $throwable); - - throw $e; - } - - $event->setResponse($response); - - if ($this->debug) { - $event->getRequest()->attributes->set('_remove_csp_headers', true); - } - } - - public function removeCspHeader(ResponseEvent $event): void - { - if ($this->debug && $event->getRequest()->attributes->get('_remove_csp_headers', false)) { - $event->getResponse()->headers->remove('Content-Security-Policy'); - } - } - - public function onControllerArguments(ControllerArgumentsEvent $event) - { - $e = $event->getRequest()->attributes->get('exception'); - - if (!$e instanceof \Throwable || false === $k = array_search($e, $event->getArguments(), true)) { - return; - } - - $r = new \ReflectionFunction(\Closure::fromCallable($event->getController())); - $r = $r->getParameters()[$k] ?? null; - - if ($r && (!($r = $r->getType()) instanceof \ReflectionNamedType || \in_array($r->getName(), [FlattenException::class, LegacyFlattenException::class], true))) { - $arguments = $event->getArguments(); - $arguments[$k] = FlattenException::createFromThrowable($e); - $event->setArguments($arguments); - } - } - - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::CONTROLLER_ARGUMENTS => 'onControllerArguments', - KernelEvents::EXCEPTION => [ - ['logKernelException', 0], - ['onKernelException', -128], - ], - KernelEvents::RESPONSE => ['removeCspHeader', -128], - ]; - } - - /** - * Logs an exception. - */ - protected function logException(\Throwable $exception, string $message, string $logLevel = null): void - { - if (null !== $this->logger) { - if (null !== $logLevel) { - $this->logger->log($logLevel, $message, ['exception' => $exception]); - } elseif (!$exception instanceof HttpExceptionInterface || $exception->getStatusCode() >= 500) { - $this->logger->critical($message, ['exception' => $exception]); - } else { - $this->logger->error($message, ['exception' => $exception]); - } - } - } - - /** - * Clones the request for the exception. - */ - protected function duplicateRequest(\Throwable $exception, Request $request): Request - { - $attributes = [ - '_controller' => $this->controller, - 'exception' => $exception, - 'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null, - ]; - $request = $request->duplicate(null, null, $attributes); - $request->setMethod('GET'); - - return $request; - } -} diff --git a/lib/symfony/http-kernel/EventListener/FragmentListener.php b/lib/symfony/http-kernel/EventListener/FragmentListener.php deleted file mode 100644 index c01d9ad49..000000000 --- a/lib/symfony/http-kernel/EventListener/FragmentListener.php +++ /dev/null @@ -1,99 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; -use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\HttpKernel\UriSigner; - -/** - * Handles content fragments represented by special URIs. - * - * All URL paths starting with /_fragment are handled as - * content fragments by this listener. - * - * Throws an AccessDeniedHttpException exception if the request - * is not signed or if it is not an internal sub-request. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class FragmentListener implements EventSubscriberInterface -{ - private $signer; - private $fragmentPath; - - /** - * @param string $fragmentPath The path that triggers this listener - */ - public function __construct(UriSigner $signer, string $fragmentPath = '/_fragment') - { - $this->signer = $signer; - $this->fragmentPath = $fragmentPath; - } - - /** - * Fixes request attributes when the path is '/_fragment'. - * - * @throws AccessDeniedHttpException if the request does not come from a trusted IP - */ - public function onKernelRequest(RequestEvent $event) - { - $request = $event->getRequest(); - - if ($this->fragmentPath !== rawurldecode($request->getPathInfo())) { - return; - } - - if ($request->attributes->has('_controller')) { - // Is a sub-request: no need to parse _path but it should still be removed from query parameters as below. - $request->query->remove('_path'); - - return; - } - - if ($event->isMainRequest()) { - $this->validateRequest($request); - } - - parse_str($request->query->get('_path', ''), $attributes); - $request->attributes->add($attributes); - $request->attributes->set('_route_params', array_replace($request->attributes->get('_route_params', []), $attributes)); - $request->query->remove('_path'); - } - - protected function validateRequest(Request $request) - { - // is the Request safe? - if (!$request->isMethodSafe()) { - throw new AccessDeniedHttpException(); - } - - // is the Request signed? - if ($this->signer->checkRequest($request)) { - return; - } - - throw new AccessDeniedHttpException(); - } - - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::REQUEST => [['onKernelRequest', 48]], - ]; - } -} diff --git a/lib/symfony/http-kernel/EventListener/LocaleAwareListener.php b/lib/symfony/http-kernel/EventListener/LocaleAwareListener.php deleted file mode 100644 index a126f06ec..000000000 --- a/lib/symfony/http-kernel/EventListener/LocaleAwareListener.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpKernel\Event\FinishRequestEvent; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Contracts\Translation\LocaleAwareInterface; - -/** - * Pass the current locale to the provided services. - * - * @author Pierre Bobiet <pierrebobiet@gmail.com> - */ -class LocaleAwareListener implements EventSubscriberInterface -{ - private $localeAwareServices; - private $requestStack; - - /** - * @param iterable<mixed, LocaleAwareInterface> $localeAwareServices - */ - public function __construct(iterable $localeAwareServices, RequestStack $requestStack) - { - $this->localeAwareServices = $localeAwareServices; - $this->requestStack = $requestStack; - } - - public function onKernelRequest(RequestEvent $event): void - { - $this->setLocale($event->getRequest()->getLocale(), $event->getRequest()->getDefaultLocale()); - } - - public function onKernelFinishRequest(FinishRequestEvent $event): void - { - if (null === $parentRequest = $this->requestStack->getParentRequest()) { - foreach ($this->localeAwareServices as $service) { - $service->setLocale($event->getRequest()->getDefaultLocale()); - } - - return; - } - - $this->setLocale($parentRequest->getLocale(), $parentRequest->getDefaultLocale()); - } - - public static function getSubscribedEvents() - { - return [ - // must be registered after the Locale listener - KernelEvents::REQUEST => [['onKernelRequest', 15]], - KernelEvents::FINISH_REQUEST => [['onKernelFinishRequest', -15]], - ]; - } - - private function setLocale(string $locale, string $defaultLocale): void - { - foreach ($this->localeAwareServices as $service) { - try { - $service->setLocale($locale); - } catch (\InvalidArgumentException $e) { - $service->setLocale($defaultLocale); - } - } - } -} diff --git a/lib/symfony/http-kernel/EventListener/LocaleListener.php b/lib/symfony/http-kernel/EventListener/LocaleListener.php deleted file mode 100644 index f19e13649..000000000 --- a/lib/symfony/http-kernel/EventListener/LocaleListener.php +++ /dev/null @@ -1,95 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpKernel\Event\FinishRequestEvent; -use Symfony\Component\HttpKernel\Event\KernelEvent; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\Routing\RequestContextAwareInterface; - -/** - * Initializes the locale based on the current request. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class LocaleListener implements EventSubscriberInterface -{ - private $router; - private $defaultLocale; - private $requestStack; - private $useAcceptLanguageHeader; - private $enabledLocales; - - public function __construct(RequestStack $requestStack, string $defaultLocale = 'en', RequestContextAwareInterface $router = null, bool $useAcceptLanguageHeader = false, array $enabledLocales = []) - { - $this->defaultLocale = $defaultLocale; - $this->requestStack = $requestStack; - $this->router = $router; - $this->useAcceptLanguageHeader = $useAcceptLanguageHeader; - $this->enabledLocales = $enabledLocales; - } - - public function setDefaultLocale(KernelEvent $event) - { - $event->getRequest()->setDefaultLocale($this->defaultLocale); - } - - public function onKernelRequest(RequestEvent $event) - { - $request = $event->getRequest(); - - $this->setLocale($request); - $this->setRouterContext($request); - } - - public function onKernelFinishRequest(FinishRequestEvent $event) - { - if (null !== $parentRequest = $this->requestStack->getParentRequest()) { - $this->setRouterContext($parentRequest); - } - } - - private function setLocale(Request $request) - { - if ($locale = $request->attributes->get('_locale')) { - $request->setLocale($locale); - } elseif ($this->useAcceptLanguageHeader && $this->enabledLocales && ($preferredLanguage = $request->getPreferredLanguage($this->enabledLocales))) { - $request->setLocale($preferredLanguage); - $request->attributes->set('_vary_by_language', true); - } - } - - private function setRouterContext(Request $request) - { - if (null !== $this->router) { - $this->router->getContext()->setParameter('_locale', $request->getLocale()); - } - } - - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::REQUEST => [ - ['setDefaultLocale', 100], - // must be registered after the Router to have access to the _locale - ['onKernelRequest', 16], - ], - KernelEvents::FINISH_REQUEST => [['onKernelFinishRequest', 0]], - ]; - } -} diff --git a/lib/symfony/http-kernel/EventListener/ProfilerListener.php b/lib/symfony/http-kernel/EventListener/ProfilerListener.php deleted file mode 100644 index adbafe62e..000000000 --- a/lib/symfony/http-kernel/EventListener/ProfilerListener.php +++ /dev/null @@ -1,150 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestMatcherInterface; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Session\Session; -use Symfony\Component\HttpKernel\Event\ExceptionEvent; -use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Symfony\Component\HttpKernel\Event\TerminateEvent; -use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\HttpKernel\Profiler\Profile; -use Symfony\Component\HttpKernel\Profiler\Profiler; - -/** - * ProfilerListener collects data for the current request by listening to the kernel events. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class ProfilerListener implements EventSubscriberInterface -{ - protected $profiler; - protected $matcher; - protected $onlyException; - protected $onlyMainRequests; - protected $exception; - /** @var \SplObjectStorage<Request, Profile> */ - protected $profiles; - protected $requestStack; - protected $collectParameter; - /** @var \SplObjectStorage<Request, Request|null> */ - protected $parents; - - /** - * @param bool $onlyException True if the profiler only collects data when an exception occurs, false otherwise - * @param bool $onlyMainRequests True if the profiler only collects data when the request is the main request, false otherwise - */ - public function __construct(Profiler $profiler, RequestStack $requestStack, RequestMatcherInterface $matcher = null, bool $onlyException = false, bool $onlyMainRequests = false, string $collectParameter = null) - { - $this->profiler = $profiler; - $this->matcher = $matcher; - $this->onlyException = $onlyException; - $this->onlyMainRequests = $onlyMainRequests; - $this->profiles = new \SplObjectStorage(); - $this->parents = new \SplObjectStorage(); - $this->requestStack = $requestStack; - $this->collectParameter = $collectParameter; - } - - /** - * Handles the onKernelException event. - */ - public function onKernelException(ExceptionEvent $event) - { - if ($this->onlyMainRequests && !$event->isMainRequest()) { - return; - } - - $this->exception = $event->getThrowable(); - } - - /** - * Handles the onKernelResponse event. - */ - public function onKernelResponse(ResponseEvent $event) - { - if ($this->onlyMainRequests && !$event->isMainRequest()) { - return; - } - - if ($this->onlyException && null === $this->exception) { - return; - } - - $request = $event->getRequest(); - if (null !== $this->collectParameter && null !== $collectParameterValue = $request->get($this->collectParameter)) { - true === $collectParameterValue || filter_var($collectParameterValue, \FILTER_VALIDATE_BOOLEAN) ? $this->profiler->enable() : $this->profiler->disable(); - } - - $exception = $this->exception; - $this->exception = null; - - if (null !== $this->matcher && !$this->matcher->matches($request)) { - return; - } - - $session = $request->hasPreviousSession() && $request->hasSession() ? $request->getSession() : null; - - if ($session instanceof Session) { - $usageIndexValue = $usageIndexReference = &$session->getUsageIndex(); - $usageIndexReference = \PHP_INT_MIN; - } - - try { - if (!$profile = $this->profiler->collect($request, $event->getResponse(), $exception)) { - return; - } - } finally { - if ($session instanceof Session) { - $usageIndexReference = $usageIndexValue; - } - } - - $this->profiles[$request] = $profile; - - $this->parents[$request] = $this->requestStack->getParentRequest(); - } - - public function onKernelTerminate(TerminateEvent $event) - { - // attach children to parents - foreach ($this->profiles as $request) { - if (null !== $parentRequest = $this->parents[$request]) { - if (isset($this->profiles[$parentRequest])) { - $this->profiles[$parentRequest]->addChild($this->profiles[$request]); - } - } - } - - // save profiles - foreach ($this->profiles as $request) { - $this->profiler->saveProfile($this->profiles[$request]); - } - - $this->profiles = new \SplObjectStorage(); - $this->parents = new \SplObjectStorage(); - } - - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::RESPONSE => ['onKernelResponse', -100], - KernelEvents::EXCEPTION => ['onKernelException', 0], - KernelEvents::TERMINATE => ['onKernelTerminate', -1024], - ]; - } -} diff --git a/lib/symfony/http-kernel/EventListener/ResponseListener.php b/lib/symfony/http-kernel/EventListener/ResponseListener.php deleted file mode 100644 index a4090159b..000000000 --- a/lib/symfony/http-kernel/EventListener/ResponseListener.php +++ /dev/null @@ -1,68 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Symfony\Component\HttpKernel\KernelEvents; - -/** - * ResponseListener fixes the Response headers based on the Request. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class ResponseListener implements EventSubscriberInterface -{ - private $charset; - private $addContentLanguageHeader; - - public function __construct(string $charset, bool $addContentLanguageHeader = false) - { - $this->charset = $charset; - $this->addContentLanguageHeader = $addContentLanguageHeader; - } - - /** - * Filters the Response. - */ - public function onKernelResponse(ResponseEvent $event) - { - if (!$event->isMainRequest()) { - return; - } - - $response = $event->getResponse(); - - if (null === $response->getCharset()) { - $response->setCharset($this->charset); - } - - if ($this->addContentLanguageHeader && !$response->isInformational() && !$response->isEmpty() && !$response->headers->has('Content-Language')) { - $response->headers->set('Content-Language', $event->getRequest()->getLocale()); - } - - if ($event->getRequest()->attributes->get('_vary_by_language')) { - $response->setVary('Accept-Language', false); - } - - $response->prepare($event->getRequest()); - } - - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::RESPONSE => 'onKernelResponse', - ]; - } -} diff --git a/lib/symfony/http-kernel/EventListener/RouterListener.php b/lib/symfony/http-kernel/EventListener/RouterListener.php deleted file mode 100644 index 7c4da9892..000000000 --- a/lib/symfony/http-kernel/EventListener/RouterListener.php +++ /dev/null @@ -1,174 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Psr\Log\LoggerInterface; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Event\ExceptionEvent; -use Symfony\Component\HttpKernel\Event\FinishRequestEvent; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; -use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -use Symfony\Component\HttpKernel\Kernel; -use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\Routing\Exception\MethodNotAllowedException; -use Symfony\Component\Routing\Exception\NoConfigurationException; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; -use Symfony\Component\Routing\Matcher\RequestMatcherInterface; -use Symfony\Component\Routing\Matcher\UrlMatcherInterface; -use Symfony\Component\Routing\RequestContext; -use Symfony\Component\Routing\RequestContextAwareInterface; - -/** - * Initializes the context from the request and sets request attributes based on a matching route. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Yonel Ceruto <yonelceruto@gmail.com> - * - * @final - */ -class RouterListener implements EventSubscriberInterface -{ - private $matcher; - private $context; - private $logger; - private $requestStack; - private $projectDir; - private $debug; - - /** - * @param UrlMatcherInterface|RequestMatcherInterface $matcher The Url or Request matcher - * @param RequestContext|null $context The RequestContext (can be null when $matcher implements RequestContextAwareInterface) - * - * @throws \InvalidArgumentException - */ - public function __construct($matcher, RequestStack $requestStack, RequestContext $context = null, LoggerInterface $logger = null, string $projectDir = null, bool $debug = true) - { - if (!$matcher instanceof UrlMatcherInterface && !$matcher instanceof RequestMatcherInterface) { - throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.'); - } - - if (null === $context && !$matcher instanceof RequestContextAwareInterface) { - throw new \InvalidArgumentException('You must either pass a RequestContext or the matcher must implement RequestContextAwareInterface.'); - } - - $this->matcher = $matcher; - $this->context = $context ?? $matcher->getContext(); - $this->requestStack = $requestStack; - $this->logger = $logger; - $this->projectDir = $projectDir; - $this->debug = $debug; - } - - private function setCurrentRequest(Request $request = null) - { - if (null !== $request) { - try { - $this->context->fromRequest($request); - } catch (\UnexpectedValueException $e) { - throw new BadRequestHttpException($e->getMessage(), $e, $e->getCode()); - } - } - } - - /** - * After a sub-request is done, we need to reset the routing context to the parent request so that the URL generator - * operates on the correct context again. - */ - public function onKernelFinishRequest(FinishRequestEvent $event) - { - $this->setCurrentRequest($this->requestStack->getParentRequest()); - } - - public function onKernelRequest(RequestEvent $event) - { - $request = $event->getRequest(); - - $this->setCurrentRequest($request); - - if ($request->attributes->has('_controller')) { - // routing is already done - return; - } - - // add attributes based on the request (routing) - try { - // matching a request is more powerful than matching a URL path + context, so try that first - if ($this->matcher instanceof RequestMatcherInterface) { - $parameters = $this->matcher->matchRequest($request); - } else { - $parameters = $this->matcher->match($request->getPathInfo()); - } - - if (null !== $this->logger) { - $this->logger->info('Matched route "{route}".', [ - 'route' => $parameters['_route'] ?? 'n/a', - 'route_parameters' => $parameters, - 'request_uri' => $request->getUri(), - 'method' => $request->getMethod(), - ]); - } - - $request->attributes->add($parameters); - unset($parameters['_route'], $parameters['_controller']); - $request->attributes->set('_route_params', $parameters); - } catch (ResourceNotFoundException $e) { - $message = sprintf('No route found for "%s %s"', $request->getMethod(), $request->getUriForPath($request->getPathInfo())); - - if ($referer = $request->headers->get('referer')) { - $message .= sprintf(' (from "%s")', $referer); - } - - throw new NotFoundHttpException($message, $e); - } catch (MethodNotAllowedException $e) { - $message = sprintf('No route found for "%s %s": Method Not Allowed (Allow: %s)', $request->getMethod(), $request->getUriForPath($request->getPathInfo()), implode(', ', $e->getAllowedMethods())); - - throw new MethodNotAllowedHttpException($e->getAllowedMethods(), $message, $e); - } - } - - public function onKernelException(ExceptionEvent $event) - { - if (!$this->debug || !($e = $event->getThrowable()) instanceof NotFoundHttpException) { - return; - } - - if ($e->getPrevious() instanceof NoConfigurationException) { - $event->setResponse($this->createWelcomeResponse()); - } - } - - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::REQUEST => [['onKernelRequest', 32]], - KernelEvents::FINISH_REQUEST => [['onKernelFinishRequest', 0]], - KernelEvents::EXCEPTION => ['onKernelException', -64], - ]; - } - - private function createWelcomeResponse(): Response - { - $version = Kernel::VERSION; - $projectDir = realpath((string) $this->projectDir).\DIRECTORY_SEPARATOR; - $docVersion = substr(Kernel::VERSION, 0, 3); - - ob_start(); - include \dirname(__DIR__).'/Resources/welcome.html.php'; - - return new Response(ob_get_clean(), Response::HTTP_NOT_FOUND); - } -} diff --git a/lib/symfony/http-kernel/EventListener/SessionListener.php b/lib/symfony/http-kernel/EventListener/SessionListener.php deleted file mode 100644 index 61887fde6..000000000 --- a/lib/symfony/http-kernel/EventListener/SessionListener.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\HttpFoundation\Session\SessionInterface; -use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; -use Symfony\Component\HttpKernel\Event\RequestEvent; - -/** - * Sets the session in the request. - * - * When the passed container contains a "session_storage" entry which - * holds a NativeSessionStorage instance, the "cookie_secure" option - * will be set to true whenever the current main request is secure. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class SessionListener extends AbstractSessionListener -{ - public function onKernelRequest(RequestEvent $event) - { - parent::onKernelRequest($event); - - if (!$event->isMainRequest() || (!$this->container->has('session') && !$this->container->has('session_factory'))) { - return; - } - - if ($this->container->has('session_storage') - && ($storage = $this->container->get('session_storage')) instanceof NativeSessionStorage - && ($mainRequest = $this->container->get('request_stack')->getMainRequest()) - && $mainRequest->isSecure() - ) { - $storage->setOptions(['cookie_secure' => true]); - } - } - - protected function getSession(): ?SessionInterface - { - if ($this->container->has('session')) { - return $this->container->get('session'); - } - - if ($this->container->has('session_factory')) { - return $this->container->get('session_factory')->createSession(); - } - - return null; - } -} diff --git a/lib/symfony/http-kernel/EventListener/StreamedResponseListener.php b/lib/symfony/http-kernel/EventListener/StreamedResponseListener.php deleted file mode 100644 index b3f7ca40f..000000000 --- a/lib/symfony/http-kernel/EventListener/StreamedResponseListener.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\StreamedResponse; -use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Symfony\Component\HttpKernel\KernelEvents; - -/** - * StreamedResponseListener is responsible for sending the Response - * to the client. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class StreamedResponseListener implements EventSubscriberInterface -{ - /** - * Filters the Response. - */ - public function onKernelResponse(ResponseEvent $event) - { - if (!$event->isMainRequest()) { - return; - } - - $response = $event->getResponse(); - - if ($response instanceof StreamedResponse) { - $response->send(); - } - } - - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::RESPONSE => ['onKernelResponse', -1024], - ]; - } -} diff --git a/lib/symfony/http-kernel/EventListener/SurrogateListener.php b/lib/symfony/http-kernel/EventListener/SurrogateListener.php deleted file mode 100644 index 9081bff65..000000000 --- a/lib/symfony/http-kernel/EventListener/SurrogateListener.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Symfony\Component\HttpKernel\HttpCache\HttpCache; -use Symfony\Component\HttpKernel\HttpCache\SurrogateInterface; -use Symfony\Component\HttpKernel\KernelEvents; - -/** - * SurrogateListener adds a Surrogate-Control HTTP header when the Response needs to be parsed for Surrogates. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class SurrogateListener implements EventSubscriberInterface -{ - private $surrogate; - - public function __construct(SurrogateInterface $surrogate = null) - { - $this->surrogate = $surrogate; - } - - /** - * Filters the Response. - */ - public function onKernelResponse(ResponseEvent $event) - { - if (!$event->isMainRequest()) { - return; - } - - $kernel = $event->getKernel(); - $surrogate = $this->surrogate; - if ($kernel instanceof HttpCache) { - $surrogate = $kernel->getSurrogate(); - if (null !== $this->surrogate && $this->surrogate->getName() !== $surrogate->getName()) { - $surrogate = $this->surrogate; - } - } - - if (null === $surrogate) { - return; - } - - $surrogate->addSurrogateControl($event->getResponse()); - } - - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::RESPONSE => 'onKernelResponse', - ]; - } -} diff --git a/lib/symfony/http-kernel/EventListener/TestSessionListener.php b/lib/symfony/http-kernel/EventListener/TestSessionListener.php deleted file mode 100644 index 45fa312be..000000000 --- a/lib/symfony/http-kernel/EventListener/TestSessionListener.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Psr\Container\ContainerInterface; -use Symfony\Component\HttpFoundation\Session\SessionInterface; - -trigger_deprecation('symfony/http-kernel', '5.4', '"%s" is deprecated, use "%s" instead.', TestSessionListener::class, SessionListener::class); - -/** - * Sets the session in the request. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - * - * @deprecated since Symfony 5.4, use SessionListener instead - */ -class TestSessionListener extends AbstractTestSessionListener -{ - private $container; - - public function __construct(ContainerInterface $container, array $sessionOptions = []) - { - $this->container = $container; - parent::__construct($sessionOptions); - } - - protected function getSession(): ?SessionInterface - { - if ($this->container->has('session')) { - return $this->container->get('session'); - } - - return null; - } -} diff --git a/lib/symfony/http-kernel/EventListener/ValidateRequestListener.php b/lib/symfony/http-kernel/EventListener/ValidateRequestListener.php deleted file mode 100644 index caa0f32aa..000000000 --- a/lib/symfony/http-kernel/EventListener/ValidateRequestListener.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\KernelEvents; - -/** - * Validates Requests. - * - * @author Magnus Nordlander <magnus@fervo.se> - * - * @final - */ -class ValidateRequestListener implements EventSubscriberInterface -{ - /** - * Performs the validation. - */ - public function onKernelRequest(RequestEvent $event) - { - if (!$event->isMainRequest()) { - return; - } - $request = $event->getRequest(); - - if ($request::getTrustedProxies()) { - $request->getClientIps(); - } - - $request->getHost(); - } - - /** - * {@inheritdoc} - */ - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::REQUEST => [ - ['onKernelRequest', 256], - ], - ]; - } -} diff --git a/lib/symfony/http-kernel/Exception/AccessDeniedHttpException.php b/lib/symfony/http-kernel/Exception/AccessDeniedHttpException.php deleted file mode 100644 index 58680a327..000000000 --- a/lib/symfony/http-kernel/Exception/AccessDeniedHttpException.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Fabien Potencier <fabien@symfony.com> - * @author Christophe Coevoet <stof@notk.org> - */ -class AccessDeniedHttpException extends HttpException -{ - /** - * @param string|null $message The internal exception message - * @param \Throwable|null $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) - { - if (null === $message) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__); - - $message = ''; - } - - parent::__construct(403, $message, $previous, $headers, $code); - } -} diff --git a/lib/symfony/http-kernel/Exception/BadRequestHttpException.php b/lib/symfony/http-kernel/Exception/BadRequestHttpException.php deleted file mode 100644 index f530f7db4..000000000 --- a/lib/symfony/http-kernel/Exception/BadRequestHttpException.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Ben Ramsey <ben@benramsey.com> - */ -class BadRequestHttpException extends HttpException -{ - /** - * @param string|null $message The internal exception message - * @param \Throwable|null $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) - { - if (null === $message) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__); - - $message = ''; - } - - parent::__construct(400, $message, $previous, $headers, $code); - } -} diff --git a/lib/symfony/http-kernel/Exception/ConflictHttpException.php b/lib/symfony/http-kernel/Exception/ConflictHttpException.php deleted file mode 100644 index 79c36041c..000000000 --- a/lib/symfony/http-kernel/Exception/ConflictHttpException.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Ben Ramsey <ben@benramsey.com> - */ -class ConflictHttpException extends HttpException -{ - /** - * @param string|null $message The internal exception message - * @param \Throwable|null $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) - { - if (null === $message) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__); - - $message = ''; - } - - parent::__construct(409, $message, $previous, $headers, $code); - } -} diff --git a/lib/symfony/http-kernel/Exception/ControllerDoesNotReturnResponseException.php b/lib/symfony/http-kernel/Exception/ControllerDoesNotReturnResponseException.php deleted file mode 100644 index 54c80be90..000000000 --- a/lib/symfony/http-kernel/Exception/ControllerDoesNotReturnResponseException.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Grégoire Pineau <lyrixx@lyrixx.info> - */ -class ControllerDoesNotReturnResponseException extends \LogicException -{ - public function __construct(string $message, callable $controller, string $file, int $line) - { - parent::__construct($message); - - if (!$controllerDefinition = $this->parseControllerDefinition($controller)) { - return; - } - - $this->file = $controllerDefinition['file']; - $this->line = $controllerDefinition['line']; - $r = new \ReflectionProperty(\Exception::class, 'trace'); - $r->setAccessible(true); - $r->setValue($this, array_merge([ - [ - 'line' => $line, - 'file' => $file, - ], - ], $this->getTrace())); - } - - private function parseControllerDefinition(callable $controller): ?array - { - if (\is_string($controller) && str_contains($controller, '::')) { - $controller = explode('::', $controller); - } - - if (\is_array($controller)) { - try { - $r = new \ReflectionMethod($controller[0], $controller[1]); - - return [ - 'file' => $r->getFileName(), - 'line' => $r->getEndLine(), - ]; - } catch (\ReflectionException $e) { - return null; - } - } - - if ($controller instanceof \Closure) { - $r = new \ReflectionFunction($controller); - - return [ - 'file' => $r->getFileName(), - 'line' => $r->getEndLine(), - ]; - } - - if (\is_object($controller)) { - $r = new \ReflectionClass($controller); - - try { - $line = $r->getMethod('__invoke')->getEndLine(); - } catch (\ReflectionException $e) { - $line = $r->getEndLine(); - } - - return [ - 'file' => $r->getFileName(), - 'line' => $line, - ]; - } - - return null; - } -} diff --git a/lib/symfony/http-kernel/Exception/GoneHttpException.php b/lib/symfony/http-kernel/Exception/GoneHttpException.php deleted file mode 100644 index 9ea65057b..000000000 --- a/lib/symfony/http-kernel/Exception/GoneHttpException.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Ben Ramsey <ben@benramsey.com> - */ -class GoneHttpException extends HttpException -{ - /** - * @param string|null $message The internal exception message - * @param \Throwable|null $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) - { - if (null === $message) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__); - - $message = ''; - } - - parent::__construct(410, $message, $previous, $headers, $code); - } -} diff --git a/lib/symfony/http-kernel/Exception/HttpException.php b/lib/symfony/http-kernel/Exception/HttpException.php deleted file mode 100644 index 249fe366d..000000000 --- a/lib/symfony/http-kernel/Exception/HttpException.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * HttpException. - * - * @author Kris Wallsmith <kris@symfony.com> - */ -class HttpException extends \RuntimeException implements HttpExceptionInterface -{ - private $statusCode; - private $headers; - - public function __construct(int $statusCode, ?string $message = '', \Throwable $previous = null, array $headers = [], ?int $code = 0) - { - if (null === $message) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__); - - $message = ''; - } - if (null === $code) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $code to "%s()" is deprecated, pass 0 instead.', __METHOD__); - - $code = 0; - } - - $this->statusCode = $statusCode; - $this->headers = $headers; - - parent::__construct($message, $code, $previous); - } - - public function getStatusCode() - { - return $this->statusCode; - } - - public function getHeaders() - { - return $this->headers; - } - - /** - * Set response headers. - * - * @param array $headers Response headers - */ - public function setHeaders(array $headers) - { - $this->headers = $headers; - } -} diff --git a/lib/symfony/http-kernel/Exception/HttpExceptionInterface.php b/lib/symfony/http-kernel/Exception/HttpExceptionInterface.php deleted file mode 100644 index 4ae050945..000000000 --- a/lib/symfony/http-kernel/Exception/HttpExceptionInterface.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * Interface for HTTP error exceptions. - * - * @author Kris Wallsmith <kris@symfony.com> - */ -interface HttpExceptionInterface extends \Throwable -{ - /** - * Returns the status code. - * - * @return int - */ - public function getStatusCode(); - - /** - * Returns response headers. - * - * @return array - */ - public function getHeaders(); -} diff --git a/lib/symfony/http-kernel/Exception/InvalidMetadataException.php b/lib/symfony/http-kernel/Exception/InvalidMetadataException.php deleted file mode 100644 index 129267ab0..000000000 --- a/lib/symfony/http-kernel/Exception/InvalidMetadataException.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -class InvalidMetadataException extends \LogicException -{ -} diff --git a/lib/symfony/http-kernel/Exception/LengthRequiredHttpException.php b/lib/symfony/http-kernel/Exception/LengthRequiredHttpException.php deleted file mode 100644 index fcac13785..000000000 --- a/lib/symfony/http-kernel/Exception/LengthRequiredHttpException.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Ben Ramsey <ben@benramsey.com> - */ -class LengthRequiredHttpException extends HttpException -{ - /** - * @param string|null $message The internal exception message - * @param \Throwable|null $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) - { - if (null === $message) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__); - - $message = ''; - } - - parent::__construct(411, $message, $previous, $headers, $code); - } -} diff --git a/lib/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php b/lib/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php deleted file mode 100644 index 37576bcac..000000000 --- a/lib/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Kris Wallsmith <kris@symfony.com> - */ -class MethodNotAllowedHttpException extends HttpException -{ - /** - * @param string[] $allow An array of allowed methods - * @param string|null $message The internal exception message - * @param \Throwable|null $previous The previous exception - * @param int|null $code The internal exception code - */ - public function __construct(array $allow, ?string $message = '', \Throwable $previous = null, ?int $code = 0, array $headers = []) - { - if (null === $message) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__); - - $message = ''; - } - if (null === $code) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $code to "%s()" is deprecated, pass 0 instead.', __METHOD__); - - $code = 0; - } - - $headers['Allow'] = strtoupper(implode(', ', $allow)); - - parent::__construct(405, $message, $previous, $headers, $code); - } -} diff --git a/lib/symfony/http-kernel/Exception/NotAcceptableHttpException.php b/lib/symfony/http-kernel/Exception/NotAcceptableHttpException.php deleted file mode 100644 index 5a422406b..000000000 --- a/lib/symfony/http-kernel/Exception/NotAcceptableHttpException.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Ben Ramsey <ben@benramsey.com> - */ -class NotAcceptableHttpException extends HttpException -{ - /** - * @param string|null $message The internal exception message - * @param \Throwable|null $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) - { - if (null === $message) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__); - - $message = ''; - } - - parent::__construct(406, $message, $previous, $headers, $code); - } -} diff --git a/lib/symfony/http-kernel/Exception/NotFoundHttpException.php b/lib/symfony/http-kernel/Exception/NotFoundHttpException.php deleted file mode 100644 index a475113c5..000000000 --- a/lib/symfony/http-kernel/Exception/NotFoundHttpException.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -class NotFoundHttpException extends HttpException -{ - /** - * @param string|null $message The internal exception message - * @param \Throwable|null $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) - { - if (null === $message) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__); - - $message = ''; - } - - parent::__construct(404, $message, $previous, $headers, $code); - } -} diff --git a/lib/symfony/http-kernel/Exception/PreconditionFailedHttpException.php b/lib/symfony/http-kernel/Exception/PreconditionFailedHttpException.php deleted file mode 100644 index e23740a28..000000000 --- a/lib/symfony/http-kernel/Exception/PreconditionFailedHttpException.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Ben Ramsey <ben@benramsey.com> - */ -class PreconditionFailedHttpException extends HttpException -{ - /** - * @param string|null $message The internal exception message - * @param \Throwable|null $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) - { - if (null === $message) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__); - - $message = ''; - } - - parent::__construct(412, $message, $previous, $headers, $code); - } -} diff --git a/lib/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php b/lib/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php deleted file mode 100644 index 5c31fae82..000000000 --- a/lib/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Ben Ramsey <ben@benramsey.com> - * - * @see http://tools.ietf.org/html/rfc6585 - */ -class PreconditionRequiredHttpException extends HttpException -{ - /** - * @param string|null $message The internal exception message - * @param \Throwable|null $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) - { - if (null === $message) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__); - - $message = ''; - } - - parent::__construct(428, $message, $previous, $headers, $code); - } -} diff --git a/lib/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php b/lib/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php deleted file mode 100644 index d5681bbeb..000000000 --- a/lib/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Ben Ramsey <ben@benramsey.com> - */ -class ServiceUnavailableHttpException extends HttpException -{ - /** - * @param int|string|null $retryAfter The number of seconds or HTTP-date after which the request may be retried - * @param string|null $message The internal exception message - * @param \Throwable|null $previous The previous exception - * @param int|null $code The internal exception code - */ - public function __construct($retryAfter = null, ?string $message = '', \Throwable $previous = null, ?int $code = 0, array $headers = []) - { - if (null === $message) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__); - - $message = ''; - } - if (null === $code) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $code to "%s()" is deprecated, pass 0 instead.', __METHOD__); - - $code = 0; - } - - if ($retryAfter) { - $headers['Retry-After'] = $retryAfter; - } - - parent::__construct(503, $message, $previous, $headers, $code); - } -} diff --git a/lib/symfony/http-kernel/Exception/TooManyRequestsHttpException.php b/lib/symfony/http-kernel/Exception/TooManyRequestsHttpException.php deleted file mode 100644 index fd74402b5..000000000 --- a/lib/symfony/http-kernel/Exception/TooManyRequestsHttpException.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Ben Ramsey <ben@benramsey.com> - * - * @see http://tools.ietf.org/html/rfc6585 - */ -class TooManyRequestsHttpException extends HttpException -{ - /** - * @param int|string|null $retryAfter The number of seconds or HTTP-date after which the request may be retried - * @param string|null $message The internal exception message - * @param \Throwable|null $previous The previous exception - * @param int|null $code The internal exception code - */ - public function __construct($retryAfter = null, ?string $message = '', \Throwable $previous = null, ?int $code = 0, array $headers = []) - { - if (null === $message) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__); - - $message = ''; - } - if (null === $code) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $code to "%s()" is deprecated, pass 0 instead.', __METHOD__); - - $code = 0; - } - - if ($retryAfter) { - $headers['Retry-After'] = $retryAfter; - } - - parent::__construct(429, $message, $previous, $headers, $code); - } -} diff --git a/lib/symfony/http-kernel/Exception/UnauthorizedHttpException.php b/lib/symfony/http-kernel/Exception/UnauthorizedHttpException.php deleted file mode 100644 index aeb9713a3..000000000 --- a/lib/symfony/http-kernel/Exception/UnauthorizedHttpException.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Ben Ramsey <ben@benramsey.com> - */ -class UnauthorizedHttpException extends HttpException -{ - /** - * @param string $challenge WWW-Authenticate challenge string - * @param string|null $message The internal exception message - * @param \Throwable|null $previous The previous exception - * @param int|null $code The internal exception code - */ - public function __construct(string $challenge, ?string $message = '', \Throwable $previous = null, ?int $code = 0, array $headers = []) - { - if (null === $message) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__); - - $message = ''; - } - if (null === $code) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $code to "%s()" is deprecated, pass 0 instead.', __METHOD__); - - $code = 0; - } - - $headers['WWW-Authenticate'] = $challenge; - - parent::__construct(401, $message, $previous, $headers, $code); - } -} diff --git a/lib/symfony/http-kernel/Exception/UnexpectedSessionUsageException.php b/lib/symfony/http-kernel/Exception/UnexpectedSessionUsageException.php deleted file mode 100644 index 0145b1691..000000000 --- a/lib/symfony/http-kernel/Exception/UnexpectedSessionUsageException.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Mathias Arlaud <mathias.arlaud@gmail.com> - */ -class UnexpectedSessionUsageException extends \LogicException -{ -} diff --git a/lib/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php b/lib/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php deleted file mode 100644 index 7b828b1d9..000000000 --- a/lib/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Steve Hutchins <hutchinsteve@gmail.com> - */ -class UnprocessableEntityHttpException extends HttpException -{ - /** - * @param string|null $message The internal exception message - * @param \Throwable|null $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) - { - if (null === $message) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__); - - $message = ''; - } - - parent::__construct(422, $message, $previous, $headers, $code); - } -} diff --git a/lib/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php b/lib/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php deleted file mode 100644 index 7908423f4..000000000 --- a/lib/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Ben Ramsey <ben@benramsey.com> - */ -class UnsupportedMediaTypeHttpException extends HttpException -{ - /** - * @param string|null $message The internal exception message - * @param \Throwable|null $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) - { - if (null === $message) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__); - - $message = ''; - } - - parent::__construct(415, $message, $previous, $headers, $code); - } -} diff --git a/lib/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php b/lib/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php deleted file mode 100644 index 4e4d028b4..000000000 --- a/lib/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php +++ /dev/null @@ -1,103 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Fragment; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Controller\ControllerReference; -use Symfony\Component\HttpKernel\HttpCache\SurrogateInterface; -use Symfony\Component\HttpKernel\UriSigner; - -/** - * Implements Surrogate rendering strategy. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRenderer -{ - private $surrogate; - private $inlineStrategy; - private $signer; - - /** - * The "fallback" strategy when surrogate is not available should always be an - * instance of InlineFragmentRenderer. - * - * @param FragmentRendererInterface $inlineStrategy The inline strategy to use when the surrogate is not supported - */ - public function __construct(SurrogateInterface $surrogate = null, FragmentRendererInterface $inlineStrategy, UriSigner $signer = null) - { - $this->surrogate = $surrogate; - $this->inlineStrategy = $inlineStrategy; - $this->signer = $signer; - } - - /** - * {@inheritdoc} - * - * Note that if the current Request has no surrogate capability, this method - * falls back to use the inline rendering strategy. - * - * Additional available options: - * - * * alt: an alternative URI to render in case of an error - * * comment: a comment to add when returning the surrogate tag - * - * Note, that not all surrogate strategies support all options. For now - * 'alt' and 'comment' are only supported by ESI. - * - * @see Symfony\Component\HttpKernel\HttpCache\SurrogateInterface - */ - public function render($uri, Request $request, array $options = []) - { - if (!$this->surrogate || !$this->surrogate->hasSurrogateCapability($request)) { - if ($uri instanceof ControllerReference && $this->containsNonScalars($uri->attributes)) { - throw new \InvalidArgumentException('Passing non-scalar values as part of URI attributes to the ESI and SSI rendering strategies is not supported. Use a different rendering strategy or pass scalar values.'); - } - - return $this->inlineStrategy->render($uri, $request, $options); - } - - if ($uri instanceof ControllerReference) { - $uri = $this->generateSignedFragmentUri($uri, $request); - } - - $alt = $options['alt'] ?? null; - if ($alt instanceof ControllerReference) { - $alt = $this->generateSignedFragmentUri($alt, $request); - } - - $tag = $this->surrogate->renderIncludeTag($uri, $alt, $options['ignore_errors'] ?? false, $options['comment'] ?? ''); - - return new Response($tag); - } - - private function generateSignedFragmentUri(ControllerReference $uri, Request $request): string - { - return (new FragmentUriGenerator($this->fragmentPath, $this->signer))->generate($uri, $request); - } - - private function containsNonScalars(array $values): bool - { - foreach ($values as $value) { - if (\is_scalar($value) || null === $value) { - continue; - } - - if (!\is_array($value) || $this->containsNonScalars($value)) { - return true; - } - } - - return false; - } -} diff --git a/lib/symfony/http-kernel/Fragment/EsiFragmentRenderer.php b/lib/symfony/http-kernel/Fragment/EsiFragmentRenderer.php deleted file mode 100644 index a4570e3be..000000000 --- a/lib/symfony/http-kernel/Fragment/EsiFragmentRenderer.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Fragment; - -/** - * Implements the ESI rendering strategy. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class EsiFragmentRenderer extends AbstractSurrogateFragmentRenderer -{ - /** - * {@inheritdoc} - */ - public function getName() - { - return 'esi'; - } -} diff --git a/lib/symfony/http-kernel/Fragment/FragmentHandler.php b/lib/symfony/http-kernel/Fragment/FragmentHandler.php deleted file mode 100644 index 1ecaaef1a..000000000 --- a/lib/symfony/http-kernel/Fragment/FragmentHandler.php +++ /dev/null @@ -1,113 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Fragment; - -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpFoundation\StreamedResponse; -use Symfony\Component\HttpKernel\Controller\ControllerReference; -use Symfony\Component\HttpKernel\Exception\HttpException; - -/** - * Renders a URI that represents a resource fragment. - * - * This class handles the rendering of resource fragments that are included into - * a main resource. The handling of the rendering is managed by specialized renderers. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @see FragmentRendererInterface - */ -class FragmentHandler -{ - private $debug; - private $renderers = []; - private $requestStack; - - /** - * @param FragmentRendererInterface[] $renderers An array of FragmentRendererInterface instances - * @param bool $debug Whether the debug mode is enabled or not - */ - public function __construct(RequestStack $requestStack, array $renderers = [], bool $debug = false) - { - $this->requestStack = $requestStack; - foreach ($renderers as $renderer) { - $this->addRenderer($renderer); - } - $this->debug = $debug; - } - - /** - * Adds a renderer. - */ - public function addRenderer(FragmentRendererInterface $renderer) - { - $this->renderers[$renderer->getName()] = $renderer; - } - - /** - * Renders a URI and returns the Response content. - * - * Available options: - * - * * ignore_errors: true to return an empty string in case of an error - * - * @param string|ControllerReference $uri A URI as a string or a ControllerReference instance - * - * @return string|null - * - * @throws \InvalidArgumentException when the renderer does not exist - * @throws \LogicException when no main request is being handled - */ - public function render($uri, string $renderer = 'inline', array $options = []) - { - if (!isset($options['ignore_errors'])) { - $options['ignore_errors'] = !$this->debug; - } - - if (!isset($this->renderers[$renderer])) { - throw new \InvalidArgumentException(sprintf('The "%s" renderer does not exist.', $renderer)); - } - - if (!$request = $this->requestStack->getCurrentRequest()) { - throw new \LogicException('Rendering a fragment can only be done when handling a Request.'); - } - - return $this->deliver($this->renderers[$renderer]->render($uri, $request, $options)); - } - - /** - * Delivers the Response as a string. - * - * When the Response is a StreamedResponse, the content is streamed immediately - * instead of being returned. - * - * @return string|null The Response content or null when the Response is streamed - * - * @throws \RuntimeException when the Response is not successful - */ - protected function deliver(Response $response) - { - if (!$response->isSuccessful()) { - $responseStatusCode = $response->getStatusCode(); - throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %d).', $this->requestStack->getCurrentRequest()->getUri(), $responseStatusCode), 0, new HttpException($responseStatusCode)); - } - - if (!$response instanceof StreamedResponse) { - return $response->getContent(); - } - - $response->sendContent(); - - return null; - } -} diff --git a/lib/symfony/http-kernel/Fragment/FragmentRendererInterface.php b/lib/symfony/http-kernel/Fragment/FragmentRendererInterface.php deleted file mode 100644 index 568b1781a..000000000 --- a/lib/symfony/http-kernel/Fragment/FragmentRendererInterface.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Fragment; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Controller\ControllerReference; - -/** - * Interface implemented by all rendering strategies. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface FragmentRendererInterface -{ - /** - * Renders a URI and returns the Response content. - * - * @param string|ControllerReference $uri A URI as a string or a ControllerReference instance - * - * @return Response - */ - public function render($uri, Request $request, array $options = []); - - /** - * Gets the name of the strategy. - * - * @return string - */ - public function getName(); -} diff --git a/lib/symfony/http-kernel/Fragment/FragmentUriGenerator.php b/lib/symfony/http-kernel/Fragment/FragmentUriGenerator.php deleted file mode 100644 index 4c0fac997..000000000 --- a/lib/symfony/http-kernel/Fragment/FragmentUriGenerator.php +++ /dev/null @@ -1,93 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Fragment; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpKernel\Controller\ControllerReference; -use Symfony\Component\HttpKernel\UriSigner; - -/** - * Generates a fragment URI. - * - * @author Kévin Dunglas <kevin@dunglas.fr> - * @author Fabien Potencier <fabien@symfony.com> - */ -final class FragmentUriGenerator implements FragmentUriGeneratorInterface -{ - private $fragmentPath; - private $signer; - private $requestStack; - - public function __construct(string $fragmentPath, UriSigner $signer = null, RequestStack $requestStack = null) - { - $this->fragmentPath = $fragmentPath; - $this->signer = $signer; - $this->requestStack = $requestStack; - } - - /** - * {@inheritDoc} - */ - public function generate(ControllerReference $controller, Request $request = null, bool $absolute = false, bool $strict = true, bool $sign = true): string - { - if (null === $request && (null === $this->requestStack || null === $request = $this->requestStack->getCurrentRequest())) { - throw new \LogicException('Generating a fragment URL can only be done when handling a Request.'); - } - - if ($sign && null === $this->signer) { - throw new \LogicException('You must use a URI when using the ESI rendering strategy or set a URL signer.'); - } - - if ($strict) { - $this->checkNonScalar($controller->attributes); - } - - // We need to forward the current _format and _locale values as we don't have - // a proper routing pattern to do the job for us. - // This makes things inconsistent if you switch from rendering a controller - // to rendering a route if the route pattern does not contain the special - // _format and _locale placeholders. - if (!isset($controller->attributes['_format'])) { - $controller->attributes['_format'] = $request->getRequestFormat(); - } - if (!isset($controller->attributes['_locale'])) { - $controller->attributes['_locale'] = $request->getLocale(); - } - - $controller->attributes['_controller'] = $controller->controller; - $controller->query['_path'] = http_build_query($controller->attributes, '', '&'); - $path = $this->fragmentPath.'?'.http_build_query($controller->query, '', '&'); - - // we need to sign the absolute URI, but want to return the path only. - $fragmentUri = $sign || $absolute ? $request->getUriForPath($path) : $request->getBaseUrl().$path; - - if (!$sign) { - return $fragmentUri; - } - - $fragmentUri = $this->signer->sign($fragmentUri); - - return $absolute ? $fragmentUri : substr($fragmentUri, \strlen($request->getSchemeAndHttpHost())); - } - - private function checkNonScalar(array $values): void - { - foreach ($values as $key => $value) { - if (\is_array($value)) { - $this->checkNonScalar($value); - } elseif (!\is_scalar($value) && null !== $value) { - throw new \LogicException(sprintf('Controller attributes cannot contain non-scalar/non-null values (value for key "%s" is not a scalar or null).', $key)); - } - } - } -} diff --git a/lib/symfony/http-kernel/Fragment/FragmentUriGeneratorInterface.php b/lib/symfony/http-kernel/Fragment/FragmentUriGeneratorInterface.php deleted file mode 100644 index b211f5e37..000000000 --- a/lib/symfony/http-kernel/Fragment/FragmentUriGeneratorInterface.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Fragment; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ControllerReference; - -/** - * Interface implemented by rendering strategies able to generate an URL for a fragment. - * - * @author Kévin Dunglas <kevin@dunglas.fr> - */ -interface FragmentUriGeneratorInterface -{ - /** - * Generates a fragment URI for a given controller. - * - * @param bool $absolute Whether to generate an absolute URL or not - * @param bool $strict Whether to allow non-scalar attributes or not - * @param bool $sign Whether to sign the URL or not - */ - public function generate(ControllerReference $controller, Request $request = null, bool $absolute = false, bool $strict = true, bool $sign = true): string; -} diff --git a/lib/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php b/lib/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php deleted file mode 100644 index 446ce2d9d..000000000 --- a/lib/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php +++ /dev/null @@ -1,104 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Fragment; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Controller\ControllerReference; -use Symfony\Component\HttpKernel\UriSigner; -use Twig\Environment; - -/** - * Implements the Hinclude rendering strategy. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class HIncludeFragmentRenderer extends RoutableFragmentRenderer -{ - private $globalDefaultTemplate; - private $signer; - private $twig; - private $charset; - - /** - * @param string $globalDefaultTemplate The global default content (it can be a template name or the content) - */ - public function __construct(Environment $twig = null, UriSigner $signer = null, string $globalDefaultTemplate = null, string $charset = 'utf-8') - { - $this->twig = $twig; - $this->globalDefaultTemplate = $globalDefaultTemplate; - $this->signer = $signer; - $this->charset = $charset; - } - - /** - * Checks if a templating engine has been set. - * - * @return bool - */ - public function hasTemplating() - { - return null !== $this->twig; - } - - /** - * {@inheritdoc} - * - * Additional available options: - * - * * default: The default content (it can be a template name or the content) - * * id: An optional hx:include tag id attribute - * * attributes: An optional array of hx:include tag attributes - */ - public function render($uri, Request $request, array $options = []) - { - if ($uri instanceof ControllerReference) { - $uri = (new FragmentUriGenerator($this->fragmentPath, $this->signer))->generate($uri, $request); - } - - // We need to replace ampersands in the URI with the encoded form in order to return valid html/xml content. - $uri = str_replace('&', '&amp;', $uri); - - $template = $options['default'] ?? $this->globalDefaultTemplate; - if (null !== $this->twig && $template && $this->twig->getLoader()->exists($template)) { - $content = $this->twig->render($template); - } else { - $content = $template; - } - - $attributes = isset($options['attributes']) && \is_array($options['attributes']) ? $options['attributes'] : []; - if (isset($options['id']) && $options['id']) { - $attributes['id'] = $options['id']; - } - $renderedAttributes = ''; - if (\count($attributes) > 0) { - $flags = \ENT_QUOTES | \ENT_SUBSTITUTE; - foreach ($attributes as $attribute => $value) { - $renderedAttributes .= sprintf( - ' %s="%s"', - htmlspecialchars($attribute, $flags, $this->charset, false), - htmlspecialchars($value, $flags, $this->charset, false) - ); - } - } - - return new Response(sprintf('<hx:include src="%s"%s>%s</hx:include>', $uri, $renderedAttributes, $content)); - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'hinclude'; - } -} diff --git a/lib/symfony/http-kernel/Fragment/InlineFragmentRenderer.php b/lib/symfony/http-kernel/Fragment/InlineFragmentRenderer.php deleted file mode 100644 index ea45fdcb3..000000000 --- a/lib/symfony/http-kernel/Fragment/InlineFragmentRenderer.php +++ /dev/null @@ -1,145 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Fragment; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Controller\ControllerReference; -use Symfony\Component\HttpKernel\Event\ExceptionEvent; -use Symfony\Component\HttpKernel\HttpCache\SubRequestHandler; -use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; - -/** - * Implements the inline rendering strategy where the Request is rendered by the current HTTP kernel. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class InlineFragmentRenderer extends RoutableFragmentRenderer -{ - private $kernel; - private $dispatcher; - - public function __construct(HttpKernelInterface $kernel, EventDispatcherInterface $dispatcher = null) - { - $this->kernel = $kernel; - $this->dispatcher = $dispatcher; - } - - /** - * {@inheritdoc} - * - * Additional available options: - * - * * alt: an alternative URI to render in case of an error - */ - public function render($uri, Request $request, array $options = []) - { - $reference = null; - if ($uri instanceof ControllerReference) { - $reference = $uri; - - // Remove attributes from the generated URI because if not, the Symfony - // routing system will use them to populate the Request attributes. We don't - // want that as we want to preserve objects (so we manually set Request attributes - // below instead) - $attributes = $reference->attributes; - $reference->attributes = []; - - // The request format and locale might have been overridden by the user - foreach (['_format', '_locale'] as $key) { - if (isset($attributes[$key])) { - $reference->attributes[$key] = $attributes[$key]; - } - } - - $uri = $this->generateFragmentUri($uri, $request, false, false); - - $reference->attributes = array_merge($attributes, $reference->attributes); - } - - $subRequest = $this->createSubRequest($uri, $request); - - // override Request attributes as they can be objects (which are not supported by the generated URI) - if (null !== $reference) { - $subRequest->attributes->add($reference->attributes); - } - - $level = ob_get_level(); - try { - return SubRequestHandler::handle($this->kernel, $subRequest, HttpKernelInterface::SUB_REQUEST, false); - } catch (\Exception $e) { - // we dispatch the exception event to trigger the logging - // the response that comes back is ignored - if (isset($options['ignore_errors']) && $options['ignore_errors'] && $this->dispatcher) { - $event = new ExceptionEvent($this->kernel, $request, HttpKernelInterface::SUB_REQUEST, $e); - - $this->dispatcher->dispatch($event, KernelEvents::EXCEPTION); - } - - // let's clean up the output buffers that were created by the sub-request - Response::closeOutputBuffers($level, false); - - if (isset($options['alt'])) { - $alt = $options['alt']; - unset($options['alt']); - - return $this->render($alt, $request, $options); - } - - if (!isset($options['ignore_errors']) || !$options['ignore_errors']) { - throw $e; - } - - return new Response(); - } - } - - protected function createSubRequest(string $uri, Request $request) - { - $cookies = $request->cookies->all(); - $server = $request->server->all(); - - unset($server['HTTP_IF_MODIFIED_SINCE']); - unset($server['HTTP_IF_NONE_MATCH']); - - $subRequest = Request::create($uri, 'get', [], $cookies, [], $server); - if ($request->headers->has('Surrogate-Capability')) { - $subRequest->headers->set('Surrogate-Capability', $request->headers->get('Surrogate-Capability')); - } - - static $setSession; - - if (null === $setSession) { - $setSession = \Closure::bind(static function ($subRequest, $request) { $subRequest->session = $request->session; }, null, Request::class); - } - $setSession($subRequest, $request); - - if ($request->get('_format')) { - $subRequest->attributes->set('_format', $request->get('_format')); - } - if ($request->getDefaultLocale() !== $request->getLocale()) { - $subRequest->setLocale($request->getLocale()); - } - - return $subRequest; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'inline'; - } -} diff --git a/lib/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php b/lib/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php deleted file mode 100644 index e922ffb64..000000000 --- a/lib/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Fragment; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ControllerReference; -use Symfony\Component\HttpKernel\EventListener\FragmentListener; - -/** - * Adds the possibility to generate a fragment URI for a given Controller. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -abstract class RoutableFragmentRenderer implements FragmentRendererInterface -{ - /** - * @internal - */ - protected $fragmentPath = '/_fragment'; - - /** - * Sets the fragment path that triggers the fragment listener. - * - * @see FragmentListener - */ - public function setFragmentPath(string $path) - { - $this->fragmentPath = $path; - } - - /** - * Generates a fragment URI for a given controller. - * - * @param bool $absolute Whether to generate an absolute URL or not - * @param bool $strict Whether to allow non-scalar attributes or not - * - * @return string - */ - protected function generateFragmentUri(ControllerReference $reference, Request $request, bool $absolute = false, bool $strict = true) - { - return (new FragmentUriGenerator($this->fragmentPath))->generate($reference, $request, $absolute, $strict, false); - } -} diff --git a/lib/symfony/http-kernel/Fragment/SsiFragmentRenderer.php b/lib/symfony/http-kernel/Fragment/SsiFragmentRenderer.php deleted file mode 100644 index 45e7122f0..000000000 --- a/lib/symfony/http-kernel/Fragment/SsiFragmentRenderer.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Fragment; - -/** - * Implements the SSI rendering strategy. - * - * @author Sebastian Krebs <krebs.seb@gmail.com> - */ -class SsiFragmentRenderer extends AbstractSurrogateFragmentRenderer -{ - /** - * {@inheritdoc} - */ - public function getName() - { - return 'ssi'; - } -} diff --git a/lib/symfony/http-kernel/HttpCache/AbstractSurrogate.php b/lib/symfony/http-kernel/HttpCache/AbstractSurrogate.php deleted file mode 100644 index f2d809e8d..000000000 --- a/lib/symfony/http-kernel/HttpCache/AbstractSurrogate.php +++ /dev/null @@ -1,136 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\HttpCache; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\HttpKernelInterface; - -/** - * Abstract class implementing Surrogate capabilities to Request and Response instances. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Robin Chalas <robin.chalas@gmail.com> - */ -abstract class AbstractSurrogate implements SurrogateInterface -{ - protected $contentTypes; - protected $phpEscapeMap = [ - ['<?', '<%', '<s', '<S'], - ['<?php echo "<?"; ?>', '<?php echo "<%"; ?>', '<?php echo "<s"; ?>', '<?php echo "<S"; ?>'], - ]; - - /** - * @param array $contentTypes An array of content-type that should be parsed for Surrogate information - * (default: text/html, text/xml, application/xhtml+xml, and application/xml) - */ - public function __construct(array $contentTypes = ['text/html', 'text/xml', 'application/xhtml+xml', 'application/xml']) - { - $this->contentTypes = $contentTypes; - } - - /** - * Returns a new cache strategy instance. - * - * @return ResponseCacheStrategyInterface - */ - public function createCacheStrategy() - { - return new ResponseCacheStrategy(); - } - - /** - * {@inheritdoc} - */ - public function hasSurrogateCapability(Request $request) - { - if (null === $value = $request->headers->get('Surrogate-Capability')) { - return false; - } - - return str_contains($value, sprintf('%s/1.0', strtoupper($this->getName()))); - } - - /** - * {@inheritdoc} - */ - public function addSurrogateCapability(Request $request) - { - $current = $request->headers->get('Surrogate-Capability'); - $new = sprintf('symfony="%s/1.0"', strtoupper($this->getName())); - - $request->headers->set('Surrogate-Capability', $current ? $current.', '.$new : $new); - } - - /** - * {@inheritdoc} - */ - public function needsParsing(Response $response) - { - if (!$control = $response->headers->get('Surrogate-Control')) { - return false; - } - - $pattern = sprintf('#content="[^"]*%s/1.0[^"]*"#', strtoupper($this->getName())); - - return (bool) preg_match($pattern, $control); - } - - /** - * {@inheritdoc} - */ - public function handle(HttpCache $cache, string $uri, string $alt, bool $ignoreErrors) - { - $subRequest = Request::create($uri, Request::METHOD_GET, [], $cache->getRequest()->cookies->all(), [], $cache->getRequest()->server->all()); - - try { - $response = $cache->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true); - - if (!$response->isSuccessful() && Response::HTTP_NOT_MODIFIED !== $response->getStatusCode()) { - throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %d).', $subRequest->getUri(), $response->getStatusCode())); - } - - return $response->getContent(); - } catch (\Exception $e) { - if ($alt) { - return $this->handle($cache, $alt, '', $ignoreErrors); - } - - if (!$ignoreErrors) { - throw $e; - } - } - - return ''; - } - - /** - * Remove the Surrogate from the Surrogate-Control header. - */ - protected function removeFromControl(Response $response) - { - if (!$response->headers->has('Surrogate-Control')) { - return; - } - - $value = $response->headers->get('Surrogate-Control'); - $upperName = strtoupper($this->getName()); - - if (sprintf('content="%s/1.0"', $upperName) == $value) { - $response->headers->remove('Surrogate-Control'); - } elseif (preg_match(sprintf('#,\s*content="%s/1.0"#', $upperName), $value)) { - $response->headers->set('Surrogate-Control', preg_replace(sprintf('#,\s*content="%s/1.0"#', $upperName), '', $value)); - } elseif (preg_match(sprintf('#content="%s/1.0",\s*#', $upperName), $value)) { - $response->headers->set('Surrogate-Control', preg_replace(sprintf('#content="%s/1.0",\s*#', $upperName), '', $value)); - } - } -} diff --git a/lib/symfony/http-kernel/HttpCache/Esi.php b/lib/symfony/http-kernel/HttpCache/Esi.php deleted file mode 100644 index cd6a00a10..000000000 --- a/lib/symfony/http-kernel/HttpCache/Esi.php +++ /dev/null @@ -1,117 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\HttpCache; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -/** - * Esi implements the ESI capabilities to Request and Response instances. - * - * For more information, read the following W3C notes: - * - * * ESI Language Specification 1.0 (http://www.w3.org/TR/esi-lang) - * - * * Edge Architecture Specification (http://www.w3.org/TR/edge-arch) - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Esi extends AbstractSurrogate -{ - public function getName() - { - return 'esi'; - } - - /** - * {@inheritdoc} - */ - public function addSurrogateControl(Response $response) - { - if (str_contains($response->getContent(), '<esi:include')) { - $response->headers->set('Surrogate-Control', 'content="ESI/1.0"'); - } - } - - /** - * {@inheritdoc} - */ - public function renderIncludeTag(string $uri, string $alt = null, bool $ignoreErrors = true, string $comment = '') - { - $html = sprintf('<esi:include src="%s"%s%s />', - $uri, - $ignoreErrors ? ' onerror="continue"' : '', - $alt ? sprintf(' alt="%s"', $alt) : '' - ); - - if (!empty($comment)) { - return sprintf("<esi:comment text=\"%s\" />\n%s", $comment, $html); - } - - return $html; - } - - /** - * {@inheritdoc} - */ - public function process(Request $request, Response $response) - { - $type = $response->headers->get('Content-Type'); - if (empty($type)) { - $type = 'text/html'; - } - - $parts = explode(';', $type); - if (!\in_array($parts[0], $this->contentTypes)) { - return $response; - } - - // we don't use a proper XML parser here as we can have ESI tags in a plain text response - $content = $response->getContent(); - $content = preg_replace('#<esi\:remove>.*?</esi\:remove>#s', '', $content); - $content = preg_replace('#<esi\:comment[^>]+>#s', '', $content); - - $chunks = preg_split('#<esi\:include\s+(.*?)\s*(?:/|</esi\:include)>#', $content, -1, \PREG_SPLIT_DELIM_CAPTURE); - $chunks[0] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[0]); - - $i = 1; - while (isset($chunks[$i])) { - $options = []; - preg_match_all('/(src|onerror|alt)="([^"]*?)"/', $chunks[$i], $matches, \PREG_SET_ORDER); - foreach ($matches as $set) { - $options[$set[1]] = $set[2]; - } - - if (!isset($options['src'])) { - throw new \RuntimeException('Unable to process an ESI tag without a "src" attribute.'); - } - - $chunks[$i] = sprintf('<?php echo $this->surrogate->handle($this, %s, %s, %s) ?>'."\n", - var_export($options['src'], true), - var_export($options['alt'] ?? '', true), - isset($options['onerror']) && 'continue' === $options['onerror'] ? 'true' : 'false' - ); - ++$i; - $chunks[$i] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[$i]); - ++$i; - } - $content = implode('', $chunks); - - $response->setContent($content); - $response->headers->set('X-Body-Eval', 'ESI'); - - // remove ESI/1.0 from the Surrogate-Control header - $this->removeFromControl($response); - - return $response; - } -} diff --git a/lib/symfony/http-kernel/HttpCache/HttpCache.php b/lib/symfony/http-kernel/HttpCache/HttpCache.php deleted file mode 100644 index 28be364c1..000000000 --- a/lib/symfony/http-kernel/HttpCache/HttpCache.php +++ /dev/null @@ -1,737 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/* - * This code is partially based on the Rack-Cache library by Ryan Tomayko, - * which is released under the MIT license. - * (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801) - */ - -namespace Symfony\Component\HttpKernel\HttpCache; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Component\HttpKernel\TerminableInterface; - -/** - * Cache provides HTTP caching. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class HttpCache implements HttpKernelInterface, TerminableInterface -{ - private $kernel; - private $store; - private $request; - private $surrogate; - private $surrogateCacheStrategy; - private $options = []; - private $traces = []; - - /** - * Constructor. - * - * The available options are: - * - * * debug If true, exceptions are thrown when things go wrong. Otherwise, the cache - * will try to carry on and deliver a meaningful response. - * - * * trace_level May be one of 'none', 'short' and 'full'. For 'short', a concise trace of the - * main request will be added as an HTTP header. 'full' will add traces for all - * requests (including ESI subrequests). (default: 'full' if in debug; 'none' otherwise) - * - * * trace_header Header name to use for traces. (default: X-Symfony-Cache) - * - * * default_ttl The number of seconds that a cache entry should be considered - * fresh when no explicit freshness information is provided in - * a response. Explicit Cache-Control or Expires headers - * override this value. (default: 0) - * - * * private_headers Set of request headers that trigger "private" cache-control behavior - * on responses that don't explicitly state whether the response is - * public or private via a Cache-Control directive. (default: Authorization and Cookie) - * - * * allow_reload Specifies whether the client can force a cache reload by including a - * Cache-Control "no-cache" directive in the request. Set it to ``true`` - * for compliance with RFC 2616. (default: false) - * - * * allow_revalidate Specifies whether the client can force a cache revalidate by including - * a Cache-Control "max-age=0" directive in the request. Set it to ``true`` - * for compliance with RFC 2616. (default: false) - * - * * stale_while_revalidate Specifies the default number of seconds (the granularity is the second as the - * Response TTL precision is a second) during which the cache can immediately return - * a stale response while it revalidates it in the background (default: 2). - * This setting is overridden by the stale-while-revalidate HTTP Cache-Control - * extension (see RFC 5861). - * - * * stale_if_error Specifies the default number of seconds (the granularity is the second) during which - * the cache can serve a stale response when an error is encountered (default: 60). - * This setting is overridden by the stale-if-error HTTP Cache-Control extension - * (see RFC 5861). - */ - public function __construct(HttpKernelInterface $kernel, StoreInterface $store, SurrogateInterface $surrogate = null, array $options = []) - { - $this->store = $store; - $this->kernel = $kernel; - $this->surrogate = $surrogate; - - // needed in case there is a fatal error because the backend is too slow to respond - register_shutdown_function([$this->store, 'cleanup']); - - $this->options = array_merge([ - 'debug' => false, - 'default_ttl' => 0, - 'private_headers' => ['Authorization', 'Cookie'], - 'allow_reload' => false, - 'allow_revalidate' => false, - 'stale_while_revalidate' => 2, - 'stale_if_error' => 60, - 'trace_level' => 'none', - 'trace_header' => 'X-Symfony-Cache', - ], $options); - - if (!isset($options['trace_level'])) { - $this->options['trace_level'] = $this->options['debug'] ? 'full' : 'none'; - } - } - - /** - * Gets the current store. - * - * @return StoreInterface - */ - public function getStore() - { - return $this->store; - } - - /** - * Returns an array of events that took place during processing of the last request. - * - * @return array - */ - public function getTraces() - { - return $this->traces; - } - - private function addTraces(Response $response) - { - $traceString = null; - - if ('full' === $this->options['trace_level']) { - $traceString = $this->getLog(); - } - - if ('short' === $this->options['trace_level'] && $masterId = array_key_first($this->traces)) { - $traceString = implode('/', $this->traces[$masterId]); - } - - if (null !== $traceString) { - $response->headers->add([$this->options['trace_header'] => $traceString]); - } - } - - /** - * Returns a log message for the events of the last request processing. - * - * @return string - */ - public function getLog() - { - $log = []; - foreach ($this->traces as $request => $traces) { - $log[] = sprintf('%s: %s', $request, implode(', ', $traces)); - } - - return implode('; ', $log); - } - - /** - * Gets the Request instance associated with the main request. - * - * @return Request - */ - public function getRequest() - { - return $this->request; - } - - /** - * Gets the Kernel instance. - * - * @return HttpKernelInterface - */ - public function getKernel() - { - return $this->kernel; - } - - /** - * Gets the Surrogate instance. - * - * @return SurrogateInterface - * - * @throws \LogicException - */ - public function getSurrogate() - { - return $this->surrogate; - } - - /** - * {@inheritdoc} - */ - public function handle(Request $request, int $type = HttpKernelInterface::MAIN_REQUEST, bool $catch = true) - { - // FIXME: catch exceptions and implement a 500 error page here? -> in Varnish, there is a built-in error page mechanism - if (HttpKernelInterface::MAIN_REQUEST === $type) { - $this->traces = []; - // Keep a clone of the original request for surrogates so they can access it. - // We must clone here to get a separate instance because the application will modify the request during - // the application flow (we know it always does because we do ourselves by setting REMOTE_ADDR to 127.0.0.1 - // and adding the X-Forwarded-For header, see HttpCache::forward()). - $this->request = clone $request; - if (null !== $this->surrogate) { - $this->surrogateCacheStrategy = $this->surrogate->createCacheStrategy(); - } - } - - $this->traces[$this->getTraceKey($request)] = []; - - if (!$request->isMethodSafe()) { - $response = $this->invalidate($request, $catch); - } elseif ($request->headers->has('expect') || !$request->isMethodCacheable()) { - $response = $this->pass($request, $catch); - } elseif ($this->options['allow_reload'] && $request->isNoCache()) { - /* - If allow_reload is configured and the client requests "Cache-Control: no-cache", - reload the cache by fetching a fresh response and caching it (if possible). - */ - $this->record($request, 'reload'); - $response = $this->fetch($request, $catch); - } else { - $response = $this->lookup($request, $catch); - } - - $this->restoreResponseBody($request, $response); - - if (HttpKernelInterface::MAIN_REQUEST === $type) { - $this->addTraces($response); - } - - if (null !== $this->surrogate) { - if (HttpKernelInterface::MAIN_REQUEST === $type) { - $this->surrogateCacheStrategy->update($response); - } else { - $this->surrogateCacheStrategy->add($response); - } - } - - $response->prepare($request); - - $response->isNotModified($request); - - return $response; - } - - /** - * {@inheritdoc} - */ - public function terminate(Request $request, Response $response) - { - if ($this->getKernel() instanceof TerminableInterface) { - $this->getKernel()->terminate($request, $response); - } - } - - /** - * Forwards the Request to the backend without storing the Response in the cache. - * - * @param bool $catch Whether to process exceptions - * - * @return Response - */ - protected function pass(Request $request, bool $catch = false) - { - $this->record($request, 'pass'); - - return $this->forward($request, $catch); - } - - /** - * Invalidates non-safe methods (like POST, PUT, and DELETE). - * - * @param bool $catch Whether to process exceptions - * - * @return Response - * - * @throws \Exception - * - * @see RFC2616 13.10 - */ - protected function invalidate(Request $request, bool $catch = false) - { - $response = $this->pass($request, $catch); - - // invalidate only when the response is successful - if ($response->isSuccessful() || $response->isRedirect()) { - try { - $this->store->invalidate($request); - - // As per the RFC, invalidate Location and Content-Location URLs if present - foreach (['Location', 'Content-Location'] as $header) { - if ($uri = $response->headers->get($header)) { - $subRequest = Request::create($uri, 'get', [], [], [], $request->server->all()); - - $this->store->invalidate($subRequest); - } - } - - $this->record($request, 'invalidate'); - } catch (\Exception $e) { - $this->record($request, 'invalidate-failed'); - - if ($this->options['debug']) { - throw $e; - } - } - } - - return $response; - } - - /** - * Lookups a Response from the cache for the given Request. - * - * When a matching cache entry is found and is fresh, it uses it as the - * response without forwarding any request to the backend. When a matching - * cache entry is found but is stale, it attempts to "validate" the entry with - * the backend using conditional GET. When no matching cache entry is found, - * it triggers "miss" processing. - * - * @param bool $catch Whether to process exceptions - * - * @return Response - * - * @throws \Exception - */ - protected function lookup(Request $request, bool $catch = false) - { - try { - $entry = $this->store->lookup($request); - } catch (\Exception $e) { - $this->record($request, 'lookup-failed'); - - if ($this->options['debug']) { - throw $e; - } - - return $this->pass($request, $catch); - } - - if (null === $entry) { - $this->record($request, 'miss'); - - return $this->fetch($request, $catch); - } - - if (!$this->isFreshEnough($request, $entry)) { - $this->record($request, 'stale'); - - return $this->validate($request, $entry, $catch); - } - - if ($entry->headers->hasCacheControlDirective('no-cache')) { - return $this->validate($request, $entry, $catch); - } - - $this->record($request, 'fresh'); - - $entry->headers->set('Age', $entry->getAge()); - - return $entry; - } - - /** - * Validates that a cache entry is fresh. - * - * The original request is used as a template for a conditional - * GET request with the backend. - * - * @param bool $catch Whether to process exceptions - * - * @return Response - */ - protected function validate(Request $request, Response $entry, bool $catch = false) - { - $subRequest = clone $request; - - // send no head requests because we want content - if ('HEAD' === $request->getMethod()) { - $subRequest->setMethod('GET'); - } - - // add our cached last-modified validator - if ($entry->headers->has('Last-Modified')) { - $subRequest->headers->set('If-Modified-Since', $entry->headers->get('Last-Modified')); - } - - // Add our cached etag validator to the environment. - // We keep the etags from the client to handle the case when the client - // has a different private valid entry which is not cached here. - $cachedEtags = $entry->getEtag() ? [$entry->getEtag()] : []; - $requestEtags = $request->getETags(); - if ($etags = array_unique(array_merge($cachedEtags, $requestEtags))) { - $subRequest->headers->set('If-None-Match', implode(', ', $etags)); - } - - $response = $this->forward($subRequest, $catch, $entry); - - if (304 == $response->getStatusCode()) { - $this->record($request, 'valid'); - - // return the response and not the cache entry if the response is valid but not cached - $etag = $response->getEtag(); - if ($etag && \in_array($etag, $requestEtags) && !\in_array($etag, $cachedEtags)) { - return $response; - } - - $entry = clone $entry; - $entry->headers->remove('Date'); - - foreach (['Date', 'Expires', 'Cache-Control', 'ETag', 'Last-Modified'] as $name) { - if ($response->headers->has($name)) { - $entry->headers->set($name, $response->headers->get($name)); - } - } - - $response = $entry; - } else { - $this->record($request, 'invalid'); - } - - if ($response->isCacheable()) { - $this->store($request, $response); - } - - return $response; - } - - /** - * Unconditionally fetches a fresh response from the backend and - * stores it in the cache if is cacheable. - * - * @param bool $catch Whether to process exceptions - * - * @return Response - */ - protected function fetch(Request $request, bool $catch = false) - { - $subRequest = clone $request; - - // send no head requests because we want content - if ('HEAD' === $request->getMethod()) { - $subRequest->setMethod('GET'); - } - - // avoid that the backend sends no content - $subRequest->headers->remove('If-Modified-Since'); - $subRequest->headers->remove('If-None-Match'); - - $response = $this->forward($subRequest, $catch); - - if ($response->isCacheable()) { - $this->store($request, $response); - } - - return $response; - } - - /** - * Forwards the Request to the backend and returns the Response. - * - * All backend requests (cache passes, fetches, cache validations) - * run through this method. - * - * @param bool $catch Whether to catch exceptions or not - * @param Response|null $entry A Response instance (the stale entry if present, null otherwise) - * - * @return Response - */ - protected function forward(Request $request, bool $catch = false, Response $entry = null) - { - if ($this->surrogate) { - $this->surrogate->addSurrogateCapability($request); - } - - // always a "master" request (as the real master request can be in cache) - $response = SubRequestHandler::handle($this->kernel, $request, HttpKernelInterface::MAIN_REQUEST, $catch); - - /* - * Support stale-if-error given on Responses or as a config option. - * RFC 7234 summarizes in Section 4.2.4 (but also mentions with the individual - * Cache-Control directives) that - * - * A cache MUST NOT generate a stale response if it is prohibited by an - * explicit in-protocol directive (e.g., by a "no-store" or "no-cache" - * cache directive, a "must-revalidate" cache-response-directive, or an - * applicable "s-maxage" or "proxy-revalidate" cache-response-directive; - * see Section 5.2.2). - * - * https://tools.ietf.org/html/rfc7234#section-4.2.4 - * - * We deviate from this in one detail, namely that we *do* serve entries in the - * stale-if-error case even if they have a `s-maxage` Cache-Control directive. - */ - if (null !== $entry - && \in_array($response->getStatusCode(), [500, 502, 503, 504]) - && !$entry->headers->hasCacheControlDirective('no-cache') - && !$entry->mustRevalidate() - ) { - if (null === $age = $entry->headers->getCacheControlDirective('stale-if-error')) { - $age = $this->options['stale_if_error']; - } - - /* - * stale-if-error gives the (extra) time that the Response may be used *after* it has become stale. - * So we compare the time the $entry has been sitting in the cache already with the - * time it was fresh plus the allowed grace period. - */ - if ($entry->getAge() <= $entry->getMaxAge() + $age) { - $this->record($request, 'stale-if-error'); - - return $entry; - } - } - - /* - RFC 7231 Sect. 7.1.1.2 says that a server that does not have a reasonably accurate - clock MUST NOT send a "Date" header, although it MUST send one in most other cases - except for 1xx or 5xx responses where it MAY do so. - - Anyway, a client that received a message without a "Date" header MUST add it. - */ - if (!$response->headers->has('Date')) { - $response->setDate(\DateTime::createFromFormat('U', time())); - } - - $this->processResponseBody($request, $response); - - if ($this->isPrivateRequest($request) && !$response->headers->hasCacheControlDirective('public')) { - $response->setPrivate(); - } elseif ($this->options['default_ttl'] > 0 && null === $response->getTtl() && !$response->headers->getCacheControlDirective('must-revalidate')) { - $response->setTtl($this->options['default_ttl']); - } - - return $response; - } - - /** - * Checks whether the cache entry is "fresh enough" to satisfy the Request. - * - * @return bool - */ - protected function isFreshEnough(Request $request, Response $entry) - { - if (!$entry->isFresh()) { - return $this->lock($request, $entry); - } - - if ($this->options['allow_revalidate'] && null !== $maxAge = $request->headers->getCacheControlDirective('max-age')) { - return $maxAge > 0 && $maxAge >= $entry->getAge(); - } - - return true; - } - - /** - * Locks a Request during the call to the backend. - * - * @return bool true if the cache entry can be returned even if it is staled, false otherwise - */ - protected function lock(Request $request, Response $entry) - { - // try to acquire a lock to call the backend - $lock = $this->store->lock($request); - - if (true === $lock) { - // we have the lock, call the backend - return false; - } - - // there is already another process calling the backend - - // May we serve a stale response? - if ($this->mayServeStaleWhileRevalidate($entry)) { - $this->record($request, 'stale-while-revalidate'); - - return true; - } - - // wait for the lock to be released - if ($this->waitForLock($request)) { - // replace the current entry with the fresh one - $new = $this->lookup($request); - $entry->headers = $new->headers; - $entry->setContent($new->getContent()); - $entry->setStatusCode($new->getStatusCode()); - $entry->setProtocolVersion($new->getProtocolVersion()); - foreach ($new->headers->getCookies() as $cookie) { - $entry->headers->setCookie($cookie); - } - } else { - // backend is slow as hell, send a 503 response (to avoid the dog pile effect) - $entry->setStatusCode(503); - $entry->setContent('503 Service Unavailable'); - $entry->headers->set('Retry-After', 10); - } - - return true; - } - - /** - * Writes the Response to the cache. - * - * @throws \Exception - */ - protected function store(Request $request, Response $response) - { - try { - $this->store->write($request, $response); - - $this->record($request, 'store'); - - $response->headers->set('Age', $response->getAge()); - } catch (\Exception $e) { - $this->record($request, 'store-failed'); - - if ($this->options['debug']) { - throw $e; - } - } - - // now that the response is cached, release the lock - $this->store->unlock($request); - } - - /** - * Restores the Response body. - */ - private function restoreResponseBody(Request $request, Response $response) - { - if ($response->headers->has('X-Body-Eval')) { - ob_start(); - - if ($response->headers->has('X-Body-File')) { - include $response->headers->get('X-Body-File'); - } else { - eval('; ?>'.$response->getContent().'<?php ;'); - } - - $response->setContent(ob_get_clean()); - $response->headers->remove('X-Body-Eval'); - if (!$response->headers->has('Transfer-Encoding')) { - $response->headers->set('Content-Length', \strlen($response->getContent())); - } - } elseif ($response->headers->has('X-Body-File')) { - // Response does not include possibly dynamic content (ESI, SSI), so we need - // not handle the content for HEAD requests - if (!$request->isMethod('HEAD')) { - $response->setContent(file_get_contents($response->headers->get('X-Body-File'))); - } - } else { - return; - } - - $response->headers->remove('X-Body-File'); - } - - protected function processResponseBody(Request $request, Response $response) - { - if (null !== $this->surrogate && $this->surrogate->needsParsing($response)) { - $this->surrogate->process($request, $response); - } - } - - /** - * Checks if the Request includes authorization or other sensitive information - * that should cause the Response to be considered private by default. - */ - private function isPrivateRequest(Request $request): bool - { - foreach ($this->options['private_headers'] as $key) { - $key = strtolower(str_replace('HTTP_', '', $key)); - - if ('cookie' === $key) { - if (\count($request->cookies->all())) { - return true; - } - } elseif ($request->headers->has($key)) { - return true; - } - } - - return false; - } - - /** - * Records that an event took place. - */ - private function record(Request $request, string $event) - { - $this->traces[$this->getTraceKey($request)][] = $event; - } - - /** - * Calculates the key we use in the "trace" array for a given request. - */ - private function getTraceKey(Request $request): string - { - $path = $request->getPathInfo(); - if ($qs = $request->getQueryString()) { - $path .= '?'.$qs; - } - - return $request->getMethod().' '.$path; - } - - /** - * Checks whether the given (cached) response may be served as "stale" when a revalidation - * is currently in progress. - */ - private function mayServeStaleWhileRevalidate(Response $entry): bool - { - $timeout = $entry->headers->getCacheControlDirective('stale-while-revalidate'); - - if (null === $timeout) { - $timeout = $this->options['stale_while_revalidate']; - } - - return abs($entry->getTtl() ?? 0) < $timeout; - } - - /** - * Waits for the store to release a locked entry. - */ - private function waitForLock(Request $request): bool - { - $wait = 0; - while ($this->store->isLocked($request) && $wait < 100) { - usleep(50000); - ++$wait; - } - - return $wait < 100; - } -} diff --git a/lib/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php b/lib/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php deleted file mode 100644 index cf8682257..000000000 --- a/lib/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php +++ /dev/null @@ -1,234 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\HttpCache; - -use Symfony\Component\HttpFoundation\Response; - -/** - * ResponseCacheStrategy knows how to compute the Response cache HTTP header - * based on the different response cache headers. - * - * This implementation changes the main response TTL to the smallest TTL received - * or force validation if one of the surrogates has validation cache strategy. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class ResponseCacheStrategy implements ResponseCacheStrategyInterface -{ - /** - * Cache-Control headers that are sent to the final response if they appear in ANY of the responses. - */ - private const OVERRIDE_DIRECTIVES = ['private', 'no-cache', 'no-store', 'no-transform', 'must-revalidate', 'proxy-revalidate']; - - /** - * Cache-Control headers that are sent to the final response if they appear in ALL of the responses. - */ - private const INHERIT_DIRECTIVES = ['public', 'immutable']; - - private $embeddedResponses = 0; - private $isNotCacheableResponseEmbedded = false; - private $age = 0; - private $flagDirectives = [ - 'no-cache' => null, - 'no-store' => null, - 'no-transform' => null, - 'must-revalidate' => null, - 'proxy-revalidate' => null, - 'public' => null, - 'private' => null, - 'immutable' => null, - ]; - private $ageDirectives = [ - 'max-age' => null, - 's-maxage' => null, - 'expires' => null, - ]; - - /** - * {@inheritdoc} - */ - public function add(Response $response) - { - ++$this->embeddedResponses; - - foreach (self::OVERRIDE_DIRECTIVES as $directive) { - if ($response->headers->hasCacheControlDirective($directive)) { - $this->flagDirectives[$directive] = true; - } - } - - foreach (self::INHERIT_DIRECTIVES as $directive) { - if (false !== $this->flagDirectives[$directive]) { - $this->flagDirectives[$directive] = $response->headers->hasCacheControlDirective($directive); - } - } - - $age = $response->getAge(); - $this->age = max($this->age, $age); - - if ($this->willMakeFinalResponseUncacheable($response)) { - $this->isNotCacheableResponseEmbedded = true; - - return; - } - - $isHeuristicallyCacheable = $response->headers->hasCacheControlDirective('public'); - $maxAge = $response->headers->hasCacheControlDirective('max-age') ? (int) $response->headers->getCacheControlDirective('max-age') : null; - $this->storeRelativeAgeDirective('max-age', $maxAge, $age, $isHeuristicallyCacheable); - $sharedMaxAge = $response->headers->hasCacheControlDirective('s-maxage') ? (int) $response->headers->getCacheControlDirective('s-maxage') : $maxAge; - $this->storeRelativeAgeDirective('s-maxage', $sharedMaxAge, $age, $isHeuristicallyCacheable); - - $expires = $response->getExpires(); - $expires = null !== $expires ? (int) $expires->format('U') - (int) $response->getDate()->format('U') : null; - $this->storeRelativeAgeDirective('expires', $expires >= 0 ? $expires : null, 0, $isHeuristicallyCacheable); - } - - /** - * {@inheritdoc} - */ - public function update(Response $response) - { - // if we have no embedded Response, do nothing - if (0 === $this->embeddedResponses) { - return; - } - - // Remove validation related headers of the master response, - // because some of the response content comes from at least - // one embedded response (which likely has a different caching strategy). - $response->setEtag(null); - $response->setLastModified(null); - - $this->add($response); - - $response->headers->set('Age', $this->age); - - if ($this->isNotCacheableResponseEmbedded) { - if ($this->flagDirectives['no-store']) { - $response->headers->set('Cache-Control', 'no-cache, no-store, must-revalidate'); - } else { - $response->headers->set('Cache-Control', 'no-cache, must-revalidate'); - } - - return; - } - - $flags = array_filter($this->flagDirectives); - - if (isset($flags['must-revalidate'])) { - $flags['no-cache'] = true; - } - - $response->headers->set('Cache-Control', implode(', ', array_keys($flags))); - - $maxAge = null; - - if (is_numeric($this->ageDirectives['max-age'])) { - $maxAge = $this->ageDirectives['max-age'] + $this->age; - $response->headers->addCacheControlDirective('max-age', $maxAge); - } - - if (is_numeric($this->ageDirectives['s-maxage'])) { - $sMaxage = $this->ageDirectives['s-maxage'] + $this->age; - - if ($maxAge !== $sMaxage) { - $response->headers->addCacheControlDirective('s-maxage', $sMaxage); - } - } - - if (is_numeric($this->ageDirectives['expires'])) { - $date = clone $response->getDate(); - $date->modify('+'.($this->ageDirectives['expires'] + $this->age).' seconds'); - $response->setExpires($date); - } - } - - /** - * RFC2616, Section 13.4. - * - * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.4 - */ - private function willMakeFinalResponseUncacheable(Response $response): bool - { - // RFC2616: A response received with a status code of 200, 203, 300, 301 or 410 - // MAY be stored by a cache […] unless a cache-control directive prohibits caching. - if ($response->headers->hasCacheControlDirective('no-cache') - || $response->headers->getCacheControlDirective('no-store') - ) { - return true; - } - - // Last-Modified and Etag headers cannot be merged, they render the response uncacheable - // by default (except if the response also has max-age etc.). - if (\in_array($response->getStatusCode(), [200, 203, 300, 301, 410]) - && null === $response->getLastModified() - && null === $response->getEtag() - ) { - return false; - } - - // RFC2616: A response received with any other status code (e.g. status codes 302 and 307) - // MUST NOT be returned in a reply to a subsequent request unless there are - // cache-control directives or another header(s) that explicitly allow it. - $cacheControl = ['max-age', 's-maxage', 'must-revalidate', 'proxy-revalidate', 'public', 'private']; - foreach ($cacheControl as $key) { - if ($response->headers->hasCacheControlDirective($key)) { - return false; - } - } - - if ($response->headers->has('Expires')) { - return false; - } - - return true; - } - - /** - * Store lowest max-age/s-maxage/expires for the final response. - * - * The response might have been stored in cache a while ago. To keep things comparable, - * we have to subtract the age so that the value is normalized for an age of 0. - * - * If the value is lower than the currently stored value, we update the value, to keep a rolling - * minimal value of each instruction. - * - * If the value is NULL and the isHeuristicallyCacheable parameter is false, the directive will - * not be set on the final response. In this case, not all responses had the directive set and no - * value can be found that satisfies the requirements of all responses. The directive will be dropped - * from the final response. - * - * If the isHeuristicallyCacheable parameter is true, however, the current response has been marked - * as cacheable in a public (shared) cache, but did not provide an explicit lifetime that would serve - * as an upper bound. In this case, we can proceed and possibly keep the directive on the final response. - */ - private function storeRelativeAgeDirective(string $directive, ?int $value, int $age, bool $isHeuristicallyCacheable) - { - if (null === $value) { - if ($isHeuristicallyCacheable) { - /* - * See https://datatracker.ietf.org/doc/html/rfc7234#section-4.2.2 - * This particular response does not require maximum lifetime; heuristics might be applied. - * Other responses, however, might have more stringent requirements on maximum lifetime. - * So, return early here so that the final response can have the more limiting value set. - */ - return; - } - $this->ageDirectives[$directive] = false; - } - - if (false !== $this->ageDirectives[$directive]) { - $value -= $age; - $this->ageDirectives[$directive] = null !== $this->ageDirectives[$directive] ? min($this->ageDirectives[$directive], $value) : $value; - } - } -} diff --git a/lib/symfony/http-kernel/HttpCache/ResponseCacheStrategyInterface.php b/lib/symfony/http-kernel/HttpCache/ResponseCacheStrategyInterface.php deleted file mode 100644 index e282299ae..000000000 --- a/lib/symfony/http-kernel/HttpCache/ResponseCacheStrategyInterface.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * This code is partially based on the Rack-Cache library by Ryan Tomayko, - * which is released under the MIT license. - * (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801) - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\HttpCache; - -use Symfony\Component\HttpFoundation\Response; - -/** - * ResponseCacheStrategyInterface implementations know how to compute the - * Response cache HTTP header based on the different response cache headers. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface ResponseCacheStrategyInterface -{ - /** - * Adds a Response. - */ - public function add(Response $response); - - /** - * Updates the Response HTTP headers based on the embedded Responses. - */ - public function update(Response $response); -} diff --git a/lib/symfony/http-kernel/HttpCache/Ssi.php b/lib/symfony/http-kernel/HttpCache/Ssi.php deleted file mode 100644 index f114e05cf..000000000 --- a/lib/symfony/http-kernel/HttpCache/Ssi.php +++ /dev/null @@ -1,100 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\HttpCache; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -/** - * Ssi implements the SSI capabilities to Request and Response instances. - * - * @author Sebastian Krebs <krebs.seb@gmail.com> - */ -class Ssi extends AbstractSurrogate -{ - /** - * {@inheritdoc} - */ - public function getName() - { - return 'ssi'; - } - - /** - * {@inheritdoc} - */ - public function addSurrogateControl(Response $response) - { - if (str_contains($response->getContent(), '<!--#include')) { - $response->headers->set('Surrogate-Control', 'content="SSI/1.0"'); - } - } - - /** - * {@inheritdoc} - */ - public function renderIncludeTag(string $uri, string $alt = null, bool $ignoreErrors = true, string $comment = '') - { - return sprintf('<!--#include virtual="%s" -->', $uri); - } - - /** - * {@inheritdoc} - */ - public function process(Request $request, Response $response) - { - $type = $response->headers->get('Content-Type'); - if (empty($type)) { - $type = 'text/html'; - } - - $parts = explode(';', $type); - if (!\in_array($parts[0], $this->contentTypes)) { - return $response; - } - - // we don't use a proper XML parser here as we can have SSI tags in a plain text response - $content = $response->getContent(); - - $chunks = preg_split('#<!--\#include\s+(.*?)\s*-->#', $content, -1, \PREG_SPLIT_DELIM_CAPTURE); - $chunks[0] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[0]); - - $i = 1; - while (isset($chunks[$i])) { - $options = []; - preg_match_all('/(virtual)="([^"]*?)"/', $chunks[$i], $matches, \PREG_SET_ORDER); - foreach ($matches as $set) { - $options[$set[1]] = $set[2]; - } - - if (!isset($options['virtual'])) { - throw new \RuntimeException('Unable to process an SSI tag without a "virtual" attribute.'); - } - - $chunks[$i] = sprintf('<?php echo $this->surrogate->handle($this, %s, \'\', false) ?>'."\n", - var_export($options['virtual'], true) - ); - ++$i; - $chunks[$i] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[$i]); - ++$i; - } - $content = implode('', $chunks); - - $response->setContent($content); - $response->headers->set('X-Body-Eval', 'SSI'); - - // remove SSI/1.0 from the Surrogate-Control header - $this->removeFromControl($response); - - return $response; - } -} diff --git a/lib/symfony/http-kernel/HttpCache/Store.php b/lib/symfony/http-kernel/HttpCache/Store.php deleted file mode 100644 index 8087e0cb1..000000000 --- a/lib/symfony/http-kernel/HttpCache/Store.php +++ /dev/null @@ -1,489 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * This code is partially based on the Rack-Cache library by Ryan Tomayko, - * which is released under the MIT license. - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\HttpCache; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -/** - * Store implements all the logic for storing cache metadata (Request and Response headers). - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Store implements StoreInterface -{ - protected $root; - /** @var \SplObjectStorage<Request, string> */ - private $keyCache; - /** @var array<string, resource> */ - private $locks = []; - private $options; - - /** - * Constructor. - * - * The available options are: - * - * * private_headers Set of response headers that should not be stored - * when a response is cached. (default: Set-Cookie) - * - * @throws \RuntimeException - */ - public function __construct(string $root, array $options = []) - { - $this->root = $root; - if (!is_dir($this->root) && !@mkdir($this->root, 0777, true) && !is_dir($this->root)) { - throw new \RuntimeException(sprintf('Unable to create the store directory (%s).', $this->root)); - } - $this->keyCache = new \SplObjectStorage(); - $this->options = array_merge([ - 'private_headers' => ['Set-Cookie'], - ], $options); - } - - /** - * Cleanups storage. - */ - public function cleanup() - { - // unlock everything - foreach ($this->locks as $lock) { - flock($lock, \LOCK_UN); - fclose($lock); - } - - $this->locks = []; - } - - /** - * Tries to lock the cache for a given Request, without blocking. - * - * @return bool|string true if the lock is acquired, the path to the current lock otherwise - */ - public function lock(Request $request) - { - $key = $this->getCacheKey($request); - - if (!isset($this->locks[$key])) { - $path = $this->getPath($key); - if (!is_dir(\dirname($path)) && false === @mkdir(\dirname($path), 0777, true) && !is_dir(\dirname($path))) { - return $path; - } - $h = fopen($path, 'c'); - if (!flock($h, \LOCK_EX | \LOCK_NB)) { - fclose($h); - - return $path; - } - - $this->locks[$key] = $h; - } - - return true; - } - - /** - * Releases the lock for the given Request. - * - * @return bool False if the lock file does not exist or cannot be unlocked, true otherwise - */ - public function unlock(Request $request) - { - $key = $this->getCacheKey($request); - - if (isset($this->locks[$key])) { - flock($this->locks[$key], \LOCK_UN); - fclose($this->locks[$key]); - unset($this->locks[$key]); - - return true; - } - - return false; - } - - public function isLocked(Request $request) - { - $key = $this->getCacheKey($request); - - if (isset($this->locks[$key])) { - return true; // shortcut if lock held by this process - } - - if (!is_file($path = $this->getPath($key))) { - return false; - } - - $h = fopen($path, 'r'); - flock($h, \LOCK_EX | \LOCK_NB, $wouldBlock); - flock($h, \LOCK_UN); // release the lock we just acquired - fclose($h); - - return (bool) $wouldBlock; - } - - /** - * Locates a cached Response for the Request provided. - * - * @return Response|null - */ - public function lookup(Request $request) - { - $key = $this->getCacheKey($request); - - if (!$entries = $this->getMetadata($key)) { - return null; - } - - // find a cached entry that matches the request. - $match = null; - foreach ($entries as $entry) { - if ($this->requestsMatch(isset($entry[1]['vary'][0]) ? implode(', ', $entry[1]['vary']) : '', $request->headers->all(), $entry[0])) { - $match = $entry; - - break; - } - } - - if (null === $match) { - return null; - } - - $headers = $match[1]; - if (file_exists($path = $this->getPath($headers['x-content-digest'][0]))) { - return $this->restoreResponse($headers, $path); - } - - // TODO the metaStore referenced an entity that doesn't exist in - // the entityStore. We definitely want to return nil but we should - // also purge the entry from the meta-store when this is detected. - return null; - } - - /** - * Writes a cache entry to the store for the given Request and Response. - * - * Existing entries are read and any that match the response are removed. This - * method calls write with the new list of cache entries. - * - * @return string - * - * @throws \RuntimeException - */ - public function write(Request $request, Response $response) - { - $key = $this->getCacheKey($request); - $storedEnv = $this->persistRequest($request); - - if ($response->headers->has('X-Body-File')) { - // Assume the response came from disk, but at least perform some safeguard checks - if (!$response->headers->has('X-Content-Digest')) { - throw new \RuntimeException('A restored response must have the X-Content-Digest header.'); - } - - $digest = $response->headers->get('X-Content-Digest'); - if ($this->getPath($digest) !== $response->headers->get('X-Body-File')) { - throw new \RuntimeException('X-Body-File and X-Content-Digest do not match.'); - } - // Everything seems ok, omit writing content to disk - } else { - $digest = $this->generateContentDigest($response); - $response->headers->set('X-Content-Digest', $digest); - - if (!$this->save($digest, $response->getContent(), false)) { - throw new \RuntimeException('Unable to store the entity.'); - } - - if (!$response->headers->has('Transfer-Encoding')) { - $response->headers->set('Content-Length', \strlen($response->getContent())); - } - } - - // read existing cache entries, remove non-varying, and add this one to the list - $entries = []; - $vary = $response->headers->get('vary'); - foreach ($this->getMetadata($key) as $entry) { - if (!isset($entry[1]['vary'][0])) { - $entry[1]['vary'] = ['']; - } - - if ($entry[1]['vary'][0] != $vary || !$this->requestsMatch($vary ?? '', $entry[0], $storedEnv)) { - $entries[] = $entry; - } - } - - $headers = $this->persistResponse($response); - unset($headers['age']); - - foreach ($this->options['private_headers'] as $h) { - unset($headers[strtolower($h)]); - } - - array_unshift($entries, [$storedEnv, $headers]); - - if (!$this->save($key, serialize($entries))) { - throw new \RuntimeException('Unable to store the metadata.'); - } - - return $key; - } - - /** - * Returns content digest for $response. - * - * @return string - */ - protected function generateContentDigest(Response $response) - { - return 'en'.hash('sha256', $response->getContent()); - } - - /** - * Invalidates all cache entries that match the request. - * - * @throws \RuntimeException - */ - public function invalidate(Request $request) - { - $modified = false; - $key = $this->getCacheKey($request); - - $entries = []; - foreach ($this->getMetadata($key) as $entry) { - $response = $this->restoreResponse($entry[1]); - if ($response->isFresh()) { - $response->expire(); - $modified = true; - $entries[] = [$entry[0], $this->persistResponse($response)]; - } else { - $entries[] = $entry; - } - } - - if ($modified && !$this->save($key, serialize($entries))) { - throw new \RuntimeException('Unable to store the metadata.'); - } - } - - /** - * Determines whether two Request HTTP header sets are non-varying based on - * the vary response header value provided. - * - * @param string|null $vary A Response vary header - * @param array $env1 A Request HTTP header array - * @param array $env2 A Request HTTP header array - */ - private function requestsMatch(?string $vary, array $env1, array $env2): bool - { - if (empty($vary)) { - return true; - } - - foreach (preg_split('/[\s,]+/', $vary) as $header) { - $key = str_replace('_', '-', strtolower($header)); - $v1 = $env1[$key] ?? null; - $v2 = $env2[$key] ?? null; - if ($v1 !== $v2) { - return false; - } - } - - return true; - } - - /** - * Gets all data associated with the given key. - * - * Use this method only if you know what you are doing. - */ - private function getMetadata(string $key): array - { - if (!$entries = $this->load($key)) { - return []; - } - - return unserialize($entries) ?: []; - } - - /** - * Purges data for the given URL. - * - * This method purges both the HTTP and the HTTPS version of the cache entry. - * - * @return bool true if the URL exists with either HTTP or HTTPS scheme and has been purged, false otherwise - */ - public function purge(string $url) - { - $http = preg_replace('#^https:#', 'http:', $url); - $https = preg_replace('#^http:#', 'https:', $url); - - $purgedHttp = $this->doPurge($http); - $purgedHttps = $this->doPurge($https); - - return $purgedHttp || $purgedHttps; - } - - /** - * Purges data for the given URL. - */ - private function doPurge(string $url): bool - { - $key = $this->getCacheKey(Request::create($url)); - if (isset($this->locks[$key])) { - flock($this->locks[$key], \LOCK_UN); - fclose($this->locks[$key]); - unset($this->locks[$key]); - } - - if (is_file($path = $this->getPath($key))) { - unlink($path); - - return true; - } - - return false; - } - - /** - * Loads data for the given key. - */ - private function load(string $key): ?string - { - $path = $this->getPath($key); - - return is_file($path) && false !== ($contents = @file_get_contents($path)) ? $contents : null; - } - - /** - * Save data for the given key. - */ - private function save(string $key, string $data, bool $overwrite = true): bool - { - $path = $this->getPath($key); - - if (!$overwrite && file_exists($path)) { - return true; - } - - if (isset($this->locks[$key])) { - $fp = $this->locks[$key]; - @ftruncate($fp, 0); - @fseek($fp, 0); - $len = @fwrite($fp, $data); - if (\strlen($data) !== $len) { - @ftruncate($fp, 0); - - return false; - } - } else { - if (!is_dir(\dirname($path)) && false === @mkdir(\dirname($path), 0777, true) && !is_dir(\dirname($path))) { - return false; - } - - $tmpFile = tempnam(\dirname($path), basename($path)); - if (false === $fp = @fopen($tmpFile, 'w')) { - @unlink($tmpFile); - - return false; - } - @fwrite($fp, $data); - @fclose($fp); - - if ($data != file_get_contents($tmpFile)) { - @unlink($tmpFile); - - return false; - } - - if (false === @rename($tmpFile, $path)) { - @unlink($tmpFile); - - return false; - } - } - - @chmod($path, 0666 & ~umask()); - - return true; - } - - public function getPath(string $key) - { - return $this->root.\DIRECTORY_SEPARATOR.substr($key, 0, 2).\DIRECTORY_SEPARATOR.substr($key, 2, 2).\DIRECTORY_SEPARATOR.substr($key, 4, 2).\DIRECTORY_SEPARATOR.substr($key, 6); - } - - /** - * Generates a cache key for the given Request. - * - * This method should return a key that must only depend on a - * normalized version of the request URI. - * - * If the same URI can have more than one representation, based on some - * headers, use a Vary header to indicate them, and each representation will - * be stored independently under the same cache key. - * - * @return string - */ - protected function generateCacheKey(Request $request) - { - return 'md'.hash('sha256', $request->getUri()); - } - - /** - * Returns a cache key for the given Request. - */ - private function getCacheKey(Request $request): string - { - if (isset($this->keyCache[$request])) { - return $this->keyCache[$request]; - } - - return $this->keyCache[$request] = $this->generateCacheKey($request); - } - - /** - * Persists the Request HTTP headers. - */ - private function persistRequest(Request $request): array - { - return $request->headers->all(); - } - - /** - * Persists the Response HTTP headers. - */ - private function persistResponse(Response $response): array - { - $headers = $response->headers->all(); - $headers['X-Status'] = [$response->getStatusCode()]; - - return $headers; - } - - /** - * Restores a Response from the HTTP headers and body. - */ - private function restoreResponse(array $headers, string $path = null): Response - { - $status = $headers['X-Status'][0]; - unset($headers['X-Status']); - - if (null !== $path) { - $headers['X-Body-File'] = [$path]; - } - - return new Response($path, $status, $headers); - } -} diff --git a/lib/symfony/http-kernel/HttpCache/StoreInterface.php b/lib/symfony/http-kernel/HttpCache/StoreInterface.php deleted file mode 100644 index 3d07ef3fc..000000000 --- a/lib/symfony/http-kernel/HttpCache/StoreInterface.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * This code is partially based on the Rack-Cache library by Ryan Tomayko, - * which is released under the MIT license. - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\HttpCache; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -/** - * Interface implemented by HTTP cache stores. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface StoreInterface -{ - /** - * Locates a cached Response for the Request provided. - * - * @return Response|null - */ - public function lookup(Request $request); - - /** - * Writes a cache entry to the store for the given Request and Response. - * - * Existing entries are read and any that match the response are removed. This - * method calls write with the new list of cache entries. - * - * @return string The key under which the response is stored - */ - public function write(Request $request, Response $response); - - /** - * Invalidates all cache entries that match the request. - */ - public function invalidate(Request $request); - - /** - * Locks the cache for a given Request. - * - * @return bool|string true if the lock is acquired, the path to the current lock otherwise - */ - public function lock(Request $request); - - /** - * Releases the lock for the given Request. - * - * @return bool False if the lock file does not exist or cannot be unlocked, true otherwise - */ - public function unlock(Request $request); - - /** - * Returns whether or not a lock exists. - * - * @return bool true if lock exists, false otherwise - */ - public function isLocked(Request $request); - - /** - * Purges data for the given URL. - * - * @return bool true if the URL exists and has been purged, false otherwise - */ - public function purge(string $url); - - /** - * Cleanups storage. - */ - public function cleanup(); -} diff --git a/lib/symfony/http-kernel/HttpCache/SubRequestHandler.php b/lib/symfony/http-kernel/HttpCache/SubRequestHandler.php deleted file mode 100644 index 253071f07..000000000 --- a/lib/symfony/http-kernel/HttpCache/SubRequestHandler.php +++ /dev/null @@ -1,92 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\HttpCache; - -use Symfony\Component\HttpFoundation\IpUtils; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\HttpKernelInterface; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -class SubRequestHandler -{ - public static function handle(HttpKernelInterface $kernel, Request $request, int $type, bool $catch): Response - { - // save global state related to trusted headers and proxies - $trustedProxies = Request::getTrustedProxies(); - $trustedHeaderSet = Request::getTrustedHeaderSet(); - - // remove untrusted values - $remoteAddr = $request->server->get('REMOTE_ADDR'); - if (!$remoteAddr || !IpUtils::checkIp($remoteAddr, $trustedProxies)) { - $trustedHeaders = [ - 'FORWARDED' => $trustedHeaderSet & Request::HEADER_FORWARDED, - 'X_FORWARDED_FOR' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_FOR, - 'X_FORWARDED_HOST' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_HOST, - 'X_FORWARDED_PROTO' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_PROTO, - 'X_FORWARDED_PORT' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_PORT, - 'X_FORWARDED_PREFIX' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_PREFIX, - ]; - foreach (array_filter($trustedHeaders) as $name => $key) { - $request->headers->remove($name); - $request->server->remove('HTTP_'.$name); - } - } - - // compute trusted values, taking any trusted proxies into account - $trustedIps = []; - $trustedValues = []; - foreach (array_reverse($request->getClientIps()) as $ip) { - $trustedIps[] = $ip; - $trustedValues[] = sprintf('for="%s"', $ip); - } - if ($ip !== $remoteAddr) { - $trustedIps[] = $remoteAddr; - $trustedValues[] = sprintf('for="%s"', $remoteAddr); - } - - // set trusted values, reusing as much as possible the global trusted settings - if (Request::HEADER_FORWARDED & $trustedHeaderSet) { - $trustedValues[0] .= sprintf(';host="%s";proto=%s', $request->getHttpHost(), $request->getScheme()); - $request->headers->set('Forwarded', $v = implode(', ', $trustedValues)); - $request->server->set('HTTP_FORWARDED', $v); - } - if (Request::HEADER_X_FORWARDED_FOR & $trustedHeaderSet) { - $request->headers->set('X-Forwarded-For', $v = implode(', ', $trustedIps)); - $request->server->set('HTTP_X_FORWARDED_FOR', $v); - } elseif (!(Request::HEADER_FORWARDED & $trustedHeaderSet)) { - Request::setTrustedProxies($trustedProxies, $trustedHeaderSet | Request::HEADER_X_FORWARDED_FOR); - $request->headers->set('X-Forwarded-For', $v = implode(', ', $trustedIps)); - $request->server->set('HTTP_X_FORWARDED_FOR', $v); - } - - // fix the client IP address by setting it to 127.0.0.1, - // which is the core responsibility of this method - $request->server->set('REMOTE_ADDR', '127.0.0.1'); - - // ensure 127.0.0.1 is set as trusted proxy - if (!IpUtils::checkIp('127.0.0.1', $trustedProxies)) { - Request::setTrustedProxies(array_merge($trustedProxies, ['127.0.0.1']), Request::getTrustedHeaderSet()); - } - - try { - return $kernel->handle($request, $type, $catch); - } finally { - // restore global state - Request::setTrustedProxies($trustedProxies, $trustedHeaderSet); - } - } -} diff --git a/lib/symfony/http-kernel/HttpCache/SurrogateInterface.php b/lib/symfony/http-kernel/HttpCache/SurrogateInterface.php deleted file mode 100644 index 3f3c74a97..000000000 --- a/lib/symfony/http-kernel/HttpCache/SurrogateInterface.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\HttpCache; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -interface SurrogateInterface -{ - /** - * Returns surrogate name. - * - * @return string - */ - public function getName(); - - /** - * Returns a new cache strategy instance. - * - * @return ResponseCacheStrategyInterface - */ - public function createCacheStrategy(); - - /** - * Checks that at least one surrogate has Surrogate capability. - * - * @return bool - */ - public function hasSurrogateCapability(Request $request); - - /** - * Adds Surrogate-capability to the given Request. - */ - public function addSurrogateCapability(Request $request); - - /** - * Adds HTTP headers to specify that the Response needs to be parsed for Surrogate. - * - * This method only adds an Surrogate HTTP header if the Response has some Surrogate tags. - */ - public function addSurrogateControl(Response $response); - - /** - * Checks that the Response needs to be parsed for Surrogate tags. - * - * @return bool - */ - public function needsParsing(Response $response); - - /** - * Renders a Surrogate tag. - * - * @param string $alt An alternate URI - * @param string $comment A comment to add as an esi:include tag - * - * @return string - */ - public function renderIncludeTag(string $uri, string $alt = null, bool $ignoreErrors = true, string $comment = ''); - - /** - * Replaces a Response Surrogate tags with the included resource content. - * - * @return Response - */ - public function process(Request $request, Response $response); - - /** - * Handles a Surrogate from the cache. - * - * @param string $alt An alternative URI - * - * @return string - * - * @throws \RuntimeException - * @throws \Exception - */ - public function handle(HttpCache $cache, string $uri, string $alt, bool $ignoreErrors); -} diff --git a/lib/symfony/http-kernel/HttpClientKernel.php b/lib/symfony/http-kernel/HttpClientKernel.php deleted file mode 100644 index 58ca82e5a..000000000 --- a/lib/symfony/http-kernel/HttpClientKernel.php +++ /dev/null @@ -1,112 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel; - -use Symfony\Component\HttpClient\HttpClient; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpFoundation\ResponseHeaderBag; -use Symfony\Component\Mime\Part\AbstractPart; -use Symfony\Component\Mime\Part\DataPart; -use Symfony\Component\Mime\Part\Multipart\FormDataPart; -use Symfony\Component\Mime\Part\TextPart; -use Symfony\Contracts\HttpClient\HttpClientInterface; - -// Help opcache.preload discover always-needed symbols -class_exists(ResponseHeaderBag::class); - -/** - * An implementation of a Symfony HTTP kernel using a "real" HTTP client. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class HttpClientKernel implements HttpKernelInterface -{ - private $client; - - public function __construct(HttpClientInterface $client = null) - { - if (null === $client && !class_exists(HttpClient::class)) { - throw new \LogicException(sprintf('You cannot use "%s" as the HttpClient component is not installed. Try running "composer require symfony/http-client".', __CLASS__)); - } - - $this->client = $client ?? HttpClient::create(); - } - - public function handle(Request $request, int $type = HttpKernelInterface::MAIN_REQUEST, bool $catch = true): Response - { - $headers = $this->getHeaders($request); - $body = ''; - if (null !== $part = $this->getBody($request)) { - $headers = array_merge($headers, $part->getPreparedHeaders()->toArray()); - $body = $part->bodyToIterable(); - } - $response = $this->client->request($request->getMethod(), $request->getUri(), [ - 'headers' => $headers, - 'body' => $body, - ] + $request->attributes->get('http_client_options', [])); - - $response = new Response($response->getContent(!$catch), $response->getStatusCode(), $response->getHeaders(!$catch)); - - $response->headers->remove('X-Body-File'); - $response->headers->remove('X-Body-Eval'); - $response->headers->remove('X-Content-Digest'); - - $response->headers = new class($response->headers->all()) extends ResponseHeaderBag { - protected function computeCacheControlValue(): string - { - return $this->getCacheControlHeader(); // preserve the original value - } - }; - - return $response; - } - - private function getBody(Request $request): ?AbstractPart - { - if (\in_array($request->getMethod(), ['GET', 'HEAD'])) { - return null; - } - - if (!class_exists(AbstractPart::class)) { - throw new \LogicException('You cannot pass non-empty bodies as the Mime component is not installed. Try running "composer require symfony/mime".'); - } - - if ($content = $request->getContent()) { - return new TextPart($content, 'utf-8', 'plain', '8bit'); - } - - $fields = $request->request->all(); - foreach ($request->files->all() as $name => $file) { - $fields[$name] = DataPart::fromPath($file->getPathname(), $file->getClientOriginalName(), $file->getClientMimeType()); - } - - return new FormDataPart($fields); - } - - private function getHeaders(Request $request): array - { - $headers = []; - foreach ($request->headers as $key => $value) { - $headers[$key] = $value; - } - $cookies = []; - foreach ($request->cookies->all() as $name => $value) { - $cookies[] = $name.'='.$value; - } - if ($cookies) { - $headers['cookie'] = implode('; ', $cookies); - } - - return $headers; - } -} diff --git a/lib/symfony/http-kernel/HttpKernel.php b/lib/symfony/http-kernel/HttpKernel.php deleted file mode 100644 index 38102e252..000000000 --- a/lib/symfony/http-kernel/HttpKernel.php +++ /dev/null @@ -1,299 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel; - -use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver; -use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface; -use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; -use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent; -use Symfony\Component\HttpKernel\Event\ControllerEvent; -use Symfony\Component\HttpKernel\Event\ExceptionEvent; -use Symfony\Component\HttpKernel\Event\FinishRequestEvent; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Symfony\Component\HttpKernel\Event\TerminateEvent; -use Symfony\Component\HttpKernel\Event\ViewEvent; -use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; -use Symfony\Component\HttpKernel\Exception\ControllerDoesNotReturnResponseException; -use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; - -// Help opcache.preload discover always-needed symbols -class_exists(ControllerArgumentsEvent::class); -class_exists(ControllerEvent::class); -class_exists(ExceptionEvent::class); -class_exists(FinishRequestEvent::class); -class_exists(RequestEvent::class); -class_exists(ResponseEvent::class); -class_exists(TerminateEvent::class); -class_exists(ViewEvent::class); -class_exists(KernelEvents::class); - -/** - * HttpKernel notifies events to convert a Request object to a Response one. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class HttpKernel implements HttpKernelInterface, TerminableInterface -{ - protected $dispatcher; - protected $resolver; - protected $requestStack; - private $argumentResolver; - - public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver, RequestStack $requestStack = null, ArgumentResolverInterface $argumentResolver = null) - { - $this->dispatcher = $dispatcher; - $this->resolver = $resolver; - $this->requestStack = $requestStack ?? new RequestStack(); - $this->argumentResolver = $argumentResolver ?? new ArgumentResolver(); - } - - /** - * {@inheritdoc} - */ - public function handle(Request $request, int $type = HttpKernelInterface::MAIN_REQUEST, bool $catch = true) - { - $request->headers->set('X-Php-Ob-Level', (string) ob_get_level()); - - $this->requestStack->push($request); - try { - return $this->handleRaw($request, $type); - } catch (\Exception $e) { - if ($e instanceof RequestExceptionInterface) { - $e = new BadRequestHttpException($e->getMessage(), $e); - } - if (false === $catch) { - $this->finishRequest($request, $type); - - throw $e; - } - - return $this->handleThrowable($e, $request, $type); - } finally { - $this->requestStack->pop(); - } - } - - /** - * {@inheritdoc} - */ - public function terminate(Request $request, Response $response) - { - $this->dispatcher->dispatch(new TerminateEvent($this, $request, $response), KernelEvents::TERMINATE); - } - - /** - * @internal - */ - public function terminateWithException(\Throwable $exception, Request $request = null) - { - if (!$request = $request ?: $this->requestStack->getMainRequest()) { - throw $exception; - } - - if ($pop = $request !== $this->requestStack->getMainRequest()) { - $this->requestStack->push($request); - } - - try { - $response = $this->handleThrowable($exception, $request, self::MAIN_REQUEST); - } finally { - if ($pop) { - $this->requestStack->pop(); - } - } - - $response->sendHeaders(); - $response->sendContent(); - - $this->terminate($request, $response); - } - - /** - * Handles a request to convert it to a response. - * - * Exceptions are not caught. - * - * @throws \LogicException If one of the listener does not behave as expected - * @throws NotFoundHttpException When controller cannot be found - */ - private function handleRaw(Request $request, int $type = self::MAIN_REQUEST): Response - { - // request - $event = new RequestEvent($this, $request, $type); - $this->dispatcher->dispatch($event, KernelEvents::REQUEST); - - if ($event->hasResponse()) { - return $this->filterResponse($event->getResponse(), $request, $type); - } - - // load controller - if (false === $controller = $this->resolver->getController($request)) { - throw new NotFoundHttpException(sprintf('Unable to find the controller for path "%s". The route is wrongly configured.', $request->getPathInfo())); - } - - $event = new ControllerEvent($this, $controller, $request, $type); - $this->dispatcher->dispatch($event, KernelEvents::CONTROLLER); - $controller = $event->getController(); - - // controller arguments - $arguments = $this->argumentResolver->getArguments($request, $controller); - - $event = new ControllerArgumentsEvent($this, $controller, $arguments, $request, $type); - $this->dispatcher->dispatch($event, KernelEvents::CONTROLLER_ARGUMENTS); - $controller = $event->getController(); - $arguments = $event->getArguments(); - - // call controller - $response = $controller(...$arguments); - - // view - if (!$response instanceof Response) { - $event = new ViewEvent($this, $request, $type, $response); - $this->dispatcher->dispatch($event, KernelEvents::VIEW); - - if ($event->hasResponse()) { - $response = $event->getResponse(); - } else { - $msg = sprintf('The controller must return a "Symfony\Component\HttpFoundation\Response" object but it returned %s.', $this->varToString($response)); - - // the user may have forgotten to return something - if (null === $response) { - $msg .= ' Did you forget to add a return statement somewhere in your controller?'; - } - - throw new ControllerDoesNotReturnResponseException($msg, $controller, __FILE__, __LINE__ - 17); - } - } - - return $this->filterResponse($response, $request, $type); - } - - /** - * Filters a response object. - * - * @throws \RuntimeException if the passed object is not a Response instance - */ - private function filterResponse(Response $response, Request $request, int $type): Response - { - $event = new ResponseEvent($this, $request, $type, $response); - - $this->dispatcher->dispatch($event, KernelEvents::RESPONSE); - - $this->finishRequest($request, $type); - - return $event->getResponse(); - } - - /** - * Publishes the finish request event, then pop the request from the stack. - * - * Note that the order of the operations is important here, otherwise - * operations such as {@link RequestStack::getParentRequest()} can lead to - * weird results. - */ - private function finishRequest(Request $request, int $type) - { - $this->dispatcher->dispatch(new FinishRequestEvent($this, $request, $type), KernelEvents::FINISH_REQUEST); - } - - /** - * Handles a throwable by trying to convert it to a Response. - * - * @throws \Exception - */ - private function handleThrowable(\Throwable $e, Request $request, int $type): Response - { - $event = new ExceptionEvent($this, $request, $type, $e); - $this->dispatcher->dispatch($event, KernelEvents::EXCEPTION); - - // a listener might have replaced the exception - $e = $event->getThrowable(); - - if (!$event->hasResponse()) { - $this->finishRequest($request, $type); - - throw $e; - } - - $response = $event->getResponse(); - - // the developer asked for a specific status code - if (!$event->isAllowingCustomResponseCode() && !$response->isClientError() && !$response->isServerError() && !$response->isRedirect()) { - // ensure that we actually have an error response - if ($e instanceof HttpExceptionInterface) { - // keep the HTTP status code and headers - $response->setStatusCode($e->getStatusCode()); - $response->headers->add($e->getHeaders()); - } else { - $response->setStatusCode(500); - } - } - - try { - return $this->filterResponse($response, $request, $type); - } catch (\Exception $e) { - return $response; - } - } - - /** - * Returns a human-readable string for the specified variable. - */ - private function varToString($var): string - { - if (\is_object($var)) { - return sprintf('an object of type %s', \get_class($var)); - } - - if (\is_array($var)) { - $a = []; - foreach ($var as $k => $v) { - $a[] = sprintf('%s => ...', $k); - } - - return sprintf('an array ([%s])', mb_substr(implode(', ', $a), 0, 255)); - } - - if (\is_resource($var)) { - return sprintf('a resource (%s)', get_resource_type($var)); - } - - if (null === $var) { - return 'null'; - } - - if (false === $var) { - return 'a boolean value (false)'; - } - - if (true === $var) { - return 'a boolean value (true)'; - } - - if (\is_string($var)) { - return sprintf('a string ("%s%s")', mb_substr($var, 0, 255), mb_strlen($var) > 255 ? '...' : ''); - } - - if (is_numeric($var)) { - return sprintf('a number (%s)', (string) $var); - } - - return (string) $var; - } -} diff --git a/lib/symfony/http-kernel/HttpKernelBrowser.php b/lib/symfony/http-kernel/HttpKernelBrowser.php deleted file mode 100644 index 643134f1b..000000000 --- a/lib/symfony/http-kernel/HttpKernelBrowser.php +++ /dev/null @@ -1,208 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel; - -use Symfony\Component\BrowserKit\AbstractBrowser; -use Symfony\Component\BrowserKit\CookieJar; -use Symfony\Component\BrowserKit\History; -use Symfony\Component\BrowserKit\Request as DomRequest; -use Symfony\Component\BrowserKit\Response as DomResponse; -use Symfony\Component\HttpFoundation\File\UploadedFile; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -/** - * Simulates a browser and makes requests to an HttpKernel instance. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @method Request getRequest() - * @method Response getResponse() - */ -class HttpKernelBrowser extends AbstractBrowser -{ - protected $kernel; - private $catchExceptions = true; - - /** - * @param array $server The server parameters (equivalent of $_SERVER) - */ - public function __construct(HttpKernelInterface $kernel, array $server = [], History $history = null, CookieJar $cookieJar = null) - { - // These class properties must be set before calling the parent constructor, as it may depend on it. - $this->kernel = $kernel; - $this->followRedirects = false; - - parent::__construct($server, $history, $cookieJar); - } - - /** - * Sets whether to catch exceptions when the kernel is handling a request. - */ - public function catchExceptions(bool $catchExceptions) - { - $this->catchExceptions = $catchExceptions; - } - - /** - * {@inheritdoc} - * - * @param Request $request - * - * @return Response - */ - protected function doRequest(object $request) - { - $response = $this->kernel->handle($request, HttpKernelInterface::MAIN_REQUEST, $this->catchExceptions); - - if ($this->kernel instanceof TerminableInterface) { - $this->kernel->terminate($request, $response); - } - - return $response; - } - - /** - * {@inheritdoc} - * - * @param Request $request - * - * @return string - */ - protected function getScript(object $request) - { - $kernel = var_export(serialize($this->kernel), true); - $request = var_export(serialize($request), true); - - $errorReporting = error_reporting(); - - $requires = ''; - foreach (get_declared_classes() as $class) { - if (0 === strpos($class, 'ComposerAutoloaderInit')) { - $r = new \ReflectionClass($class); - $file = \dirname($r->getFileName(), 2).'/autoload.php'; - if (file_exists($file)) { - $requires .= 'require_once '.var_export($file, true).";\n"; - } - } - } - - if (!$requires) { - throw new \RuntimeException('Composer autoloader not found.'); - } - - $code = <<<EOF -<?php - -error_reporting($errorReporting); - -$requires - -\$kernel = unserialize($kernel); -\$request = unserialize($request); -EOF; - - return $code.$this->getHandleScript(); - } - - protected function getHandleScript() - { - return <<<'EOF' -$response = $kernel->handle($request); - -if ($kernel instanceof Symfony\Component\HttpKernel\TerminableInterface) { - $kernel->terminate($request, $response); -} - -echo serialize($response); -EOF; - } - - /** - * {@inheritdoc} - * - * @return Request - */ - protected function filterRequest(DomRequest $request) - { - $httpRequest = Request::create($request->getUri(), $request->getMethod(), $request->getParameters(), $request->getCookies(), $request->getFiles(), $server = $request->getServer(), $request->getContent()); - if (!isset($server['HTTP_ACCEPT'])) { - $httpRequest->headers->remove('Accept'); - } - - foreach ($this->filterFiles($httpRequest->files->all()) as $key => $value) { - $httpRequest->files->set($key, $value); - } - - return $httpRequest; - } - - /** - * Filters an array of files. - * - * This method created test instances of UploadedFile so that the move() - * method can be called on those instances. - * - * If the size of a file is greater than the allowed size (from php.ini) then - * an invalid UploadedFile is returned with an error set to UPLOAD_ERR_INI_SIZE. - * - * @see UploadedFile - * - * @return array - */ - protected function filterFiles(array $files) - { - $filtered = []; - foreach ($files as $key => $value) { - if (\is_array($value)) { - $filtered[$key] = $this->filterFiles($value); - } elseif ($value instanceof UploadedFile) { - if ($value->isValid() && $value->getSize() > UploadedFile::getMaxFilesize()) { - $filtered[$key] = new UploadedFile( - '', - $value->getClientOriginalName(), - $value->getClientMimeType(), - \UPLOAD_ERR_INI_SIZE, - true - ); - } else { - $filtered[$key] = new UploadedFile( - $value->getPathname(), - $value->getClientOriginalName(), - $value->getClientMimeType(), - $value->getError(), - true - ); - } - } - } - - return $filtered; - } - - /** - * {@inheritdoc} - * - * @param Response $response - * - * @return DomResponse - */ - protected function filterResponse(object $response) - { - // this is needed to support StreamedResponse - ob_start(); - $response->sendContent(); - $content = ob_get_clean(); - - return new DomResponse($content, $response->getStatusCode(), $response->headers->all()); - } -} diff --git a/lib/symfony/http-kernel/HttpKernelInterface.php b/lib/symfony/http-kernel/HttpKernelInterface.php deleted file mode 100644 index 0449240e7..000000000 --- a/lib/symfony/http-kernel/HttpKernelInterface.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -/** - * HttpKernelInterface handles a Request to convert it to a Response. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface HttpKernelInterface -{ - public const MAIN_REQUEST = 1; - public const SUB_REQUEST = 2; - - /** - * @deprecated since symfony/http-kernel 5.3, use MAIN_REQUEST instead. - * To ease the migration, this constant won't be removed until Symfony 7.0. - */ - public const MASTER_REQUEST = self::MAIN_REQUEST; - - /** - * Handles a Request to convert it to a Response. - * - * When $catch is true, the implementation must catch all exceptions - * and do its best to convert them to a Response instance. - * - * @param int $type The type of the request - * (one of HttpKernelInterface::MAIN_REQUEST or HttpKernelInterface::SUB_REQUEST) - * @param bool $catch Whether to catch exceptions or not - * - * @return Response - * - * @throws \Exception When an Exception occurs during processing - */ - public function handle(Request $request, int $type = self::MAIN_REQUEST, bool $catch = true); -} diff --git a/lib/symfony/http-kernel/Kernel.php b/lib/symfony/http-kernel/Kernel.php deleted file mode 100644 index b2ccc7d95..000000000 --- a/lib/symfony/http-kernel/Kernel.php +++ /dev/null @@ -1,881 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel; - -use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator; -use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; -use Symfony\Component\Config\Builder\ConfigBuilderGenerator; -use Symfony\Component\Config\ConfigCache; -use Symfony\Component\Config\Loader\DelegatingLoader; -use Symfony\Component\Config\Loader\LoaderResolver; -use Symfony\Component\Debug\DebugClassLoader as LegacyDebugClassLoader; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Compiler\PassConfig; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Dumper\PhpDumper; -use Symfony\Component\DependencyInjection\Dumper\Preloader; -use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; -use Symfony\Component\DependencyInjection\Loader\ClosureLoader; -use Symfony\Component\DependencyInjection\Loader\DirectoryLoader; -use Symfony\Component\DependencyInjection\Loader\GlobFileLoader; -use Symfony\Component\DependencyInjection\Loader\IniFileLoader; -use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; -use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; -use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; -use Symfony\Component\ErrorHandler\DebugClassLoader; -use Symfony\Component\Filesystem\Filesystem; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Bundle\BundleInterface; -use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; -use Symfony\Component\HttpKernel\Config\FileLocator; -use Symfony\Component\HttpKernel\DependencyInjection\AddAnnotatedClassesToCachePass; -use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; - -// Help opcache.preload discover always-needed symbols -class_exists(ConfigCache::class); - -/** - * The Kernel is the heart of the Symfony system. - * - * It manages an environment made of bundles. - * - * Environment names must always start with a letter and - * they must only contain letters and numbers. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -abstract class Kernel implements KernelInterface, RebootableInterface, TerminableInterface -{ - /** - * @var array<string, BundleInterface> - */ - protected $bundles = []; - - protected $container; - protected $environment; - protected $debug; - protected $booted = false; - protected $startTime; - - private $projectDir; - private $warmupDir; - private $requestStackSize = 0; - private $resetServices = false; - - /** - * @var array<string, bool> - */ - private static $freshCache = []; - - public const VERSION = '5.4.20'; - public const VERSION_ID = 50420; - public const MAJOR_VERSION = 5; - public const MINOR_VERSION = 4; - public const RELEASE_VERSION = 20; - public const EXTRA_VERSION = ''; - - public const END_OF_MAINTENANCE = '11/2024'; - public const END_OF_LIFE = '11/2025'; - - public function __construct(string $environment, bool $debug) - { - if (!$this->environment = $environment) { - throw new \InvalidArgumentException(sprintf('Invalid environment provided to "%s": the environment cannot be empty.', get_debug_type($this))); - } - - $this->debug = $debug; - } - - public function __clone() - { - $this->booted = false; - $this->container = null; - $this->requestStackSize = 0; - $this->resetServices = false; - } - - /** - * {@inheritdoc} - */ - public function boot() - { - if (true === $this->booted) { - if (!$this->requestStackSize && $this->resetServices) { - if ($this->container->has('services_resetter')) { - $this->container->get('services_resetter')->reset(); - } - $this->resetServices = false; - if ($this->debug) { - $this->startTime = microtime(true); - } - } - - return; - } - - if (null === $this->container) { - $this->preBoot(); - } - - foreach ($this->getBundles() as $bundle) { - $bundle->setContainer($this->container); - $bundle->boot(); - } - - $this->booted = true; - } - - /** - * {@inheritdoc} - */ - public function reboot(?string $warmupDir) - { - $this->shutdown(); - $this->warmupDir = $warmupDir; - $this->boot(); - } - - /** - * {@inheritdoc} - */ - public function terminate(Request $request, Response $response) - { - if (false === $this->booted) { - return; - } - - if ($this->getHttpKernel() instanceof TerminableInterface) { - $this->getHttpKernel()->terminate($request, $response); - } - } - - /** - * {@inheritdoc} - */ - public function shutdown() - { - if (false === $this->booted) { - return; - } - - $this->booted = false; - - foreach ($this->getBundles() as $bundle) { - $bundle->shutdown(); - $bundle->setContainer(null); - } - - $this->container = null; - $this->requestStackSize = 0; - $this->resetServices = false; - } - - /** - * {@inheritdoc} - */ - public function handle(Request $request, int $type = HttpKernelInterface::MAIN_REQUEST, bool $catch = true) - { - if (!$this->booted) { - $container = $this->container ?? $this->preBoot(); - - if ($container->has('http_cache')) { - return $container->get('http_cache')->handle($request, $type, $catch); - } - } - - $this->boot(); - ++$this->requestStackSize; - $this->resetServices = true; - - try { - return $this->getHttpKernel()->handle($request, $type, $catch); - } finally { - --$this->requestStackSize; - } - } - - /** - * Gets an HTTP kernel from the container. - * - * @return HttpKernelInterface - */ - protected function getHttpKernel() - { - return $this->container->get('http_kernel'); - } - - /** - * {@inheritdoc} - */ - public function getBundles() - { - return $this->bundles; - } - - /** - * {@inheritdoc} - */ - public function getBundle(string $name) - { - if (!isset($this->bundles[$name])) { - throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled. Maybe you forgot to add it in the "registerBundles()" method of your "%s.php" file?', $name, get_debug_type($this))); - } - - return $this->bundles[$name]; - } - - /** - * {@inheritdoc} - */ - public function locateResource(string $name) - { - if ('@' !== $name[0]) { - throw new \InvalidArgumentException(sprintf('A resource name must start with @ ("%s" given).', $name)); - } - - if (str_contains($name, '..')) { - throw new \RuntimeException(sprintf('File name "%s" contains invalid characters (..).', $name)); - } - - $bundleName = substr($name, 1); - $path = ''; - if (str_contains($bundleName, '/')) { - [$bundleName, $path] = explode('/', $bundleName, 2); - } - - $bundle = $this->getBundle($bundleName); - if (file_exists($file = $bundle->getPath().'/'.$path)) { - return $file; - } - - throw new \InvalidArgumentException(sprintf('Unable to find file "%s".', $name)); - } - - /** - * {@inheritdoc} - */ - public function getEnvironment() - { - return $this->environment; - } - - /** - * {@inheritdoc} - */ - public function isDebug() - { - return $this->debug; - } - - /** - * Gets the application root dir (path of the project's composer file). - * - * @return string - */ - public function getProjectDir() - { - if (null === $this->projectDir) { - $r = new \ReflectionObject($this); - - if (!is_file($dir = $r->getFileName())) { - throw new \LogicException(sprintf('Cannot auto-detect project dir for kernel of class "%s".', $r->name)); - } - - $dir = $rootDir = \dirname($dir); - while (!is_file($dir.'/composer.json')) { - if ($dir === \dirname($dir)) { - return $this->projectDir = $rootDir; - } - $dir = \dirname($dir); - } - $this->projectDir = $dir; - } - - return $this->projectDir; - } - - /** - * {@inheritdoc} - */ - public function getContainer() - { - if (!$this->container) { - throw new \LogicException('Cannot retrieve the container from a non-booted kernel.'); - } - - return $this->container; - } - - /** - * @internal - */ - public function setAnnotatedClassCache(array $annotatedClasses) - { - file_put_contents(($this->warmupDir ?: $this->getBuildDir()).'/annotations.map', sprintf('<?php return %s;', var_export($annotatedClasses, true))); - } - - /** - * {@inheritdoc} - */ - public function getStartTime() - { - return $this->debug && null !== $this->startTime ? $this->startTime : -\INF; - } - - /** - * {@inheritdoc} - */ - public function getCacheDir() - { - return $this->getProjectDir().'/var/cache/'.$this->environment; - } - - /** - * {@inheritdoc} - */ - public function getBuildDir(): string - { - // Returns $this->getCacheDir() for backward compatibility - return $this->getCacheDir(); - } - - /** - * {@inheritdoc} - */ - public function getLogDir() - { - return $this->getProjectDir().'/var/log'; - } - - /** - * {@inheritdoc} - */ - public function getCharset() - { - return 'UTF-8'; - } - - /** - * Gets the patterns defining the classes to parse and cache for annotations. - */ - public function getAnnotatedClassesToCompile(): array - { - return []; - } - - /** - * Initializes bundles. - * - * @throws \LogicException if two bundles share a common name - */ - protected function initializeBundles() - { - // init bundles - $this->bundles = []; - foreach ($this->registerBundles() as $bundle) { - $name = $bundle->getName(); - if (isset($this->bundles[$name])) { - throw new \LogicException(sprintf('Trying to register two bundles with the same name "%s".', $name)); - } - $this->bundles[$name] = $bundle; - } - } - - /** - * The extension point similar to the Bundle::build() method. - * - * Use this method to register compiler passes and manipulate the container during the building process. - */ - protected function build(ContainerBuilder $container) - { - } - - /** - * Gets the container class. - * - * @throws \InvalidArgumentException If the generated classname is invalid - * - * @return string - */ - protected function getContainerClass() - { - $class = static::class; - $class = str_contains($class, "@anonymous\0") ? get_parent_class($class).str_replace('.', '_', ContainerBuilder::hash($class)) : $class; - $class = str_replace('\\', '_', $class).ucfirst($this->environment).($this->debug ? 'Debug' : '').'Container'; - - if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $class)) { - throw new \InvalidArgumentException(sprintf('The environment "%s" contains invalid characters, it can only contain characters allowed in PHP class names.', $this->environment)); - } - - return $class; - } - - /** - * Gets the container's base class. - * - * All names except Container must be fully qualified. - * - * @return string - */ - protected function getContainerBaseClass() - { - return 'Container'; - } - - /** - * Initializes the service container. - * - * The built version of the service container is used when fresh, otherwise the - * container is built. - */ - protected function initializeContainer() - { - $class = $this->getContainerClass(); - $buildDir = $this->warmupDir ?: $this->getBuildDir(); - $cache = new ConfigCache($buildDir.'/'.$class.'.php', $this->debug); - $cachePath = $cache->getPath(); - - // Silence E_WARNING to ignore "include" failures - don't use "@" to prevent silencing fatal errors - $errorLevel = error_reporting(\E_ALL ^ \E_WARNING); - - try { - if (is_file($cachePath) && \is_object($this->container = include $cachePath) - && (!$this->debug || (self::$freshCache[$cachePath] ?? $cache->isFresh())) - ) { - self::$freshCache[$cachePath] = true; - $this->container->set('kernel', $this); - error_reporting($errorLevel); - - return; - } - } catch (\Throwable $e) { - } - - $oldContainer = \is_object($this->container) ? new \ReflectionClass($this->container) : $this->container = null; - - try { - is_dir($buildDir) ?: mkdir($buildDir, 0777, true); - - if ($lock = fopen($cachePath.'.lock', 'w')) { - if (!flock($lock, \LOCK_EX | \LOCK_NB, $wouldBlock) && !flock($lock, $wouldBlock ? \LOCK_SH : \LOCK_EX)) { - fclose($lock); - $lock = null; - } elseif (!is_file($cachePath) || !\is_object($this->container = include $cachePath)) { - $this->container = null; - } elseif (!$oldContainer || \get_class($this->container) !== $oldContainer->name) { - flock($lock, \LOCK_UN); - fclose($lock); - $this->container->set('kernel', $this); - - return; - } - } - } catch (\Throwable $e) { - } finally { - error_reporting($errorLevel); - } - - if ($collectDeprecations = $this->debug && !\defined('PHPUNIT_COMPOSER_INSTALL')) { - $collectedLogs = []; - $previousHandler = set_error_handler(function ($type, $message, $file, $line) use (&$collectedLogs, &$previousHandler) { - if (\E_USER_DEPRECATED !== $type && \E_DEPRECATED !== $type) { - return $previousHandler ? $previousHandler($type, $message, $file, $line) : false; - } - - if (isset($collectedLogs[$message])) { - ++$collectedLogs[$message]['count']; - - return null; - } - - $backtrace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 5); - // Clean the trace by removing first frames added by the error handler itself. - for ($i = 0; isset($backtrace[$i]); ++$i) { - if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { - $backtrace = \array_slice($backtrace, 1 + $i); - break; - } - } - for ($i = 0; isset($backtrace[$i]); ++$i) { - if (!isset($backtrace[$i]['file'], $backtrace[$i]['line'], $backtrace[$i]['function'])) { - continue; - } - if (!isset($backtrace[$i]['class']) && 'trigger_deprecation' === $backtrace[$i]['function']) { - $file = $backtrace[$i]['file']; - $line = $backtrace[$i]['line']; - $backtrace = \array_slice($backtrace, 1 + $i); - break; - } - } - - // Remove frames added by DebugClassLoader. - for ($i = \count($backtrace) - 2; 0 < $i; --$i) { - if (\in_array($backtrace[$i]['class'] ?? null, [DebugClassLoader::class, LegacyDebugClassLoader::class], true)) { - $backtrace = [$backtrace[$i + 1]]; - break; - } - } - - $collectedLogs[$message] = [ - 'type' => $type, - 'message' => $message, - 'file' => $file, - 'line' => $line, - 'trace' => [$backtrace[0]], - 'count' => 1, - ]; - - return null; - }); - } - - try { - $container = null; - $container = $this->buildContainer(); - $container->compile(); - } finally { - if ($collectDeprecations) { - restore_error_handler(); - - @file_put_contents($buildDir.'/'.$class.'Deprecations.log', serialize(array_values($collectedLogs))); - @file_put_contents($buildDir.'/'.$class.'Compiler.log', null !== $container ? implode("\n", $container->getCompiler()->getLog()) : ''); - } - } - - $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass()); - - if ($lock) { - flock($lock, \LOCK_UN); - fclose($lock); - } - - $this->container = require $cachePath; - $this->container->set('kernel', $this); - - if ($oldContainer && \get_class($this->container) !== $oldContainer->name) { - // Because concurrent requests might still be using them, - // old container files are not removed immediately, - // but on a next dump of the container. - static $legacyContainers = []; - $oldContainerDir = \dirname($oldContainer->getFileName()); - $legacyContainers[$oldContainerDir.'.legacy'] = true; - foreach (glob(\dirname($oldContainerDir).\DIRECTORY_SEPARATOR.'*.legacy', \GLOB_NOSORT) as $legacyContainer) { - if (!isset($legacyContainers[$legacyContainer]) && @unlink($legacyContainer)) { - (new Filesystem())->remove(substr($legacyContainer, 0, -7)); - } - } - - touch($oldContainerDir.'.legacy'); - } - - $preload = $this instanceof WarmableInterface ? (array) $this->warmUp($this->container->getParameter('kernel.cache_dir')) : []; - - if ($this->container->has('cache_warmer')) { - $preload = array_merge($preload, (array) $this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir'))); - } - - if ($preload && method_exists(Preloader::class, 'append') && file_exists($preloadFile = $buildDir.'/'.$class.'.preload.php')) { - Preloader::append($preloadFile, $preload); - } - } - - /** - * Returns the kernel parameters. - * - * @return array - */ - protected function getKernelParameters() - { - $bundles = []; - $bundlesMetadata = []; - - foreach ($this->bundles as $name => $bundle) { - $bundles[$name] = \get_class($bundle); - $bundlesMetadata[$name] = [ - 'path' => $bundle->getPath(), - 'namespace' => $bundle->getNamespace(), - ]; - } - - return [ - 'kernel.project_dir' => realpath($this->getProjectDir()) ?: $this->getProjectDir(), - 'kernel.environment' => $this->environment, - 'kernel.runtime_environment' => '%env(default:kernel.environment:APP_RUNTIME_ENV)%', - 'kernel.debug' => $this->debug, - 'kernel.build_dir' => realpath($buildDir = $this->warmupDir ?: $this->getBuildDir()) ?: $buildDir, - 'kernel.cache_dir' => realpath($cacheDir = ($this->getCacheDir() === $this->getBuildDir() ? ($this->warmupDir ?: $this->getCacheDir()) : $this->getCacheDir())) ?: $cacheDir, - 'kernel.logs_dir' => realpath($this->getLogDir()) ?: $this->getLogDir(), - 'kernel.bundles' => $bundles, - 'kernel.bundles_metadata' => $bundlesMetadata, - 'kernel.charset' => $this->getCharset(), - 'kernel.container_class' => $this->getContainerClass(), - ]; - } - - /** - * Builds the service container. - * - * @return ContainerBuilder - * - * @throws \RuntimeException - */ - protected function buildContainer() - { - foreach (['cache' => $this->getCacheDir(), 'build' => $this->warmupDir ?: $this->getBuildDir(), 'logs' => $this->getLogDir()] as $name => $dir) { - if (!is_dir($dir)) { - if (false === @mkdir($dir, 0777, true) && !is_dir($dir)) { - throw new \RuntimeException(sprintf('Unable to create the "%s" directory (%s).', $name, $dir)); - } - } elseif (!is_writable($dir)) { - throw new \RuntimeException(sprintf('Unable to write in the "%s" directory (%s).', $name, $dir)); - } - } - - $container = $this->getContainerBuilder(); - $container->addObjectResource($this); - $this->prepareContainer($container); - - if (null !== $cont = $this->registerContainerConfiguration($this->getContainerLoader($container))) { - trigger_deprecation('symfony/http-kernel', '5.3', 'Returning a ContainerBuilder from "%s::registerContainerConfiguration()" is deprecated.', get_debug_type($this)); - $container->merge($cont); - } - - $container->addCompilerPass(new AddAnnotatedClassesToCachePass($this)); - - return $container; - } - - /** - * Prepares the ContainerBuilder before it is compiled. - */ - protected function prepareContainer(ContainerBuilder $container) - { - $extensions = []; - foreach ($this->bundles as $bundle) { - if ($extension = $bundle->getContainerExtension()) { - $container->registerExtension($extension); - } - - if ($this->debug) { - $container->addObjectResource($bundle); - } - } - - foreach ($this->bundles as $bundle) { - $bundle->build($container); - } - - $this->build($container); - - foreach ($container->getExtensions() as $extension) { - $extensions[] = $extension->getAlias(); - } - - // ensure these extensions are implicitly loaded - $container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions)); - } - - /** - * Gets a new ContainerBuilder instance used to build the service container. - * - * @return ContainerBuilder - */ - protected function getContainerBuilder() - { - $container = new ContainerBuilder(); - $container->getParameterBag()->add($this->getKernelParameters()); - - if ($this instanceof ExtensionInterface) { - $container->registerExtension($this); - } - if ($this instanceof CompilerPassInterface) { - $container->addCompilerPass($this, PassConfig::TYPE_BEFORE_OPTIMIZATION, -10000); - } - if (class_exists(\ProxyManager\Configuration::class) && class_exists(RuntimeInstantiator::class)) { - $container->setProxyInstantiator(new RuntimeInstantiator()); - } - - return $container; - } - - /** - * Dumps the service container to PHP code in the cache. - * - * @param string $class The name of the class to generate - * @param string $baseClass The name of the container's base class - */ - protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container, string $class, string $baseClass) - { - // cache the container - $dumper = new PhpDumper($container); - - if (class_exists(\ProxyManager\Configuration::class) && class_exists(ProxyDumper::class)) { - $dumper->setProxyDumper(new ProxyDumper()); - } - - $content = $dumper->dump([ - 'class' => $class, - 'base_class' => $baseClass, - 'file' => $cache->getPath(), - 'as_files' => true, - 'debug' => $this->debug, - 'build_time' => $container->hasParameter('kernel.container_build_time') ? $container->getParameter('kernel.container_build_time') : time(), - 'preload_classes' => array_map('get_class', $this->bundles), - ]); - - $rootCode = array_pop($content); - $dir = \dirname($cache->getPath()).'/'; - $fs = new Filesystem(); - - foreach ($content as $file => $code) { - $fs->dumpFile($dir.$file, $code); - @chmod($dir.$file, 0666 & ~umask()); - } - $legacyFile = \dirname($dir.key($content)).'.legacy'; - if (is_file($legacyFile)) { - @unlink($legacyFile); - } - - $cache->write($rootCode, $container->getResources()); - } - - /** - * Returns a loader for the container. - * - * @return DelegatingLoader - */ - protected function getContainerLoader(ContainerInterface $container) - { - $env = $this->getEnvironment(); - $locator = new FileLocator($this); - $resolver = new LoaderResolver([ - new XmlFileLoader($container, $locator, $env), - new YamlFileLoader($container, $locator, $env), - new IniFileLoader($container, $locator, $env), - new PhpFileLoader($container, $locator, $env, class_exists(ConfigBuilderGenerator::class) ? new ConfigBuilderGenerator($this->getBuildDir()) : null), - new GlobFileLoader($container, $locator, $env), - new DirectoryLoader($container, $locator, $env), - new ClosureLoader($container, $env), - ]); - - return new DelegatingLoader($resolver); - } - - private function preBoot(): ContainerInterface - { - if ($this->debug) { - $this->startTime = microtime(true); - } - if ($this->debug && !isset($_ENV['SHELL_VERBOSITY']) && !isset($_SERVER['SHELL_VERBOSITY'])) { - putenv('SHELL_VERBOSITY=3'); - $_ENV['SHELL_VERBOSITY'] = 3; - $_SERVER['SHELL_VERBOSITY'] = 3; - } - - $this->initializeBundles(); - $this->initializeContainer(); - - $container = $this->container; - - if ($container->hasParameter('kernel.trusted_hosts') && $trustedHosts = $container->getParameter('kernel.trusted_hosts')) { - Request::setTrustedHosts($trustedHosts); - } - - if ($container->hasParameter('kernel.trusted_proxies') && $container->hasParameter('kernel.trusted_headers') && $trustedProxies = $container->getParameter('kernel.trusted_proxies')) { - Request::setTrustedProxies(\is_array($trustedProxies) ? $trustedProxies : array_map('trim', explode(',', $trustedProxies)), $container->getParameter('kernel.trusted_headers')); - } - - return $container; - } - - /** - * Removes comments from a PHP source string. - * - * We don't use the PHP php_strip_whitespace() function - * as we want the content to be readable and well-formatted. - * - * @return string - */ - public static function stripComments(string $source) - { - if (!\function_exists('token_get_all')) { - return $source; - } - - $rawChunk = ''; - $output = ''; - $tokens = token_get_all($source); - $ignoreSpace = false; - for ($i = 0; isset($tokens[$i]); ++$i) { - $token = $tokens[$i]; - if (!isset($token[1]) || 'b"' === $token) { - $rawChunk .= $token; - } elseif (\T_START_HEREDOC === $token[0]) { - $output .= $rawChunk.$token[1]; - do { - $token = $tokens[++$i]; - $output .= isset($token[1]) && 'b"' !== $token ? $token[1] : $token; - } while (\T_END_HEREDOC !== $token[0]); - $rawChunk = ''; - } elseif (\T_WHITESPACE === $token[0]) { - if ($ignoreSpace) { - $ignoreSpace = false; - - continue; - } - - // replace multiple new lines with a single newline - $rawChunk .= preg_replace(['/\n{2,}/S'], "\n", $token[1]); - } elseif (\in_array($token[0], [\T_COMMENT, \T_DOC_COMMENT])) { - if (!\in_array($rawChunk[\strlen($rawChunk) - 1], [' ', "\n", "\r", "\t"], true)) { - $rawChunk .= ' '; - } - $ignoreSpace = true; - } else { - $rawChunk .= $token[1]; - - // The PHP-open tag already has a new-line - if (\T_OPEN_TAG === $token[0]) { - $ignoreSpace = true; - } else { - $ignoreSpace = false; - } - } - } - - $output .= $rawChunk; - - unset($tokens, $rawChunk); - gc_mem_caches(); - - return $output; - } - - /** - * @return array - */ - public function __sleep() - { - return ['environment', 'debug']; - } - - public function __wakeup() - { - if (\is_object($this->environment) || \is_object($this->debug)) { - throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); - } - - $this->__construct($this->environment, $this->debug); - } -} diff --git a/lib/symfony/http-kernel/KernelEvents.php b/lib/symfony/http-kernel/KernelEvents.php deleted file mode 100644 index 3d47f6080..000000000 --- a/lib/symfony/http-kernel/KernelEvents.php +++ /dev/null @@ -1,128 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel; - -use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent; -use Symfony\Component\HttpKernel\Event\ControllerEvent; -use Symfony\Component\HttpKernel\Event\ExceptionEvent; -use Symfony\Component\HttpKernel\Event\FinishRequestEvent; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Symfony\Component\HttpKernel\Event\TerminateEvent; -use Symfony\Component\HttpKernel\Event\ViewEvent; - -/** - * Contains all events thrown in the HttpKernel component. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -final class KernelEvents -{ - /** - * The REQUEST event occurs at the very beginning of request - * dispatching. - * - * This event allows you to create a response for a request before any - * other code in the framework is executed. - * - * @Event("Symfony\Component\HttpKernel\Event\RequestEvent") - */ - public const REQUEST = 'kernel.request'; - - /** - * The EXCEPTION event occurs when an uncaught exception appears. - * - * This event allows you to create a response for a thrown exception or - * to modify the thrown exception. - * - * @Event("Symfony\Component\HttpKernel\Event\ExceptionEvent") - */ - public const EXCEPTION = 'kernel.exception'; - - /** - * The CONTROLLER event occurs once a controller was found for - * handling a request. - * - * This event allows you to change the controller that will handle the - * request. - * - * @Event("Symfony\Component\HttpKernel\Event\ControllerEvent") - */ - public const CONTROLLER = 'kernel.controller'; - - /** - * The CONTROLLER_ARGUMENTS event occurs once controller arguments have been resolved. - * - * This event allows you to change the arguments that will be passed to - * the controller. - * - * @Event("Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent") - */ - public const CONTROLLER_ARGUMENTS = 'kernel.controller_arguments'; - - /** - * The VIEW event occurs when the return value of a controller - * is not a Response instance. - * - * This event allows you to create a response for the return value of the - * controller. - * - * @Event("Symfony\Component\HttpKernel\Event\ViewEvent") - */ - public const VIEW = 'kernel.view'; - - /** - * The RESPONSE event occurs once a response was created for - * replying to a request. - * - * This event allows you to modify or replace the response that will be - * replied. - * - * @Event("Symfony\Component\HttpKernel\Event\ResponseEvent") - */ - public const RESPONSE = 'kernel.response'; - - /** - * The FINISH_REQUEST event occurs when a response was generated for a request. - * - * This event allows you to reset the global and environmental state of - * the application, when it was changed during the request. - * - * @Event("Symfony\Component\HttpKernel\Event\FinishRequestEvent") - */ - public const FINISH_REQUEST = 'kernel.finish_request'; - - /** - * The TERMINATE event occurs once a response was sent. - * - * This event allows you to run expensive post-response jobs. - * - * @Event("Symfony\Component\HttpKernel\Event\TerminateEvent") - */ - public const TERMINATE = 'kernel.terminate'; - - /** - * Event aliases. - * - * These aliases can be consumed by RegisterListenersPass. - */ - public const ALIASES = [ - ControllerArgumentsEvent::class => self::CONTROLLER_ARGUMENTS, - ControllerEvent::class => self::CONTROLLER, - ResponseEvent::class => self::RESPONSE, - FinishRequestEvent::class => self::FINISH_REQUEST, - RequestEvent::class => self::REQUEST, - ViewEvent::class => self::VIEW, - ExceptionEvent::class => self::EXCEPTION, - TerminateEvent::class => self::TERMINATE, - ]; -} diff --git a/lib/symfony/http-kernel/KernelInterface.php b/lib/symfony/http-kernel/KernelInterface.php deleted file mode 100644 index 41135a6d8..000000000 --- a/lib/symfony/http-kernel/KernelInterface.php +++ /dev/null @@ -1,149 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel; - -use Symfony\Component\Config\Loader\LoaderInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\HttpKernel\Bundle\BundleInterface; - -/** - * The Kernel is the heart of the Symfony system. - * - * It manages an environment made of application kernel and bundles. - * - * @method string getBuildDir() Returns the build directory - not implementing it is deprecated since Symfony 5.2. - * This directory should be used to store build artifacts, and can be read-only at runtime. - * Caches written at runtime should be stored in the "cache directory" ({@see KernelInterface::getCacheDir()}). - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface KernelInterface extends HttpKernelInterface -{ - /** - * Returns an array of bundles to register. - * - * @return iterable<mixed, BundleInterface> - */ - public function registerBundles(); - - /** - * Loads the container configuration. - */ - public function registerContainerConfiguration(LoaderInterface $loader); - - /** - * Boots the current kernel. - */ - public function boot(); - - /** - * Shutdowns the kernel. - * - * This method is mainly useful when doing functional testing. - */ - public function shutdown(); - - /** - * Gets the registered bundle instances. - * - * @return array<string, BundleInterface> - */ - public function getBundles(); - - /** - * Returns a bundle. - * - * @return BundleInterface - * - * @throws \InvalidArgumentException when the bundle is not enabled - */ - public function getBundle(string $name); - - /** - * Returns the file path for a given bundle resource. - * - * A Resource can be a file or a directory. - * - * The resource name must follow the following pattern: - * - * "@BundleName/path/to/a/file.something" - * - * where BundleName is the name of the bundle - * and the remaining part is the relative path in the bundle. - * - * @return string - * - * @throws \InvalidArgumentException if the file cannot be found or the name is not valid - * @throws \RuntimeException if the name contains invalid/unsafe characters - */ - public function locateResource(string $name); - - /** - * Gets the environment. - * - * @return string - */ - public function getEnvironment(); - - /** - * Checks if debug mode is enabled. - * - * @return bool - */ - public function isDebug(); - - /** - * Gets the project dir (path of the project's composer file). - * - * @return string - */ - public function getProjectDir(); - - /** - * Gets the current container. - * - * @return ContainerInterface - */ - public function getContainer(); - - /** - * Gets the request start time (not available if debug is disabled). - * - * @return float - */ - public function getStartTime(); - - /** - * Gets the cache directory. - * - * Since Symfony 5.2, the cache directory should be used for caches that are written at runtime. - * For caches and artifacts that can be warmed at compile-time and deployed as read-only, - * use the new "build directory" returned by the {@see getBuildDir()} method. - * - * @return string - */ - public function getCacheDir(); - - /** - * Gets the log directory. - * - * @return string - */ - public function getLogDir(); - - /** - * Gets the charset of the application. - * - * @return string - */ - public function getCharset(); -} diff --git a/lib/symfony/http-kernel/LICENSE b/lib/symfony/http-kernel/LICENSE deleted file mode 100644 index 008370457..000000000 --- a/lib/symfony/http-kernel/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -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/lib/symfony/http-kernel/Log/DebugLoggerInterface.php b/lib/symfony/http-kernel/Log/DebugLoggerInterface.php deleted file mode 100644 index 19ff0db18..000000000 --- a/lib/symfony/http-kernel/Log/DebugLoggerInterface.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Log; - -use Symfony\Component\HttpFoundation\Request; - -/** - * DebugLoggerInterface. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface DebugLoggerInterface -{ - /** - * Returns an array of logs. - * - * A log is an array with the following mandatory keys: - * timestamp, message, priority, and priorityName. - * It can also have an optional context key containing an array. - * - * @return array - */ - public function getLogs(Request $request = null); - - /** - * Returns the number of errors. - * - * @return int - */ - public function countErrors(Request $request = null); - - /** - * Removes all log records. - */ - public function clear(); -} diff --git a/lib/symfony/http-kernel/Log/Logger.php b/lib/symfony/http-kernel/Log/Logger.php deleted file mode 100644 index c2a45bb95..000000000 --- a/lib/symfony/http-kernel/Log/Logger.php +++ /dev/null @@ -1,124 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Log; - -use Psr\Log\AbstractLogger; -use Psr\Log\InvalidArgumentException; -use Psr\Log\LogLevel; - -/** - * Minimalist PSR-3 logger designed to write in stderr or any other stream. - * - * @author Kévin Dunglas <dunglas@gmail.com> - */ -class Logger extends AbstractLogger -{ - private const LEVELS = [ - LogLevel::DEBUG => 0, - LogLevel::INFO => 1, - LogLevel::NOTICE => 2, - LogLevel::WARNING => 3, - LogLevel::ERROR => 4, - LogLevel::CRITICAL => 5, - LogLevel::ALERT => 6, - LogLevel::EMERGENCY => 7, - ]; - - private $minLevelIndex; - private $formatter; - - /** @var resource|null */ - private $handle; - - /** - * @param string|resource|null $output - */ - public function __construct(string $minLevel = null, $output = null, callable $formatter = null) - { - if (null === $minLevel) { - $minLevel = null === $output || 'php://stdout' === $output || 'php://stderr' === $output ? LogLevel::ERROR : LogLevel::WARNING; - - if (isset($_ENV['SHELL_VERBOSITY']) || isset($_SERVER['SHELL_VERBOSITY'])) { - switch ((int) ($_ENV['SHELL_VERBOSITY'] ?? $_SERVER['SHELL_VERBOSITY'])) { - case -1: $minLevel = LogLevel::ERROR; - break; - case 1: $minLevel = LogLevel::NOTICE; - break; - case 2: $minLevel = LogLevel::INFO; - break; - case 3: $minLevel = LogLevel::DEBUG; - break; - } - } - } - - if (!isset(self::LEVELS[$minLevel])) { - throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $minLevel)); - } - - $this->minLevelIndex = self::LEVELS[$minLevel]; - $this->formatter = $formatter ?: [$this, 'format']; - if ($output && false === $this->handle = \is_resource($output) ? $output : @fopen($output, 'a')) { - throw new InvalidArgumentException(sprintf('Unable to open "%s".', $output)); - } - } - - /** - * {@inheritdoc} - * - * @return void - */ - public function log($level, $message, array $context = []) - { - if (!isset(self::LEVELS[$level])) { - throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level)); - } - - if (self::LEVELS[$level] < $this->minLevelIndex) { - return; - } - - $formatter = $this->formatter; - if ($this->handle) { - @fwrite($this->handle, $formatter($level, $message, $context).\PHP_EOL); - } else { - error_log($formatter($level, $message, $context, false)); - } - } - - private function format(string $level, string $message, array $context, bool $prefixDate = true): string - { - if (str_contains($message, '{')) { - $replacements = []; - foreach ($context as $key => $val) { - if (null === $val || \is_scalar($val) || (\is_object($val) && method_exists($val, '__toString'))) { - $replacements["{{$key}}"] = $val; - } elseif ($val instanceof \DateTimeInterface) { - $replacements["{{$key}}"] = $val->format(\DateTime::RFC3339); - } elseif (\is_object($val)) { - $replacements["{{$key}}"] = '[object '.\get_class($val).']'; - } else { - $replacements["{{$key}}"] = '['.\gettype($val).']'; - } - } - - $message = strtr($message, $replacements); - } - - $log = sprintf('[%s] %s', $level, $message); - if ($prefixDate) { - $log = date(\DateTime::RFC3339).' '.$log; - } - - return $log; - } -} diff --git a/lib/symfony/http-kernel/Profiler/FileProfilerStorage.php b/lib/symfony/http-kernel/Profiler/FileProfilerStorage.php deleted file mode 100644 index 0b5a780ab..000000000 --- a/lib/symfony/http-kernel/Profiler/FileProfilerStorage.php +++ /dev/null @@ -1,311 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Profiler; - -/** - * Storage for profiler using files. - * - * @author Alexandre Salomé <alexandre.salome@gmail.com> - */ -class FileProfilerStorage implements ProfilerStorageInterface -{ - /** - * Folder where profiler data are stored. - * - * @var string - */ - private $folder; - - /** - * Constructs the file storage using a "dsn-like" path. - * - * Example : "file:/path/to/the/storage/folder" - * - * @throws \RuntimeException - */ - public function __construct(string $dsn) - { - if (!str_starts_with($dsn, 'file:')) { - throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use FileStorage with an invalid dsn "%s". The expected format is "file:/path/to/the/storage/folder".', $dsn)); - } - $this->folder = substr($dsn, 5); - - if (!is_dir($this->folder) && false === @mkdir($this->folder, 0777, true) && !is_dir($this->folder)) { - throw new \RuntimeException(sprintf('Unable to create the storage directory (%s).', $this->folder)); - } - } - - /** - * {@inheritdoc} - */ - public function find(?string $ip, ?string $url, ?int $limit, ?string $method, int $start = null, int $end = null, string $statusCode = null): array - { - $file = $this->getIndexFilename(); - - if (!file_exists($file)) { - return []; - } - - $file = fopen($file, 'r'); - fseek($file, 0, \SEEK_END); - - $result = []; - while (\count($result) < $limit && $line = $this->readLineFromFile($file)) { - $values = str_getcsv($line); - [$csvToken, $csvIp, $csvMethod, $csvUrl, $csvTime, $csvParent, $csvStatusCode] = $values; - $csvTime = (int) $csvTime; - - if ($ip && !str_contains($csvIp, $ip) || $url && !str_contains($csvUrl, $url) || $method && !str_contains($csvMethod, $method) || $statusCode && !str_contains($csvStatusCode, $statusCode)) { - continue; - } - - if (!empty($start) && $csvTime < $start) { - continue; - } - - if (!empty($end) && $csvTime > $end) { - continue; - } - - $result[$csvToken] = [ - 'token' => $csvToken, - 'ip' => $csvIp, - 'method' => $csvMethod, - 'url' => $csvUrl, - 'time' => $csvTime, - 'parent' => $csvParent, - 'status_code' => $csvStatusCode, - ]; - } - - fclose($file); - - return array_values($result); - } - - /** - * {@inheritdoc} - */ - public function purge() - { - $flags = \FilesystemIterator::SKIP_DOTS; - $iterator = new \RecursiveDirectoryIterator($this->folder, $flags); - $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::CHILD_FIRST); - - foreach ($iterator as $file) { - if (is_file($file)) { - unlink($file); - } else { - rmdir($file); - } - } - } - - /** - * {@inheritdoc} - */ - public function read(string $token): ?Profile - { - return $this->doRead($token); - } - - /** - * {@inheritdoc} - * - * @throws \RuntimeException - */ - public function write(Profile $profile): bool - { - $file = $this->getFilename($profile->getToken()); - - $profileIndexed = is_file($file); - if (!$profileIndexed) { - // Create directory - $dir = \dirname($file); - if (!is_dir($dir) && false === @mkdir($dir, 0777, true) && !is_dir($dir)) { - throw new \RuntimeException(sprintf('Unable to create the storage directory (%s).', $dir)); - } - } - - $profileToken = $profile->getToken(); - // when there are errors in sub-requests, the parent and/or children tokens - // may equal the profile token, resulting in infinite loops - $parentToken = $profile->getParentToken() !== $profileToken ? $profile->getParentToken() : null; - $childrenToken = array_filter(array_map(function (Profile $p) use ($profileToken) { - return $profileToken !== $p->getToken() ? $p->getToken() : null; - }, $profile->getChildren())); - - // Store profile - $data = [ - 'token' => $profileToken, - 'parent' => $parentToken, - 'children' => $childrenToken, - 'data' => $profile->getCollectors(), - 'ip' => $profile->getIp(), - 'method' => $profile->getMethod(), - 'url' => $profile->getUrl(), - 'time' => $profile->getTime(), - 'status_code' => $profile->getStatusCode(), - ]; - - $data = serialize($data); - - if (\function_exists('gzencode')) { - $data = gzencode($data, 3); - } - - if (false === file_put_contents($file, $data, \LOCK_EX)) { - return false; - } - - if (!$profileIndexed) { - // Add to index - if (false === $file = fopen($this->getIndexFilename(), 'a')) { - return false; - } - - fputcsv($file, [ - $profile->getToken(), - $profile->getIp(), - $profile->getMethod(), - $profile->getUrl(), - $profile->getTime(), - $profile->getParentToken(), - $profile->getStatusCode(), - ]); - fclose($file); - } - - return true; - } - - /** - * Gets filename to store data, associated to the token. - * - * @return string - */ - protected function getFilename(string $token) - { - // Uses 4 last characters, because first are mostly the same. - $folderA = substr($token, -2, 2); - $folderB = substr($token, -4, 2); - - return $this->folder.'/'.$folderA.'/'.$folderB.'/'.$token; - } - - /** - * Gets the index filename. - * - * @return string - */ - protected function getIndexFilename() - { - return $this->folder.'/index.csv'; - } - - /** - * Reads a line in the file, backward. - * - * This function automatically skips the empty lines and do not include the line return in result value. - * - * @param resource $file The file resource, with the pointer placed at the end of the line to read - * - * @return mixed - */ - protected function readLineFromFile($file) - { - $line = ''; - $position = ftell($file); - - if (0 === $position) { - return null; - } - - while (true) { - $chunkSize = min($position, 1024); - $position -= $chunkSize; - fseek($file, $position); - - if (0 === $chunkSize) { - // bof reached - break; - } - - $buffer = fread($file, $chunkSize); - - if (false === ($upTo = strrpos($buffer, "\n"))) { - $line = $buffer.$line; - continue; - } - - $position += $upTo; - $line = substr($buffer, $upTo + 1).$line; - fseek($file, max(0, $position), \SEEK_SET); - - if ('' !== $line) { - break; - } - } - - return '' === $line ? null : $line; - } - - protected function createProfileFromData(string $token, array $data, Profile $parent = null) - { - $profile = new Profile($token); - $profile->setIp($data['ip']); - $profile->setMethod($data['method']); - $profile->setUrl($data['url']); - $profile->setTime($data['time']); - $profile->setStatusCode($data['status_code']); - $profile->setCollectors($data['data']); - - if (!$parent && $data['parent']) { - $parent = $this->read($data['parent']); - } - - if ($parent) { - $profile->setParent($parent); - } - - foreach ($data['children'] as $token) { - if (null !== $childProfile = $this->doRead($token, $profile)) { - $profile->addChild($childProfile); - } - } - - return $profile; - } - - private function doRead($token, Profile $profile = null): ?Profile - { - if (!$token || !file_exists($file = $this->getFilename($token))) { - return null; - } - - $h = fopen($file, 'r'); - flock($h, \LOCK_SH); - $data = stream_get_contents($h); - flock($h, \LOCK_UN); - fclose($h); - - if (\function_exists('gzdecode')) { - $data = @gzdecode($data) ?: $data; - } - - if (!$data = unserialize($data)) { - return null; - } - - return $this->createProfileFromData($token, $data, $profile); - } -} diff --git a/lib/symfony/http-kernel/Profiler/Profile.php b/lib/symfony/http-kernel/Profiler/Profile.php deleted file mode 100644 index a622403e1..000000000 --- a/lib/symfony/http-kernel/Profiler/Profile.php +++ /dev/null @@ -1,270 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Profiler; - -use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; - -/** - * Profile. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Profile -{ - private $token; - - /** - * @var DataCollectorInterface[] - */ - private $collectors = []; - - private $ip; - private $method; - private $url; - private $time; - private $statusCode; - - /** - * @var Profile - */ - private $parent; - - /** - * @var Profile[] - */ - private $children = []; - - public function __construct(string $token) - { - $this->token = $token; - } - - public function setToken(string $token) - { - $this->token = $token; - } - - /** - * Gets the token. - * - * @return string - */ - public function getToken() - { - return $this->token; - } - - /** - * Sets the parent token. - */ - public function setParent(self $parent) - { - $this->parent = $parent; - } - - /** - * Returns the parent profile. - * - * @return self|null - */ - public function getParent() - { - return $this->parent; - } - - /** - * Returns the parent token. - * - * @return string|null - */ - public function getParentToken() - { - return $this->parent ? $this->parent->getToken() : null; - } - - /** - * Returns the IP. - * - * @return string|null - */ - public function getIp() - { - return $this->ip; - } - - public function setIp(?string $ip) - { - $this->ip = $ip; - } - - /** - * Returns the request method. - * - * @return string|null - */ - public function getMethod() - { - return $this->method; - } - - public function setMethod(string $method) - { - $this->method = $method; - } - - /** - * Returns the URL. - * - * @return string|null - */ - public function getUrl() - { - return $this->url; - } - - public function setUrl(?string $url) - { - $this->url = $url; - } - - /** - * @return int - */ - public function getTime() - { - return $this->time ?? 0; - } - - public function setTime(int $time) - { - $this->time = $time; - } - - public function setStatusCode(int $statusCode) - { - $this->statusCode = $statusCode; - } - - /** - * @return int|null - */ - public function getStatusCode() - { - return $this->statusCode; - } - - /** - * Finds children profilers. - * - * @return self[] - */ - public function getChildren() - { - return $this->children; - } - - /** - * Sets children profiler. - * - * @param Profile[] $children - */ - public function setChildren(array $children) - { - $this->children = []; - foreach ($children as $child) { - $this->addChild($child); - } - } - - /** - * Adds the child token. - */ - public function addChild(self $child) - { - $this->children[] = $child; - $child->setParent($this); - } - - public function getChildByToken(string $token): ?self - { - foreach ($this->children as $child) { - if ($token === $child->getToken()) { - return $child; - } - } - - return null; - } - - /** - * Gets a Collector by name. - * - * @return DataCollectorInterface - * - * @throws \InvalidArgumentException if the collector does not exist - */ - public function getCollector(string $name) - { - if (!isset($this->collectors[$name])) { - throw new \InvalidArgumentException(sprintf('Collector "%s" does not exist.', $name)); - } - - return $this->collectors[$name]; - } - - /** - * Gets the Collectors associated with this profile. - * - * @return DataCollectorInterface[] - */ - public function getCollectors() - { - return $this->collectors; - } - - /** - * Sets the Collectors associated with this profile. - * - * @param DataCollectorInterface[] $collectors - */ - public function setCollectors(array $collectors) - { - $this->collectors = []; - foreach ($collectors as $collector) { - $this->addCollector($collector); - } - } - - /** - * Adds a Collector. - */ - public function addCollector(DataCollectorInterface $collector) - { - $this->collectors[$collector->getName()] = $collector; - } - - /** - * @return bool - */ - public function hasCollector(string $name) - { - return isset($this->collectors[$name]); - } - - /** - * @return array - */ - public function __sleep() - { - return ['token', 'parent', 'children', 'collectors', 'ip', 'method', 'url', 'time', 'statusCode']; - } -} diff --git a/lib/symfony/http-kernel/Profiler/Profiler.php b/lib/symfony/http-kernel/Profiler/Profiler.php deleted file mode 100644 index 25e126f73..000000000 --- a/lib/symfony/http-kernel/Profiler/Profiler.php +++ /dev/null @@ -1,253 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Profiler; - -use Psr\Log\LoggerInterface; -use Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; -use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; -use Symfony\Contracts\Service\ResetInterface; - -/** - * Profiler. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Profiler implements ResetInterface -{ - private $storage; - - /** - * @var DataCollectorInterface[] - */ - private $collectors = []; - - private $logger; - private $initiallyEnabled = true; - private $enabled = true; - - public function __construct(ProfilerStorageInterface $storage, LoggerInterface $logger = null, bool $enable = true) - { - $this->storage = $storage; - $this->logger = $logger; - $this->initiallyEnabled = $this->enabled = $enable; - } - - /** - * Disables the profiler. - */ - public function disable() - { - $this->enabled = false; - } - - /** - * Enables the profiler. - */ - public function enable() - { - $this->enabled = true; - } - - /** - * Loads the Profile for the given Response. - * - * @return Profile|null - */ - public function loadProfileFromResponse(Response $response) - { - if (!$token = $response->headers->get('X-Debug-Token')) { - return null; - } - - return $this->loadProfile($token); - } - - /** - * Loads the Profile for the given token. - * - * @return Profile|null - */ - public function loadProfile(string $token) - { - return $this->storage->read($token); - } - - /** - * Saves a Profile. - * - * @return bool - */ - public function saveProfile(Profile $profile) - { - // late collect - foreach ($profile->getCollectors() as $collector) { - if ($collector instanceof LateDataCollectorInterface) { - $collector->lateCollect(); - } - } - - if (!($ret = $this->storage->write($profile)) && null !== $this->logger) { - $this->logger->warning('Unable to store the profiler information.', ['configured_storage' => \get_class($this->storage)]); - } - - return $ret; - } - - /** - * Purges all data from the storage. - */ - public function purge() - { - $this->storage->purge(); - } - - /** - * Finds profiler tokens for the given criteria. - * - * @param string|null $limit The maximum number of tokens to return - * @param string|null $start The start date to search from - * @param string|null $end The end date to search to - * - * @return array - * - * @see https://php.net/datetime.formats for the supported date/time formats - */ - public function find(?string $ip, ?string $url, ?string $limit, ?string $method, ?string $start, ?string $end, string $statusCode = null) - { - return $this->storage->find($ip, $url, $limit, $method, $this->getTimestamp($start), $this->getTimestamp($end), $statusCode); - } - - /** - * Collects data for the given Response. - * - * @return Profile|null - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - if (false === $this->enabled) { - return null; - } - - $profile = new Profile(substr(hash('sha256', uniqid(mt_rand(), true)), 0, 6)); - $profile->setTime(time()); - $profile->setUrl($request->getUri()); - $profile->setMethod($request->getMethod()); - $profile->setStatusCode($response->getStatusCode()); - try { - $profile->setIp($request->getClientIp()); - } catch (ConflictingHeadersException $e) { - $profile->setIp('Unknown'); - } - - if ($prevToken = $response->headers->get('X-Debug-Token')) { - $response->headers->set('X-Previous-Debug-Token', $prevToken); - } - - $response->headers->set('X-Debug-Token', $profile->getToken()); - - foreach ($this->collectors as $collector) { - $collector->collect($request, $response, $exception); - - // we need to clone for sub-requests - $profile->addCollector(clone $collector); - } - - return $profile; - } - - public function reset() - { - foreach ($this->collectors as $collector) { - $collector->reset(); - } - $this->enabled = $this->initiallyEnabled; - } - - /** - * Gets the Collectors associated with this profiler. - * - * @return array - */ - public function all() - { - return $this->collectors; - } - - /** - * Sets the Collectors associated with this profiler. - * - * @param DataCollectorInterface[] $collectors An array of collectors - */ - public function set(array $collectors = []) - { - $this->collectors = []; - foreach ($collectors as $collector) { - $this->add($collector); - } - } - - /** - * Adds a Collector. - */ - public function add(DataCollectorInterface $collector) - { - $this->collectors[$collector->getName()] = $collector; - } - - /** - * Returns true if a Collector for the given name exists. - * - * @param string $name A collector name - * - * @return bool - */ - public function has(string $name) - { - return isset($this->collectors[$name]); - } - - /** - * Gets a Collector by name. - * - * @param string $name A collector name - * - * @return DataCollectorInterface - * - * @throws \InvalidArgumentException if the collector does not exist - */ - public function get(string $name) - { - if (!isset($this->collectors[$name])) { - throw new \InvalidArgumentException(sprintf('Collector "%s" does not exist.', $name)); - } - - return $this->collectors[$name]; - } - - private function getTimestamp(?string $value): ?int - { - if (null === $value || '' === $value) { - return null; - } - - try { - $value = new \DateTime(is_numeric($value) ? '@'.$value : $value); - } catch (\Exception $e) { - return null; - } - - return $value->getTimestamp(); - } -} diff --git a/lib/symfony/http-kernel/Profiler/ProfilerStorageInterface.php b/lib/symfony/http-kernel/Profiler/ProfilerStorageInterface.php deleted file mode 100644 index 95d72f46b..000000000 --- a/lib/symfony/http-kernel/Profiler/ProfilerStorageInterface.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Profiler; - -/** - * ProfilerStorageInterface. - * - * This interface exists for historical reasons. The only supported - * implementation is FileProfilerStorage. - * - * As the profiler must only be used on non-production servers, the file storage - * is more than enough and no other implementations will ever be supported. - * - * @internal - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface ProfilerStorageInterface -{ - /** - * Finds profiler tokens for the given criteria. - * - * @param int|null $limit The maximum number of tokens to return - * @param int|null $start The start date to search from - * @param int|null $end The end date to search to - */ - public function find(?string $ip, ?string $url, ?int $limit, ?string $method, int $start = null, int $end = null): array; - - /** - * Reads data associated with the given token. - * - * The method returns false if the token does not exist in the storage. - */ - public function read(string $token): ?Profile; - - /** - * Saves a Profile. - */ - public function write(Profile $profile): bool; - - /** - * Purges all data from the database. - */ - public function purge(); -} diff --git a/lib/symfony/http-kernel/README.md b/lib/symfony/http-kernel/README.md deleted file mode 100644 index ca5041782..000000000 --- a/lib/symfony/http-kernel/README.md +++ /dev/null @@ -1,31 +0,0 @@ -HttpKernel Component -==================== - -The HttpKernel component provides a structured process for converting a Request -into a Response by making use of the EventDispatcher component. It's flexible -enough to create full-stack frameworks, micro-frameworks or advanced CMS systems like Drupal. - -Sponsor -------- - -The HttpKernel 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/http_kernel.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) - -[1]: https://symfony.com/backers -[2]: https://les-tilleuls.coop -[3]: https://symfony.com/sponsor diff --git a/lib/symfony/http-kernel/RebootableInterface.php b/lib/symfony/http-kernel/RebootableInterface.php deleted file mode 100644 index e257237da..000000000 --- a/lib/symfony/http-kernel/RebootableInterface.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel; - -/** - * Allows the Kernel to be rebooted using a temporary cache directory. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -interface RebootableInterface -{ - /** - * Reboots a kernel. - * - * The getBuildDir() method of a rebootable kernel should not be called - * while building the container. Use the %kernel.build_dir% parameter instead. - * - * @param string|null $warmupDir pass null to reboot in the regular build directory - */ - public function reboot(?string $warmupDir); -} diff --git a/lib/symfony/http-kernel/Resources/welcome.html.php b/lib/symfony/http-kernel/Resources/welcome.html.php deleted file mode 100644 index b25f99b3d..000000000 --- a/lib/symfony/http-kernel/Resources/welcome.html.php +++ /dev/null @@ -1,123 +0,0 @@ -<!DOCTYPE html> -<html dir="ltr" lang="en"> -<head> - <meta charset="UTF-8" /> - <meta name="robots" content="noindex,nofollow,noarchive,nosnippet,noodp,notranslate,noimageindex" /> - <title>Welcome to Symfony!</title> - <style> - <?php $hue = random_int(0, 360); ?> - <?php $darkColor = static function (float $alpha = 1) use ($hue) { return "hsla($hue, 20%, 45%, $alpha)"; }; ?> - <?php $lightColor = static function (float $alpha = 1) use ($hue) { return "hsla($hue, 20%, 95%, $alpha)"; }; ?> - body { background: <?= $lightColor(); ?>; color: <?= $darkColor(); ?>; display: flex; font: 16px/1.5 sans-serif; justify-content: center; margin: 0; } - h1, h2 { line-height: 1.2; margin: 0 0 .5em; } - h1 { font-size: 36px; } - h2 { font-size: 21px; margin-bottom: 1em; } - a { color: <?= $darkColor(0.75); ?> } - a:hover { text-decoration: none; } - code { border-radius: 25px; background: <?= $lightColor(); ?>; box-shadow: 0 0 45px -15px hsl(<?= $hue; ?>, 20%, 2%); color: <?= $darkColor(); ?>; font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; align-items: center; padding-right: 20px; position: relative; word-wrap: break-word; z-index: 1; } - svg { overflow: hidden; vertical-align: text-bottom; } - .wrapper { text-align: center; width: 100%; } - .container { position: relative; background: radial-gradient(ellipse at bottom, <?= $darkColor(); ?> 0%, hsl(<?= $hue; ?>, 20%, 13%) 100%); background-attachment: fixed; color: <?= $lightColor(); ?>; } - .container:after { content: ""; position: absolute; height: 2px; width: 2px; top: -2px; left: 0; background: white; box-shadow: 778px 1019px 0 0 rgba(255, 255, 255, 0.826) , 1075px 1688px 0 0 rgba(255,255,255, 0.275) , 388px 1021px 0 0 rgba(255,255,255, 0.259) , 1238px 626px 0 0 rgba(255,255,255, 0.469) , 997px 904px 0 0 rgba(255,255,255, 0.925) , 921px 1345px 0 0 rgba(255,255,255, 0.698) , 337px 1236px 0 0 rgba(255,255,255, 0.838) , 460px 569px 0 0 rgba(255,255,255, 0.01) , 690px 1488px 0 0 rgba(255,255,255, 0.154) , 859px 926px 0 0 rgba(255,255,255, 0.515) , 1272px 791px 0 0 rgba(255,255,255, 1) , 238px 1256px 0 0 rgba(255,255,255, 0.633) , 1486px 897px 0 0 rgba(255,255,255, 0.88) , 667px 6px 0 0 rgba(255,255,255, 0.508) , 853px 504px 0 0 rgba(255,255,255, 0.248) , 1329px 1778px 0 0 rgba(255,255,255, 0.217) , 768px 1340px 0 0 rgba(255,255,255, 0.792) , 631px 1383px 0 0 rgba(255,255,255, 0.698) , 991px 1603px 0 0 rgba(255,255,255, 0.939) , 1778px 1767px 0 0 rgba(255,255,255, 0.784) , 285px 546px 0 0 rgba(255,255,255, 0.8) , 1224px 1333px 0 0 rgba(255,255,255, 0.676) , 1154px 397px 0 0 rgba(255,255,255, 0.974) , 1210px 1004px 0 0 rgba(255,255,255, 0.894) , 1632px 953px 0 0 rgba(255,255,255, 0.281) , 449px 1144px 0 0 rgba(255,255,255, 0.706) , 1426px 771px 0 0 rgba(255,255,255, 0.737) , 1438px 1634px 0 0 rgba(255,255,255, 0.984) , 806px 168px 0 0 rgba(255,255,255, 0.807) , 731px 1067px 0 0 rgba(255,255,255, 0.734) , 1731px 1785px 0 0 rgba(255,255,255, 0.528) , 23px 975px 0 0 rgba(255,255,255, 0.068) , 575px 1088px 0 0 rgba(255,255,255, 0.876) , 1205px 1668px 0 0 rgba(255,255,255, 0.601) , 18px 1457px 0 0 rgba(255,255,255, 0.176) , 252px 1163px 0 0 rgba(255,255,255, 0.416) , 1752px 1px 0 0 rgba(255,255,255, 0.374) , 382px 767px 0 0 rgba(255,255,255, 0.073) , 133px 1462px 0 0 rgba(255,255,255, 0.706) , 851px 1166px 0 0 rgba(255,255,255, 0.535) , 374px 921px 0 0 rgba(255,255,255, 0.548) , 554px 1598px 0 0 rgba(255,255,255, 0.062) , 314px 685px 0 0 rgba(255,255,255, 0.187) , 1443px 209px 0 0 rgba(255,255,255, 0.097) , 1774px 1625px 0 0 rgba(255,255,255, 0.32) , 58px 278px 0 0 rgba(255,255,255, 0.684) , 986px 338px 0 0 rgba(255,255,255, 0.272) , 718px 1357px 0 0 rgba(255,255,255, 0.317) , 722px 983px 0 0 rgba(255,255,255, 0.568) , 1124px 992px 0 0 rgba(255,255,255, 0.199) , 581px 619px 0 0 rgba(255,255,255, 0.44) , 1120px 285px 0 0 rgba(255,255,255, 0.425) , 702px 138px 0 0 rgba(255,255,255, 0.816) , 262px 767px 0 0 rgba(255,255,255, 0.92) , 1204px 38px 0 0 rgba(255,255,255, 0.197) , 1196px 410px 0 0 rgba(255,255,255, 0.453) , 707px 699px 0 0 rgba(255,255,255, 0.481) , 1590px 1488px 0 0 rgba(255,255,255, 0.559) , 879px 1763px 0 0 rgba(255,255,255, 0.241) , 106px 686px 0 0 rgba(255,255,255, 0.175) , 158px 569px 0 0 rgba(255,255,255, 0.549) , 711px 1219px 0 0 rgba(255,255,255, 0.476) , 1339px 53px 0 0 rgba(255,255,255, 0.275) , 1410px 172px 0 0 rgba(255,255,255, 0.449) , 1601px 1484px 0 0 rgba(255,255,255, 0.988) , 1328px 1752px 0 0 rgba(255,255,255, 0.827) , 1733px 1475px 0 0 rgba(255,255,255, 0.567) , 559px 742px 0 0 rgba(255,255,255, 0.423) , 772px 844px 0 0 rgba(255,255,255, 0.039) , 602px 520px 0 0 rgba(255,255,255, 0.284) , 1158px 1067px 0 0 rgba(255,255,255, 0.066) , 1562px 730px 0 0 rgba(255,255,255, 0.086) , 1792px 615px 0 0 rgba(255,255,255, 0.438) , 1085px 1191px 0 0 rgba(255,255,255, 0.157) , 1402px 1087px 0 0 rgba(255,255,255, 0.797) , 569px 1685px 0 0 rgba(255,255,255, 0.992) , 1608px 52px 0 0 rgba(255,255,255, 0.302) , 1697px 1246px 0 0 rgba(255,255,255, 0.295) , 899px 1490px 0 0 rgba(255,255,255, 0.73) , 993px 901px 0 0 rgba(255,255,255, 0.961) , 1193px 1023px 0 0 rgba(255,255,255, 0.671) , 1224px 176px 0 0 rgba(255,255,255, 0.786) , 721px 1308px 0 0 rgba(255,255,255, 0.691) , 1702px 730px 0 0 rgba(255,255,255, 0.841) , 1480px 1498px 0 0 rgba(255,255,255, 0.655) , 181px 1612px 0 0 rgba(255,255,255, 0.588) , 1776px 679px 0 0 rgba(255,255,255, 0.821) , 892px 706px 0 0 rgba(255,255,255, 0.056) , 859px 267px 0 0 rgba(255,255,255, 0.565) , 784px 1285px 0 0 rgba(255,255,255, 0.029) , 1561px 1198px 0 0 rgba(255,255,255, 0.315) , 205px 421px 0 0 rgba(255,255,255, 0.584) , 236px 406px 0 0 rgba(255,255,255, 0.166) , 1259px 689px 0 0 rgba(255,255,255, 0.321) , 448px 317px 0 0 rgba(255,255,255, 0.495) , 1318px 466px 0 0 rgba(255,255,255, 0.275) , 1053px 297px 0 0 rgba(255,255,255, 0.035) , 716px 538px 0 0 rgba(255,255,255, 0.764) , 381px 207px 0 0 rgba(255,255,255, 0.692) , 871px 1140px 0 0 rgba(255,255,255, 0.342) , 361px 53px 0 0 rgba(255,255,255, 0.984) , 1565px 1593px 0 0 rgba(255,255,255, 0.102) , 145px 277px 0 0 rgba(255,255,255, 0.866) , 220px 1503px 0 0 rgba(255,255,255, 0.936) , 1068px 1475px 0 0 rgba(255,255,255, 0.156) , 1548px 483px 0 0 rgba(255,255,255, 0.768) , 710px 103px 0 0 rgba(255,255,255, 0.809) , 1660px 921px 0 0 rgba(255,255,255, 0.952) , 462px 1252px 0 0 rgba(255,255,255, 0.825) , 1123px 1628px 0 0 rgba(255,255,255, 0.409) , 1274px 729px 0 0 rgba(255,255,255, 0.26) , 1739px 679px 0 0 rgba(255,255,255, 0.83) , 1550px 1518px 0 0 rgba(255,255,255, 0.25) , 1624px 346px 0 0 rgba(255,255,255, 0.557) , 1023px 579px 0 0 rgba(255,255,255, 0.854) , 217px 661px 0 0 rgba(255,255,255, 0.731) , 1504px 549px 0 0 rgba(255,255,255, 0.705) , 939px 5px 0 0 rgba(255,255,255, 0.389) , 284px 735px 0 0 rgba(255,255,255, 0.355) , 13px 1679px 0 0 rgba(255,255,255, 0.712) , 137px 1592px 0 0 rgba(255,255,255, 0.619) , 1113px 505px 0 0 rgba(255,255,255, 0.651) , 1584px 510px 0 0 rgba(255,255,255, 0.41) , 346px 913px 0 0 rgba(255,255,255, 0.09) , 198px 1490px 0 0 rgba(255,255,255, 0.103) , 447px 1128px 0 0 rgba(255,255,255, 0.314) , 1356px 324px 0 0 rgba(255,255,255, 0.324) , 648px 667px 0 0 rgba(255,255,255, 0.155) , 442px 260px 0 0 rgba(255,255,255, 0.22) , 210px 401px 0 0 rgba(255,255,255, 0.682) , 422px 1772px 0 0 rgba(255,255,255, 0.671) , 276px 349px 0 0 rgba(255,255,255, 0.683) , 131px 539px 0 0 rgba(255,255,255, 0.977) , 892px 94px 0 0 rgba(255,255,255, 0.081) , 1295px 222px 0 0 rgba(255,255,255, 0.961) , 5px 1727px 0 0 rgba(255,255,255, 0.311) , 714px 1148px 0 0 rgba(255,255,255, 0.846) , 1455px 1182px 0 0 rgba(255,255,255, 0.313) , 1370px 708px 0 0 rgba(255,255,255, 0.824) , 812px 433px 0 0 rgba(255,255,255, 0.75) , 1110px 558px 0 0 rgba(255,255,255, 0.709) , 1132px 1543px 0 0 rgba(255,255,255, 0.868) , 644px 610px 0 0 rgba(255,255,255, 0.166) , 269px 1481px 0 0 rgba(255,255,255, 0.889) , 1712px 590px 0 0 rgba(255,255,255, 0.139) , 1159px 599px 0 0 rgba(255,255,255, 0.992) , 1551px 209px 0 0 rgba(255,255,255, 0.033) , 1020px 1721px 0 0 rgba(255,255,255, 0.028) , 216px 373px 0 0 rgba(255,255,255, 0.665) , 877px 532px 0 0 rgba(255,255,255, 0.686) , 1326px 885px 0 0 rgba(255,255,255, 0.517) , 972px 1704px 0 0 rgba(255,255,255, 0.499) , 749px 181px 0 0 rgba(255,255,255, 0.712) , 1511px 1650px 0 0 rgba(255,255,255, 0.101) , 1432px 183px 0 0 rgba(255,255,255, 0.545) , 1541px 1338px 0 0 rgba(255,255,255, 0.71) , 513px 1406px 0 0 rgba(255,255,255, 0.17) , 1314px 1197px 0 0 rgba(255,255,255, 0.789) , 824px 1659px 0 0 rgba(255,255,255, 0.597) , 308px 298px 0 0 rgba(255,255,255, 0.917) , 1225px 659px 0 0 rgba(255,255,255, 0.229) , 1253px 257px 0 0 rgba(255,255,255, 0.631) , 1653px 185px 0 0 rgba(255,255,255, 0.113) , 336px 614px 0 0 rgba(255,255,255, 0.045) , 1093px 898px 0 0 rgba(255,255,255, 0.617) , 730px 5px 0 0 rgba(255,255,255, 0.11) , 785px 645px 0 0 rgba(255,255,255, 0.516) , 989px 678px 0 0 rgba(255,255,255, 0.917) , 1511px 1614px 0 0 rgba(255,255,255, 0.938) , 584px 1117px 0 0 rgba(255,255,255, 0.631) , 534px 1012px 0 0 rgba(255,255,255, 0.668) , 1325px 1778px 0 0 rgba(255,255,255, 0.293) , 1632px 754px 0 0 rgba(255,255,255, 0.26) , 78px 1258px 0 0 rgba(255,255,255, 0.52) , 779px 1691px 0 0 rgba(255,255,255, 0.878) , 253px 1706px 0 0 rgba(255,255,255, 0.75) , 1358px 245px 0 0 rgba(255,255,255, 0.027) , 361px 1629px 0 0 rgba(255,255,255, 0.238) , 1134px 232px 0 0 rgba(255,255,255, 0.387) , 1685px 777px 0 0 rgba(255,255,255, 0.156) , 515px 724px 0 0 rgba(255,255,255, 0.863) , 588px 1728px 0 0 rgba(255,255,255, 0.159) , 1132px 47px 0 0 rgba(255,255,255, 0.691) , 315px 1446px 0 0 rgba(255,255,255, 0.782) , 79px 233px 0 0 rgba(255,255,255, 0.317) , 1498px 1050px 0 0 rgba(255,255,255, 0.358) , 30px 1073px 0 0 rgba(255,255,255, 0.939) , 1637px 620px 0 0 rgba(255,255,255, 0.141) , 1736px 1683px 0 0 rgba(255,255,255, 0.682) , 1298px 1505px 0 0 rgba(255,255,255, 0.863) , 972px 85px 0 0 rgba(255,255,255, 0.941) , 349px 1356px 0 0 rgba(255,255,255, 0.672) , 1545px 1429px 0 0 rgba(255,255,255, 0.859) , 1076px 467px 0 0 rgba(255,255,255, 0.024) , 189px 1647px 0 0 rgba(255,255,255, 0.838) , 423px 1722px 0 0 rgba(255,255,255, 0.771) , 1691px 1719px 0 0 rgba(255,255,255, 0.676) , 1747px 658px 0 0 rgba(255,255,255, 0.255) , 149px 1492px 0 0 rgba(255,255,255, 0.911) , 1203px 1138px 0 0 rgba(255,255,255, 0.964) , 781px 1584px 0 0 rgba(255,255,255, 0.465) , 1609px 1595px 0 0 rgba(255,255,255, 0.688) , 447px 1655px 0 0 rgba(255,255,255, 0.166) , 914px 1153px 0 0 rgba(255,255,255, 0.085) , 600px 1058px 0 0 rgba(255,255,255, 0.821) , 804px 505px 0 0 rgba(255,255,255, 0.608) , 1506px 584px 0 0 rgba(255,255,255, 0.618) , 587px 1290px 0 0 rgba(255,255,255, 0.071) , 258px 600px 0 0 rgba(255,255,255, 0.243) , 328px 395px 0 0 rgba(255,255,255, 0.065) , 846px 783px 0 0 rgba(255,255,255, 0.995) , 1138px 1294px 0 0 rgba(255,255,255, 0.703) , 1668px 633px 0 0 rgba(255,255,255, 0.27) , 337px 103px 0 0 rgba(255,255,255, 0.202) , 132px 986px 0 0 rgba(255,255,255, 0.726) , 414px 757px 0 0 rgba(255,255,255, 0.752) , 8px 1311px 0 0 rgba(255,255,255, 0.307) , 1791px 910px 0 0 rgba(255,255,255, 0.346) , 844px 216px 0 0 rgba(255,255,255, 0.156) , 1547px 1723px 0 0 rgba(255,255,255, 0.73) , 1187px 398px 0 0 rgba(255,255,255, 0.698) , 1550px 1520px 0 0 rgba(255,255,255, 0.462) , 1346px 655px 0 0 rgba(255,255,255, 0.58) , 668px 770px 0 0 rgba(255,255,255, 0.422) , 1774px 1435px 0 0 rgba(255,255,255, 0.089) , 693px 1061px 0 0 rgba(255,255,255, 0.893) , 132px 1689px 0 0 rgba(255,255,255, 0.937) , 894px 1561px 0 0 rgba(255,255,255, 0.88) , 906px 1706px 0 0 rgba(255,255,255, 0.567) , 1140px 297px 0 0 rgba(255,255,255, 0.358) , 13px 1288px 0 0 rgba(255,255,255, 0.464) , 1744px 423px 0 0 rgba(255,255,255, 0.845) , 119px 1548px 0 0 rgba(255,255,255, 0.769) , 1249px 1321px 0 0 rgba(255,255,255, 0.29) , 123px 795px 0 0 rgba(255,255,255, 0.597) , 390px 1542px 0 0 rgba(255,255,255, 0.47) , 825px 667px 0 0 rgba(255,255,255, 0.049) , 1071px 875px 0 0 rgba(255,255,255, 0.06) , 1428px 1786px 0 0 rgba(255,255,255, 0.222) , 993px 696px 0 0 rgba(255,255,255, 0.399) , 1585px 247px 0 0 rgba(255,255,255, 0.094) , 1340px 1312px 0 0 rgba(255,255,255, 0.603) , 1640px 725px 0 0 rgba(255,255,255, 0.026) , 1161px 1397px 0 0 rgba(255,255,255, 0.222) , 966px 1132px 0 0 rgba(255,255,255, 0.69) , 1782px 1275px 0 0 rgba(255,255,255, 0.606) , 1117px 1533px 0 0 rgba(255,255,255, 0.248) , 1027px 959px 0 0 rgba(255,255,255, 0.46) , 459px 839px 0 0 rgba(255,255,255, 0.98) , 1192px 265px 0 0 rgba(255,255,255, 0.523) , 175px 501px 0 0 rgba(255,255,255, 0.371) , 626px 19px 0 0 rgba(255,255,255, 0.246) , 46px 1173px 0 0 rgba(255,255,255, 0.124) , 573px 925px 0 0 rgba(255,255,255, 0.621) , 1px 283px 0 0 rgba(255,255,255, 0.943) , 778px 1213px 0 0 rgba(255,255,255, 0.128) , 435px 593px 0 0 rgba(255,255,255, 0.378) , 32px 394px 0 0 rgba(255,255,255, 0.451) , 1019px 1055px 0 0 rgba(255,255,255, 0.685) , 1423px 1233px 0 0 rgba(255,255,255, 0.354) , 494px 841px 0 0 rgba(255,255,255, 0.322) , 667px 194px 0 0 rgba(255,255,255, 0.655) , 1671px 195px 0 0 rgba(255,255,255, 0.502) , 403px 1710px 0 0 rgba(255,255,255, 0.623) , 665px 1597px 0 0 rgba(255,255,255, 0.839) , 61px 1742px 0 0 rgba(255,255,255, 0.566) , 1490px 1654px 0 0 rgba(255,255,255, 0.646) , 1361px 1604px 0 0 rgba(255,255,255, 0.101) , 1191px 1023px 0 0 rgba(255,255,255, 0.881) , 550px 378px 0 0 rgba(255,255,255, 0.573) , 1332px 1234px 0 0 rgba(255,255,255, 0.922) , 760px 1205px 0 0 rgba(255,255,255, 0.992) , 1506px 1328px 0 0 rgba(255,255,255, 0.723) , 1126px 813px 0 0 rgba(255,255,255, 0.549) , 67px 240px 0 0 rgba(255,255,255, 0.901) , 125px 1301px 0 0 rgba(255,255,255, 0.464) , 643px 391px 0 0 rgba(255,255,255, 0.589) , 1114px 1756px 0 0 rgba(255,255,255, 0.321) , 1602px 699px 0 0 rgba(255,255,255, 0.274) , 510px 393px 0 0 rgba(255,255,255, 0.185) , 171px 1217px 0 0 rgba(255,255,255, 0.932) , 1202px 1362px 0 0 rgba(255,255,255, 0.726) , 1160px 1324px 0 0 rgba(255,255,255, 0.867) , 121px 319px 0 0 rgba(255,255,255, 0.992) , 1474px 835px 0 0 rgba(255,255,255, 0.89) , 357px 1213px 0 0 rgba(255,255,255, 0.91) , 783px 976px 0 0 rgba(255,255,255, 0.941) , 750px 1599px 0 0 rgba(255,255,255, 0.515) , 323px 450px 0 0 rgba(255,255,255, 0.966) , 1078px 282px 0 0 rgba(255,255,255, 0.947) , 1164px 46px 0 0 rgba(255,255,255, 0.296) , 1792px 705px 0 0 rgba(255,255,255, 0.485) , 880px 1287px 0 0 rgba(255,255,255, 0.894) , 60px 1402px 0 0 rgba(255,255,255, 0.816) , 752px 894px 0 0 rgba(255,255,255, 0.803) , 285px 1535px 0 0 rgba(255,255,255, 0.93) , 1528px 401px 0 0 rgba(255,255,255, 0.727) , 651px 1767px 0 0 rgba(255,255,255, 0.146) , 1498px 1190px 0 0 rgba(255,255,255, 0.042) , 394px 1786px 0 0 rgba(255,255,255, 0.159) , 1318px 9px 0 0 rgba(255,255,255, 0.575) , 1699px 1675px 0 0 rgba(255,255,255, 0.511) , 82px 986px 0 0 rgba(255,255,255, 0.906) , 940px 970px 0 0 rgba(255,255,255, 0.562) , 1624px 259px 0 0 rgba(255,255,255, 0.537) , 1782px 222px 0 0 rgba(255,255,255, 0.259) , 1572px 1725px 0 0 rgba(255,255,255, 0.716) , 1080px 1557px 0 0 rgba(255,255,255, 0.245) , 1727px 648px 0 0 rgba(255,255,255, 0.471) , 899px 231px 0 0 rgba(255,255,255, 0.445) , 1061px 1074px 0 0 rgba(255,255,255, 0.079) , 556px 478px 0 0 rgba(255,255,255, 0.524) , 343px 359px 0 0 rgba(255,255,255, 0.162) , 711px 1254px 0 0 rgba(255,255,255, 0.323) , 1335px 242px 0 0 rgba(255,255,255, 0.936) , 933px 39px 0 0 rgba(255,255,255, 0.784) , 1629px 908px 0 0 rgba(255,255,255, 0.289) , 1800px 229px 0 0 rgba(255,255,255, 0.399) , 1589px 926px 0 0 rgba(255,255,255, 0.709) , 976px 694px 0 0 rgba(255,255,255, 0.855) , 1163px 1240px 0 0 rgba(255,255,255, 0.754) , 1662px 1784px 0 0 rgba(255,255,255, 0.088) , 656px 1388px 0 0 rgba(255,255,255, 0.688) , 1190px 1100px 0 0 rgba(255,255,255, 0.769) , 33px 392px 0 0 rgba(255,255,255, 0.301) , 56px 1405px 0 0 rgba(255,255,255, 0.969) , 1491px 118px 0 0 rgba(255,255,255, 0.991) , 1216px 997px 0 0 rgba(255,255,255, 0.727) , 1617px 712px 0 0 rgba(255,255,255, 0.45) , 163px 553px 0 0 rgba(255,255,255, 0.977) , 103px 140px 0 0 rgba(255,255,255, 0.916) , 1099px 1404px 0 0 rgba(255,255,255, 0.167) , 1423px 587px 0 0 rgba(255,255,255, 0.792) , 1797px 309px 0 0 rgba(255,255,255, 0.526) , 381px 141px 0 0 rgba(255,255,255, 0.005) , 1214px 802px 0 0 rgba(255,255,255, 0.887) , 211px 829px 0 0 rgba(255,255,255, 0.72) , 1103px 1507px 0 0 rgba(255,255,255, 0.642) , 244px 1231px 0 0 rgba(255,255,255, 0.184) , 118px 1747px 0 0 rgba(255,255,255, 0.475) , 183px 1293px 0 0 rgba(255,255,255, 0.148) , 911px 1362px 0 0 rgba(255,255,255, 0.073) , 817px 457px 0 0 rgba(255,255,255, 0.459) , 756px 18px 0 0 rgba(255,255,255, 0.544) , 481px 1118px 0 0 rgba(255,255,255, 0.878) , 380px 138px 0 0 rgba(255,255,255, 0.132) , 320px 646px 0 0 rgba(255,255,255, 0.04) , 1724px 1716px 0 0 rgba(255,255,255, 0.381) , 978px 1269px 0 0 rgba(255,255,255, 0.431) , 1530px 255px 0 0 rgba(255,255,255, 0.31) , 664px 204px 0 0 rgba(255,255,255, 0.913) , 474px 703px 0 0 rgba(255,255,255, 0.832) , 1722px 1204px 0 0 rgba(255,255,255, 0.356) , 1453px 821px 0 0 rgba(255,255,255, 0.195) , 730px 1468px 0 0 rgba(255,255,255, 0.696) , 928px 1610px 0 0 rgba(255,255,255, 0.894) , 1036px 304px 0 0 rgba(255,255,255, 0.696) , 1590px 172px 0 0 rgba(255,255,255, 0.729) , 249px 1590px 0 0 rgba(255,255,255, 0.277) , 357px 81px 0 0 rgba(255,255,255, 0.526) , 726px 1261px 0 0 rgba(255,255,255, 0.149) , 643px 946px 0 0 rgba(255,255,255, 0.005) , 1263px 995px 0 0 rgba(255,255,255, 0.124) , 1564px 1107px 0 0 rgba(255,255,255, 0.789) , 388px 83px 0 0 rgba(255,255,255, 0.498) , 715px 681px 0 0 rgba(255,255,255, 0.655) , 1618px 1624px 0 0 rgba(255,255,255, 0.63) , 1423px 1576px 0 0 rgba(255,255,255, 0.52) , 564px 1786px 0 0 rgba(255,255,255, 0.482) , 1066px 735px 0 0 rgba(255,255,255, 0.276) , 714px 1179px 0 0 rgba(255,255,255, 0.395) , 967px 1006px 0 0 rgba(255,255,255, 0.923) , 1136px 1790px 0 0 rgba(255,255,255, 0.801) , 215px 1690px 0 0 rgba(255,255,255, 0.957) , 1500px 1338px 0 0 rgba(255,255,255, 0.541) , 1679px 1065px 0 0 rgba(255,255,255, 0.925) , 426px 1489px 0 0 rgba(255,255,255, 0.193) , 1273px 853px 0 0 rgba(255,255,255, 0.317) , 665px 1189px 0 0 rgba(255,255,255, 0.512) , 520px 552px 0 0 rgba(255,255,255, 0.925) , 253px 438px 0 0 rgba(255,255,255, 0.588) , 369px 1354px 0 0 rgba(255,255,255, 0.889) , 749px 205px 0 0 rgba(255,255,255, 0.243) , 820px 145px 0 0 rgba(255,255,255, 0.207) , 1739px 228px 0 0 rgba(255,255,255, 0.267) , 392px 495px 0 0 rgba(255,255,255, 0.504) , 721px 1044px 0 0 rgba(255,255,255, 0.823) , 833px 912px 0 0 rgba(255,255,255, 0.222) , 865px 1499px 0 0 rgba(255,255,255, 0.003) , 313px 756px 0 0 rgba(255,255,255, 0.727) , 439px 1187px 0 0 rgba(255,255,255, 0.572) , 6px 1238px 0 0 rgba(255,255,255, 0.676) , 1567px 11px 0 0 rgba(255,255,255, 0.701) , 1216px 757px 0 0 rgba(255,255,255, 0.87) , 916px 588px 0 0 rgba(255,255,255, 0.565) , 831px 215px 0 0 rgba(255,255,255, 0.597) , 1289px 697px 0 0 rgba(255,255,255, 0.964) , 307px 34px 0 0 rgba(255,255,255, 0.462) , 3px 1685px 0 0 rgba(255,255,255, 0.464) , 1115px 1421px 0 0 rgba(255,255,255, 0.303) , 1451px 473px 0 0 rgba(255,255,255, 0.142) , 1374px 1205px 0 0 rgba(255,255,255, 0.086) , 1564px 317px 0 0 rgba(255,255,255, 0.773) , 304px 1127px 0 0 rgba(255,255,255, 0.653) , 446px 214px 0 0 rgba(255,255,255, 0.135) , 1541px 459px 0 0 rgba(255,255,255, 0.725) , 1387px 880px 0 0 rgba(255,255,255, 0.157) , 1172px 224px 0 0 rgba(255,255,255, 0.088) , 1420px 637px 0 0 rgba(255,255,255, 0.916) , 1385px 932px 0 0 rgba(255,255,255, 0.225) , 174px 1472px 0 0 rgba(255,255,255, 0.649) , 252px 750px 0 0 rgba(255,255,255, 0.277) , 825px 1042px 0 0 rgba(255,255,255, 0.707) , 840px 703px 0 0 rgba(255,255,255, 0.948) , 1478px 1800px 0 0 rgba(255,255,255, 0.151) , 95px 1303px 0 0 rgba(255,255,255, 0.332) , 1198px 740px 0 0 rgba(255,255,255, 0.443) , 141px 312px 0 0 rgba(255,255,255, 0.04) , 291px 729px 0 0 rgba(255,255,255, 0.284) , 1209px 1506px 0 0 rgba(255,255,255, 0.741) , 1188px 307px 0 0 rgba(255,255,255, 0.141) , 958px 41px 0 0 rgba(255,255,255, 0.858) , 1311px 1484px 0 0 rgba(255,255,255, 0.097) , 846px 1153px 0 0 rgba(255,255,255, 0.862) , 1238px 1376px 0 0 rgba(255,255,255, 0.071) , 1499px 342px 0 0 rgba(255,255,255, 0.719) , 640px 833px 0 0 rgba(255,255,255, 0.966) , 712px 545px 0 0 rgba(255,255,255, 0.194) , 1655px 1542px 0 0 rgba(255,255,255, 0.82) , 616px 353px 0 0 rgba(255,255,255, 0.871) , 1591px 1631px 0 0 rgba(255,255,255, 0.61) , 1664px 591px 0 0 rgba(255,255,255, 0.35) , 934px 454px 0 0 rgba(255,255,255, 0.58) , 1175px 477px 0 0 rgba(255,255,255, 0.966) , 299px 914px 0 0 rgba(255,255,255, 0.839) , 534px 243px 0 0 rgba(255,255,255, 0.194) , 773px 1135px 0 0 rgba(255,255,255, 0.42) , 1696px 1472px 0 0 rgba(255,255,255, 0.552) , 125px 523px 0 0 rgba(255,255,255, 0.591) , 1195px 382px 0 0 rgba(255,255,255, 0.904) , 1609px 1374px 0 0 rgba(255,255,255, 0.579) , 843px 82px 0 0 rgba(255,255,255, 0.072) , 1604px 451px 0 0 rgba(255,255,255, 0.545) , 1322px 190px 0 0 rgba(255,255,255, 0.034) , 528px 228px 0 0 rgba(255,255,255, 0.146) , 1470px 1169px 0 0 rgba(255,255,255, 0.912) , 502px 1350px 0 0 rgba(255,255,255, 0.594) , 1031px 298px 0 0 rgba(255,255,255, 0.368) , 1100px 1427px 0 0 rgba(255,255,255, 0.79) , 979px 1105px 0 0 rgba(255,255,255, 0.973) , 643px 1184px 0 0 rgba(255,255,255, 0.813) , 1636px 1701px 0 0 rgba(255,255,255, 0.013) , 1004px 245px 0 0 rgba(255,255,255, 0.412) , 680px 740px 0 0 rgba(255,255,255, 0.967) , 1599px 562px 0 0 rgba(255,255,255, 0.66) , 256px 1617px 0 0 rgba(255,255,255, 0.463) , 314px 1092px 0 0 rgba(255,255,255, 0.734) , 870px 900px 0 0 rgba(255,255,255, 0.512) , 530px 60px 0 0 rgba(255,255,255, 0.198) , 1786px 896px 0 0 rgba(255,255,255, 0.392) , 636px 212px 0 0 rgba(255,255,255, 0.997) , 672px 540px 0 0 rgba(255,255,255, 0.632) , 1118px 1649px 0 0 rgba(255,255,255, 0.377) , 433px 647px 0 0 rgba(255,255,255, 0.902) , 1200px 1737px 0 0 rgba(255,255,255, 0.262) , 1258px 143px 0 0 rgba(255,255,255, 0.729) , 1603px 1364px 0 0 rgba(255,255,255, 0.192) , 66px 1756px 0 0 rgba(255,255,255, 0.681) , 946px 263px 0 0 rgba(255,255,255, 0.105) , 1216px 1082px 0 0 rgba(255,255,255, 0.287) , 6px 1143px 0 0 rgba(255,255,255, 0.017) , 1631px 126px 0 0 rgba(255,255,255, 0.449) , 357px 1565px 0 0 rgba(255,255,255, 0.163) , 1752px 261px 0 0 rgba(255,255,255, 0.423) , 1247px 1631px 0 0 rgba(255,255,255, 0.312) , 320px 671px 0 0 rgba(255,255,255, 0.695) , 1375px 596px 0 0 rgba(255,255,255, 0.856) , 1456px 1340px 0 0 rgba(255,255,255, 0.564) , 447px 1044px 0 0 rgba(255,255,255, 0.623) , 1732px 447px 0 0 rgba(255,255,255, 0.216) , 174px 1509px 0 0 rgba(255,255,255, 0.398) , 16px 861px 0 0 rgba(255,255,255, 0.904) , 878px 1296px 0 0 rgba(255,255,255, 0.205) , 1725px 1483px 0 0 rgba(255,255,255, 0.704) , 255px 48px 0 0 rgba(255,255,255, 0.7) , 610px 1669px 0 0 rgba(255,255,255, 0.865) , 1044px 1251px 0 0 rgba(255,255,255, 0.98) , 884px 862px 0 0 rgba(255,255,255, 0.198) , 986px 545px 0 0 rgba(255,255,255, 0.379) , 1620px 217px 0 0 rgba(255,255,255, 0.159) , 383px 1763px 0 0 rgba(255,255,255, 0.518) , 595px 974px 0 0 rgba(255,255,255, 0.347) , 359px 14px 0 0 rgba(255,255,255, 0.863) , 95px 1385px 0 0 rgba(255,255,255, 0.011) , 411px 1030px 0 0 rgba(255,255,255, 0.038) , 345px 789px 0 0 rgba(255,255,255, 0.771) , 421px 460px 0 0 rgba(255,255,255, 0.133) , 972px 1160px 0 0 rgba(255,255,255, 0.342) , 597px 1061px 0 0 rgba(255,255,255, 0.781) , 1017px 1092px 0 0 rgba(255,255,255, 0.437); } - .warning { background: <?= $lightColor(); ?>; display: flex; align-items: center; padding: 10px; text-align: left; justify-content: center; } - .warning svg { flex-shrink: 0; height: 32px; width: 32px; margin-right: 10px; } - .warning p { line-height: 1.4; margin: 0; } - .container svg.wave { position: absolute; bottom: -2px; left: 0; z-index: 1; } - .container .logo { margin-bottom: 1em; } - .container .logo svg { fill: hsl(<?= $hue; ?>, 20%, 26%); } - .welcome { padding-top: 4em; margin-bottom: 3em; } - .welcome small { display: block; font-size: 85%; } - .status { padding-bottom: 2em; } - .status code, .status .status-ready { display: none; } - .version { font-size: 34px; } - .check { background: <?= $darkColor(); ?>; border-radius: 20px; width: 50px; display: flex; align-items: center; justify-content: center; height: 37px; margin: 6px 8px 6px 6px; } - .check svg { fill: <?= $lightColor(); ?>; } - .status-ready { margin: 28px 0 0; } - .resources { margin: 0 auto; max-width: 1366px; padding: 2.5em 0 3.5em; } - .resources .row { margin-left: 30px; margin-right: 30px; display: flex; justify-content: space-evenly; } - .resource { padding: 0 10px; position: relative; } - .resource svg { height: 48px; width: 48px; fill: <?= $darkColor(); ?>; margin-bottom: 5px; } - .resource h2 { font-size: 18px; font-weight: normal; margin-bottom: 5px; } - .resource p { margin-top: 5px; } - .resource a { display: block; font-size: 14px; } - - @media (min-width: 768px) { - @-webkit-keyframes fade-in { 0% { opacity: 0; } 100% { opacity: 1; } } - @keyframes fade-in { 0% { opacity: 0; } 100% { opacity: 1; } } - .sf-toolbar { opacity: 0; -webkit-animation: fade-in 1s .2s forwards; animation: fade-in 1s .2s forwards; z-index: 99999; } - - .resources .row { margin-left: 50px; margin-right: 50px; } - .resource { padding: 0 30px; } - - .status { padding-bottom: 4em; } - .status code { display: inline-flex; } - .status .status-ready { display: block; } - - .resource svg { height: 64px; width: 64px; } - .resource h2 { font-size: 22px; } - .resource a { font-size: 16px; margin-top: 0; } - } - @media (min-width: 992px) { - body { font-size: 20px; } - .warning { text-align: center; } - } - </style> -</head> -<body> -<div class="wrapper"> - <div class="warning"> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" width="32"><path fill="currentColor" d="M569.517 440.013C587.975 472.007 564.806 512 527.94 512H48.054c-36.937 0-59.999-40.055-41.577-71.987L246.423 23.985c18.467-32.009 64.72-31.951 83.154 0l239.94 416.028zM288 354c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z" class=""></path></svg> - <p> - You're seeing this page because you haven't configured any homepage URL and <a href="https://symfony.com/doc/<?= $docVersion; ?>/debug-mode">debug mode</a> is enabled. - </p> - </div> - - <div class="container"> - <div class="welcome"> - <div class="logo"> - <svg xmlns="http://www.w3.org/2000/svg" width="112.165" height="112.166"><path d="M112.165 56.079c0 30.976-25.109 56.087-56.084 56.087C25.108 112.166 0 87.055 0 56.079 0 25.108 25.107 0 56.081 0c30.975 0 56.084 25.108 56.084 56.079z" style="fill: <?= $lightColor(); ?>;"/><path d="M80.603 20.75c-5.697.195-10.67 3.34-14.373 7.68-4.1 4.765-6.824 10.411-8.791 16.18-3.514-2.882-6.223-6.611-11.864-8.233-4.359-1.253-8.936-.737-13.146 2.399-1.992 1.489-3.367 3.738-4.02 5.859-1.692 5.498 1.778 10.396 3.354 12.151l3.447 3.691c.709.725 2.422 2.613 1.584 5.319-.9 2.947-4.451 4.85-8.092 3.731-1.627-.499-3.963-1.71-3.439-3.413.215-.699.715-1.225.984-1.821.244-.521.363-.907.438-1.14.665-2.169-.245-4.994-2.57-5.713-2.171-.666-4.391-.138-5.252 2.655-.977 3.174.543 8.935 8.681 11.441 9.535 2.935 17.597-2.259 18.742-9.026.721-4.239-1.195-7.392-4.701-11.441l-2.859-3.163c-1.73-1.729-2.324-4.677-.533-6.942 1.512-1.912 3.664-2.726 7.191-1.768 5.15 1.396 7.443 4.969 11.271 7.851-1.578 5.187-2.613 10.392-3.547 15.059l-.574 3.481c-2.736 14.352-4.826 22.235-10.256 26.76-1.094.779-2.658 1.943-5.014 2.027-1.238.037-1.637-.814-1.654-1.186-.027-.865.703-1.264 1.188-1.652.727-.396 1.824-1.053 1.748-3.156-.078-2.484-2.137-4.639-5.111-4.541-2.229.075-5.625 2.171-5.497 6.011.131 3.967 3.827 6.938 9.401 6.75 2.979-.102 9.633-1.312 16.188-9.105 7.631-8.935 9.766-19.175 11.372-26.671l1.793-9.897c.992.119 2.059.2 3.217.228 9.504.201 14.256-4.72 14.328-8.302.049-2.167-1.42-4.302-3.479-4.251-1.471.041-3.32 1.022-3.762 3.057-.436 1.995 3.023 3.798.32 5.553-1.92 1.242-5.361 2.116-10.209 1.407l.881-4.872c1.799-9.238 4.018-20.6 12.436-20.878.615-.029 2.857.026 2.91 1.512.014.493-.109.623-.689 1.757-.592.884-.814 1.64-.785 2.504.08 2.356 1.873 3.908 4.471 3.818 3.473-.116 4.469-3.496 4.412-5.233-.146-4.085-4.449-6.665-10.14-6.477z"/></svg> - </div> - <h1><small>Welcome to</small> Symfony <span class="version"><?= $version; ?></span></h1> - </div> - - <div class="status"> - <code> - <span class="check"> - <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg> - </span> - <span><?= $projectDir; ?></span> - </code> - <p class="status-ready">Your application is now ready and you can start working on it.</p> - </div> - - <svg style="pointer-events: none" class="wave" width="100%" height="50px" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1920 75"><defs><style>.a{fill:none}.b{clip-path:url(#a)}.c,.d {fill: <?= $lightColor(); ?>}.d{opacity:0.5;isolation:isolate;}</style><clipPath id="a"><rect class="a" width="1920" height="75"></rect></clipPath></defs><g class="b"><path class="c" d="M1963,327H-105V65A2647.49,2647.49,0,0,1,431,19c217.7,3.5,239.6,30.8,470,36,297.3,6.7,367.5-36.2,642-28a2511.41,2511.41,0,0,1,420,48"></path></g><g class="b"><path class="d" d="M-127,404H1963V44c-140.1-28-343.3-46.7-566,22-75.5,23.3-118.5,45.9-162,64-48.6,20.2-404.7,128-784,0C355.2,97.7,341.6,78.3,235,50,86.6,10.6-41.8,6.9-127,10"></path></g><g class="b"><path class="d" d="M1979,462-155,446V106C251.8,20.2,576.6,15.9,805,30c167.4,10.3,322.3,32.9,680,56,207,13.4,378,20.3,494,24"></path></g><g class="b"><path class="d" d="M1998,484H-243V100c445.8,26.8,794.2-4.1,1035-39,141-20.4,231.1-40.1,378-45,349.6-11.6,636.7,73.8,828,150"></path></g></svg> - </div> - - <div class="resources"> - <div class="row"> - <div class="resource"> - <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 11.55C9.64 9.35 6.48 8 3 8v11c3.48 0 6.64 1.35 9 3.55 2.36-2.19 5.52-3.55 9-3.55V8c-3.48 0-6.64 1.35-9 3.55zM12 8c1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3 1.34 3 3 3z"/></svg> - <h2>Documentation</h2> - <a href="https://symfony.com/doc/<?= $docVersion; ?>/index.html"> - Guides, components, references - </a> - </div> - <div class="resource"> - <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0l4.6-4.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z"/></svg> - <h2>Tutorials</h2> - <a href="https://symfony.com/doc/<?= $docVersion; ?>/page_creation.html"> - Create your first page - </a> - </div> - <div class="resource"> - <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/></svg> - <h2>Community</h2> - <a href="https://symfony.com/community"> - Connect, get help, or contribute - </a> - </div> - </div> - </div> -</div> -</body> -</html> diff --git a/lib/symfony/http-kernel/TerminableInterface.php b/lib/symfony/http-kernel/TerminableInterface.php deleted file mode 100644 index 8aa331979..000000000 --- a/lib/symfony/http-kernel/TerminableInterface.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -/** - * Terminable extends the Kernel request/response cycle with dispatching a post - * response event after sending the response and before shutting down the kernel. - * - * @author Jordi Boggiano <j.boggiano@seld.be> - * @author Pierre Minnieur <pierre.minnieur@sensiolabs.de> - */ -interface TerminableInterface -{ - /** - * Terminates a request/response cycle. - * - * Should be called after sending the response and before shutting down the kernel. - */ - public function terminate(Request $request, Response $response); -} diff --git a/lib/symfony/http-kernel/UriSigner.php b/lib/symfony/http-kernel/UriSigner.php deleted file mode 100644 index 38931ce17..000000000 --- a/lib/symfony/http-kernel/UriSigner.php +++ /dev/null @@ -1,113 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel; - -use Symfony\Component\HttpFoundation\Request; - -/** - * Signs URIs. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class UriSigner -{ - private $secret; - private $parameter; - - /** - * @param string $secret A secret - * @param string $parameter Query string parameter to use - */ - public function __construct(string $secret, string $parameter = '_hash') - { - $this->secret = $secret; - $this->parameter = $parameter; - } - - /** - * Signs a URI. - * - * The given URI is signed by adding the query string parameter - * which value depends on the URI and the secret. - * - * @return string - */ - public function sign(string $uri) - { - $url = parse_url($uri); - if (isset($url['query'])) { - parse_str($url['query'], $params); - } else { - $params = []; - } - - $uri = $this->buildUrl($url, $params); - $params[$this->parameter] = $this->computeHash($uri); - - return $this->buildUrl($url, $params); - } - - /** - * Checks that a URI contains the correct hash. - * - * @return bool - */ - public function check(string $uri) - { - $url = parse_url($uri); - if (isset($url['query'])) { - parse_str($url['query'], $params); - } else { - $params = []; - } - - if (empty($params[$this->parameter])) { - return false; - } - - $hash = $params[$this->parameter]; - unset($params[$this->parameter]); - - return hash_equals($this->computeHash($this->buildUrl($url, $params)), $hash); - } - - public function checkRequest(Request $request): bool - { - $qs = ($qs = $request->server->get('QUERY_STRING')) ? '?'.$qs : ''; - - // we cannot use $request->getUri() here as we want to work with the original URI (no query string reordering) - return $this->check($request->getSchemeAndHttpHost().$request->getBaseUrl().$request->getPathInfo().$qs); - } - - private function computeHash(string $uri): string - { - return base64_encode(hash_hmac('sha256', $uri, $this->secret, true)); - } - - private function buildUrl(array $url, array $params = []): string - { - ksort($params, \SORT_STRING); - $url['query'] = http_build_query($params, '', '&'); - - $scheme = isset($url['scheme']) ? $url['scheme'].'://' : ''; - $host = $url['host'] ?? ''; - $port = isset($url['port']) ? ':'.$url['port'] : ''; - $user = $url['user'] ?? ''; - $pass = isset($url['pass']) ? ':'.$url['pass'] : ''; - $pass = ($user || $pass) ? "$pass@" : ''; - $path = $url['path'] ?? ''; - $query = isset($url['query']) && $url['query'] ? '?'.$url['query'] : ''; - $fragment = isset($url['fragment']) ? '#'.$url['fragment'] : ''; - - return $scheme.$user.$pass.$host.$port.$path.$query.$fragment; - } -} diff --git a/lib/symfony/http-kernel/composer.json b/lib/symfony/http-kernel/composer.json deleted file mode 100644 index 09682db49..000000000 --- a/lib/symfony/http-kernel/composer.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "name": "symfony/http-kernel", - "type": "library", - "description": "Provides a structured process for converting a Request into a Response", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/event-dispatcher": "^5.0|^6.0", - "symfony/http-foundation": "^5.3.7|^6.0", - "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16", - "psr/log": "^1|^2" - }, - "require-dev": { - "symfony/browser-kit": "^5.4|^6.0", - "symfony/config": "^5.0|^6.0", - "symfony/console": "^4.4|^5.0|^6.0", - "symfony/css-selector": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^5.3|^6.0", - "symfony/dom-crawler": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/finder": "^4.4|^5.0|^6.0", - "symfony/http-client-contracts": "^1.1|^2|^3", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/routing": "^4.4|^5.0|^6.0", - "symfony/stopwatch": "^4.4|^5.0|^6.0", - "symfony/translation": "^4.4|^5.0|^6.0", - "symfony/translation-contracts": "^1.1|^2|^3", - "psr/cache": "^1.0|^2.0|^3.0", - "twig/twig": "^2.13|^3.0.4" - }, - "provide": { - "psr/log-implementation": "1.0|2.0" - }, - "conflict": { - "symfony/browser-kit": "<5.4", - "symfony/cache": "<5.0", - "symfony/config": "<5.0", - "symfony/console": "<4.4", - "symfony/form": "<5.0", - "symfony/dependency-injection": "<5.3", - "symfony/doctrine-bridge": "<5.0", - "symfony/http-client": "<5.0", - "symfony/mailer": "<5.0", - "symfony/messenger": "<5.0", - "symfony/translation": "<5.0", - "symfony/twig-bridge": "<5.0", - "symfony/validator": "<5.0", - "twig/twig": "<2.13" - }, - "suggest": { - "symfony/browser-kit": "", - "symfony/config": "", - "symfony/console": "", - "symfony/dependency-injection": "" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\HttpKernel\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/lib/symfony/options-resolver/CHANGELOG.md b/lib/symfony/options-resolver/CHANGELOG.md deleted file mode 100644 index 84c45946a..000000000 --- a/lib/symfony/options-resolver/CHANGELOG.md +++ /dev/null @@ -1,81 +0,0 @@ -CHANGELOG -========= - -5.3 ---- - - * Add prototype definition for nested options - -5.1.0 ------ - - * added fluent configuration of options using `OptionResolver::define()` - * added `setInfo()` and `getInfo()` methods - * updated the signature of method `OptionsResolver::setDeprecated()` to `OptionsResolver::setDeprecation(string $option, string $package, string $version, $message)` - * deprecated `OptionsResolverIntrospector::getDeprecationMessage()`, use `OptionsResolverIntrospector::getDeprecation()` instead - -5.0.0 ------ - - * added argument `$triggerDeprecation` to `OptionsResolver::offsetGet()` - -4.3.0 ------ - - * added `OptionsResolver::addNormalizer` method - -4.2.0 ------ - - * added support for nested options definition - * added `setDeprecated` and `isDeprecated` methods - -3.4.0 ------ - - * added `OptionsResolverIntrospector` to inspect options definitions inside an `OptionsResolver` instance - * added array of types support in allowed types (e.g int[]) - -2.6.0 ------ - - * deprecated OptionsResolverInterface - * [BC BREAK] removed "array" type hint from OptionsResolverInterface methods - setRequired(), setAllowedValues(), addAllowedValues(), setAllowedTypes() and - addAllowedTypes() - * added OptionsResolver::setDefault() - * added OptionsResolver::hasDefault() - * added OptionsResolver::setNormalizer() - * added OptionsResolver::isRequired() - * added OptionsResolver::getRequiredOptions() - * added OptionsResolver::isMissing() - * added OptionsResolver::getMissingOptions() - * added OptionsResolver::setDefined() - * added OptionsResolver::isDefined() - * added OptionsResolver::getDefinedOptions() - * added OptionsResolver::remove() - * added OptionsResolver::clear() - * deprecated OptionsResolver::replaceDefaults() - * deprecated OptionsResolver::setOptional() in favor of setDefined() - * deprecated OptionsResolver::isKnown() in favor of isDefined() - * [BC BREAK] OptionsResolver::isRequired() returns true now if a required - option has a default value set - * [BC BREAK] merged Options into OptionsResolver and turned Options into an - interface - * deprecated Options::overload() (now in OptionsResolver) - * deprecated Options::set() (now in OptionsResolver) - * deprecated Options::get() (now in OptionsResolver) - * deprecated Options::has() (now in OptionsResolver) - * deprecated Options::replace() (now in OptionsResolver) - * [BC BREAK] Options::get() (now in OptionsResolver) can only be used within - lazy option/normalizer closures now - * [BC BREAK] removed Traversable interface from Options since using within - lazy option/normalizer closures resulted in exceptions - * [BC BREAK] removed Options::all() since using within lazy option/normalizer - closures resulted in exceptions - * [BC BREAK] OptionDefinitionException now extends LogicException instead of - RuntimeException - * [BC BREAK] normalizers are not executed anymore for unset options - * normalizers are executed after validating the options now - * [BC BREAK] an UndefinedOptionsException is now thrown instead of an - InvalidOptionsException when non-existing options are passed diff --git a/lib/symfony/options-resolver/Debug/OptionsResolverIntrospector.php b/lib/symfony/options-resolver/Debug/OptionsResolverIntrospector.php deleted file mode 100644 index 95909f32e..000000000 --- a/lib/symfony/options-resolver/Debug/OptionsResolverIntrospector.php +++ /dev/null @@ -1,120 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\OptionsResolver\Debug; - -use Symfony\Component\OptionsResolver\Exception\NoConfigurationException; -use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException; -use Symfony\Component\OptionsResolver\OptionsResolver; - -/** - * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> - * - * @final - */ -class OptionsResolverIntrospector -{ - private $get; - - public function __construct(OptionsResolver $optionsResolver) - { - $this->get = \Closure::bind(function ($property, $option, $message) { - /** @var OptionsResolver $this */ - if (!$this->isDefined($option)) { - throw new UndefinedOptionsException(sprintf('The option "%s" does not exist.', $option)); - } - - if (!\array_key_exists($option, $this->{$property})) { - throw new NoConfigurationException($message); - } - - return $this->{$property}[$option]; - }, $optionsResolver, $optionsResolver); - } - - /** - * @return mixed - * - * @throws NoConfigurationException on no configured value - */ - public function getDefault(string $option) - { - return ($this->get)('defaults', $option, sprintf('No default value was set for the "%s" option.', $option)); - } - - /** - * @return \Closure[] - * - * @throws NoConfigurationException on no configured closures - */ - public function getLazyClosures(string $option): array - { - return ($this->get)('lazy', $option, sprintf('No lazy closures were set for the "%s" option.', $option)); - } - - /** - * @return string[] - * - * @throws NoConfigurationException on no configured types - */ - public function getAllowedTypes(string $option): array - { - return ($this->get)('allowedTypes', $option, sprintf('No allowed types were set for the "%s" option.', $option)); - } - - /** - * @return mixed[] - * - * @throws NoConfigurationException on no configured values - */ - public function getAllowedValues(string $option): array - { - return ($this->get)('allowedValues', $option, sprintf('No allowed values were set for the "%s" option.', $option)); - } - - /** - * @throws NoConfigurationException on no configured normalizer - */ - public function getNormalizer(string $option): \Closure - { - return current($this->getNormalizers($option)); - } - - /** - * @throws NoConfigurationException when no normalizer is configured - */ - public function getNormalizers(string $option): array - { - return ($this->get)('normalizers', $option, sprintf('No normalizer was set for the "%s" option.', $option)); - } - - /** - * @return string|\Closure - * - * @throws NoConfigurationException on no configured deprecation - * - * @deprecated since Symfony 5.1, use "getDeprecation()" instead. - */ - public function getDeprecationMessage(string $option) - { - trigger_deprecation('symfony/options-resolver', '5.1', 'The "%s()" method is deprecated, use "getDeprecation()" instead.', __METHOD__); - - return $this->getDeprecation($option)['message']; - } - - /** - * @throws NoConfigurationException on no configured deprecation - */ - public function getDeprecation(string $option): array - { - return ($this->get)('deprecated', $option, sprintf('No deprecation was set for the "%s" option.', $option)); - } -} diff --git a/lib/symfony/options-resolver/Exception/AccessException.php b/lib/symfony/options-resolver/Exception/AccessException.php deleted file mode 100644 index c12b68064..000000000 --- a/lib/symfony/options-resolver/Exception/AccessException.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\OptionsResolver\Exception; - -/** - * Thrown when trying to read an option outside of or write it inside of - * {@link \Symfony\Component\OptionsResolver\Options::resolve()}. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class AccessException extends \LogicException implements ExceptionInterface -{ -} diff --git a/lib/symfony/options-resolver/Exception/ExceptionInterface.php b/lib/symfony/options-resolver/Exception/ExceptionInterface.php deleted file mode 100644 index ea99d050e..000000000 --- a/lib/symfony/options-resolver/Exception/ExceptionInterface.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\OptionsResolver\Exception; - -/** - * Marker interface for all exceptions thrown by the OptionsResolver component. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface ExceptionInterface extends \Throwable -{ -} diff --git a/lib/symfony/options-resolver/Exception/InvalidArgumentException.php b/lib/symfony/options-resolver/Exception/InvalidArgumentException.php deleted file mode 100644 index 6d421d68b..000000000 --- a/lib/symfony/options-resolver/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\OptionsResolver\Exception; - -/** - * Thrown when an argument is invalid. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/lib/symfony/options-resolver/Exception/InvalidOptionsException.php b/lib/symfony/options-resolver/Exception/InvalidOptionsException.php deleted file mode 100644 index 6fd4f125f..000000000 --- a/lib/symfony/options-resolver/Exception/InvalidOptionsException.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\OptionsResolver\Exception; - -/** - * Thrown when the value of an option does not match its validation rules. - * - * You should make sure a valid value is passed to the option. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class InvalidOptionsException extends InvalidArgumentException -{ -} diff --git a/lib/symfony/options-resolver/Exception/MissingOptionsException.php b/lib/symfony/options-resolver/Exception/MissingOptionsException.php deleted file mode 100644 index faa487f16..000000000 --- a/lib/symfony/options-resolver/Exception/MissingOptionsException.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\OptionsResolver\Exception; - -/** - * Exception thrown when a required option is missing. - * - * Add the option to the passed options array. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class MissingOptionsException extends InvalidArgumentException -{ -} diff --git a/lib/symfony/options-resolver/Exception/NoConfigurationException.php b/lib/symfony/options-resolver/Exception/NoConfigurationException.php deleted file mode 100644 index 6693ec14d..000000000 --- a/lib/symfony/options-resolver/Exception/NoConfigurationException.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\OptionsResolver\Exception; - -use Symfony\Component\OptionsResolver\Debug\OptionsResolverIntrospector; - -/** - * Thrown when trying to introspect an option definition property - * for which no value was configured inside the OptionsResolver instance. - * - * @see OptionsResolverIntrospector - * - * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> - */ -class NoConfigurationException extends \RuntimeException implements ExceptionInterface -{ -} diff --git a/lib/symfony/options-resolver/Exception/NoSuchOptionException.php b/lib/symfony/options-resolver/Exception/NoSuchOptionException.php deleted file mode 100644 index 4c3280f4c..000000000 --- a/lib/symfony/options-resolver/Exception/NoSuchOptionException.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\OptionsResolver\Exception; - -/** - * Thrown when trying to read an option that has no value set. - * - * When accessing optional options from within a lazy option or normalizer you should first - * check whether the optional option is set. You can do this with `isset($options['optional'])`. - * In contrast to the {@link UndefinedOptionsException}, this is a runtime exception that can - * occur when evaluating lazy options. - * - * @author Tobias Schultze <http://tobion.de> - */ -class NoSuchOptionException extends \OutOfBoundsException implements ExceptionInterface -{ -} diff --git a/lib/symfony/options-resolver/Exception/OptionDefinitionException.php b/lib/symfony/options-resolver/Exception/OptionDefinitionException.php deleted file mode 100644 index e8e339d44..000000000 --- a/lib/symfony/options-resolver/Exception/OptionDefinitionException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\OptionsResolver\Exception; - -/** - * Thrown when two lazy options have a cyclic dependency. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class OptionDefinitionException extends \LogicException implements ExceptionInterface -{ -} diff --git a/lib/symfony/options-resolver/Exception/UndefinedOptionsException.php b/lib/symfony/options-resolver/Exception/UndefinedOptionsException.php deleted file mode 100644 index 6ca3fce47..000000000 --- a/lib/symfony/options-resolver/Exception/UndefinedOptionsException.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\OptionsResolver\Exception; - -/** - * Exception thrown when an undefined option is passed. - * - * You should remove the options in question from your code or define them - * beforehand. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class UndefinedOptionsException extends InvalidArgumentException -{ -} diff --git a/lib/symfony/options-resolver/LICENSE b/lib/symfony/options-resolver/LICENSE deleted file mode 100644 index 0138f8f07..000000000 --- a/lib/symfony/options-resolver/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-present Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/lib/symfony/options-resolver/OptionConfigurator.php b/lib/symfony/options-resolver/OptionConfigurator.php deleted file mode 100644 index 62f03d064..000000000 --- a/lib/symfony/options-resolver/OptionConfigurator.php +++ /dev/null @@ -1,139 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\OptionsResolver; - -use Symfony\Component\OptionsResolver\Exception\AccessException; - -final class OptionConfigurator -{ - private $name; - private $resolver; - - public function __construct(string $name, OptionsResolver $resolver) - { - $this->name = $name; - $this->resolver = $resolver; - $this->resolver->setDefined($name); - } - - /** - * Adds allowed types for this option. - * - * @return $this - * - * @throws AccessException If called from a lazy option or normalizer - */ - public function allowedTypes(string ...$types): self - { - $this->resolver->setAllowedTypes($this->name, $types); - - return $this; - } - - /** - * Sets allowed values for this option. - * - * @param mixed ...$values One or more acceptable values/closures - * - * @return $this - * - * @throws AccessException If called from a lazy option or normalizer - */ - public function allowedValues(...$values): self - { - $this->resolver->setAllowedValues($this->name, $values); - - return $this; - } - - /** - * Sets the default value for this option. - * - * @param mixed $value The default value of the option - * - * @return $this - * - * @throws AccessException If called from a lazy option or normalizer - */ - public function default($value): self - { - $this->resolver->setDefault($this->name, $value); - - return $this; - } - - /** - * Defines an option configurator with the given name. - */ - public function define(string $option): self - { - return $this->resolver->define($option); - } - - /** - * Marks this option as deprecated. - * - * @param string $package The name of the composer package that is triggering the deprecation - * @param string $version The version of the package that introduced the deprecation - * @param string|\Closure $message The deprecation message to use - * - * @return $this - */ - public function deprecated(string $package, string $version, $message = 'The option "%name%" is deprecated.'): self - { - $this->resolver->setDeprecated($this->name, $package, $version, $message); - - return $this; - } - - /** - * Sets the normalizer for this option. - * - * @return $this - * - * @throws AccessException If called from a lazy option or normalizer - */ - public function normalize(\Closure $normalizer): self - { - $this->resolver->setNormalizer($this->name, $normalizer); - - return $this; - } - - /** - * Marks this option as required. - * - * @return $this - * - * @throws AccessException If called from a lazy option or normalizer - */ - public function required(): self - { - $this->resolver->setRequired($this->name); - - return $this; - } - - /** - * Sets an info message for an option. - * - * @return $this - * - * @throws AccessException If called from a lazy option or normalizer - */ - public function info(string $info): self - { - $this->resolver->setInfo($this->name, $info); - - return $this; - } -} diff --git a/lib/symfony/options-resolver/Options.php b/lib/symfony/options-resolver/Options.php deleted file mode 100644 index d444ec423..000000000 --- a/lib/symfony/options-resolver/Options.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\OptionsResolver; - -/** - * Contains resolved option values. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * @author Tobias Schultze <http://tobion.de> - */ -interface Options extends \ArrayAccess, \Countable -{ -} diff --git a/lib/symfony/options-resolver/OptionsResolver.php b/lib/symfony/options-resolver/OptionsResolver.php deleted file mode 100644 index 3db291f99..000000000 --- a/lib/symfony/options-resolver/OptionsResolver.php +++ /dev/null @@ -1,1347 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\OptionsResolver; - -use Symfony\Component\OptionsResolver\Exception\AccessException; -use Symfony\Component\OptionsResolver\Exception\InvalidArgumentException; -use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; -use Symfony\Component\OptionsResolver\Exception\MissingOptionsException; -use Symfony\Component\OptionsResolver\Exception\NoSuchOptionException; -use Symfony\Component\OptionsResolver\Exception\OptionDefinitionException; -use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException; - -/** - * Validates options and merges them with default values. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * @author Tobias Schultze <http://tobion.de> - */ -class OptionsResolver implements Options -{ - private const VALIDATION_FUNCTIONS = [ - 'bool' => 'is_bool', - 'boolean' => 'is_bool', - 'int' => 'is_int', - 'integer' => 'is_int', - 'long' => 'is_int', - 'float' => 'is_float', - 'double' => 'is_float', - 'real' => 'is_float', - 'numeric' => 'is_numeric', - 'string' => 'is_string', - 'scalar' => 'is_scalar', - 'array' => 'is_array', - 'iterable' => 'is_iterable', - 'countable' => 'is_countable', - 'callable' => 'is_callable', - 'object' => 'is_object', - 'resource' => 'is_resource', - ]; - - /** - * The names of all defined options. - */ - private $defined = []; - - /** - * The default option values. - */ - private $defaults = []; - - /** - * A list of closure for nested options. - * - * @var \Closure[][] - */ - private $nested = []; - - /** - * The names of required options. - */ - private $required = []; - - /** - * The resolved option values. - */ - private $resolved = []; - - /** - * A list of normalizer closures. - * - * @var \Closure[][] - */ - private $normalizers = []; - - /** - * A list of accepted values for each option. - */ - private $allowedValues = []; - - /** - * A list of accepted types for each option. - */ - private $allowedTypes = []; - - /** - * A list of info messages for each option. - */ - private $info = []; - - /** - * A list of closures for evaluating lazy options. - */ - private $lazy = []; - - /** - * A list of lazy options whose closure is currently being called. - * - * This list helps detecting circular dependencies between lazy options. - */ - private $calling = []; - - /** - * A list of deprecated options. - */ - private $deprecated = []; - - /** - * The list of options provided by the user. - */ - private $given = []; - - /** - * Whether the instance is locked for reading. - * - * Once locked, the options cannot be changed anymore. This is - * necessary in order to avoid inconsistencies during the resolving - * process. If any option is changed after being read, all evaluated - * lazy options that depend on this option would become invalid. - */ - private $locked = false; - - private $parentsOptions = []; - - /** - * Whether the whole options definition is marked as array prototype. - */ - private $prototype; - - /** - * The prototype array's index that is being read. - */ - private $prototypeIndex; - - /** - * Sets the default value of a given option. - * - * If the default value should be set based on other options, you can pass - * a closure with the following signature: - * - * function (Options $options) { - * // ... - * } - * - * The closure will be evaluated when {@link resolve()} is called. The - * closure has access to the resolved values of other options through the - * passed {@link Options} instance: - * - * function (Options $options) { - * if (isset($options['port'])) { - * // ... - * } - * } - * - * If you want to access the previously set default value, add a second - * argument to the closure's signature: - * - * $options->setDefault('name', 'Default Name'); - * - * $options->setDefault('name', function (Options $options, $previousValue) { - * // 'Default Name' === $previousValue - * }); - * - * This is mostly useful if the configuration of the {@link Options} object - * is spread across different locations of your code, such as base and - * sub-classes. - * - * If you want to define nested options, you can pass a closure with the - * following signature: - * - * $options->setDefault('database', function (OptionsResolver $resolver) { - * $resolver->setDefined(['dbname', 'host', 'port', 'user', 'pass']); - * } - * - * To get access to the parent options, add a second argument to the closure's - * signature: - * - * function (OptionsResolver $resolver, Options $parent) { - * // 'default' === $parent['connection'] - * } - * - * @param string $option The name of the option - * @param mixed $value The default value of the option - * - * @return $this - * - * @throws AccessException If called from a lazy option or normalizer - */ - public function setDefault(string $option, $value) - { - // Setting is not possible once resolving starts, because then lazy - // options could manipulate the state of the object, leading to - // inconsistent results. - if ($this->locked) { - throw new AccessException('Default values cannot be set from a lazy option or normalizer.'); - } - - // If an option is a closure that should be evaluated lazily, store it - // in the "lazy" property. - if ($value instanceof \Closure) { - $reflClosure = new \ReflectionFunction($value); - $params = $reflClosure->getParameters(); - - if (isset($params[0]) && Options::class === $this->getParameterClassName($params[0])) { - // Initialize the option if no previous value exists - if (!isset($this->defaults[$option])) { - $this->defaults[$option] = null; - } - - // Ignore previous lazy options if the closure has no second parameter - if (!isset($this->lazy[$option]) || !isset($params[1])) { - $this->lazy[$option] = []; - } - - // Store closure for later evaluation - $this->lazy[$option][] = $value; - $this->defined[$option] = true; - - // Make sure the option is processed and is not nested anymore - unset($this->resolved[$option], $this->nested[$option]); - - return $this; - } - - if (isset($params[0]) && null !== ($type = $params[0]->getType()) && self::class === $type->getName() && (!isset($params[1]) || (($type = $params[1]->getType()) instanceof \ReflectionNamedType && Options::class === $type->getName()))) { - // Store closure for later evaluation - $this->nested[$option][] = $value; - $this->defaults[$option] = []; - $this->defined[$option] = true; - - // Make sure the option is processed and is not lazy anymore - unset($this->resolved[$option], $this->lazy[$option]); - - return $this; - } - } - - // This option is not lazy nor nested anymore - unset($this->lazy[$option], $this->nested[$option]); - - // Yet undefined options can be marked as resolved, because we only need - // to resolve options with lazy closures, normalizers or validation - // rules, none of which can exist for undefined options - // If the option was resolved before, update the resolved value - if (!isset($this->defined[$option]) || \array_key_exists($option, $this->resolved)) { - $this->resolved[$option] = $value; - } - - $this->defaults[$option] = $value; - $this->defined[$option] = true; - - return $this; - } - - /** - * @return $this - * - * @throws AccessException If called from a lazy option or normalizer - */ - public function setDefaults(array $defaults) - { - foreach ($defaults as $option => $value) { - $this->setDefault($option, $value); - } - - return $this; - } - - /** - * Returns whether a default value is set for an option. - * - * Returns true if {@link setDefault()} was called for this option. - * An option is also considered set if it was set to null. - * - * @return bool - */ - public function hasDefault(string $option) - { - return \array_key_exists($option, $this->defaults); - } - - /** - * Marks one or more options as required. - * - * @param string|string[] $optionNames One or more option names - * - * @return $this - * - * @throws AccessException If called from a lazy option or normalizer - */ - public function setRequired($optionNames) - { - if ($this->locked) { - throw new AccessException('Options cannot be made required from a lazy option or normalizer.'); - } - - foreach ((array) $optionNames as $option) { - $this->defined[$option] = true; - $this->required[$option] = true; - } - - return $this; - } - - /** - * Returns whether an option is required. - * - * An option is required if it was passed to {@link setRequired()}. - * - * @return bool - */ - public function isRequired(string $option) - { - return isset($this->required[$option]); - } - - /** - * Returns the names of all required options. - * - * @return string[] - * - * @see isRequired() - */ - public function getRequiredOptions() - { - return array_keys($this->required); - } - - /** - * Returns whether an option is missing a default value. - * - * An option is missing if it was passed to {@link setRequired()}, but not - * to {@link setDefault()}. This option must be passed explicitly to - * {@link resolve()}, otherwise an exception will be thrown. - * - * @return bool - */ - public function isMissing(string $option) - { - return isset($this->required[$option]) && !\array_key_exists($option, $this->defaults); - } - - /** - * Returns the names of all options missing a default value. - * - * @return string[] - */ - public function getMissingOptions() - { - return array_keys(array_diff_key($this->required, $this->defaults)); - } - - /** - * Defines a valid option name. - * - * Defines an option name without setting a default value. The option will - * be accepted when passed to {@link resolve()}. When not passed, the - * option will not be included in the resolved options. - * - * @param string|string[] $optionNames One or more option names - * - * @return $this - * - * @throws AccessException If called from a lazy option or normalizer - */ - public function setDefined($optionNames) - { - if ($this->locked) { - throw new AccessException('Options cannot be defined from a lazy option or normalizer.'); - } - - foreach ((array) $optionNames as $option) { - $this->defined[$option] = true; - } - - return $this; - } - - /** - * Returns whether an option is defined. - * - * Returns true for any option passed to {@link setDefault()}, - * {@link setRequired()} or {@link setDefined()}. - * - * @return bool - */ - public function isDefined(string $option) - { - return isset($this->defined[$option]); - } - - /** - * Returns the names of all defined options. - * - * @return string[] - * - * @see isDefined() - */ - public function getDefinedOptions() - { - return array_keys($this->defined); - } - - public function isNested(string $option): bool - { - return isset($this->nested[$option]); - } - - /** - * Deprecates an option, allowed types or values. - * - * Instead of passing the message, you may also pass a closure with the - * following signature: - * - * function (Options $options, $value): string { - * // ... - * } - * - * The closure receives the value as argument and should return a string. - * Return an empty string to ignore the option deprecation. - * - * The closure is invoked when {@link resolve()} is called. The parameter - * passed to the closure is the value of the option after validating it - * and before normalizing it. - * - * @param string $package The name of the composer package that is triggering the deprecation - * @param string $version The version of the package that introduced the deprecation - * @param string|\Closure $message The deprecation message to use - * - * @return $this - */ - public function setDeprecated(string $option/* , string $package, string $version, $message = 'The option "%name%" is deprecated.' */): self - { - if ($this->locked) { - throw new AccessException('Options cannot be deprecated from a lazy option or normalizer.'); - } - - if (!isset($this->defined[$option])) { - throw new UndefinedOptionsException(sprintf('The option "%s" does not exist, defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined)))); - } - - $args = \func_get_args(); - - if (\func_num_args() < 3) { - trigger_deprecation('symfony/options-resolver', '5.1', 'The signature of method "%s()" requires 2 new arguments: "string $package, string $version", not defining them is deprecated.', __METHOD__); - - $message = $args[1] ?? 'The option "%name%" is deprecated.'; - $package = $version = ''; - } else { - $package = $args[1]; - $version = $args[2]; - $message = $args[3] ?? 'The option "%name%" is deprecated.'; - } - - if (!\is_string($message) && !$message instanceof \Closure) { - throw new InvalidArgumentException(sprintf('Invalid type for deprecation message argument, expected string or \Closure, but got "%s".', get_debug_type($message))); - } - - // ignore if empty string - if ('' === $message) { - return $this; - } - - $this->deprecated[$option] = [ - 'package' => $package, - 'version' => $version, - 'message' => $message, - ]; - - // Make sure the option is processed - unset($this->resolved[$option]); - - return $this; - } - - public function isDeprecated(string $option): bool - { - return isset($this->deprecated[$option]); - } - - /** - * Sets the normalizer for an option. - * - * The normalizer should be a closure with the following signature: - * - * function (Options $options, $value) { - * // ... - * } - * - * The closure is invoked when {@link resolve()} is called. The closure - * has access to the resolved values of other options through the passed - * {@link Options} instance. - * - * The second parameter passed to the closure is the value of - * the option. - * - * The resolved option value is set to the return value of the closure. - * - * @return $this - * - * @throws UndefinedOptionsException If the option is undefined - * @throws AccessException If called from a lazy option or normalizer - */ - public function setNormalizer(string $option, \Closure $normalizer) - { - if ($this->locked) { - throw new AccessException('Normalizers cannot be set from a lazy option or normalizer.'); - } - - if (!isset($this->defined[$option])) { - throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined)))); - } - - $this->normalizers[$option] = [$normalizer]; - - // Make sure the option is processed - unset($this->resolved[$option]); - - return $this; - } - - /** - * Adds a normalizer for an option. - * - * The normalizer should be a closure with the following signature: - * - * function (Options $options, $value): mixed { - * // ... - * } - * - * The closure is invoked when {@link resolve()} is called. The closure - * has access to the resolved values of other options through the passed - * {@link Options} instance. - * - * The second parameter passed to the closure is the value of - * the option. - * - * The resolved option value is set to the return value of the closure. - * - * @return $this - * - * @throws UndefinedOptionsException If the option is undefined - * @throws AccessException If called from a lazy option or normalizer - */ - public function addNormalizer(string $option, \Closure $normalizer, bool $forcePrepend = false): self - { - if ($this->locked) { - throw new AccessException('Normalizers cannot be set from a lazy option or normalizer.'); - } - - if (!isset($this->defined[$option])) { - throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined)))); - } - - if ($forcePrepend) { - $this->normalizers[$option] = $this->normalizers[$option] ?? []; - array_unshift($this->normalizers[$option], $normalizer); - } else { - $this->normalizers[$option][] = $normalizer; - } - - // Make sure the option is processed - unset($this->resolved[$option]); - - return $this; - } - - /** - * Sets allowed values for an option. - * - * Instead of passing values, you may also pass a closures with the - * following signature: - * - * function ($value) { - * // return true or false - * } - * - * The closure receives the value as argument and should return true to - * accept the value and false to reject the value. - * - * @param string $option The option name - * @param mixed $allowedValues One or more acceptable values/closures - * - * @return $this - * - * @throws UndefinedOptionsException If the option is undefined - * @throws AccessException If called from a lazy option or normalizer - */ - public function setAllowedValues(string $option, $allowedValues) - { - if ($this->locked) { - throw new AccessException('Allowed values cannot be set from a lazy option or normalizer.'); - } - - if (!isset($this->defined[$option])) { - throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined)))); - } - - $this->allowedValues[$option] = \is_array($allowedValues) ? $allowedValues : [$allowedValues]; - - // Make sure the option is processed - unset($this->resolved[$option]); - - return $this; - } - - /** - * Adds allowed values for an option. - * - * The values are merged with the allowed values defined previously. - * - * Instead of passing values, you may also pass a closures with the - * following signature: - * - * function ($value) { - * // return true or false - * } - * - * The closure receives the value as argument and should return true to - * accept the value and false to reject the value. - * - * @param string $option The option name - * @param mixed $allowedValues One or more acceptable values/closures - * - * @return $this - * - * @throws UndefinedOptionsException If the option is undefined - * @throws AccessException If called from a lazy option or normalizer - */ - public function addAllowedValues(string $option, $allowedValues) - { - if ($this->locked) { - throw new AccessException('Allowed values cannot be added from a lazy option or normalizer.'); - } - - if (!isset($this->defined[$option])) { - throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined)))); - } - - if (!\is_array($allowedValues)) { - $allowedValues = [$allowedValues]; - } - - if (!isset($this->allowedValues[$option])) { - $this->allowedValues[$option] = $allowedValues; - } else { - $this->allowedValues[$option] = array_merge($this->allowedValues[$option], $allowedValues); - } - - // Make sure the option is processed - unset($this->resolved[$option]); - - return $this; - } - - /** - * Sets allowed types for an option. - * - * Any type for which a corresponding is_<type>() function exists is - * acceptable. Additionally, fully-qualified class or interface names may - * be passed. - * - * @param string|string[] $allowedTypes One or more accepted types - * - * @return $this - * - * @throws UndefinedOptionsException If the option is undefined - * @throws AccessException If called from a lazy option or normalizer - */ - public function setAllowedTypes(string $option, $allowedTypes) - { - if ($this->locked) { - throw new AccessException('Allowed types cannot be set from a lazy option or normalizer.'); - } - - if (!isset($this->defined[$option])) { - throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined)))); - } - - $this->allowedTypes[$option] = (array) $allowedTypes; - - // Make sure the option is processed - unset($this->resolved[$option]); - - return $this; - } - - /** - * Adds allowed types for an option. - * - * The types are merged with the allowed types defined previously. - * - * Any type for which a corresponding is_<type>() function exists is - * acceptable. Additionally, fully-qualified class or interface names may - * be passed. - * - * @param string|string[] $allowedTypes One or more accepted types - * - * @return $this - * - * @throws UndefinedOptionsException If the option is undefined - * @throws AccessException If called from a lazy option or normalizer - */ - public function addAllowedTypes(string $option, $allowedTypes) - { - if ($this->locked) { - throw new AccessException('Allowed types cannot be added from a lazy option or normalizer.'); - } - - if (!isset($this->defined[$option])) { - throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined)))); - } - - if (!isset($this->allowedTypes[$option])) { - $this->allowedTypes[$option] = (array) $allowedTypes; - } else { - $this->allowedTypes[$option] = array_merge($this->allowedTypes[$option], (array) $allowedTypes); - } - - // Make sure the option is processed - unset($this->resolved[$option]); - - return $this; - } - - /** - * Defines an option configurator with the given name. - */ - public function define(string $option): OptionConfigurator - { - if (isset($this->defined[$option])) { - throw new OptionDefinitionException(sprintf('The option "%s" is already defined.', $option)); - } - - return new OptionConfigurator($option, $this); - } - - /** - * Sets an info message for an option. - * - * @return $this - * - * @throws UndefinedOptionsException If the option is undefined - * @throws AccessException If called from a lazy option or normalizer - */ - public function setInfo(string $option, string $info): self - { - if ($this->locked) { - throw new AccessException('The Info message cannot be set from a lazy option or normalizer.'); - } - - if (!isset($this->defined[$option])) { - throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined)))); - } - - $this->info[$option] = $info; - - return $this; - } - - /** - * Gets the info message for an option. - */ - public function getInfo(string $option): ?string - { - if (!isset($this->defined[$option])) { - throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined)))); - } - - return $this->info[$option] ?? null; - } - - /** - * Marks the whole options definition as array prototype. - * - * @return $this - * - * @throws AccessException If called from a lazy option, a normalizer or a root definition - */ - public function setPrototype(bool $prototype): self - { - if ($this->locked) { - throw new AccessException('The prototype property cannot be set from a lazy option or normalizer.'); - } - - if (null === $this->prototype && $prototype) { - throw new AccessException('The prototype property cannot be set from a root definition.'); - } - - $this->prototype = $prototype; - - return $this; - } - - public function isPrototype(): bool - { - return $this->prototype ?? false; - } - - /** - * Removes the option with the given name. - * - * Undefined options are ignored. - * - * @param string|string[] $optionNames One or more option names - * - * @return $this - * - * @throws AccessException If called from a lazy option or normalizer - */ - public function remove($optionNames) - { - if ($this->locked) { - throw new AccessException('Options cannot be removed from a lazy option or normalizer.'); - } - - foreach ((array) $optionNames as $option) { - unset($this->defined[$option], $this->defaults[$option], $this->required[$option], $this->resolved[$option]); - unset($this->lazy[$option], $this->normalizers[$option], $this->allowedTypes[$option], $this->allowedValues[$option], $this->info[$option]); - } - - return $this; - } - - /** - * Removes all options. - * - * @return $this - * - * @throws AccessException If called from a lazy option or normalizer - */ - public function clear() - { - if ($this->locked) { - throw new AccessException('Options cannot be cleared from a lazy option or normalizer.'); - } - - $this->defined = []; - $this->defaults = []; - $this->nested = []; - $this->required = []; - $this->resolved = []; - $this->lazy = []; - $this->normalizers = []; - $this->allowedTypes = []; - $this->allowedValues = []; - $this->deprecated = []; - $this->info = []; - - return $this; - } - - /** - * Merges options with the default values stored in the container and - * validates them. - * - * Exceptions are thrown if: - * - * - Undefined options are passed; - * - Required options are missing; - * - Options have invalid types; - * - Options have invalid values. - * - * @return array - * - * @throws UndefinedOptionsException If an option name is undefined - * @throws InvalidOptionsException If an option doesn't fulfill the - * specified validation rules - * @throws MissingOptionsException If a required option is missing - * @throws OptionDefinitionException If there is a cyclic dependency between - * lazy options and/or normalizers - * @throws NoSuchOptionException If a lazy option reads an unavailable option - * @throws AccessException If called from a lazy option or normalizer - */ - public function resolve(array $options = []) - { - if ($this->locked) { - throw new AccessException('Options cannot be resolved from a lazy option or normalizer.'); - } - - // Allow this method to be called multiple times - $clone = clone $this; - - // Make sure that no unknown options are passed - $diff = array_diff_key($options, $clone->defined); - - if (\count($diff) > 0) { - ksort($clone->defined); - ksort($diff); - - throw new UndefinedOptionsException(sprintf((\count($diff) > 1 ? 'The options "%s" do not exist.' : 'The option "%s" does not exist.').' Defined options are: "%s".', $this->formatOptions(array_keys($diff)), implode('", "', array_keys($clone->defined)))); - } - - // Override options set by the user - foreach ($options as $option => $value) { - $clone->given[$option] = true; - $clone->defaults[$option] = $value; - unset($clone->resolved[$option], $clone->lazy[$option]); - } - - // Check whether any required option is missing - $diff = array_diff_key($clone->required, $clone->defaults); - - if (\count($diff) > 0) { - ksort($diff); - - throw new MissingOptionsException(sprintf(\count($diff) > 1 ? 'The required options "%s" are missing.' : 'The required option "%s" is missing.', $this->formatOptions(array_keys($diff)))); - } - - // Lock the container - $clone->locked = true; - - // Now process the individual options. Use offsetGet(), which resolves - // the option itself and any options that the option depends on - foreach ($clone->defaults as $option => $_) { - $clone->offsetGet($option); - } - - return $clone->resolved; - } - - /** - * Returns the resolved value of an option. - * - * @param bool $triggerDeprecation Whether to trigger the deprecation or not (true by default) - * - * @return mixed - * - * @throws AccessException If accessing this method outside of - * {@link resolve()} - * @throws NoSuchOptionException If the option is not set - * @throws InvalidOptionsException If the option doesn't fulfill the - * specified validation rules - * @throws OptionDefinitionException If there is a cyclic dependency between - * lazy options and/or normalizers - */ - #[\ReturnTypeWillChange] - public function offsetGet($option, bool $triggerDeprecation = true) - { - if (!$this->locked) { - throw new AccessException('Array access is only supported within closures of lazy options and normalizers.'); - } - - // Shortcut for resolved options - if (isset($this->resolved[$option]) || \array_key_exists($option, $this->resolved)) { - if ($triggerDeprecation && isset($this->deprecated[$option]) && (isset($this->given[$option]) || $this->calling) && \is_string($this->deprecated[$option]['message'])) { - trigger_deprecation($this->deprecated[$option]['package'], $this->deprecated[$option]['version'], strtr($this->deprecated[$option]['message'], ['%name%' => $option])); - } - - return $this->resolved[$option]; - } - - // Check whether the option is set at all - if (!isset($this->defaults[$option]) && !\array_key_exists($option, $this->defaults)) { - if (!isset($this->defined[$option])) { - throw new NoSuchOptionException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined)))); - } - - throw new NoSuchOptionException(sprintf('The optional option "%s" has no value set. You should make sure it is set with "isset" before reading it.', $this->formatOptions([$option]))); - } - - $value = $this->defaults[$option]; - - // Resolve the option if it is a nested definition - if (isset($this->nested[$option])) { - // If the closure is already being called, we have a cyclic dependency - if (isset($this->calling[$option])) { - throw new OptionDefinitionException(sprintf('The options "%s" have a cyclic dependency.', $this->formatOptions(array_keys($this->calling)))); - } - - if (!\is_array($value)) { - throw new InvalidOptionsException(sprintf('The nested option "%s" with value %s is expected to be of type array, but is of type "%s".', $this->formatOptions([$option]), $this->formatValue($value), get_debug_type($value))); - } - - // The following section must be protected from cyclic calls. - $this->calling[$option] = true; - try { - $resolver = new self(); - $resolver->prototype = false; - $resolver->parentsOptions = $this->parentsOptions; - $resolver->parentsOptions[] = $option; - foreach ($this->nested[$option] as $closure) { - $closure($resolver, $this); - } - - if ($resolver->prototype) { - $values = []; - foreach ($value as $index => $prototypeValue) { - if (!\is_array($prototypeValue)) { - throw new InvalidOptionsException(sprintf('The value of the option "%s" is expected to be of type array of array, but is of type array of "%s".', $this->formatOptions([$option]), get_debug_type($prototypeValue))); - } - - $resolver->prototypeIndex = $index; - $values[$index] = $resolver->resolve($prototypeValue); - } - $value = $values; - } else { - $value = $resolver->resolve($value); - } - } finally { - $resolver->prototypeIndex = null; - unset($this->calling[$option]); - } - } - - // Resolve the option if the default value is lazily evaluated - if (isset($this->lazy[$option])) { - // If the closure is already being called, we have a cyclic - // dependency - if (isset($this->calling[$option])) { - throw new OptionDefinitionException(sprintf('The options "%s" have a cyclic dependency.', $this->formatOptions(array_keys($this->calling)))); - } - - // The following section must be protected from cyclic - // calls. Set $calling for the current $option to detect a cyclic - // dependency - // BEGIN - $this->calling[$option] = true; - try { - foreach ($this->lazy[$option] as $closure) { - $value = $closure($this, $value); - } - } finally { - unset($this->calling[$option]); - } - // END - } - - // Validate the type of the resolved option - if (isset($this->allowedTypes[$option])) { - $valid = true; - $invalidTypes = []; - - foreach ($this->allowedTypes[$option] as $type) { - if ($valid = $this->verifyTypes($type, $value, $invalidTypes)) { - break; - } - } - - if (!$valid) { - $fmtActualValue = $this->formatValue($value); - $fmtAllowedTypes = implode('" or "', $this->allowedTypes[$option]); - $fmtProvidedTypes = implode('|', array_keys($invalidTypes)); - $allowedContainsArrayType = \count(array_filter($this->allowedTypes[$option], static function ($item) { - return str_ends_with($item, '[]'); - })) > 0; - - if (\is_array($value) && $allowedContainsArrayType) { - throw new InvalidOptionsException(sprintf('The option "%s" with value %s is expected to be of type "%s", but one of the elements is of type "%s".', $this->formatOptions([$option]), $fmtActualValue, $fmtAllowedTypes, $fmtProvidedTypes)); - } - - throw new InvalidOptionsException(sprintf('The option "%s" with value %s is expected to be of type "%s", but is of type "%s".', $this->formatOptions([$option]), $fmtActualValue, $fmtAllowedTypes, $fmtProvidedTypes)); - } - } - - // Validate the value of the resolved option - if (isset($this->allowedValues[$option])) { - $success = false; - $printableAllowedValues = []; - - foreach ($this->allowedValues[$option] as $allowedValue) { - if ($allowedValue instanceof \Closure) { - if ($allowedValue($value)) { - $success = true; - break; - } - - // Don't include closures in the exception message - continue; - } - - if ($value === $allowedValue) { - $success = true; - break; - } - - $printableAllowedValues[] = $allowedValue; - } - - if (!$success) { - $message = sprintf( - 'The option "%s" with value %s is invalid.', - $option, - $this->formatValue($value) - ); - - if (\count($printableAllowedValues) > 0) { - $message .= sprintf( - ' Accepted values are: %s.', - $this->formatValues($printableAllowedValues) - ); - } - - if (isset($this->info[$option])) { - $message .= sprintf(' Info: %s.', $this->info[$option]); - } - - throw new InvalidOptionsException($message); - } - } - - // Check whether the option is deprecated - // and it is provided by the user or is being called from a lazy evaluation - if ($triggerDeprecation && isset($this->deprecated[$option]) && (isset($this->given[$option]) || ($this->calling && \is_string($this->deprecated[$option]['message'])))) { - $deprecation = $this->deprecated[$option]; - $message = $this->deprecated[$option]['message']; - - if ($message instanceof \Closure) { - // If the closure is already being called, we have a cyclic dependency - if (isset($this->calling[$option])) { - throw new OptionDefinitionException(sprintf('The options "%s" have a cyclic dependency.', $this->formatOptions(array_keys($this->calling)))); - } - - $this->calling[$option] = true; - try { - if (!\is_string($message = $message($this, $value))) { - throw new InvalidOptionsException(sprintf('Invalid type for deprecation message, expected string but got "%s", return an empty string to ignore.', get_debug_type($message))); - } - } finally { - unset($this->calling[$option]); - } - } - - if ('' !== $message) { - trigger_deprecation($deprecation['package'], $deprecation['version'], strtr($message, ['%name%' => $option])); - } - } - - // Normalize the validated option - if (isset($this->normalizers[$option])) { - // If the closure is already being called, we have a cyclic - // dependency - if (isset($this->calling[$option])) { - throw new OptionDefinitionException(sprintf('The options "%s" have a cyclic dependency.', $this->formatOptions(array_keys($this->calling)))); - } - - // The following section must be protected from cyclic - // calls. Set $calling for the current $option to detect a cyclic - // dependency - // BEGIN - $this->calling[$option] = true; - try { - foreach ($this->normalizers[$option] as $normalizer) { - $value = $normalizer($this, $value); - } - } finally { - unset($this->calling[$option]); - } - // END - } - - // Mark as resolved - $this->resolved[$option] = $value; - - return $value; - } - - private function verifyTypes(string $type, $value, array &$invalidTypes, int $level = 0): bool - { - if (\is_array($value) && '[]' === substr($type, -2)) { - $type = substr($type, 0, -2); - $valid = true; - - foreach ($value as $val) { - if (!$this->verifyTypes($type, $val, $invalidTypes, $level + 1)) { - $valid = false; - } - } - - return $valid; - } - - if (('null' === $type && null === $value) || (isset(self::VALIDATION_FUNCTIONS[$type]) ? self::VALIDATION_FUNCTIONS[$type]($value) : $value instanceof $type)) { - return true; - } - - if (!$invalidTypes || $level > 0) { - $invalidTypes[get_debug_type($value)] = true; - } - - return false; - } - - /** - * Returns whether a resolved option with the given name exists. - * - * @param string $option The option name - * - * @return bool - * - * @throws AccessException If accessing this method outside of {@link resolve()} - * - * @see \ArrayAccess::offsetExists() - */ - #[\ReturnTypeWillChange] - public function offsetExists($option) - { - if (!$this->locked) { - throw new AccessException('Array access is only supported within closures of lazy options and normalizers.'); - } - - return \array_key_exists($option, $this->defaults); - } - - /** - * Not supported. - * - * @return void - * - * @throws AccessException - */ - #[\ReturnTypeWillChange] - public function offsetSet($option, $value) - { - throw new AccessException('Setting options via array access is not supported. Use setDefault() instead.'); - } - - /** - * Not supported. - * - * @return void - * - * @throws AccessException - */ - #[\ReturnTypeWillChange] - public function offsetUnset($option) - { - throw new AccessException('Removing options via array access is not supported. Use remove() instead.'); - } - - /** - * Returns the number of set options. - * - * This may be only a subset of the defined options. - * - * @return int - * - * @throws AccessException If accessing this method outside of {@link resolve()} - * - * @see \Countable::count() - */ - #[\ReturnTypeWillChange] - public function count() - { - if (!$this->locked) { - throw new AccessException('Counting is only supported within closures of lazy options and normalizers.'); - } - - return \count($this->defaults); - } - - /** - * Returns a string representation of the value. - * - * This method returns the equivalent PHP tokens for most scalar types - * (i.e. "false" for false, "1" for 1 etc.). Strings are always wrapped - * in double quotes ("). - * - * @param mixed $value The value to format as string - */ - private function formatValue($value): string - { - if (\is_object($value)) { - return \get_class($value); - } - - if (\is_array($value)) { - return 'array'; - } - - if (\is_string($value)) { - return '"'.$value.'"'; - } - - if (\is_resource($value)) { - return 'resource'; - } - - if (null === $value) { - return 'null'; - } - - if (false === $value) { - return 'false'; - } - - if (true === $value) { - return 'true'; - } - - return (string) $value; - } - - /** - * Returns a string representation of a list of values. - * - * Each of the values is converted to a string using - * {@link formatValue()}. The values are then concatenated with commas. - * - * @see formatValue() - */ - private function formatValues(array $values): string - { - foreach ($values as $key => $value) { - $values[$key] = $this->formatValue($value); - } - - return implode(', ', $values); - } - - private function formatOptions(array $options): string - { - if ($this->parentsOptions) { - $prefix = array_shift($this->parentsOptions); - if ($this->parentsOptions) { - $prefix .= sprintf('[%s]', implode('][', $this->parentsOptions)); - } - - if ($this->prototype && null !== $this->prototypeIndex) { - $prefix .= sprintf('[%s]', $this->prototypeIndex); - } - - $options = array_map(static function (string $option) use ($prefix): string { - return sprintf('%s[%s]', $prefix, $option); - }, $options); - } - - return implode('", "', $options); - } - - private function getParameterClassName(\ReflectionParameter $parameter): ?string - { - if (!($type = $parameter->getType()) instanceof \ReflectionNamedType || $type->isBuiltin()) { - return null; - } - - return $type->getName(); - } -} diff --git a/lib/symfony/options-resolver/README.md b/lib/symfony/options-resolver/README.md deleted file mode 100644 index c63b9005e..000000000 --- a/lib/symfony/options-resolver/README.md +++ /dev/null @@ -1,15 +0,0 @@ -OptionsResolver Component -========================= - -The OptionsResolver component is `array_replace` on steroids. It allows you to -create an options system with required options, defaults, validation (type, -value), normalization and more. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/options_resolver.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/lib/symfony/options-resolver/composer.json b/lib/symfony/options-resolver/composer.json deleted file mode 100644 index a38d1bd04..000000000 --- a/lib/symfony/options-resolver/composer.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "symfony/options-resolver", - "type": "library", - "description": "Provides an improved replacement for the array_replace PHP function", - "keywords": ["options", "config", "configuration"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php73": "~1.0", - "symfony/polyfill-php80": "^1.16" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\OptionsResolver\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/lib/symfony/polyfill-ctype/Ctype.php b/lib/symfony/polyfill-ctype/Ctype.php deleted file mode 100644 index ba75a2c95..000000000 --- a/lib/symfony/polyfill-ctype/Ctype.php +++ /dev/null @@ -1,232 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Ctype; - -/** - * Ctype implementation through regex. - * - * @internal - * - * @author Gert de Pagter <BackEndTea@gmail.com> - */ -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/lib/symfony/polyfill-ctype/LICENSE b/lib/symfony/polyfill-ctype/LICENSE deleted file mode 100644 index 3f853aaf3..000000000 --- a/lib/symfony/polyfill-ctype/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2018-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/lib/symfony/polyfill-ctype/README.md b/lib/symfony/polyfill-ctype/README.md deleted file mode 100644 index b144d03c3..000000000 --- a/lib/symfony/polyfill-ctype/README.md +++ /dev/null @@ -1,12 +0,0 @@ -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/lib/symfony/polyfill-ctype/bootstrap.php b/lib/symfony/polyfill-ctype/bootstrap.php deleted file mode 100644 index d54524b31..000000000 --- a/lib/symfony/polyfill-ctype/bootstrap.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -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/lib/symfony/polyfill-ctype/bootstrap80.php b/lib/symfony/polyfill-ctype/bootstrap80.php deleted file mode 100644 index ab2f8611d..000000000 --- a/lib/symfony/polyfill-ctype/bootstrap80.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -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/lib/symfony/polyfill-ctype/composer.json b/lib/symfony/polyfill-ctype/composer.json deleted file mode 100644 index ee5c931cd..000000000 --- a/lib/symfony/polyfill-ctype/composer.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "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.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - } -} diff --git a/lib/symfony/polyfill-intl-grapheme/Grapheme.php b/lib/symfony/polyfill-intl-grapheme/Grapheme.php deleted file mode 100644 index 6f7c0c78d..000000000 --- a/lib/symfony/polyfill-intl-grapheme/Grapheme.php +++ /dev/null @@ -1,247 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Grapheme; - -\define('SYMFONY_GRAPHEME_CLUSTER_RX', ((float) \PCRE_VERSION < 10 ? (float) \PCRE_VERSION >= 8.32 : (float) \PCRE_VERSION >= 10.39) ? '\X' : Grapheme::GRAPHEME_CLUSTER_RX); - -/** - * Partial intl implementation in pure PHP. - * - * Implemented: - * - grapheme_extract - Extract a sequence of grapheme clusters from a text buffer, which must be encoded in UTF-8 - * - grapheme_stripos - Find position (in grapheme units) of first occurrence of a case-insensitive string - * - grapheme_stristr - Returns part of haystack string from the first occurrence of case-insensitive needle to the end of haystack - * - grapheme_strlen - Get string length in grapheme units - * - grapheme_strpos - Find position (in grapheme units) of first occurrence of a string - * - grapheme_strripos - Find position (in grapheme units) of last occurrence of a case-insensitive string - * - grapheme_strrpos - Find position (in grapheme units) of last occurrence of a string - * - grapheme_strstr - Returns part of haystack string from the first occurrence of needle to the end of haystack - * - grapheme_substr - Return part of a string - * - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -final class Grapheme -{ - // (CRLF|([ZWNJ-ZWJ]|T+|L*(LV?V+|LV|LVT)T*|L+|[^Control])[Extend]*|[Control]) - // This regular expression is a work around for http://bugs.exim.org/1279 - public const GRAPHEME_CLUSTER_RX = '(?:\r\n|(?:[ -~\x{200C}\x{200D}]|[ᆨ-ᇹ]+|[ᄀ-ᅟ]*(?:[가개갸걔거게겨계고과괘괴교구궈궤귀규그긔기까깨꺄꺠꺼께껴꼐꼬꽈꽤꾀꾜꾸꿔꿰뀌뀨끄끠끼나내냐냬너네녀녜노놔놰뇌뇨누눠눼뉘뉴느늬니다대댜댸더데뎌뎨도돠돼되됴두둬뒈뒤듀드듸디따때땨떄떠떼뗘뗴또똬뙈뙤뚀뚜뚸뛔뛰뜌뜨띄띠라래랴럐러레려례로롸뢔뢰료루뤄뤠뤼류르릐리마매먀먜머메며몌모뫄뫠뫼묘무뭐뭬뮈뮤므믜미바배뱌뱨버베벼볘보봐봬뵈뵤부붜붸뷔뷰브븨비빠빼뺘뺴뻐뻬뼈뼤뽀뽜뽸뾔뾰뿌뿨쀄쀠쀼쁘쁴삐사새샤섀서세셔셰소솨쇄쇠쇼수숴쉐쉬슈스싀시싸쌔쌰썌써쎄쎠쎼쏘쏴쐐쐬쑈쑤쒀쒜쒸쓔쓰씌씨아애야얘어에여예오와왜외요우워웨위유으의이자재쟈쟤저제져졔조좌좨죄죠주줘줴쥐쥬즈즤지짜째쨔쨰쩌쩨쪄쪠쪼쫘쫴쬐쬬쭈쭤쮀쮜쮸쯔쯰찌차채챠챼처체쳐쳬초촤쵀최쵸추춰췌취츄츠츼치카캐캬컈커케켜켸코콰쾌쾨쿄쿠쿼퀘퀴큐크킈키타태탸턔터테텨톄토톼퇘퇴툐투퉈퉤튀튜트틔티파패퍄퍠퍼페펴폐포퐈퐤푀표푸풔풰퓌퓨프픠피하해햐햬허헤혀혜호화홰회효후훠훼휘휴흐희히]?[ᅠ-ᆢ]+|[가-힣])[ᆨ-ᇹ]*|[ᄀ-ᅟ]+|[^\p{Cc}\p{Cf}\p{Zl}\p{Zp}])[\p{Mn}\p{Me}\x{09BE}\x{09D7}\x{0B3E}\x{0B57}\x{0BBE}\x{0BD7}\x{0CC2}\x{0CD5}\x{0CD6}\x{0D3E}\x{0D57}\x{0DCF}\x{0DDF}\x{200C}\x{200D}\x{1D165}\x{1D16E}-\x{1D172}]*|[\p{Cc}\p{Cf}\p{Zl}\p{Zp}])'; - - private const CASE_FOLD = [ - ['µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"], - ['μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'], - ]; - - public static function grapheme_extract($s, $size, $type = \GRAPHEME_EXTR_COUNT, $start = 0, &$next = 0) - { - if (0 > $start) { - $start = \strlen($s) + $start; - } - - if (!is_scalar($s)) { - $hasError = false; - set_error_handler(function () use (&$hasError) { $hasError = true; }); - $next = substr($s, $start); - restore_error_handler(); - if ($hasError) { - substr($s, $start); - $s = ''; - } else { - $s = $next; - } - } else { - $s = substr($s, $start); - } - $size = (int) $size; - $type = (int) $type; - $start = (int) $start; - - if (\GRAPHEME_EXTR_COUNT !== $type && \GRAPHEME_EXTR_MAXBYTES !== $type && \GRAPHEME_EXTR_MAXCHARS !== $type) { - if (80000 > \PHP_VERSION_ID) { - return false; - } - - throw new \ValueError('grapheme_extract(): Argument #3 ($type) must be one of GRAPHEME_EXTR_COUNT, GRAPHEME_EXTR_MAXBYTES, or GRAPHEME_EXTR_MAXCHARS'); - } - - if (!isset($s[0]) || 0 > $size || 0 > $start) { - return false; - } - if (0 === $size) { - return ''; - } - - $next = $start; - - $s = preg_split('/('.SYMFONY_GRAPHEME_CLUSTER_RX.')/u', "\r\n".$s, $size + 1, \PREG_SPLIT_NO_EMPTY | \PREG_SPLIT_DELIM_CAPTURE); - - if (!isset($s[1])) { - return false; - } - - $i = 1; - $ret = ''; - - do { - if (\GRAPHEME_EXTR_COUNT === $type) { - --$size; - } elseif (\GRAPHEME_EXTR_MAXBYTES === $type) { - $size -= \strlen($s[$i]); - } else { - $size -= iconv_strlen($s[$i], 'UTF-8//IGNORE'); - } - - if ($size >= 0) { - $ret .= $s[$i]; - } - } while (isset($s[++$i]) && $size > 0); - - $next += \strlen($ret); - - return $ret; - } - - public static function grapheme_strlen($s) - { - preg_replace('/'.SYMFONY_GRAPHEME_CLUSTER_RX.'/u', '', $s, -1, $len); - - return 0 === $len && '' !== $s ? null : $len; - } - - public static function grapheme_substr($s, $start, $len = null) - { - if (null === $len) { - $len = 2147483647; - } - - preg_match_all('/'.SYMFONY_GRAPHEME_CLUSTER_RX.'/u', $s, $s); - - $slen = \count($s[0]); - $start = (int) $start; - - if (0 > $start) { - $start += $slen; - } - if (0 > $start) { - if (\PHP_VERSION_ID < 80000) { - return false; - } - - $start = 0; - } - if ($start >= $slen) { - return \PHP_VERSION_ID >= 80000 ? '' : false; - } - - $rem = $slen - $start; - - if (0 > $len) { - $len += $rem; - } - if (0 === $len) { - return ''; - } - if (0 > $len) { - return \PHP_VERSION_ID >= 80000 ? '' : false; - } - if ($len > $rem) { - $len = $rem; - } - - return implode('', \array_slice($s[0], $start, $len)); - } - - public static function grapheme_strpos($s, $needle, $offset = 0) - { - return self::grapheme_position($s, $needle, $offset, 0); - } - - public static function grapheme_stripos($s, $needle, $offset = 0) - { - return self::grapheme_position($s, $needle, $offset, 1); - } - - public static function grapheme_strrpos($s, $needle, $offset = 0) - { - return self::grapheme_position($s, $needle, $offset, 2); - } - - public static function grapheme_strripos($s, $needle, $offset = 0) - { - return self::grapheme_position($s, $needle, $offset, 3); - } - - public static function grapheme_stristr($s, $needle, $beforeNeedle = false) - { - return mb_stristr($s, $needle, $beforeNeedle, 'UTF-8'); - } - - public static function grapheme_strstr($s, $needle, $beforeNeedle = false) - { - return mb_strstr($s, $needle, $beforeNeedle, 'UTF-8'); - } - - private static function grapheme_position($s, $needle, $offset, $mode) - { - $needle = (string) $needle; - if (80000 > \PHP_VERSION_ID && !preg_match('/./us', $needle)) { - return false; - } - $s = (string) $s; - if (!preg_match('/./us', $s)) { - return false; - } - if ($offset > 0) { - $s = self::grapheme_substr($s, $offset); - } elseif ($offset < 0) { - if (2 > $mode) { - $offset += self::grapheme_strlen($s); - $s = self::grapheme_substr($s, $offset); - if (0 > $offset) { - $offset = 0; - } - } elseif (0 > $offset += self::grapheme_strlen($needle)) { - $s = self::grapheme_substr($s, 0, $offset); - $offset = 0; - } else { - $offset = 0; - } - } - - // As UTF-8 is self-synchronizing, and we have ensured the strings are valid UTF-8, - // we can use normal binary string functions here. For case-insensitive searches, - // case fold the strings first. - $caseInsensitive = $mode & 1; - $reverse = $mode & 2; - if ($caseInsensitive) { - // Use the same case folding mode as mbstring does for mb_stripos(). - // Stick to SIMPLE case folding to avoid changing the length of the string, which - // might result in offsets being shifted. - $mode = \defined('MB_CASE_FOLD_SIMPLE') ? \MB_CASE_FOLD_SIMPLE : \MB_CASE_LOWER; - $s = mb_convert_case($s, $mode, 'UTF-8'); - $needle = mb_convert_case($needle, $mode, 'UTF-8'); - - if (!\defined('MB_CASE_FOLD_SIMPLE')) { - $s = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $s); - $needle = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $needle); - } - } - if ($reverse) { - $needlePos = strrpos($s, $needle); - } else { - $needlePos = strpos($s, $needle); - } - - return false !== $needlePos ? self::grapheme_strlen(substr($s, 0, $needlePos)) + $offset : false; - } -} diff --git a/lib/symfony/polyfill-intl-grapheme/LICENSE b/lib/symfony/polyfill-intl-grapheme/LICENSE deleted file mode 100644 index 4cd8bdd30..000000000 --- a/lib/symfony/polyfill-intl-grapheme/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2015-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/lib/symfony/polyfill-intl-grapheme/README.md b/lib/symfony/polyfill-intl-grapheme/README.md deleted file mode 100644 index f55d92c5c..000000000 --- a/lib/symfony/polyfill-intl-grapheme/README.md +++ /dev/null @@ -1,31 +0,0 @@ -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/lib/symfony/polyfill-intl-grapheme/bootstrap.php b/lib/symfony/polyfill-intl-grapheme/bootstrap.php deleted file mode 100644 index a9ea03c7e..000000000 --- a/lib/symfony/polyfill-intl-grapheme/bootstrap.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -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/lib/symfony/polyfill-intl-grapheme/bootstrap80.php b/lib/symfony/polyfill-intl-grapheme/bootstrap80.php deleted file mode 100644 index b8c078677..000000000 --- a/lib/symfony/polyfill-intl-grapheme/bootstrap80.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -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/lib/symfony/polyfill-intl-grapheme/composer.json b/lib/symfony/polyfill-intl-grapheme/composer.json deleted file mode 100644 index 824c96f93..000000000 --- a/lib/symfony/polyfill-intl-grapheme/composer.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "symfony/polyfill-intl-grapheme", - "type": "library", - "description": "Symfony polyfill for intl's grapheme_* functions", - "keywords": ["polyfill", "shim", "compatibility", "portable", "intl", "grapheme"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.1" - }, - "autoload": { - "psr-4": { "Symfony\\Polyfill\\Intl\\Grapheme\\": "" }, - "files": [ "bootstrap.php" ] - }, - "suggest": { - "ext-intl": "For best performance" - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - } -} diff --git a/lib/symfony/polyfill-intl-icu/Collator.php b/lib/symfony/polyfill-intl-icu/Collator.php deleted file mode 100644 index 685522ba6..000000000 --- a/lib/symfony/polyfill-intl-icu/Collator.php +++ /dev/null @@ -1,262 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu; - -use Symfony\Polyfill\Intl\Icu\Exception\MethodArgumentValueNotImplementedException; -use Symfony\Polyfill\Intl\Icu\Exception\MethodNotImplementedException; - -/** - * Replacement for PHP's native {@link \Collator} class. - * - * The only methods currently supported in this class are: - * - * - {@link \__construct} - * - {@link create} - * - {@link asort} - * - {@link getErrorCode} - * - {@link getErrorMessage} - * - {@link getLocale} - * - * @author Igor Wiedler <igor@wiedler.ch> - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @internal - */ -abstract class Collator -{ - /* Attribute constants */ - public const FRENCH_COLLATION = 0; - public const ALTERNATE_HANDLING = 1; - public const CASE_FIRST = 2; - public const CASE_LEVEL = 3; - public const NORMALIZATION_MODE = 4; - public const STRENGTH = 5; - public const HIRAGANA_QUATERNARY_MODE = 6; - public const NUMERIC_COLLATION = 7; - - /* Attribute constants values */ - public const DEFAULT_VALUE = -1; - - public const PRIMARY = 0; - public const SECONDARY = 1; - public const TERTIARY = 2; - public const DEFAULT_STRENGTH = 2; - public const QUATERNARY = 3; - public const IDENTICAL = 15; - - public const OFF = 16; - public const ON = 17; - - public const SHIFTED = 20; - public const NON_IGNORABLE = 21; - - public const LOWER_FIRST = 24; - public const UPPER_FIRST = 25; - - /* Sorting options */ - public const SORT_REGULAR = 0; - public const SORT_NUMERIC = 2; - public const SORT_STRING = 1; - - /** - * @param string|null $locale The locale code. The only currently supported locale is "en" (or null using the default locale, i.e. "en") - * - * @throws MethodArgumentValueNotImplementedException When $locale different than "en" or null is passed - */ - public function __construct(?string $locale) - { - if ('en' !== $locale && null !== $locale) { - throw new MethodArgumentValueNotImplementedException(__METHOD__, 'locale', $locale, 'Only the locale "en" is supported'); - } - } - - /** - * Static constructor. - * - * @param string|null $locale The locale code. The only currently supported locale is "en" (or null using the default locale, i.e. "en") - * - * @return static - * - * @throws MethodArgumentValueNotImplementedException When $locale different than "en" or null is passed - */ - public static function create(?string $locale) - { - return new static($locale); - } - - /** - * Sort array maintaining index association. - * - * @param array &$array Input array - * @param int $flags Flags for sorting, can be one of the following: - * Collator::SORT_REGULAR - compare items normally (don't change types) - * Collator::SORT_NUMERIC - compare items numerically - * Collator::SORT_STRING - compare items as strings - * - * @return bool True on success or false on failure - */ - public function asort(array &$array, int $flags = self::SORT_REGULAR) - { - $intlToPlainFlagMap = [ - self::SORT_REGULAR => \SORT_REGULAR, - self::SORT_NUMERIC => \SORT_NUMERIC, - self::SORT_STRING => \SORT_STRING, - ]; - - $plainSortFlag = $intlToPlainFlagMap[$flags] ?? self::SORT_REGULAR; - - return asort($array, $plainSortFlag); - } - - /** - * Not supported. Compare two Unicode strings. - * - * @return bool|int - * - * @see https://php.net/collator.compare - * - * @throws MethodNotImplementedException - */ - public function compare(string $string1, string $string2) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Not supported. Get a value of an integer collator attribute. - * - * @return bool|int The attribute value on success or false on error - * - * @see https://php.net/collator.getattribute - * - * @throws MethodNotImplementedException - */ - public function getAttribute(int $attribute) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Returns collator's last error code. Always returns the U_ZERO_ERROR class constant value. - * - * @return int The error code from last collator call - */ - public function getErrorCode() - { - return Icu::U_ZERO_ERROR; - } - - /** - * Returns collator's last error message. Always returns the U_ZERO_ERROR_MESSAGE class constant value. - * - * @return string The error message from last collator call - */ - public function getErrorMessage() - { - return 'U_ZERO_ERROR'; - } - - /** - * Returns the collator's locale. - * - * @return string The locale used to create the collator. Currently always - * returns "en". - */ - public function getLocale(int $type = Locale::ACTUAL_LOCALE) - { - return 'en'; - } - - /** - * Not supported. Get sorting key for a string. - * - * @return string The collation key for $string - * - * @see https://php.net/collator.getsortkey - * - * @throws MethodNotImplementedException - */ - public function getSortKey(string $string) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Not supported. Get current collator's strength. - * - * @return bool|int The current collator's strength or false on failure - * - * @see https://php.net/collator.getstrength - * - * @throws MethodNotImplementedException - */ - public function getStrength() - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Not supported. Set a collator's attribute. - * - * @return bool True on success or false on failure - * - * @see https://php.net/collator.setattribute - * - * @throws MethodNotImplementedException - */ - public function setAttribute(int $attribute, int $value) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Not supported. Set the collator's strength. - * - * @return bool True on success or false on failure - * - * @see https://php.net/collator.setstrength - * - * @throws MethodNotImplementedException - */ - public function setStrength(int $strength) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Not supported. Sort array using specified collator and sort keys. - * - * @return bool True on success or false on failure - * - * @see https://php.net/collator.sortwithsortkeys - * - * @throws MethodNotImplementedException - */ - public function sortWithSortKeys(array &$array) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Not supported. Sort array using specified collator. - * - * @return bool True on success or false on failure - * - * @see https://php.net/collator.sort - * - * @throws MethodNotImplementedException - */ - public function sort(array &$array, int $flags = self::SORT_REGULAR) - { - throw new MethodNotImplementedException(__METHOD__); - } -} diff --git a/lib/symfony/polyfill-intl-icu/Currencies.php b/lib/symfony/polyfill-intl-icu/Currencies.php deleted file mode 100644 index 90b1efa69..000000000 --- a/lib/symfony/polyfill-intl-icu/Currencies.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -class Currencies -{ - private static $data; - - public static function getSymbol(string $currency): ?string - { - $data = self::$data ?? self::$data = require __DIR__.'/Resources/currencies.php'; - - return $data[$currency][0] ?? $data[strtoupper($currency)][0] ?? null; - } - - public static function getFractionDigits(string $currency): int - { - $data = self::$data ?? self::$data = require __DIR__.'/Resources/currencies.php'; - - return $data[$currency][1] ?? $data[strtoupper($currency)][1] ?? $data['DEFAULT'][1]; - } - - public static function getRoundingIncrement(string $currency): int - { - $data = self::$data ?? self::$data = require __DIR__.'/Resources/currencies.php'; - - return $data[$currency][2] ?? $data[strtoupper($currency)][2] ?? $data['DEFAULT'][2]; - } -} diff --git a/lib/symfony/polyfill-intl-icu/DateFormat/AmPmTransformer.php b/lib/symfony/polyfill-intl-icu/DateFormat/AmPmTransformer.php deleted file mode 100644 index 196c604be..000000000 --- a/lib/symfony/polyfill-intl-icu/DateFormat/AmPmTransformer.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu\DateFormat; - -/** - * Parser and formatter for AM/PM markers format. - * - * @author Igor Wiedler <igor@wiedler.ch> - * - * @internal - */ -class AmPmTransformer extends Transformer -{ - public function format(\DateTime $dateTime, int $length): string - { - return $dateTime->format('A'); - } - - public function getReverseMatchingRegExp(int $length): string - { - return 'AM|PM'; - } - - public function extractDateOptions(string $matched, int $length): array - { - return [ - 'marker' => $matched, - ]; - } -} diff --git a/lib/symfony/polyfill-intl-icu/DateFormat/DayOfWeekTransformer.php b/lib/symfony/polyfill-intl-icu/DateFormat/DayOfWeekTransformer.php deleted file mode 100644 index 6eedd2444..000000000 --- a/lib/symfony/polyfill-intl-icu/DateFormat/DayOfWeekTransformer.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu\DateFormat; - -/** - * Parser and formatter for day of week format. - * - * @author Igor Wiedler <igor@wiedler.ch> - * - * @internal - */ -class DayOfWeekTransformer extends Transformer -{ - public function format(\DateTime $dateTime, int $length): string - { - $dayOfWeek = $dateTime->format('l'); - switch ($length) { - case 4: - return $dayOfWeek; - case 5: - return $dayOfWeek[0]; - case 6: - return substr($dayOfWeek, 0, 2); - default: - return substr($dayOfWeek, 0, 3); - } - } - - public function getReverseMatchingRegExp(int $length): string - { - switch ($length) { - case 4: - return 'Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday'; - case 5: - return '[MTWFS]'; - case 6: - return 'Mo|Tu|We|Th|Fr|Sa|Su'; - default: - return 'Mon|Tue|Wed|Thu|Fri|Sat|Sun'; - } - } - - public function extractDateOptions(string $matched, int $length): array - { - return []; - } -} diff --git a/lib/symfony/polyfill-intl-icu/DateFormat/DayOfYearTransformer.php b/lib/symfony/polyfill-intl-icu/DateFormat/DayOfYearTransformer.php deleted file mode 100644 index ed78853e0..000000000 --- a/lib/symfony/polyfill-intl-icu/DateFormat/DayOfYearTransformer.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu\DateFormat; - -/** - * Parser and formatter for day of year format. - * - * @author Igor Wiedler <igor@wiedler.ch> - * - * @internal - */ -class DayOfYearTransformer extends Transformer -{ - public function format(\DateTime $dateTime, int $length): string - { - $dayOfYear = (int) $dateTime->format('z') + 1; - - return $this->padLeft($dayOfYear, $length); - } - - public function getReverseMatchingRegExp(int $length): string - { - return '\d{'.$length.'}'; - } - - public function extractDateOptions(string $matched, int $length): array - { - return []; - } -} diff --git a/lib/symfony/polyfill-intl-icu/DateFormat/DayTransformer.php b/lib/symfony/polyfill-intl-icu/DateFormat/DayTransformer.php deleted file mode 100644 index bdce79e6e..000000000 --- a/lib/symfony/polyfill-intl-icu/DateFormat/DayTransformer.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu\DateFormat; - -/** - * Parser and formatter for day format. - * - * @author Igor Wiedler <igor@wiedler.ch> - * - * @internal - */ -class DayTransformer extends Transformer -{ - public function format(\DateTime $dateTime, int $length): string - { - return $this->padLeft($dateTime->format('j'), $length); - } - - public function getReverseMatchingRegExp(int $length): string - { - return 1 === $length ? '\d{1,2}' : '\d{1,'.$length.'}'; - } - - public function extractDateOptions(string $matched, int $length): array - { - return [ - 'day' => (int) $matched, - ]; - } -} diff --git a/lib/symfony/polyfill-intl-icu/DateFormat/FullTransformer.php b/lib/symfony/polyfill-intl-icu/DateFormat/FullTransformer.php deleted file mode 100644 index 02d071da5..000000000 --- a/lib/symfony/polyfill-intl-icu/DateFormat/FullTransformer.php +++ /dev/null @@ -1,312 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu\DateFormat; - -use Symfony\Polyfill\Intl\Icu\Exception\NotImplementedException; -use Symfony\Polyfill\Intl\Icu\Icu; - -/** - * Parser and formatter for date formats. - * - * @author Igor Wiedler <igor@wiedler.ch> - * - * @internal - */ -class FullTransformer -{ - private $quoteMatch = "'(?:[^']+|'')*'"; - private $implementedChars = 'MLydQqhDEaHkKmsz'; - private $notImplementedChars = 'GYuwWFgecSAZvVW'; - private $regExp; - - /** - * @var Transformer[] - */ - private $transformers; - - private $pattern; - private $timezone; - - /** - * @param string $pattern The pattern to be used to format and/or parse values - * @param string $timezone The timezone to perform the date/time calculations - */ - public function __construct(string $pattern, string $timezone) - { - $this->pattern = $pattern; - $this->timezone = $timezone; - - $implementedCharsMatch = $this->buildCharsMatch($this->implementedChars); - $notImplementedCharsMatch = $this->buildCharsMatch($this->notImplementedChars); - $this->regExp = "/($this->quoteMatch|$implementedCharsMatch|$notImplementedCharsMatch)/"; - - $this->transformers = [ - 'M' => new MonthTransformer(), - 'L' => new MonthTransformer(), - 'y' => new YearTransformer(), - 'd' => new DayTransformer(), - 'q' => new QuarterTransformer(), - 'Q' => new QuarterTransformer(), - 'h' => new Hour1201Transformer(), - 'D' => new DayOfYearTransformer(), - 'E' => new DayOfWeekTransformer(), - 'a' => new AmPmTransformer(), - 'H' => new Hour2400Transformer(), - 'K' => new Hour1200Transformer(), - 'k' => new Hour2401Transformer(), - 'm' => new MinuteTransformer(), - 's' => new SecondTransformer(), - 'z' => new TimezoneTransformer(), - ]; - } - - /** - * Format a DateTime using ICU dateformat pattern. - * - * @return string The formatted value - */ - public function format(\DateTime $dateTime): string - { - $formatted = preg_replace_callback($this->regExp, function ($matches) use ($dateTime) { - return $this->formatReplace($matches[0], $dateTime); - }, $this->pattern); - - return $formatted; - } - - /** - * Return the formatted ICU value for the matched date characters. - * - * @throws NotImplementedException When it encounters a not implemented date character - */ - private function formatReplace(string $dateChars, \DateTime $dateTime): string - { - $length = \strlen($dateChars); - - if ($this->isQuoteMatch($dateChars)) { - return $this->replaceQuoteMatch($dateChars); - } - - if (isset($this->transformers[$dateChars[0]])) { - $transformer = $this->transformers[$dateChars[0]]; - - return $transformer->format($dateTime, $length); - } - - // handle unimplemented characters - if (false !== strpos($this->notImplementedChars, $dateChars[0])) { - throw new NotImplementedException(sprintf('Unimplemented date character "%s" in format "%s".', $dateChars[0], $this->pattern)); - } - - return ''; - } - - /** - * Parse a pattern based string to a timestamp value. - * - * @param \DateTime $dateTime A configured DateTime object to use to perform the date calculation - * @param string $value String to convert to a time value - * - * @return int|false The corresponding Unix timestamp - * - * @throws \InvalidArgumentException When the value can not be matched with pattern - */ - public function parse(\DateTime $dateTime, string $value) - { - $reverseMatchingRegExp = $this->getReverseMatchingRegExp($this->pattern); - $reverseMatchingRegExp = '/^'.$reverseMatchingRegExp.'$/'; - - $options = []; - - if (preg_match($reverseMatchingRegExp, $value, $matches)) { - $matches = $this->normalizeArray($matches); - - foreach ($this->transformers as $char => $transformer) { - if (isset($matches[$char])) { - $length = \strlen($matches[$char]['pattern']); - $options = array_merge($options, $transformer->extractDateOptions($matches[$char]['value'], $length)); - } - } - - // reset error code and message - Icu::setError(Icu::U_ZERO_ERROR); - - return $this->calculateUnixTimestamp($dateTime, $options); - } - - // behave like the intl extension - Icu::setError(Icu::U_PARSE_ERROR, 'Date parsing failed'); - - return false; - } - - /** - * Retrieve a regular expression to match with a formatted value. - * - * @return string The reverse matching regular expression with named captures being formed by the - * transformer index in the $transformer array - */ - private function getReverseMatchingRegExp(string $pattern): string - { - $escapedPattern = preg_quote($pattern, '/'); - - // ICU 4.8 recognizes slash ("/") in a value to be parsed as a dash ("-") and vice-versa - // when parsing a date/time value - $escapedPattern = preg_replace('/\\\[\-|\/]/', '[\/\-]', $escapedPattern); - - $reverseMatchingRegExp = preg_replace_callback($this->regExp, function ($matches) { - $length = \strlen($matches[0]); - $transformerIndex = $matches[0][0]; - - $dateChars = $matches[0]; - if ($this->isQuoteMatch($dateChars)) { - return $this->replaceQuoteMatch($dateChars); - } - - if (isset($this->transformers[$transformerIndex])) { - $transformer = $this->transformers[$transformerIndex]; - $captureName = str_repeat($transformerIndex, $length); - - return "(?P<$captureName>".$transformer->getReverseMatchingRegExp($length).')'; - } - - return null; - }, $escapedPattern); - - return $reverseMatchingRegExp; - } - - /** - * Check if the first char of a string is a single quote. - */ - private function isQuoteMatch(string $quoteMatch): bool - { - return "'" === $quoteMatch[0]; - } - - /** - * Replaces single quotes at the start or end of a string with two single quotes. - */ - private function replaceQuoteMatch(string $quoteMatch): string - { - if (preg_match("/^'+$/", $quoteMatch)) { - return str_replace("''", "'", $quoteMatch); - } - - return str_replace("''", "'", substr($quoteMatch, 1, -1)); - } - - /** - * Builds a chars match regular expression. - */ - private function buildCharsMatch(string $specialChars): string - { - $specialCharsArray = str_split($specialChars); - - $specialCharsMatch = implode('|', array_map(function ($char) { - return $char.'+'; - }, $specialCharsArray)); - - return $specialCharsMatch; - } - - /** - * Normalize a preg_replace match array, removing the numeric keys and returning an associative array - * with the value and pattern values for the matched Transformer. - */ - private function normalizeArray(array $data): array - { - $ret = []; - - foreach ($data as $key => $value) { - if (!\is_string($key)) { - continue; - } - - $ret[$key[0]] = [ - 'value' => $value, - 'pattern' => $key, - ]; - } - - return $ret; - } - - /** - * Calculates the Unix timestamp based on the matched values by the reverse matching regular - * expression of parse(). - * - * @return bool|int The calculated timestamp or false if matched date is invalid - */ - private function calculateUnixTimestamp(\DateTime $dateTime, array $options) - { - $options = $this->getDefaultValueForOptions($options); - - $year = $options['year']; - $month = $options['month']; - $day = $options['day']; - $hour = $options['hour']; - $hourInstance = $options['hourInstance']; - $minute = $options['minute']; - $second = $options['second']; - $marker = $options['marker']; - $timezone = $options['timezone']; - - // If month is false, return immediately (intl behavior) - if (false === $month) { - Icu::setError(Icu::U_PARSE_ERROR, 'Date parsing failed'); - - return false; - } - - // Normalize hour - if ($hourInstance instanceof HourTransformer) { - $hour = $hourInstance->normalizeHour($hour, $marker); - } - - // Set the timezone if different from the default one - if (null !== $timezone && $timezone !== $this->timezone) { - $dateTime->setTimezone(new \DateTimeZone($timezone)); - } - - // Normalize yy year - preg_match_all($this->regExp, $this->pattern, $matches); - if (\in_array('yy', $matches[0])) { - $dateTime->setTimestamp(time()); - $year = $year > (int) $dateTime->format('y') + 20 ? 1900 + $year : 2000 + $year; - } - - $dateTime->setDate($year, $month, $day); - $dateTime->setTime($hour, $minute, $second); - - return $dateTime->getTimestamp(); - } - - /** - * Add sensible default values for missing items in the extracted date/time options array. The values - * are base in the beginning of the Unix era. - */ - private function getDefaultValueForOptions(array $options): array - { - return [ - 'year' => $options['year'] ?? 1970, - 'month' => $options['month'] ?? 1, - 'day' => $options['day'] ?? 1, - 'hour' => $options['hour'] ?? 0, - 'hourInstance' => $options['hourInstance'] ?? null, - 'minute' => $options['minute'] ?? 0, - 'second' => $options['second'] ?? 0, - 'marker' => $options['marker'] ?? null, - 'timezone' => $options['timezone'] ?? null, - ]; - } -} diff --git a/lib/symfony/polyfill-intl-icu/DateFormat/Hour1200Transformer.php b/lib/symfony/polyfill-intl-icu/DateFormat/Hour1200Transformer.php deleted file mode 100644 index 839632a94..000000000 --- a/lib/symfony/polyfill-intl-icu/DateFormat/Hour1200Transformer.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu\DateFormat; - -/** - * Parser and formatter for 12 hour format (0-11). - * - * @author Igor Wiedler <igor@wiedler.ch> - * - * @internal - */ -class Hour1200Transformer extends HourTransformer -{ - public function format(\DateTime $dateTime, int $length): string - { - $hourOfDay = $dateTime->format('g'); - $hourOfDay = '12' === $hourOfDay ? '0' : $hourOfDay; - - return $this->padLeft($hourOfDay, $length); - } - - public function normalizeHour(int $hour, string $marker = null): int - { - if ('PM' === $marker) { - $hour += 12; - } - - return $hour; - } - - public function getReverseMatchingRegExp(int $length): string - { - return '\d{1,2}'; - } - - public function extractDateOptions(string $matched, int $length): array - { - return [ - 'hour' => (int) $matched, - 'hourInstance' => $this, - ]; - } -} diff --git a/lib/symfony/polyfill-intl-icu/DateFormat/Hour1201Transformer.php b/lib/symfony/polyfill-intl-icu/DateFormat/Hour1201Transformer.php deleted file mode 100644 index 12c0694d5..000000000 --- a/lib/symfony/polyfill-intl-icu/DateFormat/Hour1201Transformer.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu\DateFormat; - -/** - * Parser and formatter for 12 hour format (1-12). - * - * @author Igor Wiedler <igor@wiedler.ch> - * - * @internal - */ -class Hour1201Transformer extends HourTransformer -{ - public function format(\DateTime $dateTime, int $length): string - { - return $this->padLeft($dateTime->format('g'), $length); - } - - public function normalizeHour(int $hour, string $marker = null): int - { - if ('PM' !== $marker && 12 === $hour) { - $hour = 0; - } elseif ('PM' === $marker && 12 !== $hour) { - // If PM and hour is not 12 (1-12), sum 12 hour - $hour += 12; - } - - return $hour; - } - - public function getReverseMatchingRegExp(int $length): string - { - return '\d{1,2}'; - } - - public function extractDateOptions(string $matched, int $length): array - { - return [ - 'hour' => (int) $matched, - 'hourInstance' => $this, - ]; - } -} diff --git a/lib/symfony/polyfill-intl-icu/DateFormat/Hour2400Transformer.php b/lib/symfony/polyfill-intl-icu/DateFormat/Hour2400Transformer.php deleted file mode 100644 index 32f585f8a..000000000 --- a/lib/symfony/polyfill-intl-icu/DateFormat/Hour2400Transformer.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu\DateFormat; - -/** - * Parser and formatter for 24 hour format (0-23). - * - * @author Igor Wiedler <igor@wiedler.ch> - * - * @internal - */ -class Hour2400Transformer extends HourTransformer -{ - public function format(\DateTime $dateTime, int $length): string - { - return $this->padLeft($dateTime->format('G'), $length); - } - - public function normalizeHour(int $hour, string $marker = null): int - { - if ('AM' === $marker) { - $hour = 0; - } elseif ('PM' === $marker) { - $hour = 12; - } - - return $hour; - } - - public function getReverseMatchingRegExp(int $length): string - { - return '\d{1,2}'; - } - - public function extractDateOptions(string $matched, int $length): array - { - return [ - 'hour' => (int) $matched, - 'hourInstance' => $this, - ]; - } -} diff --git a/lib/symfony/polyfill-intl-icu/DateFormat/Hour2401Transformer.php b/lib/symfony/polyfill-intl-icu/DateFormat/Hour2401Transformer.php deleted file mode 100644 index e7c8bb0a4..000000000 --- a/lib/symfony/polyfill-intl-icu/DateFormat/Hour2401Transformer.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu\DateFormat; - -/** - * Parser and formatter for 24 hour format (1-24). - * - * @author Igor Wiedler <igor@wiedler.ch> - * - * @internal - */ -class Hour2401Transformer extends HourTransformer -{ - public function format(\DateTime $dateTime, int $length): string - { - $hourOfDay = $dateTime->format('G'); - $hourOfDay = '0' === $hourOfDay ? '24' : $hourOfDay; - - return $this->padLeft($hourOfDay, $length); - } - - public function normalizeHour(int $hour, string $marker = null): int - { - if ((null === $marker && 24 === $hour) || 'AM' === $marker) { - $hour = 0; - } elseif ('PM' === $marker) { - $hour = 12; - } - - return $hour; - } - - public function getReverseMatchingRegExp(int $length): string - { - return '\d{1,2}'; - } - - public function extractDateOptions(string $matched, int $length): array - { - return [ - 'hour' => (int) $matched, - 'hourInstance' => $this, - ]; - } -} diff --git a/lib/symfony/polyfill-intl-icu/DateFormat/HourTransformer.php b/lib/symfony/polyfill-intl-icu/DateFormat/HourTransformer.php deleted file mode 100644 index b042ccf79..000000000 --- a/lib/symfony/polyfill-intl-icu/DateFormat/HourTransformer.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu\DateFormat; - -/** - * Base class for hour transformers. - * - * @author Eriksen Costa <eriksen.costa@infranology.com.br> - * - * @internal - */ -abstract class HourTransformer extends Transformer -{ - /** - * Returns a normalized hour value suitable for the hour transformer type. - * - * @param int $hour The hour value - * @param string $marker An optional AM/PM marker - * - * @return int The normalized hour value - */ - abstract public function normalizeHour(int $hour, string $marker = null): int; -} diff --git a/lib/symfony/polyfill-intl-icu/DateFormat/MinuteTransformer.php b/lib/symfony/polyfill-intl-icu/DateFormat/MinuteTransformer.php deleted file mode 100644 index e8bddc6fd..000000000 --- a/lib/symfony/polyfill-intl-icu/DateFormat/MinuteTransformer.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu\DateFormat; - -/** - * Parser and formatter for minute format. - * - * @author Igor Wiedler <igor@wiedler.ch> - * - * @internal - */ -class MinuteTransformer extends Transformer -{ - public function format(\DateTime $dateTime, int $length): string - { - $minuteOfHour = (int) $dateTime->format('i'); - - return $this->padLeft($minuteOfHour, $length); - } - - public function getReverseMatchingRegExp(int $length): string - { - return 1 === $length ? '\d{1,2}' : '\d{'.$length.'}'; - } - - public function extractDateOptions(string $matched, int $length): array - { - return [ - 'minute' => (int) $matched, - ]; - } -} diff --git a/lib/symfony/polyfill-intl-icu/DateFormat/MonthTransformer.php b/lib/symfony/polyfill-intl-icu/DateFormat/MonthTransformer.php deleted file mode 100644 index 6712ed282..000000000 --- a/lib/symfony/polyfill-intl-icu/DateFormat/MonthTransformer.php +++ /dev/null @@ -1,127 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu\DateFormat; - -/** - * Parser and formatter for month format. - * - * @author Igor Wiedler <igor@wiedler.ch> - * - * @internal - */ -class MonthTransformer extends Transformer -{ - protected static $months = [ - 'January', - 'February', - 'March', - 'April', - 'May', - 'June', - 'July', - 'August', - 'September', - 'October', - 'November', - 'December', - ]; - - /** - * Short months names (first 3 letters). - */ - protected static $shortMonths = []; - - /** - * Flipped $months array, $name => $index. - */ - protected static $flippedMonths = []; - - /** - * Flipped $shortMonths array, $name => $index. - */ - protected static $flippedShortMonths = []; - - public function __construct() - { - if (0 === \count(self::$shortMonths)) { - self::$shortMonths = array_map(function ($month) { - return substr($month, 0, 3); - }, self::$months); - - self::$flippedMonths = array_flip(self::$months); - self::$flippedShortMonths = array_flip(self::$shortMonths); - } - } - - public function format(\DateTime $dateTime, int $length): string - { - $matchLengthMap = [ - 1 => 'n', - 2 => 'm', - 3 => 'M', - 4 => 'F', - ]; - - if (isset($matchLengthMap[$length])) { - return $dateTime->format($matchLengthMap[$length]); - } - - if (5 === $length) { - return substr($dateTime->format('M'), 0, 1); - } - - return $this->padLeft($dateTime->format('m'), $length); - } - - public function getReverseMatchingRegExp(int $length): string - { - switch ($length) { - case 1: - $regExp = '\d{1,2}'; - break; - case 3: - $regExp = implode('|', self::$shortMonths); - break; - case 4: - $regExp = implode('|', self::$months); - break; - case 5: - $regExp = '[JFMASOND]'; - break; - default: - $regExp = '\d{1,'.$length.'}'; - break; - } - - return $regExp; - } - - public function extractDateOptions(string $matched, int $length): array - { - if (!is_numeric($matched)) { - if (3 === $length) { - $matched = self::$flippedShortMonths[$matched] + 1; - } elseif (4 === $length) { - $matched = self::$flippedMonths[$matched] + 1; - } elseif (5 === $length) { - // IntlDateFormatter::parse() always returns false for MMMMM or LLLLL - $matched = false; - } - } else { - $matched = (int) $matched; - } - - return [ - 'month' => $matched, - ]; - } -} diff --git a/lib/symfony/polyfill-intl-icu/DateFormat/QuarterTransformer.php b/lib/symfony/polyfill-intl-icu/DateFormat/QuarterTransformer.php deleted file mode 100644 index a549deeda..000000000 --- a/lib/symfony/polyfill-intl-icu/DateFormat/QuarterTransformer.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu\DateFormat; - -/** - * Parser and formatter for quarter format. - * - * @author Igor Wiedler <igor@wiedler.ch> - * - * @internal - */ -class QuarterTransformer extends Transformer -{ - public function format(\DateTime $dateTime, int $length): string - { - $month = (int) $dateTime->format('n'); - $quarter = (int) floor(($month - 1) / 3) + 1; - switch ($length) { - case 1: - case 2: - return $this->padLeft($quarter, $length); - case 3: - return 'Q'.$quarter; - case 4: - $map = [1 => '1st quarter', 2 => '2nd quarter', 3 => '3rd quarter', 4 => '4th quarter']; - - return $map[$quarter]; - default: - if (\defined('INTL_ICU_VERSION') && version_compare(\INTL_ICU_VERSION, '70.1', '<')) { - $map = [1 => '1st quarter', 2 => '2nd quarter', 3 => '3rd quarter', 4 => '4th quarter']; - - return $map[$quarter]; - } else { - return $quarter; - } - } - } - - public function getReverseMatchingRegExp(int $length): string - { - switch ($length) { - case 1: - case 2: - return '\d{'.$length.'}'; - case 3: - return 'Q\d'; - default: - return '(?:1st|2nd|3rd|4th) quarter'; - } - } - - public function extractDateOptions(string $matched, int $length): array - { - return []; - } -} diff --git a/lib/symfony/polyfill-intl-icu/DateFormat/SecondTransformer.php b/lib/symfony/polyfill-intl-icu/DateFormat/SecondTransformer.php deleted file mode 100644 index fcb1028f4..000000000 --- a/lib/symfony/polyfill-intl-icu/DateFormat/SecondTransformer.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu\DateFormat; - -/** - * Parser and formatter for the second format. - * - * @author Igor Wiedler <igor@wiedler.ch> - * - * @internal - */ -class SecondTransformer extends Transformer -{ - public function format(\DateTime $dateTime, int $length): string - { - $secondOfMinute = (int) $dateTime->format('s'); - - return $this->padLeft($secondOfMinute, $length); - } - - public function getReverseMatchingRegExp(int $length): string - { - return 1 === $length ? '\d{1,2}' : '\d{'.$length.'}'; - } - - public function extractDateOptions(string $matched, int $length): array - { - return [ - 'second' => (int) $matched, - ]; - } -} diff --git a/lib/symfony/polyfill-intl-icu/DateFormat/TimezoneTransformer.php b/lib/symfony/polyfill-intl-icu/DateFormat/TimezoneTransformer.php deleted file mode 100644 index bab7a96f8..000000000 --- a/lib/symfony/polyfill-intl-icu/DateFormat/TimezoneTransformer.php +++ /dev/null @@ -1,108 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu\DateFormat; - -use Symfony\Polyfill\Intl\Icu\Exception\NotImplementedException; - -/** - * Parser and formatter for time zone format. - * - * @author Igor Wiedler <igor@wiedler.ch> - * - * @internal - */ -class TimezoneTransformer extends Transformer -{ - /** - * @throws NotImplementedException When time zone is different than UTC or GMT (Etc/GMT) - */ - public function format(\DateTime $dateTime, int $length): string - { - $timeZone = substr($dateTime->getTimezone()->getName(), 0, 3); - - if (!\in_array($timeZone, ['Etc', 'UTC', 'GMT'])) { - throw new NotImplementedException('Time zone different than GMT or UTC is not supported as a formatting output.'); - } - - if ('Etc' === $timeZone) { - // i.e. Etc/GMT+1, Etc/UTC, Etc/Zulu - $timeZone = substr($dateTime->getTimezone()->getName(), 4); - } - - // From ICU >= 59.1 GMT and UTC are no longer unified - if (\in_array($timeZone, ['UTC', 'UCT', 'Universal', 'Zulu'])) { - // offset is not supported with UTC - return $length > 3 ? 'Coordinated Universal Time' : 'UTC'; - } - - $offset = (int) $dateTime->format('O'); - - // From ICU >= 4.8, the zero offset is no more used, example: GMT instead of GMT+00:00 - if (0 === $offset) { - return $length > 3 ? 'Greenwich Mean Time' : 'GMT'; - } - - if ($length > 3) { - return $dateTime->format('\G\M\TP'); - } - - return sprintf('GMT%s%d', $offset >= 0 ? '+' : '', $offset / 100); - } - - public function getReverseMatchingRegExp(int $length): string - { - return 'GMT[+-]\d{2}:?\d{2}'; - } - - public function extractDateOptions(string $matched, int $length): array - { - return [ - 'timezone' => self::getEtcTimeZoneId($matched), - ]; - } - - /** - * Get an Etc/GMT timezone identifier for the specified timezone. - * - * The PHP documentation for timezones states to not use the 'Other' time zones because them exists - * "for backwards compatibility". However all Etc/GMT time zones are in the tz database 'etcetera' file, - * which indicates they are not deprecated (neither are old names). - * - * Only GMT, Etc/Universal, Etc/Zulu, Etc/Greenwich, Etc/GMT-0, Etc/GMT+0 and Etc/GMT0 are old names and - * are linked to Etc/GMT or Etc/UTC. - * - * @param string $formattedTimeZone A GMT timezone string (GMT-03:00, e.g.) - * - * @return string A timezone identifier - * - * @see https://php.net/timezones.others - * - * @throws NotImplementedException When the GMT time zone have minutes offset different than zero - * @throws \InvalidArgumentException When the value can not be matched with pattern - */ - public static function getEtcTimeZoneId(string $formattedTimeZone): string - { - if (preg_match('/GMT(?P<signal>[+-])(?P<hours>\d{2}):?(?P<minutes>\d{2})/', $formattedTimeZone, $matches)) { - $hours = (int) $matches['hours']; - $minutes = (int) $matches['minutes']; - $signal = '-' === $matches['signal'] ? '+' : '-'; - - if (0 < $minutes) { - throw new NotImplementedException(sprintf('It is not possible to use a GMT time zone with minutes offset different than zero (0). GMT time zone tried: "%s".', $formattedTimeZone)); - } - - return 'Etc/GMT'.(0 !== $hours ? $signal.$hours : ''); - } - - throw new \InvalidArgumentException(sprintf('The GMT time zone "%s" does not match with the supported formats GMT[+-]HH:MM or GMT[+-]HHMM.', $formattedTimeZone)); - } -} diff --git a/lib/symfony/polyfill-intl-icu/DateFormat/Transformer.php b/lib/symfony/polyfill-intl-icu/DateFormat/Transformer.php deleted file mode 100644 index 7f8bf25b5..000000000 --- a/lib/symfony/polyfill-intl-icu/DateFormat/Transformer.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu\DateFormat; - -/** - * Parser and formatter for date formats. - * - * @author Igor Wiedler <igor@wiedler.ch> - * - * @internal - */ -abstract class Transformer -{ - /** - * Format a value using a configured DateTime as date/time source. - * - * @param \DateTime $dateTime A DateTime object to be used to generate the formatted value - * @param int $length The formatted value string length - * - * @return string The formatted value - */ - abstract public function format(\DateTime $dateTime, int $length): string; - - /** - * Returns a reverse matching regular expression of a string generated by format(). - * - * @param int $length The length of the value to be reverse matched - * - * @return string The reverse matching regular expression - */ - abstract public function getReverseMatchingRegExp(int $length): string; - - /** - * Extract date options from a matched value returned by the processing of the reverse matching - * regular expression. - * - * @param string $matched The matched value - * @param int $length The length of the Transformer pattern string - * - * @return array An associative array - */ - abstract public function extractDateOptions(string $matched, int $length): array; - - /** - * Pad a string with zeros to the left. - * - * @param string $value The string to be padded - * @param int $length The length to pad - * - * @return string The padded string - */ - protected function padLeft(string $value, int $length): string - { - return str_pad($value, $length, '0', \STR_PAD_LEFT); - } -} diff --git a/lib/symfony/polyfill-intl-icu/DateFormat/YearTransformer.php b/lib/symfony/polyfill-intl-icu/DateFormat/YearTransformer.php deleted file mode 100644 index a27ce8555..000000000 --- a/lib/symfony/polyfill-intl-icu/DateFormat/YearTransformer.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu\DateFormat; - -/** - * Parser and formatter for year format. - * - * @author Igor Wiedler <igor@wiedler.ch> - * - * @internal - */ -class YearTransformer extends Transformer -{ - public function format(\DateTime $dateTime, int $length): string - { - if (2 === $length) { - return $dateTime->format('y'); - } - - return $this->padLeft($dateTime->format('Y'), $length); - } - - public function getReverseMatchingRegExp(int $length): string - { - return 2 === $length ? '\d{2}' : '\d{1,4}'; - } - - public function extractDateOptions(string $matched, int $length): array - { - return [ - 'year' => (int) $matched, - ]; - } -} diff --git a/lib/symfony/polyfill-intl-icu/Exception/ExceptionInterface.php b/lib/symfony/polyfill-intl-icu/Exception/ExceptionInterface.php deleted file mode 100644 index a453b5e2f..000000000 --- a/lib/symfony/polyfill-intl-icu/Exception/ExceptionInterface.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu\Exception; - -/** - * Base ExceptionInterface for the Intl component. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface ExceptionInterface extends \Throwable -{ -} diff --git a/lib/symfony/polyfill-intl-icu/Exception/MethodArgumentNotImplementedException.php b/lib/symfony/polyfill-intl-icu/Exception/MethodArgumentNotImplementedException.php deleted file mode 100644 index db120a340..000000000 --- a/lib/symfony/polyfill-intl-icu/Exception/MethodArgumentNotImplementedException.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu\Exception; - -/** - * @author Eriksen Costa <eriksen.costa@infranology.com.br> - */ -class MethodArgumentNotImplementedException extends NotImplementedException -{ - /** - * @param string $methodName The method name that raised the exception - * @param string $argName The argument name that is not implemented - */ - public function __construct(string $methodName, string $argName) - { - $message = sprintf('The %s() method\'s argument $%s behavior is not implemented.', $methodName, $argName); - parent::__construct($message); - } -} diff --git a/lib/symfony/polyfill-intl-icu/Exception/MethodArgumentValueNotImplementedException.php b/lib/symfony/polyfill-intl-icu/Exception/MethodArgumentValueNotImplementedException.php deleted file mode 100644 index bd9204234..000000000 --- a/lib/symfony/polyfill-intl-icu/Exception/MethodArgumentValueNotImplementedException.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu\Exception; - -/** - * @author Eriksen Costa <eriksen.costa@infranology.com.br> - */ -class MethodArgumentValueNotImplementedException extends NotImplementedException -{ - /** - * @param string $methodName The method name that raised the exception - * @param string $argName The argument name - * @param mixed $argValue The argument value that is not implemented - * @param string $additionalMessage An optional additional message to append to the exception message - */ - public function __construct(string $methodName, string $argName, $argValue, string $additionalMessage = '') - { - $message = sprintf( - 'The %s() method\'s argument $%s value %s behavior is not implemented.%s', - $methodName, - $argName, - var_export($argValue, true), - '' !== $additionalMessage ? ' '.$additionalMessage.'. ' : '' - ); - - parent::__construct($message); - } -} diff --git a/lib/symfony/polyfill-intl-icu/Exception/MethodNotImplementedException.php b/lib/symfony/polyfill-intl-icu/Exception/MethodNotImplementedException.php deleted file mode 100644 index 9e1a43985..000000000 --- a/lib/symfony/polyfill-intl-icu/Exception/MethodNotImplementedException.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu\Exception; - -/** - * @author Eriksen Costa <eriksen.costa@infranology.com.br> - */ -class MethodNotImplementedException extends NotImplementedException -{ - /** - * @param string $methodName The name of the method - */ - public function __construct(string $methodName) - { - parent::__construct(sprintf('The %s() is not implemented.', $methodName)); - } -} diff --git a/lib/symfony/polyfill-intl-icu/Exception/NotImplementedException.php b/lib/symfony/polyfill-intl-icu/Exception/NotImplementedException.php deleted file mode 100644 index 929b9334d..000000000 --- a/lib/symfony/polyfill-intl-icu/Exception/NotImplementedException.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu\Exception; - -/** - * Base exception class for not implemented behaviors of the intl extension in the Locale component. - * - * @author Eriksen Costa <eriksen.costa@infranology.com.br> - */ -class NotImplementedException extends RuntimeException -{ - public const INTL_INSTALL_MESSAGE = 'Please install the "intl" extension for full localization capabilities.'; - - /** - * @param string $message The exception message. A note to install the intl extension is appended to this string - */ - public function __construct(string $message) - { - parent::__construct($message.' '.self::INTL_INSTALL_MESSAGE); - } -} diff --git a/lib/symfony/polyfill-intl-icu/Exception/RuntimeException.php b/lib/symfony/polyfill-intl-icu/Exception/RuntimeException.php deleted file mode 100644 index ceedffe8e..000000000 --- a/lib/symfony/polyfill-intl-icu/Exception/RuntimeException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu\Exception; - -/** - * RuntimeException for the Intl component. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class RuntimeException extends \RuntimeException implements ExceptionInterface -{ -} diff --git a/lib/symfony/polyfill-intl-icu/Icu.php b/lib/symfony/polyfill-intl-icu/Icu.php deleted file mode 100644 index b9590f43d..000000000 --- a/lib/symfony/polyfill-intl-icu/Icu.php +++ /dev/null @@ -1,117 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu; - -/** - * Provides fake static versions of the global functions in the intl extension. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @internal - */ -abstract class Icu -{ - /** - * Indicates that no error occurred. - */ - public const U_ZERO_ERROR = 0; - - /** - * Indicates that an invalid argument was passed. - */ - public const U_ILLEGAL_ARGUMENT_ERROR = 1; - - /** - * Indicates that the parse() operation failed. - */ - public const U_PARSE_ERROR = 9; - - /** - * All known error codes. - */ - private static $errorCodes = [ - self::U_ZERO_ERROR => 'U_ZERO_ERROR', - self::U_ILLEGAL_ARGUMENT_ERROR => 'U_ILLEGAL_ARGUMENT_ERROR', - self::U_PARSE_ERROR => 'U_PARSE_ERROR', - ]; - - /** - * The error code of the last operation. - */ - private static $errorCode = self::U_ZERO_ERROR; - - /** - * The error code of the last operation. - */ - private static $errorMessage = 'U_ZERO_ERROR'; - - /** - * Returns whether the error code indicates a failure. - * - * @param int $errorCode The error code returned by Icu::getErrorCode() - */ - public static function isFailure(int $errorCode): bool - { - return isset(self::$errorCodes[$errorCode]) - && $errorCode > self::U_ZERO_ERROR; - } - - /** - * Returns the error code of the last operation. - * - * Returns Icu::U_ZERO_ERROR if no error occurred. - * - * @return int - */ - public static function getErrorCode() - { - return self::$errorCode; - } - - /** - * Returns the error message of the last operation. - * - * Returns "U_ZERO_ERROR" if no error occurred. - */ - public static function getErrorMessage(): string - { - return self::$errorMessage; - } - - /** - * Returns the symbolic name for a given error code. - * - * @param int $code The error code returned by Icu::getErrorCode() - */ - public static function getErrorName(int $code): string - { - return self::$errorCodes[$code] ?? '[BOGUS UErrorCode]'; - } - - /** - * Sets the current error. - * - * @param int $code One of the error constants in this class - * @param string $message The ICU class error message - * - * @throws \InvalidArgumentException If the code is not one of the error constants in this class - */ - public static function setError(int $code, string $message = '') - { - if (!isset(self::$errorCodes[$code])) { - throw new \InvalidArgumentException(sprintf('No such error code: "%s".', $code)); - } - - self::$errorMessage = $message ? sprintf('%s: %s', $message, self::$errorCodes[$code]) : self::$errorCodes[$code]; - self::$errorCode = $code; - } -} diff --git a/lib/symfony/polyfill-intl-icu/IntlDateFormatter.php b/lib/symfony/polyfill-intl-icu/IntlDateFormatter.php deleted file mode 100644 index 402a07c0e..000000000 --- a/lib/symfony/polyfill-intl-icu/IntlDateFormatter.php +++ /dev/null @@ -1,645 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu; - -use Symfony\Polyfill\Intl\Icu\DateFormat\FullTransformer; -use Symfony\Polyfill\Intl\Icu\Exception\MethodArgumentNotImplementedException; -use Symfony\Polyfill\Intl\Icu\Exception\MethodArgumentValueNotImplementedException; -use Symfony\Polyfill\Intl\Icu\Exception\MethodNotImplementedException; - -/** - * Replacement for PHP's native {@link \IntlDateFormatter} class. - * - * The only methods currently supported in this class are: - * - * - {@link __construct} - * - {@link create} - * - {@link format} - * - {@link getCalendar} - * - {@link getDateType} - * - {@link getErrorCode} - * - {@link getErrorMessage} - * - {@link getLocale} - * - {@link getPattern} - * - {@link getTimeType} - * - {@link getTimeZoneId} - * - {@link isLenient} - * - {@link parse} - * - {@link setLenient} - * - {@link setPattern} - * - {@link setTimeZoneId} - * - {@link setTimeZone} - * - * @author Igor Wiedler <igor@wiedler.ch> - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @internal - */ -abstract class IntlDateFormatter -{ - /** - * The error code from the last operation. - * - * @var int - */ - protected $errorCode = Icu::U_ZERO_ERROR; - - /** - * The error message from the last operation. - * - * @var string - */ - protected $errorMessage = 'U_ZERO_ERROR'; - - /* date/time format types */ - public const NONE = -1; - public const FULL = 0; - public const LONG = 1; - public const MEDIUM = 2; - public const SHORT = 3; - - /* date format types */ - public const RELATIVE_FULL = 128; - public const RELATIVE_LONG = 129; - public const RELATIVE_MEDIUM = 130; - public const RELATIVE_SHORT = 131; - - /* calendar formats */ - public const TRADITIONAL = 0; - public const GREGORIAN = 1; - - /** - * Patterns used to format the date when no pattern is provided. - */ - private $defaultDateFormats = [ - self::NONE => '', - self::FULL => 'EEEE, MMMM d, y', - self::LONG => 'MMMM d, y', - self::MEDIUM => 'MMM d, y', - self::SHORT => 'M/d/yy', - self::RELATIVE_FULL => 'EEEE, MMMM d, y', - self::RELATIVE_LONG => 'MMMM d, y', - self::RELATIVE_MEDIUM => 'MMM d, y', - self::RELATIVE_SHORT => 'M/d/yy', - ]; - - /** - * Patterns used to format the time when no pattern is provided. - */ - private $defaultTimeFormats = [ - self::FULL => 'h:mm:ss a zzzz', - self::LONG => 'h:mm:ss a z', - self::MEDIUM => 'h:mm:ss a', - self::SHORT => 'h:mm a', - ]; - - private $dateType; - private $timeType; - - /** - * @var string - */ - private $pattern; - - /** - * @var \DateTimeZone - */ - private $dateTimeZone; - - /** - * @var bool - */ - private $uninitializedTimeZoneId = false; - - /** - * @var string - */ - private $timezoneId; - - /** - * @var bool - */ - private $isRelativeDateType = false; - - /** - * @param string|null $locale The locale code. The only currently supported locale is "en" (or null using the default locale, i.e. "en") - * @param \IntlTimeZone|\DateTimeZone|string|null $timezone Timezone identifier - * @param \IntlCalendar|int|null $calendar Calendar to use for formatting or parsing. The only currently - * supported value is IntlDateFormatter::GREGORIAN (or null using the default calendar, i.e. "GREGORIAN") - * - * @see https://php.net/intldateformatter.create - * @see http://userguide.icu-project.org/formatparse/datetime - * - * @throws MethodArgumentValueNotImplementedException When $locale different than "en" or null is passed - * @throws MethodArgumentValueNotImplementedException When $calendar different than GREGORIAN is passed - */ - public function __construct(?string $locale, ?int $dateType, ?int $timeType, $timezone = null, $calendar = null, ?string $pattern = '') - { - if ('en' !== $locale && null !== $locale) { - throw new MethodArgumentValueNotImplementedException(__METHOD__, 'locale', $locale, 'Only the locale "en" is supported'); - } - - if (self::GREGORIAN !== $calendar && null !== $calendar) { - throw new MethodArgumentValueNotImplementedException(__METHOD__, 'calendar', $calendar, 'Only the GREGORIAN calendar is supported'); - } - - if (\PHP_VERSION_ID >= 80100) { - if (null === $dateType) { - @trigger_error('Passing null to parameter #2 ($dateType) of type int is deprecated', \E_USER_DEPRECATED); - } - - if (null === $timeType) { - @trigger_error('Passing null to parameter #3 ($timeType) of type int is deprecated', \E_USER_DEPRECATED); - } - } - - $this->dateType = $dateType ?? self::FULL; - $this->timeType = $timeType ?? self::FULL; - - if ('' === ($pattern ?? '')) { - $pattern = $this->getDefaultPattern(); - } - - $this->setPattern($pattern); - $this->setTimeZone($timezone); - - if (\in_array($this->dateType, [self::RELATIVE_FULL, self::RELATIVE_LONG, self::RELATIVE_MEDIUM, self::RELATIVE_SHORT], true)) { - $this->isRelativeDateType = true; - } - } - - /** - * Static constructor. - * - * @param string|null $locale The locale code. The only currently supported locale is "en" (or null using the default locale, i.e. "en") - * @param \IntlTimeZone|\DateTimeZone|string|null $timezone Timezone identifier - * @param \IntlCalendar|int|null $calendar Calendar to use for formatting or parsing; default is Gregorian - * One of the calendar constants - * - * @return static - * - * @see https://php.net/intldateformatter.create - * @see http://userguide.icu-project.org/formatparse/datetime - * - * @throws MethodArgumentValueNotImplementedException When $locale different than "en" or null is passed - * @throws MethodArgumentValueNotImplementedException When $calendar different than GREGORIAN is passed - */ - public static function create(?string $locale, ?int $dateType, ?int $timeType, $timezone = null, int $calendar = null, ?string $pattern = '') - { - return new static($locale, $dateType, $timeType, $timezone, $calendar, $pattern); - } - - /** - * Format the date/time value (timestamp) as a string. - * - * @param int|string|\DateTimeInterface $datetime The timestamp to format - * - * @return string|bool The formatted value or false if formatting failed - * - * @see https://php.net/intldateformatter.format - * - * @throws MethodArgumentValueNotImplementedException If one of the formatting characters is not implemented - */ - public function format($datetime) - { - // intl allows timestamps to be passed as arrays - we don't - if (\is_array($datetime)) { - $message = 'Only Unix timestamps and DateTime objects are supported'; - - throw new MethodArgumentValueNotImplementedException(__METHOD__, 'datetime', $datetime, $message); - } - - if (\is_string($datetime) && $dt = \DateTime::createFromFormat('U', $datetime)) { - $datetime = $dt; - } - - // behave like the intl extension - $argumentError = null; - if (!\is_int($datetime) && !$datetime instanceof \DateTimeInterface) { - $argumentError = sprintf('datefmt_format: string \'%s\' is not numeric, which would be required for it to be a valid date', $datetime); - } - - if (null !== $argumentError) { - Icu::setError(Icu::U_ILLEGAL_ARGUMENT_ERROR, $argumentError); - $this->errorCode = Icu::getErrorCode(); - $this->errorMessage = Icu::getErrorMessage(); - - return false; - } - - if ($datetime instanceof \DateTimeInterface) { - $datetime = $datetime->format('U'); - } - - $pattern = $this->getPattern(); - $formatted = ''; - - if ($this->isRelativeDateType && $formatted = $this->getRelativeDateFormat($datetime)) { - if (self::NONE === $this->timeType) { - $pattern = ''; - } else { - $pattern = $this->defaultTimeFormats[$this->timeType]; - if (\in_array($this->dateType, [self::RELATIVE_MEDIUM, self::RELATIVE_SHORT], true)) { - $formatted .= ', '; - } else { - $formatted .= ' at '; - } - } - } - - $transformer = new FullTransformer($pattern, $this->getTimeZoneId()); - $formatted .= $transformer->format($this->createDateTime($datetime)); - - // behave like the intl extension - Icu::setError(Icu::U_ZERO_ERROR); - $this->errorCode = Icu::getErrorCode(); - $this->errorMessage = Icu::getErrorMessage(); - - return $formatted; - } - - /** - * Not supported. Formats an object. - * - * @return string The formatted value - * - * @see https://php.net/intldateformatter.formatobject - * - * @throws MethodNotImplementedException - */ - public static function formatObject($datetime, $format = null, string $locale = null) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Returns the formatter's calendar. - * - * @return int The calendar being used by the formatter. Currently always returns - * IntlDateFormatter::GREGORIAN. - * - * @see https://php.net/intldateformatter.getcalendar - */ - public function getCalendar() - { - return self::GREGORIAN; - } - - /** - * Not supported. Returns the formatter's calendar object. - * - * @return object The calendar's object being used by the formatter - * - * @see https://php.net/intldateformatter.getcalendarobject - * - * @throws MethodNotImplementedException - */ - public function getCalendarObject() - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Returns the formatter's datetype. - * - * @return int The current value of the formatter - * - * @see https://php.net/intldateformatter.getdatetype - */ - public function getDateType() - { - return $this->dateType; - } - - /** - * Returns formatter's last error code. Always returns the U_ZERO_ERROR class constant value. - * - * @return int The error code from last formatter call - * - * @see https://php.net/intldateformatter.geterrorcode - */ - public function getErrorCode() - { - return $this->errorCode; - } - - /** - * Returns formatter's last error message. Always returns the U_ZERO_ERROR_MESSAGE class constant value. - * - * @return string The error message from last formatter call - * - * @see https://php.net/intldateformatter.geterrormessage - */ - public function getErrorMessage() - { - return $this->errorMessage; - } - - /** - * Returns the formatter's locale. - * - * @param int $type Not supported. The locale name type to return (Locale::VALID_LOCALE or Locale::ACTUAL_LOCALE) - * - * @return string The locale used to create the formatter. Currently always - * returns "en". - * - * @see https://php.net/intldateformatter.getlocale - */ - public function getLocale(int $type = Locale::ACTUAL_LOCALE) - { - return 'en'; - } - - /** - * Returns the formatter's pattern. - * - * @return string The pattern string used by the formatter - * - * @see https://php.net/intldateformatter.getpattern - */ - public function getPattern() - { - return $this->pattern; - } - - /** - * Returns the formatter's time type. - * - * @return int The time type used by the formatter - * - * @see https://php.net/intldateformatter.gettimetype - */ - public function getTimeType() - { - return $this->timeType; - } - - /** - * Returns the formatter's timezone identifier. - * - * @return string The timezone identifier used by the formatter - * - * @see https://php.net/intldateformatter.gettimezoneid - */ - public function getTimeZoneId() - { - if (!$this->uninitializedTimeZoneId) { - return $this->timezoneId; - } - - return date_default_timezone_get(); - } - - /** - * Not supported. Returns the formatter's timezone. - * - * @return mixed The timezone used by the formatter - * - * @see https://php.net/intldateformatter.gettimezone - * - * @throws MethodNotImplementedException - */ - public function getTimeZone() - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Returns whether the formatter is lenient. - * - * @return bool Currently always returns false - * - * @see https://php.net/intldateformatter.islenient - * - * @throws MethodNotImplementedException - */ - public function isLenient() - { - return false; - } - - /** - * Not supported. Parse string to a field-based time value. - * - * @return string Localtime compatible array of integers: contains 24 hour clock value in tm_hour field - * - * @see https://php.net/intldateformatter.localtime - * - * @throws MethodNotImplementedException - */ - public function localtime(string $string, &$offset = null) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Parse string to a timestamp value. - * - * @return int|false Parsed value as a timestamp - * - * @see https://php.net/intldateformatter.parse - * - * @throws MethodArgumentNotImplementedException When $offset different than null, behavior not implemented - */ - public function parse(string $string, &$offset = null) - { - // We don't calculate the position when parsing the value - if (null !== $offset) { - throw new MethodArgumentNotImplementedException(__METHOD__, 'offset'); - } - - $dateTime = $this->createDateTime(0); - $transformer = new FullTransformer($this->getPattern(), $this->getTimeZoneId()); - - $timestamp = $transformer->parse($dateTime, $string); - - // behave like the intl extension. FullTransformer::parse() set the proper error - $this->errorCode = Icu::getErrorCode(); - $this->errorMessage = Icu::getErrorMessage(); - - return $timestamp; - } - - /** - * Not supported. Set the formatter's calendar. - * - * @param \IntlCalendar|int|null $calendar - * - * @return bool true on success or false on failure - * - * @see https://php.net/intldateformatter.setcalendar - * - * @throws MethodNotImplementedException - */ - public function setCalendar($calendar) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Set the leniency of the parser. - * - * Define if the parser is strict or lenient in interpreting inputs that do not match the pattern - * exactly. Enabling lenient parsing allows the parser to accept otherwise flawed date or time - * patterns, parsing as much as possible to obtain a value. Extra space, unrecognized tokens, or - * invalid values ("February 30th") are not accepted. - * - * @param bool $lenient Sets whether the parser is lenient or not. Currently - * only false (strict) is supported. - * - * @return bool true on success or false on failure - * - * @see https://php.net/intldateformatter.setlenient - * - * @throws MethodArgumentValueNotImplementedException When $lenient is true - */ - public function setLenient(bool $lenient) - { - if ($lenient) { - throw new MethodArgumentValueNotImplementedException(__METHOD__, 'lenient', $lenient, 'Only the strict parser is supported'); - } - - return true; - } - - /** - * Set the formatter's pattern. - * - * @return bool true on success or false on failure - * - * @see https://php.net/intldateformatter.setpattern - * @see http://userguide.icu-project.org/formatparse/datetime - */ - public function setPattern(string $pattern) - { - $this->pattern = $pattern; - - return true; - } - - /** - * Sets formatterʼs timezone. - * - * @param \IntlTimeZone|\DateTimeZone|string|null $timezone - * - * @return bool true on success or false on failure - * - * @see https://php.net/intldateformatter.settimezone - */ - public function setTimeZone($timezone) - { - if ($timezone instanceof \IntlTimeZone) { - $timezone = $timezone->getID(); - } - - if ($timezone instanceof \DateTimeZone) { - $timezone = $timezone->getName(); - - // DateTimeZone returns the GMT offset timezones without the leading GMT, while our parsing requires it. - if (!empty($timezone) && ('+' === $timezone[0] || '-' === $timezone[0])) { - $timezone = 'GMT'.$timezone; - } - } - - if (null === $timezone) { - $timezone = date_default_timezone_get(); - - $this->uninitializedTimeZoneId = true; - } - - // Backup original passed time zone - $timezoneId = $timezone; - - // Get an Etc/GMT time zone that is accepted for \DateTimeZone - if ('GMT' !== $timezone && 0 === strpos($timezone, 'GMT')) { - try { - $timezone = DateFormat\TimezoneTransformer::getEtcTimeZoneId($timezone); - } catch (\InvalidArgumentException $e) { - // Does nothing, will fallback to UTC - } - } - - try { - $this->dateTimeZone = new \DateTimeZone($timezone); - if ('GMT' !== $timezone && $this->dateTimeZone->getName() !== $timezone) { - $timezoneId = $this->getTimeZoneId(); - } - } catch (\Exception $e) { - $timezoneId = $timezone = $this->getTimeZoneId(); - $this->dateTimeZone = new \DateTimeZone($timezone); - } - - $this->timezoneId = $timezoneId; - - return true; - } - - /** - * Create and returns a DateTime object with the specified timestamp and with the - * current time zone. - * - * @return \DateTime - */ - protected function createDateTime($timestamp) - { - $dateTime = \DateTime::createFromFormat('U', $timestamp); - $dateTime->setTimezone($this->dateTimeZone); - - return $dateTime; - } - - /** - * Returns a pattern string based in the datetype and timetype values. - * - * @return string - */ - protected function getDefaultPattern() - { - $pattern = ''; - if (self::NONE !== $this->dateType) { - $pattern = $this->defaultDateFormats[$this->dateType]; - } - if (self::NONE !== $this->timeType) { - if (\in_array($this->dateType, [self::FULL, self::LONG, self::RELATIVE_FULL, self::RELATIVE_LONG], true)) { - $pattern .= ' \'at\' '; - } elseif (self::NONE !== $this->dateType) { - $pattern .= ', '; - } - $pattern .= $this->defaultTimeFormats[$this->timeType]; - } - - return $pattern; - } - - private function getRelativeDateFormat(int $timestamp): string - { - $today = $this->createDateTime(time()); - $today->setTime(0, 0, 0); - - $datetime = $this->createDateTime($timestamp); - $datetime->setTime(0, 0, 0); - - $interval = $today->diff($datetime); - - if (false !== $interval) { - if (0 === $interval->days) { - return 'today'; - } - - if (1 === $interval->days) { - return 1 === $interval->invert ? 'yesterday' : 'tomorrow'; - } - } - - return ''; - } -} diff --git a/lib/symfony/polyfill-intl-icu/LICENSE b/lib/symfony/polyfill-intl-icu/LICENSE deleted file mode 100644 index 9e936ec04..000000000 --- a/lib/symfony/polyfill-intl-icu/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-2020 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -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/lib/symfony/polyfill-intl-icu/Locale.php b/lib/symfony/polyfill-intl-icu/Locale.php deleted file mode 100644 index 91a157d93..000000000 --- a/lib/symfony/polyfill-intl-icu/Locale.php +++ /dev/null @@ -1,310 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu; - -use Symfony\Polyfill\Intl\Icu\Exception\MethodNotImplementedException; - -/** - * Replacement for PHP's native {@link \Locale} class. - * - * The only methods supported in this class are `getDefault` and `canonicalize`. - * All other methods will throw an exception when used. - * - * @author Eriksen Costa <eriksen.costa@infranology.com.br> - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @internal - */ -abstract class Locale -{ - public const DEFAULT_LOCALE = null; - - /* Locale method constants */ - public const ACTUAL_LOCALE = 0; - public const VALID_LOCALE = 1; - - /* Language tags constants */ - public const LANG_TAG = 'language'; - public const EXTLANG_TAG = 'extlang'; - public const SCRIPT_TAG = 'script'; - public const REGION_TAG = 'region'; - public const VARIANT_TAG = 'variant'; - public const GRANDFATHERED_LANG_TAG = 'grandfathered'; - public const PRIVATE_TAG = 'private'; - - /** - * Not supported. Returns the best available locale based on HTTP "Accept-Language" header according to RFC 2616. - * - * @return string The corresponding locale code - * - * @see https://php.net/locale.acceptfromhttp - * - * @throws MethodNotImplementedException - */ - public static function acceptFromHttp(string $header) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Returns a canonicalized locale string. - * - * This polyfill doesn't implement the full-spec algorithm. It only - * canonicalizes locale strings handled by the `LocaleBundle` class. - * - * @return string - */ - public static function canonicalize(string $locale) - { - if ('' === $locale || '.' === $locale[0]) { - return self::getDefault(); - } - - if (!preg_match('/^([a-z]{2})[-_]([a-z]{2})(?:([a-z]{2})(?:[-_]([a-z]{2}))?)?(?:\..*)?$/i', $locale, $m)) { - return $locale; - } - - if (!empty($m[4])) { - return strtolower($m[1]).'_'.ucfirst(strtolower($m[2].$m[3])).'_'.strtoupper($m[4]); - } - - if (!empty($m[3])) { - return strtolower($m[1]).'_'.ucfirst(strtolower($m[2].$m[3])); - } - - return strtolower($m[1]).'_'.strtoupper($m[2]); - } - - /** - * Not supported. Returns a correctly ordered and delimited locale code. - * - * @return string The corresponding locale code - * - * @see https://php.net/locale.composelocale - * - * @throws MethodNotImplementedException - */ - public static function composeLocale(array $subtags) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Not supported. Checks if a language tag filter matches with locale. - * - * @return string The corresponding locale code - * - * @see https://php.net/locale.filtermatches - * - * @throws MethodNotImplementedException - */ - public static function filterMatches(string $languageTag, string $locale, bool $canonicalize = false) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Not supported. Returns the variants for the input locale. - * - * @return array The locale variants - * - * @see https://php.net/locale.getallvariants - * - * @throws MethodNotImplementedException - */ - public static function getAllVariants(string $locale) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Returns the default locale. - * - * @return string The default locale code. Always returns 'en' - * - * @see https://php.net/locale.getdefault - */ - public static function getDefault() - { - return 'en'; - } - - /** - * Not supported. Returns the localized display name for the locale language. - * - * @return string The localized language display name - * - * @see https://php.net/locale.getdisplaylanguage - * - * @throws MethodNotImplementedException - */ - public static function getDisplayLanguage(string $locale, string $displayLocale = null) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Not supported. Returns the localized display name for the locale. - * - * @return string The localized locale display name - * - * @see https://php.net/locale.getdisplayname - * - * @throws MethodNotImplementedException - */ - public static function getDisplayName(string $locale, string $displayLocale = null) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Not supported. Returns the localized display name for the locale region. - * - * @return string The localized region display name - * - * @see https://php.net/locale.getdisplayregion - * - * @throws MethodNotImplementedException - */ - public static function getDisplayRegion(string $locale, string $displayLocale = null) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Not supported. Returns the localized display name for the locale script. - * - * @return string The localized script display name - * - * @see https://php.net/locale.getdisplayscript - * - * @throws MethodNotImplementedException - */ - public static function getDisplayScript(string $locale, string $displayLocale = null) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Not supported. Returns the localized display name for the locale variant. - * - * @return string The localized variant display name - * - * @see https://php.net/locale.getdisplayvariant - * - * @throws MethodNotImplementedException - */ - public static function getDisplayVariant(string $locale, string $displayLocale = null) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Not supported. Returns the keywords for the locale. - * - * @return array Associative array with the extracted variants - * - * @see https://php.net/locale.getkeywords - * - * @throws MethodNotImplementedException - */ - public static function getKeywords(string $locale) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Not supported. Returns the primary language for the locale. - * - * @return string|null The extracted language code or null in case of error - * - * @see https://php.net/locale.getprimarylanguage - * - * @throws MethodNotImplementedException - */ - public static function getPrimaryLanguage(string $locale) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Not supported. Returns the region for the locale. - * - * @return string|null The extracted region code or null if not present - * - * @see https://php.net/locale.getregion - * - * @throws MethodNotImplementedException - */ - public static function getRegion(string $locale) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Not supported. Returns the script for the locale. - * - * @return string|null The extracted script code or null if not present - * - * @see https://php.net/locale.getscript - * - * @throws MethodNotImplementedException - */ - public static function getScript(string $locale) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Not supported. Returns the closest language tag for the locale. - * - * @see https://php.net/locale.lookup - * - * @throws MethodNotImplementedException - */ - public static function lookup(array $languageTag, string $locale, bool $canonicalize = false, string $defaultLocale = null) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Not supported. Returns an associative array of locale identifier subtags. - * - * @return array Associative array with the extracted subtags - * - * @see https://php.net/locale.parselocale - * - * @throws MethodNotImplementedException - */ - public static function parseLocale(string $locale) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Not supported. Sets the default runtime locale. - * - * @return bool true on success or false on failure - * - * @see https://php.net/locale.setdefault - * - * @throws MethodNotImplementedException - */ - public static function setDefault(string $locale) - { - if ('en' !== $locale) { - throw new MethodNotImplementedException(__METHOD__); - } - - return true; - } -} diff --git a/lib/symfony/polyfill-intl-icu/NumberFormatter.php b/lib/symfony/polyfill-intl-icu/NumberFormatter.php deleted file mode 100644 index 9c79e3f36..000000000 --- a/lib/symfony/polyfill-intl-icu/NumberFormatter.php +++ /dev/null @@ -1,835 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Icu; - -use Symfony\Polyfill\Intl\Icu\Exception\MethodArgumentNotImplementedException; -use Symfony\Polyfill\Intl\Icu\Exception\MethodArgumentValueNotImplementedException; -use Symfony\Polyfill\Intl\Icu\Exception\MethodNotImplementedException; -use Symfony\Polyfill\Intl\Icu\Exception\NotImplementedException; - -/** - * Replacement for PHP's native {@link \NumberFormatter} class. - * - * The only methods currently supported in this class are: - * - * - {@link __construct} - * - {@link create} - * - {@link formatCurrency} - * - {@link format} - * - {@link getAttribute} - * - {@link getErrorCode} - * - {@link getErrorMessage} - * - {@link getLocale} - * - {@link parse} - * - {@link setAttribute} - * - * @author Eriksen Costa <eriksen.costa@infranology.com.br> - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @internal - */ -abstract class NumberFormatter -{ - /* Format style constants */ - public const PATTERN_DECIMAL = 0; - public const DECIMAL = 1; - public const CURRENCY = 2; - public const PERCENT = 3; - public const SCIENTIFIC = 4; - public const SPELLOUT = 5; - public const ORDINAL = 6; - public const DURATION = 7; - public const PATTERN_RULEBASED = 9; - public const IGNORE = 0; - public const DEFAULT_STYLE = 1; - - /* Format type constants */ - public const TYPE_DEFAULT = 0; - public const TYPE_INT32 = 1; - public const TYPE_INT64 = 2; - public const TYPE_DOUBLE = 3; - public const TYPE_CURRENCY = 4; - - /* Numeric attribute constants */ - public const PARSE_INT_ONLY = 0; - public const GROUPING_USED = 1; - public const DECIMAL_ALWAYS_SHOWN = 2; - public const MAX_INTEGER_DIGITS = 3; - public const MIN_INTEGER_DIGITS = 4; - public const INTEGER_DIGITS = 5; - public const MAX_FRACTION_DIGITS = 6; - public const MIN_FRACTION_DIGITS = 7; - public const FRACTION_DIGITS = 8; - public const MULTIPLIER = 9; - public const GROUPING_SIZE = 10; - public const ROUNDING_MODE = 11; - public const ROUNDING_INCREMENT = 12; - public const FORMAT_WIDTH = 13; - public const PADDING_POSITION = 14; - public const SECONDARY_GROUPING_SIZE = 15; - public const SIGNIFICANT_DIGITS_USED = 16; - public const MIN_SIGNIFICANT_DIGITS = 17; - public const MAX_SIGNIFICANT_DIGITS = 18; - public const LENIENT_PARSE = 19; - - /* Text attribute constants */ - public const POSITIVE_PREFIX = 0; - public const POSITIVE_SUFFIX = 1; - public const NEGATIVE_PREFIX = 2; - public const NEGATIVE_SUFFIX = 3; - public const PADDING_CHARACTER = 4; - public const CURRENCY_CODE = 5; - public const DEFAULT_RULESET = 6; - public const PUBLIC_RULESETS = 7; - - /* Format symbol constants */ - public const DECIMAL_SEPARATOR_SYMBOL = 0; - public const GROUPING_SEPARATOR_SYMBOL = 1; - public const PATTERN_SEPARATOR_SYMBOL = 2; - public const PERCENT_SYMBOL = 3; - public const ZERO_DIGIT_SYMBOL = 4; - public const DIGIT_SYMBOL = 5; - public const MINUS_SIGN_SYMBOL = 6; - public const PLUS_SIGN_SYMBOL = 7; - public const CURRENCY_SYMBOL = 8; - public const INTL_CURRENCY_SYMBOL = 9; - public const MONETARY_SEPARATOR_SYMBOL = 10; - public const EXPONENTIAL_SYMBOL = 11; - public const PERMILL_SYMBOL = 12; - public const PAD_ESCAPE_SYMBOL = 13; - public const INFINITY_SYMBOL = 14; - public const NAN_SYMBOL = 15; - public const SIGNIFICANT_DIGIT_SYMBOL = 16; - public const MONETARY_GROUPING_SEPARATOR_SYMBOL = 17; - - /* Rounding mode values used by NumberFormatter::setAttribute() with NumberFormatter::ROUNDING_MODE attribute */ - public const ROUND_CEILING = 0; - public const ROUND_FLOOR = 1; - public const ROUND_DOWN = 2; - public const ROUND_UP = 3; - public const ROUND_HALFEVEN = 4; - public const ROUND_HALFDOWN = 5; - public const ROUND_HALFUP = 6; - - /* Pad position values used by NumberFormatter::setAttribute() with NumberFormatter::PADDING_POSITION attribute */ - public const PAD_BEFORE_PREFIX = 0; - public const PAD_AFTER_PREFIX = 1; - public const PAD_BEFORE_SUFFIX = 2; - public const PAD_AFTER_SUFFIX = 3; - - /** - * The error code from the last operation. - * - * @var int - */ - protected $errorCode = Icu::U_ZERO_ERROR; - - /** - * The error message from the last operation. - * - * @var string - */ - protected $errorMessage = 'U_ZERO_ERROR'; - - /** - * @var int - */ - private $style; - - /** - * Default values for the en locale. - */ - private $attributes = [ - self::FRACTION_DIGITS => 0, - self::GROUPING_USED => 1, - self::ROUNDING_MODE => self::ROUND_HALFEVEN, - ]; - - /** - * Holds the initialized attributes code. - */ - private $initializedAttributes = []; - - /** - * The supported styles to the constructor $styles argument. - */ - private static $supportedStyles = [ - 'CURRENCY' => self::CURRENCY, - 'DECIMAL' => self::DECIMAL, - ]; - - /** - * Supported attributes to the setAttribute() $attr argument. - */ - private static $supportedAttributes = [ - 'FRACTION_DIGITS' => self::FRACTION_DIGITS, - 'GROUPING_USED' => self::GROUPING_USED, - 'ROUNDING_MODE' => self::ROUNDING_MODE, - ]; - - /** - * The available rounding modes for setAttribute() usage with - * NumberFormatter::ROUNDING_MODE. NumberFormatter::ROUND_DOWN - * and NumberFormatter::ROUND_UP does not have a PHP only equivalent. - */ - private static $roundingModes = [ - 'ROUND_HALFEVEN' => self::ROUND_HALFEVEN, - 'ROUND_HALFDOWN' => self::ROUND_HALFDOWN, - 'ROUND_HALFUP' => self::ROUND_HALFUP, - 'ROUND_CEILING' => self::ROUND_CEILING, - 'ROUND_FLOOR' => self::ROUND_FLOOR, - 'ROUND_DOWN' => self::ROUND_DOWN, - 'ROUND_UP' => self::ROUND_UP, - ]; - - /** - * The mapping between NumberFormatter rounding modes to the available - * modes in PHP's round() function. - * - * @see https://php.net/round - */ - private static $phpRoundingMap = [ - self::ROUND_HALFDOWN => \PHP_ROUND_HALF_DOWN, - self::ROUND_HALFEVEN => \PHP_ROUND_HALF_EVEN, - self::ROUND_HALFUP => \PHP_ROUND_HALF_UP, - ]; - - /** - * The list of supported rounding modes which aren't available modes in - * PHP's round() function, but there's an equivalent. Keys are rounding - * modes, values does not matter. - */ - private static $customRoundingList = [ - self::ROUND_CEILING => true, - self::ROUND_FLOOR => true, - self::ROUND_DOWN => true, - self::ROUND_UP => true, - ]; - - /** - * The maximum value of the integer type in 32 bit platforms. - */ - private static $int32Max = 2147483647; - - /** - * The maximum value of the integer type in 64 bit platforms. - * - * @var int|float - */ - private static $int64Max = 9223372036854775807; - - private static $enSymbols = [ - self::DECIMAL => ['.', ',', ';', '%', '0', '#', '-', '+', '¤', '¤¤', '.', 'E', '‰', '*', '∞', 'NaN', '@', ','], - self::CURRENCY => ['.', ',', ';', '%', '0', '#', '-', '+', '¤', '¤¤', '.', 'E', '‰', '*', '∞', 'NaN', '@', ','], - ]; - - private static $enTextAttributes = [ - self::DECIMAL => ['', '', '-', '', ' ', 'XXX', ''], - self::CURRENCY => ['¤', '', '-¤', '', ' ', 'XXX'], - ]; - - /** - * @param string|null $locale The locale code. The only currently supported locale is "en" (or null using the default locale, i.e. "en") - * @param int $style Style of the formatting, one of the format style constants. - * The only supported styles are NumberFormatter::DECIMAL - * and NumberFormatter::CURRENCY. - * @param string $pattern Not supported. A pattern string in case $style is NumberFormat::PATTERN_DECIMAL or - * NumberFormat::PATTERN_RULEBASED. It must conform to the syntax - * described in the ICU DecimalFormat or ICU RuleBasedNumberFormat documentation - * - * @see https://php.net/numberformatter.create - * @see https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/classicu_1_1DecimalFormat.html#details - * @see https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/classicu_1_1RuleBasedNumberFormat.html#details - * - * @throws MethodArgumentValueNotImplementedException When $locale different than "en" or null is passed - * @throws MethodArgumentValueNotImplementedException When the $style is not supported - * @throws MethodArgumentNotImplementedException When the pattern value is different than null - */ - public function __construct(?string $locale = 'en', int $style = null, string $pattern = null) - { - if ('en' !== $locale && null !== $locale) { - throw new MethodArgumentValueNotImplementedException(__METHOD__, 'locale', $locale, 'Only the locale "en" is supported'); - } - - if (!\in_array($style, self::$supportedStyles)) { - $message = sprintf('The available styles are: %s.', implode(', ', array_keys(self::$supportedStyles))); - throw new MethodArgumentValueNotImplementedException(__METHOD__, 'style', $style, $message); - } - - if (null !== $pattern) { - throw new MethodArgumentNotImplementedException(__METHOD__, 'pattern'); - } - - $this->style = $style; - } - - /** - * Static constructor. - * - * @param string|null $locale The locale code. The only supported locale is "en" (or null using the default locale, i.e. "en") - * @param int $style Style of the formatting, one of the format style constants. - * The only currently supported styles are NumberFormatter::DECIMAL - * and NumberFormatter::CURRENCY. - * @param string $pattern Not supported. A pattern string in case $style is NumberFormat::PATTERN_DECIMAL or - * NumberFormat::PATTERN_RULEBASED. It must conform to the syntax - * described in the ICU DecimalFormat or ICU RuleBasedNumberFormat documentation - * - * @return static - * - * @see https://php.net/numberformatter.create - * @see http://www.icu-project.org/apiref/icu4c/classDecimalFormat.html#_details - * @see http://www.icu-project.org/apiref/icu4c/classRuleBasedNumberFormat.html#_details - * - * @throws MethodArgumentValueNotImplementedException When $locale different than "en" or null is passed - * @throws MethodArgumentValueNotImplementedException When the $style is not supported - * @throws MethodArgumentNotImplementedException When the pattern value is different than null - */ - public static function create(?string $locale = 'en', int $style = null, string $pattern = null) - { - return new static($locale, $style, $pattern); - } - - /** - * Format a currency value. - * - * @return string The formatted currency value - * - * @see https://php.net/numberformatter.formatcurrency - * @see https://en.wikipedia.org/wiki/ISO_4217#Active_codes - */ - public function formatCurrency(float $amount, string $currency) - { - if (self::DECIMAL === $this->style) { - return $this->format($amount); - } - - if (null === $symbol = Currencies::getSymbol($currency)) { - return false; - } - $fractionDigits = Currencies::getFractionDigits($currency); - - $amount = $this->roundCurrency($amount, $currency); - - $negative = false; - if (0 > $amount) { - $negative = true; - $amount *= -1; - } - - $amount = $this->formatNumber($amount, $fractionDigits); - - // There's a non-breaking space after the currency code (i.e. CRC 100), but not if the currency has a symbol (i.e. £100). - $ret = $symbol.(mb_strlen($symbol, 'UTF-8') > 2 ? "\xc2\xa0" : '').$amount; - - return $negative ? '-'.$ret : $ret; - } - - /** - * Format a number. - * - * @param int|float $num The value to format - * @param int $type Type of the formatting, one of the format type constants. - * Only type NumberFormatter::TYPE_DEFAULT is currently supported. - * - * @return bool|string The formatted value or false on error - * - * @see https://php.net/numberformatter.format - * - * @throws NotImplementedException If the method is called with the class $style 'CURRENCY' - * @throws MethodArgumentValueNotImplementedException If the $type is different than TYPE_DEFAULT - */ - public function format($num, int $type = self::TYPE_DEFAULT) - { - // The original NumberFormatter does not support this format type - if (self::TYPE_CURRENCY === $type) { - if (\PHP_VERSION_ID >= 80000) { - throw new \ValueError(sprintf('The format type must be a NumberFormatter::TYPE_* constant (%s given).', $type)); - } - - trigger_error(__METHOD__.'(): Unsupported format type '.$type, \E_USER_WARNING); - - return false; - } - - if (self::CURRENCY === $this->style) { - throw new NotImplementedException(sprintf('"%s()" method does not support the formatting of currencies (instance with CURRENCY style). "%s".', __METHOD__, NotImplementedException::INTL_INSTALL_MESSAGE)); - } - - // Only the default type is supported. - if (self::TYPE_DEFAULT !== $type) { - throw new MethodArgumentValueNotImplementedException(__METHOD__, 'type', $type, 'Only TYPE_DEFAULT is supported'); - } - - $fractionDigits = $this->getAttribute(self::FRACTION_DIGITS); - - $num = $this->round($num, $fractionDigits); - $num = $this->formatNumber($num, $fractionDigits); - - // behave like the intl extension - $this->resetError(); - - return $num; - } - - /** - * Returns an attribute value. - * - * @return int|false The attribute value on success or false on error - * - * @see https://php.net/numberformatter.getattribute - */ - public function getAttribute(int $attribute) - { - return $this->attributes[$attribute] ?? null; - } - - /** - * Returns formatter's last error code. Always returns the U_ZERO_ERROR class constant value. - * - * @return int The error code from last formatter call - * - * @see https://php.net/numberformatter.geterrorcode - */ - public function getErrorCode() - { - return $this->errorCode; - } - - /** - * Returns formatter's last error message. Always returns the U_ZERO_ERROR_MESSAGE class constant value. - * - * @return string The error message from last formatter call - * - * @see https://php.net/numberformatter.geterrormessage - */ - public function getErrorMessage() - { - return $this->errorMessage; - } - - /** - * Returns the formatter's locale. - * - * The parameter $type is currently ignored. - * - * @param int $type Not supported. The locale name type to return (Locale::VALID_LOCALE or Locale::ACTUAL_LOCALE) - * - * @return string The locale used to create the formatter. Currently always - * returns "en". - * - * @see https://php.net/numberformatter.getlocale - */ - public function getLocale(int $type = Locale::ACTUAL_LOCALE) - { - return 'en'; - } - - /** - * Not supported. Returns the formatter's pattern. - * - * @return string|false The pattern string used by the formatter or false on error - * - * @see https://php.net/numberformatter.getpattern - * - * @throws MethodNotImplementedException - */ - public function getPattern() - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Not supported. Returns a formatter symbol value. - * - * @return string|false The symbol value or false on error - * - * @see https://php.net/numberformatter.getsymbol - */ - public function getSymbol(int $symbol) - { - return \array_key_exists($this->style, self::$enSymbols) && \array_key_exists($symbol, self::$enSymbols[$this->style]) ? self::$enSymbols[$this->style][$symbol] : false; - } - - /** - * Not supported. Returns a formatter text attribute value. - * - * @return string|false The attribute value or false on error - * - * @see https://php.net/numberformatter.gettextattribute - */ - public function getTextAttribute(int $attribute) - { - return \array_key_exists($this->style, self::$enTextAttributes) && \array_key_exists($attribute, self::$enTextAttributes[$this->style]) ? self::$enTextAttributes[$this->style][$attribute] : false; - } - - /** - * Not supported. Parse a currency number. - * - * @return float|false The parsed numeric value or false on error - * - * @see https://php.net/numberformatter.parsecurrency - * - * @throws MethodNotImplementedException - */ - public function parseCurrency(string $string, &$currency, &$offset = null) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Parse a number. - * - * @return int|float|false The parsed value or false on error - * - * @see https://php.net/numberformatter.parse - */ - public function parse(string $string, int $type = self::TYPE_DOUBLE, &$offset = null) - { - if (self::TYPE_DEFAULT === $type || self::TYPE_CURRENCY === $type) { - if (\PHP_VERSION_ID >= 80000) { - throw new \ValueError(sprintf('The format type must be a NumberFormatter::TYPE_* constant (%d given).', $type)); - } - - trigger_error(__METHOD__.'(): Unsupported format type '.$type, \E_USER_WARNING); - - return false; - } - - // Any invalid number at the end of the string is removed. - // Only numbers and the fraction separator is expected in the string. - // If grouping is used, grouping separator also becomes a valid character. - $groupingMatch = $this->getAttribute(self::GROUPING_USED) ? '|(?P<grouping>\d++(,{1}\d+)++(\.\d*+)?)' : ''; - if (preg_match("/^-?(?:\.\d++{$groupingMatch}|\d++(\.\d*+)?)/", $string, $matches)) { - $string = $matches[0]; - $offset = \strlen($string); - // value is not valid if grouping is used, but digits are not grouped in groups of three - if ($error = isset($matches['grouping']) && !preg_match('/^-?(?:\d{1,3}+)?(?:(?:,\d{3})++|\d*+)(?:\.\d*+)?$/', $string)) { - // the position on error is 0 for positive and 1 for negative numbers - $offset = 0 === strpos($string, '-') ? 1 : 0; - } - } else { - $error = true; - $offset = 0; - } - - if ($error) { - Icu::setError(Icu::U_PARSE_ERROR, 'Number parsing failed'); - $this->errorCode = Icu::getErrorCode(); - $this->errorMessage = Icu::getErrorMessage(); - - return false; - } - - $string = str_replace(',', '', $string); - $string = $this->convertValueDataType($string, $type); - - // behave like the intl extension - $this->resetError(); - - return $string; - } - - /** - * Set an attribute. - * - * @param int|float $value - * - * @return bool true on success or false on failure - * - * @see https://php.net/numberformatter.setattribute - * - * @throws MethodArgumentValueNotImplementedException When the $attribute is not supported - * @throws MethodArgumentValueNotImplementedException When the $value is not supported - */ - public function setAttribute(int $attribute, $value) - { - if (!\in_array($attribute, self::$supportedAttributes)) { - $message = sprintf( - 'The available attributes are: %s', - implode(', ', array_keys(self::$supportedAttributes)) - ); - - throw new MethodArgumentValueNotImplementedException(__METHOD__, 'attribute', $value, $message); - } - - if (self::$supportedAttributes['ROUNDING_MODE'] === $attribute && $this->isInvalidRoundingMode($value)) { - $message = sprintf( - 'The supported values for ROUNDING_MODE are: %s', - implode(', ', array_keys(self::$roundingModes)) - ); - - throw new MethodArgumentValueNotImplementedException(__METHOD__, 'attribute', $value, $message); - } - - if (self::$supportedAttributes['GROUPING_USED'] === $attribute) { - $value = $this->normalizeGroupingUsedValue($value); - } - - if (self::$supportedAttributes['FRACTION_DIGITS'] === $attribute) { - $value = $this->normalizeFractionDigitsValue($value); - if ($value < 0) { - // ignore negative values but do not raise an error - return true; - } - } - - $this->attributes[$attribute] = $value; - $this->initializedAttributes[$attribute] = true; - - return true; - } - - /** - * Not supported. Set the formatter's pattern. - * - * @return bool true on success or false on failure - * - * @see https://php.net/numberformatter.setpattern - * @see http://www.icu-project.org/apiref/icu4c/classDecimalFormat.html#_details - * - * @throws MethodNotImplementedException - */ - public function setPattern(string $pattern) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Not supported. Set the formatter's symbol. - * - * @return bool true on success or false on failure - * - * @see https://php.net/numberformatter.setsymbol - * - * @throws MethodNotImplementedException - */ - public function setSymbol(int $symbol, string $value) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Not supported. Set a text attribute. - * - * @return bool true on success or false on failure - * - * @see https://php.net/numberformatter.settextattribute - * - * @throws MethodNotImplementedException - */ - public function setTextAttribute(int $attribute, string $value) - { - throw new MethodNotImplementedException(__METHOD__); - } - - /** - * Set the error to the default U_ZERO_ERROR. - */ - protected function resetError() - { - Icu::setError(Icu::U_ZERO_ERROR); - $this->errorCode = Icu::getErrorCode(); - $this->errorMessage = Icu::getErrorMessage(); - } - - /** - * Rounds a currency value, applying increment rounding if applicable. - * - * When a currency have a rounding increment, an extra round is made after the first one. The rounding factor is - * determined in the ICU data and is explained as of: - * - * "the rounding increment is given in units of 10^(-fraction_digits)" - * - * The only actual rounding data as of this writing, is CHF. - * - * @see http://en.wikipedia.org/wiki/Swedish_rounding - * @see http://www.docjar.com/html/api/com/ibm/icu/util/Currency.java.html#1007 - */ - private function roundCurrency(float $value, string $currency): float - { - $fractionDigits = Currencies::getFractionDigits($currency); - $roundingIncrement = Currencies::getRoundingIncrement($currency); - - // Round with the formatter rounding mode - $value = $this->round($value, $fractionDigits); - - // Swiss rounding - if (0 < $roundingIncrement && 0 < $fractionDigits) { - $roundingFactor = $roundingIncrement / 10 ** $fractionDigits; - $value = round($value / $roundingFactor) * $roundingFactor; - } - - return $value; - } - - /** - * Rounds a value. - * - * @param int|float $value The value to round - * - * @return int|float The rounded value - */ - private function round($value, int $precision) - { - $precision = $this->getUninitializedPrecision($value, $precision); - - $roundingModeAttribute = $this->getAttribute(self::ROUNDING_MODE); - if (isset(self::$phpRoundingMap[$roundingModeAttribute])) { - $value = round($value, $precision, self::$phpRoundingMap[$roundingModeAttribute]); - } elseif (isset(self::$customRoundingList[$roundingModeAttribute])) { - $roundingCoef = 10 ** $precision; - $value *= $roundingCoef; - $value = (float) (string) $value; - - switch ($roundingModeAttribute) { - case self::ROUND_CEILING: - $value = ceil($value); - break; - case self::ROUND_FLOOR: - $value = floor($value); - break; - case self::ROUND_UP: - $value = $value > 0 ? ceil($value) : floor($value); - break; - case self::ROUND_DOWN: - $value = $value > 0 ? floor($value) : ceil($value); - break; - } - - $value /= $roundingCoef; - } - - return $value; - } - - /** - * Formats a number. - * - * @param int|float $value The numeric value to format - */ - private function formatNumber($value, int $precision): string - { - $precision = $this->getUninitializedPrecision($value, $precision); - - return number_format($value, $precision, '.', $this->getAttribute(self::GROUPING_USED) ? ',' : ''); - } - - /** - * Returns the precision value if the DECIMAL style is being used and the FRACTION_DIGITS attribute is uninitialized. - * - * @param int|float $value The value to get the precision from if the FRACTION_DIGITS attribute is uninitialized - */ - private function getUninitializedPrecision($value, int $precision): int - { - if (self::CURRENCY === $this->style) { - return $precision; - } - - if (!$this->isInitializedAttribute(self::FRACTION_DIGITS)) { - preg_match('/.*\.(.*)/', (string) $value, $digits); - if (isset($digits[1])) { - $precision = \strlen($digits[1]); - } - } - - return $precision; - } - - /** - * Check if the attribute is initialized (value set by client code). - */ - private function isInitializedAttribute(string $attr): bool - { - return isset($this->initializedAttributes[$attr]); - } - - /** - * Returns the numeric value using the $type to convert to the right data type. - * - * @param mixed $value The value to be converted - * - * @return int|float|false The converted value - */ - private function convertValueDataType($value, int $type) - { - if (self::TYPE_DOUBLE === $type) { - $value = (float) $value; - } elseif (self::TYPE_INT32 === $type) { - $value = $this->getInt32Value($value); - } elseif (self::TYPE_INT64 === $type) { - $value = $this->getInt64Value($value); - } - - return $value; - } - - /** - * Convert the value data type to int or returns false if the value is out of the integer value range. - * - * @return int|false The converted value - */ - private function getInt32Value($value) - { - if ($value > self::$int32Max || $value < -self::$int32Max - 1) { - return false; - } - - return (int) $value; - } - - /** - * Convert the value data type to int or returns false if the value is out of the integer value range. - * - * @return int|float|false The converted value - */ - private function getInt64Value($value) - { - if ($value > self::$int64Max || $value < -self::$int64Max - 1) { - return false; - } - - if (\PHP_INT_SIZE !== 8 && ($value > self::$int32Max || $value < -self::$int32Max - 1)) { - return (float) $value; - } - - return (int) $value; - } - - /** - * Check if the rounding mode is invalid. - */ - private function isInvalidRoundingMode(int $value): bool - { - if (\in_array($value, self::$roundingModes, true)) { - return false; - } - - return true; - } - - /** - * Returns the normalized value for the GROUPING_USED attribute. Any value that can be converted to int will be - * cast to Boolean and then to int again. This way, negative values are converted to 1 and string values to 0. - */ - private function normalizeGroupingUsedValue($value): int - { - return (int) (bool) (int) $value; - } - - /** - * Returns the normalized value for the FRACTION_DIGITS attribute. - */ - private function normalizeFractionDigitsValue($value): int - { - return (int) $value; - } -} diff --git a/lib/symfony/polyfill-intl-icu/README.md b/lib/symfony/polyfill-intl-icu/README.md deleted file mode 100644 index b7faedc5d..000000000 --- a/lib/symfony/polyfill-intl-icu/README.md +++ /dev/null @@ -1,23 +0,0 @@ -Symfony Polyfill / Intl: ICU -============================ - -This package provides fallback implementations when the -[Intl](https://php.net/intl) extension is not installed. -It is limited to the "en" locale and to: - -- [`intl_is_failure()`](https://php.net/intl-is-failure) -- [`intl_get_error_code()`](https://php.net/intl-get-error-code) -- [`intl_get_error_message()`](https://php.net/intl-get-error-message) -- [`intl_error_name()`](https://php.net/intl-error-name) -- [`Collator`](https://php.net/Collator) -- [`NumberFormatter`](https://php.net/NumberFormatter) -- [`Locale`](https://php.net/Locale) -- [`IntlDateFormatter`](https://php.net/IntlDateFormatter) - -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/lib/symfony/polyfill-intl-icu/Resources/currencies.php b/lib/symfony/polyfill-intl-icu/Resources/currencies.php deleted file mode 100644 index f802b7a89..000000000 --- a/lib/symfony/polyfill-intl-icu/Resources/currencies.php +++ /dev/null @@ -1,1321 +0,0 @@ -<?php - -return array ( - 'ADP' => - array ( - 0 => 'ADP', - 1 => 0, - 2 => 0, - ), - 'AED' => - array ( - 0 => 'AED', - ), - 'AFA' => - array ( - 0 => 'AFA', - ), - 'AFN' => - array ( - 0 => 'AFN', - 1 => 0, - 2 => 0, - ), - 'ALK' => - array ( - 0 => 'ALK', - ), - 'ALL' => - array ( - 0 => 'ALL', - 1 => 0, - 2 => 0, - ), - 'AMD' => - array ( - 0 => 'AMD', - 1 => 2, - 2 => 0, - ), - 'ANG' => - array ( - 0 => 'ANG', - ), - 'AOA' => - array ( - 0 => 'AOA', - ), - 'AOK' => - array ( - 0 => 'AOK', - ), - 'AON' => - array ( - 0 => 'AON', - ), - 'AOR' => - array ( - 0 => 'AOR', - ), - 'ARA' => - array ( - 0 => 'ARA', - ), - 'ARL' => - array ( - 0 => 'ARL', - ), - 'ARM' => - array ( - 0 => 'ARM', - ), - 'ARP' => - array ( - 0 => 'ARP', - ), - 'ARS' => - array ( - 0 => 'ARS', - ), - 'ATS' => - array ( - 0 => 'ATS', - ), - 'AUD' => - array ( - 0 => 'A$', - ), - 'AWG' => - array ( - 0 => 'AWG', - ), - 'AZM' => - array ( - 0 => 'AZM', - ), - 'AZN' => - array ( - 0 => 'AZN', - ), - 'BAD' => - array ( - 0 => 'BAD', - ), - 'BAM' => - array ( - 0 => 'BAM', - ), - 'BAN' => - array ( - 0 => 'BAN', - ), - 'BBD' => - array ( - 0 => 'BBD', - ), - 'BDT' => - array ( - 0 => 'BDT', - ), - 'BEC' => - array ( - 0 => 'BEC', - ), - 'BEF' => - array ( - 0 => 'BEF', - ), - 'BEL' => - array ( - 0 => 'BEL', - ), - 'BGL' => - array ( - 0 => 'BGL', - ), - 'BGM' => - array ( - 0 => 'BGM', - ), - 'BGN' => - array ( - 0 => 'BGN', - ), - 'BGO' => - array ( - 0 => 'BGO', - ), - 'BHD' => - array ( - 0 => 'BHD', - 1 => 3, - 2 => 0, - ), - 'BIF' => - array ( - 0 => 'BIF', - 1 => 0, - 2 => 0, - ), - 'BMD' => - array ( - 0 => 'BMD', - ), - 'BND' => - array ( - 0 => 'BND', - ), - 'BOB' => - array ( - 0 => 'BOB', - ), - 'BOL' => - array ( - 0 => 'BOL', - ), - 'BOP' => - array ( - 0 => 'BOP', - ), - 'BOV' => - array ( - 0 => 'BOV', - ), - 'BRB' => - array ( - 0 => 'BRB', - ), - 'BRC' => - array ( - 0 => 'BRC', - ), - 'BRE' => - array ( - 0 => 'BRE', - ), - 'BRL' => - array ( - 0 => 'R$', - ), - 'BRN' => - array ( - 0 => 'BRN', - ), - 'BRR' => - array ( - 0 => 'BRR', - ), - 'BRZ' => - array ( - 0 => 'BRZ', - ), - 'BSD' => - array ( - 0 => 'BSD', - ), - 'BTN' => - array ( - 0 => 'BTN', - ), - 'BUK' => - array ( - 0 => 'BUK', - ), - 'BWP' => - array ( - 0 => 'BWP', - ), - 'BYB' => - array ( - 0 => 'BYB', - ), - 'BYN' => - array ( - 0 => 'BYN', - 1 => 2, - 2 => 0, - ), - 'BYR' => - array ( - 0 => 'BYR', - 1 => 0, - 2 => 0, - ), - 'BZD' => - array ( - 0 => 'BZD', - ), - 'CAD' => - array ( - 0 => 'CA$', - 1 => 2, - 2 => 0, - ), - 'CDF' => - array ( - 0 => 'CDF', - ), - 'CHE' => - array ( - 0 => 'CHE', - ), - 'CHF' => - array ( - 0 => 'CHF', - 1 => 2, - 2 => 0, - ), - 'CHW' => - array ( - 0 => 'CHW', - ), - 'CLE' => - array ( - 0 => 'CLE', - ), - 'CLF' => - array ( - 0 => 'CLF', - 1 => 4, - 2 => 0, - ), - 'CLP' => - array ( - 0 => 'CLP', - 1 => 0, - 2 => 0, - ), - 'CNH' => - array ( - 0 => 'CNH', - ), - 'CNX' => - array ( - 0 => 'CNX', - ), - 'CNY' => - array ( - 0 => 'CN¥', - ), - 'COP' => - array ( - 0 => 'COP', - 1 => 2, - 2 => 0, - ), - 'COU' => - array ( - 0 => 'COU', - ), - 'CRC' => - array ( - 0 => 'CRC', - 1 => 2, - 2 => 0, - ), - 'CSD' => - array ( - 0 => 'CSD', - ), - 'CSK' => - array ( - 0 => 'CSK', - ), - 'CUC' => - array ( - 0 => 'CUC', - ), - 'CUP' => - array ( - 0 => 'CUP', - ), - 'CVE' => - array ( - 0 => 'CVE', - ), - 'CYP' => - array ( - 0 => 'CYP', - ), - 'CZK' => - array ( - 0 => 'CZK', - 1 => 2, - 2 => 0, - ), - 'DDM' => - array ( - 0 => 'DDM', - ), - 'DEM' => - array ( - 0 => 'DEM', - ), - 'DJF' => - array ( - 0 => 'DJF', - 1 => 0, - 2 => 0, - ), - 'DKK' => - array ( - 0 => 'DKK', - 1 => 2, - 2 => 0, - ), - 'DOP' => - array ( - 0 => 'DOP', - ), - 'DZD' => - array ( - 0 => 'DZD', - ), - 'ECS' => - array ( - 0 => 'ECS', - ), - 'ECV' => - array ( - 0 => 'ECV', - ), - 'EEK' => - array ( - 0 => 'EEK', - ), - 'EGP' => - array ( - 0 => 'EGP', - ), - 'ERN' => - array ( - 0 => 'ERN', - ), - 'ESA' => - array ( - 0 => 'ESA', - ), - 'ESB' => - array ( - 0 => 'ESB', - ), - 'ESP' => - array ( - 0 => 'ESP', - 1 => 0, - 2 => 0, - ), - 'ETB' => - array ( - 0 => 'ETB', - ), - 'EUR' => - array ( - 0 => '€', - ), - 'FIM' => - array ( - 0 => 'FIM', - ), - 'FJD' => - array ( - 0 => 'FJD', - ), - 'FKP' => - array ( - 0 => 'FKP', - ), - 'FRF' => - array ( - 0 => 'FRF', - ), - 'GBP' => - array ( - 0 => '£', - ), - 'GEK' => - array ( - 0 => 'GEK', - ), - 'GEL' => - array ( - 0 => 'GEL', - ), - 'GHC' => - array ( - 0 => 'GHC', - ), - 'GHS' => - array ( - 0 => 'GHS', - ), - 'GIP' => - array ( - 0 => 'GIP', - ), - 'GMD' => - array ( - 0 => 'GMD', - ), - 'GNF' => - array ( - 0 => 'GNF', - 1 => 0, - 2 => 0, - ), - 'GNS' => - array ( - 0 => 'GNS', - ), - 'GQE' => - array ( - 0 => 'GQE', - ), - 'GRD' => - array ( - 0 => 'GRD', - ), - 'GTQ' => - array ( - 0 => 'GTQ', - ), - 'GWE' => - array ( - 0 => 'GWE', - ), - 'GWP' => - array ( - 0 => 'GWP', - ), - 'GYD' => - array ( - 0 => 'GYD', - 1 => 2, - 2 => 0, - ), - 'HKD' => - array ( - 0 => 'HK$', - ), - 'HNL' => - array ( - 0 => 'HNL', - ), - 'HRD' => - array ( - 0 => 'HRD', - ), - 'HRK' => - array ( - 0 => 'HRK', - ), - 'HTG' => - array ( - 0 => 'HTG', - ), - 'HUF' => - array ( - 0 => 'HUF', - 1 => 2, - 2 => 0, - ), - 'IDR' => - array ( - 0 => 'IDR', - 1 => 2, - 2 => 0, - ), - 'IEP' => - array ( - 0 => 'IEP', - ), - 'ILP' => - array ( - 0 => 'ILP', - ), - 'ILR' => - array ( - 0 => 'ILR', - ), - 'ILS' => - array ( - 0 => '₪', - ), - 'INR' => - array ( - 0 => '₹', - ), - 'IQD' => - array ( - 0 => 'IQD', - 1 => 0, - 2 => 0, - ), - 'IRR' => - array ( - 0 => 'IRR', - 1 => 0, - 2 => 0, - ), - 'ISJ' => - array ( - 0 => 'ISJ', - ), - 'ISK' => - array ( - 0 => 'ISK', - 1 => 0, - 2 => 0, - ), - 'ITL' => - array ( - 0 => 'ITL', - 1 => 0, - 2 => 0, - ), - 'JMD' => - array ( - 0 => 'JMD', - ), - 'JOD' => - array ( - 0 => 'JOD', - 1 => 3, - 2 => 0, - ), - 'JPY' => - array ( - 0 => '¥', - 1 => 0, - 2 => 0, - ), - 'KES' => - array ( - 0 => 'KES', - ), - 'KGS' => - array ( - 0 => 'KGS', - ), - 'KHR' => - array ( - 0 => 'KHR', - ), - 'KMF' => - array ( - 0 => 'KMF', - 1 => 0, - 2 => 0, - ), - 'KPW' => - array ( - 0 => 'KPW', - 1 => 0, - 2 => 0, - ), - 'KRH' => - array ( - 0 => 'KRH', - ), - 'KRO' => - array ( - 0 => 'KRO', - ), - 'KRW' => - array ( - 0 => '₩', - 1 => 0, - 2 => 0, - ), - 'KWD' => - array ( - 0 => 'KWD', - 1 => 3, - 2 => 0, - ), - 'KYD' => - array ( - 0 => 'KYD', - ), - 'KZT' => - array ( - 0 => 'KZT', - ), - 'LAK' => - array ( - 0 => 'LAK', - 1 => 0, - 2 => 0, - ), - 'LBP' => - array ( - 0 => 'LBP', - 1 => 0, - 2 => 0, - ), - 'LKR' => - array ( - 0 => 'LKR', - ), - 'LRD' => - array ( - 0 => 'LRD', - ), - 'LSL' => - array ( - 0 => 'LSL', - ), - 'LTL' => - array ( - 0 => 'LTL', - ), - 'LTT' => - array ( - 0 => 'LTT', - ), - 'LUC' => - array ( - 0 => 'LUC', - ), - 'LUF' => - array ( - 0 => 'LUF', - 1 => 0, - 2 => 0, - ), - 'LUL' => - array ( - 0 => 'LUL', - ), - 'LVL' => - array ( - 0 => 'LVL', - ), - 'LVR' => - array ( - 0 => 'LVR', - ), - 'LYD' => - array ( - 0 => 'LYD', - 1 => 3, - 2 => 0, - ), - 'MAD' => - array ( - 0 => 'MAD', - ), - 'MAF' => - array ( - 0 => 'MAF', - ), - 'MCF' => - array ( - 0 => 'MCF', - ), - 'MDC' => - array ( - 0 => 'MDC', - ), - 'MDL' => - array ( - 0 => 'MDL', - ), - 'MGA' => - array ( - 0 => 'MGA', - 1 => 0, - 2 => 0, - ), - 'MGF' => - array ( - 0 => 'MGF', - 1 => 0, - 2 => 0, - ), - 'MKD' => - array ( - 0 => 'MKD', - ), - 'MKN' => - array ( - 0 => 'MKN', - ), - 'MLF' => - array ( - 0 => 'MLF', - ), - 'MMK' => - array ( - 0 => 'MMK', - 1 => 0, - 2 => 0, - ), - 'MNT' => - array ( - 0 => 'MNT', - 1 => 2, - 2 => 0, - ), - 'MOP' => - array ( - 0 => 'MOP', - ), - 'MRO' => - array ( - 0 => 'MRO', - 1 => 0, - 2 => 0, - ), - 'MRU' => - array ( - 0 => 'MRU', - ), - 'MTL' => - array ( - 0 => 'MTL', - ), - 'MTP' => - array ( - 0 => 'MTP', - ), - 'MUR' => - array ( - 0 => 'MUR', - 1 => 2, - 2 => 0, - ), - 'MVP' => - array ( - 0 => 'MVP', - ), - 'MVR' => - array ( - 0 => 'MVR', - ), - 'MWK' => - array ( - 0 => 'MWK', - ), - 'MXN' => - array ( - 0 => 'MX$', - ), - 'MXP' => - array ( - 0 => 'MXP', - ), - 'MXV' => - array ( - 0 => 'MXV', - ), - 'MYR' => - array ( - 0 => 'MYR', - ), - 'MZE' => - array ( - 0 => 'MZE', - ), - 'MZM' => - array ( - 0 => 'MZM', - ), - 'MZN' => - array ( - 0 => 'MZN', - ), - 'NAD' => - array ( - 0 => 'NAD', - ), - 'NGN' => - array ( - 0 => 'NGN', - ), - 'NIC' => - array ( - 0 => 'NIC', - ), - 'NIO' => - array ( - 0 => 'NIO', - ), - 'NLG' => - array ( - 0 => 'NLG', - ), - 'NOK' => - array ( - 0 => 'NOK', - 1 => 2, - 2 => 0, - ), - 'NPR' => - array ( - 0 => 'NPR', - ), - 'NZD' => - array ( - 0 => 'NZ$', - ), - 'OMR' => - array ( - 0 => 'OMR', - 1 => 3, - 2 => 0, - ), - 'PAB' => - array ( - 0 => 'PAB', - ), - 'PEI' => - array ( - 0 => 'PEI', - ), - 'PEN' => - array ( - 0 => 'PEN', - ), - 'PES' => - array ( - 0 => 'PES', - ), - 'PGK' => - array ( - 0 => 'PGK', - ), - 'PHP' => - array ( - 0 => '₱', - ), - 'PKR' => - array ( - 0 => 'PKR', - 1 => 2, - 2 => 0, - ), - 'PLN' => - array ( - 0 => 'PLN', - ), - 'PLZ' => - array ( - 0 => 'PLZ', - ), - 'PTE' => - array ( - 0 => 'PTE', - ), - 'PYG' => - array ( - 0 => 'PYG', - 1 => 0, - 2 => 0, - ), - 'QAR' => - array ( - 0 => 'QAR', - ), - 'RHD' => - array ( - 0 => 'RHD', - ), - 'ROL' => - array ( - 0 => 'ROL', - ), - 'RON' => - array ( - 0 => 'RON', - ), - 'RSD' => - array ( - 0 => 'RSD', - 1 => 0, - 2 => 0, - ), - 'RUB' => - array ( - 0 => 'RUB', - ), - 'RUR' => - array ( - 0 => 'RUR', - ), - 'RWF' => - array ( - 0 => 'RWF', - 1 => 0, - 2 => 0, - ), - 'SAR' => - array ( - 0 => 'SAR', - ), - 'SBD' => - array ( - 0 => 'SBD', - ), - 'SCR' => - array ( - 0 => 'SCR', - ), - 'SDD' => - array ( - 0 => 'SDD', - ), - 'SDG' => - array ( - 0 => 'SDG', - ), - 'SDP' => - array ( - 0 => 'SDP', - ), - 'SEK' => - array ( - 0 => 'SEK', - 1 => 2, - 2 => 0, - ), - 'SGD' => - array ( - 0 => 'SGD', - ), - 'SHP' => - array ( - 0 => 'SHP', - ), - 'SIT' => - array ( - 0 => 'SIT', - ), - 'SKK' => - array ( - 0 => 'SKK', - ), - 'SLE' => - array ( - 0 => 'SLE', - 1 => 2, - 2 => 0, - ), - 'SLL' => - array ( - 0 => 'SLL', - 1 => 0, - 2 => 0, - ), - 'SOS' => - array ( - 0 => 'SOS', - 1 => 0, - 2 => 0, - ), - 'SRD' => - array ( - 0 => 'SRD', - ), - 'SRG' => - array ( - 0 => 'SRG', - ), - 'SSP' => - array ( - 0 => 'SSP', - ), - 'STD' => - array ( - 0 => 'STD', - 1 => 0, - 2 => 0, - ), - 'STN' => - array ( - 0 => 'STN', - ), - 'SUR' => - array ( - 0 => 'SUR', - ), - 'SVC' => - array ( - 0 => 'SVC', - ), - 'SYP' => - array ( - 0 => 'SYP', - 1 => 0, - 2 => 0, - ), - 'SZL' => - array ( - 0 => 'SZL', - ), - 'THB' => - array ( - 0 => 'THB', - ), - 'TJR' => - array ( - 0 => 'TJR', - ), - 'TJS' => - array ( - 0 => 'TJS', - ), - 'TMM' => - array ( - 0 => 'TMM', - 1 => 0, - 2 => 0, - ), - 'TMT' => - array ( - 0 => 'TMT', - ), - 'TND' => - array ( - 0 => 'TND', - 1 => 3, - 2 => 0, - ), - 'TOP' => - array ( - 0 => 'TOP', - ), - 'TPE' => - array ( - 0 => 'TPE', - ), - 'TRL' => - array ( - 0 => 'TRL', - 1 => 0, - 2 => 0, - ), - 'TRY' => - array ( - 0 => 'TRY', - ), - 'TTD' => - array ( - 0 => 'TTD', - ), - 'TWD' => - array ( - 0 => 'NT$', - 1 => 2, - 2 => 0, - ), - 'TZS' => - array ( - 0 => 'TZS', - 1 => 2, - 2 => 0, - ), - 'UAH' => - array ( - 0 => 'UAH', - ), - 'UAK' => - array ( - 0 => 'UAK', - ), - 'UGS' => - array ( - 0 => 'UGS', - ), - 'UGX' => - array ( - 0 => 'UGX', - 1 => 0, - 2 => 0, - ), - 'USD' => - array ( - 0 => '$', - ), - 'USN' => - array ( - 0 => 'USN', - ), - 'USS' => - array ( - 0 => 'USS', - ), - 'UYI' => - array ( - 0 => 'UYI', - 1 => 0, - 2 => 0, - ), - 'UYP' => - array ( - 0 => 'UYP', - ), - 'UYU' => - array ( - 0 => 'UYU', - ), - 'UYW' => - array ( - 0 => 'UYW', - 1 => 4, - 2 => 0, - ), - 'UZS' => - array ( - 0 => 'UZS', - 1 => 2, - 2 => 0, - ), - 'VEB' => - array ( - 0 => 'VEB', - ), - 'VED' => - array ( - 0 => 'VED', - ), - 'VEF' => - array ( - 0 => 'VEF', - 1 => 2, - 2 => 0, - ), - 'VES' => - array ( - 0 => 'VES', - ), - 'VND' => - array ( - 0 => '₫', - 1 => 0, - 2 => 0, - ), - 'VNN' => - array ( - 0 => 'VNN', - ), - 'VUV' => - array ( - 0 => 'VUV', - 1 => 0, - 2 => 0, - ), - 'WST' => - array ( - 0 => 'WST', - ), - 'XAF' => - array ( - 0 => 'FCFA', - 1 => 0, - 2 => 0, - ), - 'XCD' => - array ( - 0 => 'EC$', - ), - 'XEU' => - array ( - 0 => 'XEU', - ), - 'XFO' => - array ( - 0 => 'XFO', - ), - 'XFU' => - array ( - 0 => 'XFU', - ), - 'XOF' => - array ( - 0 => 'F CFA', - 1 => 0, - 2 => 0, - ), - 'XPF' => - array ( - 0 => 'CFPF', - 1 => 0, - 2 => 0, - ), - 'XRE' => - array ( - 0 => 'XRE', - ), - 'YDD' => - array ( - 0 => 'YDD', - ), - 'YER' => - array ( - 0 => 'YER', - 1 => 0, - 2 => 0, - ), - 'YUD' => - array ( - 0 => 'YUD', - ), - 'YUM' => - array ( - 0 => 'YUM', - ), - 'YUN' => - array ( - 0 => 'YUN', - ), - 'YUR' => - array ( - 0 => 'YUR', - ), - 'ZAL' => - array ( - 0 => 'ZAL', - ), - 'ZAR' => - array ( - 0 => 'ZAR', - ), - 'ZMK' => - array ( - 0 => 'ZMK', - 1 => 0, - 2 => 0, - ), - 'ZMW' => - array ( - 0 => 'ZMW', - ), - 'ZRN' => - array ( - 0 => 'ZRN', - ), - 'ZRZ' => - array ( - 0 => 'ZRZ', - ), - 'ZWD' => - array ( - 0 => 'ZWD', - 1 => 0, - 2 => 0, - ), - 'ZWL' => - array ( - 0 => 'ZWL', - ), - 'ZWR' => - array ( - 0 => 'ZWR', - ), - 'DEFAULT' => - array ( - 1 => 2, - 2 => 0, - ), -); diff --git a/lib/symfony/polyfill-intl-icu/Resources/stubs/Collator.php b/lib/symfony/polyfill-intl-icu/Resources/stubs/Collator.php deleted file mode 100644 index a1efbcb80..000000000 --- a/lib/symfony/polyfill-intl-icu/Resources/stubs/Collator.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Intl\Icu\Collator as CollatorPolyfill; - -/** - * Stub implementation for the Collator class of the intl extension. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class Collator extends CollatorPolyfill -{ -} diff --git a/lib/symfony/polyfill-intl-icu/Resources/stubs/IntlDateFormatter.php b/lib/symfony/polyfill-intl-icu/Resources/stubs/IntlDateFormatter.php deleted file mode 100644 index e7012008e..000000000 --- a/lib/symfony/polyfill-intl-icu/Resources/stubs/IntlDateFormatter.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Intl\Icu\IntlDateFormatter as IntlDateFormatterPolyfill; - -/** - * Stub implementation for the IntlDateFormatter class of the intl extension. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class IntlDateFormatter extends IntlDateFormatterPolyfill -{ -} diff --git a/lib/symfony/polyfill-intl-icu/Resources/stubs/Locale.php b/lib/symfony/polyfill-intl-icu/Resources/stubs/Locale.php deleted file mode 100644 index f1b951e13..000000000 --- a/lib/symfony/polyfill-intl-icu/Resources/stubs/Locale.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Intl\Icu\Locale as LocalePolyfill; - -/** - * Stub implementation for the Locale class of the intl extension. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class Locale extends LocalePolyfill -{ -} diff --git a/lib/symfony/polyfill-intl-icu/Resources/stubs/NumberFormatter.php b/lib/symfony/polyfill-intl-icu/Resources/stubs/NumberFormatter.php deleted file mode 100644 index 9288b9dd6..000000000 --- a/lib/symfony/polyfill-intl-icu/Resources/stubs/NumberFormatter.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Intl\Icu\NumberFormatter as NumberFormatterPolyfill; - -/** - * Stub implementation for the NumberFormatter class of the intl extension. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @see IntlNumberFormatter - */ -class NumberFormatter extends NumberFormatterPolyfill -{ -} diff --git a/lib/symfony/polyfill-intl-icu/bootstrap.php b/lib/symfony/polyfill-intl-icu/bootstrap.php deleted file mode 100644 index 77d754379..000000000 --- a/lib/symfony/polyfill-intl-icu/bootstrap.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Intl\Icu as p; - -if (extension_loaded('intl')) { - return; -} - -if (\PHP_VERSION_ID >= 80000) { - return require __DIR__.'/bootstrap80.php'; -} - -if (!function_exists('intl_is_failure')) { - function intl_is_failure($errorCode) { return p\Icu::isFailure($errorCode); } -} -if (!function_exists('intl_get_error_code')) { - function intl_get_error_code() { return p\Icu::getErrorCode(); } -} -if (!function_exists('intl_get_error_message')) { - function intl_get_error_message() { return p\Icu::getErrorMessage(); } -} -if (!function_exists('intl_error_name')) { - function intl_error_name($errorCode) { return p\Icu::getErrorName($errorCode); } -} diff --git a/lib/symfony/polyfill-intl-icu/bootstrap80.php b/lib/symfony/polyfill-intl-icu/bootstrap80.php deleted file mode 100644 index ee1653a38..000000000 --- a/lib/symfony/polyfill-intl-icu/bootstrap80.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Intl\Icu as p; - -if (!function_exists('intl_is_failure')) { - function intl_is_failure(?int $errorCode): bool { return p\Icu::isFailure((int) $errorCode); } -} -if (!function_exists('intl_get_error_code')) { - function intl_get_error_code(): int { return p\Icu::getErrorCode(); } -} -if (!function_exists('intl_get_error_message')) { - function intl_get_error_message(): string { return p\Icu::getErrorMessage(); } -} -if (!function_exists('intl_error_name')) { - function intl_error_name(?int $errorCode): string { return p\Icu::getErrorName((int) $errorCode); } -} diff --git a/lib/symfony/polyfill-intl-icu/composer.json b/lib/symfony/polyfill-intl-icu/composer.json deleted file mode 100644 index 761d80a69..000000000 --- a/lib/symfony/polyfill-intl-icu/composer.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "symfony/polyfill-intl-icu", - "type": "library", - "description": "Symfony polyfill for intl's ICU-related data and classes", - "keywords": ["polyfill", "shim", "compatibility", "portable", "intl", "icu"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.1" - }, - "autoload": { - "files": [ "bootstrap.php" ], - "psr-4": { "Symfony\\Polyfill\\Intl\\Icu\\": "" }, - "classmap": [ "Resources/stubs" ], - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "suggest": { - "ext-intl": "For best performance and support of other locales than \"en\"" - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - } -} diff --git a/lib/symfony/polyfill-intl-idn/Idn.php b/lib/symfony/polyfill-intl-idn/Idn.php deleted file mode 100644 index fee3026df..000000000 --- a/lib/symfony/polyfill-intl-idn/Idn.php +++ /dev/null @@ -1,925 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> and Trevor Rowbotham <trevor.rowbotham@pm.me> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Idn; - -use Exception; -use Normalizer; -use Symfony\Polyfill\Intl\Idn\Resources\unidata\DisallowedRanges; -use Symfony\Polyfill\Intl\Idn\Resources\unidata\Regex; - -/** - * @see https://www.unicode.org/reports/tr46/ - * - * @internal - */ -final class Idn -{ - public const ERROR_EMPTY_LABEL = 1; - public const ERROR_LABEL_TOO_LONG = 2; - public const ERROR_DOMAIN_NAME_TOO_LONG = 4; - public const ERROR_LEADING_HYPHEN = 8; - public const ERROR_TRAILING_HYPHEN = 0x10; - public const ERROR_HYPHEN_3_4 = 0x20; - public const ERROR_LEADING_COMBINING_MARK = 0x40; - public const ERROR_DISALLOWED = 0x80; - public const ERROR_PUNYCODE = 0x100; - public const ERROR_LABEL_HAS_DOT = 0x200; - public const ERROR_INVALID_ACE_LABEL = 0x400; - public const ERROR_BIDI = 0x800; - public const ERROR_CONTEXTJ = 0x1000; - public const ERROR_CONTEXTO_PUNCTUATION = 0x2000; - public const ERROR_CONTEXTO_DIGITS = 0x4000; - - public const INTL_IDNA_VARIANT_2003 = 0; - public const INTL_IDNA_VARIANT_UTS46 = 1; - - public const IDNA_DEFAULT = 0; - public const IDNA_ALLOW_UNASSIGNED = 1; - public const IDNA_USE_STD3_RULES = 2; - public const IDNA_CHECK_BIDI = 4; - public const IDNA_CHECK_CONTEXTJ = 8; - public const IDNA_NONTRANSITIONAL_TO_ASCII = 16; - public const IDNA_NONTRANSITIONAL_TO_UNICODE = 32; - - public const MAX_DOMAIN_SIZE = 253; - public const MAX_LABEL_SIZE = 63; - - public const BASE = 36; - public const TMIN = 1; - public const TMAX = 26; - public const SKEW = 38; - public const DAMP = 700; - public const INITIAL_BIAS = 72; - public const INITIAL_N = 128; - public const DELIMITER = '-'; - public const MAX_INT = 2147483647; - - /** - * Contains the numeric value of a basic code point (for use in representing integers) in the - * range 0 to BASE-1, or -1 if b is does not represent a value. - * - * @var array<int, int> - */ - private static $basicToDigit = [ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1, - - -1, 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, 25, -1, -1, -1, -1, -1, - - -1, 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, 25, -1, -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - ]; - - /** - * @var array<int, int> - */ - private static $virama; - - /** - * @var array<int, string> - */ - private static $mapped; - - /** - * @var array<int, bool> - */ - private static $ignored; - - /** - * @var array<int, string> - */ - private static $deviation; - - /** - * @var array<int, bool> - */ - private static $disallowed; - - /** - * @var array<int, string> - */ - private static $disallowed_STD3_mapped; - - /** - * @var array<int, bool> - */ - private static $disallowed_STD3_valid; - - /** - * @var bool - */ - private static $mappingTableLoaded = false; - - /** - * @see https://www.unicode.org/reports/tr46/#ToASCII - * - * @param string $domainName - * @param int $options - * @param int $variant - * @param array $idna_info - * - * @return string|false - */ - public static function idn_to_ascii($domainName, $options = self::IDNA_DEFAULT, $variant = self::INTL_IDNA_VARIANT_UTS46, &$idna_info = []) - { - if (\PHP_VERSION_ID >= 70200 && self::INTL_IDNA_VARIANT_2003 === $variant) { - @trigger_error('idn_to_ascii(): INTL_IDNA_VARIANT_2003 is deprecated', \E_USER_DEPRECATED); - } - - $options = [ - 'CheckHyphens' => true, - 'CheckBidi' => self::INTL_IDNA_VARIANT_2003 === $variant || 0 !== ($options & self::IDNA_CHECK_BIDI), - 'CheckJoiners' => self::INTL_IDNA_VARIANT_UTS46 === $variant && 0 !== ($options & self::IDNA_CHECK_CONTEXTJ), - 'UseSTD3ASCIIRules' => 0 !== ($options & self::IDNA_USE_STD3_RULES), - 'Transitional_Processing' => self::INTL_IDNA_VARIANT_2003 === $variant || 0 === ($options & self::IDNA_NONTRANSITIONAL_TO_ASCII), - 'VerifyDnsLength' => true, - ]; - $info = new Info(); - $labels = self::process((string) $domainName, $options, $info); - - foreach ($labels as $i => $label) { - // Only convert labels to punycode that contain non-ASCII code points - if (1 === preg_match('/[^\x00-\x7F]/', $label)) { - try { - $label = 'xn--'.self::punycodeEncode($label); - } catch (Exception $e) { - $info->errors |= self::ERROR_PUNYCODE; - } - - $labels[$i] = $label; - } - } - - if ($options['VerifyDnsLength']) { - self::validateDomainAndLabelLength($labels, $info); - } - - $idna_info = [ - 'result' => implode('.', $labels), - 'isTransitionalDifferent' => $info->transitionalDifferent, - 'errors' => $info->errors, - ]; - - return 0 === $info->errors ? $idna_info['result'] : false; - } - - /** - * @see https://www.unicode.org/reports/tr46/#ToUnicode - * - * @param string $domainName - * @param int $options - * @param int $variant - * @param array $idna_info - * - * @return string|false - */ - public static function idn_to_utf8($domainName, $options = self::IDNA_DEFAULT, $variant = self::INTL_IDNA_VARIANT_UTS46, &$idna_info = []) - { - if (\PHP_VERSION_ID >= 70200 && self::INTL_IDNA_VARIANT_2003 === $variant) { - @trigger_error('idn_to_utf8(): INTL_IDNA_VARIANT_2003 is deprecated', \E_USER_DEPRECATED); - } - - $info = new Info(); - $labels = self::process((string) $domainName, [ - 'CheckHyphens' => true, - 'CheckBidi' => self::INTL_IDNA_VARIANT_2003 === $variant || 0 !== ($options & self::IDNA_CHECK_BIDI), - 'CheckJoiners' => self::INTL_IDNA_VARIANT_UTS46 === $variant && 0 !== ($options & self::IDNA_CHECK_CONTEXTJ), - 'UseSTD3ASCIIRules' => 0 !== ($options & self::IDNA_USE_STD3_RULES), - 'Transitional_Processing' => self::INTL_IDNA_VARIANT_2003 === $variant || 0 === ($options & self::IDNA_NONTRANSITIONAL_TO_UNICODE), - ], $info); - $idna_info = [ - 'result' => implode('.', $labels), - 'isTransitionalDifferent' => $info->transitionalDifferent, - 'errors' => $info->errors, - ]; - - return 0 === $info->errors ? $idna_info['result'] : false; - } - - /** - * @param string $label - * - * @return bool - */ - private static function isValidContextJ(array $codePoints, $label) - { - if (!isset(self::$virama)) { - self::$virama = require __DIR__.\DIRECTORY_SEPARATOR.'Resources'.\DIRECTORY_SEPARATOR.'unidata'.\DIRECTORY_SEPARATOR.'virama.php'; - } - - $offset = 0; - - foreach ($codePoints as $i => $codePoint) { - if (0x200C !== $codePoint && 0x200D !== $codePoint) { - continue; - } - - if (!isset($codePoints[$i - 1])) { - return false; - } - - // If Canonical_Combining_Class(Before(cp)) .eq. Virama Then True; - if (isset(self::$virama[$codePoints[$i - 1]])) { - continue; - } - - // If RegExpMatch((Joining_Type:{L,D})(Joining_Type:T)*\u200C(Joining_Type:T)*(Joining_Type:{R,D})) Then - // True; - // Generated RegExp = ([Joining_Type:{L,D}][Joining_Type:T]*\u200C[Joining_Type:T]*)[Joining_Type:{R,D}] - if (0x200C === $codePoint && 1 === preg_match(Regex::ZWNJ, $label, $matches, \PREG_OFFSET_CAPTURE, $offset)) { - $offset += \strlen($matches[1][0]); - - continue; - } - - return false; - } - - return true; - } - - /** - * @see https://www.unicode.org/reports/tr46/#ProcessingStepMap - * - * @param string $input - * @param array<string, bool> $options - * - * @return string - */ - private static function mapCodePoints($input, array $options, Info $info) - { - $str = ''; - $useSTD3ASCIIRules = $options['UseSTD3ASCIIRules']; - $transitional = $options['Transitional_Processing']; - - foreach (self::utf8Decode($input) as $codePoint) { - $data = self::lookupCodePointStatus($codePoint, $useSTD3ASCIIRules); - - switch ($data['status']) { - case 'disallowed': - $info->errors |= self::ERROR_DISALLOWED; - - // no break. - - case 'valid': - $str .= mb_chr($codePoint, 'utf-8'); - - break; - - case 'ignored': - // Do nothing. - break; - - case 'mapped': - $str .= $data['mapping']; - - break; - - case 'deviation': - $info->transitionalDifferent = true; - $str .= ($transitional ? $data['mapping'] : mb_chr($codePoint, 'utf-8')); - - break; - } - } - - return $str; - } - - /** - * @see https://www.unicode.org/reports/tr46/#Processing - * - * @param string $domain - * @param array<string, bool> $options - * - * @return array<int, string> - */ - private static function process($domain, array $options, Info $info) - { - // If VerifyDnsLength is not set, we are doing ToUnicode otherwise we are doing ToASCII and - // we need to respect the VerifyDnsLength option. - $checkForEmptyLabels = !isset($options['VerifyDnsLength']) || $options['VerifyDnsLength']; - - if ($checkForEmptyLabels && '' === $domain) { - $info->errors |= self::ERROR_EMPTY_LABEL; - - return [$domain]; - } - - // Step 1. Map each code point in the domain name string - $domain = self::mapCodePoints($domain, $options, $info); - - // Step 2. Normalize the domain name string to Unicode Normalization Form C. - if (!Normalizer::isNormalized($domain, Normalizer::FORM_C)) { - $domain = Normalizer::normalize($domain, Normalizer::FORM_C); - } - - // Step 3. Break the string into labels at U+002E (.) FULL STOP. - $labels = explode('.', $domain); - $lastLabelIndex = \count($labels) - 1; - - // Step 4. Convert and validate each label in the domain name string. - foreach ($labels as $i => $label) { - $validationOptions = $options; - - if ('xn--' === substr($label, 0, 4)) { - try { - $label = self::punycodeDecode(substr($label, 4)); - } catch (Exception $e) { - $info->errors |= self::ERROR_PUNYCODE; - - continue; - } - - $validationOptions['Transitional_Processing'] = false; - $labels[$i] = $label; - } - - self::validateLabel($label, $info, $validationOptions, $i > 0 && $i === $lastLabelIndex); - } - - if ($info->bidiDomain && !$info->validBidiDomain) { - $info->errors |= self::ERROR_BIDI; - } - - // Any input domain name string that does not record an error has been successfully - // processed according to this specification. Conversely, if an input domain_name string - // causes an error, then the processing of the input domain_name string fails. Determining - // what to do with error input is up to the caller, and not in the scope of this document. - return $labels; - } - - /** - * @see https://tools.ietf.org/html/rfc5893#section-2 - * - * @param string $label - */ - private static function validateBidiLabel($label, Info $info) - { - if (1 === preg_match(Regex::RTL_LABEL, $label)) { - $info->bidiDomain = true; - - // Step 1. The first character must be a character with Bidi property L, R, or AL. - // If it has the R or AL property, it is an RTL label - if (1 !== preg_match(Regex::BIDI_STEP_1_RTL, $label)) { - $info->validBidiDomain = false; - - return; - } - - // Step 2. In an RTL label, only characters with the Bidi properties R, AL, AN, EN, ES, - // CS, ET, ON, BN, or NSM are allowed. - if (1 === preg_match(Regex::BIDI_STEP_2, $label)) { - $info->validBidiDomain = false; - - return; - } - - // Step 3. In an RTL label, the end of the label must be a character with Bidi property - // R, AL, EN, or AN, followed by zero or more characters with Bidi property NSM. - if (1 !== preg_match(Regex::BIDI_STEP_3, $label)) { - $info->validBidiDomain = false; - - return; - } - - // Step 4. In an RTL label, if an EN is present, no AN may be present, and vice versa. - if (1 === preg_match(Regex::BIDI_STEP_4_AN, $label) && 1 === preg_match(Regex::BIDI_STEP_4_EN, $label)) { - $info->validBidiDomain = false; - - return; - } - - return; - } - - // We are a LTR label - // Step 1. The first character must be a character with Bidi property L, R, or AL. - // If it has the L property, it is an LTR label. - if (1 !== preg_match(Regex::BIDI_STEP_1_LTR, $label)) { - $info->validBidiDomain = false; - - return; - } - - // Step 5. In an LTR label, only characters with the Bidi properties L, EN, - // ES, CS, ET, ON, BN, or NSM are allowed. - if (1 === preg_match(Regex::BIDI_STEP_5, $label)) { - $info->validBidiDomain = false; - - return; - } - - // Step 6.In an LTR label, the end of the label must be a character with Bidi property L or - // EN, followed by zero or more characters with Bidi property NSM. - if (1 !== preg_match(Regex::BIDI_STEP_6, $label)) { - $info->validBidiDomain = false; - - return; - } - } - - /** - * @param array<int, string> $labels - */ - private static function validateDomainAndLabelLength(array $labels, Info $info) - { - $maxDomainSize = self::MAX_DOMAIN_SIZE; - $length = \count($labels); - - // Number of "." delimiters. - $domainLength = $length - 1; - - // If the last label is empty and it is not the first label, then it is the root label. - // Increase the max size by 1, making it 254, to account for the root label's "." - // delimiter. This also means we don't need to check the last label's length for being too - // long. - if ($length > 1 && '' === $labels[$length - 1]) { - ++$maxDomainSize; - --$length; - } - - for ($i = 0; $i < $length; ++$i) { - $bytes = \strlen($labels[$i]); - $domainLength += $bytes; - - if ($bytes > self::MAX_LABEL_SIZE) { - $info->errors |= self::ERROR_LABEL_TOO_LONG; - } - } - - if ($domainLength > $maxDomainSize) { - $info->errors |= self::ERROR_DOMAIN_NAME_TOO_LONG; - } - } - - /** - * @see https://www.unicode.org/reports/tr46/#Validity_Criteria - * - * @param string $label - * @param array<string, bool> $options - * @param bool $canBeEmpty - */ - private static function validateLabel($label, Info $info, array $options, $canBeEmpty) - { - if ('' === $label) { - if (!$canBeEmpty && (!isset($options['VerifyDnsLength']) || $options['VerifyDnsLength'])) { - $info->errors |= self::ERROR_EMPTY_LABEL; - } - - return; - } - - // Step 1. The label must be in Unicode Normalization Form C. - if (!Normalizer::isNormalized($label, Normalizer::FORM_C)) { - $info->errors |= self::ERROR_INVALID_ACE_LABEL; - } - - $codePoints = self::utf8Decode($label); - - if ($options['CheckHyphens']) { - // Step 2. If CheckHyphens, the label must not contain a U+002D HYPHEN-MINUS character - // in both the thrid and fourth positions. - if (isset($codePoints[2], $codePoints[3]) && 0x002D === $codePoints[2] && 0x002D === $codePoints[3]) { - $info->errors |= self::ERROR_HYPHEN_3_4; - } - - // Step 3. If CheckHyphens, the label must neither begin nor end with a U+002D - // HYPHEN-MINUS character. - if ('-' === substr($label, 0, 1)) { - $info->errors |= self::ERROR_LEADING_HYPHEN; - } - - if ('-' === substr($label, -1, 1)) { - $info->errors |= self::ERROR_TRAILING_HYPHEN; - } - } - - // Step 4. The label must not contain a U+002E (.) FULL STOP. - if (false !== strpos($label, '.')) { - $info->errors |= self::ERROR_LABEL_HAS_DOT; - } - - // Step 5. The label must not begin with a combining mark, that is: General_Category=Mark. - if (1 === preg_match(Regex::COMBINING_MARK, $label)) { - $info->errors |= self::ERROR_LEADING_COMBINING_MARK; - } - - // Step 6. Each code point in the label must only have certain status values according to - // Section 5, IDNA Mapping Table: - $transitional = $options['Transitional_Processing']; - $useSTD3ASCIIRules = $options['UseSTD3ASCIIRules']; - - foreach ($codePoints as $codePoint) { - $data = self::lookupCodePointStatus($codePoint, $useSTD3ASCIIRules); - $status = $data['status']; - - if ('valid' === $status || (!$transitional && 'deviation' === $status)) { - continue; - } - - $info->errors |= self::ERROR_DISALLOWED; - - break; - } - - // Step 7. If CheckJoiners, the label must satisify the ContextJ rules from Appendix A, in - // The Unicode Code Points and Internationalized Domain Names for Applications (IDNA) - // [IDNA2008]. - if ($options['CheckJoiners'] && !self::isValidContextJ($codePoints, $label)) { - $info->errors |= self::ERROR_CONTEXTJ; - } - - // Step 8. If CheckBidi, and if the domain name is a Bidi domain name, then the label must - // satisfy all six of the numbered conditions in [IDNA2008] RFC 5893, Section 2. - if ($options['CheckBidi'] && (!$info->bidiDomain || $info->validBidiDomain)) { - self::validateBidiLabel($label, $info); - } - } - - /** - * @see https://tools.ietf.org/html/rfc3492#section-6.2 - * - * @param string $input - * - * @return string - */ - private static function punycodeDecode($input) - { - $n = self::INITIAL_N; - $out = 0; - $i = 0; - $bias = self::INITIAL_BIAS; - $lastDelimIndex = strrpos($input, self::DELIMITER); - $b = false === $lastDelimIndex ? 0 : $lastDelimIndex; - $inputLength = \strlen($input); - $output = []; - $bytes = array_map('ord', str_split($input)); - - for ($j = 0; $j < $b; ++$j) { - if ($bytes[$j] > 0x7F) { - throw new Exception('Invalid input'); - } - - $output[$out++] = $input[$j]; - } - - if ($b > 0) { - ++$b; - } - - for ($in = $b; $in < $inputLength; ++$out) { - $oldi = $i; - $w = 1; - - for ($k = self::BASE; /* no condition */; $k += self::BASE) { - if ($in >= $inputLength) { - throw new Exception('Invalid input'); - } - - $digit = self::$basicToDigit[$bytes[$in++] & 0xFF]; - - if ($digit < 0) { - throw new Exception('Invalid input'); - } - - if ($digit > intdiv(self::MAX_INT - $i, $w)) { - throw new Exception('Integer overflow'); - } - - $i += $digit * $w; - - if ($k <= $bias) { - $t = self::TMIN; - } elseif ($k >= $bias + self::TMAX) { - $t = self::TMAX; - } else { - $t = $k - $bias; - } - - if ($digit < $t) { - break; - } - - $baseMinusT = self::BASE - $t; - - if ($w > intdiv(self::MAX_INT, $baseMinusT)) { - throw new Exception('Integer overflow'); - } - - $w *= $baseMinusT; - } - - $outPlusOne = $out + 1; - $bias = self::adaptBias($i - $oldi, $outPlusOne, 0 === $oldi); - - if (intdiv($i, $outPlusOne) > self::MAX_INT - $n) { - throw new Exception('Integer overflow'); - } - - $n += intdiv($i, $outPlusOne); - $i %= $outPlusOne; - array_splice($output, $i++, 0, [mb_chr($n, 'utf-8')]); - } - - return implode('', $output); - } - - /** - * @see https://tools.ietf.org/html/rfc3492#section-6.3 - * - * @param string $input - * - * @return string - */ - private static function punycodeEncode($input) - { - $n = self::INITIAL_N; - $delta = 0; - $out = 0; - $bias = self::INITIAL_BIAS; - $inputLength = 0; - $output = ''; - $iter = self::utf8Decode($input); - - foreach ($iter as $codePoint) { - ++$inputLength; - - if ($codePoint < 0x80) { - $output .= \chr($codePoint); - ++$out; - } - } - - $h = $out; - $b = $out; - - if ($b > 0) { - $output .= self::DELIMITER; - ++$out; - } - - while ($h < $inputLength) { - $m = self::MAX_INT; - - foreach ($iter as $codePoint) { - if ($codePoint >= $n && $codePoint < $m) { - $m = $codePoint; - } - } - - if ($m - $n > intdiv(self::MAX_INT - $delta, $h + 1)) { - throw new Exception('Integer overflow'); - } - - $delta += ($m - $n) * ($h + 1); - $n = $m; - - foreach ($iter as $codePoint) { - if ($codePoint < $n && 0 === ++$delta) { - throw new Exception('Integer overflow'); - } - - if ($codePoint === $n) { - $q = $delta; - - for ($k = self::BASE; /* no condition */; $k += self::BASE) { - if ($k <= $bias) { - $t = self::TMIN; - } elseif ($k >= $bias + self::TMAX) { - $t = self::TMAX; - } else { - $t = $k - $bias; - } - - if ($q < $t) { - break; - } - - $qMinusT = $q - $t; - $baseMinusT = self::BASE - $t; - $output .= self::encodeDigit($t + ($qMinusT) % ($baseMinusT), false); - ++$out; - $q = intdiv($qMinusT, $baseMinusT); - } - - $output .= self::encodeDigit($q, false); - ++$out; - $bias = self::adaptBias($delta, $h + 1, $h === $b); - $delta = 0; - ++$h; - } - } - - ++$delta; - ++$n; - } - - return $output; - } - - /** - * @see https://tools.ietf.org/html/rfc3492#section-6.1 - * - * @param int $delta - * @param int $numPoints - * @param bool $firstTime - * - * @return int - */ - private static function adaptBias($delta, $numPoints, $firstTime) - { - // xxx >> 1 is a faster way of doing intdiv(xxx, 2) - $delta = $firstTime ? intdiv($delta, self::DAMP) : $delta >> 1; - $delta += intdiv($delta, $numPoints); - $k = 0; - - while ($delta > ((self::BASE - self::TMIN) * self::TMAX) >> 1) { - $delta = intdiv($delta, self::BASE - self::TMIN); - $k += self::BASE; - } - - return $k + intdiv((self::BASE - self::TMIN + 1) * $delta, $delta + self::SKEW); - } - - /** - * @param int $d - * @param bool $flag - * - * @return string - */ - private static function encodeDigit($d, $flag) - { - return \chr($d + 22 + 75 * ($d < 26 ? 1 : 0) - (($flag ? 1 : 0) << 5)); - } - - /** - * Takes a UTF-8 encoded string and converts it into a series of integer code points. Any - * invalid byte sequences will be replaced by a U+FFFD replacement code point. - * - * @see https://encoding.spec.whatwg.org/#utf-8-decoder - * - * @param string $input - * - * @return array<int, int> - */ - private static function utf8Decode($input) - { - $bytesSeen = 0; - $bytesNeeded = 0; - $lowerBoundary = 0x80; - $upperBoundary = 0xBF; - $codePoint = 0; - $codePoints = []; - $length = \strlen($input); - - for ($i = 0; $i < $length; ++$i) { - $byte = \ord($input[$i]); - - if (0 === $bytesNeeded) { - if ($byte >= 0x00 && $byte <= 0x7F) { - $codePoints[] = $byte; - - continue; - } - - if ($byte >= 0xC2 && $byte <= 0xDF) { - $bytesNeeded = 1; - $codePoint = $byte & 0x1F; - } elseif ($byte >= 0xE0 && $byte <= 0xEF) { - if (0xE0 === $byte) { - $lowerBoundary = 0xA0; - } elseif (0xED === $byte) { - $upperBoundary = 0x9F; - } - - $bytesNeeded = 2; - $codePoint = $byte & 0xF; - } elseif ($byte >= 0xF0 && $byte <= 0xF4) { - if (0xF0 === $byte) { - $lowerBoundary = 0x90; - } elseif (0xF4 === $byte) { - $upperBoundary = 0x8F; - } - - $bytesNeeded = 3; - $codePoint = $byte & 0x7; - } else { - $codePoints[] = 0xFFFD; - } - - continue; - } - - if ($byte < $lowerBoundary || $byte > $upperBoundary) { - $codePoint = 0; - $bytesNeeded = 0; - $bytesSeen = 0; - $lowerBoundary = 0x80; - $upperBoundary = 0xBF; - --$i; - $codePoints[] = 0xFFFD; - - continue; - } - - $lowerBoundary = 0x80; - $upperBoundary = 0xBF; - $codePoint = ($codePoint << 6) | ($byte & 0x3F); - - if (++$bytesSeen !== $bytesNeeded) { - continue; - } - - $codePoints[] = $codePoint; - $codePoint = 0; - $bytesNeeded = 0; - $bytesSeen = 0; - } - - // String unexpectedly ended, so append a U+FFFD code point. - if (0 !== $bytesNeeded) { - $codePoints[] = 0xFFFD; - } - - return $codePoints; - } - - /** - * @param int $codePoint - * @param bool $useSTD3ASCIIRules - * - * @return array{status: string, mapping?: string} - */ - private static function lookupCodePointStatus($codePoint, $useSTD3ASCIIRules) - { - if (!self::$mappingTableLoaded) { - self::$mappingTableLoaded = true; - self::$mapped = require __DIR__.'/Resources/unidata/mapped.php'; - self::$ignored = require __DIR__.'/Resources/unidata/ignored.php'; - self::$deviation = require __DIR__.'/Resources/unidata/deviation.php'; - self::$disallowed = require __DIR__.'/Resources/unidata/disallowed.php'; - self::$disallowed_STD3_mapped = require __DIR__.'/Resources/unidata/disallowed_STD3_mapped.php'; - self::$disallowed_STD3_valid = require __DIR__.'/Resources/unidata/disallowed_STD3_valid.php'; - } - - if (isset(self::$mapped[$codePoint])) { - return ['status' => 'mapped', 'mapping' => self::$mapped[$codePoint]]; - } - - if (isset(self::$ignored[$codePoint])) { - return ['status' => 'ignored']; - } - - if (isset(self::$deviation[$codePoint])) { - return ['status' => 'deviation', 'mapping' => self::$deviation[$codePoint]]; - } - - if (isset(self::$disallowed[$codePoint]) || DisallowedRanges::inRange($codePoint)) { - return ['status' => 'disallowed']; - } - - $isDisallowedMapped = isset(self::$disallowed_STD3_mapped[$codePoint]); - - if ($isDisallowedMapped || isset(self::$disallowed_STD3_valid[$codePoint])) { - $status = 'disallowed'; - - if (!$useSTD3ASCIIRules) { - $status = $isDisallowedMapped ? 'mapped' : 'valid'; - } - - if ($isDisallowedMapped) { - return ['status' => $status, 'mapping' => self::$disallowed_STD3_mapped[$codePoint]]; - } - - return ['status' => $status]; - } - - return ['status' => 'valid']; - } -} diff --git a/lib/symfony/polyfill-intl-idn/Info.php b/lib/symfony/polyfill-intl-idn/Info.php deleted file mode 100644 index 25c3582b2..000000000 --- a/lib/symfony/polyfill-intl-idn/Info.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> and Trevor Rowbotham <trevor.rowbotham@pm.me> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Idn; - -/** - * @internal - */ -class Info -{ - public $bidiDomain = false; - public $errors = 0; - public $validBidiDomain = true; - public $transitionalDifferent = false; -} diff --git a/lib/symfony/polyfill-intl-idn/LICENSE b/lib/symfony/polyfill-intl-idn/LICENSE deleted file mode 100644 index 03c5e2577..000000000 --- a/lib/symfony/polyfill-intl-idn/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2018-2019 Fabien Potencier and Trevor Rowbotham <trevor.rowbotham@pm.me> - -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/lib/symfony/polyfill-intl-idn/README.md b/lib/symfony/polyfill-intl-idn/README.md deleted file mode 100644 index cae551705..000000000 --- a/lib/symfony/polyfill-intl-idn/README.md +++ /dev/null @@ -1,12 +0,0 @@ -Symfony Polyfill / Intl: Idn -============================ - -This component provides [`idn_to_ascii`](https://php.net/idn-to-ascii) and [`idn_to_utf8`](https://php.net/idn-to-utf8) functions to users who run php versions without 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/lib/symfony/polyfill-intl-idn/Resources/unidata/DisallowedRanges.php b/lib/symfony/polyfill-intl-idn/Resources/unidata/DisallowedRanges.php deleted file mode 100644 index 5bb70e48a..000000000 --- a/lib/symfony/polyfill-intl-idn/Resources/unidata/DisallowedRanges.php +++ /dev/null @@ -1,375 +0,0 @@ -<?php - -namespace Symfony\Polyfill\Intl\Idn\Resources\unidata; - -/** - * @internal - */ -final class DisallowedRanges -{ - /** - * @param int $codePoint - * - * @return bool - */ - public static function inRange($codePoint) - { - if ($codePoint >= 128 && $codePoint <= 159) { - return true; - } - - if ($codePoint >= 2155 && $codePoint <= 2207) { - return true; - } - - if ($codePoint >= 3676 && $codePoint <= 3712) { - return true; - } - - if ($codePoint >= 3808 && $codePoint <= 3839) { - return true; - } - - if ($codePoint >= 4059 && $codePoint <= 4095) { - return true; - } - - if ($codePoint >= 4256 && $codePoint <= 4293) { - return true; - } - - if ($codePoint >= 6849 && $codePoint <= 6911) { - return true; - } - - if ($codePoint >= 11859 && $codePoint <= 11903) { - return true; - } - - if ($codePoint >= 42955 && $codePoint <= 42996) { - return true; - } - - if ($codePoint >= 55296 && $codePoint <= 57343) { - return true; - } - - if ($codePoint >= 57344 && $codePoint <= 63743) { - return true; - } - - if ($codePoint >= 64218 && $codePoint <= 64255) { - return true; - } - - if ($codePoint >= 64976 && $codePoint <= 65007) { - return true; - } - - if ($codePoint >= 65630 && $codePoint <= 65663) { - return true; - } - - if ($codePoint >= 65953 && $codePoint <= 65999) { - return true; - } - - if ($codePoint >= 66046 && $codePoint <= 66175) { - return true; - } - - if ($codePoint >= 66518 && $codePoint <= 66559) { - return true; - } - - if ($codePoint >= 66928 && $codePoint <= 67071) { - return true; - } - - if ($codePoint >= 67432 && $codePoint <= 67583) { - return true; - } - - if ($codePoint >= 67760 && $codePoint <= 67807) { - return true; - } - - if ($codePoint >= 67904 && $codePoint <= 67967) { - return true; - } - - if ($codePoint >= 68256 && $codePoint <= 68287) { - return true; - } - - if ($codePoint >= 68528 && $codePoint <= 68607) { - return true; - } - - if ($codePoint >= 68681 && $codePoint <= 68735) { - return true; - } - - if ($codePoint >= 68922 && $codePoint <= 69215) { - return true; - } - - if ($codePoint >= 69298 && $codePoint <= 69375) { - return true; - } - - if ($codePoint >= 69466 && $codePoint <= 69551) { - return true; - } - - if ($codePoint >= 70207 && $codePoint <= 70271) { - return true; - } - - if ($codePoint >= 70517 && $codePoint <= 70655) { - return true; - } - - if ($codePoint >= 70874 && $codePoint <= 71039) { - return true; - } - - if ($codePoint >= 71134 && $codePoint <= 71167) { - return true; - } - - if ($codePoint >= 71370 && $codePoint <= 71423) { - return true; - } - - if ($codePoint >= 71488 && $codePoint <= 71679) { - return true; - } - - if ($codePoint >= 71740 && $codePoint <= 71839) { - return true; - } - - if ($codePoint >= 72026 && $codePoint <= 72095) { - return true; - } - - if ($codePoint >= 72441 && $codePoint <= 72703) { - return true; - } - - if ($codePoint >= 72887 && $codePoint <= 72959) { - return true; - } - - if ($codePoint >= 73130 && $codePoint <= 73439) { - return true; - } - - if ($codePoint >= 73465 && $codePoint <= 73647) { - return true; - } - - if ($codePoint >= 74650 && $codePoint <= 74751) { - return true; - } - - if ($codePoint >= 75076 && $codePoint <= 77823) { - return true; - } - - if ($codePoint >= 78905 && $codePoint <= 82943) { - return true; - } - - if ($codePoint >= 83527 && $codePoint <= 92159) { - return true; - } - - if ($codePoint >= 92784 && $codePoint <= 92879) { - return true; - } - - if ($codePoint >= 93072 && $codePoint <= 93759) { - return true; - } - - if ($codePoint >= 93851 && $codePoint <= 93951) { - return true; - } - - if ($codePoint >= 94112 && $codePoint <= 94175) { - return true; - } - - if ($codePoint >= 101590 && $codePoint <= 101631) { - return true; - } - - if ($codePoint >= 101641 && $codePoint <= 110591) { - return true; - } - - if ($codePoint >= 110879 && $codePoint <= 110927) { - return true; - } - - if ($codePoint >= 111356 && $codePoint <= 113663) { - return true; - } - - if ($codePoint >= 113828 && $codePoint <= 118783) { - return true; - } - - if ($codePoint >= 119366 && $codePoint <= 119519) { - return true; - } - - if ($codePoint >= 119673 && $codePoint <= 119807) { - return true; - } - - if ($codePoint >= 121520 && $codePoint <= 122879) { - return true; - } - - if ($codePoint >= 122923 && $codePoint <= 123135) { - return true; - } - - if ($codePoint >= 123216 && $codePoint <= 123583) { - return true; - } - - if ($codePoint >= 123648 && $codePoint <= 124927) { - return true; - } - - if ($codePoint >= 125143 && $codePoint <= 125183) { - return true; - } - - if ($codePoint >= 125280 && $codePoint <= 126064) { - return true; - } - - if ($codePoint >= 126133 && $codePoint <= 126208) { - return true; - } - - if ($codePoint >= 126270 && $codePoint <= 126463) { - return true; - } - - if ($codePoint >= 126652 && $codePoint <= 126703) { - return true; - } - - if ($codePoint >= 126706 && $codePoint <= 126975) { - return true; - } - - if ($codePoint >= 127406 && $codePoint <= 127461) { - return true; - } - - if ($codePoint >= 127590 && $codePoint <= 127743) { - return true; - } - - if ($codePoint >= 129202 && $codePoint <= 129279) { - return true; - } - - if ($codePoint >= 129751 && $codePoint <= 129791) { - return true; - } - - if ($codePoint >= 129995 && $codePoint <= 130031) { - return true; - } - - if ($codePoint >= 130042 && $codePoint <= 131069) { - return true; - } - - if ($codePoint >= 173790 && $codePoint <= 173823) { - return true; - } - - if ($codePoint >= 191457 && $codePoint <= 194559) { - return true; - } - - if ($codePoint >= 195102 && $codePoint <= 196605) { - return true; - } - - if ($codePoint >= 201547 && $codePoint <= 262141) { - return true; - } - - if ($codePoint >= 262144 && $codePoint <= 327677) { - return true; - } - - if ($codePoint >= 327680 && $codePoint <= 393213) { - return true; - } - - if ($codePoint >= 393216 && $codePoint <= 458749) { - return true; - } - - if ($codePoint >= 458752 && $codePoint <= 524285) { - return true; - } - - if ($codePoint >= 524288 && $codePoint <= 589821) { - return true; - } - - if ($codePoint >= 589824 && $codePoint <= 655357) { - return true; - } - - if ($codePoint >= 655360 && $codePoint <= 720893) { - return true; - } - - if ($codePoint >= 720896 && $codePoint <= 786429) { - return true; - } - - if ($codePoint >= 786432 && $codePoint <= 851965) { - return true; - } - - if ($codePoint >= 851968 && $codePoint <= 917501) { - return true; - } - - if ($codePoint >= 917536 && $codePoint <= 917631) { - return true; - } - - if ($codePoint >= 917632 && $codePoint <= 917759) { - return true; - } - - if ($codePoint >= 918000 && $codePoint <= 983037) { - return true; - } - - if ($codePoint >= 983040 && $codePoint <= 1048573) { - return true; - } - - if ($codePoint >= 1048576 && $codePoint <= 1114109) { - return true; - } - - return false; - } -} diff --git a/lib/symfony/polyfill-intl-idn/Resources/unidata/Regex.php b/lib/symfony/polyfill-intl-idn/Resources/unidata/Regex.php deleted file mode 100644 index 5c1c51dde..000000000 --- a/lib/symfony/polyfill-intl-idn/Resources/unidata/Regex.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -namespace Symfony\Polyfill\Intl\Idn\Resources\unidata; - -/** - * @internal - */ -final class Regex -{ - const COMBINING_MARK = '/^[\x{0300}-\x{036F}\x{0483}-\x{0487}\x{0488}-\x{0489}\x{0591}-\x{05BD}\x{05BF}\x{05C1}-\x{05C2}\x{05C4}-\x{05C5}\x{05C7}\x{0610}-\x{061A}\x{064B}-\x{065F}\x{0670}\x{06D6}-\x{06DC}\x{06DF}-\x{06E4}\x{06E7}-\x{06E8}\x{06EA}-\x{06ED}\x{0711}\x{0730}-\x{074A}\x{07A6}-\x{07B0}\x{07EB}-\x{07F3}\x{07FD}\x{0816}-\x{0819}\x{081B}-\x{0823}\x{0825}-\x{0827}\x{0829}-\x{082D}\x{0859}-\x{085B}\x{08D3}-\x{08E1}\x{08E3}-\x{0902}\x{0903}\x{093A}\x{093B}\x{093C}\x{093E}-\x{0940}\x{0941}-\x{0948}\x{0949}-\x{094C}\x{094D}\x{094E}-\x{094F}\x{0951}-\x{0957}\x{0962}-\x{0963}\x{0981}\x{0982}-\x{0983}\x{09BC}\x{09BE}-\x{09C0}\x{09C1}-\x{09C4}\x{09C7}-\x{09C8}\x{09CB}-\x{09CC}\x{09CD}\x{09D7}\x{09E2}-\x{09E3}\x{09FE}\x{0A01}-\x{0A02}\x{0A03}\x{0A3C}\x{0A3E}-\x{0A40}\x{0A41}-\x{0A42}\x{0A47}-\x{0A48}\x{0A4B}-\x{0A4D}\x{0A51}\x{0A70}-\x{0A71}\x{0A75}\x{0A81}-\x{0A82}\x{0A83}\x{0ABC}\x{0ABE}-\x{0AC0}\x{0AC1}-\x{0AC5}\x{0AC7}-\x{0AC8}\x{0AC9}\x{0ACB}-\x{0ACC}\x{0ACD}\x{0AE2}-\x{0AE3}\x{0AFA}-\x{0AFF}\x{0B01}\x{0B02}-\x{0B03}\x{0B3C}\x{0B3E}\x{0B3F}\x{0B40}\x{0B41}-\x{0B44}\x{0B47}-\x{0B48}\x{0B4B}-\x{0B4C}\x{0B4D}\x{0B55}-\x{0B56}\x{0B57}\x{0B62}-\x{0B63}\x{0B82}\x{0BBE}-\x{0BBF}\x{0BC0}\x{0BC1}-\x{0BC2}\x{0BC6}-\x{0BC8}\x{0BCA}-\x{0BCC}\x{0BCD}\x{0BD7}\x{0C00}\x{0C01}-\x{0C03}\x{0C04}\x{0C3E}-\x{0C40}\x{0C41}-\x{0C44}\x{0C46}-\x{0C48}\x{0C4A}-\x{0C4D}\x{0C55}-\x{0C56}\x{0C62}-\x{0C63}\x{0C81}\x{0C82}-\x{0C83}\x{0CBC}\x{0CBE}\x{0CBF}\x{0CC0}-\x{0CC4}\x{0CC6}\x{0CC7}-\x{0CC8}\x{0CCA}-\x{0CCB}\x{0CCC}-\x{0CCD}\x{0CD5}-\x{0CD6}\x{0CE2}-\x{0CE3}\x{0D00}-\x{0D01}\x{0D02}-\x{0D03}\x{0D3B}-\x{0D3C}\x{0D3E}-\x{0D40}\x{0D41}-\x{0D44}\x{0D46}-\x{0D48}\x{0D4A}-\x{0D4C}\x{0D4D}\x{0D57}\x{0D62}-\x{0D63}\x{0D81}\x{0D82}-\x{0D83}\x{0DCA}\x{0DCF}-\x{0DD1}\x{0DD2}-\x{0DD4}\x{0DD6}\x{0DD8}-\x{0DDF}\x{0DF2}-\x{0DF3}\x{0E31}\x{0E34}-\x{0E3A}\x{0E47}-\x{0E4E}\x{0EB1}\x{0EB4}-\x{0EBC}\x{0EC8}-\x{0ECD}\x{0F18}-\x{0F19}\x{0F35}\x{0F37}\x{0F39}\x{0F3E}-\x{0F3F}\x{0F71}-\x{0F7E}\x{0F7F}\x{0F80}-\x{0F84}\x{0F86}-\x{0F87}\x{0F8D}-\x{0F97}\x{0F99}-\x{0FBC}\x{0FC6}\x{102B}-\x{102C}\x{102D}-\x{1030}\x{1031}\x{1032}-\x{1037}\x{1038}\x{1039}-\x{103A}\x{103B}-\x{103C}\x{103D}-\x{103E}\x{1056}-\x{1057}\x{1058}-\x{1059}\x{105E}-\x{1060}\x{1062}-\x{1064}\x{1067}-\x{106D}\x{1071}-\x{1074}\x{1082}\x{1083}-\x{1084}\x{1085}-\x{1086}\x{1087}-\x{108C}\x{108D}\x{108F}\x{109A}-\x{109C}\x{109D}\x{135D}-\x{135F}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}-\x{1753}\x{1772}-\x{1773}\x{17B4}-\x{17B5}\x{17B6}\x{17B7}-\x{17BD}\x{17BE}-\x{17C5}\x{17C6}\x{17C7}-\x{17C8}\x{17C9}-\x{17D3}\x{17DD}\x{180B}-\x{180D}\x{1885}-\x{1886}\x{18A9}\x{1920}-\x{1922}\x{1923}-\x{1926}\x{1927}-\x{1928}\x{1929}-\x{192B}\x{1930}-\x{1931}\x{1932}\x{1933}-\x{1938}\x{1939}-\x{193B}\x{1A17}-\x{1A18}\x{1A19}-\x{1A1A}\x{1A1B}\x{1A55}\x{1A56}\x{1A57}\x{1A58}-\x{1A5E}\x{1A60}\x{1A61}\x{1A62}\x{1A63}-\x{1A64}\x{1A65}-\x{1A6C}\x{1A6D}-\x{1A72}\x{1A73}-\x{1A7C}\x{1A7F}\x{1AB0}-\x{1ABD}\x{1ABE}\x{1ABF}-\x{1AC0}\x{1B00}-\x{1B03}\x{1B04}\x{1B34}\x{1B35}\x{1B36}-\x{1B3A}\x{1B3B}\x{1B3C}\x{1B3D}-\x{1B41}\x{1B42}\x{1B43}-\x{1B44}\x{1B6B}-\x{1B73}\x{1B80}-\x{1B81}\x{1B82}\x{1BA1}\x{1BA2}-\x{1BA5}\x{1BA6}-\x{1BA7}\x{1BA8}-\x{1BA9}\x{1BAA}\x{1BAB}-\x{1BAD}\x{1BE6}\x{1BE7}\x{1BE8}-\x{1BE9}\x{1BEA}-\x{1BEC}\x{1BED}\x{1BEE}\x{1BEF}-\x{1BF1}\x{1BF2}-\x{1BF3}\x{1C24}-\x{1C2B}\x{1C2C}-\x{1C33}\x{1C34}-\x{1C35}\x{1C36}-\x{1C37}\x{1CD0}-\x{1CD2}\x{1CD4}-\x{1CE0}\x{1CE1}\x{1CE2}-\x{1CE8}\x{1CED}\x{1CF4}\x{1CF7}\x{1CF8}-\x{1CF9}\x{1DC0}-\x{1DF9}\x{1DFB}-\x{1DFF}\x{20D0}-\x{20DC}\x{20DD}-\x{20E0}\x{20E1}\x{20E2}-\x{20E4}\x{20E5}-\x{20F0}\x{2CEF}-\x{2CF1}\x{2D7F}\x{2DE0}-\x{2DFF}\x{302A}-\x{302D}\x{302E}-\x{302F}\x{3099}-\x{309A}\x{A66F}\x{A670}-\x{A672}\x{A674}-\x{A67D}\x{A69E}-\x{A69F}\x{A6F0}-\x{A6F1}\x{A802}\x{A806}\x{A80B}\x{A823}-\x{A824}\x{A825}-\x{A826}\x{A827}\x{A82C}\x{A880}-\x{A881}\x{A8B4}-\x{A8C3}\x{A8C4}-\x{A8C5}\x{A8E0}-\x{A8F1}\x{A8FF}\x{A926}-\x{A92D}\x{A947}-\x{A951}\x{A952}-\x{A953}\x{A980}-\x{A982}\x{A983}\x{A9B3}\x{A9B4}-\x{A9B5}\x{A9B6}-\x{A9B9}\x{A9BA}-\x{A9BB}\x{A9BC}-\x{A9BD}\x{A9BE}-\x{A9C0}\x{A9E5}\x{AA29}-\x{AA2E}\x{AA2F}-\x{AA30}\x{AA31}-\x{AA32}\x{AA33}-\x{AA34}\x{AA35}-\x{AA36}\x{AA43}\x{AA4C}\x{AA4D}\x{AA7B}\x{AA7C}\x{AA7D}\x{AAB0}\x{AAB2}-\x{AAB4}\x{AAB7}-\x{AAB8}\x{AABE}-\x{AABF}\x{AAC1}\x{AAEB}\x{AAEC}-\x{AAED}\x{AAEE}-\x{AAEF}\x{AAF5}\x{AAF6}\x{ABE3}-\x{ABE4}\x{ABE5}\x{ABE6}-\x{ABE7}\x{ABE8}\x{ABE9}-\x{ABEA}\x{ABEC}\x{ABED}\x{FB1E}\x{FE00}-\x{FE0F}\x{FE20}-\x{FE2F}\x{101FD}\x{102E0}\x{10376}-\x{1037A}\x{10A01}-\x{10A03}\x{10A05}-\x{10A06}\x{10A0C}-\x{10A0F}\x{10A38}-\x{10A3A}\x{10A3F}\x{10AE5}-\x{10AE6}\x{10D24}-\x{10D27}\x{10EAB}-\x{10EAC}\x{10F46}-\x{10F50}\x{11000}\x{11001}\x{11002}\x{11038}-\x{11046}\x{1107F}-\x{11081}\x{11082}\x{110B0}-\x{110B2}\x{110B3}-\x{110B6}\x{110B7}-\x{110B8}\x{110B9}-\x{110BA}\x{11100}-\x{11102}\x{11127}-\x{1112B}\x{1112C}\x{1112D}-\x{11134}\x{11145}-\x{11146}\x{11173}\x{11180}-\x{11181}\x{11182}\x{111B3}-\x{111B5}\x{111B6}-\x{111BE}\x{111BF}-\x{111C0}\x{111C9}-\x{111CC}\x{111CE}\x{111CF}\x{1122C}-\x{1122E}\x{1122F}-\x{11231}\x{11232}-\x{11233}\x{11234}\x{11235}\x{11236}-\x{11237}\x{1123E}\x{112DF}\x{112E0}-\x{112E2}\x{112E3}-\x{112EA}\x{11300}-\x{11301}\x{11302}-\x{11303}\x{1133B}-\x{1133C}\x{1133E}-\x{1133F}\x{11340}\x{11341}-\x{11344}\x{11347}-\x{11348}\x{1134B}-\x{1134D}\x{11357}\x{11362}-\x{11363}\x{11366}-\x{1136C}\x{11370}-\x{11374}\x{11435}-\x{11437}\x{11438}-\x{1143F}\x{11440}-\x{11441}\x{11442}-\x{11444}\x{11445}\x{11446}\x{1145E}\x{114B0}-\x{114B2}\x{114B3}-\x{114B8}\x{114B9}\x{114BA}\x{114BB}-\x{114BE}\x{114BF}-\x{114C0}\x{114C1}\x{114C2}-\x{114C3}\x{115AF}-\x{115B1}\x{115B2}-\x{115B5}\x{115B8}-\x{115BB}\x{115BC}-\x{115BD}\x{115BE}\x{115BF}-\x{115C0}\x{115DC}-\x{115DD}\x{11630}-\x{11632}\x{11633}-\x{1163A}\x{1163B}-\x{1163C}\x{1163D}\x{1163E}\x{1163F}-\x{11640}\x{116AB}\x{116AC}\x{116AD}\x{116AE}-\x{116AF}\x{116B0}-\x{116B5}\x{116B6}\x{116B7}\x{1171D}-\x{1171F}\x{11720}-\x{11721}\x{11722}-\x{11725}\x{11726}\x{11727}-\x{1172B}\x{1182C}-\x{1182E}\x{1182F}-\x{11837}\x{11838}\x{11839}-\x{1183A}\x{11930}-\x{11935}\x{11937}-\x{11938}\x{1193B}-\x{1193C}\x{1193D}\x{1193E}\x{11940}\x{11942}\x{11943}\x{119D1}-\x{119D3}\x{119D4}-\x{119D7}\x{119DA}-\x{119DB}\x{119DC}-\x{119DF}\x{119E0}\x{119E4}\x{11A01}-\x{11A0A}\x{11A33}-\x{11A38}\x{11A39}\x{11A3B}-\x{11A3E}\x{11A47}\x{11A51}-\x{11A56}\x{11A57}-\x{11A58}\x{11A59}-\x{11A5B}\x{11A8A}-\x{11A96}\x{11A97}\x{11A98}-\x{11A99}\x{11C2F}\x{11C30}-\x{11C36}\x{11C38}-\x{11C3D}\x{11C3E}\x{11C3F}\x{11C92}-\x{11CA7}\x{11CA9}\x{11CAA}-\x{11CB0}\x{11CB1}\x{11CB2}-\x{11CB3}\x{11CB4}\x{11CB5}-\x{11CB6}\x{11D31}-\x{11D36}\x{11D3A}\x{11D3C}-\x{11D3D}\x{11D3F}-\x{11D45}\x{11D47}\x{11D8A}-\x{11D8E}\x{11D90}-\x{11D91}\x{11D93}-\x{11D94}\x{11D95}\x{11D96}\x{11D97}\x{11EF3}-\x{11EF4}\x{11EF5}-\x{11EF6}\x{16AF0}-\x{16AF4}\x{16B30}-\x{16B36}\x{16F4F}\x{16F51}-\x{16F87}\x{16F8F}-\x{16F92}\x{16FE4}\x{16FF0}-\x{16FF1}\x{1BC9D}-\x{1BC9E}\x{1D165}-\x{1D166}\x{1D167}-\x{1D169}\x{1D16D}-\x{1D172}\x{1D17B}-\x{1D182}\x{1D185}-\x{1D18B}\x{1D1AA}-\x{1D1AD}\x{1D242}-\x{1D244}\x{1DA00}-\x{1DA36}\x{1DA3B}-\x{1DA6C}\x{1DA75}\x{1DA84}\x{1DA9B}-\x{1DA9F}\x{1DAA1}-\x{1DAAF}\x{1E000}-\x{1E006}\x{1E008}-\x{1E018}\x{1E01B}-\x{1E021}\x{1E023}-\x{1E024}\x{1E026}-\x{1E02A}\x{1E130}-\x{1E136}\x{1E2EC}-\x{1E2EF}\x{1E8D0}-\x{1E8D6}\x{1E944}-\x{1E94A}\x{E0100}-\x{E01EF}]/u'; - - const RTL_LABEL = '/[\x{0590}\x{05BE}\x{05C0}\x{05C3}\x{05C6}\x{05C8}-\x{05CF}\x{05D0}-\x{05EA}\x{05EB}-\x{05EE}\x{05EF}-\x{05F2}\x{05F3}-\x{05F4}\x{05F5}-\x{05FF}\x{0600}-\x{0605}\x{0608}\x{060B}\x{060D}\x{061B}\x{061C}\x{061D}\x{061E}-\x{061F}\x{0620}-\x{063F}\x{0640}\x{0641}-\x{064A}\x{0660}-\x{0669}\x{066B}-\x{066C}\x{066D}\x{066E}-\x{066F}\x{0671}-\x{06D3}\x{06D4}\x{06D5}\x{06DD}\x{06E5}-\x{06E6}\x{06EE}-\x{06EF}\x{06FA}-\x{06FC}\x{06FD}-\x{06FE}\x{06FF}\x{0700}-\x{070D}\x{070E}\x{070F}\x{0710}\x{0712}-\x{072F}\x{074B}-\x{074C}\x{074D}-\x{07A5}\x{07B1}\x{07B2}-\x{07BF}\x{07C0}-\x{07C9}\x{07CA}-\x{07EA}\x{07F4}-\x{07F5}\x{07FA}\x{07FB}-\x{07FC}\x{07FE}-\x{07FF}\x{0800}-\x{0815}\x{081A}\x{0824}\x{0828}\x{082E}-\x{082F}\x{0830}-\x{083E}\x{083F}\x{0840}-\x{0858}\x{085C}-\x{085D}\x{085E}\x{085F}\x{0860}-\x{086A}\x{086B}-\x{086F}\x{0870}-\x{089F}\x{08A0}-\x{08B4}\x{08B5}\x{08B6}-\x{08C7}\x{08C8}-\x{08D2}\x{08E2}\x{200F}\x{FB1D}\x{FB1F}-\x{FB28}\x{FB2A}-\x{FB36}\x{FB37}\x{FB38}-\x{FB3C}\x{FB3D}\x{FB3E}\x{FB3F}\x{FB40}-\x{FB41}\x{FB42}\x{FB43}-\x{FB44}\x{FB45}\x{FB46}-\x{FB4F}\x{FB50}-\x{FBB1}\x{FBB2}-\x{FBC1}\x{FBC2}-\x{FBD2}\x{FBD3}-\x{FD3D}\x{FD40}-\x{FD4F}\x{FD50}-\x{FD8F}\x{FD90}-\x{FD91}\x{FD92}-\x{FDC7}\x{FDC8}-\x{FDCF}\x{FDF0}-\x{FDFB}\x{FDFC}\x{FDFE}-\x{FDFF}\x{FE70}-\x{FE74}\x{FE75}\x{FE76}-\x{FEFC}\x{FEFD}-\x{FEFE}\x{10800}-\x{10805}\x{10806}-\x{10807}\x{10808}\x{10809}\x{1080A}-\x{10835}\x{10836}\x{10837}-\x{10838}\x{10839}-\x{1083B}\x{1083C}\x{1083D}-\x{1083E}\x{1083F}-\x{10855}\x{10856}\x{10857}\x{10858}-\x{1085F}\x{10860}-\x{10876}\x{10877}-\x{10878}\x{10879}-\x{1087F}\x{10880}-\x{1089E}\x{1089F}-\x{108A6}\x{108A7}-\x{108AF}\x{108B0}-\x{108DF}\x{108E0}-\x{108F2}\x{108F3}\x{108F4}-\x{108F5}\x{108F6}-\x{108FA}\x{108FB}-\x{108FF}\x{10900}-\x{10915}\x{10916}-\x{1091B}\x{1091C}-\x{1091E}\x{10920}-\x{10939}\x{1093A}-\x{1093E}\x{1093F}\x{10940}-\x{1097F}\x{10980}-\x{109B7}\x{109B8}-\x{109BB}\x{109BC}-\x{109BD}\x{109BE}-\x{109BF}\x{109C0}-\x{109CF}\x{109D0}-\x{109D1}\x{109D2}-\x{109FF}\x{10A00}\x{10A04}\x{10A07}-\x{10A0B}\x{10A10}-\x{10A13}\x{10A14}\x{10A15}-\x{10A17}\x{10A18}\x{10A19}-\x{10A35}\x{10A36}-\x{10A37}\x{10A3B}-\x{10A3E}\x{10A40}-\x{10A48}\x{10A49}-\x{10A4F}\x{10A50}-\x{10A58}\x{10A59}-\x{10A5F}\x{10A60}-\x{10A7C}\x{10A7D}-\x{10A7E}\x{10A7F}\x{10A80}-\x{10A9C}\x{10A9D}-\x{10A9F}\x{10AA0}-\x{10ABF}\x{10AC0}-\x{10AC7}\x{10AC8}\x{10AC9}-\x{10AE4}\x{10AE7}-\x{10AEA}\x{10AEB}-\x{10AEF}\x{10AF0}-\x{10AF6}\x{10AF7}-\x{10AFF}\x{10B00}-\x{10B35}\x{10B36}-\x{10B38}\x{10B40}-\x{10B55}\x{10B56}-\x{10B57}\x{10B58}-\x{10B5F}\x{10B60}-\x{10B72}\x{10B73}-\x{10B77}\x{10B78}-\x{10B7F}\x{10B80}-\x{10B91}\x{10B92}-\x{10B98}\x{10B99}-\x{10B9C}\x{10B9D}-\x{10BA8}\x{10BA9}-\x{10BAF}\x{10BB0}-\x{10BFF}\x{10C00}-\x{10C48}\x{10C49}-\x{10C7F}\x{10C80}-\x{10CB2}\x{10CB3}-\x{10CBF}\x{10CC0}-\x{10CF2}\x{10CF3}-\x{10CF9}\x{10CFA}-\x{10CFF}\x{10D00}-\x{10D23}\x{10D28}-\x{10D2F}\x{10D30}-\x{10D39}\x{10D3A}-\x{10D3F}\x{10D40}-\x{10E5F}\x{10E60}-\x{10E7E}\x{10E7F}\x{10E80}-\x{10EA9}\x{10EAA}\x{10EAD}\x{10EAE}-\x{10EAF}\x{10EB0}-\x{10EB1}\x{10EB2}-\x{10EFF}\x{10F00}-\x{10F1C}\x{10F1D}-\x{10F26}\x{10F27}\x{10F28}-\x{10F2F}\x{10F30}-\x{10F45}\x{10F51}-\x{10F54}\x{10F55}-\x{10F59}\x{10F5A}-\x{10F6F}\x{10F70}-\x{10FAF}\x{10FB0}-\x{10FC4}\x{10FC5}-\x{10FCB}\x{10FCC}-\x{10FDF}\x{10FE0}-\x{10FF6}\x{10FF7}-\x{10FFF}\x{1E800}-\x{1E8C4}\x{1E8C5}-\x{1E8C6}\x{1E8C7}-\x{1E8CF}\x{1E8D7}-\x{1E8FF}\x{1E900}-\x{1E943}\x{1E94B}\x{1E94C}-\x{1E94F}\x{1E950}-\x{1E959}\x{1E95A}-\x{1E95D}\x{1E95E}-\x{1E95F}\x{1E960}-\x{1EC6F}\x{1EC70}\x{1EC71}-\x{1ECAB}\x{1ECAC}\x{1ECAD}-\x{1ECAF}\x{1ECB0}\x{1ECB1}-\x{1ECB4}\x{1ECB5}-\x{1ECBF}\x{1ECC0}-\x{1ECFF}\x{1ED00}\x{1ED01}-\x{1ED2D}\x{1ED2E}\x{1ED2F}-\x{1ED3D}\x{1ED3E}-\x{1ED4F}\x{1ED50}-\x{1EDFF}\x{1EE00}-\x{1EE03}\x{1EE04}\x{1EE05}-\x{1EE1F}\x{1EE20}\x{1EE21}-\x{1EE22}\x{1EE23}\x{1EE24}\x{1EE25}-\x{1EE26}\x{1EE27}\x{1EE28}\x{1EE29}-\x{1EE32}\x{1EE33}\x{1EE34}-\x{1EE37}\x{1EE38}\x{1EE39}\x{1EE3A}\x{1EE3B}\x{1EE3C}-\x{1EE41}\x{1EE42}\x{1EE43}-\x{1EE46}\x{1EE47}\x{1EE48}\x{1EE49}\x{1EE4A}\x{1EE4B}\x{1EE4C}\x{1EE4D}-\x{1EE4F}\x{1EE50}\x{1EE51}-\x{1EE52}\x{1EE53}\x{1EE54}\x{1EE55}-\x{1EE56}\x{1EE57}\x{1EE58}\x{1EE59}\x{1EE5A}\x{1EE5B}\x{1EE5C}\x{1EE5D}\x{1EE5E}\x{1EE5F}\x{1EE60}\x{1EE61}-\x{1EE62}\x{1EE63}\x{1EE64}\x{1EE65}-\x{1EE66}\x{1EE67}-\x{1EE6A}\x{1EE6B}\x{1EE6C}-\x{1EE72}\x{1EE73}\x{1EE74}-\x{1EE77}\x{1EE78}\x{1EE79}-\x{1EE7C}\x{1EE7D}\x{1EE7E}\x{1EE7F}\x{1EE80}-\x{1EE89}\x{1EE8A}\x{1EE8B}-\x{1EE9B}\x{1EE9C}-\x{1EEA0}\x{1EEA1}-\x{1EEA3}\x{1EEA4}\x{1EEA5}-\x{1EEA9}\x{1EEAA}\x{1EEAB}-\x{1EEBB}\x{1EEBC}-\x{1EEEF}\x{1EEF2}-\x{1EEFF}\x{1EF00}-\x{1EFFF}]/u'; - - const BIDI_STEP_1_LTR = '/^[^\x{0000}-\x{0008}\x{0009}\x{000A}\x{000B}\x{000C}\x{000D}\x{000E}-\x{001B}\x{001C}-\x{001E}\x{001F}\x{0020}\x{0021}-\x{0022}\x{0023}\x{0024}\x{0025}\x{0026}-\x{0027}\x{0028}\x{0029}\x{002A}\x{002B}\x{002C}\x{002D}\x{002E}-\x{002F}\x{0030}-\x{0039}\x{003A}\x{003B}\x{003C}-\x{003E}\x{003F}-\x{0040}\x{005B}\x{005C}\x{005D}\x{005E}\x{005F}\x{0060}\x{007B}\x{007C}\x{007D}\x{007E}\x{007F}-\x{0084}\x{0085}\x{0086}-\x{009F}\x{00A0}\x{00A1}\x{00A2}-\x{00A5}\x{00A6}\x{00A7}\x{00A8}\x{00A9}\x{00AB}\x{00AC}\x{00AD}\x{00AE}\x{00AF}\x{00B0}\x{00B1}\x{00B2}-\x{00B3}\x{00B4}\x{00B6}-\x{00B7}\x{00B8}\x{00B9}\x{00BB}\x{00BC}-\x{00BE}\x{00BF}\x{00D7}\x{00F7}\x{02B9}-\x{02BA}\x{02C2}-\x{02C5}\x{02C6}-\x{02CF}\x{02D2}-\x{02DF}\x{02E5}-\x{02EB}\x{02EC}\x{02ED}\x{02EF}-\x{02FF}\x{0300}-\x{036F}\x{0374}\x{0375}\x{037E}\x{0384}-\x{0385}\x{0387}\x{03F6}\x{0483}-\x{0487}\x{0488}-\x{0489}\x{058A}\x{058D}-\x{058E}\x{058F}\x{0590}\x{0591}-\x{05BD}\x{05BE}\x{05BF}\x{05C0}\x{05C1}-\x{05C2}\x{05C3}\x{05C4}-\x{05C5}\x{05C6}\x{05C7}\x{05C8}-\x{05CF}\x{05D0}-\x{05EA}\x{05EB}-\x{05EE}\x{05EF}-\x{05F2}\x{05F3}-\x{05F4}\x{05F5}-\x{05FF}\x{0600}-\x{0605}\x{0606}-\x{0607}\x{0608}\x{0609}-\x{060A}\x{060B}\x{060C}\x{060D}\x{060E}-\x{060F}\x{0610}-\x{061A}\x{061B}\x{061C}\x{061D}\x{061E}-\x{061F}\x{0620}-\x{063F}\x{0640}\x{0641}-\x{064A}\x{064B}-\x{065F}\x{0660}-\x{0669}\x{066A}\x{066B}-\x{066C}\x{066D}\x{066E}-\x{066F}\x{0670}\x{0671}-\x{06D3}\x{06D4}\x{06D5}\x{06D6}-\x{06DC}\x{06DD}\x{06DE}\x{06DF}-\x{06E4}\x{06E5}-\x{06E6}\x{06E7}-\x{06E8}\x{06E9}\x{06EA}-\x{06ED}\x{06EE}-\x{06EF}\x{06F0}-\x{06F9}\x{06FA}-\x{06FC}\x{06FD}-\x{06FE}\x{06FF}\x{0700}-\x{070D}\x{070E}\x{070F}\x{0710}\x{0711}\x{0712}-\x{072F}\x{0730}-\x{074A}\x{074B}-\x{074C}\x{074D}-\x{07A5}\x{07A6}-\x{07B0}\x{07B1}\x{07B2}-\x{07BF}\x{07C0}-\x{07C9}\x{07CA}-\x{07EA}\x{07EB}-\x{07F3}\x{07F4}-\x{07F5}\x{07F6}\x{07F7}-\x{07F9}\x{07FA}\x{07FB}-\x{07FC}\x{07FD}\x{07FE}-\x{07FF}\x{0800}-\x{0815}\x{0816}-\x{0819}\x{081A}\x{081B}-\x{0823}\x{0824}\x{0825}-\x{0827}\x{0828}\x{0829}-\x{082D}\x{082E}-\x{082F}\x{0830}-\x{083E}\x{083F}\x{0840}-\x{0858}\x{0859}-\x{085B}\x{085C}-\x{085D}\x{085E}\x{085F}\x{0860}-\x{086A}\x{086B}-\x{086F}\x{0870}-\x{089F}\x{08A0}-\x{08B4}\x{08B5}\x{08B6}-\x{08C7}\x{08C8}-\x{08D2}\x{08D3}-\x{08E1}\x{08E2}\x{08E3}-\x{0902}\x{093A}\x{093C}\x{0941}-\x{0948}\x{094D}\x{0951}-\x{0957}\x{0962}-\x{0963}\x{0981}\x{09BC}\x{09C1}-\x{09C4}\x{09CD}\x{09E2}-\x{09E3}\x{09F2}-\x{09F3}\x{09FB}\x{09FE}\x{0A01}-\x{0A02}\x{0A3C}\x{0A41}-\x{0A42}\x{0A47}-\x{0A48}\x{0A4B}-\x{0A4D}\x{0A51}\x{0A70}-\x{0A71}\x{0A75}\x{0A81}-\x{0A82}\x{0ABC}\x{0AC1}-\x{0AC5}\x{0AC7}-\x{0AC8}\x{0ACD}\x{0AE2}-\x{0AE3}\x{0AF1}\x{0AFA}-\x{0AFF}\x{0B01}\x{0B3C}\x{0B3F}\x{0B41}-\x{0B44}\x{0B4D}\x{0B55}-\x{0B56}\x{0B62}-\x{0B63}\x{0B82}\x{0BC0}\x{0BCD}\x{0BF3}-\x{0BF8}\x{0BF9}\x{0BFA}\x{0C00}\x{0C04}\x{0C3E}-\x{0C40}\x{0C46}-\x{0C48}\x{0C4A}-\x{0C4D}\x{0C55}-\x{0C56}\x{0C62}-\x{0C63}\x{0C78}-\x{0C7E}\x{0C81}\x{0CBC}\x{0CCC}-\x{0CCD}\x{0CE2}-\x{0CE3}\x{0D00}-\x{0D01}\x{0D3B}-\x{0D3C}\x{0D41}-\x{0D44}\x{0D4D}\x{0D62}-\x{0D63}\x{0D81}\x{0DCA}\x{0DD2}-\x{0DD4}\x{0DD6}\x{0E31}\x{0E34}-\x{0E3A}\x{0E3F}\x{0E47}-\x{0E4E}\x{0EB1}\x{0EB4}-\x{0EBC}\x{0EC8}-\x{0ECD}\x{0F18}-\x{0F19}\x{0F35}\x{0F37}\x{0F39}\x{0F3A}\x{0F3B}\x{0F3C}\x{0F3D}\x{0F71}-\x{0F7E}\x{0F80}-\x{0F84}\x{0F86}-\x{0F87}\x{0F8D}-\x{0F97}\x{0F99}-\x{0FBC}\x{0FC6}\x{102D}-\x{1030}\x{1032}-\x{1037}\x{1039}-\x{103A}\x{103D}-\x{103E}\x{1058}-\x{1059}\x{105E}-\x{1060}\x{1071}-\x{1074}\x{1082}\x{1085}-\x{1086}\x{108D}\x{109D}\x{135D}-\x{135F}\x{1390}-\x{1399}\x{1400}\x{1680}\x{169B}\x{169C}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}-\x{1753}\x{1772}-\x{1773}\x{17B4}-\x{17B5}\x{17B7}-\x{17BD}\x{17C6}\x{17C9}-\x{17D3}\x{17DB}\x{17DD}\x{17F0}-\x{17F9}\x{1800}-\x{1805}\x{1806}\x{1807}-\x{180A}\x{180B}-\x{180D}\x{180E}\x{1885}-\x{1886}\x{18A9}\x{1920}-\x{1922}\x{1927}-\x{1928}\x{1932}\x{1939}-\x{193B}\x{1940}\x{1944}-\x{1945}\x{19DE}-\x{19FF}\x{1A17}-\x{1A18}\x{1A1B}\x{1A56}\x{1A58}-\x{1A5E}\x{1A60}\x{1A62}\x{1A65}-\x{1A6C}\x{1A73}-\x{1A7C}\x{1A7F}\x{1AB0}-\x{1ABD}\x{1ABE}\x{1ABF}-\x{1AC0}\x{1B00}-\x{1B03}\x{1B34}\x{1B36}-\x{1B3A}\x{1B3C}\x{1B42}\x{1B6B}-\x{1B73}\x{1B80}-\x{1B81}\x{1BA2}-\x{1BA5}\x{1BA8}-\x{1BA9}\x{1BAB}-\x{1BAD}\x{1BE6}\x{1BE8}-\x{1BE9}\x{1BED}\x{1BEF}-\x{1BF1}\x{1C2C}-\x{1C33}\x{1C36}-\x{1C37}\x{1CD0}-\x{1CD2}\x{1CD4}-\x{1CE0}\x{1CE2}-\x{1CE8}\x{1CED}\x{1CF4}\x{1CF8}-\x{1CF9}\x{1DC0}-\x{1DF9}\x{1DFB}-\x{1DFF}\x{1FBD}\x{1FBF}-\x{1FC1}\x{1FCD}-\x{1FCF}\x{1FDD}-\x{1FDF}\x{1FED}-\x{1FEF}\x{1FFD}-\x{1FFE}\x{2000}-\x{200A}\x{200B}-\x{200D}\x{200F}\x{2010}-\x{2015}\x{2016}-\x{2017}\x{2018}\x{2019}\x{201A}\x{201B}-\x{201C}\x{201D}\x{201E}\x{201F}\x{2020}-\x{2027}\x{2028}\x{2029}\x{202A}\x{202B}\x{202C}\x{202D}\x{202E}\x{202F}\x{2030}-\x{2034}\x{2035}-\x{2038}\x{2039}\x{203A}\x{203B}-\x{203E}\x{203F}-\x{2040}\x{2041}-\x{2043}\x{2044}\x{2045}\x{2046}\x{2047}-\x{2051}\x{2052}\x{2053}\x{2054}\x{2055}-\x{205E}\x{205F}\x{2060}-\x{2064}\x{2065}\x{2066}\x{2067}\x{2068}\x{2069}\x{206A}-\x{206F}\x{2070}\x{2074}-\x{2079}\x{207A}-\x{207B}\x{207C}\x{207D}\x{207E}\x{2080}-\x{2089}\x{208A}-\x{208B}\x{208C}\x{208D}\x{208E}\x{20A0}-\x{20BF}\x{20C0}-\x{20CF}\x{20D0}-\x{20DC}\x{20DD}-\x{20E0}\x{20E1}\x{20E2}-\x{20E4}\x{20E5}-\x{20F0}\x{2100}-\x{2101}\x{2103}-\x{2106}\x{2108}-\x{2109}\x{2114}\x{2116}-\x{2117}\x{2118}\x{211E}-\x{2123}\x{2125}\x{2127}\x{2129}\x{212E}\x{213A}-\x{213B}\x{2140}-\x{2144}\x{214A}\x{214B}\x{214C}-\x{214D}\x{2150}-\x{215F}\x{2189}\x{218A}-\x{218B}\x{2190}-\x{2194}\x{2195}-\x{2199}\x{219A}-\x{219B}\x{219C}-\x{219F}\x{21A0}\x{21A1}-\x{21A2}\x{21A3}\x{21A4}-\x{21A5}\x{21A6}\x{21A7}-\x{21AD}\x{21AE}\x{21AF}-\x{21CD}\x{21CE}-\x{21CF}\x{21D0}-\x{21D1}\x{21D2}\x{21D3}\x{21D4}\x{21D5}-\x{21F3}\x{21F4}-\x{2211}\x{2212}\x{2213}\x{2214}-\x{22FF}\x{2300}-\x{2307}\x{2308}\x{2309}\x{230A}\x{230B}\x{230C}-\x{231F}\x{2320}-\x{2321}\x{2322}-\x{2328}\x{2329}\x{232A}\x{232B}-\x{2335}\x{237B}\x{237C}\x{237D}-\x{2394}\x{2396}-\x{239A}\x{239B}-\x{23B3}\x{23B4}-\x{23DB}\x{23DC}-\x{23E1}\x{23E2}-\x{2426}\x{2440}-\x{244A}\x{2460}-\x{2487}\x{2488}-\x{249B}\x{24EA}-\x{24FF}\x{2500}-\x{25B6}\x{25B7}\x{25B8}-\x{25C0}\x{25C1}\x{25C2}-\x{25F7}\x{25F8}-\x{25FF}\x{2600}-\x{266E}\x{266F}\x{2670}-\x{26AB}\x{26AD}-\x{2767}\x{2768}\x{2769}\x{276A}\x{276B}\x{276C}\x{276D}\x{276E}\x{276F}\x{2770}\x{2771}\x{2772}\x{2773}\x{2774}\x{2775}\x{2776}-\x{2793}\x{2794}-\x{27BF}\x{27C0}-\x{27C4}\x{27C5}\x{27C6}\x{27C7}-\x{27E5}\x{27E6}\x{27E7}\x{27E8}\x{27E9}\x{27EA}\x{27EB}\x{27EC}\x{27ED}\x{27EE}\x{27EF}\x{27F0}-\x{27FF}\x{2900}-\x{2982}\x{2983}\x{2984}\x{2985}\x{2986}\x{2987}\x{2988}\x{2989}\x{298A}\x{298B}\x{298C}\x{298D}\x{298E}\x{298F}\x{2990}\x{2991}\x{2992}\x{2993}\x{2994}\x{2995}\x{2996}\x{2997}\x{2998}\x{2999}-\x{29D7}\x{29D8}\x{29D9}\x{29DA}\x{29DB}\x{29DC}-\x{29FB}\x{29FC}\x{29FD}\x{29FE}-\x{2AFF}\x{2B00}-\x{2B2F}\x{2B30}-\x{2B44}\x{2B45}-\x{2B46}\x{2B47}-\x{2B4C}\x{2B4D}-\x{2B73}\x{2B76}-\x{2B95}\x{2B97}-\x{2BFF}\x{2CE5}-\x{2CEA}\x{2CEF}-\x{2CF1}\x{2CF9}-\x{2CFC}\x{2CFD}\x{2CFE}-\x{2CFF}\x{2D7F}\x{2DE0}-\x{2DFF}\x{2E00}-\x{2E01}\x{2E02}\x{2E03}\x{2E04}\x{2E05}\x{2E06}-\x{2E08}\x{2E09}\x{2E0A}\x{2E0B}\x{2E0C}\x{2E0D}\x{2E0E}-\x{2E16}\x{2E17}\x{2E18}-\x{2E19}\x{2E1A}\x{2E1B}\x{2E1C}\x{2E1D}\x{2E1E}-\x{2E1F}\x{2E20}\x{2E21}\x{2E22}\x{2E23}\x{2E24}\x{2E25}\x{2E26}\x{2E27}\x{2E28}\x{2E29}\x{2E2A}-\x{2E2E}\x{2E2F}\x{2E30}-\x{2E39}\x{2E3A}-\x{2E3B}\x{2E3C}-\x{2E3F}\x{2E40}\x{2E41}\x{2E42}\x{2E43}-\x{2E4F}\x{2E50}-\x{2E51}\x{2E52}\x{2E80}-\x{2E99}\x{2E9B}-\x{2EF3}\x{2F00}-\x{2FD5}\x{2FF0}-\x{2FFB}\x{3000}\x{3001}-\x{3003}\x{3004}\x{3008}\x{3009}\x{300A}\x{300B}\x{300C}\x{300D}\x{300E}\x{300F}\x{3010}\x{3011}\x{3012}-\x{3013}\x{3014}\x{3015}\x{3016}\x{3017}\x{3018}\x{3019}\x{301A}\x{301B}\x{301C}\x{301D}\x{301E}-\x{301F}\x{3020}\x{302A}-\x{302D}\x{3030}\x{3036}-\x{3037}\x{303D}\x{303E}-\x{303F}\x{3099}-\x{309A}\x{309B}-\x{309C}\x{30A0}\x{30FB}\x{31C0}-\x{31E3}\x{321D}-\x{321E}\x{3250}\x{3251}-\x{325F}\x{327C}-\x{327E}\x{32B1}-\x{32BF}\x{32CC}-\x{32CF}\x{3377}-\x{337A}\x{33DE}-\x{33DF}\x{33FF}\x{4DC0}-\x{4DFF}\x{A490}-\x{A4C6}\x{A60D}-\x{A60F}\x{A66F}\x{A670}-\x{A672}\x{A673}\x{A674}-\x{A67D}\x{A67E}\x{A67F}\x{A69E}-\x{A69F}\x{A6F0}-\x{A6F1}\x{A700}-\x{A716}\x{A717}-\x{A71F}\x{A720}-\x{A721}\x{A788}\x{A802}\x{A806}\x{A80B}\x{A825}-\x{A826}\x{A828}-\x{A82B}\x{A82C}\x{A838}\x{A839}\x{A874}-\x{A877}\x{A8C4}-\x{A8C5}\x{A8E0}-\x{A8F1}\x{A8FF}\x{A926}-\x{A92D}\x{A947}-\x{A951}\x{A980}-\x{A982}\x{A9B3}\x{A9B6}-\x{A9B9}\x{A9BC}-\x{A9BD}\x{A9E5}\x{AA29}-\x{AA2E}\x{AA31}-\x{AA32}\x{AA35}-\x{AA36}\x{AA43}\x{AA4C}\x{AA7C}\x{AAB0}\x{AAB2}-\x{AAB4}\x{AAB7}-\x{AAB8}\x{AABE}-\x{AABF}\x{AAC1}\x{AAEC}-\x{AAED}\x{AAF6}\x{AB6A}-\x{AB6B}\x{ABE5}\x{ABE8}\x{ABED}\x{FB1D}\x{FB1E}\x{FB1F}-\x{FB28}\x{FB29}\x{FB2A}-\x{FB36}\x{FB37}\x{FB38}-\x{FB3C}\x{FB3D}\x{FB3E}\x{FB3F}\x{FB40}-\x{FB41}\x{FB42}\x{FB43}-\x{FB44}\x{FB45}\x{FB46}-\x{FB4F}\x{FB50}-\x{FBB1}\x{FBB2}-\x{FBC1}\x{FBC2}-\x{FBD2}\x{FBD3}-\x{FD3D}\x{FD3E}\x{FD3F}\x{FD40}-\x{FD4F}\x{FD50}-\x{FD8F}\x{FD90}-\x{FD91}\x{FD92}-\x{FDC7}\x{FDC8}-\x{FDCF}\x{FDD0}-\x{FDEF}\x{FDF0}-\x{FDFB}\x{FDFC}\x{FDFD}\x{FDFE}-\x{FDFF}\x{FE00}-\x{FE0F}\x{FE10}-\x{FE16}\x{FE17}\x{FE18}\x{FE19}\x{FE20}-\x{FE2F}\x{FE30}\x{FE31}-\x{FE32}\x{FE33}-\x{FE34}\x{FE35}\x{FE36}\x{FE37}\x{FE38}\x{FE39}\x{FE3A}\x{FE3B}\x{FE3C}\x{FE3D}\x{FE3E}\x{FE3F}\x{FE40}\x{FE41}\x{FE42}\x{FE43}\x{FE44}\x{FE45}-\x{FE46}\x{FE47}\x{FE48}\x{FE49}-\x{FE4C}\x{FE4D}-\x{FE4F}\x{FE50}\x{FE51}\x{FE52}\x{FE54}\x{FE55}\x{FE56}-\x{FE57}\x{FE58}\x{FE59}\x{FE5A}\x{FE5B}\x{FE5C}\x{FE5D}\x{FE5E}\x{FE5F}\x{FE60}-\x{FE61}\x{FE62}\x{FE63}\x{FE64}-\x{FE66}\x{FE68}\x{FE69}\x{FE6A}\x{FE6B}\x{FE70}-\x{FE74}\x{FE75}\x{FE76}-\x{FEFC}\x{FEFD}-\x{FEFE}\x{FEFF}\x{FF01}-\x{FF02}\x{FF03}\x{FF04}\x{FF05}\x{FF06}-\x{FF07}\x{FF08}\x{FF09}\x{FF0A}\x{FF0B}\x{FF0C}\x{FF0D}\x{FF0E}-\x{FF0F}\x{FF10}-\x{FF19}\x{FF1A}\x{FF1B}\x{FF1C}-\x{FF1E}\x{FF1F}-\x{FF20}\x{FF3B}\x{FF3C}\x{FF3D}\x{FF3E}\x{FF3F}\x{FF40}\x{FF5B}\x{FF5C}\x{FF5D}\x{FF5E}\x{FF5F}\x{FF60}\x{FF61}\x{FF62}\x{FF63}\x{FF64}-\x{FF65}\x{FFE0}-\x{FFE1}\x{FFE2}\x{FFE3}\x{FFE4}\x{FFE5}-\x{FFE6}\x{FFE8}\x{FFE9}-\x{FFEC}\x{FFED}-\x{FFEE}\x{FFF0}-\x{FFF8}\x{FFF9}-\x{FFFB}\x{FFFC}-\x{FFFD}\x{FFFE}-\x{FFFF}\x{10101}\x{10140}-\x{10174}\x{10175}-\x{10178}\x{10179}-\x{10189}\x{1018A}-\x{1018B}\x{1018C}\x{10190}-\x{1019C}\x{101A0}\x{101FD}\x{102E0}\x{102E1}-\x{102FB}\x{10376}-\x{1037A}\x{10800}-\x{10805}\x{10806}-\x{10807}\x{10808}\x{10809}\x{1080A}-\x{10835}\x{10836}\x{10837}-\x{10838}\x{10839}-\x{1083B}\x{1083C}\x{1083D}-\x{1083E}\x{1083F}-\x{10855}\x{10856}\x{10857}\x{10858}-\x{1085F}\x{10860}-\x{10876}\x{10877}-\x{10878}\x{10879}-\x{1087F}\x{10880}-\x{1089E}\x{1089F}-\x{108A6}\x{108A7}-\x{108AF}\x{108B0}-\x{108DF}\x{108E0}-\x{108F2}\x{108F3}\x{108F4}-\x{108F5}\x{108F6}-\x{108FA}\x{108FB}-\x{108FF}\x{10900}-\x{10915}\x{10916}-\x{1091B}\x{1091C}-\x{1091E}\x{1091F}\x{10920}-\x{10939}\x{1093A}-\x{1093E}\x{1093F}\x{10940}-\x{1097F}\x{10980}-\x{109B7}\x{109B8}-\x{109BB}\x{109BC}-\x{109BD}\x{109BE}-\x{109BF}\x{109C0}-\x{109CF}\x{109D0}-\x{109D1}\x{109D2}-\x{109FF}\x{10A00}\x{10A01}-\x{10A03}\x{10A04}\x{10A05}-\x{10A06}\x{10A07}-\x{10A0B}\x{10A0C}-\x{10A0F}\x{10A10}-\x{10A13}\x{10A14}\x{10A15}-\x{10A17}\x{10A18}\x{10A19}-\x{10A35}\x{10A36}-\x{10A37}\x{10A38}-\x{10A3A}\x{10A3B}-\x{10A3E}\x{10A3F}\x{10A40}-\x{10A48}\x{10A49}-\x{10A4F}\x{10A50}-\x{10A58}\x{10A59}-\x{10A5F}\x{10A60}-\x{10A7C}\x{10A7D}-\x{10A7E}\x{10A7F}\x{10A80}-\x{10A9C}\x{10A9D}-\x{10A9F}\x{10AA0}-\x{10ABF}\x{10AC0}-\x{10AC7}\x{10AC8}\x{10AC9}-\x{10AE4}\x{10AE5}-\x{10AE6}\x{10AE7}-\x{10AEA}\x{10AEB}-\x{10AEF}\x{10AF0}-\x{10AF6}\x{10AF7}-\x{10AFF}\x{10B00}-\x{10B35}\x{10B36}-\x{10B38}\x{10B39}-\x{10B3F}\x{10B40}-\x{10B55}\x{10B56}-\x{10B57}\x{10B58}-\x{10B5F}\x{10B60}-\x{10B72}\x{10B73}-\x{10B77}\x{10B78}-\x{10B7F}\x{10B80}-\x{10B91}\x{10B92}-\x{10B98}\x{10B99}-\x{10B9C}\x{10B9D}-\x{10BA8}\x{10BA9}-\x{10BAF}\x{10BB0}-\x{10BFF}\x{10C00}-\x{10C48}\x{10C49}-\x{10C7F}\x{10C80}-\x{10CB2}\x{10CB3}-\x{10CBF}\x{10CC0}-\x{10CF2}\x{10CF3}-\x{10CF9}\x{10CFA}-\x{10CFF}\x{10D00}-\x{10D23}\x{10D24}-\x{10D27}\x{10D28}-\x{10D2F}\x{10D30}-\x{10D39}\x{10D3A}-\x{10D3F}\x{10D40}-\x{10E5F}\x{10E60}-\x{10E7E}\x{10E7F}\x{10E80}-\x{10EA9}\x{10EAA}\x{10EAB}-\x{10EAC}\x{10EAD}\x{10EAE}-\x{10EAF}\x{10EB0}-\x{10EB1}\x{10EB2}-\x{10EFF}\x{10F00}-\x{10F1C}\x{10F1D}-\x{10F26}\x{10F27}\x{10F28}-\x{10F2F}\x{10F30}-\x{10F45}\x{10F46}-\x{10F50}\x{10F51}-\x{10F54}\x{10F55}-\x{10F59}\x{10F5A}-\x{10F6F}\x{10F70}-\x{10FAF}\x{10FB0}-\x{10FC4}\x{10FC5}-\x{10FCB}\x{10FCC}-\x{10FDF}\x{10FE0}-\x{10FF6}\x{10FF7}-\x{10FFF}\x{11001}\x{11038}-\x{11046}\x{11052}-\x{11065}\x{1107F}-\x{11081}\x{110B3}-\x{110B6}\x{110B9}-\x{110BA}\x{11100}-\x{11102}\x{11127}-\x{1112B}\x{1112D}-\x{11134}\x{11173}\x{11180}-\x{11181}\x{111B6}-\x{111BE}\x{111C9}-\x{111CC}\x{111CF}\x{1122F}-\x{11231}\x{11234}\x{11236}-\x{11237}\x{1123E}\x{112DF}\x{112E3}-\x{112EA}\x{11300}-\x{11301}\x{1133B}-\x{1133C}\x{11340}\x{11366}-\x{1136C}\x{11370}-\x{11374}\x{11438}-\x{1143F}\x{11442}-\x{11444}\x{11446}\x{1145E}\x{114B3}-\x{114B8}\x{114BA}\x{114BF}-\x{114C0}\x{114C2}-\x{114C3}\x{115B2}-\x{115B5}\x{115BC}-\x{115BD}\x{115BF}-\x{115C0}\x{115DC}-\x{115DD}\x{11633}-\x{1163A}\x{1163D}\x{1163F}-\x{11640}\x{11660}-\x{1166C}\x{116AB}\x{116AD}\x{116B0}-\x{116B5}\x{116B7}\x{1171D}-\x{1171F}\x{11722}-\x{11725}\x{11727}-\x{1172B}\x{1182F}-\x{11837}\x{11839}-\x{1183A}\x{1193B}-\x{1193C}\x{1193E}\x{11943}\x{119D4}-\x{119D7}\x{119DA}-\x{119DB}\x{119E0}\x{11A01}-\x{11A06}\x{11A09}-\x{11A0A}\x{11A33}-\x{11A38}\x{11A3B}-\x{11A3E}\x{11A47}\x{11A51}-\x{11A56}\x{11A59}-\x{11A5B}\x{11A8A}-\x{11A96}\x{11A98}-\x{11A99}\x{11C30}-\x{11C36}\x{11C38}-\x{11C3D}\x{11C92}-\x{11CA7}\x{11CAA}-\x{11CB0}\x{11CB2}-\x{11CB3}\x{11CB5}-\x{11CB6}\x{11D31}-\x{11D36}\x{11D3A}\x{11D3C}-\x{11D3D}\x{11D3F}-\x{11D45}\x{11D47}\x{11D90}-\x{11D91}\x{11D95}\x{11D97}\x{11EF3}-\x{11EF4}\x{11FD5}-\x{11FDC}\x{11FDD}-\x{11FE0}\x{11FE1}-\x{11FF1}\x{16AF0}-\x{16AF4}\x{16B30}-\x{16B36}\x{16F4F}\x{16F8F}-\x{16F92}\x{16FE2}\x{16FE4}\x{1BC9D}-\x{1BC9E}\x{1BCA0}-\x{1BCA3}\x{1D167}-\x{1D169}\x{1D173}-\x{1D17A}\x{1D17B}-\x{1D182}\x{1D185}-\x{1D18B}\x{1D1AA}-\x{1D1AD}\x{1D200}-\x{1D241}\x{1D242}-\x{1D244}\x{1D245}\x{1D300}-\x{1D356}\x{1D6DB}\x{1D715}\x{1D74F}\x{1D789}\x{1D7C3}\x{1D7CE}-\x{1D7FF}\x{1DA00}-\x{1DA36}\x{1DA3B}-\x{1DA6C}\x{1DA75}\x{1DA84}\x{1DA9B}-\x{1DA9F}\x{1DAA1}-\x{1DAAF}\x{1E000}-\x{1E006}\x{1E008}-\x{1E018}\x{1E01B}-\x{1E021}\x{1E023}-\x{1E024}\x{1E026}-\x{1E02A}\x{1E130}-\x{1E136}\x{1E2EC}-\x{1E2EF}\x{1E2FF}\x{1E800}-\x{1E8C4}\x{1E8C5}-\x{1E8C6}\x{1E8C7}-\x{1E8CF}\x{1E8D0}-\x{1E8D6}\x{1E8D7}-\x{1E8FF}\x{1E900}-\x{1E943}\x{1E944}-\x{1E94A}\x{1E94B}\x{1E94C}-\x{1E94F}\x{1E950}-\x{1E959}\x{1E95A}-\x{1E95D}\x{1E95E}-\x{1E95F}\x{1E960}-\x{1EC6F}\x{1EC70}\x{1EC71}-\x{1ECAB}\x{1ECAC}\x{1ECAD}-\x{1ECAF}\x{1ECB0}\x{1ECB1}-\x{1ECB4}\x{1ECB5}-\x{1ECBF}\x{1ECC0}-\x{1ECFF}\x{1ED00}\x{1ED01}-\x{1ED2D}\x{1ED2E}\x{1ED2F}-\x{1ED3D}\x{1ED3E}-\x{1ED4F}\x{1ED50}-\x{1EDFF}\x{1EE00}-\x{1EE03}\x{1EE04}\x{1EE05}-\x{1EE1F}\x{1EE20}\x{1EE21}-\x{1EE22}\x{1EE23}\x{1EE24}\x{1EE25}-\x{1EE26}\x{1EE27}\x{1EE28}\x{1EE29}-\x{1EE32}\x{1EE33}\x{1EE34}-\x{1EE37}\x{1EE38}\x{1EE39}\x{1EE3A}\x{1EE3B}\x{1EE3C}-\x{1EE41}\x{1EE42}\x{1EE43}-\x{1EE46}\x{1EE47}\x{1EE48}\x{1EE49}\x{1EE4A}\x{1EE4B}\x{1EE4C}\x{1EE4D}-\x{1EE4F}\x{1EE50}\x{1EE51}-\x{1EE52}\x{1EE53}\x{1EE54}\x{1EE55}-\x{1EE56}\x{1EE57}\x{1EE58}\x{1EE59}\x{1EE5A}\x{1EE5B}\x{1EE5C}\x{1EE5D}\x{1EE5E}\x{1EE5F}\x{1EE60}\x{1EE61}-\x{1EE62}\x{1EE63}\x{1EE64}\x{1EE65}-\x{1EE66}\x{1EE67}-\x{1EE6A}\x{1EE6B}\x{1EE6C}-\x{1EE72}\x{1EE73}\x{1EE74}-\x{1EE77}\x{1EE78}\x{1EE79}-\x{1EE7C}\x{1EE7D}\x{1EE7E}\x{1EE7F}\x{1EE80}-\x{1EE89}\x{1EE8A}\x{1EE8B}-\x{1EE9B}\x{1EE9C}-\x{1EEA0}\x{1EEA1}-\x{1EEA3}\x{1EEA4}\x{1EEA5}-\x{1EEA9}\x{1EEAA}\x{1EEAB}-\x{1EEBB}\x{1EEBC}-\x{1EEEF}\x{1EEF0}-\x{1EEF1}\x{1EEF2}-\x{1EEFF}\x{1EF00}-\x{1EFFF}\x{1F000}-\x{1F02B}\x{1F030}-\x{1F093}\x{1F0A0}-\x{1F0AE}\x{1F0B1}-\x{1F0BF}\x{1F0C1}-\x{1F0CF}\x{1F0D1}-\x{1F0F5}\x{1F100}-\x{1F10A}\x{1F10B}-\x{1F10C}\x{1F10D}-\x{1F10F}\x{1F12F}\x{1F16A}-\x{1F16F}\x{1F1AD}\x{1F260}-\x{1F265}\x{1F300}-\x{1F3FA}\x{1F3FB}-\x{1F3FF}\x{1F400}-\x{1F6D7}\x{1F6E0}-\x{1F6EC}\x{1F6F0}-\x{1F6FC}\x{1F700}-\x{1F773}\x{1F780}-\x{1F7D8}\x{1F7E0}-\x{1F7EB}\x{1F800}-\x{1F80B}\x{1F810}-\x{1F847}\x{1F850}-\x{1F859}\x{1F860}-\x{1F887}\x{1F890}-\x{1F8AD}\x{1F8B0}-\x{1F8B1}\x{1F900}-\x{1F978}\x{1F97A}-\x{1F9CB}\x{1F9CD}-\x{1FA53}\x{1FA60}-\x{1FA6D}\x{1FA70}-\x{1FA74}\x{1FA78}-\x{1FA7A}\x{1FA80}-\x{1FA86}\x{1FA90}-\x{1FAA8}\x{1FAB0}-\x{1FAB6}\x{1FAC0}-\x{1FAC2}\x{1FAD0}-\x{1FAD6}\x{1FB00}-\x{1FB92}\x{1FB94}-\x{1FBCA}\x{1FBF0}-\x{1FBF9}\x{1FFFE}-\x{1FFFF}\x{2FFFE}-\x{2FFFF}\x{3FFFE}-\x{3FFFF}\x{4FFFE}-\x{4FFFF}\x{5FFFE}-\x{5FFFF}\x{6FFFE}-\x{6FFFF}\x{7FFFE}-\x{7FFFF}\x{8FFFE}-\x{8FFFF}\x{9FFFE}-\x{9FFFF}\x{AFFFE}-\x{AFFFF}\x{BFFFE}-\x{BFFFF}\x{CFFFE}-\x{CFFFF}\x{DFFFE}-\x{E0000}\x{E0001}\x{E0002}-\x{E001F}\x{E0020}-\x{E007F}\x{E0080}-\x{E00FF}\x{E0100}-\x{E01EF}\x{E01F0}-\x{E0FFF}\x{EFFFE}-\x{EFFFF}\x{FFFFE}-\x{FFFFF}\x{10FFFE}-\x{10FFFF}]/u'; - const BIDI_STEP_1_RTL = '/^[\x{0590}\x{05BE}\x{05C0}\x{05C3}\x{05C6}\x{05C8}-\x{05CF}\x{05D0}-\x{05EA}\x{05EB}-\x{05EE}\x{05EF}-\x{05F2}\x{05F3}-\x{05F4}\x{05F5}-\x{05FF}\x{0608}\x{060B}\x{060D}\x{061B}\x{061C}\x{061D}\x{061E}-\x{061F}\x{0620}-\x{063F}\x{0640}\x{0641}-\x{064A}\x{066D}\x{066E}-\x{066F}\x{0671}-\x{06D3}\x{06D4}\x{06D5}\x{06E5}-\x{06E6}\x{06EE}-\x{06EF}\x{06FA}-\x{06FC}\x{06FD}-\x{06FE}\x{06FF}\x{0700}-\x{070D}\x{070E}\x{070F}\x{0710}\x{0712}-\x{072F}\x{074B}-\x{074C}\x{074D}-\x{07A5}\x{07B1}\x{07B2}-\x{07BF}\x{07C0}-\x{07C9}\x{07CA}-\x{07EA}\x{07F4}-\x{07F5}\x{07FA}\x{07FB}-\x{07FC}\x{07FE}-\x{07FF}\x{0800}-\x{0815}\x{081A}\x{0824}\x{0828}\x{082E}-\x{082F}\x{0830}-\x{083E}\x{083F}\x{0840}-\x{0858}\x{085C}-\x{085D}\x{085E}\x{085F}\x{0860}-\x{086A}\x{086B}-\x{086F}\x{0870}-\x{089F}\x{08A0}-\x{08B4}\x{08B5}\x{08B6}-\x{08C7}\x{08C8}-\x{08D2}\x{200F}\x{FB1D}\x{FB1F}-\x{FB28}\x{FB2A}-\x{FB36}\x{FB37}\x{FB38}-\x{FB3C}\x{FB3D}\x{FB3E}\x{FB3F}\x{FB40}-\x{FB41}\x{FB42}\x{FB43}-\x{FB44}\x{FB45}\x{FB46}-\x{FB4F}\x{FB50}-\x{FBB1}\x{FBB2}-\x{FBC1}\x{FBC2}-\x{FBD2}\x{FBD3}-\x{FD3D}\x{FD40}-\x{FD4F}\x{FD50}-\x{FD8F}\x{FD90}-\x{FD91}\x{FD92}-\x{FDC7}\x{FDC8}-\x{FDCF}\x{FDF0}-\x{FDFB}\x{FDFC}\x{FDFE}-\x{FDFF}\x{FE70}-\x{FE74}\x{FE75}\x{FE76}-\x{FEFC}\x{FEFD}-\x{FEFE}\x{10800}-\x{10805}\x{10806}-\x{10807}\x{10808}\x{10809}\x{1080A}-\x{10835}\x{10836}\x{10837}-\x{10838}\x{10839}-\x{1083B}\x{1083C}\x{1083D}-\x{1083E}\x{1083F}-\x{10855}\x{10856}\x{10857}\x{10858}-\x{1085F}\x{10860}-\x{10876}\x{10877}-\x{10878}\x{10879}-\x{1087F}\x{10880}-\x{1089E}\x{1089F}-\x{108A6}\x{108A7}-\x{108AF}\x{108B0}-\x{108DF}\x{108E0}-\x{108F2}\x{108F3}\x{108F4}-\x{108F5}\x{108F6}-\x{108FA}\x{108FB}-\x{108FF}\x{10900}-\x{10915}\x{10916}-\x{1091B}\x{1091C}-\x{1091E}\x{10920}-\x{10939}\x{1093A}-\x{1093E}\x{1093F}\x{10940}-\x{1097F}\x{10980}-\x{109B7}\x{109B8}-\x{109BB}\x{109BC}-\x{109BD}\x{109BE}-\x{109BF}\x{109C0}-\x{109CF}\x{109D0}-\x{109D1}\x{109D2}-\x{109FF}\x{10A00}\x{10A04}\x{10A07}-\x{10A0B}\x{10A10}-\x{10A13}\x{10A14}\x{10A15}-\x{10A17}\x{10A18}\x{10A19}-\x{10A35}\x{10A36}-\x{10A37}\x{10A3B}-\x{10A3E}\x{10A40}-\x{10A48}\x{10A49}-\x{10A4F}\x{10A50}-\x{10A58}\x{10A59}-\x{10A5F}\x{10A60}-\x{10A7C}\x{10A7D}-\x{10A7E}\x{10A7F}\x{10A80}-\x{10A9C}\x{10A9D}-\x{10A9F}\x{10AA0}-\x{10ABF}\x{10AC0}-\x{10AC7}\x{10AC8}\x{10AC9}-\x{10AE4}\x{10AE7}-\x{10AEA}\x{10AEB}-\x{10AEF}\x{10AF0}-\x{10AF6}\x{10AF7}-\x{10AFF}\x{10B00}-\x{10B35}\x{10B36}-\x{10B38}\x{10B40}-\x{10B55}\x{10B56}-\x{10B57}\x{10B58}-\x{10B5F}\x{10B60}-\x{10B72}\x{10B73}-\x{10B77}\x{10B78}-\x{10B7F}\x{10B80}-\x{10B91}\x{10B92}-\x{10B98}\x{10B99}-\x{10B9C}\x{10B9D}-\x{10BA8}\x{10BA9}-\x{10BAF}\x{10BB0}-\x{10BFF}\x{10C00}-\x{10C48}\x{10C49}-\x{10C7F}\x{10C80}-\x{10CB2}\x{10CB3}-\x{10CBF}\x{10CC0}-\x{10CF2}\x{10CF3}-\x{10CF9}\x{10CFA}-\x{10CFF}\x{10D00}-\x{10D23}\x{10D28}-\x{10D2F}\x{10D3A}-\x{10D3F}\x{10D40}-\x{10E5F}\x{10E7F}\x{10E80}-\x{10EA9}\x{10EAA}\x{10EAD}\x{10EAE}-\x{10EAF}\x{10EB0}-\x{10EB1}\x{10EB2}-\x{10EFF}\x{10F00}-\x{10F1C}\x{10F1D}-\x{10F26}\x{10F27}\x{10F28}-\x{10F2F}\x{10F30}-\x{10F45}\x{10F51}-\x{10F54}\x{10F55}-\x{10F59}\x{10F5A}-\x{10F6F}\x{10F70}-\x{10FAF}\x{10FB0}-\x{10FC4}\x{10FC5}-\x{10FCB}\x{10FCC}-\x{10FDF}\x{10FE0}-\x{10FF6}\x{10FF7}-\x{10FFF}\x{1E800}-\x{1E8C4}\x{1E8C5}-\x{1E8C6}\x{1E8C7}-\x{1E8CF}\x{1E8D7}-\x{1E8FF}\x{1E900}-\x{1E943}\x{1E94B}\x{1E94C}-\x{1E94F}\x{1E950}-\x{1E959}\x{1E95A}-\x{1E95D}\x{1E95E}-\x{1E95F}\x{1E960}-\x{1EC6F}\x{1EC70}\x{1EC71}-\x{1ECAB}\x{1ECAC}\x{1ECAD}-\x{1ECAF}\x{1ECB0}\x{1ECB1}-\x{1ECB4}\x{1ECB5}-\x{1ECBF}\x{1ECC0}-\x{1ECFF}\x{1ED00}\x{1ED01}-\x{1ED2D}\x{1ED2E}\x{1ED2F}-\x{1ED3D}\x{1ED3E}-\x{1ED4F}\x{1ED50}-\x{1EDFF}\x{1EE00}-\x{1EE03}\x{1EE04}\x{1EE05}-\x{1EE1F}\x{1EE20}\x{1EE21}-\x{1EE22}\x{1EE23}\x{1EE24}\x{1EE25}-\x{1EE26}\x{1EE27}\x{1EE28}\x{1EE29}-\x{1EE32}\x{1EE33}\x{1EE34}-\x{1EE37}\x{1EE38}\x{1EE39}\x{1EE3A}\x{1EE3B}\x{1EE3C}-\x{1EE41}\x{1EE42}\x{1EE43}-\x{1EE46}\x{1EE47}\x{1EE48}\x{1EE49}\x{1EE4A}\x{1EE4B}\x{1EE4C}\x{1EE4D}-\x{1EE4F}\x{1EE50}\x{1EE51}-\x{1EE52}\x{1EE53}\x{1EE54}\x{1EE55}-\x{1EE56}\x{1EE57}\x{1EE58}\x{1EE59}\x{1EE5A}\x{1EE5B}\x{1EE5C}\x{1EE5D}\x{1EE5E}\x{1EE5F}\x{1EE60}\x{1EE61}-\x{1EE62}\x{1EE63}\x{1EE64}\x{1EE65}-\x{1EE66}\x{1EE67}-\x{1EE6A}\x{1EE6B}\x{1EE6C}-\x{1EE72}\x{1EE73}\x{1EE74}-\x{1EE77}\x{1EE78}\x{1EE79}-\x{1EE7C}\x{1EE7D}\x{1EE7E}\x{1EE7F}\x{1EE80}-\x{1EE89}\x{1EE8A}\x{1EE8B}-\x{1EE9B}\x{1EE9C}-\x{1EEA0}\x{1EEA1}-\x{1EEA3}\x{1EEA4}\x{1EEA5}-\x{1EEA9}\x{1EEAA}\x{1EEAB}-\x{1EEBB}\x{1EEBC}-\x{1EEEF}\x{1EEF2}-\x{1EEFF}\x{1EF00}-\x{1EFFF}]/u'; - const BIDI_STEP_2 = '/[^\x{0000}-\x{0008}\x{000E}-\x{001B}\x{0021}-\x{0022}\x{0023}\x{0024}\x{0025}\x{0026}-\x{0027}\x{0028}\x{0029}\x{002A}\x{002B}\x{002C}\x{002D}\x{002E}-\x{002F}\x{0030}-\x{0039}\x{003A}\x{003B}\x{003C}-\x{003E}\x{003F}-\x{0040}\x{005B}\x{005C}\x{005D}\x{005E}\x{005F}\x{0060}\x{007B}\x{007C}\x{007D}\x{007E}\x{007F}-\x{0084}\x{0086}-\x{009F}\x{00A0}\x{00A1}\x{00A2}-\x{00A5}\x{00A6}\x{00A7}\x{00A8}\x{00A9}\x{00AB}\x{00AC}\x{00AD}\x{00AE}\x{00AF}\x{00B0}\x{00B1}\x{00B2}-\x{00B3}\x{00B4}\x{00B6}-\x{00B7}\x{00B8}\x{00B9}\x{00BB}\x{00BC}-\x{00BE}\x{00BF}\x{00D7}\x{00F7}\x{02B9}-\x{02BA}\x{02C2}-\x{02C5}\x{02C6}-\x{02CF}\x{02D2}-\x{02DF}\x{02E5}-\x{02EB}\x{02EC}\x{02ED}\x{02EF}-\x{02FF}\x{0300}-\x{036F}\x{0374}\x{0375}\x{037E}\x{0384}-\x{0385}\x{0387}\x{03F6}\x{0483}-\x{0487}\x{0488}-\x{0489}\x{058A}\x{058D}-\x{058E}\x{058F}\x{0590}\x{0591}-\x{05BD}\x{05BE}\x{05BF}\x{05C0}\x{05C1}-\x{05C2}\x{05C3}\x{05C4}-\x{05C5}\x{05C6}\x{05C7}\x{05C8}-\x{05CF}\x{05D0}-\x{05EA}\x{05EB}-\x{05EE}\x{05EF}-\x{05F2}\x{05F3}-\x{05F4}\x{05F5}-\x{05FF}\x{0600}-\x{0605}\x{0606}-\x{0607}\x{0608}\x{0609}-\x{060A}\x{060B}\x{060C}\x{060D}\x{060E}-\x{060F}\x{0610}-\x{061A}\x{061B}\x{061C}\x{061D}\x{061E}-\x{061F}\x{0620}-\x{063F}\x{0640}\x{0641}-\x{064A}\x{064B}-\x{065F}\x{0660}-\x{0669}\x{066A}\x{066B}-\x{066C}\x{066D}\x{066E}-\x{066F}\x{0670}\x{0671}-\x{06D3}\x{06D4}\x{06D5}\x{06D6}-\x{06DC}\x{06DD}\x{06DE}\x{06DF}-\x{06E4}\x{06E5}-\x{06E6}\x{06E7}-\x{06E8}\x{06E9}\x{06EA}-\x{06ED}\x{06EE}-\x{06EF}\x{06F0}-\x{06F9}\x{06FA}-\x{06FC}\x{06FD}-\x{06FE}\x{06FF}\x{0700}-\x{070D}\x{070E}\x{070F}\x{0710}\x{0711}\x{0712}-\x{072F}\x{0730}-\x{074A}\x{074B}-\x{074C}\x{074D}-\x{07A5}\x{07A6}-\x{07B0}\x{07B1}\x{07B2}-\x{07BF}\x{07C0}-\x{07C9}\x{07CA}-\x{07EA}\x{07EB}-\x{07F3}\x{07F4}-\x{07F5}\x{07F6}\x{07F7}-\x{07F9}\x{07FA}\x{07FB}-\x{07FC}\x{07FD}\x{07FE}-\x{07FF}\x{0800}-\x{0815}\x{0816}-\x{0819}\x{081A}\x{081B}-\x{0823}\x{0824}\x{0825}-\x{0827}\x{0828}\x{0829}-\x{082D}\x{082E}-\x{082F}\x{0830}-\x{083E}\x{083F}\x{0840}-\x{0858}\x{0859}-\x{085B}\x{085C}-\x{085D}\x{085E}\x{085F}\x{0860}-\x{086A}\x{086B}-\x{086F}\x{0870}-\x{089F}\x{08A0}-\x{08B4}\x{08B5}\x{08B6}-\x{08C7}\x{08C8}-\x{08D2}\x{08D3}-\x{08E1}\x{08E2}\x{08E3}-\x{0902}\x{093A}\x{093C}\x{0941}-\x{0948}\x{094D}\x{0951}-\x{0957}\x{0962}-\x{0963}\x{0981}\x{09BC}\x{09C1}-\x{09C4}\x{09CD}\x{09E2}-\x{09E3}\x{09F2}-\x{09F3}\x{09FB}\x{09FE}\x{0A01}-\x{0A02}\x{0A3C}\x{0A41}-\x{0A42}\x{0A47}-\x{0A48}\x{0A4B}-\x{0A4D}\x{0A51}\x{0A70}-\x{0A71}\x{0A75}\x{0A81}-\x{0A82}\x{0ABC}\x{0AC1}-\x{0AC5}\x{0AC7}-\x{0AC8}\x{0ACD}\x{0AE2}-\x{0AE3}\x{0AF1}\x{0AFA}-\x{0AFF}\x{0B01}\x{0B3C}\x{0B3F}\x{0B41}-\x{0B44}\x{0B4D}\x{0B55}-\x{0B56}\x{0B62}-\x{0B63}\x{0B82}\x{0BC0}\x{0BCD}\x{0BF3}-\x{0BF8}\x{0BF9}\x{0BFA}\x{0C00}\x{0C04}\x{0C3E}-\x{0C40}\x{0C46}-\x{0C48}\x{0C4A}-\x{0C4D}\x{0C55}-\x{0C56}\x{0C62}-\x{0C63}\x{0C78}-\x{0C7E}\x{0C81}\x{0CBC}\x{0CCC}-\x{0CCD}\x{0CE2}-\x{0CE3}\x{0D00}-\x{0D01}\x{0D3B}-\x{0D3C}\x{0D41}-\x{0D44}\x{0D4D}\x{0D62}-\x{0D63}\x{0D81}\x{0DCA}\x{0DD2}-\x{0DD4}\x{0DD6}\x{0E31}\x{0E34}-\x{0E3A}\x{0E3F}\x{0E47}-\x{0E4E}\x{0EB1}\x{0EB4}-\x{0EBC}\x{0EC8}-\x{0ECD}\x{0F18}-\x{0F19}\x{0F35}\x{0F37}\x{0F39}\x{0F3A}\x{0F3B}\x{0F3C}\x{0F3D}\x{0F71}-\x{0F7E}\x{0F80}-\x{0F84}\x{0F86}-\x{0F87}\x{0F8D}-\x{0F97}\x{0F99}-\x{0FBC}\x{0FC6}\x{102D}-\x{1030}\x{1032}-\x{1037}\x{1039}-\x{103A}\x{103D}-\x{103E}\x{1058}-\x{1059}\x{105E}-\x{1060}\x{1071}-\x{1074}\x{1082}\x{1085}-\x{1086}\x{108D}\x{109D}\x{135D}-\x{135F}\x{1390}-\x{1399}\x{1400}\x{169B}\x{169C}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}-\x{1753}\x{1772}-\x{1773}\x{17B4}-\x{17B5}\x{17B7}-\x{17BD}\x{17C6}\x{17C9}-\x{17D3}\x{17DB}\x{17DD}\x{17F0}-\x{17F9}\x{1800}-\x{1805}\x{1806}\x{1807}-\x{180A}\x{180B}-\x{180D}\x{180E}\x{1885}-\x{1886}\x{18A9}\x{1920}-\x{1922}\x{1927}-\x{1928}\x{1932}\x{1939}-\x{193B}\x{1940}\x{1944}-\x{1945}\x{19DE}-\x{19FF}\x{1A17}-\x{1A18}\x{1A1B}\x{1A56}\x{1A58}-\x{1A5E}\x{1A60}\x{1A62}\x{1A65}-\x{1A6C}\x{1A73}-\x{1A7C}\x{1A7F}\x{1AB0}-\x{1ABD}\x{1ABE}\x{1ABF}-\x{1AC0}\x{1B00}-\x{1B03}\x{1B34}\x{1B36}-\x{1B3A}\x{1B3C}\x{1B42}\x{1B6B}-\x{1B73}\x{1B80}-\x{1B81}\x{1BA2}-\x{1BA5}\x{1BA8}-\x{1BA9}\x{1BAB}-\x{1BAD}\x{1BE6}\x{1BE8}-\x{1BE9}\x{1BED}\x{1BEF}-\x{1BF1}\x{1C2C}-\x{1C33}\x{1C36}-\x{1C37}\x{1CD0}-\x{1CD2}\x{1CD4}-\x{1CE0}\x{1CE2}-\x{1CE8}\x{1CED}\x{1CF4}\x{1CF8}-\x{1CF9}\x{1DC0}-\x{1DF9}\x{1DFB}-\x{1DFF}\x{1FBD}\x{1FBF}-\x{1FC1}\x{1FCD}-\x{1FCF}\x{1FDD}-\x{1FDF}\x{1FED}-\x{1FEF}\x{1FFD}-\x{1FFE}\x{200B}-\x{200D}\x{200F}\x{2010}-\x{2015}\x{2016}-\x{2017}\x{2018}\x{2019}\x{201A}\x{201B}-\x{201C}\x{201D}\x{201E}\x{201F}\x{2020}-\x{2027}\x{202F}\x{2030}-\x{2034}\x{2035}-\x{2038}\x{2039}\x{203A}\x{203B}-\x{203E}\x{203F}-\x{2040}\x{2041}-\x{2043}\x{2044}\x{2045}\x{2046}\x{2047}-\x{2051}\x{2052}\x{2053}\x{2054}\x{2055}-\x{205E}\x{2060}-\x{2064}\x{2065}\x{206A}-\x{206F}\x{2070}\x{2074}-\x{2079}\x{207A}-\x{207B}\x{207C}\x{207D}\x{207E}\x{2080}-\x{2089}\x{208A}-\x{208B}\x{208C}\x{208D}\x{208E}\x{20A0}-\x{20BF}\x{20C0}-\x{20CF}\x{20D0}-\x{20DC}\x{20DD}-\x{20E0}\x{20E1}\x{20E2}-\x{20E4}\x{20E5}-\x{20F0}\x{2100}-\x{2101}\x{2103}-\x{2106}\x{2108}-\x{2109}\x{2114}\x{2116}-\x{2117}\x{2118}\x{211E}-\x{2123}\x{2125}\x{2127}\x{2129}\x{212E}\x{213A}-\x{213B}\x{2140}-\x{2144}\x{214A}\x{214B}\x{214C}-\x{214D}\x{2150}-\x{215F}\x{2189}\x{218A}-\x{218B}\x{2190}-\x{2194}\x{2195}-\x{2199}\x{219A}-\x{219B}\x{219C}-\x{219F}\x{21A0}\x{21A1}-\x{21A2}\x{21A3}\x{21A4}-\x{21A5}\x{21A6}\x{21A7}-\x{21AD}\x{21AE}\x{21AF}-\x{21CD}\x{21CE}-\x{21CF}\x{21D0}-\x{21D1}\x{21D2}\x{21D3}\x{21D4}\x{21D5}-\x{21F3}\x{21F4}-\x{2211}\x{2212}\x{2213}\x{2214}-\x{22FF}\x{2300}-\x{2307}\x{2308}\x{2309}\x{230A}\x{230B}\x{230C}-\x{231F}\x{2320}-\x{2321}\x{2322}-\x{2328}\x{2329}\x{232A}\x{232B}-\x{2335}\x{237B}\x{237C}\x{237D}-\x{2394}\x{2396}-\x{239A}\x{239B}-\x{23B3}\x{23B4}-\x{23DB}\x{23DC}-\x{23E1}\x{23E2}-\x{2426}\x{2440}-\x{244A}\x{2460}-\x{2487}\x{2488}-\x{249B}\x{24EA}-\x{24FF}\x{2500}-\x{25B6}\x{25B7}\x{25B8}-\x{25C0}\x{25C1}\x{25C2}-\x{25F7}\x{25F8}-\x{25FF}\x{2600}-\x{266E}\x{266F}\x{2670}-\x{26AB}\x{26AD}-\x{2767}\x{2768}\x{2769}\x{276A}\x{276B}\x{276C}\x{276D}\x{276E}\x{276F}\x{2770}\x{2771}\x{2772}\x{2773}\x{2774}\x{2775}\x{2776}-\x{2793}\x{2794}-\x{27BF}\x{27C0}-\x{27C4}\x{27C5}\x{27C6}\x{27C7}-\x{27E5}\x{27E6}\x{27E7}\x{27E8}\x{27E9}\x{27EA}\x{27EB}\x{27EC}\x{27ED}\x{27EE}\x{27EF}\x{27F0}-\x{27FF}\x{2900}-\x{2982}\x{2983}\x{2984}\x{2985}\x{2986}\x{2987}\x{2988}\x{2989}\x{298A}\x{298B}\x{298C}\x{298D}\x{298E}\x{298F}\x{2990}\x{2991}\x{2992}\x{2993}\x{2994}\x{2995}\x{2996}\x{2997}\x{2998}\x{2999}-\x{29D7}\x{29D8}\x{29D9}\x{29DA}\x{29DB}\x{29DC}-\x{29FB}\x{29FC}\x{29FD}\x{29FE}-\x{2AFF}\x{2B00}-\x{2B2F}\x{2B30}-\x{2B44}\x{2B45}-\x{2B46}\x{2B47}-\x{2B4C}\x{2B4D}-\x{2B73}\x{2B76}-\x{2B95}\x{2B97}-\x{2BFF}\x{2CE5}-\x{2CEA}\x{2CEF}-\x{2CF1}\x{2CF9}-\x{2CFC}\x{2CFD}\x{2CFE}-\x{2CFF}\x{2D7F}\x{2DE0}-\x{2DFF}\x{2E00}-\x{2E01}\x{2E02}\x{2E03}\x{2E04}\x{2E05}\x{2E06}-\x{2E08}\x{2E09}\x{2E0A}\x{2E0B}\x{2E0C}\x{2E0D}\x{2E0E}-\x{2E16}\x{2E17}\x{2E18}-\x{2E19}\x{2E1A}\x{2E1B}\x{2E1C}\x{2E1D}\x{2E1E}-\x{2E1F}\x{2E20}\x{2E21}\x{2E22}\x{2E23}\x{2E24}\x{2E25}\x{2E26}\x{2E27}\x{2E28}\x{2E29}\x{2E2A}-\x{2E2E}\x{2E2F}\x{2E30}-\x{2E39}\x{2E3A}-\x{2E3B}\x{2E3C}-\x{2E3F}\x{2E40}\x{2E41}\x{2E42}\x{2E43}-\x{2E4F}\x{2E50}-\x{2E51}\x{2E52}\x{2E80}-\x{2E99}\x{2E9B}-\x{2EF3}\x{2F00}-\x{2FD5}\x{2FF0}-\x{2FFB}\x{3001}-\x{3003}\x{3004}\x{3008}\x{3009}\x{300A}\x{300B}\x{300C}\x{300D}\x{300E}\x{300F}\x{3010}\x{3011}\x{3012}-\x{3013}\x{3014}\x{3015}\x{3016}\x{3017}\x{3018}\x{3019}\x{301A}\x{301B}\x{301C}\x{301D}\x{301E}-\x{301F}\x{3020}\x{302A}-\x{302D}\x{3030}\x{3036}-\x{3037}\x{303D}\x{303E}-\x{303F}\x{3099}-\x{309A}\x{309B}-\x{309C}\x{30A0}\x{30FB}\x{31C0}-\x{31E3}\x{321D}-\x{321E}\x{3250}\x{3251}-\x{325F}\x{327C}-\x{327E}\x{32B1}-\x{32BF}\x{32CC}-\x{32CF}\x{3377}-\x{337A}\x{33DE}-\x{33DF}\x{33FF}\x{4DC0}-\x{4DFF}\x{A490}-\x{A4C6}\x{A60D}-\x{A60F}\x{A66F}\x{A670}-\x{A672}\x{A673}\x{A674}-\x{A67D}\x{A67E}\x{A67F}\x{A69E}-\x{A69F}\x{A6F0}-\x{A6F1}\x{A700}-\x{A716}\x{A717}-\x{A71F}\x{A720}-\x{A721}\x{A788}\x{A802}\x{A806}\x{A80B}\x{A825}-\x{A826}\x{A828}-\x{A82B}\x{A82C}\x{A838}\x{A839}\x{A874}-\x{A877}\x{A8C4}-\x{A8C5}\x{A8E0}-\x{A8F1}\x{A8FF}\x{A926}-\x{A92D}\x{A947}-\x{A951}\x{A980}-\x{A982}\x{A9B3}\x{A9B6}-\x{A9B9}\x{A9BC}-\x{A9BD}\x{A9E5}\x{AA29}-\x{AA2E}\x{AA31}-\x{AA32}\x{AA35}-\x{AA36}\x{AA43}\x{AA4C}\x{AA7C}\x{AAB0}\x{AAB2}-\x{AAB4}\x{AAB7}-\x{AAB8}\x{AABE}-\x{AABF}\x{AAC1}\x{AAEC}-\x{AAED}\x{AAF6}\x{AB6A}-\x{AB6B}\x{ABE5}\x{ABE8}\x{ABED}\x{FB1D}\x{FB1E}\x{FB1F}-\x{FB28}\x{FB29}\x{FB2A}-\x{FB36}\x{FB37}\x{FB38}-\x{FB3C}\x{FB3D}\x{FB3E}\x{FB3F}\x{FB40}-\x{FB41}\x{FB42}\x{FB43}-\x{FB44}\x{FB45}\x{FB46}-\x{FB4F}\x{FB50}-\x{FBB1}\x{FBB2}-\x{FBC1}\x{FBC2}-\x{FBD2}\x{FBD3}-\x{FD3D}\x{FD3E}\x{FD3F}\x{FD40}-\x{FD4F}\x{FD50}-\x{FD8F}\x{FD90}-\x{FD91}\x{FD92}-\x{FDC7}\x{FDC8}-\x{FDCF}\x{FDD0}-\x{FDEF}\x{FDF0}-\x{FDFB}\x{FDFC}\x{FDFD}\x{FDFE}-\x{FDFF}\x{FE00}-\x{FE0F}\x{FE10}-\x{FE16}\x{FE17}\x{FE18}\x{FE19}\x{FE20}-\x{FE2F}\x{FE30}\x{FE31}-\x{FE32}\x{FE33}-\x{FE34}\x{FE35}\x{FE36}\x{FE37}\x{FE38}\x{FE39}\x{FE3A}\x{FE3B}\x{FE3C}\x{FE3D}\x{FE3E}\x{FE3F}\x{FE40}\x{FE41}\x{FE42}\x{FE43}\x{FE44}\x{FE45}-\x{FE46}\x{FE47}\x{FE48}\x{FE49}-\x{FE4C}\x{FE4D}-\x{FE4F}\x{FE50}\x{FE51}\x{FE52}\x{FE54}\x{FE55}\x{FE56}-\x{FE57}\x{FE58}\x{FE59}\x{FE5A}\x{FE5B}\x{FE5C}\x{FE5D}\x{FE5E}\x{FE5F}\x{FE60}-\x{FE61}\x{FE62}\x{FE63}\x{FE64}-\x{FE66}\x{FE68}\x{FE69}\x{FE6A}\x{FE6B}\x{FE70}-\x{FE74}\x{FE75}\x{FE76}-\x{FEFC}\x{FEFD}-\x{FEFE}\x{FEFF}\x{FF01}-\x{FF02}\x{FF03}\x{FF04}\x{FF05}\x{FF06}-\x{FF07}\x{FF08}\x{FF09}\x{FF0A}\x{FF0B}\x{FF0C}\x{FF0D}\x{FF0E}-\x{FF0F}\x{FF10}-\x{FF19}\x{FF1A}\x{FF1B}\x{FF1C}-\x{FF1E}\x{FF1F}-\x{FF20}\x{FF3B}\x{FF3C}\x{FF3D}\x{FF3E}\x{FF3F}\x{FF40}\x{FF5B}\x{FF5C}\x{FF5D}\x{FF5E}\x{FF5F}\x{FF60}\x{FF61}\x{FF62}\x{FF63}\x{FF64}-\x{FF65}\x{FFE0}-\x{FFE1}\x{FFE2}\x{FFE3}\x{FFE4}\x{FFE5}-\x{FFE6}\x{FFE8}\x{FFE9}-\x{FFEC}\x{FFED}-\x{FFEE}\x{FFF0}-\x{FFF8}\x{FFF9}-\x{FFFB}\x{FFFC}-\x{FFFD}\x{FFFE}-\x{FFFF}\x{10101}\x{10140}-\x{10174}\x{10175}-\x{10178}\x{10179}-\x{10189}\x{1018A}-\x{1018B}\x{1018C}\x{10190}-\x{1019C}\x{101A0}\x{101FD}\x{102E0}\x{102E1}-\x{102FB}\x{10376}-\x{1037A}\x{10800}-\x{10805}\x{10806}-\x{10807}\x{10808}\x{10809}\x{1080A}-\x{10835}\x{10836}\x{10837}-\x{10838}\x{10839}-\x{1083B}\x{1083C}\x{1083D}-\x{1083E}\x{1083F}-\x{10855}\x{10856}\x{10857}\x{10858}-\x{1085F}\x{10860}-\x{10876}\x{10877}-\x{10878}\x{10879}-\x{1087F}\x{10880}-\x{1089E}\x{1089F}-\x{108A6}\x{108A7}-\x{108AF}\x{108B0}-\x{108DF}\x{108E0}-\x{108F2}\x{108F3}\x{108F4}-\x{108F5}\x{108F6}-\x{108FA}\x{108FB}-\x{108FF}\x{10900}-\x{10915}\x{10916}-\x{1091B}\x{1091C}-\x{1091E}\x{1091F}\x{10920}-\x{10939}\x{1093A}-\x{1093E}\x{1093F}\x{10940}-\x{1097F}\x{10980}-\x{109B7}\x{109B8}-\x{109BB}\x{109BC}-\x{109BD}\x{109BE}-\x{109BF}\x{109C0}-\x{109CF}\x{109D0}-\x{109D1}\x{109D2}-\x{109FF}\x{10A00}\x{10A01}-\x{10A03}\x{10A04}\x{10A05}-\x{10A06}\x{10A07}-\x{10A0B}\x{10A0C}-\x{10A0F}\x{10A10}-\x{10A13}\x{10A14}\x{10A15}-\x{10A17}\x{10A18}\x{10A19}-\x{10A35}\x{10A36}-\x{10A37}\x{10A38}-\x{10A3A}\x{10A3B}-\x{10A3E}\x{10A3F}\x{10A40}-\x{10A48}\x{10A49}-\x{10A4F}\x{10A50}-\x{10A58}\x{10A59}-\x{10A5F}\x{10A60}-\x{10A7C}\x{10A7D}-\x{10A7E}\x{10A7F}\x{10A80}-\x{10A9C}\x{10A9D}-\x{10A9F}\x{10AA0}-\x{10ABF}\x{10AC0}-\x{10AC7}\x{10AC8}\x{10AC9}-\x{10AE4}\x{10AE5}-\x{10AE6}\x{10AE7}-\x{10AEA}\x{10AEB}-\x{10AEF}\x{10AF0}-\x{10AF6}\x{10AF7}-\x{10AFF}\x{10B00}-\x{10B35}\x{10B36}-\x{10B38}\x{10B39}-\x{10B3F}\x{10B40}-\x{10B55}\x{10B56}-\x{10B57}\x{10B58}-\x{10B5F}\x{10B60}-\x{10B72}\x{10B73}-\x{10B77}\x{10B78}-\x{10B7F}\x{10B80}-\x{10B91}\x{10B92}-\x{10B98}\x{10B99}-\x{10B9C}\x{10B9D}-\x{10BA8}\x{10BA9}-\x{10BAF}\x{10BB0}-\x{10BFF}\x{10C00}-\x{10C48}\x{10C49}-\x{10C7F}\x{10C80}-\x{10CB2}\x{10CB3}-\x{10CBF}\x{10CC0}-\x{10CF2}\x{10CF3}-\x{10CF9}\x{10CFA}-\x{10CFF}\x{10D00}-\x{10D23}\x{10D24}-\x{10D27}\x{10D28}-\x{10D2F}\x{10D30}-\x{10D39}\x{10D3A}-\x{10D3F}\x{10D40}-\x{10E5F}\x{10E60}-\x{10E7E}\x{10E7F}\x{10E80}-\x{10EA9}\x{10EAA}\x{10EAB}-\x{10EAC}\x{10EAD}\x{10EAE}-\x{10EAF}\x{10EB0}-\x{10EB1}\x{10EB2}-\x{10EFF}\x{10F00}-\x{10F1C}\x{10F1D}-\x{10F26}\x{10F27}\x{10F28}-\x{10F2F}\x{10F30}-\x{10F45}\x{10F46}-\x{10F50}\x{10F51}-\x{10F54}\x{10F55}-\x{10F59}\x{10F5A}-\x{10F6F}\x{10F70}-\x{10FAF}\x{10FB0}-\x{10FC4}\x{10FC5}-\x{10FCB}\x{10FCC}-\x{10FDF}\x{10FE0}-\x{10FF6}\x{10FF7}-\x{10FFF}\x{11001}\x{11038}-\x{11046}\x{11052}-\x{11065}\x{1107F}-\x{11081}\x{110B3}-\x{110B6}\x{110B9}-\x{110BA}\x{11100}-\x{11102}\x{11127}-\x{1112B}\x{1112D}-\x{11134}\x{11173}\x{11180}-\x{11181}\x{111B6}-\x{111BE}\x{111C9}-\x{111CC}\x{111CF}\x{1122F}-\x{11231}\x{11234}\x{11236}-\x{11237}\x{1123E}\x{112DF}\x{112E3}-\x{112EA}\x{11300}-\x{11301}\x{1133B}-\x{1133C}\x{11340}\x{11366}-\x{1136C}\x{11370}-\x{11374}\x{11438}-\x{1143F}\x{11442}-\x{11444}\x{11446}\x{1145E}\x{114B3}-\x{114B8}\x{114BA}\x{114BF}-\x{114C0}\x{114C2}-\x{114C3}\x{115B2}-\x{115B5}\x{115BC}-\x{115BD}\x{115BF}-\x{115C0}\x{115DC}-\x{115DD}\x{11633}-\x{1163A}\x{1163D}\x{1163F}-\x{11640}\x{11660}-\x{1166C}\x{116AB}\x{116AD}\x{116B0}-\x{116B5}\x{116B7}\x{1171D}-\x{1171F}\x{11722}-\x{11725}\x{11727}-\x{1172B}\x{1182F}-\x{11837}\x{11839}-\x{1183A}\x{1193B}-\x{1193C}\x{1193E}\x{11943}\x{119D4}-\x{119D7}\x{119DA}-\x{119DB}\x{119E0}\x{11A01}-\x{11A06}\x{11A09}-\x{11A0A}\x{11A33}-\x{11A38}\x{11A3B}-\x{11A3E}\x{11A47}\x{11A51}-\x{11A56}\x{11A59}-\x{11A5B}\x{11A8A}-\x{11A96}\x{11A98}-\x{11A99}\x{11C30}-\x{11C36}\x{11C38}-\x{11C3D}\x{11C92}-\x{11CA7}\x{11CAA}-\x{11CB0}\x{11CB2}-\x{11CB3}\x{11CB5}-\x{11CB6}\x{11D31}-\x{11D36}\x{11D3A}\x{11D3C}-\x{11D3D}\x{11D3F}-\x{11D45}\x{11D47}\x{11D90}-\x{11D91}\x{11D95}\x{11D97}\x{11EF3}-\x{11EF4}\x{11FD5}-\x{11FDC}\x{11FDD}-\x{11FE0}\x{11FE1}-\x{11FF1}\x{16AF0}-\x{16AF4}\x{16B30}-\x{16B36}\x{16F4F}\x{16F8F}-\x{16F92}\x{16FE2}\x{16FE4}\x{1BC9D}-\x{1BC9E}\x{1BCA0}-\x{1BCA3}\x{1D167}-\x{1D169}\x{1D173}-\x{1D17A}\x{1D17B}-\x{1D182}\x{1D185}-\x{1D18B}\x{1D1AA}-\x{1D1AD}\x{1D200}-\x{1D241}\x{1D242}-\x{1D244}\x{1D245}\x{1D300}-\x{1D356}\x{1D6DB}\x{1D715}\x{1D74F}\x{1D789}\x{1D7C3}\x{1D7CE}-\x{1D7FF}\x{1DA00}-\x{1DA36}\x{1DA3B}-\x{1DA6C}\x{1DA75}\x{1DA84}\x{1DA9B}-\x{1DA9F}\x{1DAA1}-\x{1DAAF}\x{1E000}-\x{1E006}\x{1E008}-\x{1E018}\x{1E01B}-\x{1E021}\x{1E023}-\x{1E024}\x{1E026}-\x{1E02A}\x{1E130}-\x{1E136}\x{1E2EC}-\x{1E2EF}\x{1E2FF}\x{1E800}-\x{1E8C4}\x{1E8C5}-\x{1E8C6}\x{1E8C7}-\x{1E8CF}\x{1E8D0}-\x{1E8D6}\x{1E8D7}-\x{1E8FF}\x{1E900}-\x{1E943}\x{1E944}-\x{1E94A}\x{1E94B}\x{1E94C}-\x{1E94F}\x{1E950}-\x{1E959}\x{1E95A}-\x{1E95D}\x{1E95E}-\x{1E95F}\x{1E960}-\x{1EC6F}\x{1EC70}\x{1EC71}-\x{1ECAB}\x{1ECAC}\x{1ECAD}-\x{1ECAF}\x{1ECB0}\x{1ECB1}-\x{1ECB4}\x{1ECB5}-\x{1ECBF}\x{1ECC0}-\x{1ECFF}\x{1ED00}\x{1ED01}-\x{1ED2D}\x{1ED2E}\x{1ED2F}-\x{1ED3D}\x{1ED3E}-\x{1ED4F}\x{1ED50}-\x{1EDFF}\x{1EE00}-\x{1EE03}\x{1EE04}\x{1EE05}-\x{1EE1F}\x{1EE20}\x{1EE21}-\x{1EE22}\x{1EE23}\x{1EE24}\x{1EE25}-\x{1EE26}\x{1EE27}\x{1EE28}\x{1EE29}-\x{1EE32}\x{1EE33}\x{1EE34}-\x{1EE37}\x{1EE38}\x{1EE39}\x{1EE3A}\x{1EE3B}\x{1EE3C}-\x{1EE41}\x{1EE42}\x{1EE43}-\x{1EE46}\x{1EE47}\x{1EE48}\x{1EE49}\x{1EE4A}\x{1EE4B}\x{1EE4C}\x{1EE4D}-\x{1EE4F}\x{1EE50}\x{1EE51}-\x{1EE52}\x{1EE53}\x{1EE54}\x{1EE55}-\x{1EE56}\x{1EE57}\x{1EE58}\x{1EE59}\x{1EE5A}\x{1EE5B}\x{1EE5C}\x{1EE5D}\x{1EE5E}\x{1EE5F}\x{1EE60}\x{1EE61}-\x{1EE62}\x{1EE63}\x{1EE64}\x{1EE65}-\x{1EE66}\x{1EE67}-\x{1EE6A}\x{1EE6B}\x{1EE6C}-\x{1EE72}\x{1EE73}\x{1EE74}-\x{1EE77}\x{1EE78}\x{1EE79}-\x{1EE7C}\x{1EE7D}\x{1EE7E}\x{1EE7F}\x{1EE80}-\x{1EE89}\x{1EE8A}\x{1EE8B}-\x{1EE9B}\x{1EE9C}-\x{1EEA0}\x{1EEA1}-\x{1EEA3}\x{1EEA4}\x{1EEA5}-\x{1EEA9}\x{1EEAA}\x{1EEAB}-\x{1EEBB}\x{1EEBC}-\x{1EEEF}\x{1EEF0}-\x{1EEF1}\x{1EEF2}-\x{1EEFF}\x{1EF00}-\x{1EFFF}\x{1F000}-\x{1F02B}\x{1F030}-\x{1F093}\x{1F0A0}-\x{1F0AE}\x{1F0B1}-\x{1F0BF}\x{1F0C1}-\x{1F0CF}\x{1F0D1}-\x{1F0F5}\x{1F100}-\x{1F10A}\x{1F10B}-\x{1F10C}\x{1F10D}-\x{1F10F}\x{1F12F}\x{1F16A}-\x{1F16F}\x{1F1AD}\x{1F260}-\x{1F265}\x{1F300}-\x{1F3FA}\x{1F3FB}-\x{1F3FF}\x{1F400}-\x{1F6D7}\x{1F6E0}-\x{1F6EC}\x{1F6F0}-\x{1F6FC}\x{1F700}-\x{1F773}\x{1F780}-\x{1F7D8}\x{1F7E0}-\x{1F7EB}\x{1F800}-\x{1F80B}\x{1F810}-\x{1F847}\x{1F850}-\x{1F859}\x{1F860}-\x{1F887}\x{1F890}-\x{1F8AD}\x{1F8B0}-\x{1F8B1}\x{1F900}-\x{1F978}\x{1F97A}-\x{1F9CB}\x{1F9CD}-\x{1FA53}\x{1FA60}-\x{1FA6D}\x{1FA70}-\x{1FA74}\x{1FA78}-\x{1FA7A}\x{1FA80}-\x{1FA86}\x{1FA90}-\x{1FAA8}\x{1FAB0}-\x{1FAB6}\x{1FAC0}-\x{1FAC2}\x{1FAD0}-\x{1FAD6}\x{1FB00}-\x{1FB92}\x{1FB94}-\x{1FBCA}\x{1FBF0}-\x{1FBF9}\x{1FFFE}-\x{1FFFF}\x{2FFFE}-\x{2FFFF}\x{3FFFE}-\x{3FFFF}\x{4FFFE}-\x{4FFFF}\x{5FFFE}-\x{5FFFF}\x{6FFFE}-\x{6FFFF}\x{7FFFE}-\x{7FFFF}\x{8FFFE}-\x{8FFFF}\x{9FFFE}-\x{9FFFF}\x{AFFFE}-\x{AFFFF}\x{BFFFE}-\x{BFFFF}\x{CFFFE}-\x{CFFFF}\x{DFFFE}-\x{E0000}\x{E0001}\x{E0002}-\x{E001F}\x{E0020}-\x{E007F}\x{E0080}-\x{E00FF}\x{E0100}-\x{E01EF}\x{E01F0}-\x{E0FFF}\x{EFFFE}-\x{EFFFF}\x{FFFFE}-\x{FFFFF}\x{10FFFE}-\x{10FFFF}]/u'; - const BIDI_STEP_3 = '/[\x{0030}-\x{0039}\x{00B2}-\x{00B3}\x{00B9}\x{0590}\x{05BE}\x{05C0}\x{05C3}\x{05C6}\x{05C8}-\x{05CF}\x{05D0}-\x{05EA}\x{05EB}-\x{05EE}\x{05EF}-\x{05F2}\x{05F3}-\x{05F4}\x{05F5}-\x{05FF}\x{0600}-\x{0605}\x{0608}\x{060B}\x{060D}\x{061B}\x{061C}\x{061D}\x{061E}-\x{061F}\x{0620}-\x{063F}\x{0640}\x{0641}-\x{064A}\x{0660}-\x{0669}\x{066B}-\x{066C}\x{066D}\x{066E}-\x{066F}\x{0671}-\x{06D3}\x{06D4}\x{06D5}\x{06DD}\x{06E5}-\x{06E6}\x{06EE}-\x{06EF}\x{06F0}-\x{06F9}\x{06FA}-\x{06FC}\x{06FD}-\x{06FE}\x{06FF}\x{0700}-\x{070D}\x{070E}\x{070F}\x{0710}\x{0712}-\x{072F}\x{074B}-\x{074C}\x{074D}-\x{07A5}\x{07B1}\x{07B2}-\x{07BF}\x{07C0}-\x{07C9}\x{07CA}-\x{07EA}\x{07F4}-\x{07F5}\x{07FA}\x{07FB}-\x{07FC}\x{07FE}-\x{07FF}\x{0800}-\x{0815}\x{081A}\x{0824}\x{0828}\x{082E}-\x{082F}\x{0830}-\x{083E}\x{083F}\x{0840}-\x{0858}\x{085C}-\x{085D}\x{085E}\x{085F}\x{0860}-\x{086A}\x{086B}-\x{086F}\x{0870}-\x{089F}\x{08A0}-\x{08B4}\x{08B5}\x{08B6}-\x{08C7}\x{08C8}-\x{08D2}\x{08E2}\x{200F}\x{2070}\x{2074}-\x{2079}\x{2080}-\x{2089}\x{2488}-\x{249B}\x{FB1D}\x{FB1F}-\x{FB28}\x{FB2A}-\x{FB36}\x{FB37}\x{FB38}-\x{FB3C}\x{FB3D}\x{FB3E}\x{FB3F}\x{FB40}-\x{FB41}\x{FB42}\x{FB43}-\x{FB44}\x{FB45}\x{FB46}-\x{FB4F}\x{FB50}-\x{FBB1}\x{FBB2}-\x{FBC1}\x{FBC2}-\x{FBD2}\x{FBD3}-\x{FD3D}\x{FD40}-\x{FD4F}\x{FD50}-\x{FD8F}\x{FD90}-\x{FD91}\x{FD92}-\x{FDC7}\x{FDC8}-\x{FDCF}\x{FDF0}-\x{FDFB}\x{FDFC}\x{FDFE}-\x{FDFF}\x{FE70}-\x{FE74}\x{FE75}\x{FE76}-\x{FEFC}\x{FEFD}-\x{FEFE}\x{FF10}-\x{FF19}\x{102E1}-\x{102FB}\x{10800}-\x{10805}\x{10806}-\x{10807}\x{10808}\x{10809}\x{1080A}-\x{10835}\x{10836}\x{10837}-\x{10838}\x{10839}-\x{1083B}\x{1083C}\x{1083D}-\x{1083E}\x{1083F}-\x{10855}\x{10856}\x{10857}\x{10858}-\x{1085F}\x{10860}-\x{10876}\x{10877}-\x{10878}\x{10879}-\x{1087F}\x{10880}-\x{1089E}\x{1089F}-\x{108A6}\x{108A7}-\x{108AF}\x{108B0}-\x{108DF}\x{108E0}-\x{108F2}\x{108F3}\x{108F4}-\x{108F5}\x{108F6}-\x{108FA}\x{108FB}-\x{108FF}\x{10900}-\x{10915}\x{10916}-\x{1091B}\x{1091C}-\x{1091E}\x{10920}-\x{10939}\x{1093A}-\x{1093E}\x{1093F}\x{10940}-\x{1097F}\x{10980}-\x{109B7}\x{109B8}-\x{109BB}\x{109BC}-\x{109BD}\x{109BE}-\x{109BF}\x{109C0}-\x{109CF}\x{109D0}-\x{109D1}\x{109D2}-\x{109FF}\x{10A00}\x{10A04}\x{10A07}-\x{10A0B}\x{10A10}-\x{10A13}\x{10A14}\x{10A15}-\x{10A17}\x{10A18}\x{10A19}-\x{10A35}\x{10A36}-\x{10A37}\x{10A3B}-\x{10A3E}\x{10A40}-\x{10A48}\x{10A49}-\x{10A4F}\x{10A50}-\x{10A58}\x{10A59}-\x{10A5F}\x{10A60}-\x{10A7C}\x{10A7D}-\x{10A7E}\x{10A7F}\x{10A80}-\x{10A9C}\x{10A9D}-\x{10A9F}\x{10AA0}-\x{10ABF}\x{10AC0}-\x{10AC7}\x{10AC8}\x{10AC9}-\x{10AE4}\x{10AE7}-\x{10AEA}\x{10AEB}-\x{10AEF}\x{10AF0}-\x{10AF6}\x{10AF7}-\x{10AFF}\x{10B00}-\x{10B35}\x{10B36}-\x{10B38}\x{10B40}-\x{10B55}\x{10B56}-\x{10B57}\x{10B58}-\x{10B5F}\x{10B60}-\x{10B72}\x{10B73}-\x{10B77}\x{10B78}-\x{10B7F}\x{10B80}-\x{10B91}\x{10B92}-\x{10B98}\x{10B99}-\x{10B9C}\x{10B9D}-\x{10BA8}\x{10BA9}-\x{10BAF}\x{10BB0}-\x{10BFF}\x{10C00}-\x{10C48}\x{10C49}-\x{10C7F}\x{10C80}-\x{10CB2}\x{10CB3}-\x{10CBF}\x{10CC0}-\x{10CF2}\x{10CF3}-\x{10CF9}\x{10CFA}-\x{10CFF}\x{10D00}-\x{10D23}\x{10D28}-\x{10D2F}\x{10D30}-\x{10D39}\x{10D3A}-\x{10D3F}\x{10D40}-\x{10E5F}\x{10E60}-\x{10E7E}\x{10E7F}\x{10E80}-\x{10EA9}\x{10EAA}\x{10EAD}\x{10EAE}-\x{10EAF}\x{10EB0}-\x{10EB1}\x{10EB2}-\x{10EFF}\x{10F00}-\x{10F1C}\x{10F1D}-\x{10F26}\x{10F27}\x{10F28}-\x{10F2F}\x{10F30}-\x{10F45}\x{10F51}-\x{10F54}\x{10F55}-\x{10F59}\x{10F5A}-\x{10F6F}\x{10F70}-\x{10FAF}\x{10FB0}-\x{10FC4}\x{10FC5}-\x{10FCB}\x{10FCC}-\x{10FDF}\x{10FE0}-\x{10FF6}\x{10FF7}-\x{10FFF}\x{1D7CE}-\x{1D7FF}\x{1E800}-\x{1E8C4}\x{1E8C5}-\x{1E8C6}\x{1E8C7}-\x{1E8CF}\x{1E8D7}-\x{1E8FF}\x{1E900}-\x{1E943}\x{1E94B}\x{1E94C}-\x{1E94F}\x{1E950}-\x{1E959}\x{1E95A}-\x{1E95D}\x{1E95E}-\x{1E95F}\x{1E960}-\x{1EC6F}\x{1EC70}\x{1EC71}-\x{1ECAB}\x{1ECAC}\x{1ECAD}-\x{1ECAF}\x{1ECB0}\x{1ECB1}-\x{1ECB4}\x{1ECB5}-\x{1ECBF}\x{1ECC0}-\x{1ECFF}\x{1ED00}\x{1ED01}-\x{1ED2D}\x{1ED2E}\x{1ED2F}-\x{1ED3D}\x{1ED3E}-\x{1ED4F}\x{1ED50}-\x{1EDFF}\x{1EE00}-\x{1EE03}\x{1EE04}\x{1EE05}-\x{1EE1F}\x{1EE20}\x{1EE21}-\x{1EE22}\x{1EE23}\x{1EE24}\x{1EE25}-\x{1EE26}\x{1EE27}\x{1EE28}\x{1EE29}-\x{1EE32}\x{1EE33}\x{1EE34}-\x{1EE37}\x{1EE38}\x{1EE39}\x{1EE3A}\x{1EE3B}\x{1EE3C}-\x{1EE41}\x{1EE42}\x{1EE43}-\x{1EE46}\x{1EE47}\x{1EE48}\x{1EE49}\x{1EE4A}\x{1EE4B}\x{1EE4C}\x{1EE4D}-\x{1EE4F}\x{1EE50}\x{1EE51}-\x{1EE52}\x{1EE53}\x{1EE54}\x{1EE55}-\x{1EE56}\x{1EE57}\x{1EE58}\x{1EE59}\x{1EE5A}\x{1EE5B}\x{1EE5C}\x{1EE5D}\x{1EE5E}\x{1EE5F}\x{1EE60}\x{1EE61}-\x{1EE62}\x{1EE63}\x{1EE64}\x{1EE65}-\x{1EE66}\x{1EE67}-\x{1EE6A}\x{1EE6B}\x{1EE6C}-\x{1EE72}\x{1EE73}\x{1EE74}-\x{1EE77}\x{1EE78}\x{1EE79}-\x{1EE7C}\x{1EE7D}\x{1EE7E}\x{1EE7F}\x{1EE80}-\x{1EE89}\x{1EE8A}\x{1EE8B}-\x{1EE9B}\x{1EE9C}-\x{1EEA0}\x{1EEA1}-\x{1EEA3}\x{1EEA4}\x{1EEA5}-\x{1EEA9}\x{1EEAA}\x{1EEAB}-\x{1EEBB}\x{1EEBC}-\x{1EEEF}\x{1EEF2}-\x{1EEFF}\x{1EF00}-\x{1EFFF}\x{1F100}-\x{1F10A}\x{1FBF0}-\x{1FBF9}][\x{0300}-\x{036F}\x{0483}-\x{0487}\x{0488}-\x{0489}\x{0591}-\x{05BD}\x{05BF}\x{05C1}-\x{05C2}\x{05C4}-\x{05C5}\x{05C7}\x{0610}-\x{061A}\x{064B}-\x{065F}\x{0670}\x{06D6}-\x{06DC}\x{06DF}-\x{06E4}\x{06E7}-\x{06E8}\x{06EA}-\x{06ED}\x{0711}\x{0730}-\x{074A}\x{07A6}-\x{07B0}\x{07EB}-\x{07F3}\x{07FD}\x{0816}-\x{0819}\x{081B}-\x{0823}\x{0825}-\x{0827}\x{0829}-\x{082D}\x{0859}-\x{085B}\x{08D3}-\x{08E1}\x{08E3}-\x{0902}\x{093A}\x{093C}\x{0941}-\x{0948}\x{094D}\x{0951}-\x{0957}\x{0962}-\x{0963}\x{0981}\x{09BC}\x{09C1}-\x{09C4}\x{09CD}\x{09E2}-\x{09E3}\x{09FE}\x{0A01}-\x{0A02}\x{0A3C}\x{0A41}-\x{0A42}\x{0A47}-\x{0A48}\x{0A4B}-\x{0A4D}\x{0A51}\x{0A70}-\x{0A71}\x{0A75}\x{0A81}-\x{0A82}\x{0ABC}\x{0AC1}-\x{0AC5}\x{0AC7}-\x{0AC8}\x{0ACD}\x{0AE2}-\x{0AE3}\x{0AFA}-\x{0AFF}\x{0B01}\x{0B3C}\x{0B3F}\x{0B41}-\x{0B44}\x{0B4D}\x{0B55}-\x{0B56}\x{0B62}-\x{0B63}\x{0B82}\x{0BC0}\x{0BCD}\x{0C00}\x{0C04}\x{0C3E}-\x{0C40}\x{0C46}-\x{0C48}\x{0C4A}-\x{0C4D}\x{0C55}-\x{0C56}\x{0C62}-\x{0C63}\x{0C81}\x{0CBC}\x{0CCC}-\x{0CCD}\x{0CE2}-\x{0CE3}\x{0D00}-\x{0D01}\x{0D3B}-\x{0D3C}\x{0D41}-\x{0D44}\x{0D4D}\x{0D62}-\x{0D63}\x{0D81}\x{0DCA}\x{0DD2}-\x{0DD4}\x{0DD6}\x{0E31}\x{0E34}-\x{0E3A}\x{0E47}-\x{0E4E}\x{0EB1}\x{0EB4}-\x{0EBC}\x{0EC8}-\x{0ECD}\x{0F18}-\x{0F19}\x{0F35}\x{0F37}\x{0F39}\x{0F71}-\x{0F7E}\x{0F80}-\x{0F84}\x{0F86}-\x{0F87}\x{0F8D}-\x{0F97}\x{0F99}-\x{0FBC}\x{0FC6}\x{102D}-\x{1030}\x{1032}-\x{1037}\x{1039}-\x{103A}\x{103D}-\x{103E}\x{1058}-\x{1059}\x{105E}-\x{1060}\x{1071}-\x{1074}\x{1082}\x{1085}-\x{1086}\x{108D}\x{109D}\x{135D}-\x{135F}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}-\x{1753}\x{1772}-\x{1773}\x{17B4}-\x{17B5}\x{17B7}-\x{17BD}\x{17C6}\x{17C9}-\x{17D3}\x{17DD}\x{180B}-\x{180D}\x{1885}-\x{1886}\x{18A9}\x{1920}-\x{1922}\x{1927}-\x{1928}\x{1932}\x{1939}-\x{193B}\x{1A17}-\x{1A18}\x{1A1B}\x{1A56}\x{1A58}-\x{1A5E}\x{1A60}\x{1A62}\x{1A65}-\x{1A6C}\x{1A73}-\x{1A7C}\x{1A7F}\x{1AB0}-\x{1ABD}\x{1ABE}\x{1ABF}-\x{1AC0}\x{1B00}-\x{1B03}\x{1B34}\x{1B36}-\x{1B3A}\x{1B3C}\x{1B42}\x{1B6B}-\x{1B73}\x{1B80}-\x{1B81}\x{1BA2}-\x{1BA5}\x{1BA8}-\x{1BA9}\x{1BAB}-\x{1BAD}\x{1BE6}\x{1BE8}-\x{1BE9}\x{1BED}\x{1BEF}-\x{1BF1}\x{1C2C}-\x{1C33}\x{1C36}-\x{1C37}\x{1CD0}-\x{1CD2}\x{1CD4}-\x{1CE0}\x{1CE2}-\x{1CE8}\x{1CED}\x{1CF4}\x{1CF8}-\x{1CF9}\x{1DC0}-\x{1DF9}\x{1DFB}-\x{1DFF}\x{20D0}-\x{20DC}\x{20DD}-\x{20E0}\x{20E1}\x{20E2}-\x{20E4}\x{20E5}-\x{20F0}\x{2CEF}-\x{2CF1}\x{2D7F}\x{2DE0}-\x{2DFF}\x{302A}-\x{302D}\x{3099}-\x{309A}\x{A66F}\x{A670}-\x{A672}\x{A674}-\x{A67D}\x{A69E}-\x{A69F}\x{A6F0}-\x{A6F1}\x{A802}\x{A806}\x{A80B}\x{A825}-\x{A826}\x{A82C}\x{A8C4}-\x{A8C5}\x{A8E0}-\x{A8F1}\x{A8FF}\x{A926}-\x{A92D}\x{A947}-\x{A951}\x{A980}-\x{A982}\x{A9B3}\x{A9B6}-\x{A9B9}\x{A9BC}-\x{A9BD}\x{A9E5}\x{AA29}-\x{AA2E}\x{AA31}-\x{AA32}\x{AA35}-\x{AA36}\x{AA43}\x{AA4C}\x{AA7C}\x{AAB0}\x{AAB2}-\x{AAB4}\x{AAB7}-\x{AAB8}\x{AABE}-\x{AABF}\x{AAC1}\x{AAEC}-\x{AAED}\x{AAF6}\x{ABE5}\x{ABE8}\x{ABED}\x{FB1E}\x{FE00}-\x{FE0F}\x{FE20}-\x{FE2F}\x{101FD}\x{102E0}\x{10376}-\x{1037A}\x{10A01}-\x{10A03}\x{10A05}-\x{10A06}\x{10A0C}-\x{10A0F}\x{10A38}-\x{10A3A}\x{10A3F}\x{10AE5}-\x{10AE6}\x{10D24}-\x{10D27}\x{10EAB}-\x{10EAC}\x{10F46}-\x{10F50}\x{11001}\x{11038}-\x{11046}\x{1107F}-\x{11081}\x{110B3}-\x{110B6}\x{110B9}-\x{110BA}\x{11100}-\x{11102}\x{11127}-\x{1112B}\x{1112D}-\x{11134}\x{11173}\x{11180}-\x{11181}\x{111B6}-\x{111BE}\x{111C9}-\x{111CC}\x{111CF}\x{1122F}-\x{11231}\x{11234}\x{11236}-\x{11237}\x{1123E}\x{112DF}\x{112E3}-\x{112EA}\x{11300}-\x{11301}\x{1133B}-\x{1133C}\x{11340}\x{11366}-\x{1136C}\x{11370}-\x{11374}\x{11438}-\x{1143F}\x{11442}-\x{11444}\x{11446}\x{1145E}\x{114B3}-\x{114B8}\x{114BA}\x{114BF}-\x{114C0}\x{114C2}-\x{114C3}\x{115B2}-\x{115B5}\x{115BC}-\x{115BD}\x{115BF}-\x{115C0}\x{115DC}-\x{115DD}\x{11633}-\x{1163A}\x{1163D}\x{1163F}-\x{11640}\x{116AB}\x{116AD}\x{116B0}-\x{116B5}\x{116B7}\x{1171D}-\x{1171F}\x{11722}-\x{11725}\x{11727}-\x{1172B}\x{1182F}-\x{11837}\x{11839}-\x{1183A}\x{1193B}-\x{1193C}\x{1193E}\x{11943}\x{119D4}-\x{119D7}\x{119DA}-\x{119DB}\x{119E0}\x{11A01}-\x{11A06}\x{11A09}-\x{11A0A}\x{11A33}-\x{11A38}\x{11A3B}-\x{11A3E}\x{11A47}\x{11A51}-\x{11A56}\x{11A59}-\x{11A5B}\x{11A8A}-\x{11A96}\x{11A98}-\x{11A99}\x{11C30}-\x{11C36}\x{11C38}-\x{11C3D}\x{11C92}-\x{11CA7}\x{11CAA}-\x{11CB0}\x{11CB2}-\x{11CB3}\x{11CB5}-\x{11CB6}\x{11D31}-\x{11D36}\x{11D3A}\x{11D3C}-\x{11D3D}\x{11D3F}-\x{11D45}\x{11D47}\x{11D90}-\x{11D91}\x{11D95}\x{11D97}\x{11EF3}-\x{11EF4}\x{16AF0}-\x{16AF4}\x{16B30}-\x{16B36}\x{16F4F}\x{16F8F}-\x{16F92}\x{16FE4}\x{1BC9D}-\x{1BC9E}\x{1D167}-\x{1D169}\x{1D17B}-\x{1D182}\x{1D185}-\x{1D18B}\x{1D1AA}-\x{1D1AD}\x{1D242}-\x{1D244}\x{1DA00}-\x{1DA36}\x{1DA3B}-\x{1DA6C}\x{1DA75}\x{1DA84}\x{1DA9B}-\x{1DA9F}\x{1DAA1}-\x{1DAAF}\x{1E000}-\x{1E006}\x{1E008}-\x{1E018}\x{1E01B}-\x{1E021}\x{1E023}-\x{1E024}\x{1E026}-\x{1E02A}\x{1E130}-\x{1E136}\x{1E2EC}-\x{1E2EF}\x{1E8D0}-\x{1E8D6}\x{1E944}-\x{1E94A}\x{E0100}-\x{E01EF}]*$/u'; - const BIDI_STEP_4_AN = '/[\x{0600}-\x{0605}\x{0660}-\x{0669}\x{066B}-\x{066C}\x{06DD}\x{08E2}\x{10D30}-\x{10D39}\x{10E60}-\x{10E7E}]/u'; - const BIDI_STEP_4_EN = '/[\x{0030}-\x{0039}\x{00B2}-\x{00B3}\x{00B9}\x{06F0}-\x{06F9}\x{2070}\x{2074}-\x{2079}\x{2080}-\x{2089}\x{2488}-\x{249B}\x{FF10}-\x{FF19}\x{102E1}-\x{102FB}\x{1D7CE}-\x{1D7FF}\x{1F100}-\x{1F10A}\x{1FBF0}-\x{1FBF9}]/u'; - const BIDI_STEP_5 = '/[\x{0009}\x{000A}\x{000B}\x{000C}\x{000D}\x{001C}-\x{001E}\x{001F}\x{0020}\x{0085}\x{0590}\x{05BE}\x{05C0}\x{05C3}\x{05C6}\x{05C8}-\x{05CF}\x{05D0}-\x{05EA}\x{05EB}-\x{05EE}\x{05EF}-\x{05F2}\x{05F3}-\x{05F4}\x{05F5}-\x{05FF}\x{0600}-\x{0605}\x{0608}\x{060B}\x{060D}\x{061B}\x{061C}\x{061D}\x{061E}-\x{061F}\x{0620}-\x{063F}\x{0640}\x{0641}-\x{064A}\x{0660}-\x{0669}\x{066B}-\x{066C}\x{066D}\x{066E}-\x{066F}\x{0671}-\x{06D3}\x{06D4}\x{06D5}\x{06DD}\x{06E5}-\x{06E6}\x{06EE}-\x{06EF}\x{06FA}-\x{06FC}\x{06FD}-\x{06FE}\x{06FF}\x{0700}-\x{070D}\x{070E}\x{070F}\x{0710}\x{0712}-\x{072F}\x{074B}-\x{074C}\x{074D}-\x{07A5}\x{07B1}\x{07B2}-\x{07BF}\x{07C0}-\x{07C9}\x{07CA}-\x{07EA}\x{07F4}-\x{07F5}\x{07FA}\x{07FB}-\x{07FC}\x{07FE}-\x{07FF}\x{0800}-\x{0815}\x{081A}\x{0824}\x{0828}\x{082E}-\x{082F}\x{0830}-\x{083E}\x{083F}\x{0840}-\x{0858}\x{085C}-\x{085D}\x{085E}\x{085F}\x{0860}-\x{086A}\x{086B}-\x{086F}\x{0870}-\x{089F}\x{08A0}-\x{08B4}\x{08B5}\x{08B6}-\x{08C7}\x{08C8}-\x{08D2}\x{08E2}\x{1680}\x{2000}-\x{200A}\x{200F}\x{2028}\x{2029}\x{202A}\x{202B}\x{202C}\x{202D}\x{202E}\x{205F}\x{2066}\x{2067}\x{2068}\x{2069}\x{3000}\x{FB1D}\x{FB1F}-\x{FB28}\x{FB2A}-\x{FB36}\x{FB37}\x{FB38}-\x{FB3C}\x{FB3D}\x{FB3E}\x{FB3F}\x{FB40}-\x{FB41}\x{FB42}\x{FB43}-\x{FB44}\x{FB45}\x{FB46}-\x{FB4F}\x{FB50}-\x{FBB1}\x{FBB2}-\x{FBC1}\x{FBC2}-\x{FBD2}\x{FBD3}-\x{FD3D}\x{FD40}-\x{FD4F}\x{FD50}-\x{FD8F}\x{FD90}-\x{FD91}\x{FD92}-\x{FDC7}\x{FDC8}-\x{FDCF}\x{FDF0}-\x{FDFB}\x{FDFC}\x{FDFE}-\x{FDFF}\x{FE70}-\x{FE74}\x{FE75}\x{FE76}-\x{FEFC}\x{FEFD}-\x{FEFE}\x{10800}-\x{10805}\x{10806}-\x{10807}\x{10808}\x{10809}\x{1080A}-\x{10835}\x{10836}\x{10837}-\x{10838}\x{10839}-\x{1083B}\x{1083C}\x{1083D}-\x{1083E}\x{1083F}-\x{10855}\x{10856}\x{10857}\x{10858}-\x{1085F}\x{10860}-\x{10876}\x{10877}-\x{10878}\x{10879}-\x{1087F}\x{10880}-\x{1089E}\x{1089F}-\x{108A6}\x{108A7}-\x{108AF}\x{108B0}-\x{108DF}\x{108E0}-\x{108F2}\x{108F3}\x{108F4}-\x{108F5}\x{108F6}-\x{108FA}\x{108FB}-\x{108FF}\x{10900}-\x{10915}\x{10916}-\x{1091B}\x{1091C}-\x{1091E}\x{10920}-\x{10939}\x{1093A}-\x{1093E}\x{1093F}\x{10940}-\x{1097F}\x{10980}-\x{109B7}\x{109B8}-\x{109BB}\x{109BC}-\x{109BD}\x{109BE}-\x{109BF}\x{109C0}-\x{109CF}\x{109D0}-\x{109D1}\x{109D2}-\x{109FF}\x{10A00}\x{10A04}\x{10A07}-\x{10A0B}\x{10A10}-\x{10A13}\x{10A14}\x{10A15}-\x{10A17}\x{10A18}\x{10A19}-\x{10A35}\x{10A36}-\x{10A37}\x{10A3B}-\x{10A3E}\x{10A40}-\x{10A48}\x{10A49}-\x{10A4F}\x{10A50}-\x{10A58}\x{10A59}-\x{10A5F}\x{10A60}-\x{10A7C}\x{10A7D}-\x{10A7E}\x{10A7F}\x{10A80}-\x{10A9C}\x{10A9D}-\x{10A9F}\x{10AA0}-\x{10ABF}\x{10AC0}-\x{10AC7}\x{10AC8}\x{10AC9}-\x{10AE4}\x{10AE7}-\x{10AEA}\x{10AEB}-\x{10AEF}\x{10AF0}-\x{10AF6}\x{10AF7}-\x{10AFF}\x{10B00}-\x{10B35}\x{10B36}-\x{10B38}\x{10B40}-\x{10B55}\x{10B56}-\x{10B57}\x{10B58}-\x{10B5F}\x{10B60}-\x{10B72}\x{10B73}-\x{10B77}\x{10B78}-\x{10B7F}\x{10B80}-\x{10B91}\x{10B92}-\x{10B98}\x{10B99}-\x{10B9C}\x{10B9D}-\x{10BA8}\x{10BA9}-\x{10BAF}\x{10BB0}-\x{10BFF}\x{10C00}-\x{10C48}\x{10C49}-\x{10C7F}\x{10C80}-\x{10CB2}\x{10CB3}-\x{10CBF}\x{10CC0}-\x{10CF2}\x{10CF3}-\x{10CF9}\x{10CFA}-\x{10CFF}\x{10D00}-\x{10D23}\x{10D28}-\x{10D2F}\x{10D30}-\x{10D39}\x{10D3A}-\x{10D3F}\x{10D40}-\x{10E5F}\x{10E60}-\x{10E7E}\x{10E7F}\x{10E80}-\x{10EA9}\x{10EAA}\x{10EAD}\x{10EAE}-\x{10EAF}\x{10EB0}-\x{10EB1}\x{10EB2}-\x{10EFF}\x{10F00}-\x{10F1C}\x{10F1D}-\x{10F26}\x{10F27}\x{10F28}-\x{10F2F}\x{10F30}-\x{10F45}\x{10F51}-\x{10F54}\x{10F55}-\x{10F59}\x{10F5A}-\x{10F6F}\x{10F70}-\x{10FAF}\x{10FB0}-\x{10FC4}\x{10FC5}-\x{10FCB}\x{10FCC}-\x{10FDF}\x{10FE0}-\x{10FF6}\x{10FF7}-\x{10FFF}\x{1E800}-\x{1E8C4}\x{1E8C5}-\x{1E8C6}\x{1E8C7}-\x{1E8CF}\x{1E8D7}-\x{1E8FF}\x{1E900}-\x{1E943}\x{1E94B}\x{1E94C}-\x{1E94F}\x{1E950}-\x{1E959}\x{1E95A}-\x{1E95D}\x{1E95E}-\x{1E95F}\x{1E960}-\x{1EC6F}\x{1EC70}\x{1EC71}-\x{1ECAB}\x{1ECAC}\x{1ECAD}-\x{1ECAF}\x{1ECB0}\x{1ECB1}-\x{1ECB4}\x{1ECB5}-\x{1ECBF}\x{1ECC0}-\x{1ECFF}\x{1ED00}\x{1ED01}-\x{1ED2D}\x{1ED2E}\x{1ED2F}-\x{1ED3D}\x{1ED3E}-\x{1ED4F}\x{1ED50}-\x{1EDFF}\x{1EE00}-\x{1EE03}\x{1EE04}\x{1EE05}-\x{1EE1F}\x{1EE20}\x{1EE21}-\x{1EE22}\x{1EE23}\x{1EE24}\x{1EE25}-\x{1EE26}\x{1EE27}\x{1EE28}\x{1EE29}-\x{1EE32}\x{1EE33}\x{1EE34}-\x{1EE37}\x{1EE38}\x{1EE39}\x{1EE3A}\x{1EE3B}\x{1EE3C}-\x{1EE41}\x{1EE42}\x{1EE43}-\x{1EE46}\x{1EE47}\x{1EE48}\x{1EE49}\x{1EE4A}\x{1EE4B}\x{1EE4C}\x{1EE4D}-\x{1EE4F}\x{1EE50}\x{1EE51}-\x{1EE52}\x{1EE53}\x{1EE54}\x{1EE55}-\x{1EE56}\x{1EE57}\x{1EE58}\x{1EE59}\x{1EE5A}\x{1EE5B}\x{1EE5C}\x{1EE5D}\x{1EE5E}\x{1EE5F}\x{1EE60}\x{1EE61}-\x{1EE62}\x{1EE63}\x{1EE64}\x{1EE65}-\x{1EE66}\x{1EE67}-\x{1EE6A}\x{1EE6B}\x{1EE6C}-\x{1EE72}\x{1EE73}\x{1EE74}-\x{1EE77}\x{1EE78}\x{1EE79}-\x{1EE7C}\x{1EE7D}\x{1EE7E}\x{1EE7F}\x{1EE80}-\x{1EE89}\x{1EE8A}\x{1EE8B}-\x{1EE9B}\x{1EE9C}-\x{1EEA0}\x{1EEA1}-\x{1EEA3}\x{1EEA4}\x{1EEA5}-\x{1EEA9}\x{1EEAA}\x{1EEAB}-\x{1EEBB}\x{1EEBC}-\x{1EEEF}\x{1EEF2}-\x{1EEFF}\x{1EF00}-\x{1EFFF}]/u'; - const BIDI_STEP_6 = '/[^\x{0000}-\x{0008}\x{0009}\x{000A}\x{000B}\x{000C}\x{000D}\x{000E}-\x{001B}\x{001C}-\x{001E}\x{001F}\x{0020}\x{0021}-\x{0022}\x{0023}\x{0024}\x{0025}\x{0026}-\x{0027}\x{0028}\x{0029}\x{002A}\x{002B}\x{002C}\x{002D}\x{002E}-\x{002F}\x{003A}\x{003B}\x{003C}-\x{003E}\x{003F}-\x{0040}\x{005B}\x{005C}\x{005D}\x{005E}\x{005F}\x{0060}\x{007B}\x{007C}\x{007D}\x{007E}\x{007F}-\x{0084}\x{0085}\x{0086}-\x{009F}\x{00A0}\x{00A1}\x{00A2}-\x{00A5}\x{00A6}\x{00A7}\x{00A8}\x{00A9}\x{00AB}\x{00AC}\x{00AD}\x{00AE}\x{00AF}\x{00B0}\x{00B1}\x{00B4}\x{00B6}-\x{00B7}\x{00B8}\x{00BB}\x{00BC}-\x{00BE}\x{00BF}\x{00D7}\x{00F7}\x{02B9}-\x{02BA}\x{02C2}-\x{02C5}\x{02C6}-\x{02CF}\x{02D2}-\x{02DF}\x{02E5}-\x{02EB}\x{02EC}\x{02ED}\x{02EF}-\x{02FF}\x{0300}-\x{036F}\x{0374}\x{0375}\x{037E}\x{0384}-\x{0385}\x{0387}\x{03F6}\x{0483}-\x{0487}\x{0488}-\x{0489}\x{058A}\x{058D}-\x{058E}\x{058F}\x{0590}\x{0591}-\x{05BD}\x{05BE}\x{05BF}\x{05C0}\x{05C1}-\x{05C2}\x{05C3}\x{05C4}-\x{05C5}\x{05C6}\x{05C7}\x{05C8}-\x{05CF}\x{05D0}-\x{05EA}\x{05EB}-\x{05EE}\x{05EF}-\x{05F2}\x{05F3}-\x{05F4}\x{05F5}-\x{05FF}\x{0600}-\x{0605}\x{0606}-\x{0607}\x{0608}\x{0609}-\x{060A}\x{060B}\x{060C}\x{060D}\x{060E}-\x{060F}\x{0610}-\x{061A}\x{061B}\x{061C}\x{061D}\x{061E}-\x{061F}\x{0620}-\x{063F}\x{0640}\x{0641}-\x{064A}\x{064B}-\x{065F}\x{0660}-\x{0669}\x{066A}\x{066B}-\x{066C}\x{066D}\x{066E}-\x{066F}\x{0670}\x{0671}-\x{06D3}\x{06D4}\x{06D5}\x{06D6}-\x{06DC}\x{06DD}\x{06DE}\x{06DF}-\x{06E4}\x{06E5}-\x{06E6}\x{06E7}-\x{06E8}\x{06E9}\x{06EA}-\x{06ED}\x{06EE}-\x{06EF}\x{06FA}-\x{06FC}\x{06FD}-\x{06FE}\x{06FF}\x{0700}-\x{070D}\x{070E}\x{070F}\x{0710}\x{0711}\x{0712}-\x{072F}\x{0730}-\x{074A}\x{074B}-\x{074C}\x{074D}-\x{07A5}\x{07A6}-\x{07B0}\x{07B1}\x{07B2}-\x{07BF}\x{07C0}-\x{07C9}\x{07CA}-\x{07EA}\x{07EB}-\x{07F3}\x{07F4}-\x{07F5}\x{07F6}\x{07F7}-\x{07F9}\x{07FA}\x{07FB}-\x{07FC}\x{07FD}\x{07FE}-\x{07FF}\x{0800}-\x{0815}\x{0816}-\x{0819}\x{081A}\x{081B}-\x{0823}\x{0824}\x{0825}-\x{0827}\x{0828}\x{0829}-\x{082D}\x{082E}-\x{082F}\x{0830}-\x{083E}\x{083F}\x{0840}-\x{0858}\x{0859}-\x{085B}\x{085C}-\x{085D}\x{085E}\x{085F}\x{0860}-\x{086A}\x{086B}-\x{086F}\x{0870}-\x{089F}\x{08A0}-\x{08B4}\x{08B5}\x{08B6}-\x{08C7}\x{08C8}-\x{08D2}\x{08D3}-\x{08E1}\x{08E2}\x{08E3}-\x{0902}\x{093A}\x{093C}\x{0941}-\x{0948}\x{094D}\x{0951}-\x{0957}\x{0962}-\x{0963}\x{0981}\x{09BC}\x{09C1}-\x{09C4}\x{09CD}\x{09E2}-\x{09E3}\x{09F2}-\x{09F3}\x{09FB}\x{09FE}\x{0A01}-\x{0A02}\x{0A3C}\x{0A41}-\x{0A42}\x{0A47}-\x{0A48}\x{0A4B}-\x{0A4D}\x{0A51}\x{0A70}-\x{0A71}\x{0A75}\x{0A81}-\x{0A82}\x{0ABC}\x{0AC1}-\x{0AC5}\x{0AC7}-\x{0AC8}\x{0ACD}\x{0AE2}-\x{0AE3}\x{0AF1}\x{0AFA}-\x{0AFF}\x{0B01}\x{0B3C}\x{0B3F}\x{0B41}-\x{0B44}\x{0B4D}\x{0B55}-\x{0B56}\x{0B62}-\x{0B63}\x{0B82}\x{0BC0}\x{0BCD}\x{0BF3}-\x{0BF8}\x{0BF9}\x{0BFA}\x{0C00}\x{0C04}\x{0C3E}-\x{0C40}\x{0C46}-\x{0C48}\x{0C4A}-\x{0C4D}\x{0C55}-\x{0C56}\x{0C62}-\x{0C63}\x{0C78}-\x{0C7E}\x{0C81}\x{0CBC}\x{0CCC}-\x{0CCD}\x{0CE2}-\x{0CE3}\x{0D00}-\x{0D01}\x{0D3B}-\x{0D3C}\x{0D41}-\x{0D44}\x{0D4D}\x{0D62}-\x{0D63}\x{0D81}\x{0DCA}\x{0DD2}-\x{0DD4}\x{0DD6}\x{0E31}\x{0E34}-\x{0E3A}\x{0E3F}\x{0E47}-\x{0E4E}\x{0EB1}\x{0EB4}-\x{0EBC}\x{0EC8}-\x{0ECD}\x{0F18}-\x{0F19}\x{0F35}\x{0F37}\x{0F39}\x{0F3A}\x{0F3B}\x{0F3C}\x{0F3D}\x{0F71}-\x{0F7E}\x{0F80}-\x{0F84}\x{0F86}-\x{0F87}\x{0F8D}-\x{0F97}\x{0F99}-\x{0FBC}\x{0FC6}\x{102D}-\x{1030}\x{1032}-\x{1037}\x{1039}-\x{103A}\x{103D}-\x{103E}\x{1058}-\x{1059}\x{105E}-\x{1060}\x{1071}-\x{1074}\x{1082}\x{1085}-\x{1086}\x{108D}\x{109D}\x{135D}-\x{135F}\x{1390}-\x{1399}\x{1400}\x{1680}\x{169B}\x{169C}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}-\x{1753}\x{1772}-\x{1773}\x{17B4}-\x{17B5}\x{17B7}-\x{17BD}\x{17C6}\x{17C9}-\x{17D3}\x{17DB}\x{17DD}\x{17F0}-\x{17F9}\x{1800}-\x{1805}\x{1806}\x{1807}-\x{180A}\x{180B}-\x{180D}\x{180E}\x{1885}-\x{1886}\x{18A9}\x{1920}-\x{1922}\x{1927}-\x{1928}\x{1932}\x{1939}-\x{193B}\x{1940}\x{1944}-\x{1945}\x{19DE}-\x{19FF}\x{1A17}-\x{1A18}\x{1A1B}\x{1A56}\x{1A58}-\x{1A5E}\x{1A60}\x{1A62}\x{1A65}-\x{1A6C}\x{1A73}-\x{1A7C}\x{1A7F}\x{1AB0}-\x{1ABD}\x{1ABE}\x{1ABF}-\x{1AC0}\x{1B00}-\x{1B03}\x{1B34}\x{1B36}-\x{1B3A}\x{1B3C}\x{1B42}\x{1B6B}-\x{1B73}\x{1B80}-\x{1B81}\x{1BA2}-\x{1BA5}\x{1BA8}-\x{1BA9}\x{1BAB}-\x{1BAD}\x{1BE6}\x{1BE8}-\x{1BE9}\x{1BED}\x{1BEF}-\x{1BF1}\x{1C2C}-\x{1C33}\x{1C36}-\x{1C37}\x{1CD0}-\x{1CD2}\x{1CD4}-\x{1CE0}\x{1CE2}-\x{1CE8}\x{1CED}\x{1CF4}\x{1CF8}-\x{1CF9}\x{1DC0}-\x{1DF9}\x{1DFB}-\x{1DFF}\x{1FBD}\x{1FBF}-\x{1FC1}\x{1FCD}-\x{1FCF}\x{1FDD}-\x{1FDF}\x{1FED}-\x{1FEF}\x{1FFD}-\x{1FFE}\x{2000}-\x{200A}\x{200B}-\x{200D}\x{200F}\x{2010}-\x{2015}\x{2016}-\x{2017}\x{2018}\x{2019}\x{201A}\x{201B}-\x{201C}\x{201D}\x{201E}\x{201F}\x{2020}-\x{2027}\x{2028}\x{2029}\x{202A}\x{202B}\x{202C}\x{202D}\x{202E}\x{202F}\x{2030}-\x{2034}\x{2035}-\x{2038}\x{2039}\x{203A}\x{203B}-\x{203E}\x{203F}-\x{2040}\x{2041}-\x{2043}\x{2044}\x{2045}\x{2046}\x{2047}-\x{2051}\x{2052}\x{2053}\x{2054}\x{2055}-\x{205E}\x{205F}\x{2060}-\x{2064}\x{2065}\x{2066}\x{2067}\x{2068}\x{2069}\x{206A}-\x{206F}\x{207A}-\x{207B}\x{207C}\x{207D}\x{207E}\x{208A}-\x{208B}\x{208C}\x{208D}\x{208E}\x{20A0}-\x{20BF}\x{20C0}-\x{20CF}\x{20D0}-\x{20DC}\x{20DD}-\x{20E0}\x{20E1}\x{20E2}-\x{20E4}\x{20E5}-\x{20F0}\x{2100}-\x{2101}\x{2103}-\x{2106}\x{2108}-\x{2109}\x{2114}\x{2116}-\x{2117}\x{2118}\x{211E}-\x{2123}\x{2125}\x{2127}\x{2129}\x{212E}\x{213A}-\x{213B}\x{2140}-\x{2144}\x{214A}\x{214B}\x{214C}-\x{214D}\x{2150}-\x{215F}\x{2189}\x{218A}-\x{218B}\x{2190}-\x{2194}\x{2195}-\x{2199}\x{219A}-\x{219B}\x{219C}-\x{219F}\x{21A0}\x{21A1}-\x{21A2}\x{21A3}\x{21A4}-\x{21A5}\x{21A6}\x{21A7}-\x{21AD}\x{21AE}\x{21AF}-\x{21CD}\x{21CE}-\x{21CF}\x{21D0}-\x{21D1}\x{21D2}\x{21D3}\x{21D4}\x{21D5}-\x{21F3}\x{21F4}-\x{2211}\x{2212}\x{2213}\x{2214}-\x{22FF}\x{2300}-\x{2307}\x{2308}\x{2309}\x{230A}\x{230B}\x{230C}-\x{231F}\x{2320}-\x{2321}\x{2322}-\x{2328}\x{2329}\x{232A}\x{232B}-\x{2335}\x{237B}\x{237C}\x{237D}-\x{2394}\x{2396}-\x{239A}\x{239B}-\x{23B3}\x{23B4}-\x{23DB}\x{23DC}-\x{23E1}\x{23E2}-\x{2426}\x{2440}-\x{244A}\x{2460}-\x{2487}\x{24EA}-\x{24FF}\x{2500}-\x{25B6}\x{25B7}\x{25B8}-\x{25C0}\x{25C1}\x{25C2}-\x{25F7}\x{25F8}-\x{25FF}\x{2600}-\x{266E}\x{266F}\x{2670}-\x{26AB}\x{26AD}-\x{2767}\x{2768}\x{2769}\x{276A}\x{276B}\x{276C}\x{276D}\x{276E}\x{276F}\x{2770}\x{2771}\x{2772}\x{2773}\x{2774}\x{2775}\x{2776}-\x{2793}\x{2794}-\x{27BF}\x{27C0}-\x{27C4}\x{27C5}\x{27C6}\x{27C7}-\x{27E5}\x{27E6}\x{27E7}\x{27E8}\x{27E9}\x{27EA}\x{27EB}\x{27EC}\x{27ED}\x{27EE}\x{27EF}\x{27F0}-\x{27FF}\x{2900}-\x{2982}\x{2983}\x{2984}\x{2985}\x{2986}\x{2987}\x{2988}\x{2989}\x{298A}\x{298B}\x{298C}\x{298D}\x{298E}\x{298F}\x{2990}\x{2991}\x{2992}\x{2993}\x{2994}\x{2995}\x{2996}\x{2997}\x{2998}\x{2999}-\x{29D7}\x{29D8}\x{29D9}\x{29DA}\x{29DB}\x{29DC}-\x{29FB}\x{29FC}\x{29FD}\x{29FE}-\x{2AFF}\x{2B00}-\x{2B2F}\x{2B30}-\x{2B44}\x{2B45}-\x{2B46}\x{2B47}-\x{2B4C}\x{2B4D}-\x{2B73}\x{2B76}-\x{2B95}\x{2B97}-\x{2BFF}\x{2CE5}-\x{2CEA}\x{2CEF}-\x{2CF1}\x{2CF9}-\x{2CFC}\x{2CFD}\x{2CFE}-\x{2CFF}\x{2D7F}\x{2DE0}-\x{2DFF}\x{2E00}-\x{2E01}\x{2E02}\x{2E03}\x{2E04}\x{2E05}\x{2E06}-\x{2E08}\x{2E09}\x{2E0A}\x{2E0B}\x{2E0C}\x{2E0D}\x{2E0E}-\x{2E16}\x{2E17}\x{2E18}-\x{2E19}\x{2E1A}\x{2E1B}\x{2E1C}\x{2E1D}\x{2E1E}-\x{2E1F}\x{2E20}\x{2E21}\x{2E22}\x{2E23}\x{2E24}\x{2E25}\x{2E26}\x{2E27}\x{2E28}\x{2E29}\x{2E2A}-\x{2E2E}\x{2E2F}\x{2E30}-\x{2E39}\x{2E3A}-\x{2E3B}\x{2E3C}-\x{2E3F}\x{2E40}\x{2E41}\x{2E42}\x{2E43}-\x{2E4F}\x{2E50}-\x{2E51}\x{2E52}\x{2E80}-\x{2E99}\x{2E9B}-\x{2EF3}\x{2F00}-\x{2FD5}\x{2FF0}-\x{2FFB}\x{3000}\x{3001}-\x{3003}\x{3004}\x{3008}\x{3009}\x{300A}\x{300B}\x{300C}\x{300D}\x{300E}\x{300F}\x{3010}\x{3011}\x{3012}-\x{3013}\x{3014}\x{3015}\x{3016}\x{3017}\x{3018}\x{3019}\x{301A}\x{301B}\x{301C}\x{301D}\x{301E}-\x{301F}\x{3020}\x{302A}-\x{302D}\x{3030}\x{3036}-\x{3037}\x{303D}\x{303E}-\x{303F}\x{3099}-\x{309A}\x{309B}-\x{309C}\x{30A0}\x{30FB}\x{31C0}-\x{31E3}\x{321D}-\x{321E}\x{3250}\x{3251}-\x{325F}\x{327C}-\x{327E}\x{32B1}-\x{32BF}\x{32CC}-\x{32CF}\x{3377}-\x{337A}\x{33DE}-\x{33DF}\x{33FF}\x{4DC0}-\x{4DFF}\x{A490}-\x{A4C6}\x{A60D}-\x{A60F}\x{A66F}\x{A670}-\x{A672}\x{A673}\x{A674}-\x{A67D}\x{A67E}\x{A67F}\x{A69E}-\x{A69F}\x{A6F0}-\x{A6F1}\x{A700}-\x{A716}\x{A717}-\x{A71F}\x{A720}-\x{A721}\x{A788}\x{A802}\x{A806}\x{A80B}\x{A825}-\x{A826}\x{A828}-\x{A82B}\x{A82C}\x{A838}\x{A839}\x{A874}-\x{A877}\x{A8C4}-\x{A8C5}\x{A8E0}-\x{A8F1}\x{A8FF}\x{A926}-\x{A92D}\x{A947}-\x{A951}\x{A980}-\x{A982}\x{A9B3}\x{A9B6}-\x{A9B9}\x{A9BC}-\x{A9BD}\x{A9E5}\x{AA29}-\x{AA2E}\x{AA31}-\x{AA32}\x{AA35}-\x{AA36}\x{AA43}\x{AA4C}\x{AA7C}\x{AAB0}\x{AAB2}-\x{AAB4}\x{AAB7}-\x{AAB8}\x{AABE}-\x{AABF}\x{AAC1}\x{AAEC}-\x{AAED}\x{AAF6}\x{AB6A}-\x{AB6B}\x{ABE5}\x{ABE8}\x{ABED}\x{FB1D}\x{FB1E}\x{FB1F}-\x{FB28}\x{FB29}\x{FB2A}-\x{FB36}\x{FB37}\x{FB38}-\x{FB3C}\x{FB3D}\x{FB3E}\x{FB3F}\x{FB40}-\x{FB41}\x{FB42}\x{FB43}-\x{FB44}\x{FB45}\x{FB46}-\x{FB4F}\x{FB50}-\x{FBB1}\x{FBB2}-\x{FBC1}\x{FBC2}-\x{FBD2}\x{FBD3}-\x{FD3D}\x{FD3E}\x{FD3F}\x{FD40}-\x{FD4F}\x{FD50}-\x{FD8F}\x{FD90}-\x{FD91}\x{FD92}-\x{FDC7}\x{FDC8}-\x{FDCF}\x{FDD0}-\x{FDEF}\x{FDF0}-\x{FDFB}\x{FDFC}\x{FDFD}\x{FDFE}-\x{FDFF}\x{FE00}-\x{FE0F}\x{FE10}-\x{FE16}\x{FE17}\x{FE18}\x{FE19}\x{FE20}-\x{FE2F}\x{FE30}\x{FE31}-\x{FE32}\x{FE33}-\x{FE34}\x{FE35}\x{FE36}\x{FE37}\x{FE38}\x{FE39}\x{FE3A}\x{FE3B}\x{FE3C}\x{FE3D}\x{FE3E}\x{FE3F}\x{FE40}\x{FE41}\x{FE42}\x{FE43}\x{FE44}\x{FE45}-\x{FE46}\x{FE47}\x{FE48}\x{FE49}-\x{FE4C}\x{FE4D}-\x{FE4F}\x{FE50}\x{FE51}\x{FE52}\x{FE54}\x{FE55}\x{FE56}-\x{FE57}\x{FE58}\x{FE59}\x{FE5A}\x{FE5B}\x{FE5C}\x{FE5D}\x{FE5E}\x{FE5F}\x{FE60}-\x{FE61}\x{FE62}\x{FE63}\x{FE64}-\x{FE66}\x{FE68}\x{FE69}\x{FE6A}\x{FE6B}\x{FE70}-\x{FE74}\x{FE75}\x{FE76}-\x{FEFC}\x{FEFD}-\x{FEFE}\x{FEFF}\x{FF01}-\x{FF02}\x{FF03}\x{FF04}\x{FF05}\x{FF06}-\x{FF07}\x{FF08}\x{FF09}\x{FF0A}\x{FF0B}\x{FF0C}\x{FF0D}\x{FF0E}-\x{FF0F}\x{FF1A}\x{FF1B}\x{FF1C}-\x{FF1E}\x{FF1F}-\x{FF20}\x{FF3B}\x{FF3C}\x{FF3D}\x{FF3E}\x{FF3F}\x{FF40}\x{FF5B}\x{FF5C}\x{FF5D}\x{FF5E}\x{FF5F}\x{FF60}\x{FF61}\x{FF62}\x{FF63}\x{FF64}-\x{FF65}\x{FFE0}-\x{FFE1}\x{FFE2}\x{FFE3}\x{FFE4}\x{FFE5}-\x{FFE6}\x{FFE8}\x{FFE9}-\x{FFEC}\x{FFED}-\x{FFEE}\x{FFF0}-\x{FFF8}\x{FFF9}-\x{FFFB}\x{FFFC}-\x{FFFD}\x{FFFE}-\x{FFFF}\x{10101}\x{10140}-\x{10174}\x{10175}-\x{10178}\x{10179}-\x{10189}\x{1018A}-\x{1018B}\x{1018C}\x{10190}-\x{1019C}\x{101A0}\x{101FD}\x{102E0}\x{10376}-\x{1037A}\x{10800}-\x{10805}\x{10806}-\x{10807}\x{10808}\x{10809}\x{1080A}-\x{10835}\x{10836}\x{10837}-\x{10838}\x{10839}-\x{1083B}\x{1083C}\x{1083D}-\x{1083E}\x{1083F}-\x{10855}\x{10856}\x{10857}\x{10858}-\x{1085F}\x{10860}-\x{10876}\x{10877}-\x{10878}\x{10879}-\x{1087F}\x{10880}-\x{1089E}\x{1089F}-\x{108A6}\x{108A7}-\x{108AF}\x{108B0}-\x{108DF}\x{108E0}-\x{108F2}\x{108F3}\x{108F4}-\x{108F5}\x{108F6}-\x{108FA}\x{108FB}-\x{108FF}\x{10900}-\x{10915}\x{10916}-\x{1091B}\x{1091C}-\x{1091E}\x{1091F}\x{10920}-\x{10939}\x{1093A}-\x{1093E}\x{1093F}\x{10940}-\x{1097F}\x{10980}-\x{109B7}\x{109B8}-\x{109BB}\x{109BC}-\x{109BD}\x{109BE}-\x{109BF}\x{109C0}-\x{109CF}\x{109D0}-\x{109D1}\x{109D2}-\x{109FF}\x{10A00}\x{10A01}-\x{10A03}\x{10A04}\x{10A05}-\x{10A06}\x{10A07}-\x{10A0B}\x{10A0C}-\x{10A0F}\x{10A10}-\x{10A13}\x{10A14}\x{10A15}-\x{10A17}\x{10A18}\x{10A19}-\x{10A35}\x{10A36}-\x{10A37}\x{10A38}-\x{10A3A}\x{10A3B}-\x{10A3E}\x{10A3F}\x{10A40}-\x{10A48}\x{10A49}-\x{10A4F}\x{10A50}-\x{10A58}\x{10A59}-\x{10A5F}\x{10A60}-\x{10A7C}\x{10A7D}-\x{10A7E}\x{10A7F}\x{10A80}-\x{10A9C}\x{10A9D}-\x{10A9F}\x{10AA0}-\x{10ABF}\x{10AC0}-\x{10AC7}\x{10AC8}\x{10AC9}-\x{10AE4}\x{10AE5}-\x{10AE6}\x{10AE7}-\x{10AEA}\x{10AEB}-\x{10AEF}\x{10AF0}-\x{10AF6}\x{10AF7}-\x{10AFF}\x{10B00}-\x{10B35}\x{10B36}-\x{10B38}\x{10B39}-\x{10B3F}\x{10B40}-\x{10B55}\x{10B56}-\x{10B57}\x{10B58}-\x{10B5F}\x{10B60}-\x{10B72}\x{10B73}-\x{10B77}\x{10B78}-\x{10B7F}\x{10B80}-\x{10B91}\x{10B92}-\x{10B98}\x{10B99}-\x{10B9C}\x{10B9D}-\x{10BA8}\x{10BA9}-\x{10BAF}\x{10BB0}-\x{10BFF}\x{10C00}-\x{10C48}\x{10C49}-\x{10C7F}\x{10C80}-\x{10CB2}\x{10CB3}-\x{10CBF}\x{10CC0}-\x{10CF2}\x{10CF3}-\x{10CF9}\x{10CFA}-\x{10CFF}\x{10D00}-\x{10D23}\x{10D24}-\x{10D27}\x{10D28}-\x{10D2F}\x{10D30}-\x{10D39}\x{10D3A}-\x{10D3F}\x{10D40}-\x{10E5F}\x{10E60}-\x{10E7E}\x{10E7F}\x{10E80}-\x{10EA9}\x{10EAA}\x{10EAB}-\x{10EAC}\x{10EAD}\x{10EAE}-\x{10EAF}\x{10EB0}-\x{10EB1}\x{10EB2}-\x{10EFF}\x{10F00}-\x{10F1C}\x{10F1D}-\x{10F26}\x{10F27}\x{10F28}-\x{10F2F}\x{10F30}-\x{10F45}\x{10F46}-\x{10F50}\x{10F51}-\x{10F54}\x{10F55}-\x{10F59}\x{10F5A}-\x{10F6F}\x{10F70}-\x{10FAF}\x{10FB0}-\x{10FC4}\x{10FC5}-\x{10FCB}\x{10FCC}-\x{10FDF}\x{10FE0}-\x{10FF6}\x{10FF7}-\x{10FFF}\x{11001}\x{11038}-\x{11046}\x{11052}-\x{11065}\x{1107F}-\x{11081}\x{110B3}-\x{110B6}\x{110B9}-\x{110BA}\x{11100}-\x{11102}\x{11127}-\x{1112B}\x{1112D}-\x{11134}\x{11173}\x{11180}-\x{11181}\x{111B6}-\x{111BE}\x{111C9}-\x{111CC}\x{111CF}\x{1122F}-\x{11231}\x{11234}\x{11236}-\x{11237}\x{1123E}\x{112DF}\x{112E3}-\x{112EA}\x{11300}-\x{11301}\x{1133B}-\x{1133C}\x{11340}\x{11366}-\x{1136C}\x{11370}-\x{11374}\x{11438}-\x{1143F}\x{11442}-\x{11444}\x{11446}\x{1145E}\x{114B3}-\x{114B8}\x{114BA}\x{114BF}-\x{114C0}\x{114C2}-\x{114C3}\x{115B2}-\x{115B5}\x{115BC}-\x{115BD}\x{115BF}-\x{115C0}\x{115DC}-\x{115DD}\x{11633}-\x{1163A}\x{1163D}\x{1163F}-\x{11640}\x{11660}-\x{1166C}\x{116AB}\x{116AD}\x{116B0}-\x{116B5}\x{116B7}\x{1171D}-\x{1171F}\x{11722}-\x{11725}\x{11727}-\x{1172B}\x{1182F}-\x{11837}\x{11839}-\x{1183A}\x{1193B}-\x{1193C}\x{1193E}\x{11943}\x{119D4}-\x{119D7}\x{119DA}-\x{119DB}\x{119E0}\x{11A01}-\x{11A06}\x{11A09}-\x{11A0A}\x{11A33}-\x{11A38}\x{11A3B}-\x{11A3E}\x{11A47}\x{11A51}-\x{11A56}\x{11A59}-\x{11A5B}\x{11A8A}-\x{11A96}\x{11A98}-\x{11A99}\x{11C30}-\x{11C36}\x{11C38}-\x{11C3D}\x{11C92}-\x{11CA7}\x{11CAA}-\x{11CB0}\x{11CB2}-\x{11CB3}\x{11CB5}-\x{11CB6}\x{11D31}-\x{11D36}\x{11D3A}\x{11D3C}-\x{11D3D}\x{11D3F}-\x{11D45}\x{11D47}\x{11D90}-\x{11D91}\x{11D95}\x{11D97}\x{11EF3}-\x{11EF4}\x{11FD5}-\x{11FDC}\x{11FDD}-\x{11FE0}\x{11FE1}-\x{11FF1}\x{16AF0}-\x{16AF4}\x{16B30}-\x{16B36}\x{16F4F}\x{16F8F}-\x{16F92}\x{16FE2}\x{16FE4}\x{1BC9D}-\x{1BC9E}\x{1BCA0}-\x{1BCA3}\x{1D167}-\x{1D169}\x{1D173}-\x{1D17A}\x{1D17B}-\x{1D182}\x{1D185}-\x{1D18B}\x{1D1AA}-\x{1D1AD}\x{1D200}-\x{1D241}\x{1D242}-\x{1D244}\x{1D245}\x{1D300}-\x{1D356}\x{1D6DB}\x{1D715}\x{1D74F}\x{1D789}\x{1D7C3}\x{1DA00}-\x{1DA36}\x{1DA3B}-\x{1DA6C}\x{1DA75}\x{1DA84}\x{1DA9B}-\x{1DA9F}\x{1DAA1}-\x{1DAAF}\x{1E000}-\x{1E006}\x{1E008}-\x{1E018}\x{1E01B}-\x{1E021}\x{1E023}-\x{1E024}\x{1E026}-\x{1E02A}\x{1E130}-\x{1E136}\x{1E2EC}-\x{1E2EF}\x{1E2FF}\x{1E800}-\x{1E8C4}\x{1E8C5}-\x{1E8C6}\x{1E8C7}-\x{1E8CF}\x{1E8D0}-\x{1E8D6}\x{1E8D7}-\x{1E8FF}\x{1E900}-\x{1E943}\x{1E944}-\x{1E94A}\x{1E94B}\x{1E94C}-\x{1E94F}\x{1E950}-\x{1E959}\x{1E95A}-\x{1E95D}\x{1E95E}-\x{1E95F}\x{1E960}-\x{1EC6F}\x{1EC70}\x{1EC71}-\x{1ECAB}\x{1ECAC}\x{1ECAD}-\x{1ECAF}\x{1ECB0}\x{1ECB1}-\x{1ECB4}\x{1ECB5}-\x{1ECBF}\x{1ECC0}-\x{1ECFF}\x{1ED00}\x{1ED01}-\x{1ED2D}\x{1ED2E}\x{1ED2F}-\x{1ED3D}\x{1ED3E}-\x{1ED4F}\x{1ED50}-\x{1EDFF}\x{1EE00}-\x{1EE03}\x{1EE04}\x{1EE05}-\x{1EE1F}\x{1EE20}\x{1EE21}-\x{1EE22}\x{1EE23}\x{1EE24}\x{1EE25}-\x{1EE26}\x{1EE27}\x{1EE28}\x{1EE29}-\x{1EE32}\x{1EE33}\x{1EE34}-\x{1EE37}\x{1EE38}\x{1EE39}\x{1EE3A}\x{1EE3B}\x{1EE3C}-\x{1EE41}\x{1EE42}\x{1EE43}-\x{1EE46}\x{1EE47}\x{1EE48}\x{1EE49}\x{1EE4A}\x{1EE4B}\x{1EE4C}\x{1EE4D}-\x{1EE4F}\x{1EE50}\x{1EE51}-\x{1EE52}\x{1EE53}\x{1EE54}\x{1EE55}-\x{1EE56}\x{1EE57}\x{1EE58}\x{1EE59}\x{1EE5A}\x{1EE5B}\x{1EE5C}\x{1EE5D}\x{1EE5E}\x{1EE5F}\x{1EE60}\x{1EE61}-\x{1EE62}\x{1EE63}\x{1EE64}\x{1EE65}-\x{1EE66}\x{1EE67}-\x{1EE6A}\x{1EE6B}\x{1EE6C}-\x{1EE72}\x{1EE73}\x{1EE74}-\x{1EE77}\x{1EE78}\x{1EE79}-\x{1EE7C}\x{1EE7D}\x{1EE7E}\x{1EE7F}\x{1EE80}-\x{1EE89}\x{1EE8A}\x{1EE8B}-\x{1EE9B}\x{1EE9C}-\x{1EEA0}\x{1EEA1}-\x{1EEA3}\x{1EEA4}\x{1EEA5}-\x{1EEA9}\x{1EEAA}\x{1EEAB}-\x{1EEBB}\x{1EEBC}-\x{1EEEF}\x{1EEF0}-\x{1EEF1}\x{1EEF2}-\x{1EEFF}\x{1EF00}-\x{1EFFF}\x{1F000}-\x{1F02B}\x{1F030}-\x{1F093}\x{1F0A0}-\x{1F0AE}\x{1F0B1}-\x{1F0BF}\x{1F0C1}-\x{1F0CF}\x{1F0D1}-\x{1F0F5}\x{1F10B}-\x{1F10C}\x{1F10D}-\x{1F10F}\x{1F12F}\x{1F16A}-\x{1F16F}\x{1F1AD}\x{1F260}-\x{1F265}\x{1F300}-\x{1F3FA}\x{1F3FB}-\x{1F3FF}\x{1F400}-\x{1F6D7}\x{1F6E0}-\x{1F6EC}\x{1F6F0}-\x{1F6FC}\x{1F700}-\x{1F773}\x{1F780}-\x{1F7D8}\x{1F7E0}-\x{1F7EB}\x{1F800}-\x{1F80B}\x{1F810}-\x{1F847}\x{1F850}-\x{1F859}\x{1F860}-\x{1F887}\x{1F890}-\x{1F8AD}\x{1F8B0}-\x{1F8B1}\x{1F900}-\x{1F978}\x{1F97A}-\x{1F9CB}\x{1F9CD}-\x{1FA53}\x{1FA60}-\x{1FA6D}\x{1FA70}-\x{1FA74}\x{1FA78}-\x{1FA7A}\x{1FA80}-\x{1FA86}\x{1FA90}-\x{1FAA8}\x{1FAB0}-\x{1FAB6}\x{1FAC0}-\x{1FAC2}\x{1FAD0}-\x{1FAD6}\x{1FB00}-\x{1FB92}\x{1FB94}-\x{1FBCA}\x{1FFFE}-\x{1FFFF}\x{2FFFE}-\x{2FFFF}\x{3FFFE}-\x{3FFFF}\x{4FFFE}-\x{4FFFF}\x{5FFFE}-\x{5FFFF}\x{6FFFE}-\x{6FFFF}\x{7FFFE}-\x{7FFFF}\x{8FFFE}-\x{8FFFF}\x{9FFFE}-\x{9FFFF}\x{AFFFE}-\x{AFFFF}\x{BFFFE}-\x{BFFFF}\x{CFFFE}-\x{CFFFF}\x{DFFFE}-\x{E0000}\x{E0001}\x{E0002}-\x{E001F}\x{E0020}-\x{E007F}\x{E0080}-\x{E00FF}\x{E0100}-\x{E01EF}\x{E01F0}-\x{E0FFF}\x{EFFFE}-\x{EFFFF}\x{FFFFE}-\x{FFFFF}\x{10FFFE}-\x{10FFFF}][\x{0300}-\x{036F}\x{0483}-\x{0487}\x{0488}-\x{0489}\x{0591}-\x{05BD}\x{05BF}\x{05C1}-\x{05C2}\x{05C4}-\x{05C5}\x{05C7}\x{0610}-\x{061A}\x{064B}-\x{065F}\x{0670}\x{06D6}-\x{06DC}\x{06DF}-\x{06E4}\x{06E7}-\x{06E8}\x{06EA}-\x{06ED}\x{0711}\x{0730}-\x{074A}\x{07A6}-\x{07B0}\x{07EB}-\x{07F3}\x{07FD}\x{0816}-\x{0819}\x{081B}-\x{0823}\x{0825}-\x{0827}\x{0829}-\x{082D}\x{0859}-\x{085B}\x{08D3}-\x{08E1}\x{08E3}-\x{0902}\x{093A}\x{093C}\x{0941}-\x{0948}\x{094D}\x{0951}-\x{0957}\x{0962}-\x{0963}\x{0981}\x{09BC}\x{09C1}-\x{09C4}\x{09CD}\x{09E2}-\x{09E3}\x{09FE}\x{0A01}-\x{0A02}\x{0A3C}\x{0A41}-\x{0A42}\x{0A47}-\x{0A48}\x{0A4B}-\x{0A4D}\x{0A51}\x{0A70}-\x{0A71}\x{0A75}\x{0A81}-\x{0A82}\x{0ABC}\x{0AC1}-\x{0AC5}\x{0AC7}-\x{0AC8}\x{0ACD}\x{0AE2}-\x{0AE3}\x{0AFA}-\x{0AFF}\x{0B01}\x{0B3C}\x{0B3F}\x{0B41}-\x{0B44}\x{0B4D}\x{0B55}-\x{0B56}\x{0B62}-\x{0B63}\x{0B82}\x{0BC0}\x{0BCD}\x{0C00}\x{0C04}\x{0C3E}-\x{0C40}\x{0C46}-\x{0C48}\x{0C4A}-\x{0C4D}\x{0C55}-\x{0C56}\x{0C62}-\x{0C63}\x{0C81}\x{0CBC}\x{0CCC}-\x{0CCD}\x{0CE2}-\x{0CE3}\x{0D00}-\x{0D01}\x{0D3B}-\x{0D3C}\x{0D41}-\x{0D44}\x{0D4D}\x{0D62}-\x{0D63}\x{0D81}\x{0DCA}\x{0DD2}-\x{0DD4}\x{0DD6}\x{0E31}\x{0E34}-\x{0E3A}\x{0E47}-\x{0E4E}\x{0EB1}\x{0EB4}-\x{0EBC}\x{0EC8}-\x{0ECD}\x{0F18}-\x{0F19}\x{0F35}\x{0F37}\x{0F39}\x{0F71}-\x{0F7E}\x{0F80}-\x{0F84}\x{0F86}-\x{0F87}\x{0F8D}-\x{0F97}\x{0F99}-\x{0FBC}\x{0FC6}\x{102D}-\x{1030}\x{1032}-\x{1037}\x{1039}-\x{103A}\x{103D}-\x{103E}\x{1058}-\x{1059}\x{105E}-\x{1060}\x{1071}-\x{1074}\x{1082}\x{1085}-\x{1086}\x{108D}\x{109D}\x{135D}-\x{135F}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}-\x{1753}\x{1772}-\x{1773}\x{17B4}-\x{17B5}\x{17B7}-\x{17BD}\x{17C6}\x{17C9}-\x{17D3}\x{17DD}\x{180B}-\x{180D}\x{1885}-\x{1886}\x{18A9}\x{1920}-\x{1922}\x{1927}-\x{1928}\x{1932}\x{1939}-\x{193B}\x{1A17}-\x{1A18}\x{1A1B}\x{1A56}\x{1A58}-\x{1A5E}\x{1A60}\x{1A62}\x{1A65}-\x{1A6C}\x{1A73}-\x{1A7C}\x{1A7F}\x{1AB0}-\x{1ABD}\x{1ABE}\x{1ABF}-\x{1AC0}\x{1B00}-\x{1B03}\x{1B34}\x{1B36}-\x{1B3A}\x{1B3C}\x{1B42}\x{1B6B}-\x{1B73}\x{1B80}-\x{1B81}\x{1BA2}-\x{1BA5}\x{1BA8}-\x{1BA9}\x{1BAB}-\x{1BAD}\x{1BE6}\x{1BE8}-\x{1BE9}\x{1BED}\x{1BEF}-\x{1BF1}\x{1C2C}-\x{1C33}\x{1C36}-\x{1C37}\x{1CD0}-\x{1CD2}\x{1CD4}-\x{1CE0}\x{1CE2}-\x{1CE8}\x{1CED}\x{1CF4}\x{1CF8}-\x{1CF9}\x{1DC0}-\x{1DF9}\x{1DFB}-\x{1DFF}\x{20D0}-\x{20DC}\x{20DD}-\x{20E0}\x{20E1}\x{20E2}-\x{20E4}\x{20E5}-\x{20F0}\x{2CEF}-\x{2CF1}\x{2D7F}\x{2DE0}-\x{2DFF}\x{302A}-\x{302D}\x{3099}-\x{309A}\x{A66F}\x{A670}-\x{A672}\x{A674}-\x{A67D}\x{A69E}-\x{A69F}\x{A6F0}-\x{A6F1}\x{A802}\x{A806}\x{A80B}\x{A825}-\x{A826}\x{A82C}\x{A8C4}-\x{A8C5}\x{A8E0}-\x{A8F1}\x{A8FF}\x{A926}-\x{A92D}\x{A947}-\x{A951}\x{A980}-\x{A982}\x{A9B3}\x{A9B6}-\x{A9B9}\x{A9BC}-\x{A9BD}\x{A9E5}\x{AA29}-\x{AA2E}\x{AA31}-\x{AA32}\x{AA35}-\x{AA36}\x{AA43}\x{AA4C}\x{AA7C}\x{AAB0}\x{AAB2}-\x{AAB4}\x{AAB7}-\x{AAB8}\x{AABE}-\x{AABF}\x{AAC1}\x{AAEC}-\x{AAED}\x{AAF6}\x{ABE5}\x{ABE8}\x{ABED}\x{FB1E}\x{FE00}-\x{FE0F}\x{FE20}-\x{FE2F}\x{101FD}\x{102E0}\x{10376}-\x{1037A}\x{10A01}-\x{10A03}\x{10A05}-\x{10A06}\x{10A0C}-\x{10A0F}\x{10A38}-\x{10A3A}\x{10A3F}\x{10AE5}-\x{10AE6}\x{10D24}-\x{10D27}\x{10EAB}-\x{10EAC}\x{10F46}-\x{10F50}\x{11001}\x{11038}-\x{11046}\x{1107F}-\x{11081}\x{110B3}-\x{110B6}\x{110B9}-\x{110BA}\x{11100}-\x{11102}\x{11127}-\x{1112B}\x{1112D}-\x{11134}\x{11173}\x{11180}-\x{11181}\x{111B6}-\x{111BE}\x{111C9}-\x{111CC}\x{111CF}\x{1122F}-\x{11231}\x{11234}\x{11236}-\x{11237}\x{1123E}\x{112DF}\x{112E3}-\x{112EA}\x{11300}-\x{11301}\x{1133B}-\x{1133C}\x{11340}\x{11366}-\x{1136C}\x{11370}-\x{11374}\x{11438}-\x{1143F}\x{11442}-\x{11444}\x{11446}\x{1145E}\x{114B3}-\x{114B8}\x{114BA}\x{114BF}-\x{114C0}\x{114C2}-\x{114C3}\x{115B2}-\x{115B5}\x{115BC}-\x{115BD}\x{115BF}-\x{115C0}\x{115DC}-\x{115DD}\x{11633}-\x{1163A}\x{1163D}\x{1163F}-\x{11640}\x{116AB}\x{116AD}\x{116B0}-\x{116B5}\x{116B7}\x{1171D}-\x{1171F}\x{11722}-\x{11725}\x{11727}-\x{1172B}\x{1182F}-\x{11837}\x{11839}-\x{1183A}\x{1193B}-\x{1193C}\x{1193E}\x{11943}\x{119D4}-\x{119D7}\x{119DA}-\x{119DB}\x{119E0}\x{11A01}-\x{11A06}\x{11A09}-\x{11A0A}\x{11A33}-\x{11A38}\x{11A3B}-\x{11A3E}\x{11A47}\x{11A51}-\x{11A56}\x{11A59}-\x{11A5B}\x{11A8A}-\x{11A96}\x{11A98}-\x{11A99}\x{11C30}-\x{11C36}\x{11C38}-\x{11C3D}\x{11C92}-\x{11CA7}\x{11CAA}-\x{11CB0}\x{11CB2}-\x{11CB3}\x{11CB5}-\x{11CB6}\x{11D31}-\x{11D36}\x{11D3A}\x{11D3C}-\x{11D3D}\x{11D3F}-\x{11D45}\x{11D47}\x{11D90}-\x{11D91}\x{11D95}\x{11D97}\x{11EF3}-\x{11EF4}\x{16AF0}-\x{16AF4}\x{16B30}-\x{16B36}\x{16F4F}\x{16F8F}-\x{16F92}\x{16FE4}\x{1BC9D}-\x{1BC9E}\x{1D167}-\x{1D169}\x{1D17B}-\x{1D182}\x{1D185}-\x{1D18B}\x{1D1AA}-\x{1D1AD}\x{1D242}-\x{1D244}\x{1DA00}-\x{1DA36}\x{1DA3B}-\x{1DA6C}\x{1DA75}\x{1DA84}\x{1DA9B}-\x{1DA9F}\x{1DAA1}-\x{1DAAF}\x{1E000}-\x{1E006}\x{1E008}-\x{1E018}\x{1E01B}-\x{1E021}\x{1E023}-\x{1E024}\x{1E026}-\x{1E02A}\x{1E130}-\x{1E136}\x{1E2EC}-\x{1E2EF}\x{1E8D0}-\x{1E8D6}\x{1E944}-\x{1E94A}\x{E0100}-\x{E01EF}]*$/u'; - - const ZWNJ = '/([\x{A872}\x{10ACD}\x{10AD7}\x{10D00}\x{10FCB}\x{0620}\x{0626}\x{0628}\x{062A}-\x{062E}\x{0633}-\x{063F}\x{0641}-\x{0647}\x{0649}-\x{064A}\x{066E}-\x{066F}\x{0678}-\x{0687}\x{069A}-\x{06BF}\x{06C1}-\x{06C2}\x{06CC}\x{06CE}\x{06D0}-\x{06D1}\x{06FA}-\x{06FC}\x{06FF}\x{0712}-\x{0714}\x{071A}-\x{071D}\x{071F}-\x{0727}\x{0729}\x{072B}\x{072D}-\x{072E}\x{074E}-\x{0758}\x{075C}-\x{076A}\x{076D}-\x{0770}\x{0772}\x{0775}-\x{0777}\x{077A}-\x{077F}\x{07CA}-\x{07EA}\x{0841}-\x{0845}\x{0848}\x{084A}-\x{0853}\x{0855}\x{0860}\x{0862}-\x{0865}\x{0868}\x{08A0}-\x{08A9}\x{08AF}-\x{08B0}\x{08B3}-\x{08B4}\x{08B6}-\x{08B8}\x{08BA}-\x{08C7}\x{1807}\x{1820}-\x{1842}\x{1843}\x{1844}-\x{1878}\x{1887}-\x{18A8}\x{18AA}\x{A840}-\x{A871}\x{10AC0}-\x{10AC4}\x{10AD3}-\x{10AD6}\x{10AD8}-\x{10ADC}\x{10ADE}-\x{10AE0}\x{10AEB}-\x{10AEE}\x{10B80}\x{10B82}\x{10B86}-\x{10B88}\x{10B8A}-\x{10B8B}\x{10B8D}\x{10B90}\x{10BAD}-\x{10BAE}\x{10D01}-\x{10D21}\x{10D23}\x{10F30}-\x{10F32}\x{10F34}-\x{10F44}\x{10F51}-\x{10F53}\x{10FB0}\x{10FB2}-\x{10FB3}\x{10FB8}\x{10FBB}-\x{10FBC}\x{10FBE}-\x{10FBF}\x{10FC1}\x{10FC4}\x{10FCA}\x{1E900}-\x{1E943}][\x{00AD}\x{0300}-\x{036F}\x{0483}-\x{0487}\x{0488}-\x{0489}\x{0591}-\x{05BD}\x{05BF}\x{05C1}-\x{05C2}\x{05C4}-\x{05C5}\x{05C7}\x{0610}-\x{061A}\x{061C}\x{064B}-\x{065F}\x{0670}\x{06D6}-\x{06DC}\x{06DF}-\x{06E4}\x{06E7}-\x{06E8}\x{06EA}-\x{06ED}\x{070F}\x{0711}\x{0730}-\x{074A}\x{07A6}-\x{07B0}\x{07EB}-\x{07F3}\x{07FD}\x{0816}-\x{0819}\x{081B}-\x{0823}\x{0825}-\x{0827}\x{0829}-\x{082D}\x{0859}-\x{085B}\x{08D3}-\x{08E1}\x{08E3}-\x{0902}\x{093A}\x{093C}\x{0941}-\x{0948}\x{094D}\x{0951}-\x{0957}\x{0962}-\x{0963}\x{0981}\x{09BC}\x{09C1}-\x{09C4}\x{09CD}\x{09E2}-\x{09E3}\x{09FE}\x{0A01}-\x{0A02}\x{0A3C}\x{0A41}-\x{0A42}\x{0A47}-\x{0A48}\x{0A4B}-\x{0A4D}\x{0A51}\x{0A70}-\x{0A71}\x{0A75}\x{0A81}-\x{0A82}\x{0ABC}\x{0AC1}-\x{0AC5}\x{0AC7}-\x{0AC8}\x{0ACD}\x{0AE2}-\x{0AE3}\x{0AFA}-\x{0AFF}\x{0B01}\x{0B3C}\x{0B3F}\x{0B41}-\x{0B44}\x{0B4D}\x{0B55}-\x{0B56}\x{0B62}-\x{0B63}\x{0B82}\x{0BC0}\x{0BCD}\x{0C00}\x{0C04}\x{0C3E}-\x{0C40}\x{0C46}-\x{0C48}\x{0C4A}-\x{0C4D}\x{0C55}-\x{0C56}\x{0C62}-\x{0C63}\x{0C81}\x{0CBC}\x{0CBF}\x{0CC6}\x{0CCC}-\x{0CCD}\x{0CE2}-\x{0CE3}\x{0D00}-\x{0D01}\x{0D3B}-\x{0D3C}\x{0D41}-\x{0D44}\x{0D4D}\x{0D62}-\x{0D63}\x{0D81}\x{0DCA}\x{0DD2}-\x{0DD4}\x{0DD6}\x{0E31}\x{0E34}-\x{0E3A}\x{0E47}-\x{0E4E}\x{0EB1}\x{0EB4}-\x{0EBC}\x{0EC8}-\x{0ECD}\x{0F18}-\x{0F19}\x{0F35}\x{0F37}\x{0F39}\x{0F71}-\x{0F7E}\x{0F80}-\x{0F84}\x{0F86}-\x{0F87}\x{0F8D}-\x{0F97}\x{0F99}-\x{0FBC}\x{0FC6}\x{102D}-\x{1030}\x{1032}-\x{1037}\x{1039}-\x{103A}\x{103D}-\x{103E}\x{1058}-\x{1059}\x{105E}-\x{1060}\x{1071}-\x{1074}\x{1082}\x{1085}-\x{1086}\x{108D}\x{109D}\x{135D}-\x{135F}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}-\x{1753}\x{1772}-\x{1773}\x{17B4}-\x{17B5}\x{17B7}-\x{17BD}\x{17C6}\x{17C9}-\x{17D3}\x{17DD}\x{180B}-\x{180D}\x{1885}-\x{1886}\x{18A9}\x{1920}-\x{1922}\x{1927}-\x{1928}\x{1932}\x{1939}-\x{193B}\x{1A17}-\x{1A18}\x{1A1B}\x{1A56}\x{1A58}-\x{1A5E}\x{1A60}\x{1A62}\x{1A65}-\x{1A6C}\x{1A73}-\x{1A7C}\x{1A7F}\x{1AB0}-\x{1ABD}\x{1ABE}\x{1ABF}-\x{1AC0}\x{1B00}-\x{1B03}\x{1B34}\x{1B36}-\x{1B3A}\x{1B3C}\x{1B42}\x{1B6B}-\x{1B73}\x{1B80}-\x{1B81}\x{1BA2}-\x{1BA5}\x{1BA8}-\x{1BA9}\x{1BAB}-\x{1BAD}\x{1BE6}\x{1BE8}-\x{1BE9}\x{1BED}\x{1BEF}-\x{1BF1}\x{1C2C}-\x{1C33}\x{1C36}-\x{1C37}\x{1CD0}-\x{1CD2}\x{1CD4}-\x{1CE0}\x{1CE2}-\x{1CE8}\x{1CED}\x{1CF4}\x{1CF8}-\x{1CF9}\x{1DC0}-\x{1DF9}\x{1DFB}-\x{1DFF}\x{200B}\x{200E}-\x{200F}\x{202A}-\x{202E}\x{2060}-\x{2064}\x{206A}-\x{206F}\x{20D0}-\x{20DC}\x{20DD}-\x{20E0}\x{20E1}\x{20E2}-\x{20E4}\x{20E5}-\x{20F0}\x{2CEF}-\x{2CF1}\x{2D7F}\x{2DE0}-\x{2DFF}\x{302A}-\x{302D}\x{3099}-\x{309A}\x{A66F}\x{A670}-\x{A672}\x{A674}-\x{A67D}\x{A69E}-\x{A69F}\x{A6F0}-\x{A6F1}\x{A802}\x{A806}\x{A80B}\x{A825}-\x{A826}\x{A82C}\x{A8C4}-\x{A8C5}\x{A8E0}-\x{A8F1}\x{A8FF}\x{A926}-\x{A92D}\x{A947}-\x{A951}\x{A980}-\x{A982}\x{A9B3}\x{A9B6}-\x{A9B9}\x{A9BC}-\x{A9BD}\x{A9E5}\x{AA29}-\x{AA2E}\x{AA31}-\x{AA32}\x{AA35}-\x{AA36}\x{AA43}\x{AA4C}\x{AA7C}\x{AAB0}\x{AAB2}-\x{AAB4}\x{AAB7}-\x{AAB8}\x{AABE}-\x{AABF}\x{AAC1}\x{AAEC}-\x{AAED}\x{AAF6}\x{ABE5}\x{ABE8}\x{ABED}\x{FB1E}\x{FE00}-\x{FE0F}\x{FE20}-\x{FE2F}\x{FEFF}\x{FFF9}-\x{FFFB}\x{101FD}\x{102E0}\x{10376}-\x{1037A}\x{10A01}-\x{10A03}\x{10A05}-\x{10A06}\x{10A0C}-\x{10A0F}\x{10A38}-\x{10A3A}\x{10A3F}\x{10AE5}-\x{10AE6}\x{10D24}-\x{10D27}\x{10EAB}-\x{10EAC}\x{10F46}-\x{10F50}\x{11001}\x{11038}-\x{11046}\x{1107F}-\x{11081}\x{110B3}-\x{110B6}\x{110B9}-\x{110BA}\x{11100}-\x{11102}\x{11127}-\x{1112B}\x{1112D}-\x{11134}\x{11173}\x{11180}-\x{11181}\x{111B6}-\x{111BE}\x{111C9}-\x{111CC}\x{111CF}\x{1122F}-\x{11231}\x{11234}\x{11236}-\x{11237}\x{1123E}\x{112DF}\x{112E3}-\x{112EA}\x{11300}-\x{11301}\x{1133B}-\x{1133C}\x{11340}\x{11366}-\x{1136C}\x{11370}-\x{11374}\x{11438}-\x{1143F}\x{11442}-\x{11444}\x{11446}\x{1145E}\x{114B3}-\x{114B8}\x{114BA}\x{114BF}-\x{114C0}\x{114C2}-\x{114C3}\x{115B2}-\x{115B5}\x{115BC}-\x{115BD}\x{115BF}-\x{115C0}\x{115DC}-\x{115DD}\x{11633}-\x{1163A}\x{1163D}\x{1163F}-\x{11640}\x{116AB}\x{116AD}\x{116B0}-\x{116B5}\x{116B7}\x{1171D}-\x{1171F}\x{11722}-\x{11725}\x{11727}-\x{1172B}\x{1182F}-\x{11837}\x{11839}-\x{1183A}\x{1193B}-\x{1193C}\x{1193E}\x{11943}\x{119D4}-\x{119D7}\x{119DA}-\x{119DB}\x{119E0}\x{11A01}-\x{11A0A}\x{11A33}-\x{11A38}\x{11A3B}-\x{11A3E}\x{11A47}\x{11A51}-\x{11A56}\x{11A59}-\x{11A5B}\x{11A8A}-\x{11A96}\x{11A98}-\x{11A99}\x{11C30}-\x{11C36}\x{11C38}-\x{11C3D}\x{11C3F}\x{11C92}-\x{11CA7}\x{11CAA}-\x{11CB0}\x{11CB2}-\x{11CB3}\x{11CB5}-\x{11CB6}\x{11D31}-\x{11D36}\x{11D3A}\x{11D3C}-\x{11D3D}\x{11D3F}-\x{11D45}\x{11D47}\x{11D90}-\x{11D91}\x{11D95}\x{11D97}\x{11EF3}-\x{11EF4}\x{13430}-\x{13438}\x{16AF0}-\x{16AF4}\x{16B30}-\x{16B36}\x{16F4F}\x{16F8F}-\x{16F92}\x{16FE4}\x{1BC9D}-\x{1BC9E}\x{1BCA0}-\x{1BCA3}\x{1D167}-\x{1D169}\x{1D173}-\x{1D17A}\x{1D17B}-\x{1D182}\x{1D185}-\x{1D18B}\x{1D1AA}-\x{1D1AD}\x{1D242}-\x{1D244}\x{1DA00}-\x{1DA36}\x{1DA3B}-\x{1DA6C}\x{1DA75}\x{1DA84}\x{1DA9B}-\x{1DA9F}\x{1DAA1}-\x{1DAAF}\x{1E000}-\x{1E006}\x{1E008}-\x{1E018}\x{1E01B}-\x{1E021}\x{1E023}-\x{1E024}\x{1E026}-\x{1E02A}\x{1E130}-\x{1E136}\x{1E2EC}-\x{1E2EF}\x{1E8D0}-\x{1E8D6}\x{1E944}-\x{1E94A}\x{1E94B}\x{E0001}\x{E0020}-\x{E007F}\x{E0100}-\x{E01EF}]*\x{200C}[\x{00AD}\x{0300}-\x{036F}\x{0483}-\x{0487}\x{0488}-\x{0489}\x{0591}-\x{05BD}\x{05BF}\x{05C1}-\x{05C2}\x{05C4}-\x{05C5}\x{05C7}\x{0610}-\x{061A}\x{061C}\x{064B}-\x{065F}\x{0670}\x{06D6}-\x{06DC}\x{06DF}-\x{06E4}\x{06E7}-\x{06E8}\x{06EA}-\x{06ED}\x{070F}\x{0711}\x{0730}-\x{074A}\x{07A6}-\x{07B0}\x{07EB}-\x{07F3}\x{07FD}\x{0816}-\x{0819}\x{081B}-\x{0823}\x{0825}-\x{0827}\x{0829}-\x{082D}\x{0859}-\x{085B}\x{08D3}-\x{08E1}\x{08E3}-\x{0902}\x{093A}\x{093C}\x{0941}-\x{0948}\x{094D}\x{0951}-\x{0957}\x{0962}-\x{0963}\x{0981}\x{09BC}\x{09C1}-\x{09C4}\x{09CD}\x{09E2}-\x{09E3}\x{09FE}\x{0A01}-\x{0A02}\x{0A3C}\x{0A41}-\x{0A42}\x{0A47}-\x{0A48}\x{0A4B}-\x{0A4D}\x{0A51}\x{0A70}-\x{0A71}\x{0A75}\x{0A81}-\x{0A82}\x{0ABC}\x{0AC1}-\x{0AC5}\x{0AC7}-\x{0AC8}\x{0ACD}\x{0AE2}-\x{0AE3}\x{0AFA}-\x{0AFF}\x{0B01}\x{0B3C}\x{0B3F}\x{0B41}-\x{0B44}\x{0B4D}\x{0B55}-\x{0B56}\x{0B62}-\x{0B63}\x{0B82}\x{0BC0}\x{0BCD}\x{0C00}\x{0C04}\x{0C3E}-\x{0C40}\x{0C46}-\x{0C48}\x{0C4A}-\x{0C4D}\x{0C55}-\x{0C56}\x{0C62}-\x{0C63}\x{0C81}\x{0CBC}\x{0CBF}\x{0CC6}\x{0CCC}-\x{0CCD}\x{0CE2}-\x{0CE3}\x{0D00}-\x{0D01}\x{0D3B}-\x{0D3C}\x{0D41}-\x{0D44}\x{0D4D}\x{0D62}-\x{0D63}\x{0D81}\x{0DCA}\x{0DD2}-\x{0DD4}\x{0DD6}\x{0E31}\x{0E34}-\x{0E3A}\x{0E47}-\x{0E4E}\x{0EB1}\x{0EB4}-\x{0EBC}\x{0EC8}-\x{0ECD}\x{0F18}-\x{0F19}\x{0F35}\x{0F37}\x{0F39}\x{0F71}-\x{0F7E}\x{0F80}-\x{0F84}\x{0F86}-\x{0F87}\x{0F8D}-\x{0F97}\x{0F99}-\x{0FBC}\x{0FC6}\x{102D}-\x{1030}\x{1032}-\x{1037}\x{1039}-\x{103A}\x{103D}-\x{103E}\x{1058}-\x{1059}\x{105E}-\x{1060}\x{1071}-\x{1074}\x{1082}\x{1085}-\x{1086}\x{108D}\x{109D}\x{135D}-\x{135F}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}-\x{1753}\x{1772}-\x{1773}\x{17B4}-\x{17B5}\x{17B7}-\x{17BD}\x{17C6}\x{17C9}-\x{17D3}\x{17DD}\x{180B}-\x{180D}\x{1885}-\x{1886}\x{18A9}\x{1920}-\x{1922}\x{1927}-\x{1928}\x{1932}\x{1939}-\x{193B}\x{1A17}-\x{1A18}\x{1A1B}\x{1A56}\x{1A58}-\x{1A5E}\x{1A60}\x{1A62}\x{1A65}-\x{1A6C}\x{1A73}-\x{1A7C}\x{1A7F}\x{1AB0}-\x{1ABD}\x{1ABE}\x{1ABF}-\x{1AC0}\x{1B00}-\x{1B03}\x{1B34}\x{1B36}-\x{1B3A}\x{1B3C}\x{1B42}\x{1B6B}-\x{1B73}\x{1B80}-\x{1B81}\x{1BA2}-\x{1BA5}\x{1BA8}-\x{1BA9}\x{1BAB}-\x{1BAD}\x{1BE6}\x{1BE8}-\x{1BE9}\x{1BED}\x{1BEF}-\x{1BF1}\x{1C2C}-\x{1C33}\x{1C36}-\x{1C37}\x{1CD0}-\x{1CD2}\x{1CD4}-\x{1CE0}\x{1CE2}-\x{1CE8}\x{1CED}\x{1CF4}\x{1CF8}-\x{1CF9}\x{1DC0}-\x{1DF9}\x{1DFB}-\x{1DFF}\x{200B}\x{200E}-\x{200F}\x{202A}-\x{202E}\x{2060}-\x{2064}\x{206A}-\x{206F}\x{20D0}-\x{20DC}\x{20DD}-\x{20E0}\x{20E1}\x{20E2}-\x{20E4}\x{20E5}-\x{20F0}\x{2CEF}-\x{2CF1}\x{2D7F}\x{2DE0}-\x{2DFF}\x{302A}-\x{302D}\x{3099}-\x{309A}\x{A66F}\x{A670}-\x{A672}\x{A674}-\x{A67D}\x{A69E}-\x{A69F}\x{A6F0}-\x{A6F1}\x{A802}\x{A806}\x{A80B}\x{A825}-\x{A826}\x{A82C}\x{A8C4}-\x{A8C5}\x{A8E0}-\x{A8F1}\x{A8FF}\x{A926}-\x{A92D}\x{A947}-\x{A951}\x{A980}-\x{A982}\x{A9B3}\x{A9B6}-\x{A9B9}\x{A9BC}-\x{A9BD}\x{A9E5}\x{AA29}-\x{AA2E}\x{AA31}-\x{AA32}\x{AA35}-\x{AA36}\x{AA43}\x{AA4C}\x{AA7C}\x{AAB0}\x{AAB2}-\x{AAB4}\x{AAB7}-\x{AAB8}\x{AABE}-\x{AABF}\x{AAC1}\x{AAEC}-\x{AAED}\x{AAF6}\x{ABE5}\x{ABE8}\x{ABED}\x{FB1E}\x{FE00}-\x{FE0F}\x{FE20}-\x{FE2F}\x{FEFF}\x{FFF9}-\x{FFFB}\x{101FD}\x{102E0}\x{10376}-\x{1037A}\x{10A01}-\x{10A03}\x{10A05}-\x{10A06}\x{10A0C}-\x{10A0F}\x{10A38}-\x{10A3A}\x{10A3F}\x{10AE5}-\x{10AE6}\x{10D24}-\x{10D27}\x{10EAB}-\x{10EAC}\x{10F46}-\x{10F50}\x{11001}\x{11038}-\x{11046}\x{1107F}-\x{11081}\x{110B3}-\x{110B6}\x{110B9}-\x{110BA}\x{11100}-\x{11102}\x{11127}-\x{1112B}\x{1112D}-\x{11134}\x{11173}\x{11180}-\x{11181}\x{111B6}-\x{111BE}\x{111C9}-\x{111CC}\x{111CF}\x{1122F}-\x{11231}\x{11234}\x{11236}-\x{11237}\x{1123E}\x{112DF}\x{112E3}-\x{112EA}\x{11300}-\x{11301}\x{1133B}-\x{1133C}\x{11340}\x{11366}-\x{1136C}\x{11370}-\x{11374}\x{11438}-\x{1143F}\x{11442}-\x{11444}\x{11446}\x{1145E}\x{114B3}-\x{114B8}\x{114BA}\x{114BF}-\x{114C0}\x{114C2}-\x{114C3}\x{115B2}-\x{115B5}\x{115BC}-\x{115BD}\x{115BF}-\x{115C0}\x{115DC}-\x{115DD}\x{11633}-\x{1163A}\x{1163D}\x{1163F}-\x{11640}\x{116AB}\x{116AD}\x{116B0}-\x{116B5}\x{116B7}\x{1171D}-\x{1171F}\x{11722}-\x{11725}\x{11727}-\x{1172B}\x{1182F}-\x{11837}\x{11839}-\x{1183A}\x{1193B}-\x{1193C}\x{1193E}\x{11943}\x{119D4}-\x{119D7}\x{119DA}-\x{119DB}\x{119E0}\x{11A01}-\x{11A0A}\x{11A33}-\x{11A38}\x{11A3B}-\x{11A3E}\x{11A47}\x{11A51}-\x{11A56}\x{11A59}-\x{11A5B}\x{11A8A}-\x{11A96}\x{11A98}-\x{11A99}\x{11C30}-\x{11C36}\x{11C38}-\x{11C3D}\x{11C3F}\x{11C92}-\x{11CA7}\x{11CAA}-\x{11CB0}\x{11CB2}-\x{11CB3}\x{11CB5}-\x{11CB6}\x{11D31}-\x{11D36}\x{11D3A}\x{11D3C}-\x{11D3D}\x{11D3F}-\x{11D45}\x{11D47}\x{11D90}-\x{11D91}\x{11D95}\x{11D97}\x{11EF3}-\x{11EF4}\x{13430}-\x{13438}\x{16AF0}-\x{16AF4}\x{16B30}-\x{16B36}\x{16F4F}\x{16F8F}-\x{16F92}\x{16FE4}\x{1BC9D}-\x{1BC9E}\x{1BCA0}-\x{1BCA3}\x{1D167}-\x{1D169}\x{1D173}-\x{1D17A}\x{1D17B}-\x{1D182}\x{1D185}-\x{1D18B}\x{1D1AA}-\x{1D1AD}\x{1D242}-\x{1D244}\x{1DA00}-\x{1DA36}\x{1DA3B}-\x{1DA6C}\x{1DA75}\x{1DA84}\x{1DA9B}-\x{1DA9F}\x{1DAA1}-\x{1DAAF}\x{1E000}-\x{1E006}\x{1E008}-\x{1E018}\x{1E01B}-\x{1E021}\x{1E023}-\x{1E024}\x{1E026}-\x{1E02A}\x{1E130}-\x{1E136}\x{1E2EC}-\x{1E2EF}\x{1E8D0}-\x{1E8D6}\x{1E944}-\x{1E94A}\x{1E94B}\x{E0001}\x{E0020}-\x{E007F}\x{E0100}-\x{E01EF}]*)[\x{0622}-\x{0625}\x{0627}\x{0629}\x{062F}-\x{0632}\x{0648}\x{0671}-\x{0673}\x{0675}-\x{0677}\x{0688}-\x{0699}\x{06C0}\x{06C3}-\x{06CB}\x{06CD}\x{06CF}\x{06D2}-\x{06D3}\x{06D5}\x{06EE}-\x{06EF}\x{0710}\x{0715}-\x{0719}\x{071E}\x{0728}\x{072A}\x{072C}\x{072F}\x{074D}\x{0759}-\x{075B}\x{076B}-\x{076C}\x{0771}\x{0773}-\x{0774}\x{0778}-\x{0779}\x{0840}\x{0846}-\x{0847}\x{0849}\x{0854}\x{0856}-\x{0858}\x{0867}\x{0869}-\x{086A}\x{08AA}-\x{08AC}\x{08AE}\x{08B1}-\x{08B2}\x{08B9}\x{10AC5}\x{10AC7}\x{10AC9}-\x{10ACA}\x{10ACE}-\x{10AD2}\x{10ADD}\x{10AE1}\x{10AE4}\x{10AEF}\x{10B81}\x{10B83}-\x{10B85}\x{10B89}\x{10B8C}\x{10B8E}-\x{10B8F}\x{10B91}\x{10BA9}-\x{10BAC}\x{10D22}\x{10F33}\x{10F54}\x{10FB4}-\x{10FB6}\x{10FB9}-\x{10FBA}\x{10FBD}\x{10FC2}-\x{10FC3}\x{10FC9}\x{0620}\x{0626}\x{0628}\x{062A}-\x{062E}\x{0633}-\x{063F}\x{0641}-\x{0647}\x{0649}-\x{064A}\x{066E}-\x{066F}\x{0678}-\x{0687}\x{069A}-\x{06BF}\x{06C1}-\x{06C2}\x{06CC}\x{06CE}\x{06D0}-\x{06D1}\x{06FA}-\x{06FC}\x{06FF}\x{0712}-\x{0714}\x{071A}-\x{071D}\x{071F}-\x{0727}\x{0729}\x{072B}\x{072D}-\x{072E}\x{074E}-\x{0758}\x{075C}-\x{076A}\x{076D}-\x{0770}\x{0772}\x{0775}-\x{0777}\x{077A}-\x{077F}\x{07CA}-\x{07EA}\x{0841}-\x{0845}\x{0848}\x{084A}-\x{0853}\x{0855}\x{0860}\x{0862}-\x{0865}\x{0868}\x{08A0}-\x{08A9}\x{08AF}-\x{08B0}\x{08B3}-\x{08B4}\x{08B6}-\x{08B8}\x{08BA}-\x{08C7}\x{1807}\x{1820}-\x{1842}\x{1843}\x{1844}-\x{1878}\x{1887}-\x{18A8}\x{18AA}\x{A840}-\x{A871}\x{10AC0}-\x{10AC4}\x{10AD3}-\x{10AD6}\x{10AD8}-\x{10ADC}\x{10ADE}-\x{10AE0}\x{10AEB}-\x{10AEE}\x{10B80}\x{10B82}\x{10B86}-\x{10B88}\x{10B8A}-\x{10B8B}\x{10B8D}\x{10B90}\x{10BAD}-\x{10BAE}\x{10D01}-\x{10D21}\x{10D23}\x{10F30}-\x{10F32}\x{10F34}-\x{10F44}\x{10F51}-\x{10F53}\x{10FB0}\x{10FB2}-\x{10FB3}\x{10FB8}\x{10FBB}-\x{10FBC}\x{10FBE}-\x{10FBF}\x{10FC1}\x{10FC4}\x{10FCA}\x{1E900}-\x{1E943}]/u'; -} diff --git a/lib/symfony/polyfill-intl-idn/Resources/unidata/deviation.php b/lib/symfony/polyfill-intl-idn/Resources/unidata/deviation.php deleted file mode 100644 index 0bbd33567..000000000 --- a/lib/symfony/polyfill-intl-idn/Resources/unidata/deviation.php +++ /dev/null @@ -1,8 +0,0 @@ -<?php - -return array ( - 223 => 'ss', - 962 => 'σ', - 8204 => '', - 8205 => '', -); diff --git a/lib/symfony/polyfill-intl-idn/Resources/unidata/disallowed.php b/lib/symfony/polyfill-intl-idn/Resources/unidata/disallowed.php deleted file mode 100644 index 25a5f564d..000000000 --- a/lib/symfony/polyfill-intl-idn/Resources/unidata/disallowed.php +++ /dev/null @@ -1,2638 +0,0 @@ -<?php - -return array ( - 888 => true, - 889 => true, - 896 => true, - 897 => true, - 898 => true, - 899 => true, - 907 => true, - 909 => true, - 930 => true, - 1216 => true, - 1328 => true, - 1367 => true, - 1368 => true, - 1419 => true, - 1420 => true, - 1424 => true, - 1480 => true, - 1481 => true, - 1482 => true, - 1483 => true, - 1484 => true, - 1485 => true, - 1486 => true, - 1487 => true, - 1515 => true, - 1516 => true, - 1517 => true, - 1518 => true, - 1525 => true, - 1526 => true, - 1527 => true, - 1528 => true, - 1529 => true, - 1530 => true, - 1531 => true, - 1532 => true, - 1533 => true, - 1534 => true, - 1535 => true, - 1536 => true, - 1537 => true, - 1538 => true, - 1539 => true, - 1540 => true, - 1541 => true, - 1564 => true, - 1565 => true, - 1757 => true, - 1806 => true, - 1807 => true, - 1867 => true, - 1868 => true, - 1970 => true, - 1971 => true, - 1972 => true, - 1973 => true, - 1974 => true, - 1975 => true, - 1976 => true, - 1977 => true, - 1978 => true, - 1979 => true, - 1980 => true, - 1981 => true, - 1982 => true, - 1983 => true, - 2043 => true, - 2044 => true, - 2094 => true, - 2095 => true, - 2111 => true, - 2140 => true, - 2141 => true, - 2143 => true, - 2229 => true, - 2248 => true, - 2249 => true, - 2250 => true, - 2251 => true, - 2252 => true, - 2253 => true, - 2254 => true, - 2255 => true, - 2256 => true, - 2257 => true, - 2258 => true, - 2274 => true, - 2436 => true, - 2445 => true, - 2446 => true, - 2449 => true, - 2450 => true, - 2473 => true, - 2481 => true, - 2483 => true, - 2484 => true, - 2485 => true, - 2490 => true, - 2491 => true, - 2501 => true, - 2502 => true, - 2505 => true, - 2506 => true, - 2511 => true, - 2512 => true, - 2513 => true, - 2514 => true, - 2515 => true, - 2516 => true, - 2517 => true, - 2518 => true, - 2520 => true, - 2521 => true, - 2522 => true, - 2523 => true, - 2526 => true, - 2532 => true, - 2533 => true, - 2559 => true, - 2560 => true, - 2564 => true, - 2571 => true, - 2572 => true, - 2573 => true, - 2574 => true, - 2577 => true, - 2578 => true, - 2601 => true, - 2609 => true, - 2612 => true, - 2615 => true, - 2618 => true, - 2619 => true, - 2621 => true, - 2627 => true, - 2628 => true, - 2629 => true, - 2630 => true, - 2633 => true, - 2634 => true, - 2638 => true, - 2639 => true, - 2640 => true, - 2642 => true, - 2643 => true, - 2644 => true, - 2645 => true, - 2646 => true, - 2647 => true, - 2648 => true, - 2653 => true, - 2655 => true, - 2656 => true, - 2657 => true, - 2658 => true, - 2659 => true, - 2660 => true, - 2661 => true, - 2679 => true, - 2680 => true, - 2681 => true, - 2682 => true, - 2683 => true, - 2684 => true, - 2685 => true, - 2686 => true, - 2687 => true, - 2688 => true, - 2692 => true, - 2702 => true, - 2706 => true, - 2729 => true, - 2737 => true, - 2740 => true, - 2746 => true, - 2747 => true, - 2758 => true, - 2762 => true, - 2766 => true, - 2767 => true, - 2769 => true, - 2770 => true, - 2771 => true, - 2772 => true, - 2773 => true, - 2774 => true, - 2775 => true, - 2776 => true, - 2777 => true, - 2778 => true, - 2779 => true, - 2780 => true, - 2781 => true, - 2782 => true, - 2783 => true, - 2788 => true, - 2789 => true, - 2802 => true, - 2803 => true, - 2804 => true, - 2805 => true, - 2806 => true, - 2807 => true, - 2808 => true, - 2816 => true, - 2820 => true, - 2829 => true, - 2830 => true, - 2833 => true, - 2834 => true, - 2857 => true, - 2865 => true, - 2868 => true, - 2874 => true, - 2875 => true, - 2885 => true, - 2886 => true, - 2889 => true, - 2890 => true, - 2894 => true, - 2895 => true, - 2896 => true, - 2897 => true, - 2898 => true, - 2899 => true, - 2900 => true, - 2904 => true, - 2905 => true, - 2906 => true, - 2907 => true, - 2910 => true, - 2916 => true, - 2917 => true, - 2936 => true, - 2937 => true, - 2938 => true, - 2939 => true, - 2940 => true, - 2941 => true, - 2942 => true, - 2943 => true, - 2944 => true, - 2945 => true, - 2948 => true, - 2955 => true, - 2956 => true, - 2957 => true, - 2961 => true, - 2966 => true, - 2967 => true, - 2968 => true, - 2971 => true, - 2973 => true, - 2976 => true, - 2977 => true, - 2978 => true, - 2981 => true, - 2982 => true, - 2983 => true, - 2987 => true, - 2988 => true, - 2989 => true, - 3002 => true, - 3003 => true, - 3004 => true, - 3005 => true, - 3011 => true, - 3012 => true, - 3013 => true, - 3017 => true, - 3022 => true, - 3023 => true, - 3025 => true, - 3026 => true, - 3027 => true, - 3028 => true, - 3029 => true, - 3030 => true, - 3032 => true, - 3033 => true, - 3034 => true, - 3035 => true, - 3036 => true, - 3037 => true, - 3038 => true, - 3039 => true, - 3040 => true, - 3041 => true, - 3042 => true, - 3043 => true, - 3044 => true, - 3045 => true, - 3067 => true, - 3068 => true, - 3069 => true, - 3070 => true, - 3071 => true, - 3085 => true, - 3089 => true, - 3113 => true, - 3130 => true, - 3131 => true, - 3132 => true, - 3141 => true, - 3145 => true, - 3150 => true, - 3151 => true, - 3152 => true, - 3153 => true, - 3154 => true, - 3155 => true, - 3156 => true, - 3159 => true, - 3163 => true, - 3164 => true, - 3165 => true, - 3166 => true, - 3167 => true, - 3172 => true, - 3173 => true, - 3184 => true, - 3185 => true, - 3186 => true, - 3187 => true, - 3188 => true, - 3189 => true, - 3190 => true, - 3213 => true, - 3217 => true, - 3241 => true, - 3252 => true, - 3258 => true, - 3259 => true, - 3269 => true, - 3273 => true, - 3278 => true, - 3279 => true, - 3280 => true, - 3281 => true, - 3282 => true, - 3283 => true, - 3284 => true, - 3287 => true, - 3288 => true, - 3289 => true, - 3290 => true, - 3291 => true, - 3292 => true, - 3293 => true, - 3295 => true, - 3300 => true, - 3301 => true, - 3312 => true, - 3315 => true, - 3316 => true, - 3317 => true, - 3318 => true, - 3319 => true, - 3320 => true, - 3321 => true, - 3322 => true, - 3323 => true, - 3324 => true, - 3325 => true, - 3326 => true, - 3327 => true, - 3341 => true, - 3345 => true, - 3397 => true, - 3401 => true, - 3408 => true, - 3409 => true, - 3410 => true, - 3411 => true, - 3428 => true, - 3429 => true, - 3456 => true, - 3460 => true, - 3479 => true, - 3480 => true, - 3481 => true, - 3506 => true, - 3516 => true, - 3518 => true, - 3519 => true, - 3527 => true, - 3528 => true, - 3529 => true, - 3531 => true, - 3532 => true, - 3533 => true, - 3534 => true, - 3541 => true, - 3543 => true, - 3552 => true, - 3553 => true, - 3554 => true, - 3555 => true, - 3556 => true, - 3557 => true, - 3568 => true, - 3569 => true, - 3573 => true, - 3574 => true, - 3575 => true, - 3576 => true, - 3577 => true, - 3578 => true, - 3579 => true, - 3580 => true, - 3581 => true, - 3582 => true, - 3583 => true, - 3584 => true, - 3643 => true, - 3644 => true, - 3645 => true, - 3646 => true, - 3715 => true, - 3717 => true, - 3723 => true, - 3748 => true, - 3750 => true, - 3774 => true, - 3775 => true, - 3781 => true, - 3783 => true, - 3790 => true, - 3791 => true, - 3802 => true, - 3803 => true, - 3912 => true, - 3949 => true, - 3950 => true, - 3951 => true, - 3952 => true, - 3992 => true, - 4029 => true, - 4045 => true, - 4294 => true, - 4296 => true, - 4297 => true, - 4298 => true, - 4299 => true, - 4300 => true, - 4302 => true, - 4303 => true, - 4447 => true, - 4448 => true, - 4681 => true, - 4686 => true, - 4687 => true, - 4695 => true, - 4697 => true, - 4702 => true, - 4703 => true, - 4745 => true, - 4750 => true, - 4751 => true, - 4785 => true, - 4790 => true, - 4791 => true, - 4799 => true, - 4801 => true, - 4806 => true, - 4807 => true, - 4823 => true, - 4881 => true, - 4886 => true, - 4887 => true, - 4955 => true, - 4956 => true, - 4989 => true, - 4990 => true, - 4991 => true, - 5018 => true, - 5019 => true, - 5020 => true, - 5021 => true, - 5022 => true, - 5023 => true, - 5110 => true, - 5111 => true, - 5118 => true, - 5119 => true, - 5760 => true, - 5789 => true, - 5790 => true, - 5791 => true, - 5881 => true, - 5882 => true, - 5883 => true, - 5884 => true, - 5885 => true, - 5886 => true, - 5887 => true, - 5901 => true, - 5909 => true, - 5910 => true, - 5911 => true, - 5912 => true, - 5913 => true, - 5914 => true, - 5915 => true, - 5916 => true, - 5917 => true, - 5918 => true, - 5919 => true, - 5943 => true, - 5944 => true, - 5945 => true, - 5946 => true, - 5947 => true, - 5948 => true, - 5949 => true, - 5950 => true, - 5951 => true, - 5972 => true, - 5973 => true, - 5974 => true, - 5975 => true, - 5976 => true, - 5977 => true, - 5978 => true, - 5979 => true, - 5980 => true, - 5981 => true, - 5982 => true, - 5983 => true, - 5997 => true, - 6001 => true, - 6004 => true, - 6005 => true, - 6006 => true, - 6007 => true, - 6008 => true, - 6009 => true, - 6010 => true, - 6011 => true, - 6012 => true, - 6013 => true, - 6014 => true, - 6015 => true, - 6068 => true, - 6069 => true, - 6110 => true, - 6111 => true, - 6122 => true, - 6123 => true, - 6124 => true, - 6125 => true, - 6126 => true, - 6127 => true, - 6138 => true, - 6139 => true, - 6140 => true, - 6141 => true, - 6142 => true, - 6143 => true, - 6150 => true, - 6158 => true, - 6159 => true, - 6170 => true, - 6171 => true, - 6172 => true, - 6173 => true, - 6174 => true, - 6175 => true, - 6265 => true, - 6266 => true, - 6267 => true, - 6268 => true, - 6269 => true, - 6270 => true, - 6271 => true, - 6315 => true, - 6316 => true, - 6317 => true, - 6318 => true, - 6319 => true, - 6390 => true, - 6391 => true, - 6392 => true, - 6393 => true, - 6394 => true, - 6395 => true, - 6396 => true, - 6397 => true, - 6398 => true, - 6399 => true, - 6431 => true, - 6444 => true, - 6445 => true, - 6446 => true, - 6447 => true, - 6460 => true, - 6461 => true, - 6462 => true, - 6463 => true, - 6465 => true, - 6466 => true, - 6467 => true, - 6510 => true, - 6511 => true, - 6517 => true, - 6518 => true, - 6519 => true, - 6520 => true, - 6521 => true, - 6522 => true, - 6523 => true, - 6524 => true, - 6525 => true, - 6526 => true, - 6527 => true, - 6572 => true, - 6573 => true, - 6574 => true, - 6575 => true, - 6602 => true, - 6603 => true, - 6604 => true, - 6605 => true, - 6606 => true, - 6607 => true, - 6619 => true, - 6620 => true, - 6621 => true, - 6684 => true, - 6685 => true, - 6751 => true, - 6781 => true, - 6782 => true, - 6794 => true, - 6795 => true, - 6796 => true, - 6797 => true, - 6798 => true, - 6799 => true, - 6810 => true, - 6811 => true, - 6812 => true, - 6813 => true, - 6814 => true, - 6815 => true, - 6830 => true, - 6831 => true, - 6988 => true, - 6989 => true, - 6990 => true, - 6991 => true, - 7037 => true, - 7038 => true, - 7039 => true, - 7156 => true, - 7157 => true, - 7158 => true, - 7159 => true, - 7160 => true, - 7161 => true, - 7162 => true, - 7163 => true, - 7224 => true, - 7225 => true, - 7226 => true, - 7242 => true, - 7243 => true, - 7244 => true, - 7305 => true, - 7306 => true, - 7307 => true, - 7308 => true, - 7309 => true, - 7310 => true, - 7311 => true, - 7355 => true, - 7356 => true, - 7368 => true, - 7369 => true, - 7370 => true, - 7371 => true, - 7372 => true, - 7373 => true, - 7374 => true, - 7375 => true, - 7419 => true, - 7420 => true, - 7421 => true, - 7422 => true, - 7423 => true, - 7674 => true, - 7958 => true, - 7959 => true, - 7966 => true, - 7967 => true, - 8006 => true, - 8007 => true, - 8014 => true, - 8015 => true, - 8024 => true, - 8026 => true, - 8028 => true, - 8030 => true, - 8062 => true, - 8063 => true, - 8117 => true, - 8133 => true, - 8148 => true, - 8149 => true, - 8156 => true, - 8176 => true, - 8177 => true, - 8181 => true, - 8191 => true, - 8206 => true, - 8207 => true, - 8228 => true, - 8229 => true, - 8230 => true, - 8232 => true, - 8233 => true, - 8234 => true, - 8235 => true, - 8236 => true, - 8237 => true, - 8238 => true, - 8289 => true, - 8290 => true, - 8291 => true, - 8293 => true, - 8294 => true, - 8295 => true, - 8296 => true, - 8297 => true, - 8298 => true, - 8299 => true, - 8300 => true, - 8301 => true, - 8302 => true, - 8303 => true, - 8306 => true, - 8307 => true, - 8335 => true, - 8349 => true, - 8350 => true, - 8351 => true, - 8384 => true, - 8385 => true, - 8386 => true, - 8387 => true, - 8388 => true, - 8389 => true, - 8390 => true, - 8391 => true, - 8392 => true, - 8393 => true, - 8394 => true, - 8395 => true, - 8396 => true, - 8397 => true, - 8398 => true, - 8399 => true, - 8433 => true, - 8434 => true, - 8435 => true, - 8436 => true, - 8437 => true, - 8438 => true, - 8439 => true, - 8440 => true, - 8441 => true, - 8442 => true, - 8443 => true, - 8444 => true, - 8445 => true, - 8446 => true, - 8447 => true, - 8498 => true, - 8579 => true, - 8588 => true, - 8589 => true, - 8590 => true, - 8591 => true, - 9255 => true, - 9256 => true, - 9257 => true, - 9258 => true, - 9259 => true, - 9260 => true, - 9261 => true, - 9262 => true, - 9263 => true, - 9264 => true, - 9265 => true, - 9266 => true, - 9267 => true, - 9268 => true, - 9269 => true, - 9270 => true, - 9271 => true, - 9272 => true, - 9273 => true, - 9274 => true, - 9275 => true, - 9276 => true, - 9277 => true, - 9278 => true, - 9279 => true, - 9291 => true, - 9292 => true, - 9293 => true, - 9294 => true, - 9295 => true, - 9296 => true, - 9297 => true, - 9298 => true, - 9299 => true, - 9300 => true, - 9301 => true, - 9302 => true, - 9303 => true, - 9304 => true, - 9305 => true, - 9306 => true, - 9307 => true, - 9308 => true, - 9309 => true, - 9310 => true, - 9311 => true, - 9352 => true, - 9353 => true, - 9354 => true, - 9355 => true, - 9356 => true, - 9357 => true, - 9358 => true, - 9359 => true, - 9360 => true, - 9361 => true, - 9362 => true, - 9363 => true, - 9364 => true, - 9365 => true, - 9366 => true, - 9367 => true, - 9368 => true, - 9369 => true, - 9370 => true, - 9371 => true, - 11124 => true, - 11125 => true, - 11158 => true, - 11311 => true, - 11359 => true, - 11508 => true, - 11509 => true, - 11510 => true, - 11511 => true, - 11512 => true, - 11558 => true, - 11560 => true, - 11561 => true, - 11562 => true, - 11563 => true, - 11564 => true, - 11566 => true, - 11567 => true, - 11624 => true, - 11625 => true, - 11626 => true, - 11627 => true, - 11628 => true, - 11629 => true, - 11630 => true, - 11633 => true, - 11634 => true, - 11635 => true, - 11636 => true, - 11637 => true, - 11638 => true, - 11639 => true, - 11640 => true, - 11641 => true, - 11642 => true, - 11643 => true, - 11644 => true, - 11645 => true, - 11646 => true, - 11671 => true, - 11672 => true, - 11673 => true, - 11674 => true, - 11675 => true, - 11676 => true, - 11677 => true, - 11678 => true, - 11679 => true, - 11687 => true, - 11695 => true, - 11703 => true, - 11711 => true, - 11719 => true, - 11727 => true, - 11735 => true, - 11743 => true, - 11930 => true, - 12020 => true, - 12021 => true, - 12022 => true, - 12023 => true, - 12024 => true, - 12025 => true, - 12026 => true, - 12027 => true, - 12028 => true, - 12029 => true, - 12030 => true, - 12031 => true, - 12246 => true, - 12247 => true, - 12248 => true, - 12249 => true, - 12250 => true, - 12251 => true, - 12252 => true, - 12253 => true, - 12254 => true, - 12255 => true, - 12256 => true, - 12257 => true, - 12258 => true, - 12259 => true, - 12260 => true, - 12261 => true, - 12262 => true, - 12263 => true, - 12264 => true, - 12265 => true, - 12266 => true, - 12267 => true, - 12268 => true, - 12269 => true, - 12270 => true, - 12271 => true, - 12272 => true, - 12273 => true, - 12274 => true, - 12275 => true, - 12276 => true, - 12277 => true, - 12278 => true, - 12279 => true, - 12280 => true, - 12281 => true, - 12282 => true, - 12283 => true, - 12284 => true, - 12285 => true, - 12286 => true, - 12287 => true, - 12352 => true, - 12439 => true, - 12440 => true, - 12544 => true, - 12545 => true, - 12546 => true, - 12547 => true, - 12548 => true, - 12592 => true, - 12644 => true, - 12687 => true, - 12772 => true, - 12773 => true, - 12774 => true, - 12775 => true, - 12776 => true, - 12777 => true, - 12778 => true, - 12779 => true, - 12780 => true, - 12781 => true, - 12782 => true, - 12783 => true, - 12831 => true, - 13250 => true, - 13255 => true, - 13272 => true, - 40957 => true, - 40958 => true, - 40959 => true, - 42125 => true, - 42126 => true, - 42127 => true, - 42183 => true, - 42184 => true, - 42185 => true, - 42186 => true, - 42187 => true, - 42188 => true, - 42189 => true, - 42190 => true, - 42191 => true, - 42540 => true, - 42541 => true, - 42542 => true, - 42543 => true, - 42544 => true, - 42545 => true, - 42546 => true, - 42547 => true, - 42548 => true, - 42549 => true, - 42550 => true, - 42551 => true, - 42552 => true, - 42553 => true, - 42554 => true, - 42555 => true, - 42556 => true, - 42557 => true, - 42558 => true, - 42559 => true, - 42744 => true, - 42745 => true, - 42746 => true, - 42747 => true, - 42748 => true, - 42749 => true, - 42750 => true, - 42751 => true, - 42944 => true, - 42945 => true, - 43053 => true, - 43054 => true, - 43055 => true, - 43066 => true, - 43067 => true, - 43068 => true, - 43069 => true, - 43070 => true, - 43071 => true, - 43128 => true, - 43129 => true, - 43130 => true, - 43131 => true, - 43132 => true, - 43133 => true, - 43134 => true, - 43135 => true, - 43206 => true, - 43207 => true, - 43208 => true, - 43209 => true, - 43210 => true, - 43211 => true, - 43212 => true, - 43213 => true, - 43226 => true, - 43227 => true, - 43228 => true, - 43229 => true, - 43230 => true, - 43231 => true, - 43348 => true, - 43349 => true, - 43350 => true, - 43351 => true, - 43352 => true, - 43353 => true, - 43354 => true, - 43355 => true, - 43356 => true, - 43357 => true, - 43358 => true, - 43389 => true, - 43390 => true, - 43391 => true, - 43470 => true, - 43482 => true, - 43483 => true, - 43484 => true, - 43485 => true, - 43519 => true, - 43575 => true, - 43576 => true, - 43577 => true, - 43578 => true, - 43579 => true, - 43580 => true, - 43581 => true, - 43582 => true, - 43583 => true, - 43598 => true, - 43599 => true, - 43610 => true, - 43611 => true, - 43715 => true, - 43716 => true, - 43717 => true, - 43718 => true, - 43719 => true, - 43720 => true, - 43721 => true, - 43722 => true, - 43723 => true, - 43724 => true, - 43725 => true, - 43726 => true, - 43727 => true, - 43728 => true, - 43729 => true, - 43730 => true, - 43731 => true, - 43732 => true, - 43733 => true, - 43734 => true, - 43735 => true, - 43736 => true, - 43737 => true, - 43738 => true, - 43767 => true, - 43768 => true, - 43769 => true, - 43770 => true, - 43771 => true, - 43772 => true, - 43773 => true, - 43774 => true, - 43775 => true, - 43776 => true, - 43783 => true, - 43784 => true, - 43791 => true, - 43792 => true, - 43799 => true, - 43800 => true, - 43801 => true, - 43802 => true, - 43803 => true, - 43804 => true, - 43805 => true, - 43806 => true, - 43807 => true, - 43815 => true, - 43823 => true, - 43884 => true, - 43885 => true, - 43886 => true, - 43887 => true, - 44014 => true, - 44015 => true, - 44026 => true, - 44027 => true, - 44028 => true, - 44029 => true, - 44030 => true, - 44031 => true, - 55204 => true, - 55205 => true, - 55206 => true, - 55207 => true, - 55208 => true, - 55209 => true, - 55210 => true, - 55211 => true, - 55212 => true, - 55213 => true, - 55214 => true, - 55215 => true, - 55239 => true, - 55240 => true, - 55241 => true, - 55242 => true, - 55292 => true, - 55293 => true, - 55294 => true, - 55295 => true, - 64110 => true, - 64111 => true, - 64263 => true, - 64264 => true, - 64265 => true, - 64266 => true, - 64267 => true, - 64268 => true, - 64269 => true, - 64270 => true, - 64271 => true, - 64272 => true, - 64273 => true, - 64274 => true, - 64280 => true, - 64281 => true, - 64282 => true, - 64283 => true, - 64284 => true, - 64311 => true, - 64317 => true, - 64319 => true, - 64322 => true, - 64325 => true, - 64450 => true, - 64451 => true, - 64452 => true, - 64453 => true, - 64454 => true, - 64455 => true, - 64456 => true, - 64457 => true, - 64458 => true, - 64459 => true, - 64460 => true, - 64461 => true, - 64462 => true, - 64463 => true, - 64464 => true, - 64465 => true, - 64466 => true, - 64832 => true, - 64833 => true, - 64834 => true, - 64835 => true, - 64836 => true, - 64837 => true, - 64838 => true, - 64839 => true, - 64840 => true, - 64841 => true, - 64842 => true, - 64843 => true, - 64844 => true, - 64845 => true, - 64846 => true, - 64847 => true, - 64912 => true, - 64913 => true, - 64968 => true, - 64969 => true, - 64970 => true, - 64971 => true, - 64972 => true, - 64973 => true, - 64974 => true, - 64975 => true, - 65022 => true, - 65023 => true, - 65042 => true, - 65049 => true, - 65050 => true, - 65051 => true, - 65052 => true, - 65053 => true, - 65054 => true, - 65055 => true, - 65072 => true, - 65106 => true, - 65107 => true, - 65127 => true, - 65132 => true, - 65133 => true, - 65134 => true, - 65135 => true, - 65141 => true, - 65277 => true, - 65278 => true, - 65280 => true, - 65440 => true, - 65471 => true, - 65472 => true, - 65473 => true, - 65480 => true, - 65481 => true, - 65488 => true, - 65489 => true, - 65496 => true, - 65497 => true, - 65501 => true, - 65502 => true, - 65503 => true, - 65511 => true, - 65519 => true, - 65520 => true, - 65521 => true, - 65522 => true, - 65523 => true, - 65524 => true, - 65525 => true, - 65526 => true, - 65527 => true, - 65528 => true, - 65529 => true, - 65530 => true, - 65531 => true, - 65532 => true, - 65533 => true, - 65534 => true, - 65535 => true, - 65548 => true, - 65575 => true, - 65595 => true, - 65598 => true, - 65614 => true, - 65615 => true, - 65787 => true, - 65788 => true, - 65789 => true, - 65790 => true, - 65791 => true, - 65795 => true, - 65796 => true, - 65797 => true, - 65798 => true, - 65844 => true, - 65845 => true, - 65846 => true, - 65935 => true, - 65949 => true, - 65950 => true, - 65951 => true, - 66205 => true, - 66206 => true, - 66207 => true, - 66257 => true, - 66258 => true, - 66259 => true, - 66260 => true, - 66261 => true, - 66262 => true, - 66263 => true, - 66264 => true, - 66265 => true, - 66266 => true, - 66267 => true, - 66268 => true, - 66269 => true, - 66270 => true, - 66271 => true, - 66300 => true, - 66301 => true, - 66302 => true, - 66303 => true, - 66340 => true, - 66341 => true, - 66342 => true, - 66343 => true, - 66344 => true, - 66345 => true, - 66346 => true, - 66347 => true, - 66348 => true, - 66379 => true, - 66380 => true, - 66381 => true, - 66382 => true, - 66383 => true, - 66427 => true, - 66428 => true, - 66429 => true, - 66430 => true, - 66431 => true, - 66462 => true, - 66500 => true, - 66501 => true, - 66502 => true, - 66503 => true, - 66718 => true, - 66719 => true, - 66730 => true, - 66731 => true, - 66732 => true, - 66733 => true, - 66734 => true, - 66735 => true, - 66772 => true, - 66773 => true, - 66774 => true, - 66775 => true, - 66812 => true, - 66813 => true, - 66814 => true, - 66815 => true, - 66856 => true, - 66857 => true, - 66858 => true, - 66859 => true, - 66860 => true, - 66861 => true, - 66862 => true, - 66863 => true, - 66916 => true, - 66917 => true, - 66918 => true, - 66919 => true, - 66920 => true, - 66921 => true, - 66922 => true, - 66923 => true, - 66924 => true, - 66925 => true, - 66926 => true, - 67383 => true, - 67384 => true, - 67385 => true, - 67386 => true, - 67387 => true, - 67388 => true, - 67389 => true, - 67390 => true, - 67391 => true, - 67414 => true, - 67415 => true, - 67416 => true, - 67417 => true, - 67418 => true, - 67419 => true, - 67420 => true, - 67421 => true, - 67422 => true, - 67423 => true, - 67590 => true, - 67591 => true, - 67593 => true, - 67638 => true, - 67641 => true, - 67642 => true, - 67643 => true, - 67645 => true, - 67646 => true, - 67670 => true, - 67743 => true, - 67744 => true, - 67745 => true, - 67746 => true, - 67747 => true, - 67748 => true, - 67749 => true, - 67750 => true, - 67827 => true, - 67830 => true, - 67831 => true, - 67832 => true, - 67833 => true, - 67834 => true, - 67868 => true, - 67869 => true, - 67870 => true, - 67898 => true, - 67899 => true, - 67900 => true, - 67901 => true, - 67902 => true, - 68024 => true, - 68025 => true, - 68026 => true, - 68027 => true, - 68048 => true, - 68049 => true, - 68100 => true, - 68103 => true, - 68104 => true, - 68105 => true, - 68106 => true, - 68107 => true, - 68116 => true, - 68120 => true, - 68150 => true, - 68151 => true, - 68155 => true, - 68156 => true, - 68157 => true, - 68158 => true, - 68169 => true, - 68170 => true, - 68171 => true, - 68172 => true, - 68173 => true, - 68174 => true, - 68175 => true, - 68185 => true, - 68186 => true, - 68187 => true, - 68188 => true, - 68189 => true, - 68190 => true, - 68191 => true, - 68327 => true, - 68328 => true, - 68329 => true, - 68330 => true, - 68343 => true, - 68344 => true, - 68345 => true, - 68346 => true, - 68347 => true, - 68348 => true, - 68349 => true, - 68350 => true, - 68351 => true, - 68406 => true, - 68407 => true, - 68408 => true, - 68438 => true, - 68439 => true, - 68467 => true, - 68468 => true, - 68469 => true, - 68470 => true, - 68471 => true, - 68498 => true, - 68499 => true, - 68500 => true, - 68501 => true, - 68502 => true, - 68503 => true, - 68504 => true, - 68509 => true, - 68510 => true, - 68511 => true, - 68512 => true, - 68513 => true, - 68514 => true, - 68515 => true, - 68516 => true, - 68517 => true, - 68518 => true, - 68519 => true, - 68520 => true, - 68787 => true, - 68788 => true, - 68789 => true, - 68790 => true, - 68791 => true, - 68792 => true, - 68793 => true, - 68794 => true, - 68795 => true, - 68796 => true, - 68797 => true, - 68798 => true, - 68799 => true, - 68851 => true, - 68852 => true, - 68853 => true, - 68854 => true, - 68855 => true, - 68856 => true, - 68857 => true, - 68904 => true, - 68905 => true, - 68906 => true, - 68907 => true, - 68908 => true, - 68909 => true, - 68910 => true, - 68911 => true, - 69247 => true, - 69290 => true, - 69294 => true, - 69295 => true, - 69416 => true, - 69417 => true, - 69418 => true, - 69419 => true, - 69420 => true, - 69421 => true, - 69422 => true, - 69423 => true, - 69580 => true, - 69581 => true, - 69582 => true, - 69583 => true, - 69584 => true, - 69585 => true, - 69586 => true, - 69587 => true, - 69588 => true, - 69589 => true, - 69590 => true, - 69591 => true, - 69592 => true, - 69593 => true, - 69594 => true, - 69595 => true, - 69596 => true, - 69597 => true, - 69598 => true, - 69599 => true, - 69623 => true, - 69624 => true, - 69625 => true, - 69626 => true, - 69627 => true, - 69628 => true, - 69629 => true, - 69630 => true, - 69631 => true, - 69710 => true, - 69711 => true, - 69712 => true, - 69713 => true, - 69744 => true, - 69745 => true, - 69746 => true, - 69747 => true, - 69748 => true, - 69749 => true, - 69750 => true, - 69751 => true, - 69752 => true, - 69753 => true, - 69754 => true, - 69755 => true, - 69756 => true, - 69757 => true, - 69758 => true, - 69821 => true, - 69826 => true, - 69827 => true, - 69828 => true, - 69829 => true, - 69830 => true, - 69831 => true, - 69832 => true, - 69833 => true, - 69834 => true, - 69835 => true, - 69836 => true, - 69837 => true, - 69838 => true, - 69839 => true, - 69865 => true, - 69866 => true, - 69867 => true, - 69868 => true, - 69869 => true, - 69870 => true, - 69871 => true, - 69882 => true, - 69883 => true, - 69884 => true, - 69885 => true, - 69886 => true, - 69887 => true, - 69941 => true, - 69960 => true, - 69961 => true, - 69962 => true, - 69963 => true, - 69964 => true, - 69965 => true, - 69966 => true, - 69967 => true, - 70007 => true, - 70008 => true, - 70009 => true, - 70010 => true, - 70011 => true, - 70012 => true, - 70013 => true, - 70014 => true, - 70015 => true, - 70112 => true, - 70133 => true, - 70134 => true, - 70135 => true, - 70136 => true, - 70137 => true, - 70138 => true, - 70139 => true, - 70140 => true, - 70141 => true, - 70142 => true, - 70143 => true, - 70162 => true, - 70279 => true, - 70281 => true, - 70286 => true, - 70302 => true, - 70314 => true, - 70315 => true, - 70316 => true, - 70317 => true, - 70318 => true, - 70319 => true, - 70379 => true, - 70380 => true, - 70381 => true, - 70382 => true, - 70383 => true, - 70394 => true, - 70395 => true, - 70396 => true, - 70397 => true, - 70398 => true, - 70399 => true, - 70404 => true, - 70413 => true, - 70414 => true, - 70417 => true, - 70418 => true, - 70441 => true, - 70449 => true, - 70452 => true, - 70458 => true, - 70469 => true, - 70470 => true, - 70473 => true, - 70474 => true, - 70478 => true, - 70479 => true, - 70481 => true, - 70482 => true, - 70483 => true, - 70484 => true, - 70485 => true, - 70486 => true, - 70488 => true, - 70489 => true, - 70490 => true, - 70491 => true, - 70492 => true, - 70500 => true, - 70501 => true, - 70509 => true, - 70510 => true, - 70511 => true, - 70748 => true, - 70754 => true, - 70755 => true, - 70756 => true, - 70757 => true, - 70758 => true, - 70759 => true, - 70760 => true, - 70761 => true, - 70762 => true, - 70763 => true, - 70764 => true, - 70765 => true, - 70766 => true, - 70767 => true, - 70768 => true, - 70769 => true, - 70770 => true, - 70771 => true, - 70772 => true, - 70773 => true, - 70774 => true, - 70775 => true, - 70776 => true, - 70777 => true, - 70778 => true, - 70779 => true, - 70780 => true, - 70781 => true, - 70782 => true, - 70783 => true, - 70856 => true, - 70857 => true, - 70858 => true, - 70859 => true, - 70860 => true, - 70861 => true, - 70862 => true, - 70863 => true, - 71094 => true, - 71095 => true, - 71237 => true, - 71238 => true, - 71239 => true, - 71240 => true, - 71241 => true, - 71242 => true, - 71243 => true, - 71244 => true, - 71245 => true, - 71246 => true, - 71247 => true, - 71258 => true, - 71259 => true, - 71260 => true, - 71261 => true, - 71262 => true, - 71263 => true, - 71277 => true, - 71278 => true, - 71279 => true, - 71280 => true, - 71281 => true, - 71282 => true, - 71283 => true, - 71284 => true, - 71285 => true, - 71286 => true, - 71287 => true, - 71288 => true, - 71289 => true, - 71290 => true, - 71291 => true, - 71292 => true, - 71293 => true, - 71294 => true, - 71295 => true, - 71353 => true, - 71354 => true, - 71355 => true, - 71356 => true, - 71357 => true, - 71358 => true, - 71359 => true, - 71451 => true, - 71452 => true, - 71468 => true, - 71469 => true, - 71470 => true, - 71471 => true, - 71923 => true, - 71924 => true, - 71925 => true, - 71926 => true, - 71927 => true, - 71928 => true, - 71929 => true, - 71930 => true, - 71931 => true, - 71932 => true, - 71933 => true, - 71934 => true, - 71943 => true, - 71944 => true, - 71946 => true, - 71947 => true, - 71956 => true, - 71959 => true, - 71990 => true, - 71993 => true, - 71994 => true, - 72007 => true, - 72008 => true, - 72009 => true, - 72010 => true, - 72011 => true, - 72012 => true, - 72013 => true, - 72014 => true, - 72015 => true, - 72104 => true, - 72105 => true, - 72152 => true, - 72153 => true, - 72165 => true, - 72166 => true, - 72167 => true, - 72168 => true, - 72169 => true, - 72170 => true, - 72171 => true, - 72172 => true, - 72173 => true, - 72174 => true, - 72175 => true, - 72176 => true, - 72177 => true, - 72178 => true, - 72179 => true, - 72180 => true, - 72181 => true, - 72182 => true, - 72183 => true, - 72184 => true, - 72185 => true, - 72186 => true, - 72187 => true, - 72188 => true, - 72189 => true, - 72190 => true, - 72191 => true, - 72264 => true, - 72265 => true, - 72266 => true, - 72267 => true, - 72268 => true, - 72269 => true, - 72270 => true, - 72271 => true, - 72355 => true, - 72356 => true, - 72357 => true, - 72358 => true, - 72359 => true, - 72360 => true, - 72361 => true, - 72362 => true, - 72363 => true, - 72364 => true, - 72365 => true, - 72366 => true, - 72367 => true, - 72368 => true, - 72369 => true, - 72370 => true, - 72371 => true, - 72372 => true, - 72373 => true, - 72374 => true, - 72375 => true, - 72376 => true, - 72377 => true, - 72378 => true, - 72379 => true, - 72380 => true, - 72381 => true, - 72382 => true, - 72383 => true, - 72713 => true, - 72759 => true, - 72774 => true, - 72775 => true, - 72776 => true, - 72777 => true, - 72778 => true, - 72779 => true, - 72780 => true, - 72781 => true, - 72782 => true, - 72783 => true, - 72813 => true, - 72814 => true, - 72815 => true, - 72848 => true, - 72849 => true, - 72872 => true, - 72967 => true, - 72970 => true, - 73015 => true, - 73016 => true, - 73017 => true, - 73019 => true, - 73022 => true, - 73032 => true, - 73033 => true, - 73034 => true, - 73035 => true, - 73036 => true, - 73037 => true, - 73038 => true, - 73039 => true, - 73050 => true, - 73051 => true, - 73052 => true, - 73053 => true, - 73054 => true, - 73055 => true, - 73062 => true, - 73065 => true, - 73103 => true, - 73106 => true, - 73113 => true, - 73114 => true, - 73115 => true, - 73116 => true, - 73117 => true, - 73118 => true, - 73119 => true, - 73649 => true, - 73650 => true, - 73651 => true, - 73652 => true, - 73653 => true, - 73654 => true, - 73655 => true, - 73656 => true, - 73657 => true, - 73658 => true, - 73659 => true, - 73660 => true, - 73661 => true, - 73662 => true, - 73663 => true, - 73714 => true, - 73715 => true, - 73716 => true, - 73717 => true, - 73718 => true, - 73719 => true, - 73720 => true, - 73721 => true, - 73722 => true, - 73723 => true, - 73724 => true, - 73725 => true, - 73726 => true, - 74863 => true, - 74869 => true, - 74870 => true, - 74871 => true, - 74872 => true, - 74873 => true, - 74874 => true, - 74875 => true, - 74876 => true, - 74877 => true, - 74878 => true, - 74879 => true, - 78895 => true, - 78896 => true, - 78897 => true, - 78898 => true, - 78899 => true, - 78900 => true, - 78901 => true, - 78902 => true, - 78903 => true, - 78904 => true, - 92729 => true, - 92730 => true, - 92731 => true, - 92732 => true, - 92733 => true, - 92734 => true, - 92735 => true, - 92767 => true, - 92778 => true, - 92779 => true, - 92780 => true, - 92781 => true, - 92910 => true, - 92911 => true, - 92918 => true, - 92919 => true, - 92920 => true, - 92921 => true, - 92922 => true, - 92923 => true, - 92924 => true, - 92925 => true, - 92926 => true, - 92927 => true, - 92998 => true, - 92999 => true, - 93000 => true, - 93001 => true, - 93002 => true, - 93003 => true, - 93004 => true, - 93005 => true, - 93006 => true, - 93007 => true, - 93018 => true, - 93026 => true, - 93048 => true, - 93049 => true, - 93050 => true, - 93051 => true, - 93052 => true, - 94027 => true, - 94028 => true, - 94029 => true, - 94030 => true, - 94088 => true, - 94089 => true, - 94090 => true, - 94091 => true, - 94092 => true, - 94093 => true, - 94094 => true, - 94181 => true, - 94182 => true, - 94183 => true, - 94184 => true, - 94185 => true, - 94186 => true, - 94187 => true, - 94188 => true, - 94189 => true, - 94190 => true, - 94191 => true, - 94194 => true, - 94195 => true, - 94196 => true, - 94197 => true, - 94198 => true, - 94199 => true, - 94200 => true, - 94201 => true, - 94202 => true, - 94203 => true, - 94204 => true, - 94205 => true, - 94206 => true, - 94207 => true, - 100344 => true, - 100345 => true, - 100346 => true, - 100347 => true, - 100348 => true, - 100349 => true, - 100350 => true, - 100351 => true, - 110931 => true, - 110932 => true, - 110933 => true, - 110934 => true, - 110935 => true, - 110936 => true, - 110937 => true, - 110938 => true, - 110939 => true, - 110940 => true, - 110941 => true, - 110942 => true, - 110943 => true, - 110944 => true, - 110945 => true, - 110946 => true, - 110947 => true, - 110952 => true, - 110953 => true, - 110954 => true, - 110955 => true, - 110956 => true, - 110957 => true, - 110958 => true, - 110959 => true, - 113771 => true, - 113772 => true, - 113773 => true, - 113774 => true, - 113775 => true, - 113789 => true, - 113790 => true, - 113791 => true, - 113801 => true, - 113802 => true, - 113803 => true, - 113804 => true, - 113805 => true, - 113806 => true, - 113807 => true, - 113818 => true, - 113819 => true, - 119030 => true, - 119031 => true, - 119032 => true, - 119033 => true, - 119034 => true, - 119035 => true, - 119036 => true, - 119037 => true, - 119038 => true, - 119039 => true, - 119079 => true, - 119080 => true, - 119155 => true, - 119156 => true, - 119157 => true, - 119158 => true, - 119159 => true, - 119160 => true, - 119161 => true, - 119162 => true, - 119273 => true, - 119274 => true, - 119275 => true, - 119276 => true, - 119277 => true, - 119278 => true, - 119279 => true, - 119280 => true, - 119281 => true, - 119282 => true, - 119283 => true, - 119284 => true, - 119285 => true, - 119286 => true, - 119287 => true, - 119288 => true, - 119289 => true, - 119290 => true, - 119291 => true, - 119292 => true, - 119293 => true, - 119294 => true, - 119295 => true, - 119540 => true, - 119541 => true, - 119542 => true, - 119543 => true, - 119544 => true, - 119545 => true, - 119546 => true, - 119547 => true, - 119548 => true, - 119549 => true, - 119550 => true, - 119551 => true, - 119639 => true, - 119640 => true, - 119641 => true, - 119642 => true, - 119643 => true, - 119644 => true, - 119645 => true, - 119646 => true, - 119647 => true, - 119893 => true, - 119965 => true, - 119968 => true, - 119969 => true, - 119971 => true, - 119972 => true, - 119975 => true, - 119976 => true, - 119981 => true, - 119994 => true, - 119996 => true, - 120004 => true, - 120070 => true, - 120075 => true, - 120076 => true, - 120085 => true, - 120093 => true, - 120122 => true, - 120127 => true, - 120133 => true, - 120135 => true, - 120136 => true, - 120137 => true, - 120145 => true, - 120486 => true, - 120487 => true, - 120780 => true, - 120781 => true, - 121484 => true, - 121485 => true, - 121486 => true, - 121487 => true, - 121488 => true, - 121489 => true, - 121490 => true, - 121491 => true, - 121492 => true, - 121493 => true, - 121494 => true, - 121495 => true, - 121496 => true, - 121497 => true, - 121498 => true, - 121504 => true, - 122887 => true, - 122905 => true, - 122906 => true, - 122914 => true, - 122917 => true, - 123181 => true, - 123182 => true, - 123183 => true, - 123198 => true, - 123199 => true, - 123210 => true, - 123211 => true, - 123212 => true, - 123213 => true, - 123642 => true, - 123643 => true, - 123644 => true, - 123645 => true, - 123646 => true, - 125125 => true, - 125126 => true, - 125260 => true, - 125261 => true, - 125262 => true, - 125263 => true, - 125274 => true, - 125275 => true, - 125276 => true, - 125277 => true, - 126468 => true, - 126496 => true, - 126499 => true, - 126501 => true, - 126502 => true, - 126504 => true, - 126515 => true, - 126520 => true, - 126522 => true, - 126524 => true, - 126525 => true, - 126526 => true, - 126527 => true, - 126528 => true, - 126529 => true, - 126531 => true, - 126532 => true, - 126533 => true, - 126534 => true, - 126536 => true, - 126538 => true, - 126540 => true, - 126544 => true, - 126547 => true, - 126549 => true, - 126550 => true, - 126552 => true, - 126554 => true, - 126556 => true, - 126558 => true, - 126560 => true, - 126563 => true, - 126565 => true, - 126566 => true, - 126571 => true, - 126579 => true, - 126584 => true, - 126589 => true, - 126591 => true, - 126602 => true, - 126620 => true, - 126621 => true, - 126622 => true, - 126623 => true, - 126624 => true, - 126628 => true, - 126634 => true, - 127020 => true, - 127021 => true, - 127022 => true, - 127023 => true, - 127124 => true, - 127125 => true, - 127126 => true, - 127127 => true, - 127128 => true, - 127129 => true, - 127130 => true, - 127131 => true, - 127132 => true, - 127133 => true, - 127134 => true, - 127135 => true, - 127151 => true, - 127152 => true, - 127168 => true, - 127184 => true, - 127222 => true, - 127223 => true, - 127224 => true, - 127225 => true, - 127226 => true, - 127227 => true, - 127228 => true, - 127229 => true, - 127230 => true, - 127231 => true, - 127232 => true, - 127491 => true, - 127492 => true, - 127493 => true, - 127494 => true, - 127495 => true, - 127496 => true, - 127497 => true, - 127498 => true, - 127499 => true, - 127500 => true, - 127501 => true, - 127502 => true, - 127503 => true, - 127548 => true, - 127549 => true, - 127550 => true, - 127551 => true, - 127561 => true, - 127562 => true, - 127563 => true, - 127564 => true, - 127565 => true, - 127566 => true, - 127567 => true, - 127570 => true, - 127571 => true, - 127572 => true, - 127573 => true, - 127574 => true, - 127575 => true, - 127576 => true, - 127577 => true, - 127578 => true, - 127579 => true, - 127580 => true, - 127581 => true, - 127582 => true, - 127583 => true, - 128728 => true, - 128729 => true, - 128730 => true, - 128731 => true, - 128732 => true, - 128733 => true, - 128734 => true, - 128735 => true, - 128749 => true, - 128750 => true, - 128751 => true, - 128765 => true, - 128766 => true, - 128767 => true, - 128884 => true, - 128885 => true, - 128886 => true, - 128887 => true, - 128888 => true, - 128889 => true, - 128890 => true, - 128891 => true, - 128892 => true, - 128893 => true, - 128894 => true, - 128895 => true, - 128985 => true, - 128986 => true, - 128987 => true, - 128988 => true, - 128989 => true, - 128990 => true, - 128991 => true, - 129004 => true, - 129005 => true, - 129006 => true, - 129007 => true, - 129008 => true, - 129009 => true, - 129010 => true, - 129011 => true, - 129012 => true, - 129013 => true, - 129014 => true, - 129015 => true, - 129016 => true, - 129017 => true, - 129018 => true, - 129019 => true, - 129020 => true, - 129021 => true, - 129022 => true, - 129023 => true, - 129036 => true, - 129037 => true, - 129038 => true, - 129039 => true, - 129096 => true, - 129097 => true, - 129098 => true, - 129099 => true, - 129100 => true, - 129101 => true, - 129102 => true, - 129103 => true, - 129114 => true, - 129115 => true, - 129116 => true, - 129117 => true, - 129118 => true, - 129119 => true, - 129160 => true, - 129161 => true, - 129162 => true, - 129163 => true, - 129164 => true, - 129165 => true, - 129166 => true, - 129167 => true, - 129198 => true, - 129199 => true, - 129401 => true, - 129484 => true, - 129620 => true, - 129621 => true, - 129622 => true, - 129623 => true, - 129624 => true, - 129625 => true, - 129626 => true, - 129627 => true, - 129628 => true, - 129629 => true, - 129630 => true, - 129631 => true, - 129646 => true, - 129647 => true, - 129653 => true, - 129654 => true, - 129655 => true, - 129659 => true, - 129660 => true, - 129661 => true, - 129662 => true, - 129663 => true, - 129671 => true, - 129672 => true, - 129673 => true, - 129674 => true, - 129675 => true, - 129676 => true, - 129677 => true, - 129678 => true, - 129679 => true, - 129705 => true, - 129706 => true, - 129707 => true, - 129708 => true, - 129709 => true, - 129710 => true, - 129711 => true, - 129719 => true, - 129720 => true, - 129721 => true, - 129722 => true, - 129723 => true, - 129724 => true, - 129725 => true, - 129726 => true, - 129727 => true, - 129731 => true, - 129732 => true, - 129733 => true, - 129734 => true, - 129735 => true, - 129736 => true, - 129737 => true, - 129738 => true, - 129739 => true, - 129740 => true, - 129741 => true, - 129742 => true, - 129743 => true, - 129939 => true, - 131070 => true, - 131071 => true, - 177973 => true, - 177974 => true, - 177975 => true, - 177976 => true, - 177977 => true, - 177978 => true, - 177979 => true, - 177980 => true, - 177981 => true, - 177982 => true, - 177983 => true, - 178206 => true, - 178207 => true, - 183970 => true, - 183971 => true, - 183972 => true, - 183973 => true, - 183974 => true, - 183975 => true, - 183976 => true, - 183977 => true, - 183978 => true, - 183979 => true, - 183980 => true, - 183981 => true, - 183982 => true, - 183983 => true, - 194664 => true, - 194676 => true, - 194847 => true, - 194911 => true, - 195007 => true, - 196606 => true, - 196607 => true, - 262142 => true, - 262143 => true, - 327678 => true, - 327679 => true, - 393214 => true, - 393215 => true, - 458750 => true, - 458751 => true, - 524286 => true, - 524287 => true, - 589822 => true, - 589823 => true, - 655358 => true, - 655359 => true, - 720894 => true, - 720895 => true, - 786430 => true, - 786431 => true, - 851966 => true, - 851967 => true, - 917502 => true, - 917503 => true, - 917504 => true, - 917505 => true, - 917506 => true, - 917507 => true, - 917508 => true, - 917509 => true, - 917510 => true, - 917511 => true, - 917512 => true, - 917513 => true, - 917514 => true, - 917515 => true, - 917516 => true, - 917517 => true, - 917518 => true, - 917519 => true, - 917520 => true, - 917521 => true, - 917522 => true, - 917523 => true, - 917524 => true, - 917525 => true, - 917526 => true, - 917527 => true, - 917528 => true, - 917529 => true, - 917530 => true, - 917531 => true, - 917532 => true, - 917533 => true, - 917534 => true, - 917535 => true, - 983038 => true, - 983039 => true, - 1048574 => true, - 1048575 => true, - 1114110 => true, - 1114111 => true, -); diff --git a/lib/symfony/polyfill-intl-idn/Resources/unidata/disallowed_STD3_mapped.php b/lib/symfony/polyfill-intl-idn/Resources/unidata/disallowed_STD3_mapped.php deleted file mode 100644 index 54f21cc0c..000000000 --- a/lib/symfony/polyfill-intl-idn/Resources/unidata/disallowed_STD3_mapped.php +++ /dev/null @@ -1,308 +0,0 @@ -<?php - -return array ( - 160 => ' ', - 168 => ' ̈', - 175 => ' ̄', - 180 => ' ́', - 184 => ' ̧', - 728 => ' ̆', - 729 => ' ̇', - 730 => ' ̊', - 731 => ' ̨', - 732 => ' ̃', - 733 => ' ̋', - 890 => ' ι', - 894 => ';', - 900 => ' ́', - 901 => ' ̈́', - 8125 => ' ̓', - 8127 => ' ̓', - 8128 => ' ͂', - 8129 => ' ̈͂', - 8141 => ' ̓̀', - 8142 => ' ̓́', - 8143 => ' ̓͂', - 8157 => ' ̔̀', - 8158 => ' ̔́', - 8159 => ' ̔͂', - 8173 => ' ̈̀', - 8174 => ' ̈́', - 8175 => '`', - 8189 => ' ́', - 8190 => ' ̔', - 8192 => ' ', - 8193 => ' ', - 8194 => ' ', - 8195 => ' ', - 8196 => ' ', - 8197 => ' ', - 8198 => ' ', - 8199 => ' ', - 8200 => ' ', - 8201 => ' ', - 8202 => ' ', - 8215 => ' ̳', - 8239 => ' ', - 8252 => '!!', - 8254 => ' ̅', - 8263 => '??', - 8264 => '?!', - 8265 => '!?', - 8287 => ' ', - 8314 => '+', - 8316 => '=', - 8317 => '(', - 8318 => ')', - 8330 => '+', - 8332 => '=', - 8333 => '(', - 8334 => ')', - 8448 => 'a/c', - 8449 => 'a/s', - 8453 => 'c/o', - 8454 => 'c/u', - 9332 => '(1)', - 9333 => '(2)', - 9334 => '(3)', - 9335 => '(4)', - 9336 => '(5)', - 9337 => '(6)', - 9338 => '(7)', - 9339 => '(8)', - 9340 => '(9)', - 9341 => '(10)', - 9342 => '(11)', - 9343 => '(12)', - 9344 => '(13)', - 9345 => '(14)', - 9346 => '(15)', - 9347 => '(16)', - 9348 => '(17)', - 9349 => '(18)', - 9350 => '(19)', - 9351 => '(20)', - 9372 => '(a)', - 9373 => '(b)', - 9374 => '(c)', - 9375 => '(d)', - 9376 => '(e)', - 9377 => '(f)', - 9378 => '(g)', - 9379 => '(h)', - 9380 => '(i)', - 9381 => '(j)', - 9382 => '(k)', - 9383 => '(l)', - 9384 => '(m)', - 9385 => '(n)', - 9386 => '(o)', - 9387 => '(p)', - 9388 => '(q)', - 9389 => '(r)', - 9390 => '(s)', - 9391 => '(t)', - 9392 => '(u)', - 9393 => '(v)', - 9394 => '(w)', - 9395 => '(x)', - 9396 => '(y)', - 9397 => '(z)', - 10868 => '::=', - 10869 => '==', - 10870 => '===', - 12288 => ' ', - 12443 => ' ゙', - 12444 => ' ゚', - 12800 => '(ᄀ)', - 12801 => '(ᄂ)', - 12802 => '(ᄃ)', - 12803 => '(ᄅ)', - 12804 => '(ᄆ)', - 12805 => '(ᄇ)', - 12806 => '(ᄉ)', - 12807 => '(ᄋ)', - 12808 => '(ᄌ)', - 12809 => '(ᄎ)', - 12810 => '(ᄏ)', - 12811 => '(ᄐ)', - 12812 => '(ᄑ)', - 12813 => '(ᄒ)', - 12814 => '(가)', - 12815 => '(나)', - 12816 => '(다)', - 12817 => '(라)', - 12818 => '(마)', - 12819 => '(바)', - 12820 => '(사)', - 12821 => '(아)', - 12822 => '(자)', - 12823 => '(차)', - 12824 => '(카)', - 12825 => '(타)', - 12826 => '(파)', - 12827 => '(하)', - 12828 => '(주)', - 12829 => '(오전)', - 12830 => '(오후)', - 12832 => '(一)', - 12833 => '(二)', - 12834 => '(三)', - 12835 => '(四)', - 12836 => '(五)', - 12837 => '(六)', - 12838 => '(七)', - 12839 => '(八)', - 12840 => '(九)', - 12841 => '(十)', - 12842 => '(月)', - 12843 => '(火)', - 12844 => '(水)', - 12845 => '(木)', - 12846 => '(金)', - 12847 => '(土)', - 12848 => '(日)', - 12849 => '(株)', - 12850 => '(有)', - 12851 => '(社)', - 12852 => '(名)', - 12853 => '(特)', - 12854 => '(財)', - 12855 => '(祝)', - 12856 => '(労)', - 12857 => '(代)', - 12858 => '(呼)', - 12859 => '(学)', - 12860 => '(監)', - 12861 => '(企)', - 12862 => '(資)', - 12863 => '(協)', - 12864 => '(祭)', - 12865 => '(休)', - 12866 => '(自)', - 12867 => '(至)', - 64297 => '+', - 64606 => ' ٌّ', - 64607 => ' ٍّ', - 64608 => ' َّ', - 64609 => ' ُّ', - 64610 => ' ِّ', - 64611 => ' ّٰ', - 65018 => 'صلى الله عليه وسلم', - 65019 => 'جل جلاله', - 65040 => ',', - 65043 => ':', - 65044 => ';', - 65045 => '!', - 65046 => '?', - 65075 => '_', - 65076 => '_', - 65077 => '(', - 65078 => ')', - 65079 => '{', - 65080 => '}', - 65095 => '[', - 65096 => ']', - 65097 => ' ̅', - 65098 => ' ̅', - 65099 => ' ̅', - 65100 => ' ̅', - 65101 => '_', - 65102 => '_', - 65103 => '_', - 65104 => ',', - 65108 => ';', - 65109 => ':', - 65110 => '?', - 65111 => '!', - 65113 => '(', - 65114 => ')', - 65115 => '{', - 65116 => '}', - 65119 => '#', - 65120 => '&', - 65121 => '*', - 65122 => '+', - 65124 => '<', - 65125 => '>', - 65126 => '=', - 65128 => '\\', - 65129 => '$', - 65130 => '%', - 65131 => '@', - 65136 => ' ً', - 65138 => ' ٌ', - 65140 => ' ٍ', - 65142 => ' َ', - 65144 => ' ُ', - 65146 => ' ِ', - 65148 => ' ّ', - 65150 => ' ْ', - 65281 => '!', - 65282 => '"', - 65283 => '#', - 65284 => '$', - 65285 => '%', - 65286 => '&', - 65287 => '\'', - 65288 => '(', - 65289 => ')', - 65290 => '*', - 65291 => '+', - 65292 => ',', - 65295 => '/', - 65306 => ':', - 65307 => ';', - 65308 => '<', - 65309 => '=', - 65310 => '>', - 65311 => '?', - 65312 => '@', - 65339 => '[', - 65340 => '\\', - 65341 => ']', - 65342 => '^', - 65343 => '_', - 65344 => '`', - 65371 => '{', - 65372 => '|', - 65373 => '}', - 65374 => '~', - 65507 => ' ̄', - 127233 => '0,', - 127234 => '1,', - 127235 => '2,', - 127236 => '3,', - 127237 => '4,', - 127238 => '5,', - 127239 => '6,', - 127240 => '7,', - 127241 => '8,', - 127242 => '9,', - 127248 => '(a)', - 127249 => '(b)', - 127250 => '(c)', - 127251 => '(d)', - 127252 => '(e)', - 127253 => '(f)', - 127254 => '(g)', - 127255 => '(h)', - 127256 => '(i)', - 127257 => '(j)', - 127258 => '(k)', - 127259 => '(l)', - 127260 => '(m)', - 127261 => '(n)', - 127262 => '(o)', - 127263 => '(p)', - 127264 => '(q)', - 127265 => '(r)', - 127266 => '(s)', - 127267 => '(t)', - 127268 => '(u)', - 127269 => '(v)', - 127270 => '(w)', - 127271 => '(x)', - 127272 => '(y)', - 127273 => '(z)', -); diff --git a/lib/symfony/polyfill-intl-idn/Resources/unidata/disallowed_STD3_valid.php b/lib/symfony/polyfill-intl-idn/Resources/unidata/disallowed_STD3_valid.php deleted file mode 100644 index 223396ec4..000000000 --- a/lib/symfony/polyfill-intl-idn/Resources/unidata/disallowed_STD3_valid.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php - -return array ( - 0 => true, - 1 => true, - 2 => true, - 3 => true, - 4 => true, - 5 => true, - 6 => true, - 7 => true, - 8 => true, - 9 => true, - 10 => true, - 11 => true, - 12 => true, - 13 => true, - 14 => true, - 15 => true, - 16 => true, - 17 => true, - 18 => true, - 19 => true, - 20 => true, - 21 => true, - 22 => true, - 23 => true, - 24 => true, - 25 => true, - 26 => true, - 27 => true, - 28 => true, - 29 => true, - 30 => true, - 31 => true, - 32 => true, - 33 => true, - 34 => true, - 35 => true, - 36 => true, - 37 => true, - 38 => true, - 39 => true, - 40 => true, - 41 => true, - 42 => true, - 43 => true, - 44 => true, - 47 => true, - 58 => true, - 59 => true, - 60 => true, - 61 => true, - 62 => true, - 63 => true, - 64 => true, - 91 => true, - 92 => true, - 93 => true, - 94 => true, - 95 => true, - 96 => true, - 123 => true, - 124 => true, - 125 => true, - 126 => true, - 127 => true, - 8800 => true, - 8814 => true, - 8815 => true, -); diff --git a/lib/symfony/polyfill-intl-idn/Resources/unidata/ignored.php b/lib/symfony/polyfill-intl-idn/Resources/unidata/ignored.php deleted file mode 100644 index b37784413..000000000 --- a/lib/symfony/polyfill-intl-idn/Resources/unidata/ignored.php +++ /dev/null @@ -1,273 +0,0 @@ -<?php - -return array ( - 173 => true, - 847 => true, - 6155 => true, - 6156 => true, - 6157 => true, - 8203 => true, - 8288 => true, - 8292 => true, - 65024 => true, - 65025 => true, - 65026 => true, - 65027 => true, - 65028 => true, - 65029 => true, - 65030 => true, - 65031 => true, - 65032 => true, - 65033 => true, - 65034 => true, - 65035 => true, - 65036 => true, - 65037 => true, - 65038 => true, - 65039 => true, - 65279 => true, - 113824 => true, - 113825 => true, - 113826 => true, - 113827 => true, - 917760 => true, - 917761 => true, - 917762 => true, - 917763 => true, - 917764 => true, - 917765 => true, - 917766 => true, - 917767 => true, - 917768 => true, - 917769 => true, - 917770 => true, - 917771 => true, - 917772 => true, - 917773 => true, - 917774 => true, - 917775 => true, - 917776 => true, - 917777 => true, - 917778 => true, - 917779 => true, - 917780 => true, - 917781 => true, - 917782 => true, - 917783 => true, - 917784 => true, - 917785 => true, - 917786 => true, - 917787 => true, - 917788 => true, - 917789 => true, - 917790 => true, - 917791 => true, - 917792 => true, - 917793 => true, - 917794 => true, - 917795 => true, - 917796 => true, - 917797 => true, - 917798 => true, - 917799 => true, - 917800 => true, - 917801 => true, - 917802 => true, - 917803 => true, - 917804 => true, - 917805 => true, - 917806 => true, - 917807 => true, - 917808 => true, - 917809 => true, - 917810 => true, - 917811 => true, - 917812 => true, - 917813 => true, - 917814 => true, - 917815 => true, - 917816 => true, - 917817 => true, - 917818 => true, - 917819 => true, - 917820 => true, - 917821 => true, - 917822 => true, - 917823 => true, - 917824 => true, - 917825 => true, - 917826 => true, - 917827 => true, - 917828 => true, - 917829 => true, - 917830 => true, - 917831 => true, - 917832 => true, - 917833 => true, - 917834 => true, - 917835 => true, - 917836 => true, - 917837 => true, - 917838 => true, - 917839 => true, - 917840 => true, - 917841 => true, - 917842 => true, - 917843 => true, - 917844 => true, - 917845 => true, - 917846 => true, - 917847 => true, - 917848 => true, - 917849 => true, - 917850 => true, - 917851 => true, - 917852 => true, - 917853 => true, - 917854 => true, - 917855 => true, - 917856 => true, - 917857 => true, - 917858 => true, - 917859 => true, - 917860 => true, - 917861 => true, - 917862 => true, - 917863 => true, - 917864 => true, - 917865 => true, - 917866 => true, - 917867 => true, - 917868 => true, - 917869 => true, - 917870 => true, - 917871 => true, - 917872 => true, - 917873 => true, - 917874 => true, - 917875 => true, - 917876 => true, - 917877 => true, - 917878 => true, - 917879 => true, - 917880 => true, - 917881 => true, - 917882 => true, - 917883 => true, - 917884 => true, - 917885 => true, - 917886 => true, - 917887 => true, - 917888 => true, - 917889 => true, - 917890 => true, - 917891 => true, - 917892 => true, - 917893 => true, - 917894 => true, - 917895 => true, - 917896 => true, - 917897 => true, - 917898 => true, - 917899 => true, - 917900 => true, - 917901 => true, - 917902 => true, - 917903 => true, - 917904 => true, - 917905 => true, - 917906 => true, - 917907 => true, - 917908 => true, - 917909 => true, - 917910 => true, - 917911 => true, - 917912 => true, - 917913 => true, - 917914 => true, - 917915 => true, - 917916 => true, - 917917 => true, - 917918 => true, - 917919 => true, - 917920 => true, - 917921 => true, - 917922 => true, - 917923 => true, - 917924 => true, - 917925 => true, - 917926 => true, - 917927 => true, - 917928 => true, - 917929 => true, - 917930 => true, - 917931 => true, - 917932 => true, - 917933 => true, - 917934 => true, - 917935 => true, - 917936 => true, - 917937 => true, - 917938 => true, - 917939 => true, - 917940 => true, - 917941 => true, - 917942 => true, - 917943 => true, - 917944 => true, - 917945 => true, - 917946 => true, - 917947 => true, - 917948 => true, - 917949 => true, - 917950 => true, - 917951 => true, - 917952 => true, - 917953 => true, - 917954 => true, - 917955 => true, - 917956 => true, - 917957 => true, - 917958 => true, - 917959 => true, - 917960 => true, - 917961 => true, - 917962 => true, - 917963 => true, - 917964 => true, - 917965 => true, - 917966 => true, - 917967 => true, - 917968 => true, - 917969 => true, - 917970 => true, - 917971 => true, - 917972 => true, - 917973 => true, - 917974 => true, - 917975 => true, - 917976 => true, - 917977 => true, - 917978 => true, - 917979 => true, - 917980 => true, - 917981 => true, - 917982 => true, - 917983 => true, - 917984 => true, - 917985 => true, - 917986 => true, - 917987 => true, - 917988 => true, - 917989 => true, - 917990 => true, - 917991 => true, - 917992 => true, - 917993 => true, - 917994 => true, - 917995 => true, - 917996 => true, - 917997 => true, - 917998 => true, - 917999 => true, -); diff --git a/lib/symfony/polyfill-intl-idn/Resources/unidata/mapped.php b/lib/symfony/polyfill-intl-idn/Resources/unidata/mapped.php deleted file mode 100644 index 9b85fe9d3..000000000 --- a/lib/symfony/polyfill-intl-idn/Resources/unidata/mapped.php +++ /dev/null @@ -1,5778 +0,0 @@ -<?php - -return array ( - 65 => 'a', - 66 => 'b', - 67 => 'c', - 68 => 'd', - 69 => 'e', - 70 => 'f', - 71 => 'g', - 72 => 'h', - 73 => 'i', - 74 => 'j', - 75 => 'k', - 76 => 'l', - 77 => 'm', - 78 => 'n', - 79 => 'o', - 80 => 'p', - 81 => 'q', - 82 => 'r', - 83 => 's', - 84 => 't', - 85 => 'u', - 86 => 'v', - 87 => 'w', - 88 => 'x', - 89 => 'y', - 90 => 'z', - 170 => 'a', - 178 => '2', - 179 => '3', - 181 => 'μ', - 185 => '1', - 186 => 'o', - 188 => '1⁄4', - 189 => '1⁄2', - 190 => '3⁄4', - 192 => 'à', - 193 => 'á', - 194 => 'â', - 195 => 'ã', - 196 => 'ä', - 197 => 'å', - 198 => 'æ', - 199 => 'ç', - 200 => 'è', - 201 => 'é', - 202 => 'ê', - 203 => 'ë', - 204 => 'ì', - 205 => 'í', - 206 => 'î', - 207 => 'ï', - 208 => 'ð', - 209 => 'ñ', - 210 => 'ò', - 211 => 'ó', - 212 => 'ô', - 213 => 'õ', - 214 => 'ö', - 216 => 'ø', - 217 => 'ù', - 218 => 'ú', - 219 => 'û', - 220 => 'ü', - 221 => 'ý', - 222 => 'þ', - 256 => 'ā', - 258 => 'ă', - 260 => 'ą', - 262 => 'ć', - 264 => 'ĉ', - 266 => 'ċ', - 268 => 'č', - 270 => 'ď', - 272 => 'đ', - 274 => 'ē', - 276 => 'ĕ', - 278 => 'ė', - 280 => 'ę', - 282 => 'ě', - 284 => 'ĝ', - 286 => 'ğ', - 288 => 'ġ', - 290 => 'ģ', - 292 => 'ĥ', - 294 => 'ħ', - 296 => 'ĩ', - 298 => 'ī', - 300 => 'ĭ', - 302 => 'į', - 304 => 'i̇', - 306 => 'ij', - 307 => 'ij', - 308 => 'ĵ', - 310 => 'ķ', - 313 => 'ĺ', - 315 => 'ļ', - 317 => 'ľ', - 319 => 'l·', - 320 => 'l·', - 321 => 'ł', - 323 => 'ń', - 325 => 'ņ', - 327 => 'ň', - 329 => 'ʼn', - 330 => 'ŋ', - 332 => 'ō', - 334 => 'ŏ', - 336 => 'ő', - 338 => 'œ', - 340 => 'ŕ', - 342 => 'ŗ', - 344 => 'ř', - 346 => 'ś', - 348 => 'ŝ', - 350 => 'ş', - 352 => 'š', - 354 => 'ţ', - 356 => 'ť', - 358 => 'ŧ', - 360 => 'ũ', - 362 => 'ū', - 364 => 'ŭ', - 366 => 'ů', - 368 => 'ű', - 370 => 'ų', - 372 => 'ŵ', - 374 => 'ŷ', - 376 => 'ÿ', - 377 => 'ź', - 379 => 'ż', - 381 => 'ž', - 383 => 's', - 385 => 'ɓ', - 386 => 'ƃ', - 388 => 'ƅ', - 390 => 'ɔ', - 391 => 'ƈ', - 393 => 'ɖ', - 394 => 'ɗ', - 395 => 'ƌ', - 398 => 'ǝ', - 399 => 'ə', - 400 => 'ɛ', - 401 => 'ƒ', - 403 => 'ɠ', - 404 => 'ɣ', - 406 => 'ɩ', - 407 => 'ɨ', - 408 => 'ƙ', - 412 => 'ɯ', - 413 => 'ɲ', - 415 => 'ɵ', - 416 => 'ơ', - 418 => 'ƣ', - 420 => 'ƥ', - 422 => 'ʀ', - 423 => 'ƨ', - 425 => 'ʃ', - 428 => 'ƭ', - 430 => 'ʈ', - 431 => 'ư', - 433 => 'ʊ', - 434 => 'ʋ', - 435 => 'ƴ', - 437 => 'ƶ', - 439 => 'ʒ', - 440 => 'ƹ', - 444 => 'ƽ', - 452 => 'dž', - 453 => 'dž', - 454 => 'dž', - 455 => 'lj', - 456 => 'lj', - 457 => 'lj', - 458 => 'nj', - 459 => 'nj', - 460 => 'nj', - 461 => 'ǎ', - 463 => 'ǐ', - 465 => 'ǒ', - 467 => 'ǔ', - 469 => 'ǖ', - 471 => 'ǘ', - 473 => 'ǚ', - 475 => 'ǜ', - 478 => 'ǟ', - 480 => 'ǡ', - 482 => 'ǣ', - 484 => 'ǥ', - 486 => 'ǧ', - 488 => 'ǩ', - 490 => 'ǫ', - 492 => 'ǭ', - 494 => 'ǯ', - 497 => 'dz', - 498 => 'dz', - 499 => 'dz', - 500 => 'ǵ', - 502 => 'ƕ', - 503 => 'ƿ', - 504 => 'ǹ', - 506 => 'ǻ', - 508 => 'ǽ', - 510 => 'ǿ', - 512 => 'ȁ', - 514 => 'ȃ', - 516 => 'ȅ', - 518 => 'ȇ', - 520 => 'ȉ', - 522 => 'ȋ', - 524 => 'ȍ', - 526 => 'ȏ', - 528 => 'ȑ', - 530 => 'ȓ', - 532 => 'ȕ', - 534 => 'ȗ', - 536 => 'ș', - 538 => 'ț', - 540 => 'ȝ', - 542 => 'ȟ', - 544 => 'ƞ', - 546 => 'ȣ', - 548 => 'ȥ', - 550 => 'ȧ', - 552 => 'ȩ', - 554 => 'ȫ', - 556 => 'ȭ', - 558 => 'ȯ', - 560 => 'ȱ', - 562 => 'ȳ', - 570 => 'ⱥ', - 571 => 'ȼ', - 573 => 'ƚ', - 574 => 'ⱦ', - 577 => 'ɂ', - 579 => 'ƀ', - 580 => 'ʉ', - 581 => 'ʌ', - 582 => 'ɇ', - 584 => 'ɉ', - 586 => 'ɋ', - 588 => 'ɍ', - 590 => 'ɏ', - 688 => 'h', - 689 => 'ɦ', - 690 => 'j', - 691 => 'r', - 692 => 'ɹ', - 693 => 'ɻ', - 694 => 'ʁ', - 695 => 'w', - 696 => 'y', - 736 => 'ɣ', - 737 => 'l', - 738 => 's', - 739 => 'x', - 740 => 'ʕ', - 832 => '̀', - 833 => '́', - 835 => '̓', - 836 => '̈́', - 837 => 'ι', - 880 => 'ͱ', - 882 => 'ͳ', - 884 => 'ʹ', - 886 => 'ͷ', - 895 => 'ϳ', - 902 => 'ά', - 903 => '·', - 904 => 'έ', - 905 => 'ή', - 906 => 'ί', - 908 => 'ό', - 910 => 'ύ', - 911 => 'ώ', - 913 => 'α', - 914 => 'β', - 915 => 'γ', - 916 => 'δ', - 917 => 'ε', - 918 => 'ζ', - 919 => 'η', - 920 => 'θ', - 921 => 'ι', - 922 => 'κ', - 923 => 'λ', - 924 => 'μ', - 925 => 'ν', - 926 => 'ξ', - 927 => 'ο', - 928 => 'π', - 929 => 'ρ', - 931 => 'σ', - 932 => 'τ', - 933 => 'υ', - 934 => 'φ', - 935 => 'χ', - 936 => 'ψ', - 937 => 'ω', - 938 => 'ϊ', - 939 => 'ϋ', - 975 => 'ϗ', - 976 => 'β', - 977 => 'θ', - 978 => 'υ', - 979 => 'ύ', - 980 => 'ϋ', - 981 => 'φ', - 982 => 'π', - 984 => 'ϙ', - 986 => 'ϛ', - 988 => 'ϝ', - 990 => 'ϟ', - 992 => 'ϡ', - 994 => 'ϣ', - 996 => 'ϥ', - 998 => 'ϧ', - 1000 => 'ϩ', - 1002 => 'ϫ', - 1004 => 'ϭ', - 1006 => 'ϯ', - 1008 => 'κ', - 1009 => 'ρ', - 1010 => 'σ', - 1012 => 'θ', - 1013 => 'ε', - 1015 => 'ϸ', - 1017 => 'σ', - 1018 => 'ϻ', - 1021 => 'ͻ', - 1022 => 'ͼ', - 1023 => 'ͽ', - 1024 => 'ѐ', - 1025 => 'ё', - 1026 => 'ђ', - 1027 => 'ѓ', - 1028 => 'є', - 1029 => 'ѕ', - 1030 => 'і', - 1031 => 'ї', - 1032 => 'ј', - 1033 => 'љ', - 1034 => 'њ', - 1035 => 'ћ', - 1036 => 'ќ', - 1037 => 'ѝ', - 1038 => 'ў', - 1039 => 'џ', - 1040 => 'а', - 1041 => 'б', - 1042 => 'в', - 1043 => 'г', - 1044 => 'д', - 1045 => 'е', - 1046 => 'ж', - 1047 => 'з', - 1048 => 'и', - 1049 => 'й', - 1050 => 'к', - 1051 => 'л', - 1052 => 'м', - 1053 => 'н', - 1054 => 'о', - 1055 => 'п', - 1056 => 'р', - 1057 => 'с', - 1058 => 'т', - 1059 => 'у', - 1060 => 'ф', - 1061 => 'х', - 1062 => 'ц', - 1063 => 'ч', - 1064 => 'ш', - 1065 => 'щ', - 1066 => 'ъ', - 1067 => 'ы', - 1068 => 'ь', - 1069 => 'э', - 1070 => 'ю', - 1071 => 'я', - 1120 => 'ѡ', - 1122 => 'ѣ', - 1124 => 'ѥ', - 1126 => 'ѧ', - 1128 => 'ѩ', - 1130 => 'ѫ', - 1132 => 'ѭ', - 1134 => 'ѯ', - 1136 => 'ѱ', - 1138 => 'ѳ', - 1140 => 'ѵ', - 1142 => 'ѷ', - 1144 => 'ѹ', - 1146 => 'ѻ', - 1148 => 'ѽ', - 1150 => 'ѿ', - 1152 => 'ҁ', - 1162 => 'ҋ', - 1164 => 'ҍ', - 1166 => 'ҏ', - 1168 => 'ґ', - 1170 => 'ғ', - 1172 => 'ҕ', - 1174 => 'җ', - 1176 => 'ҙ', - 1178 => 'қ', - 1180 => 'ҝ', - 1182 => 'ҟ', - 1184 => 'ҡ', - 1186 => 'ң', - 1188 => 'ҥ', - 1190 => 'ҧ', - 1192 => 'ҩ', - 1194 => 'ҫ', - 1196 => 'ҭ', - 1198 => 'ү', - 1200 => 'ұ', - 1202 => 'ҳ', - 1204 => 'ҵ', - 1206 => 'ҷ', - 1208 => 'ҹ', - 1210 => 'һ', - 1212 => 'ҽ', - 1214 => 'ҿ', - 1217 => 'ӂ', - 1219 => 'ӄ', - 1221 => 'ӆ', - 1223 => 'ӈ', - 1225 => 'ӊ', - 1227 => 'ӌ', - 1229 => 'ӎ', - 1232 => 'ӑ', - 1234 => 'ӓ', - 1236 => 'ӕ', - 1238 => 'ӗ', - 1240 => 'ә', - 1242 => 'ӛ', - 1244 => 'ӝ', - 1246 => 'ӟ', - 1248 => 'ӡ', - 1250 => 'ӣ', - 1252 => 'ӥ', - 1254 => 'ӧ', - 1256 => 'ө', - 1258 => 'ӫ', - 1260 => 'ӭ', - 1262 => 'ӯ', - 1264 => 'ӱ', - 1266 => 'ӳ', - 1268 => 'ӵ', - 1270 => 'ӷ', - 1272 => 'ӹ', - 1274 => 'ӻ', - 1276 => 'ӽ', - 1278 => 'ӿ', - 1280 => 'ԁ', - 1282 => 'ԃ', - 1284 => 'ԅ', - 1286 => 'ԇ', - 1288 => 'ԉ', - 1290 => 'ԋ', - 1292 => 'ԍ', - 1294 => 'ԏ', - 1296 => 'ԑ', - 1298 => 'ԓ', - 1300 => 'ԕ', - 1302 => 'ԗ', - 1304 => 'ԙ', - 1306 => 'ԛ', - 1308 => 'ԝ', - 1310 => 'ԟ', - 1312 => 'ԡ', - 1314 => 'ԣ', - 1316 => 'ԥ', - 1318 => 'ԧ', - 1320 => 'ԩ', - 1322 => 'ԫ', - 1324 => 'ԭ', - 1326 => 'ԯ', - 1329 => 'ա', - 1330 => 'բ', - 1331 => 'գ', - 1332 => 'դ', - 1333 => 'ե', - 1334 => 'զ', - 1335 => 'է', - 1336 => 'ը', - 1337 => 'թ', - 1338 => 'ժ', - 1339 => 'ի', - 1340 => 'լ', - 1341 => 'խ', - 1342 => 'ծ', - 1343 => 'կ', - 1344 => 'հ', - 1345 => 'ձ', - 1346 => 'ղ', - 1347 => 'ճ', - 1348 => 'մ', - 1349 => 'յ', - 1350 => 'ն', - 1351 => 'շ', - 1352 => 'ո', - 1353 => 'չ', - 1354 => 'պ', - 1355 => 'ջ', - 1356 => 'ռ', - 1357 => 'ս', - 1358 => 'վ', - 1359 => 'տ', - 1360 => 'ր', - 1361 => 'ց', - 1362 => 'ւ', - 1363 => 'փ', - 1364 => 'ք', - 1365 => 'օ', - 1366 => 'ֆ', - 1415 => 'եւ', - 1653 => 'اٴ', - 1654 => 'وٴ', - 1655 => 'ۇٴ', - 1656 => 'يٴ', - 2392 => 'क़', - 2393 => 'ख़', - 2394 => 'ग़', - 2395 => 'ज़', - 2396 => 'ड़', - 2397 => 'ढ़', - 2398 => 'फ़', - 2399 => 'य़', - 2524 => 'ড়', - 2525 => 'ঢ়', - 2527 => 'য়', - 2611 => 'ਲ਼', - 2614 => 'ਸ਼', - 2649 => 'ਖ਼', - 2650 => 'ਗ਼', - 2651 => 'ਜ਼', - 2654 => 'ਫ਼', - 2908 => 'ଡ଼', - 2909 => 'ଢ଼', - 3635 => 'ํา', - 3763 => 'ໍາ', - 3804 => 'ຫນ', - 3805 => 'ຫມ', - 3852 => '་', - 3907 => 'གྷ', - 3917 => 'ཌྷ', - 3922 => 'དྷ', - 3927 => 'བྷ', - 3932 => 'ཛྷ', - 3945 => 'ཀྵ', - 3955 => 'ཱི', - 3957 => 'ཱུ', - 3958 => 'ྲྀ', - 3959 => 'ྲཱྀ', - 3960 => 'ླྀ', - 3961 => 'ླཱྀ', - 3969 => 'ཱྀ', - 3987 => 'ྒྷ', - 3997 => 'ྜྷ', - 4002 => 'ྡྷ', - 4007 => 'ྦྷ', - 4012 => 'ྫྷ', - 4025 => 'ྐྵ', - 4295 => 'ⴧ', - 4301 => 'ⴭ', - 4348 => 'ნ', - 5112 => 'Ᏸ', - 5113 => 'Ᏹ', - 5114 => 'Ᏺ', - 5115 => 'Ᏻ', - 5116 => 'Ᏼ', - 5117 => 'Ᏽ', - 7296 => 'в', - 7297 => 'д', - 7298 => 'о', - 7299 => 'с', - 7300 => 'т', - 7301 => 'т', - 7302 => 'ъ', - 7303 => 'ѣ', - 7304 => 'ꙋ', - 7312 => 'ა', - 7313 => 'ბ', - 7314 => 'გ', - 7315 => 'დ', - 7316 => 'ე', - 7317 => 'ვ', - 7318 => 'ზ', - 7319 => 'თ', - 7320 => 'ი', - 7321 => 'კ', - 7322 => 'ლ', - 7323 => 'მ', - 7324 => 'ნ', - 7325 => 'ო', - 7326 => 'პ', - 7327 => 'ჟ', - 7328 => 'რ', - 7329 => 'ს', - 7330 => 'ტ', - 7331 => 'უ', - 7332 => 'ფ', - 7333 => 'ქ', - 7334 => 'ღ', - 7335 => 'ყ', - 7336 => 'შ', - 7337 => 'ჩ', - 7338 => 'ც', - 7339 => 'ძ', - 7340 => 'წ', - 7341 => 'ჭ', - 7342 => 'ხ', - 7343 => 'ჯ', - 7344 => 'ჰ', - 7345 => 'ჱ', - 7346 => 'ჲ', - 7347 => 'ჳ', - 7348 => 'ჴ', - 7349 => 'ჵ', - 7350 => 'ჶ', - 7351 => 'ჷ', - 7352 => 'ჸ', - 7353 => 'ჹ', - 7354 => 'ჺ', - 7357 => 'ჽ', - 7358 => 'ჾ', - 7359 => 'ჿ', - 7468 => 'a', - 7469 => 'æ', - 7470 => 'b', - 7472 => 'd', - 7473 => 'e', - 7474 => 'ǝ', - 7475 => 'g', - 7476 => 'h', - 7477 => 'i', - 7478 => 'j', - 7479 => 'k', - 7480 => 'l', - 7481 => 'm', - 7482 => 'n', - 7484 => 'o', - 7485 => 'ȣ', - 7486 => 'p', - 7487 => 'r', - 7488 => 't', - 7489 => 'u', - 7490 => 'w', - 7491 => 'a', - 7492 => 'ɐ', - 7493 => 'ɑ', - 7494 => 'ᴂ', - 7495 => 'b', - 7496 => 'd', - 7497 => 'e', - 7498 => 'ə', - 7499 => 'ɛ', - 7500 => 'ɜ', - 7501 => 'g', - 7503 => 'k', - 7504 => 'm', - 7505 => 'ŋ', - 7506 => 'o', - 7507 => 'ɔ', - 7508 => 'ᴖ', - 7509 => 'ᴗ', - 7510 => 'p', - 7511 => 't', - 7512 => 'u', - 7513 => 'ᴝ', - 7514 => 'ɯ', - 7515 => 'v', - 7516 => 'ᴥ', - 7517 => 'β', - 7518 => 'γ', - 7519 => 'δ', - 7520 => 'φ', - 7521 => 'χ', - 7522 => 'i', - 7523 => 'r', - 7524 => 'u', - 7525 => 'v', - 7526 => 'β', - 7527 => 'γ', - 7528 => 'ρ', - 7529 => 'φ', - 7530 => 'χ', - 7544 => 'н', - 7579 => 'ɒ', - 7580 => 'c', - 7581 => 'ɕ', - 7582 => 'ð', - 7583 => 'ɜ', - 7584 => 'f', - 7585 => 'ɟ', - 7586 => 'ɡ', - 7587 => 'ɥ', - 7588 => 'ɨ', - 7589 => 'ɩ', - 7590 => 'ɪ', - 7591 => 'ᵻ', - 7592 => 'ʝ', - 7593 => 'ɭ', - 7594 => 'ᶅ', - 7595 => 'ʟ', - 7596 => 'ɱ', - 7597 => 'ɰ', - 7598 => 'ɲ', - 7599 => 'ɳ', - 7600 => 'ɴ', - 7601 => 'ɵ', - 7602 => 'ɸ', - 7603 => 'ʂ', - 7604 => 'ʃ', - 7605 => 'ƫ', - 7606 => 'ʉ', - 7607 => 'ʊ', - 7608 => 'ᴜ', - 7609 => 'ʋ', - 7610 => 'ʌ', - 7611 => 'z', - 7612 => 'ʐ', - 7613 => 'ʑ', - 7614 => 'ʒ', - 7615 => 'θ', - 7680 => 'ḁ', - 7682 => 'ḃ', - 7684 => 'ḅ', - 7686 => 'ḇ', - 7688 => 'ḉ', - 7690 => 'ḋ', - 7692 => 'ḍ', - 7694 => 'ḏ', - 7696 => 'ḑ', - 7698 => 'ḓ', - 7700 => 'ḕ', - 7702 => 'ḗ', - 7704 => 'ḙ', - 7706 => 'ḛ', - 7708 => 'ḝ', - 7710 => 'ḟ', - 7712 => 'ḡ', - 7714 => 'ḣ', - 7716 => 'ḥ', - 7718 => 'ḧ', - 7720 => 'ḩ', - 7722 => 'ḫ', - 7724 => 'ḭ', - 7726 => 'ḯ', - 7728 => 'ḱ', - 7730 => 'ḳ', - 7732 => 'ḵ', - 7734 => 'ḷ', - 7736 => 'ḹ', - 7738 => 'ḻ', - 7740 => 'ḽ', - 7742 => 'ḿ', - 7744 => 'ṁ', - 7746 => 'ṃ', - 7748 => 'ṅ', - 7750 => 'ṇ', - 7752 => 'ṉ', - 7754 => 'ṋ', - 7756 => 'ṍ', - 7758 => 'ṏ', - 7760 => 'ṑ', - 7762 => 'ṓ', - 7764 => 'ṕ', - 7766 => 'ṗ', - 7768 => 'ṙ', - 7770 => 'ṛ', - 7772 => 'ṝ', - 7774 => 'ṟ', - 7776 => 'ṡ', - 7778 => 'ṣ', - 7780 => 'ṥ', - 7782 => 'ṧ', - 7784 => 'ṩ', - 7786 => 'ṫ', - 7788 => 'ṭ', - 7790 => 'ṯ', - 7792 => 'ṱ', - 7794 => 'ṳ', - 7796 => 'ṵ', - 7798 => 'ṷ', - 7800 => 'ṹ', - 7802 => 'ṻ', - 7804 => 'ṽ', - 7806 => 'ṿ', - 7808 => 'ẁ', - 7810 => 'ẃ', - 7812 => 'ẅ', - 7814 => 'ẇ', - 7816 => 'ẉ', - 7818 => 'ẋ', - 7820 => 'ẍ', - 7822 => 'ẏ', - 7824 => 'ẑ', - 7826 => 'ẓ', - 7828 => 'ẕ', - 7834 => 'aʾ', - 7835 => 'ṡ', - 7838 => 'ss', - 7840 => 'ạ', - 7842 => 'ả', - 7844 => 'ấ', - 7846 => 'ầ', - 7848 => 'ẩ', - 7850 => 'ẫ', - 7852 => 'ậ', - 7854 => 'ắ', - 7856 => 'ằ', - 7858 => 'ẳ', - 7860 => 'ẵ', - 7862 => 'ặ', - 7864 => 'ẹ', - 7866 => 'ẻ', - 7868 => 'ẽ', - 7870 => 'ế', - 7872 => 'ề', - 7874 => 'ể', - 7876 => 'ễ', - 7878 => 'ệ', - 7880 => 'ỉ', - 7882 => 'ị', - 7884 => 'ọ', - 7886 => 'ỏ', - 7888 => 'ố', - 7890 => 'ồ', - 7892 => 'ổ', - 7894 => 'ỗ', - 7896 => 'ộ', - 7898 => 'ớ', - 7900 => 'ờ', - 7902 => 'ở', - 7904 => 'ỡ', - 7906 => 'ợ', - 7908 => 'ụ', - 7910 => 'ủ', - 7912 => 'ứ', - 7914 => 'ừ', - 7916 => 'ử', - 7918 => 'ữ', - 7920 => 'ự', - 7922 => 'ỳ', - 7924 => 'ỵ', - 7926 => 'ỷ', - 7928 => 'ỹ', - 7930 => 'ỻ', - 7932 => 'ỽ', - 7934 => 'ỿ', - 7944 => 'ἀ', - 7945 => 'ἁ', - 7946 => 'ἂ', - 7947 => 'ἃ', - 7948 => 'ἄ', - 7949 => 'ἅ', - 7950 => 'ἆ', - 7951 => 'ἇ', - 7960 => 'ἐ', - 7961 => 'ἑ', - 7962 => 'ἒ', - 7963 => 'ἓ', - 7964 => 'ἔ', - 7965 => 'ἕ', - 7976 => 'ἠ', - 7977 => 'ἡ', - 7978 => 'ἢ', - 7979 => 'ἣ', - 7980 => 'ἤ', - 7981 => 'ἥ', - 7982 => 'ἦ', - 7983 => 'ἧ', - 7992 => 'ἰ', - 7993 => 'ἱ', - 7994 => 'ἲ', - 7995 => 'ἳ', - 7996 => 'ἴ', - 7997 => 'ἵ', - 7998 => 'ἶ', - 7999 => 'ἷ', - 8008 => 'ὀ', - 8009 => 'ὁ', - 8010 => 'ὂ', - 8011 => 'ὃ', - 8012 => 'ὄ', - 8013 => 'ὅ', - 8025 => 'ὑ', - 8027 => 'ὓ', - 8029 => 'ὕ', - 8031 => 'ὗ', - 8040 => 'ὠ', - 8041 => 'ὡ', - 8042 => 'ὢ', - 8043 => 'ὣ', - 8044 => 'ὤ', - 8045 => 'ὥ', - 8046 => 'ὦ', - 8047 => 'ὧ', - 8049 => 'ά', - 8051 => 'έ', - 8053 => 'ή', - 8055 => 'ί', - 8057 => 'ό', - 8059 => 'ύ', - 8061 => 'ώ', - 8064 => 'ἀι', - 8065 => 'ἁι', - 8066 => 'ἂι', - 8067 => 'ἃι', - 8068 => 'ἄι', - 8069 => 'ἅι', - 8070 => 'ἆι', - 8071 => 'ἇι', - 8072 => 'ἀι', - 8073 => 'ἁι', - 8074 => 'ἂι', - 8075 => 'ἃι', - 8076 => 'ἄι', - 8077 => 'ἅι', - 8078 => 'ἆι', - 8079 => 'ἇι', - 8080 => 'ἠι', - 8081 => 'ἡι', - 8082 => 'ἢι', - 8083 => 'ἣι', - 8084 => 'ἤι', - 8085 => 'ἥι', - 8086 => 'ἦι', - 8087 => 'ἧι', - 8088 => 'ἠι', - 8089 => 'ἡι', - 8090 => 'ἢι', - 8091 => 'ἣι', - 8092 => 'ἤι', - 8093 => 'ἥι', - 8094 => 'ἦι', - 8095 => 'ἧι', - 8096 => 'ὠι', - 8097 => 'ὡι', - 8098 => 'ὢι', - 8099 => 'ὣι', - 8100 => 'ὤι', - 8101 => 'ὥι', - 8102 => 'ὦι', - 8103 => 'ὧι', - 8104 => 'ὠι', - 8105 => 'ὡι', - 8106 => 'ὢι', - 8107 => 'ὣι', - 8108 => 'ὤι', - 8109 => 'ὥι', - 8110 => 'ὦι', - 8111 => 'ὧι', - 8114 => 'ὰι', - 8115 => 'αι', - 8116 => 'άι', - 8119 => 'ᾶι', - 8120 => 'ᾰ', - 8121 => 'ᾱ', - 8122 => 'ὰ', - 8123 => 'ά', - 8124 => 'αι', - 8126 => 'ι', - 8130 => 'ὴι', - 8131 => 'ηι', - 8132 => 'ήι', - 8135 => 'ῆι', - 8136 => 'ὲ', - 8137 => 'έ', - 8138 => 'ὴ', - 8139 => 'ή', - 8140 => 'ηι', - 8147 => 'ΐ', - 8152 => 'ῐ', - 8153 => 'ῑ', - 8154 => 'ὶ', - 8155 => 'ί', - 8163 => 'ΰ', - 8168 => 'ῠ', - 8169 => 'ῡ', - 8170 => 'ὺ', - 8171 => 'ύ', - 8172 => 'ῥ', - 8178 => 'ὼι', - 8179 => 'ωι', - 8180 => 'ώι', - 8183 => 'ῶι', - 8184 => 'ὸ', - 8185 => 'ό', - 8186 => 'ὼ', - 8187 => 'ώ', - 8188 => 'ωι', - 8209 => '‐', - 8243 => '′′', - 8244 => '′′′', - 8246 => '‵‵', - 8247 => '‵‵‵', - 8279 => '′′′′', - 8304 => '0', - 8305 => 'i', - 8308 => '4', - 8309 => '5', - 8310 => '6', - 8311 => '7', - 8312 => '8', - 8313 => '9', - 8315 => '−', - 8319 => 'n', - 8320 => '0', - 8321 => '1', - 8322 => '2', - 8323 => '3', - 8324 => '4', - 8325 => '5', - 8326 => '6', - 8327 => '7', - 8328 => '8', - 8329 => '9', - 8331 => '−', - 8336 => 'a', - 8337 => 'e', - 8338 => 'o', - 8339 => 'x', - 8340 => 'ə', - 8341 => 'h', - 8342 => 'k', - 8343 => 'l', - 8344 => 'm', - 8345 => 'n', - 8346 => 'p', - 8347 => 's', - 8348 => 't', - 8360 => 'rs', - 8450 => 'c', - 8451 => '°c', - 8455 => 'ɛ', - 8457 => '°f', - 8458 => 'g', - 8459 => 'h', - 8460 => 'h', - 8461 => 'h', - 8462 => 'h', - 8463 => 'ħ', - 8464 => 'i', - 8465 => 'i', - 8466 => 'l', - 8467 => 'l', - 8469 => 'n', - 8470 => 'no', - 8473 => 'p', - 8474 => 'q', - 8475 => 'r', - 8476 => 'r', - 8477 => 'r', - 8480 => 'sm', - 8481 => 'tel', - 8482 => 'tm', - 8484 => 'z', - 8486 => 'ω', - 8488 => 'z', - 8490 => 'k', - 8491 => 'å', - 8492 => 'b', - 8493 => 'c', - 8495 => 'e', - 8496 => 'e', - 8497 => 'f', - 8499 => 'm', - 8500 => 'o', - 8501 => 'א', - 8502 => 'ב', - 8503 => 'ג', - 8504 => 'ד', - 8505 => 'i', - 8507 => 'fax', - 8508 => 'π', - 8509 => 'γ', - 8510 => 'γ', - 8511 => 'π', - 8512 => '∑', - 8517 => 'd', - 8518 => 'd', - 8519 => 'e', - 8520 => 'i', - 8521 => 'j', - 8528 => '1⁄7', - 8529 => '1⁄9', - 8530 => '1⁄10', - 8531 => '1⁄3', - 8532 => '2⁄3', - 8533 => '1⁄5', - 8534 => '2⁄5', - 8535 => '3⁄5', - 8536 => '4⁄5', - 8537 => '1⁄6', - 8538 => '5⁄6', - 8539 => '1⁄8', - 8540 => '3⁄8', - 8541 => '5⁄8', - 8542 => '7⁄8', - 8543 => '1⁄', - 8544 => 'i', - 8545 => 'ii', - 8546 => 'iii', - 8547 => 'iv', - 8548 => 'v', - 8549 => 'vi', - 8550 => 'vii', - 8551 => 'viii', - 8552 => 'ix', - 8553 => 'x', - 8554 => 'xi', - 8555 => 'xii', - 8556 => 'l', - 8557 => 'c', - 8558 => 'd', - 8559 => 'm', - 8560 => 'i', - 8561 => 'ii', - 8562 => 'iii', - 8563 => 'iv', - 8564 => 'v', - 8565 => 'vi', - 8566 => 'vii', - 8567 => 'viii', - 8568 => 'ix', - 8569 => 'x', - 8570 => 'xi', - 8571 => 'xii', - 8572 => 'l', - 8573 => 'c', - 8574 => 'd', - 8575 => 'm', - 8585 => '0⁄3', - 8748 => '∫∫', - 8749 => '∫∫∫', - 8751 => '∮∮', - 8752 => '∮∮∮', - 9001 => '〈', - 9002 => '〉', - 9312 => '1', - 9313 => '2', - 9314 => '3', - 9315 => '4', - 9316 => '5', - 9317 => '6', - 9318 => '7', - 9319 => '8', - 9320 => '9', - 9321 => '10', - 9322 => '11', - 9323 => '12', - 9324 => '13', - 9325 => '14', - 9326 => '15', - 9327 => '16', - 9328 => '17', - 9329 => '18', - 9330 => '19', - 9331 => '20', - 9398 => 'a', - 9399 => 'b', - 9400 => 'c', - 9401 => 'd', - 9402 => 'e', - 9403 => 'f', - 9404 => 'g', - 9405 => 'h', - 9406 => 'i', - 9407 => 'j', - 9408 => 'k', - 9409 => 'l', - 9410 => 'm', - 9411 => 'n', - 9412 => 'o', - 9413 => 'p', - 9414 => 'q', - 9415 => 'r', - 9416 => 's', - 9417 => 't', - 9418 => 'u', - 9419 => 'v', - 9420 => 'w', - 9421 => 'x', - 9422 => 'y', - 9423 => 'z', - 9424 => 'a', - 9425 => 'b', - 9426 => 'c', - 9427 => 'd', - 9428 => 'e', - 9429 => 'f', - 9430 => 'g', - 9431 => 'h', - 9432 => 'i', - 9433 => 'j', - 9434 => 'k', - 9435 => 'l', - 9436 => 'm', - 9437 => 'n', - 9438 => 'o', - 9439 => 'p', - 9440 => 'q', - 9441 => 'r', - 9442 => 's', - 9443 => 't', - 9444 => 'u', - 9445 => 'v', - 9446 => 'w', - 9447 => 'x', - 9448 => 'y', - 9449 => 'z', - 9450 => '0', - 10764 => '∫∫∫∫', - 10972 => '⫝̸', - 11264 => 'ⰰ', - 11265 => 'ⰱ', - 11266 => 'ⰲ', - 11267 => 'ⰳ', - 11268 => 'ⰴ', - 11269 => 'ⰵ', - 11270 => 'ⰶ', - 11271 => 'ⰷ', - 11272 => 'ⰸ', - 11273 => 'ⰹ', - 11274 => 'ⰺ', - 11275 => 'ⰻ', - 11276 => 'ⰼ', - 11277 => 'ⰽ', - 11278 => 'ⰾ', - 11279 => 'ⰿ', - 11280 => 'ⱀ', - 11281 => 'ⱁ', - 11282 => 'ⱂ', - 11283 => 'ⱃ', - 11284 => 'ⱄ', - 11285 => 'ⱅ', - 11286 => 'ⱆ', - 11287 => 'ⱇ', - 11288 => 'ⱈ', - 11289 => 'ⱉ', - 11290 => 'ⱊ', - 11291 => 'ⱋ', - 11292 => 'ⱌ', - 11293 => 'ⱍ', - 11294 => 'ⱎ', - 11295 => 'ⱏ', - 11296 => 'ⱐ', - 11297 => 'ⱑ', - 11298 => 'ⱒ', - 11299 => 'ⱓ', - 11300 => 'ⱔ', - 11301 => 'ⱕ', - 11302 => 'ⱖ', - 11303 => 'ⱗ', - 11304 => 'ⱘ', - 11305 => 'ⱙ', - 11306 => 'ⱚ', - 11307 => 'ⱛ', - 11308 => 'ⱜ', - 11309 => 'ⱝ', - 11310 => 'ⱞ', - 11360 => 'ⱡ', - 11362 => 'ɫ', - 11363 => 'ᵽ', - 11364 => 'ɽ', - 11367 => 'ⱨ', - 11369 => 'ⱪ', - 11371 => 'ⱬ', - 11373 => 'ɑ', - 11374 => 'ɱ', - 11375 => 'ɐ', - 11376 => 'ɒ', - 11378 => 'ⱳ', - 11381 => 'ⱶ', - 11388 => 'j', - 11389 => 'v', - 11390 => 'ȿ', - 11391 => 'ɀ', - 11392 => 'ⲁ', - 11394 => 'ⲃ', - 11396 => 'ⲅ', - 11398 => 'ⲇ', - 11400 => 'ⲉ', - 11402 => 'ⲋ', - 11404 => 'ⲍ', - 11406 => 'ⲏ', - 11408 => 'ⲑ', - 11410 => 'ⲓ', - 11412 => 'ⲕ', - 11414 => 'ⲗ', - 11416 => 'ⲙ', - 11418 => 'ⲛ', - 11420 => 'ⲝ', - 11422 => 'ⲟ', - 11424 => 'ⲡ', - 11426 => 'ⲣ', - 11428 => 'ⲥ', - 11430 => 'ⲧ', - 11432 => 'ⲩ', - 11434 => 'ⲫ', - 11436 => 'ⲭ', - 11438 => 'ⲯ', - 11440 => 'ⲱ', - 11442 => 'ⲳ', - 11444 => 'ⲵ', - 11446 => 'ⲷ', - 11448 => 'ⲹ', - 11450 => 'ⲻ', - 11452 => 'ⲽ', - 11454 => 'ⲿ', - 11456 => 'ⳁ', - 11458 => 'ⳃ', - 11460 => 'ⳅ', - 11462 => 'ⳇ', - 11464 => 'ⳉ', - 11466 => 'ⳋ', - 11468 => 'ⳍ', - 11470 => 'ⳏ', - 11472 => 'ⳑ', - 11474 => 'ⳓ', - 11476 => 'ⳕ', - 11478 => 'ⳗ', - 11480 => 'ⳙ', - 11482 => 'ⳛ', - 11484 => 'ⳝ', - 11486 => 'ⳟ', - 11488 => 'ⳡ', - 11490 => 'ⳣ', - 11499 => 'ⳬ', - 11501 => 'ⳮ', - 11506 => 'ⳳ', - 11631 => 'ⵡ', - 11935 => '母', - 12019 => '龟', - 12032 => '一', - 12033 => '丨', - 12034 => '丶', - 12035 => '丿', - 12036 => '乙', - 12037 => '亅', - 12038 => '二', - 12039 => '亠', - 12040 => '人', - 12041 => '儿', - 12042 => '入', - 12043 => '八', - 12044 => '冂', - 12045 => '冖', - 12046 => '冫', - 12047 => '几', - 12048 => '凵', - 12049 => '刀', - 12050 => '力', - 12051 => '勹', - 12052 => '匕', - 12053 => '匚', - 12054 => '匸', - 12055 => '十', - 12056 => '卜', - 12057 => '卩', - 12058 => '厂', - 12059 => '厶', - 12060 => '又', - 12061 => '口', - 12062 => '囗', - 12063 => '土', - 12064 => '士', - 12065 => '夂', - 12066 => '夊', - 12067 => '夕', - 12068 => '大', - 12069 => '女', - 12070 => '子', - 12071 => '宀', - 12072 => '寸', - 12073 => '小', - 12074 => '尢', - 12075 => '尸', - 12076 => '屮', - 12077 => '山', - 12078 => '巛', - 12079 => '工', - 12080 => '己', - 12081 => '巾', - 12082 => '干', - 12083 => '幺', - 12084 => '广', - 12085 => '廴', - 12086 => '廾', - 12087 => '弋', - 12088 => '弓', - 12089 => '彐', - 12090 => '彡', - 12091 => '彳', - 12092 => '心', - 12093 => '戈', - 12094 => '戶', - 12095 => '手', - 12096 => '支', - 12097 => '攴', - 12098 => '文', - 12099 => '斗', - 12100 => '斤', - 12101 => '方', - 12102 => '无', - 12103 => '日', - 12104 => '曰', - 12105 => '月', - 12106 => '木', - 12107 => '欠', - 12108 => '止', - 12109 => '歹', - 12110 => '殳', - 12111 => '毋', - 12112 => '比', - 12113 => '毛', - 12114 => '氏', - 12115 => '气', - 12116 => '水', - 12117 => '火', - 12118 => '爪', - 12119 => '父', - 12120 => '爻', - 12121 => '爿', - 12122 => '片', - 12123 => '牙', - 12124 => '牛', - 12125 => '犬', - 12126 => '玄', - 12127 => '玉', - 12128 => '瓜', - 12129 => '瓦', - 12130 => '甘', - 12131 => '生', - 12132 => '用', - 12133 => '田', - 12134 => '疋', - 12135 => '疒', - 12136 => '癶', - 12137 => '白', - 12138 => '皮', - 12139 => '皿', - 12140 => '目', - 12141 => '矛', - 12142 => '矢', - 12143 => '石', - 12144 => '示', - 12145 => '禸', - 12146 => '禾', - 12147 => '穴', - 12148 => '立', - 12149 => '竹', - 12150 => '米', - 12151 => '糸', - 12152 => '缶', - 12153 => '网', - 12154 => '羊', - 12155 => '羽', - 12156 => '老', - 12157 => '而', - 12158 => '耒', - 12159 => '耳', - 12160 => '聿', - 12161 => '肉', - 12162 => '臣', - 12163 => '自', - 12164 => '至', - 12165 => '臼', - 12166 => '舌', - 12167 => '舛', - 12168 => '舟', - 12169 => '艮', - 12170 => '色', - 12171 => '艸', - 12172 => '虍', - 12173 => '虫', - 12174 => '血', - 12175 => '行', - 12176 => '衣', - 12177 => '襾', - 12178 => '見', - 12179 => '角', - 12180 => '言', - 12181 => '谷', - 12182 => '豆', - 12183 => '豕', - 12184 => '豸', - 12185 => '貝', - 12186 => '赤', - 12187 => '走', - 12188 => '足', - 12189 => '身', - 12190 => '車', - 12191 => '辛', - 12192 => '辰', - 12193 => '辵', - 12194 => '邑', - 12195 => '酉', - 12196 => '釆', - 12197 => '里', - 12198 => '金', - 12199 => '長', - 12200 => '門', - 12201 => '阜', - 12202 => '隶', - 12203 => '隹', - 12204 => '雨', - 12205 => '靑', - 12206 => '非', - 12207 => '面', - 12208 => '革', - 12209 => '韋', - 12210 => '韭', - 12211 => '音', - 12212 => '頁', - 12213 => '風', - 12214 => '飛', - 12215 => '食', - 12216 => '首', - 12217 => '香', - 12218 => '馬', - 12219 => '骨', - 12220 => '高', - 12221 => '髟', - 12222 => '鬥', - 12223 => '鬯', - 12224 => '鬲', - 12225 => '鬼', - 12226 => '魚', - 12227 => '鳥', - 12228 => '鹵', - 12229 => '鹿', - 12230 => '麥', - 12231 => '麻', - 12232 => '黃', - 12233 => '黍', - 12234 => '黑', - 12235 => '黹', - 12236 => '黽', - 12237 => '鼎', - 12238 => '鼓', - 12239 => '鼠', - 12240 => '鼻', - 12241 => '齊', - 12242 => '齒', - 12243 => '龍', - 12244 => '龜', - 12245 => '龠', - 12290 => '.', - 12342 => '〒', - 12344 => '十', - 12345 => '卄', - 12346 => '卅', - 12447 => 'より', - 12543 => 'コト', - 12593 => 'ᄀ', - 12594 => 'ᄁ', - 12595 => 'ᆪ', - 12596 => 'ᄂ', - 12597 => 'ᆬ', - 12598 => 'ᆭ', - 12599 => 'ᄃ', - 12600 => 'ᄄ', - 12601 => 'ᄅ', - 12602 => 'ᆰ', - 12603 => 'ᆱ', - 12604 => 'ᆲ', - 12605 => 'ᆳ', - 12606 => 'ᆴ', - 12607 => 'ᆵ', - 12608 => 'ᄚ', - 12609 => 'ᄆ', - 12610 => 'ᄇ', - 12611 => 'ᄈ', - 12612 => 'ᄡ', - 12613 => 'ᄉ', - 12614 => 'ᄊ', - 12615 => 'ᄋ', - 12616 => 'ᄌ', - 12617 => 'ᄍ', - 12618 => 'ᄎ', - 12619 => 'ᄏ', - 12620 => 'ᄐ', - 12621 => 'ᄑ', - 12622 => 'ᄒ', - 12623 => 'ᅡ', - 12624 => 'ᅢ', - 12625 => 'ᅣ', - 12626 => 'ᅤ', - 12627 => 'ᅥ', - 12628 => 'ᅦ', - 12629 => 'ᅧ', - 12630 => 'ᅨ', - 12631 => 'ᅩ', - 12632 => 'ᅪ', - 12633 => 'ᅫ', - 12634 => 'ᅬ', - 12635 => 'ᅭ', - 12636 => 'ᅮ', - 12637 => 'ᅯ', - 12638 => 'ᅰ', - 12639 => 'ᅱ', - 12640 => 'ᅲ', - 12641 => 'ᅳ', - 12642 => 'ᅴ', - 12643 => 'ᅵ', - 12645 => 'ᄔ', - 12646 => 'ᄕ', - 12647 => 'ᇇ', - 12648 => 'ᇈ', - 12649 => 'ᇌ', - 12650 => 'ᇎ', - 12651 => 'ᇓ', - 12652 => 'ᇗ', - 12653 => 'ᇙ', - 12654 => 'ᄜ', - 12655 => 'ᇝ', - 12656 => 'ᇟ', - 12657 => 'ᄝ', - 12658 => 'ᄞ', - 12659 => 'ᄠ', - 12660 => 'ᄢ', - 12661 => 'ᄣ', - 12662 => 'ᄧ', - 12663 => 'ᄩ', - 12664 => 'ᄫ', - 12665 => 'ᄬ', - 12666 => 'ᄭ', - 12667 => 'ᄮ', - 12668 => 'ᄯ', - 12669 => 'ᄲ', - 12670 => 'ᄶ', - 12671 => 'ᅀ', - 12672 => 'ᅇ', - 12673 => 'ᅌ', - 12674 => 'ᇱ', - 12675 => 'ᇲ', - 12676 => 'ᅗ', - 12677 => 'ᅘ', - 12678 => 'ᅙ', - 12679 => 'ᆄ', - 12680 => 'ᆅ', - 12681 => 'ᆈ', - 12682 => 'ᆑ', - 12683 => 'ᆒ', - 12684 => 'ᆔ', - 12685 => 'ᆞ', - 12686 => 'ᆡ', - 12690 => '一', - 12691 => '二', - 12692 => '三', - 12693 => '四', - 12694 => '上', - 12695 => '中', - 12696 => '下', - 12697 => '甲', - 12698 => '乙', - 12699 => '丙', - 12700 => '丁', - 12701 => '天', - 12702 => '地', - 12703 => '人', - 12868 => '問', - 12869 => '幼', - 12870 => '文', - 12871 => '箏', - 12880 => 'pte', - 12881 => '21', - 12882 => '22', - 12883 => '23', - 12884 => '24', - 12885 => '25', - 12886 => '26', - 12887 => '27', - 12888 => '28', - 12889 => '29', - 12890 => '30', - 12891 => '31', - 12892 => '32', - 12893 => '33', - 12894 => '34', - 12895 => '35', - 12896 => 'ᄀ', - 12897 => 'ᄂ', - 12898 => 'ᄃ', - 12899 => 'ᄅ', - 12900 => 'ᄆ', - 12901 => 'ᄇ', - 12902 => 'ᄉ', - 12903 => 'ᄋ', - 12904 => 'ᄌ', - 12905 => 'ᄎ', - 12906 => 'ᄏ', - 12907 => 'ᄐ', - 12908 => 'ᄑ', - 12909 => 'ᄒ', - 12910 => '가', - 12911 => '나', - 12912 => '다', - 12913 => '라', - 12914 => '마', - 12915 => '바', - 12916 => '사', - 12917 => '아', - 12918 => '자', - 12919 => '차', - 12920 => '카', - 12921 => '타', - 12922 => '파', - 12923 => '하', - 12924 => '참고', - 12925 => '주의', - 12926 => '우', - 12928 => '一', - 12929 => '二', - 12930 => '三', - 12931 => '四', - 12932 => '五', - 12933 => '六', - 12934 => '七', - 12935 => '八', - 12936 => '九', - 12937 => '十', - 12938 => '月', - 12939 => '火', - 12940 => '水', - 12941 => '木', - 12942 => '金', - 12943 => '土', - 12944 => '日', - 12945 => '株', - 12946 => '有', - 12947 => '社', - 12948 => '名', - 12949 => '特', - 12950 => '財', - 12951 => '祝', - 12952 => '労', - 12953 => '秘', - 12954 => '男', - 12955 => '女', - 12956 => '適', - 12957 => '優', - 12958 => '印', - 12959 => '注', - 12960 => '項', - 12961 => '休', - 12962 => '写', - 12963 => '正', - 12964 => '上', - 12965 => '中', - 12966 => '下', - 12967 => '左', - 12968 => '右', - 12969 => '医', - 12970 => '宗', - 12971 => '学', - 12972 => '監', - 12973 => '企', - 12974 => '資', - 12975 => '協', - 12976 => '夜', - 12977 => '36', - 12978 => '37', - 12979 => '38', - 12980 => '39', - 12981 => '40', - 12982 => '41', - 12983 => '42', - 12984 => '43', - 12985 => '44', - 12986 => '45', - 12987 => '46', - 12988 => '47', - 12989 => '48', - 12990 => '49', - 12991 => '50', - 12992 => '1月', - 12993 => '2月', - 12994 => '3月', - 12995 => '4月', - 12996 => '5月', - 12997 => '6月', - 12998 => '7月', - 12999 => '8月', - 13000 => '9月', - 13001 => '10月', - 13002 => '11月', - 13003 => '12月', - 13004 => 'hg', - 13005 => 'erg', - 13006 => 'ev', - 13007 => 'ltd', - 13008 => 'ア', - 13009 => 'イ', - 13010 => 'ウ', - 13011 => 'エ', - 13012 => 'オ', - 13013 => 'カ', - 13014 => 'キ', - 13015 => 'ク', - 13016 => 'ケ', - 13017 => 'コ', - 13018 => 'サ', - 13019 => 'シ', - 13020 => 'ス', - 13021 => 'セ', - 13022 => 'ソ', - 13023 => 'タ', - 13024 => 'チ', - 13025 => 'ツ', - 13026 => 'テ', - 13027 => 'ト', - 13028 => 'ナ', - 13029 => 'ニ', - 13030 => 'ヌ', - 13031 => 'ネ', - 13032 => 'ノ', - 13033 => 'ハ', - 13034 => 'ヒ', - 13035 => 'フ', - 13036 => 'ヘ', - 13037 => 'ホ', - 13038 => 'マ', - 13039 => 'ミ', - 13040 => 'ム', - 13041 => 'メ', - 13042 => 'モ', - 13043 => 'ヤ', - 13044 => 'ユ', - 13045 => 'ヨ', - 13046 => 'ラ', - 13047 => 'リ', - 13048 => 'ル', - 13049 => 'レ', - 13050 => 'ロ', - 13051 => 'ワ', - 13052 => 'ヰ', - 13053 => 'ヱ', - 13054 => 'ヲ', - 13055 => '令和', - 13056 => 'アパート', - 13057 => 'アルファ', - 13058 => 'アンペア', - 13059 => 'アール', - 13060 => 'イニング', - 13061 => 'インチ', - 13062 => 'ウォン', - 13063 => 'エスクード', - 13064 => 'エーカー', - 13065 => 'オンス', - 13066 => 'オーム', - 13067 => 'カイリ', - 13068 => 'カラット', - 13069 => 'カロリー', - 13070 => 'ガロン', - 13071 => 'ガンマ', - 13072 => 'ギガ', - 13073 => 'ギニー', - 13074 => 'キュリー', - 13075 => 'ギルダー', - 13076 => 'キロ', - 13077 => 'キログラム', - 13078 => 'キロメートル', - 13079 => 'キロワット', - 13080 => 'グラム', - 13081 => 'グラムトン', - 13082 => 'クルゼイロ', - 13083 => 'クローネ', - 13084 => 'ケース', - 13085 => 'コルナ', - 13086 => 'コーポ', - 13087 => 'サイクル', - 13088 => 'サンチーム', - 13089 => 'シリング', - 13090 => 'センチ', - 13091 => 'セント', - 13092 => 'ダース', - 13093 => 'デシ', - 13094 => 'ドル', - 13095 => 'トン', - 13096 => 'ナノ', - 13097 => 'ノット', - 13098 => 'ハイツ', - 13099 => 'パーセント', - 13100 => 'パーツ', - 13101 => 'バーレル', - 13102 => 'ピアストル', - 13103 => 'ピクル', - 13104 => 'ピコ', - 13105 => 'ビル', - 13106 => 'ファラッド', - 13107 => 'フィート', - 13108 => 'ブッシェル', - 13109 => 'フラン', - 13110 => 'ヘクタール', - 13111 => 'ペソ', - 13112 => 'ペニヒ', - 13113 => 'ヘルツ', - 13114 => 'ペンス', - 13115 => 'ページ', - 13116 => 'ベータ', - 13117 => 'ポイント', - 13118 => 'ボルト', - 13119 => 'ホン', - 13120 => 'ポンド', - 13121 => 'ホール', - 13122 => 'ホーン', - 13123 => 'マイクロ', - 13124 => 'マイル', - 13125 => 'マッハ', - 13126 => 'マルク', - 13127 => 'マンション', - 13128 => 'ミクロン', - 13129 => 'ミリ', - 13130 => 'ミリバール', - 13131 => 'メガ', - 13132 => 'メガトン', - 13133 => 'メートル', - 13134 => 'ヤード', - 13135 => 'ヤール', - 13136 => 'ユアン', - 13137 => 'リットル', - 13138 => 'リラ', - 13139 => 'ルピー', - 13140 => 'ルーブル', - 13141 => 'レム', - 13142 => 'レントゲン', - 13143 => 'ワット', - 13144 => '0点', - 13145 => '1点', - 13146 => '2点', - 13147 => '3点', - 13148 => '4点', - 13149 => '5点', - 13150 => '6点', - 13151 => '7点', - 13152 => '8点', - 13153 => '9点', - 13154 => '10点', - 13155 => '11点', - 13156 => '12点', - 13157 => '13点', - 13158 => '14点', - 13159 => '15点', - 13160 => '16点', - 13161 => '17点', - 13162 => '18点', - 13163 => '19点', - 13164 => '20点', - 13165 => '21点', - 13166 => '22点', - 13167 => '23点', - 13168 => '24点', - 13169 => 'hpa', - 13170 => 'da', - 13171 => 'au', - 13172 => 'bar', - 13173 => 'ov', - 13174 => 'pc', - 13175 => 'dm', - 13176 => 'dm2', - 13177 => 'dm3', - 13178 => 'iu', - 13179 => '平成', - 13180 => '昭和', - 13181 => '大正', - 13182 => '明治', - 13183 => '株式会社', - 13184 => 'pa', - 13185 => 'na', - 13186 => 'μa', - 13187 => 'ma', - 13188 => 'ka', - 13189 => 'kb', - 13190 => 'mb', - 13191 => 'gb', - 13192 => 'cal', - 13193 => 'kcal', - 13194 => 'pf', - 13195 => 'nf', - 13196 => 'μf', - 13197 => 'μg', - 13198 => 'mg', - 13199 => 'kg', - 13200 => 'hz', - 13201 => 'khz', - 13202 => 'mhz', - 13203 => 'ghz', - 13204 => 'thz', - 13205 => 'μl', - 13206 => 'ml', - 13207 => 'dl', - 13208 => 'kl', - 13209 => 'fm', - 13210 => 'nm', - 13211 => 'μm', - 13212 => 'mm', - 13213 => 'cm', - 13214 => 'km', - 13215 => 'mm2', - 13216 => 'cm2', - 13217 => 'm2', - 13218 => 'km2', - 13219 => 'mm3', - 13220 => 'cm3', - 13221 => 'm3', - 13222 => 'km3', - 13223 => 'm∕s', - 13224 => 'm∕s2', - 13225 => 'pa', - 13226 => 'kpa', - 13227 => 'mpa', - 13228 => 'gpa', - 13229 => 'rad', - 13230 => 'rad∕s', - 13231 => 'rad∕s2', - 13232 => 'ps', - 13233 => 'ns', - 13234 => 'μs', - 13235 => 'ms', - 13236 => 'pv', - 13237 => 'nv', - 13238 => 'μv', - 13239 => 'mv', - 13240 => 'kv', - 13241 => 'mv', - 13242 => 'pw', - 13243 => 'nw', - 13244 => 'μw', - 13245 => 'mw', - 13246 => 'kw', - 13247 => 'mw', - 13248 => 'kω', - 13249 => 'mω', - 13251 => 'bq', - 13252 => 'cc', - 13253 => 'cd', - 13254 => 'c∕kg', - 13256 => 'db', - 13257 => 'gy', - 13258 => 'ha', - 13259 => 'hp', - 13260 => 'in', - 13261 => 'kk', - 13262 => 'km', - 13263 => 'kt', - 13264 => 'lm', - 13265 => 'ln', - 13266 => 'log', - 13267 => 'lx', - 13268 => 'mb', - 13269 => 'mil', - 13270 => 'mol', - 13271 => 'ph', - 13273 => 'ppm', - 13274 => 'pr', - 13275 => 'sr', - 13276 => 'sv', - 13277 => 'wb', - 13278 => 'v∕m', - 13279 => 'a∕m', - 13280 => '1日', - 13281 => '2日', - 13282 => '3日', - 13283 => '4日', - 13284 => '5日', - 13285 => '6日', - 13286 => '7日', - 13287 => '8日', - 13288 => '9日', - 13289 => '10日', - 13290 => '11日', - 13291 => '12日', - 13292 => '13日', - 13293 => '14日', - 13294 => '15日', - 13295 => '16日', - 13296 => '17日', - 13297 => '18日', - 13298 => '19日', - 13299 => '20日', - 13300 => '21日', - 13301 => '22日', - 13302 => '23日', - 13303 => '24日', - 13304 => '25日', - 13305 => '26日', - 13306 => '27日', - 13307 => '28日', - 13308 => '29日', - 13309 => '30日', - 13310 => '31日', - 13311 => 'gal', - 42560 => 'ꙁ', - 42562 => 'ꙃ', - 42564 => 'ꙅ', - 42566 => 'ꙇ', - 42568 => 'ꙉ', - 42570 => 'ꙋ', - 42572 => 'ꙍ', - 42574 => 'ꙏ', - 42576 => 'ꙑ', - 42578 => 'ꙓ', - 42580 => 'ꙕ', - 42582 => 'ꙗ', - 42584 => 'ꙙ', - 42586 => 'ꙛ', - 42588 => 'ꙝ', - 42590 => 'ꙟ', - 42592 => 'ꙡ', - 42594 => 'ꙣ', - 42596 => 'ꙥ', - 42598 => 'ꙧ', - 42600 => 'ꙩ', - 42602 => 'ꙫ', - 42604 => 'ꙭ', - 42624 => 'ꚁ', - 42626 => 'ꚃ', - 42628 => 'ꚅ', - 42630 => 'ꚇ', - 42632 => 'ꚉ', - 42634 => 'ꚋ', - 42636 => 'ꚍ', - 42638 => 'ꚏ', - 42640 => 'ꚑ', - 42642 => 'ꚓ', - 42644 => 'ꚕ', - 42646 => 'ꚗ', - 42648 => 'ꚙ', - 42650 => 'ꚛ', - 42652 => 'ъ', - 42653 => 'ь', - 42786 => 'ꜣ', - 42788 => 'ꜥ', - 42790 => 'ꜧ', - 42792 => 'ꜩ', - 42794 => 'ꜫ', - 42796 => 'ꜭ', - 42798 => 'ꜯ', - 42802 => 'ꜳ', - 42804 => 'ꜵ', - 42806 => 'ꜷ', - 42808 => 'ꜹ', - 42810 => 'ꜻ', - 42812 => 'ꜽ', - 42814 => 'ꜿ', - 42816 => 'ꝁ', - 42818 => 'ꝃ', - 42820 => 'ꝅ', - 42822 => 'ꝇ', - 42824 => 'ꝉ', - 42826 => 'ꝋ', - 42828 => 'ꝍ', - 42830 => 'ꝏ', - 42832 => 'ꝑ', - 42834 => 'ꝓ', - 42836 => 'ꝕ', - 42838 => 'ꝗ', - 42840 => 'ꝙ', - 42842 => 'ꝛ', - 42844 => 'ꝝ', - 42846 => 'ꝟ', - 42848 => 'ꝡ', - 42850 => 'ꝣ', - 42852 => 'ꝥ', - 42854 => 'ꝧ', - 42856 => 'ꝩ', - 42858 => 'ꝫ', - 42860 => 'ꝭ', - 42862 => 'ꝯ', - 42864 => 'ꝯ', - 42873 => 'ꝺ', - 42875 => 'ꝼ', - 42877 => 'ᵹ', - 42878 => 'ꝿ', - 42880 => 'ꞁ', - 42882 => 'ꞃ', - 42884 => 'ꞅ', - 42886 => 'ꞇ', - 42891 => 'ꞌ', - 42893 => 'ɥ', - 42896 => 'ꞑ', - 42898 => 'ꞓ', - 42902 => 'ꞗ', - 42904 => 'ꞙ', - 42906 => 'ꞛ', - 42908 => 'ꞝ', - 42910 => 'ꞟ', - 42912 => 'ꞡ', - 42914 => 'ꞣ', - 42916 => 'ꞥ', - 42918 => 'ꞧ', - 42920 => 'ꞩ', - 42922 => 'ɦ', - 42923 => 'ɜ', - 42924 => 'ɡ', - 42925 => 'ɬ', - 42926 => 'ɪ', - 42928 => 'ʞ', - 42929 => 'ʇ', - 42930 => 'ʝ', - 42931 => 'ꭓ', - 42932 => 'ꞵ', - 42934 => 'ꞷ', - 42936 => 'ꞹ', - 42938 => 'ꞻ', - 42940 => 'ꞽ', - 42942 => 'ꞿ', - 42946 => 'ꟃ', - 42948 => 'ꞔ', - 42949 => 'ʂ', - 42950 => 'ᶎ', - 42951 => 'ꟈ', - 42953 => 'ꟊ', - 42997 => 'ꟶ', - 43000 => 'ħ', - 43001 => 'œ', - 43868 => 'ꜧ', - 43869 => 'ꬷ', - 43870 => 'ɫ', - 43871 => 'ꭒ', - 43881 => 'ʍ', - 43888 => 'Ꭰ', - 43889 => 'Ꭱ', - 43890 => 'Ꭲ', - 43891 => 'Ꭳ', - 43892 => 'Ꭴ', - 43893 => 'Ꭵ', - 43894 => 'Ꭶ', - 43895 => 'Ꭷ', - 43896 => 'Ꭸ', - 43897 => 'Ꭹ', - 43898 => 'Ꭺ', - 43899 => 'Ꭻ', - 43900 => 'Ꭼ', - 43901 => 'Ꭽ', - 43902 => 'Ꭾ', - 43903 => 'Ꭿ', - 43904 => 'Ꮀ', - 43905 => 'Ꮁ', - 43906 => 'Ꮂ', - 43907 => 'Ꮃ', - 43908 => 'Ꮄ', - 43909 => 'Ꮅ', - 43910 => 'Ꮆ', - 43911 => 'Ꮇ', - 43912 => 'Ꮈ', - 43913 => 'Ꮉ', - 43914 => 'Ꮊ', - 43915 => 'Ꮋ', - 43916 => 'Ꮌ', - 43917 => 'Ꮍ', - 43918 => 'Ꮎ', - 43919 => 'Ꮏ', - 43920 => 'Ꮐ', - 43921 => 'Ꮑ', - 43922 => 'Ꮒ', - 43923 => 'Ꮓ', - 43924 => 'Ꮔ', - 43925 => 'Ꮕ', - 43926 => 'Ꮖ', - 43927 => 'Ꮗ', - 43928 => 'Ꮘ', - 43929 => 'Ꮙ', - 43930 => 'Ꮚ', - 43931 => 'Ꮛ', - 43932 => 'Ꮜ', - 43933 => 'Ꮝ', - 43934 => 'Ꮞ', - 43935 => 'Ꮟ', - 43936 => 'Ꮠ', - 43937 => 'Ꮡ', - 43938 => 'Ꮢ', - 43939 => 'Ꮣ', - 43940 => 'Ꮤ', - 43941 => 'Ꮥ', - 43942 => 'Ꮦ', - 43943 => 'Ꮧ', - 43944 => 'Ꮨ', - 43945 => 'Ꮩ', - 43946 => 'Ꮪ', - 43947 => 'Ꮫ', - 43948 => 'Ꮬ', - 43949 => 'Ꮭ', - 43950 => 'Ꮮ', - 43951 => 'Ꮯ', - 43952 => 'Ꮰ', - 43953 => 'Ꮱ', - 43954 => 'Ꮲ', - 43955 => 'Ꮳ', - 43956 => 'Ꮴ', - 43957 => 'Ꮵ', - 43958 => 'Ꮶ', - 43959 => 'Ꮷ', - 43960 => 'Ꮸ', - 43961 => 'Ꮹ', - 43962 => 'Ꮺ', - 43963 => 'Ꮻ', - 43964 => 'Ꮼ', - 43965 => 'Ꮽ', - 43966 => 'Ꮾ', - 43967 => 'Ꮿ', - 63744 => '豈', - 63745 => '更', - 63746 => '車', - 63747 => '賈', - 63748 => '滑', - 63749 => '串', - 63750 => '句', - 63751 => '龜', - 63752 => '龜', - 63753 => '契', - 63754 => '金', - 63755 => '喇', - 63756 => '奈', - 63757 => '懶', - 63758 => '癩', - 63759 => '羅', - 63760 => '蘿', - 63761 => '螺', - 63762 => '裸', - 63763 => '邏', - 63764 => '樂', - 63765 => '洛', - 63766 => '烙', - 63767 => '珞', - 63768 => '落', - 63769 => '酪', - 63770 => '駱', - 63771 => '亂', - 63772 => '卵', - 63773 => '欄', - 63774 => '爛', - 63775 => '蘭', - 63776 => '鸞', - 63777 => '嵐', - 63778 => '濫', - 63779 => '藍', - 63780 => '襤', - 63781 => '拉', - 63782 => '臘', - 63783 => '蠟', - 63784 => '廊', - 63785 => '朗', - 63786 => '浪', - 63787 => '狼', - 63788 => '郎', - 63789 => '來', - 63790 => '冷', - 63791 => '勞', - 63792 => '擄', - 63793 => '櫓', - 63794 => '爐', - 63795 => '盧', - 63796 => '老', - 63797 => '蘆', - 63798 => '虜', - 63799 => '路', - 63800 => '露', - 63801 => '魯', - 63802 => '鷺', - 63803 => '碌', - 63804 => '祿', - 63805 => '綠', - 63806 => '菉', - 63807 => '錄', - 63808 => '鹿', - 63809 => '論', - 63810 => '壟', - 63811 => '弄', - 63812 => '籠', - 63813 => '聾', - 63814 => '牢', - 63815 => '磊', - 63816 => '賂', - 63817 => '雷', - 63818 => '壘', - 63819 => '屢', - 63820 => '樓', - 63821 => '淚', - 63822 => '漏', - 63823 => '累', - 63824 => '縷', - 63825 => '陋', - 63826 => '勒', - 63827 => '肋', - 63828 => '凜', - 63829 => '凌', - 63830 => '稜', - 63831 => '綾', - 63832 => '菱', - 63833 => '陵', - 63834 => '讀', - 63835 => '拏', - 63836 => '樂', - 63837 => '諾', - 63838 => '丹', - 63839 => '寧', - 63840 => '怒', - 63841 => '率', - 63842 => '異', - 63843 => '北', - 63844 => '磻', - 63845 => '便', - 63846 => '復', - 63847 => '不', - 63848 => '泌', - 63849 => '數', - 63850 => '索', - 63851 => '參', - 63852 => '塞', - 63853 => '省', - 63854 => '葉', - 63855 => '說', - 63856 => '殺', - 63857 => '辰', - 63858 => '沈', - 63859 => '拾', - 63860 => '若', - 63861 => '掠', - 63862 => '略', - 63863 => '亮', - 63864 => '兩', - 63865 => '凉', - 63866 => '梁', - 63867 => '糧', - 63868 => '良', - 63869 => '諒', - 63870 => '量', - 63871 => '勵', - 63872 => '呂', - 63873 => '女', - 63874 => '廬', - 63875 => '旅', - 63876 => '濾', - 63877 => '礪', - 63878 => '閭', - 63879 => '驪', - 63880 => '麗', - 63881 => '黎', - 63882 => '力', - 63883 => '曆', - 63884 => '歷', - 63885 => '轢', - 63886 => '年', - 63887 => '憐', - 63888 => '戀', - 63889 => '撚', - 63890 => '漣', - 63891 => '煉', - 63892 => '璉', - 63893 => '秊', - 63894 => '練', - 63895 => '聯', - 63896 => '輦', - 63897 => '蓮', - 63898 => '連', - 63899 => '鍊', - 63900 => '列', - 63901 => '劣', - 63902 => '咽', - 63903 => '烈', - 63904 => '裂', - 63905 => '說', - 63906 => '廉', - 63907 => '念', - 63908 => '捻', - 63909 => '殮', - 63910 => '簾', - 63911 => '獵', - 63912 => '令', - 63913 => '囹', - 63914 => '寧', - 63915 => '嶺', - 63916 => '怜', - 63917 => '玲', - 63918 => '瑩', - 63919 => '羚', - 63920 => '聆', - 63921 => '鈴', - 63922 => '零', - 63923 => '靈', - 63924 => '領', - 63925 => '例', - 63926 => '禮', - 63927 => '醴', - 63928 => '隸', - 63929 => '惡', - 63930 => '了', - 63931 => '僚', - 63932 => '寮', - 63933 => '尿', - 63934 => '料', - 63935 => '樂', - 63936 => '燎', - 63937 => '療', - 63938 => '蓼', - 63939 => '遼', - 63940 => '龍', - 63941 => '暈', - 63942 => '阮', - 63943 => '劉', - 63944 => '杻', - 63945 => '柳', - 63946 => '流', - 63947 => '溜', - 63948 => '琉', - 63949 => '留', - 63950 => '硫', - 63951 => '紐', - 63952 => '類', - 63953 => '六', - 63954 => '戮', - 63955 => '陸', - 63956 => '倫', - 63957 => '崙', - 63958 => '淪', - 63959 => '輪', - 63960 => '律', - 63961 => '慄', - 63962 => '栗', - 63963 => '率', - 63964 => '隆', - 63965 => '利', - 63966 => '吏', - 63967 => '履', - 63968 => '易', - 63969 => '李', - 63970 => '梨', - 63971 => '泥', - 63972 => '理', - 63973 => '痢', - 63974 => '罹', - 63975 => '裏', - 63976 => '裡', - 63977 => '里', - 63978 => '離', - 63979 => '匿', - 63980 => '溺', - 63981 => '吝', - 63982 => '燐', - 63983 => '璘', - 63984 => '藺', - 63985 => '隣', - 63986 => '鱗', - 63987 => '麟', - 63988 => '林', - 63989 => '淋', - 63990 => '臨', - 63991 => '立', - 63992 => '笠', - 63993 => '粒', - 63994 => '狀', - 63995 => '炙', - 63996 => '識', - 63997 => '什', - 63998 => '茶', - 63999 => '刺', - 64000 => '切', - 64001 => '度', - 64002 => '拓', - 64003 => '糖', - 64004 => '宅', - 64005 => '洞', - 64006 => '暴', - 64007 => '輻', - 64008 => '行', - 64009 => '降', - 64010 => '見', - 64011 => '廓', - 64012 => '兀', - 64013 => '嗀', - 64016 => '塚', - 64018 => '晴', - 64021 => '凞', - 64022 => '猪', - 64023 => '益', - 64024 => '礼', - 64025 => '神', - 64026 => '祥', - 64027 => '福', - 64028 => '靖', - 64029 => '精', - 64030 => '羽', - 64032 => '蘒', - 64034 => '諸', - 64037 => '逸', - 64038 => '都', - 64042 => '飯', - 64043 => '飼', - 64044 => '館', - 64045 => '鶴', - 64046 => '郞', - 64047 => '隷', - 64048 => '侮', - 64049 => '僧', - 64050 => '免', - 64051 => '勉', - 64052 => '勤', - 64053 => '卑', - 64054 => '喝', - 64055 => '嘆', - 64056 => '器', - 64057 => '塀', - 64058 => '墨', - 64059 => '層', - 64060 => '屮', - 64061 => '悔', - 64062 => '慨', - 64063 => '憎', - 64064 => '懲', - 64065 => '敏', - 64066 => '既', - 64067 => '暑', - 64068 => '梅', - 64069 => '海', - 64070 => '渚', - 64071 => '漢', - 64072 => '煮', - 64073 => '爫', - 64074 => '琢', - 64075 => '碑', - 64076 => '社', - 64077 => '祉', - 64078 => '祈', - 64079 => '祐', - 64080 => '祖', - 64081 => '祝', - 64082 => '禍', - 64083 => '禎', - 64084 => '穀', - 64085 => '突', - 64086 => '節', - 64087 => '練', - 64088 => '縉', - 64089 => '繁', - 64090 => '署', - 64091 => '者', - 64092 => '臭', - 64093 => '艹', - 64094 => '艹', - 64095 => '著', - 64096 => '褐', - 64097 => '視', - 64098 => '謁', - 64099 => '謹', - 64100 => '賓', - 64101 => '贈', - 64102 => '辶', - 64103 => '逸', - 64104 => '難', - 64105 => '響', - 64106 => '頻', - 64107 => '恵', - 64108 => '𤋮', - 64109 => '舘', - 64112 => '並', - 64113 => '况', - 64114 => '全', - 64115 => '侀', - 64116 => '充', - 64117 => '冀', - 64118 => '勇', - 64119 => '勺', - 64120 => '喝', - 64121 => '啕', - 64122 => '喙', - 64123 => '嗢', - 64124 => '塚', - 64125 => '墳', - 64126 => '奄', - 64127 => '奔', - 64128 => '婢', - 64129 => '嬨', - 64130 => '廒', - 64131 => '廙', - 64132 => '彩', - 64133 => '徭', - 64134 => '惘', - 64135 => '慎', - 64136 => '愈', - 64137 => '憎', - 64138 => '慠', - 64139 => '懲', - 64140 => '戴', - 64141 => '揄', - 64142 => '搜', - 64143 => '摒', - 64144 => '敖', - 64145 => '晴', - 64146 => '朗', - 64147 => '望', - 64148 => '杖', - 64149 => '歹', - 64150 => '殺', - 64151 => '流', - 64152 => '滛', - 64153 => '滋', - 64154 => '漢', - 64155 => '瀞', - 64156 => '煮', - 64157 => '瞧', - 64158 => '爵', - 64159 => '犯', - 64160 => '猪', - 64161 => '瑱', - 64162 => '甆', - 64163 => '画', - 64164 => '瘝', - 64165 => '瘟', - 64166 => '益', - 64167 => '盛', - 64168 => '直', - 64169 => '睊', - 64170 => '着', - 64171 => '磌', - 64172 => '窱', - 64173 => '節', - 64174 => '类', - 64175 => '絛', - 64176 => '練', - 64177 => '缾', - 64178 => '者', - 64179 => '荒', - 64180 => '華', - 64181 => '蝹', - 64182 => '襁', - 64183 => '覆', - 64184 => '視', - 64185 => '調', - 64186 => '諸', - 64187 => '請', - 64188 => '謁', - 64189 => '諾', - 64190 => '諭', - 64191 => '謹', - 64192 => '變', - 64193 => '贈', - 64194 => '輸', - 64195 => '遲', - 64196 => '醙', - 64197 => '鉶', - 64198 => '陼', - 64199 => '難', - 64200 => '靖', - 64201 => '韛', - 64202 => '響', - 64203 => '頋', - 64204 => '頻', - 64205 => '鬒', - 64206 => '龜', - 64207 => '𢡊', - 64208 => '𢡄', - 64209 => '𣏕', - 64210 => '㮝', - 64211 => '䀘', - 64212 => '䀹', - 64213 => '𥉉', - 64214 => '𥳐', - 64215 => '𧻓', - 64216 => '齃', - 64217 => '龎', - 64256 => 'ff', - 64257 => 'fi', - 64258 => 'fl', - 64259 => 'ffi', - 64260 => 'ffl', - 64261 => 'st', - 64262 => 'st', - 64275 => 'մն', - 64276 => 'մե', - 64277 => 'մի', - 64278 => 'վն', - 64279 => 'մխ', - 64285 => 'יִ', - 64287 => 'ײַ', - 64288 => 'ע', - 64289 => 'א', - 64290 => 'ד', - 64291 => 'ה', - 64292 => 'כ', - 64293 => 'ל', - 64294 => 'ם', - 64295 => 'ר', - 64296 => 'ת', - 64298 => 'שׁ', - 64299 => 'שׂ', - 64300 => 'שּׁ', - 64301 => 'שּׂ', - 64302 => 'אַ', - 64303 => 'אָ', - 64304 => 'אּ', - 64305 => 'בּ', - 64306 => 'גּ', - 64307 => 'דּ', - 64308 => 'הּ', - 64309 => 'וּ', - 64310 => 'זּ', - 64312 => 'טּ', - 64313 => 'יּ', - 64314 => 'ךּ', - 64315 => 'כּ', - 64316 => 'לּ', - 64318 => 'מּ', - 64320 => 'נּ', - 64321 => 'סּ', - 64323 => 'ףּ', - 64324 => 'פּ', - 64326 => 'צּ', - 64327 => 'קּ', - 64328 => 'רּ', - 64329 => 'שּ', - 64330 => 'תּ', - 64331 => 'וֹ', - 64332 => 'בֿ', - 64333 => 'כֿ', - 64334 => 'פֿ', - 64335 => 'אל', - 64336 => 'ٱ', - 64337 => 'ٱ', - 64338 => 'ٻ', - 64339 => 'ٻ', - 64340 => 'ٻ', - 64341 => 'ٻ', - 64342 => 'پ', - 64343 => 'پ', - 64344 => 'پ', - 64345 => 'پ', - 64346 => 'ڀ', - 64347 => 'ڀ', - 64348 => 'ڀ', - 64349 => 'ڀ', - 64350 => 'ٺ', - 64351 => 'ٺ', - 64352 => 'ٺ', - 64353 => 'ٺ', - 64354 => 'ٿ', - 64355 => 'ٿ', - 64356 => 'ٿ', - 64357 => 'ٿ', - 64358 => 'ٹ', - 64359 => 'ٹ', - 64360 => 'ٹ', - 64361 => 'ٹ', - 64362 => 'ڤ', - 64363 => 'ڤ', - 64364 => 'ڤ', - 64365 => 'ڤ', - 64366 => 'ڦ', - 64367 => 'ڦ', - 64368 => 'ڦ', - 64369 => 'ڦ', - 64370 => 'ڄ', - 64371 => 'ڄ', - 64372 => 'ڄ', - 64373 => 'ڄ', - 64374 => 'ڃ', - 64375 => 'ڃ', - 64376 => 'ڃ', - 64377 => 'ڃ', - 64378 => 'چ', - 64379 => 'چ', - 64380 => 'چ', - 64381 => 'چ', - 64382 => 'ڇ', - 64383 => 'ڇ', - 64384 => 'ڇ', - 64385 => 'ڇ', - 64386 => 'ڍ', - 64387 => 'ڍ', - 64388 => 'ڌ', - 64389 => 'ڌ', - 64390 => 'ڎ', - 64391 => 'ڎ', - 64392 => 'ڈ', - 64393 => 'ڈ', - 64394 => 'ژ', - 64395 => 'ژ', - 64396 => 'ڑ', - 64397 => 'ڑ', - 64398 => 'ک', - 64399 => 'ک', - 64400 => 'ک', - 64401 => 'ک', - 64402 => 'گ', - 64403 => 'گ', - 64404 => 'گ', - 64405 => 'گ', - 64406 => 'ڳ', - 64407 => 'ڳ', - 64408 => 'ڳ', - 64409 => 'ڳ', - 64410 => 'ڱ', - 64411 => 'ڱ', - 64412 => 'ڱ', - 64413 => 'ڱ', - 64414 => 'ں', - 64415 => 'ں', - 64416 => 'ڻ', - 64417 => 'ڻ', - 64418 => 'ڻ', - 64419 => 'ڻ', - 64420 => 'ۀ', - 64421 => 'ۀ', - 64422 => 'ہ', - 64423 => 'ہ', - 64424 => 'ہ', - 64425 => 'ہ', - 64426 => 'ھ', - 64427 => 'ھ', - 64428 => 'ھ', - 64429 => 'ھ', - 64430 => 'ے', - 64431 => 'ے', - 64432 => 'ۓ', - 64433 => 'ۓ', - 64467 => 'ڭ', - 64468 => 'ڭ', - 64469 => 'ڭ', - 64470 => 'ڭ', - 64471 => 'ۇ', - 64472 => 'ۇ', - 64473 => 'ۆ', - 64474 => 'ۆ', - 64475 => 'ۈ', - 64476 => 'ۈ', - 64477 => 'ۇٴ', - 64478 => 'ۋ', - 64479 => 'ۋ', - 64480 => 'ۅ', - 64481 => 'ۅ', - 64482 => 'ۉ', - 64483 => 'ۉ', - 64484 => 'ې', - 64485 => 'ې', - 64486 => 'ې', - 64487 => 'ې', - 64488 => 'ى', - 64489 => 'ى', - 64490 => 'ئا', - 64491 => 'ئا', - 64492 => 'ئە', - 64493 => 'ئە', - 64494 => 'ئو', - 64495 => 'ئو', - 64496 => 'ئۇ', - 64497 => 'ئۇ', - 64498 => 'ئۆ', - 64499 => 'ئۆ', - 64500 => 'ئۈ', - 64501 => 'ئۈ', - 64502 => 'ئې', - 64503 => 'ئې', - 64504 => 'ئې', - 64505 => 'ئى', - 64506 => 'ئى', - 64507 => 'ئى', - 64508 => 'ی', - 64509 => 'ی', - 64510 => 'ی', - 64511 => 'ی', - 64512 => 'ئج', - 64513 => 'ئح', - 64514 => 'ئم', - 64515 => 'ئى', - 64516 => 'ئي', - 64517 => 'بج', - 64518 => 'بح', - 64519 => 'بخ', - 64520 => 'بم', - 64521 => 'بى', - 64522 => 'بي', - 64523 => 'تج', - 64524 => 'تح', - 64525 => 'تخ', - 64526 => 'تم', - 64527 => 'تى', - 64528 => 'تي', - 64529 => 'ثج', - 64530 => 'ثم', - 64531 => 'ثى', - 64532 => 'ثي', - 64533 => 'جح', - 64534 => 'جم', - 64535 => 'حج', - 64536 => 'حم', - 64537 => 'خج', - 64538 => 'خح', - 64539 => 'خم', - 64540 => 'سج', - 64541 => 'سح', - 64542 => 'سخ', - 64543 => 'سم', - 64544 => 'صح', - 64545 => 'صم', - 64546 => 'ضج', - 64547 => 'ضح', - 64548 => 'ضخ', - 64549 => 'ضم', - 64550 => 'طح', - 64551 => 'طم', - 64552 => 'ظم', - 64553 => 'عج', - 64554 => 'عم', - 64555 => 'غج', - 64556 => 'غم', - 64557 => 'فج', - 64558 => 'فح', - 64559 => 'فخ', - 64560 => 'فم', - 64561 => 'فى', - 64562 => 'في', - 64563 => 'قح', - 64564 => 'قم', - 64565 => 'قى', - 64566 => 'قي', - 64567 => 'كا', - 64568 => 'كج', - 64569 => 'كح', - 64570 => 'كخ', - 64571 => 'كل', - 64572 => 'كم', - 64573 => 'كى', - 64574 => 'كي', - 64575 => 'لج', - 64576 => 'لح', - 64577 => 'لخ', - 64578 => 'لم', - 64579 => 'لى', - 64580 => 'لي', - 64581 => 'مج', - 64582 => 'مح', - 64583 => 'مخ', - 64584 => 'مم', - 64585 => 'مى', - 64586 => 'مي', - 64587 => 'نج', - 64588 => 'نح', - 64589 => 'نخ', - 64590 => 'نم', - 64591 => 'نى', - 64592 => 'ني', - 64593 => 'هج', - 64594 => 'هم', - 64595 => 'هى', - 64596 => 'هي', - 64597 => 'يج', - 64598 => 'يح', - 64599 => 'يخ', - 64600 => 'يم', - 64601 => 'يى', - 64602 => 'يي', - 64603 => 'ذٰ', - 64604 => 'رٰ', - 64605 => 'ىٰ', - 64612 => 'ئر', - 64613 => 'ئز', - 64614 => 'ئم', - 64615 => 'ئن', - 64616 => 'ئى', - 64617 => 'ئي', - 64618 => 'بر', - 64619 => 'بز', - 64620 => 'بم', - 64621 => 'بن', - 64622 => 'بى', - 64623 => 'بي', - 64624 => 'تر', - 64625 => 'تز', - 64626 => 'تم', - 64627 => 'تن', - 64628 => 'تى', - 64629 => 'تي', - 64630 => 'ثر', - 64631 => 'ثز', - 64632 => 'ثم', - 64633 => 'ثن', - 64634 => 'ثى', - 64635 => 'ثي', - 64636 => 'فى', - 64637 => 'في', - 64638 => 'قى', - 64639 => 'قي', - 64640 => 'كا', - 64641 => 'كل', - 64642 => 'كم', - 64643 => 'كى', - 64644 => 'كي', - 64645 => 'لم', - 64646 => 'لى', - 64647 => 'لي', - 64648 => 'ما', - 64649 => 'مم', - 64650 => 'نر', - 64651 => 'نز', - 64652 => 'نم', - 64653 => 'نن', - 64654 => 'نى', - 64655 => 'ني', - 64656 => 'ىٰ', - 64657 => 'ير', - 64658 => 'يز', - 64659 => 'يم', - 64660 => 'ين', - 64661 => 'يى', - 64662 => 'يي', - 64663 => 'ئج', - 64664 => 'ئح', - 64665 => 'ئخ', - 64666 => 'ئم', - 64667 => 'ئه', - 64668 => 'بج', - 64669 => 'بح', - 64670 => 'بخ', - 64671 => 'بم', - 64672 => 'به', - 64673 => 'تج', - 64674 => 'تح', - 64675 => 'تخ', - 64676 => 'تم', - 64677 => 'ته', - 64678 => 'ثم', - 64679 => 'جح', - 64680 => 'جم', - 64681 => 'حج', - 64682 => 'حم', - 64683 => 'خج', - 64684 => 'خم', - 64685 => 'سج', - 64686 => 'سح', - 64687 => 'سخ', - 64688 => 'سم', - 64689 => 'صح', - 64690 => 'صخ', - 64691 => 'صم', - 64692 => 'ضج', - 64693 => 'ضح', - 64694 => 'ضخ', - 64695 => 'ضم', - 64696 => 'طح', - 64697 => 'ظم', - 64698 => 'عج', - 64699 => 'عم', - 64700 => 'غج', - 64701 => 'غم', - 64702 => 'فج', - 64703 => 'فح', - 64704 => 'فخ', - 64705 => 'فم', - 64706 => 'قح', - 64707 => 'قم', - 64708 => 'كج', - 64709 => 'كح', - 64710 => 'كخ', - 64711 => 'كل', - 64712 => 'كم', - 64713 => 'لج', - 64714 => 'لح', - 64715 => 'لخ', - 64716 => 'لم', - 64717 => 'له', - 64718 => 'مج', - 64719 => 'مح', - 64720 => 'مخ', - 64721 => 'مم', - 64722 => 'نج', - 64723 => 'نح', - 64724 => 'نخ', - 64725 => 'نم', - 64726 => 'نه', - 64727 => 'هج', - 64728 => 'هم', - 64729 => 'هٰ', - 64730 => 'يج', - 64731 => 'يح', - 64732 => 'يخ', - 64733 => 'يم', - 64734 => 'يه', - 64735 => 'ئم', - 64736 => 'ئه', - 64737 => 'بم', - 64738 => 'به', - 64739 => 'تم', - 64740 => 'ته', - 64741 => 'ثم', - 64742 => 'ثه', - 64743 => 'سم', - 64744 => 'سه', - 64745 => 'شم', - 64746 => 'شه', - 64747 => 'كل', - 64748 => 'كم', - 64749 => 'لم', - 64750 => 'نم', - 64751 => 'نه', - 64752 => 'يم', - 64753 => 'يه', - 64754 => 'ـَّ', - 64755 => 'ـُّ', - 64756 => 'ـِّ', - 64757 => 'طى', - 64758 => 'طي', - 64759 => 'عى', - 64760 => 'عي', - 64761 => 'غى', - 64762 => 'غي', - 64763 => 'سى', - 64764 => 'سي', - 64765 => 'شى', - 64766 => 'شي', - 64767 => 'حى', - 64768 => 'حي', - 64769 => 'جى', - 64770 => 'جي', - 64771 => 'خى', - 64772 => 'خي', - 64773 => 'صى', - 64774 => 'صي', - 64775 => 'ضى', - 64776 => 'ضي', - 64777 => 'شج', - 64778 => 'شح', - 64779 => 'شخ', - 64780 => 'شم', - 64781 => 'شر', - 64782 => 'سر', - 64783 => 'صر', - 64784 => 'ضر', - 64785 => 'طى', - 64786 => 'طي', - 64787 => 'عى', - 64788 => 'عي', - 64789 => 'غى', - 64790 => 'غي', - 64791 => 'سى', - 64792 => 'سي', - 64793 => 'شى', - 64794 => 'شي', - 64795 => 'حى', - 64796 => 'حي', - 64797 => 'جى', - 64798 => 'جي', - 64799 => 'خى', - 64800 => 'خي', - 64801 => 'صى', - 64802 => 'صي', - 64803 => 'ضى', - 64804 => 'ضي', - 64805 => 'شج', - 64806 => 'شح', - 64807 => 'شخ', - 64808 => 'شم', - 64809 => 'شر', - 64810 => 'سر', - 64811 => 'صر', - 64812 => 'ضر', - 64813 => 'شج', - 64814 => 'شح', - 64815 => 'شخ', - 64816 => 'شم', - 64817 => 'سه', - 64818 => 'شه', - 64819 => 'طم', - 64820 => 'سج', - 64821 => 'سح', - 64822 => 'سخ', - 64823 => 'شج', - 64824 => 'شح', - 64825 => 'شخ', - 64826 => 'طم', - 64827 => 'ظم', - 64828 => 'اً', - 64829 => 'اً', - 64848 => 'تجم', - 64849 => 'تحج', - 64850 => 'تحج', - 64851 => 'تحم', - 64852 => 'تخم', - 64853 => 'تمج', - 64854 => 'تمح', - 64855 => 'تمخ', - 64856 => 'جمح', - 64857 => 'جمح', - 64858 => 'حمي', - 64859 => 'حمى', - 64860 => 'سحج', - 64861 => 'سجح', - 64862 => 'سجى', - 64863 => 'سمح', - 64864 => 'سمح', - 64865 => 'سمج', - 64866 => 'سمم', - 64867 => 'سمم', - 64868 => 'صحح', - 64869 => 'صحح', - 64870 => 'صمم', - 64871 => 'شحم', - 64872 => 'شحم', - 64873 => 'شجي', - 64874 => 'شمخ', - 64875 => 'شمخ', - 64876 => 'شمم', - 64877 => 'شمم', - 64878 => 'ضحى', - 64879 => 'ضخم', - 64880 => 'ضخم', - 64881 => 'طمح', - 64882 => 'طمح', - 64883 => 'طمم', - 64884 => 'طمي', - 64885 => 'عجم', - 64886 => 'عمم', - 64887 => 'عمم', - 64888 => 'عمى', - 64889 => 'غمم', - 64890 => 'غمي', - 64891 => 'غمى', - 64892 => 'فخم', - 64893 => 'فخم', - 64894 => 'قمح', - 64895 => 'قمم', - 64896 => 'لحم', - 64897 => 'لحي', - 64898 => 'لحى', - 64899 => 'لجج', - 64900 => 'لجج', - 64901 => 'لخم', - 64902 => 'لخم', - 64903 => 'لمح', - 64904 => 'لمح', - 64905 => 'محج', - 64906 => 'محم', - 64907 => 'محي', - 64908 => 'مجح', - 64909 => 'مجم', - 64910 => 'مخج', - 64911 => 'مخم', - 64914 => 'مجخ', - 64915 => 'همج', - 64916 => 'همم', - 64917 => 'نحم', - 64918 => 'نحى', - 64919 => 'نجم', - 64920 => 'نجم', - 64921 => 'نجى', - 64922 => 'نمي', - 64923 => 'نمى', - 64924 => 'يمم', - 64925 => 'يمم', - 64926 => 'بخي', - 64927 => 'تجي', - 64928 => 'تجى', - 64929 => 'تخي', - 64930 => 'تخى', - 64931 => 'تمي', - 64932 => 'تمى', - 64933 => 'جمي', - 64934 => 'جحى', - 64935 => 'جمى', - 64936 => 'سخى', - 64937 => 'صحي', - 64938 => 'شحي', - 64939 => 'ضحي', - 64940 => 'لجي', - 64941 => 'لمي', - 64942 => 'يحي', - 64943 => 'يجي', - 64944 => 'يمي', - 64945 => 'ممي', - 64946 => 'قمي', - 64947 => 'نحي', - 64948 => 'قمح', - 64949 => 'لحم', - 64950 => 'عمي', - 64951 => 'كمي', - 64952 => 'نجح', - 64953 => 'مخي', - 64954 => 'لجم', - 64955 => 'كمم', - 64956 => 'لجم', - 64957 => 'نجح', - 64958 => 'جحي', - 64959 => 'حجي', - 64960 => 'مجي', - 64961 => 'فمي', - 64962 => 'بحي', - 64963 => 'كمم', - 64964 => 'عجم', - 64965 => 'صمم', - 64966 => 'سخي', - 64967 => 'نجي', - 65008 => 'صلے', - 65009 => 'قلے', - 65010 => 'الله', - 65011 => 'اكبر', - 65012 => 'محمد', - 65013 => 'صلعم', - 65014 => 'رسول', - 65015 => 'عليه', - 65016 => 'وسلم', - 65017 => 'صلى', - 65020 => 'ریال', - 65041 => '、', - 65047 => '〖', - 65048 => '〗', - 65073 => '—', - 65074 => '–', - 65081 => '〔', - 65082 => '〕', - 65083 => '【', - 65084 => '】', - 65085 => '《', - 65086 => '》', - 65087 => '〈', - 65088 => '〉', - 65089 => '「', - 65090 => '」', - 65091 => '『', - 65092 => '』', - 65105 => '、', - 65112 => '—', - 65117 => '〔', - 65118 => '〕', - 65123 => '-', - 65137 => 'ـً', - 65143 => 'ـَ', - 65145 => 'ـُ', - 65147 => 'ـِ', - 65149 => 'ـّ', - 65151 => 'ـْ', - 65152 => 'ء', - 65153 => 'آ', - 65154 => 'آ', - 65155 => 'أ', - 65156 => 'أ', - 65157 => 'ؤ', - 65158 => 'ؤ', - 65159 => 'إ', - 65160 => 'إ', - 65161 => 'ئ', - 65162 => 'ئ', - 65163 => 'ئ', - 65164 => 'ئ', - 65165 => 'ا', - 65166 => 'ا', - 65167 => 'ب', - 65168 => 'ب', - 65169 => 'ب', - 65170 => 'ب', - 65171 => 'ة', - 65172 => 'ة', - 65173 => 'ت', - 65174 => 'ت', - 65175 => 'ت', - 65176 => 'ت', - 65177 => 'ث', - 65178 => 'ث', - 65179 => 'ث', - 65180 => 'ث', - 65181 => 'ج', - 65182 => 'ج', - 65183 => 'ج', - 65184 => 'ج', - 65185 => 'ح', - 65186 => 'ح', - 65187 => 'ح', - 65188 => 'ح', - 65189 => 'خ', - 65190 => 'خ', - 65191 => 'خ', - 65192 => 'خ', - 65193 => 'د', - 65194 => 'د', - 65195 => 'ذ', - 65196 => 'ذ', - 65197 => 'ر', - 65198 => 'ر', - 65199 => 'ز', - 65200 => 'ز', - 65201 => 'س', - 65202 => 'س', - 65203 => 'س', - 65204 => 'س', - 65205 => 'ش', - 65206 => 'ش', - 65207 => 'ش', - 65208 => 'ش', - 65209 => 'ص', - 65210 => 'ص', - 65211 => 'ص', - 65212 => 'ص', - 65213 => 'ض', - 65214 => 'ض', - 65215 => 'ض', - 65216 => 'ض', - 65217 => 'ط', - 65218 => 'ط', - 65219 => 'ط', - 65220 => 'ط', - 65221 => 'ظ', - 65222 => 'ظ', - 65223 => 'ظ', - 65224 => 'ظ', - 65225 => 'ع', - 65226 => 'ع', - 65227 => 'ع', - 65228 => 'ع', - 65229 => 'غ', - 65230 => 'غ', - 65231 => 'غ', - 65232 => 'غ', - 65233 => 'ف', - 65234 => 'ف', - 65235 => 'ف', - 65236 => 'ف', - 65237 => 'ق', - 65238 => 'ق', - 65239 => 'ق', - 65240 => 'ق', - 65241 => 'ك', - 65242 => 'ك', - 65243 => 'ك', - 65244 => 'ك', - 65245 => 'ل', - 65246 => 'ل', - 65247 => 'ل', - 65248 => 'ل', - 65249 => 'م', - 65250 => 'م', - 65251 => 'م', - 65252 => 'م', - 65253 => 'ن', - 65254 => 'ن', - 65255 => 'ن', - 65256 => 'ن', - 65257 => 'ه', - 65258 => 'ه', - 65259 => 'ه', - 65260 => 'ه', - 65261 => 'و', - 65262 => 'و', - 65263 => 'ى', - 65264 => 'ى', - 65265 => 'ي', - 65266 => 'ي', - 65267 => 'ي', - 65268 => 'ي', - 65269 => 'لآ', - 65270 => 'لآ', - 65271 => 'لأ', - 65272 => 'لأ', - 65273 => 'لإ', - 65274 => 'لإ', - 65275 => 'لا', - 65276 => 'لا', - 65293 => '-', - 65294 => '.', - 65296 => '0', - 65297 => '1', - 65298 => '2', - 65299 => '3', - 65300 => '4', - 65301 => '5', - 65302 => '6', - 65303 => '7', - 65304 => '8', - 65305 => '9', - 65313 => 'a', - 65314 => 'b', - 65315 => 'c', - 65316 => 'd', - 65317 => 'e', - 65318 => 'f', - 65319 => 'g', - 65320 => 'h', - 65321 => 'i', - 65322 => 'j', - 65323 => 'k', - 65324 => 'l', - 65325 => 'm', - 65326 => 'n', - 65327 => 'o', - 65328 => 'p', - 65329 => 'q', - 65330 => 'r', - 65331 => 's', - 65332 => 't', - 65333 => 'u', - 65334 => 'v', - 65335 => 'w', - 65336 => 'x', - 65337 => 'y', - 65338 => 'z', - 65345 => 'a', - 65346 => 'b', - 65347 => 'c', - 65348 => 'd', - 65349 => 'e', - 65350 => 'f', - 65351 => 'g', - 65352 => 'h', - 65353 => 'i', - 65354 => 'j', - 65355 => 'k', - 65356 => 'l', - 65357 => 'm', - 65358 => 'n', - 65359 => 'o', - 65360 => 'p', - 65361 => 'q', - 65362 => 'r', - 65363 => 's', - 65364 => 't', - 65365 => 'u', - 65366 => 'v', - 65367 => 'w', - 65368 => 'x', - 65369 => 'y', - 65370 => 'z', - 65375 => '⦅', - 65376 => '⦆', - 65377 => '.', - 65378 => '「', - 65379 => '」', - 65380 => '、', - 65381 => '・', - 65382 => 'ヲ', - 65383 => 'ァ', - 65384 => 'ィ', - 65385 => 'ゥ', - 65386 => 'ェ', - 65387 => 'ォ', - 65388 => 'ャ', - 65389 => 'ュ', - 65390 => 'ョ', - 65391 => 'ッ', - 65392 => 'ー', - 65393 => 'ア', - 65394 => 'イ', - 65395 => 'ウ', - 65396 => 'エ', - 65397 => 'オ', - 65398 => 'カ', - 65399 => 'キ', - 65400 => 'ク', - 65401 => 'ケ', - 65402 => 'コ', - 65403 => 'サ', - 65404 => 'シ', - 65405 => 'ス', - 65406 => 'セ', - 65407 => 'ソ', - 65408 => 'タ', - 65409 => 'チ', - 65410 => 'ツ', - 65411 => 'テ', - 65412 => 'ト', - 65413 => 'ナ', - 65414 => 'ニ', - 65415 => 'ヌ', - 65416 => 'ネ', - 65417 => 'ノ', - 65418 => 'ハ', - 65419 => 'ヒ', - 65420 => 'フ', - 65421 => 'ヘ', - 65422 => 'ホ', - 65423 => 'マ', - 65424 => 'ミ', - 65425 => 'ム', - 65426 => 'メ', - 65427 => 'モ', - 65428 => 'ヤ', - 65429 => 'ユ', - 65430 => 'ヨ', - 65431 => 'ラ', - 65432 => 'リ', - 65433 => 'ル', - 65434 => 'レ', - 65435 => 'ロ', - 65436 => 'ワ', - 65437 => 'ン', - 65438 => '゙', - 65439 => '゚', - 65441 => 'ᄀ', - 65442 => 'ᄁ', - 65443 => 'ᆪ', - 65444 => 'ᄂ', - 65445 => 'ᆬ', - 65446 => 'ᆭ', - 65447 => 'ᄃ', - 65448 => 'ᄄ', - 65449 => 'ᄅ', - 65450 => 'ᆰ', - 65451 => 'ᆱ', - 65452 => 'ᆲ', - 65453 => 'ᆳ', - 65454 => 'ᆴ', - 65455 => 'ᆵ', - 65456 => 'ᄚ', - 65457 => 'ᄆ', - 65458 => 'ᄇ', - 65459 => 'ᄈ', - 65460 => 'ᄡ', - 65461 => 'ᄉ', - 65462 => 'ᄊ', - 65463 => 'ᄋ', - 65464 => 'ᄌ', - 65465 => 'ᄍ', - 65466 => 'ᄎ', - 65467 => 'ᄏ', - 65468 => 'ᄐ', - 65469 => 'ᄑ', - 65470 => 'ᄒ', - 65474 => 'ᅡ', - 65475 => 'ᅢ', - 65476 => 'ᅣ', - 65477 => 'ᅤ', - 65478 => 'ᅥ', - 65479 => 'ᅦ', - 65482 => 'ᅧ', - 65483 => 'ᅨ', - 65484 => 'ᅩ', - 65485 => 'ᅪ', - 65486 => 'ᅫ', - 65487 => 'ᅬ', - 65490 => 'ᅭ', - 65491 => 'ᅮ', - 65492 => 'ᅯ', - 65493 => 'ᅰ', - 65494 => 'ᅱ', - 65495 => 'ᅲ', - 65498 => 'ᅳ', - 65499 => 'ᅴ', - 65500 => 'ᅵ', - 65504 => '¢', - 65505 => '£', - 65506 => '¬', - 65508 => '¦', - 65509 => '¥', - 65510 => '₩', - 65512 => '│', - 65513 => '←', - 65514 => '↑', - 65515 => '→', - 65516 => '↓', - 65517 => '■', - 65518 => '○', - 66560 => '𐐨', - 66561 => '𐐩', - 66562 => '𐐪', - 66563 => '𐐫', - 66564 => '𐐬', - 66565 => '𐐭', - 66566 => '𐐮', - 66567 => '𐐯', - 66568 => '𐐰', - 66569 => '𐐱', - 66570 => '𐐲', - 66571 => '𐐳', - 66572 => '𐐴', - 66573 => '𐐵', - 66574 => '𐐶', - 66575 => '𐐷', - 66576 => '𐐸', - 66577 => '𐐹', - 66578 => '𐐺', - 66579 => '𐐻', - 66580 => '𐐼', - 66581 => '𐐽', - 66582 => '𐐾', - 66583 => '𐐿', - 66584 => '𐑀', - 66585 => '𐑁', - 66586 => '𐑂', - 66587 => '𐑃', - 66588 => '𐑄', - 66589 => '𐑅', - 66590 => '𐑆', - 66591 => '𐑇', - 66592 => '𐑈', - 66593 => '𐑉', - 66594 => '𐑊', - 66595 => '𐑋', - 66596 => '𐑌', - 66597 => '𐑍', - 66598 => '𐑎', - 66599 => '𐑏', - 66736 => '𐓘', - 66737 => '𐓙', - 66738 => '𐓚', - 66739 => '𐓛', - 66740 => '𐓜', - 66741 => '𐓝', - 66742 => '𐓞', - 66743 => '𐓟', - 66744 => '𐓠', - 66745 => '𐓡', - 66746 => '𐓢', - 66747 => '𐓣', - 66748 => '𐓤', - 66749 => '𐓥', - 66750 => '𐓦', - 66751 => '𐓧', - 66752 => '𐓨', - 66753 => '𐓩', - 66754 => '𐓪', - 66755 => '𐓫', - 66756 => '𐓬', - 66757 => '𐓭', - 66758 => '𐓮', - 66759 => '𐓯', - 66760 => '𐓰', - 66761 => '𐓱', - 66762 => '𐓲', - 66763 => '𐓳', - 66764 => '𐓴', - 66765 => '𐓵', - 66766 => '𐓶', - 66767 => '𐓷', - 66768 => '𐓸', - 66769 => '𐓹', - 66770 => '𐓺', - 66771 => '𐓻', - 68736 => '𐳀', - 68737 => '𐳁', - 68738 => '𐳂', - 68739 => '𐳃', - 68740 => '𐳄', - 68741 => '𐳅', - 68742 => '𐳆', - 68743 => '𐳇', - 68744 => '𐳈', - 68745 => '𐳉', - 68746 => '𐳊', - 68747 => '𐳋', - 68748 => '𐳌', - 68749 => '𐳍', - 68750 => '𐳎', - 68751 => '𐳏', - 68752 => '𐳐', - 68753 => '𐳑', - 68754 => '𐳒', - 68755 => '𐳓', - 68756 => '𐳔', - 68757 => '𐳕', - 68758 => '𐳖', - 68759 => '𐳗', - 68760 => '𐳘', - 68761 => '𐳙', - 68762 => '𐳚', - 68763 => '𐳛', - 68764 => '𐳜', - 68765 => '𐳝', - 68766 => '𐳞', - 68767 => '𐳟', - 68768 => '𐳠', - 68769 => '𐳡', - 68770 => '𐳢', - 68771 => '𐳣', - 68772 => '𐳤', - 68773 => '𐳥', - 68774 => '𐳦', - 68775 => '𐳧', - 68776 => '𐳨', - 68777 => '𐳩', - 68778 => '𐳪', - 68779 => '𐳫', - 68780 => '𐳬', - 68781 => '𐳭', - 68782 => '𐳮', - 68783 => '𐳯', - 68784 => '𐳰', - 68785 => '𐳱', - 68786 => '𐳲', - 71840 => '𑣀', - 71841 => '𑣁', - 71842 => '𑣂', - 71843 => '𑣃', - 71844 => '𑣄', - 71845 => '𑣅', - 71846 => '𑣆', - 71847 => '𑣇', - 71848 => '𑣈', - 71849 => '𑣉', - 71850 => '𑣊', - 71851 => '𑣋', - 71852 => '𑣌', - 71853 => '𑣍', - 71854 => '𑣎', - 71855 => '𑣏', - 71856 => '𑣐', - 71857 => '𑣑', - 71858 => '𑣒', - 71859 => '𑣓', - 71860 => '𑣔', - 71861 => '𑣕', - 71862 => '𑣖', - 71863 => '𑣗', - 71864 => '𑣘', - 71865 => '𑣙', - 71866 => '𑣚', - 71867 => '𑣛', - 71868 => '𑣜', - 71869 => '𑣝', - 71870 => '𑣞', - 71871 => '𑣟', - 93760 => '𖹠', - 93761 => '𖹡', - 93762 => '𖹢', - 93763 => '𖹣', - 93764 => '𖹤', - 93765 => '𖹥', - 93766 => '𖹦', - 93767 => '𖹧', - 93768 => '𖹨', - 93769 => '𖹩', - 93770 => '𖹪', - 93771 => '𖹫', - 93772 => '𖹬', - 93773 => '𖹭', - 93774 => '𖹮', - 93775 => '𖹯', - 93776 => '𖹰', - 93777 => '𖹱', - 93778 => '𖹲', - 93779 => '𖹳', - 93780 => '𖹴', - 93781 => '𖹵', - 93782 => '𖹶', - 93783 => '𖹷', - 93784 => '𖹸', - 93785 => '𖹹', - 93786 => '𖹺', - 93787 => '𖹻', - 93788 => '𖹼', - 93789 => '𖹽', - 93790 => '𖹾', - 93791 => '𖹿', - 119134 => '𝅗𝅥', - 119135 => '𝅘𝅥', - 119136 => '𝅘𝅥𝅮', - 119137 => '𝅘𝅥𝅯', - 119138 => '𝅘𝅥𝅰', - 119139 => '𝅘𝅥𝅱', - 119140 => '𝅘𝅥𝅲', - 119227 => '𝆹𝅥', - 119228 => '𝆺𝅥', - 119229 => '𝆹𝅥𝅮', - 119230 => '𝆺𝅥𝅮', - 119231 => '𝆹𝅥𝅯', - 119232 => '𝆺𝅥𝅯', - 119808 => 'a', - 119809 => 'b', - 119810 => 'c', - 119811 => 'd', - 119812 => 'e', - 119813 => 'f', - 119814 => 'g', - 119815 => 'h', - 119816 => 'i', - 119817 => 'j', - 119818 => 'k', - 119819 => 'l', - 119820 => 'm', - 119821 => 'n', - 119822 => 'o', - 119823 => 'p', - 119824 => 'q', - 119825 => 'r', - 119826 => 's', - 119827 => 't', - 119828 => 'u', - 119829 => 'v', - 119830 => 'w', - 119831 => 'x', - 119832 => 'y', - 119833 => 'z', - 119834 => 'a', - 119835 => 'b', - 119836 => 'c', - 119837 => 'd', - 119838 => 'e', - 119839 => 'f', - 119840 => 'g', - 119841 => 'h', - 119842 => 'i', - 119843 => 'j', - 119844 => 'k', - 119845 => 'l', - 119846 => 'm', - 119847 => 'n', - 119848 => 'o', - 119849 => 'p', - 119850 => 'q', - 119851 => 'r', - 119852 => 's', - 119853 => 't', - 119854 => 'u', - 119855 => 'v', - 119856 => 'w', - 119857 => 'x', - 119858 => 'y', - 119859 => 'z', - 119860 => 'a', - 119861 => 'b', - 119862 => 'c', - 119863 => 'd', - 119864 => 'e', - 119865 => 'f', - 119866 => 'g', - 119867 => 'h', - 119868 => 'i', - 119869 => 'j', - 119870 => 'k', - 119871 => 'l', - 119872 => 'm', - 119873 => 'n', - 119874 => 'o', - 119875 => 'p', - 119876 => 'q', - 119877 => 'r', - 119878 => 's', - 119879 => 't', - 119880 => 'u', - 119881 => 'v', - 119882 => 'w', - 119883 => 'x', - 119884 => 'y', - 119885 => 'z', - 119886 => 'a', - 119887 => 'b', - 119888 => 'c', - 119889 => 'd', - 119890 => 'e', - 119891 => 'f', - 119892 => 'g', - 119894 => 'i', - 119895 => 'j', - 119896 => 'k', - 119897 => 'l', - 119898 => 'm', - 119899 => 'n', - 119900 => 'o', - 119901 => 'p', - 119902 => 'q', - 119903 => 'r', - 119904 => 's', - 119905 => 't', - 119906 => 'u', - 119907 => 'v', - 119908 => 'w', - 119909 => 'x', - 119910 => 'y', - 119911 => 'z', - 119912 => 'a', - 119913 => 'b', - 119914 => 'c', - 119915 => 'd', - 119916 => 'e', - 119917 => 'f', - 119918 => 'g', - 119919 => 'h', - 119920 => 'i', - 119921 => 'j', - 119922 => 'k', - 119923 => 'l', - 119924 => 'm', - 119925 => 'n', - 119926 => 'o', - 119927 => 'p', - 119928 => 'q', - 119929 => 'r', - 119930 => 's', - 119931 => 't', - 119932 => 'u', - 119933 => 'v', - 119934 => 'w', - 119935 => 'x', - 119936 => 'y', - 119937 => 'z', - 119938 => 'a', - 119939 => 'b', - 119940 => 'c', - 119941 => 'd', - 119942 => 'e', - 119943 => 'f', - 119944 => 'g', - 119945 => 'h', - 119946 => 'i', - 119947 => 'j', - 119948 => 'k', - 119949 => 'l', - 119950 => 'm', - 119951 => 'n', - 119952 => 'o', - 119953 => 'p', - 119954 => 'q', - 119955 => 'r', - 119956 => 's', - 119957 => 't', - 119958 => 'u', - 119959 => 'v', - 119960 => 'w', - 119961 => 'x', - 119962 => 'y', - 119963 => 'z', - 119964 => 'a', - 119966 => 'c', - 119967 => 'd', - 119970 => 'g', - 119973 => 'j', - 119974 => 'k', - 119977 => 'n', - 119978 => 'o', - 119979 => 'p', - 119980 => 'q', - 119982 => 's', - 119983 => 't', - 119984 => 'u', - 119985 => 'v', - 119986 => 'w', - 119987 => 'x', - 119988 => 'y', - 119989 => 'z', - 119990 => 'a', - 119991 => 'b', - 119992 => 'c', - 119993 => 'd', - 119995 => 'f', - 119997 => 'h', - 119998 => 'i', - 119999 => 'j', - 120000 => 'k', - 120001 => 'l', - 120002 => 'm', - 120003 => 'n', - 120005 => 'p', - 120006 => 'q', - 120007 => 'r', - 120008 => 's', - 120009 => 't', - 120010 => 'u', - 120011 => 'v', - 120012 => 'w', - 120013 => 'x', - 120014 => 'y', - 120015 => 'z', - 120016 => 'a', - 120017 => 'b', - 120018 => 'c', - 120019 => 'd', - 120020 => 'e', - 120021 => 'f', - 120022 => 'g', - 120023 => 'h', - 120024 => 'i', - 120025 => 'j', - 120026 => 'k', - 120027 => 'l', - 120028 => 'm', - 120029 => 'n', - 120030 => 'o', - 120031 => 'p', - 120032 => 'q', - 120033 => 'r', - 120034 => 's', - 120035 => 't', - 120036 => 'u', - 120037 => 'v', - 120038 => 'w', - 120039 => 'x', - 120040 => 'y', - 120041 => 'z', - 120042 => 'a', - 120043 => 'b', - 120044 => 'c', - 120045 => 'd', - 120046 => 'e', - 120047 => 'f', - 120048 => 'g', - 120049 => 'h', - 120050 => 'i', - 120051 => 'j', - 120052 => 'k', - 120053 => 'l', - 120054 => 'm', - 120055 => 'n', - 120056 => 'o', - 120057 => 'p', - 120058 => 'q', - 120059 => 'r', - 120060 => 's', - 120061 => 't', - 120062 => 'u', - 120063 => 'v', - 120064 => 'w', - 120065 => 'x', - 120066 => 'y', - 120067 => 'z', - 120068 => 'a', - 120069 => 'b', - 120071 => 'd', - 120072 => 'e', - 120073 => 'f', - 120074 => 'g', - 120077 => 'j', - 120078 => 'k', - 120079 => 'l', - 120080 => 'm', - 120081 => 'n', - 120082 => 'o', - 120083 => 'p', - 120084 => 'q', - 120086 => 's', - 120087 => 't', - 120088 => 'u', - 120089 => 'v', - 120090 => 'w', - 120091 => 'x', - 120092 => 'y', - 120094 => 'a', - 120095 => 'b', - 120096 => 'c', - 120097 => 'd', - 120098 => 'e', - 120099 => 'f', - 120100 => 'g', - 120101 => 'h', - 120102 => 'i', - 120103 => 'j', - 120104 => 'k', - 120105 => 'l', - 120106 => 'm', - 120107 => 'n', - 120108 => 'o', - 120109 => 'p', - 120110 => 'q', - 120111 => 'r', - 120112 => 's', - 120113 => 't', - 120114 => 'u', - 120115 => 'v', - 120116 => 'w', - 120117 => 'x', - 120118 => 'y', - 120119 => 'z', - 120120 => 'a', - 120121 => 'b', - 120123 => 'd', - 120124 => 'e', - 120125 => 'f', - 120126 => 'g', - 120128 => 'i', - 120129 => 'j', - 120130 => 'k', - 120131 => 'l', - 120132 => 'm', - 120134 => 'o', - 120138 => 's', - 120139 => 't', - 120140 => 'u', - 120141 => 'v', - 120142 => 'w', - 120143 => 'x', - 120144 => 'y', - 120146 => 'a', - 120147 => 'b', - 120148 => 'c', - 120149 => 'd', - 120150 => 'e', - 120151 => 'f', - 120152 => 'g', - 120153 => 'h', - 120154 => 'i', - 120155 => 'j', - 120156 => 'k', - 120157 => 'l', - 120158 => 'm', - 120159 => 'n', - 120160 => 'o', - 120161 => 'p', - 120162 => 'q', - 120163 => 'r', - 120164 => 's', - 120165 => 't', - 120166 => 'u', - 120167 => 'v', - 120168 => 'w', - 120169 => 'x', - 120170 => 'y', - 120171 => 'z', - 120172 => 'a', - 120173 => 'b', - 120174 => 'c', - 120175 => 'd', - 120176 => 'e', - 120177 => 'f', - 120178 => 'g', - 120179 => 'h', - 120180 => 'i', - 120181 => 'j', - 120182 => 'k', - 120183 => 'l', - 120184 => 'm', - 120185 => 'n', - 120186 => 'o', - 120187 => 'p', - 120188 => 'q', - 120189 => 'r', - 120190 => 's', - 120191 => 't', - 120192 => 'u', - 120193 => 'v', - 120194 => 'w', - 120195 => 'x', - 120196 => 'y', - 120197 => 'z', - 120198 => 'a', - 120199 => 'b', - 120200 => 'c', - 120201 => 'd', - 120202 => 'e', - 120203 => 'f', - 120204 => 'g', - 120205 => 'h', - 120206 => 'i', - 120207 => 'j', - 120208 => 'k', - 120209 => 'l', - 120210 => 'm', - 120211 => 'n', - 120212 => 'o', - 120213 => 'p', - 120214 => 'q', - 120215 => 'r', - 120216 => 's', - 120217 => 't', - 120218 => 'u', - 120219 => 'v', - 120220 => 'w', - 120221 => 'x', - 120222 => 'y', - 120223 => 'z', - 120224 => 'a', - 120225 => 'b', - 120226 => 'c', - 120227 => 'd', - 120228 => 'e', - 120229 => 'f', - 120230 => 'g', - 120231 => 'h', - 120232 => 'i', - 120233 => 'j', - 120234 => 'k', - 120235 => 'l', - 120236 => 'm', - 120237 => 'n', - 120238 => 'o', - 120239 => 'p', - 120240 => 'q', - 120241 => 'r', - 120242 => 's', - 120243 => 't', - 120244 => 'u', - 120245 => 'v', - 120246 => 'w', - 120247 => 'x', - 120248 => 'y', - 120249 => 'z', - 120250 => 'a', - 120251 => 'b', - 120252 => 'c', - 120253 => 'd', - 120254 => 'e', - 120255 => 'f', - 120256 => 'g', - 120257 => 'h', - 120258 => 'i', - 120259 => 'j', - 120260 => 'k', - 120261 => 'l', - 120262 => 'm', - 120263 => 'n', - 120264 => 'o', - 120265 => 'p', - 120266 => 'q', - 120267 => 'r', - 120268 => 's', - 120269 => 't', - 120270 => 'u', - 120271 => 'v', - 120272 => 'w', - 120273 => 'x', - 120274 => 'y', - 120275 => 'z', - 120276 => 'a', - 120277 => 'b', - 120278 => 'c', - 120279 => 'd', - 120280 => 'e', - 120281 => 'f', - 120282 => 'g', - 120283 => 'h', - 120284 => 'i', - 120285 => 'j', - 120286 => 'k', - 120287 => 'l', - 120288 => 'm', - 120289 => 'n', - 120290 => 'o', - 120291 => 'p', - 120292 => 'q', - 120293 => 'r', - 120294 => 's', - 120295 => 't', - 120296 => 'u', - 120297 => 'v', - 120298 => 'w', - 120299 => 'x', - 120300 => 'y', - 120301 => 'z', - 120302 => 'a', - 120303 => 'b', - 120304 => 'c', - 120305 => 'd', - 120306 => 'e', - 120307 => 'f', - 120308 => 'g', - 120309 => 'h', - 120310 => 'i', - 120311 => 'j', - 120312 => 'k', - 120313 => 'l', - 120314 => 'm', - 120315 => 'n', - 120316 => 'o', - 120317 => 'p', - 120318 => 'q', - 120319 => 'r', - 120320 => 's', - 120321 => 't', - 120322 => 'u', - 120323 => 'v', - 120324 => 'w', - 120325 => 'x', - 120326 => 'y', - 120327 => 'z', - 120328 => 'a', - 120329 => 'b', - 120330 => 'c', - 120331 => 'd', - 120332 => 'e', - 120333 => 'f', - 120334 => 'g', - 120335 => 'h', - 120336 => 'i', - 120337 => 'j', - 120338 => 'k', - 120339 => 'l', - 120340 => 'm', - 120341 => 'n', - 120342 => 'o', - 120343 => 'p', - 120344 => 'q', - 120345 => 'r', - 120346 => 's', - 120347 => 't', - 120348 => 'u', - 120349 => 'v', - 120350 => 'w', - 120351 => 'x', - 120352 => 'y', - 120353 => 'z', - 120354 => 'a', - 120355 => 'b', - 120356 => 'c', - 120357 => 'd', - 120358 => 'e', - 120359 => 'f', - 120360 => 'g', - 120361 => 'h', - 120362 => 'i', - 120363 => 'j', - 120364 => 'k', - 120365 => 'l', - 120366 => 'm', - 120367 => 'n', - 120368 => 'o', - 120369 => 'p', - 120370 => 'q', - 120371 => 'r', - 120372 => 's', - 120373 => 't', - 120374 => 'u', - 120375 => 'v', - 120376 => 'w', - 120377 => 'x', - 120378 => 'y', - 120379 => 'z', - 120380 => 'a', - 120381 => 'b', - 120382 => 'c', - 120383 => 'd', - 120384 => 'e', - 120385 => 'f', - 120386 => 'g', - 120387 => 'h', - 120388 => 'i', - 120389 => 'j', - 120390 => 'k', - 120391 => 'l', - 120392 => 'm', - 120393 => 'n', - 120394 => 'o', - 120395 => 'p', - 120396 => 'q', - 120397 => 'r', - 120398 => 's', - 120399 => 't', - 120400 => 'u', - 120401 => 'v', - 120402 => 'w', - 120403 => 'x', - 120404 => 'y', - 120405 => 'z', - 120406 => 'a', - 120407 => 'b', - 120408 => 'c', - 120409 => 'd', - 120410 => 'e', - 120411 => 'f', - 120412 => 'g', - 120413 => 'h', - 120414 => 'i', - 120415 => 'j', - 120416 => 'k', - 120417 => 'l', - 120418 => 'm', - 120419 => 'n', - 120420 => 'o', - 120421 => 'p', - 120422 => 'q', - 120423 => 'r', - 120424 => 's', - 120425 => 't', - 120426 => 'u', - 120427 => 'v', - 120428 => 'w', - 120429 => 'x', - 120430 => 'y', - 120431 => 'z', - 120432 => 'a', - 120433 => 'b', - 120434 => 'c', - 120435 => 'd', - 120436 => 'e', - 120437 => 'f', - 120438 => 'g', - 120439 => 'h', - 120440 => 'i', - 120441 => 'j', - 120442 => 'k', - 120443 => 'l', - 120444 => 'm', - 120445 => 'n', - 120446 => 'o', - 120447 => 'p', - 120448 => 'q', - 120449 => 'r', - 120450 => 's', - 120451 => 't', - 120452 => 'u', - 120453 => 'v', - 120454 => 'w', - 120455 => 'x', - 120456 => 'y', - 120457 => 'z', - 120458 => 'a', - 120459 => 'b', - 120460 => 'c', - 120461 => 'd', - 120462 => 'e', - 120463 => 'f', - 120464 => 'g', - 120465 => 'h', - 120466 => 'i', - 120467 => 'j', - 120468 => 'k', - 120469 => 'l', - 120470 => 'm', - 120471 => 'n', - 120472 => 'o', - 120473 => 'p', - 120474 => 'q', - 120475 => 'r', - 120476 => 's', - 120477 => 't', - 120478 => 'u', - 120479 => 'v', - 120480 => 'w', - 120481 => 'x', - 120482 => 'y', - 120483 => 'z', - 120484 => 'ı', - 120485 => 'ȷ', - 120488 => 'α', - 120489 => 'β', - 120490 => 'γ', - 120491 => 'δ', - 120492 => 'ε', - 120493 => 'ζ', - 120494 => 'η', - 120495 => 'θ', - 120496 => 'ι', - 120497 => 'κ', - 120498 => 'λ', - 120499 => 'μ', - 120500 => 'ν', - 120501 => 'ξ', - 120502 => 'ο', - 120503 => 'π', - 120504 => 'ρ', - 120505 => 'θ', - 120506 => 'σ', - 120507 => 'τ', - 120508 => 'υ', - 120509 => 'φ', - 120510 => 'χ', - 120511 => 'ψ', - 120512 => 'ω', - 120513 => '∇', - 120514 => 'α', - 120515 => 'β', - 120516 => 'γ', - 120517 => 'δ', - 120518 => 'ε', - 120519 => 'ζ', - 120520 => 'η', - 120521 => 'θ', - 120522 => 'ι', - 120523 => 'κ', - 120524 => 'λ', - 120525 => 'μ', - 120526 => 'ν', - 120527 => 'ξ', - 120528 => 'ο', - 120529 => 'π', - 120530 => 'ρ', - 120531 => 'σ', - 120532 => 'σ', - 120533 => 'τ', - 120534 => 'υ', - 120535 => 'φ', - 120536 => 'χ', - 120537 => 'ψ', - 120538 => 'ω', - 120539 => '∂', - 120540 => 'ε', - 120541 => 'θ', - 120542 => 'κ', - 120543 => 'φ', - 120544 => 'ρ', - 120545 => 'π', - 120546 => 'α', - 120547 => 'β', - 120548 => 'γ', - 120549 => 'δ', - 120550 => 'ε', - 120551 => 'ζ', - 120552 => 'η', - 120553 => 'θ', - 120554 => 'ι', - 120555 => 'κ', - 120556 => 'λ', - 120557 => 'μ', - 120558 => 'ν', - 120559 => 'ξ', - 120560 => 'ο', - 120561 => 'π', - 120562 => 'ρ', - 120563 => 'θ', - 120564 => 'σ', - 120565 => 'τ', - 120566 => 'υ', - 120567 => 'φ', - 120568 => 'χ', - 120569 => 'ψ', - 120570 => 'ω', - 120571 => '∇', - 120572 => 'α', - 120573 => 'β', - 120574 => 'γ', - 120575 => 'δ', - 120576 => 'ε', - 120577 => 'ζ', - 120578 => 'η', - 120579 => 'θ', - 120580 => 'ι', - 120581 => 'κ', - 120582 => 'λ', - 120583 => 'μ', - 120584 => 'ν', - 120585 => 'ξ', - 120586 => 'ο', - 120587 => 'π', - 120588 => 'ρ', - 120589 => 'σ', - 120590 => 'σ', - 120591 => 'τ', - 120592 => 'υ', - 120593 => 'φ', - 120594 => 'χ', - 120595 => 'ψ', - 120596 => 'ω', - 120597 => '∂', - 120598 => 'ε', - 120599 => 'θ', - 120600 => 'κ', - 120601 => 'φ', - 120602 => 'ρ', - 120603 => 'π', - 120604 => 'α', - 120605 => 'β', - 120606 => 'γ', - 120607 => 'δ', - 120608 => 'ε', - 120609 => 'ζ', - 120610 => 'η', - 120611 => 'θ', - 120612 => 'ι', - 120613 => 'κ', - 120614 => 'λ', - 120615 => 'μ', - 120616 => 'ν', - 120617 => 'ξ', - 120618 => 'ο', - 120619 => 'π', - 120620 => 'ρ', - 120621 => 'θ', - 120622 => 'σ', - 120623 => 'τ', - 120624 => 'υ', - 120625 => 'φ', - 120626 => 'χ', - 120627 => 'ψ', - 120628 => 'ω', - 120629 => '∇', - 120630 => 'α', - 120631 => 'β', - 120632 => 'γ', - 120633 => 'δ', - 120634 => 'ε', - 120635 => 'ζ', - 120636 => 'η', - 120637 => 'θ', - 120638 => 'ι', - 120639 => 'κ', - 120640 => 'λ', - 120641 => 'μ', - 120642 => 'ν', - 120643 => 'ξ', - 120644 => 'ο', - 120645 => 'π', - 120646 => 'ρ', - 120647 => 'σ', - 120648 => 'σ', - 120649 => 'τ', - 120650 => 'υ', - 120651 => 'φ', - 120652 => 'χ', - 120653 => 'ψ', - 120654 => 'ω', - 120655 => '∂', - 120656 => 'ε', - 120657 => 'θ', - 120658 => 'κ', - 120659 => 'φ', - 120660 => 'ρ', - 120661 => 'π', - 120662 => 'α', - 120663 => 'β', - 120664 => 'γ', - 120665 => 'δ', - 120666 => 'ε', - 120667 => 'ζ', - 120668 => 'η', - 120669 => 'θ', - 120670 => 'ι', - 120671 => 'κ', - 120672 => 'λ', - 120673 => 'μ', - 120674 => 'ν', - 120675 => 'ξ', - 120676 => 'ο', - 120677 => 'π', - 120678 => 'ρ', - 120679 => 'θ', - 120680 => 'σ', - 120681 => 'τ', - 120682 => 'υ', - 120683 => 'φ', - 120684 => 'χ', - 120685 => 'ψ', - 120686 => 'ω', - 120687 => '∇', - 120688 => 'α', - 120689 => 'β', - 120690 => 'γ', - 120691 => 'δ', - 120692 => 'ε', - 120693 => 'ζ', - 120694 => 'η', - 120695 => 'θ', - 120696 => 'ι', - 120697 => 'κ', - 120698 => 'λ', - 120699 => 'μ', - 120700 => 'ν', - 120701 => 'ξ', - 120702 => 'ο', - 120703 => 'π', - 120704 => 'ρ', - 120705 => 'σ', - 120706 => 'σ', - 120707 => 'τ', - 120708 => 'υ', - 120709 => 'φ', - 120710 => 'χ', - 120711 => 'ψ', - 120712 => 'ω', - 120713 => '∂', - 120714 => 'ε', - 120715 => 'θ', - 120716 => 'κ', - 120717 => 'φ', - 120718 => 'ρ', - 120719 => 'π', - 120720 => 'α', - 120721 => 'β', - 120722 => 'γ', - 120723 => 'δ', - 120724 => 'ε', - 120725 => 'ζ', - 120726 => 'η', - 120727 => 'θ', - 120728 => 'ι', - 120729 => 'κ', - 120730 => 'λ', - 120731 => 'μ', - 120732 => 'ν', - 120733 => 'ξ', - 120734 => 'ο', - 120735 => 'π', - 120736 => 'ρ', - 120737 => 'θ', - 120738 => 'σ', - 120739 => 'τ', - 120740 => 'υ', - 120741 => 'φ', - 120742 => 'χ', - 120743 => 'ψ', - 120744 => 'ω', - 120745 => '∇', - 120746 => 'α', - 120747 => 'β', - 120748 => 'γ', - 120749 => 'δ', - 120750 => 'ε', - 120751 => 'ζ', - 120752 => 'η', - 120753 => 'θ', - 120754 => 'ι', - 120755 => 'κ', - 120756 => 'λ', - 120757 => 'μ', - 120758 => 'ν', - 120759 => 'ξ', - 120760 => 'ο', - 120761 => 'π', - 120762 => 'ρ', - 120763 => 'σ', - 120764 => 'σ', - 120765 => 'τ', - 120766 => 'υ', - 120767 => 'φ', - 120768 => 'χ', - 120769 => 'ψ', - 120770 => 'ω', - 120771 => '∂', - 120772 => 'ε', - 120773 => 'θ', - 120774 => 'κ', - 120775 => 'φ', - 120776 => 'ρ', - 120777 => 'π', - 120778 => 'ϝ', - 120779 => 'ϝ', - 120782 => '0', - 120783 => '1', - 120784 => '2', - 120785 => '3', - 120786 => '4', - 120787 => '5', - 120788 => '6', - 120789 => '7', - 120790 => '8', - 120791 => '9', - 120792 => '0', - 120793 => '1', - 120794 => '2', - 120795 => '3', - 120796 => '4', - 120797 => '5', - 120798 => '6', - 120799 => '7', - 120800 => '8', - 120801 => '9', - 120802 => '0', - 120803 => '1', - 120804 => '2', - 120805 => '3', - 120806 => '4', - 120807 => '5', - 120808 => '6', - 120809 => '7', - 120810 => '8', - 120811 => '9', - 120812 => '0', - 120813 => '1', - 120814 => '2', - 120815 => '3', - 120816 => '4', - 120817 => '5', - 120818 => '6', - 120819 => '7', - 120820 => '8', - 120821 => '9', - 120822 => '0', - 120823 => '1', - 120824 => '2', - 120825 => '3', - 120826 => '4', - 120827 => '5', - 120828 => '6', - 120829 => '7', - 120830 => '8', - 120831 => '9', - 125184 => '𞤢', - 125185 => '𞤣', - 125186 => '𞤤', - 125187 => '𞤥', - 125188 => '𞤦', - 125189 => '𞤧', - 125190 => '𞤨', - 125191 => '𞤩', - 125192 => '𞤪', - 125193 => '𞤫', - 125194 => '𞤬', - 125195 => '𞤭', - 125196 => '𞤮', - 125197 => '𞤯', - 125198 => '𞤰', - 125199 => '𞤱', - 125200 => '𞤲', - 125201 => '𞤳', - 125202 => '𞤴', - 125203 => '𞤵', - 125204 => '𞤶', - 125205 => '𞤷', - 125206 => '𞤸', - 125207 => '𞤹', - 125208 => '𞤺', - 125209 => '𞤻', - 125210 => '𞤼', - 125211 => '𞤽', - 125212 => '𞤾', - 125213 => '𞤿', - 125214 => '𞥀', - 125215 => '𞥁', - 125216 => '𞥂', - 125217 => '𞥃', - 126464 => 'ا', - 126465 => 'ب', - 126466 => 'ج', - 126467 => 'د', - 126469 => 'و', - 126470 => 'ز', - 126471 => 'ح', - 126472 => 'ط', - 126473 => 'ي', - 126474 => 'ك', - 126475 => 'ل', - 126476 => 'م', - 126477 => 'ن', - 126478 => 'س', - 126479 => 'ع', - 126480 => 'ف', - 126481 => 'ص', - 126482 => 'ق', - 126483 => 'ر', - 126484 => 'ش', - 126485 => 'ت', - 126486 => 'ث', - 126487 => 'خ', - 126488 => 'ذ', - 126489 => 'ض', - 126490 => 'ظ', - 126491 => 'غ', - 126492 => 'ٮ', - 126493 => 'ں', - 126494 => 'ڡ', - 126495 => 'ٯ', - 126497 => 'ب', - 126498 => 'ج', - 126500 => 'ه', - 126503 => 'ح', - 126505 => 'ي', - 126506 => 'ك', - 126507 => 'ل', - 126508 => 'م', - 126509 => 'ن', - 126510 => 'س', - 126511 => 'ع', - 126512 => 'ف', - 126513 => 'ص', - 126514 => 'ق', - 126516 => 'ش', - 126517 => 'ت', - 126518 => 'ث', - 126519 => 'خ', - 126521 => 'ض', - 126523 => 'غ', - 126530 => 'ج', - 126535 => 'ح', - 126537 => 'ي', - 126539 => 'ل', - 126541 => 'ن', - 126542 => 'س', - 126543 => 'ع', - 126545 => 'ص', - 126546 => 'ق', - 126548 => 'ش', - 126551 => 'خ', - 126553 => 'ض', - 126555 => 'غ', - 126557 => 'ں', - 126559 => 'ٯ', - 126561 => 'ب', - 126562 => 'ج', - 126564 => 'ه', - 126567 => 'ح', - 126568 => 'ط', - 126569 => 'ي', - 126570 => 'ك', - 126572 => 'م', - 126573 => 'ن', - 126574 => 'س', - 126575 => 'ع', - 126576 => 'ف', - 126577 => 'ص', - 126578 => 'ق', - 126580 => 'ش', - 126581 => 'ت', - 126582 => 'ث', - 126583 => 'خ', - 126585 => 'ض', - 126586 => 'ظ', - 126587 => 'غ', - 126588 => 'ٮ', - 126590 => 'ڡ', - 126592 => 'ا', - 126593 => 'ب', - 126594 => 'ج', - 126595 => 'د', - 126596 => 'ه', - 126597 => 'و', - 126598 => 'ز', - 126599 => 'ح', - 126600 => 'ط', - 126601 => 'ي', - 126603 => 'ل', - 126604 => 'م', - 126605 => 'ن', - 126606 => 'س', - 126607 => 'ع', - 126608 => 'ف', - 126609 => 'ص', - 126610 => 'ق', - 126611 => 'ر', - 126612 => 'ش', - 126613 => 'ت', - 126614 => 'ث', - 126615 => 'خ', - 126616 => 'ذ', - 126617 => 'ض', - 126618 => 'ظ', - 126619 => 'غ', - 126625 => 'ب', - 126626 => 'ج', - 126627 => 'د', - 126629 => 'و', - 126630 => 'ز', - 126631 => 'ح', - 126632 => 'ط', - 126633 => 'ي', - 126635 => 'ل', - 126636 => 'م', - 126637 => 'ن', - 126638 => 'س', - 126639 => 'ع', - 126640 => 'ف', - 126641 => 'ص', - 126642 => 'ق', - 126643 => 'ر', - 126644 => 'ش', - 126645 => 'ت', - 126646 => 'ث', - 126647 => 'خ', - 126648 => 'ذ', - 126649 => 'ض', - 126650 => 'ظ', - 126651 => 'غ', - 127274 => '〔s〕', - 127275 => 'c', - 127276 => 'r', - 127277 => 'cd', - 127278 => 'wz', - 127280 => 'a', - 127281 => 'b', - 127282 => 'c', - 127283 => 'd', - 127284 => 'e', - 127285 => 'f', - 127286 => 'g', - 127287 => 'h', - 127288 => 'i', - 127289 => 'j', - 127290 => 'k', - 127291 => 'l', - 127292 => 'm', - 127293 => 'n', - 127294 => 'o', - 127295 => 'p', - 127296 => 'q', - 127297 => 'r', - 127298 => 's', - 127299 => 't', - 127300 => 'u', - 127301 => 'v', - 127302 => 'w', - 127303 => 'x', - 127304 => 'y', - 127305 => 'z', - 127306 => 'hv', - 127307 => 'mv', - 127308 => 'sd', - 127309 => 'ss', - 127310 => 'ppv', - 127311 => 'wc', - 127338 => 'mc', - 127339 => 'md', - 127340 => 'mr', - 127376 => 'dj', - 127488 => 'ほか', - 127489 => 'ココ', - 127490 => 'サ', - 127504 => '手', - 127505 => '字', - 127506 => '双', - 127507 => 'デ', - 127508 => '二', - 127509 => '多', - 127510 => '解', - 127511 => '天', - 127512 => '交', - 127513 => '映', - 127514 => '無', - 127515 => '料', - 127516 => '前', - 127517 => '後', - 127518 => '再', - 127519 => '新', - 127520 => '初', - 127521 => '終', - 127522 => '生', - 127523 => '販', - 127524 => '声', - 127525 => '吹', - 127526 => '演', - 127527 => '投', - 127528 => '捕', - 127529 => '一', - 127530 => '三', - 127531 => '遊', - 127532 => '左', - 127533 => '中', - 127534 => '右', - 127535 => '指', - 127536 => '走', - 127537 => '打', - 127538 => '禁', - 127539 => '空', - 127540 => '合', - 127541 => '満', - 127542 => '有', - 127543 => '月', - 127544 => '申', - 127545 => '割', - 127546 => '営', - 127547 => '配', - 127552 => '〔本〕', - 127553 => '〔三〕', - 127554 => '〔二〕', - 127555 => '〔安〕', - 127556 => '〔点〕', - 127557 => '〔打〕', - 127558 => '〔盗〕', - 127559 => '〔勝〕', - 127560 => '〔敗〕', - 127568 => '得', - 127569 => '可', - 130032 => '0', - 130033 => '1', - 130034 => '2', - 130035 => '3', - 130036 => '4', - 130037 => '5', - 130038 => '6', - 130039 => '7', - 130040 => '8', - 130041 => '9', - 194560 => '丽', - 194561 => '丸', - 194562 => '乁', - 194563 => '𠄢', - 194564 => '你', - 194565 => '侮', - 194566 => '侻', - 194567 => '倂', - 194568 => '偺', - 194569 => '備', - 194570 => '僧', - 194571 => '像', - 194572 => '㒞', - 194573 => '𠘺', - 194574 => '免', - 194575 => '兔', - 194576 => '兤', - 194577 => '具', - 194578 => '𠔜', - 194579 => '㒹', - 194580 => '內', - 194581 => '再', - 194582 => '𠕋', - 194583 => '冗', - 194584 => '冤', - 194585 => '仌', - 194586 => '冬', - 194587 => '况', - 194588 => '𩇟', - 194589 => '凵', - 194590 => '刃', - 194591 => '㓟', - 194592 => '刻', - 194593 => '剆', - 194594 => '割', - 194595 => '剷', - 194596 => '㔕', - 194597 => '勇', - 194598 => '勉', - 194599 => '勤', - 194600 => '勺', - 194601 => '包', - 194602 => '匆', - 194603 => '北', - 194604 => '卉', - 194605 => '卑', - 194606 => '博', - 194607 => '即', - 194608 => '卽', - 194609 => '卿', - 194610 => '卿', - 194611 => '卿', - 194612 => '𠨬', - 194613 => '灰', - 194614 => '及', - 194615 => '叟', - 194616 => '𠭣', - 194617 => '叫', - 194618 => '叱', - 194619 => '吆', - 194620 => '咞', - 194621 => '吸', - 194622 => '呈', - 194623 => '周', - 194624 => '咢', - 194625 => '哶', - 194626 => '唐', - 194627 => '啓', - 194628 => '啣', - 194629 => '善', - 194630 => '善', - 194631 => '喙', - 194632 => '喫', - 194633 => '喳', - 194634 => '嗂', - 194635 => '圖', - 194636 => '嘆', - 194637 => '圗', - 194638 => '噑', - 194639 => '噴', - 194640 => '切', - 194641 => '壮', - 194642 => '城', - 194643 => '埴', - 194644 => '堍', - 194645 => '型', - 194646 => '堲', - 194647 => '報', - 194648 => '墬', - 194649 => '𡓤', - 194650 => '売', - 194651 => '壷', - 194652 => '夆', - 194653 => '多', - 194654 => '夢', - 194655 => '奢', - 194656 => '𡚨', - 194657 => '𡛪', - 194658 => '姬', - 194659 => '娛', - 194660 => '娧', - 194661 => '姘', - 194662 => '婦', - 194663 => '㛮', - 194665 => '嬈', - 194666 => '嬾', - 194667 => '嬾', - 194668 => '𡧈', - 194669 => '寃', - 194670 => '寘', - 194671 => '寧', - 194672 => '寳', - 194673 => '𡬘', - 194674 => '寿', - 194675 => '将', - 194677 => '尢', - 194678 => '㞁', - 194679 => '屠', - 194680 => '屮', - 194681 => '峀', - 194682 => '岍', - 194683 => '𡷤', - 194684 => '嵃', - 194685 => '𡷦', - 194686 => '嵮', - 194687 => '嵫', - 194688 => '嵼', - 194689 => '巡', - 194690 => '巢', - 194691 => '㠯', - 194692 => '巽', - 194693 => '帨', - 194694 => '帽', - 194695 => '幩', - 194696 => '㡢', - 194697 => '𢆃', - 194698 => '㡼', - 194699 => '庰', - 194700 => '庳', - 194701 => '庶', - 194702 => '廊', - 194703 => '𪎒', - 194704 => '廾', - 194705 => '𢌱', - 194706 => '𢌱', - 194707 => '舁', - 194708 => '弢', - 194709 => '弢', - 194710 => '㣇', - 194711 => '𣊸', - 194712 => '𦇚', - 194713 => '形', - 194714 => '彫', - 194715 => '㣣', - 194716 => '徚', - 194717 => '忍', - 194718 => '志', - 194719 => '忹', - 194720 => '悁', - 194721 => '㤺', - 194722 => '㤜', - 194723 => '悔', - 194724 => '𢛔', - 194725 => '惇', - 194726 => '慈', - 194727 => '慌', - 194728 => '慎', - 194729 => '慌', - 194730 => '慺', - 194731 => '憎', - 194732 => '憲', - 194733 => '憤', - 194734 => '憯', - 194735 => '懞', - 194736 => '懲', - 194737 => '懶', - 194738 => '成', - 194739 => '戛', - 194740 => '扝', - 194741 => '抱', - 194742 => '拔', - 194743 => '捐', - 194744 => '𢬌', - 194745 => '挽', - 194746 => '拼', - 194747 => '捨', - 194748 => '掃', - 194749 => '揤', - 194750 => '𢯱', - 194751 => '搢', - 194752 => '揅', - 194753 => '掩', - 194754 => '㨮', - 194755 => '摩', - 194756 => '摾', - 194757 => '撝', - 194758 => '摷', - 194759 => '㩬', - 194760 => '敏', - 194761 => '敬', - 194762 => '𣀊', - 194763 => '旣', - 194764 => '書', - 194765 => '晉', - 194766 => '㬙', - 194767 => '暑', - 194768 => '㬈', - 194769 => '㫤', - 194770 => '冒', - 194771 => '冕', - 194772 => '最', - 194773 => '暜', - 194774 => '肭', - 194775 => '䏙', - 194776 => '朗', - 194777 => '望', - 194778 => '朡', - 194779 => '杞', - 194780 => '杓', - 194781 => '𣏃', - 194782 => '㭉', - 194783 => '柺', - 194784 => '枅', - 194785 => '桒', - 194786 => '梅', - 194787 => '𣑭', - 194788 => '梎', - 194789 => '栟', - 194790 => '椔', - 194791 => '㮝', - 194792 => '楂', - 194793 => '榣', - 194794 => '槪', - 194795 => '檨', - 194796 => '𣚣', - 194797 => '櫛', - 194798 => '㰘', - 194799 => '次', - 194800 => '𣢧', - 194801 => '歔', - 194802 => '㱎', - 194803 => '歲', - 194804 => '殟', - 194805 => '殺', - 194806 => '殻', - 194807 => '𣪍', - 194808 => '𡴋', - 194809 => '𣫺', - 194810 => '汎', - 194811 => '𣲼', - 194812 => '沿', - 194813 => '泍', - 194814 => '汧', - 194815 => '洖', - 194816 => '派', - 194817 => '海', - 194818 => '流', - 194819 => '浩', - 194820 => '浸', - 194821 => '涅', - 194822 => '𣴞', - 194823 => '洴', - 194824 => '港', - 194825 => '湮', - 194826 => '㴳', - 194827 => '滋', - 194828 => '滇', - 194829 => '𣻑', - 194830 => '淹', - 194831 => '潮', - 194832 => '𣽞', - 194833 => '𣾎', - 194834 => '濆', - 194835 => '瀹', - 194836 => '瀞', - 194837 => '瀛', - 194838 => '㶖', - 194839 => '灊', - 194840 => '災', - 194841 => '灷', - 194842 => '炭', - 194843 => '𠔥', - 194844 => '煅', - 194845 => '𤉣', - 194846 => '熜', - 194848 => '爨', - 194849 => '爵', - 194850 => '牐', - 194851 => '𤘈', - 194852 => '犀', - 194853 => '犕', - 194854 => '𤜵', - 194855 => '𤠔', - 194856 => '獺', - 194857 => '王', - 194858 => '㺬', - 194859 => '玥', - 194860 => '㺸', - 194861 => '㺸', - 194862 => '瑇', - 194863 => '瑜', - 194864 => '瑱', - 194865 => '璅', - 194866 => '瓊', - 194867 => '㼛', - 194868 => '甤', - 194869 => '𤰶', - 194870 => '甾', - 194871 => '𤲒', - 194872 => '異', - 194873 => '𢆟', - 194874 => '瘐', - 194875 => '𤾡', - 194876 => '𤾸', - 194877 => '𥁄', - 194878 => '㿼', - 194879 => '䀈', - 194880 => '直', - 194881 => '𥃳', - 194882 => '𥃲', - 194883 => '𥄙', - 194884 => '𥄳', - 194885 => '眞', - 194886 => '真', - 194887 => '真', - 194888 => '睊', - 194889 => '䀹', - 194890 => '瞋', - 194891 => '䁆', - 194892 => '䂖', - 194893 => '𥐝', - 194894 => '硎', - 194895 => '碌', - 194896 => '磌', - 194897 => '䃣', - 194898 => '𥘦', - 194899 => '祖', - 194900 => '𥚚', - 194901 => '𥛅', - 194902 => '福', - 194903 => '秫', - 194904 => '䄯', - 194905 => '穀', - 194906 => '穊', - 194907 => '穏', - 194908 => '𥥼', - 194909 => '𥪧', - 194910 => '𥪧', - 194912 => '䈂', - 194913 => '𥮫', - 194914 => '篆', - 194915 => '築', - 194916 => '䈧', - 194917 => '𥲀', - 194918 => '糒', - 194919 => '䊠', - 194920 => '糨', - 194921 => '糣', - 194922 => '紀', - 194923 => '𥾆', - 194924 => '絣', - 194925 => '䌁', - 194926 => '緇', - 194927 => '縂', - 194928 => '繅', - 194929 => '䌴', - 194930 => '𦈨', - 194931 => '𦉇', - 194932 => '䍙', - 194933 => '𦋙', - 194934 => '罺', - 194935 => '𦌾', - 194936 => '羕', - 194937 => '翺', - 194938 => '者', - 194939 => '𦓚', - 194940 => '𦔣', - 194941 => '聠', - 194942 => '𦖨', - 194943 => '聰', - 194944 => '𣍟', - 194945 => '䏕', - 194946 => '育', - 194947 => '脃', - 194948 => '䐋', - 194949 => '脾', - 194950 => '媵', - 194951 => '𦞧', - 194952 => '𦞵', - 194953 => '𣎓', - 194954 => '𣎜', - 194955 => '舁', - 194956 => '舄', - 194957 => '辞', - 194958 => '䑫', - 194959 => '芑', - 194960 => '芋', - 194961 => '芝', - 194962 => '劳', - 194963 => '花', - 194964 => '芳', - 194965 => '芽', - 194966 => '苦', - 194967 => '𦬼', - 194968 => '若', - 194969 => '茝', - 194970 => '荣', - 194971 => '莭', - 194972 => '茣', - 194973 => '莽', - 194974 => '菧', - 194975 => '著', - 194976 => '荓', - 194977 => '菊', - 194978 => '菌', - 194979 => '菜', - 194980 => '𦰶', - 194981 => '𦵫', - 194982 => '𦳕', - 194983 => '䔫', - 194984 => '蓱', - 194985 => '蓳', - 194986 => '蔖', - 194987 => '𧏊', - 194988 => '蕤', - 194989 => '𦼬', - 194990 => '䕝', - 194991 => '䕡', - 194992 => '𦾱', - 194993 => '𧃒', - 194994 => '䕫', - 194995 => '虐', - 194996 => '虜', - 194997 => '虧', - 194998 => '虩', - 194999 => '蚩', - 195000 => '蚈', - 195001 => '蜎', - 195002 => '蛢', - 195003 => '蝹', - 195004 => '蜨', - 195005 => '蝫', - 195006 => '螆', - 195008 => '蟡', - 195009 => '蠁', - 195010 => '䗹', - 195011 => '衠', - 195012 => '衣', - 195013 => '𧙧', - 195014 => '裗', - 195015 => '裞', - 195016 => '䘵', - 195017 => '裺', - 195018 => '㒻', - 195019 => '𧢮', - 195020 => '𧥦', - 195021 => '䚾', - 195022 => '䛇', - 195023 => '誠', - 195024 => '諭', - 195025 => '變', - 195026 => '豕', - 195027 => '𧲨', - 195028 => '貫', - 195029 => '賁', - 195030 => '贛', - 195031 => '起', - 195032 => '𧼯', - 195033 => '𠠄', - 195034 => '跋', - 195035 => '趼', - 195036 => '跰', - 195037 => '𠣞', - 195038 => '軔', - 195039 => '輸', - 195040 => '𨗒', - 195041 => '𨗭', - 195042 => '邔', - 195043 => '郱', - 195044 => '鄑', - 195045 => '𨜮', - 195046 => '鄛', - 195047 => '鈸', - 195048 => '鋗', - 195049 => '鋘', - 195050 => '鉼', - 195051 => '鏹', - 195052 => '鐕', - 195053 => '𨯺', - 195054 => '開', - 195055 => '䦕', - 195056 => '閷', - 195057 => '𨵷', - 195058 => '䧦', - 195059 => '雃', - 195060 => '嶲', - 195061 => '霣', - 195062 => '𩅅', - 195063 => '𩈚', - 195064 => '䩮', - 195065 => '䩶', - 195066 => '韠', - 195067 => '𩐊', - 195068 => '䪲', - 195069 => '𩒖', - 195070 => '頋', - 195071 => '頋', - 195072 => '頩', - 195073 => '𩖶', - 195074 => '飢', - 195075 => '䬳', - 195076 => '餩', - 195077 => '馧', - 195078 => '駂', - 195079 => '駾', - 195080 => '䯎', - 195081 => '𩬰', - 195082 => '鬒', - 195083 => '鱀', - 195084 => '鳽', - 195085 => '䳎', - 195086 => '䳭', - 195087 => '鵧', - 195088 => '𪃎', - 195089 => '䳸', - 195090 => '𪄅', - 195091 => '𪈎', - 195092 => '𪊑', - 195093 => '麻', - 195094 => '䵖', - 195095 => '黹', - 195096 => '黾', - 195097 => '鼅', - 195098 => '鼏', - 195099 => '鼖', - 195100 => '鼻', - 195101 => '𪘀', -); diff --git a/lib/symfony/polyfill-intl-idn/Resources/unidata/virama.php b/lib/symfony/polyfill-intl-idn/Resources/unidata/virama.php deleted file mode 100644 index 1958e37ed..000000000 --- a/lib/symfony/polyfill-intl-idn/Resources/unidata/virama.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php - -return array ( - 2381 => 9, - 2509 => 9, - 2637 => 9, - 2765 => 9, - 2893 => 9, - 3021 => 9, - 3149 => 9, - 3277 => 9, - 3387 => 9, - 3388 => 9, - 3405 => 9, - 3530 => 9, - 3642 => 9, - 3770 => 9, - 3972 => 9, - 4153 => 9, - 4154 => 9, - 5908 => 9, - 5940 => 9, - 6098 => 9, - 6752 => 9, - 6980 => 9, - 7082 => 9, - 7083 => 9, - 7154 => 9, - 7155 => 9, - 11647 => 9, - 43014 => 9, - 43052 => 9, - 43204 => 9, - 43347 => 9, - 43456 => 9, - 43766 => 9, - 44013 => 9, - 68159 => 9, - 69702 => 9, - 69759 => 9, - 69817 => 9, - 69939 => 9, - 69940 => 9, - 70080 => 9, - 70197 => 9, - 70378 => 9, - 70477 => 9, - 70722 => 9, - 70850 => 9, - 71103 => 9, - 71231 => 9, - 71350 => 9, - 71467 => 9, - 71737 => 9, - 71997 => 9, - 71998 => 9, - 72160 => 9, - 72244 => 9, - 72263 => 9, - 72345 => 9, - 72767 => 9, - 73028 => 9, - 73029 => 9, - 73111 => 9, -); diff --git a/lib/symfony/polyfill-intl-idn/bootstrap.php b/lib/symfony/polyfill-intl-idn/bootstrap.php deleted file mode 100644 index 57c78356c..000000000 --- a/lib/symfony/polyfill-intl-idn/bootstrap.php +++ /dev/null @@ -1,145 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Intl\Idn as p; - -if (extension_loaded('intl')) { - return; -} - -if (\PHP_VERSION_ID >= 80000) { - return require __DIR__.'/bootstrap80.php'; -} - -if (!defined('U_IDNA_PROHIBITED_ERROR')) { - define('U_IDNA_PROHIBITED_ERROR', 66560); -} -if (!defined('U_IDNA_ERROR_START')) { - define('U_IDNA_ERROR_START', 66560); -} -if (!defined('U_IDNA_UNASSIGNED_ERROR')) { - define('U_IDNA_UNASSIGNED_ERROR', 66561); -} -if (!defined('U_IDNA_CHECK_BIDI_ERROR')) { - define('U_IDNA_CHECK_BIDI_ERROR', 66562); -} -if (!defined('U_IDNA_STD3_ASCII_RULES_ERROR')) { - define('U_IDNA_STD3_ASCII_RULES_ERROR', 66563); -} -if (!defined('U_IDNA_ACE_PREFIX_ERROR')) { - define('U_IDNA_ACE_PREFIX_ERROR', 66564); -} -if (!defined('U_IDNA_VERIFICATION_ERROR')) { - define('U_IDNA_VERIFICATION_ERROR', 66565); -} -if (!defined('U_IDNA_LABEL_TOO_LONG_ERROR')) { - define('U_IDNA_LABEL_TOO_LONG_ERROR', 66566); -} -if (!defined('U_IDNA_ZERO_LENGTH_LABEL_ERROR')) { - define('U_IDNA_ZERO_LENGTH_LABEL_ERROR', 66567); -} -if (!defined('U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR')) { - define('U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR', 66568); -} -if (!defined('U_IDNA_ERROR_LIMIT')) { - define('U_IDNA_ERROR_LIMIT', 66569); -} -if (!defined('U_STRINGPREP_PROHIBITED_ERROR')) { - define('U_STRINGPREP_PROHIBITED_ERROR', 66560); -} -if (!defined('U_STRINGPREP_UNASSIGNED_ERROR')) { - define('U_STRINGPREP_UNASSIGNED_ERROR', 66561); -} -if (!defined('U_STRINGPREP_CHECK_BIDI_ERROR')) { - define('U_STRINGPREP_CHECK_BIDI_ERROR', 66562); -} -if (!defined('IDNA_DEFAULT')) { - define('IDNA_DEFAULT', 0); -} -if (!defined('IDNA_ALLOW_UNASSIGNED')) { - define('IDNA_ALLOW_UNASSIGNED', 1); -} -if (!defined('IDNA_USE_STD3_RULES')) { - define('IDNA_USE_STD3_RULES', 2); -} -if (!defined('IDNA_CHECK_BIDI')) { - define('IDNA_CHECK_BIDI', 4); -} -if (!defined('IDNA_CHECK_CONTEXTJ')) { - define('IDNA_CHECK_CONTEXTJ', 8); -} -if (!defined('IDNA_NONTRANSITIONAL_TO_ASCII')) { - define('IDNA_NONTRANSITIONAL_TO_ASCII', 16); -} -if (!defined('IDNA_NONTRANSITIONAL_TO_UNICODE')) { - define('IDNA_NONTRANSITIONAL_TO_UNICODE', 32); -} -if (!defined('INTL_IDNA_VARIANT_2003')) { - define('INTL_IDNA_VARIANT_2003', 0); -} -if (!defined('INTL_IDNA_VARIANT_UTS46')) { - define('INTL_IDNA_VARIANT_UTS46', 1); -} -if (!defined('IDNA_ERROR_EMPTY_LABEL')) { - define('IDNA_ERROR_EMPTY_LABEL', 1); -} -if (!defined('IDNA_ERROR_LABEL_TOO_LONG')) { - define('IDNA_ERROR_LABEL_TOO_LONG', 2); -} -if (!defined('IDNA_ERROR_DOMAIN_NAME_TOO_LONG')) { - define('IDNA_ERROR_DOMAIN_NAME_TOO_LONG', 4); -} -if (!defined('IDNA_ERROR_LEADING_HYPHEN')) { - define('IDNA_ERROR_LEADING_HYPHEN', 8); -} -if (!defined('IDNA_ERROR_TRAILING_HYPHEN')) { - define('IDNA_ERROR_TRAILING_HYPHEN', 16); -} -if (!defined('IDNA_ERROR_HYPHEN_3_4')) { - define('IDNA_ERROR_HYPHEN_3_4', 32); -} -if (!defined('IDNA_ERROR_LEADING_COMBINING_MARK')) { - define('IDNA_ERROR_LEADING_COMBINING_MARK', 64); -} -if (!defined('IDNA_ERROR_DISALLOWED')) { - define('IDNA_ERROR_DISALLOWED', 128); -} -if (!defined('IDNA_ERROR_PUNYCODE')) { - define('IDNA_ERROR_PUNYCODE', 256); -} -if (!defined('IDNA_ERROR_LABEL_HAS_DOT')) { - define('IDNA_ERROR_LABEL_HAS_DOT', 512); -} -if (!defined('IDNA_ERROR_INVALID_ACE_LABEL')) { - define('IDNA_ERROR_INVALID_ACE_LABEL', 1024); -} -if (!defined('IDNA_ERROR_BIDI')) { - define('IDNA_ERROR_BIDI', 2048); -} -if (!defined('IDNA_ERROR_CONTEXTJ')) { - define('IDNA_ERROR_CONTEXTJ', 4096); -} - -if (\PHP_VERSION_ID < 70400) { - if (!function_exists('idn_to_ascii')) { - function idn_to_ascii($domain, $flags = 0, $variant = \INTL_IDNA_VARIANT_2003, &$idna_info = null) { return p\Idn::idn_to_ascii($domain, $flags, $variant, $idna_info); } - } - if (!function_exists('idn_to_utf8')) { - function idn_to_utf8($domain, $flags = 0, $variant = \INTL_IDNA_VARIANT_2003, &$idna_info = null) { return p\Idn::idn_to_utf8($domain, $flags, $variant, $idna_info); } - } -} else { - if (!function_exists('idn_to_ascii')) { - function idn_to_ascii($domain, $flags = 0, $variant = \INTL_IDNA_VARIANT_UTS46, &$idna_info = null) { return p\Idn::idn_to_ascii($domain, $flags, $variant, $idna_info); } - } - if (!function_exists('idn_to_utf8')) { - function idn_to_utf8($domain, $flags = 0, $variant = \INTL_IDNA_VARIANT_UTS46, &$idna_info = null) { return p\Idn::idn_to_utf8($domain, $flags, $variant, $idna_info); } - } -} diff --git a/lib/symfony/polyfill-intl-idn/bootstrap80.php b/lib/symfony/polyfill-intl-idn/bootstrap80.php deleted file mode 100644 index a62c2d69b..000000000 --- a/lib/symfony/polyfill-intl-idn/bootstrap80.php +++ /dev/null @@ -1,125 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Intl\Idn as p; - -if (!defined('U_IDNA_PROHIBITED_ERROR')) { - define('U_IDNA_PROHIBITED_ERROR', 66560); -} -if (!defined('U_IDNA_ERROR_START')) { - define('U_IDNA_ERROR_START', 66560); -} -if (!defined('U_IDNA_UNASSIGNED_ERROR')) { - define('U_IDNA_UNASSIGNED_ERROR', 66561); -} -if (!defined('U_IDNA_CHECK_BIDI_ERROR')) { - define('U_IDNA_CHECK_BIDI_ERROR', 66562); -} -if (!defined('U_IDNA_STD3_ASCII_RULES_ERROR')) { - define('U_IDNA_STD3_ASCII_RULES_ERROR', 66563); -} -if (!defined('U_IDNA_ACE_PREFIX_ERROR')) { - define('U_IDNA_ACE_PREFIX_ERROR', 66564); -} -if (!defined('U_IDNA_VERIFICATION_ERROR')) { - define('U_IDNA_VERIFICATION_ERROR', 66565); -} -if (!defined('U_IDNA_LABEL_TOO_LONG_ERROR')) { - define('U_IDNA_LABEL_TOO_LONG_ERROR', 66566); -} -if (!defined('U_IDNA_ZERO_LENGTH_LABEL_ERROR')) { - define('U_IDNA_ZERO_LENGTH_LABEL_ERROR', 66567); -} -if (!defined('U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR')) { - define('U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR', 66568); -} -if (!defined('U_IDNA_ERROR_LIMIT')) { - define('U_IDNA_ERROR_LIMIT', 66569); -} -if (!defined('U_STRINGPREP_PROHIBITED_ERROR')) { - define('U_STRINGPREP_PROHIBITED_ERROR', 66560); -} -if (!defined('U_STRINGPREP_UNASSIGNED_ERROR')) { - define('U_STRINGPREP_UNASSIGNED_ERROR', 66561); -} -if (!defined('U_STRINGPREP_CHECK_BIDI_ERROR')) { - define('U_STRINGPREP_CHECK_BIDI_ERROR', 66562); -} -if (!defined('IDNA_DEFAULT')) { - define('IDNA_DEFAULT', 0); -} -if (!defined('IDNA_ALLOW_UNASSIGNED')) { - define('IDNA_ALLOW_UNASSIGNED', 1); -} -if (!defined('IDNA_USE_STD3_RULES')) { - define('IDNA_USE_STD3_RULES', 2); -} -if (!defined('IDNA_CHECK_BIDI')) { - define('IDNA_CHECK_BIDI', 4); -} -if (!defined('IDNA_CHECK_CONTEXTJ')) { - define('IDNA_CHECK_CONTEXTJ', 8); -} -if (!defined('IDNA_NONTRANSITIONAL_TO_ASCII')) { - define('IDNA_NONTRANSITIONAL_TO_ASCII', 16); -} -if (!defined('IDNA_NONTRANSITIONAL_TO_UNICODE')) { - define('IDNA_NONTRANSITIONAL_TO_UNICODE', 32); -} -if (!defined('INTL_IDNA_VARIANT_UTS46')) { - define('INTL_IDNA_VARIANT_UTS46', 1); -} -if (!defined('IDNA_ERROR_EMPTY_LABEL')) { - define('IDNA_ERROR_EMPTY_LABEL', 1); -} -if (!defined('IDNA_ERROR_LABEL_TOO_LONG')) { - define('IDNA_ERROR_LABEL_TOO_LONG', 2); -} -if (!defined('IDNA_ERROR_DOMAIN_NAME_TOO_LONG')) { - define('IDNA_ERROR_DOMAIN_NAME_TOO_LONG', 4); -} -if (!defined('IDNA_ERROR_LEADING_HYPHEN')) { - define('IDNA_ERROR_LEADING_HYPHEN', 8); -} -if (!defined('IDNA_ERROR_TRAILING_HYPHEN')) { - define('IDNA_ERROR_TRAILING_HYPHEN', 16); -} -if (!defined('IDNA_ERROR_HYPHEN_3_4')) { - define('IDNA_ERROR_HYPHEN_3_4', 32); -} -if (!defined('IDNA_ERROR_LEADING_COMBINING_MARK')) { - define('IDNA_ERROR_LEADING_COMBINING_MARK', 64); -} -if (!defined('IDNA_ERROR_DISALLOWED')) { - define('IDNA_ERROR_DISALLOWED', 128); -} -if (!defined('IDNA_ERROR_PUNYCODE')) { - define('IDNA_ERROR_PUNYCODE', 256); -} -if (!defined('IDNA_ERROR_LABEL_HAS_DOT')) { - define('IDNA_ERROR_LABEL_HAS_DOT', 512); -} -if (!defined('IDNA_ERROR_INVALID_ACE_LABEL')) { - define('IDNA_ERROR_INVALID_ACE_LABEL', 1024); -} -if (!defined('IDNA_ERROR_BIDI')) { - define('IDNA_ERROR_BIDI', 2048); -} -if (!defined('IDNA_ERROR_CONTEXTJ')) { - define('IDNA_ERROR_CONTEXTJ', 4096); -} - -if (!function_exists('idn_to_ascii')) { - function idn_to_ascii(?string $domain, ?int $flags = IDNA_DEFAULT, ?int $variant = INTL_IDNA_VARIANT_UTS46, &$idna_info = null): string|false { return p\Idn::idn_to_ascii((string) $domain, (int) $flags, (int) $variant, $idna_info); } -} -if (!function_exists('idn_to_utf8')) { - function idn_to_utf8(?string $domain, ?int $flags = IDNA_DEFAULT, ?int $variant = INTL_IDNA_VARIANT_UTS46, &$idna_info = null): string|false { return p\Idn::idn_to_utf8((string) $domain, (int) $flags, (int) $variant, $idna_info); } -} diff --git a/lib/symfony/polyfill-intl-idn/composer.json b/lib/symfony/polyfill-intl-idn/composer.json deleted file mode 100644 index 71030a2ed..000000000 --- a/lib/symfony/polyfill-intl-idn/composer.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "symfony/polyfill-intl-idn", - "type": "library", - "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", - "keywords": ["polyfill", "shim", "compatibility", "portable", "intl", "idn"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Laurent Bassin", - "email": "laurent@bassin.info" - }, - { - "name": "Trevor Rowbotham", - "email": "trevor.rowbotham@pm.me" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.1", - "symfony/polyfill-intl-normalizer": "^1.10", - "symfony/polyfill-php72": "^1.10" - }, - "autoload": { - "psr-4": { "Symfony\\Polyfill\\Intl\\Idn\\": "" }, - "files": [ "bootstrap.php" ] - }, - "suggest": { - "ext-intl": "For best performance" - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - } -} diff --git a/lib/symfony/polyfill-intl-normalizer/LICENSE b/lib/symfony/polyfill-intl-normalizer/LICENSE deleted file mode 100644 index 4cd8bdd30..000000000 --- a/lib/symfony/polyfill-intl-normalizer/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2015-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/lib/symfony/polyfill-intl-normalizer/Normalizer.php b/lib/symfony/polyfill-intl-normalizer/Normalizer.php deleted file mode 100644 index 4443c2322..000000000 --- a/lib/symfony/polyfill-intl-normalizer/Normalizer.php +++ /dev/null @@ -1,310 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Intl\Normalizer; - -/** - * Normalizer is a PHP fallback implementation of the Normalizer class provided by the intl extension. - * - * It has been validated with Unicode 6.3 Normalization Conformance Test. - * See http://www.unicode.org/reports/tr15/ for detailed info about Unicode normalizations. - * - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -class Normalizer -{ - public const FORM_D = \Normalizer::FORM_D; - public const FORM_KD = \Normalizer::FORM_KD; - public const FORM_C = \Normalizer::FORM_C; - public const FORM_KC = \Normalizer::FORM_KC; - public const NFD = \Normalizer::NFD; - public const NFKD = \Normalizer::NFKD; - public const NFC = \Normalizer::NFC; - public const NFKC = \Normalizer::NFKC; - - private static $C; - private static $D; - private static $KD; - private static $cC; - private static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4]; - private static $ASCII = "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"; - - public static function isNormalized(string $s, int $form = self::FORM_C) - { - if (!\in_array($form, [self::NFD, self::NFKD, self::NFC, self::NFKC])) { - return false; - } - if (!isset($s[strspn($s, self::$ASCII)])) { - return true; - } - if (self::NFC == $form && preg_match('//u', $s) && !preg_match('/[^\x00-\x{2FF}]/u', $s)) { - return true; - } - - return self::normalize($s, $form) === $s; - } - - public static function normalize(string $s, int $form = self::FORM_C) - { - if (!preg_match('//u', $s)) { - return false; - } - - switch ($form) { - case self::NFC: $C = true; $K = false; break; - case self::NFD: $C = false; $K = false; break; - case self::NFKC: $C = true; $K = true; break; - case self::NFKD: $C = false; $K = true; break; - default: - if (\defined('Normalizer::NONE') && \Normalizer::NONE == $form) { - return $s; - } - - if (80000 > \PHP_VERSION_ID) { - return false; - } - - throw new \ValueError('normalizer_normalize(): Argument #2 ($form) must be a a valid normalization form'); - } - - if ('' === $s) { - return ''; - } - - if ($K && null === self::$KD) { - self::$KD = self::getData('compatibilityDecomposition'); - } - - if (null === self::$D) { - self::$D = self::getData('canonicalDecomposition'); - self::$cC = self::getData('combiningClass'); - } - - if (null !== $mbEncoding = (2 /* MB_OVERLOAD_STRING */ & (int) ini_get('mbstring.func_overload')) ? mb_internal_encoding() : null) { - mb_internal_encoding('8bit'); - } - - $r = self::decompose($s, $K); - - if ($C) { - if (null === self::$C) { - self::$C = self::getData('canonicalComposition'); - } - - $r = self::recompose($r); - } - if (null !== $mbEncoding) { - mb_internal_encoding($mbEncoding); - } - - return $r; - } - - private static function recompose($s) - { - $ASCII = self::$ASCII; - $compMap = self::$C; - $combClass = self::$cC; - $ulenMask = self::$ulenMask; - - $result = $tail = ''; - - $i = $s[0] < "\x80" ? 1 : $ulenMask[$s[0] & "\xF0"]; - $len = \strlen($s); - - $lastUchr = substr($s, 0, $i); - $lastUcls = isset($combClass[$lastUchr]) ? 256 : 0; - - while ($i < $len) { - if ($s[$i] < "\x80") { - // ASCII chars - - if ($tail) { - $lastUchr .= $tail; - $tail = ''; - } - - if ($j = strspn($s, $ASCII, $i + 1)) { - $lastUchr .= substr($s, $i, $j); - $i += $j; - } - - $result .= $lastUchr; - $lastUchr = $s[$i]; - $lastUcls = 0; - ++$i; - continue; - } - - $ulen = $ulenMask[$s[$i] & "\xF0"]; - $uchr = substr($s, $i, $ulen); - - if ($lastUchr < "\xE1\x84\x80" || "\xE1\x84\x92" < $lastUchr - || $uchr < "\xE1\x85\xA1" || "\xE1\x85\xB5" < $uchr - || $lastUcls) { - // Table lookup and combining chars composition - - $ucls = $combClass[$uchr] ?? 0; - - if (isset($compMap[$lastUchr.$uchr]) && (!$lastUcls || $lastUcls < $ucls)) { - $lastUchr = $compMap[$lastUchr.$uchr]; - } elseif ($lastUcls = $ucls) { - $tail .= $uchr; - } else { - if ($tail) { - $lastUchr .= $tail; - $tail = ''; - } - - $result .= $lastUchr; - $lastUchr = $uchr; - } - } else { - // Hangul chars - - $L = \ord($lastUchr[2]) - 0x80; - $V = \ord($uchr[2]) - 0xA1; - $T = 0; - - $uchr = substr($s, $i + $ulen, 3); - - if ("\xE1\x86\xA7" <= $uchr && $uchr <= "\xE1\x87\x82") { - $T = \ord($uchr[2]) - 0xA7; - 0 > $T && $T += 0x40; - $ulen += 3; - } - - $L = 0xAC00 + ($L * 21 + $V) * 28 + $T; - $lastUchr = \chr(0xE0 | $L >> 12).\chr(0x80 | $L >> 6 & 0x3F).\chr(0x80 | $L & 0x3F); - } - - $i += $ulen; - } - - return $result.$lastUchr.$tail; - } - - private static function decompose($s, $c) - { - $result = ''; - - $ASCII = self::$ASCII; - $decompMap = self::$D; - $combClass = self::$cC; - $ulenMask = self::$ulenMask; - if ($c) { - $compatMap = self::$KD; - } - - $c = []; - $i = 0; - $len = \strlen($s); - - while ($i < $len) { - if ($s[$i] < "\x80") { - // ASCII chars - - if ($c) { - ksort($c); - $result .= implode('', $c); - $c = []; - } - - $j = 1 + strspn($s, $ASCII, $i + 1); - $result .= substr($s, $i, $j); - $i += $j; - continue; - } - - $ulen = $ulenMask[$s[$i] & "\xF0"]; - $uchr = substr($s, $i, $ulen); - $i += $ulen; - - if ($uchr < "\xEA\xB0\x80" || "\xED\x9E\xA3" < $uchr) { - // Table lookup - - if ($uchr !== $j = $compatMap[$uchr] ?? ($decompMap[$uchr] ?? $uchr)) { - $uchr = $j; - - $j = \strlen($uchr); - $ulen = $uchr[0] < "\x80" ? 1 : $ulenMask[$uchr[0] & "\xF0"]; - - if ($ulen != $j) { - // Put trailing chars in $s - - $j -= $ulen; - $i -= $j; - - if (0 > $i) { - $s = str_repeat(' ', -$i).$s; - $len -= $i; - $i = 0; - } - - while ($j--) { - $s[$i + $j] = $uchr[$ulen + $j]; - } - - $uchr = substr($uchr, 0, $ulen); - } - } - if (isset($combClass[$uchr])) { - // Combining chars, for sorting - - if (!isset($c[$combClass[$uchr]])) { - $c[$combClass[$uchr]] = ''; - } - $c[$combClass[$uchr]] .= $uchr; - continue; - } - } else { - // Hangul chars - - $uchr = unpack('C*', $uchr); - $j = (($uchr[1] - 224) << 12) + (($uchr[2] - 128) << 6) + $uchr[3] - 0xAC80; - - $uchr = "\xE1\x84".\chr(0x80 + (int) ($j / 588)) - ."\xE1\x85".\chr(0xA1 + (int) (($j % 588) / 28)); - - if ($j %= 28) { - $uchr .= $j < 25 - ? ("\xE1\x86".\chr(0xA7 + $j)) - : ("\xE1\x87".\chr(0x67 + $j)); - } - } - if ($c) { - ksort($c); - $result .= implode('', $c); - $c = []; - } - - $result .= $uchr; - } - - if ($c) { - ksort($c); - $result .= implode('', $c); - } - - return $result; - } - - private static function getData($file) - { - if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) { - return require $file; - } - - return false; - } -} diff --git a/lib/symfony/polyfill-intl-normalizer/README.md b/lib/symfony/polyfill-intl-normalizer/README.md deleted file mode 100644 index b9b762e85..000000000 --- a/lib/symfony/polyfill-intl-normalizer/README.md +++ /dev/null @@ -1,14 +0,0 @@ -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/lib/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php b/lib/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php deleted file mode 100644 index 0fdfc890a..000000000 --- a/lib/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php - -class Normalizer extends Symfony\Polyfill\Intl\Normalizer\Normalizer -{ - /** - * @deprecated since ICU 56 and removed in PHP 8 - */ - public const NONE = 2; - public const FORM_D = 4; - public const FORM_KD = 8; - public const FORM_C = 16; - public const FORM_KC = 32; - public const NFD = 4; - public const NFKD = 8; - public const NFC = 16; - public const NFKC = 32; -} diff --git a/lib/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalComposition.php b/lib/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalComposition.php deleted file mode 100644 index db4764419..000000000 --- a/lib/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalComposition.php +++ /dev/null @@ -1,945 +0,0 @@ -<?php - -return array ( - 'À' => 'À', - 'Á' => 'Á', - 'Â' => 'Â', - 'Ã' => 'Ã', - 'Ä' => 'Ä', - 'Å' => 'Å', - 'Ç' => 'Ç', - 'È' => 'È', - 'É' => 'É', - 'Ê' => 'Ê', - 'Ë' => 'Ë', - 'Ì' => 'Ì', - 'Í' => 'Í', - 'Î' => 'Î', - 'Ï' => 'Ï', - 'Ñ' => 'Ñ', - 'Ò' => 'Ò', - 'Ó' => 'Ó', - 'Ô' => 'Ô', - 'Õ' => 'Õ', - 'Ö' => 'Ö', - 'Ù' => 'Ù', - 'Ú' => 'Ú', - 'Û' => 'Û', - 'Ü' => 'Ü', - 'Ý' => 'Ý', - 'à' => 'à', - 'á' => 'á', - 'â' => 'â', - 'ã' => 'ã', - 'ä' => 'ä', - 'å' => 'å', - 'ç' => 'ç', - 'è' => 'è', - 'é' => 'é', - 'ê' => 'ê', - 'ë' => 'ë', - 'ì' => 'ì', - 'í' => 'í', - 'î' => 'î', - 'ï' => 'ï', - 'ñ' => 'ñ', - 'ò' => 'ò', - 'ó' => 'ó', - 'ô' => 'ô', - 'õ' => 'õ', - 'ö' => 'ö', - 'ù' => 'ù', - 'ú' => 'ú', - 'û' => 'û', - 'ü' => 'ü', - 'ý' => 'ý', - 'ÿ' => 'ÿ', - 'Ā' => 'Ā', - 'ā' => 'ā', - 'Ă' => 'Ă', - 'ă' => 'ă', - 'Ą' => 'Ą', - 'ą' => 'ą', - 'Ć' => 'Ć', - 'ć' => 'ć', - 'Ĉ' => 'Ĉ', - 'ĉ' => 'ĉ', - 'Ċ' => 'Ċ', - 'ċ' => 'ċ', - 'Č' => 'Č', - 'č' => 'č', - 'Ď' => 'Ď', - 'ď' => 'ď', - 'Ē' => 'Ē', - 'ē' => 'ē', - 'Ĕ' => 'Ĕ', - 'ĕ' => 'ĕ', - 'Ė' => 'Ė', - 'ė' => 'ė', - 'Ę' => 'Ę', - 'ę' => 'ę', - 'Ě' => 'Ě', - 'ě' => 'ě', - 'Ĝ' => 'Ĝ', - 'ĝ' => 'ĝ', - 'Ğ' => 'Ğ', - 'ğ' => 'ğ', - 'Ġ' => 'Ġ', - 'ġ' => 'ġ', - 'Ģ' => 'Ģ', - 'ģ' => 'ģ', - 'Ĥ' => 'Ĥ', - 'ĥ' => 'ĥ', - 'Ĩ' => 'Ĩ', - 'ĩ' => 'ĩ', - 'Ī' => 'Ī', - 'ī' => 'ī', - 'Ĭ' => 'Ĭ', - 'ĭ' => 'ĭ', - 'Į' => 'Į', - 'į' => 'į', - 'İ' => 'İ', - 'Ĵ' => 'Ĵ', - 'ĵ' => 'ĵ', - 'Ķ' => 'Ķ', - 'ķ' => 'ķ', - 'Ĺ' => 'Ĺ', - 'ĺ' => 'ĺ', - 'Ļ' => 'Ļ', - 'ļ' => 'ļ', - 'Ľ' => 'Ľ', - 'ľ' => 'ľ', - 'Ń' => 'Ń', - 'ń' => 'ń', - 'Ņ' => 'Ņ', - 'ņ' => 'ņ', - 'Ň' => 'Ň', - 'ň' => 'ň', - 'Ō' => 'Ō', - 'ō' => 'ō', - 'Ŏ' => 'Ŏ', - 'ŏ' => 'ŏ', - 'Ő' => 'Ő', - 'ő' => 'ő', - 'Ŕ' => 'Ŕ', - 'ŕ' => 'ŕ', - 'Ŗ' => 'Ŗ', - 'ŗ' => 'ŗ', - 'Ř' => 'Ř', - 'ř' => 'ř', - 'Ś' => 'Ś', - 'ś' => 'ś', - 'Ŝ' => 'Ŝ', - 'ŝ' => 'ŝ', - 'Ş' => 'Ş', - 'ş' => 'ş', - 'Š' => 'Š', - 'š' => 'š', - 'Ţ' => 'Ţ', - 'ţ' => 'ţ', - 'Ť' => 'Ť', - 'ť' => 'ť', - 'Ũ' => 'Ũ', - 'ũ' => 'ũ', - 'Ū' => 'Ū', - 'ū' => 'ū', - 'Ŭ' => 'Ŭ', - 'ŭ' => 'ŭ', - 'Ů' => 'Ů', - 'ů' => 'ů', - 'Ű' => 'Ű', - 'ű' => 'ű', - 'Ų' => 'Ų', - 'ų' => 'ų', - 'Ŵ' => 'Ŵ', - 'ŵ' => 'ŵ', - 'Ŷ' => 'Ŷ', - 'ŷ' => 'ŷ', - 'Ÿ' => 'Ÿ', - 'Ź' => 'Ź', - 'ź' => 'ź', - 'Ż' => 'Ż', - 'ż' => 'ż', - 'Ž' => 'Ž', - 'ž' => 'ž', - 'Ơ' => 'Ơ', - 'ơ' => 'ơ', - 'Ư' => 'Ư', - 'ư' => 'ư', - 'Ǎ' => 'Ǎ', - 'ǎ' => 'ǎ', - 'Ǐ' => 'Ǐ', - 'ǐ' => 'ǐ', - 'Ǒ' => 'Ǒ', - 'ǒ' => 'ǒ', - 'Ǔ' => 'Ǔ', - 'ǔ' => 'ǔ', - 'Ǖ' => 'Ǖ', - 'ǖ' => 'ǖ', - 'Ǘ' => 'Ǘ', - 'ǘ' => 'ǘ', - 'Ǚ' => 'Ǚ', - 'ǚ' => 'ǚ', - 'Ǜ' => 'Ǜ', - 'ǜ' => 'ǜ', - 'Ǟ' => 'Ǟ', - 'ǟ' => 'ǟ', - 'Ǡ' => 'Ǡ', - 'ǡ' => 'ǡ', - 'Ǣ' => 'Ǣ', - 'ǣ' => 'ǣ', - 'Ǧ' => 'Ǧ', - 'ǧ' => 'ǧ', - 'Ǩ' => 'Ǩ', - 'ǩ' => 'ǩ', - 'Ǫ' => 'Ǫ', - 'ǫ' => 'ǫ', - 'Ǭ' => 'Ǭ', - 'ǭ' => 'ǭ', - 'Ǯ' => 'Ǯ', - 'ǯ' => 'ǯ', - 'ǰ' => 'ǰ', - 'Ǵ' => 'Ǵ', - 'ǵ' => 'ǵ', - 'Ǹ' => 'Ǹ', - 'ǹ' => 'ǹ', - 'Ǻ' => 'Ǻ', - 'ǻ' => 'ǻ', - 'Ǽ' => 'Ǽ', - 'ǽ' => 'ǽ', - 'Ǿ' => 'Ǿ', - 'ǿ' => 'ǿ', - 'Ȁ' => 'Ȁ', - 'ȁ' => 'ȁ', - 'Ȃ' => 'Ȃ', - 'ȃ' => 'ȃ', - 'Ȅ' => 'Ȅ', - 'ȅ' => 'ȅ', - 'Ȇ' => 'Ȇ', - 'ȇ' => 'ȇ', - 'Ȉ' => 'Ȉ', - 'ȉ' => 'ȉ', - 'Ȋ' => 'Ȋ', - 'ȋ' => 'ȋ', - 'Ȍ' => 'Ȍ', - 'ȍ' => 'ȍ', - 'Ȏ' => 'Ȏ', - 'ȏ' => 'ȏ', - 'Ȑ' => 'Ȑ', - 'ȑ' => 'ȑ', - 'Ȓ' => 'Ȓ', - 'ȓ' => 'ȓ', - 'Ȕ' => 'Ȕ', - 'ȕ' => 'ȕ', - 'Ȗ' => 'Ȗ', - 'ȗ' => 'ȗ', - 'Ș' => 'Ș', - 'ș' => 'ș', - 'Ț' => 'Ț', - 'ț' => 'ț', - 'Ȟ' => 'Ȟ', - 'ȟ' => 'ȟ', - 'Ȧ' => 'Ȧ', - 'ȧ' => 'ȧ', - 'Ȩ' => 'Ȩ', - 'ȩ' => 'ȩ', - 'Ȫ' => 'Ȫ', - 'ȫ' => 'ȫ', - 'Ȭ' => 'Ȭ', - 'ȭ' => 'ȭ', - 'Ȯ' => 'Ȯ', - 'ȯ' => 'ȯ', - 'Ȱ' => 'Ȱ', - 'ȱ' => 'ȱ', - 'Ȳ' => 'Ȳ', - 'ȳ' => 'ȳ', - '΅' => '΅', - 'Ά' => 'Ά', - 'Έ' => 'Έ', - 'Ή' => 'Ή', - 'Ί' => 'Ί', - 'Ό' => 'Ό', - 'Ύ' => 'Ύ', - 'Ώ' => 'Ώ', - 'ΐ' => 'ΐ', - 'Ϊ' => 'Ϊ', - 'Ϋ' => 'Ϋ', - 'ά' => 'ά', - 'έ' => 'έ', - 'ή' => 'ή', - 'ί' => 'ί', - 'ΰ' => 'ΰ', - 'ϊ' => 'ϊ', - 'ϋ' => 'ϋ', - 'ό' => 'ό', - 'ύ' => 'ύ', - 'ώ' => 'ώ', - 'ϓ' => 'ϓ', - 'ϔ' => 'ϔ', - 'Ѐ' => 'Ѐ', - 'Ё' => 'Ё', - 'Ѓ' => 'Ѓ', - 'Ї' => 'Ї', - 'Ќ' => 'Ќ', - 'Ѝ' => 'Ѝ', - 'Ў' => 'Ў', - 'Й' => 'Й', - 'й' => 'й', - 'ѐ' => 'ѐ', - 'ё' => 'ё', - 'ѓ' => 'ѓ', - 'ї' => 'ї', - 'ќ' => 'ќ', - 'ѝ' => 'ѝ', - 'ў' => 'ў', - 'Ѷ' => 'Ѷ', - 'ѷ' => 'ѷ', - 'Ӂ' => 'Ӂ', - 'ӂ' => 'ӂ', - 'Ӑ' => 'Ӑ', - 'ӑ' => 'ӑ', - 'Ӓ' => 'Ӓ', - 'ӓ' => 'ӓ', - 'Ӗ' => 'Ӗ', - 'ӗ' => 'ӗ', - 'Ӛ' => 'Ӛ', - 'ӛ' => 'ӛ', - 'Ӝ' => 'Ӝ', - 'ӝ' => 'ӝ', - 'Ӟ' => 'Ӟ', - 'ӟ' => 'ӟ', - 'Ӣ' => 'Ӣ', - 'ӣ' => 'ӣ', - 'Ӥ' => 'Ӥ', - 'ӥ' => 'ӥ', - 'Ӧ' => 'Ӧ', - 'ӧ' => 'ӧ', - 'Ӫ' => 'Ӫ', - 'ӫ' => 'ӫ', - 'Ӭ' => 'Ӭ', - 'ӭ' => 'ӭ', - 'Ӯ' => 'Ӯ', - 'ӯ' => 'ӯ', - 'Ӱ' => 'Ӱ', - 'ӱ' => 'ӱ', - 'Ӳ' => 'Ӳ', - 'ӳ' => 'ӳ', - 'Ӵ' => 'Ӵ', - 'ӵ' => 'ӵ', - 'Ӹ' => 'Ӹ', - 'ӹ' => 'ӹ', - 'آ' => 'آ', - 'أ' => 'أ', - 'ؤ' => 'ؤ', - 'إ' => 'إ', - 'ئ' => 'ئ', - 'ۀ' => 'ۀ', - 'ۂ' => 'ۂ', - 'ۓ' => 'ۓ', - 'ऩ' => 'ऩ', - 'ऱ' => 'ऱ', - 'ऴ' => 'ऴ', - 'ো' => 'ো', - 'ৌ' => 'ৌ', - 'ୈ' => 'ୈ', - 'ୋ' => 'ୋ', - 'ୌ' => 'ୌ', - 'ஔ' => 'ஔ', - 'ொ' => 'ொ', - 'ோ' => 'ோ', - 'ௌ' => 'ௌ', - 'ై' => 'ై', - 'ೀ' => 'ೀ', - 'ೇ' => 'ೇ', - 'ೈ' => 'ೈ', - 'ೊ' => 'ೊ', - 'ೋ' => 'ೋ', - 'ൊ' => 'ൊ', - 'ോ' => 'ോ', - 'ൌ' => 'ൌ', - 'ේ' => 'ේ', - 'ො' => 'ො', - 'ෝ' => 'ෝ', - 'ෞ' => 'ෞ', - 'ဦ' => 'ဦ', - 'ᬆ' => 'ᬆ', - 'ᬈ' => 'ᬈ', - 'ᬊ' => 'ᬊ', - 'ᬌ' => 'ᬌ', - 'ᬎ' => 'ᬎ', - 'ᬒ' => 'ᬒ', - 'ᬻ' => 'ᬻ', - 'ᬽ' => 'ᬽ', - 'ᭀ' => 'ᭀ', - 'ᭁ' => 'ᭁ', - 'ᭃ' => 'ᭃ', - 'Ḁ' => 'Ḁ', - 'ḁ' => 'ḁ', - 'Ḃ' => 'Ḃ', - 'ḃ' => 'ḃ', - 'Ḅ' => 'Ḅ', - 'ḅ' => 'ḅ', - 'Ḇ' => 'Ḇ', - 'ḇ' => 'ḇ', - 'Ḉ' => 'Ḉ', - 'ḉ' => 'ḉ', - 'Ḋ' => 'Ḋ', - 'ḋ' => 'ḋ', - 'Ḍ' => 'Ḍ', - 'ḍ' => 'ḍ', - 'Ḏ' => 'Ḏ', - 'ḏ' => 'ḏ', - 'Ḑ' => 'Ḑ', - 'ḑ' => 'ḑ', - 'Ḓ' => 'Ḓ', - 'ḓ' => 'ḓ', - 'Ḕ' => 'Ḕ', - 'ḕ' => 'ḕ', - 'Ḗ' => 'Ḗ', - 'ḗ' => 'ḗ', - 'Ḙ' => 'Ḙ', - 'ḙ' => 'ḙ', - 'Ḛ' => 'Ḛ', - 'ḛ' => 'ḛ', - 'Ḝ' => 'Ḝ', - 'ḝ' => 'ḝ', - 'Ḟ' => 'Ḟ', - 'ḟ' => 'ḟ', - 'Ḡ' => 'Ḡ', - 'ḡ' => 'ḡ', - 'Ḣ' => 'Ḣ', - 'ḣ' => 'ḣ', - 'Ḥ' => 'Ḥ', - 'ḥ' => 'ḥ', - 'Ḧ' => 'Ḧ', - 'ḧ' => 'ḧ', - 'Ḩ' => 'Ḩ', - 'ḩ' => 'ḩ', - 'Ḫ' => 'Ḫ', - 'ḫ' => 'ḫ', - 'Ḭ' => 'Ḭ', - 'ḭ' => 'ḭ', - 'Ḯ' => 'Ḯ', - 'ḯ' => 'ḯ', - 'Ḱ' => 'Ḱ', - 'ḱ' => 'ḱ', - 'Ḳ' => 'Ḳ', - 'ḳ' => 'ḳ', - 'Ḵ' => 'Ḵ', - 'ḵ' => 'ḵ', - 'Ḷ' => 'Ḷ', - 'ḷ' => 'ḷ', - 'Ḹ' => 'Ḹ', - 'ḹ' => 'ḹ', - 'Ḻ' => 'Ḻ', - 'ḻ' => 'ḻ', - 'Ḽ' => 'Ḽ', - 'ḽ' => 'ḽ', - 'Ḿ' => 'Ḿ', - 'ḿ' => 'ḿ', - 'Ṁ' => 'Ṁ', - 'ṁ' => 'ṁ', - 'Ṃ' => 'Ṃ', - 'ṃ' => 'ṃ', - 'Ṅ' => 'Ṅ', - 'ṅ' => 'ṅ', - 'Ṇ' => 'Ṇ', - 'ṇ' => 'ṇ', - 'Ṉ' => 'Ṉ', - 'ṉ' => 'ṉ', - 'Ṋ' => 'Ṋ', - 'ṋ' => 'ṋ', - 'Ṍ' => 'Ṍ', - 'ṍ' => 'ṍ', - 'Ṏ' => 'Ṏ', - 'ṏ' => 'ṏ', - 'Ṑ' => 'Ṑ', - 'ṑ' => 'ṑ', - 'Ṓ' => 'Ṓ', - 'ṓ' => 'ṓ', - 'Ṕ' => 'Ṕ', - 'ṕ' => 'ṕ', - 'Ṗ' => 'Ṗ', - 'ṗ' => 'ṗ', - 'Ṙ' => 'Ṙ', - 'ṙ' => 'ṙ', - 'Ṛ' => 'Ṛ', - 'ṛ' => 'ṛ', - 'Ṝ' => 'Ṝ', - 'ṝ' => 'ṝ', - 'Ṟ' => 'Ṟ', - 'ṟ' => 'ṟ', - 'Ṡ' => 'Ṡ', - 'ṡ' => 'ṡ', - 'Ṣ' => 'Ṣ', - 'ṣ' => 'ṣ', - 'Ṥ' => 'Ṥ', - 'ṥ' => 'ṥ', - 'Ṧ' => 'Ṧ', - 'ṧ' => 'ṧ', - 'Ṩ' => 'Ṩ', - 'ṩ' => 'ṩ', - 'Ṫ' => 'Ṫ', - 'ṫ' => 'ṫ', - 'Ṭ' => 'Ṭ', - 'ṭ' => 'ṭ', - 'Ṯ' => 'Ṯ', - 'ṯ' => 'ṯ', - 'Ṱ' => 'Ṱ', - 'ṱ' => 'ṱ', - 'Ṳ' => 'Ṳ', - 'ṳ' => 'ṳ', - 'Ṵ' => 'Ṵ', - 'ṵ' => 'ṵ', - 'Ṷ' => 'Ṷ', - 'ṷ' => 'ṷ', - 'Ṹ' => 'Ṹ', - 'ṹ' => 'ṹ', - 'Ṻ' => 'Ṻ', - 'ṻ' => 'ṻ', - 'Ṽ' => 'Ṽ', - 'ṽ' => 'ṽ', - 'Ṿ' => 'Ṿ', - 'ṿ' => 'ṿ', - 'Ẁ' => 'Ẁ', - 'ẁ' => 'ẁ', - 'Ẃ' => 'Ẃ', - 'ẃ' => 'ẃ', - 'Ẅ' => 'Ẅ', - 'ẅ' => 'ẅ', - 'Ẇ' => 'Ẇ', - 'ẇ' => 'ẇ', - 'Ẉ' => 'Ẉ', - 'ẉ' => 'ẉ', - 'Ẋ' => 'Ẋ', - 'ẋ' => 'ẋ', - 'Ẍ' => 'Ẍ', - 'ẍ' => 'ẍ', - 'Ẏ' => 'Ẏ', - 'ẏ' => 'ẏ', - 'Ẑ' => 'Ẑ', - 'ẑ' => 'ẑ', - 'Ẓ' => 'Ẓ', - 'ẓ' => 'ẓ', - 'Ẕ' => 'Ẕ', - 'ẕ' => 'ẕ', - 'ẖ' => 'ẖ', - 'ẗ' => 'ẗ', - 'ẘ' => 'ẘ', - 'ẙ' => 'ẙ', - 'ẛ' => 'ẛ', - 'Ạ' => 'Ạ', - 'ạ' => 'ạ', - 'Ả' => 'Ả', - 'ả' => 'ả', - 'Ấ' => 'Ấ', - 'ấ' => 'ấ', - 'Ầ' => 'Ầ', - 'ầ' => 'ầ', - 'Ẩ' => 'Ẩ', - 'ẩ' => 'ẩ', - 'Ẫ' => 'Ẫ', - 'ẫ' => 'ẫ', - 'Ậ' => 'Ậ', - 'ậ' => 'ậ', - 'Ắ' => 'Ắ', - 'ắ' => 'ắ', - 'Ằ' => 'Ằ', - 'ằ' => 'ằ', - 'Ẳ' => 'Ẳ', - 'ẳ' => 'ẳ', - 'Ẵ' => 'Ẵ', - 'ẵ' => 'ẵ', - 'Ặ' => 'Ặ', - 'ặ' => 'ặ', - 'Ẹ' => 'Ẹ', - 'ẹ' => 'ẹ', - 'Ẻ' => 'Ẻ', - 'ẻ' => 'ẻ', - 'Ẽ' => 'Ẽ', - 'ẽ' => 'ẽ', - 'Ế' => 'Ế', - 'ế' => 'ế', - 'Ề' => 'Ề', - 'ề' => 'ề', - 'Ể' => 'Ể', - 'ể' => 'ể', - 'Ễ' => 'Ễ', - 'ễ' => 'ễ', - 'Ệ' => 'Ệ', - 'ệ' => 'ệ', - 'Ỉ' => 'Ỉ', - 'ỉ' => 'ỉ', - 'Ị' => 'Ị', - 'ị' => 'ị', - 'Ọ' => 'Ọ', - 'ọ' => 'ọ', - 'Ỏ' => 'Ỏ', - 'ỏ' => 'ỏ', - 'Ố' => 'Ố', - 'ố' => 'ố', - 'Ồ' => 'Ồ', - 'ồ' => 'ồ', - 'Ổ' => 'Ổ', - 'ổ' => 'ổ', - 'Ỗ' => 'Ỗ', - 'ỗ' => 'ỗ', - 'Ộ' => 'Ộ', - 'ộ' => 'ộ', - 'Ớ' => 'Ớ', - 'ớ' => 'ớ', - 'Ờ' => 'Ờ', - 'ờ' => 'ờ', - 'Ở' => 'Ở', - 'ở' => 'ở', - 'Ỡ' => 'Ỡ', - 'ỡ' => 'ỡ', - 'Ợ' => 'Ợ', - 'ợ' => 'ợ', - 'Ụ' => 'Ụ', - 'ụ' => 'ụ', - 'Ủ' => 'Ủ', - 'ủ' => 'ủ', - 'Ứ' => 'Ứ', - 'ứ' => 'ứ', - 'Ừ' => 'Ừ', - 'ừ' => 'ừ', - 'Ử' => 'Ử', - 'ử' => 'ử', - 'Ữ' => 'Ữ', - 'ữ' => 'ữ', - 'Ự' => 'Ự', - 'ự' => 'ự', - 'Ỳ' => 'Ỳ', - 'ỳ' => 'ỳ', - 'Ỵ' => 'Ỵ', - 'ỵ' => 'ỵ', - 'Ỷ' => 'Ỷ', - 'ỷ' => 'ỷ', - 'Ỹ' => 'Ỹ', - 'ỹ' => 'ỹ', - 'ἀ' => 'ἀ', - 'ἁ' => 'ἁ', - 'ἂ' => 'ἂ', - 'ἃ' => 'ἃ', - 'ἄ' => 'ἄ', - 'ἅ' => 'ἅ', - 'ἆ' => 'ἆ', - 'ἇ' => 'ἇ', - 'Ἀ' => 'Ἀ', - 'Ἁ' => 'Ἁ', - 'Ἂ' => 'Ἂ', - 'Ἃ' => 'Ἃ', - 'Ἄ' => 'Ἄ', - 'Ἅ' => 'Ἅ', - 'Ἆ' => 'Ἆ', - 'Ἇ' => 'Ἇ', - 'ἐ' => 'ἐ', - 'ἑ' => 'ἑ', - 'ἒ' => 'ἒ', - 'ἓ' => 'ἓ', - 'ἔ' => 'ἔ', - 'ἕ' => 'ἕ', - 'Ἐ' => 'Ἐ', - 'Ἑ' => 'Ἑ', - 'Ἒ' => 'Ἒ', - 'Ἓ' => 'Ἓ', - 'Ἔ' => 'Ἔ', - 'Ἕ' => 'Ἕ', - 'ἠ' => 'ἠ', - 'ἡ' => 'ἡ', - 'ἢ' => 'ἢ', - 'ἣ' => 'ἣ', - 'ἤ' => 'ἤ', - 'ἥ' => 'ἥ', - 'ἦ' => 'ἦ', - 'ἧ' => 'ἧ', - 'Ἠ' => 'Ἠ', - 'Ἡ' => 'Ἡ', - 'Ἢ' => 'Ἢ', - 'Ἣ' => 'Ἣ', - 'Ἤ' => 'Ἤ', - 'Ἥ' => 'Ἥ', - 'Ἦ' => 'Ἦ', - 'Ἧ' => 'Ἧ', - 'ἰ' => 'ἰ', - 'ἱ' => 'ἱ', - 'ἲ' => 'ἲ', - 'ἳ' => 'ἳ', - 'ἴ' => 'ἴ', - 'ἵ' => 'ἵ', - 'ἶ' => 'ἶ', - 'ἷ' => 'ἷ', - 'Ἰ' => 'Ἰ', - 'Ἱ' => 'Ἱ', - 'Ἲ' => 'Ἲ', - 'Ἳ' => 'Ἳ', - 'Ἴ' => 'Ἴ', - 'Ἵ' => 'Ἵ', - 'Ἶ' => 'Ἶ', - 'Ἷ' => 'Ἷ', - 'ὀ' => 'ὀ', - 'ὁ' => 'ὁ', - 'ὂ' => 'ὂ', - 'ὃ' => 'ὃ', - 'ὄ' => 'ὄ', - 'ὅ' => 'ὅ', - 'Ὀ' => 'Ὀ', - 'Ὁ' => 'Ὁ', - 'Ὂ' => 'Ὂ', - 'Ὃ' => 'Ὃ', - 'Ὄ' => 'Ὄ', - 'Ὅ' => 'Ὅ', - 'ὐ' => 'ὐ', - 'ὑ' => 'ὑ', - 'ὒ' => 'ὒ', - 'ὓ' => 'ὓ', - 'ὔ' => 'ὔ', - 'ὕ' => 'ὕ', - 'ὖ' => 'ὖ', - 'ὗ' => 'ὗ', - 'Ὑ' => 'Ὑ', - 'Ὓ' => 'Ὓ', - 'Ὕ' => 'Ὕ', - 'Ὗ' => 'Ὗ', - 'ὠ' => 'ὠ', - 'ὡ' => 'ὡ', - 'ὢ' => 'ὢ', - 'ὣ' => 'ὣ', - 'ὤ' => 'ὤ', - 'ὥ' => 'ὥ', - 'ὦ' => 'ὦ', - 'ὧ' => 'ὧ', - 'Ὠ' => 'Ὠ', - 'Ὡ' => 'Ὡ', - 'Ὢ' => 'Ὢ', - 'Ὣ' => 'Ὣ', - 'Ὤ' => 'Ὤ', - 'Ὥ' => 'Ὥ', - 'Ὦ' => 'Ὦ', - 'Ὧ' => 'Ὧ', - 'ὰ' => 'ὰ', - 'ὲ' => 'ὲ', - 'ὴ' => 'ὴ', - 'ὶ' => 'ὶ', - 'ὸ' => 'ὸ', - 'ὺ' => 'ὺ', - 'ὼ' => 'ὼ', - 'ᾀ' => 'ᾀ', - 'ᾁ' => 'ᾁ', - 'ᾂ' => 'ᾂ', - 'ᾃ' => 'ᾃ', - 'ᾄ' => 'ᾄ', - 'ᾅ' => 'ᾅ', - 'ᾆ' => 'ᾆ', - 'ᾇ' => 'ᾇ', - 'ᾈ' => 'ᾈ', - 'ᾉ' => 'ᾉ', - 'ᾊ' => 'ᾊ', - 'ᾋ' => 'ᾋ', - 'ᾌ' => 'ᾌ', - 'ᾍ' => 'ᾍ', - 'ᾎ' => 'ᾎ', - 'ᾏ' => 'ᾏ', - 'ᾐ' => 'ᾐ', - 'ᾑ' => 'ᾑ', - 'ᾒ' => 'ᾒ', - 'ᾓ' => 'ᾓ', - 'ᾔ' => 'ᾔ', - 'ᾕ' => 'ᾕ', - 'ᾖ' => 'ᾖ', - 'ᾗ' => 'ᾗ', - 'ᾘ' => 'ᾘ', - 'ᾙ' => 'ᾙ', - 'ᾚ' => 'ᾚ', - 'ᾛ' => 'ᾛ', - 'ᾜ' => 'ᾜ', - 'ᾝ' => 'ᾝ', - 'ᾞ' => 'ᾞ', - 'ᾟ' => 'ᾟ', - 'ᾠ' => 'ᾠ', - 'ᾡ' => 'ᾡ', - 'ᾢ' => 'ᾢ', - 'ᾣ' => 'ᾣ', - 'ᾤ' => 'ᾤ', - 'ᾥ' => 'ᾥ', - 'ᾦ' => 'ᾦ', - 'ᾧ' => 'ᾧ', - 'ᾨ' => 'ᾨ', - 'ᾩ' => 'ᾩ', - 'ᾪ' => 'ᾪ', - 'ᾫ' => 'ᾫ', - 'ᾬ' => 'ᾬ', - 'ᾭ' => 'ᾭ', - 'ᾮ' => 'ᾮ', - 'ᾯ' => 'ᾯ', - 'ᾰ' => 'ᾰ', - 'ᾱ' => 'ᾱ', - 'ᾲ' => 'ᾲ', - 'ᾳ' => 'ᾳ', - 'ᾴ' => 'ᾴ', - 'ᾶ' => 'ᾶ', - 'ᾷ' => 'ᾷ', - 'Ᾰ' => 'Ᾰ', - 'Ᾱ' => 'Ᾱ', - 'Ὰ' => 'Ὰ', - 'ᾼ' => 'ᾼ', - '῁' => '῁', - 'ῂ' => 'ῂ', - 'ῃ' => 'ῃ', - 'ῄ' => 'ῄ', - 'ῆ' => 'ῆ', - 'ῇ' => 'ῇ', - 'Ὲ' => 'Ὲ', - 'Ὴ' => 'Ὴ', - 'ῌ' => 'ῌ', - '῍' => '῍', - '῎' => '῎', - '῏' => '῏', - 'ῐ' => 'ῐ', - 'ῑ' => 'ῑ', - 'ῒ' => 'ῒ', - 'ῖ' => 'ῖ', - 'ῗ' => 'ῗ', - 'Ῐ' => 'Ῐ', - 'Ῑ' => 'Ῑ', - 'Ὶ' => 'Ὶ', - '῝' => '῝', - '῞' => '῞', - '῟' => '῟', - 'ῠ' => 'ῠ', - 'ῡ' => 'ῡ', - 'ῢ' => 'ῢ', - 'ῤ' => 'ῤ', - 'ῥ' => 'ῥ', - 'ῦ' => 'ῦ', - 'ῧ' => 'ῧ', - 'Ῠ' => 'Ῠ', - 'Ῡ' => 'Ῡ', - 'Ὺ' => 'Ὺ', - 'Ῥ' => 'Ῥ', - '῭' => '῭', - 'ῲ' => 'ῲ', - 'ῳ' => 'ῳ', - 'ῴ' => 'ῴ', - 'ῶ' => 'ῶ', - 'ῷ' => 'ῷ', - 'Ὸ' => 'Ὸ', - 'Ὼ' => 'Ὼ', - 'ῼ' => 'ῼ', - '↚' => '↚', - '↛' => '↛', - '↮' => '↮', - '⇍' => '⇍', - '⇎' => '⇎', - '⇏' => '⇏', - '∄' => '∄', - '∉' => '∉', - '∌' => '∌', - '∤' => '∤', - '∦' => '∦', - '≁' => '≁', - '≄' => '≄', - '≇' => '≇', - '≉' => '≉', - '≠' => '≠', - '≢' => '≢', - '≭' => '≭', - '≮' => '≮', - '≯' => '≯', - '≰' => '≰', - '≱' => '≱', - '≴' => '≴', - '≵' => '≵', - '≸' => '≸', - '≹' => '≹', - '⊀' => '⊀', - '⊁' => '⊁', - '⊄' => '⊄', - '⊅' => '⊅', - '⊈' => '⊈', - '⊉' => '⊉', - '⊬' => '⊬', - '⊭' => '⊭', - '⊮' => '⊮', - '⊯' => '⊯', - '⋠' => '⋠', - '⋡' => '⋡', - '⋢' => '⋢', - '⋣' => '⋣', - '⋪' => '⋪', - '⋫' => '⋫', - '⋬' => '⋬', - '⋭' => '⋭', - 'が' => 'が', - 'ぎ' => 'ぎ', - 'ぐ' => 'ぐ', - 'げ' => 'げ', - 'ご' => 'ご', - 'ざ' => 'ざ', - 'じ' => 'じ', - 'ず' => 'ず', - 'ぜ' => 'ぜ', - 'ぞ' => 'ぞ', - 'だ' => 'だ', - 'ぢ' => 'ぢ', - 'づ' => 'づ', - 'で' => 'で', - 'ど' => 'ど', - 'ば' => 'ば', - 'ぱ' => 'ぱ', - 'び' => 'び', - 'ぴ' => 'ぴ', - 'ぶ' => 'ぶ', - 'ぷ' => 'ぷ', - 'べ' => 'べ', - 'ぺ' => 'ぺ', - 'ぼ' => 'ぼ', - 'ぽ' => 'ぽ', - 'ゔ' => 'ゔ', - 'ゞ' => 'ゞ', - 'ガ' => 'ガ', - 'ギ' => 'ギ', - 'グ' => 'グ', - 'ゲ' => 'ゲ', - 'ゴ' => 'ゴ', - 'ザ' => 'ザ', - 'ジ' => 'ジ', - 'ズ' => 'ズ', - 'ゼ' => 'ゼ', - 'ゾ' => 'ゾ', - 'ダ' => 'ダ', - 'ヂ' => 'ヂ', - 'ヅ' => 'ヅ', - 'デ' => 'デ', - 'ド' => 'ド', - 'バ' => 'バ', - 'パ' => 'パ', - 'ビ' => 'ビ', - 'ピ' => 'ピ', - 'ブ' => 'ブ', - 'プ' => 'プ', - 'ベ' => 'ベ', - 'ペ' => 'ペ', - 'ボ' => 'ボ', - 'ポ' => 'ポ', - 'ヴ' => 'ヴ', - 'ヷ' => 'ヷ', - 'ヸ' => 'ヸ', - 'ヹ' => 'ヹ', - 'ヺ' => 'ヺ', - 'ヾ' => 'ヾ', - '𑂚' => '𑂚', - '𑂜' => '𑂜', - '𑂫' => '𑂫', - '𑄮' => '𑄮', - '𑄯' => '𑄯', - '𑍋' => '𑍋', - '𑍌' => '𑍌', - '𑒻' => '𑒻', - '𑒼' => '𑒼', - '𑒾' => '𑒾', - '𑖺' => '𑖺', - '𑖻' => '𑖻', - '𑤸' => '𑤸', -); diff --git a/lib/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalDecomposition.php b/lib/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalDecomposition.php deleted file mode 100644 index 5a3e8e096..000000000 --- a/lib/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalDecomposition.php +++ /dev/null @@ -1,2065 +0,0 @@ -<?php - -return array ( - 'À' => 'À', - 'Á' => 'Á', - 'Â' => 'Â', - 'Ã' => 'Ã', - 'Ä' => 'Ä', - 'Å' => 'Å', - 'Ç' => 'Ç', - 'È' => 'È', - 'É' => 'É', - 'Ê' => 'Ê', - 'Ë' => 'Ë', - 'Ì' => 'Ì', - 'Í' => 'Í', - 'Î' => 'Î', - 'Ï' => 'Ï', - 'Ñ' => 'Ñ', - 'Ò' => 'Ò', - 'Ó' => 'Ó', - 'Ô' => 'Ô', - 'Õ' => 'Õ', - 'Ö' => 'Ö', - 'Ù' => 'Ù', - 'Ú' => 'Ú', - 'Û' => 'Û', - 'Ü' => 'Ü', - 'Ý' => 'Ý', - 'à' => 'à', - 'á' => 'á', - 'â' => 'â', - 'ã' => 'ã', - 'ä' => 'ä', - 'å' => 'å', - 'ç' => 'ç', - 'è' => 'è', - 'é' => 'é', - 'ê' => 'ê', - 'ë' => 'ë', - 'ì' => 'ì', - 'í' => 'í', - 'î' => 'î', - 'ï' => 'ï', - 'ñ' => 'ñ', - 'ò' => 'ò', - 'ó' => 'ó', - 'ô' => 'ô', - 'õ' => 'õ', - 'ö' => 'ö', - 'ù' => 'ù', - 'ú' => 'ú', - 'û' => 'û', - 'ü' => 'ü', - 'ý' => 'ý', - 'ÿ' => 'ÿ', - 'Ā' => 'Ā', - 'ā' => 'ā', - 'Ă' => 'Ă', - 'ă' => 'ă', - 'Ą' => 'Ą', - 'ą' => 'ą', - 'Ć' => 'Ć', - 'ć' => 'ć', - 'Ĉ' => 'Ĉ', - 'ĉ' => 'ĉ', - 'Ċ' => 'Ċ', - 'ċ' => 'ċ', - 'Č' => 'Č', - 'č' => 'č', - 'Ď' => 'Ď', - 'ď' => 'ď', - 'Ē' => 'Ē', - 'ē' => 'ē', - 'Ĕ' => 'Ĕ', - 'ĕ' => 'ĕ', - 'Ė' => 'Ė', - 'ė' => 'ė', - 'Ę' => 'Ę', - 'ę' => 'ę', - 'Ě' => 'Ě', - 'ě' => 'ě', - 'Ĝ' => 'Ĝ', - 'ĝ' => 'ĝ', - 'Ğ' => 'Ğ', - 'ğ' => 'ğ', - 'Ġ' => 'Ġ', - 'ġ' => 'ġ', - 'Ģ' => 'Ģ', - 'ģ' => 'ģ', - 'Ĥ' => 'Ĥ', - 'ĥ' => 'ĥ', - 'Ĩ' => 'Ĩ', - 'ĩ' => 'ĩ', - 'Ī' => 'Ī', - 'ī' => 'ī', - 'Ĭ' => 'Ĭ', - 'ĭ' => 'ĭ', - 'Į' => 'Į', - 'į' => 'į', - 'İ' => 'İ', - 'Ĵ' => 'Ĵ', - 'ĵ' => 'ĵ', - 'Ķ' => 'Ķ', - 'ķ' => 'ķ', - 'Ĺ' => 'Ĺ', - 'ĺ' => 'ĺ', - 'Ļ' => 'Ļ', - 'ļ' => 'ļ', - 'Ľ' => 'Ľ', - 'ľ' => 'ľ', - 'Ń' => 'Ń', - 'ń' => 'ń', - 'Ņ' => 'Ņ', - 'ņ' => 'ņ', - 'Ň' => 'Ň', - 'ň' => 'ň', - 'Ō' => 'Ō', - 'ō' => 'ō', - 'Ŏ' => 'Ŏ', - 'ŏ' => 'ŏ', - 'Ő' => 'Ő', - 'ő' => 'ő', - 'Ŕ' => 'Ŕ', - 'ŕ' => 'ŕ', - 'Ŗ' => 'Ŗ', - 'ŗ' => 'ŗ', - 'Ř' => 'Ř', - 'ř' => 'ř', - 'Ś' => 'Ś', - 'ś' => 'ś', - 'Ŝ' => 'Ŝ', - 'ŝ' => 'ŝ', - 'Ş' => 'Ş', - 'ş' => 'ş', - 'Š' => 'Š', - 'š' => 'š', - 'Ţ' => 'Ţ', - 'ţ' => 'ţ', - 'Ť' => 'Ť', - 'ť' => 'ť', - 'Ũ' => 'Ũ', - 'ũ' => 'ũ', - 'Ū' => 'Ū', - 'ū' => 'ū', - 'Ŭ' => 'Ŭ', - 'ŭ' => 'ŭ', - 'Ů' => 'Ů', - 'ů' => 'ů', - 'Ű' => 'Ű', - 'ű' => 'ű', - 'Ų' => 'Ų', - 'ų' => 'ų', - 'Ŵ' => 'Ŵ', - 'ŵ' => 'ŵ', - 'Ŷ' => 'Ŷ', - 'ŷ' => 'ŷ', - 'Ÿ' => 'Ÿ', - 'Ź' => 'Ź', - 'ź' => 'ź', - 'Ż' => 'Ż', - 'ż' => 'ż', - 'Ž' => 'Ž', - 'ž' => 'ž', - 'Ơ' => 'Ơ', - 'ơ' => 'ơ', - 'Ư' => 'Ư', - 'ư' => 'ư', - 'Ǎ' => 'Ǎ', - 'ǎ' => 'ǎ', - 'Ǐ' => 'Ǐ', - 'ǐ' => 'ǐ', - 'Ǒ' => 'Ǒ', - 'ǒ' => 'ǒ', - 'Ǔ' => 'Ǔ', - 'ǔ' => 'ǔ', - 'Ǖ' => 'Ǖ', - 'ǖ' => 'ǖ', - 'Ǘ' => 'Ǘ', - 'ǘ' => 'ǘ', - 'Ǚ' => 'Ǚ', - 'ǚ' => 'ǚ', - 'Ǜ' => 'Ǜ', - 'ǜ' => 'ǜ', - 'Ǟ' => 'Ǟ', - 'ǟ' => 'ǟ', - 'Ǡ' => 'Ǡ', - 'ǡ' => 'ǡ', - 'Ǣ' => 'Ǣ', - 'ǣ' => 'ǣ', - 'Ǧ' => 'Ǧ', - 'ǧ' => 'ǧ', - 'Ǩ' => 'Ǩ', - 'ǩ' => 'ǩ', - 'Ǫ' => 'Ǫ', - 'ǫ' => 'ǫ', - 'Ǭ' => 'Ǭ', - 'ǭ' => 'ǭ', - 'Ǯ' => 'Ǯ', - 'ǯ' => 'ǯ', - 'ǰ' => 'ǰ', - 'Ǵ' => 'Ǵ', - 'ǵ' => 'ǵ', - 'Ǹ' => 'Ǹ', - 'ǹ' => 'ǹ', - 'Ǻ' => 'Ǻ', - 'ǻ' => 'ǻ', - 'Ǽ' => 'Ǽ', - 'ǽ' => 'ǽ', - 'Ǿ' => 'Ǿ', - 'ǿ' => 'ǿ', - 'Ȁ' => 'Ȁ', - 'ȁ' => 'ȁ', - 'Ȃ' => 'Ȃ', - 'ȃ' => 'ȃ', - 'Ȅ' => 'Ȅ', - 'ȅ' => 'ȅ', - 'Ȇ' => 'Ȇ', - 'ȇ' => 'ȇ', - 'Ȉ' => 'Ȉ', - 'ȉ' => 'ȉ', - 'Ȋ' => 'Ȋ', - 'ȋ' => 'ȋ', - 'Ȍ' => 'Ȍ', - 'ȍ' => 'ȍ', - 'Ȏ' => 'Ȏ', - 'ȏ' => 'ȏ', - 'Ȑ' => 'Ȑ', - 'ȑ' => 'ȑ', - 'Ȓ' => 'Ȓ', - 'ȓ' => 'ȓ', - 'Ȕ' => 'Ȕ', - 'ȕ' => 'ȕ', - 'Ȗ' => 'Ȗ', - 'ȗ' => 'ȗ', - 'Ș' => 'Ș', - 'ș' => 'ș', - 'Ț' => 'Ț', - 'ț' => 'ț', - 'Ȟ' => 'Ȟ', - 'ȟ' => 'ȟ', - 'Ȧ' => 'Ȧ', - 'ȧ' => 'ȧ', - 'Ȩ' => 'Ȩ', - 'ȩ' => 'ȩ', - 'Ȫ' => 'Ȫ', - 'ȫ' => 'ȫ', - 'Ȭ' => 'Ȭ', - 'ȭ' => 'ȭ', - 'Ȯ' => 'Ȯ', - 'ȯ' => 'ȯ', - 'Ȱ' => 'Ȱ', - 'ȱ' => 'ȱ', - 'Ȳ' => 'Ȳ', - 'ȳ' => 'ȳ', - '̀' => '̀', - '́' => '́', - '̓' => '̓', - '̈́' => '̈́', - 'ʹ' => 'ʹ', - ';' => ';', - '΅' => '΅', - 'Ά' => 'Ά', - '·' => '·', - 'Έ' => 'Έ', - 'Ή' => 'Ή', - 'Ί' => 'Ί', - 'Ό' => 'Ό', - 'Ύ' => 'Ύ', - 'Ώ' => 'Ώ', - 'ΐ' => 'ΐ', - 'Ϊ' => 'Ϊ', - 'Ϋ' => 'Ϋ', - 'ά' => 'ά', - 'έ' => 'έ', - 'ή' => 'ή', - 'ί' => 'ί', - 'ΰ' => 'ΰ', - 'ϊ' => 'ϊ', - 'ϋ' => 'ϋ', - 'ό' => 'ό', - 'ύ' => 'ύ', - 'ώ' => 'ώ', - 'ϓ' => 'ϓ', - 'ϔ' => 'ϔ', - 'Ѐ' => 'Ѐ', - 'Ё' => 'Ё', - 'Ѓ' => 'Ѓ', - 'Ї' => 'Ї', - 'Ќ' => 'Ќ', - 'Ѝ' => 'Ѝ', - 'Ў' => 'Ў', - 'Й' => 'Й', - 'й' => 'й', - 'ѐ' => 'ѐ', - 'ё' => 'ё', - 'ѓ' => 'ѓ', - 'ї' => 'ї', - 'ќ' => 'ќ', - 'ѝ' => 'ѝ', - 'ў' => 'ў', - 'Ѷ' => 'Ѷ', - 'ѷ' => 'ѷ', - 'Ӂ' => 'Ӂ', - 'ӂ' => 'ӂ', - 'Ӑ' => 'Ӑ', - 'ӑ' => 'ӑ', - 'Ӓ' => 'Ӓ', - 'ӓ' => 'ӓ', - 'Ӗ' => 'Ӗ', - 'ӗ' => 'ӗ', - 'Ӛ' => 'Ӛ', - 'ӛ' => 'ӛ', - 'Ӝ' => 'Ӝ', - 'ӝ' => 'ӝ', - 'Ӟ' => 'Ӟ', - 'ӟ' => 'ӟ', - 'Ӣ' => 'Ӣ', - 'ӣ' => 'ӣ', - 'Ӥ' => 'Ӥ', - 'ӥ' => 'ӥ', - 'Ӧ' => 'Ӧ', - 'ӧ' => 'ӧ', - 'Ӫ' => 'Ӫ', - 'ӫ' => 'ӫ', - 'Ӭ' => 'Ӭ', - 'ӭ' => 'ӭ', - 'Ӯ' => 'Ӯ', - 'ӯ' => 'ӯ', - 'Ӱ' => 'Ӱ', - 'ӱ' => 'ӱ', - 'Ӳ' => 'Ӳ', - 'ӳ' => 'ӳ', - 'Ӵ' => 'Ӵ', - 'ӵ' => 'ӵ', - 'Ӹ' => 'Ӹ', - 'ӹ' => 'ӹ', - 'آ' => 'آ', - 'أ' => 'أ', - 'ؤ' => 'ؤ', - 'إ' => 'إ', - 'ئ' => 'ئ', - 'ۀ' => 'ۀ', - 'ۂ' => 'ۂ', - 'ۓ' => 'ۓ', - 'ऩ' => 'ऩ', - 'ऱ' => 'ऱ', - 'ऴ' => 'ऴ', - 'क़' => 'क़', - 'ख़' => 'ख़', - 'ग़' => 'ग़', - 'ज़' => 'ज़', - 'ड़' => 'ड़', - 'ढ़' => 'ढ़', - 'फ़' => 'फ़', - 'य़' => 'य़', - 'ো' => 'ো', - 'ৌ' => 'ৌ', - 'ড়' => 'ড়', - 'ঢ়' => 'ঢ়', - 'য়' => 'য়', - 'ਲ਼' => 'ਲ਼', - 'ਸ਼' => 'ਸ਼', - 'ਖ਼' => 'ਖ਼', - 'ਗ਼' => 'ਗ਼', - 'ਜ਼' => 'ਜ਼', - 'ਫ਼' => 'ਫ਼', - 'ୈ' => 'ୈ', - 'ୋ' => 'ୋ', - 'ୌ' => 'ୌ', - 'ଡ଼' => 'ଡ଼', - 'ଢ଼' => 'ଢ଼', - 'ஔ' => 'ஔ', - 'ொ' => 'ொ', - 'ோ' => 'ோ', - 'ௌ' => 'ௌ', - 'ై' => 'ై', - 'ೀ' => 'ೀ', - 'ೇ' => 'ೇ', - 'ೈ' => 'ೈ', - 'ೊ' => 'ೊ', - 'ೋ' => 'ೋ', - 'ൊ' => 'ൊ', - 'ോ' => 'ോ', - 'ൌ' => 'ൌ', - 'ේ' => 'ේ', - 'ො' => 'ො', - 'ෝ' => 'ෝ', - 'ෞ' => 'ෞ', - 'གྷ' => 'གྷ', - 'ཌྷ' => 'ཌྷ', - 'དྷ' => 'དྷ', - 'བྷ' => 'བྷ', - 'ཛྷ' => 'ཛྷ', - 'ཀྵ' => 'ཀྵ', - 'ཱི' => 'ཱི', - 'ཱུ' => 'ཱུ', - 'ྲྀ' => 'ྲྀ', - 'ླྀ' => 'ླྀ', - 'ཱྀ' => 'ཱྀ', - 'ྒྷ' => 'ྒྷ', - 'ྜྷ' => 'ྜྷ', - 'ྡྷ' => 'ྡྷ', - 'ྦྷ' => 'ྦྷ', - 'ྫྷ' => 'ྫྷ', - 'ྐྵ' => 'ྐྵ', - 'ဦ' => 'ဦ', - 'ᬆ' => 'ᬆ', - 'ᬈ' => 'ᬈ', - 'ᬊ' => 'ᬊ', - 'ᬌ' => 'ᬌ', - 'ᬎ' => 'ᬎ', - 'ᬒ' => 'ᬒ', - 'ᬻ' => 'ᬻ', - 'ᬽ' => 'ᬽ', - 'ᭀ' => 'ᭀ', - 'ᭁ' => 'ᭁ', - 'ᭃ' => 'ᭃ', - 'Ḁ' => 'Ḁ', - 'ḁ' => 'ḁ', - 'Ḃ' => 'Ḃ', - 'ḃ' => 'ḃ', - 'Ḅ' => 'Ḅ', - 'ḅ' => 'ḅ', - 'Ḇ' => 'Ḇ', - 'ḇ' => 'ḇ', - 'Ḉ' => 'Ḉ', - 'ḉ' => 'ḉ', - 'Ḋ' => 'Ḋ', - 'ḋ' => 'ḋ', - 'Ḍ' => 'Ḍ', - 'ḍ' => 'ḍ', - 'Ḏ' => 'Ḏ', - 'ḏ' => 'ḏ', - 'Ḑ' => 'Ḑ', - 'ḑ' => 'ḑ', - 'Ḓ' => 'Ḓ', - 'ḓ' => 'ḓ', - 'Ḕ' => 'Ḕ', - 'ḕ' => 'ḕ', - 'Ḗ' => 'Ḗ', - 'ḗ' => 'ḗ', - 'Ḙ' => 'Ḙ', - 'ḙ' => 'ḙ', - 'Ḛ' => 'Ḛ', - 'ḛ' => 'ḛ', - 'Ḝ' => 'Ḝ', - 'ḝ' => 'ḝ', - 'Ḟ' => 'Ḟ', - 'ḟ' => 'ḟ', - 'Ḡ' => 'Ḡ', - 'ḡ' => 'ḡ', - 'Ḣ' => 'Ḣ', - 'ḣ' => 'ḣ', - 'Ḥ' => 'Ḥ', - 'ḥ' => 'ḥ', - 'Ḧ' => 'Ḧ', - 'ḧ' => 'ḧ', - 'Ḩ' => 'Ḩ', - 'ḩ' => 'ḩ', - 'Ḫ' => 'Ḫ', - 'ḫ' => 'ḫ', - 'Ḭ' => 'Ḭ', - 'ḭ' => 'ḭ', - 'Ḯ' => 'Ḯ', - 'ḯ' => 'ḯ', - 'Ḱ' => 'Ḱ', - 'ḱ' => 'ḱ', - 'Ḳ' => 'Ḳ', - 'ḳ' => 'ḳ', - 'Ḵ' => 'Ḵ', - 'ḵ' => 'ḵ', - 'Ḷ' => 'Ḷ', - 'ḷ' => 'ḷ', - 'Ḹ' => 'Ḹ', - 'ḹ' => 'ḹ', - 'Ḻ' => 'Ḻ', - 'ḻ' => 'ḻ', - 'Ḽ' => 'Ḽ', - 'ḽ' => 'ḽ', - 'Ḿ' => 'Ḿ', - 'ḿ' => 'ḿ', - 'Ṁ' => 'Ṁ', - 'ṁ' => 'ṁ', - 'Ṃ' => 'Ṃ', - 'ṃ' => 'ṃ', - 'Ṅ' => 'Ṅ', - 'ṅ' => 'ṅ', - 'Ṇ' => 'Ṇ', - 'ṇ' => 'ṇ', - 'Ṉ' => 'Ṉ', - 'ṉ' => 'ṉ', - 'Ṋ' => 'Ṋ', - 'ṋ' => 'ṋ', - 'Ṍ' => 'Ṍ', - 'ṍ' => 'ṍ', - 'Ṏ' => 'Ṏ', - 'ṏ' => 'ṏ', - 'Ṑ' => 'Ṑ', - 'ṑ' => 'ṑ', - 'Ṓ' => 'Ṓ', - 'ṓ' => 'ṓ', - 'Ṕ' => 'Ṕ', - 'ṕ' => 'ṕ', - 'Ṗ' => 'Ṗ', - 'ṗ' => 'ṗ', - 'Ṙ' => 'Ṙ', - 'ṙ' => 'ṙ', - 'Ṛ' => 'Ṛ', - 'ṛ' => 'ṛ', - 'Ṝ' => 'Ṝ', - 'ṝ' => 'ṝ', - 'Ṟ' => 'Ṟ', - 'ṟ' => 'ṟ', - 'Ṡ' => 'Ṡ', - 'ṡ' => 'ṡ', - 'Ṣ' => 'Ṣ', - 'ṣ' => 'ṣ', - 'Ṥ' => 'Ṥ', - 'ṥ' => 'ṥ', - 'Ṧ' => 'Ṧ', - 'ṧ' => 'ṧ', - 'Ṩ' => 'Ṩ', - 'ṩ' => 'ṩ', - 'Ṫ' => 'Ṫ', - 'ṫ' => 'ṫ', - 'Ṭ' => 'Ṭ', - 'ṭ' => 'ṭ', - 'Ṯ' => 'Ṯ', - 'ṯ' => 'ṯ', - 'Ṱ' => 'Ṱ', - 'ṱ' => 'ṱ', - 'Ṳ' => 'Ṳ', - 'ṳ' => 'ṳ', - 'Ṵ' => 'Ṵ', - 'ṵ' => 'ṵ', - 'Ṷ' => 'Ṷ', - 'ṷ' => 'ṷ', - 'Ṹ' => 'Ṹ', - 'ṹ' => 'ṹ', - 'Ṻ' => 'Ṻ', - 'ṻ' => 'ṻ', - 'Ṽ' => 'Ṽ', - 'ṽ' => 'ṽ', - 'Ṿ' => 'Ṿ', - 'ṿ' => 'ṿ', - 'Ẁ' => 'Ẁ', - 'ẁ' => 'ẁ', - 'Ẃ' => 'Ẃ', - 'ẃ' => 'ẃ', - 'Ẅ' => 'Ẅ', - 'ẅ' => 'ẅ', - 'Ẇ' => 'Ẇ', - 'ẇ' => 'ẇ', - 'Ẉ' => 'Ẉ', - 'ẉ' => 'ẉ', - 'Ẋ' => 'Ẋ', - 'ẋ' => 'ẋ', - 'Ẍ' => 'Ẍ', - 'ẍ' => 'ẍ', - 'Ẏ' => 'Ẏ', - 'ẏ' => 'ẏ', - 'Ẑ' => 'Ẑ', - 'ẑ' => 'ẑ', - 'Ẓ' => 'Ẓ', - 'ẓ' => 'ẓ', - 'Ẕ' => 'Ẕ', - 'ẕ' => 'ẕ', - 'ẖ' => 'ẖ', - 'ẗ' => 'ẗ', - 'ẘ' => 'ẘ', - 'ẙ' => 'ẙ', - 'ẛ' => 'ẛ', - 'Ạ' => 'Ạ', - 'ạ' => 'ạ', - 'Ả' => 'Ả', - 'ả' => 'ả', - 'Ấ' => 'Ấ', - 'ấ' => 'ấ', - 'Ầ' => 'Ầ', - 'ầ' => 'ầ', - 'Ẩ' => 'Ẩ', - 'ẩ' => 'ẩ', - 'Ẫ' => 'Ẫ', - 'ẫ' => 'ẫ', - 'Ậ' => 'Ậ', - 'ậ' => 'ậ', - 'Ắ' => 'Ắ', - 'ắ' => 'ắ', - 'Ằ' => 'Ằ', - 'ằ' => 'ằ', - 'Ẳ' => 'Ẳ', - 'ẳ' => 'ẳ', - 'Ẵ' => 'Ẵ', - 'ẵ' => 'ẵ', - 'Ặ' => 'Ặ', - 'ặ' => 'ặ', - 'Ẹ' => 'Ẹ', - 'ẹ' => 'ẹ', - 'Ẻ' => 'Ẻ', - 'ẻ' => 'ẻ', - 'Ẽ' => 'Ẽ', - 'ẽ' => 'ẽ', - 'Ế' => 'Ế', - 'ế' => 'ế', - 'Ề' => 'Ề', - 'ề' => 'ề', - 'Ể' => 'Ể', - 'ể' => 'ể', - 'Ễ' => 'Ễ', - 'ễ' => 'ễ', - 'Ệ' => 'Ệ', - 'ệ' => 'ệ', - 'Ỉ' => 'Ỉ', - 'ỉ' => 'ỉ', - 'Ị' => 'Ị', - 'ị' => 'ị', - 'Ọ' => 'Ọ', - 'ọ' => 'ọ', - 'Ỏ' => 'Ỏ', - 'ỏ' => 'ỏ', - 'Ố' => 'Ố', - 'ố' => 'ố', - 'Ồ' => 'Ồ', - 'ồ' => 'ồ', - 'Ổ' => 'Ổ', - 'ổ' => 'ổ', - 'Ỗ' => 'Ỗ', - 'ỗ' => 'ỗ', - 'Ộ' => 'Ộ', - 'ộ' => 'ộ', - 'Ớ' => 'Ớ', - 'ớ' => 'ớ', - 'Ờ' => 'Ờ', - 'ờ' => 'ờ', - 'Ở' => 'Ở', - 'ở' => 'ở', - 'Ỡ' => 'Ỡ', - 'ỡ' => 'ỡ', - 'Ợ' => 'Ợ', - 'ợ' => 'ợ', - 'Ụ' => 'Ụ', - 'ụ' => 'ụ', - 'Ủ' => 'Ủ', - 'ủ' => 'ủ', - 'Ứ' => 'Ứ', - 'ứ' => 'ứ', - 'Ừ' => 'Ừ', - 'ừ' => 'ừ', - 'Ử' => 'Ử', - 'ử' => 'ử', - 'Ữ' => 'Ữ', - 'ữ' => 'ữ', - 'Ự' => 'Ự', - 'ự' => 'ự', - 'Ỳ' => 'Ỳ', - 'ỳ' => 'ỳ', - 'Ỵ' => 'Ỵ', - 'ỵ' => 'ỵ', - 'Ỷ' => 'Ỷ', - 'ỷ' => 'ỷ', - 'Ỹ' => 'Ỹ', - 'ỹ' => 'ỹ', - 'ἀ' => 'ἀ', - 'ἁ' => 'ἁ', - 'ἂ' => 'ἂ', - 'ἃ' => 'ἃ', - 'ἄ' => 'ἄ', - 'ἅ' => 'ἅ', - 'ἆ' => 'ἆ', - 'ἇ' => 'ἇ', - 'Ἀ' => 'Ἀ', - 'Ἁ' => 'Ἁ', - 'Ἂ' => 'Ἂ', - 'Ἃ' => 'Ἃ', - 'Ἄ' => 'Ἄ', - 'Ἅ' => 'Ἅ', - 'Ἆ' => 'Ἆ', - 'Ἇ' => 'Ἇ', - 'ἐ' => 'ἐ', - 'ἑ' => 'ἑ', - 'ἒ' => 'ἒ', - 'ἓ' => 'ἓ', - 'ἔ' => 'ἔ', - 'ἕ' => 'ἕ', - 'Ἐ' => 'Ἐ', - 'Ἑ' => 'Ἑ', - 'Ἒ' => 'Ἒ', - 'Ἓ' => 'Ἓ', - 'Ἔ' => 'Ἔ', - 'Ἕ' => 'Ἕ', - 'ἠ' => 'ἠ', - 'ἡ' => 'ἡ', - 'ἢ' => 'ἢ', - 'ἣ' => 'ἣ', - 'ἤ' => 'ἤ', - 'ἥ' => 'ἥ', - 'ἦ' => 'ἦ', - 'ἧ' => 'ἧ', - 'Ἠ' => 'Ἠ', - 'Ἡ' => 'Ἡ', - 'Ἢ' => 'Ἢ', - 'Ἣ' => 'Ἣ', - 'Ἤ' => 'Ἤ', - 'Ἥ' => 'Ἥ', - 'Ἦ' => 'Ἦ', - 'Ἧ' => 'Ἧ', - 'ἰ' => 'ἰ', - 'ἱ' => 'ἱ', - 'ἲ' => 'ἲ', - 'ἳ' => 'ἳ', - 'ἴ' => 'ἴ', - 'ἵ' => 'ἵ', - 'ἶ' => 'ἶ', - 'ἷ' => 'ἷ', - 'Ἰ' => 'Ἰ', - 'Ἱ' => 'Ἱ', - 'Ἲ' => 'Ἲ', - 'Ἳ' => 'Ἳ', - 'Ἴ' => 'Ἴ', - 'Ἵ' => 'Ἵ', - 'Ἶ' => 'Ἶ', - 'Ἷ' => 'Ἷ', - 'ὀ' => 'ὀ', - 'ὁ' => 'ὁ', - 'ὂ' => 'ὂ', - 'ὃ' => 'ὃ', - 'ὄ' => 'ὄ', - 'ὅ' => 'ὅ', - 'Ὀ' => 'Ὀ', - 'Ὁ' => 'Ὁ', - 'Ὂ' => 'Ὂ', - 'Ὃ' => 'Ὃ', - 'Ὄ' => 'Ὄ', - 'Ὅ' => 'Ὅ', - 'ὐ' => 'ὐ', - 'ὑ' => 'ὑ', - 'ὒ' => 'ὒ', - 'ὓ' => 'ὓ', - 'ὔ' => 'ὔ', - 'ὕ' => 'ὕ', - 'ὖ' => 'ὖ', - 'ὗ' => 'ὗ', - 'Ὑ' => 'Ὑ', - 'Ὓ' => 'Ὓ', - 'Ὕ' => 'Ὕ', - 'Ὗ' => 'Ὗ', - 'ὠ' => 'ὠ', - 'ὡ' => 'ὡ', - 'ὢ' => 'ὢ', - 'ὣ' => 'ὣ', - 'ὤ' => 'ὤ', - 'ὥ' => 'ὥ', - 'ὦ' => 'ὦ', - 'ὧ' => 'ὧ', - 'Ὠ' => 'Ὠ', - 'Ὡ' => 'Ὡ', - 'Ὢ' => 'Ὢ', - 'Ὣ' => 'Ὣ', - 'Ὤ' => 'Ὤ', - 'Ὥ' => 'Ὥ', - 'Ὦ' => 'Ὦ', - 'Ὧ' => 'Ὧ', - 'ὰ' => 'ὰ', - 'ά' => 'ά', - 'ὲ' => 'ὲ', - 'έ' => 'έ', - 'ὴ' => 'ὴ', - 'ή' => 'ή', - 'ὶ' => 'ὶ', - 'ί' => 'ί', - 'ὸ' => 'ὸ', - 'ό' => 'ό', - 'ὺ' => 'ὺ', - 'ύ' => 'ύ', - 'ὼ' => 'ὼ', - 'ώ' => 'ώ', - 'ᾀ' => 'ᾀ', - 'ᾁ' => 'ᾁ', - 'ᾂ' => 'ᾂ', - 'ᾃ' => 'ᾃ', - 'ᾄ' => 'ᾄ', - 'ᾅ' => 'ᾅ', - 'ᾆ' => 'ᾆ', - 'ᾇ' => 'ᾇ', - 'ᾈ' => 'ᾈ', - 'ᾉ' => 'ᾉ', - 'ᾊ' => 'ᾊ', - 'ᾋ' => 'ᾋ', - 'ᾌ' => 'ᾌ', - 'ᾍ' => 'ᾍ', - 'ᾎ' => 'ᾎ', - 'ᾏ' => 'ᾏ', - 'ᾐ' => 'ᾐ', - 'ᾑ' => 'ᾑ', - 'ᾒ' => 'ᾒ', - 'ᾓ' => 'ᾓ', - 'ᾔ' => 'ᾔ', - 'ᾕ' => 'ᾕ', - 'ᾖ' => 'ᾖ', - 'ᾗ' => 'ᾗ', - 'ᾘ' => 'ᾘ', - 'ᾙ' => 'ᾙ', - 'ᾚ' => 'ᾚ', - 'ᾛ' => 'ᾛ', - 'ᾜ' => 'ᾜ', - 'ᾝ' => 'ᾝ', - 'ᾞ' => 'ᾞ', - 'ᾟ' => 'ᾟ', - 'ᾠ' => 'ᾠ', - 'ᾡ' => 'ᾡ', - 'ᾢ' => 'ᾢ', - 'ᾣ' => 'ᾣ', - 'ᾤ' => 'ᾤ', - 'ᾥ' => 'ᾥ', - 'ᾦ' => 'ᾦ', - 'ᾧ' => 'ᾧ', - 'ᾨ' => 'ᾨ', - 'ᾩ' => 'ᾩ', - 'ᾪ' => 'ᾪ', - 'ᾫ' => 'ᾫ', - 'ᾬ' => 'ᾬ', - 'ᾭ' => 'ᾭ', - 'ᾮ' => 'ᾮ', - 'ᾯ' => 'ᾯ', - 'ᾰ' => 'ᾰ', - 'ᾱ' => 'ᾱ', - 'ᾲ' => 'ᾲ', - 'ᾳ' => 'ᾳ', - 'ᾴ' => 'ᾴ', - 'ᾶ' => 'ᾶ', - 'ᾷ' => 'ᾷ', - 'Ᾰ' => 'Ᾰ', - 'Ᾱ' => 'Ᾱ', - 'Ὰ' => 'Ὰ', - 'Ά' => 'Ά', - 'ᾼ' => 'ᾼ', - 'ι' => 'ι', - '῁' => '῁', - 'ῂ' => 'ῂ', - 'ῃ' => 'ῃ', - 'ῄ' => 'ῄ', - 'ῆ' => 'ῆ', - 'ῇ' => 'ῇ', - 'Ὲ' => 'Ὲ', - 'Έ' => 'Έ', - 'Ὴ' => 'Ὴ', - 'Ή' => 'Ή', - 'ῌ' => 'ῌ', - '῍' => '῍', - '῎' => '῎', - '῏' => '῏', - 'ῐ' => 'ῐ', - 'ῑ' => 'ῑ', - 'ῒ' => 'ῒ', - 'ΐ' => 'ΐ', - 'ῖ' => 'ῖ', - 'ῗ' => 'ῗ', - 'Ῐ' => 'Ῐ', - 'Ῑ' => 'Ῑ', - 'Ὶ' => 'Ὶ', - 'Ί' => 'Ί', - '῝' => '῝', - '῞' => '῞', - '῟' => '῟', - 'ῠ' => 'ῠ', - 'ῡ' => 'ῡ', - 'ῢ' => 'ῢ', - 'ΰ' => 'ΰ', - 'ῤ' => 'ῤ', - 'ῥ' => 'ῥ', - 'ῦ' => 'ῦ', - 'ῧ' => 'ῧ', - 'Ῠ' => 'Ῠ', - 'Ῡ' => 'Ῡ', - 'Ὺ' => 'Ὺ', - 'Ύ' => 'Ύ', - 'Ῥ' => 'Ῥ', - '῭' => '῭', - '΅' => '΅', - '`' => '`', - 'ῲ' => 'ῲ', - 'ῳ' => 'ῳ', - 'ῴ' => 'ῴ', - 'ῶ' => 'ῶ', - 'ῷ' => 'ῷ', - 'Ὸ' => 'Ὸ', - 'Ό' => 'Ό', - 'Ὼ' => 'Ὼ', - 'Ώ' => 'Ώ', - 'ῼ' => 'ῼ', - '´' => '´', - ' ' => ' ', - ' ' => ' ', - 'Ω' => 'Ω', - 'K' => 'K', - 'Å' => 'Å', - '↚' => '↚', - '↛' => '↛', - '↮' => '↮', - '⇍' => '⇍', - '⇎' => '⇎', - '⇏' => '⇏', - '∄' => '∄', - '∉' => '∉', - '∌' => '∌', - '∤' => '∤', - '∦' => '∦', - '≁' => '≁', - '≄' => '≄', - '≇' => '≇', - '≉' => '≉', - '≠' => '≠', - '≢' => '≢', - '≭' => '≭', - '≮' => '≮', - '≯' => '≯', - '≰' => '≰', - '≱' => '≱', - '≴' => '≴', - '≵' => '≵', - '≸' => '≸', - '≹' => '≹', - '⊀' => '⊀', - '⊁' => '⊁', - '⊄' => '⊄', - '⊅' => '⊅', - '⊈' => '⊈', - '⊉' => '⊉', - '⊬' => '⊬', - '⊭' => '⊭', - '⊮' => '⊮', - '⊯' => '⊯', - '⋠' => '⋠', - '⋡' => '⋡', - '⋢' => '⋢', - '⋣' => '⋣', - '⋪' => '⋪', - '⋫' => '⋫', - '⋬' => '⋬', - '⋭' => '⋭', - '〈' => '〈', - '〉' => '〉', - '⫝̸' => '⫝̸', - 'が' => 'が', - 'ぎ' => 'ぎ', - 'ぐ' => 'ぐ', - 'げ' => 'げ', - 'ご' => 'ご', - 'ざ' => 'ざ', - 'じ' => 'じ', - 'ず' => 'ず', - 'ぜ' => 'ぜ', - 'ぞ' => 'ぞ', - 'だ' => 'だ', - 'ぢ' => 'ぢ', - 'づ' => 'づ', - 'で' => 'で', - 'ど' => 'ど', - 'ば' => 'ば', - 'ぱ' => 'ぱ', - 'び' => 'び', - 'ぴ' => 'ぴ', - 'ぶ' => 'ぶ', - 'ぷ' => 'ぷ', - 'べ' => 'べ', - 'ぺ' => 'ぺ', - 'ぼ' => 'ぼ', - 'ぽ' => 'ぽ', - 'ゔ' => 'ゔ', - 'ゞ' => 'ゞ', - 'ガ' => 'ガ', - 'ギ' => 'ギ', - 'グ' => 'グ', - 'ゲ' => 'ゲ', - 'ゴ' => 'ゴ', - 'ザ' => 'ザ', - 'ジ' => 'ジ', - 'ズ' => 'ズ', - 'ゼ' => 'ゼ', - 'ゾ' => 'ゾ', - 'ダ' => 'ダ', - 'ヂ' => 'ヂ', - 'ヅ' => 'ヅ', - 'デ' => 'デ', - 'ド' => 'ド', - 'バ' => 'バ', - 'パ' => 'パ', - 'ビ' => 'ビ', - 'ピ' => 'ピ', - 'ブ' => 'ブ', - 'プ' => 'プ', - 'ベ' => 'ベ', - 'ペ' => 'ペ', - 'ボ' => 'ボ', - 'ポ' => 'ポ', - 'ヴ' => 'ヴ', - 'ヷ' => 'ヷ', - 'ヸ' => 'ヸ', - 'ヹ' => 'ヹ', - 'ヺ' => 'ヺ', - 'ヾ' => 'ヾ', - '豈' => '豈', - '更' => '更', - '車' => '車', - '賈' => '賈', - '滑' => '滑', - '串' => '串', - '句' => '句', - '龜' => '龜', - '龜' => '龜', - '契' => '契', - '金' => '金', - '喇' => '喇', - '奈' => '奈', - '懶' => '懶', - '癩' => '癩', - '羅' => '羅', - '蘿' => '蘿', - '螺' => '螺', - '裸' => '裸', - '邏' => '邏', - '樂' => '樂', - '洛' => '洛', - '烙' => '烙', - '珞' => '珞', - '落' => '落', - '酪' => '酪', - '駱' => '駱', - '亂' => '亂', - '卵' => '卵', - '欄' => '欄', - '爛' => '爛', - '蘭' => '蘭', - '鸞' => '鸞', - '嵐' => '嵐', - '濫' => '濫', - '藍' => '藍', - '襤' => '襤', - '拉' => '拉', - '臘' => '臘', - '蠟' => '蠟', - '廊' => '廊', - '朗' => '朗', - '浪' => '浪', - '狼' => '狼', - '郎' => '郎', - '來' => '來', - '冷' => '冷', - '勞' => '勞', - '擄' => '擄', - '櫓' => '櫓', - '爐' => '爐', - '盧' => '盧', - '老' => '老', - '蘆' => '蘆', - '虜' => '虜', - '路' => '路', - '露' => '露', - '魯' => '魯', - '鷺' => '鷺', - '碌' => '碌', - '祿' => '祿', - '綠' => '綠', - '菉' => '菉', - '錄' => '錄', - '鹿' => '鹿', - '論' => '論', - '壟' => '壟', - '弄' => '弄', - '籠' => '籠', - '聾' => '聾', - '牢' => '牢', - '磊' => '磊', - '賂' => '賂', - '雷' => '雷', - '壘' => '壘', - '屢' => '屢', - '樓' => '樓', - '淚' => '淚', - '漏' => '漏', - '累' => '累', - '縷' => '縷', - '陋' => '陋', - '勒' => '勒', - '肋' => '肋', - '凜' => '凜', - '凌' => '凌', - '稜' => '稜', - '綾' => '綾', - '菱' => '菱', - '陵' => '陵', - '讀' => '讀', - '拏' => '拏', - '樂' => '樂', - '諾' => '諾', - '丹' => '丹', - '寧' => '寧', - '怒' => '怒', - '率' => '率', - '異' => '異', - '北' => '北', - '磻' => '磻', - '便' => '便', - '復' => '復', - '不' => '不', - '泌' => '泌', - '數' => '數', - '索' => '索', - '參' => '參', - '塞' => '塞', - '省' => '省', - '葉' => '葉', - '說' => '說', - '殺' => '殺', - '辰' => '辰', - '沈' => '沈', - '拾' => '拾', - '若' => '若', - '掠' => '掠', - '略' => '略', - '亮' => '亮', - '兩' => '兩', - '凉' => '凉', - '梁' => '梁', - '糧' => '糧', - '良' => '良', - '諒' => '諒', - '量' => '量', - '勵' => '勵', - '呂' => '呂', - '女' => '女', - '廬' => '廬', - '旅' => '旅', - '濾' => '濾', - '礪' => '礪', - '閭' => '閭', - '驪' => '驪', - '麗' => '麗', - '黎' => '黎', - '力' => '力', - '曆' => '曆', - '歷' => '歷', - '轢' => '轢', - '年' => '年', - '憐' => '憐', - '戀' => '戀', - '撚' => '撚', - '漣' => '漣', - '煉' => '煉', - '璉' => '璉', - '秊' => '秊', - '練' => '練', - '聯' => '聯', - '輦' => '輦', - '蓮' => '蓮', - '連' => '連', - '鍊' => '鍊', - '列' => '列', - '劣' => '劣', - '咽' => '咽', - '烈' => '烈', - '裂' => '裂', - '說' => '說', - '廉' => '廉', - '念' => '念', - '捻' => '捻', - '殮' => '殮', - '簾' => '簾', - '獵' => '獵', - '令' => '令', - '囹' => '囹', - '寧' => '寧', - '嶺' => '嶺', - '怜' => '怜', - '玲' => '玲', - '瑩' => '瑩', - '羚' => '羚', - '聆' => '聆', - '鈴' => '鈴', - '零' => '零', - '靈' => '靈', - '領' => '領', - '例' => '例', - '禮' => '禮', - '醴' => '醴', - '隸' => '隸', - '惡' => '惡', - '了' => '了', - '僚' => '僚', - '寮' => '寮', - '尿' => '尿', - '料' => '料', - '樂' => '樂', - '燎' => '燎', - '療' => '療', - '蓼' => '蓼', - '遼' => '遼', - '龍' => '龍', - '暈' => '暈', - '阮' => '阮', - '劉' => '劉', - '杻' => '杻', - '柳' => '柳', - '流' => '流', - '溜' => '溜', - '琉' => '琉', - '留' => '留', - '硫' => '硫', - '紐' => '紐', - '類' => '類', - '六' => '六', - '戮' => '戮', - '陸' => '陸', - '倫' => '倫', - '崙' => '崙', - '淪' => '淪', - '輪' => '輪', - '律' => '律', - '慄' => '慄', - '栗' => '栗', - '率' => '率', - '隆' => '隆', - '利' => '利', - '吏' => '吏', - '履' => '履', - '易' => '易', - '李' => '李', - '梨' => '梨', - '泥' => '泥', - '理' => '理', - '痢' => '痢', - '罹' => '罹', - '裏' => '裏', - '裡' => '裡', - '里' => '里', - '離' => '離', - '匿' => '匿', - '溺' => '溺', - '吝' => '吝', - '燐' => '燐', - '璘' => '璘', - '藺' => '藺', - '隣' => '隣', - '鱗' => '鱗', - '麟' => '麟', - '林' => '林', - '淋' => '淋', - '臨' => '臨', - '立' => '立', - '笠' => '笠', - '粒' => '粒', - '狀' => '狀', - '炙' => '炙', - '識' => '識', - '什' => '什', - '茶' => '茶', - '刺' => '刺', - '切' => '切', - '度' => '度', - '拓' => '拓', - '糖' => '糖', - '宅' => '宅', - '洞' => '洞', - '暴' => '暴', - '輻' => '輻', - '行' => '行', - '降' => '降', - '見' => '見', - '廓' => '廓', - '兀' => '兀', - '嗀' => '嗀', - '塚' => '塚', - '晴' => '晴', - '凞' => '凞', - '猪' => '猪', - '益' => '益', - '礼' => '礼', - '神' => '神', - '祥' => '祥', - '福' => '福', - '靖' => '靖', - '精' => '精', - '羽' => '羽', - '蘒' => '蘒', - '諸' => '諸', - '逸' => '逸', - '都' => '都', - '飯' => '飯', - '飼' => '飼', - '館' => '館', - '鶴' => '鶴', - '郞' => '郞', - '隷' => '隷', - '侮' => '侮', - '僧' => '僧', - '免' => '免', - '勉' => '勉', - '勤' => '勤', - '卑' => '卑', - '喝' => '喝', - '嘆' => '嘆', - '器' => '器', - '塀' => '塀', - '墨' => '墨', - '層' => '層', - '屮' => '屮', - '悔' => '悔', - '慨' => '慨', - '憎' => '憎', - '懲' => '懲', - '敏' => '敏', - '既' => '既', - '暑' => '暑', - '梅' => '梅', - '海' => '海', - '渚' => '渚', - '漢' => '漢', - '煮' => '煮', - '爫' => '爫', - '琢' => '琢', - '碑' => '碑', - '社' => '社', - '祉' => '祉', - '祈' => '祈', - '祐' => '祐', - '祖' => '祖', - '祝' => '祝', - '禍' => '禍', - '禎' => '禎', - '穀' => '穀', - '突' => '突', - '節' => '節', - '練' => '練', - '縉' => '縉', - '繁' => '繁', - '署' => '署', - '者' => '者', - '臭' => '臭', - '艹' => '艹', - '艹' => '艹', - '著' => '著', - '褐' => '褐', - '視' => '視', - '謁' => '謁', - '謹' => '謹', - '賓' => '賓', - '贈' => '贈', - '辶' => '辶', - '逸' => '逸', - '難' => '難', - '響' => '響', - '頻' => '頻', - '恵' => '恵', - '𤋮' => '𤋮', - '舘' => '舘', - '並' => '並', - '况' => '况', - '全' => '全', - '侀' => '侀', - '充' => '充', - '冀' => '冀', - '勇' => '勇', - '勺' => '勺', - '喝' => '喝', - '啕' => '啕', - '喙' => '喙', - '嗢' => '嗢', - '塚' => '塚', - '墳' => '墳', - '奄' => '奄', - '奔' => '奔', - '婢' => '婢', - '嬨' => '嬨', - '廒' => '廒', - '廙' => '廙', - '彩' => '彩', - '徭' => '徭', - '惘' => '惘', - '慎' => '慎', - '愈' => '愈', - '憎' => '憎', - '慠' => '慠', - '懲' => '懲', - '戴' => '戴', - '揄' => '揄', - '搜' => '搜', - '摒' => '摒', - '敖' => '敖', - '晴' => '晴', - '朗' => '朗', - '望' => '望', - '杖' => '杖', - '歹' => '歹', - '殺' => '殺', - '流' => '流', - '滛' => '滛', - '滋' => '滋', - '漢' => '漢', - '瀞' => '瀞', - '煮' => '煮', - '瞧' => '瞧', - '爵' => '爵', - '犯' => '犯', - '猪' => '猪', - '瑱' => '瑱', - '甆' => '甆', - '画' => '画', - '瘝' => '瘝', - '瘟' => '瘟', - '益' => '益', - '盛' => '盛', - '直' => '直', - '睊' => '睊', - '着' => '着', - '磌' => '磌', - '窱' => '窱', - '節' => '節', - '类' => '类', - '絛' => '絛', - '練' => '練', - '缾' => '缾', - '者' => '者', - '荒' => '荒', - '華' => '華', - '蝹' => '蝹', - '襁' => '襁', - '覆' => '覆', - '視' => '視', - '調' => '調', - '諸' => '諸', - '請' => '請', - '謁' => '謁', - '諾' => '諾', - '諭' => '諭', - '謹' => '謹', - '變' => '變', - '贈' => '贈', - '輸' => '輸', - '遲' => '遲', - '醙' => '醙', - '鉶' => '鉶', - '陼' => '陼', - '難' => '難', - '靖' => '靖', - '韛' => '韛', - '響' => '響', - '頋' => '頋', - '頻' => '頻', - '鬒' => '鬒', - '龜' => '龜', - '𢡊' => '𢡊', - '𢡄' => '𢡄', - '𣏕' => '𣏕', - '㮝' => '㮝', - '䀘' => '䀘', - '䀹' => '䀹', - '𥉉' => '𥉉', - '𥳐' => '𥳐', - '𧻓' => '𧻓', - '齃' => '齃', - '龎' => '龎', - 'יִ' => 'יִ', - 'ײַ' => 'ײַ', - 'שׁ' => 'שׁ', - 'שׂ' => 'שׂ', - 'שּׁ' => 'שּׁ', - 'שּׂ' => 'שּׂ', - 'אַ' => 'אַ', - 'אָ' => 'אָ', - 'אּ' => 'אּ', - 'בּ' => 'בּ', - 'גּ' => 'גּ', - 'דּ' => 'דּ', - 'הּ' => 'הּ', - 'וּ' => 'וּ', - 'זּ' => 'זּ', - 'טּ' => 'טּ', - 'יּ' => 'יּ', - 'ךּ' => 'ךּ', - 'כּ' => 'כּ', - 'לּ' => 'לּ', - 'מּ' => 'מּ', - 'נּ' => 'נּ', - 'סּ' => 'סּ', - 'ףּ' => 'ףּ', - 'פּ' => 'פּ', - 'צּ' => 'צּ', - 'קּ' => 'קּ', - 'רּ' => 'רּ', - 'שּ' => 'שּ', - 'תּ' => 'תּ', - 'וֹ' => 'וֹ', - 'בֿ' => 'בֿ', - 'כֿ' => 'כֿ', - 'פֿ' => 'פֿ', - '𑂚' => '𑂚', - '𑂜' => '𑂜', - '𑂫' => '𑂫', - '𑄮' => '𑄮', - '𑄯' => '𑄯', - '𑍋' => '𑍋', - '𑍌' => '𑍌', - '𑒻' => '𑒻', - '𑒼' => '𑒼', - '𑒾' => '𑒾', - '𑖺' => '𑖺', - '𑖻' => '𑖻', - '𑤸' => '𑤸', - '𝅗𝅥' => '𝅗𝅥', - '𝅘𝅥' => '𝅘𝅥', - '𝅘𝅥𝅮' => '𝅘𝅥𝅮', - '𝅘𝅥𝅯' => '𝅘𝅥𝅯', - '𝅘𝅥𝅰' => '𝅘𝅥𝅰', - '𝅘𝅥𝅱' => '𝅘𝅥𝅱', - '𝅘𝅥𝅲' => '𝅘𝅥𝅲', - '𝆹𝅥' => '𝆹𝅥', - '𝆺𝅥' => '𝆺𝅥', - '𝆹𝅥𝅮' => '𝆹𝅥𝅮', - '𝆺𝅥𝅮' => '𝆺𝅥𝅮', - '𝆹𝅥𝅯' => '𝆹𝅥𝅯', - '𝆺𝅥𝅯' => '𝆺𝅥𝅯', - '丽' => '丽', - '丸' => '丸', - '乁' => '乁', - '𠄢' => '𠄢', - '你' => '你', - '侮' => '侮', - '侻' => '侻', - '倂' => '倂', - '偺' => '偺', - '備' => '備', - '僧' => '僧', - '像' => '像', - '㒞' => '㒞', - '𠘺' => '𠘺', - '免' => '免', - '兔' => '兔', - '兤' => '兤', - '具' => '具', - '𠔜' => '𠔜', - '㒹' => '㒹', - '內' => '內', - '再' => '再', - '𠕋' => '𠕋', - '冗' => '冗', - '冤' => '冤', - '仌' => '仌', - '冬' => '冬', - '况' => '况', - '𩇟' => '𩇟', - '凵' => '凵', - '刃' => '刃', - '㓟' => '㓟', - '刻' => '刻', - '剆' => '剆', - '割' => '割', - '剷' => '剷', - '㔕' => '㔕', - '勇' => '勇', - '勉' => '勉', - '勤' => '勤', - '勺' => '勺', - '包' => '包', - '匆' => '匆', - '北' => '北', - '卉' => '卉', - '卑' => '卑', - '博' => '博', - '即' => '即', - '卽' => '卽', - '卿' => '卿', - '卿' => '卿', - '卿' => '卿', - '𠨬' => '𠨬', - '灰' => '灰', - '及' => '及', - '叟' => '叟', - '𠭣' => '𠭣', - '叫' => '叫', - '叱' => '叱', - '吆' => '吆', - '咞' => '咞', - '吸' => '吸', - '呈' => '呈', - '周' => '周', - '咢' => '咢', - '哶' => '哶', - '唐' => '唐', - '啓' => '啓', - '啣' => '啣', - '善' => '善', - '善' => '善', - '喙' => '喙', - '喫' => '喫', - '喳' => '喳', - '嗂' => '嗂', - '圖' => '圖', - '嘆' => '嘆', - '圗' => '圗', - '噑' => '噑', - '噴' => '噴', - '切' => '切', - '壮' => '壮', - '城' => '城', - '埴' => '埴', - '堍' => '堍', - '型' => '型', - '堲' => '堲', - '報' => '報', - '墬' => '墬', - '𡓤' => '𡓤', - '売' => '売', - '壷' => '壷', - '夆' => '夆', - '多' => '多', - '夢' => '夢', - '奢' => '奢', - '𡚨' => '𡚨', - '𡛪' => '𡛪', - '姬' => '姬', - '娛' => '娛', - '娧' => '娧', - '姘' => '姘', - '婦' => '婦', - '㛮' => '㛮', - '㛼' => '㛼', - '嬈' => '嬈', - '嬾' => '嬾', - '嬾' => '嬾', - '𡧈' => '𡧈', - '寃' => '寃', - '寘' => '寘', - '寧' => '寧', - '寳' => '寳', - '𡬘' => '𡬘', - '寿' => '寿', - '将' => '将', - '当' => '当', - '尢' => '尢', - '㞁' => '㞁', - '屠' => '屠', - '屮' => '屮', - '峀' => '峀', - '岍' => '岍', - '𡷤' => '𡷤', - '嵃' => '嵃', - '𡷦' => '𡷦', - '嵮' => '嵮', - '嵫' => '嵫', - '嵼' => '嵼', - '巡' => '巡', - '巢' => '巢', - '㠯' => '㠯', - '巽' => '巽', - '帨' => '帨', - '帽' => '帽', - '幩' => '幩', - '㡢' => '㡢', - '𢆃' => '𢆃', - '㡼' => '㡼', - '庰' => '庰', - '庳' => '庳', - '庶' => '庶', - '廊' => '廊', - '𪎒' => '𪎒', - '廾' => '廾', - '𢌱' => '𢌱', - '𢌱' => '𢌱', - '舁' => '舁', - '弢' => '弢', - '弢' => '弢', - '㣇' => '㣇', - '𣊸' => '𣊸', - '𦇚' => '𦇚', - '形' => '形', - '彫' => '彫', - '㣣' => '㣣', - '徚' => '徚', - '忍' => '忍', - '志' => '志', - '忹' => '忹', - '悁' => '悁', - '㤺' => '㤺', - '㤜' => '㤜', - '悔' => '悔', - '𢛔' => '𢛔', - '惇' => '惇', - '慈' => '慈', - '慌' => '慌', - '慎' => '慎', - '慌' => '慌', - '慺' => '慺', - '憎' => '憎', - '憲' => '憲', - '憤' => '憤', - '憯' => '憯', - '懞' => '懞', - '懲' => '懲', - '懶' => '懶', - '成' => '成', - '戛' => '戛', - '扝' => '扝', - '抱' => '抱', - '拔' => '拔', - '捐' => '捐', - '𢬌' => '𢬌', - '挽' => '挽', - '拼' => '拼', - '捨' => '捨', - '掃' => '掃', - '揤' => '揤', - '𢯱' => '𢯱', - '搢' => '搢', - '揅' => '揅', - '掩' => '掩', - '㨮' => '㨮', - '摩' => '摩', - '摾' => '摾', - '撝' => '撝', - '摷' => '摷', - '㩬' => '㩬', - '敏' => '敏', - '敬' => '敬', - '𣀊' => '𣀊', - '旣' => '旣', - '書' => '書', - '晉' => '晉', - '㬙' => '㬙', - '暑' => '暑', - '㬈' => '㬈', - '㫤' => '㫤', - '冒' => '冒', - '冕' => '冕', - '最' => '最', - '暜' => '暜', - '肭' => '肭', - '䏙' => '䏙', - '朗' => '朗', - '望' => '望', - '朡' => '朡', - '杞' => '杞', - '杓' => '杓', - '𣏃' => '𣏃', - '㭉' => '㭉', - '柺' => '柺', - '枅' => '枅', - '桒' => '桒', - '梅' => '梅', - '𣑭' => '𣑭', - '梎' => '梎', - '栟' => '栟', - '椔' => '椔', - '㮝' => '㮝', - '楂' => '楂', - '榣' => '榣', - '槪' => '槪', - '檨' => '檨', - '𣚣' => '𣚣', - '櫛' => '櫛', - '㰘' => '㰘', - '次' => '次', - '𣢧' => '𣢧', - '歔' => '歔', - '㱎' => '㱎', - '歲' => '歲', - '殟' => '殟', - '殺' => '殺', - '殻' => '殻', - '𣪍' => '𣪍', - '𡴋' => '𡴋', - '𣫺' => '𣫺', - '汎' => '汎', - '𣲼' => '𣲼', - '沿' => '沿', - '泍' => '泍', - '汧' => '汧', - '洖' => '洖', - '派' => '派', - '海' => '海', - '流' => '流', - '浩' => '浩', - '浸' => '浸', - '涅' => '涅', - '𣴞' => '𣴞', - '洴' => '洴', - '港' => '港', - '湮' => '湮', - '㴳' => '㴳', - '滋' => '滋', - '滇' => '滇', - '𣻑' => '𣻑', - '淹' => '淹', - '潮' => '潮', - '𣽞' => '𣽞', - '𣾎' => '𣾎', - '濆' => '濆', - '瀹' => '瀹', - '瀞' => '瀞', - '瀛' => '瀛', - '㶖' => '㶖', - '灊' => '灊', - '災' => '災', - '灷' => '灷', - '炭' => '炭', - '𠔥' => '𠔥', - '煅' => '煅', - '𤉣' => '𤉣', - '熜' => '熜', - '𤎫' => '𤎫', - '爨' => '爨', - '爵' => '爵', - '牐' => '牐', - '𤘈' => '𤘈', - '犀' => '犀', - '犕' => '犕', - '𤜵' => '𤜵', - '𤠔' => '𤠔', - '獺' => '獺', - '王' => '王', - '㺬' => '㺬', - '玥' => '玥', - '㺸' => '㺸', - '㺸' => '㺸', - '瑇' => '瑇', - '瑜' => '瑜', - '瑱' => '瑱', - '璅' => '璅', - '瓊' => '瓊', - '㼛' => '㼛', - '甤' => '甤', - '𤰶' => '𤰶', - '甾' => '甾', - '𤲒' => '𤲒', - '異' => '異', - '𢆟' => '𢆟', - '瘐' => '瘐', - '𤾡' => '𤾡', - '𤾸' => '𤾸', - '𥁄' => '𥁄', - '㿼' => '㿼', - '䀈' => '䀈', - '直' => '直', - '𥃳' => '𥃳', - '𥃲' => '𥃲', - '𥄙' => '𥄙', - '𥄳' => '𥄳', - '眞' => '眞', - '真' => '真', - '真' => '真', - '睊' => '睊', - '䀹' => '䀹', - '瞋' => '瞋', - '䁆' => '䁆', - '䂖' => '䂖', - '𥐝' => '𥐝', - '硎' => '硎', - '碌' => '碌', - '磌' => '磌', - '䃣' => '䃣', - '𥘦' => '𥘦', - '祖' => '祖', - '𥚚' => '𥚚', - '𥛅' => '𥛅', - '福' => '福', - '秫' => '秫', - '䄯' => '䄯', - '穀' => '穀', - '穊' => '穊', - '穏' => '穏', - '𥥼' => '𥥼', - '𥪧' => '𥪧', - '𥪧' => '𥪧', - '竮' => '竮', - '䈂' => '䈂', - '𥮫' => '𥮫', - '篆' => '篆', - '築' => '築', - '䈧' => '䈧', - '𥲀' => '𥲀', - '糒' => '糒', - '䊠' => '䊠', - '糨' => '糨', - '糣' => '糣', - '紀' => '紀', - '𥾆' => '𥾆', - '絣' => '絣', - '䌁' => '䌁', - '緇' => '緇', - '縂' => '縂', - '繅' => '繅', - '䌴' => '䌴', - '𦈨' => '𦈨', - '𦉇' => '𦉇', - '䍙' => '䍙', - '𦋙' => '𦋙', - '罺' => '罺', - '𦌾' => '𦌾', - '羕' => '羕', - '翺' => '翺', - '者' => '者', - '𦓚' => '𦓚', - '𦔣' => '𦔣', - '聠' => '聠', - '𦖨' => '𦖨', - '聰' => '聰', - '𣍟' => '𣍟', - '䏕' => '䏕', - '育' => '育', - '脃' => '脃', - '䐋' => '䐋', - '脾' => '脾', - '媵' => '媵', - '𦞧' => '𦞧', - '𦞵' => '𦞵', - '𣎓' => '𣎓', - '𣎜' => '𣎜', - '舁' => '舁', - '舄' => '舄', - '辞' => '辞', - '䑫' => '䑫', - '芑' => '芑', - '芋' => '芋', - '芝' => '芝', - '劳' => '劳', - '花' => '花', - '芳' => '芳', - '芽' => '芽', - '苦' => '苦', - '𦬼' => '𦬼', - '若' => '若', - '茝' => '茝', - '荣' => '荣', - '莭' => '莭', - '茣' => '茣', - '莽' => '莽', - '菧' => '菧', - '著' => '著', - '荓' => '荓', - '菊' => '菊', - '菌' => '菌', - '菜' => '菜', - '𦰶' => '𦰶', - '𦵫' => '𦵫', - '𦳕' => '𦳕', - '䔫' => '䔫', - '蓱' => '蓱', - '蓳' => '蓳', - '蔖' => '蔖', - '𧏊' => '𧏊', - '蕤' => '蕤', - '𦼬' => '𦼬', - '䕝' => '䕝', - '䕡' => '䕡', - '𦾱' => '𦾱', - '𧃒' => '𧃒', - '䕫' => '䕫', - '虐' => '虐', - '虜' => '虜', - '虧' => '虧', - '虩' => '虩', - '蚩' => '蚩', - '蚈' => '蚈', - '蜎' => '蜎', - '蛢' => '蛢', - '蝹' => '蝹', - '蜨' => '蜨', - '蝫' => '蝫', - '螆' => '螆', - '䗗' => '䗗', - '蟡' => '蟡', - '蠁' => '蠁', - '䗹' => '䗹', - '衠' => '衠', - '衣' => '衣', - '𧙧' => '𧙧', - '裗' => '裗', - '裞' => '裞', - '䘵' => '䘵', - '裺' => '裺', - '㒻' => '㒻', - '𧢮' => '𧢮', - '𧥦' => '𧥦', - '䚾' => '䚾', - '䛇' => '䛇', - '誠' => '誠', - '諭' => '諭', - '變' => '變', - '豕' => '豕', - '𧲨' => '𧲨', - '貫' => '貫', - '賁' => '賁', - '贛' => '贛', - '起' => '起', - '𧼯' => '𧼯', - '𠠄' => '𠠄', - '跋' => '跋', - '趼' => '趼', - '跰' => '跰', - '𠣞' => '𠣞', - '軔' => '軔', - '輸' => '輸', - '𨗒' => '𨗒', - '𨗭' => '𨗭', - '邔' => '邔', - '郱' => '郱', - '鄑' => '鄑', - '𨜮' => '𨜮', - '鄛' => '鄛', - '鈸' => '鈸', - '鋗' => '鋗', - '鋘' => '鋘', - '鉼' => '鉼', - '鏹' => '鏹', - '鐕' => '鐕', - '𨯺' => '𨯺', - '開' => '開', - '䦕' => '䦕', - '閷' => '閷', - '𨵷' => '𨵷', - '䧦' => '䧦', - '雃' => '雃', - '嶲' => '嶲', - '霣' => '霣', - '𩅅' => '𩅅', - '𩈚' => '𩈚', - '䩮' => '䩮', - '䩶' => '䩶', - '韠' => '韠', - '𩐊' => '𩐊', - '䪲' => '䪲', - '𩒖' => '𩒖', - '頋' => '頋', - '頋' => '頋', - '頩' => '頩', - '𩖶' => '𩖶', - '飢' => '飢', - '䬳' => '䬳', - '餩' => '餩', - '馧' => '馧', - '駂' => '駂', - '駾' => '駾', - '䯎' => '䯎', - '𩬰' => '𩬰', - '鬒' => '鬒', - '鱀' => '鱀', - '鳽' => '鳽', - '䳎' => '䳎', - '䳭' => '䳭', - '鵧' => '鵧', - '𪃎' => '𪃎', - '䳸' => '䳸', - '𪄅' => '𪄅', - '𪈎' => '𪈎', - '𪊑' => '𪊑', - '麻' => '麻', - '䵖' => '䵖', - '黹' => '黹', - '黾' => '黾', - '鼅' => '鼅', - '鼏' => '鼏', - '鼖' => '鼖', - '鼻' => '鼻', - '𪘀' => '𪘀', -); diff --git a/lib/symfony/polyfill-intl-normalizer/Resources/unidata/combiningClass.php b/lib/symfony/polyfill-intl-normalizer/Resources/unidata/combiningClass.php deleted file mode 100644 index ec90f36eb..000000000 --- a/lib/symfony/polyfill-intl-normalizer/Resources/unidata/combiningClass.php +++ /dev/null @@ -1,876 +0,0 @@ -<?php - -return array ( - '̀' => 230, - '́' => 230, - '̂' => 230, - '̃' => 230, - '̄' => 230, - '̅' => 230, - '̆' => 230, - '̇' => 230, - '̈' => 230, - '̉' => 230, - '̊' => 230, - '̋' => 230, - '̌' => 230, - '̍' => 230, - '̎' => 230, - '̏' => 230, - '̐' => 230, - '̑' => 230, - '̒' => 230, - '̓' => 230, - '̔' => 230, - '̕' => 232, - '̖' => 220, - '̗' => 220, - '̘' => 220, - '̙' => 220, - '̚' => 232, - '̛' => 216, - '̜' => 220, - '̝' => 220, - '̞' => 220, - '̟' => 220, - '̠' => 220, - '̡' => 202, - '̢' => 202, - '̣' => 220, - '̤' => 220, - '̥' => 220, - '̦' => 220, - '̧' => 202, - '̨' => 202, - '̩' => 220, - '̪' => 220, - '̫' => 220, - '̬' => 220, - '̭' => 220, - '̮' => 220, - '̯' => 220, - '̰' => 220, - '̱' => 220, - '̲' => 220, - '̳' => 220, - '̴' => 1, - '̵' => 1, - '̶' => 1, - '̷' => 1, - '̸' => 1, - '̹' => 220, - '̺' => 220, - '̻' => 220, - '̼' => 220, - '̽' => 230, - '̾' => 230, - '̿' => 230, - '̀' => 230, - '́' => 230, - '͂' => 230, - '̓' => 230, - '̈́' => 230, - 'ͅ' => 240, - '͆' => 230, - '͇' => 220, - '͈' => 220, - '͉' => 220, - '͊' => 230, - '͋' => 230, - '͌' => 230, - '͍' => 220, - '͎' => 220, - '͐' => 230, - '͑' => 230, - '͒' => 230, - '͓' => 220, - '͔' => 220, - '͕' => 220, - '͖' => 220, - '͗' => 230, - '͘' => 232, - '͙' => 220, - '͚' => 220, - '͛' => 230, - '͜' => 233, - '͝' => 234, - '͞' => 234, - '͟' => 233, - '͠' => 234, - '͡' => 234, - '͢' => 233, - 'ͣ' => 230, - 'ͤ' => 230, - 'ͥ' => 230, - 'ͦ' => 230, - 'ͧ' => 230, - 'ͨ' => 230, - 'ͩ' => 230, - 'ͪ' => 230, - 'ͫ' => 230, - 'ͬ' => 230, - 'ͭ' => 230, - 'ͮ' => 230, - 'ͯ' => 230, - '҃' => 230, - '҄' => 230, - '҅' => 230, - '҆' => 230, - '҇' => 230, - '֑' => 220, - '֒' => 230, - '֓' => 230, - '֔' => 230, - '֕' => 230, - '֖' => 220, - '֗' => 230, - '֘' => 230, - '֙' => 230, - '֚' => 222, - '֛' => 220, - '֜' => 230, - '֝' => 230, - '֞' => 230, - '֟' => 230, - '֠' => 230, - '֡' => 230, - '֢' => 220, - '֣' => 220, - '֤' => 220, - '֥' => 220, - '֦' => 220, - '֧' => 220, - '֨' => 230, - '֩' => 230, - '֪' => 220, - '֫' => 230, - '֬' => 230, - '֭' => 222, - '֮' => 228, - '֯' => 230, - 'ְ' => 10, - 'ֱ' => 11, - 'ֲ' => 12, - 'ֳ' => 13, - 'ִ' => 14, - 'ֵ' => 15, - 'ֶ' => 16, - 'ַ' => 17, - 'ָ' => 18, - 'ֹ' => 19, - 'ֺ' => 19, - 'ֻ' => 20, - 'ּ' => 21, - 'ֽ' => 22, - 'ֿ' => 23, - 'ׁ' => 24, - 'ׂ' => 25, - 'ׄ' => 230, - 'ׅ' => 220, - 'ׇ' => 18, - 'ؐ' => 230, - 'ؑ' => 230, - 'ؒ' => 230, - 'ؓ' => 230, - 'ؔ' => 230, - 'ؕ' => 230, - 'ؖ' => 230, - 'ؗ' => 230, - 'ؘ' => 30, - 'ؙ' => 31, - 'ؚ' => 32, - 'ً' => 27, - 'ٌ' => 28, - 'ٍ' => 29, - 'َ' => 30, - 'ُ' => 31, - 'ِ' => 32, - 'ّ' => 33, - 'ْ' => 34, - 'ٓ' => 230, - 'ٔ' => 230, - 'ٕ' => 220, - 'ٖ' => 220, - 'ٗ' => 230, - '٘' => 230, - 'ٙ' => 230, - 'ٚ' => 230, - 'ٛ' => 230, - 'ٜ' => 220, - 'ٝ' => 230, - 'ٞ' => 230, - 'ٟ' => 220, - 'ٰ' => 35, - 'ۖ' => 230, - 'ۗ' => 230, - 'ۘ' => 230, - 'ۙ' => 230, - 'ۚ' => 230, - 'ۛ' => 230, - 'ۜ' => 230, - '۟' => 230, - '۠' => 230, - 'ۡ' => 230, - 'ۢ' => 230, - 'ۣ' => 220, - 'ۤ' => 230, - 'ۧ' => 230, - 'ۨ' => 230, - '۪' => 220, - '۫' => 230, - '۬' => 230, - 'ۭ' => 220, - 'ܑ' => 36, - 'ܰ' => 230, - 'ܱ' => 220, - 'ܲ' => 230, - 'ܳ' => 230, - 'ܴ' => 220, - 'ܵ' => 230, - 'ܶ' => 230, - 'ܷ' => 220, - 'ܸ' => 220, - 'ܹ' => 220, - 'ܺ' => 230, - 'ܻ' => 220, - 'ܼ' => 220, - 'ܽ' => 230, - 'ܾ' => 220, - 'ܿ' => 230, - '݀' => 230, - '݁' => 230, - '݂' => 220, - '݃' => 230, - '݄' => 220, - '݅' => 230, - '݆' => 220, - '݇' => 230, - '݈' => 220, - '݉' => 230, - '݊' => 230, - '߫' => 230, - '߬' => 230, - '߭' => 230, - '߮' => 230, - '߯' => 230, - '߰' => 230, - '߱' => 230, - '߲' => 220, - '߳' => 230, - '߽' => 220, - 'ࠖ' => 230, - 'ࠗ' => 230, - '࠘' => 230, - '࠙' => 230, - 'ࠛ' => 230, - 'ࠜ' => 230, - 'ࠝ' => 230, - 'ࠞ' => 230, - 'ࠟ' => 230, - 'ࠠ' => 230, - 'ࠡ' => 230, - 'ࠢ' => 230, - 'ࠣ' => 230, - 'ࠥ' => 230, - 'ࠦ' => 230, - 'ࠧ' => 230, - 'ࠩ' => 230, - 'ࠪ' => 230, - 'ࠫ' => 230, - 'ࠬ' => 230, - '࠭' => 230, - '࡙' => 220, - '࡚' => 220, - '࡛' => 220, - '࣓' => 220, - 'ࣔ' => 230, - 'ࣕ' => 230, - 'ࣖ' => 230, - 'ࣗ' => 230, - 'ࣘ' => 230, - 'ࣙ' => 230, - 'ࣚ' => 230, - 'ࣛ' => 230, - 'ࣜ' => 230, - 'ࣝ' => 230, - 'ࣞ' => 230, - 'ࣟ' => 230, - '࣠' => 230, - '࣡' => 230, - 'ࣣ' => 220, - 'ࣤ' => 230, - 'ࣥ' => 230, - 'ࣦ' => 220, - 'ࣧ' => 230, - 'ࣨ' => 230, - 'ࣩ' => 220, - '࣪' => 230, - '࣫' => 230, - '࣬' => 230, - '࣭' => 220, - '࣮' => 220, - '࣯' => 220, - 'ࣰ' => 27, - 'ࣱ' => 28, - 'ࣲ' => 29, - 'ࣳ' => 230, - 'ࣴ' => 230, - 'ࣵ' => 230, - 'ࣶ' => 220, - 'ࣷ' => 230, - 'ࣸ' => 230, - 'ࣹ' => 220, - 'ࣺ' => 220, - 'ࣻ' => 230, - 'ࣼ' => 230, - 'ࣽ' => 230, - 'ࣾ' => 230, - 'ࣿ' => 230, - '़' => 7, - '्' => 9, - '॑' => 230, - '॒' => 220, - '॓' => 230, - '॔' => 230, - '়' => 7, - '্' => 9, - '৾' => 230, - '਼' => 7, - '੍' => 9, - '઼' => 7, - '્' => 9, - '଼' => 7, - '୍' => 9, - '்' => 9, - '్' => 9, - 'ౕ' => 84, - 'ౖ' => 91, - '಼' => 7, - '್' => 9, - '഻' => 9, - '഼' => 9, - '്' => 9, - '්' => 9, - 'ุ' => 103, - 'ู' => 103, - 'ฺ' => 9, - '่' => 107, - '้' => 107, - '๊' => 107, - '๋' => 107, - 'ຸ' => 118, - 'ູ' => 118, - '຺' => 9, - '່' => 122, - '້' => 122, - '໊' => 122, - '໋' => 122, - '༘' => 220, - '༙' => 220, - '༵' => 220, - '༷' => 220, - '༹' => 216, - 'ཱ' => 129, - 'ི' => 130, - 'ུ' => 132, - 'ེ' => 130, - 'ཻ' => 130, - 'ོ' => 130, - 'ཽ' => 130, - 'ྀ' => 130, - 'ྂ' => 230, - 'ྃ' => 230, - '྄' => 9, - '྆' => 230, - '྇' => 230, - '࿆' => 220, - '့' => 7, - '္' => 9, - '်' => 9, - 'ႍ' => 220, - '፝' => 230, - '፞' => 230, - '፟' => 230, - '᜔' => 9, - '᜴' => 9, - '្' => 9, - '៝' => 230, - 'ᢩ' => 228, - '᤹' => 222, - '᤺' => 230, - '᤻' => 220, - 'ᨗ' => 230, - 'ᨘ' => 220, - '᩠' => 9, - '᩵' => 230, - '᩶' => 230, - '᩷' => 230, - '᩸' => 230, - '᩹' => 230, - '᩺' => 230, - '᩻' => 230, - '᩼' => 230, - '᩿' => 220, - '᪰' => 230, - '᪱' => 230, - '᪲' => 230, - '᪳' => 230, - '᪴' => 230, - '᪵' => 220, - '᪶' => 220, - '᪷' => 220, - '᪸' => 220, - '᪹' => 220, - '᪺' => 220, - '᪻' => 230, - '᪼' => 230, - '᪽' => 220, - 'ᪿ' => 220, - 'ᫀ' => 220, - '᬴' => 7, - '᭄' => 9, - '᭫' => 230, - '᭬' => 220, - '᭭' => 230, - '᭮' => 230, - '᭯' => 230, - '᭰' => 230, - '᭱' => 230, - '᭲' => 230, - '᭳' => 230, - '᮪' => 9, - '᮫' => 9, - '᯦' => 7, - '᯲' => 9, - '᯳' => 9, - '᰷' => 7, - '᳐' => 230, - '᳑' => 230, - '᳒' => 230, - '᳔' => 1, - '᳕' => 220, - '᳖' => 220, - '᳗' => 220, - '᳘' => 220, - '᳙' => 220, - '᳚' => 230, - '᳛' => 230, - '᳜' => 220, - '᳝' => 220, - '᳞' => 220, - '᳟' => 220, - '᳠' => 230, - '᳢' => 1, - '᳣' => 1, - '᳤' => 1, - '᳥' => 1, - '᳦' => 1, - '᳧' => 1, - '᳨' => 1, - '᳭' => 220, - '᳴' => 230, - '᳸' => 230, - '᳹' => 230, - '᷀' => 230, - '᷁' => 230, - '᷂' => 220, - '᷃' => 230, - '᷄' => 230, - '᷅' => 230, - '᷆' => 230, - '᷇' => 230, - '᷈' => 230, - '᷉' => 230, - '᷊' => 220, - '᷋' => 230, - '᷌' => 230, - '᷍' => 234, - '᷎' => 214, - '᷏' => 220, - '᷐' => 202, - '᷑' => 230, - '᷒' => 230, - 'ᷓ' => 230, - 'ᷔ' => 230, - 'ᷕ' => 230, - 'ᷖ' => 230, - 'ᷗ' => 230, - 'ᷘ' => 230, - 'ᷙ' => 230, - 'ᷚ' => 230, - 'ᷛ' => 230, - 'ᷜ' => 230, - 'ᷝ' => 230, - 'ᷞ' => 230, - 'ᷟ' => 230, - 'ᷠ' => 230, - 'ᷡ' => 230, - 'ᷢ' => 230, - 'ᷣ' => 230, - 'ᷤ' => 230, - 'ᷥ' => 230, - 'ᷦ' => 230, - 'ᷧ' => 230, - 'ᷨ' => 230, - 'ᷩ' => 230, - 'ᷪ' => 230, - 'ᷫ' => 230, - 'ᷬ' => 230, - 'ᷭ' => 230, - 'ᷮ' => 230, - 'ᷯ' => 230, - 'ᷰ' => 230, - 'ᷱ' => 230, - 'ᷲ' => 230, - 'ᷳ' => 230, - 'ᷴ' => 230, - '᷵' => 230, - '᷶' => 232, - '᷷' => 228, - '᷸' => 228, - '᷹' => 220, - '᷻' => 230, - '᷼' => 233, - '᷽' => 220, - '᷾' => 230, - '᷿' => 220, - '⃐' => 230, - '⃑' => 230, - '⃒' => 1, - '⃓' => 1, - '⃔' => 230, - '⃕' => 230, - '⃖' => 230, - '⃗' => 230, - '⃘' => 1, - '⃙' => 1, - '⃚' => 1, - '⃛' => 230, - '⃜' => 230, - '⃡' => 230, - '⃥' => 1, - '⃦' => 1, - '⃧' => 230, - '⃨' => 220, - '⃩' => 230, - '⃪' => 1, - '⃫' => 1, - '⃬' => 220, - '⃭' => 220, - '⃮' => 220, - '⃯' => 220, - '⃰' => 230, - '⳯' => 230, - '⳰' => 230, - '⳱' => 230, - '⵿' => 9, - 'ⷠ' => 230, - 'ⷡ' => 230, - 'ⷢ' => 230, - 'ⷣ' => 230, - 'ⷤ' => 230, - 'ⷥ' => 230, - 'ⷦ' => 230, - 'ⷧ' => 230, - 'ⷨ' => 230, - 'ⷩ' => 230, - 'ⷪ' => 230, - 'ⷫ' => 230, - 'ⷬ' => 230, - 'ⷭ' => 230, - 'ⷮ' => 230, - 'ⷯ' => 230, - 'ⷰ' => 230, - 'ⷱ' => 230, - 'ⷲ' => 230, - 'ⷳ' => 230, - 'ⷴ' => 230, - 'ⷵ' => 230, - 'ⷶ' => 230, - 'ⷷ' => 230, - 'ⷸ' => 230, - 'ⷹ' => 230, - 'ⷺ' => 230, - 'ⷻ' => 230, - 'ⷼ' => 230, - 'ⷽ' => 230, - 'ⷾ' => 230, - 'ⷿ' => 230, - '〪' => 218, - '〫' => 228, - '〬' => 232, - '〭' => 222, - '〮' => 224, - '〯' => 224, - '゙' => 8, - '゚' => 8, - '꙯' => 230, - 'ꙴ' => 230, - 'ꙵ' => 230, - 'ꙶ' => 230, - 'ꙷ' => 230, - 'ꙸ' => 230, - 'ꙹ' => 230, - 'ꙺ' => 230, - 'ꙻ' => 230, - '꙼' => 230, - '꙽' => 230, - 'ꚞ' => 230, - 'ꚟ' => 230, - '꛰' => 230, - '꛱' => 230, - '꠆' => 9, - '꠬' => 9, - '꣄' => 9, - '꣠' => 230, - '꣡' => 230, - '꣢' => 230, - '꣣' => 230, - '꣤' => 230, - '꣥' => 230, - '꣦' => 230, - '꣧' => 230, - '꣨' => 230, - '꣩' => 230, - '꣪' => 230, - '꣫' => 230, - '꣬' => 230, - '꣭' => 230, - '꣮' => 230, - '꣯' => 230, - '꣰' => 230, - '꣱' => 230, - '꤫' => 220, - '꤬' => 220, - '꤭' => 220, - '꥓' => 9, - '꦳' => 7, - '꧀' => 9, - 'ꪰ' => 230, - 'ꪲ' => 230, - 'ꪳ' => 230, - 'ꪴ' => 220, - 'ꪷ' => 230, - 'ꪸ' => 230, - 'ꪾ' => 230, - '꪿' => 230, - '꫁' => 230, - '꫶' => 9, - '꯭' => 9, - 'ﬞ' => 26, - '︠' => 230, - '︡' => 230, - '︢' => 230, - '︣' => 230, - '︤' => 230, - '︥' => 230, - '︦' => 230, - '︧' => 220, - '︨' => 220, - '︩' => 220, - '︪' => 220, - '︫' => 220, - '︬' => 220, - '︭' => 220, - '︮' => 230, - '︯' => 230, - '𐇽' => 220, - '𐋠' => 220, - '𐍶' => 230, - '𐍷' => 230, - '𐍸' => 230, - '𐍹' => 230, - '𐍺' => 230, - '𐨍' => 220, - '𐨏' => 230, - '𐨸' => 230, - '𐨹' => 1, - '𐨺' => 220, - '𐨿' => 9, - '𐫥' => 230, - '𐫦' => 220, - '𐴤' => 230, - '𐴥' => 230, - '𐴦' => 230, - '𐴧' => 230, - '𐺫' => 230, - '𐺬' => 230, - '𐽆' => 220, - '𐽇' => 220, - '𐽈' => 230, - '𐽉' => 230, - '𐽊' => 230, - '𐽋' => 220, - '𐽌' => 230, - '𐽍' => 220, - '𐽎' => 220, - '𐽏' => 220, - '𐽐' => 220, - '𑁆' => 9, - '𑁿' => 9, - '𑂹' => 9, - '𑂺' => 7, - '𑄀' => 230, - '𑄁' => 230, - '𑄂' => 230, - '𑄳' => 9, - '𑄴' => 9, - '𑅳' => 7, - '𑇀' => 9, - '𑇊' => 7, - '𑈵' => 9, - '𑈶' => 7, - '𑋩' => 7, - '𑋪' => 9, - '𑌻' => 7, - '𑌼' => 7, - '𑍍' => 9, - '𑍦' => 230, - '𑍧' => 230, - '𑍨' => 230, - '𑍩' => 230, - '𑍪' => 230, - '𑍫' => 230, - '𑍬' => 230, - '𑍰' => 230, - '𑍱' => 230, - '𑍲' => 230, - '𑍳' => 230, - '𑍴' => 230, - '𑑂' => 9, - '𑑆' => 7, - '𑑞' => 230, - '𑓂' => 9, - '𑓃' => 7, - '𑖿' => 9, - '𑗀' => 7, - '𑘿' => 9, - '𑚶' => 9, - '𑚷' => 7, - '𑜫' => 9, - '𑠹' => 9, - '𑠺' => 7, - '𑤽' => 9, - '𑤾' => 9, - '𑥃' => 7, - '𑧠' => 9, - '𑨴' => 9, - '𑩇' => 9, - '𑪙' => 9, - '𑰿' => 9, - '𑵂' => 7, - '𑵄' => 9, - '𑵅' => 9, - '𑶗' => 9, - '𖫰' => 1, - '𖫱' => 1, - '𖫲' => 1, - '𖫳' => 1, - '𖫴' => 1, - '𖬰' => 230, - '𖬱' => 230, - '𖬲' => 230, - '𖬳' => 230, - '𖬴' => 230, - '𖬵' => 230, - '𖬶' => 230, - '𖿰' => 6, - '𖿱' => 6, - '𛲞' => 1, - '𝅥' => 216, - '𝅦' => 216, - '𝅧' => 1, - '𝅨' => 1, - '𝅩' => 1, - '𝅭' => 226, - '𝅮' => 216, - '𝅯' => 216, - '𝅰' => 216, - '𝅱' => 216, - '𝅲' => 216, - '𝅻' => 220, - '𝅼' => 220, - '𝅽' => 220, - '𝅾' => 220, - '𝅿' => 220, - '𝆀' => 220, - '𝆁' => 220, - '𝆂' => 220, - '𝆅' => 230, - '𝆆' => 230, - '𝆇' => 230, - '𝆈' => 230, - '𝆉' => 230, - '𝆊' => 220, - '𝆋' => 220, - '𝆪' => 230, - '𝆫' => 230, - '𝆬' => 230, - '𝆭' => 230, - '𝉂' => 230, - '𝉃' => 230, - '𝉄' => 230, - '𞀀' => 230, - '𞀁' => 230, - '𞀂' => 230, - '𞀃' => 230, - '𞀄' => 230, - '𞀅' => 230, - '𞀆' => 230, - '𞀈' => 230, - '𞀉' => 230, - '𞀊' => 230, - '𞀋' => 230, - '𞀌' => 230, - '𞀍' => 230, - '𞀎' => 230, - '𞀏' => 230, - '𞀐' => 230, - '𞀑' => 230, - '𞀒' => 230, - '𞀓' => 230, - '𞀔' => 230, - '𞀕' => 230, - '𞀖' => 230, - '𞀗' => 230, - '𞀘' => 230, - '𞀛' => 230, - '𞀜' => 230, - '𞀝' => 230, - '𞀞' => 230, - '𞀟' => 230, - '𞀠' => 230, - '𞀡' => 230, - '𞀣' => 230, - '𞀤' => 230, - '𞀦' => 230, - '𞀧' => 230, - '𞀨' => 230, - '𞀩' => 230, - '𞀪' => 230, - '𞄰' => 230, - '𞄱' => 230, - '𞄲' => 230, - '𞄳' => 230, - '𞄴' => 230, - '𞄵' => 230, - '𞄶' => 230, - '𞋬' => 230, - '𞋭' => 230, - '𞋮' => 230, - '𞋯' => 230, - '𞣐' => 220, - '𞣑' => 220, - '𞣒' => 220, - '𞣓' => 220, - '𞣔' => 220, - '𞣕' => 220, - '𞣖' => 220, - '𞥄' => 230, - '𞥅' => 230, - '𞥆' => 230, - '𞥇' => 230, - '𞥈' => 230, - '𞥉' => 230, - '𞥊' => 7, -); diff --git a/lib/symfony/polyfill-intl-normalizer/Resources/unidata/compatibilityDecomposition.php b/lib/symfony/polyfill-intl-normalizer/Resources/unidata/compatibilityDecomposition.php deleted file mode 100644 index 157490289..000000000 --- a/lib/symfony/polyfill-intl-normalizer/Resources/unidata/compatibilityDecomposition.php +++ /dev/null @@ -1,3695 +0,0 @@ -<?php - -return array ( - ' ' => ' ', - '¨' => ' ̈', - 'ª' => 'a', - '¯' => ' ̄', - '²' => '2', - '³' => '3', - '´' => ' ́', - 'µ' => 'μ', - '¸' => ' ̧', - '¹' => '1', - 'º' => 'o', - '¼' => '1⁄4', - '½' => '1⁄2', - '¾' => '3⁄4', - 'IJ' => 'IJ', - 'ij' => 'ij', - 'Ŀ' => 'L·', - 'ŀ' => 'l·', - 'ʼn' => 'ʼn', - 'ſ' => 's', - 'DŽ' => 'DŽ', - 'Dž' => 'Dž', - 'dž' => 'dž', - 'LJ' => 'LJ', - 'Lj' => 'Lj', - 'lj' => 'lj', - 'NJ' => 'NJ', - 'Nj' => 'Nj', - 'nj' => 'nj', - 'DZ' => 'DZ', - 'Dz' => 'Dz', - 'dz' => 'dz', - 'ʰ' => 'h', - 'ʱ' => 'ɦ', - 'ʲ' => 'j', - 'ʳ' => 'r', - 'ʴ' => 'ɹ', - 'ʵ' => 'ɻ', - 'ʶ' => 'ʁ', - 'ʷ' => 'w', - 'ʸ' => 'y', - '˘' => ' ̆', - '˙' => ' ̇', - '˚' => ' ̊', - '˛' => ' ̨', - '˜' => ' ̃', - '˝' => ' ̋', - 'ˠ' => 'ɣ', - 'ˡ' => 'l', - 'ˢ' => 's', - 'ˣ' => 'x', - 'ˤ' => 'ʕ', - 'ͺ' => ' ͅ', - '΄' => ' ́', - '΅' => ' ̈́', - 'ϐ' => 'β', - 'ϑ' => 'θ', - 'ϒ' => 'Υ', - 'ϓ' => 'Ύ', - 'ϔ' => 'Ϋ', - 'ϕ' => 'φ', - 'ϖ' => 'π', - 'ϰ' => 'κ', - 'ϱ' => 'ρ', - 'ϲ' => 'ς', - 'ϴ' => 'Θ', - 'ϵ' => 'ε', - 'Ϲ' => 'Σ', - 'և' => 'եւ', - 'ٵ' => 'اٴ', - 'ٶ' => 'وٴ', - 'ٷ' => 'ۇٴ', - 'ٸ' => 'يٴ', - 'ำ' => 'ํา', - 'ຳ' => 'ໍາ', - 'ໜ' => 'ຫນ', - 'ໝ' => 'ຫມ', - '༌' => '་', - 'ཷ' => 'ྲཱྀ', - 'ཹ' => 'ླཱྀ', - 'ჼ' => 'ნ', - 'ᴬ' => 'A', - 'ᴭ' => 'Æ', - 'ᴮ' => 'B', - 'ᴰ' => 'D', - 'ᴱ' => 'E', - 'ᴲ' => 'Ǝ', - 'ᴳ' => 'G', - 'ᴴ' => 'H', - 'ᴵ' => 'I', - 'ᴶ' => 'J', - 'ᴷ' => 'K', - 'ᴸ' => 'L', - 'ᴹ' => 'M', - 'ᴺ' => 'N', - 'ᴼ' => 'O', - 'ᴽ' => 'Ȣ', - 'ᴾ' => 'P', - 'ᴿ' => 'R', - 'ᵀ' => 'T', - 'ᵁ' => 'U', - 'ᵂ' => 'W', - 'ᵃ' => 'a', - 'ᵄ' => 'ɐ', - 'ᵅ' => 'ɑ', - 'ᵆ' => 'ᴂ', - 'ᵇ' => 'b', - 'ᵈ' => 'd', - 'ᵉ' => 'e', - 'ᵊ' => 'ə', - 'ᵋ' => 'ɛ', - 'ᵌ' => 'ɜ', - 'ᵍ' => 'g', - 'ᵏ' => 'k', - 'ᵐ' => 'm', - 'ᵑ' => 'ŋ', - 'ᵒ' => 'o', - 'ᵓ' => 'ɔ', - 'ᵔ' => 'ᴖ', - 'ᵕ' => 'ᴗ', - 'ᵖ' => 'p', - 'ᵗ' => 't', - 'ᵘ' => 'u', - 'ᵙ' => 'ᴝ', - 'ᵚ' => 'ɯ', - 'ᵛ' => 'v', - 'ᵜ' => 'ᴥ', - 'ᵝ' => 'β', - 'ᵞ' => 'γ', - 'ᵟ' => 'δ', - 'ᵠ' => 'φ', - 'ᵡ' => 'χ', - 'ᵢ' => 'i', - 'ᵣ' => 'r', - 'ᵤ' => 'u', - 'ᵥ' => 'v', - 'ᵦ' => 'β', - 'ᵧ' => 'γ', - 'ᵨ' => 'ρ', - 'ᵩ' => 'φ', - 'ᵪ' => 'χ', - 'ᵸ' => 'н', - 'ᶛ' => 'ɒ', - 'ᶜ' => 'c', - 'ᶝ' => 'ɕ', - 'ᶞ' => 'ð', - 'ᶟ' => 'ɜ', - 'ᶠ' => 'f', - 'ᶡ' => 'ɟ', - 'ᶢ' => 'ɡ', - 'ᶣ' => 'ɥ', - 'ᶤ' => 'ɨ', - 'ᶥ' => 'ɩ', - 'ᶦ' => 'ɪ', - 'ᶧ' => 'ᵻ', - 'ᶨ' => 'ʝ', - 'ᶩ' => 'ɭ', - 'ᶪ' => 'ᶅ', - 'ᶫ' => 'ʟ', - 'ᶬ' => 'ɱ', - 'ᶭ' => 'ɰ', - 'ᶮ' => 'ɲ', - 'ᶯ' => 'ɳ', - 'ᶰ' => 'ɴ', - 'ᶱ' => 'ɵ', - 'ᶲ' => 'ɸ', - 'ᶳ' => 'ʂ', - 'ᶴ' => 'ʃ', - 'ᶵ' => 'ƫ', - 'ᶶ' => 'ʉ', - 'ᶷ' => 'ʊ', - 'ᶸ' => 'ᴜ', - 'ᶹ' => 'ʋ', - 'ᶺ' => 'ʌ', - 'ᶻ' => 'z', - 'ᶼ' => 'ʐ', - 'ᶽ' => 'ʑ', - 'ᶾ' => 'ʒ', - 'ᶿ' => 'θ', - 'ẚ' => 'aʾ', - 'ẛ' => 'ṡ', - '᾽' => ' ̓', - '᾿' => ' ̓', - '῀' => ' ͂', - '῁' => ' ̈͂', - '῍' => ' ̓̀', - '῎' => ' ̓́', - '῏' => ' ̓͂', - '῝' => ' ̔̀', - '῞' => ' ̔́', - '῟' => ' ̔͂', - '῭' => ' ̈̀', - '΅' => ' ̈́', - '´' => ' ́', - '῾' => ' ̔', - ' ' => ' ', - ' ' => ' ', - ' ' => ' ', - ' ' => ' ', - ' ' => ' ', - ' ' => ' ', - ' ' => ' ', - ' ' => ' ', - ' ' => ' ', - ' ' => ' ', - ' ' => ' ', - '‑' => '‐', - '‗' => ' ̳', - '․' => '.', - '‥' => '..', - '…' => '...', - ' ' => ' ', - '″' => '′′', - '‴' => '′′′', - '‶' => '‵‵', - '‷' => '‵‵‵', - '‼' => '!!', - '‾' => ' ̅', - '⁇' => '??', - '⁈' => '?!', - '⁉' => '!?', - '⁗' => '′′′′', - ' ' => ' ', - '⁰' => '0', - 'ⁱ' => 'i', - '⁴' => '4', - '⁵' => '5', - '⁶' => '6', - '⁷' => '7', - '⁸' => '8', - '⁹' => '9', - '⁺' => '+', - '⁻' => '−', - '⁼' => '=', - '⁽' => '(', - '⁾' => ')', - 'ⁿ' => 'n', - '₀' => '0', - '₁' => '1', - '₂' => '2', - '₃' => '3', - '₄' => '4', - '₅' => '5', - '₆' => '6', - '₇' => '7', - '₈' => '8', - '₉' => '9', - '₊' => '+', - '₋' => '−', - '₌' => '=', - '₍' => '(', - '₎' => ')', - 'ₐ' => 'a', - 'ₑ' => 'e', - 'ₒ' => 'o', - 'ₓ' => 'x', - 'ₔ' => 'ə', - 'ₕ' => 'h', - 'ₖ' => 'k', - 'ₗ' => 'l', - 'ₘ' => 'm', - 'ₙ' => 'n', - 'ₚ' => 'p', - 'ₛ' => 's', - 'ₜ' => 't', - '₨' => 'Rs', - '℀' => 'a/c', - '℁' => 'a/s', - 'ℂ' => 'C', - '℃' => '°C', - '℅' => 'c/o', - '℆' => 'c/u', - 'ℇ' => 'Ɛ', - '℉' => '°F', - 'ℊ' => 'g', - 'ℋ' => 'H', - 'ℌ' => 'H', - 'ℍ' => 'H', - 'ℎ' => 'h', - 'ℏ' => 'ħ', - 'ℐ' => 'I', - 'ℑ' => 'I', - 'ℒ' => 'L', - 'ℓ' => 'l', - 'ℕ' => 'N', - '№' => 'No', - 'ℙ' => 'P', - 'ℚ' => 'Q', - 'ℛ' => 'R', - 'ℜ' => 'R', - 'ℝ' => 'R', - '℠' => 'SM', - '℡' => 'TEL', - '™' => 'TM', - 'ℤ' => 'Z', - 'ℨ' => 'Z', - 'ℬ' => 'B', - 'ℭ' => 'C', - 'ℯ' => 'e', - 'ℰ' => 'E', - 'ℱ' => 'F', - 'ℳ' => 'M', - 'ℴ' => 'o', - 'ℵ' => 'א', - 'ℶ' => 'ב', - 'ℷ' => 'ג', - 'ℸ' => 'ד', - 'ℹ' => 'i', - '℻' => 'FAX', - 'ℼ' => 'π', - 'ℽ' => 'γ', - 'ℾ' => 'Γ', - 'ℿ' => 'Π', - '⅀' => '∑', - 'ⅅ' => 'D', - 'ⅆ' => 'd', - 'ⅇ' => 'e', - 'ⅈ' => 'i', - 'ⅉ' => 'j', - '⅐' => '1⁄7', - '⅑' => '1⁄9', - '⅒' => '1⁄10', - '⅓' => '1⁄3', - '⅔' => '2⁄3', - '⅕' => '1⁄5', - '⅖' => '2⁄5', - '⅗' => '3⁄5', - '⅘' => '4⁄5', - '⅙' => '1⁄6', - '⅚' => '5⁄6', - '⅛' => '1⁄8', - '⅜' => '3⁄8', - '⅝' => '5⁄8', - '⅞' => '7⁄8', - '⅟' => '1⁄', - 'Ⅰ' => 'I', - 'Ⅱ' => 'II', - 'Ⅲ' => 'III', - 'Ⅳ' => 'IV', - 'Ⅴ' => 'V', - 'Ⅵ' => 'VI', - 'Ⅶ' => 'VII', - 'Ⅷ' => 'VIII', - 'Ⅸ' => 'IX', - 'Ⅹ' => 'X', - 'Ⅺ' => 'XI', - 'Ⅻ' => 'XII', - 'Ⅼ' => 'L', - 'Ⅽ' => 'C', - 'Ⅾ' => 'D', - 'Ⅿ' => 'M', - 'ⅰ' => 'i', - 'ⅱ' => 'ii', - 'ⅲ' => 'iii', - 'ⅳ' => 'iv', - 'ⅴ' => 'v', - 'ⅵ' => 'vi', - 'ⅶ' => 'vii', - 'ⅷ' => 'viii', - 'ⅸ' => 'ix', - 'ⅹ' => 'x', - 'ⅺ' => 'xi', - 'ⅻ' => 'xii', - 'ⅼ' => 'l', - 'ⅽ' => 'c', - 'ⅾ' => 'd', - 'ⅿ' => 'm', - '↉' => '0⁄3', - '∬' => '∫∫', - '∭' => '∫∫∫', - '∯' => '∮∮', - '∰' => '∮∮∮', - '①' => '1', - '②' => '2', - '③' => '3', - '④' => '4', - '⑤' => '5', - '⑥' => '6', - '⑦' => '7', - '⑧' => '8', - '⑨' => '9', - '⑩' => '10', - '⑪' => '11', - '⑫' => '12', - '⑬' => '13', - '⑭' => '14', - '⑮' => '15', - '⑯' => '16', - '⑰' => '17', - '⑱' => '18', - '⑲' => '19', - '⑳' => '20', - '⑴' => '(1)', - '⑵' => '(2)', - '⑶' => '(3)', - '⑷' => '(4)', - '⑸' => '(5)', - '⑹' => '(6)', - '⑺' => '(7)', - '⑻' => '(8)', - '⑼' => '(9)', - '⑽' => '(10)', - '⑾' => '(11)', - '⑿' => '(12)', - '⒀' => '(13)', - '⒁' => '(14)', - '⒂' => '(15)', - '⒃' => '(16)', - '⒄' => '(17)', - '⒅' => '(18)', - '⒆' => '(19)', - '⒇' => '(20)', - '⒈' => '1.', - '⒉' => '2.', - '⒊' => '3.', - '⒋' => '4.', - '⒌' => '5.', - '⒍' => '6.', - '⒎' => '7.', - '⒏' => '8.', - '⒐' => '9.', - '⒑' => '10.', - '⒒' => '11.', - '⒓' => '12.', - '⒔' => '13.', - '⒕' => '14.', - '⒖' => '15.', - '⒗' => '16.', - '⒘' => '17.', - '⒙' => '18.', - '⒚' => '19.', - '⒛' => '20.', - '⒜' => '(a)', - '⒝' => '(b)', - '⒞' => '(c)', - '⒟' => '(d)', - '⒠' => '(e)', - '⒡' => '(f)', - '⒢' => '(g)', - '⒣' => '(h)', - '⒤' => '(i)', - '⒥' => '(j)', - '⒦' => '(k)', - '⒧' => '(l)', - '⒨' => '(m)', - '⒩' => '(n)', - '⒪' => '(o)', - '⒫' => '(p)', - '⒬' => '(q)', - '⒭' => '(r)', - '⒮' => '(s)', - '⒯' => '(t)', - '⒰' => '(u)', - '⒱' => '(v)', - '⒲' => '(w)', - '⒳' => '(x)', - '⒴' => '(y)', - '⒵' => '(z)', - 'Ⓐ' => 'A', - 'Ⓑ' => 'B', - 'Ⓒ' => 'C', - 'Ⓓ' => 'D', - 'Ⓔ' => 'E', - 'Ⓕ' => 'F', - 'Ⓖ' => 'G', - 'Ⓗ' => 'H', - 'Ⓘ' => 'I', - 'Ⓙ' => 'J', - 'Ⓚ' => 'K', - 'Ⓛ' => 'L', - 'Ⓜ' => 'M', - 'Ⓝ' => 'N', - 'Ⓞ' => 'O', - 'Ⓟ' => 'P', - 'Ⓠ' => 'Q', - 'Ⓡ' => 'R', - 'Ⓢ' => 'S', - 'Ⓣ' => 'T', - 'Ⓤ' => 'U', - 'Ⓥ' => 'V', - 'Ⓦ' => 'W', - 'Ⓧ' => 'X', - 'Ⓨ' => 'Y', - 'Ⓩ' => 'Z', - 'ⓐ' => 'a', - 'ⓑ' => 'b', - 'ⓒ' => 'c', - 'ⓓ' => 'd', - 'ⓔ' => 'e', - 'ⓕ' => 'f', - 'ⓖ' => 'g', - 'ⓗ' => 'h', - 'ⓘ' => 'i', - 'ⓙ' => 'j', - 'ⓚ' => 'k', - 'ⓛ' => 'l', - 'ⓜ' => 'm', - 'ⓝ' => 'n', - 'ⓞ' => 'o', - 'ⓟ' => 'p', - 'ⓠ' => 'q', - 'ⓡ' => 'r', - 'ⓢ' => 's', - 'ⓣ' => 't', - 'ⓤ' => 'u', - 'ⓥ' => 'v', - 'ⓦ' => 'w', - 'ⓧ' => 'x', - 'ⓨ' => 'y', - 'ⓩ' => 'z', - '⓪' => '0', - '⨌' => '∫∫∫∫', - '⩴' => '::=', - '⩵' => '==', - '⩶' => '===', - 'ⱼ' => 'j', - 'ⱽ' => 'V', - 'ⵯ' => 'ⵡ', - '⺟' => '母', - '⻳' => '龟', - '⼀' => '一', - '⼁' => '丨', - '⼂' => '丶', - '⼃' => '丿', - '⼄' => '乙', - '⼅' => '亅', - '⼆' => '二', - '⼇' => '亠', - '⼈' => '人', - '⼉' => '儿', - '⼊' => '入', - '⼋' => '八', - '⼌' => '冂', - '⼍' => '冖', - '⼎' => '冫', - '⼏' => '几', - '⼐' => '凵', - '⼑' => '刀', - '⼒' => '力', - '⼓' => '勹', - '⼔' => '匕', - '⼕' => '匚', - '⼖' => '匸', - '⼗' => '十', - '⼘' => '卜', - '⼙' => '卩', - '⼚' => '厂', - '⼛' => '厶', - '⼜' => '又', - '⼝' => '口', - '⼞' => '囗', - '⼟' => '土', - '⼠' => '士', - '⼡' => '夂', - '⼢' => '夊', - '⼣' => '夕', - '⼤' => '大', - '⼥' => '女', - '⼦' => '子', - '⼧' => '宀', - '⼨' => '寸', - '⼩' => '小', - '⼪' => '尢', - '⼫' => '尸', - '⼬' => '屮', - '⼭' => '山', - '⼮' => '巛', - '⼯' => '工', - '⼰' => '己', - '⼱' => '巾', - '⼲' => '干', - '⼳' => '幺', - '⼴' => '广', - '⼵' => '廴', - '⼶' => '廾', - '⼷' => '弋', - '⼸' => '弓', - '⼹' => '彐', - '⼺' => '彡', - '⼻' => '彳', - '⼼' => '心', - '⼽' => '戈', - '⼾' => '戶', - '⼿' => '手', - '⽀' => '支', - '⽁' => '攴', - '⽂' => '文', - '⽃' => '斗', - '⽄' => '斤', - '⽅' => '方', - '⽆' => '无', - '⽇' => '日', - '⽈' => '曰', - '⽉' => '月', - '⽊' => '木', - '⽋' => '欠', - '⽌' => '止', - '⽍' => '歹', - '⽎' => '殳', - '⽏' => '毋', - '⽐' => '比', - '⽑' => '毛', - '⽒' => '氏', - '⽓' => '气', - '⽔' => '水', - '⽕' => '火', - '⽖' => '爪', - '⽗' => '父', - '⽘' => '爻', - '⽙' => '爿', - '⽚' => '片', - '⽛' => '牙', - '⽜' => '牛', - '⽝' => '犬', - '⽞' => '玄', - '⽟' => '玉', - '⽠' => '瓜', - '⽡' => '瓦', - '⽢' => '甘', - '⽣' => '生', - '⽤' => '用', - '⽥' => '田', - '⽦' => '疋', - '⽧' => '疒', - '⽨' => '癶', - '⽩' => '白', - '⽪' => '皮', - '⽫' => '皿', - '⽬' => '目', - '⽭' => '矛', - '⽮' => '矢', - '⽯' => '石', - '⽰' => '示', - '⽱' => '禸', - '⽲' => '禾', - '⽳' => '穴', - '⽴' => '立', - '⽵' => '竹', - '⽶' => '米', - '⽷' => '糸', - '⽸' => '缶', - '⽹' => '网', - '⽺' => '羊', - '⽻' => '羽', - '⽼' => '老', - '⽽' => '而', - '⽾' => '耒', - '⽿' => '耳', - '⾀' => '聿', - '⾁' => '肉', - '⾂' => '臣', - '⾃' => '自', - '⾄' => '至', - '⾅' => '臼', - '⾆' => '舌', - '⾇' => '舛', - '⾈' => '舟', - '⾉' => '艮', - '⾊' => '色', - '⾋' => '艸', - '⾌' => '虍', - '⾍' => '虫', - '⾎' => '血', - '⾏' => '行', - '⾐' => '衣', - '⾑' => '襾', - '⾒' => '見', - '⾓' => '角', - '⾔' => '言', - '⾕' => '谷', - '⾖' => '豆', - '⾗' => '豕', - '⾘' => '豸', - '⾙' => '貝', - '⾚' => '赤', - '⾛' => '走', - '⾜' => '足', - '⾝' => '身', - '⾞' => '車', - '⾟' => '辛', - '⾠' => '辰', - '⾡' => '辵', - '⾢' => '邑', - '⾣' => '酉', - '⾤' => '釆', - '⾥' => '里', - '⾦' => '金', - '⾧' => '長', - '⾨' => '門', - '⾩' => '阜', - '⾪' => '隶', - '⾫' => '隹', - '⾬' => '雨', - '⾭' => '靑', - '⾮' => '非', - '⾯' => '面', - '⾰' => '革', - '⾱' => '韋', - '⾲' => '韭', - '⾳' => '音', - '⾴' => '頁', - '⾵' => '風', - '⾶' => '飛', - '⾷' => '食', - '⾸' => '首', - '⾹' => '香', - '⾺' => '馬', - '⾻' => '骨', - '⾼' => '高', - '⾽' => '髟', - '⾾' => '鬥', - '⾿' => '鬯', - '⿀' => '鬲', - '⿁' => '鬼', - '⿂' => '魚', - '⿃' => '鳥', - '⿄' => '鹵', - '⿅' => '鹿', - '⿆' => '麥', - '⿇' => '麻', - '⿈' => '黃', - '⿉' => '黍', - '⿊' => '黑', - '⿋' => '黹', - '⿌' => '黽', - '⿍' => '鼎', - '⿎' => '鼓', - '⿏' => '鼠', - '⿐' => '鼻', - '⿑' => '齊', - '⿒' => '齒', - '⿓' => '龍', - '⿔' => '龜', - '⿕' => '龠', - ' ' => ' ', - '〶' => '〒', - '〸' => '十', - '〹' => '卄', - '〺' => '卅', - '゛' => ' ゙', - '゜' => ' ゚', - 'ゟ' => 'より', - 'ヿ' => 'コト', - 'ㄱ' => 'ᄀ', - 'ㄲ' => 'ᄁ', - 'ㄳ' => 'ᆪ', - 'ㄴ' => 'ᄂ', - 'ㄵ' => 'ᆬ', - 'ㄶ' => 'ᆭ', - 'ㄷ' => 'ᄃ', - 'ㄸ' => 'ᄄ', - 'ㄹ' => 'ᄅ', - 'ㄺ' => 'ᆰ', - 'ㄻ' => 'ᆱ', - 'ㄼ' => 'ᆲ', - 'ㄽ' => 'ᆳ', - 'ㄾ' => 'ᆴ', - 'ㄿ' => 'ᆵ', - 'ㅀ' => 'ᄚ', - 'ㅁ' => 'ᄆ', - 'ㅂ' => 'ᄇ', - 'ㅃ' => 'ᄈ', - 'ㅄ' => 'ᄡ', - 'ㅅ' => 'ᄉ', - 'ㅆ' => 'ᄊ', - 'ㅇ' => 'ᄋ', - 'ㅈ' => 'ᄌ', - 'ㅉ' => 'ᄍ', - 'ㅊ' => 'ᄎ', - 'ㅋ' => 'ᄏ', - 'ㅌ' => 'ᄐ', - 'ㅍ' => 'ᄑ', - 'ㅎ' => 'ᄒ', - 'ㅏ' => 'ᅡ', - 'ㅐ' => 'ᅢ', - 'ㅑ' => 'ᅣ', - 'ㅒ' => 'ᅤ', - 'ㅓ' => 'ᅥ', - 'ㅔ' => 'ᅦ', - 'ㅕ' => 'ᅧ', - 'ㅖ' => 'ᅨ', - 'ㅗ' => 'ᅩ', - 'ㅘ' => 'ᅪ', - 'ㅙ' => 'ᅫ', - 'ㅚ' => 'ᅬ', - 'ㅛ' => 'ᅭ', - 'ㅜ' => 'ᅮ', - 'ㅝ' => 'ᅯ', - 'ㅞ' => 'ᅰ', - 'ㅟ' => 'ᅱ', - 'ㅠ' => 'ᅲ', - 'ㅡ' => 'ᅳ', - 'ㅢ' => 'ᅴ', - 'ㅣ' => 'ᅵ', - 'ㅤ' => 'ᅠ', - 'ㅥ' => 'ᄔ', - 'ㅦ' => 'ᄕ', - 'ㅧ' => 'ᇇ', - 'ㅨ' => 'ᇈ', - 'ㅩ' => 'ᇌ', - 'ㅪ' => 'ᇎ', - 'ㅫ' => 'ᇓ', - 'ㅬ' => 'ᇗ', - 'ㅭ' => 'ᇙ', - 'ㅮ' => 'ᄜ', - 'ㅯ' => 'ᇝ', - 'ㅰ' => 'ᇟ', - 'ㅱ' => 'ᄝ', - 'ㅲ' => 'ᄞ', - 'ㅳ' => 'ᄠ', - 'ㅴ' => 'ᄢ', - 'ㅵ' => 'ᄣ', - 'ㅶ' => 'ᄧ', - 'ㅷ' => 'ᄩ', - 'ㅸ' => 'ᄫ', - 'ㅹ' => 'ᄬ', - 'ㅺ' => 'ᄭ', - 'ㅻ' => 'ᄮ', - 'ㅼ' => 'ᄯ', - 'ㅽ' => 'ᄲ', - 'ㅾ' => 'ᄶ', - 'ㅿ' => 'ᅀ', - 'ㆀ' => 'ᅇ', - 'ㆁ' => 'ᅌ', - 'ㆂ' => 'ᇱ', - 'ㆃ' => 'ᇲ', - 'ㆄ' => 'ᅗ', - 'ㆅ' => 'ᅘ', - 'ㆆ' => 'ᅙ', - 'ㆇ' => 'ᆄ', - 'ㆈ' => 'ᆅ', - 'ㆉ' => 'ᆈ', - 'ㆊ' => 'ᆑ', - 'ㆋ' => 'ᆒ', - 'ㆌ' => 'ᆔ', - 'ㆍ' => 'ᆞ', - 'ㆎ' => 'ᆡ', - '㆒' => '一', - '㆓' => '二', - '㆔' => '三', - '㆕' => '四', - '㆖' => '上', - '㆗' => '中', - '㆘' => '下', - '㆙' => '甲', - '㆚' => '乙', - '㆛' => '丙', - '㆜' => '丁', - '㆝' => '天', - '㆞' => '地', - '㆟' => '人', - '㈀' => '(ᄀ)', - '㈁' => '(ᄂ)', - '㈂' => '(ᄃ)', - '㈃' => '(ᄅ)', - '㈄' => '(ᄆ)', - '㈅' => '(ᄇ)', - '㈆' => '(ᄉ)', - '㈇' => '(ᄋ)', - '㈈' => '(ᄌ)', - '㈉' => '(ᄎ)', - '㈊' => '(ᄏ)', - '㈋' => '(ᄐ)', - '㈌' => '(ᄑ)', - '㈍' => '(ᄒ)', - '㈎' => '(가)', - '㈏' => '(나)', - '㈐' => '(다)', - '㈑' => '(라)', - '㈒' => '(마)', - '㈓' => '(바)', - '㈔' => '(사)', - '㈕' => '(아)', - '㈖' => '(자)', - '㈗' => '(차)', - '㈘' => '(카)', - '㈙' => '(타)', - '㈚' => '(파)', - '㈛' => '(하)', - '㈜' => '(주)', - '㈝' => '(오전)', - '㈞' => '(오후)', - '㈠' => '(一)', - '㈡' => '(二)', - '㈢' => '(三)', - '㈣' => '(四)', - '㈤' => '(五)', - '㈥' => '(六)', - '㈦' => '(七)', - '㈧' => '(八)', - '㈨' => '(九)', - '㈩' => '(十)', - '㈪' => '(月)', - '㈫' => '(火)', - '㈬' => '(水)', - '㈭' => '(木)', - '㈮' => '(金)', - '㈯' => '(土)', - '㈰' => '(日)', - '㈱' => '(株)', - '㈲' => '(有)', - '㈳' => '(社)', - '㈴' => '(名)', - '㈵' => '(特)', - '㈶' => '(財)', - '㈷' => '(祝)', - '㈸' => '(労)', - '㈹' => '(代)', - '㈺' => '(呼)', - '㈻' => '(学)', - '㈼' => '(監)', - '㈽' => '(企)', - '㈾' => '(資)', - '㈿' => '(協)', - '㉀' => '(祭)', - '㉁' => '(休)', - '㉂' => '(自)', - '㉃' => '(至)', - '㉄' => '問', - '㉅' => '幼', - '㉆' => '文', - '㉇' => '箏', - '㉐' => 'PTE', - '㉑' => '21', - '㉒' => '22', - '㉓' => '23', - '㉔' => '24', - '㉕' => '25', - '㉖' => '26', - '㉗' => '27', - '㉘' => '28', - '㉙' => '29', - '㉚' => '30', - '㉛' => '31', - '㉜' => '32', - '㉝' => '33', - '㉞' => '34', - '㉟' => '35', - '㉠' => 'ᄀ', - '㉡' => 'ᄂ', - '㉢' => 'ᄃ', - '㉣' => 'ᄅ', - '㉤' => 'ᄆ', - '㉥' => 'ᄇ', - '㉦' => 'ᄉ', - '㉧' => 'ᄋ', - '㉨' => 'ᄌ', - '㉩' => 'ᄎ', - '㉪' => 'ᄏ', - '㉫' => 'ᄐ', - '㉬' => 'ᄑ', - '㉭' => 'ᄒ', - '㉮' => '가', - '㉯' => '나', - '㉰' => '다', - '㉱' => '라', - '㉲' => '마', - '㉳' => '바', - '㉴' => '사', - '㉵' => '아', - '㉶' => '자', - '㉷' => '차', - '㉸' => '카', - '㉹' => '타', - '㉺' => '파', - '㉻' => '하', - '㉼' => '참고', - '㉽' => '주의', - '㉾' => '우', - '㊀' => '一', - '㊁' => '二', - '㊂' => '三', - '㊃' => '四', - '㊄' => '五', - '㊅' => '六', - '㊆' => '七', - '㊇' => '八', - '㊈' => '九', - '㊉' => '十', - '㊊' => '月', - '㊋' => '火', - '㊌' => '水', - '㊍' => '木', - '㊎' => '金', - '㊏' => '土', - '㊐' => '日', - '㊑' => '株', - '㊒' => '有', - '㊓' => '社', - '㊔' => '名', - '㊕' => '特', - '㊖' => '財', - '㊗' => '祝', - '㊘' => '労', - '㊙' => '秘', - '㊚' => '男', - '㊛' => '女', - '㊜' => '適', - '㊝' => '優', - '㊞' => '印', - '㊟' => '注', - '㊠' => '項', - '㊡' => '休', - '㊢' => '写', - '㊣' => '正', - '㊤' => '上', - '㊥' => '中', - '㊦' => '下', - '㊧' => '左', - '㊨' => '右', - '㊩' => '医', - '㊪' => '宗', - '㊫' => '学', - '㊬' => '監', - '㊭' => '企', - '㊮' => '資', - '㊯' => '協', - '㊰' => '夜', - '㊱' => '36', - '㊲' => '37', - '㊳' => '38', - '㊴' => '39', - '㊵' => '40', - '㊶' => '41', - '㊷' => '42', - '㊸' => '43', - '㊹' => '44', - '㊺' => '45', - '㊻' => '46', - '㊼' => '47', - '㊽' => '48', - '㊾' => '49', - '㊿' => '50', - '㋀' => '1月', - '㋁' => '2月', - '㋂' => '3月', - '㋃' => '4月', - '㋄' => '5月', - '㋅' => '6月', - '㋆' => '7月', - '㋇' => '8月', - '㋈' => '9月', - '㋉' => '10月', - '㋊' => '11月', - '㋋' => '12月', - '㋌' => 'Hg', - '㋍' => 'erg', - '㋎' => 'eV', - '㋏' => 'LTD', - '㋐' => 'ア', - '㋑' => 'イ', - '㋒' => 'ウ', - '㋓' => 'エ', - '㋔' => 'オ', - '㋕' => 'カ', - '㋖' => 'キ', - '㋗' => 'ク', - '㋘' => 'ケ', - '㋙' => 'コ', - '㋚' => 'サ', - '㋛' => 'シ', - '㋜' => 'ス', - '㋝' => 'セ', - '㋞' => 'ソ', - '㋟' => 'タ', - '㋠' => 'チ', - '㋡' => 'ツ', - '㋢' => 'テ', - '㋣' => 'ト', - '㋤' => 'ナ', - '㋥' => 'ニ', - '㋦' => 'ヌ', - '㋧' => 'ネ', - '㋨' => 'ノ', - '㋩' => 'ハ', - '㋪' => 'ヒ', - '㋫' => 'フ', - '㋬' => 'ヘ', - '㋭' => 'ホ', - '㋮' => 'マ', - '㋯' => 'ミ', - '㋰' => 'ム', - '㋱' => 'メ', - '㋲' => 'モ', - '㋳' => 'ヤ', - '㋴' => 'ユ', - '㋵' => 'ヨ', - '㋶' => 'ラ', - '㋷' => 'リ', - '㋸' => 'ル', - '㋹' => 'レ', - '㋺' => 'ロ', - '㋻' => 'ワ', - '㋼' => 'ヰ', - '㋽' => 'ヱ', - '㋾' => 'ヲ', - '㋿' => '令和', - '㌀' => 'アパート', - '㌁' => 'アルファ', - '㌂' => 'アンペア', - '㌃' => 'アール', - '㌄' => 'イニング', - '㌅' => 'インチ', - '㌆' => 'ウォン', - '㌇' => 'エスクード', - '㌈' => 'エーカー', - '㌉' => 'オンス', - '㌊' => 'オーム', - '㌋' => 'カイリ', - '㌌' => 'カラット', - '㌍' => 'カロリー', - '㌎' => 'ガロン', - '㌏' => 'ガンマ', - '㌐' => 'ギガ', - '㌑' => 'ギニー', - '㌒' => 'キュリー', - '㌓' => 'ギルダー', - '㌔' => 'キロ', - '㌕' => 'キログラム', - '㌖' => 'キロメートル', - '㌗' => 'キロワット', - '㌘' => 'グラム', - '㌙' => 'グラムトン', - '㌚' => 'クルゼイロ', - '㌛' => 'クローネ', - '㌜' => 'ケース', - '㌝' => 'コルナ', - '㌞' => 'コーポ', - '㌟' => 'サイクル', - '㌠' => 'サンチーム', - '㌡' => 'シリング', - '㌢' => 'センチ', - '㌣' => 'セント', - '㌤' => 'ダース', - '㌥' => 'デシ', - '㌦' => 'ドル', - '㌧' => 'トン', - '㌨' => 'ナノ', - '㌩' => 'ノット', - '㌪' => 'ハイツ', - '㌫' => 'パーセント', - '㌬' => 'パーツ', - '㌭' => 'バーレル', - '㌮' => 'ピアストル', - '㌯' => 'ピクル', - '㌰' => 'ピコ', - '㌱' => 'ビル', - '㌲' => 'ファラッド', - '㌳' => 'フィート', - '㌴' => 'ブッシェル', - '㌵' => 'フラン', - '㌶' => 'ヘクタール', - '㌷' => 'ペソ', - '㌸' => 'ペニヒ', - '㌹' => 'ヘルツ', - '㌺' => 'ペンス', - '㌻' => 'ページ', - '㌼' => 'ベータ', - '㌽' => 'ポイント', - '㌾' => 'ボルト', - '㌿' => 'ホン', - '㍀' => 'ポンド', - '㍁' => 'ホール', - '㍂' => 'ホーン', - '㍃' => 'マイクロ', - '㍄' => 'マイル', - '㍅' => 'マッハ', - '㍆' => 'マルク', - '㍇' => 'マンション', - '㍈' => 'ミクロン', - '㍉' => 'ミリ', - '㍊' => 'ミリバール', - '㍋' => 'メガ', - '㍌' => 'メガトン', - '㍍' => 'メートル', - '㍎' => 'ヤード', - '㍏' => 'ヤール', - '㍐' => 'ユアン', - '㍑' => 'リットル', - '㍒' => 'リラ', - '㍓' => 'ルピー', - '㍔' => 'ルーブル', - '㍕' => 'レム', - '㍖' => 'レントゲン', - '㍗' => 'ワット', - '㍘' => '0点', - '㍙' => '1点', - '㍚' => '2点', - '㍛' => '3点', - '㍜' => '4点', - '㍝' => '5点', - '㍞' => '6点', - '㍟' => '7点', - '㍠' => '8点', - '㍡' => '9点', - '㍢' => '10点', - '㍣' => '11点', - '㍤' => '12点', - '㍥' => '13点', - '㍦' => '14点', - '㍧' => '15点', - '㍨' => '16点', - '㍩' => '17点', - '㍪' => '18点', - '㍫' => '19点', - '㍬' => '20点', - '㍭' => '21点', - '㍮' => '22点', - '㍯' => '23点', - '㍰' => '24点', - '㍱' => 'hPa', - '㍲' => 'da', - '㍳' => 'AU', - '㍴' => 'bar', - '㍵' => 'oV', - '㍶' => 'pc', - '㍷' => 'dm', - '㍸' => 'dm2', - '㍹' => 'dm3', - '㍺' => 'IU', - '㍻' => '平成', - '㍼' => '昭和', - '㍽' => '大正', - '㍾' => '明治', - '㍿' => '株式会社', - '㎀' => 'pA', - '㎁' => 'nA', - '㎂' => 'μA', - '㎃' => 'mA', - '㎄' => 'kA', - '㎅' => 'KB', - '㎆' => 'MB', - '㎇' => 'GB', - '㎈' => 'cal', - '㎉' => 'kcal', - '㎊' => 'pF', - '㎋' => 'nF', - '㎌' => 'μF', - '㎍' => 'μg', - '㎎' => 'mg', - '㎏' => 'kg', - '㎐' => 'Hz', - '㎑' => 'kHz', - '㎒' => 'MHz', - '㎓' => 'GHz', - '㎔' => 'THz', - '㎕' => 'μl', - '㎖' => 'ml', - '㎗' => 'dl', - '㎘' => 'kl', - '㎙' => 'fm', - '㎚' => 'nm', - '㎛' => 'μm', - '㎜' => 'mm', - '㎝' => 'cm', - '㎞' => 'km', - '㎟' => 'mm2', - '㎠' => 'cm2', - '㎡' => 'm2', - '㎢' => 'km2', - '㎣' => 'mm3', - '㎤' => 'cm3', - '㎥' => 'm3', - '㎦' => 'km3', - '㎧' => 'm∕s', - '㎨' => 'm∕s2', - '㎩' => 'Pa', - '㎪' => 'kPa', - '㎫' => 'MPa', - '㎬' => 'GPa', - '㎭' => 'rad', - '㎮' => 'rad∕s', - '㎯' => 'rad∕s2', - '㎰' => 'ps', - '㎱' => 'ns', - '㎲' => 'μs', - '㎳' => 'ms', - '㎴' => 'pV', - '㎵' => 'nV', - '㎶' => 'μV', - '㎷' => 'mV', - '㎸' => 'kV', - '㎹' => 'MV', - '㎺' => 'pW', - '㎻' => 'nW', - '㎼' => 'μW', - '㎽' => 'mW', - '㎾' => 'kW', - '㎿' => 'MW', - '㏀' => 'kΩ', - '㏁' => 'MΩ', - '㏂' => 'a.m.', - '㏃' => 'Bq', - '㏄' => 'cc', - '㏅' => 'cd', - '㏆' => 'C∕kg', - '㏇' => 'Co.', - '㏈' => 'dB', - '㏉' => 'Gy', - '㏊' => 'ha', - '㏋' => 'HP', - '㏌' => 'in', - '㏍' => 'KK', - '㏎' => 'KM', - '㏏' => 'kt', - '㏐' => 'lm', - '㏑' => 'ln', - '㏒' => 'log', - '㏓' => 'lx', - '㏔' => 'mb', - '㏕' => 'mil', - '㏖' => 'mol', - '㏗' => 'PH', - '㏘' => 'p.m.', - '㏙' => 'PPM', - '㏚' => 'PR', - '㏛' => 'sr', - '㏜' => 'Sv', - '㏝' => 'Wb', - '㏞' => 'V∕m', - '㏟' => 'A∕m', - '㏠' => '1日', - '㏡' => '2日', - '㏢' => '3日', - '㏣' => '4日', - '㏤' => '5日', - '㏥' => '6日', - '㏦' => '7日', - '㏧' => '8日', - '㏨' => '9日', - '㏩' => '10日', - '㏪' => '11日', - '㏫' => '12日', - '㏬' => '13日', - '㏭' => '14日', - '㏮' => '15日', - '㏯' => '16日', - '㏰' => '17日', - '㏱' => '18日', - '㏲' => '19日', - '㏳' => '20日', - '㏴' => '21日', - '㏵' => '22日', - '㏶' => '23日', - '㏷' => '24日', - '㏸' => '25日', - '㏹' => '26日', - '㏺' => '27日', - '㏻' => '28日', - '㏼' => '29日', - '㏽' => '30日', - '㏾' => '31日', - '㏿' => 'gal', - 'ꚜ' => 'ъ', - 'ꚝ' => 'ь', - 'ꝰ' => 'ꝯ', - 'ꟸ' => 'Ħ', - 'ꟹ' => 'œ', - 'ꭜ' => 'ꜧ', - 'ꭝ' => 'ꬷ', - 'ꭞ' => 'ɫ', - 'ꭟ' => 'ꭒ', - 'ꭩ' => 'ʍ', - 'ff' => 'ff', - 'fi' => 'fi', - 'fl' => 'fl', - 'ffi' => 'ffi', - 'ffl' => 'ffl', - 'ſt' => 'st', - 'st' => 'st', - 'ﬓ' => 'մն', - 'ﬔ' => 'մե', - 'ﬕ' => 'մի', - 'ﬖ' => 'վն', - 'ﬗ' => 'մխ', - 'ﬠ' => 'ע', - 'ﬡ' => 'א', - 'ﬢ' => 'ד', - 'ﬣ' => 'ה', - 'ﬤ' => 'כ', - 'ﬥ' => 'ל', - 'ﬦ' => 'ם', - 'ﬧ' => 'ר', - 'ﬨ' => 'ת', - '﬩' => '+', - 'ﭏ' => 'אל', - 'ﭐ' => 'ٱ', - 'ﭑ' => 'ٱ', - 'ﭒ' => 'ٻ', - 'ﭓ' => 'ٻ', - 'ﭔ' => 'ٻ', - 'ﭕ' => 'ٻ', - 'ﭖ' => 'پ', - 'ﭗ' => 'پ', - 'ﭘ' => 'پ', - 'ﭙ' => 'پ', - 'ﭚ' => 'ڀ', - 'ﭛ' => 'ڀ', - 'ﭜ' => 'ڀ', - 'ﭝ' => 'ڀ', - 'ﭞ' => 'ٺ', - 'ﭟ' => 'ٺ', - 'ﭠ' => 'ٺ', - 'ﭡ' => 'ٺ', - 'ﭢ' => 'ٿ', - 'ﭣ' => 'ٿ', - 'ﭤ' => 'ٿ', - 'ﭥ' => 'ٿ', - 'ﭦ' => 'ٹ', - 'ﭧ' => 'ٹ', - 'ﭨ' => 'ٹ', - 'ﭩ' => 'ٹ', - 'ﭪ' => 'ڤ', - 'ﭫ' => 'ڤ', - 'ﭬ' => 'ڤ', - 'ﭭ' => 'ڤ', - 'ﭮ' => 'ڦ', - 'ﭯ' => 'ڦ', - 'ﭰ' => 'ڦ', - 'ﭱ' => 'ڦ', - 'ﭲ' => 'ڄ', - 'ﭳ' => 'ڄ', - 'ﭴ' => 'ڄ', - 'ﭵ' => 'ڄ', - 'ﭶ' => 'ڃ', - 'ﭷ' => 'ڃ', - 'ﭸ' => 'ڃ', - 'ﭹ' => 'ڃ', - 'ﭺ' => 'چ', - 'ﭻ' => 'چ', - 'ﭼ' => 'چ', - 'ﭽ' => 'چ', - 'ﭾ' => 'ڇ', - 'ﭿ' => 'ڇ', - 'ﮀ' => 'ڇ', - 'ﮁ' => 'ڇ', - 'ﮂ' => 'ڍ', - 'ﮃ' => 'ڍ', - 'ﮄ' => 'ڌ', - 'ﮅ' => 'ڌ', - 'ﮆ' => 'ڎ', - 'ﮇ' => 'ڎ', - 'ﮈ' => 'ڈ', - 'ﮉ' => 'ڈ', - 'ﮊ' => 'ژ', - 'ﮋ' => 'ژ', - 'ﮌ' => 'ڑ', - 'ﮍ' => 'ڑ', - 'ﮎ' => 'ک', - 'ﮏ' => 'ک', - 'ﮐ' => 'ک', - 'ﮑ' => 'ک', - 'ﮒ' => 'گ', - 'ﮓ' => 'گ', - 'ﮔ' => 'گ', - 'ﮕ' => 'گ', - 'ﮖ' => 'ڳ', - 'ﮗ' => 'ڳ', - 'ﮘ' => 'ڳ', - 'ﮙ' => 'ڳ', - 'ﮚ' => 'ڱ', - 'ﮛ' => 'ڱ', - 'ﮜ' => 'ڱ', - 'ﮝ' => 'ڱ', - 'ﮞ' => 'ں', - 'ﮟ' => 'ں', - 'ﮠ' => 'ڻ', - 'ﮡ' => 'ڻ', - 'ﮢ' => 'ڻ', - 'ﮣ' => 'ڻ', - 'ﮤ' => 'ۀ', - 'ﮥ' => 'ۀ', - 'ﮦ' => 'ہ', - 'ﮧ' => 'ہ', - 'ﮨ' => 'ہ', - 'ﮩ' => 'ہ', - 'ﮪ' => 'ھ', - 'ﮫ' => 'ھ', - 'ﮬ' => 'ھ', - 'ﮭ' => 'ھ', - 'ﮮ' => 'ے', - 'ﮯ' => 'ے', - 'ﮰ' => 'ۓ', - 'ﮱ' => 'ۓ', - 'ﯓ' => 'ڭ', - 'ﯔ' => 'ڭ', - 'ﯕ' => 'ڭ', - 'ﯖ' => 'ڭ', - 'ﯗ' => 'ۇ', - 'ﯘ' => 'ۇ', - 'ﯙ' => 'ۆ', - 'ﯚ' => 'ۆ', - 'ﯛ' => 'ۈ', - 'ﯜ' => 'ۈ', - 'ﯝ' => 'ۇٴ', - 'ﯞ' => 'ۋ', - 'ﯟ' => 'ۋ', - 'ﯠ' => 'ۅ', - 'ﯡ' => 'ۅ', - 'ﯢ' => 'ۉ', - 'ﯣ' => 'ۉ', - 'ﯤ' => 'ې', - 'ﯥ' => 'ې', - 'ﯦ' => 'ې', - 'ﯧ' => 'ې', - 'ﯨ' => 'ى', - 'ﯩ' => 'ى', - 'ﯪ' => 'ئا', - 'ﯫ' => 'ئا', - 'ﯬ' => 'ئە', - 'ﯭ' => 'ئە', - 'ﯮ' => 'ئو', - 'ﯯ' => 'ئو', - 'ﯰ' => 'ئۇ', - 'ﯱ' => 'ئۇ', - 'ﯲ' => 'ئۆ', - 'ﯳ' => 'ئۆ', - 'ﯴ' => 'ئۈ', - 'ﯵ' => 'ئۈ', - 'ﯶ' => 'ئې', - 'ﯷ' => 'ئې', - 'ﯸ' => 'ئې', - 'ﯹ' => 'ئى', - 'ﯺ' => 'ئى', - 'ﯻ' => 'ئى', - 'ﯼ' => 'ی', - 'ﯽ' => 'ی', - 'ﯾ' => 'ی', - 'ﯿ' => 'ی', - 'ﰀ' => 'ئج', - 'ﰁ' => 'ئح', - 'ﰂ' => 'ئم', - 'ﰃ' => 'ئى', - 'ﰄ' => 'ئي', - 'ﰅ' => 'بج', - 'ﰆ' => 'بح', - 'ﰇ' => 'بخ', - 'ﰈ' => 'بم', - 'ﰉ' => 'بى', - 'ﰊ' => 'بي', - 'ﰋ' => 'تج', - 'ﰌ' => 'تح', - 'ﰍ' => 'تخ', - 'ﰎ' => 'تم', - 'ﰏ' => 'تى', - 'ﰐ' => 'تي', - 'ﰑ' => 'ثج', - 'ﰒ' => 'ثم', - 'ﰓ' => 'ثى', - 'ﰔ' => 'ثي', - 'ﰕ' => 'جح', - 'ﰖ' => 'جم', - 'ﰗ' => 'حج', - 'ﰘ' => 'حم', - 'ﰙ' => 'خج', - 'ﰚ' => 'خح', - 'ﰛ' => 'خم', - 'ﰜ' => 'سج', - 'ﰝ' => 'سح', - 'ﰞ' => 'سخ', - 'ﰟ' => 'سم', - 'ﰠ' => 'صح', - 'ﰡ' => 'صم', - 'ﰢ' => 'ضج', - 'ﰣ' => 'ضح', - 'ﰤ' => 'ضخ', - 'ﰥ' => 'ضم', - 'ﰦ' => 'طح', - 'ﰧ' => 'طم', - 'ﰨ' => 'ظم', - 'ﰩ' => 'عج', - 'ﰪ' => 'عم', - 'ﰫ' => 'غج', - 'ﰬ' => 'غم', - 'ﰭ' => 'فج', - 'ﰮ' => 'فح', - 'ﰯ' => 'فخ', - 'ﰰ' => 'فم', - 'ﰱ' => 'فى', - 'ﰲ' => 'في', - 'ﰳ' => 'قح', - 'ﰴ' => 'قم', - 'ﰵ' => 'قى', - 'ﰶ' => 'قي', - 'ﰷ' => 'كا', - 'ﰸ' => 'كج', - 'ﰹ' => 'كح', - 'ﰺ' => 'كخ', - 'ﰻ' => 'كل', - 'ﰼ' => 'كم', - 'ﰽ' => 'كى', - 'ﰾ' => 'كي', - 'ﰿ' => 'لج', - 'ﱀ' => 'لح', - 'ﱁ' => 'لخ', - 'ﱂ' => 'لم', - 'ﱃ' => 'لى', - 'ﱄ' => 'لي', - 'ﱅ' => 'مج', - 'ﱆ' => 'مح', - 'ﱇ' => 'مخ', - 'ﱈ' => 'مم', - 'ﱉ' => 'مى', - 'ﱊ' => 'مي', - 'ﱋ' => 'نج', - 'ﱌ' => 'نح', - 'ﱍ' => 'نخ', - 'ﱎ' => 'نم', - 'ﱏ' => 'نى', - 'ﱐ' => 'ني', - 'ﱑ' => 'هج', - 'ﱒ' => 'هم', - 'ﱓ' => 'هى', - 'ﱔ' => 'هي', - 'ﱕ' => 'يج', - 'ﱖ' => 'يح', - 'ﱗ' => 'يخ', - 'ﱘ' => 'يم', - 'ﱙ' => 'يى', - 'ﱚ' => 'يي', - 'ﱛ' => 'ذٰ', - 'ﱜ' => 'رٰ', - 'ﱝ' => 'ىٰ', - 'ﱞ' => ' ٌّ', - 'ﱟ' => ' ٍّ', - 'ﱠ' => ' َّ', - 'ﱡ' => ' ُّ', - 'ﱢ' => ' ِّ', - 'ﱣ' => ' ّٰ', - 'ﱤ' => 'ئر', - 'ﱥ' => 'ئز', - 'ﱦ' => 'ئم', - 'ﱧ' => 'ئن', - 'ﱨ' => 'ئى', - 'ﱩ' => 'ئي', - 'ﱪ' => 'بر', - 'ﱫ' => 'بز', - 'ﱬ' => 'بم', - 'ﱭ' => 'بن', - 'ﱮ' => 'بى', - 'ﱯ' => 'بي', - 'ﱰ' => 'تر', - 'ﱱ' => 'تز', - 'ﱲ' => 'تم', - 'ﱳ' => 'تن', - 'ﱴ' => 'تى', - 'ﱵ' => 'تي', - 'ﱶ' => 'ثر', - 'ﱷ' => 'ثز', - 'ﱸ' => 'ثم', - 'ﱹ' => 'ثن', - 'ﱺ' => 'ثى', - 'ﱻ' => 'ثي', - 'ﱼ' => 'فى', - 'ﱽ' => 'في', - 'ﱾ' => 'قى', - 'ﱿ' => 'قي', - 'ﲀ' => 'كا', - 'ﲁ' => 'كل', - 'ﲂ' => 'كم', - 'ﲃ' => 'كى', - 'ﲄ' => 'كي', - 'ﲅ' => 'لم', - 'ﲆ' => 'لى', - 'ﲇ' => 'لي', - 'ﲈ' => 'ما', - 'ﲉ' => 'مم', - 'ﲊ' => 'نر', - 'ﲋ' => 'نز', - 'ﲌ' => 'نم', - 'ﲍ' => 'نن', - 'ﲎ' => 'نى', - 'ﲏ' => 'ني', - 'ﲐ' => 'ىٰ', - 'ﲑ' => 'ير', - 'ﲒ' => 'يز', - 'ﲓ' => 'يم', - 'ﲔ' => 'ين', - 'ﲕ' => 'يى', - 'ﲖ' => 'يي', - 'ﲗ' => 'ئج', - 'ﲘ' => 'ئح', - 'ﲙ' => 'ئخ', - 'ﲚ' => 'ئم', - 'ﲛ' => 'ئه', - 'ﲜ' => 'بج', - 'ﲝ' => 'بح', - 'ﲞ' => 'بخ', - 'ﲟ' => 'بم', - 'ﲠ' => 'به', - 'ﲡ' => 'تج', - 'ﲢ' => 'تح', - 'ﲣ' => 'تخ', - 'ﲤ' => 'تم', - 'ﲥ' => 'ته', - 'ﲦ' => 'ثم', - 'ﲧ' => 'جح', - 'ﲨ' => 'جم', - 'ﲩ' => 'حج', - 'ﲪ' => 'حم', - 'ﲫ' => 'خج', - 'ﲬ' => 'خم', - 'ﲭ' => 'سج', - 'ﲮ' => 'سح', - 'ﲯ' => 'سخ', - 'ﲰ' => 'سم', - 'ﲱ' => 'صح', - 'ﲲ' => 'صخ', - 'ﲳ' => 'صم', - 'ﲴ' => 'ضج', - 'ﲵ' => 'ضح', - 'ﲶ' => 'ضخ', - 'ﲷ' => 'ضم', - 'ﲸ' => 'طح', - 'ﲹ' => 'ظم', - 'ﲺ' => 'عج', - 'ﲻ' => 'عم', - 'ﲼ' => 'غج', - 'ﲽ' => 'غم', - 'ﲾ' => 'فج', - 'ﲿ' => 'فح', - 'ﳀ' => 'فخ', - 'ﳁ' => 'فم', - 'ﳂ' => 'قح', - 'ﳃ' => 'قم', - 'ﳄ' => 'كج', - 'ﳅ' => 'كح', - 'ﳆ' => 'كخ', - 'ﳇ' => 'كل', - 'ﳈ' => 'كم', - 'ﳉ' => 'لج', - 'ﳊ' => 'لح', - 'ﳋ' => 'لخ', - 'ﳌ' => 'لم', - 'ﳍ' => 'له', - 'ﳎ' => 'مج', - 'ﳏ' => 'مح', - 'ﳐ' => 'مخ', - 'ﳑ' => 'مم', - 'ﳒ' => 'نج', - 'ﳓ' => 'نح', - 'ﳔ' => 'نخ', - 'ﳕ' => 'نم', - 'ﳖ' => 'نه', - 'ﳗ' => 'هج', - 'ﳘ' => 'هم', - 'ﳙ' => 'هٰ', - 'ﳚ' => 'يج', - 'ﳛ' => 'يح', - 'ﳜ' => 'يخ', - 'ﳝ' => 'يم', - 'ﳞ' => 'يه', - 'ﳟ' => 'ئم', - 'ﳠ' => 'ئه', - 'ﳡ' => 'بم', - 'ﳢ' => 'به', - 'ﳣ' => 'تم', - 'ﳤ' => 'ته', - 'ﳥ' => 'ثم', - 'ﳦ' => 'ثه', - 'ﳧ' => 'سم', - 'ﳨ' => 'سه', - 'ﳩ' => 'شم', - 'ﳪ' => 'شه', - 'ﳫ' => 'كل', - 'ﳬ' => 'كم', - 'ﳭ' => 'لم', - 'ﳮ' => 'نم', - 'ﳯ' => 'نه', - 'ﳰ' => 'يم', - 'ﳱ' => 'يه', - 'ﳲ' => 'ـَّ', - 'ﳳ' => 'ـُّ', - 'ﳴ' => 'ـِّ', - 'ﳵ' => 'طى', - 'ﳶ' => 'طي', - 'ﳷ' => 'عى', - 'ﳸ' => 'عي', - 'ﳹ' => 'غى', - 'ﳺ' => 'غي', - 'ﳻ' => 'سى', - 'ﳼ' => 'سي', - 'ﳽ' => 'شى', - 'ﳾ' => 'شي', - 'ﳿ' => 'حى', - 'ﴀ' => 'حي', - 'ﴁ' => 'جى', - 'ﴂ' => 'جي', - 'ﴃ' => 'خى', - 'ﴄ' => 'خي', - 'ﴅ' => 'صى', - 'ﴆ' => 'صي', - 'ﴇ' => 'ضى', - 'ﴈ' => 'ضي', - 'ﴉ' => 'شج', - 'ﴊ' => 'شح', - 'ﴋ' => 'شخ', - 'ﴌ' => 'شم', - 'ﴍ' => 'شر', - 'ﴎ' => 'سر', - 'ﴏ' => 'صر', - 'ﴐ' => 'ضر', - 'ﴑ' => 'طى', - 'ﴒ' => 'طي', - 'ﴓ' => 'عى', - 'ﴔ' => 'عي', - 'ﴕ' => 'غى', - 'ﴖ' => 'غي', - 'ﴗ' => 'سى', - 'ﴘ' => 'سي', - 'ﴙ' => 'شى', - 'ﴚ' => 'شي', - 'ﴛ' => 'حى', - 'ﴜ' => 'حي', - 'ﴝ' => 'جى', - 'ﴞ' => 'جي', - 'ﴟ' => 'خى', - 'ﴠ' => 'خي', - 'ﴡ' => 'صى', - 'ﴢ' => 'صي', - 'ﴣ' => 'ضى', - 'ﴤ' => 'ضي', - 'ﴥ' => 'شج', - 'ﴦ' => 'شح', - 'ﴧ' => 'شخ', - 'ﴨ' => 'شم', - 'ﴩ' => 'شر', - 'ﴪ' => 'سر', - 'ﴫ' => 'صر', - 'ﴬ' => 'ضر', - 'ﴭ' => 'شج', - 'ﴮ' => 'شح', - 'ﴯ' => 'شخ', - 'ﴰ' => 'شم', - 'ﴱ' => 'سه', - 'ﴲ' => 'شه', - 'ﴳ' => 'طم', - 'ﴴ' => 'سج', - 'ﴵ' => 'سح', - 'ﴶ' => 'سخ', - 'ﴷ' => 'شج', - 'ﴸ' => 'شح', - 'ﴹ' => 'شخ', - 'ﴺ' => 'طم', - 'ﴻ' => 'ظم', - 'ﴼ' => 'اً', - 'ﴽ' => 'اً', - 'ﵐ' => 'تجم', - 'ﵑ' => 'تحج', - 'ﵒ' => 'تحج', - 'ﵓ' => 'تحم', - 'ﵔ' => 'تخم', - 'ﵕ' => 'تمج', - 'ﵖ' => 'تمح', - 'ﵗ' => 'تمخ', - 'ﵘ' => 'جمح', - 'ﵙ' => 'جمح', - 'ﵚ' => 'حمي', - 'ﵛ' => 'حمى', - 'ﵜ' => 'سحج', - 'ﵝ' => 'سجح', - 'ﵞ' => 'سجى', - 'ﵟ' => 'سمح', - 'ﵠ' => 'سمح', - 'ﵡ' => 'سمج', - 'ﵢ' => 'سمم', - 'ﵣ' => 'سمم', - 'ﵤ' => 'صحح', - 'ﵥ' => 'صحح', - 'ﵦ' => 'صمم', - 'ﵧ' => 'شحم', - 'ﵨ' => 'شحم', - 'ﵩ' => 'شجي', - 'ﵪ' => 'شمخ', - 'ﵫ' => 'شمخ', - 'ﵬ' => 'شمم', - 'ﵭ' => 'شمم', - 'ﵮ' => 'ضحى', - 'ﵯ' => 'ضخم', - 'ﵰ' => 'ضخم', - 'ﵱ' => 'طمح', - 'ﵲ' => 'طمح', - 'ﵳ' => 'طمم', - 'ﵴ' => 'طمي', - 'ﵵ' => 'عجم', - 'ﵶ' => 'عمم', - 'ﵷ' => 'عمم', - 'ﵸ' => 'عمى', - 'ﵹ' => 'غمم', - 'ﵺ' => 'غمي', - 'ﵻ' => 'غمى', - 'ﵼ' => 'فخم', - 'ﵽ' => 'فخم', - 'ﵾ' => 'قمح', - 'ﵿ' => 'قمم', - 'ﶀ' => 'لحم', - 'ﶁ' => 'لحي', - 'ﶂ' => 'لحى', - 'ﶃ' => 'لجج', - 'ﶄ' => 'لجج', - 'ﶅ' => 'لخم', - 'ﶆ' => 'لخم', - 'ﶇ' => 'لمح', - 'ﶈ' => 'لمح', - 'ﶉ' => 'محج', - 'ﶊ' => 'محم', - 'ﶋ' => 'محي', - 'ﶌ' => 'مجح', - 'ﶍ' => 'مجم', - 'ﶎ' => 'مخج', - 'ﶏ' => 'مخم', - 'ﶒ' => 'مجخ', - 'ﶓ' => 'همج', - 'ﶔ' => 'همم', - 'ﶕ' => 'نحم', - 'ﶖ' => 'نحى', - 'ﶗ' => 'نجم', - 'ﶘ' => 'نجم', - 'ﶙ' => 'نجى', - 'ﶚ' => 'نمي', - 'ﶛ' => 'نمى', - 'ﶜ' => 'يمم', - 'ﶝ' => 'يمم', - 'ﶞ' => 'بخي', - 'ﶟ' => 'تجي', - 'ﶠ' => 'تجى', - 'ﶡ' => 'تخي', - 'ﶢ' => 'تخى', - 'ﶣ' => 'تمي', - 'ﶤ' => 'تمى', - 'ﶥ' => 'جمي', - 'ﶦ' => 'جحى', - 'ﶧ' => 'جمى', - 'ﶨ' => 'سخى', - 'ﶩ' => 'صحي', - 'ﶪ' => 'شحي', - 'ﶫ' => 'ضحي', - 'ﶬ' => 'لجي', - 'ﶭ' => 'لمي', - 'ﶮ' => 'يحي', - 'ﶯ' => 'يجي', - 'ﶰ' => 'يمي', - 'ﶱ' => 'ممي', - 'ﶲ' => 'قمي', - 'ﶳ' => 'نحي', - 'ﶴ' => 'قمح', - 'ﶵ' => 'لحم', - 'ﶶ' => 'عمي', - 'ﶷ' => 'كمي', - 'ﶸ' => 'نجح', - 'ﶹ' => 'مخي', - 'ﶺ' => 'لجم', - 'ﶻ' => 'كمم', - 'ﶼ' => 'لجم', - 'ﶽ' => 'نجح', - 'ﶾ' => 'جحي', - 'ﶿ' => 'حجي', - 'ﷀ' => 'مجي', - 'ﷁ' => 'فمي', - 'ﷂ' => 'بحي', - 'ﷃ' => 'كمم', - 'ﷄ' => 'عجم', - 'ﷅ' => 'صمم', - 'ﷆ' => 'سخي', - 'ﷇ' => 'نجي', - 'ﷰ' => 'صلے', - 'ﷱ' => 'قلے', - 'ﷲ' => 'الله', - 'ﷳ' => 'اكبر', - 'ﷴ' => 'محمد', - 'ﷵ' => 'صلعم', - 'ﷶ' => 'رسول', - 'ﷷ' => 'عليه', - 'ﷸ' => 'وسلم', - 'ﷹ' => 'صلى', - 'ﷺ' => 'صلى الله عليه وسلم', - 'ﷻ' => 'جل جلاله', - '﷼' => 'ریال', - '︐' => ',', - '︑' => '、', - '︒' => '。', - '︓' => ':', - '︔' => ';', - '︕' => '!', - '︖' => '?', - '︗' => '〖', - '︘' => '〗', - '︙' => '...', - '︰' => '..', - '︱' => '—', - '︲' => '–', - '︳' => '_', - '︴' => '_', - '︵' => '(', - '︶' => ')', - '︷' => '{', - '︸' => '}', - '︹' => '〔', - '︺' => '〕', - '︻' => '【', - '︼' => '】', - '︽' => '《', - '︾' => '》', - '︿' => '〈', - '﹀' => '〉', - '﹁' => '「', - '﹂' => '」', - '﹃' => '『', - '﹄' => '』', - '﹇' => '[', - '﹈' => ']', - '﹉' => ' ̅', - '﹊' => ' ̅', - '﹋' => ' ̅', - '﹌' => ' ̅', - '﹍' => '_', - '﹎' => '_', - '﹏' => '_', - '﹐' => ',', - '﹑' => '、', - '﹒' => '.', - '﹔' => ';', - '﹕' => ':', - '﹖' => '?', - '﹗' => '!', - '﹘' => '—', - '﹙' => '(', - '﹚' => ')', - '﹛' => '{', - '﹜' => '}', - '﹝' => '〔', - '﹞' => '〕', - '﹟' => '#', - '﹠' => '&', - '﹡' => '*', - '﹢' => '+', - '﹣' => '-', - '﹤' => '<', - '﹥' => '>', - '﹦' => '=', - '﹨' => '\\', - '﹩' => '$', - '﹪' => '%', - '﹫' => '@', - 'ﹰ' => ' ً', - 'ﹱ' => 'ـً', - 'ﹲ' => ' ٌ', - 'ﹴ' => ' ٍ', - 'ﹶ' => ' َ', - 'ﹷ' => 'ـَ', - 'ﹸ' => ' ُ', - 'ﹹ' => 'ـُ', - 'ﹺ' => ' ِ', - 'ﹻ' => 'ـِ', - 'ﹼ' => ' ّ', - 'ﹽ' => 'ـّ', - 'ﹾ' => ' ْ', - 'ﹿ' => 'ـْ', - 'ﺀ' => 'ء', - 'ﺁ' => 'آ', - 'ﺂ' => 'آ', - 'ﺃ' => 'أ', - 'ﺄ' => 'أ', - 'ﺅ' => 'ؤ', - 'ﺆ' => 'ؤ', - 'ﺇ' => 'إ', - 'ﺈ' => 'إ', - 'ﺉ' => 'ئ', - 'ﺊ' => 'ئ', - 'ﺋ' => 'ئ', - 'ﺌ' => 'ئ', - 'ﺍ' => 'ا', - 'ﺎ' => 'ا', - 'ﺏ' => 'ب', - 'ﺐ' => 'ب', - 'ﺑ' => 'ب', - 'ﺒ' => 'ب', - 'ﺓ' => 'ة', - 'ﺔ' => 'ة', - 'ﺕ' => 'ت', - 'ﺖ' => 'ت', - 'ﺗ' => 'ت', - 'ﺘ' => 'ت', - 'ﺙ' => 'ث', - 'ﺚ' => 'ث', - 'ﺛ' => 'ث', - 'ﺜ' => 'ث', - 'ﺝ' => 'ج', - 'ﺞ' => 'ج', - 'ﺟ' => 'ج', - 'ﺠ' => 'ج', - 'ﺡ' => 'ح', - 'ﺢ' => 'ح', - 'ﺣ' => 'ح', - 'ﺤ' => 'ح', - 'ﺥ' => 'خ', - 'ﺦ' => 'خ', - 'ﺧ' => 'خ', - 'ﺨ' => 'خ', - 'ﺩ' => 'د', - 'ﺪ' => 'د', - 'ﺫ' => 'ذ', - 'ﺬ' => 'ذ', - 'ﺭ' => 'ر', - 'ﺮ' => 'ر', - 'ﺯ' => 'ز', - 'ﺰ' => 'ز', - 'ﺱ' => 'س', - 'ﺲ' => 'س', - 'ﺳ' => 'س', - 'ﺴ' => 'س', - 'ﺵ' => 'ش', - 'ﺶ' => 'ش', - 'ﺷ' => 'ش', - 'ﺸ' => 'ش', - 'ﺹ' => 'ص', - 'ﺺ' => 'ص', - 'ﺻ' => 'ص', - 'ﺼ' => 'ص', - 'ﺽ' => 'ض', - 'ﺾ' => 'ض', - 'ﺿ' => 'ض', - 'ﻀ' => 'ض', - 'ﻁ' => 'ط', - 'ﻂ' => 'ط', - 'ﻃ' => 'ط', - 'ﻄ' => 'ط', - 'ﻅ' => 'ظ', - 'ﻆ' => 'ظ', - 'ﻇ' => 'ظ', - 'ﻈ' => 'ظ', - 'ﻉ' => 'ع', - 'ﻊ' => 'ع', - 'ﻋ' => 'ع', - 'ﻌ' => 'ع', - 'ﻍ' => 'غ', - 'ﻎ' => 'غ', - 'ﻏ' => 'غ', - 'ﻐ' => 'غ', - 'ﻑ' => 'ف', - 'ﻒ' => 'ف', - 'ﻓ' => 'ف', - 'ﻔ' => 'ف', - 'ﻕ' => 'ق', - 'ﻖ' => 'ق', - 'ﻗ' => 'ق', - 'ﻘ' => 'ق', - 'ﻙ' => 'ك', - 'ﻚ' => 'ك', - 'ﻛ' => 'ك', - 'ﻜ' => 'ك', - 'ﻝ' => 'ل', - 'ﻞ' => 'ل', - 'ﻟ' => 'ل', - 'ﻠ' => 'ل', - 'ﻡ' => 'م', - 'ﻢ' => 'م', - 'ﻣ' => 'م', - 'ﻤ' => 'م', - 'ﻥ' => 'ن', - 'ﻦ' => 'ن', - 'ﻧ' => 'ن', - 'ﻨ' => 'ن', - 'ﻩ' => 'ه', - 'ﻪ' => 'ه', - 'ﻫ' => 'ه', - 'ﻬ' => 'ه', - 'ﻭ' => 'و', - 'ﻮ' => 'و', - 'ﻯ' => 'ى', - 'ﻰ' => 'ى', - 'ﻱ' => 'ي', - 'ﻲ' => 'ي', - 'ﻳ' => 'ي', - 'ﻴ' => 'ي', - 'ﻵ' => 'لآ', - 'ﻶ' => 'لآ', - 'ﻷ' => 'لأ', - 'ﻸ' => 'لأ', - 'ﻹ' => 'لإ', - 'ﻺ' => 'لإ', - 'ﻻ' => 'لا', - 'ﻼ' => 'لا', - '!' => '!', - '"' => '"', - '#' => '#', - '$' => '$', - '%' => '%', - '&' => '&', - ''' => '\'', - '(' => '(', - ')' => ')', - '*' => '*', - '+' => '+', - ',' => ',', - '-' => '-', - '.' => '.', - '/' => '/', - '0' => '0', - '1' => '1', - '2' => '2', - '3' => '3', - '4' => '4', - '5' => '5', - '6' => '6', - '7' => '7', - '8' => '8', - '9' => '9', - ':' => ':', - ';' => ';', - '<' => '<', - '=' => '=', - '>' => '>', - '?' => '?', - '@' => '@', - 'A' => 'A', - 'B' => 'B', - 'C' => 'C', - 'D' => 'D', - 'E' => 'E', - 'F' => 'F', - 'G' => 'G', - 'H' => 'H', - 'I' => 'I', - 'J' => 'J', - 'K' => 'K', - 'L' => 'L', - 'M' => 'M', - 'N' => 'N', - 'O' => 'O', - 'P' => 'P', - 'Q' => 'Q', - 'R' => 'R', - 'S' => 'S', - 'T' => 'T', - 'U' => 'U', - 'V' => 'V', - 'W' => 'W', - 'X' => 'X', - 'Y' => 'Y', - 'Z' => 'Z', - '[' => '[', - '\' => '\\', - ']' => ']', - '^' => '^', - '_' => '_', - '`' => '`', - 'a' => 'a', - 'b' => 'b', - 'c' => 'c', - 'd' => 'd', - 'e' => 'e', - 'f' => 'f', - 'g' => 'g', - 'h' => 'h', - 'i' => 'i', - 'j' => 'j', - 'k' => 'k', - 'l' => 'l', - 'm' => 'm', - 'n' => 'n', - 'o' => 'o', - 'p' => 'p', - 'q' => 'q', - 'r' => 'r', - 's' => 's', - 't' => 't', - 'u' => 'u', - 'v' => 'v', - 'w' => 'w', - 'x' => 'x', - 'y' => 'y', - 'z' => 'z', - '{' => '{', - '|' => '|', - '}' => '}', - '~' => '~', - '⦅' => '⦅', - '⦆' => '⦆', - '。' => '。', - '「' => '「', - '」' => '」', - '、' => '、', - '・' => '・', - 'ヲ' => 'ヲ', - 'ァ' => 'ァ', - 'ィ' => 'ィ', - 'ゥ' => 'ゥ', - 'ェ' => 'ェ', - 'ォ' => 'ォ', - 'ャ' => 'ャ', - 'ュ' => 'ュ', - 'ョ' => 'ョ', - 'ッ' => 'ッ', - 'ー' => 'ー', - 'ア' => 'ア', - 'イ' => 'イ', - 'ウ' => 'ウ', - 'エ' => 'エ', - 'オ' => 'オ', - 'カ' => 'カ', - 'キ' => 'キ', - 'ク' => 'ク', - 'ケ' => 'ケ', - 'コ' => 'コ', - 'サ' => 'サ', - 'シ' => 'シ', - 'ス' => 'ス', - 'セ' => 'セ', - 'ソ' => 'ソ', - 'タ' => 'タ', - 'チ' => 'チ', - 'ツ' => 'ツ', - 'テ' => 'テ', - 'ト' => 'ト', - 'ナ' => 'ナ', - 'ニ' => 'ニ', - 'ヌ' => 'ヌ', - 'ネ' => 'ネ', - 'ノ' => 'ノ', - 'ハ' => 'ハ', - 'ヒ' => 'ヒ', - 'フ' => 'フ', - 'ヘ' => 'ヘ', - 'ホ' => 'ホ', - 'マ' => 'マ', - 'ミ' => 'ミ', - 'ム' => 'ム', - 'メ' => 'メ', - 'モ' => 'モ', - 'ヤ' => 'ヤ', - 'ユ' => 'ユ', - 'ヨ' => 'ヨ', - 'ラ' => 'ラ', - 'リ' => 'リ', - 'ル' => 'ル', - 'レ' => 'レ', - 'ロ' => 'ロ', - 'ワ' => 'ワ', - 'ン' => 'ン', - '゙' => '゙', - '゚' => '゚', - 'ᅠ' => 'ᅠ', - 'ᄀ' => 'ᄀ', - 'ᄁ' => 'ᄁ', - 'ᆪ' => 'ᆪ', - 'ᄂ' => 'ᄂ', - 'ᆬ' => 'ᆬ', - 'ᆭ' => 'ᆭ', - 'ᄃ' => 'ᄃ', - 'ᄄ' => 'ᄄ', - 'ᄅ' => 'ᄅ', - 'ᆰ' => 'ᆰ', - 'ᆱ' => 'ᆱ', - 'ᆲ' => 'ᆲ', - 'ᆳ' => 'ᆳ', - 'ᆴ' => 'ᆴ', - 'ᆵ' => 'ᆵ', - 'ᄚ' => 'ᄚ', - 'ᄆ' => 'ᄆ', - 'ᄇ' => 'ᄇ', - 'ᄈ' => 'ᄈ', - 'ᄡ' => 'ᄡ', - 'ᄉ' => 'ᄉ', - 'ᄊ' => 'ᄊ', - 'ᄋ' => 'ᄋ', - 'ᄌ' => 'ᄌ', - 'ᄍ' => 'ᄍ', - 'ᄎ' => 'ᄎ', - 'ᄏ' => 'ᄏ', - 'ᄐ' => 'ᄐ', - 'ᄑ' => 'ᄑ', - 'ᄒ' => 'ᄒ', - 'ᅡ' => 'ᅡ', - 'ᅢ' => 'ᅢ', - 'ᅣ' => 'ᅣ', - 'ᅤ' => 'ᅤ', - 'ᅥ' => 'ᅥ', - 'ᅦ' => 'ᅦ', - 'ᅧ' => 'ᅧ', - 'ᅨ' => 'ᅨ', - 'ᅩ' => 'ᅩ', - 'ᅪ' => 'ᅪ', - 'ᅫ' => 'ᅫ', - 'ᅬ' => 'ᅬ', - 'ᅭ' => 'ᅭ', - 'ᅮ' => 'ᅮ', - 'ᅯ' => 'ᅯ', - 'ᅰ' => 'ᅰ', - 'ᅱ' => 'ᅱ', - 'ᅲ' => 'ᅲ', - 'ᅳ' => 'ᅳ', - 'ᅴ' => 'ᅴ', - 'ᅵ' => 'ᅵ', - '¢' => '¢', - '£' => '£', - '¬' => '¬', - ' ̄' => ' ̄', - '¦' => '¦', - '¥' => '¥', - '₩' => '₩', - '│' => '│', - '←' => '←', - '↑' => '↑', - '→' => '→', - '↓' => '↓', - '■' => '■', - '○' => '○', - '𝐀' => 'A', - '𝐁' => 'B', - '𝐂' => 'C', - '𝐃' => 'D', - '𝐄' => 'E', - '𝐅' => 'F', - '𝐆' => 'G', - '𝐇' => 'H', - '𝐈' => 'I', - '𝐉' => 'J', - '𝐊' => 'K', - '𝐋' => 'L', - '𝐌' => 'M', - '𝐍' => 'N', - '𝐎' => 'O', - '𝐏' => 'P', - '𝐐' => 'Q', - '𝐑' => 'R', - '𝐒' => 'S', - '𝐓' => 'T', - '𝐔' => 'U', - '𝐕' => 'V', - '𝐖' => 'W', - '𝐗' => 'X', - '𝐘' => 'Y', - '𝐙' => 'Z', - '𝐚' => 'a', - '𝐛' => 'b', - '𝐜' => 'c', - '𝐝' => 'd', - '𝐞' => 'e', - '𝐟' => 'f', - '𝐠' => 'g', - '𝐡' => 'h', - '𝐢' => 'i', - '𝐣' => 'j', - '𝐤' => 'k', - '𝐥' => 'l', - '𝐦' => 'm', - '𝐧' => 'n', - '𝐨' => 'o', - '𝐩' => 'p', - '𝐪' => 'q', - '𝐫' => 'r', - '𝐬' => 's', - '𝐭' => 't', - '𝐮' => 'u', - '𝐯' => 'v', - '𝐰' => 'w', - '𝐱' => 'x', - '𝐲' => 'y', - '𝐳' => 'z', - '𝐴' => 'A', - '𝐵' => 'B', - '𝐶' => 'C', - '𝐷' => 'D', - '𝐸' => 'E', - '𝐹' => 'F', - '𝐺' => 'G', - '𝐻' => 'H', - '𝐼' => 'I', - '𝐽' => 'J', - '𝐾' => 'K', - '𝐿' => 'L', - '𝑀' => 'M', - '𝑁' => 'N', - '𝑂' => 'O', - '𝑃' => 'P', - '𝑄' => 'Q', - '𝑅' => 'R', - '𝑆' => 'S', - '𝑇' => 'T', - '𝑈' => 'U', - '𝑉' => 'V', - '𝑊' => 'W', - '𝑋' => 'X', - '𝑌' => 'Y', - '𝑍' => 'Z', - '𝑎' => 'a', - '𝑏' => 'b', - '𝑐' => 'c', - '𝑑' => 'd', - '𝑒' => 'e', - '𝑓' => 'f', - '𝑔' => 'g', - '𝑖' => 'i', - '𝑗' => 'j', - '𝑘' => 'k', - '𝑙' => 'l', - '𝑚' => 'm', - '𝑛' => 'n', - '𝑜' => 'o', - '𝑝' => 'p', - '𝑞' => 'q', - '𝑟' => 'r', - '𝑠' => 's', - '𝑡' => 't', - '𝑢' => 'u', - '𝑣' => 'v', - '𝑤' => 'w', - '𝑥' => 'x', - '𝑦' => 'y', - '𝑧' => 'z', - '𝑨' => 'A', - '𝑩' => 'B', - '𝑪' => 'C', - '𝑫' => 'D', - '𝑬' => 'E', - '𝑭' => 'F', - '𝑮' => 'G', - '𝑯' => 'H', - '𝑰' => 'I', - '𝑱' => 'J', - '𝑲' => 'K', - '𝑳' => 'L', - '𝑴' => 'M', - '𝑵' => 'N', - '𝑶' => 'O', - '𝑷' => 'P', - '𝑸' => 'Q', - '𝑹' => 'R', - '𝑺' => 'S', - '𝑻' => 'T', - '𝑼' => 'U', - '𝑽' => 'V', - '𝑾' => 'W', - '𝑿' => 'X', - '𝒀' => 'Y', - '𝒁' => 'Z', - '𝒂' => 'a', - '𝒃' => 'b', - '𝒄' => 'c', - '𝒅' => 'd', - '𝒆' => 'e', - '𝒇' => 'f', - '𝒈' => 'g', - '𝒉' => 'h', - '𝒊' => 'i', - '𝒋' => 'j', - '𝒌' => 'k', - '𝒍' => 'l', - '𝒎' => 'm', - '𝒏' => 'n', - '𝒐' => 'o', - '𝒑' => 'p', - '𝒒' => 'q', - '𝒓' => 'r', - '𝒔' => 's', - '𝒕' => 't', - '𝒖' => 'u', - '𝒗' => 'v', - '𝒘' => 'w', - '𝒙' => 'x', - '𝒚' => 'y', - '𝒛' => 'z', - '𝒜' => 'A', - '𝒞' => 'C', - '𝒟' => 'D', - '𝒢' => 'G', - '𝒥' => 'J', - '𝒦' => 'K', - '𝒩' => 'N', - '𝒪' => 'O', - '𝒫' => 'P', - '𝒬' => 'Q', - '𝒮' => 'S', - '𝒯' => 'T', - '𝒰' => 'U', - '𝒱' => 'V', - '𝒲' => 'W', - '𝒳' => 'X', - '𝒴' => 'Y', - '𝒵' => 'Z', - '𝒶' => 'a', - '𝒷' => 'b', - '𝒸' => 'c', - '𝒹' => 'd', - '𝒻' => 'f', - '𝒽' => 'h', - '𝒾' => 'i', - '𝒿' => 'j', - '𝓀' => 'k', - '𝓁' => 'l', - '𝓂' => 'm', - '𝓃' => 'n', - '𝓅' => 'p', - '𝓆' => 'q', - '𝓇' => 'r', - '𝓈' => 's', - '𝓉' => 't', - '𝓊' => 'u', - '𝓋' => 'v', - '𝓌' => 'w', - '𝓍' => 'x', - '𝓎' => 'y', - '𝓏' => 'z', - '𝓐' => 'A', - '𝓑' => 'B', - '𝓒' => 'C', - '𝓓' => 'D', - '𝓔' => 'E', - '𝓕' => 'F', - '𝓖' => 'G', - '𝓗' => 'H', - '𝓘' => 'I', - '𝓙' => 'J', - '𝓚' => 'K', - '𝓛' => 'L', - '𝓜' => 'M', - '𝓝' => 'N', - '𝓞' => 'O', - '𝓟' => 'P', - '𝓠' => 'Q', - '𝓡' => 'R', - '𝓢' => 'S', - '𝓣' => 'T', - '𝓤' => 'U', - '𝓥' => 'V', - '𝓦' => 'W', - '𝓧' => 'X', - '𝓨' => 'Y', - '𝓩' => 'Z', - '𝓪' => 'a', - '𝓫' => 'b', - '𝓬' => 'c', - '𝓭' => 'd', - '𝓮' => 'e', - '𝓯' => 'f', - '𝓰' => 'g', - '𝓱' => 'h', - '𝓲' => 'i', - '𝓳' => 'j', - '𝓴' => 'k', - '𝓵' => 'l', - '𝓶' => 'm', - '𝓷' => 'n', - '𝓸' => 'o', - '𝓹' => 'p', - '𝓺' => 'q', - '𝓻' => 'r', - '𝓼' => 's', - '𝓽' => 't', - '𝓾' => 'u', - '𝓿' => 'v', - '𝔀' => 'w', - '𝔁' => 'x', - '𝔂' => 'y', - '𝔃' => 'z', - '𝔄' => 'A', - '𝔅' => 'B', - '𝔇' => 'D', - '𝔈' => 'E', - '𝔉' => 'F', - '𝔊' => 'G', - '𝔍' => 'J', - '𝔎' => 'K', - '𝔏' => 'L', - '𝔐' => 'M', - '𝔑' => 'N', - '𝔒' => 'O', - '𝔓' => 'P', - '𝔔' => 'Q', - '𝔖' => 'S', - '𝔗' => 'T', - '𝔘' => 'U', - '𝔙' => 'V', - '𝔚' => 'W', - '𝔛' => 'X', - '𝔜' => 'Y', - '𝔞' => 'a', - '𝔟' => 'b', - '𝔠' => 'c', - '𝔡' => 'd', - '𝔢' => 'e', - '𝔣' => 'f', - '𝔤' => 'g', - '𝔥' => 'h', - '𝔦' => 'i', - '𝔧' => 'j', - '𝔨' => 'k', - '𝔩' => 'l', - '𝔪' => 'm', - '𝔫' => 'n', - '𝔬' => 'o', - '𝔭' => 'p', - '𝔮' => 'q', - '𝔯' => 'r', - '𝔰' => 's', - '𝔱' => 't', - '𝔲' => 'u', - '𝔳' => 'v', - '𝔴' => 'w', - '𝔵' => 'x', - '𝔶' => 'y', - '𝔷' => 'z', - '𝔸' => 'A', - '𝔹' => 'B', - '𝔻' => 'D', - '𝔼' => 'E', - '𝔽' => 'F', - '𝔾' => 'G', - '𝕀' => 'I', - '𝕁' => 'J', - '𝕂' => 'K', - '𝕃' => 'L', - '𝕄' => 'M', - '𝕆' => 'O', - '𝕊' => 'S', - '𝕋' => 'T', - '𝕌' => 'U', - '𝕍' => 'V', - '𝕎' => 'W', - '𝕏' => 'X', - '𝕐' => 'Y', - '𝕒' => 'a', - '𝕓' => 'b', - '𝕔' => 'c', - '𝕕' => 'd', - '𝕖' => 'e', - '𝕗' => 'f', - '𝕘' => 'g', - '𝕙' => 'h', - '𝕚' => 'i', - '𝕛' => 'j', - '𝕜' => 'k', - '𝕝' => 'l', - '𝕞' => 'm', - '𝕟' => 'n', - '𝕠' => 'o', - '𝕡' => 'p', - '𝕢' => 'q', - '𝕣' => 'r', - '𝕤' => 's', - '𝕥' => 't', - '𝕦' => 'u', - '𝕧' => 'v', - '𝕨' => 'w', - '𝕩' => 'x', - '𝕪' => 'y', - '𝕫' => 'z', - '𝕬' => 'A', - '𝕭' => 'B', - '𝕮' => 'C', - '𝕯' => 'D', - '𝕰' => 'E', - '𝕱' => 'F', - '𝕲' => 'G', - '𝕳' => 'H', - '𝕴' => 'I', - '𝕵' => 'J', - '𝕶' => 'K', - '𝕷' => 'L', - '𝕸' => 'M', - '𝕹' => 'N', - '𝕺' => 'O', - '𝕻' => 'P', - '𝕼' => 'Q', - '𝕽' => 'R', - '𝕾' => 'S', - '𝕿' => 'T', - '𝖀' => 'U', - '𝖁' => 'V', - '𝖂' => 'W', - '𝖃' => 'X', - '𝖄' => 'Y', - '𝖅' => 'Z', - '𝖆' => 'a', - '𝖇' => 'b', - '𝖈' => 'c', - '𝖉' => 'd', - '𝖊' => 'e', - '𝖋' => 'f', - '𝖌' => 'g', - '𝖍' => 'h', - '𝖎' => 'i', - '𝖏' => 'j', - '𝖐' => 'k', - '𝖑' => 'l', - '𝖒' => 'm', - '𝖓' => 'n', - '𝖔' => 'o', - '𝖕' => 'p', - '𝖖' => 'q', - '𝖗' => 'r', - '𝖘' => 's', - '𝖙' => 't', - '𝖚' => 'u', - '𝖛' => 'v', - '𝖜' => 'w', - '𝖝' => 'x', - '𝖞' => 'y', - '𝖟' => 'z', - '𝖠' => 'A', - '𝖡' => 'B', - '𝖢' => 'C', - '𝖣' => 'D', - '𝖤' => 'E', - '𝖥' => 'F', - '𝖦' => 'G', - '𝖧' => 'H', - '𝖨' => 'I', - '𝖩' => 'J', - '𝖪' => 'K', - '𝖫' => 'L', - '𝖬' => 'M', - '𝖭' => 'N', - '𝖮' => 'O', - '𝖯' => 'P', - '𝖰' => 'Q', - '𝖱' => 'R', - '𝖲' => 'S', - '𝖳' => 'T', - '𝖴' => 'U', - '𝖵' => 'V', - '𝖶' => 'W', - '𝖷' => 'X', - '𝖸' => 'Y', - '𝖹' => 'Z', - '𝖺' => 'a', - '𝖻' => 'b', - '𝖼' => 'c', - '𝖽' => 'd', - '𝖾' => 'e', - '𝖿' => 'f', - '𝗀' => 'g', - '𝗁' => 'h', - '𝗂' => 'i', - '𝗃' => 'j', - '𝗄' => 'k', - '𝗅' => 'l', - '𝗆' => 'm', - '𝗇' => 'n', - '𝗈' => 'o', - '𝗉' => 'p', - '𝗊' => 'q', - '𝗋' => 'r', - '𝗌' => 's', - '𝗍' => 't', - '𝗎' => 'u', - '𝗏' => 'v', - '𝗐' => 'w', - '𝗑' => 'x', - '𝗒' => 'y', - '𝗓' => 'z', - '𝗔' => 'A', - '𝗕' => 'B', - '𝗖' => 'C', - '𝗗' => 'D', - '𝗘' => 'E', - '𝗙' => 'F', - '𝗚' => 'G', - '𝗛' => 'H', - '𝗜' => 'I', - '𝗝' => 'J', - '𝗞' => 'K', - '𝗟' => 'L', - '𝗠' => 'M', - '𝗡' => 'N', - '𝗢' => 'O', - '𝗣' => 'P', - '𝗤' => 'Q', - '𝗥' => 'R', - '𝗦' => 'S', - '𝗧' => 'T', - '𝗨' => 'U', - '𝗩' => 'V', - '𝗪' => 'W', - '𝗫' => 'X', - '𝗬' => 'Y', - '𝗭' => 'Z', - '𝗮' => 'a', - '𝗯' => 'b', - '𝗰' => 'c', - '𝗱' => 'd', - '𝗲' => 'e', - '𝗳' => 'f', - '𝗴' => 'g', - '𝗵' => 'h', - '𝗶' => 'i', - '𝗷' => 'j', - '𝗸' => 'k', - '𝗹' => 'l', - '𝗺' => 'm', - '𝗻' => 'n', - '𝗼' => 'o', - '𝗽' => 'p', - '𝗾' => 'q', - '𝗿' => 'r', - '𝘀' => 's', - '𝘁' => 't', - '𝘂' => 'u', - '𝘃' => 'v', - '𝘄' => 'w', - '𝘅' => 'x', - '𝘆' => 'y', - '𝘇' => 'z', - '𝘈' => 'A', - '𝘉' => 'B', - '𝘊' => 'C', - '𝘋' => 'D', - '𝘌' => 'E', - '𝘍' => 'F', - '𝘎' => 'G', - '𝘏' => 'H', - '𝘐' => 'I', - '𝘑' => 'J', - '𝘒' => 'K', - '𝘓' => 'L', - '𝘔' => 'M', - '𝘕' => 'N', - '𝘖' => 'O', - '𝘗' => 'P', - '𝘘' => 'Q', - '𝘙' => 'R', - '𝘚' => 'S', - '𝘛' => 'T', - '𝘜' => 'U', - '𝘝' => 'V', - '𝘞' => 'W', - '𝘟' => 'X', - '𝘠' => 'Y', - '𝘡' => 'Z', - '𝘢' => 'a', - '𝘣' => 'b', - '𝘤' => 'c', - '𝘥' => 'd', - '𝘦' => 'e', - '𝘧' => 'f', - '𝘨' => 'g', - '𝘩' => 'h', - '𝘪' => 'i', - '𝘫' => 'j', - '𝘬' => 'k', - '𝘭' => 'l', - '𝘮' => 'm', - '𝘯' => 'n', - '𝘰' => 'o', - '𝘱' => 'p', - '𝘲' => 'q', - '𝘳' => 'r', - '𝘴' => 's', - '𝘵' => 't', - '𝘶' => 'u', - '𝘷' => 'v', - '𝘸' => 'w', - '𝘹' => 'x', - '𝘺' => 'y', - '𝘻' => 'z', - '𝘼' => 'A', - '𝘽' => 'B', - '𝘾' => 'C', - '𝘿' => 'D', - '𝙀' => 'E', - '𝙁' => 'F', - '𝙂' => 'G', - '𝙃' => 'H', - '𝙄' => 'I', - '𝙅' => 'J', - '𝙆' => 'K', - '𝙇' => 'L', - '𝙈' => 'M', - '𝙉' => 'N', - '𝙊' => 'O', - '𝙋' => 'P', - '𝙌' => 'Q', - '𝙍' => 'R', - '𝙎' => 'S', - '𝙏' => 'T', - '𝙐' => 'U', - '𝙑' => 'V', - '𝙒' => 'W', - '𝙓' => 'X', - '𝙔' => 'Y', - '𝙕' => 'Z', - '𝙖' => 'a', - '𝙗' => 'b', - '𝙘' => 'c', - '𝙙' => 'd', - '𝙚' => 'e', - '𝙛' => 'f', - '𝙜' => 'g', - '𝙝' => 'h', - '𝙞' => 'i', - '𝙟' => 'j', - '𝙠' => 'k', - '𝙡' => 'l', - '𝙢' => 'm', - '𝙣' => 'n', - '𝙤' => 'o', - '𝙥' => 'p', - '𝙦' => 'q', - '𝙧' => 'r', - '𝙨' => 's', - '𝙩' => 't', - '𝙪' => 'u', - '𝙫' => 'v', - '𝙬' => 'w', - '𝙭' => 'x', - '𝙮' => 'y', - '𝙯' => 'z', - '𝙰' => 'A', - '𝙱' => 'B', - '𝙲' => 'C', - '𝙳' => 'D', - '𝙴' => 'E', - '𝙵' => 'F', - '𝙶' => 'G', - '𝙷' => 'H', - '𝙸' => 'I', - '𝙹' => 'J', - '𝙺' => 'K', - '𝙻' => 'L', - '𝙼' => 'M', - '𝙽' => 'N', - '𝙾' => 'O', - '𝙿' => 'P', - '𝚀' => 'Q', - '𝚁' => 'R', - '𝚂' => 'S', - '𝚃' => 'T', - '𝚄' => 'U', - '𝚅' => 'V', - '𝚆' => 'W', - '𝚇' => 'X', - '𝚈' => 'Y', - '𝚉' => 'Z', - '𝚊' => 'a', - '𝚋' => 'b', - '𝚌' => 'c', - '𝚍' => 'd', - '𝚎' => 'e', - '𝚏' => 'f', - '𝚐' => 'g', - '𝚑' => 'h', - '𝚒' => 'i', - '𝚓' => 'j', - '𝚔' => 'k', - '𝚕' => 'l', - '𝚖' => 'm', - '𝚗' => 'n', - '𝚘' => 'o', - '𝚙' => 'p', - '𝚚' => 'q', - '𝚛' => 'r', - '𝚜' => 's', - '𝚝' => 't', - '𝚞' => 'u', - '𝚟' => 'v', - '𝚠' => 'w', - '𝚡' => 'x', - '𝚢' => 'y', - '𝚣' => 'z', - '𝚤' => 'ı', - '𝚥' => 'ȷ', - '𝚨' => 'Α', - '𝚩' => 'Β', - '𝚪' => 'Γ', - '𝚫' => 'Δ', - '𝚬' => 'Ε', - '𝚭' => 'Ζ', - '𝚮' => 'Η', - '𝚯' => 'Θ', - '𝚰' => 'Ι', - '𝚱' => 'Κ', - '𝚲' => 'Λ', - '𝚳' => 'Μ', - '𝚴' => 'Ν', - '𝚵' => 'Ξ', - '𝚶' => 'Ο', - '𝚷' => 'Π', - '𝚸' => 'Ρ', - '𝚹' => 'Θ', - '𝚺' => 'Σ', - '𝚻' => 'Τ', - '𝚼' => 'Υ', - '𝚽' => 'Φ', - '𝚾' => 'Χ', - '𝚿' => 'Ψ', - '𝛀' => 'Ω', - '𝛁' => '∇', - '𝛂' => 'α', - '𝛃' => 'β', - '𝛄' => 'γ', - '𝛅' => 'δ', - '𝛆' => 'ε', - '𝛇' => 'ζ', - '𝛈' => 'η', - '𝛉' => 'θ', - '𝛊' => 'ι', - '𝛋' => 'κ', - '𝛌' => 'λ', - '𝛍' => 'μ', - '𝛎' => 'ν', - '𝛏' => 'ξ', - '𝛐' => 'ο', - '𝛑' => 'π', - '𝛒' => 'ρ', - '𝛓' => 'ς', - '𝛔' => 'σ', - '𝛕' => 'τ', - '𝛖' => 'υ', - '𝛗' => 'φ', - '𝛘' => 'χ', - '𝛙' => 'ψ', - '𝛚' => 'ω', - '𝛛' => '∂', - '𝛜' => 'ε', - '𝛝' => 'θ', - '𝛞' => 'κ', - '𝛟' => 'φ', - '𝛠' => 'ρ', - '𝛡' => 'π', - '𝛢' => 'Α', - '𝛣' => 'Β', - '𝛤' => 'Γ', - '𝛥' => 'Δ', - '𝛦' => 'Ε', - '𝛧' => 'Ζ', - '𝛨' => 'Η', - '𝛩' => 'Θ', - '𝛪' => 'Ι', - '𝛫' => 'Κ', - '𝛬' => 'Λ', - '𝛭' => 'Μ', - '𝛮' => 'Ν', - '𝛯' => 'Ξ', - '𝛰' => 'Ο', - '𝛱' => 'Π', - '𝛲' => 'Ρ', - '𝛳' => 'Θ', - '𝛴' => 'Σ', - '𝛵' => 'Τ', - '𝛶' => 'Υ', - '𝛷' => 'Φ', - '𝛸' => 'Χ', - '𝛹' => 'Ψ', - '𝛺' => 'Ω', - '𝛻' => '∇', - '𝛼' => 'α', - '𝛽' => 'β', - '𝛾' => 'γ', - '𝛿' => 'δ', - '𝜀' => 'ε', - '𝜁' => 'ζ', - '𝜂' => 'η', - '𝜃' => 'θ', - '𝜄' => 'ι', - '𝜅' => 'κ', - '𝜆' => 'λ', - '𝜇' => 'μ', - '𝜈' => 'ν', - '𝜉' => 'ξ', - '𝜊' => 'ο', - '𝜋' => 'π', - '𝜌' => 'ρ', - '𝜍' => 'ς', - '𝜎' => 'σ', - '𝜏' => 'τ', - '𝜐' => 'υ', - '𝜑' => 'φ', - '𝜒' => 'χ', - '𝜓' => 'ψ', - '𝜔' => 'ω', - '𝜕' => '∂', - '𝜖' => 'ε', - '𝜗' => 'θ', - '𝜘' => 'κ', - '𝜙' => 'φ', - '𝜚' => 'ρ', - '𝜛' => 'π', - '𝜜' => 'Α', - '𝜝' => 'Β', - '𝜞' => 'Γ', - '𝜟' => 'Δ', - '𝜠' => 'Ε', - '𝜡' => 'Ζ', - '𝜢' => 'Η', - '𝜣' => 'Θ', - '𝜤' => 'Ι', - '𝜥' => 'Κ', - '𝜦' => 'Λ', - '𝜧' => 'Μ', - '𝜨' => 'Ν', - '𝜩' => 'Ξ', - '𝜪' => 'Ο', - '𝜫' => 'Π', - '𝜬' => 'Ρ', - '𝜭' => 'Θ', - '𝜮' => 'Σ', - '𝜯' => 'Τ', - '𝜰' => 'Υ', - '𝜱' => 'Φ', - '𝜲' => 'Χ', - '𝜳' => 'Ψ', - '𝜴' => 'Ω', - '𝜵' => '∇', - '𝜶' => 'α', - '𝜷' => 'β', - '𝜸' => 'γ', - '𝜹' => 'δ', - '𝜺' => 'ε', - '𝜻' => 'ζ', - '𝜼' => 'η', - '𝜽' => 'θ', - '𝜾' => 'ι', - '𝜿' => 'κ', - '𝝀' => 'λ', - '𝝁' => 'μ', - '𝝂' => 'ν', - '𝝃' => 'ξ', - '𝝄' => 'ο', - '𝝅' => 'π', - '𝝆' => 'ρ', - '𝝇' => 'ς', - '𝝈' => 'σ', - '𝝉' => 'τ', - '𝝊' => 'υ', - '𝝋' => 'φ', - '𝝌' => 'χ', - '𝝍' => 'ψ', - '𝝎' => 'ω', - '𝝏' => '∂', - '𝝐' => 'ε', - '𝝑' => 'θ', - '𝝒' => 'κ', - '𝝓' => 'φ', - '𝝔' => 'ρ', - '𝝕' => 'π', - '𝝖' => 'Α', - '𝝗' => 'Β', - '𝝘' => 'Γ', - '𝝙' => 'Δ', - '𝝚' => 'Ε', - '𝝛' => 'Ζ', - '𝝜' => 'Η', - '𝝝' => 'Θ', - '𝝞' => 'Ι', - '𝝟' => 'Κ', - '𝝠' => 'Λ', - '𝝡' => 'Μ', - '𝝢' => 'Ν', - '𝝣' => 'Ξ', - '𝝤' => 'Ο', - '𝝥' => 'Π', - '𝝦' => 'Ρ', - '𝝧' => 'Θ', - '𝝨' => 'Σ', - '𝝩' => 'Τ', - '𝝪' => 'Υ', - '𝝫' => 'Φ', - '𝝬' => 'Χ', - '𝝭' => 'Ψ', - '𝝮' => 'Ω', - '𝝯' => '∇', - '𝝰' => 'α', - '𝝱' => 'β', - '𝝲' => 'γ', - '𝝳' => 'δ', - '𝝴' => 'ε', - '𝝵' => 'ζ', - '𝝶' => 'η', - '𝝷' => 'θ', - '𝝸' => 'ι', - '𝝹' => 'κ', - '𝝺' => 'λ', - '𝝻' => 'μ', - '𝝼' => 'ν', - '𝝽' => 'ξ', - '𝝾' => 'ο', - '𝝿' => 'π', - '𝞀' => 'ρ', - '𝞁' => 'ς', - '𝞂' => 'σ', - '𝞃' => 'τ', - '𝞄' => 'υ', - '𝞅' => 'φ', - '𝞆' => 'χ', - '𝞇' => 'ψ', - '𝞈' => 'ω', - '𝞉' => '∂', - '𝞊' => 'ε', - '𝞋' => 'θ', - '𝞌' => 'κ', - '𝞍' => 'φ', - '𝞎' => 'ρ', - '𝞏' => 'π', - '𝞐' => 'Α', - '𝞑' => 'Β', - '𝞒' => 'Γ', - '𝞓' => 'Δ', - '𝞔' => 'Ε', - '𝞕' => 'Ζ', - '𝞖' => 'Η', - '𝞗' => 'Θ', - '𝞘' => 'Ι', - '𝞙' => 'Κ', - '𝞚' => 'Λ', - '𝞛' => 'Μ', - '𝞜' => 'Ν', - '𝞝' => 'Ξ', - '𝞞' => 'Ο', - '𝞟' => 'Π', - '𝞠' => 'Ρ', - '𝞡' => 'Θ', - '𝞢' => 'Σ', - '𝞣' => 'Τ', - '𝞤' => 'Υ', - '𝞥' => 'Φ', - '𝞦' => 'Χ', - '𝞧' => 'Ψ', - '𝞨' => 'Ω', - '𝞩' => '∇', - '𝞪' => 'α', - '𝞫' => 'β', - '𝞬' => 'γ', - '𝞭' => 'δ', - '𝞮' => 'ε', - '𝞯' => 'ζ', - '𝞰' => 'η', - '𝞱' => 'θ', - '𝞲' => 'ι', - '𝞳' => 'κ', - '𝞴' => 'λ', - '𝞵' => 'μ', - '𝞶' => 'ν', - '𝞷' => 'ξ', - '𝞸' => 'ο', - '𝞹' => 'π', - '𝞺' => 'ρ', - '𝞻' => 'ς', - '𝞼' => 'σ', - '𝞽' => 'τ', - '𝞾' => 'υ', - '𝞿' => 'φ', - '𝟀' => 'χ', - '𝟁' => 'ψ', - '𝟂' => 'ω', - '𝟃' => '∂', - '𝟄' => 'ε', - '𝟅' => 'θ', - '𝟆' => 'κ', - '𝟇' => 'φ', - '𝟈' => 'ρ', - '𝟉' => 'π', - '𝟊' => 'Ϝ', - '𝟋' => 'ϝ', - '𝟎' => '0', - '𝟏' => '1', - '𝟐' => '2', - '𝟑' => '3', - '𝟒' => '4', - '𝟓' => '5', - '𝟔' => '6', - '𝟕' => '7', - '𝟖' => '8', - '𝟗' => '9', - '𝟘' => '0', - '𝟙' => '1', - '𝟚' => '2', - '𝟛' => '3', - '𝟜' => '4', - '𝟝' => '5', - '𝟞' => '6', - '𝟟' => '7', - '𝟠' => '8', - '𝟡' => '9', - '𝟢' => '0', - '𝟣' => '1', - '𝟤' => '2', - '𝟥' => '3', - '𝟦' => '4', - '𝟧' => '5', - '𝟨' => '6', - '𝟩' => '7', - '𝟪' => '8', - '𝟫' => '9', - '𝟬' => '0', - '𝟭' => '1', - '𝟮' => '2', - '𝟯' => '3', - '𝟰' => '4', - '𝟱' => '5', - '𝟲' => '6', - '𝟳' => '7', - '𝟴' => '8', - '𝟵' => '9', - '𝟶' => '0', - '𝟷' => '1', - '𝟸' => '2', - '𝟹' => '3', - '𝟺' => '4', - '𝟻' => '5', - '𝟼' => '6', - '𝟽' => '7', - '𝟾' => '8', - '𝟿' => '9', - '𞸀' => 'ا', - '𞸁' => 'ب', - '𞸂' => 'ج', - '𞸃' => 'د', - '𞸅' => 'و', - '𞸆' => 'ز', - '𞸇' => 'ح', - '𞸈' => 'ط', - '𞸉' => 'ي', - '𞸊' => 'ك', - '𞸋' => 'ل', - '𞸌' => 'م', - '𞸍' => 'ن', - '𞸎' => 'س', - '𞸏' => 'ع', - '𞸐' => 'ف', - '𞸑' => 'ص', - '𞸒' => 'ق', - '𞸓' => 'ر', - '𞸔' => 'ش', - '𞸕' => 'ت', - '𞸖' => 'ث', - '𞸗' => 'خ', - '𞸘' => 'ذ', - '𞸙' => 'ض', - '𞸚' => 'ظ', - '𞸛' => 'غ', - '𞸜' => 'ٮ', - '𞸝' => 'ں', - '𞸞' => 'ڡ', - '𞸟' => 'ٯ', - '𞸡' => 'ب', - '𞸢' => 'ج', - '𞸤' => 'ه', - '𞸧' => 'ح', - '𞸩' => 'ي', - '𞸪' => 'ك', - '𞸫' => 'ل', - '𞸬' => 'م', - '𞸭' => 'ن', - '𞸮' => 'س', - '𞸯' => 'ع', - '𞸰' => 'ف', - '𞸱' => 'ص', - '𞸲' => 'ق', - '𞸴' => 'ش', - '𞸵' => 'ت', - '𞸶' => 'ث', - '𞸷' => 'خ', - '𞸹' => 'ض', - '𞸻' => 'غ', - '𞹂' => 'ج', - '𞹇' => 'ح', - '𞹉' => 'ي', - '𞹋' => 'ل', - '𞹍' => 'ن', - '𞹎' => 'س', - '𞹏' => 'ع', - '𞹑' => 'ص', - '𞹒' => 'ق', - '𞹔' => 'ش', - '𞹗' => 'خ', - '𞹙' => 'ض', - '𞹛' => 'غ', - '𞹝' => 'ں', - '𞹟' => 'ٯ', - '𞹡' => 'ب', - '𞹢' => 'ج', - '𞹤' => 'ه', - '𞹧' => 'ح', - '𞹨' => 'ط', - '𞹩' => 'ي', - '𞹪' => 'ك', - '𞹬' => 'م', - '𞹭' => 'ن', - '𞹮' => 'س', - '𞹯' => 'ع', - '𞹰' => 'ف', - '𞹱' => 'ص', - '𞹲' => 'ق', - '𞹴' => 'ش', - '𞹵' => 'ت', - '𞹶' => 'ث', - '𞹷' => 'خ', - '𞹹' => 'ض', - '𞹺' => 'ظ', - '𞹻' => 'غ', - '𞹼' => 'ٮ', - '𞹾' => 'ڡ', - '𞺀' => 'ا', - '𞺁' => 'ب', - '𞺂' => 'ج', - '𞺃' => 'د', - '𞺄' => 'ه', - '𞺅' => 'و', - '𞺆' => 'ز', - '𞺇' => 'ح', - '𞺈' => 'ط', - '𞺉' => 'ي', - '𞺋' => 'ل', - '𞺌' => 'م', - '𞺍' => 'ن', - '𞺎' => 'س', - '𞺏' => 'ع', - '𞺐' => 'ف', - '𞺑' => 'ص', - '𞺒' => 'ق', - '𞺓' => 'ر', - '𞺔' => 'ش', - '𞺕' => 'ت', - '𞺖' => 'ث', - '𞺗' => 'خ', - '𞺘' => 'ذ', - '𞺙' => 'ض', - '𞺚' => 'ظ', - '𞺛' => 'غ', - '𞺡' => 'ب', - '𞺢' => 'ج', - '𞺣' => 'د', - '𞺥' => 'و', - '𞺦' => 'ز', - '𞺧' => 'ح', - '𞺨' => 'ط', - '𞺩' => 'ي', - '𞺫' => 'ل', - '𞺬' => 'م', - '𞺭' => 'ن', - '𞺮' => 'س', - '𞺯' => 'ع', - '𞺰' => 'ف', - '𞺱' => 'ص', - '𞺲' => 'ق', - '𞺳' => 'ر', - '𞺴' => 'ش', - '𞺵' => 'ت', - '𞺶' => 'ث', - '𞺷' => 'خ', - '𞺸' => 'ذ', - '𞺹' => 'ض', - '𞺺' => 'ظ', - '𞺻' => 'غ', - '🄀' => '0.', - '🄁' => '0,', - '🄂' => '1,', - '🄃' => '2,', - '🄄' => '3,', - '🄅' => '4,', - '🄆' => '5,', - '🄇' => '6,', - '🄈' => '7,', - '🄉' => '8,', - '🄊' => '9,', - '🄐' => '(A)', - '🄑' => '(B)', - '🄒' => '(C)', - '🄓' => '(D)', - '🄔' => '(E)', - '🄕' => '(F)', - '🄖' => '(G)', - '🄗' => '(H)', - '🄘' => '(I)', - '🄙' => '(J)', - '🄚' => '(K)', - '🄛' => '(L)', - '🄜' => '(M)', - '🄝' => '(N)', - '🄞' => '(O)', - '🄟' => '(P)', - '🄠' => '(Q)', - '🄡' => '(R)', - '🄢' => '(S)', - '🄣' => '(T)', - '🄤' => '(U)', - '🄥' => '(V)', - '🄦' => '(W)', - '🄧' => '(X)', - '🄨' => '(Y)', - '🄩' => '(Z)', - '🄪' => '〔S〕', - '🄫' => 'C', - '🄬' => 'R', - '🄭' => 'CD', - '🄮' => 'WZ', - '🄰' => 'A', - '🄱' => 'B', - '🄲' => 'C', - '🄳' => 'D', - '🄴' => 'E', - '🄵' => 'F', - '🄶' => 'G', - '🄷' => 'H', - '🄸' => 'I', - '🄹' => 'J', - '🄺' => 'K', - '🄻' => 'L', - '🄼' => 'M', - '🄽' => 'N', - '🄾' => 'O', - '🄿' => 'P', - '🅀' => 'Q', - '🅁' => 'R', - '🅂' => 'S', - '🅃' => 'T', - '🅄' => 'U', - '🅅' => 'V', - '🅆' => 'W', - '🅇' => 'X', - '🅈' => 'Y', - '🅉' => 'Z', - '🅊' => 'HV', - '🅋' => 'MV', - '🅌' => 'SD', - '🅍' => 'SS', - '🅎' => 'PPV', - '🅏' => 'WC', - '🅪' => 'MC', - '🅫' => 'MD', - '🅬' => 'MR', - '🆐' => 'DJ', - '🈀' => 'ほか', - '🈁' => 'ココ', - '🈂' => 'サ', - '🈐' => '手', - '🈑' => '字', - '🈒' => '双', - '🈓' => 'デ', - '🈔' => '二', - '🈕' => '多', - '🈖' => '解', - '🈗' => '天', - '🈘' => '交', - '🈙' => '映', - '🈚' => '無', - '🈛' => '料', - '🈜' => '前', - '🈝' => '後', - '🈞' => '再', - '🈟' => '新', - '🈠' => '初', - '🈡' => '終', - '🈢' => '生', - '🈣' => '販', - '🈤' => '声', - '🈥' => '吹', - '🈦' => '演', - '🈧' => '投', - '🈨' => '捕', - '🈩' => '一', - '🈪' => '三', - '🈫' => '遊', - '🈬' => '左', - '🈭' => '中', - '🈮' => '右', - '🈯' => '指', - '🈰' => '走', - '🈱' => '打', - '🈲' => '禁', - '🈳' => '空', - '🈴' => '合', - '🈵' => '満', - '🈶' => '有', - '🈷' => '月', - '🈸' => '申', - '🈹' => '割', - '🈺' => '営', - '🈻' => '配', - '🉀' => '〔本〕', - '🉁' => '〔三〕', - '🉂' => '〔二〕', - '🉃' => '〔安〕', - '🉄' => '〔点〕', - '🉅' => '〔打〕', - '🉆' => '〔盗〕', - '🉇' => '〔勝〕', - '🉈' => '〔敗〕', - '🉐' => '得', - '🉑' => '可', - '🯰' => '0', - '🯱' => '1', - '🯲' => '2', - '🯳' => '3', - '🯴' => '4', - '🯵' => '5', - '🯶' => '6', - '🯷' => '7', - '🯸' => '8', - '🯹' => '9', -); diff --git a/lib/symfony/polyfill-intl-normalizer/bootstrap.php b/lib/symfony/polyfill-intl-normalizer/bootstrap.php deleted file mode 100644 index 3608e5c05..000000000 --- a/lib/symfony/polyfill-intl-normalizer/bootstrap.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -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/lib/symfony/polyfill-intl-normalizer/bootstrap80.php b/lib/symfony/polyfill-intl-normalizer/bootstrap80.php deleted file mode 100644 index e36d1a947..000000000 --- a/lib/symfony/polyfill-intl-normalizer/bootstrap80.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -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/lib/symfony/polyfill-intl-normalizer/composer.json b/lib/symfony/polyfill-intl-normalizer/composer.json deleted file mode 100644 index eb452bfd4..000000000 --- a/lib/symfony/polyfill-intl-normalizer/composer.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "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.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - } -} diff --git a/lib/symfony/polyfill-mbstring/LICENSE b/lib/symfony/polyfill-mbstring/LICENSE deleted file mode 100644 index 4cd8bdd30..000000000 --- a/lib/symfony/polyfill-mbstring/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2015-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/lib/symfony/polyfill-mbstring/Mbstring.php b/lib/symfony/polyfill-mbstring/Mbstring.php deleted file mode 100644 index 693749f22..000000000 --- a/lib/symfony/polyfill-mbstring/Mbstring.php +++ /dev/null @@ -1,873 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\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 <p@tchwork.com> - * - * @internal - */ -final class Mbstring -{ - public const MB_CASE_FOLD = \PHP_INT_MAX; - - private const CASE_FOLD = [ - ['µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"], - ['μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'], - ]; - - private static $encodingList = ['ASCII', 'UTF-8']; - private static $language = 'neutral'; - private static $internalEncoding = 'UTF-8'; - - public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null) - { - if (\is_array($fromEncoding) || ($fromEncoding !== null && 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) { - $s = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $s); - } - - 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 (null === $encoding) { - if (null === $var) { - return false; - } - $encoding = self::$internalEncoding; - } - - return self::mb_detect_encoding($var, [$encoding]) || false !== @\iconv($encoding, $encoding, $var); - } - - 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 = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding); - $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding); - - return self::mb_strpos($haystack, $needle, $offset, $encoding); - } - - 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, self::MB_CASE_FOLD, $encoding); - $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding); - - 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; - } - - 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/lib/symfony/polyfill-mbstring/README.md b/lib/symfony/polyfill-mbstring/README.md deleted file mode 100644 index 478b40da2..000000000 --- a/lib/symfony/polyfill-mbstring/README.md +++ /dev/null @@ -1,13 +0,0 @@ -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/lib/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php b/lib/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php deleted file mode 100644 index fac60b081..000000000 --- a/lib/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php +++ /dev/null @@ -1,1397 +0,0 @@ -<?php - -return array ( - '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', - 'À' => 'à', - 'Á' => 'á', - 'Â' => 'â', - 'Ã' => 'ã', - 'Ä' => 'ä', - 'Å' => 'å', - 'Æ' => 'æ', - 'Ç' => 'ç', - 'È' => 'è', - 'É' => 'é', - 'Ê' => 'ê', - 'Ë' => 'ë', - 'Ì' => 'ì', - 'Í' => 'í', - 'Î' => 'î', - 'Ï' => 'ï', - 'Ð' => 'ð', - 'Ñ' => 'ñ', - 'Ò' => 'ò', - 'Ó' => 'ó', - 'Ô' => 'ô', - 'Õ' => 'õ', - 'Ö' => 'ö', - 'Ø' => 'ø', - 'Ù' => 'ù', - 'Ú' => 'ú', - 'Û' => 'û', - 'Ü' => 'ü', - 'Ý' => 'ý', - 'Þ' => 'þ', - 'Ā' => 'ā', - 'Ă' => 'ă', - 'Ą' => 'ą', - 'Ć' => 'ć', - 'Ĉ' => 'ĉ', - 'Ċ' => 'ċ', - 'Č' => 'č', - 'Ď' => 'ď', - 'Đ' => 'đ', - 'Ē' => 'ē', - 'Ĕ' => 'ĕ', - 'Ė' => 'ė', - 'Ę' => 'ę', - 'Ě' => 'ě', - 'Ĝ' => 'ĝ', - 'Ğ' => 'ğ', - 'Ġ' => 'ġ', - 'Ģ' => 'ģ', - 'Ĥ' => 'ĥ', - 'Ħ' => 'ħ', - 'Ĩ' => 'ĩ', - 'Ī' => 'ī', - 'Ĭ' => 'ĭ', - 'Į' => 'į', - 'İ' => '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/lib/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php b/lib/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php deleted file mode 100644 index 2a8f6e73b..000000000 --- a/lib/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php +++ /dev/null @@ -1,5 +0,0 @@ -<?php - -// from Case_Ignorable in https://unicode.org/Public/UNIDATA/DerivedCoreProperties.txt - -return '/(?<![\x{0027}\x{002E}\x{003A}\x{005E}\x{0060}\x{00A8}\x{00AD}\x{00AF}\x{00B4}\x{00B7}\x{00B8}\x{02B0}-\x{02C1}\x{02C2}-\x{02C5}\x{02C6}-\x{02D1}\x{02D2}-\x{02DF}\x{02E0}-\x{02E4}\x{02E5}-\x{02EB}\x{02EC}\x{02ED}\x{02EE}\x{02EF}-\x{02FF}\x{0300}-\x{036F}\x{0374}\x{0375}\x{037A}\x{0384}-\x{0385}\x{0387}\x{0483}-\x{0487}\x{0488}-\x{0489}\x{0559}\x{0591}-\x{05BD}\x{05BF}\x{05C1}-\x{05C2}\x{05C4}-\x{05C5}\x{05C7}\x{05F4}\x{0600}-\x{0605}\x{0610}-\x{061A}\x{061C}\x{0640}\x{064B}-\x{065F}\x{0670}\x{06D6}-\x{06DC}\x{06DD}\x{06DF}-\x{06E4}\x{06E5}-\x{06E6}\x{06E7}-\x{06E8}\x{06EA}-\x{06ED}\x{070F}\x{0711}\x{0730}-\x{074A}\x{07A6}-\x{07B0}\x{07EB}-\x{07F3}\x{07F4}-\x{07F5}\x{07FA}\x{07FD}\x{0816}-\x{0819}\x{081A}\x{081B}-\x{0823}\x{0824}\x{0825}-\x{0827}\x{0828}\x{0829}-\x{082D}\x{0859}-\x{085B}\x{08D3}-\x{08E1}\x{08E2}\x{08E3}-\x{0902}\x{093A}\x{093C}\x{0941}-\x{0948}\x{094D}\x{0951}-\x{0957}\x{0962}-\x{0963}\x{0971}\x{0981}\x{09BC}\x{09C1}-\x{09C4}\x{09CD}\x{09E2}-\x{09E3}\x{09FE}\x{0A01}-\x{0A02}\x{0A3C}\x{0A41}-\x{0A42}\x{0A47}-\x{0A48}\x{0A4B}-\x{0A4D}\x{0A51}\x{0A70}-\x{0A71}\x{0A75}\x{0A81}-\x{0A82}\x{0ABC}\x{0AC1}-\x{0AC5}\x{0AC7}-\x{0AC8}\x{0ACD}\x{0AE2}-\x{0AE3}\x{0AFA}-\x{0AFF}\x{0B01}\x{0B3C}\x{0B3F}\x{0B41}-\x{0B44}\x{0B4D}\x{0B56}\x{0B62}-\x{0B63}\x{0B82}\x{0BC0}\x{0BCD}\x{0C00}\x{0C04}\x{0C3E}-\x{0C40}\x{0C46}-\x{0C48}\x{0C4A}-\x{0C4D}\x{0C55}-\x{0C56}\x{0C62}-\x{0C63}\x{0C81}\x{0CBC}\x{0CBF}\x{0CC6}\x{0CCC}-\x{0CCD}\x{0CE2}-\x{0CE3}\x{0D00}-\x{0D01}\x{0D3B}-\x{0D3C}\x{0D41}-\x{0D44}\x{0D4D}\x{0D62}-\x{0D63}\x{0DCA}\x{0DD2}-\x{0DD4}\x{0DD6}\x{0E31}\x{0E34}-\x{0E3A}\x{0E46}\x{0E47}-\x{0E4E}\x{0EB1}\x{0EB4}-\x{0EB9}\x{0EBB}-\x{0EBC}\x{0EC6}\x{0EC8}-\x{0ECD}\x{0F18}-\x{0F19}\x{0F35}\x{0F37}\x{0F39}\x{0F71}-\x{0F7E}\x{0F80}-\x{0F84}\x{0F86}-\x{0F87}\x{0F8D}-\x{0F97}\x{0F99}-\x{0FBC}\x{0FC6}\x{102D}-\x{1030}\x{1032}-\x{1037}\x{1039}-\x{103A}\x{103D}-\x{103E}\x{1058}-\x{1059}\x{105E}-\x{1060}\x{1071}-\x{1074}\x{1082}\x{1085}-\x{1086}\x{108D}\x{109D}\x{10FC}\x{135D}-\x{135F}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}-\x{1753}\x{1772}-\x{1773}\x{17B4}-\x{17B5}\x{17B7}-\x{17BD}\x{17C6}\x{17C9}-\x{17D3}\x{17D7}\x{17DD}\x{180B}-\x{180D}\x{180E}\x{1843}\x{1885}-\x{1886}\x{18A9}\x{1920}-\x{1922}\x{1927}-\x{1928}\x{1932}\x{1939}-\x{193B}\x{1A17}-\x{1A18}\x{1A1B}\x{1A56}\x{1A58}-\x{1A5E}\x{1A60}\x{1A62}\x{1A65}-\x{1A6C}\x{1A73}-\x{1A7C}\x{1A7F}\x{1AA7}\x{1AB0}-\x{1ABD}\x{1ABE}\x{1B00}-\x{1B03}\x{1B34}\x{1B36}-\x{1B3A}\x{1B3C}\x{1B42}\x{1B6B}-\x{1B73}\x{1B80}-\x{1B81}\x{1BA2}-\x{1BA5}\x{1BA8}-\x{1BA9}\x{1BAB}-\x{1BAD}\x{1BE6}\x{1BE8}-\x{1BE9}\x{1BED}\x{1BEF}-\x{1BF1}\x{1C2C}-\x{1C33}\x{1C36}-\x{1C37}\x{1C78}-\x{1C7D}\x{1CD0}-\x{1CD2}\x{1CD4}-\x{1CE0}\x{1CE2}-\x{1CE8}\x{1CED}\x{1CF4}\x{1CF8}-\x{1CF9}\x{1D2C}-\x{1D6A}\x{1D78}\x{1D9B}-\x{1DBF}\x{1DC0}-\x{1DF9}\x{1DFB}-\x{1DFF}\x{1FBD}\x{1FBF}-\x{1FC1}\x{1FCD}-\x{1FCF}\x{1FDD}-\x{1FDF}\x{1FED}-\x{1FEF}\x{1FFD}-\x{1FFE}\x{200B}-\x{200F}\x{2018}\x{2019}\x{2024}\x{2027}\x{202A}-\x{202E}\x{2060}-\x{2064}\x{2066}-\x{206F}\x{2071}\x{207F}\x{2090}-\x{209C}\x{20D0}-\x{20DC}\x{20DD}-\x{20E0}\x{20E1}\x{20E2}-\x{20E4}\x{20E5}-\x{20F0}\x{2C7C}-\x{2C7D}\x{2CEF}-\x{2CF1}\x{2D6F}\x{2D7F}\x{2DE0}-\x{2DFF}\x{2E2F}\x{3005}\x{302A}-\x{302D}\x{3031}-\x{3035}\x{303B}\x{3099}-\x{309A}\x{309B}-\x{309C}\x{309D}-\x{309E}\x{30FC}-\x{30FE}\x{A015}\x{A4F8}-\x{A4FD}\x{A60C}\x{A66F}\x{A670}-\x{A672}\x{A674}-\x{A67D}\x{A67F}\x{A69C}-\x{A69D}\x{A69E}-\x{A69F}\x{A6F0}-\x{A6F1}\x{A700}-\x{A716}\x{A717}-\x{A71F}\x{A720}-\x{A721}\x{A770}\x{A788}\x{A789}-\x{A78A}\x{A7F8}-\x{A7F9}\x{A802}\x{A806}\x{A80B}\x{A825}-\x{A826}\x{A8C4}-\x{A8C5}\x{A8E0}-\x{A8F1}\x{A8FF}\x{A926}-\x{A92D}\x{A947}-\x{A951}\x{A980}-\x{A982}\x{A9B3}\x{A9B6}-\x{A9B9}\x{A9BC}\x{A9CF}\x{A9E5}\x{A9E6}\x{AA29}-\x{AA2E}\x{AA31}-\x{AA32}\x{AA35}-\x{AA36}\x{AA43}\x{AA4C}\x{AA70}\x{AA7C}\x{AAB0}\x{AAB2}-\x{AAB4}\x{AAB7}-\x{AAB8}\x{AABE}-\x{AABF}\x{AAC1}\x{AADD}\x{AAEC}-\x{AAED}\x{AAF3}-\x{AAF4}\x{AAF6}\x{AB5B}\x{AB5C}-\x{AB5F}\x{ABE5}\x{ABE8}\x{ABED}\x{FB1E}\x{FBB2}-\x{FBC1}\x{FE00}-\x{FE0F}\x{FE13}\x{FE20}-\x{FE2F}\x{FE52}\x{FE55}\x{FEFF}\x{FF07}\x{FF0E}\x{FF1A}\x{FF3E}\x{FF40}\x{FF70}\x{FF9E}-\x{FF9F}\x{FFE3}\x{FFF9}-\x{FFFB}\x{101FD}\x{102E0}\x{10376}-\x{1037A}\x{10A01}-\x{10A03}\x{10A05}-\x{10A06}\x{10A0C}-\x{10A0F}\x{10A38}-\x{10A3A}\x{10A3F}\x{10AE5}-\x{10AE6}\x{10D24}-\x{10D27}\x{10F46}-\x{10F50}\x{11001}\x{11038}-\x{11046}\x{1107F}-\x{11081}\x{110B3}-\x{110B6}\x{110B9}-\x{110BA}\x{110BD}\x{110CD}\x{11100}-\x{11102}\x{11127}-\x{1112B}\x{1112D}-\x{11134}\x{11173}\x{11180}-\x{11181}\x{111B6}-\x{111BE}\x{111C9}-\x{111CC}\x{1122F}-\x{11231}\x{11234}\x{11236}-\x{11237}\x{1123E}\x{112DF}\x{112E3}-\x{112EA}\x{11300}-\x{11301}\x{1133B}-\x{1133C}\x{11340}\x{11366}-\x{1136C}\x{11370}-\x{11374}\x{11438}-\x{1143F}\x{11442}-\x{11444}\x{11446}\x{1145E}\x{114B3}-\x{114B8}\x{114BA}\x{114BF}-\x{114C0}\x{114C2}-\x{114C3}\x{115B2}-\x{115B5}\x{115BC}-\x{115BD}\x{115BF}-\x{115C0}\x{115DC}-\x{115DD}\x{11633}-\x{1163A}\x{1163D}\x{1163F}-\x{11640}\x{116AB}\x{116AD}\x{116B0}-\x{116B5}\x{116B7}\x{1171D}-\x{1171F}\x{11722}-\x{11725}\x{11727}-\x{1172B}\x{1182F}-\x{11837}\x{11839}-\x{1183A}\x{11A01}-\x{11A0A}\x{11A33}-\x{11A38}\x{11A3B}-\x{11A3E}\x{11A47}\x{11A51}-\x{11A56}\x{11A59}-\x{11A5B}\x{11A8A}-\x{11A96}\x{11A98}-\x{11A99}\x{11C30}-\x{11C36}\x{11C38}-\x{11C3D}\x{11C3F}\x{11C92}-\x{11CA7}\x{11CAA}-\x{11CB0}\x{11CB2}-\x{11CB3}\x{11CB5}-\x{11CB6}\x{11D31}-\x{11D36}\x{11D3A}\x{11D3C}-\x{11D3D}\x{11D3F}-\x{11D45}\x{11D47}\x{11D90}-\x{11D91}\x{11D95}\x{11D97}\x{11EF3}-\x{11EF4}\x{16AF0}-\x{16AF4}\x{16B30}-\x{16B36}\x{16B40}-\x{16B43}\x{16F8F}-\x{16F92}\x{16F93}-\x{16F9F}\x{16FE0}-\x{16FE1}\x{1BC9D}-\x{1BC9E}\x{1BCA0}-\x{1BCA3}\x{1D167}-\x{1D169}\x{1D173}-\x{1D17A}\x{1D17B}-\x{1D182}\x{1D185}-\x{1D18B}\x{1D1AA}-\x{1D1AD}\x{1D242}-\x{1D244}\x{1DA00}-\x{1DA36}\x{1DA3B}-\x{1DA6C}\x{1DA75}\x{1DA84}\x{1DA9B}-\x{1DA9F}\x{1DAA1}-\x{1DAAF}\x{1E000}-\x{1E006}\x{1E008}-\x{1E018}\x{1E01B}-\x{1E021}\x{1E023}-\x{1E024}\x{1E026}-\x{1E02A}\x{1E8D0}-\x{1E8D6}\x{1E944}-\x{1E94A}\x{1F3FB}-\x{1F3FF}\x{E0001}\x{E0020}-\x{E007F}\x{E0100}-\x{E01EF}])(\pL)(\pL*+)/u'; diff --git a/lib/symfony/polyfill-mbstring/Resources/unidata/upperCase.php b/lib/symfony/polyfill-mbstring/Resources/unidata/upperCase.php deleted file mode 100644 index 56b9cb852..000000000 --- a/lib/symfony/polyfill-mbstring/Resources/unidata/upperCase.php +++ /dev/null @@ -1,1489 +0,0 @@ -<?php - -return array ( - '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', - 'µ' => 'Μ', - 'à' => 'À', - 'á' => 'Á', - 'â' => 'Â', - 'ã' => 'Ã', - 'ä' => 'Ä', - 'å' => 'Å', - 'æ' => 'Æ', - 'ç' => 'Ç', - 'è' => 'È', - 'é' => 'É', - 'ê' => 'Ê', - 'ë' => 'Ë', - 'ì' => 'Ì', - 'í' => 'Í', - 'î' => 'Î', - 'ï' => 'Ï', - 'ð' => 'Ð', - 'ñ' => 'Ñ', - 'ò' => 'Ò', - 'ó' => 'Ó', - 'ô' => 'Ô', - 'õ' => 'Õ', - 'ö' => 'Ö', - 'ø' => 'Ø', - 'ù' => 'Ù', - 'ú' => 'Ú', - 'û' => 'Û', - 'ü' => 'Ü', - 'ý' => 'Ý', - 'þ' => 'Þ', - 'ÿ' => 'Ÿ', - 'ā' => 'Ā', - 'ă' => 'Ă', - 'ą' => 'Ą', - 'ć' => 'Ć', - 'ĉ' => 'Ĉ', - 'ċ' => 'Ċ', - 'č' => 'Č', - 'ď' => 'Ď', - 'đ' => 'Đ', - 'ē' => 'Ē', - 'ĕ' => 'Ĕ', - 'ė' => 'Ė', - 'ę' => 'Ę', - 'ě' => 'Ě', - 'ĝ' => 'Ĝ', - 'ğ' => 'Ğ', - 'ġ' => 'Ġ', - 'ģ' => 'Ģ', - 'ĥ' => 'Ĥ', - 'ħ' => 'Ħ', - 'ĩ' => 'Ĩ', - 'ī' => 'Ī', - 'ĭ' => 'Ĭ', - 'į' => 'Į', - 'ı' => '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/lib/symfony/polyfill-mbstring/bootstrap.php b/lib/symfony/polyfill-mbstring/bootstrap.php deleted file mode 100644 index 1fedd1f7c..000000000 --- a/lib/symfony/polyfill-mbstring/bootstrap.php +++ /dev/null @@ -1,147 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -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 (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/lib/symfony/polyfill-mbstring/bootstrap80.php b/lib/symfony/polyfill-mbstring/bootstrap80.php deleted file mode 100644 index 82f5ac4d0..000000000 --- a/lib/symfony/polyfill-mbstring/bootstrap80.php +++ /dev/null @@ -1,143 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Mbstring as p; - -if (!function_exists('mb_convert_encoding')) { - function mb_convert_encoding(array|string|null $string, ?string $to_encoding, array|string|null $from_encoding = null): array|string|false { return p\Mbstring::mb_convert_encoding($string ?? '', (string) $to_encoding, $from_encoding); } -} -if (!function_exists('mb_decode_mimeheader')) { - function mb_decode_mimeheader(?string $string): string { return p\Mbstring::mb_decode_mimeheader((string) $string); } -} -if (!function_exists('mb_encode_mimeheader')) { - function mb_encode_mimeheader(?string $string, ?string $charset = null, ?string $transfer_encoding = null, ?string $newline = "\r\n", ?int $indent = 0): string { return p\Mbstring::mb_encode_mimeheader((string) $string, $charset, $transfer_encoding, (string) $newline, (int) $indent); } -} -if (!function_exists('mb_decode_numericentity')) { - function mb_decode_numericentity(?string $string, array $map, ?string $encoding = null): string { return p\Mbstring::mb_decode_numericentity((string) $string, $map, $encoding); } -} -if (!function_exists('mb_encode_numericentity')) { - function mb_encode_numericentity(?string $string, array $map, ?string $encoding = null, ?bool $hex = false): string { return p\Mbstring::mb_encode_numericentity((string) $string, $map, $encoding, (bool) $hex); } -} -if (!function_exists('mb_convert_case')) { - function mb_convert_case(?string $string, ?int $mode, ?string $encoding = null): string { return p\Mbstring::mb_convert_case((string) $string, (int) $mode, $encoding); } -} -if (!function_exists('mb_internal_encoding')) { - function mb_internal_encoding(?string $encoding = null): string|bool { return p\Mbstring::mb_internal_encoding($encoding); } -} -if (!function_exists('mb_language')) { - function mb_language(?string $language = null): string|bool { return p\Mbstring::mb_language($language); } -} -if (!function_exists('mb_list_encodings')) { - function mb_list_encodings(): array { return p\Mbstring::mb_list_encodings(); } -} -if (!function_exists('mb_encoding_aliases')) { - function mb_encoding_aliases(?string $encoding): array { return p\Mbstring::mb_encoding_aliases((string) $encoding); } -} -if (!function_exists('mb_check_encoding')) { - function mb_check_encoding(array|string|null $value = null, ?string $encoding = null): bool { return p\Mbstring::mb_check_encoding($value, $encoding); } -} -if (!function_exists('mb_detect_encoding')) { - function mb_detect_encoding(?string $string, array|string|null $encodings = null, ?bool $strict = false): string|false { return p\Mbstring::mb_detect_encoding((string) $string, $encodings, (bool) $strict); } -} -if (!function_exists('mb_detect_order')) { - function mb_detect_order(array|string|null $encoding = null): array|bool { return p\Mbstring::mb_detect_order($encoding); } -} -if (!function_exists('mb_parse_str')) { - function mb_parse_str(?string $string, &$result = []): bool { parse_str((string) $string, $result); return (bool) $result; } -} -if (!function_exists('mb_strlen')) { - function mb_strlen(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strlen((string) $string, $encoding); } -} -if (!function_exists('mb_strpos')) { - function mb_strpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strpos((string) $haystack, (string) $needle, (int) $offset, $encoding); } -} -if (!function_exists('mb_strtolower')) { - function mb_strtolower(?string $string, ?string $encoding = null): string { return p\Mbstring::mb_strtolower((string) $string, $encoding); } -} -if (!function_exists('mb_strtoupper')) { - function mb_strtoupper(?string $string, ?string $encoding = null): string { return p\Mbstring::mb_strtoupper((string) $string, $encoding); } -} -if (!function_exists('mb_substitute_character')) { - function mb_substitute_character(string|int|null $substitute_character = null): string|int|bool { return p\Mbstring::mb_substitute_character($substitute_character); } -} -if (!function_exists('mb_substr')) { - function mb_substr(?string $string, ?int $start, ?int $length = null, ?string $encoding = null): string { return p\Mbstring::mb_substr((string) $string, (int) $start, $length, $encoding); } -} -if (!function_exists('mb_stripos')) { - function mb_stripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_stripos((string) $haystack, (string) $needle, (int) $offset, $encoding); } -} -if (!function_exists('mb_stristr')) { - function mb_stristr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_stristr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } -} -if (!function_exists('mb_strrchr')) { - function mb_strrchr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrchr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } -} -if (!function_exists('mb_strrichr')) { - function mb_strrichr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrichr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } -} -if (!function_exists('mb_strripos')) { - function mb_strripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strripos((string) $haystack, (string) $needle, (int) $offset, $encoding); } -} -if (!function_exists('mb_strrpos')) { - function mb_strrpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strrpos((string) $haystack, (string) $needle, (int) $offset, $encoding); } -} -if (!function_exists('mb_strstr')) { - function mb_strstr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strstr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } -} -if (!function_exists('mb_get_info')) { - function mb_get_info(?string $type = 'all'): array|string|int|false { return p\Mbstring::mb_get_info((string) $type); } -} -if (!function_exists('mb_http_output')) { - function mb_http_output(?string $encoding = null): string|bool { return p\Mbstring::mb_http_output($encoding); } -} -if (!function_exists('mb_strwidth')) { - function mb_strwidth(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strwidth((string) $string, $encoding); } -} -if (!function_exists('mb_substr_count')) { - function mb_substr_count(?string $haystack, ?string $needle, ?string $encoding = null): int { return p\Mbstring::mb_substr_count((string) $haystack, (string) $needle, $encoding); } -} -if (!function_exists('mb_output_handler')) { - function mb_output_handler(?string $string, ?int $status): string { return p\Mbstring::mb_output_handler((string) $string, (int) $status); } -} -if (!function_exists('mb_http_input')) { - function mb_http_input(?string $type = null): array|string|false { return p\Mbstring::mb_http_input($type); } -} - -if (!function_exists('mb_convert_variables')) { - function mb_convert_variables(?string $to_encoding, array|string|null $from_encoding, mixed &$var, mixed &...$vars): string|false { return p\Mbstring::mb_convert_variables((string) $to_encoding, $from_encoding ?? '', $var, ...$vars); } -} - -if (!function_exists('mb_ord')) { - function mb_ord(?string $string, ?string $encoding = null): int|false { return p\Mbstring::mb_ord((string) $string, $encoding); } -} -if (!function_exists('mb_chr')) { - function mb_chr(?int $codepoint, ?string $encoding = null): string|false { return p\Mbstring::mb_chr((int) $codepoint, $encoding); } -} -if (!function_exists('mb_scrub')) { - function mb_scrub(?string $string, ?string $encoding = null): string { $encoding ??= mb_internal_encoding(); return mb_convert_encoding((string) $string, $encoding, $encoding); } -} -if (!function_exists('mb_str_split')) { - function mb_str_split(?string $string, ?int $length = 1, ?string $encoding = null): array { return p\Mbstring::mb_str_split((string) $string, (int) $length, $encoding); } -} - -if (extension_loaded('mbstring')) { - return; -} - -if (!defined('MB_CASE_UPPER')) { - define('MB_CASE_UPPER', 0); -} -if (!defined('MB_CASE_LOWER')) { - define('MB_CASE_LOWER', 1); -} -if (!defined('MB_CASE_TITLE')) { - define('MB_CASE_TITLE', 2); -} diff --git a/lib/symfony/polyfill-mbstring/composer.json b/lib/symfony/polyfill-mbstring/composer.json deleted file mode 100644 index 9cd2e924e..000000000 --- a/lib/symfony/polyfill-mbstring/composer.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "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.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - } -} diff --git a/lib/symfony/polyfill-php72/LICENSE b/lib/symfony/polyfill-php72/LICENSE deleted file mode 100644 index 4cd8bdd30..000000000 --- a/lib/symfony/polyfill-php72/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2015-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/lib/symfony/polyfill-php72/Php72.php b/lib/symfony/polyfill-php72/Php72.php deleted file mode 100644 index 5e20d5bf8..000000000 --- a/lib/symfony/polyfill-php72/Php72.php +++ /dev/null @@ -1,217 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Php72; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> - * - * @internal - */ -final class Php72 -{ - private static $hashMask; - - public static function utf8_encode($s) - { - $s .= $s; - $len = \strlen($s); - - for ($i = $len >> 1, $j = 0; $i < $len; ++$i, ++$j) { - switch (true) { - case $s[$i] < "\x80": $s[$j] = $s[$i]; break; - case $s[$i] < "\xC0": $s[$j] = "\xC2"; $s[++$j] = $s[$i]; break; - default: $s[$j] = "\xC3"; $s[++$j] = \chr(\ord($s[$i]) - 64); break; - } - } - - return substr($s, 0, $j); - } - - public static function utf8_decode($s) - { - $s = (string) $s; - $len = \strlen($s); - - for ($i = 0, $j = 0; $i < $len; ++$i, ++$j) { - switch ($s[$i] & "\xF0") { - case "\xC0": - case "\xD0": - $c = (\ord($s[$i] & "\x1F") << 6) | \ord($s[++$i] & "\x3F"); - $s[$j] = $c < 256 ? \chr($c) : '?'; - break; - - case "\xF0": - ++$i; - // no break - - case "\xE0": - $s[$j] = '?'; - $i += 2; - break; - - default: - $s[$j] = $s[$i]; - } - } - - return substr($s, 0, $j); - } - - public static function php_os_family() - { - if ('\\' === \DIRECTORY_SEPARATOR) { - return 'Windows'; - } - - $map = [ - 'Darwin' => 'Darwin', - 'DragonFly' => 'BSD', - 'FreeBSD' => 'BSD', - 'NetBSD' => 'BSD', - 'OpenBSD' => 'BSD', - 'Linux' => 'Linux', - 'SunOS' => 'Solaris', - ]; - - return isset($map[\PHP_OS]) ? $map[\PHP_OS] : 'Unknown'; - } - - public static function spl_object_id($object) - { - if (null === self::$hashMask) { - self::initHashMask(); - } - if (null === $hash = spl_object_hash($object)) { - return; - } - - // On 32-bit systems, PHP_INT_SIZE is 4, - return self::$hashMask ^ hexdec(substr($hash, 16 - (\PHP_INT_SIZE * 2 - 1), (\PHP_INT_SIZE * 2 - 1))); - } - - public static function sapi_windows_vt100_support($stream, $enable = null) - { - if (!\is_resource($stream)) { - trigger_error('sapi_windows_vt100_support() expects parameter 1 to be resource, '.\gettype($stream).' given', \E_USER_WARNING); - - return false; - } - - $meta = stream_get_meta_data($stream); - - if ('STDIO' !== $meta['stream_type']) { - trigger_error('sapi_windows_vt100_support() was not able to analyze the specified stream', \E_USER_WARNING); - - return false; - } - - // We cannot actually disable vt100 support if it is set - if (false === $enable || !self::stream_isatty($stream)) { - return false; - } - - // The native function does not apply to stdin - $meta = array_map('strtolower', $meta); - $stdin = 'php://stdin' === $meta['uri'] || 'php://fd/0' === $meta['uri']; - - return !$stdin - && (false !== getenv('ANSICON') - || 'ON' === getenv('ConEmuANSI') - || 'xterm' === getenv('TERM') - || 'Hyper' === getenv('TERM_PROGRAM')); - } - - public static function stream_isatty($stream) - { - if (!\is_resource($stream)) { - trigger_error('stream_isatty() expects parameter 1 to be resource, '.\gettype($stream).' given', \E_USER_WARNING); - - return false; - } - - if ('\\' === \DIRECTORY_SEPARATOR) { - $stat = @fstat($stream); - // Check if formatted mode is S_IFCHR - return $stat ? 0020000 === ($stat['mode'] & 0170000) : false; - } - - return \function_exists('posix_isatty') && @posix_isatty($stream); - } - - private static function initHashMask() - { - $obj = (object) []; - self::$hashMask = -1; - - // check if we are nested in an output buffering handler to prevent a fatal error with ob_start() below - $obFuncs = ['ob_clean', 'ob_end_clean', 'ob_flush', 'ob_end_flush', 'ob_get_contents', 'ob_get_flush']; - foreach (debug_backtrace(\PHP_VERSION_ID >= 50400 ? \DEBUG_BACKTRACE_IGNORE_ARGS : false) as $frame) { - if (isset($frame['function'][0]) && !isset($frame['class']) && 'o' === $frame['function'][0] && \in_array($frame['function'], $obFuncs)) { - $frame['line'] = 0; - break; - } - } - if (!empty($frame['line'])) { - ob_start(); - debug_zval_dump($obj); - self::$hashMask = (int) substr(ob_get_clean(), 17); - } - - self::$hashMask ^= hexdec(substr(spl_object_hash($obj), 16 - (\PHP_INT_SIZE * 2 - 1), (\PHP_INT_SIZE * 2 - 1))); - } - - public static function mb_chr($code, $encoding = null) - { - if (0x80 > $code %= 0x200000) { - $s = \chr($code); - } elseif (0x800 > $code) { - $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F); - } elseif (0x10000 > $code) { - $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); - } else { - $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); - } - - if ('UTF-8' !== $encoding = $encoding ?? mb_internal_encoding()) { - $s = mb_convert_encoding($s, $encoding, 'UTF-8'); - } - - return $s; - } - - public static function mb_ord($s, $encoding = null) - { - if (null === $encoding) { - $s = mb_convert_encoding($s, 'UTF-8'); - } elseif ('UTF-8' !== $encoding) { - $s = mb_convert_encoding($s, 'UTF-8', $encoding); - } - - if (1 === \strlen($s)) { - return \ord($s); - } - - $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0; - if (0xF0 <= $code) { - return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80; - } - if (0xE0 <= $code) { - return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80; - } - if (0xC0 <= $code) { - return (($code - 0xC0) << 6) + $s[2] - 0x80; - } - - return $code; - } -} diff --git a/lib/symfony/polyfill-php72/README.md b/lib/symfony/polyfill-php72/README.md deleted file mode 100644 index ed1905055..000000000 --- a/lib/symfony/polyfill-php72/README.md +++ /dev/null @@ -1,35 +0,0 @@ -Symfony Polyfill / Php72 -======================== - -This component provides functions added to PHP 7.2 core: - -- [`spl_object_id`](https://php.net/spl_object_id) -- [`stream_isatty`](https://php.net/stream_isatty) - -And also functions added to PHP 7.2 mbstring: - -- [`mb_ord`](https://php.net/mb_ord) -- [`mb_chr`](https://php.net/mb_chr) -- [`mb_scrub`](https://php.net/mb_scrub) - -On Windows only: - -- [`sapi_windows_vt100_support`](https://php.net/sapi_windows_vt100_support) - -Moved to core since 7.2 (was in the optional XML extension earlier): - -- [`utf8_encode`](https://php.net/utf8_encode) -- [`utf8_decode`](https://php.net/utf8_decode) - -Also, it provides constants added to PHP 7.2: - -- [`PHP_FLOAT_*`](https://php.net/reserved.constants#constant.php-float-dig) -- [`PHP_OS_FAMILY`](https://php.net/reserved.constants#constant.php-os-family) - -More information can be found in the -[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). - -License -======= - -This library is released under the [MIT license](LICENSE). diff --git a/lib/symfony/polyfill-php72/bootstrap.php b/lib/symfony/polyfill-php72/bootstrap.php deleted file mode 100644 index b5c92d4c7..000000000 --- a/lib/symfony/polyfill-php72/bootstrap.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Php72 as p; - -if (\PHP_VERSION_ID >= 70200) { - return; -} - -if (!defined('PHP_FLOAT_DIG')) { - define('PHP_FLOAT_DIG', 15); -} -if (!defined('PHP_FLOAT_EPSILON')) { - define('PHP_FLOAT_EPSILON', 2.2204460492503E-16); -} -if (!defined('PHP_FLOAT_MIN')) { - define('PHP_FLOAT_MIN', 2.2250738585072E-308); -} -if (!defined('PHP_FLOAT_MAX')) { - define('PHP_FLOAT_MAX', 1.7976931348623157E+308); -} -if (!defined('PHP_OS_FAMILY')) { - define('PHP_OS_FAMILY', p\Php72::php_os_family()); -} - -if ('\\' === \DIRECTORY_SEPARATOR && !function_exists('sapi_windows_vt100_support')) { - function sapi_windows_vt100_support($stream, $enable = null) { return p\Php72::sapi_windows_vt100_support($stream, $enable); } -} -if (!function_exists('stream_isatty')) { - function stream_isatty($stream) { return p\Php72::stream_isatty($stream); } -} -if (!function_exists('utf8_encode')) { - function utf8_encode($string) { return p\Php72::utf8_encode($string); } -} -if (!function_exists('utf8_decode')) { - function utf8_decode($string) { return p\Php72::utf8_decode($string); } -} -if (!function_exists('spl_object_id')) { - function spl_object_id($object) { return p\Php72::spl_object_id($object); } -} -if (!function_exists('mb_ord')) { - function mb_ord($string, $encoding = null) { return p\Php72::mb_ord($string, $encoding); } -} -if (!function_exists('mb_chr')) { - function mb_chr($codepoint, $encoding = null) { return p\Php72::mb_chr($codepoint, $encoding); } -} -if (!function_exists('mb_scrub')) { - function mb_scrub($string, $encoding = null) { $encoding = null === $encoding ? mb_internal_encoding() : $encoding; return mb_convert_encoding($string, $encoding, $encoding); } -} diff --git a/lib/symfony/polyfill-php72/composer.json b/lib/symfony/polyfill-php72/composer.json deleted file mode 100644 index 4eac690e0..000000000 --- a/lib/symfony/polyfill-php72/composer.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "symfony/polyfill-php72", - "type": "library", - "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", - "keywords": ["polyfill", "shim", "compatibility", "portable"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.1" - }, - "autoload": { - "psr-4": { "Symfony\\Polyfill\\Php72\\": "" }, - "files": [ "bootstrap.php" ] - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - } -} diff --git a/lib/symfony/polyfill-php73/LICENSE b/lib/symfony/polyfill-php73/LICENSE deleted file mode 100644 index 3f853aaf3..000000000 --- a/lib/symfony/polyfill-php73/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2018-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/lib/symfony/polyfill-php73/Php73.php b/lib/symfony/polyfill-php73/Php73.php deleted file mode 100644 index 65c35a6a1..000000000 --- a/lib/symfony/polyfill-php73/Php73.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Php73; - -/** - * @author Gabriel Caruso <carusogabriel34@gmail.com> - * @author Ion Bazan <ion.bazan@gmail.com> - * - * @internal - */ -final class Php73 -{ - public static $startAt = 1533462603; - - /** - * @param bool $asNum - * - * @return array|float|int - */ - public static function hrtime($asNum = false) - { - $ns = microtime(false); - $s = substr($ns, 11) - self::$startAt; - $ns = 1E9 * (float) $ns; - - if ($asNum) { - $ns += $s * 1E9; - - return \PHP_INT_SIZE === 4 ? $ns : (int) $ns; - } - - return [$s, (int) $ns]; - } -} diff --git a/lib/symfony/polyfill-php73/README.md b/lib/symfony/polyfill-php73/README.md deleted file mode 100644 index 032fafbda..000000000 --- a/lib/symfony/polyfill-php73/README.md +++ /dev/null @@ -1,18 +0,0 @@ -Symfony Polyfill / Php73 -======================== - -This component provides functions added to PHP 7.3 core: - -- [`array_key_first`](https://php.net/array_key_first) -- [`array_key_last`](https://php.net/array_key_last) -- [`hrtime`](https://php.net/function.hrtime) -- [`is_countable`](https://php.net/is_countable) -- [`JsonException`](https://php.net/JsonException) - -More information can be found in the -[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). - -License -======= - -This library is released under the [MIT license](LICENSE). diff --git a/lib/symfony/polyfill-php73/Resources/stubs/JsonException.php b/lib/symfony/polyfill-php73/Resources/stubs/JsonException.php deleted file mode 100644 index f06d6c269..000000000 --- a/lib/symfony/polyfill-php73/Resources/stubs/JsonException.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -if (\PHP_VERSION_ID < 70300) { - class JsonException extends Exception - { - } -} diff --git a/lib/symfony/polyfill-php73/bootstrap.php b/lib/symfony/polyfill-php73/bootstrap.php deleted file mode 100644 index d6b215382..000000000 --- a/lib/symfony/polyfill-php73/bootstrap.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Php73 as p; - -if (\PHP_VERSION_ID >= 70300) { - return; -} - -if (!function_exists('is_countable')) { - function is_countable($value) { return is_array($value) || $value instanceof Countable || $value instanceof ResourceBundle || $value instanceof SimpleXmlElement; } -} -if (!function_exists('hrtime')) { - require_once __DIR__.'/Php73.php'; - p\Php73::$startAt = (int) microtime(true); - function hrtime($as_number = false) { return p\Php73::hrtime($as_number); } -} -if (!function_exists('array_key_first')) { - function array_key_first(array $array) { foreach ($array as $key => $value) { return $key; } } -} -if (!function_exists('array_key_last')) { - function array_key_last(array $array) { return key(array_slice($array, -1, 1, true)); } -} diff --git a/lib/symfony/polyfill-php73/composer.json b/lib/symfony/polyfill-php73/composer.json deleted file mode 100644 index af0cf42d2..000000000 --- a/lib/symfony/polyfill-php73/composer.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "symfony/polyfill-php73", - "type": "library", - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", - "keywords": ["polyfill", "shim", "compatibility", "portable"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.1" - }, - "autoload": { - "psr-4": { "Symfony\\Polyfill\\Php73\\": "" }, - "files": [ "bootstrap.php" ], - "classmap": [ "Resources/stubs" ] - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - } -} diff --git a/lib/symfony/polyfill-php80/LICENSE b/lib/symfony/polyfill-php80/LICENSE deleted file mode 100644 index 5593b1d84..000000000 --- a/lib/symfony/polyfill-php80/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2020 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/lib/symfony/polyfill-php80/Php80.php b/lib/symfony/polyfill-php80/Php80.php deleted file mode 100644 index 362dd1a95..000000000 --- a/lib/symfony/polyfill-php80/Php80.php +++ /dev/null @@ -1,115 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Php80; - -/** - * @author Ion Bazan <ion.bazan@gmail.com> - * @author Nico Oelgart <nicoswd@gmail.com> - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -final class Php80 -{ - public static function fdiv(float $dividend, float $divisor): float - { - return @($dividend / $divisor); - } - - public static function get_debug_type($value): string - { - switch (true) { - case null === $value: return 'null'; - case \is_bool($value): return 'bool'; - case \is_string($value): return 'string'; - case \is_array($value): return 'array'; - case \is_int($value): return 'int'; - case \is_float($value): return 'float'; - case \is_object($value): break; - case $value instanceof \__PHP_Incomplete_Class: return '__PHP_Incomplete_Class'; - default: - if (null === $type = @get_resource_type($value)) { - return 'unknown'; - } - - if ('Unknown' === $type) { - $type = 'closed'; - } - - return "resource ($type)"; - } - - $class = \get_class($value); - - if (false === strpos($class, '@')) { - return $class; - } - - return (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous'; - } - - public static function get_resource_id($res): int - { - if (!\is_resource($res) && null === @get_resource_type($res)) { - throw new \TypeError(sprintf('Argument 1 passed to get_resource_id() must be of the type resource, %s given', get_debug_type($res))); - } - - return (int) $res; - } - - public static function preg_last_error_msg(): string - { - switch (preg_last_error()) { - case \PREG_INTERNAL_ERROR: - return 'Internal error'; - case \PREG_BAD_UTF8_ERROR: - return 'Malformed UTF-8 characters, possibly incorrectly encoded'; - case \PREG_BAD_UTF8_OFFSET_ERROR: - return 'The offset did not correspond to the beginning of a valid UTF-8 code point'; - case \PREG_BACKTRACK_LIMIT_ERROR: - return 'Backtrack limit exhausted'; - case \PREG_RECURSION_LIMIT_ERROR: - return 'Recursion limit exhausted'; - case \PREG_JIT_STACKLIMIT_ERROR: - return 'JIT stack limit exhausted'; - case \PREG_NO_ERROR: - return 'No error'; - default: - return 'Unknown error'; - } - } - - public static function str_contains(string $haystack, string $needle): bool - { - return '' === $needle || false !== strpos($haystack, $needle); - } - - public static function str_starts_with(string $haystack, string $needle): bool - { - return 0 === strncmp($haystack, $needle, \strlen($needle)); - } - - public static function str_ends_with(string $haystack, string $needle): bool - { - if ('' === $needle || $needle === $haystack) { - return true; - } - - if ('' === $haystack) { - return false; - } - - $needleLength = \strlen($needle); - - return $needleLength <= \strlen($haystack) && 0 === substr_compare($haystack, $needle, -$needleLength); - } -} diff --git a/lib/symfony/polyfill-php80/PhpToken.php b/lib/symfony/polyfill-php80/PhpToken.php deleted file mode 100644 index fe6e69105..000000000 --- a/lib/symfony/polyfill-php80/PhpToken.php +++ /dev/null @@ -1,103 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Php80; - -/** - * @author Fedonyuk Anton <info@ensostudio.ru> - * - * @internal - */ -class PhpToken implements \Stringable -{ - /** - * @var int - */ - public $id; - - /** - * @var string - */ - public $text; - - /** - * @var int - */ - public $line; - - /** - * @var int - */ - public $pos; - - public function __construct(int $id, string $text, int $line = -1, int $position = -1) - { - $this->id = $id; - $this->text = $text; - $this->line = $line; - $this->pos = $position; - } - - public function getTokenName(): ?string - { - if ('UNKNOWN' === $name = token_name($this->id)) { - $name = \strlen($this->text) > 1 || \ord($this->text) < 32 ? null : $this->text; - } - - return $name; - } - - /** - * @param int|string|array $kind - */ - public function is($kind): bool - { - foreach ((array) $kind as $value) { - if (\in_array($value, [$this->id, $this->text], true)) { - return true; - } - } - - return false; - } - - public function isIgnorable(): bool - { - return \in_array($this->id, [\T_WHITESPACE, \T_COMMENT, \T_DOC_COMMENT, \T_OPEN_TAG], true); - } - - public function __toString(): string - { - return (string) $this->text; - } - - /** - * @return static[] - */ - public static function tokenize(string $code, int $flags = 0): array - { - $line = 1; - $position = 0; - $tokens = token_get_all($code, $flags); - foreach ($tokens as $index => $token) { - if (\is_string($token)) { - $id = \ord($token); - $text = $token; - } else { - [$id, $text, $line] = $token; - } - $tokens[$index] = new static($id, $text, $line, $position); - $position += \strlen($text); - } - - return $tokens; - } -} diff --git a/lib/symfony/polyfill-php80/README.md b/lib/symfony/polyfill-php80/README.md deleted file mode 100644 index 3816c559d..000000000 --- a/lib/symfony/polyfill-php80/README.md +++ /dev/null @@ -1,25 +0,0 @@ -Symfony Polyfill / Php80 -======================== - -This component provides features added to PHP 8.0 core: - -- [`Stringable`](https://php.net/stringable) interface -- [`fdiv`](https://php.net/fdiv) -- [`ValueError`](https://php.net/valueerror) class -- [`UnhandledMatchError`](https://php.net/unhandledmatcherror) class -- `FILTER_VALIDATE_BOOL` constant -- [`get_debug_type`](https://php.net/get_debug_type) -- [`PhpToken`](https://php.net/phptoken) class -- [`preg_last_error_msg`](https://php.net/preg_last_error_msg) -- [`str_contains`](https://php.net/str_contains) -- [`str_starts_with`](https://php.net/str_starts_with) -- [`str_ends_with`](https://php.net/str_ends_with) -- [`get_resource_id`](https://php.net/get_resource_id) - -More information can be found in the -[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). - -License -======= - -This library is released under the [MIT license](LICENSE). diff --git a/lib/symfony/polyfill-php80/Resources/stubs/Attribute.php b/lib/symfony/polyfill-php80/Resources/stubs/Attribute.php deleted file mode 100644 index 7ea6d2772..000000000 --- a/lib/symfony/polyfill-php80/Resources/stubs/Attribute.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -#[Attribute(Attribute::TARGET_CLASS)] -final class Attribute -{ - public const TARGET_CLASS = 1; - public const TARGET_FUNCTION = 2; - public const TARGET_METHOD = 4; - public const TARGET_PROPERTY = 8; - public const TARGET_CLASS_CONSTANT = 16; - public const TARGET_PARAMETER = 32; - public const TARGET_ALL = 63; - public const IS_REPEATABLE = 64; - - /** @var int */ - public $flags; - - public function __construct(int $flags = self::TARGET_ALL) - { - $this->flags = $flags; - } -} diff --git a/lib/symfony/polyfill-php80/Resources/stubs/PhpToken.php b/lib/symfony/polyfill-php80/Resources/stubs/PhpToken.php deleted file mode 100644 index 72f10812b..000000000 --- a/lib/symfony/polyfill-php80/Resources/stubs/PhpToken.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -if (\PHP_VERSION_ID < 80000 && \extension_loaded('tokenizer')) { - class PhpToken extends Symfony\Polyfill\Php80\PhpToken - { - } -} diff --git a/lib/symfony/polyfill-php80/Resources/stubs/Stringable.php b/lib/symfony/polyfill-php80/Resources/stubs/Stringable.php deleted file mode 100644 index 77e037cb5..000000000 --- a/lib/symfony/polyfill-php80/Resources/stubs/Stringable.php +++ /dev/null @@ -1,11 +0,0 @@ -<?php - -if (\PHP_VERSION_ID < 80000) { - interface Stringable - { - /** - * @return string - */ - public function __toString(); - } -} diff --git a/lib/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php b/lib/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php deleted file mode 100644 index 37937cbfa..000000000 --- a/lib/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -if (\PHP_VERSION_ID < 80000) { - class UnhandledMatchError extends Error - { - } -} diff --git a/lib/symfony/polyfill-php80/Resources/stubs/ValueError.php b/lib/symfony/polyfill-php80/Resources/stubs/ValueError.php deleted file mode 100644 index a3a9b88b0..000000000 --- a/lib/symfony/polyfill-php80/Resources/stubs/ValueError.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -if (\PHP_VERSION_ID < 80000) { - class ValueError extends Error - { - } -} diff --git a/lib/symfony/polyfill-php80/bootstrap.php b/lib/symfony/polyfill-php80/bootstrap.php deleted file mode 100644 index e5f7dbc1a..000000000 --- a/lib/symfony/polyfill-php80/bootstrap.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Php80 as p; - -if (\PHP_VERSION_ID >= 80000) { - return; -} - -if (!defined('FILTER_VALIDATE_BOOL') && defined('FILTER_VALIDATE_BOOLEAN')) { - define('FILTER_VALIDATE_BOOL', \FILTER_VALIDATE_BOOLEAN); -} - -if (!function_exists('fdiv')) { - function fdiv(float $num1, float $num2): float { return p\Php80::fdiv($num1, $num2); } -} -if (!function_exists('preg_last_error_msg')) { - function preg_last_error_msg(): string { return p\Php80::preg_last_error_msg(); } -} -if (!function_exists('str_contains')) { - function str_contains(?string $haystack, ?string $needle): bool { return p\Php80::str_contains($haystack ?? '', $needle ?? ''); } -} -if (!function_exists('str_starts_with')) { - function str_starts_with(?string $haystack, ?string $needle): bool { return p\Php80::str_starts_with($haystack ?? '', $needle ?? ''); } -} -if (!function_exists('str_ends_with')) { - function str_ends_with(?string $haystack, ?string $needle): bool { return p\Php80::str_ends_with($haystack ?? '', $needle ?? ''); } -} -if (!function_exists('get_debug_type')) { - function get_debug_type($value): string { return p\Php80::get_debug_type($value); } -} -if (!function_exists('get_resource_id')) { - function get_resource_id($resource): int { return p\Php80::get_resource_id($resource); } -} diff --git a/lib/symfony/polyfill-php80/composer.json b/lib/symfony/polyfill-php80/composer.json deleted file mode 100644 index cd3e9b65f..000000000 --- a/lib/symfony/polyfill-php80/composer.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "symfony/polyfill-php80", - "type": "library", - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "keywords": ["polyfill", "shim", "compatibility", "portable"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.1" - }, - "autoload": { - "psr-4": { "Symfony\\Polyfill\\Php80\\": "" }, - "files": [ "bootstrap.php" ], - "classmap": [ "Resources/stubs" ] - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - } -} diff --git a/lib/symfony/polyfill-php81/LICENSE b/lib/symfony/polyfill-php81/LICENSE deleted file mode 100644 index efb17f98e..000000000 --- a/lib/symfony/polyfill-php81/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2021 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -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/lib/symfony/polyfill-php81/Php81.php b/lib/symfony/polyfill-php81/Php81.php deleted file mode 100644 index f0507b765..000000000 --- a/lib/symfony/polyfill-php81/Php81.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Php81; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -final class Php81 -{ - public static function array_is_list(array $array): bool - { - if ([] === $array || $array === array_values($array)) { - return true; - } - - $nextKey = -1; - - foreach ($array as $k => $v) { - if ($k !== ++$nextKey) { - return false; - } - } - - return true; - } -} diff --git a/lib/symfony/polyfill-php81/README.md b/lib/symfony/polyfill-php81/README.md deleted file mode 100644 index 7d8dd1907..000000000 --- a/lib/symfony/polyfill-php81/README.md +++ /dev/null @@ -1,17 +0,0 @@ -Symfony Polyfill / Php81 -======================== - -This component provides features added to PHP 8.1 core: - -- [`array_is_list`](https://php.net/array_is_list) -- [`enum_exists`](https://php.net/enum-exists) -- [`MYSQLI_REFRESH_REPLICA`](https://php.net/mysqli.constants#constantmysqli-refresh-replica) constant -- [`ReturnTypeWillChange`](https://wiki.php.net/rfc/internal_method_return_types) - -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/lib/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php b/lib/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php deleted file mode 100644 index f4cad34f6..000000000 --- a/lib/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php +++ /dev/null @@ -1,11 +0,0 @@ -<?php - -if (\PHP_VERSION_ID < 80100) { - #[Attribute(Attribute::TARGET_METHOD)] - final class ReturnTypeWillChange - { - public function __construct() - { - } - } -} diff --git a/lib/symfony/polyfill-php81/bootstrap.php b/lib/symfony/polyfill-php81/bootstrap.php deleted file mode 100644 index 9f872e02f..000000000 --- a/lib/symfony/polyfill-php81/bootstrap.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Php81 as p; - -if (\PHP_VERSION_ID >= 80100) { - return; -} - -if (defined('MYSQLI_REFRESH_SLAVE') && !defined('MYSQLI_REFRESH_REPLICA')) { - define('MYSQLI_REFRESH_REPLICA', 64); -} - -if (!function_exists('array_is_list')) { - function array_is_list(array $array): bool { return p\Php81::array_is_list($array); } -} - -if (!function_exists('enum_exists')) { - function enum_exists(string $enum, bool $autoload = true): bool { return $autoload && class_exists($enum) && false; } -} diff --git a/lib/symfony/polyfill-php81/composer.json b/lib/symfony/polyfill-php81/composer.json deleted file mode 100644 index 014da788e..000000000 --- a/lib/symfony/polyfill-php81/composer.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "symfony/polyfill-php81", - "type": "library", - "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", - "keywords": ["polyfill", "shim", "compatibility", "portable"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.1" - }, - "autoload": { - "psr-4": { "Symfony\\Polyfill\\Php81\\": "" }, - "files": [ "bootstrap.php" ], - "classmap": [ "Resources/stubs" ] - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - } -} diff --git a/lib/symfony/property-access/CHANGELOG.md b/lib/symfony/property-access/CHANGELOG.md deleted file mode 100644 index f90c6f5e7..000000000 --- a/lib/symfony/property-access/CHANGELOG.md +++ /dev/null @@ -1,70 +0,0 @@ -CHANGELOG -========= - -5.3.0 ------ - - * deprecate passing a boolean as the second argument of `PropertyAccessor::__construct()`, expecting a combination of bitwise flags instead - -5.2.0 ------ - - * deprecated passing a boolean as the first argument of `PropertyAccessor::__construct()`, expecting a combination of bitwise flags instead - * added the ability to disable usage of the magic `__get` & `__set` methods - -5.1.0 ------ - - * Added an `UninitializedPropertyException` - * Linking to PropertyInfo extractor to remove a lot of duplicate code - -4.4.0 ------ - - * deprecated passing `null` as `$defaultLifetime` 2nd argument of `PropertyAccessor::createCache()` method, - pass `0` instead - -4.3.0 ------ - - * added a `$throwExceptionOnInvalidPropertyPath` argument to the PropertyAccessor constructor. - * added `enableExceptionOnInvalidPropertyPath()`, `disableExceptionOnInvalidPropertyPath()` and - `isExceptionOnInvalidPropertyPath()` methods to `PropertyAccessorBuilder` - -4.0.0 ------ - - * removed the `StringUtil` class, use `Symfony\Component\Inflector\Inflector` - -3.1.0 ------ - - * deprecated the `StringUtil` class, use `Symfony\Component\Inflector\Inflector` - instead - -2.7.0 ------- - - * `UnexpectedTypeException` now expects three constructor arguments: The invalid property value, - the `PropertyPathInterface` object and the current index of the property path. - -2.5.0 ------- - - * allowed non alpha numeric characters in second level and deeper object properties names - * [BC BREAK] when accessing an index on an object that does not implement - ArrayAccess, a NoSuchIndexException is now thrown instead of the - semantically wrong NoSuchPropertyException - * [BC BREAK] added isReadable() and isWritable() to PropertyAccessorInterface - -2.3.0 ------- - - * added PropertyAccessorBuilder, to enable or disable the support of "__call" - * added support for "__call" in the PropertyAccessor (disabled by default) - * [BC BREAK] changed PropertyAccessor to continue its search for a property or - method even if a non-public match was found. Before, a PropertyAccessDeniedException - was thrown in this case. Class PropertyAccessDeniedException was removed - now. - * deprecated PropertyAccess::getPropertyAccessor - * added PropertyAccess::createPropertyAccessor and PropertyAccess::createPropertyAccessorBuilder diff --git a/lib/symfony/property-access/Exception/AccessException.php b/lib/symfony/property-access/Exception/AccessException.php deleted file mode 100644 index b3a854646..000000000 --- a/lib/symfony/property-access/Exception/AccessException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyAccess\Exception; - -/** - * Thrown when a property path is not available. - * - * @author Stéphane Escandell <stephane.escandell@gmail.com> - */ -class AccessException extends RuntimeException -{ -} diff --git a/lib/symfony/property-access/Exception/ExceptionInterface.php b/lib/symfony/property-access/Exception/ExceptionInterface.php deleted file mode 100644 index fabf9a080..000000000 --- a/lib/symfony/property-access/Exception/ExceptionInterface.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyAccess\Exception; - -/** - * Marker interface for the PropertyAccess component. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface ExceptionInterface extends \Throwable -{ -} diff --git a/lib/symfony/property-access/Exception/InvalidArgumentException.php b/lib/symfony/property-access/Exception/InvalidArgumentException.php deleted file mode 100644 index 47bc7e150..000000000 --- a/lib/symfony/property-access/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyAccess\Exception; - -/** - * Base InvalidArgumentException for the PropertyAccess component. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/lib/symfony/property-access/Exception/InvalidPropertyPathException.php b/lib/symfony/property-access/Exception/InvalidPropertyPathException.php deleted file mode 100644 index 69de31cee..000000000 --- a/lib/symfony/property-access/Exception/InvalidPropertyPathException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyAccess\Exception; - -/** - * Thrown when a property path is malformed. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class InvalidPropertyPathException extends RuntimeException -{ -} diff --git a/lib/symfony/property-access/Exception/NoSuchIndexException.php b/lib/symfony/property-access/Exception/NoSuchIndexException.php deleted file mode 100644 index 597b9904a..000000000 --- a/lib/symfony/property-access/Exception/NoSuchIndexException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyAccess\Exception; - -/** - * Thrown when an index cannot be found. - * - * @author Stéphane Escandell <stephane.escandell@gmail.com> - */ -class NoSuchIndexException extends AccessException -{ -} diff --git a/lib/symfony/property-access/Exception/NoSuchPropertyException.php b/lib/symfony/property-access/Exception/NoSuchPropertyException.php deleted file mode 100644 index 1c7eda5f8..000000000 --- a/lib/symfony/property-access/Exception/NoSuchPropertyException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyAccess\Exception; - -/** - * Thrown when a property cannot be found. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class NoSuchPropertyException extends AccessException -{ -} diff --git a/lib/symfony/property-access/Exception/OutOfBoundsException.php b/lib/symfony/property-access/Exception/OutOfBoundsException.php deleted file mode 100644 index a3c45597d..000000000 --- a/lib/symfony/property-access/Exception/OutOfBoundsException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyAccess\Exception; - -/** - * Base OutOfBoundsException for the PropertyAccess component. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface -{ -} diff --git a/lib/symfony/property-access/Exception/RuntimeException.php b/lib/symfony/property-access/Exception/RuntimeException.php deleted file mode 100644 index 9fe843e30..000000000 --- a/lib/symfony/property-access/Exception/RuntimeException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyAccess\Exception; - -/** - * Base RuntimeException for the PropertyAccess component. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class RuntimeException extends \RuntimeException implements ExceptionInterface -{ -} diff --git a/lib/symfony/property-access/Exception/UnexpectedTypeException.php b/lib/symfony/property-access/Exception/UnexpectedTypeException.php deleted file mode 100644 index 78bc41673..000000000 --- a/lib/symfony/property-access/Exception/UnexpectedTypeException.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyAccess\Exception; - -use Symfony\Component\PropertyAccess\PropertyPathInterface; - -/** - * Thrown when a value does not match an expected type. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class UnexpectedTypeException extends RuntimeException -{ - /** - * @param mixed $value The unexpected value found while traversing property path - * @param int $pathIndex The property path index when the unexpected value was found - */ - public function __construct($value, PropertyPathInterface $path, int $pathIndex) - { - $message = sprintf( - 'PropertyAccessor requires a graph of objects or arrays to operate on, '. - 'but it found type "%s" while trying to traverse path "%s" at property "%s".', - \gettype($value), - (string) $path, - $path->getElement($pathIndex) - ); - - parent::__construct($message); - } -} diff --git a/lib/symfony/property-access/Exception/UninitializedPropertyException.php b/lib/symfony/property-access/Exception/UninitializedPropertyException.php deleted file mode 100644 index c0d69735d..000000000 --- a/lib/symfony/property-access/Exception/UninitializedPropertyException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyAccess\Exception; - -/** - * Thrown when a property is not initialized. - * - * @author Jules Pietri <jules@heahprod.com> - */ -class UninitializedPropertyException extends AccessException -{ -} diff --git a/lib/symfony/property-access/LICENSE b/lib/symfony/property-access/LICENSE deleted file mode 100644 index 0138f8f07..000000000 --- a/lib/symfony/property-access/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-present Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/lib/symfony/property-access/PropertyAccess.php b/lib/symfony/property-access/PropertyAccess.php deleted file mode 100644 index 1953ac096..000000000 --- a/lib/symfony/property-access/PropertyAccess.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyAccess; - -/** - * Entry point of the PropertyAccess component. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -final class PropertyAccess -{ - /** - * Creates a property accessor with the default configuration. - */ - public static function createPropertyAccessor(): PropertyAccessor - { - return self::createPropertyAccessorBuilder()->getPropertyAccessor(); - } - - public static function createPropertyAccessorBuilder(): PropertyAccessorBuilder - { - return new PropertyAccessorBuilder(); - } - - /** - * This class cannot be instantiated. - */ - private function __construct() - { - } -} diff --git a/lib/symfony/property-access/PropertyAccessor.php b/lib/symfony/property-access/PropertyAccessor.php deleted file mode 100644 index a611f2654..000000000 --- a/lib/symfony/property-access/PropertyAccessor.php +++ /dev/null @@ -1,748 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyAccess; - -use Psr\Cache\CacheItemPoolInterface; -use Psr\Log\LoggerInterface; -use Psr\Log\NullLogger; -use Symfony\Component\Cache\Adapter\AdapterInterface; -use Symfony\Component\Cache\Adapter\ApcuAdapter; -use Symfony\Component\Cache\Adapter\NullAdapter; -use Symfony\Component\PropertyAccess\Exception\AccessException; -use Symfony\Component\PropertyAccess\Exception\InvalidArgumentException; -use Symfony\Component\PropertyAccess\Exception\NoSuchIndexException; -use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException; -use Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException; -use Symfony\Component\PropertyAccess\Exception\UninitializedPropertyException; -use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor; -use Symfony\Component\PropertyInfo\PropertyReadInfo; -use Symfony\Component\PropertyInfo\PropertyReadInfoExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyWriteInfo; -use Symfony\Component\PropertyInfo\PropertyWriteInfoExtractorInterface; - -/** - * Default implementation of {@link PropertyAccessorInterface}. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * @author Kévin Dunglas <dunglas@gmail.com> - * @author Nicolas Grekas <p@tchwork.com> - */ -class PropertyAccessor implements PropertyAccessorInterface -{ - /** @var int Allow none of the magic methods */ - public const DISALLOW_MAGIC_METHODS = ReflectionExtractor::DISALLOW_MAGIC_METHODS; - /** @var int Allow magic __get methods */ - public const MAGIC_GET = ReflectionExtractor::ALLOW_MAGIC_GET; - /** @var int Allow magic __set methods */ - public const MAGIC_SET = ReflectionExtractor::ALLOW_MAGIC_SET; - /** @var int Allow magic __call methods */ - public const MAGIC_CALL = ReflectionExtractor::ALLOW_MAGIC_CALL; - - public const DO_NOT_THROW = 0; - public const THROW_ON_INVALID_INDEX = 1; - public const THROW_ON_INVALID_PROPERTY_PATH = 2; - - private const VALUE = 0; - private const REF = 1; - private const IS_REF_CHAINED = 2; - private const CACHE_PREFIX_READ = 'r'; - private const CACHE_PREFIX_WRITE = 'w'; - private const CACHE_PREFIX_PROPERTY_PATH = 'p'; - - private $magicMethodsFlags; - private $ignoreInvalidIndices; - private $ignoreInvalidProperty; - - /** - * @var CacheItemPoolInterface - */ - private $cacheItemPool; - - private $propertyPathCache = []; - - /** - * @var PropertyReadInfoExtractorInterface - */ - private $readInfoExtractor; - - /** - * @var PropertyWriteInfoExtractorInterface - */ - private $writeInfoExtractor; - private $readPropertyCache = []; - private $writePropertyCache = []; - private const RESULT_PROTO = [self::VALUE => null]; - - /** - * Should not be used by application code. Use - * {@link PropertyAccess::createPropertyAccessor()} instead. - * - * @param int $magicMethods A bitwise combination of the MAGIC_* constants - * to specify the allowed magic methods (__get, __set, __call) - * or self::DISALLOW_MAGIC_METHODS for none - * @param int $throw A bitwise combination of the THROW_* constants - * to specify when exceptions should be thrown - * @param PropertyReadInfoExtractorInterface $readInfoExtractor - * @param PropertyWriteInfoExtractorInterface $writeInfoExtractor - */ - public function __construct($magicMethods = self::MAGIC_GET | self::MAGIC_SET, $throw = self::THROW_ON_INVALID_PROPERTY_PATH, CacheItemPoolInterface $cacheItemPool = null, $readInfoExtractor = null, $writeInfoExtractor = null) - { - if (\is_bool($magicMethods)) { - trigger_deprecation('symfony/property-access', '5.2', 'Passing a boolean as the first argument to "%s()" is deprecated. Pass a combination of bitwise flags instead (i.e an integer).', __METHOD__); - - $magicMethods = ($magicMethods ? self::MAGIC_CALL : 0) | self::MAGIC_GET | self::MAGIC_SET; - } elseif (!\is_int($magicMethods)) { - throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be an integer, "%s" given.', __METHOD__, get_debug_type($readInfoExtractor))); - } - - if (\is_bool($throw)) { - trigger_deprecation('symfony/property-access', '5.3', 'Passing a boolean as the second argument to "%s()" is deprecated. Pass a combination of bitwise flags instead (i.e an integer).', __METHOD__); - - $throw = $throw ? self::THROW_ON_INVALID_INDEX : self::DO_NOT_THROW; - - if (!\is_bool($readInfoExtractor)) { - $throw |= self::THROW_ON_INVALID_PROPERTY_PATH; - } - } - - if (\is_bool($readInfoExtractor)) { - trigger_deprecation('symfony/property-access', '5.3', 'Passing a boolean as the fourth argument to "%s()" is deprecated. Pass a combination of bitwise flags as the second argument instead (i.e an integer).', __METHOD__); - - if ($readInfoExtractor) { - $throw |= self::THROW_ON_INVALID_PROPERTY_PATH; - } - - $readInfoExtractor = $writeInfoExtractor; - $writeInfoExtractor = 4 < \func_num_args() ? func_get_arg(4) : null; - } - - if (null !== $readInfoExtractor && !$readInfoExtractor instanceof PropertyReadInfoExtractorInterface) { - throw new \TypeError(sprintf('Argument 4 passed to "%s()" must be null or an instance of "%s", "%s" given.', __METHOD__, PropertyReadInfoExtractorInterface::class, get_debug_type($readInfoExtractor))); - } - - if (null !== $writeInfoExtractor && !$writeInfoExtractor instanceof PropertyWriteInfoExtractorInterface) { - throw new \TypeError(sprintf('Argument 5 passed to "%s()" must be null or an instance of "%s", "%s" given.', __METHOD__, PropertyWriteInfoExtractorInterface::class, get_debug_type($writeInfoExtractor))); - } - - $this->magicMethodsFlags = $magicMethods; - $this->ignoreInvalidIndices = 0 === ($throw & self::THROW_ON_INVALID_INDEX); - $this->cacheItemPool = $cacheItemPool instanceof NullAdapter ? null : $cacheItemPool; // Replace the NullAdapter by the null value - $this->ignoreInvalidProperty = 0 === ($throw & self::THROW_ON_INVALID_PROPERTY_PATH); - $this->readInfoExtractor = $readInfoExtractor ?? new ReflectionExtractor([], null, null, false); - $this->writeInfoExtractor = $writeInfoExtractor ?? new ReflectionExtractor(['set'], null, null, false); - } - - /** - * {@inheritdoc} - */ - public function getValue($objectOrArray, $propertyPath) - { - $zval = [ - self::VALUE => $objectOrArray, - ]; - - if (\is_object($objectOrArray) && false === strpbrk((string) $propertyPath, '.[')) { - return $this->readProperty($zval, $propertyPath, $this->ignoreInvalidProperty)[self::VALUE]; - } - - $propertyPath = $this->getPropertyPath($propertyPath); - - $propertyValues = $this->readPropertiesUntil($zval, $propertyPath, $propertyPath->getLength(), $this->ignoreInvalidIndices); - - return $propertyValues[\count($propertyValues) - 1][self::VALUE]; - } - - /** - * {@inheritdoc} - */ - public function setValue(&$objectOrArray, $propertyPath, $value) - { - if (\is_object($objectOrArray) && false === strpbrk((string) $propertyPath, '.[')) { - $zval = [ - self::VALUE => $objectOrArray, - ]; - - try { - $this->writeProperty($zval, $propertyPath, $value); - - return; - } catch (\TypeError $e) { - self::throwInvalidArgumentException($e->getMessage(), $e->getTrace(), 0, $propertyPath, $e); - // It wasn't thrown in this class so rethrow it - throw $e; - } - } - - $propertyPath = $this->getPropertyPath($propertyPath); - - $zval = [ - self::VALUE => $objectOrArray, - self::REF => &$objectOrArray, - ]; - $propertyValues = $this->readPropertiesUntil($zval, $propertyPath, $propertyPath->getLength() - 1); - $overwrite = true; - - try { - for ($i = \count($propertyValues) - 1; 0 <= $i; --$i) { - $zval = $propertyValues[$i]; - unset($propertyValues[$i]); - - // You only need set value for current element if: - // 1. it's the parent of the last index element - // OR - // 2. its child is not passed by reference - // - // This may avoid unnecessary value setting process for array elements. - // For example: - // '[a][b][c]' => 'old-value' - // If you want to change its value to 'new-value', - // you only need set value for '[a][b][c]' and it's safe to ignore '[a][b]' and '[a]' - if ($overwrite) { - $property = $propertyPath->getElement($i); - - if ($propertyPath->isIndex($i)) { - if ($overwrite = !isset($zval[self::REF])) { - $ref = &$zval[self::REF]; - $ref = $zval[self::VALUE]; - } - $this->writeIndex($zval, $property, $value); - if ($overwrite) { - $zval[self::VALUE] = $zval[self::REF]; - } - } else { - $this->writeProperty($zval, $property, $value); - } - - // if current element is an object - // OR - // if current element's reference chain is not broken - current element - // as well as all its ancients in the property path are all passed by reference, - // then there is no need to continue the value setting process - if (\is_object($zval[self::VALUE]) || isset($zval[self::IS_REF_CHAINED])) { - break; - } - } - - $value = $zval[self::VALUE]; - } - } catch (\TypeError $e) { - self::throwInvalidArgumentException($e->getMessage(), $e->getTrace(), 0, $propertyPath, $e); - - // It wasn't thrown in this class so rethrow it - throw $e; - } - } - - private static function throwInvalidArgumentException(string $message, array $trace, int $i, string $propertyPath, \Throwable $previous = null): void - { - if (!isset($trace[$i]['file']) || __FILE__ !== $trace[$i]['file']) { - return; - } - - if (\PHP_VERSION_ID < 80000) { - if (preg_match('/^Typed property \S+::\$\S+ must be (\S+), (\S+) used$/', $message, $matches)) { - [, $expectedType, $actualType] = $matches; - - throw new InvalidArgumentException(sprintf('Expected argument of type "%s", "%s" given at property path "%s".', $expectedType, 'NULL' === $actualType ? 'null' : $actualType, $propertyPath), 0, $previous); - } - - if (!str_starts_with($message, 'Argument ')) { - return; - } - - $pos = strpos($message, $delim = 'must be of the type ') ?: (strpos($message, $delim = 'must be an instance of ') ?: strpos($message, $delim = 'must implement interface ')); - $pos += \strlen($delim); - $j = strpos($message, ',', $pos); - $type = substr($message, 2 + $j, strpos($message, ' given', $j) - $j - 2); - $message = substr($message, $pos, $j - $pos); - - throw new InvalidArgumentException(sprintf('Expected argument of type "%s", "%s" given at property path "%s".', $message, 'NULL' === $type ? 'null' : $type, $propertyPath), 0, $previous); - } - - if (preg_match('/^\S+::\S+\(\): Argument #\d+ \(\$\S+\) must be of type (\S+), (\S+) given/', $message, $matches)) { - [, $expectedType, $actualType] = $matches; - - throw new InvalidArgumentException(sprintf('Expected argument of type "%s", "%s" given at property path "%s".', $expectedType, 'NULL' === $actualType ? 'null' : $actualType, $propertyPath), 0, $previous); - } - if (preg_match('/^Cannot assign (\S+) to property \S+::\$\S+ of type (\S+)$/', $message, $matches)) { - [, $actualType, $expectedType] = $matches; - - throw new InvalidArgumentException(sprintf('Expected argument of type "%s", "%s" given at property path "%s".', $expectedType, 'NULL' === $actualType ? 'null' : $actualType, $propertyPath), 0, $previous); - } - } - - /** - * {@inheritdoc} - */ - public function isReadable($objectOrArray, $propertyPath) - { - if (!$propertyPath instanceof PropertyPathInterface) { - $propertyPath = new PropertyPath($propertyPath); - } - - try { - $zval = [ - self::VALUE => $objectOrArray, - ]; - $this->readPropertiesUntil($zval, $propertyPath, $propertyPath->getLength(), $this->ignoreInvalidIndices); - - return true; - } catch (AccessException $e) { - return false; - } catch (UnexpectedTypeException $e) { - return false; - } - } - - /** - * {@inheritdoc} - */ - public function isWritable($objectOrArray, $propertyPath) - { - $propertyPath = $this->getPropertyPath($propertyPath); - - try { - $zval = [ - self::VALUE => $objectOrArray, - ]; - $propertyValues = $this->readPropertiesUntil($zval, $propertyPath, $propertyPath->getLength() - 1); - - for ($i = \count($propertyValues) - 1; 0 <= $i; --$i) { - $zval = $propertyValues[$i]; - unset($propertyValues[$i]); - - if ($propertyPath->isIndex($i)) { - if (!$zval[self::VALUE] instanceof \ArrayAccess && !\is_array($zval[self::VALUE])) { - return false; - } - } elseif (!\is_object($zval[self::VALUE]) || !$this->isPropertyWritable($zval[self::VALUE], $propertyPath->getElement($i))) { - return false; - } - - if (\is_object($zval[self::VALUE])) { - return true; - } - } - - return true; - } catch (AccessException $e) { - return false; - } catch (UnexpectedTypeException $e) { - return false; - } - } - - /** - * Reads the path from an object up to a given path index. - * - * @throws UnexpectedTypeException if a value within the path is neither object nor array - * @throws NoSuchIndexException If a non-existing index is accessed - */ - private function readPropertiesUntil(array $zval, PropertyPathInterface $propertyPath, int $lastIndex, bool $ignoreInvalidIndices = true): array - { - if (!\is_object($zval[self::VALUE]) && !\is_array($zval[self::VALUE])) { - throw new UnexpectedTypeException($zval[self::VALUE], $propertyPath, 0); - } - - // Add the root object to the list - $propertyValues = [$zval]; - - for ($i = 0; $i < $lastIndex; ++$i) { - $property = $propertyPath->getElement($i); - $isIndex = $propertyPath->isIndex($i); - - if ($isIndex) { - // Create missing nested arrays on demand - if (($zval[self::VALUE] instanceof \ArrayAccess && !$zval[self::VALUE]->offsetExists($property)) || - (\is_array($zval[self::VALUE]) && !isset($zval[self::VALUE][$property]) && !\array_key_exists($property, $zval[self::VALUE])) - ) { - if (!$ignoreInvalidIndices) { - if (!\is_array($zval[self::VALUE])) { - if (!$zval[self::VALUE] instanceof \Traversable) { - throw new NoSuchIndexException(sprintf('Cannot read index "%s" while trying to traverse path "%s".', $property, (string) $propertyPath)); - } - - $zval[self::VALUE] = iterator_to_array($zval[self::VALUE]); - } - - throw new NoSuchIndexException(sprintf('Cannot read index "%s" while trying to traverse path "%s". Available indices are "%s".', $property, (string) $propertyPath, print_r(array_keys($zval[self::VALUE]), true))); - } - - if ($i + 1 < $propertyPath->getLength()) { - if (isset($zval[self::REF])) { - $zval[self::VALUE][$property] = []; - $zval[self::REF] = $zval[self::VALUE]; - } else { - $zval[self::VALUE] = [$property => []]; - } - } - } - - $zval = $this->readIndex($zval, $property); - } else { - $zval = $this->readProperty($zval, $property, $this->ignoreInvalidProperty); - } - - // the final value of the path must not be validated - if ($i + 1 < $propertyPath->getLength() && !\is_object($zval[self::VALUE]) && !\is_array($zval[self::VALUE])) { - throw new UnexpectedTypeException($zval[self::VALUE], $propertyPath, $i + 1); - } - - if (isset($zval[self::REF]) && (0 === $i || isset($propertyValues[$i - 1][self::IS_REF_CHAINED]))) { - // Set the IS_REF_CHAINED flag to true if: - // current property is passed by reference and - // it is the first element in the property path or - // the IS_REF_CHAINED flag of its parent element is true - // Basically, this flag is true only when the reference chain from the top element to current element is not broken - $zval[self::IS_REF_CHAINED] = true; - } - - $propertyValues[] = $zval; - } - - return $propertyValues; - } - - /** - * Reads a key from an array-like structure. - * - * @param string|int $index The key to read - * - * @throws NoSuchIndexException If the array does not implement \ArrayAccess or it is not an array - */ - private function readIndex(array $zval, $index): array - { - if (!$zval[self::VALUE] instanceof \ArrayAccess && !\is_array($zval[self::VALUE])) { - throw new NoSuchIndexException(sprintf('Cannot read index "%s" from object of type "%s" because it doesn\'t implement \ArrayAccess.', $index, get_debug_type($zval[self::VALUE]))); - } - - $result = self::RESULT_PROTO; - - if (isset($zval[self::VALUE][$index])) { - $result[self::VALUE] = $zval[self::VALUE][$index]; - - if (!isset($zval[self::REF])) { - // Save creating references when doing read-only lookups - } elseif (\is_array($zval[self::VALUE])) { - $result[self::REF] = &$zval[self::REF][$index]; - } elseif (\is_object($result[self::VALUE])) { - $result[self::REF] = $result[self::VALUE]; - } - } - - return $result; - } - - /** - * Reads the value of a property from an object. - * - * @throws NoSuchPropertyException If $ignoreInvalidProperty is false and the property does not exist or is not public - */ - private function readProperty(array $zval, string $property, bool $ignoreInvalidProperty = false): array - { - if (!\is_object($zval[self::VALUE])) { - throw new NoSuchPropertyException(sprintf('Cannot read property "%s" from an array. Maybe you intended to write the property path as "[%1$s]" instead.', $property)); - } - - $result = self::RESULT_PROTO; - $object = $zval[self::VALUE]; - $class = \get_class($object); - $access = $this->getReadInfo($class, $property); - - if (null !== $access) { - $name = $access->getName(); - $type = $access->getType(); - - try { - if (PropertyReadInfo::TYPE_METHOD === $type) { - try { - $result[self::VALUE] = $object->$name(); - } catch (\TypeError $e) { - [$trace] = $e->getTrace(); - - // handle uninitialized properties in PHP >= 7 - if (__FILE__ === $trace['file'] - && $name === $trace['function'] - && $object instanceof $trace['class'] - && preg_match('/Return value (?:of .*::\w+\(\) )?must be of (?:the )?type (\w+), null returned$/', $e->getMessage(), $matches) - ) { - throw new UninitializedPropertyException(sprintf('The method "%s::%s()" returned "null", but expected type "%3$s". Did you forget to initialize a property or to make the return type nullable using "?%3$s"?', get_debug_type($object), $name, $matches[1]), 0, $e); - } - - throw $e; - } - } elseif (PropertyReadInfo::TYPE_PROPERTY === $type) { - if ($access->canBeReference() && !isset($object->$name) && !\array_key_exists($name, (array) $object) && (\PHP_VERSION_ID < 70400 || !(new \ReflectionProperty($class, $name))->hasType())) { - throw new UninitializedPropertyException(sprintf('The property "%s::$%s" is not initialized.', $class, $name)); - } - - $result[self::VALUE] = $object->$name; - - if (isset($zval[self::REF]) && $access->canBeReference()) { - $result[self::REF] = &$object->$name; - } - } - } catch (\Error $e) { - // handle uninitialized properties in PHP >= 7.4 - if (\PHP_VERSION_ID >= 70400 && preg_match('/^Typed property ([\w\\\\@]+)::\$(\w+) must not be accessed before initialization$/', $e->getMessage(), $matches)) { - $r = new \ReflectionProperty(str_contains($matches[1], '@anonymous') ? $class : $matches[1], $matches[2]); - $type = ($type = $r->getType()) instanceof \ReflectionNamedType ? $type->getName() : (string) $type; - - throw new UninitializedPropertyException(sprintf('The property "%s::$%s" is not readable because it is typed "%s". You should initialize it or declare a default value instead.', $matches[1], $r->getName(), $type), 0, $e); - } - - throw $e; - } - } elseif (property_exists($object, $property) && \array_key_exists($property, (array) $object)) { - $result[self::VALUE] = $object->$property; - if (isset($zval[self::REF])) { - $result[self::REF] = &$object->$property; - } - } elseif (!$ignoreInvalidProperty) { - throw new NoSuchPropertyException(sprintf('Can\'t get a way to read the property "%s" in class "%s".', $property, $class)); - } - - // Objects are always passed around by reference - if (isset($zval[self::REF]) && \is_object($result[self::VALUE])) { - $result[self::REF] = $result[self::VALUE]; - } - - return $result; - } - - /** - * Guesses how to read the property value. - */ - private function getReadInfo(string $class, string $property): ?PropertyReadInfo - { - $key = str_replace('\\', '.', $class).'..'.$property; - - if (isset($this->readPropertyCache[$key])) { - return $this->readPropertyCache[$key]; - } - - if ($this->cacheItemPool) { - $item = $this->cacheItemPool->getItem(self::CACHE_PREFIX_READ.rawurlencode($key)); - if ($item->isHit()) { - return $this->readPropertyCache[$key] = $item->get(); - } - } - - $accessor = $this->readInfoExtractor->getReadInfo($class, $property, [ - 'enable_getter_setter_extraction' => true, - 'enable_magic_methods_extraction' => $this->magicMethodsFlags, - 'enable_constructor_extraction' => false, - ]); - - if (isset($item)) { - $this->cacheItemPool->save($item->set($accessor)); - } - - return $this->readPropertyCache[$key] = $accessor; - } - - /** - * Sets the value of an index in a given array-accessible value. - * - * @param string|int $index The index to write at - * @param mixed $value The value to write - * - * @throws NoSuchIndexException If the array does not implement \ArrayAccess or it is not an array - */ - private function writeIndex(array $zval, $index, $value) - { - if (!$zval[self::VALUE] instanceof \ArrayAccess && !\is_array($zval[self::VALUE])) { - throw new NoSuchIndexException(sprintf('Cannot modify index "%s" in object of type "%s" because it doesn\'t implement \ArrayAccess.', $index, get_debug_type($zval[self::VALUE]))); - } - - $zval[self::REF][$index] = $value; - } - - /** - * Sets the value of a property in the given object. - * - * @param mixed $value The value to write - * - * @throws NoSuchPropertyException if the property does not exist or is not public - */ - private function writeProperty(array $zval, string $property, $value) - { - if (!\is_object($zval[self::VALUE])) { - throw new NoSuchPropertyException(sprintf('Cannot write property "%s" to an array. Maybe you should write the property path as "[%1$s]" instead?', $property)); - } - - $object = $zval[self::VALUE]; - $class = \get_class($object); - $mutator = $this->getWriteInfo($class, $property, $value); - - if (PropertyWriteInfo::TYPE_NONE !== $mutator->getType()) { - $type = $mutator->getType(); - - if (PropertyWriteInfo::TYPE_METHOD === $type) { - $object->{$mutator->getName()}($value); - } elseif (PropertyWriteInfo::TYPE_PROPERTY === $type) { - $object->{$mutator->getName()} = $value; - } elseif (PropertyWriteInfo::TYPE_ADDER_AND_REMOVER === $type) { - $this->writeCollection($zval, $property, $value, $mutator->getAdderInfo(), $mutator->getRemoverInfo()); - } - } elseif ($object instanceof \stdClass && property_exists($object, $property)) { - $object->$property = $value; - } elseif (!$this->ignoreInvalidProperty) { - if ($mutator->hasErrors()) { - throw new NoSuchPropertyException(implode('. ', $mutator->getErrors()).'.'); - } - - throw new NoSuchPropertyException(sprintf('Could not determine access type for property "%s" in class "%s".', $property, get_debug_type($object))); - } - } - - /** - * Adjusts a collection-valued property by calling add*() and remove*() methods. - */ - private function writeCollection(array $zval, string $property, iterable $collection, PropertyWriteInfo $addMethod, PropertyWriteInfo $removeMethod) - { - // At this point the add and remove methods have been found - $previousValue = $this->readProperty($zval, $property); - $previousValue = $previousValue[self::VALUE]; - - $removeMethodName = $removeMethod->getName(); - $addMethodName = $addMethod->getName(); - - if ($previousValue instanceof \Traversable) { - $previousValue = iterator_to_array($previousValue); - } - if ($previousValue && \is_array($previousValue)) { - if (\is_object($collection)) { - $collection = iterator_to_array($collection); - } - foreach ($previousValue as $key => $item) { - if (!\in_array($item, $collection, true)) { - unset($previousValue[$key]); - $zval[self::VALUE]->$removeMethodName($item); - } - } - } else { - $previousValue = false; - } - - foreach ($collection as $item) { - if (!$previousValue || !\in_array($item, $previousValue, true)) { - $zval[self::VALUE]->$addMethodName($item); - } - } - } - - private function getWriteInfo(string $class, string $property, $value): PropertyWriteInfo - { - $useAdderAndRemover = is_iterable($value); - $key = str_replace('\\', '.', $class).'..'.$property.'..'.(int) $useAdderAndRemover; - - if (isset($this->writePropertyCache[$key])) { - return $this->writePropertyCache[$key]; - } - - if ($this->cacheItemPool) { - $item = $this->cacheItemPool->getItem(self::CACHE_PREFIX_WRITE.rawurlencode($key)); - if ($item->isHit()) { - return $this->writePropertyCache[$key] = $item->get(); - } - } - - $mutator = $this->writeInfoExtractor->getWriteInfo($class, $property, [ - 'enable_getter_setter_extraction' => true, - 'enable_magic_methods_extraction' => $this->magicMethodsFlags, - 'enable_constructor_extraction' => false, - 'enable_adder_remover_extraction' => $useAdderAndRemover, - ]); - - if (isset($item)) { - $this->cacheItemPool->save($item->set($mutator)); - } - - return $this->writePropertyCache[$key] = $mutator; - } - - /** - * Returns whether a property is writable in the given object. - */ - private function isPropertyWritable(object $object, string $property): bool - { - $mutatorForArray = $this->getWriteInfo(\get_class($object), $property, []); - - if (PropertyWriteInfo::TYPE_NONE !== $mutatorForArray->getType() || ($object instanceof \stdClass && property_exists($object, $property))) { - return true; - } - - $mutator = $this->getWriteInfo(\get_class($object), $property, ''); - - return PropertyWriteInfo::TYPE_NONE !== $mutator->getType() || ($object instanceof \stdClass && property_exists($object, $property)); - } - - /** - * Gets a PropertyPath instance and caches it. - * - * @param string|PropertyPath $propertyPath - */ - private function getPropertyPath($propertyPath): PropertyPath - { - if ($propertyPath instanceof PropertyPathInterface) { - // Don't call the copy constructor has it is not needed here - return $propertyPath; - } - - if (isset($this->propertyPathCache[$propertyPath])) { - return $this->propertyPathCache[$propertyPath]; - } - - if ($this->cacheItemPool) { - $item = $this->cacheItemPool->getItem(self::CACHE_PREFIX_PROPERTY_PATH.rawurlencode($propertyPath)); - if ($item->isHit()) { - return $this->propertyPathCache[$propertyPath] = $item->get(); - } - } - - $propertyPathInstance = new PropertyPath($propertyPath); - if (isset($item)) { - $item->set($propertyPathInstance); - $this->cacheItemPool->save($item); - } - - return $this->propertyPathCache[$propertyPath] = $propertyPathInstance; - } - - /** - * Creates the APCu adapter if applicable. - * - * @return AdapterInterface - * - * @throws \LogicException When the Cache Component isn't available - */ - public static function createCache(string $namespace, int $defaultLifetime, string $version, LoggerInterface $logger = null) - { - if (!class_exists(ApcuAdapter::class)) { - throw new \LogicException(sprintf('The Symfony Cache component must be installed to use "%s()".', __METHOD__)); - } - - if (!ApcuAdapter::isSupported()) { - return new NullAdapter(); - } - - $apcu = new ApcuAdapter($namespace, $defaultLifetime / 5, $version); - if ('cli' === \PHP_SAPI && !filter_var(\ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) { - $apcu->setLogger(new NullLogger()); - } elseif (null !== $logger) { - $apcu->setLogger($logger); - } - - return $apcu; - } -} diff --git a/lib/symfony/property-access/PropertyAccessorBuilder.php b/lib/symfony/property-access/PropertyAccessorBuilder.php deleted file mode 100644 index 68c1984c6..000000000 --- a/lib/symfony/property-access/PropertyAccessorBuilder.php +++ /dev/null @@ -1,308 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyAccess; - -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\PropertyInfo\PropertyReadInfoExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyWriteInfoExtractorInterface; - -/** - * A configurable builder to create a PropertyAccessor. - * - * @author Jérémie Augustin <jeremie.augustin@pixel-cookers.com> - */ -class PropertyAccessorBuilder -{ - /** @var int */ - private $magicMethods = PropertyAccessor::MAGIC_GET | PropertyAccessor::MAGIC_SET; - private $throwExceptionOnInvalidIndex = false; - private $throwExceptionOnInvalidPropertyPath = true; - - /** - * @var CacheItemPoolInterface|null - */ - private $cacheItemPool; - - /** - * @var PropertyReadInfoExtractorInterface|null - */ - private $readInfoExtractor; - - /** - * @var PropertyWriteInfoExtractorInterface|null - */ - private $writeInfoExtractor; - - /** - * Enables the use of all magic methods by the PropertyAccessor. - * - * @return $this - */ - public function enableMagicMethods(): self - { - $this->magicMethods = PropertyAccessor::MAGIC_GET | PropertyAccessor::MAGIC_SET | PropertyAccessor::MAGIC_CALL; - - return $this; - } - - /** - * Disable the use of all magic methods by the PropertyAccessor. - * - * @return $this - */ - public function disableMagicMethods(): self - { - $this->magicMethods = PropertyAccessor::DISALLOW_MAGIC_METHODS; - - return $this; - } - - /** - * Enables the use of "__call" by the PropertyAccessor. - * - * @return $this - */ - public function enableMagicCall() - { - $this->magicMethods |= PropertyAccessor::MAGIC_CALL; - - return $this; - } - - /** - * Enables the use of "__get" by the PropertyAccessor. - */ - public function enableMagicGet(): self - { - $this->magicMethods |= PropertyAccessor::MAGIC_GET; - - return $this; - } - - /** - * Enables the use of "__set" by the PropertyAccessor. - * - * @return $this - */ - public function enableMagicSet(): self - { - $this->magicMethods |= PropertyAccessor::MAGIC_SET; - - return $this; - } - - /** - * Disables the use of "__call" by the PropertyAccessor. - * - * @return $this - */ - public function disableMagicCall() - { - $this->magicMethods &= ~PropertyAccessor::MAGIC_CALL; - - return $this; - } - - /** - * Disables the use of "__get" by the PropertyAccessor. - * - * @return $this - */ - public function disableMagicGet(): self - { - $this->magicMethods &= ~PropertyAccessor::MAGIC_GET; - - return $this; - } - - /** - * Disables the use of "__set" by the PropertyAccessor. - * - * @return $this - */ - public function disableMagicSet(): self - { - $this->magicMethods &= ~PropertyAccessor::MAGIC_SET; - - return $this; - } - - /** - * @return bool whether the use of "__call" by the PropertyAccessor is enabled - */ - public function isMagicCallEnabled() - { - return (bool) ($this->magicMethods & PropertyAccessor::MAGIC_CALL); - } - - /** - * @return bool whether the use of "__get" by the PropertyAccessor is enabled - */ - public function isMagicGetEnabled(): bool - { - return $this->magicMethods & PropertyAccessor::MAGIC_GET; - } - - /** - * @return bool whether the use of "__set" by the PropertyAccessor is enabled - */ - public function isMagicSetEnabled(): bool - { - return $this->magicMethods & PropertyAccessor::MAGIC_SET; - } - - /** - * Enables exceptions when reading a non-existing index. - * - * This has no influence on writing non-existing indices with PropertyAccessorInterface::setValue() - * which are always created on-the-fly. - * - * @return $this - */ - public function enableExceptionOnInvalidIndex() - { - $this->throwExceptionOnInvalidIndex = true; - - return $this; - } - - /** - * Disables exceptions when reading a non-existing index. - * - * Instead, null is returned when calling PropertyAccessorInterface::getValue() on a non-existing index. - * - * @return $this - */ - public function disableExceptionOnInvalidIndex() - { - $this->throwExceptionOnInvalidIndex = false; - - return $this; - } - - /** - * @return bool whether an exception is thrown or null is returned when reading a non-existing index - */ - public function isExceptionOnInvalidIndexEnabled() - { - return $this->throwExceptionOnInvalidIndex; - } - - /** - * Enables exceptions when reading a non-existing property. - * - * This has no influence on writing non-existing indices with PropertyAccessorInterface::setValue() - * which are always created on-the-fly. - * - * @return $this - */ - public function enableExceptionOnInvalidPropertyPath() - { - $this->throwExceptionOnInvalidPropertyPath = true; - - return $this; - } - - /** - * Disables exceptions when reading a non-existing index. - * - * Instead, null is returned when calling PropertyAccessorInterface::getValue() on a non-existing index. - * - * @return $this - */ - public function disableExceptionOnInvalidPropertyPath() - { - $this->throwExceptionOnInvalidPropertyPath = false; - - return $this; - } - - /** - * @return bool whether an exception is thrown or null is returned when reading a non-existing property - */ - public function isExceptionOnInvalidPropertyPath() - { - return $this->throwExceptionOnInvalidPropertyPath; - } - - /** - * Sets a cache system. - * - * @return $this - */ - public function setCacheItemPool(CacheItemPoolInterface $cacheItemPool = null) - { - $this->cacheItemPool = $cacheItemPool; - - return $this; - } - - /** - * Gets the used cache system. - * - * @return CacheItemPoolInterface|null - */ - public function getCacheItemPool() - { - return $this->cacheItemPool; - } - - /** - * @return $this - */ - public function setReadInfoExtractor(?PropertyReadInfoExtractorInterface $readInfoExtractor) - { - $this->readInfoExtractor = $readInfoExtractor; - - return $this; - } - - public function getReadInfoExtractor(): ?PropertyReadInfoExtractorInterface - { - return $this->readInfoExtractor; - } - - /** - * @return $this - */ - public function setWriteInfoExtractor(?PropertyWriteInfoExtractorInterface $writeInfoExtractor) - { - $this->writeInfoExtractor = $writeInfoExtractor; - - return $this; - } - - public function getWriteInfoExtractor(): ?PropertyWriteInfoExtractorInterface - { - return $this->writeInfoExtractor; - } - - /** - * Builds and returns a new PropertyAccessor object. - * - * @return PropertyAccessorInterface - */ - public function getPropertyAccessor() - { - $throw = PropertyAccessor::DO_NOT_THROW; - - if ($this->throwExceptionOnInvalidIndex) { - $throw |= PropertyAccessor::THROW_ON_INVALID_INDEX; - } - - if ($this->throwExceptionOnInvalidPropertyPath) { - $throw |= PropertyAccessor::THROW_ON_INVALID_PROPERTY_PATH; - } - - return new PropertyAccessor($this->magicMethods, $throw, $this->cacheItemPool, $this->readInfoExtractor, $this->writeInfoExtractor); - } -} diff --git a/lib/symfony/property-access/PropertyAccessorInterface.php b/lib/symfony/property-access/PropertyAccessorInterface.php deleted file mode 100644 index c5226b2fe..000000000 --- a/lib/symfony/property-access/PropertyAccessorInterface.php +++ /dev/null @@ -1,114 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyAccess; - -/** - * Writes and reads values to/from an object/array graph. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -interface PropertyAccessorInterface -{ - /** - * Sets the value at the end of the property path of the object graph. - * - * Example: - * - * use Symfony\Component\PropertyAccess\PropertyAccess; - * - * $propertyAccessor = PropertyAccess::createPropertyAccessor(); - * - * echo $propertyAccessor->setValue($object, 'child.name', 'Fabien'); - * // equals echo $object->getChild()->setName('Fabien'); - * - * This method first tries to find a public setter for each property in the - * path. The name of the setter must be the camel-cased property name - * prefixed with "set". - * - * If the setter does not exist, this method tries to find a public - * property. The value of the property is then changed. - * - * If neither is found, an exception is thrown. - * - * @param object|array $objectOrArray The object or array to modify - * @param string|PropertyPathInterface $propertyPath The property path to modify - * @param mixed $value The value to set at the end of the property path - * - * @throws Exception\InvalidArgumentException If the property path is invalid - * @throws Exception\AccessException If a property/index does not exist or is not public - * @throws Exception\UnexpectedTypeException If a value within the path is neither object nor array - */ - public function setValue(&$objectOrArray, $propertyPath, $value); - - /** - * Returns the value at the end of the property path of the object graph. - * - * Example: - * - * use Symfony\Component\PropertyAccess\PropertyAccess; - * - * $propertyAccessor = PropertyAccess::createPropertyAccessor(); - * - * echo $propertyAccessor->getValue($object, 'child.name'); - * // equals echo $object->getChild()->getName(); - * - * This method first tries to find a public getter for each property in the - * path. The name of the getter must be the camel-cased property name - * prefixed with "get", "is", or "has". - * - * If the getter does not exist, this method tries to find a public - * property. The value of the property is then returned. - * - * If none of them are found, an exception is thrown. - * - * @param object|array $objectOrArray The object or array to traverse - * @param string|PropertyPathInterface $propertyPath The property path to read - * - * @return mixed - * - * @throws Exception\InvalidArgumentException If the property path is invalid - * @throws Exception\AccessException If a property/index does not exist or is not public - * @throws Exception\UnexpectedTypeException If a value within the path is neither object - * nor array - */ - public function getValue($objectOrArray, $propertyPath); - - /** - * Returns whether a value can be written at a given property path. - * - * Whenever this method returns true, {@link setValue()} is guaranteed not - * to throw an exception when called with the same arguments. - * - * @param object|array $objectOrArray The object or array to check - * @param string|PropertyPathInterface $propertyPath The property path to check - * - * @return bool - * - * @throws Exception\InvalidArgumentException If the property path is invalid - */ - public function isWritable($objectOrArray, $propertyPath); - - /** - * Returns whether a property path can be read from an object graph. - * - * Whenever this method returns true, {@link getValue()} is guaranteed not - * to throw an exception when called with the same arguments. - * - * @param object|array $objectOrArray The object or array to check - * @param string|PropertyPathInterface $propertyPath The property path to check - * - * @return bool - * - * @throws Exception\InvalidArgumentException If the property path is invalid - */ - public function isReadable($objectOrArray, $propertyPath); -} diff --git a/lib/symfony/property-access/PropertyPath.php b/lib/symfony/property-access/PropertyPath.php deleted file mode 100644 index e99c019a8..000000000 --- a/lib/symfony/property-access/PropertyPath.php +++ /dev/null @@ -1,208 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyAccess; - -use Symfony\Component\PropertyAccess\Exception\InvalidArgumentException; -use Symfony\Component\PropertyAccess\Exception\InvalidPropertyPathException; -use Symfony\Component\PropertyAccess\Exception\OutOfBoundsException; - -/** - * Default implementation of {@link PropertyPathInterface}. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @implements \IteratorAggregate<int, string> - */ -class PropertyPath implements \IteratorAggregate, PropertyPathInterface -{ - /** - * Character used for separating between plural and singular of an element. - */ - public const SINGULAR_SEPARATOR = '|'; - - /** - * The elements of the property path. - * - * @var list<string> - */ - private $elements = []; - - /** - * The number of elements in the property path. - * - * @var int - */ - private $length; - - /** - * Contains a Boolean for each property in $elements denoting whether this - * element is an index. It is a property otherwise. - * - * @var array - */ - private $isIndex = []; - - /** - * String representation of the path. - * - * @var string - */ - private $pathAsString; - - /** - * Constructs a property path from a string. - * - * @param PropertyPath|string $propertyPath The property path as string or instance - * - * @throws InvalidArgumentException If the given path is not a string - * @throws InvalidPropertyPathException If the syntax of the property path is not valid - */ - public function __construct($propertyPath) - { - // Can be used as copy constructor - if ($propertyPath instanceof self) { - /* @var PropertyPath $propertyPath */ - $this->elements = $propertyPath->elements; - $this->length = $propertyPath->length; - $this->isIndex = $propertyPath->isIndex; - $this->pathAsString = $propertyPath->pathAsString; - - return; - } - if (!\is_string($propertyPath)) { - throw new InvalidArgumentException(sprintf('The property path constructor needs a string or an instance of "Symfony\Component\PropertyAccess\PropertyPath". Got: "%s".', get_debug_type($propertyPath))); - } - - if ('' === $propertyPath) { - throw new InvalidPropertyPathException('The property path should not be empty.'); - } - - $this->pathAsString = $propertyPath; - $position = 0; - $remaining = $propertyPath; - - // first element is evaluated differently - no leading dot for properties - $pattern = '/^(([^\.\[]++)|\[([^\]]++)\])(.*)/'; - - while (preg_match($pattern, $remaining, $matches)) { - if ('' !== $matches[2]) { - $element = $matches[2]; - $this->isIndex[] = false; - } else { - $element = $matches[3]; - $this->isIndex[] = true; - } - - $this->elements[] = $element; - - $position += \strlen($matches[1]); - $remaining = $matches[4]; - $pattern = '/^(\.([^\.|\[]++)|\[([^\]]++)\])(.*)/'; - } - - if ('' !== $remaining) { - throw new InvalidPropertyPathException(sprintf('Could not parse property path "%s". Unexpected token "%s" at position %d.', $propertyPath, $remaining[0], $position)); - } - - $this->length = \count($this->elements); - } - - /** - * {@inheritdoc} - */ - public function __toString() - { - return $this->pathAsString; - } - - /** - * {@inheritdoc} - */ - public function getLength() - { - return $this->length; - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - if ($this->length <= 1) { - return null; - } - - $parent = clone $this; - - --$parent->length; - $parent->pathAsString = substr($parent->pathAsString, 0, max(strrpos($parent->pathAsString, '.'), strrpos($parent->pathAsString, '['))); - array_pop($parent->elements); - array_pop($parent->isIndex); - - return $parent; - } - - /** - * Returns a new iterator for this path. - * - * @return PropertyPathIteratorInterface - */ - #[\ReturnTypeWillChange] - public function getIterator() - { - return new PropertyPathIterator($this); - } - - /** - * {@inheritdoc} - */ - public function getElements() - { - return $this->elements; - } - - /** - * {@inheritdoc} - */ - public function getElement(int $index) - { - if (!isset($this->elements[$index])) { - throw new OutOfBoundsException(sprintf('The index "%s" is not within the property path.', $index)); - } - - return $this->elements[$index]; - } - - /** - * {@inheritdoc} - */ - public function isProperty(int $index) - { - if (!isset($this->isIndex[$index])) { - throw new OutOfBoundsException(sprintf('The index "%s" is not within the property path.', $index)); - } - - return !$this->isIndex[$index]; - } - - /** - * {@inheritdoc} - */ - public function isIndex(int $index) - { - if (!isset($this->isIndex[$index])) { - throw new OutOfBoundsException(sprintf('The index "%s" is not within the property path.', $index)); - } - - return $this->isIndex[$index]; - } -} diff --git a/lib/symfony/property-access/PropertyPathBuilder.php b/lib/symfony/property-access/PropertyPathBuilder.php deleted file mode 100644 index b521f6ad1..000000000 --- a/lib/symfony/property-access/PropertyPathBuilder.php +++ /dev/null @@ -1,281 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyAccess; - -use Symfony\Component\PropertyAccess\Exception\OutOfBoundsException; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class PropertyPathBuilder -{ - private $elements = []; - private $isIndex = []; - - /** - * Creates a new property path builder. - * - * @param PropertyPathInterface|string|null $path The path to initially store - * in the builder. Optional. - */ - public function __construct($path = null) - { - if (null !== $path) { - $this->append($path); - } - } - - /** - * Appends a (sub-) path to the current path. - * - * @param PropertyPathInterface|string $path The path to append - * @param int $offset The offset where the appended - * piece starts in $path - * @param int $length The length of the appended piece - * If 0, the full path is appended - */ - public function append($path, int $offset = 0, int $length = 0) - { - if (\is_string($path)) { - $path = new PropertyPath($path); - } - - if (0 === $length) { - $end = $path->getLength(); - } else { - $end = $offset + $length; - } - - for (; $offset < $end; ++$offset) { - $this->elements[] = $path->getElement($offset); - $this->isIndex[] = $path->isIndex($offset); - } - } - - /** - * Appends an index element to the current path. - */ - public function appendIndex(string $name) - { - $this->elements[] = $name; - $this->isIndex[] = true; - } - - /** - * Appends a property element to the current path. - */ - public function appendProperty(string $name) - { - $this->elements[] = $name; - $this->isIndex[] = false; - } - - /** - * Removes elements from the current path. - * - * @throws OutOfBoundsException if offset is invalid - */ - public function remove(int $offset, int $length = 1) - { - if (!isset($this->elements[$offset])) { - throw new OutOfBoundsException(sprintf('The offset "%s" is not within the property path.', $offset)); - } - - $this->resize($offset, $length, 0); - } - - /** - * Replaces a sub-path by a different (sub-) path. - * - * @param int $offset The offset at which to replace - * @param int $length The length of the piece to replace - * @param PropertyPathInterface|string $path The path to insert - * @param int $pathOffset The offset where the inserted piece - * starts in $path - * @param int $pathLength The length of the inserted piece - * If 0, the full path is inserted - * - * @throws OutOfBoundsException If the offset is invalid - */ - public function replace(int $offset, int $length, $path, int $pathOffset = 0, int $pathLength = 0) - { - if (\is_string($path)) { - $path = new PropertyPath($path); - } - - if ($offset < 0 && abs($offset) <= $this->getLength()) { - $offset = $this->getLength() + $offset; - } elseif (!isset($this->elements[$offset])) { - throw new OutOfBoundsException('The offset '.$offset.' is not within the property path'); - } - - if (0 === $pathLength) { - $pathLength = $path->getLength() - $pathOffset; - } - - $this->resize($offset, $length, $pathLength); - - for ($i = 0; $i < $pathLength; ++$i) { - $this->elements[$offset + $i] = $path->getElement($pathOffset + $i); - $this->isIndex[$offset + $i] = $path->isIndex($pathOffset + $i); - } - ksort($this->elements); - } - - /** - * Replaces a property element by an index element. - * - * @throws OutOfBoundsException If the offset is invalid - */ - public function replaceByIndex(int $offset, string $name = null) - { - if (!isset($this->elements[$offset])) { - throw new OutOfBoundsException(sprintf('The offset "%s" is not within the property path.', $offset)); - } - - if (null !== $name) { - $this->elements[$offset] = $name; - } - - $this->isIndex[$offset] = true; - } - - /** - * Replaces an index element by a property element. - * - * @throws OutOfBoundsException If the offset is invalid - */ - public function replaceByProperty(int $offset, string $name = null) - { - if (!isset($this->elements[$offset])) { - throw new OutOfBoundsException(sprintf('The offset "%s" is not within the property path.', $offset)); - } - - if (null !== $name) { - $this->elements[$offset] = $name; - } - - $this->isIndex[$offset] = false; - } - - /** - * Returns the length of the current path. - * - * @return int - */ - public function getLength() - { - return \count($this->elements); - } - - /** - * Returns the current property path. - * - * @return PropertyPathInterface|null - */ - public function getPropertyPath() - { - $pathAsString = $this->__toString(); - - return '' !== $pathAsString ? new PropertyPath($pathAsString) : null; - } - - /** - * Returns the current property path as string. - * - * @return string - */ - public function __toString() - { - $string = ''; - - foreach ($this->elements as $offset => $element) { - if ($this->isIndex[$offset]) { - $element = '['.$element.']'; - } elseif ('' !== $string) { - $string .= '.'; - } - - $string .= $element; - } - - return $string; - } - - /** - * Resizes the path so that a chunk of length $cutLength is - * removed at $offset and another chunk of length $insertionLength - * can be inserted. - */ - private function resize(int $offset, int $cutLength, int $insertionLength) - { - // Nothing else to do in this case - if ($insertionLength === $cutLength) { - return; - } - - $length = \count($this->elements); - - if ($cutLength > $insertionLength) { - // More elements should be removed than inserted - $diff = $cutLength - $insertionLength; - $newLength = $length - $diff; - - // Shift elements to the left (left-to-right until the new end) - // Max allowed offset to be shifted is such that - // $offset + $diff < $length (otherwise invalid index access) - // i.e. $offset < $length - $diff = $newLength - for ($i = $offset; $i < $newLength; ++$i) { - $this->elements[$i] = $this->elements[$i + $diff]; - $this->isIndex[$i] = $this->isIndex[$i + $diff]; - } - - // All remaining elements should be removed - $this->elements = \array_slice($this->elements, 0, $i); - $this->isIndex = \array_slice($this->isIndex, 0, $i); - } else { - $diff = $insertionLength - $cutLength; - - $newLength = $length + $diff; - $indexAfterInsertion = $offset + $insertionLength; - - // $diff <= $insertionLength - // $indexAfterInsertion >= $insertionLength - // => $diff <= $indexAfterInsertion - - // In each of the following loops, $i >= $diff must hold, - // otherwise ($i - $diff) becomes negative. - - // Shift old elements to the right to make up space for the - // inserted elements. This needs to be done left-to-right in - // order to preserve an ascending array index order - // Since $i = max($length, $indexAfterInsertion) and $indexAfterInsertion >= $diff, - // $i >= $diff is guaranteed. - for ($i = max($length, $indexAfterInsertion); $i < $newLength; ++$i) { - $this->elements[$i] = $this->elements[$i - $diff]; - $this->isIndex[$i] = $this->isIndex[$i - $diff]; - } - - // Shift remaining elements to the right. Do this right-to-left - // so we don't overwrite elements before copying them - // The last written index is the immediate index after the inserted - // string, because the indices before that will be overwritten - // anyway. - // Since $i >= $indexAfterInsertion and $indexAfterInsertion >= $diff, - // $i >= $diff is guaranteed. - for ($i = $length - 1; $i >= $indexAfterInsertion; --$i) { - $this->elements[$i] = $this->elements[$i - $diff]; - $this->isIndex[$i] = $this->isIndex[$i - $diff]; - } - } - } -} diff --git a/lib/symfony/property-access/PropertyPathInterface.php b/lib/symfony/property-access/PropertyPathInterface.php deleted file mode 100644 index d58ad328f..000000000 --- a/lib/symfony/property-access/PropertyPathInterface.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyAccess; - -/** - * A sequence of property names or array indices. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @extends \Traversable<int, string> - */ -interface PropertyPathInterface extends \Traversable -{ - /** - * Returns the string representation of the property path. - * - * @return string - */ - public function __toString(); - - /** - * Returns the length of the property path, i.e. the number of elements. - * - * @return int - */ - public function getLength(); - - /** - * Returns the parent property path. - * - * The parent property path is the one that contains the same items as - * this one except for the last one. - * - * If this property path only contains one item, null is returned. - * - * @return self|null - */ - public function getParent(); - - /** - * Returns the elements of the property path as array. - * - * @return list<string> - */ - public function getElements(); - - /** - * Returns the element at the given index in the property path. - * - * @param int $index The index key - * - * @return string - * - * @throws Exception\OutOfBoundsException If the offset is invalid - */ - public function getElement(int $index); - - /** - * Returns whether the element at the given index is a property. - * - * @param int $index The index in the property path - * - * @return bool - * - * @throws Exception\OutOfBoundsException If the offset is invalid - */ - public function isProperty(int $index); - - /** - * Returns whether the element at the given index is an array index. - * - * @param int $index The index in the property path - * - * @return bool - * - * @throws Exception\OutOfBoundsException If the offset is invalid - */ - public function isIndex(int $index); -} diff --git a/lib/symfony/property-access/PropertyPathIterator.php b/lib/symfony/property-access/PropertyPathIterator.php deleted file mode 100644 index a3335e31b..000000000 --- a/lib/symfony/property-access/PropertyPathIterator.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyAccess; - -/** - * Traverses a property path and provides additional methods to find out - * information about the current element. - * - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @extends \ArrayIterator<int, string> - */ -class PropertyPathIterator extends \ArrayIterator implements PropertyPathIteratorInterface -{ - protected $path; - - public function __construct(PropertyPathInterface $path) - { - parent::__construct($path->getElements()); - - $this->path = $path; - } - - /** - * {@inheritdoc} - */ - public function isIndex() - { - return $this->path->isIndex($this->key()); - } - - /** - * {@inheritdoc} - */ - public function isProperty() - { - return $this->path->isProperty($this->key()); - } -} diff --git a/lib/symfony/property-access/PropertyPathIteratorInterface.php b/lib/symfony/property-access/PropertyPathIteratorInterface.php deleted file mode 100644 index 0397f9c17..000000000 --- a/lib/symfony/property-access/PropertyPathIteratorInterface.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyAccess; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @extends \SeekableIterator<int, string> - */ -interface PropertyPathIteratorInterface extends \SeekableIterator -{ - /** - * Returns whether the current element in the property path is an array - * index. - * - * @return bool - */ - public function isIndex(); - - /** - * Returns whether the current element in the property path is a property - * name. - * - * @return bool - */ - public function isProperty(); -} diff --git a/lib/symfony/property-access/README.md b/lib/symfony/property-access/README.md deleted file mode 100644 index 29cb233a0..000000000 --- a/lib/symfony/property-access/README.md +++ /dev/null @@ -1,14 +0,0 @@ -PropertyAccess Component -======================== - -The PropertyAccess component provides functions to read and write from/to an -object or array using a simple string notation. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/property_access.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/lib/symfony/property-access/composer.json b/lib/symfony/property-access/composer.json deleted file mode 100644 index b797151a0..000000000 --- a/lib/symfony/property-access/composer.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "symfony/property-access", - "type": "library", - "description": "Provides functions to read and write from/to an object or array using a simple string notation", - "keywords": ["property", "index", "access", "object", "array", "extraction", "injection", "reflection", "property-path"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16", - "symfony/property-info": "^5.2|^6.0" - }, - "require-dev": { - "symfony/cache": "^4.4|^5.0|^6.0" - }, - "suggest": { - "psr/cache-implementation": "To cache access methods." - }, - "autoload": { - "psr-4": { "Symfony\\Component\\PropertyAccess\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/lib/symfony/property-info/CHANGELOG.md b/lib/symfony/property-info/CHANGELOG.md deleted file mode 100644 index 8963b940e..000000000 --- a/lib/symfony/property-info/CHANGELOG.md +++ /dev/null @@ -1,39 +0,0 @@ -CHANGELOG -========= - -5.4 ---- - - * Add PhpStanExtractor - -5.3 ---- - - * Add support for multiple types for collection keys & values - * Deprecate the `Type::getCollectionKeyType()` and `Type::getCollectionValueType()` methods, use `Type::getCollectionKeyTypes()` and `Type::getCollectionValueTypes()` instead - -5.2.0 ------ - - * deprecated the `enable_magic_call_extraction` context option in `ReflectionExtractor::getWriteInfo()` and `ReflectionExtractor::getReadInfo()` in favor of `enable_magic_methods_extraction` - -5.1.0 ------ - - * Add support for extracting accessor and mutator via PHP Reflection - -4.3.0 ------ - - * Added the ability to extract private and protected properties and methods on `ReflectionExtractor` - * Added the ability to extract property type based on its initial value - -4.2.0 ------ - - * added `PropertyInitializableExtractorInterface` to test if a property can be initialized through the constructor (implemented by `ReflectionExtractor`) - -3.3.0 ------ - - * Added `PropertyInfoPass` diff --git a/lib/symfony/property-info/DependencyInjection/PropertyInfoConstructorPass.php b/lib/symfony/property-info/DependencyInjection/PropertyInfoConstructorPass.php deleted file mode 100644 index cab31b365..000000000 --- a/lib/symfony/property-info/DependencyInjection/PropertyInfoConstructorPass.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo\DependencyInjection; - -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * Adds extractors to the property_info.constructor_extractor service. - * - * @author Dmitrii Poddubnyi <dpoddubny@gmail.com> - */ -final class PropertyInfoConstructorPass implements CompilerPassInterface -{ - use PriorityTaggedServiceTrait; - - private $service; - private $tag; - - public function __construct(string $service = 'property_info.constructor_extractor', string $tag = 'property_info.constructor_extractor') - { - if (0 < \func_num_args()) { - trigger_deprecation('symfony/property-info', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->service = $service; - $this->tag = $tag; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition($this->service)) { - return; - } - $definition = $container->getDefinition($this->service); - - $listExtractors = $this->findAndSortTaggedServices($this->tag, $container); - $definition->replaceArgument(0, new IteratorArgument($listExtractors)); - } -} diff --git a/lib/symfony/property-info/DependencyInjection/PropertyInfoPass.php b/lib/symfony/property-info/DependencyInjection/PropertyInfoPass.php deleted file mode 100644 index 289b114f1..000000000 --- a/lib/symfony/property-info/DependencyInjection/PropertyInfoPass.php +++ /dev/null @@ -1,75 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo\DependencyInjection; - -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * Adds extractors to the property_info service. - * - * @author Kévin Dunglas <dunglas@gmail.com> - */ -class PropertyInfoPass implements CompilerPassInterface -{ - use PriorityTaggedServiceTrait; - - private $propertyInfoService; - private $listExtractorTag; - private $typeExtractorTag; - private $descriptionExtractorTag; - private $accessExtractorTag; - private $initializableExtractorTag; - - public function __construct(string $propertyInfoService = 'property_info', string $listExtractorTag = 'property_info.list_extractor', string $typeExtractorTag = 'property_info.type_extractor', string $descriptionExtractorTag = 'property_info.description_extractor', string $accessExtractorTag = 'property_info.access_extractor', string $initializableExtractorTag = 'property_info.initializable_extractor') - { - if (0 < \func_num_args()) { - trigger_deprecation('symfony/property-info', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->propertyInfoService = $propertyInfoService; - $this->listExtractorTag = $listExtractorTag; - $this->typeExtractorTag = $typeExtractorTag; - $this->descriptionExtractorTag = $descriptionExtractorTag; - $this->accessExtractorTag = $accessExtractorTag; - $this->initializableExtractorTag = $initializableExtractorTag; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition($this->propertyInfoService)) { - return; - } - - $definition = $container->getDefinition($this->propertyInfoService); - - $listExtractors = $this->findAndSortTaggedServices($this->listExtractorTag, $container); - $definition->replaceArgument(0, new IteratorArgument($listExtractors)); - - $typeExtractors = $this->findAndSortTaggedServices($this->typeExtractorTag, $container); - $definition->replaceArgument(1, new IteratorArgument($typeExtractors)); - - $descriptionExtractors = $this->findAndSortTaggedServices($this->descriptionExtractorTag, $container); - $definition->replaceArgument(2, new IteratorArgument($descriptionExtractors)); - - $accessExtractors = $this->findAndSortTaggedServices($this->accessExtractorTag, $container); - $definition->replaceArgument(3, new IteratorArgument($accessExtractors)); - - $initializableExtractors = $this->findAndSortTaggedServices($this->initializableExtractorTag, $container); - $definition->setArgument(4, new IteratorArgument($initializableExtractors)); - } -} diff --git a/lib/symfony/property-info/Extractor/ConstructorArgumentTypeExtractorInterface.php b/lib/symfony/property-info/Extractor/ConstructorArgumentTypeExtractorInterface.php deleted file mode 100644 index cbde902e9..000000000 --- a/lib/symfony/property-info/Extractor/ConstructorArgumentTypeExtractorInterface.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo\Extractor; - -use Symfony\Component\PropertyInfo\Type; - -/** - * Infers the constructor argument type. - * - * @author Dmitrii Poddubnyi <dpoddubny@gmail.com> - * - * @internal - */ -interface ConstructorArgumentTypeExtractorInterface -{ - /** - * Gets types of an argument from constructor. - * - * @return Type[]|null - * - * @internal - */ - public function getTypesFromConstructor(string $class, string $property): ?array; -} diff --git a/lib/symfony/property-info/Extractor/ConstructorExtractor.php b/lib/symfony/property-info/Extractor/ConstructorExtractor.php deleted file mode 100644 index fb32634fb..000000000 --- a/lib/symfony/property-info/Extractor/ConstructorExtractor.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo\Extractor; - -use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; - -/** - * Extracts the constructor argument type using ConstructorArgumentTypeExtractorInterface implementations. - * - * @author Dmitrii Poddubnyi <dpoddubny@gmail.com> - */ -final class ConstructorExtractor implements PropertyTypeExtractorInterface -{ - private $extractors; - - /** - * @param iterable<int, ConstructorArgumentTypeExtractorInterface> $extractors - */ - public function __construct(iterable $extractors = []) - { - $this->extractors = $extractors; - } - - /** - * {@inheritdoc} - */ - public function getTypes(string $class, string $property, array $context = []): ?array - { - foreach ($this->extractors as $extractor) { - $value = $extractor->getTypesFromConstructor($class, $property); - if (null !== $value) { - return $value; - } - } - - return null; - } -} diff --git a/lib/symfony/property-info/Extractor/PhpDocExtractor.php b/lib/symfony/property-info/Extractor/PhpDocExtractor.php deleted file mode 100644 index 2cecfcf8b..000000000 --- a/lib/symfony/property-info/Extractor/PhpDocExtractor.php +++ /dev/null @@ -1,360 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo\Extractor; - -use phpDocumentor\Reflection\DocBlock; -use phpDocumentor\Reflection\DocBlock\Tags\InvalidTag; -use phpDocumentor\Reflection\DocBlockFactory; -use phpDocumentor\Reflection\DocBlockFactoryInterface; -use phpDocumentor\Reflection\Types\Context; -use phpDocumentor\Reflection\Types\ContextFactory; -use Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\PropertyInfo\Util\PhpDocTypeHelper; - -/** - * Extracts data using a PHPDoc parser. - * - * @author Kévin Dunglas <dunglas@gmail.com> - * - * @final - */ -class PhpDocExtractor implements PropertyDescriptionExtractorInterface, PropertyTypeExtractorInterface, ConstructorArgumentTypeExtractorInterface -{ - public const PROPERTY = 0; - public const ACCESSOR = 1; - public const MUTATOR = 2; - - /** - * @var array<string, array{DocBlock|null, int|null, string|null}> - */ - private $docBlocks = []; - - /** - * @var Context[] - */ - private $contexts = []; - - private $docBlockFactory; - private $contextFactory; - private $phpDocTypeHelper; - private $mutatorPrefixes; - private $accessorPrefixes; - private $arrayMutatorPrefixes; - - /** - * @param string[]|null $mutatorPrefixes - * @param string[]|null $accessorPrefixes - * @param string[]|null $arrayMutatorPrefixes - */ - public function __construct(DocBlockFactoryInterface $docBlockFactory = null, array $mutatorPrefixes = null, array $accessorPrefixes = null, array $arrayMutatorPrefixes = null) - { - if (!class_exists(DocBlockFactory::class)) { - throw new \LogicException(sprintf('Unable to use the "%s" class as the "phpdocumentor/reflection-docblock" package is not installed. Try running composer require "phpdocumentor/reflection-docblock".', __CLASS__)); - } - - $this->docBlockFactory = $docBlockFactory ?: DocBlockFactory::createInstance(); - $this->contextFactory = new ContextFactory(); - $this->phpDocTypeHelper = new PhpDocTypeHelper(); - $this->mutatorPrefixes = $mutatorPrefixes ?? ReflectionExtractor::$defaultMutatorPrefixes; - $this->accessorPrefixes = $accessorPrefixes ?? ReflectionExtractor::$defaultAccessorPrefixes; - $this->arrayMutatorPrefixes = $arrayMutatorPrefixes ?? ReflectionExtractor::$defaultArrayMutatorPrefixes; - } - - /** - * {@inheritdoc} - */ - public function getShortDescription(string $class, string $property, array $context = []): ?string - { - /** @var $docBlock DocBlock */ - [$docBlock] = $this->getDocBlock($class, $property); - if (!$docBlock) { - return null; - } - - $shortDescription = $docBlock->getSummary(); - - if (!empty($shortDescription)) { - return $shortDescription; - } - - foreach ($docBlock->getTagsByName('var') as $var) { - if ($var && !$var instanceof InvalidTag) { - $varDescription = $var->getDescription()->render(); - - if (!empty($varDescription)) { - return $varDescription; - } - } - } - - return null; - } - - /** - * {@inheritdoc} - */ - public function getLongDescription(string $class, string $property, array $context = []): ?string - { - /** @var $docBlock DocBlock */ - [$docBlock] = $this->getDocBlock($class, $property); - if (!$docBlock) { - return null; - } - - $contents = $docBlock->getDescription()->render(); - - return '' === $contents ? null : $contents; - } - - /** - * {@inheritdoc} - */ - public function getTypes(string $class, string $property, array $context = []): ?array - { - /** @var $docBlock DocBlock */ - [$docBlock, $source, $prefix] = $this->getDocBlock($class, $property); - if (!$docBlock) { - return null; - } - - switch ($source) { - case self::PROPERTY: - $tag = 'var'; - break; - - case self::ACCESSOR: - $tag = 'return'; - break; - - case self::MUTATOR: - $tag = 'param'; - break; - } - - $parentClass = null; - $types = []; - /** @var DocBlock\Tags\Var_|DocBlock\Tags\Return_|DocBlock\Tags\Param $tag */ - foreach ($docBlock->getTagsByName($tag) as $tag) { - if ($tag && !$tag instanceof InvalidTag && null !== $tag->getType()) { - foreach ($this->phpDocTypeHelper->getTypes($tag->getType()) as $type) { - switch ($type->getClassName()) { - case 'self': - case 'static': - $resolvedClass = $class; - break; - - case 'parent': - if (false !== $resolvedClass = $parentClass ?? $parentClass = get_parent_class($class)) { - break; - } - // no break - - default: - $types[] = $type; - continue 2; - } - - $types[] = new Type(Type::BUILTIN_TYPE_OBJECT, $type->isNullable(), $resolvedClass, $type->isCollection(), $type->getCollectionKeyTypes(), $type->getCollectionValueTypes()); - } - } - } - - if (!isset($types[0])) { - return null; - } - - if (!\in_array($prefix, $this->arrayMutatorPrefixes)) { - return $types; - } - - return [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), $types[0])]; - } - - /** - * {@inheritdoc} - */ - public function getTypesFromConstructor(string $class, string $property): ?array - { - $docBlock = $this->getDocBlockFromConstructor($class, $property); - - if (!$docBlock) { - return null; - } - - $types = []; - /** @var DocBlock\Tags\Var_|DocBlock\Tags\Return_|DocBlock\Tags\Param $tag */ - foreach ($docBlock->getTagsByName('param') as $tag) { - if ($tag && null !== $tag->getType()) { - $types[] = $this->phpDocTypeHelper->getTypes($tag->getType()); - } - } - - if (!isset($types[0]) || [] === $types[0]) { - return null; - } - - return array_merge([], ...$types); - } - - private function getDocBlockFromConstructor(string $class, string $property): ?DocBlock - { - try { - $reflectionClass = new \ReflectionClass($class); - } catch (\ReflectionException $e) { - return null; - } - $reflectionConstructor = $reflectionClass->getConstructor(); - if (!$reflectionConstructor) { - return null; - } - - try { - $docBlock = $this->docBlockFactory->create($reflectionConstructor, $this->contextFactory->createFromReflector($reflectionConstructor)); - - return $this->filterDocBlockParams($docBlock, $property); - } catch (\InvalidArgumentException $e) { - return null; - } - } - - private function filterDocBlockParams(DocBlock $docBlock, string $allowedParam): DocBlock - { - $tags = array_values(array_filter($docBlock->getTagsByName('param'), function ($tag) use ($allowedParam) { - return $tag instanceof DocBlock\Tags\Param && $allowedParam === $tag->getVariableName(); - })); - - return new DocBlock($docBlock->getSummary(), $docBlock->getDescription(), $tags, $docBlock->getContext(), - $docBlock->getLocation(), $docBlock->isTemplateStart(), $docBlock->isTemplateEnd()); - } - - /** - * @return array{DocBlock|null, int|null, string|null} - */ - private function getDocBlock(string $class, string $property): array - { - $propertyHash = sprintf('%s::%s', $class, $property); - - if (isset($this->docBlocks[$propertyHash])) { - return $this->docBlocks[$propertyHash]; - } - - $ucFirstProperty = ucfirst($property); - - switch (true) { - case $docBlock = $this->getDocBlockFromProperty($class, $property): - $data = [$docBlock, self::PROPERTY, null]; - break; - - case [$docBlock] = $this->getDocBlockFromMethod($class, $ucFirstProperty, self::ACCESSOR): - $data = [$docBlock, self::ACCESSOR, null]; - break; - - case [$docBlock, $prefix] = $this->getDocBlockFromMethod($class, $ucFirstProperty, self::MUTATOR): - $data = [$docBlock, self::MUTATOR, $prefix]; - break; - - default: - $data = [null, null, null]; - } - - return $this->docBlocks[$propertyHash] = $data; - } - - private function getDocBlockFromProperty(string $class, string $property): ?DocBlock - { - // Use a ReflectionProperty instead of $class to get the parent class if applicable - try { - $reflectionProperty = new \ReflectionProperty($class, $property); - } catch (\ReflectionException $e) { - return null; - } - - $reflector = $reflectionProperty->getDeclaringClass(); - - foreach ($reflector->getTraits() as $trait) { - if ($trait->hasProperty($property)) { - return $this->getDocBlockFromProperty($trait->getName(), $property); - } - } - - try { - return $this->docBlockFactory->create($reflectionProperty, $this->createFromReflector($reflector)); - } catch (\InvalidArgumentException|\RuntimeException $e) { - return null; - } - } - - /** - * @return array{DocBlock, string}|null - */ - private function getDocBlockFromMethod(string $class, string $ucFirstProperty, int $type): ?array - { - $prefixes = self::ACCESSOR === $type ? $this->accessorPrefixes : $this->mutatorPrefixes; - $prefix = null; - - foreach ($prefixes as $prefix) { - $methodName = $prefix.$ucFirstProperty; - - try { - $reflectionMethod = new \ReflectionMethod($class, $methodName); - if ($reflectionMethod->isStatic()) { - continue; - } - - if ( - (self::ACCESSOR === $type && 0 === $reflectionMethod->getNumberOfRequiredParameters()) || - (self::MUTATOR === $type && $reflectionMethod->getNumberOfParameters() >= 1) - ) { - break; - } - } catch (\ReflectionException $e) { - // Try the next prefix if the method doesn't exist - } - } - - if (!isset($reflectionMethod)) { - return null; - } - - $reflector = $reflectionMethod->getDeclaringClass(); - - foreach ($reflector->getTraits() as $trait) { - if ($trait->hasMethod($methodName)) { - return $this->getDocBlockFromMethod($trait->getName(), $ucFirstProperty, $type); - } - } - - try { - return [$this->docBlockFactory->create($reflectionMethod, $this->createFromReflector($reflector)), $prefix]; - } catch (\InvalidArgumentException|\RuntimeException $e) { - return null; - } - } - - /** - * Prevents a lot of redundant calls to ContextFactory::createForNamespace(). - */ - private function createFromReflector(\ReflectionClass $reflector): Context - { - $cacheKey = $reflector->getNamespaceName().':'.$reflector->getFileName(); - - if (isset($this->contexts[$cacheKey])) { - return $this->contexts[$cacheKey]; - } - - $this->contexts[$cacheKey] = $this->contextFactory->createFromReflector($reflector); - - return $this->contexts[$cacheKey]; - } -} diff --git a/lib/symfony/property-info/Extractor/PhpStanExtractor.php b/lib/symfony/property-info/Extractor/PhpStanExtractor.php deleted file mode 100644 index a964b5036..000000000 --- a/lib/symfony/property-info/Extractor/PhpStanExtractor.php +++ /dev/null @@ -1,289 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo\Extractor; - -use phpDocumentor\Reflection\Types\ContextFactory; -use PHPStan\PhpDocParser\Ast\PhpDoc\InvalidTagValueNode; -use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode; -use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode; -use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode; -use PHPStan\PhpDocParser\Lexer\Lexer; -use PHPStan\PhpDocParser\Parser\ConstExprParser; -use PHPStan\PhpDocParser\Parser\PhpDocParser; -use PHPStan\PhpDocParser\Parser\TokenIterator; -use PHPStan\PhpDocParser\Parser\TypeParser; -use Symfony\Component\PropertyInfo\PhpStan\NameScopeFactory; -use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\PropertyInfo\Util\PhpStanTypeHelper; - -/** - * Extracts data using PHPStan parser. - * - * @author Baptiste Leduc <baptiste.leduc@gmail.com> - */ -final class PhpStanExtractor implements PropertyTypeExtractorInterface, ConstructorArgumentTypeExtractorInterface -{ - private const PROPERTY = 0; - private const ACCESSOR = 1; - private const MUTATOR = 2; - - /** @var PhpDocParser */ - private $phpDocParser; - - /** @var Lexer */ - private $lexer; - - /** @var NameScopeFactory */ - private $nameScopeFactory; - - /** @var array<string, array{PhpDocNode|null, int|null, string|null, string|null}> */ - private $docBlocks = []; - private $phpStanTypeHelper; - private $mutatorPrefixes; - private $accessorPrefixes; - private $arrayMutatorPrefixes; - - /** - * @param list<string>|null $mutatorPrefixes - * @param list<string>|null $accessorPrefixes - * @param list<string>|null $arrayMutatorPrefixes - */ - public function __construct(array $mutatorPrefixes = null, array $accessorPrefixes = null, array $arrayMutatorPrefixes = null) - { - if (!class_exists(ContextFactory::class)) { - throw new \LogicException(sprintf('Unable to use the "%s" class as the "phpdocumentor/type-resolver" package is not installed. Try running composer require "phpdocumentor/type-resolver".', __CLASS__)); - } - - if (!class_exists(PhpDocParser::class)) { - throw new \LogicException(sprintf('Unable to use the "%s" class as the "phpstan/phpdoc-parser" package is not installed. Try running composer require "phpstan/phpdoc-parser".', __CLASS__)); - } - - $this->phpStanTypeHelper = new PhpStanTypeHelper(); - $this->mutatorPrefixes = $mutatorPrefixes ?? ReflectionExtractor::$defaultMutatorPrefixes; - $this->accessorPrefixes = $accessorPrefixes ?? ReflectionExtractor::$defaultAccessorPrefixes; - $this->arrayMutatorPrefixes = $arrayMutatorPrefixes ?? ReflectionExtractor::$defaultArrayMutatorPrefixes; - - $this->phpDocParser = new PhpDocParser(new TypeParser(new ConstExprParser()), new ConstExprParser()); - $this->lexer = new Lexer(); - $this->nameScopeFactory = new NameScopeFactory(); - } - - public function getTypes(string $class, string $property, array $context = []): ?array - { - /** @var PhpDocNode|null $docNode */ - [$docNode, $source, $prefix, $declaringClass] = $this->getDocBlock($class, $property); - $nameScope = $this->nameScopeFactory->create($class, $declaringClass); - if (null === $docNode) { - return null; - } - - switch ($source) { - case self::PROPERTY: - $tag = '@var'; - break; - - case self::ACCESSOR: - $tag = '@return'; - break; - - case self::MUTATOR: - $tag = '@param'; - break; - } - - $parentClass = null; - $types = []; - foreach ($docNode->getTagsByName($tag) as $tagDocNode) { - if ($tagDocNode->value instanceof InvalidTagValueNode) { - continue; - } - - foreach ($this->phpStanTypeHelper->getTypes($tagDocNode->value, $nameScope) as $type) { - switch ($type->getClassName()) { - case 'self': - case 'static': - $resolvedClass = $class; - break; - - case 'parent': - if (false !== $resolvedClass = $parentClass ?? $parentClass = get_parent_class($class)) { - break; - } - // no break - - default: - $types[] = $type; - continue 2; - } - - $types[] = new Type(Type::BUILTIN_TYPE_OBJECT, $type->isNullable(), $resolvedClass, $type->isCollection(), $type->getCollectionKeyTypes(), $type->getCollectionValueTypes()); - } - } - - if (!isset($types[0])) { - return null; - } - - if (!\in_array($prefix, $this->arrayMutatorPrefixes, true)) { - return $types; - } - - return [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), $types[0])]; - } - - public function getTypesFromConstructor(string $class, string $property): ?array - { - if (null === $tagDocNode = $this->getDocBlockFromConstructor($class, $property)) { - return null; - } - - $types = []; - foreach ($this->phpStanTypeHelper->getTypes($tagDocNode, $this->nameScopeFactory->create($class)) as $type) { - $types[] = $type; - } - - if (!isset($types[0])) { - return null; - } - - return $types; - } - - private function getDocBlockFromConstructor(string $class, string $property): ?ParamTagValueNode - { - try { - $reflectionClass = new \ReflectionClass($class); - } catch (\ReflectionException $e) { - return null; - } - - if (null === $reflectionConstructor = $reflectionClass->getConstructor()) { - return null; - } - - if (!$rawDocNode = $reflectionConstructor->getDocComment()) { - return null; - } - - $tokens = new TokenIterator($this->lexer->tokenize($rawDocNode)); - $phpDocNode = $this->phpDocParser->parse($tokens); - $tokens->consumeTokenType(Lexer::TOKEN_END); - - return $this->filterDocBlockParams($phpDocNode, $property); - } - - private function filterDocBlockParams(PhpDocNode $docNode, string $allowedParam): ?ParamTagValueNode - { - $tags = array_values(array_filter($docNode->getTagsByName('@param'), function ($tagNode) use ($allowedParam) { - return $tagNode instanceof PhpDocTagNode && ('$'.$allowedParam) === $tagNode->value->parameterName; - })); - - if (!$tags) { - return null; - } - - return $tags[0]->value; - } - - /** - * @return array{PhpDocNode|null, int|null, string|null, string|null} - */ - private function getDocBlock(string $class, string $property): array - { - $propertyHash = $class.'::'.$property; - - if (isset($this->docBlocks[$propertyHash])) { - return $this->docBlocks[$propertyHash]; - } - - $ucFirstProperty = ucfirst($property); - - if ([$docBlock, $declaringClass] = $this->getDocBlockFromProperty($class, $property)) { - $data = [$docBlock, self::PROPERTY, null, $declaringClass]; - } elseif ([$docBlock, $_, $declaringClass] = $this->getDocBlockFromMethod($class, $ucFirstProperty, self::ACCESSOR)) { - $data = [$docBlock, self::ACCESSOR, null, $declaringClass]; - } elseif ([$docBlock, $prefix, $declaringClass] = $this->getDocBlockFromMethod($class, $ucFirstProperty, self::MUTATOR)) { - $data = [$docBlock, self::MUTATOR, $prefix, $declaringClass]; - } else { - $data = [null, null, null, null]; - } - - return $this->docBlocks[$propertyHash] = $data; - } - - /** - * @return array{PhpDocNode, string}|null - */ - private function getDocBlockFromProperty(string $class, string $property): ?array - { - // Use a ReflectionProperty instead of $class to get the parent class if applicable - try { - $reflectionProperty = new \ReflectionProperty($class, $property); - } catch (\ReflectionException $e) { - return null; - } - - if (null === $rawDocNode = $reflectionProperty->getDocComment() ?: null) { - return null; - } - - $tokens = new TokenIterator($this->lexer->tokenize($rawDocNode)); - $phpDocNode = $this->phpDocParser->parse($tokens); - $tokens->consumeTokenType(Lexer::TOKEN_END); - - return [$phpDocNode, $reflectionProperty->class]; - } - - /** - * @return array{PhpDocNode, string, string}|null - */ - private function getDocBlockFromMethod(string $class, string $ucFirstProperty, int $type): ?array - { - $prefixes = self::ACCESSOR === $type ? $this->accessorPrefixes : $this->mutatorPrefixes; - $prefix = null; - - foreach ($prefixes as $prefix) { - $methodName = $prefix.$ucFirstProperty; - - try { - $reflectionMethod = new \ReflectionMethod($class, $methodName); - if ($reflectionMethod->isStatic()) { - continue; - } - - if ( - (self::ACCESSOR === $type && 0 === $reflectionMethod->getNumberOfRequiredParameters()) - || (self::MUTATOR === $type && $reflectionMethod->getNumberOfParameters() >= 1) - ) { - break; - } - } catch (\ReflectionException $e) { - // Try the next prefix if the method doesn't exist - } - } - - if (!isset($reflectionMethod)) { - return null; - } - - if (null === $rawDocNode = $reflectionMethod->getDocComment() ?: null) { - return null; - } - - $tokens = new TokenIterator($this->lexer->tokenize($rawDocNode)); - $phpDocNode = $this->phpDocParser->parse($tokens); - $tokens->consumeTokenType(Lexer::TOKEN_END); - - return [$phpDocNode, $prefix, $reflectionMethod->class]; - } -} diff --git a/lib/symfony/property-info/Extractor/ReflectionExtractor.php b/lib/symfony/property-info/Extractor/ReflectionExtractor.php deleted file mode 100644 index 4da591238..000000000 --- a/lib/symfony/property-info/Extractor/ReflectionExtractor.php +++ /dev/null @@ -1,885 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo\Extractor; - -use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyInitializableExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyListExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyReadInfo; -use Symfony\Component\PropertyInfo\PropertyReadInfoExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyWriteInfo; -use Symfony\Component\PropertyInfo\PropertyWriteInfoExtractorInterface; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\String\Inflector\EnglishInflector; -use Symfony\Component\String\Inflector\InflectorInterface; - -/** - * Extracts data using the reflection API. - * - * @author Kévin Dunglas <dunglas@gmail.com> - * - * @final - */ -class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTypeExtractorInterface, PropertyAccessExtractorInterface, PropertyInitializableExtractorInterface, PropertyReadInfoExtractorInterface, PropertyWriteInfoExtractorInterface, ConstructorArgumentTypeExtractorInterface -{ - /** - * @internal - */ - public static $defaultMutatorPrefixes = ['add', 'remove', 'set']; - - /** - * @internal - */ - public static $defaultAccessorPrefixes = ['get', 'is', 'has', 'can']; - - /** - * @internal - */ - public static $defaultArrayMutatorPrefixes = ['add', 'remove']; - - public const ALLOW_PRIVATE = 1; - public const ALLOW_PROTECTED = 2; - public const ALLOW_PUBLIC = 4; - - /** @var int Allow none of the magic methods */ - public const DISALLOW_MAGIC_METHODS = 0; - /** @var int Allow magic __get methods */ - public const ALLOW_MAGIC_GET = 1 << 0; - /** @var int Allow magic __set methods */ - public const ALLOW_MAGIC_SET = 1 << 1; - /** @var int Allow magic __call methods */ - public const ALLOW_MAGIC_CALL = 1 << 2; - - private const MAP_TYPES = [ - 'integer' => Type::BUILTIN_TYPE_INT, - 'boolean' => Type::BUILTIN_TYPE_BOOL, - 'double' => Type::BUILTIN_TYPE_FLOAT, - ]; - - private $mutatorPrefixes; - private $accessorPrefixes; - private $arrayMutatorPrefixes; - private $enableConstructorExtraction; - private $methodReflectionFlags; - private $magicMethodsFlags; - private $propertyReflectionFlags; - private $inflector; - - private $arrayMutatorPrefixesFirst; - private $arrayMutatorPrefixesLast; - - /** - * @param string[]|null $mutatorPrefixes - * @param string[]|null $accessorPrefixes - * @param string[]|null $arrayMutatorPrefixes - */ - public function __construct(array $mutatorPrefixes = null, array $accessorPrefixes = null, array $arrayMutatorPrefixes = null, bool $enableConstructorExtraction = true, int $accessFlags = self::ALLOW_PUBLIC, InflectorInterface $inflector = null, int $magicMethodsFlags = self::ALLOW_MAGIC_GET | self::ALLOW_MAGIC_SET) - { - $this->mutatorPrefixes = $mutatorPrefixes ?? self::$defaultMutatorPrefixes; - $this->accessorPrefixes = $accessorPrefixes ?? self::$defaultAccessorPrefixes; - $this->arrayMutatorPrefixes = $arrayMutatorPrefixes ?? self::$defaultArrayMutatorPrefixes; - $this->enableConstructorExtraction = $enableConstructorExtraction; - $this->methodReflectionFlags = $this->getMethodsFlags($accessFlags); - $this->propertyReflectionFlags = $this->getPropertyFlags($accessFlags); - $this->magicMethodsFlags = $magicMethodsFlags; - $this->inflector = $inflector ?? new EnglishInflector(); - - $this->arrayMutatorPrefixesFirst = array_merge($this->arrayMutatorPrefixes, array_diff($this->mutatorPrefixes, $this->arrayMutatorPrefixes)); - $this->arrayMutatorPrefixesLast = array_reverse($this->arrayMutatorPrefixesFirst); - } - - /** - * {@inheritdoc} - */ - public function getProperties(string $class, array $context = []): ?array - { - try { - $reflectionClass = new \ReflectionClass($class); - } catch (\ReflectionException $e) { - return null; - } - - $reflectionProperties = $reflectionClass->getProperties(); - - $properties = []; - foreach ($reflectionProperties as $reflectionProperty) { - if ($reflectionProperty->getModifiers() & $this->propertyReflectionFlags) { - $properties[$reflectionProperty->name] = $reflectionProperty->name; - } - } - - foreach ($reflectionClass->getMethods($this->methodReflectionFlags) as $reflectionMethod) { - if ($reflectionMethod->isStatic()) { - continue; - } - - $propertyName = $this->getPropertyName($reflectionMethod->name, $reflectionProperties); - if (!$propertyName || isset($properties[$propertyName])) { - continue; - } - if ($reflectionClass->hasProperty($lowerCasedPropertyName = lcfirst($propertyName)) || (!$reflectionClass->hasProperty($propertyName) && !preg_match('/^[A-Z]{2,}/', $propertyName))) { - $propertyName = $lowerCasedPropertyName; - } - $properties[$propertyName] = $propertyName; - } - - return $properties ? array_values($properties) : null; - } - - /** - * {@inheritdoc} - */ - public function getTypes(string $class, string $property, array $context = []): ?array - { - if ($fromMutator = $this->extractFromMutator($class, $property)) { - return $fromMutator; - } - - if ($fromAccessor = $this->extractFromAccessor($class, $property)) { - return $fromAccessor; - } - - if ( - ($context['enable_constructor_extraction'] ?? $this->enableConstructorExtraction) && - $fromConstructor = $this->extractFromConstructor($class, $property) - ) { - return $fromConstructor; - } - - if ($fromPropertyDeclaration = $this->extractFromPropertyDeclaration($class, $property)) { - return $fromPropertyDeclaration; - } - - return null; - } - - /** - * {@inheritdoc} - */ - public function getTypesFromConstructor(string $class, string $property): ?array - { - try { - $reflection = new \ReflectionClass($class); - } catch (\ReflectionException $e) { - return null; - } - if (!$reflectionConstructor = $reflection->getConstructor()) { - return null; - } - if (!$reflectionParameter = $this->getReflectionParameterFromConstructor($property, $reflectionConstructor)) { - return null; - } - if (!$reflectionType = $reflectionParameter->getType()) { - return null; - } - if (!$types = $this->extractFromReflectionType($reflectionType, $reflectionConstructor->getDeclaringClass())) { - return null; - } - - return $types; - } - - private function getReflectionParameterFromConstructor(string $property, \ReflectionMethod $reflectionConstructor): ?\ReflectionParameter - { - $reflectionParameter = null; - foreach ($reflectionConstructor->getParameters() as $reflectionParameter) { - if ($reflectionParameter->getName() === $property) { - return $reflectionParameter; - } - } - - return null; - } - - /** - * {@inheritdoc} - */ - public function isReadable(string $class, string $property, array $context = []): ?bool - { - if ($this->isAllowedProperty($class, $property)) { - return true; - } - - return null !== $this->getReadInfo($class, $property, $context); - } - - /** - * {@inheritdoc} - */ - public function isWritable(string $class, string $property, array $context = []): ?bool - { - if ($this->isAllowedProperty($class, $property, true)) { - return true; - } - - [$reflectionMethod] = $this->getMutatorMethod($class, $property); - - return null !== $reflectionMethod; - } - - /** - * {@inheritdoc} - */ - public function isInitializable(string $class, string $property, array $context = []): ?bool - { - try { - $reflectionClass = new \ReflectionClass($class); - } catch (\ReflectionException $e) { - return null; - } - - if (!$reflectionClass->isInstantiable()) { - return false; - } - - if ($constructor = $reflectionClass->getConstructor()) { - foreach ($constructor->getParameters() as $parameter) { - if ($property === $parameter->name) { - return true; - } - } - } elseif ($parentClass = $reflectionClass->getParentClass()) { - return $this->isInitializable($parentClass->getName(), $property); - } - - return false; - } - - /** - * {@inheritdoc} - */ - public function getReadInfo(string $class, string $property, array $context = []): ?PropertyReadInfo - { - try { - $reflClass = new \ReflectionClass($class); - } catch (\ReflectionException $e) { - return null; - } - - $allowGetterSetter = $context['enable_getter_setter_extraction'] ?? false; - $magicMethods = $context['enable_magic_methods_extraction'] ?? $this->magicMethodsFlags; - $allowMagicCall = (bool) ($magicMethods & self::ALLOW_MAGIC_CALL); - $allowMagicGet = (bool) ($magicMethods & self::ALLOW_MAGIC_GET); - - if (isset($context['enable_magic_call_extraction'])) { - trigger_deprecation('symfony/property-info', '5.2', 'Using the "enable_magic_call_extraction" context option in "%s()" is deprecated. Use "enable_magic_methods_extraction" instead.', __METHOD__); - - $allowMagicCall = $context['enable_magic_call_extraction'] ?? false; - } - - $hasProperty = $reflClass->hasProperty($property); - $camelProp = $this->camelize($property); - $getsetter = lcfirst($camelProp); // jQuery style, e.g. read: last(), write: last($item) - - foreach ($this->accessorPrefixes as $prefix) { - $methodName = $prefix.$camelProp; - - if ($reflClass->hasMethod($methodName) && $reflClass->getMethod($methodName)->getModifiers() & $this->methodReflectionFlags && !$reflClass->getMethod($methodName)->getNumberOfRequiredParameters()) { - $method = $reflClass->getMethod($methodName); - - return new PropertyReadInfo(PropertyReadInfo::TYPE_METHOD, $methodName, $this->getReadVisiblityForMethod($method), $method->isStatic(), false); - } - } - - if ($allowGetterSetter && $reflClass->hasMethod($getsetter) && ($reflClass->getMethod($getsetter)->getModifiers() & $this->methodReflectionFlags)) { - $method = $reflClass->getMethod($getsetter); - - return new PropertyReadInfo(PropertyReadInfo::TYPE_METHOD, $getsetter, $this->getReadVisiblityForMethod($method), $method->isStatic(), false); - } - - if ($allowMagicGet && $reflClass->hasMethod('__get') && ($reflClass->getMethod('__get')->getModifiers() & $this->methodReflectionFlags)) { - return new PropertyReadInfo(PropertyReadInfo::TYPE_PROPERTY, $property, PropertyReadInfo::VISIBILITY_PUBLIC, false, false); - } - - if ($hasProperty && ($reflClass->getProperty($property)->getModifiers() & $this->propertyReflectionFlags)) { - $reflProperty = $reflClass->getProperty($property); - - return new PropertyReadInfo(PropertyReadInfo::TYPE_PROPERTY, $property, $this->getReadVisiblityForProperty($reflProperty), $reflProperty->isStatic(), true); - } - - if ($allowMagicCall && $reflClass->hasMethod('__call') && ($reflClass->getMethod('__call')->getModifiers() & $this->methodReflectionFlags)) { - return new PropertyReadInfo(PropertyReadInfo::TYPE_METHOD, 'get'.$camelProp, PropertyReadInfo::VISIBILITY_PUBLIC, false, false); - } - - return null; - } - - /** - * {@inheritdoc} - */ - public function getWriteInfo(string $class, string $property, array $context = []): ?PropertyWriteInfo - { - try { - $reflClass = new \ReflectionClass($class); - } catch (\ReflectionException $e) { - return null; - } - - $allowGetterSetter = $context['enable_getter_setter_extraction'] ?? false; - $magicMethods = $context['enable_magic_methods_extraction'] ?? $this->magicMethodsFlags; - $allowMagicCall = (bool) ($magicMethods & self::ALLOW_MAGIC_CALL); - $allowMagicSet = (bool) ($magicMethods & self::ALLOW_MAGIC_SET); - - if (isset($context['enable_magic_call_extraction'])) { - trigger_deprecation('symfony/property-info', '5.2', 'Using the "enable_magic_call_extraction" context option in "%s()" is deprecated. Use "enable_magic_methods_extraction" instead.', __METHOD__); - - $allowMagicCall = $context['enable_magic_call_extraction'] ?? false; - } - - $allowConstruct = $context['enable_constructor_extraction'] ?? $this->enableConstructorExtraction; - $allowAdderRemover = $context['enable_adder_remover_extraction'] ?? true; - - $camelized = $this->camelize($property); - $constructor = $reflClass->getConstructor(); - $singulars = $this->inflector->singularize($camelized); - $errors = []; - - if (null !== $constructor && $allowConstruct) { - foreach ($constructor->getParameters() as $parameter) { - if ($parameter->getName() === $property) { - return new PropertyWriteInfo(PropertyWriteInfo::TYPE_CONSTRUCTOR, $property); - } - } - } - - [$adderAccessName, $removerAccessName, $adderAndRemoverErrors] = $this->findAdderAndRemover($reflClass, $singulars); - if ($allowAdderRemover && null !== $adderAccessName && null !== $removerAccessName) { - $adderMethod = $reflClass->getMethod($adderAccessName); - $removerMethod = $reflClass->getMethod($removerAccessName); - - $mutator = new PropertyWriteInfo(PropertyWriteInfo::TYPE_ADDER_AND_REMOVER); - $mutator->setAdderInfo(new PropertyWriteInfo(PropertyWriteInfo::TYPE_METHOD, $adderAccessName, $this->getWriteVisiblityForMethod($adderMethod), $adderMethod->isStatic())); - $mutator->setRemoverInfo(new PropertyWriteInfo(PropertyWriteInfo::TYPE_METHOD, $removerAccessName, $this->getWriteVisiblityForMethod($removerMethod), $removerMethod->isStatic())); - - return $mutator; - } - - $errors[] = $adderAndRemoverErrors; - - foreach ($this->mutatorPrefixes as $mutatorPrefix) { - $methodName = $mutatorPrefix.$camelized; - - [$accessible, $methodAccessibleErrors] = $this->isMethodAccessible($reflClass, $methodName, 1); - if (!$accessible) { - $errors[] = $methodAccessibleErrors; - continue; - } - - $method = $reflClass->getMethod($methodName); - - if (!\in_array($mutatorPrefix, $this->arrayMutatorPrefixes, true)) { - return new PropertyWriteInfo(PropertyWriteInfo::TYPE_METHOD, $methodName, $this->getWriteVisiblityForMethod($method), $method->isStatic()); - } - } - - $getsetter = lcfirst($camelized); - - if ($allowGetterSetter) { - [$accessible, $methodAccessibleErrors] = $this->isMethodAccessible($reflClass, $getsetter, 1); - if ($accessible) { - $method = $reflClass->getMethod($getsetter); - - return new PropertyWriteInfo(PropertyWriteInfo::TYPE_METHOD, $getsetter, $this->getWriteVisiblityForMethod($method), $method->isStatic()); - } - - $errors[] = $methodAccessibleErrors; - } - - if ($reflClass->hasProperty($property) && ($reflClass->getProperty($property)->getModifiers() & $this->propertyReflectionFlags)) { - $reflProperty = $reflClass->getProperty($property); - if (\PHP_VERSION_ID < 80100 || !$reflProperty->isReadOnly()) { - return new PropertyWriteInfo(PropertyWriteInfo::TYPE_PROPERTY, $property, $this->getWriteVisiblityForProperty($reflProperty), $reflProperty->isStatic()); - } - - $errors[] = [sprintf('The property "%s" in class "%s" is a promoted readonly property.', $property, $reflClass->getName())]; - $allowMagicSet = $allowMagicCall = false; - } - - if ($allowMagicSet) { - [$accessible, $methodAccessibleErrors] = $this->isMethodAccessible($reflClass, '__set', 2); - if ($accessible) { - return new PropertyWriteInfo(PropertyWriteInfo::TYPE_PROPERTY, $property, PropertyWriteInfo::VISIBILITY_PUBLIC, false); - } - - $errors[] = $methodAccessibleErrors; - } - - if ($allowMagicCall) { - [$accessible, $methodAccessibleErrors] = $this->isMethodAccessible($reflClass, '__call', 2); - if ($accessible) { - return new PropertyWriteInfo(PropertyWriteInfo::TYPE_METHOD, 'set'.$camelized, PropertyWriteInfo::VISIBILITY_PUBLIC, false); - } - - $errors[] = $methodAccessibleErrors; - } - - if (!$allowAdderRemover && null !== $adderAccessName && null !== $removerAccessName) { - $errors[] = [sprintf( - 'The property "%s" in class "%s" can be defined with the methods "%s()" but '. - 'the new value must be an array or an instance of \Traversable', - $property, - $reflClass->getName(), - implode('()", "', [$adderAccessName, $removerAccessName]) - )]; - } - - $noneProperty = new PropertyWriteInfo(); - $noneProperty->setErrors(array_merge([], ...$errors)); - - return $noneProperty; - } - - /** - * @return Type[]|null - */ - private function extractFromMutator(string $class, string $property): ?array - { - [$reflectionMethod, $prefix] = $this->getMutatorMethod($class, $property); - if (null === $reflectionMethod) { - return null; - } - - $reflectionParameters = $reflectionMethod->getParameters(); - $reflectionParameter = $reflectionParameters[0]; - - if (!$reflectionType = $reflectionParameter->getType()) { - return null; - } - $type = $this->extractFromReflectionType($reflectionType, $reflectionMethod->getDeclaringClass()); - - if (1 === \count($type) && \in_array($prefix, $this->arrayMutatorPrefixes)) { - $type = [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), $type[0])]; - } - - return $type; - } - - /** - * Tries to extract type information from accessors. - * - * @return Type[]|null - */ - private function extractFromAccessor(string $class, string $property): ?array - { - [$reflectionMethod, $prefix] = $this->getAccessorMethod($class, $property); - if (null === $reflectionMethod) { - return null; - } - - if ($reflectionType = $reflectionMethod->getReturnType()) { - return $this->extractFromReflectionType($reflectionType, $reflectionMethod->getDeclaringClass()); - } - - if (\in_array($prefix, ['is', 'can', 'has'])) { - return [new Type(Type::BUILTIN_TYPE_BOOL)]; - } - - return null; - } - - /** - * Tries to extract type information from constructor. - * - * @return Type[]|null - */ - private function extractFromConstructor(string $class, string $property): ?array - { - try { - $reflectionClass = new \ReflectionClass($class); - } catch (\ReflectionException $e) { - return null; - } - - $constructor = $reflectionClass->getConstructor(); - - if (!$constructor) { - return null; - } - - foreach ($constructor->getParameters() as $parameter) { - if ($property !== $parameter->name) { - continue; - } - $reflectionType = $parameter->getType(); - - return $reflectionType ? $this->extractFromReflectionType($reflectionType, $constructor->getDeclaringClass()) : null; - } - - if ($parentClass = $reflectionClass->getParentClass()) { - return $this->extractFromConstructor($parentClass->getName(), $property); - } - - return null; - } - - private function extractFromPropertyDeclaration(string $class, string $property): ?array - { - try { - $reflectionClass = new \ReflectionClass($class); - - if (\PHP_VERSION_ID >= 70400) { - $reflectionProperty = $reflectionClass->getProperty($property); - $reflectionPropertyType = $reflectionProperty->getType(); - - if (null !== $reflectionPropertyType && $types = $this->extractFromReflectionType($reflectionPropertyType, $reflectionProperty->getDeclaringClass())) { - return $types; - } - } - } catch (\ReflectionException $e) { - return null; - } - - $defaultValue = $reflectionClass->getDefaultProperties()[$property] ?? null; - - if (null === $defaultValue) { - return null; - } - - $type = \gettype($defaultValue); - $type = static::MAP_TYPES[$type] ?? $type; - - return [new Type($type, $this->isNullableProperty($class, $property), null, Type::BUILTIN_TYPE_ARRAY === $type)]; - } - - private function extractFromReflectionType(\ReflectionType $reflectionType, \ReflectionClass $declaringClass): array - { - $types = []; - $nullable = $reflectionType->allowsNull(); - - foreach (($reflectionType instanceof \ReflectionUnionType || $reflectionType instanceof \ReflectionIntersectionType) ? $reflectionType->getTypes() : [$reflectionType] as $type) { - if (!$type instanceof \ReflectionNamedType) { - // Nested composite types are not supported yet. - return []; - } - - $phpTypeOrClass = $type->getName(); - if ('null' === $phpTypeOrClass || 'mixed' === $phpTypeOrClass || 'never' === $phpTypeOrClass) { - continue; - } - - if (Type::BUILTIN_TYPE_ARRAY === $phpTypeOrClass) { - $types[] = new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true); - } elseif ('void' === $phpTypeOrClass) { - $types[] = new Type(Type::BUILTIN_TYPE_NULL, $nullable); - } elseif ($type->isBuiltin()) { - $types[] = new Type($phpTypeOrClass, $nullable); - } else { - $types[] = new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $this->resolveTypeName($phpTypeOrClass, $declaringClass)); - } - } - - return $types; - } - - private function resolveTypeName(string $name, \ReflectionClass $declaringClass): string - { - if ('self' === $lcName = strtolower($name)) { - return $declaringClass->name; - } - if ('parent' === $lcName && $parent = $declaringClass->getParentClass()) { - return $parent->name; - } - - return $name; - } - - private function isNullableProperty(string $class, string $property): bool - { - try { - $reflectionProperty = new \ReflectionProperty($class, $property); - - if (\PHP_VERSION_ID >= 70400) { - $reflectionPropertyType = $reflectionProperty->getType(); - - return null !== $reflectionPropertyType && $reflectionPropertyType->allowsNull(); - } - - return false; - } catch (\ReflectionException $e) { - // Return false if the property doesn't exist - } - - return false; - } - - private function isAllowedProperty(string $class, string $property, bool $writeAccessRequired = false): bool - { - try { - $reflectionProperty = new \ReflectionProperty($class, $property); - - if (\PHP_VERSION_ID >= 80100 && $writeAccessRequired && $reflectionProperty->isReadOnly()) { - return false; - } - - return (bool) ($reflectionProperty->getModifiers() & $this->propertyReflectionFlags); - } catch (\ReflectionException $e) { - // Return false if the property doesn't exist - } - - return false; - } - - /** - * Gets the accessor method. - * - * Returns an array with a the instance of \ReflectionMethod as first key - * and the prefix of the method as second or null if not found. - */ - private function getAccessorMethod(string $class, string $property): ?array - { - $ucProperty = ucfirst($property); - - foreach ($this->accessorPrefixes as $prefix) { - try { - $reflectionMethod = new \ReflectionMethod($class, $prefix.$ucProperty); - if ($reflectionMethod->isStatic()) { - continue; - } - - if (0 === $reflectionMethod->getNumberOfRequiredParameters()) { - return [$reflectionMethod, $prefix]; - } - } catch (\ReflectionException $e) { - // Return null if the property doesn't exist - } - } - - return null; - } - - /** - * Returns an array with a the instance of \ReflectionMethod as first key - * and the prefix of the method as second or null if not found. - */ - private function getMutatorMethod(string $class, string $property): ?array - { - $ucProperty = ucfirst($property); - $ucSingulars = $this->inflector->singularize($ucProperty); - - $mutatorPrefixes = \in_array($ucProperty, $ucSingulars, true) ? $this->arrayMutatorPrefixesLast : $this->arrayMutatorPrefixesFirst; - - foreach ($mutatorPrefixes as $prefix) { - $names = [$ucProperty]; - if (\in_array($prefix, $this->arrayMutatorPrefixes)) { - $names = array_merge($names, $ucSingulars); - } - - foreach ($names as $name) { - try { - $reflectionMethod = new \ReflectionMethod($class, $prefix.$name); - if ($reflectionMethod->isStatic()) { - continue; - } - - // Parameter can be optional to allow things like: method(array $foo = null) - if ($reflectionMethod->getNumberOfParameters() >= 1) { - return [$reflectionMethod, $prefix]; - } - } catch (\ReflectionException $e) { - // Try the next prefix if the method doesn't exist - } - } - } - - return null; - } - - private function getPropertyName(string $methodName, array $reflectionProperties): ?string - { - $pattern = implode('|', array_merge($this->accessorPrefixes, $this->mutatorPrefixes)); - - if ('' !== $pattern && preg_match('/^('.$pattern.')(.+)$/i', $methodName, $matches)) { - if (!\in_array($matches[1], $this->arrayMutatorPrefixes)) { - return $matches[2]; - } - - foreach ($reflectionProperties as $reflectionProperty) { - foreach ($this->inflector->singularize($reflectionProperty->name) as $name) { - if (strtolower($name) === strtolower($matches[2])) { - return $reflectionProperty->name; - } - } - } - - return $matches[2]; - } - - return null; - } - - /** - * Searches for add and remove methods. - * - * @param \ReflectionClass $reflClass The reflection class for the given object - * @param array $singulars The singular form of the property name or null - * - * @return array An array containing the adder and remover when found and errors - */ - private function findAdderAndRemover(\ReflectionClass $reflClass, array $singulars): array - { - if (!\is_array($this->arrayMutatorPrefixes) && 2 !== \count($this->arrayMutatorPrefixes)) { - return [null, null, []]; - } - - [$addPrefix, $removePrefix] = $this->arrayMutatorPrefixes; - $errors = []; - - foreach ($singulars as $singular) { - $addMethod = $addPrefix.$singular; - $removeMethod = $removePrefix.$singular; - - [$addMethodFound, $addMethodAccessibleErrors] = $this->isMethodAccessible($reflClass, $addMethod, 1); - [$removeMethodFound, $removeMethodAccessibleErrors] = $this->isMethodAccessible($reflClass, $removeMethod, 1); - $errors[] = $addMethodAccessibleErrors; - $errors[] = $removeMethodAccessibleErrors; - - if ($addMethodFound && $removeMethodFound) { - return [$addMethod, $removeMethod, []]; - } - - if ($addMethodFound && !$removeMethodFound) { - $errors[] = [sprintf('The add method "%s" in class "%s" was found, but the corresponding remove method "%s" was not found', $addMethod, $reflClass->getName(), $removeMethod)]; - } elseif (!$addMethodFound && $removeMethodFound) { - $errors[] = [sprintf('The remove method "%s" in class "%s" was found, but the corresponding add method "%s" was not found', $removeMethod, $reflClass->getName(), $addMethod)]; - } - } - - return [null, null, array_merge([], ...$errors)]; - } - - /** - * Returns whether a method is public and has the number of required parameters and errors. - */ - private function isMethodAccessible(\ReflectionClass $class, string $methodName, int $parameters): array - { - $errors = []; - - if ($class->hasMethod($methodName)) { - $method = $class->getMethod($methodName); - - if (\ReflectionMethod::IS_PUBLIC === $this->methodReflectionFlags && !$method->isPublic()) { - $errors[] = sprintf('The method "%s" in class "%s" was found but does not have public access.', $methodName, $class->getName()); - } elseif ($method->getNumberOfRequiredParameters() > $parameters || $method->getNumberOfParameters() < $parameters) { - $errors[] = sprintf('The method "%s" in class "%s" requires %d arguments, but should accept only %d.', $methodName, $class->getName(), $method->getNumberOfRequiredParameters(), $parameters); - } else { - return [true, $errors]; - } - } - - return [false, $errors]; - } - - /** - * Camelizes a given string. - */ - private function camelize(string $string): string - { - return str_replace(' ', '', ucwords(str_replace('_', ' ', $string))); - } - - /** - * Return allowed reflection method flags. - */ - private function getMethodsFlags(int $accessFlags): int - { - $methodFlags = 0; - - if ($accessFlags & self::ALLOW_PUBLIC) { - $methodFlags |= \ReflectionMethod::IS_PUBLIC; - } - - if ($accessFlags & self::ALLOW_PRIVATE) { - $methodFlags |= \ReflectionMethod::IS_PRIVATE; - } - - if ($accessFlags & self::ALLOW_PROTECTED) { - $methodFlags |= \ReflectionMethod::IS_PROTECTED; - } - - return $methodFlags; - } - - /** - * Return allowed reflection property flags. - */ - private function getPropertyFlags(int $accessFlags): int - { - $propertyFlags = 0; - - if ($accessFlags & self::ALLOW_PUBLIC) { - $propertyFlags |= \ReflectionProperty::IS_PUBLIC; - } - - if ($accessFlags & self::ALLOW_PRIVATE) { - $propertyFlags |= \ReflectionProperty::IS_PRIVATE; - } - - if ($accessFlags & self::ALLOW_PROTECTED) { - $propertyFlags |= \ReflectionProperty::IS_PROTECTED; - } - - return $propertyFlags; - } - - private function getReadVisiblityForProperty(\ReflectionProperty $reflectionProperty): string - { - if ($reflectionProperty->isPrivate()) { - return PropertyReadInfo::VISIBILITY_PRIVATE; - } - - if ($reflectionProperty->isProtected()) { - return PropertyReadInfo::VISIBILITY_PROTECTED; - } - - return PropertyReadInfo::VISIBILITY_PUBLIC; - } - - private function getReadVisiblityForMethod(\ReflectionMethod $reflectionMethod): string - { - if ($reflectionMethod->isPrivate()) { - return PropertyReadInfo::VISIBILITY_PRIVATE; - } - - if ($reflectionMethod->isProtected()) { - return PropertyReadInfo::VISIBILITY_PROTECTED; - } - - return PropertyReadInfo::VISIBILITY_PUBLIC; - } - - private function getWriteVisiblityForProperty(\ReflectionProperty $reflectionProperty): string - { - if ($reflectionProperty->isPrivate()) { - return PropertyWriteInfo::VISIBILITY_PRIVATE; - } - - if ($reflectionProperty->isProtected()) { - return PropertyWriteInfo::VISIBILITY_PROTECTED; - } - - return PropertyWriteInfo::VISIBILITY_PUBLIC; - } - - private function getWriteVisiblityForMethod(\ReflectionMethod $reflectionMethod): string - { - if ($reflectionMethod->isPrivate()) { - return PropertyWriteInfo::VISIBILITY_PRIVATE; - } - - if ($reflectionMethod->isProtected()) { - return PropertyWriteInfo::VISIBILITY_PROTECTED; - } - - return PropertyWriteInfo::VISIBILITY_PUBLIC; - } -} diff --git a/lib/symfony/property-info/Extractor/SerializerExtractor.php b/lib/symfony/property-info/Extractor/SerializerExtractor.php deleted file mode 100644 index 08ff10d04..000000000 --- a/lib/symfony/property-info/Extractor/SerializerExtractor.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo\Extractor; - -use Symfony\Component\PropertyInfo\PropertyListExtractorInterface; -use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; - -/** - * Lists available properties using Symfony Serializer Component metadata. - * - * @author Kévin Dunglas <dunglas@gmail.com> - * - * @final - */ -class SerializerExtractor implements PropertyListExtractorInterface -{ - private $classMetadataFactory; - - public function __construct(ClassMetadataFactoryInterface $classMetadataFactory) - { - $this->classMetadataFactory = $classMetadataFactory; - } - - /** - * {@inheritdoc} - */ - public function getProperties(string $class, array $context = []): ?array - { - if (!\array_key_exists('serializer_groups', $context) || (null !== $context['serializer_groups'] && !\is_array($context['serializer_groups']))) { - return null; - } - - if (!$this->classMetadataFactory->getMetadataFor($class)) { - return null; - } - - $properties = []; - $serializerClassMetadata = $this->classMetadataFactory->getMetadataFor($class); - - foreach ($serializerClassMetadata->getAttributesMetadata() as $serializerAttributeMetadata) { - $ignored = method_exists($serializerAttributeMetadata, 'isIgnored') && $serializerAttributeMetadata->isIgnored(); - if (!$ignored && (null === $context['serializer_groups'] || array_intersect($context['serializer_groups'], $serializerAttributeMetadata->getGroups()))) { - $properties[] = $serializerAttributeMetadata->getName(); - } - } - - return $properties; - } -} diff --git a/lib/symfony/property-info/LICENSE b/lib/symfony/property-info/LICENSE deleted file mode 100644 index 6e3afce69..000000000 --- a/lib/symfony/property-info/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -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/lib/symfony/property-info/PhpStan/NameScope.php b/lib/symfony/property-info/PhpStan/NameScope.php deleted file mode 100644 index 7d9a5f9ac..000000000 --- a/lib/symfony/property-info/PhpStan/NameScope.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo\PhpStan; - -/** - * NameScope class adapted from PHPStan code. - * - * @copyright Copyright (c) 2016, PHPStan https://github.com/phpstan/phpstan-src - * @copyright Copyright (c) 2016, Ondřej Mirtes - * @author Baptiste Leduc <baptiste.leduc@gmail.com> - * - * @internal - */ -final class NameScope -{ - private $calledClassName; - private $namespace; - /** @var array<string, string> alias(string) => fullName(string) */ - private $uses; - - public function __construct(string $calledClassName, string $namespace, array $uses = []) - { - $this->calledClassName = $calledClassName; - $this->namespace = $namespace; - $this->uses = $uses; - } - - public function resolveStringName(string $name): string - { - if (0 === strpos($name, '\\')) { - return ltrim($name, '\\'); - } - - $nameParts = explode('\\', $name); - $firstNamePart = $nameParts[0]; - if (isset($this->uses[$firstNamePart])) { - if (1 === \count($nameParts)) { - return $this->uses[$firstNamePart]; - } - array_shift($nameParts); - - return sprintf('%s\\%s', $this->uses[$firstNamePart], implode('\\', $nameParts)); - } - - if (null !== $this->namespace) { - return sprintf('%s\\%s', $this->namespace, $name); - } - - return $name; - } - - public function resolveRootClass(): string - { - return $this->resolveStringName($this->calledClassName); - } -} diff --git a/lib/symfony/property-info/PhpStan/NameScopeFactory.php b/lib/symfony/property-info/PhpStan/NameScopeFactory.php deleted file mode 100644 index 32f2f330e..000000000 --- a/lib/symfony/property-info/PhpStan/NameScopeFactory.php +++ /dev/null @@ -1,70 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo\PhpStan; - -use phpDocumentor\Reflection\Types\ContextFactory; - -/** - * @author Baptiste Leduc <baptiste.leduc@gmail.com> - * - * @internal - */ -final class NameScopeFactory -{ - public function create(string $calledClassName, string $declaringClassName = null): NameScope - { - $declaringClassName = $declaringClassName ?? $calledClassName; - - $path = explode('\\', $calledClassName); - $calledClassName = array_pop($path); - - $declaringReflection = new \ReflectionClass($declaringClassName); - [$declaringNamespace, $declaringUses] = $this->extractFromFullClassName($declaringReflection); - $declaringUses = array_merge($declaringUses, $this->collectUses($declaringReflection)); - - return new NameScope($calledClassName, $declaringNamespace, $declaringUses); - } - - private function collectUses(\ReflectionClass $reflection): array - { - $uses = [$this->extractFromFullClassName($reflection)[1]]; - - foreach ($reflection->getTraits() as $traitReflection) { - $uses[] = $this->extractFromFullClassName($traitReflection)[1]; - } - - if (false !== $parentClass = $reflection->getParentClass()) { - $uses[] = $this->collectUses($parentClass); - } - - return $uses ? array_merge(...$uses) : []; - } - - private function extractFromFullClassName(\ReflectionClass $reflection): array - { - $namespace = trim($reflection->getNamespaceName(), '\\'); - $fileName = $reflection->getFileName(); - - if (\is_string($fileName) && is_file($fileName)) { - if (false === $contents = file_get_contents($fileName)) { - throw new \RuntimeException(sprintf('Unable to read file "%s".', $fileName)); - } - - $factory = new ContextFactory(); - $context = $factory->createForNamespace($namespace, $contents); - - return [$namespace, $context->getNamespaceAliases()]; - } - - return [$namespace, []]; - } -} diff --git a/lib/symfony/property-info/PropertyAccessExtractorInterface.php b/lib/symfony/property-info/PropertyAccessExtractorInterface.php deleted file mode 100644 index f9ee78713..000000000 --- a/lib/symfony/property-info/PropertyAccessExtractorInterface.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo; - -/** - * Guesses if the property can be accessed or mutated. - * - * @author Kévin Dunglas <dunglas@gmail.com> - */ -interface PropertyAccessExtractorInterface -{ - /** - * Is the property readable? - * - * @return bool|null - */ - public function isReadable(string $class, string $property, array $context = []); - - /** - * Is the property writable? - * - * @return bool|null - */ - public function isWritable(string $class, string $property, array $context = []); -} diff --git a/lib/symfony/property-info/PropertyDescriptionExtractorInterface.php b/lib/symfony/property-info/PropertyDescriptionExtractorInterface.php deleted file mode 100644 index f37653753..000000000 --- a/lib/symfony/property-info/PropertyDescriptionExtractorInterface.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo; - -/** - * Guesses the property's human readable description. - * - * @author Kévin Dunglas <dunglas@gmail.com> - */ -interface PropertyDescriptionExtractorInterface -{ - /** - * Gets the short description of the property. - * - * @return string|null - */ - public function getShortDescription(string $class, string $property, array $context = []); - - /** - * Gets the long description of the property. - * - * @return string|null - */ - public function getLongDescription(string $class, string $property, array $context = []); -} diff --git a/lib/symfony/property-info/PropertyInfoCacheExtractor.php b/lib/symfony/property-info/PropertyInfoCacheExtractor.php deleted file mode 100644 index ca7b32427..000000000 --- a/lib/symfony/property-info/PropertyInfoCacheExtractor.php +++ /dev/null @@ -1,124 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo; - -use Psr\Cache\CacheItemPoolInterface; - -/** - * Adds a PSR-6 cache layer on top of an extractor. - * - * @author Kévin Dunglas <dunglas@gmail.com> - * - * @final - */ -class PropertyInfoCacheExtractor implements PropertyInfoExtractorInterface, PropertyInitializableExtractorInterface -{ - private $propertyInfoExtractor; - private $cacheItemPool; - private $arrayCache = []; - - public function __construct(PropertyInfoExtractorInterface $propertyInfoExtractor, CacheItemPoolInterface $cacheItemPool) - { - $this->propertyInfoExtractor = $propertyInfoExtractor; - $this->cacheItemPool = $cacheItemPool; - } - - /** - * {@inheritdoc} - */ - public function isReadable(string $class, string $property, array $context = []): ?bool - { - return $this->extract('isReadable', [$class, $property, $context]); - } - - /** - * {@inheritdoc} - */ - public function isWritable(string $class, string $property, array $context = []): ?bool - { - return $this->extract('isWritable', [$class, $property, $context]); - } - - /** - * {@inheritdoc} - */ - public function getShortDescription(string $class, string $property, array $context = []): ?string - { - return $this->extract('getShortDescription', [$class, $property, $context]); - } - - /** - * {@inheritdoc} - */ - public function getLongDescription(string $class, string $property, array $context = []): ?string - { - return $this->extract('getLongDescription', [$class, $property, $context]); - } - - /** - * {@inheritdoc} - */ - public function getProperties(string $class, array $context = []): ?array - { - return $this->extract('getProperties', [$class, $context]); - } - - /** - * {@inheritdoc} - */ - public function getTypes(string $class, string $property, array $context = []): ?array - { - return $this->extract('getTypes', [$class, $property, $context]); - } - - /** - * {@inheritdoc} - */ - public function isInitializable(string $class, string $property, array $context = []): ?bool - { - return $this->extract('isInitializable', [$class, $property, $context]); - } - - /** - * Retrieves the cached data if applicable or delegates to the decorated extractor. - * - * @return mixed - */ - private function extract(string $method, array $arguments) - { - try { - $serializedArguments = serialize($arguments); - } catch (\Exception $exception) { - // If arguments are not serializable, skip the cache - return $this->propertyInfoExtractor->{$method}(...$arguments); - } - - // Calling rawurlencode escapes special characters not allowed in PSR-6's keys - $key = rawurlencode($method.'.'.$serializedArguments); - - if (\array_key_exists($key, $this->arrayCache)) { - return $this->arrayCache[$key]; - } - - $item = $this->cacheItemPool->getItem($key); - - if ($item->isHit()) { - return $this->arrayCache[$key] = $item->get(); - } - - $value = $this->propertyInfoExtractor->{$method}(...$arguments); - $item->set($value); - $this->cacheItemPool->save($item); - - return $this->arrayCache[$key] = $value; - } -} diff --git a/lib/symfony/property-info/PropertyInfoExtractor.php b/lib/symfony/property-info/PropertyInfoExtractor.php deleted file mode 100644 index eca169f18..000000000 --- a/lib/symfony/property-info/PropertyInfoExtractor.php +++ /dev/null @@ -1,119 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo; - -/** - * Default {@see PropertyInfoExtractorInterface} implementation. - * - * @author Kévin Dunglas <dunglas@gmail.com> - * - * @final - */ -class PropertyInfoExtractor implements PropertyInfoExtractorInterface, PropertyInitializableExtractorInterface -{ - private $listExtractors; - private $typeExtractors; - private $descriptionExtractors; - private $accessExtractors; - private $initializableExtractors; - - /** - * @param iterable<mixed, PropertyListExtractorInterface> $listExtractors - * @param iterable<mixed, PropertyTypeExtractorInterface> $typeExtractors - * @param iterable<mixed, PropertyDescriptionExtractorInterface> $descriptionExtractors - * @param iterable<mixed, PropertyAccessExtractorInterface> $accessExtractors - * @param iterable<mixed, PropertyInitializableExtractorInterface> $initializableExtractors - */ - public function __construct(iterable $listExtractors = [], iterable $typeExtractors = [], iterable $descriptionExtractors = [], iterable $accessExtractors = [], iterable $initializableExtractors = []) - { - $this->listExtractors = $listExtractors; - $this->typeExtractors = $typeExtractors; - $this->descriptionExtractors = $descriptionExtractors; - $this->accessExtractors = $accessExtractors; - $this->initializableExtractors = $initializableExtractors; - } - - /** - * {@inheritdoc} - */ - public function getProperties(string $class, array $context = []): ?array - { - return $this->extract($this->listExtractors, 'getProperties', [$class, $context]); - } - - /** - * {@inheritdoc} - */ - public function getShortDescription(string $class, string $property, array $context = []): ?string - { - return $this->extract($this->descriptionExtractors, 'getShortDescription', [$class, $property, $context]); - } - - /** - * {@inheritdoc} - */ - public function getLongDescription(string $class, string $property, array $context = []): ?string - { - return $this->extract($this->descriptionExtractors, 'getLongDescription', [$class, $property, $context]); - } - - /** - * {@inheritdoc} - */ - public function getTypes(string $class, string $property, array $context = []): ?array - { - return $this->extract($this->typeExtractors, 'getTypes', [$class, $property, $context]); - } - - /** - * {@inheritdoc} - */ - public function isReadable(string $class, string $property, array $context = []): ?bool - { - return $this->extract($this->accessExtractors, 'isReadable', [$class, $property, $context]); - } - - /** - * {@inheritdoc} - */ - public function isWritable(string $class, string $property, array $context = []): ?bool - { - return $this->extract($this->accessExtractors, 'isWritable', [$class, $property, $context]); - } - - /** - * {@inheritdoc} - */ - public function isInitializable(string $class, string $property, array $context = []): ?bool - { - return $this->extract($this->initializableExtractors, 'isInitializable', [$class, $property, $context]); - } - - /** - * Iterates over registered extractors and return the first value found. - * - * @param iterable<mixed, object> $extractors - * @param list<mixed> $arguments - * - * @return mixed - */ - private function extract(iterable $extractors, string $method, array $arguments) - { - foreach ($extractors as $extractor) { - if (null !== $value = $extractor->{$method}(...$arguments)) { - return $value; - } - } - - return null; - } -} diff --git a/lib/symfony/property-info/PropertyInfoExtractorInterface.php b/lib/symfony/property-info/PropertyInfoExtractorInterface.php deleted file mode 100644 index 889301865..000000000 --- a/lib/symfony/property-info/PropertyInfoExtractorInterface.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo; - -/** - * Gets info about PHP class properties. - * - * A convenient interface inheriting all specific info interfaces. - * - * @author Kévin Dunglas <dunglas@gmail.com> - */ -interface PropertyInfoExtractorInterface extends PropertyTypeExtractorInterface, PropertyDescriptionExtractorInterface, PropertyAccessExtractorInterface, PropertyListExtractorInterface -{ -} diff --git a/lib/symfony/property-info/PropertyInitializableExtractorInterface.php b/lib/symfony/property-info/PropertyInitializableExtractorInterface.php deleted file mode 100644 index 13248fc19..000000000 --- a/lib/symfony/property-info/PropertyInitializableExtractorInterface.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo; - -/** - * Guesses if the property can be initialized through the constructor. - * - * @author Kévin Dunglas <dunglas@gmail.com> - */ -interface PropertyInitializableExtractorInterface -{ - /** - * Is the property initializable? Returns true if a constructor's parameter matches the given property name. - */ - public function isInitializable(string $class, string $property, array $context = []): ?bool; -} diff --git a/lib/symfony/property-info/PropertyListExtractorInterface.php b/lib/symfony/property-info/PropertyListExtractorInterface.php deleted file mode 100644 index 326e6cccb..000000000 --- a/lib/symfony/property-info/PropertyListExtractorInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo; - -/** - * Extracts the list of properties available for the given class. - * - * @author Kévin Dunglas <dunglas@gmail.com> - */ -interface PropertyListExtractorInterface -{ - /** - * Gets the list of properties available for the given class. - * - * @return string[]|null - */ - public function getProperties(string $class, array $context = []); -} diff --git a/lib/symfony/property-info/PropertyReadInfo.php b/lib/symfony/property-info/PropertyReadInfo.php deleted file mode 100644 index ae1035244..000000000 --- a/lib/symfony/property-info/PropertyReadInfo.php +++ /dev/null @@ -1,82 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo; - -/** - * The property read info tells how a property can be read. - * - * @author Joel Wurtz <jwurtz@jolicode.com> - * - * @internal - */ -final class PropertyReadInfo -{ - public const TYPE_METHOD = 'method'; - public const TYPE_PROPERTY = 'property'; - - public const VISIBILITY_PUBLIC = 'public'; - public const VISIBILITY_PROTECTED = 'protected'; - public const VISIBILITY_PRIVATE = 'private'; - - private $type; - - private $name; - - private $visibility; - - private $static; - - private $byRef; - - public function __construct(string $type, string $name, string $visibility, bool $static, bool $byRef) - { - $this->type = $type; - $this->name = $name; - $this->visibility = $visibility; - $this->static = $static; - $this->byRef = $byRef; - } - - /** - * Get type of access. - */ - public function getType(): string - { - return $this->type; - } - - /** - * Get name of the access, which can be a method name or a property name, depending on the type. - */ - public function getName(): string - { - return $this->name; - } - - public function getVisibility(): string - { - return $this->visibility; - } - - public function isStatic(): bool - { - return $this->static; - } - - /** - * Whether this accessor can be accessed by reference. - */ - public function canBeReference(): bool - { - return $this->byRef; - } -} diff --git a/lib/symfony/property-info/PropertyReadInfoExtractorInterface.php b/lib/symfony/property-info/PropertyReadInfoExtractorInterface.php deleted file mode 100644 index 816b2825d..000000000 --- a/lib/symfony/property-info/PropertyReadInfoExtractorInterface.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo; - -/** - * Extract read information for the property of a class. - * - * @author Joel Wurtz <jwurtz@jolicode.com> - */ -interface PropertyReadInfoExtractorInterface -{ - /** - * Get read information object for a given property of a class. - */ - public function getReadInfo(string $class, string $property, array $context = []): ?PropertyReadInfo; -} diff --git a/lib/symfony/property-info/PropertyTypeExtractorInterface.php b/lib/symfony/property-info/PropertyTypeExtractorInterface.php deleted file mode 100644 index 6da0bcb4c..000000000 --- a/lib/symfony/property-info/PropertyTypeExtractorInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo; - -/** - * Type Extractor Interface. - * - * @author Kévin Dunglas <dunglas@gmail.com> - */ -interface PropertyTypeExtractorInterface -{ - /** - * Gets types of a property. - * - * @return Type[]|null - */ - public function getTypes(string $class, string $property, array $context = []); -} diff --git a/lib/symfony/property-info/PropertyWriteInfo.php b/lib/symfony/property-info/PropertyWriteInfo.php deleted file mode 100644 index b4e33b240..000000000 --- a/lib/symfony/property-info/PropertyWriteInfo.php +++ /dev/null @@ -1,123 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo; - -/** - * The write mutator defines how a property can be written. - * - * @author Joel Wurtz <jwurtz@jolicode.com> - * - * @internal - */ -final class PropertyWriteInfo -{ - public const TYPE_NONE = 'none'; - public const TYPE_METHOD = 'method'; - public const TYPE_PROPERTY = 'property'; - public const TYPE_ADDER_AND_REMOVER = 'adder_and_remover'; - public const TYPE_CONSTRUCTOR = 'constructor'; - - public const VISIBILITY_PUBLIC = 'public'; - public const VISIBILITY_PROTECTED = 'protected'; - public const VISIBILITY_PRIVATE = 'private'; - - private $type; - private $name; - private $visibility; - private $static; - private $adderInfo; - private $removerInfo; - private $errors = []; - - public function __construct(string $type = self::TYPE_NONE, string $name = null, string $visibility = null, bool $static = null) - { - $this->type = $type; - $this->name = $name; - $this->visibility = $visibility; - $this->static = $static; - } - - public function getType(): string - { - return $this->type; - } - - public function getName(): string - { - if (null === $this->name) { - throw new \LogicException("Calling getName() when having a mutator of type {$this->type} is not tolerated."); - } - - return $this->name; - } - - public function setAdderInfo(self $adderInfo): void - { - $this->adderInfo = $adderInfo; - } - - public function getAdderInfo(): self - { - if (null === $this->adderInfo) { - throw new \LogicException("Calling getAdderInfo() when having a mutator of type {$this->type} is not tolerated."); - } - - return $this->adderInfo; - } - - public function setRemoverInfo(self $removerInfo): void - { - $this->removerInfo = $removerInfo; - } - - public function getRemoverInfo(): self - { - if (null === $this->removerInfo) { - throw new \LogicException("Calling getRemoverInfo() when having a mutator of type {$this->type} is not tolerated."); - } - - return $this->removerInfo; - } - - public function getVisibility(): string - { - if (null === $this->visibility) { - throw new \LogicException("Calling getVisibility() when having a mutator of type {$this->type} is not tolerated."); - } - - return $this->visibility; - } - - public function isStatic(): bool - { - if (null === $this->static) { - throw new \LogicException("Calling isStatic() when having a mutator of type {$this->type} is not tolerated."); - } - - return $this->static; - } - - public function setErrors(array $errors): void - { - $this->errors = $errors; - } - - public function getErrors(): array - { - return $this->errors; - } - - public function hasErrors(): bool - { - return (bool) \count($this->errors); - } -} diff --git a/lib/symfony/property-info/PropertyWriteInfoExtractorInterface.php b/lib/symfony/property-info/PropertyWriteInfoExtractorInterface.php deleted file mode 100644 index f11346381..000000000 --- a/lib/symfony/property-info/PropertyWriteInfoExtractorInterface.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo; - -/** - * Extract write information for the property of a class. - * - * @author Joel Wurtz <jwurtz@jolicode.com> - */ -interface PropertyWriteInfoExtractorInterface -{ - /** - * Get write information object for a given property of a class. - */ - public function getWriteInfo(string $class, string $property, array $context = []): ?PropertyWriteInfo; -} diff --git a/lib/symfony/property-info/README.md b/lib/symfony/property-info/README.md deleted file mode 100644 index da3514fc9..000000000 --- a/lib/symfony/property-info/README.md +++ /dev/null @@ -1,14 +0,0 @@ -PropertyInfo Component -====================== - -The PropertyInfo component extracts information about PHP class' properties -using metadata of popular sources. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/property_info.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/lib/symfony/property-info/Type.php b/lib/symfony/property-info/Type.php deleted file mode 100644 index 5c1b5c124..000000000 --- a/lib/symfony/property-info/Type.php +++ /dev/null @@ -1,206 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo; - -/** - * Type value object (immutable). - * - * @author Kévin Dunglas <dunglas@gmail.com> - * - * @final - */ -class Type -{ - public const BUILTIN_TYPE_INT = 'int'; - public const BUILTIN_TYPE_FLOAT = 'float'; - public const BUILTIN_TYPE_STRING = 'string'; - public const BUILTIN_TYPE_BOOL = 'bool'; - public const BUILTIN_TYPE_RESOURCE = 'resource'; - public const BUILTIN_TYPE_OBJECT = 'object'; - public const BUILTIN_TYPE_ARRAY = 'array'; - public const BUILTIN_TYPE_NULL = 'null'; - public const BUILTIN_TYPE_FALSE = 'false'; - public const BUILTIN_TYPE_TRUE = 'true'; - public const BUILTIN_TYPE_CALLABLE = 'callable'; - public const BUILTIN_TYPE_ITERABLE = 'iterable'; - - /** - * List of PHP builtin types. - * - * @var string[] - */ - public static $builtinTypes = [ - self::BUILTIN_TYPE_INT, - self::BUILTIN_TYPE_FLOAT, - self::BUILTIN_TYPE_STRING, - self::BUILTIN_TYPE_BOOL, - self::BUILTIN_TYPE_RESOURCE, - self::BUILTIN_TYPE_OBJECT, - self::BUILTIN_TYPE_ARRAY, - self::BUILTIN_TYPE_CALLABLE, - self::BUILTIN_TYPE_FALSE, - self::BUILTIN_TYPE_TRUE, - self::BUILTIN_TYPE_NULL, - self::BUILTIN_TYPE_ITERABLE, - ]; - - /** - * List of PHP builtin collection types. - * - * @var string[] - */ - public static $builtinCollectionTypes = [ - self::BUILTIN_TYPE_ARRAY, - self::BUILTIN_TYPE_ITERABLE, - ]; - - private $builtinType; - private $nullable; - private $class; - private $collection; - private $collectionKeyType; - private $collectionValueType; - - /** - * @param Type[]|Type|null $collectionKeyType - * @param Type[]|Type|null $collectionValueType - * - * @throws \InvalidArgumentException - */ - public function __construct(string $builtinType, bool $nullable = false, string $class = null, bool $collection = false, $collectionKeyType = null, $collectionValueType = null) - { - if (!\in_array($builtinType, self::$builtinTypes)) { - throw new \InvalidArgumentException(sprintf('"%s" is not a valid PHP type.', $builtinType)); - } - - $this->builtinType = $builtinType; - $this->nullable = $nullable; - $this->class = $class; - $this->collection = $collection; - $this->collectionKeyType = $this->validateCollectionArgument($collectionKeyType, 5, '$collectionKeyType') ?? []; - $this->collectionValueType = $this->validateCollectionArgument($collectionValueType, 6, '$collectionValueType') ?? []; - } - - private function validateCollectionArgument($collectionArgument, int $argumentIndex, string $argumentName): ?array - { - if (null === $collectionArgument) { - return null; - } - - if (!\is_array($collectionArgument) && !$collectionArgument instanceof self) { - throw new \TypeError(sprintf('"%s()": Argument #%d (%s) must be of type "%s[]", "%s" or "null", "%s" given.', __METHOD__, $argumentIndex, $argumentName, self::class, self::class, get_debug_type($collectionArgument))); - } - - if (\is_array($collectionArgument)) { - foreach ($collectionArgument as $type) { - if (!$type instanceof self) { - throw new \TypeError(sprintf('"%s()": Argument #%d (%s) must be of type "%s[]", "%s" or "null", array value "%s" given.', __METHOD__, $argumentIndex, $argumentName, self::class, self::class, get_debug_type($collectionArgument))); - } - } - - return $collectionArgument; - } - - return [$collectionArgument]; - } - - /** - * Gets built-in type. - * - * Can be bool, int, float, string, array, object, resource, null, callback or iterable. - */ - public function getBuiltinType(): string - { - return $this->builtinType; - } - - public function isNullable(): bool - { - return $this->nullable; - } - - /** - * Gets the class name. - * - * Only applicable if the built-in type is object. - */ - public function getClassName(): ?string - { - return $this->class; - } - - public function isCollection(): bool - { - return $this->collection; - } - - /** - * Gets collection key type. - * - * Only applicable for a collection type. - * - * @deprecated since Symfony 5.3, use "getCollectionKeyTypes()" instead - */ - public function getCollectionKeyType(): ?self - { - trigger_deprecation('symfony/property-info', '5.3', 'The "%s()" method is deprecated, use "getCollectionKeyTypes()" instead.', __METHOD__); - - $type = $this->getCollectionKeyTypes(); - if (0 === \count($type)) { - return null; - } - - if (\is_array($type)) { - [$type] = $type; - } - - return $type; - } - - /** - * Gets collection key types. - * - * Only applicable for a collection type. - * - * @return Type[] - */ - public function getCollectionKeyTypes(): array - { - return $this->collectionKeyType; - } - - /** - * Gets collection value type. - * - * Only applicable for a collection type. - * - * @deprecated since Symfony 5.3, use "getCollectionValueTypes()" instead - */ - public function getCollectionValueType(): ?self - { - trigger_deprecation('symfony/property-info', '5.3', 'The "%s()" method is deprecated, use "getCollectionValueTypes()" instead.', __METHOD__); - - return $this->getCollectionValueTypes()[0] ?? null; - } - - /** - * Gets collection value types. - * - * Only applicable for a collection type. - * - * @return Type[] - */ - public function getCollectionValueTypes(): array - { - return $this->collectionValueType; - } -} diff --git a/lib/symfony/property-info/Util/PhpDocTypeHelper.php b/lib/symfony/property-info/Util/PhpDocTypeHelper.php deleted file mode 100644 index 44a461498..000000000 --- a/lib/symfony/property-info/Util/PhpDocTypeHelper.php +++ /dev/null @@ -1,191 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo\Util; - -use phpDocumentor\Reflection\PseudoTypes\ConstExpression; -use phpDocumentor\Reflection\PseudoTypes\List_; -use phpDocumentor\Reflection\Type as DocType; -use phpDocumentor\Reflection\Types\Array_; -use phpDocumentor\Reflection\Types\Collection; -use phpDocumentor\Reflection\Types\Compound; -use phpDocumentor\Reflection\Types\Null_; -use phpDocumentor\Reflection\Types\Nullable; -use Symfony\Component\PropertyInfo\Type; - -// Workaround for phpdocumentor/type-resolver < 1.6 -// We trigger the autoloader here, so we don't need to trigger it inside the loop later. -class_exists(List_::class); - -/** - * Transforms a php doc type to a {@link Type} instance. - * - * @author Kévin Dunglas <dunglas@gmail.com> - * @author Guilhem N. <egetick@gmail.com> - */ -final class PhpDocTypeHelper -{ - /** - * Creates a {@see Type} from a PHPDoc type. - * - * @return Type[] - */ - public function getTypes(DocType $varType): array - { - if ($varType instanceof ConstExpression) { - // It's safer to fall back to other extractors here, as resolving const types correctly is not easy at the moment - return []; - } - - $types = []; - $nullable = false; - - if ($varType instanceof Nullable) { - $nullable = true; - $varType = $varType->getActualType(); - } - - if (!$varType instanceof Compound) { - if ($varType instanceof Null_) { - $nullable = true; - } - - $type = $this->createType($varType, $nullable); - if (null !== $type) { - $types[] = $type; - } - - return $types; - } - - $varTypes = []; - for ($typeIndex = 0; $varType->has($typeIndex); ++$typeIndex) { - $type = $varType->get($typeIndex); - - if ($type instanceof ConstExpression) { - // It's safer to fall back to other extractors here, as resolving const types correctly is not easy at the moment - return []; - } - - // If null is present, all types are nullable - if ($type instanceof Null_) { - $nullable = true; - continue; - } - - if ($type instanceof Nullable) { - $nullable = true; - $type = $type->getActualType(); - } - - $varTypes[] = $type; - } - - foreach ($varTypes as $varType) { - $type = $this->createType($varType, $nullable); - if (null !== $type) { - $types[] = $type; - } - } - - return $types; - } - - /** - * Creates a {@see Type} from a PHPDoc type. - */ - private function createType(DocType $type, bool $nullable, string $docType = null): ?Type - { - $docType = $docType ?? (string) $type; - - if ($type instanceof Collection) { - $fqsen = $type->getFqsen(); - if ($fqsen && 'list' === $fqsen->getName() && !class_exists(List_::class, false) && !class_exists((string) $fqsen)) { - // Workaround for phpdocumentor/type-resolver < 1.6 - return new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, new Type(Type::BUILTIN_TYPE_INT), $this->getTypes($type->getValueType())); - } - - [$phpType, $class] = $this->getPhpTypeAndClass((string) $fqsen); - - $keys = $this->getTypes($type->getKeyType()); - $values = $this->getTypes($type->getValueType()); - - return new Type($phpType, $nullable, $class, true, $keys, $values); - } - - // Cannot guess - if (!$docType || 'mixed' === $docType) { - return null; - } - - if (str_ends_with($docType, '[]') && $type instanceof Array_) { - $collectionKeyTypes = new Type(Type::BUILTIN_TYPE_INT); - $collectionValueTypes = $this->getTypes($type->getValueType()); - - return new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, $collectionKeyTypes, $collectionValueTypes); - } - - if ((str_starts_with($docType, 'list<') || str_starts_with($docType, 'array<')) && $type instanceof Array_) { - // array<value> is converted to x[] which is handled above - // so it's only necessary to handle array<key, value> here - $collectionKeyTypes = $this->getTypes($type->getKeyType()); - $collectionValueTypes = $this->getTypes($type->getValueType()); - - return new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, $collectionKeyTypes, $collectionValueTypes); - } - - $docType = $this->normalizeType($docType); - [$phpType, $class] = $this->getPhpTypeAndClass($docType); - - if ('array' === $docType) { - return new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, null, null); - } - - return new Type($phpType, $nullable, $class); - } - - private function normalizeType(string $docType): string - { - switch ($docType) { - case 'integer': - return 'int'; - - case 'boolean': - return 'bool'; - - // real is not part of the PHPDoc standard, so we ignore it - case 'double': - return 'float'; - - case 'callback': - return 'callable'; - - case 'void': - return 'null'; - - default: - return $docType; - } - } - - private function getPhpTypeAndClass(string $docType): array - { - if (\in_array($docType, Type::$builtinTypes)) { - return [$docType, null]; - } - - if (\in_array($docType, ['parent', 'self', 'static'], true)) { - return ['object', $docType]; - } - - return ['object', ltrim($docType, '\\')]; - } -} diff --git a/lib/symfony/property-info/Util/PhpStanTypeHelper.php b/lib/symfony/property-info/Util/PhpStanTypeHelper.php deleted file mode 100644 index 256122af7..000000000 --- a/lib/symfony/property-info/Util/PhpStanTypeHelper.php +++ /dev/null @@ -1,192 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyInfo\Util; - -use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode; -use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode; -use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode; -use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode; -use PHPStan\PhpDocParser\Ast\Type\ArrayShapeNode; -use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode; -use PHPStan\PhpDocParser\Ast\Type\CallableTypeNode; -use PHPStan\PhpDocParser\Ast\Type\CallableTypeParameterNode; -use PHPStan\PhpDocParser\Ast\Type\ConstTypeNode; -use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode; -use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; -use PHPStan\PhpDocParser\Ast\Type\NullableTypeNode; -use PHPStan\PhpDocParser\Ast\Type\ThisTypeNode; -use PHPStan\PhpDocParser\Ast\Type\TypeNode; -use PHPStan\PhpDocParser\Ast\Type\UnionTypeNode; -use Symfony\Component\PropertyInfo\PhpStan\NameScope; -use Symfony\Component\PropertyInfo\Type; - -/** - * Transforms a php doc tag value to a {@link Type} instance. - * - * @author Baptiste Leduc <baptiste.leduc@gmail.com> - * - * @internal - */ -final class PhpStanTypeHelper -{ - /** - * Creates a {@see Type} from a PhpDocTagValueNode type. - * - * @return Type[] - */ - public function getTypes(PhpDocTagValueNode $node, NameScope $nameScope): array - { - if ($node instanceof ParamTagValueNode || $node instanceof ReturnTagValueNode || $node instanceof VarTagValueNode) { - return $this->compressNullableType($this->extractTypes($node->type, $nameScope)); - } - - return []; - } - - /** - * Because PhpStan extract null as a separated type when Symfony / PHP compress it in the first available type we - * need this method to mimic how Symfony want null types. - * - * @param Type[] $types - * - * @return Type[] - */ - private function compressNullableType(array $types): array - { - $firstTypeIndex = null; - $nullableTypeIndex = null; - - foreach ($types as $k => $type) { - if (null === $firstTypeIndex && Type::BUILTIN_TYPE_NULL !== $type->getBuiltinType() && !$type->isNullable()) { - $firstTypeIndex = $k; - } - - if (null === $nullableTypeIndex && Type::BUILTIN_TYPE_NULL === $type->getBuiltinType()) { - $nullableTypeIndex = $k; - } - - if (null !== $firstTypeIndex && null !== $nullableTypeIndex) { - break; - } - } - - if (null !== $firstTypeIndex && null !== $nullableTypeIndex) { - $firstType = $types[$firstTypeIndex]; - $types[$firstTypeIndex] = new Type( - $firstType->getBuiltinType(), - true, - $firstType->getClassName(), - $firstType->isCollection(), - $firstType->getCollectionKeyTypes(), - $firstType->getCollectionValueTypes() - ); - unset($types[$nullableTypeIndex]); - } - - return array_values($types); - } - - /** - * @return Type[] - */ - private function extractTypes(TypeNode $node, NameScope $nameScope): array - { - if ($node instanceof UnionTypeNode) { - $types = []; - foreach ($node->types as $type) { - if ($type instanceof ConstTypeNode) { - // It's safer to fall back to other extractors here, as resolving const types correctly is not easy at the moment - return []; - } - foreach ($this->extractTypes($type, $nameScope) as $subType) { - $types[] = $subType; - } - } - - return $this->compressNullableType($types); - } - if ($node instanceof GenericTypeNode) { - [$mainType] = $this->extractTypes($node->type, $nameScope); - - if (Type::BUILTIN_TYPE_INT === $mainType->getBuiltinType()) { - return [$mainType]; - } - - $collectionKeyTypes = $mainType->getCollectionKeyTypes(); - $collectionKeyValues = []; - if (1 === \count($node->genericTypes)) { - foreach ($this->extractTypes($node->genericTypes[0], $nameScope) as $subType) { - $collectionKeyValues[] = $subType; - } - } elseif (2 === \count($node->genericTypes)) { - foreach ($this->extractTypes($node->genericTypes[0], $nameScope) as $keySubType) { - $collectionKeyTypes[] = $keySubType; - } - foreach ($this->extractTypes($node->genericTypes[1], $nameScope) as $valueSubType) { - $collectionKeyValues[] = $valueSubType; - } - } - - return [new Type($mainType->getBuiltinType(), $mainType->isNullable(), $mainType->getClassName(), true, $collectionKeyTypes, $collectionKeyValues)]; - } - if ($node instanceof ArrayShapeNode) { - return [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true)]; - } - if ($node instanceof ArrayTypeNode) { - return [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [new Type(Type::BUILTIN_TYPE_INT)], $this->extractTypes($node->type, $nameScope))]; - } - if ($node instanceof CallableTypeNode || $node instanceof CallableTypeParameterNode) { - return [new Type(Type::BUILTIN_TYPE_CALLABLE)]; - } - if ($node instanceof NullableTypeNode) { - $subTypes = $this->extractTypes($node->type, $nameScope); - if (\count($subTypes) > 1) { - $subTypes[] = new Type(Type::BUILTIN_TYPE_NULL); - - return $subTypes; - } - - return [new Type($subTypes[0]->getBuiltinType(), true, $subTypes[0]->getClassName(), $subTypes[0]->isCollection(), $subTypes[0]->getCollectionKeyTypes(), $subTypes[0]->getCollectionValueTypes())]; - } - if ($node instanceof ThisTypeNode) { - return [new Type(Type::BUILTIN_TYPE_OBJECT, false, $nameScope->resolveRootClass())]; - } - if ($node instanceof IdentifierTypeNode) { - if (\in_array($node->name, Type::$builtinTypes)) { - return [new Type($node->name, false, null, \in_array($node->name, Type::$builtinCollectionTypes))]; - } - - switch ($node->name) { - case 'integer': - return [new Type(Type::BUILTIN_TYPE_INT)]; - case 'list': - case 'non-empty-list': - return [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT))]; - case 'non-empty-array': - return [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true)]; - case 'mixed': - return []; // mixed seems to be ignored in all other extractors - case 'parent': - return [new Type(Type::BUILTIN_TYPE_OBJECT, false, $node->name)]; - case 'static': - case 'self': - return [new Type(Type::BUILTIN_TYPE_OBJECT, false, $nameScope->resolveRootClass())]; - case 'void': - return [new Type(Type::BUILTIN_TYPE_NULL)]; - } - - return [new Type(Type::BUILTIN_TYPE_OBJECT, false, $nameScope->resolveStringName($node->name))]; - } - - return []; - } -} diff --git a/lib/symfony/property-info/composer.json b/lib/symfony/property-info/composer.json deleted file mode 100644 index 79af9e860..000000000 --- a/lib/symfony/property-info/composer.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "name": "symfony/property-info", - "type": "library", - "description": "Extracts information about PHP class' properties using metadata of popular sources", - "keywords": [ - "property", - "type", - "phpdoc", - "symfony", - "validator", - "doctrine" - ], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Kévin Dunglas", - "email": "dunglas@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16", - "symfony/string": "^5.1|^6.0" - }, - "require-dev": { - "symfony/serializer": "^4.4|^5.0|^6.0", - "symfony/cache": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "phpstan/phpdoc-parser": "^1.0", - "doctrine/annotations": "^1.10.4|^2" - }, - "conflict": { - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", - "symfony/dependency-injection": "<4.4" - }, - "suggest": { - "psr/cache-implementation": "To cache results", - "symfony/doctrine-bridge": "To use Doctrine metadata", - "phpdocumentor/reflection-docblock": "To use the PHPDoc", - "symfony/serializer": "To use Serializer metadata" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\PropertyInfo\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/lib/symfony/routing/Alias.php b/lib/symfony/routing/Alias.php deleted file mode 100644 index f3e1d5a85..000000000 --- a/lib/symfony/routing/Alias.php +++ /dev/null @@ -1,96 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -use Symfony\Component\Routing\Exception\InvalidArgumentException; - -class Alias -{ - private $id; - private $deprecation = []; - - public function __construct(string $id) - { - $this->id = $id; - } - - /** - * @return static - */ - public function withId(string $id): self - { - $new = clone $this; - - $new->id = $id; - - return $new; - } - - /** - * Returns the target name of this alias. - * - * @return string The target name - */ - public function getId(): string - { - return $this->id; - } - - /** - * Whether this alias is deprecated, that means it should not be referenced anymore. - * - * @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 deprecation message to use - * - * @return $this - * - * @throws InvalidArgumentException when the message template is invalid - */ - public function setDeprecated(string $package, string $version, string $message): self - { - if ('' !== $message) { - if (preg_match('#[\r\n]|\*/#', $message)) { - throw new InvalidArgumentException('Invalid characters found in deprecation template.'); - } - - if (!str_contains($message, '%alias_id%')) { - throw new InvalidArgumentException('The deprecation template must contain the "%alias_id%" placeholder.'); - } - } - - $this->deprecation = [ - 'package' => $package, - 'version' => $version, - 'message' => $message ?: 'The "%alias_id%" route alias is deprecated. You should stop using it, as it will be removed in the future.', - ]; - - return $this; - } - - public function isDeprecated(): bool - { - return (bool) $this->deprecation; - } - - /** - * @param string $name Route name relying on this alias - */ - public function getDeprecation(string $name): array - { - return [ - 'package' => $this->deprecation['package'], - 'version' => $this->deprecation['version'], - 'message' => str_replace('%alias_id%', $name, $this->deprecation['message']), - ]; - } -} diff --git a/lib/symfony/routing/Annotation/Route.php b/lib/symfony/routing/Annotation/Route.php deleted file mode 100644 index 81563df20..000000000 --- a/lib/symfony/routing/Annotation/Route.php +++ /dev/null @@ -1,272 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Annotation; - -/** - * Annotation class for @Route(). - * - * @Annotation - * @NamedArgumentConstructor - * @Target({"CLASS", "METHOD"}) - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Alexander M. Turek <me@derrabus.de> - */ -#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD)] -class Route -{ - private $path; - private $localizedPaths = []; - private $name; - private $requirements = []; - private $options = []; - private $defaults = []; - private $host; - private $methods = []; - private $schemes = []; - private $condition; - private $priority; - private $env; - - /** - * @param array|string $data data array managed by the Doctrine Annotations library or the path - * @param array|string|null $path - * @param string[] $requirements - * @param string[]|string $methods - * @param string[]|string $schemes - * - * @throws \BadMethodCallException - */ - public function __construct( - $data = [], - $path = null, - string $name = null, - array $requirements = [], - array $options = [], - array $defaults = [], - string $host = null, - $methods = [], - $schemes = [], - string $condition = null, - int $priority = null, - string $locale = null, - string $format = null, - bool $utf8 = null, - bool $stateless = null, - string $env = null - ) { - if (\is_string($data)) { - $data = ['path' => $data]; - } elseif (!\is_array($data)) { - throw new \TypeError(sprintf('"%s": Argument $data is expected to be a string or array, got "%s".', __METHOD__, get_debug_type($data))); - } elseif ([] !== $data) { - $deprecation = false; - foreach ($data as $key => $val) { - if (\in_array($key, ['path', 'name', 'requirements', 'options', 'defaults', 'host', 'methods', 'schemes', 'condition', 'priority', 'locale', 'format', 'utf8', 'stateless', 'env', 'value'])) { - $deprecation = true; - } - } - - if ($deprecation) { - trigger_deprecation('symfony/routing', '5.3', 'Passing an array as first argument to "%s" is deprecated. Use named arguments instead.', __METHOD__); - } else { - $localizedPaths = $data; - $data = ['path' => $localizedPaths]; - } - } - if (null !== $path && !\is_string($path) && !\is_array($path)) { - throw new \TypeError(sprintf('"%s": Argument $path is expected to be a string, array or null, got "%s".', __METHOD__, get_debug_type($path))); - } - - $data['path'] = $data['path'] ?? $path; - $data['name'] = $data['name'] ?? $name; - $data['requirements'] = $data['requirements'] ?? $requirements; - $data['options'] = $data['options'] ?? $options; - $data['defaults'] = $data['defaults'] ?? $defaults; - $data['host'] = $data['host'] ?? $host; - $data['methods'] = $data['methods'] ?? $methods; - $data['schemes'] = $data['schemes'] ?? $schemes; - $data['condition'] = $data['condition'] ?? $condition; - $data['priority'] = $data['priority'] ?? $priority; - $data['locale'] = $data['locale'] ?? $locale; - $data['format'] = $data['format'] ?? $format; - $data['utf8'] = $data['utf8'] ?? $utf8; - $data['stateless'] = $data['stateless'] ?? $stateless; - $data['env'] = $data['env'] ?? $env; - - $data = array_filter($data, static function ($value): bool { - return null !== $value; - }); - - if (isset($data['localized_paths'])) { - throw new \BadMethodCallException(sprintf('Unknown property "localized_paths" on annotation "%s".', static::class)); - } - - if (isset($data['value'])) { - $data[\is_array($data['value']) ? 'localized_paths' : 'path'] = $data['value']; - unset($data['value']); - } - - if (isset($data['path']) && \is_array($data['path'])) { - $data['localized_paths'] = $data['path']; - unset($data['path']); - } - - if (isset($data['locale'])) { - $data['defaults']['_locale'] = $data['locale']; - unset($data['locale']); - } - - if (isset($data['format'])) { - $data['defaults']['_format'] = $data['format']; - unset($data['format']); - } - - if (isset($data['utf8'])) { - $data['options']['utf8'] = filter_var($data['utf8'], \FILTER_VALIDATE_BOOLEAN) ?: false; - unset($data['utf8']); - } - - if (isset($data['stateless'])) { - $data['defaults']['_stateless'] = filter_var($data['stateless'], \FILTER_VALIDATE_BOOLEAN) ?: false; - unset($data['stateless']); - } - - foreach ($data as $key => $value) { - $method = 'set'.str_replace('_', '', $key); - if (!method_exists($this, $method)) { - throw new \BadMethodCallException(sprintf('Unknown property "%s" on annotation "%s".', $key, static::class)); - } - $this->$method($value); - } - } - - public function setPath(string $path) - { - $this->path = $path; - } - - public function getPath() - { - return $this->path; - } - - public function setLocalizedPaths(array $localizedPaths) - { - $this->localizedPaths = $localizedPaths; - } - - public function getLocalizedPaths(): array - { - return $this->localizedPaths; - } - - public function setHost(string $pattern) - { - $this->host = $pattern; - } - - public function getHost() - { - return $this->host; - } - - public function setName(string $name) - { - $this->name = $name; - } - - public function getName() - { - return $this->name; - } - - public function setRequirements(array $requirements) - { - $this->requirements = $requirements; - } - - public function getRequirements() - { - return $this->requirements; - } - - public function setOptions(array $options) - { - $this->options = $options; - } - - public function getOptions() - { - return $this->options; - } - - public function setDefaults(array $defaults) - { - $this->defaults = $defaults; - } - - public function getDefaults() - { - return $this->defaults; - } - - public function setSchemes($schemes) - { - $this->schemes = \is_array($schemes) ? $schemes : [$schemes]; - } - - public function getSchemes() - { - return $this->schemes; - } - - public function setMethods($methods) - { - $this->methods = \is_array($methods) ? $methods : [$methods]; - } - - public function getMethods() - { - return $this->methods; - } - - public function setCondition(?string $condition) - { - $this->condition = $condition; - } - - public function getCondition() - { - return $this->condition; - } - - public function setPriority(int $priority): void - { - $this->priority = $priority; - } - - public function getPriority(): ?int - { - return $this->priority; - } - - public function setEnv(?string $env): void - { - $this->env = $env; - } - - public function getEnv(): ?string - { - return $this->env; - } -} diff --git a/lib/symfony/routing/CHANGELOG.md b/lib/symfony/routing/CHANGELOG.md deleted file mode 100644 index b96638987..000000000 --- a/lib/symfony/routing/CHANGELOG.md +++ /dev/null @@ -1,296 +0,0 @@ -CHANGELOG -========= - -5.3 ---- - - * Already encoded slashes are not decoded nor double-encoded anymore when generating URLs - * Add support for per-env configuration in XML and Yaml loaders - * Deprecate creating instances of the `Route` annotation class by passing an array of parameters - * Add `RoutingConfigurator::env()` to get the current environment - -5.2.0 ------ - - * Added support for inline definition of requirements and defaults for host - * Added support for `\A` and `\z` as regex start and end for route requirement - * Added support for `#[Route]` attributes - -5.1.0 ------ - - * added the protected method `PhpFileLoader::callConfigurator()` as extension point to ease custom routing configuration - * deprecated `RouteCollectionBuilder` in favor of `RoutingConfigurator`. - * added "priority" option to annotated routes - * added argument `$priority` to `RouteCollection::add()` - * deprecated the `RouteCompiler::REGEX_DELIMITER` constant - * added `ExpressionLanguageProvider` to expose extra functions to route conditions - * added support for a `stateless` keyword for configuring route stateless in PHP, YAML and XML configurations. - * added the "hosts" option to be able to configure the host per locale. - * added `RequestContext::fromUri()` to ease building the default context - -5.0.0 ------ - - * removed `PhpGeneratorDumper` and `PhpMatcherDumper` - * removed `generator_base_class`, `generator_cache_class`, `matcher_base_class` and `matcher_cache_class` router options - * `Serializable` implementing methods for `Route` and `CompiledRoute` are final - * removed referencing service route loaders with a single colon - * Removed `ServiceRouterLoader` and `ObjectRouteLoader`. - -4.4.0 ------ - - * Deprecated `ServiceRouterLoader` in favor of `ContainerLoader`. - * Deprecated `ObjectRouteLoader` in favor of `ObjectLoader`. - * Added a way to exclude patterns of resources from being imported by the `import()` method - -4.3.0 ------ - - * added `CompiledUrlMatcher` and `CompiledUrlMatcherDumper` - * added `CompiledUrlGenerator` and `CompiledUrlGeneratorDumper` - * deprecated `PhpGeneratorDumper` and `PhpMatcherDumper` - * deprecated `generator_base_class`, `generator_cache_class`, `matcher_base_class` and `matcher_cache_class` router options - * `Serializable` implementing methods for `Route` and `CompiledRoute` are marked as `@internal` and `@final`. - Instead of overwriting them, use `__serialize` and `__unserialize` as extension points which are forward compatible - with the new serialization methods in PHP 7.4. - * exposed `utf8` Route option, defaults "locale" and "format" in configuration loaders and configurators - * added support for invokable service route loaders - -4.2.0 ------ - - * added fallback to cultureless locale for internationalized routes - -4.0.0 ------ - - * dropped support for using UTF-8 route patterns without using the `utf8` option - * dropped support for using UTF-8 route requirements without using the `utf8` option - -3.4.0 ------ - - * Added `NoConfigurationException`. - * Added the possibility to define a prefix for all routes of a controller via @Route(name="prefix_") - * Added support for prioritized routing loaders. - * Add matched and default parameters to redirect responses - * Added support for a `controller` keyword for configuring route controllers in YAML and XML configurations. - -3.3.0 ------ - - * [DEPRECATION] Class parameters have been deprecated and will be removed in 4.0. - * router.options.generator_class - * router.options.generator_base_class - * router.options.generator_dumper_class - * router.options.matcher_class - * router.options.matcher_base_class - * router.options.matcher_dumper_class - * router.options.matcher.cache_class - * router.options.generator.cache_class - -3.2.0 ------ - - * Added support for `bool`, `int`, `float`, `string`, `list` and `map` defaults in XML configurations. - * Added support for UTF-8 requirements - -2.8.0 ------ - - * allowed specifying a directory to recursively load all routing configuration files it contains - * Added ObjectRouteLoader and ServiceRouteLoader that allow routes to be loaded - by calling a method on an object/service. - * [DEPRECATION] Deprecated the hardcoded value for the `$referenceType` argument of the `UrlGeneratorInterface::generate` method. - Use the constants defined in the `UrlGeneratorInterface` instead. - - Before: - - ```php - $router->generate('blog_show', ['slug' => 'my-blog-post'], true); - ``` - - After: - - ```php - use Symfony\Component\Routing\Generator\UrlGeneratorInterface; - - $router->generate('blog_show', ['slug' => 'my-blog-post'], UrlGeneratorInterface::ABSOLUTE_URL); - ``` - -2.5.0 ------ - - * [DEPRECATION] The `ApacheMatcherDumper` and `ApacheUrlMatcher` were deprecated and - will be removed in Symfony 3.0, since the performance gains were minimal and - it's hard to replicate the behavior of PHP implementation. - -2.3.0 ------ - - * added RequestContext::getQueryString() - -2.2.0 ------ - - * [DEPRECATION] Several route settings have been renamed (the old ones will be removed in 3.0): - - * The `pattern` setting for a route has been deprecated in favor of `path` - * The `_scheme` and `_method` requirements have been moved to the `schemes` and `methods` settings - - Before: - - ```yaml - article_edit: - pattern: /article/{id} - requirements: { '_method': 'POST|PUT', '_scheme': 'https', 'id': '\d+' } - ``` - - ```xml - <route id="article_edit" pattern="/article/{id}"> - <requirement key="_method">POST|PUT</requirement> - <requirement key="_scheme">https</requirement> - <requirement key="id">\d+</requirement> - </route> - ``` - - ```php - $route = new Route(); - $route->setPattern('/article/{id}'); - $route->setRequirement('_method', 'POST|PUT'); - $route->setRequirement('_scheme', 'https'); - ``` - - After: - - ```yaml - article_edit: - path: /article/{id} - methods: [POST, PUT] - schemes: https - requirements: { 'id': '\d+' } - ``` - - ```xml - <route id="article_edit" pattern="/article/{id}" methods="POST PUT" schemes="https"> - <requirement key="id">\d+</requirement> - </route> - ``` - - ```php - $route = new Route(); - $route->setPath('/article/{id}'); - $route->setMethods(['POST', 'PUT']); - $route->setSchemes('https'); - ``` - - * [BC BREAK] RouteCollection does not behave like a tree structure anymore but as - a flat array of Routes. So when using PHP to build the RouteCollection, you must - make sure to add routes to the sub-collection before adding it to the parent - collection (this is not relevant when using YAML or XML for Route definitions). - - Before: - - ```php - $rootCollection = new RouteCollection(); - $subCollection = new RouteCollection(); - $rootCollection->addCollection($subCollection); - $subCollection->add('foo', new Route('/foo')); - ``` - - After: - - ```php - $rootCollection = new RouteCollection(); - $subCollection = new RouteCollection(); - $subCollection->add('foo', new Route('/foo')); - $rootCollection->addCollection($subCollection); - ``` - - Also one must call `addCollection` from the bottom to the top hierarchy. - So the correct sequence is the following (and not the reverse): - - ```php - $childCollection->addCollection($grandchildCollection); - $rootCollection->addCollection($childCollection); - ``` - - * [DEPRECATION] The methods `RouteCollection::getParent()` and `RouteCollection::getRoot()` - have been deprecated and will be removed in Symfony 2.3. - * [BC BREAK] Misusing the `RouteCollection::addPrefix` method to add defaults, requirements - or options without adding a prefix is not supported anymore. So if you called `addPrefix` - with an empty prefix or `/` only (both have no relevance), like - `addPrefix('', $defaultsArray, $requirementsArray, $optionsArray)` - you need to use the new dedicated methods `addDefaults($defaultsArray)`, - `addRequirements($requirementsArray)` or `addOptions($optionsArray)` instead. - * [DEPRECATION] The `$options` parameter to `RouteCollection::addPrefix()` has been deprecated - because adding options has nothing to do with adding a path prefix. If you want to add options - to all child routes of a RouteCollection, you can use `addOptions()`. - * [DEPRECATION] The method `RouteCollection::getPrefix()` has been deprecated - because it suggested that all routes in the collection would have this prefix, which is - not necessarily true. On top of that, since there is no tree structure anymore, this method - is also useless. Don't worry about performance, prefix optimization for matching is still done - in the dumper, which was also improved in 2.2.0 to find even more grouping possibilities. - * [DEPRECATION] `RouteCollection::addCollection(RouteCollection $collection)` should now only be - used with a single parameter. The other params `$prefix`, `$default`, `$requirements` and `$options` - will still work, but have been deprecated. The `addPrefix` method should be used for this - use-case instead. - Before: `$parentCollection->addCollection($collection, '/prefix', [...], [...])` - After: - ```php - $collection->addPrefix('/prefix', [...], [...]); - $parentCollection->addCollection($collection); - ``` - * added support for the method default argument values when defining a @Route - * Adjacent placeholders without separator work now, e.g. `/{x}{y}{z}.{_format}`. - * Characters that function as separator between placeholders are now whitelisted - to fix routes with normal text around a variable, e.g. `/prefix{var}suffix`. - * [BC BREAK] The default requirement of a variable has been changed slightly. - Previously it disallowed the previous and the next char around a variable. Now - it disallows the slash (`/`) and the next char. Using the previous char added - no value and was problematic because the route `/index.{_format}` would be - matched by `/index.ht/ml`. - * The default requirement now uses possessive quantifiers when possible which - improves matching performance by up to 20% because it prevents backtracking - when it's not needed. - * The ConfigurableRequirementsInterface can now also be used to disable the requirements - check on URL generation completely by calling `setStrictRequirements(null)`. It - improves performance in production environment as you should know that params always - pass the requirements (otherwise it would break your link anyway). - * There is no restriction on the route name anymore. So non-alphanumeric characters - are now also allowed. - * [BC BREAK] `RouteCompilerInterface::compile(Route $route)` was made static - (only relevant if you implemented your own RouteCompiler). - * Added possibility to generate relative paths and network paths in the UrlGenerator, e.g. - "../parent-file" and "//example.com/dir/file". The third parameter in - `UrlGeneratorInterface::generate($name, $parameters = [], $referenceType = self::ABSOLUTE_PATH)` - now accepts more values and you should use the constants defined in `UrlGeneratorInterface` for - claritiy. The old method calls with a Boolean parameter will continue to work because they - equal the signature using the constants. - -2.1.0 ------ - - * added RequestMatcherInterface - * added RequestContext::fromRequest() - * the UrlMatcher does not throw a \LogicException anymore when the required - scheme is not the current one - * added TraceableUrlMatcher - * added the possibility to define options, default values and requirements - for placeholders in prefix, including imported routes - * added RouterInterface::getRouteCollection - * [BC BREAK] the UrlMatcher urldecodes the route parameters only once, they - were decoded twice before. Note that the `urldecode()` calls have been - changed for a single `rawurldecode()` in order to support `+` for input - paths. - * added RouteCollection::getRoot method to retrieve the root of a - RouteCollection tree - * [BC BREAK] made RouteCollection::setParent private which could not have - been used anyway without creating inconsistencies - * [BC BREAK] RouteCollection::remove also removes a route from parent - collections (not only from its children) - * added ConfigurableRequirementsInterface that allows to disable exceptions - (and generate empty URLs instead) when generating a route with an invalid - parameter value diff --git a/lib/symfony/routing/CompiledRoute.php b/lib/symfony/routing/CompiledRoute.php deleted file mode 100644 index 1449cdb92..000000000 --- a/lib/symfony/routing/CompiledRoute.php +++ /dev/null @@ -1,173 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -/** - * CompiledRoutes are returned by the RouteCompiler class. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class CompiledRoute implements \Serializable -{ - private $variables; - private $tokens; - private $staticPrefix; - private $regex; - private $pathVariables; - private $hostVariables; - private $hostRegex; - private $hostTokens; - - /** - * @param string $staticPrefix The static prefix of the compiled route - * @param string $regex The regular expression to use to match this route - * @param array $tokens An array of tokens to use to generate URL for this route - * @param array $pathVariables An array of path variables - * @param string|null $hostRegex Host regex - * @param array $hostTokens Host tokens - * @param array $hostVariables An array of host variables - * @param array $variables An array of variables (variables defined in the path and in the host patterns) - */ - public function __construct(string $staticPrefix, string $regex, array $tokens, array $pathVariables, string $hostRegex = null, array $hostTokens = [], array $hostVariables = [], array $variables = []) - { - $this->staticPrefix = $staticPrefix; - $this->regex = $regex; - $this->tokens = $tokens; - $this->pathVariables = $pathVariables; - $this->hostRegex = $hostRegex; - $this->hostTokens = $hostTokens; - $this->hostVariables = $hostVariables; - $this->variables = $variables; - } - - public function __serialize(): array - { - return [ - 'vars' => $this->variables, - 'path_prefix' => $this->staticPrefix, - 'path_regex' => $this->regex, - 'path_tokens' => $this->tokens, - 'path_vars' => $this->pathVariables, - 'host_regex' => $this->hostRegex, - 'host_tokens' => $this->hostTokens, - 'host_vars' => $this->hostVariables, - ]; - } - - /** - * @internal - */ - final public function serialize(): string - { - return serialize($this->__serialize()); - } - - public function __unserialize(array $data): void - { - $this->variables = $data['vars']; - $this->staticPrefix = $data['path_prefix']; - $this->regex = $data['path_regex']; - $this->tokens = $data['path_tokens']; - $this->pathVariables = $data['path_vars']; - $this->hostRegex = $data['host_regex']; - $this->hostTokens = $data['host_tokens']; - $this->hostVariables = $data['host_vars']; - } - - /** - * @internal - */ - final public function unserialize($serialized) - { - $this->__unserialize(unserialize($serialized, ['allowed_classes' => false])); - } - - /** - * Returns the static prefix. - * - * @return string - */ - public function getStaticPrefix() - { - return $this->staticPrefix; - } - - /** - * Returns the regex. - * - * @return string - */ - public function getRegex() - { - return $this->regex; - } - - /** - * Returns the host regex. - * - * @return string|null - */ - public function getHostRegex() - { - return $this->hostRegex; - } - - /** - * Returns the tokens. - * - * @return array - */ - public function getTokens() - { - return $this->tokens; - } - - /** - * Returns the host tokens. - * - * @return array - */ - public function getHostTokens() - { - return $this->hostTokens; - } - - /** - * Returns the variables. - * - * @return array - */ - public function getVariables() - { - return $this->variables; - } - - /** - * Returns the path variables. - * - * @return array - */ - public function getPathVariables() - { - return $this->pathVariables; - } - - /** - * Returns the host variables. - * - * @return array - */ - public function getHostVariables() - { - return $this->hostVariables; - } -} diff --git a/lib/symfony/routing/DependencyInjection/RoutingResolverPass.php b/lib/symfony/routing/DependencyInjection/RoutingResolverPass.php deleted file mode 100644 index 0e9b9c893..000000000 --- a/lib/symfony/routing/DependencyInjection/RoutingResolverPass.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\DependencyInjection; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Adds tagged routing.loader services to routing.resolver service. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class RoutingResolverPass implements CompilerPassInterface -{ - use PriorityTaggedServiceTrait; - - private $resolverServiceId; - private $loaderTag; - - public function __construct(string $resolverServiceId = 'routing.resolver', string $loaderTag = 'routing.loader') - { - if (0 < \func_num_args()) { - trigger_deprecation('symfony/routing', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); - } - - $this->resolverServiceId = $resolverServiceId; - $this->loaderTag = $loaderTag; - } - - public function process(ContainerBuilder $container) - { - if (false === $container->hasDefinition($this->resolverServiceId)) { - return; - } - - $definition = $container->getDefinition($this->resolverServiceId); - - foreach ($this->findAndSortTaggedServices($this->loaderTag, $container) as $id) { - $definition->addMethodCall('addLoader', [new Reference($id)]); - } - } -} diff --git a/lib/symfony/routing/Exception/ExceptionInterface.php b/lib/symfony/routing/Exception/ExceptionInterface.php deleted file mode 100644 index 22e72b16b..000000000 --- a/lib/symfony/routing/Exception/ExceptionInterface.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -/** - * ExceptionInterface. - * - * @author Alexandre Salomé <alexandre.salome@gmail.com> - */ -interface ExceptionInterface extends \Throwable -{ -} diff --git a/lib/symfony/routing/Exception/InvalidArgumentException.php b/lib/symfony/routing/Exception/InvalidArgumentException.php deleted file mode 100644 index 950b9b15c..000000000 --- a/lib/symfony/routing/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/lib/symfony/routing/Exception/InvalidParameterException.php b/lib/symfony/routing/Exception/InvalidParameterException.php deleted file mode 100644 index 94d841f4c..000000000 --- a/lib/symfony/routing/Exception/InvalidParameterException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -/** - * Exception thrown when a parameter is not valid. - * - * @author Alexandre Salomé <alexandre.salome@gmail.com> - */ -class InvalidParameterException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/lib/symfony/routing/Exception/MethodNotAllowedException.php b/lib/symfony/routing/Exception/MethodNotAllowedException.php deleted file mode 100644 index 27cf2125e..000000000 --- a/lib/symfony/routing/Exception/MethodNotAllowedException.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -/** - * The resource was found but the request method is not allowed. - * - * This exception should trigger an HTTP 405 response in your application code. - * - * @author Kris Wallsmith <kris@symfony.com> - */ -class MethodNotAllowedException extends \RuntimeException implements ExceptionInterface -{ - protected $allowedMethods = []; - - /** - * @param string[] $allowedMethods - */ - public function __construct(array $allowedMethods, ?string $message = '', int $code = 0, \Throwable $previous = null) - { - if (null === $message) { - trigger_deprecation('symfony/routing', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__); - - $message = ''; - } - - $this->allowedMethods = array_map('strtoupper', $allowedMethods); - - parent::__construct($message, $code, $previous); - } - - /** - * Gets the allowed HTTP methods. - * - * @return string[] - */ - public function getAllowedMethods() - { - return $this->allowedMethods; - } -} diff --git a/lib/symfony/routing/Exception/MissingMandatoryParametersException.php b/lib/symfony/routing/Exception/MissingMandatoryParametersException.php deleted file mode 100644 index 57f3a40df..000000000 --- a/lib/symfony/routing/Exception/MissingMandatoryParametersException.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -/** - * Exception thrown when a route cannot be generated because of missing - * mandatory parameters. - * - * @author Alexandre Salomé <alexandre.salome@gmail.com> - */ -class MissingMandatoryParametersException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/lib/symfony/routing/Exception/NoConfigurationException.php b/lib/symfony/routing/Exception/NoConfigurationException.php deleted file mode 100644 index 333bc7433..000000000 --- a/lib/symfony/routing/Exception/NoConfigurationException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -/** - * Exception thrown when no routes are configured. - * - * @author Yonel Ceruto <yonelceruto@gmail.com> - */ -class NoConfigurationException extends ResourceNotFoundException -{ -} diff --git a/lib/symfony/routing/Exception/ResourceNotFoundException.php b/lib/symfony/routing/Exception/ResourceNotFoundException.php deleted file mode 100644 index ccbca1527..000000000 --- a/lib/symfony/routing/Exception/ResourceNotFoundException.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -/** - * The resource was not found. - * - * This exception should trigger an HTTP 404 response in your application code. - * - * @author Kris Wallsmith <kris@symfony.com> - */ -class ResourceNotFoundException extends \RuntimeException implements ExceptionInterface -{ -} diff --git a/lib/symfony/routing/Exception/RouteCircularReferenceException.php b/lib/symfony/routing/Exception/RouteCircularReferenceException.php deleted file mode 100644 index 841e35989..000000000 --- a/lib/symfony/routing/Exception/RouteCircularReferenceException.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -class RouteCircularReferenceException extends RuntimeException -{ - public function __construct(string $routeId, array $path) - { - parent::__construct(sprintf('Circular reference detected for route "%s", path: "%s".', $routeId, implode(' -> ', $path))); - } -} diff --git a/lib/symfony/routing/Exception/RouteNotFoundException.php b/lib/symfony/routing/Exception/RouteNotFoundException.php deleted file mode 100644 index 24ab0b44a..000000000 --- a/lib/symfony/routing/Exception/RouteNotFoundException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -/** - * Exception thrown when a route does not exist. - * - * @author Alexandre Salomé <alexandre.salome@gmail.com> - */ -class RouteNotFoundException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/lib/symfony/routing/Exception/RuntimeException.php b/lib/symfony/routing/Exception/RuntimeException.php deleted file mode 100644 index 48da62ec8..000000000 --- a/lib/symfony/routing/Exception/RuntimeException.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -class RuntimeException extends \RuntimeException implements ExceptionInterface -{ -} diff --git a/lib/symfony/routing/Generator/CompiledUrlGenerator.php b/lib/symfony/routing/Generator/CompiledUrlGenerator.php deleted file mode 100644 index 8cbbf8f70..000000000 --- a/lib/symfony/routing/Generator/CompiledUrlGenerator.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Generator; - -use Psr\Log\LoggerInterface; -use Symfony\Component\Routing\Exception\RouteNotFoundException; -use Symfony\Component\Routing\RequestContext; - -/** - * Generates URLs based on rules dumped by CompiledUrlGeneratorDumper. - */ -class CompiledUrlGenerator extends UrlGenerator -{ - private $compiledRoutes = []; - private $defaultLocale; - - public function __construct(array $compiledRoutes, RequestContext $context, LoggerInterface $logger = null, string $defaultLocale = null) - { - $this->compiledRoutes = $compiledRoutes; - $this->context = $context; - $this->logger = $logger; - $this->defaultLocale = $defaultLocale; - } - - public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH) - { - $locale = $parameters['_locale'] - ?? $this->context->getParameter('_locale') - ?: $this->defaultLocale; - - if (null !== $locale) { - do { - if (($this->compiledRoutes[$name.'.'.$locale][1]['_canonical_route'] ?? null) === $name) { - $name .= '.'.$locale; - break; - } - } while (false !== $locale = strstr($locale, '_', true)); - } - - if (!isset($this->compiledRoutes[$name])) { - throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name)); - } - - [$variables, $defaults, $requirements, $tokens, $hostTokens, $requiredSchemes, $deprecations] = $this->compiledRoutes[$name] + [6 => []]; - - foreach ($deprecations as $deprecation) { - trigger_deprecation($deprecation['package'], $deprecation['version'], $deprecation['message']); - } - - if (isset($defaults['_canonical_route']) && isset($defaults['_locale'])) { - if (!\in_array('_locale', $variables, true)) { - unset($parameters['_locale']); - } elseif (!isset($parameters['_locale'])) { - $parameters['_locale'] = $defaults['_locale']; - } - } - - return $this->doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, $requiredSchemes); - } -} diff --git a/lib/symfony/routing/Generator/ConfigurableRequirementsInterface.php b/lib/symfony/routing/Generator/ConfigurableRequirementsInterface.php deleted file mode 100644 index 568f7f775..000000000 --- a/lib/symfony/routing/Generator/ConfigurableRequirementsInterface.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Generator; - -/** - * ConfigurableRequirementsInterface must be implemented by URL generators that - * can be configured whether an exception should be generated when the parameters - * do not match the requirements. It is also possible to disable the requirements - * check for URL generation completely. - * - * The possible configurations and use-cases: - * - setStrictRequirements(true): Throw an exception for mismatching requirements. This - * is mostly useful in development environment. - * - setStrictRequirements(false): Don't throw an exception but return an empty string as URL for - * mismatching requirements and log the problem. Useful when you cannot control all - * params because they come from third party libs but don't want to have a 404 in - * production environment. It should log the mismatch so one can review it. - * - setStrictRequirements(null): Return the URL with the given parameters without - * checking the requirements at all. When generating a URL you should either trust - * your params or you validated them beforehand because otherwise it would break your - * link anyway. So in production environment you should know that params always pass - * the requirements. Thus this option allows to disable the check on URL generation for - * performance reasons (saving a preg_match for each requirement every time a URL is - * generated). - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Tobias Schultze <http://tobion.de> - */ -interface ConfigurableRequirementsInterface -{ - /** - * Enables or disables the exception on incorrect parameters. - * Passing null will deactivate the requirements check completely. - */ - public function setStrictRequirements(?bool $enabled); - - /** - * Returns whether to throw an exception on incorrect parameters. - * Null means the requirements check is deactivated completely. - * - * @return bool|null - */ - public function isStrictRequirements(); -} diff --git a/lib/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php b/lib/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php deleted file mode 100644 index 9c6740b61..000000000 --- a/lib/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php +++ /dev/null @@ -1,124 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Generator\Dumper; - -use Symfony\Component\Routing\Exception\RouteCircularReferenceException; -use Symfony\Component\Routing\Exception\RouteNotFoundException; -use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; - -/** - * CompiledUrlGeneratorDumper creates a PHP array to be used with CompiledUrlGenerator. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Tobias Schultze <http://tobion.de> - * @author Nicolas Grekas <p@tchwork.com> - */ -class CompiledUrlGeneratorDumper extends GeneratorDumper -{ - public function getCompiledRoutes(): array - { - $compiledRoutes = []; - foreach ($this->getRoutes()->all() as $name => $route) { - $compiledRoute = $route->compile(); - - $compiledRoutes[$name] = [ - $compiledRoute->getVariables(), - $route->getDefaults(), - $route->getRequirements(), - $compiledRoute->getTokens(), - $compiledRoute->getHostTokens(), - $route->getSchemes(), - [], - ]; - } - - return $compiledRoutes; - } - - public function getCompiledAliases(): array - { - $routes = $this->getRoutes(); - $compiledAliases = []; - foreach ($routes->getAliases() as $name => $alias) { - $deprecations = $alias->isDeprecated() ? [$alias->getDeprecation($name)] : []; - $currentId = $alias->getId(); - $visited = []; - while (null !== $alias = $routes->getAlias($currentId) ?? null) { - if (false !== $searchKey = array_search($currentId, $visited)) { - $visited[] = $currentId; - - throw new RouteCircularReferenceException($currentId, \array_slice($visited, $searchKey)); - } - - if ($alias->isDeprecated()) { - $deprecations[] = $deprecation = $alias->getDeprecation($currentId); - trigger_deprecation($deprecation['package'], $deprecation['version'], $deprecation['message']); - } - - $visited[] = $currentId; - $currentId = $alias->getId(); - } - - if (null === $target = $routes->get($currentId)) { - throw new RouteNotFoundException(sprintf('Target route "%s" for alias "%s" does not exist.', $currentId, $name)); - } - - $compiledTarget = $target->compile(); - - $compiledAliases[$name] = [ - $compiledTarget->getVariables(), - $target->getDefaults(), - $target->getRequirements(), - $compiledTarget->getTokens(), - $compiledTarget->getHostTokens(), - $target->getSchemes(), - $deprecations, - ]; - } - - return $compiledAliases; - } - - /** - * {@inheritdoc} - */ - public function dump(array $options = []) - { - return <<<EOF -<?php - -// This file has been auto-generated by the Symfony Routing Component. - -return [{$this->generateDeclaredRoutes()} -]; - -EOF; - } - - /** - * Generates PHP code representing an array of defined routes - * together with the routes properties (e.g. requirements). - */ - private function generateDeclaredRoutes(): string - { - $routes = ''; - foreach ($this->getCompiledRoutes() as $name => $properties) { - $routes .= sprintf("\n '%s' => %s,", $name, CompiledUrlMatcherDumper::export($properties)); - } - - foreach ($this->getCompiledAliases() as $alias => $properties) { - $routes .= sprintf("\n '%s' => %s,", $alias, CompiledUrlMatcherDumper::export($properties)); - } - - return $routes; - } -} diff --git a/lib/symfony/routing/Generator/Dumper/GeneratorDumper.php b/lib/symfony/routing/Generator/Dumper/GeneratorDumper.php deleted file mode 100644 index 659c5ba1c..000000000 --- a/lib/symfony/routing/Generator/Dumper/GeneratorDumper.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Generator\Dumper; - -use Symfony\Component\Routing\RouteCollection; - -/** - * GeneratorDumper is the base class for all built-in generator dumpers. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -abstract class GeneratorDumper implements GeneratorDumperInterface -{ - private $routes; - - public function __construct(RouteCollection $routes) - { - $this->routes = $routes; - } - - /** - * {@inheritdoc} - */ - public function getRoutes() - { - return $this->routes; - } -} diff --git a/lib/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php b/lib/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php deleted file mode 100644 index d4a248a5b..000000000 --- a/lib/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Generator\Dumper; - -use Symfony\Component\Routing\RouteCollection; - -/** - * GeneratorDumperInterface is the interface that all generator dumper classes must implement. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface GeneratorDumperInterface -{ - /** - * Dumps a set of routes to a string representation of executable code - * that can then be used to generate a URL of such a route. - * - * @return string - */ - public function dump(array $options = []); - - /** - * Gets the routes to dump. - * - * @return RouteCollection - */ - public function getRoutes(); -} diff --git a/lib/symfony/routing/Generator/UrlGenerator.php b/lib/symfony/routing/Generator/UrlGenerator.php deleted file mode 100644 index acf3ead4f..000000000 --- a/lib/symfony/routing/Generator/UrlGenerator.php +++ /dev/null @@ -1,378 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Generator; - -use Psr\Log\LoggerInterface; -use Symfony\Component\Routing\Exception\InvalidParameterException; -use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; -use Symfony\Component\Routing\Exception\RouteNotFoundException; -use Symfony\Component\Routing\RequestContext; -use Symfony\Component\Routing\RouteCollection; - -/** - * UrlGenerator can generate a URL or a path for any route in the RouteCollection - * based on the passed parameters. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Tobias Schultze <http://tobion.de> - */ -class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInterface -{ - private const QUERY_FRAGMENT_DECODED = [ - // RFC 3986 explicitly allows those in the query/fragment to reference other URIs unencoded - '%2F' => '/', - '%3F' => '?', - // reserved chars that have no special meaning for HTTP URIs in a query or fragment - // this excludes esp. "&", "=" and also "+" because PHP would treat it as a space (form-encoded) - '%40' => '@', - '%3A' => ':', - '%21' => '!', - '%3B' => ';', - '%2C' => ',', - '%2A' => '*', - ]; - - protected $routes; - protected $context; - - /** - * @var bool|null - */ - protected $strictRequirements = true; - - protected $logger; - - private $defaultLocale; - - /** - * This array defines the characters (besides alphanumeric ones) that will not be percent-encoded in the path segment of the generated URL. - * - * PHP's rawurlencode() encodes all chars except "a-zA-Z0-9-._~" according to RFC 3986. But we want to allow some chars - * to be used in their literal form (reasons below). Other chars inside the path must of course be encoded, e.g. - * "?" and "#" (would be interpreted wrongly as query and fragment identifier), - * "'" and """ (are used as delimiters in HTML). - */ - protected $decodedChars = [ - // the slash can be used to designate a hierarchical structure and we want allow using it with this meaning - // some webservers don't allow the slash in encoded form in the path for security reasons anyway - // see http://stackoverflow.com/questions/4069002/http-400-if-2f-part-of-get-url-in-jboss - '%2F' => '/', - '%252F' => '%2F', - // the following chars are general delimiters in the URI specification but have only special meaning in the authority component - // so they can safely be used in the path in unencoded form - '%40' => '@', - '%3A' => ':', - // these chars are only sub-delimiters that have no predefined meaning and can therefore be used literally - // so URI producing applications can use these chars to delimit subcomponents in a path segment without being encoded for better readability - '%3B' => ';', - '%2C' => ',', - '%3D' => '=', - '%2B' => '+', - '%21' => '!', - '%2A' => '*', - '%7C' => '|', - ]; - - public function __construct(RouteCollection $routes, RequestContext $context, LoggerInterface $logger = null, string $defaultLocale = null) - { - $this->routes = $routes; - $this->context = $context; - $this->logger = $logger; - $this->defaultLocale = $defaultLocale; - } - - /** - * {@inheritdoc} - */ - public function setContext(RequestContext $context) - { - $this->context = $context; - } - - /** - * {@inheritdoc} - */ - public function getContext() - { - return $this->context; - } - - /** - * {@inheritdoc} - */ - public function setStrictRequirements(?bool $enabled) - { - $this->strictRequirements = $enabled; - } - - /** - * {@inheritdoc} - */ - public function isStrictRequirements() - { - return $this->strictRequirements; - } - - /** - * {@inheritdoc} - */ - public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH) - { - $route = null; - $locale = $parameters['_locale'] - ?? $this->context->getParameter('_locale') - ?: $this->defaultLocale; - - if (null !== $locale) { - do { - if (null !== ($route = $this->routes->get($name.'.'.$locale)) && $route->getDefault('_canonical_route') === $name) { - break; - } - } while (false !== $locale = strstr($locale, '_', true)); - } - - if (null === $route = $route ?? $this->routes->get($name)) { - throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name)); - } - - // the Route has a cache of its own and is not recompiled as long as it does not get modified - $compiledRoute = $route->compile(); - - $defaults = $route->getDefaults(); - $variables = $compiledRoute->getVariables(); - - if (isset($defaults['_canonical_route']) && isset($defaults['_locale'])) { - if (!\in_array('_locale', $variables, true)) { - unset($parameters['_locale']); - } elseif (!isset($parameters['_locale'])) { - $parameters['_locale'] = $defaults['_locale']; - } - } - - return $this->doGenerate($variables, $defaults, $route->getRequirements(), $compiledRoute->getTokens(), $parameters, $name, $referenceType, $compiledRoute->getHostTokens(), $route->getSchemes()); - } - - /** - * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route - * @throws InvalidParameterException When a parameter value for a placeholder is not correct because - * it does not match the requirement - * - * @return string - */ - protected function doGenerate(array $variables, array $defaults, array $requirements, array $tokens, array $parameters, string $name, int $referenceType, array $hostTokens, array $requiredSchemes = []) - { - $variables = array_flip($variables); - $mergedParams = array_replace($defaults, $this->context->getParameters(), $parameters); - - // all params must be given - if ($diff = array_diff_key($variables, $mergedParams)) { - throw new MissingMandatoryParametersException(sprintf('Some mandatory parameters are missing ("%s") to generate a URL for route "%s".', implode('", "', array_keys($diff)), $name)); - } - - $url = ''; - $optional = true; - $message = 'Parameter "{parameter}" for route "{route}" must match "{expected}" ("{given}" given) to generate a corresponding URL.'; - foreach ($tokens as $token) { - if ('variable' === $token[0]) { - $varName = $token[3]; - // variable is not important by default - $important = $token[5] ?? false; - - if (!$optional || $important || !\array_key_exists($varName, $defaults) || (null !== $mergedParams[$varName] && (string) $mergedParams[$varName] !== (string) $defaults[$varName])) { - // check requirement (while ignoring look-around patterns) - if (null !== $this->strictRequirements && !preg_match('#^'.preg_replace('/\(\?(?:=|<=|!|<!)((?:[^()\\\\]+|\\\\.|\((?1)\))*)\)/', '', $token[2]).'$#i'.(empty($token[4]) ? '' : 'u'), $mergedParams[$token[3]] ?? '')) { - if ($this->strictRequirements) { - throw new InvalidParameterException(strtr($message, ['{parameter}' => $varName, '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$varName]])); - } - - if ($this->logger) { - $this->logger->error($message, ['parameter' => $varName, 'route' => $name, 'expected' => $token[2], 'given' => $mergedParams[$varName]]); - } - - return ''; - } - - $url = $token[1].$mergedParams[$varName].$url; - $optional = false; - } - } else { - // static text - $url = $token[1].$url; - $optional = false; - } - } - - if ('' === $url) { - $url = '/'; - } - - // the contexts base URL is already encoded (see Symfony\Component\HttpFoundation\Request) - $url = strtr(rawurlencode($url), $this->decodedChars); - - // the path segments "." and ".." are interpreted as relative reference when resolving a URI; see http://tools.ietf.org/html/rfc3986#section-3.3 - // so we need to encode them as they are not used for this purpose here - // otherwise we would generate a URI that, when followed by a user agent (e.g. browser), does not match this route - $url = strtr($url, ['/../' => '/%2E%2E/', '/./' => '/%2E/']); - if (str_ends_with($url, '/..')) { - $url = substr($url, 0, -2).'%2E%2E'; - } elseif (str_ends_with($url, '/.')) { - $url = substr($url, 0, -1).'%2E'; - } - - $schemeAuthority = ''; - $host = $this->context->getHost(); - $scheme = $this->context->getScheme(); - - if ($requiredSchemes) { - if (!\in_array($scheme, $requiredSchemes, true)) { - $referenceType = self::ABSOLUTE_URL; - $scheme = current($requiredSchemes); - } - } - - if ($hostTokens) { - $routeHost = ''; - foreach ($hostTokens as $token) { - if ('variable' === $token[0]) { - // check requirement (while ignoring look-around patterns) - if (null !== $this->strictRequirements && !preg_match('#^'.preg_replace('/\(\?(?:=|<=|!|<!)((?:[^()\\\\]+|\\\\.|\((?1)\))*)\)/', '', $token[2]).'$#i'.(empty($token[4]) ? '' : 'u'), $mergedParams[$token[3]])) { - if ($this->strictRequirements) { - throw new InvalidParameterException(strtr($message, ['{parameter}' => $token[3], '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$token[3]]])); - } - - if ($this->logger) { - $this->logger->error($message, ['parameter' => $token[3], 'route' => $name, 'expected' => $token[2], 'given' => $mergedParams[$token[3]]]); - } - - return ''; - } - - $routeHost = $token[1].$mergedParams[$token[3]].$routeHost; - } else { - $routeHost = $token[1].$routeHost; - } - } - - if ($routeHost !== $host) { - $host = $routeHost; - if (self::ABSOLUTE_URL !== $referenceType) { - $referenceType = self::NETWORK_PATH; - } - } - } - - if (self::ABSOLUTE_URL === $referenceType || self::NETWORK_PATH === $referenceType) { - if ('' !== $host || ('' !== $scheme && 'http' !== $scheme && 'https' !== $scheme)) { - $port = ''; - if ('http' === $scheme && 80 !== $this->context->getHttpPort()) { - $port = ':'.$this->context->getHttpPort(); - } elseif ('https' === $scheme && 443 !== $this->context->getHttpsPort()) { - $port = ':'.$this->context->getHttpsPort(); - } - - $schemeAuthority = self::NETWORK_PATH === $referenceType || '' === $scheme ? '//' : "$scheme://"; - $schemeAuthority .= $host.$port; - } - } - - if (self::RELATIVE_PATH === $referenceType) { - $url = self::getRelativePath($this->context->getPathInfo(), $url); - } else { - $url = $schemeAuthority.$this->context->getBaseUrl().$url; - } - - // add a query string if needed - $extra = array_udiff_assoc(array_diff_key($parameters, $variables), $defaults, function ($a, $b) { - return $a == $b ? 0 : 1; - }); - - array_walk_recursive($extra, $caster = static function (&$v) use (&$caster) { - if (\is_object($v)) { - if ($vars = get_object_vars($v)) { - array_walk_recursive($vars, $caster); - $v = $vars; - } elseif (method_exists($v, '__toString')) { - $v = (string) $v; - } - } - }); - - // extract fragment - $fragment = $defaults['_fragment'] ?? ''; - - if (isset($extra['_fragment'])) { - $fragment = $extra['_fragment']; - unset($extra['_fragment']); - } - - if ($extra && $query = http_build_query($extra, '', '&', \PHP_QUERY_RFC3986)) { - $url .= '?'.strtr($query, self::QUERY_FRAGMENT_DECODED); - } - - if ('' !== $fragment) { - $url .= '#'.strtr(rawurlencode($fragment), self::QUERY_FRAGMENT_DECODED); - } - - return $url; - } - - /** - * Returns the target path as relative reference from the base path. - * - * Only the URIs path component (no schema, host etc.) is relevant and must be given, starting with a slash. - * Both paths must be absolute and not contain relative parts. - * Relative URLs from one resource to another are useful when generating self-contained downloadable document archives. - * Furthermore, they can be used to reduce the link size in documents. - * - * Example target paths, given a base path of "/a/b/c/d": - * - "/a/b/c/d" -> "" - * - "/a/b/c/" -> "./" - * - "/a/b/" -> "../" - * - "/a/b/c/other" -> "other" - * - "/a/x/y" -> "../../x/y" - * - * @param string $basePath The base path - * @param string $targetPath The target path - * - * @return string - */ - public static function getRelativePath(string $basePath, string $targetPath) - { - if ($basePath === $targetPath) { - return ''; - } - - $sourceDirs = explode('/', isset($basePath[0]) && '/' === $basePath[0] ? substr($basePath, 1) : $basePath); - $targetDirs = explode('/', isset($targetPath[0]) && '/' === $targetPath[0] ? substr($targetPath, 1) : $targetPath); - array_pop($sourceDirs); - $targetFile = array_pop($targetDirs); - - foreach ($sourceDirs as $i => $dir) { - if (isset($targetDirs[$i]) && $dir === $targetDirs[$i]) { - unset($sourceDirs[$i], $targetDirs[$i]); - } else { - break; - } - } - - $targetDirs[] = $targetFile; - $path = str_repeat('../', \count($sourceDirs)).implode('/', $targetDirs); - - // A reference to the same base directory or an empty subdirectory must be prefixed with "./". - // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used - // as the first segment of a relative-path reference, as it would be mistaken for a scheme name - // (see http://tools.ietf.org/html/rfc3986#section-4.2). - return '' === $path || '/' === $path[0] - || false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || false === $slashPos) - ? "./$path" : $path; - } -} diff --git a/lib/symfony/routing/Generator/UrlGeneratorInterface.php b/lib/symfony/routing/Generator/UrlGeneratorInterface.php deleted file mode 100644 index c6d5005f9..000000000 --- a/lib/symfony/routing/Generator/UrlGeneratorInterface.php +++ /dev/null @@ -1,82 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Generator; - -use Symfony\Component\Routing\Exception\InvalidParameterException; -use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; -use Symfony\Component\Routing\Exception\RouteNotFoundException; -use Symfony\Component\Routing\RequestContextAwareInterface; - -/** - * UrlGeneratorInterface is the interface that all URL generator classes must implement. - * - * The constants in this interface define the different types of resource references that - * are declared in RFC 3986: http://tools.ietf.org/html/rfc3986 - * We are using the term "URL" instead of "URI" as this is more common in web applications - * and we do not need to distinguish them as the difference is mostly semantical and - * less technical. Generating URIs, i.e. representation-independent resource identifiers, - * is also possible. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Tobias Schultze <http://tobion.de> - */ -interface UrlGeneratorInterface extends RequestContextAwareInterface -{ - /** - * Generates an absolute URL, e.g. "http://example.com/dir/file". - */ - public const ABSOLUTE_URL = 0; - - /** - * Generates an absolute path, e.g. "/dir/file". - */ - public const ABSOLUTE_PATH = 1; - - /** - * Generates a relative path based on the current request path, e.g. "../parent-file". - * - * @see UrlGenerator::getRelativePath() - */ - public const RELATIVE_PATH = 2; - - /** - * Generates a network path, e.g. "//example.com/dir/file". - * Such reference reuses the current scheme but specifies the host. - */ - public const NETWORK_PATH = 3; - - /** - * Generates a URL or path for a specific route based on the given parameters. - * - * Parameters that reference placeholders in the route pattern will substitute them in the - * path or host. Extra params are added as query string to the URL. - * - * When the passed reference type cannot be generated for the route because it requires a different - * host or scheme than the current one, the method will return a more comprehensive reference - * that includes the required params. For example, when you call this method with $referenceType = ABSOLUTE_PATH - * but the route requires the https scheme whereas the current scheme is http, it will instead return an - * ABSOLUTE_URL with the https scheme and the current host. This makes sure the generated URL matches - * the route in any case. - * - * If there is no route with the given name, the generator must throw the RouteNotFoundException. - * - * The special parameter _fragment will be used as the document fragment suffixed to the final URL. - * - * @return string - * - * @throws RouteNotFoundException If the named route doesn't exist - * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route - * @throws InvalidParameterException When a parameter value for a placeholder is not correct because - * it does not match the requirement - */ - public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH); -} diff --git a/lib/symfony/routing/LICENSE b/lib/symfony/routing/LICENSE deleted file mode 100644 index 88bf75bb4..000000000 --- a/lib/symfony/routing/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-2022 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -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/lib/symfony/routing/Loader/AnnotationClassLoader.php b/lib/symfony/routing/Loader/AnnotationClassLoader.php deleted file mode 100644 index ad5af5c94..000000000 --- a/lib/symfony/routing/Loader/AnnotationClassLoader.php +++ /dev/null @@ -1,394 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Doctrine\Common\Annotations\Reader; -use Symfony\Component\Config\Loader\LoaderInterface; -use Symfony\Component\Config\Loader\LoaderResolverInterface; -use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\Routing\Annotation\Route as RouteAnnotation; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * AnnotationClassLoader loads routing information from a PHP class and its methods. - * - * You need to define an implementation for the configureRoute() method. Most of the - * time, this method should define some PHP callable to be called for the route - * (a controller in MVC speak). - * - * The @Route annotation can be set on the class (for global parameters), - * and on each method. - * - * The @Route annotation main value is the route path. The annotation also - * recognizes several parameters: requirements, options, defaults, schemes, - * methods, host, and name. The name parameter is mandatory. - * Here is an example of how you should be able to use it: - * /** - * * @Route("/Blog") - * * / - * class Blog - * { - * /** - * * @Route("/", name="blog_index") - * * / - * public function index() - * { - * } - * /** - * * @Route("/{id}", name="blog_post", requirements = {"id" = "\d+"}) - * * / - * public function show() - * { - * } - * } - * - * On PHP 8, the annotation class can be used as an attribute as well: - * #[Route('/Blog')] - * class Blog - * { - * #[Route('/', name: 'blog_index')] - * public function index() - * { - * } - * #[Route('/{id}', name: 'blog_post', requirements: ["id" => '\d+'])] - * public function show() - * { - * } - * } - - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Alexander M. Turek <me@derrabus.de> - */ -abstract class AnnotationClassLoader implements LoaderInterface -{ - protected $reader; - protected $env; - - /** - * @var string - */ - protected $routeAnnotationClass = RouteAnnotation::class; - - /** - * @var int - */ - protected $defaultRouteIndex = 0; - - public function __construct(Reader $reader = null, string $env = null) - { - $this->reader = $reader; - $this->env = $env; - } - - /** - * Sets the annotation class to read route properties from. - */ - public function setRouteAnnotationClass(string $class) - { - $this->routeAnnotationClass = $class; - } - - /** - * Loads from annotations from a class. - * - * @param string $class A class name - * - * @return RouteCollection - * - * @throws \InvalidArgumentException When route can't be parsed - */ - public function load($class, string $type = null) - { - if (!class_exists($class)) { - throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class)); - } - - $class = new \ReflectionClass($class); - if ($class->isAbstract()) { - throw new \InvalidArgumentException(sprintf('Annotations from class "%s" cannot be read as it is abstract.', $class->getName())); - } - - $globals = $this->getGlobals($class); - - $collection = new RouteCollection(); - $collection->addResource(new FileResource($class->getFileName())); - - if ($globals['env'] && $this->env !== $globals['env']) { - return $collection; - } - - foreach ($class->getMethods() as $method) { - $this->defaultRouteIndex = 0; - foreach ($this->getAnnotations($method) as $annot) { - $this->addRoute($collection, $annot, $globals, $class, $method); - } - } - - if (0 === $collection->count() && $class->hasMethod('__invoke')) { - $globals = $this->resetGlobals(); - foreach ($this->getAnnotations($class) as $annot) { - $this->addRoute($collection, $annot, $globals, $class, $class->getMethod('__invoke')); - } - } - - return $collection; - } - - /** - * @param RouteAnnotation $annot or an object that exposes a similar interface - */ - protected function addRoute(RouteCollection $collection, object $annot, array $globals, \ReflectionClass $class, \ReflectionMethod $method) - { - if ($annot->getEnv() && $annot->getEnv() !== $this->env) { - return; - } - - $name = $annot->getName(); - if (null === $name) { - $name = $this->getDefaultRouteName($class, $method); - } - $name = $globals['name'].$name; - - $requirements = $annot->getRequirements(); - - foreach ($requirements as $placeholder => $requirement) { - if (\is_int($placeholder)) { - throw new \InvalidArgumentException(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" of route "%s" in "%s::%s()"?', $placeholder, $requirement, $name, $class->getName(), $method->getName())); - } - } - - $defaults = array_replace($globals['defaults'], $annot->getDefaults()); - $requirements = array_replace($globals['requirements'], $requirements); - $options = array_replace($globals['options'], $annot->getOptions()); - $schemes = array_merge($globals['schemes'], $annot->getSchemes()); - $methods = array_merge($globals['methods'], $annot->getMethods()); - - $host = $annot->getHost(); - if (null === $host) { - $host = $globals['host']; - } - - $condition = $annot->getCondition() ?? $globals['condition']; - $priority = $annot->getPriority() ?? $globals['priority']; - - $path = $annot->getLocalizedPaths() ?: $annot->getPath(); - $prefix = $globals['localized_paths'] ?: $globals['path']; - $paths = []; - - if (\is_array($path)) { - if (!\is_array($prefix)) { - foreach ($path as $locale => $localePath) { - $paths[$locale] = $prefix.$localePath; - } - } elseif ($missing = array_diff_key($prefix, $path)) { - throw new \LogicException(sprintf('Route to "%s" is missing paths for locale(s) "%s".', $class->name.'::'.$method->name, implode('", "', array_keys($missing)))); - } else { - foreach ($path as $locale => $localePath) { - if (!isset($prefix[$locale])) { - throw new \LogicException(sprintf('Route to "%s" with locale "%s" is missing a corresponding prefix in class "%s".', $method->name, $locale, $class->name)); - } - - $paths[$locale] = $prefix[$locale].$localePath; - } - } - } elseif (\is_array($prefix)) { - foreach ($prefix as $locale => $localePrefix) { - $paths[$locale] = $localePrefix.$path; - } - } else { - $paths[] = $prefix.$path; - } - - foreach ($method->getParameters() as $param) { - if (isset($defaults[$param->name]) || !$param->isDefaultValueAvailable()) { - continue; - } - foreach ($paths as $locale => $path) { - if (preg_match(sprintf('/\{%s(?:<.*?>)?\}/', preg_quote($param->name)), $path)) { - $defaults[$param->name] = $param->getDefaultValue(); - break; - } - } - } - - foreach ($paths as $locale => $path) { - $route = $this->createRoute($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition); - $this->configureRoute($route, $class, $method, $annot); - if (0 !== $locale) { - $route->setDefault('_locale', $locale); - $route->setRequirement('_locale', preg_quote($locale)); - $route->setDefault('_canonical_route', $name); - $collection->add($name.'.'.$locale, $route, $priority); - } else { - $collection->add($name, $route, $priority); - } - } - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - return \is_string($resource) && preg_match('/^(?:\\\\?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)+$/', $resource) && (!$type || 'annotation' === $type); - } - - /** - * {@inheritdoc} - */ - public function setResolver(LoaderResolverInterface $resolver) - { - } - - /** - * {@inheritdoc} - */ - public function getResolver() - { - } - - /** - * Gets the default route name for a class method. - * - * @return string - */ - protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method) - { - $name = str_replace('\\', '_', $class->name).'_'.$method->name; - $name = \function_exists('mb_strtolower') && preg_match('//u', $name) ? mb_strtolower($name, 'UTF-8') : strtolower($name); - if ($this->defaultRouteIndex > 0) { - $name .= '_'.$this->defaultRouteIndex; - } - ++$this->defaultRouteIndex; - - return $name; - } - - protected function getGlobals(\ReflectionClass $class) - { - $globals = $this->resetGlobals(); - - $annot = null; - if (\PHP_VERSION_ID >= 80000 && ($attribute = $class->getAttributes($this->routeAnnotationClass, \ReflectionAttribute::IS_INSTANCEOF)[0] ?? null)) { - $annot = $attribute->newInstance(); - } - if (!$annot && $this->reader) { - $annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass); - } - - if ($annot) { - if (null !== $annot->getName()) { - $globals['name'] = $annot->getName(); - } - - if (null !== $annot->getPath()) { - $globals['path'] = $annot->getPath(); - } - - $globals['localized_paths'] = $annot->getLocalizedPaths(); - - if (null !== $annot->getRequirements()) { - $globals['requirements'] = $annot->getRequirements(); - } - - if (null !== $annot->getOptions()) { - $globals['options'] = $annot->getOptions(); - } - - if (null !== $annot->getDefaults()) { - $globals['defaults'] = $annot->getDefaults(); - } - - if (null !== $annot->getSchemes()) { - $globals['schemes'] = $annot->getSchemes(); - } - - if (null !== $annot->getMethods()) { - $globals['methods'] = $annot->getMethods(); - } - - if (null !== $annot->getHost()) { - $globals['host'] = $annot->getHost(); - } - - if (null !== $annot->getCondition()) { - $globals['condition'] = $annot->getCondition(); - } - - $globals['priority'] = $annot->getPriority() ?? 0; - $globals['env'] = $annot->getEnv(); - - foreach ($globals['requirements'] as $placeholder => $requirement) { - if (\is_int($placeholder)) { - throw new \InvalidArgumentException(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" in "%s"?', $placeholder, $requirement, $class->getName())); - } - } - } - - return $globals; - } - - private function resetGlobals(): array - { - return [ - 'path' => null, - 'localized_paths' => [], - 'requirements' => [], - 'options' => [], - 'defaults' => [], - 'schemes' => [], - 'methods' => [], - 'host' => '', - 'condition' => '', - 'name' => '', - 'priority' => 0, - 'env' => null, - ]; - } - - protected function createRoute(string $path, array $defaults, array $requirements, array $options, ?string $host, array $schemes, array $methods, ?string $condition) - { - return new Route($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition); - } - - abstract protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, object $annot); - - /** - * @param \ReflectionClass|\ReflectionMethod $reflection - * - * @return iterable<int, RouteAnnotation> - */ - private function getAnnotations(object $reflection): iterable - { - if (\PHP_VERSION_ID >= 80000) { - foreach ($reflection->getAttributes($this->routeAnnotationClass, \ReflectionAttribute::IS_INSTANCEOF) as $attribute) { - yield $attribute->newInstance(); - } - } - - if (!$this->reader) { - return; - } - - $anntotations = $reflection instanceof \ReflectionClass - ? $this->reader->getClassAnnotations($reflection) - : $this->reader->getMethodAnnotations($reflection); - - foreach ($anntotations as $annotation) { - if ($annotation instanceof $this->routeAnnotationClass) { - yield $annotation; - } - } - } -} diff --git a/lib/symfony/routing/Loader/AnnotationDirectoryLoader.php b/lib/symfony/routing/Loader/AnnotationDirectoryLoader.php deleted file mode 100644 index ae825a39f..000000000 --- a/lib/symfony/routing/Loader/AnnotationDirectoryLoader.php +++ /dev/null @@ -1,93 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Resource\DirectoryResource; -use Symfony\Component\Routing\RouteCollection; - -/** - * AnnotationDirectoryLoader loads routing information from annotations set - * on PHP classes and methods. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class AnnotationDirectoryLoader extends AnnotationFileLoader -{ - /** - * Loads from annotations from a directory. - * - * @param string $path A directory path - * @param string|null $type The resource type - * - * @return RouteCollection - * - * @throws \InvalidArgumentException When the directory does not exist or its routes cannot be parsed - */ - public function load($path, string $type = null) - { - if (!is_dir($dir = $this->locator->locate($path))) { - return parent::supports($path, $type) ? parent::load($path, $type) : new RouteCollection(); - } - - $collection = new RouteCollection(); - $collection->addResource(new DirectoryResource($dir, '/\.php$/')); - $files = iterator_to_array(new \RecursiveIteratorIterator( - new \RecursiveCallbackFilterIterator( - new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS), - function (\SplFileInfo $current) { - return '.' !== substr($current->getBasename(), 0, 1); - } - ), - \RecursiveIteratorIterator::LEAVES_ONLY - )); - usort($files, function (\SplFileInfo $a, \SplFileInfo $b) { - return (string) $a > (string) $b ? 1 : -1; - }); - - foreach ($files as $file) { - if (!$file->isFile() || !str_ends_with($file->getFilename(), '.php')) { - continue; - } - - if ($class = $this->findClass($file)) { - $refl = new \ReflectionClass($class); - if ($refl->isAbstract()) { - continue; - } - - $collection->addCollection($this->loader->load($class, $type)); - } - } - - return $collection; - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - if ('annotation' === $type) { - return true; - } - - if ($type || !\is_string($resource)) { - return false; - } - - try { - return is_dir($this->locator->locate($resource)); - } catch (\Exception $e) { - return false; - } - } -} diff --git a/lib/symfony/routing/Loader/AnnotationFileLoader.php b/lib/symfony/routing/Loader/AnnotationFileLoader.php deleted file mode 100644 index 27af66ee6..000000000 --- a/lib/symfony/routing/Loader/AnnotationFileLoader.php +++ /dev/null @@ -1,146 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\FileLocatorInterface; -use Symfony\Component\Config\Loader\FileLoader; -use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\Routing\RouteCollection; - -/** - * AnnotationFileLoader loads routing information from annotations set - * on a PHP class and its methods. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class AnnotationFileLoader extends FileLoader -{ - protected $loader; - - public function __construct(FileLocatorInterface $locator, AnnotationClassLoader $loader) - { - if (!\function_exists('token_get_all')) { - throw new \LogicException('The Tokenizer extension is required for the routing annotation loaders.'); - } - - parent::__construct($locator); - - $this->loader = $loader; - } - - /** - * Loads from annotations from a file. - * - * @param string $file A PHP file path - * @param string|null $type The resource type - * - * @return RouteCollection|null - * - * @throws \InvalidArgumentException When the file does not exist or its routes cannot be parsed - */ - public function load($file, string $type = null) - { - $path = $this->locator->locate($file); - - $collection = new RouteCollection(); - if ($class = $this->findClass($path)) { - $refl = new \ReflectionClass($class); - if ($refl->isAbstract()) { - return null; - } - - $collection->addResource(new FileResource($path)); - $collection->addCollection($this->loader->load($class, $type)); - } - - gc_mem_caches(); - - return $collection; - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - return \is_string($resource) && 'php' === pathinfo($resource, \PATHINFO_EXTENSION) && (!$type || 'annotation' === $type); - } - - /** - * Returns the full class name for the first class in the file. - * - * @return string|false - */ - protected function findClass(string $file) - { - $class = false; - $namespace = false; - $tokens = token_get_all(file_get_contents($file)); - - if (1 === \count($tokens) && \T_INLINE_HTML === $tokens[0][0]) { - throw new \InvalidArgumentException(sprintf('The file "%s" does not contain PHP code. Did you forgot to add the "<?php" start tag at the beginning of the file?', $file)); - } - - $nsTokens = [\T_NS_SEPARATOR => true, \T_STRING => true]; - if (\defined('T_NAME_QUALIFIED')) { - $nsTokens[\T_NAME_QUALIFIED] = true; - } - for ($i = 0; isset($tokens[$i]); ++$i) { - $token = $tokens[$i]; - if (!isset($token[1])) { - continue; - } - - if (true === $class && \T_STRING === $token[0]) { - return $namespace.'\\'.$token[1]; - } - - if (true === $namespace && isset($nsTokens[$token[0]])) { - $namespace = $token[1]; - while (isset($tokens[++$i][1], $nsTokens[$tokens[$i][0]])) { - $namespace .= $tokens[$i][1]; - } - $token = $tokens[$i]; - } - - if (\T_CLASS === $token[0]) { - // Skip usage of ::class constant and anonymous classes - $skipClassToken = false; - for ($j = $i - 1; $j > 0; --$j) { - if (!isset($tokens[$j][1])) { - if ('(' === $tokens[$j] || ',' === $tokens[$j]) { - $skipClassToken = true; - } - break; - } - - if (\T_DOUBLE_COLON === $tokens[$j][0] || \T_NEW === $tokens[$j][0]) { - $skipClassToken = true; - break; - } elseif (!\in_array($tokens[$j][0], [\T_WHITESPACE, \T_DOC_COMMENT, \T_COMMENT])) { - break; - } - } - - if (!$skipClassToken) { - $class = true; - } - } - - if (\T_NAMESPACE === $token[0]) { - $namespace = true; - } - } - - return false; - } -} diff --git a/lib/symfony/routing/Loader/ClosureLoader.php b/lib/symfony/routing/Loader/ClosureLoader.php deleted file mode 100644 index 42f950f50..000000000 --- a/lib/symfony/routing/Loader/ClosureLoader.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Loader\Loader; -use Symfony\Component\Routing\RouteCollection; - -/** - * ClosureLoader loads routes from a PHP closure. - * - * The Closure must return a RouteCollection instance. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class ClosureLoader extends Loader -{ - /** - * Loads a Closure. - * - * @param \Closure $closure A Closure - * @param string|null $type The resource type - * - * @return RouteCollection - */ - public function load($closure, string $type = null) - { - return $closure($this->env); - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - return $resource instanceof \Closure && (!$type || 'closure' === $type); - } -} diff --git a/lib/symfony/routing/Loader/Configurator/AliasConfigurator.php b/lib/symfony/routing/Loader/Configurator/AliasConfigurator.php deleted file mode 100644 index 4b2206e68..000000000 --- a/lib/symfony/routing/Loader/Configurator/AliasConfigurator.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\Routing\Alias; - -class AliasConfigurator -{ - private $alias; - - public function __construct(Alias $alias) - { - $this->alias = $alias; - } - - /** - * Whether this alias is deprecated, that means it should not be called anymore. - * - * @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 deprecation message to use - * - * @return $this - * - * @throws InvalidArgumentException when the message template is invalid - */ - public function deprecate(string $package, string $version, string $message): self - { - $this->alias->setDeprecated($package, $version, $message); - - return $this; - } -} diff --git a/lib/symfony/routing/Loader/Configurator/CollectionConfigurator.php b/lib/symfony/routing/Loader/Configurator/CollectionConfigurator.php deleted file mode 100644 index 09274ccdc..000000000 --- a/lib/symfony/routing/Loader/Configurator/CollectionConfigurator.php +++ /dev/null @@ -1,125 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator; - -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class CollectionConfigurator -{ - use Traits\AddTrait; - use Traits\HostTrait; - use Traits\RouteTrait; - - private $parent; - private $parentConfigurator; - private $parentPrefixes; - private $host; - - public function __construct(RouteCollection $parent, string $name, self $parentConfigurator = null, array $parentPrefixes = null) - { - $this->parent = $parent; - $this->name = $name; - $this->collection = new RouteCollection(); - $this->route = new Route(''); - $this->parentConfigurator = $parentConfigurator; // for GC control - $this->parentPrefixes = $parentPrefixes; - } - - /** - * @return array - */ - public function __sleep() - { - throw new \BadMethodCallException('Cannot serialize '.__CLASS__); - } - - public function __wakeup() - { - throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); - } - - public function __destruct() - { - if (null === $this->prefixes) { - $this->collection->addPrefix($this->route->getPath()); - } - if (null !== $this->host) { - $this->addHost($this->collection, $this->host); - } - - $this->parent->addCollection($this->collection); - } - - /** - * Creates a sub-collection. - */ - final public function collection(string $name = ''): self - { - return new self($this->collection, $this->name.$name, $this, $this->prefixes); - } - - /** - * Sets the prefix to add to the path of all child routes. - * - * @param string|array $prefix the prefix, or the localized prefixes - * - * @return $this - */ - final public function prefix($prefix): self - { - if (\is_array($prefix)) { - if (null === $this->parentPrefixes) { - // no-op - } elseif ($missing = array_diff_key($this->parentPrefixes, $prefix)) { - throw new \LogicException(sprintf('Collection "%s" is missing prefixes for locale(s) "%s".', $this->name, implode('", "', array_keys($missing)))); - } else { - foreach ($prefix as $locale => $localePrefix) { - if (!isset($this->parentPrefixes[$locale])) { - throw new \LogicException(sprintf('Collection "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $this->name, $locale)); - } - - $prefix[$locale] = $this->parentPrefixes[$locale].$localePrefix; - } - } - $this->prefixes = $prefix; - $this->route->setPath('/'); - } else { - $this->prefixes = null; - $this->route->setPath($prefix); - } - - return $this; - } - - /** - * Sets the host to use for all child routes. - * - * @param string|array $host the host, or the localized hosts - * - * @return $this - */ - final public function host($host): self - { - $this->host = $host; - - return $this; - } - - private function createRoute(string $path): Route - { - return (clone $this->route)->setPath($path); - } -} diff --git a/lib/symfony/routing/Loader/Configurator/ImportConfigurator.php b/lib/symfony/routing/Loader/Configurator/ImportConfigurator.php deleted file mode 100644 index 32f3efe3a..000000000 --- a/lib/symfony/routing/Loader/Configurator/ImportConfigurator.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator; - -use Symfony\Component\Routing\RouteCollection; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class ImportConfigurator -{ - use Traits\HostTrait; - use Traits\PrefixTrait; - use Traits\RouteTrait; - - private $parent; - - public function __construct(RouteCollection $parent, RouteCollection $route) - { - $this->parent = $parent; - $this->route = $route; - } - - /** - * @return array - */ - public function __sleep() - { - throw new \BadMethodCallException('Cannot serialize '.__CLASS__); - } - - public function __wakeup() - { - throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); - } - - public function __destruct() - { - $this->parent->addCollection($this->route); - } - - /** - * Sets the prefix to add to the path of all child routes. - * - * @param string|array $prefix the prefix, or the localized prefixes - * - * @return $this - */ - final public function prefix($prefix, bool $trailingSlashOnRoot = true): self - { - $this->addPrefix($this->route, $prefix, $trailingSlashOnRoot); - - return $this; - } - - /** - * Sets the prefix to add to the name of all child routes. - * - * @return $this - */ - final public function namePrefix(string $namePrefix): self - { - $this->route->addNamePrefix($namePrefix); - - return $this; - } - - /** - * Sets the host to use for all child routes. - * - * @param string|array $host the host, or the localized hosts - * - * @return $this - */ - final public function host($host): self - { - $this->addHost($this->route, $host); - - return $this; - } -} diff --git a/lib/symfony/routing/Loader/Configurator/RouteConfigurator.php b/lib/symfony/routing/Loader/Configurator/RouteConfigurator.php deleted file mode 100644 index bb6ce267a..000000000 --- a/lib/symfony/routing/Loader/Configurator/RouteConfigurator.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator; - -use Symfony\Component\Routing\RouteCollection; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class RouteConfigurator -{ - use Traits\AddTrait; - use Traits\HostTrait; - use Traits\RouteTrait; - - protected $parentConfigurator; - - public function __construct(RouteCollection $collection, RouteCollection $route, string $name = '', CollectionConfigurator $parentConfigurator = null, array $prefixes = null) - { - $this->collection = $collection; - $this->route = $route; - $this->name = $name; - $this->parentConfigurator = $parentConfigurator; // for GC control - $this->prefixes = $prefixes; - } - - /** - * Sets the host to use for all child routes. - * - * @param string|array $host the host, or the localized hosts - * - * @return $this - */ - final public function host($host): self - { - $this->addHost($this->route, $host); - - return $this; - } -} diff --git a/lib/symfony/routing/Loader/Configurator/RoutingConfigurator.php b/lib/symfony/routing/Loader/Configurator/RoutingConfigurator.php deleted file mode 100644 index 4687bf681..000000000 --- a/lib/symfony/routing/Loader/Configurator/RoutingConfigurator.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator; - -use Symfony\Component\Routing\Loader\PhpFileLoader; -use Symfony\Component\Routing\RouteCollection; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class RoutingConfigurator -{ - use Traits\AddTrait; - - private $loader; - private $path; - private $file; - private $env; - - public function __construct(RouteCollection $collection, PhpFileLoader $loader, string $path, string $file, string $env = null) - { - $this->collection = $collection; - $this->loader = $loader; - $this->path = $path; - $this->file = $file; - $this->env = $env; - } - - /** - * @param string|string[]|null $exclude Glob patterns to exclude from the import - */ - final public function import($resource, string $type = null, bool $ignoreErrors = false, $exclude = null): ImportConfigurator - { - $this->loader->setCurrentDir(\dirname($this->path)); - - $imported = $this->loader->import($resource, $type, $ignoreErrors, $this->file, $exclude) ?: []; - if (!\is_array($imported)) { - return new ImportConfigurator($this->collection, $imported); - } - - $mergedCollection = new RouteCollection(); - foreach ($imported as $subCollection) { - $mergedCollection->addCollection($subCollection); - } - - return new ImportConfigurator($this->collection, $mergedCollection); - } - - final public function collection(string $name = ''): CollectionConfigurator - { - return new CollectionConfigurator($this->collection, $name); - } - - /** - * Get the current environment to be able to write conditional configuration. - */ - final public function env(): ?string - { - return $this->env; - } - - /** - * @return static - */ - final public function withPath(string $path): self - { - $clone = clone $this; - $clone->path = $clone->file = $path; - - return $clone; - } -} diff --git a/lib/symfony/routing/Loader/Configurator/Traits/AddTrait.php b/lib/symfony/routing/Loader/Configurator/Traits/AddTrait.php deleted file mode 100644 index 92b1bd0ea..000000000 --- a/lib/symfony/routing/Loader/Configurator/Traits/AddTrait.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator\Traits; - -use Symfony\Component\Routing\Loader\Configurator\AliasConfigurator; -use Symfony\Component\Routing\Loader\Configurator\CollectionConfigurator; -use Symfony\Component\Routing\Loader\Configurator\RouteConfigurator; -use Symfony\Component\Routing\RouteCollection; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -trait AddTrait -{ - use LocalizedRouteTrait; - - /** - * @var RouteCollection - */ - protected $collection; - protected $name = ''; - protected $prefixes; - - /** - * Adds a route. - * - * @param string|array $path the path, or the localized paths of the route - */ - public function add(string $name, $path): RouteConfigurator - { - $parentConfigurator = $this instanceof CollectionConfigurator ? $this : ($this instanceof RouteConfigurator ? $this->parentConfigurator : null); - $route = $this->createLocalizedRoute($this->collection, $name, $path, $this->name, $this->prefixes); - - return new RouteConfigurator($this->collection, $route, $this->name, $parentConfigurator, $this->prefixes); - } - - public function alias(string $name, string $alias): AliasConfigurator - { - return new AliasConfigurator($this->collection->addAlias($name, $alias)); - } - - /** - * Adds a route. - * - * @param string|array $path the path, or the localized paths of the route - */ - public function __invoke(string $name, $path): RouteConfigurator - { - return $this->add($name, $path); - } -} diff --git a/lib/symfony/routing/Loader/Configurator/Traits/HostTrait.php b/lib/symfony/routing/Loader/Configurator/Traits/HostTrait.php deleted file mode 100644 index 54ae6566a..000000000 --- a/lib/symfony/routing/Loader/Configurator/Traits/HostTrait.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator\Traits; - -use Symfony\Component\Routing\RouteCollection; - -/** - * @internal - */ -trait HostTrait -{ - final protected function addHost(RouteCollection $routes, $hosts) - { - if (!$hosts || !\is_array($hosts)) { - $routes->setHost($hosts ?: ''); - - return; - } - - foreach ($routes->all() as $name => $route) { - if (null === $locale = $route->getDefault('_locale')) { - $routes->remove($name); - foreach ($hosts as $locale => $host) { - $localizedRoute = clone $route; - $localizedRoute->setDefault('_locale', $locale); - $localizedRoute->setRequirement('_locale', preg_quote($locale)); - $localizedRoute->setDefault('_canonical_route', $name); - $localizedRoute->setHost($host); - $routes->add($name.'.'.$locale, $localizedRoute); - } - } elseif (!isset($hosts[$locale])) { - throw new \InvalidArgumentException(sprintf('Route "%s" with locale "%s" is missing a corresponding host in its parent collection.', $name, $locale)); - } else { - $route->setHost($hosts[$locale]); - $route->setRequirement('_locale', preg_quote($locale)); - $routes->add($name, $route); - } - } - } -} diff --git a/lib/symfony/routing/Loader/Configurator/Traits/LocalizedRouteTrait.php b/lib/symfony/routing/Loader/Configurator/Traits/LocalizedRouteTrait.php deleted file mode 100644 index 4734a4eac..000000000 --- a/lib/symfony/routing/Loader/Configurator/Traits/LocalizedRouteTrait.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator\Traits; - -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * @internal - * - * @author Nicolas Grekas <p@tchwork.com> - * @author Jules Pietri <jules@heahprod.com> - */ -trait LocalizedRouteTrait -{ - /** - * Creates one or many routes. - * - * @param string|array $path the path, or the localized paths of the route - */ - final protected function createLocalizedRoute(RouteCollection $collection, string $name, $path, string $namePrefix = '', array $prefixes = null): RouteCollection - { - $paths = []; - - $routes = new RouteCollection(); - - if (\is_array($path)) { - if (null === $prefixes) { - $paths = $path; - } elseif ($missing = array_diff_key($prefixes, $path)) { - throw new \LogicException(sprintf('Route "%s" is missing routes for locale(s) "%s".', $name, implode('", "', array_keys($missing)))); - } else { - foreach ($path as $locale => $localePath) { - if (!isset($prefixes[$locale])) { - throw new \LogicException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $name, $locale)); - } - - $paths[$locale] = $prefixes[$locale].$localePath; - } - } - } elseif (null !== $prefixes) { - foreach ($prefixes as $locale => $prefix) { - $paths[$locale] = $prefix.$path; - } - } else { - $routes->add($namePrefix.$name, $route = $this->createRoute($path)); - $collection->add($namePrefix.$name, $route); - - return $routes; - } - - foreach ($paths as $locale => $path) { - $routes->add($name.'.'.$locale, $route = $this->createRoute($path)); - $collection->add($namePrefix.$name.'.'.$locale, $route); - $route->setDefault('_locale', $locale); - $route->setRequirement('_locale', preg_quote($locale)); - $route->setDefault('_canonical_route', $namePrefix.$name); - } - - return $routes; - } - - private function createRoute(string $path): Route - { - return new Route($path); - } -} diff --git a/lib/symfony/routing/Loader/Configurator/Traits/PrefixTrait.php b/lib/symfony/routing/Loader/Configurator/Traits/PrefixTrait.php deleted file mode 100644 index 27053bcaf..000000000 --- a/lib/symfony/routing/Loader/Configurator/Traits/PrefixTrait.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator\Traits; - -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * @internal - * - * @author Nicolas Grekas <p@tchwork.com> - */ -trait PrefixTrait -{ - final protected function addPrefix(RouteCollection $routes, $prefix, bool $trailingSlashOnRoot) - { - if (\is_array($prefix)) { - foreach ($prefix as $locale => $localePrefix) { - $prefix[$locale] = trim(trim($localePrefix), '/'); - } - foreach ($routes->all() as $name => $route) { - if (null === $locale = $route->getDefault('_locale')) { - $routes->remove($name); - foreach ($prefix as $locale => $localePrefix) { - $localizedRoute = clone $route; - $localizedRoute->setDefault('_locale', $locale); - $localizedRoute->setRequirement('_locale', preg_quote($locale)); - $localizedRoute->setDefault('_canonical_route', $name); - $localizedRoute->setPath($localePrefix.(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath())); - $routes->add($name.'.'.$locale, $localizedRoute); - } - } elseif (!isset($prefix[$locale])) { - throw new \InvalidArgumentException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $name, $locale)); - } else { - $route->setPath($prefix[$locale].(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath())); - $routes->add($name, $route); - } - } - - return; - } - - $routes->addPrefix($prefix); - if (!$trailingSlashOnRoot) { - $rootPath = (new Route(trim(trim($prefix), '/').'/'))->getPath(); - foreach ($routes->all() as $route) { - if ($route->getPath() === $rootPath) { - $route->setPath(rtrim($rootPath, '/')); - } - } - } - } -} diff --git a/lib/symfony/routing/Loader/Configurator/Traits/RouteTrait.php b/lib/symfony/routing/Loader/Configurator/Traits/RouteTrait.php deleted file mode 100644 index ac05d10e5..000000000 --- a/lib/symfony/routing/Loader/Configurator/Traits/RouteTrait.php +++ /dev/null @@ -1,175 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator\Traits; - -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -trait RouteTrait -{ - /** - * @var RouteCollection|Route - */ - protected $route; - - /** - * Adds defaults. - * - * @return $this - */ - final public function defaults(array $defaults): self - { - $this->route->addDefaults($defaults); - - return $this; - } - - /** - * Adds requirements. - * - * @return $this - */ - final public function requirements(array $requirements): self - { - $this->route->addRequirements($requirements); - - return $this; - } - - /** - * Adds options. - * - * @return $this - */ - final public function options(array $options): self - { - $this->route->addOptions($options); - - return $this; - } - - /** - * Whether paths should accept utf8 encoding. - * - * @return $this - */ - final public function utf8(bool $utf8 = true): self - { - $this->route->addOptions(['utf8' => $utf8]); - - return $this; - } - - /** - * Sets the condition. - * - * @return $this - */ - final public function condition(string $condition): self - { - $this->route->setCondition($condition); - - return $this; - } - - /** - * Sets the pattern for the host. - * - * @return $this - */ - final public function host(string $pattern): self - { - $this->route->setHost($pattern); - - return $this; - } - - /** - * Sets the schemes (e.g. 'https') this route is restricted to. - * So an empty array means that any scheme is allowed. - * - * @param string[] $schemes - * - * @return $this - */ - final public function schemes(array $schemes): self - { - $this->route->setSchemes($schemes); - - return $this; - } - - /** - * Sets the HTTP methods (e.g. 'POST') this route is restricted to. - * So an empty array means that any method is allowed. - * - * @param string[] $methods - * - * @return $this - */ - final public function methods(array $methods): self - { - $this->route->setMethods($methods); - - return $this; - } - - /** - * Adds the "_controller" entry to defaults. - * - * @param callable|string|array $controller a callable or parseable pseudo-callable - * - * @return $this - */ - final public function controller($controller): self - { - $this->route->addDefaults(['_controller' => $controller]); - - return $this; - } - - /** - * Adds the "_locale" entry to defaults. - * - * @return $this - */ - final public function locale(string $locale): self - { - $this->route->addDefaults(['_locale' => $locale]); - - return $this; - } - - /** - * Adds the "_format" entry to defaults. - * - * @return $this - */ - final public function format(string $format): self - { - $this->route->addDefaults(['_format' => $format]); - - return $this; - } - - /** - * Adds the "_stateless" entry to defaults. - * - * @return $this - */ - final public function stateless(bool $stateless = true): self - { - $this->route->addDefaults(['_stateless' => $stateless]); - - return $this; - } -} diff --git a/lib/symfony/routing/Loader/ContainerLoader.php b/lib/symfony/routing/Loader/ContainerLoader.php deleted file mode 100644 index d8730aec6..000000000 --- a/lib/symfony/routing/Loader/ContainerLoader.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Psr\Container\ContainerInterface; - -/** - * A route loader that executes a service from a PSR-11 container to load the routes. - * - * @author Ryan Weaver <ryan@knpuniversity.com> - */ -class ContainerLoader extends ObjectLoader -{ - private $container; - - public function __construct(ContainerInterface $container, string $env = null) - { - $this->container = $container; - parent::__construct($env); - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - return 'service' === $type && \is_string($resource); - } - - /** - * {@inheritdoc} - */ - protected function getObject(string $id) - { - return $this->container->get($id); - } -} diff --git a/lib/symfony/routing/Loader/DirectoryLoader.php b/lib/symfony/routing/Loader/DirectoryLoader.php deleted file mode 100644 index c0f349177..000000000 --- a/lib/symfony/routing/Loader/DirectoryLoader.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Loader\FileLoader; -use Symfony\Component\Config\Resource\DirectoryResource; -use Symfony\Component\Routing\RouteCollection; - -class DirectoryLoader extends FileLoader -{ - /** - * {@inheritdoc} - */ - public function load($file, string $type = null) - { - $path = $this->locator->locate($file); - - $collection = new RouteCollection(); - $collection->addResource(new DirectoryResource($path)); - - foreach (scandir($path) as $dir) { - if ('.' !== $dir[0]) { - $this->setCurrentDir($path); - $subPath = $path.'/'.$dir; - $subType = null; - - if (is_dir($subPath)) { - $subPath .= '/'; - $subType = 'directory'; - } - - $subCollection = $this->import($subPath, $subType, false, $path); - $collection->addCollection($subCollection); - } - } - - return $collection; - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - // only when type is forced to directory, not to conflict with AnnotationLoader - - return 'directory' === $type; - } -} diff --git a/lib/symfony/routing/Loader/GlobFileLoader.php b/lib/symfony/routing/Loader/GlobFileLoader.php deleted file mode 100644 index 780fb15dc..000000000 --- a/lib/symfony/routing/Loader/GlobFileLoader.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Loader\FileLoader; -use Symfony\Component\Routing\RouteCollection; - -/** - * GlobFileLoader loads files from a glob pattern. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class GlobFileLoader extends FileLoader -{ - /** - * {@inheritdoc} - */ - public function load($resource, string $type = null) - { - $collection = new RouteCollection(); - - foreach ($this->glob($resource, false, $globResource) as $path => $info) { - $collection->addCollection($this->import($path)); - } - - $collection->addResource($globResource); - - return $collection; - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - return 'glob' === $type; - } -} diff --git a/lib/symfony/routing/Loader/ObjectLoader.php b/lib/symfony/routing/Loader/ObjectLoader.php deleted file mode 100644 index 062453908..000000000 --- a/lib/symfony/routing/Loader/ObjectLoader.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Loader\Loader; -use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\Routing\RouteCollection; - -/** - * A route loader that calls a method on an object to load the routes. - * - * @author Ryan Weaver <ryan@knpuniversity.com> - */ -abstract class ObjectLoader extends Loader -{ - /** - * Returns the object that the method will be called on to load routes. - * - * For example, if your application uses a service container, - * the $id may be a service id. - * - * @return object - */ - abstract protected function getObject(string $id); - - /** - * Calls the object method that will load the routes. - * - * @param string $resource object_id::method - * @param string|null $type The resource type - * - * @return RouteCollection - */ - public function load($resource, string $type = null) - { - if (!preg_match('/^[^\:]+(?:::(?:[^\:]+))?$/', $resource)) { - throw new \InvalidArgumentException(sprintf('Invalid resource "%s" passed to the %s route loader: use the format "object_id::method" or "object_id" if your object class has an "__invoke" method.', $resource, \is_string($type) ? '"'.$type.'"' : 'object')); - } - - $parts = explode('::', $resource); - $method = $parts[1] ?? '__invoke'; - - $loaderObject = $this->getObject($parts[0]); - - if (!\is_object($loaderObject)) { - throw new \TypeError(sprintf('"%s:getObject()" must return an object: "%s" returned.', static::class, get_debug_type($loaderObject))); - } - - if (!\is_callable([$loaderObject, $method])) { - throw new \BadMethodCallException(sprintf('Method "%s" not found on "%s" when importing routing resource "%s".', $method, get_debug_type($loaderObject), $resource)); - } - - $routeCollection = $loaderObject->$method($this, $this->env); - - if (!$routeCollection instanceof RouteCollection) { - $type = get_debug_type($routeCollection); - - throw new \LogicException(sprintf('The "%s::%s()" method must return a RouteCollection: "%s" returned.', get_debug_type($loaderObject), $method, $type)); - } - - // make the object file tracked so that if it changes, the cache rebuilds - $this->addClassResource(new \ReflectionClass($loaderObject), $routeCollection); - - return $routeCollection; - } - - private function addClassResource(\ReflectionClass $class, RouteCollection $collection) - { - do { - if (is_file($class->getFileName())) { - $collection->addResource(new FileResource($class->getFileName())); - } - } while ($class = $class->getParentClass()); - } -} diff --git a/lib/symfony/routing/Loader/PhpFileLoader.php b/lib/symfony/routing/Loader/PhpFileLoader.php deleted file mode 100644 index 39ac81273..000000000 --- a/lib/symfony/routing/Loader/PhpFileLoader.php +++ /dev/null @@ -1,85 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Loader\FileLoader; -use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; -use Symfony\Component\Routing\RouteCollection; - -/** - * PhpFileLoader loads routes from a PHP file. - * - * The file must return a RouteCollection instance. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Nicolas grekas <p@tchwork.com> - * @author Jules Pietri <jules@heahprod.com> - */ -class PhpFileLoader extends FileLoader -{ - /** - * Loads a PHP file. - * - * @param string $file A PHP file path - * @param string|null $type The resource type - * - * @return RouteCollection - */ - public function load($file, string $type = null) - { - $path = $this->locator->locate($file); - $this->setCurrentDir(\dirname($path)); - - // the closure forbids access to the private scope in the included file - $loader = $this; - $load = \Closure::bind(static function ($file) use ($loader) { - return include $file; - }, null, ProtectedPhpFileLoader::class); - - $result = $load($path); - - if (\is_object($result) && \is_callable($result)) { - $collection = $this->callConfigurator($result, $path, $file); - } else { - $collection = $result; - } - - $collection->addResource(new FileResource($path)); - - return $collection; - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - return \is_string($resource) && 'php' === pathinfo($resource, \PATHINFO_EXTENSION) && (!$type || 'php' === $type); - } - - protected function callConfigurator(callable $result, string $path, string $file): RouteCollection - { - $collection = new RouteCollection(); - - $result(new RoutingConfigurator($collection, $this, $path, $file, $this->env)); - - return $collection; - } -} - -/** - * @internal - */ -final class ProtectedPhpFileLoader extends PhpFileLoader -{ -} diff --git a/lib/symfony/routing/Loader/XmlFileLoader.php b/lib/symfony/routing/Loader/XmlFileLoader.php deleted file mode 100644 index 220153364..000000000 --- a/lib/symfony/routing/Loader/XmlFileLoader.php +++ /dev/null @@ -1,469 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Loader\FileLoader; -use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\Config\Util\XmlUtils; -use Symfony\Component\Routing\Loader\Configurator\Traits\HostTrait; -use Symfony\Component\Routing\Loader\Configurator\Traits\LocalizedRouteTrait; -use Symfony\Component\Routing\Loader\Configurator\Traits\PrefixTrait; -use Symfony\Component\Routing\RouteCollection; - -/** - * XmlFileLoader loads XML routing files. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Tobias Schultze <http://tobion.de> - */ -class XmlFileLoader extends FileLoader -{ - use HostTrait; - use LocalizedRouteTrait; - use PrefixTrait; - - public const NAMESPACE_URI = 'http://symfony.com/schema/routing'; - public const SCHEME_PATH = '/schema/routing/routing-1.0.xsd'; - - /** - * Loads an XML file. - * - * @param string $file An XML file path - * @param string|null $type The resource type - * - * @return RouteCollection - * - * @throws \InvalidArgumentException when the file cannot be loaded or when the XML cannot be - * parsed because it does not validate against the scheme - */ - public function load($file, string $type = null) - { - $path = $this->locator->locate($file); - - $xml = $this->loadFile($path); - - $collection = new RouteCollection(); - $collection->addResource(new FileResource($path)); - - // process routes and imports - foreach ($xml->documentElement->childNodes as $node) { - if (!$node instanceof \DOMElement) { - continue; - } - - $this->parseNode($collection, $node, $path, $file); - } - - return $collection; - } - - /** - * Parses a node from a loaded XML file. - * - * @throws \InvalidArgumentException When the XML is invalid - */ - protected function parseNode(RouteCollection $collection, \DOMElement $node, string $path, string $file) - { - if (self::NAMESPACE_URI !== $node->namespaceURI) { - return; - } - - switch ($node->localName) { - case 'route': - $this->parseRoute($collection, $node, $path); - break; - case 'import': - $this->parseImport($collection, $node, $path, $file); - break; - case 'when': - if (!$this->env || $node->getAttribute('env') !== $this->env) { - break; - } - foreach ($node->childNodes as $node) { - if ($node instanceof \DOMElement) { - $this->parseNode($collection, $node, $path, $file); - } - } - break; - default: - throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "route" or "import".', $node->localName, $path)); - } - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - return \is_string($resource) && 'xml' === pathinfo($resource, \PATHINFO_EXTENSION) && (!$type || 'xml' === $type); - } - - /** - * Parses a route and adds it to the RouteCollection. - * - * @throws \InvalidArgumentException When the XML is invalid - */ - protected function parseRoute(RouteCollection $collection, \DOMElement $node, string $path) - { - if ('' === $id = $node->getAttribute('id')) { - throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must have an "id" attribute.', $path)); - } - - if ('' !== $alias = $node->getAttribute('alias')) { - $alias = $collection->addAlias($id, $alias); - - if ($deprecationInfo = $this->parseDeprecation($node, $path)) { - $alias->setDeprecated($deprecationInfo['package'], $deprecationInfo['version'], $deprecationInfo['message']); - } - - return; - } - - $schemes = preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, \PREG_SPLIT_NO_EMPTY); - $methods = preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, \PREG_SPLIT_NO_EMPTY); - - [$defaults, $requirements, $options, $condition, $paths, /* $prefixes */, $hosts] = $this->parseConfigs($node, $path); - - if (!$paths && '' === $node->getAttribute('path')) { - throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must have a "path" attribute or <path> child nodes.', $path)); - } - - if ($paths && '' !== $node->getAttribute('path')) { - throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must not have both a "path" attribute and <path> child nodes.', $path)); - } - - $routes = $this->createLocalizedRoute($collection, $id, $paths ?: $node->getAttribute('path')); - $routes->addDefaults($defaults); - $routes->addRequirements($requirements); - $routes->addOptions($options); - $routes->setSchemes($schemes); - $routes->setMethods($methods); - $routes->setCondition($condition); - - if (null !== $hosts) { - $this->addHost($routes, $hosts); - } - } - - /** - * Parses an import and adds the routes in the resource to the RouteCollection. - * - * @throws \InvalidArgumentException When the XML is invalid - */ - protected function parseImport(RouteCollection $collection, \DOMElement $node, string $path, string $file) - { - if ('' === $resource = $node->getAttribute('resource')) { - throw new \InvalidArgumentException(sprintf('The <import> element in file "%s" must have a "resource" attribute.', $path)); - } - - $type = $node->getAttribute('type'); - $prefix = $node->getAttribute('prefix'); - $schemes = $node->hasAttribute('schemes') ? preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, \PREG_SPLIT_NO_EMPTY) : null; - $methods = $node->hasAttribute('methods') ? preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, \PREG_SPLIT_NO_EMPTY) : null; - $trailingSlashOnRoot = $node->hasAttribute('trailing-slash-on-root') ? XmlUtils::phpize($node->getAttribute('trailing-slash-on-root')) : true; - $namePrefix = $node->getAttribute('name-prefix') ?: null; - - [$defaults, $requirements, $options, $condition, /* $paths */, $prefixes, $hosts] = $this->parseConfigs($node, $path); - - if ('' !== $prefix && $prefixes) { - throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must not have both a "prefix" attribute and <prefix> child nodes.', $path)); - } - - $exclude = []; - foreach ($node->childNodes as $child) { - if ($child instanceof \DOMElement && $child->localName === $exclude && self::NAMESPACE_URI === $child->namespaceURI) { - $exclude[] = $child->nodeValue; - } - } - - if ($node->hasAttribute('exclude')) { - if ($exclude) { - throw new \InvalidArgumentException('You cannot use both the attribute "exclude" and <exclude> tags at the same time.'); - } - $exclude = [$node->getAttribute('exclude')]; - } - - $this->setCurrentDir(\dirname($path)); - - /** @var RouteCollection[] $imported */ - $imported = $this->import($resource, '' !== $type ? $type : null, false, $file, $exclude) ?: []; - - if (!\is_array($imported)) { - $imported = [$imported]; - } - - foreach ($imported as $subCollection) { - $this->addPrefix($subCollection, $prefixes ?: $prefix, $trailingSlashOnRoot); - - if (null !== $hosts) { - $this->addHost($subCollection, $hosts); - } - - if (null !== $condition) { - $subCollection->setCondition($condition); - } - if (null !== $schemes) { - $subCollection->setSchemes($schemes); - } - if (null !== $methods) { - $subCollection->setMethods($methods); - } - if (null !== $namePrefix) { - $subCollection->addNamePrefix($namePrefix); - } - $subCollection->addDefaults($defaults); - $subCollection->addRequirements($requirements); - $subCollection->addOptions($options); - - $collection->addCollection($subCollection); - } - } - - /** - * @return \DOMDocument - * - * @throws \InvalidArgumentException When loading of XML file fails because of syntax errors - * or when the XML structure is not as expected by the scheme - - * see validate() - */ - protected function loadFile(string $file) - { - return XmlUtils::loadFile($file, __DIR__.static::SCHEME_PATH); - } - - /** - * Parses the config elements (default, requirement, option). - * - * @throws \InvalidArgumentException When the XML is invalid - */ - private function parseConfigs(\DOMElement $node, string $path): array - { - $defaults = []; - $requirements = []; - $options = []; - $condition = null; - $prefixes = []; - $paths = []; - $hosts = []; - - /** @var \DOMElement $n */ - foreach ($node->getElementsByTagNameNS(self::NAMESPACE_URI, '*') as $n) { - if ($node !== $n->parentNode) { - continue; - } - - switch ($n->localName) { - case 'path': - $paths[$n->getAttribute('locale')] = trim($n->textContent); - break; - case 'host': - $hosts[$n->getAttribute('locale')] = trim($n->textContent); - break; - case 'prefix': - $prefixes[$n->getAttribute('locale')] = trim($n->textContent); - break; - case 'default': - if ($this->isElementValueNull($n)) { - $defaults[$n->getAttribute('key')] = null; - } else { - $defaults[$n->getAttribute('key')] = $this->parseDefaultsConfig($n, $path); - } - - break; - case 'requirement': - $requirements[$n->getAttribute('key')] = trim($n->textContent); - break; - case 'option': - $options[$n->getAttribute('key')] = XmlUtils::phpize(trim($n->textContent)); - break; - case 'condition': - $condition = trim($n->textContent); - break; - default: - throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "default", "requirement", "option" or "condition".', $n->localName, $path)); - } - } - - if ($controller = $node->getAttribute('controller')) { - if (isset($defaults['_controller'])) { - $name = $node->hasAttribute('id') ? sprintf('"%s".', $node->getAttribute('id')) : sprintf('the "%s" tag.', $node->tagName); - - throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "controller" attribute and the defaults key "_controller" for ', $path).$name); - } - - $defaults['_controller'] = $controller; - } - if ($node->hasAttribute('locale')) { - $defaults['_locale'] = $node->getAttribute('locale'); - } - if ($node->hasAttribute('format')) { - $defaults['_format'] = $node->getAttribute('format'); - } - if ($node->hasAttribute('utf8')) { - $options['utf8'] = XmlUtils::phpize($node->getAttribute('utf8')); - } - if ($stateless = $node->getAttribute('stateless')) { - if (isset($defaults['_stateless'])) { - $name = $node->hasAttribute('id') ? sprintf('"%s".', $node->getAttribute('id')) : sprintf('the "%s" tag.', $node->tagName); - - throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "stateless" attribute and the defaults key "_stateless" for ', $path).$name); - } - - $defaults['_stateless'] = XmlUtils::phpize($stateless); - } - - if (!$hosts) { - $hosts = $node->hasAttribute('host') ? $node->getAttribute('host') : null; - } - - return [$defaults, $requirements, $options, $condition, $paths, $prefixes, $hosts]; - } - - /** - * Parses the "default" elements. - * - * @return array|bool|float|int|string|null - */ - private function parseDefaultsConfig(\DOMElement $element, string $path) - { - if ($this->isElementValueNull($element)) { - return null; - } - - // Check for existing element nodes in the default element. There can - // only be a single element inside a default element. So this element - // (if one was found) can safely be returned. - foreach ($element->childNodes as $child) { - if (!$child instanceof \DOMElement) { - continue; - } - - if (self::NAMESPACE_URI !== $child->namespaceURI) { - continue; - } - - return $this->parseDefaultNode($child, $path); - } - - // If the default element doesn't contain a nested "bool", "int", "float", - // "string", "list", or "map" element, the element contents will be treated - // as the string value of the associated default option. - return trim($element->textContent); - } - - /** - * Recursively parses the value of a "default" element. - * - * @return array|bool|float|int|string|null - * - * @throws \InvalidArgumentException when the XML is invalid - */ - private function parseDefaultNode(\DOMElement $node, string $path) - { - if ($this->isElementValueNull($node)) { - return null; - } - - switch ($node->localName) { - case 'bool': - return 'true' === trim($node->nodeValue) || '1' === trim($node->nodeValue); - case 'int': - return (int) trim($node->nodeValue); - case 'float': - return (float) trim($node->nodeValue); - case 'string': - return trim($node->nodeValue); - case 'list': - $list = []; - - foreach ($node->childNodes as $element) { - if (!$element instanceof \DOMElement) { - continue; - } - - if (self::NAMESPACE_URI !== $element->namespaceURI) { - continue; - } - - $list[] = $this->parseDefaultNode($element, $path); - } - - return $list; - case 'map': - $map = []; - - foreach ($node->childNodes as $element) { - if (!$element instanceof \DOMElement) { - continue; - } - - if (self::NAMESPACE_URI !== $element->namespaceURI) { - continue; - } - - $map[$element->getAttribute('key')] = $this->parseDefaultNode($element, $path); - } - - return $map; - default: - throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "bool", "int", "float", "string", "list", or "map".', $node->localName, $path)); - } - } - - private function isElementValueNull(\DOMElement $element): bool - { - $namespaceUri = 'http://www.w3.org/2001/XMLSchema-instance'; - - if (!$element->hasAttributeNS($namespaceUri, 'nil')) { - return false; - } - - return 'true' === $element->getAttributeNS($namespaceUri, 'nil') || '1' === $element->getAttributeNS($namespaceUri, 'nil'); - } - - /** - * Parses the deprecation elements. - * - * @throws \InvalidArgumentException When the XML is invalid - */ - private function parseDeprecation(\DOMElement $node, string $path): array - { - $deprecatedNode = null; - foreach ($node->childNodes as $child) { - if (!$child instanceof \DOMElement || self::NAMESPACE_URI !== $child->namespaceURI) { - continue; - } - if ('deprecated' !== $child->localName) { - throw new \InvalidArgumentException(sprintf('Invalid child element "%s" defined for alias "%s" in "%s".', $child->localName, $node->getAttribute('id'), $path)); - } - - $deprecatedNode = $child; - } - - if (null === $deprecatedNode) { - return []; - } - - if (!$deprecatedNode->hasAttribute('package')) { - throw new \InvalidArgumentException(sprintf('The <deprecated> element in file "%s" must have a "package" attribute.', $path)); - } - if (!$deprecatedNode->hasAttribute('version')) { - throw new \InvalidArgumentException(sprintf('The <deprecated> element in file "%s" must have a "version" attribute.', $path)); - } - - return [ - 'package' => $deprecatedNode->getAttribute('package'), - 'version' => $deprecatedNode->getAttribute('version'), - 'message' => trim($deprecatedNode->nodeValue), - ]; - } -} diff --git a/lib/symfony/routing/Loader/YamlFileLoader.php b/lib/symfony/routing/Loader/YamlFileLoader.php deleted file mode 100644 index ae98a314e..000000000 --- a/lib/symfony/routing/Loader/YamlFileLoader.php +++ /dev/null @@ -1,314 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Loader\FileLoader; -use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\Routing\Loader\Configurator\Traits\HostTrait; -use Symfony\Component\Routing\Loader\Configurator\Traits\LocalizedRouteTrait; -use Symfony\Component\Routing\Loader\Configurator\Traits\PrefixTrait; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Yaml\Exception\ParseException; -use Symfony\Component\Yaml\Parser as YamlParser; -use Symfony\Component\Yaml\Yaml; - -/** - * YamlFileLoader loads Yaml routing files. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Tobias Schultze <http://tobion.de> - */ -class YamlFileLoader extends FileLoader -{ - use HostTrait; - use LocalizedRouteTrait; - use PrefixTrait; - - private const AVAILABLE_KEYS = [ - 'resource', 'type', 'prefix', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options', 'condition', 'controller', 'name_prefix', 'trailing_slash_on_root', 'locale', 'format', 'utf8', 'exclude', 'stateless', - ]; - private $yamlParser; - - /** - * Loads a Yaml file. - * - * @param string $file A Yaml file path - * @param string|null $type The resource type - * - * @return RouteCollection - * - * @throws \InvalidArgumentException When a route can't be parsed because YAML is invalid - */ - public function load($file, string $type = null) - { - $path = $this->locator->locate($file); - - if (!stream_is_local($path)) { - throw new \InvalidArgumentException(sprintf('This is not a local file "%s".', $path)); - } - - if (!file_exists($path)) { - throw new \InvalidArgumentException(sprintf('File "%s" not found.', $path)); - } - - if (null === $this->yamlParser) { - $this->yamlParser = new YamlParser(); - } - - try { - $parsedConfig = $this->yamlParser->parseFile($path, Yaml::PARSE_CONSTANT); - } catch (ParseException $e) { - throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML: ', $path).$e->getMessage(), 0, $e); - } - - $collection = new RouteCollection(); - $collection->addResource(new FileResource($path)); - - // empty file - if (null === $parsedConfig) { - return $collection; - } - - // not an array - if (!\is_array($parsedConfig)) { - throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $path)); - } - - foreach ($parsedConfig as $name => $config) { - if (0 === strpos($name, 'when@')) { - if (!$this->env || 'when@'.$this->env !== $name) { - continue; - } - - foreach ($config as $name => $config) { - $this->validate($config, $name.'" when "@'.$this->env, $path); - - if (isset($config['resource'])) { - $this->parseImport($collection, $config, $path, $file); - } else { - $this->parseRoute($collection, $name, $config, $path); - } - } - - continue; - } - - $this->validate($config, $name, $path); - - if (isset($config['resource'])) { - $this->parseImport($collection, $config, $path, $file); - } else { - $this->parseRoute($collection, $name, $config, $path); - } - } - - return $collection; - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - return \is_string($resource) && \in_array(pathinfo($resource, \PATHINFO_EXTENSION), ['yml', 'yaml'], true) && (!$type || 'yaml' === $type); - } - - /** - * Parses a route and adds it to the RouteCollection. - */ - protected function parseRoute(RouteCollection $collection, string $name, array $config, string $path) - { - if (isset($config['alias'])) { - $alias = $collection->addAlias($name, $config['alias']); - $deprecation = $config['deprecated'] ?? null; - if (null !== $deprecation) { - $alias->setDeprecated( - $deprecation['package'], - $deprecation['version'], - $deprecation['message'] ?? '' - ); - } - - return; - } - - $defaults = $config['defaults'] ?? []; - $requirements = $config['requirements'] ?? []; - $options = $config['options'] ?? []; - - foreach ($requirements as $placeholder => $requirement) { - if (\is_int($placeholder)) { - throw new \InvalidArgumentException(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" of route "%s" in "%s"?', $placeholder, $requirement, $name, $path)); - } - } - - if (isset($config['controller'])) { - $defaults['_controller'] = $config['controller']; - } - if (isset($config['locale'])) { - $defaults['_locale'] = $config['locale']; - } - if (isset($config['format'])) { - $defaults['_format'] = $config['format']; - } - if (isset($config['utf8'])) { - $options['utf8'] = $config['utf8']; - } - if (isset($config['stateless'])) { - $defaults['_stateless'] = $config['stateless']; - } - - $routes = $this->createLocalizedRoute($collection, $name, $config['path']); - $routes->addDefaults($defaults); - $routes->addRequirements($requirements); - $routes->addOptions($options); - $routes->setSchemes($config['schemes'] ?? []); - $routes->setMethods($config['methods'] ?? []); - $routes->setCondition($config['condition'] ?? null); - - if (isset($config['host'])) { - $this->addHost($routes, $config['host']); - } - } - - /** - * Parses an import and adds the routes in the resource to the RouteCollection. - */ - protected function parseImport(RouteCollection $collection, array $config, string $path, string $file) - { - $type = $config['type'] ?? null; - $prefix = $config['prefix'] ?? ''; - $defaults = $config['defaults'] ?? []; - $requirements = $config['requirements'] ?? []; - $options = $config['options'] ?? []; - $host = $config['host'] ?? null; - $condition = $config['condition'] ?? null; - $schemes = $config['schemes'] ?? null; - $methods = $config['methods'] ?? null; - $trailingSlashOnRoot = $config['trailing_slash_on_root'] ?? true; - $namePrefix = $config['name_prefix'] ?? null; - $exclude = $config['exclude'] ?? null; - - if (isset($config['controller'])) { - $defaults['_controller'] = $config['controller']; - } - if (isset($config['locale'])) { - $defaults['_locale'] = $config['locale']; - } - if (isset($config['format'])) { - $defaults['_format'] = $config['format']; - } - if (isset($config['utf8'])) { - $options['utf8'] = $config['utf8']; - } - if (isset($config['stateless'])) { - $defaults['_stateless'] = $config['stateless']; - } - - $this->setCurrentDir(\dirname($path)); - - /** @var RouteCollection[] $imported */ - $imported = $this->import($config['resource'], $type, false, $file, $exclude) ?: []; - - if (!\is_array($imported)) { - $imported = [$imported]; - } - - foreach ($imported as $subCollection) { - $this->addPrefix($subCollection, $prefix, $trailingSlashOnRoot); - - if (null !== $host) { - $this->addHost($subCollection, $host); - } - if (null !== $condition) { - $subCollection->setCondition($condition); - } - if (null !== $schemes) { - $subCollection->setSchemes($schemes); - } - if (null !== $methods) { - $subCollection->setMethods($methods); - } - if (null !== $namePrefix) { - $subCollection->addNamePrefix($namePrefix); - } - $subCollection->addDefaults($defaults); - $subCollection->addRequirements($requirements); - $subCollection->addOptions($options); - - $collection->addCollection($subCollection); - } - } - - /** - * Validates the route configuration. - * - * @param array $config A resource config - * @param string $name The config key - * @param string $path The loaded file path - * - * @throws \InvalidArgumentException If one of the provided config keys is not supported, - * something is missing or the combination is nonsense - */ - protected function validate($config, string $name, string $path) - { - if (!\is_array($config)) { - throw new \InvalidArgumentException(sprintf('The definition of "%s" in "%s" must be a YAML array.', $name, $path)); - } - if (isset($config['alias'])) { - $this->validateAlias($config, $name, $path); - - return; - } - if ($extraKeys = array_diff(array_keys($config), self::AVAILABLE_KEYS)) { - throw new \InvalidArgumentException(sprintf('The routing file "%s" contains unsupported keys for "%s": "%s". Expected one of: "%s".', $path, $name, implode('", "', $extraKeys), implode('", "', self::AVAILABLE_KEYS))); - } - if (isset($config['resource']) && isset($config['path'])) { - throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "resource" key and the "path" key for "%s". Choose between an import and a route definition.', $path, $name)); - } - if (!isset($config['resource']) && isset($config['type'])) { - throw new \InvalidArgumentException(sprintf('The "type" key for the route definition "%s" in "%s" is unsupported. It is only available for imports in combination with the "resource" key.', $name, $path)); - } - if (!isset($config['resource']) && !isset($config['path'])) { - throw new \InvalidArgumentException(sprintf('You must define a "path" for the route "%s" in file "%s".', $name, $path)); - } - if (isset($config['controller']) && isset($config['defaults']['_controller'])) { - throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "controller" key and the defaults key "_controller" for "%s".', $path, $name)); - } - if (isset($config['stateless']) && isset($config['defaults']['_stateless'])) { - throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "stateless" key and the defaults key "_stateless" for "%s".', $path, $name)); - } - } - - /** - * @throws \InvalidArgumentException If one of the provided config keys is not supported, - * something is missing or the combination is nonsense - */ - private function validateAlias(array $config, string $name, string $path): void - { - foreach ($config as $key => $value) { - if (!\in_array($key, ['alias', 'deprecated'], true)) { - throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify other keys than "alias" and "deprecated" for "%s".', $path, $name)); - } - - if ('deprecated' === $key) { - if (!isset($value['package'])) { - throw new \InvalidArgumentException(sprintf('The routing file "%s" must specify the attribute "package" of the "deprecated" option for "%s".', $path, $name)); - } - - if (!isset($value['version'])) { - throw new \InvalidArgumentException(sprintf('The routing file "%s" must specify the attribute "version" of the "deprecated" option for "%s".', $path, $name)); - } - } - } - } -} diff --git a/lib/symfony/routing/Loader/schema/routing/routing-1.0.xsd b/lib/symfony/routing/Loader/schema/routing/routing-1.0.xsd deleted file mode 100644 index 66c40a0d8..000000000 --- a/lib/symfony/routing/Loader/schema/routing/routing-1.0.xsd +++ /dev/null @@ -1,194 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> - -<xsd:schema xmlns="http://symfony.com/schema/routing" - xmlns:xsd="http://www.w3.org/2001/XMLSchema" - targetNamespace="http://symfony.com/schema/routing" - elementFormDefault="qualified"> - - <xsd:annotation> - <xsd:documentation><![CDATA[ - Symfony XML Routing Schema, version 1.0 - Authors: Fabien Potencier, Tobias Schultze - - This scheme defines the elements and attributes that can be used to define - routes. A route maps an HTTP request to a set of configuration variables. - ]]></xsd:documentation> - </xsd:annotation> - - <xsd:element name="routes" type="routes" /> - - <xsd:complexType name="routes"> - <xsd:choice minOccurs="0" maxOccurs="unbounded"> - <xsd:element name="import" type="import" /> - <xsd:element name="route" type="route" /> - <xsd:element name="when" type="when" /> - </xsd:choice> - </xsd:complexType> - - <xsd:complexType name="when"> - <xsd:choice minOccurs="0" maxOccurs="unbounded"> - <xsd:element name="import" type="import" /> - <xsd:element name="route" type="route" /> - </xsd:choice> - <xsd:attribute name="env" type="xsd:string" use="required" /> - </xsd:complexType> - - <xsd:complexType name="localized-path"> - <xsd:simpleContent> - <xsd:extension base="xsd:string"> - <xsd:attribute name="locale" type="xsd:string" use="required" /> - </xsd:extension> - </xsd:simpleContent> - </xsd:complexType> - - <xsd:group name="configs"> - <xsd:choice> - <xsd:element name="default" nillable="true" type="default" /> - <xsd:element name="requirement" type="element" /> - <xsd:element name="option" type="element" /> - <xsd:element name="condition" type="xsd:string" /> - </xsd:choice> - </xsd:group> - - <xsd:complexType name="route"> - <xsd:sequence> - <xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="path" type="localized-path" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="host" type="localized-path" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="deprecated" type="deprecated" minOccurs="0" maxOccurs="1" /> - </xsd:sequence> - <xsd:attribute name="id" type="xsd:string" use="required" /> - <xsd:attribute name="path" type="xsd:string" /> - <xsd:attribute name="host" type="xsd:string" /> - <xsd:attribute name="schemes" type="xsd:string" /> - <xsd:attribute name="methods" type="xsd:string" /> - <xsd:attribute name="controller" type="xsd:string" /> - <xsd:attribute name="locale" type="xsd:string" /> - <xsd:attribute name="format" type="xsd:string" /> - <xsd:attribute name="utf8" type="xsd:boolean" /> - <xsd:attribute name="stateless" type="xsd:boolean" /> - <xsd:attribute name="alias" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="import"> - <xsd:sequence maxOccurs="unbounded" minOccurs="0"> - <xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="prefix" type="localized-path" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="exclude" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="host" type="localized-path" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - <xsd:attribute name="resource" type="xsd:string" use="required" /> - <xsd:attribute name="type" type="xsd:string" /> - <xsd:attribute name="exclude" type="xsd:string" /> - <xsd:attribute name="prefix" type="xsd:string" /> - <xsd:attribute name="name-prefix" type="xsd:string" /> - <xsd:attribute name="host" type="xsd:string" /> - <xsd:attribute name="schemes" type="xsd:string" /> - <xsd:attribute name="methods" type="xsd:string" /> - <xsd:attribute name="controller" type="xsd:string" /> - <xsd:attribute name="locale" type="xsd:string" /> - <xsd:attribute name="format" type="xsd:string" /> - <xsd:attribute name="trailing-slash-on-root" type="xsd:boolean" /> - <xsd:attribute name="utf8" type="xsd:boolean" /> - <xsd:attribute name="stateless" type="xsd:boolean" /> - </xsd:complexType> - - <xsd:complexType name="default" mixed="true"> - <xsd:choice minOccurs="0" maxOccurs="1"> - <xsd:element name="bool" type="xsd:boolean" /> - <xsd:element name="int" type="xsd:integer" /> - <xsd:element name="float" type="xsd:float" /> - <xsd:element name="string" type="xsd:string" /> - <xsd:element name="list" type="list" /> - <xsd:element name="map" type="map" /> - </xsd:choice> - <xsd:attribute name="key" type="xsd:string" use="required" /> - </xsd:complexType> - - <xsd:complexType name="element"> - <xsd:simpleContent> - <xsd:extension base="xsd:string"> - <xsd:attribute name="key" type="xsd:string" use="required" /> - </xsd:extension> - </xsd:simpleContent> - </xsd:complexType> - - <xsd:complexType name="list"> - <xsd:choice minOccurs="0" maxOccurs="unbounded"> - <xsd:element name="bool" nillable="true" type="xsd:boolean" /> - <xsd:element name="int" nillable="true" type="xsd:integer" /> - <xsd:element name="float" nillable="true" type="xsd:float" /> - <xsd:element name="string" nillable="true" type="xsd:string" /> - <xsd:element name="list" nillable="true" type="list" /> - <xsd:element name="map" nillable="true" type="map" /> - </xsd:choice> - </xsd:complexType> - - <xsd:complexType name="map"> - <xsd:choice minOccurs="0" maxOccurs="unbounded"> - <xsd:element name="bool" nillable="true" type="map-bool-entry" /> - <xsd:element name="int" nillable="true" type="map-int-entry" /> - <xsd:element name="float" nillable="true" type="map-float-entry" /> - <xsd:element name="string" nillable="true" type="map-string-entry" /> - <xsd:element name="list" nillable="true" type="map-list-entry" /> - <xsd:element name="map" nillable="true" type="map-map-entry" /> - </xsd:choice> - </xsd:complexType> - - <xsd:complexType name="map-bool-entry"> - <xsd:simpleContent> - <xsd:extension base="xsd:boolean"> - <xsd:attribute name="key" type="xsd:string" use="required" /> - </xsd:extension> - </xsd:simpleContent> - </xsd:complexType> - - <xsd:complexType name="map-int-entry"> - <xsd:simpleContent> - <xsd:extension base="xsd:integer"> - <xsd:attribute name="key" type="xsd:string" use="required" /> - </xsd:extension> - </xsd:simpleContent> - </xsd:complexType> - - <xsd:complexType name="map-float-entry"> - <xsd:simpleContent> - <xsd:extension base="xsd:float"> - <xsd:attribute name="key" type="xsd:string" use="required" /> - </xsd:extension> - </xsd:simpleContent> - </xsd:complexType> - - <xsd:complexType name="map-string-entry"> - <xsd:simpleContent> - <xsd:extension base="xsd:string"> - <xsd:attribute name="key" type="xsd:string" use="required" /> - </xsd:extension> - </xsd:simpleContent> - </xsd:complexType> - - <xsd:complexType name="map-list-entry"> - <xsd:complexContent> - <xsd:extension base="list"> - <xsd:attribute name="key" type="xsd:string" use="required" /> - </xsd:extension> - </xsd:complexContent> - </xsd:complexType> - - <xsd:complexType name="map-map-entry"> - <xsd:complexContent> - <xsd:extension base="map"> - <xsd:attribute name="key" type="xsd:string" use="required" /> - </xsd:extension> - </xsd:complexContent> - </xsd:complexType> - - <xsd:complexType name="deprecated"> - <xsd:simpleContent> - <xsd:extension base="xsd:string"> - <xsd:attribute name="package" type="xsd:string" use="required" /> - <xsd:attribute name="version" type="xsd:string" use="required" /> - </xsd:extension> - </xsd:simpleContent> - </xsd:complexType> -</xsd:schema> diff --git a/lib/symfony/routing/Matcher/CompiledUrlMatcher.php b/lib/symfony/routing/Matcher/CompiledUrlMatcher.php deleted file mode 100644 index ae13fd701..000000000 --- a/lib/symfony/routing/Matcher/CompiledUrlMatcher.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher; - -use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait; -use Symfony\Component\Routing\RequestContext; - -/** - * Matches URLs based on rules dumped by CompiledUrlMatcherDumper. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class CompiledUrlMatcher extends UrlMatcher -{ - use CompiledUrlMatcherTrait; - - public function __construct(array $compiledRoutes, RequestContext $context) - { - $this->context = $context; - [$this->matchHost, $this->staticRoutes, $this->regexpList, $this->dynamicRoutes, $this->checkCondition] = $compiledRoutes; - } -} diff --git a/lib/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php b/lib/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php deleted file mode 100644 index 123130ed4..000000000 --- a/lib/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php +++ /dev/null @@ -1,501 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher\Dumper; - -use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; -use Symfony\Component\ExpressionLanguage\ExpressionLanguage; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * CompiledUrlMatcherDumper creates PHP arrays to be used with CompiledUrlMatcher. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Tobias Schultze <http://tobion.de> - * @author Arnaud Le Blanc <arnaud.lb@gmail.com> - * @author Nicolas Grekas <p@tchwork.com> - */ -class CompiledUrlMatcherDumper extends MatcherDumper -{ - private $expressionLanguage; - private $signalingException; - - /** - * @var ExpressionFunctionProviderInterface[] - */ - private $expressionLanguageProviders = []; - - /** - * {@inheritdoc} - */ - public function dump(array $options = []) - { - return <<<EOF -<?php - -/** - * This file has been auto-generated - * by the Symfony Routing Component. - */ - -return [ -{$this->generateCompiledRoutes()}]; - -EOF; - } - - public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) - { - $this->expressionLanguageProviders[] = $provider; - } - - /** - * Generates the arrays for CompiledUrlMatcher's constructor. - */ - public function getCompiledRoutes(bool $forDump = false): array - { - // Group hosts by same-suffix, re-order when possible - $matchHost = false; - $routes = new StaticPrefixCollection(); - foreach ($this->getRoutes()->all() as $name => $route) { - if ($host = $route->getHost()) { - $matchHost = true; - $host = '/'.strtr(strrev($host), '}.{', '(/)'); - } - - $routes->addRoute($host ?: '/(.*)', [$name, $route]); - } - - if ($matchHost) { - $compiledRoutes = [true]; - $routes = $routes->populateCollection(new RouteCollection()); - } else { - $compiledRoutes = [false]; - $routes = $this->getRoutes(); - } - - [$staticRoutes, $dynamicRoutes] = $this->groupStaticRoutes($routes); - - $conditions = [null]; - $compiledRoutes[] = $this->compileStaticRoutes($staticRoutes, $conditions); - $chunkLimit = \count($dynamicRoutes); - - while (true) { - try { - $this->signalingException = new \RuntimeException('Compilation failed: regular expression is too large'); - $compiledRoutes = array_merge($compiledRoutes, $this->compileDynamicRoutes($dynamicRoutes, $matchHost, $chunkLimit, $conditions)); - - break; - } catch (\Exception $e) { - if (1 < $chunkLimit && $this->signalingException === $e) { - $chunkLimit = 1 + ($chunkLimit >> 1); - continue; - } - throw $e; - } - } - - if ($forDump) { - $compiledRoutes[2] = $compiledRoutes[4]; - } - unset($conditions[0]); - - if ($conditions) { - foreach ($conditions as $expression => $condition) { - $conditions[$expression] = "case {$condition}: return {$expression};"; - } - - $checkConditionCode = <<<EOF - static function (\$condition, \$context, \$request) { // \$checkCondition - switch (\$condition) { -{$this->indent(implode("\n", $conditions), 3)} - } - } -EOF; - $compiledRoutes[4] = $forDump ? $checkConditionCode.",\n" : eval('return '.$checkConditionCode.';'); - } else { - $compiledRoutes[4] = $forDump ? " null, // \$checkCondition\n" : null; - } - - return $compiledRoutes; - } - - private function generateCompiledRoutes(): string - { - [$matchHost, $staticRoutes, $regexpCode, $dynamicRoutes, $checkConditionCode] = $this->getCompiledRoutes(true); - - $code = self::export($matchHost).', // $matchHost'."\n"; - - $code .= '[ // $staticRoutes'."\n"; - foreach ($staticRoutes as $path => $routes) { - $code .= sprintf(" %s => [\n", self::export($path)); - foreach ($routes as $route) { - $code .= sprintf(" [%s, %s, %s, %s, %s, %s, %s],\n", ...array_map([__CLASS__, 'export'], $route)); - } - $code .= " ],\n"; - } - $code .= "],\n"; - - $code .= sprintf("[ // \$regexpList%s\n],\n", $regexpCode); - - $code .= '[ // $dynamicRoutes'."\n"; - foreach ($dynamicRoutes as $path => $routes) { - $code .= sprintf(" %s => [\n", self::export($path)); - foreach ($routes as $route) { - $code .= sprintf(" [%s, %s, %s, %s, %s, %s, %s],\n", ...array_map([__CLASS__, 'export'], $route)); - } - $code .= " ],\n"; - } - $code .= "],\n"; - $code = preg_replace('/ => \[\n (\[.+?),\n \],/', ' => [$1],', $code); - - return $this->indent($code, 1).$checkConditionCode; - } - - /** - * Splits static routes from dynamic routes, so that they can be matched first, using a simple switch. - */ - private function groupStaticRoutes(RouteCollection $collection): array - { - $staticRoutes = $dynamicRegex = []; - $dynamicRoutes = new RouteCollection(); - - foreach ($collection->all() as $name => $route) { - $compiledRoute = $route->compile(); - $staticPrefix = rtrim($compiledRoute->getStaticPrefix(), '/'); - $hostRegex = $compiledRoute->getHostRegex(); - $regex = $compiledRoute->getRegex(); - if ($hasTrailingSlash = '/' !== $route->getPath()) { - $pos = strrpos($regex, '$'); - $hasTrailingSlash = '/' === $regex[$pos - 1]; - $regex = substr_replace($regex, '/?$', $pos - $hasTrailingSlash, 1 + $hasTrailingSlash); - } - - if (!$compiledRoute->getPathVariables()) { - $host = !$compiledRoute->getHostVariables() ? $route->getHost() : ''; - $url = $route->getPath(); - if ($hasTrailingSlash) { - $url = substr($url, 0, -1); - } - foreach ($dynamicRegex as [$hostRx, $rx, $prefix]) { - if (('' === $prefix || str_starts_with($url, $prefix)) && (preg_match($rx, $url) || preg_match($rx, $url.'/')) && (!$host || !$hostRx || preg_match($hostRx, $host))) { - $dynamicRegex[] = [$hostRegex, $regex, $staticPrefix]; - $dynamicRoutes->add($name, $route); - continue 2; - } - } - - $staticRoutes[$url][$name] = [$route, $hasTrailingSlash]; - } else { - $dynamicRegex[] = [$hostRegex, $regex, $staticPrefix]; - $dynamicRoutes->add($name, $route); - } - } - - return [$staticRoutes, $dynamicRoutes]; - } - - /** - * Compiles static routes in a switch statement. - * - * Condition-less paths are put in a static array in the switch's default, with generic matching logic. - * Paths that can match two or more routes, or have user-specified conditions are put in separate switch's cases. - * - * @throws \LogicException - */ - private function compileStaticRoutes(array $staticRoutes, array &$conditions): array - { - if (!$staticRoutes) { - return []; - } - $compiledRoutes = []; - - foreach ($staticRoutes as $url => $routes) { - $compiledRoutes[$url] = []; - foreach ($routes as $name => [$route, $hasTrailingSlash]) { - $compiledRoutes[$url][] = $this->compileRoute($route, $name, (!$route->compile()->getHostVariables() ? $route->getHost() : $route->compile()->getHostRegex()) ?: null, $hasTrailingSlash, false, $conditions); - } - } - - return $compiledRoutes; - } - - /** - * Compiles a regular expression followed by a switch statement to match dynamic routes. - * - * The regular expression matches both the host and the pathinfo at the same time. For stellar performance, - * it is built as a tree of patterns, with re-ordering logic to group same-prefix routes together when possible. - * - * Patterns are named so that we know which one matched (https://pcre.org/current/doc/html/pcre2syntax.html#SEC23). - * This name is used to "switch" to the additional logic required to match the final route. - * - * Condition-less paths are put in a static array in the switch's default, with generic matching logic. - * Paths that can match two or more routes, or have user-specified conditions are put in separate switch's cases. - * - * Last but not least: - * - Because it is not possible to mix unicode/non-unicode patterns in a single regexp, several of them can be generated. - * - The same regexp can be used several times when the logic in the switch rejects the match. When this happens, the - * matching-but-failing subpattern is excluded by replacing its name by "(*F)", which forces a failure-to-match. - * To ease this backlisting operation, the name of subpatterns is also the string offset where the replacement should occur. - */ - private function compileDynamicRoutes(RouteCollection $collection, bool $matchHost, int $chunkLimit, array &$conditions): array - { - if (!$collection->all()) { - return [[], [], '']; - } - $regexpList = []; - $code = ''; - $state = (object) [ - 'regexMark' => 0, - 'regex' => [], - 'routes' => [], - 'mark' => 0, - 'markTail' => 0, - 'hostVars' => [], - 'vars' => [], - ]; - $state->getVars = static function ($m) use ($state) { - if ('_route' === $m[1]) { - return '?:'; - } - - $state->vars[] = $m[1]; - - return ''; - }; - - $chunkSize = 0; - $prev = null; - $perModifiers = []; - foreach ($collection->all() as $name => $route) { - preg_match('#[a-zA-Z]*$#', $route->compile()->getRegex(), $rx); - if ($chunkLimit < ++$chunkSize || $prev !== $rx[0] && $route->compile()->getPathVariables()) { - $chunkSize = 1; - $routes = new RouteCollection(); - $perModifiers[] = [$rx[0], $routes]; - $prev = $rx[0]; - } - $routes->add($name, $route); - } - - foreach ($perModifiers as [$modifiers, $routes]) { - $prev = false; - $perHost = []; - foreach ($routes->all() as $name => $route) { - $regex = $route->compile()->getHostRegex(); - if ($prev !== $regex) { - $routes = new RouteCollection(); - $perHost[] = [$regex, $routes]; - $prev = $regex; - } - $routes->add($name, $route); - } - $prev = false; - $rx = '{^(?'; - $code .= "\n {$state->mark} => ".self::export($rx); - $startingMark = $state->mark; - $state->mark += \strlen($rx); - $state->regex = $rx; - - foreach ($perHost as [$hostRegex, $routes]) { - if ($matchHost) { - if ($hostRegex) { - preg_match('#^.\^(.*)\$.[a-zA-Z]*$#', $hostRegex, $rx); - $state->vars = []; - $hostRegex = '(?i:'.preg_replace_callback('#\?P<([^>]++)>#', $state->getVars, $rx[1]).')\.'; - $state->hostVars = $state->vars; - } else { - $hostRegex = '(?:(?:[^./]*+\.)++)'; - $state->hostVars = []; - } - $state->mark += \strlen($rx = ($prev ? ')' : '')."|{$hostRegex}(?"); - $code .= "\n .".self::export($rx); - $state->regex .= $rx; - $prev = true; - } - - $tree = new StaticPrefixCollection(); - foreach ($routes->all() as $name => $route) { - preg_match('#^.\^(.*)\$.[a-zA-Z]*$#', $route->compile()->getRegex(), $rx); - - $state->vars = []; - $regex = preg_replace_callback('#\?P<([^>]++)>#', $state->getVars, $rx[1]); - if ($hasTrailingSlash = '/' !== $regex && '/' === $regex[-1]) { - $regex = substr($regex, 0, -1); - } - $hasTrailingVar = (bool) preg_match('#\{\w+\}/?$#', $route->getPath()); - - $tree->addRoute($regex, [$name, $regex, $state->vars, $route, $hasTrailingSlash, $hasTrailingVar]); - } - - $code .= $this->compileStaticPrefixCollection($tree, $state, 0, $conditions); - } - if ($matchHost) { - $code .= "\n .')'"; - $state->regex .= ')'; - } - $rx = ")/?$}{$modifiers}"; - $code .= "\n .'{$rx}',"; - $state->regex .= $rx; - $state->markTail = 0; - - // if the regex is too large, throw a signaling exception to recompute with smaller chunk size - set_error_handler(function ($type, $message) { throw str_contains($message, $this->signalingException->getMessage()) ? $this->signalingException : new \ErrorException($message); }); - try { - preg_match($state->regex, ''); - } finally { - restore_error_handler(); - } - - $regexpList[$startingMark] = $state->regex; - } - - $state->routes[$state->mark][] = [null, null, null, null, false, false, 0]; - unset($state->getVars); - - return [$regexpList, $state->routes, $code]; - } - - /** - * Compiles a regexp tree of subpatterns that matches nested same-prefix routes. - * - * @param \stdClass $state A simple state object that keeps track of the progress of the compilation, - * and gathers the generated switch's "case" and "default" statements - */ - private function compileStaticPrefixCollection(StaticPrefixCollection $tree, \stdClass $state, int $prefixLen, array &$conditions): string - { - $code = ''; - $prevRegex = null; - $routes = $tree->getRoutes(); - - foreach ($routes as $i => $route) { - if ($route instanceof StaticPrefixCollection) { - $prevRegex = null; - $prefix = substr($route->getPrefix(), $prefixLen); - $state->mark += \strlen($rx = "|{$prefix}(?"); - $code .= "\n .".self::export($rx); - $state->regex .= $rx; - $code .= $this->indent($this->compileStaticPrefixCollection($route, $state, $prefixLen + \strlen($prefix), $conditions)); - $code .= "\n .')'"; - $state->regex .= ')'; - ++$state->markTail; - continue; - } - - [$name, $regex, $vars, $route, $hasTrailingSlash, $hasTrailingVar] = $route; - $compiledRoute = $route->compile(); - $vars = array_merge($state->hostVars, $vars); - - if ($compiledRoute->getRegex() === $prevRegex) { - $state->routes[$state->mark][] = $this->compileRoute($route, $name, $vars, $hasTrailingSlash, $hasTrailingVar, $conditions); - continue; - } - - $state->mark += 3 + $state->markTail + \strlen($regex) - $prefixLen; - $state->markTail = 2 + \strlen($state->mark); - $rx = sprintf('|%s(*:%s)', substr($regex, $prefixLen), $state->mark); - $code .= "\n .".self::export($rx); - $state->regex .= $rx; - - $prevRegex = $compiledRoute->getRegex(); - $state->routes[$state->mark] = [$this->compileRoute($route, $name, $vars, $hasTrailingSlash, $hasTrailingVar, $conditions)]; - } - - return $code; - } - - /** - * Compiles a single Route to PHP code used to match it against the path info. - */ - private function compileRoute(Route $route, string $name, $vars, bool $hasTrailingSlash, bool $hasTrailingVar, array &$conditions): array - { - $defaults = $route->getDefaults(); - - if (isset($defaults['_canonical_route'])) { - $name = $defaults['_canonical_route']; - unset($defaults['_canonical_route']); - } - - if ($condition = $route->getCondition()) { - $condition = $this->getExpressionLanguage()->compile($condition, ['context', 'request']); - $condition = $conditions[$condition] ?? $conditions[$condition] = (str_contains($condition, '$request') ? 1 : -1) * \count($conditions); - } else { - $condition = null; - } - - return [ - ['_route' => $name] + $defaults, - $vars, - array_flip($route->getMethods()) ?: null, - array_flip($route->getSchemes()) ?: null, - $hasTrailingSlash, - $hasTrailingVar, - $condition, - ]; - } - - private function getExpressionLanguage(): ExpressionLanguage - { - if (null === $this->expressionLanguage) { - if (!class_exists(ExpressionLanguage::class)) { - throw new \LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); - } - $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders); - } - - return $this->expressionLanguage; - } - - private function indent(string $code, int $level = 1): string - { - return preg_replace('/^./m', str_repeat(' ', $level).'$0', $code); - } - - /** - * @internal - */ - public static function export($value): string - { - if (null === $value) { - return 'null'; - } - if (!\is_array($value)) { - if (\is_object($value)) { - throw new \InvalidArgumentException('Symfony\Component\Routing\Route cannot contain objects.'); - } - - return str_replace("\n", '\'."\n".\'', var_export($value, true)); - } - if (!$value) { - return '[]'; - } - - $i = 0; - $export = '['; - - foreach ($value as $k => $v) { - if ($i === $k) { - ++$i; - } else { - $export .= self::export($k).' => '; - - if (\is_int($k) && $i < $k) { - $i = 1 + $k; - } - } - - $export .= self::export($v).', '; - } - - return substr_replace($export, ']', -2); - } -} diff --git a/lib/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php b/lib/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php deleted file mode 100644 index bdb7ba3d0..000000000 --- a/lib/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php +++ /dev/null @@ -1,191 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher\Dumper; - -use Symfony\Component\Routing\Exception\MethodNotAllowedException; -use Symfony\Component\Routing\Exception\NoConfigurationException; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; -use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface; -use Symfony\Component\Routing\RequestContext; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - * - * @property RequestContext $context - */ -trait CompiledUrlMatcherTrait -{ - private $matchHost = false; - private $staticRoutes = []; - private $regexpList = []; - private $dynamicRoutes = []; - - /** - * @var callable|null - */ - private $checkCondition; - - public function match(string $pathinfo): array - { - $allow = $allowSchemes = []; - if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) { - return $ret; - } - if ($allow) { - throw new MethodNotAllowedException(array_keys($allow)); - } - if (!$this instanceof RedirectableUrlMatcherInterface) { - throw new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo)); - } - if (!\in_array($this->context->getMethod(), ['HEAD', 'GET'], true)) { - // no-op - } elseif ($allowSchemes) { - redirect_scheme: - $scheme = $this->context->getScheme(); - $this->context->setScheme(key($allowSchemes)); - try { - if ($ret = $this->doMatch($pathinfo)) { - return $this->redirect($pathinfo, $ret['_route'], $this->context->getScheme()) + $ret; - } - } finally { - $this->context->setScheme($scheme); - } - } elseif ('/' !== $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/') { - $pathinfo = $trimmedPathinfo === $pathinfo ? $pathinfo.'/' : $trimmedPathinfo; - if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) { - return $this->redirect($pathinfo, $ret['_route']) + $ret; - } - if ($allowSchemes) { - goto redirect_scheme; - } - } - - throw new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo)); - } - - private function doMatch(string $pathinfo, array &$allow = [], array &$allowSchemes = []): array - { - $allow = $allowSchemes = []; - $pathinfo = rawurldecode($pathinfo) ?: '/'; - $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/'; - $context = $this->context; - $requestMethod = $canonicalMethod = $context->getMethod(); - - if ($this->matchHost) { - $host = strtolower($context->getHost()); - } - - if ('HEAD' === $requestMethod) { - $canonicalMethod = 'GET'; - } - $supportsRedirections = 'GET' === $canonicalMethod && $this instanceof RedirectableUrlMatcherInterface; - - foreach ($this->staticRoutes[$trimmedPathinfo] ?? [] as [$ret, $requiredHost, $requiredMethods, $requiredSchemes, $hasTrailingSlash, , $condition]) { - if ($condition && !($this->checkCondition)($condition, $context, 0 < $condition ? $request ?? $request = $this->request ?: $this->createRequest($pathinfo) : null)) { - continue; - } - - if ($requiredHost) { - if ('{' !== $requiredHost[0] ? $requiredHost !== $host : !preg_match($requiredHost, $host, $hostMatches)) { - continue; - } - if ('{' === $requiredHost[0] && $hostMatches) { - $hostMatches['_route'] = $ret['_route']; - $ret = $this->mergeDefaults($hostMatches, $ret); - } - } - - if ('/' !== $pathinfo && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) { - if ($supportsRedirections && (!$requiredMethods || isset($requiredMethods['GET']))) { - return $allow = $allowSchemes = []; - } - continue; - } - - $hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]); - if ($hasRequiredScheme && $requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) { - $allow += $requiredMethods; - continue; - } - - if (!$hasRequiredScheme) { - $allowSchemes += $requiredSchemes; - continue; - } - - return $ret; - } - - $matchedPathinfo = $this->matchHost ? $host.'.'.$pathinfo : $pathinfo; - - foreach ($this->regexpList as $offset => $regex) { - while (preg_match($regex, $matchedPathinfo, $matches)) { - foreach ($this->dynamicRoutes[$m = (int) $matches['MARK']] as [$ret, $vars, $requiredMethods, $requiredSchemes, $hasTrailingSlash, $hasTrailingVar, $condition]) { - if (null !== $condition) { - if (0 === $condition) { // marks the last route in the regexp - continue 3; - } - if (!($this->checkCondition)($condition, $context, 0 < $condition ? $request ?? $request = $this->request ?: $this->createRequest($pathinfo) : null)) { - continue; - } - } - - $hasTrailingVar = $trimmedPathinfo !== $pathinfo && $hasTrailingVar; - - if ($hasTrailingVar && ($hasTrailingSlash || (null === $n = $matches[\count($vars)] ?? null) || '/' !== ($n[-1] ?? '/')) && preg_match($regex, $this->matchHost ? $host.'.'.$trimmedPathinfo : $trimmedPathinfo, $n) && $m === (int) $n['MARK']) { - if ($hasTrailingSlash) { - $matches = $n; - } else { - $hasTrailingVar = false; - } - } - - if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) { - if ($supportsRedirections && (!$requiredMethods || isset($requiredMethods['GET']))) { - return $allow = $allowSchemes = []; - } - continue; - } - - foreach ($vars as $i => $v) { - if (isset($matches[1 + $i])) { - $ret[$v] = $matches[1 + $i]; - } - } - - if ($requiredSchemes && !isset($requiredSchemes[$context->getScheme()])) { - $allowSchemes += $requiredSchemes; - continue; - } - - if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) { - $allow += $requiredMethods; - continue; - } - - return $ret; - } - - $regex = substr_replace($regex, 'F', $m - $offset, 1 + \strlen($m)); - $offset += \strlen($m); - } - } - - if ('/' === $pathinfo && !$allow && !$allowSchemes) { - throw new NoConfigurationException(); - } - - return []; - } -} diff --git a/lib/symfony/routing/Matcher/Dumper/MatcherDumper.php b/lib/symfony/routing/Matcher/Dumper/MatcherDumper.php deleted file mode 100644 index ea51ab406..000000000 --- a/lib/symfony/routing/Matcher/Dumper/MatcherDumper.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher\Dumper; - -use Symfony\Component\Routing\RouteCollection; - -/** - * MatcherDumper is the abstract class for all built-in matcher dumpers. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -abstract class MatcherDumper implements MatcherDumperInterface -{ - private $routes; - - public function __construct(RouteCollection $routes) - { - $this->routes = $routes; - } - - /** - * {@inheritdoc} - */ - public function getRoutes() - { - return $this->routes; - } -} diff --git a/lib/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php b/lib/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php deleted file mode 100644 index 8e33802d3..000000000 --- a/lib/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher\Dumper; - -use Symfony\Component\Routing\RouteCollection; - -/** - * MatcherDumperInterface is the interface that all matcher dumper classes must implement. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface MatcherDumperInterface -{ - /** - * Dumps a set of routes to a string representation of executable code - * that can then be used to match a request against these routes. - * - * @return string - */ - public function dump(array $options = []); - - /** - * Gets the routes to dump. - * - * @return RouteCollection - */ - public function getRoutes(); -} diff --git a/lib/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php b/lib/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php deleted file mode 100644 index 97bd692a5..000000000 --- a/lib/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php +++ /dev/null @@ -1,205 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher\Dumper; - -use Symfony\Component\Routing\RouteCollection; - -/** - * Prefix tree of routes preserving routes order. - * - * @author Frank de Jonge <info@frankdejonge.nl> - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -class StaticPrefixCollection -{ - private $prefix; - - /** - * @var string[] - */ - private $staticPrefixes = []; - - /** - * @var string[] - */ - private $prefixes = []; - - /** - * @var array[]|self[] - */ - private $items = []; - - public function __construct(string $prefix = '/') - { - $this->prefix = $prefix; - } - - public function getPrefix(): string - { - return $this->prefix; - } - - /** - * @return array[]|self[] - */ - public function getRoutes(): array - { - return $this->items; - } - - /** - * Adds a route to a group. - * - * @param array|self $route - */ - public function addRoute(string $prefix, $route) - { - [$prefix, $staticPrefix] = $this->getCommonPrefix($prefix, $prefix); - - for ($i = \count($this->items) - 1; 0 <= $i; --$i) { - $item = $this->items[$i]; - - [$commonPrefix, $commonStaticPrefix] = $this->getCommonPrefix($prefix, $this->prefixes[$i]); - - if ($this->prefix === $commonPrefix) { - // the new route and a previous one have no common prefix, let's see if they are exclusive to each others - - if ($this->prefix !== $staticPrefix && $this->prefix !== $this->staticPrefixes[$i]) { - // the new route and the previous one have exclusive static prefixes - continue; - } - - if ($this->prefix === $staticPrefix && $this->prefix === $this->staticPrefixes[$i]) { - // the new route and the previous one have no static prefix - break; - } - - if ($this->prefixes[$i] !== $this->staticPrefixes[$i] && $this->prefix === $this->staticPrefixes[$i]) { - // the previous route is non-static and has no static prefix - break; - } - - if ($prefix !== $staticPrefix && $this->prefix === $staticPrefix) { - // the new route is non-static and has no static prefix - break; - } - - continue; - } - - if ($item instanceof self && $this->prefixes[$i] === $commonPrefix) { - // the new route is a child of a previous one, let's nest it - $item->addRoute($prefix, $route); - } else { - // the new route and a previous one have a common prefix, let's merge them - $child = new self($commonPrefix); - [$child->prefixes[0], $child->staticPrefixes[0]] = $child->getCommonPrefix($this->prefixes[$i], $this->prefixes[$i]); - [$child->prefixes[1], $child->staticPrefixes[1]] = $child->getCommonPrefix($prefix, $prefix); - $child->items = [$this->items[$i], $route]; - - $this->staticPrefixes[$i] = $commonStaticPrefix; - $this->prefixes[$i] = $commonPrefix; - $this->items[$i] = $child; - } - - return; - } - - // No optimised case was found, in this case we simple add the route for possible - // grouping when new routes are added. - $this->staticPrefixes[] = $staticPrefix; - $this->prefixes[] = $prefix; - $this->items[] = $route; - } - - /** - * Linearizes back a set of nested routes into a collection. - */ - public function populateCollection(RouteCollection $routes): RouteCollection - { - foreach ($this->items as $route) { - if ($route instanceof self) { - $route->populateCollection($routes); - } else { - $routes->add(...$route); - } - } - - return $routes; - } - - /** - * Gets the full and static common prefixes between two route patterns. - * - * The static prefix stops at last at the first opening bracket. - */ - private function getCommonPrefix(string $prefix, string $anotherPrefix): array - { - $baseLength = \strlen($this->prefix); - $end = min(\strlen($prefix), \strlen($anotherPrefix)); - $staticLength = null; - set_error_handler([__CLASS__, 'handleError']); - - try { - for ($i = $baseLength; $i < $end && $prefix[$i] === $anotherPrefix[$i]; ++$i) { - if ('(' === $prefix[$i]) { - $staticLength = $staticLength ?? $i; - for ($j = 1 + $i, $n = 1; $j < $end && 0 < $n; ++$j) { - if ($prefix[$j] !== $anotherPrefix[$j]) { - break 2; - } - if ('(' === $prefix[$j]) { - ++$n; - } elseif (')' === $prefix[$j]) { - --$n; - } elseif ('\\' === $prefix[$j] && (++$j === $end || $prefix[$j] !== $anotherPrefix[$j])) { - --$j; - break; - } - } - if (0 < $n) { - break; - } - if (('?' === ($prefix[$j] ?? '') || '?' === ($anotherPrefix[$j] ?? '')) && ($prefix[$j] ?? '') !== ($anotherPrefix[$j] ?? '')) { - break; - } - $subPattern = substr($prefix, $i, $j - $i); - if ($prefix !== $anotherPrefix && !preg_match('/^\(\[[^\]]++\]\+\+\)$/', $subPattern) && !preg_match('{(?<!'.$subPattern.')}', '')) { - // sub-patterns of variable length are not considered as common prefixes because their greediness would break in-order matching - break; - } - $i = $j - 1; - } elseif ('\\' === $prefix[$i] && (++$i === $end || $prefix[$i] !== $anotherPrefix[$i])) { - --$i; - break; - } - } - } finally { - restore_error_handler(); - } - if ($i < $end && 0b10 === (\ord($prefix[$i]) >> 6) && preg_match('//u', $prefix.' '.$anotherPrefix)) { - do { - // Prevent cutting in the middle of an UTF-8 characters - --$i; - } while (0b10 === (\ord($prefix[$i]) >> 6)); - } - - return [substr($prefix, 0, $i), substr($prefix, 0, $staticLength ?? $i)]; - } - - public static function handleError(int $type, string $msg) - { - return str_contains($msg, 'Compilation failed: lookbehind assertion is not fixed length'); - } -} diff --git a/lib/symfony/routing/Matcher/ExpressionLanguageProvider.php b/lib/symfony/routing/Matcher/ExpressionLanguageProvider.php deleted file mode 100644 index 96bb7babf..000000000 --- a/lib/symfony/routing/Matcher/ExpressionLanguageProvider.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher; - -use Symfony\Component\ExpressionLanguage\ExpressionFunction; -use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; -use Symfony\Contracts\Service\ServiceProviderInterface; - -/** - * Exposes functions defined in the request context to route conditions. - * - * @author Ahmed TAILOULOUTE <ahmed.tailouloute@gmail.com> - */ -class ExpressionLanguageProvider implements ExpressionFunctionProviderInterface -{ - private $functions; - - public function __construct(ServiceProviderInterface $functions) - { - $this->functions = $functions; - } - - /** - * {@inheritdoc} - */ - public function getFunctions() - { - $functions = []; - - foreach ($this->functions->getProvidedServices() as $function => $type) { - $functions[] = new ExpressionFunction( - $function, - static function (...$args) use ($function) { - return sprintf('($context->getParameter(\'_functions\')->get(%s)(%s))', var_export($function, true), implode(', ', $args)); - }, - function ($values, ...$args) use ($function) { - return $values['context']->getParameter('_functions')->get($function)(...$args); - } - ); - } - - return $functions; - } - - public function get(string $function): callable - { - return $this->functions->get($function); - } -} diff --git a/lib/symfony/routing/Matcher/RedirectableUrlMatcher.php b/lib/symfony/routing/Matcher/RedirectableUrlMatcher.php deleted file mode 100644 index 3cd7c81a6..000000000 --- a/lib/symfony/routing/Matcher/RedirectableUrlMatcher.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher; - -use Symfony\Component\Routing\Exception\ExceptionInterface; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -abstract class RedirectableUrlMatcher extends UrlMatcher implements RedirectableUrlMatcherInterface -{ - /** - * {@inheritdoc} - */ - public function match(string $pathinfo) - { - try { - return parent::match($pathinfo); - } catch (ResourceNotFoundException $e) { - if (!\in_array($this->context->getMethod(), ['HEAD', 'GET'], true)) { - throw $e; - } - - if ($this->allowSchemes) { - redirect_scheme: - $scheme = $this->context->getScheme(); - $this->context->setScheme(current($this->allowSchemes)); - try { - $ret = parent::match($pathinfo); - - return $this->redirect($pathinfo, $ret['_route'] ?? null, $this->context->getScheme()) + $ret; - } catch (ExceptionInterface $e2) { - throw $e; - } finally { - $this->context->setScheme($scheme); - } - } elseif ('/' === $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/') { - throw $e; - } else { - try { - $pathinfo = $trimmedPathinfo === $pathinfo ? $pathinfo.'/' : $trimmedPathinfo; - $ret = parent::match($pathinfo); - - return $this->redirect($pathinfo, $ret['_route'] ?? null) + $ret; - } catch (ExceptionInterface $e2) { - if ($this->allowSchemes) { - goto redirect_scheme; - } - throw $e; - } - } - } - } -} diff --git a/lib/symfony/routing/Matcher/RedirectableUrlMatcherInterface.php b/lib/symfony/routing/Matcher/RedirectableUrlMatcherInterface.php deleted file mode 100644 index d07f42093..000000000 --- a/lib/symfony/routing/Matcher/RedirectableUrlMatcherInterface.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher; - -/** - * RedirectableUrlMatcherInterface knows how to redirect the user. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface RedirectableUrlMatcherInterface -{ - /** - * Redirects the user to another URL and returns the parameters for the redirection. - * - * @param string $path The path info to redirect to - * @param string $route The route name that matched - * @param string|null $scheme The URL scheme (null to keep the current one) - * - * @return array - */ - public function redirect(string $path, string $route, string $scheme = null); -} diff --git a/lib/symfony/routing/Matcher/RequestMatcherInterface.php b/lib/symfony/routing/Matcher/RequestMatcherInterface.php deleted file mode 100644 index c05016e82..000000000 --- a/lib/symfony/routing/Matcher/RequestMatcherInterface.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Routing\Exception\MethodNotAllowedException; -use Symfony\Component\Routing\Exception\NoConfigurationException; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; - -/** - * RequestMatcherInterface is the interface that all request matcher classes must implement. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface RequestMatcherInterface -{ - /** - * Tries to match a request with a set of routes. - * - * If the matcher cannot find information, it must throw one of the exceptions documented - * below. - * - * @return array - * - * @throws NoConfigurationException If no routing configuration could be found - * @throws ResourceNotFoundException If no matching resource could be found - * @throws MethodNotAllowedException If a matching resource was found but the request method is not allowed - */ - public function matchRequest(Request $request); -} diff --git a/lib/symfony/routing/Matcher/TraceableUrlMatcher.php b/lib/symfony/routing/Matcher/TraceableUrlMatcher.php deleted file mode 100644 index 9e8c4c42d..000000000 --- a/lib/symfony/routing/Matcher/TraceableUrlMatcher.php +++ /dev/null @@ -1,164 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Routing\Exception\ExceptionInterface; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * TraceableUrlMatcher helps debug path info matching by tracing the match. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class TraceableUrlMatcher extends UrlMatcher -{ - public const ROUTE_DOES_NOT_MATCH = 0; - public const ROUTE_ALMOST_MATCHES = 1; - public const ROUTE_MATCHES = 2; - - protected $traces; - - public function getTraces(string $pathinfo) - { - $this->traces = []; - - try { - $this->match($pathinfo); - } catch (ExceptionInterface $e) { - } - - return $this->traces; - } - - public function getTracesForRequest(Request $request) - { - $this->request = $request; - $traces = $this->getTraces($request->getPathInfo()); - $this->request = null; - - return $traces; - } - - protected function matchCollection(string $pathinfo, RouteCollection $routes) - { - // HEAD and GET are equivalent as per RFC - if ('HEAD' === $method = $this->context->getMethod()) { - $method = 'GET'; - } - $supportsTrailingSlash = 'GET' === $method && $this instanceof RedirectableUrlMatcherInterface; - $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/'; - - foreach ($routes as $name => $route) { - $compiledRoute = $route->compile(); - $staticPrefix = rtrim($compiledRoute->getStaticPrefix(), '/'); - $requiredMethods = $route->getMethods(); - - // check the static prefix of the URL first. Only use the more expensive preg_match when it matches - if ('' !== $staticPrefix && !str_starts_with($trimmedPathinfo, $staticPrefix)) { - $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route); - continue; - } - $regex = $compiledRoute->getRegex(); - - $pos = strrpos($regex, '$'); - $hasTrailingSlash = '/' === $regex[$pos - 1]; - $regex = substr_replace($regex, '/?$', $pos - $hasTrailingSlash, 1 + $hasTrailingSlash); - - if (!preg_match($regex, $pathinfo, $matches)) { - // does it match without any requirements? - $r = new Route($route->getPath(), $route->getDefaults(), [], $route->getOptions()); - $cr = $r->compile(); - if (!preg_match($cr->getRegex(), $pathinfo)) { - $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route); - - continue; - } - - foreach ($route->getRequirements() as $n => $regex) { - $r = new Route($route->getPath(), $route->getDefaults(), [$n => $regex], $route->getOptions()); - $cr = $r->compile(); - - if (\in_array($n, $cr->getVariables()) && !preg_match($cr->getRegex(), $pathinfo)) { - $this->addTrace(sprintf('Requirement for "%s" does not match (%s)', $n, $regex), self::ROUTE_ALMOST_MATCHES, $name, $route); - - continue 2; - } - } - - continue; - } - - $hasTrailingVar = $trimmedPathinfo !== $pathinfo && preg_match('#\{\w+\}/?$#', $route->getPath()); - - if ($hasTrailingVar && ($hasTrailingSlash || (null === $m = $matches[\count($compiledRoute->getPathVariables())] ?? null) || '/' !== ($m[-1] ?? '/')) && preg_match($regex, $trimmedPathinfo, $m)) { - if ($hasTrailingSlash) { - $matches = $m; - } else { - $hasTrailingVar = false; - } - } - - $hostMatches = []; - if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) { - $this->addTrace(sprintf('Host "%s" does not match the requirement ("%s")', $this->context->getHost(), $route->getHost()), self::ROUTE_ALMOST_MATCHES, $name, $route); - continue; - } - - $status = $this->handleRouteRequirements($pathinfo, $name, $route); - - if (self::REQUIREMENT_MISMATCH === $status[0]) { - $this->addTrace(sprintf('Condition "%s" does not evaluate to "true"', $route->getCondition()), self::ROUTE_ALMOST_MATCHES, $name, $route); - continue; - } - - if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) { - if ($supportsTrailingSlash && (!$requiredMethods || \in_array('GET', $requiredMethods))) { - $this->addTrace('Route matches!', self::ROUTE_MATCHES, $name, $route); - - return $this->allow = $this->allowSchemes = []; - } - $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route); - continue; - } - - if ($route->getSchemes() && !$route->hasScheme($this->context->getScheme())) { - $this->allowSchemes = array_merge($this->allowSchemes, $route->getSchemes()); - $this->addTrace(sprintf('Scheme "%s" does not match any of the required schemes (%s)', $this->context->getScheme(), implode(', ', $route->getSchemes())), self::ROUTE_ALMOST_MATCHES, $name, $route); - continue; - } - - if ($requiredMethods && !\in_array($method, $requiredMethods)) { - $this->allow = array_merge($this->allow, $requiredMethods); - $this->addTrace(sprintf('Method "%s" does not match any of the required methods (%s)', $this->context->getMethod(), implode(', ', $requiredMethods)), self::ROUTE_ALMOST_MATCHES, $name, $route); - continue; - } - - $this->addTrace('Route matches!', self::ROUTE_MATCHES, $name, $route); - - return $this->getAttributes($route, $name, array_replace($matches, $hostMatches, $status[1] ?? [])); - } - - return []; - } - - private function addTrace(string $log, int $level = self::ROUTE_DOES_NOT_MATCH, string $name = null, Route $route = null) - { - $this->traces[] = [ - 'log' => $log, - 'name' => $name, - 'level' => $level, - 'path' => null !== $route ? $route->getPath() : null, - ]; - } -} diff --git a/lib/symfony/routing/Matcher/UrlMatcher.php b/lib/symfony/routing/Matcher/UrlMatcher.php deleted file mode 100644 index f076a2f5e..000000000 --- a/lib/symfony/routing/Matcher/UrlMatcher.php +++ /dev/null @@ -1,279 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher; - -use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; -use Symfony\Component\ExpressionLanguage\ExpressionLanguage; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Routing\Exception\MethodNotAllowedException; -use Symfony\Component\Routing\Exception\NoConfigurationException; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; -use Symfony\Component\Routing\RequestContext; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * UrlMatcher matches URL based on a set of routes. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface -{ - public const REQUIREMENT_MATCH = 0; - public const REQUIREMENT_MISMATCH = 1; - public const ROUTE_MATCH = 2; - - /** @var RequestContext */ - protected $context; - - /** - * Collects HTTP methods that would be allowed for the request. - */ - protected $allow = []; - - /** - * Collects URI schemes that would be allowed for the request. - * - * @internal - */ - protected $allowSchemes = []; - - protected $routes; - protected $request; - protected $expressionLanguage; - - /** - * @var ExpressionFunctionProviderInterface[] - */ - protected $expressionLanguageProviders = []; - - public function __construct(RouteCollection $routes, RequestContext $context) - { - $this->routes = $routes; - $this->context = $context; - } - - /** - * {@inheritdoc} - */ - public function setContext(RequestContext $context) - { - $this->context = $context; - } - - /** - * {@inheritdoc} - */ - public function getContext() - { - return $this->context; - } - - /** - * {@inheritdoc} - */ - public function match(string $pathinfo) - { - $this->allow = $this->allowSchemes = []; - - if ($ret = $this->matchCollection(rawurldecode($pathinfo) ?: '/', $this->routes)) { - return $ret; - } - - if ('/' === $pathinfo && !$this->allow && !$this->allowSchemes) { - throw new NoConfigurationException(); - } - - throw 0 < \count($this->allow) ? new MethodNotAllowedException(array_unique($this->allow)) : new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo)); - } - - /** - * {@inheritdoc} - */ - public function matchRequest(Request $request) - { - $this->request = $request; - - $ret = $this->match($request->getPathInfo()); - - $this->request = null; - - return $ret; - } - - public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) - { - $this->expressionLanguageProviders[] = $provider; - } - - /** - * Tries to match a URL with a set of routes. - * - * @param string $pathinfo The path info to be parsed - * - * @return array - * - * @throws NoConfigurationException If no routing configuration could be found - * @throws ResourceNotFoundException If the resource could not be found - * @throws MethodNotAllowedException If the resource was found but the request method is not allowed - */ - protected function matchCollection(string $pathinfo, RouteCollection $routes) - { - // HEAD and GET are equivalent as per RFC - if ('HEAD' === $method = $this->context->getMethod()) { - $method = 'GET'; - } - $supportsTrailingSlash = 'GET' === $method && $this instanceof RedirectableUrlMatcherInterface; - $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/'; - - foreach ($routes as $name => $route) { - $compiledRoute = $route->compile(); - $staticPrefix = rtrim($compiledRoute->getStaticPrefix(), '/'); - $requiredMethods = $route->getMethods(); - - // check the static prefix of the URL first. Only use the more expensive preg_match when it matches - if ('' !== $staticPrefix && !str_starts_with($trimmedPathinfo, $staticPrefix)) { - continue; - } - $regex = $compiledRoute->getRegex(); - - $pos = strrpos($regex, '$'); - $hasTrailingSlash = '/' === $regex[$pos - 1]; - $regex = substr_replace($regex, '/?$', $pos - $hasTrailingSlash, 1 + $hasTrailingSlash); - - if (!preg_match($regex, $pathinfo, $matches)) { - continue; - } - - $hasTrailingVar = $trimmedPathinfo !== $pathinfo && preg_match('#\{\w+\}/?$#', $route->getPath()); - - if ($hasTrailingVar && ($hasTrailingSlash || (null === $m = $matches[\count($compiledRoute->getPathVariables())] ?? null) || '/' !== ($m[-1] ?? '/')) && preg_match($regex, $trimmedPathinfo, $m)) { - if ($hasTrailingSlash) { - $matches = $m; - } else { - $hasTrailingVar = false; - } - } - - $hostMatches = []; - if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) { - continue; - } - - $status = $this->handleRouteRequirements($pathinfo, $name, $route); - - if (self::REQUIREMENT_MISMATCH === $status[0]) { - continue; - } - - if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) { - if ($supportsTrailingSlash && (!$requiredMethods || \in_array('GET', $requiredMethods))) { - return $this->allow = $this->allowSchemes = []; - } - continue; - } - - if ($route->getSchemes() && !$route->hasScheme($this->context->getScheme())) { - $this->allowSchemes = array_merge($this->allowSchemes, $route->getSchemes()); - continue; - } - - if ($requiredMethods && !\in_array($method, $requiredMethods)) { - $this->allow = array_merge($this->allow, $requiredMethods); - continue; - } - - return $this->getAttributes($route, $name, array_replace($matches, $hostMatches, $status[1] ?? [])); - } - - return []; - } - - /** - * Returns an array of values to use as request attributes. - * - * As this method requires the Route object, it is not available - * in matchers that do not have access to the matched Route instance - * (like the PHP and Apache matcher dumpers). - * - * @return array - */ - protected function getAttributes(Route $route, string $name, array $attributes) - { - $defaults = $route->getDefaults(); - if (isset($defaults['_canonical_route'])) { - $name = $defaults['_canonical_route']; - unset($defaults['_canonical_route']); - } - $attributes['_route'] = $name; - - return $this->mergeDefaults($attributes, $defaults); - } - - /** - * Handles specific route requirements. - * - * @return array The first element represents the status, the second contains additional information - */ - protected function handleRouteRequirements(string $pathinfo, string $name, Route $route) - { - // expression condition - if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), ['context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)])) { - return [self::REQUIREMENT_MISMATCH, null]; - } - - return [self::REQUIREMENT_MATCH, null]; - } - - /** - * Get merged default parameters. - * - * @return array - */ - protected function mergeDefaults(array $params, array $defaults) - { - foreach ($params as $key => $value) { - if (!\is_int($key) && null !== $value) { - $defaults[$key] = $value; - } - } - - return $defaults; - } - - protected function getExpressionLanguage() - { - if (null === $this->expressionLanguage) { - if (!class_exists(ExpressionLanguage::class)) { - throw new \LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); - } - $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders); - } - - return $this->expressionLanguage; - } - - /** - * @internal - */ - protected function createRequest(string $pathinfo): ?Request - { - if (!class_exists(Request::class)) { - return null; - } - - return Request::create($this->context->getScheme().'://'.$this->context->getHost().$this->context->getBaseUrl().$pathinfo, $this->context->getMethod(), $this->context->getParameters(), [], [], [ - 'SCRIPT_FILENAME' => $this->context->getBaseUrl(), - 'SCRIPT_NAME' => $this->context->getBaseUrl(), - ]); - } -} diff --git a/lib/symfony/routing/Matcher/UrlMatcherInterface.php b/lib/symfony/routing/Matcher/UrlMatcherInterface.php deleted file mode 100644 index 0a5be9744..000000000 --- a/lib/symfony/routing/Matcher/UrlMatcherInterface.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher; - -use Symfony\Component\Routing\Exception\MethodNotAllowedException; -use Symfony\Component\Routing\Exception\NoConfigurationException; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; -use Symfony\Component\Routing\RequestContextAwareInterface; - -/** - * UrlMatcherInterface is the interface that all URL matcher classes must implement. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface UrlMatcherInterface extends RequestContextAwareInterface -{ - /** - * Tries to match a URL path with a set of routes. - * - * If the matcher cannot find information, it must throw one of the exceptions documented - * below. - * - * @param string $pathinfo The path info to be parsed (raw format, i.e. not urldecoded) - * - * @return array - * - * @throws NoConfigurationException If no routing configuration could be found - * @throws ResourceNotFoundException If the resource could not be found - * @throws MethodNotAllowedException If the resource was found but the request method is not allowed - */ - public function match(string $pathinfo); -} diff --git a/lib/symfony/routing/README.md b/lib/symfony/routing/README.md deleted file mode 100644 index ae8284f54..000000000 --- a/lib/symfony/routing/README.md +++ /dev/null @@ -1,51 +0,0 @@ -Routing Component -================= - -The Routing component maps an HTTP request to a set of configuration variables. - -Getting Started ---------------- - -``` -$ composer require symfony/routing -``` - -```php -use App\Controller\BlogController; -use Symfony\Component\Routing\Generator\UrlGenerator; -use Symfony\Component\Routing\Matcher\UrlMatcher; -use Symfony\Component\Routing\RequestContext; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -$route = new Route('/blog/{slug}', ['_controller' => BlogController::class]); -$routes = new RouteCollection(); -$routes->add('blog_show', $route); - -$context = new RequestContext(); - -// Routing can match routes with incoming requests -$matcher = new UrlMatcher($routes, $context); -$parameters = $matcher->match('/blog/lorem-ipsum'); -// $parameters = [ -// '_controller' => 'App\Controller\BlogController', -// 'slug' => 'lorem-ipsum', -// '_route' => 'blog_show' -// ] - -// Routing can also generate URLs for a given route -$generator = new UrlGenerator($routes, $context); -$url = $generator->generate('blog_show', [ - 'slug' => 'my-blog-post', -]); -// $url = '/blog/my-blog-post' -``` - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/routing.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/lib/symfony/routing/RequestContext.php b/lib/symfony/routing/RequestContext.php deleted file mode 100644 index f54c430ee..000000000 --- a/lib/symfony/routing/RequestContext.php +++ /dev/null @@ -1,327 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -use Symfony\Component\HttpFoundation\Request; - -/** - * Holds information about the current request. - * - * This class implements a fluent interface. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Tobias Schultze <http://tobion.de> - */ -class RequestContext -{ - private $baseUrl; - private $pathInfo; - private $method; - private $host; - private $scheme; - private $httpPort; - private $httpsPort; - private $queryString; - private $parameters = []; - - public function __construct(string $baseUrl = '', string $method = 'GET', string $host = 'localhost', string $scheme = 'http', int $httpPort = 80, int $httpsPort = 443, string $path = '/', string $queryString = '') - { - $this->setBaseUrl($baseUrl); - $this->setMethod($method); - $this->setHost($host); - $this->setScheme($scheme); - $this->setHttpPort($httpPort); - $this->setHttpsPort($httpsPort); - $this->setPathInfo($path); - $this->setQueryString($queryString); - } - - public static function fromUri(string $uri, string $host = 'localhost', string $scheme = 'http', int $httpPort = 80, int $httpsPort = 443): self - { - $uri = parse_url($uri); - $scheme = $uri['scheme'] ?? $scheme; - $host = $uri['host'] ?? $host; - - if (isset($uri['port'])) { - if ('http' === $scheme) { - $httpPort = $uri['port']; - } elseif ('https' === $scheme) { - $httpsPort = $uri['port']; - } - } - - return new self($uri['path'] ?? '', 'GET', $host, $scheme, $httpPort, $httpsPort); - } - - /** - * Updates the RequestContext information based on a HttpFoundation Request. - * - * @return $this - */ - public function fromRequest(Request $request) - { - $this->setBaseUrl($request->getBaseUrl()); - $this->setPathInfo($request->getPathInfo()); - $this->setMethod($request->getMethod()); - $this->setHost($request->getHost()); - $this->setScheme($request->getScheme()); - $this->setHttpPort($request->isSecure() || null === $request->getPort() ? $this->httpPort : $request->getPort()); - $this->setHttpsPort($request->isSecure() && null !== $request->getPort() ? $request->getPort() : $this->httpsPort); - $this->setQueryString($request->server->get('QUERY_STRING', '')); - - return $this; - } - - /** - * Gets the base URL. - * - * @return string - */ - public function getBaseUrl() - { - return $this->baseUrl; - } - - /** - * Sets the base URL. - * - * @return $this - */ - public function setBaseUrl(string $baseUrl) - { - $this->baseUrl = rtrim($baseUrl, '/'); - - return $this; - } - - /** - * Gets the path info. - * - * @return string - */ - public function getPathInfo() - { - return $this->pathInfo; - } - - /** - * Sets the path info. - * - * @return $this - */ - public function setPathInfo(string $pathInfo) - { - $this->pathInfo = $pathInfo; - - return $this; - } - - /** - * Gets the HTTP method. - * - * The method is always an uppercased string. - * - * @return string - */ - public function getMethod() - { - return $this->method; - } - - /** - * Sets the HTTP method. - * - * @return $this - */ - public function setMethod(string $method) - { - $this->method = strtoupper($method); - - return $this; - } - - /** - * Gets the HTTP host. - * - * The host is always lowercased because it must be treated case-insensitive. - * - * @return string - */ - public function getHost() - { - return $this->host; - } - - /** - * Sets the HTTP host. - * - * @return $this - */ - public function setHost(string $host) - { - $this->host = strtolower($host); - - return $this; - } - - /** - * Gets the HTTP scheme. - * - * @return string - */ - public function getScheme() - { - return $this->scheme; - } - - /** - * Sets the HTTP scheme. - * - * @return $this - */ - public function setScheme(string $scheme) - { - $this->scheme = strtolower($scheme); - - return $this; - } - - /** - * Gets the HTTP port. - * - * @return int - */ - public function getHttpPort() - { - return $this->httpPort; - } - - /** - * Sets the HTTP port. - * - * @return $this - */ - public function setHttpPort(int $httpPort) - { - $this->httpPort = $httpPort; - - return $this; - } - - /** - * Gets the HTTPS port. - * - * @return int - */ - public function getHttpsPort() - { - return $this->httpsPort; - } - - /** - * Sets the HTTPS port. - * - * @return $this - */ - public function setHttpsPort(int $httpsPort) - { - $this->httpsPort = $httpsPort; - - return $this; - } - - /** - * Gets the query string without the "?". - * - * @return string - */ - public function getQueryString() - { - return $this->queryString; - } - - /** - * Sets the query string. - * - * @return $this - */ - public function setQueryString(?string $queryString) - { - // string cast to be fault-tolerant, accepting null - $this->queryString = (string) $queryString; - - return $this; - } - - /** - * Returns the parameters. - * - * @return array - */ - public function getParameters() - { - return $this->parameters; - } - - /** - * Sets the parameters. - * - * @param array $parameters The parameters - * - * @return $this - */ - public function setParameters(array $parameters) - { - $this->parameters = $parameters; - - return $this; - } - - /** - * Gets a parameter value. - * - * @return mixed - */ - public function getParameter(string $name) - { - return $this->parameters[$name] ?? null; - } - - /** - * Checks if a parameter value is set for the given parameter. - * - * @return bool - */ - public function hasParameter(string $name) - { - return \array_key_exists($name, $this->parameters); - } - - /** - * Sets a parameter value. - * - * @param mixed $parameter The parameter value - * - * @return $this - */ - public function setParameter(string $name, $parameter) - { - $this->parameters[$name] = $parameter; - - return $this; - } - - public function isSecure(): bool - { - return 'https' === $this->scheme; - } -} diff --git a/lib/symfony/routing/RequestContextAwareInterface.php b/lib/symfony/routing/RequestContextAwareInterface.php deleted file mode 100644 index 270a2b084..000000000 --- a/lib/symfony/routing/RequestContextAwareInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -interface RequestContextAwareInterface -{ - /** - * Sets the request context. - */ - public function setContext(RequestContext $context); - - /** - * Gets the request context. - * - * @return RequestContext - */ - public function getContext(); -} diff --git a/lib/symfony/routing/Route.php b/lib/symfony/routing/Route.php deleted file mode 100644 index c67bd2de5..000000000 --- a/lib/symfony/routing/Route.php +++ /dev/null @@ -1,507 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -/** - * A Route describes a route and its parameters. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Tobias Schultze <http://tobion.de> - */ -class Route implements \Serializable -{ - private $path = '/'; - private $host = ''; - private $schemes = []; - private $methods = []; - private $defaults = []; - private $requirements = []; - private $options = []; - private $condition = ''; - - /** - * @var CompiledRoute|null - */ - private $compiled; - - /** - * Constructor. - * - * Available options: - * - * * compiler_class: A class name able to compile this route instance (RouteCompiler by default) - * * utf8: Whether UTF-8 matching is enforced ot not - * - * @param string $path The path pattern to match - * @param array $defaults An array of default parameter values - * @param array $requirements An array of requirements for parameters (regexes) - * @param array $options An array of options - * @param string|null $host The host pattern to match - * @param string|string[] $schemes A required URI scheme or an array of restricted schemes - * @param string|string[] $methods A required HTTP method or an array of restricted methods - * @param string|null $condition A condition that should evaluate to true for the route to match - */ - public function __construct(string $path, array $defaults = [], array $requirements = [], array $options = [], ?string $host = '', $schemes = [], $methods = [], ?string $condition = '') - { - $this->setPath($path); - $this->addDefaults($defaults); - $this->addRequirements($requirements); - $this->setOptions($options); - $this->setHost($host); - $this->setSchemes($schemes); - $this->setMethods($methods); - $this->setCondition($condition); - } - - public function __serialize(): array - { - return [ - 'path' => $this->path, - 'host' => $this->host, - 'defaults' => $this->defaults, - 'requirements' => $this->requirements, - 'options' => $this->options, - 'schemes' => $this->schemes, - 'methods' => $this->methods, - 'condition' => $this->condition, - 'compiled' => $this->compiled, - ]; - } - - /** - * @internal - */ - final public function serialize(): string - { - return serialize($this->__serialize()); - } - - public function __unserialize(array $data): void - { - $this->path = $data['path']; - $this->host = $data['host']; - $this->defaults = $data['defaults']; - $this->requirements = $data['requirements']; - $this->options = $data['options']; - $this->schemes = $data['schemes']; - $this->methods = $data['methods']; - - if (isset($data['condition'])) { - $this->condition = $data['condition']; - } - if (isset($data['compiled'])) { - $this->compiled = $data['compiled']; - } - } - - /** - * @internal - */ - final public function unserialize($serialized) - { - $this->__unserialize(unserialize($serialized)); - } - - /** - * @return string - */ - public function getPath() - { - return $this->path; - } - - /** - * @return $this - */ - public function setPath(string $pattern) - { - $pattern = $this->extractInlineDefaultsAndRequirements($pattern); - - // A pattern must start with a slash and must not have multiple slashes at the beginning because the - // generated path for this route would be confused with a network path, e.g. '//domain.com/path'. - $this->path = '/'.ltrim(trim($pattern), '/'); - $this->compiled = null; - - return $this; - } - - /** - * @return string - */ - public function getHost() - { - return $this->host; - } - - /** - * @return $this - */ - public function setHost(?string $pattern) - { - $this->host = $this->extractInlineDefaultsAndRequirements((string) $pattern); - $this->compiled = null; - - return $this; - } - - /** - * Returns the lowercased schemes this route is restricted to. - * So an empty array means that any scheme is allowed. - * - * @return string[] - */ - public function getSchemes() - { - return $this->schemes; - } - - /** - * Sets the schemes (e.g. 'https') this route is restricted to. - * So an empty array means that any scheme is allowed. - * - * @param string|string[] $schemes The scheme or an array of schemes - * - * @return $this - */ - public function setSchemes($schemes) - { - $this->schemes = array_map('strtolower', (array) $schemes); - $this->compiled = null; - - return $this; - } - - /** - * Checks if a scheme requirement has been set. - * - * @return bool - */ - public function hasScheme(string $scheme) - { - return \in_array(strtolower($scheme), $this->schemes, true); - } - - /** - * Returns the uppercased HTTP methods this route is restricted to. - * So an empty array means that any method is allowed. - * - * @return string[] - */ - public function getMethods() - { - return $this->methods; - } - - /** - * Sets the HTTP methods (e.g. 'POST') this route is restricted to. - * So an empty array means that any method is allowed. - * - * @param string|string[] $methods The method or an array of methods - * - * @return $this - */ - public function setMethods($methods) - { - $this->methods = array_map('strtoupper', (array) $methods); - $this->compiled = null; - - return $this; - } - - /** - * @return array - */ - public function getOptions() - { - return $this->options; - } - - /** - * @return $this - */ - public function setOptions(array $options) - { - $this->options = [ - 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler', - ]; - - return $this->addOptions($options); - } - - /** - * @return $this - */ - public function addOptions(array $options) - { - foreach ($options as $name => $option) { - $this->options[$name] = $option; - } - $this->compiled = null; - - return $this; - } - - /** - * Sets an option value. - * - * @param mixed $value The option value - * - * @return $this - */ - public function setOption(string $name, $value) - { - $this->options[$name] = $value; - $this->compiled = null; - - return $this; - } - - /** - * Returns the option value or null when not found. - * - * @return mixed - */ - public function getOption(string $name) - { - return $this->options[$name] ?? null; - } - - /** - * @return bool - */ - public function hasOption(string $name) - { - return \array_key_exists($name, $this->options); - } - - /** - * @return array - */ - public function getDefaults() - { - return $this->defaults; - } - - /** - * @return $this - */ - public function setDefaults(array $defaults) - { - $this->defaults = []; - - return $this->addDefaults($defaults); - } - - /** - * @return $this - */ - public function addDefaults(array $defaults) - { - if (isset($defaults['_locale']) && $this->isLocalized()) { - unset($defaults['_locale']); - } - - foreach ($defaults as $name => $default) { - $this->defaults[$name] = $default; - } - $this->compiled = null; - - return $this; - } - - /** - * @return mixed - */ - public function getDefault(string $name) - { - return $this->defaults[$name] ?? null; - } - - /** - * @return bool - */ - public function hasDefault(string $name) - { - return \array_key_exists($name, $this->defaults); - } - - /** - * Sets a default value. - * - * @param mixed $default The default value - * - * @return $this - */ - public function setDefault(string $name, $default) - { - if ('_locale' === $name && $this->isLocalized()) { - return $this; - } - - $this->defaults[$name] = $default; - $this->compiled = null; - - return $this; - } - - /** - * @return array - */ - public function getRequirements() - { - return $this->requirements; - } - - /** - * @return $this - */ - public function setRequirements(array $requirements) - { - $this->requirements = []; - - return $this->addRequirements($requirements); - } - - /** - * @return $this - */ - public function addRequirements(array $requirements) - { - if (isset($requirements['_locale']) && $this->isLocalized()) { - unset($requirements['_locale']); - } - - foreach ($requirements as $key => $regex) { - $this->requirements[$key] = $this->sanitizeRequirement($key, $regex); - } - $this->compiled = null; - - return $this; - } - - /** - * @return string|null - */ - public function getRequirement(string $key) - { - return $this->requirements[$key] ?? null; - } - - /** - * @return bool - */ - public function hasRequirement(string $key) - { - return \array_key_exists($key, $this->requirements); - } - - /** - * @return $this - */ - public function setRequirement(string $key, string $regex) - { - if ('_locale' === $key && $this->isLocalized()) { - return $this; - } - - $this->requirements[$key] = $this->sanitizeRequirement($key, $regex); - $this->compiled = null; - - return $this; - } - - /** - * @return string - */ - public function getCondition() - { - return $this->condition; - } - - /** - * @return $this - */ - public function setCondition(?string $condition) - { - $this->condition = (string) $condition; - $this->compiled = null; - - return $this; - } - - /** - * Compiles the route. - * - * @return CompiledRoute - * - * @throws \LogicException If the Route cannot be compiled because the - * path or host pattern is invalid - * - * @see RouteCompiler which is responsible for the compilation process - */ - public function compile() - { - if (null !== $this->compiled) { - return $this->compiled; - } - - $class = $this->getOption('compiler_class'); - - return $this->compiled = $class::compile($this); - } - - private function extractInlineDefaultsAndRequirements(string $pattern): string - { - if (false === strpbrk($pattern, '?<')) { - return $pattern; - } - - return preg_replace_callback('#\{(!?)(\w++)(<.*?>)?(\?[^\}]*+)?\}#', function ($m) { - if (isset($m[4][0])) { - $this->setDefault($m[2], '?' !== $m[4] ? substr($m[4], 1) : null); - } - if (isset($m[3][0])) { - $this->setRequirement($m[2], substr($m[3], 1, -1)); - } - - return '{'.$m[1].$m[2].'}'; - }, $pattern); - } - - private function sanitizeRequirement(string $key, string $regex) - { - if ('' !== $regex) { - if ('^' === $regex[0]) { - $regex = substr($regex, 1); - } elseif (0 === strpos($regex, '\\A')) { - $regex = substr($regex, 2); - } - } - - if (str_ends_with($regex, '$')) { - $regex = substr($regex, 0, -1); - } elseif (\strlen($regex) - 2 === strpos($regex, '\\z')) { - $regex = substr($regex, 0, -2); - } - - if ('' === $regex) { - throw new \InvalidArgumentException(sprintf('Routing requirement for "%s" cannot be empty.', $key)); - } - - return $regex; - } - - private function isLocalized(): bool - { - return isset($this->defaults['_locale']) && isset($this->defaults['_canonical_route']) && ($this->requirements['_locale'] ?? null) === preg_quote($this->defaults['_locale']); - } -} diff --git a/lib/symfony/routing/RouteCollection.php b/lib/symfony/routing/RouteCollection.php deleted file mode 100644 index a0700bba3..000000000 --- a/lib/symfony/routing/RouteCollection.php +++ /dev/null @@ -1,383 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -use Symfony\Component\Config\Resource\ResourceInterface; -use Symfony\Component\Routing\Exception\InvalidArgumentException; -use Symfony\Component\Routing\Exception\RouteCircularReferenceException; - -/** - * A RouteCollection represents a set of Route instances. - * - * When adding a route at the end of the collection, an existing route - * with the same name is removed first. So there can only be one route - * with a given name. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Tobias Schultze <http://tobion.de> - * - * @implements \IteratorAggregate<string, Route> - */ -class RouteCollection implements \IteratorAggregate, \Countable -{ - /** - * @var array<string, Route> - */ - private $routes = []; - - /** - * @var array<string, Alias> - */ - private $aliases = []; - - /** - * @var array<string, ResourceInterface> - */ - private $resources = []; - - /** - * @var array<string, int> - */ - private $priorities = []; - - public function __clone() - { - foreach ($this->routes as $name => $route) { - $this->routes[$name] = clone $route; - } - - foreach ($this->aliases as $name => $alias) { - $this->aliases[$name] = clone $alias; - } - } - - /** - * Gets the current RouteCollection as an Iterator that includes all routes. - * - * It implements \IteratorAggregate. - * - * @see all() - * - * @return \ArrayIterator<string, Route> - */ - #[\ReturnTypeWillChange] - public function getIterator() - { - return new \ArrayIterator($this->all()); - } - - /** - * Gets the number of Routes in this collection. - * - * @return int - */ - #[\ReturnTypeWillChange] - public function count() - { - return \count($this->routes); - } - - /** - * @param int $priority - */ - public function add(string $name, Route $route/* , int $priority = 0 */) - { - if (\func_num_args() < 3 && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface && !$this instanceof \Mockery\MockInterface) { - trigger_deprecation('symfony/routing', '5.1', 'The "%s()" method will have a new "int $priority = 0" argument in version 6.0, not defining it is deprecated.', __METHOD__); - } - - unset($this->routes[$name], $this->priorities[$name], $this->aliases[$name]); - - $this->routes[$name] = $route; - - if ($priority = 3 <= \func_num_args() ? func_get_arg(2) : 0) { - $this->priorities[$name] = $priority; - } - } - - /** - * Returns all routes in this collection. - * - * @return array<string, Route> - */ - public function all() - { - if ($this->priorities) { - $priorities = $this->priorities; - $keysOrder = array_flip(array_keys($this->routes)); - uksort($this->routes, static function ($n1, $n2) use ($priorities, $keysOrder) { - return (($priorities[$n2] ?? 0) <=> ($priorities[$n1] ?? 0)) ?: ($keysOrder[$n1] <=> $keysOrder[$n2]); - }); - } - - return $this->routes; - } - - /** - * Gets a route by name. - * - * @return Route|null - */ - public function get(string $name) - { - $visited = []; - while (null !== $alias = $this->aliases[$name] ?? null) { - if (false !== $searchKey = array_search($name, $visited)) { - $visited[] = $name; - - throw new RouteCircularReferenceException($name, \array_slice($visited, $searchKey)); - } - - if ($alias->isDeprecated()) { - $deprecation = $alias->getDeprecation($name); - - trigger_deprecation($deprecation['package'], $deprecation['version'], $deprecation['message']); - } - - $visited[] = $name; - $name = $alias->getId(); - } - - return $this->routes[$name] ?? null; - } - - /** - * Removes a route or an array of routes by name from the collection. - * - * @param string|string[] $name The route name or an array of route names - */ - public function remove($name) - { - foreach ((array) $name as $n) { - unset($this->routes[$n], $this->priorities[$n], $this->aliases[$n]); - } - } - - /** - * Adds a route collection at the end of the current set by appending all - * routes of the added collection. - */ - public function addCollection(self $collection) - { - // we need to remove all routes with the same names first because just replacing them - // would not place the new route at the end of the merged array - foreach ($collection->all() as $name => $route) { - unset($this->routes[$name], $this->priorities[$name], $this->aliases[$name]); - $this->routes[$name] = $route; - - if (isset($collection->priorities[$name])) { - $this->priorities[$name] = $collection->priorities[$name]; - } - } - - foreach ($collection->getAliases() as $name => $alias) { - unset($this->routes[$name], $this->priorities[$name], $this->aliases[$name]); - - $this->aliases[$name] = $alias; - } - - foreach ($collection->getResources() as $resource) { - $this->addResource($resource); - } - } - - /** - * Adds a prefix to the path of all child routes. - */ - public function addPrefix(string $prefix, array $defaults = [], array $requirements = []) - { - $prefix = trim(trim($prefix), '/'); - - if ('' === $prefix) { - return; - } - - foreach ($this->routes as $route) { - $route->setPath('/'.$prefix.$route->getPath()); - $route->addDefaults($defaults); - $route->addRequirements($requirements); - } - } - - /** - * Adds a prefix to the name of all the routes within in the collection. - */ - public function addNamePrefix(string $prefix) - { - $prefixedRoutes = []; - $prefixedPriorities = []; - $prefixedAliases = []; - - foreach ($this->routes as $name => $route) { - $prefixedRoutes[$prefix.$name] = $route; - if (null !== $canonicalName = $route->getDefault('_canonical_route')) { - $route->setDefault('_canonical_route', $prefix.$canonicalName); - } - if (isset($this->priorities[$name])) { - $prefixedPriorities[$prefix.$name] = $this->priorities[$name]; - } - } - - foreach ($this->aliases as $name => $alias) { - $prefixedAliases[$prefix.$name] = $alias->withId($prefix.$alias->getId()); - } - - $this->routes = $prefixedRoutes; - $this->priorities = $prefixedPriorities; - $this->aliases = $prefixedAliases; - } - - /** - * Sets the host pattern on all routes. - */ - public function setHost(?string $pattern, array $defaults = [], array $requirements = []) - { - foreach ($this->routes as $route) { - $route->setHost($pattern); - $route->addDefaults($defaults); - $route->addRequirements($requirements); - } - } - - /** - * Sets a condition on all routes. - * - * Existing conditions will be overridden. - */ - public function setCondition(?string $condition) - { - foreach ($this->routes as $route) { - $route->setCondition($condition); - } - } - - /** - * Adds defaults to all routes. - * - * An existing default value under the same name in a route will be overridden. - */ - public function addDefaults(array $defaults) - { - if ($defaults) { - foreach ($this->routes as $route) { - $route->addDefaults($defaults); - } - } - } - - /** - * Adds requirements to all routes. - * - * An existing requirement under the same name in a route will be overridden. - */ - public function addRequirements(array $requirements) - { - if ($requirements) { - foreach ($this->routes as $route) { - $route->addRequirements($requirements); - } - } - } - - /** - * Adds options to all routes. - * - * An existing option value under the same name in a route will be overridden. - */ - public function addOptions(array $options) - { - if ($options) { - foreach ($this->routes as $route) { - $route->addOptions($options); - } - } - } - - /** - * Sets the schemes (e.g. 'https') all child routes are restricted to. - * - * @param string|string[] $schemes The scheme or an array of schemes - */ - public function setSchemes($schemes) - { - foreach ($this->routes as $route) { - $route->setSchemes($schemes); - } - } - - /** - * Sets the HTTP methods (e.g. 'POST') all child routes are restricted to. - * - * @param string|string[] $methods The method or an array of methods - */ - public function setMethods($methods) - { - foreach ($this->routes as $route) { - $route->setMethods($methods); - } - } - - /** - * Returns an array of resources loaded to build this collection. - * - * @return ResourceInterface[] - */ - public function getResources() - { - return array_values($this->resources); - } - - /** - * Adds a resource for this collection. If the resource already exists - * it is not added. - */ - public function addResource(ResourceInterface $resource) - { - $key = (string) $resource; - - if (!isset($this->resources[$key])) { - $this->resources[$key] = $resource; - } - } - - /** - * Sets an alias for an existing route. - * - * @param string $name The alias to create - * @param string $alias The route to alias - * - * @throws InvalidArgumentException if the alias is for itself - */ - public function addAlias(string $name, string $alias): Alias - { - if ($name === $alias) { - throw new InvalidArgumentException(sprintf('Route alias "%s" can not reference itself.', $name)); - } - - unset($this->routes[$name], $this->priorities[$name]); - - return $this->aliases[$name] = new Alias($alias); - } - - /** - * @return array<string, Alias> - */ - public function getAliases(): array - { - return $this->aliases; - } - - public function getAlias(string $name): ?Alias - { - return $this->aliases[$name] ?? null; - } -} diff --git a/lib/symfony/routing/RouteCollectionBuilder.php b/lib/symfony/routing/RouteCollectionBuilder.php deleted file mode 100644 index d7eed31eb..000000000 --- a/lib/symfony/routing/RouteCollectionBuilder.php +++ /dev/null @@ -1,364 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -use Symfony\Component\Config\Exception\LoaderLoadException; -use Symfony\Component\Config\Loader\LoaderInterface; -use Symfony\Component\Config\Resource\ResourceInterface; -use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; - -trigger_deprecation('symfony/routing', '5.1', 'The "%s" class is deprecated, use "%s" instead.', RouteCollectionBuilder::class, RoutingConfigurator::class); - -/** - * Helps add and import routes into a RouteCollection. - * - * @author Ryan Weaver <ryan@knpuniversity.com> - * - * @deprecated since Symfony 5.1, use RoutingConfigurator instead - */ -class RouteCollectionBuilder -{ - /** - * @var Route[]|RouteCollectionBuilder[] - */ - private $routes = []; - - private $loader; - private $defaults = []; - private $prefix; - private $host; - private $condition; - private $requirements = []; - private $options = []; - private $schemes; - private $methods; - private $resources = []; - - public function __construct(LoaderInterface $loader = null) - { - $this->loader = $loader; - } - - /** - * Import an external routing resource and returns the RouteCollectionBuilder. - * - * $routes->import('blog.yml', '/blog'); - * - * @param mixed $resource - * - * @return self - * - * @throws LoaderLoadException - */ - public function import($resource, string $prefix = '/', string $type = null) - { - /** @var RouteCollection[] $collections */ - $collections = $this->load($resource, $type); - - // create a builder from the RouteCollection - $builder = $this->createBuilder(); - - foreach ($collections as $collection) { - if (null === $collection) { - continue; - } - - foreach ($collection->all() as $name => $route) { - $builder->addRoute($route, $name); - } - - foreach ($collection->getResources() as $resource) { - $builder->addResource($resource); - } - } - - // mount into this builder - $this->mount($prefix, $builder); - - return $builder; - } - - /** - * Adds a route and returns it for future modification. - * - * @return Route - */ - public function add(string $path, string $controller, string $name = null) - { - $route = new Route($path); - $route->setDefault('_controller', $controller); - $this->addRoute($route, $name); - - return $route; - } - - /** - * Returns a RouteCollectionBuilder that can be configured and then added with mount(). - * - * @return self - */ - public function createBuilder() - { - return new self($this->loader); - } - - /** - * Add a RouteCollectionBuilder. - */ - public function mount(string $prefix, self $builder) - { - $builder->prefix = trim(trim($prefix), '/'); - $this->routes[] = $builder; - } - - /** - * Adds a Route object to the builder. - * - * @return $this - */ - public function addRoute(Route $route, string $name = null) - { - if (null === $name) { - // used as a flag to know which routes will need a name later - $name = '_unnamed_route_'.spl_object_hash($route); - } - - $this->routes[$name] = $route; - - return $this; - } - - /** - * Sets the host on all embedded routes (unless already set). - * - * @return $this - */ - public function setHost(?string $pattern) - { - $this->host = $pattern; - - return $this; - } - - /** - * Sets a condition on all embedded routes (unless already set). - * - * @return $this - */ - public function setCondition(?string $condition) - { - $this->condition = $condition; - - return $this; - } - - /** - * Sets a default value that will be added to all embedded routes (unless that - * default value is already set). - * - * @param mixed $value - * - * @return $this - */ - public function setDefault(string $key, $value) - { - $this->defaults[$key] = $value; - - return $this; - } - - /** - * Sets a requirement that will be added to all embedded routes (unless that - * requirement is already set). - * - * @param mixed $regex - * - * @return $this - */ - public function setRequirement(string $key, $regex) - { - $this->requirements[$key] = $regex; - - return $this; - } - - /** - * Sets an option that will be added to all embedded routes (unless that - * option is already set). - * - * @param mixed $value - * - * @return $this - */ - public function setOption(string $key, $value) - { - $this->options[$key] = $value; - - return $this; - } - - /** - * Sets the schemes on all embedded routes (unless already set). - * - * @param array|string $schemes - * - * @return $this - */ - public function setSchemes($schemes) - { - $this->schemes = $schemes; - - return $this; - } - - /** - * Sets the methods on all embedded routes (unless already set). - * - * @param array|string $methods - * - * @return $this - */ - public function setMethods($methods) - { - $this->methods = $methods; - - return $this; - } - - /** - * Adds a resource for this collection. - * - * @return $this - */ - private function addResource(ResourceInterface $resource): self - { - $this->resources[] = $resource; - - return $this; - } - - /** - * Creates the final RouteCollection and returns it. - * - * @return RouteCollection - */ - public function build() - { - $routeCollection = new RouteCollection(); - - foreach ($this->routes as $name => $route) { - if ($route instanceof Route) { - $route->setDefaults(array_merge($this->defaults, $route->getDefaults())); - $route->setOptions(array_merge($this->options, $route->getOptions())); - - foreach ($this->requirements as $key => $val) { - if (!$route->hasRequirement($key)) { - $route->setRequirement($key, $val); - } - } - - if (null !== $this->prefix) { - $route->setPath('/'.$this->prefix.$route->getPath()); - } - - if (!$route->getHost()) { - $route->setHost($this->host); - } - - if (!$route->getCondition()) { - $route->setCondition($this->condition); - } - - if (!$route->getSchemes()) { - $route->setSchemes($this->schemes); - } - - if (!$route->getMethods()) { - $route->setMethods($this->methods); - } - - // auto-generate the route name if it's been marked - if ('_unnamed_route_' === substr($name, 0, 15)) { - $name = $this->generateRouteName($route); - } - - $routeCollection->add($name, $route); - } else { - /* @var self $route */ - $subCollection = $route->build(); - if (null !== $this->prefix) { - $subCollection->addPrefix($this->prefix); - } - - $routeCollection->addCollection($subCollection); - } - } - - foreach ($this->resources as $resource) { - $routeCollection->addResource($resource); - } - - return $routeCollection; - } - - /** - * Generates a route name based on details of this route. - */ - private function generateRouteName(Route $route): string - { - $methods = implode('_', $route->getMethods()).'_'; - - $routeName = $methods.$route->getPath(); - $routeName = str_replace(['/', ':', '|', '-'], '_', $routeName); - $routeName = preg_replace('/[^a-z0-9A-Z_.]+/', '', $routeName); - - // Collapse consecutive underscores down into a single underscore. - $routeName = preg_replace('/_+/', '_', $routeName); - - return $routeName; - } - - /** - * Finds a loader able to load an imported resource and loads it. - * - * @param mixed $resource A resource - * @param string|null $type The resource type or null if unknown - * - * @return RouteCollection[] - * - * @throws LoaderLoadException If no loader is found - */ - private function load($resource, string $type = null): array - { - if (null === $this->loader) { - throw new \BadMethodCallException('Cannot import other routing resources: you must pass a LoaderInterface when constructing RouteCollectionBuilder.'); - } - - if ($this->loader->supports($resource, $type)) { - $collections = $this->loader->load($resource, $type); - - return \is_array($collections) ? $collections : [$collections]; - } - - if (null === $resolver = $this->loader->getResolver()) { - throw new LoaderLoadException($resource, null, 0, null, $type); - } - - if (false === $loader = $resolver->resolve($resource, $type)) { - throw new LoaderLoadException($resource, null, 0, null, $type); - } - - $collections = $loader->load($resource, $type); - - return \is_array($collections) ? $collections : [$collections]; - } -} diff --git a/lib/symfony/routing/RouteCompiler.php b/lib/symfony/routing/RouteCompiler.php deleted file mode 100644 index 7e78c2931..000000000 --- a/lib/symfony/routing/RouteCompiler.php +++ /dev/null @@ -1,346 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -/** - * RouteCompiler compiles Route instances to CompiledRoute instances. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Tobias Schultze <http://tobion.de> - */ -class RouteCompiler implements RouteCompilerInterface -{ - /** - * @deprecated since Symfony 5.1, to be removed in 6.0 - */ - public const REGEX_DELIMITER = '#'; - - /** - * This string defines the characters that are automatically considered separators in front of - * optional placeholders (with default and no static text following). Such a single separator - * can be left out together with the optional placeholder from matching and generating URLs. - */ - public const SEPARATORS = '/,;.:-_~+*=@|'; - - /** - * The maximum supported length of a PCRE subpattern name - * http://pcre.org/current/doc/html/pcre2pattern.html#SEC16. - * - * @internal - */ - public const VARIABLE_MAXIMUM_LENGTH = 32; - - /** - * {@inheritdoc} - * - * @throws \InvalidArgumentException if a path variable is named _fragment - * @throws \LogicException if a variable is referenced more than once - * @throws \DomainException if a variable name starts with a digit or if it is too long to be successfully used as - * a PCRE subpattern - */ - public static function compile(Route $route) - { - $hostVariables = []; - $variables = []; - $hostRegex = null; - $hostTokens = []; - - if ('' !== $host = $route->getHost()) { - $result = self::compilePattern($route, $host, true); - - $hostVariables = $result['variables']; - $variables = $hostVariables; - - $hostTokens = $result['tokens']; - $hostRegex = $result['regex']; - } - - $locale = $route->getDefault('_locale'); - if (null !== $locale && null !== $route->getDefault('_canonical_route') && preg_quote($locale) === $route->getRequirement('_locale')) { - $requirements = $route->getRequirements(); - unset($requirements['_locale']); - $route->setRequirements($requirements); - $route->setPath(str_replace('{_locale}', $locale, $route->getPath())); - } - - $path = $route->getPath(); - - $result = self::compilePattern($route, $path, false); - - $staticPrefix = $result['staticPrefix']; - - $pathVariables = $result['variables']; - - foreach ($pathVariables as $pathParam) { - if ('_fragment' === $pathParam) { - throw new \InvalidArgumentException(sprintf('Route pattern "%s" cannot contain "_fragment" as a path parameter.', $route->getPath())); - } - } - - $variables = array_merge($variables, $pathVariables); - - $tokens = $result['tokens']; - $regex = $result['regex']; - - return new CompiledRoute( - $staticPrefix, - $regex, - $tokens, - $pathVariables, - $hostRegex, - $hostTokens, - $hostVariables, - array_unique($variables) - ); - } - - private static function compilePattern(Route $route, string $pattern, bool $isHost): array - { - $tokens = []; - $variables = []; - $matches = []; - $pos = 0; - $defaultSeparator = $isHost ? '.' : '/'; - $useUtf8 = preg_match('//u', $pattern); - $needsUtf8 = $route->getOption('utf8'); - - if (!$needsUtf8 && $useUtf8 && preg_match('/[\x80-\xFF]/', $pattern)) { - throw new \LogicException(sprintf('Cannot use UTF-8 route patterns without setting the "utf8" option for route "%s".', $route->getPath())); - } - if (!$useUtf8 && $needsUtf8) { - throw new \LogicException(sprintf('Cannot mix UTF-8 requirements with non-UTF-8 pattern "%s".', $pattern)); - } - - // Match all variables enclosed in "{}" and iterate over them. But we only want to match the innermost variable - // in case of nested "{}", e.g. {foo{bar}}. This in ensured because \w does not match "{" or "}" itself. - preg_match_all('#\{(!)?(\w+)\}#', $pattern, $matches, \PREG_OFFSET_CAPTURE | \PREG_SET_ORDER); - foreach ($matches as $match) { - $important = $match[1][1] >= 0; - $varName = $match[2][0]; - // get all static text preceding the current variable - $precedingText = substr($pattern, $pos, $match[0][1] - $pos); - $pos = $match[0][1] + \strlen($match[0][0]); - - if (!\strlen($precedingText)) { - $precedingChar = ''; - } elseif ($useUtf8) { - preg_match('/.$/u', $precedingText, $precedingChar); - $precedingChar = $precedingChar[0]; - } else { - $precedingChar = substr($precedingText, -1); - } - $isSeparator = '' !== $precedingChar && str_contains(static::SEPARATORS, $precedingChar); - - // A PCRE subpattern name must start with a non-digit. Also a PHP variable cannot start with a digit so the - // variable would not be usable as a Controller action argument. - if (preg_match('/^\d/', $varName)) { - throw new \DomainException(sprintf('Variable name "%s" cannot start with a digit in route pattern "%s". Please use a different name.', $varName, $pattern)); - } - if (\in_array($varName, $variables)) { - throw new \LogicException(sprintf('Route pattern "%s" cannot reference variable name "%s" more than once.', $pattern, $varName)); - } - - if (\strlen($varName) > self::VARIABLE_MAXIMUM_LENGTH) { - throw new \DomainException(sprintf('Variable name "%s" cannot be longer than %d characters in route pattern "%s". Please use a shorter name.', $varName, self::VARIABLE_MAXIMUM_LENGTH, $pattern)); - } - - if ($isSeparator && $precedingText !== $precedingChar) { - $tokens[] = ['text', substr($precedingText, 0, -\strlen($precedingChar))]; - } elseif (!$isSeparator && '' !== $precedingText) { - $tokens[] = ['text', $precedingText]; - } - - $regexp = $route->getRequirement($varName); - if (null === $regexp) { - $followingPattern = (string) substr($pattern, $pos); - // Find the next static character after the variable that functions as a separator. By default, this separator and '/' - // are disallowed for the variable. This default requirement makes sure that optional variables can be matched at all - // and that the generating-matching-combination of URLs unambiguous, i.e. the params used for generating the URL are - // the same that will be matched. Example: new Route('/{page}.{_format}', ['_format' => 'html']) - // If {page} would also match the separating dot, {_format} would never match as {page} will eagerly consume everything. - // Also even if {_format} was not optional the requirement prevents that {page} matches something that was originally - // part of {_format} when generating the URL, e.g. _format = 'mobile.html'. - $nextSeparator = self::findNextSeparator($followingPattern, $useUtf8); - $regexp = sprintf( - '[^%s%s]+', - preg_quote($defaultSeparator), - $defaultSeparator !== $nextSeparator && '' !== $nextSeparator ? preg_quote($nextSeparator) : '' - ); - if (('' !== $nextSeparator && !preg_match('#^\{\w+\}#', $followingPattern)) || '' === $followingPattern) { - // When we have a separator, which is disallowed for the variable, we can optimize the regex with a possessive - // quantifier. This prevents useless backtracking of PCRE and improves performance by 20% for matching those patterns. - // Given the above example, there is no point in backtracking into {page} (that forbids the dot) when a dot must follow - // after it. This optimization cannot be applied when the next char is no real separator or when the next variable is - // directly adjacent, e.g. '/{x}{y}'. - $regexp .= '+'; - } - } else { - if (!preg_match('//u', $regexp)) { - $useUtf8 = false; - } elseif (!$needsUtf8 && preg_match('/[\x80-\xFF]|(?<!\\\\)\\\\(?:\\\\\\\\)*+(?-i:X|[pP][\{CLMNPSZ]|x\{[A-Fa-f0-9]{3})/', $regexp)) { - throw new \LogicException(sprintf('Cannot use UTF-8 route requirements without setting the "utf8" option for variable "%s" in pattern "%s".', $varName, $pattern)); - } - if (!$useUtf8 && $needsUtf8) { - throw new \LogicException(sprintf('Cannot mix UTF-8 requirement with non-UTF-8 charset for variable "%s" in pattern "%s".', $varName, $pattern)); - } - $regexp = self::transformCapturingGroupsToNonCapturings($regexp); - } - - if ($important) { - $token = ['variable', $isSeparator ? $precedingChar : '', $regexp, $varName, false, true]; - } else { - $token = ['variable', $isSeparator ? $precedingChar : '', $regexp, $varName]; - } - - $tokens[] = $token; - $variables[] = $varName; - } - - if ($pos < \strlen($pattern)) { - $tokens[] = ['text', substr($pattern, $pos)]; - } - - // find the first optional token - $firstOptional = \PHP_INT_MAX; - if (!$isHost) { - for ($i = \count($tokens) - 1; $i >= 0; --$i) { - $token = $tokens[$i]; - // variable is optional when it is not important and has a default value - if ('variable' === $token[0] && !($token[5] ?? false) && $route->hasDefault($token[3])) { - $firstOptional = $i; - } else { - break; - } - } - } - - // compute the matching regexp - $regexp = ''; - for ($i = 0, $nbToken = \count($tokens); $i < $nbToken; ++$i) { - $regexp .= self::computeRegexp($tokens, $i, $firstOptional); - } - $regexp = '{^'.$regexp.'$}sD'.($isHost ? 'i' : ''); - - // enable Utf8 matching if really required - if ($needsUtf8) { - $regexp .= 'u'; - for ($i = 0, $nbToken = \count($tokens); $i < $nbToken; ++$i) { - if ('variable' === $tokens[$i][0]) { - $tokens[$i][4] = true; - } - } - } - - return [ - 'staticPrefix' => self::determineStaticPrefix($route, $tokens), - 'regex' => $regexp, - 'tokens' => array_reverse($tokens), - 'variables' => $variables, - ]; - } - - /** - * Determines the longest static prefix possible for a route. - */ - private static function determineStaticPrefix(Route $route, array $tokens): string - { - if ('text' !== $tokens[0][0]) { - return ($route->hasDefault($tokens[0][3]) || '/' === $tokens[0][1]) ? '' : $tokens[0][1]; - } - - $prefix = $tokens[0][1]; - - if (isset($tokens[1][1]) && '/' !== $tokens[1][1] && false === $route->hasDefault($tokens[1][3])) { - $prefix .= $tokens[1][1]; - } - - return $prefix; - } - - /** - * Returns the next static character in the Route pattern that will serve as a separator (or the empty string when none available). - */ - private static function findNextSeparator(string $pattern, bool $useUtf8): string - { - if ('' == $pattern) { - // return empty string if pattern is empty or false (false which can be returned by substr) - return ''; - } - // first remove all placeholders from the pattern so we can find the next real static character - if ('' === $pattern = preg_replace('#\{\w+\}#', '', $pattern)) { - return ''; - } - if ($useUtf8) { - preg_match('/^./u', $pattern, $pattern); - } - - return str_contains(static::SEPARATORS, $pattern[0]) ? $pattern[0] : ''; - } - - /** - * Computes the regexp used to match a specific token. It can be static text or a subpattern. - * - * @param array $tokens The route tokens - * @param int $index The index of the current token - * @param int $firstOptional The index of the first optional token - */ - private static function computeRegexp(array $tokens, int $index, int $firstOptional): string - { - $token = $tokens[$index]; - if ('text' === $token[0]) { - // Text tokens - return preg_quote($token[1]); - } else { - // Variable tokens - if (0 === $index && 0 === $firstOptional) { - // When the only token is an optional variable token, the separator is required - return sprintf('%s(?P<%s>%s)?', preg_quote($token[1]), $token[3], $token[2]); - } else { - $regexp = sprintf('%s(?P<%s>%s)', preg_quote($token[1]), $token[3], $token[2]); - if ($index >= $firstOptional) { - // Enclose each optional token in a subpattern to make it optional. - // "?:" means it is non-capturing, i.e. the portion of the subject string that - // matched the optional subpattern is not passed back. - $regexp = "(?:$regexp"; - $nbTokens = \count($tokens); - if ($nbTokens - 1 == $index) { - // Close the optional subpatterns - $regexp .= str_repeat(')?', $nbTokens - $firstOptional - (0 === $firstOptional ? 1 : 0)); - } - } - - return $regexp; - } - } - } - - private static function transformCapturingGroupsToNonCapturings(string $regexp): string - { - for ($i = 0; $i < \strlen($regexp); ++$i) { - if ('\\' === $regexp[$i]) { - ++$i; - continue; - } - if ('(' !== $regexp[$i] || !isset($regexp[$i + 2])) { - continue; - } - if ('*' === $regexp[++$i] || '?' === $regexp[$i]) { - ++$i; - continue; - } - $regexp = substr_replace($regexp, '?:', $i, 0); - ++$i; - } - - return $regexp; - } -} diff --git a/lib/symfony/routing/RouteCompilerInterface.php b/lib/symfony/routing/RouteCompilerInterface.php deleted file mode 100644 index 9bae33a91..000000000 --- a/lib/symfony/routing/RouteCompilerInterface.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -/** - * RouteCompilerInterface is the interface that all RouteCompiler classes must implement. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface RouteCompilerInterface -{ - /** - * Compiles the current route instance. - * - * @return CompiledRoute - * - * @throws \LogicException If the Route cannot be compiled because the - * path or host pattern is invalid - */ - public static function compile(Route $route); -} diff --git a/lib/symfony/routing/Router.php b/lib/symfony/routing/Router.php deleted file mode 100644 index 89b14925e..000000000 --- a/lib/symfony/routing/Router.php +++ /dev/null @@ -1,393 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -use Psr\Log\LoggerInterface; -use Symfony\Component\Config\ConfigCacheFactory; -use Symfony\Component\Config\ConfigCacheFactoryInterface; -use Symfony\Component\Config\ConfigCacheInterface; -use Symfony\Component\Config\Loader\LoaderInterface; -use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Routing\Generator\CompiledUrlGenerator; -use Symfony\Component\Routing\Generator\ConfigurableRequirementsInterface; -use Symfony\Component\Routing\Generator\Dumper\CompiledUrlGeneratorDumper; -use Symfony\Component\Routing\Generator\Dumper\GeneratorDumperInterface; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; -use Symfony\Component\Routing\Matcher\CompiledUrlMatcher; -use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; -use Symfony\Component\Routing\Matcher\Dumper\MatcherDumperInterface; -use Symfony\Component\Routing\Matcher\RequestMatcherInterface; -use Symfony\Component\Routing\Matcher\UrlMatcherInterface; - -/** - * The Router class is an example of the integration of all pieces of the - * routing system for easier use. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Router implements RouterInterface, RequestMatcherInterface -{ - /** - * @var UrlMatcherInterface|null - */ - protected $matcher; - - /** - * @var UrlGeneratorInterface|null - */ - protected $generator; - - /** - * @var RequestContext - */ - protected $context; - - /** - * @var LoaderInterface - */ - protected $loader; - - /** - * @var RouteCollection|null - */ - protected $collection; - - /** - * @var mixed - */ - protected $resource; - - /** - * @var array - */ - protected $options = []; - - /** - * @var LoggerInterface|null - */ - protected $logger; - - /** - * @var string|null - */ - protected $defaultLocale; - - /** - * @var ConfigCacheFactoryInterface|null - */ - private $configCacheFactory; - - /** - * @var ExpressionFunctionProviderInterface[] - */ - private $expressionLanguageProviders = []; - - private static $cache = []; - - /** - * @param mixed $resource The main resource to load - */ - public function __construct(LoaderInterface $loader, $resource, array $options = [], RequestContext $context = null, LoggerInterface $logger = null, string $defaultLocale = null) - { - $this->loader = $loader; - $this->resource = $resource; - $this->logger = $logger; - $this->context = $context ?? new RequestContext(); - $this->setOptions($options); - $this->defaultLocale = $defaultLocale; - } - - /** - * Sets options. - * - * Available options: - * - * * cache_dir: The cache directory (or null to disable caching) - * * debug: Whether to enable debugging or not (false by default) - * * generator_class: The name of a UrlGeneratorInterface implementation - * * generator_dumper_class: The name of a GeneratorDumperInterface implementation - * * matcher_class: The name of a UrlMatcherInterface implementation - * * matcher_dumper_class: The name of a MatcherDumperInterface implementation - * * resource_type: Type hint for the main resource (optional) - * * strict_requirements: Configure strict requirement checking for generators - * implementing ConfigurableRequirementsInterface (default is true) - * - * @throws \InvalidArgumentException When unsupported option is provided - */ - public function setOptions(array $options) - { - $this->options = [ - 'cache_dir' => null, - 'debug' => false, - 'generator_class' => CompiledUrlGenerator::class, - 'generator_dumper_class' => CompiledUrlGeneratorDumper::class, - 'matcher_class' => CompiledUrlMatcher::class, - 'matcher_dumper_class' => CompiledUrlMatcherDumper::class, - 'resource_type' => null, - 'strict_requirements' => true, - ]; - - // check option names and live merge, if errors are encountered Exception will be thrown - $invalid = []; - foreach ($options as $key => $value) { - if (\array_key_exists($key, $this->options)) { - $this->options[$key] = $value; - } else { - $invalid[] = $key; - } - } - - if ($invalid) { - throw new \InvalidArgumentException(sprintf('The Router does not support the following options: "%s".', implode('", "', $invalid))); - } - } - - /** - * Sets an option. - * - * @param mixed $value The value - * - * @throws \InvalidArgumentException - */ - public function setOption(string $key, $value) - { - if (!\array_key_exists($key, $this->options)) { - throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); - } - - $this->options[$key] = $value; - } - - /** - * Gets an option value. - * - * @return mixed - * - * @throws \InvalidArgumentException - */ - public function getOption(string $key) - { - if (!\array_key_exists($key, $this->options)) { - throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); - } - - return $this->options[$key]; - } - - /** - * {@inheritdoc} - */ - public function getRouteCollection() - { - if (null === $this->collection) { - $this->collection = $this->loader->load($this->resource, $this->options['resource_type']); - } - - return $this->collection; - } - - /** - * {@inheritdoc} - */ - public function setContext(RequestContext $context) - { - $this->context = $context; - - if (null !== $this->matcher) { - $this->getMatcher()->setContext($context); - } - if (null !== $this->generator) { - $this->getGenerator()->setContext($context); - } - } - - /** - * {@inheritdoc} - */ - public function getContext() - { - return $this->context; - } - - /** - * Sets the ConfigCache factory to use. - */ - public function setConfigCacheFactory(ConfigCacheFactoryInterface $configCacheFactory) - { - $this->configCacheFactory = $configCacheFactory; - } - - /** - * {@inheritdoc} - */ - public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH) - { - return $this->getGenerator()->generate($name, $parameters, $referenceType); - } - - /** - * {@inheritdoc} - */ - public function match(string $pathinfo) - { - return $this->getMatcher()->match($pathinfo); - } - - /** - * {@inheritdoc} - */ - public function matchRequest(Request $request) - { - $matcher = $this->getMatcher(); - if (!$matcher instanceof RequestMatcherInterface) { - // fallback to the default UrlMatcherInterface - return $matcher->match($request->getPathInfo()); - } - - return $matcher->matchRequest($request); - } - - /** - * Gets the UrlMatcher or RequestMatcher instance associated with this Router. - * - * @return UrlMatcherInterface|RequestMatcherInterface - */ - public function getMatcher() - { - if (null !== $this->matcher) { - return $this->matcher; - } - - if (null === $this->options['cache_dir']) { - $routes = $this->getRouteCollection(); - $compiled = is_a($this->options['matcher_class'], CompiledUrlMatcher::class, true); - if ($compiled) { - $routes = (new CompiledUrlMatcherDumper($routes))->getCompiledRoutes(); - } - $this->matcher = new $this->options['matcher_class']($routes, $this->context); - if (method_exists($this->matcher, 'addExpressionLanguageProvider')) { - foreach ($this->expressionLanguageProviders as $provider) { - $this->matcher->addExpressionLanguageProvider($provider); - } - } - - return $this->matcher; - } - - $cache = $this->getConfigCacheFactory()->cache($this->options['cache_dir'].'/url_matching_routes.php', - function (ConfigCacheInterface $cache) { - $dumper = $this->getMatcherDumperInstance(); - if (method_exists($dumper, 'addExpressionLanguageProvider')) { - foreach ($this->expressionLanguageProviders as $provider) { - $dumper->addExpressionLanguageProvider($provider); - } - } - - $cache->write($dumper->dump(), $this->getRouteCollection()->getResources()); - } - ); - - return $this->matcher = new $this->options['matcher_class'](self::getCompiledRoutes($cache->getPath()), $this->context); - } - - /** - * Gets the UrlGenerator instance associated with this Router. - * - * @return UrlGeneratorInterface - */ - public function getGenerator() - { - if (null !== $this->generator) { - return $this->generator; - } - - if (null === $this->options['cache_dir']) { - $routes = $this->getRouteCollection(); - $aliases = []; - $compiled = is_a($this->options['generator_class'], CompiledUrlGenerator::class, true); - if ($compiled) { - $generatorDumper = new CompiledUrlGeneratorDumper($routes); - $routes = $generatorDumper->getCompiledRoutes(); - $aliases = $generatorDumper->getCompiledAliases(); - } - $this->generator = new $this->options['generator_class'](array_merge($routes, $aliases), $this->context, $this->logger, $this->defaultLocale); - } else { - $cache = $this->getConfigCacheFactory()->cache($this->options['cache_dir'].'/url_generating_routes.php', - function (ConfigCacheInterface $cache) { - $dumper = $this->getGeneratorDumperInstance(); - - $cache->write($dumper->dump(), $this->getRouteCollection()->getResources()); - } - ); - - $this->generator = new $this->options['generator_class'](self::getCompiledRoutes($cache->getPath()), $this->context, $this->logger, $this->defaultLocale); - } - - if ($this->generator instanceof ConfigurableRequirementsInterface) { - $this->generator->setStrictRequirements($this->options['strict_requirements']); - } - - return $this->generator; - } - - public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) - { - $this->expressionLanguageProviders[] = $provider; - } - - /** - * @return GeneratorDumperInterface - */ - protected function getGeneratorDumperInstance() - { - return new $this->options['generator_dumper_class']($this->getRouteCollection()); - } - - /** - * @return MatcherDumperInterface - */ - protected function getMatcherDumperInstance() - { - return new $this->options['matcher_dumper_class']($this->getRouteCollection()); - } - - /** - * Provides the ConfigCache factory implementation, falling back to a - * default implementation if necessary. - */ - private function getConfigCacheFactory(): ConfigCacheFactoryInterface - { - if (null === $this->configCacheFactory) { - $this->configCacheFactory = new ConfigCacheFactory($this->options['debug']); - } - - return $this->configCacheFactory; - } - - private static function getCompiledRoutes(string $path): array - { - if ([] === self::$cache && \function_exists('opcache_invalidate') && filter_var(\ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) || filter_var(\ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOLEAN))) { - self::$cache = null; - } - - if (null === self::$cache) { - return require $path; - } - - if (isset(self::$cache[$path])) { - return self::$cache[$path]; - } - - return self::$cache[$path] = require $path; - } -} diff --git a/lib/symfony/routing/RouterInterface.php b/lib/symfony/routing/RouterInterface.php deleted file mode 100644 index 6912f8a15..000000000 --- a/lib/symfony/routing/RouterInterface.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; -use Symfony\Component\Routing\Matcher\UrlMatcherInterface; - -/** - * RouterInterface is the interface that all Router classes must implement. - * - * This interface is the concatenation of UrlMatcherInterface and UrlGeneratorInterface. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface RouterInterface extends UrlMatcherInterface, UrlGeneratorInterface -{ - /** - * Gets the RouteCollection instance associated with this Router. - * - * WARNING: This method should never be used at runtime as it is SLOW. - * You might use it in a cache warmer though. - * - * @return RouteCollection - */ - public function getRouteCollection(); -} diff --git a/lib/symfony/routing/composer.json b/lib/symfony/routing/composer.json deleted file mode 100644 index b978c0626..000000000 --- a/lib/symfony/routing/composer.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "symfony/routing", - "type": "library", - "description": "Maps an HTTP request to a set of configuration variables", - "keywords": ["routing", "router", "URL", "URI"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16" - }, - "require-dev": { - "symfony/config": "^5.3|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", - "symfony/yaml": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "doctrine/annotations": "^1.12", - "psr/log": "^1|^2|^3" - }, - "conflict": { - "doctrine/annotations": "<1.12", - "symfony/config": "<5.3", - "symfony/dependency-injection": "<4.4", - "symfony/yaml": "<4.4" - }, - "suggest": { - "symfony/http-foundation": "For using a Symfony Request object", - "symfony/config": "For using the all-in-one router or any loader", - "symfony/yaml": "For using the YAML loader", - "symfony/expression-language": "For using expression matching" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\Routing\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/lib/symfony/service-contracts/.gitignore b/lib/symfony/service-contracts/.gitignore deleted file mode 100644 index c49a5d8df..000000000 --- a/lib/symfony/service-contracts/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -vendor/ -composer.lock -phpunit.xml diff --git a/lib/symfony/service-contracts/Attribute/Required.php b/lib/symfony/service-contracts/Attribute/Required.php deleted file mode 100644 index 9df851189..000000000 --- a/lib/symfony/service-contracts/Attribute/Required.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Service\Attribute; - -/** - * A required dependency. - * - * This attribute indicates that a property holds a required dependency. The annotated property or method should be - * considered during the instantiation process of the containing class. - * - * @author Alexander M. Turek <me@derrabus.de> - */ -#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)] -final class Required -{ -} diff --git a/lib/symfony/service-contracts/Attribute/SubscribedService.php b/lib/symfony/service-contracts/Attribute/SubscribedService.php deleted file mode 100644 index 10d1bc38e..000000000 --- a/lib/symfony/service-contracts/Attribute/SubscribedService.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Service\Attribute; - -use Symfony\Contracts\Service\ServiceSubscriberTrait; - -/** - * Use with {@see ServiceSubscriberTrait} to mark a method's return type - * as a subscribed service. - * - * @author Kevin Bond <kevinbond@gmail.com> - */ -#[\Attribute(\Attribute::TARGET_METHOD)] -final class SubscribedService -{ - /** - * @param string|null $key The key to use for the service - * If null, use "ClassName::methodName" - */ - public function __construct( - public ?string $key = null - ) { - } -} diff --git a/lib/symfony/service-contracts/CHANGELOG.md b/lib/symfony/service-contracts/CHANGELOG.md deleted file mode 100644 index 7932e2613..000000000 --- a/lib/symfony/service-contracts/CHANGELOG.md +++ /dev/null @@ -1,5 +0,0 @@ -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/lib/symfony/service-contracts/LICENSE b/lib/symfony/service-contracts/LICENSE deleted file mode 100644 index 74cdc2dbf..000000000 --- a/lib/symfony/service-contracts/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -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/lib/symfony/service-contracts/README.md b/lib/symfony/service-contracts/README.md deleted file mode 100644 index 41e054a10..000000000 --- a/lib/symfony/service-contracts/README.md +++ /dev/null @@ -1,9 +0,0 @@ -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/lib/symfony/service-contracts/ResetInterface.php b/lib/symfony/service-contracts/ResetInterface.php deleted file mode 100644 index 1af1075ee..000000000 --- a/lib/symfony/service-contracts/ResetInterface.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\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/lib/symfony/service-contracts/ServiceLocatorTrait.php b/lib/symfony/service-contracts/ServiceLocatorTrait.php deleted file mode 100644 index 74dfa4362..000000000 --- a/lib/symfony/service-contracts/ServiceLocatorTrait.php +++ /dev/null @@ -1,128 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Service; - -use Psr\Container\ContainerExceptionInterface; -use Psr\Container\NotFoundExceptionInterface; - -// Help opcache.preload discover always-needed symbols -class_exists(ContainerExceptionInterface::class); -class_exists(NotFoundExceptionInterface::class); - -/** - * A trait to help implement ServiceProviderInterface. - * - * @author Robin Chalas <robin.chalas@gmail.com> - * @author Nicolas Grekas <p@tchwork.com> - */ -trait ServiceLocatorTrait -{ - private $factories; - private $loading = []; - private $providedTypes; - - /** - * @param callable[] $factories - */ - public function __construct(array $factories) - { - $this->factories = $factories; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function has(string $id) - { - return isset($this->factories[$id]); - } - - /** - * {@inheritdoc} - * - * @return mixed - */ - public function get(string $id) - { - if (!isset($this->factories[$id])) { - throw $this->createNotFoundException($id); - } - - if (isset($this->loading[$id])) { - $ids = array_values($this->loading); - $ids = \array_slice($this->loading, array_search($id, $ids)); - $ids[] = $id; - - throw $this->createCircularReferenceException($id, $ids); - } - - $this->loading[$id] = $id; - try { - return $this->factories[$id]($this); - } finally { - unset($this->loading[$id]); - } - } - - /** - * {@inheritdoc} - */ - public function getProvidedServices(): array - { - if (null === $this->providedTypes) { - $this->providedTypes = []; - - foreach ($this->factories as $name => $factory) { - if (!\is_callable($factory)) { - $this->providedTypes[$name] = '?'; - } else { - $type = (new \ReflectionFunction($factory))->getReturnType(); - - $this->providedTypes[$name] = $type ? ($type->allowsNull() ? '?' : '').($type instanceof \ReflectionNamedType ? $type->getName() : $type) : '?'; - } - } - } - - return $this->providedTypes; - } - - private function createNotFoundException(string $id): NotFoundExceptionInterface - { - if (!$alternatives = array_keys($this->factories)) { - $message = 'is empty...'; - } else { - $last = array_pop($alternatives); - if ($alternatives) { - $message = sprintf('only knows about the "%s" and "%s" services.', implode('", "', $alternatives), $last); - } else { - $message = sprintf('only knows about the "%s" service.', $last); - } - } - - if ($this->loading) { - $message = sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', end($this->loading), $id, $message); - } else { - $message = sprintf('Service "%s" not found: the current service locator %s', $id, $message); - } - - return new class($message) extends \InvalidArgumentException implements NotFoundExceptionInterface { - }; - } - - private function createCircularReferenceException(string $id, array $path): ContainerExceptionInterface - { - return new class(sprintf('Circular reference detected for service "%s", path: "%s".', $id, implode(' -> ', $path))) extends \RuntimeException implements ContainerExceptionInterface { - }; - } -} diff --git a/lib/symfony/service-contracts/ServiceProviderInterface.php b/lib/symfony/service-contracts/ServiceProviderInterface.php deleted file mode 100644 index c60ad0bd4..000000000 --- a/lib/symfony/service-contracts/ServiceProviderInterface.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Service; - -use Psr\Container\ContainerInterface; - -/** - * A ServiceProviderInterface exposes the identifiers and the types of services provided by a container. - * - * @author Nicolas Grekas <p@tchwork.com> - * @author Mateusz Sip <mateusz.sip@gmail.com> - */ -interface ServiceProviderInterface extends ContainerInterface -{ - /** - * Returns an associative array of service types keyed by the identifiers provided by the current container. - * - * Examples: - * - * * ['logger' => 'Psr\Log\LoggerInterface'] means the object provides a service named "logger" that implements Psr\Log\LoggerInterface - * * ['foo' => '?'] means the container provides service name "foo" of unspecified type - * * ['bar' => '?Bar\Baz'] means the container provides a service "bar" of type Bar\Baz|null - * - * @return string[] The provided service types, keyed by service names - */ - public function getProvidedServices(): array; -} diff --git a/lib/symfony/service-contracts/ServiceSubscriberInterface.php b/lib/symfony/service-contracts/ServiceSubscriberInterface.php deleted file mode 100644 index 098ab908c..000000000 --- a/lib/symfony/service-contracts/ServiceSubscriberInterface.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Service; - -/** - * A ServiceSubscriber exposes its dependencies via the static {@link getSubscribedServices} method. - * - * The getSubscribedServices method returns an array of service types required by such instances, - * optionally keyed by the service names used internally. Service types that start with an interrogation - * mark "?" are optional, while the other ones are mandatory service dependencies. - * - * The injected service locators SHOULD NOT allow access to any other services not specified by the method. - * - * It is expected that ServiceSubscriber instances consume PSR-11-based service locators internally. - * This interface does not dictate any injection method for these service locators, although constructor - * injection is recommended. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -interface ServiceSubscriberInterface -{ - /** - * Returns an array of service types required by such instances, optionally keyed by the service names used internally. - * - * For mandatory dependencies: - * - * * ['logger' => 'Psr\Log\LoggerInterface'] means the objects use the "logger" name - * internally to fetch a service which must implement Psr\Log\LoggerInterface. - * * ['loggers' => 'Psr\Log\LoggerInterface[]'] means the objects use the "loggers" name - * internally to fetch an iterable of Psr\Log\LoggerInterface instances. - * * ['Psr\Log\LoggerInterface'] is a shortcut for - * * ['Psr\Log\LoggerInterface' => 'Psr\Log\LoggerInterface'] - * - * otherwise: - * - * * ['logger' => '?Psr\Log\LoggerInterface'] denotes an optional dependency - * * ['loggers' => '?Psr\Log\LoggerInterface[]'] denotes an optional iterable dependency - * * ['?Psr\Log\LoggerInterface'] is a shortcut for - * * ['Psr\Log\LoggerInterface' => '?Psr\Log\LoggerInterface'] - * - * @return string[] The required service types, optionally keyed by service names - */ - public static function getSubscribedServices(); -} diff --git a/lib/symfony/service-contracts/ServiceSubscriberTrait.php b/lib/symfony/service-contracts/ServiceSubscriberTrait.php deleted file mode 100644 index 16e3eb2c1..000000000 --- a/lib/symfony/service-contracts/ServiceSubscriberTrait.php +++ /dev/null @@ -1,109 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Service; - -use Psr\Container\ContainerInterface; -use Symfony\Contracts\Service\Attribute\SubscribedService; - -/** - * Implementation of ServiceSubscriberInterface that determines subscribed services from - * method return types. Service ids are available as "ClassName::methodName". - * - * @author Kevin Bond <kevinbond@gmail.com> - */ -trait ServiceSubscriberTrait -{ - /** @var ContainerInterface */ - protected $container; - - /** - * {@inheritdoc} - */ - public static function getSubscribedServices(): array - { - $services = method_exists(get_parent_class(self::class) ?: '', __FUNCTION__) ? parent::getSubscribedServices() : []; - $attributeOptIn = false; - - if (\PHP_VERSION_ID >= 80000) { - foreach ((new \ReflectionClass(self::class))->getMethods() as $method) { - if (self::class !== $method->getDeclaringClass()->name) { - continue; - } - - if (!$attribute = $method->getAttributes(SubscribedService::class)[0] ?? null) { - continue; - } - - if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) { - throw new \LogicException(sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name)); - } - - if (!$returnType = $method->getReturnType()) { - throw new \LogicException(sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class)); - } - - $serviceId = $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType; - - if ($returnType->allowsNull()) { - $serviceId = '?'.$serviceId; - } - - $services[$attribute->newInstance()->key ?? self::class.'::'.$method->name] = $serviceId; - $attributeOptIn = true; - } - } - - if (!$attributeOptIn) { - foreach ((new \ReflectionClass(self::class))->getMethods() as $method) { - if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) { - continue; - } - - if (self::class !== $method->getDeclaringClass()->name) { - continue; - } - - if (!($returnType = $method->getReturnType()) instanceof \ReflectionNamedType) { - continue; - } - - if ($returnType->isBuiltin()) { - continue; - } - - if (\PHP_VERSION_ID >= 80000) { - trigger_deprecation('symfony/service-contracts', '2.5', 'Using "%s" in "%s" without using the "%s" attribute on any method is deprecated.', ServiceSubscriberTrait::class, self::class, SubscribedService::class); - } - - $services[self::class.'::'.$method->name] = '?'.($returnType instanceof \ReflectionNamedType ? $returnType->getName() : $returnType); - } - } - - return $services; - } - - /** - * @required - * - * @return ContainerInterface|null - */ - public function setContainer(ContainerInterface $container) - { - $this->container = $container; - - if (method_exists(get_parent_class(self::class) ?: '', __FUNCTION__)) { - return parent::setContainer($container); - } - - return null; - } -} diff --git a/lib/symfony/service-contracts/composer.json b/lib/symfony/service-contracts/composer.json deleted file mode 100644 index f05863701..000000000 --- a/lib/symfony/service-contracts/composer.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "symfony/service-contracts", - "type": "library", - "description": "Generic abstractions related to writing services", - "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1|^3" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "suggest": { - "symfony/service-implementation": "" - }, - "autoload": { - "psr-4": { "Symfony\\Contracts\\Service\\": "" } - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - } -} diff --git a/lib/symfony/stopwatch/CHANGELOG.md b/lib/symfony/stopwatch/CHANGELOG.md deleted file mode 100644 index f2fd7d0f0..000000000 --- a/lib/symfony/stopwatch/CHANGELOG.md +++ /dev/null @@ -1,24 +0,0 @@ -CHANGELOG -========= - -5.2 ---- - - * Add `name` argument to the `StopWatchEvent` constructor, accessible via a new `StopwatchEvent::getName()` - -5.0.0 ------ - - * Removed support for passing `null` as 1st (`$id`) argument of `Section::get()` method, pass a valid child section identifier instead. - -4.4.0 ------ - - * Deprecated passing `null` as 1st (`$id`) argument of `Section::get()` method, pass a valid child section identifier instead. - -3.4.0 ------ - - * added the `Stopwatch::reset()` method - * allowed to measure sub-millisecond times by introducing an argument to the - constructor of `Stopwatch` diff --git a/lib/symfony/stopwatch/LICENSE b/lib/symfony/stopwatch/LICENSE deleted file mode 100644 index 008370457..000000000 --- a/lib/symfony/stopwatch/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -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/lib/symfony/stopwatch/README.md b/lib/symfony/stopwatch/README.md deleted file mode 100644 index 13a9dfa5f..000000000 --- a/lib/symfony/stopwatch/README.md +++ /dev/null @@ -1,42 +0,0 @@ -Stopwatch Component -=================== - -The Stopwatch component provides a way to profile code. - -Getting Started ---------------- - -``` -$ composer require symfony/stopwatch -``` - -```php -use Symfony\Component\Stopwatch\Stopwatch; - -$stopwatch = new Stopwatch(); - -// optionally group events into sections (e.g. phases of the execution) -$stopwatch->openSection(); - -// starts event named 'eventName' -$stopwatch->start('eventName'); - -// ... run your code here - -// optionally, start a new "lap" time -$stopwatch->lap('foo'); - -// ... run your code here - -$event = $stopwatch->stop('eventName'); - -$stopwatch->stopSection('phase_1'); -``` - -Resources ---------- - - * [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/lib/symfony/stopwatch/Section.php b/lib/symfony/stopwatch/Section.php deleted file mode 100644 index 56cdc6f12..000000000 --- a/lib/symfony/stopwatch/Section.php +++ /dev/null @@ -1,185 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Stopwatch; - -/** - * Stopwatch section. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Section -{ - /** - * @var StopwatchEvent[] - */ - private $events = []; - - /** - * @var float|null - */ - private $origin; - - /** - * @var bool - */ - private $morePrecision; - - /** - * @var string - */ - private $id; - - /** - * @var Section[] - */ - private $children = []; - - /** - * @param float|null $origin Set the origin of the events in this section, use null to set their origin to their start time - * @param bool $morePrecision If true, time is stored as float to keep the original microsecond precision - */ - public function __construct(float $origin = null, bool $morePrecision = false) - { - $this->origin = $origin; - $this->morePrecision = $morePrecision; - } - - /** - * Returns the child section. - * - * @return self|null - */ - public function get(string $id) - { - foreach ($this->children as $child) { - if ($id === $child->getId()) { - return $child; - } - } - - return null; - } - - /** - * Creates or re-opens a child section. - * - * @param string|null $id Null to create a new section, the identifier to re-open an existing one - * - * @return self - */ - public function open(?string $id) - { - if (null === $id || null === $session = $this->get($id)) { - $session = $this->children[] = new self(microtime(true) * 1000, $this->morePrecision); - } - - return $session; - } - - /** - * @return string - */ - public function getId() - { - return $this->id; - } - - /** - * Sets the session identifier. - * - * @return $this - */ - public function setId(string $id) - { - $this->id = $id; - - return $this; - } - - /** - * Starts an event. - * - * @return StopwatchEvent - */ - public function startEvent(string $name, ?string $category) - { - if (!isset($this->events[$name])) { - $this->events[$name] = new StopwatchEvent($this->origin ?: microtime(true) * 1000, $category, $this->morePrecision, $name); - } - - return $this->events[$name]->start(); - } - - /** - * Checks if the event was started. - * - * @return bool - */ - public function isEventStarted(string $name) - { - return isset($this->events[$name]) && $this->events[$name]->isStarted(); - } - - /** - * Stops an event. - * - * @return StopwatchEvent - * - * @throws \LogicException When the event has not been started - */ - public function stopEvent(string $name) - { - if (!isset($this->events[$name])) { - throw new \LogicException(sprintf('Event "%s" is not started.', $name)); - } - - return $this->events[$name]->stop(); - } - - /** - * Stops then restarts an event. - * - * @return StopwatchEvent - * - * @throws \LogicException When the event has not been started - */ - public function lap(string $name) - { - return $this->stopEvent($name)->start(); - } - - /** - * Returns a specific event by name. - * - * @return StopwatchEvent - * - * @throws \LogicException When the event is not known - */ - public function getEvent(string $name) - { - if (!isset($this->events[$name])) { - throw new \LogicException(sprintf('Event "%s" is not known.', $name)); - } - - return $this->events[$name]; - } - - /** - * Returns the events from this section. - * - * @return StopwatchEvent[] - */ - public function getEvents() - { - return $this->events; - } -} diff --git a/lib/symfony/stopwatch/Stopwatch.php b/lib/symfony/stopwatch/Stopwatch.php deleted file mode 100644 index 2f46c5998..000000000 --- a/lib/symfony/stopwatch/Stopwatch.php +++ /dev/null @@ -1,166 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Stopwatch; - -use Symfony\Contracts\Service\ResetInterface; - -// Help opcache.preload discover always-needed symbols -class_exists(Section::class); - -/** - * Stopwatch provides a way to profile code. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Stopwatch implements ResetInterface -{ - /** - * @var bool - */ - private $morePrecision; - - /** - * @var Section[] - */ - private $sections; - - /** - * @var Section[] - */ - private $activeSections; - - /** - * @param bool $morePrecision If true, time is stored as float to keep the original microsecond precision - */ - public function __construct(bool $morePrecision = false) - { - $this->morePrecision = $morePrecision; - $this->reset(); - } - - /** - * @return Section[] - */ - public function getSections() - { - return $this->sections; - } - - /** - * Creates a new section or re-opens an existing section. - * - * @param string|null $id The id of the session to re-open, null to create a new one - * - * @throws \LogicException When the section to re-open is not reachable - */ - public function openSection(string $id = null) - { - $current = end($this->activeSections); - - if (null !== $id && null === $current->get($id)) { - throw new \LogicException(sprintf('The section "%s" has been started at an other level and cannot be opened.', $id)); - } - - $this->start('__section__.child', 'section'); - $this->activeSections[] = $current->open($id); - $this->start('__section__'); - } - - /** - * Stops the last started section. - * - * The id parameter is used to retrieve the events from this section. - * - * @see getSectionEvents() - * - * @throws \LogicException When there's no started section to be stopped - */ - public function stopSection(string $id) - { - $this->stop('__section__'); - - if (1 == \count($this->activeSections)) { - throw new \LogicException('There is no started section to stop.'); - } - - $this->sections[$id] = array_pop($this->activeSections)->setId($id); - $this->stop('__section__.child'); - } - - /** - * Starts an event. - * - * @return StopwatchEvent - */ - public function start(string $name, string $category = null) - { - return end($this->activeSections)->startEvent($name, $category); - } - - /** - * Checks if the event was started. - * - * @return bool - */ - public function isStarted(string $name) - { - return end($this->activeSections)->isEventStarted($name); - } - - /** - * Stops an event. - * - * @return StopwatchEvent - */ - public function stop(string $name) - { - return end($this->activeSections)->stopEvent($name); - } - - /** - * Stops then restarts an event. - * - * @return StopwatchEvent - */ - public function lap(string $name) - { - return end($this->activeSections)->stopEvent($name)->start(); - } - - /** - * Returns a specific event by name. - * - * @return StopwatchEvent - */ - public function getEvent(string $name) - { - return end($this->activeSections)->getEvent($name); - } - - /** - * Gets all events for a given section. - * - * @return StopwatchEvent[] - */ - public function getSectionEvents(string $id) - { - return isset($this->sections[$id]) ? $this->sections[$id]->getEvents() : []; - } - - /** - * Resets the stopwatch to its original state. - */ - public function reset() - { - $this->sections = $this->activeSections = ['__root__' => new Section(null, $this->morePrecision)]; - } -} diff --git a/lib/symfony/stopwatch/StopwatchEvent.php b/lib/symfony/stopwatch/StopwatchEvent.php deleted file mode 100644 index 945bc7029..000000000 --- a/lib/symfony/stopwatch/StopwatchEvent.php +++ /dev/null @@ -1,258 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Stopwatch; - -/** - * Represents an Event managed by Stopwatch. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class StopwatchEvent -{ - /** - * @var StopwatchPeriod[] - */ - private $periods = []; - - /** - * @var float - */ - private $origin; - - /** - * @var string - */ - private $category; - - /** - * @var bool - */ - private $morePrecision; - - /** - * @var float[] - */ - private $started = []; - - /** - * @var string - */ - private $name; - - /** - * @param float $origin The origin time in milliseconds - * @param string|null $category The event category or null to use the default - * @param bool $morePrecision If true, time is stored as float to keep the original microsecond precision - * @param string|null $name The event name or null to define the name as default - * - * @throws \InvalidArgumentException When the raw time is not valid - */ - public function __construct(float $origin, string $category = null, bool $morePrecision = false, string $name = null) - { - $this->origin = $this->formatTime($origin); - $this->category = \is_string($category) ? $category : 'default'; - $this->morePrecision = $morePrecision; - $this->name = $name ?? 'default'; - } - - /** - * Gets the category. - * - * @return string - */ - public function getCategory() - { - return $this->category; - } - - /** - * Gets the origin in milliseconds. - * - * @return float - */ - public function getOrigin() - { - return $this->origin; - } - - /** - * Starts a new event period. - * - * @return $this - */ - public function start() - { - $this->started[] = $this->getNow(); - - return $this; - } - - /** - * Stops the last started event period. - * - * @return $this - * - * @throws \LogicException When stop() is called without a matching call to start() - */ - public function stop() - { - if (!\count($this->started)) { - throw new \LogicException('stop() called but start() has not been called before.'); - } - - $this->periods[] = new StopwatchPeriod(array_pop($this->started), $this->getNow(), $this->morePrecision); - - return $this; - } - - /** - * Checks if the event was started. - * - * @return bool - */ - public function isStarted() - { - return !empty($this->started); - } - - /** - * Stops the current period and then starts a new one. - * - * @return $this - */ - public function lap() - { - return $this->stop()->start(); - } - - /** - * Stops all non already stopped periods. - */ - public function ensureStopped() - { - while (\count($this->started)) { - $this->stop(); - } - } - - /** - * Gets all event periods. - * - * @return StopwatchPeriod[] - */ - public function getPeriods() - { - return $this->periods; - } - - /** - * Gets the relative time of the start of the first period in milliseconds. - * - * @return int|float - */ - public function getStartTime() - { - if (isset($this->periods[0])) { - return $this->periods[0]->getStartTime(); - } - - if ($this->started) { - return $this->started[0]; - } - - return 0; - } - - /** - * Gets the relative time of the end of the last period in milliseconds. - * - * @return int|float - */ - public function getEndTime() - { - $count = \count($this->periods); - - return $count ? $this->periods[$count - 1]->getEndTime() : 0; - } - - /** - * Gets the duration of the events in milliseconds (including all periods). - * - * @return int|float - */ - public function getDuration() - { - $periods = $this->periods; - $left = \count($this->started); - - for ($i = $left - 1; $i >= 0; --$i) { - $periods[] = new StopwatchPeriod($this->started[$i], $this->getNow(), $this->morePrecision); - } - - $total = 0; - foreach ($periods as $period) { - $total += $period->getDuration(); - } - - return $total; - } - - /** - * Gets the max memory usage of all periods in bytes. - * - * @return int - */ - public function getMemory() - { - $memory = 0; - foreach ($this->periods as $period) { - if ($period->getMemory() > $memory) { - $memory = $period->getMemory(); - } - } - - return $memory; - } - - /** - * Return the current time relative to origin in milliseconds. - * - * @return float - */ - protected function getNow() - { - return $this->formatTime(microtime(true) * 1000 - $this->origin); - } - - /** - * Formats a time. - * - * @throws \InvalidArgumentException When the raw time is not valid - */ - private function formatTime(float $time): float - { - return round($time, 1); - } - - /** - * Gets the event name. - */ - public function getName(): string - { - return $this->name; - } - - public function __toString(): string - { - return sprintf('%s/%s: %.2F MiB - %d ms', $this->getCategory(), $this->getName(), $this->getMemory() / 1024 / 1024, $this->getDuration()); - } -} diff --git a/lib/symfony/stopwatch/StopwatchPeriod.php b/lib/symfony/stopwatch/StopwatchPeriod.php deleted file mode 100644 index 7a7ae1a77..000000000 --- a/lib/symfony/stopwatch/StopwatchPeriod.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Stopwatch; - -/** - * Represents an Period for an Event. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class StopwatchPeriod -{ - private $start; - private $end; - private $memory; - - /** - * @param int|float $start The relative time of the start of the period (in milliseconds) - * @param int|float $end The relative time of the end of the period (in milliseconds) - * @param bool $morePrecision If true, time is stored as float to keep the original microsecond precision - */ - public function __construct($start, $end, bool $morePrecision = false) - { - $this->start = $morePrecision ? (float) $start : (int) $start; - $this->end = $morePrecision ? (float) $end : (int) $end; - $this->memory = memory_get_usage(true); - } - - /** - * Gets the relative time of the start of the period in milliseconds. - * - * @return int|float - */ - public function getStartTime() - { - return $this->start; - } - - /** - * Gets the relative time of the end of the period in milliseconds. - * - * @return int|float - */ - public function getEndTime() - { - return $this->end; - } - - /** - * Gets the time spent in this period in milliseconds. - * - * @return int|float - */ - public function getDuration() - { - return $this->end - $this->start; - } - - /** - * Gets the memory usage in bytes. - * - * @return int - */ - public function getMemory() - { - return $this->memory; - } - - public function __toString(): string - { - return sprintf('%.2F MiB - %d ms', $this->getMemory() / 1024 / 1024, $this->getDuration()); - } -} diff --git a/lib/symfony/stopwatch/composer.json b/lib/symfony/stopwatch/composer.json deleted file mode 100644 index ed918d36f..000000000 --- a/lib/symfony/stopwatch/composer.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "symfony/stopwatch", - "type": "library", - "description": "Provides a way to profile code", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/service-contracts": "^1|^2|^3" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\Stopwatch\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/lib/symfony/string/AbstractString.php b/lib/symfony/string/AbstractString.php deleted file mode 100644 index cf21fef1f..000000000 --- a/lib/symfony/string/AbstractString.php +++ /dev/null @@ -1,795 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\String; - -use Symfony\Component\String\Exception\ExceptionInterface; -use Symfony\Component\String\Exception\InvalidArgumentException; -use Symfony\Component\String\Exception\RuntimeException; - -/** - * Represents a string of abstract characters. - * - * Unicode defines 3 types of "characters" (bytes, code points and grapheme clusters). - * This class is the abstract type to use as a type-hint when the logic you want to - * implement doesn't care about the exact variant it deals with. - * - * @author Nicolas Grekas <p@tchwork.com> - * @author Hugo Hamon <hugohamon@neuf.fr> - * - * @throws ExceptionInterface - */ -abstract class AbstractString implements \Stringable, \JsonSerializable -{ - public const PREG_PATTERN_ORDER = \PREG_PATTERN_ORDER; - public const PREG_SET_ORDER = \PREG_SET_ORDER; - public const PREG_OFFSET_CAPTURE = \PREG_OFFSET_CAPTURE; - public const PREG_UNMATCHED_AS_NULL = \PREG_UNMATCHED_AS_NULL; - - public const PREG_SPLIT = 0; - public const PREG_SPLIT_NO_EMPTY = \PREG_SPLIT_NO_EMPTY; - public const PREG_SPLIT_DELIM_CAPTURE = \PREG_SPLIT_DELIM_CAPTURE; - public const PREG_SPLIT_OFFSET_CAPTURE = \PREG_SPLIT_OFFSET_CAPTURE; - - protected $string = ''; - protected $ignoreCase = false; - - abstract public function __construct(string $string = ''); - - /** - * Unwraps instances of AbstractString back to strings. - * - * @return string[]|array - */ - public static function unwrap(array $values): array - { - foreach ($values as $k => $v) { - if ($v instanceof self) { - $values[$k] = $v->__toString(); - } elseif (\is_array($v) && $values[$k] !== $v = static::unwrap($v)) { - $values[$k] = $v; - } - } - - return $values; - } - - /** - * Wraps (and normalizes) strings in instances of AbstractString. - * - * @return static[]|array - */ - public static function wrap(array $values): array - { - $i = 0; - $keys = null; - - foreach ($values as $k => $v) { - if (\is_string($k) && '' !== $k && $k !== $j = (string) new static($k)) { - $keys = $keys ?? array_keys($values); - $keys[$i] = $j; - } - - if (\is_string($v)) { - $values[$k] = new static($v); - } elseif (\is_array($v) && $values[$k] !== $v = static::wrap($v)) { - $values[$k] = $v; - } - - ++$i; - } - - return null !== $keys ? array_combine($keys, $values) : $values; - } - - /** - * @param string|string[] $needle - * - * @return static - */ - public function after($needle, bool $includeNeedle = false, int $offset = 0): self - { - $str = clone $this; - $i = \PHP_INT_MAX; - - foreach ((array) $needle as $n) { - $n = (string) $n; - $j = $this->indexOf($n, $offset); - - if (null !== $j && $j < $i) { - $i = $j; - $str->string = $n; - } - } - - if (\PHP_INT_MAX === $i) { - return $str; - } - - if (!$includeNeedle) { - $i += $str->length(); - } - - return $this->slice($i); - } - - /** - * @param string|string[] $needle - * - * @return static - */ - public function afterLast($needle, bool $includeNeedle = false, int $offset = 0): self - { - $str = clone $this; - $i = null; - - foreach ((array) $needle as $n) { - $n = (string) $n; - $j = $this->indexOfLast($n, $offset); - - if (null !== $j && $j >= $i) { - $i = $offset = $j; - $str->string = $n; - } - } - - if (null === $i) { - return $str; - } - - if (!$includeNeedle) { - $i += $str->length(); - } - - return $this->slice($i); - } - - /** - * @return static - */ - abstract public function append(string ...$suffix): self; - - /** - * @param string|string[] $needle - * - * @return static - */ - public function before($needle, bool $includeNeedle = false, int $offset = 0): self - { - $str = clone $this; - $i = \PHP_INT_MAX; - - foreach ((array) $needle as $n) { - $n = (string) $n; - $j = $this->indexOf($n, $offset); - - if (null !== $j && $j < $i) { - $i = $j; - $str->string = $n; - } - } - - if (\PHP_INT_MAX === $i) { - return $str; - } - - if ($includeNeedle) { - $i += $str->length(); - } - - return $this->slice(0, $i); - } - - /** - * @param string|string[] $needle - * - * @return static - */ - public function beforeLast($needle, bool $includeNeedle = false, int $offset = 0): self - { - $str = clone $this; - $i = null; - - foreach ((array) $needle as $n) { - $n = (string) $n; - $j = $this->indexOfLast($n, $offset); - - if (null !== $j && $j >= $i) { - $i = $offset = $j; - $str->string = $n; - } - } - - if (null === $i) { - return $str; - } - - if ($includeNeedle) { - $i += $str->length(); - } - - return $this->slice(0, $i); - } - - /** - * @return int[] - */ - public function bytesAt(int $offset): array - { - $str = $this->slice($offset, 1); - - return '' === $str->string ? [] : array_values(unpack('C*', $str->string)); - } - - /** - * @return static - */ - abstract public function camel(): self; - - /** - * @return static[] - */ - abstract public function chunk(int $length = 1): array; - - /** - * @return static - */ - public function collapseWhitespace(): self - { - $str = clone $this; - $str->string = trim(preg_replace('/(?:\s{2,}+|[^\S ])/', ' ', $str->string)); - - return $str; - } - - /** - * @param string|string[] $needle - */ - public function containsAny($needle): bool - { - return null !== $this->indexOf($needle); - } - - /** - * @param string|string[] $suffix - */ - public function endsWith($suffix): bool - { - if (!\is_array($suffix) && !$suffix instanceof \Traversable) { - throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); - } - - foreach ($suffix as $s) { - if ($this->endsWith((string) $s)) { - return true; - } - } - - return false; - } - - /** - * @return static - */ - public function ensureEnd(string $suffix): self - { - if (!$this->endsWith($suffix)) { - return $this->append($suffix); - } - - $suffix = preg_quote($suffix); - $regex = '{('.$suffix.')(?:'.$suffix.')++$}D'; - - return $this->replaceMatches($regex.($this->ignoreCase ? 'i' : ''), '$1'); - } - - /** - * @return static - */ - public function ensureStart(string $prefix): self - { - $prefix = new static($prefix); - - if (!$this->startsWith($prefix)) { - return $this->prepend($prefix); - } - - $str = clone $this; - $i = $prefixLen = $prefix->length(); - - while ($this->indexOf($prefix, $i) === $i) { - $str = $str->slice($prefixLen); - $i += $prefixLen; - } - - return $str; - } - - /** - * @param string|string[] $string - */ - public function equalsTo($string): bool - { - if (!\is_array($string) && !$string instanceof \Traversable) { - throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); - } - - foreach ($string as $s) { - if ($this->equalsTo((string) $s)) { - return true; - } - } - - return false; - } - - /** - * @return static - */ - abstract public function folded(): self; - - /** - * @return static - */ - public function ignoreCase(): self - { - $str = clone $this; - $str->ignoreCase = true; - - return $str; - } - - /** - * @param string|string[] $needle - */ - public function indexOf($needle, int $offset = 0): ?int - { - if (!\is_array($needle) && !$needle instanceof \Traversable) { - throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); - } - - $i = \PHP_INT_MAX; - - foreach ($needle as $n) { - $j = $this->indexOf((string) $n, $offset); - - if (null !== $j && $j < $i) { - $i = $j; - } - } - - return \PHP_INT_MAX === $i ? null : $i; - } - - /** - * @param string|string[] $needle - */ - public function indexOfLast($needle, int $offset = 0): ?int - { - if (!\is_array($needle) && !$needle instanceof \Traversable) { - throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); - } - - $i = null; - - foreach ($needle as $n) { - $j = $this->indexOfLast((string) $n, $offset); - - if (null !== $j && $j >= $i) { - $i = $offset = $j; - } - } - - return $i; - } - - public function isEmpty(): bool - { - return '' === $this->string; - } - - /** - * @return static - */ - abstract public function join(array $strings, string $lastGlue = null): self; - - public function jsonSerialize(): string - { - return $this->string; - } - - abstract public function length(): int; - - /** - * @return static - */ - abstract public function lower(): self; - - /** - * Matches the string using a regular expression. - * - * Pass PREG_PATTERN_ORDER or PREG_SET_ORDER as $flags to get all occurrences matching the regular expression. - * - * @return array All matches in a multi-dimensional array ordered according to flags - */ - abstract public function match(string $regexp, int $flags = 0, int $offset = 0): array; - - /** - * @return static - */ - abstract public function padBoth(int $length, string $padStr = ' '): self; - - /** - * @return static - */ - abstract public function padEnd(int $length, string $padStr = ' '): self; - - /** - * @return static - */ - abstract public function padStart(int $length, string $padStr = ' '): self; - - /** - * @return static - */ - abstract public function prepend(string ...$prefix): self; - - /** - * @return static - */ - public function repeat(int $multiplier): self - { - if (0 > $multiplier) { - throw new InvalidArgumentException(sprintf('Multiplier must be positive, %d given.', $multiplier)); - } - - $str = clone $this; - $str->string = str_repeat($str->string, $multiplier); - - return $str; - } - - /** - * @return static - */ - abstract public function replace(string $from, string $to): self; - - /** - * @param string|callable $to - * - * @return static - */ - abstract public function replaceMatches(string $fromRegexp, $to): self; - - /** - * @return static - */ - abstract public function reverse(): self; - - /** - * @return static - */ - abstract public function slice(int $start = 0, int $length = null): self; - - /** - * @return static - */ - abstract public function snake(): self; - - /** - * @return static - */ - abstract public function splice(string $replacement, int $start = 0, int $length = null): self; - - /** - * @return static[] - */ - public function split(string $delimiter, int $limit = null, int $flags = null): array - { - if (null === $flags) { - throw new \TypeError('Split behavior when $flags is null must be implemented by child classes.'); - } - - if ($this->ignoreCase) { - $delimiter .= 'i'; - } - - set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); - - try { - if (false === $chunks = preg_split($delimiter, $this->string, $limit, $flags)) { - $lastError = preg_last_error(); - - foreach (get_defined_constants(true)['pcre'] as $k => $v) { - if ($lastError === $v && '_ERROR' === substr($k, -6)) { - throw new RuntimeException('Splitting failed with '.$k.'.'); - } - } - - throw new RuntimeException('Splitting failed with unknown error code.'); - } - } finally { - restore_error_handler(); - } - - $str = clone $this; - - if (self::PREG_SPLIT_OFFSET_CAPTURE & $flags) { - foreach ($chunks as &$chunk) { - $str->string = $chunk[0]; - $chunk[0] = clone $str; - } - } else { - foreach ($chunks as &$chunk) { - $str->string = $chunk; - $chunk = clone $str; - } - } - - return $chunks; - } - - /** - * @param string|string[] $prefix - */ - public function startsWith($prefix): bool - { - if (!\is_array($prefix) && !$prefix instanceof \Traversable) { - throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); - } - - foreach ($prefix as $prefix) { - if ($this->startsWith((string) $prefix)) { - return true; - } - } - - return false; - } - - /** - * @return static - */ - abstract public function title(bool $allWords = false): self; - - public function toByteString(string $toEncoding = null): ByteString - { - $b = new ByteString(); - - $toEncoding = \in_array($toEncoding, ['utf8', 'utf-8', 'UTF8'], true) ? 'UTF-8' : $toEncoding; - - if (null === $toEncoding || $toEncoding === $fromEncoding = $this instanceof AbstractUnicodeString || preg_match('//u', $b->string) ? 'UTF-8' : 'Windows-1252') { - $b->string = $this->string; - - return $b; - } - - set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); - - try { - try { - $b->string = mb_convert_encoding($this->string, $toEncoding, 'UTF-8'); - } catch (InvalidArgumentException $e) { - if (!\function_exists('iconv')) { - throw $e; - } - - $b->string = iconv('UTF-8', $toEncoding, $this->string); - } - } finally { - restore_error_handler(); - } - - return $b; - } - - public function toCodePointString(): CodePointString - { - return new CodePointString($this->string); - } - - public function toString(): string - { - return $this->string; - } - - public function toUnicodeString(): UnicodeString - { - return new UnicodeString($this->string); - } - - /** - * @return static - */ - abstract public function trim(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): self; - - /** - * @return static - */ - abstract public function trimEnd(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): self; - - /** - * @param string|string[] $prefix - * - * @return static - */ - public function trimPrefix($prefix): self - { - if (\is_array($prefix) || $prefix instanceof \Traversable) { - foreach ($prefix as $s) { - $t = $this->trimPrefix($s); - - if ($t->string !== $this->string) { - return $t; - } - } - - return clone $this; - } - - $str = clone $this; - - if ($prefix instanceof self) { - $prefix = $prefix->string; - } else { - $prefix = (string) $prefix; - } - - if ('' !== $prefix && \strlen($this->string) >= \strlen($prefix) && 0 === substr_compare($this->string, $prefix, 0, \strlen($prefix), $this->ignoreCase)) { - $str->string = substr($this->string, \strlen($prefix)); - } - - return $str; - } - - /** - * @return static - */ - abstract public function trimStart(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): self; - - /** - * @param string|string[] $suffix - * - * @return static - */ - public function trimSuffix($suffix): self - { - if (\is_array($suffix) || $suffix instanceof \Traversable) { - foreach ($suffix as $s) { - $t = $this->trimSuffix($s); - - if ($t->string !== $this->string) { - return $t; - } - } - - return clone $this; - } - - $str = clone $this; - - if ($suffix instanceof self) { - $suffix = $suffix->string; - } else { - $suffix = (string) $suffix; - } - - if ('' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase)) { - $str->string = substr($this->string, 0, -\strlen($suffix)); - } - - return $str; - } - - /** - * @return static - */ - public function truncate(int $length, string $ellipsis = '', bool $cut = true): self - { - $stringLength = $this->length(); - - if ($stringLength <= $length) { - return clone $this; - } - - $ellipsisLength = '' !== $ellipsis ? (new static($ellipsis))->length() : 0; - - if ($length < $ellipsisLength) { - $ellipsisLength = 0; - } - - if (!$cut) { - if (null === $length = $this->indexOf([' ', "\r", "\n", "\t"], ($length ?: 1) - 1)) { - return clone $this; - } - - $length += $ellipsisLength; - } - - $str = $this->slice(0, $length - $ellipsisLength); - - return $ellipsisLength ? $str->trimEnd()->append($ellipsis) : $str; - } - - /** - * @return static - */ - abstract public function upper(): self; - - /** - * Returns the printable length on a terminal. - */ - abstract public function width(bool $ignoreAnsiDecoration = true): int; - - /** - * @return static - */ - public function wordwrap(int $width = 75, string $break = "\n", bool $cut = false): self - { - $lines = '' !== $break ? $this->split($break) : [clone $this]; - $chars = []; - $mask = ''; - - if (1 === \count($lines) && '' === $lines[0]->string) { - return $lines[0]; - } - - foreach ($lines as $i => $line) { - if ($i) { - $chars[] = $break; - $mask .= '#'; - } - - foreach ($line->chunk() as $char) { - $chars[] = $char->string; - $mask .= ' ' === $char->string ? ' ' : '?'; - } - } - - $string = ''; - $j = 0; - $b = $i = -1; - $mask = wordwrap($mask, $width, '#', $cut); - - while (false !== $b = strpos($mask, '#', $b + 1)) { - for (++$i; $i < $b; ++$i) { - $string .= $chars[$j]; - unset($chars[$j++]); - } - - if ($break === $chars[$j] || ' ' === $chars[$j]) { - unset($chars[$j++]); - } - - $string .= $break; - } - - $str = clone $this; - $str->string = $string.implode('', $chars); - - return $str; - } - - public function __sleep(): array - { - return ['string']; - } - - public function __clone() - { - $this->ignoreCase = false; - } - - public function __toString(): string - { - return $this->string; - } -} diff --git a/lib/symfony/string/AbstractUnicodeString.php b/lib/symfony/string/AbstractUnicodeString.php deleted file mode 100644 index a482300d2..000000000 --- a/lib/symfony/string/AbstractUnicodeString.php +++ /dev/null @@ -1,623 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\String; - -use Symfony\Component\String\Exception\ExceptionInterface; -use Symfony\Component\String\Exception\InvalidArgumentException; -use Symfony\Component\String\Exception\RuntimeException; - -/** - * Represents a string of abstract Unicode characters. - * - * Unicode defines 3 types of "characters" (bytes, code points and grapheme clusters). - * This class is the abstract type to use as a type-hint when the logic you want to - * implement is Unicode-aware but doesn't care about code points vs grapheme clusters. - * - * @author Nicolas Grekas <p@tchwork.com> - * - * @throws ExceptionInterface - */ -abstract class AbstractUnicodeString extends AbstractString -{ - public const NFC = \Normalizer::NFC; - public const NFD = \Normalizer::NFD; - public const NFKC = \Normalizer::NFKC; - public const NFKD = \Normalizer::NFKD; - - // all ASCII letters sorted by typical frequency of occurrence - private const ASCII = "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"; - - // the subset of folded case mappings that is not in lower case mappings - private const FOLD_FROM = ['İ', 'µ', 'ſ', "\xCD\x85", 'ς', 'ϐ', 'ϑ', 'ϕ', 'ϖ', 'ϰ', 'ϱ', 'ϵ', 'ẛ', "\xE1\xBE\xBE", 'ß', 'İ', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'և', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'ẚ', 'ẞ', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', 'ᾅ', 'ᾆ', 'ᾇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'ᾐ', 'ᾑ', 'ᾒ', 'ᾓ', 'ᾔ', 'ᾕ', 'ᾖ', 'ᾗ', 'ᾘ', 'ᾙ', 'ᾚ', 'ᾛ', 'ᾜ', 'ᾝ', 'ᾞ', 'ᾟ', 'ᾠ', 'ᾡ', 'ᾢ', 'ᾣ', 'ᾤ', 'ᾥ', 'ᾦ', 'ᾧ', 'ᾨ', 'ᾩ', 'ᾪ', 'ᾫ', 'ᾬ', 'ᾭ', 'ᾮ', 'ᾯ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'ᾼ', 'ῂ', 'ῃ', 'ῄ', 'ῆ', 'ῇ', 'ῌ', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'ῢ', 'ΰ', 'ῤ', 'ῦ', 'ῧ', 'ῲ', 'ῳ', 'ῴ', 'ῶ', 'ῷ', 'ῼ', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'ſt', 'st', 'ﬓ', 'ﬔ', 'ﬕ', 'ﬖ', 'ﬗ']; - private const FOLD_TO = ['i̇', 'μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', 'ṡ', 'ι', 'ss', '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; - - /** - * @return static - */ - public static function fromCodePoints(int ...$codes): self - { - $string = ''; - - foreach ($codes as $code) { - if (0x80 > $code %= 0x200000) { - $string .= \chr($code); - } elseif (0x800 > $code) { - $string .= \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F); - } elseif (0x10000 > $code) { - $string .= \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); - } else { - $string .= \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); - } - } - - return new static($string); - } - - /** - * Generic UTF-8 to ASCII transliteration. - * - * Install the intl extension for best results. - * - * @param string[]|\Transliterator[]|\Closure[] $rules See "*-Latin" rules from Transliterator::listIDs() - */ - public function ascii(array $rules = []): self - { - $str = clone $this; - $s = $str->string; - $str->string = ''; - - array_unshift($rules, 'nfd'); - $rules[] = 'latin-ascii'; - - if (\function_exists('transliterator_transliterate')) { - $rules[] = 'any-latin/bgn'; - } - - $rules[] = 'nfkd'; - $rules[] = '[:nonspacing mark:] remove'; - - while (\strlen($s) - 1 > $i = strspn($s, self::ASCII)) { - if (0 < --$i) { - $str->string .= substr($s, 0, $i); - $s = substr($s, $i); - } - - if (!$rule = array_shift($rules)) { - $rules = []; // An empty rule interrupts the next ones - } - - if ($rule instanceof \Transliterator) { - $s = $rule->transliterate($s); - } elseif ($rule instanceof \Closure) { - $s = $rule($s); - } elseif ($rule) { - if ('nfd' === $rule = strtolower($rule)) { - normalizer_is_normalized($s, self::NFD) ?: $s = normalizer_normalize($s, self::NFD); - } elseif ('nfkd' === $rule) { - normalizer_is_normalized($s, self::NFKD) ?: $s = normalizer_normalize($s, self::NFKD); - } elseif ('[:nonspacing mark:] remove' === $rule) { - $s = preg_replace('/\p{Mn}++/u', '', $s); - } elseif ('latin-ascii' === $rule) { - $s = str_replace(self::TRANSLIT_FROM, self::TRANSLIT_TO, $s); - } elseif ('de-ascii' === $rule) { - $s = preg_replace("/([AUO])\u{0308}(?=\p{Ll})/u", '$1e', $s); - $s = str_replace(["a\u{0308}", "o\u{0308}", "u\u{0308}", "A\u{0308}", "O\u{0308}", "U\u{0308}"], ['ae', 'oe', 'ue', 'AE', 'OE', 'UE'], $s); - } elseif (\function_exists('transliterator_transliterate')) { - if (null === $transliterator = self::$transliterators[$rule] ?? self::$transliterators[$rule] = \Transliterator::create($rule)) { - if ('any-latin/bgn' === $rule) { - $rule = 'any-latin'; - $transliterator = self::$transliterators[$rule] ?? self::$transliterators[$rule] = \Transliterator::create($rule); - } - - if (null === $transliterator) { - throw new InvalidArgumentException(sprintf('Unknown transliteration rule "%s".', $rule)); - } - - self::$transliterators['any-latin/bgn'] = $transliterator; - } - - $s = $transliterator->transliterate($s); - } - } elseif (!\function_exists('iconv')) { - $s = preg_replace('/[^\x00-\x7F]/u', '?', $s); - } else { - $s = @preg_replace_callback('/[^\x00-\x7F]/u', static function ($c) { - $c = (string) iconv('UTF-8', 'ASCII//TRANSLIT', $c[0]); - - if ('' === $c && '' === iconv('UTF-8', 'ASCII//TRANSLIT', '²')) { - throw new \LogicException(sprintf('"%s" requires a translit-able iconv implementation, try installing "gnu-libiconv" if you\'re using Alpine Linux.', static::class)); - } - - return 1 < \strlen($c) ? ltrim($c, '\'`"^~') : ('' !== $c ? $c : '?'); - }, $s); - } - } - - $str->string .= $s; - - return $str; - } - - public function camel(): parent - { - $str = clone $this; - $str->string = str_replace(' ', '', preg_replace_callback('/\b./u', static function ($m) use (&$i) { - return 1 === ++$i ? ('İ' === $m[0] ? 'i̇' : mb_strtolower($m[0], 'UTF-8')) : mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8'); - }, preg_replace('/[^\pL0-9]++/u', ' ', $this->string))); - - return $str; - } - - /** - * @return int[] - */ - public function codePointsAt(int $offset): array - { - $str = $this->slice($offset, 1); - - if ('' === $str->string) { - return []; - } - - $codePoints = []; - - foreach (preg_split('//u', $str->string, -1, \PREG_SPLIT_NO_EMPTY) as $c) { - $codePoints[] = mb_ord($c, 'UTF-8'); - } - - return $codePoints; - } - - public function folded(bool $compat = true): parent - { - $str = clone $this; - - if (!$compat || \PHP_VERSION_ID < 70300 || !\defined('Normalizer::NFKC_CF')) { - $str->string = normalizer_normalize($str->string, $compat ? \Normalizer::NFKC : \Normalizer::NFC); - $str->string = mb_strtolower(str_replace(self::FOLD_FROM, self::FOLD_TO, $this->string), 'UTF-8'); - } else { - $str->string = normalizer_normalize($str->string, \Normalizer::NFKC_CF); - } - - return $str; - } - - public function join(array $strings, string $lastGlue = null): parent - { - $str = clone $this; - - $tail = null !== $lastGlue && 1 < \count($strings) ? $lastGlue.array_pop($strings) : ''; - $str->string = implode($this->string, $strings).$tail; - - if (!preg_match('//u', $str->string)) { - throw new InvalidArgumentException('Invalid UTF-8 string.'); - } - - return $str; - } - - public function lower(): parent - { - $str = clone $this; - $str->string = mb_strtolower(str_replace('İ', 'i̇', $str->string), 'UTF-8'); - - return $str; - } - - public function match(string $regexp, int $flags = 0, int $offset = 0): array - { - $match = ((\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags) ? 'preg_match_all' : 'preg_match'; - - if ($this->ignoreCase) { - $regexp .= 'i'; - } - - set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); - - try { - if (false === $match($regexp.'u', $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) { - $lastError = preg_last_error(); - - foreach (get_defined_constants(true)['pcre'] as $k => $v) { - if ($lastError === $v && '_ERROR' === substr($k, -6)) { - throw new RuntimeException('Matching failed with '.$k.'.'); - } - } - - throw new RuntimeException('Matching failed with unknown error code.'); - } - } finally { - restore_error_handler(); - } - - return $matches; - } - - /** - * @return static - */ - public function normalize(int $form = self::NFC): self - { - if (!\in_array($form, [self::NFC, self::NFD, self::NFKC, self::NFKD])) { - throw new InvalidArgumentException('Unsupported normalization form.'); - } - - $str = clone $this; - normalizer_is_normalized($str->string, $form) ?: $str->string = normalizer_normalize($str->string, $form); - - return $str; - } - - public function padBoth(int $length, string $padStr = ' '): parent - { - if ('' === $padStr || !preg_match('//u', $padStr)) { - throw new InvalidArgumentException('Invalid UTF-8 string.'); - } - - $pad = clone $this; - $pad->string = $padStr; - - return $this->pad($length, $pad, \STR_PAD_BOTH); - } - - public function padEnd(int $length, string $padStr = ' '): parent - { - if ('' === $padStr || !preg_match('//u', $padStr)) { - throw new InvalidArgumentException('Invalid UTF-8 string.'); - } - - $pad = clone $this; - $pad->string = $padStr; - - return $this->pad($length, $pad, \STR_PAD_RIGHT); - } - - public function padStart(int $length, string $padStr = ' '): parent - { - if ('' === $padStr || !preg_match('//u', $padStr)) { - throw new InvalidArgumentException('Invalid UTF-8 string.'); - } - - $pad = clone $this; - $pad->string = $padStr; - - return $this->pad($length, $pad, \STR_PAD_LEFT); - } - - public function replaceMatches(string $fromRegexp, $to): parent - { - if ($this->ignoreCase) { - $fromRegexp .= 'i'; - } - - if (\is_array($to) || $to instanceof \Closure) { - if (!\is_callable($to)) { - throw new \TypeError(sprintf('Argument 2 passed to "%s::replaceMatches()" must be callable, array given.', static::class)); - } - - $replace = 'preg_replace_callback'; - $to = static function (array $m) use ($to): string { - $to = $to($m); - - if ('' !== $to && (!\is_string($to) || !preg_match('//u', $to))) { - throw new InvalidArgumentException('Replace callback must return a valid UTF-8 string.'); - } - - return $to; - }; - } elseif ('' !== $to && !preg_match('//u', $to)) { - throw new InvalidArgumentException('Invalid UTF-8 string.'); - } else { - $replace = 'preg_replace'; - } - - set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); - - try { - if (null === $string = $replace($fromRegexp.'u', $to, $this->string)) { - $lastError = preg_last_error(); - - foreach (get_defined_constants(true)['pcre'] as $k => $v) { - if ($lastError === $v && '_ERROR' === substr($k, -6)) { - throw new RuntimeException('Matching failed with '.$k.'.'); - } - } - - throw new RuntimeException('Matching failed with unknown error code.'); - } - } finally { - restore_error_handler(); - } - - $str = clone $this; - $str->string = $string; - - return $str; - } - - public function reverse(): parent - { - $str = clone $this; - $str->string = implode('', array_reverse(preg_split('/(\X)/u', $str->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY))); - - return $str; - } - - public function snake(): parent - { - $str = $this->camel()->title(); - $str->string = mb_strtolower(preg_replace(['/(\p{Lu}+)(\p{Lu}\p{Ll})/u', '/([\p{Ll}0-9])(\p{Lu})/u'], '\1_\2', $str->string), 'UTF-8'); - - return $str; - } - - public function title(bool $allWords = false): parent - { - $str = clone $this; - - $limit = $allWords ? -1 : 1; - - $str->string = preg_replace_callback('/\b./u', static function (array $m): string { - return mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8'); - }, $str->string, $limit); - - return $str; - } - - public function trim(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): parent - { - if (" \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}" !== $chars && !preg_match('//u', $chars)) { - throw new InvalidArgumentException('Invalid UTF-8 chars.'); - } - $chars = preg_quote($chars); - - $str = clone $this; - $str->string = preg_replace("{^[$chars]++|[$chars]++$}uD", '', $str->string); - - return $str; - } - - public function trimEnd(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): parent - { - if (" \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}" !== $chars && !preg_match('//u', $chars)) { - throw new InvalidArgumentException('Invalid UTF-8 chars.'); - } - $chars = preg_quote($chars); - - $str = clone $this; - $str->string = preg_replace("{[$chars]++$}uD", '', $str->string); - - return $str; - } - - public function trimPrefix($prefix): parent - { - if (!$this->ignoreCase) { - return parent::trimPrefix($prefix); - } - - $str = clone $this; - - if ($prefix instanceof \Traversable) { - $prefix = iterator_to_array($prefix, false); - } elseif ($prefix instanceof parent) { - $prefix = $prefix->string; - } - - $prefix = implode('|', array_map('preg_quote', (array) $prefix)); - $str->string = preg_replace("{^(?:$prefix)}iuD", '', $this->string); - - return $str; - } - - public function trimStart(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): parent - { - if (" \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}" !== $chars && !preg_match('//u', $chars)) { - throw new InvalidArgumentException('Invalid UTF-8 chars.'); - } - $chars = preg_quote($chars); - - $str = clone $this; - $str->string = preg_replace("{^[$chars]++}uD", '', $str->string); - - return $str; - } - - public function trimSuffix($suffix): parent - { - if (!$this->ignoreCase) { - return parent::trimSuffix($suffix); - } - - $str = clone $this; - - if ($suffix instanceof \Traversable) { - $suffix = iterator_to_array($suffix, false); - } elseif ($suffix instanceof parent) { - $suffix = $suffix->string; - } - - $suffix = implode('|', array_map('preg_quote', (array) $suffix)); - $str->string = preg_replace("{(?:$suffix)$}iuD", '', $this->string); - - return $str; - } - - public function upper(): parent - { - $str = clone $this; - $str->string = mb_strtoupper($str->string, 'UTF-8'); - - if (\PHP_VERSION_ID < 70300) { - $str->string = str_replace(self::UPPER_FROM, self::UPPER_TO, $str->string); - } - - return $str; - } - - public function width(bool $ignoreAnsiDecoration = true): int - { - $width = 0; - $s = str_replace(["\x00", "\x05", "\x07"], '', $this->string); - - if (false !== strpos($s, "\r")) { - $s = str_replace(["\r\n", "\r"], "\n", $s); - } - - if (!$ignoreAnsiDecoration) { - $s = preg_replace('/[\p{Cc}\x7F]++/u', '', $s); - } - - foreach (explode("\n", $s) as $s) { - if ($ignoreAnsiDecoration) { - $s = preg_replace('/(?:\x1B(?: - \[ [\x30-\x3F]*+ [\x20-\x2F]*+ [\x40-\x7E] - | [P\]X^_] .*? \x1B\\\\ - | [\x41-\x7E] - )|[\p{Cc}\x7F]++)/xu', '', $s); - } - - $lineWidth = $this->wcswidth($s); - - if ($lineWidth > $width) { - $width = $lineWidth; - } - } - - return $width; - } - - /** - * @return static - */ - private function pad(int $len, self $pad, int $type): parent - { - $sLen = $this->length(); - - if ($len <= $sLen) { - return clone $this; - } - - $padLen = $pad->length(); - $freeLen = $len - $sLen; - $len = $freeLen % $padLen; - - switch ($type) { - case \STR_PAD_RIGHT: - return $this->append(str_repeat($pad->string, intdiv($freeLen, $padLen)).($len ? $pad->slice(0, $len) : '')); - - case \STR_PAD_LEFT: - return $this->prepend(str_repeat($pad->string, intdiv($freeLen, $padLen)).($len ? $pad->slice(0, $len) : '')); - - case \STR_PAD_BOTH: - $freeLen /= 2; - - $rightLen = ceil($freeLen); - $len = $rightLen % $padLen; - $str = $this->append(str_repeat($pad->string, intdiv($rightLen, $padLen)).($len ? $pad->slice(0, $len) : '')); - - $leftLen = floor($freeLen); - $len = $leftLen % $padLen; - - return $str->prepend(str_repeat($pad->string, intdiv($leftLen, $padLen)).($len ? $pad->slice(0, $len) : '')); - - default: - throw new InvalidArgumentException('Invalid padding type.'); - } - } - - /** - * Based on https://github.com/jquast/wcwidth, a Python implementation of https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c. - */ - private function wcswidth(string $string): int - { - $width = 0; - - foreach (preg_split('//u', $string, -1, \PREG_SPLIT_NO_EMPTY) as $c) { - $codePoint = mb_ord($c, 'UTF-8'); - - if (0 === $codePoint // NULL - || 0x034F === $codePoint // COMBINING GRAPHEME JOINER - || (0x200B <= $codePoint && 0x200F >= $codePoint) // ZERO WIDTH SPACE to RIGHT-TO-LEFT MARK - || 0x2028 === $codePoint // LINE SEPARATOR - || 0x2029 === $codePoint // PARAGRAPH SEPARATOR - || (0x202A <= $codePoint && 0x202E >= $codePoint) // LEFT-TO-RIGHT EMBEDDING to RIGHT-TO-LEFT OVERRIDE - || (0x2060 <= $codePoint && 0x2063 >= $codePoint) // WORD JOINER to INVISIBLE SEPARATOR - ) { - continue; - } - - // Non printable characters - if (32 > $codePoint // C0 control characters - || (0x07F <= $codePoint && 0x0A0 > $codePoint) // C1 control characters and DEL - ) { - return -1; - } - - if (null === self::$tableZero) { - self::$tableZero = require __DIR__.'/Resources/data/wcswidth_table_zero.php'; - } - - if ($codePoint >= self::$tableZero[0][0] && $codePoint <= self::$tableZero[$ubound = \count(self::$tableZero) - 1][1]) { - $lbound = 0; - while ($ubound >= $lbound) { - $mid = floor(($lbound + $ubound) / 2); - - if ($codePoint > self::$tableZero[$mid][1]) { - $lbound = $mid + 1; - } elseif ($codePoint < self::$tableZero[$mid][0]) { - $ubound = $mid - 1; - } else { - continue 2; - } - } - } - - if (null === self::$tableWide) { - self::$tableWide = require __DIR__.'/Resources/data/wcswidth_table_wide.php'; - } - - if ($codePoint >= self::$tableWide[0][0] && $codePoint <= self::$tableWide[$ubound = \count(self::$tableWide) - 1][1]) { - $lbound = 0; - while ($ubound >= $lbound) { - $mid = floor(($lbound + $ubound) / 2); - - if ($codePoint > self::$tableWide[$mid][1]) { - $lbound = $mid + 1; - } elseif ($codePoint < self::$tableWide[$mid][0]) { - $ubound = $mid - 1; - } else { - $width += 2; - - continue 2; - } - } - } - - ++$width; - } - - return $width; - } -} diff --git a/lib/symfony/string/ByteString.php b/lib/symfony/string/ByteString.php deleted file mode 100644 index bbf8614cf..000000000 --- a/lib/symfony/string/ByteString.php +++ /dev/null @@ -1,506 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\String; - -use Symfony\Component\String\Exception\ExceptionInterface; -use Symfony\Component\String\Exception\InvalidArgumentException; -use Symfony\Component\String\Exception\RuntimeException; - -/** - * Represents a binary-safe string of bytes. - * - * @author Nicolas Grekas <p@tchwork.com> - * @author Hugo Hamon <hugohamon@neuf.fr> - * - * @throws ExceptionInterface - */ -class ByteString extends AbstractString -{ - private const ALPHABET_ALPHANUMERIC = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; - - public function __construct(string $string = '') - { - $this->string = $string; - } - - /* - * The following method was derived from code of the Hack Standard Library (v4.40 - 2020-05-03) - * - * https://github.com/hhvm/hsl/blob/80a42c02f036f72a42f0415e80d6b847f4bf62d5/src/random/private.php#L16 - * - * Code subject to the MIT license (https://github.com/hhvm/hsl/blob/master/LICENSE). - * - * Copyright (c) 2004-2020, Facebook, Inc. (https://www.facebook.com/) - */ - - public static function fromRandom(int $length = 16, string $alphabet = null): self - { - if ($length <= 0) { - throw new InvalidArgumentException(sprintf('A strictly positive length is expected, "%d" given.', $length)); - } - - $alphabet = $alphabet ?? self::ALPHABET_ALPHANUMERIC; - $alphabetSize = \strlen($alphabet); - $bits = (int) ceil(log($alphabetSize, 2.0)); - if ($bits <= 0 || $bits > 56) { - throw new InvalidArgumentException('The length of the alphabet must in the [2^1, 2^56] range.'); - } - - $ret = ''; - while ($length > 0) { - $urandomLength = (int) ceil(2 * $length * $bits / 8.0); - $data = random_bytes($urandomLength); - $unpackedData = 0; - $unpackedBits = 0; - for ($i = 0; $i < $urandomLength && $length > 0; ++$i) { - // Unpack 8 bits - $unpackedData = ($unpackedData << 8) | \ord($data[$i]); - $unpackedBits += 8; - - // While we have enough bits to select a character from the alphabet, keep - // consuming the random data - for (; $unpackedBits >= $bits && $length > 0; $unpackedBits -= $bits) { - $index = ($unpackedData & ((1 << $bits) - 1)); - $unpackedData >>= $bits; - // Unfortunately, the alphabet size is not necessarily a power of two. - // Worst case, it is 2^k + 1, which means we need (k+1) bits and we - // have around a 50% chance of missing as k gets larger - if ($index < $alphabetSize) { - $ret .= $alphabet[$index]; - --$length; - } - } - } - } - - return new static($ret); - } - - public function bytesAt(int $offset): array - { - $str = $this->string[$offset] ?? ''; - - return '' === $str ? [] : [\ord($str)]; - } - - public function append(string ...$suffix): parent - { - $str = clone $this; - $str->string .= 1 >= \count($suffix) ? ($suffix[0] ?? '') : implode('', $suffix); - - return $str; - } - - public function camel(): parent - { - $str = clone $this; - $str->string = lcfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $this->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 []; - } - - $str = clone $this; - $chunks = []; - - foreach (str_split($this->string, $length) as $chunk) { - $str->string = $chunk; - $chunks[] = clone $str; - } - - return $chunks; - } - - public function endsWith($suffix): bool - { - if ($suffix instanceof parent) { - $suffix = $suffix->string; - } elseif (\is_array($suffix) || $suffix instanceof \Traversable) { - return parent::endsWith($suffix); - } else { - $suffix = (string) $suffix; - } - - return '' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase); - } - - public function equalsTo($string): bool - { - if ($string instanceof parent) { - $string = $string->string; - } elseif (\is_array($string) || $string instanceof \Traversable) { - return parent::equalsTo($string); - } else { - $string = (string) $string; - } - - if ('' !== $string && $this->ignoreCase) { - return 0 === strcasecmp($string, $this->string); - } - - return $string === $this->string; - } - - public function folded(): parent - { - $str = clone $this; - $str->string = strtolower($str->string); - - return $str; - } - - public function indexOf($needle, int $offset = 0): ?int - { - if ($needle instanceof parent) { - $needle = $needle->string; - } elseif (\is_array($needle) || $needle instanceof \Traversable) { - return parent::indexOf($needle, $offset); - } else { - $needle = (string) $needle; - } - - if ('' === $needle) { - return null; - } - - $i = $this->ignoreCase ? stripos($this->string, $needle, $offset) : strpos($this->string, $needle, $offset); - - return false === $i ? null : $i; - } - - public function indexOfLast($needle, int $offset = 0): ?int - { - if ($needle instanceof parent) { - $needle = $needle->string; - } elseif (\is_array($needle) || $needle instanceof \Traversable) { - return parent::indexOfLast($needle, $offset); - } else { - $needle = (string) $needle; - } - - if ('' === $needle) { - return null; - } - - $i = $this->ignoreCase ? strripos($this->string, $needle, $offset) : strrpos($this->string, $needle, $offset); - - return false === $i ? null : $i; - } - - public function isUtf8(): bool - { - return '' === $this->string || preg_match('//u', $this->string); - } - - public function join(array $strings, string $lastGlue = null): parent - { - $str = clone $this; - - $tail = null !== $lastGlue && 1 < \count($strings) ? $lastGlue.array_pop($strings) : ''; - $str->string = implode($this->string, $strings).$tail; - - return $str; - } - - public function length(): int - { - return \strlen($this->string); - } - - public function lower(): parent - { - $str = clone $this; - $str->string = strtolower($str->string); - - return $str; - } - - public function match(string $regexp, int $flags = 0, int $offset = 0): array - { - $match = ((\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags) ? 'preg_match_all' : 'preg_match'; - - if ($this->ignoreCase) { - $regexp .= 'i'; - } - - set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); - - try { - if (false === $match($regexp, $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) { - $lastError = preg_last_error(); - - foreach (get_defined_constants(true)['pcre'] as $k => $v) { - if ($lastError === $v && '_ERROR' === substr($k, -6)) { - throw new RuntimeException('Matching failed with '.$k.'.'); - } - } - - throw new RuntimeException('Matching failed with unknown error code.'); - } - } finally { - restore_error_handler(); - } - - return $matches; - } - - public function padBoth(int $length, string $padStr = ' '): parent - { - $str = clone $this; - $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_BOTH); - - return $str; - } - - public function padEnd(int $length, string $padStr = ' '): parent - { - $str = clone $this; - $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_RIGHT); - - return $str; - } - - public function padStart(int $length, string $padStr = ' '): parent - { - $str = clone $this; - $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_LEFT); - - return $str; - } - - public function prepend(string ...$prefix): parent - { - $str = clone $this; - $str->string = (1 >= \count($prefix) ? ($prefix[0] ?? '') : implode('', $prefix)).$str->string; - - return $str; - } - - public function replace(string $from, string $to): parent - { - $str = clone $this; - - if ('' !== $from) { - $str->string = $this->ignoreCase ? str_ireplace($from, $to, $this->string) : str_replace($from, $to, $this->string); - } - - return $str; - } - - public function replaceMatches(string $fromRegexp, $to): parent - { - if ($this->ignoreCase) { - $fromRegexp .= 'i'; - } - - if (\is_array($to)) { - if (!\is_callable($to)) { - throw new \TypeError(sprintf('Argument 2 passed to "%s::replaceMatches()" must be callable, array given.', static::class)); - } - - $replace = 'preg_replace_callback'; - } else { - $replace = $to instanceof \Closure ? 'preg_replace_callback' : 'preg_replace'; - } - - set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); - - try { - if (null === $string = $replace($fromRegexp, $to, $this->string)) { - $lastError = preg_last_error(); - - foreach (get_defined_constants(true)['pcre'] as $k => $v) { - if ($lastError === $v && '_ERROR' === substr($k, -6)) { - throw new RuntimeException('Matching failed with '.$k.'.'); - } - } - - throw new RuntimeException('Matching failed with unknown error code.'); - } - } finally { - restore_error_handler(); - } - - $str = clone $this; - $str->string = $string; - - return $str; - } - - public function reverse(): parent - { - $str = clone $this; - $str->string = strrev($str->string); - - return $str; - } - - public function slice(int $start = 0, int $length = null): parent - { - $str = clone $this; - $str->string = (string) substr($this->string, $start, $length ?? \PHP_INT_MAX); - - return $str; - } - - public function snake(): parent - { - $str = $this->camel()->title(); - $str->string = strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], '\1_\2', $str->string)); - - return $str; - } - - public function splice(string $replacement, int $start = 0, int $length = null): parent - { - $str = clone $this; - $str->string = substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX); - - return $str; - } - - public function split(string $delimiter, int $limit = null, int $flags = null): array - { - if (1 > $limit = $limit ?? \PHP_INT_MAX) { - throw new InvalidArgumentException('Split limit must be a positive integer.'); - } - - if ('' === $delimiter) { - throw new InvalidArgumentException('Split delimiter is empty.'); - } - - if (null !== $flags) { - return parent::split($delimiter, $limit, $flags); - } - - $str = clone $this; - $chunks = $this->ignoreCase - ? preg_split('{'.preg_quote($delimiter).'}iD', $this->string, $limit) - : explode($delimiter, $this->string, $limit); - - foreach ($chunks as &$chunk) { - $str->string = $chunk; - $chunk = clone $str; - } - - return $chunks; - } - - public function startsWith($prefix): bool - { - if ($prefix instanceof parent) { - $prefix = $prefix->string; - } elseif (!\is_string($prefix)) { - return parent::startsWith($prefix); - } - - return '' !== $prefix && 0 === ($this->ignoreCase ? strncasecmp($this->string, $prefix, \strlen($prefix)) : strncmp($this->string, $prefix, \strlen($prefix))); - } - - public function title(bool $allWords = false): parent - { - $str = clone $this; - $str->string = $allWords ? ucwords($str->string) : ucfirst($str->string); - - return $str; - } - - public function toUnicodeString(string $fromEncoding = null): UnicodeString - { - return new UnicodeString($this->toCodePointString($fromEncoding)->string); - } - - public function toCodePointString(string $fromEncoding = null): CodePointString - { - $u = new CodePointString(); - - if (\in_array($fromEncoding, [null, 'utf8', 'utf-8', 'UTF8', 'UTF-8'], true) && preg_match('//u', $this->string)) { - $u->string = $this->string; - - return $u; - } - - set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); - - try { - try { - $validEncoding = false !== mb_detect_encoding($this->string, $fromEncoding ?? 'Windows-1252', true); - } catch (InvalidArgumentException $e) { - if (!\function_exists('iconv')) { - throw $e; - } - - $u->string = iconv($fromEncoding ?? 'Windows-1252', 'UTF-8', $this->string); - - return $u; - } - } finally { - restore_error_handler(); - } - - if (!$validEncoding) { - throw new InvalidArgumentException(sprintf('Invalid "%s" string.', $fromEncoding ?? 'Windows-1252')); - } - - $u->string = mb_convert_encoding($this->string, 'UTF-8', $fromEncoding ?? 'Windows-1252'); - - return $u; - } - - public function trim(string $chars = " \t\n\r\0\x0B\x0C"): parent - { - $str = clone $this; - $str->string = trim($str->string, $chars); - - return $str; - } - - public function trimEnd(string $chars = " \t\n\r\0\x0B\x0C"): parent - { - $str = clone $this; - $str->string = rtrim($str->string, $chars); - - return $str; - } - - public function trimStart(string $chars = " \t\n\r\0\x0B\x0C"): parent - { - $str = clone $this; - $str->string = ltrim($str->string, $chars); - - return $str; - } - - public function upper(): parent - { - $str = clone $this; - $str->string = strtoupper($str->string); - - return $str; - } - - public function width(bool $ignoreAnsiDecoration = true): int - { - $string = preg_match('//u', $this->string) ? $this->string : preg_replace('/[\x80-\xFF]/', '?', $this->string); - - return (new CodePointString($string))->width($ignoreAnsiDecoration); - } -} diff --git a/lib/symfony/string/CHANGELOG.md b/lib/symfony/string/CHANGELOG.md deleted file mode 100644 index 53af36400..000000000 --- a/lib/symfony/string/CHANGELOG.md +++ /dev/null @@ -1,35 +0,0 @@ -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/lib/symfony/string/CodePointString.php b/lib/symfony/string/CodePointString.php deleted file mode 100644 index 8ab920941..000000000 --- a/lib/symfony/string/CodePointString.php +++ /dev/null @@ -1,270 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\String; - -use Symfony\Component\String\Exception\ExceptionInterface; -use Symfony\Component\String\Exception\InvalidArgumentException; - -/** - * Represents a string of Unicode code points encoded as UTF-8. - * - * @author Nicolas Grekas <p@tchwork.com> - * @author Hugo Hamon <hugohamon@neuf.fr> - * - * @throws ExceptionInterface - */ -class CodePointString extends AbstractUnicodeString -{ - public function __construct(string $string = '') - { - if ('' !== $string && !preg_match('//u', $string)) { - throw new InvalidArgumentException('Invalid UTF-8 string.'); - } - - $this->string = $string; - } - - public function append(string ...$suffix): AbstractString - { - $str = clone $this; - $str->string .= 1 >= \count($suffix) ? ($suffix[0] ?? '') : implode('', $suffix); - - if (!preg_match('//u', $str->string)) { - throw new InvalidArgumentException('Invalid UTF-8 string.'); - } - - return $str; - } - - public function chunk(int $length = 1): array - { - if (1 > $length) { - throw new InvalidArgumentException('The chunk length must be greater than zero.'); - } - - if ('' === $this->string) { - return []; - } - - $rx = '/('; - while (65535 < $length) { - $rx .= '.{65535}'; - $length -= 65535; - } - $rx .= '.{'.$length.'})/us'; - - $str = clone $this; - $chunks = []; - - foreach (preg_split($rx, $this->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY) as $chunk) { - $str->string = $chunk; - $chunks[] = clone $str; - } - - return $chunks; - } - - public function codePointsAt(int $offset): array - { - $str = $offset ? $this->slice($offset, 1) : $this; - - return '' === $str->string ? [] : [mb_ord($str->string, 'UTF-8')]; - } - - public function endsWith($suffix): bool - { - if ($suffix instanceof AbstractString) { - $suffix = $suffix->string; - } elseif (\is_array($suffix) || $suffix instanceof \Traversable) { - return parent::endsWith($suffix); - } else { - $suffix = (string) $suffix; - } - - if ('' === $suffix || !preg_match('//u', $suffix)) { - return false; - } - - if ($this->ignoreCase) { - return preg_match('{'.preg_quote($suffix).'$}iuD', $this->string); - } - - return \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix)); - } - - public function equalsTo($string): bool - { - if ($string instanceof AbstractString) { - $string = $string->string; - } elseif (\is_array($string) || $string instanceof \Traversable) { - return parent::equalsTo($string); - } else { - $string = (string) $string; - } - - if ('' !== $string && $this->ignoreCase) { - return \strlen($string) === \strlen($this->string) && 0 === mb_stripos($this->string, $string, 0, 'UTF-8'); - } - - return $string === $this->string; - } - - public function indexOf($needle, int $offset = 0): ?int - { - if ($needle instanceof AbstractString) { - $needle = $needle->string; - } elseif (\is_array($needle) || $needle instanceof \Traversable) { - return parent::indexOf($needle, $offset); - } else { - $needle = (string) $needle; - } - - if ('' === $needle) { - return null; - } - - $i = $this->ignoreCase ? mb_stripos($this->string, $needle, $offset, 'UTF-8') : mb_strpos($this->string, $needle, $offset, 'UTF-8'); - - return false === $i ? null : $i; - } - - public function indexOfLast($needle, int $offset = 0): ?int - { - if ($needle instanceof AbstractString) { - $needle = $needle->string; - } elseif (\is_array($needle) || $needle instanceof \Traversable) { - return parent::indexOfLast($needle, $offset); - } else { - $needle = (string) $needle; - } - - if ('' === $needle) { - return null; - } - - $i = $this->ignoreCase ? mb_strripos($this->string, $needle, $offset, 'UTF-8') : mb_strrpos($this->string, $needle, $offset, 'UTF-8'); - - return false === $i ? null : $i; - } - - public function length(): int - { - return mb_strlen($this->string, 'UTF-8'); - } - - public function prepend(string ...$prefix): AbstractString - { - $str = clone $this; - $str->string = (1 >= \count($prefix) ? ($prefix[0] ?? '') : implode('', $prefix)).$this->string; - - if (!preg_match('//u', $str->string)) { - throw new InvalidArgumentException('Invalid UTF-8 string.'); - } - - return $str; - } - - public function replace(string $from, string $to): AbstractString - { - $str = clone $this; - - if ('' === $from || !preg_match('//u', $from)) { - return $str; - } - - if ('' !== $to && !preg_match('//u', $to)) { - throw new InvalidArgumentException('Invalid UTF-8 string.'); - } - - if ($this->ignoreCase) { - $str->string = implode($to, preg_split('{'.preg_quote($from).'}iuD', $this->string)); - } else { - $str->string = str_replace($from, $to, $this->string); - } - - return $str; - } - - public function slice(int $start = 0, int $length = null): AbstractString - { - $str = clone $this; - $str->string = mb_substr($this->string, $start, $length, 'UTF-8'); - - return $str; - } - - public function splice(string $replacement, int $start = 0, int $length = null): AbstractString - { - if (!preg_match('//u', $replacement)) { - throw new InvalidArgumentException('Invalid UTF-8 string.'); - } - - $str = clone $this; - $start = $start ? \strlen(mb_substr($this->string, 0, $start, 'UTF-8')) : 0; - $length = $length ? \strlen(mb_substr($this->string, $start, $length, 'UTF-8')) : $length; - $str->string = substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX); - - return $str; - } - - public function split(string $delimiter, int $limit = null, int $flags = null): array - { - if (1 > $limit = $limit ?? \PHP_INT_MAX) { - throw new InvalidArgumentException('Split limit must be a positive integer.'); - } - - if ('' === $delimiter) { - throw new InvalidArgumentException('Split delimiter is empty.'); - } - - if (null !== $flags) { - return parent::split($delimiter.'u', $limit, $flags); - } - - if (!preg_match('//u', $delimiter)) { - throw new InvalidArgumentException('Split delimiter is not a valid UTF-8 string.'); - } - - $str = clone $this; - $chunks = $this->ignoreCase - ? preg_split('{'.preg_quote($delimiter).'}iuD', $this->string, $limit) - : explode($delimiter, $this->string, $limit); - - foreach ($chunks as &$chunk) { - $str->string = $chunk; - $chunk = clone $str; - } - - return $chunks; - } - - public function startsWith($prefix): bool - { - if ($prefix instanceof AbstractString) { - $prefix = $prefix->string; - } elseif (\is_array($prefix) || $prefix instanceof \Traversable) { - return parent::startsWith($prefix); - } else { - $prefix = (string) $prefix; - } - - if ('' === $prefix || !preg_match('//u', $prefix)) { - return false; - } - - if ($this->ignoreCase) { - return 0 === mb_stripos($this->string, $prefix, 0, 'UTF-8'); - } - - return 0 === strncmp($this->string, $prefix, \strlen($prefix)); - } -} diff --git a/lib/symfony/string/Exception/ExceptionInterface.php b/lib/symfony/string/Exception/ExceptionInterface.php deleted file mode 100644 index 361978656..000000000 --- a/lib/symfony/string/Exception/ExceptionInterface.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\String\Exception; - -interface ExceptionInterface extends \Throwable -{ -} diff --git a/lib/symfony/string/Exception/InvalidArgumentException.php b/lib/symfony/string/Exception/InvalidArgumentException.php deleted file mode 100644 index 6aa586bcf..000000000 --- a/lib/symfony/string/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\String\Exception; - -class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/lib/symfony/string/Exception/RuntimeException.php b/lib/symfony/string/Exception/RuntimeException.php deleted file mode 100644 index 77cb091f9..000000000 --- a/lib/symfony/string/Exception/RuntimeException.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\String\Exception; - -class RuntimeException extends \RuntimeException implements ExceptionInterface -{ -} diff --git a/lib/symfony/string/Inflector/EnglishInflector.php b/lib/symfony/string/Inflector/EnglishInflector.php deleted file mode 100644 index 9f2fac675..000000000 --- a/lib/symfony/string/Inflector/EnglishInflector.php +++ /dev/null @@ -1,511 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\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/lib/symfony/string/Inflector/FrenchInflector.php b/lib/symfony/string/Inflector/FrenchInflector.php deleted file mode 100644 index 612c8f2e0..000000000 --- a/lib/symfony/string/Inflector/FrenchInflector.php +++ /dev/null @@ -1,157 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\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/lib/symfony/string/Inflector/InflectorInterface.php b/lib/symfony/string/Inflector/InflectorInterface.php deleted file mode 100644 index 67f283404..000000000 --- a/lib/symfony/string/Inflector/InflectorInterface.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\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/lib/symfony/string/LICENSE b/lib/symfony/string/LICENSE deleted file mode 100644 index 9c907a46a..000000000 --- a/lib/symfony/string/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2019-2022 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -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/lib/symfony/string/LazyString.php b/lib/symfony/string/LazyString.php deleted file mode 100644 index 3b10595f3..000000000 --- a/lib/symfony/string/LazyString.php +++ /dev/null @@ -1,164 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\String; - -/** - * A string whose value is computed lazily by a callback. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class LazyString implements \Stringable, \JsonSerializable -{ - private $value; - - /** - * @param callable|array $callback A callable or a [Closure, method] lazy-callable - * - * @return static - */ - public static function fromCallable($callback, ...$arguments): self - { - if (!\is_callable($callback) && !(\is_array($callback) && isset($callback[0]) && $callback[0] instanceof \Closure && 2 >= \count($callback))) { - throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a callable or a [Closure, method] lazy-callable, "%s" given.', __METHOD__, get_debug_type($callback))); - } - - $lazyString = new static(); - $lazyString->value = static function () use (&$callback, &$arguments, &$value): string { - if (null !== $arguments) { - if (!\is_callable($callback)) { - $callback[0] = $callback[0](); - $callback[1] = $callback[1] ?? '__invoke'; - } - $value = $callback(...$arguments); - $callback = self::getPrettyName($callback); - $arguments = null; - } - - return $value ?? ''; - }; - - return $lazyString; - } - - /** - * @param string|int|float|bool|\Stringable $value - * - * @return static - */ - public static function fromStringable($value): self - { - if (!self::isStringable($value)) { - throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a scalar or a stringable object, "%s" given.', __METHOD__, get_debug_type($value))); - } - - if (\is_object($value)) { - return static::fromCallable([$value, '__toString']); - } - - $lazyString = new static(); - $lazyString->value = (string) $value; - - return $lazyString; - } - - /** - * Tells whether the provided value can be cast to string. - */ - final public static function isStringable($value): bool - { - return \is_string($value) || $value instanceof self || (\is_object($value) ? method_exists($value, '__toString') : \is_scalar($value)); - } - - /** - * Casts scalars and stringable objects to strings. - * - * @param object|string|int|float|bool $value - * - * @throws \TypeError When the provided value is not stringable - */ - final public static function resolve($value): string - { - return $value; - } - - /** - * @return string - */ - public function __toString() - { - if (\is_string($this->value)) { - return $this->value; - } - - try { - return $this->value = ($this->value)(); - } catch (\Throwable $e) { - if (\TypeError::class === \get_class($e) && __FILE__ === $e->getFile()) { - $type = explode(', ', $e->getMessage()); - $type = substr(array_pop($type), 0, -\strlen(' returned')); - $r = new \ReflectionFunction($this->value); - $callback = $r->getStaticVariables()['callback']; - - $e = new \TypeError(sprintf('Return value of %s() passed to %s::fromCallable() must be of the type string, %s returned.', $callback, static::class, $type)); - } - - if (\PHP_VERSION_ID < 70400) { - // leverage the ErrorHandler component with graceful fallback when it's not available - return trigger_error($e, \E_USER_ERROR); - } - - throw $e; - } - } - - public function __sleep(): array - { - $this->__toString(); - - return ['value']; - } - - public function jsonSerialize(): string - { - return $this->__toString(); - } - - private function __construct() - { - } - - private static function getPrettyName(callable $callback): string - { - if (\is_string($callback)) { - return $callback; - } - - if (\is_array($callback)) { - $class = \is_object($callback[0]) ? get_debug_type($callback[0]) : $callback[0]; - $method = $callback[1]; - } elseif ($callback instanceof \Closure) { - $r = new \ReflectionFunction($callback); - - if (false !== strpos($r->name, '{closure}') || !$class = $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/lib/symfony/string/README.md b/lib/symfony/string/README.md deleted file mode 100644 index 9c7e1e190..000000000 --- a/lib/symfony/string/README.md +++ /dev/null @@ -1,14 +0,0 @@ -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/lib/symfony/string/Resources/data/wcswidth_table_wide.php b/lib/symfony/string/Resources/data/wcswidth_table_wide.php deleted file mode 100644 index 43c802d05..000000000 --- a/lib/symfony/string/Resources/data/wcswidth_table_wide.php +++ /dev/null @@ -1,1135 +0,0 @@ -<?php - -/* - * This file has been auto-generated by the Symfony String Component for internal use. - * - * Unicode version: 14.0.0 - * Date: 2021-09-17T09:20:30+02:00 - */ - -return [ - [ - 4352, - 4447, - ], - [ - 8986, - 8987, - ], - [ - 9001, - 9001, - ], - [ - 9002, - 9002, - ], - [ - 9193, - 9196, - ], - [ - 9200, - 9200, - ], - [ - 9203, - 9203, - ], - [ - 9725, - 9726, - ], - [ - 9748, - 9749, - ], - [ - 9800, - 9811, - ], - [ - 9855, - 9855, - ], - [ - 9875, - 9875, - ], - [ - 9889, - 9889, - ], - [ - 9898, - 9899, - ], - [ - 9917, - 9918, - ], - [ - 9924, - 9925, - ], - [ - 9934, - 9934, - ], - [ - 9940, - 9940, - ], - [ - 9962, - 9962, - ], - [ - 9970, - 9971, - ], - [ - 9973, - 9973, - ], - [ - 9978, - 9978, - ], - [ - 9981, - 9981, - ], - [ - 9989, - 9989, - ], - [ - 9994, - 9995, - ], - [ - 10024, - 10024, - ], - [ - 10060, - 10060, - ], - [ - 10062, - 10062, - ], - [ - 10067, - 10069, - ], - [ - 10071, - 10071, - ], - [ - 10133, - 10135, - ], - [ - 10160, - 10160, - ], - [ - 10175, - 10175, - ], - [ - 11035, - 11036, - ], - [ - 11088, - 11088, - ], - [ - 11093, - 11093, - ], - [ - 11904, - 11929, - ], - [ - 11931, - 12019, - ], - [ - 12032, - 12245, - ], - [ - 12272, - 12283, - ], - [ - 12288, - 12288, - ], - [ - 12289, - 12291, - ], - [ - 12292, - 12292, - ], - [ - 12293, - 12293, - ], - [ - 12294, - 12294, - ], - [ - 12295, - 12295, - ], - [ - 12296, - 12296, - ], - [ - 12297, - 12297, - ], - [ - 12298, - 12298, - ], - [ - 12299, - 12299, - ], - [ - 12300, - 12300, - ], - [ - 12301, - 12301, - ], - [ - 12302, - 12302, - ], - [ - 12303, - 12303, - ], - [ - 12304, - 12304, - ], - [ - 12305, - 12305, - ], - [ - 12306, - 12307, - ], - [ - 12308, - 12308, - ], - [ - 12309, - 12309, - ], - [ - 12310, - 12310, - ], - [ - 12311, - 12311, - ], - [ - 12312, - 12312, - ], - [ - 12313, - 12313, - ], - [ - 12314, - 12314, - ], - [ - 12315, - 12315, - ], - [ - 12316, - 12316, - ], - [ - 12317, - 12317, - ], - [ - 12318, - 12319, - ], - [ - 12320, - 12320, - ], - [ - 12321, - 12329, - ], - [ - 12330, - 12333, - ], - [ - 12334, - 12335, - ], - [ - 12336, - 12336, - ], - [ - 12337, - 12341, - ], - [ - 12342, - 12343, - ], - [ - 12344, - 12346, - ], - [ - 12347, - 12347, - ], - [ - 12348, - 12348, - ], - [ - 12349, - 12349, - ], - [ - 12350, - 12350, - ], - [ - 12353, - 12438, - ], - [ - 12441, - 12442, - ], - [ - 12443, - 12444, - ], - [ - 12445, - 12446, - ], - [ - 12447, - 12447, - ], - [ - 12448, - 12448, - ], - [ - 12449, - 12538, - ], - [ - 12539, - 12539, - ], - [ - 12540, - 12542, - ], - [ - 12543, - 12543, - ], - [ - 12549, - 12591, - ], - [ - 12593, - 12686, - ], - [ - 12688, - 12689, - ], - [ - 12690, - 12693, - ], - [ - 12694, - 12703, - ], - [ - 12704, - 12735, - ], - [ - 12736, - 12771, - ], - [ - 12784, - 12799, - ], - [ - 12800, - 12830, - ], - [ - 12832, - 12841, - ], - [ - 12842, - 12871, - ], - [ - 12880, - 12880, - ], - [ - 12881, - 12895, - ], - [ - 12896, - 12927, - ], - [ - 12928, - 12937, - ], - [ - 12938, - 12976, - ], - [ - 12977, - 12991, - ], - [ - 12992, - 13055, - ], - [ - 13056, - 13311, - ], - [ - 13312, - 19903, - ], - [ - 19968, - 40959, - ], - [ - 40960, - 40980, - ], - [ - 40981, - 40981, - ], - [ - 40982, - 42124, - ], - [ - 42128, - 42182, - ], - [ - 43360, - 43388, - ], - [ - 44032, - 55203, - ], - [ - 63744, - 64109, - ], - [ - 64110, - 64111, - ], - [ - 64112, - 64217, - ], - [ - 64218, - 64255, - ], - [ - 65040, - 65046, - ], - [ - 65047, - 65047, - ], - [ - 65048, - 65048, - ], - [ - 65049, - 65049, - ], - [ - 65072, - 65072, - ], - [ - 65073, - 65074, - ], - [ - 65075, - 65076, - ], - [ - 65077, - 65077, - ], - [ - 65078, - 65078, - ], - [ - 65079, - 65079, - ], - [ - 65080, - 65080, - ], - [ - 65081, - 65081, - ], - [ - 65082, - 65082, - ], - [ - 65083, - 65083, - ], - [ - 65084, - 65084, - ], - [ - 65085, - 65085, - ], - [ - 65086, - 65086, - ], - [ - 65087, - 65087, - ], - [ - 65088, - 65088, - ], - [ - 65089, - 65089, - ], - [ - 65090, - 65090, - ], - [ - 65091, - 65091, - ], - [ - 65092, - 65092, - ], - [ - 65093, - 65094, - ], - [ - 65095, - 65095, - ], - [ - 65096, - 65096, - ], - [ - 65097, - 65100, - ], - [ - 65101, - 65103, - ], - [ - 65104, - 65106, - ], - [ - 65108, - 65111, - ], - [ - 65112, - 65112, - ], - [ - 65113, - 65113, - ], - [ - 65114, - 65114, - ], - [ - 65115, - 65115, - ], - [ - 65116, - 65116, - ], - [ - 65117, - 65117, - ], - [ - 65118, - 65118, - ], - [ - 65119, - 65121, - ], - [ - 65122, - 65122, - ], - [ - 65123, - 65123, - ], - [ - 65124, - 65126, - ], - [ - 65128, - 65128, - ], - [ - 65129, - 65129, - ], - [ - 65130, - 65131, - ], - [ - 65281, - 65283, - ], - [ - 65284, - 65284, - ], - [ - 65285, - 65287, - ], - [ - 65288, - 65288, - ], - [ - 65289, - 65289, - ], - [ - 65290, - 65290, - ], - [ - 65291, - 65291, - ], - [ - 65292, - 65292, - ], - [ - 65293, - 65293, - ], - [ - 65294, - 65295, - ], - [ - 65296, - 65305, - ], - [ - 65306, - 65307, - ], - [ - 65308, - 65310, - ], - [ - 65311, - 65312, - ], - [ - 65313, - 65338, - ], - [ - 65339, - 65339, - ], - [ - 65340, - 65340, - ], - [ - 65341, - 65341, - ], - [ - 65342, - 65342, - ], - [ - 65343, - 65343, - ], - [ - 65344, - 65344, - ], - [ - 65345, - 65370, - ], - [ - 65371, - 65371, - ], - [ - 65372, - 65372, - ], - [ - 65373, - 65373, - ], - [ - 65374, - 65374, - ], - [ - 65375, - 65375, - ], - [ - 65376, - 65376, - ], - [ - 65504, - 65505, - ], - [ - 65506, - 65506, - ], - [ - 65507, - 65507, - ], - [ - 65508, - 65508, - ], - [ - 65509, - 65510, - ], - [ - 94176, - 94177, - ], - [ - 94178, - 94178, - ], - [ - 94179, - 94179, - ], - [ - 94180, - 94180, - ], - [ - 94192, - 94193, - ], - [ - 94208, - 100343, - ], - [ - 100352, - 101119, - ], - [ - 101120, - 101589, - ], - [ - 101632, - 101640, - ], - [ - 110576, - 110579, - ], - [ - 110581, - 110587, - ], - [ - 110589, - 110590, - ], - [ - 110592, - 110847, - ], - [ - 110848, - 110882, - ], - [ - 110928, - 110930, - ], - [ - 110948, - 110951, - ], - [ - 110960, - 111355, - ], - [ - 126980, - 126980, - ], - [ - 127183, - 127183, - ], - [ - 127374, - 127374, - ], - [ - 127377, - 127386, - ], - [ - 127488, - 127490, - ], - [ - 127504, - 127547, - ], - [ - 127552, - 127560, - ], - [ - 127568, - 127569, - ], - [ - 127584, - 127589, - ], - [ - 127744, - 127776, - ], - [ - 127789, - 127797, - ], - [ - 127799, - 127868, - ], - [ - 127870, - 127891, - ], - [ - 127904, - 127946, - ], - [ - 127951, - 127955, - ], - [ - 127968, - 127984, - ], - [ - 127988, - 127988, - ], - [ - 127992, - 127994, - ], - [ - 127995, - 127999, - ], - [ - 128000, - 128062, - ], - [ - 128064, - 128064, - ], - [ - 128066, - 128252, - ], - [ - 128255, - 128317, - ], - [ - 128331, - 128334, - ], - [ - 128336, - 128359, - ], - [ - 128378, - 128378, - ], - [ - 128405, - 128406, - ], - [ - 128420, - 128420, - ], - [ - 128507, - 128511, - ], - [ - 128512, - 128591, - ], - [ - 128640, - 128709, - ], - [ - 128716, - 128716, - ], - [ - 128720, - 128722, - ], - [ - 128725, - 128727, - ], - [ - 128733, - 128735, - ], - [ - 128747, - 128748, - ], - [ - 128756, - 128764, - ], - [ - 128992, - 129003, - ], - [ - 129008, - 129008, - ], - [ - 129292, - 129338, - ], - [ - 129340, - 129349, - ], - [ - 129351, - 129535, - ], - [ - 129648, - 129652, - ], - [ - 129656, - 129660, - ], - [ - 129664, - 129670, - ], - [ - 129680, - 129708, - ], - [ - 129712, - 129722, - ], - [ - 129728, - 129733, - ], - [ - 129744, - 129753, - ], - [ - 129760, - 129767, - ], - [ - 129776, - 129782, - ], - [ - 131072, - 173791, - ], - [ - 173792, - 173823, - ], - [ - 173824, - 177976, - ], - [ - 177977, - 177983, - ], - [ - 177984, - 178205, - ], - [ - 178206, - 178207, - ], - [ - 178208, - 183969, - ], - [ - 183970, - 183983, - ], - [ - 183984, - 191456, - ], - [ - 191457, - 194559, - ], - [ - 194560, - 195101, - ], - [ - 195102, - 195103, - ], - [ - 195104, - 196605, - ], - [ - 196608, - 201546, - ], - [ - 201547, - 262141, - ], -]; diff --git a/lib/symfony/string/Resources/data/wcswidth_table_zero.php b/lib/symfony/string/Resources/data/wcswidth_table_zero.php deleted file mode 100644 index 63b082473..000000000 --- a/lib/symfony/string/Resources/data/wcswidth_table_zero.php +++ /dev/null @@ -1,1375 +0,0 @@ -<?php - -/* - * This file has been auto-generated by the Symfony String Component for internal use. - * - * Unicode version: 14.0.0 - * Date: 2021-09-17T09:20:30+02:00 - */ - -return [ - [ - 768, - 879, - ], - [ - 1155, - 1159, - ], - [ - 1160, - 1161, - ], - [ - 1425, - 1469, - ], - [ - 1471, - 1471, - ], - [ - 1473, - 1474, - ], - [ - 1476, - 1477, - ], - [ - 1479, - 1479, - ], - [ - 1552, - 1562, - ], - [ - 1611, - 1631, - ], - [ - 1648, - 1648, - ], - [ - 1750, - 1756, - ], - [ - 1759, - 1764, - ], - [ - 1767, - 1768, - ], - [ - 1770, - 1773, - ], - [ - 1809, - 1809, - ], - [ - 1840, - 1866, - ], - [ - 1958, - 1968, - ], - [ - 2027, - 2035, - ], - [ - 2045, - 2045, - ], - [ - 2070, - 2073, - ], - [ - 2075, - 2083, - ], - [ - 2085, - 2087, - ], - [ - 2089, - 2093, - ], - [ - 2137, - 2139, - ], - [ - 2200, - 2207, - ], - [ - 2250, - 2273, - ], - [ - 2275, - 2306, - ], - [ - 2362, - 2362, - ], - [ - 2364, - 2364, - ], - [ - 2369, - 2376, - ], - [ - 2381, - 2381, - ], - [ - 2385, - 2391, - ], - [ - 2402, - 2403, - ], - [ - 2433, - 2433, - ], - [ - 2492, - 2492, - ], - [ - 2497, - 2500, - ], - [ - 2509, - 2509, - ], - [ - 2530, - 2531, - ], - [ - 2558, - 2558, - ], - [ - 2561, - 2562, - ], - [ - 2620, - 2620, - ], - [ - 2625, - 2626, - ], - [ - 2631, - 2632, - ], - [ - 2635, - 2637, - ], - [ - 2641, - 2641, - ], - [ - 2672, - 2673, - ], - [ - 2677, - 2677, - ], - [ - 2689, - 2690, - ], - [ - 2748, - 2748, - ], - [ - 2753, - 2757, - ], - [ - 2759, - 2760, - ], - [ - 2765, - 2765, - ], - [ - 2786, - 2787, - ], - [ - 2810, - 2815, - ], - [ - 2817, - 2817, - ], - [ - 2876, - 2876, - ], - [ - 2879, - 2879, - ], - [ - 2881, - 2884, - ], - [ - 2893, - 2893, - ], - [ - 2901, - 2902, - ], - [ - 2914, - 2915, - ], - [ - 2946, - 2946, - ], - [ - 3008, - 3008, - ], - [ - 3021, - 3021, - ], - [ - 3072, - 3072, - ], - [ - 3076, - 3076, - ], - [ - 3132, - 3132, - ], - [ - 3134, - 3136, - ], - [ - 3142, - 3144, - ], - [ - 3146, - 3149, - ], - [ - 3157, - 3158, - ], - [ - 3170, - 3171, - ], - [ - 3201, - 3201, - ], - [ - 3260, - 3260, - ], - [ - 3263, - 3263, - ], - [ - 3270, - 3270, - ], - [ - 3276, - 3277, - ], - [ - 3298, - 3299, - ], - [ - 3328, - 3329, - ], - [ - 3387, - 3388, - ], - [ - 3393, - 3396, - ], - [ - 3405, - 3405, - ], - [ - 3426, - 3427, - ], - [ - 3457, - 3457, - ], - [ - 3530, - 3530, - ], - [ - 3538, - 3540, - ], - [ - 3542, - 3542, - ], - [ - 3633, - 3633, - ], - [ - 3636, - 3642, - ], - [ - 3655, - 3662, - ], - [ - 3761, - 3761, - ], - [ - 3764, - 3772, - ], - [ - 3784, - 3789, - ], - [ - 3864, - 3865, - ], - [ - 3893, - 3893, - ], - [ - 3895, - 3895, - ], - [ - 3897, - 3897, - ], - [ - 3953, - 3966, - ], - [ - 3968, - 3972, - ], - [ - 3974, - 3975, - ], - [ - 3981, - 3991, - ], - [ - 3993, - 4028, - ], - [ - 4038, - 4038, - ], - [ - 4141, - 4144, - ], - [ - 4146, - 4151, - ], - [ - 4153, - 4154, - ], - [ - 4157, - 4158, - ], - [ - 4184, - 4185, - ], - [ - 4190, - 4192, - ], - [ - 4209, - 4212, - ], - [ - 4226, - 4226, - ], - [ - 4229, - 4230, - ], - [ - 4237, - 4237, - ], - [ - 4253, - 4253, - ], - [ - 4957, - 4959, - ], - [ - 5906, - 5908, - ], - [ - 5938, - 5939, - ], - [ - 5970, - 5971, - ], - [ - 6002, - 6003, - ], - [ - 6068, - 6069, - ], - [ - 6071, - 6077, - ], - [ - 6086, - 6086, - ], - [ - 6089, - 6099, - ], - [ - 6109, - 6109, - ], - [ - 6155, - 6157, - ], - [ - 6159, - 6159, - ], - [ - 6277, - 6278, - ], - [ - 6313, - 6313, - ], - [ - 6432, - 6434, - ], - [ - 6439, - 6440, - ], - [ - 6450, - 6450, - ], - [ - 6457, - 6459, - ], - [ - 6679, - 6680, - ], - [ - 6683, - 6683, - ], - [ - 6742, - 6742, - ], - [ - 6744, - 6750, - ], - [ - 6752, - 6752, - ], - [ - 6754, - 6754, - ], - [ - 6757, - 6764, - ], - [ - 6771, - 6780, - ], - [ - 6783, - 6783, - ], - [ - 6832, - 6845, - ], - [ - 6846, - 6846, - ], - [ - 6847, - 6862, - ], - [ - 6912, - 6915, - ], - [ - 6964, - 6964, - ], - [ - 6966, - 6970, - ], - [ - 6972, - 6972, - ], - [ - 6978, - 6978, - ], - [ - 7019, - 7027, - ], - [ - 7040, - 7041, - ], - [ - 7074, - 7077, - ], - [ - 7080, - 7081, - ], - [ - 7083, - 7085, - ], - [ - 7142, - 7142, - ], - [ - 7144, - 7145, - ], - [ - 7149, - 7149, - ], - [ - 7151, - 7153, - ], - [ - 7212, - 7219, - ], - [ - 7222, - 7223, - ], - [ - 7376, - 7378, - ], - [ - 7380, - 7392, - ], - [ - 7394, - 7400, - ], - [ - 7405, - 7405, - ], - [ - 7412, - 7412, - ], - [ - 7416, - 7417, - ], - [ - 7616, - 7679, - ], - [ - 8400, - 8412, - ], - [ - 8413, - 8416, - ], - [ - 8417, - 8417, - ], - [ - 8418, - 8420, - ], - [ - 8421, - 8432, - ], - [ - 11503, - 11505, - ], - [ - 11647, - 11647, - ], - [ - 11744, - 11775, - ], - [ - 12330, - 12333, - ], - [ - 12441, - 12442, - ], - [ - 42607, - 42607, - ], - [ - 42608, - 42610, - ], - [ - 42612, - 42621, - ], - [ - 42654, - 42655, - ], - [ - 42736, - 42737, - ], - [ - 43010, - 43010, - ], - [ - 43014, - 43014, - ], - [ - 43019, - 43019, - ], - [ - 43045, - 43046, - ], - [ - 43052, - 43052, - ], - [ - 43204, - 43205, - ], - [ - 43232, - 43249, - ], - [ - 43263, - 43263, - ], - [ - 43302, - 43309, - ], - [ - 43335, - 43345, - ], - [ - 43392, - 43394, - ], - [ - 43443, - 43443, - ], - [ - 43446, - 43449, - ], - [ - 43452, - 43453, - ], - [ - 43493, - 43493, - ], - [ - 43561, - 43566, - ], - [ - 43569, - 43570, - ], - [ - 43573, - 43574, - ], - [ - 43587, - 43587, - ], - [ - 43596, - 43596, - ], - [ - 43644, - 43644, - ], - [ - 43696, - 43696, - ], - [ - 43698, - 43700, - ], - [ - 43703, - 43704, - ], - [ - 43710, - 43711, - ], - [ - 43713, - 43713, - ], - [ - 43756, - 43757, - ], - [ - 43766, - 43766, - ], - [ - 44005, - 44005, - ], - [ - 44008, - 44008, - ], - [ - 44013, - 44013, - ], - [ - 64286, - 64286, - ], - [ - 65024, - 65039, - ], - [ - 65056, - 65071, - ], - [ - 66045, - 66045, - ], - [ - 66272, - 66272, - ], - [ - 66422, - 66426, - ], - [ - 68097, - 68099, - ], - [ - 68101, - 68102, - ], - [ - 68108, - 68111, - ], - [ - 68152, - 68154, - ], - [ - 68159, - 68159, - ], - [ - 68325, - 68326, - ], - [ - 68900, - 68903, - ], - [ - 69291, - 69292, - ], - [ - 69446, - 69456, - ], - [ - 69506, - 69509, - ], - [ - 69633, - 69633, - ], - [ - 69688, - 69702, - ], - [ - 69744, - 69744, - ], - [ - 69747, - 69748, - ], - [ - 69759, - 69761, - ], - [ - 69811, - 69814, - ], - [ - 69817, - 69818, - ], - [ - 69826, - 69826, - ], - [ - 69888, - 69890, - ], - [ - 69927, - 69931, - ], - [ - 69933, - 69940, - ], - [ - 70003, - 70003, - ], - [ - 70016, - 70017, - ], - [ - 70070, - 70078, - ], - [ - 70089, - 70092, - ], - [ - 70095, - 70095, - ], - [ - 70191, - 70193, - ], - [ - 70196, - 70196, - ], - [ - 70198, - 70199, - ], - [ - 70206, - 70206, - ], - [ - 70367, - 70367, - ], - [ - 70371, - 70378, - ], - [ - 70400, - 70401, - ], - [ - 70459, - 70460, - ], - [ - 70464, - 70464, - ], - [ - 70502, - 70508, - ], - [ - 70512, - 70516, - ], - [ - 70712, - 70719, - ], - [ - 70722, - 70724, - ], - [ - 70726, - 70726, - ], - [ - 70750, - 70750, - ], - [ - 70835, - 70840, - ], - [ - 70842, - 70842, - ], - [ - 70847, - 70848, - ], - [ - 70850, - 70851, - ], - [ - 71090, - 71093, - ], - [ - 71100, - 71101, - ], - [ - 71103, - 71104, - ], - [ - 71132, - 71133, - ], - [ - 71219, - 71226, - ], - [ - 71229, - 71229, - ], - [ - 71231, - 71232, - ], - [ - 71339, - 71339, - ], - [ - 71341, - 71341, - ], - [ - 71344, - 71349, - ], - [ - 71351, - 71351, - ], - [ - 71453, - 71455, - ], - [ - 71458, - 71461, - ], - [ - 71463, - 71467, - ], - [ - 71727, - 71735, - ], - [ - 71737, - 71738, - ], - [ - 71995, - 71996, - ], - [ - 71998, - 71998, - ], - [ - 72003, - 72003, - ], - [ - 72148, - 72151, - ], - [ - 72154, - 72155, - ], - [ - 72160, - 72160, - ], - [ - 72193, - 72202, - ], - [ - 72243, - 72248, - ], - [ - 72251, - 72254, - ], - [ - 72263, - 72263, - ], - [ - 72273, - 72278, - ], - [ - 72281, - 72283, - ], - [ - 72330, - 72342, - ], - [ - 72344, - 72345, - ], - [ - 72752, - 72758, - ], - [ - 72760, - 72765, - ], - [ - 72767, - 72767, - ], - [ - 72850, - 72871, - ], - [ - 72874, - 72880, - ], - [ - 72882, - 72883, - ], - [ - 72885, - 72886, - ], - [ - 73009, - 73014, - ], - [ - 73018, - 73018, - ], - [ - 73020, - 73021, - ], - [ - 73023, - 73029, - ], - [ - 73031, - 73031, - ], - [ - 73104, - 73105, - ], - [ - 73109, - 73109, - ], - [ - 73111, - 73111, - ], - [ - 73459, - 73460, - ], - [ - 92912, - 92916, - ], - [ - 92976, - 92982, - ], - [ - 94031, - 94031, - ], - [ - 94095, - 94098, - ], - [ - 94180, - 94180, - ], - [ - 113821, - 113822, - ], - [ - 118528, - 118573, - ], - [ - 118576, - 118598, - ], - [ - 119143, - 119145, - ], - [ - 119163, - 119170, - ], - [ - 119173, - 119179, - ], - [ - 119210, - 119213, - ], - [ - 119362, - 119364, - ], - [ - 121344, - 121398, - ], - [ - 121403, - 121452, - ], - [ - 121461, - 121461, - ], - [ - 121476, - 121476, - ], - [ - 121499, - 121503, - ], - [ - 121505, - 121519, - ], - [ - 122880, - 122886, - ], - [ - 122888, - 122904, - ], - [ - 122907, - 122913, - ], - [ - 122915, - 122916, - ], - [ - 122918, - 122922, - ], - [ - 123184, - 123190, - ], - [ - 123566, - 123566, - ], - [ - 123628, - 123631, - ], - [ - 125136, - 125142, - ], - [ - 125252, - 125258, - ], - [ - 917760, - 917999, - ], -]; diff --git a/lib/symfony/string/Resources/functions.php b/lib/symfony/string/Resources/functions.php deleted file mode 100644 index c950894f3..000000000 --- a/lib/symfony/string/Resources/functions.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\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/lib/symfony/string/Slugger/AsciiSlugger.php b/lib/symfony/string/Slugger/AsciiSlugger.php deleted file mode 100644 index 5aecfeb5f..000000000 --- a/lib/symfony/string/Slugger/AsciiSlugger.php +++ /dev/null @@ -1,183 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\String\Slugger; - -use Symfony\Component\String\AbstractUnicodeString; -use Symfony\Component\String\UnicodeString; -use Symfony\Contracts\Translation\LocaleAwareInterface; - -if (!interface_exists(LocaleAwareInterface::class)) { - throw new \LogicException('You cannot use the "Symfony\Component\String\Slugger\AsciiSlugger" as the "symfony/translation-contracts" package is not installed. Try running "composer require symfony/translation-contracts".'); -} - -/** - * @author Titouan Galopin <galopintitouan@gmail.com> - */ -class AsciiSlugger implements SluggerInterface, LocaleAwareInterface -{ - private const LOCALE_TO_TRANSLITERATOR_ID = [ - 'am' => 'Amharic-Latin', - 'ar' => 'Arabic-Latin', - 'az' => 'Azerbaijani-Latin', - 'be' => 'Belarusian-Latin', - 'bg' => 'Bulgarian-Latin', - 'bn' => 'Bengali-Latin', - 'de' => 'de-ASCII', - 'el' => 'Greek-Latin', - 'fa' => 'Persian-Latin', - 'he' => 'Hebrew-Latin', - 'hy' => 'Armenian-Latin', - 'ka' => 'Georgian-Latin', - 'kk' => 'Kazakh-Latin', - 'ky' => 'Kirghiz-Latin', - 'ko' => 'Korean-Latin', - 'mk' => 'Macedonian-Latin', - 'mn' => 'Mongolian-Latin', - 'or' => 'Oriya-Latin', - 'ps' => 'Pashto-Latin', - 'ru' => 'Russian-Latin', - 'sr' => 'Serbian-Latin', - 'sr_Cyrl' => 'Serbian-Latin', - 'th' => 'Thai-Latin', - 'tk' => 'Turkmen-Latin', - 'uk' => 'Ukrainian-Latin', - 'uz' => 'Uzbek-Latin', - 'zh' => 'Han-Latin', - ]; - - private $defaultLocale; - private $symbolsMap = [ - 'en' => ['@' => 'at', '&' => 'and'], - ]; - - /** - * Cache of transliterators per locale. - * - * @var \Transliterator[] - */ - private $transliterators = []; - - /** - * @param array|\Closure|null $symbolsMap - */ - public function __construct(string $defaultLocale = null, $symbolsMap = null) - { - if (null !== $symbolsMap && !\is_array($symbolsMap) && !$symbolsMap instanceof \Closure) { - throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be array, Closure or null, "%s" given.', __METHOD__, \gettype($symbolsMap))); - } - - $this->defaultLocale = $defaultLocale; - $this->symbolsMap = $symbolsMap ?? $this->symbolsMap; - } - - /** - * {@inheritdoc} - */ - public function setLocale($locale) - { - $this->defaultLocale = $locale; - } - - /** - * {@inheritdoc} - */ - public function getLocale() - { - return $this->defaultLocale; - } - - /** - * {@inheritdoc} - */ - public function slug(string $string, string $separator = '-', string $locale = null): AbstractUnicodeString - { - $locale = $locale ?? $this->defaultLocale; - - $transliterator = []; - if ($locale && ('de' === $locale || 0 === strpos($locale, 'de_'))) { - // Use the shortcut for German in UnicodeString::ascii() if possible (faster and no requirement on intl) - $transliterator = ['de-ASCII']; - } elseif (\function_exists('transliterator_transliterate') && $locale) { - $transliterator = (array) $this->createTransliterator($locale); - } - - if ($this->symbolsMap instanceof \Closure) { - // If the symbols map is passed as a closure, there is no need to fallback to the parent locale - // as the closure can just provide substitutions for all locales of interest. - $symbolsMap = $this->symbolsMap; - array_unshift($transliterator, static function ($s) use ($symbolsMap, $locale) { - return $symbolsMap($s, $locale); - }); - } - - $unicodeString = (new UnicodeString($string))->ascii($transliterator); - - if (\is_array($this->symbolsMap)) { - $map = null; - if (isset($this->symbolsMap[$locale])) { - $map = $this->symbolsMap[$locale]; - } else { - $parent = self::getParentLocale($locale); - if ($parent && isset($this->symbolsMap[$parent])) { - $map = $this->symbolsMap[$parent]; - } - } - if ($map) { - foreach ($map as $char => $replace) { - $unicodeString = $unicodeString->replace($char, ' '.$replace.' '); - } - } - } - - return $unicodeString - ->replaceMatches('/[^A-Za-z0-9]++/', $separator) - ->trim($separator) - ; - } - - private function createTransliterator(string $locale): ?\Transliterator - { - if (\array_key_exists($locale, $this->transliterators)) { - return $this->transliterators[$locale]; - } - - // Exact locale supported, cache and return - if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$locale] ?? null) { - return $this->transliterators[$locale] = \Transliterator::create($id.'/BGN') ?? \Transliterator::create($id); - } - - // Locale not supported and no parent, fallback to any-latin - if (!$parent = self::getParentLocale($locale)) { - return $this->transliterators[$locale] = null; - } - - // Try to use the parent locale (ie. try "de" for "de_AT") and cache both locales - if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$parent] ?? null) { - $transliterator = \Transliterator::create($id.'/BGN') ?? \Transliterator::create($id); - } - - return $this->transliterators[$locale] = $this->transliterators[$parent] = $transliterator ?? null; - } - - private static function getParentLocale(?string $locale): ?string - { - if (!$locale) { - return null; - } - if (false === $str = strrchr($locale, '_')) { - // no parent locale - return null; - } - - return substr($locale, 0, -\strlen($str)); - } -} diff --git a/lib/symfony/string/Slugger/SluggerInterface.php b/lib/symfony/string/Slugger/SluggerInterface.php deleted file mode 100644 index c679ed933..000000000 --- a/lib/symfony/string/Slugger/SluggerInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\String\Slugger; - -use Symfony\Component\String\AbstractUnicodeString; - -/** - * Creates a URL-friendly slug from a given string. - * - * @author Titouan Galopin <galopintitouan@gmail.com> - */ -interface SluggerInterface -{ - /** - * Creates a slug for the given string and locale, using appropriate transliteration when needed. - */ - public function slug(string $string, string $separator = '-', string $locale = null): AbstractUnicodeString; -} diff --git a/lib/symfony/string/UnicodeString.php b/lib/symfony/string/UnicodeString.php deleted file mode 100644 index 9b906c6fc..000000000 --- a/lib/symfony/string/UnicodeString.php +++ /dev/null @@ -1,377 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\String; - -use Symfony\Component\String\Exception\ExceptionInterface; -use Symfony\Component\String\Exception\InvalidArgumentException; - -/** - * Represents a string of Unicode grapheme clusters encoded as UTF-8. - * - * A letter followed by combining characters (accents typically) form what Unicode defines - * as a grapheme cluster: a character as humans mean it in written texts. This class knows - * about the concept and won't split a letter apart from its combining accents. It also - * ensures all string comparisons happen on their canonically-composed representation, - * ignoring e.g. the order in which accents are listed when a letter has many of them. - * - * @see https://unicode.org/reports/tr15/ - * - * @author Nicolas Grekas <p@tchwork.com> - * @author Hugo Hamon <hugohamon@neuf.fr> - * - * @throws ExceptionInterface - */ -class UnicodeString extends AbstractUnicodeString -{ - public function __construct(string $string = '') - { - $this->string = normalizer_is_normalized($string) ? $string : normalizer_normalize($string); - - if (false === $this->string) { - throw new InvalidArgumentException('Invalid UTF-8 string.'); - } - } - - public function append(string ...$suffix): AbstractString - { - $str = clone $this; - $str->string = $this->string.(1 >= \count($suffix) ? ($suffix[0] ?? '') : implode('', $suffix)); - normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); - - if (false === $str->string) { - throw new InvalidArgumentException('Invalid UTF-8 string.'); - } - - return $str; - } - - public function chunk(int $length = 1): array - { - if (1 > $length) { - throw new InvalidArgumentException('The chunk length must be greater than zero.'); - } - - if ('' === $this->string) { - return []; - } - - $rx = '/('; - while (65535 < $length) { - $rx .= '\X{65535}'; - $length -= 65535; - } - $rx .= '\X{'.$length.'})/u'; - - $str = clone $this; - $chunks = []; - - foreach (preg_split($rx, $this->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY) as $chunk) { - $str->string = $chunk; - $chunks[] = clone $str; - } - - return $chunks; - } - - public function endsWith($suffix): bool - { - if ($suffix instanceof AbstractString) { - $suffix = $suffix->string; - } elseif (\is_array($suffix) || $suffix instanceof \Traversable) { - return parent::endsWith($suffix); - } else { - $suffix = (string) $suffix; - } - - $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; - normalizer_is_normalized($suffix, $form) ?: $suffix = normalizer_normalize($suffix, $form); - - if ('' === $suffix || false === $suffix) { - return false; - } - - if ($this->ignoreCase) { - return 0 === mb_stripos(grapheme_extract($this->string, \strlen($suffix), \GRAPHEME_EXTR_MAXBYTES, \strlen($this->string) - \strlen($suffix)), $suffix, 0, 'UTF-8'); - } - - return $suffix === grapheme_extract($this->string, \strlen($suffix), \GRAPHEME_EXTR_MAXBYTES, \strlen($this->string) - \strlen($suffix)); - } - - public function equalsTo($string): bool - { - if ($string instanceof AbstractString) { - $string = $string->string; - } elseif (\is_array($string) || $string instanceof \Traversable) { - return parent::equalsTo($string); - } else { - $string = (string) $string; - } - - $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; - normalizer_is_normalized($string, $form) ?: $string = normalizer_normalize($string, $form); - - if ('' !== $string && false !== $string && $this->ignoreCase) { - return \strlen($string) === \strlen($this->string) && 0 === mb_stripos($this->string, $string, 0, 'UTF-8'); - } - - return $string === $this->string; - } - - public function indexOf($needle, int $offset = 0): ?int - { - if ($needle instanceof AbstractString) { - $needle = $needle->string; - } elseif (\is_array($needle) || $needle instanceof \Traversable) { - return parent::indexOf($needle, $offset); - } else { - $needle = (string) $needle; - } - - $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; - normalizer_is_normalized($needle, $form) ?: $needle = normalizer_normalize($needle, $form); - - if ('' === $needle || false === $needle) { - return null; - } - - try { - $i = $this->ignoreCase ? grapheme_stripos($this->string, $needle, $offset) : grapheme_strpos($this->string, $needle, $offset); - } catch (\ValueError $e) { - return null; - } - - return false === $i ? null : $i; - } - - public function indexOfLast($needle, int $offset = 0): ?int - { - if ($needle instanceof AbstractString) { - $needle = $needle->string; - } elseif (\is_array($needle) || $needle instanceof \Traversable) { - return parent::indexOfLast($needle, $offset); - } else { - $needle = (string) $needle; - } - - $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; - normalizer_is_normalized($needle, $form) ?: $needle = normalizer_normalize($needle, $form); - - if ('' === $needle || false === $needle) { - return null; - } - - $string = $this->string; - - if (0 > $offset) { - // workaround https://bugs.php.net/74264 - if (0 > $offset += grapheme_strlen($needle)) { - $string = grapheme_substr($string, 0, $offset); - } - $offset = 0; - } - - $i = $this->ignoreCase ? grapheme_strripos($string, $needle, $offset) : grapheme_strrpos($string, $needle, $offset); - - return false === $i ? null : $i; - } - - public function join(array $strings, string $lastGlue = null): AbstractString - { - $str = parent::join($strings, $lastGlue); - normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); - - return $str; - } - - public function length(): int - { - return grapheme_strlen($this->string); - } - - /** - * @return static - */ - public function normalize(int $form = self::NFC): parent - { - $str = clone $this; - - if (\in_array($form, [self::NFC, self::NFKC], true)) { - normalizer_is_normalized($str->string, $form) ?: $str->string = normalizer_normalize($str->string, $form); - } elseif (!\in_array($form, [self::NFD, self::NFKD], true)) { - throw new InvalidArgumentException('Unsupported normalization form.'); - } elseif (!normalizer_is_normalized($str->string, $form)) { - $str->string = normalizer_normalize($str->string, $form); - $str->ignoreCase = null; - } - - return $str; - } - - public function prepend(string ...$prefix): AbstractString - { - $str = clone $this; - $str->string = (1 >= \count($prefix) ? ($prefix[0] ?? '') : implode('', $prefix)).$this->string; - normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); - - if (false === $str->string) { - throw new InvalidArgumentException('Invalid UTF-8 string.'); - } - - return $str; - } - - public function replace(string $from, string $to): AbstractString - { - $str = clone $this; - normalizer_is_normalized($from) ?: $from = normalizer_normalize($from); - - if ('' !== $from && false !== $from) { - $tail = $str->string; - $result = ''; - $indexOf = $this->ignoreCase ? 'grapheme_stripos' : 'grapheme_strpos'; - - while ('' !== $tail && false !== $i = $indexOf($tail, $from)) { - $slice = grapheme_substr($tail, 0, $i); - $result .= $slice.$to; - $tail = substr($tail, \strlen($slice) + \strlen($from)); - } - - $str->string = $result.$tail; - normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); - - if (false === $str->string) { - throw new InvalidArgumentException('Invalid UTF-8 string.'); - } - } - - return $str; - } - - public function replaceMatches(string $fromRegexp, $to): AbstractString - { - $str = parent::replaceMatches($fromRegexp, $to); - normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); - - return $str; - } - - public function slice(int $start = 0, int $length = null): AbstractString - { - $str = clone $this; - - if (\PHP_VERSION_ID < 80000 && 0 > $start && grapheme_strlen($this->string) < -$start) { - $start = 0; - } - $str->string = (string) grapheme_substr($this->string, $start, $length ?? 2147483647); - - return $str; - } - - public function splice(string $replacement, int $start = 0, int $length = null): AbstractString - { - $str = clone $this; - - if (\PHP_VERSION_ID < 80000 && 0 > $start && grapheme_strlen($this->string) < -$start) { - $start = 0; - } - $start = $start ? \strlen(grapheme_substr($this->string, 0, $start)) : 0; - $length = $length ? \strlen(grapheme_substr($this->string, $start, $length ?? 2147483647)) : $length; - $str->string = substr_replace($this->string, $replacement, $start, $length ?? 2147483647); - normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); - - if (false === $str->string) { - throw new InvalidArgumentException('Invalid UTF-8 string.'); - } - - return $str; - } - - public function split(string $delimiter, int $limit = null, int $flags = null): array - { - if (1 > $limit = $limit ?? 2147483647) { - throw new InvalidArgumentException('Split limit must be a positive integer.'); - } - - if ('' === $delimiter) { - throw new InvalidArgumentException('Split delimiter is empty.'); - } - - if (null !== $flags) { - return parent::split($delimiter.'u', $limit, $flags); - } - - normalizer_is_normalized($delimiter) ?: $delimiter = normalizer_normalize($delimiter); - - if (false === $delimiter) { - throw new InvalidArgumentException('Split delimiter is not a valid UTF-8 string.'); - } - - $str = clone $this; - $tail = $this->string; - $chunks = []; - $indexOf = $this->ignoreCase ? 'grapheme_stripos' : 'grapheme_strpos'; - - while (1 < $limit && false !== $i = $indexOf($tail, $delimiter)) { - $str->string = grapheme_substr($tail, 0, $i); - $chunks[] = clone $str; - $tail = substr($tail, \strlen($str->string) + \strlen($delimiter)); - --$limit; - } - - $str->string = $tail; - $chunks[] = clone $str; - - return $chunks; - } - - public function startsWith($prefix): bool - { - if ($prefix instanceof AbstractString) { - $prefix = $prefix->string; - } elseif (\is_array($prefix) || $prefix instanceof \Traversable) { - return parent::startsWith($prefix); - } else { - $prefix = (string) $prefix; - } - - $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; - normalizer_is_normalized($prefix, $form) ?: $prefix = normalizer_normalize($prefix, $form); - - if ('' === $prefix || false === $prefix) { - return false; - } - - if ($this->ignoreCase) { - return 0 === mb_stripos(grapheme_extract($this->string, \strlen($prefix), \GRAPHEME_EXTR_MAXBYTES), $prefix, 0, 'UTF-8'); - } - - return $prefix === grapheme_extract($this->string, \strlen($prefix), \GRAPHEME_EXTR_MAXBYTES); - } - - public function __wakeup() - { - if (!\is_string($this->string)) { - throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); - } - - normalizer_is_normalized($this->string) ?: $this->string = normalizer_normalize($this->string); - } - - public function __clone() - { - if (null === $this->ignoreCase) { - normalizer_is_normalized($this->string) ?: $this->string = normalizer_normalize($this->string); - } - - $this->ignoreCase = false; - } -} diff --git a/lib/symfony/string/composer.json b/lib/symfony/string/composer.json deleted file mode 100644 index 2b88fd529..000000000 --- a/lib/symfony/string/composer.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "name": "symfony/string", - "type": "library", - "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", - "keywords": ["string", "utf8", "utf-8", "grapheme", "i18n", "unicode"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "~1.15" - }, - "require-dev": { - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/translation-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0|^6.0" - }, - "conflict": { - "symfony/translation-contracts": ">=3.0" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\String\\": "" }, - "files": [ "Resources/functions.php" ], - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/lib/symfony/translation-contracts/.gitignore b/lib/symfony/translation-contracts/.gitignore deleted file mode 100644 index c49a5d8df..000000000 --- a/lib/symfony/translation-contracts/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -vendor/ -composer.lock -phpunit.xml diff --git a/lib/symfony/translation-contracts/CHANGELOG.md b/lib/symfony/translation-contracts/CHANGELOG.md deleted file mode 100644 index 7932e2613..000000000 --- a/lib/symfony/translation-contracts/CHANGELOG.md +++ /dev/null @@ -1,5 +0,0 @@ -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/lib/symfony/translation-contracts/LICENSE b/lib/symfony/translation-contracts/LICENSE deleted file mode 100644 index 74cdc2dbf..000000000 --- a/lib/symfony/translation-contracts/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -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/lib/symfony/translation-contracts/LocaleAwareInterface.php b/lib/symfony/translation-contracts/LocaleAwareInterface.php deleted file mode 100644 index 693f92ba9..000000000 --- a/lib/symfony/translation-contracts/LocaleAwareInterface.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Translation; - -interface LocaleAwareInterface -{ - /** - * Sets the current locale. - * - * @param string $locale The locale - * - * @throws \InvalidArgumentException If the locale contains invalid characters - */ - public function setLocale(string $locale); - - /** - * Returns the current locale. - * - * @return string - */ - public function getLocale(); -} diff --git a/lib/symfony/translation-contracts/README.md b/lib/symfony/translation-contracts/README.md deleted file mode 100644 index 42e5c5175..000000000 --- a/lib/symfony/translation-contracts/README.md +++ /dev/null @@ -1,9 +0,0 @@ -Symfony Translation 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/lib/symfony/translation-contracts/TranslatableInterface.php b/lib/symfony/translation-contracts/TranslatableInterface.php deleted file mode 100644 index 47fd6fa02..000000000 --- a/lib/symfony/translation-contracts/TranslatableInterface.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Translation; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -interface TranslatableInterface -{ - public function trans(TranslatorInterface $translator, string $locale = null): string; -} diff --git a/lib/symfony/translation-contracts/TranslatorInterface.php b/lib/symfony/translation-contracts/TranslatorInterface.php deleted file mode 100644 index 77b7a9c58..000000000 --- a/lib/symfony/translation-contracts/TranslatorInterface.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Translation; - -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @method string getLocale() Returns the default locale - */ -interface TranslatorInterface -{ - /** - * Translates the given message. - * - * When a number is provided as a parameter named "%count%", the message is parsed for plural - * forms and a translation is chosen according to this number using the following rules: - * - * Given a message with different plural translations separated by a - * pipe (|), this method returns the correct portion of the message based - * on the given number, locale and the pluralization rules in the message - * itself. - * - * The message supports two different types of pluralization rules: - * - * interval: {0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples - * indexed: There is one apple|There are %count% apples - * - * The indexed solution can also contain labels (e.g. one: There is one apple). - * This is purely for making the translations more clear - it does not - * affect the functionality. - * - * The two methods can also be mixed: - * {0} There are no apples|one: There is one apple|more: There are %count% apples - * - * An interval can represent a finite set of numbers: - * {1,2,3,4} - * - * An interval can represent numbers between two numbers: - * [1, +Inf] - * ]-1,2[ - * - * The left delimiter can be [ (inclusive) or ] (exclusive). - * The right delimiter can be [ (exclusive) or ] (inclusive). - * Beside numbers, you can use -Inf and +Inf for the infinite. - * - * @see https://en.wikipedia.org/wiki/ISO_31-11 - * - * @param string $id The message id (may also be an object that can be cast to string) - * @param array $parameters An array of parameters for the message - * @param string|null $domain The domain for the message or null to use the default - * @param string|null $locale The locale or null to use the default - * - * @return string - * - * @throws \InvalidArgumentException If the locale contains invalid characters - */ - public function trans(string $id, array $parameters = [], string $domain = null, string $locale = null); -} diff --git a/lib/symfony/translation-contracts/TranslatorTrait.php b/lib/symfony/translation-contracts/TranslatorTrait.php deleted file mode 100644 index 405ce8d70..000000000 --- a/lib/symfony/translation-contracts/TranslatorTrait.php +++ /dev/null @@ -1,262 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Translation; - -use Symfony\Component\Translation\Exception\InvalidArgumentException; - -/** - * A trait to help implement TranslatorInterface and LocaleAwareInterface. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -trait TranslatorTrait -{ - private $locale; - - /** - * {@inheritdoc} - */ - public function setLocale(string $locale) - { - $this->locale = $locale; - } - - /** - * {@inheritdoc} - * - * @return string - */ - public function getLocale() - { - return $this->locale ?: (class_exists(\Locale::class) ? \Locale::getDefault() : 'en'); - } - - /** - * {@inheritdoc} - */ - public function trans(?string $id, array $parameters = [], string $domain = null, string $locale = null): string - { - if (null === $id || '' === $id) { - return ''; - } - - if (!isset($parameters['%count%']) || !is_numeric($parameters['%count%'])) { - return strtr($id, $parameters); - } - - $number = (float) $parameters['%count%']; - $locale = $locale ?: $this->getLocale(); - - $parts = []; - if (preg_match('/^\|++$/', $id)) { - $parts = explode('|', $id); - } elseif (preg_match_all('/(?:\|\||[^\|])++/', $id, $matches)) { - $parts = $matches[0]; - } - - $intervalRegexp = <<<'EOF' -/^(?P<interval> - ({\s* - (\-?\d+(\.\d+)?[\s*,\s*\-?\d+(\.\d+)?]*) - \s*}) - - | - - (?P<left_delimiter>[\[\]]) - \s* - (?P<left>-Inf|\-?\d+(\.\d+)?) - \s*,\s* - (?P<right>\+?Inf|\-?\d+(\.\d+)?) - \s* - (?P<right_delimiter>[\[\]]) -)\s*(?P<message>.*?)$/xs -EOF; - - $standardRules = []; - foreach ($parts as $part) { - $part = trim(str_replace('||', '|', $part)); - - // try to match an explicit rule, then fallback to the standard ones - if (preg_match($intervalRegexp, $part, $matches)) { - if ($matches[2]) { - foreach (explode(',', $matches[3]) as $n) { - if ($number == $n) { - return strtr($matches['message'], $parameters); - } - } - } else { - $leftNumber = '-Inf' === $matches['left'] ? -\INF : (float) $matches['left']; - $rightNumber = is_numeric($matches['right']) ? (float) $matches['right'] : \INF; - - if (('[' === $matches['left_delimiter'] ? $number >= $leftNumber : $number > $leftNumber) - && (']' === $matches['right_delimiter'] ? $number <= $rightNumber : $number < $rightNumber) - ) { - return strtr($matches['message'], $parameters); - } - } - } elseif (preg_match('/^\w+\:\s*(.*?)$/', $part, $matches)) { - $standardRules[] = $matches[1]; - } else { - $standardRules[] = $part; - } - } - - $position = $this->getPluralizationRule($number, $locale); - - if (!isset($standardRules[$position])) { - // when there's exactly one rule given, and that rule is a standard - // rule, use this rule - if (1 === \count($parts) && isset($standardRules[0])) { - return strtr($standardRules[0], $parameters); - } - - $message = sprintf('Unable to choose a translation for "%s" with locale "%s" for value "%d". Double check that this translation has the correct plural options (e.g. "There is one apple|There are %%count%% apples").', $id, $locale, $number); - - if (class_exists(InvalidArgumentException::class)) { - throw new InvalidArgumentException($message); - } - - throw new \InvalidArgumentException($message); - } - - return strtr($standardRules[$position], $parameters); - } - - /** - * Returns the plural position to use for the given locale and number. - * - * The plural rules are derived from code of the Zend Framework (2010-09-25), - * which is subject to the new BSD license (http://framework.zend.com/license/new-bsd). - * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - */ - private function getPluralizationRule(float $number, string $locale): int - { - $number = abs($number); - - switch ('pt_BR' !== $locale && 'en_US_POSIX' !== $locale && \strlen($locale) > 3 ? substr($locale, 0, strrpos($locale, '_')) : $locale) { - case 'af': - case 'bn': - case 'bg': - case 'ca': - case 'da': - case 'de': - case 'el': - case 'en': - case 'en_US_POSIX': - case 'eo': - case 'es': - case 'et': - case 'eu': - case 'fa': - case 'fi': - case 'fo': - case 'fur': - case 'fy': - case 'gl': - case 'gu': - case 'ha': - case 'he': - case 'hu': - case 'is': - case 'it': - case 'ku': - case 'lb': - case 'ml': - case 'mn': - case 'mr': - case 'nah': - case 'nb': - case 'ne': - case 'nl': - case 'nn': - case 'no': - case 'oc': - case 'om': - case 'or': - case 'pa': - case 'pap': - case 'ps': - case 'pt': - case 'so': - case 'sq': - case 'sv': - case 'sw': - case 'ta': - case 'te': - case 'tk': - case 'ur': - case 'zu': - return (1 == $number) ? 0 : 1; - - case 'am': - case 'bh': - case 'fil': - case 'fr': - case 'gun': - case 'hi': - case 'hy': - case 'ln': - case 'mg': - case 'nso': - case 'pt_BR': - case 'ti': - case 'wa': - return ($number < 2) ? 0 : 1; - - case 'be': - case 'bs': - case 'hr': - case 'ru': - case 'sh': - case 'sr': - case 'uk': - return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); - - case 'cs': - case 'sk': - return (1 == $number) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2); - - case 'ga': - return (1 == $number) ? 0 : ((2 == $number) ? 1 : 2); - - case 'lt': - return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); - - case 'sl': - return (1 == $number % 100) ? 0 : ((2 == $number % 100) ? 1 : (((3 == $number % 100) || (4 == $number % 100)) ? 2 : 3)); - - case 'mk': - return (1 == $number % 10) ? 0 : 1; - - case 'mt': - return (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3)); - - case 'lv': - return (0 == $number) ? 0 : (((1 == $number % 10) && (11 != $number % 100)) ? 1 : 2); - - case 'pl': - return (1 == $number) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2); - - case 'cy': - return (1 == $number) ? 0 : ((2 == $number) ? 1 : (((8 == $number) || (11 == $number)) ? 2 : 3)); - - case 'ro': - return (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2); - - case 'ar': - return (0 == $number) ? 0 : ((1 == $number) ? 1 : ((2 == $number) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : 5)))); - - default: - return 0; - } - } -} diff --git a/lib/symfony/translation-contracts/composer.json b/lib/symfony/translation-contracts/composer.json deleted file mode 100644 index 65fe243a4..000000000 --- a/lib/symfony/translation-contracts/composer.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "symfony/translation-contracts", - "type": "library", - "description": "Generic abstractions related to translation", - "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5" - }, - "suggest": { - "symfony/translation-implementation": "" - }, - "autoload": { - "psr-4": { "Symfony\\Contracts\\Translation\\": "" } - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - } -} diff --git a/lib/symfony/twig-bridge/AppVariable.php b/lib/symfony/twig-bridge/AppVariable.php deleted file mode 100644 index 23683eb35..000000000 --- a/lib/symfony/twig-bridge/AppVariable.php +++ /dev/null @@ -1,182 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Session\Session; -use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; -use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; -use Symfony\Component\Security\Core\User\UserInterface; - -/** - * Exposes some Symfony parameters and services as an "app" global variable. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class AppVariable -{ - private $tokenStorage; - private $requestStack; - private $environment; - private $debug; - - public function setTokenStorage(TokenStorageInterface $tokenStorage) - { - $this->tokenStorage = $tokenStorage; - } - - public function setRequestStack(RequestStack $requestStack) - { - $this->requestStack = $requestStack; - } - - public function setEnvironment(string $environment) - { - $this->environment = $environment; - } - - public function setDebug(bool $debug) - { - $this->debug = $debug; - } - - /** - * Returns the current token. - * - * @return TokenInterface|null - * - * @throws \RuntimeException When the TokenStorage is not available - */ - public function getToken() - { - if (null === $tokenStorage = $this->tokenStorage) { - throw new \RuntimeException('The "app.token" variable is not available.'); - } - - return $tokenStorage->getToken(); - } - - /** - * Returns the current user. - * - * @return UserInterface|null - * - * @see TokenInterface::getUser() - */ - public function getUser() - { - if (null === $tokenStorage = $this->tokenStorage) { - throw new \RuntimeException('The "app.user" variable is not available.'); - } - - if (!$token = $tokenStorage->getToken()) { - return null; - } - - $user = $token->getUser(); - - // @deprecated since Symfony 5.4, $user will always be a UserInterface instance - return \is_object($user) ? $user : null; - } - - /** - * Returns the current request. - * - * @return Request|null - */ - public function getRequest() - { - if (null === $this->requestStack) { - throw new \RuntimeException('The "app.request" variable is not available.'); - } - - return $this->requestStack->getCurrentRequest(); - } - - /** - * Returns the current session. - * - * @return Session|null - */ - public function getSession() - { - if (null === $this->requestStack) { - throw new \RuntimeException('The "app.session" variable is not available.'); - } - $request = $this->getRequest(); - - return $request && $request->hasSession() ? $request->getSession() : null; - } - - /** - * Returns the current app environment. - * - * @return string - */ - public function getEnvironment() - { - if (null === $this->environment) { - throw new \RuntimeException('The "app.environment" variable is not available.'); - } - - return $this->environment; - } - - /** - * Returns the current app debug mode. - * - * @return bool - */ - public function getDebug() - { - if (null === $this->debug) { - throw new \RuntimeException('The "app.debug" variable is not available.'); - } - - return $this->debug; - } - - /** - * Returns some or all the existing flash messages: - * * getFlashes() returns all the flash messages - * * getFlashes('notice') returns a simple array with flash messages of that type - * * getFlashes(['notice', 'error']) returns a nested array of type => messages. - * - * @return array - */ - public function getFlashes($types = null) - { - try { - if (null === $session = $this->getSession()) { - return []; - } - } catch (\RuntimeException $e) { - return []; - } - - if (null === $types || '' === $types || [] === $types) { - return $session->getFlashBag()->all(); - } - - if (\is_string($types)) { - return $session->getFlashBag()->get($types); - } - - $result = []; - foreach ($types as $type) { - $result[$type] = $session->getFlashBag()->get($type); - } - - return $result; - } -} diff --git a/lib/symfony/twig-bridge/CHANGELOG.md b/lib/symfony/twig-bridge/CHANGELOG.md deleted file mode 100644 index 535df0c08..000000000 --- a/lib/symfony/twig-bridge/CHANGELOG.md +++ /dev/null @@ -1,169 +0,0 @@ -CHANGELOG -========= - -5.4 ---- - -* Add `github` format & autodetection to render errors as annotations when - running the Twig linter command in a Github Actions environment. - -5.3 ---- - - * Add a new `markAsPublic` method on `NotificationEmail` to change the `importance` context option to null after creation - * Add a new `fragment_uri()` helper to generate the URI of a fragment - * Add support of Bootstrap 5 for form theming - * Add a new `serialize` filter to serialize objects using the Serializer component - -5.2.0 ------ - - * added the `impersonation_exit_url()` and `impersonation_exit_path()` functions. They return a URL that allows to switch back to the original user. - * added the `workflow_transition()` function to easily retrieve a specific transition object - * added support for translating `TranslatableInterface` objects - * added the `t()` function to easily create `TranslatableMessage` objects - * Added support for extracting messages from the `t()` function - * Added `field_*` Twig functions to access string values from Form fields - * changed the `importance` context option of `NotificationEmail` to allow `null` - -5.0.0 ------ - - * removed `TwigEngine` class, use `\Twig\Environment` instead. - * removed `transChoice` filter and token - * `HttpFoundationExtension` requires a `UrlHelper` on instantiation - * removed support for implicit STDIN usage in the `lint:twig` command, use `lint:twig -` (append a dash) instead to make it explicit. - * added form theme for Foundation 6 - * added support for Foundation 6 switches: add the `switch-input` class to the attributes of a `CheckboxType` - -4.4.0 ------ - - * added a new `TwigErrorRenderer` for `html` format, integrated with the `ErrorHandler` component - * marked all classes extending twig as `@final` - * deprecated to pass `$rootDir` and `$fileLinkFormatter` as 5th and 6th argument respectively to the - `DebugCommand::__construct()` method, swap the variables position. - * the `LintCommand` lints all the templates stored in all configured Twig paths if none argument is provided - * deprecated accepting STDIN implicitly when using the `lint:twig` command, use `lint:twig -` (append a dash) instead to make it explicit. - * added `--show-deprecations` option to the `lint:twig` command - * added support for Bootstrap4 switches: add the `switch-custom` class to the label attributes of a `CheckboxType` - * Marked the `TwigDataCollector` class as `@final`. - -4.3.0 ------ - - * added the `form_parent()` function that allows to reliably retrieve the parent form in Twig templates - * added the `workflow_transition_blockers()` function - * deprecated the `$requestStack` and `$requestContext` arguments of the - `HttpFoundationExtension`, pass a `Symfony\Component\HttpFoundation\UrlHelper` - instance as the only argument instead - -4.2.0 ------ - - * add bundle name suggestion on wrongly overridden templates paths - * added `name` argument in `debug:twig` command and changed `filter` argument as `--filter` option - * deprecated the `transchoice` tag and filter, use the `trans` ones instead with a `%count%` parameter - -4.1.0 ------ - - * add a `workflow_metadata` function - -3.4.0 ------ - - * added an `only` keyword to `form_theme` tag to disable usage of default themes when rendering a form - * deprecated `Symfony\Bridge\Twig\Form\TwigRenderer` - * deprecated `DebugCommand::set/getTwigEnvironment`. Pass an instance of - `Twig\Environment` as first argument of the constructor instead - * deprecated `LintCommand::set/getTwigEnvironment`. Pass an instance of - `Twig\Environment` as first argument of the constructor instead - -3.3.0 ------ - - * added a `workflow_has_marked_place` function - * added a `workflow_marked_places` function - -3.2.0 ------ - - * added `AppVariable::getToken()` - * Deprecated the possibility to inject the Form `TwigRenderer` into the `FormExtension`. - * [BC BREAK] Registering the `FormExtension` without configuring a runtime loader for the `TwigRenderer` - doesn't work anymore. - - Before: - - ```php - use Symfony\Bridge\Twig\Extension\FormExtension; - use Symfony\Bridge\Twig\Form\TwigRenderer; - use Symfony\Bridge\Twig\Form\TwigRendererEngine; - - // ... - $rendererEngine = new TwigRendererEngine(['form_div_layout.html.twig']); - $rendererEngine->setEnvironment($twig); - $twig->addExtension(new FormExtension(new TwigRenderer($rendererEngine, $csrfTokenManager))); - ``` - - After: - - ```php - // ... - $rendererEngine = new TwigRendererEngine(['form_div_layout.html.twig'], $twig); - // require Twig 1.30+ - $twig->addRuntimeLoader(new \Twig\RuntimeLoader\FactoryRuntimeLoader([ - TwigRenderer::class => function () use ($rendererEngine, $csrfTokenManager) { - return new TwigRenderer($rendererEngine, $csrfTokenManager); - }, - ])); - $twig->addExtension(new FormExtension()); - ``` - * Deprecated the `TwigRendererEngineInterface` interface. - * added WorkflowExtension (provides `workflow_can` and `workflow_transitions`) - -2.7.0 ------ - - * added LogoutUrlExtension (provides `logout_url` and `logout_path`) - * added an HttpFoundation extension (provides the `absolute_url` and the `relative_path` functions) - * added AssetExtension (provides the `asset` and `asset_version` functions) - * Added possibility to extract translation messages from a file or files besides extracting from a directory - -2.5.0 ------ - - * moved command `twig:lint` from `TwigBundle` - -2.4.0 ------ - - * added stopwatch tag to time templates with the WebProfilerBundle - -2.3.0 ------ - - * added helpers form(), form_start() and form_end() - * deprecated form_enctype() in favor of form_start() - -2.2.0 ------ - - * added a `controller` function to help generating controller references - * added a `render_esi` and a `render_hinclude` function - * [BC BREAK] restricted the `render` tag to only accept URIs or ControllerReference instances (the signature changed) - * added a `render` function to render a request - * The `app` global variable is now injected even when using the twig service directly. - * Added an optional parameter to the `path` and `url` function which allows to generate - relative paths (e.g. "../parent-file") and scheme-relative URLs (e.g. "//example.com/dir/file"). - -2.1.0 ------ - - * added global variables access in a form theme - * added TwigEngine - * added TwigExtractor - * added a csrf_token function - * added a way to specify a default domain for a Twig template (via the - 'trans_default_domain' tag) diff --git a/lib/symfony/twig-bridge/Command/DebugCommand.php b/lib/symfony/twig-bridge/Command/DebugCommand.php deleted file mode 100644 index d4c782101..000000000 --- a/lib/symfony/twig-bridge/Command/DebugCommand.php +++ /dev/null @@ -1,600 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Completion\CompletionInput; -use Symfony\Component\Console\Completion\CompletionSuggestions; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Formatter\OutputFormatter; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\Finder\Finder; -use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; -use Twig\Environment; -use Twig\Loader\ChainLoader; -use Twig\Loader\FilesystemLoader; - -/** - * Lists twig functions, filters, globals and tests present in the current project. - * - * @author Jordi Boggiano <j.boggiano@seld.be> - */ -class DebugCommand extends Command -{ - protected static $defaultName = 'debug:twig'; - protected static $defaultDescription = 'Show a list of twig functions, filters, globals and tests'; - - private $twig; - private $projectDir; - private $bundlesMetadata; - private $twigDefaultPath; - private $filesystemLoaders; - private $fileLinkFormatter; - - public function __construct(Environment $twig, string $projectDir = null, array $bundlesMetadata = [], string $twigDefaultPath = null, FileLinkFormatter $fileLinkFormatter = null) - { - parent::__construct(); - - $this->twig = $twig; - $this->projectDir = $projectDir; - $this->bundlesMetadata = $bundlesMetadata; - $this->twigDefaultPath = $twigDefaultPath; - $this->fileLinkFormatter = $fileLinkFormatter; - } - - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('name', InputArgument::OPTIONAL, 'The template name'), - new InputOption('filter', null, InputOption::VALUE_REQUIRED, 'Show details for all entries matching this filter'), - new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (text or json)', 'text'), - ]) - ->setDescription(self::$defaultDescription) - ->setHelp(<<<'EOF' -The <info>%command.name%</info> command outputs a list of twig functions, -filters, globals and tests. - - <info>php %command.full_name%</info> - -The command lists all functions, filters, etc. - - <info>php %command.full_name% @Twig/Exception/error.html.twig</info> - -The command lists all paths that match the given template name. - - <info>php %command.full_name% --filter=date</info> - -The command lists everything that contains the word date. - - <info>php %command.full_name% --format=json</info> - -The command lists everything in a machine readable json format. -EOF - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - $io = new SymfonyStyle($input, $output); - $name = $input->getArgument('name'); - $filter = $input->getOption('filter'); - - if (null !== $name && [] === $this->getFilesystemLoaders()) { - throw new InvalidArgumentException(sprintf('Argument "name" not supported, it requires the Twig loader "%s".', FilesystemLoader::class)); - } - - switch ($input->getOption('format')) { - case 'text': - $name ? $this->displayPathsText($io, $name) : $this->displayGeneralText($io, $filter); - break; - case 'json': - $name ? $this->displayPathsJson($io, $name) : $this->displayGeneralJson($io, $filter); - break; - default: - throw new InvalidArgumentException(sprintf('The format "%s" is not supported.', $input->getOption('format'))); - } - - return 0; - } - - public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void - { - if ($input->mustSuggestArgumentValuesFor('name')) { - $suggestions->suggestValues(array_keys($this->getLoaderPaths())); - } - - if ($input->mustSuggestOptionValuesFor('format')) { - $suggestions->suggestValues(['text', 'json']); - } - } - - private function displayPathsText(SymfonyStyle $io, string $name) - { - $file = new \ArrayIterator($this->findTemplateFiles($name)); - $paths = $this->getLoaderPaths($name); - - $io->section('Matched File'); - if ($file->valid()) { - if ($fileLink = $this->getFileLink($file->key())) { - $io->block($file->current(), 'OK', sprintf('fg=black;bg=green;href=%s', $fileLink), ' ', true); - } else { - $io->success($file->current()); - } - $file->next(); - - if ($file->valid()) { - $io->section('Overridden Files'); - do { - if ($fileLink = $this->getFileLink($file->key())) { - $io->text(sprintf('* <href=%s>%s</>', $fileLink, $file->current())); - } else { - $io->text(sprintf('* %s', $file->current())); - } - $file->next(); - } while ($file->valid()); - } - } else { - $alternatives = []; - - if ($paths) { - $shortnames = []; - $dirs = []; - foreach (current($paths) as $path) { - $dirs[] = $this->isAbsolutePath($path) ? $path : $this->projectDir.'/'.$path; - } - foreach (Finder::create()->files()->followLinks()->in($dirs) as $file) { - $shortnames[] = str_replace('\\', '/', $file->getRelativePathname()); - } - - [$namespace, $shortname] = $this->parseTemplateName($name); - $alternatives = $this->findAlternatives($shortname, $shortnames); - if (FilesystemLoader::MAIN_NAMESPACE !== $namespace) { - $alternatives = array_map(function ($shortname) use ($namespace) { - return '@'.$namespace.'/'.$shortname; - }, $alternatives); - } - } - - $this->error($io, sprintf('Template name "%s" not found', $name), $alternatives); - } - - $io->section('Configured Paths'); - if ($paths) { - $io->table(['Namespace', 'Paths'], $this->buildTableRows($paths)); - } else { - $alternatives = []; - $namespace = $this->parseTemplateName($name)[0]; - - if (FilesystemLoader::MAIN_NAMESPACE === $namespace) { - $message = 'No template paths configured for your application'; - } else { - $message = sprintf('No template paths configured for "@%s" namespace', $namespace); - foreach ($this->getFilesystemLoaders() as $loader) { - $namespaces = $loader->getNamespaces(); - foreach ($this->findAlternatives($namespace, $namespaces) as $namespace) { - $alternatives[] = '@'.$namespace; - } - } - } - - $this->error($io, $message, $alternatives); - - if (!$alternatives && $paths = $this->getLoaderPaths()) { - $io->table(['Namespace', 'Paths'], $this->buildTableRows($paths)); - } - } - } - - private function displayPathsJson(SymfonyStyle $io, string $name) - { - $files = $this->findTemplateFiles($name); - $paths = $this->getLoaderPaths($name); - - if ($files) { - $data['matched_file'] = array_shift($files); - if ($files) { - $data['overridden_files'] = $files; - } - } else { - $data['matched_file'] = sprintf('Template name "%s" not found', $name); - } - $data['loader_paths'] = $paths; - - $io->writeln(json_encode($data)); - } - - private function displayGeneralText(SymfonyStyle $io, string $filter = null) - { - $decorated = $io->isDecorated(); - $types = ['functions', 'filters', 'tests', 'globals']; - foreach ($types as $index => $type) { - $items = []; - foreach ($this->twig->{'get'.ucfirst($type)}() as $name => $entity) { - if (!$filter || str_contains($name, $filter)) { - $items[$name] = $name.$this->getPrettyMetadata($type, $entity, $decorated); - } - } - - if (!$items) { - continue; - } - - $io->section(ucfirst($type)); - - ksort($items); - $io->listing($items); - } - - if (!$filter && $paths = $this->getLoaderPaths()) { - $io->section('Loader Paths'); - $io->table(['Namespace', 'Paths'], $this->buildTableRows($paths)); - } - - if ($wrongBundles = $this->findWrongBundleOverrides()) { - foreach ($this->buildWarningMessages($wrongBundles) as $message) { - $io->warning($message); - } - } - } - - private function displayGeneralJson(SymfonyStyle $io, ?string $filter) - { - $decorated = $io->isDecorated(); - $types = ['functions', 'filters', 'tests', 'globals']; - $data = []; - foreach ($types as $type) { - foreach ($this->twig->{'get'.ucfirst($type)}() as $name => $entity) { - if (!$filter || str_contains($name, $filter)) { - $data[$type][$name] = $this->getMetadata($type, $entity); - } - } - } - if (isset($data['tests'])) { - $data['tests'] = array_keys($data['tests']); - } - - if (!$filter && $paths = $this->getLoaderPaths($filter)) { - $data['loader_paths'] = $paths; - } - - if ($wrongBundles = $this->findWrongBundleOverrides()) { - $data['warnings'] = $this->buildWarningMessages($wrongBundles); - } - - $data = json_encode($data, \JSON_PRETTY_PRINT); - $io->writeln($decorated ? OutputFormatter::escape($data) : $data); - } - - private function getLoaderPaths(string $name = null): array - { - $loaderPaths = []; - foreach ($this->getFilesystemLoaders() as $loader) { - $namespaces = $loader->getNamespaces(); - if (null !== $name) { - $namespace = $this->parseTemplateName($name)[0]; - $namespaces = array_intersect([$namespace], $namespaces); - } - - foreach ($namespaces as $namespace) { - $paths = array_map([$this, 'getRelativePath'], $loader->getPaths($namespace)); - - if (FilesystemLoader::MAIN_NAMESPACE === $namespace) { - $namespace = '(None)'; - } else { - $namespace = '@'.$namespace; - } - - $loaderPaths[$namespace] = array_merge($loaderPaths[$namespace] ?? [], $paths); - } - } - - return $loaderPaths; - } - - private function getMetadata(string $type, $entity) - { - if ('globals' === $type) { - return $entity; - } - if ('tests' === $type) { - return null; - } - if ('functions' === $type || 'filters' === $type) { - $cb = $entity->getCallable(); - if (null === $cb) { - return null; - } - if (\is_array($cb)) { - if (!method_exists($cb[0], $cb[1])) { - return null; - } - $refl = new \ReflectionMethod($cb[0], $cb[1]); - } elseif (\is_object($cb) && method_exists($cb, '__invoke')) { - $refl = new \ReflectionMethod($cb, '__invoke'); - } elseif (\function_exists($cb)) { - $refl = new \ReflectionFunction($cb); - } elseif (\is_string($cb) && preg_match('{^(.+)::(.+)$}', $cb, $m) && method_exists($m[1], $m[2])) { - $refl = new \ReflectionMethod($m[1], $m[2]); - } else { - throw new \UnexpectedValueException('Unsupported callback type.'); - } - - $args = $refl->getParameters(); - - // filter out context/environment args - if ($entity->needsEnvironment()) { - array_shift($args); - } - if ($entity->needsContext()) { - array_shift($args); - } - - if ('filters' === $type) { - // remove the value the filter is applied on - array_shift($args); - } - - // format args - $args = array_map(function (\ReflectionParameter $param) { - if ($param->isDefaultValueAvailable()) { - return $param->getName().' = '.json_encode($param->getDefaultValue()); - } - - return $param->getName(); - }, $args); - - return $args; - } - - return null; - } - - private function getPrettyMetadata(string $type, $entity, bool $decorated): ?string - { - if ('tests' === $type) { - return ''; - } - - try { - $meta = $this->getMetadata($type, $entity); - if (null === $meta) { - return '(unknown?)'; - } - } catch (\UnexpectedValueException $e) { - return sprintf(' <error>%s</error>', $decorated ? OutputFormatter::escape($e->getMessage()) : $e->getMessage()); - } - - if ('globals' === $type) { - if (\is_object($meta)) { - return ' = object('.\get_class($meta).')'; - } - - $description = substr(@json_encode($meta), 0, 50); - - return sprintf(' = %s', $decorated ? OutputFormatter::escape($description) : $description); - } - - if ('functions' === $type) { - return '('.implode(', ', $meta).')'; - } - - if ('filters' === $type) { - return $meta ? '('.implode(', ', $meta).')' : ''; - } - - return null; - } - - private function findWrongBundleOverrides(): array - { - $alternatives = []; - $bundleNames = []; - - if ($this->twigDefaultPath && $this->projectDir) { - $folders = glob($this->twigDefaultPath.'/bundles/*', \GLOB_ONLYDIR); - $relativePath = ltrim(substr($this->twigDefaultPath.'/bundles/', \strlen($this->projectDir)), \DIRECTORY_SEPARATOR); - $bundleNames = array_reduce($folders, function ($carry, $absolutePath) use ($relativePath) { - if (str_starts_with($absolutePath, $this->projectDir)) { - $name = basename($absolutePath); - $path = ltrim($relativePath.$name, \DIRECTORY_SEPARATOR); - $carry[$name] = $path; - } - - return $carry; - }, $bundleNames); - } - - if ($notFoundBundles = array_diff_key($bundleNames, $this->bundlesMetadata)) { - $alternatives = []; - foreach ($notFoundBundles as $notFoundBundle => $path) { - $alternatives[$path] = $this->findAlternatives($notFoundBundle, array_keys($this->bundlesMetadata)); - } - } - - return $alternatives; - } - - private function buildWarningMessages(array $wrongBundles): array - { - $messages = []; - foreach ($wrongBundles as $path => $alternatives) { - $message = sprintf('Path "%s" not matching any bundle found', $path); - if ($alternatives) { - if (1 === \count($alternatives)) { - $message .= sprintf(", did you mean \"%s\"?\n", $alternatives[0]); - } else { - $message .= ", did you mean one of these:\n"; - foreach ($alternatives as $bundle) { - $message .= sprintf(" - %s\n", $bundle); - } - } - } - $messages[] = trim($message); - } - - return $messages; - } - - private function error(SymfonyStyle $io, string $message, array $alternatives = []): void - { - if ($alternatives) { - 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); - } - - $io->block($message, null, 'fg=white;bg=red', ' ', true); - } - - private function findTemplateFiles(string $name): array - { - [$namespace, $shortname] = $this->parseTemplateName($name); - - $files = []; - foreach ($this->getFilesystemLoaders() as $loader) { - foreach ($loader->getPaths($namespace) as $path) { - if (!$this->isAbsolutePath($path)) { - $path = $this->projectDir.'/'.$path; - } - $filename = $path.'/'.$shortname; - - if (is_file($filename)) { - if (false !== $realpath = realpath($filename)) { - $files[$realpath] = $this->getRelativePath($realpath); - } else { - $files[$filename] = $this->getRelativePath($filename); - } - } - } - } - - return $files; - } - - private function parseTemplateName(string $name, string $default = FilesystemLoader::MAIN_NAMESPACE): array - { - if (isset($name[0]) && '@' === $name[0]) { - if (false === ($pos = strpos($name, '/')) || $pos === \strlen($name) - 1) { - throw new InvalidArgumentException(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name)); - } - - $namespace = substr($name, 1, $pos - 1); - $shortname = substr($name, $pos + 1); - - return [$namespace, $shortname]; - } - - return [$default, $name]; - } - - private function buildTableRows(array $loaderPaths): array - { - $rows = []; - $firstNamespace = true; - $prevHasSeparator = false; - - foreach ($loaderPaths as $namespace => $paths) { - if (!$firstNamespace && !$prevHasSeparator && \count($paths) > 1) { - $rows[] = ['', '']; - } - $firstNamespace = false; - foreach ($paths as $path) { - $rows[] = [$namespace, $path.\DIRECTORY_SEPARATOR]; - $namespace = ''; - } - if (\count($paths) > 1) { - $rows[] = ['', '']; - $prevHasSeparator = true; - } else { - $prevHasSeparator = false; - } - } - if ($prevHasSeparator) { - array_pop($rows); - } - - return $rows; - } - - private function findAlternatives(string $name, array $collection): array - { - $alternatives = []; - 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; - } - } - - $threshold = 1e3; - $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; }); - ksort($alternatives, \SORT_NATURAL | \SORT_FLAG_CASE); - - return array_keys($alternatives); - } - - private function getRelativePath(string $path): string - { - if (null !== $this->projectDir && str_starts_with($path, $this->projectDir)) { - return ltrim(substr($path, \strlen($this->projectDir)), \DIRECTORY_SEPARATOR); - } - - return $path; - } - - private function isAbsolutePath(string $file): bool - { - return strspn($file, '/\\', 0, 1) || (\strlen($file) > 3 && ctype_alpha($file[0]) && ':' === $file[1] && strspn($file, '/\\', 2, 1)) || null !== parse_url($file, \PHP_URL_SCHEME); - } - - /** - * @return FilesystemLoader[] - */ - private function getFilesystemLoaders(): array - { - if (null !== $this->filesystemLoaders) { - return $this->filesystemLoaders; - } - $this->filesystemLoaders = []; - - $loader = $this->twig->getLoader(); - if ($loader instanceof FilesystemLoader) { - $this->filesystemLoaders[] = $loader; - } elseif ($loader instanceof ChainLoader) { - foreach ($loader->getLoaders() as $l) { - if ($l instanceof FilesystemLoader) { - $this->filesystemLoaders[] = $l; - } - } - } - - return $this->filesystemLoaders; - } - - private function getFileLink(string $absolutePath): string - { - if (null === $this->fileLinkFormatter) { - return ''; - } - - return (string) $this->fileLinkFormatter->format($absolutePath, 1); - } -} diff --git a/lib/symfony/twig-bridge/Command/LintCommand.php b/lib/symfony/twig-bridge/Command/LintCommand.php deleted file mode 100644 index b91110b34..000000000 --- a/lib/symfony/twig-bridge/Command/LintCommand.php +++ /dev/null @@ -1,296 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Command; - -use Symfony\Component\Console\CI\GithubActionReporter; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Completion\CompletionInput; -use Symfony\Component\Console\Completion\CompletionSuggestions; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Exception\RuntimeException; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\Finder\Finder; -use Twig\Environment; -use Twig\Error\Error; -use Twig\Loader\ArrayLoader; -use Twig\Loader\FilesystemLoader; -use Twig\Source; - -/** - * Command that will validate your template syntax and output encountered errors. - * - * @author Marc Weistroff <marc.weistroff@sensiolabs.com> - * @author Jérôme Tamarelle <jerome@tamarelle.net> - */ -class LintCommand extends Command -{ - protected static $defaultName = 'lint:twig'; - protected static $defaultDescription = 'Lint a Twig template and outputs encountered errors'; - - private $twig; - - /** - * @var string|null - */ - private $format; - - public function __construct(Environment $twig) - { - parent::__construct(); - - $this->twig = $twig; - } - - protected function configure() - { - $this - ->setDescription(self::$defaultDescription) - ->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format') - ->addOption('show-deprecations', null, InputOption::VALUE_NONE, 'Show deprecations as errors') - ->addArgument('filename', InputArgument::IS_ARRAY, 'A file, a directory or "-" for reading from STDIN') - ->setHelp(<<<'EOF' -The <info>%command.name%</info> command lints a template and outputs to STDOUT -the first encountered syntax error. - -You can validate the syntax of contents passed from STDIN: - - <info>cat filename | php %command.full_name% -</info> - -Or the syntax of a file: - - <info>php %command.full_name% filename</info> - -Or of a whole directory: - - <info>php %command.full_name% dirname</info> - <info>php %command.full_name% dirname --format=json</info> - -EOF - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - $io = new SymfonyStyle($input, $output); - $filenames = $input->getArgument('filename'); - $showDeprecations = $input->getOption('show-deprecations'); - $this->format = $input->getOption('format'); - - if (null === $this->format) { - $this->format = GithubActionReporter::isGithubActionEnvironment() ? 'github' : 'txt'; - } - - if (['-'] === $filenames) { - return $this->display($input, $output, $io, [$this->validate(file_get_contents('php://stdin'), uniqid('sf_', true))]); - } - - if (!$filenames) { - $loader = $this->twig->getLoader(); - if ($loader instanceof FilesystemLoader) { - $paths = []; - foreach ($loader->getNamespaces() as $namespace) { - $paths[] = $loader->getPaths($namespace); - } - $filenames = array_merge(...$paths); - } - - if (!$filenames) { - throw new RuntimeException('Please provide a filename or pipe template content to STDIN.'); - } - } - - if ($showDeprecations) { - $prevErrorHandler = set_error_handler(static function ($level, $message, $file, $line) use (&$prevErrorHandler) { - if (\E_USER_DEPRECATED === $level) { - $templateLine = 0; - if (preg_match('/ at line (\d+)[ .]/', $message, $matches)) { - $templateLine = $matches[1]; - } - - throw new Error($message, $templateLine); - } - - return $prevErrorHandler ? $prevErrorHandler($level, $message, $file, $line) : false; - }); - } - - try { - $filesInfo = $this->getFilesInfo($filenames); - } finally { - if ($showDeprecations) { - restore_error_handler(); - } - } - - return $this->display($input, $output, $io, $filesInfo); - } - - private function getFilesInfo(array $filenames): array - { - $filesInfo = []; - foreach ($filenames as $filename) { - foreach ($this->findFiles($filename) as $file) { - $filesInfo[] = $this->validate(file_get_contents($file), $file); - } - } - - return $filesInfo; - } - - protected function findFiles(string $filename) - { - if (is_file($filename)) { - return [$filename]; - } elseif (is_dir($filename)) { - return Finder::create()->files()->in($filename)->name('*.twig'); - } - - throw new RuntimeException(sprintf('File or directory "%s" is not readable.', $filename)); - } - - private function validate(string $template, string $file): array - { - $realLoader = $this->twig->getLoader(); - try { - $temporaryLoader = new ArrayLoader([$file => $template]); - $this->twig->setLoader($temporaryLoader); - $nodeTree = $this->twig->parse($this->twig->tokenize(new Source($template, $file))); - $this->twig->compile($nodeTree); - $this->twig->setLoader($realLoader); - } catch (Error $e) { - $this->twig->setLoader($realLoader); - - return ['template' => $template, 'file' => $file, 'line' => $e->getTemplateLine(), 'valid' => false, 'exception' => $e]; - } - - return ['template' => $template, 'file' => $file, 'valid' => true]; - } - - private function display(InputInterface $input, OutputInterface $output, SymfonyStyle $io, array $files) - { - switch ($this->format) { - case 'txt': - return $this->displayTxt($output, $io, $files); - case 'json': - return $this->displayJson($output, $files); - case 'github': - return $this->displayTxt($output, $io, $files, true); - default: - throw new InvalidArgumentException(sprintf('The format "%s" is not supported.', $input->getOption('format'))); - } - } - - private function displayTxt(OutputInterface $output, SymfonyStyle $io, array $filesInfo, bool $errorAsGithubAnnotations = false) - { - $errors = 0; - $githubReporter = $errorAsGithubAnnotations ? new GithubActionReporter($output) : null; - - foreach ($filesInfo as $info) { - if ($info['valid'] && $output->isVerbose()) { - $io->comment('<info>OK</info>'.($info['file'] ? sprintf(' in %s', $info['file']) : '')); - } elseif (!$info['valid']) { - ++$errors; - $this->renderException($io, $info['template'], $info['exception'], $info['file'], $githubReporter); - } - } - - if (0 === $errors) { - $io->success(sprintf('All %d Twig files contain valid syntax.', \count($filesInfo))); - } else { - $io->warning(sprintf('%d Twig files have valid syntax and %d contain errors.', \count($filesInfo) - $errors, $errors)); - } - - return min($errors, 1); - } - - private function displayJson(OutputInterface $output, array $filesInfo) - { - $errors = 0; - - array_walk($filesInfo, function (&$v) use (&$errors) { - $v['file'] = (string) $v['file']; - unset($v['template']); - if (!$v['valid']) { - $v['message'] = $v['exception']->getMessage(); - unset($v['exception']); - ++$errors; - } - }); - - $output->writeln(json_encode($filesInfo, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES)); - - return min($errors, 1); - } - - private function renderException(SymfonyStyle $output, string $template, Error $exception, string $file = null, GithubActionReporter $githubReporter = null) - { - $line = $exception->getTemplateLine(); - - if ($githubReporter) { - $githubReporter->error($exception->getRawMessage(), $file, $line <= 0 ? null : $line); - } - - if ($file) { - $output->text(sprintf('<error> ERROR </error> in %s (line %s)', $file, $line)); - } else { - $output->text(sprintf('<error> ERROR </error> (line %s)', $line)); - } - - // If the line is not known (this might happen for deprecations if we fail at detecting the line for instance), - // we render the message without context, to ensure the message is displayed. - if ($line <= 0) { - $output->text(sprintf('<error> >> %s</error> ', $exception->getRawMessage())); - - return; - } - - foreach ($this->getContext($template, $line) as $lineNumber => $code) { - $output->text(sprintf( - '%s %-6s %s', - $lineNumber === $line ? '<error> >> </error>' : ' ', - $lineNumber, - $code - )); - if ($lineNumber === $line) { - $output->text(sprintf('<error> >> %s</error> ', $exception->getRawMessage())); - } - } - } - - private function getContext(string $template, int $line, int $context = 3) - { - $lines = explode("\n", $template); - - $position = max(0, $line - $context); - $max = min(\count($lines), $line - 1 + $context); - - $result = []; - while ($position < $max) { - $result[$position + 1] = $lines[$position]; - ++$position; - } - - return $result; - } - - public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void - { - if ($input->mustSuggestOptionValuesFor('format')) { - $suggestions->suggestValues(['txt', 'json', 'github']); - } - } -} diff --git a/lib/symfony/twig-bridge/DataCollector/TwigDataCollector.php b/lib/symfony/twig-bridge/DataCollector/TwigDataCollector.php deleted file mode 100644 index 4a4697810..000000000 --- a/lib/symfony/twig-bridge/DataCollector/TwigDataCollector.php +++ /dev/null @@ -1,203 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\DataCollector; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\DataCollector\DataCollector; -use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; -use Twig\Environment; -use Twig\Error\LoaderError; -use Twig\Markup; -use Twig\Profiler\Dumper\HtmlDumper; -use Twig\Profiler\Profile; - -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class TwigDataCollector extends DataCollector implements LateDataCollectorInterface -{ - private $profile; - private $twig; - private $computed; - - public function __construct(Profile $profile, Environment $twig = null) - { - $this->profile = $profile; - $this->twig = $twig; - } - - /** - * {@inheritdoc} - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - } - - /** - * {@inheritdoc} - */ - public function reset() - { - $this->profile->reset(); - $this->computed = null; - $this->data = []; - } - - /** - * {@inheritdoc} - */ - public function lateCollect() - { - $this->data['profile'] = serialize($this->profile); - $this->data['template_paths'] = []; - - if (null === $this->twig) { - return; - } - - $templateFinder = function (Profile $profile) use (&$templateFinder) { - if ($profile->isTemplate()) { - try { - $template = $this->twig->load($name = $profile->getName()); - } catch (LoaderError $e) { - $template = null; - } - - if (null !== $template && '' !== $path = $template->getSourceContext()->getPath()) { - $this->data['template_paths'][$name] = $path; - } - } - - foreach ($profile as $p) { - $templateFinder($p); - } - }; - $templateFinder($this->profile); - } - - public function getTime() - { - return $this->getProfile()->getDuration() * 1000; - } - - public function getTemplateCount() - { - return $this->getComputedData('template_count'); - } - - public function getTemplatePaths() - { - return $this->data['template_paths']; - } - - public function getTemplates() - { - return $this->getComputedData('templates'); - } - - public function getBlockCount() - { - return $this->getComputedData('block_count'); - } - - public function getMacroCount() - { - return $this->getComputedData('macro_count'); - } - - public function getHtmlCallGraph() - { - $dumper = new HtmlDumper(); - $dump = $dumper->dump($this->getProfile()); - - // needed to remove the hardcoded CSS styles - $dump = str_replace([ - '<span style="background-color: #ffd">', - '<span style="color: #d44">', - '<span style="background-color: #dfd">', - '<span style="background-color: #ddf">', - ], [ - '<span class="status-warning">', - '<span class="status-error">', - '<span class="status-success">', - '<span class="status-info">', - ], $dump); - - return new Markup($dump, 'UTF-8'); - } - - public function getProfile() - { - if (null === $this->profile) { - $this->profile = unserialize($this->data['profile'], ['allowed_classes' => ['Twig_Profiler_Profile', 'Twig\Profiler\Profile']]); - } - - return $this->profile; - } - - private function getComputedData(string $index) - { - if (null === $this->computed) { - $this->computed = $this->computeData($this->getProfile()); - } - - return $this->computed[$index]; - } - - private function computeData(Profile $profile) - { - $data = [ - 'template_count' => 0, - 'block_count' => 0, - 'macro_count' => 0, - ]; - - $templates = []; - foreach ($profile as $p) { - $d = $this->computeData($p); - - $data['template_count'] += ($p->isTemplate() ? 1 : 0) + $d['template_count']; - $data['block_count'] += ($p->isBlock() ? 1 : 0) + $d['block_count']; - $data['macro_count'] += ($p->isMacro() ? 1 : 0) + $d['macro_count']; - - if ($p->isTemplate()) { - if (!isset($templates[$p->getTemplate()])) { - $templates[$p->getTemplate()] = 1; - } else { - ++$templates[$p->getTemplate()]; - } - } - - foreach ($d['templates'] as $template => $count) { - if (!isset($templates[$template])) { - $templates[$template] = $count; - } else { - $templates[$template] += $count; - } - } - } - $data['templates'] = $templates; - - return $data; - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'twig'; - } -} diff --git a/lib/symfony/twig-bridge/ErrorRenderer/TwigErrorRenderer.php b/lib/symfony/twig-bridge/ErrorRenderer/TwigErrorRenderer.php deleted file mode 100644 index b0ccd684e..000000000 --- a/lib/symfony/twig-bridge/ErrorRenderer/TwigErrorRenderer.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\ErrorRenderer; - -use Symfony\Component\ErrorHandler\ErrorRenderer\ErrorRendererInterface; -use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer; -use Symfony\Component\ErrorHandler\Exception\FlattenException; -use Symfony\Component\HttpFoundation\RequestStack; -use Twig\Environment; - -/** - * Provides the ability to render custom Twig-based HTML error pages - * in non-debug mode, otherwise falls back to HtmlErrorRenderer. - * - * @author Yonel Ceruto <yonelceruto@gmail.com> - */ -class TwigErrorRenderer implements ErrorRendererInterface -{ - private $twig; - private $fallbackErrorRenderer; - private $debug; - - /** - * @param bool|callable $debug The debugging mode as a boolean or a callable that should return it - */ - public function __construct(Environment $twig, HtmlErrorRenderer $fallbackErrorRenderer = null, $debug = false) - { - if (!\is_bool($debug) && !\is_callable($debug)) { - throw new \TypeError(sprintf('Argument 3 passed to "%s()" must be a boolean or a callable, "%s" given.', __METHOD__, get_debug_type($debug))); - } - - $this->twig = $twig; - $this->fallbackErrorRenderer = $fallbackErrorRenderer ?? new HtmlErrorRenderer(); - $this->debug = $debug; - } - - /** - * {@inheritdoc} - */ - public function render(\Throwable $exception): FlattenException - { - $exception = $this->fallbackErrorRenderer->render($exception); - $debug = \is_bool($this->debug) ? $this->debug : ($this->debug)($exception); - - if ($debug || !$template = $this->findTemplate($exception->getStatusCode())) { - return $exception; - } - - return $exception->setAsString($this->twig->render($template, [ - 'exception' => $exception, - 'status_code' => $exception->getStatusCode(), - 'status_text' => $exception->getStatusText(), - ])); - } - - public static function isDebug(RequestStack $requestStack, bool $debug): \Closure - { - return static function () use ($requestStack, $debug): bool { - if (!$request = $requestStack->getCurrentRequest()) { - return $debug; - } - - return $debug && $request->attributes->getBoolean('showException', true); - }; - } - - private function findTemplate(int $statusCode): ?string - { - $template = sprintf('@Twig/Exception/error%s.html.twig', $statusCode); - if ($this->twig->getLoader()->exists($template)) { - return $template; - } - - $template = '@Twig/Exception/error.html.twig'; - if ($this->twig->getLoader()->exists($template)) { - return $template; - } - - return null; - } -} diff --git a/lib/symfony/twig-bridge/Extension/AssetExtension.php b/lib/symfony/twig-bridge/Extension/AssetExtension.php deleted file mode 100644 index 694821f7b..000000000 --- a/lib/symfony/twig-bridge/Extension/AssetExtension.php +++ /dev/null @@ -1,61 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Extension; - -use Symfony\Component\Asset\Packages; -use Twig\Extension\AbstractExtension; -use Twig\TwigFunction; - -/** - * Twig extension for the Symfony Asset component. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class AssetExtension extends AbstractExtension -{ - private $packages; - - public function __construct(Packages $packages) - { - $this->packages = $packages; - } - - /** - * {@inheritdoc} - */ - public function getFunctions(): array - { - return [ - new TwigFunction('asset', [$this, 'getAssetUrl']), - new TwigFunction('asset_version', [$this, 'getAssetVersion']), - ]; - } - - /** - * Returns the public url/path of an asset. - * - * If the package used to generate the path is an instance of - * UrlPackage, you will always get a URL and not a path. - */ - public function getAssetUrl(string $path, string $packageName = null): string - { - return $this->packages->getUrl($path, $packageName); - } - - /** - * Returns the version of an asset. - */ - public function getAssetVersion(string $path, string $packageName = null): string - { - return $this->packages->getVersion($path, $packageName); - } -} diff --git a/lib/symfony/twig-bridge/Extension/CodeExtension.php b/lib/symfony/twig-bridge/Extension/CodeExtension.php deleted file mode 100644 index 3bf8ccd29..000000000 --- a/lib/symfony/twig-bridge/Extension/CodeExtension.php +++ /dev/null @@ -1,246 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Extension; - -use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; -use Twig\Extension\AbstractExtension; -use Twig\TwigFilter; - -/** - * Twig extension relate to PHP code and used by the profiler and the default exception templates. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class CodeExtension extends AbstractExtension -{ - private $fileLinkFormat; - private $charset; - private $projectDir; - - /** - * @param string|FileLinkFormatter $fileLinkFormat The format for links to source files - */ - public function __construct($fileLinkFormat, string $projectDir, string $charset) - { - $this->fileLinkFormat = $fileLinkFormat ?: \ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); - $this->projectDir = str_replace('\\', '/', $projectDir).'/'; - $this->charset = $charset; - } - - /** - * {@inheritdoc} - */ - public function getFilters(): array - { - return [ - new TwigFilter('abbr_class', [$this, 'abbrClass'], ['is_safe' => ['html']]), - new TwigFilter('abbr_method', [$this, 'abbrMethod'], ['is_safe' => ['html']]), - new TwigFilter('format_args', [$this, 'formatArgs'], ['is_safe' => ['html']]), - new TwigFilter('format_args_as_text', [$this, 'formatArgsAsText']), - new TwigFilter('file_excerpt', [$this, 'fileExcerpt'], ['is_safe' => ['html']]), - new TwigFilter('format_file', [$this, 'formatFile'], ['is_safe' => ['html']]), - new TwigFilter('format_file_from_text', [$this, 'formatFileFromText'], ['is_safe' => ['html']]), - new TwigFilter('format_log_message', [$this, 'formatLogMessage'], ['is_safe' => ['html']]), - new TwigFilter('file_link', [$this, 'getFileLink']), - new TwigFilter('file_relative', [$this, 'getFileRelative']), - ]; - } - - public function abbrClass(string $class): string - { - $parts = explode('\\', $class); - $short = array_pop($parts); - - return sprintf('<abbr title="%s">%s</abbr>', $class, $short); - } - - public function abbrMethod(string $method): string - { - if (str_contains($method, '::')) { - [$class, $method] = explode('::', $method, 2); - $result = sprintf('%s::%s()', $this->abbrClass($class), $method); - } elseif ('Closure' === $method) { - $result = sprintf('<abbr title="%s">%1$s</abbr>', $method); - } else { - $result = sprintf('<abbr title="%s">%1$s</abbr>()', $method); - } - - return $result; - } - - /** - * Formats an array as a string. - */ - public function formatArgs(array $args): string - { - $result = []; - foreach ($args as $key => $item) { - if ('object' === $item[0]) { - $parts = explode('\\', $item[1]); - $short = array_pop($parts); - $formattedValue = sprintf('<em>object</em>(<abbr title="%s">%s</abbr>)', $item[1], $short); - } elseif ('array' === $item[0]) { - $formattedValue = sprintf('<em>array</em>(%s)', \is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]); - } elseif ('null' === $item[0]) { - $formattedValue = '<em>null</em>'; - } elseif ('boolean' === $item[0]) { - $formattedValue = '<em>'.strtolower(var_export($item[1], true)).'</em>'; - } elseif ('resource' === $item[0]) { - $formattedValue = '<em>resource</em>'; - } else { - $formattedValue = str_replace("\n", '', htmlspecialchars(var_export($item[1], true), \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset)); - } - - $result[] = \is_int($key) ? $formattedValue : sprintf("'%s' => %s", $key, $formattedValue); - } - - return implode(', ', $result); - } - - /** - * Formats an array as a string. - */ - public function formatArgsAsText(array $args): string - { - return strip_tags($this->formatArgs($args)); - } - - /** - * Returns an excerpt of a code file around the given line number. - */ - public function fileExcerpt(string $file, int $line, int $srcContext = 3): ?string - { - if (is_file($file) && is_readable($file)) { - // highlight_file could throw warnings - // see https://bugs.php.net/25725 - $code = @highlight_file($file, true); - // remove main code/span tags - $code = preg_replace('#^<code.*?>\s*<span.*?>(.*)</span>\s*</code>#s', '\\1', $code); - // split multiline spans - $code = preg_replace_callback('#<span ([^>]++)>((?:[^<]*+<br \/>)++[^<]*+)</span>#', function ($m) { - return "<span $m[1]>".str_replace('<br />', "</span><br /><span $m[1]>", $m[2]).'</span>'; - }, $code); - $content = explode('<br />', $code); - - $lines = []; - if (0 > $srcContext) { - $srcContext = \count($content); - } - - for ($i = max($line - $srcContext, 1), $max = min($line + $srcContext, \count($content)); $i <= $max; ++$i) { - $lines[] = '<li'.($i == $line ? ' class="selected"' : '').'><a class="anchor" id="line'.$i.'"></a><code>'.self::fixCodeMarkup($content[$i - 1]).'</code></li>'; - } - - return '<ol start="'.max($line - $srcContext, 1).'">'.implode("\n", $lines).'</ol>'; - } - - return null; - } - - /** - * Formats a file path. - */ - public function formatFile(string $file, int $line, string $text = null): string - { - $file = trim($file); - - if (null === $text) { - $text = $file; - if (null !== $rel = $this->getFileRelative($text)) { - $rel = explode('/', $rel, 2); - $text = sprintf('<abbr title="%s%2$s">%s</abbr>%s', $this->projectDir, $rel[0], '/'.($rel[1] ?? '')); - } - } - - if (0 < $line) { - $text .= ' at line '.$line; - } - - if (false !== $link = $this->getFileLink($file, $line)) { - return sprintf('<a href="%s" title="Click to open this file" class="file_link">%s</a>', htmlspecialchars($link, \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset), $text); - } - - return $text; - } - - /** - * Returns the link for a given file/line pair. - * - * @return string|false - */ - public function getFileLink(string $file, int $line) - { - if ($fmt = $this->fileLinkFormat) { - return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line); - } - - return false; - } - - public function getFileRelative(string $file): ?string - { - $file = str_replace('\\', '/', $file); - - if (null !== $this->projectDir && str_starts_with($file, $this->projectDir)) { - return ltrim(substr($file, \strlen($this->projectDir)), '/'); - } - - return null; - } - - public function formatFileFromText(string $text): string - { - return preg_replace_callback('/in ("|&quot;)?(.+?)\1(?: +(?:on|at))? +line (\d+)/s', function ($match) { - return 'in '.$this->formatFile($match[2], $match[3]); - }, $text); - } - - /** - * @internal - */ - public function formatLogMessage(string $message, array $context): string - { - if ($context && str_contains($message, '{')) { - $replacements = []; - foreach ($context as $key => $val) { - if (\is_scalar($val)) { - $replacements['{'.$key.'}'] = $val; - } - } - - if ($replacements) { - $message = strtr($message, $replacements); - } - } - - return htmlspecialchars($message, \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset); - } - - protected static function fixCodeMarkup(string $line): string - { - // </span> ending tag from previous line - $opening = strpos($line, '<span'); - $closing = strpos($line, '</span>'); - if (false !== $closing && (false === $opening || $closing < $opening)) { - $line = substr_replace($line, '', $closing, 7); - } - - // missing </span> tag at the end of line - $opening = strpos($line, '<span'); - $closing = strpos($line, '</span>'); - if (false !== $opening && (false === $closing || $closing > $opening)) { - $line .= '</span>'; - } - - return trim($line); - } -} diff --git a/lib/symfony/twig-bridge/Extension/CsrfExtension.php b/lib/symfony/twig-bridge/Extension/CsrfExtension.php deleted file mode 100644 index 646a48798..000000000 --- a/lib/symfony/twig-bridge/Extension/CsrfExtension.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Extension; - -use Twig\Extension\AbstractExtension; -use Twig\TwigFunction; - -/** - * @author Christian Flothmann <christian.flothmann@sensiolabs.de> - * @author Titouan Galopin <galopintitouan@gmail.com> - */ -final class CsrfExtension extends AbstractExtension -{ - /** - * {@inheritdoc} - */ - public function getFunctions(): array - { - return [ - new TwigFunction('csrf_token', [CsrfRuntime::class, 'getCsrfToken']), - ]; - } -} diff --git a/lib/symfony/twig-bridge/Extension/CsrfRuntime.php b/lib/symfony/twig-bridge/Extension/CsrfRuntime.php deleted file mode 100644 index c3d5da647..000000000 --- a/lib/symfony/twig-bridge/Extension/CsrfRuntime.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Extension; - -use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; - -/** - * @author Christian Flothmann <christian.flothmann@sensiolabs.de> - * @author Titouan Galopin <galopintitouan@gmail.com> - */ -final class CsrfRuntime -{ - private $csrfTokenManager; - - public function __construct(CsrfTokenManagerInterface $csrfTokenManager) - { - $this->csrfTokenManager = $csrfTokenManager; - } - - public function getCsrfToken(string $tokenId): string - { - return $this->csrfTokenManager->getToken($tokenId)->getValue(); - } -} diff --git a/lib/symfony/twig-bridge/Extension/DumpExtension.php b/lib/symfony/twig-bridge/Extension/DumpExtension.php deleted file mode 100644 index 46ad8eaf6..000000000 --- a/lib/symfony/twig-bridge/Extension/DumpExtension.php +++ /dev/null @@ -1,86 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Extension; - -use Symfony\Bridge\Twig\TokenParser\DumpTokenParser; -use Symfony\Component\VarDumper\Cloner\ClonerInterface; -use Symfony\Component\VarDumper\Dumper\HtmlDumper; -use Twig\Environment; -use Twig\Extension\AbstractExtension; -use Twig\Template; -use Twig\TwigFunction; - -/** - * Provides integration of the dump() function with Twig. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -final class DumpExtension extends AbstractExtension -{ - private $cloner; - private $dumper; - - public function __construct(ClonerInterface $cloner, HtmlDumper $dumper = null) - { - $this->cloner = $cloner; - $this->dumper = $dumper; - } - - /** - * {@inheritdoc} - */ - public function getFunctions(): array - { - return [ - new TwigFunction('dump', [$this, 'dump'], ['is_safe' => ['html'], 'needs_context' => true, 'needs_environment' => true]), - ]; - } - - /** - * {@inheritdoc} - */ - public function getTokenParsers(): array - { - return [new DumpTokenParser()]; - } - - public function dump(Environment $env, array $context): ?string - { - if (!$env->isDebug()) { - return null; - } - - if (2 === \func_num_args()) { - $vars = []; - foreach ($context as $key => $value) { - if (!$value instanceof Template) { - $vars[$key] = $value; - } - } - - $vars = [$vars]; - } else { - $vars = \func_get_args(); - unset($vars[0], $vars[1]); - } - - $dump = fopen('php://memory', 'r+'); - $this->dumper = $this->dumper ?? new HtmlDumper(); - $this->dumper->setCharset($env->getCharset()); - - foreach ($vars as $value) { - $this->dumper->dump($this->cloner->cloneVar($value), $dump); - } - - return stream_get_contents($dump, -1, 0); - } -} diff --git a/lib/symfony/twig-bridge/Extension/ExpressionExtension.php b/lib/symfony/twig-bridge/Extension/ExpressionExtension.php deleted file mode 100644 index 8d2a35c99..000000000 --- a/lib/symfony/twig-bridge/Extension/ExpressionExtension.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Extension; - -use Symfony\Component\ExpressionLanguage\Expression; -use Twig\Extension\AbstractExtension; -use Twig\TwigFunction; - -/** - * ExpressionExtension gives a way to create Expressions from a template. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class ExpressionExtension extends AbstractExtension -{ - /** - * {@inheritdoc} - */ - public function getFunctions(): array - { - return [ - new TwigFunction('expression', [$this, 'createExpression']), - ]; - } - - public function createExpression(string $expression): Expression - { - return new Expression($expression); - } -} diff --git a/lib/symfony/twig-bridge/Extension/FormExtension.php b/lib/symfony/twig-bridge/Extension/FormExtension.php deleted file mode 100644 index 7f0b1ed59..000000000 --- a/lib/symfony/twig-bridge/Extension/FormExtension.php +++ /dev/null @@ -1,219 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Extension; - -use Symfony\Bridge\Twig\TokenParser\FormThemeTokenParser; -use Symfony\Component\Form\ChoiceList\View\ChoiceGroupView; -use Symfony\Component\Form\ChoiceList\View\ChoiceView; -use Symfony\Component\Form\FormError; -use Symfony\Component\Form\FormView; -use Symfony\Contracts\Translation\TranslatorInterface; -use Twig\Extension\AbstractExtension; -use Twig\TwigFilter; -use Twig\TwigFunction; -use Twig\TwigTest; - -/** - * FormExtension extends Twig with form capabilities. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Bernhard Schussek <bschussek@gmail.com> - */ -final class FormExtension extends AbstractExtension -{ - private $translator; - - public function __construct(TranslatorInterface $translator = null) - { - $this->translator = $translator; - } - - /** - * {@inheritdoc} - */ - public function getTokenParsers(): array - { - return [ - // {% form_theme form "SomeBundle::widgets.twig" %} - new FormThemeTokenParser(), - ]; - } - - /** - * {@inheritdoc} - */ - public function getFunctions(): array - { - return [ - new TwigFunction('form_widget', null, ['node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => ['html']]), - new TwigFunction('form_errors', null, ['node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => ['html']]), - new TwigFunction('form_label', null, ['node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => ['html']]), - new TwigFunction('form_help', null, ['node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => ['html']]), - new TwigFunction('form_row', null, ['node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => ['html']]), - new TwigFunction('form_rest', null, ['node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => ['html']]), - new TwigFunction('form', null, ['node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => ['html']]), - new TwigFunction('form_start', null, ['node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => ['html']]), - new TwigFunction('form_end', null, ['node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => ['html']]), - new TwigFunction('csrf_token', ['Symfony\Component\Form\FormRenderer', 'renderCsrfToken']), - new TwigFunction('form_parent', 'Symfony\Bridge\Twig\Extension\twig_get_form_parent'), - new TwigFunction('field_name', [$this, 'getFieldName']), - new TwigFunction('field_value', [$this, 'getFieldValue']), - new TwigFunction('field_label', [$this, 'getFieldLabel']), - new TwigFunction('field_help', [$this, 'getFieldHelp']), - new TwigFunction('field_errors', [$this, 'getFieldErrors']), - new TwigFunction('field_choices', [$this, 'getFieldChoices']), - ]; - } - - /** - * {@inheritdoc} - */ - public function getFilters(): array - { - return [ - new TwigFilter('humanize', ['Symfony\Component\Form\FormRenderer', 'humanize']), - new TwigFilter('form_encode_currency', ['Symfony\Component\Form\FormRenderer', 'encodeCurrency'], ['is_safe' => ['html'], 'needs_environment' => true]), - ]; - } - - /** - * {@inheritdoc} - */ - public function getTests(): array - { - return [ - new TwigTest('selectedchoice', 'Symfony\Bridge\Twig\Extension\twig_is_selected_choice'), - new TwigTest('rootform', 'Symfony\Bridge\Twig\Extension\twig_is_root_form'), - ]; - } - - public function getFieldName(FormView $view): string - { - $view->setRendered(); - - return $view->vars['full_name']; - } - - /** - * @return string|array - */ - public function getFieldValue(FormView $view) - { - return $view->vars['value']; - } - - public function getFieldLabel(FormView $view): ?string - { - if (false === $label = $view->vars['label']) { - return null; - } - - if (!$label && $labelFormat = $view->vars['label_format']) { - $label = str_replace(['%id%', '%name%'], [$view->vars['id'], $view->vars['name']], $labelFormat); - } elseif (!$label) { - $label = ucfirst(strtolower(trim(preg_replace(['/([A-Z])/', '/[_\s]+/'], ['_$1', ' '], $view->vars['name'])))); - } - - return $this->createFieldTranslation( - $label, - $view->vars['label_translation_parameters'] ?: [], - $view->vars['translation_domain'] - ); - } - - public function getFieldHelp(FormView $view): ?string - { - return $this->createFieldTranslation( - $view->vars['help'], - $view->vars['help_translation_parameters'] ?: [], - $view->vars['translation_domain'] - ); - } - - /** - * @return string[] - */ - public function getFieldErrors(FormView $view): iterable - { - /** @var FormError $error */ - foreach ($view->vars['errors'] as $error) { - yield $error->getMessage(); - } - } - - /** - * @return string[]|string[][] - */ - public function getFieldChoices(FormView $view): iterable - { - yield from $this->createFieldChoicesList($view->vars['choices'], $view->vars['choice_translation_domain']); - } - - private function createFieldChoicesList(iterable $choices, $translationDomain): iterable - { - foreach ($choices as $choice) { - $translatableLabel = $this->createFieldTranslation($choice->label, [], $translationDomain); - - if ($choice instanceof ChoiceGroupView) { - yield $translatableLabel => $this->createFieldChoicesList($choice, $translationDomain); - - continue; - } - - /* @var ChoiceView $choice */ - yield $translatableLabel => $choice->value; - } - } - - private function createFieldTranslation(?string $value, array $parameters, $domain): ?string - { - if (!$this->translator || !$value || false === $domain) { - return $value; - } - - return $this->translator->trans($value, $parameters, $domain); - } -} - -/** - * Returns whether a choice is selected for a given form value. - * - * This is a function and not callable due to performance reasons. - * - * @param string|array $selectedValue The selected value to compare - * - * @see ChoiceView::isSelected() - */ -function twig_is_selected_choice(ChoiceView $choice, $selectedValue): bool -{ - if (\is_array($selectedValue)) { - return \in_array($choice->value, $selectedValue, true); - } - - return $choice->value === $selectedValue; -} - -/** - * @internal - */ -function twig_is_root_form(FormView $formView): bool -{ - return null === $formView->parent; -} - -/** - * @internal - */ -function twig_get_form_parent(FormView $formView): ?FormView -{ - return $formView->parent; -} diff --git a/lib/symfony/twig-bridge/Extension/HttpFoundationExtension.php b/lib/symfony/twig-bridge/Extension/HttpFoundationExtension.php deleted file mode 100644 index a9ee05c4d..000000000 --- a/lib/symfony/twig-bridge/Extension/HttpFoundationExtension.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Extension; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\UrlHelper; -use Twig\Extension\AbstractExtension; -use Twig\TwigFunction; - -/** - * Twig extension for the Symfony HttpFoundation component. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class HttpFoundationExtension extends AbstractExtension -{ - private $urlHelper; - - public function __construct(UrlHelper $urlHelper) - { - $this->urlHelper = $urlHelper; - } - - /** - * {@inheritdoc} - */ - public function getFunctions(): array - { - return [ - new TwigFunction('absolute_url', [$this, 'generateAbsoluteUrl']), - new TwigFunction('relative_path', [$this, 'generateRelativePath']), - ]; - } - - /** - * Returns the absolute URL for the given absolute or relative path. - * - * This method returns the path unchanged if no request is available. - * - * @see Request::getUriForPath() - */ - public function generateAbsoluteUrl(string $path): string - { - return $this->urlHelper->getAbsoluteUrl($path); - } - - /** - * Returns a relative path based on the current Request. - * - * This method returns the path unchanged if no request is available. - * - * @see Request::getRelativeUriForPath() - */ - public function generateRelativePath(string $path): string - { - return $this->urlHelper->getRelativePath($path); - } -} diff --git a/lib/symfony/twig-bridge/Extension/HttpKernelExtension.php b/lib/symfony/twig-bridge/Extension/HttpKernelExtension.php deleted file mode 100644 index 1af9ddb23..000000000 --- a/lib/symfony/twig-bridge/Extension/HttpKernelExtension.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Extension; - -use Symfony\Component\HttpKernel\Controller\ControllerReference; -use Twig\Extension\AbstractExtension; -use Twig\TwigFunction; - -/** - * Provides integration with the HttpKernel component. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class HttpKernelExtension extends AbstractExtension -{ - /** - * {@inheritdoc} - */ - public function getFunctions(): array - { - return [ - new TwigFunction('render', [HttpKernelRuntime::class, 'renderFragment'], ['is_safe' => ['html']]), - new TwigFunction('render_*', [HttpKernelRuntime::class, 'renderFragmentStrategy'], ['is_safe' => ['html']]), - new TwigFunction('fragment_uri', [HttpKernelRuntime::class, 'generateFragmentUri']), - new TwigFunction('controller', static::class.'::controller'), - ]; - } - - public static function controller(string $controller, array $attributes = [], array $query = []): ControllerReference - { - return new ControllerReference($controller, $attributes, $query); - } -} diff --git a/lib/symfony/twig-bridge/Extension/HttpKernelRuntime.php b/lib/symfony/twig-bridge/Extension/HttpKernelRuntime.php deleted file mode 100644 index ab83054a9..000000000 --- a/lib/symfony/twig-bridge/Extension/HttpKernelRuntime.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Extension; - -use Symfony\Component\HttpKernel\Controller\ControllerReference; -use Symfony\Component\HttpKernel\Fragment\FragmentHandler; -use Symfony\Component\HttpKernel\Fragment\FragmentUriGeneratorInterface; - -/** - * Provides integration with the HttpKernel component. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class HttpKernelRuntime -{ - private $handler; - private $fragmentUriGenerator; - - public function __construct(FragmentHandler $handler, FragmentUriGeneratorInterface $fragmentUriGenerator = null) - { - $this->handler = $handler; - $this->fragmentUriGenerator = $fragmentUriGenerator; - } - - /** - * Renders a fragment. - * - * @param string|ControllerReference $uri A URI as a string or a ControllerReference instance - * - * @see FragmentHandler::render() - */ - public function renderFragment($uri, array $options = []): string - { - $strategy = $options['strategy'] ?? 'inline'; - unset($options['strategy']); - - return $this->handler->render($uri, $strategy, $options); - } - - /** - * Renders a fragment. - * - * @param string|ControllerReference $uri A URI as a string or a ControllerReference instance - * - * @see FragmentHandler::render() - */ - public function renderFragmentStrategy(string $strategy, $uri, array $options = []): string - { - return $this->handler->render($uri, $strategy, $options); - } - - public function generateFragmentUri(ControllerReference $controller, bool $absolute = false, bool $strict = true, bool $sign = true): string - { - if (null === $this->fragmentUriGenerator) { - throw new \LogicException(sprintf('An instance of "%s" must be provided to use "%s()".', FragmentUriGeneratorInterface::class, __METHOD__)); - } - - return $this->fragmentUriGenerator->generate($controller, null, $absolute, $strict, $sign); - } -} diff --git a/lib/symfony/twig-bridge/Extension/LogoutUrlExtension.php b/lib/symfony/twig-bridge/Extension/LogoutUrlExtension.php deleted file mode 100644 index 071b9ff24..000000000 --- a/lib/symfony/twig-bridge/Extension/LogoutUrlExtension.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Extension; - -use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator; -use Twig\Extension\AbstractExtension; -use Twig\TwigFunction; - -/** - * LogoutUrlHelper provides generator functions for the logout URL to Twig. - * - * @author Jeremy Mikola <jmikola@gmail.com> - */ -final class LogoutUrlExtension extends AbstractExtension -{ - private $generator; - - public function __construct(LogoutUrlGenerator $generator) - { - $this->generator = $generator; - } - - /** - * {@inheritdoc} - */ - public function getFunctions(): array - { - return [ - new TwigFunction('logout_url', [$this, 'getLogoutUrl']), - new TwigFunction('logout_path', [$this, 'getLogoutPath']), - ]; - } - - /** - * Generates the relative logout URL for the firewall. - * - * @param string|null $key The firewall key or null to use the current firewall key - */ - public function getLogoutPath(string $key = null): string - { - return $this->generator->getLogoutPath($key); - } - - /** - * Generates the absolute logout URL for the firewall. - * - * @param string|null $key The firewall key or null to use the current firewall key - */ - public function getLogoutUrl(string $key = null): string - { - return $this->generator->getLogoutUrl($key); - } -} diff --git a/lib/symfony/twig-bridge/Extension/ProfilerExtension.php b/lib/symfony/twig-bridge/Extension/ProfilerExtension.php deleted file mode 100644 index 51d6eba2d..000000000 --- a/lib/symfony/twig-bridge/Extension/ProfilerExtension.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Extension; - -use Symfony\Component\Stopwatch\Stopwatch; -use Symfony\Component\Stopwatch\StopwatchEvent; -use Twig\Extension\ProfilerExtension as BaseProfilerExtension; -use Twig\Profiler\Profile; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -final class ProfilerExtension extends BaseProfilerExtension -{ - private $stopwatch; - - /** - * @var \SplObjectStorage<Profile, StopwatchEvent> - */ - private $events; - - public function __construct(Profile $profile, Stopwatch $stopwatch = null) - { - parent::__construct($profile); - - $this->stopwatch = $stopwatch; - $this->events = new \SplObjectStorage(); - } - - public function enter(Profile $profile): void - { - if ($this->stopwatch && $profile->isTemplate()) { - $this->events[$profile] = $this->stopwatch->start($profile->getName(), 'template'); - } - - parent::enter($profile); - } - - public function leave(Profile $profile): void - { - parent::leave($profile); - - if ($this->stopwatch && $profile->isTemplate()) { - $this->events[$profile]->stop(); - unset($this->events[$profile]); - } - } -} diff --git a/lib/symfony/twig-bridge/Extension/RoutingExtension.php b/lib/symfony/twig-bridge/Extension/RoutingExtension.php deleted file mode 100644 index 800c22f6d..000000000 --- a/lib/symfony/twig-bridge/Extension/RoutingExtension.php +++ /dev/null @@ -1,93 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Extension; - -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; -use Twig\Extension\AbstractExtension; -use Twig\Node\Expression\ArrayExpression; -use Twig\Node\Expression\ConstantExpression; -use Twig\Node\Node; -use Twig\TwigFunction; - -/** - * Provides integration of the Routing component with Twig. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class RoutingExtension extends AbstractExtension -{ - private $generator; - - public function __construct(UrlGeneratorInterface $generator) - { - $this->generator = $generator; - } - - /** - * {@inheritdoc} - */ - public function getFunctions(): array - { - return [ - new TwigFunction('url', [$this, 'getUrl'], ['is_safe_callback' => [$this, 'isUrlGenerationSafe']]), - new TwigFunction('path', [$this, 'getPath'], ['is_safe_callback' => [$this, 'isUrlGenerationSafe']]), - ]; - } - - public function getPath(string $name, array $parameters = [], bool $relative = false): string - { - return $this->generator->generate($name, $parameters, $relative ? UrlGeneratorInterface::RELATIVE_PATH : UrlGeneratorInterface::ABSOLUTE_PATH); - } - - public function getUrl(string $name, array $parameters = [], bool $schemeRelative = false): string - { - return $this->generator->generate($name, $parameters, $schemeRelative ? UrlGeneratorInterface::NETWORK_PATH : UrlGeneratorInterface::ABSOLUTE_URL); - } - - /** - * Determines at compile time whether the generated URL will be safe and thus - * saving the unneeded automatic escaping for performance reasons. - * - * The URL generation process percent encodes non-alphanumeric characters. So there is no risk - * that malicious/invalid characters are part of the URL. The only character within an URL that - * must be escaped in html is the ampersand ("&") which separates query params. So we cannot mark - * the URL generation as always safe, but only when we are sure there won't be multiple query - * params. This is the case when there are none or only one constant parameter given. - * E.g. we know beforehand this will be safe: - * - path('route') - * - path('route', {'param': 'value'}) - * But the following may not: - * - path('route', var) - * - path('route', {'param': ['val1', 'val2'] }) // a sub-array - * - path('route', {'param1': 'value1', 'param2': 'value2'}) - * If param1 and param2 reference placeholder in the route, it would still be safe. But we don't know. - * - * @param Node $argsNode The arguments of the path/url function - * - * @return array An array with the contexts the URL is safe - */ - public function isUrlGenerationSafe(Node $argsNode): array - { - // support named arguments - $paramsNode = $argsNode->hasNode('parameters') ? $argsNode->getNode('parameters') : ( - $argsNode->hasNode(1) ? $argsNode->getNode(1) : null - ); - - if (null === $paramsNode || $paramsNode instanceof ArrayExpression && \count($paramsNode) <= 2 && - (!$paramsNode->hasNode(1) || $paramsNode->getNode(1) instanceof ConstantExpression) - ) { - return ['html']; - } - - return []; - } -} diff --git a/lib/symfony/twig-bridge/Extension/SecurityExtension.php b/lib/symfony/twig-bridge/Extension/SecurityExtension.php deleted file mode 100644 index 0e58fc0ec..000000000 --- a/lib/symfony/twig-bridge/Extension/SecurityExtension.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Extension; - -use Symfony\Component\Security\Acl\Voter\FieldVote; -use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; -use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException; -use Symfony\Component\Security\Http\Impersonate\ImpersonateUrlGenerator; -use Twig\Extension\AbstractExtension; -use Twig\TwigFunction; - -/** - * SecurityExtension exposes security context features. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class SecurityExtension extends AbstractExtension -{ - private $securityChecker; - - private $impersonateUrlGenerator; - - public function __construct(AuthorizationCheckerInterface $securityChecker = null, ImpersonateUrlGenerator $impersonateUrlGenerator = null) - { - $this->securityChecker = $securityChecker; - $this->impersonateUrlGenerator = $impersonateUrlGenerator; - } - - /** - * @param mixed $object - */ - public function isGranted($role, $object = null, string $field = null): bool - { - if (null === $this->securityChecker) { - return false; - } - - if (null !== $field) { - $object = new FieldVote($object, $field); - } - - try { - return $this->securityChecker->isGranted($role, $object); - } catch (AuthenticationCredentialsNotFoundException $e) { - return false; - } - } - - public function getImpersonateExitUrl(string $exitTo = null): string - { - if (null === $this->impersonateUrlGenerator) { - return ''; - } - - return $this->impersonateUrlGenerator->generateExitUrl($exitTo); - } - - public function getImpersonateExitPath(string $exitTo = null): string - { - if (null === $this->impersonateUrlGenerator) { - return ''; - } - - return $this->impersonateUrlGenerator->generateExitPath($exitTo); - } - - /** - * {@inheritdoc} - */ - public function getFunctions(): array - { - return [ - new TwigFunction('is_granted', [$this, 'isGranted']), - new TwigFunction('impersonation_exit_url', [$this, 'getImpersonateExitUrl']), - new TwigFunction('impersonation_exit_path', [$this, 'getImpersonateExitPath']), - ]; - } -} diff --git a/lib/symfony/twig-bridge/Extension/SerializerExtension.php b/lib/symfony/twig-bridge/Extension/SerializerExtension.php deleted file mode 100644 index f38571efa..000000000 --- a/lib/symfony/twig-bridge/Extension/SerializerExtension.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Extension; - -use Twig\Extension\AbstractExtension; -use Twig\TwigFilter; - -/** - * @author Jesse Rushlow <jr@rushlow.dev> - */ -final class SerializerExtension extends AbstractExtension -{ - public function getFilters(): array - { - return [ - new TwigFilter('serialize', [SerializerRuntime::class, 'serialize']), - ]; - } -} diff --git a/lib/symfony/twig-bridge/Extension/SerializerRuntime.php b/lib/symfony/twig-bridge/Extension/SerializerRuntime.php deleted file mode 100644 index 3a4087aa7..000000000 --- a/lib/symfony/twig-bridge/Extension/SerializerRuntime.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Extension; - -use Symfony\Component\Serializer\SerializerInterface; -use Twig\Extension\RuntimeExtensionInterface; - -/** - * @author Jesse Rushlow <jr@rushlow.dev> - */ -final class SerializerRuntime implements RuntimeExtensionInterface -{ - private $serializer; - - public function __construct(SerializerInterface $serializer) - { - $this->serializer = $serializer; - } - - public function serialize($data, string $format = 'json', array $context = []): string - { - return $this->serializer->serialize($data, $format, $context); - } -} diff --git a/lib/symfony/twig-bridge/Extension/StopwatchExtension.php b/lib/symfony/twig-bridge/Extension/StopwatchExtension.php deleted file mode 100644 index 80a25a949..000000000 --- a/lib/symfony/twig-bridge/Extension/StopwatchExtension.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Extension; - -use Symfony\Bridge\Twig\TokenParser\StopwatchTokenParser; -use Symfony\Component\Stopwatch\Stopwatch; -use Twig\Extension\AbstractExtension; -use Twig\TokenParser\TokenParserInterface; - -/** - * Twig extension for the stopwatch helper. - * - * @author Wouter J <wouter@wouterj.nl> - */ -final class StopwatchExtension extends AbstractExtension -{ - private $stopwatch; - private $enabled; - - public function __construct(Stopwatch $stopwatch = null, bool $enabled = true) - { - $this->stopwatch = $stopwatch; - $this->enabled = $enabled; - } - - public function getStopwatch(): Stopwatch - { - return $this->stopwatch; - } - - /** - * @return TokenParserInterface[] - */ - public function getTokenParsers(): array - { - return [ - /* - * {% stopwatch foo %} - * Some stuff which will be recorded on the timeline - * {% endstopwatch %} - */ - new StopwatchTokenParser(null !== $this->stopwatch && $this->enabled), - ]; - } -} diff --git a/lib/symfony/twig-bridge/Extension/TranslationExtension.php b/lib/symfony/twig-bridge/Extension/TranslationExtension.php deleted file mode 100644 index c2797d837..000000000 --- a/lib/symfony/twig-bridge/Extension/TranslationExtension.php +++ /dev/null @@ -1,145 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Extension; - -use Symfony\Bridge\Twig\NodeVisitor\TranslationDefaultDomainNodeVisitor; -use Symfony\Bridge\Twig\NodeVisitor\TranslationNodeVisitor; -use Symfony\Bridge\Twig\TokenParser\TransDefaultDomainTokenParser; -use Symfony\Bridge\Twig\TokenParser\TransTokenParser; -use Symfony\Component\Translation\TranslatableMessage; -use Symfony\Contracts\Translation\TranslatableInterface; -use Symfony\Contracts\Translation\TranslatorInterface; -use Symfony\Contracts\Translation\TranslatorTrait; -use Twig\Extension\AbstractExtension; -use Twig\TwigFilter; -use Twig\TwigFunction; - -// Help opcache.preload discover always-needed symbols -class_exists(TranslatorInterface::class); -class_exists(TranslatorTrait::class); - -/** - * Provides integration of the Translation component with Twig. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class TranslationExtension extends AbstractExtension -{ - private $translator; - private $translationNodeVisitor; - - public function __construct(TranslatorInterface $translator = null, TranslationNodeVisitor $translationNodeVisitor = null) - { - $this->translator = $translator; - $this->translationNodeVisitor = $translationNodeVisitor; - } - - public function getTranslator(): TranslatorInterface - { - if (null === $this->translator) { - if (!interface_exists(TranslatorInterface::class)) { - throw new \LogicException(sprintf('You cannot use the "%s" if the Translation Contracts are not available. Try running "composer require symfony/translation".', __CLASS__)); - } - - $this->translator = new class() implements TranslatorInterface { - use TranslatorTrait; - }; - } - - return $this->translator; - } - - /** - * {@inheritdoc} - */ - public function getFunctions(): array - { - return [ - new TwigFunction('t', [$this, 'createTranslatable']), - ]; - } - - /** - * {@inheritdoc} - */ - public function getFilters(): array - { - return [ - new TwigFilter('trans', [$this, 'trans']), - ]; - } - - /** - * {@inheritdoc} - */ - public function getTokenParsers(): array - { - return [ - // {% trans %}Symfony is great!{% endtrans %} - new TransTokenParser(), - - // {% trans_default_domain "foobar" %} - new TransDefaultDomainTokenParser(), - ]; - } - - /** - * {@inheritdoc} - */ - public function getNodeVisitors(): array - { - return [$this->getTranslationNodeVisitor(), new TranslationDefaultDomainNodeVisitor()]; - } - - public function getTranslationNodeVisitor(): TranslationNodeVisitor - { - return $this->translationNodeVisitor ?: $this->translationNodeVisitor = new TranslationNodeVisitor(); - } - - /** - * @param string|\Stringable|TranslatableInterface|null $message - * @param array|string $arguments Can be the locale as a string when $message is a TranslatableInterface - */ - public function trans($message, $arguments = [], string $domain = null, string $locale = null, int $count = null): string - { - if ($message instanceof TranslatableInterface) { - if ([] !== $arguments && !\is_string($arguments)) { - throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be a locale passed as a string when the message is a "%s", "%s" given.', __METHOD__, TranslatableInterface::class, get_debug_type($arguments))); - } - - return $message->trans($this->getTranslator(), $locale ?? (\is_string($arguments) ? $arguments : null)); - } - - if (!\is_array($arguments)) { - throw new \TypeError(sprintf('Unless the message is a "%s", argument 2 passed to "%s()" must be an array of parameters, "%s" given.', TranslatableInterface::class, __METHOD__, get_debug_type($arguments))); - } - - if ('' === $message = (string) $message) { - return ''; - } - - if (null !== $count) { - $arguments['%count%'] = $count; - } - - return $this->getTranslator()->trans($message, $arguments, $domain, $locale); - } - - public function createTranslatable(string $message, array $parameters = [], string $domain = null): TranslatableMessage - { - if (!class_exists(TranslatableMessage::class)) { - throw new \LogicException(sprintf('You cannot use the "%s" as the Translation Component is not installed. Try running "composer require symfony/translation".', __CLASS__)); - } - - return new TranslatableMessage($message, $parameters, $domain); - } -} diff --git a/lib/symfony/twig-bridge/Extension/WebLinkExtension.php b/lib/symfony/twig-bridge/Extension/WebLinkExtension.php deleted file mode 100644 index 652a75762..000000000 --- a/lib/symfony/twig-bridge/Extension/WebLinkExtension.php +++ /dev/null @@ -1,133 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Extension; - -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\WebLink\GenericLinkProvider; -use Symfony\Component\WebLink\Link; -use Twig\Extension\AbstractExtension; -use Twig\TwigFunction; - -/** - * Twig extension for the Symfony WebLink component. - * - * @author Kévin Dunglas <dunglas@gmail.com> - */ -final class WebLinkExtension extends AbstractExtension -{ - private $requestStack; - - public function __construct(RequestStack $requestStack) - { - $this->requestStack = $requestStack; - } - - /** - * {@inheritdoc} - */ - public function getFunctions(): array - { - return [ - new TwigFunction('link', [$this, 'link']), - new TwigFunction('preload', [$this, 'preload']), - new TwigFunction('dns_prefetch', [$this, 'dnsPrefetch']), - new TwigFunction('preconnect', [$this, 'preconnect']), - new TwigFunction('prefetch', [$this, 'prefetch']), - new TwigFunction('prerender', [$this, 'prerender']), - ]; - } - - /** - * Adds a "Link" HTTP header. - * - * @param string $rel The relation type (e.g. "preload", "prefetch", "prerender" or "dns-prefetch") - * @param array $attributes The attributes of this link (e.g. "['as' => true]", "['pr' => 0.5]") - * - * @return string The relation URI - */ - public function link(string $uri, string $rel, array $attributes = []): string - { - if (!$request = $this->requestStack->getMainRequest()) { - return $uri; - } - - $link = new Link($rel, $uri); - foreach ($attributes as $key => $value) { - $link = $link->withAttribute($key, $value); - } - - $linkProvider = $request->attributes->get('_links', new GenericLinkProvider()); - $request->attributes->set('_links', $linkProvider->withLink($link)); - - return $uri; - } - - /** - * Preloads a resource. - * - * @param array $attributes The attributes of this link (e.g. "['as' => true]", "['crossorigin' => 'use-credentials']") - * - * @return string The path of the asset - */ - public function preload(string $uri, array $attributes = []): string - { - return $this->link($uri, 'preload', $attributes); - } - - /** - * Resolves a resource origin as early as possible. - * - * @param array $attributes The attributes of this link (e.g. "['as' => true]", "['pr' => 0.5]") - * - * @return string The path of the asset - */ - public function dnsPrefetch(string $uri, array $attributes = []): string - { - return $this->link($uri, 'dns-prefetch', $attributes); - } - - /** - * Initiates a early connection to a resource (DNS resolution, TCP handshake, TLS negotiation). - * - * @param array $attributes The attributes of this link (e.g. "['as' => true]", "['pr' => 0.5]") - * - * @return string The path of the asset - */ - public function preconnect(string $uri, array $attributes = []): string - { - return $this->link($uri, 'preconnect', $attributes); - } - - /** - * Indicates to the client that it should prefetch this resource. - * - * @param array $attributes The attributes of this link (e.g. "['as' => true]", "['pr' => 0.5]") - * - * @return string The path of the asset - */ - public function prefetch(string $uri, array $attributes = []): string - { - return $this->link($uri, 'prefetch', $attributes); - } - - /** - * Indicates to the client that it should prerender this resource . - * - * @param array $attributes The attributes of this link (e.g. "['as' => true]", "['pr' => 0.5]") - * - * @return string The path of the asset - */ - public function prerender(string $uri, array $attributes = []): string - { - return $this->link($uri, 'prerender', $attributes); - } -} diff --git a/lib/symfony/twig-bridge/Extension/WorkflowExtension.php b/lib/symfony/twig-bridge/Extension/WorkflowExtension.php deleted file mode 100644 index 9b5911ec2..000000000 --- a/lib/symfony/twig-bridge/Extension/WorkflowExtension.php +++ /dev/null @@ -1,121 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Extension; - -use Symfony\Component\Workflow\Registry; -use Symfony\Component\Workflow\Transition; -use Symfony\Component\Workflow\TransitionBlockerList; -use Twig\Extension\AbstractExtension; -use Twig\TwigFunction; - -/** - * WorkflowExtension. - * - * @author Grégoire Pineau <lyrixx@lyrixx.info> - * @author Carlos Pereira De Amorim <carlos@shauri.fr> - */ -final class WorkflowExtension extends AbstractExtension -{ - private $workflowRegistry; - - public function __construct(Registry $workflowRegistry) - { - $this->workflowRegistry = $workflowRegistry; - } - - /** - * {@inheritdoc} - */ - public function getFunctions(): array - { - return [ - new TwigFunction('workflow_can', [$this, 'canTransition']), - new TwigFunction('workflow_transitions', [$this, 'getEnabledTransitions']), - new TwigFunction('workflow_transition', [$this, 'getEnabledTransition']), - new TwigFunction('workflow_has_marked_place', [$this, 'hasMarkedPlace']), - new TwigFunction('workflow_marked_places', [$this, 'getMarkedPlaces']), - new TwigFunction('workflow_metadata', [$this, 'getMetadata']), - new TwigFunction('workflow_transition_blockers', [$this, 'buildTransitionBlockerList']), - ]; - } - - /** - * Returns true if the transition is enabled. - */ - public function canTransition(object $subject, string $transitionName, string $name = null): bool - { - return $this->workflowRegistry->get($subject, $name)->can($subject, $transitionName); - } - - /** - * Returns all enabled transitions. - * - * @return Transition[] - */ - public function getEnabledTransitions(object $subject, string $name = null): array - { - return $this->workflowRegistry->get($subject, $name)->getEnabledTransitions($subject); - } - - public function getEnabledTransition(object $subject, string $transition, string $name = null): ?Transition - { - return $this->workflowRegistry->get($subject, $name)->getEnabledTransition($subject, $transition); - } - - /** - * Returns true if the place is marked. - */ - public function hasMarkedPlace(object $subject, string $placeName, string $name = null): bool - { - return $this->workflowRegistry->get($subject, $name)->getMarking($subject)->has($placeName); - } - - /** - * Returns marked places. - * - * @return string[]|int[] - */ - public function getMarkedPlaces(object $subject, bool $placesNameOnly = true, string $name = null): array - { - $places = $this->workflowRegistry->get($subject, $name)->getMarking($subject)->getPlaces(); - - if ($placesNameOnly) { - return array_keys($places); - } - - return $places; - } - - /** - * Returns the metadata for a specific subject. - * - * @param string|Transition|null $metadataSubject Use null to get workflow metadata - * Use a string (the place name) to get place metadata - * Use a Transition instance to get transition metadata - */ - public function getMetadata(object $subject, string $key, $metadataSubject = null, string $name = null) - { - return $this - ->workflowRegistry - ->get($subject, $name) - ->getMetadataStore() - ->getMetadata($key, $metadataSubject) - ; - } - - public function buildTransitionBlockerList(object $subject, string $transitionName, string $name = null): TransitionBlockerList - { - $workflow = $this->workflowRegistry->get($subject, $name); - - return $workflow->buildTransitionBlockerList($subject, $transitionName); - } -} diff --git a/lib/symfony/twig-bridge/Extension/YamlExtension.php b/lib/symfony/twig-bridge/Extension/YamlExtension.php deleted file mode 100644 index 63df13360..000000000 --- a/lib/symfony/twig-bridge/Extension/YamlExtension.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Extension; - -use Symfony\Component\Yaml\Dumper as YamlDumper; -use Twig\Extension\AbstractExtension; -use Twig\TwigFilter; - -/** - * Provides integration of the Yaml component with Twig. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class YamlExtension extends AbstractExtension -{ - /** - * {@inheritdoc} - */ - public function getFilters(): array - { - return [ - new TwigFilter('yaml_encode', [$this, 'encode']), - new TwigFilter('yaml_dump', [$this, 'dump']), - ]; - } - - public function encode($input, int $inline = 0, int $dumpObjects = 0): string - { - static $dumper; - - if (null === $dumper) { - $dumper = new YamlDumper(); - } - - if (\defined('Symfony\Component\Yaml\Yaml::DUMP_OBJECT')) { - return $dumper->dump($input, $inline, 0, $dumpObjects); - } - - return $dumper->dump($input, $inline, 0, false, $dumpObjects); - } - - public function dump($value, int $inline = 0, int $dumpObjects = 0): string - { - if (\is_resource($value)) { - return '%Resource%'; - } - - if (\is_array($value) || \is_object($value)) { - return '%'.\gettype($value).'% '.$this->encode($value, $inline, $dumpObjects); - } - - return $this->encode($value, $inline, $dumpObjects); - } -} diff --git a/lib/symfony/twig-bridge/Form/TwigRendererEngine.php b/lib/symfony/twig-bridge/Form/TwigRendererEngine.php deleted file mode 100644 index b17da3409..000000000 --- a/lib/symfony/twig-bridge/Form/TwigRendererEngine.php +++ /dev/null @@ -1,182 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Form; - -use Symfony\Component\Form\AbstractRendererEngine; -use Symfony\Component\Form\FormView; -use Twig\Environment; -use Twig\Template; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class TwigRendererEngine extends AbstractRendererEngine -{ - /** - * @var Environment - */ - private $environment; - - /** - * @var Template - */ - private $template; - - public function __construct(array $defaultThemes, Environment $environment) - { - parent::__construct($defaultThemes); - $this->environment = $environment; - } - - /** - * {@inheritdoc} - */ - public function renderBlock(FormView $view, $resource, string $blockName, array $variables = []) - { - $cacheKey = $view->vars[self::CACHE_KEY_VAR]; - - $context = $this->environment->mergeGlobals($variables); - - ob_start(); - - // By contract,This method can only be called after getting the resource - // (which is passed to the method). Getting a resource for the first time - // (with an empty cache) is guaranteed to invoke loadResourcesFromTheme(), - // where the property $template is initialized. - - // We do not call renderBlock here to avoid too many nested level calls - // (XDebug limits the level to 100 by default) - $this->template->displayBlock($blockName, $context, $this->resources[$cacheKey]); - - return ob_get_clean(); - } - - /** - * Loads the cache with the resource for a given block name. - * - * This implementation eagerly loads all blocks of the themes assigned to the given view - * and all of its ancestors views. This is necessary, because Twig receives the - * list of blocks later. At that point, all blocks must already be loaded, for the - * case that the function "block()" is used in the Twig template. - * - * @see getResourceForBlock() - * - * @return bool - */ - protected function loadResourceForBlockName(string $cacheKey, FormView $view, string $blockName) - { - // The caller guarantees that $this->resources[$cacheKey][$block] is - // not set, but it doesn't have to check whether $this->resources[$cacheKey] - // is set. If $this->resources[$cacheKey] is set, all themes for this - // $cacheKey are already loaded (due to the eager population, see doc comment). - if (isset($this->resources[$cacheKey])) { - // As said in the previous, the caller guarantees that - // $this->resources[$cacheKey][$block] is not set. Since the themes are - // already loaded, it can only be a non-existing block. - $this->resources[$cacheKey][$blockName] = false; - - return false; - } - - // Recursively try to find the block in the themes assigned to $view, - // then of its parent view, then of the parent view of the parent and so on. - // When the root view is reached in this recursion, also the default - // themes are taken into account. - - // Check each theme whether it contains the searched block - if (isset($this->themes[$cacheKey])) { - for ($i = \count($this->themes[$cacheKey]) - 1; $i >= 0; --$i) { - $this->loadResourcesFromTheme($cacheKey, $this->themes[$cacheKey][$i]); - // CONTINUE LOADING (see doc comment) - } - } - - // Check the default themes once we reach the root view without success - if (!$view->parent) { - if (!isset($this->useDefaultThemes[$cacheKey]) || $this->useDefaultThemes[$cacheKey]) { - for ($i = \count($this->defaultThemes) - 1; $i >= 0; --$i) { - $this->loadResourcesFromTheme($cacheKey, $this->defaultThemes[$i]); - // CONTINUE LOADING (see doc comment) - } - } - } - - // Proceed with the themes of the parent view - if ($view->parent) { - $parentCacheKey = $view->parent->vars[self::CACHE_KEY_VAR]; - - if (!isset($this->resources[$parentCacheKey])) { - $this->loadResourceForBlockName($parentCacheKey, $view->parent, $blockName); - } - - // EAGER CACHE POPULATION (see doc comment) - foreach ($this->resources[$parentCacheKey] as $nestedBlockName => $resource) { - if (!isset($this->resources[$cacheKey][$nestedBlockName])) { - $this->resources[$cacheKey][$nestedBlockName] = $resource; - } - } - } - - // Even though we loaded the themes, it can happen that none of them - // contains the searched block - if (!isset($this->resources[$cacheKey][$blockName])) { - // Cache that we didn't find anything to speed up further accesses - $this->resources[$cacheKey][$blockName] = false; - } - - return false !== $this->resources[$cacheKey][$blockName]; - } - - /** - * Loads the resources for all blocks in a theme. - * - * @param mixed $theme The theme to load the block from. This parameter - * is passed by reference, because it might be necessary - * to initialize the theme first. Any changes made to - * this variable will be kept and be available upon - * further calls to this method using the same theme. - */ - protected function loadResourcesFromTheme(string $cacheKey, &$theme) - { - if (!$theme instanceof Template) { - /* @var Template $theme */ - $theme = $this->environment->load($theme)->unwrap(); - } - - if (null === $this->template) { - // Store the first Template instance that we find so that - // we can call displayBlock() later on. It doesn't matter *which* - // template we use for that, since we pass the used blocks manually - // anyway. - $this->template = $theme; - } - - // Use a separate variable for the inheritance traversal, because - // theme is a reference and we don't want to change it. - $currentTheme = $theme; - - $context = $this->environment->mergeGlobals([]); - - // The do loop takes care of template inheritance. - // Add blocks from all templates in the inheritance tree, but avoid - // overriding blocks already set. - do { - foreach ($currentTheme->getBlocks() as $block => $blockData) { - if (!isset($this->resources[$cacheKey][$block])) { - // The resource given back is the key to the bucket that - // contains this block. - $this->resources[$cacheKey][$block] = $blockData; - } - } - } while (false !== $currentTheme = $currentTheme->getParent($context)); - } -} diff --git a/lib/symfony/twig-bridge/LICENSE b/lib/symfony/twig-bridge/LICENSE deleted file mode 100644 index 88bf75bb4..000000000 --- a/lib/symfony/twig-bridge/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-2022 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -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/lib/symfony/twig-bridge/Mime/BodyRenderer.php b/lib/symfony/twig-bridge/Mime/BodyRenderer.php deleted file mode 100644 index 47901d310..000000000 --- a/lib/symfony/twig-bridge/Mime/BodyRenderer.php +++ /dev/null @@ -1,105 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Mime; - -use League\HTMLToMarkdown\HtmlConverter; -use Symfony\Component\Mime\BodyRendererInterface; -use Symfony\Component\Mime\Exception\InvalidArgumentException; -use Symfony\Component\Mime\Message; -use Twig\Environment; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -final class BodyRenderer implements BodyRendererInterface -{ - private $twig; - private $context; - private $converter; - - public function __construct(Environment $twig, array $context = []) - { - $this->twig = $twig; - $this->context = $context; - if (class_exists(HtmlConverter::class)) { - $this->converter = new HtmlConverter([ - 'hard_break' => true, - 'strip_tags' => true, - 'remove_nodes' => 'head style', - ]); - } - } - - public function render(Message $message): void - { - if (!$message instanceof TemplatedEmail) { - return; - } - - $messageContext = $message->getContext(); - - $previousRenderingKey = $messageContext[__CLASS__] ?? null; - unset($messageContext[__CLASS__]); - $currentRenderingKey = $this->getFingerPrint($message); - if ($previousRenderingKey === $currentRenderingKey) { - return; - } - - if (isset($messageContext['email'])) { - throw new InvalidArgumentException(sprintf('A "%s" context cannot have an "email" entry as this is a reserved variable.', get_debug_type($message))); - } - - $vars = array_merge($this->context, $messageContext, [ - 'email' => new WrappedTemplatedEmail($this->twig, $message), - ]); - - if ($template = $message->getTextTemplate()) { - $message->text($this->twig->render($template, $vars)); - } - - if ($template = $message->getHtmlTemplate()) { - $message->html($this->twig->render($template, $vars)); - } - - // if text body is empty, compute one from the HTML body - if (!$message->getTextBody() && null !== $html = $message->getHtmlBody()) { - $message->text($this->convertHtmlToText(\is_resource($html) ? stream_get_contents($html) : $html)); - } - $message->context($message->getContext() + [__CLASS__ => $currentRenderingKey]); - } - - private function getFingerPrint(TemplatedEmail $message): string - { - $messageContext = $message->getContext(); - unset($messageContext[__CLASS__]); - - $payload = [$messageContext, $message->getTextTemplate(), $message->getHtmlTemplate()]; - try { - $serialized = serialize($payload); - } catch (\Exception $e) { - // Serialization of 'Closure' is not allowed - // Happens when context contain a closure, in that case, we assume that context always change. - $serialized = random_bytes(8); - } - - return md5($serialized); - } - - private function convertHtmlToText(string $html): string - { - if (null !== $this->converter) { - return $this->converter->convert($html); - } - - return strip_tags(preg_replace('{<(head|style)\b.*?</\1>}is', '', $html)); - } -} diff --git a/lib/symfony/twig-bridge/Mime/NotificationEmail.php b/lib/symfony/twig-bridge/Mime/NotificationEmail.php deleted file mode 100644 index 3bdcd71dd..000000000 --- a/lib/symfony/twig-bridge/Mime/NotificationEmail.php +++ /dev/null @@ -1,250 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Mime; - -use Symfony\Component\ErrorHandler\Exception\FlattenException; -use Symfony\Component\Mime\Header\Headers; -use Symfony\Component\Mime\Part\AbstractPart; -use Twig\Extra\CssInliner\CssInlinerExtension; -use Twig\Extra\Inky\InkyExtension; -use Twig\Extra\Markdown\MarkdownExtension; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -class NotificationEmail extends TemplatedEmail -{ - public const IMPORTANCE_URGENT = 'urgent'; - public const IMPORTANCE_HIGH = 'high'; - public const IMPORTANCE_MEDIUM = 'medium'; - public const IMPORTANCE_LOW = 'low'; - - private $theme = 'default'; - private $context = [ - 'importance' => self::IMPORTANCE_LOW, - 'content' => '', - 'exception' => false, - 'action_text' => null, - 'action_url' => null, - 'markdown' => false, - 'raw' => false, - 'footer_text' => 'Notification e-mail sent by Symfony', - ]; - - public function __construct(Headers $headers = null, AbstractPart $body = null) - { - $missingPackages = []; - if (!class_exists(CssInlinerExtension::class)) { - $missingPackages['twig/cssinliner-extra'] = 'CSS Inliner'; - } - - if (!class_exists(InkyExtension::class)) { - $missingPackages['twig/inky-extra'] = 'Inky'; - } - - if ($missingPackages) { - throw new \LogicException(sprintf('You cannot use "%s" if the "%s" Twig extension%s not available; try running "%s".', static::class, implode('" and "', $missingPackages), \count($missingPackages) > 1 ? 's are' : ' is', 'composer require '.implode(' ', array_keys($missingPackages)))); - } - - parent::__construct($headers, $body); - } - - /** - * Creates a NotificationEmail instance that is appropriate to send to normal (non-admin) users. - */ - public static function asPublicEmail(Headers $headers = null, AbstractPart $body = null): self - { - $email = new static($headers, $body); - $email->markAsPublic(); - - return $email; - } - - /** - * @return $this - */ - public function markAsPublic(): self - { - $this->context['importance'] = null; - $this->context['footer_text'] = null; - - return $this; - } - - /** - * @return $this - */ - public function markdown(string $content) - { - if (!class_exists(MarkdownExtension::class)) { - throw new \LogicException(sprintf('You cannot use "%s" if the Markdown Twig extension is not available; try running "composer require twig/markdown-extra".', __METHOD__)); - } - - $this->context['markdown'] = true; - - return $this->content($content); - } - - /** - * @return $this - */ - public function content(string $content, bool $raw = false) - { - $this->context['content'] = $content; - $this->context['raw'] = $raw; - - return $this; - } - - /** - * @return $this - */ - public function action(string $text, string $url) - { - $this->context['action_text'] = $text; - $this->context['action_url'] = $url; - - return $this; - } - - /** - * @return $this - */ - public function importance(string $importance) - { - $this->context['importance'] = $importance; - - return $this; - } - - /** - * @param \Throwable|FlattenException $exception - * - * @return $this - */ - public function exception($exception) - { - if (!$exception instanceof \Throwable && !$exception instanceof FlattenException) { - throw new \LogicException(sprintf('"%s" accepts "%s" or "%s" instances.', __METHOD__, \Throwable::class, FlattenException::class)); - } - - $exceptionAsString = $this->getExceptionAsString($exception); - - $this->context['exception'] = true; - $this->attach($exceptionAsString, 'exception.txt', 'text/plain'); - $this->importance(self::IMPORTANCE_URGENT); - - if (!$this->getSubject()) { - $this->subject($exception->getMessage()); - } - - return $this; - } - - /** - * @return $this - */ - public function theme(string $theme) - { - $this->theme = $theme; - - return $this; - } - - public function getTextTemplate(): ?string - { - if ($template = parent::getTextTemplate()) { - return $template; - } - - return '@email/'.$this->theme.'/notification/body.txt.twig'; - } - - public function getHtmlTemplate(): ?string - { - if ($template = parent::getHtmlTemplate()) { - return $template; - } - - return '@email/'.$this->theme.'/notification/body.html.twig'; - } - - public function getContext(): array - { - return array_merge($this->context, parent::getContext()); - } - - public function getPreparedHeaders(): Headers - { - $headers = parent::getPreparedHeaders(); - - $importance = $this->context['importance'] ?? self::IMPORTANCE_LOW; - $this->priority($this->determinePriority($importance)); - if ($this->context['importance']) { - $headers->setHeaderBody('Text', 'Subject', sprintf('[%s] %s', strtoupper($importance), $this->getSubject())); - } - - return $headers; - } - - private function determinePriority(string $importance): int - { - switch ($importance) { - case self::IMPORTANCE_URGENT: - return self::PRIORITY_HIGHEST; - case self::IMPORTANCE_HIGH: - return self::PRIORITY_HIGH; - case self::IMPORTANCE_MEDIUM: - return self::PRIORITY_NORMAL; - case self::IMPORTANCE_LOW: - default: - return self::PRIORITY_LOW; - } - } - - private function getExceptionAsString($exception): string - { - if (class_exists(FlattenException::class)) { - $exception = $exception instanceof FlattenException ? $exception : FlattenException::createFromThrowable($exception); - - return $exception->getAsString(); - } - - $message = \get_class($exception); - if ('' !== $exception->getMessage()) { - $message .= ': '.$exception->getMessage(); - } - - $message .= ' in '.$exception->getFile().':'.$exception->getLine()."\n"; - $message .= "Stack trace:\n".$exception->getTraceAsString()."\n\n"; - - return rtrim($message); - } - - /** - * @internal - */ - public function __serialize(): array - { - return [$this->context, parent::__serialize()]; - } - - /** - * @internal - */ - public function __unserialize(array $data): void - { - [$this->context, $parentData] = $data; - - parent::__unserialize($parentData); - } -} diff --git a/lib/symfony/twig-bridge/Mime/TemplatedEmail.php b/lib/symfony/twig-bridge/Mime/TemplatedEmail.php deleted file mode 100644 index 6dd9202de..000000000 --- a/lib/symfony/twig-bridge/Mime/TemplatedEmail.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Mime; - -use Symfony\Component\Mime\Email; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -class TemplatedEmail extends Email -{ - private $htmlTemplate; - private $textTemplate; - private $context = []; - - /** - * @return $this - */ - public function textTemplate(?string $template) - { - $this->textTemplate = $template; - - return $this; - } - - /** - * @return $this - */ - public function htmlTemplate(?string $template) - { - $this->htmlTemplate = $template; - - return $this; - } - - public function getTextTemplate(): ?string - { - return $this->textTemplate; - } - - public function getHtmlTemplate(): ?string - { - return $this->htmlTemplate; - } - - /** - * @return $this - */ - public function context(array $context) - { - $this->context = $context; - - return $this; - } - - public function getContext(): array - { - return $this->context; - } - - /** - * @internal - */ - public function __serialize(): array - { - return [$this->htmlTemplate, $this->textTemplate, $this->context, parent::__serialize()]; - } - - /** - * @internal - */ - public function __unserialize(array $data): void - { - [$this->htmlTemplate, $this->textTemplate, $this->context, $parentData] = $data; - - parent::__unserialize($parentData); - } -} diff --git a/lib/symfony/twig-bridge/Mime/WrappedTemplatedEmail.php b/lib/symfony/twig-bridge/Mime/WrappedTemplatedEmail.php deleted file mode 100644 index f1726914b..000000000 --- a/lib/symfony/twig-bridge/Mime/WrappedTemplatedEmail.php +++ /dev/null @@ -1,194 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Mime; - -use Symfony\Component\Mime\Address; -use Twig\Environment; - -/** - * @internal - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class WrappedTemplatedEmail -{ - private $twig; - private $message; - - public function __construct(Environment $twig, TemplatedEmail $message) - { - $this->twig = $twig; - $this->message = $message; - } - - public function toName(): string - { - return $this->message->getTo()[0]->getName(); - } - - public function image(string $image, string $contentType = null): string - { - $file = $this->twig->getLoader()->getSourceContext($image); - if ($path = $file->getPath()) { - $this->message->embedFromPath($path, $image, $contentType); - } else { - $this->message->embed($file->getCode(), $image, $contentType); - } - - return 'cid:'.$image; - } - - public function attach(string $file, string $name = null, string $contentType = null): void - { - $file = $this->twig->getLoader()->getSourceContext($file); - if ($path = $file->getPath()) { - $this->message->attachFromPath($path, $name, $contentType); - } else { - $this->message->attach($file->getCode(), $name, $contentType); - } - } - - /** - * @return $this - */ - public function setSubject(string $subject): self - { - $this->message->subject($subject); - - return $this; - } - - public function getSubject(): ?string - { - return $this->message->getSubject(); - } - - /** - * @return $this - */ - public function setReturnPath(string $address): self - { - $this->message->returnPath($address); - - return $this; - } - - public function getReturnPath(): string - { - return $this->message->getReturnPath(); - } - - /** - * @return $this - */ - public function addFrom(string $address, string $name = ''): self - { - $this->message->addFrom(new Address($address, $name)); - - return $this; - } - - /** - * @return Address[] - */ - public function getFrom(): array - { - return $this->message->getFrom(); - } - - /** - * @return $this - */ - public function addReplyTo(string $address): self - { - $this->message->addReplyTo($address); - - return $this; - } - - /** - * @return Address[] - */ - public function getReplyTo(): array - { - return $this->message->getReplyTo(); - } - - /** - * @return $this - */ - public function addTo(string $address, string $name = ''): self - { - $this->message->addTo(new Address($address, $name)); - - return $this; - } - - /** - * @return Address[] - */ - public function getTo(): array - { - return $this->message->getTo(); - } - - /** - * @return $this - */ - public function addCc(string $address, string $name = ''): self - { - $this->message->addCc(new Address($address, $name)); - - return $this; - } - - /** - * @return Address[] - */ - public function getCc(): array - { - return $this->message->getCc(); - } - - /** - * @return $this - */ - public function addBcc(string $address, string $name = ''): self - { - $this->message->addBcc(new Address($address, $name)); - - return $this; - } - - /** - * @return Address[] - */ - public function getBcc(): array - { - return $this->message->getBcc(); - } - - /** - * @return $this - */ - public function setPriority(int $priority): self - { - $this->message->priority($priority); - - return $this; - } - - public function getPriority(): int - { - return $this->message->getPriority(); - } -} diff --git a/lib/symfony/twig-bridge/Node/DumpNode.php b/lib/symfony/twig-bridge/Node/DumpNode.php deleted file mode 100644 index 68c00556f..000000000 --- a/lib/symfony/twig-bridge/Node/DumpNode.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Node; - -use Twig\Compiler; -use Twig\Node\Node; - -/** - * @author Julien Galenski <julien.galenski@gmail.com> - */ -final class DumpNode extends Node -{ - private $varPrefix; - - public function __construct(string $varPrefix, ?Node $values, int $lineno, string $tag = null) - { - $nodes = []; - if (null !== $values) { - $nodes['values'] = $values; - } - - parent::__construct($nodes, [], $lineno, $tag); - $this->varPrefix = $varPrefix; - } - - public function compile(Compiler $compiler): void - { - $compiler - ->write("if (\$this->env->isDebug()) {\n") - ->indent(); - - if (!$this->hasNode('values')) { - // remove embedded templates (macros) from the context - $compiler - ->write(sprintf('$%svars = [];'."\n", $this->varPrefix)) - ->write(sprintf('foreach ($context as $%1$skey => $%1$sval) {'."\n", $this->varPrefix)) - ->indent() - ->write(sprintf('if (!$%sval instanceof \Twig\Template) {'."\n", $this->varPrefix)) - ->indent() - ->write(sprintf('$%1$svars[$%1$skey] = $%1$sval;'."\n", $this->varPrefix)) - ->outdent() - ->write("}\n") - ->outdent() - ->write("}\n") - ->addDebugInfo($this) - ->write(sprintf('\Symfony\Component\VarDumper\VarDumper::dump($%svars);'."\n", $this->varPrefix)); - } elseif (($values = $this->getNode('values')) && 1 === $values->count()) { - $compiler - ->addDebugInfo($this) - ->write('\Symfony\Component\VarDumper\VarDumper::dump(') - ->subcompile($values->getNode(0)) - ->raw(");\n"); - } else { - $compiler - ->addDebugInfo($this) - ->write('\Symfony\Component\VarDumper\VarDumper::dump(['."\n") - ->indent(); - foreach ($values as $node) { - $compiler->write(''); - if ($node->hasAttribute('name')) { - $compiler - ->string($node->getAttribute('name')) - ->raw(' => '); - } - $compiler - ->subcompile($node) - ->raw(",\n"); - } - $compiler - ->outdent() - ->write("]);\n"); - } - - $compiler - ->outdent() - ->write("}\n"); - } -} diff --git a/lib/symfony/twig-bridge/Node/FormThemeNode.php b/lib/symfony/twig-bridge/Node/FormThemeNode.php deleted file mode 100644 index e37311267..000000000 --- a/lib/symfony/twig-bridge/Node/FormThemeNode.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Node; - -use Symfony\Component\Form\FormRenderer; -use Twig\Compiler; -use Twig\Node\Node; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -final class FormThemeNode extends Node -{ - public function __construct(Node $form, Node $resources, int $lineno, string $tag = null, bool $only = false) - { - parent::__construct(['form' => $form, 'resources' => $resources], ['only' => $only], $lineno, $tag); - } - - public function compile(Compiler $compiler): void - { - $compiler - ->addDebugInfo($this) - ->write('$this->env->getRuntime(') - ->string(FormRenderer::class) - ->raw(')->setTheme(') - ->subcompile($this->getNode('form')) - ->raw(', ') - ->subcompile($this->getNode('resources')) - ->raw(', ') - ->raw(false === $this->getAttribute('only') ? 'true' : 'false') - ->raw(");\n"); - } -} diff --git a/lib/symfony/twig-bridge/Node/RenderBlockNode.php b/lib/symfony/twig-bridge/Node/RenderBlockNode.php deleted file mode 100644 index 4d4cf6136..000000000 --- a/lib/symfony/twig-bridge/Node/RenderBlockNode.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Node; - -use Twig\Compiler; -use Twig\Node\Expression\FunctionExpression; - -/** - * Compiles a call to {@link \Symfony\Component\Form\FormRendererInterface::renderBlock()}. - * - * The function name is used as block name. For example, if the function name - * is "foo", the block "foo" will be rendered. - * - * @author Bernhard Schussek <bschussek@gmail.com> - */ -final class RenderBlockNode extends FunctionExpression -{ - public function compile(Compiler $compiler): void - { - $compiler->addDebugInfo($this); - $arguments = iterator_to_array($this->getNode('arguments')); - $compiler->write('$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->renderBlock('); - - if (isset($arguments[0])) { - $compiler->subcompile($arguments[0]); - $compiler->raw(', \''.$this->getAttribute('name').'\''); - - if (isset($arguments[1])) { - $compiler->raw(', '); - $compiler->subcompile($arguments[1]); - } - } - - $compiler->raw(')'); - } -} diff --git a/lib/symfony/twig-bridge/Node/SearchAndRenderBlockNode.php b/lib/symfony/twig-bridge/Node/SearchAndRenderBlockNode.php deleted file mode 100644 index 9967639d1..000000000 --- a/lib/symfony/twig-bridge/Node/SearchAndRenderBlockNode.php +++ /dev/null @@ -1,110 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Node; - -use Twig\Compiler; -use Twig\Node\Expression\ArrayExpression; -use Twig\Node\Expression\ConstantExpression; -use Twig\Node\Expression\FunctionExpression; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -final class SearchAndRenderBlockNode extends FunctionExpression -{ - public function compile(Compiler $compiler): void - { - $compiler->addDebugInfo($this); - $compiler->raw('$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock('); - - preg_match('/_([^_]+)$/', $this->getAttribute('name'), $matches); - - $arguments = iterator_to_array($this->getNode('arguments')); - $blockNameSuffix = $matches[1]; - - if (isset($arguments[0])) { - $compiler->subcompile($arguments[0]); - $compiler->raw(', \''.$blockNameSuffix.'\''); - - if (isset($arguments[1])) { - if ('label' === $blockNameSuffix) { - // The "label" function expects the label in the second and - // the variables in the third argument - $label = $arguments[1]; - $variables = $arguments[2] ?? null; - $lineno = $label->getTemplateLine(); - - if ($label instanceof ConstantExpression) { - // If the label argument is given as a constant, we can either - // strip it away if it is empty, or integrate it into the array - // of variables at compile time. - $labelIsExpression = false; - - // Only insert the label into the array if it is not empty - if (!twig_test_empty($label->getAttribute('value'))) { - $originalVariables = $variables; - $variables = new ArrayExpression([], $lineno); - $labelKey = new ConstantExpression('label', $lineno); - - if (null !== $originalVariables) { - foreach ($originalVariables->getKeyValuePairs() as $pair) { - // Don't copy the original label attribute over if it exists - if ((string) $labelKey !== (string) $pair['key']) { - $variables->addElement($pair['value'], $pair['key']); - } - } - } - - // Insert the label argument into the array - $variables->addElement($label, $labelKey); - } - } else { - // The label argument is not a constant, but some kind of - // expression. This expression needs to be evaluated at runtime. - // Depending on the result (whether it is null or not), the - // label in the arguments should take precedence over the label - // in the attributes or not. - $labelIsExpression = true; - } - } else { - // All other functions than "label" expect the variables - // in the second argument - $label = null; - $variables = $arguments[1]; - $labelIsExpression = false; - } - - if (null !== $variables || $labelIsExpression) { - $compiler->raw(', '); - - if (null !== $variables) { - $compiler->subcompile($variables); - } - - if ($labelIsExpression) { - if (null !== $variables) { - $compiler->raw(' + '); - } - - // Check at runtime whether the label is empty. - // If not, add it to the array at runtime. - $compiler->raw('(twig_test_empty($_label_ = '); - $compiler->subcompile($label); - $compiler->raw(') ? [] : ["label" => $_label_])'); - } - } - } - } - - $compiler->raw(')'); - } -} diff --git a/lib/symfony/twig-bridge/Node/StopwatchNode.php b/lib/symfony/twig-bridge/Node/StopwatchNode.php deleted file mode 100644 index cfa4d8a19..000000000 --- a/lib/symfony/twig-bridge/Node/StopwatchNode.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Node; - -use Twig\Compiler; -use Twig\Node\Expression\AssignNameExpression; -use Twig\Node\Node; - -/** - * Represents a stopwatch node. - * - * @author Wouter J <wouter@wouterj.nl> - */ -final class StopwatchNode extends Node -{ - public function __construct(Node $name, Node $body, AssignNameExpression $var, int $lineno = 0, string $tag = null) - { - parent::__construct(['body' => $body, 'name' => $name, 'var' => $var], [], $lineno, $tag); - } - - public function compile(Compiler $compiler): void - { - $compiler - ->addDebugInfo($this) - ->write('') - ->subcompile($this->getNode('var')) - ->raw(' = ') - ->subcompile($this->getNode('name')) - ->write(";\n") - ->write("\$this->env->getExtension('Symfony\Bridge\Twig\Extension\StopwatchExtension')->getStopwatch()->start(") - ->subcompile($this->getNode('var')) - ->raw(", 'template');\n") - ->subcompile($this->getNode('body')) - ->write("\$this->env->getExtension('Symfony\Bridge\Twig\Extension\StopwatchExtension')->getStopwatch()->stop(") - ->subcompile($this->getNode('var')) - ->raw(");\n") - ; - } -} diff --git a/lib/symfony/twig-bridge/Node/TransDefaultDomainNode.php b/lib/symfony/twig-bridge/Node/TransDefaultDomainNode.php deleted file mode 100644 index df29f0a19..000000000 --- a/lib/symfony/twig-bridge/Node/TransDefaultDomainNode.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Node; - -use Twig\Compiler; -use Twig\Node\Expression\AbstractExpression; -use Twig\Node\Node; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -final class TransDefaultDomainNode extends Node -{ - public function __construct(AbstractExpression $expr, int $lineno = 0, string $tag = null) - { - parent::__construct(['expr' => $expr], [], $lineno, $tag); - } - - public function compile(Compiler $compiler): void - { - // noop as this node is just a marker for TranslationDefaultDomainNodeVisitor - } -} diff --git a/lib/symfony/twig-bridge/Node/TransNode.php b/lib/symfony/twig-bridge/Node/TransNode.php deleted file mode 100644 index 8a126ba56..000000000 --- a/lib/symfony/twig-bridge/Node/TransNode.php +++ /dev/null @@ -1,130 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Node; - -use Twig\Compiler; -use Twig\Node\Expression\AbstractExpression; -use Twig\Node\Expression\ArrayExpression; -use Twig\Node\Expression\ConstantExpression; -use Twig\Node\Expression\NameExpression; -use Twig\Node\Node; -use Twig\Node\TextNode; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -final class TransNode extends Node -{ - public function __construct(Node $body, Node $domain = null, AbstractExpression $count = null, AbstractExpression $vars = null, AbstractExpression $locale = null, int $lineno = 0, string $tag = null) - { - $nodes = ['body' => $body]; - if (null !== $domain) { - $nodes['domain'] = $domain; - } - if (null !== $count) { - $nodes['count'] = $count; - } - if (null !== $vars) { - $nodes['vars'] = $vars; - } - if (null !== $locale) { - $nodes['locale'] = $locale; - } - - parent::__construct($nodes, [], $lineno, $tag); - } - - public function compile(Compiler $compiler): void - { - $compiler->addDebugInfo($this); - - $defaults = new ArrayExpression([], -1); - if ($this->hasNode('vars') && ($vars = $this->getNode('vars')) instanceof ArrayExpression) { - $defaults = $this->getNode('vars'); - $vars = null; - } - [$msg, $defaults] = $this->compileString($this->getNode('body'), $defaults, (bool) $vars); - - $compiler - ->write('echo $this->env->getExtension(\'Symfony\Bridge\Twig\Extension\TranslationExtension\')->trans(') - ->subcompile($msg) - ; - - $compiler->raw(', '); - - if (null !== $vars) { - $compiler - ->raw('array_merge(') - ->subcompile($defaults) - ->raw(', ') - ->subcompile($this->getNode('vars')) - ->raw(')') - ; - } else { - $compiler->subcompile($defaults); - } - - $compiler->raw(', '); - - if (!$this->hasNode('domain')) { - $compiler->repr('messages'); - } else { - $compiler->subcompile($this->getNode('domain')); - } - - if ($this->hasNode('locale')) { - $compiler - ->raw(', ') - ->subcompile($this->getNode('locale')) - ; - } elseif ($this->hasNode('count')) { - $compiler->raw(', null'); - } - - if ($this->hasNode('count')) { - $compiler - ->raw(', ') - ->subcompile($this->getNode('count')) - ; - } - - $compiler->raw(");\n"); - } - - private function compileString(Node $body, ArrayExpression $vars, bool $ignoreStrictCheck = false): array - { - if ($body instanceof ConstantExpression) { - $msg = $body->getAttribute('value'); - } elseif ($body instanceof TextNode) { - $msg = $body->getAttribute('data'); - } else { - return [$body, $vars]; - } - - preg_match_all('/(?<!%)%([^%]+)%/', $msg, $matches); - - foreach ($matches[1] as $var) { - $key = new ConstantExpression('%'.$var.'%', $body->getTemplateLine()); - if (!$vars->hasElement($key)) { - if ('count' === $var && $this->hasNode('count')) { - $vars->addElement($this->getNode('count'), $key); - } else { - $varExpr = new NameExpression($var, $body->getTemplateLine()); - $varExpr->setAttribute('ignore_strict_check', $ignoreStrictCheck); - $vars->addElement($varExpr, $key); - } - } - } - - return [new ConstantExpression(str_replace('%%', '%', trim($msg)), $body->getTemplateLine()), $vars]; - } -} diff --git a/lib/symfony/twig-bridge/NodeVisitor/Scope.php b/lib/symfony/twig-bridge/NodeVisitor/Scope.php deleted file mode 100644 index 765b4b69b..000000000 --- a/lib/symfony/twig-bridge/NodeVisitor/Scope.php +++ /dev/null @@ -1,103 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\NodeVisitor; - -/** - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - */ -class Scope -{ - private $parent; - private $data = []; - private $left = false; - - public function __construct(self $parent = null) - { - $this->parent = $parent; - } - - /** - * Opens a new child scope. - * - * @return self - */ - public function enter() - { - return new self($this); - } - - /** - * Closes current scope and returns parent one. - * - * @return self|null - */ - public function leave() - { - $this->left = true; - - return $this->parent; - } - - /** - * Stores data into current scope. - * - * @return $this - * - * @throws \LogicException - */ - public function set(string $key, $value) - { - if ($this->left) { - throw new \LogicException('Left scope is not mutable.'); - } - - $this->data[$key] = $value; - - return $this; - } - - /** - * Tests if a data is visible from current scope. - * - * @return bool - */ - public function has(string $key) - { - if (\array_key_exists($key, $this->data)) { - return true; - } - - if (null === $this->parent) { - return false; - } - - return $this->parent->has($key); - } - - /** - * Returns data visible from current scope. - * - * @return mixed - */ - public function get(string $key, $default = null) - { - if (\array_key_exists($key, $this->data)) { - return $this->data[$key]; - } - - if (null === $this->parent) { - return $default; - } - - return $this->parent->get($key, $default); - } -} diff --git a/lib/symfony/twig-bridge/NodeVisitor/TranslationDefaultDomainNodeVisitor.php b/lib/symfony/twig-bridge/NodeVisitor/TranslationDefaultDomainNodeVisitor.php deleted file mode 100644 index 213365ed9..000000000 --- a/lib/symfony/twig-bridge/NodeVisitor/TranslationDefaultDomainNodeVisitor.php +++ /dev/null @@ -1,128 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\NodeVisitor; - -use Symfony\Bridge\Twig\Node\TransDefaultDomainNode; -use Symfony\Bridge\Twig\Node\TransNode; -use Twig\Environment; -use Twig\Node\BlockNode; -use Twig\Node\Expression\ArrayExpression; -use Twig\Node\Expression\AssignNameExpression; -use Twig\Node\Expression\ConstantExpression; -use Twig\Node\Expression\FilterExpression; -use Twig\Node\Expression\NameExpression; -use Twig\Node\ModuleNode; -use Twig\Node\Node; -use Twig\Node\SetNode; -use Twig\NodeVisitor\AbstractNodeVisitor; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -final class TranslationDefaultDomainNodeVisitor extends AbstractNodeVisitor -{ - private $scope; - - public function __construct() - { - $this->scope = new Scope(); - } - - /** - * {@inheritdoc} - */ - protected function doEnterNode(Node $node, Environment $env): Node - { - if ($node instanceof BlockNode || $node instanceof ModuleNode) { - $this->scope = $this->scope->enter(); - } - - if ($node instanceof TransDefaultDomainNode) { - if ($node->getNode('expr') instanceof ConstantExpression) { - $this->scope->set('domain', $node->getNode('expr')); - - return $node; - } else { - $var = $this->getVarName(); - $name = new AssignNameExpression($var, $node->getTemplateLine()); - $this->scope->set('domain', new NameExpression($var, $node->getTemplateLine())); - - return new SetNode(false, new Node([$name]), new Node([$node->getNode('expr')]), $node->getTemplateLine()); - } - } - - if (!$this->scope->has('domain')) { - return $node; - } - - if ($node instanceof FilterExpression && 'trans' === $node->getNode('filter')->getAttribute('value')) { - $arguments = $node->getNode('arguments'); - if ($this->isNamedArguments($arguments)) { - if (!$arguments->hasNode('domain') && !$arguments->hasNode(1)) { - $arguments->setNode('domain', $this->scope->get('domain')); - } - } elseif (!$arguments->hasNode(1)) { - if (!$arguments->hasNode(0)) { - $arguments->setNode(0, new ArrayExpression([], $node->getTemplateLine())); - } - - $arguments->setNode(1, $this->scope->get('domain')); - } - } elseif ($node instanceof TransNode) { - if (!$node->hasNode('domain')) { - $node->setNode('domain', $this->scope->get('domain')); - } - } - - return $node; - } - - /** - * {@inheritdoc} - */ - protected function doLeaveNode(Node $node, Environment $env): ?Node - { - if ($node instanceof TransDefaultDomainNode) { - return null; - } - - if ($node instanceof BlockNode || $node instanceof ModuleNode) { - $this->scope = $this->scope->leave(); - } - - return $node; - } - - /** - * {@inheritdoc} - */ - public function getPriority(): int - { - return -10; - } - - private function isNamedArguments(Node $arguments): bool - { - foreach ($arguments as $name => $node) { - if (!\is_int($name)) { - return true; - } - } - - return false; - } - - private function getVarName(): string - { - return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false)); - } -} diff --git a/lib/symfony/twig-bridge/NodeVisitor/TranslationNodeVisitor.php b/lib/symfony/twig-bridge/NodeVisitor/TranslationNodeVisitor.php deleted file mode 100644 index d42245e2b..000000000 --- a/lib/symfony/twig-bridge/NodeVisitor/TranslationNodeVisitor.php +++ /dev/null @@ -1,187 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\NodeVisitor; - -use Symfony\Bridge\Twig\Node\TransNode; -use Twig\Environment; -use Twig\Node\Expression\Binary\ConcatBinary; -use Twig\Node\Expression\ConstantExpression; -use Twig\Node\Expression\FilterExpression; -use Twig\Node\Expression\FunctionExpression; -use Twig\Node\Node; -use Twig\NodeVisitor\AbstractNodeVisitor; - -/** - * TranslationNodeVisitor extracts translation messages. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class TranslationNodeVisitor extends AbstractNodeVisitor -{ - public const UNDEFINED_DOMAIN = '_undefined'; - - private $enabled = false; - private $messages = []; - - public function enable(): void - { - $this->enabled = true; - $this->messages = []; - } - - public function disable(): void - { - $this->enabled = false; - $this->messages = []; - } - - public function getMessages(): array - { - return $this->messages; - } - - /** - * {@inheritdoc} - */ - protected function doEnterNode(Node $node, Environment $env): Node - { - if (!$this->enabled) { - return $node; - } - - if ( - $node instanceof FilterExpression && - 'trans' === $node->getNode('filter')->getAttribute('value') && - $node->getNode('node') instanceof ConstantExpression - ) { - // extract constant nodes with a trans filter - $this->messages[] = [ - $node->getNode('node')->getAttribute('value'), - $this->getReadDomainFromArguments($node->getNode('arguments'), 1), - ]; - } elseif ( - $node instanceof FunctionExpression && - 't' === $node->getAttribute('name') - ) { - $nodeArguments = $node->getNode('arguments'); - - if ($nodeArguments->getIterator()->current() instanceof ConstantExpression) { - $this->messages[] = [ - $this->getReadMessageFromArguments($nodeArguments, 0), - $this->getReadDomainFromArguments($nodeArguments, 2), - ]; - } - } elseif ($node instanceof TransNode) { - // extract trans nodes - $this->messages[] = [ - $node->getNode('body')->getAttribute('data'), - $node->hasNode('domain') ? $this->getReadDomainFromNode($node->getNode('domain')) : null, - ]; - } elseif ( - $node instanceof FilterExpression && - 'trans' === $node->getNode('filter')->getAttribute('value') && - $node->getNode('node') instanceof ConcatBinary && - $message = $this->getConcatValueFromNode($node->getNode('node'), null) - ) { - $this->messages[] = [ - $message, - $this->getReadDomainFromArguments($node->getNode('arguments'), 1), - ]; - } - - return $node; - } - - /** - * {@inheritdoc} - */ - protected function doLeaveNode(Node $node, Environment $env): ?Node - { - return $node; - } - - /** - * {@inheritdoc} - */ - public function getPriority(): int - { - return 0; - } - - private function getReadMessageFromArguments(Node $arguments, int $index): ?string - { - if ($arguments->hasNode('message')) { - $argument = $arguments->getNode('message'); - } elseif ($arguments->hasNode($index)) { - $argument = $arguments->getNode($index); - } else { - return null; - } - - return $this->getReadMessageFromNode($argument); - } - - private function getReadMessageFromNode(Node $node): ?string - { - if ($node instanceof ConstantExpression) { - return $node->getAttribute('value'); - } - - return null; - } - - private function getReadDomainFromArguments(Node $arguments, int $index): ?string - { - if ($arguments->hasNode('domain')) { - $argument = $arguments->getNode('domain'); - } elseif ($arguments->hasNode($index)) { - $argument = $arguments->getNode($index); - } else { - return null; - } - - return $this->getReadDomainFromNode($argument); - } - - private function getReadDomainFromNode(Node $node): ?string - { - if ($node instanceof ConstantExpression) { - return $node->getAttribute('value'); - } - - return self::UNDEFINED_DOMAIN; - } - - private function getConcatValueFromNode(Node $node, ?string $value): ?string - { - if ($node instanceof ConcatBinary) { - foreach ($node as $nextNode) { - if ($nextNode instanceof ConcatBinary) { - $nextValue = $this->getConcatValueFromNode($nextNode, $value); - if (null === $nextValue) { - return null; - } - $value .= $nextValue; - } elseif ($nextNode instanceof ConstantExpression) { - $value .= $nextNode->getAttribute('value'); - } else { - // this is a node we cannot process (variable, or translation in translation) - return null; - } - } - } elseif ($node instanceof ConstantExpression) { - $value .= $node->getAttribute('value'); - } - - return $value; - } -} diff --git a/lib/symfony/twig-bridge/README.md b/lib/symfony/twig-bridge/README.md deleted file mode 100644 index 533d573db..000000000 --- a/lib/symfony/twig-bridge/README.md +++ /dev/null @@ -1,13 +0,0 @@ -Twig Bridge -=========== - -The Twig bridge provides integration for [Twig](https://twig.symfony.com/) with -various Symfony components. - -Resources ---------- - - * [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/lib/symfony/twig-bridge/Resources/views/Email/default/notification/body.html.twig b/lib/symfony/twig-bridge/Resources/views/Email/default/notification/body.html.twig deleted file mode 100644 index 902754686..000000000 --- a/lib/symfony/twig-bridge/Resources/views/Email/default/notification/body.html.twig +++ /dev/null @@ -1 +0,0 @@ -{% extends "@email/zurb_2/notification/body.html.twig" %} diff --git a/lib/symfony/twig-bridge/Resources/views/Email/default/notification/body.txt.twig b/lib/symfony/twig-bridge/Resources/views/Email/default/notification/body.txt.twig deleted file mode 100644 index 37671b1f2..000000000 --- a/lib/symfony/twig-bridge/Resources/views/Email/default/notification/body.txt.twig +++ /dev/null @@ -1 +0,0 @@ -{% extends "@email/zurb_2/notification/body.txt.twig" %} diff --git a/lib/symfony/twig-bridge/Resources/views/Email/zurb_2/main.css b/lib/symfony/twig-bridge/Resources/views/Email/zurb_2/main.css deleted file mode 100644 index b826813ec..000000000 --- a/lib/symfony/twig-bridge/Resources/views/Email/zurb_2/main.css +++ /dev/null @@ -1,1667 +0,0 @@ -/* - * Copyright (c) 2017 ZURB, inc. -- MIT License - * - * https://raw.githubusercontent.com/foundation/foundation-emails/v2.2.1/dist/foundation-emails.css - */ - -.wrapper { - width: 100%; -} - -#outlook a { - padding: 0; -} - -body { - width: 100% !important; - min-width: 100%; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; - margin: 0; - Margin: 0; - padding: 0; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; -} - -.ExternalClass { - width: 100%; -} - -.ExternalClass, -.ExternalClass p, -.ExternalClass span, -.ExternalClass font, -.ExternalClass td, -.ExternalClass div { - line-height: 100%; -} - -#backgroundTable { - margin: 0; - Margin: 0; - padding: 0; - width: 100% !important; - line-height: 100% !important; -} - -img { - outline: none; - text-decoration: none; - -ms-interpolation-mode: bicubic; - width: auto; - max-width: 100%; - clear: both; - display: block; -} - -center { - width: 100%; - min-width: 580px; -} - -a img { - border: none; -} - -p { - margin: 0 0 0 10px; - Margin: 0 0 0 10px; -} - -table { - border-spacing: 0; - border-collapse: collapse; -} - -td { - word-wrap: break-word; - -webkit-hyphens: auto; - -moz-hyphens: auto; - hyphens: auto; - border-collapse: collapse !important; -} - -table, -tr, -td { - padding: 0; - vertical-align: top; - text-align: left; -} - -@media only screen { - html { - min-height: 100%; - background: #f3f3f3; - } -} - -table.body { - background: #f3f3f3; - height: 100%; - width: 100%; -} - -table.container { - background: #fefefe; - width: 580px; - margin: 0 auto; - Margin: 0 auto; - text-align: inherit; -} - -table.row { - padding: 0; - width: 100%; - position: relative; -} - -table.spacer { - width: 100%; -} - -table.spacer td { - mso-line-height-rule: exactly; -} - -table.container table.row { - display: table; -} - -td.columns, -td.column, -th.columns, -th.column { - margin: 0 auto; - Margin: 0 auto; - padding-left: 16px; - padding-bottom: 16px; -} - -td.columns .column, -td.columns .columns, -td.column .column, -td.column .columns, -th.columns .column, -th.columns .columns, -th.column .column, -th.column .columns { - padding-left: 0 !important; - padding-right: 0 !important; -} - -td.columns .column center, -td.columns .columns center, -td.column .column center, -td.column .columns center, -th.columns .column center, -th.columns .columns center, -th.column .column center, -th.column .columns center { - min-width: none !important; -} - -td.columns.last, -td.column.last, -th.columns.last, -th.column.last { - padding-right: 16px; -} - -td.columns table:not(.button), -td.column table:not(.button), -th.columns table:not(.button), -th.column table:not(.button) { - width: 100%; -} - -td.large-1, -th.large-1 { - width: 32.33333px; - padding-left: 8px; - padding-right: 8px; -} - -td.large-1.first, -th.large-1.first { - padding-left: 16px; -} - -td.large-1.last, -th.large-1.last { - padding-right: 16px; -} - -.collapse>tbody>tr>td.large-1, -.collapse>tbody>tr>th.large-1 { - padding-right: 0; - padding-left: 0; - width: 48.33333px; -} - -.collapse td.large-1.first, -.collapse th.large-1.first, -.collapse td.large-1.last, -.collapse th.large-1.last { - width: 56.33333px; -} - -td.large-1 center, -th.large-1 center { - min-width: 0.33333px; -} - -.body .columns td.large-1, -.body .column td.large-1, -.body .columns th.large-1, -.body .column th.large-1 { - width: 8.33333%; -} - -td.large-2, -th.large-2 { - width: 80.66667px; - padding-left: 8px; - padding-right: 8px; -} - -td.large-2.first, -th.large-2.first { - padding-left: 16px; -} - -td.large-2.last, -th.large-2.last { - padding-right: 16px; -} - -.collapse>tbody>tr>td.large-2, -.collapse>tbody>tr>th.large-2 { - padding-right: 0; - padding-left: 0; - width: 96.66667px; -} - -.collapse td.large-2.first, -.collapse th.large-2.first, -.collapse td.large-2.last, -.collapse th.large-2.last { - width: 104.66667px; -} - -td.large-2 center, -th.large-2 center { - min-width: 48.66667px; -} - -.body .columns td.large-2, -.body .column td.large-2, -.body .columns th.large-2, -.body .column th.large-2 { - width: 16.66667%; -} - -td.large-3, -th.large-3 { - width: 129px; - padding-left: 8px; - padding-right: 8px; -} - -td.large-3.first, -th.large-3.first { - padding-left: 16px; -} - -td.large-3.last, -th.large-3.last { - padding-right: 16px; -} - -.collapse>tbody>tr>td.large-3, -.collapse>tbody>tr>th.large-3 { - padding-right: 0; - padding-left: 0; - width: 145px; -} - -.collapse td.large-3.first, -.collapse th.large-3.first, -.collapse td.large-3.last, -.collapse th.large-3.last { - width: 153px; -} - -td.large-3 center, -th.large-3 center { - min-width: 97px; -} - -.body .columns td.large-3, -.body .column td.large-3, -.body .columns th.large-3, -.body .column th.large-3 { - width: 25%; -} - -td.large-4, -th.large-4 { - width: 177.33333px; - padding-left: 8px; - padding-right: 8px; -} - -td.large-4.first, -th.large-4.first { - padding-left: 16px; -} - -td.large-4.last, -th.large-4.last { - padding-right: 16px; -} - -.collapse>tbody>tr>td.large-4, -.collapse>tbody>tr>th.large-4 { - padding-right: 0; - padding-left: 0; - width: 193.33333px; -} - -.collapse td.large-4.first, -.collapse th.large-4.first, -.collapse td.large-4.last, -.collapse th.large-4.last { - width: 201.33333px; -} - -td.large-4 center, -th.large-4 center { - min-width: 145.33333px; -} - -.body .columns td.large-4, -.body .column td.large-4, -.body .columns th.large-4, -.body .column th.large-4 { - width: 33.33333%; -} - -td.large-5, -th.large-5 { - width: 225.66667px; - padding-left: 8px; - padding-right: 8px; -} - -td.large-5.first, -th.large-5.first { - padding-left: 16px; -} - -td.large-5.last, -th.large-5.last { - padding-right: 16px; -} - -.collapse>tbody>tr>td.large-5, -.collapse>tbody>tr>th.large-5 { - padding-right: 0; - padding-left: 0; - width: 241.66667px; -} - -.collapse td.large-5.first, -.collapse th.large-5.first, -.collapse td.large-5.last, -.collapse th.large-5.last { - width: 249.66667px; -} - -td.large-5 center, -th.large-5 center { - min-width: 193.66667px; -} - -.body .columns td.large-5, -.body .column td.large-5, -.body .columns th.large-5, -.body .column th.large-5 { - width: 41.66667%; -} - -td.large-6, -th.large-6 { - width: 274px; - padding-left: 8px; - padding-right: 8px; -} - -td.large-6.first, -th.large-6.first { - padding-left: 16px; -} - -td.large-6.last, -th.large-6.last { - padding-right: 16px; -} - -.collapse>tbody>tr>td.large-6, -.collapse>tbody>tr>th.large-6 { - padding-right: 0; - padding-left: 0; - width: 290px; -} - -.collapse td.large-6.first, -.collapse th.large-6.first, -.collapse td.large-6.last, -.collapse th.large-6.last { - width: 298px; -} - -td.large-6 center, -th.large-6 center { - min-width: 242px; -} - -.body .columns td.large-6, -.body .column td.large-6, -.body .columns th.large-6, -.body .column th.large-6 { - width: 50%; -} - -td.large-7, -th.large-7 { - width: 322.33333px; - padding-left: 8px; - padding-right: 8px; -} - -td.large-7.first, -th.large-7.first { - padding-left: 16px; -} - -td.large-7.last, -th.large-7.last { - padding-right: 16px; -} - -.collapse>tbody>tr>td.large-7, -.collapse>tbody>tr>th.large-7 { - padding-right: 0; - padding-left: 0; - width: 338.33333px; -} - -.collapse td.large-7.first, -.collapse th.large-7.first, -.collapse td.large-7.last, -.collapse th.large-7.last { - width: 346.33333px; -} - -td.large-7 center, -th.large-7 center { - min-width: 290.33333px; -} - -.body .columns td.large-7, -.body .column td.large-7, -.body .columns th.large-7, -.body .column th.large-7 { - width: 58.33333%; -} - -td.large-8, -th.large-8 { - width: 370.66667px; - padding-left: 8px; - padding-right: 8px; -} - -td.large-8.first, -th.large-8.first { - padding-left: 16px; -} - -td.large-8.last, -th.large-8.last { - padding-right: 16px; -} - -.collapse>tbody>tr>td.large-8, -.collapse>tbody>tr>th.large-8 { - padding-right: 0; - padding-left: 0; - width: 386.66667px; -} - -.collapse td.large-8.first, -.collapse th.large-8.first, -.collapse td.large-8.last, -.collapse th.large-8.last { - width: 394.66667px; -} - -td.large-8 center, -th.large-8 center { - min-width: 338.66667px; -} - -.body .columns td.large-8, -.body .column td.large-8, -.body .columns th.large-8, -.body .column th.large-8 { - width: 66.66667%; -} - -td.large-9, -th.large-9 { - width: 419px; - padding-left: 8px; - padding-right: 8px; -} - -td.large-9.first, -th.large-9.first { - padding-left: 16px; -} - -td.large-9.last, -th.large-9.last { - padding-right: 16px; -} - -.collapse>tbody>tr>td.large-9, -.collapse>tbody>tr>th.large-9 { - padding-right: 0; - padding-left: 0; - width: 435px; -} - -.collapse td.large-9.first, -.collapse th.large-9.first, -.collapse td.large-9.last, -.collapse th.large-9.last { - width: 443px; -} - -td.large-9 center, -th.large-9 center { - min-width: 387px; -} - -.body .columns td.large-9, -.body .column td.large-9, -.body .columns th.large-9, -.body .column th.large-9 { - width: 75%; -} - -td.large-10, -th.large-10 { - width: 467.33333px; - padding-left: 8px; - padding-right: 8px; -} - -td.large-10.first, -th.large-10.first { - padding-left: 16px; -} - -td.large-10.last, -th.large-10.last { - padding-right: 16px; -} - -.collapse>tbody>tr>td.large-10, -.collapse>tbody>tr>th.large-10 { - padding-right: 0; - padding-left: 0; - width: 483.33333px; -} - -.collapse td.large-10.first, -.collapse th.large-10.first, -.collapse td.large-10.last, -.collapse th.large-10.last { - width: 491.33333px; -} - -td.large-10 center, -th.large-10 center { - min-width: 435.33333px; -} - -.body .columns td.large-10, -.body .column td.large-10, -.body .columns th.large-10, -.body .column th.large-10 { - width: 83.33333%; -} - -td.large-11, -th.large-11 { - width: 515.66667px; - padding-left: 8px; - padding-right: 8px; -} - -td.large-11.first, -th.large-11.first { - padding-left: 16px; -} - -td.large-11.last, -th.large-11.last { - padding-right: 16px; -} - -.collapse>tbody>tr>td.large-11, -.collapse>tbody>tr>th.large-11 { - padding-right: 0; - padding-left: 0; - width: 531.66667px; -} - -.collapse td.large-11.first, -.collapse th.large-11.first, -.collapse td.large-11.last, -.collapse th.large-11.last { - width: 539.66667px; -} - -td.large-11 center, -th.large-11 center { - min-width: 483.66667px; -} - -.body .columns td.large-11, -.body .column td.large-11, -.body .columns th.large-11, -.body .column th.large-11 { - width: 91.66667%; -} - -td.large-12, -th.large-12 { - width: 564px; - padding-left: 8px; - padding-right: 8px; -} - -td.large-12.first, -th.large-12.first { - padding-left: 16px; -} - -td.large-12.last, -th.large-12.last { - padding-right: 16px; -} - -.collapse>tbody>tr>td.large-12, -.collapse>tbody>tr>th.large-12 { - padding-right: 0; - padding-left: 0; - width: 580px; -} - -.collapse td.large-12.first, -.collapse th.large-12.first, -.collapse td.large-12.last, -.collapse th.large-12.last { - width: 588px; -} - -td.large-12 center, -th.large-12 center { - min-width: 532px; -} - -.body .columns td.large-12, -.body .column td.large-12, -.body .columns th.large-12, -.body .column th.large-12 { - width: 100%; -} - -td.large-offset-1, -td.large-offset-1.first, -td.large-offset-1.last, -th.large-offset-1, -th.large-offset-1.first, -th.large-offset-1.last { - padding-left: 64.33333px; -} - -td.large-offset-2, -td.large-offset-2.first, -td.large-offset-2.last, -th.large-offset-2, -th.large-offset-2.first, -th.large-offset-2.last { - padding-left: 112.66667px; -} - -td.large-offset-3, -td.large-offset-3.first, -td.large-offset-3.last, -th.large-offset-3, -th.large-offset-3.first, -th.large-offset-3.last { - padding-left: 161px; -} - -td.large-offset-4, -td.large-offset-4.first, -td.large-offset-4.last, -th.large-offset-4, -th.large-offset-4.first, -th.large-offset-4.last { - padding-left: 209.33333px; -} - -td.large-offset-5, -td.large-offset-5.first, -td.large-offset-5.last, -th.large-offset-5, -th.large-offset-5.first, -th.large-offset-5.last { - padding-left: 257.66667px; -} - -td.large-offset-6, -td.large-offset-6.first, -td.large-offset-6.last, -th.large-offset-6, -th.large-offset-6.first, -th.large-offset-6.last { - padding-left: 306px; -} - -td.large-offset-7, -td.large-offset-7.first, -td.large-offset-7.last, -th.large-offset-7, -th.large-offset-7.first, -th.large-offset-7.last { - padding-left: 354.33333px; -} - -td.large-offset-8, -td.large-offset-8.first, -td.large-offset-8.last, -th.large-offset-8, -th.large-offset-8.first, -th.large-offset-8.last { - padding-left: 402.66667px; -} - -td.large-offset-9, -td.large-offset-9.first, -td.large-offset-9.last, -th.large-offset-9, -th.large-offset-9.first, -th.large-offset-9.last { - padding-left: 451px; -} - -td.large-offset-10, -td.large-offset-10.first, -td.large-offset-10.last, -th.large-offset-10, -th.large-offset-10.first, -th.large-offset-10.last { - padding-left: 499.33333px; -} - -td.large-offset-11, -td.large-offset-11.first, -td.large-offset-11.last, -th.large-offset-11, -th.large-offset-11.first, -th.large-offset-11.last { - padding-left: 547.66667px; -} - -td.expander, -th.expander { - visibility: hidden; - width: 0; - padding: 0 !important; -} - -table.container.radius { - border-radius: 0; - border-collapse: separate; -} - -.block-grid { - width: 100%; - max-width: 580px; -} - -.block-grid td { - display: inline-block; - padding: 8px; -} - -.up-2 td { - width: 274px !important; -} - -.up-3 td { - width: 177px !important; -} - -.up-4 td { - width: 129px !important; -} - -.up-5 td { - width: 100px !important; -} - -.up-6 td { - width: 80px !important; -} - -.up-7 td { - width: 66px !important; -} - -.up-8 td { - width: 56px !important; -} - -table.text-center, -th.text-center, -td.text-center, -h1.text-center, -h2.text-center, -h3.text-center, -h4.text-center, -h5.text-center, -h6.text-center, -p.text-center, -span.text-center { - text-align: center; -} - -table.text-left, -th.text-left, -td.text-left, -h1.text-left, -h2.text-left, -h3.text-left, -h4.text-left, -h5.text-left, -h6.text-left, -p.text-left, -span.text-left { - text-align: left; -} - -table.text-right, -th.text-right, -td.text-right, -h1.text-right, -h2.text-right, -h3.text-right, -h4.text-right, -h5.text-right, -h6.text-right, -p.text-right, -span.text-right { - text-align: right; -} - -span.text-center { - display: block; - width: 100%; - text-align: center; -} - -@media only screen and (max-width: 596px) { - .small-float-center { - margin: 0 auto !important; - float: none !important; - text-align: center !important; - } - .small-text-center { - text-align: center !important; - } - .small-text-left { - text-align: left !important; - } - .small-text-right { - text-align: right !important; - } -} - -img.float-left { - float: left; - text-align: left; -} - -img.float-right { - float: right; - text-align: right; -} - -img.float-center, -img.text-center { - margin: 0 auto; - Margin: 0 auto; - float: none; - text-align: center; -} - -table.float-center, -td.float-center, -th.float-center { - margin: 0 auto; - Margin: 0 auto; - float: none; - text-align: center; -} - -.hide-for-large { - display: none !important; - mso-hide: all; - overflow: hidden; - max-height: 0; - font-size: 0; - width: 0; - line-height: 0; -} - -@media only screen and (max-width: 596px) { - .hide-for-large { - display: block !important; - width: auto !important; - overflow: visible !important; - max-height: none !important; - font-size: inherit !important; - line-height: inherit !important; - } -} - -table.body table.container .hide-for-large * { - mso-hide: all; -} - -@media only screen and (max-width: 596px) { - table.body table.container .hide-for-large, - table.body table.container .row.hide-for-large { - display: table !important; - width: 100% !important; - } -} - -@media only screen and (max-width: 596px) { - table.body table.container .callout-inner.hide-for-large { - display: table-cell !important; - width: 100% !important; - } -} - -@media only screen and (max-width: 596px) { - table.body table.container .show-for-large { - display: none !important; - width: 0; - mso-hide: all; - overflow: hidden; - } -} - -body, -table.body, -h1, -h2, -h3, -h4, -h5, -h6, -p, -td, -th, -a { - color: #0a0a0a; - font-family: Helvetica, Arial, sans-serif; - font-weight: normal; - padding: 0; - margin: 0; - Margin: 0; - text-align: left; - line-height: 1.3; -} - -h1, -h2, -h3, -h4, -h5, -h6 { - color: inherit; - word-wrap: normal; - font-family: Helvetica, Arial, sans-serif; - font-weight: normal; - margin-bottom: 10px; - Margin-bottom: 10px; -} - -h1 { - font-size: 34px; -} - -h2 { - font-size: 30px; -} - -h3 { - font-size: 28px; -} - -h4 { - font-size: 24px; -} - -h5 { - font-size: 20px; -} - -h6 { - font-size: 18px; -} - -body, -table.body, -p, -td, -th { - font-size: 16px; - line-height: 1.3; -} - -p { - margin-bottom: 10px; - Margin-bottom: 10px; -} - -p.lead { - font-size: 20px; - line-height: 1.6; -} - -p.subheader { - margin-top: 4px; - margin-bottom: 8px; - Margin-top: 4px; - Margin-bottom: 8px; - font-weight: normal; - line-height: 1.4; - color: #8a8a8a; -} - -small { - font-size: 80%; - color: #cacaca; -} - -a { - color: #2199e8; - text-decoration: none; -} - -a:hover { - color: #147dc2; -} - -a:active { - color: #147dc2; -} - -a:visited { - color: #2199e8; -} - -h1 a, -h1 a:visited, -h2 a, -h2 a:visited, -h3 a, -h3 a:visited, -h4 a, -h4 a:visited, -h5 a, -h5 a:visited, -h6 a, -h6 a:visited { - color: #2199e8; -} - -pre { - background: #f3f3f3; - margin: 30px 0; - Margin: 30px 0; -} - -pre code { - color: #cacaca; -} - -pre code span.callout { - color: #8a8a8a; - font-weight: bold; -} - -pre code span.callout-strong { - color: #ff6908; - font-weight: bold; -} - -table.hr { - width: 100%; -} - -table.hr th { - height: 0; - max-width: 580px; - border-top: 0; - border-right: 0; - border-bottom: 1px solid #0a0a0a; - border-left: 0; - margin: 20px auto; - Margin: 20px auto; - clear: both; -} - -.stat { - font-size: 40px; - line-height: 1; -} - -p+.stat { - margin-top: -16px; - Margin-top: -16px; -} - -span.preheader { - display: none !important; - visibility: hidden; - mso-hide: all !important; - font-size: 1px; - color: #f3f3f3; - line-height: 1px; - max-height: 0px; - max-width: 0px; - opacity: 0; - overflow: hidden; -} - -table.button { - width: auto; - margin: 0 0 16px 0; - Margin: 0 0 16px 0; -} - -table.button table td { - text-align: left; - color: #fefefe; - background: #2199e8; - border: 2px solid #2199e8; -} - -table.button table td a { - font-family: Helvetica, Arial, sans-serif; - font-size: 16px; - font-weight: bold; - color: #fefefe; - text-decoration: none; - display: inline-block; - padding: 8px 16px 8px 16px; - border: 0 solid #2199e8; - border-radius: 3px; -} - -table.button.radius table td { - border-radius: 3px; - border: none; -} - -table.button.rounded table td { - border-radius: 500px; - border: none; -} - -table.button:hover table tr td a, -table.button:active table tr td a, -table.button table tr td a:visited, -table.button.tiny:hover table tr td a, -table.button.tiny:active table tr td a, -table.button.tiny table tr td a:visited, -table.button.small:hover table tr td a, -table.button.small:active table tr td a, -table.button.small table tr td a:visited, -table.button.large:hover table tr td a, -table.button.large:active table tr td a, -table.button.large table tr td a:visited { - color: #fefefe; -} - -table.button.tiny table td, -table.button.tiny table a { - padding: 4px 8px 4px 8px; -} - -table.button.tiny table a { - font-size: 10px; - font-weight: normal; -} - -table.button.small table td, -table.button.small table a { - padding: 5px 10px 5px 10px; - font-size: 12px; -} - -table.button.large table a { - padding: 10px 20px 10px 20px; - font-size: 20px; -} - -table.button.expand, -table.button.expanded { - width: 100% !important; -} - -table.button.expand table, -table.button.expanded table { - width: 100%; -} - -table.button.expand table a, -table.button.expanded table a { - text-align: center; - width: 100%; - padding-left: 0; - padding-right: 0; -} - -table.button.expand center, -table.button.expanded center { - min-width: 0; -} - -table.button:hover table td, -table.button:visited table td, -table.button:active table td { - background: #147dc2; - color: #fefefe; -} - -table.button:hover table a, -table.button:visited table a, -table.button:active table a { - border: 0 solid #147dc2; -} - -table.button.secondary table td { - background: #777777; - color: #fefefe; - border: 0px solid #777777; -} - -table.button.secondary table a { - color: #fefefe; - border: 0 solid #777777; -} - -table.button.secondary:hover table td { - background: #919191; - color: #fefefe; -} - -table.button.secondary:hover table a { - border: 0 solid #919191; -} - -table.button.secondary:hover table td a { - color: #fefefe; -} - -table.button.secondary:active table td a { - color: #fefefe; -} - -table.button.secondary table td a:visited { - color: #fefefe; -} - -table.button.success table td { - background: #3adb76; - border: 0px solid #3adb76; -} - -table.button.success table a { - border: 0 solid #3adb76; -} - -table.button.success:hover table td { - background: #23bf5d; -} - -table.button.success:hover table a { - border: 0 solid #23bf5d; -} - -table.button.alert table td { - background: #ec5840; - border: 0px solid #ec5840; -} - -table.button.alert table a { - border: 0 solid #ec5840; -} - -table.button.alert:hover table td { - background: #e23317; -} - -table.button.alert:hover table a { - border: 0 solid #e23317; -} - -table.button.warning table td { - background: #ffae00; - border: 0px solid #ffae00; -} - -table.button.warning table a { - border: 0px solid #ffae00; -} - -table.button.warning:hover table td { - background: #cc8b00; -} - -table.button.warning:hover table a { - border: 0px solid #cc8b00; -} - -table.callout { - margin-bottom: 16px; - Margin-bottom: 16px; -} - -th.callout-inner { - width: 100%; - border: 1px solid #cbcbcb; - padding: 10px; - background: #fefefe; -} - -th.callout-inner.primary { - background: #def0fc; - border: 1px solid #444444; - color: #0a0a0a; -} - -th.callout-inner.secondary { - background: #ebebeb; - border: 1px solid #444444; - color: #0a0a0a; -} - -th.callout-inner.success { - background: #e1faea; - border: 1px solid #1b9448; - color: #fefefe; -} - -th.callout-inner.warning { - background: #fff3d9; - border: 1px solid #996800; - color: #fefefe; -} - -th.callout-inner.alert { - background: #fce6e2; - border: 1px solid #b42912; - color: #fefefe; -} - -.thumbnail { - border: solid 4px #fefefe; - box-shadow: 0 0 0 1px rgba(10, 10, 10, 0.2); - display: inline-block; - line-height: 0; - max-width: 100%; - transition: box-shadow 200ms ease-out; - border-radius: 3px; - margin-bottom: 16px; -} - -.thumbnail:hover, -.thumbnail:focus { - box-shadow: 0 0 6px 1px rgba(33, 153, 232, 0.5); -} - -table.menu { - width: 580px; -} - -table.menu td.menu-item, -table.menu th.menu-item { - padding: 10px; - padding-right: 10px; -} - -table.menu td.menu-item a, -table.menu th.menu-item a { - color: #2199e8; -} - -table.menu.vertical td.menu-item, -table.menu.vertical th.menu-item { - padding: 10px; - padding-right: 0; - display: block; -} - -table.menu.vertical td.menu-item a, -table.menu.vertical th.menu-item a { - width: 100%; -} - -table.menu.vertical td.menu-item table.menu.vertical td.menu-item, -table.menu.vertical td.menu-item table.menu.vertical th.menu-item, -table.menu.vertical th.menu-item table.menu.vertical td.menu-item, -table.menu.vertical th.menu-item table.menu.vertical th.menu-item { - padding-left: 10px; -} - -table.menu.text-center a { - text-align: center; -} - -.menu[align="center"] { - width: auto !important; -} - -body.outlook p { - display: inline !important; -} - -@media only screen and (max-width: 596px) { - table.body img { - width: auto; - height: auto; - } - table.body center { - min-width: 0 !important; - } - table.body .container { - width: 95% !important; - } - table.body .columns, - table.body .column { - height: auto !important; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - padding-left: 16px !important; - padding-right: 16px !important; - } - table.body .columns .column, - table.body .columns .columns, - table.body .column .column, - table.body .column .columns { - padding-left: 0 !important; - padding-right: 0 !important; - } - table.body .collapse .columns, - table.body .collapse .column { - padding-left: 0 !important; - padding-right: 0 !important; - } - td.small-1, - th.small-1 { - display: inline-block !important; - width: 8.33333% !important; - } - td.small-2, - th.small-2 { - display: inline-block !important; - width: 16.66667% !important; - } - td.small-3, - th.small-3 { - display: inline-block !important; - width: 25% !important; - } - td.small-4, - th.small-4 { - display: inline-block !important; - width: 33.33333% !important; - } - td.small-5, - th.small-5 { - display: inline-block !important; - width: 41.66667% !important; - } - td.small-6, - th.small-6 { - display: inline-block !important; - width: 50% !important; - } - td.small-7, - th.small-7 { - display: inline-block !important; - width: 58.33333% !important; - } - td.small-8, - th.small-8 { - display: inline-block !important; - width: 66.66667% !important; - } - td.small-9, - th.small-9 { - display: inline-block !important; - width: 75% !important; - } - td.small-10, - th.small-10 { - display: inline-block !important; - width: 83.33333% !important; - } - td.small-11, - th.small-11 { - display: inline-block !important; - width: 91.66667% !important; - } - td.small-12, - th.small-12 { - display: inline-block !important; - width: 100% !important; - } - .columns td.small-12, - .column td.small-12, - .columns th.small-12, - .column th.small-12 { - display: block !important; - width: 100% !important; - } - table.body td.small-offset-1, - table.body th.small-offset-1 { - margin-left: 8.33333% !important; - Margin-left: 8.33333% !important; - } - table.body td.small-offset-2, - table.body th.small-offset-2 { - margin-left: 16.66667% !important; - Margin-left: 16.66667% !important; - } - table.body td.small-offset-3, - table.body th.small-offset-3 { - margin-left: 25% !important; - Margin-left: 25% !important; - } - table.body td.small-offset-4, - table.body th.small-offset-4 { - margin-left: 33.33333% !important; - Margin-left: 33.33333% !important; - } - table.body td.small-offset-5, - table.body th.small-offset-5 { - margin-left: 41.66667% !important; - Margin-left: 41.66667% !important; - } - table.body td.small-offset-6, - table.body th.small-offset-6 { - margin-left: 50% !important; - Margin-left: 50% !important; - } - table.body td.small-offset-7, - table.body th.small-offset-7 { - margin-left: 58.33333% !important; - Margin-left: 58.33333% !important; - } - table.body td.small-offset-8, - table.body th.small-offset-8 { - margin-left: 66.66667% !important; - Margin-left: 66.66667% !important; - } - table.body td.small-offset-9, - table.body th.small-offset-9 { - margin-left: 75% !important; - Margin-left: 75% !important; - } - table.body td.small-offset-10, - table.body th.small-offset-10 { - margin-left: 83.33333% !important; - Margin-left: 83.33333% !important; - } - table.body td.small-offset-11, - table.body th.small-offset-11 { - margin-left: 91.66667% !important; - Margin-left: 91.66667% !important; - } - table.body table.columns td.expander, - table.body table.columns th.expander { - display: none !important; - } - table.body .right-text-pad, - table.body .text-pad-right { - padding-left: 10px !important; - } - table.body .left-text-pad, - table.body .text-pad-left { - padding-right: 10px !important; - } - table.menu { - width: 100% !important; - } - table.menu td, - table.menu th { - width: auto !important; - display: inline-block !important; - } - table.menu.vertical td, - table.menu.vertical th, - table.menu.small-vertical td, - table.menu.small-vertical th { - display: block !important; - } - table.menu[align="center"] { - width: auto !important; - } - table.button.small-expand, - table.button.small-expanded { - width: 100% !important; - } - table.button.small-expand table, - table.button.small-expanded table { - width: 100%; - } - table.button.small-expand table a, - table.button.small-expanded table a { - text-align: center !important; - width: 100% !important; - padding-left: 0 !important; - padding-right: 0 !important; - } - table.button.small-expand center, - table.button.small-expanded center { - min-width: 0; - } -} diff --git a/lib/symfony/twig-bridge/Resources/views/Email/zurb_2/notification/body.html.twig b/lib/symfony/twig-bridge/Resources/views/Email/zurb_2/notification/body.html.twig deleted file mode 100644 index 0a52d36b3..000000000 --- a/lib/symfony/twig-bridge/Resources/views/Email/zurb_2/notification/body.html.twig +++ /dev/null @@ -1,67 +0,0 @@ -{% apply inky_to_html|inline_css %} -<html> -<head> -<style> - {% block style %} - {{ source("@email/zurb_2/main.css") }} - {{ source("@email/zurb_2/notification/local.css") }} - {% endblock %} -</style> -</head> -<body> -<spacer size="32"></spacer> -<wrapper class="body"> - <container class="body_{{ ("urgent" == importance ? "alert" : ("high" == importance ? "warning" : "default")) }}"> - <spacer size="16"></spacer> - <row> - <columns large="12" small="12"> - {% block lead %} - {% if importance is not null %}<small><strong>{{ importance|upper }}</strong></small>{% endif %} - <p class="lead"> - {{ email.subject }} - </p> - {% endblock %} - - {% block content %} - {% if markdown %} - {{ include('@email/zurb_2/notification/content_markdown.html.twig') }} - {% else %} - {{ (raw ? content|raw : content)|nl2br }} - {% endif %} - {% endblock %} - - {% block action %} - {% if action_url %} - <spacer size="16"></spacer> - <button href="{{ action_url }}">{{ action_text }}</button> - {% endif %} - {% endblock %} - - {% block exception %} - {% if exception %} - <spacer size="16"></spacer> - <p><em>Exception stack trace attached.</em></p> - {% endif %} - {% endblock %} - </columns> - </row> - - <wrapper class="secondary"> - <spacer size="16"></spacer> - {% block footer %} - {% if footer_text is defined and footer_text is not null %} - <row> - <columns small="12" large="6"> - {% block footer_content %} - <p><small>{{ footer_text }}</small></p> - {% endblock %} - </columns> - </row> - {% endif %} - {% endblock %} - </wrapper> - </container> -</wrapper> -</body> -</html> -{% endapply %} diff --git a/lib/symfony/twig-bridge/Resources/views/Email/zurb_2/notification/body.txt.twig b/lib/symfony/twig-bridge/Resources/views/Email/zurb_2/notification/body.txt.twig deleted file mode 100644 index c98bb08a7..000000000 --- a/lib/symfony/twig-bridge/Resources/views/Email/zurb_2/notification/body.txt.twig +++ /dev/null @@ -1,20 +0,0 @@ -{% block lead %} -{{ email.subject }} -{% endblock %} - -{% block content %} -{{ content }} -{% endblock %} - -{% block action %} -{% if action_url %} -{{ action_text }}: {{ action_url }} -{% endif %} -{% endblock %} - -{% block exception %} -{% if exception %} -Exception stack trace attached. -{{ exception }} -{% endif %} -{% endblock %} diff --git a/lib/symfony/twig-bridge/Resources/views/Email/zurb_2/notification/content_markdown.html.twig b/lib/symfony/twig-bridge/Resources/views/Email/zurb_2/notification/content_markdown.html.twig deleted file mode 100644 index 120b2caad..000000000 --- a/lib/symfony/twig-bridge/Resources/views/Email/zurb_2/notification/content_markdown.html.twig +++ /dev/null @@ -1 +0,0 @@ -{{ content|markdown_to_html }} diff --git a/lib/symfony/twig-bridge/Resources/views/Email/zurb_2/notification/local.css b/lib/symfony/twig-bridge/Resources/views/Email/zurb_2/notification/local.css deleted file mode 100644 index 2e68dcd3e..000000000 --- a/lib/symfony/twig-bridge/Resources/views/Email/zurb_2/notification/local.css +++ /dev/null @@ -1,19 +0,0 @@ -body { - background: #f3f3f3; -} - -.wrapper.secondary { - background: #f3f3f3; -} - -.container.body_alert { - border-top: 8px solid #ec5840; -} - -.container.body_warning { - border-top: 8px solid #ffae00; -} - -.container.body_default { - border-top: 8px solid #aaaaaa; -} diff --git a/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig b/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig deleted file mode 100644 index 49cd80439..000000000 --- a/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig +++ /dev/null @@ -1,71 +0,0 @@ -{% use "bootstrap_3_layout.html.twig" %} - -{% block form_start -%} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' form-horizontal')|trim}) %} - {{- parent() -}} -{%- endblock form_start %} - -{# Labels #} - -{% block form_label -%} - {%- if label is same as(false) -%} - <div class="{{ block('form_label_class') }}"></div> - {%- else -%} - {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' ' ~ block('form_label_class'))|trim}) -%} - {{- parent() -}} - {%- endif -%} -{%- endblock form_label %} - -{% block form_label_class -%} -col-sm-2 -{%- endblock form_label_class %} - -{# Rows #} - -{% block form_row -%} - {%- set widget_attr = {} -%} - {%- if help is not empty -%} - {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} - {%- endif -%} - <div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group' ~ ((not compound or force_error|default(false)) and not valid ? ' has-error'))|trim})} %}{{ block('attributes') }}{% endwith %}> - {{- form_label(form) -}} - <div class="{{ block('form_group_class') }}"> - {{- form_widget(form, widget_attr) -}} - {{- form_help(form) -}} - {{- form_errors(form) -}} - </div> -{##}</div> -{%- endblock form_row %} - -{% block submit_row -%} - <div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group')|trim})} %}{{ block('attributes') }}{% endwith %}>{#--#} - <div class="{{ block('form_label_class') }}"></div>{#--#} - <div class="{{ block('form_group_class') }}"> - {{- form_widget(form) -}} - </div>{#--#} - </div> -{%- endblock submit_row %} - -{% block reset_row -%} - <div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group')|trim})} %}{{ block('attributes') }}{% endwith %}>{#--#} - <div class="{{ block('form_label_class') }}"></div>{#--#} - <div class="{{ block('form_group_class') }}"> - {{- form_widget(form) -}} - </div>{#--#} - </div> -{%- endblock reset_row %} - -{% block form_group_class -%} -col-sm-10 -{%- endblock form_group_class %} - -{% block checkbox_row -%} - <div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group' ~ (not valid ? ' has-error'))|trim})} %}{{ block('attributes') }}{% endwith %}>{#--#} - <div class="{{ block('form_label_class') }}"></div>{#--#} - <div class="{{ block('form_group_class') }}"> - {{- form_widget(form) -}} - {{- form_help(form) -}} - {{- form_errors(form) -}} - </div>{#--#} - </div> -{%- endblock checkbox_row %} diff --git a/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_3_layout.html.twig b/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_3_layout.html.twig deleted file mode 100644 index 865f9078a..000000000 --- a/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_3_layout.html.twig +++ /dev/null @@ -1,216 +0,0 @@ -{% use "bootstrap_base_layout.html.twig" %} - -{# Widgets #} - -{% block form_widget_simple -%} - {% if type is not defined or type not in ['file', 'hidden'] %} - {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-control')|trim}) -%} - {% endif %} - {{- parent() -}} -{%- endblock form_widget_simple %} - -{% block button_widget -%} - {%- set attr = attr|merge({class: (attr.class|default('btn-default') ~ ' btn')|trim}) -%} - {{- parent() -}} -{%- endblock button_widget %} - -{% block money_widget -%} - {% set prepend = not (money_pattern starts with '{{') %} - {% set append = not (money_pattern ends with '}}') %} - {% if prepend or append %} - <div class="input-group"> - {% if prepend %} - <span class="input-group-addon">{{ money_pattern|form_encode_currency }}</span> - {% endif %} - {{- block('form_widget_simple') -}} - {% if append %} - <span class="input-group-addon">{{ money_pattern|form_encode_currency }}</span> - {% endif %} - </div> - {% else %} - {{- block('form_widget_simple') -}} - {% endif %} -{%- endblock money_widget %} - -{% block checkbox_widget -%} - {%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%} - {% if 'checkbox-inline' in parent_label_class %} - {{- form_label(form, null, { widget: parent() }) -}} - {% else -%} - <div class="checkbox"> - {{- form_label(form, null, { widget: parent() }) -}} - </div> - {%- endif -%} -{%- endblock checkbox_widget %} - -{% block radio_widget -%} - {%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%} - {%- if 'radio-inline' in parent_label_class -%} - {{- form_label(form, null, { widget: parent() }) -}} - {%- else -%} - <div class="radio"> - {{- form_label(form, null, { widget: parent() }) -}} - </div> - {%- endif -%} -{%- endblock radio_widget %} - -{% block choice_widget_collapsed -%} - {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-control')|trim}) -%} - {{- parent() -}} -{%- endblock choice_widget_collapsed %} - -{# Labels #} - -{% block form_label -%} - {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' control-label')|trim}) -%} - {{- parent() -}} -{%- endblock form_label %} - -{% block choice_label -%} - {# remove the checkbox-inline and radio-inline class, it's only useful for embed labels #} - {%- set label_attr = label_attr|merge({class: label_attr.class|default('')|replace({'checkbox-inline': '', 'radio-inline': ''})|trim}) -%} - {{- block('form_label') -}} -{% endblock %} - -{% block checkbox_label -%} - {%- set label_attr = label_attr|merge({'for': id}) -%} - - {{- block('checkbox_radio_label') -}} -{%- endblock checkbox_label %} - -{% block radio_label -%} - {%- set label_attr = label_attr|merge({'for': id}) -%} - - {{- block('checkbox_radio_label') -}} -{%- endblock radio_label %} - -{% block checkbox_radio_label -%} - {# Do not display the label if widget is not defined in order to prevent double label rendering #} - {%- if widget is defined -%} - {%- if required -%} - {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' required')|trim}) -%} - {%- endif -%} - {%- if label is not same as(false) and label is empty -%} - {%- if label_format is not empty -%} - {%- set label = label_format|replace({ - '%name%': name, - '%id%': id, - }) -%} - {%- else -%} - {% set label = name|humanize %} - {%- endif -%} - {%- endif -%} - <label{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}> - {#- if statement must be kept on the same line, to force the space between widget and label -#} - {{- widget|raw }} {% if label is not same as(false) -%} - {%- if translation_domain is same as(false) -%} - {%- if label_html is same as(false) -%} - {{ label -}} - {%- else -%} - {{ label|raw -}} - {%- endif -%} - {%- else -%} - {%- if label_html is same as(false) -%} - {{ label|trans(label_translation_parameters, translation_domain) -}} - {%- else -%} - {{ label|trans(label_translation_parameters, translation_domain)|raw -}} - {%- endif -%} - {%- endif -%} - {%- endif -%} - </label> - {%- endif -%} -{%- endblock checkbox_radio_label %} - -{# Rows #} - -{% block form_row -%} - {%- set widget_attr = {} -%} - {%- if help is not empty -%} - {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} - {%- endif -%} - <div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group' ~ ((not compound or force_error|default(false)) and not valid ? ' has-error'))|trim})} %}{{ block('attributes') }}{% endwith %}> - {{- form_label(form) }} {# -#} - {{ form_widget(form, widget_attr) }} {# -#} - {{- form_help(form) -}} - {{ form_errors(form) }} {# -#} - </div> {# -#} -{%- endblock form_row %} - -{% block button_row -%} - <div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group')|trim})} %}{{ block('attributes') }}{% endwith %}> - {{- form_widget(form) -}} - </div> -{%- endblock button_row %} - -{% block choice_row -%} - {% set force_error = true %} - {{- block('form_row') }} -{%- endblock choice_row %} - -{% block date_row -%} - {% set force_error = true %} - {{- block('form_row') }} -{%- endblock date_row %} - -{% block time_row -%} - {% set force_error = true %} - {{- block('form_row') }} -{%- endblock time_row %} - -{% block datetime_row -%} - {% set force_error = true %} - {{- block('form_row') }} -{%- endblock datetime_row %} - -{% block checkbox_row -%} - <div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group' ~ (not valid ? ' has-error'))|trim})} %}{{ block('attributes') }}{% endwith %}> - {{- form_widget(form) -}} - {{- form_help(form) -}} - {{- form_errors(form) -}} - </div> -{%- endblock checkbox_row %} - -{% block radio_row -%} - <div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group' ~ (not valid ? ' has-error'))|trim})} %}{{ block('attributes') }}{% endwith %}> - {{- form_widget(form) -}} - {{- form_help(form) -}} - {{- form_errors(form) -}} - </div> -{%- endblock radio_row %} - -{# Errors #} - -{% block form_errors -%} - {% if errors|length > 0 -%} - {% if form is not rootform %}<span class="help-block">{% else %}<div class="alert alert-danger">{% endif %} - <ul class="list-unstyled"> - {%- for error in errors -%} - <li><span class="glyphicon glyphicon-exclamation-sign"></span> {{ error.message }}</li> - {%- endfor -%} - </ul> - {% if form is not rootform %}</span>{% else %}</div>{% endif %} - {%- endif %} -{%- endblock form_errors %} - -{# Help #} - -{% block form_help -%} - {%- if help is not empty -%} - {%- set help_attr = help_attr|merge({class: (help_attr.class|default('') ~ ' help-block')|trim}) -%} - <span id="{{ id }}_help"{% with { attr: help_attr } %}{{ block('attributes') }}{% endwith %}> - {%- if translation_domain is same as(false) -%} - {%- if help_html is same as(false) -%} - {{- help -}} - {%- else -%} - {{- help|raw -}} - {%- endif -%} - {%- else -%} - {%- if help_html is same as(false) -%} - {{- help|trans(help_translation_parameters, translation_domain) -}} - {%- else -%} - {{- help|trans(help_translation_parameters, translation_domain)|raw -}} - {%- endif -%} - {%- endif -%} - </span> - {%- endif -%} -{%- endblock form_help %} diff --git a/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig b/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig deleted file mode 100644 index 990b324cb..000000000 --- a/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig +++ /dev/null @@ -1,88 +0,0 @@ -{% use "bootstrap_4_layout.html.twig" %} - -{# Labels #} - -{% block form_label -%} - {%- if label is same as(false) -%} - <div class="{{ block('form_label_class') }}"></div> - {%- else -%} - {%- if expanded is not defined or not expanded -%} - {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' col-form-label')|trim}) -%} - {%- endif -%} - {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' ' ~ block('form_label_class'))|trim}) -%} - {{- parent() -}} - {%- endif -%} -{%- endblock form_label %} - -{% block form_label_class -%} -col-sm-2 -{%- endblock form_label_class %} - -{# Rows #} - -{% block form_row -%} - {%- if expanded is defined and expanded -%} - {{ block('fieldset_form_row') }} - {%- else -%} - {%- set widget_attr = {} -%} - {%- if help is not empty -%} - {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} - {%- endif -%} - <div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group row' ~ ((not compound or force_error|default(false)) and not valid ? ' is-invalid'))|trim})} %}{{ block('attributes') }}{% endwith %}> - {{- form_label(form) -}} - <div class="{{ block('form_group_class') }}"> - {{- form_widget(form, widget_attr) -}} - {{- form_help(form) -}} - </div> - {##}</div> - {%- endif -%} -{%- endblock form_row %} - -{% block fieldset_form_row -%} - {%- set widget_attr = {} -%} - {%- if help is not empty -%} - {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} - {%- endif -%} - <fieldset{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group')|trim})} %}{{ block('attributes') }}{% endwith %}> - <div class="row{% if (not compound or force_error|default(false)) and not valid %} is-invalid{% endif %}"> - {{- form_label(form) -}} - <div class="{{ block('form_group_class') }}"> - {{- form_widget(form, widget_attr) -}} - {{- form_help(form) -}} - {{- form_errors(form) -}} - </div> - </div> -{##}</fieldset> -{%- endblock fieldset_form_row %} - -{% block submit_row -%} - <div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group row')|trim})} %}{{ block('attributes') }}{% endwith %}>{#--#} - <div class="{{ block('form_label_class') }}"></div>{#--#} - <div class="{{ block('form_group_class') }}"> - {{- form_widget(form) -}} - </div>{#--#} - </div> -{%- endblock submit_row %} - -{% block reset_row -%} - <div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group row')|trim})} %}{{ block('attributes') }}{% endwith %}>{#--#} - <div class="{{ block('form_label_class') }}"></div>{#--#} - <div class="{{ block('form_group_class') }}"> - {{- form_widget(form) -}} - </div>{#--#} - </div> -{%- endblock reset_row %} - -{% block form_group_class -%} -col-sm-10 -{%- endblock form_group_class %} - -{% block checkbox_row -%} - <div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group row')|trim})} %}{{ block('attributes') }}{% endwith %}>{#--#} - <div class="{{ block('form_label_class') }}"></div>{#--#} - <div class="{{ block('form_group_class') }}"> - {{- form_widget(form) -}} - {{- form_help(form) -}} - </div>{#--#} - </div> -{%- endblock checkbox_row %} diff --git a/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_4_layout.html.twig b/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_4_layout.html.twig deleted file mode 100644 index 0e8084054..000000000 --- a/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_4_layout.html.twig +++ /dev/null @@ -1,371 +0,0 @@ -{% use "bootstrap_base_layout.html.twig" %} - -{# Widgets #} - -{% block money_widget -%} - {%- set prepend = not (money_pattern starts with '{{') -%} - {%- set append = not (money_pattern ends with '}}') -%} - {%- if prepend or append -%} - <div class="input-group{{ group_class|default('') }}"> - {%- if prepend -%} - <div class="input-group-prepend"> - <span class="input-group-text">{{ money_pattern|form_encode_currency }}</span> - </div> - {%- endif -%} - {{- block('form_widget_simple') -}} - {%- if append -%} - <div class="input-group-append"> - <span class="input-group-text">{{ money_pattern|form_encode_currency }}</span> - </div> - {%- endif -%} - </div> - {%- else -%} - {{- block('form_widget_simple') -}} - {%- endif -%} -{%- endblock money_widget %} - -{% block datetime_widget -%} - {%- if widget != 'single_text' and not valid -%} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' form-control is-invalid')|trim}) -%} - {% set valid = true %} - {%- endif -%} - {{- parent() -}} -{%- endblock datetime_widget %} - -{% block date_widget -%} - {%- if widget != 'single_text' and not valid -%} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' form-control is-invalid')|trim}) -%} - {% set valid = true %} - {%- endif -%} - {{- parent() -}} -{%- endblock date_widget %} - -{% block time_widget -%} - {%- if widget != 'single_text' and not valid -%} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' form-control is-invalid')|trim}) -%} - {% set valid = true %} - {%- endif -%} - {{- parent() -}} -{%- endblock time_widget %} - -{% block dateinterval_widget -%} - {%- if widget != 'single_text' and not valid -%} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' form-control is-invalid')|trim}) -%} - {% set valid = true %} - {%- endif -%} - {%- if widget == 'single_text' -%} - {{- block('form_widget_simple') -}} - {%- else -%} - {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-inline')|trim}) -%} - <div {{ block('widget_container_attributes') }}> - {%- if with_years -%} - <div class="col-auto"> - {{ form_label(form.years) }} - {{ form_widget(form.years) }} - </div> - {%- endif -%} - {%- if with_months -%} - <div class="col-auto"> - {{ form_label(form.months) }} - {{ form_widget(form.months) }} - </div> - {%- endif -%} - {%- if with_weeks -%} - <div class="col-auto"> - {{ form_label(form.weeks) }} - {{ form_widget(form.weeks) }} - </div> - {%- endif -%} - {%- if with_days -%} - <div class="col-auto"> - {{ form_label(form.days) }} - {{ form_widget(form.days) }} - </div> - {%- endif -%} - {%- if with_hours -%} - <div class="col-auto"> - {{ form_label(form.hours) }} - {{ form_widget(form.hours) }} - </div> - {%- endif -%} - {%- if with_minutes -%} - <div class="col-auto"> - {{ form_label(form.minutes) }} - {{ form_widget(form.minutes) }} - </div> - {%- endif -%} - {%- if with_seconds -%} - <div class="col-auto"> - {{ form_label(form.seconds) }} - {{ form_widget(form.seconds) }} - </div> - {%- endif -%} - {%- if with_invert %}{{ form_widget(form.invert) }}{% endif -%} - </div> - {%- endif -%} -{%- endblock dateinterval_widget %} - -{% block percent_widget -%} - {%- if symbol -%} - <div class="input-group"> - {{- block('form_widget_simple') -}} - <div class="input-group-append"> - <span class="input-group-text">{{ symbol|default('%') }}</span> - </div> - </div> - {%- else -%} - {{- block('form_widget_simple') -}} - {%- endif -%} -{%- endblock percent_widget %} - -{% block file_widget -%} - <{{ element|default('div') }} class="custom-file"> - {%- set type = type|default('file') -%} - {%- set input_lang = 'en' -%} - {% if app is defined and app.request is defined %}{%- set input_lang = app.request.locale -%}{%- endif -%} - {%- set attr = {lang: input_lang} | merge(attr) -%} - {{- block('form_widget_simple') -}} - {%- set label_attr = label_attr|merge({ class: (label_attr.class|default('') ~ ' custom-file-label')|trim })|filter((value, key) => key != 'id') -%} - <label for="{{ form.vars.id }}" {% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}> - {%- if attr.placeholder is defined and attr.placeholder is not none -%} - {{- translation_domain is same as(false) ? attr.placeholder : attr.placeholder|trans({}, translation_domain) -}} - {%- endif -%} - </label> - </{{ element|default('div') }}> -{% endblock %} - -{% block form_widget_simple -%} - {%- if type is not defined or type != 'hidden' -%} - {%- set className = ' form-control' -%} - {%- if type|default('') == 'file' -%} - {%- set className = ' custom-file-input' -%} - {%- elseif type|default('') == 'range' -%} - {%- set className = ' form-control-range' -%} - {%- endif -%} - {%- set attr = attr|merge({class: (attr.class|default('') ~ className)|trim}) -%} - {%- endif -%} - {%- if type is defined and (type == 'range' or type == 'color') %} - {# Attribute "required" is not supported #} - {%- set required = false -%} - {% endif %} - {{- parent() -}} -{%- endblock form_widget_simple %} - -{% block widget_attributes -%} - {%- if not valid -%} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' is-invalid')|trim}) %} - {%- endif -%} - {{ parent() }} -{%- endblock widget_attributes %} - -{% block button_widget -%} - {%- set attr = attr|merge({class: (attr.class|default('btn-secondary') ~ ' btn')|trim}) -%} - {{- parent() -}} -{%- endblock button_widget %} - -{% block submit_widget -%} - {%- set attr = attr|merge({class: (attr.class|default('btn-primary'))|trim}) -%} - {{- parent() -}} -{%- endblock submit_widget %} - -{% block checkbox_widget -%} - {%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%} - {%- if 'checkbox-custom' in parent_label_class -%} - {%- set attr = attr|merge({class: (attr.class|default('') ~ ' custom-control-input')|trim}) -%} - <div class="custom-control custom-checkbox{{ 'checkbox-inline' in parent_label_class ? ' custom-control-inline' }}"> - {{- form_label(form, null, { widget: parent() }) -}} - </div> - {%- elseif 'switch-custom' in parent_label_class -%} - {%- set attr = attr|merge({class: (attr.class|default('') ~ ' custom-control-input')|trim}) -%} - <div class="custom-control custom-switch{{ 'switch-inline' in parent_label_class ? ' custom-control-inline' }}"> - {{- form_label(form, null, { widget: parent() }) -}} - </div> - {%- else -%} - {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-check-input')|trim}) -%} - <div class="form-check{{ 'checkbox-inline' in parent_label_class ? ' form-check-inline' }}"> - {{- form_label(form, null, { widget: parent() }) -}} - </div> - {%- endif -%} -{%- endblock checkbox_widget %} - -{% block radio_widget -%} - {%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%} - {%- if 'radio-custom' in parent_label_class -%} - {%- set attr = attr|merge({class: (attr.class|default('') ~ ' custom-control-input')|trim}) -%} - <div class="custom-control custom-radio{{ 'radio-inline' in parent_label_class ? ' custom-control-inline' }}"> - {{- form_label(form, null, { widget: parent() }) -}} - </div> - {%- else -%} - {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-check-input')|trim}) -%} - <div class="form-check{{ 'radio-inline' in parent_label_class ? ' form-check-inline' }}"> - {{- form_label(form, null, { widget: parent() }) -}} - </div> - {%- endif -%} -{%- endblock radio_widget %} - -{% block choice_widget_collapsed -%} - {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-control')|trim}) -%} - {{- parent() -}} -{%- endblock choice_widget_collapsed %} - -{% block choice_widget_expanded -%} - <div {{ block('widget_container_attributes') }}> - {%- for child in form %} - {{- form_widget(child, { - parent_label_class: label_attr.class|default(''), - translation_domain: choice_translation_domain, - valid: valid, - }) -}} - {% endfor -%} - </div> -{%- endblock choice_widget_expanded %} - -{# Labels #} - -{% block form_label -%} - {% if label is not same as(false) -%} - {%- if compound is defined and compound -%} - {%- set element = 'legend' -%} - {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' col-form-label')|trim}) -%} - {%- else -%} - {%- set label_attr = label_attr|merge({for: id}) -%} - {%- endif -%} - {% if required -%} - {% set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' required')|trim}) %} - {%- endif -%} - {% if label is empty -%} - {%- if label_format is not empty -%} - {% set label = label_format|replace({ - '%name%': name, - '%id%': id, - }) %} - {%- else -%} - {% set label = name|humanize %} - {%- endif -%} - {%- endif -%} - <{{ element|default('label') }}{% if label_attr %}{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}{% endif %}> - {%- if translation_domain is same as(false) -%} - {%- if label_html is same as(false) -%} - {{- label -}} - {%- else -%} - {{- label|raw -}} - {%- endif -%} - {%- else -%} - {%- if label_html is same as(false) -%} - {{- label|trans(label_translation_parameters, translation_domain) -}} - {%- else -%} - {{- label|trans(label_translation_parameters, translation_domain)|raw -}} - {%- endif -%} - {%- endif -%} - {% block form_label_errors %}{{- form_errors(form) -}}{% endblock form_label_errors %}</{{ element|default('label') }}> - {%- else -%} - {%- if errors|length > 0 -%} - <div id="{{ id }}_errors" class="mb-2"> - {{- form_errors(form) -}} - </div> - {%- endif -%} - {%- endif -%} -{%- endblock form_label %} - -{% block checkbox_radio_label -%} - {#- Do not display the label if widget is not defined in order to prevent double label rendering -#} - {%- if widget is defined -%} - {% set is_parent_custom = parent_label_class is defined and ('checkbox-custom' in parent_label_class or 'radio-custom' in parent_label_class or 'switch-custom' in parent_label_class) %} - {% set is_custom = label_attr.class is defined and ('checkbox-custom' in label_attr.class or 'radio-custom' in label_attr.class or 'switch-custom' in label_attr.class) %} - {%- if is_parent_custom or is_custom -%} - {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' custom-control-label')|trim}) -%} - {%- else %} - {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' form-check-label')|trim}) -%} - {%- endif %} - {%- if not compound -%} - {% set label_attr = label_attr|merge({'for': id}) %} - {%- endif -%} - {%- if required -%} - {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' required')|trim}) -%} - {%- endif -%} - {%- if label is not same as(false) and label is empty -%} - {%- if label_format is not empty -%} - {%- set label = label_format|replace({ - '%name%': name, - '%id%': id, - }) -%} - {%- else -%} - {%- set label = name|humanize -%} - {%- endif -%} - {%- endif -%} - - {{ widget|raw }} - <label{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}> - {%- if label is not same as(false) -%} - {%- if translation_domain is same as(false) -%} - {%- if label_html is same as(false) -%} - {{- label -}} - {%- else -%} - {{- label|raw -}} - {%- endif -%} - {%- else -%} - {%- if label_html is same as(false) -%} - {{- label|trans(label_translation_parameters, translation_domain) -}} - {%- else -%} - {{- label|trans(label_translation_parameters, translation_domain)|raw -}} - {%- endif -%} - {%- endif -%} - {%- endif -%} - {{- form_errors(form) -}} - </label> - {%- endif -%} -{%- endblock checkbox_radio_label %} - -{# Rows #} - -{% block form_row -%} - {%- if compound is defined and compound -%} - {%- set element = 'fieldset' -%} - {%- endif -%} - {%- set widget_attr = {} -%} - {%- if help is not empty -%} - {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} - {%- endif -%} - <{{ element|default('div') }}{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group')|trim})} %}{{ block('attributes') }}{% endwith %}> - {{- form_label(form) -}} - {{- form_widget(form, widget_attr) -}} - {{- form_help(form) -}} - </{{ element|default('div') }}> -{%- endblock form_row %} - -{# Errors #} - -{% block form_errors -%} - {%- if errors|length > 0 -%} - <span class="{% if form is not rootform %}invalid-feedback{% else %}alert alert-danger{% endif %} d-block"> - {%- for error in errors -%} - <span class="d-block"> - <span class="form-error-icon badge badge-danger text-uppercase">{{ 'Error'|trans({}, 'validators') }}</span> <span class="form-error-message">{{ error.message }}</span> - </span> - {%- endfor -%} - </span> - {%- endif %} -{%- endblock form_errors %} - -{# Help #} - -{% block form_help -%} - {%- if help is not empty -%} - {%- set help_attr = help_attr|merge({class: (help_attr.class|default('') ~ ' form-text text-muted')|trim}) -%} - <small id="{{ id }}_help"{% with { attr: help_attr } %}{{ block('attributes') }}{% endwith %}> - {%- if translation_domain is same as(false) -%} - {%- if help_html is same as(false) -%} - {{- help -}} - {%- else -%} - {{- help|raw -}} - {%- endif -%} - {%- else -%} - {%- if help_html is same as(false) -%} - {{- help|trans(help_translation_parameters, translation_domain) -}} - {%- else -%} - {{- help|trans(help_translation_parameters, translation_domain)|raw -}} - {%- endif -%} - {%- endif -%} - </small> - {%- endif -%} -{%- endblock form_help %} diff --git a/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_5_horizontal_layout.html.twig b/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_5_horizontal_layout.html.twig deleted file mode 100644 index 3c24166d4..000000000 --- a/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_5_horizontal_layout.html.twig +++ /dev/null @@ -1,130 +0,0 @@ -{% use "bootstrap_5_layout.html.twig" %} - -{# Labels #} - -{% block form_label -%} - {%- if label is same as(false) -%} - <div class="{{ block('form_label_class') }}"></div> - {%- else -%} - {%- set row_class = row_class|default(row_attr.class|default('')) -%} - {%- if 'form-floating' not in row_class and 'input-group' not in row_class -%} - {%- if expanded is not defined or not expanded -%} - {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' col-form-label')|trim}) -%} - {%- endif -%} - {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' ' ~ block('form_label_class'))|trim}) -%} - {%- endif -%} - {{- parent() -}} - {%- endif -%} -{%- endblock form_label %} - -{% block form_label_class -%} - col-sm-2 -{%- endblock form_label_class %} - -{# Rows #} - -{% block form_row -%} - {%- if expanded is defined and expanded -%} - {{ block('fieldset_form_row') }} - {%- else -%} - {%- set widget_attr = {} -%} - {%- if help is not empty -%} - {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} - {%- endif -%} - {%- set row_class = row_class|default(row_attr.class|default('mb-3')) -%} - {%- set is_form_floating = is_form_floating|default('form-floating' in row_class) -%} - {%- set is_input_group = is_input_group|default('input-group' in row_class) -%} - {#- Remove behavior class from the main container -#} - {%- set row_class = row_class|replace({'form-floating': '', 'input-group': ''}) -%} - <div{% with {attr: row_attr|merge({class: (row_class ~ ' row' ~ ((not compound or force_error|default(false)) and not valid ? ' is-invalid'))|trim})} %}{{ block('attributes') }}{% endwith %}> - {%- if is_form_floating or is_input_group -%} - <div class="{{ block('form_label_class') }}"></div> - <div class="{{ block('form_group_class') }}"> - {%- if is_form_floating -%} - <div class="form-floating"> - {{- form_widget(form, widget_attr) -}} - {{- form_label(form) -}} - </div> - {%- elseif is_input_group -%} - <div class="input-group"> - {{- form_label(form) -}} - {{- form_widget(form, widget_attr) -}} - {#- Hack to properly display help with input group -#} - {{- form_help(form) -}} - </div> - {%- endif -%} - {%- if not is_input_group -%} - {{- form_help(form) -}} - {%- endif -%} - {{- form_errors(form) -}} - </div> - {%- else -%} - {{- form_label(form) -}} - <div class="{{ block('form_group_class') }}"> - {{- form_widget(form, widget_attr) -}} - {{- form_help(form) -}} - {{- form_errors(form) -}} - </div> - {%- endif -%} - {##}</div> - {%- endif -%} -{%- endblock form_row %} - -{% block fieldset_form_row -%} - {%- set widget_attr = {} -%} - {%- if help is not empty -%} - {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} - {%- endif -%} - <fieldset{% with {attr: row_attr|merge({class: row_attr.class|default('mb-3')|trim})} %}{{ block('attributes') }}{% endwith %}> - <div class="row{% if (not compound or force_error|default(false)) and not valid %} is-invalid{% endif %}"> - {{- form_label(form) -}} - <div class="{{ block('form_group_class') }}"> - {{- form_widget(form, widget_attr) -}} - {{- form_help(form) -}} - {{- form_errors(form) -}} - </div> - </div> - </fieldset> -{%- endblock fieldset_form_row %} - -{% block submit_row -%} - <div{% with {attr: row_attr|merge({class: (row_attr.class|default('mb-3') ~ ' row')|trim})} %}{{ block('attributes') }}{% endwith %}>{#--#} - <div class="{{ block('form_label_class') }}"></div>{#--#} - <div class="{{ block('form_group_class') }}"> - {{- form_widget(form) -}} - </div>{#--#} - </div> -{%- endblock submit_row %} - -{% block reset_row -%} - <div{% with {attr: row_attr|merge({class: (row_attr.class|default('mb-3') ~ ' row')|trim})} %}{{ block('attributes') }}{% endwith %}>{#--#} - <div class="{{ block('form_label_class') }}"></div>{#--#} - <div class="{{ block('form_group_class') }}"> - {{- form_widget(form) -}} - </div>{#--#} - </div> -{%- endblock reset_row %} - -{% block button_row -%} - <div{% with {attr: row_attr|merge({class: (row_attr.class|default('mb-3') ~ ' row')|trim})} %}{{ block('attributes') }}{% endwith %}>{#--#} - <div class="{{ block('form_label_class') }}"></div>{#--#} - <div class="{{ block('form_group_class') }}"> - {{- form_widget(form) -}} - </div>{#--#} - </div> -{%- endblock button_row %} - -{% block checkbox_row -%} - <div{% with {attr: row_attr|merge({class: (row_attr.class|default('mb-3') ~ ' row')|trim})} %}{{ block('attributes') }}{% endwith %}>{#--#} - <div class="{{ block('form_label_class') }}"></div>{#--#} - <div class="{{ block('form_group_class') }}"> - {{- form_widget(form) -}} - {{- form_help(form) -}} - {{- form_errors(form) -}} - </div>{#--#} - </div> -{%- endblock checkbox_row %} - -{% block form_group_class -%} - col-sm-10 -{%- endblock form_group_class %} diff --git a/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_5_layout.html.twig b/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_5_layout.html.twig deleted file mode 100644 index 92c603a64..000000000 --- a/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_5_layout.html.twig +++ /dev/null @@ -1,374 +0,0 @@ -{% use "bootstrap_base_layout.html.twig" %} - -{# Widgets #} - -{% block money_widget -%} - {%- set prepend = not (money_pattern starts with '{{') -%} - {%- set append = not (money_pattern ends with '}}') -%} - {%- if prepend or append -%} - <div class="input-group{{ group_class|default('') }}"> - {%- if prepend -%} - <span class="input-group-text">{{ money_pattern|form_encode_currency }}</span> - {%- endif -%} - {{- block('form_widget_simple') -}} - {%- if append -%} - <span class="input-group-text">{{ money_pattern|form_encode_currency }}</span> - {%- endif -%} - </div> - {%- else -%} - {{- block('form_widget_simple') -}} - {%- endif -%} -{%- endblock money_widget %} - -{% block date_widget -%} - {%- if widget == 'single_text' -%} - {{- block('form_widget_simple') -}} - {%- else -%} - {% if not valid %} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' is-invalid')|trim}) -%} - {% set valid = true %} - {% endif %} - {%- if datetime is not defined or not datetime -%} - <div {{ block('widget_container_attributes') -}}> - {%- endif %} - {%- if label is not same as(false) -%} - <div class="visually-hidden"> - {{- form_label(form.year) -}} - {{- form_label(form.month) -}} - {{- form_label(form.day) -}} - </div> - {%- endif -%} - <div class="input-group"> - {{- date_pattern|replace({ - '{{ year }}': form_widget(form.year), - '{{ month }}': form_widget(form.month), - '{{ day }}': form_widget(form.day), - })|raw -}} - </div> - {%- if datetime is not defined or not datetime -%} - </div> - {%- endif -%} - {%- endif -%} -{%- endblock date_widget %} - -{% block time_widget -%} - {%- if widget == 'single_text' -%} - {{- block('form_widget_simple') -}} - {%- else -%} - {% if not valid %} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' is-invalid')|trim}) -%} - {% set valid = true %} - {% endif %} - {%- if datetime is not defined or false == datetime -%} - <div {{ block('widget_container_attributes') -}}> - {%- endif -%} - {%- if label is not same as(false) -%} - <div class="visually-hidden"> - {{- form_label(form.hour) -}} - {%- if with_minutes -%}{{ form_label(form.minute) }}{%- endif -%} - {%- if with_seconds -%}{{ form_label(form.second) }}{%- endif -%} - </div> - {%- endif -%} - {% if with_minutes or with_seconds %} - <div class="input-group"> - {% endif %} - {{- form_widget(form.hour) -}} - {%- if with_minutes -%} - <span class="input-group-text">:</span> - {{- form_widget(form.minute) -}} - {%- endif -%} - {%- if with_seconds -%} - <span class="input-group-text">:</span> - {{- form_widget(form.second) -}} - {%- endif -%} - {% if with_minutes or with_seconds %} - </div> - {% endif %} - {%- if datetime is not defined or false == datetime -%} - </div> - {%- endif -%} - {%- endif -%} -{%- endblock time_widget %} - -{% block datetime_widget -%} - {%- if widget == 'single_text' -%} - {{- block('form_widget_simple') -}} - {%- else -%} - {% if not valid %} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' is-invalid')|trim}) -%} - {% set valid = true %} - {% endif %} - <div {{ block('widget_container_attributes') }}> - {{- form_widget(form.date, { datetime: true } ) -}} - {{- form_errors(form.date) -}} - {{- form_widget(form.time, { datetime: true } ) -}} - {{- form_errors(form.time) -}} - </div> - {%- endif -%} -{%- endblock datetime_widget %} - -{% block dateinterval_widget -%} - {%- if widget == 'single_text' -%} - {{- block('form_widget_simple') -}} - {%- else -%} - {% if not valid %} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' is-invalid')|trim}) -%} - {% set valid = true %} - {% endif %} - <div {{ block('widget_container_attributes') }}> - {%- if with_years -%} - <div class="col-auto mb-3"> - {{ form_label(form.years) }} - {{ form_widget(form.years) }} - </div> - {%- endif -%} - {%- if with_months -%} - <div class="col-auto mb-3"> - {{ form_label(form.months) }} - {{ form_widget(form.months) }} - </div> - {%- endif -%} - {%- if with_weeks -%} - <div class="col-auto mb-3"> - {{ form_label(form.weeks) }} - {{ form_widget(form.weeks) }} - </div> - {%- endif -%} - {%- if with_days -%} - <div class="col-auto mb-3"> - {{ form_label(form.days) }} - {{ form_widget(form.days) }} - </div> - {%- endif -%} - {%- if with_hours -%} - <div class="col-auto mb-3"> - {{ form_label(form.hours) }} - {{ form_widget(form.hours) }} - </div> - {%- endif -%} - {%- if with_minutes -%} - <div class="col-auto mb-3"> - {{ form_label(form.minutes) }} - {{ form_widget(form.minutes) }} - </div> - {%- endif -%} - {%- if with_seconds -%} - <div class="col-auto mb-3"> - {{ form_label(form.seconds) }} - {{ form_widget(form.seconds) }} - </div> - {%- endif -%} - {%- if with_invert %}{{ form_widget(form.invert) }}{% endif -%} - </div> - {%- endif -%} -{%- endblock dateinterval_widget %} - -{% block percent_widget -%} - {%- if symbol -%} - <div class="input-group"> - {{- block('form_widget_simple') -}} - <span class="input-group-text">{{ symbol|default('%') }}</span> - </div> - {%- else -%} - {{- block('form_widget_simple') -}} - {%- endif -%} -{%- endblock percent_widget %} - -{% block form_widget_simple -%} - {%- if type is not defined or type != 'hidden' %} - {%- set widget_class = ' form-control' %} - {%- if type|default('') == 'color' -%} - {%- set widget_class = widget_class ~ ' form-control-color' -%} - {%- elseif type|default('') == 'range' -%} - {%- set widget_class = ' form-range' -%} - {%- endif -%} - {%- set attr = attr|merge({class: (attr.class|default('') ~ widget_class)|trim}) -%} - {% endif -%} - {%- if type is defined and type in ['range', 'color'] %} - {# Attribute "required" is not supported #} - {% set required = false %} - {% endif -%} - {{- parent() -}} -{%- endblock form_widget_simple %} - -{%- block widget_attributes -%} - {%- if not valid %} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' is-invalid')|trim}) %} - {% endif -%} - {{ parent() }} -{%- endblock widget_attributes -%}form_labelform_label - -{%- block button_widget -%} - {%- set attr = attr|merge({class: (attr.class|default('btn-secondary') ~ ' btn')|trim}) -%} - {{- parent() -}} -{%- endblock button_widget %} - -{%- block submit_widget -%} - {%- set attr = attr|merge({class: (attr.class|default('btn-primary'))|trim}) -%} - {{- parent() -}} -{%- endblock submit_widget %} - -{%- block checkbox_widget -%} - {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-check-input')|trim}) -%} - {%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%} - {%- set row_class = 'form-check' -%} - {%- if 'checkbox-inline' in parent_label_class %} - {% set row_class = row_class ~ ' form-check-inline' %} - {% endif -%} - {%- if 'checkbox-switch' in parent_label_class %} - {% set row_class = row_class ~ ' form-switch' %} - {% endif -%} - <div class="{{ row_class }}"> - {{- form_label(form, null, { widget: parent() }) -}} - </div> -{%- endblock checkbox_widget %} - -{%- block radio_widget -%} - {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-check-input')|trim}) -%} - {%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%} - {%- set row_class = 'form-check' -%} - {%- if 'radio-inline' in parent_label_class -%} - {%- set row_class = row_class ~ ' form-check-inline' -%} - {%- endif -%} - <div class="{{ row_class }}"> - {{- form_label(form, null, { widget: parent() }) -}} - </div> -{%- endblock radio_widget %} - -{%- block choice_widget_collapsed -%} - {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-select')|trim}) -%} - {{- parent() -}} -{%- endblock choice_widget_collapsed -%} - -{%- block choice_widget_expanded -%} - <div {{ block('widget_container_attributes') }}> - {%- for child in form %} - {{- form_widget(child, { - parent_label_class: label_attr.class|default(''), - translation_domain: choice_translation_domain, - valid: valid, - }) -}} - {% endfor -%} - </div> -{%- endblock choice_widget_expanded %} - -{# Labels #} - -{%- block form_label -%} - {% if label is not same as(false) -%} - {%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%} - {%- if compound is defined and compound -%} - {%- set element = 'legend' -%} - {%- if 'col-form-label' not in parent_label_class -%} - {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' col-form-label' )|trim}) -%} - {%- endif -%} - {%- else -%} - {%- set row_class = row_class|default(row_attr.class|default('')) -%} - {%- set label_attr = label_attr|merge({for: id}) -%} - {%- if 'col-form-label' not in parent_label_class -%} - {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ('input-group' in row_class ? ' input-group-text' : ' form-label') )|trim}) -%} - {%- endif -%} - {%- endif -%} - {%- endif -%} - {{- parent() -}} -{%- endblock form_label %} - -{%- block checkbox_radio_label -%} - {#- Do not display the label if widget is not defined in order to prevent double label rendering -#} - {%- if widget is defined -%} - {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' form-check-label')|trim}) -%} - {%- if not compound -%} - {% set label_attr = label_attr|merge({'for': id}) %} - {%- endif -%} - {%- if required -%} - {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' required')|trim}) -%} - {%- endif -%} - {%- if parent_label_class is defined -%} - {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' ' ~ parent_label_class)|replace({'checkbox-inline': '', 'radio-inline': ''})|trim}) -%} - {%- endif -%} - {%- if label is not same as(false) and label is empty -%} - {%- if label_format is not empty -%} - {%- set label = label_format|replace({ - '%name%': name, - '%id%': id, - }) -%} - {%- else -%} - {%- set label = name|humanize -%} - {%- endif -%} - {%- endif -%} - - {{ widget|raw }} - <label{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}> - {%- if label is not same as(false) -%} - {%- if translation_domain is same as(false) -%} - {%- if label_html is same as(false) -%} - {{- label -}} - {%- else -%} - {{- label|raw -}} - {%- endif -%} - {%- else -%} - {%- if label_html is same as(false) -%} - {{- label|trans(label_translation_parameters, translation_domain) -}} - {%- else -%} - {{- label|trans(label_translation_parameters, translation_domain)|raw -}} - {%- endif -%} - {%- endif -%} - {%- endif -%} - </label> - {%- endif -%} -{%- endblock checkbox_radio_label %} - -{# Rows #} - -{%- block form_row -%} - {%- if compound is defined and compound -%} - {%- set element = 'fieldset' -%} - {%- endif -%} - {%- set widget_attr = {} -%} - {%- if help is not empty -%} - {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} - {%- endif -%} - {%- set row_class = row_class|default(row_attr.class|default('mb-3')|trim) -%} - <{{ element|default('div') }}{% with {attr: row_attr|merge({class: row_class})} %}{{ block('attributes') }}{% endwith %}> - {%- if 'form-floating' in row_class -%} - {{- form_widget(form, widget_attr) -}} - {{- form_label(form) -}} - {%- else -%} - {{- form_label(form) -}} - {{- form_widget(form, widget_attr) -}} - {%- endif -%} - {{- form_help(form) -}} - {{- form_errors(form) -}} - </{{ element|default('div') }}> -{%- endblock form_row %} - -{%- block button_row -%} - <div{% with {attr: row_attr|merge({class: row_attr.class|default('mb-3')|trim})} %}{{ block('attributes') }}{% endwith %}> - {{- form_widget(form) -}} - </div> -{%- endblock button_row %} - -{# Errors #} - -{%- block form_errors -%} - {%- if errors|length > 0 -%} - {%- for error in errors -%} - <div class="invalid-feedback d-block">{{ error.message }}</div> - {%- endfor -%} - {%- endif %} -{%- endblock form_errors %} - -{# Help #} - -{%- block form_help -%} - {% set row_class = row_attr.class|default('') %} - {% set help_class = ' form-text' %} - {% if 'input-group' in row_class %} - {#- Hack to properly display help with input group -#} - {% set help_class = ' input-group-text' %} - {% endif %} - {%- if help is not empty -%} - {%- set help_attr = help_attr|merge({class: (help_attr.class|default('') ~ help_class ~ ' mb-0')|trim}) -%} - {%- endif -%} - {{- parent() -}} -{%- endblock form_help %} diff --git a/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_base_layout.html.twig b/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_base_layout.html.twig deleted file mode 100644 index b8cb8c44a..000000000 --- a/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_base_layout.html.twig +++ /dev/null @@ -1,208 +0,0 @@ -{% use "form_div_layout.html.twig" %} - -{# Widgets #} - -{% block textarea_widget -%} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' form-control')|trim}) %} - {{- parent() -}} -{%- endblock textarea_widget %} - -{% block money_widget -%} - {% set prepend = not (money_pattern starts with '{{') %} - {% set append = not (money_pattern ends with '}}') %} - {% if prepend or append %} - <div class="input-group{{ group_class|default('') }}"> - {% if prepend %} - <span class="input-group-addon">{{ money_pattern|form_encode_currency }}</span> - {% endif %} - {{- block('form_widget_simple') -}} - {% if append %} - <span class="input-group-addon">{{ money_pattern|form_encode_currency }}</span> - {% endif %} - </div> - {% else %} - {{- block('form_widget_simple') -}} - {% endif %} -{%- endblock money_widget %} - -{% block percent_widget -%} - {%- if symbol -%} - <div class="input-group"> - {{- block('form_widget_simple') -}} - <span class="input-group-addon">{{ symbol|default('%') }}</span> - </div> - {%- else -%} - {{- block('form_widget_simple') -}} - {%- endif -%} -{%- endblock percent_widget %} - -{% block datetime_widget -%} - {%- if widget == 'single_text' -%} - {{- block('form_widget_simple') -}} - {%- else -%} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' form-inline')|trim}) -%} - <div {{ block('widget_container_attributes') }}> - {{- form_errors(form.date) -}} - {{- form_errors(form.time) -}} - - <div class="sr-only"> - {%- if form.date.year is defined %}{{ form_label(form.date.year) }}{% endif -%} - {%- if form.date.month is defined %}{{ form_label(form.date.month) }}{% endif -%} - {%- if form.date.day is defined %}{{ form_label(form.date.day) }}{% endif -%} - {%- if form.time.hour is defined %}{{ form_label(form.time.hour) }}{% endif -%} - {%- if form.time.minute is defined %}{{ form_label(form.time.minute) }}{% endif -%} - {%- if form.time.second is defined %}{{ form_label(form.time.second) }}{% endif -%} - </div> - - {{- form_widget(form.date, { datetime: true } ) -}} - {{- form_widget(form.time, { datetime: true } ) -}} - </div> - {%- endif -%} -{%- endblock datetime_widget %} - -{% block date_widget -%} - {%- if widget == 'single_text' -%} - {{- block('form_widget_simple') -}} - {%- else -%} - {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-inline')|trim}) -%} - {%- if datetime is not defined or not datetime -%} - <div {{ block('widget_container_attributes') -}}> - {%- endif %} - {%- if label is not same as(false) -%} - <div class="sr-only"> - {{ form_label(form.year) }} - {{ form_label(form.month) }} - {{ form_label(form.day) }} - </div> - {%- endif -%} - - {{- date_pattern|replace({ - '{{ year }}': form_widget(form.year), - '{{ month }}': form_widget(form.month), - '{{ day }}': form_widget(form.day), - })|raw -}} - {%- if datetime is not defined or not datetime -%} - </div> - {%- endif -%} - {%- endif -%} -{%- endblock date_widget %} - -{% block time_widget -%} - {%- if widget == 'single_text' -%} - {{- block('form_widget_simple') -}} - {%- else -%} - {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-inline')|trim}) -%} - {%- if datetime is not defined or false == datetime -%} - <div {{ block('widget_container_attributes') -}}> - {%- endif -%} - {%- if label is not same as(false) -%}<div class="sr-only">{{ form_label(form.hour) }}</div>{%- endif -%} - {{- form_widget(form.hour) -}} - {%- if with_minutes -%}:{%- if label is not same as(false) -%}<div class="sr-only">{{ form_label(form.minute) }}</div>{%- endif -%}{{ form_widget(form.minute) }}{%- endif -%} - {%- if with_seconds -%}:{%- if label is not same as(false) -%}<div class="sr-only">{{ form_label(form.second) }}</div>{%- endif -%}{{ form_widget(form.second) }}{%- endif -%} - {%- if datetime is not defined or false == datetime -%} - </div> - {%- endif -%} - {%- endif -%} -{%- endblock time_widget %} - -{%- block dateinterval_widget -%} - {%- if widget == 'single_text' -%} - {{- block('form_widget_simple') -}} - {%- else -%} - {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-inline')|trim}) -%} - <div {{ block('widget_container_attributes') }}> - {{- form_errors(form) -}} - <div class="table-responsive"> - <table class="table {{ table_class|default('table-bordered table-condensed table-striped') }}" role="presentation"> - <thead> - <tr> - {%- if with_years %}<th>{{ form_label(form.years) }}</th>{% endif -%} - {%- if with_months %}<th>{{ form_label(form.months) }}</th>{% endif -%} - {%- if with_weeks %}<th>{{ form_label(form.weeks) }}</th>{% endif -%} - {%- if with_days %}<th>{{ form_label(form.days) }}</th>{% endif -%} - {%- if with_hours %}<th>{{ form_label(form.hours) }}</th>{% endif -%} - {%- if with_minutes %}<th>{{ form_label(form.minutes) }}</th>{% endif -%} - {%- if with_seconds %}<th>{{ form_label(form.seconds) }}</th>{% endif -%} - </tr> - </thead> - <tbody> - <tr> - {%- if with_years %}<td>{{ form_widget(form.years) }}</td>{% endif -%} - {%- if with_months %}<td>{{ form_widget(form.months) }}</td>{% endif -%} - {%- if with_weeks %}<td>{{ form_widget(form.weeks) }}</td>{% endif -%} - {%- if with_days %}<td>{{ form_widget(form.days) }}</td>{% endif -%} - {%- if with_hours %}<td>{{ form_widget(form.hours) }}</td>{% endif -%} - {%- if with_minutes %}<td>{{ form_widget(form.minutes) }}</td>{% endif -%} - {%- if with_seconds %}<td>{{ form_widget(form.seconds) }}</td>{% endif -%} - </tr> - </tbody> - </table> - </div> - {%- if with_invert %}{{ form_widget(form.invert) }}{% endif -%} - </div> - {%- endif -%} -{%- endblock dateinterval_widget -%} - -{% block choice_widget_expanded -%} - {%- if '-inline' in label_attr.class|default('') -%} - {%- for child in form %} - {{- form_widget(child, { - parent_label_class: label_attr.class|default(''), - translation_domain: choice_translation_domain, - }) -}} - {% endfor -%} - {%- else -%} - <div {{ block('widget_container_attributes') }}> - {%- for child in form %} - {{- form_widget(child, { - parent_label_class: label_attr.class|default(''), - translation_domain: choice_translation_domain, - }) -}} - {%- endfor -%} - </div> - {%- endif -%} -{%- endblock choice_widget_expanded %} - -{# Labels #} - -{% block choice_label -%} - {# remove the checkbox-inline and radio-inline class, it's only useful for embed labels #} - {%- set label_attr = label_attr|merge({class: label_attr.class|default('')|replace({'checkbox-inline': '', 'radio-inline': '', 'checkbox-custom': '', 'radio-custom': '', 'switch-custom': ''})|trim}) -%} - {{- block('form_label') -}} -{% endblock choice_label %} - -{% block checkbox_label -%} - {{- block('checkbox_radio_label') -}} -{%- endblock checkbox_label %} - -{% block radio_label -%} - {{- block('checkbox_radio_label') -}} -{%- endblock radio_label %} - -{# Rows #} - -{% block button_row -%} - <div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group')|trim})} %}{{ block('attributes') }}{% endwith %}> - {{- form_widget(form) -}} - </div> -{%- endblock button_row %} - -{% block choice_row -%} - {%- set force_error = true -%} - {{- block('form_row') -}} -{%- endblock choice_row %} - -{% block date_row -%} - {%- set force_error = true -%} - {{- block('form_row') -}} -{%- endblock date_row %} - -{% block time_row -%} - {%- set force_error = true -%} - {{- block('form_row') -}} -{%- endblock time_row %} - -{% block datetime_row -%} - {%- set force_error = true -%} - {{- block('form_row') -}} -{%- endblock datetime_row %} diff --git a/lib/symfony/twig-bridge/Resources/views/Form/form_div_layout.html.twig b/lib/symfony/twig-bridge/Resources/views/Form/form_div_layout.html.twig deleted file mode 100644 index 94f87dc16..000000000 --- a/lib/symfony/twig-bridge/Resources/views/Form/form_div_layout.html.twig +++ /dev/null @@ -1,476 +0,0 @@ -{# Widgets #} - -{%- block form_widget -%} - {% if compound %} - {{- block('form_widget_compound') -}} - {% else %} - {{- block('form_widget_simple') -}} - {% endif %} -{%- endblock form_widget -%} - -{%- block form_widget_simple -%} - {%- set type = type|default('text') -%} - {%- if type == 'range' or type == 'color' -%} - {# Attribute "required" is not supported #} - {%- set required = false -%} - {%- endif -%} - <input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/> -{%- endblock form_widget_simple -%} - -{%- block form_widget_compound -%} - <div {{ block('widget_container_attributes') }}> - {%- if form is rootform -%} - {{ form_errors(form) }} - {%- endif -%} - {{- block('form_rows') -}} - {{- form_rest(form) -}} - </div> -{%- endblock form_widget_compound -%} - -{%- block collection_widget -%} - {% if prototype is defined and not prototype.rendered %} - {%- set attr = attr|merge({'data-prototype': form_row(prototype) }) -%} - {% endif %} - {{- block('form_widget') -}} -{%- endblock collection_widget -%} - -{%- block textarea_widget -%} - <textarea {{ block('widget_attributes') }}>{{ value }}</textarea> -{%- endblock textarea_widget -%} - -{%- block choice_widget -%} - {% if expanded %} - {{- block('choice_widget_expanded') -}} - {% else %} - {{- block('choice_widget_collapsed') -}} - {% endif %} -{%- endblock choice_widget -%} - -{%- block choice_widget_expanded -%} - <div {{ block('widget_container_attributes') }}> - {%- for child in form %} - {{- form_widget(child) -}} - {{- form_label(child, null, {translation_domain: choice_translation_domain}) -}} - {% endfor -%} - </div> -{%- endblock choice_widget_expanded -%} - -{%- block choice_widget_collapsed -%} - {%- if required and placeholder is none and not placeholder_in_choices and not multiple and (attr.size is not defined or attr.size <= 1) -%} - {% set required = false %} - {%- endif -%} - <select {{ block('widget_attributes') }}{% if multiple %} multiple="multiple"{% endif %}> - {%- if placeholder is not none -%} - <option value=""{% if required and value is empty %} selected="selected"{% endif %}>{{ placeholder != '' ? (translation_domain is same as(false) ? placeholder : placeholder|trans({}, translation_domain)) }}</option> - {%- endif -%} - {%- if preferred_choices|length > 0 -%} - {% set options = preferred_choices %} - {% set render_preferred_choices = true %} - {{- block('choice_widget_options') -}} - {%- if choices|length > 0 and separator is not none -%} - <option disabled="disabled">{{ separator }}</option> - {%- endif -%} - {%- endif -%} - {%- set options = choices -%} - {%- set render_preferred_choices = false -%} - {{- block('choice_widget_options') -}} - </select> -{%- endblock choice_widget_collapsed -%} - -{%- block choice_widget_options -%} - {% for group_label, choice in options %} - {%- if choice is iterable -%} - <optgroup label="{{ choice_translation_domain is same as(false) ? group_label : group_label|trans({}, choice_translation_domain) }}"> - {% set options = choice %} - {{- block('choice_widget_options') -}} - </optgroup> - {%- else -%} - <option value="{{ choice.value }}"{% if choice.attr %}{% with { attr: choice.attr } %}{{ block('attributes') }}{% endwith %}{% endif %}{% if not render_preferred_choices|default(false) and choice is selectedchoice(value) %} selected="selected"{% endif %}>{{ choice_translation_domain is same as(false) ? choice.label : choice.label|trans(choice.labelTranslationParameters, choice_translation_domain) }}</option> - {%- endif -%} - {% endfor %} -{%- endblock choice_widget_options -%} - -{%- block checkbox_widget -%} - <input type="checkbox" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} /> -{%- endblock checkbox_widget -%} - -{%- block radio_widget -%} - <input type="radio" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} /> -{%- endblock radio_widget -%} - -{%- block datetime_widget -%} - {% if widget == 'single_text' %} - {{- block('form_widget_simple') -}} - {%- else -%} - <div {{ block('widget_container_attributes') }}> - {{- form_errors(form.date) -}} - {{- form_errors(form.time) -}} - {{- form_widget(form.date) -}} - {{- form_widget(form.time) -}} - </div> - {%- endif -%} -{%- endblock datetime_widget -%} - -{%- block date_widget -%} - {%- if widget == 'single_text' -%} - {{ block('form_widget_simple') }} - {%- else -%} - <div {{ block('widget_container_attributes') }}> - {{- date_pattern|replace({ - '{{ year }}': form_widget(form.year), - '{{ month }}': form_widget(form.month), - '{{ day }}': form_widget(form.day), - })|raw -}} - </div> - {%- endif -%} -{%- endblock date_widget -%} - -{%- block time_widget -%} - {%- if widget == 'single_text' -%} - {{ block('form_widget_simple') }} - {%- else -%} - {%- set vars = widget == 'text' ? { 'attr': { 'size': 1 }} : {} -%} - <div {{ block('widget_container_attributes') }}> - {{ form_widget(form.hour, vars) }}{% if with_minutes %}:{{ form_widget(form.minute, vars) }}{% endif %}{% if with_seconds %}:{{ form_widget(form.second, vars) }}{% endif %} - </div> - {%- endif -%} -{%- endblock time_widget -%} - -{%- block dateinterval_widget -%} - {%- if widget == 'single_text' -%} - {{- block('form_widget_simple') -}} - {%- else -%} - <div {{ block('widget_container_attributes') }}> - {{- form_errors(form) -}} - <table class="{{ table_class|default('') }}" role="presentation"> - <thead> - <tr> - {%- if with_years %}<th>{{ form_label(form.years) }}</th>{% endif -%} - {%- if with_months %}<th>{{ form_label(form.months) }}</th>{% endif -%} - {%- if with_weeks %}<th>{{ form_label(form.weeks) }}</th>{% endif -%} - {%- if with_days %}<th>{{ form_label(form.days) }}</th>{% endif -%} - {%- if with_hours %}<th>{{ form_label(form.hours) }}</th>{% endif -%} - {%- if with_minutes %}<th>{{ form_label(form.minutes) }}</th>{% endif -%} - {%- if with_seconds %}<th>{{ form_label(form.seconds) }}</th>{% endif -%} - </tr> - </thead> - <tbody> - <tr> - {%- if with_years %}<td>{{ form_widget(form.years) }}</td>{% endif -%} - {%- if with_months %}<td>{{ form_widget(form.months) }}</td>{% endif -%} - {%- if with_weeks %}<td>{{ form_widget(form.weeks) }}</td>{% endif -%} - {%- if with_days %}<td>{{ form_widget(form.days) }}</td>{% endif -%} - {%- if with_hours %}<td>{{ form_widget(form.hours) }}</td>{% endif -%} - {%- if with_minutes %}<td>{{ form_widget(form.minutes) }}</td>{% endif -%} - {%- if with_seconds %}<td>{{ form_widget(form.seconds) }}</td>{% endif -%} - </tr> - </tbody> - </table> - {%- if with_invert %}{{ form_widget(form.invert) }}{% endif -%} - </div> - {%- endif -%} -{%- endblock dateinterval_widget -%} - -{%- block number_widget -%} - {# type="number" doesn't work with floats in localized formats #} - {%- set type = type|default('text') -%} - {{ block('form_widget_simple') }} -{%- endblock number_widget -%} - -{%- block integer_widget -%} - {%- set type = type|default('number') -%} - {{ block('form_widget_simple') }} -{%- endblock integer_widget -%} - -{%- block money_widget -%} - {{ money_pattern|form_encode_currency(block('form_widget_simple')) }} -{%- endblock money_widget -%} - -{%- block url_widget -%} - {%- set type = type|default('url') -%} - {{ block('form_widget_simple') }} -{%- endblock url_widget -%} - -{%- block search_widget -%} - {%- set type = type|default('search') -%} - {{ block('form_widget_simple') }} -{%- endblock search_widget -%} - -{%- block percent_widget -%} - {%- set type = type|default('text') -%} - {{ block('form_widget_simple') }}{% if symbol %} {{ symbol|default('%') }}{% endif %} -{%- endblock percent_widget -%} - -{%- block password_widget -%} - {%- set type = type|default('password') -%} - {{ block('form_widget_simple') }} -{%- endblock password_widget -%} - -{%- block hidden_widget -%} - {%- set type = type|default('hidden') -%} - {{ block('form_widget_simple') }} -{%- endblock hidden_widget -%} - -{%- block email_widget -%} - {%- set type = type|default('email') -%} - {{ block('form_widget_simple') }} -{%- endblock email_widget -%} - -{%- block range_widget -%} - {% set type = type|default('range') %} - {{- block('form_widget_simple') -}} -{%- endblock range_widget %} - -{%- block button_widget -%} - {%- if label is empty -%} - {%- if label_format is not empty -%} - {% set label = label_format|replace({ - '%name%': name, - '%id%': id, - }) %} - {%- elseif label is not same as(false) -%} - {% set label = name|humanize %} - {%- endif -%} - {%- endif -%} - <button type="{{ type|default('button') }}" {{ block('button_attributes') }}> - {%- if translation_domain is same as(false) -%} - {%- if label_html is same as(false) -%} - {{- label -}} - {%- else -%} - {{- label|raw -}} - {%- endif -%} - {%- else -%} - {%- if label_html is same as(false) -%} - {{- label|trans(label_translation_parameters, translation_domain) -}} - {%- else -%} - {{- label|trans(label_translation_parameters, translation_domain)|raw -}} - {%- endif -%} - {%- endif -%} - </button> -{%- endblock button_widget -%} - -{%- block submit_widget -%} - {%- set type = type|default('submit') -%} - {{ block('button_widget') }} -{%- endblock submit_widget -%} - -{%- block reset_widget -%} - {%- set type = type|default('reset') -%} - {{ block('button_widget') }} -{%- endblock reset_widget -%} - -{%- block tel_widget -%} - {%- set type = type|default('tel') -%} - {{ block('form_widget_simple') }} -{%- endblock tel_widget -%} - -{%- block color_widget -%} - {%- set type = type|default('color') -%} - {{ block('form_widget_simple') }} -{%- endblock color_widget -%} - -{%- block week_widget -%} - {%- if widget == 'single_text' -%} - {{ block('form_widget_simple') }} - {%- else -%} - {%- set vars = widget == 'text' ? { 'attr': { 'size': 1 }} : {} -%} - <div {{ block('widget_container_attributes') }}> - {{ form_widget(form.year, vars) }}-{{ form_widget(form.week, vars) }} - </div> - {%- endif -%} -{%- endblock week_widget -%} - -{# Labels #} - -{%- block form_label -%} - {% if label is not same as(false) -%} - {% if not compound -%} - {% set label_attr = label_attr|merge({'for': id}) %} - {%- endif -%} - {% if required -%} - {% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %} - {%- endif -%} - {% if label is empty -%} - {%- if label_format is not empty -%} - {% set label = label_format|replace({ - '%name%': name, - '%id%': id, - }) %} - {%- else -%} - {% set label = name|humanize %} - {%- endif -%} - {%- endif -%} - <{{ element|default('label') }}{% if label_attr %}{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}{% endif %}> - {%- if translation_domain is same as(false) -%} - {%- if label_html is same as(false) -%} - {{- label -}} - {%- else -%} - {{- label|raw -}} - {%- endif -%} - {%- else -%} - {%- if label_html is same as(false) -%} - {{- label|trans(label_translation_parameters, translation_domain) -}} - {%- else -%} - {{- label|trans(label_translation_parameters, translation_domain)|raw -}} - {%- endif -%} - {%- endif -%} - </{{ element|default('label') }}> - {%- endif -%} -{%- endblock form_label -%} - -{%- block button_label -%}{%- endblock -%} - -{# Help #} - -{% block form_help -%} - {%- if help is not empty -%} - {%- set help_attr = help_attr|merge({class: (help_attr.class|default('') ~ ' help-text')|trim}) -%} - <p id="{{ id }}_help"{% with { attr: help_attr } %}{{ block('attributes') }}{% endwith %}> - {%- if translation_domain is same as(false) -%} - {%- if help_html is same as(false) -%} - {{- help -}} - {%- else -%} - {{- help|raw -}} - {%- endif -%} - {%- else -%} - {%- if help_html is same as(false) -%} - {{- help|trans(help_translation_parameters, translation_domain) -}} - {%- else -%} - {{- help|trans(help_translation_parameters, translation_domain)|raw -}} - {%- endif -%} - {%- endif -%} - </p> - {%- endif -%} -{%- endblock form_help %} - -{# Rows #} - -{%- block repeated_row -%} - {# - No need to render the errors here, as all errors are mapped - to the first child (see RepeatedTypeValidatorExtension). - #} - {{- block('form_rows') -}} -{%- endblock repeated_row -%} - -{%- block form_row -%} - {%- set widget_attr = {} -%} - {%- if help is not empty -%} - {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} - {%- endif -%} - <div{% with {attr: row_attr} %}{{ block('attributes') }}{% endwith %}> - {{- form_label(form) -}} - {{- form_errors(form) -}} - {{- form_widget(form, widget_attr) -}} - {{- form_help(form) -}} - </div> -{%- endblock form_row -%} - -{%- block button_row -%} - <div{% with {attr: row_attr} %}{{ block('attributes') }}{% endwith %}> - {{- form_widget(form) -}} - </div> -{%- endblock button_row -%} - -{%- block hidden_row -%} - {{ form_widget(form) }} -{%- endblock hidden_row -%} - -{# Misc #} - -{%- block form -%} - {{ form_start(form) }} - {{- form_widget(form) -}} - {{ form_end(form) }} -{%- endblock form -%} - -{%- block form_start -%} - {%- do form.setMethodRendered() -%} - {% set method = method|upper %} - {%- if method in ["GET", "POST"] -%} - {% set form_method = method %} - {%- else -%} - {% set form_method = "POST" %} - {%- endif -%} - <form{% if name != '' %} name="{{ name }}"{% endif %} method="{{ form_method|lower }}"{% if action != '' %} action="{{ action }}"{% endif %}{{ block('attributes') }}{% if multipart %} enctype="multipart/form-data"{% endif %}> - {%- if form_method != method -%} - <input type="hidden" name="_method" value="{{ method }}" /> - {%- endif -%} -{%- endblock form_start -%} - -{%- block form_end -%} - {%- if not render_rest is defined or render_rest -%} - {{ form_rest(form) }} - {%- endif -%} - </form> -{%- endblock form_end -%} - -{%- block form_errors -%} - {%- if errors|length > 0 -%} - <ul> - {%- for error in errors -%} - <li>{{ error.message }}</li> - {%- endfor -%} - </ul> - {%- endif -%} -{%- endblock form_errors -%} - -{%- block form_rest -%} - {% for child in form -%} - {% if not child.rendered %} - {{- form_row(child) -}} - {% endif %} - {%- endfor -%} - - {% if not form.methodRendered and form is rootform %} - {%- do form.setMethodRendered() -%} - {% set method = method|upper %} - {%- if method in ["GET", "POST"] -%} - {% set form_method = method %} - {%- else -%} - {% set form_method = "POST" %} - {%- endif -%} - - {%- if form_method != method -%} - <input type="hidden" name="_method" value="{{ method }}" /> - {%- endif -%} - {% endif -%} -{% endblock form_rest %} - -{# Support #} - -{%- block form_rows -%} - {% for child in form|filter(child => not child.rendered) %} - {{- form_row(child) -}} - {% endfor %} -{%- endblock form_rows -%} - -{%- block widget_attributes -%} - id="{{ id }}" name="{{ full_name }}" - {%- if disabled %} disabled="disabled"{% endif -%} - {%- if required %} required="required"{% endif -%} - {{ block('attributes') }} -{%- endblock widget_attributes -%} - -{%- block widget_container_attributes -%} - {%- if id is not empty %}id="{{ id }}"{% endif -%} - {{ block('attributes') }} -{%- endblock widget_container_attributes -%} - -{%- block button_attributes -%} - id="{{ id }}" name="{{ full_name }}"{% if disabled %} disabled="disabled"{% endif -%} - {{ block('attributes') }} -{%- endblock button_attributes -%} - -{% block attributes -%} - {%- for attrname, attrvalue in attr -%} - {{- " " -}} - {%- if attrname in ['placeholder', 'title'] -%} - {{- attrname }}="{{ translation_domain is same as(false) or attrvalue is null ? attrvalue : attrvalue|trans(attr_translation_parameters, translation_domain) }}" - {%- elseif attrvalue is same as(true) -%} - {{- attrname }}="{{ attrname }}" - {%- elseif attrvalue is not same as(false) -%} - {{- attrname }}="{{ attrvalue }}" - {%- endif -%} - {%- endfor -%} -{%- endblock attributes -%} diff --git a/lib/symfony/twig-bridge/Resources/views/Form/form_table_layout.html.twig b/lib/symfony/twig-bridge/Resources/views/Form/form_table_layout.html.twig deleted file mode 100644 index 00a51ab04..000000000 --- a/lib/symfony/twig-bridge/Resources/views/Form/form_table_layout.html.twig +++ /dev/null @@ -1,50 +0,0 @@ -{% use "form_div_layout.html.twig" %} - -{%- block form_row -%} - {%- set widget_attr = {} -%} - {%- if help is not empty -%} - {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} - {%- endif -%} - <tr{% with {attr: row_attr} %}{{ block('attributes') }}{% endwith %}> - <td> - {{- form_label(form) -}} - </td> - <td> - {{- form_errors(form) -}} - {{- form_widget(form, widget_attr) -}} - {{- form_help(form) -}} - </td> - </tr> -{%- endblock form_row -%} - -{%- block button_row -%} - <tr{% with {attr: row_attr} %}{{ block('attributes') }}{% endwith %}> - <td></td> - <td> - {{- form_widget(form) -}} - </td> - </tr> -{%- endblock button_row -%} - -{%- block hidden_row -%} - {%- set style = row_attr.style is defined ? (row_attr.style ~ (row_attr.style|trim|last != ';' ? '; ')) -%} - <tr{% with {attr: row_attr|merge({style: (style ~ ' display: none')|trim})} %}{{ block('attributes') }}{% endwith %}> - <td colspan="2"> - {{- form_widget(form) -}} - </td> - </tr> -{%- endblock hidden_row -%} - -{%- block form_widget_compound -%} - <table {{ block('widget_container_attributes') }}> - {%- if form is rootform and errors|length > 0 -%} - <tr> - <td colspan="2"> - {{- form_errors(form) -}} - </td> - </tr> - {%- endif -%} - {{- block('form_rows') -}} - {{- form_rest(form) -}} - </table> -{%- endblock form_widget_compound -%} diff --git a/lib/symfony/twig-bridge/Resources/views/Form/foundation_5_layout.html.twig b/lib/symfony/twig-bridge/Resources/views/Form/foundation_5_layout.html.twig deleted file mode 100644 index f8c51b83d..000000000 --- a/lib/symfony/twig-bridge/Resources/views/Form/foundation_5_layout.html.twig +++ /dev/null @@ -1,340 +0,0 @@ -{% extends "form_div_layout.html.twig" %} - -{# Based on Foundation 5 Doc #} -{# Widgets #} - -{% block form_widget_simple -%} - {% if errors|length > 0 -%} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' error')|trim}) %} - {% endif %} - {{- parent() -}} -{%- endblock form_widget_simple %} - -{% block textarea_widget -%} - {% if errors|length > 0 -%} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' error')|trim}) %} - {% endif %} - {{- parent() -}} -{%- endblock textarea_widget %} - -{% block button_widget -%} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' button')|trim}) %} - {{- parent() -}} -{%- endblock button_widget %} - -{% block money_widget -%} - <div class="row collapse"> - {% set prepend = '{{' == money_pattern[0:2] %} - {% if not prepend %} - <div class="small-3 large-2 columns"> - <span class="prefix">{{ money_pattern|form_encode_currency }}</span> - </div> - {% endif %} - <div class="small-9 large-10 columns"> - {{- block('form_widget_simple') -}} - </div> - {% if prepend %} - <div class="small-3 large-2 columns"> - <span class="postfix">{{ money_pattern|form_encode_currency }}</span> - </div> - {% endif %} - </div> -{%- endblock money_widget %} - -{% block percent_widget -%} - <div class="row collapse"> - {%- if symbol -%} - <div class="small-9 large-10 columns"> - {{- block('form_widget_simple') -}} - </div> - <div class="small-3 large-2 columns"> - <span class="postfix">{{ symbol|default('%') }}</span> - </div> - {%- else -%} - <div class="small-12 large-12 columns"> - {{- block('form_widget_simple') -}} - </div> - {%- endif -%} - </div> -{%- endblock percent_widget %} - -{% block datetime_widget -%} - {% if widget == 'single_text' %} - {{- block('form_widget_simple') -}} - {% else %} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' row')|trim}) %} - <div class="row"> - <div class="large-7 columns">{{ form_errors(form.date) }}</div> - <div class="large-5 columns">{{ form_errors(form.time) }}</div> - </div> - <div {{ block('widget_container_attributes') }}> - <div class="large-7 columns">{{ form_widget(form.date, { datetime: true } ) }}</div> - <div class="large-5 columns">{{ form_widget(form.time, { datetime: true } ) }}</div> - </div> - {% endif %} -{%- endblock datetime_widget %} - -{% block date_widget -%} - {% if widget == 'single_text' %} - {{- block('form_widget_simple') -}} - {% else %} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' row')|trim}) %} - {% if datetime is not defined or not datetime %} - <div {{ block('widget_container_attributes') }}> - {% endif %} - {{- date_pattern|replace({ - '{{ year }}': '<div class="large-4 columns">' ~ form_widget(form.year) ~ '</div>', - '{{ month }}': '<div class="large-4 columns">' ~ form_widget(form.month) ~ '</div>', - '{{ day }}': '<div class="large-4 columns">' ~ form_widget(form.day) ~ '</div>', - })|raw -}} - {% if datetime is not defined or not datetime %} - </div> - {% endif %} - {% endif %} -{%- endblock date_widget %} - -{% block time_widget -%} - {% if widget == 'single_text' %} - {{- block('form_widget_simple') -}} - {% else %} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' row')|trim}) %} - {% if datetime is not defined or false == datetime %} - <div {{ block('widget_container_attributes') -}}> - {% endif %} - {% if with_seconds %} - <div class="large-4 columns">{{ form_widget(form.hour) }}</div> - <div class="large-4 columns"> - <div class="row collapse"> - <div class="small-3 large-2 columns"> - <span class="prefix">:</span> - </div> - <div class="small-9 large-10 columns"> - {{ form_widget(form.minute) }} - </div> - </div> - </div> - <div class="large-4 columns"> - <div class="row collapse"> - <div class="small-3 large-2 columns"> - <span class="prefix">:</span> - </div> - <div class="small-9 large-10 columns"> - {{ form_widget(form.second) }} - </div> - </div> - </div> - {% else %} - <div class="large-6 columns">{{ form_widget(form.hour) }}</div> - <div class="large-6 columns"> - <div class="row collapse"> - <div class="small-3 large-2 columns"> - <span class="prefix">:</span> - </div> - <div class="small-9 large-10 columns"> - {{ form_widget(form.minute) }} - </div> - </div> - </div> - {% endif %} - {% if datetime is not defined or false == datetime %} - </div> - {% endif %} - {% endif %} -{%- endblock time_widget %} - -{% block choice_widget_collapsed -%} - {% if errors|length > 0 -%} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' error')|trim}) %} - {% endif %} - - {% if multiple -%} - {% set attr = attr|merge({style: (attr.style|default('') ~ ' height: auto; background-image: none;')|trim}) %} - {% endif %} - - {% if required and placeholder is none and not placeholder_in_choices and not multiple -%} - {% set required = false %} - {%- endif -%} - <select {{ block('widget_attributes') }}{% if multiple %} multiple="multiple" data-customforms="disabled"{% endif %}> - {% if placeholder is not none -%} - <option value=""{% if required and value is empty %} selected="selected"{% endif %}>{{ translation_domain is same as(false) ? placeholder : placeholder|trans({}, translation_domain) }}</option> - {%- endif %} - {%- if preferred_choices|length > 0 -%} - {% set options = preferred_choices %} - {% set render_preferred_choices = true %} - {{- block('choice_widget_options') -}} - {% if choices|length > 0 and separator is not none -%} - <option disabled="disabled">{{ separator }}</option> - {%- endif %} - {%- endif -%} - {% set options = choices -%} - {%- set render_preferred_choices = false -%} - {{- block('choice_widget_options') -}} - </select> -{%- endblock choice_widget_collapsed %} - -{% block choice_widget_expanded -%} - {% if '-inline' in label_attr.class|default('') %} - <ul class="inline-list"> - {% for child in form %} - <li>{{ form_widget(child, { - parent_label_class: label_attr.class|default(''), - }) }}</li> - {% endfor %} - </ul> - {% else %} - <div {{ block('widget_container_attributes') }}> - {% for child in form %} - {{ form_widget(child, { - parent_label_class: label_attr.class|default(''), - }) }} - {% endfor %} - </div> - {% endif %} -{%- endblock choice_widget_expanded %} - -{% block checkbox_widget -%} - {% set parent_label_class = parent_label_class|default('') %} - {% if errors|length > 0 -%} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' error')|trim}) %} - {% endif %} - {% if 'checkbox-inline' in parent_label_class %} - {{ form_label(form, null, { widget: parent() }) }} - {% else %} - <div class="checkbox"> - {{ form_label(form, null, { widget: parent() }) }} - </div> - {% endif %} -{%- endblock checkbox_widget %} - -{% block radio_widget -%} - {% set parent_label_class = parent_label_class|default('') %} - {% if 'radio-inline' in parent_label_class %} - {{ form_label(form, null, { widget: parent() }) }} - {% else %} - {% if errors|length > 0 -%} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' error')|trim}) %} - {% endif %} - <div class="radio"> - {{ form_label(form, null, { widget: parent() }) }} - </div> - {% endif %} -{%- endblock radio_widget %} - -{# Labels #} - -{% block form_label -%} - {% if errors|length > 0 -%} - {% set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' error')|trim}) %} - {% endif %} - {{- parent() -}} -{%- endblock form_label %} - -{% block choice_label -%} - {% if errors|length > 0 -%} - {% set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' error')|trim}) %} - {% endif %} - {# remove the checkbox-inline and radio-inline class, it's only useful for embed labels #} - {% set label_attr = label_attr|merge({class: label_attr.class|default('')|replace({'checkbox-inline': '', 'radio-inline': ''})|trim}) %} - {{- block('form_label') -}} -{%- endblock choice_label %} - -{% block checkbox_label -%} - {{- block('checkbox_radio_label') -}} -{%- endblock checkbox_label %} - -{% block radio_label -%} - {{- block('checkbox_radio_label') -}} -{%- endblock radio_label %} - -{% block checkbox_radio_label -%} - {% if required %} - {% set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' required')|trim}) %} - {% endif %} - {% if errors|length > 0 -%} - {% set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' error')|trim}) %} - {% endif %} - {% if label is empty %} - {%- if label_format is not empty -%} - {% set label = label_format|replace({ - '%name%': name, - '%id%': id, - }) %} - {%- else -%} - {% set label = name|humanize %} - {%- endif -%} - {% endif %} - <label{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}> - {{ widget|raw }} - {{ translation_domain is same as(false) ? label : label|trans(label_translation_parameters, translation_domain) }} - </label> -{%- endblock checkbox_radio_label %} - -{# Rows #} - -{% block form_row -%} - {%- set widget_attr = {} -%} - {%- if help is not empty -%} - {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} - {%- endif -%} - <div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' row')|trim})} %}{{ block('attributes') }}{% endwith %}> - <div class="large-12 columns{% if (not compound or force_error|default(false)) and not valid %} error{% endif %}"> - {{- form_label(form) -}} - {{- form_widget(form, widget_attr) -}} - {{- form_help(form) -}} - {{- form_errors(form) -}} - </div> - </div> -{%- endblock form_row %} - -{% block choice_row -%} - {% set force_error = true %} - {{ block('form_row') }} -{%- endblock choice_row %} - -{% block date_row -%} - {% set force_error = true %} - {{ block('form_row') }} -{%- endblock date_row %} - -{% block time_row -%} - {% set force_error = true %} - {{ block('form_row') }} -{%- endblock time_row %} - -{% block datetime_row -%} - {% set force_error = true %} - {{ block('form_row') }} -{%- endblock datetime_row %} - -{% block checkbox_row -%} - <div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' row')|trim})} %}{{ block('attributes') }}{% endwith %}> - <div class="large-12 columns{% if not valid %} error{% endif %}"> - {{ form_widget(form) }} - {{- form_help(form) -}} - {{ form_errors(form) }} - </div> - </div> -{%- endblock checkbox_row %} - -{% block radio_row -%} - <div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' row')|trim})} %}{{ block('attributes') }}{% endwith %}> - <div class="large-12 columns{% if not valid %} error{% endif %}"> - {{ form_widget(form) }} - {{- form_help(form) -}} - {{ form_errors(form) }} - </div> - </div> -{%- endblock radio_row %} - -{# Errors #} - -{% block form_errors -%} - {% if errors|length > 0 -%} - {% if form is not rootform %}<small class="error">{% else %}<div data-alert class="alert-box alert">{% endif %} - {%- for error in errors -%} - {{ error.message }} - {% if not loop.last %}, {% endif %} - {%- endfor -%} - {% if form is not rootform %}</small>{% else %}</div>{% endif %} - {%- endif %} -{%- endblock form_errors %} diff --git a/lib/symfony/twig-bridge/Resources/views/Form/foundation_6_layout.html.twig b/lib/symfony/twig-bridge/Resources/views/Form/foundation_6_layout.html.twig deleted file mode 100644 index 04ed730f5..000000000 --- a/lib/symfony/twig-bridge/Resources/views/Form/foundation_6_layout.html.twig +++ /dev/null @@ -1,50 +0,0 @@ -{% extends "form_div_layout.html.twig" %} - -{%- block checkbox_row -%} - {%- set parent_class = parent_class|default(attr.class|default('')) -%} - {%- if 'switch-input' in parent_class -%} - {{- form_label(form) -}} - {%- set attr = attr|merge({class: (attr.class|default('') ~ ' switch-input')|trim}) -%} - {{- form_widget(form) -}} - <label class="switch-paddle" for="{{ form.vars.id }}"></label> - {{- form_errors(form) -}} - {%- else -%} - {{- block('form_row') -}} - {%- endif -%} -{%- endblock checkbox_row -%} - -{% block money_widget -%} - {% set prepend = not (money_pattern starts with '{{') %} - {% set append = not (money_pattern ends with '}}') %} - {% if prepend or append %} - <div class="input-group"> - {% if prepend %} - <span class="input-group-label">{{ money_pattern|form_encode_currency }}</span> - {% endif %} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' input-group-field')|trim}) %} - {{- block('form_widget_simple') -}} - {% if append %} - <span class="input-group-label">{{ money_pattern|form_encode_currency }}</span> - {% endif %} - </div> - {% else %} - {{- block('form_widget_simple') -}} - {% endif %} -{%- endblock money_widget %} - -{% block percent_widget -%} - {%- if symbol -%} - <div class="input-group"> - {% set attr = attr|merge({class: (attr.class|default('') ~ ' input-group-field')|trim}) %} - {{- block('form_widget_simple') -}} - <span class="input-group-label">{{ symbol|default('%') }}</span> - </div> - {%- else -%} - {{- block('form_widget_simple') -}} - {%- endif -%} -{%- endblock percent_widget %} - -{% block button_widget -%} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' button')|trim}) %} - {{- parent() -}} -{%- endblock button_widget %} diff --git a/lib/symfony/twig-bridge/Resources/views/Form/tailwind_2_layout.html.twig b/lib/symfony/twig-bridge/Resources/views/Form/tailwind_2_layout.html.twig deleted file mode 100644 index 7f31e70b7..000000000 --- a/lib/symfony/twig-bridge/Resources/views/Form/tailwind_2_layout.html.twig +++ /dev/null @@ -1,69 +0,0 @@ -{% use 'form_div_layout.html.twig' %} - -{%- block form_row -%} - {%- set row_attr = row_attr|merge({ class: row_attr.class|default(row_class|default('mb-6')) }) -%} - {{- parent() -}} -{%- endblock form_row -%} - -{%- block widget_attributes -%} - {%- set attr = attr|merge({ class: attr.class|default(widget_class|default('mt-1 w-full')) ~ (disabled ? ' ' ~ widget_disabled_class|default('border-gray-300 text-gray-500')) ~ (errors|length ? ' ' ~ widget_errors_class|default('border-red-700')) }) -%} - {{- parent() -}} -{%- endblock widget_attributes -%} - -{%- block form_label -%} - {%- set label_attr = label_attr|merge({ class: label_attr.class|default(label_class|default('block text-gray-800')) }) -%} - {{- parent() -}} -{%- endblock form_label -%} - -{%- block form_help -%} - {%- set help_attr = help_attr|merge({ class: help_attr.class|default(help_class|default('mt-1 text-gray-600')) }) -%} - {{- parent() -}} -{%- endblock form_help -%} - -{%- block form_errors -%} - {%- if errors|length > 0 -%} - <ul> - {%- for error in errors -%} - <li class="{{ error_item_class|default('text-red-700') }}">{{ error.message }}</li> - {%- endfor -%} - </ul> - {%- endif -%} -{%- endblock form_errors -%} - -{%- block choice_widget_expanded -%} - {%- set attr = attr|merge({ class: attr.class|default('mt-2') }) -%} - <div {{ block('widget_container_attributes') }}> - {%- for child in form %} - <div class="flex items-center"> - {{- form_widget(child) -}} - {{- form_label(child, null, { translation_domain: choice_translation_domain }) -}} - </div> - {% endfor -%} - </div> -{%- endblock choice_widget_expanded -%} - -{%- block checkbox_row -%} - {%- set row_attr = row_attr|merge({ class: row_attr.class|default(row_class|default('mb-6')) }) -%} - {%- set widget_attr = {} -%} - {%- if help is not empty -%} - {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} - {%- endif -%} - <div{% with {attr: row_attr} %}{{ block('attributes') }}{% endwith %}> - {{- form_errors(form) -}} - <div class="inline-flex items-center"> - {{- form_widget(form, widget_attr) -}} - {{- form_label(form) -}} - </div> - {{- form_help(form) -}} - </div> -{%- endblock checkbox_row -%} - -{%- block checkbox_widget -%} - {%- set widget_class = widget_class|default('mr-2') -%} - {{- parent() -}} -{%- endblock checkbox_widget -%} - -{%- block radio_widget -%} - {%- set widget_class = widget_class|default('mr-2') -%} - {{- parent() -}} -{%- endblock radio_widget -%} diff --git a/lib/symfony/twig-bridge/TokenParser/DumpTokenParser.php b/lib/symfony/twig-bridge/TokenParser/DumpTokenParser.php deleted file mode 100644 index 341dc4185..000000000 --- a/lib/symfony/twig-bridge/TokenParser/DumpTokenParser.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\TokenParser; - -use Symfony\Bridge\Twig\Node\DumpNode; -use Twig\Node\Node; -use Twig\Token; -use Twig\TokenParser\AbstractTokenParser; - -/** - * Token Parser for the 'dump' tag. - * - * Dump variables with: - * - * {% dump %} - * {% dump foo %} - * {% dump foo, bar %} - * - * @author Julien Galenski <julien.galenski@gmail.com> - */ -final class DumpTokenParser extends AbstractTokenParser -{ - /** - * {@inheritdoc} - */ - public function parse(Token $token): Node - { - $values = null; - if (!$this->parser->getStream()->test(Token::BLOCK_END_TYPE)) { - $values = $this->parser->getExpressionParser()->parseMultitargetExpression(); - } - $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); - - return new DumpNode($this->parser->getVarName(), $values, $token->getLine(), $this->getTag()); - } - - /** - * {@inheritdoc} - */ - public function getTag(): string - { - return 'dump'; - } -} diff --git a/lib/symfony/twig-bridge/TokenParser/FormThemeTokenParser.php b/lib/symfony/twig-bridge/TokenParser/FormThemeTokenParser.php deleted file mode 100644 index ef5dacb59..000000000 --- a/lib/symfony/twig-bridge/TokenParser/FormThemeTokenParser.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\TokenParser; - -use Symfony\Bridge\Twig\Node\FormThemeNode; -use Twig\Node\Expression\ArrayExpression; -use Twig\Node\Node; -use Twig\Token; -use Twig\TokenParser\AbstractTokenParser; - -/** - * Token Parser for the 'form_theme' tag. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class FormThemeTokenParser extends AbstractTokenParser -{ - /** - * {@inheritdoc} - */ - public function parse(Token $token): Node - { - $lineno = $token->getLine(); - $stream = $this->parser->getStream(); - - $form = $this->parser->getExpressionParser()->parseExpression(); - $only = false; - - if ($this->parser->getStream()->test(Token::NAME_TYPE, 'with')) { - $this->parser->getStream()->next(); - $resources = $this->parser->getExpressionParser()->parseExpression(); - - if ($this->parser->getStream()->nextIf(Token::NAME_TYPE, 'only')) { - $only = true; - } - } else { - $resources = new ArrayExpression([], $stream->getCurrent()->getLine()); - do { - $resources->addElement($this->parser->getExpressionParser()->parseExpression()); - } while (!$stream->test(Token::BLOCK_END_TYPE)); - } - - $stream->expect(Token::BLOCK_END_TYPE); - - return new FormThemeNode($form, $resources, $lineno, $this->getTag(), $only); - } - - /** - * {@inheritdoc} - */ - public function getTag(): string - { - return 'form_theme'; - } -} diff --git a/lib/symfony/twig-bridge/TokenParser/StopwatchTokenParser.php b/lib/symfony/twig-bridge/TokenParser/StopwatchTokenParser.php deleted file mode 100644 index a70e94b80..000000000 --- a/lib/symfony/twig-bridge/TokenParser/StopwatchTokenParser.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\TokenParser; - -use Symfony\Bridge\Twig\Node\StopwatchNode; -use Twig\Node\Expression\AssignNameExpression; -use Twig\Node\Node; -use Twig\Token; -use Twig\TokenParser\AbstractTokenParser; - -/** - * Token Parser for the stopwatch tag. - * - * @author Wouter J <wouter@wouterj.nl> - */ -final class StopwatchTokenParser extends AbstractTokenParser -{ - protected $stopwatchIsAvailable; - - public function __construct(bool $stopwatchIsAvailable) - { - $this->stopwatchIsAvailable = $stopwatchIsAvailable; - } - - public function parse(Token $token): Node - { - $lineno = $token->getLine(); - $stream = $this->parser->getStream(); - - // {% stopwatch 'bar' %} - $name = $this->parser->getExpressionParser()->parseExpression(); - - $stream->expect(Token::BLOCK_END_TYPE); - - // {% endstopwatch %} - $body = $this->parser->subparse([$this, 'decideStopwatchEnd'], true); - $stream->expect(Token::BLOCK_END_TYPE); - - if ($this->stopwatchIsAvailable) { - return new StopwatchNode($name, $body, new AssignNameExpression($this->parser->getVarName(), $token->getLine()), $lineno, $this->getTag()); - } - - return $body; - } - - public function decideStopwatchEnd(Token $token): bool - { - return $token->test('endstopwatch'); - } - - public function getTag(): string - { - return 'stopwatch'; - } -} diff --git a/lib/symfony/twig-bridge/TokenParser/TransDefaultDomainTokenParser.php b/lib/symfony/twig-bridge/TokenParser/TransDefaultDomainTokenParser.php deleted file mode 100644 index 19b820497..000000000 --- a/lib/symfony/twig-bridge/TokenParser/TransDefaultDomainTokenParser.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\TokenParser; - -use Symfony\Bridge\Twig\Node\TransDefaultDomainNode; -use Twig\Node\Node; -use Twig\Token; -use Twig\TokenParser\AbstractTokenParser; - -/** - * Token Parser for the 'trans_default_domain' tag. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class TransDefaultDomainTokenParser extends AbstractTokenParser -{ - /** - * {@inheritdoc} - */ - public function parse(Token $token): Node - { - $expr = $this->parser->getExpressionParser()->parseExpression(); - - $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); - - return new TransDefaultDomainNode($expr, $token->getLine(), $this->getTag()); - } - - /** - * {@inheritdoc} - */ - public function getTag(): string - { - return 'trans_default_domain'; - } -} diff --git a/lib/symfony/twig-bridge/TokenParser/TransTokenParser.php b/lib/symfony/twig-bridge/TokenParser/TransTokenParser.php deleted file mode 100644 index ffe882859..000000000 --- a/lib/symfony/twig-bridge/TokenParser/TransTokenParser.php +++ /dev/null @@ -1,95 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\TokenParser; - -use Symfony\Bridge\Twig\Node\TransNode; -use Twig\Error\SyntaxError; -use Twig\Node\Expression\AbstractExpression; -use Twig\Node\Expression\ArrayExpression; -use Twig\Node\Node; -use Twig\Node\TextNode; -use Twig\Token; -use Twig\TokenParser\AbstractTokenParser; - -/** - * Token Parser for the 'trans' tag. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class TransTokenParser extends AbstractTokenParser -{ - /** - * {@inheritdoc} - */ - public function parse(Token $token): Node - { - $lineno = $token->getLine(); - $stream = $this->parser->getStream(); - - $count = null; - $vars = new ArrayExpression([], $lineno); - $domain = null; - $locale = null; - if (!$stream->test(Token::BLOCK_END_TYPE)) { - if ($stream->test('count')) { - // {% trans count 5 %} - $stream->next(); - $count = $this->parser->getExpressionParser()->parseExpression(); - } - - if ($stream->test('with')) { - // {% trans with vars %} - $stream->next(); - $vars = $this->parser->getExpressionParser()->parseExpression(); - } - - if ($stream->test('from')) { - // {% trans from "messages" %} - $stream->next(); - $domain = $this->parser->getExpressionParser()->parseExpression(); - } - - if ($stream->test('into')) { - // {% trans into "fr" %} - $stream->next(); - $locale = $this->parser->getExpressionParser()->parseExpression(); - } elseif (!$stream->test(Token::BLOCK_END_TYPE)) { - throw new SyntaxError('Unexpected token. Twig was looking for the "with", "from", or "into" keyword.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - } - - // {% trans %}message{% endtrans %} - $stream->expect(Token::BLOCK_END_TYPE); - $body = $this->parser->subparse([$this, 'decideTransFork'], true); - - if (!$body instanceof TextNode && !$body instanceof AbstractExpression) { - throw new SyntaxError('A message inside a trans tag must be a simple text.', $body->getTemplateLine(), $stream->getSourceContext()); - } - - $stream->expect(Token::BLOCK_END_TYPE); - - return new TransNode($body, $domain, $count, $vars, $locale, $lineno, $this->getTag()); - } - - public function decideTransFork(Token $token): bool - { - return $token->test(['endtrans']); - } - - /** - * {@inheritdoc} - */ - public function getTag(): string - { - return 'trans'; - } -} diff --git a/lib/symfony/twig-bridge/Translation/TwigExtractor.php b/lib/symfony/twig-bridge/Translation/TwigExtractor.php deleted file mode 100644 index e79ec697e..000000000 --- a/lib/symfony/twig-bridge/Translation/TwigExtractor.php +++ /dev/null @@ -1,104 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Translation; - -use Symfony\Component\Finder\Finder; -use Symfony\Component\Translation\Extractor\AbstractFileExtractor; -use Symfony\Component\Translation\Extractor\ExtractorInterface; -use Symfony\Component\Translation\MessageCatalogue; -use Twig\Environment; -use Twig\Error\Error; -use Twig\Source; - -/** - * TwigExtractor extracts translation messages from a twig template. - * - * @author Michel Salib <michelsalib@hotmail.com> - * @author Fabien Potencier <fabien@symfony.com> - */ -class TwigExtractor extends AbstractFileExtractor implements ExtractorInterface -{ - /** - * Default domain for found messages. - * - * @var string - */ - private $defaultDomain = 'messages'; - - /** - * Prefix for found message. - * - * @var string - */ - private $prefix = ''; - - private $twig; - - public function __construct(Environment $twig) - { - $this->twig = $twig; - } - - /** - * {@inheritdoc} - */ - public function extract($resource, MessageCatalogue $catalogue) - { - foreach ($this->extractFiles($resource) as $file) { - try { - $this->extractTemplate(file_get_contents($file->getPathname()), $catalogue); - } catch (Error $e) { - // ignore errors, these should be fixed by using the linter - } - } - } - - /** - * {@inheritdoc} - */ - public function setPrefix(string $prefix) - { - $this->prefix = $prefix; - } - - protected function extractTemplate(string $template, MessageCatalogue $catalogue) - { - $visitor = $this->twig->getExtension('Symfony\Bridge\Twig\Extension\TranslationExtension')->getTranslationNodeVisitor(); - $visitor->enable(); - - $this->twig->parse($this->twig->tokenize(new Source($template, ''))); - - foreach ($visitor->getMessages() as $message) { - $catalogue->set(trim($message[0]), $this->prefix.trim($message[0]), $message[1] ?: $this->defaultDomain); - } - - $visitor->disable(); - } - - /** - * @return bool - */ - protected function canBeExtracted(string $file) - { - return $this->isFile($file) && 'twig' === pathinfo($file, \PATHINFO_EXTENSION); - } - - /** - * {@inheritdoc} - */ - protected function extractFromDirectory($directory) - { - $finder = new Finder(); - - return $finder->files()->name('*.twig')->in($directory); - } -} diff --git a/lib/symfony/twig-bridge/UndefinedCallableHandler.php b/lib/symfony/twig-bridge/UndefinedCallableHandler.php deleted file mode 100644 index 608bbaa8e..000000000 --- a/lib/symfony/twig-bridge/UndefinedCallableHandler.php +++ /dev/null @@ -1,107 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig; - -use Symfony\Bundle\FullStack; -use Twig\Error\SyntaxError; -use Twig\TwigFilter; -use Twig\TwigFunction; - -/** - * @internal - */ -class UndefinedCallableHandler -{ - private const FILTER_COMPONENTS = [ - 'humanize' => 'form', - 'trans' => 'translation', - 'yaml_encode' => 'yaml', - 'yaml_dump' => 'yaml', - ]; - - private const FUNCTION_COMPONENTS = [ - 'asset' => 'asset', - 'asset_version' => 'asset', - 'dump' => 'debug-bundle', - 'encore_entry_link_tags' => 'webpack-encore-bundle', - 'encore_entry_script_tags' => 'webpack-encore-bundle', - 'expression' => 'expression-language', - 'form_widget' => 'form', - 'form_errors' => 'form', - 'form_label' => 'form', - 'form_help' => 'form', - 'form_row' => 'form', - 'form_rest' => 'form', - 'form' => 'form', - 'form_start' => 'form', - 'form_end' => 'form', - 'csrf_token' => 'form', - 'logout_url' => 'security-http', - 'logout_path' => 'security-http', - 'is_granted' => 'security-core', - 'link' => 'web-link', - 'preload' => 'web-link', - 'dns_prefetch' => 'web-link', - 'preconnect' => 'web-link', - 'prefetch' => 'web-link', - 'prerender' => 'web-link', - 'workflow_can' => 'workflow', - 'workflow_transitions' => 'workflow', - 'workflow_has_marked_place' => 'workflow', - 'workflow_marked_places' => 'workflow', - ]; - - private const FULL_STACK_ENABLE = [ - 'form' => 'enable "framework.form"', - 'security-core' => 'add the "SecurityBundle"', - 'security-http' => 'add the "SecurityBundle"', - 'web-link' => 'enable "framework.web_link"', - 'workflow' => 'enable "framework.workflows"', - ]; - - /** - * @return TwigFilter|false - */ - public static function onUndefinedFilter(string $name) - { - if (!isset(self::FILTER_COMPONENTS[$name])) { - return false; - } - - throw new SyntaxError(self::onUndefined($name, 'filter', self::FILTER_COMPONENTS[$name])); - } - - /** - * @return TwigFunction|false - */ - public static function onUndefinedFunction(string $name) - { - if (!isset(self::FUNCTION_COMPONENTS[$name])) { - return false; - } - - if ('webpack-encore-bundle' === self::FUNCTION_COMPONENTS[$name]) { - return new TwigFunction($name, static function () { return ''; }); - } - - throw new SyntaxError(self::onUndefined($name, 'function', self::FUNCTION_COMPONENTS[$name])); - } - - private static function onUndefined(string $name, string $type, string $component): string - { - if (class_exists(FullStack::class) && isset(self::FULL_STACK_ENABLE[$component])) { - return sprintf('Did you forget to %s? Unknown %s "%s".', self::FULL_STACK_ENABLE[$component], $type, $name); - } - - return sprintf('Did you forget to run "composer require symfony/%s"? Unknown %s "%s".', $component, $type, $name); - } -} diff --git a/lib/symfony/twig-bridge/composer.json b/lib/symfony/twig-bridge/composer.json deleted file mode 100644 index 63b072605..000000000 --- a/lib/symfony/twig-bridge/composer.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "name": "symfony/twig-bridge", - "type": "symfony-bridge", - "description": "Provides integration for Twig with various Symfony components", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16", - "symfony/translation-contracts": "^1.1|^2|^3", - "twig/twig": "^2.13|^3.0.4" - }, - "require-dev": { - "doctrine/annotations": "^1.12", - "egulias/email-validator": "^2.1.10|^3", - "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/asset": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/finder": "^4.4|^5.0|^6.0", - "symfony/form": "^5.3|^6.0", - "symfony/http-foundation": "^5.3|^6.0", - "symfony/http-kernel": "^4.4|^5.0|^6.0", - "symfony/intl": "^4.4|^5.0|^6.0", - "symfony/mime": "^5.2|^6.0", - "symfony/polyfill-intl-icu": "~1.0", - "symfony/property-info": "^4.4|^5.1|^6.0", - "symfony/routing": "^4.4|^5.0|^6.0", - "symfony/translation": "^5.2|^6.0", - "symfony/yaml": "^4.4|^5.0|^6.0", - "symfony/security-acl": "^2.8|^3.0", - "symfony/security-core": "^4.4|^5.0|^6.0", - "symfony/security-csrf": "^4.4|^5.0|^6.0", - "symfony/security-http": "^4.4|^5.0|^6.0", - "symfony/serializer": "^5.2|^6.0", - "symfony/stopwatch": "^4.4|^5.0|^6.0", - "symfony/console": "^5.3|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/web-link": "^4.4|^5.0|^6.0", - "symfony/workflow": "^5.2|^6.0", - "twig/cssinliner-extra": "^2.12|^3", - "twig/inky-extra": "^2.12|^3", - "twig/markdown-extra": "^2.12|^3" - }, - "conflict": { - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", - "symfony/console": "<5.3", - "symfony/form": "<5.3", - "symfony/http-foundation": "<5.3", - "symfony/http-kernel": "<4.4", - "symfony/translation": "<5.2", - "symfony/workflow": "<5.2" - }, - "suggest": { - "symfony/finder": "", - "symfony/asset": "For using the AssetExtension", - "symfony/form": "For using the FormExtension", - "symfony/http-kernel": "For using the HttpKernelExtension", - "symfony/routing": "For using the RoutingExtension", - "symfony/translation": "For using the TranslationExtension", - "symfony/yaml": "For using the YamlExtension", - "symfony/security-core": "For using the SecurityExtension", - "symfony/security-csrf": "For using the CsrfExtension", - "symfony/security-http": "For using the LogoutUrlExtension", - "symfony/stopwatch": "For using the StopwatchExtension", - "symfony/var-dumper": "For using the DumpExtension", - "symfony/expression-language": "For using the ExpressionExtension", - "symfony/web-link": "For using the WebLinkExtension" - }, - "autoload": { - "psr-4": { "Symfony\\Bridge\\Twig\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/lib/symfony/twig-bundle/CHANGELOG.md b/lib/symfony/twig-bundle/CHANGELOG.md deleted file mode 100644 index 83a6cccf9..000000000 --- a/lib/symfony/twig-bundle/CHANGELOG.md +++ /dev/null @@ -1,94 +0,0 @@ -CHANGELOG -========= - -5.3 ---- - - * Add support for the new `serialize` filter (from Twig Bridge) - -5.2.0 ------ - - * deprecated the public `twig` service to private - -5.0.0 ------ - - * updated default value for the `strict_variables` option to `%kernel.debug%` parameter - * removed support to load templates from the legacy directories `src/Resources/views/` and `src/Resources/<BundleName>/views/` - * removed `TwigEngine` class, use `Twig\Environment` instead - * removed `FilesystemLoader` and `NativeFilesystemLoader`, use Twig notation for templates instead - * removed `twig.exception_controller` configuration option, use `framework.error_controller` option instead - * removed `ExceptionController`, `PreviewErrorController` and all built-in error templates in favor of the new error renderer mechanism - -4.4.0 ------ - - * marked the `TemplateIterator` as `internal` - * added HTML comment to beginning and end of `exception_full.html.twig` - * deprecated `ExceptionController` and `PreviewErrorController` controllers, use `ErrorController` from the `HttpKernel` component instead - * deprecated all built-in error templates in favor of the new error renderer mechanism - * deprecated `twig.exception_controller` configuration option, set it to "null" and use `framework.error_controller` configuration instead - -4.2.0 ------ - - * deprecated support for legacy templates directories `src/Resources/views/` and `src/Resources/<BundleName>/views/`, use `templates/` and `templates/bundles/<BundleName>/` instead. - -4.1.0 ------ - - * added priority to Twig extensions - * deprecated relying on the default value (`false`) of the `twig.strict_variables` configuration option. The `%kernel.debug%` parameter will be the new default in 5.0 - -4.0.0 ------ - - * removed `ContainerAwareRuntimeLoader` - -3.4.0 ------ - - * added exclusive Twig namespace only for root bundles - * deprecated `Symfony\Bundle\TwigBundle\Command\DebugCommand`, use `Symfony\Bridge\Twig\Command\DebugCommand` instead - * deprecated relying on the `ContainerAwareInterface` implementation for `Symfony\Bundle\TwigBundle\Command\LintCommand` - * added option to configure default path templates (via `default_path`) - -3.3.0 ------ - - * Deprecated `ContainerAwareRuntimeLoader` - -2.7.0 ------ - - * made it possible to configure the default formats for both the `date` and the `number_format` filter - * added support for the new Asset component (from Twig bridge) - * deprecated the assets extension (use the one from the Twig bridge instead) - -2.6.0 ------ - - * [BC BREAK] changed exception.json.twig to match same structure as error.json.twig making clients independent of runtime environment. - -2.3.0 ------ - - * added option to configure a custom template escaping guesser (via `autoescape_service` and `autoescape_service_method`) - -2.2.0 ------ - - * moved the exception controller to be a service (`twig.controller.exception:showAction` vs `Symfony\\Bundle\\TwigBundle\\Controller\\ExceptionController::showAction`) - * added support for multiple loaders via the "twig.loader" tag. - * added automatic registration of namespaced paths for registered bundles - * added support for namespaced paths - -2.1.0 ------ - - * added a new setting ("paths") to configure more paths for the Twig filesystem loader - * added contextual escaping based on the template file name (disabled if you explicitly pass an autoescape option) - * added a command that extracts translation messages from templates - * added the real template name when an error occurs in a Twig template - * added the twig:lint command that will validate a Twig template syntax. diff --git a/lib/symfony/twig-bundle/CacheWarmer/TemplateCacheWarmer.php b/lib/symfony/twig-bundle/CacheWarmer/TemplateCacheWarmer.php deleted file mode 100644 index 4a15dcf2f..000000000 --- a/lib/symfony/twig-bundle/CacheWarmer/TemplateCacheWarmer.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\TwigBundle\CacheWarmer; - -use Psr\Container\ContainerInterface; -use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; -use Symfony\Contracts\Service\ServiceSubscriberInterface; -use Twig\Environment; -use Twig\Error\Error; - -/** - * Generates the Twig cache for all templates. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class TemplateCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInterface -{ - private $container; - private $twig; - private $iterator; - - public function __construct(ContainerInterface $container, iterable $iterator) - { - // As this cache warmer is optional, dependencies should be lazy-loaded, that's why a container should be injected. - $this->container = $container; - $this->iterator = $iterator; - } - - /** - * {@inheritdoc} - * - * @return string[] A list of template files to preload on PHP 7.4+ - */ - public function warmUp(string $cacheDir) - { - if (null === $this->twig) { - $this->twig = $this->container->get('twig'); - } - - $files = []; - - foreach ($this->iterator as $template) { - try { - $template = $this->twig->load($template); - - if (\is_callable([$template, 'unwrap'])) { - $files[] = (new \ReflectionClass($template->unwrap()))->getFileName(); - } - } catch (Error $e) { - /* - * Problem during compilation, give up for this template (e.g. syntax errors). - * Failing silently here allows to ignore templates that rely on functions that aren't available in - * the current environment. For example, the WebProfilerBundle shouldn't be available in the prod - * environment, but some templates that are never used in prod might rely on functions the bundle provides. - * As we can't detect which templates are "really" important, we try to load all of them and ignore - * errors. Error checks may be performed by calling the lint:twig command. - */ - } - } - - return $files; - } - - /** - * {@inheritdoc} - */ - public function isOptional() - { - return true; - } - - /** - * {@inheritdoc} - */ - public static function getSubscribedServices() - { - return [ - 'twig' => Environment::class, - ]; - } -} diff --git a/lib/symfony/twig-bundle/Command/LintCommand.php b/lib/symfony/twig-bundle/Command/LintCommand.php deleted file mode 100644 index a0a52e28a..000000000 --- a/lib/symfony/twig-bundle/Command/LintCommand.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\TwigBundle\Command; - -use Symfony\Bridge\Twig\Command\LintCommand as BaseLintCommand; -use Symfony\Component\Finder\Finder; - -/** - * Command that will validate your template syntax and output encountered errors. - * - * @author Marc Weistroff <marc.weistroff@sensiolabs.com> - * @author Jérôme Tamarelle <jerome@tamarelle.net> - */ -final class LintCommand extends BaseLintCommand -{ - protected static $defaultName = 'lint:twig'; - protected static $defaultDescription = 'Lint a Twig template and outputs encountered errors'; - - /** - * {@inheritdoc} - */ - protected function configure() - { - parent::configure(); - - $this - ->setHelp( - $this->getHelp().<<<'EOF' - -Or all template files in a bundle: - - <info>php %command.full_name% @AcmeDemoBundle</info> - -EOF - ) - ; - } - - protected function findFiles(string $filename): iterable - { - if (str_starts_with($filename, '@')) { - $dir = $this->getApplication()->getKernel()->locateResource($filename); - - return Finder::create()->files()->in($dir)->name('*.twig'); - } - - return parent::findFiles($filename); - } -} diff --git a/lib/symfony/twig-bundle/DependencyInjection/Compiler/ExtensionPass.php b/lib/symfony/twig-bundle/DependencyInjection/Compiler/ExtensionPass.php deleted file mode 100644 index 12724e0f1..000000000 --- a/lib/symfony/twig-bundle/DependencyInjection/Compiler/ExtensionPass.php +++ /dev/null @@ -1,129 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\TwigBundle\DependencyInjection\Compiler; - -use Symfony\Component\Asset\Packages; -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\ExpressionLanguage\Expression; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; -use Symfony\Component\Workflow\Workflow; -use Symfony\Component\Yaml\Yaml; - -/** - * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> - */ -class ExtensionPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container) - { - if (!class_exists(Packages::class)) { - $container->removeDefinition('twig.extension.assets'); - } - - if (!class_exists(Expression::class)) { - $container->removeDefinition('twig.extension.expression'); - } - - if (!interface_exists(UrlGeneratorInterface::class)) { - $container->removeDefinition('twig.extension.routing'); - } - - if (!class_exists(Yaml::class)) { - $container->removeDefinition('twig.extension.yaml'); - } - - $viewDir = \dirname((new \ReflectionClass(\Symfony\Bridge\Twig\Extension\FormExtension::class))->getFileName(), 2).'/Resources/views'; - $templateIterator = $container->getDefinition('twig.template_iterator'); - $templatePaths = $templateIterator->getArgument(1); - $loader = $container->getDefinition('twig.loader.native_filesystem'); - - if ($container->has('mailer')) { - $emailPath = $viewDir.'/Email'; - $loader->addMethodCall('addPath', [$emailPath, 'email']); - $loader->addMethodCall('addPath', [$emailPath, '!email']); - $templatePaths[$emailPath] = 'email'; - } - - if ($container->has('form.extension')) { - $container->getDefinition('twig.extension.form')->addTag('twig.extension'); - - $coreThemePath = $viewDir.'/Form'; - $loader->addMethodCall('addPath', [$coreThemePath]); - $templatePaths[$coreThemePath] = null; - } - - $templateIterator->replaceArgument(1, $templatePaths); - - if ($container->has('router')) { - $container->getDefinition('twig.extension.routing')->addTag('twig.extension'); - } - - if ($container->has('fragment.handler')) { - $container->getDefinition('twig.extension.httpkernel')->addTag('twig.extension'); - $container->getDefinition('twig.runtime.httpkernel')->addTag('twig.runtime'); - - if ($container->hasDefinition('fragment.renderer.hinclude')) { - $container->getDefinition('fragment.renderer.hinclude') - ->addTag('kernel.fragment_renderer', ['alias' => 'hinclude']) - ; - } - } - - if ($container->has('request_stack')) { - $container->getDefinition('twig.extension.httpfoundation')->addTag('twig.extension'); - } - - if ($container->getParameter('kernel.debug')) { - $container->getDefinition('twig.extension.profiler')->addTag('twig.extension'); - - // only register if the improved version from DebugBundle is *not* present - if (!$container->has('twig.extension.dump')) { - $container->getDefinition('twig.extension.debug')->addTag('twig.extension'); - } - } - - if ($container->has('web_link.add_link_header_listener')) { - $container->getDefinition('twig.extension.weblink')->addTag('twig.extension'); - } - - $container->setAlias('twig.loader.filesystem', new Alias('twig.loader.native_filesystem', false)); - - if ($container->has('assets.packages')) { - $container->getDefinition('twig.extension.assets')->addTag('twig.extension'); - } - - if ($container->hasDefinition('twig.extension.yaml')) { - $container->getDefinition('twig.extension.yaml')->addTag('twig.extension'); - } - - if (class_exists(\Symfony\Component\Stopwatch\Stopwatch::class)) { - $container->getDefinition('twig.extension.debug.stopwatch')->addTag('twig.extension'); - } - - if ($container->hasDefinition('twig.extension.expression')) { - $container->getDefinition('twig.extension.expression')->addTag('twig.extension'); - } - - if (!class_exists(Workflow::class) || !$container->has('workflow.registry')) { - $container->removeDefinition('workflow.twig_extension'); - } else { - $container->getDefinition('workflow.twig_extension')->addTag('twig.extension'); - } - - if ($container->has('serializer')) { - $container->getDefinition('twig.runtime.serializer')->addTag('twig.runtime'); - $container->getDefinition('twig.extension.serializer')->addTag('twig.extension'); - } - } -} diff --git a/lib/symfony/twig-bundle/DependencyInjection/Compiler/RuntimeLoaderPass.php b/lib/symfony/twig-bundle/DependencyInjection/Compiler/RuntimeLoaderPass.php deleted file mode 100644 index 82cf1c145..000000000 --- a/lib/symfony/twig-bundle/DependencyInjection/Compiler/RuntimeLoaderPass.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\TwigBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Registers Twig runtime services. - */ -class RuntimeLoaderPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition('twig.runtime_loader')) { - return; - } - - $definition = $container->getDefinition('twig.runtime_loader'); - $mapping = []; - foreach ($container->findTaggedServiceIds('twig.runtime', true) as $id => $attributes) { - $def = $container->getDefinition($id); - $mapping[$def->getClass()] = new Reference($id); - } - - $definition->replaceArgument(0, ServiceLocatorTagPass::register($container, $mapping)); - } -} diff --git a/lib/symfony/twig-bundle/DependencyInjection/Compiler/TwigEnvironmentPass.php b/lib/symfony/twig-bundle/DependencyInjection/Compiler/TwigEnvironmentPass.php deleted file mode 100644 index 45413dc93..000000000 --- a/lib/symfony/twig-bundle/DependencyInjection/Compiler/TwigEnvironmentPass.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\TwigBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * Adds tagged twig.extension services to twig service. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class TwigEnvironmentPass implements CompilerPassInterface -{ - use PriorityTaggedServiceTrait; - - public function process(ContainerBuilder $container) - { - if (false === $container->hasDefinition('twig')) { - return; - } - - $definition = $container->getDefinition('twig'); - - // Extensions must always be registered before everything else. - // For instance, global variable definitions must be registered - // afterward. If not, the globals from the extensions will never - // be registered. - $currentMethodCalls = $definition->getMethodCalls(); - $twigBridgeExtensionsMethodCalls = []; - $othersExtensionsMethodCalls = []; - foreach ($this->findAndSortTaggedServices('twig.extension', $container) as $extension) { - $methodCall = ['addExtension', [$extension]]; - $extensionClass = $container->getDefinition((string) $extension)->getClass(); - - if (\is_string($extensionClass) && str_starts_with($extensionClass, 'Symfony\Bridge\Twig\Extension')) { - $twigBridgeExtensionsMethodCalls[] = $methodCall; - } else { - $othersExtensionsMethodCalls[] = $methodCall; - } - } - - if (!empty($twigBridgeExtensionsMethodCalls) || !empty($othersExtensionsMethodCalls)) { - $definition->setMethodCalls(array_merge($twigBridgeExtensionsMethodCalls, $othersExtensionsMethodCalls, $currentMethodCalls)); - } - } -} diff --git a/lib/symfony/twig-bundle/DependencyInjection/Compiler/TwigLoaderPass.php b/lib/symfony/twig-bundle/DependencyInjection/Compiler/TwigLoaderPass.php deleted file mode 100644 index a422f6682..000000000 --- a/lib/symfony/twig-bundle/DependencyInjection/Compiler/TwigLoaderPass.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\TwigBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\LogicException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Adds services tagged twig.loader as Twig loaders. - * - * @author Daniel Leech <daniel@dantleech.com> - */ -class TwigLoaderPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container) - { - if (false === $container->hasDefinition('twig')) { - return; - } - - $prioritizedLoaders = []; - $found = 0; - - foreach ($container->findTaggedServiceIds('twig.loader', true) as $id => $attributes) { - $priority = $attributes[0]['priority'] ?? 0; - $prioritizedLoaders[$priority][] = $id; - ++$found; - } - - if (!$found) { - throw new LogicException('No twig loaders found. You need to tag at least one loader with "twig.loader".'); - } - - if (1 === $found) { - $container->setAlias('twig.loader', $id); - } else { - $chainLoader = $container->getDefinition('twig.loader.chain'); - krsort($prioritizedLoaders); - - foreach ($prioritizedLoaders as $loaders) { - foreach ($loaders as $loader) { - $chainLoader->addMethodCall('addLoader', [new Reference($loader)]); - } - } - - $container->setAlias('twig.loader', 'twig.loader.chain'); - } - } -} diff --git a/lib/symfony/twig-bundle/DependencyInjection/Configuration.php b/lib/symfony/twig-bundle/DependencyInjection/Configuration.php deleted file mode 100644 index 76faa0107..000000000 --- a/lib/symfony/twig-bundle/DependencyInjection/Configuration.php +++ /dev/null @@ -1,206 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\TwigBundle\DependencyInjection; - -use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; -use Symfony\Component\Config\Definition\Builder\TreeBuilder; -use Symfony\Component\Config\Definition\ConfigurationInterface; -use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; - -/** - * TwigExtension configuration structure. - * - * @author Jeremy Mikola <jmikola@gmail.com> - */ -class Configuration implements ConfigurationInterface -{ - /** - * Generates the configuration tree builder. - * - * @return TreeBuilder - */ - public function getConfigTreeBuilder() - { - $treeBuilder = new TreeBuilder('twig'); - $rootNode = $treeBuilder->getRootNode(); - - $rootNode->beforeNormalization() - ->ifTrue(function ($v) { return \is_array($v) && \array_key_exists('exception_controller', $v); }) - ->then(function ($v) { - if (isset($v['exception_controller'])) { - throw new InvalidConfigurationException('Option "exception_controller" under "twig" must be null or unset, use "error_controller" under "framework" instead.'); - } - - unset($v['exception_controller']); - - return $v; - }) - ->end(); - - $this->addFormThemesSection($rootNode); - $this->addGlobalsSection($rootNode); - $this->addTwigOptions($rootNode); - $this->addTwigFormatOptions($rootNode); - - return $treeBuilder; - } - - private function addFormThemesSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->fixXmlConfig('form_theme') - ->children() - ->arrayNode('form_themes') - ->addDefaultChildrenIfNoneSet() - ->prototype('scalar')->defaultValue('form_div_layout.html.twig')->end() - ->example(['@My/form.html.twig']) - ->validate() - ->ifTrue(function ($v) { return !\in_array('form_div_layout.html.twig', $v); }) - ->then(function ($v) { - return array_merge(['form_div_layout.html.twig'], $v); - }) - ->end() - ->end() - ->end() - ; - } - - private function addGlobalsSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->fixXmlConfig('global') - ->children() - ->arrayNode('globals') - ->normalizeKeys(false) - ->useAttributeAsKey('key') - ->example(['foo' => '@bar', 'pi' => 3.14]) - ->prototype('array') - ->normalizeKeys(false) - ->beforeNormalization() - ->ifTrue(function ($v) { return \is_string($v) && str_starts_with($v, '@'); }) - ->then(function ($v) { - if (str_starts_with($v, '@@')) { - return substr($v, 1); - } - - return ['id' => substr($v, 1), 'type' => 'service']; - }) - ->end() - ->beforeNormalization() - ->ifTrue(function ($v) { - if (\is_array($v)) { - $keys = array_keys($v); - sort($keys); - - return $keys !== ['id', 'type'] && $keys !== ['value']; - } - - return true; - }) - ->then(function ($v) { return ['value' => $v]; }) - ->end() - ->children() - ->scalarNode('id')->end() - ->scalarNode('type') - ->validate() - ->ifNotInArray(['service']) - ->thenInvalid('The %s type is not supported') - ->end() - ->end() - ->variableNode('value')->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addTwigOptions(ArrayNodeDefinition $rootNode) - { - $rootNode - ->fixXmlConfig('path') - ->children() - ->variableNode('autoescape')->defaultValue('name')->end() - ->scalarNode('autoescape_service')->defaultNull()->end() - ->scalarNode('autoescape_service_method')->defaultNull()->end() - ->scalarNode('base_template_class')->example('Twig\Template')->cannotBeEmpty()->end() - ->scalarNode('cache')->defaultValue('%kernel.cache_dir%/twig')->end() - ->scalarNode('charset')->defaultValue('%kernel.charset%')->end() - ->booleanNode('debug')->defaultValue('%kernel.debug%')->end() - ->booleanNode('strict_variables')->defaultValue('%kernel.debug%')->end() - ->scalarNode('auto_reload')->end() - ->integerNode('optimizations')->min(-1)->end() - ->scalarNode('default_path') - ->info('The default path used to load templates') - ->defaultValue('%kernel.project_dir%/templates') - ->end() - ->arrayNode('paths') - ->normalizeKeys(false) - ->useAttributeAsKey('paths') - ->beforeNormalization() - ->always() - ->then(function ($paths) { - $normalized = []; - foreach ($paths as $path => $namespace) { - if (\is_array($namespace)) { - // xml - $path = $namespace['value']; - $namespace = $namespace['namespace']; - } - - // path within the default namespace - if (ctype_digit((string) $path)) { - $path = $namespace; - $namespace = null; - } - - $normalized[$path] = $namespace; - } - - return $normalized; - }) - ->end() - ->prototype('variable')->end() - ->end() - ->end() - ; - } - - private function addTwigFormatOptions(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('date') - ->info('The default format options used by the date filter') - ->addDefaultsIfNotSet() - ->children() - ->scalarNode('format')->defaultValue('F j, Y H:i')->end() - ->scalarNode('interval_format')->defaultValue('%d days')->end() - ->scalarNode('timezone') - ->info('The timezone used when formatting dates, when set to null, the timezone returned by date_default_timezone_get() is used') - ->defaultNull() - ->end() - ->end() - ->end() - ->arrayNode('number_format') - ->info('The default format options for the number_format filter') - ->addDefaultsIfNotSet() - ->children() - ->integerNode('decimals')->defaultValue(0)->end() - ->scalarNode('decimal_point')->defaultValue('.')->end() - ->scalarNode('thousands_separator')->defaultValue(',')->end() - ->end() - ->end() - ->end() - ; - } -} diff --git a/lib/symfony/twig-bundle/DependencyInjection/Configurator/EnvironmentConfigurator.php b/lib/symfony/twig-bundle/DependencyInjection/Configurator/EnvironmentConfigurator.php deleted file mode 100644 index 07ec69176..000000000 --- a/lib/symfony/twig-bundle/DependencyInjection/Configurator/EnvironmentConfigurator.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\TwigBundle\DependencyInjection\Configurator; - -use Symfony\Bridge\Twig\UndefinedCallableHandler; -use Twig\Environment; - -// BC/FC with namespaced Twig -class_exists(Environment::class); - -/** - * Twig environment configurator. - * - * @author Christian Flothmann <christian.flothmann@xabbuh.de> - */ -class EnvironmentConfigurator -{ - private $dateFormat; - private $intervalFormat; - private $timezone; - private $decimals; - private $decimalPoint; - private $thousandsSeparator; - - public function __construct(string $dateFormat, string $intervalFormat, ?string $timezone, int $decimals, string $decimalPoint, string $thousandsSeparator) - { - $this->dateFormat = $dateFormat; - $this->intervalFormat = $intervalFormat; - $this->timezone = $timezone; - $this->decimals = $decimals; - $this->decimalPoint = $decimalPoint; - $this->thousandsSeparator = $thousandsSeparator; - } - - public function configure(Environment $environment) - { - $environment->getExtension('Twig\Extension\CoreExtension')->setDateFormat($this->dateFormat, $this->intervalFormat); - - if (null !== $this->timezone) { - $environment->getExtension('Twig\Extension\CoreExtension')->setTimezone($this->timezone); - } - - $environment->getExtension('Twig\Extension\CoreExtension')->setNumberFormat($this->decimals, $this->decimalPoint, $this->thousandsSeparator); - - // wrap UndefinedCallableHandler in closures for lazy-autoloading - $environment->registerUndefinedFilterCallback(function ($name) { return UndefinedCallableHandler::onUndefinedFilter($name); }); - $environment->registerUndefinedFunctionCallback(function ($name) { return UndefinedCallableHandler::onUndefinedFunction($name); }); - } -} diff --git a/lib/symfony/twig-bundle/DependencyInjection/TwigExtension.php b/lib/symfony/twig-bundle/DependencyInjection/TwigExtension.php deleted file mode 100644 index 4cec78064..000000000 --- a/lib/symfony/twig-bundle/DependencyInjection/TwigExtension.php +++ /dev/null @@ -1,208 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\TwigBundle\DependencyInjection; - -use Composer\InstalledVersions; -use Symfony\Component\Config\FileLocator; -use Symfony\Component\Config\Resource\FileExistenceResource; -use Symfony\Component\Console\Application; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\Form\AbstractRendererEngine; -use Symfony\Component\Form\Form; -use Symfony\Component\HttpKernel\DependencyInjection\Extension; -use Symfony\Component\Mailer\Mailer; -use Symfony\Component\Translation\Translator; -use Symfony\Contracts\Service\ResetInterface; -use Twig\Extension\ExtensionInterface; -use Twig\Extension\RuntimeExtensionInterface; -use Twig\Loader\LoaderInterface; - -/** - * TwigExtension. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Jeremy Mikola <jmikola@gmail.com> - */ -class TwigExtension extends Extension -{ - public function load(array $configs, ContainerBuilder $container) - { - if (!class_exists(InstalledVersions::class)) { - trigger_deprecation('symfony/twig-bundle', '5.4', 'Configuring Symfony without the Composer Runtime API is deprecated. Consider upgrading to Composer 2.1 or later.'); - } - - $loader = new PhpFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); - $loader->load('twig.php'); - - if ($container::willBeAvailable('symfony/form', Form::class, ['symfony/twig-bundle'], true)) { - $loader->load('form.php'); - - if (is_subclass_of(AbstractRendererEngine::class, ResetInterface::class)) { - $container->getDefinition('twig.form.engine')->addTag('kernel.reset', [ - 'method' => 'reset', - ]); - } - } - - if ($container::willBeAvailable('symfony/console', Application::class, ['symfony/twig-bundle'], true)) { - $loader->load('console.php'); - } - - if ($container::willBeAvailable('symfony/mailer', Mailer::class, ['symfony/twig-bundle'], true)) { - $loader->load('mailer.php'); - } - - if (!$container::willBeAvailable('symfony/translation', Translator::class, ['symfony/twig-bundle'], true)) { - $container->removeDefinition('twig.translation.extractor'); - } - - foreach ($configs as $key => $config) { - if (isset($config['globals'])) { - foreach ($config['globals'] as $name => $value) { - if (\is_array($value) && isset($value['key'])) { - $configs[$key]['globals'][$name] = [ - 'key' => $name, - 'value' => $value, - ]; - } - } - } - } - - $configuration = $this->getConfiguration($configs, $container); - - $config = $this->processConfiguration($configuration, $configs); - - $container->setParameter('twig.form.resources', $config['form_themes']); - $container->setParameter('twig.default_path', $config['default_path']); - $defaultTwigPath = $container->getParameterBag()->resolveValue($config['default_path']); - - $envConfiguratorDefinition = $container->getDefinition('twig.configurator.environment'); - $envConfiguratorDefinition->replaceArgument(0, $config['date']['format']); - $envConfiguratorDefinition->replaceArgument(1, $config['date']['interval_format']); - $envConfiguratorDefinition->replaceArgument(2, $config['date']['timezone']); - $envConfiguratorDefinition->replaceArgument(3, $config['number_format']['decimals']); - $envConfiguratorDefinition->replaceArgument(4, $config['number_format']['decimal_point']); - $envConfiguratorDefinition->replaceArgument(5, $config['number_format']['thousands_separator']); - - $twigFilesystemLoaderDefinition = $container->getDefinition('twig.loader.native_filesystem'); - - // register user-configured paths - foreach ($config['paths'] as $path => $namespace) { - if (!$namespace) { - $twigFilesystemLoaderDefinition->addMethodCall('addPath', [$path]); - } else { - $twigFilesystemLoaderDefinition->addMethodCall('addPath', [$path, $namespace]); - } - } - - // paths are modified in ExtensionPass if forms are enabled - $container->getDefinition('twig.template_iterator')->replaceArgument(1, $config['paths']); - - foreach ($this->getBundleTemplatePaths($container, $config) as $name => $paths) { - $namespace = $this->normalizeBundleName($name); - foreach ($paths as $path) { - $twigFilesystemLoaderDefinition->addMethodCall('addPath', [$path, $namespace]); - } - - if ($paths) { - // the last path must be the bundle views directory - $twigFilesystemLoaderDefinition->addMethodCall('addPath', [$path, '!'.$namespace]); - } - } - - if (file_exists($defaultTwigPath)) { - $twigFilesystemLoaderDefinition->addMethodCall('addPath', [$defaultTwigPath]); - } - $container->addResource(new FileExistenceResource($defaultTwigPath)); - - if (!empty($config['globals'])) { - $def = $container->getDefinition('twig'); - foreach ($config['globals'] as $key => $global) { - if (isset($global['type']) && 'service' === $global['type']) { - $def->addMethodCall('addGlobal', [$key, new Reference($global['id'])]); - } else { - $def->addMethodCall('addGlobal', [$key, $global['value']]); - } - } - } - - if (isset($config['autoescape_service']) && isset($config['autoescape_service_method'])) { - $config['autoescape'] = [new Reference($config['autoescape_service']), $config['autoescape_service_method']]; - } - - $container->getDefinition('twig')->replaceArgument(1, array_intersect_key($config, [ - 'debug' => true, - 'charset' => true, - 'base_template_class' => true, - 'strict_variables' => true, - 'autoescape' => true, - 'cache' => true, - 'auto_reload' => true, - 'optimizations' => true, - ])); - - $container->registerForAutoconfiguration(\Twig_ExtensionInterface::class)->addTag('twig.extension'); - $container->registerForAutoconfiguration(\Twig_LoaderInterface::class)->addTag('twig.loader'); - $container->registerForAutoconfiguration(ExtensionInterface::class)->addTag('twig.extension'); - $container->registerForAutoconfiguration(LoaderInterface::class)->addTag('twig.loader'); - $container->registerForAutoconfiguration(RuntimeExtensionInterface::class)->addTag('twig.runtime'); - - if (false === $config['cache']) { - $container->removeDefinition('twig.template_cache_warmer'); - } - } - - private function getBundleTemplatePaths(ContainerBuilder $container, array $config): array - { - $bundleHierarchy = []; - foreach ($container->getParameter('kernel.bundles_metadata') as $name => $bundle) { - $defaultOverrideBundlePath = $container->getParameterBag()->resolveValue($config['default_path']).'/bundles/'.$name; - - if (file_exists($defaultOverrideBundlePath)) { - $bundleHierarchy[$name][] = $defaultOverrideBundlePath; - } - $container->addResource(new FileExistenceResource($defaultOverrideBundlePath)); - - if (file_exists($dir = $bundle['path'].'/Resources/views') || file_exists($dir = $bundle['path'].'/templates')) { - $bundleHierarchy[$name][] = $dir; - } - $container->addResource(new FileExistenceResource($dir)); - } - - return $bundleHierarchy; - } - - private function normalizeBundleName(string $name): string - { - if (str_ends_with($name, 'Bundle')) { - $name = substr($name, 0, -6); - } - - return $name; - } - - /** - * {@inheritdoc} - */ - public function getXsdValidationBasePath() - { - return __DIR__.'/../Resources/config/schema'; - } - - public function getNamespace() - { - return 'http://symfony.com/schema/dic/twig'; - } -} diff --git a/lib/symfony/twig-bundle/LICENSE b/lib/symfony/twig-bundle/LICENSE deleted file mode 100644 index 008370457..000000000 --- a/lib/symfony/twig-bundle/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -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/lib/symfony/twig-bundle/README.md b/lib/symfony/twig-bundle/README.md deleted file mode 100644 index 3ae2985ba..000000000 --- a/lib/symfony/twig-bundle/README.md +++ /dev/null @@ -1,13 +0,0 @@ -TwigBundle -========== - -TwigBundle provides a tight integration of Twig into the Symfony full-stack -framework. - -Resources ---------- - - * [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/lib/symfony/twig-bundle/Resources/config/console.php b/lib/symfony/twig-bundle/Resources/config/console.php deleted file mode 100644 index 0dc7ebdb7..000000000 --- a/lib/symfony/twig-bundle/Resources/config/console.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Bridge\Twig\Command\DebugCommand; -use Symfony\Bundle\TwigBundle\Command\LintCommand; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('twig.command.debug', DebugCommand::class) - ->args([ - service('twig'), - param('kernel.project_dir'), - param('kernel.bundles_metadata'), - param('twig.default_path'), - service('debug.file_link_formatter')->nullOnInvalid(), - ]) - ->tag('console.command') - - ->set('twig.command.lint', LintCommand::class) - ->args([service('twig')]) - ->tag('console.command') - ; -}; diff --git a/lib/symfony/twig-bundle/Resources/config/form.php b/lib/symfony/twig-bundle/Resources/config/form.php deleted file mode 100644 index 9f2efdf94..000000000 --- a/lib/symfony/twig-bundle/Resources/config/form.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Bridge\Twig\Extension\FormExtension; -use Symfony\Bridge\Twig\Form\TwigRendererEngine; -use Symfony\Component\Form\FormRenderer; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('twig.extension.form', FormExtension::class) - ->args([service('translator')->nullOnInvalid()]) - - ->set('twig.form.engine', TwigRendererEngine::class) - ->args([param('twig.form.resources'), service('twig')]) - - ->set('twig.form.renderer', FormRenderer::class) - ->args([service('twig.form.engine'), service('security.csrf.token_manager')->nullOnInvalid()]) - ->tag('twig.runtime') - ; -}; diff --git a/lib/symfony/twig-bundle/Resources/config/mailer.php b/lib/symfony/twig-bundle/Resources/config/mailer.php deleted file mode 100644 index 1444481f2..000000000 --- a/lib/symfony/twig-bundle/Resources/config/mailer.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Bridge\Twig\Mime\BodyRenderer; -use Symfony\Component\Mailer\EventListener\MessageListener; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('twig.mailer.message_listener', MessageListener::class) - ->args([null, service('twig.mime_body_renderer')]) - ->tag('kernel.event_subscriber') - - ->set('twig.mime_body_renderer', BodyRenderer::class) - ->args([service('twig')]) - ; -}; diff --git a/lib/symfony/twig-bundle/Resources/config/schema/twig-1.0.xsd b/lib/symfony/twig-bundle/Resources/config/schema/twig-1.0.xsd deleted file mode 100644 index 429c91db6..000000000 --- a/lib/symfony/twig-bundle/Resources/config/schema/twig-1.0.xsd +++ /dev/null @@ -1,58 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> - -<xsd:schema xmlns="http://symfony.com/schema/dic/twig" - xmlns:xsd="http://www.w3.org/2001/XMLSchema" - targetNamespace="http://symfony.com/schema/dic/twig" - elementFormDefault="qualified"> - - <xsd:element name="config" type="config" /> - - <xsd:complexType name="config"> - <xsd:sequence> - <xsd:element name="date" type="date" minOccurs="0" maxOccurs="1" /> - <xsd:element name="number-format" type="number_format" minOccurs="0" maxOccurs="1" /> - <xsd:element name="form-theme" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="global" type="global" minOccurs="0" maxOccurs="unbounded" /> - <xsd:element name="path" type="path" minOccurs="0" maxOccurs="unbounded" /> - </xsd:sequence> - - <xsd:attribute name="auto-reload" type="xsd:string" /> - <xsd:attribute name="autoescape" type="xsd:string" /> - <xsd:attribute name="autoescape-service" type="xsd:string" /> - <xsd:attribute name="autoescape-service-method" type="xsd:string" /> - <xsd:attribute name="base-template-class" type="xsd:string" /> - <xsd:attribute name="cache" type="xsd:string" /> - <xsd:attribute name="charset" type="xsd:string" /> - <xsd:attribute name="debug" type="xsd:string" /> - <xsd:attribute name="strict-variables" type="xsd:string" /> - <xsd:attribute name="default-path" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="date"> - <xsd:attribute name="format" type="xsd:string" /> - <xsd:attribute name="interval-format" type="xsd:string" /> - <xsd:attribute name="timezone" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="number_format"> - <xsd:attribute name="decimals" type="xsd:integer" /> - <xsd:attribute name="decimal-point" type="xsd:string" /> - <xsd:attribute name="thousands-separator" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="path" mixed="true"> - <xsd:attribute name="namespace" type="xsd:string" /> - </xsd:complexType> - - <xsd:complexType name="global" mixed="true"> - <xsd:attribute name="key" type="xsd:string" use="required" /> - <xsd:attribute name="type" type="global_type" /> - <xsd:attribute name="id" type="xsd:string" /> - </xsd:complexType> - - <xsd:simpleType name="global_type"> - <xsd:restriction base="xsd:string"> - <xsd:enumeration value="service" /> - </xsd:restriction> - </xsd:simpleType> -</xsd:schema> diff --git a/lib/symfony/twig-bundle/Resources/config/twig.php b/lib/symfony/twig-bundle/Resources/config/twig.php deleted file mode 100644 index 3bc7f66fa..000000000 --- a/lib/symfony/twig-bundle/Resources/config/twig.php +++ /dev/null @@ -1,171 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Psr\Container\ContainerInterface; -use Symfony\Bridge\Twig\AppVariable; -use Symfony\Bridge\Twig\DataCollector\TwigDataCollector; -use Symfony\Bridge\Twig\ErrorRenderer\TwigErrorRenderer; -use Symfony\Bridge\Twig\Extension\AssetExtension; -use Symfony\Bridge\Twig\Extension\CodeExtension; -use Symfony\Bridge\Twig\Extension\ExpressionExtension; -use Symfony\Bridge\Twig\Extension\HttpFoundationExtension; -use Symfony\Bridge\Twig\Extension\HttpKernelExtension; -use Symfony\Bridge\Twig\Extension\HttpKernelRuntime; -use Symfony\Bridge\Twig\Extension\ProfilerExtension; -use Symfony\Bridge\Twig\Extension\RoutingExtension; -use Symfony\Bridge\Twig\Extension\SerializerExtension; -use Symfony\Bridge\Twig\Extension\SerializerRuntime; -use Symfony\Bridge\Twig\Extension\StopwatchExtension; -use Symfony\Bridge\Twig\Extension\TranslationExtension; -use Symfony\Bridge\Twig\Extension\WebLinkExtension; -use Symfony\Bridge\Twig\Extension\WorkflowExtension; -use Symfony\Bridge\Twig\Extension\YamlExtension; -use Symfony\Bridge\Twig\Translation\TwigExtractor; -use Symfony\Bundle\TwigBundle\CacheWarmer\TemplateCacheWarmer; -use Symfony\Bundle\TwigBundle\DependencyInjection\Configurator\EnvironmentConfigurator; -use Symfony\Bundle\TwigBundle\TemplateIterator; -use Twig\Cache\FilesystemCache; -use Twig\Environment; -use Twig\Extension\CoreExtension; -use Twig\Extension\DebugExtension; -use Twig\Extension\EscaperExtension; -use Twig\Extension\OptimizerExtension; -use Twig\Extension\StagingExtension; -use Twig\ExtensionSet; -use Twig\Loader\ChainLoader; -use Twig\Loader\FilesystemLoader; -use Twig\Profiler\Profile; -use Twig\RuntimeLoader\ContainerRuntimeLoader; -use Twig\Template; -use Twig\TemplateWrapper; - -return static function (ContainerConfigurator $container) { - $container->services() - ->set('twig', Environment::class) - ->public() - ->args([service('twig.loader'), abstract_arg('Twig options')]) - ->call('addGlobal', ['app', service('twig.app_variable')]) - ->call('addRuntimeLoader', [service('twig.runtime_loader')]) - ->configurator([service('twig.configurator.environment'), 'configure']) - ->tag('container.preload', ['class' => FilesystemCache::class]) - ->tag('container.preload', ['class' => CoreExtension::class]) - ->tag('container.preload', ['class' => EscaperExtension::class]) - ->tag('container.preload', ['class' => OptimizerExtension::class]) - ->tag('container.preload', ['class' => StagingExtension::class]) - ->tag('container.preload', ['class' => ExtensionSet::class]) - ->tag('container.preload', ['class' => Template::class]) - ->tag('container.preload', ['class' => TemplateWrapper::class]) - ->tag('container.private', ['package' => 'symfony/twig-bundle', 'version' => '5.2']) - - ->alias('Twig_Environment', 'twig') - ->alias(Environment::class, 'twig') - - ->set('twig.app_variable', AppVariable::class) - ->call('setEnvironment', [param('kernel.environment')]) - ->call('setDebug', [param('kernel.debug')]) - ->call('setTokenStorage', [service('security.token_storage')->ignoreOnInvalid()]) - ->call('setRequestStack', [service('request_stack')->ignoreOnInvalid()]) - - ->set('twig.template_iterator', TemplateIterator::class) - ->args([service('kernel'), abstract_arg('Twig paths'), param('twig.default_path')]) - - ->set('twig.template_cache_warmer', TemplateCacheWarmer::class) - ->args([service(ContainerInterface::class), service('twig.template_iterator')]) - ->tag('kernel.cache_warmer') - ->tag('container.service_subscriber', ['id' => 'twig']) - - ->set('twig.loader.native_filesystem', FilesystemLoader::class) - ->args([[], param('kernel.project_dir')]) - ->tag('twig.loader') - - ->set('twig.loader.chain', ChainLoader::class) - - ->set('twig.extension.profiler', ProfilerExtension::class) - ->args([service('twig.profile'), service('debug.stopwatch')->ignoreOnInvalid()]) - - ->set('twig.profile', Profile::class) - - ->set('data_collector.twig', TwigDataCollector::class) - ->args([service('twig.profile'), service('twig')]) - ->tag('data_collector', ['template' => '@WebProfiler/Collector/twig.html.twig', 'id' => 'twig', 'priority' => 257]) - - ->set('twig.extension.trans', TranslationExtension::class) - ->args([service('translator')->nullOnInvalid()]) - ->tag('twig.extension') - - ->set('twig.extension.assets', AssetExtension::class) - ->args([service('assets.packages')]) - - ->set('twig.extension.code', CodeExtension::class) - ->args([service('debug.file_link_formatter')->ignoreOnInvalid(), param('kernel.project_dir'), param('kernel.charset')]) - ->tag('twig.extension') - - ->set('twig.extension.routing', RoutingExtension::class) - ->args([service('router')]) - - ->set('twig.extension.yaml', YamlExtension::class) - - ->set('twig.extension.debug.stopwatch', StopwatchExtension::class) - ->args([service('debug.stopwatch')->ignoreOnInvalid(), param('kernel.debug')]) - - ->set('twig.extension.expression', ExpressionExtension::class) - - ->set('twig.extension.httpkernel', HttpKernelExtension::class) - - ->set('twig.runtime.httpkernel', HttpKernelRuntime::class) - ->args([service('fragment.handler'), service('fragment.uri_generator')->ignoreOnInvalid()]) - - ->set('twig.extension.httpfoundation', HttpFoundationExtension::class) - ->args([service('url_helper')]) - - ->set('twig.extension.debug', DebugExtension::class) - - ->set('twig.extension.weblink', WebLinkExtension::class) - ->args([service('request_stack')]) - - ->set('twig.translation.extractor', TwigExtractor::class) - ->args([service('twig')]) - ->tag('translation.extractor', ['alias' => 'twig']) - - ->set('workflow.twig_extension', WorkflowExtension::class) - ->args([service('workflow.registry')]) - - ->set('twig.configurator.environment', EnvironmentConfigurator::class) - ->args([ - abstract_arg('date format, set in TwigExtension'), - abstract_arg('interval format, set in TwigExtension'), - abstract_arg('timezone, set in TwigExtension'), - abstract_arg('decimals, set in TwigExtension'), - abstract_arg('decimal point, set in TwigExtension'), - abstract_arg('thousands separator, set in TwigExtension'), - ]) - - ->set('twig.runtime_loader', ContainerRuntimeLoader::class) - ->args([abstract_arg('runtime locator')]) - - ->set('twig.error_renderer.html', TwigErrorRenderer::class) - ->decorate('error_renderer.html') - ->args([ - service('twig'), - service('twig.error_renderer.html.inner'), - inline_service('bool') - ->factory([TwigErrorRenderer::class, 'isDebug']) - ->args([service('request_stack'), param('kernel.debug')]), - ]) - - ->set('twig.runtime.serializer', SerializerRuntime::class) - ->args([service('serializer')]) - - ->set('twig.extension.serializer', SerializerExtension::class) - ; -}; diff --git a/lib/symfony/twig-bundle/TemplateIterator.php b/lib/symfony/twig-bundle/TemplateIterator.php deleted file mode 100644 index 8cc0ffc4d..000000000 --- a/lib/symfony/twig-bundle/TemplateIterator.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\TwigBundle; - -use Symfony\Component\Finder\Finder; -use Symfony\Component\HttpKernel\KernelInterface; - -/** - * Iterator for all templates in bundles and in the application Resources directory. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @internal - * - * @implements \IteratorAggregate<int, string> - */ -class TemplateIterator implements \IteratorAggregate -{ - private $kernel; - private $templates; - private $paths; - private $defaultPath; - - /** - * @param array $paths Additional Twig paths to warm - * @param string|null $defaultPath The directory where global templates can be stored - */ - public function __construct(KernelInterface $kernel, array $paths = [], string $defaultPath = null) - { - $this->kernel = $kernel; - $this->paths = $paths; - $this->defaultPath = $defaultPath; - } - - public function getIterator(): \Traversable - { - if (null !== $this->templates) { - return $this->templates; - } - - $templates = null !== $this->defaultPath ? [$this->findTemplatesInDirectory($this->defaultPath, null, ['bundles'])] : []; - - foreach ($this->kernel->getBundles() as $bundle) { - $name = $bundle->getName(); - if (str_ends_with($name, 'Bundle')) { - $name = substr($name, 0, -6); - } - - $bundleTemplatesDir = is_dir($bundle->getPath().'/Resources/views') ? $bundle->getPath().'/Resources/views' : $bundle->getPath().'/templates'; - - $templates[] = $this->findTemplatesInDirectory($bundleTemplatesDir, $name); - if (null !== $this->defaultPath) { - $templates[] = $this->findTemplatesInDirectory($this->defaultPath.'/bundles/'.$bundle->getName(), $name); - } - } - - foreach ($this->paths as $dir => $namespace) { - $templates[] = $this->findTemplatesInDirectory($dir, $namespace); - } - - return $this->templates = new \ArrayIterator(array_unique(array_merge([], ...$templates))); - } - - /** - * Find templates in the given directory. - * - * @return string[] - */ - private function findTemplatesInDirectory(string $dir, string $namespace = null, array $excludeDirs = []): array - { - if (!is_dir($dir)) { - return []; - } - - $templates = []; - foreach (Finder::create()->files()->followLinks()->in($dir)->exclude($excludeDirs) as $file) { - $templates[] = (null !== $namespace ? '@'.$namespace.'/' : '').str_replace('\\', '/', $file->getRelativePathname()); - } - - return $templates; - } -} diff --git a/lib/symfony/twig-bundle/TwigBundle.php b/lib/symfony/twig-bundle/TwigBundle.php deleted file mode 100644 index 3910dd5e2..000000000 --- a/lib/symfony/twig-bundle/TwigBundle.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\TwigBundle; - -use Symfony\Bundle\TwigBundle\DependencyInjection\Compiler\ExtensionPass; -use Symfony\Bundle\TwigBundle\DependencyInjection\Compiler\RuntimeLoaderPass; -use Symfony\Bundle\TwigBundle\DependencyInjection\Compiler\TwigEnvironmentPass; -use Symfony\Bundle\TwigBundle\DependencyInjection\Compiler\TwigLoaderPass; -use Symfony\Component\Console\Application; -use Symfony\Component\DependencyInjection\Compiler\PassConfig; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\HttpKernel\Bundle\Bundle; - -/** - * Bundle. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class TwigBundle extends Bundle -{ - public function build(ContainerBuilder $container) - { - parent::build($container); - - // ExtensionPass must be run before the FragmentRendererPass as it adds tags that are processed later - $container->addCompilerPass(new ExtensionPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 10); - $container->addCompilerPass(new TwigEnvironmentPass()); - $container->addCompilerPass(new TwigLoaderPass()); - $container->addCompilerPass(new RuntimeLoaderPass(), PassConfig::TYPE_BEFORE_REMOVING); - } - - public function registerCommands(Application $application) - { - // noop - } -} diff --git a/lib/symfony/twig-bundle/composer.json b/lib/symfony/twig-bundle/composer.json deleted file mode 100644 index a92b08930..000000000 --- a/lib/symfony/twig-bundle/composer.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "name": "symfony/twig-bundle", - "type": "symfony-bundle", - "description": "Provides a tight integration of Twig into the Symfony full-stack framework", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/twig-bridge": "^5.3|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", - "symfony/http-kernel": "^5.0|^6.0", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-php80": "^1.16", - "twig/twig": "^2.13|^3.0.4" - }, - "require-dev": { - "symfony/asset": "^4.4|^5.0|^6.0", - "symfony/stopwatch": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^5.3|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/finder": "^4.4|^5.0|^6.0", - "symfony/form": "^4.4|^5.0|^6.0", - "symfony/routing": "^4.4|^5.0|^6.0", - "symfony/translation": "^5.0|^6.0", - "symfony/yaml": "^4.4|^5.0|^6.0", - "symfony/framework-bundle": "^5.0|^6.0", - "symfony/web-link": "^4.4|^5.0|^6.0", - "doctrine/annotations": "^1.10.4|^2", - "doctrine/cache": "^1.0|^2.0" - }, - "conflict": { - "symfony/dependency-injection": "<5.3", - "symfony/framework-bundle": "<5.0", - "symfony/service-contracts": ">=3.0", - "symfony/translation": "<5.0" - }, - "autoload": { - "psr-4": { "Symfony\\Bundle\\TwigBundle\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/lib/symfony/var-dumper/CHANGELOG.md b/lib/symfony/var-dumper/CHANGELOG.md deleted file mode 100644 index f58ed3170..000000000 --- a/lib/symfony/var-dumper/CHANGELOG.md +++ /dev/null @@ -1,72 +0,0 @@ -CHANGELOG -========= - -5.4 ---- - - * Add ability to style integer and double values independently - * Add casters for Symfony's UUIDs and ULIDs - * Add support for `Fiber` - -5.2.0 ------ - - * added support for PHPUnit `--colors` option - * added `VAR_DUMPER_FORMAT=server` env var value support - * prevent replacing the handler when the `VAR_DUMPER_FORMAT` env var is set - -5.1.0 ------ - - * added `RdKafka` support - -4.4.0 ------ - - * added `VarDumperTestTrait::setUpVarDumper()` and `VarDumperTestTrait::tearDownVarDumper()` - to configure casters & flags to use in tests - * added `ImagineCaster` and infrastructure to dump images - * added the stamps of a message after it is dispatched in `TraceableMessageBus` and `MessengerDataCollector` collected data - * added `UuidCaster` - * made all casters final - * added support for the `NO_COLOR` env var (https://no-color.org/) - -4.3.0 ------ - - * added `DsCaster` to support dumping the contents of data structures from the Ds extension - -4.2.0 ------ - - * support selecting the format to use by setting the environment variable `VAR_DUMPER_FORMAT` to `html` or `cli` - -4.1.0 ------ - - * added a `ServerDumper` to send serialized Data clones to a server - * added a `ServerDumpCommand` and `DumpServer` to run a server collecting - and displaying dumps on a single place with multiple formats support - * added `CliDescriptor` and `HtmlDescriptor` descriptors for `server:dump` CLI and HTML formats support - -4.0.0 ------ - - * support for passing `\ReflectionClass` instances to the `Caster::castObject()` - method has been dropped, pass class names as strings instead - * the `Data::getRawData()` method has been removed - * the `VarDumperTestTrait::assertDumpEquals()` method expects a 3rd `$filter = 0` - argument and moves `$message = ''` argument at 4th position. - * the `VarDumperTestTrait::assertDumpMatchesFormat()` method expects a 3rd `$filter = 0` - argument and moves `$message = ''` argument at 4th position. - -3.4.0 ------ - - * added `AbstractCloner::setMinDepth()` function to ensure minimum tree depth - * deprecated `MongoCaster` - -2.7.0 ------ - - * deprecated `Cloner\Data::getLimitedClone()`. Use `withMaxDepth`, `withMaxItemsPerDepth` or `withRefHandles` instead. diff --git a/lib/symfony/var-dumper/Caster/AmqpCaster.php b/lib/symfony/var-dumper/Caster/AmqpCaster.php deleted file mode 100644 index dc3b62198..000000000 --- a/lib/symfony/var-dumper/Caster/AmqpCaster.php +++ /dev/null @@ -1,212 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts Amqp related classes to array representation. - * - * @author Grégoire Pineau <lyrixx@lyrixx.info> - * - * @final - */ -class AmqpCaster -{ - private const FLAGS = [ - \AMQP_DURABLE => 'AMQP_DURABLE', - \AMQP_PASSIVE => 'AMQP_PASSIVE', - \AMQP_EXCLUSIVE => 'AMQP_EXCLUSIVE', - \AMQP_AUTODELETE => 'AMQP_AUTODELETE', - \AMQP_INTERNAL => 'AMQP_INTERNAL', - \AMQP_NOLOCAL => 'AMQP_NOLOCAL', - \AMQP_AUTOACK => 'AMQP_AUTOACK', - \AMQP_IFEMPTY => 'AMQP_IFEMPTY', - \AMQP_IFUNUSED => 'AMQP_IFUNUSED', - \AMQP_MANDATORY => 'AMQP_MANDATORY', - \AMQP_IMMEDIATE => 'AMQP_IMMEDIATE', - \AMQP_MULTIPLE => 'AMQP_MULTIPLE', - \AMQP_NOWAIT => 'AMQP_NOWAIT', - \AMQP_REQUEUE => 'AMQP_REQUEUE', - ]; - - private const EXCHANGE_TYPES = [ - \AMQP_EX_TYPE_DIRECT => 'AMQP_EX_TYPE_DIRECT', - \AMQP_EX_TYPE_FANOUT => 'AMQP_EX_TYPE_FANOUT', - \AMQP_EX_TYPE_TOPIC => 'AMQP_EX_TYPE_TOPIC', - \AMQP_EX_TYPE_HEADERS => 'AMQP_EX_TYPE_HEADERS', - ]; - - public static function castConnection(\AMQPConnection $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - $a += [ - $prefix.'is_connected' => $c->isConnected(), - ]; - - // Recent version of the extension already expose private properties - if (isset($a["\x00AMQPConnection\x00login"])) { - return $a; - } - - // BC layer in the amqp lib - if (method_exists($c, 'getReadTimeout')) { - $timeout = $c->getReadTimeout(); - } else { - $timeout = $c->getTimeout(); - } - - $a += [ - $prefix.'is_connected' => $c->isConnected(), - $prefix.'login' => $c->getLogin(), - $prefix.'password' => $c->getPassword(), - $prefix.'host' => $c->getHost(), - $prefix.'vhost' => $c->getVhost(), - $prefix.'port' => $c->getPort(), - $prefix.'read_timeout' => $timeout, - ]; - - return $a; - } - - public static function castChannel(\AMQPChannel $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - $a += [ - $prefix.'is_connected' => $c->isConnected(), - $prefix.'channel_id' => $c->getChannelId(), - ]; - - // Recent version of the extension already expose private properties - if (isset($a["\x00AMQPChannel\x00connection"])) { - return $a; - } - - $a += [ - $prefix.'connection' => $c->getConnection(), - $prefix.'prefetch_size' => $c->getPrefetchSize(), - $prefix.'prefetch_count' => $c->getPrefetchCount(), - ]; - - return $a; - } - - public static function castQueue(\AMQPQueue $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - $a += [ - $prefix.'flags' => self::extractFlags($c->getFlags()), - ]; - - // Recent version of the extension already expose private properties - if (isset($a["\x00AMQPQueue\x00name"])) { - return $a; - } - - $a += [ - $prefix.'connection' => $c->getConnection(), - $prefix.'channel' => $c->getChannel(), - $prefix.'name' => $c->getName(), - $prefix.'arguments' => $c->getArguments(), - ]; - - return $a; - } - - public static function castExchange(\AMQPExchange $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - $a += [ - $prefix.'flags' => self::extractFlags($c->getFlags()), - ]; - - $type = isset(self::EXCHANGE_TYPES[$c->getType()]) ? new ConstStub(self::EXCHANGE_TYPES[$c->getType()], $c->getType()) : $c->getType(); - - // Recent version of the extension already expose private properties - if (isset($a["\x00AMQPExchange\x00name"])) { - $a["\x00AMQPExchange\x00type"] = $type; - - return $a; - } - - $a += [ - $prefix.'connection' => $c->getConnection(), - $prefix.'channel' => $c->getChannel(), - $prefix.'name' => $c->getName(), - $prefix.'type' => $type, - $prefix.'arguments' => $c->getArguments(), - ]; - - return $a; - } - - public static function castEnvelope(\AMQPEnvelope $c, array $a, Stub $stub, bool $isNested, int $filter = 0) - { - $prefix = Caster::PREFIX_VIRTUAL; - - $deliveryMode = new ConstStub($c->getDeliveryMode().(2 === $c->getDeliveryMode() ? ' (persistent)' : ' (non-persistent)'), $c->getDeliveryMode()); - - // Recent version of the extension already expose private properties - if (isset($a["\x00AMQPEnvelope\x00body"])) { - $a["\0AMQPEnvelope\0delivery_mode"] = $deliveryMode; - - return $a; - } - - if (!($filter & Caster::EXCLUDE_VERBOSE)) { - $a += [$prefix.'body' => $c->getBody()]; - } - - $a += [ - $prefix.'delivery_tag' => $c->getDeliveryTag(), - $prefix.'is_redelivery' => $c->isRedelivery(), - $prefix.'exchange_name' => $c->getExchangeName(), - $prefix.'routing_key' => $c->getRoutingKey(), - $prefix.'content_type' => $c->getContentType(), - $prefix.'content_encoding' => $c->getContentEncoding(), - $prefix.'headers' => $c->getHeaders(), - $prefix.'delivery_mode' => $deliveryMode, - $prefix.'priority' => $c->getPriority(), - $prefix.'correlation_id' => $c->getCorrelationId(), - $prefix.'reply_to' => $c->getReplyTo(), - $prefix.'expiration' => $c->getExpiration(), - $prefix.'message_id' => $c->getMessageId(), - $prefix.'timestamp' => $c->getTimeStamp(), - $prefix.'type' => $c->getType(), - $prefix.'user_id' => $c->getUserId(), - $prefix.'app_id' => $c->getAppId(), - ]; - - return $a; - } - - private static function extractFlags(int $flags): ConstStub - { - $flagsArray = []; - - foreach (self::FLAGS as $value => $name) { - if ($flags & $value) { - $flagsArray[] = $name; - } - } - - if (!$flagsArray) { - $flagsArray = ['AMQP_NOPARAM']; - } - - return new ConstStub(implode('|', $flagsArray), $flags); - } -} diff --git a/lib/symfony/var-dumper/Caster/ArgsStub.php b/lib/symfony/var-dumper/Caster/ArgsStub.php deleted file mode 100644 index b3f7bbee3..000000000 --- a/lib/symfony/var-dumper/Caster/ArgsStub.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Represents a list of function arguments. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class ArgsStub extends EnumStub -{ - private static $parameters = []; - - public function __construct(array $args, string $function, ?string $class) - { - [$variadic, $params] = self::getParameters($function, $class); - - $values = []; - foreach ($args as $k => $v) { - $values[$k] = !\is_scalar($v) && !$v instanceof Stub ? new CutStub($v) : $v; - } - if (null === $params) { - parent::__construct($values, false); - - return; - } - if (\count($values) < \count($params)) { - $params = \array_slice($params, 0, \count($values)); - } elseif (\count($values) > \count($params)) { - $values[] = new EnumStub(array_splice($values, \count($params)), false); - $params[] = $variadic; - } - if (['...'] === $params) { - $this->dumpKeys = false; - $this->value = $values[0]->value; - } else { - $this->value = array_combine($params, $values); - } - } - - private static function getParameters(string $function, ?string $class): array - { - if (isset(self::$parameters[$k = $class.'::'.$function])) { - return self::$parameters[$k]; - } - - try { - $r = null !== $class ? new \ReflectionMethod($class, $function) : new \ReflectionFunction($function); - } catch (\ReflectionException $e) { - return [null, null]; - } - - $variadic = '...'; - $params = []; - foreach ($r->getParameters() as $v) { - $k = '$'.$v->name; - if ($v->isPassedByReference()) { - $k = '&'.$k; - } - if ($v->isVariadic()) { - $variadic .= $k; - } else { - $params[] = $k; - } - } - - return self::$parameters[$k] = [$variadic, $params]; - } -} diff --git a/lib/symfony/var-dumper/Caster/Caster.php b/lib/symfony/var-dumper/Caster/Caster.php deleted file mode 100644 index 53f4461d0..000000000 --- a/lib/symfony/var-dumper/Caster/Caster.php +++ /dev/null @@ -1,170 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Helper for filtering out properties in casters. - * - * @author Nicolas Grekas <p@tchwork.com> - * - * @final - */ -class Caster -{ - public const EXCLUDE_VERBOSE = 1; - public const EXCLUDE_VIRTUAL = 2; - public const EXCLUDE_DYNAMIC = 4; - public const EXCLUDE_PUBLIC = 8; - public const EXCLUDE_PROTECTED = 16; - public const EXCLUDE_PRIVATE = 32; - public const EXCLUDE_NULL = 64; - public const EXCLUDE_EMPTY = 128; - public const EXCLUDE_NOT_IMPORTANT = 256; - public const EXCLUDE_STRICT = 512; - - public const PREFIX_VIRTUAL = "\0~\0"; - public const PREFIX_DYNAMIC = "\0+\0"; - public const PREFIX_PROTECTED = "\0*\0"; - - /** - * Casts objects to arrays and adds the dynamic property prefix. - * - * @param bool $hasDebugInfo Whether the __debugInfo method exists on $obj or not - */ - public static function castObject(object $obj, string $class, bool $hasDebugInfo = false, string $debugClass = null): array - { - if ($hasDebugInfo) { - try { - $debugInfo = $obj->__debugInfo(); - } catch (\Exception $e) { - // ignore failing __debugInfo() - $hasDebugInfo = false; - } - } - - $a = $obj instanceof \Closure ? [] : (array) $obj; - - if ($obj instanceof \__PHP_Incomplete_Class) { - return $a; - } - - if ($a) { - static $publicProperties = []; - $debugClass = $debugClass ?? get_debug_type($obj); - - $i = 0; - $prefixedKeys = []; - foreach ($a as $k => $v) { - if ("\0" !== ($k[0] ?? '')) { - if (!isset($publicProperties[$class])) { - foreach ((new \ReflectionClass($class))->getProperties(\ReflectionProperty::IS_PUBLIC) as $prop) { - $publicProperties[$class][$prop->name] = true; - } - } - if (!isset($publicProperties[$class][$k])) { - $prefixedKeys[$i] = self::PREFIX_DYNAMIC.$k; - } - } elseif ($debugClass !== $class && 1 === strpos($k, $class)) { - $prefixedKeys[$i] = "\0".$debugClass.strrchr($k, "\0"); - } - ++$i; - } - if ($prefixedKeys) { - $keys = array_keys($a); - foreach ($prefixedKeys as $i => $k) { - $keys[$i] = $k; - } - $a = array_combine($keys, $a); - } - } - - if ($hasDebugInfo && \is_array($debugInfo)) { - foreach ($debugInfo as $k => $v) { - if (!isset($k[0]) || "\0" !== $k[0]) { - if (\array_key_exists(self::PREFIX_DYNAMIC.$k, $a)) { - continue; - } - $k = self::PREFIX_VIRTUAL.$k; - } - - unset($a[$k]); - $a[$k] = $v; - } - } - - return $a; - } - - /** - * Filters out the specified properties. - * - * By default, a single match in the $filter bit field filters properties out, following an "or" logic. - * When EXCLUDE_STRICT is set, an "and" logic is applied: all bits must match for a property to be removed. - * - * @param array $a The array containing the properties to filter - * @param int $filter A bit field of Caster::EXCLUDE_* constants specifying which properties to filter out - * @param string[] $listedProperties List of properties to exclude when Caster::EXCLUDE_VERBOSE is set, and to preserve when Caster::EXCLUDE_NOT_IMPORTANT is set - * @param int &$count Set to the number of removed properties - */ - public static function filter(array $a, int $filter, array $listedProperties = [], ?int &$count = 0): array - { - $count = 0; - - foreach ($a as $k => $v) { - $type = self::EXCLUDE_STRICT & $filter; - - if (null === $v) { - $type |= self::EXCLUDE_NULL & $filter; - $type |= self::EXCLUDE_EMPTY & $filter; - } elseif (false === $v || '' === $v || '0' === $v || 0 === $v || 0.0 === $v || [] === $v) { - $type |= self::EXCLUDE_EMPTY & $filter; - } - if ((self::EXCLUDE_NOT_IMPORTANT & $filter) && !\in_array($k, $listedProperties, true)) { - $type |= self::EXCLUDE_NOT_IMPORTANT; - } - if ((self::EXCLUDE_VERBOSE & $filter) && \in_array($k, $listedProperties, true)) { - $type |= self::EXCLUDE_VERBOSE; - } - - if (!isset($k[1]) || "\0" !== $k[0]) { - $type |= self::EXCLUDE_PUBLIC & $filter; - } elseif ('~' === $k[1]) { - $type |= self::EXCLUDE_VIRTUAL & $filter; - } elseif ('+' === $k[1]) { - $type |= self::EXCLUDE_DYNAMIC & $filter; - } elseif ('*' === $k[1]) { - $type |= self::EXCLUDE_PROTECTED & $filter; - } else { - $type |= self::EXCLUDE_PRIVATE & $filter; - } - - if ((self::EXCLUDE_STRICT & $filter) ? $type === $filter : $type) { - unset($a[$k]); - ++$count; - } - } - - return $a; - } - - public static function castPhpIncompleteClass(\__PHP_Incomplete_Class $c, array $a, Stub $stub, bool $isNested): array - { - if (isset($a['__PHP_Incomplete_Class_Name'])) { - $stub->class .= '('.$a['__PHP_Incomplete_Class_Name'].')'; - unset($a['__PHP_Incomplete_Class_Name']); - } - - return $a; - } -} diff --git a/lib/symfony/var-dumper/Caster/ClassStub.php b/lib/symfony/var-dumper/Caster/ClassStub.php deleted file mode 100644 index 48f848354..000000000 --- a/lib/symfony/var-dumper/Caster/ClassStub.php +++ /dev/null @@ -1,106 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Represents a PHP class identifier. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class ClassStub extends ConstStub -{ - /** - * @param string $identifier A PHP identifier, e.g. a class, method, interface, etc. name - * @param callable $callable The callable targeted by the identifier when it is ambiguous or not a real PHP identifier - */ - public function __construct(string $identifier, $callable = null) - { - $this->value = $identifier; - - try { - if (null !== $callable) { - if ($callable instanceof \Closure) { - $r = new \ReflectionFunction($callable); - } elseif (\is_object($callable)) { - $r = [$callable, '__invoke']; - } elseif (\is_array($callable)) { - $r = $callable; - } elseif (false !== $i = strpos($callable, '::')) { - $r = [substr($callable, 0, $i), substr($callable, 2 + $i)]; - } else { - $r = new \ReflectionFunction($callable); - } - } elseif (0 < $i = strpos($identifier, '::') ?: strpos($identifier, '->')) { - $r = [substr($identifier, 0, $i), substr($identifier, 2 + $i)]; - } else { - $r = new \ReflectionClass($identifier); - } - - if (\is_array($r)) { - try { - $r = new \ReflectionMethod($r[0], $r[1]); - } catch (\ReflectionException $e) { - $r = new \ReflectionClass($r[0]); - } - } - - if (str_contains($identifier, "@anonymous\0")) { - $this->value = $identifier = 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]; - }, $identifier); - } - - if (null !== $callable && $r instanceof \ReflectionFunctionAbstract) { - $s = ReflectionCaster::castFunctionAbstract($r, [], new Stub(), true, Caster::EXCLUDE_VERBOSE); - $s = ReflectionCaster::getSignature($s); - - if (str_ends_with($identifier, '()')) { - $this->value = substr_replace($identifier, $s, -2); - } else { - $this->value .= $s; - } - } - } catch (\ReflectionException $e) { - return; - } finally { - if (0 < $i = strrpos($this->value, '\\')) { - $this->attr['ellipsis'] = \strlen($this->value) - $i; - $this->attr['ellipsis-type'] = 'class'; - $this->attr['ellipsis-tail'] = 1; - } - } - - if ($f = $r->getFileName()) { - $this->attr['file'] = $f; - $this->attr['line'] = $r->getStartLine(); - } - } - - public static function wrapCallable($callable) - { - if (\is_object($callable) || !\is_callable($callable)) { - return $callable; - } - - if (!\is_array($callable)) { - $callable = new static($callable, $callable); - } elseif (\is_string($callable[0])) { - $callable[0] = new static($callable[0], $callable); - } else { - $callable[1] = new static($callable[1], $callable); - } - - return $callable; - } -} diff --git a/lib/symfony/var-dumper/Caster/ConstStub.php b/lib/symfony/var-dumper/Caster/ConstStub.php deleted file mode 100644 index 8b0179745..000000000 --- a/lib/symfony/var-dumper/Caster/ConstStub.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Represents a PHP constant and its value. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class ConstStub extends Stub -{ - public function __construct(string $name, $value = null) - { - $this->class = $name; - $this->value = 1 < \func_num_args() ? $value : $name; - } - - /** - * @return string - */ - public function __toString() - { - return (string) $this->value; - } -} diff --git a/lib/symfony/var-dumper/Caster/CutArrayStub.php b/lib/symfony/var-dumper/Caster/CutArrayStub.php deleted file mode 100644 index 0e4fb363d..000000000 --- a/lib/symfony/var-dumper/Caster/CutArrayStub.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -/** - * Represents a cut array. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class CutArrayStub extends CutStub -{ - public $preservedSubset; - - public function __construct(array $value, array $preservedKeys) - { - parent::__construct($value); - - $this->preservedSubset = array_intersect_key($value, array_flip($preservedKeys)); - $this->cut -= \count($this->preservedSubset); - } -} diff --git a/lib/symfony/var-dumper/Caster/CutStub.php b/lib/symfony/var-dumper/Caster/CutStub.php deleted file mode 100644 index 464c6dbd1..000000000 --- a/lib/symfony/var-dumper/Caster/CutStub.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Represents the main properties of a PHP variable, pre-casted by a caster. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class CutStub extends Stub -{ - public function __construct($value) - { - $this->value = $value; - - switch (\gettype($value)) { - case 'object': - $this->type = self::TYPE_OBJECT; - $this->class = \get_class($value); - - if ($value instanceof \Closure) { - ReflectionCaster::castClosure($value, [], $this, true, Caster::EXCLUDE_VERBOSE); - } - - $this->cut = -1; - break; - - case 'array': - $this->type = self::TYPE_ARRAY; - $this->class = self::ARRAY_ASSOC; - $this->cut = $this->value = \count($value); - break; - - case 'resource': - case 'unknown type': - case 'resource (closed)': - $this->type = self::TYPE_RESOURCE; - $this->handle = (int) $value; - if ('Unknown' === $this->class = @get_resource_type($value)) { - $this->class = 'Closed'; - } - $this->cut = -1; - break; - - case 'string': - $this->type = self::TYPE_STRING; - $this->class = preg_match('//u', $value) ? self::STRING_UTF8 : self::STRING_BINARY; - $this->cut = self::STRING_BINARY === $this->class ? \strlen($value) : mb_strlen($value, 'UTF-8'); - $this->value = ''; - break; - } - } -} diff --git a/lib/symfony/var-dumper/Caster/DOMCaster.php b/lib/symfony/var-dumper/Caster/DOMCaster.php deleted file mode 100644 index 4dd16e0ee..000000000 --- a/lib/symfony/var-dumper/Caster/DOMCaster.php +++ /dev/null @@ -1,304 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts DOM related classes to array representation. - * - * @author Nicolas Grekas <p@tchwork.com> - * - * @final - */ -class DOMCaster -{ - private const ERROR_CODES = [ - \DOM_PHP_ERR => 'DOM_PHP_ERR', - \DOM_INDEX_SIZE_ERR => 'DOM_INDEX_SIZE_ERR', - \DOMSTRING_SIZE_ERR => 'DOMSTRING_SIZE_ERR', - \DOM_HIERARCHY_REQUEST_ERR => 'DOM_HIERARCHY_REQUEST_ERR', - \DOM_WRONG_DOCUMENT_ERR => 'DOM_WRONG_DOCUMENT_ERR', - \DOM_INVALID_CHARACTER_ERR => 'DOM_INVALID_CHARACTER_ERR', - \DOM_NO_DATA_ALLOWED_ERR => 'DOM_NO_DATA_ALLOWED_ERR', - \DOM_NO_MODIFICATION_ALLOWED_ERR => 'DOM_NO_MODIFICATION_ALLOWED_ERR', - \DOM_NOT_FOUND_ERR => 'DOM_NOT_FOUND_ERR', - \DOM_NOT_SUPPORTED_ERR => 'DOM_NOT_SUPPORTED_ERR', - \DOM_INUSE_ATTRIBUTE_ERR => 'DOM_INUSE_ATTRIBUTE_ERR', - \DOM_INVALID_STATE_ERR => 'DOM_INVALID_STATE_ERR', - \DOM_SYNTAX_ERR => 'DOM_SYNTAX_ERR', - \DOM_INVALID_MODIFICATION_ERR => 'DOM_INVALID_MODIFICATION_ERR', - \DOM_NAMESPACE_ERR => 'DOM_NAMESPACE_ERR', - \DOM_INVALID_ACCESS_ERR => 'DOM_INVALID_ACCESS_ERR', - \DOM_VALIDATION_ERR => 'DOM_VALIDATION_ERR', - ]; - - private const NODE_TYPES = [ - \XML_ELEMENT_NODE => 'XML_ELEMENT_NODE', - \XML_ATTRIBUTE_NODE => 'XML_ATTRIBUTE_NODE', - \XML_TEXT_NODE => 'XML_TEXT_NODE', - \XML_CDATA_SECTION_NODE => 'XML_CDATA_SECTION_NODE', - \XML_ENTITY_REF_NODE => 'XML_ENTITY_REF_NODE', - \XML_ENTITY_NODE => 'XML_ENTITY_NODE', - \XML_PI_NODE => 'XML_PI_NODE', - \XML_COMMENT_NODE => 'XML_COMMENT_NODE', - \XML_DOCUMENT_NODE => 'XML_DOCUMENT_NODE', - \XML_DOCUMENT_TYPE_NODE => 'XML_DOCUMENT_TYPE_NODE', - \XML_DOCUMENT_FRAG_NODE => 'XML_DOCUMENT_FRAG_NODE', - \XML_NOTATION_NODE => 'XML_NOTATION_NODE', - \XML_HTML_DOCUMENT_NODE => 'XML_HTML_DOCUMENT_NODE', - \XML_DTD_NODE => 'XML_DTD_NODE', - \XML_ELEMENT_DECL_NODE => 'XML_ELEMENT_DECL_NODE', - \XML_ATTRIBUTE_DECL_NODE => 'XML_ATTRIBUTE_DECL_NODE', - \XML_ENTITY_DECL_NODE => 'XML_ENTITY_DECL_NODE', - \XML_NAMESPACE_DECL_NODE => 'XML_NAMESPACE_DECL_NODE', - ]; - - public static function castException(\DOMException $e, array $a, Stub $stub, bool $isNested) - { - $k = Caster::PREFIX_PROTECTED.'code'; - if (isset($a[$k], self::ERROR_CODES[$a[$k]])) { - $a[$k] = new ConstStub(self::ERROR_CODES[$a[$k]], $a[$k]); - } - - return $a; - } - - public static function castLength($dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'length' => $dom->length, - ]; - - return $a; - } - - public static function castImplementation(\DOMImplementation $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - Caster::PREFIX_VIRTUAL.'Core' => '1.0', - Caster::PREFIX_VIRTUAL.'XML' => '2.0', - ]; - - return $a; - } - - public static function castNode(\DOMNode $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'nodeName' => $dom->nodeName, - 'nodeValue' => new CutStub($dom->nodeValue), - 'nodeType' => new ConstStub(self::NODE_TYPES[$dom->nodeType], $dom->nodeType), - 'parentNode' => new CutStub($dom->parentNode), - 'childNodes' => $dom->childNodes, - 'firstChild' => new CutStub($dom->firstChild), - 'lastChild' => new CutStub($dom->lastChild), - 'previousSibling' => new CutStub($dom->previousSibling), - 'nextSibling' => new CutStub($dom->nextSibling), - 'attributes' => $dom->attributes, - 'ownerDocument' => new CutStub($dom->ownerDocument), - 'namespaceURI' => $dom->namespaceURI, - 'prefix' => $dom->prefix, - 'localName' => $dom->localName, - 'baseURI' => $dom->baseURI ? new LinkStub($dom->baseURI) : $dom->baseURI, - 'textContent' => new CutStub($dom->textContent), - ]; - - return $a; - } - - public static function castNameSpaceNode(\DOMNameSpaceNode $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'nodeName' => $dom->nodeName, - 'nodeValue' => new CutStub($dom->nodeValue), - 'nodeType' => new ConstStub(self::NODE_TYPES[$dom->nodeType], $dom->nodeType), - 'prefix' => $dom->prefix, - 'localName' => $dom->localName, - 'namespaceURI' => $dom->namespaceURI, - 'ownerDocument' => new CutStub($dom->ownerDocument), - 'parentNode' => new CutStub($dom->parentNode), - ]; - - return $a; - } - - public static function castDocument(\DOMDocument $dom, array $a, Stub $stub, bool $isNested, int $filter = 0) - { - $a += [ - 'doctype' => $dom->doctype, - 'implementation' => $dom->implementation, - 'documentElement' => new CutStub($dom->documentElement), - 'actualEncoding' => $dom->actualEncoding, - 'encoding' => $dom->encoding, - 'xmlEncoding' => $dom->xmlEncoding, - 'standalone' => $dom->standalone, - 'xmlStandalone' => $dom->xmlStandalone, - 'version' => $dom->version, - 'xmlVersion' => $dom->xmlVersion, - 'strictErrorChecking' => $dom->strictErrorChecking, - 'documentURI' => $dom->documentURI ? new LinkStub($dom->documentURI) : $dom->documentURI, - 'config' => $dom->config, - 'formatOutput' => $dom->formatOutput, - 'validateOnParse' => $dom->validateOnParse, - 'resolveExternals' => $dom->resolveExternals, - 'preserveWhiteSpace' => $dom->preserveWhiteSpace, - 'recover' => $dom->recover, - 'substituteEntities' => $dom->substituteEntities, - ]; - - if (!($filter & Caster::EXCLUDE_VERBOSE)) { - $formatOutput = $dom->formatOutput; - $dom->formatOutput = true; - $a += [Caster::PREFIX_VIRTUAL.'xml' => $dom->saveXML()]; - $dom->formatOutput = $formatOutput; - } - - return $a; - } - - public static function castCharacterData(\DOMCharacterData $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'data' => $dom->data, - 'length' => $dom->length, - ]; - - return $a; - } - - public static function castAttr(\DOMAttr $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'name' => $dom->name, - 'specified' => $dom->specified, - 'value' => $dom->value, - 'ownerElement' => $dom->ownerElement, - 'schemaTypeInfo' => $dom->schemaTypeInfo, - ]; - - return $a; - } - - public static function castElement(\DOMElement $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'tagName' => $dom->tagName, - 'schemaTypeInfo' => $dom->schemaTypeInfo, - ]; - - return $a; - } - - public static function castText(\DOMText $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'wholeText' => $dom->wholeText, - ]; - - return $a; - } - - public static function castTypeinfo(\DOMTypeinfo $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'typeName' => $dom->typeName, - 'typeNamespace' => $dom->typeNamespace, - ]; - - return $a; - } - - public static function castDomError(\DOMDomError $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'severity' => $dom->severity, - 'message' => $dom->message, - 'type' => $dom->type, - 'relatedException' => $dom->relatedException, - 'related_data' => $dom->related_data, - 'location' => $dom->location, - ]; - - return $a; - } - - public static function castLocator(\DOMLocator $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'lineNumber' => $dom->lineNumber, - 'columnNumber' => $dom->columnNumber, - 'offset' => $dom->offset, - 'relatedNode' => $dom->relatedNode, - 'uri' => $dom->uri ? new LinkStub($dom->uri, $dom->lineNumber) : $dom->uri, - ]; - - return $a; - } - - public static function castDocumentType(\DOMDocumentType $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'name' => $dom->name, - 'entities' => $dom->entities, - 'notations' => $dom->notations, - 'publicId' => $dom->publicId, - 'systemId' => $dom->systemId, - 'internalSubset' => $dom->internalSubset, - ]; - - return $a; - } - - public static function castNotation(\DOMNotation $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'publicId' => $dom->publicId, - 'systemId' => $dom->systemId, - ]; - - return $a; - } - - public static function castEntity(\DOMEntity $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'publicId' => $dom->publicId, - 'systemId' => $dom->systemId, - 'notationName' => $dom->notationName, - 'actualEncoding' => $dom->actualEncoding, - 'encoding' => $dom->encoding, - 'version' => $dom->version, - ]; - - return $a; - } - - public static function castProcessingInstruction(\DOMProcessingInstruction $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'target' => $dom->target, - 'data' => $dom->data, - ]; - - return $a; - } - - public static function castXPath(\DOMXPath $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'document' => $dom->document, - ]; - - return $a; - } -} diff --git a/lib/symfony/var-dumper/Caster/DateCaster.php b/lib/symfony/var-dumper/Caster/DateCaster.php deleted file mode 100644 index 18641fbc1..000000000 --- a/lib/symfony/var-dumper/Caster/DateCaster.php +++ /dev/null @@ -1,127 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts DateTimeInterface related classes to array representation. - * - * @author Dany Maillard <danymaillard93b@gmail.com> - * - * @final - */ -class DateCaster -{ - private const PERIOD_LIMIT = 3; - - public static function castDateTime(\DateTimeInterface $d, array $a, Stub $stub, bool $isNested, int $filter) - { - $prefix = Caster::PREFIX_VIRTUAL; - $location = $d->getTimezone()->getLocation(); - $fromNow = (new \DateTime())->diff($d); - - $title = $d->format('l, F j, Y') - ."\n".self::formatInterval($fromNow).' from now' - .($location ? ($d->format('I') ? "\nDST On" : "\nDST Off") : '') - ; - - unset( - $a[Caster::PREFIX_DYNAMIC.'date'], - $a[Caster::PREFIX_DYNAMIC.'timezone'], - $a[Caster::PREFIX_DYNAMIC.'timezone_type'] - ); - $a[$prefix.'date'] = new ConstStub(self::formatDateTime($d, $location ? ' e (P)' : ' P'), $title); - - $stub->class .= $d->format(' @U'); - - return $a; - } - - public static function castInterval(\DateInterval $interval, array $a, Stub $stub, bool $isNested, int $filter) - { - $now = new \DateTimeImmutable('@0', new \DateTimeZone('UTC')); - $numberOfSeconds = $now->add($interval)->getTimestamp() - $now->getTimestamp(); - $title = number_format($numberOfSeconds, 0, '.', ' ').'s'; - - $i = [Caster::PREFIX_VIRTUAL.'interval' => new ConstStub(self::formatInterval($interval), $title)]; - - return $filter & Caster::EXCLUDE_VERBOSE ? $i : $i + $a; - } - - private static function formatInterval(\DateInterval $i): string - { - $format = '%R '; - - if (0 === $i->y && 0 === $i->m && ($i->h >= 24 || $i->i >= 60 || $i->s >= 60)) { - $d = new \DateTimeImmutable('@0', new \DateTimeZone('UTC')); - $i = $d->diff($d->add($i)); // recalculate carry over points - $format .= 0 < $i->days ? '%ad ' : ''; - } else { - $format .= ($i->y ? '%yy ' : '').($i->m ? '%mm ' : '').($i->d ? '%dd ' : ''); - } - - $format .= $i->h || $i->i || $i->s || $i->f ? '%H:%I:'.self::formatSeconds($i->s, substr($i->f, 2)) : ''; - $format = '%R ' === $format ? '0s' : $format; - - return $i->format(rtrim($format)); - } - - public static function castTimeZone(\DateTimeZone $timeZone, array $a, Stub $stub, bool $isNested, int $filter) - { - $location = $timeZone->getLocation(); - $formatted = (new \DateTime('now', $timeZone))->format($location ? 'e (P)' : 'P'); - $title = $location && \extension_loaded('intl') ? \Locale::getDisplayRegion('-'.$location['country_code']) : ''; - - $z = [Caster::PREFIX_VIRTUAL.'timezone' => new ConstStub($formatted, $title)]; - - return $filter & Caster::EXCLUDE_VERBOSE ? $z : $z + $a; - } - - public static function castPeriod(\DatePeriod $p, array $a, Stub $stub, bool $isNested, int $filter) - { - $dates = []; - foreach (clone $p as $i => $d) { - if (self::PERIOD_LIMIT === $i) { - $now = new \DateTimeImmutable('now', new \DateTimeZone('UTC')); - $dates[] = sprintf('%s more', ($end = $p->getEndDate()) - ? ceil(($end->format('U.u') - $d->format('U.u')) / ((int) $now->add($p->getDateInterval())->format('U.u') - (int) $now->format('U.u'))) - : $p->recurrences - $i - ); - break; - } - $dates[] = sprintf('%s) %s', $i + 1, self::formatDateTime($d)); - } - - $period = sprintf( - 'every %s, from %s%s %s', - self::formatInterval($p->getDateInterval()), - $p->include_start_date ? '[' : ']', - self::formatDateTime($p->getStartDate()), - ($end = $p->getEndDate()) ? 'to '.self::formatDateTime($end).(\PHP_VERSION_ID >= 80200 && $p->include_end_date ? ']' : '[') : 'recurring '.$p->recurrences.' time/s' - ); - - $p = [Caster::PREFIX_VIRTUAL.'period' => new ConstStub($period, implode("\n", $dates))]; - - return $filter & Caster::EXCLUDE_VERBOSE ? $p : $p + $a; - } - - private static function formatDateTime(\DateTimeInterface $d, string $extra = ''): string - { - return $d->format('Y-m-d H:i:'.self::formatSeconds($d->format('s'), $d->format('u')).$extra); - } - - private static function formatSeconds(string $s, string $us): string - { - return sprintf('%02d.%s', $s, 0 === ($len = \strlen($t = rtrim($us, '0'))) ? '0' : ($len <= 3 ? str_pad($t, 3, '0') : $us)); - } -} diff --git a/lib/symfony/var-dumper/Caster/DoctrineCaster.php b/lib/symfony/var-dumper/Caster/DoctrineCaster.php deleted file mode 100644 index 129b2cb47..000000000 --- a/lib/symfony/var-dumper/Caster/DoctrineCaster.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Doctrine\Common\Proxy\Proxy as CommonProxy; -use Doctrine\ORM\PersistentCollection; -use Doctrine\ORM\Proxy\Proxy as OrmProxy; -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts Doctrine related classes to array representation. - * - * @author Nicolas Grekas <p@tchwork.com> - * - * @final - */ -class DoctrineCaster -{ - public static function castCommonProxy(CommonProxy $proxy, array $a, Stub $stub, bool $isNested) - { - foreach (['__cloner__', '__initializer__'] as $k) { - if (\array_key_exists($k, $a)) { - unset($a[$k]); - ++$stub->cut; - } - } - - return $a; - } - - public static function castOrmProxy(OrmProxy $proxy, array $a, Stub $stub, bool $isNested) - { - foreach (['_entityPersister', '_identifier'] as $k) { - if (\array_key_exists($k = "\0Doctrine\\ORM\\Proxy\\Proxy\0".$k, $a)) { - unset($a[$k]); - ++$stub->cut; - } - } - - return $a; - } - - public static function castPersistentCollection(PersistentCollection $coll, array $a, Stub $stub, bool $isNested) - { - foreach (['snapshot', 'association', 'typeClass'] as $k) { - if (\array_key_exists($k = "\0Doctrine\\ORM\\PersistentCollection\0".$k, $a)) { - $a[$k] = new CutStub($a[$k]); - } - } - - return $a; - } -} diff --git a/lib/symfony/var-dumper/Caster/DsCaster.php b/lib/symfony/var-dumper/Caster/DsCaster.php deleted file mode 100644 index b34b67004..000000000 --- a/lib/symfony/var-dumper/Caster/DsCaster.php +++ /dev/null @@ -1,70 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Ds\Collection; -use Ds\Map; -use Ds\Pair; -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts Ds extension classes to array representation. - * - * @author Jáchym Toušek <enumag@gmail.com> - * - * @final - */ -class DsCaster -{ - public static function castCollection(Collection $c, array $a, Stub $stub, bool $isNested): array - { - $a[Caster::PREFIX_VIRTUAL.'count'] = $c->count(); - $a[Caster::PREFIX_VIRTUAL.'capacity'] = $c->capacity(); - - if (!$c instanceof Map) { - $a += $c->toArray(); - } - - return $a; - } - - public static function castMap(Map $c, array $a, Stub $stub, bool $isNested): array - { - foreach ($c as $k => $v) { - $a[] = new DsPairStub($k, $v); - } - - return $a; - } - - public static function castPair(Pair $c, array $a, Stub $stub, bool $isNested): array - { - foreach ($c->toArray() as $k => $v) { - $a[Caster::PREFIX_VIRTUAL.$k] = $v; - } - - return $a; - } - - public static function castPairStub(DsPairStub $c, array $a, Stub $stub, bool $isNested): array - { - if ($isNested) { - $stub->class = Pair::class; - $stub->value = null; - $stub->handle = 0; - - $a = $c->value; - } - - return $a; - } -} diff --git a/lib/symfony/var-dumper/Caster/DsPairStub.php b/lib/symfony/var-dumper/Caster/DsPairStub.php deleted file mode 100644 index a1dcc1561..000000000 --- a/lib/symfony/var-dumper/Caster/DsPairStub.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class DsPairStub extends Stub -{ - public function __construct($key, $value) - { - $this->value = [ - Caster::PREFIX_VIRTUAL.'key' => $key, - Caster::PREFIX_VIRTUAL.'value' => $value, - ]; - } -} diff --git a/lib/symfony/var-dumper/Caster/EnumStub.php b/lib/symfony/var-dumper/Caster/EnumStub.php deleted file mode 100644 index 7a4e98a21..000000000 --- a/lib/symfony/var-dumper/Caster/EnumStub.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Represents an enumeration of values. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class EnumStub extends Stub -{ - public $dumpKeys = true; - - public function __construct(array $values, bool $dumpKeys = true) - { - $this->value = $values; - $this->dumpKeys = $dumpKeys; - } -} diff --git a/lib/symfony/var-dumper/Caster/ExceptionCaster.php b/lib/symfony/var-dumper/Caster/ExceptionCaster.php deleted file mode 100644 index 7f5cb65eb..000000000 --- a/lib/symfony/var-dumper/Caster/ExceptionCaster.php +++ /dev/null @@ -1,388 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext; -use Symfony\Component\VarDumper\Cloner\Stub; -use Symfony\Component\VarDumper\Exception\ThrowingCasterException; - -/** - * Casts common Exception classes to array representation. - * - * @author Nicolas Grekas <p@tchwork.com> - * - * @final - */ -class ExceptionCaster -{ - public static $srcContext = 1; - public static $traceArgs = true; - public static $errorTypes = [ - \E_DEPRECATED => 'E_DEPRECATED', - \E_USER_DEPRECATED => 'E_USER_DEPRECATED', - \E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR', - \E_ERROR => 'E_ERROR', - \E_WARNING => 'E_WARNING', - \E_PARSE => 'E_PARSE', - \E_NOTICE => 'E_NOTICE', - \E_CORE_ERROR => 'E_CORE_ERROR', - \E_CORE_WARNING => 'E_CORE_WARNING', - \E_COMPILE_ERROR => 'E_COMPILE_ERROR', - \E_COMPILE_WARNING => 'E_COMPILE_WARNING', - \E_USER_ERROR => 'E_USER_ERROR', - \E_USER_WARNING => 'E_USER_WARNING', - \E_USER_NOTICE => 'E_USER_NOTICE', - \E_STRICT => 'E_STRICT', - ]; - - private static $framesCache = []; - - public static function castError(\Error $e, array $a, Stub $stub, bool $isNested, int $filter = 0) - { - return self::filterExceptionArray($stub->class, $a, "\0Error\0", $filter); - } - - public static function castException(\Exception $e, array $a, Stub $stub, bool $isNested, int $filter = 0) - { - return self::filterExceptionArray($stub->class, $a, "\0Exception\0", $filter); - } - - public static function castErrorException(\ErrorException $e, array $a, Stub $stub, bool $isNested) - { - if (isset($a[$s = Caster::PREFIX_PROTECTED.'severity'], self::$errorTypes[$a[$s]])) { - $a[$s] = new ConstStub(self::$errorTypes[$a[$s]], $a[$s]); - } - - return $a; - } - - public static function castThrowingCasterException(ThrowingCasterException $e, array $a, Stub $stub, bool $isNested) - { - $trace = Caster::PREFIX_VIRTUAL.'trace'; - $prefix = Caster::PREFIX_PROTECTED; - $xPrefix = "\0Exception\0"; - - if (isset($a[$xPrefix.'previous'], $a[$trace]) && $a[$xPrefix.'previous'] instanceof \Exception) { - $b = (array) $a[$xPrefix.'previous']; - $class = get_debug_type($a[$xPrefix.'previous']); - self::traceUnshift($b[$xPrefix.'trace'], $class, $b[$prefix.'file'], $b[$prefix.'line']); - $a[$trace] = new TraceStub($b[$xPrefix.'trace'], false, 0, -\count($a[$trace]->value)); - } - - unset($a[$xPrefix.'previous'], $a[$prefix.'code'], $a[$prefix.'file'], $a[$prefix.'line']); - - return $a; - } - - public static function castSilencedErrorContext(SilencedErrorContext $e, array $a, Stub $stub, bool $isNested) - { - $sPrefix = "\0".SilencedErrorContext::class."\0"; - - if (!isset($a[$s = $sPrefix.'severity'])) { - return $a; - } - - if (isset(self::$errorTypes[$a[$s]])) { - $a[$s] = new ConstStub(self::$errorTypes[$a[$s]], $a[$s]); - } - - $trace = [[ - 'file' => $a[$sPrefix.'file'], - 'line' => $a[$sPrefix.'line'], - ]]; - - if (isset($a[$sPrefix.'trace'])) { - $trace = array_merge($trace, $a[$sPrefix.'trace']); - } - - unset($a[$sPrefix.'file'], $a[$sPrefix.'line'], $a[$sPrefix.'trace']); - $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub($trace, self::$traceArgs); - - return $a; - } - - public static function castTraceStub(TraceStub $trace, array $a, Stub $stub, bool $isNested) - { - if (!$isNested) { - return $a; - } - $stub->class = ''; - $stub->handle = 0; - $frames = $trace->value; - $prefix = Caster::PREFIX_VIRTUAL; - - $a = []; - $j = \count($frames); - if (0 > $i = $trace->sliceOffset) { - $i = max(0, $j + $i); - } - if (!isset($trace->value[$i])) { - return []; - } - $lastCall = isset($frames[$i]['function']) ? (isset($frames[$i]['class']) ? $frames[0]['class'].$frames[$i]['type'] : '').$frames[$i]['function'].'()' : ''; - $frames[] = ['function' => '']; - $collapse = false; - - for ($j += $trace->numberingOffset - $i++; isset($frames[$i]); ++$i, --$j) { - $f = $frames[$i]; - $call = isset($f['function']) ? (isset($f['class']) ? $f['class'].$f['type'] : '').$f['function'] : '???'; - - $frame = new FrameStub( - [ - 'object' => $f['object'] ?? null, - 'class' => $f['class'] ?? null, - 'type' => $f['type'] ?? null, - 'function' => $f['function'] ?? null, - ] + $frames[$i - 1], - false, - true - ); - $f = self::castFrameStub($frame, [], $frame, true); - if (isset($f[$prefix.'src'])) { - foreach ($f[$prefix.'src']->value as $label => $frame) { - if (str_starts_with($label, "\0~collapse=0")) { - if ($collapse) { - $label = substr_replace($label, '1', 11, 1); - } else { - $collapse = true; - } - } - $label = substr_replace($label, "title=Stack level $j.&", 2, 0); - } - $f = $frames[$i - 1]; - if ($trace->keepArgs && !empty($f['args']) && $frame instanceof EnumStub) { - $frame->value['arguments'] = new ArgsStub($f['args'], $f['function'] ?? null, $f['class'] ?? null); - } - } elseif ('???' !== $lastCall) { - $label = new ClassStub($lastCall); - if (isset($label->attr['ellipsis'])) { - $label->attr['ellipsis'] += 2; - $label = substr_replace($prefix, "ellipsis-type=class&ellipsis={$label->attr['ellipsis']}&ellipsis-tail=1&title=Stack level $j.", 2, 0).$label->value.'()'; - } else { - $label = substr_replace($prefix, "title=Stack level $j.", 2, 0).$label->value.'()'; - } - } else { - $label = substr_replace($prefix, "title=Stack level $j.", 2, 0).$lastCall; - } - $a[substr_replace($label, sprintf('separator=%s&', $frame instanceof EnumStub ? ' ' : ':'), 2, 0)] = $frame; - - $lastCall = $call; - } - if (null !== $trace->sliceLength) { - $a = \array_slice($a, 0, $trace->sliceLength, true); - } - - return $a; - } - - public static function castFrameStub(FrameStub $frame, array $a, Stub $stub, bool $isNested) - { - if (!$isNested) { - return $a; - } - $f = $frame->value; - $prefix = Caster::PREFIX_VIRTUAL; - - if (isset($f['file'], $f['line'])) { - $cacheKey = $f; - unset($cacheKey['object'], $cacheKey['args']); - $cacheKey[] = self::$srcContext; - $cacheKey = implode('-', $cacheKey); - - if (isset(self::$framesCache[$cacheKey])) { - $a[$prefix.'src'] = self::$framesCache[$cacheKey]; - } else { - if (preg_match('/\((\d+)\)(?:\([\da-f]{32}\))? : (?:eval\(\)\'d code|runtime-created function)$/', $f['file'], $match)) { - $f['file'] = substr($f['file'], 0, -\strlen($match[0])); - $f['line'] = (int) $match[1]; - } - $src = $f['line']; - $srcKey = $f['file']; - $ellipsis = new LinkStub($srcKey, 0); - $srcAttr = 'collapse='.(int) $ellipsis->inVendor; - $ellipsisTail = $ellipsis->attr['ellipsis-tail'] ?? 0; - $ellipsis = $ellipsis->attr['ellipsis'] ?? 0; - - if (is_file($f['file']) && 0 <= self::$srcContext) { - if (!empty($f['class']) && (is_subclass_of($f['class'], 'Twig\Template') || is_subclass_of($f['class'], 'Twig_Template')) && method_exists($f['class'], 'getDebugInfo')) { - $template = null; - if (isset($f['object'])) { - $template = $f['object']; - } elseif ((new \ReflectionClass($f['class']))->isInstantiable()) { - $template = unserialize(sprintf('O:%d:"%s":0:{}', \strlen($f['class']), $f['class'])); - } - if (null !== $template) { - $ellipsis = 0; - $templateSrc = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : ''); - $templateInfo = $template->getDebugInfo(); - if (isset($templateInfo[$f['line']])) { - if (!method_exists($template, 'getSourceContext') || !is_file($templatePath = $template->getSourceContext()->getPath())) { - $templatePath = null; - } - if ($templateSrc) { - $src = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext, 'twig', $templatePath, $f); - $srcKey = ($templatePath ?: $template->getTemplateName()).':'.$templateInfo[$f['line']]; - } - } - } - } - if ($srcKey == $f['file']) { - $src = self::extractSource(file_get_contents($f['file']), $f['line'], self::$srcContext, 'php', $f['file'], $f); - $srcKey .= ':'.$f['line']; - if ($ellipsis) { - $ellipsis += 1 + \strlen($f['line']); - } - } - $srcAttr .= sprintf('&separator= &file=%s&line=%d', rawurlencode($f['file']), $f['line']); - } else { - $srcAttr .= '&separator=:'; - } - $srcAttr .= $ellipsis ? '&ellipsis-type=path&ellipsis='.$ellipsis.'&ellipsis-tail='.$ellipsisTail : ''; - self::$framesCache[$cacheKey] = $a[$prefix.'src'] = new EnumStub(["\0~$srcAttr\0$srcKey" => $src]); - } - } - - unset($a[$prefix.'args'], $a[$prefix.'line'], $a[$prefix.'file']); - if ($frame->inTraceStub) { - unset($a[$prefix.'class'], $a[$prefix.'type'], $a[$prefix.'function']); - } - foreach ($a as $k => $v) { - if (!$v) { - unset($a[$k]); - } - } - if ($frame->keepArgs && !empty($f['args'])) { - $a[$prefix.'arguments'] = new ArgsStub($f['args'], $f['function'], $f['class']); - } - - return $a; - } - - private static function filterExceptionArray(string $xClass, array $a, string $xPrefix, int $filter): array - { - if (isset($a[$xPrefix.'trace'])) { - $trace = $a[$xPrefix.'trace']; - unset($a[$xPrefix.'trace']); // Ensures the trace is always last - } else { - $trace = []; - } - - if (!($filter & Caster::EXCLUDE_VERBOSE) && $trace) { - if (isset($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line'])) { - self::traceUnshift($trace, $xClass, $a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line']); - } - $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub($trace, self::$traceArgs); - } - if (empty($a[$xPrefix.'previous'])) { - unset($a[$xPrefix.'previous']); - } - unset($a[$xPrefix.'string'], $a[Caster::PREFIX_DYNAMIC.'xdebug_message'], $a[Caster::PREFIX_DYNAMIC.'__destructorException']); - - if (isset($a[Caster::PREFIX_PROTECTED.'message']) && str_contains($a[Caster::PREFIX_PROTECTED.'message'], "@anonymous\0")) { - $a[Caster::PREFIX_PROTECTED.'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]; - }, $a[Caster::PREFIX_PROTECTED.'message']); - } - - if (isset($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line'])) { - $a[Caster::PREFIX_PROTECTED.'file'] = new LinkStub($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line']); - } - - return $a; - } - - private static function traceUnshift(array &$trace, ?string $class, string $file, int $line): void - { - if (isset($trace[0]['file'], $trace[0]['line']) && $trace[0]['file'] === $file && $trace[0]['line'] === $line) { - return; - } - array_unshift($trace, [ - 'function' => $class ? 'new '.$class : null, - 'file' => $file, - 'line' => $line, - ]); - } - - private static function extractSource(string $srcLines, int $line, int $srcContext, string $lang, ?string $file, array $frame): EnumStub - { - $srcLines = explode("\n", $srcLines); - $src = []; - - for ($i = $line - 1 - $srcContext; $i <= $line - 1 + $srcContext; ++$i) { - $src[] = ($srcLines[$i] ?? '')."\n"; - } - - if ($frame['function'] ?? false) { - $stub = new CutStub(new \stdClass()); - $stub->class = (isset($frame['class']) ? $frame['class'].$frame['type'] : '').$frame['function']; - $stub->type = Stub::TYPE_OBJECT; - $stub->attr['cut_hash'] = true; - $stub->attr['file'] = $frame['file']; - $stub->attr['line'] = $frame['line']; - - try { - $caller = isset($frame['class']) ? new \ReflectionMethod($frame['class'], $frame['function']) : new \ReflectionFunction($frame['function']); - $stub->class .= ReflectionCaster::getSignature(ReflectionCaster::castFunctionAbstract($caller, [], $stub, true, Caster::EXCLUDE_VERBOSE)); - - if ($f = $caller->getFileName()) { - $stub->attr['file'] = $f; - $stub->attr['line'] = $caller->getStartLine(); - } - } catch (\ReflectionException $e) { - // ignore fake class/function - } - - $srcLines = ["\0~separator=\0" => $stub]; - } else { - $stub = null; - $srcLines = []; - } - - $ltrim = 0; - do { - $pad = null; - for ($i = $srcContext << 1; $i >= 0; --$i) { - if (isset($src[$i][$ltrim]) && "\r" !== ($c = $src[$i][$ltrim]) && "\n" !== $c) { - if (null === $pad) { - $pad = $c; - } - if ((' ' !== $c && "\t" !== $c) || $pad !== $c) { - break; - } - } - } - ++$ltrim; - } while (0 > $i && null !== $pad); - - --$ltrim; - - foreach ($src as $i => $c) { - if ($ltrim) { - $c = isset($c[$ltrim]) && "\r" !== $c[$ltrim] ? substr($c, $ltrim) : ltrim($c, " \t"); - } - $c = substr($c, 0, -1); - if ($i !== $srcContext) { - $c = new ConstStub('default', $c); - } else { - $c = new ConstStub($c, $stub ? 'in '.$stub->class : ''); - if (null !== $file) { - $c->attr['file'] = $file; - $c->attr['line'] = $line; - } - } - $c->attr['lang'] = $lang; - $srcLines[sprintf("\0~separator=› &%d\0", $i + $line - $srcContext)] = $c; - } - - return new EnumStub($srcLines); - } -} diff --git a/lib/symfony/var-dumper/Caster/FiberCaster.php b/lib/symfony/var-dumper/Caster/FiberCaster.php deleted file mode 100644 index c74a9e59c..000000000 --- a/lib/symfony/var-dumper/Caster/FiberCaster.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts Fiber related classes to array representation. - * - * @author Grégoire Pineau <lyrixx@lyrixx.info> - */ -final class FiberCaster -{ - public static function castFiber(\Fiber $fiber, array $a, Stub $stub, bool $isNested, int $filter = 0) - { - $prefix = Caster::PREFIX_VIRTUAL; - - if ($fiber->isTerminated()) { - $status = 'terminated'; - } elseif ($fiber->isRunning()) { - $status = 'running'; - } elseif ($fiber->isSuspended()) { - $status = 'suspended'; - } elseif ($fiber->isStarted()) { - $status = 'started'; - } else { - $status = 'not started'; - } - - $a[$prefix.'status'] = $status; - - return $a; - } -} diff --git a/lib/symfony/var-dumper/Caster/FrameStub.php b/lib/symfony/var-dumper/Caster/FrameStub.php deleted file mode 100644 index 878675528..000000000 --- a/lib/symfony/var-dumper/Caster/FrameStub.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -/** - * Represents a single backtrace frame as returned by debug_backtrace() or Exception->getTrace(). - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class FrameStub extends EnumStub -{ - public $keepArgs; - public $inTraceStub; - - public function __construct(array $frame, bool $keepArgs = true, bool $inTraceStub = false) - { - $this->value = $frame; - $this->keepArgs = $keepArgs; - $this->inTraceStub = $inTraceStub; - } -} diff --git a/lib/symfony/var-dumper/Caster/GmpCaster.php b/lib/symfony/var-dumper/Caster/GmpCaster.php deleted file mode 100644 index b018cc7f8..000000000 --- a/lib/symfony/var-dumper/Caster/GmpCaster.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts GMP objects to array representation. - * - * @author Hamza Amrouche <hamza.simperfit@gmail.com> - * @author Nicolas Grekas <p@tchwork.com> - * - * @final - */ -class GmpCaster -{ - public static function castGmp(\GMP $gmp, array $a, Stub $stub, bool $isNested, int $filter): array - { - $a[Caster::PREFIX_VIRTUAL.'value'] = new ConstStub(gmp_strval($gmp), gmp_strval($gmp)); - - return $a; - } -} diff --git a/lib/symfony/var-dumper/Caster/ImagineCaster.php b/lib/symfony/var-dumper/Caster/ImagineCaster.php deleted file mode 100644 index d1289da33..000000000 --- a/lib/symfony/var-dumper/Caster/ImagineCaster.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Imagine\Image\ImageInterface; -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * @author Grégoire Pineau <lyrixx@lyrixx.info> - */ -final class ImagineCaster -{ - public static function castImage(ImageInterface $c, array $a, Stub $stub, bool $isNested): array - { - $imgData = $c->get('png'); - if (\strlen($imgData) > 1 * 1000 * 1000) { - $a += [ - Caster::PREFIX_VIRTUAL.'image' => new ConstStub($c->getSize()), - ]; - } else { - $a += [ - Caster::PREFIX_VIRTUAL.'image' => new ImgStub($imgData, 'image/png', $c->getSize()), - ]; - } - - return $a; - } -} diff --git a/lib/symfony/var-dumper/Caster/ImgStub.php b/lib/symfony/var-dumper/Caster/ImgStub.php deleted file mode 100644 index a16681f73..000000000 --- a/lib/symfony/var-dumper/Caster/ImgStub.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -/** - * @author Grégoire Pineau <lyrixx@lyrixx.info> - */ -class ImgStub extends ConstStub -{ - public function __construct(string $data, string $contentType, string $size = '') - { - $this->value = ''; - $this->attr['img-data'] = $data; - $this->attr['img-size'] = $size; - $this->attr['content-type'] = $contentType; - } -} diff --git a/lib/symfony/var-dumper/Caster/IntlCaster.php b/lib/symfony/var-dumper/Caster/IntlCaster.php deleted file mode 100644 index 1ed91d4d6..000000000 --- a/lib/symfony/var-dumper/Caster/IntlCaster.php +++ /dev/null @@ -1,172 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * @author Jan Schädlich <jan.schaedlich@sensiolabs.de> - * - * @final - */ -class IntlCaster -{ - public static function castMessageFormatter(\MessageFormatter $c, array $a, Stub $stub, bool $isNested) - { - $a += [ - Caster::PREFIX_VIRTUAL.'locale' => $c->getLocale(), - Caster::PREFIX_VIRTUAL.'pattern' => $c->getPattern(), - ]; - - return self::castError($c, $a); - } - - public static function castNumberFormatter(\NumberFormatter $c, array $a, Stub $stub, bool $isNested, int $filter = 0) - { - $a += [ - Caster::PREFIX_VIRTUAL.'locale' => $c->getLocale(), - Caster::PREFIX_VIRTUAL.'pattern' => $c->getPattern(), - ]; - - if ($filter & Caster::EXCLUDE_VERBOSE) { - $stub->cut += 3; - - return self::castError($c, $a); - } - - $a += [ - Caster::PREFIX_VIRTUAL.'attributes' => new EnumStub( - [ - 'PARSE_INT_ONLY' => $c->getAttribute(\NumberFormatter::PARSE_INT_ONLY), - 'GROUPING_USED' => $c->getAttribute(\NumberFormatter::GROUPING_USED), - 'DECIMAL_ALWAYS_SHOWN' => $c->getAttribute(\NumberFormatter::DECIMAL_ALWAYS_SHOWN), - 'MAX_INTEGER_DIGITS' => $c->getAttribute(\NumberFormatter::MAX_INTEGER_DIGITS), - 'MIN_INTEGER_DIGITS' => $c->getAttribute(\NumberFormatter::MIN_INTEGER_DIGITS), - 'INTEGER_DIGITS' => $c->getAttribute(\NumberFormatter::INTEGER_DIGITS), - 'MAX_FRACTION_DIGITS' => $c->getAttribute(\NumberFormatter::MAX_FRACTION_DIGITS), - 'MIN_FRACTION_DIGITS' => $c->getAttribute(\NumberFormatter::MIN_FRACTION_DIGITS), - 'FRACTION_DIGITS' => $c->getAttribute(\NumberFormatter::FRACTION_DIGITS), - 'MULTIPLIER' => $c->getAttribute(\NumberFormatter::MULTIPLIER), - 'GROUPING_SIZE' => $c->getAttribute(\NumberFormatter::GROUPING_SIZE), - 'ROUNDING_MODE' => $c->getAttribute(\NumberFormatter::ROUNDING_MODE), - 'ROUNDING_INCREMENT' => $c->getAttribute(\NumberFormatter::ROUNDING_INCREMENT), - 'FORMAT_WIDTH' => $c->getAttribute(\NumberFormatter::FORMAT_WIDTH), - 'PADDING_POSITION' => $c->getAttribute(\NumberFormatter::PADDING_POSITION), - 'SECONDARY_GROUPING_SIZE' => $c->getAttribute(\NumberFormatter::SECONDARY_GROUPING_SIZE), - 'SIGNIFICANT_DIGITS_USED' => $c->getAttribute(\NumberFormatter::SIGNIFICANT_DIGITS_USED), - 'MIN_SIGNIFICANT_DIGITS' => $c->getAttribute(\NumberFormatter::MIN_SIGNIFICANT_DIGITS), - 'MAX_SIGNIFICANT_DIGITS' => $c->getAttribute(\NumberFormatter::MAX_SIGNIFICANT_DIGITS), - 'LENIENT_PARSE' => $c->getAttribute(\NumberFormatter::LENIENT_PARSE), - ] - ), - Caster::PREFIX_VIRTUAL.'text_attributes' => new EnumStub( - [ - 'POSITIVE_PREFIX' => $c->getTextAttribute(\NumberFormatter::POSITIVE_PREFIX), - 'POSITIVE_SUFFIX' => $c->getTextAttribute(\NumberFormatter::POSITIVE_SUFFIX), - 'NEGATIVE_PREFIX' => $c->getTextAttribute(\NumberFormatter::NEGATIVE_PREFIX), - 'NEGATIVE_SUFFIX' => $c->getTextAttribute(\NumberFormatter::NEGATIVE_SUFFIX), - 'PADDING_CHARACTER' => $c->getTextAttribute(\NumberFormatter::PADDING_CHARACTER), - 'CURRENCY_CODE' => $c->getTextAttribute(\NumberFormatter::CURRENCY_CODE), - 'DEFAULT_RULESET' => $c->getTextAttribute(\NumberFormatter::DEFAULT_RULESET), - 'PUBLIC_RULESETS' => $c->getTextAttribute(\NumberFormatter::PUBLIC_RULESETS), - ] - ), - Caster::PREFIX_VIRTUAL.'symbols' => new EnumStub( - [ - 'DECIMAL_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL), - 'GROUPING_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL), - 'PATTERN_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::PATTERN_SEPARATOR_SYMBOL), - 'PERCENT_SYMBOL' => $c->getSymbol(\NumberFormatter::PERCENT_SYMBOL), - 'ZERO_DIGIT_SYMBOL' => $c->getSymbol(\NumberFormatter::ZERO_DIGIT_SYMBOL), - 'DIGIT_SYMBOL' => $c->getSymbol(\NumberFormatter::DIGIT_SYMBOL), - 'MINUS_SIGN_SYMBOL' => $c->getSymbol(\NumberFormatter::MINUS_SIGN_SYMBOL), - 'PLUS_SIGN_SYMBOL' => $c->getSymbol(\NumberFormatter::PLUS_SIGN_SYMBOL), - 'CURRENCY_SYMBOL' => $c->getSymbol(\NumberFormatter::CURRENCY_SYMBOL), - 'INTL_CURRENCY_SYMBOL' => $c->getSymbol(\NumberFormatter::INTL_CURRENCY_SYMBOL), - 'MONETARY_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::MONETARY_SEPARATOR_SYMBOL), - 'EXPONENTIAL_SYMBOL' => $c->getSymbol(\NumberFormatter::EXPONENTIAL_SYMBOL), - 'PERMILL_SYMBOL' => $c->getSymbol(\NumberFormatter::PERMILL_SYMBOL), - 'PAD_ESCAPE_SYMBOL' => $c->getSymbol(\NumberFormatter::PAD_ESCAPE_SYMBOL), - 'INFINITY_SYMBOL' => $c->getSymbol(\NumberFormatter::INFINITY_SYMBOL), - 'NAN_SYMBOL' => $c->getSymbol(\NumberFormatter::NAN_SYMBOL), - 'SIGNIFICANT_DIGIT_SYMBOL' => $c->getSymbol(\NumberFormatter::SIGNIFICANT_DIGIT_SYMBOL), - 'MONETARY_GROUPING_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL), - ] - ), - ]; - - return self::castError($c, $a); - } - - public static function castIntlTimeZone(\IntlTimeZone $c, array $a, Stub $stub, bool $isNested) - { - $a += [ - Caster::PREFIX_VIRTUAL.'display_name' => $c->getDisplayName(), - Caster::PREFIX_VIRTUAL.'id' => $c->getID(), - Caster::PREFIX_VIRTUAL.'raw_offset' => $c->getRawOffset(), - ]; - - if ($c->useDaylightTime()) { - $a += [ - Caster::PREFIX_VIRTUAL.'dst_savings' => $c->getDSTSavings(), - ]; - } - - return self::castError($c, $a); - } - - public static function castIntlCalendar(\IntlCalendar $c, array $a, Stub $stub, bool $isNested, int $filter = 0) - { - $a += [ - Caster::PREFIX_VIRTUAL.'type' => $c->getType(), - Caster::PREFIX_VIRTUAL.'first_day_of_week' => $c->getFirstDayOfWeek(), - Caster::PREFIX_VIRTUAL.'minimal_days_in_first_week' => $c->getMinimalDaysInFirstWeek(), - Caster::PREFIX_VIRTUAL.'repeated_wall_time_option' => $c->getRepeatedWallTimeOption(), - Caster::PREFIX_VIRTUAL.'skipped_wall_time_option' => $c->getSkippedWallTimeOption(), - Caster::PREFIX_VIRTUAL.'time' => $c->getTime(), - Caster::PREFIX_VIRTUAL.'in_daylight_time' => $c->inDaylightTime(), - Caster::PREFIX_VIRTUAL.'is_lenient' => $c->isLenient(), - Caster::PREFIX_VIRTUAL.'time_zone' => ($filter & Caster::EXCLUDE_VERBOSE) ? new CutStub($c->getTimeZone()) : $c->getTimeZone(), - ]; - - return self::castError($c, $a); - } - - public static function castIntlDateFormatter(\IntlDateFormatter $c, array $a, Stub $stub, bool $isNested, int $filter = 0) - { - $a += [ - Caster::PREFIX_VIRTUAL.'locale' => $c->getLocale(), - Caster::PREFIX_VIRTUAL.'pattern' => $c->getPattern(), - Caster::PREFIX_VIRTUAL.'calendar' => $c->getCalendar(), - Caster::PREFIX_VIRTUAL.'time_zone_id' => $c->getTimeZoneId(), - Caster::PREFIX_VIRTUAL.'time_type' => $c->getTimeType(), - Caster::PREFIX_VIRTUAL.'date_type' => $c->getDateType(), - Caster::PREFIX_VIRTUAL.'calendar_object' => ($filter & Caster::EXCLUDE_VERBOSE) ? new CutStub($c->getCalendarObject()) : $c->getCalendarObject(), - Caster::PREFIX_VIRTUAL.'time_zone' => ($filter & Caster::EXCLUDE_VERBOSE) ? new CutStub($c->getTimeZone()) : $c->getTimeZone(), - ]; - - return self::castError($c, $a); - } - - private static function castError(object $c, array $a): array - { - if ($errorCode = $c->getErrorCode()) { - $a += [ - Caster::PREFIX_VIRTUAL.'error_code' => $errorCode, - Caster::PREFIX_VIRTUAL.'error_message' => $c->getErrorMessage(), - ]; - } - - return $a; - } -} diff --git a/lib/symfony/var-dumper/Caster/LinkStub.php b/lib/symfony/var-dumper/Caster/LinkStub.php deleted file mode 100644 index 7e0780339..000000000 --- a/lib/symfony/var-dumper/Caster/LinkStub.php +++ /dev/null @@ -1,108 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -/** - * Represents a file or a URL. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class LinkStub extends ConstStub -{ - public $inVendor = false; - - private static $vendorRoots; - private static $composerRoots; - - public function __construct(string $label, int $line = 0, string $href = null) - { - $this->value = $label; - - if (null === $href) { - $href = $label; - } - if (!\is_string($href)) { - return; - } - if (str_starts_with($href, 'file://')) { - if ($href === $label) { - $label = substr($label, 7); - } - $href = substr($href, 7); - } elseif (str_contains($href, '://')) { - $this->attr['href'] = $href; - - return; - } - if (!is_file($href)) { - return; - } - if ($line) { - $this->attr['line'] = $line; - } - if ($label !== $this->attr['file'] = realpath($href) ?: $href) { - return; - } - if ($composerRoot = $this->getComposerRoot($href, $this->inVendor)) { - $this->attr['ellipsis'] = \strlen($href) - \strlen($composerRoot) + 1; - $this->attr['ellipsis-type'] = 'path'; - $this->attr['ellipsis-tail'] = 1 + ($this->inVendor ? 2 + \strlen(implode('', \array_slice(explode(\DIRECTORY_SEPARATOR, substr($href, 1 - $this->attr['ellipsis'])), 0, 2))) : 0); - } elseif (3 < \count($ellipsis = explode(\DIRECTORY_SEPARATOR, $href))) { - $this->attr['ellipsis'] = 2 + \strlen(implode('', \array_slice($ellipsis, -2))); - $this->attr['ellipsis-type'] = 'path'; - $this->attr['ellipsis-tail'] = 1; - } - } - - private function getComposerRoot(string $file, bool &$inVendor) - { - if (null === self::$vendorRoots) { - self::$vendorRoots = []; - - foreach (get_declared_classes() as $class) { - if ('C' === $class[0] && str_starts_with($class, 'ComposerAutoloaderInit')) { - $r = new \ReflectionClass($class); - $v = \dirname($r->getFileName(), 2); - if (is_file($v.'/composer/installed.json')) { - self::$vendorRoots[] = $v.\DIRECTORY_SEPARATOR; - } - } - } - } - $inVendor = false; - - if (isset(self::$composerRoots[$dir = \dirname($file)])) { - return self::$composerRoots[$dir]; - } - - foreach (self::$vendorRoots as $root) { - if ($inVendor = str_starts_with($file, $root)) { - return $root; - } - } - - $parent = $dir; - while (!@is_file($parent.'/composer.json')) { - if (!@file_exists($parent)) { - // open_basedir restriction in effect - break; - } - if ($parent === \dirname($parent)) { - return self::$composerRoots[$dir] = false; - } - - $parent = \dirname($parent); - } - - return self::$composerRoots[$dir] = $parent.\DIRECTORY_SEPARATOR; - } -} diff --git a/lib/symfony/var-dumper/Caster/MemcachedCaster.php b/lib/symfony/var-dumper/Caster/MemcachedCaster.php deleted file mode 100644 index cfef19acc..000000000 --- a/lib/symfony/var-dumper/Caster/MemcachedCaster.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * @author Jan Schädlich <jan.schaedlich@sensiolabs.de> - * - * @final - */ -class MemcachedCaster -{ - private static $optionConstants; - private static $defaultOptions; - - public static function castMemcached(\Memcached $c, array $a, Stub $stub, bool $isNested) - { - $a += [ - Caster::PREFIX_VIRTUAL.'servers' => $c->getServerList(), - Caster::PREFIX_VIRTUAL.'options' => new EnumStub( - self::getNonDefaultOptions($c) - ), - ]; - - return $a; - } - - private static function getNonDefaultOptions(\Memcached $c): array - { - self::$defaultOptions = self::$defaultOptions ?? self::discoverDefaultOptions(); - self::$optionConstants = self::$optionConstants ?? self::getOptionConstants(); - - $nonDefaultOptions = []; - foreach (self::$optionConstants as $constantKey => $value) { - if (self::$defaultOptions[$constantKey] !== $option = $c->getOption($value)) { - $nonDefaultOptions[$constantKey] = $option; - } - } - - return $nonDefaultOptions; - } - - private static function discoverDefaultOptions(): array - { - $defaultMemcached = new \Memcached(); - $defaultMemcached->addServer('127.0.0.1', 11211); - - $defaultOptions = []; - self::$optionConstants = self::$optionConstants ?? self::getOptionConstants(); - - foreach (self::$optionConstants as $constantKey => $value) { - $defaultOptions[$constantKey] = $defaultMemcached->getOption($value); - } - - return $defaultOptions; - } - - private static function getOptionConstants(): array - { - $reflectedMemcached = new \ReflectionClass(\Memcached::class); - - $optionConstants = []; - foreach ($reflectedMemcached->getConstants() as $constantKey => $value) { - if (str_starts_with($constantKey, 'OPT_')) { - $optionConstants[$constantKey] = $value; - } - } - - return $optionConstants; - } -} diff --git a/lib/symfony/var-dumper/Caster/MysqliCaster.php b/lib/symfony/var-dumper/Caster/MysqliCaster.php deleted file mode 100644 index bfe6f0822..000000000 --- a/lib/symfony/var-dumper/Caster/MysqliCaster.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -final class MysqliCaster -{ - public static function castMysqliDriver(\mysqli_driver $c, array $a, Stub $stub, bool $isNested): array - { - foreach ($a as $k => $v) { - if (isset($c->$k)) { - $a[$k] = $c->$k; - } - } - - return $a; - } -} diff --git a/lib/symfony/var-dumper/Caster/PdoCaster.php b/lib/symfony/var-dumper/Caster/PdoCaster.php deleted file mode 100644 index 140473b53..000000000 --- a/lib/symfony/var-dumper/Caster/PdoCaster.php +++ /dev/null @@ -1,122 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts PDO related classes to array representation. - * - * @author Nicolas Grekas <p@tchwork.com> - * - * @final - */ -class PdoCaster -{ - private const PDO_ATTRIBUTES = [ - 'CASE' => [ - \PDO::CASE_LOWER => 'LOWER', - \PDO::CASE_NATURAL => 'NATURAL', - \PDO::CASE_UPPER => 'UPPER', - ], - 'ERRMODE' => [ - \PDO::ERRMODE_SILENT => 'SILENT', - \PDO::ERRMODE_WARNING => 'WARNING', - \PDO::ERRMODE_EXCEPTION => 'EXCEPTION', - ], - 'TIMEOUT', - 'PREFETCH', - 'AUTOCOMMIT', - 'PERSISTENT', - 'DRIVER_NAME', - 'SERVER_INFO', - 'ORACLE_NULLS' => [ - \PDO::NULL_NATURAL => 'NATURAL', - \PDO::NULL_EMPTY_STRING => 'EMPTY_STRING', - \PDO::NULL_TO_STRING => 'TO_STRING', - ], - 'CLIENT_VERSION', - 'SERVER_VERSION', - 'STATEMENT_CLASS', - 'EMULATE_PREPARES', - 'CONNECTION_STATUS', - 'STRINGIFY_FETCHES', - 'DEFAULT_FETCH_MODE' => [ - \PDO::FETCH_ASSOC => 'ASSOC', - \PDO::FETCH_BOTH => 'BOTH', - \PDO::FETCH_LAZY => 'LAZY', - \PDO::FETCH_NUM => 'NUM', - \PDO::FETCH_OBJ => 'OBJ', - ], - ]; - - public static function castPdo(\PDO $c, array $a, Stub $stub, bool $isNested) - { - $attr = []; - $errmode = $c->getAttribute(\PDO::ATTR_ERRMODE); - $c->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); - - foreach (self::PDO_ATTRIBUTES as $k => $v) { - if (!isset($k[0])) { - $k = $v; - $v = []; - } - - try { - $attr[$k] = 'ERRMODE' === $k ? $errmode : $c->getAttribute(\constant('PDO::ATTR_'.$k)); - if ($v && isset($v[$attr[$k]])) { - $attr[$k] = new ConstStub($v[$attr[$k]], $attr[$k]); - } - } catch (\Exception $e) { - } - } - if (isset($attr[$k = 'STATEMENT_CLASS'][1])) { - if ($attr[$k][1]) { - $attr[$k][1] = new ArgsStub($attr[$k][1], '__construct', $attr[$k][0]); - } - $attr[$k][0] = new ClassStub($attr[$k][0]); - } - - $prefix = Caster::PREFIX_VIRTUAL; - $a += [ - $prefix.'inTransaction' => method_exists($c, 'inTransaction'), - $prefix.'errorInfo' => $c->errorInfo(), - $prefix.'attributes' => new EnumStub($attr), - ]; - - if ($a[$prefix.'inTransaction']) { - $a[$prefix.'inTransaction'] = $c->inTransaction(); - } else { - unset($a[$prefix.'inTransaction']); - } - - if (!isset($a[$prefix.'errorInfo'][1], $a[$prefix.'errorInfo'][2])) { - unset($a[$prefix.'errorInfo']); - } - - $c->setAttribute(\PDO::ATTR_ERRMODE, $errmode); - - return $a; - } - - public static function castPdoStatement(\PDOStatement $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - $a[$prefix.'errorInfo'] = $c->errorInfo(); - - if (!isset($a[$prefix.'errorInfo'][1], $a[$prefix.'errorInfo'][2])) { - unset($a[$prefix.'errorInfo']); - } - - return $a; - } -} diff --git a/lib/symfony/var-dumper/Caster/PgSqlCaster.php b/lib/symfony/var-dumper/Caster/PgSqlCaster.php deleted file mode 100644 index d8e5b5253..000000000 --- a/lib/symfony/var-dumper/Caster/PgSqlCaster.php +++ /dev/null @@ -1,156 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts pqsql resources to array representation. - * - * @author Nicolas Grekas <p@tchwork.com> - * - * @final - */ -class PgSqlCaster -{ - private const PARAM_CODES = [ - 'server_encoding', - 'client_encoding', - 'is_superuser', - 'session_authorization', - 'DateStyle', - 'TimeZone', - 'IntervalStyle', - 'integer_datetimes', - 'application_name', - 'standard_conforming_strings', - ]; - - private const TRANSACTION_STATUS = [ - \PGSQL_TRANSACTION_IDLE => 'PGSQL_TRANSACTION_IDLE', - \PGSQL_TRANSACTION_ACTIVE => 'PGSQL_TRANSACTION_ACTIVE', - \PGSQL_TRANSACTION_INTRANS => 'PGSQL_TRANSACTION_INTRANS', - \PGSQL_TRANSACTION_INERROR => 'PGSQL_TRANSACTION_INERROR', - \PGSQL_TRANSACTION_UNKNOWN => 'PGSQL_TRANSACTION_UNKNOWN', - ]; - - private const RESULT_STATUS = [ - \PGSQL_EMPTY_QUERY => 'PGSQL_EMPTY_QUERY', - \PGSQL_COMMAND_OK => 'PGSQL_COMMAND_OK', - \PGSQL_TUPLES_OK => 'PGSQL_TUPLES_OK', - \PGSQL_COPY_OUT => 'PGSQL_COPY_OUT', - \PGSQL_COPY_IN => 'PGSQL_COPY_IN', - \PGSQL_BAD_RESPONSE => 'PGSQL_BAD_RESPONSE', - \PGSQL_NONFATAL_ERROR => 'PGSQL_NONFATAL_ERROR', - \PGSQL_FATAL_ERROR => 'PGSQL_FATAL_ERROR', - ]; - - private const DIAG_CODES = [ - 'severity' => \PGSQL_DIAG_SEVERITY, - 'sqlstate' => \PGSQL_DIAG_SQLSTATE, - 'message' => \PGSQL_DIAG_MESSAGE_PRIMARY, - 'detail' => \PGSQL_DIAG_MESSAGE_DETAIL, - 'hint' => \PGSQL_DIAG_MESSAGE_HINT, - 'statement position' => \PGSQL_DIAG_STATEMENT_POSITION, - 'internal position' => \PGSQL_DIAG_INTERNAL_POSITION, - 'internal query' => \PGSQL_DIAG_INTERNAL_QUERY, - 'context' => \PGSQL_DIAG_CONTEXT, - 'file' => \PGSQL_DIAG_SOURCE_FILE, - 'line' => \PGSQL_DIAG_SOURCE_LINE, - 'function' => \PGSQL_DIAG_SOURCE_FUNCTION, - ]; - - public static function castLargeObject($lo, array $a, Stub $stub, bool $isNested) - { - $a['seek position'] = pg_lo_tell($lo); - - return $a; - } - - public static function castLink($link, array $a, Stub $stub, bool $isNested) - { - $a['status'] = pg_connection_status($link); - $a['status'] = new ConstStub(\PGSQL_CONNECTION_OK === $a['status'] ? 'PGSQL_CONNECTION_OK' : 'PGSQL_CONNECTION_BAD', $a['status']); - $a['busy'] = pg_connection_busy($link); - - $a['transaction'] = pg_transaction_status($link); - if (isset(self::TRANSACTION_STATUS[$a['transaction']])) { - $a['transaction'] = new ConstStub(self::TRANSACTION_STATUS[$a['transaction']], $a['transaction']); - } - - $a['pid'] = pg_get_pid($link); - $a['last error'] = pg_last_error($link); - $a['last notice'] = pg_last_notice($link); - $a['host'] = pg_host($link); - $a['port'] = pg_port($link); - $a['dbname'] = pg_dbname($link); - $a['options'] = pg_options($link); - $a['version'] = pg_version($link); - - foreach (self::PARAM_CODES as $v) { - if (false !== $s = pg_parameter_status($link, $v)) { - $a['param'][$v] = $s; - } - } - - $a['param']['client_encoding'] = pg_client_encoding($link); - $a['param'] = new EnumStub($a['param']); - - return $a; - } - - public static function castResult($result, array $a, Stub $stub, bool $isNested) - { - $a['num rows'] = pg_num_rows($result); - $a['status'] = pg_result_status($result); - if (isset(self::RESULT_STATUS[$a['status']])) { - $a['status'] = new ConstStub(self::RESULT_STATUS[$a['status']], $a['status']); - } - $a['command-completion tag'] = pg_result_status($result, \PGSQL_STATUS_STRING); - - if (-1 === $a['num rows']) { - foreach (self::DIAG_CODES as $k => $v) { - $a['error'][$k] = pg_result_error_field($result, $v); - } - } - - $a['affected rows'] = pg_affected_rows($result); - $a['last OID'] = pg_last_oid($result); - - $fields = pg_num_fields($result); - - for ($i = 0; $i < $fields; ++$i) { - $field = [ - 'name' => pg_field_name($result, $i), - 'table' => sprintf('%s (OID: %s)', pg_field_table($result, $i), pg_field_table($result, $i, true)), - 'type' => sprintf('%s (OID: %s)', pg_field_type($result, $i), pg_field_type_oid($result, $i)), - 'nullable' => (bool) pg_field_is_null($result, $i), - 'storage' => pg_field_size($result, $i).' bytes', - 'display' => pg_field_prtlen($result, $i).' chars', - ]; - if (' (OID: )' === $field['table']) { - $field['table'] = null; - } - if ('-1 bytes' === $field['storage']) { - $field['storage'] = 'variable size'; - } elseif ('1 bytes' === $field['storage']) { - $field['storage'] = '1 byte'; - } - if ('1 chars' === $field['display']) { - $field['display'] = '1 char'; - } - $a['fields'][] = new EnumStub($field); - } - - return $a; - } -} diff --git a/lib/symfony/var-dumper/Caster/ProxyManagerCaster.php b/lib/symfony/var-dumper/Caster/ProxyManagerCaster.php deleted file mode 100644 index e7120191f..000000000 --- a/lib/symfony/var-dumper/Caster/ProxyManagerCaster.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use ProxyManager\Proxy\ProxyInterface; -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @final - */ -class ProxyManagerCaster -{ - public static function castProxy(ProxyInterface $c, array $a, Stub $stub, bool $isNested) - { - if ($parent = get_parent_class($c)) { - $stub->class .= ' - '.$parent; - } - $stub->class .= '@proxy'; - - return $a; - } -} diff --git a/lib/symfony/var-dumper/Caster/RdKafkaCaster.php b/lib/symfony/var-dumper/Caster/RdKafkaCaster.php deleted file mode 100644 index db4bba8d3..000000000 --- a/lib/symfony/var-dumper/Caster/RdKafkaCaster.php +++ /dev/null @@ -1,186 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use RdKafka\Conf; -use RdKafka\Exception as RdKafkaException; -use RdKafka\KafkaConsumer; -use RdKafka\Message; -use RdKafka\Metadata\Broker as BrokerMetadata; -use RdKafka\Metadata\Collection as CollectionMetadata; -use RdKafka\Metadata\Partition as PartitionMetadata; -use RdKafka\Metadata\Topic as TopicMetadata; -use RdKafka\Topic; -use RdKafka\TopicConf; -use RdKafka\TopicPartition; -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts RdKafka related classes to array representation. - * - * @author Romain Neutron <imprec@gmail.com> - */ -class RdKafkaCaster -{ - public static function castKafkaConsumer(KafkaConsumer $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - try { - $assignment = $c->getAssignment(); - } catch (RdKafkaException $e) { - $assignment = []; - } - - $a += [ - $prefix.'subscription' => $c->getSubscription(), - $prefix.'assignment' => $assignment, - ]; - - $a += self::extractMetadata($c); - - return $a; - } - - public static function castTopic(Topic $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - $a += [ - $prefix.'name' => $c->getName(), - ]; - - return $a; - } - - public static function castTopicPartition(TopicPartition $c, array $a) - { - $prefix = Caster::PREFIX_VIRTUAL; - - $a += [ - $prefix.'offset' => $c->getOffset(), - $prefix.'partition' => $c->getPartition(), - $prefix.'topic' => $c->getTopic(), - ]; - - return $a; - } - - public static function castMessage(Message $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - $a += [ - $prefix.'errstr' => $c->errstr(), - ]; - - return $a; - } - - public static function castConf(Conf $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - foreach ($c->dump() as $key => $value) { - $a[$prefix.$key] = $value; - } - - return $a; - } - - public static function castTopicConf(TopicConf $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - foreach ($c->dump() as $key => $value) { - $a[$prefix.$key] = $value; - } - - return $a; - } - - public static function castRdKafka(\RdKafka $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - $a += [ - $prefix.'out_q_len' => $c->getOutQLen(), - ]; - - $a += self::extractMetadata($c); - - return $a; - } - - public static function castCollectionMetadata(CollectionMetadata $c, array $a, Stub $stub, bool $isNested) - { - $a += iterator_to_array($c); - - return $a; - } - - public static function castTopicMetadata(TopicMetadata $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - $a += [ - $prefix.'name' => $c->getTopic(), - $prefix.'partitions' => $c->getPartitions(), - ]; - - return $a; - } - - public static function castPartitionMetadata(PartitionMetadata $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - $a += [ - $prefix.'id' => $c->getId(), - $prefix.'err' => $c->getErr(), - $prefix.'leader' => $c->getLeader(), - ]; - - return $a; - } - - public static function castBrokerMetadata(BrokerMetadata $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - $a += [ - $prefix.'id' => $c->getId(), - $prefix.'host' => $c->getHost(), - $prefix.'port' => $c->getPort(), - ]; - - return $a; - } - - private static function extractMetadata($c) - { - $prefix = Caster::PREFIX_VIRTUAL; - - try { - $m = $c->getMetadata(true, null, 500); - } catch (RdKafkaException $e) { - return []; - } - - return [ - $prefix.'orig_broker_id' => $m->getOrigBrokerId(), - $prefix.'orig_broker_name' => $m->getOrigBrokerName(), - $prefix.'brokers' => $m->getBrokers(), - $prefix.'topics' => $m->getTopics(), - ]; - } -} diff --git a/lib/symfony/var-dumper/Caster/RedisCaster.php b/lib/symfony/var-dumper/Caster/RedisCaster.php deleted file mode 100644 index 8f97eaad3..000000000 --- a/lib/symfony/var-dumper/Caster/RedisCaster.php +++ /dev/null @@ -1,152 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts Redis class from ext-redis to array representation. - * - * @author Nicolas Grekas <p@tchwork.com> - * - * @final - */ -class RedisCaster -{ - private const SERIALIZERS = [ - \Redis::SERIALIZER_NONE => 'NONE', - \Redis::SERIALIZER_PHP => 'PHP', - 2 => 'IGBINARY', // Optional Redis::SERIALIZER_IGBINARY - ]; - - private const MODES = [ - \Redis::ATOMIC => 'ATOMIC', - \Redis::MULTI => 'MULTI', - \Redis::PIPELINE => 'PIPELINE', - ]; - - private const COMPRESSION_MODES = [ - 0 => 'NONE', // Redis::COMPRESSION_NONE - 1 => 'LZF', // Redis::COMPRESSION_LZF - ]; - - private const FAILOVER_OPTIONS = [ - \RedisCluster::FAILOVER_NONE => 'NONE', - \RedisCluster::FAILOVER_ERROR => 'ERROR', - \RedisCluster::FAILOVER_DISTRIBUTE => 'DISTRIBUTE', - \RedisCluster::FAILOVER_DISTRIBUTE_SLAVES => 'DISTRIBUTE_SLAVES', - ]; - - public static function castRedis(\Redis $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - if (!$connected = $c->isConnected()) { - return $a + [ - $prefix.'isConnected' => $connected, - ]; - } - - $mode = $c->getMode(); - - return $a + [ - $prefix.'isConnected' => $connected, - $prefix.'host' => $c->getHost(), - $prefix.'port' => $c->getPort(), - $prefix.'auth' => $c->getAuth(), - $prefix.'mode' => isset(self::MODES[$mode]) ? new ConstStub(self::MODES[$mode], $mode) : $mode, - $prefix.'dbNum' => $c->getDbNum(), - $prefix.'timeout' => $c->getTimeout(), - $prefix.'lastError' => $c->getLastError(), - $prefix.'persistentId' => $c->getPersistentID(), - $prefix.'options' => self::getRedisOptions($c), - ]; - } - - public static function castRedisArray(\RedisArray $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - return $a + [ - $prefix.'hosts' => $c->_hosts(), - $prefix.'function' => ClassStub::wrapCallable($c->_function()), - $prefix.'lastError' => $c->getLastError(), - $prefix.'options' => self::getRedisOptions($c), - ]; - } - - public static function castRedisCluster(\RedisCluster $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - $failover = $c->getOption(\RedisCluster::OPT_SLAVE_FAILOVER); - - $a += [ - $prefix.'_masters' => $c->_masters(), - $prefix.'_redir' => $c->_redir(), - $prefix.'mode' => new ConstStub($c->getMode() ? 'MULTI' : 'ATOMIC', $c->getMode()), - $prefix.'lastError' => $c->getLastError(), - $prefix.'options' => self::getRedisOptions($c, [ - 'SLAVE_FAILOVER' => isset(self::FAILOVER_OPTIONS[$failover]) ? new ConstStub(self::FAILOVER_OPTIONS[$failover], $failover) : $failover, - ]), - ]; - - return $a; - } - - /** - * @param \Redis|\RedisArray|\RedisCluster $redis - */ - private static function getRedisOptions($redis, array $options = []): EnumStub - { - $serializer = $redis->getOption(\Redis::OPT_SERIALIZER); - if (\is_array($serializer)) { - foreach ($serializer as &$v) { - if (isset(self::SERIALIZERS[$v])) { - $v = new ConstStub(self::SERIALIZERS[$v], $v); - } - } - } elseif (isset(self::SERIALIZERS[$serializer])) { - $serializer = new ConstStub(self::SERIALIZERS[$serializer], $serializer); - } - - $compression = \defined('Redis::OPT_COMPRESSION') ? $redis->getOption(\Redis::OPT_COMPRESSION) : 0; - if (\is_array($compression)) { - foreach ($compression as &$v) { - if (isset(self::COMPRESSION_MODES[$v])) { - $v = new ConstStub(self::COMPRESSION_MODES[$v], $v); - } - } - } elseif (isset(self::COMPRESSION_MODES[$compression])) { - $compression = new ConstStub(self::COMPRESSION_MODES[$compression], $compression); - } - - $retry = \defined('Redis::OPT_SCAN') ? $redis->getOption(\Redis::OPT_SCAN) : 0; - if (\is_array($retry)) { - foreach ($retry as &$v) { - $v = new ConstStub($v ? 'RETRY' : 'NORETRY', $v); - } - } else { - $retry = new ConstStub($retry ? 'RETRY' : 'NORETRY', $retry); - } - - $options += [ - 'TCP_KEEPALIVE' => \defined('Redis::OPT_TCP_KEEPALIVE') ? $redis->getOption(\Redis::OPT_TCP_KEEPALIVE) : 0, - 'READ_TIMEOUT' => $redis->getOption(\Redis::OPT_READ_TIMEOUT), - 'COMPRESSION' => $compression, - 'SERIALIZER' => $serializer, - 'PREFIX' => $redis->getOption(\Redis::OPT_PREFIX), - 'SCAN' => $retry, - ]; - - return new EnumStub($options); - } -} diff --git a/lib/symfony/var-dumper/Caster/ReflectionCaster.php b/lib/symfony/var-dumper/Caster/ReflectionCaster.php deleted file mode 100644 index 274ee0d98..000000000 --- a/lib/symfony/var-dumper/Caster/ReflectionCaster.php +++ /dev/null @@ -1,442 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts Reflector related classes to array representation. - * - * @author Nicolas Grekas <p@tchwork.com> - * - * @final - */ -class ReflectionCaster -{ - public const UNSET_CLOSURE_FILE_INFO = ['Closure' => __CLASS__.'::unsetClosureFileInfo']; - - private const EXTRA_MAP = [ - 'docComment' => 'getDocComment', - 'extension' => 'getExtensionName', - 'isDisabled' => 'isDisabled', - 'isDeprecated' => 'isDeprecated', - 'isInternal' => 'isInternal', - 'isUserDefined' => 'isUserDefined', - 'isGenerator' => 'isGenerator', - 'isVariadic' => 'isVariadic', - ]; - - public static function castClosure(\Closure $c, array $a, Stub $stub, bool $isNested, int $filter = 0) - { - $prefix = Caster::PREFIX_VIRTUAL; - $c = new \ReflectionFunction($c); - - $a = static::castFunctionAbstract($c, $a, $stub, $isNested, $filter); - - if (!str_contains($c->name, '{closure}')) { - $stub->class = isset($a[$prefix.'class']) ? $a[$prefix.'class']->value.'::'.$c->name : $c->name; - unset($a[$prefix.'class']); - } - unset($a[$prefix.'extra']); - - $stub->class .= self::getSignature($a); - - if ($f = $c->getFileName()) { - $stub->attr['file'] = $f; - $stub->attr['line'] = $c->getStartLine(); - } - - unset($a[$prefix.'parameters']); - - if ($filter & Caster::EXCLUDE_VERBOSE) { - $stub->cut += ($c->getFileName() ? 2 : 0) + \count($a); - - return []; - } - - if ($f) { - $a[$prefix.'file'] = new LinkStub($f, $c->getStartLine()); - $a[$prefix.'line'] = $c->getStartLine().' to '.$c->getEndLine(); - } - - return $a; - } - - public static function unsetClosureFileInfo(\Closure $c, array $a) - { - unset($a[Caster::PREFIX_VIRTUAL.'file'], $a[Caster::PREFIX_VIRTUAL.'line']); - - return $a; - } - - public static function castGenerator(\Generator $c, array $a, Stub $stub, bool $isNested) - { - // Cannot create ReflectionGenerator based on a terminated Generator - try { - $reflectionGenerator = new \ReflectionGenerator($c); - } catch (\Exception $e) { - $a[Caster::PREFIX_VIRTUAL.'closed'] = true; - - return $a; - } - - return self::castReflectionGenerator($reflectionGenerator, $a, $stub, $isNested); - } - - public static function castType(\ReflectionType $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - if ($c instanceof \ReflectionNamedType || \PHP_VERSION_ID < 80000) { - $a += [ - $prefix.'name' => $c instanceof \ReflectionNamedType ? $c->getName() : (string) $c, - $prefix.'allowsNull' => $c->allowsNull(), - $prefix.'isBuiltin' => $c->isBuiltin(), - ]; - } elseif ($c instanceof \ReflectionUnionType || $c instanceof \ReflectionIntersectionType) { - $a[$prefix.'allowsNull'] = $c->allowsNull(); - self::addMap($a, $c, [ - 'types' => 'getTypes', - ]); - } else { - $a[$prefix.'allowsNull'] = $c->allowsNull(); - } - - return $a; - } - - public static function castAttribute(\ReflectionAttribute $c, array $a, Stub $stub, bool $isNested) - { - self::addMap($a, $c, [ - 'name' => 'getName', - 'arguments' => 'getArguments', - ]); - - return $a; - } - - public static function castReflectionGenerator(\ReflectionGenerator $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - if ($c->getThis()) { - $a[$prefix.'this'] = new CutStub($c->getThis()); - } - $function = $c->getFunction(); - $frame = [ - 'class' => $function->class ?? null, - 'type' => isset($function->class) ? ($function->isStatic() ? '::' : '->') : null, - 'function' => $function->name, - 'file' => $c->getExecutingFile(), - 'line' => $c->getExecutingLine(), - ]; - if ($trace = $c->getTrace(\DEBUG_BACKTRACE_IGNORE_ARGS)) { - $function = new \ReflectionGenerator($c->getExecutingGenerator()); - array_unshift($trace, [ - 'function' => 'yield', - 'file' => $function->getExecutingFile(), - 'line' => $function->getExecutingLine() - (int) (\PHP_VERSION_ID < 80100), - ]); - $trace[] = $frame; - $a[$prefix.'trace'] = new TraceStub($trace, false, 0, -1, -1); - } else { - $function = new FrameStub($frame, false, true); - $function = ExceptionCaster::castFrameStub($function, [], $function, true); - $a[$prefix.'executing'] = $function[$prefix.'src']; - } - - $a[Caster::PREFIX_VIRTUAL.'closed'] = false; - - return $a; - } - - public static function castClass(\ReflectionClass $c, array $a, Stub $stub, bool $isNested, int $filter = 0) - { - $prefix = Caster::PREFIX_VIRTUAL; - - if ($n = \Reflection::getModifierNames($c->getModifiers())) { - $a[$prefix.'modifiers'] = implode(' ', $n); - } - - self::addMap($a, $c, [ - 'extends' => 'getParentClass', - 'implements' => 'getInterfaceNames', - 'constants' => 'getReflectionConstants', - ]); - - foreach ($c->getProperties() as $n) { - $a[$prefix.'properties'][$n->name] = $n; - } - - foreach ($c->getMethods() as $n) { - $a[$prefix.'methods'][$n->name] = $n; - } - - self::addAttributes($a, $c, $prefix); - - if (!($filter & Caster::EXCLUDE_VERBOSE) && !$isNested) { - self::addExtra($a, $c); - } - - return $a; - } - - public static function castFunctionAbstract(\ReflectionFunctionAbstract $c, array $a, Stub $stub, bool $isNested, int $filter = 0) - { - $prefix = Caster::PREFIX_VIRTUAL; - - self::addMap($a, $c, [ - 'returnsReference' => 'returnsReference', - 'returnType' => 'getReturnType', - 'class' => 'getClosureScopeClass', - 'this' => 'getClosureThis', - ]); - - if (isset($a[$prefix.'returnType'])) { - $v = $a[$prefix.'returnType']; - $v = $v instanceof \ReflectionNamedType ? $v->getName() : (string) $v; - $a[$prefix.'returnType'] = new ClassStub($a[$prefix.'returnType'] instanceof \ReflectionNamedType && $a[$prefix.'returnType']->allowsNull() && 'mixed' !== $v ? '?'.$v : $v, [class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '']); - } - if (isset($a[$prefix.'class'])) { - $a[$prefix.'class'] = new ClassStub($a[$prefix.'class']); - } - if (isset($a[$prefix.'this'])) { - $a[$prefix.'this'] = new CutStub($a[$prefix.'this']); - } - - foreach ($c->getParameters() as $v) { - $k = '$'.$v->name; - if ($v->isVariadic()) { - $k = '...'.$k; - } - if ($v->isPassedByReference()) { - $k = '&'.$k; - } - $a[$prefix.'parameters'][$k] = $v; - } - if (isset($a[$prefix.'parameters'])) { - $a[$prefix.'parameters'] = new EnumStub($a[$prefix.'parameters']); - } - - self::addAttributes($a, $c, $prefix); - - if (!($filter & Caster::EXCLUDE_VERBOSE) && $v = $c->getStaticVariables()) { - foreach ($v as $k => &$v) { - if (\is_object($v)) { - $a[$prefix.'use']['$'.$k] = new CutStub($v); - } else { - $a[$prefix.'use']['$'.$k] = &$v; - } - } - unset($v); - $a[$prefix.'use'] = new EnumStub($a[$prefix.'use']); - } - - if (!($filter & Caster::EXCLUDE_VERBOSE) && !$isNested) { - self::addExtra($a, $c); - } - - return $a; - } - - public static function castClassConstant(\ReflectionClassConstant $c, array $a, Stub $stub, bool $isNested) - { - $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers())); - $a[Caster::PREFIX_VIRTUAL.'value'] = $c->getValue(); - - self::addAttributes($a, $c); - - return $a; - } - - public static function castMethod(\ReflectionMethod $c, array $a, Stub $stub, bool $isNested) - { - $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers())); - - return $a; - } - - public static function castParameter(\ReflectionParameter $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - self::addMap($a, $c, [ - 'position' => 'getPosition', - 'isVariadic' => 'isVariadic', - 'byReference' => 'isPassedByReference', - 'allowsNull' => 'allowsNull', - ]); - - self::addAttributes($a, $c, $prefix); - - if ($v = $c->getType()) { - $a[$prefix.'typeHint'] = $v instanceof \ReflectionNamedType ? $v->getName() : (string) $v; - } - - if (isset($a[$prefix.'typeHint'])) { - $v = $a[$prefix.'typeHint']; - $a[$prefix.'typeHint'] = new ClassStub($v, [class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '']); - } else { - unset($a[$prefix.'allowsNull']); - } - - if ($c->isOptional()) { - try { - $a[$prefix.'default'] = $v = $c->getDefaultValue(); - if ($c->isDefaultValueConstant()) { - $a[$prefix.'default'] = new ConstStub($c->getDefaultValueConstantName(), $v); - } - if (null === $v) { - unset($a[$prefix.'allowsNull']); - } - } catch (\ReflectionException $e) { - } - } - - return $a; - } - - public static function castProperty(\ReflectionProperty $c, array $a, Stub $stub, bool $isNested) - { - $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers())); - - self::addAttributes($a, $c); - self::addExtra($a, $c); - - return $a; - } - - public static function castReference(\ReflectionReference $c, array $a, Stub $stub, bool $isNested) - { - $a[Caster::PREFIX_VIRTUAL.'id'] = $c->getId(); - - return $a; - } - - public static function castExtension(\ReflectionExtension $c, array $a, Stub $stub, bool $isNested) - { - self::addMap($a, $c, [ - 'version' => 'getVersion', - 'dependencies' => 'getDependencies', - 'iniEntries' => 'getIniEntries', - 'isPersistent' => 'isPersistent', - 'isTemporary' => 'isTemporary', - 'constants' => 'getConstants', - 'functions' => 'getFunctions', - 'classes' => 'getClasses', - ]); - - return $a; - } - - public static function castZendExtension(\ReflectionZendExtension $c, array $a, Stub $stub, bool $isNested) - { - self::addMap($a, $c, [ - 'version' => 'getVersion', - 'author' => 'getAuthor', - 'copyright' => 'getCopyright', - 'url' => 'getURL', - ]); - - return $a; - } - - public static function getSignature(array $a) - { - $prefix = Caster::PREFIX_VIRTUAL; - $signature = ''; - - if (isset($a[$prefix.'parameters'])) { - foreach ($a[$prefix.'parameters']->value as $k => $param) { - $signature .= ', '; - if ($type = $param->getType()) { - if (!$type instanceof \ReflectionNamedType) { - $signature .= $type.' '; - } else { - if (!$param->isOptional() && $param->allowsNull() && 'mixed' !== $type->getName()) { - $signature .= '?'; - } - $signature .= substr(strrchr('\\'.$type->getName(), '\\'), 1).' '; - } - } - $signature .= $k; - - if (!$param->isDefaultValueAvailable()) { - continue; - } - $v = $param->getDefaultValue(); - $signature .= ' = '; - - if ($param->isDefaultValueConstant()) { - $signature .= substr(strrchr('\\'.$param->getDefaultValueConstantName(), '\\'), 1); - } elseif (null === $v) { - $signature .= 'null'; - } elseif (\is_array($v)) { - $signature .= $v ? '[…'.\count($v).']' : '[]'; - } elseif (\is_string($v)) { - $signature .= 10 > \strlen($v) && !str_contains($v, '\\') ? "'{$v}'" : "'…".\strlen($v)."'"; - } elseif (\is_bool($v)) { - $signature .= $v ? 'true' : 'false'; - } elseif (\is_object($v)) { - $signature .= 'new '.substr(strrchr('\\'.get_debug_type($v), '\\'), 1); - } else { - $signature .= $v; - } - } - } - $signature = (empty($a[$prefix.'returnsReference']) ? '' : '&').'('.substr($signature, 2).')'; - - if (isset($a[$prefix.'returnType'])) { - $signature .= ': '.substr(strrchr('\\'.$a[$prefix.'returnType'], '\\'), 1); - } - - return $signature; - } - - private static function addExtra(array &$a, \Reflector $c) - { - $x = isset($a[Caster::PREFIX_VIRTUAL.'extra']) ? $a[Caster::PREFIX_VIRTUAL.'extra']->value : []; - - if (method_exists($c, 'getFileName') && $m = $c->getFileName()) { - $x['file'] = new LinkStub($m, $c->getStartLine()); - $x['line'] = $c->getStartLine().' to '.$c->getEndLine(); - } - - self::addMap($x, $c, self::EXTRA_MAP, ''); - - if ($x) { - $a[Caster::PREFIX_VIRTUAL.'extra'] = new EnumStub($x); - } - } - - private static function addMap(array &$a, object $c, array $map, string $prefix = Caster::PREFIX_VIRTUAL) - { - foreach ($map as $k => $m) { - if (\PHP_VERSION_ID >= 80000 && 'isDisabled' === $k) { - continue; - } - - if (method_exists($c, $m) && false !== ($m = $c->$m()) && null !== $m) { - $a[$prefix.$k] = $m instanceof \Reflector ? $m->name : $m; - } - } - } - - private static function addAttributes(array &$a, \Reflector $c, string $prefix = Caster::PREFIX_VIRTUAL): void - { - if (\PHP_VERSION_ID >= 80000) { - foreach ($c->getAttributes() as $n) { - $a[$prefix.'attributes'][] = $n; - } - } - } -} diff --git a/lib/symfony/var-dumper/Caster/ResourceCaster.php b/lib/symfony/var-dumper/Caster/ResourceCaster.php deleted file mode 100644 index 2c34ca917..000000000 --- a/lib/symfony/var-dumper/Caster/ResourceCaster.php +++ /dev/null @@ -1,103 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts common resource types to array representation. - * - * @author Nicolas Grekas <p@tchwork.com> - * - * @final - */ -class ResourceCaster -{ - /** - * @param \CurlHandle|resource $h - */ - public static function castCurl($h, array $a, Stub $stub, bool $isNested): array - { - return curl_getinfo($h); - } - - public static function castDba($dba, array $a, Stub $stub, bool $isNested) - { - $list = dba_list(); - $a['file'] = $list[(int) $dba]; - - return $a; - } - - public static function castProcess($process, array $a, Stub $stub, bool $isNested) - { - return proc_get_status($process); - } - - public static function castStream($stream, array $a, Stub $stub, bool $isNested) - { - $a = stream_get_meta_data($stream) + static::castStreamContext($stream, $a, $stub, $isNested); - if ($a['uri'] ?? false) { - $a['uri'] = new LinkStub($a['uri']); - } - - return $a; - } - - public static function castStreamContext($stream, array $a, Stub $stub, bool $isNested) - { - return @stream_context_get_params($stream) ?: $a; - } - - public static function castGd($gd, array $a, Stub $stub, bool $isNested) - { - $a['size'] = imagesx($gd).'x'.imagesy($gd); - $a['trueColor'] = imageistruecolor($gd); - - return $a; - } - - public static function castMysqlLink($h, array $a, Stub $stub, bool $isNested) - { - $a['host'] = mysql_get_host_info($h); - $a['protocol'] = mysql_get_proto_info($h); - $a['server'] = mysql_get_server_info($h); - - return $a; - } - - public static function castOpensslX509($h, array $a, Stub $stub, bool $isNested) - { - $stub->cut = -1; - $info = openssl_x509_parse($h, false); - - $pin = openssl_pkey_get_public($h); - $pin = openssl_pkey_get_details($pin)['key']; - $pin = \array_slice(explode("\n", $pin), 1, -2); - $pin = base64_decode(implode('', $pin)); - $pin = base64_encode(hash('sha256', $pin, true)); - - $a += [ - 'subject' => new EnumStub(array_intersect_key($info['subject'], ['organizationName' => true, 'commonName' => true])), - 'issuer' => new EnumStub(array_intersect_key($info['issuer'], ['organizationName' => true, 'commonName' => true])), - 'expiry' => new ConstStub(date(\DateTime::ISO8601, $info['validTo_time_t']), $info['validTo_time_t']), - 'fingerprint' => new EnumStub([ - 'md5' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'md5')), 2, ':', true)), - 'sha1' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'sha1')), 2, ':', true)), - 'sha256' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'sha256')), 2, ':', true)), - 'pin-sha256' => new ConstStub($pin), - ]), - ]; - - return $a; - } -} diff --git a/lib/symfony/var-dumper/Caster/SplCaster.php b/lib/symfony/var-dumper/Caster/SplCaster.php deleted file mode 100644 index 07f445116..000000000 --- a/lib/symfony/var-dumper/Caster/SplCaster.php +++ /dev/null @@ -1,245 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts SPL related classes to array representation. - * - * @author Nicolas Grekas <p@tchwork.com> - * - * @final - */ -class SplCaster -{ - private const SPL_FILE_OBJECT_FLAGS = [ - \SplFileObject::DROP_NEW_LINE => 'DROP_NEW_LINE', - \SplFileObject::READ_AHEAD => 'READ_AHEAD', - \SplFileObject::SKIP_EMPTY => 'SKIP_EMPTY', - \SplFileObject::READ_CSV => 'READ_CSV', - ]; - - public static function castArrayObject(\ArrayObject $c, array $a, Stub $stub, bool $isNested) - { - return self::castSplArray($c, $a, $stub, $isNested); - } - - public static function castArrayIterator(\ArrayIterator $c, array $a, Stub $stub, bool $isNested) - { - return self::castSplArray($c, $a, $stub, $isNested); - } - - public static function castHeap(\Iterator $c, array $a, Stub $stub, bool $isNested) - { - $a += [ - Caster::PREFIX_VIRTUAL.'heap' => iterator_to_array(clone $c), - ]; - - return $a; - } - - public static function castDoublyLinkedList(\SplDoublyLinkedList $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - $mode = $c->getIteratorMode(); - $c->setIteratorMode(\SplDoublyLinkedList::IT_MODE_KEEP | $mode & ~\SplDoublyLinkedList::IT_MODE_DELETE); - - $a += [ - $prefix.'mode' => new ConstStub((($mode & \SplDoublyLinkedList::IT_MODE_LIFO) ? 'IT_MODE_LIFO' : 'IT_MODE_FIFO').' | '.(($mode & \SplDoublyLinkedList::IT_MODE_DELETE) ? 'IT_MODE_DELETE' : 'IT_MODE_KEEP'), $mode), - $prefix.'dllist' => iterator_to_array($c), - ]; - $c->setIteratorMode($mode); - - return $a; - } - - public static function castFileInfo(\SplFileInfo $c, array $a, Stub $stub, bool $isNested) - { - static $map = [ - 'path' => 'getPath', - 'filename' => 'getFilename', - 'basename' => 'getBasename', - 'pathname' => 'getPathname', - 'extension' => 'getExtension', - 'realPath' => 'getRealPath', - 'aTime' => 'getATime', - 'mTime' => 'getMTime', - 'cTime' => 'getCTime', - 'inode' => 'getInode', - 'size' => 'getSize', - 'perms' => 'getPerms', - 'owner' => 'getOwner', - 'group' => 'getGroup', - 'type' => 'getType', - 'writable' => 'isWritable', - 'readable' => 'isReadable', - 'executable' => 'isExecutable', - 'file' => 'isFile', - 'dir' => 'isDir', - 'link' => 'isLink', - 'linkTarget' => 'getLinkTarget', - ]; - - $prefix = Caster::PREFIX_VIRTUAL; - unset($a["\0SplFileInfo\0fileName"]); - unset($a["\0SplFileInfo\0pathName"]); - - if (\PHP_VERSION_ID < 80000) { - if (false === $c->getPathname()) { - $a[$prefix.'⚠'] = 'The parent constructor was not called: the object is in an invalid state'; - - return $a; - } - } else { - try { - $c->isReadable(); - } catch (\RuntimeException $e) { - if ('Object not initialized' !== $e->getMessage()) { - throw $e; - } - - $a[$prefix.'⚠'] = 'The parent constructor was not called: the object is in an invalid state'; - - return $a; - } catch (\Error $e) { - if ('Object not initialized' !== $e->getMessage()) { - throw $e; - } - - $a[$prefix.'⚠'] = 'The parent constructor was not called: the object is in an invalid state'; - - return $a; - } - } - - foreach ($map as $key => $accessor) { - try { - $a[$prefix.$key] = $c->$accessor(); - } catch (\Exception $e) { - } - } - - if ($a[$prefix.'realPath'] ?? false) { - $a[$prefix.'realPath'] = new LinkStub($a[$prefix.'realPath']); - } - - if (isset($a[$prefix.'perms'])) { - $a[$prefix.'perms'] = new ConstStub(sprintf('0%o', $a[$prefix.'perms']), $a[$prefix.'perms']); - } - - static $mapDate = ['aTime', 'mTime', 'cTime']; - foreach ($mapDate as $key) { - if (isset($a[$prefix.$key])) { - $a[$prefix.$key] = new ConstStub(date('Y-m-d H:i:s', $a[$prefix.$key]), $a[$prefix.$key]); - } - } - - return $a; - } - - public static function castFileObject(\SplFileObject $c, array $a, Stub $stub, bool $isNested) - { - static $map = [ - 'csvControl' => 'getCsvControl', - 'flags' => 'getFlags', - 'maxLineLen' => 'getMaxLineLen', - 'fstat' => 'fstat', - 'eof' => 'eof', - 'key' => 'key', - ]; - - $prefix = Caster::PREFIX_VIRTUAL; - - foreach ($map as $key => $accessor) { - try { - $a[$prefix.$key] = $c->$accessor(); - } catch (\Exception $e) { - } - } - - if (isset($a[$prefix.'flags'])) { - $flagsArray = []; - foreach (self::SPL_FILE_OBJECT_FLAGS as $value => $name) { - if ($a[$prefix.'flags'] & $value) { - $flagsArray[] = $name; - } - } - $a[$prefix.'flags'] = new ConstStub(implode('|', $flagsArray), $a[$prefix.'flags']); - } - - if (isset($a[$prefix.'fstat'])) { - $a[$prefix.'fstat'] = new CutArrayStub($a[$prefix.'fstat'], ['dev', 'ino', 'nlink', 'rdev', 'blksize', 'blocks']); - } - - return $a; - } - - public static function castObjectStorage(\SplObjectStorage $c, array $a, Stub $stub, bool $isNested) - { - $storage = []; - unset($a[Caster::PREFIX_DYNAMIC."\0gcdata"]); // Don't hit https://bugs.php.net/65967 - unset($a["\0SplObjectStorage\0storage"]); - - $clone = clone $c; - foreach ($clone as $obj) { - $storage[] = [ - 'object' => $obj, - 'info' => $clone->getInfo(), - ]; - } - - $a += [ - Caster::PREFIX_VIRTUAL.'storage' => $storage, - ]; - - return $a; - } - - public static function castOuterIterator(\OuterIterator $c, array $a, Stub $stub, bool $isNested) - { - $a[Caster::PREFIX_VIRTUAL.'innerIterator'] = $c->getInnerIterator(); - - return $a; - } - - public static function castWeakReference(\WeakReference $c, array $a, Stub $stub, bool $isNested) - { - $a[Caster::PREFIX_VIRTUAL.'object'] = $c->get(); - - return $a; - } - - private static function castSplArray($c, array $a, Stub $stub, bool $isNested): array - { - $prefix = Caster::PREFIX_VIRTUAL; - $flags = $c->getFlags(); - - if (!($flags & \ArrayObject::STD_PROP_LIST)) { - $c->setFlags(\ArrayObject::STD_PROP_LIST); - $a = Caster::castObject($c, \get_class($c), method_exists($c, '__debugInfo'), $stub->class); - $c->setFlags($flags); - } - if (\PHP_VERSION_ID < 70400) { - $a[$prefix.'storage'] = $c->getArrayCopy(); - } - $a += [ - $prefix.'flag::STD_PROP_LIST' => (bool) ($flags & \ArrayObject::STD_PROP_LIST), - $prefix.'flag::ARRAY_AS_PROPS' => (bool) ($flags & \ArrayObject::ARRAY_AS_PROPS), - ]; - if ($c instanceof \ArrayObject) { - $a[$prefix.'iteratorClass'] = new ClassStub($c->getIteratorClass()); - } - - return $a; - } -} diff --git a/lib/symfony/var-dumper/Caster/StubCaster.php b/lib/symfony/var-dumper/Caster/StubCaster.php deleted file mode 100644 index 32ead7c27..000000000 --- a/lib/symfony/var-dumper/Caster/StubCaster.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts a caster's Stub. - * - * @author Nicolas Grekas <p@tchwork.com> - * - * @final - */ -class StubCaster -{ - public static function castStub(Stub $c, array $a, Stub $stub, bool $isNested) - { - if ($isNested) { - $stub->type = $c->type; - $stub->class = $c->class; - $stub->value = $c->value; - $stub->handle = $c->handle; - $stub->cut = $c->cut; - $stub->attr = $c->attr; - - if (Stub::TYPE_REF === $c->type && !$c->class && \is_string($c->value) && !preg_match('//u', $c->value)) { - $stub->type = Stub::TYPE_STRING; - $stub->class = Stub::STRING_BINARY; - } - - $a = []; - } - - return $a; - } - - public static function castCutArray(CutArrayStub $c, array $a, Stub $stub, bool $isNested) - { - return $isNested ? $c->preservedSubset : $a; - } - - public static function cutInternals($obj, array $a, Stub $stub, bool $isNested) - { - if ($isNested) { - $stub->cut += \count($a); - - return []; - } - - return $a; - } - - public static function castEnum(EnumStub $c, array $a, Stub $stub, bool $isNested) - { - if ($isNested) { - $stub->class = $c->dumpKeys ? '' : null; - $stub->handle = 0; - $stub->value = null; - $stub->cut = $c->cut; - $stub->attr = $c->attr; - - $a = []; - - if ($c->value) { - foreach (array_keys($c->value) as $k) { - $keys[] = !isset($k[0]) || "\0" !== $k[0] ? Caster::PREFIX_VIRTUAL.$k : $k; - } - // Preserve references with array_combine() - $a = array_combine($keys, $c->value); - } - } - - return $a; - } -} diff --git a/lib/symfony/var-dumper/Caster/SymfonyCaster.php b/lib/symfony/var-dumper/Caster/SymfonyCaster.php deleted file mode 100644 index 08428b927..000000000 --- a/lib/symfony/var-dumper/Caster/SymfonyCaster.php +++ /dev/null @@ -1,97 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Uid\Ulid; -use Symfony\Component\Uid\Uuid; -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * @final - */ -class SymfonyCaster -{ - private const REQUEST_GETTERS = [ - 'pathInfo' => 'getPathInfo', - 'requestUri' => 'getRequestUri', - 'baseUrl' => 'getBaseUrl', - 'basePath' => 'getBasePath', - 'method' => 'getMethod', - 'format' => 'getRequestFormat', - ]; - - public static function castRequest(Request $request, array $a, Stub $stub, bool $isNested) - { - $clone = null; - - foreach (self::REQUEST_GETTERS as $prop => $getter) { - $key = Caster::PREFIX_PROTECTED.$prop; - if (\array_key_exists($key, $a) && null === $a[$key]) { - if (null === $clone) { - $clone = clone $request; - } - $a[Caster::PREFIX_VIRTUAL.$prop] = $clone->{$getter}(); - } - } - - return $a; - } - - public static function castHttpClient($client, array $a, Stub $stub, bool $isNested) - { - $multiKey = sprintf("\0%s\0multi", \get_class($client)); - if (isset($a[$multiKey])) { - $a[$multiKey] = new CutStub($a[$multiKey]); - } - - return $a; - } - - public static function castHttpClientResponse($response, array $a, Stub $stub, bool $isNested) - { - $stub->cut += \count($a); - $a = []; - - foreach ($response->getInfo() as $k => $v) { - $a[Caster::PREFIX_VIRTUAL.$k] = $v; - } - - return $a; - } - - public static function castUuid(Uuid $uuid, array $a, Stub $stub, bool $isNested) - { - $a[Caster::PREFIX_VIRTUAL.'toBase58'] = $uuid->toBase58(); - $a[Caster::PREFIX_VIRTUAL.'toBase32'] = $uuid->toBase32(); - - // symfony/uid >= 5.3 - if (method_exists($uuid, 'getDateTime')) { - $a[Caster::PREFIX_VIRTUAL.'time'] = $uuid->getDateTime()->format('Y-m-d H:i:s.u \U\T\C'); - } - - return $a; - } - - public static function castUlid(Ulid $ulid, array $a, Stub $stub, bool $isNested) - { - $a[Caster::PREFIX_VIRTUAL.'toBase58'] = $ulid->toBase58(); - $a[Caster::PREFIX_VIRTUAL.'toRfc4122'] = $ulid->toRfc4122(); - - // symfony/uid >= 5.3 - if (method_exists($ulid, 'getDateTime')) { - $a[Caster::PREFIX_VIRTUAL.'time'] = $ulid->getDateTime()->format('Y-m-d H:i:s.v \U\T\C'); - } - - return $a; - } -} diff --git a/lib/symfony/var-dumper/Caster/TraceStub.php b/lib/symfony/var-dumper/Caster/TraceStub.php deleted file mode 100644 index 5eea1c876..000000000 --- a/lib/symfony/var-dumper/Caster/TraceStub.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Represents a backtrace as returned by debug_backtrace() or Exception->getTrace(). - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class TraceStub extends Stub -{ - public $keepArgs; - public $sliceOffset; - public $sliceLength; - public $numberingOffset; - - public function __construct(array $trace, bool $keepArgs = true, int $sliceOffset = 0, int $sliceLength = null, int $numberingOffset = 0) - { - $this->value = $trace; - $this->keepArgs = $keepArgs; - $this->sliceOffset = $sliceOffset; - $this->sliceLength = $sliceLength; - $this->numberingOffset = $numberingOffset; - } -} diff --git a/lib/symfony/var-dumper/Caster/UuidCaster.php b/lib/symfony/var-dumper/Caster/UuidCaster.php deleted file mode 100644 index b10277457..000000000 --- a/lib/symfony/var-dumper/Caster/UuidCaster.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Ramsey\Uuid\UuidInterface; -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * @author Grégoire Pineau <lyrixx@lyrixx.info> - */ -final class UuidCaster -{ - public static function castRamseyUuid(UuidInterface $c, array $a, Stub $stub, bool $isNested): array - { - $a += [ - Caster::PREFIX_VIRTUAL.'uuid' => (string) $c, - ]; - - return $a; - } -} diff --git a/lib/symfony/var-dumper/Caster/XmlReaderCaster.php b/lib/symfony/var-dumper/Caster/XmlReaderCaster.php deleted file mode 100644 index 5b455651b..000000000 --- a/lib/symfony/var-dumper/Caster/XmlReaderCaster.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts XmlReader class to array representation. - * - * @author Baptiste Clavié <clavie.b@gmail.com> - * - * @final - */ -class XmlReaderCaster -{ - private const NODE_TYPES = [ - \XMLReader::NONE => 'NONE', - \XMLReader::ELEMENT => 'ELEMENT', - \XMLReader::ATTRIBUTE => 'ATTRIBUTE', - \XMLReader::TEXT => 'TEXT', - \XMLReader::CDATA => 'CDATA', - \XMLReader::ENTITY_REF => 'ENTITY_REF', - \XMLReader::ENTITY => 'ENTITY', - \XMLReader::PI => 'PI (Processing Instruction)', - \XMLReader::COMMENT => 'COMMENT', - \XMLReader::DOC => 'DOC', - \XMLReader::DOC_TYPE => 'DOC_TYPE', - \XMLReader::DOC_FRAGMENT => 'DOC_FRAGMENT', - \XMLReader::NOTATION => 'NOTATION', - \XMLReader::WHITESPACE => 'WHITESPACE', - \XMLReader::SIGNIFICANT_WHITESPACE => 'SIGNIFICANT_WHITESPACE', - \XMLReader::END_ELEMENT => 'END_ELEMENT', - \XMLReader::END_ENTITY => 'END_ENTITY', - \XMLReader::XML_DECLARATION => 'XML_DECLARATION', - ]; - - public static function castXmlReader(\XMLReader $reader, array $a, Stub $stub, bool $isNested) - { - try { - $properties = [ - 'LOADDTD' => @$reader->getParserProperty(\XMLReader::LOADDTD), - 'DEFAULTATTRS' => @$reader->getParserProperty(\XMLReader::DEFAULTATTRS), - 'VALIDATE' => @$reader->getParserProperty(\XMLReader::VALIDATE), - 'SUBST_ENTITIES' => @$reader->getParserProperty(\XMLReader::SUBST_ENTITIES), - ]; - } catch (\Error $e) { - $properties = [ - 'LOADDTD' => false, - 'DEFAULTATTRS' => false, - 'VALIDATE' => false, - 'SUBST_ENTITIES' => false, - ]; - } - - $props = Caster::PREFIX_VIRTUAL.'parserProperties'; - $info = [ - 'localName' => $reader->localName, - 'prefix' => $reader->prefix, - 'nodeType' => new ConstStub(self::NODE_TYPES[$reader->nodeType], $reader->nodeType), - 'depth' => $reader->depth, - 'isDefault' => $reader->isDefault, - 'isEmptyElement' => \XMLReader::NONE === $reader->nodeType ? null : $reader->isEmptyElement, - 'xmlLang' => $reader->xmlLang, - 'attributeCount' => $reader->attributeCount, - 'value' => $reader->value, - 'namespaceURI' => $reader->namespaceURI, - 'baseURI' => $reader->baseURI ? new LinkStub($reader->baseURI) : $reader->baseURI, - $props => $properties, - ]; - - if ($info[$props] = Caster::filter($info[$props], Caster::EXCLUDE_EMPTY, [], $count)) { - $info[$props] = new EnumStub($info[$props]); - $info[$props]->cut = $count; - } - - $info = Caster::filter($info, Caster::EXCLUDE_EMPTY, [], $count); - // +2 because hasValue and hasAttributes are always filtered - $stub->cut += $count + 2; - - return $a + $info; - } -} diff --git a/lib/symfony/var-dumper/Caster/XmlResourceCaster.php b/lib/symfony/var-dumper/Caster/XmlResourceCaster.php deleted file mode 100644 index ba55fcedd..000000000 --- a/lib/symfony/var-dumper/Caster/XmlResourceCaster.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts XML resources to array representation. - * - * @author Nicolas Grekas <p@tchwork.com> - * - * @final - */ -class XmlResourceCaster -{ - private const XML_ERRORS = [ - \XML_ERROR_NONE => 'XML_ERROR_NONE', - \XML_ERROR_NO_MEMORY => 'XML_ERROR_NO_MEMORY', - \XML_ERROR_SYNTAX => 'XML_ERROR_SYNTAX', - \XML_ERROR_NO_ELEMENTS => 'XML_ERROR_NO_ELEMENTS', - \XML_ERROR_INVALID_TOKEN => 'XML_ERROR_INVALID_TOKEN', - \XML_ERROR_UNCLOSED_TOKEN => 'XML_ERROR_UNCLOSED_TOKEN', - \XML_ERROR_PARTIAL_CHAR => 'XML_ERROR_PARTIAL_CHAR', - \XML_ERROR_TAG_MISMATCH => 'XML_ERROR_TAG_MISMATCH', - \XML_ERROR_DUPLICATE_ATTRIBUTE => 'XML_ERROR_DUPLICATE_ATTRIBUTE', - \XML_ERROR_JUNK_AFTER_DOC_ELEMENT => 'XML_ERROR_JUNK_AFTER_DOC_ELEMENT', - \XML_ERROR_PARAM_ENTITY_REF => 'XML_ERROR_PARAM_ENTITY_REF', - \XML_ERROR_UNDEFINED_ENTITY => 'XML_ERROR_UNDEFINED_ENTITY', - \XML_ERROR_RECURSIVE_ENTITY_REF => 'XML_ERROR_RECURSIVE_ENTITY_REF', - \XML_ERROR_ASYNC_ENTITY => 'XML_ERROR_ASYNC_ENTITY', - \XML_ERROR_BAD_CHAR_REF => 'XML_ERROR_BAD_CHAR_REF', - \XML_ERROR_BINARY_ENTITY_REF => 'XML_ERROR_BINARY_ENTITY_REF', - \XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF => 'XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF', - \XML_ERROR_MISPLACED_XML_PI => 'XML_ERROR_MISPLACED_XML_PI', - \XML_ERROR_UNKNOWN_ENCODING => 'XML_ERROR_UNKNOWN_ENCODING', - \XML_ERROR_INCORRECT_ENCODING => 'XML_ERROR_INCORRECT_ENCODING', - \XML_ERROR_UNCLOSED_CDATA_SECTION => 'XML_ERROR_UNCLOSED_CDATA_SECTION', - \XML_ERROR_EXTERNAL_ENTITY_HANDLING => 'XML_ERROR_EXTERNAL_ENTITY_HANDLING', - ]; - - public static function castXml($h, array $a, Stub $stub, bool $isNested) - { - $a['current_byte_index'] = xml_get_current_byte_index($h); - $a['current_column_number'] = xml_get_current_column_number($h); - $a['current_line_number'] = xml_get_current_line_number($h); - $a['error_code'] = xml_get_error_code($h); - - if (isset(self::XML_ERRORS[$a['error_code']])) { - $a['error_code'] = new ConstStub(self::XML_ERRORS[$a['error_code']], $a['error_code']); - } - - return $a; - } -} diff --git a/lib/symfony/var-dumper/Cloner/AbstractCloner.php b/lib/symfony/var-dumper/Cloner/AbstractCloner.php deleted file mode 100644 index f74a61d7a..000000000 --- a/lib/symfony/var-dumper/Cloner/AbstractCloner.php +++ /dev/null @@ -1,400 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Cloner; - -use Symfony\Component\VarDumper\Caster\Caster; -use Symfony\Component\VarDumper\Exception\ThrowingCasterException; - -/** - * AbstractCloner implements a generic caster mechanism for objects and resources. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -abstract class AbstractCloner implements ClonerInterface -{ - public static $defaultCasters = [ - '__PHP_Incomplete_Class' => ['Symfony\Component\VarDumper\Caster\Caster', 'castPhpIncompleteClass'], - - 'Symfony\Component\VarDumper\Caster\CutStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castStub'], - 'Symfony\Component\VarDumper\Caster\CutArrayStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castCutArray'], - 'Symfony\Component\VarDumper\Caster\ConstStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castStub'], - 'Symfony\Component\VarDumper\Caster\EnumStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castEnum'], - - 'Fiber' => ['Symfony\Component\VarDumper\Caster\FiberCaster', 'castFiber'], - - 'Closure' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClosure'], - 'Generator' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castGenerator'], - 'ReflectionType' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castType'], - 'ReflectionAttribute' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castAttribute'], - 'ReflectionGenerator' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castReflectionGenerator'], - 'ReflectionClass' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClass'], - 'ReflectionClassConstant' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClassConstant'], - 'ReflectionFunctionAbstract' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castFunctionAbstract'], - 'ReflectionMethod' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castMethod'], - 'ReflectionParameter' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castParameter'], - 'ReflectionProperty' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castProperty'], - 'ReflectionReference' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castReference'], - 'ReflectionExtension' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castExtension'], - 'ReflectionZendExtension' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castZendExtension'], - - 'Doctrine\Common\Persistence\ObjectManager' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], - 'Doctrine\Common\Proxy\Proxy' => ['Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castCommonProxy'], - 'Doctrine\ORM\Proxy\Proxy' => ['Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castOrmProxy'], - 'Doctrine\ORM\PersistentCollection' => ['Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castPersistentCollection'], - 'Doctrine\Persistence\ObjectManager' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], - - 'DOMException' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castException'], - 'DOMStringList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], - 'DOMNameList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], - 'DOMImplementation' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castImplementation'], - 'DOMImplementationList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], - 'DOMNode' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNode'], - 'DOMNameSpaceNode' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNameSpaceNode'], - 'DOMDocument' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castDocument'], - 'DOMNodeList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], - 'DOMNamedNodeMap' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], - 'DOMCharacterData' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castCharacterData'], - 'DOMAttr' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castAttr'], - 'DOMElement' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castElement'], - 'DOMText' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castText'], - 'DOMTypeinfo' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castTypeinfo'], - 'DOMDomError' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castDomError'], - 'DOMLocator' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLocator'], - 'DOMDocumentType' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castDocumentType'], - 'DOMNotation' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNotation'], - 'DOMEntity' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castEntity'], - 'DOMProcessingInstruction' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castProcessingInstruction'], - 'DOMXPath' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castXPath'], - - 'XMLReader' => ['Symfony\Component\VarDumper\Caster\XmlReaderCaster', 'castXmlReader'], - - 'ErrorException' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castErrorException'], - 'Exception' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castException'], - 'Error' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castError'], - 'Symfony\Bridge\Monolog\Logger' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], - 'Symfony\Component\DependencyInjection\ContainerInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], - 'Symfony\Component\EventDispatcher\EventDispatcherInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], - 'Symfony\Component\HttpClient\AmpHttpClient' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClient'], - 'Symfony\Component\HttpClient\CurlHttpClient' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClient'], - 'Symfony\Component\HttpClient\NativeHttpClient' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClient'], - 'Symfony\Component\HttpClient\Response\AmpResponse' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClientResponse'], - 'Symfony\Component\HttpClient\Response\CurlResponse' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClientResponse'], - 'Symfony\Component\HttpClient\Response\NativeResponse' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClientResponse'], - 'Symfony\Component\HttpFoundation\Request' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castRequest'], - 'Symfony\Component\Uid\Ulid' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castUlid'], - 'Symfony\Component\Uid\Uuid' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castUuid'], - 'Symfony\Component\VarDumper\Exception\ThrowingCasterException' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castThrowingCasterException'], - 'Symfony\Component\VarDumper\Caster\TraceStub' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castTraceStub'], - 'Symfony\Component\VarDumper\Caster\FrameStub' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castFrameStub'], - 'Symfony\Component\VarDumper\Cloner\AbstractCloner' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], - 'Symfony\Component\ErrorHandler\Exception\SilencedErrorContext' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castSilencedErrorContext'], - - 'Imagine\Image\ImageInterface' => ['Symfony\Component\VarDumper\Caster\ImagineCaster', 'castImage'], - - 'Ramsey\Uuid\UuidInterface' => ['Symfony\Component\VarDumper\Caster\UuidCaster', 'castRamseyUuid'], - - 'ProxyManager\Proxy\ProxyInterface' => ['Symfony\Component\VarDumper\Caster\ProxyManagerCaster', 'castProxy'], - 'PHPUnit_Framework_MockObject_MockObject' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], - 'PHPUnit\Framework\MockObject\MockObject' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], - 'PHPUnit\Framework\MockObject\Stub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], - 'Prophecy\Prophecy\ProphecySubjectInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], - 'Mockery\MockInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], - - 'PDO' => ['Symfony\Component\VarDumper\Caster\PdoCaster', 'castPdo'], - 'PDOStatement' => ['Symfony\Component\VarDumper\Caster\PdoCaster', 'castPdoStatement'], - - 'AMQPConnection' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castConnection'], - 'AMQPChannel' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castChannel'], - 'AMQPQueue' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castQueue'], - 'AMQPExchange' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castExchange'], - 'AMQPEnvelope' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castEnvelope'], - - 'ArrayObject' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castArrayObject'], - 'ArrayIterator' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castArrayIterator'], - 'SplDoublyLinkedList' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castDoublyLinkedList'], - 'SplFileInfo' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFileInfo'], - 'SplFileObject' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFileObject'], - 'SplHeap' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'], - 'SplObjectStorage' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castObjectStorage'], - 'SplPriorityQueue' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'], - 'OuterIterator' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castOuterIterator'], - 'WeakReference' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castWeakReference'], - - 'Redis' => ['Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedis'], - 'RedisArray' => ['Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedisArray'], - 'RedisCluster' => ['Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedisCluster'], - - 'DateTimeInterface' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castDateTime'], - 'DateInterval' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castInterval'], - 'DateTimeZone' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castTimeZone'], - 'DatePeriod' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castPeriod'], - - 'GMP' => ['Symfony\Component\VarDumper\Caster\GmpCaster', 'castGmp'], - - 'MessageFormatter' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castMessageFormatter'], - 'NumberFormatter' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castNumberFormatter'], - 'IntlTimeZone' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castIntlTimeZone'], - 'IntlCalendar' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castIntlCalendar'], - 'IntlDateFormatter' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castIntlDateFormatter'], - - 'Memcached' => ['Symfony\Component\VarDumper\Caster\MemcachedCaster', 'castMemcached'], - - 'Ds\Collection' => ['Symfony\Component\VarDumper\Caster\DsCaster', 'castCollection'], - 'Ds\Map' => ['Symfony\Component\VarDumper\Caster\DsCaster', 'castMap'], - 'Ds\Pair' => ['Symfony\Component\VarDumper\Caster\DsCaster', 'castPair'], - 'Symfony\Component\VarDumper\Caster\DsPairStub' => ['Symfony\Component\VarDumper\Caster\DsCaster', 'castPairStub'], - - 'mysqli_driver' => ['Symfony\Component\VarDumper\Caster\MysqliCaster', 'castMysqliDriver'], - - 'CurlHandle' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castCurl'], - ':curl' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castCurl'], - - ':dba' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castDba'], - ':dba persistent' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castDba'], - - 'GdImage' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castGd'], - ':gd' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castGd'], - - ':mysql link' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castMysqlLink'], - ':pgsql large object' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLargeObject'], - ':pgsql link' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLink'], - ':pgsql link persistent' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLink'], - ':pgsql result' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castResult'], - ':process' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castProcess'], - ':stream' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStream'], - - 'OpenSSLCertificate' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castOpensslX509'], - ':OpenSSL X.509' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castOpensslX509'], - - ':persistent stream' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStream'], - ':stream-context' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStreamContext'], - - 'XmlParser' => ['Symfony\Component\VarDumper\Caster\XmlResourceCaster', 'castXml'], - ':xml' => ['Symfony\Component\VarDumper\Caster\XmlResourceCaster', 'castXml'], - - 'RdKafka' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castRdKafka'], - 'RdKafka\Conf' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castConf'], - 'RdKafka\KafkaConsumer' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castKafkaConsumer'], - 'RdKafka\Metadata\Broker' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castBrokerMetadata'], - 'RdKafka\Metadata\Collection' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castCollectionMetadata'], - 'RdKafka\Metadata\Partition' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castPartitionMetadata'], - 'RdKafka\Metadata\Topic' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castTopicMetadata'], - 'RdKafka\Message' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castMessage'], - 'RdKafka\Topic' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castTopic'], - 'RdKafka\TopicPartition' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castTopicPartition'], - 'RdKafka\TopicConf' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castTopicConf'], - ]; - - protected $maxItems = 2500; - protected $maxString = -1; - protected $minDepth = 1; - - /** - * @var array<string, list<callable>> - */ - private $casters = []; - - /** - * @var callable|null - */ - private $prevErrorHandler; - - private $classInfo = []; - private $filter = 0; - - /** - * @param callable[]|null $casters A map of casters - * - * @see addCasters - */ - public function __construct(array $casters = null) - { - if (null === $casters) { - $casters = static::$defaultCasters; - } - $this->addCasters($casters); - } - - /** - * Adds casters for resources and objects. - * - * Maps resources or objects types to a callback. - * Types are in the key, with a callable caster for value. - * Resource types are to be prefixed with a `:`, - * see e.g. static::$defaultCasters. - * - * @param callable[] $casters A map of casters - */ - public function addCasters(array $casters) - { - foreach ($casters as $type => $callback) { - $this->casters[$type][] = $callback; - } - } - - /** - * Sets the maximum number of items to clone past the minimum depth in nested structures. - */ - public function setMaxItems(int $maxItems) - { - $this->maxItems = $maxItems; - } - - /** - * Sets the maximum cloned length for strings. - */ - public function setMaxString(int $maxString) - { - $this->maxString = $maxString; - } - - /** - * Sets the minimum tree depth where we are guaranteed to clone all the items. After this - * depth is reached, only setMaxItems items will be cloned. - */ - public function setMinDepth(int $minDepth) - { - $this->minDepth = $minDepth; - } - - /** - * Clones a PHP variable. - * - * @param mixed $var Any PHP variable - * @param int $filter A bit field of Caster::EXCLUDE_* constants - * - * @return Data - */ - public function cloneVar($var, int $filter = 0) - { - $this->prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) { - if (\E_RECOVERABLE_ERROR === $type || \E_USER_ERROR === $type) { - // Cloner never dies - throw new \ErrorException($msg, 0, $type, $file, $line); - } - - if ($this->prevErrorHandler) { - return ($this->prevErrorHandler)($type, $msg, $file, $line, $context); - } - - return false; - }); - $this->filter = $filter; - - if ($gc = gc_enabled()) { - gc_disable(); - } - try { - return new Data($this->doClone($var)); - } finally { - if ($gc) { - gc_enable(); - } - restore_error_handler(); - $this->prevErrorHandler = null; - } - } - - /** - * Effectively clones the PHP variable. - * - * @param mixed $var Any PHP variable - * - * @return array - */ - abstract protected function doClone($var); - - /** - * Casts an object to an array representation. - * - * @param bool $isNested True if the object is nested in the dumped structure - * - * @return array - */ - protected function castObject(Stub $stub, bool $isNested) - { - $obj = $stub->value; - $class = $stub->class; - - if (\PHP_VERSION_ID < 80000 ? "\0" === ($class[15] ?? null) : str_contains($class, "@anonymous\0")) { - $stub->class = get_debug_type($obj); - } - if (isset($this->classInfo[$class])) { - [$i, $parents, $hasDebugInfo, $fileInfo] = $this->classInfo[$class]; - } else { - $i = 2; - $parents = [$class]; - $hasDebugInfo = method_exists($class, '__debugInfo'); - - foreach (class_parents($class) as $p) { - $parents[] = $p; - ++$i; - } - foreach (class_implements($class) as $p) { - $parents[] = $p; - ++$i; - } - $parents[] = '*'; - - $r = new \ReflectionClass($class); - $fileInfo = $r->isInternal() || $r->isSubclassOf(Stub::class) ? [] : [ - 'file' => $r->getFileName(), - 'line' => $r->getStartLine(), - ]; - - $this->classInfo[$class] = [$i, $parents, $hasDebugInfo, $fileInfo]; - } - - $stub->attr += $fileInfo; - $a = Caster::castObject($obj, $class, $hasDebugInfo, $stub->class); - - try { - while ($i--) { - if (!empty($this->casters[$p = $parents[$i]])) { - foreach ($this->casters[$p] as $callback) { - $a = $callback($obj, $a, $stub, $isNested, $this->filter); - } - } - } - } catch (\Exception $e) { - $a = [(Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '').'⚠' => new ThrowingCasterException($e)] + $a; - } - - return $a; - } - - /** - * Casts a resource to an array representation. - * - * @param bool $isNested True if the object is nested in the dumped structure - * - * @return array - */ - protected function castResource(Stub $stub, bool $isNested) - { - $a = []; - $res = $stub->value; - $type = $stub->class; - - try { - if (!empty($this->casters[':'.$type])) { - foreach ($this->casters[':'.$type] as $callback) { - $a = $callback($res, $a, $stub, $isNested, $this->filter); - } - } - } catch (\Exception $e) { - $a = [(Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '').'⚠' => new ThrowingCasterException($e)] + $a; - } - - return $a; - } -} diff --git a/lib/symfony/var-dumper/Cloner/ClonerInterface.php b/lib/symfony/var-dumper/Cloner/ClonerInterface.php deleted file mode 100644 index 90b149532..000000000 --- a/lib/symfony/var-dumper/Cloner/ClonerInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Cloner; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -interface ClonerInterface -{ - /** - * Clones a PHP variable. - * - * @param mixed $var Any PHP variable - * - * @return Data - */ - public function cloneVar($var); -} diff --git a/lib/symfony/var-dumper/Cloner/Cursor.php b/lib/symfony/var-dumper/Cloner/Cursor.php deleted file mode 100644 index 1fd796d67..000000000 --- a/lib/symfony/var-dumper/Cloner/Cursor.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Cloner; - -/** - * Represents the current state of a dumper while dumping. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class Cursor -{ - public const HASH_INDEXED = Stub::ARRAY_INDEXED; - public const HASH_ASSOC = Stub::ARRAY_ASSOC; - public const HASH_OBJECT = Stub::TYPE_OBJECT; - public const HASH_RESOURCE = Stub::TYPE_RESOURCE; - - public $depth = 0; - public $refIndex = 0; - public $softRefTo = 0; - public $softRefCount = 0; - public $softRefHandle = 0; - public $hardRefTo = 0; - public $hardRefCount = 0; - public $hardRefHandle = 0; - public $hashType; - public $hashKey; - public $hashKeyIsBinary; - public $hashIndex = 0; - public $hashLength = 0; - public $hashCut = 0; - public $stop = false; - public $attr = []; - public $skipChildren = false; -} diff --git a/lib/symfony/var-dumper/Cloner/Data.php b/lib/symfony/var-dumper/Cloner/Data.php deleted file mode 100644 index ea8f0f33a..000000000 --- a/lib/symfony/var-dumper/Cloner/Data.php +++ /dev/null @@ -1,468 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Cloner; - -use Symfony\Component\VarDumper\Caster\Caster; -use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class Data implements \ArrayAccess, \Countable, \IteratorAggregate -{ - private $data; - private $position = 0; - private $key = 0; - private $maxDepth = 20; - private $maxItemsPerDepth = -1; - private $useRefHandles = -1; - private $context = []; - - /** - * @param array $data An array as returned by ClonerInterface::cloneVar() - */ - public function __construct(array $data) - { - $this->data = $data; - } - - /** - * @return string|null - */ - public function getType() - { - $item = $this->data[$this->position][$this->key]; - - if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) { - $item = $item->value; - } - if (!$item instanceof Stub) { - return \gettype($item); - } - if (Stub::TYPE_STRING === $item->type) { - return 'string'; - } - if (Stub::TYPE_ARRAY === $item->type) { - return 'array'; - } - if (Stub::TYPE_OBJECT === $item->type) { - return $item->class; - } - if (Stub::TYPE_RESOURCE === $item->type) { - return $item->class.' resource'; - } - - return null; - } - - /** - * Returns a native representation of the original value. - * - * @param array|bool $recursive Whether values should be resolved recursively or not - * - * @return string|int|float|bool|array|Data[]|null - */ - public function getValue($recursive = false) - { - $item = $this->data[$this->position][$this->key]; - - if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) { - $item = $item->value; - } - if (!($item = $this->getStub($item)) instanceof Stub) { - return $item; - } - if (Stub::TYPE_STRING === $item->type) { - return $item->value; - } - - $children = $item->position ? $this->data[$item->position] : []; - - foreach ($children as $k => $v) { - if ($recursive && !($v = $this->getStub($v)) instanceof Stub) { - continue; - } - $children[$k] = clone $this; - $children[$k]->key = $k; - $children[$k]->position = $item->position; - - if ($recursive) { - if (Stub::TYPE_REF === $v->type && ($v = $this->getStub($v->value)) instanceof Stub) { - $recursive = (array) $recursive; - if (isset($recursive[$v->position])) { - continue; - } - $recursive[$v->position] = true; - } - $children[$k] = $children[$k]->getValue($recursive); - } - } - - return $children; - } - - /** - * @return int - */ - #[\ReturnTypeWillChange] - public function count() - { - return \count($this->getValue()); - } - - /** - * @return \Traversable - */ - #[\ReturnTypeWillChange] - public function getIterator() - { - if (!\is_array($value = $this->getValue())) { - throw new \LogicException(sprintf('"%s" object holds non-iterable type "%s".', self::class, get_debug_type($value))); - } - - yield from $value; - } - - public function __get(string $key) - { - if (null !== $data = $this->seek($key)) { - $item = $this->getStub($data->data[$data->position][$data->key]); - - return $item instanceof Stub || [] === $item ? $data : $item; - } - - return null; - } - - /** - * @return bool - */ - public function __isset(string $key) - { - return null !== $this->seek($key); - } - - /** - * @return bool - */ - #[\ReturnTypeWillChange] - public function offsetExists($key) - { - return $this->__isset($key); - } - - /** - * @return mixed - */ - #[\ReturnTypeWillChange] - public function offsetGet($key) - { - return $this->__get($key); - } - - /** - * @return void - */ - #[\ReturnTypeWillChange] - public function offsetSet($key, $value) - { - throw new \BadMethodCallException(self::class.' objects are immutable.'); - } - - /** - * @return void - */ - #[\ReturnTypeWillChange] - public function offsetUnset($key) - { - throw new \BadMethodCallException(self::class.' objects are immutable.'); - } - - /** - * @return string - */ - public function __toString() - { - $value = $this->getValue(); - - if (!\is_array($value)) { - return (string) $value; - } - - return sprintf('%s (count=%d)', $this->getType(), \count($value)); - } - - /** - * Returns a depth limited clone of $this. - * - * @return static - */ - public function withMaxDepth(int $maxDepth) - { - $data = clone $this; - $data->maxDepth = $maxDepth; - - return $data; - } - - /** - * Limits the number of elements per depth level. - * - * @return static - */ - public function withMaxItemsPerDepth(int $maxItemsPerDepth) - { - $data = clone $this; - $data->maxItemsPerDepth = $maxItemsPerDepth; - - return $data; - } - - /** - * Enables/disables objects' identifiers tracking. - * - * @param bool $useRefHandles False to hide global ref. handles - * - * @return static - */ - public function withRefHandles(bool $useRefHandles) - { - $data = clone $this; - $data->useRefHandles = $useRefHandles ? -1 : 0; - - return $data; - } - - /** - * @return static - */ - public function withContext(array $context) - { - $data = clone $this; - $data->context = $context; - - return $data; - } - - /** - * Seeks to a specific key in nested data structures. - * - * @param string|int $key The key to seek to - * - * @return static|null - */ - public function seek($key) - { - $item = $this->data[$this->position][$this->key]; - - if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) { - $item = $item->value; - } - if (!($item = $this->getStub($item)) instanceof Stub || !$item->position) { - return null; - } - $keys = [$key]; - - switch ($item->type) { - case Stub::TYPE_OBJECT: - $keys[] = Caster::PREFIX_DYNAMIC.$key; - $keys[] = Caster::PREFIX_PROTECTED.$key; - $keys[] = Caster::PREFIX_VIRTUAL.$key; - $keys[] = "\0$item->class\0$key"; - // no break - case Stub::TYPE_ARRAY: - case Stub::TYPE_RESOURCE: - break; - default: - return null; - } - - $data = null; - $children = $this->data[$item->position]; - - foreach ($keys as $key) { - if (isset($children[$key]) || \array_key_exists($key, $children)) { - $data = clone $this; - $data->key = $key; - $data->position = $item->position; - break; - } - } - - return $data; - } - - /** - * Dumps data with a DumperInterface dumper. - */ - public function dump(DumperInterface $dumper) - { - $refs = [0]; - $cursor = new Cursor(); - - if ($cursor->attr = $this->context[SourceContextProvider::class] ?? []) { - $cursor->attr['if_links'] = true; - $cursor->hashType = -1; - $dumper->dumpScalar($cursor, 'default', '^'); - $cursor->attr = ['if_links' => true]; - $dumper->dumpScalar($cursor, 'default', ' '); - $cursor->hashType = 0; - } - - $this->dumpItem($dumper, $cursor, $refs, $this->data[$this->position][$this->key]); - } - - /** - * Depth-first dumping of items. - * - * @param mixed $item A Stub object or the original value being dumped - */ - private function dumpItem(DumperInterface $dumper, Cursor $cursor, array &$refs, $item) - { - $cursor->refIndex = 0; - $cursor->softRefTo = $cursor->softRefHandle = $cursor->softRefCount = 0; - $cursor->hardRefTo = $cursor->hardRefHandle = $cursor->hardRefCount = 0; - $firstSeen = true; - - if (!$item instanceof Stub) { - $cursor->attr = []; - $type = \gettype($item); - if ($item && 'array' === $type) { - $item = $this->getStub($item); - } - } elseif (Stub::TYPE_REF === $item->type) { - if ($item->handle) { - if (!isset($refs[$r = $item->handle - (\PHP_INT_MAX >> 1)])) { - $cursor->refIndex = $refs[$r] = $cursor->refIndex ?: ++$refs[0]; - } else { - $firstSeen = false; - } - $cursor->hardRefTo = $refs[$r]; - $cursor->hardRefHandle = $this->useRefHandles & $item->handle; - $cursor->hardRefCount = 0 < $item->handle ? $item->refCount : 0; - } - $cursor->attr = $item->attr; - $type = $item->class ?: \gettype($item->value); - $item = $this->getStub($item->value); - } - if ($item instanceof Stub) { - if ($item->refCount) { - if (!isset($refs[$r = $item->handle])) { - $cursor->refIndex = $refs[$r] = $cursor->refIndex ?: ++$refs[0]; - } else { - $firstSeen = false; - } - $cursor->softRefTo = $refs[$r]; - } - $cursor->softRefHandle = $this->useRefHandles & $item->handle; - $cursor->softRefCount = $item->refCount; - $cursor->attr = $item->attr; - $cut = $item->cut; - - if ($item->position && $firstSeen) { - $children = $this->data[$item->position]; - - if ($cursor->stop) { - if ($cut >= 0) { - $cut += \count($children); - } - $children = []; - } - } else { - $children = []; - } - switch ($item->type) { - case Stub::TYPE_STRING: - $dumper->dumpString($cursor, $item->value, Stub::STRING_BINARY === $item->class, $cut); - break; - - case Stub::TYPE_ARRAY: - $item = clone $item; - $item->type = $item->class; - $item->class = $item->value; - // no break - case Stub::TYPE_OBJECT: - case Stub::TYPE_RESOURCE: - $withChildren = $children && $cursor->depth !== $this->maxDepth && $this->maxItemsPerDepth; - $dumper->enterHash($cursor, $item->type, $item->class, $withChildren); - if ($withChildren) { - if ($cursor->skipChildren) { - $withChildren = false; - $cut = -1; - } else { - $cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $item->type, null !== $item->class); - } - } elseif ($children && 0 <= $cut) { - $cut += \count($children); - } - $cursor->skipChildren = false; - $dumper->leaveHash($cursor, $item->type, $item->class, $withChildren, $cut); - break; - - default: - throw new \RuntimeException(sprintf('Unexpected Stub type: "%s".', $item->type)); - } - } elseif ('array' === $type) { - $dumper->enterHash($cursor, Cursor::HASH_INDEXED, 0, false); - $dumper->leaveHash($cursor, Cursor::HASH_INDEXED, 0, false, 0); - } elseif ('string' === $type) { - $dumper->dumpString($cursor, $item, false, 0); - } else { - $dumper->dumpScalar($cursor, $type, $item); - } - } - - /** - * Dumps children of hash structures. - * - * @return int The final number of removed items - */ - private function dumpChildren(DumperInterface $dumper, Cursor $parentCursor, array &$refs, array $children, int $hashCut, int $hashType, bool $dumpKeys): int - { - $cursor = clone $parentCursor; - ++$cursor->depth; - $cursor->hashType = $hashType; - $cursor->hashIndex = 0; - $cursor->hashLength = \count($children); - $cursor->hashCut = $hashCut; - foreach ($children as $key => $child) { - $cursor->hashKeyIsBinary = isset($key[0]) && !preg_match('//u', $key); - $cursor->hashKey = $dumpKeys ? $key : null; - $this->dumpItem($dumper, $cursor, $refs, $child); - if (++$cursor->hashIndex === $this->maxItemsPerDepth || $cursor->stop) { - $parentCursor->stop = true; - - return $hashCut >= 0 ? $hashCut + $cursor->hashLength - $cursor->hashIndex : $hashCut; - } - } - - return $hashCut; - } - - private function getStub($item) - { - if (!$item || !\is_array($item)) { - return $item; - } - - $stub = new Stub(); - $stub->type = Stub::TYPE_ARRAY; - foreach ($item as $stub->class => $stub->position) { - } - if (isset($item[0])) { - $stub->cut = $item[0]; - } - $stub->value = $stub->cut + ($stub->position ? \count($this->data[$stub->position]) : 0); - - return $stub; - } -} diff --git a/lib/symfony/var-dumper/Cloner/DumperInterface.php b/lib/symfony/var-dumper/Cloner/DumperInterface.php deleted file mode 100644 index 6d60b723c..000000000 --- a/lib/symfony/var-dumper/Cloner/DumperInterface.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Cloner; - -/** - * DumperInterface used by Data objects. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -interface DumperInterface -{ - /** - * Dumps a scalar value. - * - * @param string $type The PHP type of the value being dumped - * @param string|int|float|bool $value The scalar value being dumped - */ - public function dumpScalar(Cursor $cursor, string $type, $value); - - /** - * Dumps a string. - * - * @param string $str The string being dumped - * @param bool $bin Whether $str is UTF-8 or binary encoded - * @param int $cut The number of characters $str has been cut by - */ - public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut); - - /** - * Dumps while entering an hash. - * - * @param int $type A Cursor::HASH_* const for the type of hash - * @param string|int $class The object class, resource type or array count - * @param bool $hasChild When the dump of the hash has child item - */ - public function enterHash(Cursor $cursor, int $type, $class, bool $hasChild); - - /** - * Dumps while leaving an hash. - * - * @param int $type A Cursor::HASH_* const for the type of hash - * @param string|int $class The object class, resource type or array count - * @param bool $hasChild When the dump of the hash has child item - * @param int $cut The number of items the hash has been cut by - */ - public function leaveHash(Cursor $cursor, int $type, $class, bool $hasChild, int $cut); -} diff --git a/lib/symfony/var-dumper/Cloner/Stub.php b/lib/symfony/var-dumper/Cloner/Stub.php deleted file mode 100644 index 073c56efb..000000000 --- a/lib/symfony/var-dumper/Cloner/Stub.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Cloner; - -/** - * Represents the main properties of a PHP variable. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class Stub -{ - public const TYPE_REF = 1; - public const TYPE_STRING = 2; - public const TYPE_ARRAY = 3; - public const TYPE_OBJECT = 4; - public const TYPE_RESOURCE = 5; - - public const STRING_BINARY = 1; - public const STRING_UTF8 = 2; - - public const ARRAY_ASSOC = 1; - public const ARRAY_INDEXED = 2; - - public $type = self::TYPE_REF; - public $class = ''; - public $value; - public $cut = 0; - public $handle = 0; - public $refCount = 0; - public $position = 0; - public $attr = []; - - private static $defaultProperties = []; - - /** - * @internal - */ - public function __sleep(): array - { - $properties = []; - - if (!isset(self::$defaultProperties[$c = static::class])) { - self::$defaultProperties[$c] = get_class_vars($c); - - foreach ((new \ReflectionClass($c))->getStaticProperties() as $k => $v) { - unset(self::$defaultProperties[$c][$k]); - } - } - - foreach (self::$defaultProperties[$c] as $k => $v) { - if ($this->$k !== $v) { - $properties[] = $k; - } - } - - return $properties; - } -} diff --git a/lib/symfony/var-dumper/Cloner/VarCloner.php b/lib/symfony/var-dumper/Cloner/VarCloner.php deleted file mode 100644 index 80c4a2f83..000000000 --- a/lib/symfony/var-dumper/Cloner/VarCloner.php +++ /dev/null @@ -1,311 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Cloner; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class VarCloner extends AbstractCloner -{ - private static $gid; - private static $arrayCache = []; - - /** - * {@inheritdoc} - */ - protected function doClone($var) - { - $len = 1; // Length of $queue - $pos = 0; // Number of cloned items past the minimum depth - $refsCounter = 0; // Hard references counter - $queue = [[$var]]; // This breadth-first queue is the return value - $hardRefs = []; // Map of original zval ids to stub objects - $objRefs = []; // Map of original object handles to their stub object counterpart - $objects = []; // Keep a ref to objects to ensure their handle cannot be reused while cloning - $resRefs = []; // Map of original resource handles to their stub object counterpart - $values = []; // Map of stub objects' ids to original values - $maxItems = $this->maxItems; - $maxString = $this->maxString; - $minDepth = $this->minDepth; - $currentDepth = 0; // Current tree depth - $currentDepthFinalIndex = 0; // Final $queue index for current tree depth - $minimumDepthReached = 0 === $minDepth; // Becomes true when minimum tree depth has been reached - $cookie = (object) []; // Unique object used to detect hard references - $a = null; // Array cast for nested structures - $stub = null; // Stub capturing the main properties of an original item value - // or null if the original value is used directly - - if (!$gid = self::$gid) { - $gid = self::$gid = md5(random_bytes(6)); // Unique string used to detect the special $GLOBALS variable - } - $arrayStub = new Stub(); - $arrayStub->type = Stub::TYPE_ARRAY; - $fromObjCast = false; - - for ($i = 0; $i < $len; ++$i) { - // Detect when we move on to the next tree depth - if ($i > $currentDepthFinalIndex) { - ++$currentDepth; - $currentDepthFinalIndex = $len - 1; - if ($currentDepth >= $minDepth) { - $minimumDepthReached = true; - } - } - - $refs = $vals = $queue[$i]; - foreach ($vals as $k => $v) { - // $v is the original value or a stub object in case of hard references - - if (\PHP_VERSION_ID >= 70400) { - $zvalRef = ($r = \ReflectionReference::fromArrayElement($vals, $k)) ? $r->getId() : null; - } else { - $refs[$k] = $cookie; - $zvalRef = $vals[$k] === $cookie; - } - - if ($zvalRef) { - $vals[$k] = &$stub; // Break hard references to make $queue completely - unset($stub); // independent from the original structure - if (\PHP_VERSION_ID >= 70400 ? null !== $vals[$k] = $hardRefs[$zvalRef] ?? null : $v instanceof Stub && isset($hardRefs[spl_object_id($v)])) { - if (\PHP_VERSION_ID >= 70400) { - $v = $vals[$k]; - } else { - $refs[$k] = $vals[$k] = $v; - } - if ($v->value instanceof Stub && (Stub::TYPE_OBJECT === $v->value->type || Stub::TYPE_RESOURCE === $v->value->type)) { - ++$v->value->refCount; - } - ++$v->refCount; - continue; - } - $vals[$k] = new Stub(); - $vals[$k]->value = $v; - $vals[$k]->handle = ++$refsCounter; - - if (\PHP_VERSION_ID >= 70400) { - $hardRefs[$zvalRef] = $vals[$k]; - } else { - $refs[$k] = $vals[$k]; - $h = spl_object_id($refs[$k]); - $hardRefs[$h] = &$refs[$k]; - $values[$h] = $v; - } - } - // Create $stub when the original value $v cannot be used directly - // If $v is a nested structure, put that structure in array $a - switch (true) { - case null === $v: - case \is_bool($v): - case \is_int($v): - case \is_float($v): - continue 2; - case \is_string($v): - if ('' === $v) { - continue 2; - } - if (!preg_match('//u', $v)) { - $stub = new Stub(); - $stub->type = Stub::TYPE_STRING; - $stub->class = Stub::STRING_BINARY; - if (0 <= $maxString && 0 < $cut = \strlen($v) - $maxString) { - $stub->cut = $cut; - $stub->value = substr($v, 0, -$cut); - } else { - $stub->value = $v; - } - } elseif (0 <= $maxString && isset($v[1 + ($maxString >> 2)]) && 0 < $cut = mb_strlen($v, 'UTF-8') - $maxString) { - $stub = new Stub(); - $stub->type = Stub::TYPE_STRING; - $stub->class = Stub::STRING_UTF8; - $stub->cut = $cut; - $stub->value = mb_substr($v, 0, $maxString, 'UTF-8'); - } else { - continue 2; - } - $a = null; - break; - - case \is_array($v): - if (!$v) { - continue 2; - } - $stub = $arrayStub; - - if (\PHP_VERSION_ID >= 80100) { - $stub->class = array_is_list($v) ? Stub::ARRAY_INDEXED : Stub::ARRAY_ASSOC; - $a = $v; - break; - } - - $stub->class = Stub::ARRAY_INDEXED; - - $j = -1; - foreach ($v as $gk => $gv) { - if ($gk !== ++$j) { - $stub->class = Stub::ARRAY_ASSOC; - $a = $v; - $a[$gid] = true; - break; - } - } - - // Copies of $GLOBALS have very strange behavior, - // let's detect them with some black magic - if (isset($v[$gid])) { - unset($v[$gid]); - $a = []; - foreach ($v as $gk => &$gv) { - if ($v === $gv && (\PHP_VERSION_ID < 70400 || !isset($hardRefs[\ReflectionReference::fromArrayElement($v, $gk)->getId()]))) { - unset($v); - $v = new Stub(); - $v->value = [$v->cut = \count($gv), Stub::TYPE_ARRAY => 0]; - $v->handle = -1; - if (\PHP_VERSION_ID >= 70400) { - $gv = &$a[$gk]; - $hardRefs[\ReflectionReference::fromArrayElement($a, $gk)->getId()] = &$gv; - } else { - $gv = &$hardRefs[spl_object_id($v)]; - } - $gv = $v; - } - - $a[$gk] = &$gv; - } - unset($gv); - } else { - $a = $v; - } - break; - - case \is_object($v): - if (empty($objRefs[$h = spl_object_id($v)])) { - $stub = new Stub(); - $stub->type = Stub::TYPE_OBJECT; - $stub->class = \get_class($v); - $stub->value = $v; - $stub->handle = $h; - $a = $this->castObject($stub, 0 < $i); - if ($v !== $stub->value) { - if (Stub::TYPE_OBJECT !== $stub->type || null === $stub->value) { - break; - } - $stub->handle = $h = spl_object_id($stub->value); - } - $stub->value = null; - if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) { - $stub->cut = \count($a); - $a = null; - } - } - if (empty($objRefs[$h])) { - $objRefs[$h] = $stub; - $objects[] = $v; - } else { - $stub = $objRefs[$h]; - ++$stub->refCount; - $a = null; - } - break; - - default: // resource - if (empty($resRefs[$h = (int) $v])) { - $stub = new Stub(); - $stub->type = Stub::TYPE_RESOURCE; - if ('Unknown' === $stub->class = @get_resource_type($v)) { - $stub->class = 'Closed'; - } - $stub->value = $v; - $stub->handle = $h; - $a = $this->castResource($stub, 0 < $i); - $stub->value = null; - if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) { - $stub->cut = \count($a); - $a = null; - } - } - if (empty($resRefs[$h])) { - $resRefs[$h] = $stub; - } else { - $stub = $resRefs[$h]; - ++$stub->refCount; - $a = null; - } - break; - } - - if ($a) { - if (!$minimumDepthReached || 0 > $maxItems) { - $queue[$len] = $a; - $stub->position = $len++; - } elseif ($pos < $maxItems) { - if ($maxItems < $pos += \count($a)) { - $a = \array_slice($a, 0, $maxItems - $pos, true); - if ($stub->cut >= 0) { - $stub->cut += $pos - $maxItems; - } - } - $queue[$len] = $a; - $stub->position = $len++; - } elseif ($stub->cut >= 0) { - $stub->cut += \count($a); - $stub->position = 0; - } - } - - if ($arrayStub === $stub) { - if ($arrayStub->cut) { - $stub = [$arrayStub->cut, $arrayStub->class => $arrayStub->position]; - $arrayStub->cut = 0; - } elseif (isset(self::$arrayCache[$arrayStub->class][$arrayStub->position])) { - $stub = self::$arrayCache[$arrayStub->class][$arrayStub->position]; - } else { - self::$arrayCache[$arrayStub->class][$arrayStub->position] = $stub = [$arrayStub->class => $arrayStub->position]; - } - } - - if (!$zvalRef) { - $vals[$k] = $stub; - } elseif (\PHP_VERSION_ID >= 70400) { - $hardRefs[$zvalRef]->value = $stub; - } else { - $refs[$k]->value = $stub; - } - } - - if ($fromObjCast) { - $fromObjCast = false; - $refs = $vals; - $vals = []; - $j = -1; - foreach ($queue[$i] as $k => $v) { - foreach ([$k => true] as $gk => $gv) { - } - if ($gk !== $k) { - $vals = (object) $vals; - $vals->{$k} = $refs[++$j]; - $vals = (array) $vals; - } else { - $vals[$k] = $refs[++$j]; - } - } - } - - $queue[$i] = $vals; - } - - foreach ($values as $h => $v) { - $hardRefs[$h] = $v; - } - - return $queue; - } -} diff --git a/lib/symfony/var-dumper/Command/Descriptor/CliDescriptor.php b/lib/symfony/var-dumper/Command/Descriptor/CliDescriptor.php deleted file mode 100644 index 2afaa7bf3..000000000 --- a/lib/symfony/var-dumper/Command/Descriptor/CliDescriptor.php +++ /dev/null @@ -1,79 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Command\Descriptor; - -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\VarDumper\Cloner\Data; -use Symfony\Component\VarDumper\Dumper\CliDumper; - -/** - * Describe collected data clones for cli output. - * - * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> - * - * @final - */ -class CliDescriptor implements DumpDescriptorInterface -{ - private $dumper; - private $lastIdentifier; - - public function __construct(CliDumper $dumper) - { - $this->dumper = $dumper; - } - - public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void - { - $io = $output instanceof SymfonyStyle ? $output : new SymfonyStyle(new ArrayInput([]), $output); - $this->dumper->setColors($output->isDecorated()); - - $rows = [['date', date('r', (int) $context['timestamp'])]]; - $lastIdentifier = $this->lastIdentifier; - $this->lastIdentifier = $clientId; - - $section = "Received from client #$clientId"; - if (isset($context['request'])) { - $request = $context['request']; - $this->lastIdentifier = $request['identifier']; - $section = sprintf('%s %s', $request['method'], $request['uri']); - if ($controller = $request['controller']) { - $rows[] = ['controller', rtrim($this->dumper->dump($controller, true), "\n")]; - } - } elseif (isset($context['cli'])) { - $this->lastIdentifier = $context['cli']['identifier']; - $section = '$ '.$context['cli']['command_line']; - } - - if ($this->lastIdentifier !== $lastIdentifier) { - $io->section($section); - } - - if (isset($context['source'])) { - $source = $context['source']; - $sourceInfo = sprintf('%s on line %d', $source['name'], $source['line']); - if ($fileLink = $source['file_link'] ?? null) { - $sourceInfo = sprintf('<href=%s>%s</>', $fileLink, $sourceInfo); - } - $rows[] = ['source', $sourceInfo]; - $file = $source['file_relative'] ?? $source['file']; - $rows[] = ['file', $file]; - } - - $io->table([], $rows); - - $this->dumper->dump($data); - $io->newLine(); - } -} diff --git a/lib/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php b/lib/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php deleted file mode 100644 index 267d27bfa..000000000 --- a/lib/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Command\Descriptor; - -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\VarDumper\Cloner\Data; - -/** - * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> - */ -interface DumpDescriptorInterface -{ - public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void; -} diff --git a/lib/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php b/lib/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php deleted file mode 100644 index 636b61828..000000000 --- a/lib/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php +++ /dev/null @@ -1,119 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Command\Descriptor; - -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\VarDumper\Cloner\Data; -use Symfony\Component\VarDumper\Dumper\HtmlDumper; - -/** - * Describe collected data clones for html output. - * - * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> - * - * @final - */ -class HtmlDescriptor implements DumpDescriptorInterface -{ - private $dumper; - private $initialized = false; - - public function __construct(HtmlDumper $dumper) - { - $this->dumper = $dumper; - } - - public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void - { - if (!$this->initialized) { - $styles = file_get_contents(__DIR__.'/../../Resources/css/htmlDescriptor.css'); - $scripts = file_get_contents(__DIR__.'/../../Resources/js/htmlDescriptor.js'); - $output->writeln("<style>$styles</style><script>$scripts</script>"); - $this->initialized = true; - } - - $title = '-'; - if (isset($context['request'])) { - $request = $context['request']; - $controller = "<span class='dumped-tag'>{$this->dumper->dump($request['controller'], true, ['maxDepth' => 0])}</span>"; - $title = sprintf('<code>%s</code> <a href="%s">%s</a>', $request['method'], $uri = $request['uri'], $uri); - $dedupIdentifier = $request['identifier']; - } elseif (isset($context['cli'])) { - $title = '<code>$ </code>'.$context['cli']['command_line']; - $dedupIdentifier = $context['cli']['identifier']; - } else { - $dedupIdentifier = uniqid('', true); - } - - $sourceDescription = ''; - if (isset($context['source'])) { - $source = $context['source']; - $projectDir = $source['project_dir'] ?? null; - $sourceDescription = sprintf('%s on line %d', $source['name'], $source['line']); - if (isset($source['file_link'])) { - $sourceDescription = sprintf('<a href="%s">%s</a>', $source['file_link'], $sourceDescription); - } - } - - $isoDate = $this->extractDate($context, 'c'); - $tags = array_filter([ - 'controller' => $controller ?? null, - 'project dir' => $projectDir ?? null, - ]); - - $output->writeln(<<<HTML -<article data-dedup-id="$dedupIdentifier"> - <header> - <div class="row"> - <h2 class="col">$title</h2> - <time class="col text-small" title="$isoDate" datetime="$isoDate"> - {$this->extractDate($context)} - </time> - </div> - {$this->renderTags($tags)} - </header> - <section class="body"> - <p class="text-small"> - $sourceDescription - </p> - {$this->dumper->dump($data, true)} - </section> -</article> -HTML - ); - } - - private function extractDate(array $context, string $format = 'r'): string - { - return date($format, (int) $context['timestamp']); - } - - private function renderTags(array $tags): string - { - if (!$tags) { - return ''; - } - - $renderedTags = ''; - foreach ($tags as $key => $value) { - $renderedTags .= sprintf('<li><span class="badge">%s</span>%s</li>', $key, $value); - } - - return <<<HTML -<div class="row"> - <ul class="tags"> - $renderedTags - </ul> -</div> -HTML; - } -} diff --git a/lib/symfony/var-dumper/Command/ServerDumpCommand.php b/lib/symfony/var-dumper/Command/ServerDumpCommand.php deleted file mode 100644 index 3a6959522..000000000 --- a/lib/symfony/var-dumper/Command/ServerDumpCommand.php +++ /dev/null @@ -1,114 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Completion\CompletionInput; -use Symfony\Component\Console\Completion\CompletionSuggestions; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\VarDumper\Cloner\Data; -use Symfony\Component\VarDumper\Command\Descriptor\CliDescriptor; -use Symfony\Component\VarDumper\Command\Descriptor\DumpDescriptorInterface; -use Symfony\Component\VarDumper\Command\Descriptor\HtmlDescriptor; -use Symfony\Component\VarDumper\Dumper\CliDumper; -use Symfony\Component\VarDumper\Dumper\HtmlDumper; -use Symfony\Component\VarDumper\Server\DumpServer; - -/** - * Starts a dump server to collect and output dumps on a single place with multiple formats support. - * - * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> - * - * @final - */ -class ServerDumpCommand extends Command -{ - protected static $defaultName = 'server:dump'; - protected static $defaultDescription = 'Start a dump server that collects and displays dumps in a single place'; - - private $server; - - /** @var DumpDescriptorInterface[] */ - private $descriptors; - - public function __construct(DumpServer $server, array $descriptors = []) - { - $this->server = $server; - $this->descriptors = $descriptors + [ - 'cli' => new CliDescriptor(new CliDumper()), - 'html' => new HtmlDescriptor(new HtmlDumper()), - ]; - - parent::__construct(); - } - - protected function configure() - { - $this - ->addOption('format', null, InputOption::VALUE_REQUIRED, sprintf('The output format (%s)', implode(', ', $this->getAvailableFormats())), 'cli') - ->setDescription(self::$defaultDescription) - ->setHelp(<<<'EOF' -<info>%command.name%</info> starts a dump server that collects and displays -dumps in a single place for debugging you application: - - <info>php %command.full_name%</info> - -You can consult dumped data in HTML format in your browser by providing the <comment>--format=html</comment> option -and redirecting the output to a file: - - <info>php %command.full_name% --format="html" > dump.html</info> - -EOF - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - $format = $input->getOption('format'); - - if (!$descriptor = $this->descriptors[$format] ?? null) { - throw new InvalidArgumentException(sprintf('Unsupported format "%s".', $format)); - } - - $errorIo = $io->getErrorStyle(); - $errorIo->title('Symfony Var Dumper Server'); - - $this->server->start(); - - $errorIo->success(sprintf('Server listening on %s', $this->server->getHost())); - $errorIo->comment('Quit the server with CONTROL-C.'); - - $this->server->listen(function (Data $data, array $context, int $clientId) use ($descriptor, $io) { - $descriptor->describe($io, $data, $context, $clientId); - }); - - return 0; - } - - public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void - { - if ($input->mustSuggestOptionValuesFor('format')) { - $suggestions->suggestValues($this->getAvailableFormats()); - } - } - - private function getAvailableFormats(): array - { - return array_keys($this->descriptors); - } -} diff --git a/lib/symfony/var-dumper/Dumper/AbstractDumper.php b/lib/symfony/var-dumper/Dumper/AbstractDumper.php deleted file mode 100644 index ae19faf61..000000000 --- a/lib/symfony/var-dumper/Dumper/AbstractDumper.php +++ /dev/null @@ -1,202 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Dumper; - -use Symfony\Component\VarDumper\Cloner\Data; -use Symfony\Component\VarDumper\Cloner\DumperInterface; - -/** - * Abstract mechanism for dumping a Data object. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -abstract class AbstractDumper implements DataDumperInterface, DumperInterface -{ - public const DUMP_LIGHT_ARRAY = 1; - public const DUMP_STRING_LENGTH = 2; - public const DUMP_COMMA_SEPARATOR = 4; - public const DUMP_TRAILING_COMMA = 8; - - public static $defaultOutput = 'php://output'; - - protected $line = ''; - protected $lineDumper; - protected $outputStream; - protected $decimalPoint; // This is locale dependent - protected $indentPad = ' '; - protected $flags; - - private $charset = ''; - - /** - * @param callable|resource|string|null $output A line dumper callable, an opened stream or an output path, defaults to static::$defaultOutput - * @param string|null $charset The default character encoding to use for non-UTF8 strings - * @param int $flags A bit field of static::DUMP_* constants to fine tune dumps representation - */ - public function __construct($output = null, string $charset = null, int $flags = 0) - { - $this->flags = $flags; - $this->setCharset($charset ?: \ini_get('php.output_encoding') ?: \ini_get('default_charset') ?: 'UTF-8'); - $this->decimalPoint = \PHP_VERSION_ID >= 80000 ? '.' : localeconv()['decimal_point']; - $this->setOutput($output ?: static::$defaultOutput); - if (!$output && \is_string(static::$defaultOutput)) { - static::$defaultOutput = $this->outputStream; - } - } - - /** - * Sets the output destination of the dumps. - * - * @param callable|resource|string $output A line dumper callable, an opened stream or an output path - * - * @return callable|resource|string The previous output destination - */ - public function setOutput($output) - { - $prev = $this->outputStream ?? $this->lineDumper; - - if (\is_callable($output)) { - $this->outputStream = null; - $this->lineDumper = $output; - } else { - if (\is_string($output)) { - $output = fopen($output, 'w'); - } - $this->outputStream = $output; - $this->lineDumper = [$this, 'echoLine']; - } - - return $prev; - } - - /** - * Sets the default character encoding to use for non-UTF8 strings. - * - * @return string The previous charset - */ - public function setCharset(string $charset) - { - $prev = $this->charset; - - $charset = strtoupper($charset); - $charset = null === $charset || 'UTF-8' === $charset || 'UTF8' === $charset ? 'CP1252' : $charset; - - $this->charset = $charset; - - return $prev; - } - - /** - * Sets the indentation pad string. - * - * @param string $pad A string that will be prepended to dumped lines, repeated by nesting level - * - * @return string The previous indent pad - */ - public function setIndentPad(string $pad) - { - $prev = $this->indentPad; - $this->indentPad = $pad; - - return $prev; - } - - /** - * Dumps a Data object. - * - * @param callable|resource|string|true|null $output A line dumper callable, an opened stream, an output path or true to return the dump - * - * @return string|null The dump as string when $output is true - */ - public function dump(Data $data, $output = null) - { - $this->decimalPoint = \PHP_VERSION_ID >= 80000 ? '.' : localeconv()['decimal_point']; - - if ($locale = $this->flags & (self::DUMP_COMMA_SEPARATOR | self::DUMP_TRAILING_COMMA) ? setlocale(\LC_NUMERIC, 0) : null) { - setlocale(\LC_NUMERIC, 'C'); - } - - if ($returnDump = true === $output) { - $output = fopen('php://memory', 'r+'); - } - if ($output) { - $prevOutput = $this->setOutput($output); - } - try { - $data->dump($this); - $this->dumpLine(-1); - - if ($returnDump) { - $result = stream_get_contents($output, -1, 0); - fclose($output); - - return $result; - } - } finally { - if ($output) { - $this->setOutput($prevOutput); - } - if ($locale) { - setlocale(\LC_NUMERIC, $locale); - } - } - - return null; - } - - /** - * Dumps the current line. - * - * @param int $depth The recursive depth in the dumped structure for the line being dumped, - * or -1 to signal the end-of-dump to the line dumper callable - */ - protected function dumpLine(int $depth) - { - ($this->lineDumper)($this->line, $depth, $this->indentPad); - $this->line = ''; - } - - /** - * Generic line dumper callback. - */ - protected function echoLine(string $line, int $depth, string $indentPad) - { - if (-1 !== $depth) { - fwrite($this->outputStream, str_repeat($indentPad, $depth).$line."\n"); - } - } - - /** - * Converts a non-UTF-8 string to UTF-8. - * - * @return string|null - */ - protected function utf8Encode(?string $s) - { - if (null === $s || preg_match('//u', $s)) { - return $s; - } - - if (!\function_exists('iconv')) { - throw new \RuntimeException('Unable to convert a non-UTF-8 string to UTF-8: required function iconv() does not exist. You should install ext-iconv or symfony/polyfill-iconv.'); - } - - if (false !== $c = @iconv($this->charset, 'UTF-8', $s)) { - return $c; - } - if ('CP1252' !== $this->charset && false !== $c = @iconv('CP1252', 'UTF-8', $s)) { - return $c; - } - - return iconv('CP850', 'UTF-8', $s); - } -} diff --git a/lib/symfony/var-dumper/Dumper/CliDumper.php b/lib/symfony/var-dumper/Dumper/CliDumper.php deleted file mode 100644 index 94dc8ee97..000000000 --- a/lib/symfony/var-dumper/Dumper/CliDumper.php +++ /dev/null @@ -1,652 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Dumper; - -use Symfony\Component\VarDumper\Cloner\Cursor; -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * CliDumper dumps variables for command line output. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class CliDumper extends AbstractDumper -{ - public static $defaultColors; - public static $defaultOutput = 'php://stdout'; - - protected $colors; - protected $maxStringWidth = 0; - protected $styles = [ - // See http://en.wikipedia.org/wiki/ANSI_escape_code#graphics - 'default' => '0;38;5;208', - 'num' => '1;38;5;38', - 'const' => '1;38;5;208', - 'str' => '1;38;5;113', - 'note' => '38;5;38', - 'ref' => '38;5;247', - 'public' => '', - 'protected' => '', - 'private' => '', - 'meta' => '38;5;170', - 'key' => '38;5;113', - 'index' => '38;5;38', - ]; - - protected static $controlCharsRx = '/[\x00-\x1F\x7F]+/'; - protected static $controlCharsMap = [ - "\t" => '\t', - "\n" => '\n', - "\v" => '\v', - "\f" => '\f', - "\r" => '\r', - "\033" => '\e', - ]; - - protected $collapseNextHash = false; - protected $expandNextHash = false; - - private $displayOptions = [ - 'fileLinkFormat' => null, - ]; - - private $handlesHrefGracefully; - - /** - * {@inheritdoc} - */ - public function __construct($output = null, string $charset = null, int $flags = 0) - { - parent::__construct($output, $charset, $flags); - - if ('\\' === \DIRECTORY_SEPARATOR && !$this->isWindowsTrueColor()) { - // Use only the base 16 xterm colors when using ANSICON or standard Windows 10 CLI - $this->setStyles([ - 'default' => '31', - 'num' => '1;34', - 'const' => '1;31', - 'str' => '1;32', - 'note' => '34', - 'ref' => '1;30', - 'meta' => '35', - 'key' => '32', - 'index' => '34', - ]); - } - - $this->displayOptions['fileLinkFormat'] = \ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format') ?: 'file://%f#L%l'; - } - - /** - * Enables/disables colored output. - */ - public function setColors(bool $colors) - { - $this->colors = $colors; - } - - /** - * Sets the maximum number of characters per line for dumped strings. - */ - public function setMaxStringWidth(int $maxStringWidth) - { - $this->maxStringWidth = $maxStringWidth; - } - - /** - * Configures styles. - * - * @param array $styles A map of style names to style definitions - */ - public function setStyles(array $styles) - { - $this->styles = $styles + $this->styles; - } - - /** - * Configures display options. - * - * @param array $displayOptions A map of display options to customize the behavior - */ - public function setDisplayOptions(array $displayOptions) - { - $this->displayOptions = $displayOptions + $this->displayOptions; - } - - /** - * {@inheritdoc} - */ - public function dumpScalar(Cursor $cursor, string $type, $value) - { - $this->dumpKey($cursor); - - $style = 'const'; - $attr = $cursor->attr; - - switch ($type) { - case 'default': - $style = 'default'; - break; - - case 'integer': - $style = 'num'; - - if (isset($this->styles['integer'])) { - $style = 'integer'; - } - - break; - - case 'double': - $style = 'num'; - - if (isset($this->styles['float'])) { - $style = 'float'; - } - - switch (true) { - case \INF === $value: $value = 'INF'; break; - case -\INF === $value: $value = '-INF'; break; - case is_nan($value): $value = 'NAN'; break; - default: - $value = (string) $value; - if (!str_contains($value, $this->decimalPoint)) { - $value .= $this->decimalPoint.'0'; - } - break; - } - break; - - case 'NULL': - $value = 'null'; - break; - - case 'boolean': - $value = $value ? 'true' : 'false'; - break; - - default: - $attr += ['value' => $this->utf8Encode($value)]; - $value = $this->utf8Encode($type); - break; - } - - $this->line .= $this->style($style, $value, $attr); - - $this->endValue($cursor); - } - - /** - * {@inheritdoc} - */ - public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut) - { - $this->dumpKey($cursor); - $attr = $cursor->attr; - - if ($bin) { - $str = $this->utf8Encode($str); - } - if ('' === $str) { - $this->line .= '""'; - $this->endValue($cursor); - } else { - $attr += [ - 'length' => 0 <= $cut ? mb_strlen($str, 'UTF-8') + $cut : 0, - 'binary' => $bin, - ]; - $str = $bin && false !== strpos($str, "\0") ? [$str] : explode("\n", $str); - if (isset($str[1]) && !isset($str[2]) && !isset($str[1][0])) { - unset($str[1]); - $str[0] .= "\n"; - } - $m = \count($str) - 1; - $i = $lineCut = 0; - - if (self::DUMP_STRING_LENGTH & $this->flags) { - $this->line .= '('.$attr['length'].') '; - } - if ($bin) { - $this->line .= 'b'; - } - - if ($m) { - $this->line .= '"""'; - $this->dumpLine($cursor->depth); - } else { - $this->line .= '"'; - } - - foreach ($str as $str) { - if ($i < $m) { - $str .= "\n"; - } - if (0 < $this->maxStringWidth && $this->maxStringWidth < $len = mb_strlen($str, 'UTF-8')) { - $str = mb_substr($str, 0, $this->maxStringWidth, 'UTF-8'); - $lineCut = $len - $this->maxStringWidth; - } - if ($m && 0 < $cursor->depth) { - $this->line .= $this->indentPad; - } - if ('' !== $str) { - $this->line .= $this->style('str', $str, $attr); - } - if ($i++ == $m) { - if ($m) { - if ('' !== $str) { - $this->dumpLine($cursor->depth); - if (0 < $cursor->depth) { - $this->line .= $this->indentPad; - } - } - $this->line .= '"""'; - } else { - $this->line .= '"'; - } - if ($cut < 0) { - $this->line .= '…'; - $lineCut = 0; - } elseif ($cut) { - $lineCut += $cut; - } - } - if ($lineCut) { - $this->line .= '…'.$lineCut; - $lineCut = 0; - } - - if ($i > $m) { - $this->endValue($cursor); - } else { - $this->dumpLine($cursor->depth); - } - } - } - } - - /** - * {@inheritdoc} - */ - public function enterHash(Cursor $cursor, int $type, $class, bool $hasChild) - { - if (null === $this->colors) { - $this->colors = $this->supportsColors(); - } - - $this->dumpKey($cursor); - $attr = $cursor->attr; - - if ($this->collapseNextHash) { - $cursor->skipChildren = true; - $this->collapseNextHash = $hasChild = false; - } - - $class = $this->utf8Encode($class); - if (Cursor::HASH_OBJECT === $type) { - $prefix = $class && 'stdClass' !== $class ? $this->style('note', $class, $attr).(empty($attr['cut_hash']) ? ' {' : '') : '{'; - } elseif (Cursor::HASH_RESOURCE === $type) { - $prefix = $this->style('note', $class.' resource', $attr).($hasChild ? ' {' : ' '); - } else { - $prefix = $class && !(self::DUMP_LIGHT_ARRAY & $this->flags) ? $this->style('note', 'array:'.$class).' [' : '['; - } - - if (($cursor->softRefCount || 0 < $cursor->softRefHandle) && empty($attr['cut_hash'])) { - $prefix .= $this->style('ref', (Cursor::HASH_RESOURCE === $type ? '@' : '#').(0 < $cursor->softRefHandle ? $cursor->softRefHandle : $cursor->softRefTo), ['count' => $cursor->softRefCount]); - } elseif ($cursor->hardRefTo && !$cursor->refIndex && $class) { - $prefix .= $this->style('ref', '&'.$cursor->hardRefTo, ['count' => $cursor->hardRefCount]); - } elseif (!$hasChild && Cursor::HASH_RESOURCE === $type) { - $prefix = substr($prefix, 0, -1); - } - - $this->line .= $prefix; - - if ($hasChild) { - $this->dumpLine($cursor->depth); - } - } - - /** - * {@inheritdoc} - */ - public function leaveHash(Cursor $cursor, int $type, $class, bool $hasChild, int $cut) - { - if (empty($cursor->attr['cut_hash'])) { - $this->dumpEllipsis($cursor, $hasChild, $cut); - $this->line .= Cursor::HASH_OBJECT === $type ? '}' : (Cursor::HASH_RESOURCE !== $type ? ']' : ($hasChild ? '}' : '')); - } - - $this->endValue($cursor); - } - - /** - * Dumps an ellipsis for cut children. - * - * @param bool $hasChild When the dump of the hash has child item - * @param int $cut The number of items the hash has been cut by - */ - protected function dumpEllipsis(Cursor $cursor, bool $hasChild, int $cut) - { - if ($cut) { - $this->line .= ' …'; - if (0 < $cut) { - $this->line .= $cut; - } - if ($hasChild) { - $this->dumpLine($cursor->depth + 1); - } - } - } - - /** - * Dumps a key in a hash structure. - */ - protected function dumpKey(Cursor $cursor) - { - if (null !== $key = $cursor->hashKey) { - if ($cursor->hashKeyIsBinary) { - $key = $this->utf8Encode($key); - } - $attr = ['binary' => $cursor->hashKeyIsBinary]; - $bin = $cursor->hashKeyIsBinary ? 'b' : ''; - $style = 'key'; - switch ($cursor->hashType) { - default: - case Cursor::HASH_INDEXED: - if (self::DUMP_LIGHT_ARRAY & $this->flags) { - break; - } - $style = 'index'; - // no break - case Cursor::HASH_ASSOC: - if (\is_int($key)) { - $this->line .= $this->style($style, $key).' => '; - } else { - $this->line .= $bin.'"'.$this->style($style, $key).'" => '; - } - break; - - case Cursor::HASH_RESOURCE: - $key = "\0~\0".$key; - // no break - case Cursor::HASH_OBJECT: - if (!isset($key[0]) || "\0" !== $key[0]) { - $this->line .= '+'.$bin.$this->style('public', $key).': '; - } elseif (0 < strpos($key, "\0", 1)) { - $key = explode("\0", substr($key, 1), 2); - - switch ($key[0][0]) { - case '+': // User inserted keys - $attr['dynamic'] = true; - $this->line .= '+'.$bin.'"'.$this->style('public', $key[1], $attr).'": '; - break 2; - case '~': - $style = 'meta'; - if (isset($key[0][1])) { - parse_str(substr($key[0], 1), $attr); - $attr += ['binary' => $cursor->hashKeyIsBinary]; - } - break; - case '*': - $style = 'protected'; - $bin = '#'.$bin; - break; - default: - $attr['class'] = $key[0]; - $style = 'private'; - $bin = '-'.$bin; - break; - } - - if (isset($attr['collapse'])) { - if ($attr['collapse']) { - $this->collapseNextHash = true; - } else { - $this->expandNextHash = true; - } - } - - $this->line .= $bin.$this->style($style, $key[1], $attr).($attr['separator'] ?? ': '); - } else { - // This case should not happen - $this->line .= '-'.$bin.'"'.$this->style('private', $key, ['class' => '']).'": '; - } - break; - } - - if ($cursor->hardRefTo) { - $this->line .= $this->style('ref', '&'.($cursor->hardRefCount ? $cursor->hardRefTo : ''), ['count' => $cursor->hardRefCount]).' '; - } - } - } - - /** - * Decorates a value with some style. - * - * @param string $style The type of style being applied - * @param string $value The value being styled - * @param array $attr Optional context information - * - * @return string - */ - protected function style(string $style, string $value, array $attr = []) - { - if (null === $this->colors) { - $this->colors = $this->supportsColors(); - } - - if (null === $this->handlesHrefGracefully) { - $this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR') - && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100); - } - - if (isset($attr['ellipsis'], $attr['ellipsis-type'])) { - $prefix = substr($value, 0, -$attr['ellipsis']); - if ('cli' === \PHP_SAPI && 'path' === $attr['ellipsis-type'] && isset($_SERVER[$pwd = '\\' === \DIRECTORY_SEPARATOR ? 'CD' : 'PWD']) && str_starts_with($prefix, $_SERVER[$pwd])) { - $prefix = '.'.substr($prefix, \strlen($_SERVER[$pwd])); - } - if (!empty($attr['ellipsis-tail'])) { - $prefix .= substr($value, -$attr['ellipsis'], $attr['ellipsis-tail']); - $value = substr($value, -$attr['ellipsis'] + $attr['ellipsis-tail']); - } else { - $value = substr($value, -$attr['ellipsis']); - } - - $value = $this->style('default', $prefix).$this->style($style, $value); - - goto href; - } - - $map = static::$controlCharsMap; - $startCchr = $this->colors ? "\033[m\033[{$this->styles['default']}m" : ''; - $endCchr = $this->colors ? "\033[m\033[{$this->styles[$style]}m" : ''; - $value = preg_replace_callback(static::$controlCharsRx, function ($c) use ($map, $startCchr, $endCchr) { - $s = $startCchr; - $c = $c[$i = 0]; - do { - $s .= $map[$c[$i]] ?? sprintf('\x%02X', \ord($c[$i])); - } while (isset($c[++$i])); - - return $s.$endCchr; - }, $value, -1, $cchrCount); - - if ($this->colors) { - if ($cchrCount && "\033" === $value[0]) { - $value = substr($value, \strlen($startCchr)); - } else { - $value = "\033[{$this->styles[$style]}m".$value; - } - if ($cchrCount && str_ends_with($value, $endCchr)) { - $value = substr($value, 0, -\strlen($endCchr)); - } else { - $value .= "\033[{$this->styles['default']}m"; - } - } - - href: - if ($this->colors && $this->handlesHrefGracefully) { - if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], $attr['line'] ?? 0)) { - if ('note' === $style) { - $value .= "\033]8;;{$href}\033\\^\033]8;;\033\\"; - } else { - $attr['href'] = $href; - } - } - if (isset($attr['href'])) { - $value = "\033]8;;{$attr['href']}\033\\{$value}\033]8;;\033\\"; - } - } elseif ($attr['if_links'] ?? false) { - return ''; - } - - return $value; - } - - /** - * @return bool - */ - protected function supportsColors() - { - if ($this->outputStream !== static::$defaultOutput) { - return $this->hasColorSupport($this->outputStream); - } - if (null !== static::$defaultColors) { - return static::$defaultColors; - } - if (isset($_SERVER['argv'][1])) { - $colors = $_SERVER['argv']; - $i = \count($colors); - while (--$i > 0) { - if (isset($colors[$i][5])) { - switch ($colors[$i]) { - case '--ansi': - case '--color': - case '--color=yes': - case '--color=force': - case '--color=always': - case '--colors=always': - return static::$defaultColors = true; - - case '--no-ansi': - case '--color=no': - case '--color=none': - case '--color=never': - case '--colors=never': - return static::$defaultColors = false; - } - } - } - } - - $h = stream_get_meta_data($this->outputStream) + ['wrapper_type' => null]; - $h = 'Output' === $h['stream_type'] && 'PHP' === $h['wrapper_type'] ? fopen('php://stdout', 'w') : $this->outputStream; - - return static::$defaultColors = $this->hasColorSupport($h); - } - - /** - * {@inheritdoc} - */ - protected function dumpLine(int $depth, bool $endOfValue = false) - { - if ($this->colors) { - $this->line = sprintf("\033[%sm%s\033[m", $this->styles['default'], $this->line); - } - parent::dumpLine($depth); - } - - protected function endValue(Cursor $cursor) - { - if (-1 === $cursor->hashType) { - return; - } - - if (Stub::ARRAY_INDEXED === $cursor->hashType || Stub::ARRAY_ASSOC === $cursor->hashType) { - if (self::DUMP_TRAILING_COMMA & $this->flags && 0 < $cursor->depth) { - $this->line .= ','; - } elseif (self::DUMP_COMMA_SEPARATOR & $this->flags && 1 < $cursor->hashLength - $cursor->hashIndex) { - $this->line .= ','; - } - } - - $this->dumpLine($cursor->depth, true); - } - - /** - * Returns true if the stream supports colorization. - * - * Reference: Composer\XdebugHandler\Process::supportsColor - * https://github.com/composer/xdebug-handler - * - * @param mixed $stream A CLI output stream - */ - private function hasColorSupport($stream): bool - { - if (!\is_resource($stream) || 'stream' !== get_resource_type($stream)) { - return false; - } - - // 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($stream)) - || false !== getenv('ANSICON') - || 'ON' === getenv('ConEmuANSI') - || 'xterm' === getenv('TERM'); - } - - return stream_isatty($stream); - } - - /** - * Returns true if the Windows terminal supports true color. - * - * Note that this does not check an output stream, but relies on environment - * variables from known implementations, or a PHP and Windows version that - * supports true color. - */ - private function isWindowsTrueColor(): bool - { - $result = 183 <= getenv('ANSICON_VER') - || 'ON' === getenv('ConEmuANSI') - || 'xterm' === getenv('TERM') - || 'Hyper' === getenv('TERM_PROGRAM'); - - if (!$result) { - $version = sprintf( - '%s.%s.%s', - PHP_WINDOWS_VERSION_MAJOR, - PHP_WINDOWS_VERSION_MINOR, - PHP_WINDOWS_VERSION_BUILD - ); - $result = $version >= '10.0.15063'; - } - - return $result; - } - - private function getSourceLink(string $file, int $line) - { - if ($fmt = $this->displayOptions['fileLinkFormat']) { - return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : ($fmt->format($file, $line) ?: 'file://'.$file.'#L'.$line); - } - - return false; - } -} diff --git a/lib/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php b/lib/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php deleted file mode 100644 index 38f878971..000000000 --- a/lib/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Dumper\ContextProvider; - -/** - * Tries to provide context on CLI. - * - * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> - */ -final class CliContextProvider implements ContextProviderInterface -{ - public function getContext(): ?array - { - if ('cli' !== \PHP_SAPI) { - return null; - } - - return [ - 'command_line' => $commandLine = implode(' ', $_SERVER['argv'] ?? []), - 'identifier' => hash('crc32b', $commandLine.$_SERVER['REQUEST_TIME_FLOAT']), - ]; - } -} diff --git a/lib/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php b/lib/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php deleted file mode 100644 index 532aa0f96..000000000 --- a/lib/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Dumper\ContextProvider; - -/** - * Interface to provide contextual data about dump data clones sent to a server. - * - * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> - */ -interface ContextProviderInterface -{ - public function getContext(): ?array; -} diff --git a/lib/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php b/lib/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php deleted file mode 100644 index 3684a4753..000000000 --- a/lib/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Dumper\ContextProvider; - -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\VarDumper\Caster\ReflectionCaster; -use Symfony\Component\VarDumper\Cloner\VarCloner; - -/** - * Tries to provide context from a request. - * - * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> - */ -final class RequestContextProvider implements ContextProviderInterface -{ - private $requestStack; - private $cloner; - - public function __construct(RequestStack $requestStack) - { - $this->requestStack = $requestStack; - $this->cloner = new VarCloner(); - $this->cloner->setMaxItems(0); - $this->cloner->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO); - } - - public function getContext(): ?array - { - if (null === $request = $this->requestStack->getCurrentRequest()) { - return null; - } - - $controller = $request->attributes->get('_controller'); - - return [ - 'uri' => $request->getUri(), - 'method' => $request->getMethod(), - 'controller' => $controller ? $this->cloner->cloneVar($controller) : $controller, - 'identifier' => spl_object_hash($request), - ]; - } -} diff --git a/lib/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php b/lib/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php deleted file mode 100644 index 2e2c81816..000000000 --- a/lib/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php +++ /dev/null @@ -1,126 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Dumper\ContextProvider; - -use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; -use Symfony\Component\VarDumper\Cloner\VarCloner; -use Symfony\Component\VarDumper\Dumper\HtmlDumper; -use Symfony\Component\VarDumper\VarDumper; -use Twig\Template; - -/** - * Tries to provide context from sources (class name, file, line, code excerpt, ...). - * - * @author Nicolas Grekas <p@tchwork.com> - * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> - */ -final class SourceContextProvider implements ContextProviderInterface -{ - private $limit; - private $charset; - private $projectDir; - private $fileLinkFormatter; - - public function __construct(string $charset = null, string $projectDir = null, FileLinkFormatter $fileLinkFormatter = null, int $limit = 9) - { - $this->charset = $charset; - $this->projectDir = $projectDir; - $this->fileLinkFormatter = $fileLinkFormatter; - $this->limit = $limit; - } - - public function getContext(): ?array - { - $trace = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT | \DEBUG_BACKTRACE_IGNORE_ARGS, $this->limit); - - $file = $trace[1]['file']; - $line = $trace[1]['line']; - $name = false; - $fileExcerpt = false; - - for ($i = 2; $i < $this->limit; ++$i) { - if (isset($trace[$i]['class'], $trace[$i]['function']) - && 'dump' === $trace[$i]['function'] - && VarDumper::class === $trace[$i]['class'] - ) { - $file = $trace[$i]['file'] ?? $file; - $line = $trace[$i]['line'] ?? $line; - - while (++$i < $this->limit) { - if (isset($trace[$i]['function'], $trace[$i]['file']) && empty($trace[$i]['class']) && !str_starts_with($trace[$i]['function'], 'call_user_func')) { - $file = $trace[$i]['file']; - $line = $trace[$i]['line']; - - break; - } elseif (isset($trace[$i]['object']) && $trace[$i]['object'] instanceof Template) { - $template = $trace[$i]['object']; - $name = $template->getTemplateName(); - $src = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : false); - $info = $template->getDebugInfo(); - if (isset($info[$trace[$i - 1]['line']])) { - $line = $info[$trace[$i - 1]['line']]; - $file = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getPath() : null; - - if ($src) { - $src = explode("\n", $src); - $fileExcerpt = []; - - for ($i = max($line - 3, 1), $max = min($line + 3, \count($src)); $i <= $max; ++$i) { - $fileExcerpt[] = '<li'.($i === $line ? ' class="selected"' : '').'><code>'.$this->htmlEncode($src[$i - 1]).'</code></li>'; - } - - $fileExcerpt = '<ol start="'.max($line - 3, 1).'">'.implode("\n", $fileExcerpt).'</ol>'; - } - } - break; - } - } - break; - } - } - - if (false === $name) { - $name = str_replace('\\', '/', $file); - $name = substr($name, strrpos($name, '/') + 1); - } - - $context = ['name' => $name, 'file' => $file, 'line' => $line]; - $context['file_excerpt'] = $fileExcerpt; - - if (null !== $this->projectDir) { - $context['project_dir'] = $this->projectDir; - if (str_starts_with($file, $this->projectDir)) { - $context['file_relative'] = ltrim(substr($file, \strlen($this->projectDir)), \DIRECTORY_SEPARATOR); - } - } - - if ($this->fileLinkFormatter && $fileLink = $this->fileLinkFormatter->format($context['file'], $context['line'])) { - $context['file_link'] = $fileLink; - } - - return $context; - } - - private function htmlEncode(string $s): string - { - $html = ''; - - $dumper = new HtmlDumper(function ($line) use (&$html) { $html .= $line; }, $this->charset); - $dumper->setDumpHeader(''); - $dumper->setDumpBoundaries('', ''); - - $cloner = new VarCloner(); - $dumper->dump($cloner->cloneVar($s)); - - return substr(strip_tags($html), 1, -1); - } -} diff --git a/lib/symfony/var-dumper/Dumper/ContextualizedDumper.php b/lib/symfony/var-dumper/Dumper/ContextualizedDumper.php deleted file mode 100644 index 76384176e..000000000 --- a/lib/symfony/var-dumper/Dumper/ContextualizedDumper.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Dumper; - -use Symfony\Component\VarDumper\Cloner\Data; -use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface; - -/** - * @author Kévin Thérage <therage.kevin@gmail.com> - */ -class ContextualizedDumper implements DataDumperInterface -{ - private $wrappedDumper; - private $contextProviders; - - /** - * @param ContextProviderInterface[] $contextProviders - */ - public function __construct(DataDumperInterface $wrappedDumper, array $contextProviders) - { - $this->wrappedDumper = $wrappedDumper; - $this->contextProviders = $contextProviders; - } - - public function dump(Data $data) - { - $context = []; - foreach ($this->contextProviders as $contextProvider) { - $context[\get_class($contextProvider)] = $contextProvider->getContext(); - } - - $this->wrappedDumper->dump($data->withContext($context)); - } -} diff --git a/lib/symfony/var-dumper/Dumper/DataDumperInterface.php b/lib/symfony/var-dumper/Dumper/DataDumperInterface.php deleted file mode 100644 index b173bccf3..000000000 --- a/lib/symfony/var-dumper/Dumper/DataDumperInterface.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Dumper; - -use Symfony\Component\VarDumper\Cloner\Data; - -/** - * DataDumperInterface for dumping Data objects. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -interface DataDumperInterface -{ - public function dump(Data $data); -} diff --git a/lib/symfony/var-dumper/Dumper/HtmlDumper.php b/lib/symfony/var-dumper/Dumper/HtmlDumper.php deleted file mode 100644 index af4de9613..000000000 --- a/lib/symfony/var-dumper/Dumper/HtmlDumper.php +++ /dev/null @@ -1,986 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Dumper; - -use Symfony\Component\VarDumper\Cloner\Cursor; -use Symfony\Component\VarDumper\Cloner\Data; - -/** - * HtmlDumper dumps variables as HTML. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class HtmlDumper extends CliDumper -{ - public static $defaultOutput = 'php://output'; - - protected static $themes = [ - 'dark' => [ - 'default' => 'background-color:#18171B; color:#FF8400; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: break-all', - 'num' => 'font-weight:bold; color:#1299DA', - 'const' => 'font-weight:bold', - 'str' => 'font-weight:bold; color:#56DB3A', - 'note' => 'color:#1299DA', - 'ref' => 'color:#A0A0A0', - 'public' => 'color:#FFFFFF', - 'protected' => 'color:#FFFFFF', - 'private' => 'color:#FFFFFF', - 'meta' => 'color:#B729D9', - 'key' => 'color:#56DB3A', - 'index' => 'color:#1299DA', - 'ellipsis' => 'color:#FF8400', - 'ns' => 'user-select:none;', - ], - 'light' => [ - 'default' => 'background:none; color:#CC7832; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: break-all', - 'num' => 'font-weight:bold; color:#1299DA', - 'const' => 'font-weight:bold', - 'str' => 'font-weight:bold; color:#629755;', - 'note' => 'color:#6897BB', - 'ref' => 'color:#6E6E6E', - 'public' => 'color:#262626', - 'protected' => 'color:#262626', - 'private' => 'color:#262626', - 'meta' => 'color:#B729D9', - 'key' => 'color:#789339', - 'index' => 'color:#1299DA', - 'ellipsis' => 'color:#CC7832', - 'ns' => 'user-select:none;', - ], - ]; - - protected $dumpHeader; - protected $dumpPrefix = '<pre class=sf-dump id=%s data-indent-pad="%s">'; - protected $dumpSuffix = '</pre><script>Sfdump(%s)</script>'; - protected $dumpId = 'sf-dump'; - protected $colors = true; - protected $headerIsDumped = false; - protected $lastDepth = -1; - protected $styles; - - private $displayOptions = [ - 'maxDepth' => 1, - 'maxStringLength' => 160, - 'fileLinkFormat' => null, - ]; - private $extraDisplayOptions = []; - - /** - * {@inheritdoc} - */ - public function __construct($output = null, string $charset = null, int $flags = 0) - { - AbstractDumper::__construct($output, $charset, $flags); - $this->dumpId = 'sf-dump-'.mt_rand(); - $this->displayOptions['fileLinkFormat'] = \ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); - $this->styles = static::$themes['dark'] ?? self::$themes['dark']; - } - - /** - * {@inheritdoc} - */ - public function setStyles(array $styles) - { - $this->headerIsDumped = false; - $this->styles = $styles + $this->styles; - } - - public function setTheme(string $themeName) - { - if (!isset(static::$themes[$themeName])) { - throw new \InvalidArgumentException(sprintf('Theme "%s" does not exist in class "%s".', $themeName, static::class)); - } - - $this->setStyles(static::$themes[$themeName]); - } - - /** - * Configures display options. - * - * @param array $displayOptions A map of display options to customize the behavior - */ - public function setDisplayOptions(array $displayOptions) - { - $this->headerIsDumped = false; - $this->displayOptions = $displayOptions + $this->displayOptions; - } - - /** - * Sets an HTML header that will be dumped once in the output stream. - */ - public function setDumpHeader(?string $header) - { - $this->dumpHeader = $header; - } - - /** - * Sets an HTML prefix and suffix that will encapse every single dump. - */ - public function setDumpBoundaries(string $prefix, string $suffix) - { - $this->dumpPrefix = $prefix; - $this->dumpSuffix = $suffix; - } - - /** - * {@inheritdoc} - */ - public function dump(Data $data, $output = null, array $extraDisplayOptions = []) - { - $this->extraDisplayOptions = $extraDisplayOptions; - $result = parent::dump($data, $output); - $this->dumpId = 'sf-dump-'.mt_rand(); - - return $result; - } - - /** - * Dumps the HTML header. - */ - protected function getDumpHeader() - { - $this->headerIsDumped = $this->outputStream ?? $this->lineDumper; - - if (null !== $this->dumpHeader) { - return $this->dumpHeader; - } - - $line = str_replace('{$options}', json_encode($this->displayOptions, \JSON_FORCE_OBJECT), <<<'EOHTML' -<script> -Sfdump = window.Sfdump || (function (doc) { - -var refStyle = doc.createElement('style'), - rxEsc = /([.*+?^${}()|\[\]\/\\])/g, - idRx = /\bsf-dump-\d+-ref[012]\w+\b/, - keyHint = 0 <= navigator.platform.toUpperCase().indexOf('MAC') ? 'Cmd' : 'Ctrl', - addEventListener = function (e, n, cb) { - e.addEventListener(n, cb, false); - }; - -refStyle.innerHTML = 'pre.sf-dump .sf-dump-compact, .sf-dump-str-collapse .sf-dump-str-collapse, .sf-dump-str-expand .sf-dump-str-expand { display: none; }'; -(doc.documentElement.firstElementChild || doc.documentElement.children[0]).appendChild(refStyle); -refStyle = doc.createElement('style'); -(doc.documentElement.firstElementChild || doc.documentElement.children[0]).appendChild(refStyle); - -if (!doc.addEventListener) { - addEventListener = function (element, eventName, callback) { - element.attachEvent('on' + eventName, function (e) { - e.preventDefault = function () {e.returnValue = false;}; - e.target = e.srcElement; - callback(e); - }); - }; -} - -function toggle(a, recursive) { - var s = a.nextSibling || {}, oldClass = s.className, arrow, newClass; - - if (/\bsf-dump-compact\b/.test(oldClass)) { - arrow = '▼'; - newClass = 'sf-dump-expanded'; - } else if (/\bsf-dump-expanded\b/.test(oldClass)) { - arrow = '▶'; - newClass = 'sf-dump-compact'; - } else { - return false; - } - - if (doc.createEvent && s.dispatchEvent) { - var event = doc.createEvent('Event'); - event.initEvent('sf-dump-expanded' === newClass ? 'sfbeforedumpexpand' : 'sfbeforedumpcollapse', true, false); - - s.dispatchEvent(event); - } - - a.lastChild.innerHTML = arrow; - s.className = s.className.replace(/\bsf-dump-(compact|expanded)\b/, newClass); - - if (recursive) { - try { - a = s.querySelectorAll('.'+oldClass); - for (s = 0; s < a.length; ++s) { - if (-1 == a[s].className.indexOf(newClass)) { - a[s].className = newClass; - a[s].previousSibling.lastChild.innerHTML = arrow; - } - } - } catch (e) { - } - } - - return true; -}; - -function collapse(a, recursive) { - var s = a.nextSibling || {}, oldClass = s.className; - - if (/\bsf-dump-expanded\b/.test(oldClass)) { - toggle(a, recursive); - - return true; - } - - return false; -}; - -function expand(a, recursive) { - var s = a.nextSibling || {}, oldClass = s.className; - - if (/\bsf-dump-compact\b/.test(oldClass)) { - toggle(a, recursive); - - return true; - } - - return false; -}; - -function collapseAll(root) { - var a = root.querySelector('a.sf-dump-toggle'); - if (a) { - collapse(a, true); - expand(a); - - return true; - } - - return false; -} - -function reveal(node) { - var previous, parents = []; - - while ((node = node.parentNode || {}) && (previous = node.previousSibling) && 'A' === previous.tagName) { - parents.push(previous); - } - - if (0 !== parents.length) { - parents.forEach(function (parent) { - expand(parent); - }); - - return true; - } - - return false; -} - -function highlight(root, activeNode, nodes) { - resetHighlightedNodes(root); - - Array.from(nodes||[]).forEach(function (node) { - if (!/\bsf-dump-highlight\b/.test(node.className)) { - node.className = node.className + ' sf-dump-highlight'; - } - }); - - if (!/\bsf-dump-highlight-active\b/.test(activeNode.className)) { - activeNode.className = activeNode.className + ' sf-dump-highlight-active'; - } -} - -function resetHighlightedNodes(root) { - Array.from(root.querySelectorAll('.sf-dump-str, .sf-dump-key, .sf-dump-public, .sf-dump-protected, .sf-dump-private')).forEach(function (strNode) { - strNode.className = strNode.className.replace(/\bsf-dump-highlight\b/, ''); - strNode.className = strNode.className.replace(/\bsf-dump-highlight-active\b/, ''); - }); -} - -return function (root, x) { - root = doc.getElementById(root); - - var indentRx = new RegExp('^('+(root.getAttribute('data-indent-pad') || ' ').replace(rxEsc, '\\$1')+')+', 'm'), - options = {$options}, - elt = root.getElementsByTagName('A'), - len = elt.length, - i = 0, s, h, - t = []; - - while (i < len) t.push(elt[i++]); - - for (i in x) { - options[i] = x[i]; - } - - function a(e, f) { - addEventListener(root, e, function (e, n) { - if ('A' == e.target.tagName) { - f(e.target, e); - } else if ('A' == e.target.parentNode.tagName) { - f(e.target.parentNode, e); - } else { - n = /\bsf-dump-ellipsis\b/.test(e.target.className) ? e.target.parentNode : e.target; - - if ((n = n.nextElementSibling) && 'A' == n.tagName) { - if (!/\bsf-dump-toggle\b/.test(n.className)) { - n = n.nextElementSibling || n; - } - - f(n, e, true); - } - } - }); - }; - function isCtrlKey(e) { - return e.ctrlKey || e.metaKey; - } - function xpathString(str) { - var parts = str.match(/[^'"]+|['"]/g).map(function (part) { - if ("'" == part) { - return '"\'"'; - } - if ('"' == part) { - return "'\"'"; - } - - return "'" + part + "'"; - }); - - return "concat(" + parts.join(",") + ", '')"; - } - function xpathHasClass(className) { - return "contains(concat(' ', normalize-space(@class), ' '), ' " + className +" ')"; - } - addEventListener(root, 'mouseover', function (e) { - if ('' != refStyle.innerHTML) { - refStyle.innerHTML = ''; - } - }); - a('mouseover', function (a, e, c) { - if (c) { - e.target.style.cursor = "pointer"; - } else if (a = idRx.exec(a.className)) { - try { - refStyle.innerHTML = 'pre.sf-dump .'+a[0]+'{background-color: #B729D9; color: #FFF !important; border-radius: 2px}'; - } catch (e) { - } - } - }); - a('click', function (a, e, c) { - if (/\bsf-dump-toggle\b/.test(a.className)) { - e.preventDefault(); - if (!toggle(a, isCtrlKey(e))) { - var r = doc.getElementById(a.getAttribute('href').slice(1)), - s = r.previousSibling, - f = r.parentNode, - t = a.parentNode; - t.replaceChild(r, a); - f.replaceChild(a, s); - t.insertBefore(s, r); - f = f.firstChild.nodeValue.match(indentRx); - t = t.firstChild.nodeValue.match(indentRx); - if (f && t && f[0] !== t[0]) { - r.innerHTML = r.innerHTML.replace(new RegExp('^'+f[0].replace(rxEsc, '\\$1'), 'mg'), t[0]); - } - if (/\bsf-dump-compact\b/.test(r.className)) { - toggle(s, isCtrlKey(e)); - } - } - - if (c) { - } else if (doc.getSelection) { - try { - doc.getSelection().removeAllRanges(); - } catch (e) { - doc.getSelection().empty(); - } - } else { - doc.selection.empty(); - } - } else if (/\bsf-dump-str-toggle\b/.test(a.className)) { - e.preventDefault(); - e = a.parentNode.parentNode; - e.className = e.className.replace(/\bsf-dump-str-(expand|collapse)\b/, a.parentNode.className); - } - }); - - elt = root.getElementsByTagName('SAMP'); - len = elt.length; - i = 0; - - while (i < len) t.push(elt[i++]); - len = t.length; - - for (i = 0; i < len; ++i) { - elt = t[i]; - if ('SAMP' == elt.tagName) { - a = elt.previousSibling || {}; - if ('A' != a.tagName) { - a = doc.createElement('A'); - a.className = 'sf-dump-ref'; - elt.parentNode.insertBefore(a, elt); - } else { - a.innerHTML += ' '; - } - a.title = (a.title ? a.title+'\n[' : '[')+keyHint+'+click] Expand all children'; - a.innerHTML += elt.className == 'sf-dump-compact' ? '<span>▶</span>' : '<span>▼</span>'; - a.className += ' sf-dump-toggle'; - - x = 1; - if ('sf-dump' != elt.parentNode.className) { - x += elt.parentNode.getAttribute('data-depth')/1; - } - } else if (/\bsf-dump-ref\b/.test(elt.className) && (a = elt.getAttribute('href'))) { - a = a.slice(1); - elt.className += ' '+a; - - if (/[\[{]$/.test(elt.previousSibling.nodeValue)) { - a = a != elt.nextSibling.id && doc.getElementById(a); - try { - s = a.nextSibling; - elt.appendChild(a); - s.parentNode.insertBefore(a, s); - if (/^[@#]/.test(elt.innerHTML)) { - elt.innerHTML += ' <span>▶</span>'; - } else { - elt.innerHTML = '<span>▶</span>'; - elt.className = 'sf-dump-ref'; - } - elt.className += ' sf-dump-toggle'; - } catch (e) { - if ('&' == elt.innerHTML.charAt(0)) { - elt.innerHTML = '…'; - elt.className = 'sf-dump-ref'; - } - } - } - } - } - - if (doc.evaluate && Array.from && root.children.length > 1) { - root.setAttribute('tabindex', 0); - - SearchState = function () { - this.nodes = []; - this.idx = 0; - }; - SearchState.prototype = { - next: function () { - if (this.isEmpty()) { - return this.current(); - } - this.idx = this.idx < (this.nodes.length - 1) ? this.idx + 1 : 0; - - return this.current(); - }, - previous: function () { - if (this.isEmpty()) { - return this.current(); - } - this.idx = this.idx > 0 ? this.idx - 1 : (this.nodes.length - 1); - - return this.current(); - }, - isEmpty: function () { - return 0 === this.count(); - }, - current: function () { - if (this.isEmpty()) { - return null; - } - return this.nodes[this.idx]; - }, - reset: function () { - this.nodes = []; - this.idx = 0; - }, - count: function () { - return this.nodes.length; - }, - }; - - function showCurrent(state) - { - var currentNode = state.current(), currentRect, searchRect; - if (currentNode) { - reveal(currentNode); - highlight(root, currentNode, state.nodes); - if ('scrollIntoView' in currentNode) { - currentNode.scrollIntoView(true); - currentRect = currentNode.getBoundingClientRect(); - searchRect = search.getBoundingClientRect(); - if (currentRect.top < (searchRect.top + searchRect.height)) { - window.scrollBy(0, -(searchRect.top + searchRect.height + 5)); - } - } - } - counter.textContent = (state.isEmpty() ? 0 : state.idx + 1) + ' of ' + state.count(); - } - - var search = doc.createElement('div'); - search.className = 'sf-dump-search-wrapper sf-dump-search-hidden'; - search.innerHTML = ' - <input type="text" class="sf-dump-search-input"> - <span class="sf-dump-search-count">0 of 0<\/span> - <button type="button" class="sf-dump-search-input-previous" tabindex="-1"> - <svg viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1683 1331l-166 165q-19 19-45 19t-45-19L896 965l-531 531q-19 19-45 19t-45-19l-166-165q-19-19-19-45.5t19-45.5l742-741q19-19 45-19t45 19l742 741q19 19 19 45.5t-19 45.5z"\/><\/svg> - <\/button> - <button type="button" class="sf-dump-search-input-next" tabindex="-1"> - <svg viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1683 808l-742 741q-19 19-45 19t-45-19L109 808q-19-19-19-45.5t19-45.5l166-165q19-19 45-19t45 19l531 531 531-531q19-19 45-19t45 19l166 165q19 19 19 45.5t-19 45.5z"\/><\/svg> - <\/button> - '; - root.insertBefore(search, root.firstChild); - - var state = new SearchState(); - var searchInput = search.querySelector('.sf-dump-search-input'); - var counter = search.querySelector('.sf-dump-search-count'); - var searchInputTimer = 0; - var previousSearchQuery = ''; - - addEventListener(searchInput, 'keyup', function (e) { - var searchQuery = e.target.value; - /* Don't perform anything if the pressed key didn't change the query */ - if (searchQuery === previousSearchQuery) { - return; - } - previousSearchQuery = searchQuery; - clearTimeout(searchInputTimer); - searchInputTimer = setTimeout(function () { - state.reset(); - collapseAll(root); - resetHighlightedNodes(root); - if ('' === searchQuery) { - counter.textContent = '0 of 0'; - - return; - } - - var classMatches = [ - "sf-dump-str", - "sf-dump-key", - "sf-dump-public", - "sf-dump-protected", - "sf-dump-private", - ].map(xpathHasClass).join(' or '); - - var xpathResult = doc.evaluate('.//span[' + classMatches + '][contains(translate(child::text(), ' + xpathString(searchQuery.toUpperCase()) + ', ' + xpathString(searchQuery.toLowerCase()) + '), ' + xpathString(searchQuery.toLowerCase()) + ')]', root, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null); - - while (node = xpathResult.iterateNext()) state.nodes.push(node); - - showCurrent(state); - }, 400); - }); - - Array.from(search.querySelectorAll('.sf-dump-search-input-next, .sf-dump-search-input-previous')).forEach(function (btn) { - addEventListener(btn, 'click', function (e) { - e.preventDefault(); - -1 !== e.target.className.indexOf('next') ? state.next() : state.previous(); - searchInput.focus(); - collapseAll(root); - showCurrent(state); - }) - }); - - addEventListener(root, 'keydown', function (e) { - var isSearchActive = !/\bsf-dump-search-hidden\b/.test(search.className); - if ((114 === e.keyCode && !isSearchActive) || (isCtrlKey(e) && 70 === e.keyCode)) { - /* F3 or CMD/CTRL + F */ - if (70 === e.keyCode && document.activeElement === searchInput) { - /* - * If CMD/CTRL + F is hit while having focus on search input, - * the user probably meant to trigger browser search instead. - * Let the browser execute its behavior: - */ - return; - } - - e.preventDefault(); - search.className = search.className.replace(/\bsf-dump-search-hidden\b/, ''); - searchInput.focus(); - } else if (isSearchActive) { - if (27 === e.keyCode) { - /* ESC key */ - search.className += ' sf-dump-search-hidden'; - e.preventDefault(); - resetHighlightedNodes(root); - searchInput.value = ''; - } else if ( - (isCtrlKey(e) && 71 === e.keyCode) /* CMD/CTRL + G */ - || 13 === e.keyCode /* Enter */ - || 114 === e.keyCode /* F3 */ - ) { - e.preventDefault(); - e.shiftKey ? state.previous() : state.next(); - collapseAll(root); - showCurrent(state); - } - } - }); - } - - if (0 >= options.maxStringLength) { - return; - } - try { - elt = root.querySelectorAll('.sf-dump-str'); - len = elt.length; - i = 0; - t = []; - - while (i < len) t.push(elt[i++]); - len = t.length; - - for (i = 0; i < len; ++i) { - elt = t[i]; - s = elt.innerText || elt.textContent; - x = s.length - options.maxStringLength; - if (0 < x) { - h = elt.innerHTML; - elt[elt.innerText ? 'innerText' : 'textContent'] = s.substring(0, options.maxStringLength); - elt.className += ' sf-dump-str-collapse'; - elt.innerHTML = '<span class=sf-dump-str-collapse>'+h+'<a class="sf-dump-ref sf-dump-str-toggle" title="Collapse"> ◀</a></span>'+ - '<span class=sf-dump-str-expand>'+elt.innerHTML+'<a class="sf-dump-ref sf-dump-str-toggle" title="'+x+' remaining characters"> ▶</a></span>'; - } - } - } catch (e) { - } -}; - -})(document); -</script><style> -pre.sf-dump { - display: block; - white-space: pre; - padding: 5px; - overflow: initial !important; -} -pre.sf-dump:after { - content: ""; - visibility: hidden; - display: block; - height: 0; - clear: both; -} -pre.sf-dump span { - display: inline; -} -pre.sf-dump a { - text-decoration: none; - cursor: pointer; - border: 0; - outline: none; - color: inherit; -} -pre.sf-dump img { - max-width: 50em; - max-height: 50em; - margin: .5em 0 0 0; - padding: 0; - background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAHUlEQVQY02O8zAABilCaiQEN0EeA8QuUcX9g3QEAAjcC5piyhyEAAAAASUVORK5CYII=) #D3D3D3; -} -pre.sf-dump .sf-dump-ellipsis { - display: inline-block; - overflow: visible; - text-overflow: ellipsis; - max-width: 5em; - white-space: nowrap; - overflow: hidden; - vertical-align: top; -} -pre.sf-dump .sf-dump-ellipsis+.sf-dump-ellipsis { - max-width: none; -} -pre.sf-dump code { - display:inline; - padding:0; - background:none; -} -.sf-dump-public.sf-dump-highlight, -.sf-dump-protected.sf-dump-highlight, -.sf-dump-private.sf-dump-highlight, -.sf-dump-str.sf-dump-highlight, -.sf-dump-key.sf-dump-highlight { - background: rgba(111, 172, 204, 0.3); - border: 1px solid #7DA0B1; - border-radius: 3px; -} -.sf-dump-public.sf-dump-highlight-active, -.sf-dump-protected.sf-dump-highlight-active, -.sf-dump-private.sf-dump-highlight-active, -.sf-dump-str.sf-dump-highlight-active, -.sf-dump-key.sf-dump-highlight-active { - background: rgba(253, 175, 0, 0.4); - border: 1px solid #ffa500; - border-radius: 3px; -} -pre.sf-dump .sf-dump-search-hidden { - display: none !important; -} -pre.sf-dump .sf-dump-search-wrapper { - font-size: 0; - white-space: nowrap; - margin-bottom: 5px; - display: flex; - position: -webkit-sticky; - position: sticky; - top: 5px; -} -pre.sf-dump .sf-dump-search-wrapper > * { - vertical-align: top; - box-sizing: border-box; - height: 21px; - font-weight: normal; - border-radius: 0; - background: #FFF; - color: #757575; - border: 1px solid #BBB; -} -pre.sf-dump .sf-dump-search-wrapper > input.sf-dump-search-input { - padding: 3px; - height: 21px; - font-size: 12px; - border-right: none; - border-top-left-radius: 3px; - border-bottom-left-radius: 3px; - color: #000; - min-width: 15px; - width: 100%; -} -pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next, -pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-previous { - background: #F2F2F2; - outline: none; - border-left: none; - font-size: 0; - line-height: 0; -} -pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next { - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; -} -pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next > svg, -pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-previous > svg { - pointer-events: none; - width: 12px; - height: 12px; -} -pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-count { - display: inline-block; - padding: 0 5px; - margin: 0; - border-left: none; - line-height: 21px; - font-size: 12px; -} -EOHTML - ); - - foreach ($this->styles as $class => $style) { - $line .= 'pre.sf-dump'.('default' === $class ? ', pre.sf-dump' : '').' .sf-dump-'.$class.'{'.$style.'}'; - } - $line .= 'pre.sf-dump .sf-dump-ellipsis-note{'.$this->styles['note'].'}'; - - return $this->dumpHeader = preg_replace('/\s+/', ' ', $line).'</style>'.$this->dumpHeader; - } - - /** - * {@inheritdoc} - */ - public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut) - { - if ('' === $str && isset($cursor->attr['img-data'], $cursor->attr['content-type'])) { - $this->dumpKey($cursor); - $this->line .= $this->style('default', $cursor->attr['img-size'] ?? '', []); - $this->line .= $cursor->depth >= $this->displayOptions['maxDepth'] ? ' <samp class=sf-dump-compact>' : ' <samp class=sf-dump-expanded>'; - $this->endValue($cursor); - $this->line .= $this->indentPad; - $this->line .= sprintf('<img src="data:%s;base64,%s" /></samp>', $cursor->attr['content-type'], base64_encode($cursor->attr['img-data'])); - $this->endValue($cursor); - } else { - parent::dumpString($cursor, $str, $bin, $cut); - } - } - - /** - * {@inheritdoc} - */ - public function enterHash(Cursor $cursor, int $type, $class, bool $hasChild) - { - if (Cursor::HASH_OBJECT === $type) { - $cursor->attr['depth'] = $cursor->depth; - } - parent::enterHash($cursor, $type, $class, false); - - if ($cursor->skipChildren || $cursor->depth >= $this->displayOptions['maxDepth']) { - $cursor->skipChildren = false; - $eol = ' class=sf-dump-compact>'; - } else { - $this->expandNextHash = false; - $eol = ' class=sf-dump-expanded>'; - } - - if ($hasChild) { - $this->line .= '<samp data-depth='.($cursor->depth + 1); - if ($cursor->refIndex) { - $r = Cursor::HASH_OBJECT !== $type ? 1 - (Cursor::HASH_RESOURCE !== $type) : 2; - $r .= $r && 0 < $cursor->softRefHandle ? $cursor->softRefHandle : $cursor->refIndex; - - $this->line .= sprintf(' id=%s-ref%s', $this->dumpId, $r); - } - $this->line .= $eol; - $this->dumpLine($cursor->depth); - } - } - - /** - * {@inheritdoc} - */ - public function leaveHash(Cursor $cursor, int $type, $class, bool $hasChild, int $cut) - { - $this->dumpEllipsis($cursor, $hasChild, $cut); - if ($hasChild) { - $this->line .= '</samp>'; - } - parent::leaveHash($cursor, $type, $class, $hasChild, 0); - } - - /** - * {@inheritdoc} - */ - protected function style(string $style, string $value, array $attr = []) - { - if ('' === $value) { - return ''; - } - - $v = esc($value); - - if ('ref' === $style) { - if (empty($attr['count'])) { - return sprintf('<a class=sf-dump-ref>%s</a>', $v); - } - $r = ('#' !== $v[0] ? 1 - ('@' !== $v[0]) : 2).substr($value, 1); - - return sprintf('<a class=sf-dump-ref href=#%s-ref%s title="%d occurrences">%s</a>', $this->dumpId, $r, 1 + $attr['count'], $v); - } - - if ('const' === $style && isset($attr['value'])) { - $style .= sprintf(' title="%s"', esc(\is_scalar($attr['value']) ? $attr['value'] : json_encode($attr['value']))); - } elseif ('public' === $style) { - $style .= sprintf(' title="%s"', empty($attr['dynamic']) ? 'Public property' : 'Runtime added dynamic property'); - } elseif ('str' === $style && 1 < $attr['length']) { - $style .= sprintf(' title="%d%s characters"', $attr['length'], $attr['binary'] ? ' binary or non-UTF-8' : ''); - } elseif ('note' === $style && 0 < ($attr['depth'] ?? 0) && false !== $c = strrpos($value, '\\')) { - $style .= ' title=""'; - $attr += [ - 'ellipsis' => \strlen($value) - $c, - 'ellipsis-type' => 'note', - 'ellipsis-tail' => 1, - ]; - } elseif ('protected' === $style) { - $style .= ' title="Protected property"'; - } elseif ('meta' === $style && isset($attr['title'])) { - $style .= sprintf(' title="%s"', esc($this->utf8Encode($attr['title']))); - } elseif ('private' === $style) { - $style .= sprintf(' title="Private property defined in class:&#10;`%s`"', esc($this->utf8Encode($attr['class']))); - } - $map = static::$controlCharsMap; - - if (isset($attr['ellipsis'])) { - $class = 'sf-dump-ellipsis'; - if (isset($attr['ellipsis-type'])) { - $class = sprintf('"%s sf-dump-ellipsis-%s"', $class, $attr['ellipsis-type']); - } - $label = esc(substr($value, -$attr['ellipsis'])); - $style = str_replace(' title="', " title=\"$v\n", $style); - $v = sprintf('<span class=%s>%s</span>', $class, substr($v, 0, -\strlen($label))); - - if (!empty($attr['ellipsis-tail'])) { - $tail = \strlen(esc(substr($value, -$attr['ellipsis'], $attr['ellipsis-tail']))); - $v .= sprintf('<span class=%s>%s</span>%s', $class, substr($label, 0, $tail), substr($label, $tail)); - } else { - $v .= $label; - } - } - - $v = "<span class=sf-dump-{$style}>".preg_replace_callback(static::$controlCharsRx, function ($c) use ($map) { - $s = $b = '<span class="sf-dump-default'; - $c = $c[$i = 0]; - if ($ns = "\r" === $c[$i] || "\n" === $c[$i]) { - $s .= ' sf-dump-ns'; - } - $s .= '">'; - do { - if (("\r" === $c[$i] || "\n" === $c[$i]) !== $ns) { - $s .= '</span>'.$b; - if ($ns = !$ns) { - $s .= ' sf-dump-ns'; - } - $s .= '">'; - } - - $s .= $map[$c[$i]] ?? sprintf('\x%02X', \ord($c[$i])); - } while (isset($c[++$i])); - - return $s.'</span>'; - }, $v).'</span>'; - - if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], $attr['line'] ?? 0)) { - $attr['href'] = $href; - } - if (isset($attr['href'])) { - $target = isset($attr['file']) ? '' : ' target="_blank"'; - $v = sprintf('<a href="%s"%s rel="noopener noreferrer">%s</a>', esc($this->utf8Encode($attr['href'])), $target, $v); - } - if (isset($attr['lang'])) { - $v = sprintf('<code class="%s">%s</code>', esc($attr['lang']), $v); - } - - return $v; - } - - /** - * {@inheritdoc} - */ - protected function dumpLine(int $depth, bool $endOfValue = false) - { - if (-1 === $this->lastDepth) { - $this->line = sprintf($this->dumpPrefix, $this->dumpId, $this->indentPad).$this->line; - } - if ($this->headerIsDumped !== ($this->outputStream ?? $this->lineDumper)) { - $this->line = $this->getDumpHeader().$this->line; - } - - if (-1 === $depth) { - $args = ['"'.$this->dumpId.'"']; - if ($this->extraDisplayOptions) { - $args[] = json_encode($this->extraDisplayOptions, \JSON_FORCE_OBJECT); - } - // Replace is for BC - $this->line .= sprintf(str_replace('"%s"', '%s', $this->dumpSuffix), implode(', ', $args)); - } - $this->lastDepth = $depth; - - $this->line = mb_encode_numericentity($this->line, [0x80, 0x10FFFF, 0, 0x1FFFFF], 'UTF-8'); - - if (-1 === $depth) { - AbstractDumper::dumpLine(0); - } - AbstractDumper::dumpLine($depth); - } - - private function getSourceLink(string $file, int $line) - { - $options = $this->extraDisplayOptions + $this->displayOptions; - - if ($fmt = $options['fileLinkFormat']) { - return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line); - } - - return false; - } -} - -function esc(string $str) -{ - return htmlspecialchars($str, \ENT_QUOTES, 'UTF-8'); -} diff --git a/lib/symfony/var-dumper/Dumper/ServerDumper.php b/lib/symfony/var-dumper/Dumper/ServerDumper.php deleted file mode 100644 index 94795bf6d..000000000 --- a/lib/symfony/var-dumper/Dumper/ServerDumper.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Dumper; - -use Symfony\Component\VarDumper\Cloner\Data; -use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface; -use Symfony\Component\VarDumper\Server\Connection; - -/** - * ServerDumper forwards serialized Data clones to a server. - * - * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> - */ -class ServerDumper implements DataDumperInterface -{ - private $connection; - private $wrappedDumper; - - /** - * @param string $host The server host - * @param DataDumperInterface|null $wrappedDumper A wrapped instance used whenever we failed contacting the server - * @param ContextProviderInterface[] $contextProviders Context providers indexed by context name - */ - public function __construct(string $host, DataDumperInterface $wrappedDumper = null, array $contextProviders = []) - { - $this->connection = new Connection($host, $contextProviders); - $this->wrappedDumper = $wrappedDumper; - } - - public function getContextProviders(): array - { - return $this->connection->getContextProviders(); - } - - /** - * {@inheritdoc} - */ - public function dump(Data $data) - { - if (!$this->connection->write($data) && $this->wrappedDumper) { - $this->wrappedDumper->dump($data); - } - } -} diff --git a/lib/symfony/var-dumper/Exception/ThrowingCasterException.php b/lib/symfony/var-dumper/Exception/ThrowingCasterException.php deleted file mode 100644 index 122f0d358..000000000 --- a/lib/symfony/var-dumper/Exception/ThrowingCasterException.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Exception; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class ThrowingCasterException extends \Exception -{ - /** - * @param \Throwable $prev The exception thrown from the caster - */ - public function __construct(\Throwable $prev) - { - parent::__construct('Unexpected '.\get_class($prev).' thrown from a caster: '.$prev->getMessage(), 0, $prev); - } -} diff --git a/lib/symfony/var-dumper/LICENSE b/lib/symfony/var-dumper/LICENSE deleted file mode 100644 index a843ec124..000000000 --- a/lib/symfony/var-dumper/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2014-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/lib/symfony/var-dumper/README.md b/lib/symfony/var-dumper/README.md deleted file mode 100644 index a0da8c9ab..000000000 --- a/lib/symfony/var-dumper/README.md +++ /dev/null @@ -1,15 +0,0 @@ -VarDumper Component -=================== - -The VarDumper component provides mechanisms for walking through any arbitrary -PHP variable. It provides a better `dump()` function that you can use instead -of `var_dump()`. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/var_dumper/introduction.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/lib/symfony/var-dumper/Resources/bin/var-dump-server b/lib/symfony/var-dumper/Resources/bin/var-dump-server deleted file mode 100644 index 98c813a06..000000000 --- a/lib/symfony/var-dumper/Resources/bin/var-dump-server +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env php -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Starts a dump server to collect and output dumps on a single place with multiple formats support. - * - * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> - */ - -use Psr\Log\LoggerInterface; -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Input\ArgvInput; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Logger\ConsoleLogger; -use Symfony\Component\Console\Output\ConsoleOutput; -use Symfony\Component\VarDumper\Command\ServerDumpCommand; -use Symfony\Component\VarDumper\Server\DumpServer; - -function includeIfExists(string $file): bool -{ - return file_exists($file) && include $file; -} - -if ( - !includeIfExists(__DIR__ . '/../../../../autoload.php') && - !includeIfExists(__DIR__ . '/../../vendor/autoload.php') && - !includeIfExists(__DIR__ . '/../../../../../../vendor/autoload.php') -) { - fwrite(STDERR, 'Install dependencies using Composer.'.PHP_EOL); - exit(1); -} - -if (!class_exists(Application::class)) { - fwrite(STDERR, 'You need the "symfony/console" component in order to run the VarDumper server.'.PHP_EOL); - exit(1); -} - -$input = new ArgvInput(); -$output = new ConsoleOutput(); -$defaultHost = '127.0.0.1:9912'; -$host = $input->getParameterOption(['--host'], $_SERVER['VAR_DUMPER_SERVER'] ?? $defaultHost, true); -$logger = interface_exists(LoggerInterface::class) ? new ConsoleLogger($output->getErrorOutput()) : null; - -$app = new Application(); - -$app->getDefinition()->addOption( - new InputOption('--host', null, InputOption::VALUE_REQUIRED, 'The address the server should listen to', $defaultHost) -); - -$app->add($command = new ServerDumpCommand(new DumpServer($host, $logger))) - ->getApplication() - ->setDefaultCommand($command->getName(), true) - ->run($input, $output) -; diff --git a/lib/symfony/var-dumper/Resources/css/htmlDescriptor.css b/lib/symfony/var-dumper/Resources/css/htmlDescriptor.css deleted file mode 100644 index 8f706d640..000000000 --- a/lib/symfony/var-dumper/Resources/css/htmlDescriptor.css +++ /dev/null @@ -1,130 +0,0 @@ -body { - display: flex; - flex-direction: column-reverse; - justify-content: flex-end; - max-width: 1140px; - margin: auto; - padding: 15px; - word-wrap: break-word; - background-color: #F9F9F9; - color: #222; - font-family: Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 1.4; -} -p { - margin: 0; -} -a { - color: #218BC3; - text-decoration: none; -} -a:hover { - text-decoration: underline; -} -.text-small { - font-size: 12px !important; -} -article { - margin: 5px; - margin-bottom: 10px; -} -article > header > .row { - display: flex; - flex-direction: row; - align-items: baseline; - margin-bottom: 10px; -} -article > header > .row > .col { - flex: 1; - display: flex; - align-items: baseline; -} -article > header > .row > h2 { - font-size: 14px; - color: #222; - font-weight: normal; - font-family: "Lucida Console", monospace, sans-serif; - word-break: break-all; - margin: 20px 5px 0 0; - user-select: all; -} -article > header > .row > h2 > code { - white-space: nowrap; - user-select: none; - color: #cc2255; - background-color: #f7f7f9; - border: 1px solid #e1e1e8; - border-radius: 3px; - margin-right: 5px; - padding: 0 3px; -} -article > header > .row > time.col { - flex: 0; - text-align: right; - white-space: nowrap; - color: #999; - font-style: italic; -} -article > header ul.tags { - list-style: none; - padding: 0; - margin: 0; - font-size: 12px; -} -article > header ul.tags > li { - user-select: all; - margin-bottom: 2px; -} -article > header ul.tags > li > span.badge { - display: inline-block; - padding: .25em .4em; - margin-right: 5px; - border-radius: 4px; - background-color: #6c757d3b; - color: #524d4d; - font-size: 12px; - text-align: center; - font-weight: 700; - line-height: 1; - white-space: nowrap; - vertical-align: baseline; - user-select: none; -} -article > section.body { - border: 1px solid #d8d8d8; - background: #FFF; - padding: 10px; - border-radius: 3px; -} -pre.sf-dump { - border-radius: 3px; - margin-bottom: 0; -} -.hidden { - display: none !important; -} -.dumped-tag > .sf-dump { - display: inline-block; - margin: 0; - padding: 1px 5px; - line-height: 1.4; - vertical-align: top; - background-color: transparent; - user-select: auto; -} -.dumped-tag > pre.sf-dump, -.dumped-tag > .sf-dump-default { - color: #CC7832; - background: none; -} -.dumped-tag > .sf-dump .sf-dump-str { color: #629755; } -.dumped-tag > .sf-dump .sf-dump-private, -.dumped-tag > .sf-dump .sf-dump-protected, -.dumped-tag > .sf-dump .sf-dump-public { color: #262626; } -.dumped-tag > .sf-dump .sf-dump-note { color: #6897BB; } -.dumped-tag > .sf-dump .sf-dump-key { color: #789339; } -.dumped-tag > .sf-dump .sf-dump-ref { color: #6E6E6E; } -.dumped-tag > .sf-dump .sf-dump-ellipsis { color: #CC7832; max-width: 100em; } -.dumped-tag > .sf-dump .sf-dump-ellipsis-path { max-width: 5em; } -.dumped-tag > .sf-dump .sf-dump-ns { user-select: none; } diff --git a/lib/symfony/var-dumper/Resources/functions/dump.php b/lib/symfony/var-dumper/Resources/functions/dump.php deleted file mode 100644 index f26aad5bd..000000000 --- a/lib/symfony/var-dumper/Resources/functions/dump.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Component\VarDumper\VarDumper; - -if (!function_exists('dump')) { - /** - * @author Nicolas Grekas <p@tchwork.com> - */ - function dump($var, ...$moreVars) - { - VarDumper::dump($var); - - foreach ($moreVars as $v) { - VarDumper::dump($v); - } - - if (1 < func_num_args()) { - return func_get_args(); - } - - return $var; - } -} - -if (!function_exists('dd')) { - /** - * @return never - */ - function dd(...$vars) - { - if (!in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && !headers_sent()) { - header('HTTP/1.1 500 Internal Server Error'); - } - - foreach ($vars as $v) { - VarDumper::dump($v); - } - - exit(1); - } -} diff --git a/lib/symfony/var-dumper/Resources/js/htmlDescriptor.js b/lib/symfony/var-dumper/Resources/js/htmlDescriptor.js deleted file mode 100644 index 63101e57c..000000000 --- a/lib/symfony/var-dumper/Resources/js/htmlDescriptor.js +++ /dev/null @@ -1,10 +0,0 @@ -document.addEventListener('DOMContentLoaded', function() { - let prev = null; - Array.from(document.getElementsByTagName('article')).reverse().forEach(function (article) { - const dedupId = article.dataset.dedupId; - if (dedupId === prev) { - article.getElementsByTagName('header')[0].classList.add('hidden'); - } - prev = dedupId; - }); -}); diff --git a/lib/symfony/var-dumper/Server/Connection.php b/lib/symfony/var-dumper/Server/Connection.php deleted file mode 100644 index d0611a1f6..000000000 --- a/lib/symfony/var-dumper/Server/Connection.php +++ /dev/null @@ -1,99 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Server; - -use Symfony\Component\VarDumper\Cloner\Data; -use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface; - -/** - * Forwards serialized Data clones to a server. - * - * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> - */ -class Connection -{ - private $host; - private $contextProviders; - - /** - * @var resource|null - */ - private $socket; - - /** - * @param string $host The server host - * @param ContextProviderInterface[] $contextProviders Context providers indexed by context name - */ - public function __construct(string $host, array $contextProviders = []) - { - if (!str_contains($host, '://')) { - $host = 'tcp://'.$host; - } - - $this->host = $host; - $this->contextProviders = $contextProviders; - } - - public function getContextProviders(): array - { - return $this->contextProviders; - } - - public function write(Data $data): bool - { - $socketIsFresh = !$this->socket; - if (!$this->socket = $this->socket ?: $this->createSocket()) { - return false; - } - - $context = ['timestamp' => microtime(true)]; - foreach ($this->contextProviders as $name => $provider) { - $context[$name] = $provider->getContext(); - } - $context = array_filter($context); - $encodedPayload = base64_encode(serialize([$data, $context]))."\n"; - - set_error_handler([self::class, 'nullErrorHandler']); - try { - if (-1 !== stream_socket_sendto($this->socket, $encodedPayload)) { - return true; - } - if (!$socketIsFresh) { - stream_socket_shutdown($this->socket, \STREAM_SHUT_RDWR); - fclose($this->socket); - $this->socket = $this->createSocket(); - } - if (-1 !== stream_socket_sendto($this->socket, $encodedPayload)) { - return true; - } - } finally { - restore_error_handler(); - } - - return false; - } - - private static function nullErrorHandler(int $t, string $m) - { - // no-op - } - - private function createSocket() - { - set_error_handler([self::class, 'nullErrorHandler']); - try { - return stream_socket_client($this->host, $errno, $errstr, 3, \STREAM_CLIENT_CONNECT | \STREAM_CLIENT_ASYNC_CONNECT); - } finally { - restore_error_handler(); - } - } -} diff --git a/lib/symfony/var-dumper/Server/DumpServer.php b/lib/symfony/var-dumper/Server/DumpServer.php deleted file mode 100644 index f9735db78..000000000 --- a/lib/symfony/var-dumper/Server/DumpServer.php +++ /dev/null @@ -1,115 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Server; - -use Psr\Log\LoggerInterface; -use Symfony\Component\VarDumper\Cloner\Data; -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * A server collecting Data clones sent by a ServerDumper. - * - * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> - * - * @final - */ -class DumpServer -{ - private $host; - private $logger; - - /** - * @var resource|null - */ - private $socket; - - public function __construct(string $host, LoggerInterface $logger = null) - { - if (!str_contains($host, '://')) { - $host = 'tcp://'.$host; - } - - $this->host = $host; - $this->logger = $logger; - } - - public function start(): void - { - if (!$this->socket = stream_socket_server($this->host, $errno, $errstr)) { - throw new \RuntimeException(sprintf('Server start failed on "%s": ', $this->host).$errstr.' '.$errno); - } - } - - public function listen(callable $callback): void - { - if (null === $this->socket) { - $this->start(); - } - - foreach ($this->getMessages() as $clientId => $message) { - if ($this->logger) { - $this->logger->info('Received a payload from client {clientId}', ['clientId' => $clientId]); - } - - $payload = @unserialize(base64_decode($message), ['allowed_classes' => [Data::class, Stub::class]]); - - // Impossible to decode the message, give up. - if (false === $payload) { - if ($this->logger) { - $this->logger->warning('Unable to decode a message from {clientId} client.', ['clientId' => $clientId]); - } - - continue; - } - - if (!\is_array($payload) || \count($payload) < 2 || !$payload[0] instanceof Data || !\is_array($payload[1])) { - if ($this->logger) { - $this->logger->warning('Invalid payload from {clientId} client. Expected an array of two elements (Data $data, array $context)', ['clientId' => $clientId]); - } - - continue; - } - - [$data, $context] = $payload; - - $callback($data, $context, $clientId); - } - } - - public function getHost(): string - { - return $this->host; - } - - private function getMessages(): iterable - { - $sockets = [(int) $this->socket => $this->socket]; - $write = []; - - while (true) { - $read = $sockets; - stream_select($read, $write, $write, null); - - foreach ($read as $stream) { - if ($this->socket === $stream) { - $stream = stream_socket_accept($this->socket); - $sockets[(int) $stream] = $stream; - } elseif (feof($stream)) { - unset($sockets[(int) $stream]); - fclose($stream); - } else { - yield (int) $stream => fgets($stream); - } - } - } - } -} diff --git a/lib/symfony/var-dumper/VarDumper.php b/lib/symfony/var-dumper/VarDumper.php deleted file mode 100644 index 20429ac78..000000000 --- a/lib/symfony/var-dumper/VarDumper.php +++ /dev/null @@ -1,115 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; -use Symfony\Component\VarDumper\Caster\ReflectionCaster; -use Symfony\Component\VarDumper\Cloner\VarCloner; -use Symfony\Component\VarDumper\Dumper\CliDumper; -use Symfony\Component\VarDumper\Dumper\ContextProvider\CliContextProvider; -use Symfony\Component\VarDumper\Dumper\ContextProvider\RequestContextProvider; -use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider; -use Symfony\Component\VarDumper\Dumper\ContextualizedDumper; -use Symfony\Component\VarDumper\Dumper\HtmlDumper; -use Symfony\Component\VarDumper\Dumper\ServerDumper; - -// Load the global dump() function -require_once __DIR__.'/Resources/functions/dump.php'; - -/** - * @author Nicolas Grekas <p@tchwork.com> - */ -class VarDumper -{ - /** - * @var callable|null - */ - private static $handler; - - public static function dump($var) - { - if (null === self::$handler) { - self::register(); - } - - return (self::$handler)($var); - } - - /** - * @return callable|null - */ - public static function setHandler(callable $callable = null) - { - $prevHandler = self::$handler; - - // Prevent replacing the handler with expected format as soon as the env var was set: - if (isset($_SERVER['VAR_DUMPER_FORMAT'])) { - return $prevHandler; - } - - self::$handler = $callable; - - return $prevHandler; - } - - private static function register(): void - { - $cloner = new VarCloner(); - $cloner->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO); - - $format = $_SERVER['VAR_DUMPER_FORMAT'] ?? null; - switch (true) { - case 'html' === $format: - $dumper = new HtmlDumper(); - break; - case 'cli' === $format: - $dumper = new CliDumper(); - break; - case 'server' === $format: - case $format && 'tcp' === parse_url($format, \PHP_URL_SCHEME): - $host = 'server' === $format ? $_SERVER['VAR_DUMPER_SERVER'] ?? '127.0.0.1:9912' : $format; - $dumper = \in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? new CliDumper() : new HtmlDumper(); - $dumper = new ServerDumper($host, $dumper, self::getDefaultContextProviders()); - break; - default: - $dumper = \in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? new CliDumper() : new HtmlDumper(); - } - - if (!$dumper instanceof ServerDumper) { - $dumper = new ContextualizedDumper($dumper, [new SourceContextProvider()]); - } - - self::$handler = function ($var) use ($cloner, $dumper) { - $dumper->dump($cloner->cloneVar($var)); - }; - } - - private static function getDefaultContextProviders(): array - { - $contextProviders = []; - - if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && class_exists(Request::class)) { - $requestStack = new RequestStack(); - $requestStack->push(Request::createFromGlobals()); - $contextProviders['request'] = new RequestContextProvider($requestStack); - } - - $fileLinkFormatter = class_exists(FileLinkFormatter::class) ? new FileLinkFormatter(null, $requestStack ?? null) : null; - - return $contextProviders + [ - 'cli' => new CliContextProvider(), - 'source' => new SourceContextProvider(null, null, $fileLinkFormatter), - ]; - } -} diff --git a/lib/symfony/var-dumper/composer.json b/lib/symfony/var-dumper/composer.json deleted file mode 100644 index dc46f58d9..000000000 --- a/lib/symfony/var-dumper/composer.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "name": "symfony/var-dumper", - "type": "library", - "description": "Provides mechanisms for walking through any arbitrary PHP variable", - "keywords": ["dump", "debug"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "^1.16" - }, - "require-dev": { - "ext-iconv": "*", - "symfony/console": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/uid": "^5.1|^6.0", - "twig/twig": "^2.13|^3.0.4" - }, - "conflict": { - "phpunit/phpunit": "<5.4.3", - "symfony/console": "<4.4" - }, - "suggest": { - "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", - "ext-intl": "To show region name in time zone dump", - "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" - }, - "autoload": { - "files": [ "Resources/functions/dump.php" ], - "psr-4": { "Symfony\\Component\\VarDumper\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "bin": [ - "Resources/bin/var-dump-server" - ], - "minimum-stability": "dev" -} diff --git a/lib/symfony/var-exporter/CHANGELOG.md b/lib/symfony/var-exporter/CHANGELOG.md deleted file mode 100644 index 3406c30ef..000000000 --- a/lib/symfony/var-exporter/CHANGELOG.md +++ /dev/null @@ -1,12 +0,0 @@ -CHANGELOG -========= - -5.1.0 ------ - - * added argument `array &$foundClasses` to `VarExporter::export()` to ease with preloading exported values - -4.2.0 ------ - - * added the component diff --git a/lib/symfony/var-exporter/Exception/ClassNotFoundException.php b/lib/symfony/var-exporter/Exception/ClassNotFoundException.php deleted file mode 100644 index 4cebe44b0..000000000 --- a/lib/symfony/var-exporter/Exception/ClassNotFoundException.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter\Exception; - -class ClassNotFoundException extends \Exception implements ExceptionInterface -{ - public function __construct(string $class, \Throwable $previous = null) - { - parent::__construct(sprintf('Class "%s" not found.', $class), 0, $previous); - } -} diff --git a/lib/symfony/var-exporter/Exception/ExceptionInterface.php b/lib/symfony/var-exporter/Exception/ExceptionInterface.php deleted file mode 100644 index adfaed47c..000000000 --- a/lib/symfony/var-exporter/Exception/ExceptionInterface.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter\Exception; - -interface ExceptionInterface extends \Throwable -{ -} diff --git a/lib/symfony/var-exporter/Exception/NotInstantiableTypeException.php b/lib/symfony/var-exporter/Exception/NotInstantiableTypeException.php deleted file mode 100644 index 771ee612d..000000000 --- a/lib/symfony/var-exporter/Exception/NotInstantiableTypeException.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter\Exception; - -class NotInstantiableTypeException extends \Exception implements ExceptionInterface -{ - public function __construct(string $type, \Throwable $previous = null) - { - parent::__construct(sprintf('Type "%s" is not instantiable.', $type), 0, $previous); - } -} diff --git a/lib/symfony/var-exporter/Instantiator.php b/lib/symfony/var-exporter/Instantiator.php deleted file mode 100644 index 368c769ac..000000000 --- a/lib/symfony/var-exporter/Instantiator.php +++ /dev/null @@ -1,92 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter; - -use Symfony\Component\VarExporter\Exception\ExceptionInterface; -use Symfony\Component\VarExporter\Exception\NotInstantiableTypeException; -use Symfony\Component\VarExporter\Internal\Hydrator; -use Symfony\Component\VarExporter\Internal\Registry; - -/** - * A utility class to create objects without calling their constructor. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -final class Instantiator -{ - /** - * Creates an object and sets its properties without calling its constructor nor any other methods. - * - * For example: - * - * // creates an empty instance of Foo - * Instantiator::instantiate(Foo::class); - * - * // creates a Foo instance and sets one of its properties - * Instantiator::instantiate(Foo::class, ['propertyName' => $propertyValue]); - * - * // creates a Foo instance and sets a private property defined on its parent Bar class - * Instantiator::instantiate(Foo::class, [], [ - * Bar::class => ['privateBarProperty' => $propertyValue], - * ]); - * - * Instances of ArrayObject, ArrayIterator and SplObjectStorage can be created - * by using the special "\0" property name to define their internal value: - * - * // creates an SplObjectStorage where $info1 is attached to $obj1, etc. - * Instantiator::instantiate(SplObjectStorage::class, ["\0" => [$obj1, $info1, $obj2, $info2...]]); - * - * // creates an ArrayObject populated with $inputArray - * Instantiator::instantiate(ArrayObject::class, ["\0" => [$inputArray]]); - * - * @param string $class The class of the instance to create - * @param array $properties The properties to set on the instance - * @param array $privateProperties The private properties to set on the instance, - * keyed by their declaring class - * - * @throws ExceptionInterface When the instance cannot be created - */ - public static function instantiate(string $class, array $properties = [], array $privateProperties = []): object - { - $reflector = Registry::$reflectors[$class] ?? Registry::getClassReflector($class); - - if (Registry::$cloneable[$class]) { - $wrappedInstance = [clone Registry::$prototypes[$class]]; - } elseif (Registry::$instantiableWithoutConstructor[$class]) { - $wrappedInstance = [$reflector->newInstanceWithoutConstructor()]; - } elseif (null === Registry::$prototypes[$class]) { - throw new NotInstantiableTypeException($class); - } elseif ($reflector->implementsInterface('Serializable') && (\PHP_VERSION_ID < 70400 || !method_exists($class, '__unserialize'))) { - $wrappedInstance = [unserialize('C:'.\strlen($class).':"'.$class.'":0:{}')]; - } else { - $wrappedInstance = [unserialize('O:'.\strlen($class).':"'.$class.'":0:{}')]; - } - - if ($properties) { - $privateProperties[$class] = isset($privateProperties[$class]) ? $properties + $privateProperties[$class] : $properties; - } - - foreach ($privateProperties as $class => $properties) { - if (!$properties) { - continue; - } - foreach ($properties as $name => $value) { - // because they're also used for "unserialization", hydrators - // deal with array of instances, so we need to wrap values - $properties[$name] = [$value]; - } - (Hydrator::$hydrators[$class] ?? Hydrator::getHydrator($class))($properties, $wrappedInstance); - } - - return $wrappedInstance[0]; - } -} diff --git a/lib/symfony/var-exporter/Internal/Exporter.php b/lib/symfony/var-exporter/Internal/Exporter.php deleted file mode 100644 index a034dddb9..000000000 --- a/lib/symfony/var-exporter/Internal/Exporter.php +++ /dev/null @@ -1,406 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter\Internal; - -use Symfony\Component\VarExporter\Exception\NotInstantiableTypeException; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -class Exporter -{ - /** - * Prepares an array of values for VarExporter. - * - * For performance this method is public and has no type-hints. - * - * @param array &$values - * @param \SplObjectStorage $objectsPool - * @param array &$refsPool - * @param int &$objectsCount - * @param bool &$valuesAreStatic - * - * @throws NotInstantiableTypeException When a value cannot be serialized - */ - public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount, &$valuesAreStatic): array - { - $refs = $values; - foreach ($values as $k => $value) { - if (\is_resource($value)) { - throw new NotInstantiableTypeException(get_resource_type($value).' resource'); - } - $refs[$k] = $objectsPool; - - if ($isRef = !$valueIsStatic = $values[$k] !== $objectsPool) { - $values[$k] = &$value; // Break hard references to make $values completely - unset($value); // independent from the original structure - $refs[$k] = $value = $values[$k]; - if ($value instanceof Reference && 0 > $value->id) { - $valuesAreStatic = false; - ++$value->count; - continue; - } - $refsPool[] = [&$refs[$k], $value, &$value]; - $refs[$k] = $values[$k] = new Reference(-\count($refsPool), $value); - } - - if (\is_array($value)) { - if ($value) { - $value = self::prepare($value, $objectsPool, $refsPool, $objectsCount, $valueIsStatic); - } - goto handle_value; - } elseif (!\is_object($value) || $value instanceof \UnitEnum) { - goto handle_value; - } - - $valueIsStatic = false; - if (isset($objectsPool[$value])) { - ++$objectsCount; - $value = new Reference($objectsPool[$value][0]); - goto handle_value; - } - - $class = \get_class($value); - $reflector = Registry::$reflectors[$class] ?? Registry::getClassReflector($class); - - if ($reflector->hasMethod('__serialize')) { - if (!$reflector->getMethod('__serialize')->isPublic()) { - throw new \Error(sprintf('Call to %s method "%s::__serialize()".', $reflector->getMethod('__serialize')->isProtected() ? 'protected' : 'private', $class)); - } - - if (!\is_array($properties = $value->__serialize())) { - throw new \TypeError($class.'::__serialize() must return an array'); - } - - goto prepare_value; - } - - $properties = []; - $sleep = null; - $proto = Registry::$prototypes[$class]; - - if (($value instanceof \ArrayIterator || $value instanceof \ArrayObject) && null !== $proto) { - // ArrayIterator and ArrayObject need special care because their "flags" - // option changes the behavior of the (array) casting operator. - [$arrayValue, $properties] = self::getArrayObjectProperties($value, $proto); - - // populates Registry::$prototypes[$class] with a new instance - Registry::getClassReflector($class, Registry::$instantiableWithoutConstructor[$class], Registry::$cloneable[$class]); - } elseif ($value instanceof \SplObjectStorage && Registry::$cloneable[$class] && null !== $proto) { - // By implementing Serializable, SplObjectStorage breaks - // internal references; let's deal with it on our own. - foreach (clone $value as $v) { - $properties[] = $v; - $properties[] = $value[$v]; - } - $properties = ['SplObjectStorage' => ["\0" => $properties]]; - $arrayValue = (array) $value; - } elseif ($value instanceof \Serializable - || $value instanceof \__PHP_Incomplete_Class - || \PHP_VERSION_ID < 80200 && $value instanceof \DatePeriod - ) { - ++$objectsCount; - $objectsPool[$value] = [$id = \count($objectsPool), serialize($value), [], 0]; - $value = new Reference($id); - goto handle_value; - } else { - if (method_exists($class, '__sleep')) { - if (!\is_array($sleep = $value->__sleep())) { - trigger_error('serialize(): __sleep should return an array only containing the names of instance-variables to serialize', \E_USER_NOTICE); - $value = null; - goto handle_value; - } - $sleep = array_flip($sleep); - } - - $arrayValue = (array) $value; - } - - $proto = (array) $proto; - - foreach ($arrayValue as $name => $v) { - $i = 0; - $n = (string) $name; - if ('' === $n || "\0" !== $n[0]) { - $c = \PHP_VERSION_ID >= 80100 && $reflector->hasProperty($n) && ($p = $reflector->getProperty($n))->isReadOnly() ? $p->class : 'stdClass'; - } elseif ('*' === $n[1]) { - $n = substr($n, 3); - $c = $reflector->getProperty($n)->class; - if ('Error' === $c) { - $c = 'TypeError'; - } elseif ('Exception' === $c) { - $c = 'ErrorException'; - } - } else { - $i = strpos($n, "\0", 2); - $c = substr($n, 1, $i - 1); - $n = substr($n, 1 + $i); - } - if (null !== $sleep) { - if (!isset($sleep[$n]) || ($i && $c !== $class)) { - continue; - } - $sleep[$n] = false; - } - if (!\array_key_exists($name, $proto) || $proto[$name] !== $v || "\x00Error\x00trace" === $name || "\x00Exception\x00trace" === $name) { - $properties[$c][$n] = $v; - } - } - if ($sleep) { - foreach ($sleep as $n => $v) { - if (false !== $v) { - trigger_error(sprintf('serialize(): "%s" returned as member variable from __sleep() but does not exist', $n), \E_USER_NOTICE); - } - } - } - - prepare_value: - $objectsPool[$value] = [$id = \count($objectsPool)]; - $properties = self::prepare($properties, $objectsPool, $refsPool, $objectsCount, $valueIsStatic); - ++$objectsCount; - $objectsPool[$value] = [$id, $class, $properties, method_exists($class, '__unserialize') ? -$objectsCount : (method_exists($class, '__wakeup') ? $objectsCount : 0)]; - - $value = new Reference($id); - - handle_value: - if ($isRef) { - unset($value); // Break the hard reference created above - } elseif (!$valueIsStatic) { - $values[$k] = $value; - } - $valuesAreStatic = $valueIsStatic && $valuesAreStatic; - } - - return $values; - } - - public static function export($value, string $indent = '') - { - switch (true) { - case \is_int($value) || \is_float($value): return var_export($value, true); - case [] === $value: return '[]'; - case false === $value: return 'false'; - case true === $value: return 'true'; - case null === $value: return 'null'; - case '' === $value: return "''"; - case $value instanceof \UnitEnum: return ltrim(var_export($value, true), '\\'); - } - - if ($value instanceof Reference) { - if (0 <= $value->id) { - return '$o['.$value->id.']'; - } - if (!$value->count) { - return self::export($value->value, $indent); - } - $value = -$value->id; - - return '&$r['.$value.']'; - } - $subIndent = $indent.' '; - - if (\is_string($value)) { - $code = sprintf("'%s'", addcslashes($value, "'\\")); - - $code = preg_replace_callback("/((?:[\\0\\r\\n]|\u{202A}|\u{202B}|\u{202D}|\u{202E}|\u{2066}|\u{2067}|\u{2068}|\u{202C}|\u{2069})++)(.)/", function ($m) use ($subIndent) { - $m[1] = sprintf('\'."%s".\'', str_replace( - ["\0", "\r", "\n", "\u{202A}", "\u{202B}", "\u{202D}", "\u{202E}", "\u{2066}", "\u{2067}", "\u{2068}", "\u{202C}", "\u{2069}", '\n\\'], - ['\0', '\r', '\n', '\u{202A}', '\u{202B}', '\u{202D}', '\u{202E}', '\u{2066}', '\u{2067}', '\u{2068}', '\u{202C}', '\u{2069}', '\n"'."\n".$subIndent.'."\\'], - $m[1] - )); - - if ("'" === $m[2]) { - return substr($m[1], 0, -2); - } - - if ('n".\'' === substr($m[1], -4)) { - return substr_replace($m[1], "\n".$subIndent.".'".$m[2], -2); - } - - return $m[1].$m[2]; - }, $code, -1, $count); - - if ($count && str_starts_with($code, "''.")) { - $code = substr($code, 3); - } - - return $code; - } - - if (\is_array($value)) { - $j = -1; - $code = ''; - foreach ($value as $k => $v) { - $code .= $subIndent; - if (!\is_int($k) || 1 !== $k - $j) { - $code .= self::export($k, $subIndent).' => '; - } - if (\is_int($k) && $k > $j) { - $j = $k; - } - $code .= self::export($v, $subIndent).",\n"; - } - - return "[\n".$code.$indent.']'; - } - - if ($value instanceof Values) { - $code = $subIndent."\$r = [],\n"; - foreach ($value->values as $k => $v) { - $code .= $subIndent.'$r['.$k.'] = '.self::export($v, $subIndent).",\n"; - } - - return "[\n".$code.$indent.']'; - } - - if ($value instanceof Registry) { - return self::exportRegistry($value, $indent, $subIndent); - } - - if ($value instanceof Hydrator) { - return self::exportHydrator($value, $indent, $subIndent); - } - - throw new \UnexpectedValueException(sprintf('Cannot export value of type "%s".', get_debug_type($value))); - } - - private static function exportRegistry(Registry $value, string $indent, string $subIndent): string - { - $code = ''; - $serializables = []; - $seen = []; - $prototypesAccess = 0; - $factoriesAccess = 0; - $r = '\\'.Registry::class; - $j = -1; - - foreach ($value->classes as $k => $class) { - if (':' === ($class[1] ?? null)) { - $serializables[$k] = $class; - continue; - } - if (!Registry::$instantiableWithoutConstructor[$class]) { - if (is_subclass_of($class, 'Serializable') && !method_exists($class, '__unserialize')) { - $serializables[$k] = 'C:'.\strlen($class).':"'.$class.'":0:{}'; - } else { - $serializables[$k] = 'O:'.\strlen($class).':"'.$class.'":0:{}'; - } - if (is_subclass_of($class, 'Throwable')) { - $eol = is_subclass_of($class, 'Error') ? "\0Error\0" : "\0Exception\0"; - $serializables[$k] = substr_replace($serializables[$k], '1:{s:'.(5 + \strlen($eol)).':"'.$eol.'trace";a:0:{}}', -4); - } - continue; - } - $code .= $subIndent.(1 !== $k - $j ? $k.' => ' : ''); - $j = $k; - $eol = ",\n"; - $c = '['.self::export($class).']'; - - if ($seen[$class] ?? false) { - if (Registry::$cloneable[$class]) { - ++$prototypesAccess; - $code .= 'clone $p'.$c; - } else { - ++$factoriesAccess; - $code .= '$f'.$c.'()'; - } - } else { - $seen[$class] = true; - if (Registry::$cloneable[$class]) { - $code .= 'clone ('.($prototypesAccess++ ? '$p' : '($p = &'.$r.'::$prototypes)').$c.' ?? '.$r.'::p'; - } else { - $code .= '('.($factoriesAccess++ ? '$f' : '($f = &'.$r.'::$factories)').$c.' ?? '.$r.'::f'; - $eol = '()'.$eol; - } - $code .= '('.substr($c, 1, -1).'))'; - } - $code .= $eol; - } - - if (1 === $prototypesAccess) { - $code = str_replace('($p = &'.$r.'::$prototypes)', $r.'::$prototypes', $code); - } - if (1 === $factoriesAccess) { - $code = str_replace('($f = &'.$r.'::$factories)', $r.'::$factories', $code); - } - if ('' !== $code) { - $code = "\n".$code.$indent; - } - - if ($serializables) { - $code = $r.'::unserialize(['.$code.'], '.self::export($serializables, $indent).')'; - } else { - $code = '['.$code.']'; - } - - return '$o = '.$code; - } - - private static function exportHydrator(Hydrator $value, string $indent, string $subIndent): string - { - $code = ''; - foreach ($value->properties as $class => $properties) { - $code .= $subIndent.' '.self::export($class).' => '.self::export($properties, $subIndent.' ').",\n"; - } - - $code = [ - self::export($value->registry, $subIndent), - self::export($value->values, $subIndent), - '' !== $code ? "[\n".$code.$subIndent.']' : '[]', - self::export($value->value, $subIndent), - self::export($value->wakeups, $subIndent), - ]; - - return '\\'.\get_class($value)."::hydrate(\n".$subIndent.implode(",\n".$subIndent, $code)."\n".$indent.')'; - } - - /** - * @param \ArrayIterator|\ArrayObject $value - * @param \ArrayIterator|\ArrayObject $proto - */ - private static function getArrayObjectProperties($value, $proto): array - { - $reflector = $value instanceof \ArrayIterator ? 'ArrayIterator' : 'ArrayObject'; - $reflector = Registry::$reflectors[$reflector] ?? Registry::getClassReflector($reflector); - - $properties = [ - $arrayValue = (array) $value, - $reflector->getMethod('getFlags')->invoke($value), - $value instanceof \ArrayObject ? $reflector->getMethod('getIteratorClass')->invoke($value) : 'ArrayIterator', - ]; - - $reflector = $reflector->getMethod('setFlags'); - $reflector->invoke($proto, \ArrayObject::STD_PROP_LIST); - - if ($properties[1] & \ArrayObject::STD_PROP_LIST) { - $reflector->invoke($value, 0); - $properties[0] = (array) $value; - } else { - $reflector->invoke($value, \ArrayObject::STD_PROP_LIST); - $arrayValue = (array) $value; - } - $reflector->invoke($value, $properties[1]); - - if ([[], 0, 'ArrayIterator'] === $properties) { - $properties = []; - } else { - if ('ArrayIterator' === $properties[2]) { - unset($properties[2]); - } - $properties = [$reflector->class => ["\0" => $properties]]; - } - - return [$arrayValue, $properties]; - } -} diff --git a/lib/symfony/var-exporter/Internal/Hydrator.php b/lib/symfony/var-exporter/Internal/Hydrator.php deleted file mode 100644 index 5ed6bdc94..000000000 --- a/lib/symfony/var-exporter/Internal/Hydrator.php +++ /dev/null @@ -1,152 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter\Internal; - -use Symfony\Component\VarExporter\Exception\ClassNotFoundException; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -class Hydrator -{ - public static $hydrators = []; - - public $registry; - public $values; - public $properties; - public $value; - public $wakeups; - - public function __construct(?Registry $registry, ?Values $values, array $properties, $value, array $wakeups) - { - $this->registry = $registry; - $this->values = $values; - $this->properties = $properties; - $this->value = $value; - $this->wakeups = $wakeups; - } - - public static function hydrate($objects, $values, $properties, $value, $wakeups) - { - foreach ($properties as $class => $vars) { - (self::$hydrators[$class] ?? self::getHydrator($class))($vars, $objects); - } - foreach ($wakeups as $k => $v) { - if (\is_array($v)) { - $objects[-$k]->__unserialize($v); - } else { - $objects[$v]->__wakeup(); - } - } - - return $value; - } - - public static function getHydrator($class) - { - switch ($class) { - case 'stdClass': - return self::$hydrators[$class] = static function ($properties, $objects) { - foreach ($properties as $name => $values) { - foreach ($values as $i => $v) { - $objects[$i]->$name = $v; - } - } - }; - - case 'ErrorException': - return self::$hydrators[$class] = (self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'))->bindTo(null, new class() extends \ErrorException { - }); - - case 'TypeError': - return self::$hydrators[$class] = (self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'))->bindTo(null, new class() extends \Error { - }); - - case 'SplObjectStorage': - return self::$hydrators[$class] = static function ($properties, $objects) { - foreach ($properties as $name => $values) { - if ("\0" === $name) { - foreach ($values as $i => $v) { - for ($j = 0; $j < \count($v); ++$j) { - $objects[$i]->attach($v[$j], $v[++$j]); - } - } - continue; - } - foreach ($values as $i => $v) { - $objects[$i]->$name = $v; - } - } - }; - } - - if (!class_exists($class) && !interface_exists($class, false) && !trait_exists($class, false)) { - throw new ClassNotFoundException($class); - } - $classReflector = new \ReflectionClass($class); - - switch ($class) { - case 'ArrayIterator': - case 'ArrayObject': - $constructor = \Closure::fromCallable([$classReflector->getConstructor(), 'invokeArgs']); - - return self::$hydrators[$class] = static function ($properties, $objects) use ($constructor) { - foreach ($properties as $name => $values) { - if ("\0" !== $name) { - foreach ($values as $i => $v) { - $objects[$i]->$name = $v; - } - } - } - foreach ($properties["\0"] ?? [] as $i => $v) { - $constructor($objects[$i], $v); - } - }; - } - - if (!$classReflector->isInternal()) { - return self::$hydrators[$class] = (self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'))->bindTo(null, $class); - } - - if ($classReflector->name !== $class) { - return self::$hydrators[$classReflector->name] ?? self::getHydrator($classReflector->name); - } - - $propertySetters = []; - foreach ($classReflector->getProperties() as $propertyReflector) { - if (!$propertyReflector->isStatic()) { - $propertyReflector->setAccessible(true); - $propertySetters[$propertyReflector->name] = \Closure::fromCallable([$propertyReflector, 'setValue']); - } - } - - if (!$propertySetters) { - return self::$hydrators[$class] = self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'); - } - - return self::$hydrators[$class] = static function ($properties, $objects) use ($propertySetters) { - foreach ($properties as $name => $values) { - if ($setValue = $propertySetters[$name] ?? null) { - foreach ($values as $i => $v) { - $setValue($objects[$i], $v); - } - continue; - } - foreach ($values as $i => $v) { - $objects[$i]->$name = $v; - } - } - }; - } -} diff --git a/lib/symfony/var-exporter/Internal/Reference.php b/lib/symfony/var-exporter/Internal/Reference.php deleted file mode 100644 index e371c07b8..000000000 --- a/lib/symfony/var-exporter/Internal/Reference.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter\Internal; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -class Reference -{ - public $id; - public $value; - public $count = 0; - - public function __construct(int $id, $value = null) - { - $this->id = $id; - $this->value = $value; - } -} diff --git a/lib/symfony/var-exporter/Internal/Registry.php b/lib/symfony/var-exporter/Internal/Registry.php deleted file mode 100644 index 24b77b9ef..000000000 --- a/lib/symfony/var-exporter/Internal/Registry.php +++ /dev/null @@ -1,146 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter\Internal; - -use Symfony\Component\VarExporter\Exception\ClassNotFoundException; -use Symfony\Component\VarExporter\Exception\NotInstantiableTypeException; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -class Registry -{ - public static $reflectors = []; - public static $prototypes = []; - public static $factories = []; - public static $cloneable = []; - public static $instantiableWithoutConstructor = []; - - public $classes = []; - - public function __construct(array $classes) - { - $this->classes = $classes; - } - - public static function unserialize($objects, $serializables) - { - $unserializeCallback = ini_set('unserialize_callback_func', __CLASS__.'::getClassReflector'); - - try { - foreach ($serializables as $k => $v) { - $objects[$k] = unserialize($v); - } - } finally { - ini_set('unserialize_callback_func', $unserializeCallback); - } - - return $objects; - } - - public static function p($class) - { - self::getClassReflector($class, true, true); - - return self::$prototypes[$class]; - } - - public static function f($class) - { - $reflector = self::$reflectors[$class] ?? self::getClassReflector($class, true, false); - - return self::$factories[$class] = \Closure::fromCallable([$reflector, 'newInstanceWithoutConstructor']); - } - - public static function getClassReflector($class, $instantiableWithoutConstructor = false, $cloneable = null) - { - if (!($isClass = class_exists($class)) && !interface_exists($class, false) && !trait_exists($class, false)) { - throw new ClassNotFoundException($class); - } - $reflector = new \ReflectionClass($class); - - if ($instantiableWithoutConstructor) { - $proto = $reflector->newInstanceWithoutConstructor(); - } elseif (!$isClass || $reflector->isAbstract()) { - throw new NotInstantiableTypeException($class); - } elseif ($reflector->name !== $class) { - $reflector = self::$reflectors[$name = $reflector->name] ?? self::getClassReflector($name, false, $cloneable); - self::$cloneable[$class] = self::$cloneable[$name]; - self::$instantiableWithoutConstructor[$class] = self::$instantiableWithoutConstructor[$name]; - self::$prototypes[$class] = self::$prototypes[$name]; - - return self::$reflectors[$class] = $reflector; - } else { - try { - $proto = $reflector->newInstanceWithoutConstructor(); - $instantiableWithoutConstructor = true; - } catch (\ReflectionException $e) { - $proto = $reflector->implementsInterface('Serializable') && !method_exists($class, '__unserialize') ? 'C:' : 'O:'; - if ('C:' === $proto && !$reflector->getMethod('unserialize')->isInternal()) { - $proto = null; - } else { - try { - $proto = @unserialize($proto.\strlen($class).':"'.$class.'":0:{}'); - } catch (\Exception $e) { - if (__FILE__ !== $e->getFile()) { - throw $e; - } - throw new NotInstantiableTypeException($class, $e); - } - if (false === $proto) { - throw new NotInstantiableTypeException($class); - } - } - } - if (null !== $proto && !$proto instanceof \Throwable && !$proto instanceof \Serializable && !method_exists($class, '__sleep') && (\PHP_VERSION_ID < 70400 || !method_exists($class, '__serialize'))) { - try { - serialize($proto); - } catch (\Exception $e) { - throw new NotInstantiableTypeException($class, $e); - } - } - } - - if (null === $cloneable) { - if (($proto instanceof \Reflector || $proto instanceof \ReflectionGenerator || $proto instanceof \ReflectionType || $proto instanceof \IteratorIterator || $proto instanceof \RecursiveIteratorIterator) && (!$proto instanceof \Serializable && !method_exists($proto, '__wakeup') && (\PHP_VERSION_ID < 70400 || !method_exists($class, '__unserialize')))) { - throw new NotInstantiableTypeException($class); - } - - $cloneable = $reflector->isCloneable() && !$reflector->hasMethod('__clone'); - } - - self::$cloneable[$class] = $cloneable; - self::$instantiableWithoutConstructor[$class] = $instantiableWithoutConstructor; - self::$prototypes[$class] = $proto; - - if ($proto instanceof \Throwable) { - static $setTrace; - - if (null === $setTrace) { - $setTrace = [ - new \ReflectionProperty(\Error::class, 'trace'), - new \ReflectionProperty(\Exception::class, 'trace'), - ]; - $setTrace[0]->setAccessible(true); - $setTrace[1]->setAccessible(true); - $setTrace[0] = \Closure::fromCallable([$setTrace[0], 'setValue']); - $setTrace[1] = \Closure::fromCallable([$setTrace[1], 'setValue']); - } - - $setTrace[$proto instanceof \Exception]($proto, []); - } - - return self::$reflectors[$class] = $reflector; - } -} diff --git a/lib/symfony/var-exporter/Internal/Values.php b/lib/symfony/var-exporter/Internal/Values.php deleted file mode 100644 index 21ae04e68..000000000 --- a/lib/symfony/var-exporter/Internal/Values.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter\Internal; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -class Values -{ - public $values; - - public function __construct(array $values) - { - $this->values = $values; - } -} diff --git a/lib/symfony/var-exporter/LICENSE b/lib/symfony/var-exporter/LICENSE deleted file mode 100644 index 74cdc2dbf..000000000 --- a/lib/symfony/var-exporter/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -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/lib/symfony/var-exporter/README.md b/lib/symfony/var-exporter/README.md deleted file mode 100644 index a34e4c23d..000000000 --- a/lib/symfony/var-exporter/README.md +++ /dev/null @@ -1,38 +0,0 @@ -VarExporter Component -===================== - -The VarExporter component allows exporting any serializable PHP data structure to -plain PHP code. While doing so, it preserves all the semantics associated with -the serialization mechanism of PHP (`__wakeup`, `__sleep`, `Serializable`, -`__serialize`, `__unserialize`). - -It also provides an instantiator that allows creating and populating objects -without calling their constructor nor any other methods. - -The reason to use this component *vs* `serialize()` or -[igbinary](https://github.com/igbinary/igbinary) is performance: thanks to -OPcache, the resulting code is significantly faster and more memory efficient -than using `unserialize()` or `igbinary_unserialize()`. - -Unlike `var_export()`, this works on any serializable PHP value. - -It also provides a few improvements over `var_export()`/`serialize()`: - - * the output is PSR-2 compatible; - * the output can be re-indented without messing up with `\r` or `\n` in the data - * missing classes throw a `ClassNotFoundException` instead of being unserialized to - `PHP_Incomplete_Class` objects; - * references involving `SplObjectStorage`, `ArrayObject` or `ArrayIterator` - instances are preserved; - * `Reflection*`, `IteratorIterator` and `RecursiveIteratorIterator` classes - throw an exception when being serialized (their unserialized version is broken - anyway, see https://bugs.php.net/76737). - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/var_exporter.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/lib/symfony/var-exporter/VarExporter.php b/lib/symfony/var-exporter/VarExporter.php deleted file mode 100644 index 003388e79..000000000 --- a/lib/symfony/var-exporter/VarExporter.php +++ /dev/null @@ -1,115 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter; - -use Symfony\Component\VarExporter\Exception\ExceptionInterface; -use Symfony\Component\VarExporter\Internal\Exporter; -use Symfony\Component\VarExporter\Internal\Hydrator; -use Symfony\Component\VarExporter\Internal\Registry; -use Symfony\Component\VarExporter\Internal\Values; - -/** - * Exports serializable PHP values to PHP code. - * - * VarExporter allows serializing PHP data structures to plain PHP code (like var_export()) - * while preserving all the semantics associated with serialize() (unlike var_export()). - * - * By leveraging OPcache, the generated PHP code is faster than doing the same with unserialize(). - * - * @author Nicolas Grekas <p@tchwork.com> - */ -final class VarExporter -{ - /** - * Exports a serializable PHP value to PHP code. - * - * @param mixed $value The value to export - * @param bool &$isStaticValue Set to true after execution if the provided value is static, false otherwise - * @param bool &$classes Classes found in the value are added to this list as both keys and values - * - * @throws ExceptionInterface When the provided value cannot be serialized - */ - public static function export($value, bool &$isStaticValue = null, array &$foundClasses = []): string - { - $isStaticValue = true; - - if (!\is_object($value) && !(\is_array($value) && $value) && !\is_resource($value) || $value instanceof \UnitEnum) { - return Exporter::export($value); - } - - $objectsPool = new \SplObjectStorage(); - $refsPool = []; - $objectsCount = 0; - - try { - $value = Exporter::prepare([$value], $objectsPool, $refsPool, $objectsCount, $isStaticValue)[0]; - } finally { - $references = []; - foreach ($refsPool as $i => $v) { - if ($v[0]->count) { - $references[1 + $i] = $v[2]; - } - $v[0] = $v[1]; - } - } - - if ($isStaticValue) { - return Exporter::export($value); - } - - $classes = []; - $values = []; - $states = []; - foreach ($objectsPool as $i => $v) { - [, $class, $values[], $wakeup] = $objectsPool[$v]; - $foundClasses[$class] = $classes[] = $class; - - if (0 < $wakeup) { - $states[$wakeup] = $i; - } elseif (0 > $wakeup) { - $states[-$wakeup] = [$i, array_pop($values)]; - $values[] = []; - } - } - ksort($states); - - $wakeups = [null]; - foreach ($states as $k => $v) { - if (\is_array($v)) { - $wakeups[-$v[0]] = $v[1]; - } else { - $wakeups[] = $v; - } - } - - if (null === $wakeups[0]) { - unset($wakeups[0]); - } - - $properties = []; - foreach ($values as $i => $vars) { - foreach ($vars as $class => $values) { - foreach ($values as $name => $v) { - $properties[$class][$name][$i] = $v; - } - } - } - - if ($classes || $references) { - $value = new Hydrator(new Registry($classes), $references ? new Values($references) : null, $properties, $value, $wakeups); - } else { - $isStaticValue = true; - } - - return Exporter::export($value); - } -} diff --git a/lib/symfony/var-exporter/composer.json b/lib/symfony/var-exporter/composer.json deleted file mode 100644 index 29d4901d3..000000000 --- a/lib/symfony/var-exporter/composer.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "symfony/var-exporter", - "type": "library", - "description": "Allows exporting any serializable PHP data structure to plain PHP code", - "keywords": ["export", "serialize", "instantiate", "hydrate", "construct", "clone"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" - }, - "require-dev": { - "symfony/var-dumper": "^4.4.9|^5.0.9|^6.0" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\VarExporter\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/lib/symfony/web-profiler-bundle/CHANGELOG.md b/lib/symfony/web-profiler-bundle/CHANGELOG.md deleted file mode 100644 index f0974a6ed..000000000 --- a/lib/symfony/web-profiler-bundle/CHANGELOG.md +++ /dev/null @@ -1,95 +0,0 @@ -CHANGELOG -========= - -5.4 ---- - - * Add a "preview" tab in mailer profiler for HTML email - -5.2.0 ------ - - * added session usage - -5.0.0 ------ - - * removed the `ExceptionController`, use `ExceptionPanelController` instead - * removed the `TemplateManager::templateExists()` method - -4.4.0 ------ - - * added support for the Mailer component - * added support for the HttpClient component - * added button to clear the ajax request tab - * deprecated the `ExceptionController::templateExists()` method - * deprecated the `TemplateManager::templateExists()` method - * deprecated the `ExceptionController` in favor of `ExceptionPanelController` - * marked all classes of the WebProfilerBundle as internal - * added a section with the stamps of a message after it is dispatched in the Messenger panel - -4.3.0 ------ - - * Replaced the canvas performance graph renderer with an SVG renderer - -4.1.0 ------ - - * added information about orphaned events - * made the toolbar auto-update with info from ajax reponses when they set the - `Symfony-Debug-Toolbar-Replace header` to `1` - -4.0.0 ------ - - * removed the `WebProfilerExtension::dumpValue()` method - * removed the `getTemplates()` method of the `TemplateManager` class in favor of the ``getNames()`` method - * removed the `web_profiler.position` config option and the - `web_profiler.debug_toolbar.position` container parameter - -3.4.0 ------ - - * Deprecated the `web_profiler.position` config option (in 4.0 version the toolbar - will always be displayed at the bottom) and the `web_profiler.debug_toolbar.position` - container parameter. - -3.1.0 ------ - - * added information about redirected and forwarded requests to the profiler - -3.0.0 ------ - - * removed profiler:import and profiler:export commands - -2.8.0 ------ - - * deprecated profiler:import and profiler:export commands - -2.7.0 ------ - - * [BC BREAK] if you are using a DB to store profiles, the table must be dropped - * added the HTTP status code to profiles - -2.3.0 ------ - - * draw retina canvas if devicePixelRatio is bigger than 1 - -2.1.0 ------ - - * deprecated the verbose setting (not relevant anymore) - * [BC BREAK] You must clear old profiles after upgrading to 2.1 (don't forget - to remove the table if you are using a DB) - * added support for the request method - * added a routing panel - * added a timeline panel - * The toolbar position can now be configured via the `position` option (can - be `top` or `bottom`) diff --git a/lib/symfony/web-profiler-bundle/Controller/ExceptionPanelController.php b/lib/symfony/web-profiler-bundle/Controller/ExceptionPanelController.php deleted file mode 100644 index 4941208c8..000000000 --- a/lib/symfony/web-profiler-bundle/Controller/ExceptionPanelController.php +++ /dev/null @@ -1,61 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\WebProfilerBundle\Controller; - -use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -use Symfony\Component\HttpKernel\Profiler\Profiler; - -/** - * Renders the exception panel. - * - * @author Yonel Ceruto <yonelceruto@gmail.com> - * - * @internal - */ -class ExceptionPanelController -{ - private $errorRenderer; - private $profiler; - - public function __construct(HtmlErrorRenderer $errorRenderer, Profiler $profiler = null) - { - $this->errorRenderer = $errorRenderer; - $this->profiler = $profiler; - } - - /** - * Renders the exception panel stacktrace for the given token. - */ - public function body(string $token): Response - { - if (null === $this->profiler) { - throw new NotFoundHttpException('The profiler must be enabled.'); - } - - $exception = $this->profiler->loadProfile($token) - ->getCollector('exception') - ->getException() - ; - - return new Response($this->errorRenderer->getBody($exception), 200, ['Content-Type' => 'text/html']); - } - - /** - * Renders the exception panel stylesheet. - */ - public function stylesheet(): Response - { - return new Response($this->errorRenderer->getStylesheet(), 200, ['Content-Type' => 'text/css']); - } -} diff --git a/lib/symfony/web-profiler-bundle/Controller/ProfilerController.php b/lib/symfony/web-profiler-bundle/Controller/ProfilerController.php deleted file mode 100644 index 2ad7df329..000000000 --- a/lib/symfony/web-profiler-bundle/Controller/ProfilerController.php +++ /dev/null @@ -1,391 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\WebProfilerBundle\Controller; - -use Symfony\Bundle\FullStack; -use Symfony\Bundle\WebProfilerBundle\Csp\ContentSecurityPolicyHandler; -use Symfony\Bundle\WebProfilerBundle\Profiler\TemplateManager; -use Symfony\Component\HttpFoundation\RedirectResponse; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpFoundation\Session\Flash\AutoExpireFlashBag; -use Symfony\Component\HttpKernel\DataCollector\DumpDataCollector; -use Symfony\Component\HttpKernel\DataCollector\ExceptionDataCollector; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -use Symfony\Component\HttpKernel\Profiler\Profiler; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; -use Twig\Environment; - -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @internal - */ -class ProfilerController -{ - private $templateManager; - private $generator; - private $profiler; - private $twig; - private $templates; - private $cspHandler; - private $baseDir; - - public function __construct(UrlGeneratorInterface $generator, Profiler $profiler = null, Environment $twig, array $templates, ContentSecurityPolicyHandler $cspHandler = null, string $baseDir = null) - { - $this->generator = $generator; - $this->profiler = $profiler; - $this->twig = $twig; - $this->templates = $templates; - $this->cspHandler = $cspHandler; - $this->baseDir = $baseDir; - } - - /** - * Redirects to the last profiles. - * - * @throws NotFoundHttpException - */ - public function homeAction(): RedirectResponse - { - $this->denyAccessIfProfilerDisabled(); - - return new RedirectResponse($this->generator->generate('_profiler_search_results', ['token' => 'empty', 'limit' => 10]), 302, ['Content-Type' => 'text/html']); - } - - /** - * Renders a profiler panel for the given token. - * - * @throws NotFoundHttpException - */ - public function panelAction(Request $request, string $token): Response - { - $this->denyAccessIfProfilerDisabled(); - - if (null !== $this->cspHandler) { - $this->cspHandler->disableCsp(); - } - - $panel = $request->query->get('panel'); - $page = $request->query->get('page', 'home'); - - if ('latest' === $token && $latest = current($this->profiler->find(null, null, 1, null, null, null))) { - $token = $latest['token']; - } - - if (!$profile = $this->profiler->loadProfile($token)) { - return $this->renderWithCspNonces($request, '@WebProfiler/Profiler/info.html.twig', ['about' => 'no_token', 'token' => $token, 'request' => $request]); - } - - if (null === $panel) { - $panel = 'request'; - - foreach ($profile->getCollectors() as $collector) { - if ($collector instanceof ExceptionDataCollector && $collector->hasException()) { - $panel = $collector->getName(); - - break; - } - - if ($collector instanceof DumpDataCollector && $collector->getDumpsCount() > 0) { - $panel = $collector->getName(); - } - } - } - - if (!$profile->hasCollector($panel)) { - throw new NotFoundHttpException(sprintf('Panel "%s" is not available for token "%s".', $panel, $token)); - } - - return $this->renderWithCspNonces($request, $this->getTemplateManager()->getName($profile, $panel), [ - 'token' => $token, - 'profile' => $profile, - 'collector' => $profile->getCollector($panel), - 'panel' => $panel, - 'page' => $page, - 'request' => $request, - 'templates' => $this->getTemplateManager()->getNames($profile), - 'is_ajax' => $request->isXmlHttpRequest(), - 'profiler_markup_version' => 2, // 1 = original profiler, 2 = Symfony 2.8+ profiler - ]); - } - - /** - * Renders the Web Debug Toolbar. - * - * @throws NotFoundHttpException - */ - public function toolbarAction(Request $request, string $token = null): Response - { - if (null === $this->profiler) { - throw new NotFoundHttpException('The profiler must be enabled.'); - } - - if ($request->hasSession() && ($session = $request->getSession())->isStarted() && $session->getFlashBag() instanceof AutoExpireFlashBag) { - // keep current flashes for one more request if using AutoExpireFlashBag - $session->getFlashBag()->setAll($session->getFlashBag()->peekAll()); - } - - if ('empty' === $token || null === $token) { - return new Response('', 200, ['Content-Type' => 'text/html']); - } - - $this->profiler->disable(); - - if (!$profile = $this->profiler->loadProfile($token)) { - return new Response('', 404, ['Content-Type' => 'text/html']); - } - - $url = null; - try { - $url = $this->generator->generate('_profiler', ['token' => $token], UrlGeneratorInterface::ABSOLUTE_URL); - } catch (\Exception $e) { - // the profiler is not enabled - } - - return $this->renderWithCspNonces($request, '@WebProfiler/Profiler/toolbar.html.twig', [ - 'full_stack' => class_exists(FullStack::class), - 'request' => $request, - 'profile' => $profile, - 'templates' => $this->getTemplateManager()->getNames($profile), - 'profiler_url' => $url, - 'token' => $token, - 'profiler_markup_version' => 2, // 1 = original toolbar, 2 = Symfony 2.8+ toolbar - ]); - } - - /** - * Renders the profiler search bar. - * - * @throws NotFoundHttpException - */ - public function searchBarAction(Request $request): Response - { - $this->denyAccessIfProfilerDisabled(); - - if (null !== $this->cspHandler) { - $this->cspHandler->disableCsp(); - } - - if (!$request->hasSession()) { - $ip = - $method = - $statusCode = - $url = - $start = - $end = - $limit = - $token = null; - } else { - $session = $request->getSession(); - - $ip = $request->query->get('ip', $session->get('_profiler_search_ip')); - $method = $request->query->get('method', $session->get('_profiler_search_method')); - $statusCode = $request->query->get('status_code', $session->get('_profiler_search_status_code')); - $url = $request->query->get('url', $session->get('_profiler_search_url')); - $start = $request->query->get('start', $session->get('_profiler_search_start')); - $end = $request->query->get('end', $session->get('_profiler_search_end')); - $limit = $request->query->get('limit', $session->get('_profiler_search_limit')); - $token = $request->query->get('token', $session->get('_profiler_search_token')); - } - - return new Response( - $this->twig->render('@WebProfiler/Profiler/search.html.twig', [ - 'token' => $token, - 'ip' => $ip, - 'method' => $method, - 'status_code' => $statusCode, - 'url' => $url, - 'start' => $start, - 'end' => $end, - 'limit' => $limit, - 'request' => $request, - ]), - 200, - ['Content-Type' => 'text/html'] - ); - } - - /** - * Renders the search results. - * - * @throws NotFoundHttpException - */ - public function searchResultsAction(Request $request, string $token): Response - { - $this->denyAccessIfProfilerDisabled(); - - if (null !== $this->cspHandler) { - $this->cspHandler->disableCsp(); - } - - $profile = $this->profiler->loadProfile($token); - - $ip = $request->query->get('ip'); - $method = $request->query->get('method'); - $statusCode = $request->query->get('status_code'); - $url = $request->query->get('url'); - $start = $request->query->get('start', null); - $end = $request->query->get('end', null); - $limit = $request->query->get('limit'); - - return $this->renderWithCspNonces($request, '@WebProfiler/Profiler/results.html.twig', [ - 'request' => $request, - 'token' => $token, - 'profile' => $profile, - 'tokens' => $this->profiler->find($ip, $url, $limit, $method, $start, $end, $statusCode), - 'ip' => $ip, - 'method' => $method, - 'status_code' => $statusCode, - 'url' => $url, - 'start' => $start, - 'end' => $end, - 'limit' => $limit, - 'panel' => null, - ]); - } - - /** - * Narrows the search bar. - * - * @throws NotFoundHttpException - */ - public function searchAction(Request $request): Response - { - $this->denyAccessIfProfilerDisabled(); - - $ip = $request->query->get('ip'); - $method = $request->query->get('method'); - $statusCode = $request->query->get('status_code'); - $url = $request->query->get('url'); - $start = $request->query->get('start', null); - $end = $request->query->get('end', null); - $limit = $request->query->get('limit'); - $token = $request->query->get('token'); - - if ($request->hasSession()) { - $session = $request->getSession(); - - $session->set('_profiler_search_ip', $ip); - $session->set('_profiler_search_method', $method); - $session->set('_profiler_search_status_code', $statusCode); - $session->set('_profiler_search_url', $url); - $session->set('_profiler_search_start', $start); - $session->set('_profiler_search_end', $end); - $session->set('_profiler_search_limit', $limit); - $session->set('_profiler_search_token', $token); - } - - if (!empty($token)) { - return new RedirectResponse($this->generator->generate('_profiler', ['token' => $token]), 302, ['Content-Type' => 'text/html']); - } - - $tokens = $this->profiler->find($ip, $url, $limit, $method, $start, $end, $statusCode); - - return new RedirectResponse($this->generator->generate('_profiler_search_results', [ - 'token' => $tokens ? $tokens[0]['token'] : 'empty', - 'ip' => $ip, - 'method' => $method, - 'status_code' => $statusCode, - 'url' => $url, - 'start' => $start, - 'end' => $end, - 'limit' => $limit, - ]), 302, ['Content-Type' => 'text/html']); - } - - /** - * Displays the PHP info. - * - * @throws NotFoundHttpException - */ - public function phpinfoAction(): Response - { - $this->denyAccessIfProfilerDisabled(); - - if (null !== $this->cspHandler) { - $this->cspHandler->disableCsp(); - } - - ob_start(); - phpinfo(); - $phpinfo = ob_get_clean(); - - return new Response($phpinfo, 200, ['Content-Type' => 'text/html']); - } - - /** - * Displays the source of a file. - * - * @throws NotFoundHttpException - */ - public function openAction(Request $request): Response - { - if (null === $this->baseDir) { - throw new NotFoundHttpException('The base dir should be set.'); - } - - if ($this->profiler) { - $this->profiler->disable(); - } - - $file = $request->query->get('file'); - $line = $request->query->get('line'); - - $filename = $this->baseDir.\DIRECTORY_SEPARATOR.$file; - - if (preg_match("'(^|[/\\\\])\.'", $file) || !is_readable($filename)) { - throw new NotFoundHttpException(sprintf('The file "%s" cannot be opened.', $file)); - } - - return $this->renderWithCspNonces($request, '@WebProfiler/Profiler/open.html.twig', [ - 'filename' => $filename, - 'file' => $file, - 'line' => $line, - ]); - } - - /** - * Gets the Template Manager. - */ - protected function getTemplateManager(): TemplateManager - { - if (null === $this->templateManager) { - $this->templateManager = new TemplateManager($this->profiler, $this->twig, $this->templates); - } - - return $this->templateManager; - } - - private function denyAccessIfProfilerDisabled() - { - if (null === $this->profiler) { - throw new NotFoundHttpException('The profiler must be enabled.'); - } - - $this->profiler->disable(); - } - - private function renderWithCspNonces(Request $request, string $template, array $variables, int $code = 200, array $headers = ['Content-Type' => 'text/html']): Response - { - $response = new Response('', $code, $headers); - - $nonces = $this->cspHandler ? $this->cspHandler->getNonces($request, $response) : []; - - $variables['csp_script_nonce'] = $nonces['csp_script_nonce'] ?? null; - $variables['csp_style_nonce'] = $nonces['csp_style_nonce'] ?? null; - - $response->setContent($this->twig->render($template, $variables)); - - return $response; - } -} diff --git a/lib/symfony/web-profiler-bundle/Controller/RouterController.php b/lib/symfony/web-profiler-bundle/Controller/RouterController.php deleted file mode 100644 index 50560e0b3..000000000 --- a/lib/symfony/web-profiler-bundle/Controller/RouterController.php +++ /dev/null @@ -1,104 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\WebProfilerBundle\Controller; - -use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\DataCollector\RequestDataCollector; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -use Symfony\Component\HttpKernel\Profiler\Profiler; -use Symfony\Component\Routing\Matcher\TraceableUrlMatcher; -use Symfony\Component\Routing\Matcher\UrlMatcherInterface; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\RouterInterface; -use Twig\Environment; - -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @internal - */ -class RouterController -{ - private $profiler; - private $twig; - private $matcher; - private $routes; - - /** - * @var ExpressionFunctionProviderInterface[] - */ - private $expressionLanguageProviders = []; - - public function __construct(Profiler $profiler = null, Environment $twig, UrlMatcherInterface $matcher = null, RouteCollection $routes = null, iterable $expressionLanguageProviders = []) - { - $this->profiler = $profiler; - $this->twig = $twig; - $this->matcher = $matcher; - $this->routes = (null === $routes && $matcher instanceof RouterInterface) ? $matcher->getRouteCollection() : $routes; - $this->expressionLanguageProviders = $expressionLanguageProviders; - } - - /** - * Renders the profiler panel for the given token. - * - * @throws NotFoundHttpException - */ - public function panelAction(string $token): Response - { - if (null === $this->profiler) { - throw new NotFoundHttpException('The profiler must be enabled.'); - } - - $this->profiler->disable(); - - if (null === $this->matcher || null === $this->routes) { - return new Response('The Router is not enabled.', 200, ['Content-Type' => 'text/html']); - } - - $profile = $this->profiler->loadProfile($token); - - /** @var RequestDataCollector $request */ - $request = $profile->getCollector('request'); - - return new Response($this->twig->render('@WebProfiler/Router/panel.html.twig', [ - 'request' => $request, - 'router' => $profile->getCollector('router'), - 'traces' => $this->getTraces($request, $profile->getMethod()), - ]), 200, ['Content-Type' => 'text/html']); - } - - /** - * Returns the routing traces associated to the given request. - */ - private function getTraces(RequestDataCollector $request, string $method): array - { - $traceRequest = Request::create( - $request->getPathInfo(), - $request->getRequestServer(true)->get('REQUEST_METHOD'), - \in_array($request->getMethod(), ['DELETE', 'PATCH', 'POST', 'PUT'], true) ? $request->getRequestRequest()->all() : $request->getRequestQuery()->all(), - $request->getRequestCookies(true)->all(), - [], - $request->getRequestServer(true)->all() - ); - - $context = $this->matcher->getContext(); - $context->setMethod($method); - $matcher = new TraceableUrlMatcher($this->routes, $context); - foreach ($this->expressionLanguageProviders as $provider) { - $matcher->addExpressionLanguageProvider($provider); - } - - return $matcher->getTracesForRequest($traceRequest); - } -} diff --git a/lib/symfony/web-profiler-bundle/Csp/ContentSecurityPolicyHandler.php b/lib/symfony/web-profiler-bundle/Csp/ContentSecurityPolicyHandler.php deleted file mode 100644 index ce2413692..000000000 --- a/lib/symfony/web-profiler-bundle/Csp/ContentSecurityPolicyHandler.php +++ /dev/null @@ -1,270 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\WebProfilerBundle\Csp; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -/** - * Handles Content-Security-Policy HTTP header for the WebProfiler Bundle. - * - * @author Romain Neutron <imprec@gmail.com> - * - * @internal - */ -class ContentSecurityPolicyHandler -{ - private $nonceGenerator; - private $cspDisabled = false; - - public function __construct(NonceGenerator $nonceGenerator) - { - $this->nonceGenerator = $nonceGenerator; - } - - /** - * Returns an array of nonces to be used in Twig templates and Content-Security-Policy headers. - * - * Nonce can be provided by; - * - The request - In case HTML content is fetched via AJAX and inserted in DOM, it must use the same nonce as origin - * - The response - A call to getNonces() has already been done previously. Same nonce are returned - * - They are otherwise randomly generated - */ - public function getNonces(Request $request, Response $response): array - { - if ($request->headers->has('X-SymfonyProfiler-Script-Nonce') && $request->headers->has('X-SymfonyProfiler-Style-Nonce')) { - return [ - 'csp_script_nonce' => $request->headers->get('X-SymfonyProfiler-Script-Nonce'), - 'csp_style_nonce' => $request->headers->get('X-SymfonyProfiler-Style-Nonce'), - ]; - } - - if ($response->headers->has('X-SymfonyProfiler-Script-Nonce') && $response->headers->has('X-SymfonyProfiler-Style-Nonce')) { - return [ - 'csp_script_nonce' => $response->headers->get('X-SymfonyProfiler-Script-Nonce'), - 'csp_style_nonce' => $response->headers->get('X-SymfonyProfiler-Style-Nonce'), - ]; - } - - $nonces = [ - 'csp_script_nonce' => $this->generateNonce(), - 'csp_style_nonce' => $this->generateNonce(), - ]; - - $response->headers->set('X-SymfonyProfiler-Script-Nonce', $nonces['csp_script_nonce']); - $response->headers->set('X-SymfonyProfiler-Style-Nonce', $nonces['csp_style_nonce']); - - return $nonces; - } - - /** - * Disables Content-Security-Policy. - * - * All related headers will be removed. - */ - public function disableCsp() - { - $this->cspDisabled = true; - } - - /** - * Cleanup temporary headers and updates Content-Security-Policy headers. - * - * @return array Nonces used by the bundle in Content-Security-Policy header - */ - public function updateResponseHeaders(Request $request, Response $response): array - { - if ($this->cspDisabled) { - $this->removeCspHeaders($response); - - return []; - } - - $nonces = $this->getNonces($request, $response); - $this->cleanHeaders($response); - $this->updateCspHeaders($response, $nonces); - - return $nonces; - } - - private function cleanHeaders(Response $response) - { - $response->headers->remove('X-SymfonyProfiler-Script-Nonce'); - $response->headers->remove('X-SymfonyProfiler-Style-Nonce'); - } - - private function removeCspHeaders(Response $response) - { - $response->headers->remove('X-Content-Security-Policy'); - $response->headers->remove('Content-Security-Policy'); - $response->headers->remove('Content-Security-Policy-Report-Only'); - } - - /** - * Updates Content-Security-Policy headers in a response. - */ - private function updateCspHeaders(Response $response, array $nonces = []): array - { - $nonces = array_replace([ - 'csp_script_nonce' => $this->generateNonce(), - 'csp_style_nonce' => $this->generateNonce(), - ], $nonces); - - $ruleIsSet = false; - - $headers = $this->getCspHeaders($response); - - $types = [ - 'script-src' => 'csp_script_nonce', - 'script-src-elem' => 'csp_script_nonce', - 'style-src' => 'csp_style_nonce', - 'style-src-elem' => 'csp_style_nonce', - ]; - - foreach ($headers as $header => $directives) { - foreach ($types as $type => $tokenName) { - if ($this->authorizesInline($directives, $type)) { - continue; - } - if (!isset($headers[$header][$type])) { - if (null === $fallback = $this->getDirectiveFallback($directives, $type)) { - continue; - } - - if (['\'none\''] === $fallback) { - // Fallback came from "default-src: 'none'" - // 'none' is invalid if it's not the only expression in the source list, so we leave it out - $fallback = []; - } - - $headers[$header][$type] = $fallback; - } - $ruleIsSet = true; - if (!\in_array('\'unsafe-inline\'', $headers[$header][$type], true)) { - $headers[$header][$type][] = '\'unsafe-inline\''; - } - $headers[$header][$type][] = sprintf('\'nonce-%s\'', $nonces[$tokenName]); - } - } - - if (!$ruleIsSet) { - return $nonces; - } - - foreach ($headers as $header => $directives) { - $response->headers->set($header, $this->generateCspHeader($directives)); - } - - return $nonces; - } - - /** - * Generates a valid Content-Security-Policy nonce. - */ - private function generateNonce(): string - { - return $this->nonceGenerator->generate(); - } - - /** - * Converts a directive set array into Content-Security-Policy header. - */ - private function generateCspHeader(array $directives): string - { - return array_reduce(array_keys($directives), function ($res, $name) use ($directives) { - return ('' !== $res ? $res.'; ' : '').sprintf('%s %s', $name, implode(' ', $directives[$name])); - }, ''); - } - - /** - * Converts a Content-Security-Policy header value into a directive set array. - */ - private function parseDirectives(string $header): array - { - $directives = []; - - foreach (explode(';', $header) as $directive) { - $parts = explode(' ', trim($directive)); - if (\count($parts) < 1) { - continue; - } - $name = array_shift($parts); - $directives[$name] = $parts; - } - - return $directives; - } - - /** - * Detects if the 'unsafe-inline' is prevented for a directive within the directive set. - */ - private function authorizesInline(array $directivesSet, string $type): bool - { - if (isset($directivesSet[$type])) { - $directives = $directivesSet[$type]; - } elseif (null === $directives = $this->getDirectiveFallback($directivesSet, $type)) { - return false; - } - - return \in_array('\'unsafe-inline\'', $directives, true) && !$this->hasHashOrNonce($directives); - } - - private function hasHashOrNonce(array $directives): bool - { - foreach ($directives as $directive) { - if (!str_ends_with($directive, '\'')) { - continue; - } - if ('\'nonce-' === substr($directive, 0, 7)) { - return true; - } - if (\in_array(substr($directive, 0, 8), ['\'sha256-', '\'sha384-', '\'sha512-'], true)) { - return true; - } - } - - return false; - } - - private function getDirectiveFallback(array $directiveSet, string $type) - { - if (\in_array($type, ['script-src-elem', 'style-src-elem'], true) || !isset($directiveSet['default-src'])) { - // Let the browser fallback on it's own - return null; - } - - return $directiveSet['default-src']; - } - - /** - * Retrieves the Content-Security-Policy headers (either X-Content-Security-Policy or Content-Security-Policy) from - * a response. - */ - private function getCspHeaders(Response $response): array - { - $headers = []; - - if ($response->headers->has('Content-Security-Policy')) { - $headers['Content-Security-Policy'] = $this->parseDirectives($response->headers->get('Content-Security-Policy')); - } - - if ($response->headers->has('Content-Security-Policy-Report-Only')) { - $headers['Content-Security-Policy-Report-Only'] = $this->parseDirectives($response->headers->get('Content-Security-Policy-Report-Only')); - } - - if ($response->headers->has('X-Content-Security-Policy')) { - $headers['X-Content-Security-Policy'] = $this->parseDirectives($response->headers->get('X-Content-Security-Policy')); - } - - return $headers; - } -} diff --git a/lib/symfony/web-profiler-bundle/Csp/NonceGenerator.php b/lib/symfony/web-profiler-bundle/Csp/NonceGenerator.php deleted file mode 100644 index 19af84969..000000000 --- a/lib/symfony/web-profiler-bundle/Csp/NonceGenerator.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\WebProfilerBundle\Csp; - -/** - * Generates Content-Security-Policy nonce. - * - * @author Romain Neutron <imprec@gmail.com> - * - * @internal - */ -class NonceGenerator -{ - public function generate(): string - { - return bin2hex(random_bytes(16)); - } -} diff --git a/lib/symfony/web-profiler-bundle/DependencyInjection/Configuration.php b/lib/symfony/web-profiler-bundle/DependencyInjection/Configuration.php deleted file mode 100644 index 041c3350a..000000000 --- a/lib/symfony/web-profiler-bundle/DependencyInjection/Configuration.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\WebProfilerBundle\DependencyInjection; - -use Symfony\Component\Config\Definition\Builder\TreeBuilder; -use Symfony\Component\Config\Definition\ConfigurationInterface; - -/** - * This class contains the configuration information for the bundle. - * - * This information is solely responsible for how the different configuration - * sections are normalized, and merged. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Configuration implements ConfigurationInterface -{ - /** - * Generates the configuration tree builder. - * - * @return TreeBuilder - */ - public function getConfigTreeBuilder() - { - $treeBuilder = new TreeBuilder('web_profiler'); - - $treeBuilder->getRootNode() - ->children() - ->booleanNode('toolbar')->defaultFalse()->end() - ->booleanNode('intercept_redirects')->defaultFalse()->end() - ->scalarNode('excluded_ajax_paths')->defaultValue('^/((index|app(_[\w]+)?)\.php/)?_wdt')->end() - ->end() - ; - - return $treeBuilder; - } -} diff --git a/lib/symfony/web-profiler-bundle/DependencyInjection/WebProfilerExtension.php b/lib/symfony/web-profiler-bundle/DependencyInjection/WebProfilerExtension.php deleted file mode 100644 index 0bb949c09..000000000 --- a/lib/symfony/web-profiler-bundle/DependencyInjection/WebProfilerExtension.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\WebProfilerBundle\DependencyInjection; - -use Symfony\Bundle\WebProfilerBundle\EventListener\WebDebugToolbarListener; -use Symfony\Component\Config\FileLocator; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Extension\Extension; -use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; -use Symfony\Component\DependencyInjection\Reference; - -/** - * WebProfilerExtension. - * - * Usage: - * - * <webprofiler:config - * toolbar="true" - * intercept-redirects="true" - * /> - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class WebProfilerExtension extends Extension -{ - /** - * Loads the web profiler configuration. - * - * @param array $configs An array of configuration settings - */ - public function load(array $configs, ContainerBuilder $container) - { - $configuration = $this->getConfiguration($configs, $container); - $config = $this->processConfiguration($configuration, $configs); - - $loader = new PhpFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); - $loader->load('profiler.php'); - - if ($config['toolbar'] || $config['intercept_redirects']) { - $loader->load('toolbar.php'); - $container->getDefinition('web_profiler.debug_toolbar')->replaceArgument(4, $config['excluded_ajax_paths']); - $container->setParameter('web_profiler.debug_toolbar.intercept_redirects', $config['intercept_redirects']); - $container->setParameter('web_profiler.debug_toolbar.mode', $config['toolbar'] ? WebDebugToolbarListener::ENABLED : WebDebugToolbarListener::DISABLED); - } - - $container->getDefinition('debug.file_link_formatter') - ->replaceArgument(3, new ServiceClosureArgument(new Reference('debug.file_link_formatter.url_format'))); - } - - /** - * {@inheritdoc} - */ - public function getXsdValidationBasePath() - { - return __DIR__.'/../Resources/config/schema'; - } - - public function getNamespace() - { - return 'http://symfony.com/schema/dic/webprofiler'; - } -} diff --git a/lib/symfony/web-profiler-bundle/EventListener/WebDebugToolbarListener.php b/lib/symfony/web-profiler-bundle/EventListener/WebDebugToolbarListener.php deleted file mode 100644 index b2e7db269..000000000 --- a/lib/symfony/web-profiler-bundle/EventListener/WebDebugToolbarListener.php +++ /dev/null @@ -1,165 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\WebProfilerBundle\EventListener; - -use Symfony\Bundle\FullStack; -use Symfony\Bundle\WebProfilerBundle\Csp\ContentSecurityPolicyHandler; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpFoundation\Session\Flash\AutoExpireFlashBag; -use Symfony\Component\HttpKernel\DataCollector\DumpDataCollector; -use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; -use Twig\Environment; - -/** - * WebDebugToolbarListener injects the Web Debug Toolbar. - * - * The onKernelResponse method must be connected to the kernel.response event. - * - * The WDT is only injected on well-formed HTML (with a proper </body> tag). - * This means that the WDT is never included in sub-requests or ESI requests. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class WebDebugToolbarListener implements EventSubscriberInterface -{ - public const DISABLED = 1; - public const ENABLED = 2; - - protected $twig; - protected $urlGenerator; - protected $interceptRedirects; - protected $mode; - protected $excludedAjaxPaths; - private $cspHandler; - private $dumpDataCollector; - - public function __construct(Environment $twig, bool $interceptRedirects = false, int $mode = self::ENABLED, UrlGeneratorInterface $urlGenerator = null, string $excludedAjaxPaths = '^/bundles|^/_wdt', ContentSecurityPolicyHandler $cspHandler = null, DumpDataCollector $dumpDataCollector = null) - { - $this->twig = $twig; - $this->urlGenerator = $urlGenerator; - $this->interceptRedirects = $interceptRedirects; - $this->mode = $mode; - $this->excludedAjaxPaths = $excludedAjaxPaths; - $this->cspHandler = $cspHandler; - $this->dumpDataCollector = $dumpDataCollector; - } - - public function isEnabled(): bool - { - return self::DISABLED !== $this->mode; - } - - public function setMode(int $mode): void - { - if (self::DISABLED !== $mode && self::ENABLED !== $mode) { - throw new \InvalidArgumentException(sprintf('Invalid value provided for mode, use one of "%s::DISABLED" or "%s::ENABLED".', self::class, self::class)); - } - - $this->mode = $mode; - } - - public function onKernelResponse(ResponseEvent $event) - { - $response = $event->getResponse(); - $request = $event->getRequest(); - - if ($response->headers->has('X-Debug-Token') && null !== $this->urlGenerator) { - try { - $response->headers->set( - 'X-Debug-Token-Link', - $this->urlGenerator->generate('_profiler', ['token' => $response->headers->get('X-Debug-Token')], UrlGeneratorInterface::ABSOLUTE_URL) - ); - } catch (\Exception $e) { - $response->headers->set('X-Debug-Error', \get_class($e).': '.preg_replace('/\s+/', ' ', $e->getMessage())); - } - } - - if (!$event->isMainRequest()) { - return; - } - - $nonces = []; - if ($this->cspHandler) { - if ($this->dumpDataCollector && $this->dumpDataCollector->getDumpsCount() > 0) { - $this->cspHandler->disableCsp(); - } - - $nonces = $this->cspHandler->updateResponseHeaders($request, $response); - } - - // do not capture redirects or modify XML HTTP Requests - if ($request->isXmlHttpRequest()) { - return; - } - - if ($response->headers->has('X-Debug-Token') && $response->isRedirect() && $this->interceptRedirects && 'html' === $request->getRequestFormat()) { - if ($request->hasSession() && ($session = $request->getSession())->isStarted() && $session->getFlashBag() instanceof AutoExpireFlashBag) { - // keep current flashes for one more request if using AutoExpireFlashBag - $session->getFlashBag()->setAll($session->getFlashBag()->peekAll()); - } - - $response->setContent($this->twig->render('@WebProfiler/Profiler/toolbar_redirect.html.twig', ['location' => $response->headers->get('Location')])); - $response->setStatusCode(200); - $response->headers->remove('Location'); - } - - if (self::DISABLED === $this->mode - || !$response->headers->has('X-Debug-Token') - || $response->isRedirection() - || ($response->headers->has('Content-Type') && !str_contains($response->headers->get('Content-Type'), 'html')) - || 'html' !== $request->getRequestFormat() - || false !== stripos($response->headers->get('Content-Disposition', ''), 'attachment;') - ) { - return; - } - - $this->injectToolbar($response, $request, $nonces); - } - - /** - * Injects the web debug toolbar into the given Response. - */ - protected function injectToolbar(Response $response, Request $request, array $nonces) - { - $content = $response->getContent(); - $pos = strripos($content, '</body>'); - - if (false !== $pos) { - $toolbar = "\n".str_replace("\n", '', $this->twig->render( - '@WebProfiler/Profiler/toolbar_js.html.twig', - [ - 'full_stack' => class_exists(FullStack::class), - 'excluded_ajax_paths' => $this->excludedAjaxPaths, - 'token' => $response->headers->get('X-Debug-Token'), - 'request' => $request, - 'csp_script_nonce' => $nonces['csp_script_nonce'] ?? null, - 'csp_style_nonce' => $nonces['csp_style_nonce'] ?? null, - ] - ))."\n"; - $content = substr($content, 0, $pos).$toolbar.substr($content, $pos); - $response->setContent($content); - } - } - - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::RESPONSE => ['onKernelResponse', -128], - ]; - } -} diff --git a/lib/symfony/web-profiler-bundle/LICENSE b/lib/symfony/web-profiler-bundle/LICENSE deleted file mode 100644 index 008370457..000000000 --- a/lib/symfony/web-profiler-bundle/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -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/lib/symfony/web-profiler-bundle/Profiler/TemplateManager.php b/lib/symfony/web-profiler-bundle/Profiler/TemplateManager.php deleted file mode 100644 index f962e69f1..000000000 --- a/lib/symfony/web-profiler-bundle/Profiler/TemplateManager.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\WebProfilerBundle\Profiler; - -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -use Symfony\Component\HttpKernel\Profiler\Profile; -use Symfony\Component\HttpKernel\Profiler\Profiler; -use Twig\Environment; - -/** - * @author Fabien Potencier <fabien@symfony.com> - * @author Artur Wielogórski <wodor@wodor.net> - * - * @internal - */ -class TemplateManager -{ - protected $twig; - protected $templates; - protected $profiler; - - public function __construct(Profiler $profiler, Environment $twig, array $templates) - { - $this->profiler = $profiler; - $this->twig = $twig; - $this->templates = $templates; - } - - /** - * Gets the template name for a given panel. - * - * @return mixed - * - * @throws NotFoundHttpException - */ - public function getName(Profile $profile, string $panel) - { - $templates = $this->getNames($profile); - - if (!isset($templates[$panel])) { - throw new NotFoundHttpException(sprintf('Panel "%s" is not registered in profiler or is not present in viewed profile.', $panel)); - } - - return $templates[$panel]; - } - - /** - * Gets template names of templates that are present in the viewed profile. - * - * @throws \UnexpectedValueException - */ - public function getNames(Profile $profile): array - { - $loader = $this->twig->getLoader(); - $templates = []; - - foreach ($this->templates as $arguments) { - if (null === $arguments) { - continue; - } - - [$name, $template] = $arguments; - - if (!$this->profiler->has($name) || !$profile->hasCollector($name)) { - continue; - } - - if (str_ends_with($template, '.html.twig')) { - $template = substr($template, 0, -10); - } - - if (!$loader->exists($template.'.html.twig')) { - throw new \UnexpectedValueException(sprintf('The profiler template "%s.html.twig" for data collector "%s" does not exist.', $template, $name)); - } - - $templates[$name] = $template.'.html.twig'; - } - - return $templates; - } -} diff --git a/lib/symfony/web-profiler-bundle/README.md b/lib/symfony/web-profiler-bundle/README.md deleted file mode 100644 index e3c1400b1..000000000 --- a/lib/symfony/web-profiler-bundle/README.md +++ /dev/null @@ -1,16 +0,0 @@ -WebProfilerBundle -================= - -WebProfilerBundle provides a **development tool** that gives detailed -information about the execution of any request. - -**Never** enable it on production servers as it will lead to major security -vulnerabilities in your project. - -Resources ---------- - - * [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/lib/symfony/web-profiler-bundle/Resources/ICONS_LICENSE.txt b/lib/symfony/web-profiler-bundle/Resources/ICONS_LICENSE.txt deleted file mode 100644 index 2e2027267..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/ICONS_LICENSE.txt +++ /dev/null @@ -1,5 +0,0 @@ -Icons License -============= - -Icons created by Sensio (http://www.sensio.com/) are shared under a Creative -Commons Attribution license (http://creativecommons.org/licenses/by-sa/3.0/). \ No newline at end of file diff --git a/lib/symfony/web-profiler-bundle/Resources/config/profiler.php b/lib/symfony/web-profiler-bundle/Resources/config/profiler.php deleted file mode 100644 index 85c64f268..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/config/profiler.php +++ /dev/null @@ -1,83 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Bundle\WebProfilerBundle\Controller\ExceptionPanelController; -use Symfony\Bundle\WebProfilerBundle\Controller\ProfilerController; -use Symfony\Bundle\WebProfilerBundle\Controller\RouterController; -use Symfony\Bundle\WebProfilerBundle\Csp\ContentSecurityPolicyHandler; -use Symfony\Bundle\WebProfilerBundle\Csp\NonceGenerator; -use Symfony\Bundle\WebProfilerBundle\Twig\WebProfilerExtension; -use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; -use Symfony\Component\VarDumper\Dumper\HtmlDumper; - -return static function (ContainerConfigurator $container) { - $container->services() - - ->set('web_profiler.controller.profiler', ProfilerController::class) - ->public() - ->args([ - service('router')->nullOnInvalid(), - service('profiler')->nullOnInvalid(), - service('twig'), - param('data_collector.templates'), - service('web_profiler.csp.handler'), - param('kernel.project_dir'), - ]) - - ->set('web_profiler.controller.router', RouterController::class) - ->public() - ->args([ - service('profiler')->nullOnInvalid(), - service('twig'), - service('router')->nullOnInvalid(), - null, - tagged_iterator('routing.expression_language_provider'), - ]) - - ->set('web_profiler.controller.exception_panel', ExceptionPanelController::class) - ->public() - ->args([ - service('error_handler.error_renderer.html'), - service('profiler')->nullOnInvalid(), - ]) - - ->set('web_profiler.csp.handler', ContentSecurityPolicyHandler::class) - ->args([ - inline_service(NonceGenerator::class), - ]) - - ->set('twig.extension.webprofiler', WebProfilerExtension::class) - ->args([ - inline_service(HtmlDumper::class) - ->args([null, param('kernel.charset'), HtmlDumper::DUMP_LIGHT_ARRAY]) - ->call('setDisplayOptions', [['maxStringLength' => 4096, 'fileLinkFormat' => service('debug.file_link_formatter')]]), - ]) - ->tag('twig.extension') - - ->set('debug.file_link_formatter', FileLinkFormatter::class) - ->args([ - param('debug.file_link_format'), - service('request_stack')->ignoreOnInvalid(), - param('kernel.project_dir'), - '/_profiler/open?file=%%f&line=%%l#line%%l', - ]) - - ->set('debug.file_link_formatter.url_format', 'string') - ->factory([FileLinkFormatter::class, 'generateUrlFormat']) - ->args([ - service('router'), - '_profiler_open_file', - '?file=%%f&line=%%l#line%%l', - ]) - ; -}; diff --git a/lib/symfony/web-profiler-bundle/Resources/config/routing/profiler.xml b/lib/symfony/web-profiler-bundle/Resources/config/routing/profiler.xml deleted file mode 100644 index f20cba0e6..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/config/routing/profiler.xml +++ /dev/null @@ -1,47 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> - -<routes xmlns="http://symfony.com/schema/routing" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd"> - - <route id="_profiler_home" path="/"> - <default key="_controller">web_profiler.controller.profiler::homeAction</default> - </route> - - <route id="_profiler_search" path="/search"> - <default key="_controller">web_profiler.controller.profiler::searchAction</default> - </route> - - <route id="_profiler_search_bar" path="/search_bar"> - <default key="_controller">web_profiler.controller.profiler::searchBarAction</default> - </route> - - <route id="_profiler_phpinfo" path="/phpinfo"> - <default key="_controller">web_profiler.controller.profiler::phpinfoAction</default> - </route> - - <route id="_profiler_search_results" path="/{token}/search/results"> - <default key="_controller">web_profiler.controller.profiler::searchResultsAction</default> - </route> - - <route id="_profiler_open_file" path="/open"> - <default key="_controller">web_profiler.controller.profiler::openAction</default> - </route> - - <route id="_profiler" path="/{token}"> - <default key="_controller">web_profiler.controller.profiler::panelAction</default> - </route> - - <route id="_profiler_router" path="/{token}/router"> - <default key="_controller">web_profiler.controller.router::panelAction</default> - </route> - - <route id="_profiler_exception" path="/{token}/exception"> - <default key="_controller">web_profiler.controller.exception_panel::body</default> - </route> - - <route id="_profiler_exception_css" path="/{token}/exception.css"> - <default key="_controller">web_profiler.controller.exception_panel::stylesheet</default> - </route> - -</routes> diff --git a/lib/symfony/web-profiler-bundle/Resources/config/routing/wdt.xml b/lib/symfony/web-profiler-bundle/Resources/config/routing/wdt.xml deleted file mode 100644 index 0f7e960cc..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/config/routing/wdt.xml +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> - -<routes xmlns="http://symfony.com/schema/routing" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd"> - - <route id="_wdt" path="/{token}"> - <default key="_controller">web_profiler.controller.profiler::toolbarAction</default> - </route> -</routes> diff --git a/lib/symfony/web-profiler-bundle/Resources/config/schema/webprofiler-1.0.xsd b/lib/symfony/web-profiler-bundle/Resources/config/schema/webprofiler-1.0.xsd deleted file mode 100644 index e22105a17..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/config/schema/webprofiler-1.0.xsd +++ /dev/null @@ -1,14 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> - -<xsd:schema xmlns="http://symfony.com/schema/dic/webprofiler" - xmlns:xsd="http://www.w3.org/2001/XMLSchema" - targetNamespace="http://symfony.com/schema/dic/webprofiler" - elementFormDefault="qualified"> - - <xsd:element name="config" type="config" /> - - <xsd:complexType name="config"> - <xsd:attribute name="toolbar" type="xsd:boolean" /> - <xsd:attribute name="intercept-redirects" type="xsd:boolean" /> - </xsd:complexType> -</xsd:schema> diff --git a/lib/symfony/web-profiler-bundle/Resources/config/toolbar.php b/lib/symfony/web-profiler-bundle/Resources/config/toolbar.php deleted file mode 100644 index 473b3630f..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/config/toolbar.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Bundle\WebProfilerBundle\EventListener\WebDebugToolbarListener; - -return static function (ContainerConfigurator $container) { - $container->services() - - ->set('web_profiler.debug_toolbar', WebDebugToolbarListener::class) - ->args([ - service('twig'), - param('web_profiler.debug_toolbar.intercept_redirects'), - param('web_profiler.debug_toolbar.mode'), - service('router')->ignoreOnInvalid(), - abstract_arg('paths that should be excluded from the AJAX requests shown in the toolbar'), - service('web_profiler.csp.handler'), - service('data_collector.dump')->ignoreOnInvalid(), - ]) - ->tag('kernel.event_subscriber') - ; -}; diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Collector/ajax.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Collector/ajax.html.twig deleted file mode 100644 index e4e7d6418..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Collector/ajax.html.twig +++ /dev/null @@ -1,35 +0,0 @@ -{% extends '@WebProfiler/Profiler/layout.html.twig' %} - -{% block toolbar %} - {% set icon %} - {{ include('@WebProfiler/Icon/ajax.svg') }} - <span class="sf-toolbar-value sf-toolbar-ajax-request-counter">0</span> - {% endset %} - - {% set text %} - <div class="sf-toolbar-info-piece"> - <span class="sf-toolbar-header"> - <b class="sf-toolbar-ajax-info"></b> - <b class="sf-toolbar-action">(<a class="sf-toolbar-ajax-clear" href="javascript:void(0);">Clear</a>)</b> - </span> - </div> - <div class="sf-toolbar-info-piece"> - <table class="sf-toolbar-ajax-requests"> - <thead> - <tr> - <th>#</th> - <th>Profile</th> - <th>Method</th> - <th>Type</th> - <th>Status</th> - <th>URL</th> - <th>Time</th> - </tr> - </thead> - <tbody class="sf-toolbar-ajax-request-list"></tbody> - </table> - </div> - {% endset %} - - {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: false }) }} -{% endblock %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Collector/cache.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Collector/cache.html.twig deleted file mode 100644 index 0c406e944..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Collector/cache.html.twig +++ /dev/null @@ -1,153 +0,0 @@ -{% extends '@WebProfiler/Profiler/layout.html.twig' %} - -{% block toolbar %} - {% if collector.totals.calls > 0 %} - {% set icon %} - {{ include('@WebProfiler/Icon/cache.svg') }} - <span class="sf-toolbar-value">{{ collector.totals.calls }}</span> - <span class="sf-toolbar-info-piece-additional-detail"> - <span class="sf-toolbar-label">in</span> - <span class="sf-toolbar-value">{{ '%0.2f'|format(collector.totals.time * 1000) }}</span> - <span class="sf-toolbar-label">ms</span> - </span> - {% endset %} - {% set text %} - <div class="sf-toolbar-info-piece"> - <b>Cache Calls</b> - <span>{{ collector.totals.calls }}</span> - </div> - <div class="sf-toolbar-info-piece"> - <b>Total time</b> - <span>{{ '%0.2f'|format(collector.totals.time * 1000) }} ms</span> - </div> - <div class="sf-toolbar-info-piece"> - <b>Cache hits</b> - <span>{{ collector.totals.hits }} / {{ collector.totals.reads }}{% if collector.totals.hit_read_ratio is not null %} ({{ collector.totals.hit_read_ratio }}%){% endif %}</span> - </div> - <div class="sf-toolbar-info-piece"> - <b>Cache writes</b> - <span>{{ collector.totals.writes }}</span> - </div> - {% endset %} - - {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url }) }} - {% endif %} -{% endblock %} - -{% block menu %} - <span class="label {{ collector.totals.calls == 0 ? 'disabled' }}"> - <span class="icon"> - {{ include('@WebProfiler/Icon/cache.svg') }} - </span> - <strong>Cache</strong> -</span> -{% endblock %} - -{% block panel %} - <h2>Cache</h2> - - {% if collector.totals.calls == 0 %} - <div class="empty"> - <p>No cache calls were made.</p> - </div> - {% else %} - <div class="metrics"> - <div class="metric"> - <span class="value">{{ collector.totals.calls }}</span> - <span class="label">Total calls</span> - </div> - <div class="metric"> - <span class="value">{{ '%0.2f'|format(collector.totals.time * 1000) }} <span class="unit">ms</span></span> - <span class="label">Total time</span> - </div> - <div class="metric-divider"></div> - <div class="metric"> - <span class="value">{{ collector.totals.reads }}</span> - <span class="label">Total reads</span> - </div> - <div class="metric"> - <span class="value">{{ collector.totals.writes }}</span> - <span class="label">Total writes</span> - </div> - <div class="metric"> - <span class="value">{{ collector.totals.deletes }}</span> - <span class="label">Total deletes</span> - </div> - <div class="metric-divider"></div> - <div class="metric"> - <span class="value">{{ collector.totals.hits }}</span> - <span class="label">Total hits</span> - </div> - <div class="metric"> - <span class="value">{{ collector.totals.misses }}</span> - <span class="label">Total misses</span> - </div> - <div class="metric"> - <span class="value"> - {{ collector.totals.hit_read_ratio ?? 0 }} <span class="unit">%</span> - </span> - <span class="label">Hits/reads</span> - </div> - </div> - - <h2>Pools</h2> - <div class="sf-tabs"> - {% for name, calls in collector.calls %} - <div class="tab {{ calls|length == 0 ? 'disabled' }}"> - <h3 class="tab-title">{{ name }} <span class="badge">{{ collector.statistics[name].calls }}</span></h3> - - <div class="tab-content"> - {% if calls|length == 0 %} - <div class="empty"> - <p>No calls were made for {{ name }} pool.</p> - </div> - {% else %} - <h4>Metrics</h4> - <div class="metrics"> - {% for key, value in collector.statistics[name] %} - <div class="metric"> - <span class="value"> - {% if key == 'time' %} - {{ '%0.2f'|format(1000 * value) }} <span class="unit">ms</span> - {% elseif key == 'hit_read_ratio' %} - {{ value ?? 0 }} <span class="unit">%</span> - {% else %} - {{ value }} - {% endif %} - </span> - <span class="label">{{ key == 'hit_read_ratio' ? 'Hits/reads' : key|capitalize }}</span> - </div> - {% if key == 'time' or key == 'deletes' %} - <div class="metric-divider"></div> - {% endif %} - {% endfor %} - </div> - - <h4>Calls</h4> - <table> - <thead> - <tr> - <th>#</th> - <th>Time</th> - <th>Call</th> - <th>Hit</th> - </tr> - </thead> - <tbody> - {% for call in calls %} - <tr> - <td class="font-normal text-small text-muted nowrap">{{ loop.index }}</td> - <td class="nowrap">{{ '%0.2f'|format((call.end - call.start) * 1000) }} ms</td> - <td class="nowrap">{{ call.name }}()</td> - <td>{{ profiler_dump(call.value.result, maxDepth=2) }}</td> - </tr> - {% endfor %} - </tbody> - </table> - {% endif %} - </div> - </div> - {% endfor %} - </div> - {% endif %} -{% endblock %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Collector/config.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Collector/config.html.twig deleted file mode 100644 index 6dfd27bcb..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Collector/config.html.twig +++ /dev/null @@ -1,226 +0,0 @@ -{% extends '@WebProfiler/Profiler/layout.html.twig' %} - -{% block toolbar %} - {% if 'unknown' == collector.symfonyState %} - {% set block_status = '' %} - {% set symfony_version_status = 'Unable to retrieve information about the Symfony version.' %} - {% elseif 'eol' == collector.symfonyState %} - {% set block_status = 'red' %} - {% set symfony_version_status = 'This Symfony version will no longer receive security fixes.' %} - {% elseif 'eom' == collector.symfonyState %} - {% set block_status = 'yellow' %} - {% set symfony_version_status = 'This Symfony version will only receive security fixes.' %} - {% elseif 'dev' == collector.symfonyState %} - {% set block_status = 'yellow' %} - {% set symfony_version_status = 'This Symfony version is still in the development phase.' %} - {% else %} - {% set block_status = '' %} - {% set symfony_version_status = '' %} - {% endif %} - - {% set icon %} - <span class="sf-toolbar-label"> - {{ include('@WebProfiler/Icon/symfony.svg') }} - </span> - <span class="sf-toolbar-value">{{ collector.symfonyState is defined ? collector.symfonyversion : 'n/a' }}</span> - {% endset %} - - {% set text %} - <div class="sf-toolbar-info-group"> - <div class="sf-toolbar-info-piece"> - <b>Profiler token</b> - <span> - {% if profiler_url %} - <a href="{{ profiler_url }}">{{ collector.token }}</a> - {% else %} - {{ collector.token }} - {% endif %} - </span> - </div> - - {% if 'n/a' is not same as(collector.env) %} - <div class="sf-toolbar-info-piece"> - <b>Environment</b> - <span>{{ collector.env }}</span> - </div> - {% endif %} - - {% if 'n/a' is not same as(collector.debug) %} - <div class="sf-toolbar-info-piece"> - <b>Debug</b> - <span class="sf-toolbar-status sf-toolbar-status-{{ collector.debug ? 'green' : 'red' }}">{{ collector.debug ? 'enabled' : 'disabled' }}</span> - </div> - {% endif %} - </div> - - <div class="sf-toolbar-info-group"> - <div class="sf-toolbar-info-piece sf-toolbar-info-php"> - <b>PHP version</b> - <span{% if collector.phpversionextra %} title="{{ collector.phpversion ~ collector.phpversionextra }}"{% endif %}> - {{ collector.phpversion }} - &nbsp; <a href="{{ path('_profiler_phpinfo') }}">View phpinfo()</a> - </span> - </div> - - <div class="sf-toolbar-info-piece sf-toolbar-info-php-ext"> - <b>PHP Extensions</b> - <span class="sf-toolbar-status sf-toolbar-status-{{ collector.hasxdebug ? 'green' : 'gray' }}">xdebug {{ collector.hasxdebug ? '✓' : '✗' }}</span> - <span class="sf-toolbar-status sf-toolbar-status-{{ collector.hasapcu ? 'green' : 'gray' }}">APCu {{ collector.hasapcu ? '✓' : '✗' }}</span> - <span class="sf-toolbar-status sf-toolbar-status-{{ collector.haszendopcache ? 'green' : 'red' }}">OPcache {{ collector.haszendopcache ? '✓' : '✗' }}</span> - </div> - - <div class="sf-toolbar-info-piece"> - <b>PHP SAPI</b> - <span>{{ collector.sapiName }}</span> - </div> - </div> - - <div class="sf-toolbar-info-group"> - {% if collector.symfonyversion is defined %} - <div class="sf-toolbar-info-piece"> - <b>Resources</b> - <span> - <a href="https://symfony.com/doc/{{ collector.symfonyversion }}/index.html" rel="help"> - Read Symfony {{ collector.symfonyversion }} Docs - </a> - </span> - </div> - <div class="sf-toolbar-info-piece"> - <b>Help</b> - <span> - <a href="https://symfony.com/support"> - Symfony Support Channels - </a> - </span> - </div> - {% endif %} - </div> - {% endset %} - - {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: true, name: 'config', status: block_status, additional_classes: 'sf-toolbar-block-right', block_attrs: 'title="' ~ symfony_version_status ~ '"' }) }} -{% endblock %} - -{% block menu %} - <span class="label label-status-{{ collector.symfonyState == 'eol' ? 'red' : collector.symfonyState in ['eom', 'dev'] ? 'yellow' }}"> - <span class="icon">{{ include('@WebProfiler/Icon/config.svg') }}</span> - <strong>Configuration</strong> - </span> -{% endblock %} - -{% block panel %} - <h2>Symfony Configuration</h2> - - <div class="metrics"> - <div class="metric"> - <span class="value">{{ collector.symfonyversion }}</span> - <span class="label">Symfony version</span> - </div> - - {% if 'n/a' is not same as(collector.env) %} - <div class="metric"> - <span class="value">{{ collector.env }}</span> - <span class="label">Environment</span> - </div> - {% endif %} - - {% if 'n/a' is not same as(collector.debug) %} - <div class="metric"> - <span class="value">{{ collector.debug ? 'enabled' : 'disabled' }}</span> - <span class="label">Debug</span> - </div> - {% endif %} - </div> - - {% set symfony_status = { dev: 'Unstable Version', stable: 'Stable Version', eom: 'Maintenance Ended', eol: 'Version Expired' } %} - {% set symfony_status_class = { dev: 'warning', stable: 'success', eom: 'warning', eol: 'error' } %} - <table> - <thead class="small"> - <tr> - <th>Symfony Status</th> - <th>Bugs {{ collector.symfonystate in ['eom', 'eol'] ? 'were' : 'are' }} fixed until</th> - <th>Security issues {{ collector.symfonystate == 'eol' ? 'were' : 'are' }} fixed until</th> - <th></th> - </tr> - </thead> - <tbody> - <tr> - <td class="font-normal"> - <span class="label status-{{ symfony_status_class[collector.symfonystate] }}">{{ symfony_status[collector.symfonystate]|upper }}</span> - {% if collector.symfonylts %} - &nbsp; <span class="label status-success">Long-Term Support</span> - {% endif %} - </td> - <td class="font-normal">{{ collector.symfonyeom }}</td> - <td class="font-normal">{{ collector.symfonyeol }}</td> - <td class="font-normal"> - <a href="https://symfony.com/releases/{{ collector.symfonyminorversion }}#release-checker">View roadmap</a> - </td> - </tr> - </tbody> - </table> - - <h2>PHP Configuration</h2> - - <div class="metrics"> - <div class="metric"> - <span class="value">{{ collector.phpversion }}{% if collector.phpversionextra %} <span class="unit">{{ collector.phpversionextra }}</span>{% endif %}</span> - <span class="label">PHP version</span> - </div> - - <div class="metric"> - <span class="value">{{ collector.phparchitecture }} <span class="unit">bits</span></span> - <span class="label">Architecture</span> - </div> - - <div class="metric"> - <span class="value">{{ collector.phpintllocale }}</span> - <span class="label">Intl locale</span> - </div> - - <div class="metric"> - <span class="value">{{ collector.phptimezone }}</span> - <span class="label">Timezone</span> - </div> - </div> - - <div class="metrics"> - <div class="metric"> - <span class="value">{{ include('@WebProfiler/Icon/' ~ (collector.haszendopcache ? 'yes' : 'no') ~ '.svg') }}</span> - <span class="label">OPcache</span> - </div> - - <div class="metric"> - <span class="value">{{ include('@WebProfiler/Icon/' ~ (collector.hasapcu ? 'yes' : 'no-gray') ~ '.svg') }}</span> - <span class="label">APCu</span> - </div> - - <div class="metric"> - <span class="value">{{ include('@WebProfiler/Icon/' ~ (collector.hasxdebug ? 'yes' : 'no-gray') ~ '.svg') }}</span> - <span class="label">Xdebug</span> - </div> - </div> - - <p> - <a href="{{ path('_profiler_phpinfo') }}">View full PHP configuration</a> - </p> - - {% if collector.bundles %} - <h2>Enabled Bundles <small>({{ collector.bundles|length }})</small></h2> - <table> - <thead> - <tr> - <th class="key">Name</th> - <th>Class</th> - </tr> - </thead> - <tbody> - {% for name in collector.bundles|keys|sort %} - <tr> - <th scope="row" class="font-normal">{{ name }}</th> - <td class="font-normal">{{ profiler_dump(collector.bundles[name]) }}</td> - </tr> - {% endfor %} - </tbody> - </table> - {% endif %} -{% endblock %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Collector/events.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Collector/events.html.twig deleted file mode 100644 index c0be48a37..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Collector/events.html.twig +++ /dev/null @@ -1,119 +0,0 @@ -{% extends '@WebProfiler/Profiler/layout.html.twig' %} - -{% import _self as helper %} - -{% block menu %} -<span class="label"> - <span class="icon">{{ include('@WebProfiler/Icon/event.svg') }}</span> - <strong>Events</strong> -</span> -{% endblock %} - -{% block panel %} - <h2>Event Dispatcher</h2> - - {% if collector.calledlisteners is empty %} - <div class="empty"> - <p>No events have been recorded. Check that debugging is enabled in the kernel.</p> - </div> - {% else %} - <div class="sf-tabs"> - <div class="tab"> - <h3 class="tab-title">Called Listeners <span class="badge">{{ collector.calledlisteners|length }}</span></h3> - - <div class="tab-content"> - {{ helper.render_table(collector.calledlisteners) }} - </div> - </div> - - <div class="tab"> - <h3 class="tab-title">Not Called Listeners <span class="badge">{{ collector.notcalledlisteners|length }}</span></h3> - <div class="tab-content"> - {% if collector.notcalledlisteners is empty %} - <div class="empty"> - <p> - <strong>There are no uncalled listeners</strong>. - </p> - <p> - All listeners were called for this request or an error occurred - when trying to collect uncalled listeners (in which case check the - logs to get more information). - </p> - </div> - {% else %} - {{ helper.render_table(collector.notcalledlisteners) }} - {% endif %} - </div> - </div> - - <div class="tab"> - <h3 class="tab-title">Orphaned Events <span class="badge">{{ collector.orphanedEvents|length }}</span></h3> - <div class="tab-content"> - {% if collector.orphanedEvents is empty %} - <div class="empty"> - <p> - <strong>There are no orphaned events</strong>. - </p> - <p> - All dispatched events were handled or an error occurred - when trying to collect orphaned events (in which case check the - logs to get more information). - </p> - </div> - {% else %} - <table> - <thead> - <tr> - <th>Event</th> - </tr> - </thead> - <tbody> - {% for event in collector.orphanedEvents %} - <tr> - <td class="font-normal">{{ event }}</td> - </tr> - {% endfor %} - </tbody> - </table> - {% endif %} - </div> - </div> - </div> - {% endif %} -{% endblock %} - -{% macro render_table(listeners) %} - <table> - <thead> - <tr> - <th class="text-right">Priority</th> - <th>Listener</th> - </tr> - </thead> - - {% set previous_event = (listeners|first).event %} - {% for listener in listeners %} - {% if loop.first or listener.event != previous_event %} - {% if not loop.first %} - </tbody> - {% endif %} - - <tbody> - <tr> - <th colspan="2" class="colored font-normal">{{ listener.event }}</th> - </tr> - - {% set previous_event = listener.event %} - {% endif %} - - <tr> - <td class="text-right nowrap">{{ listener.priority|default('-') }}</td> - <td class="font-normal">{{ profiler_dump(listener.stub) }}</td> - </tr> - - {% if loop.last %} - </tbody> - {% endif %} - {% endfor %} - </table> -{% endmacro %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Collector/exception.css.twig b/lib/symfony/web-profiler-bundle/Resources/views/Collector/exception.css.twig deleted file mode 100644 index aad7625a2..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Collector/exception.css.twig +++ /dev/null @@ -1,32 +0,0 @@ -.container { - max-width: none; - margin: 0; - padding: 0; -} -.container .container { - padding: 0; -} - -.exception-summary { - background: var(--base-0); - border: var(--border); - box-shadow: 0 0 1px rgba(128, 128, 128, .2); - margin: 1em 0; - padding: 10px; -} -.exception-summary.exception-without-message { - display: none; -} - -.exception-message { - color: var(--color-error); -} - -.exception-metadata, -.exception-illustration { - display: none; -} - -.exception-message-wrapper .container { - min-height: unset; -} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Collector/exception.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Collector/exception.html.twig deleted file mode 100644 index 1fe0f5d47..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Collector/exception.html.twig +++ /dev/null @@ -1,37 +0,0 @@ -{% extends '@WebProfiler/Profiler/layout.html.twig' %} - -{% block head %} - {% if collector.hasexception %} - <style> - {{ render(controller('web_profiler.controller.exception_panel::stylesheet', { token: token })) }} - {{ include('@WebProfiler/Collector/exception.css.twig') }} - </style> - {% endif %} - {{ parent() }} -{% endblock %} - -{% block menu %} - <span class="label {{ collector.hasexception ? 'label-status-error' : 'disabled' }}"> - <span class="icon">{{ include('@WebProfiler/Icon/exception.svg') }}</span> - <strong>Exception</strong> - {% if collector.hasexception %} - <span class="count"> - <span>1</span> - </span> - {% endif %} - </span> -{% endblock %} - -{% block panel %} - <h2>Exceptions</h2> - - {% if not collector.hasexception %} - <div class="empty"> - <p>No exception was thrown and caught during the request.</p> - </div> - {% else %} - <div class="sf-reset"> - {{ render(controller('web_profiler.controller.exception_panel::body', { token: token })) }} - </div> - {% endif %} -{% endblock %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Collector/form.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Collector/form.html.twig deleted file mode 100644 index d99ad4f77..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Collector/form.html.twig +++ /dev/null @@ -1,731 +0,0 @@ -{% extends '@WebProfiler/Profiler/layout.html.twig' %} - -{% from _self import form_tree_entry, form_tree_details %} - -{% block toolbar %} - {% if collector.data.nb_errors > 0 or collector.data.forms|length %} - {% set status_color = collector.data.nb_errors ? 'red' %} - {% set icon %} - {{ include('@WebProfiler/Icon/form.svg') }} - <span class="sf-toolbar-value"> - {{ collector.data.nb_errors ?: collector.data.forms|length }} - </span> - {% endset %} - - {% set text %} - <div class="sf-toolbar-info-piece"> - <b>Number of forms</b> - <span class="sf-toolbar-status">{{ collector.data.forms|length }}</span> - </div> - <div class="sf-toolbar-info-piece"> - <b>Number of errors</b> - <span class="sf-toolbar-status sf-toolbar-status-{{ collector.data.nb_errors > 0 ? 'red' }}">{{ collector.data.nb_errors }}</span> - </div> - {% endset %} - - {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url, status: status_color }) }} - {% endif %} -{% endblock %} - -{% block menu %} - <span class="label label-status-{{ collector.data.nb_errors ? 'error' }} {{ collector.data.forms is empty ? 'disabled' }}"> - <span class="icon">{{ include('@WebProfiler/Icon/form.svg') }}</span> - <strong>Forms</strong> - {% if collector.data.nb_errors > 0 %} - <span class="count"> - <span>{{ collector.data.nb_errors }}</span> - </span> - {% endif %} - </span> -{% endblock %} - -{% block head %} - {{ parent() }} - - <style> - #tree-menu { - float: left; - padding-right: 10px; - width: 230px; - } - #tree-menu ul { - list-style: none; - margin: 0; - padding-left: 0; - } - #tree-menu li { - margin: 0; - padding: 0; - width: 100%; - } - #tree-menu .empty { - border: 0; - padding: 0; - } - #tree-details-container { - border-left: 1px solid #DDD; - margin-left: 250px; - padding-left: 20px; - } - .tree-details { - padding-bottom: 40px; - } - .tree-details h3 { - font-size: 18px; - position: relative; - } - - .toggle-icon { - display: inline-block; - background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAgBAMAAADpp+X/AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QweDgwx4LcKwAAAABVQTFRFAAAA////////////////ZmZm////bvjBwAAAAAV0Uk5TABZwsuCVEUjgAAAAAWJLR0QF+G/pxwAAAE1JREFUGNNjSHMSYGBgUEljSGYAAzMGBwiDhUEBwmBiEIAwGBmwgTQgQGWgA7h2uIFwK+CWwp1BpHvYEqDuATEYkBlY3IOmBq6dCPcAAIT5Eg2IksjQAAAAAElFTkSuQmCC") no-repeat top left #5eb5e0; - } - .closed .toggle-icon, .closed.toggle-icon { - background-position: bottom left; - } - .toggle-icon.empty { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QAZgBmAGYHukptAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QweDhIf6CA40AAAAFRJREFUOMvtk7ENACEMA61vfx767MROWfO+AdGBHlNyTZrYUZRYDBII4NWE1pNdpFarfgLUbpDaBEgBYRiEVjsvDLa1l6O4Z3wkFWN+OfLKdpisOH/TlICzukmUJwAAAABJRU5ErkJggg=="); - } - - .tree .tree-inner { - cursor: pointer; - padding: 5px 7px 5px 22px; - position: relative; - overflow: hidden; - text-overflow: ellipsis; - } - .tree .toggle-button { - /* provide a bigger clickable area than just 10x10px */ - width: 16px; - height: 16px; - margin-left: -18px; - } - .tree .toggle-icon { - width: 10px; - height: 10px; - /* position the icon in the center of the clickable area */ - margin-left: 3px; - margin-top: 3px; - background-size: 10px 20px; - background-color: #AAA; - } - .tree .toggle-icon.empty { - width: 10px; - height: 10px; - position: absolute; - top: 50%; - margin-top: -5px; - margin-left: -15px; - background-size: 10px 10px; - } - .tree ul ul .tree-inner { - padding-left: 37px; - } - .tree ul ul ul .tree-inner { - padding-left: 52px; - } - .tree ul ul ul ul .tree-inner { - padding-left: 67px; - } - .tree ul ul ul ul ul .tree-inner { - padding-left: 82px; - } - .tree .tree-inner:hover { - background: #dfdfdf; - } - .tree .tree-inner:hover span:not(.has-error) { - color: var(--base-0); - } - .tree .tree-inner.active, .tree .tree-inner.active:hover { - background: var(--tree-active-background); - font-weight: bold; - } - .tree .tree-inner.active .toggle-icon, .tree .tree-inner:hover .toggle-icon, .tree .tree-inner.active:hover .toggle-icon { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAgBAMAAADpp+X/AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QweDhEYXWn+sAAAABhQTFRFAAAA39/f39/f39/f39/fZmZm39/f////gc3YPwAAAAV0Uk5TAAtAc6ZeVyCYAAAAAWJLR0QF+G/pxwAAAE1JREFUGNNjSHMSYGBgUEljSGYAAzMGBwiDhUEBwmBiEIAwGBmwgXIgQGWgA7h2uIFwK+CWwp1BpHvYC6DuATEYkBlY3IOmBq6dCPcAADqLE4MnBi/fAAAAAElFTkSuQmCC"); - background-color: #999; - } - .tree .tree-inner.active .toggle-icon.empty, .tree .tree-inner:hover .toggle-icon.empty, .tree .tree-inner.active:hover .toggle-icon.empty { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QweDhoucSey4gAAABVQTFRFAAAA39/f39/f39/f39/fZmZm39/fD5Dx2AAAAAV0Uk5TAAtAc6ZeVyCYAAAAAWJLR0QF+G/pxwAAADJJREFUCNdjSHMSYGBgUEljSGYAAzMGBwiDhUEBwmBiEIAwGBnIA3DtcAPhVsAthTkDAFOfBKW9C1iqAAAAAElFTkSuQmCC"); - } - .tree-details .toggle-icon { - width: 16px; - height: 16px; - /* vertically center the button */ - position: absolute; - top: 50%; - margin-top: -9px; - margin-left: 6px; - } - .badge-error { - float: right; - background: var(--background-error); - color: #FFF; - padding: 1px 4px; - font-size: 10px; - font-weight: bold; - vertical-align: middle; - } - .has-error { - color: var(--color-error); - } - .errors h3 { - color: var(--color-error); - } - .errors th { - background: var(--background-error); - color: #FFF; - } - .errors .toggle-icon { - background-color: var(--background-error); - } - h3 a, h3 a:hover, h3 a:focus { - color: inherit; - text-decoration: inherit; - } - h2 + h3.form-data-type { - margin-top: 0; - } - h3.form-data-type + h3 { - margin-top: 1em; - } - .theme-dark .toggle-icon { - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAgBAMAAADpp+X/AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAVUExURUdwTH+Ag0lNUZiYmGRmbP///zU5P2n9VV4AAAAFdFJOUwCv+yror0g1sQAAAE1JREFUGNNjSFM0YGBgEEpjSGEAAzcGBQiDiUEAwmBkMIAwmBmwgVAgQGWgA7h2uIFwK+CWwp1BpHtYA6DuATEYkBlY3IOmBq6dCPcAAKMtEEs3tfChAAAAAElFTkSuQmCC'); - } - .theme-dark .toggle-icon.empty { - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAASUExURUdwTDI3OzQ5PS4uLjU3PzU5P4keoyIAAAAFdFJOUwBApgtzrnKGEwAAADJJREFUCNdjCFU0YGBgEAplCGEAA1cGBQiDiUEAwmBkMIAwmBnIA3DtcAPhVsAthTkDACsZBBmrTTSxAAAAAElFTkSuQmCC'); - } - .theme-dark .tree .tree-inner.active .toggle-icon, .theme-dark .tree .tree-inner:hover .toggle-icon, .theme-dark .tree .tree-inner.active:hover .toggle-icon { - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAgBAMAAADpp+X/AAAAD1BMVEVHcEx/gIOYmJiZmZn///+IJ2wIAAAAA3RSTlMAryoIUq0uAAAAUElEQVQY02NgYFQ2NjYWYGBgMAYDBgZmCMOAQRjCMGRQhjCMoEqAipAYLkCAykBXA9cONxBuBdxShDOIc4+JM9Q9IIYxMgOLe9DUwLUT4R4AznguG0qfEa0AAAAASUVORK5CYII='); - background-color: transparent; - } - .theme-dark .tree .tree-inner.active .toggle-icon.empty, .theme-dark .tree .tree-inner:hover .toggle-icon.empty, .theme-dark .tree .tree-inner.active:hover .toggle-icon.empty { - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAACVBMVEVHcEwyNzuqqqrd9nIgAAAAAnRSTlMAQABPjKgAAAArSURBVAjXY2BctcqBgWvVqgUMWqtWrWDIWrVqJcMqICCGACsGawMbADIKANflJYEoGMqtAAAAAElFTkSuQmCC'); - background-color: transparent; - } - </style> -{% endblock %} - -{% block panel %} - <h2>Forms</h2> - - {% if collector.data.forms|length %} - <div id="tree-menu" class="tree"> - <ul> - {% for formName, formData in collector.data.forms %} - {{ form_tree_entry(formName, formData, true) }} - {% endfor %} - </ul> - </div> - - <div id="tree-details-container"> - {% for formName, formData in collector.data.forms %} - {{ form_tree_details(formName, formData, collector.data.forms_by_hash, loop.first) }} - {% endfor %} - </div> - {% else %} - <div class="empty"> - <p>No forms were submitted for this request.</p> - </div> - {% endif %} - - <script> - function Toggler(storage) { - "use strict"; - - var STORAGE_KEY = 'sf_toggle_data', - - states = {}, - - isCollapsed = function (button) { - return Sfjs.hasClass(button, 'closed'); - }, - - isExpanded = function (button) { - return !isCollapsed(button); - }, - - expand = function (button) { - var targetId = button.dataset.toggleTargetId, - target = document.getElementById(targetId); - - if (!target) { - throw "Toggle target " + targetId + " does not exist"; - } - - if (isCollapsed(button)) { - Sfjs.removeClass(button, 'closed'); - Sfjs.removeClass(target, 'hidden'); - - states[targetId] = 1; - storage.setItem(STORAGE_KEY, states); - } - }, - - collapse = function (button) { - var targetId = button.dataset.toggleTargetId, - target = document.getElementById(targetId); - - if (!target) { - throw "Toggle target " + targetId + " does not exist"; - } - - if (isExpanded(button)) { - Sfjs.addClass(button, 'closed'); - Sfjs.addClass(target, 'hidden'); - - states[targetId] = 0; - storage.setItem(STORAGE_KEY, states); - } - }, - - toggle = function (button) { - if (Sfjs.hasClass(button, 'closed')) { - expand(button); - } else { - collapse(button); - } - }, - - initButtons = function (buttons) { - states = storage.getItem(STORAGE_KEY, {}); - - // must be an object, not an array or anything else - // `typeof` returns "object" also for arrays, so the following - // check must be done - // see http://stackoverflow.com/questions/4775722/check-if-object-is-array - if ('[object Object]' !== Object.prototype.toString.call(states)) { - states = {}; - } - - for (var i = 0, l = buttons.length; i < l; ++i) { - var targetId = buttons[i].dataset.toggleTargetId, - target = document.getElementById(targetId); - - if (!target) { - throw "Toggle target " + targetId + " does not exist"; - } - - // correct the initial state of the button - if (Sfjs.hasClass(target, 'hidden')) { - Sfjs.addClass(buttons[i], 'closed'); - } - - // attach listener for expanding/collapsing the target - clickHandler(buttons[i], toggle); - - if (states.hasOwnProperty(targetId)) { - // open or collapse based on stored data - if (0 === states[targetId]) { - collapse(buttons[i]); - } else { - expand(buttons[i]); - } - } - } - }; - - return { - initButtons: initButtons, - - toggle: toggle, - - isExpanded: isExpanded, - - isCollapsed: isCollapsed, - - expand: expand, - - collapse: collapse - }; - } - - function JsonStorage(storage) { - var setItem = function (key, data) { - storage.setItem(key, JSON.stringify(data)); - }, - - getItem = function (key, defaultValue) { - var data = storage.getItem(key); - - if (null !== data) { - try { - return JSON.parse(data); - } catch(e) { - } - } - - return defaultValue; - }; - - return { - setItem: setItem, - - getItem: getItem - }; - } - - function TabView() { - "use strict"; - - var activeTab = null, - - activeTarget = null, - - select = function (tab) { - var targetId = tab.dataset.tabTargetId, - target = document.getElementById(targetId); - - if (!target) { - throw "Tab target " + targetId + " does not exist"; - } - - if (activeTab) { - Sfjs.removeClass(activeTab, 'active'); - } - - if (activeTarget) { - Sfjs.addClass(activeTarget, 'hidden'); - } - - Sfjs.addClass(tab, 'active'); - Sfjs.removeClass(target, 'hidden'); - - activeTab = tab; - activeTarget = target; - }, - - initTabs = function (tabs) { - for (var i = 0, l = tabs.length; i < l; ++i) { - var targetId = tabs[i].dataset.tabTargetId, - target = document.getElementById(targetId); - - if (!target) { - throw "Tab target " + targetId + " does not exist"; - } - - clickHandler(tabs[i], select); - - Sfjs.addClass(target, 'hidden'); - } - - if (tabs.length > 0) { - select(tabs[0]); - } - }; - - return { - initTabs: initTabs, - - select: select - }; - } - - var tabTarget = new TabView(), - toggler = new Toggler(new JsonStorage(sessionStorage)), - clickHandler = function (element, callback) { - Sfjs.addEventListener(element, 'click', function (e) { - if (!e) { - e = window.event; - } - - callback(this); - - if (e.preventDefault) { - e.preventDefault(); - } else { - e.returnValue = false; - } - - e.stopPropagation(); - - return false; - }); - }; - - tabTarget.initTabs(document.querySelectorAll('.tree .tree-inner')); - toggler.initButtons(document.querySelectorAll('a.toggle-button')); - </script> -{% endblock %} - -{% macro form_tree_entry(name, data, is_root) %} - {% import _self as tree %} - {% set has_error = data.errors is defined and data.errors|length > 0 %} - <li> - <div class="tree-inner" data-tab-target-id="{{ data.id }}-details" title="{{ name|default('(no name)') }}"> - {% if has_error %} - <div class="badge-error">{{ data.errors|length }}</div> - {% endif %} - - {% if data.children is not empty %} - <a class="toggle-button" data-toggle-target-id="{{ data.id }}-children" href="#"><span class="toggle-icon"></span></a> - {% else %} - <div class="toggle-icon empty"></div> - {% endif %} - - <span {% if has_error or data.has_children_error|default(false) %}class="has-error"{% endif %}> - {{ name|default('(no name)') }} - </span> - </div> - - {% if data.children is not empty %} - <ul id="{{ data.id }}-children" {% if not is_root and not data.has_children_error|default(false) %}class="hidden"{% endif %}> - {% for childName, childData in data.children %} - {{ tree.form_tree_entry(childName, childData, false) }} - {% endfor %} - </ul> - {% endif %} - </li> -{% endmacro %} - -{% macro form_tree_details(name, data, forms_by_hash, show) %} - {% import _self as tree %} - <div class="tree-details{% if not show|default(false) %} hidden{% endif %}" {% if data.id is defined %}id="{{ data.id }}-details"{% endif %}> - <h2>{{ name|default('(no name)') }}</h2> - {% if data.type_class is defined %} - <h3 class="dump-inline form-data-type">{{ profiler_dump(data.type_class) }}</h3> - {% endif %} - - {% if data.errors is defined and data.errors|length > 0 %} - <div class="errors"> - <h3> - <a class="toggle-button" data-toggle-target-id="{{ data.id }}-errors" href="#"> - Errors <span class="toggle-icon"></span> - </a> - </h3> - - <table id="{{ data.id }}-errors"> - <thead> - <tr> - <th>Message</th> - <th>Origin</th> - <th>Cause</th> - </tr> - </thead> - <tbody> - {% for error in data.errors %} - <tr> - <td>{{ error.message }}</td> - <td> - {% if error.origin is empty %} - <em>This form.</em> - {% elseif forms_by_hash[error.origin] is not defined %} - <em>Unknown.</em> - {% else %} - {{ forms_by_hash[error.origin].name }} - {% endif %} - </td> - <td> - {% if error.trace %} - <span class="newline">Caused by:</span> - {% for stacked in error.trace %} - {{ profiler_dump(stacked) }} - {% endfor %} - {% else %} - <em>Unknown.</em> - {% endif %} - </td> - </tr> - {% endfor %} - </tbody> - </table> - </div> - {% endif %} - - {% if data.default_data is defined %} - <h3> - <a class="toggle-button" data-toggle-target-id="{{ data.id }}-default_data" href="#"> - Default Data <span class="toggle-icon"></span> - </a> - </h3> - - <div id="{{ data.id }}-default_data"> - <table> - <thead> - <tr> - <th width="180">Property</th> - <th>Value</th> - </tr> - </thead> - <tbody> - <tr> - <th class="font-normal" scope="row">Model Format</th> - <td> - {% if data.default_data.model is defined %} - {{ profiler_dump(data.default_data.seek('model')) }} - {% else %} - <em class="font-normal text-muted">same as normalized format</em> - {% endif %} - </td> - </tr> - <tr> - <th class="font-normal" scope="row">Normalized Format</th> - <td>{{ profiler_dump(data.default_data.seek('norm')) }}</td> - </tr> - <tr> - <th class="font-normal" scope="row">View Format</th> - <td> - {% if data.default_data.view is defined %} - {{ profiler_dump(data.default_data.seek('view')) }} - {% else %} - <em class="font-normal text-muted">same as normalized format</em> - {% endif %} - </td> - </tr> - </tbody> - </table> - </div> - {% endif %} - - {% if data.submitted_data is defined %} - <h3> - <a class="toggle-button" data-toggle-target-id="{{ data.id }}-submitted_data" href="#"> - Submitted Data <span class="toggle-icon"></span> - </a> - </h3> - - <div id="{{ data.id }}-submitted_data"> - {% if data.submitted_data.norm is defined %} - <table> - <thead> - <tr> - <th width="180">Property</th> - <th>Value</th> - </tr> - </thead> - <tbody> - <tr> - <th class="font-normal" scope="row">View Format</th> - <td> - {% if data.submitted_data.view is defined %} - {{ profiler_dump(data.submitted_data.seek('view')) }} - {% else %} - <em class="font-normal text-muted">same as normalized format</em> - {% endif %} - </td> - </tr> - <tr> - <th class="font-normal" scope="row">Normalized Format</th> - <td>{{ profiler_dump(data.submitted_data.seek('norm')) }}</td> - </tr> - <tr> - <th class="font-normal" scope="row">Model Format</th> - <td> - {% if data.submitted_data.model is defined %} - {{ profiler_dump(data.submitted_data.seek('model')) }} - {% else %} - <em class="font-normal text-muted">same as normalized format</em> - {% endif %} - </td> - </tr> - </tbody> - </table> - {% else %} - <div class="empty"> - <p>This form was not submitted.</p> - </div> - {% endif %} - </div> - {% endif %} - - {% if data.passed_options is defined %} - <h3> - <a class="toggle-button" data-toggle-target-id="{{ data.id }}-passed_options" href="#"> - Passed Options <span class="toggle-icon"></span> - </a> - </h3> - - <div id="{{ data.id }}-passed_options"> - {% if data.passed_options|length %} - <table> - <thead> - <tr> - <th width="180">Option</th> - <th>Passed Value</th> - <th>Resolved Value</th> - </tr> - </thead> - <tbody> - {% for option, value in data.passed_options %} - <tr> - <th>{{ option }}</th> - <td>{{ profiler_dump(value) }}</td> - <td> - {# values can be stubs #} - {% set option_value = value.value|default(value) %} - {% set resolved_option_value = data.resolved_options[option].value|default(data.resolved_options[option]) %} - {% if resolved_option_value == option_value %} - <em class="font-normal text-muted">same as passed value</em> - {% else %} - {{ profiler_dump(data.resolved_options.seek(option)) }} - {% endif %} - </td> - </tr> - {% endfor %} - </tbody> - </table> - {% else %} - <div class="empty"> - <p>No options were passed when constructing this form.</p> - </div> - {% endif %} - </div> - {% endif %} - - {% if data.resolved_options is defined %} - <h3> - <a class="toggle-button" data-toggle-target-id="{{ data.id }}-resolved_options" href="#"> - Resolved Options <span class="toggle-icon"></span> - </a> - </h3> - - <div id="{{ data.id }}-resolved_options" class="hidden"> - <table> - <thead> - <tr> - <th width="180">Option</th> - <th>Value</th> - </tr> - </thead> - <tbody> - {% for option, value in data.resolved_options %} - <tr> - <th scope="row">{{ option }}</th> - <td>{{ profiler_dump(value) }}</td> - </tr> - {% endfor %} - </tbody> - </table> - </div> - {% endif %} - - {% if data.view_vars is defined %} - <h3> - <a class="toggle-button" data-toggle-target-id="{{ data.id }}-view_vars" href="#"> - View Variables <span class="toggle-icon"></span> - </a> - </h3> - - <div id="{{ data.id }}-view_vars" class="hidden"> - <table> - <thead> - <tr> - <th width="180">Variable</th> - <th>Value</th> - </tr> - </thead> - <tbody> - {% for variable, value in data.view_vars %} - <tr> - <th scope="row">{{ variable }}</th> - <td>{{ profiler_dump(value) }}</td> - </tr> - {% endfor %} - </tbody> - </table> - </div> - {% endif %} - </div> - - {% for childName, childData in data.children %} - {{ tree.form_tree_details(childName, childData, forms_by_hash) }} - {% endfor %} -{% endmacro %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Collector/http_client.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Collector/http_client.html.twig deleted file mode 100644 index 8496ef186..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Collector/http_client.html.twig +++ /dev/null @@ -1,131 +0,0 @@ -{% extends '@WebProfiler/Profiler/layout.html.twig' %} - -{% block toolbar %} - {% if collector.requestCount %} - {% set icon %} - {{ include('@WebProfiler/Icon/http-client.svg') }} - {% set status_color = '' %} - <span class="sf-toolbar-value">{{ collector.requestCount }}</span> - {% endset %} - - {% set text %} - <div class="sf-toolbar-info-piece"> - <b>Total requests</b> - <span>{{ collector.requestCount }}</span> - </div> - <div class="sf-toolbar-info-piece"> - <b>HTTP errors</b> - <span class="sf-toolbar-status {{ collector.errorCount > 0 ? 'sf-toolbar-status-red' }}">{{ collector.errorCount }}</span> - </div> - {% endset %} - - {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url, status: status_color }) }} - {% endif %} -{% endblock %} - -{% block menu %} -<span class="label {{ collector.requestCount == 0 ? 'disabled' }}"> - <span class="icon">{{ include('@WebProfiler/Icon/http-client.svg') }}</span> - <strong>HTTP Client</strong> - {% if collector.requestCount %} - <span class="count"> - {{ collector.requestCount }} - </span> - {% endif %} -</span> -{% endblock %} - -{% block panel %} - <h2>HTTP Client</h2> - {% if collector.requestCount == 0 %} - <div class="empty"> - <p>No HTTP requests were made.</p> - </div> - {% else %} - <div class="metrics"> - <div class="metric"> - <span class="value">{{ collector.requestCount }}</span> - <span class="label">Total requests</span> - </div> - <div class="metric"> - <span class="value">{{ collector.errorCount }}</span> - <span class="label">HTTP errors</span> - </div> - </div> - <h2>Clients</h2> - <div class="sf-tabs"> - {% for name, client in collector.clients %} - <div class="tab {{ client.traces|length == 0 ? 'disabled' }}"> - <h3 class="tab-title">{{ name }} <span class="badge">{{ client.traces|length }}</span></h3> - <div class="tab-content"> - {% if client.traces|length == 0 %} - <div class="empty"> - <p>No requests were made with the "{{ name }}" service.</p> - </div> - {% else %} - <h4>Requests</h4> - {% for trace in client.traces %} - {% set profiler_token = '' %} - {% set profiler_link = '' %} - {% if trace.info.response_headers is defined %} - {% for header in trace.info.response_headers %} - {% if header matches '/^x-debug-token: .*$/i' %} - {% set profiler_token = (header.getValue | slice('x-debug-token: ' | length)) %} - {% endif %} - {% if header matches '/^x-debug-token-link: .*$/i' %} - {% set profiler_link = (header.getValue | slice('x-debug-token-link: ' | length)) %} - {% endif %} - {% endfor %} - {% endif %} - <table> - <thead> - <tr> - <th> - <span class="label">{{ trace.method }}</span> - </th> - <th class="full-width"> - {{ trace.url }} - {% if trace.options is not empty %} - {{ profiler_dump(trace.options, maxDepth=1) }} - {% endif %} - </th> - {% if profiler_token and profiler_link %} - <th> - Profile - </th> - {% endif %} - </tr> - </thead> - <tbody> - <tr> - <th> - {% if trace.http_code >= 500 %} - {% set responseStatus = 'error' %} - {% elseif trace.http_code >= 400 %} - {% set responseStatus = 'warning' %} - {% else %} - {% set responseStatus = 'success' %} - {% endif %} - <span class="label status-{{ responseStatus }}"> - {{ trace.http_code }} - </span> - </th> - <td> - {{ profiler_dump(trace.info, maxDepth=1) }} - </td> - {% if profiler_token and profiler_link %} - <td> - <span><a href="{{ profiler_link }}" target="_blank">{{ profiler_token }}</a></span> - </td> - {% endif %} - </tr> - </tbody> - </table> - {% endfor %} - {% endif %} - </div> - </div> - {% endfor %} - {% endif %} - </div> -{% endblock %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Collector/logger.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Collector/logger.html.twig deleted file mode 100644 index b1642d4e1..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Collector/logger.html.twig +++ /dev/null @@ -1,270 +0,0 @@ -{% extends '@WebProfiler/Profiler/layout.html.twig' %} - -{% import _self as helper %} - -{% block toolbar %} - {% if collector.counterrors or collector.countdeprecations or collector.countwarnings %} - {% set icon %} - {% set status_color = collector.counterrors ? 'red' : collector.countwarnings ? 'yellow' : 'none' %} - {{ include('@WebProfiler/Icon/logger.svg') }} - <span class="sf-toolbar-value">{{ collector.counterrors ?: (collector.countdeprecations + collector.countwarnings) }}</span> - {% endset %} - - {% set text %} - <div class="sf-toolbar-info-piece"> - <b>Errors</b> - <span class="sf-toolbar-status sf-toolbar-status-{{ collector.counterrors ? 'red' }}">{{ collector.counterrors|default(0) }}</span> - </div> - - <div class="sf-toolbar-info-piece"> - <b>Warnings</b> - <span class="sf-toolbar-status sf-toolbar-status-{{ collector.countwarnings ? 'yellow' }}">{{ collector.countwarnings|default(0) }}</span> - </div> - - <div class="sf-toolbar-info-piece"> - <b>Deprecations</b> - <span class="sf-toolbar-status sf-toolbar-status-{{ collector.countdeprecations ? 'none' }}">{{ collector.countdeprecations|default(0) }}</span> - </div> - {% endset %} - - {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url, status: status_color }) }} - {% endif %} -{% endblock %} - -{% block menu %} - <span class="label label-status-{{ collector.counterrors ? 'error' : collector.countwarnings ? 'warning' : 'none' }} {{ collector.logs is empty ? 'disabled' }}"> - <span class="icon">{{ include('@WebProfiler/Icon/logger.svg') }}</span> - <strong>Logs</strong> - {% if collector.counterrors or collector.countdeprecations or collector.countwarnings %} - <span class="count"> - <span>{{ collector.counterrors ?: (collector.countdeprecations + collector.countwarnings) }}</span> - </span> - {% endif %} - </span> -{% endblock %} - -{% block panel %} - <h2>Log Messages</h2> - - {% if collector.processedLogs is empty %} - <div class="empty"> - <p>No log messages available.</p> - </div> - {% else %} - {% set has_error_logs = collector.processedLogs|column('type')|filter(type => 'error' == type)|length > 0 %} - {% set has_deprecation_logs = collector.processedLogs|column('type')|filter(type => 'deprecation' == type)|length > 0 %} - - {% set filters = collector.filters %} - <div class="log-filters"> - <div id="log-filter-type" class="log-filter"> - <ul class="tab-navigation"> - <li class="{{ not has_error_logs and not has_deprecation_logs ? 'active' }}"> - <input {{ not has_error_logs and not has_deprecation_logs ? 'checked' }} type="radio" id="filter-log-type-all" name="filter-log-type" value="all"> - <label for="filter-log-type-all">All messages</label> - </li> - - <li class="{{ has_error_logs ? 'active' }}"> - <input {{ has_error_logs ? 'checked' }} type="radio" id="filter-log-type-error" name="filter-log-type" value="error"> - <label for="filter-log-type-error"> - Errors - <span class="badge status-{{ collector.counterrors ? 'error' }}">{{ collector.counterrors|default(0) }}</span> - </label> - </li> - - <li class="{{ not has_error_logs and has_deprecation_logs ? 'active' }}"> - <input {{ not has_error_logs and has_deprecation_logs ? 'checked' }} type="radio" id="filter-log-type-deprecation" name="filter-log-type" value="deprecation"> - <label for="filter-log-type-deprecation"> - Deprecations - <span class="badge status-{{ collector.countdeprecations ? 'warning' }}">{{ collector.countdeprecations|default(0) }}</span> - </label> - </li> - </ul> - </div> - - <details id="log-filter-priority" class="log-filter"> - <summary> - <span class="icon">{{ include('@WebProfiler/Icon/filter.svg') }}</span> - Level (<span class="filter-active-num">{{ filters.priority|length - 1 }}</span>) - </summary> - - <div class="log-filter-content"> - <div class="filter-select-all-or-none"> - <button type="button" class="btn btn-link select-all">Select All</button> - <button type="button" class="btn btn-link select-none">Select None</button> - </div> - - {% for label, value in filters.priority %} - <div class="log-filter-option"> - <input {{ 'debug' != value ? 'checked' }} type="checkbox" id="filter-log-level-{{ value }}" name="filter-log-level-{{ value }}" value="{{ value }}"> - <label for="filter-log-level-{{ value }}">{{ label }}</label> - </div> - {% endfor %} - </div> - </details> - - <details id="log-filter-channel" class="log-filter"> - <summary> - <span class="icon">{{ include('@WebProfiler/Icon/filter.svg') }}</span> - Channel (<span class="filter-active-num">{{ filters.channel|length - 1 }}</span>) - </summary> - - <div class="log-filter-content"> - <div class="filter-select-all-or-none"> - <button type="button" class="btn btn-link select-all">Select All</button> - <button type="button" class="btn btn-link select-none">Select None</button> - </div> - - {% for value in filters.channel %} - <div class="log-filter-option"> - <input {{ 'event' != value ? 'checked' }} type="checkbox" id="filter-log-channel-{{ value }}" name="filter-log-channel-{{ value }}" value="{{ value }}"> - <label for="filter-log-channel-{{ value }}">{{ value|title }}</label> - </div> - {% endfor %} - </div> - </details> - </div> - - <table class="logs"> - <colgroup> - <col width="140px"> - <col> - </colgroup> - - <thead> - <th>Time</th> - <th>Message</th> - </thead> - - <tbody> - {% for log in collector.processedLogs %} - {% set css_class = 'error' == log.type ? 'error' - : (log.priorityName == 'WARNING' or 'deprecation' == log.type) ? 'warning' - : 'silenced' == log.type ? 'silenced' - %} - <tr class="log-status-{{ css_class }}" data-type="{{ log.type }}" data-priority="{{ log.priority }}" data-channel="{{ log.channel }}" style="{{ 'event' == log.channel or 'DEBUG' == log.priorityName ? 'display: none' }}"> - <td class="log-timestamp"> - <time title="{{ log.timestamp|date('r') }}" datetime="{{ log.timestamp|date('c') }}"> - {{ log.timestamp|date('H:i:s.v') }} - </time> - - {% if log.type in ['error', 'deprecation', 'silenced'] or 'WARNING' == log.priorityName %} - <span class="log-type-badge badge badge-{{ css_class }}"> - {% if 'error' == log.type or 'WARNING' == log.priorityName %} - {{ log.priorityName|lower }} - {% else %} - {{ log.type|lower }} - {% endif %} - </span> - {% else %} - <span class="log-type-badge badge badge-{{ css_class }}"> - {{ log.priorityName|lower }} - </span> - {% endif %} - </td> - - <td class="font-normal"> - {{ helper.render_log_message('debug', loop.index, log) }} - </td> - </tr> - {% endfor %} - </tbody> - </table> - - <div class="no-logs-message empty"> - <p>There are no log messages.</p> - </div> - - <script>Sfjs.initializeLogsTable();</script> - {% endif %} - - {% set compilerLogTotal = 0 %} - {% for logs in collector.compilerLogs %} - {% set compilerLogTotal = compilerLogTotal + logs|length %} - {% endfor %} - - <details class="container-compilation-logs"> - <summary> - <h4>Container Compilation Logs <span class="text-muted">({{ compilerLogTotal }})</span></h4> - <p class="text-muted">Log messages generated during the compilation of the service container.</p> - </summary> - - {% if collector.compilerLogs is empty %} - <div class="empty"> - <p>There are no compiler log messages.</p> - </div> - {% else %} - <table class="container-logs"> - <thead> - <tr> - <th>Messages</th> - <th class="full-width">Class</th> - </tr> - </thead> - - <tbody> - {% for class, logs in collector.compilerLogs %} - <tr> - <td class="font-normal text-right">{{ logs|length }}</td> - <td class="font-normal"> - {% set context_id = 'context-compiler-' ~ loop.index %} - - <button type="button" class="btn btn-link sf-toggle" data-toggle-selector="#{{ context_id }}" data-toggle-alt-content="{{ class }}">{{ class }}</button> - - <div id="{{ context_id }}" class="context sf-toggle-content sf-toggle-hidden"> - <ul class="break-long-words"> - {% for log in logs %} - <li>{{ profiler_dump_log(log.message) }}</li> - {% endfor %} - </ul> - </div> - </td> - </tr> - {% endfor %} - </tbody> - </table> - {% endif %} - </details> -{% endblock %} - -{% macro render_log_message(category, log_index, log) %} - {% set has_context = log.context is defined and log.context is not empty %} - {% set has_trace = log.context.exception.trace is defined %} - - {% if not has_context %} - {{ profiler_dump_log(log.message) }} - {% else %} - {{ profiler_dump_log(log.message, log.context) }} - {% endif %} - - <div class="log-metadata"> - {% if log.channel %} - <span class="badge">{{ log.channel }}</span> - {% endif %} - - {% if log.errorCount is defined and log.errorCount > 1 %} - <span class="log-num-occurrences">{{ log.errorCount }} times</span> - {% endif %} - - {% if has_context %} - {% set context_id = 'context-' ~ category ~ '-' ~ log_index %} - <span><button type="button" class="btn btn-link text-small sf-toggle" data-toggle-selector="#{{ context_id }}" data-toggle-alt-content="Hide context">Show context</button></span> - {% endif %} - - {% if has_trace %} - {% set trace_id = 'trace-' ~ category ~ '-' ~ log_index %} - <span><button type="button" class="btn btn-link text-small sf-toggle" data-toggle-selector="#{{ trace_id }}" data-toggle-alt-content="Hide trace">Show trace</button></span> - {% endif %} - - {% if has_context %} - <div id="{{ context_id }}" class="context sf-toggle-content sf-toggle-hidden"> - {{ profiler_dump(log.context, maxDepth=1) }} - </div> - {% endif %} - - {% if has_trace %} - <div id="{{ trace_id }}" class="context sf-toggle-content sf-toggle-hidden"> - {{ profiler_dump(log.context.exception.trace, maxDepth=1) }} - </div> - {% endif %} - </div> -{% endmacro %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Collector/mailer.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Collector/mailer.html.twig deleted file mode 100644 index dab2e9c6c..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Collector/mailer.html.twig +++ /dev/null @@ -1,217 +0,0 @@ -{% extends '@WebProfiler/Profiler/layout.html.twig' %} - -{% block toolbar %} - {% set events = collector.events %} - - {% if events.messages|length %} - {% set icon %} - {% include('@WebProfiler/Icon/mailer.svg') %} - <span class="sf-toolbar-value">{{ events.messages|length }}</span> - {% endset %} - - {% set text %} - <div class="sf-toolbar-info-piece"> - <b>Queued messages</b> - <span class="sf-toolbar-status">{{ events.events|filter(e => e.isQueued())|length }}</span> - </div> - <div class="sf-toolbar-info-piece"> - <b>Sent messages</b> - <span class="sf-toolbar-status">{{ events.events|filter(e => not e.isQueued())|length }}</span> - </div> - {% endset %} - - {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { 'link': profiler_url }) }} - {% endif %} -{% endblock %} - -{% block head %} - {{ parent() }} - <style type="text/css"> - /* utility classes */ - .m-t-0 { margin-top: 0 !important; } - .m-t-10 { margin-top: 10px !important; } - - /* basic grid */ - .row { - display: flex; - flex-wrap: wrap; - margin-right: -15px; - margin-left: -15px; - } - .col { - flex-basis: 0; - flex-grow: 1; - max-width: 100%; - position: relative; - width: 100%; - min-height: 1px; - padding-right: 15px; - padding-left: 15px; - } - .col-4 { - flex: 0 0 33.333333%; - max-width: 33.333333%; - } - - /* small tabs */ - .sf-tabs-sm .tab-navigation li { - font-size: 14px; - padding: .3em .5em; - } - </style> -{% endblock %} - -{% block menu %} - {% set events = collector.events %} - - <span class="label {{ events.messages is empty ? 'disabled' }}"> - <span class="icon">{{ include('@WebProfiler/Icon/mailer.svg') }}</span> - - <strong>E-mails</strong> - {% if events.messages|length > 0 %} - <span class="count"> - <span>{{ events.messages|length }}</span> - </span> - {% endif %} - </span> -{% endblock %} - -{% block panel %} - {% set events = collector.events %} - - <h2>Emails</h2> - - {% if not events.messages|length %} - <div class="empty"> - <p>No emails were sent.</p> - </div> - {% endif %} - - <div class="metrics"> - <div class="metric"> - <span class="value">{{ events.events|filter(e => e.isQueued())|length }}</span> - <span class="label">Queued</span> - </div> - - <div class="metric"> - <span class="value">{{ events.events|filter(e => not e.isQueued())|length }}</span> - <span class="label">Sent</span> - </div> - </div> - - {% for transport in events.transports %} - <div class="card-block"> - <div class="sf-tabs sf-tabs-sm"> - {% for event in events.events(transport) %} - {% set message = event.message %} - <div class="tab"> - <h3 class="tab-title">Email {{ event.isQueued() ? 'queued' : 'sent via ' ~ transport }}</h3> - <div class="tab-content"> - <div class="card"> - {% if message.headers is not defined %} - {# RawMessage instance #} - <div class="card-block"> - <pre class="prewrap" style="max-height: 600px">{{ message.toString() }}</pre> - </div> - {% else %} - {# Message instance #} - <div class="card-block"> - <div class="sf-tabs sf-tabs-sm"> - <div class="tab"> - <h3 class="tab-title">Headers</h3> - <div class="tab-content"> - <span class="label">Subject</span> - <h2 class="m-t-10">{{ message.headers.get('subject').bodyAsString() ?? '(empty)' }}</h2> - <div class="row"> - <div class="col col-4"> - <span class="label">From</span> - <pre class="prewrap">{{ (message.headers.get('from').bodyAsString() ?? '(empty)')|replace({'From:': ''}) }}</pre> - - <span class="label">To</span> - <pre class="prewrap">{{ (message.headers.get('to').bodyAsString() ?? '(empty)')|replace({'To:': ''}) }}</pre> - </div> - <div class="col"> - <span class="label">Headers</span> - <pre class="prewrap">{% for header in message.headers.all|filter(header => (header.name ?? '') not in ['Subject', 'From', 'To']) %} - {{- header.toString }} - {%~ endfor %}</pre> - </div> - </div> - </div> - </div> - {% if message.htmlBody is defined %} - {# Email instance #} - {% set htmlBody = message.htmlBody() %} - {% if htmlBody is not null %} - <div class="tab"> - <h3 class="tab-title">HTML Preview</h3> - <div class="tab-content"> - <pre class="prewrap" style="max-height: 600px"> - <iframe - src="data:text/html;charset=utf-8;base64,{{ collector.base64Encode(htmlBody) }}" - style="height: 80vh;width: 100%;" - > - </iframe> - </pre> - </div> - </div> - <div class="tab"> - <h3 class="tab-title">HTML Content</h3> - <div class="tab-content"> - <pre class="prewrap" style="max-height: 600px"> - {%- if message.htmlCharset() %} - {{- htmlBody|convert_encoding('UTF-8', message.htmlCharset()) }} - {%- else %} - {{- htmlBody }} - {%- endif -%} - </pre> - </div> - </div> - {% endif %} - {% set textBody = message.textBody() %} - {% if textBody is not null %} - <div class="tab"> - <h3 class="tab-title">Text Content</h3> - <div class="tab-content"> - <pre class="prewrap" style="max-height: 600px"> - {%- if message.textCharset() %} - {{- textBody|convert_encoding('UTF-8', message.textCharset()) }} - {%- else %} - {{- textBody }} - {%- endif -%} - </pre> - </div> - </div> - {% endif %} - {% for attachment in message.attachments %} - <div class="tab"> - <h3 class="tab-title">Attachment #{{ loop.index }}</h3> - <div class="tab-content"> - <pre class="prewrap" style="max-height: 600px">{{ attachment.toString() }}</pre> - </div> - </div> - {% endfor %} - {% endif %} - <div class="tab"> - <h3 class="tab-title">Parts Hierarchy</h3> - <div class="tab-content"> - <pre class="prewrap" style="max-height: 600px">{{ message.body().asDebugString() }}</pre> - </div> - </div> - <div class="tab"> - <h3 class="tab-title">Raw</h3> - <div class="tab-content"> - <pre class="prewrap" style="max-height: 600px">{{ message.toString() }}</pre> - </div> - </div> - </div> - </div> - {% endif %} - </div> - </div> - </div> - {% endfor %} - </div> - </div> - {% endfor %} -{% endblock %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Collector/memory.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Collector/memory.html.twig deleted file mode 100644 index 1336a57a2..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Collector/memory.html.twig +++ /dev/null @@ -1,24 +0,0 @@ -{% extends '@WebProfiler/Profiler/layout.html.twig' %} - -{% block toolbar %} - {% set icon %} - {% set status_color = (collector.memory / 1024 / 1024) > 50 ? 'yellow' %} - {{ include('@WebProfiler/Icon/memory.svg') }} - <span class="sf-toolbar-value">{{ '%.1f'|format(collector.memory / 1024 / 1024) }}</span> - <span class="sf-toolbar-label">MiB</span> - {% endset %} - - {% set text %} - <div class="sf-toolbar-info-piece"> - <b>Peak memory usage</b> - <span>{{ '%.1f'|format(collector.memory / 1024 / 1024) }} MiB</span> - </div> - - <div class="sf-toolbar-info-piece"> - <b>PHP memory limit</b> - <span>{{ collector.memoryLimit == -1 ? 'Unlimited' : '%.0f MiB'|format(collector.memoryLimit / 1024 / 1024) }}</span> - </div> - {% endset %} - - {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url, name: 'time', status: status_color }) }} -{% endblock %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Collector/messenger.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Collector/messenger.html.twig deleted file mode 100644 index b48aaa82e..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Collector/messenger.html.twig +++ /dev/null @@ -1,201 +0,0 @@ -{% extends '@WebProfiler/Profiler/layout.html.twig' %} - -{% import _self as helper %} - -{% block toolbar %} - {% if collector.messages|length > 0 %} - {% set status_color = collector.exceptionsCount ? 'red' %} - {% set icon %} - {{ include('@WebProfiler/Icon/messenger.svg') }} - <span class="sf-toolbar-value">{{ collector.messages|length }}</span> - {% endset %} - - {% set text %} - {% for bus in collector.buses %} - {% set exceptionsCount = collector.exceptionsCount(bus) %} - <div class="sf-toolbar-info-piece"> - <b>{{ bus }}</b> - <span - title="{{ exceptionsCount }} message(s) with exceptions" - class="sf-toolbar-status sf-toolbar-status-{{ exceptionsCount ? 'red' }}" - > - {{ collector.messages(bus)|length }} - </span> - </div> - {% endfor %} - {% endset %} - - {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: 'messenger', status: status_color }) }} - {% endif %} -{% endblock %} - -{% block menu %} - <span class="label{{ collector.exceptionsCount ? ' label-status-error' }}{{ collector.messages is empty ? ' disabled' }}"> - <span class="icon">{{ include('@WebProfiler/Icon/messenger.svg') }}</span> - <strong>Messages</strong> - {% if collector.exceptionsCount > 0 %} - <span class="count"> - <span>{{ collector.exceptionsCount }}</span> - </span> - {% endif %} - </span> -{% endblock %} - -{% block head %} - {{ parent() }} - <style> - .message-item thead th { position: relative; cursor: pointer; user-select: none; padding-right: 35px; } - .message-item tbody tr td:first-child { width: 170px; } - - .message-item .label { float: right; padding: 1px 5px; opacity: .75; margin-left: 5px; } - .message-item .toggle-button { position: absolute; right: 6px; top: 6px; opacity: .5; pointer-events: none } - .message-item .icon svg { height: 24px; width: 24px; } - - .message-item .sf-toggle-off .icon-close, .sf-toggle-on .icon-open { display: none; } - .message-item .sf-toggle-off .icon-open, .sf-toggle-on .icon-close { display: block; } - - .message-bus .badge.status-some-errors { line-height: 16px; border-bottom: 2px solid #B0413E; } - - .message-item tbody.sf-toggle-content.sf-toggle-visible { display: table-row-group; } - td.message-bus-dispatch-caller { background: #f1f2f3; } - .theme-dark td.message-bus-dispatch-caller { background: var(--base-1); } - </style> -{% endblock %} - -{% block panel %} - {% import _self as helper %} - - <h2>Messages</h2> - - {% if collector.messages is empty %} - <div class="empty"> - <p>No messages have been collected.</p> - </div> - {% else %} - <div class="sf-tabs message-bus"> - <div class="tab"> - {% set messages = collector.messages %} - {% set exceptionsCount = collector.exceptionsCount %} - <h3 class="tab-title">All<span class="badge {{ exceptionsCount ? exceptionsCount == messages|length ? 'status-error' : 'status-some-errors' }}">{{ messages|length }}</span></h3> - - <div class="tab-content"> - <p class="text-muted">Ordered list of dispatched messages across all your buses</p> - {{ helper.render_bus_messages(messages, true) }} - </div> - </div> - - {% for bus in collector.buses %} - <div class="tab message-bus"> - {% set messages = collector.messages(bus) %} - {% set exceptionsCount = collector.exceptionsCount(bus) %} - <h3 class="tab-title">{{ bus }}<span class="badge {{ exceptionsCount ? exceptionsCount == messages|length ? 'status-error' : 'status-some-errors' }}">{{ messages|length }}</span></h3> - - <div class="tab-content"> - <p class="text-muted">Ordered list of messages dispatched on the <code>{{ bus }}</code> bus</p> - {{ helper.render_bus_messages(messages) }} - </div> - </div> - {% endfor %} - </div> - {% endif %} - -{% endblock %} - -{% macro render_bus_messages(messages, showBus = false) %} - {% set discr = random() %} - {% for dispatchCall in messages %} - <table class="message-item"> - <thead> - <tr> - <th colspan="2" class="sf-toggle" - data-toggle-selector="#message-item-{{ discr }}-{{ loop.index0 }}-details" - data-toggle-initial="{{ loop.first ? 'display' }}" - > - <span class="dump-inline">{{ profiler_dump(dispatchCall.message.type) }}</span> - {% if showBus %} - <span class="label">{{ dispatchCall.bus }}</span> - {% endif %} - {% if dispatchCall.exception is defined %} - <span class="label status-error">exception</span> - {% endif %} - <a class="toggle-button"> - <span class="icon icon-close">{{ include('@WebProfiler/images/icon-minus-square.svg') }}</span> - <span class="icon icon-open">{{ include('@WebProfiler/images/icon-plus-square.svg') }}</span> - </a> - </th> - </tr> - </thead> - <tbody id="message-item-{{ discr }}-{{ loop.index0 }}-details" class="sf-toggle-content"> - <tr> - <td colspan="2" class="message-bus-dispatch-caller"> - <span class="metadata">In - {% set caller = dispatchCall.caller %} - {% if caller.line %} - {% set link = caller.file|file_link(caller.line) %} - {% if link %} - <a href="{{ link }}" title="{{ caller.file }}">{{ caller.name }}</a> - {% else %} - <abbr title="{{ caller.file }}">{{ caller.name }}</abbr> - {% endif %} - {% else %} - {{ caller.name }} - {% endif %} - line <a class="text-small sf-toggle" data-toggle-selector="#sf-trace-{{ discr }}-{{ loop.index0 }}">{{ caller.line }}</a> - </span> - - <div class="hidden" id="sf-trace-{{ discr }}-{{ loop.index0 }}"> - <div class="trace"> - {{ caller.file|file_excerpt(caller.line)|replace({ - '#DD0000': 'var(--highlight-string)', - '#007700': 'var(--highlight-keyword)', - '#0000BB': 'var(--highlight-default)', - '#FF8000': 'var(--highlight-comment)' - })|raw }} - </div> - </div> - </td> - </tr> - {% if showBus %} - <tr> - <td class="text-bold">Bus</td> - <td>{{ dispatchCall.bus }}</td> - </tr> - {% endif %} - <tr> - <td class="text-bold">Message</td> - <td>{{ profiler_dump(dispatchCall.message.value, maxDepth=2) }}</td> - </tr> - <tr> - <td class="text-bold">Envelope stamps <span class="text-muted">when dispatching</span></td> - <td> - {% for item in dispatchCall.stamps %} - {{ profiler_dump(item) }} - {% else %} - <span class="text-muted">No items</span> - {% endfor %} - </td> - </tr> - {% if dispatchCall.stamps_after_dispatch is defined %} - <tr> - <td class="text-bold">Envelope stamps <span class="text-muted">after dispatch</span></td> - <td> - {% for item in dispatchCall.stamps_after_dispatch %} - {{ profiler_dump(item) }} - {% else %} - <span class="text-muted">No items</span> - {% endfor %} - </td> - </tr> - {% endif %} - {% if dispatchCall.exception is defined %} - <tr> - <td class="text-bold">Exception</td> - <td> - {{ profiler_dump(dispatchCall.exception.value, maxDepth=1) }} - </td> - </tr> - {% endif %} - </tbody> - </table> - {% endfor %} -{% endmacro %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Collector/notifier.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Collector/notifier.html.twig deleted file mode 100644 index dd17fab98..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Collector/notifier.html.twig +++ /dev/null @@ -1,168 +0,0 @@ -{% extends '@WebProfiler/Profiler/layout.html.twig' %} - -{% block toolbar %} - {% set events = collector.events %} - - {% if events.messages|length %} - {% set icon %} - {% include('@WebProfiler/Icon/notifier.svg') %} - <span class="sf-toolbar-value">{{ events.messages|length }}</span> - {% endset %} - - {% set text %} - <div class="sf-toolbar-info-piece"> - <b>Sent notifications</b> - <span class="sf-toolbar-status">{{ events.messages|length }}</span> - </div> - - {% for transport in events.transports %} - <div class="sf-toolbar-info-piece"> - <b>{{ transport }}</b> - <span class="sf-toolbar-status">{{ events.messages(transport)|length }}</span> - </div> - {% endfor %} - {% endset %} - - {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { 'link': profiler_url }) }} - {% endif %} -{% endblock %} - -{% block head %} - {{ parent() }} - <style type="text/css"> - /* utility classes */ - .m-t-0 { margin-top: 0 !important; } - .m-t-10 { margin-top: 10px !important; } - - /* basic grid */ - .row { - display: flex; - flex-wrap: wrap; - margin-right: -15px; - margin-left: -15px; - } - .col { - flex-basis: 0; - flex-grow: 1; - max-width: 100%; - position: relative; - width: 100%; - min-height: 1px; - padding-right: 15px; - padding-left: 15px; - } - .col-4 { - flex: 0 0 33.333333%; - max-width: 33.333333%; - } - - /* small tabs */ - .sf-tabs-sm .tab-navigation li { - font-size: 14px; - padding: .3em .5em; - } - </style> -{% endblock %} - -{% block menu %} - {% set events = collector.events %} - - <span class="label {{ events.messages|length ? '' : 'disabled' }}"> - <span class="icon">{{ include('@WebProfiler/Icon/notifier.svg') }}</span> - - <strong>Notifications</strong> - {% if events.messages|length > 0 %} - <span class="count"> - <span>{{ events.messages|length }}</span> - </span> - {% endif %} - </span> -{% endblock %} - -{% block panel %} - {% set events = collector.events %} - - <h2>Notifications</h2> - - {% if not events.messages|length %} - <div class="empty"> - <p>No notifications were sent.</p> - </div> - {% endif %} - - <div class="metrics"> - {% for transport in events.transports %} - <div class="metric"> - <span class="value">{{ events.messages(transport)|length }}</span> - <span class="label">{{ transport }}</span> - </div> - {% endfor %} - </div> - - {% for transport in events.transports %} - <h3>{{ transport }}</h3> - - <div class="card-block"> - <div class="sf-tabs sf-tabs-sm"> - {% for event in events.events(transport) %} - {% set message = event.message %} - <div class="tab"> - <h3 class="tab-title">Message #{{ loop.index }} <small>({{ event.isQueued() ? 'queued' : 'sent' }})</small></h3> - <div class="tab-content"> - <div class="card"> - <div class="card-block"> - <span class="label">Subject</span> - <h2 class="m-t-10">{{ message.getSubject() ?? '(empty)' }}</h2> - </div> - {% if message.getNotification is defined %} - <div class="card-block"> - <div class="row"> - <div class="col"> - <span class="label">Content</span> - <pre class="prewrap">{{ message.getNotification().getContent() ?? '(empty)' }}</pre> - <span class="label">Importance</span> - <pre class="prewrap">{{ message.getNotification().getImportance() }}</pre> - </div> - </div> - </div> - {% endif %} - <div class="card-block"> - <div class="sf-tabs sf-tabs-sm"> - {% if message.getNotification is defined %} - <div class="tab"> - <h3 class="tab-title">Notification</h3> - {% set notification = event.message.getNotification() %} - <div class="tab-content"> - <pre class="prewrap" style="max-height: 600px"> - {{- 'Subject: ' ~ notification.getSubject() }}<br/> - {{- 'Content: ' ~ notification.getContent() }}<br/> - {{- 'Importance: ' ~ notification.getImportance() }}<br/> - {{- 'Emoji: ' ~ (notification.getEmoji() is empty ? '(empty)' : notification.getEmoji()) }}<br/> - {{- 'Exception: ' ~ notification.getException() ?? '(empty)' }}<br/> - {{- 'ExceptionAsString: ' ~ (notification.getExceptionAsString() is empty ? '(empty)' : notification.getExceptionAsString()) }} - </pre> - </div> - </div> - {% endif %} - <div class="tab"> - <h3 class="tab-title">Message Options</h3> - <div class="tab-content"> - <pre class="prewrap" style="max-height: 600px"> - {%- if message.getOptions() is null %} - {{- '(empty)' }} - {%- else %} - {{- message.getOptions()|json_encode(constant('JSON_PRETTY_PRINT')) }} - {%- endif %} - </pre> - </div> - </div> - </div> - </div> - </div> - </div> - </div> - {% endfor %} - </div> - </div> - {% endfor %} -{% endblock %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Collector/request.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Collector/request.html.twig deleted file mode 100644 index 18311c169..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Collector/request.html.twig +++ /dev/null @@ -1,392 +0,0 @@ -{% extends '@WebProfiler/Profiler/layout.html.twig' %} - -{% block toolbar %} - {% import _self as helper %} - {% set request_handler %} - {{ helper.set_handler(collector.controller) }} - {% endset %} - - {% if collector.redirect %} - {% set redirect_handler %} - {{ helper.set_handler(collector.redirect.controller, collector.redirect.route, 'GET' != collector.redirect.method ? collector.redirect.method) }} - {% endset %} - {% endif %} - - {% if collector.forwardtoken %} - {% set forward_profile = profile.childByToken(collector.forwardtoken) %} - {% set forward_handler %} - {{ helper.set_handler(forward_profile ? forward_profile.collector('request').controller : 'n/a') }} - {% endset %} - {% endif %} - - {% set request_status_code_color = (collector.statuscode >= 400) ? 'red' : (collector.statuscode >= 300) ? 'yellow' : 'green' %} - - {% set icon %} - <span class="sf-toolbar-status sf-toolbar-status-{{ request_status_code_color }}">{{ collector.statuscode }}</span> - {% if collector.route %} - {% if collector.redirect %}{{ include('@WebProfiler/Icon/redirect.svg') }}{% endif %} - {% if collector.forwardtoken %}{{ include('@WebProfiler/Icon/forward.svg') }}{% endif %} - <span class="sf-toolbar-label">{{ 'GET' != collector.method ? collector.method }} @</span> - <span class="sf-toolbar-value sf-toolbar-info-piece-additional">{{ collector.route }}</span> - {% endif %} - {% endset %} - - {% set text %} - <div class="sf-toolbar-info-group"> - <div class="sf-toolbar-info-piece"> - <b>HTTP status</b> - <span>{{ collector.statuscode }} {{ collector.statustext }}</span> - </div> - - {% if 'GET' != collector.method -%} - <div class="sf-toolbar-info-piece"> - <b>Method</b> - <span>{{ collector.method }}</span> - </div> - {%- endif %} - - <div class="sf-toolbar-info-piece"> - <b>Controller</b> - <span>{{ request_handler }}</span> - </div> - - <div class="sf-toolbar-info-piece"> - <b>Route name</b> - <span>{{ collector.route|default('n/a') }}</span> - </div> - - <div class="sf-toolbar-info-piece"> - <b>Has session</b> - <span>{% if collector.sessionmetadata|length %}yes{% else %}no{% endif %}</span> - </div> - - <div class="sf-toolbar-info-piece"> - <b>Stateless Check</b> - <span>{% if collector.statelesscheck %}yes{% else %}no{% endif %}</span> - </div> - </div> - - {% if redirect_handler is defined -%} - <div class="sf-toolbar-info-group"> - <div class="sf-toolbar-info-piece"> - <b> - <span class="sf-toolbar-redirection-status sf-toolbar-status-yellow">{{ collector.redirect.status_code }}</span> - Redirect from - </b> - <span> - {{ redirect_handler }} - (<a href="{{ path('_profiler', { token: collector.redirect.token }) }}">{{ collector.redirect.token }}</a>) - </span> - </div> - </div> - {% endif %} - - {% if forward_handler is defined %} - <div class="sf-toolbar-info-group"> - <div class="sf-toolbar-info-piece"> - <b>Forwarded to</b> - <span> - {{ forward_handler }} - (<a href="{{ path('_profiler', { token: collector.forwardtoken }) }}">{{ collector.forwardtoken }}</a>) - </span> - </div> - </div> - {% endif %} - {% endset %} - - {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url }) }} -{% endblock %} - -{% block menu %} - <span class="label"> - <span class="icon">{{ include('@WebProfiler/Icon/request.svg') }}</span> - <strong>Request / Response</strong> - </span> -{% endblock %} - -{% block panel %} - {% import _self as helper %} - - <h2> - {{ helper.set_handler(collector.controller) }} - </h2> - - <div class="sf-tabs"> - <div class="tab"> - <h3 class="tab-title">Request</h3> - - <div class="tab-content"> - <h3>GET Parameters</h3> - - {% if collector.requestquery.all is empty %} - <div class="empty"> - <p>No GET parameters</p> - </div> - {% else %} - {{ include('@WebProfiler/Profiler/bag.html.twig', { bag: collector.requestquery, maxDepth: 1 }, with_context = false) }} - {% endif %} - - <h3>POST Parameters</h3> - - {% if collector.requestrequest.all is empty %} - <div class="empty"> - <p>No POST parameters</p> - </div> - {% else %} - {{ include('@WebProfiler/Profiler/bag.html.twig', { bag: collector.requestrequest, maxDepth: 1 }, with_context = false) }} - {% endif %} - - <h4>Uploaded Files</h4> - - {% if collector.requestfiles is empty %} - <div class="empty"> - <p>No files were uploaded</p> - </div> - {% else %} - {{ include('@WebProfiler/Profiler/bag.html.twig', { bag: collector.requestfiles, maxDepth: 1 }, with_context = false) }} - {% endif %} - - <h3>Request Attributes</h3> - - {% if collector.requestattributes.all is empty %} - <div class="empty"> - <p>No attributes</p> - </div> - {% else %} - {{ include('@WebProfiler/Profiler/bag.html.twig', { bag: collector.requestattributes }, with_context = false) }} - {% endif %} - - <h3>Request Headers</h3> - {{ include('@WebProfiler/Profiler/bag.html.twig', { bag: collector.requestheaders, labels: ['Header', 'Value'], maxDepth: 1 }, with_context = false) }} - - <h3>Request Content</h3> - - {% if collector.content == false %} - <div class="empty"> - <p>Request content not available (it was retrieved as a resource).</p> - </div> - {% elseif collector.content %} - <div class="sf-tabs"> - {% set prettyJson = collector.isJsonRequest ? collector.prettyJson : null %} - {% if prettyJson is not null %} - <div class="tab"> - <h3 class="tab-title">Pretty</h3> - <div class="tab-content"> - <div class="card" style="max-height: 500px; overflow-y: auto;"> - <pre class="break-long-words">{{ prettyJson }}</pre> - </div> - </div> - </div> - {% endif %} - - <div class="tab"> - <h3 class="tab-title">Raw</h3> - <div class="tab-content"> - <div class="card"> - <pre class="break-long-words">{{ collector.content }}</pre> - </div> - </div> - </div> - </div> - {% else %} - <div class="empty"> - <p>No content</p> - </div> - {% endif %} - </div> - </div> - - <div class="tab"> - <h3 class="tab-title">Response</h3> - - <div class="tab-content"> - <h3>Response Headers</h3> - - {{ include('@WebProfiler/Profiler/bag.html.twig', { bag: collector.responseheaders, labels: ['Header', 'Value'], maxDepth: 1 }, with_context = false) }} - </div> - </div> - - <div class="tab {{ collector.requestcookies.all is empty and collector.responsecookies.all is empty ? 'disabled' }}"> - <h3 class="tab-title">Cookies</h3> - - <div class="tab-content"> - <h3>Request Cookies</h3> - - {% if collector.requestcookies.all is empty %} - <div class="empty"> - <p>No request cookies</p> - </div> - {% else %} - {{ include('@WebProfiler/Profiler/bag.html.twig', { bag: collector.requestcookies }, with_context = false) }} - {% endif %} - - <h3>Response Cookies</h3> - - {% if collector.responsecookies.all is empty %} - <div class="empty"> - <p>No response cookies</p> - </div> - {% else %} - {{ include('@WebProfiler/Profiler/bag.html.twig', { bag: collector.responsecookies }, with_context = true) }} - {% endif %} - </div> - </div> - - <div class="tab {{ collector.sessionmetadata is empty ? 'disabled' }}"> - <h3 class="tab-title">Session{% if collector.sessionusages is not empty %} <span class="badge">{{ collector.sessionusages|length }}</span>{% endif %}</h3> - - <div class="tab-content"> - <h3>Session Metadata</h3> - - {% if collector.sessionmetadata is empty %} - <div class="empty"> - <p>No session metadata</p> - </div> - {% else %} - {{ include('@WebProfiler/Profiler/table.html.twig', { data: collector.sessionmetadata }, with_context = false) }} - {% endif %} - - <h3>Session Attributes</h3> - - {% if collector.sessionattributes is empty %} - <div class="empty"> - <p>No session attributes</p> - </div> - {% else %} - {{ include('@WebProfiler/Profiler/table.html.twig', { data: collector.sessionattributes, labels: ['Attribute', 'Value'] }, with_context = false) }} - {% endif %} - - <h3>Session Usage</h3> - - <div class="metrics"> - <div class="metric"> - <span class="value">{{ collector.sessionusages|length }}</span> - <span class="label">Usages</span> - </div> - - <div class="metric"> - <span class="value">{{ include('@WebProfiler/Icon/' ~ (collector.statelesscheck ? 'yes' : 'no') ~ '.svg') }}</span> - <span class="label">Stateless check enabled</span> - </div> - </div> - - {% if collector.sessionusages is empty %} - <div class="empty"> - <p>Session not used.</p> - </div> - {% else %} - <table class="session_usages"> - <thead> - <tr> - <th class="full-width">Usage</th> - </tr> - </thead> - - <tbody> - {% for key, usage in collector.sessionusages %} - <tr> - <td class="font-normal"> - {%- set link = usage.file|file_link(usage.line) %} - {%- if link %}<a href="{{ link }}" title="{{ usage.name }}">{% else %}<span title="{{ usage.name }}">{% endif %} - {{ usage.name }} - {%- if link %}</a>{% else %}</span>{% endif %} - <div class="text-small font-normal"> - {% set usage_id = 'session-usage-trace-' ~ key %} - <a class="btn btn-link text-small sf-toggle" data-toggle-selector="#{{ usage_id }}" data-toggle-alt-content="Hide trace">Show trace</a> - </div> - <div id="{{ usage_id }}" class="context sf-toggle-content sf-toggle-hidden"> - {{ profiler_dump(usage.trace, maxDepth=2) }} - </div> - </td> - </tr> - {% endfor %} - </tbody> - </table> - {% endif %} - </div> - </div> - - <div class="tab {{ collector.flashes is empty ? 'disabled' }}"> - <h3 class="tab-title">Flashes</h3> - - <div class="tab-content"> - <h3>Flashes</h3> - - {% if collector.flashes is empty %} - <div class="empty"> - <p>No flash messages were created.</p> - </div> - {% else %} - {{ include('@WebProfiler/Profiler/table.html.twig', { data: collector.flashes }, with_context = false) }} - {% endif %} - </div> - </div> - - <div class="tab"> - <h3 class="tab-title">Server Parameters</h3> - <div class="tab-content"> - <h3>Server Parameters</h3> - <h4>Defined in .env</h4> - {{ include('@WebProfiler/Profiler/bag.html.twig', { bag: collector.dotenvvars }, with_context = false) }} - - <h4>Defined as regular env variables</h4> - {% set requestserver = [] %} - {% for key, value in collector.requestserver|filter((_, key) => key not in collector.dotenvvars.keys) %} - {% set requestserver = requestserver|merge({(key): value}) %} - {% endfor %} - {{ include('@WebProfiler/Profiler/table.html.twig', { data: requestserver }, with_context = false) }} - </div> - </div> - - {% if profile.parent %} - <div class="tab"> - <h3 class="tab-title">Parent Request</h3> - - <div class="tab-content"> - <h3> - <a href="{{ path('_profiler', { token: profile.parent.token }) }}">Return to parent request</a> - <small>(token = {{ profile.parent.token }})</small> - </h3> - - {{ include('@WebProfiler/Profiler/bag.html.twig', { bag: profile.parent.getcollector('request').requestattributes }, with_context = false) }} - </div> - </div> - {% endif %} - - {% if profile.children|length %} - <div class="tab"> - <h3 class="tab-title">Sub Requests <span class="badge">{{ profile.children|length }}</span></h3> - - <div class="tab-content"> - {% for child in profile.children %} - <h3> - {{ helper.set_handler(child.getcollector('request').controller) }} - <small>(token = <a href="{{ path('_profiler', { token: child.token }) }}">{{ child.token }}</a>)</small> - </h3> - - {{ include('@WebProfiler/Profiler/bag.html.twig', { bag: child.getcollector('request').requestattributes }, with_context = false) }} - {% endfor %} - </div> - </div> - {% endif %} - </div> -{% endblock %} - -{% macro set_handler(controller, route, method) %} - {% if controller.class is defined -%} - {%- if method|default(false) %}<span class="sf-toolbar-status sf-toolbar-redirection-method">{{ method }}</span>{% endif -%} - {%- set link = controller.file|file_link(controller.line) %} - {%- if link %}<a href="{{ link }}" title="{{ controller.class }}">{% else %}<span title="{{ controller.class }}">{% endif %} - - {%- if route|default(false) -%} - @{{ route }} - {%- else -%} - {{- controller.class|abbr_class|striptags -}} - {{- controller.method ? ' :: ' ~ controller.method -}} - {%- endif -%} - - {%- if link %}</a>{% else %}</span>{% endif %} - {%- else -%} - <span>{{ route|default(controller) }}</span> - {%- endif %} -{% endmacro %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Collector/router.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Collector/router.html.twig deleted file mode 100644 index a1449c2b2..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Collector/router.html.twig +++ /dev/null @@ -1,14 +0,0 @@ -{% extends '@WebProfiler/Profiler/layout.html.twig' %} - -{% block toolbar %}{% endblock %} - -{% block menu %} -<span class="label"> - <span class="icon">{{ include('@WebProfiler/Icon/router.svg') }}</span> - <strong>Routing</strong> -</span> -{% endblock %} - -{% block panel %} - {{ render(controller('web_profiler.controller.router::panelAction', { token: token })) }} -{% endblock %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Collector/time.css.twig b/lib/symfony/web-profiler-bundle/Resources/views/Collector/time.css.twig deleted file mode 100644 index b64b6ff86..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Collector/time.css.twig +++ /dev/null @@ -1,64 +0,0 @@ -/* Legend */ - -.sf-profiler-timeline .legends .timeline-category { - border: none; - background: none; - border-left: 1em solid transparent; - line-height: 1em; - margin: 0 1em 0 0; - padding: 0 0.5em; - display: none; - opacity: 0.5; -} - -.sf-profiler-timeline .legends .timeline-category.active { - opacity: 1; -} - -.sf-profiler-timeline .legends .timeline-category.present { - display: inline-block; -} - -.timeline-graph { - margin: 1em 0; - width: 100%; - background-color: var(--table-background); - border: 1px solid var(--table-border); -} - -/* Typography */ - -.timeline-graph .timeline-label { - font-family: var(--font-sans-serif); - font-size: 12px; - line-height: 12px; - font-weight: normal; - fill: var(--color-text); -} - -.timeline-graph .timeline-label .timeline-sublabel { - margin-left: 1em; - fill: var(--color-muted); -} - -.timeline-graph .timeline-subrequest, -.timeline-graph .timeline-border { - fill: none; - stroke: var(--table-border); - stroke-width: 1px; -} - -.timeline-graph .timeline-subrequest { - fill: url(#subrequest); - fill-opacity: 0.5; -} - -.timeline-subrequest-pattern { - fill: var(--table-border); -} - -/* Timeline periods */ - -.timeline-graph .timeline-period { - stroke-width: 0; -} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Collector/time.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Collector/time.html.twig deleted file mode 100644 index 0ed3ddc09..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Collector/time.html.twig +++ /dev/null @@ -1,214 +0,0 @@ -{% extends '@WebProfiler/Profiler/layout.html.twig' %} - -{% import _self as helper %} - -{% block toolbar %} - {% set has_time_events = collector.events|length > 0 %} - {% set total_time = has_time_events ? '%.0f'|format(collector.duration) : 'n/a' %} - {% set initialization_time = collector.events|length ? '%.0f'|format(collector.inittime) : 'n/a' %} - {% set status_color = has_time_events and collector.duration > 1000 ? 'yellow' %} - - {% set icon %} - {{ include('@WebProfiler/Icon/time.svg') }} - <span class="sf-toolbar-value">{{ total_time }}</span> - <span class="sf-toolbar-label">ms</span> - {% endset %} - - {% set text %} - <div class="sf-toolbar-info-piece"> - <b>Total time</b> - <span>{{ total_time }} ms</span> - </div> - <div class="sf-toolbar-info-piece"> - <b>Initialization time</b> - <span>{{ initialization_time }} ms</span> - </div> - {% endset %} - - {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url, status: status_color }) }} -{% endblock %} - -{% block menu %} - <span class="label"> - <span class="icon">{{ include('@WebProfiler/Icon/time.svg') }}</span> - <strong>Performance</strong> - </span> -{% endblock %} - -{% block panel %} - {% set has_time_events = collector.events|length > 0 %} - <h2>Performance metrics</h2> - - <div class="metrics"> - <div class="metric"> - <span class="value">{{ '%.0f'|format(collector.duration) }} <span class="unit">ms</span></span> - <span class="label">Total execution time</span> - </div> - - <div class="metric"> - <span class="value">{{ '%.0f'|format(collector.inittime) }} <span class="unit">ms</span></span> - <span class="label">Symfony initialization</span> - </div> - - {% if profile.collectors.memory %} - <div class="metric"> - <span class="value">{{ '%.2f'|format(profile.collectors.memory.memory / 1024 / 1024) }} <span class="unit">MiB</span></span> - <span class="label">Peak memory usage</span> - </div> - {% endif %} - - {% if profile.children|length > 0 %} - <div class="metric-divider"></div> - - <div class="metric"> - <span class="value">{{ profile.children|length }}</span> - <span class="label">Sub-Request{{ profile.children|length > 1 ? 's' }}</span> - </div> - - {% if has_time_events %} - {% set subrequests_time = 0 %} - {% for child in profile.children %} - {% set subrequests_time = subrequests_time + child.getcollector('time').events.__section__.duration %} - {% endfor %} - {% else %} - {% set subrequests_time = 'n/a' %} - {% endif %} - - <div class="metric"> - <span class="value">{{ subrequests_time }} <span class="unit">ms</span></span> - <span class="label">Sub-Request{{ profile.children|length > 1 ? 's' }} time</span> - </div> - {% endif %} - </div> - - <h2>Execution timeline</h2> - - {% if not collector.isStopwatchInstalled() %} - <div class="empty"> - <p>The Stopwatch component is not installed. If you want to see timing events, run: <code>composer require symfony/stopwatch</code>.</p> - </div> - {% elseif collector.events is empty %} - <div class="empty"> - <p>No timing events have been recorded. Check that symfony/stopwatch is installed and debugging enabled in the kernel.</p> - </div> - {% else %} - {{ block('panelContent') }} - {% endif %} -{% endblock %} - -{% block panelContent %} - <form id="timeline-control" action="" method="get"> - <input type="hidden" name="panel" value="time"> - <label for="threshold">Threshold</label> - <input type="number" name="threshold" id="threshold" value="1" min="0" placeholder="1.1"> ms - <span class="help">(timeline only displays events with a duration longer than this threshold)</span> - </form> - - {% if profile.parent %} - <h3 class="dump-inline"> - Sub-Request {{ profiler_dump(profile.getcollector('request').requestattributes.get('_controller')) }} - <small> - {{ collector.events.__section__.duration }} ms - <a class="newline" href="{{ path('_profiler', { token: profile.parent.token, panel: 'time' }) }}">Return to parent request</a> - </small> - </h3> - {% elseif profile.children|length > 0 %} - <h3> - Main Request <small>{{ collector.events.__section__.duration }} ms</small> - </h3> - {% endif %} - - {{ helper.display_timeline(token, collector.events, collector.events.__section__.origin) }} - - {% if profile.children|length %} - <p class="help">Note: sections with a striped background correspond to sub-requests.</p> - - <h3>Sub-requests <small>({{ profile.children|length }})</small></h3> - - {% for child in profile.children %} - {% set events = child.getcollector('time').events %} - <h4> - <a href="{{ path('_profiler', { token: child.token, panel: 'time' }) }}">{{ child.getcollector('request').identifier }}</a> - <small>{{ events.__section__.duration }} ms</small> - </h4> - - {{ helper.display_timeline(child.token, events, collector.events.__section__.origin) }} - {% endfor %} - {% endif %} - -<svg id="timeline-template" width="0" height="0"> - <defs> - <pattern id="subrequest" class="timeline-subrequest-pattern" patternUnits="userSpaceOnUse" width="20" height="20" viewBox="0 0 40 40"> - <path d="M0 40L40 0H20L0 20M40 40V20L20 40"/> - </pattern> - </defs> -</svg> -<style type="text/css"> -{% include '@WebProfiler/Collector/time.css.twig' %} -</style> -<script> -{% include '@WebProfiler/Collector/time.js' %} -</script> -{% endblock %} - -{% macro dump_request_data(token, events, origin) %} -{% autoescape 'js' %} -{% from _self import dump_events %} -{ - id: "{{ token }}", - left: {{ "%F"|format(events.__section__.origin - origin) }}, - end: "{{ '%F'|format(events.__section__.endtime) }}", - events: [ {{ dump_events(events) }} ], -} -{% endautoescape %} -{% endmacro %} - -{% macro dump_events(events) %} -{% autoescape 'js' %} -{% for name, event in events %} -{% if '__section__' != name %} -{ - name: "{{ name }}", - category: "{{ event.category }}", - origin: {{ "%F"|format(event.origin) }}, - starttime: {{ "%F"|format(event.starttime) }}, - endtime: {{ "%F"|format(event.endtime) }}, - duration: {{ "%F"|format(event.duration) }}, - memory: {{ "%.1F"|format(event.memory / 1024 / 1024) }}, - elements: {}, - periods: [ - {%- for period in event.periods -%} - { - start: {{ "%F"|format(period.starttime) }}, - end: {{ "%F"|format(period.endtime) }}, - duration: {{ "%F"|format(period.duration) }}, - elements: {} - }, - {%- endfor -%} - ], -}, -{% endif %} -{% endfor %} -{% endautoescape %} -{% endmacro %} - -{% macro display_timeline(token, events, origin) %} -{% import _self as helper %} - <div class="sf-profiler-timeline"> - <div id="legend-{{ token }}" class="legends"></div> - <svg id="timeline-{{ token }}" class="timeline-graph"></svg> - <script>{% autoescape 'js' %} - window.addEventListener('load', function onLoad() { - const theme = new Theme(); - - new TimelineEngine( - theme, - new SvgRenderer(document.getElementById('timeline-{{ token }}')), - new Legend(document.getElementById('legend-{{ token }}'), theme), - document.getElementById('threshold'), - {{ helper.dump_request_data(token, events, origin) }} - ); - }); - {% endautoescape %}</script> - </div> -{% endmacro %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Collector/time.js b/lib/symfony/web-profiler-bundle/Resources/views/Collector/time.js deleted file mode 100644 index 156c9343f..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Collector/time.js +++ /dev/null @@ -1,457 +0,0 @@ -'use strict'; - -class TimelineEngine { - /** - * @param {Theme} theme - * @param {Renderer} renderer - * @param {Legend} legend - * @param {Element} threshold - * @param {Object} request - * @param {Number} eventHeight - * @param {Number} horizontalMargin - */ - constructor(theme, renderer, legend, threshold, request, eventHeight = 36, horizontalMargin = 10) { - this.theme = theme; - this.renderer = renderer; - this.legend = legend; - this.threshold = threshold; - this.request = request; - this.scale = renderer.width / request.end; - this.eventHeight = eventHeight; - this.horizontalMargin = horizontalMargin; - this.labelY = Math.round(this.eventHeight * 0.48); - this.periodY = Math.round(this.eventHeight * 0.66); - this.FqcnMatcher = /\\([^\\]+)$/i; - this.origin = null; - - this.createEventElements = this.createEventElements.bind(this); - this.createBackground = this.createBackground.bind(this); - this.createPeriod = this.createPeriod.bind(this); - this.render = this.render.bind(this); - this.renderEvent = this.renderEvent.bind(this); - this.renderPeriod = this.renderPeriod.bind(this); - this.onResize = this.onResize.bind(this); - this.isActive = this.isActive.bind(this); - - this.threshold.addEventListener('change', this.render); - this.legend.addEventListener('change', this.render); - - window.addEventListener('resize', this.onResize); - - this.createElements(); - this.render(); - } - - onResize() { - this.renderer.measure(); - this.setScale(this.renderer.width / this.request.end); - } - - setScale(scale) { - if (scale !== this.scale) { - this.scale = scale; - this.render(); - } - } - - createElements() { - this.origin = this.renderer.setFullVerticalLine(this.createBorder(), 0); - this.renderer.add(this.origin); - - this.request.events - .filter(event => event.category === 'section') - .map(this.createBackground) - .forEach(this.renderer.add); - - this.request.events - .map(this.createEventElements) - .forEach(this.renderer.add); - } - - createBackground(event) { - const subrequest = event.name === '__section__.child'; - const background = this.renderer.create('rect', subrequest ? 'timeline-subrequest' : 'timeline-border'); - - event.elements = Object.assign(event.elements || {}, { background }); - - return background; - } - - createEventElements(event) { - const { name, category, duration, memory, periods } = event; - const border = this.renderer.setFullHorizontalLine(this.createBorder(), 0); - const lines = periods.map(period => this.createPeriod(period, category)); - const label = this.createLabel(this.getShortName(name), duration, memory, periods[0]); - const title = this.renderer.createTitle(name); - const group = this.renderer.group([title, border, label].concat(lines), this.theme.getCategoryColor(event.category)); - - event.elements = Object.assign(event.elements || {}, { group, label, border }); - - this.legend.add(event.category) - - return group; - } - - createLabel(name, duration, memory, period) { - const label = this.renderer.createText(name, period.start * this.scale, this.labelY, 'timeline-label'); - const sublabel = this.renderer.createTspan(` ${duration} ms / ${memory} MiB`, 'timeline-sublabel'); - - label.appendChild(sublabel); - - return label; - } - - createPeriod(period, category) { - const timeline = this.renderer.createPath(null, 'timeline-period', this.theme.getCategoryColor(category)); - - period.draw = category === 'section' ? this.renderer.setSectionLine : this.renderer.setPeriodLine; - period.elements = Object.assign(period.elements || {}, { timeline }); - - return timeline; - } - - createBorder() { - return this.renderer.createPath(null, 'timeline-border'); - } - - isActive(event) { - const { duration, category } = event; - - return duration >= this.threshold.value && this.legend.isActive(category); - } - - render() { - const events = this.request.events.filter(this.isActive); - const width = this.renderer.width + this.horizontalMargin * 2; - const height = this.eventHeight * events.length; - - // Set view box - this.renderer.setViewBox(-this.horizontalMargin, 0, width, height); - - // Show 0ms origin - this.renderer.setFullVerticalLine(this.origin, 0); - - // Render all events - this.request.events.forEach(event => this.renderEvent(event, events.indexOf(event))); - } - - renderEvent(event, index) { - const { name, category, duration, memory, periods, elements } = event; - const { group, label, border, background } = elements; - const visible = index >= 0; - - group.setAttribute('visibility', visible ? 'visible' : 'hidden'); - - if (background) { - background.setAttribute('visibility', visible ? 'visible' : 'hidden'); - - if (visible) { - const [min, max] = this.getEventLimits(event); - - this.renderer.setFullRectangle(background, min * this.scale, max * this.scale); - } - } - - if (visible) { - // Position the group - group.setAttribute('transform', `translate(0, ${index * this.eventHeight})`); - - // Update top border - this.renderer.setFullHorizontalLine(border, 0); - - // render label and ensure it doesn't escape the viewport - this.renderLabel(label, event); - - // Update periods - periods.forEach(this.renderPeriod); - } - } - - renderLabel(label, event) { - const width = this.getLabelWidth(label); - const [min, max] = this.getEventLimits(event); - const alignLeft = (min * this.scale) + width <= this.renderer.width; - - label.setAttribute('x', (alignLeft ? min : max) * this.scale); - label.setAttribute('text-anchor', alignLeft ? 'start' : 'end'); - } - - renderPeriod(period) { - const { elements, start, duration } = period; - - period.draw(elements.timeline, start * this.scale, this.periodY, Math.max(duration * this.scale, 1)); - } - - getLabelWidth(label) { - if (typeof label.width === 'undefined') { - label.width = label.getBBox().width; - } - - return label.width; - } - - getEventLimits(event) { - if (typeof event.limits === 'undefined') { - const { periods } = event; - - event.limits = [ - periods[0].start, - periods[periods.length - 1].end - ]; - } - - return event.limits; - } - - getShortName(name) { - const matches = this.FqcnMatcher.exec(name); - - if (matches) { - return matches[1]; - } - - return name; - } -} - -class Legend { - constructor(element, theme) { - this.element = element; - this.theme = theme; - - this.toggle = this.toggle.bind(this); - this.createCategory = this.createCategory.bind(this); - - this.categories = []; - this.theme.getDefaultCategories().forEach(this.createCategory); - } - - add(category) { - this.get(category).classList.add('present'); - } - - createCategory(category) { - const element = document.createElement('button'); - element.className = `timeline-category active`; - element.style.borderColor = this.theme.getCategoryColor(category); - element.innerText = category; - element.value = category; - element.type = 'button'; - element.addEventListener('click', this.toggle); - - this.element.appendChild(element); - - this.categories.push(element); - - return element; - } - - toggle(event) { - event.target.classList.toggle('active'); - - this.emit('change'); - } - - isActive(category) { - return this.get(category).classList.contains('active'); - } - - get(category) { - return this.categories.find(element => element.value === category) || this.createCategory(category); - } - - emit(name) { - this.element.dispatchEvent(new Event(name)); - } - - addEventListener(name, callback) { - this.element.addEventListener(name, callback); - } - - removeEventListener(name, callback) { - this.element.removeEventListener(name, callback); - } -} - -class SvgRenderer { - /** - * @param {SVGElement} element - */ - constructor(element) { - this.ns = 'http://www.w3.org/2000/svg'; - this.width = null; - this.viewBox = {}; - this.element = element; - - this.add = this.add.bind(this); - - this.setViewBox(0, 0, 0, 0); - this.measure(); - } - - setViewBox(x, y, width, height) { - this.viewBox = { x, y, width, height }; - this.element.setAttribute('viewBox', `${x} ${y} ${width} ${height}`); - } - - measure() { - this.width = this.element.getBoundingClientRect().width; - } - - add(element) { - this.element.appendChild(element); - } - - group(elements, className) { - const group = this.create('g', className); - - elements.forEach(element => group.appendChild(element)); - - return group; - } - - setHorizontalLine(element, x, y, width) { - element.setAttribute('d', `M${x},${y} h${width}`); - - return element; - } - - setVerticalLine(element, x, y, height) { - element.setAttribute('d', `M${x},${y} v${height}`); - - return element; - } - - setFullHorizontalLine(element, y) { - return this.setHorizontalLine(element, this.viewBox.x, y, this.viewBox.width); - } - - setFullVerticalLine(element, x) { - return this.setVerticalLine(element, x, this.viewBox.y, this.viewBox.height); - } - - setFullRectangle(element, min, max) { - element.setAttribute('x', min); - element.setAttribute('y', this.viewBox.y); - element.setAttribute('width', max - min); - element.setAttribute('height', this.viewBox.height); - } - - setSectionLine(element, x, y, width, height = 4, markerSize = 6) { - const totalHeight = height + markerSize; - const maxMarkerWidth = Math.min(markerSize, width / 2); - const widthWithoutMarker = Math.max(0, width - (maxMarkerWidth * 2)); - - element.setAttribute('d', `M${x},${y + totalHeight} v${-totalHeight} h${width} v${totalHeight} l${-maxMarkerWidth} ${-markerSize} h${-widthWithoutMarker} Z`); - } - - setPeriodLine(element, x, y, width, height = 4, markerWidth = 2, markerHeight = 4) { - const totalHeight = height + markerHeight; - const maxMarkerWidth = Math.min(markerWidth, width); - - element.setAttribute('d', `M${x + maxMarkerWidth},${y + totalHeight} h${-maxMarkerWidth} v${-totalHeight} h${width} v${height} h${maxMarkerWidth-width}Z`); - } - - createText(content, x, y, className) { - const element = this.create('text', className); - - element.setAttribute('x', x); - element.setAttribute('y', y); - element.textContent = content; - - return element; - } - - createTspan(content, className) { - const element = this.create('tspan', className); - - element.textContent = content; - - return element; - } - - createTitle(content) { - const element = this.create('title'); - - element.textContent = content; - - return element; - } - - createPath(path = null, className = null, color = null) { - const element = this.create('path', className); - - if (path) { - element.setAttribute('d', path); - } - - if (color) { - element.setAttribute('fill', color); - } - - return element; - } - - create(name, className = null) { - const element = document.createElementNS(this.ns, name); - - if (className) { - element.setAttribute('class', className); - } - - return element; - } -} - -class Theme { - constructor(element) { - this.reservedCategoryColors = { - 'default': '#777', - 'section': '#999', - 'event_listener': '#00b8f5', - 'template': '#66cc00', - 'doctrine': '#ff6633', - 'messenger_middleware': '#bdb81e', - 'controller.argument_value_resolver': '#8c5de6', - 'http_client': '#ffa333', - }; - - this.customCategoryColors = [ - '#dbab09', // dark yellow - '#ea4aaa', // pink - '#964b00', // brown - '#22863a', // dark green - '#0366d6', // dark blue - '#17a2b8', // teal - ]; - - this.getCategoryColor = this.getCategoryColor.bind(this); - this.getDefaultCategories = this.getDefaultCategories.bind(this); - } - - getDefaultCategories() { - return Object.keys(this.reservedCategoryColors); - } - - getCategoryColor(category) { - return this.reservedCategoryColors[category] || this.getRandomColor(category); - } - - getRandomColor(category) { - // instead of pure randomness, colors are assigned deterministically based on the - // category name, to ensure that each custom category always displays the same color - return this.customCategoryColors[this.hash(category) % this.customCategoryColors.length]; - } - - // copied from https://github.com/darkskyapp/string-hash - hash(string) { - var hash = 5381; - var i = string.length; - - while(i) { - hash = (hash * 33) ^ string.charCodeAt(--i); - } - - return hash >>> 0; - } -} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Collector/translation.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Collector/translation.html.twig deleted file mode 100644 index a8a5c2736..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Collector/translation.html.twig +++ /dev/null @@ -1,210 +0,0 @@ -{% extends '@WebProfiler/Profiler/layout.html.twig' %} - -{% import _self as helper %} - -{% block toolbar %} - {% if collector.messages|length %} - {% set icon %} - {{ include('@WebProfiler/Icon/translation.svg') }} - {% set status_color = collector.countMissings ? 'red' : collector.countFallbacks ? 'yellow' %} - {% set error_count = collector.countMissings + collector.countFallbacks %} - <span class="sf-toolbar-value">{{ error_count ?: collector.countDefines }}</span> - {% endset %} - - {% set text %} - <div class="sf-toolbar-info-piece"> - <b>Default locale</b> - <span class="sf-toolbar-status"> - {{ collector.locale|default('-') }} - </span> - </div> - <div class="sf-toolbar-info-piece"> - <b>Missing messages</b> - <span class="sf-toolbar-status sf-toolbar-status-{{ collector.countMissings ? 'red' }}"> - {{ collector.countMissings }} - </span> - </div> - - <div class="sf-toolbar-info-piece"> - <b>Fallback messages</b> - <span class="sf-toolbar-status sf-toolbar-status-{{ collector.countFallbacks ? 'yellow' }}"> - {{ collector.countFallbacks }} - </span> - </div> - - <div class="sf-toolbar-info-piece"> - <b>Defined messages</b> - <span class="sf-toolbar-status">{{ collector.countDefines }}</span> - </div> - {% endset %} - - {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url, status: status_color }) }} - {% endif %} -{% endblock %} - -{% block menu %} - <span class="label label-status-{{ collector.countMissings ? 'error' : collector.countFallbacks ? 'warning' }} {{ collector.messages is empty ? 'disabled' }}"> - <span class="icon">{{ include('@WebProfiler/Icon/translation.svg') }}</span> - <strong>Translation</strong> - {% if collector.countMissings or collector.countFallbacks %} - {% set error_count = collector.countMissings + collector.countFallbacks %} - <span class="count"> - <span>{{ error_count }}</span> - </span> - {% endif %} - </span> -{% endblock %} - -{% block panel %} - <h2>Translation</h2> - - <div class="metrics"> - <div class="metric"> - <span class="value">{{ collector.locale|default('-') }}</span> - <span class="label">Default locale</span> - </div> - <div class="metric"> - <span class="value">{{ collector.fallbackLocales|join(', ')|default('-') }}</span> - <span class="label">Fallback locale{{ collector.fallbackLocales|length != 1 ? 's' }}</span> - </div> - </div> - - <h2>Messages</h2> - - {% if collector.messages is empty %} - <div class="empty"> - <p>No translations have been called.</p> - </div> - {% else %} - {% block messages %} - - {# sort translation messages in groups #} - {% set messages_defined, messages_missing, messages_fallback = [], [], [] %} - {% for message in collector.messages %} - {% if message.state == constant('Symfony\\Component\\Translation\\DataCollectorTranslator::MESSAGE_DEFINED') %} - {% set messages_defined = messages_defined|merge([message]) %} - {% elseif message.state == constant('Symfony\\Component\\Translation\\DataCollectorTranslator::MESSAGE_MISSING') %} - {% set messages_missing = messages_missing|merge([message]) %} - {% elseif message.state == constant('Symfony\\Component\\Translation\\DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK') %} - {% set messages_fallback = messages_fallback|merge([message]) %} - {% endif %} - {% endfor %} - - <div class="sf-tabs"> - <div class="tab {{ collector.countMissings == 0 ? 'active' }}"> - <h3 class="tab-title">Defined <span class="badge">{{ collector.countDefines }}</span></h3> - - <div class="tab-content"> - <p class="help"> - These messages are correctly translated into the given locale. - </p> - - {% if messages_defined is empty %} - <div class="empty"> - <p>None of the used translation messages are defined for the given locale.</p> - </div> - {% else %} - {% block defined_messages %} - {{ helper.render_table(messages_defined) }} - {% endblock %} - {% endif %} - </div> - </div> - - <div class="tab"> - <h3 class="tab-title">Fallback <span class="badge {{ collector.countFallbacks ? 'status-warning' }}">{{ collector.countFallbacks }}</span></h3> - - <div class="tab-content"> - <p class="help"> - These messages are not available for the given locale - but Symfony found them in the fallback locale catalog. - </p> - - {% if messages_fallback is empty %} - <div class="empty"> - <p>No fallback translation messages were used.</p> - </div> - {% else %} - {% block fallback_messages %} - {{ helper.render_table(messages_fallback, true) }} - {% endblock %} - {% endif %} - </div> - </div> - - <div class="tab {{ collector.countMissings > 0 ? 'active' }}"> - <h3 class="tab-title">Missing <span class="badge {{ collector.countMissings ? 'status-error' }}">{{ collector.countMissings }}</span></h3> - - <div class="tab-content"> - <p class="help"> - These messages are not available for the given locale and cannot - be found in the fallback locales. Add them to the translation - catalogue to avoid Symfony outputting untranslated contents. - </p> - - {% if messages_missing is empty %} - <div class="empty"> - <p>There are no messages of this category.</p> - </div> - {% else %} - {% block missing_messages %} - {{ helper.render_table(messages_missing) }} - {% endblock %} - {% endif %} - </div> - </div> - </div> - - <script>Sfjs.createFilters();</script> - - {% endblock messages %} - {% endif %} - -{% endblock %} - -{% macro render_table(messages, is_fallback) %} - <table data-filters> - <thead> - <tr> - <th data-filter="locale">Locale</th> - {% if is_fallback %} - <th>Fallback locale</th> - {% endif %} - <th data-filter="domain">Domain</th> - <th>Times used</th> - <th>Message ID</th> - <th>Message Preview</th> - </tr> - </thead> - <tbody> - {% for message in messages %} - <tr data-filter-locale="{{ message.locale }}" data-filter-domain="{{ message.domain }}"> - <td class="font-normal text-small nowrap">{{ message.locale }}</td> - {% if is_fallback %} - <td class="font-normal text-small nowrap">{{ message.fallbackLocale|default('-') }}</td> - {% endif %} - <td class="font-normal text-small text-bold nowrap">{{ message.domain }}</td> - <td class="font-normal text-small nowrap">{{ message.count }}</td> - <td> - <span class="nowrap">{{ message.id }}</span> - - {% if message.transChoiceNumber is not null %} - <small class="newline">(pluralization is used)</small> - {% endif %} - - {% if message.parameters|length > 0 %} - <button class="btn-link newline text-small sf-toggle" data-toggle-selector="#parameters-{{ loop.index }}" data-toggle-alt-content="Hide parameters">Show parameters</button> - - <div id="parameters-{{ loop.index }}" class="hidden"> - {% for parameters in message.parameters %} - {{ profiler_dump(parameters, maxDepth=1) }} - {% endfor %} - </div> - {% endif %} - </td> - <td class="prewrap">{{ message.translation }}</td> - </tr> - {% endfor %} - </tbody> - </table> -{% endmacro %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Collector/twig.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Collector/twig.html.twig deleted file mode 100644 index be84c19b1..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Collector/twig.html.twig +++ /dev/null @@ -1,115 +0,0 @@ -{% extends '@WebProfiler/Profiler/layout.html.twig' %} - -{% block toolbar %} - {% set time = collector.templatecount ? '%0.0f'|format(collector.time) : 'n/a' %} - {% set icon %} - {{ include('@WebProfiler/Icon/twig.svg') }} - <span class="sf-toolbar-value">{{ time }}</span> - <span class="sf-toolbar-label">ms</span> - {% endset %} - - {% set text %} - <div class="sf-toolbar-info-piece"> - <b>Render Time</b> - <span>{{ time }} ms</span> - </div> - <div class="sf-toolbar-info-piece"> - <b>Template Calls</b> - <span class="sf-toolbar-status">{{ collector.templatecount }}</span> - </div> - <div class="sf-toolbar-info-piece"> - <b>Block Calls</b> - <span class="sf-toolbar-status">{{ collector.blockcount }}</span> - </div> - <div class="sf-toolbar-info-piece"> - <b>Macro Calls</b> - <span class="sf-toolbar-status">{{ collector.macrocount }}</span> - </div> - {% endset %} - - {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url }) }} -{% endblock %} - -{% block menu %} - <span class="label {{ 0 == collector.templateCount ? 'disabled' }}"> - <span class="icon">{{ include('@WebProfiler/Icon/twig.svg') }}</span> - <strong>Twig</strong> - </span> -{% endblock %} - -{% block panel %} - {% if collector.templatecount == 0 %} - <h2>Twig</h2> - - <div class="empty"> - <p>No Twig templates were rendered for this request.</p> - </div> - {% else %} - <h2>Twig Metrics</h2> - - <div class="metrics"> - <div class="metric"> - <span class="value">{{ '%0.0f'|format(collector.time) }} <span class="unit">ms</span></span> - <span class="label">Render time</span> - </div> - - <div class="metric"> - <span class="value">{{ collector.templatecount }}</span> - <span class="label">Template calls</span> - </div> - - <div class="metric"> - <span class="value">{{ collector.blockcount }}</span> - <span class="label">Block calls</span> - </div> - - <div class="metric"> - <span class="value">{{ collector.macrocount }}</span> - <span class="label">Macro calls</span> - </div> - </div> - - <p class="help"> - Render time includes sub-requests rendering time (if any). - </p> - - <h2>Rendered Templates</h2> - - <table id="twig-table"> - <thead> - <tr> - <th scope="col">Template Name &amp; Path</th> - <th class="num-col" scope="col">Render Count</th> - </tr> - </thead> - <tbody> - {% for template, count in collector.templates %} - <tr> - {%- set file = collector.templatePaths[template]|default(false) -%} - {%- set link = file ? file|file_link(1) : false -%} - <td> - <span class="sf-icon icon-twig">{{ include('@WebProfiler/Icon/twig.svg') }}</span> - {% if link %} - <a href="{{ link }}" title="{{ file }}">{{ template }}</a> - <div> - <a class="text-muted" href="{{ link }}" title="{{ file }}"> - {{ file|file_relative|default(file) }} - </a> - </div> - {% else %} - {{ template }} - {% endif %} - </td> - <td class="font-normal num-col">{{ count }}</td> - </tr> - {% endfor %} - </tbody> - </table> - - <h2>Rendering Call Graph</h2> - - <div id="twig-dump"> - {{ collector.htmlcallgraph }} - </div> - {% endif %} -{% endblock %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Collector/validator.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Collector/validator.html.twig deleted file mode 100644 index f3b7b7656..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Collector/validator.html.twig +++ /dev/null @@ -1,103 +0,0 @@ -{% extends '@WebProfiler/Profiler/layout.html.twig' %} - -{% block toolbar %} - {% if collector.violationsCount > 0 or collector.calls|length %} - {% set status_color = collector.violationsCount ? 'red' %} - {% set icon %} - {{ include('@WebProfiler/Icon/validator.svg') }} - <span class="sf-toolbar-value"> - {{ collector.violationsCount ?: collector.calls|length }} - </span> - {% endset %} - - {% set text %} - <div class="sf-toolbar-info-piece"> - <b>Validator calls</b> - <span class="sf-toolbar-status">{{ collector.calls|length }}</span> - </div> - <div class="sf-toolbar-info-piece"> - <b>Number of violations</b> - <span class="sf-toolbar-status {{- collector.violationsCount > 0 ? ' sf-toolbar-status-red' }}">{{ collector.violationsCount }}</span> - </div> - {% endset %} - - {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url, status: status_color }) }} - {% endif %} -{% endblock %} - -{% block menu %} - <span class="label {{- collector.violationsCount ? ' label-status-error' }} {{ collector.calls is empty ? 'disabled' }}"> - <span class="icon">{{ include('@WebProfiler/Icon/validator.svg') }}</span> - <strong>Validator</strong> - {% if collector.violationsCount > 0 %} - <span class="count"> - <span>{{ collector.violationsCount }}</span> - </span> - {% endif %} - </span> -{% endblock %} - -{% block panel %} - <h2>Validator calls</h2> - - {% for call in collector.calls %} - <div class="sf-validator sf-reset"> - <span class="metadata">In - {% set caller = call.caller %} - {% if caller.line %} - {% set link = caller.file|file_link(caller.line) %} - {% if link %} - <a href="{{ link }}" title="{{ caller.file }}">{{ caller.name }}</a> - {% else %} - <abbr title="{{ caller.file }}">{{ caller.name }}</abbr> - {% endif %} - {% else %} - {{ caller.name }} - {% endif %} - line <a class="text-small sf-toggle" data-toggle-selector="#sf-trace-{{ loop.index0 }}">{{ caller.line }}</a> (<a class="text-small sf-toggle" data-toggle-selector="#sf-context-{{ loop.index0 }}">context</a>): - </span> - - <div class="sf-validator-compact hidden" id="sf-trace-{{ loop.index0 }}"> - <div class="trace"> - {{ caller.file|file_excerpt(caller.line)|replace({ - '#DD0000': 'var(--highlight-string)', - '#007700': 'var(--highlight-keyword)', - '#0000BB': 'var(--highlight-default)', - '#FF8000': 'var(--highlight-comment)' - })|raw }} - </div> - </div> - - <div class="sf-validator-compact hidden sf-validator-context" id="sf-context-{{ loop.index0 }}"> - {{ profiler_dump(call.context, maxDepth=1) }} - </div> - - {% if call.violations|length %} - <table> - <thead> - <tr> - <th>Path</th> - <th>Message</th> - <th>Invalid value</th> - <th>Violation</th> - </tr> - </thead> - {% for violation in call.violations %} - <tr> - <td>{{ violation.propertyPath }}</td> - <td>{{ violation.message }}</td> - <td>{{ profiler_dump(violation.seek('invalidValue')) }}</td> - <td>{{ profiler_dump(violation) }}</td> - </tr> - {% endfor %} - </table> - {% else %} - No violations - {% endif %} - </div> - {% else %} - <div class="empty"> - <p>No calls to the validator were collected during this request.</p> - </div> - {% endfor %} -{% endblock %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/ajax.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/ajax.svg deleted file mode 100644 index 4019e3249..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/ajax.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#AAA" d="M9.8 18L6 22.4c-.3.3-.8.4-1.1 0L1 18c-.4-.5-.1-1 .5-1H3V6.4C3 3.8 5.5 2 8.2 2h3.9c1.1 0 2 .9 2 2s-.9 2-2 2H8.2C7.7 6 7 6 7 6.4V17h2.2c.6 0 1 .5.6 1zM23 6l-3.8-4.5a.8.8 0 0 0-1.1 0L14.2 6c-.4.5-.1 1 .5 1H17v10.6c0 .4-.7.4-1.2.4h-3.9c-1.1 0-2 .9-2 2s.9 2 2 2h3.9c2.6 0 5.2-1.8 5.2-4.4V7h1.5c.6 0 .9-.5.5-1z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/cache.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/cache.svg deleted file mode 100644 index 798198928..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/cache.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#AAA" d="M2.3 6l9-4.6a1.5 1.5 0 0 1 1.4 0l9 4.7a1.5 1.5 0 0 1 0 2.6l-9 4.7a1.5 1.5 0 0 1-1.4 0l-9-4.7a1.5 1.5 0 0 1 0-2.6zm18.3 5L12 15.4 3.4 11a1.4 1.4 0 0 0-1.2 2.4l9.2 4.8a1.4 1.4 0 0 0 1.2 0l9.2-4.8a1.4 1.4 0 0 0-1.3-2.4zm0 4.5L12 19.9l-8.6-4.4a1.4 1.4 0 0 0-1.2 2.4l9.2 4.7a1.4 1.4 0 0 0 1.2 0l9.2-4.7a1.4 1.4 0 0 0-1.3-2.5z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/close.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/close.svg deleted file mode 100644 index 6038d73f9..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/close.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#AAA" d="M21.1 18.3c.8.8.8 2 0 2.8-.4.4-.9.6-1.4.6s-1-.2-1.4-.6L12 14.8l-6.3 6.3c-.4.4-.9.6-1.4.6s-1-.2-1.4-.6a2 2 0 0 1 0-2.8L9.2 12 2.9 5.7a2 2 0 0 1 0-2.8 2 2 0 0 1 2.8 0L12 9.2l6.3-6.3a2 2 0 0 1 2.8 0c.8.8.8 2 0 2.8L14.8 12l6.3 6.3z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/config.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/config.svg deleted file mode 100644 index ba51407d1..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/config.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#AAA" d="M11 5.1C11 3.4 9.6 2 7.9 2H5.1A3.1 3.1 0 0 0 2 5.1V18c0 1.6 1.4 3 3.1 3H8c1.7 0 3.1-1.4 3.1-3.1V5.1zM5.2 4h2.7C8.4 4 9 4.8 9 5.3V11H4V5.3C4 4.8 4.6 4 5.2 4zM22 5.1C22 3.4 20.6 2 18.9 2H16c-1.6 0-3 1.4-3 3.1V18c0 1.7 1.4 3.1 3.1 3.1H19c1.7 0 3.1-1.4 3.1-3.1V5.1zM16 4h2.8c.6 0 1.2.8 1.2 1.3V8h-5V5.3c0-.5.5-1.3 1-1.3z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/event.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/event.svg deleted file mode 100644 index 76eaa3245..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/event.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#AAA" d="M19.2 20.8c.4.7.1 1.6-.6 2l-.7.2c-.5 0-1-.3-1.3-.8l-3.7-6.7-1 .1-.9-.1-3.7 6.7c-.4.5-.9.8-1.5.8l-.7-.2c-.7-.4-1-1.3-.6-2l3.8-6.9c-.5-.7-.9-1.6-.9-2.6.1-2.4 2-4.3 4.4-4.3s4.3 1.9 4.3 4.3c0 .9-.3 1.8-.8 2.5l3.9 7zM5.2 11c.6 0 1-.3 1-.8 0-2.1 1.6-3.8 3.7-4.1.5-.1.9-.6.8-1.2-.1-.5-.6-.9-1.1-.9-3.1.5-5.3 3-5.3 6.1-.1.6.4.9.9.9zm8.4-5c2.1.3 3.7 2.1 3.8 4.2 0 .5.5.8 1 .8.6 0 1-.3 1-.8 0-3.1-2.4-5.6-5.5-6.1-.5-.1-1.1.3-1.1.8-.2.6.2 1 .8 1.1zM9 3c.5-.1.9-.6.8-1.1-.1-.6-.6-.9-1.1-.8a9 9 0 0 0-7.4 8.7c0 .6.4 1.2 1 1.2.5 0 1-.6 1-1.2C3.3 6.5 5.7 3.5 9 3zm5.7-2c-.5-.1-1.1.3-1.1.9s.3 1.1.8 1.1c3.3.5 5.8 3.4 5.8 6.8 0 .5.5 1.2 1 1.2.6 0 1-.7 1-1.2A9 9 0 0 0 14.7 1z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/exception.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/exception.svg deleted file mode 100644 index 0e4df2b23..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/exception.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#AAA" d="M23.5 9.5c0-.2-1.2.2-1.6.2l.4-.8C23 7.4 22 6.6 21 7.5c-.4.4 0 1.1 0 1.8v.3l-.6-.3c-.5-.8-1.1-.2-1.1 0 0 .3.7.9 1.1.9h.2v.5c0 .7-.8 1.1-1.7 1.2V9.1c0-4.3-3.3-6.4-6.9-6.4-3.5 0-6.9 2-6.9 6.4v2.8c-.9-.2-1.8-.5-1.8-1.2v-.2h.2c.5 0 1.1-.2 1.1-.4.2-1.4-.6-.5-1.1-.5h-.3l.1-.4c0-.5 1.2-1.7-.8-1.9-.4 0-.5.9-.4 1.3l.4 1.2c-.1-.2-.3-.2-.5-.3-.2-.2-1.6-1.9-1.9 0-.1 1.1 1 1.2 1.9 1l.3-.1-.2 1.2c0 1.3 1.5 1.6 2.9 1.7v5.2c0 1.6.5 2.8 2.2 2.8 1.8 0 2.4-1.3 2.4-2.9 0 1.6.6 2.9 2.3 2.9s2.3-2.2 2.3-2.8c0 1.7.7 2.8 2.4 2.8s2.2-1.2 2.2-2.9v-5.1c1.4-.1 2.9-.4 2.9-1.7l-.1-1c.4.5 1.1.8 1.7.5 1.2-.7.2-1.4.2-1.6zM6.8 8.4c0-1.5 1-2.5 2.3-2.5 1.3 0 2.3 1.1 2.3 2.5s-1 2.6-2.2 2.6c.6 0 1.1-.5 1.1-1.2 0-.6-.5-1.2-1.2-1.2-.6 0-1.2.5-1.2 1.2 0 .6.5 1.2 1.2 1.2-1.3 0-2.3-1.1-2.3-2.6zm5.1 7.5c-2.9-.1-3.1-1.6-3.1-2.5 0-.9 1.7-.3 3.2-.3 1.5 0 3.1-.7 3.1.2 0 1-.8 2.7-3.2 2.6zM15 11c.6-.1 1-.6 1-1.2s-.5-1.2-1.2-1.2c-.6 0-1.2.5-1.2 1.2 0 .6.5 1.2 1.1 1.2-1.3 0-2.3-1.2-2.3-2.6 0-1.5 1-2.5 2.3-2.5C16 5.9 17 7 17 8.4c.1 1.4-.8 2.5-2 2.6z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/filter.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/filter.svg deleted file mode 100644 index 8800f1c05..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/filter.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z" fill="currentColor"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/form.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/form.svg deleted file mode 100644 index e1307960b..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/form.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#AAA" d="M20.5 4H18V2.5c0-.8-.7-1.5-1.5-1.5h-9C6.7 1 6 1.7 6 2.5V4H3.5C2.7 4 2 4.7 2 5.5v16c0 .8.7 1.5 1.5 1.5h17c.8 0 1.5-.7 1.5-1.5v-16c0-.8-.7-1.5-1.5-1.5zM9 4h6v1H9V4zm10 16H5V7h1.1c.2.6.8 1 1.4 1h9c.7 0 1.2-.4 1.4-1H19v13zm-2-9c0 .6-.4 1-1 1H8c-.6 0-1-.4-1-1s.4-1 1-1h8c.6 0 1 .4 1 1zm0 3c0 .6-.4 1-1 1H8c-.6 0-1-.4-1-1s.4-1 1-1h8c.6 0 1 .4 1 1zm-4 3c0 .6-.4 1-1 1H8c-.6 0-1-.4-1-1s.4-1 1-1h4c.6 0 1 .4 1 1z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/forward.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/forward.svg deleted file mode 100644 index 28a960a5b..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/forward.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#aaa" d="M23.6 11l-6.5-6.6a1.2 1.2 0 0 0-2.1.9V9H1.4A1.8 1.8 0 0 0 0 10.8v2.6A1.6 1.6 0 0 0 1.4 15H15v3.7a1.2 1.2 0 0 0 2 1l6.7-6.8a1.3 1.3 0 0 0 0-1.8z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/http-client.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/http-client.svg deleted file mode 100644 index e6b1fb2fe..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/http-client.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#AAA" d="M20.4 12c-1 0-1.8.6-2.2 1.4l-2.6-.9c.1-.3.1-.5.1-.8 0-1.2-.6-2.2-1.5-2.9l1.5-2.6c.3.1.6.2 1 .2 1.4 0 2.5-1.1 2.5-2.5s-1.1-2.5-2.5-2.5-2.5 1.1-2.5 2.5c0 .8.4 1.5.9 1.9l-1.5 2.6c-.5-.3-1-.4-1.6-.4-.9 0-1.7.3-2.3.9L7.4 6.6c.3-.4.5-.9.5-1.5 0-1.4-1.1-2.5-2.5-2.5S2.7 3.7 2.7 5.1s1.1 2.5 2.5 2.5c.6 0 1.1-.2 1.5-.5L9 9.4c-.5.6-.8 1.4-.8 2.3 0 .7.2 1.4.6 2l-3.9 3.8c-.4-.3-.9-.5-1.5-.5C2 17 .9 18.1.9 19.5S2.2 22 3.6 22s2.5-1.1 2.5-2.5c0-.5-.2-1-.5-1.5l3.8-3.7c.7.7 1.6 1.1 2.6 1.1h.2l.4 2.4c-1 .3-1.7 1.3-1.7 2.4 0 1.4 1.1 2.5 2.5 2.5s2.5-1.1 2.5-2.5-1.1-2.5-2.5-2.5l-.4-2.5c1-.3 1.9-1 2.3-2l2.6.9v.4c0 1.4 1.1 2.5 2.5 2.5s2.5-1.1 2.5-2.5c.1-1.4-1.1-2.5-2.5-2.5z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/logger.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/logger.svg deleted file mode 100644 index ae8c5aae4..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/logger.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#AAA" d="M21 4v13.8c0 2.7-2.5 5.2-5.2 5.2H6c-.6 0-1-.4-1-1s.4-1 1-1h9.8c1.6 0 3.2-1.7 3.2-3.2V4c0-.6.4-1 1-1s1 .4 1 1zM5.5 20A2.5 2.5 0 0 1 3 17.5v-14C3 2.1 4.1 1 5.5 1h10.1C16.9 1 18 2.1 18 3.5v14.1c0 1.4-1.1 2.5-2.5 2.5h-10zM9 11.4c0 .3.3.6.6.6h1.8c.3 0 .6-.3.6-.6V4.6c0-.3-.3-.6-.6-.6H9.6c-.3 0-.6.3-.6.6v6.8zm0 5c0 .3.3.6.6.6h1.8c.3 0 .6-.3.6-.6v-1.8c0-.3-.3-.6-.6-.6H9.6c-.3 0-.6.3-.6.6v1.8z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/mailer.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/mailer.svg deleted file mode 100644 index ed649d068..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/mailer.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#AAAAAA" d="M22,4.9C22,3.9,21.1,3,20.1,3H3.9C2.9,3,2,3.9,2,4.9v13.1C2,19.1,2.9,20,3.9,20h16.1c1.1,0,1.9-0.9,1.9-1.9V4.9z M8.3,14.1l-3.1,3.1c-0.2,0.2-0.5,0.3-0.7,0.3S4,17.4,3.8,17.2c-0.4-0.4-0.4-1,0-1.4l3.1-3.1c0.4-0.4,1-0.4,1.4,0S8.7,13.7,8.3,14.1z M20.4,17.2c-0.2,0.2-0.5,0.3-0.7,0.3s-0.5-0.1-0.7-0.3l-3.1-3.1c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l3.1,3.1C20.8,16.2,20.8,16.8,20.4,17.2z M20.4,7.2l-7.6,7.6c-0.2,0.2-0.5,0.3-0.7,0.3s-0.5-0.1-0.7-0.3L3.8,7.2c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6.9,6.9L19,5.8c0.4-0.4,1-0.4,1.4,0S20.8,6.8,20.4,7.2z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/memory.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/memory.svg deleted file mode 100644 index deb047fc4..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/memory.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#AAA" d="M6 18.9V15h12v3.9c0 .7-.2 1.1-1 1.1H7c-.8 0-1-.4-1-1.1zM20 1c-.6 0-1 .5-1 1.1v18c0 .5-.4.9-.9.9H5.9a.9.9 0 0 1-.9-.9v-18C5 1.5 4.6 1 4 1c-.5 0-1 .5-1 1.1v18C3 21.7 4.3 23 5.9 23h12.2c1.6 0 2.9-1.3 2.9-2.9v-18c0-.6-.4-1.1-1-1.1zm-2 8H6v5h12V9z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/menu.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/menu.svg deleted file mode 100644 index afccc7f62..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/menu.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#AAA" d="M2.6 17.5h18.8c.9 0 1.6.7 1.6 1.6v1.5c0 1-.7 1.6-1.6 1.6H2.6c-.9 0-1.6-.7-1.6-1.6v-1.5c0-.9.7-1.6 1.6-1.6zM1 11.2v1.6c0 .9.7 1.6 1.6 1.6h18.8c.9 0 1.6-.7 1.6-1.6v-1.6c0-.8-.7-1.6-1.6-1.6H2.6A1.6 1.6 0 0 0 1 11.2zm0-7.8v1.5a1.6 1.6 0 0 0 1.6 1.6h18.8c.9 0 1.6-.7 1.6-1.6V3.4c0-1-.7-1.6-1.6-1.6H2.6A1.6 1.6 0 0 0 1 3.4z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/messenger.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/messenger.svg deleted file mode 100644 index 3af517813..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/messenger.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#aaa" d="M16 9a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2h-3V4a1 1 0 0 0-1-1H8a2 2 0 0 0-2-2H2a2 2 0 0 0-2 2v2a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2h3v6H8a2 2 0 0 0-2-2H2a2 2 0 0 0-2 2v2a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2h3v9a1 1 0 0 0 2 0v-5h3a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2v-2a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2h-3V9zm2.52-2.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1 0-1zm0 1.63h3a.5.5 0 0 1 .5.5.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5.5.5 0 0 1 .5-.52zm-13-2.82h-3a.5.5 0 0 1-.5-.5.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 .5.5.5.5 0 0 1-.54.48zm0-1.62h-3a.5.5 0 0 1-.5-.5.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 .5.5.5.5 0 0 1-.54.48zm0 9.62h-3a.5.5 0 0 1-.5-.5.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 .5.5.5.5 0 0 1-.54.48zm0-1.62h-3a.5.5 0 0 1-.5-.5.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 .5.5.5.5 0 0 1-.54.48zm13 2.81h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1 0-1zm0 1.63h3a.5.5 0 0 1 .5.5.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5.5.5 0 0 1 .5-.52z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/no-gray.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/no-gray.svg deleted file mode 100644 index ea0089159..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/no-gray.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 12 12"><path fill="#999" d="M10.4 8.4L8 6l2.4-2.4c.8-.8.7-1.6.2-2.2-.6-.5-1.4-.6-2.2.2L6 4 3.6 1.6C2.8.8 2 .9 1.4 1.4c-.5.6-.6 1.4.2 2.2L4 6 1.6 8.4c-.8.8-.7 1.6-.2 2.2.6.6 1.4.6 2.2-.2L6 8l2.4 2.4c.8.8 1.6.7 2.2.2.5-.6.6-1.4-.2-2.2z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/no.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/no.svg deleted file mode 100644 index 5ffc020f4..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/no.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 12 12"><path fill="#B0413E" d="M10.4 8.4L8 6l2.4-2.4c.8-.8.7-1.6.2-2.2-.6-.5-1.4-.6-2.2.2L6 4 3.6 1.6C2.8.8 2 .9 1.4 1.4c-.5.6-.6 1.4.2 2.2L4 6 1.6 8.4c-.8.8-.7 1.6-.2 2.2.6.6 1.4.6 2.2-.2L6 8l2.4 2.4c.8.8 1.6.7 2.2.2.5-.6.6-1.4-.2-2.2z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/notifier.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/notifier.svg deleted file mode 100644 index 0648f126e..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/notifier.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#AAA" d="M11.23,4.8c-3,.83-5.07,3.18-5.07,5.9H7.39c0-2.21,1.77-4,4.17-4.72ZM7.49,0A12.22,12.22,0,0,0,0,11.59H2.07A10.14,10.14,0,0,1,8.23,2Zm8.24,2a10.14,10.14,0,0,1,6.16,9.64H24A12.24,12.24,0,0,0,16.47,0ZM4.41,15.64V10.7a7.57,7.57,0,0,1,15.14,0v4.94l3.3,4.4H1.11Zm4.45,5.3A3.06,3.06,0,0,0,11.92,24H12a3.07,3.07,0,0,0,3.07-3.06Z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/redirect.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/redirect.svg deleted file mode 100644 index 8c329d052..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/redirect.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#aaa" d="M23 7.8L14 .4a1.3 1.3 0 0 0-2 .9V4a13.6 13.6 0 0 1-2.2.6l-1.3.5c-.5.1-1 .4-1.4.6l-.7.4-.7.4a10.6 10.6 0 0 0-1.4 1A13.2 13.2 0 0 0 3 8.8a15.3 15.3 0 0 0-1.1 1.5 17.6 17.6 0 0 0-.9 1.6l-.5 1.7c-.2.5 0 1.2 0 1.7a10.2 10.2 0 0 0 0 1.5A5.7 5.7 0 0 0 1 18l.4 1.2 1 2 1 1.4 1 1c.2.2.4.1.3-.2l-.3-1.2-.3-1.6-.1-1.9v-1a3.4 3.4 0 0 1 .2-1 6.4 6.4 0 0 1 .3-.8l.4-.8.6-.6.6-.6.7-.4a7.5 7.5 0 0 1 .8-.2 4.5 4.5 0 0 1 .8-.2h2.5a3.8 3.8 0 0 1 1.2.3v3.1a1.3 1.3 0 0 0 2 1l9-7.5a1.5 1.5 0 0 0 0-2.3z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/request.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/request.svg deleted file mode 100644 index 67d6c643f..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/request.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#AAA" d="M15.8 6.4h-1.1s-.1.1-.1 0l.8-.7c.5-.5.5-1.3 0-1.9L14 2.4c-.5-.5-1.4-.5-1.9 0l-.6.8c-.1 0 0 0 0-.1v-1c0-.8-1-1.4-1.8-1.4h-2c-.8 0-1.9.6-1.9 1.4v1.1l.1.1-.8-.8c-.5-.5-1.3-.5-1.9 0L1.8 3.9c-.5.5-.5 1.4 0 1.9l.8.6c0 .1 0 0-.1 0H1.4C.7 6.4 0 7.5 0 8.2v2C0 11 .7 12 1.4 12h1.2l.1-.1-.8.7c-.5.5-.5 1.3 0 1.9L3.3 16c.5.5 1.4.5 1.9 0l.6-.8-.1.1v1.2c0 .8 1.1 1.4 1.9 1.4h2c.8 0 1.8-.6 1.8-1.4v-1.2s-.1-.1 0-.1l.7.8c.5.5 1.3.5 1.9 0l1.4-1.4c.5-.5.5-1.4 0-1.9l-.8-.7.1.1h1.1c.8 0 1.3-1.1 1.3-1.8v-2c0-.8-.6-1.9-1.3-1.9zM8.6 13a3.8 3.8 0 1 1 3.8-3.8A4 4 0 0 1 8.6 13zm13.7 2.6l-.6.2s0 .1 0 0l.3-.5c.2-.4 0-.8-.4-1l-1-.4c-.4-.2-.8 0-1 .4l-.1.5-.2-.6c-.2-.4-.8-.5-1.2-.3l-1.1.4c-.4.2-.8.7-.7 1.1l.2.6h.1l-.5-.3c-.4-.2-.8 0-1 .4l-.4 1c-.2.4 0 .8.4 1l.5.1-.6.2c-.4.2-.5.8-.4 1.2l.4 1.1c.2.4.7.8 1.1.7l.6-.2s0-.1 0 0l-.3.5c-.2.4 0 .8.4 1l1 .4c.4.2.8 0 1-.4l.1-.5.2.6c.2.4.9.5 1.2.3l1.1-.4c.4-.2.8-.7.6-1.1l-.2-.6s-.1 0 0 0l.5.3c.4.2.8 0 1-.4l.4-1c.2-.4 0-.8-.4-1l-.5-.1.6-.2c.4-.2.5-.8.3-1.2l-.4-1.1c-.1-.4-.6-.8-1-.7zm-2.4 4.9a2 2 0 0 1-2.7-1.2 2 2 0 0 1 1.2-2.7 2 2 0 0 1 2.7 1.2 2 2 0 0 1-1.2 2.7z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/router.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/router.svg deleted file mode 100644 index e16c617eb..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/router.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#AAA" d="M13 3v18c0 1.1-.9 2-2 2s-2-.9-2-2V3c0-1.1.9-2 2-2s2 .9 2 2zm10.2 1.6l-1.8-1.4c-.2-.3-.6-.2-1-.2H14v5h6.4c.4 0 .8-.3 1.1-.5l1.8-1.6c.3-.3.3-1-.1-1.3zm-3.7 4.8c-.3-.3-.7-.4-1.1-.4H14v5h4.4a2 2 0 0 0 1.1-.3l1.8-1.5c.4-.3.4-.9 0-1.3l-1.8-1.5zM3.5 7c-.4 0-.7 0-1 .3L.7 8.8c-.4.3-.4.9 0 1.3l1.8 1.6c.3.2.6.3 1 .3H8V7H3.5z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/search.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/search.svg deleted file mode 100644 index cae0a67f9..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/search.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#AAA" d="M11.6.4A8 8 0 0 0 5.2 13L.8 17.5a1.3 1.3 0 0 0-.4.9c0 .3.1.6.4.9s.5.3.9.3c.3 0 .6 0 .9-.3l4.3-4.5a7.9 7.9 0 0 0 4.7 1.5 8 8 0 0 0 0-16zm5.5 8a5.5 5.5 0 0 1-5.5 5.4 5.5 5.5 0 1 1 5.5-5.5z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/symfony.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/symfony.svg deleted file mode 100644 index c3beff6c8..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/symfony.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#AAA" d="M12 .9C5.8.9.9 5.8.9 12a11 11 0 1 0 22.2 0A11 11 0 0 0 12 .9zm6.5 6c-.6 0-.9-.3-.9-.8 0-.2 0-.4.2-.6l.2-.4c0-.3-.5-.4-.6-.4-1.8.1-2.3 2.5-2.7 4.4l-.2 1c1 .2 1.8 0 2.2-.3.6-.4-.2-.7-.1-1.2.1-.3.5-.5.7-.6.5 0 .7.5.7.9 0 .7-1 1.8-3 1.8l-.6-.1-.6 2.4c-.4 1.6-.8 3.8-2.4 5.7-1.4 1.7-2.9 1.9-3.5 1.9-1.2 0-1.9-.6-2-1.5 0-.8.7-1.3 1.2-1.3.6 0 1.1.5 1.1 1s-.2.6-.4.6c-.1.1-.3.2-.3.4 0 .1.1.3.4.3.5 0 .8-.3 1.1-.5 1.2-.9 1.6-2.7 2.2-5.7l.1-.7.7-3.2c-.8-.6-1.3-1.4-2.4-1.7-.6-.1-1.1.1-1.5.5-.4.5-.2 1.1.2 1.5l.7.6c.7.8 1.2 1.6 1 2.5-.3 1.5-2 2.6-4 1.9-1.8-.6-2-1.8-1.8-2.5.2-.6.6-.7 1.1-.6.5.2.6.7.6 1.2l-.1.3c-.2.1-.3.3-.3.4-.1.4.4.6.7.7.7.3 1.6-.2 1.8-.8a1 1 0 0 0-.4-1.1l-.7-.8c-.4-.4-1.1-1.4-.7-2.6.1-.5.4-.9.7-1.3a4 4 0 0 1 2.8-.6c1.2.4 1.8 1.1 2.6 1.8.5-1.2 1-2.4 1.8-3.5.9-.9 1.9-1.6 3.1-1.7 1.3.2 2.2.7 2.2 1.6 0 .4-.2 1.1-.9 1.1z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/time.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/time.svg deleted file mode 100644 index d49851d44..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/time.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#AAA" d="M15.1 4.3a13 13 0 0 0-6.2 0c-.3 0-.7-.2-.7-.5v-.4c0-1.2 1-2.3 2.3-2.3h3c1.2 0 2.3 1 2.3 2.3v.3c0 .4-.4.6-.7.6zm5.8 9.7a9 9 0 0 1-17.8 0 9 9 0 0 1 17.8 0zm-4.2 1c0-.6-.4-1-1-1H13V8.4c0-.6-.4-1-1-1s-1 .4-1 1v6.2c0 .6.4 1.3 1 1.3h3.7c.5.1 1-.3 1-.9z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/translation.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/translation.svg deleted file mode 100644 index 735bb92c7..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/translation.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#AAA" d="M5.4 6H7v.3c0 1.2-.7 1.9-1.7 1.9-1.1 0-1.4-.4-1.4-1.1 0-.9.6-1.1 1.5-1.1zm3.8-6H2.7C1.2 0 0 .9 0 2.4v6.5C0 10.4 1.2 11 2.7 11h1.2l3.3 3.2c.4.2.8.3.8-.1V9.9l.1-1.1h-.4c-.3.1-.7-.1-.7-.4v-.5c0 .7-1 1-1.8 1-1.5 0-2.4-.7-2.4-2s1.1-2 2.6-2H7v-.4c0-1-.4-1.6-1.5-1.6-.7 0-1.1.2-1.5.7l-.3.2a.4.4 0 0 1-.4-.4l.1-.2c.4-.7 1-1.2 2.2-1.2C7.2 2 8 3 8 4.5v3c1-1.4 1.8-2.4 4-2.4V2.4C12 .9 10.7 0 9.2 0zm11.5 6h-8C10.8 6 9 7.2 9 9v8c0 1.8 2 3.3 4 3.3v3c0 .5.5.7.9.3l4-3.7h2.7c1.8 0 3.3-1.2 3.3-3V9c.1-1.8-1.4-3-3.2-3zM13 9h7v.8s-.7.3-1.1.3h-4.8a10 10 0 0 1-1.1-.4V9zm-.5 7.9l-.6-.5c1-.8 1.8-2.1 2.2-3.4l.7.3c-.6 1.5-1.4 2.6-2.3 3.6zM17 12v4.8c0 .7-.2.8-1.2.8l-1.4-.1-.2-.7 1.4.1c.4 0 .4 0 .4-.3V12h-2.9l-1.1.1v-.8s.7-.4 1.1-.4h6.8c.5 0 1.1.4 1.1.4v.8l-1.1-.1H17zm3.7 4.8c-1-1.1-1.6-1.9-2.3-3.6l.6-.2a9 9 0 0 0 2.2 3.3l-.5.5z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/twig.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/twig.svg deleted file mode 100644 index 4a6ef7ab3..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/twig.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#AAA" d="M8.932 22.492c.016-6.448-.971-11.295-5.995-11.619 4.69-.352 7.113 2.633 9.298 6.907C12.205 6.354 9.882 1.553 4.8 1.297c7.433.07 10.028 5.9 11.508 14.293 1.171-2.282 3.56-5.553 5.347-1.361-1.594-2.04-3.607-1.617-3.978 8.262H8.933z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/validator.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/validator.svg deleted file mode 100644 index 6a81d92da..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/validator.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#aaa" d="M19.5 22.5H4.3a2.9 2.9 0 0 1-2.9-2.9V4.4a2.9 2.9 0 0 1 2.9-2.9h14.2a1 1 0 0 1 0 2H4.3a.9.9 0 0 0-.9.9v15.2a.9.9 0 0 0 .9.9h15.2a.9.9 0 0 0 1-.9v-8.3a1 1 0 1 1 2 0v8.3a2.9 2.9 0 0 1-3 2.9zM13 17.3L22.9 6a1.5 1.5 0 1 0-2.3-2L12 14 8 9.1A1.5 1.5 0 0 0 5.7 11l5 6.3a1.5 1.5 0 0 0 1.2.5 1.5 1.5 0 0 0 1.1-.5z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Icon/yes.svg b/lib/symfony/web-profiler-bundle/Resources/views/Icon/yes.svg deleted file mode 100644 index dbbff93d0..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Icon/yes.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 12 12"><path fill="#5E976E" d="M12 3.1c0 .4-.1.8-.4 1.1L5.9 9.8c-.3.3-.6.4-1 .4s-.7-.1-1-.4L.4 6.3C.1 6 0 5.6 0 5.2c0-.4.2-.7.4-.9.2-.3.6-.4.9-.4.4 0 .8.1 1.1.4l2.5 2.5 4.7-4.7c.3-.3.7-.4 1-.4.4 0 .7.2.9.4.3.3.5.6.5 1z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/ajax_layout.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/ajax_layout.html.twig deleted file mode 100644 index 3e2f6f09f..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/ajax_layout.html.twig +++ /dev/null @@ -1 +0,0 @@ -{% block panel '' %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/bag.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/bag.html.twig deleted file mode 100644 index 4df5ccf1c..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/bag.html.twig +++ /dev/null @@ -1,20 +0,0 @@ -<table class="{{ class|default('') }}"> - <thead> - <tr> - <th scope="col" class="key">{{ labels is defined ? labels[0] : 'Key' }}</th> - <th scope="col">{{ labels is defined ? labels[1] : 'Value' }}</th> - </tr> - </thead> - <tbody> - {% for key in bag.keys|sort %} - <tr> - <th>{{ key }}</th> - <td>{{ profiler_dump(bag.get(key), maxDepth=maxDepth|default(0)) }}</td> - </tr> - {% else %} - <tr> - <td colspan="2">(no data)</td> - </tr> - {% endfor %} - </tbody> -</table> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/base.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/base.html.twig deleted file mode 100644 index 1a74431d8..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/base.html.twig +++ /dev/null @@ -1,34 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="{{ _charset }}" /> - <meta name="robots" content="noindex,nofollow" /> - <meta name="viewport" content="width=device-width,initial-scale=1" /> - <title>{% block title %}Symfony Profiler{% endblock %}</title> - <link rel="icon" type="image/x-icon" sizes="16x16" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAFEUlEQVR4AZVXA4wm2RMf27bXDM/+3/+sYBGfrbVtezc6BWtzfPbYXtvDL9906t6v0vWl05me7q1JzXuvvu4yXnvZgJ9hH6bwZYXLFR739vauUGuDwhq1L1N4Uv/tRYUhFjwcg49hn6aYr1V4TiGp86CoP9Oh1tV414KnM6t9fHymKUZ3DAI0hW4b1AyK3lE8phh5OxWeoJgUGhi5mLm95YzBwcHuhIQEV1JSEoWGhoKWHxYWFmenhJ/B5W0GwZpDt5Ovry9lZWWRyWOu5ORk7JsUpogsq5gnmISTU+HKQoLFQv/qq6/os88+I+EVFRUlSsRZ5oRiVmwlXMWShQkahUdERJCfnx/vd+3aRTU1NXTixAmqrq6mK1eu0PTp05mnrmD+QK6XhLO0XP2O2FJAQICRjjMU4P1PP/1EfX19NGfOHM8Z0N7ezueQkBBXYGAgSWIaQ5Em2T5QzFNSUig9PV3OHOe4uDjZ87p//34C7Nm7x/NcRUUFAX799Vec8Y7m7+8Pz92SfBDXr7VwPYRbxn/MmDG8Tps2jQBd3V30/PPPe35/6qmnaPXq1TR69Gg+h4eHiwwosdLT4dBkQDSXWmJiIq/vv/8+/fvvv3ThwgWqr6+n/Px8oyCmAerq6jy03Nxc2Yv7ySSjQzrmi4i92fVpaWlYOZ79/f2MW7dtpSlTptDp06epo6ODPvroI850ASiGdyZOnEjXrl2jyspKT4XA9cgjkaPL/D8UWG62HokieyQQoKSkRGiMs2bNotraWmprayOBNWvWyO+scGdnp5zF/WYvLEb8TwpRykp1MV7feust6uzqJMD169fpueeeY/rDDz/MKzzgdrsJoGkaffvtt/TFF19wQsIDmzZtssojt+6Fo1CgzKiAvAB3DRs2jAULtLS0eErPGB5Ad3c3lZaWUnFxMfeAd955h5+JjY3FaqXAPwhBnRCNySK4b98+Aoilv/z6i/zGggSk1g0opWupAMvGP91yt96zadWqVdTc3Ezz58/31LOAy+US6zgHBP766y+mDR8+HBUgFWSnQI2EAFnqlpcaGxsJIFkMN8L9AnPnzmX6jRs3SACeAi0vL888JwYPgTEJpauhnADo6/LSgQMHCHD37l2Cp15//XXq7eslgKb+Fi1exM9lZmbaCDclIcpQQhATE4OVsrOzuamg+cyePZuzG64Hrlu3jp9ZuWolCdy+fZueeOIJpkdHR1sLHqgM0Yh0bTRz1m7fvp2KiopYkYKCApo8ebLZIwzlFeXSOXEnsLPe2Ij+p5DbYYdOdOtDQ0rNjFya5sTcsGGDcTDZoXTcNoVBMoxWyzDS2yXmOyeUtGSskmDjx4/nRgPAfBDmMpZtUIbRcsi2GsfSD2QYyd2OcdmyZSSwdu1apuXk5GB16v4bak0yX0imyIUEgwNovFTglhMZGcm0srIy43zAVUxuTLbW4xn17Fci23wly9dngUummrTaixcvMpOtW7fiiBwQpqKYU9efHuxDJE5hC9wvL9TW1RLg+PHjPGTQ8wsLC4WpDC5Y5UR4k5qKMSLT6lqeAiX0nuAaMmSI9sMPP9CZM2foyJEj9O677wpTVIuTjidNp0HibvttoH9E5OMqbWKkSaNSlojldoLF7TEP+nUEmKI62y1kOBINbVaNarcI0PuGGUlHyfYvLHg7/jhFSFYqZh0P8KHSptd5ksOPU3tvqAEUot/hFmOIYJLp87wGe9Dwm95eg5xa/R8G6d8U5EcFhwAAAABJRU5ErkJggg=="> - - {% block head %} - <style{% if csp_style_nonce is defined and csp_style_nonce %} nonce="{{ csp_style_nonce }}"{% endif %}> - {{ include('@WebProfiler/Profiler/profiler.css.twig') }} - </style> - {% endblock %} - </head> - <body> - <script{% if csp_script_nonce is defined and csp_script_nonce %} nonce="{{ csp_script_nonce }}"{% endif %}> - if (null === localStorage.getItem('symfony/profiler/theme') || 'theme-auto' === localStorage.getItem('symfony/profiler/theme')) { - document.body.classList.add((matchMedia('(prefers-color-scheme: dark)').matches ? 'theme-dark' : 'theme-light')); - // needed to respond dynamically to OS changes without having to refresh the page - window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => { - document.body.classList.remove('theme-light', 'theme-dark'); - document.body.classList.add(e.matches ? 'theme-dark' : 'theme-light'); - }); - } else { - document.body.classList.add(localStorage.getItem('symfony/profiler/theme')); - } - - document.body.classList.add(localStorage.getItem('symfony/profiler/width') || 'width-normal'); - </script> - - {% block body '' %} - </body> -</html> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/base_js.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/base_js.html.twig deleted file mode 100644 index af36bc033..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/base_js.html.twig +++ /dev/null @@ -1,874 +0,0 @@ -{# This file is partially duplicated in src/Symfony/Component/ErrorHandler/Resources/assets/js/exception.js. - If you make any change in this file, verify the same change is needed in the other file. #} -<script{% if csp_script_nonce is defined and csp_script_nonce %} nonce="{{ csp_script_nonce }}"{% endif %}>/*<![CDATA[*/ - {# Caution: the contents of this file are processed by Twig before loading - them as JavaScript source code. Always use '/*' comments instead - of '//' comments to avoid impossible-to-debug side-effects #} - -if (typeof Sfjs === 'undefined' || typeof Sfjs.loadToolbar === 'undefined') { - Sfjs = (function() { - "use strict"; - - if ('classList' in document.documentElement) { - var hasClass = function (el, cssClass) { return el.classList.contains(cssClass); }; - var removeClass = function(el, cssClass) { el.classList.remove(cssClass); }; - var addClass = function(el, cssClass) { el.classList.add(cssClass); }; - var toggleClass = function(el, cssClass) { el.classList.toggle(cssClass); }; - } else { - var hasClass = function (el, cssClass) { return el.className.match(new RegExp('\\b' + cssClass + '\\b')); }; - var removeClass = function(el, cssClass) { el.className = el.className.replace(new RegExp('\\b' + cssClass + '\\b'), ' '); }; - var addClass = function(el, cssClass) { if (!hasClass(el, cssClass)) { el.className += " " + cssClass; } }; - var toggleClass = function(el, cssClass) { hasClass(el, cssClass) ? removeClass(el, cssClass) : addClass(el, cssClass); }; - } - - var noop = function() {}; - - var profilerStorageKey = 'symfony/profiler/'; - - var addEventListener; - - var el = document.createElement('div'); - if (!('addEventListener' in el)) { - addEventListener = function (element, eventName, callback) { - element.attachEvent('on' + eventName, callback); - }; - } else { - addEventListener = function (element, eventName, callback) { - element.addEventListener(eventName, callback, false); - }; - } - - if (navigator.clipboard) { - document.querySelectorAll('[data-clipboard-text]').forEach(function(element) { - removeClass(element, 'hidden'); - element.addEventListener('click', function() { - navigator.clipboard.writeText(element.getAttribute('data-clipboard-text')); - }) - }); - } - - var request = function(url, onSuccess, onError, payload, options, tries) { - var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); - options = options || {}; - options.retry = options.retry || false; - tries = tries || 1; - /* this delays for 125, 375, 625, 875, and 1000, ... */ - var delay = tries < 5 ? (tries - 0.5) * 250 : 1000; - - xhr.open(options.method || 'GET', url, true); - xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); - xhr.onreadystatechange = function(state) { - if (4 !== xhr.readyState) { - return null; - } - - if (xhr.status == 404 && options.retry && !options.stop) { - setTimeout(function() { - if (options.stop) { - return; - } - request(url, onSuccess, onError, payload, options, tries + 1); - }, delay); - - return null; - } - - if (200 === xhr.status) { - (onSuccess || noop)(xhr); - } else { - (onError || noop)(xhr); - } - }; - - if (options.onSend) { - options.onSend(tries); - } - - xhr.send(payload || ''); - }; - - var getPreference = function(name) { - if (!window.localStorage) { - return null; - } - - return localStorage.getItem(profilerStorageKey + name); - }; - - var setPreference = function(name, value) { - if (!window.localStorage) { - return null; - } - - localStorage.setItem(profilerStorageKey + name, value); - }; - - var requestStack = []; - - var extractHeaders = function(xhr, stackElement) { - /* Here we avoid to call xhr.getResponseHeader in order to */ - /* prevent polluting the console with CORS security errors */ - var allHeaders = xhr.getAllResponseHeaders(); - var ret; - - if (ret = allHeaders.match(/^x-debug-token:\s+(.*)$/im)) { - stackElement.profile = ret[1]; - } - if (ret = allHeaders.match(/^x-debug-token-link:\s+(.*)$/im)) { - stackElement.profilerUrl = ret[1]; - } - if (ret = allHeaders.match(/^Symfony-Debug-Toolbar-Replace:\s+(.*)$/im)) { - stackElement.toolbarReplaceFinished = false; - stackElement.toolbarReplace = '1' === ret[1]; - } - }; - - var successStreak = 4; - var pendingRequests = 0; - var renderAjaxRequests = function() { - var requestCounter = document.querySelector('.sf-toolbar-ajax-request-counter'); - if (!requestCounter) { - return; - } - requestCounter.textContent = requestStack.length; - - var infoSpan = document.querySelector(".sf-toolbar-ajax-info"); - if (infoSpan) { - infoSpan.textContent = requestStack.length + ' AJAX request' + (requestStack.length !== 1 ? 's' : ''); - } - - var ajaxToolbarPanel = document.querySelector('.sf-toolbar-block-ajax'); - if (requestStack.length) { - ajaxToolbarPanel.style.display = 'block'; - } else { - ajaxToolbarPanel.style.display = 'none'; - } - if (pendingRequests > 0) { - addClass(ajaxToolbarPanel, 'sf-ajax-request-loading'); - } else if (successStreak < 4) { - addClass(ajaxToolbarPanel, 'sf-toolbar-status-red'); - removeClass(ajaxToolbarPanel, 'sf-ajax-request-loading'); - } else { - removeClass(ajaxToolbarPanel, 'sf-ajax-request-loading'); - removeClass(ajaxToolbarPanel, 'sf-toolbar-status-red'); - } - }; - - var startAjaxRequest = function(index) { - var tbody = document.querySelector('.sf-toolbar-ajax-request-list'); - if (!tbody) { - return; - } - - var nbOfAjaxRequest = tbody.rows.length; - if (nbOfAjaxRequest >= 100) { - tbody.deleteRow(0); - } - - var request = requestStack[index]; - pendingRequests++; - var row = document.createElement('tr'); - request.DOMNode = row; - - var requestNumberCell = document.createElement('td'); - requestNumberCell.textContent = index + 1; - row.appendChild(requestNumberCell); - - var profilerCell = document.createElement('td'); - profilerCell.textContent = 'n/a'; - row.appendChild(profilerCell); - - var methodCell = document.createElement('td'); - methodCell.textContent = request.method; - row.appendChild(methodCell); - - var typeCell = document.createElement('td'); - typeCell.textContent = request.type; - row.appendChild(typeCell); - - var statusCodeCell = document.createElement('td'); - var statusCode = document.createElement('span'); - statusCode.textContent = 'n/a'; - statusCodeCell.appendChild(statusCode); - row.appendChild(statusCodeCell); - - var pathCell = document.createElement('td'); - pathCell.className = 'sf-ajax-request-url'; - if ('GET' === request.method) { - var pathLink = document.createElement('a'); - pathLink.setAttribute('href', request.url); - pathLink.textContent = request.url; - pathCell.appendChild(pathLink); - } else { - pathCell.textContent = request.url; - } - pathCell.setAttribute('title', request.url); - row.appendChild(pathCell); - - var durationCell = document.createElement('td'); - durationCell.className = 'sf-ajax-request-duration'; - durationCell.textContent = 'n/a'; - row.appendChild(durationCell); - - request.liveDurationHandle = setInterval(function() { - durationCell.textContent = (new Date() - request.start) + ' ms'; - }, 100); - - row.className = 'sf-ajax-request sf-ajax-request-loading'; - tbody.insertBefore(row, null); - - var toolbarInfo = document.querySelector('.sf-toolbar-block-ajax .sf-toolbar-info'); - toolbarInfo.scrollTop = toolbarInfo.scrollHeight; - - renderAjaxRequests(); - }; - - var finishAjaxRequest = function(index) { - var request = requestStack[index]; - clearInterval(request.liveDurationHandle); - - if (!request.DOMNode) { - return; - } - - if (request.toolbarReplace && !request.toolbarReplaceFinished && request.profile) { - /* Flag as complete because finishAjaxRequest can be called multiple times. */ - request.toolbarReplaceFinished = true; - /* Search up through the DOM to find the toolbar's container ID. */ - for (var elem = request.DOMNode; elem && elem !== document; elem = elem.parentNode) { - if (elem.id.match(/^sfwdt/)) { - Sfjs.loadToolbar(elem.id.replace(/^sfwdt/, ''), request.profile); - break; - } - } - } - - pendingRequests--; - var row = request.DOMNode; - /* Unpack the children from the row */ - var profilerCell = row.children[1]; - var methodCell = row.children[2]; - var statusCodeCell = row.children[4]; - var statusCodeElem = statusCodeCell.children[0]; - var durationCell = row.children[6]; - - if (request.error) { - row.className = 'sf-ajax-request sf-ajax-request-error'; - methodCell.className = 'sf-ajax-request-error'; - successStreak = 0; - } else { - row.className = 'sf-ajax-request sf-ajax-request-ok'; - successStreak++; - } - - if (request.statusCode) { - if (request.statusCode < 300) { - statusCodeElem.setAttribute('class', 'sf-toolbar-status'); - } else if (request.statusCode < 400) { - statusCodeElem.setAttribute('class', 'sf-toolbar-status sf-toolbar-status-yellow'); - } else { - statusCodeElem.setAttribute('class', 'sf-toolbar-status sf-toolbar-status-red'); - } - statusCodeElem.textContent = request.statusCode; - } else { - statusCodeElem.setAttribute('class', 'sf-toolbar-status sf-toolbar-status-red'); - } - - if (request.duration) { - durationCell.textContent = request.duration + ' ms'; - } - - if (request.profilerUrl) { - profilerCell.textContent = ''; - var profilerLink = document.createElement('a'); - profilerLink.setAttribute('href', request.profilerUrl); - profilerLink.textContent = request.profile; - profilerCell.appendChild(profilerLink); - } - - renderAjaxRequests(); - }; - - {% if excluded_ajax_paths is defined %} - if (window.fetch && window.fetch.polyfill === undefined) { - var oldFetch = window.fetch; - window.fetch = function () { - var promise = oldFetch.apply(this, arguments); - var url = arguments[0]; - var params = arguments[1]; - var paramType = Object.prototype.toString.call(arguments[0]); - if (paramType === '[object Request]') { - url = arguments[0].url; - params = { - method: arguments[0].method, - credentials: arguments[0].credentials, - headers: arguments[0].headers, - mode: arguments[0].mode, - redirect: arguments[0].redirect - }; - } else { - url = String(url); - } - if (!url.match(new RegExp({{ excluded_ajax_paths|json_encode|raw }}))) { - var method = 'GET'; - if (params && params.method !== undefined) { - method = params.method; - } - - var stackElement = { - error: false, - url: url, - method: method, - type: 'fetch', - start: new Date() - }; - - var idx = requestStack.push(stackElement) - 1; - promise.then(function (r) { - stackElement.duration = new Date() - stackElement.start; - stackElement.error = r.status < 200 || r.status >= 400; - stackElement.statusCode = r.status; - stackElement.profile = r.headers.get('x-debug-token'); - stackElement.profilerUrl = r.headers.get('x-debug-token-link'); - stackElement.toolbarReplaceFinished = false; - stackElement.toolbarReplace = '1' === r.headers.get('Symfony-Debug-Toolbar-Replace'); - finishAjaxRequest(idx); - }, function (e){ - stackElement.error = true; - finishAjaxRequest(idx); - }); - startAjaxRequest(idx); - } - - return promise; - }; - } - if (window.XMLHttpRequest && XMLHttpRequest.prototype.addEventListener) { - var proxied = XMLHttpRequest.prototype.open; - - XMLHttpRequest.prototype.open = function(method, url, async, user, pass) { - var self = this; - - /* prevent logging AJAX calls to static and inline files, like templates */ - var path = url; - if (url.slice(0, 1) === '/') { - if (0 === url.indexOf('{{ request.basePath|e('js') }}')) { - path = url.slice({{ request.basePath|length }}); - } - } - else if (0 === url.indexOf('{{ (request.schemeAndHttpHost ~ request.basePath)|e('js') }}')) { - path = url.slice({{ (request.schemeAndHttpHost ~ request.basePath)|length }}); - } - - if (!path.match(new RegExp({{ excluded_ajax_paths|json_encode|raw }}))) { - var stackElement = { - error: false, - url: url, - method: method, - type: 'xhr', - start: new Date() - }; - - var idx = requestStack.push(stackElement) - 1; - - this.addEventListener('readystatechange', function() { - if (self.readyState == 4) { - stackElement.duration = new Date() - stackElement.start; - stackElement.error = self.status < 200 || self.status >= 400; - stackElement.statusCode = self.status; - extractHeaders(self, stackElement); - - finishAjaxRequest(idx); - } - }, false); - - startAjaxRequest(idx); - } - - proxied.apply(this, Array.prototype.slice.call(arguments)); - }; - } - {% endif %} - - return { - hasClass: hasClass, - - removeClass: removeClass, - - addClass: addClass, - - toggleClass: toggleClass, - - getPreference: getPreference, - - setPreference: setPreference, - - addEventListener: addEventListener, - - request: request, - - renderAjaxRequests: renderAjaxRequests, - - getSfwdt: function(token) { - if (!this.sfwdt) { - this.sfwdt = document.getElementById('sfwdt' + token); - } - - return this.sfwdt; - }, - - load: function(selector, url, onSuccess, onError, options) { - var el = document.getElementById(selector); - - if (el && el.getAttribute('data-sfurl') !== url) { - request( - url, - function(xhr) { - el.innerHTML = xhr.responseText; - el.setAttribute('data-sfurl', url); - removeClass(el, 'loading'); - var pending = pendingRequests; - for (var i = 0; i < requestStack.length; i++) { - startAjaxRequest(i); - if (requestStack[i].duration) { - finishAjaxRequest(i); - } - } - /* Revert the pending state in case there was a start called without a finish above. */ - pendingRequests = pending; - (onSuccess || noop)(xhr, el); - }, - function(xhr) { (onError || noop)(xhr, el); }, - '', - options - ); - } - - return this; - }, - - showToolbar: function(token) { - var sfwdt = this.getSfwdt(token); - removeClass(sfwdt, 'sf-display-none'); - - if (getPreference('toolbar/displayState') == 'none') { - document.getElementById('sfToolbarMainContent-' + token).style.display = 'none'; - document.getElementById('sfToolbarClearer-' + token).style.display = 'none'; - document.getElementById('sfMiniToolbar-' + token).style.display = 'block'; - } else { - document.getElementById('sfToolbarMainContent-' + token).style.display = 'block'; - document.getElementById('sfToolbarClearer-' + token).style.display = 'block'; - document.getElementById('sfMiniToolbar-' + token).style.display = 'none'; - } - }, - - hideToolbar: function(token) { - var sfwdt = this.getSfwdt(token); - addClass(sfwdt, 'sf-display-none'); - }, - - initToolbar: function(token) { - this.showToolbar(token); - - var hideButton = document.getElementById('sfToolbarHideButton-' + token); - var hideButtonSvg = hideButton.querySelector('svg'); - hideButtonSvg.setAttribute('aria-hidden', 'true'); - hideButtonSvg.setAttribute('focusable', 'false'); - addEventListener(hideButton, 'click', function (event) { - event.preventDefault(); - - var p = this.parentNode; - p.style.display = 'none'; - (p.previousElementSibling || p.previousSibling).style.display = 'none'; - document.getElementById('sfMiniToolbar-' + token).style.display = 'block'; - setPreference('toolbar/displayState', 'none'); - }); - - var showButton = document.getElementById('sfToolbarMiniToggler-' + token); - var showButtonSvg = showButton.querySelector('svg'); - showButtonSvg.setAttribute('aria-hidden', 'true'); - showButtonSvg.setAttribute('focusable', 'false'); - addEventListener(showButton, 'click', function (event) { - event.preventDefault(); - - var elem = this.parentNode; - if (elem.style.display == 'none') { - document.getElementById('sfToolbarMainContent-' + token).style.display = 'none'; - document.getElementById('sfToolbarClearer-' + token).style.display = 'none'; - elem.style.display = 'block'; - } else { - document.getElementById('sfToolbarMainContent-' + token).style.display = 'block'; - document.getElementById('sfToolbarClearer-' + token).style.display = 'block'; - elem.style.display = 'none' - } - - setPreference('toolbar/displayState', 'block'); - }); - }, - - loadToolbar: function(token, newToken) { - var that = this; - var triesCounter = document.getElementById('sfLoadCounter-' + token); - - var options = { - retry: true, - onSend: function (count) { - if (count === 3) { - that.initToolbar(token); - } - - if (triesCounter) { - triesCounter.textContent = count; - } - }, - }; - - var cancelButton = document.getElementById('sfLoadCancel-' + token); - if (cancelButton) { - addEventListener(cancelButton, 'click', function (event) { - event.preventDefault(); - - options.stop = true; - that.hideToolbar(token); - }); - } - - newToken = (newToken || token); - - this.load( - 'sfwdt' + token, - '{{ url("_wdt", { "token": "xxxxxx" })|escape('js') }}'.replace(/xxxxxx/, newToken), - function(xhr, el) { - /* Do nothing in the edge case where the toolbar has already been replaced with a new one */ - if (!document.getElementById('sfToolbarMainContent-' + newToken)) { - return; - } - - /* Evaluate in global scope scripts embedded inside the toolbar */ - var i, scripts = [].slice.call(el.querySelectorAll('script')); - for (i = 0; i < scripts.length; ++i) { - eval.call({}, scripts[i].firstChild.nodeValue); - } - - el.style.display = -1 !== xhr.responseText.indexOf('sf-toolbarreset') ? 'block' : 'none'; - - if (el.style.display == 'none') { - return; - } - - that.initToolbar(newToken); - - /* Handle toolbar-info position */ - var toolbarBlocks = [].slice.call(el.querySelectorAll('.sf-toolbar-block')); - for (i = 0; i < toolbarBlocks.length; ++i) { - toolbarBlocks[i].onmouseover = function () { - var toolbarInfo = this.querySelectorAll('.sf-toolbar-info')[0]; - var pageWidth = document.body.clientWidth; - var elementWidth = toolbarInfo.offsetWidth; - var leftValue = (elementWidth + this.offsetLeft) - pageWidth; - var rightValue = (elementWidth + (pageWidth - this.offsetLeft)) - pageWidth; - - /* Reset right and left value, useful on window resize */ - toolbarInfo.style.right = ''; - toolbarInfo.style.left = ''; - - if (elementWidth > pageWidth) { - toolbarInfo.style.left = 0; - } - else if (leftValue > 0 && rightValue > 0) { - toolbarInfo.style.right = (rightValue * -1) + 'px'; - } else if (leftValue < 0) { - toolbarInfo.style.left = 0; - } else { - toolbarInfo.style.right = '0px'; - } - }; - } - - renderAjaxRequests(); - addEventListener(document.querySelector('.sf-toolbar-ajax-clear'), 'click', function() { - requestStack = []; - renderAjaxRequests(); - successStreak = 4; - document.querySelector('.sf-toolbar-ajax-request-list').innerHTML = ''; - }); - addEventListener(document.querySelector('.sf-toolbar-block-ajax'), 'mouseenter', function (event) { - var elem = document.querySelector('.sf-toolbar-block-ajax .sf-toolbar-info'); - elem.scrollTop = elem.scrollHeight; - }); - addEventListener(document.querySelector('.sf-toolbar-block-ajax > .sf-toolbar-icon'), 'click', function (event) { - event.preventDefault(); - - toggleClass(this.parentNode, 'hover'); - }); - - var dumpInfo = document.querySelector('.sf-toolbar-block-dump .sf-toolbar-info'); - if (null !== dumpInfo) { - addEventListener(dumpInfo, 'sfbeforedumpcollapse', function () { - dumpInfo.style.minHeight = dumpInfo.getBoundingClientRect().height+'px'; - }); - addEventListener(dumpInfo, 'mouseleave', function () { - dumpInfo.style.minHeight = ''; - }); - } - }, - function(xhr) { - if (xhr.status !== 0 && !options.stop) { - var sfwdt = that.getSfwdt(token); - sfwdt.innerHTML = '\ - <div class="sf-toolbarreset">\ - <div class="sf-toolbar-icon"><svg width="26" height="28" xmlns="http://www.w3.org/2000/svg" version="1.1" x="0px" y="0px" viewBox="0 0 26 28" enable-background="new 0 0 26 28" xml:space="preserve"><path fill="#FFFFFF" d="M13 0C5.8 0 0 5.8 0 13c0 7.2 5.8 13 13 13c7.2 0 13-5.8 13-13C26 5.8 20.2 0 13 0z M20 7.5 c-0.6 0-1-0.3-1-0.9c0-0.2 0-0.4 0.2-0.6c0.1-0.3 0.2-0.3 0.2-0.4c0-0.3-0.5-0.4-0.7-0.4c-2 0.1-2.5 2.7-2.9 4.8l-0.2 1.1 c1.1 0.2 1.9 0 2.4-0.3c0.6-0.4-0.2-0.8-0.1-1.3C18 9.2 18.4 9 18.7 8.9c0.5 0 0.8 0.5 0.8 1c0 0.8-1.1 2-3.3 1.9 c-0.3 0-0.5 0-0.7-0.1L15 14.1c-0.4 1.7-0.9 4.1-2.6 6.2c-1.5 1.8-3.1 2.1-3.8 2.1c-1.3 0-2.1-0.6-2.2-1.6c0-0.9 0.8-1.4 1.3-1.4 c0.7 0 1.2 0.5 1.2 1.1c0 0.5-0.2 0.6-0.4 0.7c-0.1 0.1-0.3 0.2-0.3 0.4c0 0.1 0.1 0.3 0.4 0.3c0.5 0 0.9-0.3 1.2-0.5 c1.3-1 1.7-2.9 2.4-6.2l0.1-0.8c0.2-1.1 0.5-2.3 0.8-3.5c-0.9-0.7-1.4-1.5-2.6-1.8c-0.8-0.2-1.3 0-1.7 0.4C8.4 10 8.6 10.7 9 11.1 l0.7 0.7c0.8 0.9 1.3 1.7 1.1 2.7c-0.3 1.6-2.1 2.8-4.3 2.1c-1.9-0.6-2.2-1.9-2-2.7c0.2-0.6 0.7-0.8 1.2-0.6 c0.5 0.2 0.7 0.8 0.6 1.3c0 0.1 0 0.1-0.1 0.3C6 15 5.9 15.2 5.9 15.3c-0.1 0.4 0.4 0.7 0.8 0.8c0.8 0.3 1.7-0.2 1.9-0.9 c0.2-0.6-0.2-1.1-0.4-1.2l-0.8-0.9c-0.4-0.4-1.2-1.5-0.8-2.8c0.2-0.5 0.5-1 0.9-1.4c1-0.7 2-0.8 3-0.6c1.3 0.4 1.9 1.2 2.8 1.9 c0.5-1.3 1.1-2.6 2-3.8c0.9-1 2-1.7 3.3-1.8C20 4.8 21 5.4 21 6.3C21 6.7 20.8 7.5 20 7.5z"/></svg></div>\ - An error occurred while loading the web debug toolbar. <a href="{{ url("_profiler_home")|escape('js') }}' + newToken + '>Open the web profiler.</a>\ - </div>\ - '; - sfwdt.setAttribute('class', 'sf-toolbar sf-error-toolbar'); - } - }, - options - ); - - return this; - }, - - toggle: function(selector, elOn, elOff) { - var tmp = elOn.style.display, - el = document.getElementById(selector); - - elOn.style.display = elOff.style.display; - elOff.style.display = tmp; - - if (el) { - el.style.display = 'none' === tmp ? 'none' : 'block'; - } - - return this; - }, - - createTabs: function() { - var tabGroups = document.querySelectorAll('.sf-tabs:not([data-processed=true])'); - - /* create the tab navigation for each group of tabs */ - for (var i = 0; i < tabGroups.length; i++) { - var tabs = tabGroups[i].querySelectorAll(':scope > .tab'); - var tabNavigation = document.createElement('ul'); - tabNavigation.className = 'tab-navigation'; - - var selectedTabId = 'tab-' + i + '-0'; /* select the first tab by default */ - for (var j = 0; j < tabs.length; j++) { - var tabId = 'tab-' + i + '-' + j; - var tabTitle = tabs[j].querySelector('.tab-title').innerHTML; - - var tabNavigationItem = document.createElement('li'); - tabNavigationItem.setAttribute('data-tab-id', tabId); - if (hasClass(tabs[j], 'active')) { selectedTabId = tabId; } - if (hasClass(tabs[j], 'disabled')) { addClass(tabNavigationItem, 'disabled'); } - tabNavigationItem.innerHTML = tabTitle; - tabNavigation.appendChild(tabNavigationItem); - - var tabContent = tabs[j].querySelector('.tab-content'); - tabContent.parentElement.setAttribute('id', tabId); - } - - tabGroups[i].insertBefore(tabNavigation, tabGroups[i].firstChild); - addClass(document.querySelector('[data-tab-id="' + selectedTabId + '"]'), 'active'); - } - - /* display the active tab and add the 'click' event listeners */ - for (i = 0; i < tabGroups.length; i++) { - tabNavigation = tabGroups[i].querySelectorAll(':scope > .tab-navigation li'); - - for (j = 0; j < tabNavigation.length; j++) { - tabId = tabNavigation[j].getAttribute('data-tab-id'); - document.getElementById(tabId).querySelector('.tab-title').className = 'hidden'; - - if (hasClass(tabNavigation[j], 'active')) { - document.getElementById(tabId).className = 'block'; - } else { - document.getElementById(tabId).className = 'hidden'; - } - - tabNavigation[j].addEventListener('click', function(e) { - var activeTab = e.target || e.srcElement; - - /* needed because when the tab contains HTML contents, user can click */ - /* on any of those elements instead of their parent '<li>' element */ - while (activeTab.tagName.toLowerCase() !== 'li') { - activeTab = activeTab.parentNode; - } - - /* get the full list of tabs through the parent of the active tab element */ - var tabNavigation = activeTab.parentNode.children; - for (var k = 0; k < tabNavigation.length; k++) { - var tabId = tabNavigation[k].getAttribute('data-tab-id'); - document.getElementById(tabId).className = 'hidden'; - removeClass(tabNavigation[k], 'active'); - } - - addClass(activeTab, 'active'); - var activeTabId = activeTab.getAttribute('data-tab-id'); - document.getElementById(activeTabId).className = 'block'; - }); - } - - tabGroups[i].setAttribute('data-processed', 'true'); - } - }, - - createToggles: function() { - var toggles = document.querySelectorAll('.sf-toggle:not([data-processed=true])'); - - for (var i = 0; i < toggles.length; i++) { - var elementSelector = toggles[i].getAttribute('data-toggle-selector'); - var element = document.querySelector(elementSelector); - - addClass(element, 'sf-toggle-content'); - - if (toggles[i].hasAttribute('data-toggle-initial') && toggles[i].getAttribute('data-toggle-initial') == 'display') { - addClass(toggles[i], 'sf-toggle-on'); - addClass(element, 'sf-toggle-visible'); - } else { - addClass(toggles[i], 'sf-toggle-off'); - addClass(element, 'sf-toggle-hidden'); - } - - addEventListener(toggles[i], 'click', function(e) { - e.preventDefault(); - - if ('' !== window.getSelection().toString()) { - /* Don't do anything on text selection */ - return; - } - - var toggle = e.target || e.srcElement; - - /* needed because when the toggle contains HTML contents, user can click */ - /* on any of those elements instead of their parent '.sf-toggle' element */ - while (!hasClass(toggle, 'sf-toggle')) { - toggle = toggle.parentNode; - } - - var element = document.querySelector(toggle.getAttribute('data-toggle-selector')); - - toggleClass(toggle, 'sf-toggle-on'); - toggleClass(toggle, 'sf-toggle-off'); - toggleClass(element, 'sf-toggle-hidden'); - toggleClass(element, 'sf-toggle-visible'); - - /* the toggle doesn't change its contents when clicking on it */ - if (!toggle.hasAttribute('data-toggle-alt-content')) { - return; - } - - if (!toggle.hasAttribute('data-toggle-original-content')) { - toggle.setAttribute('data-toggle-original-content', toggle.innerHTML); - } - - var currentContent = toggle.innerHTML; - var originalContent = toggle.getAttribute('data-toggle-original-content'); - var altContent = toggle.getAttribute('data-toggle-alt-content'); - toggle.innerHTML = currentContent !== altContent ? altContent : originalContent; - }); - - /* Prevents from disallowing clicks on links inside toggles */ - var toggleLinks = toggles[i].querySelectorAll('a'); - for (var j = 0; j < toggleLinks.length; j++) { - addEventListener(toggleLinks[j], 'click', function(e) { - e.stopPropagation(); - }); - } - - /* Prevents from disallowing clicks on "copy to clipboard" elements inside toggles */ - var copyToClipboardElements = toggles[i].querySelectorAll('span[data-clipboard-text]'); - for (var k = 0; k < copyToClipboardElements.length; k++) { - addEventListener(copyToClipboardElements[k], 'click', function(e) { - e.stopPropagation(); - }); - } - - toggles[i].setAttribute('data-processed', 'true'); - } - }, - - initializeLogsTable: function() { - Sfjs.updateLogsTable(); - - document.querySelectorAll('.log-filter input').forEach((input) => { - input.addEventListener('change', () => { Sfjs.updateLogsTable(); }); - }); - - document.querySelectorAll('.filter-select-all-or-none button').forEach((link) => { - link.addEventListener('click', () => { - const selectAll = link.classList.contains('select-all'); - link.closest('.log-filter-content').querySelectorAll('input').forEach((input) => { - input.checked = selectAll; - }); - - Sfjs.updateLogsTable(); - }); - }); - - document.body.addEventListener('click', (event) => { - document.querySelectorAll('details.log-filter').forEach((filterElement) => { - if (!filterElement.contains(event.target) && filterElement.open) { - filterElement.open = false; - } - }); - }); - }, - - updateLogsTable: function() { - const selectedType = document.querySelector('#log-filter-type input:checked').value; - const priorities = document.querySelectorAll('#log-filter-priority input'); - const allPriorities = Array.from(priorities).map((input) => input.value); - const selectedPriorities = Array.from(priorities).filter((input) => input.checked).map((input) => input.value); - const channels = document.querySelectorAll('#log-filter-channel input'); - const selectedChannels = Array.from(channels).filter((input) => input.checked).map((input) => input.value); - - const logs = document.querySelector('table.logs'); - if (null === logs) { - return; - } - - /* hide rows that don't match the current filters */ - let numVisibleRows = 0; - logs.querySelectorAll('tbody tr').forEach((row) => { - if ('all' !== selectedType && selectedType !== row.getAttribute('data-type')) { - row.style.display = 'none'; - return; - } - - const priority = row.getAttribute('data-priority'); - if (false === selectedPriorities.includes(priority) && true === allPriorities.includes(priority)) { - row.style.display = 'none'; - return; - } - - if ('' !== row.getAttribute('data-channel') && false === selectedChannels.includes(row.getAttribute('data-channel'))) { - row.style.display = 'none'; - return; - } - - row.style.display = 'table-row'; - numVisibleRows++; - }); - - document.querySelector('table.logs').style.display = 0 === numVisibleRows ? 'none' : 'table'; - document.querySelector('.no-logs-message').style.display = 0 === numVisibleRows ? 'block' : 'none'; - - /* update the selected totals of all filters */ - document.querySelector('#log-filter-priority .filter-active-num').innerText = (priorities.length === selectedPriorities.length) ? 'All' : selectedPriorities.length; - document.querySelector('#log-filter-channel .filter-active-num').innerText = (channels.length === selectedChannels.length) ? 'All' : selectedChannels.length; - - /* update the currently selected "log type" tab */ - document.querySelectorAll('#log-filter-type li').forEach((tab) => tab.classList.remove('active')); - document.querySelector(`#log-filter-type input[value="${selectedType}"]`).parentElement.classList.add('active'); - }, - }; - })(); - - Sfjs.addEventListener(document, 'DOMContentLoaded', function() { - Sfjs.createTabs(); - Sfjs.createToggles(); - }); -} -/*]]>*/</script> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/cancel.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/cancel.html.twig deleted file mode 100644 index 6f1763d3a..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/cancel.html.twig +++ /dev/null @@ -1,25 +0,0 @@ -{% block toolbar %} - {% set icon %} - {{ include('@WebProfiler/Icon/symfony.svg') }} - - <span class="sf-toolbar-value sf-toolbar-ajax-request-counter"> - Loading&hellip; - </span> - {% endset %} - - {% set text %} - <div class="sf-toolbar-info-piece"> - <b>Loading the web debug toolbar&hellip;</b> - </div> - <div class="sf-toolbar-info-piece"> - Attempt #<span id="sfLoadCounter-{{ token }}"></span> - </div> - <div class="sf-toolbar-info-piece"> - <b> - <button class="sf-cancel-button" type="button" id="sfLoadCancel-{{ token }}" title="Cancel loading">Cancel</button> - </b> - </div> - {% endset %} - - {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url }) }} -{% endblock %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/header.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/header.html.twig deleted file mode 100644 index d04cf37e6..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/header.html.twig +++ /dev/null @@ -1,14 +0,0 @@ -<div id="header"> - <div class="container"> - <h1>{{ include('@WebProfiler/Icon/symfony.svg') }} Symfony <span>Profiler</span></h1> - - <div class="search"> - <form method="get" action="https://symfony.com/search" target="_blank"> - <div class="form-row"> - <input name="q" id="search-id" type="search" placeholder="search on symfony.com"> - <button type="submit" class="btn">Search</button> - </div> - </form> - </div> - </div> -</div> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/info.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/info.html.twig deleted file mode 100644 index 43404393e..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/info.html.twig +++ /dev/null @@ -1,22 +0,0 @@ -{% extends '@WebProfiler/Profiler/layout.html.twig' %} - -{% set messages = { - 'no_token' : { - status: 'error', - title: (token|default('') == 'latest') ? 'There are no profiles' : 'Token not found', - message: (token|default('') == 'latest') ? 'No profiles found.' : 'Token "' ~ token|default('') ~ '" not found.' - } -} %} - -{% block summary %} - <div class="status status-{{ messages[about].status }}"> - <div class="container"> - <h2>{{ messages[about].status|title }}</h2> - </div> - </div> -{% endblock %} - -{% block panel %} - <h2>{{ messages[about].title }}</h2> - <p>{{ messages[about].message }}</p> -{% endblock %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/layout.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/layout.html.twig deleted file mode 100644 index 00c64cadf..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/layout.html.twig +++ /dev/null @@ -1,153 +0,0 @@ -{% extends '@WebProfiler/Profiler/base.html.twig' %} - -{% block body %} - {{ include('@WebProfiler/Profiler/header.html.twig', with_context = false) }} - - <div id="summary"> - {% block summary %} - {% if profile is defined %} - {% set request_collector = profile.collectors.request|default(false) %} - {% set status_code = request_collector ? request_collector.statuscode|default(0) : 0 %} - {% set css_class = status_code > 399 ? 'status-error' : status_code > 299 ? 'status-warning' : 'status-success' %} - - <div class="status {{ css_class }}"> - <div class="container"> - <h2 class="break-long-words"> - {% if profile.method|upper in ['GET', 'HEAD'] %} - <a href="{{ profile.url }}">{{ profile.url }}</a> - {% else %} - {{ profile.url }} - {% set referer = request_collector ? request_collector.requestheaders.get('referer') : null %} - {% if referer %} - <a href="{{ referer }}" class="referer">Return to referer URL</a> - {% endif %} - {% endif %} - </h2> - - {% if request_collector and request_collector.redirect -%} - {%- set redirect = request_collector.redirect -%} - {%- set controller = redirect.controller -%} - {%- set redirect_route = '@' ~ redirect.route %} - <dl class="metadata"> - <dt> - <span class="label">{{ redirect.status_code }}</span> - Redirect from - </dt> - <dd> - {{ 'GET' != redirect.method ? redirect.method }} - {% if redirect.controller.class is defined -%} - {%- set link = controller.file|file_link(controller.line) -%} - {% if link %}<a href="{{ link }}" title="{{ controller.file }}">{% endif -%} - {{ redirect_route }} - {%- if link %}</a>{% endif -%} - {%- else -%} - {{ redirect_route }} - {%- endif %} - (<a href="{{ path('_profiler', { token: redirect.token, panel: request.query.get('panel', 'request') }) }}">{{ redirect.token }}</a>) - </dd> - </dl> - {%- endif %} - - {% if request_collector and request_collector.forwardtoken -%} - {% set forward_profile = profile.childByToken(request_collector.forwardtoken) %} - {% set controller = forward_profile ? forward_profile.collector('request').controller : 'n/a' %} - <dl class="metadata"> - <dt>Forwarded to</dt> - <dd> - {% set link = controller.file is defined ? controller.file|file_link(controller.line) : null -%} - {%- if link %}<a href="{{ link }}" title="{{ controller.file }}">{% endif -%} - {% if controller.class is defined %} - {{- controller.class|abbr_class|striptags -}} - {{- controller.method ? ' :: ' ~ controller.method -}} - {% else %} - {{- controller -}} - {% endif %} - {%- if link %}</a>{% endif %} - (<a href="{{ path('_profiler', { token: request_collector.forwardtoken }) }}">{{ request_collector.forwardtoken }}</a>) - </dd> - </dl> - {%- endif %} - - <dl class="metadata"> - <dt>Method</dt> - <dd>{{ profile.method|upper }}</dd> - - <dt>HTTP Status</dt> - <dd>{{ status_code }}</dd> - - <dt>IP</dt> - <dd> - <a href="{{ path('_profiler_search_results', { token: token, limit: 10, ip: profile.ip }) }}">{{ profile.ip }}</a> - </dd> - - <dt>Profiled on</dt> - <dd><time datetime="{{ profile.time|date('c') }}">{{ profile.time|date('r') }}</time></dd> - - <dt>Token</dt> - <dd>{{ profile.token }}</dd> - </dl> - </div> - </div> - {% endif %} - {% endblock %} - </div> - - <div id="content" class="container"> - <div id="main"> - <div id="sidebar"> - <div id="sidebar-shortcuts"> - <div class="shortcuts"> - <a href="#" id="sidebarShortcutsMenu" class="visible-small"> - <span class="icon">{{ include('@WebProfiler/Icon/menu.svg') }}</span> - </a> - - <a class="btn btn-sm" href="{{ path('_profiler_search', { limit: 10 }) }}">Last 10</a> - <a class="btn btn-sm" href="{{ path('_profiler', { token: 'latest' }|merge(request.query.all)) }}">Latest</a> - - <a class="sf-toggle btn btn-sm" data-toggle-selector="#sidebar-search" {% if tokens is defined or about is defined %}data-toggle-initial="display"{% endif %}> - {{ include('@WebProfiler/Icon/search.svg') }} <span class="hidden-small">Search</span> - </a> - - {{ render(controller('web_profiler.controller.profiler::searchBarAction', query=request.query.all)) }} - </div> - </div> - - {% if templates is defined %} - <ul id="menu-profiler"> - {% for name, template in templates %} - {% set menu -%} - {%- if block('menu', template) is defined -%} - {% with { collector: profile.getcollector(name), profiler_markup_version: profiler_markup_version } %} - {{- block('menu', template) -}} - {% endwith %} - {%- endif -%} - {%- endset %} - {% if menu is not empty %} - <li class="{{ name }} {{ name == panel ? 'selected' }}"> - <a href="{{ path('_profiler', { token: token, panel: name }) }}">{{ menu|raw }}</a> - </li> - {% endif %} - {% endfor %} - </ul> - {% endif %} - - {{ include('@WebProfiler/Profiler/settings.html.twig') }} - </div> - - <div id="collector-wrapper"> - <div id="collector-content"> - {{ include('@WebProfiler/Profiler/base_js.html.twig') }} - {% block panel '' %} - </div> - </div> - </div> - </div> - <script> - (function () { - Sfjs.addEventListener(document.getElementById('sidebarShortcutsMenu'), 'click', function (event) { - event.preventDefault(); - Sfjs.toggleClass(document.getElementById('sidebar'), 'expanded'); - }) - }()); - </script> -{% endblock %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/open.css.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/open.css.twig deleted file mode 100644 index 747d73f5d..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/open.css.twig +++ /dev/null @@ -1,79 +0,0 @@ -{# Mixins - ========================================================================= #} -{% set mixins = { - 'break_long_words': '-ms-word-break: break-all; word-break: break-all; word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto;', - 'monospace_font': 'font-family: monospace; font-size: 13px; font-size-adjust: 0.5;', - 'sans_serif_font': 'font-family: Helvetica, Arial, sans-serif;', - 'subtle_border_and_shadow': 'background: #FFF; border: 1px solid #E0E0E0; box-shadow: 0px 0px 1px rgba(128, 128, 128, .2);' -} %} - -{# Normalization - (normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css) - ========================================================================= #} -html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0} - -{# Basic styles - ========================================================================= #} -html, body { - height: 100%; - width: 100%; -} -body { - background-color: #F9F9F9; - color: #aaa; - display: flex; - flex-direction: column; - {{ mixins.sans_serif_font|raw }} - font-size: 14px; - line-height: 1.4; -} -.header { - background-color: #222; - position: fixed; - top: 0; - display: flex; - width: 100%; -} -.header h1 { - color: #FFF; - font-weight: normal; - font-size: 21px; - margin: 0; - padding: 10px 10px 8px; - word-break: break-all; -} - -a.doc { - color: #FFF; - text-decoration: none; - margin: auto; - margin-right: 10px; -} - -a.doc:hover { - text-decoration: underline; -} - -.empty { - padding: 10px; - color: #555; -} - -.source { - margin-top: 41px; -} - -.source li code { - color: #555; -} - -.source li.selected { - background: rgba(255, 255, 153, 0.5); -} - -.anchor { - position: relative; - display: inline-block; - top: -7em; - visibility: hidden; -} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/open.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/open.html.twig deleted file mode 100644 index ba94bc0ef..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/open.html.twig +++ /dev/null @@ -1,22 +0,0 @@ -{% extends '@WebProfiler/Profiler/base.html.twig' %} - -{% block head %} - <style> - {{ include('@WebProfiler/Profiler/open.css.twig') }} - </style> -{% endblock %} - -{% block body %} - {% set source = filename|file_excerpt(line, -1) %} - <div class="header"> - <h1>{{ file }}{% if 0 < line %} <small>line {{ line }}</small>{% endif %}</h1> - <a class="doc" href="https://symfony.com/doc/{{ constant('Symfony\\Component\\HttpKernel\\Kernel::VERSION') }}/reference/configuration/framework.html#ide" rel="help">Open in your IDE?</a> - </div> - <div class="source"> - {% if source is null %} - <p class="empty">The file is not readable.</p> - {% else %} - {{ source|raw }} - {% endif %} - </div> -{% endblock %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/profiler.css.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/profiler.css.twig deleted file mode 100644 index 24ec0863d..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/profiler.css.twig +++ /dev/null @@ -1,1479 +0,0 @@ -{# This file is partially duplicated in TwigBundle/Resources/views/exceotion.css.twig. - If you make any change in this file, verify the same change is needed in the other file. #} -{# Normalization - (normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css) - ========================================================================= #} -*{-webkit-box-sizing: border-box;-moz-box-sizing: border-box;box-sizing: border-box}html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0} - -:root { - --font-sans-serif: Helvetica, Arial, sans-serif; - --page-background: #f9f9f9; - --color-text: #222; - --color-muted: #999; - --color-link: #218BC3; - /* when updating any of these colors, do the same in toolbar.css.twig */ - --color-success: #4f805d; - --color-warning: #a46a1f; - --color-error: #b0413e; - --badge-background: #f5f5f5; - --badge-color: #666; - --badge-warning-background: #FEF3C7; - --badge-warning-color: #B45309; - --badge-danger-background: #FEE2E2; - --badge-danger-color: #B91C1C; - --tab-background: #fff; - --tab-color: #444; - --tab-active-background: #666; - --tab-active-color: #fafafa; - --tab-disabled-background: #f5f5f5; - --tab-disabled-color: #999; - --log-filter-button-background: #fff; - --log-filter-button-border: #999; - --log-filter-button-color: #555; - --log-filter-active-num-color: #2563EB; - --log-timestamp-color: #555; - --metric-value-background: #fff; - --metric-value-color: inherit; - --metric-unit-color: #999; - --metric-label-background: #e0e0e0; - --metric-label-color: inherit; - --trace-selected-background: #F7E5A1; - --table-border: #e0e0e0; - --table-background: #fff; - --table-header: #e0e0e0; - --info-background: #ddf; - --tree-active-background: #F7E5A1; - --exception-title-color: var(--base-2); - --shadow: 0px 0px 1px rgba(128, 128, 128, .2); - --border: 1px solid #e0e0e0; - --background-error: var(--color-error); - --highlight-comment: #969896; - --highlight-default: #222222; - --highlight-keyword: #a71d5d; - --highlight-string: #183691; - --highlight-selected-line: rgba(255, 255, 153, 0.5); - --base-0: #fff; - --base-1: #f5f5f5; - --base-2: #e0e0e0; - --base-3: #ccc; - --base-4: #666; - --base-5: #444; - --base-6: #222; - --card-label-background: #eee; - --card-label-color: var(--base-6); -} - -.theme-dark { - --page-background: #36393e; - --color-text: #e0e0e0; - --color-muted: #777; - --color-link: #93C5FD; - --color-error: #d43934; - --badge-background: #555; - --badge-color: #ddd; - --badge-warning-background: #B45309; - --badge-warning-color: #FEF3C7; - --badge-danger-background: #B91C1C; - --badge-danger-color: #FEE2E2; - --tab-background: #555; - --tab-color: #ccc; - --tab-active-background: #888; - --tab-active-color: #fafafa; - --tab-disabled-background: var(--page-background); - --tab-disabled-color: #777; - --log-filter-button-background: #555; - --log-filter-button-border: #999; - --log-filter-button-color: #ccc; - --log-filter-active-num-color: #93C5FD; - --log-timestamp-color: #ccc; - --metric-value-background: #555; - --metric-value-color: inherit; - --metric-unit-color: #999; - --metric-label-background: #777; - --metric-label-color: #e0e0e0; - --trace-selected-background: #71663acc; - --table-border: #444; - --table-background: #333; - --table-header: #555; - --info-background: rgba(79, 148, 195, 0.5); - --tree-active-background: var(--metric-label-background); - --exception-title-color: var(--base-2); - --shadow: 0px 0px 1px rgba(32, 32, 32, .2); - --border: 1px solid #666; - --background-error: #b0413e; - --highlight-comment: #dedede; - --highlight-default: var(--base-6); - --highlight-keyword: #ff413c; - --highlight-string: #70a6fd; - --highlight-selected-line: rgba(14, 14, 14, 0.5); - --base-0: #2e3136; - --base-1: #444; - --base-2: #666; - --base-3: #666; - --base-4: #666; - --base-5: #e0e0e0; - --base-6: #f5f5f5; - --card-label-background: var(--tab-active-background); - --card-label-color: var(--tab-active-color); -} - -{# Basic styles - ========================================================================= #} -html, body { - height: 100%; - width: 100%; -} -body { - background-color: var(--page-background); - color: var(--base-6); - display: flex; - flex-direction: column; - font-family: var(--font-sans-serif); - font-size: 14px; - line-height: 1.4; -} - -h2, h3, h4 { - font-weight: 500; - margin: 1.5em 0 .5em; -} -h2 + h3, -h3 + h4 { - margin-top: 1em; -} -h2 { - font-size: 24px; -} -h3 { - font-size: 21px; -} -h4 { - font-size: 18px; -} -h2 span, h3 span, h4 span, -h2 small, h3 small, h4 small { - color: var(--color-muted); -} - -li { - margin-bottom: 10px; -} - -p { - font-size: 16px; - margin-bottom: 1em; -} - -a { - color: var(--color-link); - text-decoration: none; -} -a:hover { - text-decoration: underline; -} -a.link-inverse { - text-decoration: underline; -} -a.link-inverse:hover { - text-decoration: none; -} -a:active, -a:hover { - outline: 0; -} -h2 a, -h3 a, -h4 a { - text-decoration: underline; -} -h2 a:hover, -h3 a:hover, -h4 a:hover { - text-decoration: none; -} - -abbr { - border-bottom: 1px dotted var(--base-5); - cursor: help; -} - -code, pre { - font-family: monospace; - font-size: 13px; -} - -{# Buttons (the colors of this element don't change based on the selected theme) - ------------------------------------------------------------------------- #} -button { - font-family: var(--font-sans-serif); -} -.btn { - background: #777; - border-radius: 2px; - border: 0; - color: #f5f5f5; - display: inline-block; - padding: .5em .75em; -} -.btn:hover { - cursor: pointer; - opacity: 0.8; - text-decoration: none; -} -.btn-sm { - font-size: 12px; -} -.btn-sm svg { - height: 16px; - width: 16px; - vertical-align: middle; -} -.btn-link { - border-color: transparent; - color: var(--color-link); - text-decoration: none; - background-color: transparent; - outline: none; - border: 0; - padding: 0; - cursor: pointer; -} -.btn-link:hover { - text-decoration: underline; -} -{# Tables - ------------------------------------------------------------------------- #} -table, tr, th, td { - background: var(--table-background); - border-collapse: collapse; - line-height: 1.5; - vertical-align: top; -} -table { - background: var(--base-0); - border: var(--border); - box-shadow: var(--shadow); - margin: 1em 0; - width: 100%; -} - -table th, table td { - padding: 8px 10px; -} - -table th { - font-weight: bold; - text-align: left; -} -table thead th { - background-color: var(--table-header); -} -table thead th.key { - width: 19%; -} -table thead.small th { - font-size: 12px; - padding: 4px 10px; -} - -table tbody th, -table tbody td { - border: 1px solid var(--base-2); - border-width: 1px 0; - font-family: monospace; - font-size: 13px; -} - -table tbody div { - margin: .25em 0; -} -table tbody ul { - margin: 0; - padding: 0 0 0 1em; -} - -table thead th.num-col, -table tbody td.num-col { - text-align: center; -} - -{# Utility classes - ========================================================================= #} -.block { - display: block; -} -.full-width { - width: 100%; -} -.hidden { - display: none; -} -.nowrap { - white-space: pre; -} -.prewrap { - white-space: pre-wrap; -} -.newline { - display: block; -} -.break-long-words { - -ms-word-break: break-all; - word-break: break-all; - word-break: break-word; - -webkit-hyphens: auto; - -moz-hyphens: auto; - hyphens: auto; -} -.text-small { - font-size: 12px !important; -} -.text-muted { - color: var(--color-muted); -} -.text-danger { - color: var(--color-error); -} -.text-bold { - font-weight: bold; -} -.text-right { - text-align: right; -} -.text-center { - text-align: center; -} -.font-normal { - font-family: var(--font-sans-serif); - font-size: 14px; -} -.help { - color: var(--color-muted); - font-size: 14px; - margin-bottom: .5em; -} -.empty { - border: 4px dashed var(--base-2); - color: var(--color-muted); - margin: 1em 0; - padding: .5em 2em; -} - -.label { - background-color: var(--base-4); - color: #FAFAFA; - display: inline-block; - font-size: 12px; - font-weight: bold; - padding: 3px 7px; - white-space: nowrap; -} -.label.same-width { - min-width: 70px; - text-align: center; -} -.label.status-success { background: var(--color-success); color: #FFF; } -.label.status-warning { background: var(--color-warning); color: #FFF; } -.label.status-error { background: var(--background-error); color: #FFF; } - -{# Metrics - ------------------------------------------------------------------------- #} -.metrics { - margin: 1em 0 0; - overflow: auto; -} -.metrics .metric { - float: left; - margin: 0 1em 1em 0; -} - -.metric { - background: var(--metric-value-background); - border: 1px solid var(--table-border); - box-shadow: var(--shadow); - color: var(--metric-value-color); - min-width: 100px; - min-height: 70px; -} -.metric .value { - display: block; - font-size: 28px; - padding: 8px 15px 4px; - text-align: center; -} -.metric .value svg { - margin: 5px 0 -5px; -} -.metric .unit { - color: var(--metric-unit-color); - font-size: 18px; - margin-left: -4px; -} -.metric .label { - background: var(--metric-label-background); - color: var(--metric-label-color); - display: block; - font-size: 12px; - padding: 5px; - text-align: center; -} - -.metrics-horizontal .metric { - min-height: 0; - min-width: 0; -} -.metrics-horizontal .metric .value, -.metrics-horizontal .metric .label { - display: inline; - padding: 2px 6px; -} -.metrics-horizontal .metric .label { - display: inline-block; - padding: 6px; -} -.metrics-horizontal .metric .value { - font-size: 16px; -} -.metrics-horizontal .metric .value svg { - max-height: 14px; - line-height: 10px; - margin: 0; - padding-left: 4px; - vertical-align: middle; -} - -.metric-divider { - float: left; - margin: 0 1em; - min-height: 1px; {# required to apply 'margin' to an empty 'div' #} -} - -{# Cards - ------------------------------------------------------------------------- #} -.card { - background: var(--base-0); - border: var(--border); - box-shadow: var(--shadow); - margin: 1em 0; - padding: 10px; -} -.card-block + .card-block { - border-top: 1px solid var(--base-2); - padding-top: 10px; -} -.card *:first-child, -.card-block *:first-child { - margin-top: 0; -} -.card .label { - background-color: var(--card-label-background); - color: var(--card-label-color); -} - -{# Status - ------------------------------------------------------------------------- #} -.status-success { - background: rgba(94, 151, 110, 0.3); -} -.status-warning { - background: rgba(240, 181, 24, 0.3); -} -.status-error { - background: rgba(176, 65, 62, 0.2); -} -.status-success td, -.status-warning td, -.status-error td { - background: transparent; -} -tr.status-error td, -tr.status-warning td { - border-bottom: 1px solid var(--base-2); - border-top: 1px solid var(--base-2); -} - -.status-warning .colored { - color: var(--color-warning); -} -.status-error .colored { - color: var(--color-error); -} - -{# Syntax highlighting - ========================================================================= #} -.highlight pre { - margin: 0; - white-space: pre-wrap; -} - -.highlight .keyword { color: #8959A8; font-weight: bold; } -.highlight .word { color: var(--color-text); } -.highlight .variable { color: #916319; } -.highlight .symbol { color: var(--color-text); } -.highlight .comment { color: #999999; } -.highlight .backtick { color: #718C00; } -.highlight .string { color: #718C00; } -.highlight .number { color: #F5871F; font-weight: bold; } -.highlight .error { color: #C82829; } - -{# Icons - ========================================================================= #} -.sf-icon { - vertical-align: middle; - background-repeat: no-repeat; - background-size: contain; - width: 16px; - height: 16px; - display: inline-block; -} -.sf-icon svg { - width: 16px; - height: 16px; -} -.sf-icon.sf-medium, -.sf-icon.sf-medium svg { - width: 24px; - height: 24px; -} -.sf-icon.sf-large, -.sf-icon.sf-large svg { - width: 32px; - height: 32px; -} - - -{# Layout - ========================================================================= #} -.container { - max-width: 1300px; - padding-right: 15px; -} -#header { - flex: 0 0 auto; -} -#header .container { - display: flex; - flex-direction: row; - justify-content: space-between; -} -#summary { - flex: 0 0 auto; -} -#content { - height: 100%; -} -#main { - display: flex; - flex-direction: row; - min-height: 100%; -} -#sidebar { - flex: 0 0 220px; -} -#collector-wrapper { - flex: 0 1 100%; - min-width: 0; -} -#collector-content { - margin: 0 0 30px 0; - padding: 14px 0 14px 20px; -} - -#main h2:first-of-type { - margin-top: 0; -} - -{# Header (the colors of this element don't change based on the selected theme) - ========================================================================= #} -#header { - background-color: #222; - overflow: hidden; -} -#header h1 { - color: #fff; - flex: 1; - font-weight: normal; - font-size: 21px; - margin: 0; - padding: 10px 10px 8px; -} -#header h1 span { - color: #ccc; -} -#header h1 svg { - height: 40px; - width: 40px; - margin-top: -4px; - vertical-align: middle; -} -#header h1 svg path, -#header h1 svg .sf-svg-path { - fill: #fff; -} -#header .search { - padding-top: 11px; -} -#header .search input { - border: 1px solid #ddd; - margin-right: 4px; - padding: 7px 8px; - width: 200px; -} - -{# Summary - ========================================================================= #} -#summary .status { - background: var(--base-2); - border: solid rgba(0, 0, 0, 0.1); - border-width: 2px 0; - padding: 10px; -} -#summary h2, -#summary h2 a { - color: var(--base-6); - font-size: 21px; - margin: 0; - text-decoration: none; - vertical-align: middle; -} -#summary h2 a:hover { - text-decoration: underline; -} -#summary h2 a.referer { - margin-left: .5em; - font-size: 75%; - color: rgba(255, 255, 255, 0.5); -} -#summary h2 a.referer:before { - content: '\1F503\00a0'; -} - -#summary .status-success { background: var(--color-success); } -#summary .status-warning { background: var(--color-warning); } -#summary .status-error { background: var(--background-error); } - -#summary .status-success h2, -#summary .status-success a, -#summary .status-warning h2, -#summary .status-warning a, -#summary .status-error h2, -#summary .status-error a { - color: #FFF; -} - -#summary dl.metadata, -#summary dl.metadata a { - margin: 5px 0 0; - color: rgba(255, 255, 255, 0.75); -} -#summary dl.metadata dt, -#summary dl.metadata dd { - display: inline-block; - font-size: 13px; -} -#summary dl.metadata dt { - font-weight: bold; -} -#summary dl.metadata dt:after { - content: ':'; -} -#summary dl.metadata dd { - margin: 0 1.5em 0 0; -} - -#summary dl.metadata .label { - background: rgba(255, 255, 255, 0.2); -} - -{# Sidebar - ========================================================================= #} -#sidebar { - background: #444; - color: #ccc; - padding-bottom: 30px; - position: relative; - width: 220px; - z-index: 9999; -} -#sidebar .module { - padding: 10px; - width: 220px; -} - -{# Sidebar Shortcuts - ------------------------------------------------------------------------- #} -#sidebar #sidebar-shortcuts { - background: #333; - width: 220px; -} -#sidebar #sidebar-shortcuts .shortcuts { - position: relative; - padding: 16px 10px; -} -#sidebar-shortcuts .icon { - display: block; - float: left; - width: 50px; - margin: 2px 0 0 -10px; - text-align: center; -} -#sidebar #sidebar-shortcuts .btn { - color: #f5f5f5; -} -#sidebar #sidebar-shortcuts .btn + .btn { - margin-left: 5px; -} -#sidebar #sidebar-shortcuts .btn { - padding: .5em; -} - -{# Sidebar Search (the colors of this element don't change based on the selected theme) - ------------------------------------------------------------------------- #} -#sidebar-search .form-group:first-of-type { - padding-top: 20px; -} -#sidebar-search .form-group { - clear: both; - overflow: hidden; - padding-bottom: 10px; -} -#sidebar-search .form-group label { - float: left; - font-size: 13px; - line-height: 24px; - width: 60px; -} -#sidebar-search .form-group input, -#sidebar-search .form-group select { - float: left; - font-size: 13px; - padding: 3px 6px; -} -#sidebar-search .form-group input { - background: #ccc; - border: 1px solid var(--color-muted); - color: #222; - width: 120px; -} -#sidebar-search .form-group select { - color: #222; -} -#sidebar-search .form-group .btn { - float: right; - margin-right: 10px; -} - -{# Sidebar Menu (the colors of this element don't change based on the selected theme) - ------------------------------------------------------------------------- #} -#menu-profiler { - margin: 0; - padding: 0; - list-style-type: none; -} -#menu-profiler li { - position: relative; - margin-bottom: 0; -} -#menu-profiler li a { - border: solid transparent; - border-width: 2px 0; - color: var(--base-3); - display: block; -} -#menu-profiler li a:hover { - text-decoration: none; -} -#menu-profiler li a .label { - background: transparent; - color: #EEE; - display: block; - padding: 8px 10px 8px 50px; - overflow: hidden; - white-space: nowrap; -} -#menu-profiler li a .label .icon { - display: block; - position: absolute; - left: 0; - top: 8px; - width: 50px; - text-align: center; -} -#menu-profiler .label .icon img, -#menu-profiler .label .icon svg { - height: 24px; - max-width: 24px; -} -#menu-profiler li a .label .icon svg path, -#menu-profiler li a .label .icon svg .sf-svg-path { - fill: #DDD; -} -#menu-profiler li a .label strong { - font-size: 16px; - font-weight: normal; -} -#menu-profiler li a .label.disabled { - opacity: .25; -} -#menu-profiler li a:hover .label.disabled, -#menu-profiler li.selected a .label.disabled { - opacity: 1; -} - -#menu-profiler li.selected a, -#menu-profiler:hover li.selected a:hover, -#menu-profiler li a:hover { - background: #666; - border: solid #555; - border-width: 2px 0; -} -#menu-profiler li.selected a .label, -#menu-profiler li a:hover .label { - color: #FFF; -} -#menu-profiler li.selected a .icon svg path, -#menu-profiler li.selected a .icon svg .sf-svg-path, -#menu-profiler li a:hover .icon svg path, -#menu-profiler li a:hover .icon svg .sf-svg-path { - fill: #fff; -} - -#menu-profiler li a .count { - background-color: #666; - color: #fff; - display: inline-block; - font-weight: bold; - min-width: 10px; - padding: 2px 6px; - position: absolute; - right: 10px; - text-align: center; - vertical-align: baseline; - white-space: nowrap; -} -#menu-profiler li a span.count span { - font-size: 12px; - -} -#menu-profiler li a span.count span + span::before { - content: " / "; - color: #AAA; -} - -#menu-profiler .label-status-warning .count { - background: var(--color-warning); -} -#menu-profiler .label-status-error .count { - background: var(--background-error); -} - -{# Timeline panel - ========================================================================= #} -#timeline-control { - background: var(--table-background); - box-shadow: var(--shadow); - margin: 1em 0; - padding: 10px; -} -#timeline-control label { - font-weight: bold; - margin-right: 1em; -} -#timeline-control input { - background: var(--metric-value-background); - border: 1px solid var(--table-border); - font-size: 16px; - padding: 4px; - text-align: right; - width: 5em; -} -#timeline-control .help { - margin-left: 1em; -} - -.sf-profiler-timeline .legends { - font-size: 12px; - line-height: 1.5em; -} -.sf-profiler-timeline + p.help { - margin-top: 0; -} - -{# Tabbed navigation - ========================================================================= #} -.tab-navigation { - margin: 0 0 1em 0; - padding: 0; -} -.tab-navigation li { - background: var(--tab-background); - border: 1px solid var(--table-border); - color: var(--tab-color); - cursor: pointer; - display: inline-block; - font-size: 16px; - margin: 0 0 0 -1px; - padding: .5em .75em; - z-index: 1; -} -.tab-navigation li .badge { - background-color: var(--base-1); - color: var(--base-4); - display: inline-block; - font-size: 14px; - font-weight: bold; - margin-left: 8px; - min-width: 10px; - padding: 1px 6px; - text-align: center; - white-space: nowrap; -} -.tab-navigation li.disabled { - background: var(--tab-disabled-background); - color: var(--tab-disabled-color); -} -.tab-navigation li.active { - background: var(--tab-active-background); - color: var(--tab-active-color); - z-index: 1100; -} -.tab-navigation li.active .badge { - background-color: var(--base-5); - color: var(--base-2); -} -.tab-content > *:first-child { - margin-top: 0; -} -.tab-navigation li .badge.status-warning { background: var(--color-warning); color: #FFF; } -.tab-navigation li .badge.status-error { background: var(--background-error); color: #FFF; } - -.sf-tabs .tab:not(:first-child) { display: none; } - -{# Toggles - ========================================================================= #} -.sf-toggle-content { - -moz-transition: display .25s ease; - -webkit-transition: display .25s ease; - transition: display .25s ease; -} -.sf-toggle-content.sf-toggle-hidden { - display: none; -} -.sf-toggle-content.sf-toggle-visible { - display: block; -} - -{# Filters - ========================================================================= #} -[data-filters] { position: relative; } -[data-filtered] { cursor: pointer; } -[data-filtered]:after { content: '\00a0\25BE'; } -[data-filtered]:hover .filter-list li { display: inline-flex; } -[class*="filter-hidden-"] { display: none; } -.filter-list { position: absolute; border: var(--border); box-shadow: var(--shadow); margin: 0; padding: 0; display: flex; flex-direction: column; } -.filter-list :after { content: ''; } -.filter-list li { - background: var(--tab-disabled-background); - border-bottom: var(--border); - color: var(--tab-disabled-color); - display: none; - list-style: none; - margin: 0; - padding: 5px 10px; - text-align: left; - font-weight: normal; -} -.filter-list li.active { - background: var(--tab-background); - color: var(--tab-color); -} -.filter-list li.last-active { - background: var(--tab-active-background); - color: var(--tab-active-color); -} - -.filter-list-level li { cursor: s-resize; } -.filter-list-level li.active { cursor: n-resize; } -.filter-list-level li.last-active { cursor: default; } -.filter-list-level li.last-active:before { content: '\2714\00a0'; } -.filter-list-choice li:before { content: '\2714\00a0'; color: transparent; } -.filter-list-choice li.active:before { color: unset; } - -{# Twig panel - ========================================================================= #} -#twig-dump pre { - font-size: 12px; - line-height: 1.7; - background-color: var(--base-0); - border: var(--border); - padding: 15px; - box-shadow: 0 0 1px rgba(128, 128, 128, .2); -} -#twig-dump span { - border-radius: 2px; - padding: 1px 2px; -} -#twig-dump .status-error { background: transparent; color: var(--color-error); } -#twig-dump .status-warning { background: rgba(240, 181, 24, 0.3); } -#twig-dump .status-success { background: rgba(100, 189, 99, 0.2); } -#twig-dump .status-info { background: var(--info-background); } - -#twig-table tbody td { - vertical-align: middle; -} -#twig-table tbody td > a { - margin-left: -5px; -} -#twig-table tbody td div { - margin: 0; -} - -.icon-twig { - vertical-align: text-bottom; -} -.icon-twig svg path { - fill: #7eea12; -} - -{# Logger panel - ========================================================================= #} -.badge { - background: var(--badge-background); - border-radius: 4px; - color: var(--badge-color); - font-size: 12px; - font-weight: bold; - padding: 1px 4px; -} -.badge-warning { - background: var(--badge-warning-background); - color: var(--badge-warning-color); -} - -.log-filters { - display: flex; -} -.log-filters .log-filter { - position: relative; -} -.log-filters .log-filter + .log-filter { - margin-left: 15px; -} -.log-filters .log-filter summary { - align-items: center; - background: var(--log-filter-button-background); - border-radius: 2px; - border: 1px solid var(--log-filter-button-border); - color: var(--log-filter-button-color); - cursor: pointer; - display: flex; - padding: 5px 8px; -} -.log-filters .log-filter summary .icon { - height: 18px; - width: 18px; - margin: 0 7px 0 0; -} -.log-filters .log-filter summary svg { - height: 18px; - width: 18px; - opacity: 0.7; -} -.log-filters .log-filter summary .filter-active-num { - color: var(--log-filter-active-num-color); - font-weight: bold; - padding: 0 1px; -} -.log-filter .tab-navigation { - margin-bottom: 0; -} -.log-filter .tab-navigation li:first-child { - border-top-left-radius: 2px; - border-bottom-left-radius: 2px; -} -.log-filter .tab-navigation li:last-child { - border-top-right-radius: 2px; - border-bottom-right-radius: 2px; -} -.log-filter .tab-navigation li { - border-color: var(--log-filter-button-border); - padding: 0; -} -.log-filter .tab-navigation li + li { - margin-left: -5px; -} -.log-filter .tab-navigation li .badge { - font-size: 13px; - padding: 0 6px; -} -.log-filter .tab-navigation li input { - display: none; -} -.log-filter .tab-navigation li label { - align-items: center; - cursor: pointer; - padding: 5px 10px; - display: inline-flex; - font-size: 14px; -} - -.log-filters .log-filter .log-filter-content { - background: var(--base-0); - border: 1px solid var(--table-border); - border-radius: 2px; - box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); - padding: 15px; - position: absolute; - left: 0; - top: 36px; - max-width: 400px; - min-width: 200px; - z-index: 9999; -} -.log-filters .log-filter .log-filter-content .log-filter-option { - align-items: center; - display: flex; -} -.log-filter .filter-select-all-or-none { - margin-bottom: 10px; -} -.log-filter .filter-select-all-or-none button + button { - margin-left: 15px; -} -.log-filters .log-filter .log-filter-content .log-filter-option + .log-filter-option { - margin: 7px 0 0; -} -.log-filters .log-filter .log-filter-content .log-filter-option label { - cursor: pointer; - flex: 1; - padding-left: 10px; -} - -table.logs .metadata { - display: block; - font-size: 12px; -} -.theme-dark tr.status-error td, -.theme-dark tr.status-warning td { border-bottom: unset; border-top: unset; } - -table.logs .log-timestamp { - color: var(--log-timestamp-color); -} -table.logs .log-metadata { - margin: 8px 0 0; -} -table.logs .log-metadata > span { - display: inline-block; -} -table.logs .log-metadata > span + span { - margin-left: 10px; -} -table.logs .log-metadata .log-channel { - color: var(--base-1); - font-size: 13px; - font-weight: bold; -} -table.logs .log-metadata .log-num-occurrences { - color: var(--color-muted); - font-size: 13px; -} -.log-type-badge { - display: inline-block; - font-family: var(--font-sans-serif); - margin-top: 5px; -} -.log-type-badge.badge-deprecation { - background: var(--badge-warning-background); - color: var(--badge-warning-color); -} -.log-type-badge.badge-error { - background: var(--badge-danger-background); - color: var(--badge-danger-color); -} -.log-type-badge.badge-silenced { - background: #EDE9FE; - color: #6D28D9; -} -.theme-dark .log-type-badge.badge-silenced { - background: #5B21B6; - color: #EDE9FE; -} - -tr.log-status-warning { - border-left: 4px solid #F59E0B; -} -tr.log-status-error { - border-left: 4px solid #EF4444; -} -tr.log-status-silenced { - border-left: 4px solid #A78BFA; -} - -.container-compilation-logs { - background: var(--table-background); - border: 1px solid var(--base-2); - margin-top: 30px; - padding: 15px; -} -.container-compilation-logs summary { - cursor: pointer; -} -.container-compilation-logs summary h4 { - margin: 0 0 5px; -} -.container-compilation-logs summary p { - margin: 0; -} - -{# Doctrine panel - ========================================================================= #} -.sql-runnable { - background: var(--base-1); - margin: .5em 0; - padding: 1em; -} -.sql-explain { - overflow-x: auto; - max-width: 920px; -} -.sql-explain table td, .sql-explain table tr { - word-break: normal; -} -.queries-table pre { - margin: 0; - white-space: pre-wrap; - -ms-word-break: break-all; - word-break: break-all; - word-break: break-word; - -webkit-hyphens: auto; - -moz-hyphens: auto; - hyphens: auto; -} - -{# Security panel - ========================================================================= #} -#collector-content .decision-log .voter_result td { - border-top-width: 1px; - border-bottom-width: 0; - padding-bottom: 0; -} - -#collector-content .decision-log .voter_details td { - border-top-width: 0; - border-bottom-width: 1px; - padding-bottom: 0; -} - -#collector-content .decision-log .voter_details table { - border: 0; - margin: 0; - box-shadow: unset; -} - -#collector-content .decision-log .voter_details table td { - border: 0; - padding: 0 0 8px 0; -} - -{# Validator panel - ========================================================================= #} - -#collector-content .sf-validator { - margin-bottom: 2em; -} - -#collector-content .sf-validator .sf-validator-context, -#collector-content .sf-validator .trace { - border: var(--border); - background: var(--base-0); - padding: 10px; - margin: 0.5em 0; - overflow: auto; -} -#collector-content .sf-validator .trace { - font-size: 12px; -} -#collector-content .sf-validator .trace li { - margin-bottom: 0; - padding: 0; -} -#collector-content .sf-validator .trace li.selected { - background: var(--highlight-selected-line); -} - -{# Messenger panel - ========================================================================= #} - -#collector-content .message-bus .trace { - border: var(--border); - background: var(--base-0); - padding: 10px; - margin: 0.5em 0; - overflow: auto; -} -#collector-content .message-bus .trace { - font-size: 12px; -} -#collector-content .message-bus .trace li { - margin-bottom: 0; - padding: 0; -} -#collector-content .message-bus .trace li.selected { - background: var(--highlight-selected-line); -} - -{# Dump panel - ========================================================================= #} -pre.sf-dump, pre.sf-dump .sf-dump-default { - z-index: 1000 !important; -} - -#collector-content .sf-dump { - margin-bottom: 2em; -} -#collector-content pre.sf-dump, -#collector-content .sf-dump code, -#collector-content .sf-dump samp { - font-family: monospace; - font-size: 13px; -} -#collector-content .sf-dump a { - cursor: pointer; -} -#collector-content .sf-dump pre.sf-dump, -#collector-content .sf-dump .trace { - border: var(--border); - padding: 10px; - margin: 0.5em 0; - overflow: auto; -} - -#collector-content pre.sf-dump, -#collector-content .sf-dump-default { - background: none; -} -#collector-content .sf-dump-ellipsis { max-width: 100em; } - -#collector-content .sf-dump { - margin: 0; - padding: 0; - line-height: 1.4; -} - -#collector-content .dump-inline .sf-dump { - display: inline; - white-space: normal; - font-size: inherit; - line-height: inherit; -} -#collector-content .dump-inline .sf-dump:after { - display: none; -} - -#collector-content .sf-dump .trace { - font-size: 12px; -} -#collector-content .sf-dump .trace li { - margin-bottom: 0; - padding: 0; -} - -{# Search Results page - ========================================================================= #} -#search-results td { - font-family: var(--font-sans-serif); - vertical-align: middle; -} - -#search-results .sf-search { - visibility: hidden; - margin-left: 2px; -} -#search-results tr:hover .sf-search { - visibility: visible; -} - -{# Small screens - ========================================================================= #} - -.visible-small { - display: none; -} -.hidden-small { - display: inherit; -} - -@media (max-width: 768px) { - #sidebar { - flex-basis: 50px; - overflow-x: hidden; - transition: flex-basis 200ms ease-out; - } - #sidebar:hover, #sidebar.expanded { - flex-basis: 220px; - } - - #sidebar-search { - display: none; - } - #sidebar:hover #sidebar-search.sf-toggle-visible, #sidebar.expanded #sidebar-search.sf-toggle-visible { - display: block; - } - - #sidebar .module { - display: none; - } - #sidebar:hover .module, #sidebar.expanded .module { - display: block; - } - - #sidebar:not(:hover):not(.expanded) .label .count { - border-radius: 50%; - border: 1px solid #eee; - height: 8px; - min-width: 0; - padding: 0; - right: 4px; - text-indent: -9999px; - top: 50%; - width: 8px; - } - - .visible-small { - display: inherit; - } - .hidden-small { - display: none; - } - - .btn-sm svg { - margin-left: 2px; - } -} - -{# Config Options - ========================================================================= #} -body.width-full .container { - max-width: 100%; -} - -body.theme-light #collector-content .sf-dump pre.sf-dump, -body.theme-light #collector-content .sf-dump .trace { - background: #FFF; -} -body.theme-light #collector-content pre.sf-dump, -body.theme-light #collector-content .sf-dump-default { - color: #CC7832; -} -body.theme-light #collector-content .sf-dump-str { color: #629755; } -body.theme-light #collector-content .sf-dump-private, -body.theme-light #collector-content .sf-dump-protected, -body.theme-light #collector-content .sf-dump-public { color: #262626; } -body.theme-light #collector-content .sf-dump-note { color: #6897BB; } -body.theme-light #collector-content .sf-dump-key { color: #789339; } -body.theme-light #collector-content .sf-dump-ref { color: #6E6E6E; } -body.theme-light #collector-content .sf-dump-ellipsis { color: #CC7832; max-width: 100em; } -body.theme-light #collector-content .sf-dump-ellipsis-path { max-width: 5em; } -body.theme-light #collector-content .sf-dump .trace li.selected { - background: rgba(255, 255, 153, 0.5); -} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/results.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/results.html.twig deleted file mode 100644 index 7ddbf9c4f..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/results.html.twig +++ /dev/null @@ -1,67 +0,0 @@ -{% extends '@WebProfiler/Profiler/layout.html.twig' %} - -{% macro profile_search_filter(request, result, property) %} - {%- if request.hasSession -%} - <a href="{{ path('_profiler_search_results', request.query.all|merge({token: result.token})|merge({ (property): result[property] })) }}" title="Search"><span title="Search" class="sf-icon sf-search">{{ include('@WebProfiler/Icon/search.svg') }}</span></a> - {%- endif -%} -{% endmacro %} - -{% import _self as helper %} - -{% block summary %} - <div class="status"> - <div class="container"> - <h2>Profile Search</h2> - </div> - </div> -{% endblock %} - -{% block panel %} - <h2>{{ tokens ? tokens|length : 'No' }} results found</h2> - - {% if tokens %} - <table id="search-results"> - <thead> - <tr> - <th scope="col" class="text-center">Status</th> - <th scope="col">IP</th> - <th scope="col">Method</th> - <th scope="col">URL</th> - <th scope="col">Time</th> - <th scope="col">Token</th> - </tr> - </thead> - <tbody> - {% for result in tokens %} - {% set css_class = result.status_code|default(0) > 399 ? 'status-error' : result.status_code|default(0) > 299 ? 'status-warning' : 'status-success' %} - - <tr> - <td class="text-center"> - <span class="label {{ css_class }}">{{ result.status_code|default('n/a') }}</span> - </td> - <td> - <span class="nowrap">{{ result.ip }} {{ helper.profile_search_filter(request, result, 'ip') }}</span> - </td> - <td> - <span class="nowrap">{{ result.method }} {{ helper.profile_search_filter(request, result, 'method') }}</span> - </td> - <td class="break-long-words"> - {{ result.url }} - {{ helper.profile_search_filter(request, result, 'url') }} - </td> - <td class="text-small"> - <span class="nowrap">{{ result.time|date('d-M-Y') }}</span> - <span class="nowrap newline">{{ result.time|date('H:i:s') }}</span> - </td> - <td class="nowrap"><a href="{{ path('_profiler', { token: result.token }) }}">{{ result.token }}</a></td> - </tr> - {% endfor %} - </tbody> - </table> - {% else %} - <div class="empty"> - <p>The query returned no result.</p> - </div> - {% endif %} - -{% endblock %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/search.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/search.html.twig deleted file mode 100644 index 7494b4ec7..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/search.html.twig +++ /dev/null @@ -1,56 +0,0 @@ -<div id="sidebar-search" class="hidden"> - <form action="{{ path('_profiler_search') }}" method="get"> - <div class="form-group"> - <label for="ip">IP</label> - <input type="text" name="ip" id="ip" value="{{ ip }}"> - </div> - - <div class="form-group"> - <label for="method">Method</label> - <select name="method" id="method"> - <option value="">Any</option> - {% for m in ['DELETE', 'GET', 'HEAD', 'PATCH', 'POST', 'PUT'] %} - <option {{ m == method ? 'selected="selected"' }}>{{ m }}</option> - {% endfor %} - </select> - </div> - - <div class="form-group"> - <label for="status_code">Status</label> - <input type="number" name="status_code" id="status_code" min="100" max="599" value="{{ status_code }}"> - </div> - - <div class="form-group"> - <label for="url">URL</label> - <input type="text" name="url" id="url" value="{{ url }}"> - </div> - - <div class="form-group"> - <label for="token">Token</label> - <input type="text" name="token" id="token" value="{{ token }}"> - </div> - - <div class="form-group"> - <label for="start">From</label> - <input type="date" name="start" id="start" value="{{ start }}"> - </div> - - <div class="form-group"> - <label for="end">Until</label> - <input type="date" name="end" id="end" value="{{ end }}"> - </div> - - <div class="form-group"> - <label for="limit">Results</label> - <select name="limit" id="limit"> - {% for l in [10, 50, 100] %} - <option {{ l == limit ? 'selected="selected"' }}>{{ l }}</option> - {% endfor %} - </select> - </div> - - <div class="form-group"> - <button type="submit" class="btn btn-sm">Search</button> - </div> - </form> -</div> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/settings.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/settings.html.twig deleted file mode 100644 index 4b2394687..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/settings.html.twig +++ /dev/null @@ -1,193 +0,0 @@ -<style> -#open-settings { - color: var(--color-muted); - display: block; - margin: 15px 15px 5px; -} - -.modal-wrap { - -webkit-transition: all 0.3s ease-in-out; - align-items: center; - background: rgba(0, 0, 0, 0.8); - display: flex; - height: 100%; - justify-content: center; - left: 0; - opacity: 1; - overflow: auto; - position: fixed; - top: 0; - transition: all 0.3s ease-in-out; - visibility: hidden; - width: 100%; - z-index: 100000; -} -.modal-wrap.visible { - opacity: 1; - visibility: visible; -} -.modal-wrap .modal-container { - box-shadow: 5px 5px 10px 0px rgba(0, 0, 0, 0.5); - color: var(--base-6); - margin: 1em; - max-width: 94%; - width: 600px; -} - -.modal-wrap .modal-header { - align-items: center; - background: var(--table-header); - display: flex; - justify-content: space-between; - padding: 15px 30px; -} -.modal-wrap .modal-header h3 { - color: var(--base-6); - margin: 0; -} -.modal-wrap .modal-header .close-modal { - background: transparent; - border: 0; - color: var(--base-4); - cursor: pointer; - font-size: 28px; - line-height: 1; -} - -.modal-wrap .modal-header .close-modal:hover { opacity: 1; } - -.modal-wrap .modal-content { - background: var(--base-1); - margin: 0; - padding: 15px 30px; - width: 100%; - z-index: 100000; -} -.modal-content h4 { - border-bottom: var(--border); - margin: 0 0 15px; - padding: 0 0 5px; -} -.modal-content input, .modal-content .form-help { - margin-left: 15px; -} -.modal-content label { - cursor: pointer; - font-size: 16px; - margin-left: 3px; -} -.modal-content .form-help { - color: var(--color-muted); - font-size: 14px; - margin: 5px 0 15px 33px; -} -.modal-content .form-help + h4 { - margin-top: 45px; -} - -@media (max-width: 768px) { - #open-settings { - color: transparent; - } - #sidebar:hover #open-settings, #sidebar.expanded #open-settings { - color: var(--color-muted); - } - #open-settings:before { - content: '\2699'; - font-weight: bold; - font-size: 25px; - color: var(--color-muted); - } - #sidebar:hover #open-settings:before, #sidebar.expanded #open-settings:before { - content: ''; - } -} -</style> - -<a href="#" id="open-settings">Settings</a> - -<div class="modal-wrap" id="profiler-settings"> - <div class="modal-container"> - <div class="modal-header"> - <h3>Configuration Settings</h3> - <button class="close-modal">&times;</button> - </div> - - <div class="modal-content"> - <h4>Theme</h4> - - <input class="config-option" type="radio" name="theme" value="auto" id="settings-theme-auto"> - <label for="settings-theme-auto">Auto</label> - <p class="form-help"><strong>Default theme</strong>. It switches between Light and Dark automatically to match the operating system theme.</p> - - <input class="config-option" type="radio" name="theme" value="light" id="settings-theme-light"> - <label for="settings-theme-light">Light</label> - <p class="form-help">Provides greatest readability, but requires a well-lit environment.</p> - - <input class="config-option" type="radio" name="theme" value="dark" id="settings-theme-dark"> - <label for="settings-theme-dark">Dark</label> - <p class="form-help">Reduces eye fatigue. Ideal for low light environments.</p> - - <h4>Page Width</h4> - - <input class="config-option" type="radio" name="width" value="normal" id="settings-width-normal"> - <label for="settings-width-normal">Normal</label> - <p class="form-help">Fixed page width. Improves readability.</p> - - <input class="config-option" type="radio" name="width" value="full" id="settings-width-full"> - <label for="settings-width-full">Full-page</label> - <p class="form-help">Dynamic page width. As wide as the browser window.</p> - </div> - </div> -</div> - -<script> -(function() { - const configOptions = document.querySelectorAll('.config-option'); - const allSettingValues = ['theme-auto', 'theme-ligh', 'theme-dark', 'width-normal', 'width-full']; - [...configOptions].forEach(option => { - option.addEventListener('change', function (event) { - const optionName = option.name; - const optionValue = option.value; - const settingName = 'symfony/profiler/' + optionName; - const settingValue = optionName + '-' + optionValue; - - localStorage.setItem(settingName, settingValue); - - document.body.classList.forEach((cssClass) => { - if (cssClass.startsWith(optionName)) { - document.body.classList.remove(cssClass); - } - }); - - if ('theme-auto' === settingValue) { - document.body.classList.add((matchMedia('(prefers-color-scheme: dark)').matches ? 'theme-dark' : 'theme-light')); - } else { - document.body.classList.add(settingValue); - } - }); - }); - - const openModalButton = document.getElementById('open-settings'); - const modalWindow = document.getElementById('profiler-settings'); - const closeModalButton = document.getElementsByClassName('close-modal')[0]; - const modalWrapper = document.getElementsByClassName('modal-wrap')[0] - - openModalButton.addEventListener('click', function(event) { - document.getElementById('settings-' + (localStorage.getItem('symfony/profiler/theme') || 'theme-auto')).checked = 'checked'; - document.getElementById('settings-' + (localStorage.getItem('symfony/profiler/width') || 'width-normal')).checked = 'checked'; - - modalWindow.classList.toggle('visible'); - event.preventDefault(); - }); - - closeModalButton.addEventListener('click', function() { - modalWindow.classList.remove('visible'); - }); - modalWrapper.addEventListener('click', function(event) { - if (event.target == event.currentTarget) { - modalWindow.classList.remove('visible'); - } - }); -})(); -</script> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/table.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/table.html.twig deleted file mode 100644 index cb9986bd2..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/table.html.twig +++ /dev/null @@ -1,16 +0,0 @@ -<table class="{{ class|default('') }}"> - <thead> - <tr> - <th scope="col" class="key">{{ labels is defined ? labels[0] : 'Key' }}</th> - <th scope="col">{{ labels is defined ? labels[1] : 'Value' }}</th> - </tr> - </thead> - <tbody> - {% for key in data|keys|sort %} - <tr> - <th scope="row">{{ key }}</th> - <td>{{ profiler_dump(data[key]) }}</td> - </tr> - {% endfor %} - </tbody> -</table> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar.css.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar.css.twig deleted file mode 100644 index 5e675b960..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar.css.twig +++ /dev/null @@ -1,562 +0,0 @@ -{# when updating any of these colors, do the same in profiler.css.twig #} -{% set colors = { 'success': '#4F805D', 'warning': '#A46A1F', 'error': '#B0413E' } %} - -.sf-minitoolbar { - background-color: #222; - border-top-left-radius: 4px; - bottom: 0; - box-sizing: border-box; - display: none; - height: 36px; - padding: 6px; - position: fixed; - right: 0; - z-index: 99999; -} - -.sf-minitoolbar button { - background-color: transparent; - padding: 0; - border: none; -} -.sf-minitoolbar svg, -.sf-minitoolbar img { - max-height: 24px; - max-width: 24px; - display: inline; -} - -.sf-toolbar-clearer { - clear: both; - height: 36px; -} - -.sf-display-none { - display: none; -} - -.sf-toolbarreset * { - box-sizing: content-box; - vertical-align: baseline; - letter-spacing: normal; - width: auto; -} - -.sf-toolbarreset { - background-color: #222; - bottom: 0; - box-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); - color: #EEE; - font: 11px Arial, sans-serif; - left: 0; - margin: 0; - padding: 0 36px 0 0; - position: fixed; - right: 0; - text-align: left; - text-transform: none; - z-index: 99999; - direction: ltr; - - /* neutralize the aliasing defined by external CSS styles */ - -webkit-font-smoothing: subpixel-antialiased; - -moz-osx-font-smoothing: auto; -} -.sf-toolbarreset abbr { - border: dashed #777; - border-width: 0 0 1px; -} -.sf-toolbarreset svg, -.sf-toolbarreset img { - height: 20px; - width: 20px; - display: inline-block; -} - -.sf-toolbarreset .sf-cancel-button { - color: #444; -} - -.sf-toolbarreset .hide-button { - background: #444; - display: block; - position: absolute; - top: 0; - right: 0; - width: 36px; - height: 36px; - cursor: pointer; - text-align: center; - border: none; - margin: 0; - padding: 0; -} -.sf-toolbarreset .hide-button svg { - max-height: 18px; - margin-top: 1px; -} - -.sf-toolbar-block { - cursor: default; - display: block; - float: left; - height: 36px; - margin-right: 0; - white-space: nowrap; - max-width: 15%; -} -.sf-toolbar-block > a, -.sf-toolbar-block > a:hover { - display: block; - text-decoration: none; - background-color: transparent; - color: inherit; -} - -.sf-toolbar-block span { - display: inline-block; -} -.sf-toolbar-block .sf-toolbar-value { - color: #F5F5F5; - font-size: 13px; - line-height: 36px; - padding: 0; -} -.sf-toolbar-block .sf-toolbar-label, -.sf-toolbar-block .sf-toolbar-class-separator { - color: #AAA; - font-size: 12px; -} - -.sf-toolbar-block .sf-toolbar-info { - border-collapse: collapse; - display: table; - z-index: 100000; -} -.sf-toolbar-block hr { - border-top: 1px solid #777; - margin: 4px 0; - padding-top: 4px; -} -.sf-toolbar-block .sf-toolbar-info-piece { - /* this 'border-bottom' trick is needed because 'margin-bottom' doesn't work for table rows */ - border-bottom: solid transparent 3px; - display: table-row; -} -.sf-toolbar-block .sf-toolbar-info-piece-additional, -.sf-toolbar-block .sf-toolbar-info-piece-additional-detail { - display: none; -} -.sf-toolbar-block .sf-toolbar-info-group { - margin-bottom: 4px; - padding-bottom: 2px; - border-bottom: 1px solid #333333; -} -.sf-toolbar-block .sf-toolbar-info-group:last-child { - margin-bottom: 0; - padding-bottom: 0; - border-bottom: none; -} - -.sf-toolbar-block .sf-toolbar-info-piece .sf-toolbar-status { - padding: 2px 5px; - margin-bottom: 0; -} -.sf-toolbar-block .sf-toolbar-info-piece .sf-toolbar-status + .sf-toolbar-status { - margin-left: 4px; -} - -.sf-toolbar-block .sf-toolbar-info-piece:last-child { - margin-bottom: 0; -} - -div.sf-toolbar .sf-toolbar-block .sf-toolbar-info-piece a { - color: #99CDD8; - text-decoration: underline; -} -div.sf-toolbar .sf-toolbar-block a:hover { - text-decoration: none; -} - -.sf-toolbar-block .sf-toolbar-info-piece b { - color: #AAA; - display: table-cell; - font-size: 11px; - padding: 4px 8px 4px 0; -} -.sf-toolbar-block:not(.sf-toolbar-block-dump) .sf-toolbar-info-piece span { - color: #F5F5F5; -} -.sf-toolbar-block .sf-toolbar-info-piece span { - font-size: 12px; -} - -.sf-toolbar-block .sf-toolbar-info { - background-color: #444; - bottom: 36px; - color: #F5F5F5; - display: none; - padding: 9px 0; - position: absolute; -} - -.sf-toolbar-block .sf-toolbar-info:empty { - visibility: hidden; -} - -.sf-toolbar-block .sf-toolbar-status { - display: inline-block; - color: #FFF; - background-color: #666; - padding: 3px 6px; - margin-bottom: 2px; - vertical-align: middle; - min-width: 15px; - min-height: 13px; - text-align: center; -} - -.sf-toolbar-block .sf-toolbar-status-green { - background-color: {{ colors.success|raw }}; -} -.sf-toolbar-block .sf-toolbar-status-red { - background-color: {{ colors.error|raw }}; -} -.sf-toolbar-block .sf-toolbar-status-yellow { - background-color: {{ colors.warning|raw }}; -} - -.sf-toolbar-block.sf-toolbar-status-green { - background-color: {{ colors.success|raw }}; - color: #FFF; -} -.sf-toolbar-block.sf-toolbar-status-red { - background-color: {{ colors.error|raw }}; - color: #FFF; -} -.sf-toolbar-block.sf-toolbar-status-yellow { - background-color: {{ colors.warning|raw }}; - color: #FFF; -} - -.sf-toolbar-block-request .sf-toolbar-status { - color: #FFF; - display: inline-block; - font-size: 14px; - height: 36px; - line-height: 36px; - padding: 0 10px; -} -.sf-toolbar-block-request .sf-toolbar-info-piece a { - background-color: transparent; - text-decoration: none; -} -.sf-toolbar-block-request .sf-toolbar-info-piece a:hover { - text-decoration: underline; -} -.sf-toolbar-block-request .sf-toolbar-redirection-status { - font-weight: normal; - padding: 2px 4px; - line-height: 18px; -} -.sf-toolbar-block-request .sf-toolbar-info-piece span.sf-toolbar-redirection-method { - font-size: 12px; - height: 17px; - line-height: 17px; - margin-right: 5px; -} - -.sf-toolbar-block-ajax .sf-toolbar-icon { - cursor: pointer; -} - -.sf-toolbar-status-green .sf-toolbar-label, -.sf-toolbar-status-yellow .sf-toolbar-label, -.sf-toolbar-status-red .sf-toolbar-label { - color: #FFF; -} -.sf-toolbar-status-green svg path, -.sf-toolbar-status-green svg .sf-svg-path, -.sf-toolbar-status-red svg path, -.sf-toolbar-status-red svg .sf-svg-path, -.sf-toolbar-status-yellow svg path, -.sf-toolbar-status-yellow svg .sf-svg-path { - fill: #FFF; -} -.sf-toolbar-block-config svg path, -.sf-toolbar-block-config svg .sf-svg-path { - fill: #FFF; -} - -.sf-toolbar-block .sf-toolbar-icon { - display: block; - height: 36px; - padding: 0 7px; - overflow: hidden; - text-overflow: ellipsis; -} -.sf-toolbar-block-request .sf-toolbar-icon { - padding-left: 0; - padding-right: 0; -} - -.sf-toolbar-block .sf-toolbar-icon img, -.sf-toolbar-block .sf-toolbar-icon svg { - border-width: 0; - position: relative; - top: 8px; - vertical-align: baseline; -} - -.sf-toolbar-block .sf-toolbar-icon img + span, -.sf-toolbar-block .sf-toolbar-icon svg + span { - margin-left: 4px; -} -.sf-toolbar-block-config .sf-toolbar-icon .sf-toolbar-value { - margin-left: 4px; -} - -.sf-toolbar-block:hover, -.sf-toolbar-block.hover { - position: relative; -} -.sf-toolbar-block:hover .sf-toolbar-icon, -.sf-toolbar-block.hover .sf-toolbar-icon { - background-color: #444; - position: relative; - z-index: 10002; -} -.sf-toolbar-block-ajax.hover .sf-toolbar-info { - z-index: 10001; -} -.sf-toolbar-block:hover .sf-toolbar-info, -.sf-toolbar-block.hover .sf-toolbar-info { - display: block; - padding: 10px; - max-width: 525px; - max-height: 480px; - word-wrap: break-word; - overflow: hidden; - overflow-y: auto; -} -.sf-toolbar-info-piece b.sf-toolbar-ajax-info { - color: #F5F5F5; -} -.sf-toolbar-ajax-requests { - table-layout: auto; - width: 100%; -} -.sf-toolbar-ajax-requests td { - background-color: #444; - border-bottom: 1px solid #777; - color: #F5F5F5; - font-size: 12px; - padding: 4px; -} -.sf-toolbar-ajax-requests tr:last-child td { - border-bottom: 0; -} -.sf-toolbar-ajax-requests th { - background-color: #222; - border-bottom: 0; - color: #AAA; - font-size: 11px; - padding: 4px; -} -.sf-ajax-request-url { - max-width: 250px; - line-height: 9px; - overflow: hidden; - text-overflow: ellipsis; -} -.sf-toolbar-ajax-requests .sf-ajax-request-url a { - text-decoration: none; -} -.sf-toolbar-ajax-requests .sf-ajax-request-url a:hover { - text-decoration: underline; -} -.sf-ajax-request-duration { - text-align: right; -} -.sf-ajax-request-loading { - animation: sf-blink .5s ease-in-out infinite; -} -@keyframes sf-blink { - 0% { background: #222; } - 50% { background: #444; } - 100% { background: #222; } -} - -.sf-toolbar-block.sf-toolbar-block-dump .sf-toolbar-info { - max-width: none; - width: 100%; - position: fixed; - box-sizing: border-box; - left: 0; -} - -.sf-toolbar-block-dump pre.sf-dump { - background-color: #222; - border-color: #777; - border-radius: 0; - margin: 6px 0 12px 0; -} -.sf-toolbar-block-dump pre.sf-dump:last-child { - margin-bottom: 0; -} -.sf-toolbar-block-dump pre.sf-dump .sf-dump-search-wrapper { - margin-bottom: 5px; -} -.sf-toolbar-block-dump pre.sf-dump span.sf-dump-search-count { - color: #333; - font-size: 12px; -} -.sf-toolbar-block-dump .sf-toolbar-info-piece { - display: block; -} -.sf-toolbar-block-dump .sf-toolbar-info-piece .sf-toolbar-file-line { - color: #AAA; - margin-left: 4px; -} -.sf-toolbar-block-dump .sf-toolbar-info img { - display: none; -} - -/* Responsive Design */ -.sf-toolbar-icon .sf-toolbar-label, -.sf-toolbar-icon .sf-toolbar-value { - display: none; -} -.sf-toolbar-block-config .sf-toolbar-icon .sf-toolbar-label { - display: inline-block; -} - -/* Legacy Design - these styles are maintained to make old panels look - a bit better on the new toolbar */ -.sf-toolbar-block .sf-toolbar-info-piece-additional-detail { - color: #AAA; - font-size: 12px; -} -.sf-toolbar-status-green .sf-toolbar-info-piece-additional-detail, -.sf-toolbar-status-yellow .sf-toolbar-info-piece-additional-detail, -.sf-toolbar-status-red .sf-toolbar-info-piece-additional-detail { - color: #FFF; -} - -@media (min-width: 768px) { - - .sf-toolbar-icon .sf-toolbar-label, - .sf-toolbar-icon .sf-toolbar-value { - display: inline; - } - - .sf-toolbar-block .sf-toolbar-icon img, - .sf-toolbar-block .sf-toolbar-icon svg { - top: 6px; - } - .sf-toolbar-block-time .sf-toolbar-icon svg, - .sf-toolbar-block-memory .sf-toolbar-icon svg { - display: none; - } - .sf-toolbar-block-time .sf-toolbar-icon svg + span, - .sf-toolbar-block-memory .sf-toolbar-icon svg + span { - margin-left: 0; - } - - .sf-toolbar-block .sf-toolbar-icon { - padding: 0 10px; - } - .sf-toolbar-block-time .sf-toolbar-icon { - padding-right: 5px; - } - .sf-toolbar-block-memory .sf-toolbar-icon { - padding-left: 5px; - } - .sf-toolbar-block-request .sf-toolbar-icon { - padding-left: 0; - padding-right: 0; - } - .sf-toolbar-block-request .sf-toolbar-label { - margin-left: 5px; - } - .sf-toolbar-block-request .sf-toolbar-status + svg { - margin-left: 5px; - } - .sf-toolbar-block-request .sf-toolbar-icon svg + .sf-toolbar-label { - margin-left: 0; - } - .sf-toolbar-block-request .sf-toolbar-label + .sf-toolbar-value { - margin-right: 10px; - } - - .sf-toolbar-block-request:hover .sf-toolbar-info { - max-width: none; - } - - .sf-toolbar-block .sf-toolbar-info-piece b { - font-size: 12px; - } - .sf-toolbar-block .sf-toolbar-info-piece span { - font-size: 13px; - } - - .sf-toolbar-block-right { - float: right; - margin-left: 0; - margin-right: 0; - } -} - -@media (min-width: 1024px) { - .sf-toolbar-block .sf-toolbar-info-piece-additional, - .sf-toolbar-block .sf-toolbar-info-piece-additional-detail { - display: inline; - } - - .sf-toolbar-block .sf-toolbar-info-piece-additional:empty, - .sf-toolbar-block .sf-toolbar-info-piece-additional-detail:empty { - display: none; - } -} - -/***** Error Toolbar *****/ -.sf-error-toolbar .sf-toolbarreset { - background: #222; - color: #f5f5f5; - font: 13px/36px Arial, sans-serif; - height: 36px; - padding: 0 15px; - text-align: left; -} - -.sf-error-toolbar .sf-toolbarreset svg { - height: auto; -} - -.sf-error-toolbar .sf-toolbarreset a { - color: #99cdd8; - margin-left: 5px; - text-decoration: underline; -} - -.sf-error-toolbar .sf-toolbarreset a:hover { - text-decoration: none; -} - -.sf-error-toolbar .sf-toolbarreset .sf-toolbar-icon { - float: left; - padding: 5px 0; - margin-right: 10px; -} - -.sf-full-stack { - left: 0px; - font-size: 12px; -} - -/***** Media query print: Do not print the Toolbar. *****/ -@media print { - .sf-toolbar { - display: none !important; - } -} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar.html.twig deleted file mode 100644 index 236fc70da..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar.html.twig +++ /dev/null @@ -1,46 +0,0 @@ -<!-- START of Symfony Web Debug Toolbar --> -<div id="sfMiniToolbar-{{ token }}" class="sf-minitoolbar" data-no-turbolink> - <button type="button" title="Show Symfony toolbar" id="sfToolbarMiniToggler-{{ token }}" accesskey="D" aria-expanded="false" aria-controls="sfToolbarMainContent-{{ token }}"> - {{ include('@WebProfiler/Icon/symfony.svg') }} - </button> -</div> -<div id="sfToolbarClearer-{{ token }}" class="sf-toolbar-clearer"></div> - -<div id="sfToolbarMainContent-{{ token }}" class="sf-toolbarreset clear-fix" data-no-turbolink> - {% for name, template in templates %} - {% if block('toolbar', template) is defined %} - {% with { - collector: profile ? profile.getcollector(name) : null, - profiler_url: profiler_url, - token: token ?? (profile ? profile.token : null), - name: name, - profiler_markup_version: profiler_markup_version, - csp_script_nonce: csp_script_nonce, - csp_style_nonce: csp_style_nonce - } %} - {{ block('toolbar', template) }} - {% endwith %} - {% endif %} - {% endfor %} - {% if full_stack %} - <div class="sf-full-stack sf-toolbar-block sf-toolbar-block-full-stack sf-toolbar-status-red sf-toolbar-block-right"> - <div class="sf-toolbar-icon"> - <span class="sf-toolbar-value">Using symfony/symfony is NOT supported</span> - </div> - <div class="sf-toolbar-info sf-toolbar-status-red"> - <p>This project is using Symfony via the "symfony/symfony" package.</p> - <p>This is NOT supported anymore since Symfony 4.0.</p> - <p>Even if it seems to work well, it has some important limitations with no workarounds.</p> - <p>Using this package also makes your project slower.</p> - - <strong>Please, stop using this package and replace it with individual packages instead.</strong> - </div> - <div></div> - </div> - {% endif %} - - <button class="hide-button" type="button" id="sfToolbarHideButton-{{ token }}" title="Close Toolbar" accesskey="D" aria-expanded="true" aria-controls="sfToolbarMainContent-{{ token }}"> - {{ include('@WebProfiler/Icon/close.svg') }} - </button> -</div> -<!-- END of Symfony Web Debug Toolbar --> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar_item.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar_item.html.twig deleted file mode 100644 index d81e87797..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar_item.html.twig +++ /dev/null @@ -1,6 +0,0 @@ -<div class="sf-toolbar-block sf-toolbar-block-{{ name }} sf-toolbar-status-{{ status|default('normal') }} {{ additional_classes|default('') }}" {{ block_attrs|default('')|raw }}> - {% if link is not defined or link %}<a href="{{ url('_profiler', { token: token, panel: name }) }}">{% endif %} - <div class="sf-toolbar-icon">{{ icon|default('') }}</div> - {% if link|default(false) %}</a>{% endif %} - <div class="sf-toolbar-info">{{ text|default('') }}</div> -</div> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar_js.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar_js.html.twig deleted file mode 100644 index 352fbb0ea..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar_js.html.twig +++ /dev/null @@ -1,21 +0,0 @@ -<div id="sfwdt{{ token }}" class="sf-toolbar sf-display-none" role="region" aria-label="Symfony Web Debug Toolbar"> - {% include('@WebProfiler/Profiler/toolbar.html.twig') with { - templates: { - 'request': '@WebProfiler/Profiler/cancel.html.twig' - }, - profile: null, - profiler_url: url('_profiler', {token: token}), - profiler_markup_version: 2, - } %} -</div> - -{{ include('@WebProfiler/Profiler/base_js.html.twig') }} - -<style{% if csp_style_nonce %} nonce="{{ csp_style_nonce }}"{% endif %}> - {{ include('@WebProfiler/Profiler/toolbar.css.twig') }} -</style> -<script{% if csp_script_nonce %} nonce="{{ csp_script_nonce }}"{% endif %}>/*<![CDATA[*/ - (function () { - Sfjs.loadToolbar('{{ token }}'); - })(); -/*]]>*/</script> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar_redirect.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar_redirect.html.twig deleted file mode 100644 index 18d43b225..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar_redirect.html.twig +++ /dev/null @@ -1,18 +0,0 @@ -{% extends '@WebProfiler/Profiler/base.html.twig' %} - -{% block title 'Redirection Intercepted' %} - -{% block body %} - <div class="sf-reset"> - <div class="block-exception"> - <h1>This request redirects to <a href="{{ location }}">{{ location }}</a>.</h1> - - <p> - <small> - The redirect was intercepted by the web debug toolbar to help debugging. - For more information, see the "intercept-redirects" option of the Profiler. - </small> - </p> - </div> - </div> -{% endblock %} diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Router/panel.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Router/panel.html.twig deleted file mode 100644 index 41636d144..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/Router/panel.html.twig +++ /dev/null @@ -1,71 +0,0 @@ -<h2>Routing</h2> - -<div class="metrics"> - <div class="metric"> - <span class="value">{{ request.route ?: '(none)' }}</span> - <span class="label">Matched route</span> - </div> -</div> - -{% if request.route %} - <h3>Route Parameters</h3> - - {% if request.routeParams is empty %} - <div class="empty"> - <p>No parameters.</p> - </div> - {% else %} - {{ include('@WebProfiler/Profiler/table.html.twig', { data: request.routeParams, labels: ['Name', 'Value'] }, with_context = false) }} - {% endif %} -{% endif %} - -{% if router.redirect %} - <h3>Route Redirection</h3> - - <p>This page redirects to:</p> - <div class="card break-long-words"> - {{ router.targetUrl }} - {% if router.targetRoute %}<span class="text-muted">(route: "{{ router.targetRoute }}")</span>{% endif %} - </div> -{% endif %} - -<h3>Route Matching Logs</h3> - -<div class="card"> - <strong>Path to match:</strong> <code>{{ request.pathinfo }}</code> -</div> - -<table id="router-logs"> - <thead> - <tr> - <th>#</th> - <th>Route name</th> - <th>Path</th> - <th>Log</th> - </tr> - </thead> - <tbody> - {% for trace in traces %} - <tr class="{{ trace.level == 1 ? 'status-warning' : trace.level == 2 ? 'status-success' }}"> - <td class="font-normal text-muted nowrap">{{ loop.index }}</td> - <td class="break-long-words">{{ trace.name }}</td> - <td class="break-long-words">{{ trace.path }}</td> - <td class="font-normal"> - {% if trace.level == 1 %} - Path almost matches, but - <span class="newline">{{ trace.log }}</span> - {% elseif trace.level == 2 %} - {{ trace.log }} - {% else %} - Path does not match - {% endif %} - </td> - </tr> - {% endfor %} - </tbody> -</table> - -<p class="help"> - Note: These matching logs are based on the current router configuration, - which might differ from the configuration used when profiling this request. -</p> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/images/icon-minus-square.svg b/lib/symfony/web-profiler-bundle/Resources/views/images/icon-minus-square.svg deleted file mode 100644 index 471c2741c..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/images/icon-minus-square.svg +++ /dev/null @@ -1 +0,0 @@ -<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1408 960V832q0-26-19-45t-45-19H448q-26 0-45 19t-19 45v128q0 26 19 45t45 19h896q26 0 45-19t19-45zm256-544v960q0 119-84.5 203.5T1376 1664H416q-119 0-203.5-84.5T128 1376V416q0-119 84.5-203.5T416 128h960q119 0 203.5 84.5T1664 416z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Resources/views/images/icon-plus-square.svg b/lib/symfony/web-profiler-bundle/Resources/views/images/icon-plus-square.svg deleted file mode 100644 index 2f5c3b358..000000000 --- a/lib/symfony/web-profiler-bundle/Resources/views/images/icon-plus-square.svg +++ /dev/null @@ -1 +0,0 @@ -<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1408 960V832q0-26-19-45t-45-19h-320V448q0-26-19-45t-45-19H832q-26 0-45 19t-19 45v320H448q-26 0-45 19t-19 45v128q0 26 19 45t45 19h320v320q0 26 19 45t45 19h128q26 0 45-19t19-45v-320h320q26 0 45-19t19-45zm256-544v960q0 119-84.5 203.5T1376 1664H416q-119 0-203.5-84.5T128 1376V416q0-119 84.5-203.5T416 128h960q119 0 203.5 84.5T1664 416z"/></svg> diff --git a/lib/symfony/web-profiler-bundle/Twig/WebProfilerExtension.php b/lib/symfony/web-profiler-bundle/Twig/WebProfilerExtension.php deleted file mode 100644 index b5f0f3cad..000000000 --- a/lib/symfony/web-profiler-bundle/Twig/WebProfilerExtension.php +++ /dev/null @@ -1,119 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\WebProfilerBundle\Twig; - -use Symfony\Component\VarDumper\Cloner\Data; -use Symfony\Component\VarDumper\Dumper\HtmlDumper; -use Twig\Environment; -use Twig\Extension\ProfilerExtension; -use Twig\Profiler\Profile; -use Twig\TwigFunction; - -/** - * Twig extension for the profiler. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @internal - */ -class WebProfilerExtension extends ProfilerExtension -{ - /** - * @var HtmlDumper - */ - private $dumper; - - /** - * @var resource - */ - private $output; - - /** - * @var int - */ - private $stackLevel = 0; - - public function __construct(HtmlDumper $dumper = null) - { - $this->dumper = $dumper ?? new HtmlDumper(); - $this->dumper->setOutput($this->output = fopen('php://memory', 'r+')); - } - - public function enter(Profile $profile): void - { - ++$this->stackLevel; - } - - public function leave(Profile $profile): void - { - if (0 === --$this->stackLevel) { - $this->dumper->setOutput($this->output = fopen('php://memory', 'r+')); - } - } - - /** - * {@inheritdoc} - */ - public function getFunctions(): array - { - return [ - new TwigFunction('profiler_dump', [$this, 'dumpData'], ['is_safe' => ['html'], 'needs_environment' => true]), - new TwigFunction('profiler_dump_log', [$this, 'dumpLog'], ['is_safe' => ['html'], 'needs_environment' => true]), - ]; - } - - public function dumpData(Environment $env, Data $data, int $maxDepth = 0) - { - $this->dumper->setCharset($env->getCharset()); - $this->dumper->dump($data, null, [ - 'maxDepth' => $maxDepth, - ]); - - $dump = stream_get_contents($this->output, -1, 0); - rewind($this->output); - ftruncate($this->output, 0); - - return str_replace("\n</pre", '</pre', rtrim($dump)); - } - - public function dumpLog(Environment $env, string $message, Data $context = null) - { - $message = twig_escape_filter($env, $message); - $message = preg_replace('/&quot;(.*?)&quot;/', '&quot;<b>$1</b>&quot;', $message); - - $replacements = []; - foreach ($context ?? [] as $k => $v) { - $k = '{'.twig_escape_filter($env, $k).'}'; - if (str_contains($message, $k)) { - $replacements[$k] = $v; - } - } - - if (!$replacements) { - return '<span class="dump-inline">'.$message.'</span>'; - } - - foreach ($replacements as $k => $v) { - $replacements['&quot;<b>'.$k.'</b>&quot;'] = $replacements['&quot;'.$k.'&quot;'] = $replacements[$k] = $this->dumpData($env, $v); - } - - return '<span class="dump-inline">'.strtr($message, $replacements).'</span>'; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'profiler'; - } -} diff --git a/lib/symfony/web-profiler-bundle/WebProfilerBundle.php b/lib/symfony/web-profiler-bundle/WebProfilerBundle.php deleted file mode 100644 index 7fcc4ec47..000000000 --- a/lib/symfony/web-profiler-bundle/WebProfilerBundle.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\WebProfilerBundle; - -use Symfony\Component\HttpKernel\Bundle\Bundle; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -class WebProfilerBundle extends Bundle -{ - public function boot() - { - if ('prod' === $this->container->getParameter('kernel.environment')) { - @trigger_error('Using WebProfilerBundle in production is not supported and puts your project at risk, disable it.', \E_USER_WARNING); - } - } -} diff --git a/lib/symfony/web-profiler-bundle/composer.json b/lib/symfony/web-profiler-bundle/composer.json deleted file mode 100644 index 3f67bb6ff..000000000 --- a/lib/symfony/web-profiler-bundle/composer.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "name": "symfony/web-profiler-bundle", - "type": "symfony-bundle", - "description": "Provides a development tool that gives detailed information about the execution of any request", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/framework-bundle": "^5.3|^6.0", - "symfony/http-kernel": "^5.3|^6.0", - "symfony/polyfill-php80": "^1.16", - "symfony/routing": "^4.4|^5.0|^6.0", - "symfony/twig-bundle": "^4.4|^5.0|^6.0", - "twig/twig": "^2.13|^3.0.4" - }, - "require-dev": { - "symfony/browser-kit": "^4.4|^5.0|^6.0", - "symfony/console": "^4.4|^5.0|^6.0", - "symfony/css-selector": "^4.4|^5.0|^6.0", - "symfony/stopwatch": "^4.4|^5.0|^6.0" - }, - "conflict": { - "symfony/form": "<4.4", - "symfony/mailer": "<5.4", - "symfony/messenger": "<4.4", - "symfony/dependency-injection": "<5.2" - }, - "autoload": { - "psr-4": { "Symfony\\Bundle\\WebProfilerBundle\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/lib/symfony/yaml/CHANGELOG.md b/lib/symfony/yaml/CHANGELOG.md deleted file mode 100644 index b9561b2af..000000000 --- a/lib/symfony/yaml/CHANGELOG.md +++ /dev/null @@ -1,237 +0,0 @@ -CHANGELOG -========= - -5.4 ---- - - * Add new `lint:yaml dirname --exclude=/dirname/foo.yaml --exclude=/dirname/bar.yaml` - option to exclude one or more specific files from multiple file list - * Allow negatable for the parse tags option with `--no-parse-tags` - -5.3 ---- - - * Added `github` format support & autodetection to render errors as annotations - when running the YAML linter command in a Github Action environment. - -5.1.0 ------ - - * Added support for parsing numbers prefixed with `0o` as octal numbers. - * Deprecated support for parsing numbers starting with `0` as octal numbers. They will be parsed as strings as of Symfony 6.0. Prefix numbers with `0o` - so that they are parsed as octal numbers. - - Before: - - ```yaml - Yaml::parse('072'); - ``` - - After: - - ```yaml - Yaml::parse('0o72'); - ``` - - * Added `yaml-lint` binary. - * Deprecated using the `!php/object` and `!php/const` tags without a value. - -5.0.0 ------ - - * Removed support for mappings inside multi-line strings. - * removed support for implicit STDIN usage in the `lint:yaml` command, use `lint:yaml -` (append a dash) instead to make it explicit. - -4.4.0 ------ - - * Added support for parsing the inline notation spanning multiple lines. - * Added support to dump `null` as `~` by using the `Yaml::DUMP_NULL_AS_TILDE` flag. - * deprecated accepting STDIN implicitly when using the `lint:yaml` command, use `lint:yaml -` (append a dash) instead to make it explicit. - -4.3.0 ------ - - * Using a mapping inside a multi-line string is deprecated and will throw a `ParseException` in 5.0. - -4.2.0 ------ - - * added support for multiple files or directories in `LintCommand` - -4.0.0 ------ - - * The behavior of the non-specific tag `!` is changed and now forces - non-evaluating your values. - * complex mappings will throw a `ParseException` - * support for the comma as a group separator for floats has been dropped, use - the underscore instead - * support for the `!!php/object` tag has been dropped, use the `!php/object` - tag instead - * duplicate mapping keys throw a `ParseException` - * non-string mapping keys throw a `ParseException`, use the `Yaml::PARSE_KEYS_AS_STRINGS` - flag to cast them to strings - * `%` at the beginning of an unquoted string throw a `ParseException` - * mappings with a colon (`:`) that is not followed by a whitespace throw a - `ParseException` - * the `Dumper::setIndentation()` method has been removed - * being able to pass boolean options to the `Yaml::parse()`, `Yaml::dump()`, - `Parser::parse()`, and `Dumper::dump()` methods to configure the behavior of - the parser and dumper is no longer supported, pass bitmask flags instead - * the constructor arguments of the `Parser` class have been removed - * the `Inline` class is internal and no longer part of the BC promise - * removed support for the `!str` tag, use the `!!str` tag instead - * added support for tagged scalars. - - ```yml - Yaml::parse('!foo bar', Yaml::PARSE_CUSTOM_TAGS); - // returns TaggedValue('foo', 'bar'); - ``` - -3.4.0 ------ - - * added support for parsing YAML files using the `Yaml::parseFile()` or `Parser::parseFile()` method - - * the `Dumper`, `Parser`, and `Yaml` classes are marked as final - - * Deprecated the `!php/object:` tag which will be replaced by the - `!php/object` tag (without the colon) in 4.0. - - * Deprecated the `!php/const:` tag which will be replaced by the - `!php/const` tag (without the colon) in 4.0. - - * Support for the `!str` tag is deprecated, use the `!!str` tag instead. - - * Deprecated using the non-specific tag `!` as its behavior will change in 4.0. - It will force non-evaluating your values in 4.0. Use plain integers or `!!float` instead. - -3.3.0 ------ - - * Starting an unquoted string with a question mark followed by a space is - deprecated and will throw a `ParseException` in Symfony 4.0. - - * Deprecated support for implicitly parsing non-string mapping keys as strings. - Mapping keys that are no strings will lead to a `ParseException` in Symfony - 4.0. Use quotes to opt-in for keys to be parsed as strings. - - Before: - - ```php - $yaml = <<<YAML - null: null key - true: boolean true - 2.0: float key - YAML; - - Yaml::parse($yaml); - ``` - - After: - - ```php - - $yaml = <<<YAML - "null": null key - "true": boolean true - "2.0": float key - YAML; - - Yaml::parse($yaml); - ``` - - * Omitted mapping values will be parsed as `null`. - - * Omitting the key of a mapping is deprecated and will throw a `ParseException` in Symfony 4.0. - - * Added support for dumping empty PHP arrays as YAML sequences: - - ```php - Yaml::dump([], 0, 0, Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE); - ``` - -3.2.0 ------ - - * Mappings with a colon (`:`) that is not followed by a whitespace are deprecated - when the mapping key is not quoted and will lead to a `ParseException` in - Symfony 4.0 (e.g. `foo:bar` must be `foo: bar`). - - * Added support for parsing PHP constants: - - ```php - Yaml::parse('!php/const:PHP_INT_MAX', Yaml::PARSE_CONSTANT); - ``` - - * Support for silently ignoring duplicate mapping keys in YAML has been - deprecated and will lead to a `ParseException` in Symfony 4.0. - -3.1.0 ------ - - * Added support to dump `stdClass` and `ArrayAccess` objects as YAML mappings - through the `Yaml::DUMP_OBJECT_AS_MAP` flag. - - * Strings that are not UTF-8 encoded will be dumped as base64 encoded binary - data. - - * Added support for dumping multi line strings as literal blocks. - - * Added support for parsing base64 encoded binary data when they are tagged - with the `!!binary` tag. - - * Added support for parsing timestamps as `\DateTime` objects: - - ```php - Yaml::parse('2001-12-15 21:59:43.10 -5', Yaml::PARSE_DATETIME); - ``` - - * `\DateTime` and `\DateTimeImmutable` objects are dumped as YAML timestamps. - - * Deprecated usage of `%` at the beginning of an unquoted string. - - * Added support for customizing the YAML parser behavior through an optional bit field: - - ```php - Yaml::parse('{ "foo": "bar", "fiz": "cat" }', Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE | Yaml::PARSE_OBJECT | Yaml::PARSE_OBJECT_FOR_MAP); - ``` - - * Added support for customizing the dumped YAML string through an optional bit field: - - ```php - Yaml::dump(['foo' => new A(), 'bar' => 1], 0, 0, Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE | Yaml::DUMP_OBJECT); - ``` - -3.0.0 ------ - - * Yaml::parse() now throws an exception when a blackslash is not escaped - in double-quoted strings - -2.8.0 ------ - - * Deprecated usage of a colon in an unquoted mapping value - * Deprecated usage of @, \`, | and > at the beginning of an unquoted string - * When surrounding strings with double-quotes, you must now escape `\` characters. Not - escaping those characters (when surrounded by double-quotes) is deprecated. - - Before: - - ```yml - class: "Foo\Var" - ``` - - After: - - ```yml - class: "Foo\\Var" - ``` - -2.1.0 ------ - - * Yaml::parse() does not evaluate loaded files as PHP files by default - anymore (call Yaml::enablePhpParsing() to get back the old behavior) diff --git a/lib/symfony/yaml/Command/LintCommand.php b/lib/symfony/yaml/Command/LintCommand.php deleted file mode 100644 index 3ebd570e7..000000000 --- a/lib/symfony/yaml/Command/LintCommand.php +++ /dev/null @@ -1,289 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Yaml\Command; - -use Symfony\Component\Console\CI\GithubActionReporter; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Completion\CompletionInput; -use Symfony\Component\Console\Completion\CompletionSuggestions; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Exception\RuntimeException; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\Yaml\Exception\ParseException; -use Symfony\Component\Yaml\Parser; -use Symfony\Component\Yaml\Yaml; - -/** - * Validates YAML files syntax and outputs encountered errors. - * - * @author Grégoire Pineau <lyrixx@lyrixx.info> - * @author Robin Chalas <robin.chalas@gmail.com> - */ -class LintCommand extends Command -{ - protected static $defaultName = 'lint:yaml'; - protected static $defaultDescription = 'Lint a YAML file and outputs encountered errors'; - - private $parser; - private $format; - private $displayCorrectFiles; - private $directoryIteratorProvider; - private $isReadableProvider; - - public function __construct(string $name = null, callable $directoryIteratorProvider = null, callable $isReadableProvider = null) - { - parent::__construct($name); - - $this->directoryIteratorProvider = $directoryIteratorProvider; - $this->isReadableProvider = $isReadableProvider; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDescription(self::$defaultDescription) - ->addArgument('filename', InputArgument::IS_ARRAY, 'A file, a directory or "-" for reading from STDIN') - ->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format') - ->addOption('exclude', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Path(s) to exclude') - ->addOption('parse-tags', null, InputOption::VALUE_NEGATABLE, 'Parse custom tags', null) - ->setHelp(<<<EOF -The <info>%command.name%</info> command lints a YAML file and outputs to STDOUT -the first encountered syntax error. - -You can validates YAML contents passed from STDIN: - - <info>cat filename | php %command.full_name% -</info> - -You can also validate the syntax of a file: - - <info>php %command.full_name% filename</info> - -Or of a whole directory: - - <info>php %command.full_name% dirname</info> - <info>php %command.full_name% dirname --format=json</info> - -You can also exclude one or more specific files: - - <info>php %command.full_name% dirname --exclude="dirname/foo.yaml" --exclude="dirname/bar.yaml"</info> - -EOF - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - $io = new SymfonyStyle($input, $output); - $filenames = (array) $input->getArgument('filename'); - $excludes = $input->getOption('exclude'); - $this->format = $input->getOption('format'); - $flags = $input->getOption('parse-tags'); - - if ('github' === $this->format && !class_exists(GithubActionReporter::class)) { - throw new \InvalidArgumentException('The "github" format is only available since "symfony/console" >= 5.3.'); - } - - if (null === $this->format) { - // Autodetect format according to CI environment - $this->format = class_exists(GithubActionReporter::class) && GithubActionReporter::isGithubActionEnvironment() ? 'github' : 'txt'; - } - - $flags = $flags ? Yaml::PARSE_CUSTOM_TAGS : 0; - - $this->displayCorrectFiles = $output->isVerbose(); - - if (['-'] === $filenames) { - return $this->display($io, [$this->validate(file_get_contents('php://stdin'), $flags)]); - } - - if (!$filenames) { - throw new RuntimeException('Please provide a filename or pipe file content to STDIN.'); - } - - $filesInfo = []; - foreach ($filenames as $filename) { - if (!$this->isReadable($filename)) { - throw new RuntimeException(sprintf('File or directory "%s" is not readable.', $filename)); - } - - foreach ($this->getFiles($filename) as $file) { - if (!\in_array($file->getPathname(), $excludes, true)) { - $filesInfo[] = $this->validate(file_get_contents($file), $flags, $file); - } - } - } - - return $this->display($io, $filesInfo); - } - - private function validate(string $content, int $flags, string $file = null) - { - $prevErrorHandler = set_error_handler(function ($level, $message, $file, $line) use (&$prevErrorHandler) { - if (\E_USER_DEPRECATED === $level) { - throw new ParseException($message, $this->getParser()->getRealCurrentLineNb() + 1); - } - - return $prevErrorHandler ? $prevErrorHandler($level, $message, $file, $line) : false; - }); - - try { - $this->getParser()->parse($content, Yaml::PARSE_CONSTANT | $flags); - } catch (ParseException $e) { - return ['file' => $file, 'line' => $e->getParsedLine(), 'valid' => false, 'message' => $e->getMessage()]; - } finally { - restore_error_handler(); - } - - return ['file' => $file, 'valid' => true]; - } - - private function display(SymfonyStyle $io, array $files): int - { - switch ($this->format) { - case 'txt': - return $this->displayTxt($io, $files); - case 'json': - return $this->displayJson($io, $files); - case 'github': - return $this->displayTxt($io, $files, true); - default: - throw new InvalidArgumentException(sprintf('The format "%s" is not supported.', $this->format)); - } - } - - private function displayTxt(SymfonyStyle $io, array $filesInfo, bool $errorAsGithubAnnotations = false): int - { - $countFiles = \count($filesInfo); - $erroredFiles = 0; - $suggestTagOption = false; - - if ($errorAsGithubAnnotations) { - $githubReporter = new GithubActionReporter($io); - } - - foreach ($filesInfo as $info) { - if ($info['valid'] && $this->displayCorrectFiles) { - $io->comment('<info>OK</info>'.($info['file'] ? sprintf(' in %s', $info['file']) : '')); - } elseif (!$info['valid']) { - ++$erroredFiles; - $io->text('<error> ERROR </error>'.($info['file'] ? sprintf(' in %s', $info['file']) : '')); - $io->text(sprintf('<error> >> %s</error>', $info['message'])); - - if (false !== strpos($info['message'], 'PARSE_CUSTOM_TAGS')) { - $suggestTagOption = true; - } - - if ($errorAsGithubAnnotations) { - $githubReporter->error($info['message'], $info['file'] ?? 'php://stdin', $info['line']); - } - } - } - - if (0 === $erroredFiles) { - $io->success(sprintf('All %d YAML files contain valid syntax.', $countFiles)); - } else { - $io->warning(sprintf('%d YAML files have valid syntax and %d contain errors.%s', $countFiles - $erroredFiles, $erroredFiles, $suggestTagOption ? ' Use the --parse-tags option if you want parse custom tags.' : '')); - } - - return min($erroredFiles, 1); - } - - private function displayJson(SymfonyStyle $io, array $filesInfo): int - { - $errors = 0; - - array_walk($filesInfo, function (&$v) use (&$errors) { - $v['file'] = (string) $v['file']; - if (!$v['valid']) { - ++$errors; - } - - if (isset($v['message']) && false !== strpos($v['message'], 'PARSE_CUSTOM_TAGS')) { - $v['message'] .= ' Use the --parse-tags option if you want parse custom tags.'; - } - }); - - $io->writeln(json_encode($filesInfo, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES)); - - return min($errors, 1); - } - - private function getFiles(string $fileOrDirectory): iterable - { - if (is_file($fileOrDirectory)) { - yield new \SplFileInfo($fileOrDirectory); - - return; - } - - foreach ($this->getDirectoryIterator($fileOrDirectory) as $file) { - if (!\in_array($file->getExtension(), ['yml', 'yaml'])) { - continue; - } - - yield $file; - } - } - - private function getParser(): Parser - { - if (!$this->parser) { - $this->parser = new Parser(); - } - - return $this->parser; - } - - private function getDirectoryIterator(string $directory): iterable - { - $default = function ($directory) { - return new \RecursiveIteratorIterator( - new \RecursiveDirectoryIterator($directory, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS), - \RecursiveIteratorIterator::LEAVES_ONLY - ); - }; - - if (null !== $this->directoryIteratorProvider) { - return ($this->directoryIteratorProvider)($directory, $default); - } - - return $default($directory); - } - - private function isReadable(string $fileOrDirectory): bool - { - $default = function ($fileOrDirectory) { - return is_readable($fileOrDirectory); - }; - - if (null !== $this->isReadableProvider) { - return ($this->isReadableProvider)($fileOrDirectory, $default); - } - - return $default($fileOrDirectory); - } - - public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void - { - if ($input->mustSuggestOptionValuesFor('format')) { - $suggestions->suggestValues(['txt', 'json', 'github']); - } - } -} diff --git a/lib/symfony/yaml/Dumper.php b/lib/symfony/yaml/Dumper.php deleted file mode 100644 index 679d533cb..000000000 --- a/lib/symfony/yaml/Dumper.php +++ /dev/null @@ -1,166 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Yaml; - -use Symfony\Component\Yaml\Tag\TaggedValue; - -/** - * Dumper dumps PHP variables to YAML strings. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class Dumper -{ - /** - * The amount of spaces to use for indentation of nested nodes. - * - * @var int - */ - protected $indentation; - - public function __construct(int $indentation = 4) - { - if ($indentation < 1) { - throw new \InvalidArgumentException('The indentation must be greater than zero.'); - } - - $this->indentation = $indentation; - } - - /** - * Dumps a PHP value to YAML. - * - * @param mixed $input The PHP value - * @param int $inline The level where you switch to inline YAML - * @param int $indent The level of indentation (used internally) - * @param int $flags A bit field of Yaml::DUMP_* constants to customize the dumped YAML string - */ - public function dump($input, int $inline = 0, int $indent = 0, int $flags = 0): string - { - $output = ''; - $prefix = $indent ? str_repeat(' ', $indent) : ''; - $dumpObjectAsInlineMap = true; - - if (Yaml::DUMP_OBJECT_AS_MAP & $flags && ($input instanceof \ArrayObject || $input instanceof \stdClass)) { - $dumpObjectAsInlineMap = empty((array) $input); - } - - if ($inline <= 0 || (!\is_array($input) && !$input instanceof TaggedValue && $dumpObjectAsInlineMap) || empty($input)) { - $output .= $prefix.Inline::dump($input, $flags); - } elseif ($input instanceof TaggedValue) { - $output .= $this->dumpTaggedValue($input, $inline, $indent, $flags, $prefix); - } else { - $dumpAsMap = Inline::isHash($input); - - foreach ($input as $key => $value) { - if ('' !== $output && "\n" !== $output[-1]) { - $output .= "\n"; - } - - if (Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && \is_string($value) && false !== strpos($value, "\n") && false === strpos($value, "\r")) { - // If the first line starts with a space character, the spec requires a blockIndicationIndicator - // http://www.yaml.org/spec/1.2/spec.html#id2793979 - $blockIndentationIndicator = (' ' === substr($value, 0, 1)) ? (string) $this->indentation : ''; - - if (isset($value[-2]) && "\n" === $value[-2] && "\n" === $value[-1]) { - $blockChompingIndicator = '+'; - } elseif ("\n" === $value[-1]) { - $blockChompingIndicator = ''; - } else { - $blockChompingIndicator = '-'; - } - - $output .= sprintf('%s%s%s |%s%s', $prefix, $dumpAsMap ? Inline::dump($key, $flags).':' : '-', '', $blockIndentationIndicator, $blockChompingIndicator); - - foreach (explode("\n", $value) as $row) { - if ('' === $row) { - $output .= "\n"; - } else { - $output .= sprintf("\n%s%s%s", $prefix, str_repeat(' ', $this->indentation), $row); - } - } - - continue; - } - - if ($value instanceof TaggedValue) { - $output .= sprintf('%s%s !%s', $prefix, $dumpAsMap ? Inline::dump($key, $flags).':' : '-', $value->getTag()); - - if (Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && \is_string($value->getValue()) && false !== strpos($value->getValue(), "\n") && false === strpos($value->getValue(), "\r\n")) { - // If the first line starts with a space character, the spec requires a blockIndicationIndicator - // http://www.yaml.org/spec/1.2/spec.html#id2793979 - $blockIndentationIndicator = (' ' === substr($value->getValue(), 0, 1)) ? (string) $this->indentation : ''; - $output .= sprintf(' |%s', $blockIndentationIndicator); - - foreach (explode("\n", $value->getValue()) as $row) { - $output .= sprintf("\n%s%s%s", $prefix, str_repeat(' ', $this->indentation), $row); - } - - continue; - } - - if ($inline - 1 <= 0 || null === $value->getValue() || \is_scalar($value->getValue())) { - $output .= ' '.$this->dump($value->getValue(), $inline - 1, 0, $flags)."\n"; - } else { - $output .= "\n"; - $output .= $this->dump($value->getValue(), $inline - 1, $dumpAsMap ? $indent + $this->indentation : $indent + 2, $flags); - } - - continue; - } - - $dumpObjectAsInlineMap = true; - - if (Yaml::DUMP_OBJECT_AS_MAP & $flags && ($value instanceof \ArrayObject || $value instanceof \stdClass)) { - $dumpObjectAsInlineMap = empty((array) $value); - } - - $willBeInlined = $inline - 1 <= 0 || !\is_array($value) && $dumpObjectAsInlineMap || empty($value); - - $output .= sprintf('%s%s%s%s', - $prefix, - $dumpAsMap ? Inline::dump($key, $flags).':' : '-', - $willBeInlined ? ' ' : "\n", - $this->dump($value, $inline - 1, $willBeInlined ? 0 : $indent + $this->indentation, $flags) - ).($willBeInlined ? "\n" : ''); - } - } - - return $output; - } - - private function dumpTaggedValue(TaggedValue $value, int $inline, int $indent, int $flags, string $prefix): string - { - $output = sprintf('%s!%s', $prefix ? $prefix.' ' : '', $value->getTag()); - - if (Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && \is_string($value->getValue()) && false !== strpos($value->getValue(), "\n") && false === strpos($value->getValue(), "\r\n")) { - // If the first line starts with a space character, the spec requires a blockIndicationIndicator - // http://www.yaml.org/spec/1.2/spec.html#id2793979 - $blockIndentationIndicator = (' ' === substr($value->getValue(), 0, 1)) ? (string) $this->indentation : ''; - $output .= sprintf(' |%s', $blockIndentationIndicator); - - foreach (explode("\n", $value->getValue()) as $row) { - $output .= sprintf("\n%s%s%s", $prefix, str_repeat(' ', $this->indentation), $row); - } - - return $output; - } - - if ($inline - 1 <= 0 || null === $value->getValue() || \is_scalar($value->getValue())) { - return $output.' '.$this->dump($value->getValue(), $inline - 1, 0, $flags)."\n"; - } - - return $output."\n".$this->dump($value->getValue(), $inline - 1, $indent, $flags); - } -} diff --git a/lib/symfony/yaml/Escaper.php b/lib/symfony/yaml/Escaper.php deleted file mode 100644 index e8090d8c6..000000000 --- a/lib/symfony/yaml/Escaper.php +++ /dev/null @@ -1,95 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Yaml; - -/** - * Escaper encapsulates escaping rules for single and double-quoted - * YAML strings. - * - * @author Matthew Lewinski <matthew@lewinski.org> - * - * @internal - */ -class Escaper -{ - // Characters that would cause a dumped string to require double quoting. - public const REGEX_CHARACTER_TO_ESCAPE = "[\\x00-\\x1f]|\x7f|\xc2\x85|\xc2\xa0|\xe2\x80\xa8|\xe2\x80\xa9"; - - // Mapping arrays for escaping a double quoted string. The backslash is - // first to ensure proper escaping because str_replace operates iteratively - // on the input arrays. This ordering of the characters avoids the use of strtr, - // which performs more slowly. - private const ESCAPEES = ['\\', '\\\\', '\\"', '"', - "\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07", - "\x08", "\x09", "\x0a", "\x0b", "\x0c", "\x0d", "\x0e", "\x0f", - "\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17", - "\x18", "\x19", "\x1a", "\x1b", "\x1c", "\x1d", "\x1e", "\x1f", - "\x7f", - "\xc2\x85", "\xc2\xa0", "\xe2\x80\xa8", "\xe2\x80\xa9", - ]; - private const ESCAPED = ['\\\\', '\\"', '\\\\', '\\"', - '\\0', '\\x01', '\\x02', '\\x03', '\\x04', '\\x05', '\\x06', '\\a', - '\\b', '\\t', '\\n', '\\v', '\\f', '\\r', '\\x0e', '\\x0f', - '\\x10', '\\x11', '\\x12', '\\x13', '\\x14', '\\x15', '\\x16', '\\x17', - '\\x18', '\\x19', '\\x1a', '\\e', '\\x1c', '\\x1d', '\\x1e', '\\x1f', - '\\x7f', - '\\N', '\\_', '\\L', '\\P', - ]; - - /** - * Determines if a PHP value would require double quoting in YAML. - * - * @param string $value A PHP value - */ - public static function requiresDoubleQuoting(string $value): bool - { - return 0 < preg_match('/'.self::REGEX_CHARACTER_TO_ESCAPE.'/u', $value); - } - - /** - * Escapes and surrounds a PHP value with double quotes. - * - * @param string $value A PHP value - */ - public static function escapeWithDoubleQuotes(string $value): string - { - return sprintf('"%s"', str_replace(self::ESCAPEES, self::ESCAPED, $value)); - } - - /** - * Determines if a PHP value would require single quoting in YAML. - * - * @param string $value A PHP value - */ - public static function requiresSingleQuoting(string $value): bool - { - // Determines if a PHP value is entirely composed of a value that would - // require single quoting in YAML. - if (\in_array(strtolower($value), ['null', '~', 'true', 'false', 'y', 'n', 'yes', 'no', 'on', 'off'])) { - return true; - } - - // Determines if the PHP value contains any single characters that would - // cause it to require single quoting in YAML. - return 0 < preg_match('/[ \s \' " \: \{ \} \[ \] , & \* \# \?] | \A[ \- ? | < > = ! % @ ` \p{Zs}]/xu', $value); - } - - /** - * Escapes and surrounds a PHP value with single quotes. - * - * @param string $value A PHP value - */ - public static function escapeWithSingleQuotes(string $value): string - { - return sprintf("'%s'", str_replace('\'', '\'\'', $value)); - } -} diff --git a/lib/symfony/yaml/Exception/DumpException.php b/lib/symfony/yaml/Exception/DumpException.php deleted file mode 100644 index cce972f24..000000000 --- a/lib/symfony/yaml/Exception/DumpException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Yaml\Exception; - -/** - * Exception class thrown when an error occurs during dumping. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class DumpException extends RuntimeException -{ -} diff --git a/lib/symfony/yaml/Exception/ExceptionInterface.php b/lib/symfony/yaml/Exception/ExceptionInterface.php deleted file mode 100644 index 909131684..000000000 --- a/lib/symfony/yaml/Exception/ExceptionInterface.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Yaml\Exception; - -/** - * Exception interface for all exceptions thrown by the component. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface ExceptionInterface extends \Throwable -{ -} diff --git a/lib/symfony/yaml/Exception/ParseException.php b/lib/symfony/yaml/Exception/ParseException.php deleted file mode 100644 index 8748d2b22..000000000 --- a/lib/symfony/yaml/Exception/ParseException.php +++ /dev/null @@ -1,132 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Yaml\Exception; - -/** - * Exception class thrown when an error occurs during parsing. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class ParseException extends RuntimeException -{ - private $parsedFile; - private $parsedLine; - private $snippet; - private $rawMessage; - - /** - * @param string $message The error message - * @param int $parsedLine The line where the error occurred - * @param string|null $snippet The snippet of code near the problem - * @param string|null $parsedFile The file name where the error occurred - */ - public function __construct(string $message, int $parsedLine = -1, string $snippet = null, string $parsedFile = null, \Throwable $previous = null) - { - $this->parsedFile = $parsedFile; - $this->parsedLine = $parsedLine; - $this->snippet = $snippet; - $this->rawMessage = $message; - - $this->updateRepr(); - - parent::__construct($this->message, 0, $previous); - } - - /** - * Gets the snippet of code near the error. - * - * @return string - */ - public function getSnippet() - { - return $this->snippet; - } - - /** - * Sets the snippet of code near the error. - */ - public function setSnippet(string $snippet) - { - $this->snippet = $snippet; - - $this->updateRepr(); - } - - /** - * Gets the filename where the error occurred. - * - * This method returns null if a string is parsed. - * - * @return string - */ - public function getParsedFile() - { - return $this->parsedFile; - } - - /** - * Sets the filename where the error occurred. - */ - public function setParsedFile(string $parsedFile) - { - $this->parsedFile = $parsedFile; - - $this->updateRepr(); - } - - /** - * Gets the line where the error occurred. - * - * @return int - */ - public function getParsedLine() - { - return $this->parsedLine; - } - - /** - * Sets the line where the error occurred. - */ - public function setParsedLine(int $parsedLine) - { - $this->parsedLine = $parsedLine; - - $this->updateRepr(); - } - - private function updateRepr() - { - $this->message = $this->rawMessage; - - $dot = false; - if ('.' === substr($this->message, -1)) { - $this->message = substr($this->message, 0, -1); - $dot = true; - } - - if (null !== $this->parsedFile) { - $this->message .= sprintf(' in %s', json_encode($this->parsedFile, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE)); - } - - if ($this->parsedLine >= 0) { - $this->message .= sprintf(' at line %d', $this->parsedLine); - } - - if ($this->snippet) { - $this->message .= sprintf(' (near "%s")', $this->snippet); - } - - if ($dot) { - $this->message .= '.'; - } - } -} diff --git a/lib/symfony/yaml/Exception/RuntimeException.php b/lib/symfony/yaml/Exception/RuntimeException.php deleted file mode 100644 index 3f36b73be..000000000 --- a/lib/symfony/yaml/Exception/RuntimeException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Yaml\Exception; - -/** - * Exception class thrown when an error occurs during parsing. - * - * @author Romain Neutron <imprec@gmail.com> - */ -class RuntimeException extends \RuntimeException implements ExceptionInterface -{ -} diff --git a/lib/symfony/yaml/Inline.php b/lib/symfony/yaml/Inline.php deleted file mode 100644 index 8118a43ab..000000000 --- a/lib/symfony/yaml/Inline.php +++ /dev/null @@ -1,811 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Yaml; - -use Symfony\Component\Yaml\Exception\DumpException; -use Symfony\Component\Yaml\Exception\ParseException; -use Symfony\Component\Yaml\Tag\TaggedValue; - -/** - * Inline implements a YAML parser/dumper for the YAML inline syntax. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @internal - */ -class Inline -{ - public const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*+(?:\\\\.[^"\\\\]*+)*+)"|\'([^\']*+(?:\'\'[^\']*+)*+)\')'; - - public static $parsedLineNumber = -1; - public static $parsedFilename; - - private static $exceptionOnInvalidType = false; - private static $objectSupport = false; - private static $objectForMap = false; - private static $constantSupport = false; - - public static function initialize(int $flags, int $parsedLineNumber = null, string $parsedFilename = null) - { - self::$exceptionOnInvalidType = (bool) (Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE & $flags); - self::$objectSupport = (bool) (Yaml::PARSE_OBJECT & $flags); - self::$objectForMap = (bool) (Yaml::PARSE_OBJECT_FOR_MAP & $flags); - self::$constantSupport = (bool) (Yaml::PARSE_CONSTANT & $flags); - self::$parsedFilename = $parsedFilename; - - if (null !== $parsedLineNumber) { - self::$parsedLineNumber = $parsedLineNumber; - } - } - - /** - * Converts a YAML string to a PHP value. - * - * @param string $value A YAML string - * @param int $flags A bit field of Yaml::PARSE_* constants to customize the YAML parser behavior - * @param array $references Mapping of variable names to values - * - * @return mixed - * - * @throws ParseException - */ - public static function parse(string $value = null, int $flags = 0, array &$references = []) - { - self::initialize($flags); - - $value = trim($value); - - if ('' === $value) { - return ''; - } - - if (2 /* MB_OVERLOAD_STRING */ & (int) \ini_get('mbstring.func_overload')) { - $mbEncoding = mb_internal_encoding(); - mb_internal_encoding('ASCII'); - } - - try { - $i = 0; - $tag = self::parseTag($value, $i, $flags); - switch ($value[$i]) { - case '[': - $result = self::parseSequence($value, $flags, $i, $references); - ++$i; - break; - case '{': - $result = self::parseMapping($value, $flags, $i, $references); - ++$i; - break; - default: - $result = self::parseScalar($value, $flags, null, $i, true, $references); - } - - // some comments are allowed at the end - if (preg_replace('/\s*#.*$/A', '', substr($value, $i))) { - throw new ParseException(sprintf('Unexpected characters near "%s".', substr($value, $i)), self::$parsedLineNumber + 1, $value, self::$parsedFilename); - } - - if (null !== $tag && '' !== $tag) { - return new TaggedValue($tag, $result); - } - - return $result; - } finally { - if (isset($mbEncoding)) { - mb_internal_encoding($mbEncoding); - } - } - } - - /** - * Dumps a given PHP variable to a YAML string. - * - * @param mixed $value The PHP variable to convert - * @param int $flags A bit field of Yaml::DUMP_* constants to customize the dumped YAML string - * - * @throws DumpException When trying to dump PHP resource - */ - public static function dump($value, int $flags = 0): string - { - switch (true) { - case \is_resource($value): - if (Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE & $flags) { - throw new DumpException(sprintf('Unable to dump PHP resources in a YAML file ("%s").', get_resource_type($value))); - } - - return self::dumpNull($flags); - case $value instanceof \DateTimeInterface: - return $value->format('c'); - case $value instanceof \UnitEnum: - return sprintf('!php/const %s::%s', \get_class($value), $value->name); - case \is_object($value): - if ($value instanceof TaggedValue) { - return '!'.$value->getTag().' '.self::dump($value->getValue(), $flags); - } - - if (Yaml::DUMP_OBJECT & $flags) { - return '!php/object '.self::dump(serialize($value)); - } - - if (Yaml::DUMP_OBJECT_AS_MAP & $flags && ($value instanceof \stdClass || $value instanceof \ArrayObject)) { - $output = []; - - foreach ($value as $key => $val) { - $output[] = sprintf('%s: %s', self::dump($key, $flags), self::dump($val, $flags)); - } - - return sprintf('{ %s }', implode(', ', $output)); - } - - if (Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE & $flags) { - throw new DumpException('Object support when dumping a YAML file has been disabled.'); - } - - return self::dumpNull($flags); - case \is_array($value): - return self::dumpArray($value, $flags); - case null === $value: - return self::dumpNull($flags); - case true === $value: - return 'true'; - case false === $value: - return 'false'; - case \is_int($value): - return $value; - case is_numeric($value) && false === strpbrk($value, "\f\n\r\t\v"): - $locale = setlocale(\LC_NUMERIC, 0); - if (false !== $locale) { - setlocale(\LC_NUMERIC, 'C'); - } - if (\is_float($value)) { - $repr = (string) $value; - if (is_infinite($value)) { - $repr = str_ireplace('INF', '.Inf', $repr); - } elseif (floor($value) == $value && $repr == $value) { - // Preserve float data type since storing a whole number will result in integer value. - if (false === strpos($repr, 'E')) { - $repr = $repr.'.0'; - } - } - } else { - $repr = \is_string($value) ? "'$value'" : (string) $value; - } - if (false !== $locale) { - setlocale(\LC_NUMERIC, $locale); - } - - return $repr; - case '' == $value: - return "''"; - case self::isBinaryString($value): - return '!!binary '.base64_encode($value); - case Escaper::requiresDoubleQuoting($value): - return Escaper::escapeWithDoubleQuotes($value); - case Escaper::requiresSingleQuoting($value): - case Parser::preg_match('{^[0-9]+[_0-9]*$}', $value): - case Parser::preg_match(self::getHexRegex(), $value): - case Parser::preg_match(self::getTimestampRegex(), $value): - return Escaper::escapeWithSingleQuotes($value); - default: - return $value; - } - } - - /** - * Check if given array is hash or just normal indexed array. - * - * @param array|\ArrayObject|\stdClass $value The PHP array or array-like object to check - */ - public static function isHash($value): bool - { - if ($value instanceof \stdClass || $value instanceof \ArrayObject) { - return true; - } - - $expectedKey = 0; - - foreach ($value as $key => $val) { - if ($key !== $expectedKey++) { - return true; - } - } - - return false; - } - - /** - * Dumps a PHP array to a YAML string. - * - * @param array $value The PHP array to dump - * @param int $flags A bit field of Yaml::DUMP_* constants to customize the dumped YAML string - */ - private static function dumpArray(array $value, int $flags): string - { - // array - if (($value || Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE & $flags) && !self::isHash($value)) { - $output = []; - foreach ($value as $val) { - $output[] = self::dump($val, $flags); - } - - return sprintf('[%s]', implode(', ', $output)); - } - - // hash - $output = []; - foreach ($value as $key => $val) { - $output[] = sprintf('%s: %s', self::dump($key, $flags), self::dump($val, $flags)); - } - - return sprintf('{ %s }', implode(', ', $output)); - } - - private static function dumpNull(int $flags): string - { - if (Yaml::DUMP_NULL_AS_TILDE & $flags) { - return '~'; - } - - return 'null'; - } - - /** - * Parses a YAML scalar. - * - * @return mixed - * - * @throws ParseException When malformed inline YAML string is parsed - */ - public static function parseScalar(string $scalar, int $flags = 0, array $delimiters = null, int &$i = 0, bool $evaluate = true, array &$references = [], bool &$isQuoted = null) - { - if (\in_array($scalar[$i], ['"', "'"], true)) { - // quoted scalar - $isQuoted = true; - $output = self::parseQuotedScalar($scalar, $i); - - if (null !== $delimiters) { - $tmp = ltrim(substr($scalar, $i), " \n"); - if ('' === $tmp) { - throw new ParseException(sprintf('Unexpected end of line, expected one of "%s".', implode('', $delimiters)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); - } - if (!\in_array($tmp[0], $delimiters)) { - throw new ParseException(sprintf('Unexpected characters (%s).', substr($scalar, $i)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); - } - } - } else { - // "normal" string - $isQuoted = false; - - if (!$delimiters) { - $output = substr($scalar, $i); - $i += \strlen($output); - - // remove comments - if (Parser::preg_match('/[ \t]+#/', $output, $match, \PREG_OFFSET_CAPTURE)) { - $output = substr($output, 0, $match[0][1]); - } - } elseif (Parser::preg_match('/^(.*?)('.implode('|', $delimiters).')/', substr($scalar, $i), $match)) { - $output = $match[1]; - $i += \strlen($output); - $output = trim($output); - } else { - throw new ParseException(sprintf('Malformed inline YAML string: "%s".', $scalar), self::$parsedLineNumber + 1, null, self::$parsedFilename); - } - - // a non-quoted string cannot start with @ or ` (reserved) nor with a scalar indicator (| or >) - if ($output && ('@' === $output[0] || '`' === $output[0] || '|' === $output[0] || '>' === $output[0] || '%' === $output[0])) { - throw new ParseException(sprintf('The reserved indicator "%s" cannot start a plain scalar; you need to quote the scalar.', $output[0]), self::$parsedLineNumber + 1, $output, self::$parsedFilename); - } - - if ($evaluate) { - $output = self::evaluateScalar($output, $flags, $references, $isQuoted); - } - } - - return $output; - } - - /** - * Parses a YAML quoted scalar. - * - * @throws ParseException When malformed inline YAML string is parsed - */ - private static function parseQuotedScalar(string $scalar, int &$i = 0): string - { - if (!Parser::preg_match('/'.self::REGEX_QUOTED_STRING.'/Au', substr($scalar, $i), $match)) { - throw new ParseException(sprintf('Malformed inline YAML string: "%s".', substr($scalar, $i)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); - } - - $output = substr($match[0], 1, -1); - - $unescaper = new Unescaper(); - if ('"' == $scalar[$i]) { - $output = $unescaper->unescapeDoubleQuotedString($output); - } else { - $output = $unescaper->unescapeSingleQuotedString($output); - } - - $i += \strlen($match[0]); - - return $output; - } - - /** - * Parses a YAML sequence. - * - * @throws ParseException When malformed inline YAML string is parsed - */ - private static function parseSequence(string $sequence, int $flags, int &$i = 0, array &$references = []): array - { - $output = []; - $len = \strlen($sequence); - ++$i; - - // [foo, bar, ...] - while ($i < $len) { - if (']' === $sequence[$i]) { - return $output; - } - if (',' === $sequence[$i] || ' ' === $sequence[$i]) { - ++$i; - - continue; - } - - $tag = self::parseTag($sequence, $i, $flags); - switch ($sequence[$i]) { - case '[': - // nested sequence - $value = self::parseSequence($sequence, $flags, $i, $references); - break; - case '{': - // nested mapping - $value = self::parseMapping($sequence, $flags, $i, $references); - break; - default: - $value = self::parseScalar($sequence, $flags, [',', ']'], $i, null === $tag, $references, $isQuoted); - - // the value can be an array if a reference has been resolved to an array var - if (\is_string($value) && !$isQuoted && false !== strpos($value, ': ')) { - // embedded mapping? - try { - $pos = 0; - $value = self::parseMapping('{'.$value.'}', $flags, $pos, $references); - } catch (\InvalidArgumentException $e) { - // no, it's not - } - } - - if (!$isQuoted && \is_string($value) && '' !== $value && '&' === $value[0] && Parser::preg_match(Parser::REFERENCE_PATTERN, $value, $matches)) { - $references[$matches['ref']] = $matches['value']; - $value = $matches['value']; - } - - --$i; - } - - if (null !== $tag && '' !== $tag) { - $value = new TaggedValue($tag, $value); - } - - $output[] = $value; - - ++$i; - } - - throw new ParseException(sprintf('Malformed inline YAML string: "%s".', $sequence), self::$parsedLineNumber + 1, null, self::$parsedFilename); - } - - /** - * Parses a YAML mapping. - * - * @return array|\stdClass - * - * @throws ParseException When malformed inline YAML string is parsed - */ - private static function parseMapping(string $mapping, int $flags, int &$i = 0, array &$references = []) - { - $output = []; - $len = \strlen($mapping); - ++$i; - $allowOverwrite = false; - - // {foo: bar, bar:foo, ...} - while ($i < $len) { - switch ($mapping[$i]) { - case ' ': - case ',': - case "\n": - ++$i; - continue 2; - case '}': - if (self::$objectForMap) { - return (object) $output; - } - - return $output; - } - - // key - $offsetBeforeKeyParsing = $i; - $isKeyQuoted = \in_array($mapping[$i], ['"', "'"], true); - $key = self::parseScalar($mapping, $flags, [':', ' '], $i, false); - - if ($offsetBeforeKeyParsing === $i) { - throw new ParseException('Missing mapping key.', self::$parsedLineNumber + 1, $mapping); - } - - if ('!php/const' === $key) { - $key .= ' '.self::parseScalar($mapping, $flags, [':'], $i, false); - $key = self::evaluateScalar($key, $flags); - } - - if (false === $i = strpos($mapping, ':', $i)) { - break; - } - - if (!$isKeyQuoted) { - $evaluatedKey = self::evaluateScalar($key, $flags, $references); - - if ('' !== $key && $evaluatedKey !== $key && !\is_string($evaluatedKey) && !\is_int($evaluatedKey)) { - throw new ParseException('Implicit casting of incompatible mapping keys to strings is not supported. Quote your evaluable mapping keys instead.', self::$parsedLineNumber + 1, $mapping); - } - } - - if (!$isKeyQuoted && (!isset($mapping[$i + 1]) || !\in_array($mapping[$i + 1], [' ', ',', '[', ']', '{', '}', "\n"], true))) { - throw new ParseException('Colons must be followed by a space or an indication character (i.e. " ", ",", "[", "]", "{", "}").', self::$parsedLineNumber + 1, $mapping); - } - - if ('<<' === $key) { - $allowOverwrite = true; - } - - while ($i < $len) { - if (':' === $mapping[$i] || ' ' === $mapping[$i] || "\n" === $mapping[$i]) { - ++$i; - - continue; - } - - $tag = self::parseTag($mapping, $i, $flags); - switch ($mapping[$i]) { - case '[': - // nested sequence - $value = self::parseSequence($mapping, $flags, $i, $references); - // Spec: Keys MUST be unique; first one wins. - // Parser cannot abort this mapping earlier, since lines - // are processed sequentially. - // But overwriting is allowed when a merge node is used in current block. - if ('<<' === $key) { - foreach ($value as $parsedValue) { - $output += $parsedValue; - } - } elseif ($allowOverwrite || !isset($output[$key])) { - if (null !== $tag) { - $output[$key] = new TaggedValue($tag, $value); - } else { - $output[$key] = $value; - } - } elseif (isset($output[$key])) { - throw new ParseException(sprintf('Duplicate key "%s" detected.', $key), self::$parsedLineNumber + 1, $mapping); - } - break; - case '{': - // nested mapping - $value = self::parseMapping($mapping, $flags, $i, $references); - // Spec: Keys MUST be unique; first one wins. - // Parser cannot abort this mapping earlier, since lines - // are processed sequentially. - // But overwriting is allowed when a merge node is used in current block. - if ('<<' === $key) { - $output += $value; - } elseif ($allowOverwrite || !isset($output[$key])) { - if (null !== $tag) { - $output[$key] = new TaggedValue($tag, $value); - } else { - $output[$key] = $value; - } - } elseif (isset($output[$key])) { - throw new ParseException(sprintf('Duplicate key "%s" detected.', $key), self::$parsedLineNumber + 1, $mapping); - } - break; - default: - $value = self::parseScalar($mapping, $flags, [',', '}', "\n"], $i, null === $tag, $references, $isValueQuoted); - // Spec: Keys MUST be unique; first one wins. - // Parser cannot abort this mapping earlier, since lines - // are processed sequentially. - // But overwriting is allowed when a merge node is used in current block. - if ('<<' === $key) { - $output += $value; - } elseif ($allowOverwrite || !isset($output[$key])) { - if (!$isValueQuoted && \is_string($value) && '' !== $value && '&' === $value[0] && Parser::preg_match(Parser::REFERENCE_PATTERN, $value, $matches)) { - $references[$matches['ref']] = $matches['value']; - $value = $matches['value']; - } - - if (null !== $tag) { - $output[$key] = new TaggedValue($tag, $value); - } else { - $output[$key] = $value; - } - } elseif (isset($output[$key])) { - throw new ParseException(sprintf('Duplicate key "%s" detected.', $key), self::$parsedLineNumber + 1, $mapping); - } - --$i; - } - ++$i; - - continue 2; - } - } - - throw new ParseException(sprintf('Malformed inline YAML string: "%s".', $mapping), self::$parsedLineNumber + 1, null, self::$parsedFilename); - } - - /** - * Evaluates scalars and replaces magic values. - * - * @return mixed - * - * @throws ParseException when object parsing support was disabled and the parser detected a PHP object or when a reference could not be resolved - */ - private static function evaluateScalar(string $scalar, int $flags, array &$references = [], bool &$isQuotedString = null) - { - $isQuotedString = false; - $scalar = trim($scalar); - - if (0 === strpos($scalar, '*')) { - if (false !== $pos = strpos($scalar, '#')) { - $value = substr($scalar, 1, $pos - 2); - } else { - $value = substr($scalar, 1); - } - - // an unquoted * - if (false === $value || '' === $value) { - throw new ParseException('A reference must contain at least one character.', self::$parsedLineNumber + 1, $value, self::$parsedFilename); - } - - if (!\array_key_exists($value, $references)) { - throw new ParseException(sprintf('Reference "%s" does not exist.', $value), self::$parsedLineNumber + 1, $value, self::$parsedFilename); - } - - return $references[$value]; - } - - $scalarLower = strtolower($scalar); - - switch (true) { - case 'null' === $scalarLower: - case '' === $scalar: - case '~' === $scalar: - return null; - case 'true' === $scalarLower: - return true; - case 'false' === $scalarLower: - return false; - case '!' === $scalar[0]: - switch (true) { - case 0 === strpos($scalar, '!!str '): - $s = (string) substr($scalar, 6); - - if (\in_array($s[0] ?? '', ['"', "'"], true)) { - $isQuotedString = true; - $s = self::parseQuotedScalar($s); - } - - return $s; - case 0 === strpos($scalar, '! '): - return substr($scalar, 2); - case 0 === strpos($scalar, '!php/object'): - if (self::$objectSupport) { - if (!isset($scalar[12])) { - trigger_deprecation('symfony/yaml', '5.1', 'Using the !php/object tag without a value is deprecated.'); - - return false; - } - - return unserialize(self::parseScalar(substr($scalar, 12))); - } - - if (self::$exceptionOnInvalidType) { - throw new ParseException('Object support when parsing a YAML file has been disabled.', self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); - } - - return null; - case 0 === strpos($scalar, '!php/const'): - if (self::$constantSupport) { - if (!isset($scalar[11])) { - trigger_deprecation('symfony/yaml', '5.1', 'Using the !php/const tag without a value is deprecated.'); - - return ''; - } - - $i = 0; - if (\defined($const = self::parseScalar(substr($scalar, 11), 0, null, $i, false))) { - return \constant($const); - } - - throw new ParseException(sprintf('The constant "%s" is not defined.', $const), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); - } - if (self::$exceptionOnInvalidType) { - throw new ParseException(sprintf('The string "%s" could not be parsed as a constant. Did you forget to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); - } - - return null; - case 0 === strpos($scalar, '!!float '): - return (float) substr($scalar, 8); - case 0 === strpos($scalar, '!!binary '): - return self::evaluateBinaryScalar(substr($scalar, 9)); - } - - throw new ParseException(sprintf('The string "%s" could not be parsed as it uses an unsupported built-in tag.', $scalar), self::$parsedLineNumber, $scalar, self::$parsedFilename); - case preg_match('/^(?:\+|-)?0o(?P<value>[0-7_]++)$/', $scalar, $matches): - $value = str_replace('_', '', $matches['value']); - - if ('-' === $scalar[0]) { - return -octdec($value); - } - - return octdec($value); - case \in_array($scalar[0], ['+', '-', '.'], true) || is_numeric($scalar[0]): - if (Parser::preg_match('{^[+-]?[0-9][0-9_]*$}', $scalar)) { - $scalar = str_replace('_', '', $scalar); - } - - switch (true) { - case ctype_digit($scalar): - if (preg_match('/^0[0-7]+$/', $scalar)) { - trigger_deprecation('symfony/yaml', '5.1', 'Support for parsing numbers prefixed with 0 as octal numbers. They will be parsed as strings as of 6.0. Use "%s" to represent the octal number.', '0o'.substr($scalar, 1)); - - return octdec($scalar); - } - - $cast = (int) $scalar; - - return ($scalar === (string) $cast) ? $cast : $scalar; - case '-' === $scalar[0] && ctype_digit(substr($scalar, 1)): - if (preg_match('/^-0[0-7]+$/', $scalar)) { - trigger_deprecation('symfony/yaml', '5.1', 'Support for parsing numbers prefixed with 0 as octal numbers. They will be parsed as strings as of 6.0. Use "%s" to represent the octal number.', '-0o'.substr($scalar, 2)); - - return -octdec(substr($scalar, 1)); - } - - $cast = (int) $scalar; - - return ($scalar === (string) $cast) ? $cast : $scalar; - case is_numeric($scalar): - case Parser::preg_match(self::getHexRegex(), $scalar): - $scalar = str_replace('_', '', $scalar); - - return '0x' === $scalar[0].$scalar[1] ? hexdec($scalar) : (float) $scalar; - case '.inf' === $scalarLower: - case '.nan' === $scalarLower: - return -log(0); - case '-.inf' === $scalarLower: - return log(0); - case Parser::preg_match('/^(-|\+)?[0-9][0-9_]*(\.[0-9_]+)?$/', $scalar): - return (float) str_replace('_', '', $scalar); - case Parser::preg_match(self::getTimestampRegex(), $scalar): - // When no timezone is provided in the parsed date, YAML spec says we must assume UTC. - $time = new \DateTime($scalar, new \DateTimeZone('UTC')); - - if (Yaml::PARSE_DATETIME & $flags) { - return $time; - } - - try { - if (false !== $scalar = $time->getTimestamp()) { - return $scalar; - } - } catch (\ValueError $e) { - // no-op - } - - return $time->format('U'); - } - } - - return (string) $scalar; - } - - private static function parseTag(string $value, int &$i, int $flags): ?string - { - if ('!' !== $value[$i]) { - return null; - } - - $tagLength = strcspn($value, " \t\n[]{},", $i + 1); - $tag = substr($value, $i + 1, $tagLength); - - $nextOffset = $i + $tagLength + 1; - $nextOffset += strspn($value, ' ', $nextOffset); - - if ('' === $tag && (!isset($value[$nextOffset]) || \in_array($value[$nextOffset], [']', '}', ','], true))) { - throw new ParseException('Using the unquoted scalar value "!" is not supported. You must quote it.', self::$parsedLineNumber + 1, $value, self::$parsedFilename); - } - - // Is followed by a scalar and is a built-in tag - if ('' !== $tag && (!isset($value[$nextOffset]) || !\in_array($value[$nextOffset], ['[', '{'], true)) && ('!' === $tag[0] || 'str' === $tag || 'php/const' === $tag || 'php/object' === $tag)) { - // Manage in {@link self::evaluateScalar()} - return null; - } - - $i = $nextOffset; - - // Built-in tags - if ('' !== $tag && '!' === $tag[0]) { - throw new ParseException(sprintf('The built-in tag "!%s" is not implemented.', $tag), self::$parsedLineNumber + 1, $value, self::$parsedFilename); - } - - if ('' !== $tag && !isset($value[$i])) { - throw new ParseException(sprintf('Missing value for tag "%s".', $tag), self::$parsedLineNumber + 1, $value, self::$parsedFilename); - } - - if ('' === $tag || Yaml::PARSE_CUSTOM_TAGS & $flags) { - return $tag; - } - - throw new ParseException(sprintf('Tags support is not enabled. Enable the "Yaml::PARSE_CUSTOM_TAGS" flag to use "!%s".', $tag), self::$parsedLineNumber + 1, $value, self::$parsedFilename); - } - - public static function evaluateBinaryScalar(string $scalar): string - { - $parsedBinaryData = self::parseScalar(preg_replace('/\s/', '', $scalar)); - - if (0 !== (\strlen($parsedBinaryData) % 4)) { - throw new ParseException(sprintf('The normalized base64 encoded data (data without whitespace characters) length must be a multiple of four (%d bytes given).', \strlen($parsedBinaryData)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); - } - - if (!Parser::preg_match('#^[A-Z0-9+/]+={0,2}$#i', $parsedBinaryData)) { - throw new ParseException(sprintf('The base64 encoded data (%s) contains invalid characters.', $parsedBinaryData), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); - } - - return base64_decode($parsedBinaryData, true); - } - - private static function isBinaryString(string $value): bool - { - return !preg_match('//u', $value) || preg_match('/[^\x00\x07-\x0d\x1B\x20-\xff]/', $value); - } - - /** - * Gets a regex that matches a YAML date. - * - * @see http://www.yaml.org/spec/1.2/spec.html#id2761573 - */ - private static function getTimestampRegex(): string - { - return <<<EOF - ~^ - (?P<year>[0-9][0-9][0-9][0-9]) - -(?P<month>[0-9][0-9]?) - -(?P<day>[0-9][0-9]?) - (?:(?:[Tt]|[ \t]+) - (?P<hour>[0-9][0-9]?) - :(?P<minute>[0-9][0-9]) - :(?P<second>[0-9][0-9]) - (?:\.(?P<fraction>[0-9]*))? - (?:[ \t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?) - (?::(?P<tz_minute>[0-9][0-9]))?))?)? - $~x -EOF; - } - - /** - * Gets a regex that matches a YAML number in hexadecimal notation. - */ - private static function getHexRegex(): string - { - return '~^0x[0-9a-f_]++$~i'; - } -} diff --git a/lib/symfony/yaml/LICENSE b/lib/symfony/yaml/LICENSE deleted file mode 100644 index 008370457..000000000 --- a/lib/symfony/yaml/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -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/lib/symfony/yaml/Parser.php b/lib/symfony/yaml/Parser.php deleted file mode 100644 index d8886bb18..000000000 --- a/lib/symfony/yaml/Parser.php +++ /dev/null @@ -1,1305 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Yaml; - -use Symfony\Component\Yaml\Exception\ParseException; -use Symfony\Component\Yaml\Tag\TaggedValue; - -/** - * Parser parses YAML strings to convert them to PHP arrays. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class Parser -{ - public const TAG_PATTERN = '(?P<tag>![\w!.\/:-]+)'; - public const BLOCK_SCALAR_HEADER_PATTERN = '(?P<separator>\||>)(?P<modifiers>\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P<comments> +#.*)?'; - public const REFERENCE_PATTERN = '#^&(?P<ref>[^ ]++) *+(?P<value>.*)#u'; - - private $filename; - private $offset = 0; - private $numberOfParsedLines = 0; - private $totalNumberOfLines; - private $lines = []; - private $currentLineNb = -1; - private $currentLine = ''; - private $refs = []; - private $skippedLineNumbers = []; - private $locallySkippedLineNumbers = []; - private $refsBeingParsed = []; - - /** - * Parses a YAML file into a PHP value. - * - * @param string $filename The path to the YAML file to be parsed - * @param int $flags A bit field of Yaml::PARSE_* constants to customize the YAML parser behavior - * - * @return mixed - * - * @throws ParseException If the file could not be read or the YAML is not valid - */ - public function parseFile(string $filename, int $flags = 0) - { - if (!is_file($filename)) { - throw new ParseException(sprintf('File "%s" does not exist.', $filename)); - } - - if (!is_readable($filename)) { - throw new ParseException(sprintf('File "%s" cannot be read.', $filename)); - } - - $this->filename = $filename; - - try { - return $this->parse(file_get_contents($filename), $flags); - } finally { - $this->filename = null; - } - } - - /** - * Parses a YAML string to a PHP value. - * - * @param string $value A YAML string - * @param int $flags A bit field of Yaml::PARSE_* constants to customize the YAML parser behavior - * - * @return mixed - * - * @throws ParseException If the YAML is not valid - */ - public function parse(string $value, int $flags = 0) - { - if (false === preg_match('//u', $value)) { - throw new ParseException('The YAML value does not appear to be valid UTF-8.', -1, null, $this->filename); - } - - $this->refs = []; - - $mbEncoding = null; - - if (2 /* MB_OVERLOAD_STRING */ & (int) \ini_get('mbstring.func_overload')) { - $mbEncoding = mb_internal_encoding(); - mb_internal_encoding('UTF-8'); - } - - try { - $data = $this->doParse($value, $flags); - } finally { - if (null !== $mbEncoding) { - mb_internal_encoding($mbEncoding); - } - $this->refsBeingParsed = []; - $this->offset = 0; - $this->lines = []; - $this->currentLine = ''; - $this->numberOfParsedLines = 0; - $this->refs = []; - $this->skippedLineNumbers = []; - $this->locallySkippedLineNumbers = []; - $this->totalNumberOfLines = null; - } - - return $data; - } - - private function doParse(string $value, int $flags) - { - $this->currentLineNb = -1; - $this->currentLine = ''; - $value = $this->cleanup($value); - $this->lines = explode("\n", $value); - $this->numberOfParsedLines = \count($this->lines); - $this->locallySkippedLineNumbers = []; - - if (null === $this->totalNumberOfLines) { - $this->totalNumberOfLines = $this->numberOfParsedLines; - } - - if (!$this->moveToNextLine()) { - return null; - } - - $data = []; - $context = null; - $allowOverwrite = false; - - while ($this->isCurrentLineEmpty()) { - if (!$this->moveToNextLine()) { - return null; - } - } - - // Resolves the tag and returns if end of the document - if (null !== ($tag = $this->getLineTag($this->currentLine, $flags, false)) && !$this->moveToNextLine()) { - return new TaggedValue($tag, ''); - } - - do { - if ($this->isCurrentLineEmpty()) { - continue; - } - - // tab? - if ("\t" === $this->currentLine[0]) { - throw new ParseException('A YAML file cannot contain tabs as indentation.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); - } - - Inline::initialize($flags, $this->getRealCurrentLineNb(), $this->filename); - - $isRef = $mergeNode = false; - if ('-' === $this->currentLine[0] && self::preg_match('#^\-((?P<leadspaces>\s+)(?P<value>.+))?$#u', rtrim($this->currentLine), $values)) { - if ($context && 'mapping' == $context) { - throw new ParseException('You cannot define a sequence item when in a mapping.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); - } - $context = 'sequence'; - - if (isset($values['value']) && '&' === $values['value'][0] && self::preg_match(self::REFERENCE_PATTERN, $values['value'], $matches)) { - $isRef = $matches['ref']; - $this->refsBeingParsed[] = $isRef; - $values['value'] = $matches['value']; - } - - if (isset($values['value'][1]) && '?' === $values['value'][0] && ' ' === $values['value'][1]) { - throw new ParseException('Complex mappings are not supported.', $this->getRealCurrentLineNb() + 1, $this->currentLine); - } - - // array - if (isset($values['value']) && 0 === strpos(ltrim($values['value'], ' '), '-')) { - // Inline first child - $currentLineNumber = $this->getRealCurrentLineNb(); - - $sequenceIndentation = \strlen($values['leadspaces']) + 1; - $sequenceYaml = substr($this->currentLine, $sequenceIndentation); - $sequenceYaml .= "\n".$this->getNextEmbedBlock($sequenceIndentation, true); - - $data[] = $this->parseBlock($currentLineNumber, rtrim($sequenceYaml), $flags); - } elseif (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) { - $data[] = $this->parseBlock($this->getRealCurrentLineNb() + 1, $this->getNextEmbedBlock(null, true) ?? '', $flags); - } elseif (null !== $subTag = $this->getLineTag(ltrim($values['value'], ' '), $flags)) { - $data[] = new TaggedValue( - $subTag, - $this->parseBlock($this->getRealCurrentLineNb() + 1, $this->getNextEmbedBlock(null, true), $flags) - ); - } else { - if ( - isset($values['leadspaces']) - && ( - '!' === $values['value'][0] - || self::preg_match('#^(?P<key>'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\{\[].*?) *\:(\s+(?P<value>.+?))?\s*$#u', $this->trimTag($values['value']), $matches) - ) - ) { - // this is a compact notation element, add to next block and parse - $block = $values['value']; - if ($this->isNextLineIndented()) { - $block .= "\n".$this->getNextEmbedBlock($this->getCurrentLineIndentation() + \strlen($values['leadspaces']) + 1); - } - - $data[] = $this->parseBlock($this->getRealCurrentLineNb(), $block, $flags); - } else { - $data[] = $this->parseValue($values['value'], $flags, $context); - } - } - if ($isRef) { - $this->refs[$isRef] = end($data); - array_pop($this->refsBeingParsed); - } - } elseif ( - self::preg_match('#^(?P<key>(?:![^\s]++\s++)?(?:'.Inline::REGEX_QUOTED_STRING.'|(?:!?!php/const:)?[^ \'"\[\{!].*?)) *\:(( |\t)++(?P<value>.+))?$#u', rtrim($this->currentLine), $values) - && (false === strpos($values['key'], ' #') || \in_array($values['key'][0], ['"', "'"])) - ) { - if ($context && 'sequence' == $context) { - throw new ParseException('You cannot define a mapping item when in a sequence.', $this->currentLineNb + 1, $this->currentLine, $this->filename); - } - $context = 'mapping'; - - try { - $key = Inline::parseScalar($values['key']); - } catch (ParseException $e) { - $e->setParsedLine($this->getRealCurrentLineNb() + 1); - $e->setSnippet($this->currentLine); - - throw $e; - } - - if (!\is_string($key) && !\is_int($key)) { - throw new ParseException((is_numeric($key) ? 'Numeric' : 'Non-string').' keys are not supported. Quote your evaluable mapping keys instead.', $this->getRealCurrentLineNb() + 1, $this->currentLine); - } - - // Convert float keys to strings, to avoid being converted to integers by PHP - if (\is_float($key)) { - $key = (string) $key; - } - - if ('<<' === $key && (!isset($values['value']) || '&' !== $values['value'][0] || !self::preg_match('#^&(?P<ref>[^ ]+)#u', $values['value'], $refMatches))) { - $mergeNode = true; - $allowOverwrite = true; - if (isset($values['value'][0]) && '*' === $values['value'][0]) { - $refName = substr(rtrim($values['value']), 1); - if (!\array_key_exists($refName, $this->refs)) { - if (false !== $pos = array_search($refName, $this->refsBeingParsed, true)) { - throw new ParseException(sprintf('Circular reference [%s] detected for reference "%s".', implode(', ', array_merge(\array_slice($this->refsBeingParsed, $pos), [$refName])), $refName), $this->currentLineNb + 1, $this->currentLine, $this->filename); - } - - throw new ParseException(sprintf('Reference "%s" does not exist.', $refName), $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); - } - - $refValue = $this->refs[$refName]; - - if (Yaml::PARSE_OBJECT_FOR_MAP & $flags && $refValue instanceof \stdClass) { - $refValue = (array) $refValue; - } - - if (!\is_array($refValue)) { - throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); - } - - $data += $refValue; // array union - } else { - if (isset($values['value']) && '' !== $values['value']) { - $value = $values['value']; - } else { - $value = $this->getNextEmbedBlock(); - } - $parsed = $this->parseBlock($this->getRealCurrentLineNb() + 1, $value, $flags); - - if (Yaml::PARSE_OBJECT_FOR_MAP & $flags && $parsed instanceof \stdClass) { - $parsed = (array) $parsed; - } - - if (!\is_array($parsed)) { - throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); - } - - if (isset($parsed[0])) { - // If the value associated with the merge key is a sequence, then this sequence is expected to contain mapping nodes - // and each of these nodes is merged in turn according to its order in the sequence. Keys in mapping nodes earlier - // in the sequence override keys specified in later mapping nodes. - foreach ($parsed as $parsedItem) { - if (Yaml::PARSE_OBJECT_FOR_MAP & $flags && $parsedItem instanceof \stdClass) { - $parsedItem = (array) $parsedItem; - } - - if (!\is_array($parsedItem)) { - throw new ParseException('Merge items must be arrays.', $this->getRealCurrentLineNb() + 1, $parsedItem, $this->filename); - } - - $data += $parsedItem; // array union - } - } else { - // If the value associated with the key is a single mapping node, each of its key/value pairs is inserted into the - // current mapping, unless the key already exists in it. - $data += $parsed; // array union - } - } - } elseif ('<<' !== $key && isset($values['value']) && '&' === $values['value'][0] && self::preg_match(self::REFERENCE_PATTERN, $values['value'], $matches)) { - $isRef = $matches['ref']; - $this->refsBeingParsed[] = $isRef; - $values['value'] = $matches['value']; - } - - $subTag = null; - if ($mergeNode) { - // Merge keys - } elseif (!isset($values['value']) || '' === $values['value'] || 0 === strpos($values['value'], '#') || (null !== $subTag = $this->getLineTag($values['value'], $flags)) || '<<' === $key) { - // hash - // if next line is less indented or equal, then it means that the current value is null - if (!$this->isNextLineIndented() && !$this->isNextLineUnIndentedCollection()) { - // Spec: Keys MUST be unique; first one wins. - // But overwriting is allowed when a merge node is used in current block. - if ($allowOverwrite || !isset($data[$key])) { - if (null !== $subTag) { - $data[$key] = new TaggedValue($subTag, ''); - } else { - $data[$key] = null; - } - } else { - throw new ParseException(sprintf('Duplicate key "%s" detected.', $key), $this->getRealCurrentLineNb() + 1, $this->currentLine); - } - } else { - // remember the parsed line number here in case we need it to provide some contexts in error messages below - $realCurrentLineNbKey = $this->getRealCurrentLineNb(); - $value = $this->parseBlock($this->getRealCurrentLineNb() + 1, $this->getNextEmbedBlock(), $flags); - if ('<<' === $key) { - $this->refs[$refMatches['ref']] = $value; - - if (Yaml::PARSE_OBJECT_FOR_MAP & $flags && $value instanceof \stdClass) { - $value = (array) $value; - } - - $data += $value; - } elseif ($allowOverwrite || !isset($data[$key])) { - // Spec: Keys MUST be unique; first one wins. - // But overwriting is allowed when a merge node is used in current block. - if (null !== $subTag) { - $data[$key] = new TaggedValue($subTag, $value); - } else { - $data[$key] = $value; - } - } else { - throw new ParseException(sprintf('Duplicate key "%s" detected.', $key), $realCurrentLineNbKey + 1, $this->currentLine); - } - } - } else { - $value = $this->parseValue(rtrim($values['value']), $flags, $context); - // Spec: Keys MUST be unique; first one wins. - // But overwriting is allowed when a merge node is used in current block. - if ($allowOverwrite || !isset($data[$key])) { - $data[$key] = $value; - } else { - throw new ParseException(sprintf('Duplicate key "%s" detected.', $key), $this->getRealCurrentLineNb() + 1, $this->currentLine); - } - } - if ($isRef) { - $this->refs[$isRef] = $data[$key]; - array_pop($this->refsBeingParsed); - } - } elseif ('"' === $this->currentLine[0] || "'" === $this->currentLine[0]) { - if (null !== $context) { - throw new ParseException('Unable to parse.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); - } - - try { - return Inline::parse($this->lexInlineQuotedString(), $flags, $this->refs); - } catch (ParseException $e) { - $e->setParsedLine($this->getRealCurrentLineNb() + 1); - $e->setSnippet($this->currentLine); - - throw $e; - } - } elseif ('{' === $this->currentLine[0]) { - if (null !== $context) { - throw new ParseException('Unable to parse.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); - } - - try { - $parsedMapping = Inline::parse($this->lexInlineMapping(), $flags, $this->refs); - - while ($this->moveToNextLine()) { - if (!$this->isCurrentLineEmpty()) { - throw new ParseException('Unable to parse.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); - } - } - - return $parsedMapping; - } catch (ParseException $e) { - $e->setParsedLine($this->getRealCurrentLineNb() + 1); - $e->setSnippet($this->currentLine); - - throw $e; - } - } elseif ('[' === $this->currentLine[0]) { - if (null !== $context) { - throw new ParseException('Unable to parse.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); - } - - try { - $parsedSequence = Inline::parse($this->lexInlineSequence(), $flags, $this->refs); - - while ($this->moveToNextLine()) { - if (!$this->isCurrentLineEmpty()) { - throw new ParseException('Unable to parse.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); - } - } - - return $parsedSequence; - } catch (ParseException $e) { - $e->setParsedLine($this->getRealCurrentLineNb() + 1); - $e->setSnippet($this->currentLine); - - throw $e; - } - } else { - // multiple documents are not supported - if ('---' === $this->currentLine) { - throw new ParseException('Multiple documents are not supported.', $this->currentLineNb + 1, $this->currentLine, $this->filename); - } - - if ($deprecatedUsage = (isset($this->currentLine[1]) && '?' === $this->currentLine[0] && ' ' === $this->currentLine[1])) { - throw new ParseException('Complex mappings are not supported.', $this->getRealCurrentLineNb() + 1, $this->currentLine); - } - - // 1-liner optionally followed by newline(s) - if (\is_string($value) && $this->lines[0] === trim($value)) { - try { - $value = Inline::parse($this->lines[0], $flags, $this->refs); - } catch (ParseException $e) { - $e->setParsedLine($this->getRealCurrentLineNb() + 1); - $e->setSnippet($this->currentLine); - - throw $e; - } - - return $value; - } - - // try to parse the value as a multi-line string as a last resort - if (0 === $this->currentLineNb) { - $previousLineWasNewline = false; - $previousLineWasTerminatedWithBackslash = false; - $value = ''; - - foreach ($this->lines as $line) { - $trimmedLine = trim($line); - if ('#' === ($trimmedLine[0] ?? '')) { - continue; - } - // If the indentation is not consistent at offset 0, it is to be considered as a ParseError - if (0 === $this->offset && !$deprecatedUsage && isset($line[0]) && ' ' === $line[0]) { - throw new ParseException('Unable to parse.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); - } - - if (false !== strpos($line, ': ')) { - throw new ParseException('Mapping values are not allowed in multi-line blocks.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); - } - - if ('' === $trimmedLine) { - $value .= "\n"; - } elseif (!$previousLineWasNewline && !$previousLineWasTerminatedWithBackslash) { - $value .= ' '; - } - - if ('' !== $trimmedLine && '\\' === substr($line, -1)) { - $value .= ltrim(substr($line, 0, -1)); - } elseif ('' !== $trimmedLine) { - $value .= $trimmedLine; - } - - if ('' === $trimmedLine) { - $previousLineWasNewline = true; - $previousLineWasTerminatedWithBackslash = false; - } elseif ('\\' === substr($line, -1)) { - $previousLineWasNewline = false; - $previousLineWasTerminatedWithBackslash = true; - } else { - $previousLineWasNewline = false; - $previousLineWasTerminatedWithBackslash = false; - } - } - - try { - return Inline::parse(trim($value)); - } catch (ParseException $e) { - // fall-through to the ParseException thrown below - } - } - - throw new ParseException('Unable to parse.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); - } - } while ($this->moveToNextLine()); - - if (null !== $tag) { - $data = new TaggedValue($tag, $data); - } - - if (Yaml::PARSE_OBJECT_FOR_MAP & $flags && 'mapping' === $context && !\is_object($data)) { - $object = new \stdClass(); - - foreach ($data as $key => $value) { - $object->$key = $value; - } - - $data = $object; - } - - return empty($data) ? null : $data; - } - - private function parseBlock(int $offset, string $yaml, int $flags) - { - $skippedLineNumbers = $this->skippedLineNumbers; - - foreach ($this->locallySkippedLineNumbers as $lineNumber) { - if ($lineNumber < $offset) { - continue; - } - - $skippedLineNumbers[] = $lineNumber; - } - - $parser = new self(); - $parser->offset = $offset; - $parser->totalNumberOfLines = $this->totalNumberOfLines; - $parser->skippedLineNumbers = $skippedLineNumbers; - $parser->refs = &$this->refs; - $parser->refsBeingParsed = $this->refsBeingParsed; - - return $parser->doParse($yaml, $flags); - } - - /** - * Returns the current line number (takes the offset into account). - * - * @internal - */ - public function getRealCurrentLineNb(): int - { - $realCurrentLineNumber = $this->currentLineNb + $this->offset; - - foreach ($this->skippedLineNumbers as $skippedLineNumber) { - if ($skippedLineNumber > $realCurrentLineNumber) { - break; - } - - ++$realCurrentLineNumber; - } - - return $realCurrentLineNumber; - } - - /** - * Returns the current line indentation. - */ - private function getCurrentLineIndentation(): int - { - if (' ' !== ($this->currentLine[0] ?? '')) { - return 0; - } - - return \strlen($this->currentLine) - \strlen(ltrim($this->currentLine, ' ')); - } - - /** - * Returns the next embed block of YAML. - * - * @param int|null $indentation The indent level at which the block is to be read, or null for default - * @param bool $inSequence True if the enclosing data structure is a sequence - * - * @throws ParseException When indentation problem are detected - */ - private function getNextEmbedBlock(int $indentation = null, bool $inSequence = false): string - { - $oldLineIndentation = $this->getCurrentLineIndentation(); - - if (!$this->moveToNextLine()) { - return ''; - } - - if (null === $indentation) { - $newIndent = null; - $movements = 0; - - do { - $EOF = false; - - // empty and comment-like lines do not influence the indentation depth - if ($this->isCurrentLineEmpty() || $this->isCurrentLineComment()) { - $EOF = !$this->moveToNextLine(); - - if (!$EOF) { - ++$movements; - } - } else { - $newIndent = $this->getCurrentLineIndentation(); - } - } while (!$EOF && null === $newIndent); - - for ($i = 0; $i < $movements; ++$i) { - $this->moveToPreviousLine(); - } - - $unindentedEmbedBlock = $this->isStringUnIndentedCollectionItem(); - - if (!$this->isCurrentLineEmpty() && 0 === $newIndent && !$unindentedEmbedBlock) { - throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); - } - } else { - $newIndent = $indentation; - } - - $data = []; - - if ($this->getCurrentLineIndentation() >= $newIndent) { - $data[] = substr($this->currentLine, $newIndent ?? 0); - } elseif ($this->isCurrentLineEmpty() || $this->isCurrentLineComment()) { - $data[] = $this->currentLine; - } else { - $this->moveToPreviousLine(); - - return ''; - } - - if ($inSequence && $oldLineIndentation === $newIndent && isset($data[0][0]) && '-' === $data[0][0]) { - // the previous line contained a dash but no item content, this line is a sequence item with the same indentation - // and therefore no nested list or mapping - $this->moveToPreviousLine(); - - return ''; - } - - $isItUnindentedCollection = $this->isStringUnIndentedCollectionItem(); - $isItComment = $this->isCurrentLineComment(); - - while ($this->moveToNextLine()) { - if ($isItComment && !$isItUnindentedCollection) { - $isItUnindentedCollection = $this->isStringUnIndentedCollectionItem(); - $isItComment = $this->isCurrentLineComment(); - } - - $indent = $this->getCurrentLineIndentation(); - - if ($isItUnindentedCollection && !$this->isCurrentLineEmpty() && !$this->isStringUnIndentedCollectionItem() && $newIndent === $indent) { - $this->moveToPreviousLine(); - break; - } - - if ($this->isCurrentLineBlank()) { - $data[] = substr($this->currentLine, $newIndent); - continue; - } - - if ($indent >= $newIndent) { - $data[] = substr($this->currentLine, $newIndent); - } elseif ($this->isCurrentLineComment()) { - $data[] = $this->currentLine; - } elseif (0 == $indent) { - $this->moveToPreviousLine(); - - break; - } else { - throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); - } - } - - return implode("\n", $data); - } - - private function hasMoreLines(): bool - { - return (\count($this->lines) - 1) > $this->currentLineNb; - } - - /** - * Moves the parser to the next line. - */ - private function moveToNextLine(): bool - { - if ($this->currentLineNb >= $this->numberOfParsedLines - 1) { - return false; - } - - $this->currentLine = $this->lines[++$this->currentLineNb]; - - return true; - } - - /** - * Moves the parser to the previous line. - */ - private function moveToPreviousLine(): bool - { - if ($this->currentLineNb < 1) { - return false; - } - - $this->currentLine = $this->lines[--$this->currentLineNb]; - - return true; - } - - /** - * Parses a YAML value. - * - * @param string $value A YAML value - * @param int $flags A bit field of Yaml::PARSE_* constants to customize the YAML parser behavior - * @param string $context The parser context (either sequence or mapping) - * - * @return mixed - * - * @throws ParseException When reference does not exist - */ - private function parseValue(string $value, int $flags, string $context) - { - if (0 === strpos($value, '*')) { - if (false !== $pos = strpos($value, '#')) { - $value = substr($value, 1, $pos - 2); - } else { - $value = substr($value, 1); - } - - if (!\array_key_exists($value, $this->refs)) { - if (false !== $pos = array_search($value, $this->refsBeingParsed, true)) { - throw new ParseException(sprintf('Circular reference [%s] detected for reference "%s".', implode(', ', array_merge(\array_slice($this->refsBeingParsed, $pos), [$value])), $value), $this->currentLineNb + 1, $this->currentLine, $this->filename); - } - - throw new ParseException(sprintf('Reference "%s" does not exist.', $value), $this->currentLineNb + 1, $this->currentLine, $this->filename); - } - - return $this->refs[$value]; - } - - if (\in_array($value[0], ['!', '|', '>'], true) && self::preg_match('/^(?:'.self::TAG_PATTERN.' +)?'.self::BLOCK_SCALAR_HEADER_PATTERN.'$/', $value, $matches)) { - $modifiers = $matches['modifiers'] ?? ''; - - $data = $this->parseBlockScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), abs((int) $modifiers)); - - if ('' !== $matches['tag'] && '!' !== $matches['tag']) { - if ('!!binary' === $matches['tag']) { - return Inline::evaluateBinaryScalar($data); - } - - return new TaggedValue(substr($matches['tag'], 1), $data); - } - - return $data; - } - - try { - if ('' !== $value && '{' === $value[0]) { - $cursor = \strlen(rtrim($this->currentLine)) - \strlen(rtrim($value)); - - return Inline::parse($this->lexInlineMapping($cursor), $flags, $this->refs); - } elseif ('' !== $value && '[' === $value[0]) { - $cursor = \strlen(rtrim($this->currentLine)) - \strlen(rtrim($value)); - - return Inline::parse($this->lexInlineSequence($cursor), $flags, $this->refs); - } - - switch ($value[0] ?? '') { - case '"': - case "'": - $cursor = \strlen(rtrim($this->currentLine)) - \strlen(rtrim($value)); - $parsedValue = Inline::parse($this->lexInlineQuotedString($cursor), $flags, $this->refs); - - if (isset($this->currentLine[$cursor]) && preg_replace('/\s*(#.*)?$/A', '', substr($this->currentLine, $cursor))) { - throw new ParseException(sprintf('Unexpected characters near "%s".', substr($this->currentLine, $cursor))); - } - - return $parsedValue; - default: - $lines = []; - - while ($this->moveToNextLine()) { - // unquoted strings end before the first unindented line - if (0 === $this->getCurrentLineIndentation()) { - $this->moveToPreviousLine(); - - break; - } - - $lines[] = trim($this->currentLine); - } - - for ($i = 0, $linesCount = \count($lines), $previousLineBlank = false; $i < $linesCount; ++$i) { - if ('' === $lines[$i]) { - $value .= "\n"; - $previousLineBlank = true; - } elseif ($previousLineBlank) { - $value .= $lines[$i]; - $previousLineBlank = false; - } else { - $value .= ' '.$lines[$i]; - $previousLineBlank = false; - } - } - - Inline::$parsedLineNumber = $this->getRealCurrentLineNb(); - - $parsedValue = Inline::parse($value, $flags, $this->refs); - - if ('mapping' === $context && \is_string($parsedValue) && '"' !== $value[0] && "'" !== $value[0] && '[' !== $value[0] && '{' !== $value[0] && '!' !== $value[0] && false !== strpos($parsedValue, ': ')) { - throw new ParseException('A colon cannot be used in an unquoted mapping value.', $this->getRealCurrentLineNb() + 1, $value, $this->filename); - } - - return $parsedValue; - } - } catch (ParseException $e) { - $e->setParsedLine($this->getRealCurrentLineNb() + 1); - $e->setSnippet($this->currentLine); - - throw $e; - } - } - - /** - * Parses a block scalar. - * - * @param string $style The style indicator that was used to begin this block scalar (| or >) - * @param string $chomping The chomping indicator that was used to begin this block scalar (+ or -) - * @param int $indentation The indentation indicator that was used to begin this block scalar - */ - private function parseBlockScalar(string $style, string $chomping = '', int $indentation = 0): string - { - $notEOF = $this->moveToNextLine(); - if (!$notEOF) { - return ''; - } - - $isCurrentLineBlank = $this->isCurrentLineBlank(); - $blockLines = []; - - // leading blank lines are consumed before determining indentation - while ($notEOF && $isCurrentLineBlank) { - // newline only if not EOF - if ($notEOF = $this->moveToNextLine()) { - $blockLines[] = ''; - $isCurrentLineBlank = $this->isCurrentLineBlank(); - } - } - - // determine indentation if not specified - if (0 === $indentation) { - $currentLineLength = \strlen($this->currentLine); - - for ($i = 0; $i < $currentLineLength && ' ' === $this->currentLine[$i]; ++$i) { - ++$indentation; - } - } - - if ($indentation > 0) { - $pattern = sprintf('/^ {%d}(.*)$/', $indentation); - - while ( - $notEOF && ( - $isCurrentLineBlank || - self::preg_match($pattern, $this->currentLine, $matches) - ) - ) { - if ($isCurrentLineBlank && \strlen($this->currentLine) > $indentation) { - $blockLines[] = substr($this->currentLine, $indentation); - } elseif ($isCurrentLineBlank) { - $blockLines[] = ''; - } else { - $blockLines[] = $matches[1]; - } - - // newline only if not EOF - if ($notEOF = $this->moveToNextLine()) { - $isCurrentLineBlank = $this->isCurrentLineBlank(); - } - } - } elseif ($notEOF) { - $blockLines[] = ''; - } - - if ($notEOF) { - $blockLines[] = ''; - $this->moveToPreviousLine(); - } elseif (!$notEOF && !$this->isCurrentLineLastLineInDocument()) { - $blockLines[] = ''; - } - - // folded style - if ('>' === $style) { - $text = ''; - $previousLineIndented = false; - $previousLineBlank = false; - - for ($i = 0, $blockLinesCount = \count($blockLines); $i < $blockLinesCount; ++$i) { - if ('' === $blockLines[$i]) { - $text .= "\n"; - $previousLineIndented = false; - $previousLineBlank = true; - } elseif (' ' === $blockLines[$i][0]) { - $text .= "\n".$blockLines[$i]; - $previousLineIndented = true; - $previousLineBlank = false; - } elseif ($previousLineIndented) { - $text .= "\n".$blockLines[$i]; - $previousLineIndented = false; - $previousLineBlank = false; - } elseif ($previousLineBlank || 0 === $i) { - $text .= $blockLines[$i]; - $previousLineIndented = false; - $previousLineBlank = false; - } else { - $text .= ' '.$blockLines[$i]; - $previousLineIndented = false; - $previousLineBlank = false; - } - } - } else { - $text = implode("\n", $blockLines); - } - - // deal with trailing newlines - if ('' === $chomping) { - $text = preg_replace('/\n+$/', "\n", $text); - } elseif ('-' === $chomping) { - $text = preg_replace('/\n+$/', '', $text); - } - - return $text; - } - - /** - * Returns true if the next line is indented. - */ - private function isNextLineIndented(): bool - { - $currentIndentation = $this->getCurrentLineIndentation(); - $movements = 0; - - do { - $EOF = !$this->moveToNextLine(); - - if (!$EOF) { - ++$movements; - } - } while (!$EOF && ($this->isCurrentLineEmpty() || $this->isCurrentLineComment())); - - if ($EOF) { - return false; - } - - $ret = $this->getCurrentLineIndentation() > $currentIndentation; - - for ($i = 0; $i < $movements; ++$i) { - $this->moveToPreviousLine(); - } - - return $ret; - } - - /** - * Returns true if the current line is blank or if it is a comment line. - */ - private function isCurrentLineEmpty(): bool - { - return $this->isCurrentLineBlank() || $this->isCurrentLineComment(); - } - - /** - * Returns true if the current line is blank. - */ - private function isCurrentLineBlank(): bool - { - return '' === $this->currentLine || '' === trim($this->currentLine, ' '); - } - - /** - * Returns true if the current line is a comment line. - */ - private function isCurrentLineComment(): bool - { - // checking explicitly the first char of the trim is faster than loops or strpos - $ltrimmedLine = '' !== $this->currentLine && ' ' === $this->currentLine[0] ? ltrim($this->currentLine, ' ') : $this->currentLine; - - return '' !== $ltrimmedLine && '#' === $ltrimmedLine[0]; - } - - private function isCurrentLineLastLineInDocument(): bool - { - return ($this->offset + $this->currentLineNb) >= ($this->totalNumberOfLines - 1); - } - - /** - * Cleanups a YAML string to be parsed. - * - * @param string $value The input YAML string - */ - private function cleanup(string $value): string - { - $value = str_replace(["\r\n", "\r"], "\n", $value); - - // strip YAML header - $count = 0; - $value = preg_replace('#^\%YAML[: ][\d\.]+.*\n#u', '', $value, -1, $count); - $this->offset += $count; - - // remove leading comments - $trimmedValue = preg_replace('#^(\#.*?\n)+#s', '', $value, -1, $count); - if (1 === $count) { - // items have been removed, update the offset - $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n"); - $value = $trimmedValue; - } - - // remove start of the document marker (---) - $trimmedValue = preg_replace('#^\-\-\-.*?\n#s', '', $value, -1, $count); - if (1 === $count) { - // items have been removed, update the offset - $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n"); - $value = $trimmedValue; - - // remove end of the document marker (...) - $value = preg_replace('#\.\.\.\s*$#', '', $value); - } - - return $value; - } - - /** - * Returns true if the next line starts unindented collection. - */ - private function isNextLineUnIndentedCollection(): bool - { - $currentIndentation = $this->getCurrentLineIndentation(); - $movements = 0; - - do { - $EOF = !$this->moveToNextLine(); - - if (!$EOF) { - ++$movements; - } - } while (!$EOF && ($this->isCurrentLineEmpty() || $this->isCurrentLineComment())); - - if ($EOF) { - return false; - } - - $ret = $this->getCurrentLineIndentation() === $currentIndentation && $this->isStringUnIndentedCollectionItem(); - - for ($i = 0; $i < $movements; ++$i) { - $this->moveToPreviousLine(); - } - - return $ret; - } - - /** - * Returns true if the string is un-indented collection item. - */ - private function isStringUnIndentedCollectionItem(): bool - { - return '-' === rtrim($this->currentLine) || 0 === strpos($this->currentLine, '- '); - } - - /** - * A local wrapper for "preg_match" which will throw a ParseException if there - * is an internal error in the PCRE engine. - * - * This avoids us needing to check for "false" every time PCRE is used - * in the YAML engine - * - * @throws ParseException on a PCRE internal error - * - * @see preg_last_error() - * - * @internal - */ - public static function preg_match(string $pattern, string $subject, array &$matches = null, int $flags = 0, int $offset = 0): int - { - if (false === $ret = preg_match($pattern, $subject, $matches, $flags, $offset)) { - switch (preg_last_error()) { - case \PREG_INTERNAL_ERROR: - $error = 'Internal PCRE error.'; - break; - case \PREG_BACKTRACK_LIMIT_ERROR: - $error = 'pcre.backtrack_limit reached.'; - break; - case \PREG_RECURSION_LIMIT_ERROR: - $error = 'pcre.recursion_limit reached.'; - break; - case \PREG_BAD_UTF8_ERROR: - $error = 'Malformed UTF-8 data.'; - break; - case \PREG_BAD_UTF8_OFFSET_ERROR: - $error = 'Offset doesn\'t correspond to the begin of a valid UTF-8 code point.'; - break; - default: - $error = 'Error.'; - } - - throw new ParseException($error); - } - - return $ret; - } - - /** - * Trim the tag on top of the value. - * - * Prevent values such as "!foo {quz: bar}" to be considered as - * a mapping block. - */ - private function trimTag(string $value): string - { - if ('!' === $value[0]) { - return ltrim(substr($value, 1, strcspn($value, " \r\n", 1)), ' '); - } - - return $value; - } - - private function getLineTag(string $value, int $flags, bool $nextLineCheck = true): ?string - { - if ('' === $value || '!' !== $value[0] || 1 !== self::preg_match('/^'.self::TAG_PATTERN.' *( +#.*)?$/', $value, $matches)) { - return null; - } - - if ($nextLineCheck && !$this->isNextLineIndented()) { - return null; - } - - $tag = substr($matches['tag'], 1); - - // Built-in tags - if ($tag && '!' === $tag[0]) { - throw new ParseException(sprintf('The built-in tag "!%s" is not implemented.', $tag), $this->getRealCurrentLineNb() + 1, $value, $this->filename); - } - - if (Yaml::PARSE_CUSTOM_TAGS & $flags) { - return $tag; - } - - throw new ParseException(sprintf('Tags support is not enabled. You must use the flag "Yaml::PARSE_CUSTOM_TAGS" to use "%s".', $matches['tag']), $this->getRealCurrentLineNb() + 1, $value, $this->filename); - } - - private function lexInlineQuotedString(int &$cursor = 0): string - { - $quotation = $this->currentLine[$cursor]; - $value = $quotation; - ++$cursor; - - $previousLineWasNewline = true; - $previousLineWasTerminatedWithBackslash = false; - $lineNumber = 0; - - do { - if (++$lineNumber > 1) { - $cursor += strspn($this->currentLine, ' ', $cursor); - } - - if ($this->isCurrentLineBlank()) { - $value .= "\n"; - } elseif (!$previousLineWasNewline && !$previousLineWasTerminatedWithBackslash) { - $value .= ' '; - } - - for (; \strlen($this->currentLine) > $cursor; ++$cursor) { - switch ($this->currentLine[$cursor]) { - case '\\': - if ("'" === $quotation) { - $value .= '\\'; - } elseif (isset($this->currentLine[++$cursor])) { - $value .= '\\'.$this->currentLine[$cursor]; - } - - break; - case $quotation: - ++$cursor; - - if ("'" === $quotation && isset($this->currentLine[$cursor]) && "'" === $this->currentLine[$cursor]) { - $value .= "''"; - break; - } - - return $value.$quotation; - default: - $value .= $this->currentLine[$cursor]; - } - } - - if ($this->isCurrentLineBlank()) { - $previousLineWasNewline = true; - $previousLineWasTerminatedWithBackslash = false; - } elseif ('\\' === $this->currentLine[-1]) { - $previousLineWasNewline = false; - $previousLineWasTerminatedWithBackslash = true; - } else { - $previousLineWasNewline = false; - $previousLineWasTerminatedWithBackslash = false; - } - - if ($this->hasMoreLines()) { - $cursor = 0; - } - } while ($this->moveToNextLine()); - - throw new ParseException('Malformed inline YAML string.'); - } - - private function lexUnquotedString(int &$cursor): string - { - $offset = $cursor; - $cursor += strcspn($this->currentLine, '[]{},: ', $cursor); - - if ($cursor === $offset) { - throw new ParseException('Malformed unquoted YAML string.'); - } - - return substr($this->currentLine, $offset, $cursor - $offset); - } - - private function lexInlineMapping(int &$cursor = 0): string - { - return $this->lexInlineStructure($cursor, '}'); - } - - private function lexInlineSequence(int &$cursor = 0): string - { - return $this->lexInlineStructure($cursor, ']'); - } - - private function lexInlineStructure(int &$cursor, string $closingTag): string - { - $value = $this->currentLine[$cursor]; - ++$cursor; - - do { - $this->consumeWhitespaces($cursor); - - while (isset($this->currentLine[$cursor])) { - switch ($this->currentLine[$cursor]) { - case '"': - case "'": - $value .= $this->lexInlineQuotedString($cursor); - break; - case ':': - case ',': - $value .= $this->currentLine[$cursor]; - ++$cursor; - break; - case '{': - $value .= $this->lexInlineMapping($cursor); - break; - case '[': - $value .= $this->lexInlineSequence($cursor); - break; - case $closingTag: - $value .= $this->currentLine[$cursor]; - ++$cursor; - - return $value; - case '#': - break 2; - default: - $value .= $this->lexUnquotedString($cursor); - } - - if ($this->consumeWhitespaces($cursor)) { - $value .= ' '; - } - } - - if ($this->hasMoreLines()) { - $cursor = 0; - } - } while ($this->moveToNextLine()); - - throw new ParseException('Malformed inline YAML string.'); - } - - private function consumeWhitespaces(int &$cursor): bool - { - $whitespacesConsumed = 0; - - do { - $whitespaceOnlyTokenLength = strspn($this->currentLine, ' ', $cursor); - $whitespacesConsumed += $whitespaceOnlyTokenLength; - $cursor += $whitespaceOnlyTokenLength; - - if (isset($this->currentLine[$cursor])) { - return 0 < $whitespacesConsumed; - } - - if ($this->hasMoreLines()) { - $cursor = 0; - } - } while ($this->moveToNextLine()); - - return 0 < $whitespacesConsumed; - } -} diff --git a/lib/symfony/yaml/README.md b/lib/symfony/yaml/README.md deleted file mode 100644 index ac25024b6..000000000 --- a/lib/symfony/yaml/README.md +++ /dev/null @@ -1,13 +0,0 @@ -Yaml Component -============== - -The Yaml component loads and dumps YAML files. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/yaml.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/lib/symfony/yaml/Resources/bin/yaml-lint b/lib/symfony/yaml/Resources/bin/yaml-lint deleted file mode 100644 index 143869e01..000000000 --- a/lib/symfony/yaml/Resources/bin/yaml-lint +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env php -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -if ('cli' !== \PHP_SAPI) { - throw new Exception('This script must be run from the command line.'); -} - -/** - * Runs the Yaml lint command. - * - * @author Jan Schädlich <jan.schaedlich@sensiolabs.de> - */ - -use Symfony\Component\Console\Application; -use Symfony\Component\Yaml\Command\LintCommand; - -function includeIfExists(string $file): bool -{ - return file_exists($file) && include $file; -} - -if ( - !includeIfExists(__DIR__ . '/../../../../autoload.php') && - !includeIfExists(__DIR__ . '/../../vendor/autoload.php') && - !includeIfExists(__DIR__ . '/../../../../../../vendor/autoload.php') -) { - fwrite(STDERR, 'Install dependencies using Composer.'.PHP_EOL); - exit(1); -} - -if (!class_exists(Application::class)) { - fwrite(STDERR, 'You need the "symfony/console" component in order to run the Yaml linter.'.PHP_EOL); - exit(1); -} - -(new Application())->add($command = new LintCommand()) - ->getApplication() - ->setDefaultCommand($command->getName(), true) - ->run() -; diff --git a/lib/symfony/yaml/Tag/TaggedValue.php b/lib/symfony/yaml/Tag/TaggedValue.php deleted file mode 100644 index 4ea340613..000000000 --- a/lib/symfony/yaml/Tag/TaggedValue.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Yaml\Tag; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * @author Guilhem N. <egetick@gmail.com> - */ -final class TaggedValue -{ - private $tag; - private $value; - - public function __construct(string $tag, $value) - { - $this->tag = $tag; - $this->value = $value; - } - - public function getTag(): string - { - return $this->tag; - } - - public function getValue() - { - return $this->value; - } -} diff --git a/lib/symfony/yaml/Unescaper.php b/lib/symfony/yaml/Unescaper.php deleted file mode 100644 index d1ef04123..000000000 --- a/lib/symfony/yaml/Unescaper.php +++ /dev/null @@ -1,132 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Yaml; - -use Symfony\Component\Yaml\Exception\ParseException; - -/** - * Unescaper encapsulates unescaping rules for single and double-quoted - * YAML strings. - * - * @author Matthew Lewinski <matthew@lewinski.org> - * - * @internal - */ -class Unescaper -{ - /** - * Regex fragment that matches an escaped character in a double quoted string. - */ - public const REGEX_ESCAPED_CHARACTER = '\\\\(x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8}|.)'; - - /** - * Unescapes a single quoted string. - * - * @param string $value A single quoted string - */ - public function unescapeSingleQuotedString(string $value): string - { - return str_replace('\'\'', '\'', $value); - } - - /** - * Unescapes a double quoted string. - * - * @param string $value A double quoted string - */ - public function unescapeDoubleQuotedString(string $value): string - { - $callback = function ($match) { - return $this->unescapeCharacter($match[0]); - }; - - // evaluate the string - return preg_replace_callback('/'.self::REGEX_ESCAPED_CHARACTER.'/u', $callback, $value); - } - - /** - * Unescapes a character that was found in a double-quoted string. - * - * @param string $value An escaped character - */ - private function unescapeCharacter(string $value): string - { - switch ($value[1]) { - case '0': - return "\x0"; - case 'a': - return "\x7"; - case 'b': - return "\x8"; - case 't': - return "\t"; - case "\t": - return "\t"; - case 'n': - return "\n"; - case 'v': - return "\xB"; - case 'f': - return "\xC"; - case 'r': - return "\r"; - case 'e': - return "\x1B"; - case ' ': - return ' '; - case '"': - return '"'; - case '/': - return '/'; - case '\\': - return '\\'; - case 'N': - // U+0085 NEXT LINE - return "\xC2\x85"; - case '_': - // U+00A0 NO-BREAK SPACE - return "\xC2\xA0"; - case 'L': - // U+2028 LINE SEPARATOR - return "\xE2\x80\xA8"; - case 'P': - // U+2029 PARAGRAPH SEPARATOR - return "\xE2\x80\xA9"; - case 'x': - return self::utf8chr(hexdec(substr($value, 2, 2))); - case 'u': - return self::utf8chr(hexdec(substr($value, 2, 4))); - case 'U': - return self::utf8chr(hexdec(substr($value, 2, 8))); - default: - throw new ParseException(sprintf('Found unknown escape character "%s".', $value)); - } - } - - /** - * Get the UTF-8 character for the given code point. - */ - private static function utf8chr(int $c): string - { - if (0x80 > $c %= 0x200000) { - return \chr($c); - } - if (0x800 > $c) { - return \chr(0xC0 | $c >> 6).\chr(0x80 | $c & 0x3F); - } - if (0x10000 > $c) { - return \chr(0xE0 | $c >> 12).\chr(0x80 | $c >> 6 & 0x3F).\chr(0x80 | $c & 0x3F); - } - - return \chr(0xF0 | $c >> 18).\chr(0x80 | $c >> 12 & 0x3F).\chr(0x80 | $c >> 6 & 0x3F).\chr(0x80 | $c & 0x3F); - } -} diff --git a/lib/symfony/yaml/Yaml.php b/lib/symfony/yaml/Yaml.php deleted file mode 100644 index ea1304528..000000000 --- a/lib/symfony/yaml/Yaml.php +++ /dev/null @@ -1,100 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Yaml; - -use Symfony\Component\Yaml\Exception\ParseException; - -/** - * Yaml offers convenience methods to load and dump YAML. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class Yaml -{ - public const DUMP_OBJECT = 1; - public const PARSE_EXCEPTION_ON_INVALID_TYPE = 2; - public const PARSE_OBJECT = 4; - public const PARSE_OBJECT_FOR_MAP = 8; - public const DUMP_EXCEPTION_ON_INVALID_TYPE = 16; - public const PARSE_DATETIME = 32; - public const DUMP_OBJECT_AS_MAP = 64; - public const DUMP_MULTI_LINE_LITERAL_BLOCK = 128; - public const PARSE_CONSTANT = 256; - public const PARSE_CUSTOM_TAGS = 512; - public const DUMP_EMPTY_ARRAY_AS_SEQUENCE = 1024; - public const DUMP_NULL_AS_TILDE = 2048; - - /** - * Parses a YAML file into a PHP value. - * - * Usage: - * - * $array = Yaml::parseFile('config.yml'); - * print_r($array); - * - * @param string $filename The path to the YAML file to be parsed - * @param int $flags A bit field of PARSE_* constants to customize the YAML parser behavior - * - * @return mixed - * - * @throws ParseException If the file could not be read or the YAML is not valid - */ - public static function parseFile(string $filename, int $flags = 0) - { - $yaml = new Parser(); - - return $yaml->parseFile($filename, $flags); - } - - /** - * Parses YAML into a PHP value. - * - * Usage: - * <code> - * $array = Yaml::parse(file_get_contents('config.yml')); - * print_r($array); - * </code> - * - * @param string $input A string containing YAML - * @param int $flags A bit field of PARSE_* constants to customize the YAML parser behavior - * - * @return mixed - * - * @throws ParseException If the YAML is not valid - */ - public static function parse(string $input, int $flags = 0) - { - $yaml = new Parser(); - - return $yaml->parse($input, $flags); - } - - /** - * Dumps a PHP value to a YAML string. - * - * The dump method, when supplied with an array, will do its best - * to convert the array into friendly YAML. - * - * @param mixed $input The PHP value - * @param int $inline The level where you switch to inline YAML - * @param int $indent The amount of spaces to use for indentation of nested nodes - * @param int $flags A bit field of DUMP_* constants to customize the dumped YAML string - */ - public static function dump($input, int $inline = 2, int $indent = 4, int $flags = 0): string - { - $yaml = new Dumper($indent); - - return $yaml->dump($input, $inline, 0, $flags); - } -} diff --git a/lib/symfony/yaml/composer.json b/lib/symfony/yaml/composer.json deleted file mode 100644 index 7fa6e2cc5..000000000 --- a/lib/symfony/yaml/composer.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "symfony/yaml", - "type": "library", - "description": "Loads and dumps YAML files", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-ctype": "^1.8" - }, - "require-dev": { - "symfony/console": "^5.3|^6.0" - }, - "conflict": { - "symfony/console": "<5.3" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\Yaml\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "bin": [ - "Resources/bin/yaml-lint" - ], - "minimum-stability": "dev" -} diff --git a/lib/thenetworg/oauth2-azure/.devcontainer/Dockerfile b/lib/thenetworg/oauth2-azure/.devcontainer/Dockerfile deleted file mode 100644 index 35ab8f9c4..000000000 --- a/lib/thenetworg/oauth2-azure/.devcontainer/Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.134.0/containers/php/.devcontainer/base.Dockerfile -ARG VARIANT="7" -FROM mcr.microsoft.com/vscode/devcontainers/php:0-${VARIANT} - -# [Optional] Install a version of Node.js using nvm for front end dev -ARG INSTALL_NODE="true" -ARG NODE_VERSION="lts/*" -RUN if [ "${INSTALL_NODE}" = "true" ]; then su vscode -c "source /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi - -# [Optional] Uncomment this section to install additional OS packages. -# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ -# && apt-get -y install --no-install-recommends <your-package-list-here> - -# [Optional] Uncomment this line to install global node packages. -# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1 \ No newline at end of file diff --git a/lib/thenetworg/oauth2-azure/.devcontainer/devcontainer.json b/lib/thenetworg/oauth2-azure/.devcontainer/devcontainer.json deleted file mode 100644 index 676de3dcb..000000000 --- a/lib/thenetworg/oauth2-azure/.devcontainer/devcontainer.json +++ /dev/null @@ -1,29 +0,0 @@ -// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at: -// https://github.com/microsoft/vscode-dev-containers/tree/v0.134.0/containers/php -{ - "name": "PHP", - "build": { - "dockerfile": "Dockerfile", - "args": { - // Update VARIANT to pick a PHP version: 7, 7.4, 7.3 - "VARIANT": "7", - "INSTALL_NODE": "false", - "NODE_VERSION": "lts/*" - } - }, - // Set *default* container specific settings.json values on container create. - "settings": { - "terminal.integrated.shell.linux": "/bin/bash" - }, - // Add the IDs of extensions you want installed when the container is created. - "extensions": [ - "felixfbecker.php-debug", - "felixfbecker.php-intellisense" - ], - // Use 'forwardPorts' to make a list of ports inside the container available locally. - // "forwardPorts": [], - // Use 'postCreateCommand' to run commands after the container is created. - // "postCreateCommand": "php -v", - // Comment out to connect as root instead. - "remoteUser": "vscode" -} \ No newline at end of file diff --git a/lib/thenetworg/oauth2-azure/.gitignore b/lib/thenetworg/oauth2-azure/.gitignore deleted file mode 100644 index 57a23bd06..000000000 --- a/lib/thenetworg/oauth2-azure/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -/build -/vendor -composer.phar -composer.lock -.DS_Store - -# IDE -/.idea -/.vscode diff --git a/lib/thenetworg/oauth2-azure/.php_cs b/lib/thenetworg/oauth2-azure/.php_cs deleted file mode 100644 index 47be3dfc0..000000000 --- a/lib/thenetworg/oauth2-azure/.php_cs +++ /dev/null @@ -1,70 +0,0 @@ -<?php - -$finder = PhpCsFixer\Finder::create() - ->in(__DIR__ . '/src'); - -return PhpCsFixer\Config::create() - ->setRiskyAllowed(true) - ->setUsingCache(false) - ->setRules([ - '@PSR2' => true, - 'align_multiline_comment' => true, - 'array_indentation' => true, - 'array_syntax' => ['syntax' => 'short'], - 'binary_operator_spaces' => ['default' => 'align_single_space_minimal'], - 'blank_line_after_opening_tag' => true, - 'class_attributes_separation' => true, - 'combine_consecutive_issets' => true, - 'general_phpdoc_annotation_remove' => ['annotations' => ['author', 'package', 'subpackage']], - 'declare_equal_normalize' => ['space' => 'single'], - 'dir_constant' => true, - 'fully_qualified_strict_types' => true, - 'function_typehint_space' => true, - 'heredoc_to_nowdoc' => true, - 'include' => true, - 'is_null' => ['use_yoda_style' => true], - 'linebreak_after_opening_tag' => true, - 'lowercase_cast' => true, - 'modernize_types_casting' => true, - 'new_with_braces' => true, - 'no_alias_functions' => true, - 'no_alternative_syntax' => true, - 'no_blank_lines_after_phpdoc' => true, - 'no_empty_comment' => true, - 'no_empty_phpdoc' => true, - 'no_empty_statement' => true, - 'no_leading_import_slash' => true, - 'no_leading_namespace_whitespace' => true, - 'no_mixed_echo_print' => ['use' => 'echo'], - 'no_multiline_whitespace_before_semicolons' => true, - 'no_null_property_initialization' => true, - 'no_php4_constructor' => true, - 'no_short_echo_tag' => false, - 'no_unreachable_default_argument_value' => true, - 'no_useless_else' => true, - 'no_useless_return' => true, - 'ordered_class_elements' => true, - 'ordered_imports' => true, - 'phpdoc_add_missing_param_annotation' => ['only_untyped' => false], - 'phpdoc_order' => true, - 'phpdoc_return_self_reference' => true, - 'phpdoc_scalar' => true, - 'phpdoc_single_line_var_spacing' => true, - 'phpdoc_to_comment' => true, - 'phpdoc_trim' => true, - 'phpdoc_types' => true, - 'phpdoc_types_order' => ['null_adjustment' => 'always_last'], - 'phpdoc_var_without_name' => true, - 'short_scalar_cast' => true, - 'simplified_null_return' => true, - 'single_blank_line_before_namespace' => true, - 'single_line_comment_style' => true, - 'single_quote' => ['strings_containing_single_quote_chars' => true], - 'standardize_increment' => true, - 'standardize_not_equals' => true, - 'trailing_comma_in_multiline_array' => true, - 'trim_array_spaces' => true, - 'whitespace_after_comma_in_array' => true, - 'yoda_style' => true, - ]) - ->setFinder($finder); diff --git a/lib/thenetworg/oauth2-azure/.vscode/launch.json b/lib/thenetworg/oauth2-azure/.vscode/launch.json deleted file mode 100644 index c69965a9e..000000000 --- a/lib/thenetworg/oauth2-azure/.vscode/launch.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Launch application", - "type": "php", - "request": "launch", - "program": "${workspaceFolder}/index.php", - "cwd": "${workspaceFolder}", - "port": 9000 - }, - { - "name": "Listen for XDebug", - "type": "php", - "request": "launch", - "port": 9000 - }, - { - "name": "Launch currently open script", - "type": "php", - "request": "launch", - "program": "${file}", - "cwd": "${fileDirname}", - "port": 9000 - } - ] -} \ No newline at end of file diff --git a/lib/thenetworg/oauth2-azure/CHANGELOG.md b/lib/thenetworg/oauth2-azure/CHANGELOG.md deleted file mode 100644 index 689c66685..000000000 --- a/lib/thenetworg/oauth2-azure/CHANGELOG.md +++ /dev/null @@ -1,5 +0,0 @@ -# Changelog -All Notable changes to `oauth2-azure` will be documented in this file - -## v1.0.0 - 16NOV2015 -- Initial release \ No newline at end of file diff --git a/lib/thenetworg/oauth2-azure/LICENSE.md b/lib/thenetworg/oauth2-azure/LICENSE.md deleted file mode 100644 index 196dd8655..000000000 --- a/lib/thenetworg/oauth2-azure/LICENSE.md +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2016 TheNetw.org - -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/lib/thenetworg/oauth2-azure/README.md b/lib/thenetworg/oauth2-azure/README.md deleted file mode 100644 index ee6f06d3f..000000000 --- a/lib/thenetworg/oauth2-azure/README.md +++ /dev/null @@ -1,283 +0,0 @@ -# Azure Active Directory Provider for OAuth 2.0 Client -[![Latest Version](https://img.shields.io/github/release/thenetworg/oauth2-azure.svg?style=flat-square)](https://github.com/thenetworg/oauth2-azure/releases) -[![Total Downloads](https://img.shields.io/packagist/dt/thenetworg/oauth2-azure.svg?style=flat-square)](https://packagist.org/packages/thenetworg/oauth2-azure) -[![Software License](https://img.shields.io/packagist/l/thenetworg/oauth2-azure.svg?style=flat-square)](LICENSE.md) - -This package provides [Azure Active Directory](https://azure.microsoft.com/en-us/services/active-directory/) OAuth 2.0 support for the PHP League's [OAuth 2.0 Client](https://github.com/thephpleague/oauth2-client). - -## Table of Contents -- [Installation](#installation) -- [Usage](#usage) - - [Authorization Code Flow](#authorization-code-flow) - - [Advanced flow](#advanced-flow) - - [Using custom parameters](#using-custom-parameters) - - [**NEW** - Call on behalf of a token provided by another app](#call-on-behalf-of-a-token-provided-by-another-app) - - [**NEW** - Logging out](#logging-out) -- [Making API Requests](#making-api-requests) - - [Variables](#variables) -- [Resource Owner](#resource-owner) -- [**UPDATED** - Microsoft Graph](#microsoft-graph) -- [**NEW** - Protecting your API - *experimental*](#protecting-your-api---experimental) -- [Azure Active Directory B2C - *experimental*](#azure-active-directory-b2c---experimental) -- [Multipurpose refresh tokens - *experimental*](#multipurpose-refresh-tokens---experimental) -- [Known users](#known-users) -- [Contributing](#contributing) -- [Credits](#credits) -- [Support](#support) -- [License](#license) - -## Installation - -To install, use composer: - -``` -composer require thenetworg/oauth2-azure -``` - -## Usage - -Usage is the same as The League's OAuth client, using `\TheNetworg\OAuth2\Client\Provider\Azure` as the provider. - -### Authorization Code Flow - -```php -$provider = new TheNetworg\OAuth2\Client\Provider\Azure([ - 'clientId' => '{azure-client-id}', - 'clientSecret' => '{azure-client-secret}', - 'redirectUri' => 'https://example.com/callback-url', - //Optional - 'scopes' => ['openid'], - //Optional - 'defaultEndPointVersion' => '2.0' -]); - -// Set to use v2 API, skip the line or set the value to Azure::ENDPOINT_VERSION_1_0 if willing to use v1 API -$provider->defaultEndPointVersion = TheNetworg\OAuth2\Client\Provider\Azure::ENDPOINT_VERSION_2_0; - -$baseGraphUri = $provider->getRootMicrosoftGraphUri(null); -$provider->scope = 'openid profile email offline_access ' . $baseGraphUri . '/User.Read'; - -if (isset($_GET['code']) && isset($_SESSION['OAuth2.state']) && isset($_GET['state'])) { - if ($_GET['state'] == $_SESSION['OAuth2.state']) { - unset($_SESSION['OAuth2.state']); - - // Try to get an access token (using the authorization code grant) - /** @var AccessToken $token */ - $token = $provider->getAccessToken('authorization_code', [ - 'scope' => $provider->scope, - 'code' => $_GET['code'], - ]); - - // Verify token - // Save it to local server session data - - return $token->getToken(); - } else { - echo 'Invalid state'; - - return null; - } -} else { - // // Check local server's session data for a token - // // and verify if still valid - // /** @var ?AccessToken $token */ - // $token = // token cached in session data, null if not found; - // - // if (isset($token)) { - // $me = $provider->get($provider->getRootMicrosoftGraphUri($token) . '/v1.0/me', $token); - // $userEmail = $me['mail']; - // - // if ($token->hasExpired()) { - // if (!is_null($token->getRefreshToken())) { - // $token = $provider->getAccessToken('refresh_token', [ - // 'scope' => $provider->scope, - // 'refresh_token' => $token->getRefreshToken() - // ]); - // } else { - // $token = null; - // } - // } - //} - // - // If the token is not found in - // if (!isset($token)) { - $authorizationUrl = $provider->getAuthorizationUrl(['scope' => $provider->scope]); - - $_SESSION['OAuth2.state'] = $provider->getState(); - - header('Location: ' . $authorizationUrl); - - exit; - // } - - return $token->getToken(); -} -``` - -#### Advanced flow - -The [Authorization Code Grant Flow](https://msdn.microsoft.com/en-us/library/azure/dn645542.aspx) is a little bit different for Azure Active Directory. Instead of scopes, you specify the resource which you would like to access - there is a param `$provider->authWithResource` which will automatically populate the `resource` param of request with the value of either `$provider->resource` or `$provider->urlAPI`. This feature is mostly intended for v2.0 endpoint of Azure AD (see more [here](https://docs.microsoft.com/en-us/azure/active-directory/develop/azure-ad-endpoint-comparison#scopes-not-resources)). - -#### Using custom parameters - -With [oauth2-client](https://github.com/thephpleague/oauth2-client) of version 1.3.0 and higher, it is now possible to specify custom parameters for the authorization URL, so you can now make use of options like `prompt`, `login_hint` and similar. See the following example of obtaining an authorization URL which will force the user to reauthenticate: -```php -$authUrl = $provider->getAuthorizationUrl([ - 'prompt' => 'login' -]); -``` -You can find additional parameters [here](https://msdn.microsoft.com/en-us/library/azure/dn645542.aspx). - -### Logging out -If you need to quickly generate a logout URL for the user, you can do following: -```php -// Assuming you have provider properly initialized. -$post_logout_redirect_uri = 'https://www.msn.com'; // The logout destination after the user is logged out from their account. -$logoutUrl = $provider->getLogoutUrl($post_logout_redirect_uri); -header('Location: '.$logoutUrl); // Redirect the user to the generated URL -``` - -#### Call on behalf of a token provided by another app - -```php -// Use token provided by the other app -// Make sure the other app mentioned this app in the scope when requesting the token -$suppliedToken = ''; - -$provider = xxxxx;// Initialize provider - -// Call this to get claims -// $claims = $provider->validateAccessToken($suppliedToken); - -/** @var AccessToken $token */ -$token = $provider->getAccessToken('jwt_bearer', [ - 'scope' => $provider->scope, - 'assertion' => $suppliedToken, - 'requested_token_use' => 'on_behalf_of', -]); -``` - -## Making API Requests - -This library also provides easy interface to make it easier to interact with [Azure Graph API](https://msdn.microsoft.com/en-us/library/azure/hh974476.aspx) and [Microsoft Graph](http://graph.microsoft.io), the following methods are available on `provider` object (it also handles automatic token refresh flow should it be needed during making the request): - -- `get($ref, $accessToken, $headers = [])` -- `post($ref, $body, $accessToken, $headers = [])` -- `put($ref, $body, $accessToken, $headers = [])` -- `delete($ref, $body, $accessToken, $headers = [])` -- `patch($ref, $body, $accessToken, $headers = [])` -- `getObjects($tenant, $ref, $accessToken, $headers = [])` This is used for example for listing large amount of data - where you need to list all users for example - it automatically follows `odata.nextLink` until the end. - - `$tenant` tenant has to be provided since the `odata.nextLink` doesn't contain it. -- `request($method, $ref, $accessToken, $options = [])` See [#36](https://github.com/TheNetworg/oauth2-azure/issues/36) for use case. - -*Please note that if you need to create a custom request, the method getAuthenticatedRequest and getResponse can still be used.* - -### Variables -- `$ref` The URL reference without the leading `/`, for example `myOrganization/groups` -- `$body` The contents of the request, make has to be either string (so make sure to use `json_encode` to encode the request)s or stream (see [Guzzle HTTP](http://docs.guzzlephp.org/en/latest/request-options.html#body)) -- `$accessToken` The access token object obtained by using `getAccessToken` method -- `$headers` Ability to set custom headers for the request (see [Guzzle HTTP](http://docs.guzzlephp.org/en/latest/request-options.html#headers)) - -## Resource Owner -With version 1.1.0 and onward, the Resource Owner information is parsed from the JWT passed in `access_token` by Azure Active Directory. It exposes few attributes and one function. - -**Example:** -```php -$resourceOwner = $provider->getResourceOwner($token); -echo 'Hello, '.$resourceOwner->getFirstName().'!'; -``` -The exposed attributes and function are: -- `getId()` - Gets user's object id - unique for each user -- `getFirstName()` - Gets user's first name -- `getLastName()` - Gets user's family name/surname -- `getTenantId()` - Gets id of tenant which the user is member of -- `getUpn()` - Gets user's User Principal Name, which can be also used as user's e-mail address -- `claim($name)` - Gets any other claim (specified as `$name`) from the JWT, full list can be found [here](https://azure.microsoft.com/en-us/documentation/articles/active-directory-token-and-claims/) - -## Microsoft Graph -Calling [Microsoft Graph](http://graph.microsoft.io/) is very simple with this library. After provider initialization simply change the API URL followingly (replace `v1.0` with your desired version): -```php -// Mention Microsoft Graph scope when initializing the provider -$baseGraphUri = $provider->getRootMicrosoftGraphUri(null); -$provider->scope = 'your scope ' . $baseGraphUri . '/User.Read'; - -// Call a query -$provider->get($provider->getRootMicrosoftGraphUri($token) . '/v1.0/me', $token); -``` -After that, when requesting access token, refresh token or so, provide the `resource` with value `https://graph.microsoft.com/` in order to be able to make calls to the Graph (see more about `resource` [here](#advanced-flow)). - -## Protecting your API - *experimental* -With version 1.2.0 you can now use this library to protect your API with Azure Active Directory authentication very easily. The Provider now also exposes `validateAccessToken(string $token)` which lets you pass an access token inside which you for example received in the `Authorization` header of the request on your API. You can use the function followingly (in vanilla PHP): -```php -// Assuming you have already initialized the $provider - -// Obtain the accessToken - in this case, we are getting it from Authorization header -$headers = getallheaders(); -// Assuming you got the value of Authorization header as "Bearer [the_access_token]" we parse it -$authorization = explode(' ', $headers['Authorization']); -$accessToken = $authorization[1]; - -try { - $claims = $provider->validateAccessToken($accessToken); -} catch (Exception $e) { - // Something happened, handle the error -} - -// The access token is valid, you can now proceed with your code. You can also access the $claims as defined in JWT - for example roles, group memberships etc. -``` - -You may also need to access some other resource from the API like the Microsoft Graph to get some additional information. In order to do that, there is `urn:ietf:params:oauth:grant-type:jwt-bearer` grant available ([RFC](https://tools.ietf.org/html/draft-jones-oauth-jwt-bearer-03)). An example (assuming you have the code above working and you have the required permissions configured correctly in the Azure AD application): -```php -$graphAccessToken = $provider->getAccessToken('jwt_bearer', [ - 'resource' => 'https://graph.microsoft.com/v1.0/', - 'assertion' => $accessToken, - 'requested_token_use' => 'on_behalf_of' -]); - -$me = $provider->get('https://graph.microsoft.com/v1.0/me', $graphAccessToken); -print_r($me); -``` -Just to make it easier so you don't have to remember entire name for `grant_type` (`urn:ietf:params:oauth:grant-type:jwt-bearer`), you just use short `jwt_bearer` instead. - -## Azure Active Directory B2C - *experimental* -You can also now very simply make use of [Azure Active Directory B2C](https://azure.microsoft.com/en-us/documentation/articles/active-directory-b2c-reference-oauth-code/). Before authentication, change the endpoints using `pathAuthorize`, `pathToken` and `scope` and additionally specify your [login policy](https://azure.microsoft.com/en-gb/documentation/articles/active-directory-b2c-reference-policies/). **Please note that the B2C support is still experimental and wasn't fully tested.** -```php -$provider->pathAuthorize = "/oauth2/v2.0/authorize"; -$provider->pathToken = "/oauth2/v2.0/token"; -$provider->scope = ["idtoken"]; - -// Specify custom policy in our authorization URL -$authUrl = $provider->getAuthorizationUrl([ - 'p' => 'b2c_1_siup' -]); -``` - -## Multipurpose refresh tokens - *experimental* -In cause that you need to access multiple resources (like your API and Microsoft Graph), you can use multipurpose [refresh tokens](https://msdn.microsoft.com/en-us/library/azure/dn645538.aspx). Once obtaining a token for first resource, you can simply request another token for different resource like so: -```php -$accessToken2 = $provider->getAccessToken('refresh_token', [ - 'refresh_token' => $accessToken1->getRefreshToken(), - 'resource' => 'http://urlOfYourSecondResource' -]); -``` -At the moment, there is one issue: When you make a call to your API and the token has expired, it will have the value of `$provider->urlAPI` which is obviously wrong for `$accessToken2`. The solution is very simple - set the `$provider->urlAPI` to the resource which you want to call. This issue will be addressed in future release. **Please note that this is experimental and wasn't fully tested.** - -## Known users -If you are using this library and would like to be listed here, please let us know! -- [TheNetworg/DreamSpark-SSO](https://github.com/thenetworg/dreamspark-sso) - -## Contributing -We accept contributions via [Pull Requests on Github](https://github.com/thenetworg/oauth2-azure). - -## Credits -- [Jan Hajek](https://github.com/hajekj) ([TheNetw.org](https://thenetw.org)) -- [Vittorio Bertocci](https://github.com/vibronet) (Microsoft) - - Thanks for the splendid support while implementing #16 -- [Martin Cetkovský](https://github.com/mcetkovsky) ([cetkovsky.eu](https://www.cetkovsky.eu)] -- [All Contributors](https://github.com/thenetworg/oauth2-azure/contributors) - -## Support -If you find a bug or encounter any issue or have a problem/question with this library please create a [new issue](https://github.com/TheNetworg/oauth2-azure/issues). - -## License -The MIT License (MIT). Please see [License File](https://github.com/thenetworg/oauth2-azure/blob/master/LICENSE) for more information. diff --git a/lib/thenetworg/oauth2-azure/composer.json b/lib/thenetworg/oauth2-azure/composer.json deleted file mode 100644 index 4fb348463..000000000 --- a/lib/thenetworg/oauth2-azure/composer.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "thenetworg/oauth2-azure", - "description": "Azure Active Directory OAuth 2.0 Client Provider for The PHP League OAuth2-Client", - "license": "MIT", - "authors": [ - { - "name": "Jan Hajek", - "email": "jan.hajek@thenetw.org", - "homepage": "https://thenetw.org" - } - ], - "keywords": [ - "oauth", - "oauth2", - "client", - "authorization", - "microsoft", - "windows azure", - "azure", - "azure active directory", - "aad", - "sso" - ], - "require": { - "ext-json": "*", - "ext-openssl": "*", - "php": "^7.1|^8.0", - "league/oauth2-client": "~2.0", - "firebase/php-jwt": "~3.0||~4.0||~5.0||~6.0" - }, - "autoload": { - "psr-4": { - "TheNetworg\\OAuth2\\Client\\": "src/" - } - } -} diff --git a/lib/thenetworg/oauth2-azure/src/Grant/JwtBearer.php b/lib/thenetworg/oauth2-azure/src/Grant/JwtBearer.php deleted file mode 100644 index c23772855..000000000 --- a/lib/thenetworg/oauth2-azure/src/Grant/JwtBearer.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -namespace TheNetworg\OAuth2\Client\Grant; - -class JwtBearer extends \League\OAuth2\Client\Grant\AbstractGrant -{ - protected function getName() - { - return 'urn:ietf:params:oauth:grant-type:jwt-bearer'; - } - - protected function getRequiredRequestParameters() - { - return [ - 'requested_token_use', - 'assertion', - ]; - } -} diff --git a/lib/thenetworg/oauth2-azure/src/Provider/Azure.php b/lib/thenetworg/oauth2-azure/src/Provider/Azure.php deleted file mode 100644 index 50aec8235..000000000 --- a/lib/thenetworg/oauth2-azure/src/Provider/Azure.php +++ /dev/null @@ -1,492 +0,0 @@ -<?php - -namespace TheNetworg\OAuth2\Client\Provider; - -use Firebase\JWT\JWT; -use Firebase\JWT\JWK; -use Firebase\JWT\Key; -use League\OAuth2\Client\Grant\AbstractGrant; -use League\OAuth2\Client\Provider\AbstractProvider; -use League\OAuth2\Client\Provider\Exception\IdentityProviderException; -use League\OAuth2\Client\Provider\ResourceOwnerInterface; -use League\OAuth2\Client\Token\AccessTokenInterface; -use League\OAuth2\Client\Tool\BearerAuthorizationTrait; -use Psr\Http\Message\ResponseInterface; -use TheNetworg\OAuth2\Client\Grant\JwtBearer; -use TheNetworg\OAuth2\Client\Token\AccessToken; - -class Azure extends AbstractProvider -{ - const ENDPOINT_VERSION_1_0 = '1.0'; - const ENDPOINT_VERSION_2_0 = '2.0'; - const ENDPOINT_VERSIONS = [self::ENDPOINT_VERSION_1_0, self::ENDPOINT_VERSION_2_0]; - - use BearerAuthorizationTrait; - - public $urlLogin = 'https://login.microsoftonline.com/'; - - /** @var array|null */ - protected $openIdConfiguration; - - public $scope = []; - - public $scopeSeparator = ' '; - - public $tenant = 'common'; - - public $defaultEndPointVersion = self::ENDPOINT_VERSION_1_0; - - public $urlAPI = 'https://graph.windows.net/'; - - public $resource = ''; - - public $API_VERSION = '1.6'; - - public $authWithResource = true; - - public function __construct(array $options = [], array $collaborators = []) - { - parent::__construct($options, $collaborators); - if (isset($options['scopes'])) { - $this->scope = array_merge($options['scopes'], $this->scope); - } - if (isset($options['defaultEndPointVersion']) && - in_array($options['defaultEndPointVersion'], self::ENDPOINT_VERSIONS, true)) { - $this->defaultEndPointVersion = $options['defaultEndPointVersion']; - } - $this->grantFactory->setGrant('jwt_bearer', new JwtBearer()); - } - - /** - * @param string $tenant - * @param string $version - */ - protected function getOpenIdConfiguration($tenant, $version) { - if (!is_array($this->openIdConfiguration)) { - $this->openIdConfiguration = []; - } - if (!array_key_exists($tenant, $this->openIdConfiguration)) { - $this->openIdConfiguration[$tenant] = []; - } - if (!array_key_exists($version, $this->openIdConfiguration[$tenant])) { - $versionInfix = $this->getVersionUriInfix($version); - $openIdConfigurationUri = $this->urlLogin . $tenant . $versionInfix . '/.well-known/openid-configuration?appid=' . $this->clientId; - - $factory = $this->getRequestFactory(); - $request = $factory->getRequestWithOptions( - 'get', - $openIdConfigurationUri, - [] - ); - $response = $this->getParsedResponse($request); - $this->openIdConfiguration[$tenant][$version] = $response; - } - - return $this->openIdConfiguration[$tenant][$version]; - } - - /** - * @inheritdoc - */ - public function getBaseAuthorizationUrl(): string - { - $openIdConfiguration = $this->getOpenIdConfiguration($this->tenant, $this->defaultEndPointVersion); - return $openIdConfiguration['authorization_endpoint']; - } - - /** - * @inheritdoc - */ - public function getBaseAccessTokenUrl(array $params): string - { - $openIdConfiguration = $this->getOpenIdConfiguration($this->tenant, $this->defaultEndPointVersion); - return $openIdConfiguration['token_endpoint']; - } - - /** - * @inheritdoc - */ - public function getAccessToken($grant, array $options = []): AccessTokenInterface - { - if ($this->defaultEndPointVersion != self::ENDPOINT_VERSION_2_0) { - // Version 2.0 does not support the resources parameter - // https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow - // while version 1.0 does recommend it - // https://docs.microsoft.com/en-us/azure/active-directory/develop/v1-protocols-oauth-code - if ($this->authWithResource) { - $options['resource'] = $this->resource ? $this->resource : $this->urlAPI; - } - } - return parent::getAccessToken($grant, $options); - } - - /** - * @inheritdoc - */ - public function getResourceOwner(\League\OAuth2\Client\Token\AccessToken $token): ResourceOwnerInterface - { - $data = $token->getIdTokenClaims(); - return $this->createResourceOwner($data, $token); - } - - /** - * @inheritdoc - */ - public function getResourceOwnerDetailsUrl(\League\OAuth2\Client\Token\AccessToken $token): string - { - return ''; // shouldn't that return such a URL? - } - - public function getObjects($tenant, $ref, &$accessToken, $headers = []) - { - $objects = []; - - $response = null; - do { - if (false === filter_var($ref, FILTER_VALIDATE_URL)) { - $ref = $tenant . '/' . $ref; - } - - $response = $this->request('get', $ref, $accessToken, ['headers' => $headers]); - $values = $response; - if (isset($response['value'])) { - $values = $response['value']; - } - foreach ($values as $value) { - $objects[] = $value; - } - if (isset($response['odata.nextLink'])) { - $ref = $response['odata.nextLink']; - } elseif (isset($response['@odata.nextLink'])) { - $ref = $response['@odata.nextLink']; - } else { - $ref = null; - } - } while (null != $ref); - - return $objects; - } - - /** - * @param $accessToken AccessToken|null - * @return string - */ - public function getRootMicrosoftGraphUri($accessToken) - { - if (is_null($accessToken)) { - $tenant = $this->tenant; - $version = $this->defaultEndPointVersion; - } else { - $idTokenClaims = $accessToken->getIdTokenClaims(); - $tenant = array_key_exists('tid', $idTokenClaims) ? $idTokenClaims['tid'] : $this->tenant; - $version = array_key_exists('ver', $idTokenClaims) ? $idTokenClaims['ver'] : $this->defaultEndPointVersion; - } - $openIdConfiguration = $this->getOpenIdConfiguration($tenant, $version); - return 'https://' . $openIdConfiguration['msgraph_host']; - } - - public function get($ref, &$accessToken, $headers = [], $doNotWrap = false) - { - $response = $this->request('get', $ref, $accessToken, ['headers' => $headers]); - - return $doNotWrap ? $response : $this->wrapResponse($response); - } - - public function post($ref, $body, &$accessToken, $headers = []) - { - $response = $this->request('post', $ref, $accessToken, ['body' => $body, 'headers' => $headers]); - - return $this->wrapResponse($response); - } - - public function put($ref, $body, &$accessToken, $headers = []) - { - $response = $this->request('put', $ref, $accessToken, ['body' => $body, 'headers' => $headers]); - - return $this->wrapResponse($response); - } - - public function delete($ref, &$accessToken, $headers = []) - { - $response = $this->request('delete', $ref, $accessToken, ['headers' => $headers]); - - return $this->wrapResponse($response); - } - - public function patch($ref, $body, &$accessToken, $headers = []) - { - $response = $this->request('patch', $ref, $accessToken, ['body' => $body, 'headers' => $headers]); - - return $this->wrapResponse($response); - } - - public function request($method, $ref, &$accessToken, $options = []) - { - if ($accessToken->hasExpired()) { - $accessToken = $this->getAccessToken('refresh_token', [ - 'refresh_token' => $accessToken->getRefreshToken(), - ]); - } - - $url = null; - if (false !== filter_var($ref, FILTER_VALIDATE_URL)) { - $url = $ref; - } else { - if (false !== strpos($this->urlAPI, 'graph.windows.net')) { - $tenant = 'common'; - if (property_exists($this, 'tenant')) { - $tenant = $this->tenant; - } - $ref = "$tenant/$ref"; - - $url = $this->urlAPI . $ref; - - $url .= (false === strrpos($url, '?')) ? '?' : '&'; - $url .= 'api-version=' . $this->API_VERSION; - } else { - $url = $this->urlAPI . $ref; - } - } - - if (isset($options['body']) && ('array' == gettype($options['body']) || 'object' == gettype($options['body']))) { - $options['body'] = json_encode($options['body']); - } - if (!isset($options['headers']['Content-Type']) && isset($options['body'])) { - $options['headers']['Content-Type'] = 'application/json'; - } - - $request = $this->getAuthenticatedRequest($method, $url, $accessToken, $options); - $response = $this->getParsedResponse($request); - - return $response; - } - - public function getClientId() - { - return $this->clientId; - } - - /** - * Obtain URL for logging out the user. - * - * @param $post_logout_redirect_uri string The URL which the user should be redirected to after logout - * - * @return string - */ - public function getLogoutUrl($post_logout_redirect_uri = "") - { - $openIdConfiguration = $this->getOpenIdConfiguration($this->tenant, $this->defaultEndPointVersion); - $logoutUri = $openIdConfiguration['end_session_endpoint']; - - if (!empty($post_logout_redirect_uri)) { - $logoutUri .= '?post_logout_redirect_uri=' . rawurlencode($post_logout_redirect_uri); - } - - return $logoutUri; - } - - /** - * Validate the access token you received in your application. - * - * @param $accessToken string The access token you received in the authorization header. - * - * @return array - */ - public function validateAccessToken($accessToken) - { - $keys = $this->getJwtVerificationKeys(); - $tokenClaims = (array)JWT::decode($accessToken, $keys, ['RS256']); - - $this->validateTokenClaims($tokenClaims); - - return $tokenClaims; - } - - /** - * Validate the access token claims from an access token you received in your application. - * - * @param $tokenClaims array The token claims from an access token you received in the authorization header. - * - * @return void - */ - public function validateTokenClaims($tokenClaims) { - if ($this->getClientId() != $tokenClaims['aud']) { - throw new \RuntimeException('The client_id / audience is invalid!'); - } - if ($tokenClaims['nbf'] > time() || $tokenClaims['exp'] < time()) { - // Additional validation is being performed in firebase/JWT itself - throw new \RuntimeException('The id_token is invalid!'); - } - - if ('common' == $this->tenant) { - $this->tenant = $tokenClaims['tid']; - } - - $version = array_key_exists('ver', $tokenClaims) ? $tokenClaims['ver'] : $this->defaultEndPointVersion; - $tenant = $this->getTenantDetails($this->tenant, $version); - if ($tokenClaims['iss'] != $tenant['issuer']) { - throw new \RuntimeException('Invalid token issuer (tokenClaims[iss]' . $tokenClaims['iss'] . ', tenant[issuer] ' . $tenant['issuer'] . ')!'); - } - } - - /** - * Get JWT verification keys from Azure Active Directory. - * - * @return array - */ - public function getJwtVerificationKeys() - { - $openIdConfiguration = $this->getOpenIdConfiguration($this->tenant, $this->defaultEndPointVersion); - $keysUri = $openIdConfiguration['jwks_uri']; - - $factory = $this->getRequestFactory(); - $request = $factory->getRequestWithOptions('get', $keysUri, []); - - $response = $this->getParsedResponse($request); - - $keys = []; - foreach ($response['keys'] as $i => $keyinfo) { - if (isset($keyinfo['x5c']) && is_array($keyinfo['x5c'])) { - foreach ($keyinfo['x5c'] as $encodedkey) { - $cert = - '-----BEGIN CERTIFICATE-----' . PHP_EOL - . chunk_split($encodedkey, 64, PHP_EOL) - . '-----END CERTIFICATE-----' . PHP_EOL; - - $cert_object = openssl_x509_read($cert); - - if ($cert_object === false) { - throw new \RuntimeException('An attempt to read ' . $encodedkey . ' as a certificate failed.'); - } - - $pkey_object = openssl_pkey_get_public($cert_object); - - if ($pkey_object === false) { - throw new \RuntimeException('An attempt to read a public key from a ' . $encodedkey . ' certificate failed.'); - } - - $pkey_array = openssl_pkey_get_details($pkey_object); - - if ($pkey_array === false) { - throw new \RuntimeException('An attempt to get a public key as an array from a ' . $encodedkey . ' certificate failed.'); - } - - $publicKey = $pkey_array ['key']; - - $keys[$keyinfo['kid']] = new Key($publicKey, 'RS256'); - } - } else if (isset($keyinfo['n']) && isset($keyinfo['e'])) { - $pkey_object = JWK::parseKey($keyinfo); - - if ($pkey_object === false) { - throw new \RuntimeException('An attempt to read a public key from a ' . $keyinfo['n'] . ' certificate failed.'); - } - - $pkey_array = openssl_pkey_get_details($pkey_object); - - if ($pkey_array === false) { - throw new \RuntimeException('An attempt to get a public key as an array from a ' . $keyinfo['n'] . ' certificate failed.'); - } - - $publicKey = $pkey_array ['key']; - - $keys[$keyinfo['kid']] = new Key($publicKey, 'RS256');; - } - } - - return $keys; - } - - protected function getVersionUriInfix($version) - { - return - ($version == self::ENDPOINT_VERSION_2_0) - ? '/v' . self::ENDPOINT_VERSION_2_0 - : ''; - } - - /** - * Get the specified tenant's details. - * - * @param string $tenant - * @param string|null $version - * - * @return array - * @throws IdentityProviderException - */ - public function getTenantDetails($tenant, $version) - { - return $this->getOpenIdConfiguration($this->tenant, $this->defaultEndPointVersion); - } - - /** - * @inheritdoc - */ - protected function checkResponse(ResponseInterface $response, $data): void - { - if (isset($data['odata.error']) || isset($data['error'])) { - if (isset($data['odata.error']['message']['value'])) { - $message = $data['odata.error']['message']['value']; - } elseif (isset($data['error']['message'])) { - $message = $data['error']['message']; - } elseif (isset($data['error']) && !is_array($data['error'])) { - $message = $data['error']; - } else { - $message = $response->getReasonPhrase(); - } - - if (isset($data['error_description']) && !is_array($data['error_description'])) { - $message .= PHP_EOL . $data['error_description']; - } - - throw new IdentityProviderException( - $message, - $response->getStatusCode(), - $response->getBody() - ); - } - } - - /** - * @inheritdoc - */ - protected function getDefaultScopes(): array - { - return $this->scope; - } - - /** - * @inheritdoc - */ - protected function getScopeSeparator(): string - { - return $this->scopeSeparator; - } - - /** - * @inheritdoc - */ - protected function createAccessToken(array $response, AbstractGrant $grant): AccessToken - { - return new AccessToken($response, $this); - } - - /** - * @inheritdoc - */ - protected function createResourceOwner(array $response, \League\OAuth2\Client\Token\AccessToken $token): AzureResourceOwner - { - return new AzureResourceOwner($response); - } - - private function wrapResponse($response) - { - if (empty($response)) { - return; - } elseif (isset($response['value'])) { - return $response['value']; - } - - return $response; - } -} diff --git a/lib/thenetworg/oauth2-azure/src/Provider/AzureResourceOwner.php b/lib/thenetworg/oauth2-azure/src/Provider/AzureResourceOwner.php deleted file mode 100644 index 337ae5125..000000000 --- a/lib/thenetworg/oauth2-azure/src/Provider/AzureResourceOwner.php +++ /dev/null @@ -1,97 +0,0 @@ -<?php - -namespace TheNetworg\OAuth2\Client\Provider; - -use League\OAuth2\Client\Provider\ResourceOwnerInterface; - -class AzureResourceOwner implements ResourceOwnerInterface -{ - /** - * Response payload - * - * @var array - */ - protected $data; - - /** - * Creates new azure resource owner. - * - * @param array $data - */ - public function __construct($data = []) - { - $this->data = $data; - } - - /** - * Retrieves id of resource owner. - * - * @return string|null - */ - public function getId() - { - return $this->claim('oid'); - } - - /** - * Retrieves first name of resource owner. - * - * @return string|null - */ - public function getFirstName() - { - return $this->claim('given_name'); - } - - /** - * Retrieves last name of resource owner. - * - * @return string|null - */ - public function getLastName() - { - return $this->claim('family_name'); - } - - /** - * Retrieves user principal name of resource owner. - * - * @return string|null - */ - public function getUpn() - { - return $this->claim('upn'); - } - - /** - * Retrieves tenant id of resource owner. - * - * @return string|null - */ - public function getTenantId() - { - return $this->claim('tid'); - } - - /** - * Returns a field from the parsed JWT data. - * - * @param string $name - * - * @return mixed|null - */ - public function claim($name) - { - return isset($this->data[$name]) ? $this->data[$name] : null; - } - - /** - * Returns all the data obtained about the user. - * - * @return array - */ - public function toArray() - { - return $this->data; - } -} diff --git a/lib/thenetworg/oauth2-azure/src/Token/AccessToken.php b/lib/thenetworg/oauth2-azure/src/Token/AccessToken.php deleted file mode 100644 index 7de80f9e5..000000000 --- a/lib/thenetworg/oauth2-azure/src/Token/AccessToken.php +++ /dev/null @@ -1,73 +0,0 @@ -<?php - -namespace TheNetworg\OAuth2\Client\Token; - -use Firebase\JWT\JWT; -use InvalidArgumentException; -use League\OAuth2\Client\Tool\RequestFactory; -use RuntimeException; - -class AccessToken extends \League\OAuth2\Client\Token\AccessToken -{ - protected $idToken; - - protected $idTokenClaims; - - public function __construct(array $options, $provider) - { - parent::__construct($options); - if (!empty($options['id_token'])) { - $this->idToken = $options['id_token']; - - unset($this->values['id_token']); - - $keys = $provider->getJwtVerificationKeys(); - $idTokenClaims = null; - try { - $tks = explode('.', $this->idToken); - // Check if the id_token contains signature - if (3 == count($tks) && !empty($tks[2])) { - $idTokenClaims = (array)JWT::decode($this->idToken, $keys, ['RS256']); - } else { - // The id_token is unsigned (coming from v1.0 endpoint) - https://msdn.microsoft.com/en-us/library/azure/dn645542.aspx - - // Since idToken is not signed, we just do OAuth2 flow without validating the id_token - // // Validate the access_token signature first by parsing it as JWT into claims - // $accessTokenClaims = (array)JWT::decode($options['access_token'], $keys, ['RS256']); - // Then parse the idToken claims only without validating the signature - $idTokenClaims = (array)JWT::jsonDecode(JWT::urlsafeB64Decode($tks[1])); - } - } catch (JWT_Exception $e) { - throw new RuntimeException('Unable to parse the id_token!'); - } - - $provider->validateTokenClaims($idTokenClaims); - - $this->idTokenClaims = $idTokenClaims; - } - } - - public function getIdToken() - { - return $this->idToken; - } - - public function getIdTokenClaims() - { - return $this->idTokenClaims; - } - - /** - * @inheritdoc - */ - public function jsonSerialize() - { - $parameters = parent::jsonSerialize(); - - if ($this->idToken) { - $parameters['id_token'] = $this->idToken; - } - - return $parameters; - } -} diff --git a/lib/twig/twig/.editorconfig b/lib/twig/twig/.editorconfig deleted file mode 100644 index 270f1d1b7..000000000 --- a/lib/twig/twig/.editorconfig +++ /dev/null @@ -1,18 +0,0 @@ -; top-most EditorConfig file -root = true - -; Unix-style newlines -[*] -end_of_line = LF - -[*.php] -indent_style = space -indent_size = 4 - -[*.test] -indent_style = space -indent_size = 4 - -[*.rst] -indent_style = space -indent_size = 4 diff --git a/lib/twig/twig/.gitattributes b/lib/twig/twig/.gitattributes deleted file mode 100644 index 06bc36713..000000000 --- a/lib/twig/twig/.gitattributes +++ /dev/null @@ -1,4 +0,0 @@ -/doc/ export-ignore -/extra/ export-ignore -/tests/ export-ignore -/phpunit.xml.dist export-ignore diff --git a/lib/twig/twig/.github/workflows/ci.yml b/lib/twig/twig/.github/workflows/ci.yml deleted file mode 100644 index 50f23f9a4..000000000 --- a/lib/twig/twig/.github/workflows/ci.yml +++ /dev/null @@ -1,149 +0,0 @@ -name: "CI" - -on: - pull_request: - push: - branches: - - '3.x' - -env: - SYMFONY_PHPUNIT_DISABLE_RESULT_CACHE: 1 - -permissions: - contents: read - -jobs: - tests: - name: "PHP ${{ matrix.php-version }}" - - runs-on: 'ubuntu-latest' - - continue-on-error: ${{ matrix.experimental }} - - strategy: - matrix: - php-version: - - '7.2.5' - - '7.3' - - '7.4' - - '8.0' - - '8.1' - experimental: [false] - - steps: - - name: "Checkout code" - uses: actions/checkout@v2 - - - name: "Install PHP with extensions" - uses: shivammathur/setup-php@v2 - with: - coverage: "none" - php-version: ${{ matrix.php-version }} - ini-values: memory_limit=-1 - - - name: "Add PHPUnit matcher" - run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - - - run: composer install - - - name: "Install PHPUnit" - run: vendor/bin/simple-phpunit install - - - name: "PHPUnit version" - run: vendor/bin/simple-phpunit --version - - - name: "Run tests" - run: vendor/bin/simple-phpunit - - extension-tests: - needs: - - 'tests' - - name: "${{ matrix.extension }} with PHP ${{ matrix.php-version }}" - - runs-on: 'ubuntu-latest' - - continue-on-error: true - - strategy: - matrix: - php-version: - - '7.2.5' - - '7.3' - - '7.4' - - '8.0' - - '8.1' - extension: - - 'extra/cache-extra' - - 'extra/cssinliner-extra' - - 'extra/html-extra' - - 'extra/inky-extra' - - 'extra/intl-extra' - - 'extra/markdown-extra' - - 'extra/string-extra' - - 'extra/twig-extra-bundle' - experimental: [false] - - steps: - - name: "Checkout code" - uses: actions/checkout@v2 - - - name: "Install PHP with extensions" - uses: shivammathur/setup-php@v2 - with: - coverage: "none" - php-version: ${{ matrix.php-version }} - ini-values: memory_limit=-1 - - - name: "Add PHPUnit matcher" - run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - - - run: composer install - - - name: "Install PHPUnit" - run: vendor/bin/simple-phpunit install - - - name: "PHPUnit version" - run: vendor/bin/simple-phpunit --version - - - name: "Composer install" - working-directory: ${{ matrix.extension}} - run: composer install - - - name: "Run tests" - working-directory: ${{ matrix.extension}} - run: ../../vendor/bin/simple-phpunit - -# -# Drupal does not support Twig 3 now! -# -# integration-tests: -# needs: -# - 'tests' -# -# name: "Integration tests with PHP ${{ matrix.php-version }}" -# -# runs-on: 'ubuntu-20.04' -# -# continue-on-error: true -# -# strategy: -# matrix: -# php-version: -# - '7.3' -# -# steps: -# - name: "Checkout code" -# uses: actions/checkout@v2 -# -# - name: "Install PHP with extensions" -# uses: shivammathur/setup-php@2 -# with: -# coverage: "none" -# extensions: "gd, pdo_sqlite" -# php-version: ${{ matrix.php-version }} -# ini-values: memory_limit=-1 -# tools: composer:v2 -# -# - run: bash ./tests/drupal_test.sh -# shell: "bash" diff --git a/lib/twig/twig/.github/workflows/documentation.yml b/lib/twig/twig/.github/workflows/documentation.yml deleted file mode 100644 index ee83b5887..000000000 --- a/lib/twig/twig/.github/workflows/documentation.yml +++ /dev/null @@ -1,64 +0,0 @@ -name: "Documentation" - -on: - pull_request: - push: - branches: - - '2.x' - - '3.x' - -permissions: - contents: read - -jobs: - build: - name: "Build" - - runs-on: ubuntu-latest - - steps: - - name: "Checkout code" - uses: actions/checkout@v2 - - - name: "Set-up PHP" - uses: shivammathur/setup-php@v2 - with: - php-version: 8.1 - coverage: none - tools: "composer:v2" - - - name: Get composer cache directory - id: composercache - working-directory: doc/_build - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - - name: Cache dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.composercache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer- - - - name: "Install dependencies" - working-directory: doc/_build - run: composer install --prefer-dist --no-progress - - - name: "Build the docs" - working-directory: doc/_build - run: php build.php --disable-cache - - doctor-rst: - name: "DOCtor-RST" - - runs-on: ubuntu-latest - - steps: - - name: "Checkout code" - uses: actions/checkout@v2 - - - name: "Run DOCtor-RST" - uses: docker://oskarstark/doctor-rst - with: - args: --short - env: - DOCS_DIR: 'doc/' diff --git a/lib/twig/twig/.gitignore b/lib/twig/twig/.gitignore deleted file mode 100644 index b197246ba..000000000 --- a/lib/twig/twig/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -/doc/_build/vendor -/doc/_build/output -/composer.lock -/phpunit.xml -/vendor -.phpunit.result.cache diff --git a/lib/twig/twig/.php-cs-fixer.dist.php b/lib/twig/twig/.php-cs-fixer.dist.php deleted file mode 100644 index b07ac7fca..000000000 --- a/lib/twig/twig/.php-cs-fixer.dist.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php - -return (new PhpCsFixer\Config()) - ->setRules([ - '@Symfony' => true, - '@Symfony:risky' => true, - '@PHPUnit75Migration:risky' => true, - 'php_unit_dedicate_assert' => ['target' => '5.6'], - 'array_syntax' => ['syntax' => 'short'], - 'php_unit_fqcn_annotation' => true, - 'no_unreachable_default_argument_value' => false, - 'braces' => ['allow_single_line_closure' => true], - 'heredoc_to_nowdoc' => false, - 'ordered_imports' => true, - 'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'], - 'native_function_invocation' => ['include' => ['@compiler_optimized'], 'scope' => 'all'], - ]) - ->setRiskyAllowed(true) - ->setFinder((new PhpCsFixer\Finder())->in(__DIR__)) -; diff --git a/lib/twig/twig/CHANGELOG b/lib/twig/twig/CHANGELOG deleted file mode 100644 index 379387644..000000000 --- a/lib/twig/twig/CHANGELOG +++ /dev/null @@ -1,150 +0,0 @@ -# 3.4.3 (2022-09-28) - - * Fix a security issue on filesystem loader (possibility to load a template outside a configured directory) - -# 3.4.2 (2022-08-12) - - * Allow inherited magic method to still run with calling class - * Fix CallExpression::reflectCallable() throwing TypeError - * Fix typo in naming (currency_code) - -# 3.4.1 (2022-05-17) - -* Fix optimizing non-public named closures - -# 3.4.0 (2022-05-22) - - * Add support for named closures - -# 3.3.10 (2022-04-06) - - * Enable bytecode invalidation when auto_reload is enabled - -# 3.3.9 (2022-03-25) - - * Fix custom escapers when using multiple Twig environments - * Add support for "constant('class', object)" - * Do not reuse internally generated variable names during parsing - -# 3.3.8 (2022-02-04) - - * Fix a security issue when in a sandbox: the `sort` filter must require a Closure for the `arrow` parameter - * Fix deprecation notice on `round` - * Fix call to deprecated `convertToHtml` method - -# 3.3.7 (2022-01-03) - -* Allow more null support when Twig expects a string (for better 8.1 support) -* Only use Commonmark extensions if markdown enabled - -# 3.3.6 (2022-01-03) - -* Only use Commonmark extensions if markdown enabled - -# 3.3.5 (2022-01-03) - -* Allow CommonMark extensions to easily be added -* Allow null when Twig expects a string (for better 8.1 support) -* Make some performance optimizations -* Allow Symfony translation contract v3+ - -# 3.3.4 (2021-11-25) - - * Bump minimum supported Symfony component versions - * Fix a deprecated message - -# 3.3.3 (2021-09-17) - - * Allow Symfony 6 - * Improve compatibility with PHP 8.1 - * Explicitly specify the encoding for mb_ord in JS escaper - -# 3.3.2 (2021-05-16) - - * Revert "Throw a proper exception when a template name is an absolute path (as it has never been supported)" - -# 3.3.1 (2021-05-12) - - * Fix PHP 8.1 compatibility - * Throw a proper exception when a template name is an absolute path (as it has never been supported) - -# 3.3.0 (2021-02-08) - - * Fix macro calls in a "cache" tag - * Add the slug filter - * Allow extra bundle to be compatible with Twig 2 - -# 3.2.1 (2021-01-05) - - * Fix extra bundle compat with older versions of Symfony - -# 3.2.0 (2021-01-05) - - * Add the Cache extension in the "extra" repositories: "cache" tag - * Add "registerUndefinedTokenParserCallback" - * Mark built-in node visitors as @internal - * Fix "odd" not working for negative numbers - -# 3.1.1 (2020-10-27) - - * Fix "include(template_from_string())" - -# 3.1.0 (2020-10-21) - - * Fix sandbox support when using "include(template_from_string())" - * Make round brackets optional for one argument tests like "same as" or "divisible by" - * Add support for ES2015 style object initialisation shortcut { a } is the same as { 'a': a } - -# 3.0.5 (2020-08-05) - - * Fix twig_compare w.r.t. whitespace trimming - * Fix sandbox not disabled if syntax error occurs within {% sandbox %} tag - * Fix a regression when not using a space before an operator - * Restrict callables to closures in filters - * Allow trailing commas in argument lists (in calls as well as definitions) - -# 3.0.4 (2020-07-05) - - * Fix comparison operators - * Fix options not taken into account when using "Michelf\MarkdownExtra" - * Fix "Twig\Extra\Intl\IntlExtension::getCountryName()" to accept "null" as a first argument - * Throw exception in case non-Traversable data is passed to "filter" - * Fix context optimization on PHP 7.4 - * Fix PHP 8 compatibility - * Fix ambiguous syntax parsing - -# 3.0.3 (2020-02-11) - - * Add a check to ensure that iconv() is defined - -# 3.0.2 (2020-02-11) - - * Avoid exceptions when an intl resource is not found - * Fix implementation of case-insensitivity for method names - -# 3.0.1 (2019-12-28) - - * fixed Symfony 5.0 support for the HTML extra extension - -# 3.0.0 (2019-11-15) - - * fixed number formatter in Intl extra extension when using a formatter prototype - -# 3.0.0-BETA1 (2019-11-11) - - * removed the "if" condition support on the "for" tag - * made the in, <, >, <=, >=, ==, and != operators more strict when comparing strings and integers/floats - * removed the "filter" tag - * added type hints everywhere - * changed Environment::resolveTemplate() to always return a TemplateWrapper instance - * removed Template::__toString() - * removed Parser::isReservedMacroName() - * removed SanboxedPrintNode - * removed Node::setTemplateName() - * made classes maked as "@final" final - * removed InitRuntimeInterface, ExistsLoaderInterface, and SourceContextLoaderInterface - * removed the "spaceless" tag - * removed Twig\Environment::getBaseTemplateClass() and Twig\Environment::setBaseTemplateClass() - * removed the "base_template_class" option on Twig\Environment - * bumped minimum PHP version to 7.2 - * removed PSR-0 classes diff --git a/lib/twig/twig/LICENSE b/lib/twig/twig/LICENSE deleted file mode 100644 index 8711927f6..000000000 --- a/lib/twig/twig/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2009-2022 by the Twig Team. - -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of Twig nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/lib/twig/twig/README.rst b/lib/twig/twig/README.rst deleted file mode 100644 index fbe7e9a9f..000000000 --- a/lib/twig/twig/README.rst +++ /dev/null @@ -1,23 +0,0 @@ -Twig, the flexible, fast, and secure template language for PHP -============================================================== - -Twig is a template language for PHP. - -Twig uses a syntax similar to the Django and Jinja template languages which -inspired the Twig runtime environment. - -Sponsors --------- - -.. raw:: html - - <a href="https://blackfire.io/docs/introduction?utm_source=twig&utm_medium=github_readme&utm_campaign=logo"> - <img src="https://static.blackfire.io/assets/intemporals/logo/png/blackfire-io_secondary_horizontal_transparent.png?1" width="255px" alt="Blackfire.io"> - </a> - -More Information ----------------- - -Read the `documentation`_ for more information. - -.. _documentation: https://twig.symfony.com/documentation diff --git a/lib/twig/twig/composer.json b/lib/twig/twig/composer.json deleted file mode 100644 index 33e46405c..000000000 --- a/lib/twig/twig/composer.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "name": "twig/twig", - "type": "library", - "description": "Twig, the flexible, fast, and secure template language for PHP", - "keywords": ["templating"], - "homepage": "https://twig.symfony.com", - "license": "BSD-3-Clause", - "minimum-stability": "dev", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, - { - "name": "Twig Team", - "role": "Contributors" - }, - { - "name": "Armin Ronacher", - "email": "armin.ronacher@active-4.com", - "role": "Project Founder" - } - ], - "require": { - "php": ">=7.2.5", - "symfony/polyfill-mbstring": "^1.3", - "symfony/polyfill-ctype": "^1.8" - }, - "require-dev": { - "symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0", - "psr/container": "^1.0" - }, - "autoload": { - "psr-4" : { - "Twig\\" : "src/" - } - }, - "autoload-dev": { - "psr-4" : { - "Twig\\Tests\\" : "tests/" - } - }, - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - } -} diff --git a/lib/twig/twig/src/Cache/CacheInterface.php b/lib/twig/twig/src/Cache/CacheInterface.php deleted file mode 100644 index 6e8c409be..000000000 --- a/lib/twig/twig/src/Cache/CacheInterface.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Cache; - -/** - * Interface implemented by cache classes. - * - * It is highly recommended to always store templates on the filesystem to - * benefit from the PHP opcode cache. This interface is mostly useful if you - * need to implement a custom strategy for storing templates on the filesystem. - * - * @author Andrew Tch <andrew@noop.lv> - */ -interface CacheInterface -{ - /** - * Generates a cache key for the given template class name. - */ - public function generateKey(string $name, string $className): string; - - /** - * Writes the compiled template to cache. - * - * @param string $content The template representation as a PHP class - */ - public function write(string $key, string $content): void; - - /** - * Loads a template from the cache. - */ - public function load(string $key): void; - - /** - * Returns the modification timestamp of a key. - */ - public function getTimestamp(string $key): int; -} diff --git a/lib/twig/twig/src/Cache/FilesystemCache.php b/lib/twig/twig/src/Cache/FilesystemCache.php deleted file mode 100644 index e075563ae..000000000 --- a/lib/twig/twig/src/Cache/FilesystemCache.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Cache; - -/** - * Implements a cache on the filesystem. - * - * @author Andrew Tch <andrew@noop.lv> - */ -class FilesystemCache implements CacheInterface -{ - public const FORCE_BYTECODE_INVALIDATION = 1; - - private $directory; - private $options; - - public function __construct(string $directory, int $options = 0) - { - $this->directory = rtrim($directory, '\/').'/'; - $this->options = $options; - } - - public function generateKey(string $name, string $className): string - { - $hash = hash(\PHP_VERSION_ID < 80100 ? 'sha256' : 'xxh128', $className); - - return $this->directory.$hash[0].$hash[1].'/'.$hash.'.php'; - } - - public function load(string $key): void - { - if (is_file($key)) { - @include_once $key; - } - } - - public function write(string $key, string $content): void - { - $dir = \dirname($key); - if (!is_dir($dir)) { - if (false === @mkdir($dir, 0777, true)) { - clearstatcache(true, $dir); - if (!is_dir($dir)) { - throw new \RuntimeException(sprintf('Unable to create the cache directory (%s).', $dir)); - } - } - } elseif (!is_writable($dir)) { - throw new \RuntimeException(sprintf('Unable to write in the cache directory (%s).', $dir)); - } - - $tmpFile = tempnam($dir, basename($key)); - if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $key)) { - @chmod($key, 0666 & ~umask()); - - if (self::FORCE_BYTECODE_INVALIDATION == ($this->options & self::FORCE_BYTECODE_INVALIDATION)) { - // Compile cached file into bytecode cache - if (\function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN)) { - @opcache_invalidate($key, true); - } elseif (\function_exists('apc_compile_file')) { - apc_compile_file($key); - } - } - - return; - } - - throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $key)); - } - - public function getTimestamp(string $key): int - { - if (!is_file($key)) { - return 0; - } - - return (int) @filemtime($key); - } -} diff --git a/lib/twig/twig/src/Cache/NullCache.php b/lib/twig/twig/src/Cache/NullCache.php deleted file mode 100644 index 8d20d59d8..000000000 --- a/lib/twig/twig/src/Cache/NullCache.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Cache; - -/** - * Implements a no-cache strategy. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class NullCache implements CacheInterface -{ - public function generateKey(string $name, string $className): string - { - return ''; - } - - public function write(string $key, string $content): void - { - } - - public function load(string $key): void - { - } - - public function getTimestamp(string $key): int - { - return 0; - } -} diff --git a/lib/twig/twig/src/Compiler.php b/lib/twig/twig/src/Compiler.php deleted file mode 100644 index 95e1f183b..000000000 --- a/lib/twig/twig/src/Compiler.php +++ /dev/null @@ -1,214 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig; - -use Twig\Node\Node; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -class Compiler -{ - private $lastLine; - private $source; - private $indentation; - private $env; - private $debugInfo = []; - private $sourceOffset; - private $sourceLine; - private $varNameSalt = 0; - - public function __construct(Environment $env) - { - $this->env = $env; - } - - public function getEnvironment(): Environment - { - return $this->env; - } - - public function getSource(): string - { - return $this->source; - } - - /** - * @return $this - */ - public function compile(Node $node, int $indentation = 0) - { - $this->lastLine = null; - $this->source = ''; - $this->debugInfo = []; - $this->sourceOffset = 0; - // source code starts at 1 (as we then increment it when we encounter new lines) - $this->sourceLine = 1; - $this->indentation = $indentation; - $this->varNameSalt = 0; - - $node->compile($this); - - return $this; - } - - /** - * @return $this - */ - public function subcompile(Node $node, bool $raw = true) - { - if (false === $raw) { - $this->source .= str_repeat(' ', $this->indentation * 4); - } - - $node->compile($this); - - return $this; - } - - /** - * Adds a raw string to the compiled code. - * - * @return $this - */ - public function raw(string $string) - { - $this->source .= $string; - - return $this; - } - - /** - * Writes a string to the compiled code by adding indentation. - * - * @return $this - */ - public function write(...$strings) - { - foreach ($strings as $string) { - $this->source .= str_repeat(' ', $this->indentation * 4).$string; - } - - return $this; - } - - /** - * Adds a quoted string to the compiled code. - * - * @return $this - */ - public function string(string $value) - { - $this->source .= sprintf('"%s"', addcslashes($value, "\0\t\"\$\\")); - - return $this; - } - - /** - * Returns a PHP representation of a given value. - * - * @return $this - */ - public function repr($value) - { - if (\is_int($value) || \is_float($value)) { - if (false !== $locale = setlocale(\LC_NUMERIC, '0')) { - setlocale(\LC_NUMERIC, 'C'); - } - - $this->raw(var_export($value, true)); - - if (false !== $locale) { - setlocale(\LC_NUMERIC, $locale); - } - } elseif (null === $value) { - $this->raw('null'); - } elseif (\is_bool($value)) { - $this->raw($value ? 'true' : 'false'); - } elseif (\is_array($value)) { - $this->raw('array('); - $first = true; - foreach ($value as $key => $v) { - if (!$first) { - $this->raw(', '); - } - $first = false; - $this->repr($key); - $this->raw(' => '); - $this->repr($v); - } - $this->raw(')'); - } else { - $this->string($value); - } - - return $this; - } - - /** - * @return $this - */ - public function addDebugInfo(Node $node) - { - if ($node->getTemplateLine() != $this->lastLine) { - $this->write(sprintf("// line %d\n", $node->getTemplateLine())); - - $this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset); - $this->sourceOffset = \strlen($this->source); - $this->debugInfo[$this->sourceLine] = $node->getTemplateLine(); - - $this->lastLine = $node->getTemplateLine(); - } - - return $this; - } - - public function getDebugInfo(): array - { - ksort($this->debugInfo); - - return $this->debugInfo; - } - - /** - * @return $this - */ - public function indent(int $step = 1) - { - $this->indentation += $step; - - return $this; - } - - /** - * @return $this - * - * @throws \LogicException When trying to outdent too much so the indentation would become negative - */ - public function outdent(int $step = 1) - { - // can't outdent by more steps than the current indentation level - if ($this->indentation < $step) { - throw new \LogicException('Unable to call outdent() as the indentation would become negative.'); - } - - $this->indentation -= $step; - - return $this; - } - - public function getVarName(): string - { - return sprintf('__internal_compile_%d', $this->varNameSalt++); - } -} diff --git a/lib/twig/twig/src/Environment.php b/lib/twig/twig/src/Environment.php deleted file mode 100644 index 85aaab916..000000000 --- a/lib/twig/twig/src/Environment.php +++ /dev/null @@ -1,832 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig; - -use Twig\Cache\CacheInterface; -use Twig\Cache\FilesystemCache; -use Twig\Cache\NullCache; -use Twig\Error\Error; -use Twig\Error\LoaderError; -use Twig\Error\RuntimeError; -use Twig\Error\SyntaxError; -use Twig\Extension\CoreExtension; -use Twig\Extension\EscaperExtension; -use Twig\Extension\ExtensionInterface; -use Twig\Extension\OptimizerExtension; -use Twig\Loader\ArrayLoader; -use Twig\Loader\ChainLoader; -use Twig\Loader\LoaderInterface; -use Twig\Node\ModuleNode; -use Twig\Node\Node; -use Twig\NodeVisitor\NodeVisitorInterface; -use Twig\RuntimeLoader\RuntimeLoaderInterface; -use Twig\TokenParser\TokenParserInterface; - -/** - * Stores the Twig configuration and renders templates. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Environment -{ - public const VERSION = '3.4.3'; - public const VERSION_ID = 30403; - public const MAJOR_VERSION = 3; - public const MINOR_VERSION = 4; - public const RELEASE_VERSION = 3; - public const EXTRA_VERSION = ''; - - private $charset; - private $loader; - private $debug; - private $autoReload; - private $cache; - private $lexer; - private $parser; - private $compiler; - private $globals = []; - private $resolvedGlobals; - private $loadedTemplates; - private $strictVariables; - private $templateClassPrefix = '__TwigTemplate_'; - private $originalCache; - private $extensionSet; - private $runtimeLoaders = []; - private $runtimes = []; - private $optionsHash; - - /** - * Constructor. - * - * Available options: - * - * * debug: When set to true, it automatically set "auto_reload" to true as - * well (default to false). - * - * * charset: The charset used by the templates (default to UTF-8). - * - * * cache: An absolute path where to store the compiled templates, - * a \Twig\Cache\CacheInterface implementation, - * or false to disable compilation cache (default). - * - * * auto_reload: Whether to reload the template if the original source changed. - * If you don't provide the auto_reload option, it will be - * determined automatically based on the debug value. - * - * * strict_variables: Whether to ignore invalid variables in templates - * (default to false). - * - * * autoescape: Whether to enable auto-escaping (default to html): - * * false: disable auto-escaping - * * html, js: set the autoescaping to one of the supported strategies - * * name: set the autoescaping strategy based on the template name extension - * * PHP callback: a PHP callback that returns an escaping strategy based on the template "name" - * - * * optimizations: A flag that indicates which optimizations to apply - * (default to -1 which means that all optimizations are enabled; - * set it to 0 to disable). - */ - public function __construct(LoaderInterface $loader, $options = []) - { - $this->setLoader($loader); - - $options = array_merge([ - 'debug' => false, - 'charset' => 'UTF-8', - 'strict_variables' => false, - 'autoescape' => 'html', - 'cache' => false, - 'auto_reload' => null, - 'optimizations' => -1, - ], $options); - - $this->debug = (bool) $options['debug']; - $this->setCharset($options['charset'] ?? 'UTF-8'); - $this->autoReload = null === $options['auto_reload'] ? $this->debug : (bool) $options['auto_reload']; - $this->strictVariables = (bool) $options['strict_variables']; - $this->setCache($options['cache']); - $this->extensionSet = new ExtensionSet(); - - $this->addExtension(new CoreExtension()); - $this->addExtension(new EscaperExtension($options['autoescape'])); - $this->addExtension(new OptimizerExtension($options['optimizations'])); - } - - /** - * Enables debugging mode. - */ - public function enableDebug() - { - $this->debug = true; - $this->updateOptionsHash(); - } - - /** - * Disables debugging mode. - */ - public function disableDebug() - { - $this->debug = false; - $this->updateOptionsHash(); - } - - /** - * Checks if debug mode is enabled. - * - * @return bool true if debug mode is enabled, false otherwise - */ - public function isDebug() - { - return $this->debug; - } - - /** - * Enables the auto_reload option. - */ - public function enableAutoReload() - { - $this->autoReload = true; - } - - /** - * Disables the auto_reload option. - */ - public function disableAutoReload() - { - $this->autoReload = false; - } - - /** - * Checks if the auto_reload option is enabled. - * - * @return bool true if auto_reload is enabled, false otherwise - */ - public function isAutoReload() - { - return $this->autoReload; - } - - /** - * Enables the strict_variables option. - */ - public function enableStrictVariables() - { - $this->strictVariables = true; - $this->updateOptionsHash(); - } - - /** - * Disables the strict_variables option. - */ - public function disableStrictVariables() - { - $this->strictVariables = false; - $this->updateOptionsHash(); - } - - /** - * Checks if the strict_variables option is enabled. - * - * @return bool true if strict_variables is enabled, false otherwise - */ - public function isStrictVariables() - { - return $this->strictVariables; - } - - /** - * Gets the current cache implementation. - * - * @param bool $original Whether to return the original cache option or the real cache instance - * - * @return CacheInterface|string|false A Twig\Cache\CacheInterface implementation, - * an absolute path to the compiled templates, - * or false to disable cache - */ - public function getCache($original = true) - { - return $original ? $this->originalCache : $this->cache; - } - - /** - * Sets the current cache implementation. - * - * @param CacheInterface|string|false $cache A Twig\Cache\CacheInterface implementation, - * an absolute path to the compiled templates, - * or false to disable cache - */ - public function setCache($cache) - { - if (\is_string($cache)) { - $this->originalCache = $cache; - $this->cache = new FilesystemCache($cache, $this->autoReload ? FilesystemCache::FORCE_BYTECODE_INVALIDATION : 0); - } elseif (false === $cache) { - $this->originalCache = $cache; - $this->cache = new NullCache(); - } elseif ($cache instanceof CacheInterface) { - $this->originalCache = $this->cache = $cache; - } else { - throw new \LogicException('Cache can only be a string, false, or a \Twig\Cache\CacheInterface implementation.'); - } - } - - /** - * Gets the template class associated with the given string. - * - * The generated template class is based on the following parameters: - * - * * The cache key for the given template; - * * The currently enabled extensions; - * * Whether the Twig C extension is available or not; - * * PHP version; - * * Twig version; - * * Options with what environment was created. - * - * @param string $name The name for which to calculate the template class name - * @param int|null $index The index if it is an embedded template - * - * @internal - */ - public function getTemplateClass(string $name, int $index = null): string - { - $key = $this->getLoader()->getCacheKey($name).$this->optionsHash; - - return $this->templateClassPrefix.hash(\PHP_VERSION_ID < 80100 ? 'sha256' : 'xxh128', $key).(null === $index ? '' : '___'.$index); - } - - /** - * Renders a template. - * - * @param string|TemplateWrapper $name The template name - * - * @throws LoaderError When the template cannot be found - * @throws SyntaxError When an error occurred during compilation - * @throws RuntimeError When an error occurred during rendering - */ - public function render($name, array $context = []): string - { - return $this->load($name)->render($context); - } - - /** - * Displays a template. - * - * @param string|TemplateWrapper $name The template name - * - * @throws LoaderError When the template cannot be found - * @throws SyntaxError When an error occurred during compilation - * @throws RuntimeError When an error occurred during rendering - */ - public function display($name, array $context = []): void - { - $this->load($name)->display($context); - } - - /** - * Loads a template. - * - * @param string|TemplateWrapper $name The template name - * - * @throws LoaderError When the template cannot be found - * @throws RuntimeError When a previously generated cache is corrupted - * @throws SyntaxError When an error occurred during compilation - */ - public function load($name): TemplateWrapper - { - if ($name instanceof TemplateWrapper) { - return $name; - } - - return new TemplateWrapper($this, $this->loadTemplate($this->getTemplateClass($name), $name)); - } - - /** - * Loads a template internal representation. - * - * This method is for internal use only and should never be called - * directly. - * - * @param string $name The template name - * @param int $index The index if it is an embedded template - * - * @throws LoaderError When the template cannot be found - * @throws RuntimeError When a previously generated cache is corrupted - * @throws SyntaxError When an error occurred during compilation - * - * @internal - */ - public function loadTemplate(string $cls, string $name, int $index = null): Template - { - $mainCls = $cls; - if (null !== $index) { - $cls .= '___'.$index; - } - - if (isset($this->loadedTemplates[$cls])) { - return $this->loadedTemplates[$cls]; - } - - if (!class_exists($cls, false)) { - $key = $this->cache->generateKey($name, $mainCls); - - if (!$this->isAutoReload() || $this->isTemplateFresh($name, $this->cache->getTimestamp($key))) { - $this->cache->load($key); - } - - $source = null; - if (!class_exists($cls, false)) { - $source = $this->getLoader()->getSourceContext($name); - $content = $this->compileSource($source); - $this->cache->write($key, $content); - $this->cache->load($key); - - if (!class_exists($mainCls, false)) { - /* Last line of defense if either $this->bcWriteCacheFile was used, - * $this->cache is implemented as a no-op or we have a race condition - * where the cache was cleared between the above calls to write to and load from - * the cache. - */ - eval('?>'.$content); - } - - if (!class_exists($cls, false)) { - throw new RuntimeError(sprintf('Failed to load Twig template "%s", index "%s": cache might be corrupted.', $name, $index), -1, $source); - } - } - } - - $this->extensionSet->initRuntime(); - - return $this->loadedTemplates[$cls] = new $cls($this); - } - - /** - * Creates a template from source. - * - * This method should not be used as a generic way to load templates. - * - * @param string $template The template source - * @param string $name An optional name of the template to be used in error messages - * - * @throws LoaderError When the template cannot be found - * @throws SyntaxError When an error occurred during compilation - */ - public function createTemplate(string $template, string $name = null): TemplateWrapper - { - $hash = hash(\PHP_VERSION_ID < 80100 ? 'sha256' : 'xxh128', $template, false); - if (null !== $name) { - $name = sprintf('%s (string template %s)', $name, $hash); - } else { - $name = sprintf('__string_template__%s', $hash); - } - - $loader = new ChainLoader([ - new ArrayLoader([$name => $template]), - $current = $this->getLoader(), - ]); - - $this->setLoader($loader); - try { - return new TemplateWrapper($this, $this->loadTemplate($this->getTemplateClass($name), $name)); - } finally { - $this->setLoader($current); - } - } - - /** - * Returns true if the template is still fresh. - * - * Besides checking the loader for freshness information, - * this method also checks if the enabled extensions have - * not changed. - * - * @param int $time The last modification time of the cached template - */ - public function isTemplateFresh(string $name, int $time): bool - { - return $this->extensionSet->getLastModified() <= $time && $this->getLoader()->isFresh($name, $time); - } - - /** - * Tries to load a template consecutively from an array. - * - * Similar to load() but it also accepts instances of \Twig\Template and - * \Twig\TemplateWrapper, and an array of templates where each is tried to be loaded. - * - * @param string|TemplateWrapper|array $names A template or an array of templates to try consecutively - * - * @throws LoaderError When none of the templates can be found - * @throws SyntaxError When an error occurred during compilation - */ - public function resolveTemplate($names): TemplateWrapper - { - if (!\is_array($names)) { - return $this->load($names); - } - - $count = \count($names); - foreach ($names as $name) { - if ($name instanceof Template) { - return $name; - } - if ($name instanceof TemplateWrapper) { - return $name; - } - - if (1 !== $count && !$this->getLoader()->exists($name)) { - continue; - } - - return $this->load($name); - } - - throw new LoaderError(sprintf('Unable to find one of the following templates: "%s".', implode('", "', $names))); - } - - public function setLexer(Lexer $lexer) - { - $this->lexer = $lexer; - } - - /** - * @throws SyntaxError When the code is syntactically wrong - */ - public function tokenize(Source $source): TokenStream - { - if (null === $this->lexer) { - $this->lexer = new Lexer($this); - } - - return $this->lexer->tokenize($source); - } - - public function setParser(Parser $parser) - { - $this->parser = $parser; - } - - /** - * Converts a token stream to a node tree. - * - * @throws SyntaxError When the token stream is syntactically or semantically wrong - */ - public function parse(TokenStream $stream): ModuleNode - { - if (null === $this->parser) { - $this->parser = new Parser($this); - } - - return $this->parser->parse($stream); - } - - public function setCompiler(Compiler $compiler) - { - $this->compiler = $compiler; - } - - /** - * Compiles a node and returns the PHP code. - */ - public function compile(Node $node): string - { - if (null === $this->compiler) { - $this->compiler = new Compiler($this); - } - - return $this->compiler->compile($node)->getSource(); - } - - /** - * Compiles a template source code. - * - * @throws SyntaxError When there was an error during tokenizing, parsing or compiling - */ - public function compileSource(Source $source): string - { - try { - return $this->compile($this->parse($this->tokenize($source))); - } catch (Error $e) { - $e->setSourceContext($source); - throw $e; - } catch (\Exception $e) { - throw new SyntaxError(sprintf('An exception has been thrown during the compilation of a template ("%s").', $e->getMessage()), -1, $source, $e); - } - } - - public function setLoader(LoaderInterface $loader) - { - $this->loader = $loader; - } - - public function getLoader(): LoaderInterface - { - return $this->loader; - } - - public function setCharset(string $charset) - { - if ('UTF8' === $charset = null === $charset ? null : strtoupper($charset)) { - // iconv on Windows requires "UTF-8" instead of "UTF8" - $charset = 'UTF-8'; - } - - $this->charset = $charset; - } - - public function getCharset(): string - { - return $this->charset; - } - - public function hasExtension(string $class): bool - { - return $this->extensionSet->hasExtension($class); - } - - public function addRuntimeLoader(RuntimeLoaderInterface $loader) - { - $this->runtimeLoaders[] = $loader; - } - - /** - * @template TExtension of ExtensionInterface - * - * @param class-string<TExtension> $class - * - * @return TExtension - */ - public function getExtension(string $class): ExtensionInterface - { - return $this->extensionSet->getExtension($class); - } - - /** - * Returns the runtime implementation of a Twig element (filter/function/tag/test). - * - * @template TRuntime of object - * - * @param class-string<TRuntime> $class A runtime class name - * - * @return TRuntime The runtime implementation - * - * @throws RuntimeError When the template cannot be found - */ - public function getRuntime(string $class) - { - if (isset($this->runtimes[$class])) { - return $this->runtimes[$class]; - } - - foreach ($this->runtimeLoaders as $loader) { - if (null !== $runtime = $loader->load($class)) { - return $this->runtimes[$class] = $runtime; - } - } - - throw new RuntimeError(sprintf('Unable to load the "%s" runtime.', $class)); - } - - public function addExtension(ExtensionInterface $extension) - { - $this->extensionSet->addExtension($extension); - $this->updateOptionsHash(); - } - - /** - * @param ExtensionInterface[] $extensions An array of extensions - */ - public function setExtensions(array $extensions) - { - $this->extensionSet->setExtensions($extensions); - $this->updateOptionsHash(); - } - - /** - * @return ExtensionInterface[] An array of extensions (keys are for internal usage only and should not be relied on) - */ - public function getExtensions(): array - { - return $this->extensionSet->getExtensions(); - } - - public function addTokenParser(TokenParserInterface $parser) - { - $this->extensionSet->addTokenParser($parser); - } - - /** - * @return TokenParserInterface[] - * - * @internal - */ - public function getTokenParsers(): array - { - return $this->extensionSet->getTokenParsers(); - } - - /** - * @internal - */ - public function getTokenParser(string $name): ?TokenParserInterface - { - return $this->extensionSet->getTokenParser($name); - } - - public function registerUndefinedTokenParserCallback(callable $callable): void - { - $this->extensionSet->registerUndefinedTokenParserCallback($callable); - } - - public function addNodeVisitor(NodeVisitorInterface $visitor) - { - $this->extensionSet->addNodeVisitor($visitor); - } - - /** - * @return NodeVisitorInterface[] - * - * @internal - */ - public function getNodeVisitors(): array - { - return $this->extensionSet->getNodeVisitors(); - } - - public function addFilter(TwigFilter $filter) - { - $this->extensionSet->addFilter($filter); - } - - /** - * @internal - */ - public function getFilter(string $name): ?TwigFilter - { - return $this->extensionSet->getFilter($name); - } - - public function registerUndefinedFilterCallback(callable $callable): void - { - $this->extensionSet->registerUndefinedFilterCallback($callable); - } - - /** - * Gets the registered Filters. - * - * Be warned that this method cannot return filters defined with registerUndefinedFilterCallback. - * - * @return TwigFilter[] - * - * @see registerUndefinedFilterCallback - * - * @internal - */ - public function getFilters(): array - { - return $this->extensionSet->getFilters(); - } - - public function addTest(TwigTest $test) - { - $this->extensionSet->addTest($test); - } - - /** - * @return TwigTest[] - * - * @internal - */ - public function getTests(): array - { - return $this->extensionSet->getTests(); - } - - /** - * @internal - */ - public function getTest(string $name): ?TwigTest - { - return $this->extensionSet->getTest($name); - } - - public function addFunction(TwigFunction $function) - { - $this->extensionSet->addFunction($function); - } - - /** - * @internal - */ - public function getFunction(string $name): ?TwigFunction - { - return $this->extensionSet->getFunction($name); - } - - public function registerUndefinedFunctionCallback(callable $callable): void - { - $this->extensionSet->registerUndefinedFunctionCallback($callable); - } - - /** - * Gets registered functions. - * - * Be warned that this method cannot return functions defined with registerUndefinedFunctionCallback. - * - * @return TwigFunction[] - * - * @see registerUndefinedFunctionCallback - * - * @internal - */ - public function getFunctions(): array - { - return $this->extensionSet->getFunctions(); - } - - /** - * Registers a Global. - * - * New globals can be added before compiling or rendering a template; - * but after, you can only update existing globals. - * - * @param mixed $value The global value - */ - public function addGlobal(string $name, $value) - { - if ($this->extensionSet->isInitialized() && !\array_key_exists($name, $this->getGlobals())) { - throw new \LogicException(sprintf('Unable to add global "%s" as the runtime or the extensions have already been initialized.', $name)); - } - - if (null !== $this->resolvedGlobals) { - $this->resolvedGlobals[$name] = $value; - } else { - $this->globals[$name] = $value; - } - } - - /** - * @internal - */ - public function getGlobals(): array - { - if ($this->extensionSet->isInitialized()) { - if (null === $this->resolvedGlobals) { - $this->resolvedGlobals = array_merge($this->extensionSet->getGlobals(), $this->globals); - } - - return $this->resolvedGlobals; - } - - return array_merge($this->extensionSet->getGlobals(), $this->globals); - } - - public function mergeGlobals(array $context): array - { - // we don't use array_merge as the context being generally - // bigger than globals, this code is faster. - foreach ($this->getGlobals() as $key => $value) { - if (!\array_key_exists($key, $context)) { - $context[$key] = $value; - } - } - - return $context; - } - - /** - * @internal - */ - public function getUnaryOperators(): array - { - return $this->extensionSet->getUnaryOperators(); - } - - /** - * @internal - */ - public function getBinaryOperators(): array - { - return $this->extensionSet->getBinaryOperators(); - } - - private function updateOptionsHash(): void - { - $this->optionsHash = implode(':', [ - $this->extensionSet->getSignature(), - \PHP_MAJOR_VERSION, - \PHP_MINOR_VERSION, - self::VERSION, - (int) $this->debug, - (int) $this->strictVariables, - ]); - } -} diff --git a/lib/twig/twig/src/Error/Error.php b/lib/twig/twig/src/Error/Error.php deleted file mode 100644 index a68be65f2..000000000 --- a/lib/twig/twig/src/Error/Error.php +++ /dev/null @@ -1,227 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Error; - -use Twig\Source; -use Twig\Template; - -/** - * Twig base exception. - * - * This exception class and its children must only be used when - * an error occurs during the loading of a template, when a syntax error - * is detected in a template, or when rendering a template. Other - * errors must use regular PHP exception classes (like when the template - * cache directory is not writable for instance). - * - * To help debugging template issues, this class tracks the original template - * name and line where the error occurred. - * - * Whenever possible, you must set these information (original template name - * and line number) yourself by passing them to the constructor. If some or all - * these information are not available from where you throw the exception, then - * this class will guess them automatically (when the line number is set to -1 - * and/or the name is set to null). As this is a costly operation, this - * can be disabled by passing false for both the name and the line number - * when creating a new instance of this class. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Error extends \Exception -{ - private $lineno; - private $name; - private $rawMessage; - private $sourcePath; - private $sourceCode; - - /** - * Constructor. - * - * By default, automatic guessing is enabled. - * - * @param string $message The error message - * @param int $lineno The template line where the error occurred - * @param Source|null $source The source context where the error occurred - */ - public function __construct(string $message, int $lineno = -1, Source $source = null, \Exception $previous = null) - { - parent::__construct('', 0, $previous); - - if (null === $source) { - $name = null; - } else { - $name = $source->getName(); - $this->sourceCode = $source->getCode(); - $this->sourcePath = $source->getPath(); - } - - $this->lineno = $lineno; - $this->name = $name; - $this->rawMessage = $message; - $this->updateRepr(); - } - - public function getRawMessage(): string - { - return $this->rawMessage; - } - - public function getTemplateLine(): int - { - return $this->lineno; - } - - public function setTemplateLine(int $lineno): void - { - $this->lineno = $lineno; - - $this->updateRepr(); - } - - public function getSourceContext(): ?Source - { - return $this->name ? new Source($this->sourceCode, $this->name, $this->sourcePath) : null; - } - - public function setSourceContext(Source $source = null): void - { - if (null === $source) { - $this->sourceCode = $this->name = $this->sourcePath = null; - } else { - $this->sourceCode = $source->getCode(); - $this->name = $source->getName(); - $this->sourcePath = $source->getPath(); - } - - $this->updateRepr(); - } - - public function guess(): void - { - $this->guessTemplateInfo(); - $this->updateRepr(); - } - - public function appendMessage($rawMessage): void - { - $this->rawMessage .= $rawMessage; - $this->updateRepr(); - } - - private function updateRepr(): void - { - $this->message = $this->rawMessage; - - if ($this->sourcePath && $this->lineno > 0) { - $this->file = $this->sourcePath; - $this->line = $this->lineno; - - return; - } - - $dot = false; - if ('.' === substr($this->message, -1)) { - $this->message = substr($this->message, 0, -1); - $dot = true; - } - - $questionMark = false; - if ('?' === substr($this->message, -1)) { - $this->message = substr($this->message, 0, -1); - $questionMark = true; - } - - if ($this->name) { - if (\is_string($this->name) || (\is_object($this->name) && method_exists($this->name, '__toString'))) { - $name = sprintf('"%s"', $this->name); - } else { - $name = json_encode($this->name); - } - $this->message .= sprintf(' in %s', $name); - } - - if ($this->lineno && $this->lineno >= 0) { - $this->message .= sprintf(' at line %d', $this->lineno); - } - - if ($dot) { - $this->message .= '.'; - } - - if ($questionMark) { - $this->message .= '?'; - } - } - - private function guessTemplateInfo(): void - { - $template = null; - $templateClass = null; - - $backtrace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS | \DEBUG_BACKTRACE_PROVIDE_OBJECT); - foreach ($backtrace as $trace) { - if (isset($trace['object']) && $trace['object'] instanceof Template) { - $currentClass = \get_class($trace['object']); - $isEmbedContainer = null === $templateClass ? false : 0 === strpos($templateClass, $currentClass); - if (null === $this->name || ($this->name == $trace['object']->getTemplateName() && !$isEmbedContainer)) { - $template = $trace['object']; - $templateClass = \get_class($trace['object']); - } - } - } - - // update template name - if (null !== $template && null === $this->name) { - $this->name = $template->getTemplateName(); - } - - // update template path if any - if (null !== $template && null === $this->sourcePath) { - $src = $template->getSourceContext(); - $this->sourceCode = $src->getCode(); - $this->sourcePath = $src->getPath(); - } - - if (null === $template || $this->lineno > -1) { - return; - } - - $r = new \ReflectionObject($template); - $file = $r->getFileName(); - - $exceptions = [$e = $this]; - while ($e = $e->getPrevious()) { - $exceptions[] = $e; - } - - while ($e = array_pop($exceptions)) { - $traces = $e->getTrace(); - array_unshift($traces, ['file' => $e->getFile(), 'line' => $e->getLine()]); - - while ($trace = array_shift($traces)) { - if (!isset($trace['file']) || !isset($trace['line']) || $file != $trace['file']) { - continue; - } - - foreach ($template->getDebugInfo() as $codeLine => $templateLine) { - if ($codeLine <= $trace['line']) { - // update template line - $this->lineno = $templateLine; - - return; - } - } - } - } - } -} diff --git a/lib/twig/twig/src/Error/LoaderError.php b/lib/twig/twig/src/Error/LoaderError.php deleted file mode 100644 index 7c8c23c19..000000000 --- a/lib/twig/twig/src/Error/LoaderError.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Error; - -/** - * Exception thrown when an error occurs during template loading. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class LoaderError extends Error -{ -} diff --git a/lib/twig/twig/src/Error/RuntimeError.php b/lib/twig/twig/src/Error/RuntimeError.php deleted file mode 100644 index f6b84766c..000000000 --- a/lib/twig/twig/src/Error/RuntimeError.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Error; - -/** - * Exception thrown when an error occurs at runtime. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class RuntimeError extends Error -{ -} diff --git a/lib/twig/twig/src/Error/SyntaxError.php b/lib/twig/twig/src/Error/SyntaxError.php deleted file mode 100644 index 726b3309e..000000000 --- a/lib/twig/twig/src/Error/SyntaxError.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Error; - -/** - * \Exception thrown when a syntax error occurs during lexing or parsing of a template. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class SyntaxError extends Error -{ - /** - * Tweaks the error message to include suggestions. - * - * @param string $name The original name of the item that does not exist - * @param array $items An array of possible items - */ - public function addSuggestions(string $name, array $items): void - { - $alternatives = []; - foreach ($items as $item) { - $lev = levenshtein($name, $item); - if ($lev <= \strlen($name) / 3 || false !== strpos($item, $name)) { - $alternatives[$item] = $lev; - } - } - - if (!$alternatives) { - return; - } - - asort($alternatives); - - $this->appendMessage(sprintf(' Did you mean "%s"?', implode('", "', array_keys($alternatives)))); - } -} diff --git a/lib/twig/twig/src/ExpressionParser.php b/lib/twig/twig/src/ExpressionParser.php deleted file mode 100644 index 70b6eb05c..000000000 --- a/lib/twig/twig/src/ExpressionParser.php +++ /dev/null @@ -1,825 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig; - -use Twig\Error\SyntaxError; -use Twig\Node\Expression\AbstractExpression; -use Twig\Node\Expression\ArrayExpression; -use Twig\Node\Expression\ArrowFunctionExpression; -use Twig\Node\Expression\AssignNameExpression; -use Twig\Node\Expression\Binary\ConcatBinary; -use Twig\Node\Expression\BlockReferenceExpression; -use Twig\Node\Expression\ConditionalExpression; -use Twig\Node\Expression\ConstantExpression; -use Twig\Node\Expression\GetAttrExpression; -use Twig\Node\Expression\MethodCallExpression; -use Twig\Node\Expression\NameExpression; -use Twig\Node\Expression\ParentExpression; -use Twig\Node\Expression\TestExpression; -use Twig\Node\Expression\Unary\NegUnary; -use Twig\Node\Expression\Unary\NotUnary; -use Twig\Node\Expression\Unary\PosUnary; -use Twig\Node\Node; - -/** - * Parses expressions. - * - * This parser implements a "Precedence climbing" algorithm. - * - * @see https://www.engr.mun.ca/~theo/Misc/exp_parsing.htm - * @see https://en.wikipedia.org/wiki/Operator-precedence_parser - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @internal - */ -class ExpressionParser -{ - public const OPERATOR_LEFT = 1; - public const OPERATOR_RIGHT = 2; - - private $parser; - private $env; - private $unaryOperators; - private $binaryOperators; - - public function __construct(Parser $parser, Environment $env) - { - $this->parser = $parser; - $this->env = $env; - $this->unaryOperators = $env->getUnaryOperators(); - $this->binaryOperators = $env->getBinaryOperators(); - } - - public function parseExpression($precedence = 0, $allowArrow = false) - { - if ($allowArrow && $arrow = $this->parseArrow()) { - return $arrow; - } - - $expr = $this->getPrimary(); - $token = $this->parser->getCurrentToken(); - while ($this->isBinary($token) && $this->binaryOperators[$token->getValue()]['precedence'] >= $precedence) { - $op = $this->binaryOperators[$token->getValue()]; - $this->parser->getStream()->next(); - - if ('is not' === $token->getValue()) { - $expr = $this->parseNotTestExpression($expr); - } elseif ('is' === $token->getValue()) { - $expr = $this->parseTestExpression($expr); - } elseif (isset($op['callable'])) { - $expr = $op['callable']($this->parser, $expr); - } else { - $expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence']); - $class = $op['class']; - $expr = new $class($expr, $expr1, $token->getLine()); - } - - $token = $this->parser->getCurrentToken(); - } - - if (0 === $precedence) { - return $this->parseConditionalExpression($expr); - } - - return $expr; - } - - /** - * @return ArrowFunctionExpression|null - */ - private function parseArrow() - { - $stream = $this->parser->getStream(); - - // short array syntax (one argument, no parentheses)? - if ($stream->look(1)->test(/* Token::ARROW_TYPE */ 12)) { - $line = $stream->getCurrent()->getLine(); - $token = $stream->expect(/* Token::NAME_TYPE */ 5); - $names = [new AssignNameExpression($token->getValue(), $token->getLine())]; - $stream->expect(/* Token::ARROW_TYPE */ 12); - - return new ArrowFunctionExpression($this->parseExpression(0), new Node($names), $line); - } - - // first, determine if we are parsing an arrow function by finding => (long form) - $i = 0; - if (!$stream->look($i)->test(/* Token::PUNCTUATION_TYPE */ 9, '(')) { - return null; - } - ++$i; - while (true) { - // variable name - ++$i; - if (!$stream->look($i)->test(/* Token::PUNCTUATION_TYPE */ 9, ',')) { - break; - } - ++$i; - } - if (!$stream->look($i)->test(/* Token::PUNCTUATION_TYPE */ 9, ')')) { - return null; - } - ++$i; - if (!$stream->look($i)->test(/* Token::ARROW_TYPE */ 12)) { - return null; - } - - // yes, let's parse it properly - $token = $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, '('); - $line = $token->getLine(); - - $names = []; - while (true) { - $token = $stream->expect(/* Token::NAME_TYPE */ 5); - $names[] = new AssignNameExpression($token->getValue(), $token->getLine()); - - if (!$stream->nextIf(/* Token::PUNCTUATION_TYPE */ 9, ',')) { - break; - } - } - $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, ')'); - $stream->expect(/* Token::ARROW_TYPE */ 12); - - return new ArrowFunctionExpression($this->parseExpression(0), new Node($names), $line); - } - - private function getPrimary(): AbstractExpression - { - $token = $this->parser->getCurrentToken(); - - if ($this->isUnary($token)) { - $operator = $this->unaryOperators[$token->getValue()]; - $this->parser->getStream()->next(); - $expr = $this->parseExpression($operator['precedence']); - $class = $operator['class']; - - return $this->parsePostfixExpression(new $class($expr, $token->getLine())); - } elseif ($token->test(/* Token::PUNCTUATION_TYPE */ 9, '(')) { - $this->parser->getStream()->next(); - $expr = $this->parseExpression(); - $this->parser->getStream()->expect(/* Token::PUNCTUATION_TYPE */ 9, ')', 'An opened parenthesis is not properly closed'); - - return $this->parsePostfixExpression($expr); - } - - return $this->parsePrimaryExpression(); - } - - private function parseConditionalExpression($expr): AbstractExpression - { - while ($this->parser->getStream()->nextIf(/* Token::PUNCTUATION_TYPE */ 9, '?')) { - if (!$this->parser->getStream()->nextIf(/* Token::PUNCTUATION_TYPE */ 9, ':')) { - $expr2 = $this->parseExpression(); - if ($this->parser->getStream()->nextIf(/* Token::PUNCTUATION_TYPE */ 9, ':')) { - $expr3 = $this->parseExpression(); - } else { - $expr3 = new ConstantExpression('', $this->parser->getCurrentToken()->getLine()); - } - } else { - $expr2 = $expr; - $expr3 = $this->parseExpression(); - } - - $expr = new ConditionalExpression($expr, $expr2, $expr3, $this->parser->getCurrentToken()->getLine()); - } - - return $expr; - } - - private function isUnary(Token $token): bool - { - return $token->test(/* Token::OPERATOR_TYPE */ 8) && isset($this->unaryOperators[$token->getValue()]); - } - - private function isBinary(Token $token): bool - { - return $token->test(/* Token::OPERATOR_TYPE */ 8) && isset($this->binaryOperators[$token->getValue()]); - } - - public function parsePrimaryExpression() - { - $token = $this->parser->getCurrentToken(); - switch ($token->getType()) { - case /* Token::NAME_TYPE */ 5: - $this->parser->getStream()->next(); - switch ($token->getValue()) { - case 'true': - case 'TRUE': - $node = new ConstantExpression(true, $token->getLine()); - break; - - case 'false': - case 'FALSE': - $node = new ConstantExpression(false, $token->getLine()); - break; - - case 'none': - case 'NONE': - case 'null': - case 'NULL': - $node = new ConstantExpression(null, $token->getLine()); - break; - - default: - if ('(' === $this->parser->getCurrentToken()->getValue()) { - $node = $this->getFunctionNode($token->getValue(), $token->getLine()); - } else { - $node = new NameExpression($token->getValue(), $token->getLine()); - } - } - break; - - case /* Token::NUMBER_TYPE */ 6: - $this->parser->getStream()->next(); - $node = new ConstantExpression($token->getValue(), $token->getLine()); - break; - - case /* Token::STRING_TYPE */ 7: - case /* Token::INTERPOLATION_START_TYPE */ 10: - $node = $this->parseStringExpression(); - break; - - case /* Token::OPERATOR_TYPE */ 8: - if (preg_match(Lexer::REGEX_NAME, $token->getValue(), $matches) && $matches[0] == $token->getValue()) { - // in this context, string operators are variable names - $this->parser->getStream()->next(); - $node = new NameExpression($token->getValue(), $token->getLine()); - break; - } - - if (isset($this->unaryOperators[$token->getValue()])) { - $class = $this->unaryOperators[$token->getValue()]['class']; - if (!\in_array($class, [NegUnary::class, PosUnary::class])) { - throw new SyntaxError(sprintf('Unexpected unary operator "%s".', $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()); - } - - $this->parser->getStream()->next(); - $expr = $this->parsePrimaryExpression(); - - $node = new $class($expr, $token->getLine()); - break; - } - - // no break - default: - if ($token->test(/* Token::PUNCTUATION_TYPE */ 9, '[')) { - $node = $this->parseArrayExpression(); - } elseif ($token->test(/* Token::PUNCTUATION_TYPE */ 9, '{')) { - $node = $this->parseHashExpression(); - } elseif ($token->test(/* Token::OPERATOR_TYPE */ 8, '=') && ('==' === $this->parser->getStream()->look(-1)->getValue() || '!=' === $this->parser->getStream()->look(-1)->getValue())) { - throw new SyntaxError(sprintf('Unexpected operator of value "%s". Did you try to use "===" or "!==" for strict comparison? Use "is same as(value)" instead.', $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()); - } else { - throw new SyntaxError(sprintf('Unexpected token "%s" of value "%s".', Token::typeToEnglish($token->getType()), $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()); - } - } - - return $this->parsePostfixExpression($node); - } - - public function parseStringExpression() - { - $stream = $this->parser->getStream(); - - $nodes = []; - // a string cannot be followed by another string in a single expression - $nextCanBeString = true; - while (true) { - if ($nextCanBeString && $token = $stream->nextIf(/* Token::STRING_TYPE */ 7)) { - $nodes[] = new ConstantExpression($token->getValue(), $token->getLine()); - $nextCanBeString = false; - } elseif ($stream->nextIf(/* Token::INTERPOLATION_START_TYPE */ 10)) { - $nodes[] = $this->parseExpression(); - $stream->expect(/* Token::INTERPOLATION_END_TYPE */ 11); - $nextCanBeString = true; - } else { - break; - } - } - - $expr = array_shift($nodes); - foreach ($nodes as $node) { - $expr = new ConcatBinary($expr, $node, $node->getTemplateLine()); - } - - return $expr; - } - - public function parseArrayExpression() - { - $stream = $this->parser->getStream(); - $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, '[', 'An array element was expected'); - - $node = new ArrayExpression([], $stream->getCurrent()->getLine()); - $first = true; - while (!$stream->test(/* Token::PUNCTUATION_TYPE */ 9, ']')) { - if (!$first) { - $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, ',', 'An array element must be followed by a comma'); - - // trailing ,? - if ($stream->test(/* Token::PUNCTUATION_TYPE */ 9, ']')) { - break; - } - } - $first = false; - - $node->addElement($this->parseExpression()); - } - $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, ']', 'An opened array is not properly closed'); - - return $node; - } - - public function parseHashExpression() - { - $stream = $this->parser->getStream(); - $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, '{', 'A hash element was expected'); - - $node = new ArrayExpression([], $stream->getCurrent()->getLine()); - $first = true; - while (!$stream->test(/* Token::PUNCTUATION_TYPE */ 9, '}')) { - if (!$first) { - $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, ',', 'A hash value must be followed by a comma'); - - // trailing ,? - if ($stream->test(/* Token::PUNCTUATION_TYPE */ 9, '}')) { - break; - } - } - $first = false; - - // a hash key can be: - // - // * a number -- 12 - // * a string -- 'a' - // * a name, which is equivalent to a string -- a - // * an expression, which must be enclosed in parentheses -- (1 + 2) - if ($token = $stream->nextIf(/* Token::NAME_TYPE */ 5)) { - $key = new ConstantExpression($token->getValue(), $token->getLine()); - - // {a} is a shortcut for {a:a} - if ($stream->test(Token::PUNCTUATION_TYPE, [',', '}'])) { - $value = new NameExpression($key->getAttribute('value'), $key->getTemplateLine()); - $node->addElement($value, $key); - continue; - } - } elseif (($token = $stream->nextIf(/* Token::STRING_TYPE */ 7)) || $token = $stream->nextIf(/* Token::NUMBER_TYPE */ 6)) { - $key = new ConstantExpression($token->getValue(), $token->getLine()); - } elseif ($stream->test(/* Token::PUNCTUATION_TYPE */ 9, '(')) { - $key = $this->parseExpression(); - } else { - $current = $stream->getCurrent(); - - throw new SyntaxError(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s".', Token::typeToEnglish($current->getType()), $current->getValue()), $current->getLine(), $stream->getSourceContext()); - } - - $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, ':', 'A hash key must be followed by a colon (:)'); - $value = $this->parseExpression(); - - $node->addElement($value, $key); - } - $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, '}', 'An opened hash is not properly closed'); - - return $node; - } - - public function parsePostfixExpression($node) - { - while (true) { - $token = $this->parser->getCurrentToken(); - if (/* Token::PUNCTUATION_TYPE */ 9 == $token->getType()) { - if ('.' == $token->getValue() || '[' == $token->getValue()) { - $node = $this->parseSubscriptExpression($node); - } elseif ('|' == $token->getValue()) { - $node = $this->parseFilterExpression($node); - } else { - break; - } - } else { - break; - } - } - - return $node; - } - - public function getFunctionNode($name, $line) - { - switch ($name) { - case 'parent': - $this->parseArguments(); - if (!\count($this->parser->getBlockStack())) { - throw new SyntaxError('Calling "parent" outside a block is forbidden.', $line, $this->parser->getStream()->getSourceContext()); - } - - if (!$this->parser->getParent() && !$this->parser->hasTraits()) { - throw new SyntaxError('Calling "parent" on a template that does not extend nor "use" another template is forbidden.', $line, $this->parser->getStream()->getSourceContext()); - } - - return new ParentExpression($this->parser->peekBlockStack(), $line); - case 'block': - $args = $this->parseArguments(); - if (\count($args) < 1) { - throw new SyntaxError('The "block" function takes one argument (the block name).', $line, $this->parser->getStream()->getSourceContext()); - } - - return new BlockReferenceExpression($args->getNode(0), \count($args) > 1 ? $args->getNode(1) : null, $line); - case 'attribute': - $args = $this->parseArguments(); - if (\count($args) < 2) { - throw new SyntaxError('The "attribute" function takes at least two arguments (the variable and the attributes).', $line, $this->parser->getStream()->getSourceContext()); - } - - return new GetAttrExpression($args->getNode(0), $args->getNode(1), \count($args) > 2 ? $args->getNode(2) : null, Template::ANY_CALL, $line); - default: - if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) { - $arguments = new ArrayExpression([], $line); - foreach ($this->parseArguments() as $n) { - $arguments->addElement($n); - } - - $node = new MethodCallExpression($alias['node'], $alias['name'], $arguments, $line); - $node->setAttribute('safe', true); - - return $node; - } - - $args = $this->parseArguments(true); - $class = $this->getFunctionNodeClass($name, $line); - - return new $class($name, $args, $line); - } - } - - public function parseSubscriptExpression($node) - { - $stream = $this->parser->getStream(); - $token = $stream->next(); - $lineno = $token->getLine(); - $arguments = new ArrayExpression([], $lineno); - $type = Template::ANY_CALL; - if ('.' == $token->getValue()) { - $token = $stream->next(); - if ( - /* Token::NAME_TYPE */ 5 == $token->getType() - || - /* Token::NUMBER_TYPE */ 6 == $token->getType() - || - (/* Token::OPERATOR_TYPE */ 8 == $token->getType() && preg_match(Lexer::REGEX_NAME, $token->getValue())) - ) { - $arg = new ConstantExpression($token->getValue(), $lineno); - - if ($stream->test(/* Token::PUNCTUATION_TYPE */ 9, '(')) { - $type = Template::METHOD_CALL; - foreach ($this->parseArguments() as $n) { - $arguments->addElement($n); - } - } - } else { - throw new SyntaxError(sprintf('Expected name or number, got value "%s" of type %s.', $token->getValue(), Token::typeToEnglish($token->getType())), $lineno, $stream->getSourceContext()); - } - - if ($node instanceof NameExpression && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) { - if (!$arg instanceof ConstantExpression) { - throw new SyntaxError(sprintf('Dynamic macro names are not supported (called on "%s").', $node->getAttribute('name')), $token->getLine(), $stream->getSourceContext()); - } - - $name = $arg->getAttribute('value'); - - $node = new MethodCallExpression($node, 'macro_'.$name, $arguments, $lineno); - $node->setAttribute('safe', true); - - return $node; - } - } else { - $type = Template::ARRAY_CALL; - - // slice? - $slice = false; - if ($stream->test(/* Token::PUNCTUATION_TYPE */ 9, ':')) { - $slice = true; - $arg = new ConstantExpression(0, $token->getLine()); - } else { - $arg = $this->parseExpression(); - } - - if ($stream->nextIf(/* Token::PUNCTUATION_TYPE */ 9, ':')) { - $slice = true; - } - - if ($slice) { - if ($stream->test(/* Token::PUNCTUATION_TYPE */ 9, ']')) { - $length = new ConstantExpression(null, $token->getLine()); - } else { - $length = $this->parseExpression(); - } - - $class = $this->getFilterNodeClass('slice', $token->getLine()); - $arguments = new Node([$arg, $length]); - $filter = new $class($node, new ConstantExpression('slice', $token->getLine()), $arguments, $token->getLine()); - - $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, ']'); - - return $filter; - } - - $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, ']'); - } - - return new GetAttrExpression($node, $arg, $arguments, $type, $lineno); - } - - public function parseFilterExpression($node) - { - $this->parser->getStream()->next(); - - return $this->parseFilterExpressionRaw($node); - } - - public function parseFilterExpressionRaw($node, $tag = null) - { - while (true) { - $token = $this->parser->getStream()->expect(/* Token::NAME_TYPE */ 5); - - $name = new ConstantExpression($token->getValue(), $token->getLine()); - if (!$this->parser->getStream()->test(/* Token::PUNCTUATION_TYPE */ 9, '(')) { - $arguments = new Node(); - } else { - $arguments = $this->parseArguments(true, false, true); - } - - $class = $this->getFilterNodeClass($name->getAttribute('value'), $token->getLine()); - - $node = new $class($node, $name, $arguments, $token->getLine(), $tag); - - if (!$this->parser->getStream()->test(/* Token::PUNCTUATION_TYPE */ 9, '|')) { - break; - } - - $this->parser->getStream()->next(); - } - - return $node; - } - - /** - * Parses arguments. - * - * @param bool $namedArguments Whether to allow named arguments or not - * @param bool $definition Whether we are parsing arguments for a function definition - * - * @return Node - * - * @throws SyntaxError - */ - public function parseArguments($namedArguments = false, $definition = false, $allowArrow = false) - { - $args = []; - $stream = $this->parser->getStream(); - - $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, '(', 'A list of arguments must begin with an opening parenthesis'); - while (!$stream->test(/* Token::PUNCTUATION_TYPE */ 9, ')')) { - if (!empty($args)) { - $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, ',', 'Arguments must be separated by a comma'); - - // if the comma above was a trailing comma, early exit the argument parse loop - if ($stream->test(/* Token::PUNCTUATION_TYPE */ 9, ')')) { - break; - } - } - - if ($definition) { - $token = $stream->expect(/* Token::NAME_TYPE */ 5, null, 'An argument must be a name'); - $value = new NameExpression($token->getValue(), $this->parser->getCurrentToken()->getLine()); - } else { - $value = $this->parseExpression(0, $allowArrow); - } - - $name = null; - if ($namedArguments && $token = $stream->nextIf(/* Token::OPERATOR_TYPE */ 8, '=')) { - if (!$value instanceof NameExpression) { - throw new SyntaxError(sprintf('A parameter name must be a string, "%s" given.', \get_class($value)), $token->getLine(), $stream->getSourceContext()); - } - $name = $value->getAttribute('name'); - - if ($definition) { - $value = $this->parsePrimaryExpression(); - - if (!$this->checkConstantExpression($value)) { - throw new SyntaxError('A default value for an argument must be a constant (a boolean, a string, a number, or an array).', $token->getLine(), $stream->getSourceContext()); - } - } else { - $value = $this->parseExpression(0, $allowArrow); - } - } - - if ($definition) { - if (null === $name) { - $name = $value->getAttribute('name'); - $value = new ConstantExpression(null, $this->parser->getCurrentToken()->getLine()); - } - $args[$name] = $value; - } else { - if (null === $name) { - $args[] = $value; - } else { - $args[$name] = $value; - } - } - } - $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, ')', 'A list of arguments must be closed by a parenthesis'); - - return new Node($args); - } - - public function parseAssignmentExpression() - { - $stream = $this->parser->getStream(); - $targets = []; - while (true) { - $token = $this->parser->getCurrentToken(); - if ($stream->test(/* Token::OPERATOR_TYPE */ 8) && preg_match(Lexer::REGEX_NAME, $token->getValue())) { - // in this context, string operators are variable names - $this->parser->getStream()->next(); - } else { - $stream->expect(/* Token::NAME_TYPE */ 5, null, 'Only variables can be assigned to'); - } - $value = $token->getValue(); - if (\in_array(strtr($value, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), ['true', 'false', 'none', 'null'])) { - throw new SyntaxError(sprintf('You cannot assign a value to "%s".', $value), $token->getLine(), $stream->getSourceContext()); - } - $targets[] = new AssignNameExpression($value, $token->getLine()); - - if (!$stream->nextIf(/* Token::PUNCTUATION_TYPE */ 9, ',')) { - break; - } - } - - return new Node($targets); - } - - public function parseMultitargetExpression() - { - $targets = []; - while (true) { - $targets[] = $this->parseExpression(); - if (!$this->parser->getStream()->nextIf(/* Token::PUNCTUATION_TYPE */ 9, ',')) { - break; - } - } - - return new Node($targets); - } - - private function parseNotTestExpression(Node $node): NotUnary - { - return new NotUnary($this->parseTestExpression($node), $this->parser->getCurrentToken()->getLine()); - } - - private function parseTestExpression(Node $node): TestExpression - { - $stream = $this->parser->getStream(); - list($name, $test) = $this->getTest($node->getTemplateLine()); - - $class = $this->getTestNodeClass($test); - $arguments = null; - if ($stream->test(/* Token::PUNCTUATION_TYPE */ 9, '(')) { - $arguments = $this->parseArguments(true); - } elseif ($test->hasOneMandatoryArgument()) { - $arguments = new Node([0 => $this->parsePrimaryExpression()]); - } - - if ('defined' === $name && $node instanceof NameExpression && null !== $alias = $this->parser->getImportedSymbol('function', $node->getAttribute('name'))) { - $node = new MethodCallExpression($alias['node'], $alias['name'], new ArrayExpression([], $node->getTemplateLine()), $node->getTemplateLine()); - $node->setAttribute('safe', true); - } - - return new $class($node, $name, $arguments, $this->parser->getCurrentToken()->getLine()); - } - - private function getTest(int $line): array - { - $stream = $this->parser->getStream(); - $name = $stream->expect(/* Token::NAME_TYPE */ 5)->getValue(); - - if ($test = $this->env->getTest($name)) { - return [$name, $test]; - } - - if ($stream->test(/* Token::NAME_TYPE */ 5)) { - // try 2-words tests - $name = $name.' '.$this->parser->getCurrentToken()->getValue(); - - if ($test = $this->env->getTest($name)) { - $stream->next(); - - return [$name, $test]; - } - } - - $e = new SyntaxError(sprintf('Unknown "%s" test.', $name), $line, $stream->getSourceContext()); - $e->addSuggestions($name, array_keys($this->env->getTests())); - - throw $e; - } - - private function getTestNodeClass(TwigTest $test): string - { - if ($test->isDeprecated()) { - $stream = $this->parser->getStream(); - $message = sprintf('Twig Test "%s" is deprecated', $test->getName()); - - if ($test->getDeprecatedVersion()) { - $message .= sprintf(' since version %s', $test->getDeprecatedVersion()); - } - if ($test->getAlternative()) { - $message .= sprintf('. Use "%s" instead', $test->getAlternative()); - } - $src = $stream->getSourceContext(); - $message .= sprintf(' in %s at line %d.', $src->getPath() ?: $src->getName(), $stream->getCurrent()->getLine()); - - @trigger_error($message, \E_USER_DEPRECATED); - } - - return $test->getNodeClass(); - } - - private function getFunctionNodeClass(string $name, int $line): string - { - if (!$function = $this->env->getFunction($name)) { - $e = new SyntaxError(sprintf('Unknown "%s" function.', $name), $line, $this->parser->getStream()->getSourceContext()); - $e->addSuggestions($name, array_keys($this->env->getFunctions())); - - throw $e; - } - - if ($function->isDeprecated()) { - $message = sprintf('Twig Function "%s" is deprecated', $function->getName()); - if ($function->getDeprecatedVersion()) { - $message .= sprintf(' since version %s', $function->getDeprecatedVersion()); - } - if ($function->getAlternative()) { - $message .= sprintf('. Use "%s" instead', $function->getAlternative()); - } - $src = $this->parser->getStream()->getSourceContext(); - $message .= sprintf(' in %s at line %d.', $src->getPath() ?: $src->getName(), $line); - - @trigger_error($message, \E_USER_DEPRECATED); - } - - return $function->getNodeClass(); - } - - private function getFilterNodeClass(string $name, int $line): string - { - if (!$filter = $this->env->getFilter($name)) { - $e = new SyntaxError(sprintf('Unknown "%s" filter.', $name), $line, $this->parser->getStream()->getSourceContext()); - $e->addSuggestions($name, array_keys($this->env->getFilters())); - - throw $e; - } - - if ($filter->isDeprecated()) { - $message = sprintf('Twig Filter "%s" is deprecated', $filter->getName()); - if ($filter->getDeprecatedVersion()) { - $message .= sprintf(' since version %s', $filter->getDeprecatedVersion()); - } - if ($filter->getAlternative()) { - $message .= sprintf('. Use "%s" instead', $filter->getAlternative()); - } - $src = $this->parser->getStream()->getSourceContext(); - $message .= sprintf(' in %s at line %d.', $src->getPath() ?: $src->getName(), $line); - - @trigger_error($message, \E_USER_DEPRECATED); - } - - return $filter->getNodeClass(); - } - - // checks that the node only contains "constant" elements - private function checkConstantExpression(Node $node): bool - { - if (!($node instanceof ConstantExpression || $node instanceof ArrayExpression - || $node instanceof NegUnary || $node instanceof PosUnary - )) { - return false; - } - - foreach ($node as $n) { - if (!$this->checkConstantExpression($n)) { - return false; - } - } - - return true; - } -} diff --git a/lib/twig/twig/src/Extension/AbstractExtension.php b/lib/twig/twig/src/Extension/AbstractExtension.php deleted file mode 100644 index 422925f31..000000000 --- a/lib/twig/twig/src/Extension/AbstractExtension.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Extension; - -abstract class AbstractExtension implements ExtensionInterface -{ - public function getTokenParsers() - { - return []; - } - - public function getNodeVisitors() - { - return []; - } - - public function getFilters() - { - return []; - } - - public function getTests() - { - return []; - } - - public function getFunctions() - { - return []; - } - - public function getOperators() - { - return []; - } -} diff --git a/lib/twig/twig/src/Extension/CoreExtension.php b/lib/twig/twig/src/Extension/CoreExtension.php deleted file mode 100644 index b77985859..000000000 --- a/lib/twig/twig/src/Extension/CoreExtension.php +++ /dev/null @@ -1,1695 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Extension { -use Twig\ExpressionParser; -use Twig\Node\Expression\Binary\AddBinary; -use Twig\Node\Expression\Binary\AndBinary; -use Twig\Node\Expression\Binary\BitwiseAndBinary; -use Twig\Node\Expression\Binary\BitwiseOrBinary; -use Twig\Node\Expression\Binary\BitwiseXorBinary; -use Twig\Node\Expression\Binary\ConcatBinary; -use Twig\Node\Expression\Binary\DivBinary; -use Twig\Node\Expression\Binary\EndsWithBinary; -use Twig\Node\Expression\Binary\EqualBinary; -use Twig\Node\Expression\Binary\FloorDivBinary; -use Twig\Node\Expression\Binary\GreaterBinary; -use Twig\Node\Expression\Binary\GreaterEqualBinary; -use Twig\Node\Expression\Binary\InBinary; -use Twig\Node\Expression\Binary\LessBinary; -use Twig\Node\Expression\Binary\LessEqualBinary; -use Twig\Node\Expression\Binary\MatchesBinary; -use Twig\Node\Expression\Binary\ModBinary; -use Twig\Node\Expression\Binary\MulBinary; -use Twig\Node\Expression\Binary\NotEqualBinary; -use Twig\Node\Expression\Binary\NotInBinary; -use Twig\Node\Expression\Binary\OrBinary; -use Twig\Node\Expression\Binary\PowerBinary; -use Twig\Node\Expression\Binary\RangeBinary; -use Twig\Node\Expression\Binary\SpaceshipBinary; -use Twig\Node\Expression\Binary\StartsWithBinary; -use Twig\Node\Expression\Binary\SubBinary; -use Twig\Node\Expression\Filter\DefaultFilter; -use Twig\Node\Expression\NullCoalesceExpression; -use Twig\Node\Expression\Test\ConstantTest; -use Twig\Node\Expression\Test\DefinedTest; -use Twig\Node\Expression\Test\DivisiblebyTest; -use Twig\Node\Expression\Test\EvenTest; -use Twig\Node\Expression\Test\NullTest; -use Twig\Node\Expression\Test\OddTest; -use Twig\Node\Expression\Test\SameasTest; -use Twig\Node\Expression\Unary\NegUnary; -use Twig\Node\Expression\Unary\NotUnary; -use Twig\Node\Expression\Unary\PosUnary; -use Twig\NodeVisitor\MacroAutoImportNodeVisitor; -use Twig\TokenParser\ApplyTokenParser; -use Twig\TokenParser\BlockTokenParser; -use Twig\TokenParser\DeprecatedTokenParser; -use Twig\TokenParser\DoTokenParser; -use Twig\TokenParser\EmbedTokenParser; -use Twig\TokenParser\ExtendsTokenParser; -use Twig\TokenParser\FlushTokenParser; -use Twig\TokenParser\ForTokenParser; -use Twig\TokenParser\FromTokenParser; -use Twig\TokenParser\IfTokenParser; -use Twig\TokenParser\ImportTokenParser; -use Twig\TokenParser\IncludeTokenParser; -use Twig\TokenParser\MacroTokenParser; -use Twig\TokenParser\SetTokenParser; -use Twig\TokenParser\UseTokenParser; -use Twig\TokenParser\WithTokenParser; -use Twig\TwigFilter; -use Twig\TwigFunction; -use Twig\TwigTest; - -final class CoreExtension extends AbstractExtension -{ - private $dateFormats = ['F j, Y H:i', '%d days']; - private $numberFormat = [0, '.', ',']; - private $timezone = null; - - /** - * Sets the default format to be used by the date filter. - * - * @param string $format The default date format string - * @param string $dateIntervalFormat The default date interval format string - */ - public function setDateFormat($format = null, $dateIntervalFormat = null) - { - if (null !== $format) { - $this->dateFormats[0] = $format; - } - - if (null !== $dateIntervalFormat) { - $this->dateFormats[1] = $dateIntervalFormat; - } - } - - /** - * Gets the default format to be used by the date filter. - * - * @return array The default date format string and the default date interval format string - */ - public function getDateFormat() - { - return $this->dateFormats; - } - - /** - * Sets the default timezone to be used by the date filter. - * - * @param \DateTimeZone|string $timezone The default timezone string or a \DateTimeZone object - */ - public function setTimezone($timezone) - { - $this->timezone = $timezone instanceof \DateTimeZone ? $timezone : new \DateTimeZone($timezone); - } - - /** - * Gets the default timezone to be used by the date filter. - * - * @return \DateTimeZone The default timezone currently in use - */ - public function getTimezone() - { - if (null === $this->timezone) { - $this->timezone = new \DateTimeZone(date_default_timezone_get()); - } - - return $this->timezone; - } - - /** - * Sets the default format to be used by the number_format filter. - * - * @param int $decimal the number of decimal places to use - * @param string $decimalPoint the character(s) to use for the decimal point - * @param string $thousandSep the character(s) to use for the thousands separator - */ - public function setNumberFormat($decimal, $decimalPoint, $thousandSep) - { - $this->numberFormat = [$decimal, $decimalPoint, $thousandSep]; - } - - /** - * Get the default format used by the number_format filter. - * - * @return array The arguments for number_format() - */ - public function getNumberFormat() - { - return $this->numberFormat; - } - - public function getTokenParsers(): array - { - return [ - new ApplyTokenParser(), - new ForTokenParser(), - new IfTokenParser(), - new ExtendsTokenParser(), - new IncludeTokenParser(), - new BlockTokenParser(), - new UseTokenParser(), - new MacroTokenParser(), - new ImportTokenParser(), - new FromTokenParser(), - new SetTokenParser(), - new FlushTokenParser(), - new DoTokenParser(), - new EmbedTokenParser(), - new WithTokenParser(), - new DeprecatedTokenParser(), - ]; - } - - public function getFilters(): array - { - return [ - // formatting filters - new TwigFilter('date', 'twig_date_format_filter', ['needs_environment' => true]), - new TwigFilter('date_modify', 'twig_date_modify_filter', ['needs_environment' => true]), - new TwigFilter('format', 'twig_sprintf'), - new TwigFilter('replace', 'twig_replace_filter'), - new TwigFilter('number_format', 'twig_number_format_filter', ['needs_environment' => true]), - new TwigFilter('abs', 'abs'), - new TwigFilter('round', 'twig_round'), - - // encoding - new TwigFilter('url_encode', 'twig_urlencode_filter'), - new TwigFilter('json_encode', 'json_encode'), - new TwigFilter('convert_encoding', 'twig_convert_encoding'), - - // string filters - new TwigFilter('title', 'twig_title_string_filter', ['needs_environment' => true]), - new TwigFilter('capitalize', 'twig_capitalize_string_filter', ['needs_environment' => true]), - new TwigFilter('upper', 'twig_upper_filter', ['needs_environment' => true]), - new TwigFilter('lower', 'twig_lower_filter', ['needs_environment' => true]), - new TwigFilter('striptags', 'twig_striptags'), - new TwigFilter('trim', 'twig_trim_filter'), - new TwigFilter('nl2br', 'twig_nl2br', ['pre_escape' => 'html', 'is_safe' => ['html']]), - new TwigFilter('spaceless', 'twig_spaceless', ['is_safe' => ['html']]), - - // array helpers - new TwigFilter('join', 'twig_join_filter'), - new TwigFilter('split', 'twig_split_filter', ['needs_environment' => true]), - new TwigFilter('sort', 'twig_sort_filter', ['needs_environment' => true]), - new TwigFilter('merge', 'twig_array_merge'), - new TwigFilter('batch', 'twig_array_batch'), - new TwigFilter('column', 'twig_array_column'), - new TwigFilter('filter', 'twig_array_filter', ['needs_environment' => true]), - new TwigFilter('map', 'twig_array_map', ['needs_environment' => true]), - new TwigFilter('reduce', 'twig_array_reduce', ['needs_environment' => true]), - - // string/array filters - new TwigFilter('reverse', 'twig_reverse_filter', ['needs_environment' => true]), - new TwigFilter('length', 'twig_length_filter', ['needs_environment' => true]), - new TwigFilter('slice', 'twig_slice', ['needs_environment' => true]), - new TwigFilter('first', 'twig_first', ['needs_environment' => true]), - new TwigFilter('last', 'twig_last', ['needs_environment' => true]), - - // iteration and runtime - new TwigFilter('default', '_twig_default_filter', ['node_class' => DefaultFilter::class]), - new TwigFilter('keys', 'twig_get_array_keys_filter'), - ]; - } - - public function getFunctions(): array - { - return [ - new TwigFunction('max', 'max'), - new TwigFunction('min', 'min'), - new TwigFunction('range', 'range'), - new TwigFunction('constant', 'twig_constant'), - new TwigFunction('cycle', 'twig_cycle'), - new TwigFunction('random', 'twig_random', ['needs_environment' => true]), - new TwigFunction('date', 'twig_date_converter', ['needs_environment' => true]), - new TwigFunction('include', 'twig_include', ['needs_environment' => true, 'needs_context' => true, 'is_safe' => ['all']]), - new TwigFunction('source', 'twig_source', ['needs_environment' => true, 'is_safe' => ['all']]), - ]; - } - - public function getTests(): array - { - return [ - new TwigTest('even', null, ['node_class' => EvenTest::class]), - new TwigTest('odd', null, ['node_class' => OddTest::class]), - new TwigTest('defined', null, ['node_class' => DefinedTest::class]), - new TwigTest('same as', null, ['node_class' => SameasTest::class, 'one_mandatory_argument' => true]), - new TwigTest('none', null, ['node_class' => NullTest::class]), - new TwigTest('null', null, ['node_class' => NullTest::class]), - new TwigTest('divisible by', null, ['node_class' => DivisiblebyTest::class, 'one_mandatory_argument' => true]), - new TwigTest('constant', null, ['node_class' => ConstantTest::class]), - new TwigTest('empty', 'twig_test_empty'), - new TwigTest('iterable', 'twig_test_iterable'), - ]; - } - - public function getNodeVisitors(): array - { - return [new MacroAutoImportNodeVisitor()]; - } - - public function getOperators(): array - { - return [ - [ - 'not' => ['precedence' => 50, 'class' => NotUnary::class], - '-' => ['precedence' => 500, 'class' => NegUnary::class], - '+' => ['precedence' => 500, 'class' => PosUnary::class], - ], - [ - 'or' => ['precedence' => 10, 'class' => OrBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - 'and' => ['precedence' => 15, 'class' => AndBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - 'b-or' => ['precedence' => 16, 'class' => BitwiseOrBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - 'b-xor' => ['precedence' => 17, 'class' => BitwiseXorBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - 'b-and' => ['precedence' => 18, 'class' => BitwiseAndBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - '==' => ['precedence' => 20, 'class' => EqualBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - '!=' => ['precedence' => 20, 'class' => NotEqualBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - '<=>' => ['precedence' => 20, 'class' => SpaceshipBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - '<' => ['precedence' => 20, 'class' => LessBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - '>' => ['precedence' => 20, 'class' => GreaterBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - '>=' => ['precedence' => 20, 'class' => GreaterEqualBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - '<=' => ['precedence' => 20, 'class' => LessEqualBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - 'not in' => ['precedence' => 20, 'class' => NotInBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - 'in' => ['precedence' => 20, 'class' => InBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - 'matches' => ['precedence' => 20, 'class' => MatchesBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - 'starts with' => ['precedence' => 20, 'class' => StartsWithBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - 'ends with' => ['precedence' => 20, 'class' => EndsWithBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - '..' => ['precedence' => 25, 'class' => RangeBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - '+' => ['precedence' => 30, 'class' => AddBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - '-' => ['precedence' => 30, 'class' => SubBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - '~' => ['precedence' => 40, 'class' => ConcatBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - '*' => ['precedence' => 60, 'class' => MulBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - '/' => ['precedence' => 60, 'class' => DivBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - '//' => ['precedence' => 60, 'class' => FloorDivBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - '%' => ['precedence' => 60, 'class' => ModBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - 'is' => ['precedence' => 100, 'associativity' => ExpressionParser::OPERATOR_LEFT], - 'is not' => ['precedence' => 100, 'associativity' => ExpressionParser::OPERATOR_LEFT], - '**' => ['precedence' => 200, 'class' => PowerBinary::class, 'associativity' => ExpressionParser::OPERATOR_RIGHT], - '??' => ['precedence' => 300, 'class' => NullCoalesceExpression::class, 'associativity' => ExpressionParser::OPERATOR_RIGHT], - ], - ]; - } -} -} - -namespace { - use Twig\Environment; - use Twig\Error\LoaderError; - use Twig\Error\RuntimeError; - use Twig\Extension\CoreExtension; - use Twig\Extension\SandboxExtension; - use Twig\Markup; - use Twig\Source; - use Twig\Template; - use Twig\TemplateWrapper; - -/** - * Cycles over a value. - * - * @param \ArrayAccess|array $values - * @param int $position The cycle position - * - * @return string The next value in the cycle - */ -function twig_cycle($values, $position) -{ - if (!\is_array($values) && !$values instanceof \ArrayAccess) { - return $values; - } - - return $values[$position % \count($values)]; -} - -/** - * Returns a random value depending on the supplied parameter type: - * - a random item from a \Traversable or array - * - a random character from a string - * - a random integer between 0 and the integer parameter. - * - * @param \Traversable|array|int|float|string $values The values to pick a random item from - * @param int|null $max Maximum value used when $values is an int - * - * @throws RuntimeError when $values is an empty array (does not apply to an empty string which is returned as is) - * - * @return mixed A random value from the given sequence - */ -function twig_random(Environment $env, $values = null, $max = null) -{ - if (null === $values) { - return null === $max ? mt_rand() : mt_rand(0, (int) $max); - } - - if (\is_int($values) || \is_float($values)) { - if (null === $max) { - if ($values < 0) { - $max = 0; - $min = $values; - } else { - $max = $values; - $min = 0; - } - } else { - $min = $values; - $max = $max; - } - - return mt_rand((int) $min, (int) $max); - } - - if (\is_string($values)) { - if ('' === $values) { - return ''; - } - - $charset = $env->getCharset(); - - if ('UTF-8' !== $charset) { - $values = twig_convert_encoding($values, 'UTF-8', $charset); - } - - // unicode version of str_split() - // split at all positions, but not after the start and not before the end - $values = preg_split('/(?<!^)(?!$)/u', $values); - - if ('UTF-8' !== $charset) { - foreach ($values as $i => $value) { - $values[$i] = twig_convert_encoding($value, $charset, 'UTF-8'); - } - } - } - - if (!twig_test_iterable($values)) { - return $values; - } - - $values = twig_to_array($values); - - if (0 === \count($values)) { - throw new RuntimeError('The random function cannot pick from an empty array.'); - } - - return $values[array_rand($values, 1)]; -} - -/** - * Converts a date to the given format. - * - * {{ post.published_at|date("m/d/Y") }} - * - * @param \DateTimeInterface|\DateInterval|string $date A date - * @param string|null $format The target format, null to use the default - * @param \DateTimeZone|string|false|null $timezone The target timezone, null to use the default, false to leave unchanged - * - * @return string The formatted date - */ -function twig_date_format_filter(Environment $env, $date, $format = null, $timezone = null) -{ - if (null === $format) { - $formats = $env->getExtension(CoreExtension::class)->getDateFormat(); - $format = $date instanceof \DateInterval ? $formats[1] : $formats[0]; - } - - if ($date instanceof \DateInterval) { - return $date->format($format); - } - - return twig_date_converter($env, $date, $timezone)->format($format); -} - -/** - * Returns a new date object modified. - * - * {{ post.published_at|date_modify("-1day")|date("m/d/Y") }} - * - * @param \DateTimeInterface|string $date A date - * @param string $modifier A modifier string - * - * @return \DateTimeInterface - */ -function twig_date_modify_filter(Environment $env, $date, $modifier) -{ - $date = twig_date_converter($env, $date, false); - - return $date->modify($modifier); -} - -/** - * Returns a formatted string. - * - * @param string|null $format - * @param ...$values - * - * @return string - */ -function twig_sprintf($format, ...$values) -{ - return sprintf($format ?? '', ...$values); -} - -/** - * Converts an input to a \DateTime instance. - * - * {% if date(user.created_at) < date('+2days') %} - * {# do something #} - * {% endif %} - * - * @param \DateTimeInterface|string|null $date A date or null to use the current time - * @param \DateTimeZone|string|false|null $timezone The target timezone, null to use the default, false to leave unchanged - * - * @return \DateTimeInterface - */ -function twig_date_converter(Environment $env, $date = null, $timezone = null) -{ - // determine the timezone - if (false !== $timezone) { - if (null === $timezone) { - $timezone = $env->getExtension(CoreExtension::class)->getTimezone(); - } elseif (!$timezone instanceof \DateTimeZone) { - $timezone = new \DateTimeZone($timezone); - } - } - - // immutable dates - if ($date instanceof \DateTimeImmutable) { - return false !== $timezone ? $date->setTimezone($timezone) : $date; - } - - if ($date instanceof \DateTimeInterface) { - $date = clone $date; - if (false !== $timezone) { - $date->setTimezone($timezone); - } - - return $date; - } - - if (null === $date || 'now' === $date) { - if (null === $date) { - $date = 'now'; - } - - return new \DateTime($date, false !== $timezone ? $timezone : $env->getExtension(CoreExtension::class)->getTimezone()); - } - - $asString = (string) $date; - if (ctype_digit($asString) || (!empty($asString) && '-' === $asString[0] && ctype_digit(substr($asString, 1)))) { - $date = new \DateTime('@'.$date); - } else { - $date = new \DateTime($date, $env->getExtension(CoreExtension::class)->getTimezone()); - } - - if (false !== $timezone) { - $date->setTimezone($timezone); - } - - return $date; -} - -/** - * Replaces strings within a string. - * - * @param string|null $str String to replace in - * @param array|\Traversable $from Replace values - * - * @return string - */ -function twig_replace_filter($str, $from) -{ - if (!twig_test_iterable($from)) { - throw new RuntimeError(sprintf('The "replace" filter expects an array or "Traversable" as replace values, got "%s".', \is_object($from) ? \get_class($from) : \gettype($from))); - } - - return strtr($str ?? '', twig_to_array($from)); -} - -/** - * Rounds a number. - * - * @param int|float|string|null $value The value to round - * @param int|float $precision The rounding precision - * @param string $method The method to use for rounding - * - * @return int|float The rounded number - */ -function twig_round($value, $precision = 0, $method = 'common') -{ - $value = (float) $value; - - if ('common' === $method) { - return round($value, $precision); - } - - if ('ceil' !== $method && 'floor' !== $method) { - throw new RuntimeError('The round filter only supports the "common", "ceil", and "floor" methods.'); - } - - return $method($value * 10 ** $precision) / 10 ** $precision; -} - -/** - * Number format filter. - * - * All of the formatting options can be left null, in that case the defaults will - * be used. Supplying any of the parameters will override the defaults set in the - * environment object. - * - * @param mixed $number A float/int/string of the number to format - * @param int $decimal the number of decimal points to display - * @param string $decimalPoint the character(s) to use for the decimal point - * @param string $thousandSep the character(s) to use for the thousands separator - * - * @return string The formatted number - */ -function twig_number_format_filter(Environment $env, $number, $decimal = null, $decimalPoint = null, $thousandSep = null) -{ - $defaults = $env->getExtension(CoreExtension::class)->getNumberFormat(); - if (null === $decimal) { - $decimal = $defaults[0]; - } - - if (null === $decimalPoint) { - $decimalPoint = $defaults[1]; - } - - if (null === $thousandSep) { - $thousandSep = $defaults[2]; - } - - return number_format((float) $number, $decimal, $decimalPoint, $thousandSep); -} - -/** - * URL encodes (RFC 3986) a string as a path segment or an array as a query string. - * - * @param string|array|null $url A URL or an array of query parameters - * - * @return string The URL encoded value - */ -function twig_urlencode_filter($url) -{ - if (\is_array($url)) { - return http_build_query($url, '', '&', \PHP_QUERY_RFC3986); - } - - return rawurlencode($url ?? ''); -} - -/** - * Merges an array with another one. - * - * {% set items = { 'apple': 'fruit', 'orange': 'fruit' } %} - * - * {% set items = items|merge({ 'peugeot': 'car' }) %} - * - * {# items now contains { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'car' } #} - * - * @param array|\Traversable $arr1 An array - * @param array|\Traversable $arr2 An array - * - * @return array The merged array - */ -function twig_array_merge($arr1, $arr2) -{ - if (!twig_test_iterable($arr1)) { - throw new RuntimeError(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as first argument.', \gettype($arr1))); - } - - if (!twig_test_iterable($arr2)) { - throw new RuntimeError(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as second argument.', \gettype($arr2))); - } - - return array_merge(twig_to_array($arr1), twig_to_array($arr2)); -} - -/** - * Slices a variable. - * - * @param mixed $item A variable - * @param int $start Start of the slice - * @param int $length Size of the slice - * @param bool $preserveKeys Whether to preserve key or not (when the input is an array) - * - * @return mixed The sliced variable - */ -function twig_slice(Environment $env, $item, $start, $length = null, $preserveKeys = false) -{ - if ($item instanceof \Traversable) { - while ($item instanceof \IteratorAggregate) { - $item = $item->getIterator(); - } - - if ($start >= 0 && $length >= 0 && $item instanceof \Iterator) { - try { - return iterator_to_array(new \LimitIterator($item, $start, null === $length ? -1 : $length), $preserveKeys); - } catch (\OutOfBoundsException $e) { - return []; - } - } - - $item = iterator_to_array($item, $preserveKeys); - } - - if (\is_array($item)) { - return \array_slice($item, $start, $length, $preserveKeys); - } - - return (string) mb_substr((string) $item, $start, $length, $env->getCharset()); -} - -/** - * Returns the first element of the item. - * - * @param mixed $item A variable - * - * @return mixed The first element of the item - */ -function twig_first(Environment $env, $item) -{ - $elements = twig_slice($env, $item, 0, 1, false); - - return \is_string($elements) ? $elements : current($elements); -} - -/** - * Returns the last element of the item. - * - * @param mixed $item A variable - * - * @return mixed The last element of the item - */ -function twig_last(Environment $env, $item) -{ - $elements = twig_slice($env, $item, -1, 1, false); - - return \is_string($elements) ? $elements : current($elements); -} - -/** - * Joins the values to a string. - * - * The separators between elements are empty strings per default, you can define them with the optional parameters. - * - * {{ [1, 2, 3]|join(', ', ' and ') }} - * {# returns 1, 2 and 3 #} - * - * {{ [1, 2, 3]|join('|') }} - * {# returns 1|2|3 #} - * - * {{ [1, 2, 3]|join }} - * {# returns 123 #} - * - * @param array $value An array - * @param string $glue The separator - * @param string|null $and The separator for the last pair - * - * @return string The concatenated string - */ -function twig_join_filter($value, $glue = '', $and = null) -{ - if (!twig_test_iterable($value)) { - $value = (array) $value; - } - - $value = twig_to_array($value, false); - - if (0 === \count($value)) { - return ''; - } - - if (null === $and || $and === $glue) { - return implode($glue, $value); - } - - if (1 === \count($value)) { - return $value[0]; - } - - return implode($glue, \array_slice($value, 0, -1)).$and.$value[\count($value) - 1]; -} - -/** - * Splits the string into an array. - * - * {{ "one,two,three"|split(',') }} - * {# returns [one, two, three] #} - * - * {{ "one,two,three,four,five"|split(',', 3) }} - * {# returns [one, two, "three,four,five"] #} - * - * {{ "123"|split('') }} - * {# returns [1, 2, 3] #} - * - * {{ "aabbcc"|split('', 2) }} - * {# returns [aa, bb, cc] #} - * - * @param string|null $value A string - * @param string $delimiter The delimiter - * @param int $limit The limit - * - * @return array The split string as an array - */ -function twig_split_filter(Environment $env, $value, $delimiter, $limit = null) -{ - $value = $value ?? ''; - - if (\strlen($delimiter) > 0) { - return null === $limit ? explode($delimiter, $value) : explode($delimiter, $value, $limit); - } - - if ($limit <= 1) { - return preg_split('/(?<!^)(?!$)/u', $value); - } - - $length = mb_strlen($value, $env->getCharset()); - if ($length < $limit) { - return [$value]; - } - - $r = []; - for ($i = 0; $i < $length; $i += $limit) { - $r[] = mb_substr($value, $i, $limit, $env->getCharset()); - } - - return $r; -} - -// The '_default' filter is used internally to avoid using the ternary operator -// which costs a lot for big contexts (before PHP 5.4). So, on average, -// a function call is cheaper. -/** - * @internal - */ -function _twig_default_filter($value, $default = '') -{ - if (twig_test_empty($value)) { - return $default; - } - - return $value; -} - -/** - * Returns the keys for the given array. - * - * It is useful when you want to iterate over the keys of an array: - * - * {% for key in array|keys %} - * {# ... #} - * {% endfor %} - * - * @param array $array An array - * - * @return array The keys - */ -function twig_get_array_keys_filter($array) -{ - if ($array instanceof \Traversable) { - while ($array instanceof \IteratorAggregate) { - $array = $array->getIterator(); - } - - $keys = []; - if ($array instanceof \Iterator) { - $array->rewind(); - while ($array->valid()) { - $keys[] = $array->key(); - $array->next(); - } - - return $keys; - } - - foreach ($array as $key => $item) { - $keys[] = $key; - } - - return $keys; - } - - if (!\is_array($array)) { - return []; - } - - return array_keys($array); -} - -/** - * Reverses a variable. - * - * @param array|\Traversable|string|null $item An array, a \Traversable instance, or a string - * @param bool $preserveKeys Whether to preserve key or not - * - * @return mixed The reversed input - */ -function twig_reverse_filter(Environment $env, $item, $preserveKeys = false) -{ - if ($item instanceof \Traversable) { - return array_reverse(iterator_to_array($item), $preserveKeys); - } - - if (\is_array($item)) { - return array_reverse($item, $preserveKeys); - } - - $string = (string) $item; - - $charset = $env->getCharset(); - - if ('UTF-8' !== $charset) { - $string = twig_convert_encoding($string, 'UTF-8', $charset); - } - - preg_match_all('/./us', $string, $matches); - - $string = implode('', array_reverse($matches[0])); - - if ('UTF-8' !== $charset) { - $string = twig_convert_encoding($string, $charset, 'UTF-8'); - } - - return $string; -} - -/** - * Sorts an array. - * - * @param array|\Traversable $array - * - * @return array - */ -function twig_sort_filter(Environment $env, $array, $arrow = null) -{ - if ($array instanceof \Traversable) { - $array = iterator_to_array($array); - } elseif (!\is_array($array)) { - throw new RuntimeError(sprintf('The sort filter only works with arrays or "Traversable", got "%s".', \gettype($array))); - } - - if (null !== $arrow) { - twig_check_arrow_in_sandbox($env, $arrow, 'sort', 'filter'); - - uasort($array, $arrow); - } else { - asort($array); - } - - return $array; -} - -/** - * @internal - */ -function twig_in_filter($value, $compare) -{ - if ($value instanceof Markup) { - $value = (string) $value; - } - if ($compare instanceof Markup) { - $compare = (string) $compare; - } - - if (\is_string($compare)) { - if (\is_string($value) || \is_int($value) || \is_float($value)) { - return '' === $value || false !== strpos($compare, (string) $value); - } - - return false; - } - - if (!is_iterable($compare)) { - return false; - } - - if (\is_object($value) || \is_resource($value)) { - if (!\is_array($compare)) { - foreach ($compare as $item) { - if ($item === $value) { - return true; - } - } - - return false; - } - - return \in_array($value, $compare, true); - } - - foreach ($compare as $item) { - if (0 === twig_compare($value, $item)) { - return true; - } - } - - return false; -} - -/** - * Compares two values using a more strict version of the PHP non-strict comparison operator. - * - * @see https://wiki.php.net/rfc/string_to_number_comparison - * @see https://wiki.php.net/rfc/trailing_whitespace_numerics - * - * @internal - */ -function twig_compare($a, $b) -{ - // int <=> string - if (\is_int($a) && \is_string($b)) { - $bTrim = trim($b, " \t\n\r\v\f"); - if (!is_numeric($bTrim)) { - return (string) $a <=> $b; - } - if ((int) $bTrim == $bTrim) { - return $a <=> (int) $bTrim; - } else { - return (float) $a <=> (float) $bTrim; - } - } - if (\is_string($a) && \is_int($b)) { - $aTrim = trim($a, " \t\n\r\v\f"); - if (!is_numeric($aTrim)) { - return $a <=> (string) $b; - } - if ((int) $aTrim == $aTrim) { - return (int) $aTrim <=> $b; - } else { - return (float) $aTrim <=> (float) $b; - } - } - - // float <=> string - if (\is_float($a) && \is_string($b)) { - if (is_nan($a)) { - return 1; - } - $bTrim = trim($b, " \t\n\r\v\f"); - if (!is_numeric($bTrim)) { - return (string) $a <=> $b; - } - - return $a <=> (float) $bTrim; - } - if (\is_string($a) && \is_float($b)) { - if (is_nan($b)) { - return 1; - } - $aTrim = trim($a, " \t\n\r\v\f"); - if (!is_numeric($aTrim)) { - return $a <=> (string) $b; - } - - return (float) $aTrim <=> $b; - } - - // fallback to <=> - return $a <=> $b; -} - -/** - * Returns a trimmed string. - * - * @param string|null $string - * @param string|null $characterMask - * @param string $side - * - * @return string - * - * @throws RuntimeError When an invalid trimming side is used (not a string or not 'left', 'right', or 'both') - */ -function twig_trim_filter($string, $characterMask = null, $side = 'both') -{ - if (null === $characterMask) { - $characterMask = " \t\n\r\0\x0B"; - } - - switch ($side) { - case 'both': - return trim($string ?? '', $characterMask); - case 'left': - return ltrim($string ?? '', $characterMask); - case 'right': - return rtrim($string ?? '', $characterMask); - default: - throw new RuntimeError('Trimming side must be "left", "right" or "both".'); - } -} - -/** - * Inserts HTML line breaks before all newlines in a string. - * - * @param string|null $string - * - * @return string - */ -function twig_nl2br($string) -{ - return nl2br($string ?? ''); -} - -/** - * Removes whitespaces between HTML tags. - * - * @param string|null $string - * - * @return string - */ -function twig_spaceless($content) -{ - return trim(preg_replace('/>\s+</', '><', $content ?? '')); -} - -/** - * @param string|null $string - * @param string $to - * @param string $from - * - * @return string - */ -function twig_convert_encoding($string, $to, $from) -{ - if (!\function_exists('iconv')) { - throw new RuntimeError('Unable to convert encoding: required function iconv() does not exist. You should install ext-iconv or symfony/polyfill-iconv.'); - } - - return iconv($from, $to, $string ?? ''); -} - -/** - * Returns the length of a variable. - * - * @param mixed $thing A variable - * - * @return int The length of the value - */ -function twig_length_filter(Environment $env, $thing) -{ - if (null === $thing) { - return 0; - } - - if (is_scalar($thing)) { - return mb_strlen($thing, $env->getCharset()); - } - - if ($thing instanceof \Countable || \is_array($thing) || $thing instanceof \SimpleXMLElement) { - return \count($thing); - } - - if ($thing instanceof \Traversable) { - return iterator_count($thing); - } - - if (method_exists($thing, '__toString') && !$thing instanceof \Countable) { - return mb_strlen((string) $thing, $env->getCharset()); - } - - return 1; -} - -/** - * Converts a string to uppercase. - * - * @param string|null $string A string - * - * @return string The uppercased string - */ -function twig_upper_filter(Environment $env, $string) -{ - return mb_strtoupper($string ?? '', $env->getCharset()); -} - -/** - * Converts a string to lowercase. - * - * @param string|null $string A string - * - * @return string The lowercased string - */ -function twig_lower_filter(Environment $env, $string) -{ - return mb_strtolower($string ?? '', $env->getCharset()); -} - -/** - * Strips HTML and PHP tags from a string. - * - * @param string|null $string - * @param string[]|string|null $string - * - * @return string - */ -function twig_striptags($string, $allowable_tags = null) -{ - return strip_tags($string ?? '', $allowable_tags); -} - -/** - * Returns a titlecased string. - * - * @param string|null $string A string - * - * @return string The titlecased string - */ -function twig_title_string_filter(Environment $env, $string) -{ - if (null !== $charset = $env->getCharset()) { - return mb_convert_case($string ?? '', \MB_CASE_TITLE, $charset); - } - - return ucwords(strtolower($string ?? '')); -} - -/** - * Returns a capitalized string. - * - * @param string|null $string A string - * - * @return string The capitalized string - */ -function twig_capitalize_string_filter(Environment $env, $string) -{ - $charset = $env->getCharset(); - - return mb_strtoupper(mb_substr($string ?? '', 0, 1, $charset), $charset).mb_strtolower(mb_substr($string ?? '', 1, null, $charset), $charset); -} - -/** - * @internal - */ -function twig_call_macro(Template $template, string $method, array $args, int $lineno, array $context, Source $source) -{ - if (!method_exists($template, $method)) { - $parent = $template; - while ($parent = $parent->getParent($context)) { - if (method_exists($parent, $method)) { - return $parent->$method(...$args); - } - } - - throw new RuntimeError(sprintf('Macro "%s" is not defined in template "%s".', substr($method, \strlen('macro_')), $template->getTemplateName()), $lineno, $source); - } - - return $template->$method(...$args); -} - -/** - * @internal - */ -function twig_ensure_traversable($seq) -{ - if ($seq instanceof \Traversable || \is_array($seq)) { - return $seq; - } - - return []; -} - -/** - * @internal - */ -function twig_to_array($seq, $preserveKeys = true) -{ - if ($seq instanceof \Traversable) { - return iterator_to_array($seq, $preserveKeys); - } - - if (!\is_array($seq)) { - return $seq; - } - - return $preserveKeys ? $seq : array_values($seq); -} - -/** - * Checks if a variable is empty. - * - * {# evaluates to true if the foo variable is null, false, or the empty string #} - * {% if foo is empty %} - * {# ... #} - * {% endif %} - * - * @param mixed $value A variable - * - * @return bool true if the value is empty, false otherwise - */ -function twig_test_empty($value) -{ - if ($value instanceof \Countable) { - return 0 === \count($value); - } - - if ($value instanceof \Traversable) { - return !iterator_count($value); - } - - if (\is_object($value) && method_exists($value, '__toString')) { - return '' === (string) $value; - } - - return '' === $value || false === $value || null === $value || [] === $value; -} - -/** - * Checks if a variable is traversable. - * - * {# evaluates to true if the foo variable is an array or a traversable object #} - * {% if foo is iterable %} - * {# ... #} - * {% endif %} - * - * @param mixed $value A variable - * - * @return bool true if the value is traversable - */ -function twig_test_iterable($value) -{ - return $value instanceof \Traversable || \is_array($value); -} - -/** - * Renders a template. - * - * @param array $context - * @param string|array $template The template to render or an array of templates to try consecutively - * @param array $variables The variables to pass to the template - * @param bool $withContext - * @param bool $ignoreMissing Whether to ignore missing templates or not - * @param bool $sandboxed Whether to sandbox the template or not - * - * @return string The rendered template - */ -function twig_include(Environment $env, $context, $template, $variables = [], $withContext = true, $ignoreMissing = false, $sandboxed = false) -{ - $alreadySandboxed = false; - $sandbox = null; - if ($withContext) { - $variables = array_merge($context, $variables); - } - - if ($isSandboxed = $sandboxed && $env->hasExtension(SandboxExtension::class)) { - $sandbox = $env->getExtension(SandboxExtension::class); - if (!$alreadySandboxed = $sandbox->isSandboxed()) { - $sandbox->enableSandbox(); - } - - foreach ((\is_array($template) ? $template : [$template]) as $name) { - // if a Template instance is passed, it might have been instantiated outside of a sandbox, check security - if ($name instanceof TemplateWrapper || $name instanceof Template) { - $name->unwrap()->checkSecurity(); - } - } - } - - try { - $loaded = null; - try { - $loaded = $env->resolveTemplate($template); - } catch (LoaderError $e) { - if (!$ignoreMissing) { - throw $e; - } - } - - return $loaded ? $loaded->render($variables) : ''; - } finally { - if ($isSandboxed && !$alreadySandboxed) { - $sandbox->disableSandbox(); - } - } -} - -/** - * Returns a template content without rendering it. - * - * @param string $name The template name - * @param bool $ignoreMissing Whether to ignore missing templates or not - * - * @return string The template source - */ -function twig_source(Environment $env, $name, $ignoreMissing = false) -{ - $loader = $env->getLoader(); - try { - return $loader->getSourceContext($name)->getCode(); - } catch (LoaderError $e) { - if (!$ignoreMissing) { - throw $e; - } - } -} - -/** - * Provides the ability to get constants from instances as well as class/global constants. - * - * @param string $constant The name of the constant - * @param object|null $object The object to get the constant from - * - * @return string - */ -function twig_constant($constant, $object = null) -{ - if (null !== $object) { - if ('class' === $constant) { - return \get_class($object); - } - - $constant = \get_class($object).'::'.$constant; - } - - return \constant($constant); -} - -/** - * Checks if a constant exists. - * - * @param string $constant The name of the constant - * @param object|null $object The object to get the constant from - * - * @return bool - */ -function twig_constant_is_defined($constant, $object = null) -{ - if (null !== $object) { - if ('class' === $constant) { - return true; - } - - $constant = \get_class($object).'::'.$constant; - } - - return \defined($constant); -} - -/** - * Batches item. - * - * @param array $items An array of items - * @param int $size The size of the batch - * @param mixed $fill A value used to fill missing items - * - * @return array - */ -function twig_array_batch($items, $size, $fill = null, $preserveKeys = true) -{ - if (!twig_test_iterable($items)) { - throw new RuntimeError(sprintf('The "batch" filter expects an array or "Traversable", got "%s".', \is_object($items) ? \get_class($items) : \gettype($items))); - } - - $size = ceil($size); - - $result = array_chunk(twig_to_array($items, $preserveKeys), $size, $preserveKeys); - - if (null !== $fill && $result) { - $last = \count($result) - 1; - if ($fillCount = $size - \count($result[$last])) { - for ($i = 0; $i < $fillCount; ++$i) { - $result[$last][] = $fill; - } - } - } - - return $result; -} - -/** - * Returns the attribute value for a given array/object. - * - * @param mixed $object The object or array from where to get the item - * @param mixed $item The item to get from the array or object - * @param array $arguments An array of arguments to pass if the item is an object method - * @param string $type The type of attribute (@see \Twig\Template constants) - * @param bool $isDefinedTest Whether this is only a defined check - * @param bool $ignoreStrictCheck Whether to ignore the strict attribute check or not - * @param int $lineno The template line where the attribute was called - * - * @return mixed The attribute value, or a Boolean when $isDefinedTest is true, or null when the attribute is not set and $ignoreStrictCheck is true - * - * @throws RuntimeError if the attribute does not exist and Twig is running in strict mode and $isDefinedTest is false - * - * @internal - */ -function twig_get_attribute(Environment $env, Source $source, $object, $item, array $arguments = [], $type = /* Template::ANY_CALL */ 'any', $isDefinedTest = false, $ignoreStrictCheck = false, $sandboxed = false, int $lineno = -1) -{ - // array - if (/* Template::METHOD_CALL */ 'method' !== $type) { - $arrayItem = \is_bool($item) || \is_float($item) ? (int) $item : $item; - - if (((\is_array($object) || $object instanceof \ArrayObject) && (isset($object[$arrayItem]) || \array_key_exists($arrayItem, (array) $object))) - || ($object instanceof ArrayAccess && isset($object[$arrayItem])) - ) { - if ($isDefinedTest) { - return true; - } - - return $object[$arrayItem]; - } - - if (/* Template::ARRAY_CALL */ 'array' === $type || !\is_object($object)) { - if ($isDefinedTest) { - return false; - } - - if ($ignoreStrictCheck || !$env->isStrictVariables()) { - return; - } - - if ($object instanceof ArrayAccess) { - $message = sprintf('Key "%s" in object with ArrayAccess of class "%s" does not exist.', $arrayItem, \get_class($object)); - } elseif (\is_object($object)) { - $message = sprintf('Impossible to access a key "%s" on an object of class "%s" that does not implement ArrayAccess interface.', $item, \get_class($object)); - } elseif (\is_array($object)) { - if (empty($object)) { - $message = sprintf('Key "%s" does not exist as the array is empty.', $arrayItem); - } else { - $message = sprintf('Key "%s" for array with keys "%s" does not exist.', $arrayItem, implode(', ', array_keys($object))); - } - } elseif (/* Template::ARRAY_CALL */ 'array' === $type) { - if (null === $object) { - $message = sprintf('Impossible to access a key ("%s") on a null variable.', $item); - } else { - $message = sprintf('Impossible to access a key ("%s") on a %s variable ("%s").', $item, \gettype($object), $object); - } - } elseif (null === $object) { - $message = sprintf('Impossible to access an attribute ("%s") on a null variable.', $item); - } else { - $message = sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s").', $item, \gettype($object), $object); - } - - throw new RuntimeError($message, $lineno, $source); - } - } - - if (!\is_object($object)) { - if ($isDefinedTest) { - return false; - } - - if ($ignoreStrictCheck || !$env->isStrictVariables()) { - return; - } - - if (null === $object) { - $message = sprintf('Impossible to invoke a method ("%s") on a null variable.', $item); - } elseif (\is_array($object)) { - $message = sprintf('Impossible to invoke a method ("%s") on an array.', $item); - } else { - $message = sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s").', $item, \gettype($object), $object); - } - - throw new RuntimeError($message, $lineno, $source); - } - - if ($object instanceof Template) { - throw new RuntimeError('Accessing \Twig\Template attributes is forbidden.', $lineno, $source); - } - - // object property - if (/* Template::METHOD_CALL */ 'method' !== $type) { - if (isset($object->$item) || \array_key_exists((string) $item, (array) $object)) { - if ($isDefinedTest) { - return true; - } - - if ($sandboxed) { - $env->getExtension(SandboxExtension::class)->checkPropertyAllowed($object, $item, $lineno, $source); - } - - return $object->$item; - } - } - - static $cache = []; - - $class = \get_class($object); - - // object method - // precedence: getXxx() > isXxx() > hasXxx() - if (!isset($cache[$class])) { - $methods = get_class_methods($object); - sort($methods); - $lcMethods = array_map(function ($value) { return strtr($value, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); }, $methods); - $classCache = []; - foreach ($methods as $i => $method) { - $classCache[$method] = $method; - $classCache[$lcName = $lcMethods[$i]] = $method; - - if ('g' === $lcName[0] && 0 === strpos($lcName, 'get')) { - $name = substr($method, 3); - $lcName = substr($lcName, 3); - } elseif ('i' === $lcName[0] && 0 === strpos($lcName, 'is')) { - $name = substr($method, 2); - $lcName = substr($lcName, 2); - } elseif ('h' === $lcName[0] && 0 === strpos($lcName, 'has')) { - $name = substr($method, 3); - $lcName = substr($lcName, 3); - if (\in_array('is'.$lcName, $lcMethods)) { - continue; - } - } else { - continue; - } - - // skip get() and is() methods (in which case, $name is empty) - if ($name) { - if (!isset($classCache[$name])) { - $classCache[$name] = $method; - } - - if (!isset($classCache[$lcName])) { - $classCache[$lcName] = $method; - } - } - } - $cache[$class] = $classCache; - } - - $call = false; - if (isset($cache[$class][$item])) { - $method = $cache[$class][$item]; - } elseif (isset($cache[$class][$lcItem = strtr($item, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')])) { - $method = $cache[$class][$lcItem]; - } elseif (isset($cache[$class]['__call'])) { - $method = $item; - $call = true; - } else { - if ($isDefinedTest) { - return false; - } - - if ($ignoreStrictCheck || !$env->isStrictVariables()) { - return; - } - - throw new RuntimeError(sprintf('Neither the property "%1$s" nor one of the methods "%1$s()", "get%1$s()"/"is%1$s()"/"has%1$s()" or "__call()" exist and have public access in class "%2$s".', $item, $class), $lineno, $source); - } - - if ($isDefinedTest) { - return true; - } - - if ($sandboxed) { - $env->getExtension(SandboxExtension::class)->checkMethodAllowed($object, $method, $lineno, $source); - } - - // Some objects throw exceptions when they have __call, and the method we try - // to call is not supported. If ignoreStrictCheck is true, we should return null. - try { - $ret = $object->$method(...$arguments); - } catch (\BadMethodCallException $e) { - if ($call && ($ignoreStrictCheck || !$env->isStrictVariables())) { - return; - } - throw $e; - } - - return $ret; -} - -/** - * Returns the values from a single column in the input array. - * - * <pre> - * {% set items = [{ 'fruit' : 'apple'}, {'fruit' : 'orange' }] %} - * - * {% set fruits = items|column('fruit') %} - * - * {# fruits now contains ['apple', 'orange'] #} - * </pre> - * - * @param array|Traversable $array An array - * @param mixed $name The column name - * @param mixed $index The column to use as the index/keys for the returned array - * - * @return array The array of values - */ -function twig_array_column($array, $name, $index = null): array -{ - if ($array instanceof Traversable) { - $array = iterator_to_array($array); - } elseif (!\is_array($array)) { - throw new RuntimeError(sprintf('The column filter only works with arrays or "Traversable", got "%s" as first argument.', \gettype($array))); - } - - return array_column($array, $name, $index); -} - -function twig_array_filter(Environment $env, $array, $arrow) -{ - if (!twig_test_iterable($array)) { - throw new RuntimeError(sprintf('The "filter" filter expects an array or "Traversable", got "%s".', \is_object($array) ? \get_class($array) : \gettype($array))); - } - - twig_check_arrow_in_sandbox($env, $arrow, 'filter', 'filter'); - - if (\is_array($array)) { - return array_filter($array, $arrow, \ARRAY_FILTER_USE_BOTH); - } - - // the IteratorIterator wrapping is needed as some internal PHP classes are \Traversable but do not implement \Iterator - return new \CallbackFilterIterator(new \IteratorIterator($array), $arrow); -} - -function twig_array_map(Environment $env, $array, $arrow) -{ - twig_check_arrow_in_sandbox($env, $arrow, 'map', 'filter'); - - $r = []; - foreach ($array as $k => $v) { - $r[$k] = $arrow($v, $k); - } - - return $r; -} - -function twig_array_reduce(Environment $env, $array, $arrow, $initial = null) -{ - twig_check_arrow_in_sandbox($env, $arrow, 'reduce', 'filter'); - - if (!\is_array($array)) { - if (!$array instanceof \Traversable) { - throw new RuntimeError(sprintf('The "reduce" filter only works with arrays or "Traversable", got "%s" as first argument.', \gettype($array))); - } - - $array = iterator_to_array($array); - } - - return array_reduce($array, $arrow, $initial); -} - -function twig_check_arrow_in_sandbox(Environment $env, $arrow, $thing, $type) -{ - if (!$arrow instanceof Closure && $env->hasExtension('\Twig\Extension\SandboxExtension') && $env->getExtension('\Twig\Extension\SandboxExtension')->isSandboxed()) { - throw new RuntimeError(sprintf('The callable passed to the "%s" %s must be a Closure in sandbox mode.', $thing, $type)); - } -} -} diff --git a/lib/twig/twig/src/Extension/DebugExtension.php b/lib/twig/twig/src/Extension/DebugExtension.php deleted file mode 100644 index bfb23d7bd..000000000 --- a/lib/twig/twig/src/Extension/DebugExtension.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Extension { -use Twig\TwigFunction; - -final class DebugExtension extends AbstractExtension -{ - public function getFunctions(): array - { - // dump is safe if var_dump is overridden by xdebug - $isDumpOutputHtmlSafe = \extension_loaded('xdebug') - // false means that it was not set (and the default is on) or it explicitly enabled - && (false === ini_get('xdebug.overload_var_dump') || ini_get('xdebug.overload_var_dump')) - // false means that it was not set (and the default is on) or it explicitly enabled - // xdebug.overload_var_dump produces HTML only when html_errors is also enabled - && (false === ini_get('html_errors') || ini_get('html_errors')) - || 'cli' === \PHP_SAPI - ; - - return [ - new TwigFunction('dump', 'twig_var_dump', ['is_safe' => $isDumpOutputHtmlSafe ? ['html'] : [], 'needs_context' => true, 'needs_environment' => true, 'is_variadic' => true]), - ]; - } -} -} - -namespace { -use Twig\Environment; -use Twig\Template; -use Twig\TemplateWrapper; - -function twig_var_dump(Environment $env, $context, ...$vars) -{ - if (!$env->isDebug()) { - return; - } - - ob_start(); - - if (!$vars) { - $vars = []; - foreach ($context as $key => $value) { - if (!$value instanceof Template && !$value instanceof TemplateWrapper) { - $vars[$key] = $value; - } - } - - var_dump($vars); - } else { - var_dump(...$vars); - } - - return ob_get_clean(); -} -} diff --git a/lib/twig/twig/src/Extension/EscaperExtension.php b/lib/twig/twig/src/Extension/EscaperExtension.php deleted file mode 100644 index 9d2251dc6..000000000 --- a/lib/twig/twig/src/Extension/EscaperExtension.php +++ /dev/null @@ -1,416 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Extension { -use Twig\FileExtensionEscapingStrategy; -use Twig\NodeVisitor\EscaperNodeVisitor; -use Twig\TokenParser\AutoEscapeTokenParser; -use Twig\TwigFilter; - -final class EscaperExtension extends AbstractExtension -{ - private $defaultStrategy; - private $escapers = []; - - /** @internal */ - public $safeClasses = []; - - /** @internal */ - public $safeLookup = []; - - /** - * @param string|false|callable $defaultStrategy An escaping strategy - * - * @see setDefaultStrategy() - */ - public function __construct($defaultStrategy = 'html') - { - $this->setDefaultStrategy($defaultStrategy); - } - - public function getTokenParsers(): array - { - return [new AutoEscapeTokenParser()]; - } - - public function getNodeVisitors(): array - { - return [new EscaperNodeVisitor()]; - } - - public function getFilters(): array - { - return [ - new TwigFilter('escape', 'twig_escape_filter', ['needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe']), - new TwigFilter('e', 'twig_escape_filter', ['needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe']), - new TwigFilter('raw', 'twig_raw_filter', ['is_safe' => ['all']]), - ]; - } - - /** - * Sets the default strategy to use when not defined by the user. - * - * The strategy can be a valid PHP callback that takes the template - * name as an argument and returns the strategy to use. - * - * @param string|false|callable $defaultStrategy An escaping strategy - */ - public function setDefaultStrategy($defaultStrategy): void - { - if ('name' === $defaultStrategy) { - $defaultStrategy = [FileExtensionEscapingStrategy::class, 'guess']; - } - - $this->defaultStrategy = $defaultStrategy; - } - - /** - * Gets the default strategy to use when not defined by the user. - * - * @param string $name The template name - * - * @return string|false The default strategy to use for the template - */ - public function getDefaultStrategy(string $name) - { - // disable string callables to avoid calling a function named html or js, - // or any other upcoming escaping strategy - if (!\is_string($this->defaultStrategy) && false !== $this->defaultStrategy) { - return \call_user_func($this->defaultStrategy, $name); - } - - return $this->defaultStrategy; - } - - /** - * Defines a new escaper to be used via the escape filter. - * - * @param string $strategy The strategy name that should be used as a strategy in the escape call - * @param callable $callable A valid PHP callable - */ - public function setEscaper($strategy, callable $callable) - { - $this->escapers[$strategy] = $callable; - } - - /** - * Gets all defined escapers. - * - * @return callable[] An array of escapers - */ - public function getEscapers() - { - return $this->escapers; - } - - public function setSafeClasses(array $safeClasses = []) - { - $this->safeClasses = []; - $this->safeLookup = []; - foreach ($safeClasses as $class => $strategies) { - $this->addSafeClass($class, $strategies); - } - } - - public function addSafeClass(string $class, array $strategies) - { - $class = ltrim($class, '\\'); - if (!isset($this->safeClasses[$class])) { - $this->safeClasses[$class] = []; - } - $this->safeClasses[$class] = array_merge($this->safeClasses[$class], $strategies); - - foreach ($strategies as $strategy) { - $this->safeLookup[$strategy][$class] = true; - } - } -} -} - -namespace { -use Twig\Environment; -use Twig\Error\RuntimeError; -use Twig\Extension\EscaperExtension; -use Twig\Markup; -use Twig\Node\Expression\ConstantExpression; -use Twig\Node\Node; - -/** - * Marks a variable as being safe. - * - * @param string $string A PHP variable - */ -function twig_raw_filter($string) -{ - return $string; -} - -/** - * Escapes a string. - * - * @param mixed $string The value to be escaped - * @param string $strategy The escaping strategy - * @param string $charset The charset - * @param bool $autoescape Whether the function is called by the auto-escaping feature (true) or by the developer (false) - * - * @return string - */ -function twig_escape_filter(Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false) -{ - if ($autoescape && $string instanceof Markup) { - return $string; - } - - if (!\is_string($string)) { - if (\is_object($string) && method_exists($string, '__toString')) { - if ($autoescape) { - $c = \get_class($string); - $ext = $env->getExtension(EscaperExtension::class); - if (!isset($ext->safeClasses[$c])) { - $ext->safeClasses[$c] = []; - foreach (class_parents($string) + class_implements($string) as $class) { - if (isset($ext->safeClasses[$class])) { - $ext->safeClasses[$c] = array_unique(array_merge($ext->safeClasses[$c], $ext->safeClasses[$class])); - foreach ($ext->safeClasses[$class] as $s) { - $ext->safeLookup[$s][$c] = true; - } - } - } - } - if (isset($ext->safeLookup[$strategy][$c]) || isset($ext->safeLookup['all'][$c])) { - return (string) $string; - } - } - - $string = (string) $string; - } elseif (\in_array($strategy, ['html', 'js', 'css', 'html_attr', 'url'])) { - return $string; - } - } - - if ('' === $string) { - return ''; - } - - if (null === $charset) { - $charset = $env->getCharset(); - } - - switch ($strategy) { - case 'html': - // see https://www.php.net/htmlspecialchars - - // Using a static variable to avoid initializing the array - // each time the function is called. Moving the declaration on the - // top of the function slow downs other escaping strategies. - static $htmlspecialcharsCharsets = [ - 'ISO-8859-1' => true, 'ISO8859-1' => true, - 'ISO-8859-15' => true, 'ISO8859-15' => true, - 'utf-8' => true, 'UTF-8' => true, - 'CP866' => true, 'IBM866' => true, '866' => true, - 'CP1251' => true, 'WINDOWS-1251' => true, 'WIN-1251' => true, - '1251' => true, - 'CP1252' => true, 'WINDOWS-1252' => true, '1252' => true, - 'KOI8-R' => true, 'KOI8-RU' => true, 'KOI8R' => true, - 'BIG5' => true, '950' => true, - 'GB2312' => true, '936' => true, - 'BIG5-HKSCS' => true, - 'SHIFT_JIS' => true, 'SJIS' => true, '932' => true, - 'EUC-JP' => true, 'EUCJP' => true, - 'ISO8859-5' => true, 'ISO-8859-5' => true, 'MACROMAN' => true, - ]; - - if (isset($htmlspecialcharsCharsets[$charset])) { - return htmlspecialchars($string, \ENT_QUOTES | \ENT_SUBSTITUTE, $charset); - } - - if (isset($htmlspecialcharsCharsets[strtoupper($charset)])) { - // cache the lowercase variant for future iterations - $htmlspecialcharsCharsets[$charset] = true; - - return htmlspecialchars($string, \ENT_QUOTES | \ENT_SUBSTITUTE, $charset); - } - - $string = twig_convert_encoding($string, 'UTF-8', $charset); - $string = htmlspecialchars($string, \ENT_QUOTES | \ENT_SUBSTITUTE, 'UTF-8'); - - return iconv('UTF-8', $charset, $string); - - case 'js': - // escape all non-alphanumeric characters - // into their \x or \uHHHH representations - if ('UTF-8' !== $charset) { - $string = twig_convert_encoding($string, 'UTF-8', $charset); - } - - if (!preg_match('//u', $string)) { - throw new RuntimeError('The string to escape is not a valid UTF-8 string.'); - } - - $string = preg_replace_callback('#[^a-zA-Z0-9,\._]#Su', function ($matches) { - $char = $matches[0]; - - /* - * A few characters have short escape sequences in JSON and JavaScript. - * Escape sequences supported only by JavaScript, not JSON, are omitted. - * \" is also supported but omitted, because the resulting string is not HTML safe. - */ - static $shortMap = [ - '\\' => '\\\\', - '/' => '\\/', - "\x08" => '\b', - "\x0C" => '\f', - "\x0A" => '\n', - "\x0D" => '\r', - "\x09" => '\t', - ]; - - if (isset($shortMap[$char])) { - return $shortMap[$char]; - } - - $codepoint = mb_ord($char, 'UTF-8'); - if (0x10000 > $codepoint) { - return sprintf('\u%04X', $codepoint); - } - - // Split characters outside the BMP into surrogate pairs - // https://tools.ietf.org/html/rfc2781.html#section-2.1 - $u = $codepoint - 0x10000; - $high = 0xD800 | ($u >> 10); - $low = 0xDC00 | ($u & 0x3FF); - - return sprintf('\u%04X\u%04X', $high, $low); - }, $string); - - if ('UTF-8' !== $charset) { - $string = iconv('UTF-8', $charset, $string); - } - - return $string; - - case 'css': - if ('UTF-8' !== $charset) { - $string = twig_convert_encoding($string, 'UTF-8', $charset); - } - - if (!preg_match('//u', $string)) { - throw new RuntimeError('The string to escape is not a valid UTF-8 string.'); - } - - $string = preg_replace_callback('#[^a-zA-Z0-9]#Su', function ($matches) { - $char = $matches[0]; - - return sprintf('\\%X ', 1 === \strlen($char) ? \ord($char) : mb_ord($char, 'UTF-8')); - }, $string); - - if ('UTF-8' !== $charset) { - $string = iconv('UTF-8', $charset, $string); - } - - return $string; - - case 'html_attr': - if ('UTF-8' !== $charset) { - $string = twig_convert_encoding($string, 'UTF-8', $charset); - } - - if (!preg_match('//u', $string)) { - throw new RuntimeError('The string to escape is not a valid UTF-8 string.'); - } - - $string = preg_replace_callback('#[^a-zA-Z0-9,\.\-_]#Su', function ($matches) { - /** - * This function is adapted from code coming from Zend Framework. - * - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (https://www.zend.com) - * @license https://framework.zend.com/license/new-bsd New BSD License - */ - $chr = $matches[0]; - $ord = \ord($chr); - - /* - * The following replaces characters undefined in HTML with the - * hex entity for the Unicode replacement character. - */ - if (($ord <= 0x1f && "\t" != $chr && "\n" != $chr && "\r" != $chr) || ($ord >= 0x7f && $ord <= 0x9f)) { - return '&#xFFFD;'; - } - - /* - * Check if the current character to escape has a name entity we should - * replace it with while grabbing the hex value of the character. - */ - if (1 === \strlen($chr)) { - /* - * While HTML supports far more named entities, the lowest common denominator - * has become HTML5's XML Serialisation which is restricted to the those named - * entities that XML supports. Using HTML entities would result in this error: - * XML Parsing Error: undefined entity - */ - static $entityMap = [ - 34 => '&quot;', /* quotation mark */ - 38 => '&amp;', /* ampersand */ - 60 => '&lt;', /* less-than sign */ - 62 => '&gt;', /* greater-than sign */ - ]; - - if (isset($entityMap[$ord])) { - return $entityMap[$ord]; - } - - return sprintf('&#x%02X;', $ord); - } - - /* - * Per OWASP recommendations, we'll use hex entities for any other - * characters where a named entity does not exist. - */ - return sprintf('&#x%04X;', mb_ord($chr, 'UTF-8')); - }, $string); - - if ('UTF-8' !== $charset) { - $string = iconv('UTF-8', $charset, $string); - } - - return $string; - - case 'url': - return rawurlencode($string); - - default: - $escapers = $env->getExtension(EscaperExtension::class)->getEscapers(); - if (array_key_exists($strategy, $escapers)) { - return $escapers[$strategy]($env, $string, $charset); - } - - $validStrategies = implode(', ', array_merge(['html', 'js', 'url', 'css', 'html_attr'], array_keys($escapers))); - - throw new RuntimeError(sprintf('Invalid escaping strategy "%s" (valid ones: %s).', $strategy, $validStrategies)); - } -} - -/** - * @internal - */ -function twig_escape_filter_is_safe(Node $filterArgs) -{ - foreach ($filterArgs as $arg) { - if ($arg instanceof ConstantExpression) { - return [$arg->getAttribute('value')]; - } - - return []; - } - - return ['html']; -} -} diff --git a/lib/twig/twig/src/Extension/ExtensionInterface.php b/lib/twig/twig/src/Extension/ExtensionInterface.php deleted file mode 100644 index 75fa237e1..000000000 --- a/lib/twig/twig/src/Extension/ExtensionInterface.php +++ /dev/null @@ -1,68 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Extension; - -use Twig\NodeVisitor\NodeVisitorInterface; -use Twig\TokenParser\TokenParserInterface; -use Twig\TwigFilter; -use Twig\TwigFunction; -use Twig\TwigTest; - -/** - * Interface implemented by extension classes. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface ExtensionInterface -{ - /** - * Returns the token parser instances to add to the existing list. - * - * @return TokenParserInterface[] - */ - public function getTokenParsers(); - - /** - * Returns the node visitor instances to add to the existing list. - * - * @return NodeVisitorInterface[] - */ - public function getNodeVisitors(); - - /** - * Returns a list of filters to add to the existing list. - * - * @return TwigFilter[] - */ - public function getFilters(); - - /** - * Returns a list of tests to add to the existing list. - * - * @return TwigTest[] - */ - public function getTests(); - - /** - * Returns a list of functions to add to the existing list. - * - * @return TwigFunction[] - */ - public function getFunctions(); - - /** - * Returns a list of operators to add to the existing list. - * - * @return array<array> First array of unary operators, second array of binary operators - */ - public function getOperators(); -} diff --git a/lib/twig/twig/src/Extension/GlobalsInterface.php b/lib/twig/twig/src/Extension/GlobalsInterface.php deleted file mode 100644 index ec0c68292..000000000 --- a/lib/twig/twig/src/Extension/GlobalsInterface.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Extension; - -/** - * Enables usage of the deprecated Twig\Extension\AbstractExtension::getGlobals() method. - * - * Explicitly implement this interface if you really need to implement the - * deprecated getGlobals() method in your extensions. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface GlobalsInterface -{ - public function getGlobals(): array; -} diff --git a/lib/twig/twig/src/Extension/OptimizerExtension.php b/lib/twig/twig/src/Extension/OptimizerExtension.php deleted file mode 100644 index 965bfdb04..000000000 --- a/lib/twig/twig/src/Extension/OptimizerExtension.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Extension; - -use Twig\NodeVisitor\OptimizerNodeVisitor; - -final class OptimizerExtension extends AbstractExtension -{ - private $optimizers; - - public function __construct(int $optimizers = -1) - { - $this->optimizers = $optimizers; - } - - public function getNodeVisitors(): array - { - return [new OptimizerNodeVisitor($this->optimizers)]; - } -} diff --git a/lib/twig/twig/src/Extension/ProfilerExtension.php b/lib/twig/twig/src/Extension/ProfilerExtension.php deleted file mode 100644 index 43e4a449e..000000000 --- a/lib/twig/twig/src/Extension/ProfilerExtension.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Extension; - -use Twig\Profiler\NodeVisitor\ProfilerNodeVisitor; -use Twig\Profiler\Profile; - -class ProfilerExtension extends AbstractExtension -{ - private $actives = []; - - public function __construct(Profile $profile) - { - $this->actives[] = $profile; - } - - /** - * @return void - */ - public function enter(Profile $profile) - { - $this->actives[0]->addProfile($profile); - array_unshift($this->actives, $profile); - } - - /** - * @return void - */ - public function leave(Profile $profile) - { - $profile->leave(); - array_shift($this->actives); - - if (1 === \count($this->actives)) { - $this->actives[0]->leave(); - } - } - - public function getNodeVisitors(): array - { - return [new ProfilerNodeVisitor(static::class)]; - } -} diff --git a/lib/twig/twig/src/Extension/RuntimeExtensionInterface.php b/lib/twig/twig/src/Extension/RuntimeExtensionInterface.php deleted file mode 100644 index 63bc3b1ab..000000000 --- a/lib/twig/twig/src/Extension/RuntimeExtensionInterface.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Extension; - -/** - * @author Grégoire Pineau <lyrixx@lyrixx.info> - */ -interface RuntimeExtensionInterface -{ -} diff --git a/lib/twig/twig/src/Extension/SandboxExtension.php b/lib/twig/twig/src/Extension/SandboxExtension.php deleted file mode 100644 index c861159b6..000000000 --- a/lib/twig/twig/src/Extension/SandboxExtension.php +++ /dev/null @@ -1,123 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Extension; - -use Twig\NodeVisitor\SandboxNodeVisitor; -use Twig\Sandbox\SecurityNotAllowedMethodError; -use Twig\Sandbox\SecurityNotAllowedPropertyError; -use Twig\Sandbox\SecurityPolicyInterface; -use Twig\Source; -use Twig\TokenParser\SandboxTokenParser; - -final class SandboxExtension extends AbstractExtension -{ - private $sandboxedGlobally; - private $sandboxed; - private $policy; - - public function __construct(SecurityPolicyInterface $policy, $sandboxed = false) - { - $this->policy = $policy; - $this->sandboxedGlobally = $sandboxed; - } - - public function getTokenParsers(): array - { - return [new SandboxTokenParser()]; - } - - public function getNodeVisitors(): array - { - return [new SandboxNodeVisitor()]; - } - - public function enableSandbox(): void - { - $this->sandboxed = true; - } - - public function disableSandbox(): void - { - $this->sandboxed = false; - } - - public function isSandboxed(): bool - { - return $this->sandboxedGlobally || $this->sandboxed; - } - - public function isSandboxedGlobally(): bool - { - return $this->sandboxedGlobally; - } - - public function setSecurityPolicy(SecurityPolicyInterface $policy) - { - $this->policy = $policy; - } - - public function getSecurityPolicy(): SecurityPolicyInterface - { - return $this->policy; - } - - public function checkSecurity($tags, $filters, $functions): void - { - if ($this->isSandboxed()) { - $this->policy->checkSecurity($tags, $filters, $functions); - } - } - - public function checkMethodAllowed($obj, $method, int $lineno = -1, Source $source = null): void - { - if ($this->isSandboxed()) { - try { - $this->policy->checkMethodAllowed($obj, $method); - } catch (SecurityNotAllowedMethodError $e) { - $e->setSourceContext($source); - $e->setTemplateLine($lineno); - - throw $e; - } - } - } - - public function checkPropertyAllowed($obj, $property, int $lineno = -1, Source $source = null): void - { - if ($this->isSandboxed()) { - try { - $this->policy->checkPropertyAllowed($obj, $property); - } catch (SecurityNotAllowedPropertyError $e) { - $e->setSourceContext($source); - $e->setTemplateLine($lineno); - - throw $e; - } - } - } - - public function ensureToStringAllowed($obj, int $lineno = -1, Source $source = null) - { - if ($this->isSandboxed() && \is_object($obj) && method_exists($obj, '__toString')) { - try { - $this->policy->checkMethodAllowed($obj, '__toString'); - } catch (SecurityNotAllowedMethodError $e) { - $e->setSourceContext($source); - $e->setTemplateLine($lineno); - - throw $e; - } - } - - return $obj; - } -} diff --git a/lib/twig/twig/src/Extension/StagingExtension.php b/lib/twig/twig/src/Extension/StagingExtension.php deleted file mode 100644 index 0ea47f90c..000000000 --- a/lib/twig/twig/src/Extension/StagingExtension.php +++ /dev/null @@ -1,100 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Extension; - -use Twig\NodeVisitor\NodeVisitorInterface; -use Twig\TokenParser\TokenParserInterface; -use Twig\TwigFilter; -use Twig\TwigFunction; -use Twig\TwigTest; - -/** - * Used by \Twig\Environment as a staging area. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @internal - */ -final class StagingExtension extends AbstractExtension -{ - private $functions = []; - private $filters = []; - private $visitors = []; - private $tokenParsers = []; - private $tests = []; - - public function addFunction(TwigFunction $function): void - { - if (isset($this->functions[$function->getName()])) { - throw new \LogicException(sprintf('Function "%s" is already registered.', $function->getName())); - } - - $this->functions[$function->getName()] = $function; - } - - public function getFunctions(): array - { - return $this->functions; - } - - public function addFilter(TwigFilter $filter): void - { - if (isset($this->filters[$filter->getName()])) { - throw new \LogicException(sprintf('Filter "%s" is already registered.', $filter->getName())); - } - - $this->filters[$filter->getName()] = $filter; - } - - public function getFilters(): array - { - return $this->filters; - } - - public function addNodeVisitor(NodeVisitorInterface $visitor): void - { - $this->visitors[] = $visitor; - } - - public function getNodeVisitors(): array - { - return $this->visitors; - } - - public function addTokenParser(TokenParserInterface $parser): void - { - if (isset($this->tokenParsers[$parser->getTag()])) { - throw new \LogicException(sprintf('Tag "%s" is already registered.', $parser->getTag())); - } - - $this->tokenParsers[$parser->getTag()] = $parser; - } - - public function getTokenParsers(): array - { - return $this->tokenParsers; - } - - public function addTest(TwigTest $test): void - { - if (isset($this->tests[$test->getName()])) { - throw new \LogicException(sprintf('Test "%s" is already registered.', $test->getName())); - } - - $this->tests[$test->getName()] = $test; - } - - public function getTests(): array - { - return $this->tests; - } -} diff --git a/lib/twig/twig/src/Extension/StringLoaderExtension.php b/lib/twig/twig/src/Extension/StringLoaderExtension.php deleted file mode 100644 index 7b4514710..000000000 --- a/lib/twig/twig/src/Extension/StringLoaderExtension.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Extension { -use Twig\TwigFunction; - -final class StringLoaderExtension extends AbstractExtension -{ - public function getFunctions(): array - { - return [ - new TwigFunction('template_from_string', 'twig_template_from_string', ['needs_environment' => true]), - ]; - } -} -} - -namespace { -use Twig\Environment; -use Twig\TemplateWrapper; - -/** - * Loads a template from a string. - * - * {{ include(template_from_string("Hello {{ name }}")) }} - * - * @param string $template A template as a string or object implementing __toString() - * @param string $name An optional name of the template to be used in error messages - */ -function twig_template_from_string(Environment $env, $template, string $name = null): TemplateWrapper -{ - return $env->createTemplate((string) $template, $name); -} -} diff --git a/lib/twig/twig/src/ExtensionSet.php b/lib/twig/twig/src/ExtensionSet.php deleted file mode 100644 index 36e5bbc59..000000000 --- a/lib/twig/twig/src/ExtensionSet.php +++ /dev/null @@ -1,463 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig; - -use Twig\Error\RuntimeError; -use Twig\Extension\ExtensionInterface; -use Twig\Extension\GlobalsInterface; -use Twig\Extension\StagingExtension; -use Twig\NodeVisitor\NodeVisitorInterface; -use Twig\TokenParser\TokenParserInterface; - -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @internal - */ -final class ExtensionSet -{ - private $extensions; - private $initialized = false; - private $runtimeInitialized = false; - private $staging; - private $parsers; - private $visitors; - private $filters; - private $tests; - private $functions; - private $unaryOperators; - private $binaryOperators; - private $globals; - private $functionCallbacks = []; - private $filterCallbacks = []; - private $parserCallbacks = []; - private $lastModified = 0; - - public function __construct() - { - $this->staging = new StagingExtension(); - } - - public function initRuntime() - { - $this->runtimeInitialized = true; - } - - public function hasExtension(string $class): bool - { - return isset($this->extensions[ltrim($class, '\\')]); - } - - public function getExtension(string $class): ExtensionInterface - { - $class = ltrim($class, '\\'); - - if (!isset($this->extensions[$class])) { - throw new RuntimeError(sprintf('The "%s" extension is not enabled.', $class)); - } - - return $this->extensions[$class]; - } - - /** - * @param ExtensionInterface[] $extensions - */ - public function setExtensions(array $extensions): void - { - foreach ($extensions as $extension) { - $this->addExtension($extension); - } - } - - /** - * @return ExtensionInterface[] - */ - public function getExtensions(): array - { - return $this->extensions; - } - - public function getSignature(): string - { - return json_encode(array_keys($this->extensions)); - } - - public function isInitialized(): bool - { - return $this->initialized || $this->runtimeInitialized; - } - - public function getLastModified(): int - { - if (0 !== $this->lastModified) { - return $this->lastModified; - } - - foreach ($this->extensions as $extension) { - $r = new \ReflectionObject($extension); - if (is_file($r->getFileName()) && ($extensionTime = filemtime($r->getFileName())) > $this->lastModified) { - $this->lastModified = $extensionTime; - } - } - - return $this->lastModified; - } - - public function addExtension(ExtensionInterface $extension): void - { - $class = \get_class($extension); - - if ($this->initialized) { - throw new \LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.', $class)); - } - - if (isset($this->extensions[$class])) { - throw new \LogicException(sprintf('Unable to register extension "%s" as it is already registered.', $class)); - } - - $this->extensions[$class] = $extension; - } - - public function addFunction(TwigFunction $function): void - { - if ($this->initialized) { - throw new \LogicException(sprintf('Unable to add function "%s" as extensions have already been initialized.', $function->getName())); - } - - $this->staging->addFunction($function); - } - - /** - * @return TwigFunction[] - */ - public function getFunctions(): array - { - if (!$this->initialized) { - $this->initExtensions(); - } - - return $this->functions; - } - - public function getFunction(string $name): ?TwigFunction - { - if (!$this->initialized) { - $this->initExtensions(); - } - - if (isset($this->functions[$name])) { - return $this->functions[$name]; - } - - foreach ($this->functions as $pattern => $function) { - $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count); - - if ($count && preg_match('#^'.$pattern.'$#', $name, $matches)) { - array_shift($matches); - $function->setArguments($matches); - - return $function; - } - } - - foreach ($this->functionCallbacks as $callback) { - if (false !== $function = $callback($name)) { - return $function; - } - } - - return null; - } - - public function registerUndefinedFunctionCallback(callable $callable): void - { - $this->functionCallbacks[] = $callable; - } - - public function addFilter(TwigFilter $filter): void - { - if ($this->initialized) { - throw new \LogicException(sprintf('Unable to add filter "%s" as extensions have already been initialized.', $filter->getName())); - } - - $this->staging->addFilter($filter); - } - - /** - * @return TwigFilter[] - */ - public function getFilters(): array - { - if (!$this->initialized) { - $this->initExtensions(); - } - - return $this->filters; - } - - public function getFilter(string $name): ?TwigFilter - { - if (!$this->initialized) { - $this->initExtensions(); - } - - if (isset($this->filters[$name])) { - return $this->filters[$name]; - } - - foreach ($this->filters as $pattern => $filter) { - $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count); - - if ($count && preg_match('#^'.$pattern.'$#', $name, $matches)) { - array_shift($matches); - $filter->setArguments($matches); - - return $filter; - } - } - - foreach ($this->filterCallbacks as $callback) { - if (false !== $filter = $callback($name)) { - return $filter; - } - } - - return null; - } - - public function registerUndefinedFilterCallback(callable $callable): void - { - $this->filterCallbacks[] = $callable; - } - - public function addNodeVisitor(NodeVisitorInterface $visitor): void - { - if ($this->initialized) { - throw new \LogicException('Unable to add a node visitor as extensions have already been initialized.'); - } - - $this->staging->addNodeVisitor($visitor); - } - - /** - * @return NodeVisitorInterface[] - */ - public function getNodeVisitors(): array - { - if (!$this->initialized) { - $this->initExtensions(); - } - - return $this->visitors; - } - - public function addTokenParser(TokenParserInterface $parser): void - { - if ($this->initialized) { - throw new \LogicException('Unable to add a token parser as extensions have already been initialized.'); - } - - $this->staging->addTokenParser($parser); - } - - /** - * @return TokenParserInterface[] - */ - public function getTokenParsers(): array - { - if (!$this->initialized) { - $this->initExtensions(); - } - - return $this->parsers; - } - - public function getTokenParser(string $name): ?TokenParserInterface - { - if (!$this->initialized) { - $this->initExtensions(); - } - - if (isset($this->parsers[$name])) { - return $this->parsers[$name]; - } - - foreach ($this->parserCallbacks as $callback) { - if (false !== $parser = $callback($name)) { - return $parser; - } - } - - return null; - } - - public function registerUndefinedTokenParserCallback(callable $callable): void - { - $this->parserCallbacks[] = $callable; - } - - public function getGlobals(): array - { - if (null !== $this->globals) { - return $this->globals; - } - - $globals = []; - foreach ($this->extensions as $extension) { - if (!$extension instanceof GlobalsInterface) { - continue; - } - - $extGlobals = $extension->getGlobals(); - if (!\is_array($extGlobals)) { - throw new \UnexpectedValueException(sprintf('"%s::getGlobals()" must return an array of globals.', \get_class($extension))); - } - - $globals = array_merge($globals, $extGlobals); - } - - if ($this->initialized) { - $this->globals = $globals; - } - - return $globals; - } - - public function addTest(TwigTest $test): void - { - if ($this->initialized) { - throw new \LogicException(sprintf('Unable to add test "%s" as extensions have already been initialized.', $test->getName())); - } - - $this->staging->addTest($test); - } - - /** - * @return TwigTest[] - */ - public function getTests(): array - { - if (!$this->initialized) { - $this->initExtensions(); - } - - return $this->tests; - } - - public function getTest(string $name): ?TwigTest - { - if (!$this->initialized) { - $this->initExtensions(); - } - - if (isset($this->tests[$name])) { - return $this->tests[$name]; - } - - foreach ($this->tests as $pattern => $test) { - $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count); - - if ($count) { - if (preg_match('#^'.$pattern.'$#', $name, $matches)) { - array_shift($matches); - $test->setArguments($matches); - - return $test; - } - } - } - - return null; - } - - public function getUnaryOperators(): array - { - if (!$this->initialized) { - $this->initExtensions(); - } - - return $this->unaryOperators; - } - - public function getBinaryOperators(): array - { - if (!$this->initialized) { - $this->initExtensions(); - } - - return $this->binaryOperators; - } - - private function initExtensions(): void - { - $this->parsers = []; - $this->filters = []; - $this->functions = []; - $this->tests = []; - $this->visitors = []; - $this->unaryOperators = []; - $this->binaryOperators = []; - - foreach ($this->extensions as $extension) { - $this->initExtension($extension); - } - $this->initExtension($this->staging); - // Done at the end only, so that an exception during initialization does not mark the environment as initialized when catching the exception - $this->initialized = true; - } - - private function initExtension(ExtensionInterface $extension): void - { - // filters - foreach ($extension->getFilters() as $filter) { - $this->filters[$filter->getName()] = $filter; - } - - // functions - foreach ($extension->getFunctions() as $function) { - $this->functions[$function->getName()] = $function; - } - - // tests - foreach ($extension->getTests() as $test) { - $this->tests[$test->getName()] = $test; - } - - // token parsers - foreach ($extension->getTokenParsers() as $parser) { - if (!$parser instanceof TokenParserInterface) { - throw new \LogicException('getTokenParsers() must return an array of \Twig\TokenParser\TokenParserInterface.'); - } - - $this->parsers[$parser->getTag()] = $parser; - } - - // node visitors - foreach ($extension->getNodeVisitors() as $visitor) { - $this->visitors[] = $visitor; - } - - // operators - if ($operators = $extension->getOperators()) { - if (!\is_array($operators)) { - throw new \InvalidArgumentException(sprintf('"%s::getOperators()" must return an array with operators, got "%s".', \get_class($extension), \is_object($operators) ? \get_class($operators) : \gettype($operators).(\is_resource($operators) ? '' : '#'.$operators))); - } - - if (2 !== \count($operators)) { - throw new \InvalidArgumentException(sprintf('"%s::getOperators()" must return an array of 2 elements, got %d.', \get_class($extension), \count($operators))); - } - - $this->unaryOperators = array_merge($this->unaryOperators, $operators[0]); - $this->binaryOperators = array_merge($this->binaryOperators, $operators[1]); - } - } -} diff --git a/lib/twig/twig/src/FileExtensionEscapingStrategy.php b/lib/twig/twig/src/FileExtensionEscapingStrategy.php deleted file mode 100644 index 65198bbb6..000000000 --- a/lib/twig/twig/src/FileExtensionEscapingStrategy.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig; - -/** - * Default autoescaping strategy based on file names. - * - * This strategy sets the HTML as the default autoescaping strategy, - * but changes it based on the template name. - * - * Note that there is no runtime performance impact as the - * default autoescaping strategy is set at compilation time. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class FileExtensionEscapingStrategy -{ - /** - * Guesses the best autoescaping strategy based on the file name. - * - * @param string $name The template name - * - * @return string|false The escaping strategy name to use or false to disable - */ - public static function guess(string $name) - { - if (\in_array(substr($name, -1), ['/', '\\'])) { - return 'html'; // return html for directories - } - - if ('.twig' === substr($name, -5)) { - $name = substr($name, 0, -5); - } - - $extension = pathinfo($name, \PATHINFO_EXTENSION); - - switch ($extension) { - case 'js': - return 'js'; - - case 'css': - return 'css'; - - case 'txt': - return false; - - default: - return 'html'; - } - } -} diff --git a/lib/twig/twig/src/Lexer.php b/lib/twig/twig/src/Lexer.php deleted file mode 100644 index 9ff028c87..000000000 --- a/lib/twig/twig/src/Lexer.php +++ /dev/null @@ -1,501 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig; - -use Twig\Error\SyntaxError; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -class Lexer -{ - private $tokens; - private $code; - private $cursor; - private $lineno; - private $end; - private $state; - private $states; - private $brackets; - private $env; - private $source; - private $options; - private $regexes; - private $position; - private $positions; - private $currentVarBlockLine; - - public const STATE_DATA = 0; - public const STATE_BLOCK = 1; - public const STATE_VAR = 2; - public const STATE_STRING = 3; - public const STATE_INTERPOLATION = 4; - - public const REGEX_NAME = '/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A'; - public const REGEX_NUMBER = '/[0-9]+(?:\.[0-9]+)?([Ee][\+\-][0-9]+)?/A'; - public const REGEX_STRING = '/"([^#"\\\\]*(?:\\\\.[^#"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'/As'; - public const REGEX_DQ_STRING_DELIM = '/"/A'; - public const REGEX_DQ_STRING_PART = '/[^#"\\\\]*(?:(?:\\\\.|#(?!\{))[^#"\\\\]*)*/As'; - public const PUNCTUATION = '()[]{}?:.,|'; - - public function __construct(Environment $env, array $options = []) - { - $this->env = $env; - - $this->options = array_merge([ - 'tag_comment' => ['{#', '#}'], - 'tag_block' => ['{%', '%}'], - 'tag_variable' => ['{{', '}}'], - 'whitespace_trim' => '-', - 'whitespace_line_trim' => '~', - 'whitespace_line_chars' => ' \t\0\x0B', - 'interpolation' => ['#{', '}'], - ], $options); - - // when PHP 7.3 is the min version, we will be able to remove the '#' part in preg_quote as it's part of the default - $this->regexes = [ - // }} - 'lex_var' => '{ - \s* - (?:'. - preg_quote($this->options['whitespace_trim'].$this->options['tag_variable'][1], '#').'\s*'. // -}}\s* - '|'. - preg_quote($this->options['whitespace_line_trim'].$this->options['tag_variable'][1], '#').'['.$this->options['whitespace_line_chars'].']*'. // ~}}[ \t\0\x0B]* - '|'. - preg_quote($this->options['tag_variable'][1], '#'). // }} - ') - }Ax', - - // %} - 'lex_block' => '{ - \s* - (?:'. - preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '#').'\s*\n?'. // -%}\s*\n? - '|'. - preg_quote($this->options['whitespace_line_trim'].$this->options['tag_block'][1], '#').'['.$this->options['whitespace_line_chars'].']*'. // ~%}[ \t\0\x0B]* - '|'. - preg_quote($this->options['tag_block'][1], '#').'\n?'. // %}\n? - ') - }Ax', - - // {% endverbatim %} - 'lex_raw_data' => '{'. - preg_quote($this->options['tag_block'][0], '#'). // {% - '('. - $this->options['whitespace_trim']. // - - '|'. - $this->options['whitespace_line_trim']. // ~ - ')?\s*endverbatim\s*'. - '(?:'. - preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '#').'\s*'. // -%} - '|'. - preg_quote($this->options['whitespace_line_trim'].$this->options['tag_block'][1], '#').'['.$this->options['whitespace_line_chars'].']*'. // ~%}[ \t\0\x0B]* - '|'. - preg_quote($this->options['tag_block'][1], '#'). // %} - ') - }sx', - - 'operator' => $this->getOperatorRegex(), - - // #} - 'lex_comment' => '{ - (?:'. - preg_quote($this->options['whitespace_trim'].$this->options['tag_comment'][1], '#').'\s*\n?'. // -#}\s*\n? - '|'. - preg_quote($this->options['whitespace_line_trim'].$this->options['tag_comment'][1], '#').'['.$this->options['whitespace_line_chars'].']*'. // ~#}[ \t\0\x0B]* - '|'. - preg_quote($this->options['tag_comment'][1], '#').'\n?'. // #}\n? - ') - }sx', - - // verbatim %} - 'lex_block_raw' => '{ - \s*verbatim\s* - (?:'. - preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '#').'\s*'. // -%}\s* - '|'. - preg_quote($this->options['whitespace_line_trim'].$this->options['tag_block'][1], '#').'['.$this->options['whitespace_line_chars'].']*'. // ~%}[ \t\0\x0B]* - '|'. - preg_quote($this->options['tag_block'][1], '#'). // %} - ') - }Asx', - - 'lex_block_line' => '{\s*line\s+(\d+)\s*'.preg_quote($this->options['tag_block'][1], '#').'}As', - - // {{ or {% or {# - 'lex_tokens_start' => '{ - ('. - preg_quote($this->options['tag_variable'][0], '#'). // {{ - '|'. - preg_quote($this->options['tag_block'][0], '#'). // {% - '|'. - preg_quote($this->options['tag_comment'][0], '#'). // {# - ')('. - preg_quote($this->options['whitespace_trim'], '#'). // - - '|'. - preg_quote($this->options['whitespace_line_trim'], '#'). // ~ - ')? - }sx', - 'interpolation_start' => '{'.preg_quote($this->options['interpolation'][0], '#').'\s*}A', - 'interpolation_end' => '{\s*'.preg_quote($this->options['interpolation'][1], '#').'}A', - ]; - } - - public function tokenize(Source $source): TokenStream - { - $this->source = $source; - $this->code = str_replace(["\r\n", "\r"], "\n", $source->getCode()); - $this->cursor = 0; - $this->lineno = 1; - $this->end = \strlen($this->code); - $this->tokens = []; - $this->state = self::STATE_DATA; - $this->states = []; - $this->brackets = []; - $this->position = -1; - - // find all token starts in one go - preg_match_all($this->regexes['lex_tokens_start'], $this->code, $matches, \PREG_OFFSET_CAPTURE); - $this->positions = $matches; - - while ($this->cursor < $this->end) { - // dispatch to the lexing functions depending - // on the current state - switch ($this->state) { - case self::STATE_DATA: - $this->lexData(); - break; - - case self::STATE_BLOCK: - $this->lexBlock(); - break; - - case self::STATE_VAR: - $this->lexVar(); - break; - - case self::STATE_STRING: - $this->lexString(); - break; - - case self::STATE_INTERPOLATION: - $this->lexInterpolation(); - break; - } - } - - $this->pushToken(/* Token::EOF_TYPE */ -1); - - if (!empty($this->brackets)) { - list($expect, $lineno) = array_pop($this->brackets); - throw new SyntaxError(sprintf('Unclosed "%s".', $expect), $lineno, $this->source); - } - - return new TokenStream($this->tokens, $this->source); - } - - private function lexData(): void - { - // if no matches are left we return the rest of the template as simple text token - if ($this->position == \count($this->positions[0]) - 1) { - $this->pushToken(/* Token::TEXT_TYPE */ 0, substr($this->code, $this->cursor)); - $this->cursor = $this->end; - - return; - } - - // Find the first token after the current cursor - $position = $this->positions[0][++$this->position]; - while ($position[1] < $this->cursor) { - if ($this->position == \count($this->positions[0]) - 1) { - return; - } - $position = $this->positions[0][++$this->position]; - } - - // push the template text first - $text = $textContent = substr($this->code, $this->cursor, $position[1] - $this->cursor); - - // trim? - if (isset($this->positions[2][$this->position][0])) { - if ($this->options['whitespace_trim'] === $this->positions[2][$this->position][0]) { - // whitespace_trim detected ({%-, {{- or {#-) - $text = rtrim($text); - } elseif ($this->options['whitespace_line_trim'] === $this->positions[2][$this->position][0]) { - // whitespace_line_trim detected ({%~, {{~ or {#~) - // don't trim \r and \n - $text = rtrim($text, " \t\0\x0B"); - } - } - $this->pushToken(/* Token::TEXT_TYPE */ 0, $text); - $this->moveCursor($textContent.$position[0]); - - switch ($this->positions[1][$this->position][0]) { - case $this->options['tag_comment'][0]: - $this->lexComment(); - break; - - case $this->options['tag_block'][0]: - // raw data? - if (preg_match($this->regexes['lex_block_raw'], $this->code, $match, 0, $this->cursor)) { - $this->moveCursor($match[0]); - $this->lexRawData(); - // {% line \d+ %} - } elseif (preg_match($this->regexes['lex_block_line'], $this->code, $match, 0, $this->cursor)) { - $this->moveCursor($match[0]); - $this->lineno = (int) $match[1]; - } else { - $this->pushToken(/* Token::BLOCK_START_TYPE */ 1); - $this->pushState(self::STATE_BLOCK); - $this->currentVarBlockLine = $this->lineno; - } - break; - - case $this->options['tag_variable'][0]: - $this->pushToken(/* Token::VAR_START_TYPE */ 2); - $this->pushState(self::STATE_VAR); - $this->currentVarBlockLine = $this->lineno; - break; - } - } - - private function lexBlock(): void - { - if (empty($this->brackets) && preg_match($this->regexes['lex_block'], $this->code, $match, 0, $this->cursor)) { - $this->pushToken(/* Token::BLOCK_END_TYPE */ 3); - $this->moveCursor($match[0]); - $this->popState(); - } else { - $this->lexExpression(); - } - } - - private function lexVar(): void - { - if (empty($this->brackets) && preg_match($this->regexes['lex_var'], $this->code, $match, 0, $this->cursor)) { - $this->pushToken(/* Token::VAR_END_TYPE */ 4); - $this->moveCursor($match[0]); - $this->popState(); - } else { - $this->lexExpression(); - } - } - - private function lexExpression(): void - { - // whitespace - if (preg_match('/\s+/A', $this->code, $match, 0, $this->cursor)) { - $this->moveCursor($match[0]); - - if ($this->cursor >= $this->end) { - throw new SyntaxError(sprintf('Unclosed "%s".', self::STATE_BLOCK === $this->state ? 'block' : 'variable'), $this->currentVarBlockLine, $this->source); - } - } - - // arrow function - if ('=' === $this->code[$this->cursor] && '>' === $this->code[$this->cursor + 1]) { - $this->pushToken(Token::ARROW_TYPE, '=>'); - $this->moveCursor('=>'); - } - // operators - elseif (preg_match($this->regexes['operator'], $this->code, $match, 0, $this->cursor)) { - $this->pushToken(/* Token::OPERATOR_TYPE */ 8, preg_replace('/\s+/', ' ', $match[0])); - $this->moveCursor($match[0]); - } - // names - elseif (preg_match(self::REGEX_NAME, $this->code, $match, 0, $this->cursor)) { - $this->pushToken(/* Token::NAME_TYPE */ 5, $match[0]); - $this->moveCursor($match[0]); - } - // numbers - elseif (preg_match(self::REGEX_NUMBER, $this->code, $match, 0, $this->cursor)) { - $number = (float) $match[0]; // floats - if (ctype_digit($match[0]) && $number <= \PHP_INT_MAX) { - $number = (int) $match[0]; // integers lower than the maximum - } - $this->pushToken(/* Token::NUMBER_TYPE */ 6, $number); - $this->moveCursor($match[0]); - } - // punctuation - elseif (false !== strpos(self::PUNCTUATION, $this->code[$this->cursor])) { - // opening bracket - if (false !== strpos('([{', $this->code[$this->cursor])) { - $this->brackets[] = [$this->code[$this->cursor], $this->lineno]; - } - // closing bracket - elseif (false !== strpos(')]}', $this->code[$this->cursor])) { - if (empty($this->brackets)) { - throw new SyntaxError(sprintf('Unexpected "%s".', $this->code[$this->cursor]), $this->lineno, $this->source); - } - - list($expect, $lineno) = array_pop($this->brackets); - if ($this->code[$this->cursor] != strtr($expect, '([{', ')]}')) { - throw new SyntaxError(sprintf('Unclosed "%s".', $expect), $lineno, $this->source); - } - } - - $this->pushToken(/* Token::PUNCTUATION_TYPE */ 9, $this->code[$this->cursor]); - ++$this->cursor; - } - // strings - elseif (preg_match(self::REGEX_STRING, $this->code, $match, 0, $this->cursor)) { - $this->pushToken(/* Token::STRING_TYPE */ 7, stripcslashes(substr($match[0], 1, -1))); - $this->moveCursor($match[0]); - } - // opening double quoted string - elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, 0, $this->cursor)) { - $this->brackets[] = ['"', $this->lineno]; - $this->pushState(self::STATE_STRING); - $this->moveCursor($match[0]); - } - // unlexable - else { - throw new SyntaxError(sprintf('Unexpected character "%s".', $this->code[$this->cursor]), $this->lineno, $this->source); - } - } - - private function lexRawData(): void - { - if (!preg_match($this->regexes['lex_raw_data'], $this->code, $match, \PREG_OFFSET_CAPTURE, $this->cursor)) { - throw new SyntaxError('Unexpected end of file: Unclosed "verbatim" block.', $this->lineno, $this->source); - } - - $text = substr($this->code, $this->cursor, $match[0][1] - $this->cursor); - $this->moveCursor($text.$match[0][0]); - - // trim? - if (isset($match[1][0])) { - if ($this->options['whitespace_trim'] === $match[1][0]) { - // whitespace_trim detected ({%-, {{- or {#-) - $text = rtrim($text); - } else { - // whitespace_line_trim detected ({%~, {{~ or {#~) - // don't trim \r and \n - $text = rtrim($text, " \t\0\x0B"); - } - } - - $this->pushToken(/* Token::TEXT_TYPE */ 0, $text); - } - - private function lexComment(): void - { - if (!preg_match($this->regexes['lex_comment'], $this->code, $match, \PREG_OFFSET_CAPTURE, $this->cursor)) { - throw new SyntaxError('Unclosed comment.', $this->lineno, $this->source); - } - - $this->moveCursor(substr($this->code, $this->cursor, $match[0][1] - $this->cursor).$match[0][0]); - } - - private function lexString(): void - { - if (preg_match($this->regexes['interpolation_start'], $this->code, $match, 0, $this->cursor)) { - $this->brackets[] = [$this->options['interpolation'][0], $this->lineno]; - $this->pushToken(/* Token::INTERPOLATION_START_TYPE */ 10); - $this->moveCursor($match[0]); - $this->pushState(self::STATE_INTERPOLATION); - } elseif (preg_match(self::REGEX_DQ_STRING_PART, $this->code, $match, 0, $this->cursor) && \strlen($match[0]) > 0) { - $this->pushToken(/* Token::STRING_TYPE */ 7, stripcslashes($match[0])); - $this->moveCursor($match[0]); - } elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, 0, $this->cursor)) { - list($expect, $lineno) = array_pop($this->brackets); - if ('"' != $this->code[$this->cursor]) { - throw new SyntaxError(sprintf('Unclosed "%s".', $expect), $lineno, $this->source); - } - - $this->popState(); - ++$this->cursor; - } else { - // unlexable - throw new SyntaxError(sprintf('Unexpected character "%s".', $this->code[$this->cursor]), $this->lineno, $this->source); - } - } - - private function lexInterpolation(): void - { - $bracket = end($this->brackets); - if ($this->options['interpolation'][0] === $bracket[0] && preg_match($this->regexes['interpolation_end'], $this->code, $match, 0, $this->cursor)) { - array_pop($this->brackets); - $this->pushToken(/* Token::INTERPOLATION_END_TYPE */ 11); - $this->moveCursor($match[0]); - $this->popState(); - } else { - $this->lexExpression(); - } - } - - private function pushToken($type, $value = ''): void - { - // do not push empty text tokens - if (/* Token::TEXT_TYPE */ 0 === $type && '' === $value) { - return; - } - - $this->tokens[] = new Token($type, $value, $this->lineno); - } - - private function moveCursor($text): void - { - $this->cursor += \strlen($text); - $this->lineno += substr_count($text, "\n"); - } - - private function getOperatorRegex(): string - { - $operators = array_merge( - ['='], - array_keys($this->env->getUnaryOperators()), - array_keys($this->env->getBinaryOperators()) - ); - - $operators = array_combine($operators, array_map('strlen', $operators)); - arsort($operators); - - $regex = []; - foreach ($operators as $operator => $length) { - // an operator that ends with a character must be followed by - // a whitespace, a parenthesis, an opening map [ or sequence { - $r = preg_quote($operator, '/'); - if (ctype_alpha($operator[$length - 1])) { - $r .= '(?=[\s()\[{])'; - } - - // an operator that begins with a character must not have a dot or pipe before - if (ctype_alpha($operator[0])) { - $r = '(?<![\.\|])'.$r; - } - - // an operator with a space can be any amount of whitespaces - $r = preg_replace('/\s+/', '\s+', $r); - - $regex[] = $r; - } - - return '/'.implode('|', $regex).'/A'; - } - - private function pushState($state): void - { - $this->states[] = $this->state; - $this->state = $state; - } - - private function popState(): void - { - if (0 === \count($this->states)) { - throw new \LogicException('Cannot pop state without a previous state.'); - } - - $this->state = array_pop($this->states); - } -} diff --git a/lib/twig/twig/src/Loader/ArrayLoader.php b/lib/twig/twig/src/Loader/ArrayLoader.php deleted file mode 100644 index 5d726c35a..000000000 --- a/lib/twig/twig/src/Loader/ArrayLoader.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Loader; - -use Twig\Error\LoaderError; -use Twig\Source; - -/** - * Loads a template from an array. - * - * When using this loader with a cache mechanism, you should know that a new cache - * key is generated each time a template content "changes" (the cache key being the - * source code of the template). If you don't want to see your cache grows out of - * control, you need to take care of clearing the old cache file by yourself. - * - * This loader should only be used for unit testing. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class ArrayLoader implements LoaderInterface -{ - private $templates = []; - - /** - * @param array $templates An array of templates (keys are the names, and values are the source code) - */ - public function __construct(array $templates = []) - { - $this->templates = $templates; - } - - public function setTemplate(string $name, string $template): void - { - $this->templates[$name] = $template; - } - - public function getSourceContext(string $name): Source - { - if (!isset($this->templates[$name])) { - throw new LoaderError(sprintf('Template "%s" is not defined.', $name)); - } - - return new Source($this->templates[$name], $name); - } - - public function exists(string $name): bool - { - return isset($this->templates[$name]); - } - - public function getCacheKey(string $name): string - { - if (!isset($this->templates[$name])) { - throw new LoaderError(sprintf('Template "%s" is not defined.', $name)); - } - - return $name.':'.$this->templates[$name]; - } - - public function isFresh(string $name, int $time): bool - { - if (!isset($this->templates[$name])) { - throw new LoaderError(sprintf('Template "%s" is not defined.', $name)); - } - - return true; - } -} diff --git a/lib/twig/twig/src/Loader/ChainLoader.php b/lib/twig/twig/src/Loader/ChainLoader.php deleted file mode 100644 index fbf4f3a06..000000000 --- a/lib/twig/twig/src/Loader/ChainLoader.php +++ /dev/null @@ -1,119 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Loader; - -use Twig\Error\LoaderError; -use Twig\Source; - -/** - * Loads templates from other loaders. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class ChainLoader implements LoaderInterface -{ - private $hasSourceCache = []; - private $loaders = []; - - /** - * @param LoaderInterface[] $loaders - */ - public function __construct(array $loaders = []) - { - foreach ($loaders as $loader) { - $this->addLoader($loader); - } - } - - public function addLoader(LoaderInterface $loader): void - { - $this->loaders[] = $loader; - $this->hasSourceCache = []; - } - - /** - * @return LoaderInterface[] - */ - public function getLoaders(): array - { - return $this->loaders; - } - - public function getSourceContext(string $name): Source - { - $exceptions = []; - foreach ($this->loaders as $loader) { - if (!$loader->exists($name)) { - continue; - } - - try { - return $loader->getSourceContext($name); - } catch (LoaderError $e) { - $exceptions[] = $e->getMessage(); - } - } - - throw new LoaderError(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); - } - - public function exists(string $name): bool - { - if (isset($this->hasSourceCache[$name])) { - return $this->hasSourceCache[$name]; - } - - foreach ($this->loaders as $loader) { - if ($loader->exists($name)) { - return $this->hasSourceCache[$name] = true; - } - } - - return $this->hasSourceCache[$name] = false; - } - - public function getCacheKey(string $name): string - { - $exceptions = []; - foreach ($this->loaders as $loader) { - if (!$loader->exists($name)) { - continue; - } - - try { - return $loader->getCacheKey($name); - } catch (LoaderError $e) { - $exceptions[] = \get_class($loader).': '.$e->getMessage(); - } - } - - throw new LoaderError(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); - } - - public function isFresh(string $name, int $time): bool - { - $exceptions = []; - foreach ($this->loaders as $loader) { - if (!$loader->exists($name)) { - continue; - } - - try { - return $loader->isFresh($name, $time); - } catch (LoaderError $e) { - $exceptions[] = \get_class($loader).': '.$e->getMessage(); - } - } - - throw new LoaderError(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); - } -} diff --git a/lib/twig/twig/src/Loader/FilesystemLoader.php b/lib/twig/twig/src/Loader/FilesystemLoader.php deleted file mode 100644 index 62267a11c..000000000 --- a/lib/twig/twig/src/Loader/FilesystemLoader.php +++ /dev/null @@ -1,283 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Loader; - -use Twig\Error\LoaderError; -use Twig\Source; - -/** - * Loads template from the filesystem. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class FilesystemLoader implements LoaderInterface -{ - /** Identifier of the main namespace. */ - public const MAIN_NAMESPACE = '__main__'; - - protected $paths = []; - protected $cache = []; - protected $errorCache = []; - - private $rootPath; - - /** - * @param string|array $paths A path or an array of paths where to look for templates - * @param string|null $rootPath The root path common to all relative paths (null for getcwd()) - */ - public function __construct($paths = [], string $rootPath = null) - { - $this->rootPath = (null === $rootPath ? getcwd() : $rootPath).\DIRECTORY_SEPARATOR; - if (null !== $rootPath && false !== ($realPath = realpath($rootPath))) { - $this->rootPath = $realPath.\DIRECTORY_SEPARATOR; - } - - if ($paths) { - $this->setPaths($paths); - } - } - - /** - * Returns the paths to the templates. - */ - public function getPaths(string $namespace = self::MAIN_NAMESPACE): array - { - return $this->paths[$namespace] ?? []; - } - - /** - * Returns the path namespaces. - * - * The main namespace is always defined. - */ - public function getNamespaces(): array - { - return array_keys($this->paths); - } - - /** - * @param string|array $paths A path or an array of paths where to look for templates - */ - public function setPaths($paths, string $namespace = self::MAIN_NAMESPACE): void - { - if (!\is_array($paths)) { - $paths = [$paths]; - } - - $this->paths[$namespace] = []; - foreach ($paths as $path) { - $this->addPath($path, $namespace); - } - } - - /** - * @throws LoaderError - */ - public function addPath(string $path, string $namespace = self::MAIN_NAMESPACE): void - { - // invalidate the cache - $this->cache = $this->errorCache = []; - - $checkPath = $this->isAbsolutePath($path) ? $path : $this->rootPath.$path; - if (!is_dir($checkPath)) { - throw new LoaderError(sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath)); - } - - $this->paths[$namespace][] = rtrim($path, '/\\'); - } - - /** - * @throws LoaderError - */ - public function prependPath(string $path, string $namespace = self::MAIN_NAMESPACE): void - { - // invalidate the cache - $this->cache = $this->errorCache = []; - - $checkPath = $this->isAbsolutePath($path) ? $path : $this->rootPath.$path; - if (!is_dir($checkPath)) { - throw new LoaderError(sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath)); - } - - $path = rtrim($path, '/\\'); - - if (!isset($this->paths[$namespace])) { - $this->paths[$namespace][] = $path; - } else { - array_unshift($this->paths[$namespace], $path); - } - } - - public function getSourceContext(string $name): Source - { - if (null === $path = $this->findTemplate($name)) { - return new Source('', $name, ''); - } - - return new Source(file_get_contents($path), $name, $path); - } - - public function getCacheKey(string $name): string - { - if (null === $path = $this->findTemplate($name)) { - return ''; - } - $len = \strlen($this->rootPath); - if (0 === strncmp($this->rootPath, $path, $len)) { - return substr($path, $len); - } - - return $path; - } - - /** - * @return bool - */ - public function exists(string $name) - { - $name = $this->normalizeName($name); - - if (isset($this->cache[$name])) { - return true; - } - - return null !== $this->findTemplate($name, false); - } - - public function isFresh(string $name, int $time): bool - { - // false support to be removed in 3.0 - if (null === $path = $this->findTemplate($name)) { - return false; - } - - return filemtime($path) < $time; - } - - /** - * @return string|null - */ - protected function findTemplate(string $name, bool $throw = true) - { - $name = $this->normalizeName($name); - - if (isset($this->cache[$name])) { - return $this->cache[$name]; - } - - if (isset($this->errorCache[$name])) { - if (!$throw) { - return null; - } - - throw new LoaderError($this->errorCache[$name]); - } - - try { - list($namespace, $shortname) = $this->parseName($name); - - $this->validateName($shortname); - } catch (LoaderError $e) { - if (!$throw) { - return null; - } - - throw $e; - } - - if (!isset($this->paths[$namespace])) { - $this->errorCache[$name] = sprintf('There are no registered paths for namespace "%s".', $namespace); - - if (!$throw) { - return null; - } - - throw new LoaderError($this->errorCache[$name]); - } - - foreach ($this->paths[$namespace] as $path) { - if (!$this->isAbsolutePath($path)) { - $path = $this->rootPath.$path; - } - - if (is_file($path.'/'.$shortname)) { - if (false !== $realpath = realpath($path.'/'.$shortname)) { - return $this->cache[$name] = $realpath; - } - - return $this->cache[$name] = $path.'/'.$shortname; - } - } - - $this->errorCache[$name] = sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths[$namespace])); - - if (!$throw) { - return null; - } - - throw new LoaderError($this->errorCache[$name]); - } - - private function normalizeName(string $name): string - { - return preg_replace('#/{2,}#', '/', str_replace('\\', '/', $name)); - } - - private function parseName(string $name, string $default = self::MAIN_NAMESPACE): array - { - if (isset($name[0]) && '@' == $name[0]) { - if (false === $pos = strpos($name, '/')) { - throw new LoaderError(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name)); - } - - $namespace = substr($name, 1, $pos - 1); - $shortname = substr($name, $pos + 1); - - return [$namespace, $shortname]; - } - - return [$default, $name]; - } - - private function validateName(string $name): void - { - if (false !== strpos($name, "\0")) { - throw new LoaderError('A template name cannot contain NUL bytes.'); - } - - $name = ltrim($name, '/'); - $parts = explode('/', $name); - $level = 0; - foreach ($parts as $part) { - if ('..' === $part) { - --$level; - } elseif ('.' !== $part) { - ++$level; - } - - if ($level < 0) { - throw new LoaderError(sprintf('Looks like you try to load a template outside configured directories (%s).', $name)); - } - } - } - - private function isAbsolutePath(string $file): bool - { - return strspn($file, '/\\', 0, 1) - || (\strlen($file) > 3 && ctype_alpha($file[0]) - && ':' === $file[1] - && strspn($file, '/\\', 2, 1) - ) - || null !== parse_url($file, \PHP_URL_SCHEME) - ; - } -} diff --git a/lib/twig/twig/src/Loader/LoaderInterface.php b/lib/twig/twig/src/Loader/LoaderInterface.php deleted file mode 100644 index fec7e85ff..000000000 --- a/lib/twig/twig/src/Loader/LoaderInterface.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Loader; - -use Twig\Error\LoaderError; -use Twig\Source; - -/** - * Interface all loaders must implement. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface LoaderInterface -{ - /** - * Returns the source context for a given template logical name. - * - * @throws LoaderError When $name is not found - */ - public function getSourceContext(string $name): Source; - - /** - * Gets the cache key to use for the cache for a given template name. - * - * @throws LoaderError When $name is not found - */ - public function getCacheKey(string $name): string; - - /** - * @param int $time Timestamp of the last modification time of the cached template - * - * @throws LoaderError When $name is not found - */ - public function isFresh(string $name, int $time): bool; - - /** - * @return bool - */ - public function exists(string $name); -} diff --git a/lib/twig/twig/src/Markup.php b/lib/twig/twig/src/Markup.php deleted file mode 100644 index 1788acc4f..000000000 --- a/lib/twig/twig/src/Markup.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig; - -/** - * Marks a content as safe. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Markup implements \Countable, \JsonSerializable -{ - private $content; - private $charset; - - public function __construct($content, $charset) - { - $this->content = (string) $content; - $this->charset = $charset; - } - - public function __toString() - { - return $this->content; - } - - /** - * @return int - */ - #[\ReturnTypeWillChange] - public function count() - { - return mb_strlen($this->content, $this->charset); - } - - /** - * @return mixed - */ - #[\ReturnTypeWillChange] - public function jsonSerialize() - { - return $this->content; - } -} diff --git a/lib/twig/twig/src/Node/AutoEscapeNode.php b/lib/twig/twig/src/Node/AutoEscapeNode.php deleted file mode 100644 index cd970411b..000000000 --- a/lib/twig/twig/src/Node/AutoEscapeNode.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -use Twig\Compiler; - -/** - * Represents an autoescape node. - * - * The value is the escaping strategy (can be html, js, ...) - * - * The true value is equivalent to html. - * - * If autoescaping is disabled, then the value is false. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class AutoEscapeNode extends Node -{ - public function __construct($value, Node $body, int $lineno, string $tag = 'autoescape') - { - parent::__construct(['body' => $body], ['value' => $value], $lineno, $tag); - } - - public function compile(Compiler $compiler): void - { - $compiler->subcompile($this->getNode('body')); - } -} diff --git a/lib/twig/twig/src/Node/BlockNode.php b/lib/twig/twig/src/Node/BlockNode.php deleted file mode 100644 index 0632ba747..000000000 --- a/lib/twig/twig/src/Node/BlockNode.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -use Twig\Compiler; - -/** - * Represents a block node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class BlockNode extends Node -{ - public function __construct(string $name, Node $body, int $lineno, string $tag = null) - { - parent::__construct(['body' => $body], ['name' => $name], $lineno, $tag); - } - - public function compile(Compiler $compiler): void - { - $compiler - ->addDebugInfo($this) - ->write(sprintf("public function block_%s(\$context, array \$blocks = [])\n", $this->getAttribute('name')), "{\n") - ->indent() - ->write("\$macros = \$this->macros;\n") - ; - - $compiler - ->subcompile($this->getNode('body')) - ->outdent() - ->write("}\n\n") - ; - } -} diff --git a/lib/twig/twig/src/Node/BlockReferenceNode.php b/lib/twig/twig/src/Node/BlockReferenceNode.php deleted file mode 100644 index cc8af5b52..000000000 --- a/lib/twig/twig/src/Node/BlockReferenceNode.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -use Twig\Compiler; - -/** - * Represents a block call node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class BlockReferenceNode extends Node implements NodeOutputInterface -{ - public function __construct(string $name, int $lineno, string $tag = null) - { - parent::__construct([], ['name' => $name], $lineno, $tag); - } - - public function compile(Compiler $compiler): void - { - $compiler - ->addDebugInfo($this) - ->write(sprintf("\$this->displayBlock('%s', \$context, \$blocks);\n", $this->getAttribute('name'))) - ; - } -} diff --git a/lib/twig/twig/src/Node/BodyNode.php b/lib/twig/twig/src/Node/BodyNode.php deleted file mode 100644 index 041cbf685..000000000 --- a/lib/twig/twig/src/Node/BodyNode.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -/** - * Represents a body node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class BodyNode extends Node -{ -} diff --git a/lib/twig/twig/src/Node/CheckSecurityCallNode.php b/lib/twig/twig/src/Node/CheckSecurityCallNode.php deleted file mode 100644 index a78a38d80..000000000 --- a/lib/twig/twig/src/Node/CheckSecurityCallNode.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -use Twig\Compiler; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -class CheckSecurityCallNode extends Node -{ - public function compile(Compiler $compiler) - { - $compiler - ->write("\$this->sandbox = \$this->env->getExtension('\Twig\Extension\SandboxExtension');\n") - ->write("\$this->checkSecurity();\n") - ; - } -} diff --git a/lib/twig/twig/src/Node/CheckSecurityNode.php b/lib/twig/twig/src/Node/CheckSecurityNode.php deleted file mode 100644 index 472732796..000000000 --- a/lib/twig/twig/src/Node/CheckSecurityNode.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -use Twig\Compiler; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -class CheckSecurityNode extends Node -{ - private $usedFilters; - private $usedTags; - private $usedFunctions; - - public function __construct(array $usedFilters, array $usedTags, array $usedFunctions) - { - $this->usedFilters = $usedFilters; - $this->usedTags = $usedTags; - $this->usedFunctions = $usedFunctions; - - parent::__construct(); - } - - public function compile(Compiler $compiler): void - { - $tags = $filters = $functions = []; - foreach (['tags', 'filters', 'functions'] as $type) { - foreach ($this->{'used'.ucfirst($type)} as $name => $node) { - if ($node instanceof Node) { - ${$type}[$name] = $node->getTemplateLine(); - } else { - ${$type}[$node] = null; - } - } - } - - $compiler - ->write("\n") - ->write("public function checkSecurity()\n") - ->write("{\n") - ->indent() - ->write('static $tags = ')->repr(array_filter($tags))->raw(";\n") - ->write('static $filters = ')->repr(array_filter($filters))->raw(";\n") - ->write('static $functions = ')->repr(array_filter($functions))->raw(";\n\n") - ->write("try {\n") - ->indent() - ->write("\$this->sandbox->checkSecurity(\n") - ->indent() - ->write(!$tags ? "[],\n" : "['".implode("', '", array_keys($tags))."'],\n") - ->write(!$filters ? "[],\n" : "['".implode("', '", array_keys($filters))."'],\n") - ->write(!$functions ? "[]\n" : "['".implode("', '", array_keys($functions))."']\n") - ->outdent() - ->write(");\n") - ->outdent() - ->write("} catch (SecurityError \$e) {\n") - ->indent() - ->write("\$e->setSourceContext(\$this->source);\n\n") - ->write("if (\$e instanceof SecurityNotAllowedTagError && isset(\$tags[\$e->getTagName()])) {\n") - ->indent() - ->write("\$e->setTemplateLine(\$tags[\$e->getTagName()]);\n") - ->outdent() - ->write("} elseif (\$e instanceof SecurityNotAllowedFilterError && isset(\$filters[\$e->getFilterName()])) {\n") - ->indent() - ->write("\$e->setTemplateLine(\$filters[\$e->getFilterName()]);\n") - ->outdent() - ->write("} elseif (\$e instanceof SecurityNotAllowedFunctionError && isset(\$functions[\$e->getFunctionName()])) {\n") - ->indent() - ->write("\$e->setTemplateLine(\$functions[\$e->getFunctionName()]);\n") - ->outdent() - ->write("}\n\n") - ->write("throw \$e;\n") - ->outdent() - ->write("}\n\n") - ->outdent() - ->write("}\n") - ; - } -} diff --git a/lib/twig/twig/src/Node/CheckToStringNode.php b/lib/twig/twig/src/Node/CheckToStringNode.php deleted file mode 100644 index c7a9d6984..000000000 --- a/lib/twig/twig/src/Node/CheckToStringNode.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -use Twig\Compiler; -use Twig\Node\Expression\AbstractExpression; - -/** - * Checks if casting an expression to __toString() is allowed by the sandbox. - * - * For instance, when there is a simple Print statement, like {{ article }}, - * and if the sandbox is enabled, we need to check that the __toString() - * method is allowed if 'article' is an object. The same goes for {{ article|upper }} - * or {{ random(article) }} - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class CheckToStringNode extends AbstractExpression -{ - public function __construct(AbstractExpression $expr) - { - parent::__construct(['expr' => $expr], [], $expr->getTemplateLine(), $expr->getNodeTag()); - } - - public function compile(Compiler $compiler): void - { - $expr = $this->getNode('expr'); - $compiler - ->raw('$this->sandbox->ensureToStringAllowed(') - ->subcompile($expr) - ->raw(', ') - ->repr($expr->getTemplateLine()) - ->raw(', $this->source)') - ; - } -} diff --git a/lib/twig/twig/src/Node/DeprecatedNode.php b/lib/twig/twig/src/Node/DeprecatedNode.php deleted file mode 100644 index 5ff44307f..000000000 --- a/lib/twig/twig/src/Node/DeprecatedNode.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -use Twig\Compiler; -use Twig\Node\Expression\AbstractExpression; -use Twig\Node\Expression\ConstantExpression; - -/** - * Represents a deprecated node. - * - * @author Yonel Ceruto <yonelceruto@gmail.com> - */ -class DeprecatedNode extends Node -{ - public function __construct(AbstractExpression $expr, int $lineno, string $tag = null) - { - parent::__construct(['expr' => $expr], [], $lineno, $tag); - } - - public function compile(Compiler $compiler): void - { - $compiler->addDebugInfo($this); - - $expr = $this->getNode('expr'); - - if ($expr instanceof ConstantExpression) { - $compiler->write('@trigger_error(') - ->subcompile($expr); - } else { - $varName = $compiler->getVarName(); - $compiler->write(sprintf('$%s = ', $varName)) - ->subcompile($expr) - ->raw(";\n") - ->write(sprintf('@trigger_error($%s', $varName)); - } - - $compiler - ->raw('.') - ->string(sprintf(' ("%s" at line %d).', $this->getTemplateName(), $this->getTemplateLine())) - ->raw(", E_USER_DEPRECATED);\n") - ; - } -} diff --git a/lib/twig/twig/src/Node/DoNode.php b/lib/twig/twig/src/Node/DoNode.php deleted file mode 100644 index f7783d19f..000000000 --- a/lib/twig/twig/src/Node/DoNode.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -use Twig\Compiler; -use Twig\Node\Expression\AbstractExpression; - -/** - * Represents a do node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class DoNode extends Node -{ - public function __construct(AbstractExpression $expr, int $lineno, string $tag = null) - { - parent::__construct(['expr' => $expr], [], $lineno, $tag); - } - - public function compile(Compiler $compiler): void - { - $compiler - ->addDebugInfo($this) - ->write('') - ->subcompile($this->getNode('expr')) - ->raw(";\n") - ; - } -} diff --git a/lib/twig/twig/src/Node/EmbedNode.php b/lib/twig/twig/src/Node/EmbedNode.php deleted file mode 100644 index 903c3f6c7..000000000 --- a/lib/twig/twig/src/Node/EmbedNode.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -use Twig\Compiler; -use Twig\Node\Expression\AbstractExpression; -use Twig\Node\Expression\ConstantExpression; - -/** - * Represents an embed node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class EmbedNode extends IncludeNode -{ - // we don't inject the module to avoid node visitors to traverse it twice (as it will be already visited in the main module) - public function __construct(string $name, int $index, ?AbstractExpression $variables, bool $only, bool $ignoreMissing, int $lineno, string $tag = null) - { - parent::__construct(new ConstantExpression('not_used', $lineno), $variables, $only, $ignoreMissing, $lineno, $tag); - - $this->setAttribute('name', $name); - $this->setAttribute('index', $index); - } - - protected function addGetTemplate(Compiler $compiler): void - { - $compiler - ->write('$this->loadTemplate(') - ->string($this->getAttribute('name')) - ->raw(', ') - ->repr($this->getTemplateName()) - ->raw(', ') - ->repr($this->getTemplateLine()) - ->raw(', ') - ->string($this->getAttribute('index')) - ->raw(')') - ; - } -} diff --git a/lib/twig/twig/src/Node/Expression/AbstractExpression.php b/lib/twig/twig/src/Node/Expression/AbstractExpression.php deleted file mode 100644 index 42da0559d..000000000 --- a/lib/twig/twig/src/Node/Expression/AbstractExpression.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression; - -use Twig\Node\Node; - -/** - * Abstract class for all nodes that represents an expression. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -abstract class AbstractExpression extends Node -{ -} diff --git a/lib/twig/twig/src/Node/Expression/ArrayExpression.php b/lib/twig/twig/src/Node/Expression/ArrayExpression.php deleted file mode 100644 index 0e25fe46a..000000000 --- a/lib/twig/twig/src/Node/Expression/ArrayExpression.php +++ /dev/null @@ -1,85 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression; - -use Twig\Compiler; - -class ArrayExpression extends AbstractExpression -{ - private $index; - - public function __construct(array $elements, int $lineno) - { - parent::__construct($elements, [], $lineno); - - $this->index = -1; - foreach ($this->getKeyValuePairs() as $pair) { - if ($pair['key'] instanceof ConstantExpression && ctype_digit((string) $pair['key']->getAttribute('value')) && $pair['key']->getAttribute('value') > $this->index) { - $this->index = $pair['key']->getAttribute('value'); - } - } - } - - public function getKeyValuePairs(): array - { - $pairs = []; - foreach (array_chunk($this->nodes, 2) as $pair) { - $pairs[] = [ - 'key' => $pair[0], - 'value' => $pair[1], - ]; - } - - return $pairs; - } - - public function hasElement(AbstractExpression $key): bool - { - foreach ($this->getKeyValuePairs() as $pair) { - // we compare the string representation of the keys - // to avoid comparing the line numbers which are not relevant here. - if ((string) $key === (string) $pair['key']) { - return true; - } - } - - return false; - } - - public function addElement(AbstractExpression $value, AbstractExpression $key = null): void - { - if (null === $key) { - $key = new ConstantExpression(++$this->index, $value->getTemplateLine()); - } - - array_push($this->nodes, $key, $value); - } - - public function compile(Compiler $compiler): void - { - $compiler->raw('['); - $first = true; - foreach ($this->getKeyValuePairs() as $pair) { - if (!$first) { - $compiler->raw(', '); - } - $first = false; - - $compiler - ->subcompile($pair['key']) - ->raw(' => ') - ->subcompile($pair['value']) - ; - } - $compiler->raw(']'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/ArrowFunctionExpression.php b/lib/twig/twig/src/Node/Expression/ArrowFunctionExpression.php deleted file mode 100644 index eaad03c9c..000000000 --- a/lib/twig/twig/src/Node/Expression/ArrowFunctionExpression.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression; - -use Twig\Compiler; -use Twig\Node\Node; - -/** - * Represents an arrow function. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class ArrowFunctionExpression extends AbstractExpression -{ - public function __construct(AbstractExpression $expr, Node $names, $lineno, $tag = null) - { - parent::__construct(['expr' => $expr, 'names' => $names], [], $lineno, $tag); - } - - public function compile(Compiler $compiler): void - { - $compiler - ->addDebugInfo($this) - ->raw('function (') - ; - foreach ($this->getNode('names') as $i => $name) { - if ($i) { - $compiler->raw(', '); - } - - $compiler - ->raw('$__') - ->raw($name->getAttribute('name')) - ->raw('__') - ; - } - $compiler - ->raw(') use ($context, $macros) { ') - ; - foreach ($this->getNode('names') as $name) { - $compiler - ->raw('$context["') - ->raw($name->getAttribute('name')) - ->raw('"] = $__') - ->raw($name->getAttribute('name')) - ->raw('__; ') - ; - } - $compiler - ->raw('return ') - ->subcompile($this->getNode('expr')) - ->raw('; }') - ; - } -} diff --git a/lib/twig/twig/src/Node/Expression/AssignNameExpression.php b/lib/twig/twig/src/Node/Expression/AssignNameExpression.php deleted file mode 100644 index 7dd1bc4a3..000000000 --- a/lib/twig/twig/src/Node/Expression/AssignNameExpression.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression; - -use Twig\Compiler; - -class AssignNameExpression extends NameExpression -{ - public function compile(Compiler $compiler): void - { - $compiler - ->raw('$context[') - ->string($this->getAttribute('name')) - ->raw(']') - ; - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/AbstractBinary.php b/lib/twig/twig/src/Node/Expression/Binary/AbstractBinary.php deleted file mode 100644 index c424e5cc5..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/AbstractBinary.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; -use Twig\Node\Expression\AbstractExpression; -use Twig\Node\Node; - -abstract class AbstractBinary extends AbstractExpression -{ - public function __construct(Node $left, Node $right, int $lineno) - { - parent::__construct(['left' => $left, 'right' => $right], [], $lineno); - } - - public function compile(Compiler $compiler): void - { - $compiler - ->raw('(') - ->subcompile($this->getNode('left')) - ->raw(' ') - ; - $this->operator($compiler); - $compiler - ->raw(' ') - ->subcompile($this->getNode('right')) - ->raw(')') - ; - } - - abstract public function operator(Compiler $compiler): Compiler; -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/AddBinary.php b/lib/twig/twig/src/Node/Expression/Binary/AddBinary.php deleted file mode 100644 index ee4307e33..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/AddBinary.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class AddBinary extends AbstractBinary -{ - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('+'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/AndBinary.php b/lib/twig/twig/src/Node/Expression/Binary/AndBinary.php deleted file mode 100644 index 5f2380da5..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/AndBinary.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class AndBinary extends AbstractBinary -{ - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('&&'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/BitwiseAndBinary.php b/lib/twig/twig/src/Node/Expression/Binary/BitwiseAndBinary.php deleted file mode 100644 index db7d6d612..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/BitwiseAndBinary.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class BitwiseAndBinary extends AbstractBinary -{ - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('&'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/BitwiseOrBinary.php b/lib/twig/twig/src/Node/Expression/Binary/BitwiseOrBinary.php deleted file mode 100644 index ce803dd90..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/BitwiseOrBinary.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class BitwiseOrBinary extends AbstractBinary -{ - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('|'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/BitwiseXorBinary.php b/lib/twig/twig/src/Node/Expression/Binary/BitwiseXorBinary.php deleted file mode 100644 index 5c2978501..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/BitwiseXorBinary.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class BitwiseXorBinary extends AbstractBinary -{ - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('^'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/ConcatBinary.php b/lib/twig/twig/src/Node/Expression/Binary/ConcatBinary.php deleted file mode 100644 index f825ab874..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/ConcatBinary.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class ConcatBinary extends AbstractBinary -{ - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('.'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/DivBinary.php b/lib/twig/twig/src/Node/Expression/Binary/DivBinary.php deleted file mode 100644 index e3817d1cd..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/DivBinary.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class DivBinary extends AbstractBinary -{ - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('/'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/EndsWithBinary.php b/lib/twig/twig/src/Node/Expression/Binary/EndsWithBinary.php deleted file mode 100644 index c3516b853..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/EndsWithBinary.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class EndsWithBinary extends AbstractBinary -{ - public function compile(Compiler $compiler): void - { - $left = $compiler->getVarName(); - $right = $compiler->getVarName(); - $compiler - ->raw(sprintf('(is_string($%s = ', $left)) - ->subcompile($this->getNode('left')) - ->raw(sprintf(') && is_string($%s = ', $right)) - ->subcompile($this->getNode('right')) - ->raw(sprintf(') && (\'\' === $%2$s || $%2$s === substr($%1$s, -strlen($%2$s))))', $left, $right)) - ; - } - - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw(''); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/EqualBinary.php b/lib/twig/twig/src/Node/Expression/Binary/EqualBinary.php deleted file mode 100644 index 6b48549ef..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/EqualBinary.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class EqualBinary extends AbstractBinary -{ - public function compile(Compiler $compiler): void - { - if (\PHP_VERSION_ID >= 80000) { - parent::compile($compiler); - - return; - } - - $compiler - ->raw('(0 === twig_compare(') - ->subcompile($this->getNode('left')) - ->raw(', ') - ->subcompile($this->getNode('right')) - ->raw('))') - ; - } - - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('=='); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/FloorDivBinary.php b/lib/twig/twig/src/Node/Expression/Binary/FloorDivBinary.php deleted file mode 100644 index d7e7980ef..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/FloorDivBinary.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class FloorDivBinary extends AbstractBinary -{ - public function compile(Compiler $compiler): void - { - $compiler->raw('(int) floor('); - parent::compile($compiler); - $compiler->raw(')'); - } - - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('/'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/GreaterBinary.php b/lib/twig/twig/src/Node/Expression/Binary/GreaterBinary.php deleted file mode 100644 index e1dd06780..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/GreaterBinary.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class GreaterBinary extends AbstractBinary -{ - public function compile(Compiler $compiler): void - { - if (\PHP_VERSION_ID >= 80000) { - parent::compile($compiler); - - return; - } - - $compiler - ->raw('(1 === twig_compare(') - ->subcompile($this->getNode('left')) - ->raw(', ') - ->subcompile($this->getNode('right')) - ->raw('))') - ; - } - - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('>'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/GreaterEqualBinary.php b/lib/twig/twig/src/Node/Expression/Binary/GreaterEqualBinary.php deleted file mode 100644 index df9bfcfbf..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/GreaterEqualBinary.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class GreaterEqualBinary extends AbstractBinary -{ - public function compile(Compiler $compiler): void - { - if (\PHP_VERSION_ID >= 80000) { - parent::compile($compiler); - - return; - } - - $compiler - ->raw('(0 <= twig_compare(') - ->subcompile($this->getNode('left')) - ->raw(', ') - ->subcompile($this->getNode('right')) - ->raw('))') - ; - } - - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('>='); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/InBinary.php b/lib/twig/twig/src/Node/Expression/Binary/InBinary.php deleted file mode 100644 index 6dbfa97f0..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/InBinary.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class InBinary extends AbstractBinary -{ - public function compile(Compiler $compiler): void - { - $compiler - ->raw('twig_in_filter(') - ->subcompile($this->getNode('left')) - ->raw(', ') - ->subcompile($this->getNode('right')) - ->raw(')') - ; - } - - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('in'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/LessBinary.php b/lib/twig/twig/src/Node/Expression/Binary/LessBinary.php deleted file mode 100644 index 598e62913..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/LessBinary.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class LessBinary extends AbstractBinary -{ - public function compile(Compiler $compiler): void - { - if (\PHP_VERSION_ID >= 80000) { - parent::compile($compiler); - - return; - } - - $compiler - ->raw('(-1 === twig_compare(') - ->subcompile($this->getNode('left')) - ->raw(', ') - ->subcompile($this->getNode('right')) - ->raw('))') - ; - } - - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('<'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/LessEqualBinary.php b/lib/twig/twig/src/Node/Expression/Binary/LessEqualBinary.php deleted file mode 100644 index e3c4af58d..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/LessEqualBinary.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class LessEqualBinary extends AbstractBinary -{ - public function compile(Compiler $compiler): void - { - if (\PHP_VERSION_ID >= 80000) { - parent::compile($compiler); - - return; - } - - $compiler - ->raw('(0 >= twig_compare(') - ->subcompile($this->getNode('left')) - ->raw(', ') - ->subcompile($this->getNode('right')) - ->raw('))') - ; - } - - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('<='); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/MatchesBinary.php b/lib/twig/twig/src/Node/Expression/Binary/MatchesBinary.php deleted file mode 100644 index bc97292cd..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/MatchesBinary.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class MatchesBinary extends AbstractBinary -{ - public function compile(Compiler $compiler): void - { - $compiler - ->raw('preg_match(') - ->subcompile($this->getNode('right')) - ->raw(', ') - ->subcompile($this->getNode('left')) - ->raw(')') - ; - } - - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw(''); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/ModBinary.php b/lib/twig/twig/src/Node/Expression/Binary/ModBinary.php deleted file mode 100644 index 271b45cac..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/ModBinary.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class ModBinary extends AbstractBinary -{ - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('%'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/MulBinary.php b/lib/twig/twig/src/Node/Expression/Binary/MulBinary.php deleted file mode 100644 index 6d4c1e0b6..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/MulBinary.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class MulBinary extends AbstractBinary -{ - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('*'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/NotEqualBinary.php b/lib/twig/twig/src/Node/Expression/Binary/NotEqualBinary.php deleted file mode 100644 index db47a2890..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/NotEqualBinary.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class NotEqualBinary extends AbstractBinary -{ - public function compile(Compiler $compiler): void - { - if (\PHP_VERSION_ID >= 80000) { - parent::compile($compiler); - - return; - } - - $compiler - ->raw('(0 !== twig_compare(') - ->subcompile($this->getNode('left')) - ->raw(', ') - ->subcompile($this->getNode('right')) - ->raw('))') - ; - } - - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('!='); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/NotInBinary.php b/lib/twig/twig/src/Node/Expression/Binary/NotInBinary.php deleted file mode 100644 index fcba6cca1..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/NotInBinary.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class NotInBinary extends AbstractBinary -{ - public function compile(Compiler $compiler): void - { - $compiler - ->raw('!twig_in_filter(') - ->subcompile($this->getNode('left')) - ->raw(', ') - ->subcompile($this->getNode('right')) - ->raw(')') - ; - } - - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('not in'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/OrBinary.php b/lib/twig/twig/src/Node/Expression/Binary/OrBinary.php deleted file mode 100644 index 21f87c91b..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/OrBinary.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class OrBinary extends AbstractBinary -{ - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('||'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/PowerBinary.php b/lib/twig/twig/src/Node/Expression/Binary/PowerBinary.php deleted file mode 100644 index c9f4c6697..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/PowerBinary.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class PowerBinary extends AbstractBinary -{ - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('**'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/RangeBinary.php b/lib/twig/twig/src/Node/Expression/Binary/RangeBinary.php deleted file mode 100644 index 55982c819..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/RangeBinary.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class RangeBinary extends AbstractBinary -{ - public function compile(Compiler $compiler): void - { - $compiler - ->raw('range(') - ->subcompile($this->getNode('left')) - ->raw(', ') - ->subcompile($this->getNode('right')) - ->raw(')') - ; - } - - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('..'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/SpaceshipBinary.php b/lib/twig/twig/src/Node/Expression/Binary/SpaceshipBinary.php deleted file mode 100644 index ae5a4a493..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/SpaceshipBinary.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class SpaceshipBinary extends AbstractBinary -{ - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('<=>'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/StartsWithBinary.php b/lib/twig/twig/src/Node/Expression/Binary/StartsWithBinary.php deleted file mode 100644 index d0df1c4b6..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/StartsWithBinary.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class StartsWithBinary extends AbstractBinary -{ - public function compile(Compiler $compiler): void - { - $left = $compiler->getVarName(); - $right = $compiler->getVarName(); - $compiler - ->raw(sprintf('(is_string($%s = ', $left)) - ->subcompile($this->getNode('left')) - ->raw(sprintf(') && is_string($%s = ', $right)) - ->subcompile($this->getNode('right')) - ->raw(sprintf(') && (\'\' === $%2$s || 0 === strpos($%1$s, $%2$s)))', $left, $right)) - ; - } - - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw(''); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Binary/SubBinary.php b/lib/twig/twig/src/Node/Expression/Binary/SubBinary.php deleted file mode 100644 index eeb87faca..000000000 --- a/lib/twig/twig/src/Node/Expression/Binary/SubBinary.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Binary; - -use Twig\Compiler; - -class SubBinary extends AbstractBinary -{ - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('-'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/BlockReferenceExpression.php b/lib/twig/twig/src/Node/Expression/BlockReferenceExpression.php deleted file mode 100644 index b1e2a8f7b..000000000 --- a/lib/twig/twig/src/Node/Expression/BlockReferenceExpression.php +++ /dev/null @@ -1,86 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression; - -use Twig\Compiler; -use Twig\Node\Node; - -/** - * Represents a block call node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class BlockReferenceExpression extends AbstractExpression -{ - public function __construct(Node $name, ?Node $template, int $lineno, string $tag = null) - { - $nodes = ['name' => $name]; - if (null !== $template) { - $nodes['template'] = $template; - } - - parent::__construct($nodes, ['is_defined_test' => false, 'output' => false], $lineno, $tag); - } - - public function compile(Compiler $compiler): void - { - if ($this->getAttribute('is_defined_test')) { - $this->compileTemplateCall($compiler, 'hasBlock'); - } else { - if ($this->getAttribute('output')) { - $compiler->addDebugInfo($this); - - $this - ->compileTemplateCall($compiler, 'displayBlock') - ->raw(";\n"); - } else { - $this->compileTemplateCall($compiler, 'renderBlock'); - } - } - } - - private function compileTemplateCall(Compiler $compiler, string $method): Compiler - { - if (!$this->hasNode('template')) { - $compiler->write('$this'); - } else { - $compiler - ->write('$this->loadTemplate(') - ->subcompile($this->getNode('template')) - ->raw(', ') - ->repr($this->getTemplateName()) - ->raw(', ') - ->repr($this->getTemplateLine()) - ->raw(')') - ; - } - - $compiler->raw(sprintf('->%s', $method)); - - return $this->compileBlockArguments($compiler); - } - - private function compileBlockArguments(Compiler $compiler): Compiler - { - $compiler - ->raw('(') - ->subcompile($this->getNode('name')) - ->raw(', $context'); - - if (!$this->hasNode('template')) { - $compiler->raw(', $blocks'); - } - - return $compiler->raw(')'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/CallExpression.php b/lib/twig/twig/src/Node/Expression/CallExpression.php deleted file mode 100644 index 28881066b..000000000 --- a/lib/twig/twig/src/Node/Expression/CallExpression.php +++ /dev/null @@ -1,319 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression; - -use Twig\Compiler; -use Twig\Error\SyntaxError; -use Twig\Extension\ExtensionInterface; -use Twig\Node\Node; - -abstract class CallExpression extends AbstractExpression -{ - private $reflector; - - protected function compileCallable(Compiler $compiler) - { - $callable = $this->getAttribute('callable'); - - if (\is_string($callable) && false === strpos($callable, '::')) { - $compiler->raw($callable); - } else { - [$r, $callable] = $this->reflectCallable($callable); - - if (\is_string($callable)) { - $compiler->raw($callable); - } elseif (\is_array($callable) && \is_string($callable[0])) { - if (!$r instanceof \ReflectionMethod || $r->isStatic()) { - $compiler->raw(sprintf('%s::%s', $callable[0], $callable[1])); - } else { - $compiler->raw(sprintf('$this->env->getRuntime(\'%s\')->%s', $callable[0], $callable[1])); - } - } elseif (\is_array($callable) && $callable[0] instanceof ExtensionInterface) { - $class = \get_class($callable[0]); - if (!$compiler->getEnvironment()->hasExtension($class)) { - // Compile a non-optimized call to trigger a \Twig\Error\RuntimeError, which cannot be a compile-time error - $compiler->raw(sprintf('$this->env->getExtension(\'%s\')', $class)); - } else { - $compiler->raw(sprintf('$this->extensions[\'%s\']', ltrim($class, '\\'))); - } - - $compiler->raw(sprintf('->%s', $callable[1])); - } else { - $compiler->raw(sprintf('$this->env->get%s(\'%s\')->getCallable()', ucfirst($this->getAttribute('type')), $this->getAttribute('name'))); - } - } - - $this->compileArguments($compiler); - } - - protected function compileArguments(Compiler $compiler, $isArray = false): void - { - $compiler->raw($isArray ? '[' : '('); - - $first = true; - - if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) { - $compiler->raw('$this->env'); - $first = false; - } - - if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) { - if (!$first) { - $compiler->raw(', '); - } - $compiler->raw('$context'); - $first = false; - } - - if ($this->hasAttribute('arguments')) { - foreach ($this->getAttribute('arguments') as $argument) { - if (!$first) { - $compiler->raw(', '); - } - $compiler->string($argument); - $first = false; - } - } - - if ($this->hasNode('node')) { - if (!$first) { - $compiler->raw(', '); - } - $compiler->subcompile($this->getNode('node')); - $first = false; - } - - if ($this->hasNode('arguments')) { - $callable = $this->getAttribute('callable'); - $arguments = $this->getArguments($callable, $this->getNode('arguments')); - foreach ($arguments as $node) { - if (!$first) { - $compiler->raw(', '); - } - $compiler->subcompile($node); - $first = false; - } - } - - $compiler->raw($isArray ? ']' : ')'); - } - - protected function getArguments($callable, $arguments) - { - $callType = $this->getAttribute('type'); - $callName = $this->getAttribute('name'); - - $parameters = []; - $named = false; - foreach ($arguments as $name => $node) { - if (!\is_int($name)) { - $named = true; - $name = $this->normalizeName($name); - } elseif ($named) { - throw new SyntaxError(sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $callType, $callName), $this->getTemplateLine(), $this->getSourceContext()); - } - - $parameters[$name] = $node; - } - - $isVariadic = $this->hasAttribute('is_variadic') && $this->getAttribute('is_variadic'); - if (!$named && !$isVariadic) { - return $parameters; - } - - if (!$callable) { - if ($named) { - $message = sprintf('Named arguments are not supported for %s "%s".', $callType, $callName); - } else { - $message = sprintf('Arbitrary positional arguments are not supported for %s "%s".', $callType, $callName); - } - - throw new \LogicException($message); - } - - list($callableParameters, $isPhpVariadic) = $this->getCallableParameters($callable, $isVariadic); - $arguments = []; - $names = []; - $missingArguments = []; - $optionalArguments = []; - $pos = 0; - foreach ($callableParameters as $callableParameter) { - $name = $this->normalizeName($callableParameter->name); - if (\PHP_VERSION_ID >= 80000 && 'range' === $callable) { - if ('start' === $name) { - $name = 'low'; - } elseif ('end' === $name) { - $name = 'high'; - } - } - - $names[] = $name; - - if (\array_key_exists($name, $parameters)) { - if (\array_key_exists($pos, $parameters)) { - throw new SyntaxError(sprintf('Argument "%s" is defined twice for %s "%s".', $name, $callType, $callName), $this->getTemplateLine(), $this->getSourceContext()); - } - - if (\count($missingArguments)) { - throw new SyntaxError(sprintf( - 'Argument "%s" could not be assigned for %s "%s(%s)" because it is mapped to an internal PHP function which cannot determine default value for optional argument%s "%s".', - $name, $callType, $callName, implode(', ', $names), \count($missingArguments) > 1 ? 's' : '', implode('", "', $missingArguments) - ), $this->getTemplateLine(), $this->getSourceContext()); - } - - $arguments = array_merge($arguments, $optionalArguments); - $arguments[] = $parameters[$name]; - unset($parameters[$name]); - $optionalArguments = []; - } elseif (\array_key_exists($pos, $parameters)) { - $arguments = array_merge($arguments, $optionalArguments); - $arguments[] = $parameters[$pos]; - unset($parameters[$pos]); - $optionalArguments = []; - ++$pos; - } elseif ($callableParameter->isDefaultValueAvailable()) { - $optionalArguments[] = new ConstantExpression($callableParameter->getDefaultValue(), -1); - } elseif ($callableParameter->isOptional()) { - if (empty($parameters)) { - break; - } else { - $missingArguments[] = $name; - } - } else { - throw new SyntaxError(sprintf('Value for argument "%s" is required for %s "%s".', $name, $callType, $callName), $this->getTemplateLine(), $this->getSourceContext()); - } - } - - if ($isVariadic) { - $arbitraryArguments = $isPhpVariadic ? new VariadicExpression([], -1) : new ArrayExpression([], -1); - foreach ($parameters as $key => $value) { - if (\is_int($key)) { - $arbitraryArguments->addElement($value); - } else { - $arbitraryArguments->addElement($value, new ConstantExpression($key, -1)); - } - unset($parameters[$key]); - } - - if ($arbitraryArguments->count()) { - $arguments = array_merge($arguments, $optionalArguments); - $arguments[] = $arbitraryArguments; - } - } - - if (!empty($parameters)) { - $unknownParameter = null; - foreach ($parameters as $parameter) { - if ($parameter instanceof Node) { - $unknownParameter = $parameter; - break; - } - } - - throw new SyntaxError( - sprintf( - 'Unknown argument%s "%s" for %s "%s(%s)".', - \count($parameters) > 1 ? 's' : '', implode('", "', array_keys($parameters)), $callType, $callName, implode(', ', $names) - ), - $unknownParameter ? $unknownParameter->getTemplateLine() : $this->getTemplateLine(), - $unknownParameter ? $unknownParameter->getSourceContext() : $this->getSourceContext() - ); - } - - return $arguments; - } - - protected function normalizeName(string $name): string - { - return strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], ['\\1_\\2', '\\1_\\2'], $name)); - } - - private function getCallableParameters($callable, bool $isVariadic): array - { - [$r, , $callableName] = $this->reflectCallable($callable); - - $parameters = $r->getParameters(); - if ($this->hasNode('node')) { - array_shift($parameters); - } - if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) { - array_shift($parameters); - } - if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) { - array_shift($parameters); - } - if ($this->hasAttribute('arguments') && null !== $this->getAttribute('arguments')) { - foreach ($this->getAttribute('arguments') as $argument) { - array_shift($parameters); - } - } - $isPhpVariadic = false; - if ($isVariadic) { - $argument = end($parameters); - $isArray = $argument && $argument->hasType() && 'array' === $argument->getType()->getName(); - if ($isArray && $argument->isDefaultValueAvailable() && [] === $argument->getDefaultValue()) { - array_pop($parameters); - } elseif ($argument && $argument->isVariadic()) { - array_pop($parameters); - $isPhpVariadic = true; - } else { - throw new \LogicException(sprintf('The last parameter of "%s" for %s "%s" must be an array with default value, eg. "array $arg = []".', $callableName, $this->getAttribute('type'), $this->getAttribute('name'))); - } - } - - return [$parameters, $isPhpVariadic]; - } - - private function reflectCallable($callable) - { - if (null !== $this->reflector) { - return $this->reflector; - } - - if (\is_string($callable) && false !== $pos = strpos($callable, '::')) { - $callable = [substr($callable, 0, $pos), substr($callable, 2 + $pos)]; - } - - if (\is_array($callable) && method_exists($callable[0], $callable[1])) { - $r = new \ReflectionMethod($callable[0], $callable[1]); - - return $this->reflector = [$r, $callable, $r->class.'::'.$r->name]; - } - - $checkVisibility = $callable instanceof \Closure; - try { - $closure = \Closure::fromCallable($callable); - } catch (\TypeError $e) { - throw new \LogicException(sprintf('Callback for %s "%s" is not callable in the current scope.', $this->getAttribute('type'), $this->getAttribute('name')), 0, $e); - } - $r = new \ReflectionFunction($closure); - - if (false !== strpos($r->name, '{closure}')) { - return $this->reflector = [$r, $callable, 'Closure']; - } - - if ($object = $r->getClosureThis()) { - $callable = [$object, $r->name]; - $callableName = (\function_exists('get_debug_type') ? get_debug_type($object) : \get_class($object)).'::'.$r->name; - } elseif ($class = $r->getClosureScopeClass()) { - $callableName = (\is_array($callable) ? $callable[0] : $class->name).'::'.$r->name; - } else { - $callable = $callableName = $r->name; - } - - if ($checkVisibility && \is_array($callable) && method_exists(...$callable) && !(new \ReflectionMethod(...$callable))->isPublic()) { - $callable = $r->getClosure(); - } - - return $this->reflector = [$r, $callable, $callableName]; - } -} diff --git a/lib/twig/twig/src/Node/Expression/ConditionalExpression.php b/lib/twig/twig/src/Node/Expression/ConditionalExpression.php deleted file mode 100644 index 2c7bd0a27..000000000 --- a/lib/twig/twig/src/Node/Expression/ConditionalExpression.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression; - -use Twig\Compiler; - -class ConditionalExpression extends AbstractExpression -{ - public function __construct(AbstractExpression $expr1, AbstractExpression $expr2, AbstractExpression $expr3, int $lineno) - { - parent::__construct(['expr1' => $expr1, 'expr2' => $expr2, 'expr3' => $expr3], [], $lineno); - } - - public function compile(Compiler $compiler): void - { - $compiler - ->raw('((') - ->subcompile($this->getNode('expr1')) - ->raw(') ? (') - ->subcompile($this->getNode('expr2')) - ->raw(') : (') - ->subcompile($this->getNode('expr3')) - ->raw('))') - ; - } -} diff --git a/lib/twig/twig/src/Node/Expression/ConstantExpression.php b/lib/twig/twig/src/Node/Expression/ConstantExpression.php deleted file mode 100644 index 7ddbcc6fa..000000000 --- a/lib/twig/twig/src/Node/Expression/ConstantExpression.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression; - -use Twig\Compiler; - -class ConstantExpression extends AbstractExpression -{ - public function __construct($value, int $lineno) - { - parent::__construct([], ['value' => $value], $lineno); - } - - public function compile(Compiler $compiler): void - { - $compiler->repr($this->getAttribute('value')); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Filter/DefaultFilter.php b/lib/twig/twig/src/Node/Expression/Filter/DefaultFilter.php deleted file mode 100644 index 6a572d488..000000000 --- a/lib/twig/twig/src/Node/Expression/Filter/DefaultFilter.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Filter; - -use Twig\Compiler; -use Twig\Node\Expression\ConditionalExpression; -use Twig\Node\Expression\ConstantExpression; -use Twig\Node\Expression\FilterExpression; -use Twig\Node\Expression\GetAttrExpression; -use Twig\Node\Expression\NameExpression; -use Twig\Node\Expression\Test\DefinedTest; -use Twig\Node\Node; - -/** - * Returns the value or the default value when it is undefined or empty. - * - * {{ var.foo|default('foo item on var is not defined') }} - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class DefaultFilter extends FilterExpression -{ - public function __construct(Node $node, ConstantExpression $filterName, Node $arguments, int $lineno, string $tag = null) - { - $default = new FilterExpression($node, new ConstantExpression('default', $node->getTemplateLine()), $arguments, $node->getTemplateLine()); - - if ('default' === $filterName->getAttribute('value') && ($node instanceof NameExpression || $node instanceof GetAttrExpression)) { - $test = new DefinedTest(clone $node, 'defined', new Node(), $node->getTemplateLine()); - $false = \count($arguments) ? $arguments->getNode(0) : new ConstantExpression('', $node->getTemplateLine()); - - $node = new ConditionalExpression($test, $default, $false, $node->getTemplateLine()); - } else { - $node = $default; - } - - parent::__construct($node, $filterName, $arguments, $lineno, $tag); - } - - public function compile(Compiler $compiler): void - { - $compiler->subcompile($this->getNode('node')); - } -} diff --git a/lib/twig/twig/src/Node/Expression/FilterExpression.php b/lib/twig/twig/src/Node/Expression/FilterExpression.php deleted file mode 100644 index 0fc158869..000000000 --- a/lib/twig/twig/src/Node/Expression/FilterExpression.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression; - -use Twig\Compiler; -use Twig\Node\Node; - -class FilterExpression extends CallExpression -{ - public function __construct(Node $node, ConstantExpression $filterName, Node $arguments, int $lineno, string $tag = null) - { - parent::__construct(['node' => $node, 'filter' => $filterName, 'arguments' => $arguments], [], $lineno, $tag); - } - - public function compile(Compiler $compiler): void - { - $name = $this->getNode('filter')->getAttribute('value'); - $filter = $compiler->getEnvironment()->getFilter($name); - - $this->setAttribute('name', $name); - $this->setAttribute('type', 'filter'); - $this->setAttribute('needs_environment', $filter->needsEnvironment()); - $this->setAttribute('needs_context', $filter->needsContext()); - $this->setAttribute('arguments', $filter->getArguments()); - $this->setAttribute('callable', $filter->getCallable()); - $this->setAttribute('is_variadic', $filter->isVariadic()); - - $this->compileCallable($compiler); - } -} diff --git a/lib/twig/twig/src/Node/Expression/FunctionExpression.php b/lib/twig/twig/src/Node/Expression/FunctionExpression.php deleted file mode 100644 index 71269775c..000000000 --- a/lib/twig/twig/src/Node/Expression/FunctionExpression.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression; - -use Twig\Compiler; -use Twig\Node\Node; - -class FunctionExpression extends CallExpression -{ - public function __construct(string $name, Node $arguments, int $lineno) - { - parent::__construct(['arguments' => $arguments], ['name' => $name, 'is_defined_test' => false], $lineno); - } - - public function compile(Compiler $compiler) - { - $name = $this->getAttribute('name'); - $function = $compiler->getEnvironment()->getFunction($name); - - $this->setAttribute('name', $name); - $this->setAttribute('type', 'function'); - $this->setAttribute('needs_environment', $function->needsEnvironment()); - $this->setAttribute('needs_context', $function->needsContext()); - $this->setAttribute('arguments', $function->getArguments()); - $callable = $function->getCallable(); - if ('constant' === $name && $this->getAttribute('is_defined_test')) { - $callable = 'twig_constant_is_defined'; - } - $this->setAttribute('callable', $callable); - $this->setAttribute('is_variadic', $function->isVariadic()); - - $this->compileCallable($compiler); - } -} diff --git a/lib/twig/twig/src/Node/Expression/GetAttrExpression.php b/lib/twig/twig/src/Node/Expression/GetAttrExpression.php deleted file mode 100644 index e6a75ce94..000000000 --- a/lib/twig/twig/src/Node/Expression/GetAttrExpression.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression; - -use Twig\Compiler; -use Twig\Extension\SandboxExtension; -use Twig\Template; - -class GetAttrExpression extends AbstractExpression -{ - public function __construct(AbstractExpression $node, AbstractExpression $attribute, ?AbstractExpression $arguments, string $type, int $lineno) - { - $nodes = ['node' => $node, 'attribute' => $attribute]; - if (null !== $arguments) { - $nodes['arguments'] = $arguments; - } - - parent::__construct($nodes, ['type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false, 'optimizable' => true], $lineno); - } - - public function compile(Compiler $compiler): void - { - $env = $compiler->getEnvironment(); - - // optimize array calls - if ( - $this->getAttribute('optimizable') - && (!$env->isStrictVariables() || $this->getAttribute('ignore_strict_check')) - && !$this->getAttribute('is_defined_test') - && Template::ARRAY_CALL === $this->getAttribute('type') - ) { - $var = '$'.$compiler->getVarName(); - $compiler - ->raw('(('.$var.' = ') - ->subcompile($this->getNode('node')) - ->raw(') && is_array(') - ->raw($var) - ->raw(') || ') - ->raw($var) - ->raw(' instanceof ArrayAccess ? (') - ->raw($var) - ->raw('[') - ->subcompile($this->getNode('attribute')) - ->raw('] ?? null) : null)') - ; - - return; - } - - $compiler->raw('twig_get_attribute($this->env, $this->source, '); - - if ($this->getAttribute('ignore_strict_check')) { - $this->getNode('node')->setAttribute('ignore_strict_check', true); - } - - $compiler - ->subcompile($this->getNode('node')) - ->raw(', ') - ->subcompile($this->getNode('attribute')) - ; - - if ($this->hasNode('arguments')) { - $compiler->raw(', ')->subcompile($this->getNode('arguments')); - } else { - $compiler->raw(', []'); - } - - $compiler->raw(', ') - ->repr($this->getAttribute('type')) - ->raw(', ')->repr($this->getAttribute('is_defined_test')) - ->raw(', ')->repr($this->getAttribute('ignore_strict_check')) - ->raw(', ')->repr($env->hasExtension(SandboxExtension::class)) - ->raw(', ')->repr($this->getNode('node')->getTemplateLine()) - ->raw(')') - ; - } -} diff --git a/lib/twig/twig/src/Node/Expression/InlinePrint.php b/lib/twig/twig/src/Node/Expression/InlinePrint.php deleted file mode 100644 index 1ad4751e4..000000000 --- a/lib/twig/twig/src/Node/Expression/InlinePrint.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression; - -use Twig\Compiler; -use Twig\Node\Node; - -/** - * @internal - */ -final class InlinePrint extends AbstractExpression -{ - public function __construct(Node $node, int $lineno) - { - parent::__construct(['node' => $node], [], $lineno); - } - - public function compile(Compiler $compiler): void - { - $compiler - ->raw('print (') - ->subcompile($this->getNode('node')) - ->raw(')') - ; - } -} diff --git a/lib/twig/twig/src/Node/Expression/MethodCallExpression.php b/lib/twig/twig/src/Node/Expression/MethodCallExpression.php deleted file mode 100644 index d5ec0b6ef..000000000 --- a/lib/twig/twig/src/Node/Expression/MethodCallExpression.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression; - -use Twig\Compiler; - -class MethodCallExpression extends AbstractExpression -{ - public function __construct(AbstractExpression $node, string $method, ArrayExpression $arguments, int $lineno) - { - parent::__construct(['node' => $node, 'arguments' => $arguments], ['method' => $method, 'safe' => false, 'is_defined_test' => false], $lineno); - - if ($node instanceof NameExpression) { - $node->setAttribute('always_defined', true); - } - } - - public function compile(Compiler $compiler): void - { - if ($this->getAttribute('is_defined_test')) { - $compiler - ->raw('method_exists($macros[') - ->repr($this->getNode('node')->getAttribute('name')) - ->raw('], ') - ->repr($this->getAttribute('method')) - ->raw(')') - ; - - return; - } - - $compiler - ->raw('twig_call_macro($macros[') - ->repr($this->getNode('node')->getAttribute('name')) - ->raw('], ') - ->repr($this->getAttribute('method')) - ->raw(', [') - ; - $first = true; - foreach ($this->getNode('arguments')->getKeyValuePairs() as $pair) { - if (!$first) { - $compiler->raw(', '); - } - $first = false; - - $compiler->subcompile($pair['value']); - } - $compiler - ->raw('], ') - ->repr($this->getTemplateLine()) - ->raw(', $context, $this->getSourceContext())'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/NameExpression.php b/lib/twig/twig/src/Node/Expression/NameExpression.php deleted file mode 100644 index c3563f012..000000000 --- a/lib/twig/twig/src/Node/Expression/NameExpression.php +++ /dev/null @@ -1,97 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression; - -use Twig\Compiler; - -class NameExpression extends AbstractExpression -{ - private $specialVars = [ - '_self' => '$this->getTemplateName()', - '_context' => '$context', - '_charset' => '$this->env->getCharset()', - ]; - - public function __construct(string $name, int $lineno) - { - parent::__construct([], ['name' => $name, 'is_defined_test' => false, 'ignore_strict_check' => false, 'always_defined' => false], $lineno); - } - - public function compile(Compiler $compiler): void - { - $name = $this->getAttribute('name'); - - $compiler->addDebugInfo($this); - - if ($this->getAttribute('is_defined_test')) { - if ($this->isSpecial()) { - $compiler->repr(true); - } elseif (\PHP_VERSION_ID >= 70400) { - $compiler - ->raw('array_key_exists(') - ->string($name) - ->raw(', $context)') - ; - } else { - $compiler - ->raw('(isset($context[') - ->string($name) - ->raw(']) || array_key_exists(') - ->string($name) - ->raw(', $context))') - ; - } - } elseif ($this->isSpecial()) { - $compiler->raw($this->specialVars[$name]); - } elseif ($this->getAttribute('always_defined')) { - $compiler - ->raw('$context[') - ->string($name) - ->raw(']') - ; - } else { - if ($this->getAttribute('ignore_strict_check') || !$compiler->getEnvironment()->isStrictVariables()) { - $compiler - ->raw('($context[') - ->string($name) - ->raw('] ?? null)') - ; - } else { - $compiler - ->raw('(isset($context[') - ->string($name) - ->raw(']) || array_key_exists(') - ->string($name) - ->raw(', $context) ? $context[') - ->string($name) - ->raw('] : (function () { throw new RuntimeError(\'Variable ') - ->string($name) - ->raw(' does not exist.\', ') - ->repr($this->lineno) - ->raw(', $this->source); })()') - ->raw(')') - ; - } - } - } - - public function isSpecial() - { - return isset($this->specialVars[$this->getAttribute('name')]); - } - - public function isSimple() - { - return !$this->isSpecial() && !$this->getAttribute('is_defined_test'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/NullCoalesceExpression.php b/lib/twig/twig/src/Node/Expression/NullCoalesceExpression.php deleted file mode 100644 index a72bc4fc6..000000000 --- a/lib/twig/twig/src/Node/Expression/NullCoalesceExpression.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression; - -use Twig\Compiler; -use Twig\Node\Expression\Binary\AndBinary; -use Twig\Node\Expression\Test\DefinedTest; -use Twig\Node\Expression\Test\NullTest; -use Twig\Node\Expression\Unary\NotUnary; -use Twig\Node\Node; - -class NullCoalesceExpression extends ConditionalExpression -{ - public function __construct(Node $left, Node $right, int $lineno) - { - $test = new DefinedTest(clone $left, 'defined', new Node(), $left->getTemplateLine()); - // for "block()", we don't need the null test as the return value is always a string - if (!$left instanceof BlockReferenceExpression) { - $test = new AndBinary( - $test, - new NotUnary(new NullTest($left, 'null', new Node(), $left->getTemplateLine()), $left->getTemplateLine()), - $left->getTemplateLine() - ); - } - - parent::__construct($test, $left, $right, $lineno); - } - - public function compile(Compiler $compiler): void - { - /* - * This optimizes only one case. PHP 7 also supports more complex expressions - * that can return null. So, for instance, if log is defined, log("foo") ?? "..." works, - * but log($a["foo"]) ?? "..." does not if $a["foo"] is not defined. More advanced - * cases might be implemented as an optimizer node visitor, but has not been done - * as benefits are probably not worth the added complexity. - */ - if ($this->getNode('expr2') instanceof NameExpression) { - $this->getNode('expr2')->setAttribute('always_defined', true); - $compiler - ->raw('((') - ->subcompile($this->getNode('expr2')) - ->raw(') ?? (') - ->subcompile($this->getNode('expr3')) - ->raw('))') - ; - } else { - parent::compile($compiler); - } - } -} diff --git a/lib/twig/twig/src/Node/Expression/ParentExpression.php b/lib/twig/twig/src/Node/Expression/ParentExpression.php deleted file mode 100644 index 254919718..000000000 --- a/lib/twig/twig/src/Node/Expression/ParentExpression.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression; - -use Twig\Compiler; - -/** - * Represents a parent node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class ParentExpression extends AbstractExpression -{ - public function __construct(string $name, int $lineno, string $tag = null) - { - parent::__construct([], ['output' => false, 'name' => $name], $lineno, $tag); - } - - public function compile(Compiler $compiler): void - { - if ($this->getAttribute('output')) { - $compiler - ->addDebugInfo($this) - ->write('$this->displayParentBlock(') - ->string($this->getAttribute('name')) - ->raw(", \$context, \$blocks);\n") - ; - } else { - $compiler - ->raw('$this->renderParentBlock(') - ->string($this->getAttribute('name')) - ->raw(', $context, $blocks)') - ; - } - } -} diff --git a/lib/twig/twig/src/Node/Expression/TempNameExpression.php b/lib/twig/twig/src/Node/Expression/TempNameExpression.php deleted file mode 100644 index 004c704a5..000000000 --- a/lib/twig/twig/src/Node/Expression/TempNameExpression.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression; - -use Twig\Compiler; - -class TempNameExpression extends AbstractExpression -{ - public function __construct(string $name, int $lineno) - { - parent::__construct([], ['name' => $name], $lineno); - } - - public function compile(Compiler $compiler): void - { - $compiler - ->raw('$_') - ->raw($this->getAttribute('name')) - ->raw('_') - ; - } -} diff --git a/lib/twig/twig/src/Node/Expression/Test/ConstantTest.php b/lib/twig/twig/src/Node/Expression/Test/ConstantTest.php deleted file mode 100644 index 57e9319d5..000000000 --- a/lib/twig/twig/src/Node/Expression/Test/ConstantTest.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Test; - -use Twig\Compiler; -use Twig\Node\Expression\TestExpression; - -/** - * Checks if a variable is the exact same value as a constant. - * - * {% if post.status is constant('Post::PUBLISHED') %} - * the status attribute is exactly the same as Post::PUBLISHED - * {% endif %} - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class ConstantTest extends TestExpression -{ - public function compile(Compiler $compiler): void - { - $compiler - ->raw('(') - ->subcompile($this->getNode('node')) - ->raw(' === constant(') - ; - - if ($this->getNode('arguments')->hasNode(1)) { - $compiler - ->raw('get_class(') - ->subcompile($this->getNode('arguments')->getNode(1)) - ->raw(')."::".') - ; - } - - $compiler - ->subcompile($this->getNode('arguments')->getNode(0)) - ->raw('))') - ; - } -} diff --git a/lib/twig/twig/src/Node/Expression/Test/DefinedTest.php b/lib/twig/twig/src/Node/Expression/Test/DefinedTest.php deleted file mode 100644 index 3953bbbe2..000000000 --- a/lib/twig/twig/src/Node/Expression/Test/DefinedTest.php +++ /dev/null @@ -1,74 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Test; - -use Twig\Compiler; -use Twig\Error\SyntaxError; -use Twig\Node\Expression\ArrayExpression; -use Twig\Node\Expression\BlockReferenceExpression; -use Twig\Node\Expression\ConstantExpression; -use Twig\Node\Expression\FunctionExpression; -use Twig\Node\Expression\GetAttrExpression; -use Twig\Node\Expression\MethodCallExpression; -use Twig\Node\Expression\NameExpression; -use Twig\Node\Expression\TestExpression; -use Twig\Node\Node; - -/** - * Checks if a variable is defined in the current context. - * - * {# defined works with variable names and variable attributes #} - * {% if foo is defined %} - * {# ... #} - * {% endif %} - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class DefinedTest extends TestExpression -{ - public function __construct(Node $node, string $name, ?Node $arguments, int $lineno) - { - if ($node instanceof NameExpression) { - $node->setAttribute('is_defined_test', true); - } elseif ($node instanceof GetAttrExpression) { - $node->setAttribute('is_defined_test', true); - $this->changeIgnoreStrictCheck($node); - } elseif ($node instanceof BlockReferenceExpression) { - $node->setAttribute('is_defined_test', true); - } elseif ($node instanceof FunctionExpression && 'constant' === $node->getAttribute('name')) { - $node->setAttribute('is_defined_test', true); - } elseif ($node instanceof ConstantExpression || $node instanceof ArrayExpression) { - $node = new ConstantExpression(true, $node->getTemplateLine()); - } elseif ($node instanceof MethodCallExpression) { - $node->setAttribute('is_defined_test', true); - } else { - throw new SyntaxError('The "defined" test only works with simple variables.', $lineno); - } - - parent::__construct($node, $name, $arguments, $lineno); - } - - private function changeIgnoreStrictCheck(GetAttrExpression $node) - { - $node->setAttribute('optimizable', false); - $node->setAttribute('ignore_strict_check', true); - - if ($node->getNode('node') instanceof GetAttrExpression) { - $this->changeIgnoreStrictCheck($node->getNode('node')); - } - } - - public function compile(Compiler $compiler): void - { - $compiler->subcompile($this->getNode('node')); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Test/DivisiblebyTest.php b/lib/twig/twig/src/Node/Expression/Test/DivisiblebyTest.php deleted file mode 100644 index 4cb3ee096..000000000 --- a/lib/twig/twig/src/Node/Expression/Test/DivisiblebyTest.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Test; - -use Twig\Compiler; -use Twig\Node\Expression\TestExpression; - -/** - * Checks if a variable is divisible by a number. - * - * {% if loop.index is divisible by(3) %} - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class DivisiblebyTest extends TestExpression -{ - public function compile(Compiler $compiler): void - { - $compiler - ->raw('(0 == ') - ->subcompile($this->getNode('node')) - ->raw(' % ') - ->subcompile($this->getNode('arguments')->getNode(0)) - ->raw(')') - ; - } -} diff --git a/lib/twig/twig/src/Node/Expression/Test/EvenTest.php b/lib/twig/twig/src/Node/Expression/Test/EvenTest.php deleted file mode 100644 index a0e3ed62c..000000000 --- a/lib/twig/twig/src/Node/Expression/Test/EvenTest.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Test; - -use Twig\Compiler; -use Twig\Node\Expression\TestExpression; - -/** - * Checks if a number is even. - * - * {{ var is even }} - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class EvenTest extends TestExpression -{ - public function compile(Compiler $compiler): void - { - $compiler - ->raw('(') - ->subcompile($this->getNode('node')) - ->raw(' % 2 == 0') - ->raw(')') - ; - } -} diff --git a/lib/twig/twig/src/Node/Expression/Test/NullTest.php b/lib/twig/twig/src/Node/Expression/Test/NullTest.php deleted file mode 100644 index 45b54ae37..000000000 --- a/lib/twig/twig/src/Node/Expression/Test/NullTest.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Test; - -use Twig\Compiler; -use Twig\Node\Expression\TestExpression; - -/** - * Checks that a variable is null. - * - * {{ var is none }} - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class NullTest extends TestExpression -{ - public function compile(Compiler $compiler): void - { - $compiler - ->raw('(null === ') - ->subcompile($this->getNode('node')) - ->raw(')') - ; - } -} diff --git a/lib/twig/twig/src/Node/Expression/Test/OddTest.php b/lib/twig/twig/src/Node/Expression/Test/OddTest.php deleted file mode 100644 index d56c71116..000000000 --- a/lib/twig/twig/src/Node/Expression/Test/OddTest.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Test; - -use Twig\Compiler; -use Twig\Node\Expression\TestExpression; - -/** - * Checks if a number is odd. - * - * {{ var is odd }} - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class OddTest extends TestExpression -{ - public function compile(Compiler $compiler): void - { - $compiler - ->raw('(') - ->subcompile($this->getNode('node')) - ->raw(' % 2 != 0') - ->raw(')') - ; - } -} diff --git a/lib/twig/twig/src/Node/Expression/Test/SameasTest.php b/lib/twig/twig/src/Node/Expression/Test/SameasTest.php deleted file mode 100644 index c96d2bc01..000000000 --- a/lib/twig/twig/src/Node/Expression/Test/SameasTest.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Test; - -use Twig\Compiler; -use Twig\Node\Expression\TestExpression; - -/** - * Checks if a variable is the same as another one (=== in PHP). - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class SameasTest extends TestExpression -{ - public function compile(Compiler $compiler): void - { - $compiler - ->raw('(') - ->subcompile($this->getNode('node')) - ->raw(' === ') - ->subcompile($this->getNode('arguments')->getNode(0)) - ->raw(')') - ; - } -} diff --git a/lib/twig/twig/src/Node/Expression/TestExpression.php b/lib/twig/twig/src/Node/Expression/TestExpression.php deleted file mode 100644 index e518bd8f1..000000000 --- a/lib/twig/twig/src/Node/Expression/TestExpression.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression; - -use Twig\Compiler; -use Twig\Node\Node; - -class TestExpression extends CallExpression -{ - public function __construct(Node $node, string $name, ?Node $arguments, int $lineno) - { - $nodes = ['node' => $node]; - if (null !== $arguments) { - $nodes['arguments'] = $arguments; - } - - parent::__construct($nodes, ['name' => $name], $lineno); - } - - public function compile(Compiler $compiler): void - { - $name = $this->getAttribute('name'); - $test = $compiler->getEnvironment()->getTest($name); - - $this->setAttribute('name', $name); - $this->setAttribute('type', 'test'); - $this->setAttribute('arguments', $test->getArguments()); - $this->setAttribute('callable', $test->getCallable()); - $this->setAttribute('is_variadic', $test->isVariadic()); - - $this->compileCallable($compiler); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Unary/AbstractUnary.php b/lib/twig/twig/src/Node/Expression/Unary/AbstractUnary.php deleted file mode 100644 index e31e3f84b..000000000 --- a/lib/twig/twig/src/Node/Expression/Unary/AbstractUnary.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Unary; - -use Twig\Compiler; -use Twig\Node\Expression\AbstractExpression; -use Twig\Node\Node; - -abstract class AbstractUnary extends AbstractExpression -{ - public function __construct(Node $node, int $lineno) - { - parent::__construct(['node' => $node], [], $lineno); - } - - public function compile(Compiler $compiler): void - { - $compiler->raw(' '); - $this->operator($compiler); - $compiler->subcompile($this->getNode('node')); - } - - abstract public function operator(Compiler $compiler): Compiler; -} diff --git a/lib/twig/twig/src/Node/Expression/Unary/NegUnary.php b/lib/twig/twig/src/Node/Expression/Unary/NegUnary.php deleted file mode 100644 index dc2f2350a..000000000 --- a/lib/twig/twig/src/Node/Expression/Unary/NegUnary.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Unary; - -use Twig\Compiler; - -class NegUnary extends AbstractUnary -{ - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('-'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Unary/NotUnary.php b/lib/twig/twig/src/Node/Expression/Unary/NotUnary.php deleted file mode 100644 index 55c11bacf..000000000 --- a/lib/twig/twig/src/Node/Expression/Unary/NotUnary.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Unary; - -use Twig\Compiler; - -class NotUnary extends AbstractUnary -{ - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('!'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/Unary/PosUnary.php b/lib/twig/twig/src/Node/Expression/Unary/PosUnary.php deleted file mode 100644 index 4b0a06208..000000000 --- a/lib/twig/twig/src/Node/Expression/Unary/PosUnary.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression\Unary; - -use Twig\Compiler; - -class PosUnary extends AbstractUnary -{ - public function operator(Compiler $compiler): Compiler - { - return $compiler->raw('+'); - } -} diff --git a/lib/twig/twig/src/Node/Expression/VariadicExpression.php b/lib/twig/twig/src/Node/Expression/VariadicExpression.php deleted file mode 100644 index a1bdb48c2..000000000 --- a/lib/twig/twig/src/Node/Expression/VariadicExpression.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node\Expression; - -use Twig\Compiler; - -class VariadicExpression extends ArrayExpression -{ - public function compile(Compiler $compiler): void - { - $compiler->raw('...'); - - parent::compile($compiler); - } -} diff --git a/lib/twig/twig/src/Node/FlushNode.php b/lib/twig/twig/src/Node/FlushNode.php deleted file mode 100644 index fa50a88ee..000000000 --- a/lib/twig/twig/src/Node/FlushNode.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -use Twig\Compiler; - -/** - * Represents a flush node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class FlushNode extends Node -{ - public function __construct(int $lineno, string $tag) - { - parent::__construct([], [], $lineno, $tag); - } - - public function compile(Compiler $compiler): void - { - $compiler - ->addDebugInfo($this) - ->write("flush();\n") - ; - } -} diff --git a/lib/twig/twig/src/Node/ForLoopNode.php b/lib/twig/twig/src/Node/ForLoopNode.php deleted file mode 100644 index d5ce845a7..000000000 --- a/lib/twig/twig/src/Node/ForLoopNode.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -use Twig\Compiler; - -/** - * Internal node used by the for node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class ForLoopNode extends Node -{ - public function __construct(int $lineno, string $tag = null) - { - parent::__construct([], ['with_loop' => false, 'ifexpr' => false, 'else' => false], $lineno, $tag); - } - - public function compile(Compiler $compiler): void - { - if ($this->getAttribute('else')) { - $compiler->write("\$context['_iterated'] = true;\n"); - } - - if ($this->getAttribute('with_loop')) { - $compiler - ->write("++\$context['loop']['index0'];\n") - ->write("++\$context['loop']['index'];\n") - ->write("\$context['loop']['first'] = false;\n") - ->write("if (isset(\$context['loop']['length'])) {\n") - ->indent() - ->write("--\$context['loop']['revindex0'];\n") - ->write("--\$context['loop']['revindex'];\n") - ->write("\$context['loop']['last'] = 0 === \$context['loop']['revindex0'];\n") - ->outdent() - ->write("}\n") - ; - } - } -} diff --git a/lib/twig/twig/src/Node/ForNode.php b/lib/twig/twig/src/Node/ForNode.php deleted file mode 100644 index 04addfbfe..000000000 --- a/lib/twig/twig/src/Node/ForNode.php +++ /dev/null @@ -1,107 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -use Twig\Compiler; -use Twig\Node\Expression\AbstractExpression; -use Twig\Node\Expression\AssignNameExpression; - -/** - * Represents a for node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class ForNode extends Node -{ - private $loop; - - public function __construct(AssignNameExpression $keyTarget, AssignNameExpression $valueTarget, AbstractExpression $seq, ?Node $ifexpr, Node $body, ?Node $else, int $lineno, string $tag = null) - { - $body = new Node([$body, $this->loop = new ForLoopNode($lineno, $tag)]); - - $nodes = ['key_target' => $keyTarget, 'value_target' => $valueTarget, 'seq' => $seq, 'body' => $body]; - if (null !== $else) { - $nodes['else'] = $else; - } - - parent::__construct($nodes, ['with_loop' => true], $lineno, $tag); - } - - public function compile(Compiler $compiler): void - { - $compiler - ->addDebugInfo($this) - ->write("\$context['_parent'] = \$context;\n") - ->write("\$context['_seq'] = twig_ensure_traversable(") - ->subcompile($this->getNode('seq')) - ->raw(");\n") - ; - - if ($this->hasNode('else')) { - $compiler->write("\$context['_iterated'] = false;\n"); - } - - if ($this->getAttribute('with_loop')) { - $compiler - ->write("\$context['loop'] = [\n") - ->write(" 'parent' => \$context['_parent'],\n") - ->write(" 'index0' => 0,\n") - ->write(" 'index' => 1,\n") - ->write(" 'first' => true,\n") - ->write("];\n") - ->write("if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_seq'] instanceof \Countable)) {\n") - ->indent() - ->write("\$length = count(\$context['_seq']);\n") - ->write("\$context['loop']['revindex0'] = \$length - 1;\n") - ->write("\$context['loop']['revindex'] = \$length;\n") - ->write("\$context['loop']['length'] = \$length;\n") - ->write("\$context['loop']['last'] = 1 === \$length;\n") - ->outdent() - ->write("}\n") - ; - } - - $this->loop->setAttribute('else', $this->hasNode('else')); - $this->loop->setAttribute('with_loop', $this->getAttribute('with_loop')); - - $compiler - ->write("foreach (\$context['_seq'] as ") - ->subcompile($this->getNode('key_target')) - ->raw(' => ') - ->subcompile($this->getNode('value_target')) - ->raw(") {\n") - ->indent() - ->subcompile($this->getNode('body')) - ->outdent() - ->write("}\n") - ; - - if ($this->hasNode('else')) { - $compiler - ->write("if (!\$context['_iterated']) {\n") - ->indent() - ->subcompile($this->getNode('else')) - ->outdent() - ->write("}\n") - ; - } - - $compiler->write("\$_parent = \$context['_parent'];\n"); - - // remove some "private" loop variables (needed for nested loops) - $compiler->write('unset($context[\'_seq\'], $context[\'_iterated\'], $context[\''.$this->getNode('key_target')->getAttribute('name').'\'], $context[\''.$this->getNode('value_target')->getAttribute('name').'\'], $context[\'_parent\'], $context[\'loop\']);'."\n"); - - // keep the values set in the inner context for variables defined in the outer context - $compiler->write("\$context = array_intersect_key(\$context, \$_parent) + \$_parent;\n"); - } -} diff --git a/lib/twig/twig/src/Node/IfNode.php b/lib/twig/twig/src/Node/IfNode.php deleted file mode 100644 index 5fa20082a..000000000 --- a/lib/twig/twig/src/Node/IfNode.php +++ /dev/null @@ -1,70 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -use Twig\Compiler; - -/** - * Represents an if node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class IfNode extends Node -{ - public function __construct(Node $tests, ?Node $else, int $lineno, string $tag = null) - { - $nodes = ['tests' => $tests]; - if (null !== $else) { - $nodes['else'] = $else; - } - - parent::__construct($nodes, [], $lineno, $tag); - } - - public function compile(Compiler $compiler): void - { - $compiler->addDebugInfo($this); - for ($i = 0, $count = \count($this->getNode('tests')); $i < $count; $i += 2) { - if ($i > 0) { - $compiler - ->outdent() - ->write('} elseif (') - ; - } else { - $compiler - ->write('if (') - ; - } - - $compiler - ->subcompile($this->getNode('tests')->getNode($i)) - ->raw(") {\n") - ->indent() - ->subcompile($this->getNode('tests')->getNode($i + 1)) - ; - } - - if ($this->hasNode('else')) { - $compiler - ->outdent() - ->write("} else {\n") - ->indent() - ->subcompile($this->getNode('else')) - ; - } - - $compiler - ->outdent() - ->write("}\n"); - } -} diff --git a/lib/twig/twig/src/Node/ImportNode.php b/lib/twig/twig/src/Node/ImportNode.php deleted file mode 100644 index 5378d799e..000000000 --- a/lib/twig/twig/src/Node/ImportNode.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -use Twig\Compiler; -use Twig\Node\Expression\AbstractExpression; -use Twig\Node\Expression\NameExpression; - -/** - * Represents an import node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class ImportNode extends Node -{ - public function __construct(AbstractExpression $expr, AbstractExpression $var, int $lineno, string $tag = null, bool $global = true) - { - parent::__construct(['expr' => $expr, 'var' => $var], ['global' => $global], $lineno, $tag); - } - - public function compile(Compiler $compiler): void - { - $compiler - ->addDebugInfo($this) - ->write('$macros[') - ->repr($this->getNode('var')->getAttribute('name')) - ->raw('] = ') - ; - - if ($this->getAttribute('global')) { - $compiler - ->raw('$this->macros[') - ->repr($this->getNode('var')->getAttribute('name')) - ->raw('] = ') - ; - } - - if ($this->getNode('expr') instanceof NameExpression && '_self' === $this->getNode('expr')->getAttribute('name')) { - $compiler->raw('$this'); - } else { - $compiler - ->raw('$this->loadTemplate(') - ->subcompile($this->getNode('expr')) - ->raw(', ') - ->repr($this->getTemplateName()) - ->raw(', ') - ->repr($this->getTemplateLine()) - ->raw(')->unwrap()') - ; - } - - $compiler->raw(";\n"); - } -} diff --git a/lib/twig/twig/src/Node/IncludeNode.php b/lib/twig/twig/src/Node/IncludeNode.php deleted file mode 100644 index d540d6b23..000000000 --- a/lib/twig/twig/src/Node/IncludeNode.php +++ /dev/null @@ -1,106 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -use Twig\Compiler; -use Twig\Node\Expression\AbstractExpression; - -/** - * Represents an include node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class IncludeNode extends Node implements NodeOutputInterface -{ - public function __construct(AbstractExpression $expr, ?AbstractExpression $variables, bool $only, bool $ignoreMissing, int $lineno, string $tag = null) - { - $nodes = ['expr' => $expr]; - if (null !== $variables) { - $nodes['variables'] = $variables; - } - - parent::__construct($nodes, ['only' => $only, 'ignore_missing' => $ignoreMissing], $lineno, $tag); - } - - public function compile(Compiler $compiler): void - { - $compiler->addDebugInfo($this); - - if ($this->getAttribute('ignore_missing')) { - $template = $compiler->getVarName(); - - $compiler - ->write(sprintf("$%s = null;\n", $template)) - ->write("try {\n") - ->indent() - ->write(sprintf('$%s = ', $template)) - ; - - $this->addGetTemplate($compiler); - - $compiler - ->raw(";\n") - ->outdent() - ->write("} catch (LoaderError \$e) {\n") - ->indent() - ->write("// ignore missing template\n") - ->outdent() - ->write("}\n") - ->write(sprintf("if ($%s) {\n", $template)) - ->indent() - ->write(sprintf('$%s->display(', $template)) - ; - $this->addTemplateArguments($compiler); - $compiler - ->raw(");\n") - ->outdent() - ->write("}\n") - ; - } else { - $this->addGetTemplate($compiler); - $compiler->raw('->display('); - $this->addTemplateArguments($compiler); - $compiler->raw(");\n"); - } - } - - protected function addGetTemplate(Compiler $compiler) - { - $compiler - ->write('$this->loadTemplate(') - ->subcompile($this->getNode('expr')) - ->raw(', ') - ->repr($this->getTemplateName()) - ->raw(', ') - ->repr($this->getTemplateLine()) - ->raw(')') - ; - } - - protected function addTemplateArguments(Compiler $compiler) - { - if (!$this->hasNode('variables')) { - $compiler->raw(false === $this->getAttribute('only') ? '$context' : '[]'); - } elseif (false === $this->getAttribute('only')) { - $compiler - ->raw('twig_array_merge($context, ') - ->subcompile($this->getNode('variables')) - ->raw(')') - ; - } else { - $compiler->raw('twig_to_array('); - $compiler->subcompile($this->getNode('variables')); - $compiler->raw(')'); - } - } -} diff --git a/lib/twig/twig/src/Node/MacroNode.php b/lib/twig/twig/src/Node/MacroNode.php deleted file mode 100644 index 7f1b24d53..000000000 --- a/lib/twig/twig/src/Node/MacroNode.php +++ /dev/null @@ -1,113 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -use Twig\Compiler; -use Twig\Error\SyntaxError; - -/** - * Represents a macro node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class MacroNode extends Node -{ - public const VARARGS_NAME = 'varargs'; - - public function __construct(string $name, Node $body, Node $arguments, int $lineno, string $tag = null) - { - foreach ($arguments as $argumentName => $argument) { - if (self::VARARGS_NAME === $argumentName) { - throw new SyntaxError(sprintf('The argument "%s" in macro "%s" cannot be defined because the variable "%s" is reserved for arbitrary arguments.', self::VARARGS_NAME, $name, self::VARARGS_NAME), $argument->getTemplateLine(), $argument->getSourceContext()); - } - } - - parent::__construct(['body' => $body, 'arguments' => $arguments], ['name' => $name], $lineno, $tag); - } - - public function compile(Compiler $compiler): void - { - $compiler - ->addDebugInfo($this) - ->write(sprintf('public function macro_%s(', $this->getAttribute('name'))) - ; - - $count = \count($this->getNode('arguments')); - $pos = 0; - foreach ($this->getNode('arguments') as $name => $default) { - $compiler - ->raw('$__'.$name.'__ = ') - ->subcompile($default) - ; - - if (++$pos < $count) { - $compiler->raw(', '); - } - } - - if ($count) { - $compiler->raw(', '); - } - - $compiler - ->raw('...$__varargs__') - ->raw(")\n") - ->write("{\n") - ->indent() - ->write("\$macros = \$this->macros;\n") - ->write("\$context = \$this->env->mergeGlobals([\n") - ->indent() - ; - - foreach ($this->getNode('arguments') as $name => $default) { - $compiler - ->write('') - ->string($name) - ->raw(' => $__'.$name.'__') - ->raw(",\n") - ; - } - - $compiler - ->write('') - ->string(self::VARARGS_NAME) - ->raw(' => ') - ; - - $compiler - ->raw("\$__varargs__,\n") - ->outdent() - ->write("]);\n\n") - ->write("\$blocks = [];\n\n") - ; - if ($compiler->getEnvironment()->isDebug()) { - $compiler->write("ob_start();\n"); - } else { - $compiler->write("ob_start(function () { return ''; });\n"); - } - $compiler - ->write("try {\n") - ->indent() - ->subcompile($this->getNode('body')) - ->raw("\n") - ->write("return ('' === \$tmp = ob_get_contents()) ? '' : new Markup(\$tmp, \$this->env->getCharset());\n") - ->outdent() - ->write("} finally {\n") - ->indent() - ->write("ob_end_clean();\n") - ->outdent() - ->write("}\n") - ->outdent() - ->write("}\n\n") - ; - } -} diff --git a/lib/twig/twig/src/Node/ModuleNode.php b/lib/twig/twig/src/Node/ModuleNode.php deleted file mode 100644 index e972b6ba5..000000000 --- a/lib/twig/twig/src/Node/ModuleNode.php +++ /dev/null @@ -1,464 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -use Twig\Compiler; -use Twig\Node\Expression\AbstractExpression; -use Twig\Node\Expression\ConstantExpression; -use Twig\Source; - -/** - * Represents a module node. - * - * Consider this class as being final. If you need to customize the behavior of - * the generated class, consider adding nodes to the following nodes: display_start, - * display_end, constructor_start, constructor_end, and class_end. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class ModuleNode extends Node -{ - public function __construct(Node $body, ?AbstractExpression $parent, Node $blocks, Node $macros, Node $traits, $embeddedTemplates, Source $source) - { - $nodes = [ - 'body' => $body, - 'blocks' => $blocks, - 'macros' => $macros, - 'traits' => $traits, - 'display_start' => new Node(), - 'display_end' => new Node(), - 'constructor_start' => new Node(), - 'constructor_end' => new Node(), - 'class_end' => new Node(), - ]; - if (null !== $parent) { - $nodes['parent'] = $parent; - } - - // embedded templates are set as attributes so that they are only visited once by the visitors - parent::__construct($nodes, [ - 'index' => null, - 'embedded_templates' => $embeddedTemplates, - ], 1); - - // populate the template name of all node children - $this->setSourceContext($source); - } - - public function setIndex($index) - { - $this->setAttribute('index', $index); - } - - public function compile(Compiler $compiler): void - { - $this->compileTemplate($compiler); - - foreach ($this->getAttribute('embedded_templates') as $template) { - $compiler->subcompile($template); - } - } - - protected function compileTemplate(Compiler $compiler) - { - if (!$this->getAttribute('index')) { - $compiler->write('<?php'); - } - - $this->compileClassHeader($compiler); - - $this->compileConstructor($compiler); - - $this->compileGetParent($compiler); - - $this->compileDisplay($compiler); - - $compiler->subcompile($this->getNode('blocks')); - - $this->compileMacros($compiler); - - $this->compileGetTemplateName($compiler); - - $this->compileIsTraitable($compiler); - - $this->compileDebugInfo($compiler); - - $this->compileGetSourceContext($compiler); - - $this->compileClassFooter($compiler); - } - - protected function compileGetParent(Compiler $compiler) - { - if (!$this->hasNode('parent')) { - return; - } - $parent = $this->getNode('parent'); - - $compiler - ->write("protected function doGetParent(array \$context)\n", "{\n") - ->indent() - ->addDebugInfo($parent) - ->write('return ') - ; - - if ($parent instanceof ConstantExpression) { - $compiler->subcompile($parent); - } else { - $compiler - ->raw('$this->loadTemplate(') - ->subcompile($parent) - ->raw(', ') - ->repr($this->getSourceContext()->getName()) - ->raw(', ') - ->repr($parent->getTemplateLine()) - ->raw(')') - ; - } - - $compiler - ->raw(";\n") - ->outdent() - ->write("}\n\n") - ; - } - - protected function compileClassHeader(Compiler $compiler) - { - $compiler - ->write("\n\n") - ; - if (!$this->getAttribute('index')) { - $compiler - ->write("use Twig\Environment;\n") - ->write("use Twig\Error\LoaderError;\n") - ->write("use Twig\Error\RuntimeError;\n") - ->write("use Twig\Extension\SandboxExtension;\n") - ->write("use Twig\Markup;\n") - ->write("use Twig\Sandbox\SecurityError;\n") - ->write("use Twig\Sandbox\SecurityNotAllowedTagError;\n") - ->write("use Twig\Sandbox\SecurityNotAllowedFilterError;\n") - ->write("use Twig\Sandbox\SecurityNotAllowedFunctionError;\n") - ->write("use Twig\Source;\n") - ->write("use Twig\Template;\n\n") - ; - } - $compiler - // if the template name contains */, add a blank to avoid a PHP parse error - ->write('/* '.str_replace('*/', '* /', $this->getSourceContext()->getName())." */\n") - ->write('class '.$compiler->getEnvironment()->getTemplateClass($this->getSourceContext()->getName(), $this->getAttribute('index'))) - ->raw(" extends Template\n") - ->write("{\n") - ->indent() - ->write("private \$source;\n") - ->write("private \$macros = [];\n\n") - ; - } - - protected function compileConstructor(Compiler $compiler) - { - $compiler - ->write("public function __construct(Environment \$env)\n", "{\n") - ->indent() - ->subcompile($this->getNode('constructor_start')) - ->write("parent::__construct(\$env);\n\n") - ->write("\$this->source = \$this->getSourceContext();\n\n") - ; - - // parent - if (!$this->hasNode('parent')) { - $compiler->write("\$this->parent = false;\n\n"); - } - - $countTraits = \count($this->getNode('traits')); - if ($countTraits) { - // traits - foreach ($this->getNode('traits') as $i => $trait) { - $node = $trait->getNode('template'); - - $compiler - ->addDebugInfo($node) - ->write(sprintf('$_trait_%s = $this->loadTemplate(', $i)) - ->subcompile($node) - ->raw(', ') - ->repr($node->getTemplateName()) - ->raw(', ') - ->repr($node->getTemplateLine()) - ->raw(");\n") - ->write(sprintf("if (!\$_trait_%s->isTraitable()) {\n", $i)) - ->indent() - ->write("throw new RuntimeError('Template \"'.") - ->subcompile($trait->getNode('template')) - ->raw(".'\" cannot be used as a trait.', ") - ->repr($node->getTemplateLine()) - ->raw(", \$this->source);\n") - ->outdent() - ->write("}\n") - ->write(sprintf("\$_trait_%s_blocks = \$_trait_%s->getBlocks();\n\n", $i, $i)) - ; - - foreach ($trait->getNode('targets') as $key => $value) { - $compiler - ->write(sprintf('if (!isset($_trait_%s_blocks[', $i)) - ->string($key) - ->raw("])) {\n") - ->indent() - ->write("throw new RuntimeError('Block ") - ->string($key) - ->raw(' is not defined in trait ') - ->subcompile($trait->getNode('template')) - ->raw(".', ") - ->repr($node->getTemplateLine()) - ->raw(", \$this->source);\n") - ->outdent() - ->write("}\n\n") - - ->write(sprintf('$_trait_%s_blocks[', $i)) - ->subcompile($value) - ->raw(sprintf('] = $_trait_%s_blocks[', $i)) - ->string($key) - ->raw(sprintf(']; unset($_trait_%s_blocks[', $i)) - ->string($key) - ->raw("]);\n\n") - ; - } - } - - if ($countTraits > 1) { - $compiler - ->write("\$this->traits = array_merge(\n") - ->indent() - ; - - for ($i = 0; $i < $countTraits; ++$i) { - $compiler - ->write(sprintf('$_trait_%s_blocks'.($i == $countTraits - 1 ? '' : ',')."\n", $i)) - ; - } - - $compiler - ->outdent() - ->write(");\n\n") - ; - } else { - $compiler - ->write("\$this->traits = \$_trait_0_blocks;\n\n") - ; - } - - $compiler - ->write("\$this->blocks = array_merge(\n") - ->indent() - ->write("\$this->traits,\n") - ->write("[\n") - ; - } else { - $compiler - ->write("\$this->blocks = [\n") - ; - } - - // blocks - $compiler - ->indent() - ; - - foreach ($this->getNode('blocks') as $name => $node) { - $compiler - ->write(sprintf("'%s' => [\$this, 'block_%s'],\n", $name, $name)) - ; - } - - if ($countTraits) { - $compiler - ->outdent() - ->write("]\n") - ->outdent() - ->write(");\n") - ; - } else { - $compiler - ->outdent() - ->write("];\n") - ; - } - - $compiler - ->subcompile($this->getNode('constructor_end')) - ->outdent() - ->write("}\n\n") - ; - } - - protected function compileDisplay(Compiler $compiler) - { - $compiler - ->write("protected function doDisplay(array \$context, array \$blocks = [])\n", "{\n") - ->indent() - ->write("\$macros = \$this->macros;\n") - ->subcompile($this->getNode('display_start')) - ->subcompile($this->getNode('body')) - ; - - if ($this->hasNode('parent')) { - $parent = $this->getNode('parent'); - - $compiler->addDebugInfo($parent); - if ($parent instanceof ConstantExpression) { - $compiler - ->write('$this->parent = $this->loadTemplate(') - ->subcompile($parent) - ->raw(', ') - ->repr($this->getSourceContext()->getName()) - ->raw(', ') - ->repr($parent->getTemplateLine()) - ->raw(");\n") - ; - $compiler->write('$this->parent'); - } else { - $compiler->write('$this->getParent($context)'); - } - $compiler->raw("->display(\$context, array_merge(\$this->blocks, \$blocks));\n"); - } - - $compiler - ->subcompile($this->getNode('display_end')) - ->outdent() - ->write("}\n\n") - ; - } - - protected function compileClassFooter(Compiler $compiler) - { - $compiler - ->subcompile($this->getNode('class_end')) - ->outdent() - ->write("}\n") - ; - } - - protected function compileMacros(Compiler $compiler) - { - $compiler->subcompile($this->getNode('macros')); - } - - protected function compileGetTemplateName(Compiler $compiler) - { - $compiler - ->write("public function getTemplateName()\n", "{\n") - ->indent() - ->write('return ') - ->repr($this->getSourceContext()->getName()) - ->raw(";\n") - ->outdent() - ->write("}\n\n") - ; - } - - protected function compileIsTraitable(Compiler $compiler) - { - // A template can be used as a trait if: - // * it has no parent - // * it has no macros - // * it has no body - // - // Put another way, a template can be used as a trait if it - // only contains blocks and use statements. - $traitable = !$this->hasNode('parent') && 0 === \count($this->getNode('macros')); - if ($traitable) { - if ($this->getNode('body') instanceof BodyNode) { - $nodes = $this->getNode('body')->getNode(0); - } else { - $nodes = $this->getNode('body'); - } - - if (!\count($nodes)) { - $nodes = new Node([$nodes]); - } - - foreach ($nodes as $node) { - if (!\count($node)) { - continue; - } - - if ($node instanceof TextNode && ctype_space($node->getAttribute('data'))) { - continue; - } - - if ($node instanceof BlockReferenceNode) { - continue; - } - - $traitable = false; - break; - } - } - - if ($traitable) { - return; - } - - $compiler - ->write("public function isTraitable()\n", "{\n") - ->indent() - ->write(sprintf("return %s;\n", $traitable ? 'true' : 'false')) - ->outdent() - ->write("}\n\n") - ; - } - - protected function compileDebugInfo(Compiler $compiler) - { - $compiler - ->write("public function getDebugInfo()\n", "{\n") - ->indent() - ->write(sprintf("return %s;\n", str_replace("\n", '', var_export(array_reverse($compiler->getDebugInfo(), true), true)))) - ->outdent() - ->write("}\n\n") - ; - } - - protected function compileGetSourceContext(Compiler $compiler) - { - $compiler - ->write("public function getSourceContext()\n", "{\n") - ->indent() - ->write('return new Source(') - ->string($compiler->getEnvironment()->isDebug() ? $this->getSourceContext()->getCode() : '') - ->raw(', ') - ->string($this->getSourceContext()->getName()) - ->raw(', ') - ->string($this->getSourceContext()->getPath()) - ->raw(");\n") - ->outdent() - ->write("}\n") - ; - } - - protected function compileLoadTemplate(Compiler $compiler, $node, $var) - { - if ($node instanceof ConstantExpression) { - $compiler - ->write(sprintf('%s = $this->loadTemplate(', $var)) - ->subcompile($node) - ->raw(', ') - ->repr($node->getTemplateName()) - ->raw(', ') - ->repr($node->getTemplateLine()) - ->raw(");\n") - ; - } else { - throw new \LogicException('Trait templates can only be constant nodes.'); - } - } -} diff --git a/lib/twig/twig/src/Node/Node.php b/lib/twig/twig/src/Node/Node.php deleted file mode 100644 index c0558b9af..000000000 --- a/lib/twig/twig/src/Node/Node.php +++ /dev/null @@ -1,179 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -use Twig\Compiler; -use Twig\Source; - -/** - * Represents a node in the AST. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Node implements \Countable, \IteratorAggregate -{ - protected $nodes; - protected $attributes; - protected $lineno; - protected $tag; - - private $name; - private $sourceContext; - - /** - * @param array $nodes An array of named nodes - * @param array $attributes An array of attributes (should not be nodes) - * @param int $lineno The line number - * @param string $tag The tag name associated with the Node - */ - public function __construct(array $nodes = [], array $attributes = [], int $lineno = 0, string $tag = null) - { - foreach ($nodes as $name => $node) { - if (!$node instanceof self) { - throw new \InvalidArgumentException(sprintf('Using "%s" for the value of node "%s" of "%s" is not supported. You must pass a \Twig\Node\Node instance.', \is_object($node) ? \get_class($node) : (null === $node ? 'null' : \gettype($node)), $name, static::class)); - } - } - $this->nodes = $nodes; - $this->attributes = $attributes; - $this->lineno = $lineno; - $this->tag = $tag; - } - - public function __toString() - { - $attributes = []; - foreach ($this->attributes as $name => $value) { - $attributes[] = sprintf('%s: %s', $name, str_replace("\n", '', var_export($value, true))); - } - - $repr = [static::class.'('.implode(', ', $attributes)]; - - if (\count($this->nodes)) { - foreach ($this->nodes as $name => $node) { - $len = \strlen($name) + 4; - $noderepr = []; - foreach (explode("\n", (string) $node) as $line) { - $noderepr[] = str_repeat(' ', $len).$line; - } - - $repr[] = sprintf(' %s: %s', $name, ltrim(implode("\n", $noderepr))); - } - - $repr[] = ')'; - } else { - $repr[0] .= ')'; - } - - return implode("\n", $repr); - } - - /** - * @return void - */ - public function compile(Compiler $compiler) - { - foreach ($this->nodes as $node) { - $node->compile($compiler); - } - } - - public function getTemplateLine(): int - { - return $this->lineno; - } - - public function getNodeTag(): ?string - { - return $this->tag; - } - - public function hasAttribute(string $name): bool - { - return \array_key_exists($name, $this->attributes); - } - - public function getAttribute(string $name) - { - if (!\array_key_exists($name, $this->attributes)) { - throw new \LogicException(sprintf('Attribute "%s" does not exist for Node "%s".', $name, static::class)); - } - - return $this->attributes[$name]; - } - - public function setAttribute(string $name, $value): void - { - $this->attributes[$name] = $value; - } - - public function removeAttribute(string $name): void - { - unset($this->attributes[$name]); - } - - public function hasNode(string $name): bool - { - return isset($this->nodes[$name]); - } - - public function getNode(string $name): self - { - if (!isset($this->nodes[$name])) { - throw new \LogicException(sprintf('Node "%s" does not exist for Node "%s".', $name, static::class)); - } - - return $this->nodes[$name]; - } - - public function setNode(string $name, self $node): void - { - $this->nodes[$name] = $node; - } - - public function removeNode(string $name): void - { - unset($this->nodes[$name]); - } - - /** - * @return int - */ - #[\ReturnTypeWillChange] - public function count() - { - return \count($this->nodes); - } - - public function getIterator(): \Traversable - { - return new \ArrayIterator($this->nodes); - } - - public function getTemplateName(): ?string - { - return $this->sourceContext ? $this->sourceContext->getName() : null; - } - - public function setSourceContext(Source $source): void - { - $this->sourceContext = $source; - foreach ($this->nodes as $node) { - $node->setSourceContext($source); - } - } - - public function getSourceContext(): ?Source - { - return $this->sourceContext; - } -} diff --git a/lib/twig/twig/src/Node/NodeCaptureInterface.php b/lib/twig/twig/src/Node/NodeCaptureInterface.php deleted file mode 100644 index 9fb6a0ca1..000000000 --- a/lib/twig/twig/src/Node/NodeCaptureInterface.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -/** - * Represents a node that captures any nested displayable nodes. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface NodeCaptureInterface -{ -} diff --git a/lib/twig/twig/src/Node/NodeOutputInterface.php b/lib/twig/twig/src/Node/NodeOutputInterface.php deleted file mode 100644 index 5e35b406b..000000000 --- a/lib/twig/twig/src/Node/NodeOutputInterface.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -/** - * Represents a displayable node in the AST. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface NodeOutputInterface -{ -} diff --git a/lib/twig/twig/src/Node/PrintNode.php b/lib/twig/twig/src/Node/PrintNode.php deleted file mode 100644 index 60386d299..000000000 --- a/lib/twig/twig/src/Node/PrintNode.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -use Twig\Compiler; -use Twig\Node\Expression\AbstractExpression; - -/** - * Represents a node that outputs an expression. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class PrintNode extends Node implements NodeOutputInterface -{ - public function __construct(AbstractExpression $expr, int $lineno, string $tag = null) - { - parent::__construct(['expr' => $expr], [], $lineno, $tag); - } - - public function compile(Compiler $compiler): void - { - $compiler - ->addDebugInfo($this) - ->write('echo ') - ->subcompile($this->getNode('expr')) - ->raw(";\n") - ; - } -} diff --git a/lib/twig/twig/src/Node/SandboxNode.php b/lib/twig/twig/src/Node/SandboxNode.php deleted file mode 100644 index 4d5666bff..000000000 --- a/lib/twig/twig/src/Node/SandboxNode.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -use Twig\Compiler; - -/** - * Represents a sandbox node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class SandboxNode extends Node -{ - public function __construct(Node $body, int $lineno, string $tag = null) - { - parent::__construct(['body' => $body], [], $lineno, $tag); - } - - public function compile(Compiler $compiler): void - { - $compiler - ->addDebugInfo($this) - ->write("if (!\$alreadySandboxed = \$this->sandbox->isSandboxed()) {\n") - ->indent() - ->write("\$this->sandbox->enableSandbox();\n") - ->outdent() - ->write("}\n") - ->write("try {\n") - ->indent() - ->subcompile($this->getNode('body')) - ->outdent() - ->write("} finally {\n") - ->indent() - ->write("if (!\$alreadySandboxed) {\n") - ->indent() - ->write("\$this->sandbox->disableSandbox();\n") - ->outdent() - ->write("}\n") - ->outdent() - ->write("}\n") - ; - } -} diff --git a/lib/twig/twig/src/Node/SetNode.php b/lib/twig/twig/src/Node/SetNode.php deleted file mode 100644 index 96b6bd8bf..000000000 --- a/lib/twig/twig/src/Node/SetNode.php +++ /dev/null @@ -1,105 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -use Twig\Compiler; -use Twig\Node\Expression\ConstantExpression; - -/** - * Represents a set node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class SetNode extends Node implements NodeCaptureInterface -{ - public function __construct(bool $capture, Node $names, Node $values, int $lineno, string $tag = null) - { - parent::__construct(['names' => $names, 'values' => $values], ['capture' => $capture, 'safe' => false], $lineno, $tag); - - /* - * Optimizes the node when capture is used for a large block of text. - * - * {% set foo %}foo{% endset %} is compiled to $context['foo'] = new Twig\Markup("foo"); - */ - if ($this->getAttribute('capture')) { - $this->setAttribute('safe', true); - - $values = $this->getNode('values'); - if ($values instanceof TextNode) { - $this->setNode('values', new ConstantExpression($values->getAttribute('data'), $values->getTemplateLine())); - $this->setAttribute('capture', false); - } - } - } - - public function compile(Compiler $compiler): void - { - $compiler->addDebugInfo($this); - - if (\count($this->getNode('names')) > 1) { - $compiler->write('list('); - foreach ($this->getNode('names') as $idx => $node) { - if ($idx) { - $compiler->raw(', '); - } - - $compiler->subcompile($node); - } - $compiler->raw(')'); - } else { - if ($this->getAttribute('capture')) { - if ($compiler->getEnvironment()->isDebug()) { - $compiler->write("ob_start();\n"); - } else { - $compiler->write("ob_start(function () { return ''; });\n"); - } - $compiler - ->subcompile($this->getNode('values')) - ; - } - - $compiler->subcompile($this->getNode('names'), false); - - if ($this->getAttribute('capture')) { - $compiler->raw(" = ('' === \$tmp = ob_get_clean()) ? '' : new Markup(\$tmp, \$this->env->getCharset())"); - } - } - - if (!$this->getAttribute('capture')) { - $compiler->raw(' = '); - - if (\count($this->getNode('names')) > 1) { - $compiler->write('['); - foreach ($this->getNode('values') as $idx => $value) { - if ($idx) { - $compiler->raw(', '); - } - - $compiler->subcompile($value); - } - $compiler->raw(']'); - } else { - if ($this->getAttribute('safe')) { - $compiler - ->raw("('' === \$tmp = ") - ->subcompile($this->getNode('values')) - ->raw(") ? '' : new Markup(\$tmp, \$this->env->getCharset())") - ; - } else { - $compiler->subcompile($this->getNode('values')); - } - } - } - - $compiler->raw(";\n"); - } -} diff --git a/lib/twig/twig/src/Node/TextNode.php b/lib/twig/twig/src/Node/TextNode.php deleted file mode 100644 index d74ebe630..000000000 --- a/lib/twig/twig/src/Node/TextNode.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -use Twig\Compiler; - -/** - * Represents a text node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class TextNode extends Node implements NodeOutputInterface -{ - public function __construct(string $data, int $lineno) - { - parent::__construct([], ['data' => $data], $lineno); - } - - public function compile(Compiler $compiler): void - { - $compiler - ->addDebugInfo($this) - ->write('echo ') - ->string($this->getAttribute('data')) - ->raw(";\n") - ; - } -} diff --git a/lib/twig/twig/src/Node/WithNode.php b/lib/twig/twig/src/Node/WithNode.php deleted file mode 100644 index 56a334496..000000000 --- a/lib/twig/twig/src/Node/WithNode.php +++ /dev/null @@ -1,70 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Node; - -use Twig\Compiler; - -/** - * Represents a nested "with" scope. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class WithNode extends Node -{ - public function __construct(Node $body, ?Node $variables, bool $only, int $lineno, string $tag = null) - { - $nodes = ['body' => $body]; - if (null !== $variables) { - $nodes['variables'] = $variables; - } - - parent::__construct($nodes, ['only' => $only], $lineno, $tag); - } - - public function compile(Compiler $compiler): void - { - $compiler->addDebugInfo($this); - - $parentContextName = $compiler->getVarName(); - - $compiler->write(sprintf("\$%s = \$context;\n", $parentContextName)); - - if ($this->hasNode('variables')) { - $node = $this->getNode('variables'); - $varsName = $compiler->getVarName(); - $compiler - ->write(sprintf('$%s = ', $varsName)) - ->subcompile($node) - ->raw(";\n") - ->write(sprintf("if (!twig_test_iterable(\$%s)) {\n", $varsName)) - ->indent() - ->write("throw new RuntimeError('Variables passed to the \"with\" tag must be a hash.', ") - ->repr($node->getTemplateLine()) - ->raw(", \$this->getSourceContext());\n") - ->outdent() - ->write("}\n") - ->write(sprintf("\$%s = twig_to_array(\$%s);\n", $varsName, $varsName)) - ; - - if ($this->getAttribute('only')) { - $compiler->write("\$context = [];\n"); - } - - $compiler->write(sprintf("\$context = \$this->env->mergeGlobals(array_merge(\$context, \$%s));\n", $varsName)); - } - - $compiler - ->subcompile($this->getNode('body')) - ->write(sprintf("\$context = \$%s;\n", $parentContextName)) - ; - } -} diff --git a/lib/twig/twig/src/NodeTraverser.php b/lib/twig/twig/src/NodeTraverser.php deleted file mode 100644 index 47a2d5ca3..000000000 --- a/lib/twig/twig/src/NodeTraverser.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig; - -use Twig\Node\Node; -use Twig\NodeVisitor\NodeVisitorInterface; - -/** - * A node traverser. - * - * It visits all nodes and their children and calls the given visitor for each. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class NodeTraverser -{ - private $env; - private $visitors = []; - - /** - * @param NodeVisitorInterface[] $visitors - */ - public function __construct(Environment $env, array $visitors = []) - { - $this->env = $env; - foreach ($visitors as $visitor) { - $this->addVisitor($visitor); - } - } - - public function addVisitor(NodeVisitorInterface $visitor): void - { - $this->visitors[$visitor->getPriority()][] = $visitor; - } - - /** - * Traverses a node and calls the registered visitors. - */ - public function traverse(Node $node): Node - { - ksort($this->visitors); - foreach ($this->visitors as $visitors) { - foreach ($visitors as $visitor) { - $node = $this->traverseForVisitor($visitor, $node); - } - } - - return $node; - } - - private function traverseForVisitor(NodeVisitorInterface $visitor, Node $node): ?Node - { - $node = $visitor->enterNode($node, $this->env); - - foreach ($node as $k => $n) { - if (null !== $m = $this->traverseForVisitor($visitor, $n)) { - if ($m !== $n) { - $node->setNode($k, $m); - } - } else { - $node->removeNode($k); - } - } - - return $visitor->leaveNode($node, $this->env); - } -} diff --git a/lib/twig/twig/src/NodeVisitor/AbstractNodeVisitor.php b/lib/twig/twig/src/NodeVisitor/AbstractNodeVisitor.php deleted file mode 100644 index d7036ae55..000000000 --- a/lib/twig/twig/src/NodeVisitor/AbstractNodeVisitor.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\NodeVisitor; - -use Twig\Environment; -use Twig\Node\Node; - -/** - * Used to make node visitors compatible with Twig 1.x and 2.x. - * - * To be removed in Twig 3.1. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -abstract class AbstractNodeVisitor implements NodeVisitorInterface -{ - final public function enterNode(Node $node, Environment $env): Node - { - return $this->doEnterNode($node, $env); - } - - final public function leaveNode(Node $node, Environment $env): ?Node - { - return $this->doLeaveNode($node, $env); - } - - /** - * Called before child nodes are visited. - * - * @return Node The modified node - */ - abstract protected function doEnterNode(Node $node, Environment $env); - - /** - * Called after child nodes are visited. - * - * @return Node|null The modified node or null if the node must be removed - */ - abstract protected function doLeaveNode(Node $node, Environment $env); -} diff --git a/lib/twig/twig/src/NodeVisitor/EscaperNodeVisitor.php b/lib/twig/twig/src/NodeVisitor/EscaperNodeVisitor.php deleted file mode 100644 index fe56ea307..000000000 --- a/lib/twig/twig/src/NodeVisitor/EscaperNodeVisitor.php +++ /dev/null @@ -1,208 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\NodeVisitor; - -use Twig\Environment; -use Twig\Extension\EscaperExtension; -use Twig\Node\AutoEscapeNode; -use Twig\Node\BlockNode; -use Twig\Node\BlockReferenceNode; -use Twig\Node\DoNode; -use Twig\Node\Expression\ConditionalExpression; -use Twig\Node\Expression\ConstantExpression; -use Twig\Node\Expression\FilterExpression; -use Twig\Node\Expression\InlinePrint; -use Twig\Node\ImportNode; -use Twig\Node\ModuleNode; -use Twig\Node\Node; -use Twig\Node\PrintNode; -use Twig\NodeTraverser; - -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @internal - */ -final class EscaperNodeVisitor implements NodeVisitorInterface -{ - private $statusStack = []; - private $blocks = []; - private $safeAnalysis; - private $traverser; - private $defaultStrategy = false; - private $safeVars = []; - - public function __construct() - { - $this->safeAnalysis = new SafeAnalysisNodeVisitor(); - } - - public function enterNode(Node $node, Environment $env): Node - { - if ($node instanceof ModuleNode) { - if ($env->hasExtension(EscaperExtension::class) && $defaultStrategy = $env->getExtension(EscaperExtension::class)->getDefaultStrategy($node->getTemplateName())) { - $this->defaultStrategy = $defaultStrategy; - } - $this->safeVars = []; - $this->blocks = []; - } elseif ($node instanceof AutoEscapeNode) { - $this->statusStack[] = $node->getAttribute('value'); - } elseif ($node instanceof BlockNode) { - $this->statusStack[] = isset($this->blocks[$node->getAttribute('name')]) ? $this->blocks[$node->getAttribute('name')] : $this->needEscaping($env); - } elseif ($node instanceof ImportNode) { - $this->safeVars[] = $node->getNode('var')->getAttribute('name'); - } - - return $node; - } - - public function leaveNode(Node $node, Environment $env): ?Node - { - if ($node instanceof ModuleNode) { - $this->defaultStrategy = false; - $this->safeVars = []; - $this->blocks = []; - } elseif ($node instanceof FilterExpression) { - return $this->preEscapeFilterNode($node, $env); - } elseif ($node instanceof PrintNode && false !== $type = $this->needEscaping($env)) { - $expression = $node->getNode('expr'); - if ($expression instanceof ConditionalExpression && $this->shouldUnwrapConditional($expression, $env, $type)) { - return new DoNode($this->unwrapConditional($expression, $env, $type), $expression->getTemplateLine()); - } - - return $this->escapePrintNode($node, $env, $type); - } - - if ($node instanceof AutoEscapeNode || $node instanceof BlockNode) { - array_pop($this->statusStack); - } elseif ($node instanceof BlockReferenceNode) { - $this->blocks[$node->getAttribute('name')] = $this->needEscaping($env); - } - - return $node; - } - - private function shouldUnwrapConditional(ConditionalExpression $expression, Environment $env, string $type): bool - { - $expr2Safe = $this->isSafeFor($type, $expression->getNode('expr2'), $env); - $expr3Safe = $this->isSafeFor($type, $expression->getNode('expr3'), $env); - - return $expr2Safe !== $expr3Safe; - } - - private function unwrapConditional(ConditionalExpression $expression, Environment $env, string $type): ConditionalExpression - { - // convert "echo a ? b : c" to "a ? echo b : echo c" recursively - $expr2 = $expression->getNode('expr2'); - if ($expr2 instanceof ConditionalExpression && $this->shouldUnwrapConditional($expr2, $env, $type)) { - $expr2 = $this->unwrapConditional($expr2, $env, $type); - } else { - $expr2 = $this->escapeInlinePrintNode(new InlinePrint($expr2, $expr2->getTemplateLine()), $env, $type); - } - $expr3 = $expression->getNode('expr3'); - if ($expr3 instanceof ConditionalExpression && $this->shouldUnwrapConditional($expr3, $env, $type)) { - $expr3 = $this->unwrapConditional($expr3, $env, $type); - } else { - $expr3 = $this->escapeInlinePrintNode(new InlinePrint($expr3, $expr3->getTemplateLine()), $env, $type); - } - - return new ConditionalExpression($expression->getNode('expr1'), $expr2, $expr3, $expression->getTemplateLine()); - } - - private function escapeInlinePrintNode(InlinePrint $node, Environment $env, string $type): Node - { - $expression = $node->getNode('node'); - - if ($this->isSafeFor($type, $expression, $env)) { - return $node; - } - - return new InlinePrint($this->getEscaperFilter($type, $expression), $node->getTemplateLine()); - } - - private function escapePrintNode(PrintNode $node, Environment $env, string $type): Node - { - if (false === $type) { - return $node; - } - - $expression = $node->getNode('expr'); - - if ($this->isSafeFor($type, $expression, $env)) { - return $node; - } - - $class = \get_class($node); - - return new $class($this->getEscaperFilter($type, $expression), $node->getTemplateLine()); - } - - private function preEscapeFilterNode(FilterExpression $filter, Environment $env): FilterExpression - { - $name = $filter->getNode('filter')->getAttribute('value'); - - $type = $env->getFilter($name)->getPreEscape(); - if (null === $type) { - return $filter; - } - - $node = $filter->getNode('node'); - if ($this->isSafeFor($type, $node, $env)) { - return $filter; - } - - $filter->setNode('node', $this->getEscaperFilter($type, $node)); - - return $filter; - } - - private function isSafeFor(string $type, Node $expression, Environment $env): bool - { - $safe = $this->safeAnalysis->getSafe($expression); - - if (null === $safe) { - if (null === $this->traverser) { - $this->traverser = new NodeTraverser($env, [$this->safeAnalysis]); - } - - $this->safeAnalysis->setSafeVars($this->safeVars); - - $this->traverser->traverse($expression); - $safe = $this->safeAnalysis->getSafe($expression); - } - - return \in_array($type, $safe) || \in_array('all', $safe); - } - - private function needEscaping(Environment $env) - { - if (\count($this->statusStack)) { - return $this->statusStack[\count($this->statusStack) - 1]; - } - - return $this->defaultStrategy ? $this->defaultStrategy : false; - } - - private function getEscaperFilter(string $type, Node $node): FilterExpression - { - $line = $node->getTemplateLine(); - $name = new ConstantExpression('escape', $line); - $args = new Node([new ConstantExpression($type, $line), new ConstantExpression(null, $line), new ConstantExpression(true, $line)]); - - return new FilterExpression($node, $name, $args, $line); - } - - public function getPriority(): int - { - return 0; - } -} diff --git a/lib/twig/twig/src/NodeVisitor/MacroAutoImportNodeVisitor.php b/lib/twig/twig/src/NodeVisitor/MacroAutoImportNodeVisitor.php deleted file mode 100644 index af477e653..000000000 --- a/lib/twig/twig/src/NodeVisitor/MacroAutoImportNodeVisitor.php +++ /dev/null @@ -1,74 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\NodeVisitor; - -use Twig\Environment; -use Twig\Node\Expression\AssignNameExpression; -use Twig\Node\Expression\ConstantExpression; -use Twig\Node\Expression\GetAttrExpression; -use Twig\Node\Expression\MethodCallExpression; -use Twig\Node\Expression\NameExpression; -use Twig\Node\ImportNode; -use Twig\Node\ModuleNode; -use Twig\Node\Node; - -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @internal - */ -final class MacroAutoImportNodeVisitor implements NodeVisitorInterface -{ - private $inAModule = false; - private $hasMacroCalls = false; - - public function enterNode(Node $node, Environment $env): Node - { - if ($node instanceof ModuleNode) { - $this->inAModule = true; - $this->hasMacroCalls = false; - } - - return $node; - } - - public function leaveNode(Node $node, Environment $env): Node - { - if ($node instanceof ModuleNode) { - $this->inAModule = false; - if ($this->hasMacroCalls) { - $node->getNode('constructor_end')->setNode('_auto_macro_import', new ImportNode(new NameExpression('_self', 0), new AssignNameExpression('_self', 0), 0, 'import', true)); - } - } elseif ($this->inAModule) { - if ( - $node instanceof GetAttrExpression && - $node->getNode('node') instanceof NameExpression && - '_self' === $node->getNode('node')->getAttribute('name') && - $node->getNode('attribute') instanceof ConstantExpression - ) { - $this->hasMacroCalls = true; - - $name = $node->getNode('attribute')->getAttribute('value'); - $node = new MethodCallExpression($node->getNode('node'), 'macro_'.$name, $node->getNode('arguments'), $node->getTemplateLine()); - $node->setAttribute('safe', true); - } - } - - return $node; - } - - public function getPriority(): int - { - // we must be ran before auto-escaping - return -10; - } -} diff --git a/lib/twig/twig/src/NodeVisitor/NodeVisitorInterface.php b/lib/twig/twig/src/NodeVisitor/NodeVisitorInterface.php deleted file mode 100644 index 59e836dbd..000000000 --- a/lib/twig/twig/src/NodeVisitor/NodeVisitorInterface.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\NodeVisitor; - -use Twig\Environment; -use Twig\Node\Node; - -/** - * Interface for node visitor classes. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface NodeVisitorInterface -{ - /** - * Called before child nodes are visited. - * - * @return Node The modified node - */ - public function enterNode(Node $node, Environment $env): Node; - - /** - * Called after child nodes are visited. - * - * @return Node|null The modified node or null if the node must be removed - */ - public function leaveNode(Node $node, Environment $env): ?Node; - - /** - * Returns the priority for this visitor. - * - * Priority should be between -10 and 10 (0 is the default). - * - * @return int The priority level - */ - public function getPriority(); -} diff --git a/lib/twig/twig/src/NodeVisitor/OptimizerNodeVisitor.php b/lib/twig/twig/src/NodeVisitor/OptimizerNodeVisitor.php deleted file mode 100644 index 7ac75e41a..000000000 --- a/lib/twig/twig/src/NodeVisitor/OptimizerNodeVisitor.php +++ /dev/null @@ -1,217 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\NodeVisitor; - -use Twig\Environment; -use Twig\Node\BlockReferenceNode; -use Twig\Node\Expression\BlockReferenceExpression; -use Twig\Node\Expression\ConstantExpression; -use Twig\Node\Expression\FilterExpression; -use Twig\Node\Expression\FunctionExpression; -use Twig\Node\Expression\GetAttrExpression; -use Twig\Node\Expression\NameExpression; -use Twig\Node\Expression\ParentExpression; -use Twig\Node\ForNode; -use Twig\Node\IncludeNode; -use Twig\Node\Node; -use Twig\Node\PrintNode; - -/** - * Tries to optimize the AST. - * - * This visitor is always the last registered one. - * - * You can configure which optimizations you want to activate via the - * optimizer mode. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @internal - */ -final class OptimizerNodeVisitor implements NodeVisitorInterface -{ - public const OPTIMIZE_ALL = -1; - public const OPTIMIZE_NONE = 0; - public const OPTIMIZE_FOR = 2; - public const OPTIMIZE_RAW_FILTER = 4; - - private $loops = []; - private $loopsTargets = []; - private $optimizers; - - /** - * @param int $optimizers The optimizer mode - */ - public function __construct(int $optimizers = -1) - { - if ($optimizers > (self::OPTIMIZE_FOR | self::OPTIMIZE_RAW_FILTER)) { - throw new \InvalidArgumentException(sprintf('Optimizer mode "%s" is not valid.', $optimizers)); - } - - $this->optimizers = $optimizers; - } - - public function enterNode(Node $node, Environment $env): Node - { - if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) { - $this->enterOptimizeFor($node, $env); - } - - return $node; - } - - public function leaveNode(Node $node, Environment $env): ?Node - { - if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) { - $this->leaveOptimizeFor($node, $env); - } - - if (self::OPTIMIZE_RAW_FILTER === (self::OPTIMIZE_RAW_FILTER & $this->optimizers)) { - $node = $this->optimizeRawFilter($node, $env); - } - - $node = $this->optimizePrintNode($node, $env); - - return $node; - } - - /** - * Optimizes print nodes. - * - * It replaces: - * - * * "echo $this->render(Parent)Block()" with "$this->display(Parent)Block()" - */ - private function optimizePrintNode(Node $node, Environment $env): Node - { - if (!$node instanceof PrintNode) { - return $node; - } - - $exprNode = $node->getNode('expr'); - if ( - $exprNode instanceof BlockReferenceExpression || - $exprNode instanceof ParentExpression - ) { - $exprNode->setAttribute('output', true); - - return $exprNode; - } - - return $node; - } - - /** - * Removes "raw" filters. - */ - private function optimizeRawFilter(Node $node, Environment $env): Node - { - if ($node instanceof FilterExpression && 'raw' == $node->getNode('filter')->getAttribute('value')) { - return $node->getNode('node'); - } - - return $node; - } - - /** - * Optimizes "for" tag by removing the "loop" variable creation whenever possible. - */ - private function enterOptimizeFor(Node $node, Environment $env): void - { - if ($node instanceof ForNode) { - // disable the loop variable by default - $node->setAttribute('with_loop', false); - array_unshift($this->loops, $node); - array_unshift($this->loopsTargets, $node->getNode('value_target')->getAttribute('name')); - array_unshift($this->loopsTargets, $node->getNode('key_target')->getAttribute('name')); - } elseif (!$this->loops) { - // we are outside a loop - return; - } - - // when do we need to add the loop variable back? - - // the loop variable is referenced for the current loop - elseif ($node instanceof NameExpression && 'loop' === $node->getAttribute('name')) { - $node->setAttribute('always_defined', true); - $this->addLoopToCurrent(); - } - - // optimize access to loop targets - elseif ($node instanceof NameExpression && \in_array($node->getAttribute('name'), $this->loopsTargets)) { - $node->setAttribute('always_defined', true); - } - - // block reference - elseif ($node instanceof BlockReferenceNode || $node instanceof BlockReferenceExpression) { - $this->addLoopToCurrent(); - } - - // include without the only attribute - elseif ($node instanceof IncludeNode && !$node->getAttribute('only')) { - $this->addLoopToAll(); - } - - // include function without the with_context=false parameter - elseif ($node instanceof FunctionExpression - && 'include' === $node->getAttribute('name') - && (!$node->getNode('arguments')->hasNode('with_context') - || false !== $node->getNode('arguments')->getNode('with_context')->getAttribute('value') - ) - ) { - $this->addLoopToAll(); - } - - // the loop variable is referenced via an attribute - elseif ($node instanceof GetAttrExpression - && (!$node->getNode('attribute') instanceof ConstantExpression - || 'parent' === $node->getNode('attribute')->getAttribute('value') - ) - && (true === $this->loops[0]->getAttribute('with_loop') - || ($node->getNode('node') instanceof NameExpression - && 'loop' === $node->getNode('node')->getAttribute('name') - ) - ) - ) { - $this->addLoopToAll(); - } - } - - /** - * Optimizes "for" tag by removing the "loop" variable creation whenever possible. - */ - private function leaveOptimizeFor(Node $node, Environment $env): void - { - if ($node instanceof ForNode) { - array_shift($this->loops); - array_shift($this->loopsTargets); - array_shift($this->loopsTargets); - } - } - - private function addLoopToCurrent(): void - { - $this->loops[0]->setAttribute('with_loop', true); - } - - private function addLoopToAll(): void - { - foreach ($this->loops as $loop) { - $loop->setAttribute('with_loop', true); - } - } - - public function getPriority(): int - { - return 255; - } -} diff --git a/lib/twig/twig/src/NodeVisitor/SafeAnalysisNodeVisitor.php b/lib/twig/twig/src/NodeVisitor/SafeAnalysisNodeVisitor.php deleted file mode 100644 index 90d6f2e0f..000000000 --- a/lib/twig/twig/src/NodeVisitor/SafeAnalysisNodeVisitor.php +++ /dev/null @@ -1,160 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\NodeVisitor; - -use Twig\Environment; -use Twig\Node\Expression\BlockReferenceExpression; -use Twig\Node\Expression\ConditionalExpression; -use Twig\Node\Expression\ConstantExpression; -use Twig\Node\Expression\FilterExpression; -use Twig\Node\Expression\FunctionExpression; -use Twig\Node\Expression\GetAttrExpression; -use Twig\Node\Expression\MethodCallExpression; -use Twig\Node\Expression\NameExpression; -use Twig\Node\Expression\ParentExpression; -use Twig\Node\Node; - -/** - * @internal - */ -final class SafeAnalysisNodeVisitor implements NodeVisitorInterface -{ - private $data = []; - private $safeVars = []; - - public function setSafeVars(array $safeVars): void - { - $this->safeVars = $safeVars; - } - - public function getSafe(Node $node) - { - $hash = spl_object_hash($node); - if (!isset($this->data[$hash])) { - return; - } - - foreach ($this->data[$hash] as $bucket) { - if ($bucket['key'] !== $node) { - continue; - } - - if (\in_array('html_attr', $bucket['value'])) { - $bucket['value'][] = 'html'; - } - - return $bucket['value']; - } - } - - private function setSafe(Node $node, array $safe): void - { - $hash = spl_object_hash($node); - if (isset($this->data[$hash])) { - foreach ($this->data[$hash] as &$bucket) { - if ($bucket['key'] === $node) { - $bucket['value'] = $safe; - - return; - } - } - } - $this->data[$hash][] = [ - 'key' => $node, - 'value' => $safe, - ]; - } - - public function enterNode(Node $node, Environment $env): Node - { - return $node; - } - - public function leaveNode(Node $node, Environment $env): ?Node - { - if ($node instanceof ConstantExpression) { - // constants are marked safe for all - $this->setSafe($node, ['all']); - } elseif ($node instanceof BlockReferenceExpression) { - // blocks are safe by definition - $this->setSafe($node, ['all']); - } elseif ($node instanceof ParentExpression) { - // parent block is safe by definition - $this->setSafe($node, ['all']); - } elseif ($node instanceof ConditionalExpression) { - // intersect safeness of both operands - $safe = $this->intersectSafe($this->getSafe($node->getNode('expr2')), $this->getSafe($node->getNode('expr3'))); - $this->setSafe($node, $safe); - } elseif ($node instanceof FilterExpression) { - // filter expression is safe when the filter is safe - $name = $node->getNode('filter')->getAttribute('value'); - $args = $node->getNode('arguments'); - if ($filter = $env->getFilter($name)) { - $safe = $filter->getSafe($args); - if (null === $safe) { - $safe = $this->intersectSafe($this->getSafe($node->getNode('node')), $filter->getPreservesSafety()); - } - $this->setSafe($node, $safe); - } else { - $this->setSafe($node, []); - } - } elseif ($node instanceof FunctionExpression) { - // function expression is safe when the function is safe - $name = $node->getAttribute('name'); - $args = $node->getNode('arguments'); - if ($function = $env->getFunction($name)) { - $this->setSafe($node, $function->getSafe($args)); - } else { - $this->setSafe($node, []); - } - } elseif ($node instanceof MethodCallExpression) { - if ($node->getAttribute('safe')) { - $this->setSafe($node, ['all']); - } else { - $this->setSafe($node, []); - } - } elseif ($node instanceof GetAttrExpression && $node->getNode('node') instanceof NameExpression) { - $name = $node->getNode('node')->getAttribute('name'); - if (\in_array($name, $this->safeVars)) { - $this->setSafe($node, ['all']); - } else { - $this->setSafe($node, []); - } - } else { - $this->setSafe($node, []); - } - - return $node; - } - - private function intersectSafe(array $a = null, array $b = null): array - { - if (null === $a || null === $b) { - return []; - } - - if (\in_array('all', $a)) { - return $b; - } - - if (\in_array('all', $b)) { - return $a; - } - - return array_intersect($a, $b); - } - - public function getPriority(): int - { - return 0; - } -} diff --git a/lib/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php b/lib/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php deleted file mode 100644 index 1446cee6b..000000000 --- a/lib/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php +++ /dev/null @@ -1,136 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\NodeVisitor; - -use Twig\Environment; -use Twig\Node\CheckSecurityCallNode; -use Twig\Node\CheckSecurityNode; -use Twig\Node\CheckToStringNode; -use Twig\Node\Expression\Binary\ConcatBinary; -use Twig\Node\Expression\Binary\RangeBinary; -use Twig\Node\Expression\FilterExpression; -use Twig\Node\Expression\FunctionExpression; -use Twig\Node\Expression\GetAttrExpression; -use Twig\Node\Expression\NameExpression; -use Twig\Node\ModuleNode; -use Twig\Node\Node; -use Twig\Node\PrintNode; -use Twig\Node\SetNode; - -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @internal - */ -final class SandboxNodeVisitor implements NodeVisitorInterface -{ - private $inAModule = false; - private $tags; - private $filters; - private $functions; - private $needsToStringWrap = false; - - public function enterNode(Node $node, Environment $env): Node - { - if ($node instanceof ModuleNode) { - $this->inAModule = true; - $this->tags = []; - $this->filters = []; - $this->functions = []; - - return $node; - } elseif ($this->inAModule) { - // look for tags - if ($node->getNodeTag() && !isset($this->tags[$node->getNodeTag()])) { - $this->tags[$node->getNodeTag()] = $node; - } - - // look for filters - if ($node instanceof FilterExpression && !isset($this->filters[$node->getNode('filter')->getAttribute('value')])) { - $this->filters[$node->getNode('filter')->getAttribute('value')] = $node; - } - - // look for functions - if ($node instanceof FunctionExpression && !isset($this->functions[$node->getAttribute('name')])) { - $this->functions[$node->getAttribute('name')] = $node; - } - - // the .. operator is equivalent to the range() function - if ($node instanceof RangeBinary && !isset($this->functions['range'])) { - $this->functions['range'] = $node; - } - - if ($node instanceof PrintNode) { - $this->needsToStringWrap = true; - $this->wrapNode($node, 'expr'); - } - - if ($node instanceof SetNode && !$node->getAttribute('capture')) { - $this->needsToStringWrap = true; - } - - // wrap outer nodes that can implicitly call __toString() - if ($this->needsToStringWrap) { - if ($node instanceof ConcatBinary) { - $this->wrapNode($node, 'left'); - $this->wrapNode($node, 'right'); - } - if ($node instanceof FilterExpression) { - $this->wrapNode($node, 'node'); - $this->wrapArrayNode($node, 'arguments'); - } - if ($node instanceof FunctionExpression) { - $this->wrapArrayNode($node, 'arguments'); - } - } - } - - return $node; - } - - public function leaveNode(Node $node, Environment $env): ?Node - { - if ($node instanceof ModuleNode) { - $this->inAModule = false; - - $node->setNode('constructor_end', new Node([new CheckSecurityCallNode(), $node->getNode('constructor_end')])); - $node->setNode('class_end', new Node([new CheckSecurityNode($this->filters, $this->tags, $this->functions), $node->getNode('class_end')])); - } elseif ($this->inAModule) { - if ($node instanceof PrintNode || $node instanceof SetNode) { - $this->needsToStringWrap = false; - } - } - - return $node; - } - - private function wrapNode(Node $node, string $name): void - { - $expr = $node->getNode($name); - if ($expr instanceof NameExpression || $expr instanceof GetAttrExpression) { - $node->setNode($name, new CheckToStringNode($expr)); - } - } - - private function wrapArrayNode(Node $node, string $name): void - { - $args = $node->getNode($name); - foreach ($args as $name => $_) { - $this->wrapNode($args, $name); - } - } - - public function getPriority(): int - { - return 0; - } -} diff --git a/lib/twig/twig/src/Parser.php b/lib/twig/twig/src/Parser.php deleted file mode 100644 index 4428208fe..000000000 --- a/lib/twig/twig/src/Parser.php +++ /dev/null @@ -1,348 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig; - -use Twig\Error\SyntaxError; -use Twig\Node\BlockNode; -use Twig\Node\BlockReferenceNode; -use Twig\Node\BodyNode; -use Twig\Node\Expression\AbstractExpression; -use Twig\Node\MacroNode; -use Twig\Node\ModuleNode; -use Twig\Node\Node; -use Twig\Node\NodeCaptureInterface; -use Twig\Node\NodeOutputInterface; -use Twig\Node\PrintNode; -use Twig\Node\TextNode; -use Twig\TokenParser\TokenParserInterface; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -class Parser -{ - private $stack = []; - private $stream; - private $parent; - private $visitors; - private $expressionParser; - private $blocks; - private $blockStack; - private $macros; - private $env; - private $importedSymbols; - private $traits; - private $embeddedTemplates = []; - private $varNameSalt = 0; - - public function __construct(Environment $env) - { - $this->env = $env; - } - - public function getVarName(): string - { - return sprintf('__internal_parse_%d', $this->varNameSalt++); - } - - public function parse(TokenStream $stream, $test = null, bool $dropNeedle = false): ModuleNode - { - $vars = get_object_vars($this); - unset($vars['stack'], $vars['env'], $vars['handlers'], $vars['visitors'], $vars['expressionParser'], $vars['reservedMacroNames'], $vars['varNameSalt']); - $this->stack[] = $vars; - - // node visitors - if (null === $this->visitors) { - $this->visitors = $this->env->getNodeVisitors(); - } - - if (null === $this->expressionParser) { - $this->expressionParser = new ExpressionParser($this, $this->env); - } - - $this->stream = $stream; - $this->parent = null; - $this->blocks = []; - $this->macros = []; - $this->traits = []; - $this->blockStack = []; - $this->importedSymbols = [[]]; - $this->embeddedTemplates = []; - - try { - $body = $this->subparse($test, $dropNeedle); - - if (null !== $this->parent && null === $body = $this->filterBodyNodes($body)) { - $body = new Node(); - } - } catch (SyntaxError $e) { - if (!$e->getSourceContext()) { - $e->setSourceContext($this->stream->getSourceContext()); - } - - if (!$e->getTemplateLine()) { - $e->setTemplateLine($this->stream->getCurrent()->getLine()); - } - - throw $e; - } - - $node = new ModuleNode(new BodyNode([$body]), $this->parent, new Node($this->blocks), new Node($this->macros), new Node($this->traits), $this->embeddedTemplates, $stream->getSourceContext()); - - $traverser = new NodeTraverser($this->env, $this->visitors); - - $node = $traverser->traverse($node); - - // restore previous stack so previous parse() call can resume working - foreach (array_pop($this->stack) as $key => $val) { - $this->$key = $val; - } - - return $node; - } - - public function subparse($test, bool $dropNeedle = false): Node - { - $lineno = $this->getCurrentToken()->getLine(); - $rv = []; - while (!$this->stream->isEOF()) { - switch ($this->getCurrentToken()->getType()) { - case /* Token::TEXT_TYPE */ 0: - $token = $this->stream->next(); - $rv[] = new TextNode($token->getValue(), $token->getLine()); - break; - - case /* Token::VAR_START_TYPE */ 2: - $token = $this->stream->next(); - $expr = $this->expressionParser->parseExpression(); - $this->stream->expect(/* Token::VAR_END_TYPE */ 4); - $rv[] = new PrintNode($expr, $token->getLine()); - break; - - case /* Token::BLOCK_START_TYPE */ 1: - $this->stream->next(); - $token = $this->getCurrentToken(); - - if (/* Token::NAME_TYPE */ 5 !== $token->getType()) { - throw new SyntaxError('A block must start with a tag name.', $token->getLine(), $this->stream->getSourceContext()); - } - - if (null !== $test && $test($token)) { - if ($dropNeedle) { - $this->stream->next(); - } - - if (1 === \count($rv)) { - return $rv[0]; - } - - return new Node($rv, [], $lineno); - } - - if (!$subparser = $this->env->getTokenParser($token->getValue())) { - if (null !== $test) { - $e = new SyntaxError(sprintf('Unexpected "%s" tag', $token->getValue()), $token->getLine(), $this->stream->getSourceContext()); - - if (\is_array($test) && isset($test[0]) && $test[0] instanceof TokenParserInterface) { - $e->appendMessage(sprintf(' (expecting closing tag for the "%s" tag defined near line %s).', $test[0]->getTag(), $lineno)); - } - } else { - $e = new SyntaxError(sprintf('Unknown "%s" tag.', $token->getValue()), $token->getLine(), $this->stream->getSourceContext()); - $e->addSuggestions($token->getValue(), array_keys($this->env->getTokenParsers())); - } - - throw $e; - } - - $this->stream->next(); - - $subparser->setParser($this); - $node = $subparser->parse($token); - if (null !== $node) { - $rv[] = $node; - } - break; - - default: - throw new SyntaxError('Lexer or parser ended up in unsupported state.', $this->getCurrentToken()->getLine(), $this->stream->getSourceContext()); - } - } - - if (1 === \count($rv)) { - return $rv[0]; - } - - return new Node($rv, [], $lineno); - } - - public function getBlockStack(): array - { - return $this->blockStack; - } - - public function peekBlockStack() - { - return $this->blockStack[\count($this->blockStack) - 1] ?? null; - } - - public function popBlockStack(): void - { - array_pop($this->blockStack); - } - - public function pushBlockStack($name): void - { - $this->blockStack[] = $name; - } - - public function hasBlock(string $name): bool - { - return isset($this->blocks[$name]); - } - - public function getBlock(string $name): Node - { - return $this->blocks[$name]; - } - - public function setBlock(string $name, BlockNode $value): void - { - $this->blocks[$name] = new BodyNode([$value], [], $value->getTemplateLine()); - } - - public function hasMacro(string $name): bool - { - return isset($this->macros[$name]); - } - - public function setMacro(string $name, MacroNode $node): void - { - $this->macros[$name] = $node; - } - - public function addTrait($trait): void - { - $this->traits[] = $trait; - } - - public function hasTraits(): bool - { - return \count($this->traits) > 0; - } - - public function embedTemplate(ModuleNode $template) - { - $template->setIndex(mt_rand()); - - $this->embeddedTemplates[] = $template; - } - - public function addImportedSymbol(string $type, string $alias, string $name = null, AbstractExpression $node = null): void - { - $this->importedSymbols[0][$type][$alias] = ['name' => $name, 'node' => $node]; - } - - public function getImportedSymbol(string $type, string $alias) - { - // if the symbol does not exist in the current scope (0), try in the main/global scope (last index) - return $this->importedSymbols[0][$type][$alias] ?? ($this->importedSymbols[\count($this->importedSymbols) - 1][$type][$alias] ?? null); - } - - public function isMainScope(): bool - { - return 1 === \count($this->importedSymbols); - } - - public function pushLocalScope(): void - { - array_unshift($this->importedSymbols, []); - } - - public function popLocalScope(): void - { - array_shift($this->importedSymbols); - } - - public function getExpressionParser(): ExpressionParser - { - return $this->expressionParser; - } - - public function getParent(): ?Node - { - return $this->parent; - } - - public function setParent(?Node $parent): void - { - $this->parent = $parent; - } - - public function getStream(): TokenStream - { - return $this->stream; - } - - public function getCurrentToken(): Token - { - return $this->stream->getCurrent(); - } - - private function filterBodyNodes(Node $node, bool $nested = false): ?Node - { - // check that the body does not contain non-empty output nodes - if ( - ($node instanceof TextNode && !ctype_space($node->getAttribute('data'))) - || - (!$node instanceof TextNode && !$node instanceof BlockReferenceNode && $node instanceof NodeOutputInterface) - ) { - if (false !== strpos((string) $node, \chr(0xEF).\chr(0xBB).\chr(0xBF))) { - $t = substr($node->getAttribute('data'), 3); - if ('' === $t || ctype_space($t)) { - // bypass empty nodes starting with a BOM - return null; - } - } - - throw new SyntaxError('A template that extends another one cannot include content outside Twig blocks. Did you forget to put the content inside a {% block %} tag?', $node->getTemplateLine(), $this->stream->getSourceContext()); - } - - // bypass nodes that "capture" the output - if ($node instanceof NodeCaptureInterface) { - // a "block" tag in such a node will serve as a block definition AND be displayed in place as well - return $node; - } - - // "block" tags that are not captured (see above) are only used for defining - // the content of the block. In such a case, nesting it does not work as - // expected as the definition is not part of the default template code flow. - if ($nested && $node instanceof BlockReferenceNode) { - throw new SyntaxError('A block definition cannot be nested under non-capturing nodes.', $node->getTemplateLine(), $this->stream->getSourceContext()); - } - - if ($node instanceof NodeOutputInterface) { - return null; - } - - // here, $nested means "being at the root level of a child template" - // we need to discard the wrapping "Node" for the "body" node - $nested = $nested || Node::class !== \get_class($node); - foreach ($node as $k => $n) { - if (null !== $n && null === $this->filterBodyNodes($n, $nested)) { - $node->removeNode($k); - } - } - - return $node; - } -} diff --git a/lib/twig/twig/src/Profiler/Dumper/BaseDumper.php b/lib/twig/twig/src/Profiler/Dumper/BaseDumper.php deleted file mode 100644 index 4da43e475..000000000 --- a/lib/twig/twig/src/Profiler/Dumper/BaseDumper.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Profiler\Dumper; - -use Twig\Profiler\Profile; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -abstract class BaseDumper -{ - private $root; - - public function dump(Profile $profile): string - { - return $this->dumpProfile($profile); - } - - abstract protected function formatTemplate(Profile $profile, $prefix): string; - - abstract protected function formatNonTemplate(Profile $profile, $prefix): string; - - abstract protected function formatTime(Profile $profile, $percent): string; - - private function dumpProfile(Profile $profile, $prefix = '', $sibling = false): string - { - if ($profile->isRoot()) { - $this->root = $profile->getDuration(); - $start = $profile->getName(); - } else { - if ($profile->isTemplate()) { - $start = $this->formatTemplate($profile, $prefix); - } else { - $start = $this->formatNonTemplate($profile, $prefix); - } - $prefix .= $sibling ? '│ ' : ' '; - } - - $percent = $this->root ? $profile->getDuration() / $this->root * 100 : 0; - - if ($profile->getDuration() * 1000 < 1) { - $str = $start."\n"; - } else { - $str = sprintf("%s %s\n", $start, $this->formatTime($profile, $percent)); - } - - $nCount = \count($profile->getProfiles()); - foreach ($profile as $i => $p) { - $str .= $this->dumpProfile($p, $prefix, $i + 1 !== $nCount); - } - - return $str; - } -} diff --git a/lib/twig/twig/src/Profiler/Dumper/BlackfireDumper.php b/lib/twig/twig/src/Profiler/Dumper/BlackfireDumper.php deleted file mode 100644 index 03abe0fa0..000000000 --- a/lib/twig/twig/src/Profiler/Dumper/BlackfireDumper.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Profiler\Dumper; - -use Twig\Profiler\Profile; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -final class BlackfireDumper -{ - public function dump(Profile $profile): string - { - $data = []; - $this->dumpProfile('main()', $profile, $data); - $this->dumpChildren('main()', $profile, $data); - - $start = sprintf('%f', microtime(true)); - $str = <<<EOF -file-format: BlackfireProbe -cost-dimensions: wt mu pmu -request-start: $start - - -EOF; - - foreach ($data as $name => $values) { - $str .= "$name//{$values['ct']} {$values['wt']} {$values['mu']} {$values['pmu']}\n"; - } - - return $str; - } - - private function dumpChildren(string $parent, Profile $profile, &$data) - { - foreach ($profile as $p) { - if ($p->isTemplate()) { - $name = $p->getTemplate(); - } else { - $name = sprintf('%s::%s(%s)', $p->getTemplate(), $p->getType(), $p->getName()); - } - $this->dumpProfile(sprintf('%s==>%s', $parent, $name), $p, $data); - $this->dumpChildren($name, $p, $data); - } - } - - private function dumpProfile(string $edge, Profile $profile, &$data) - { - if (isset($data[$edge])) { - ++$data[$edge]['ct']; - $data[$edge]['wt'] += floor($profile->getDuration() * 1000000); - $data[$edge]['mu'] += $profile->getMemoryUsage(); - $data[$edge]['pmu'] += $profile->getPeakMemoryUsage(); - } else { - $data[$edge] = [ - 'ct' => 1, - 'wt' => floor($profile->getDuration() * 1000000), - 'mu' => $profile->getMemoryUsage(), - 'pmu' => $profile->getPeakMemoryUsage(), - ]; - } - } -} diff --git a/lib/twig/twig/src/Profiler/Dumper/HtmlDumper.php b/lib/twig/twig/src/Profiler/Dumper/HtmlDumper.php deleted file mode 100644 index 1f2433b4d..000000000 --- a/lib/twig/twig/src/Profiler/Dumper/HtmlDumper.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Profiler\Dumper; - -use Twig\Profiler\Profile; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -final class HtmlDumper extends BaseDumper -{ - private static $colors = [ - 'block' => '#dfd', - 'macro' => '#ddf', - 'template' => '#ffd', - 'big' => '#d44', - ]; - - public function dump(Profile $profile): string - { - return '<pre>'.parent::dump($profile).'</pre>'; - } - - protected function formatTemplate(Profile $profile, $prefix): string - { - return sprintf('%s└ <span style="background-color: %s">%s</span>', $prefix, self::$colors['template'], $profile->getTemplate()); - } - - protected function formatNonTemplate(Profile $profile, $prefix): string - { - return sprintf('%s└ %s::%s(<span style="background-color: %s">%s</span>)', $prefix, $profile->getTemplate(), $profile->getType(), isset(self::$colors[$profile->getType()]) ? self::$colors[$profile->getType()] : 'auto', $profile->getName()); - } - - protected function formatTime(Profile $profile, $percent): string - { - return sprintf('<span style="color: %s">%.2fms/%.0f%%</span>', $percent > 20 ? self::$colors['big'] : 'auto', $profile->getDuration() * 1000, $percent); - } -} diff --git a/lib/twig/twig/src/Profiler/Dumper/TextDumper.php b/lib/twig/twig/src/Profiler/Dumper/TextDumper.php deleted file mode 100644 index 31561c466..000000000 --- a/lib/twig/twig/src/Profiler/Dumper/TextDumper.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Profiler\Dumper; - -use Twig\Profiler\Profile; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -final class TextDumper extends BaseDumper -{ - protected function formatTemplate(Profile $profile, $prefix): string - { - return sprintf('%s└ %s', $prefix, $profile->getTemplate()); - } - - protected function formatNonTemplate(Profile $profile, $prefix): string - { - return sprintf('%s└ %s::%s(%s)', $prefix, $profile->getTemplate(), $profile->getType(), $profile->getName()); - } - - protected function formatTime(Profile $profile, $percent): string - { - return sprintf('%.2fms/%.0f%%', $profile->getDuration() * 1000, $percent); - } -} diff --git a/lib/twig/twig/src/Profiler/Node/EnterProfileNode.php b/lib/twig/twig/src/Profiler/Node/EnterProfileNode.php deleted file mode 100644 index 1494baf44..000000000 --- a/lib/twig/twig/src/Profiler/Node/EnterProfileNode.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Profiler\Node; - -use Twig\Compiler; -use Twig\Node\Node; - -/** - * Represents a profile enter node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class EnterProfileNode extends Node -{ - public function __construct(string $extensionName, string $type, string $name, string $varName) - { - parent::__construct([], ['extension_name' => $extensionName, 'name' => $name, 'type' => $type, 'var_name' => $varName]); - } - - public function compile(Compiler $compiler): void - { - $compiler - ->write(sprintf('$%s = $this->extensions[', $this->getAttribute('var_name'))) - ->repr($this->getAttribute('extension_name')) - ->raw("];\n") - ->write(sprintf('$%s->enter($%s = new \Twig\Profiler\Profile($this->getTemplateName(), ', $this->getAttribute('var_name'), $this->getAttribute('var_name').'_prof')) - ->repr($this->getAttribute('type')) - ->raw(', ') - ->repr($this->getAttribute('name')) - ->raw("));\n\n") - ; - } -} diff --git a/lib/twig/twig/src/Profiler/Node/LeaveProfileNode.php b/lib/twig/twig/src/Profiler/Node/LeaveProfileNode.php deleted file mode 100644 index 94cebbaa8..000000000 --- a/lib/twig/twig/src/Profiler/Node/LeaveProfileNode.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Profiler\Node; - -use Twig\Compiler; -use Twig\Node\Node; - -/** - * Represents a profile leave node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class LeaveProfileNode extends Node -{ - public function __construct(string $varName) - { - parent::__construct([], ['var_name' => $varName]); - } - - public function compile(Compiler $compiler): void - { - $compiler - ->write("\n") - ->write(sprintf("\$%s->leave(\$%s);\n\n", $this->getAttribute('var_name'), $this->getAttribute('var_name').'_prof')) - ; - } -} diff --git a/lib/twig/twig/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php b/lib/twig/twig/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php deleted file mode 100644 index 91abee807..000000000 --- a/lib/twig/twig/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php +++ /dev/null @@ -1,70 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Profiler\NodeVisitor; - -use Twig\Environment; -use Twig\Node\BlockNode; -use Twig\Node\BodyNode; -use Twig\Node\MacroNode; -use Twig\Node\ModuleNode; -use Twig\Node\Node; -use Twig\NodeVisitor\NodeVisitorInterface; -use Twig\Profiler\Node\EnterProfileNode; -use Twig\Profiler\Node\LeaveProfileNode; -use Twig\Profiler\Profile; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -final class ProfilerNodeVisitor implements NodeVisitorInterface -{ - private $extensionName; - private $varName; - - public function __construct(string $extensionName) - { - $this->extensionName = $extensionName; - $this->varName = sprintf('__internal_%s', hash(\PHP_VERSION_ID < 80100 ? 'sha256' : 'xxh128', $extensionName)); - } - - public function enterNode(Node $node, Environment $env): Node - { - return $node; - } - - public function leaveNode(Node $node, Environment $env): ?Node - { - if ($node instanceof ModuleNode) { - $node->setNode('display_start', new Node([new EnterProfileNode($this->extensionName, Profile::TEMPLATE, $node->getTemplateName(), $this->varName), $node->getNode('display_start')])); - $node->setNode('display_end', new Node([new LeaveProfileNode($this->varName), $node->getNode('display_end')])); - } elseif ($node instanceof BlockNode) { - $node->setNode('body', new BodyNode([ - new EnterProfileNode($this->extensionName, Profile::BLOCK, $node->getAttribute('name'), $this->varName), - $node->getNode('body'), - new LeaveProfileNode($this->varName), - ])); - } elseif ($node instanceof MacroNode) { - $node->setNode('body', new BodyNode([ - new EnterProfileNode($this->extensionName, Profile::MACRO, $node->getAttribute('name'), $this->varName), - $node->getNode('body'), - new LeaveProfileNode($this->varName), - ])); - } - - return $node; - } - - public function getPriority(): int - { - return 0; - } -} diff --git a/lib/twig/twig/src/Profiler/Profile.php b/lib/twig/twig/src/Profiler/Profile.php deleted file mode 100644 index 252ca9b0c..000000000 --- a/lib/twig/twig/src/Profiler/Profile.php +++ /dev/null @@ -1,181 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Profiler; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -final class Profile implements \IteratorAggregate, \Serializable -{ - public const ROOT = 'ROOT'; - public const BLOCK = 'block'; - public const TEMPLATE = 'template'; - public const MACRO = 'macro'; - - private $template; - private $name; - private $type; - private $starts = []; - private $ends = []; - private $profiles = []; - - public function __construct(string $template = 'main', string $type = self::ROOT, string $name = 'main') - { - $this->template = $template; - $this->type = $type; - $this->name = 0 === strpos($name, '__internal_') ? 'INTERNAL' : $name; - $this->enter(); - } - - public function getTemplate(): string - { - return $this->template; - } - - public function getType(): string - { - return $this->type; - } - - public function getName(): string - { - return $this->name; - } - - public function isRoot(): bool - { - return self::ROOT === $this->type; - } - - public function isTemplate(): bool - { - return self::TEMPLATE === $this->type; - } - - public function isBlock(): bool - { - return self::BLOCK === $this->type; - } - - public function isMacro(): bool - { - return self::MACRO === $this->type; - } - - /** - * @return Profile[] - */ - public function getProfiles(): array - { - return $this->profiles; - } - - public function addProfile(self $profile): void - { - $this->profiles[] = $profile; - } - - /** - * Returns the duration in microseconds. - */ - public function getDuration(): float - { - if ($this->isRoot() && $this->profiles) { - // for the root node with children, duration is the sum of all child durations - $duration = 0; - foreach ($this->profiles as $profile) { - $duration += $profile->getDuration(); - } - - return $duration; - } - - return isset($this->ends['wt']) && isset($this->starts['wt']) ? $this->ends['wt'] - $this->starts['wt'] : 0; - } - - /** - * Returns the memory usage in bytes. - */ - public function getMemoryUsage(): int - { - return isset($this->ends['mu']) && isset($this->starts['mu']) ? $this->ends['mu'] - $this->starts['mu'] : 0; - } - - /** - * Returns the peak memory usage in bytes. - */ - public function getPeakMemoryUsage(): int - { - return isset($this->ends['pmu']) && isset($this->starts['pmu']) ? $this->ends['pmu'] - $this->starts['pmu'] : 0; - } - - /** - * Starts the profiling. - */ - public function enter(): void - { - $this->starts = [ - 'wt' => microtime(true), - 'mu' => memory_get_usage(), - 'pmu' => memory_get_peak_usage(), - ]; - } - - /** - * Stops the profiling. - */ - public function leave(): void - { - $this->ends = [ - 'wt' => microtime(true), - 'mu' => memory_get_usage(), - 'pmu' => memory_get_peak_usage(), - ]; - } - - public function reset(): void - { - $this->starts = $this->ends = $this->profiles = []; - $this->enter(); - } - - public function getIterator(): \Traversable - { - return new \ArrayIterator($this->profiles); - } - - public function serialize(): string - { - return serialize($this->__serialize()); - } - - public function unserialize($data): void - { - $this->__unserialize(unserialize($data)); - } - - /** - * @internal - */ - public function __serialize(): array - { - return [$this->template, $this->name, $this->type, $this->starts, $this->ends, $this->profiles]; - } - - /** - * @internal - */ - public function __unserialize(array $data): void - { - list($this->template, $this->name, $this->type, $this->starts, $this->ends, $this->profiles) = $data; - } -} diff --git a/lib/twig/twig/src/RuntimeLoader/ContainerRuntimeLoader.php b/lib/twig/twig/src/RuntimeLoader/ContainerRuntimeLoader.php deleted file mode 100644 index b360d7bea..000000000 --- a/lib/twig/twig/src/RuntimeLoader/ContainerRuntimeLoader.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\RuntimeLoader; - -use Psr\Container\ContainerInterface; - -/** - * Lazily loads Twig runtime implementations from a PSR-11 container. - * - * Note that the runtime services MUST use their class names as identifiers. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Robin Chalas <robin.chalas@gmail.com> - */ -class ContainerRuntimeLoader implements RuntimeLoaderInterface -{ - private $container; - - public function __construct(ContainerInterface $container) - { - $this->container = $container; - } - - public function load(string $class) - { - return $this->container->has($class) ? $this->container->get($class) : null; - } -} diff --git a/lib/twig/twig/src/RuntimeLoader/FactoryRuntimeLoader.php b/lib/twig/twig/src/RuntimeLoader/FactoryRuntimeLoader.php deleted file mode 100644 index 130648392..000000000 --- a/lib/twig/twig/src/RuntimeLoader/FactoryRuntimeLoader.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\RuntimeLoader; - -/** - * Lazy loads the runtime implementations for a Twig element. - * - * @author Robin Chalas <robin.chalas@gmail.com> - */ -class FactoryRuntimeLoader implements RuntimeLoaderInterface -{ - private $map; - - /** - * @param array $map An array where keys are class names and values factory callables - */ - public function __construct(array $map = []) - { - $this->map = $map; - } - - public function load(string $class) - { - if (!isset($this->map[$class])) { - return null; - } - - $runtimeFactory = $this->map[$class]; - - return $runtimeFactory(); - } -} diff --git a/lib/twig/twig/src/RuntimeLoader/RuntimeLoaderInterface.php b/lib/twig/twig/src/RuntimeLoader/RuntimeLoaderInterface.php deleted file mode 100644 index 9e5b2048e..000000000 --- a/lib/twig/twig/src/RuntimeLoader/RuntimeLoaderInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\RuntimeLoader; - -/** - * Creates runtime implementations for Twig elements (filters/functions/tests). - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface RuntimeLoaderInterface -{ - /** - * Creates the runtime implementation of a Twig element (filter/function/test). - * - * @return object|null The runtime instance or null if the loader does not know how to create the runtime for this class - */ - public function load(string $class); -} diff --git a/lib/twig/twig/src/Sandbox/SecurityError.php b/lib/twig/twig/src/Sandbox/SecurityError.php deleted file mode 100644 index 30a404f28..000000000 --- a/lib/twig/twig/src/Sandbox/SecurityError.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Sandbox; - -use Twig\Error\Error; - -/** - * Exception thrown when a security error occurs at runtime. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class SecurityError extends Error -{ -} diff --git a/lib/twig/twig/src/Sandbox/SecurityNotAllowedFilterError.php b/lib/twig/twig/src/Sandbox/SecurityNotAllowedFilterError.php deleted file mode 100644 index 02d306360..000000000 --- a/lib/twig/twig/src/Sandbox/SecurityNotAllowedFilterError.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Sandbox; - -/** - * Exception thrown when a not allowed filter is used in a template. - * - * @author Martin Hasoň <martin.hason@gmail.com> - */ -final class SecurityNotAllowedFilterError extends SecurityError -{ - private $filterName; - - public function __construct(string $message, string $functionName) - { - parent::__construct($message); - $this->filterName = $functionName; - } - - public function getFilterName(): string - { - return $this->filterName; - } -} diff --git a/lib/twig/twig/src/Sandbox/SecurityNotAllowedFunctionError.php b/lib/twig/twig/src/Sandbox/SecurityNotAllowedFunctionError.php deleted file mode 100644 index 4f76dc6ec..000000000 --- a/lib/twig/twig/src/Sandbox/SecurityNotAllowedFunctionError.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Sandbox; - -/** - * Exception thrown when a not allowed function is used in a template. - * - * @author Martin Hasoň <martin.hason@gmail.com> - */ -final class SecurityNotAllowedFunctionError extends SecurityError -{ - private $functionName; - - public function __construct(string $message, string $functionName) - { - parent::__construct($message); - $this->functionName = $functionName; - } - - public function getFunctionName(): string - { - return $this->functionName; - } -} diff --git a/lib/twig/twig/src/Sandbox/SecurityNotAllowedMethodError.php b/lib/twig/twig/src/Sandbox/SecurityNotAllowedMethodError.php deleted file mode 100644 index 8df9d0baa..000000000 --- a/lib/twig/twig/src/Sandbox/SecurityNotAllowedMethodError.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Sandbox; - -/** - * Exception thrown when a not allowed class method is used in a template. - * - * @author Kit Burton-Senior <mail@kitbs.com> - */ -final class SecurityNotAllowedMethodError extends SecurityError -{ - private $className; - private $methodName; - - public function __construct(string $message, string $className, string $methodName) - { - parent::__construct($message); - $this->className = $className; - $this->methodName = $methodName; - } - - public function getClassName(): string - { - return $this->className; - } - - public function getMethodName() - { - return $this->methodName; - } -} diff --git a/lib/twig/twig/src/Sandbox/SecurityNotAllowedPropertyError.php b/lib/twig/twig/src/Sandbox/SecurityNotAllowedPropertyError.php deleted file mode 100644 index 42ec4f386..000000000 --- a/lib/twig/twig/src/Sandbox/SecurityNotAllowedPropertyError.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Sandbox; - -/** - * Exception thrown when a not allowed class property is used in a template. - * - * @author Kit Burton-Senior <mail@kitbs.com> - */ -final class SecurityNotAllowedPropertyError extends SecurityError -{ - private $className; - private $propertyName; - - public function __construct(string $message, string $className, string $propertyName) - { - parent::__construct($message); - $this->className = $className; - $this->propertyName = $propertyName; - } - - public function getClassName(): string - { - return $this->className; - } - - public function getPropertyName() - { - return $this->propertyName; - } -} diff --git a/lib/twig/twig/src/Sandbox/SecurityNotAllowedTagError.php b/lib/twig/twig/src/Sandbox/SecurityNotAllowedTagError.php deleted file mode 100644 index 4522150e1..000000000 --- a/lib/twig/twig/src/Sandbox/SecurityNotAllowedTagError.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Sandbox; - -/** - * Exception thrown when a not allowed tag is used in a template. - * - * @author Martin Hasoň <martin.hason@gmail.com> - */ -final class SecurityNotAllowedTagError extends SecurityError -{ - private $tagName; - - public function __construct(string $message, string $tagName) - { - parent::__construct($message); - $this->tagName = $tagName; - } - - public function getTagName(): string - { - return $this->tagName; - } -} diff --git a/lib/twig/twig/src/Sandbox/SecurityPolicy.php b/lib/twig/twig/src/Sandbox/SecurityPolicy.php deleted file mode 100644 index 2fc0d0131..000000000 --- a/lib/twig/twig/src/Sandbox/SecurityPolicy.php +++ /dev/null @@ -1,126 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Sandbox; - -use Twig\Markup; -use Twig\Template; - -/** - * Represents a security policy which need to be enforced when sandbox mode is enabled. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class SecurityPolicy implements SecurityPolicyInterface -{ - private $allowedTags; - private $allowedFilters; - private $allowedMethods; - private $allowedProperties; - private $allowedFunctions; - - public function __construct(array $allowedTags = [], array $allowedFilters = [], array $allowedMethods = [], array $allowedProperties = [], array $allowedFunctions = []) - { - $this->allowedTags = $allowedTags; - $this->allowedFilters = $allowedFilters; - $this->setAllowedMethods($allowedMethods); - $this->allowedProperties = $allowedProperties; - $this->allowedFunctions = $allowedFunctions; - } - - public function setAllowedTags(array $tags): void - { - $this->allowedTags = $tags; - } - - public function setAllowedFilters(array $filters): void - { - $this->allowedFilters = $filters; - } - - public function setAllowedMethods(array $methods): void - { - $this->allowedMethods = []; - foreach ($methods as $class => $m) { - $this->allowedMethods[$class] = array_map(function ($value) { return strtr($value, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); }, \is_array($m) ? $m : [$m]); - } - } - - public function setAllowedProperties(array $properties): void - { - $this->allowedProperties = $properties; - } - - public function setAllowedFunctions(array $functions): void - { - $this->allowedFunctions = $functions; - } - - public function checkSecurity($tags, $filters, $functions): void - { - foreach ($tags as $tag) { - if (!\in_array($tag, $this->allowedTags)) { - throw new SecurityNotAllowedTagError(sprintf('Tag "%s" is not allowed.', $tag), $tag); - } - } - - foreach ($filters as $filter) { - if (!\in_array($filter, $this->allowedFilters)) { - throw new SecurityNotAllowedFilterError(sprintf('Filter "%s" is not allowed.', $filter), $filter); - } - } - - foreach ($functions as $function) { - if (!\in_array($function, $this->allowedFunctions)) { - throw new SecurityNotAllowedFunctionError(sprintf('Function "%s" is not allowed.', $function), $function); - } - } - } - - public function checkMethodAllowed($obj, $method): void - { - if ($obj instanceof Template || $obj instanceof Markup) { - return; - } - - $allowed = false; - $method = strtr($method, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); - foreach ($this->allowedMethods as $class => $methods) { - if ($obj instanceof $class) { - $allowed = \in_array($method, $methods); - - break; - } - } - - if (!$allowed) { - $class = \get_class($obj); - throw new SecurityNotAllowedMethodError(sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, $class), $class, $method); - } - } - - public function checkPropertyAllowed($obj, $property): void - { - $allowed = false; - foreach ($this->allowedProperties as $class => $properties) { - if ($obj instanceof $class) { - $allowed = \in_array($property, \is_array($properties) ? $properties : [$properties]); - - break; - } - } - - if (!$allowed) { - $class = \get_class($obj); - throw new SecurityNotAllowedPropertyError(sprintf('Calling "%s" property on a "%s" object is not allowed.', $property, $class), $class, $property); - } - } -} diff --git a/lib/twig/twig/src/Sandbox/SecurityPolicyInterface.php b/lib/twig/twig/src/Sandbox/SecurityPolicyInterface.php deleted file mode 100644 index 36471c54c..000000000 --- a/lib/twig/twig/src/Sandbox/SecurityPolicyInterface.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Sandbox; - -/** - * Interface that all security policy classes must implements. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface SecurityPolicyInterface -{ - /** - * @param string[] $tags - * @param string[] $filters - * @param string[] $functions - * - * @throws SecurityError - */ - public function checkSecurity($tags, $filters, $functions): void; - - /** - * @param object $obj - * @param string $method - * - * @throws SecurityNotAllowedMethodError - */ - public function checkMethodAllowed($obj, $method): void; - - /** - * @param object $obj - * @param string $property - * - * @throws SecurityNotAllowedPropertyError - */ - public function checkPropertyAllowed($obj, $property): void; -} diff --git a/lib/twig/twig/src/Source.php b/lib/twig/twig/src/Source.php deleted file mode 100644 index 3cb02403c..000000000 --- a/lib/twig/twig/src/Source.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig; - -/** - * Holds information about a non-compiled Twig template. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class Source -{ - private $code; - private $name; - private $path; - - /** - * @param string $code The template source code - * @param string $name The template logical name - * @param string $path The filesystem path of the template if any - */ - public function __construct(string $code, string $name, string $path = '') - { - $this->code = $code; - $this->name = $name; - $this->path = $path; - } - - public function getCode(): string - { - return $this->code; - } - - public function getName(): string - { - return $this->name; - } - - public function getPath(): string - { - return $this->path; - } -} diff --git a/lib/twig/twig/src/Template.php b/lib/twig/twig/src/Template.php deleted file mode 100644 index e04bd04a6..000000000 --- a/lib/twig/twig/src/Template.php +++ /dev/null @@ -1,422 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig; - -use Twig\Error\Error; -use Twig\Error\LoaderError; -use Twig\Error\RuntimeError; - -/** - * Default base class for compiled templates. - * - * This class is an implementation detail of how template compilation currently - * works, which might change. It should never be used directly. Use $twig->load() - * instead, which returns an instance of \Twig\TemplateWrapper. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @internal - */ -abstract class Template -{ - public const ANY_CALL = 'any'; - public const ARRAY_CALL = 'array'; - public const METHOD_CALL = 'method'; - - protected $parent; - protected $parents = []; - protected $env; - protected $blocks = []; - protected $traits = []; - protected $extensions = []; - protected $sandbox; - - public function __construct(Environment $env) - { - $this->env = $env; - $this->extensions = $env->getExtensions(); - } - - /** - * Returns the template name. - * - * @return string The template name - */ - abstract public function getTemplateName(); - - /** - * Returns debug information about the template. - * - * @return array Debug information - */ - abstract public function getDebugInfo(); - - /** - * Returns information about the original template source code. - * - * @return Source - */ - abstract public function getSourceContext(); - - /** - * Returns the parent template. - * - * This method is for internal use only and should never be called - * directly. - * - * @return Template|TemplateWrapper|false The parent template or false if there is no parent - */ - public function getParent(array $context) - { - if (null !== $this->parent) { - return $this->parent; - } - - try { - $parent = $this->doGetParent($context); - - if (false === $parent) { - return false; - } - - if ($parent instanceof self || $parent instanceof TemplateWrapper) { - return $this->parents[$parent->getSourceContext()->getName()] = $parent; - } - - if (!isset($this->parents[$parent])) { - $this->parents[$parent] = $this->loadTemplate($parent); - } - } catch (LoaderError $e) { - $e->setSourceContext(null); - $e->guess(); - - throw $e; - } - - return $this->parents[$parent]; - } - - protected function doGetParent(array $context) - { - return false; - } - - public function isTraitable() - { - return true; - } - - /** - * Displays a parent block. - * - * This method is for internal use only and should never be called - * directly. - * - * @param string $name The block name to display from the parent - * @param array $context The context - * @param array $blocks The current set of blocks - */ - public function displayParentBlock($name, array $context, array $blocks = []) - { - if (isset($this->traits[$name])) { - $this->traits[$name][0]->displayBlock($name, $context, $blocks, false); - } elseif (false !== $parent = $this->getParent($context)) { - $parent->displayBlock($name, $context, $blocks, false); - } else { - throw new RuntimeError(sprintf('The template has no parent and no traits defining the "%s" block.', $name), -1, $this->getSourceContext()); - } - } - - /** - * Displays a block. - * - * This method is for internal use only and should never be called - * directly. - * - * @param string $name The block name to display - * @param array $context The context - * @param array $blocks The current set of blocks - * @param bool $useBlocks Whether to use the current set of blocks - */ - public function displayBlock($name, array $context, array $blocks = [], $useBlocks = true, self $templateContext = null) - { - if ($useBlocks && isset($blocks[$name])) { - $template = $blocks[$name][0]; - $block = $blocks[$name][1]; - } elseif (isset($this->blocks[$name])) { - $template = $this->blocks[$name][0]; - $block = $this->blocks[$name][1]; - } else { - $template = null; - $block = null; - } - - // avoid RCEs when sandbox is enabled - if (null !== $template && !$template instanceof self) { - throw new \LogicException('A block must be a method on a \Twig\Template instance.'); - } - - if (null !== $template) { - try { - $template->$block($context, $blocks); - } catch (Error $e) { - if (!$e->getSourceContext()) { - $e->setSourceContext($template->getSourceContext()); - } - - // this is mostly useful for \Twig\Error\LoaderError exceptions - // see \Twig\Error\LoaderError - if (-1 === $e->getTemplateLine()) { - $e->guess(); - } - - throw $e; - } catch (\Exception $e) { - $e = new RuntimeError(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $template->getSourceContext(), $e); - $e->guess(); - - throw $e; - } - } elseif (false !== $parent = $this->getParent($context)) { - $parent->displayBlock($name, $context, array_merge($this->blocks, $blocks), false, $templateContext ?? $this); - } elseif (isset($blocks[$name])) { - throw new RuntimeError(sprintf('Block "%s" should not call parent() in "%s" as the block does not exist in the parent template "%s".', $name, $blocks[$name][0]->getTemplateName(), $this->getTemplateName()), -1, $blocks[$name][0]->getSourceContext()); - } else { - throw new RuntimeError(sprintf('Block "%s" on template "%s" does not exist.', $name, $this->getTemplateName()), -1, ($templateContext ?? $this)->getSourceContext()); - } - } - - /** - * Renders a parent block. - * - * This method is for internal use only and should never be called - * directly. - * - * @param string $name The block name to render from the parent - * @param array $context The context - * @param array $blocks The current set of blocks - * - * @return string The rendered block - */ - public function renderParentBlock($name, array $context, array $blocks = []) - { - if ($this->env->isDebug()) { - ob_start(); - } else { - ob_start(function () { return ''; }); - } - $this->displayParentBlock($name, $context, $blocks); - - return ob_get_clean(); - } - - /** - * Renders a block. - * - * This method is for internal use only and should never be called - * directly. - * - * @param string $name The block name to render - * @param array $context The context - * @param array $blocks The current set of blocks - * @param bool $useBlocks Whether to use the current set of blocks - * - * @return string The rendered block - */ - public function renderBlock($name, array $context, array $blocks = [], $useBlocks = true) - { - if ($this->env->isDebug()) { - ob_start(); - } else { - ob_start(function () { return ''; }); - } - $this->displayBlock($name, $context, $blocks, $useBlocks); - - return ob_get_clean(); - } - - /** - * Returns whether a block exists or not in the current context of the template. - * - * This method checks blocks defined in the current template - * or defined in "used" traits or defined in parent templates. - * - * @param string $name The block name - * @param array $context The context - * @param array $blocks The current set of blocks - * - * @return bool true if the block exists, false otherwise - */ - public function hasBlock($name, array $context, array $blocks = []) - { - if (isset($blocks[$name])) { - return $blocks[$name][0] instanceof self; - } - - if (isset($this->blocks[$name])) { - return true; - } - - if (false !== $parent = $this->getParent($context)) { - return $parent->hasBlock($name, $context); - } - - return false; - } - - /** - * Returns all block names in the current context of the template. - * - * This method checks blocks defined in the current template - * or defined in "used" traits or defined in parent templates. - * - * @param array $context The context - * @param array $blocks The current set of blocks - * - * @return array An array of block names - */ - public function getBlockNames(array $context, array $blocks = []) - { - $names = array_merge(array_keys($blocks), array_keys($this->blocks)); - - if (false !== $parent = $this->getParent($context)) { - $names = array_merge($names, $parent->getBlockNames($context)); - } - - return array_unique($names); - } - - /** - * @return Template|TemplateWrapper - */ - protected function loadTemplate($template, $templateName = null, $line = null, $index = null) - { - try { - if (\is_array($template)) { - return $this->env->resolveTemplate($template); - } - - if ($template instanceof self || $template instanceof TemplateWrapper) { - return $template; - } - - if ($template === $this->getTemplateName()) { - $class = static::class; - if (false !== $pos = strrpos($class, '___', -1)) { - $class = substr($class, 0, $pos); - } - } else { - $class = $this->env->getTemplateClass($template); - } - - return $this->env->loadTemplate($class, $template, $index); - } catch (Error $e) { - if (!$e->getSourceContext()) { - $e->setSourceContext($templateName ? new Source('', $templateName) : $this->getSourceContext()); - } - - if ($e->getTemplateLine() > 0) { - throw $e; - } - - if (!$line) { - $e->guess(); - } else { - $e->setTemplateLine($line); - } - - throw $e; - } - } - - /** - * @internal - * - * @return Template - */ - public function unwrap() - { - return $this; - } - - /** - * Returns all blocks. - * - * This method is for internal use only and should never be called - * directly. - * - * @return array An array of blocks - */ - public function getBlocks() - { - return $this->blocks; - } - - public function display(array $context, array $blocks = []) - { - $this->displayWithErrorHandling($this->env->mergeGlobals($context), array_merge($this->blocks, $blocks)); - } - - public function render(array $context) - { - $level = ob_get_level(); - if ($this->env->isDebug()) { - ob_start(); - } else { - ob_start(function () { return ''; }); - } - try { - $this->display($context); - } catch (\Throwable $e) { - while (ob_get_level() > $level) { - ob_end_clean(); - } - - throw $e; - } - - return ob_get_clean(); - } - - protected function displayWithErrorHandling(array $context, array $blocks = []) - { - try { - $this->doDisplay($context, $blocks); - } catch (Error $e) { - if (!$e->getSourceContext()) { - $e->setSourceContext($this->getSourceContext()); - } - - // this is mostly useful for \Twig\Error\LoaderError exceptions - // see \Twig\Error\LoaderError - if (-1 === $e->getTemplateLine()) { - $e->guess(); - } - - throw $e; - } catch (\Exception $e) { - $e = new RuntimeError(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $this->getSourceContext(), $e); - $e->guess(); - - throw $e; - } - } - - /** - * Auto-generated method to display the template with the given context. - * - * @param array $context An array of parameters to pass to the template - * @param array $blocks An array of blocks to pass to the template - */ - abstract protected function doDisplay(array $context, array $blocks = []); -} diff --git a/lib/twig/twig/src/TemplateWrapper.php b/lib/twig/twig/src/TemplateWrapper.php deleted file mode 100644 index c9c6b07c6..000000000 --- a/lib/twig/twig/src/TemplateWrapper.php +++ /dev/null @@ -1,109 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig; - -/** - * Exposes a template to userland. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class TemplateWrapper -{ - private $env; - private $template; - - /** - * This method is for internal use only and should never be called - * directly (use Twig\Environment::load() instead). - * - * @internal - */ - public function __construct(Environment $env, Template $template) - { - $this->env = $env; - $this->template = $template; - } - - public function render(array $context = []): string - { - // using func_get_args() allows to not expose the blocks argument - // as it should only be used by internal code - return $this->template->render($context, \func_get_args()[1] ?? []); - } - - public function display(array $context = []) - { - // using func_get_args() allows to not expose the blocks argument - // as it should only be used by internal code - $this->template->display($context, \func_get_args()[1] ?? []); - } - - public function hasBlock(string $name, array $context = []): bool - { - return $this->template->hasBlock($name, $context); - } - - /** - * @return string[] An array of defined template block names - */ - public function getBlockNames(array $context = []): array - { - return $this->template->getBlockNames($context); - } - - public function renderBlock(string $name, array $context = []): string - { - $context = $this->env->mergeGlobals($context); - $level = ob_get_level(); - if ($this->env->isDebug()) { - ob_start(); - } else { - ob_start(function () { return ''; }); - } - try { - $this->template->displayBlock($name, $context); - } catch (\Throwable $e) { - while (ob_get_level() > $level) { - ob_end_clean(); - } - - throw $e; - } - - return ob_get_clean(); - } - - public function displayBlock(string $name, array $context = []) - { - $this->template->displayBlock($name, $this->env->mergeGlobals($context)); - } - - public function getSourceContext(): Source - { - return $this->template->getSourceContext(); - } - - public function getTemplateName(): string - { - return $this->template->getTemplateName(); - } - - /** - * @internal - * - * @return Template - */ - public function unwrap() - { - return $this->template; - } -} diff --git a/lib/twig/twig/src/Token.php b/lib/twig/twig/src/Token.php deleted file mode 100644 index 53a6cafc3..000000000 --- a/lib/twig/twig/src/Token.php +++ /dev/null @@ -1,178 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -final class Token -{ - private $value; - private $type; - private $lineno; - - public const EOF_TYPE = -1; - public const TEXT_TYPE = 0; - public const BLOCK_START_TYPE = 1; - public const VAR_START_TYPE = 2; - public const BLOCK_END_TYPE = 3; - public const VAR_END_TYPE = 4; - public const NAME_TYPE = 5; - public const NUMBER_TYPE = 6; - public const STRING_TYPE = 7; - public const OPERATOR_TYPE = 8; - public const PUNCTUATION_TYPE = 9; - public const INTERPOLATION_START_TYPE = 10; - public const INTERPOLATION_END_TYPE = 11; - public const ARROW_TYPE = 12; - - public function __construct(int $type, $value, int $lineno) - { - $this->type = $type; - $this->value = $value; - $this->lineno = $lineno; - } - - public function __toString() - { - return sprintf('%s(%s)', self::typeToString($this->type, true), $this->value); - } - - /** - * Tests the current token for a type and/or a value. - * - * Parameters may be: - * * just type - * * type and value (or array of possible values) - * * just value (or array of possible values) (NAME_TYPE is used as type) - * - * @param array|string|int $type The type to test - * @param array|string|null $values The token value - */ - public function test($type, $values = null): bool - { - if (null === $values && !\is_int($type)) { - $values = $type; - $type = self::NAME_TYPE; - } - - return ($this->type === $type) && ( - null === $values || - (\is_array($values) && \in_array($this->value, $values)) || - $this->value == $values - ); - } - - public function getLine(): int - { - return $this->lineno; - } - - public function getType(): int - { - return $this->type; - } - - public function getValue() - { - return $this->value; - } - - public static function typeToString(int $type, bool $short = false): string - { - switch ($type) { - case self::EOF_TYPE: - $name = 'EOF_TYPE'; - break; - case self::TEXT_TYPE: - $name = 'TEXT_TYPE'; - break; - case self::BLOCK_START_TYPE: - $name = 'BLOCK_START_TYPE'; - break; - case self::VAR_START_TYPE: - $name = 'VAR_START_TYPE'; - break; - case self::BLOCK_END_TYPE: - $name = 'BLOCK_END_TYPE'; - break; - case self::VAR_END_TYPE: - $name = 'VAR_END_TYPE'; - break; - case self::NAME_TYPE: - $name = 'NAME_TYPE'; - break; - case self::NUMBER_TYPE: - $name = 'NUMBER_TYPE'; - break; - case self::STRING_TYPE: - $name = 'STRING_TYPE'; - break; - case self::OPERATOR_TYPE: - $name = 'OPERATOR_TYPE'; - break; - case self::PUNCTUATION_TYPE: - $name = 'PUNCTUATION_TYPE'; - break; - case self::INTERPOLATION_START_TYPE: - $name = 'INTERPOLATION_START_TYPE'; - break; - case self::INTERPOLATION_END_TYPE: - $name = 'INTERPOLATION_END_TYPE'; - break; - case self::ARROW_TYPE: - $name = 'ARROW_TYPE'; - break; - default: - throw new \LogicException(sprintf('Token of type "%s" does not exist.', $type)); - } - - return $short ? $name : 'Twig\Token::'.$name; - } - - public static function typeToEnglish(int $type): string - { - switch ($type) { - case self::EOF_TYPE: - return 'end of template'; - case self::TEXT_TYPE: - return 'text'; - case self::BLOCK_START_TYPE: - return 'begin of statement block'; - case self::VAR_START_TYPE: - return 'begin of print statement'; - case self::BLOCK_END_TYPE: - return 'end of statement block'; - case self::VAR_END_TYPE: - return 'end of print statement'; - case self::NAME_TYPE: - return 'name'; - case self::NUMBER_TYPE: - return 'number'; - case self::STRING_TYPE: - return 'string'; - case self::OPERATOR_TYPE: - return 'operator'; - case self::PUNCTUATION_TYPE: - return 'punctuation'; - case self::INTERPOLATION_START_TYPE: - return 'begin of string interpolation'; - case self::INTERPOLATION_END_TYPE: - return 'end of string interpolation'; - case self::ARROW_TYPE: - return 'arrow function'; - default: - throw new \LogicException(sprintf('Token of type "%s" does not exist.', $type)); - } - } -} diff --git a/lib/twig/twig/src/TokenParser/AbstractTokenParser.php b/lib/twig/twig/src/TokenParser/AbstractTokenParser.php deleted file mode 100644 index 720ea6762..000000000 --- a/lib/twig/twig/src/TokenParser/AbstractTokenParser.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\TokenParser; - -use Twig\Parser; - -/** - * Base class for all token parsers. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -abstract class AbstractTokenParser implements TokenParserInterface -{ - /** - * @var Parser - */ - protected $parser; - - public function setParser(Parser $parser): void - { - $this->parser = $parser; - } -} diff --git a/lib/twig/twig/src/TokenParser/ApplyTokenParser.php b/lib/twig/twig/src/TokenParser/ApplyTokenParser.php deleted file mode 100644 index 4dbf30406..000000000 --- a/lib/twig/twig/src/TokenParser/ApplyTokenParser.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\TokenParser; - -use Twig\Node\Expression\TempNameExpression; -use Twig\Node\Node; -use Twig\Node\PrintNode; -use Twig\Node\SetNode; -use Twig\Token; - -/** - * Applies filters on a section of a template. - * - * {% apply upper %} - * This text becomes uppercase - * {% endapply %} - * - * @internal - */ -final class ApplyTokenParser extends AbstractTokenParser -{ - public function parse(Token $token): Node - { - $lineno = $token->getLine(); - $name = $this->parser->getVarName(); - - $ref = new TempNameExpression($name, $lineno); - $ref->setAttribute('always_defined', true); - - $filter = $this->parser->getExpressionParser()->parseFilterExpressionRaw($ref, $this->getTag()); - - $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); - $body = $this->parser->subparse([$this, 'decideApplyEnd'], true); - $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); - - return new Node([ - new SetNode(true, $ref, $body, $lineno, $this->getTag()), - new PrintNode($filter, $lineno, $this->getTag()), - ]); - } - - public function decideApplyEnd(Token $token): bool - { - return $token->test('endapply'); - } - - public function getTag(): string - { - return 'apply'; - } -} diff --git a/lib/twig/twig/src/TokenParser/AutoEscapeTokenParser.php b/lib/twig/twig/src/TokenParser/AutoEscapeTokenParser.php deleted file mode 100644 index b674bea4a..000000000 --- a/lib/twig/twig/src/TokenParser/AutoEscapeTokenParser.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\TokenParser; - -use Twig\Error\SyntaxError; -use Twig\Node\AutoEscapeNode; -use Twig\Node\Expression\ConstantExpression; -use Twig\Node\Node; -use Twig\Token; - -/** - * Marks a section of a template to be escaped or not. - * - * @internal - */ -final class AutoEscapeTokenParser extends AbstractTokenParser -{ - public function parse(Token $token): Node - { - $lineno = $token->getLine(); - $stream = $this->parser->getStream(); - - if ($stream->test(/* Token::BLOCK_END_TYPE */ 3)) { - $value = 'html'; - } else { - $expr = $this->parser->getExpressionParser()->parseExpression(); - if (!$expr instanceof ConstantExpression) { - throw new SyntaxError('An escaping strategy must be a string or false.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - $value = $expr->getAttribute('value'); - } - - $stream->expect(/* Token::BLOCK_END_TYPE */ 3); - $body = $this->parser->subparse([$this, 'decideBlockEnd'], true); - $stream->expect(/* Token::BLOCK_END_TYPE */ 3); - - return new AutoEscapeNode($value, $body, $lineno, $this->getTag()); - } - - public function decideBlockEnd(Token $token): bool - { - return $token->test('endautoescape'); - } - - public function getTag(): string - { - return 'autoescape'; - } -} diff --git a/lib/twig/twig/src/TokenParser/BlockTokenParser.php b/lib/twig/twig/src/TokenParser/BlockTokenParser.php deleted file mode 100644 index 5878131be..000000000 --- a/lib/twig/twig/src/TokenParser/BlockTokenParser.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\TokenParser; - -use Twig\Error\SyntaxError; -use Twig\Node\BlockNode; -use Twig\Node\BlockReferenceNode; -use Twig\Node\Node; -use Twig\Node\PrintNode; -use Twig\Token; - -/** - * Marks a section of a template as being reusable. - * - * {% block head %} - * <link rel="stylesheet" href="style.css" /> - * <title>{% block title %}{% endblock %} - My Webpage</title> - * {% endblock %} - * - * @internal - */ -final class BlockTokenParser extends AbstractTokenParser -{ - public function parse(Token $token): Node - { - $lineno = $token->getLine(); - $stream = $this->parser->getStream(); - $name = $stream->expect(/* Token::NAME_TYPE */ 5)->getValue(); - if ($this->parser->hasBlock($name)) { - throw new SyntaxError(sprintf("The block '%s' has already been defined line %d.", $name, $this->parser->getBlock($name)->getTemplateLine()), $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - $this->parser->setBlock($name, $block = new BlockNode($name, new Node([]), $lineno)); - $this->parser->pushLocalScope(); - $this->parser->pushBlockStack($name); - - if ($stream->nextIf(/* Token::BLOCK_END_TYPE */ 3)) { - $body = $this->parser->subparse([$this, 'decideBlockEnd'], true); - if ($token = $stream->nextIf(/* Token::NAME_TYPE */ 5)) { - $value = $token->getValue(); - - if ($value != $name) { - throw new SyntaxError(sprintf('Expected endblock for block "%s" (but "%s" given).', $name, $value), $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - } - } else { - $body = new Node([ - new PrintNode($this->parser->getExpressionParser()->parseExpression(), $lineno), - ]); - } - $stream->expect(/* Token::BLOCK_END_TYPE */ 3); - - $block->setNode('body', $body); - $this->parser->popBlockStack(); - $this->parser->popLocalScope(); - - return new BlockReferenceNode($name, $lineno, $this->getTag()); - } - - public function decideBlockEnd(Token $token): bool - { - return $token->test('endblock'); - } - - public function getTag(): string - { - return 'block'; - } -} diff --git a/lib/twig/twig/src/TokenParser/DeprecatedTokenParser.php b/lib/twig/twig/src/TokenParser/DeprecatedTokenParser.php deleted file mode 100644 index 31416c79c..000000000 --- a/lib/twig/twig/src/TokenParser/DeprecatedTokenParser.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\TokenParser; - -use Twig\Node\DeprecatedNode; -use Twig\Node\Node; -use Twig\Token; - -/** - * Deprecates a section of a template. - * - * {% deprecated 'The "base.twig" template is deprecated, use "layout.twig" instead.' %} - * {% extends 'layout.html.twig' %} - * - * @author Yonel Ceruto <yonelceruto@gmail.com> - * - * @internal - */ -final class DeprecatedTokenParser extends AbstractTokenParser -{ - public function parse(Token $token): Node - { - $expr = $this->parser->getExpressionParser()->parseExpression(); - - $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); - - return new DeprecatedNode($expr, $token->getLine(), $this->getTag()); - } - - public function getTag(): string - { - return 'deprecated'; - } -} diff --git a/lib/twig/twig/src/TokenParser/DoTokenParser.php b/lib/twig/twig/src/TokenParser/DoTokenParser.php deleted file mode 100644 index 32c8f12ff..000000000 --- a/lib/twig/twig/src/TokenParser/DoTokenParser.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\TokenParser; - -use Twig\Node\DoNode; -use Twig\Node\Node; -use Twig\Token; - -/** - * Evaluates an expression, discarding the returned value. - * - * @internal - */ -final class DoTokenParser extends AbstractTokenParser -{ - public function parse(Token $token): Node - { - $expr = $this->parser->getExpressionParser()->parseExpression(); - - $this->parser->getStream()->expect(/* Token::BLOCK_END_TYPE */ 3); - - return new DoNode($expr, $token->getLine(), $this->getTag()); - } - - public function getTag(): string - { - return 'do'; - } -} diff --git a/lib/twig/twig/src/TokenParser/EmbedTokenParser.php b/lib/twig/twig/src/TokenParser/EmbedTokenParser.php deleted file mode 100644 index 64b4f296f..000000000 --- a/lib/twig/twig/src/TokenParser/EmbedTokenParser.php +++ /dev/null @@ -1,73 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\TokenParser; - -use Twig\Node\EmbedNode; -use Twig\Node\Expression\ConstantExpression; -use Twig\Node\Expression\NameExpression; -use Twig\Node\Node; -use Twig\Token; - -/** - * Embeds a template. - * - * @internal - */ -final class EmbedTokenParser extends IncludeTokenParser -{ - public function parse(Token $token): Node - { - $stream = $this->parser->getStream(); - - $parent = $this->parser->getExpressionParser()->parseExpression(); - - list($variables, $only, $ignoreMissing) = $this->parseArguments(); - - $parentToken = $fakeParentToken = new Token(/* Token::STRING_TYPE */ 7, '__parent__', $token->getLine()); - if ($parent instanceof ConstantExpression) { - $parentToken = new Token(/* Token::STRING_TYPE */ 7, $parent->getAttribute('value'), $token->getLine()); - } elseif ($parent instanceof NameExpression) { - $parentToken = new Token(/* Token::NAME_TYPE */ 5, $parent->getAttribute('name'), $token->getLine()); - } - - // inject a fake parent to make the parent() function work - $stream->injectTokens([ - new Token(/* Token::BLOCK_START_TYPE */ 1, '', $token->getLine()), - new Token(/* Token::NAME_TYPE */ 5, 'extends', $token->getLine()), - $parentToken, - new Token(/* Token::BLOCK_END_TYPE */ 3, '', $token->getLine()), - ]); - - $module = $this->parser->parse($stream, [$this, 'decideBlockEnd'], true); - - // override the parent with the correct one - if ($fakeParentToken === $parentToken) { - $module->setNode('parent', $parent); - } - - $this->parser->embedTemplate($module); - - $stream->expect(/* Token::BLOCK_END_TYPE */ 3); - - return new EmbedNode($module->getTemplateName(), $module->getAttribute('index'), $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag()); - } - - public function decideBlockEnd(Token $token): bool - { - return $token->test('endembed'); - } - - public function getTag(): string - { - return 'embed'; - } -} diff --git a/lib/twig/twig/src/TokenParser/ExtendsTokenParser.php b/lib/twig/twig/src/TokenParser/ExtendsTokenParser.php deleted file mode 100644 index 0ca46dd29..000000000 --- a/lib/twig/twig/src/TokenParser/ExtendsTokenParser.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\TokenParser; - -use Twig\Error\SyntaxError; -use Twig\Node\Node; -use Twig\Token; - -/** - * Extends a template by another one. - * - * {% extends "base.html" %} - * - * @internal - */ -final class ExtendsTokenParser extends AbstractTokenParser -{ - public function parse(Token $token): Node - { - $stream = $this->parser->getStream(); - - if ($this->parser->peekBlockStack()) { - throw new SyntaxError('Cannot use "extend" in a block.', $token->getLine(), $stream->getSourceContext()); - } elseif (!$this->parser->isMainScope()) { - throw new SyntaxError('Cannot use "extend" in a macro.', $token->getLine(), $stream->getSourceContext()); - } - - if (null !== $this->parser->getParent()) { - throw new SyntaxError('Multiple extends tags are forbidden.', $token->getLine(), $stream->getSourceContext()); - } - $this->parser->setParent($this->parser->getExpressionParser()->parseExpression()); - - $stream->expect(/* Token::BLOCK_END_TYPE */ 3); - - return new Node(); - } - - public function getTag(): string - { - return 'extends'; - } -} diff --git a/lib/twig/twig/src/TokenParser/FlushTokenParser.php b/lib/twig/twig/src/TokenParser/FlushTokenParser.php deleted file mode 100644 index 02c74aa13..000000000 --- a/lib/twig/twig/src/TokenParser/FlushTokenParser.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\TokenParser; - -use Twig\Node\FlushNode; -use Twig\Node\Node; -use Twig\Token; - -/** - * Flushes the output to the client. - * - * @see flush() - * - * @internal - */ -final class FlushTokenParser extends AbstractTokenParser -{ - public function parse(Token $token): Node - { - $this->parser->getStream()->expect(/* Token::BLOCK_END_TYPE */ 3); - - return new FlushNode($token->getLine(), $this->getTag()); - } - - public function getTag(): string - { - return 'flush'; - } -} diff --git a/lib/twig/twig/src/TokenParser/ForTokenParser.php b/lib/twig/twig/src/TokenParser/ForTokenParser.php deleted file mode 100644 index bac8ba2da..000000000 --- a/lib/twig/twig/src/TokenParser/ForTokenParser.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\TokenParser; - -use Twig\Node\Expression\AssignNameExpression; -use Twig\Node\ForNode; -use Twig\Node\Node; -use Twig\Token; - -/** - * Loops over each item of a sequence. - * - * <ul> - * {% for user in users %} - * <li>{{ user.username|e }}</li> - * {% endfor %} - * </ul> - * - * @internal - */ -final class ForTokenParser extends AbstractTokenParser -{ - public function parse(Token $token): Node - { - $lineno = $token->getLine(); - $stream = $this->parser->getStream(); - $targets = $this->parser->getExpressionParser()->parseAssignmentExpression(); - $stream->expect(/* Token::OPERATOR_TYPE */ 8, 'in'); - $seq = $this->parser->getExpressionParser()->parseExpression(); - - $stream->expect(/* Token::BLOCK_END_TYPE */ 3); - $body = $this->parser->subparse([$this, 'decideForFork']); - if ('else' == $stream->next()->getValue()) { - $stream->expect(/* Token::BLOCK_END_TYPE */ 3); - $else = $this->parser->subparse([$this, 'decideForEnd'], true); - } else { - $else = null; - } - $stream->expect(/* Token::BLOCK_END_TYPE */ 3); - - if (\count($targets) > 1) { - $keyTarget = $targets->getNode(0); - $keyTarget = new AssignNameExpression($keyTarget->getAttribute('name'), $keyTarget->getTemplateLine()); - $valueTarget = $targets->getNode(1); - } else { - $keyTarget = new AssignNameExpression('_key', $lineno); - $valueTarget = $targets->getNode(0); - } - $valueTarget = new AssignNameExpression($valueTarget->getAttribute('name'), $valueTarget->getTemplateLine()); - - return new ForNode($keyTarget, $valueTarget, $seq, null, $body, $else, $lineno, $this->getTag()); - } - - public function decideForFork(Token $token): bool - { - return $token->test(['else', 'endfor']); - } - - public function decideForEnd(Token $token): bool - { - return $token->test('endfor'); - } - - public function getTag(): string - { - return 'for'; - } -} diff --git a/lib/twig/twig/src/TokenParser/FromTokenParser.php b/lib/twig/twig/src/TokenParser/FromTokenParser.php deleted file mode 100644 index 35098c267..000000000 --- a/lib/twig/twig/src/TokenParser/FromTokenParser.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\TokenParser; - -use Twig\Node\Expression\AssignNameExpression; -use Twig\Node\ImportNode; -use Twig\Node\Node; -use Twig\Token; - -/** - * Imports macros. - * - * {% from 'forms.html' import forms %} - * - * @internal - */ -final class FromTokenParser extends AbstractTokenParser -{ - public function parse(Token $token): Node - { - $macro = $this->parser->getExpressionParser()->parseExpression(); - $stream = $this->parser->getStream(); - $stream->expect(/* Token::NAME_TYPE */ 5, 'import'); - - $targets = []; - do { - $name = $stream->expect(/* Token::NAME_TYPE */ 5)->getValue(); - - $alias = $name; - if ($stream->nextIf('as')) { - $alias = $stream->expect(/* Token::NAME_TYPE */ 5)->getValue(); - } - - $targets[$name] = $alias; - - if (!$stream->nextIf(/* Token::PUNCTUATION_TYPE */ 9, ',')) { - break; - } - } while (true); - - $stream->expect(/* Token::BLOCK_END_TYPE */ 3); - - $var = new AssignNameExpression($this->parser->getVarName(), $token->getLine()); - $node = new ImportNode($macro, $var, $token->getLine(), $this->getTag(), $this->parser->isMainScope()); - - foreach ($targets as $name => $alias) { - $this->parser->addImportedSymbol('function', $alias, 'macro_'.$name, $var); - } - - return $node; - } - - public function getTag(): string - { - return 'from'; - } -} diff --git a/lib/twig/twig/src/TokenParser/IfTokenParser.php b/lib/twig/twig/src/TokenParser/IfTokenParser.php deleted file mode 100644 index c0fe6df0d..000000000 --- a/lib/twig/twig/src/TokenParser/IfTokenParser.php +++ /dev/null @@ -1,89 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\TokenParser; - -use Twig\Error\SyntaxError; -use Twig\Node\IfNode; -use Twig\Node\Node; -use Twig\Token; - -/** - * Tests a condition. - * - * {% if users %} - * <ul> - * {% for user in users %} - * <li>{{ user.username|e }}</li> - * {% endfor %} - * </ul> - * {% endif %} - * - * @internal - */ -final class IfTokenParser extends AbstractTokenParser -{ - public function parse(Token $token): Node - { - $lineno = $token->getLine(); - $expr = $this->parser->getExpressionParser()->parseExpression(); - $stream = $this->parser->getStream(); - $stream->expect(/* Token::BLOCK_END_TYPE */ 3); - $body = $this->parser->subparse([$this, 'decideIfFork']); - $tests = [$expr, $body]; - $else = null; - - $end = false; - while (!$end) { - switch ($stream->next()->getValue()) { - case 'else': - $stream->expect(/* Token::BLOCK_END_TYPE */ 3); - $else = $this->parser->subparse([$this, 'decideIfEnd']); - break; - - case 'elseif': - $expr = $this->parser->getExpressionParser()->parseExpression(); - $stream->expect(/* Token::BLOCK_END_TYPE */ 3); - $body = $this->parser->subparse([$this, 'decideIfFork']); - $tests[] = $expr; - $tests[] = $body; - break; - - case 'endif': - $end = true; - break; - - default: - throw new SyntaxError(sprintf('Unexpected end of template. Twig was looking for the following tags "else", "elseif", or "endif" to close the "if" block started at line %d).', $lineno), $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - } - - $stream->expect(/* Token::BLOCK_END_TYPE */ 3); - - return new IfNode(new Node($tests), $else, $lineno, $this->getTag()); - } - - public function decideIfFork(Token $token): bool - { - return $token->test(['elseif', 'else', 'endif']); - } - - public function decideIfEnd(Token $token): bool - { - return $token->test(['endif']); - } - - public function getTag(): string - { - return 'if'; - } -} diff --git a/lib/twig/twig/src/TokenParser/ImportTokenParser.php b/lib/twig/twig/src/TokenParser/ImportTokenParser.php deleted file mode 100644 index 44cb4dad7..000000000 --- a/lib/twig/twig/src/TokenParser/ImportTokenParser.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\TokenParser; - -use Twig\Node\Expression\AssignNameExpression; -use Twig\Node\ImportNode; -use Twig\Node\Node; -use Twig\Token; - -/** - * Imports macros. - * - * {% import 'forms.html' as forms %} - * - * @internal - */ -final class ImportTokenParser extends AbstractTokenParser -{ - public function parse(Token $token): Node - { - $macro = $this->parser->getExpressionParser()->parseExpression(); - $this->parser->getStream()->expect(/* Token::NAME_TYPE */ 5, 'as'); - $var = new AssignNameExpression($this->parser->getStream()->expect(/* Token::NAME_TYPE */ 5)->getValue(), $token->getLine()); - $this->parser->getStream()->expect(/* Token::BLOCK_END_TYPE */ 3); - - $this->parser->addImportedSymbol('template', $var->getAttribute('name')); - - return new ImportNode($macro, $var, $token->getLine(), $this->getTag(), $this->parser->isMainScope()); - } - - public function getTag(): string - { - return 'import'; - } -} diff --git a/lib/twig/twig/src/TokenParser/IncludeTokenParser.php b/lib/twig/twig/src/TokenParser/IncludeTokenParser.php deleted file mode 100644 index 28beb8ae4..000000000 --- a/lib/twig/twig/src/TokenParser/IncludeTokenParser.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\TokenParser; - -use Twig\Node\IncludeNode; -use Twig\Node\Node; -use Twig\Token; - -/** - * Includes a template. - * - * {% include 'header.html' %} - * Body - * {% include 'footer.html' %} - * - * @internal - */ -class IncludeTokenParser extends AbstractTokenParser -{ - public function parse(Token $token): Node - { - $expr = $this->parser->getExpressionParser()->parseExpression(); - - list($variables, $only, $ignoreMissing) = $this->parseArguments(); - - return new IncludeNode($expr, $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag()); - } - - protected function parseArguments() - { - $stream = $this->parser->getStream(); - - $ignoreMissing = false; - if ($stream->nextIf(/* Token::NAME_TYPE */ 5, 'ignore')) { - $stream->expect(/* Token::NAME_TYPE */ 5, 'missing'); - - $ignoreMissing = true; - } - - $variables = null; - if ($stream->nextIf(/* Token::NAME_TYPE */ 5, 'with')) { - $variables = $this->parser->getExpressionParser()->parseExpression(); - } - - $only = false; - if ($stream->nextIf(/* Token::NAME_TYPE */ 5, 'only')) { - $only = true; - } - - $stream->expect(/* Token::BLOCK_END_TYPE */ 3); - - return [$variables, $only, $ignoreMissing]; - } - - public function getTag(): string - { - return 'include'; - } -} diff --git a/lib/twig/twig/src/TokenParser/MacroTokenParser.php b/lib/twig/twig/src/TokenParser/MacroTokenParser.php deleted file mode 100644 index f584927e9..000000000 --- a/lib/twig/twig/src/TokenParser/MacroTokenParser.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\TokenParser; - -use Twig\Error\SyntaxError; -use Twig\Node\BodyNode; -use Twig\Node\MacroNode; -use Twig\Node\Node; -use Twig\Token; - -/** - * Defines a macro. - * - * {% macro input(name, value, type, size) %} - * <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" /> - * {% endmacro %} - * - * @internal - */ -final class MacroTokenParser extends AbstractTokenParser -{ - public function parse(Token $token): Node - { - $lineno = $token->getLine(); - $stream = $this->parser->getStream(); - $name = $stream->expect(/* Token::NAME_TYPE */ 5)->getValue(); - - $arguments = $this->parser->getExpressionParser()->parseArguments(true, true); - - $stream->expect(/* Token::BLOCK_END_TYPE */ 3); - $this->parser->pushLocalScope(); - $body = $this->parser->subparse([$this, 'decideBlockEnd'], true); - if ($token = $stream->nextIf(/* Token::NAME_TYPE */ 5)) { - $value = $token->getValue(); - - if ($value != $name) { - throw new SyntaxError(sprintf('Expected endmacro for macro "%s" (but "%s" given).', $name, $value), $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - } - $this->parser->popLocalScope(); - $stream->expect(/* Token::BLOCK_END_TYPE */ 3); - - $this->parser->setMacro($name, new MacroNode($name, new BodyNode([$body]), $arguments, $lineno, $this->getTag())); - - return new Node(); - } - - public function decideBlockEnd(Token $token): bool - { - return $token->test('endmacro'); - } - - public function getTag(): string - { - return 'macro'; - } -} diff --git a/lib/twig/twig/src/TokenParser/SandboxTokenParser.php b/lib/twig/twig/src/TokenParser/SandboxTokenParser.php deleted file mode 100644 index c919556ec..000000000 --- a/lib/twig/twig/src/TokenParser/SandboxTokenParser.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\TokenParser; - -use Twig\Error\SyntaxError; -use Twig\Node\IncludeNode; -use Twig\Node\Node; -use Twig\Node\SandboxNode; -use Twig\Node\TextNode; -use Twig\Token; - -/** - * Marks a section of a template as untrusted code that must be evaluated in the sandbox mode. - * - * {% sandbox %} - * {% include 'user.html' %} - * {% endsandbox %} - * - * @see https://twig.symfony.com/doc/api.html#sandbox-extension for details - * - * @internal - */ -final class SandboxTokenParser extends AbstractTokenParser -{ - public function parse(Token $token): Node - { - $stream = $this->parser->getStream(); - $stream->expect(/* Token::BLOCK_END_TYPE */ 3); - $body = $this->parser->subparse([$this, 'decideBlockEnd'], true); - $stream->expect(/* Token::BLOCK_END_TYPE */ 3); - - // in a sandbox tag, only include tags are allowed - if (!$body instanceof IncludeNode) { - foreach ($body as $node) { - if ($node instanceof TextNode && ctype_space($node->getAttribute('data'))) { - continue; - } - - if (!$node instanceof IncludeNode) { - throw new SyntaxError('Only "include" tags are allowed within a "sandbox" section.', $node->getTemplateLine(), $stream->getSourceContext()); - } - } - } - - return new SandboxNode($body, $token->getLine(), $this->getTag()); - } - - public function decideBlockEnd(Token $token): bool - { - return $token->test('endsandbox'); - } - - public function getTag(): string - { - return 'sandbox'; - } -} diff --git a/lib/twig/twig/src/TokenParser/SetTokenParser.php b/lib/twig/twig/src/TokenParser/SetTokenParser.php deleted file mode 100644 index 2fbdfe090..000000000 --- a/lib/twig/twig/src/TokenParser/SetTokenParser.php +++ /dev/null @@ -1,73 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\TokenParser; - -use Twig\Error\SyntaxError; -use Twig\Node\Node; -use Twig\Node\SetNode; -use Twig\Token; - -/** - * Defines a variable. - * - * {% set foo = 'foo' %} - * {% set foo = [1, 2] %} - * {% set foo = {'foo': 'bar'} %} - * {% set foo = 'foo' ~ 'bar' %} - * {% set foo, bar = 'foo', 'bar' %} - * {% set foo %}Some content{% endset %} - * - * @internal - */ -final class SetTokenParser extends AbstractTokenParser -{ - public function parse(Token $token): Node - { - $lineno = $token->getLine(); - $stream = $this->parser->getStream(); - $names = $this->parser->getExpressionParser()->parseAssignmentExpression(); - - $capture = false; - if ($stream->nextIf(/* Token::OPERATOR_TYPE */ 8, '=')) { - $values = $this->parser->getExpressionParser()->parseMultitargetExpression(); - - $stream->expect(/* Token::BLOCK_END_TYPE */ 3); - - if (\count($names) !== \count($values)) { - throw new SyntaxError('When using set, you must have the same number of variables and assignments.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - } else { - $capture = true; - - if (\count($names) > 1) { - throw new SyntaxError('When using set with a block, you cannot have a multi-target.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - - $stream->expect(/* Token::BLOCK_END_TYPE */ 3); - - $values = $this->parser->subparse([$this, 'decideBlockEnd'], true); - $stream->expect(/* Token::BLOCK_END_TYPE */ 3); - } - - return new SetNode($capture, $names, $values, $lineno, $this->getTag()); - } - - public function decideBlockEnd(Token $token): bool - { - return $token->test('endset'); - } - - public function getTag(): string - { - return 'set'; - } -} diff --git a/lib/twig/twig/src/TokenParser/TokenParserInterface.php b/lib/twig/twig/src/TokenParser/TokenParserInterface.php deleted file mode 100644 index bb8db3e5c..000000000 --- a/lib/twig/twig/src/TokenParser/TokenParserInterface.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\TokenParser; - -use Twig\Error\SyntaxError; -use Twig\Node\Node; -use Twig\Parser; -use Twig\Token; - -/** - * Interface implemented by token parsers. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface TokenParserInterface -{ - /** - * Sets the parser associated with this token parser. - */ - public function setParser(Parser $parser): void; - - /** - * Parses a token and returns a node. - * - * @return Node - * - * @throws SyntaxError - */ - public function parse(Token $token); - - /** - * Gets the tag name associated with this token parser. - * - * @return string - */ - public function getTag(); -} diff --git a/lib/twig/twig/src/TokenParser/UseTokenParser.php b/lib/twig/twig/src/TokenParser/UseTokenParser.php deleted file mode 100644 index d0a2de41a..000000000 --- a/lib/twig/twig/src/TokenParser/UseTokenParser.php +++ /dev/null @@ -1,73 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\TokenParser; - -use Twig\Error\SyntaxError; -use Twig\Node\Expression\ConstantExpression; -use Twig\Node\Node; -use Twig\Token; - -/** - * Imports blocks defined in another template into the current template. - * - * {% extends "base.html" %} - * - * {% use "blocks.html" %} - * - * {% block title %}{% endblock %} - * {% block content %}{% endblock %} - * - * @see https://twig.symfony.com/doc/templates.html#horizontal-reuse for details. - * - * @internal - */ -final class UseTokenParser extends AbstractTokenParser -{ - public function parse(Token $token): Node - { - $template = $this->parser->getExpressionParser()->parseExpression(); - $stream = $this->parser->getStream(); - - if (!$template instanceof ConstantExpression) { - throw new SyntaxError('The template references in a "use" statement must be a string.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - - $targets = []; - if ($stream->nextIf('with')) { - do { - $name = $stream->expect(/* Token::NAME_TYPE */ 5)->getValue(); - - $alias = $name; - if ($stream->nextIf('as')) { - $alias = $stream->expect(/* Token::NAME_TYPE */ 5)->getValue(); - } - - $targets[$name] = new ConstantExpression($alias, -1); - - if (!$stream->nextIf(/* Token::PUNCTUATION_TYPE */ 9, ',')) { - break; - } - } while (true); - } - - $stream->expect(/* Token::BLOCK_END_TYPE */ 3); - - $this->parser->addTrait(new Node(['template' => $template, 'targets' => new Node($targets)])); - - return new Node(); - } - - public function getTag(): string - { - return 'use'; - } -} diff --git a/lib/twig/twig/src/TokenParser/WithTokenParser.php b/lib/twig/twig/src/TokenParser/WithTokenParser.php deleted file mode 100644 index 7d8cbe261..000000000 --- a/lib/twig/twig/src/TokenParser/WithTokenParser.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\TokenParser; - -use Twig\Node\Node; -use Twig\Node\WithNode; -use Twig\Token; - -/** - * Creates a nested scope. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @internal - */ -final class WithTokenParser extends AbstractTokenParser -{ - public function parse(Token $token): Node - { - $stream = $this->parser->getStream(); - - $variables = null; - $only = false; - if (!$stream->test(/* Token::BLOCK_END_TYPE */ 3)) { - $variables = $this->parser->getExpressionParser()->parseExpression(); - $only = (bool) $stream->nextIf(/* Token::NAME_TYPE */ 5, 'only'); - } - - $stream->expect(/* Token::BLOCK_END_TYPE */ 3); - - $body = $this->parser->subparse([$this, 'decideWithEnd'], true); - - $stream->expect(/* Token::BLOCK_END_TYPE */ 3); - - return new WithNode($body, $variables, $only, $token->getLine(), $this->getTag()); - } - - public function decideWithEnd(Token $token): bool - { - return $token->test('endwith'); - } - - public function getTag(): string - { - return 'with'; - } -} diff --git a/lib/twig/twig/src/TokenStream.php b/lib/twig/twig/src/TokenStream.php deleted file mode 100644 index 1eac11a02..000000000 --- a/lib/twig/twig/src/TokenStream.php +++ /dev/null @@ -1,132 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig; - -use Twig\Error\SyntaxError; - -/** - * Represents a token stream. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class TokenStream -{ - private $tokens; - private $current = 0; - private $source; - - public function __construct(array $tokens, Source $source = null) - { - $this->tokens = $tokens; - $this->source = $source ?: new Source('', ''); - } - - public function __toString() - { - return implode("\n", $this->tokens); - } - - public function injectTokens(array $tokens) - { - $this->tokens = array_merge(\array_slice($this->tokens, 0, $this->current), $tokens, \array_slice($this->tokens, $this->current)); - } - - /** - * Sets the pointer to the next token and returns the old one. - */ - public function next(): Token - { - if (!isset($this->tokens[++$this->current])) { - throw new SyntaxError('Unexpected end of template.', $this->tokens[$this->current - 1]->getLine(), $this->source); - } - - return $this->tokens[$this->current - 1]; - } - - /** - * Tests a token, sets the pointer to the next one and returns it or throws a syntax error. - * - * @return Token|null The next token if the condition is true, null otherwise - */ - public function nextIf($primary, $secondary = null) - { - if ($this->tokens[$this->current]->test($primary, $secondary)) { - return $this->next(); - } - } - - /** - * Tests a token and returns it or throws a syntax error. - */ - public function expect($type, $value = null, string $message = null): Token - { - $token = $this->tokens[$this->current]; - if (!$token->test($type, $value)) { - $line = $token->getLine(); - throw new SyntaxError(sprintf('%sUnexpected token "%s"%s ("%s" expected%s).', - $message ? $message.'. ' : '', - Token::typeToEnglish($token->getType()), - $token->getValue() ? sprintf(' of value "%s"', $token->getValue()) : '', - Token::typeToEnglish($type), $value ? sprintf(' with value "%s"', $value) : ''), - $line, - $this->source - ); - } - $this->next(); - - return $token; - } - - /** - * Looks at the next token. - */ - public function look(int $number = 1): Token - { - if (!isset($this->tokens[$this->current + $number])) { - throw new SyntaxError('Unexpected end of template.', $this->tokens[$this->current + $number - 1]->getLine(), $this->source); - } - - return $this->tokens[$this->current + $number]; - } - - /** - * Tests the current token. - */ - public function test($primary, $secondary = null): bool - { - return $this->tokens[$this->current]->test($primary, $secondary); - } - - /** - * Checks if end of stream was reached. - */ - public function isEOF(): bool - { - return /* Token::EOF_TYPE */ -1 === $this->tokens[$this->current]->getType(); - } - - public function getCurrent(): Token - { - return $this->tokens[$this->current]; - } - - /** - * Gets the source associated with this stream. - * - * @internal - */ - public function getSourceContext(): Source - { - return $this->source; - } -} diff --git a/lib/twig/twig/src/TwigFilter.php b/lib/twig/twig/src/TwigFilter.php deleted file mode 100644 index 94e5f9b01..000000000 --- a/lib/twig/twig/src/TwigFilter.php +++ /dev/null @@ -1,134 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig; - -use Twig\Node\Expression\FilterExpression; -use Twig\Node\Node; - -/** - * Represents a template filter. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @see https://twig.symfony.com/doc/templates.html#filters - */ -final class TwigFilter -{ - private $name; - private $callable; - private $options; - private $arguments = []; - - /** - * @param callable|null $callable A callable implementing the filter. If null, you need to overwrite the "node_class" option to customize compilation. - */ - public function __construct(string $name, $callable = null, array $options = []) - { - $this->name = $name; - $this->callable = $callable; - $this->options = array_merge([ - 'needs_environment' => false, - 'needs_context' => false, - 'is_variadic' => false, - 'is_safe' => null, - 'is_safe_callback' => null, - 'pre_escape' => null, - 'preserves_safety' => null, - 'node_class' => FilterExpression::class, - 'deprecated' => false, - 'alternative' => null, - ], $options); - } - - public function getName(): string - { - return $this->name; - } - - /** - * Returns the callable to execute for this filter. - * - * @return callable|null - */ - public function getCallable() - { - return $this->callable; - } - - public function getNodeClass(): string - { - return $this->options['node_class']; - } - - public function setArguments(array $arguments): void - { - $this->arguments = $arguments; - } - - public function getArguments(): array - { - return $this->arguments; - } - - public function needsEnvironment(): bool - { - return $this->options['needs_environment']; - } - - public function needsContext(): bool - { - return $this->options['needs_context']; - } - - public function getSafe(Node $filterArgs): ?array - { - if (null !== $this->options['is_safe']) { - return $this->options['is_safe']; - } - - if (null !== $this->options['is_safe_callback']) { - return $this->options['is_safe_callback']($filterArgs); - } - - return null; - } - - public function getPreservesSafety(): ?array - { - return $this->options['preserves_safety']; - } - - public function getPreEscape(): ?string - { - return $this->options['pre_escape']; - } - - public function isVariadic(): bool - { - return $this->options['is_variadic']; - } - - public function isDeprecated(): bool - { - return (bool) $this->options['deprecated']; - } - - public function getDeprecatedVersion(): string - { - return \is_bool($this->options['deprecated']) ? '' : $this->options['deprecated']; - } - - public function getAlternative(): ?string - { - return $this->options['alternative']; - } -} diff --git a/lib/twig/twig/src/TwigFunction.php b/lib/twig/twig/src/TwigFunction.php deleted file mode 100644 index 494d45b08..000000000 --- a/lib/twig/twig/src/TwigFunction.php +++ /dev/null @@ -1,122 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig; - -use Twig\Node\Expression\FunctionExpression; -use Twig\Node\Node; - -/** - * Represents a template function. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @see https://twig.symfony.com/doc/templates.html#functions - */ -final class TwigFunction -{ - private $name; - private $callable; - private $options; - private $arguments = []; - - /** - * @param callable|null $callable A callable implementing the function. If null, you need to overwrite the "node_class" option to customize compilation. - */ - public function __construct(string $name, $callable = null, array $options = []) - { - $this->name = $name; - $this->callable = $callable; - $this->options = array_merge([ - 'needs_environment' => false, - 'needs_context' => false, - 'is_variadic' => false, - 'is_safe' => null, - 'is_safe_callback' => null, - 'node_class' => FunctionExpression::class, - 'deprecated' => false, - 'alternative' => null, - ], $options); - } - - public function getName(): string - { - return $this->name; - } - - /** - * Returns the callable to execute for this function. - * - * @return callable|null - */ - public function getCallable() - { - return $this->callable; - } - - public function getNodeClass(): string - { - return $this->options['node_class']; - } - - public function setArguments(array $arguments): void - { - $this->arguments = $arguments; - } - - public function getArguments(): array - { - return $this->arguments; - } - - public function needsEnvironment(): bool - { - return $this->options['needs_environment']; - } - - public function needsContext(): bool - { - return $this->options['needs_context']; - } - - public function getSafe(Node $functionArgs): ?array - { - if (null !== $this->options['is_safe']) { - return $this->options['is_safe']; - } - - if (null !== $this->options['is_safe_callback']) { - return $this->options['is_safe_callback']($functionArgs); - } - - return []; - } - - public function isVariadic(): bool - { - return (bool) $this->options['is_variadic']; - } - - public function isDeprecated(): bool - { - return (bool) $this->options['deprecated']; - } - - public function getDeprecatedVersion(): string - { - return \is_bool($this->options['deprecated']) ? '' : $this->options['deprecated']; - } - - public function getAlternative(): ?string - { - return $this->options['alternative']; - } -} diff --git a/lib/twig/twig/src/TwigTest.php b/lib/twig/twig/src/TwigTest.php deleted file mode 100644 index 4c18632f5..000000000 --- a/lib/twig/twig/src/TwigTest.php +++ /dev/null @@ -1,100 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig; - -use Twig\Node\Expression\TestExpression; - -/** - * Represents a template test. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @see https://twig.symfony.com/doc/templates.html#test-operator - */ -final class TwigTest -{ - private $name; - private $callable; - private $options; - private $arguments = []; - - /** - * @param callable|null $callable A callable implementing the test. If null, you need to overwrite the "node_class" option to customize compilation. - */ - public function __construct(string $name, $callable = null, array $options = []) - { - $this->name = $name; - $this->callable = $callable; - $this->options = array_merge([ - 'is_variadic' => false, - 'node_class' => TestExpression::class, - 'deprecated' => false, - 'alternative' => null, - 'one_mandatory_argument' => false, - ], $options); - } - - public function getName(): string - { - return $this->name; - } - - /** - * Returns the callable to execute for this test. - * - * @return callable|null - */ - public function getCallable() - { - return $this->callable; - } - - public function getNodeClass(): string - { - return $this->options['node_class']; - } - - public function setArguments(array $arguments): void - { - $this->arguments = $arguments; - } - - public function getArguments(): array - { - return $this->arguments; - } - - public function isVariadic(): bool - { - return (bool) $this->options['is_variadic']; - } - - public function isDeprecated(): bool - { - return (bool) $this->options['deprecated']; - } - - public function getDeprecatedVersion(): string - { - return \is_bool($this->options['deprecated']) ? '' : $this->options['deprecated']; - } - - public function getAlternative(): ?string - { - return $this->options['alternative']; - } - - public function hasOneMandatoryArgument(): bool - { - return (bool) $this->options['one_mandatory_argument']; - } -} diff --git a/lib/twig/twig/src/Util/DeprecationCollector.php b/lib/twig/twig/src/Util/DeprecationCollector.php deleted file mode 100644 index 378b666bd..000000000 --- a/lib/twig/twig/src/Util/DeprecationCollector.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Util; - -use Twig\Environment; -use Twig\Error\SyntaxError; -use Twig\Source; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -final class DeprecationCollector -{ - private $twig; - - public function __construct(Environment $twig) - { - $this->twig = $twig; - } - - /** - * Returns deprecations for templates contained in a directory. - * - * @param string $dir A directory where templates are stored - * @param string $ext Limit the loaded templates by extension - * - * @return array An array of deprecations - */ - public function collectDir(string $dir, string $ext = '.twig'): array - { - $iterator = new \RegexIterator( - new \RecursiveIteratorIterator( - new \RecursiveDirectoryIterator($dir), \RecursiveIteratorIterator::LEAVES_ONLY - ), '{'.preg_quote($ext).'$}' - ); - - return $this->collect(new TemplateDirIterator($iterator)); - } - - /** - * Returns deprecations for passed templates. - * - * @param \Traversable $iterator An iterator of templates (where keys are template names and values the contents of the template) - * - * @return array An array of deprecations - */ - public function collect(\Traversable $iterator): array - { - $deprecations = []; - set_error_handler(function ($type, $msg) use (&$deprecations) { - if (\E_USER_DEPRECATED === $type) { - $deprecations[] = $msg; - } - }); - - foreach ($iterator as $name => $contents) { - try { - $this->twig->parse($this->twig->tokenize(new Source($contents, $name))); - } catch (SyntaxError $e) { - // ignore templates containing syntax errors - } - } - - restore_error_handler(); - - return $deprecations; - } -} diff --git a/lib/twig/twig/src/Util/TemplateDirIterator.php b/lib/twig/twig/src/Util/TemplateDirIterator.php deleted file mode 100644 index 3bef14bee..000000000 --- a/lib/twig/twig/src/Util/TemplateDirIterator.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Twig\Util; - -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -class TemplateDirIterator extends \IteratorIterator -{ - /** - * @return mixed - */ - #[\ReturnTypeWillChange] - public function current() - { - return file_get_contents(parent::current()); - } - - /** - * @return mixed - */ - #[\ReturnTypeWillChange] - public function key() - { - return (string) parent::key(); - } -} diff --git a/lib/web.config b/lib/web.config deleted file mode 100644 index 88956be1b..000000000 --- a/lib/web.config +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!-- Allow only static resources files --> -<!-- - HTML not allowed as there could be some test pages calling server scripts or executing JS scripts --> -<!-- - PHP not allowed as they should not be publicly accessible --> -<configuration> - <system.webServer> - <security> - <requestFiltering> - <fileExtensions applyToWebDAV="false" allowUnlisted="false" > - <add fileExtension=".css" allowed="true" /> - <add fileExtension=".scss" allowed="true" /> - <add fileExtension=".js" allowed="true" /> - <add fileExtension=".map" allowed="true" /> - <add fileExtension=".png" allowed="true" /> - <add fileExtension=".bmp" allowed="true" /> - <add fileExtension=".gif" allowed="true" /> - <add fileExtension=".jpeg" allowed="true" /> - <add fileExtension=".jpg" allowed="true" /> - <add fileExtension=".svg" allowed="true" /> - <add fileExtension=".tiff" allowed="true" /> - - <add fileExtension=".woff" allowed="true" /> - <add fileExtension=".woff2" allowed="true" /> - <add fileExtension=".ttf" allowed="true" /> - <add fileExtension=".eot" allowed="true" /> - </fileExtensions> - </requestFiltering> - </security> - </system.webServer> -</configuration> diff --git a/lib/webmozart/assert/CHANGELOG.md b/lib/webmozart/assert/CHANGELOG.md deleted file mode 100644 index 56c8011de..000000000 --- a/lib/webmozart/assert/CHANGELOG.md +++ /dev/null @@ -1,207 +0,0 @@ -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/lib/webmozart/assert/LICENSE b/lib/webmozart/assert/LICENSE deleted file mode 100644 index 9e2e3075e..000000000 --- a/lib/webmozart/assert/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -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/lib/webmozart/assert/README.md b/lib/webmozart/assert/README.md deleted file mode 100644 index 3b2397a1a..000000000 --- a/lib/webmozart/assert/README.md +++ /dev/null @@ -1,287 +0,0 @@ -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/lib/webmozart/assert/composer.json b/lib/webmozart/assert/composer.json deleted file mode 100644 index b340452c7..000000000 --- a/lib/webmozart/assert/composer.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "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/lib/webmozart/assert/src/Assert.php b/lib/webmozart/assert/src/Assert.php deleted file mode 100644 index db1f3a51a..000000000 --- a/lib/webmozart/assert/src/Assert.php +++ /dev/null @@ -1,2080 +0,0 @@ -<?php - -/* - * This file is part of the webmozart/assert package. - * - * (c) Bernhard Schussek <bschussek@gmail.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Webmozart\Assert; - -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 <bschussek@gmail.com> - */ -class Assert -{ - use Mixin; - - /** - * @psalm-pure - * @psalm-assert string $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - */ - public static function string($value, $message = '') - { - if (!\is_string($value)) { - static::reportInvalidArgument(\sprintf( - $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<ExpectedType> $class - * @psalm-assert ExpectedType $value - * - * @param mixed $value - * @param string|object $class - * @param string $message - * - * @throws InvalidArgumentException - */ - public static function isInstanceOf($value, $class, $message = '') - { - if (!($value instanceof $class)) { - static::reportInvalidArgument(\sprintf( - $message ?: 'Expected an instance of %2$s. Got: %s', - static::typeToString($value), - $class - )); - } - } - - /** - * @psalm-pure - * @psalm-template ExpectedType of object - * @psalm-param class-string<ExpectedType> $class - * @psalm-assert !ExpectedType $value - * - * @param mixed $value - * @param string|object $class - * @param string $message - * - * @throws InvalidArgumentException - */ - public static function notInstanceOf($value, $class, $message = '') - { - if ($value instanceof $class) { - static::reportInvalidArgument(\sprintf( - $message ?: 'Expected an instance other than %2$s. Got: %s', - static::typeToString($value), - $class - )); - } - } - - /** - * @psalm-pure - * @psalm-param array<class-string> $classes - * - * @param mixed $value - * @param array<object|string> $classes - * @param string $message - * - * @throws InvalidArgumentException - */ - public static function isInstanceOfAny($value, array $classes, $message = '') - { - foreach ($classes as $class) { - 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<ExpectedType> $class - * @psalm-assert ExpectedType|class-string<ExpectedType> $value - * - * @param object|string $value - * @param string $class - * @param string $message - * - * @throws InvalidArgumentException - */ - public static function isAOf($value, $class, $message = '') - { - static::string($class, 'Expected class as a string. Got: %s'); - - if (!\is_a($value, $class, \is_string($value))) { - static::reportInvalidArgument(sprintf( - $message ?: 'Expected an instance of this class or to this class among its parents "%2$s". Got: %s', - static::valueToString($value), - $class - )); - } - } - - /** - * @psalm-pure - * @psalm-template UnexpectedType of object - * @psalm-param class-string<UnexpectedType> $class - * @psalm-assert !UnexpectedType $value - * @psalm-assert !class-string<UnexpectedType> $value - * - * @param object|string $value - * @param string $class - * @param string $message - * - * @throws InvalidArgumentException - */ - public static function isNotA($value, $class, $message = '') - { - static::string($class, 'Expected class as a string. Got: %s'); - - if (\is_a($value, $class, \is_string($value))) { - static::reportInvalidArgument(sprintf( - $message ?: 'Expected an instance of this class or to this class among its parents other than "%2$s". Got: %s', - static::valueToString($value), - $class - )); - } - } - - /** - * @psalm-pure - * @psalm-param array<class-string> $classes - * - * @param object|string $value - * @param string[] $classes - * @param string $message - * - * @throws InvalidArgumentException - */ - public static function isAnyOf($value, array $classes, $message = '') - { - foreach ($classes as $class) { - static::string($class, 'Expected class as a string. Got: %s'); - - if (\is_a($value, $class, \is_string($value))) { - return; - } - } - - static::reportInvalidArgument(sprintf( - $message ?: 'Expected an instance of any of this classes or any of those classes among their parents "%2$s". Got: %s', - static::valueToString($value), - \implode(', ', $classes) - )); - } - - /** - * @psalm-pure - * @psalm-assert empty $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - */ - public static function isEmpty($value, $message = '') - { - if (!empty($value)) { - static::reportInvalidArgument(\sprintf( - $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<ExpectedType> $class - * @psalm-assert class-string<ExpectedType>|ExpectedType $value - * - * @param mixed $value - * @param string|object $class - * @param string $message - * - * @throws InvalidArgumentException - */ - public static function subclassOf($value, $class, $message = '') - { - if (!\is_subclass_of($value, $class)) { - static::reportInvalidArgument(\sprintf( - $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<ExpectedType> $interface - * @psalm-assert class-string<ExpectedType> $value - * - * @param mixed $value - * @param mixed $interface - * @param string $message - * - * @throws InvalidArgumentException - */ - public static function implementsInterface($value, $interface, $message = '') - { - if (!\in_array($interface, \class_implements($value))) { - static::reportInvalidArgument(\sprintf( - $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<T> $array - * @psalm-assert array<string, T> $array - * - * @param mixed $array - * @param string $message - * - * @throws InvalidArgumentException - */ - public static function isMap($array, $message = '') - { - if ( - !\is_array($array) || - \array_keys($array) !== \array_filter(\array_keys($array), '\is_string') - ) { - static::reportInvalidArgument( - $message ?: 'Expected map - associative array with string keys.' - ); - } - } - - /** - * @psalm-pure - * @psalm-template T - * @psalm-param mixed|array<T> $array - * @psalm-assert array<string, T> $array - * @psalm-assert !empty $array - * - * @param mixed $array - * @param string $message - * - * @throws InvalidArgumentException - */ - public static function isNonEmptyMap($array, $message = '') - { - static::isMap($array, $message); - static::notEmpty($array, $message); - } - - /** - * @psalm-pure - * - * @param string $value - * @param string $message - * - * @throws InvalidArgumentException - */ - public static function uuid($value, $message = '') - { - $value = \str_replace(array('urn:', 'uuid:', '{', '}'), '', $value); - - // 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<Throwable> $class - * - * @param Closure $expression - * @param string $class - * @param string $message - * - * @throws InvalidArgumentException - */ - public static function throws(Closure $expression, $class = 'Exception', $message = '') - { - static::string($class); - - $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/lib/webmozart/assert/src/InvalidArgumentException.php b/lib/webmozart/assert/src/InvalidArgumentException.php deleted file mode 100644 index 9d95a58c5..000000000 --- a/lib/webmozart/assert/src/InvalidArgumentException.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -/* - * This file is part of the webmozart/assert package. - * - * (c) Bernhard Schussek <bschussek@gmail.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Webmozart\Assert; - -class InvalidArgumentException extends \InvalidArgumentException -{ -} diff --git a/lib/webmozart/assert/src/Mixin.php b/lib/webmozart/assert/src/Mixin.php deleted file mode 100644 index 0f0a75e33..000000000 --- a/lib/webmozart/assert/src/Mixin.php +++ /dev/null @@ -1,5089 +0,0 @@ -<?php - -namespace Webmozart\Assert; - -use ArrayAccess; -use Closure; -use Countable; -use Throwable; - -/** - * This trait provides nurllOr*, all* and allNullOr* variants of assertion base methods. - * Do not use this trait directly: it will change, and is not designed for reuse. - */ -trait Mixin -{ - /** - * @psalm-pure - * @psalm-assert string|null $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrString($value, $message = '') - { - null === $value || static::string($value, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<string> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allString($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::string($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<string|null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrString($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::string($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert non-empty-string|null $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrStringNotEmpty($value, $message = '') - { - null === $value || static::stringNotEmpty($value, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<non-empty-string> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allStringNotEmpty($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::stringNotEmpty($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<non-empty-string|null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrStringNotEmpty($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::stringNotEmpty($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert int|null $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrInteger($value, $message = '') - { - null === $value || static::integer($value, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<int> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allInteger($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::integer($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<int|null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrInteger($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::integer($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert numeric|null $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrIntegerish($value, $message = '') - { - null === $value || static::integerish($value, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<numeric> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allIntegerish($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::integerish($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<numeric|null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrIntegerish($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::integerish($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert positive-int|null $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrPositiveInteger($value, $message = '') - { - null === $value || static::positiveInteger($value, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<positive-int> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allPositiveInteger($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::positiveInteger($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<positive-int|null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrPositiveInteger($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::positiveInteger($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert float|null $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrFloat($value, $message = '') - { - null === $value || static::float($value, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<float> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allFloat($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::float($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<float|null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrFloat($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::float($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert numeric|null $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrNumeric($value, $message = '') - { - null === $value || static::numeric($value, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<numeric> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNumeric($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::numeric($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<numeric|null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrNumeric($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::numeric($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert positive-int|0|null $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrNatural($value, $message = '') - { - null === $value || static::natural($value, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<positive-int|0> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNatural($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::natural($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<positive-int|0|null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrNatural($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::natural($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert bool|null $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrBoolean($value, $message = '') - { - null === $value || static::boolean($value, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<bool> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allBoolean($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::boolean($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<bool|null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrBoolean($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::boolean($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert scalar|null $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrScalar($value, $message = '') - { - null === $value || static::scalar($value, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<scalar> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allScalar($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::scalar($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<scalar|null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrScalar($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::scalar($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert object|null $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrObject($value, $message = '') - { - null === $value || static::object($value, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<object> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allObject($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::object($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<object|null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrObject($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::object($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert resource|null $value - * - * @param mixed $value - * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrResource($value, $type = null, $message = '') - { - null === $value || static::resource($value, $type, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<resource> $value - * - * @param mixed $value - * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allResource($value, $type = null, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::resource($entry, $type, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<resource|null> $value - * - * @param mixed $value - * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrResource($value, $type = null, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::resource($entry, $type, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert callable|null $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrIsCallable($value, $message = '') - { - null === $value || static::isCallable($value, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<callable> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allIsCallable($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::isCallable($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<callable|null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrIsCallable($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::isCallable($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert array|null $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrIsArray($value, $message = '') - { - null === $value || static::isArray($value, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<array> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allIsArray($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::isArray($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<array|null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrIsArray($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::isArray($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable|null $value - * - * @deprecated use "isIterable" or "isInstanceOf" instead - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrIsTraversable($value, $message = '') - { - null === $value || static::isTraversable($value, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<iterable> $value - * - * @deprecated use "isIterable" or "isInstanceOf" instead - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allIsTraversable($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::isTraversable($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<iterable|null> $value - * - * @deprecated use "isIterable" or "isInstanceOf" instead - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrIsTraversable($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::isTraversable($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert array|ArrayAccess|null $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrIsArrayAccessible($value, $message = '') - { - null === $value || static::isArrayAccessible($value, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<array|ArrayAccess> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allIsArrayAccessible($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::isArrayAccessible($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<array|ArrayAccess|null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrIsArrayAccessible($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::isArrayAccessible($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert countable|null $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrIsCountable($value, $message = '') - { - null === $value || static::isCountable($value, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<countable> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allIsCountable($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::isCountable($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<countable|null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrIsCountable($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::isCountable($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable|null $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrIsIterable($value, $message = '') - { - null === $value || static::isIterable($value, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<iterable> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allIsIterable($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::isIterable($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<iterable|null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrIsIterable($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::isIterable($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-template ExpectedType of object - * @psalm-param class-string<ExpectedType> $class - * @psalm-assert ExpectedType|null $value - * - * @param mixed $value - * @param string|object $class - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrIsInstanceOf($value, $class, $message = '') - { - null === $value || static::isInstanceOf($value, $class, $message); - } - - /** - * @psalm-pure - * @psalm-template ExpectedType of object - * @psalm-param class-string<ExpectedType> $class - * @psalm-assert iterable<ExpectedType> $value - * - * @param mixed $value - * @param string|object $class - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allIsInstanceOf($value, $class, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::isInstanceOf($entry, $class, $message); - } - } - - /** - * @psalm-pure - * @psalm-template ExpectedType of object - * @psalm-param class-string<ExpectedType> $class - * @psalm-assert iterable<ExpectedType|null> $value - * - * @param mixed $value - * @param string|object $class - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrIsInstanceOf($value, $class, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::isInstanceOf($entry, $class, $message); - } - } - - /** - * @psalm-pure - * @psalm-template ExpectedType of object - * @psalm-param class-string<ExpectedType> $class - * - * @param mixed $value - * @param string|object $class - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrNotInstanceOf($value, $class, $message = '') - { - null === $value || static::notInstanceOf($value, $class, $message); - } - - /** - * @psalm-pure - * @psalm-template ExpectedType of object - * @psalm-param class-string<ExpectedType> $class - * - * @param mixed $value - * @param string|object $class - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNotInstanceOf($value, $class, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::notInstanceOf($entry, $class, $message); - } - } - - /** - * @psalm-pure - * @psalm-template ExpectedType of object - * @psalm-param class-string<ExpectedType> $class - * @psalm-assert iterable<!ExpectedType|null> $value - * - * @param mixed $value - * @param string|object $class - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrNotInstanceOf($value, $class, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::notInstanceOf($entry, $class, $message); - } - } - - /** - * @psalm-pure - * @psalm-param array<class-string> $classes - * - * @param mixed $value - * @param array<object|string> $classes - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrIsInstanceOfAny($value, $classes, $message = '') - { - null === $value || static::isInstanceOfAny($value, $classes, $message); - } - - /** - * @psalm-pure - * @psalm-param array<class-string> $classes - * - * @param mixed $value - * @param array<object|string> $classes - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allIsInstanceOfAny($value, $classes, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::isInstanceOfAny($entry, $classes, $message); - } - } - - /** - * @psalm-pure - * @psalm-param array<class-string> $classes - * - * @param mixed $value - * @param array<object|string> $classes - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrIsInstanceOfAny($value, $classes, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::isInstanceOfAny($entry, $classes, $message); - } - } - - /** - * @psalm-pure - * @psalm-template ExpectedType of object - * @psalm-param class-string<ExpectedType> $class - * @psalm-assert ExpectedType|class-string<ExpectedType>|null $value - * - * @param object|string|null $value - * @param string $class - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrIsAOf($value, $class, $message = '') - { - null === $value || static::isAOf($value, $class, $message); - } - - /** - * @psalm-pure - * @psalm-template ExpectedType of object - * @psalm-param class-string<ExpectedType> $class - * @psalm-assert iterable<ExpectedType|class-string<ExpectedType>> $value - * - * @param iterable<object|string> $value - * @param string $class - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allIsAOf($value, $class, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::isAOf($entry, $class, $message); - } - } - - /** - * @psalm-pure - * @psalm-template ExpectedType of object - * @psalm-param class-string<ExpectedType> $class - * @psalm-assert iterable<ExpectedType|class-string<ExpectedType>|null> $value - * - * @param iterable<object|string|null> $value - * @param string $class - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrIsAOf($value, $class, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::isAOf($entry, $class, $message); - } - } - - /** - * @psalm-pure - * @psalm-template UnexpectedType of object - * @psalm-param class-string<UnexpectedType> $class - * - * @param object|string|null $value - * @param string $class - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrIsNotA($value, $class, $message = '') - { - null === $value || static::isNotA($value, $class, $message); - } - - /** - * @psalm-pure - * @psalm-template UnexpectedType of object - * @psalm-param class-string<UnexpectedType> $class - * - * @param iterable<object|string> $value - * @param string $class - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allIsNotA($value, $class, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::isNotA($entry, $class, $message); - } - } - - /** - * @psalm-pure - * @psalm-template UnexpectedType of object - * @psalm-param class-string<UnexpectedType> $class - * @psalm-assert iterable<!UnexpectedType|null> $value - * @psalm-assert iterable<!class-string<UnexpectedType>|null> $value - * - * @param iterable<object|string|null> $value - * @param string $class - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrIsNotA($value, $class, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::isNotA($entry, $class, $message); - } - } - - /** - * @psalm-pure - * @psalm-param array<class-string> $classes - * - * @param object|string|null $value - * @param string[] $classes - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrIsAnyOf($value, $classes, $message = '') - { - null === $value || static::isAnyOf($value, $classes, $message); - } - - /** - * @psalm-pure - * @psalm-param array<class-string> $classes - * - * @param iterable<object|string> $value - * @param string[] $classes - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allIsAnyOf($value, $classes, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::isAnyOf($entry, $classes, $message); - } - } - - /** - * @psalm-pure - * @psalm-param array<class-string> $classes - * - * @param iterable<object|string|null> $value - * @param string[] $classes - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrIsAnyOf($value, $classes, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::isAnyOf($entry, $classes, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert empty $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrIsEmpty($value, $message = '') - { - null === $value || static::isEmpty($value, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<empty> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allIsEmpty($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::isEmpty($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<empty|null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrIsEmpty($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::isEmpty($entry, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrNotEmpty($value, $message = '') - { - null === $value || static::notEmpty($value, $message); - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNotEmpty($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::notEmpty($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<!empty|null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrNotEmpty($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::notEmpty($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNull($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::null($entry, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNotNull($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::notNull($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert true|null $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrTrue($value, $message = '') - { - null === $value || static::true($value, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<true> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allTrue($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::true($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<true|null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrTrue($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::true($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert false|null $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrFalse($value, $message = '') - { - null === $value || static::false($value, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<false> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allFalse($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::false($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<false|null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrFalse($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::false($entry, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrNotFalse($value, $message = '') - { - null === $value || static::notFalse($value, $message); - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNotFalse($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::notFalse($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<!false|null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrNotFalse($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::notFalse($entry, $message); - } - } - - /** - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrIp($value, $message = '') - { - null === $value || static::ip($value, $message); - } - - /** - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allIp($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::ip($entry, $message); - } - } - - /** - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrIp($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::ip($entry, $message); - } - } - - /** - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrIpv4($value, $message = '') - { - null === $value || static::ipv4($value, $message); - } - - /** - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allIpv4($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::ipv4($entry, $message); - } - } - - /** - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrIpv4($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::ipv4($entry, $message); - } - } - - /** - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrIpv6($value, $message = '') - { - null === $value || static::ipv6($value, $message); - } - - /** - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allIpv6($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::ipv6($entry, $message); - } - } - - /** - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrIpv6($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::ipv6($entry, $message); - } - } - - /** - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrEmail($value, $message = '') - { - null === $value || static::email($value, $message); - } - - /** - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allEmail($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::email($entry, $message); - } - } - - /** - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrEmail($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::email($entry, $message); - } - } - - /** - * @param array|null $values - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrUniqueValues($values, $message = '') - { - null === $values || static::uniqueValues($values, $message); - } - - /** - * @param iterable<array> $values - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allUniqueValues($values, $message = '') - { - static::isIterable($values); - - foreach ($values as $entry) { - static::uniqueValues($entry, $message); - } - } - - /** - * @param iterable<array|null> $values - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrUniqueValues($values, $message = '') - { - static::isIterable($values); - - foreach ($values as $entry) { - null === $entry || static::uniqueValues($entry, $message); - } - } - - /** - * @param mixed $value - * @param mixed $expect - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrEq($value, $expect, $message = '') - { - null === $value || static::eq($value, $expect, $message); - } - - /** - * @param mixed $value - * @param mixed $expect - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allEq($value, $expect, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::eq($entry, $expect, $message); - } - } - - /** - * @param mixed $value - * @param mixed $expect - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrEq($value, $expect, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::eq($entry, $expect, $message); - } - } - - /** - * @param mixed $value - * @param mixed $expect - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrNotEq($value, $expect, $message = '') - { - null === $value || static::notEq($value, $expect, $message); - } - - /** - * @param mixed $value - * @param mixed $expect - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNotEq($value, $expect, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::notEq($entry, $expect, $message); - } - } - - /** - * @param mixed $value - * @param mixed $expect - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrNotEq($value, $expect, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::notEq($entry, $expect, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param mixed $expect - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrSame($value, $expect, $message = '') - { - null === $value || static::same($value, $expect, $message); - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param mixed $expect - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allSame($value, $expect, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::same($entry, $expect, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param mixed $expect - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrSame($value, $expect, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::same($entry, $expect, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param mixed $expect - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrNotSame($value, $expect, $message = '') - { - null === $value || static::notSame($value, $expect, $message); - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param mixed $expect - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNotSame($value, $expect, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::notSame($entry, $expect, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param mixed $expect - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrNotSame($value, $expect, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::notSame($entry, $expect, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param mixed $limit - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrGreaterThan($value, $limit, $message = '') - { - null === $value || static::greaterThan($value, $limit, $message); - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param mixed $limit - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allGreaterThan($value, $limit, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::greaterThan($entry, $limit, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param mixed $limit - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrGreaterThan($value, $limit, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::greaterThan($entry, $limit, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param mixed $limit - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrGreaterThanEq($value, $limit, $message = '') - { - null === $value || static::greaterThanEq($value, $limit, $message); - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param mixed $limit - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allGreaterThanEq($value, $limit, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::greaterThanEq($entry, $limit, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param mixed $limit - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrGreaterThanEq($value, $limit, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::greaterThanEq($entry, $limit, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param mixed $limit - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrLessThan($value, $limit, $message = '') - { - null === $value || static::lessThan($value, $limit, $message); - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param mixed $limit - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allLessThan($value, $limit, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::lessThan($entry, $limit, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param mixed $limit - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrLessThan($value, $limit, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::lessThan($entry, $limit, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param mixed $limit - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrLessThanEq($value, $limit, $message = '') - { - null === $value || static::lessThanEq($value, $limit, $message); - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param mixed $limit - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allLessThanEq($value, $limit, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::lessThanEq($entry, $limit, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param mixed $limit - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrLessThanEq($value, $limit, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::lessThanEq($entry, $limit, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param mixed $min - * @param mixed $max - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrRange($value, $min, $max, $message = '') - { - null === $value || static::range($value, $min, $max, $message); - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param mixed $min - * @param mixed $max - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allRange($value, $min, $max, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::range($entry, $min, $max, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param mixed $min - * @param mixed $max - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrRange($value, $min, $max, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::range($entry, $min, $max, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param array $values - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrOneOf($value, $values, $message = '') - { - null === $value || static::oneOf($value, $values, $message); - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param array $values - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allOneOf($value, $values, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::oneOf($entry, $values, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param array $values - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrOneOf($value, $values, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::oneOf($entry, $values, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param array $values - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrInArray($value, $values, $message = '') - { - null === $value || static::inArray($value, $values, $message); - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param array $values - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allInArray($value, $values, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::inArray($entry, $values, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param array $values - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrInArray($value, $values, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::inArray($entry, $values, $message); - } - } - - /** - * @psalm-pure - * - * @param string|null $value - * @param string $subString - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrContains($value, $subString, $message = '') - { - null === $value || static::contains($value, $subString, $message); - } - - /** - * @psalm-pure - * - * @param iterable<string> $value - * @param string $subString - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allContains($value, $subString, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::contains($entry, $subString, $message); - } - } - - /** - * @psalm-pure - * - * @param iterable<string|null> $value - * @param string $subString - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrContains($value, $subString, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::contains($entry, $subString, $message); - } - } - - /** - * @psalm-pure - * - * @param string|null $value - * @param string $subString - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrNotContains($value, $subString, $message = '') - { - null === $value || static::notContains($value, $subString, $message); - } - - /** - * @psalm-pure - * - * @param iterable<string> $value - * @param string $subString - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNotContains($value, $subString, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::notContains($entry, $subString, $message); - } - } - - /** - * @psalm-pure - * - * @param iterable<string|null> $value - * @param string $subString - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrNotContains($value, $subString, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::notContains($entry, $subString, $message); - } - } - - /** - * @psalm-pure - * - * @param string|null $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrNotWhitespaceOnly($value, $message = '') - { - null === $value || static::notWhitespaceOnly($value, $message); - } - - /** - * @psalm-pure - * - * @param iterable<string> $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNotWhitespaceOnly($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::notWhitespaceOnly($entry, $message); - } - } - - /** - * @psalm-pure - * - * @param iterable<string|null> $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrNotWhitespaceOnly($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::notWhitespaceOnly($entry, $message); - } - } - - /** - * @psalm-pure - * - * @param string|null $value - * @param string $prefix - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrStartsWith($value, $prefix, $message = '') - { - null === $value || static::startsWith($value, $prefix, $message); - } - - /** - * @psalm-pure - * - * @param iterable<string> $value - * @param string $prefix - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allStartsWith($value, $prefix, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::startsWith($entry, $prefix, $message); - } - } - - /** - * @psalm-pure - * - * @param iterable<string|null> $value - * @param string $prefix - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrStartsWith($value, $prefix, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::startsWith($entry, $prefix, $message); - } - } - - /** - * @psalm-pure - * - * @param string|null $value - * @param string $prefix - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrNotStartsWith($value, $prefix, $message = '') - { - null === $value || static::notStartsWith($value, $prefix, $message); - } - - /** - * @psalm-pure - * - * @param iterable<string> $value - * @param string $prefix - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNotStartsWith($value, $prefix, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::notStartsWith($entry, $prefix, $message); - } - } - - /** - * @psalm-pure - * - * @param iterable<string|null> $value - * @param string $prefix - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrNotStartsWith($value, $prefix, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::notStartsWith($entry, $prefix, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrStartsWithLetter($value, $message = '') - { - null === $value || static::startsWithLetter($value, $message); - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allStartsWithLetter($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::startsWithLetter($entry, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrStartsWithLetter($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::startsWithLetter($entry, $message); - } - } - - /** - * @psalm-pure - * - * @param string|null $value - * @param string $suffix - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrEndsWith($value, $suffix, $message = '') - { - null === $value || static::endsWith($value, $suffix, $message); - } - - /** - * @psalm-pure - * - * @param iterable<string> $value - * @param string $suffix - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allEndsWith($value, $suffix, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::endsWith($entry, $suffix, $message); - } - } - - /** - * @psalm-pure - * - * @param iterable<string|null> $value - * @param string $suffix - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrEndsWith($value, $suffix, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::endsWith($entry, $suffix, $message); - } - } - - /** - * @psalm-pure - * - * @param string|null $value - * @param string $suffix - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrNotEndsWith($value, $suffix, $message = '') - { - null === $value || static::notEndsWith($value, $suffix, $message); - } - - /** - * @psalm-pure - * - * @param iterable<string> $value - * @param string $suffix - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNotEndsWith($value, $suffix, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::notEndsWith($entry, $suffix, $message); - } - } - - /** - * @psalm-pure - * - * @param iterable<string|null> $value - * @param string $suffix - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrNotEndsWith($value, $suffix, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::notEndsWith($entry, $suffix, $message); - } - } - - /** - * @psalm-pure - * - * @param string|null $value - * @param string $pattern - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrRegex($value, $pattern, $message = '') - { - null === $value || static::regex($value, $pattern, $message); - } - - /** - * @psalm-pure - * - * @param iterable<string> $value - * @param string $pattern - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allRegex($value, $pattern, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::regex($entry, $pattern, $message); - } - } - - /** - * @psalm-pure - * - * @param iterable<string|null> $value - * @param string $pattern - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrRegex($value, $pattern, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::regex($entry, $pattern, $message); - } - } - - /** - * @psalm-pure - * - * @param string|null $value - * @param string $pattern - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrNotRegex($value, $pattern, $message = '') - { - null === $value || static::notRegex($value, $pattern, $message); - } - - /** - * @psalm-pure - * - * @param iterable<string> $value - * @param string $pattern - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNotRegex($value, $pattern, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::notRegex($entry, $pattern, $message); - } - } - - /** - * @psalm-pure - * - * @param iterable<string|null> $value - * @param string $pattern - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrNotRegex($value, $pattern, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::notRegex($entry, $pattern, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrUnicodeLetters($value, $message = '') - { - null === $value || static::unicodeLetters($value, $message); - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allUnicodeLetters($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::unicodeLetters($entry, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrUnicodeLetters($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::unicodeLetters($entry, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrAlpha($value, $message = '') - { - null === $value || static::alpha($value, $message); - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allAlpha($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::alpha($entry, $message); - } - } - - /** - * @psalm-pure - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrAlpha($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::alpha($entry, $message); - } - } - - /** - * @psalm-pure - * - * @param string|null $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrDigits($value, $message = '') - { - null === $value || static::digits($value, $message); - } - - /** - * @psalm-pure - * - * @param iterable<string> $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allDigits($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::digits($entry, $message); - } - } - - /** - * @psalm-pure - * - * @param iterable<string|null> $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrDigits($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::digits($entry, $message); - } - } - - /** - * @psalm-pure - * - * @param string|null $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrAlnum($value, $message = '') - { - null === $value || static::alnum($value, $message); - } - - /** - * @psalm-pure - * - * @param iterable<string> $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allAlnum($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::alnum($entry, $message); - } - } - - /** - * @psalm-pure - * - * @param iterable<string|null> $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrAlnum($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::alnum($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert lowercase-string|null $value - * - * @param string|null $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrLower($value, $message = '') - { - null === $value || static::lower($value, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<lowercase-string> $value - * - * @param iterable<string> $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allLower($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::lower($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<lowercase-string|null> $value - * - * @param iterable<string|null> $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrLower($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::lower($entry, $message); - } - } - - /** - * @psalm-pure - * - * @param string|null $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrUpper($value, $message = '') - { - null === $value || static::upper($value, $message); - } - - /** - * @psalm-pure - * - * @param iterable<string> $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allUpper($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::upper($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<!lowercase-string|null> $value - * - * @param iterable<string|null> $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrUpper($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::upper($entry, $message); - } - } - - /** - * @psalm-pure - * - * @param string|null $value - * @param int $length - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrLength($value, $length, $message = '') - { - null === $value || static::length($value, $length, $message); - } - - /** - * @psalm-pure - * - * @param iterable<string> $value - * @param int $length - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allLength($value, $length, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::length($entry, $length, $message); - } - } - - /** - * @psalm-pure - * - * @param iterable<string|null> $value - * @param int $length - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrLength($value, $length, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::length($entry, $length, $message); - } - } - - /** - * @psalm-pure - * - * @param string|null $value - * @param int|float $min - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrMinLength($value, $min, $message = '') - { - null === $value || static::minLength($value, $min, $message); - } - - /** - * @psalm-pure - * - * @param iterable<string> $value - * @param int|float $min - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allMinLength($value, $min, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::minLength($entry, $min, $message); - } - } - - /** - * @psalm-pure - * - * @param iterable<string|null> $value - * @param int|float $min - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrMinLength($value, $min, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::minLength($entry, $min, $message); - } - } - - /** - * @psalm-pure - * - * @param string|null $value - * @param int|float $max - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrMaxLength($value, $max, $message = '') - { - null === $value || static::maxLength($value, $max, $message); - } - - /** - * @psalm-pure - * - * @param iterable<string> $value - * @param int|float $max - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allMaxLength($value, $max, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::maxLength($entry, $max, $message); - } - } - - /** - * @psalm-pure - * - * @param iterable<string|null> $value - * @param int|float $max - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrMaxLength($value, $max, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::maxLength($entry, $max, $message); - } - } - - /** - * @psalm-pure - * - * @param string|null $value - * @param int|float $min - * @param int|float $max - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrLengthBetween($value, $min, $max, $message = '') - { - null === $value || static::lengthBetween($value, $min, $max, $message); - } - - /** - * @psalm-pure - * - * @param iterable<string> $value - * @param int|float $min - * @param int|float $max - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allLengthBetween($value, $min, $max, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::lengthBetween($entry, $min, $max, $message); - } - } - - /** - * @psalm-pure - * - * @param iterable<string|null> $value - * @param int|float $min - * @param int|float $max - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrLengthBetween($value, $min, $max, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::lengthBetween($entry, $min, $max, $message); - } - } - - /** - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrFileExists($value, $message = '') - { - null === $value || static::fileExists($value, $message); - } - - /** - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allFileExists($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::fileExists($entry, $message); - } - } - - /** - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrFileExists($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::fileExists($entry, $message); - } - } - - /** - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrFile($value, $message = '') - { - null === $value || static::file($value, $message); - } - - /** - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allFile($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::file($entry, $message); - } - } - - /** - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrFile($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::file($entry, $message); - } - } - - /** - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrDirectory($value, $message = '') - { - null === $value || static::directory($value, $message); - } - - /** - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allDirectory($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::directory($entry, $message); - } - } - - /** - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrDirectory($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::directory($entry, $message); - } - } - - /** - * @param string|null $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrReadable($value, $message = '') - { - null === $value || static::readable($value, $message); - } - - /** - * @param iterable<string> $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allReadable($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::readable($entry, $message); - } - } - - /** - * @param iterable<string|null> $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrReadable($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::readable($entry, $message); - } - } - - /** - * @param string|null $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrWritable($value, $message = '') - { - null === $value || static::writable($value, $message); - } - - /** - * @param iterable<string> $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allWritable($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::writable($entry, $message); - } - } - - /** - * @param iterable<string|null> $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrWritable($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::writable($entry, $message); - } - } - - /** - * @psalm-assert class-string|null $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrClassExists($value, $message = '') - { - null === $value || static::classExists($value, $message); - } - - /** - * @psalm-assert iterable<class-string> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allClassExists($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::classExists($entry, $message); - } - } - - /** - * @psalm-assert iterable<class-string|null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrClassExists($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::classExists($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-template ExpectedType of object - * @psalm-param class-string<ExpectedType> $class - * @psalm-assert class-string<ExpectedType>|ExpectedType|null $value - * - * @param mixed $value - * @param string|object $class - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrSubclassOf($value, $class, $message = '') - { - null === $value || static::subclassOf($value, $class, $message); - } - - /** - * @psalm-pure - * @psalm-template ExpectedType of object - * @psalm-param class-string<ExpectedType> $class - * @psalm-assert iterable<class-string<ExpectedType>|ExpectedType> $value - * - * @param mixed $value - * @param string|object $class - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allSubclassOf($value, $class, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::subclassOf($entry, $class, $message); - } - } - - /** - * @psalm-pure - * @psalm-template ExpectedType of object - * @psalm-param class-string<ExpectedType> $class - * @psalm-assert iterable<class-string<ExpectedType>|ExpectedType|null> $value - * - * @param mixed $value - * @param string|object $class - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrSubclassOf($value, $class, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::subclassOf($entry, $class, $message); - } - } - - /** - * @psalm-assert class-string|null $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrInterfaceExists($value, $message = '') - { - null === $value || static::interfaceExists($value, $message); - } - - /** - * @psalm-assert iterable<class-string> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allInterfaceExists($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::interfaceExists($entry, $message); - } - } - - /** - * @psalm-assert iterable<class-string|null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrInterfaceExists($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::interfaceExists($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-template ExpectedType of object - * @psalm-param class-string<ExpectedType> $interface - * @psalm-assert class-string<ExpectedType>|null $value - * - * @param mixed $value - * @param mixed $interface - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrImplementsInterface($value, $interface, $message = '') - { - null === $value || static::implementsInterface($value, $interface, $message); - } - - /** - * @psalm-pure - * @psalm-template ExpectedType of object - * @psalm-param class-string<ExpectedType> $interface - * @psalm-assert iterable<class-string<ExpectedType>> $value - * - * @param mixed $value - * @param mixed $interface - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allImplementsInterface($value, $interface, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::implementsInterface($entry, $interface, $message); - } - } - - /** - * @psalm-pure - * @psalm-template ExpectedType of object - * @psalm-param class-string<ExpectedType> $interface - * @psalm-assert iterable<class-string<ExpectedType>|null> $value - * - * @param mixed $value - * @param mixed $interface - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrImplementsInterface($value, $interface, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::implementsInterface($entry, $interface, $message); - } - } - - /** - * @psalm-pure - * @psalm-param class-string|object|null $classOrObject - * - * @param string|object|null $classOrObject - * @param mixed $property - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrPropertyExists($classOrObject, $property, $message = '') - { - null === $classOrObject || static::propertyExists($classOrObject, $property, $message); - } - - /** - * @psalm-pure - * @psalm-param iterable<class-string|object> $classOrObject - * - * @param iterable<string|object> $classOrObject - * @param mixed $property - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allPropertyExists($classOrObject, $property, $message = '') - { - static::isIterable($classOrObject); - - foreach ($classOrObject as $entry) { - static::propertyExists($entry, $property, $message); - } - } - - /** - * @psalm-pure - * @psalm-param iterable<class-string|object|null> $classOrObject - * - * @param iterable<string|object|null> $classOrObject - * @param mixed $property - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrPropertyExists($classOrObject, $property, $message = '') - { - static::isIterable($classOrObject); - - foreach ($classOrObject as $entry) { - null === $entry || static::propertyExists($entry, $property, $message); - } - } - - /** - * @psalm-pure - * @psalm-param class-string|object|null $classOrObject - * - * @param string|object|null $classOrObject - * @param mixed $property - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrPropertyNotExists($classOrObject, $property, $message = '') - { - null === $classOrObject || static::propertyNotExists($classOrObject, $property, $message); - } - - /** - * @psalm-pure - * @psalm-param iterable<class-string|object> $classOrObject - * - * @param iterable<string|object> $classOrObject - * @param mixed $property - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allPropertyNotExists($classOrObject, $property, $message = '') - { - static::isIterable($classOrObject); - - foreach ($classOrObject as $entry) { - static::propertyNotExists($entry, $property, $message); - } - } - - /** - * @psalm-pure - * @psalm-param iterable<class-string|object|null> $classOrObject - * - * @param iterable<string|object|null> $classOrObject - * @param mixed $property - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrPropertyNotExists($classOrObject, $property, $message = '') - { - static::isIterable($classOrObject); - - foreach ($classOrObject as $entry) { - null === $entry || static::propertyNotExists($entry, $property, $message); - } - } - - /** - * @psalm-pure - * @psalm-param class-string|object|null $classOrObject - * - * @param string|object|null $classOrObject - * @param mixed $method - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrMethodExists($classOrObject, $method, $message = '') - { - null === $classOrObject || static::methodExists($classOrObject, $method, $message); - } - - /** - * @psalm-pure - * @psalm-param iterable<class-string|object> $classOrObject - * - * @param iterable<string|object> $classOrObject - * @param mixed $method - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allMethodExists($classOrObject, $method, $message = '') - { - static::isIterable($classOrObject); - - foreach ($classOrObject as $entry) { - static::methodExists($entry, $method, $message); - } - } - - /** - * @psalm-pure - * @psalm-param iterable<class-string|object|null> $classOrObject - * - * @param iterable<string|object|null> $classOrObject - * @param mixed $method - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrMethodExists($classOrObject, $method, $message = '') - { - static::isIterable($classOrObject); - - foreach ($classOrObject as $entry) { - null === $entry || static::methodExists($entry, $method, $message); - } - } - - /** - * @psalm-pure - * @psalm-param class-string|object|null $classOrObject - * - * @param string|object|null $classOrObject - * @param mixed $method - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrMethodNotExists($classOrObject, $method, $message = '') - { - null === $classOrObject || static::methodNotExists($classOrObject, $method, $message); - } - - /** - * @psalm-pure - * @psalm-param iterable<class-string|object> $classOrObject - * - * @param iterable<string|object> $classOrObject - * @param mixed $method - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allMethodNotExists($classOrObject, $method, $message = '') - { - static::isIterable($classOrObject); - - foreach ($classOrObject as $entry) { - static::methodNotExists($entry, $method, $message); - } - } - - /** - * @psalm-pure - * @psalm-param iterable<class-string|object|null> $classOrObject - * - * @param iterable<string|object|null> $classOrObject - * @param mixed $method - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrMethodNotExists($classOrObject, $method, $message = '') - { - static::isIterable($classOrObject); - - foreach ($classOrObject as $entry) { - null === $entry || static::methodNotExists($entry, $method, $message); - } - } - - /** - * @psalm-pure - * - * @param array|null $array - * @param string|int $key - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrKeyExists($array, $key, $message = '') - { - null === $array || static::keyExists($array, $key, $message); - } - - /** - * @psalm-pure - * - * @param iterable<array> $array - * @param string|int $key - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allKeyExists($array, $key, $message = '') - { - static::isIterable($array); - - foreach ($array as $entry) { - static::keyExists($entry, $key, $message); - } - } - - /** - * @psalm-pure - * - * @param iterable<array|null> $array - * @param string|int $key - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrKeyExists($array, $key, $message = '') - { - static::isIterable($array); - - foreach ($array as $entry) { - null === $entry || static::keyExists($entry, $key, $message); - } - } - - /** - * @psalm-pure - * - * @param array|null $array - * @param string|int $key - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrKeyNotExists($array, $key, $message = '') - { - null === $array || static::keyNotExists($array, $key, $message); - } - - /** - * @psalm-pure - * - * @param iterable<array> $array - * @param string|int $key - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allKeyNotExists($array, $key, $message = '') - { - static::isIterable($array); - - foreach ($array as $entry) { - static::keyNotExists($entry, $key, $message); - } - } - - /** - * @psalm-pure - * - * @param iterable<array|null> $array - * @param string|int $key - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrKeyNotExists($array, $key, $message = '') - { - static::isIterable($array); - - foreach ($array as $entry) { - null === $entry || static::keyNotExists($entry, $key, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert array-key|null $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrValidArrayKey($value, $message = '') - { - null === $value || static::validArrayKey($value, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<array-key> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allValidArrayKey($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::validArrayKey($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<array-key|null> $value - * - * @param mixed $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrValidArrayKey($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::validArrayKey($entry, $message); - } - } - - /** - * @param Countable|array|null $array - * @param int $number - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrCount($array, $number, $message = '') - { - null === $array || static::count($array, $number, $message); - } - - /** - * @param iterable<Countable|array> $array - * @param int $number - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allCount($array, $number, $message = '') - { - static::isIterable($array); - - foreach ($array as $entry) { - static::count($entry, $number, $message); - } - } - - /** - * @param iterable<Countable|array|null> $array - * @param int $number - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrCount($array, $number, $message = '') - { - static::isIterable($array); - - foreach ($array as $entry) { - null === $entry || static::count($entry, $number, $message); - } - } - - /** - * @param Countable|array|null $array - * @param int|float $min - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrMinCount($array, $min, $message = '') - { - null === $array || static::minCount($array, $min, $message); - } - - /** - * @param iterable<Countable|array> $array - * @param int|float $min - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allMinCount($array, $min, $message = '') - { - static::isIterable($array); - - foreach ($array as $entry) { - static::minCount($entry, $min, $message); - } - } - - /** - * @param iterable<Countable|array|null> $array - * @param int|float $min - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrMinCount($array, $min, $message = '') - { - static::isIterable($array); - - foreach ($array as $entry) { - null === $entry || static::minCount($entry, $min, $message); - } - } - - /** - * @param Countable|array|null $array - * @param int|float $max - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrMaxCount($array, $max, $message = '') - { - null === $array || static::maxCount($array, $max, $message); - } - - /** - * @param iterable<Countable|array> $array - * @param int|float $max - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allMaxCount($array, $max, $message = '') - { - static::isIterable($array); - - foreach ($array as $entry) { - static::maxCount($entry, $max, $message); - } - } - - /** - * @param iterable<Countable|array|null> $array - * @param int|float $max - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrMaxCount($array, $max, $message = '') - { - static::isIterable($array); - - foreach ($array as $entry) { - null === $entry || static::maxCount($entry, $max, $message); - } - } - - /** - * @param Countable|array|null $array - * @param int|float $min - * @param int|float $max - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrCountBetween($array, $min, $max, $message = '') - { - null === $array || static::countBetween($array, $min, $max, $message); - } - - /** - * @param iterable<Countable|array> $array - * @param int|float $min - * @param int|float $max - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allCountBetween($array, $min, $max, $message = '') - { - static::isIterable($array); - - foreach ($array as $entry) { - static::countBetween($entry, $min, $max, $message); - } - } - - /** - * @param iterable<Countable|array|null> $array - * @param int|float $min - * @param int|float $max - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrCountBetween($array, $min, $max, $message = '') - { - static::isIterable($array); - - foreach ($array as $entry) { - null === $entry || static::countBetween($entry, $min, $max, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert list|null $array - * - * @param mixed $array - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrIsList($array, $message = '') - { - null === $array || static::isList($array, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<list> $array - * - * @param mixed $array - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allIsList($array, $message = '') - { - static::isIterable($array); - - foreach ($array as $entry) { - static::isList($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<list|null> $array - * - * @param mixed $array - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrIsList($array, $message = '') - { - static::isIterable($array); - - foreach ($array as $entry) { - null === $entry || static::isList($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert non-empty-list|null $array - * - * @param mixed $array - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrIsNonEmptyList($array, $message = '') - { - null === $array || static::isNonEmptyList($array, $message); - } - - /** - * @psalm-pure - * @psalm-assert iterable<non-empty-list> $array - * - * @param mixed $array - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allIsNonEmptyList($array, $message = '') - { - static::isIterable($array); - - foreach ($array as $entry) { - static::isNonEmptyList($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-assert iterable<non-empty-list|null> $array - * - * @param mixed $array - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrIsNonEmptyList($array, $message = '') - { - static::isIterable($array); - - foreach ($array as $entry) { - null === $entry || static::isNonEmptyList($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-template T - * @psalm-param mixed|array<T>|null $array - * @psalm-assert array<string, T>|null $array - * - * @param mixed $array - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrIsMap($array, $message = '') - { - null === $array || static::isMap($array, $message); - } - - /** - * @psalm-pure - * @psalm-template T - * @psalm-param iterable<mixed|array<T>> $array - * @psalm-assert iterable<array<string, T>> $array - * - * @param mixed $array - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allIsMap($array, $message = '') - { - static::isIterable($array); - - foreach ($array as $entry) { - static::isMap($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-template T - * @psalm-param iterable<mixed|array<T>|null> $array - * @psalm-assert iterable<array<string, T>|null> $array - * - * @param mixed $array - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrIsMap($array, $message = '') - { - static::isIterable($array); - - foreach ($array as $entry) { - null === $entry || static::isMap($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-template T - * @psalm-param mixed|array<T>|null $array - * - * @param mixed $array - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrIsNonEmptyMap($array, $message = '') - { - null === $array || static::isNonEmptyMap($array, $message); - } - - /** - * @psalm-pure - * @psalm-template T - * @psalm-param iterable<mixed|array<T>> $array - * - * @param mixed $array - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allIsNonEmptyMap($array, $message = '') - { - static::isIterable($array); - - foreach ($array as $entry) { - static::isNonEmptyMap($entry, $message); - } - } - - /** - * @psalm-pure - * @psalm-template T - * @psalm-param iterable<mixed|array<T>|null> $array - * @psalm-assert iterable<array<string, T>|null> $array - * @psalm-assert iterable<!empty|null> $array - * - * @param mixed $array - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrIsNonEmptyMap($array, $message = '') - { - static::isIterable($array); - - foreach ($array as $entry) { - null === $entry || static::isNonEmptyMap($entry, $message); - } - } - - /** - * @psalm-pure - * - * @param string|null $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrUuid($value, $message = '') - { - null === $value || static::uuid($value, $message); - } - - /** - * @psalm-pure - * - * @param iterable<string> $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allUuid($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - static::uuid($entry, $message); - } - } - - /** - * @psalm-pure - * - * @param iterable<string|null> $value - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrUuid($value, $message = '') - { - static::isIterable($value); - - foreach ($value as $entry) { - null === $entry || static::uuid($entry, $message); - } - } - - /** - * @psalm-param class-string<Throwable> $class - * - * @param Closure|null $expression - * @param string $class - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function nullOrThrows($expression, $class = 'Exception', $message = '') - { - null === $expression || static::throws($expression, $class, $message); - } - - /** - * @psalm-param class-string<Throwable> $class - * - * @param iterable<Closure> $expression - * @param string $class - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allThrows($expression, $class = 'Exception', $message = '') - { - static::isIterable($expression); - - foreach ($expression as $entry) { - static::throws($entry, $class, $message); - } - } - - /** - * @psalm-param class-string<Throwable> $class - * - * @param iterable<Closure|null> $expression - * @param string $class - * @param string $message - * - * @throws InvalidArgumentException - * - * @return void - */ - public static function allNullOrThrows($expression, $class = 'Exception', $message = '') - { - static::isIterable($expression); - - foreach ($expression as $entry) { - null === $entry || static::throws($entry, $class, $message); - } - } -} diff --git a/sources/DI/Controller/Controller.php b/sources/DI/Controller/Controller.php index c34630b99..1db7cc5cc 100644 --- a/sources/DI/Controller/Controller.php +++ b/sources/DI/Controller/Controller.php @@ -2,16 +2,18 @@ namespace Combodo\iTop\DI\Controller; -use Combodo\iTop\DI\Form\Type\ConfigurationType; -use Combodo\iTop\DI\Form\Type\ObjectType; -use Combodo\iTop\DI\Form\Type\ObjectSingleAttributeType; +use Combodo\iTop\DI\Form\Type\Compound\ConfigurationType; +use Combodo\iTop\DI\Form\Type\Compound\ObjectSingleAttributeType; +use Combodo\iTop\DI\Form\Type\Compound\ObjectType; use Combodo\iTop\DI\Services\ObjectService; use Exception; use MetaModel; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\Routing\Annotation\Route; class Controller extends AbstractController @@ -38,7 +40,7 @@ class Controller extends AbstractController */ public function objectView(string $class, int $id) : Response { - // retrieve person + // retrieve object try{ $oObject = MetaModel::GetObject($class, $id); } @@ -46,7 +48,7 @@ class Controller extends AbstractController throw $this->createNotFoundException("The $class $id does not exist"); } - // return person view + // return object view return $this->render('DI/object/view.html.twig', [ 'id' => $id, 'class' => $class, @@ -59,7 +61,7 @@ class Controller extends AbstractController */ public function objectJSon(string $class, int $id) : Response { - // retrieve person + // retrieve object try{ $oObject = MetaModel::GetObject($class, $id); } @@ -67,7 +69,7 @@ class Controller extends AbstractController throw $this->createNotFoundException("The $class $id does not exist"); } - // return person as json response + // return object as json response $oResponse = new JsonResponse($oObject->GetValues()); $oResponse->setEncodingOptions($oResponse->getEncodingOptions() | JSON_PRETTY_PRINT); return $oResponse; @@ -78,14 +80,9 @@ class Controller extends AbstractController */ public function objectEdit(Request $request, string $class, int $id, ObjectService $oObjectService) : Response { - // retrieve person + // retrieve object try{ - if($id !== 0){ - $oObject = MetaModel::GetObject($class, $id); - } - else{ - $oObject = MetaModel::NewObject($class); - } + $oObject= $oObjectService->getObject($class, $id); } catch(Exception $e){ throw $this->createNotFoundException("The $class $id does not exist"); @@ -93,7 +90,10 @@ class Controller extends AbstractController // create object form $oForm = $this->createForm(ObjectType::class, $oObject, [ - 'object_class' => $class + 'object_class' => $class, + 'attr' => [ + 'data-reload-url' => $this->generateUrl('object_reload', ['class' => $class, "id" => $id]) + ] ]); // handle HTTP request @@ -105,11 +105,16 @@ class Controller extends AbstractController // retrieve object $oObject = $oForm->getData(); - // handle link set (apply DbInsert, DbDelete, DbUpdate) could be automatic ? - $oObjectService->handleLinkSetDB($oObject); + try { + // handle link set (apply DbInsert, DbDelete, DbUpdate) could be automatic ? + $oObjectService->handleLinkSetDB($oObject); - // save object - $oObject->DBUpdate(); + // save object + $oObject->DBUpdate(); + } + catch(Exception $e){ + throw new HttpException(500, 'Error while trying to save object'); + } // redirect to view object return $this->redirectToRoute('object_view', [ @@ -118,35 +123,94 @@ class Controller extends AbstractController ]); } - // return person edition form + // return object edition form return $this->renderForm('DI/object/edit.html.twig', [ 'id' => $id, 'class' => $class, 'form' => $oForm, - 'reload_url' => $this->generateUrl('object_reload', ['class' => $class, "id" => $id]), 'db_host' => $oObjectService->getDbHost(), 'db_name' => $oObjectService->getDbName() ]); } + /** + * @Route("/{class<\w+>}/{id<\d+>}/{name<\w+>}/form", name="object_form", methods={"POST"}) + */ + public function objectForm(Request $request, string $name, string $class, int $id, ObjectService $oObjectService, FormFactoryInterface $oFormFactory) : Response + { + // retrieve object + try{ + $oObject= $oObjectService->getObject($class, $id); + } + catch(Exception $e){ + throw $this->createNotFoundException("The $class $id does not exist"); + } + + // decode data + $aData = json_decode($request->getContent(), true); + + // create object form + $oForm = $oFormFactory->createNamed($name, ObjectType::class, $oObject, [ + 'object_class' => $class, + 'locked_attributes' => $aData['locked_attributes'], + 'attr' => [ + 'data-reload-url' => $this->generateUrl('object_reload', [ + 'class' => $class, + 'id' => $id + ]) + ] + ]); + + // handle HTTP request + $oForm->handleRequest($request); + + // submitted and valid + if ($oForm->isSubmitted() && $oForm->isValid()) { + + // retrieve object + $oObject = $oForm->getData(); + + try { + // handle link set (apply DbInsert, DbDelete, DbUpdate) could be automatic ? + $oObjectService->handleLinkSetDB($oObject); + + // save object + $oObject->DBUpdate(); + } + catch(Exception $e){ + throw new HttpException(500, 'Error while trying to save object'); + } + + // redirect to view object + return new JsonResponse(); + } + + // return object form + return new JsonResponse([ + 'template' => $this->renderView('DI/form.html.twig', [ + 'id' => $id, + 'class' => $class, + 'form' => $oForm->createView(), + ]) + ]); + } /** * @Route("/{class<\w+>}/{id<\d+>}/reload", name="object_reload") */ - public function objectReload(Request $request, string $class, int $id) : Response + public function objectReload(Request $request, string $class, int $id, ObjectService $oObjectService) : Response { - // retrieve person + // retrieve object try{ - $oObject = MetaModel::GetObject($class, $id); + $oObject= $oObjectService->getObject($class, $id); } catch(Exception $e){ throw $this->createNotFoundException("The $class $id does not exist"); } // create form with request data (dependent field) - $oForm = $this->createForm(ObjectSingleAttributeType::class, $oObject, [ + $oForm = $this->createForm(ObjectType::class, $oObject, [ 'object_class' => $class, - 'att_code' => $request->get('dependency_att_code') ]); // handle form data @@ -161,8 +225,8 @@ class Controller extends AbstractController 'att_code' => $request->get('att_code') ]); - // return person edition form - return $this->renderForm('DI/object/object_single_attribute.html.twig', [ + // return object form + return $this->renderForm('DI/form.html.twig', [ 'form' => $oForm, ]); } @@ -178,7 +242,7 @@ class Controller extends AbstractController // handle HTTP request $oForm->handleRequest($request); - // return person edition form + // return object form return $this->renderForm('DI/configuration/edit.html.twig', [ 'form' => $oForm ]); diff --git a/sources/DI/Form/Builder/AttributeBuilder.php b/sources/DI/Form/Builder/AttributeBuilder.php new file mode 100644 index 000000000..c87110e76 --- /dev/null +++ b/sources/DI/Form/Builder/AttributeBuilder.php @@ -0,0 +1,195 @@ +<?php + +namespace Combodo\iTop\DI\Form\Builder; + +use AttributeBoolean; +use AttributeDate; +use AttributeDateTime; +use AttributeEmailAddress; +use AttributeEnum; +use AttributeExternalField; +use AttributeExternalKey; +use AttributeImage; +use AttributeLinkedSet; +use AttributePassword; +use AttributePhoneNumber; +use AttributeText; +use Combodo\iTop\DI\Form\Type\Attribute\DocumentType; +use Combodo\iTop\DI\Form\Type\Attribute\ExternalFieldType; +use Combodo\iTop\DI\Form\Type\Attribute\ExternalKeyType; +use Combodo\iTop\DI\Form\Type\Attribute\LinkSetType; +use Combodo\iTop\DI\Services\ObjectService; +use Combodo\iTop\Service\Links\LinkSetModel; +use Exception; +use MetaModel; +use Symfony\Component\Form\Extension\Core\Type\CheckboxType; +use Symfony\Component\Form\Extension\Core\Type\ChoiceType; +use Symfony\Component\Form\Extension\Core\Type\DateTimeType; +use Symfony\Component\Form\Extension\Core\Type\DateType; +use Symfony\Component\Form\Extension\Core\Type\EmailType; +use Symfony\Component\Form\Extension\Core\Type\PasswordType; +use Symfony\Component\Form\Extension\Core\Type\TelType; +use Symfony\Component\Form\Extension\Core\Type\TextareaType; +use Symfony\Component\Form\Extension\Core\Type\TextType; + +class AttributeBuilder +{ + /** @var \Combodo\iTop\DI\Services\ObjectService object service */ + private ObjectService $oObjectService; + + /** + * Constructor. + * + * @param \Combodo\iTop\DI\Services\ObjectService $oObjectService + */ + public function __construct(ObjectService $oObjectService) + { + $this->oObjectService = $oObjectService; + } + + /** + * Map AttributeDefinition >> FormType + * + * @param string $sObjectClass + * @param string $sCode + * @param array|null $lockedAttributes + * + * @return array|null + * @throws \CoreException + */ + public function createAttribute(string $sObjectClass, string $sCode, ?array $lockedAttributes) : ?array + { + // load attribute definition + try { + $oAttributeDefinition = MetaModel::GetAttributeDef($sObjectClass, $sCode); + $sLabel = $oAttributeDefinition->GetLabel(); + } + catch(Exception $e){ + return null; + } + + // locked state + $bIsLocked = $lockedAttributes !== null && array_key_exists($sCode, $lockedAttributes); + + // create global form type (default as text) + $aFormType = [ + 'type' => TextType::class, + 'label' => $sLabel, + 'options' => [ + 'required' => !$oAttributeDefinition->IsNullAllowed(), + 'disabled' => !$oAttributeDefinition->IsWritable() || $bIsLocked, + 'attr' => [ + 'data-att-code' => $sCode + ], + 'row_attr' => [ + 'data-block' => 'container' + ], + 'label_attr' => [ + 'class' => $bIsLocked ? 'locked' : '' + ] + ] + ]; + + // register dependencies + if(count($oAttributeDefinition->GetPrerequisiteAttributes()) > 0){ + $dependencies = implode(' ', $oAttributeDefinition->GetPrerequisiteAttributes()); + $aFormType['options']['attr']['data-depends-on'] = $dependencies; + $aFormType['depends_on'] = $dependencies; + } + + // inject corresponding configuration + if($oAttributeDefinition instanceof AttributeExternalKey){ + $aFormType['type'] = ExternalKeyType::class; + $aFormType['options']['allow_target_creation'] = $oAttributeDefinition->AllowTargetCreation(); + $aFormType['options']['object_class'] = $oAttributeDefinition->GetTargetClass(); + $aFormType['options']['att_code'] = $oAttributeDefinition->GetCode(); + try{ + $oObjectsSet = MetaModel::GetAllowedValuesAsObjectSet($oAttributeDefinition->GetHostClass(), $oAttributeDefinition->GetCode(), []); + $aFormType['options']['choices'] = $this->oObjectService->ToChoices($oObjectsSet); + } + catch(Exception $e){ + + } + } + else if($oAttributeDefinition instanceof AttributeExternalField){ + $aFormType['type'] = ExternalFieldType::class; + $bIsExternalKey = $oAttributeDefinition->IsExternalKey(EXTKEY_ABSOLUTE); + if($bIsExternalKey){ + $aFormType['options']['is_external_key'] = true; + $aFormType['options']['object_class'] = $oAttributeDefinition->GetExtAttDef()->GetTargetClass(); + } + } + else if($oAttributeDefinition instanceof AttributeEmailAddress){ + $aFormType['type'] = EmailType::class; + } + else if($oAttributeDefinition instanceof AttributePassword){ + $aFormType['type'] = PasswordType::class; + } + else if($oAttributeDefinition instanceof AttributePhoneNumber){ + $aFormType['type'] = TelType::class; + $aFormType['options']['attr'] = [ + 'pattern' => '\+[0-9]{2}\s[0-9]\s[0-9]{2}\s[0-9]{2}\s[0-9]{2}\s[0-9]{2}', + 'placeholder' => '+-- - -- -- --' + ]; + } + else if($oAttributeDefinition instanceof AttributeBoolean){ + $aFormType['type'] = CheckboxType::class; + } + else if($oAttributeDefinition instanceof AttributeEnum){ + $aFormType['type'] = ChoiceType::class; + try{ + $aOptions = array_flip($oAttributeDefinition->GetAllowedValues()); + } + catch(Exception $e){ + $aOptions = []; + } + $aFormType['options']['choices'] = $aOptions; + } + else if($oAttributeDefinition instanceof AttributeImage){ + $aFormType['type'] = DocumentType::class; + } + else if($oAttributeDefinition instanceof AttributeLinkedSet){ + + $aFormType['type'] = LinkSetType::class; + $aFormType['options']['is_indirect'] = $oAttributeDefinition->IsIndirect(); + $aFormType['options']['is_abstract'] = MetaModel::IsAbstract(LinkSetModel::GetTargetClass($oAttributeDefinition)); + $aFormType['options']['target_class'] = LinkSetModel::GetTargetClass($oAttributeDefinition); + if($aFormType['options']['is_abstract']){ + $aFormType['options']['object_classes'] = MetaModel::EnumChildClasses(LinkSetModel::GetTargetClass($oAttributeDefinition)); + } + $aFormType['options']['entry_options'] = [ + 'object_class' => $oAttributeDefinition->GetLinkedClass(), + 'data_class' => $oAttributeDefinition->GetLinkedClass(), + 'is_link_set' => true, + 'ext_key_to_me' => $oAttributeDefinition->GetExtKeyToMe(), + 'z_list' => 'list', + 'attr' => [ + 'class' => 'z_list_list' + ] + ]; + $aFormType['options']['attr'] = [ + 'class' => 'link_set' + ]; + $aFormType['options']['label_attr'] = [ + 'class' => 'combodo-field-set-label' + ]; + } + else if($oAttributeDefinition instanceof AttributeText){ + $aFormType['type'] = TextareaType::class; + $aFormType['options']['attr']['rows'] = 10; + $aFormType['options']['attr']['data-widget'] = 'text_widget'; + } + else if($oAttributeDefinition instanceof AttributeDate){ + $aFormType['type'] = DateType::class; + $aFormType['options']['input'] = 'string'; + } + else if($oAttributeDefinition instanceof AttributeDateTime){ + $aFormType['type'] = DateTimeType::class; + $aFormType['options']['input'] = 'string'; + $aFormType['options']['widget'] = 'single_text'; + $aFormType['options']['with_seconds'] = true; + } + + return $aFormType; + } +} \ No newline at end of file diff --git a/sources/DI/Form/Builder/LayoutBuilder.php b/sources/DI/Form/Builder/LayoutBuilder.php new file mode 100644 index 000000000..6a9b98515 --- /dev/null +++ b/sources/DI/Form/Builder/LayoutBuilder.php @@ -0,0 +1,79 @@ +<?php + +namespace Combodo\iTop\DI\Form\Builder; + +use Combodo\iTop\DI\Form\Type\Layout\ColumnType; +use Combodo\iTop\DI\Form\Type\Layout\FieldSetType; +use Combodo\iTop\DI\Form\Type\Layout\RowType; +use Dict; + +class LayoutBuilder +{ + /** + * createRow. + * + * @param $key + * @param $columns + * + * @return array + */ + public function createRow($key, $columns) : array + { + return [ + 'type' => RowType::class, + 'options' => [ + 'items' => $columns, + 'label' => false, + 'row_attr' => [ + 'data-block' => 'container' + ] + ] + ]; + } + + /** + * createColumn. + * + * @param $key + * @param $item + * @param $dataClass + * + * @return array + */ + public function createColumn($key, $items) : array + { + return [ + 'type' => ColumnType::class, + 'options' => [ + 'items' => $items, + 'label' => false, + 'row_attr' => [ + 'data-block' => 'container' + ] + ] + ]; + } + + /** + * createFieldSet. + * + * @param $key + * @param $item + * @param $dataClass + * + * @return array + */ + public function createFieldSet($key, $items) : array + { + return [ + 'type' => FieldSetType::class, + 'options' => [ + 'items' => $items, + 'label' => Dict::S(substr($key, 9)), + 'row_attr' => [ + 'data-block' => 'container' + ] + ] + ]; + } +} \ No newline at end of file diff --git a/sources/DI/Form/Listener/IFormTypeOptionModifier.php b/sources/DI/Form/Listener/IFormTypeOptionModifier.php index f3a788be1..639007c5c 100644 --- a/sources/DI/Form/Listener/IFormTypeOptionModifier.php +++ b/sources/DI/Form/Listener/IFormTypeOptionModifier.php @@ -11,10 +11,12 @@ use DBObject; interface IFormTypeOptionModifier { /** - * @param array $aInitialOptions form type option + * Return new form type options for the provided DB object. + * + * @param array $aInitialOptions initial form type options * @param DBObject $oObject iTop DB object * - * @return array + * @return array new form type options */ public function getNewOptions(array $aInitialOptions, DBObject $oObject) : array; } \ No newline at end of file diff --git a/sources/DI/Form/Listener/ObjectFormListener.php b/sources/DI/Form/Listener/ObjectFormListener.php index ede3c68bd..90ff17433 100644 --- a/sources/DI/Form/Listener/ObjectFormListener.php +++ b/sources/DI/Form/Listener/ObjectFormListener.php @@ -36,7 +36,7 @@ class ObjectFormListener implements EventSubscriberInterface * When form is first initialized, it hasn't data set yet. * So we listen for form PRE_SET_DATA event to modify form with data. * - * @param FormEvent $oEvent + * @param FormEvent $oEvent form event * * @suppress-unused-warning */ @@ -50,7 +50,7 @@ class ObjectFormListener implements EventSubscriberInterface * Previous preSetData handling doesn't know about form submission data. * So, to allow us to use our DBObject for filters we need to update it before. * - * @param FormEvent $oEvent + * @param FormEvent $oEvent form event * * @suppress-unused-warning */ @@ -71,6 +71,7 @@ class ObjectFormListener implements EventSubscriberInterface * * We need to reset fields to take into account object values. * The form fields options can't be changed at this time. + * All fields are reset to keep fields order. * * @param FormInterface $oForm * @param FormEvent $oEvent @@ -113,6 +114,8 @@ class ObjectFormListener implements EventSubscriberInterface /** * Handle posted data. + * The data are the view data. We skipped data transformation !! + * @todo handle data transformation * * @param FormInterface $form * @param DBObject $oDBObject diff --git a/sources/DI/Form/Transformer/DocumentTransformer.php b/sources/DI/Form/Transformer/DocumentTransformer.php new file mode 100644 index 000000000..9e7bbf699 --- /dev/null +++ b/sources/DI/Form/Transformer/DocumentTransformer.php @@ -0,0 +1,31 @@ +<?php + +namespace Combodo\iTop\DI\Form\Transformer; + +use ormDocument; +use Symfony\Component\Form\DataTransformerInterface; + +/** + * Perform transformation between ormDocument and UploadedFile. + */ +class DocumentTransformer implements DataTransformerInterface +{ + + /** @inheritdoc */ + public function transform($value) + { + + return null; + } + + /** @inheritdoc */ + public function reverseTransform($value) + { + if($value === null){ + return null; + } + + $doc_content = file_get_contents($value->getRealPath()); + return new ormDocument($doc_content, $value->getClientMimeType(), $value->getRealPath()); + } +} diff --git a/sources/DI/Form/Transformer/ExternalKeyTransformer.php b/sources/DI/Form/Transformer/ExternalKeyTransformer.php new file mode 100644 index 000000000..8a0dc232b --- /dev/null +++ b/sources/DI/Form/Transformer/ExternalKeyTransformer.php @@ -0,0 +1,42 @@ +<?php + +namespace Combodo\iTop\DI\Form\Transformer; + +use Exception; +use MetaModel; +use Symfony\Component\Form\DataTransformerInterface; + +/** + * Transform external key ref to external key name representation. + */ +class ExternalKeyTransformer implements DataTransformerInterface +{ + + /** @var string $sObjectClass */ + private string $sObjectClass; + + /** + * @param string $sObjectClass + */ + public function __construct(string $sObjectClass) + { + $this->sObjectClass = $sObjectClass; + } + + /** @inheritdoc */ + public function transform($value) + { + try{ + return MetaModel::GetObject($this->sObjectClass, $value)->GetName(); + } + catch(Exception $e){ + return null; + } + } + + /** @inheritdoc */ + public function reverseTransform($value) + { + return $value; + } +} diff --git a/sources/DI/Form/Type/Simple/DocumentType.php b/sources/DI/Form/Type/Attribute/DocumentType.php similarity index 60% rename from sources/DI/Form/Type/Simple/DocumentType.php rename to sources/DI/Form/Type/Attribute/DocumentType.php index 8d0cbf4c9..09d4ec05e 100644 --- a/sources/DI/Form/Type/Simple/DocumentType.php +++ b/sources/DI/Form/Type/Attribute/DocumentType.php @@ -1,15 +1,14 @@ <?php -namespace Combodo\iTop\DI\Form\Type\Simple; +namespace Combodo\iTop\DI\Form\Type\Attribute; +use Combodo\iTop\DI\Form\Transformer\DocumentTransformer; use ormDocument; use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\CallbackTransformer; use Symfony\Component\Form\Extension\Core\Type\FileType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; -use Symfony\Component\HttpFoundation\File\UploadedFile; /** * Example of type with data transformer. @@ -23,23 +22,7 @@ class DocumentType extends AbstractType { parent::buildForm($builder, $options); - $builder->addModelTransformer(new CallbackTransformer( - - // transform - function (?ormDocument $oDocument){ - return null; - }, - - // reverse - function (?UploadedFile $oFileData){ - if($oFileData === null){ - return null; - } - - $doc_content = file_get_contents($oFileData->getRealPath()); - return new ormDocument($doc_content, $oFileData->getClientMimeType(), $oFileData->getRealPath()); - }, - )); + $builder->addModelTransformer(new DocumentTransformer()); } /** @inheritdoc */ @@ -47,7 +30,7 @@ class DocumentType extends AbstractType { /** @var ormDocument $oOrmDocument */ $oOrmDocument = $form->getData(); - $view->vars['data'] = 'data:image/' . $oOrmDocument->GetMimeType() . ';base64,' . base64_encode($oOrmDocument->GetData());; + $view->vars['data'] = 'data:image/' . $oOrmDocument->GetMimeType() . ';base64,' . base64_encode($oOrmDocument->GetData()); $view->vars['mime_type'] = $oOrmDocument->GetMimeType(); $view->vars['filename'] = $oOrmDocument->GetFileName(); } diff --git a/sources/DI/Form/Type/Attribute/ExternalFieldType.php b/sources/DI/Form/Type/Attribute/ExternalFieldType.php new file mode 100644 index 000000000..d61477376 --- /dev/null +++ b/sources/DI/Form/Type/Attribute/ExternalFieldType.php @@ -0,0 +1,38 @@ +<?php + +namespace Combodo\iTop\DI\Form\Type\Attribute; + +use Combodo\iTop\DI\Form\Transformer\ExternalKeyTransformer; +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Extension\Core\Type\TextType; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\OptionsResolver\OptionsResolver; + +class ExternalFieldType extends AbstractType +{ + + /** @inheritdoc */ + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'object_class' => null, + 'is_external_key' => false, + ]); + + } + /** @inheritdoc */ + public function buildForm(FormBuilderInterface $builder, array $options) + { + if($options['is_external_key']){ + $builder->addViewTransformer(new ExternalKeyTransformer($options['object_class'])); + } + + } + + /** @inheritdoc */ + public function getParent(): string + { + return TextType::class; + } + +} diff --git a/sources/DI/Form/Type/Simple/ExternalKeyType.php b/sources/DI/Form/Type/Attribute/ExternalKeyType.php similarity index 86% rename from sources/DI/Form/Type/Simple/ExternalKeyType.php rename to sources/DI/Form/Type/Attribute/ExternalKeyType.php index bf8d50b31..a5b44b653 100644 --- a/sources/DI/Form/Type/Simple/ExternalKeyType.php +++ b/sources/DI/Form/Type/Attribute/ExternalKeyType.php @@ -1,6 +1,6 @@ <?php -namespace Combodo\iTop\DI\Form\Type\Simple; +namespace Combodo\iTop\DI\Form\Type\Attribute; use Combodo\iTop\DI\Form\Listener\IFormTypeOptionModifier; use Combodo\iTop\DI\Services\ObjectService; @@ -32,14 +32,10 @@ class ExternalKeyType extends AbstractType implements IFormTypeOptionModifier public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ - 'display_style' => 'list', 'allow_target_creation' => false, 'object_class' => null, 'att_code' => null, ]); - - $resolver->setAllowedTypes('display_style', 'string'); - $resolver->setAllowedValues('display_style', ['radio', 'radio_horizontal', 'radio_vertical', 'select', 'list']); } /** @inheritdoc */ @@ -58,7 +54,8 @@ class ExternalKeyType extends AbstractType implements IFormTypeOptionModifier public function getNewOptions(array $aInitialOptions, DBObject $oObject) : array { try{ - $oObjectsSet = MetaModel::GetAllowedValuesAsObjectSet(get_class($oObject), $aInitialOptions['att_code'], ['this' => $oObject]); +// $iVal = $oObject->Get($aInitialOptions['att_code']); // because we can't list all items du to performance, we want to force current value to be present, even if it's not part of the result + $oObjectsSet = MetaModel::GetAllowedValuesAsObjectSet(get_class($oObject), $aInitialOptions['att_code'], ['this' => $oObject]/*, null, $iVal*/); $aInitialOptions['choices'] = $this->oObjectService->ToChoices($oObjectsSet); } catch(Exception $e){ diff --git a/sources/DI/Form/Type/Simple/LinkSetType.php b/sources/DI/Form/Type/Attribute/LinkSetType.php similarity index 66% rename from sources/DI/Form/Type/Simple/LinkSetType.php rename to sources/DI/Form/Type/Attribute/LinkSetType.php index 12f2bbd5e..f3658bca9 100644 --- a/sources/DI/Form/Type/Simple/LinkSetType.php +++ b/sources/DI/Form/Type/Attribute/LinkSetType.php @@ -1,10 +1,9 @@ <?php -namespace Combodo\iTop\DI\Form\Type\Simple; +namespace Combodo\iTop\DI\Form\Type\Attribute; -use Combodo\iTop\DI\Form\Type\ObjectType; +use Combodo\iTop\DI\Form\Type\Compound\ObjectType; use Combodo\iTop\DI\Services\ObjectPresentationService; -use Combodo\iTop\DI\Services\ObjectService; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\CollectionType; use Symfony\Component\Form\FormInterface; @@ -35,9 +34,11 @@ class LinkSetType extends AbstractType { $resolver->setDefaults([ 'entry_type' => ObjectType::class, - 'entry_options' => [ - 'object_class' => null - ], + 'is_indirect' => false, + 'is_abstract' => false, + 'object_classes' => null, + 'target_class' => null, + 'entry_options' => null, 'allow_add' => true, 'allow_delete' => true, ]); @@ -53,6 +54,12 @@ class LinkSetType extends AbstractType /** @inheritdoc */ public function buildView(FormView $view, FormInterface $form, array $options): void { - $view->vars['labels'] = $this->oObjectService->getFormPresentationLabels($options['entry_options']['object_class'], 'list', $options['entry_options']['ext_key_to_me']);; + $view->vars['labels'] = $this->oObjectService->getFormPresentationLabels($options['entry_options']['object_class'], 'list', $options['entry_options']['ext_key_to_me']); + $view->vars['object_class'] = $options['entry_options']['object_class']; + $view->vars['ext_key_to_me'] = $options['entry_options']['ext_key_to_me']; + $view->vars['target_class'] = $options['target_class']; + $view->vars['is_indirect'] = $options['is_indirect']; + $view->vars['is_abstract'] = $options['is_abstract']; + $view->vars['object_classes'] = $options['object_classes']; } } diff --git a/sources/DI/Form/Type/ConfigurationType.php b/sources/DI/Form/Type/Compound/ConfigurationType.php similarity index 85% rename from sources/DI/Form/Type/ConfigurationType.php rename to sources/DI/Form/Type/Compound/ConfigurationType.php index 7c1c4d98b..4459739f3 100644 --- a/sources/DI/Form/Type/ConfigurationType.php +++ b/sources/DI/Form/Type/Compound/ConfigurationType.php @@ -1,6 +1,6 @@ <?php -namespace Combodo\iTop\DI\Form\Type; +namespace Combodo\iTop\DI\Form\Type\Compound; use Combodo\iTop\DI\Form\Type\Layout\FieldSetType; use MetaModel; @@ -95,13 +95,13 @@ class ConfigurationType extends AbstractType /** * Handle category. * - * @param $aCategories - * @param $aSettings - * @param $builder + * @param array $aCategories + * @param array $aSettings + * @param FormBuilderInterface $builder * * @return void */ - private function handleCategories($aCategories, $aSettings, $builder) + private function handleCategories(array $aCategories, array $aSettings, FormBuilderInterface $builder) { // iterate throw categories... foreach ($aCategories as $sKey => $sValue) { @@ -145,12 +145,12 @@ class ConfigurationType extends AbstractType * Handle array of entries. * * @param array $aEntries - * @param $aSettings - * @param $builder + * @param array $aSettings + * @param FormBuilderInterface $builder * * @return void */ - private function handleEntries(array $aEntries, $aSettings, $builder) + private function handleEntries(array $aEntries, array $aSettings, FormBuilderInterface $builder) { // iterate throw entries... foreach ($aEntries as $sKey => $aValue){ @@ -168,12 +168,12 @@ class ConfigurationType extends AbstractType /** * Return form type depending on settings definition. * - * @param $aSettings - * @param $sKey + * @param array $aSettings + * @param string $sKey * * @return string */ - private function getFormType($aSettings, $sKey) : string{ + private function getFormType(array $aSettings, string $sKey) : string{ if(!array_key_exists($sKey, $aSettings)){ return TextType::class; @@ -190,13 +190,16 @@ class ConfigurationType extends AbstractType } /** - * @param $aSettings - * @param $sKey - * @param $sTopic + * Get parameter setting topic. * - * @return string + * @param array $aSettings + * @param string $sKey + * @param string $sTopic + * + * @return string|null */ - private function getTopic($aSettings, $sKey, $sTopic) : ?string{ + private function getTopic(array $aSettings, string $sKey, string $sTopic) : ?string + { if(!array_key_exists($sKey, $aSettings)){ return null; diff --git a/sources/DI/Form/Type/ObjectSingleAttributeType.php b/sources/DI/Form/Type/Compound/ObjectSingleAttributeType.php similarity index 66% rename from sources/DI/Form/Type/ObjectSingleAttributeType.php rename to sources/DI/Form/Type/Compound/ObjectSingleAttributeType.php index 7e6344704..4199e368d 100644 --- a/sources/DI/Form/Type/ObjectSingleAttributeType.php +++ b/sources/DI/Form/Type/Compound/ObjectSingleAttributeType.php @@ -1,9 +1,9 @@ <?php -namespace Combodo\iTop\DI\Form\Type; +namespace Combodo\iTop\DI\Form\Type\Compound; +use Combodo\iTop\DI\Form\Builder\AttributeBuilder; use Combodo\iTop\DI\Form\Listener\ObjectFormListener; -use Combodo\iTop\DI\Services\ObjectPresentationService; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -17,19 +17,19 @@ class ObjectSingleAttributeType extends AbstractType /** @var ObjectFormListener object form modifier */ private ObjectFormListener $oObjectFormModifier; - /** @var ObjectPresentationService object presentation service */ - private ObjectPresentationService $objectPresentationService; + /** @var AttributeBuilder attribute builder */ + private AttributeBuilder $oAttributeBuilder; /** * Constructor. * * @param ObjectFormListener $oObjectFormModifier - * @param ObjectPresentationService $objectPresentationService + * @param AttributeBuilder $oAttributeBuilder */ - public function __construct(ObjectFormListener $oObjectFormModifier, ObjectPresentationService $objectPresentationService) + public function __construct(ObjectFormListener $oObjectFormModifier, AttributeBuilder $oAttributeBuilder) { $this->oObjectFormModifier = $oObjectFormModifier; - $this->objectPresentationService = $objectPresentationService; + $this->oAttributeBuilder = $oAttributeBuilder; } /** @inheritdoc */ @@ -41,11 +41,13 @@ class ObjectSingleAttributeType extends AbstractType ]); } - /** @inheritdoc */ + /** @inheritdoc + * @throws \CoreException + */ public function buildForm(FormBuilderInterface $builder, array $options): void { // build form from options - $sFormType = $this->objectPresentationService->GetAttributeFormType($options['object_class'], $options['att_code']); + $sFormType = $this->oAttributeBuilder->createAttribute($options['object_class'], $options['att_code']); // add form field $builder->add($options['att_code'], $sFormType['type'], $sFormType['options']); diff --git a/sources/DI/Form/Type/ObjectType.php b/sources/DI/Form/Type/Compound/ObjectType.php similarity index 63% rename from sources/DI/Form/Type/ObjectType.php rename to sources/DI/Form/Type/Compound/ObjectType.php index fdff793ac..142aa3aff 100644 --- a/sources/DI/Form/Type/ObjectType.php +++ b/sources/DI/Form/Type/Compound/ObjectType.php @@ -1,8 +1,10 @@ <?php -namespace Combodo\iTop\DI\Form\Type; +namespace Combodo\iTop\DI\Form\Type\Compound; use cmdbAbstractObject; +use Combodo\iTop\DI\Form\Builder\AttributeBuilder; +use Combodo\iTop\DI\Form\Builder\LayoutBuilder; use Combodo\iTop\DI\Form\Listener\ObjectFormListener; use Combodo\iTop\DI\Services\ObjectPresentationService; use Symfony\Component\Form\AbstractType; @@ -25,16 +27,26 @@ class ObjectType extends AbstractType /** @var ObjectPresentationService object presentation service */ private ObjectPresentationService $objectPresentationService; + /** @var \Combodo\iTop\DI\Form\Builder\AttributeBuilder attribute builder */ + private AttributeBuilder $oAttributeBuilder; + + /** @var \Combodo\iTop\DI\Form\Builder\LayoutBuilder layout builder */ + private LayoutBuilder $oLayoutBuilder; + /** * Constructor. * * @param ObjectFormListener $oObjectFormModifier * @param ObjectPresentationService $objectPresentationService + * @param \Combodo\iTop\DI\Form\Builder\AttributeBuilder $oAttributeBuilder + * @param \Combodo\iTop\DI\Form\Builder\LayoutBuilder $oLayoutBuilder */ - public function __construct(ObjectFormListener $oObjectFormModifier, ObjectPresentationService $objectPresentationService) + public function __construct(ObjectFormListener $oObjectFormModifier, ObjectPresentationService $objectPresentationService, AttributeBuilder $oAttributeBuilder, LayoutBuilder $oLayoutBuilder) { $this->oObjectFormModifier = $oObjectFormModifier; $this->objectPresentationService = $objectPresentationService; + $this->oAttributeBuilder = $oAttributeBuilder; + $this->oLayoutBuilder = $oLayoutBuilder; } /** @inheritdoc */ @@ -48,24 +60,29 @@ class ObjectType extends AbstractType 'class' => 'z_list_details' ], 'object_class' => null, + 'locked_attributes' => null, 'data_class' => cmdbAbstractObject::class, ]); } - /** - * @inheritdoc - * @throws \Exception - */ + /** @inheritdoc */ public function buildForm(FormBuilderInterface $builder, array $options): void { // build form from presentation - $this->objectPresentationService->buildFormFromPresentation($options['object_class'], $options['z_list'], $options['is_link_set'], $options['ext_key_to_me'], $builder); + $this->objectPresentationService->buildFormFromPresentation( + $options['object_class'], + $options['z_list'], + $options['is_link_set'], + $options['ext_key_to_me'], + $options['locked_attributes'], + $builder); // dynamic form handling $builder->addEventSubscriber($this->oObjectFormModifier); } + /** @inheritdoc */ public function buildView(FormView $view, FormInterface $form, array $options) { parent::buildView($view, $form, $options); diff --git a/sources/DI/ITopKernel.php b/sources/DI/ITopKernel.php index 4a0cc1b99..8a7d7656c 100644 --- a/sources/DI/ITopKernel.php +++ b/sources/DI/ITopKernel.php @@ -40,6 +40,8 @@ class ITopKernel extends BaseKernel * @param \Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator $container * * @return void + * + * @suppress-unused-warning */ protected function configureContainer(ContainerConfigurator $container): void { diff --git a/sources/DI/Services/ObjectPresentationService.php b/sources/DI/Services/ObjectPresentationService.php index d0089c23d..65868f62f 100644 --- a/sources/DI/Services/ObjectPresentationService.php +++ b/sources/DI/Services/ObjectPresentationService.php @@ -2,35 +2,10 @@ namespace Combodo\iTop\DI\Services; -use AttributeBoolean; -use AttributeDate; -use AttributeDateTime; -use AttributeEmailAddress; -use AttributeEnum; -use AttributeExternalKey; -use AttributeImage; -use AttributeLinkedSet; -use AttributePassword; -use AttributePhoneNumber; -use AttributeText; -use Combodo\iTop\DI\Form\Type\Layout\ColumnType; -use Combodo\iTop\DI\Form\Type\Simple\ExternalKeyType; -use Combodo\iTop\DI\Form\Type\Layout\FieldSetType; -use Combodo\iTop\DI\Form\Type\Layout\RowType; -use Combodo\iTop\DI\Form\Type\Simple\DocumentType; -use Combodo\iTop\DI\Form\Type\Simple\LinkSetType; +use Combodo\iTop\DI\Form\Builder\AttributeBuilder; +use Combodo\iTop\DI\Form\Builder\LayoutBuilder; use Dict; -use Exception; use MetaModel; -use Symfony\Component\Form\Extension\Core\Type\CheckboxType; -use Symfony\Component\Form\Extension\Core\Type\ChoiceType; -use Symfony\Component\Form\Extension\Core\Type\DateTimeType; -use Symfony\Component\Form\Extension\Core\Type\DateType; -use Symfony\Component\Form\Extension\Core\Type\EmailType; -use Symfony\Component\Form\Extension\Core\Type\PasswordType; -use Symfony\Component\Form\Extension\Core\Type\TelType; -use Symfony\Component\Form\Extension\Core\Type\TextareaType; -use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; /** @@ -39,54 +14,71 @@ use Symfony\Component\Form\FormBuilderInterface; */ class ObjectPresentationService { + /** @var \Combodo\iTop\DI\Form\Builder\LayoutBuilder $oLayoutBuilder */ + private LayoutBuilder $oLayoutBuilder; + /** @var \Combodo\iTop\DI\Form\Builder\AttributeBuilder $oAttributeBuilder */ + private AttributeBuilder $oAttributeBuilder; + + /** + * @param \Combodo\iTop\DI\Form\Builder\LayoutBuilder $oLayoutBuilder + * @param \Combodo\iTop\DI\Form\Builder\AttributeBuilder $oAttributeBuilder + */ + public function __construct(LayoutBuilder $oLayoutBuilder, AttributeBuilder $oAttributeBuilder) + { + $this->oLayoutBuilder = $oLayoutBuilder; + $this->oAttributeBuilder = $oAttributeBuilder; + } /** * buildFormFromPresentation. * - * @param $class - * @param $zList - * @param $isLinkSet - * @param $sExtKeyToMe + * @param string $class + * @param string $sZList + * @param bool $isLinkSet + * @param string|null $sExtKeyToMe + * @param array|null $lockedAttributes * @param \Symfony\Component\Form\FormBuilderInterface $builder * * @return void + * @throws \Exception */ - public function buildFormFromPresentation($class, $zList, $isLinkSet, $sExtKeyToMe, FormBuilderInterface $builder) + public function buildFormFromPresentation(string $class, string $sZList, bool $isLinkSet, ?string $sExtKeyToMe, ?array $lockedAttributes, FormBuilderInterface $builder) { // retrieve presentation - $aPresentation = MetaModel::GetZListItems($class, $zList); + $aPresentation = MetaModel::GetZListItems($class, $sZList); + // filter zList for links set if($isLinkSet){ - $aPresentation = $this->filterLinkSetpresentation($aPresentation, $class, $sExtKeyToMe); + $aPresentation = $this->filterLinkSetPresentation($aPresentation, $class, $sExtKeyToMe); } - $level = $this->handleLevel($aPresentation, $class); - + // handle level + $level = $this->handleLevel($aPresentation, $class, $lockedAttributes); foreach ($level as $key => $value) { - $value['options']['attr']['data-att-code'] = $key; $builder->add($key, $value['type'], $value['options']); } } /** - * filterLinkSetpresentation. + * filterLinkSetPresentation. * - * @param $aPresentation - * @param $class - * @param $sExtKeyToMe + * @param array $aPresentation + * @param string $sClass + * @param string|null $sExtKeyToMe * * @return array * @throws \Exception */ - private function filterLinkSetpresentation($aPresentation, $class, $sExtKeyToMe){ + private function filterLinkSetPresentation(array $aPresentation, string $sClass, ?string $sExtKeyToMe) : array + { $aNewPresentation = []; foreach($aPresentation as $sLinkedAttCode) { if ($sLinkedAttCode != $sExtKeyToMe) { - $oAttDef = MetaModel::GetAttributeDef($class, $sLinkedAttCode); + $oAttDef = MetaModel::GetAttributeDef($sClass, $sLinkedAttCode); if ((!$oAttDef->IsExternalField() || ($oAttDef->GetKeyAttCode() != $sExtKeyToMe)) && (!$oAttDef->IsLinkSet()) ) @@ -101,20 +93,34 @@ class ObjectPresentationService return $aNewPresentation; } - - public function getFormPresentationLabels($class, $zList, $sExtKeyToMe) + /** + * @param $class + * @param $zList + * @param $sExtKeyToMe + * + * @return array + * @throws \Exception + */ + public function getFormPresentationLabels($class, $zList, $sExtKeyToMe) : array { // retrieve presentation $aPresentation = MetaModel::GetZListItems($class, $zList); $aPresentation = $this->filterLinkSetpresentation($aPresentation, $class, $sExtKeyToMe); - $level = $this->handleLevel($aPresentation, $class); - $labels = []; + $level = $this->handleLevel($aPresentation, $class, null, null); + $aLabels = []; foreach ($level as $key => $value) { $value['options']['attr']['data-att-code'] = $key; - $labels[] = $key; + + $sKey = "Class:$class/Attribute:$key"; + if(Dict::Exists($sKey)){ + $aLabels[] = Dict::S($sKey); + } + else{ + $aLabels[] = $key; + } } - return $labels; + return $aLabels; } @@ -122,26 +128,30 @@ class ObjectPresentationService * handleLevel. * * @param array $aElement - * @param $dataClass + * @param string $sDataClass + * @param array|null $lockedAttributes * * @return array + * @throws \CoreException */ - private function handleLevel(array $aElement, $dataClass) : array + private function handleLevel(array $aElement, string $sDataClass, ?array $lockedAttributes) : array { $aChildren = []; - $aRowCol = []; + $aRowCols = []; // iterate trow level entries... foreach ($aElement as $key => $item){ // column if(str_starts_with($key, 'col')){ - $aRowCol[$key] = $this->createColumn($key, $item, $dataClass); - $this->handleDynamics($key, $aRowCol[$key]); + $aItems = $this->handleLevel($item, $sDataClass, $lockedAttributes); + $aRowCols[$key] = $this->oLayoutBuilder->createColumn($key, $aItems); + $this->handleDynamics($key, $aRowCols[$key]); } // field set else if(str_starts_with($key, 'fieldset')){ - $aChildren[$key] =$this->createFieldSet($key, $item, $dataClass); + $aItems = $this->handleLevel($item, $sDataClass, $lockedAttributes); + $aChildren[$key] = $this->oLayoutBuilder->createFieldSet($key, $aItems); $this->handleDynamics($key, $aChildren[$key]); } // logs @@ -150,7 +160,7 @@ class ObjectPresentationService } // others else{ - $sFormType = $this->GetAttributeFormType($dataClass, $item); + $sFormType = $this->oAttributeBuilder->createAttribute($sDataClass, $item, $lockedAttributes); if($sFormType !== null){ $sFormType['options']['attr']['data-att-code'] = $item; $aChildren[$item] = $sFormType; @@ -159,8 +169,8 @@ class ObjectPresentationService } } - if(count($aRowCol)){ - $aChildren['row'] = $this->createRow('row', $aRowCol, $dataClass); + if(count($aRowCols)){ + $aChildren['row'] = $this->oLayoutBuilder->createRow('row', $aRowCols); } return $aChildren; @@ -201,207 +211,4 @@ class ObjectPresentationService } } - /** - * createRow. - * - * @param $key - * @param $columns - * @param $dataClass - * - * @return array - */ - private function createRow($key, $columns, $dataClass) : array - { - return [ - 'type' => RowType::class, - 'options' => [ - 'items' => $columns, - 'label' => false, - 'row_attr' => [ - 'data-block' => 'container' - ] - ] - ]; - } - - /** - * createColumn. - * - * @param $key - * @param $item - * @param $dataClass - * - * @return array - */ - private function createColumn($key, $item, $dataClass) : array - { - return [ - 'type' => ColumnType::class, - 'options' => [ - 'items' => $this->handleLevel($item, $dataClass), - 'label' => false, - 'row_attr' => [ - 'data-block' => 'container' - ] - ] - ]; - } - - /** - * createFieldSet. - * - * @param $key - * @param $item - * @param $dataClass - * - * @return array - */ - private function createFieldSet($key, $item, $dataClass) : array - { - return [ - 'type' => FieldSetType::class, - 'options' => [ - 'items' => $this->handleLevel($item, $dataClass), - 'label' => Dict::S(substr($key, 9)), - 'row_attr' => [ - 'data-block' => 'container' - ] - ] - ]; - } - - /** - * Map AttributeDefinition >> FormType - * - * @param string $sObjectClass - * @param string $sCode - * - * @return array|null - */ - public function GetAttributeFormType(string $sObjectClass, string $sCode) : ?array - { - // load attribute definition - try { - $oAttributeDefinition = MetaModel::GetAttributeDef($sObjectClass, $sCode); - $sLabel = $oAttributeDefinition->GetLabel(); - } - catch(Exception $e){ - return null; - } - - // create global form type - $aFormType = [ - 'type' => TextType::class, - 'label' => $sLabel, - 'options' => [ - 'required' => !$oAttributeDefinition->IsNullAllowed(), - 'disabled' => !$oAttributeDefinition->IsWritable(), - ] - ]; - - // inject corresponding configuration - if($oAttributeDefinition instanceof AttributeExternalKey){ - $aFormType['type'] = ExternalKeyType::class; - $aFormType['options']['display_style'] = 'list'; - $aFormType['options']['allow_target_creation'] = true; - $aFormType['options']['object_class'] = $oAttributeDefinition->GetTargetClass(); - $aFormType['options']['att_code'] = $oAttributeDefinition->GetCode(); - - try{ - $oObjectsSet = MetaModel::GetAllowedValuesAsObjectSet($oAttributeDefinition->GetHostClass(), $oAttributeDefinition->GetCode(), []); - $aFormType['options']['choices'] = $this->ToChoices($oObjectsSet); - } - catch(Exception $e){ - - } - - } - else if($oAttributeDefinition instanceof AttributeEmailAddress){ - $aFormType['type'] = EmailType::class; - } - else if($oAttributeDefinition instanceof AttributePassword){ - $aFormType['type'] = PasswordType::class; - } - else if($oAttributeDefinition instanceof AttributePhoneNumber){ - $aFormType['type'] = TelType::class; - $aFormType['options']['attr'] = [ - 'pattern' => '\+[0-9]{2}\s[0-9]\s[0-9]{2}\s[0-9]{2}\s[0-9]{2}\s[0-9]{2}', - 'placeholder' => '+-- - -- -- --' - ]; - } - else if($oAttributeDefinition instanceof AttributeBoolean){ - $aFormType['type'] = CheckboxType::class; - } - else if($oAttributeDefinition instanceof AttributeEnum){ - $aFormType['type'] = ChoiceType::class; - try{ - $aOptions = array_flip($oAttributeDefinition->GetAllowedValues()); - } - catch(Exception $e){ - $aOptions = []; - } - $aFormType['options']['choices'] = $aOptions; - } - else if($oAttributeDefinition instanceof AttributeImage){ - $aFormType['type'] = DocumentType::class; - } - else if($oAttributeDefinition instanceof AttributeLinkedSet){ - $aFormType['type'] = LinkSetType::class; - $aFormType['options']['entry_options'] = [ - 'object_class' => $oAttributeDefinition->GetLinkedClass(), - 'data_class' => $oAttributeDefinition->GetLinkedClass(), - 'is_link_set' => true, - 'ext_key_to_me' => $oAttributeDefinition->GetExtKeyToMe(), - 'z_list' => 'list', - 'attr' => [ - 'class' => 'z_list_list' - ] - ]; - $aFormType['options']['attr'] = [ - 'class' => 'link_set' - ]; - $aFormType['options']['label_attr'] = [ - 'class' => 'combodo-field-set-label' - ]; - } - else if($oAttributeDefinition instanceof AttributeText){ - $aFormType['type'] = TextareaType::class; - $aFormType['options']['attr']['rows'] = 10; - $aFormType['options']['attr']['data-widget'] = 'text_widget'; - } - else if($oAttributeDefinition instanceof AttributeDate){ - $aFormType['type'] = DateType::class; - $aFormType['options']['input'] = 'string'; - } - else if($oAttributeDefinition instanceof AttributeDateTime){ - $aFormType['type'] = DateTimeType::class; - $aFormType['options']['input'] = 'string'; - $aFormType['options']['widget'] = 'single_text'; - $aFormType['options']['with_seconds'] = true; - } - - if(count($oAttributeDefinition->GetPrerequisiteAttributes()) > 0){ - $dependencies = implode(' ', $oAttributeDefinition->GetPrerequisiteAttributes()); - $aFormType['options']['attr']['data-depends-on'] = $dependencies; - $aFormType['depends_on'] = $dependencies; - } - - $aFormType['options']['row_attr']['data-block'] = 'container'; - - return $aFormType; - } - - public function ToChoices($oObjectsSet) : array - { - $aChoices = []; - - $i = 0; - - while ($i < 100 && $oObj = $oObjectsSet->Fetch()) { - $aChoices[$oObj->GetName()] = $oObj->GetKey(); - $i++; - } - - return $aChoices; - } } \ No newline at end of file diff --git a/sources/DI/Services/ObjectService.php b/sources/DI/Services/ObjectService.php index 29fface07..ff0084e01 100644 --- a/sources/DI/Services/ObjectService.php +++ b/sources/DI/Services/ObjectService.php @@ -3,7 +3,10 @@ namespace Combodo\iTop\DI\Services; use AttributeLinkedSet; +use Combodo\iTop\Core\MetaModel\FriendlyNameType; +use Combodo\iTop\Service\Base\ObjectRepository; use DBObject; +use DBObjectSet; use MetaModel; use ormLinkSet; @@ -27,20 +30,52 @@ class ObjectService $this->sDbName = $sDbName; } + /** + * @param string $sClass + * @param $sRef + * + * @return DBObject + * @throws \ArchivedObjectException + * @throws \CoreException + */ + public function getObject(string $sClass, $sRef) : DBObject + { + if($sRef !== 0){ + return MetaModel::GetObject($sClass, $sRef); + } + else{ + return MetaModel::NewObject($sClass); + } + } + /** * Convert object set to array of choices. * - * @param $oObjectsSet + * @param DBObjectSet $oObjectsSet * * @return array + * @throws \CoreException + * @throws \CoreUnexpectedValue + * @throws \DictExceptionMissingString + * @throws \MySQLException */ - public function ToChoices($oObjectsSet) : array + public function ToChoices(DBObjectSet $oObjectsSet) : array { $aChoices = []; - $i = 0; + // Retrieve friendly name complementary specification + $aComplementAttributeSpec = MetaModel::GetNameSpec($oObjectsSet->GetClass(), FriendlyNameType::COMPLEMENTARY); - while ($i < 100 && $oObj = $oObjectsSet->Fetch()) { + // Retrieve image attribute code + $sObjectImageAttCode = MetaModel::GetImageAttributeCode($oObjectsSet->GetClass()); + + // Prepare fields to load + $aDefaultFieldsToLoad = ObjectRepository::GetDefaultFieldsToLoad($aComplementAttributeSpec, $sObjectImageAttCode); + + $oObjectsSet->OptimizeColumnLoad([$oObjectsSet->GetClassAlias() => $aDefaultFieldsToLoad]); + + $i = 0; + while ($i < 30 && $oObj = $oObjectsSet->Fetch()) { $aChoices[$oObj->GetName()] = $oObj->GetKey(); $i++; } @@ -64,12 +99,27 @@ class ObjectService return $this->sDbName; } + /** + * @param \DBObject $object + * + * @return void + * @throws \ArchivedObjectException + * @throws \CoreCannotSaveObjectException + * @throws \CoreException + * @throws \CoreUnexpectedValue + * @throws \CoreWarning + * @throws \DeleteException + * @throws \MySQLException + * @throws \MySQLHasGoneAwayException + * @throws \OQLException + * @throws \Exception + */ public function handleLinkSetDB(DBObject $object){ foreach($object->GetValues() as $key => $value){ if($value instanceof ormLinkSet){ - /** @var AttributeLinkedSet $a */ - $a = MetaModel::GetAttributeDef(get_class($object), $key); + /** @var AttributeLinkedSet $a */ + $a = MetaModel::GetAttributeDef(get_class($object), $key); /** @var DBObject $link */ foreach($value->ListModifiedLinks() as $link){ @@ -78,7 +128,6 @@ class ObjectService } } - /** @var DBObject $link */ foreach($value->ListModifiedLinks() as $link){ if($link->IsNew()){ diff --git a/sources/DI/Services/TwigHelper.php b/sources/DI/Services/TwigHelper.php index 7a275ae14..4eb9e16ea 100644 --- a/sources/DI/Services/TwigHelper.php +++ b/sources/DI/Services/TwigHelper.php @@ -2,6 +2,7 @@ namespace Combodo\iTop\DI\Services; +use MetaModel; use Twig\Extension\AbstractExtension; use Twig\TwigFunction; @@ -11,7 +12,8 @@ use Twig\TwigFunction; */ class TwigHelper extends AbstractExtension { - private string $sAppRoot = ''; + /** @var string|mixed application root */ + private string $sAppRoot; /** * Constructor. @@ -19,7 +21,7 @@ class TwigHelper extends AbstractExtension */ public function __construct() { - $this->sAppRoot = \MetaModel::GetConfig()->Get('app_root_url'); + $this->sAppRoot = MetaModel::GetConfig()->Get('app_root_url'); } /** @inheritdoc */ @@ -37,7 +39,7 @@ class TwigHelper extends AbstractExtension * * @return string */ - public function asset_js($name) + public function asset_js($name) : string { return $this->sAppRoot . 'js/' . $name; } @@ -47,7 +49,7 @@ class TwigHelper extends AbstractExtension * * @return string */ - public function asset_css($name) + public function asset_css($name) : string { return $this->sAppRoot . 'css/' . $name; } @@ -57,7 +59,7 @@ class TwigHelper extends AbstractExtension * * @return string */ - public function asset_image($name) + public function asset_image($name) : string { return $this->sAppRoot . 'images/' . $name; } diff --git a/templates/DI/base.html.twig b/templates/DI/base.html.twig index 96ad0aeb2..905466214 100644 --- a/templates/DI/base.html.twig +++ b/templates/DI/base.html.twig @@ -1,138 +1,128 @@ <!DOCTYPE html> <html> -<head> - <title>{% block title %}{% endblock %}</title> - <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous"> - <link rel="shortcut icon" href="{{ asset_image('DI/flask-adaptive.svg') }}"> - <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script> - <script src=" https://releases.jquery.com/git/ui/jquery-ui-git.js"></script> - <script src="{{ asset_js('ckeditor/ckeditor.js') }}"></script> - <script src="{{ asset_js('DI/form.js') }}"></script> - <script src="{{ asset_js('DI/text_widget.js') }}"></script> - <link href='https://fonts.googleapis.com/css?family=Montserrat' rel='stylesheet'> - <script src="https://kit.fontawesome.com/f2d58012d0.js" crossorigin="anonymous"></script> - <style> - body{ - font-family: 'Montserrat'; - } - .combodo-row{ - display: flex; - } - .combodo-row fieldset{ - flex-grow: 1; - } - .combodo-column{ - padding: 10px; - } - .combodo-field-set{ - border: #b7b7b7 dashed 1px; - padding: 10px; - border-radius: 10px; - } - .combodo-field-set-label{ - font-weight: bold; - border-bottom: 2px solid #b7b7b7; - margin-bottom: 10px; - } - .loading{ - position: relative; - } - .loading:after{ - content: 'loading...'; - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - background-color: #0d6efd11; - display: flex; - align-items: center; - justify-content: center; - border-radius: 10px; - } - label.required:after{ - content: ' *'; - color: red; - } - form{ - background-color: #f8f8f8; - border-radius: 10px; - padding: 5px; - } - form.actions button,a{ - margin: 0 3px; - } - [data-block="container"]:has(.test:empty) { - display: none; - } - .z_list_list{ - display: flex; - } - </style> - {% block head %}{% endblock %} + <head> - <script> + {# page #} + <title>{% block title %}{% endblock %}</title> + <link rel="shortcut icon" href="{{ asset_image('DI/flask-adaptive.svg') }}"> + <meta name="viewport" content="width=device-width, initial-scale=1"> - const addFormToCollection = (e) => { + {# lib #} + <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script> + <script src=" https://releases.jquery.com/git/ui/jquery-ui-git.js"></script> + <script src="{{ asset_js('ckeditor/ckeditor.js') }}"></script> + <script src="https://kit.fontawesome.com/f2d58012d0.js" crossorigin="anonymous"></script> + <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-HwwvtgBNo3bZJJLYd8oVXjrBZt8cqVSpeBNS5n7C8IVInixGAoxmnlMuBnhbgrkm" crossorigin="anonymous"></script> + <link href='https://fonts.googleapis.com/css?family=Montserrat' rel='stylesheet'> + <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9" crossorigin="anonymous"> + <link href='https://fonts.googleapis.com/css?family=Montserrat' rel='stylesheet'> - const collectionHolder = document.querySelector('.' + e.currentTarget.dataset.collectionHolderClass); + {# css #} + <link href='{{ asset_css('DI/app.css') }}' rel='stylesheet'> - const item = document.createElement('tr'); + {# JS #} + <script src="{{ asset_js('DI/toolkit.js') }}"></script> + <script src="{{ asset_js('DI/app.js') }}"></script> + <script src="{{ asset_js('DI/collection.js') }}"></script> + <script src="{{ asset_js('DI/form.js') }}"></script> + <script src="{{ asset_js('DI/widget.js') }}"></script> - item.innerHTML = collectionHolder - .dataset - .prototype - .replace( - /__name__/g, - collectionHolder.dataset.index - ); + {# - BLOCK HEAD - #} + {% block head %}{% endblock %} - collectionHolder.appendChild(item); + </head> - collectionHolder.dataset.index++; - }; + <body data-bs-theme="light"> - </script> -</head> -<body> - <nav class="navbar navbar-expand-lg bg-body-tertiary"> - <div class="container-fluid"> - <a class="navbar-brand" href="#"><img src="{{ asset_image('DI/flask-solid.svg') }}" width="24px"> Router / DI / Forms</a> - <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> - <span class="navbar-toggler-icon"></span> - </button> - <div class="collapse navbar-collapse" id="navbarSupportedContent"> - <ul class="navbar-nav me-auto mb-2 mb-lg-0"> - <li class="nav-item"> - <a class="nav-link active" aria-current="page" href="{{ path('home') }}">Home</a> - </li> - <li class="nav-item"> - <a href="{{ path('object_view', {'class': 'Person', 'id': 1}) }}" class="nav-link">View Person</a> - </li> - <li class="nav-item"> - <a href="{{ path('object_json', {'class': 'Person', 'id': 1}) }}" class="nav-link" target="_blank">View Person (JSON)</a> - </li> - <li class="nav-item"> - <a href="{{ path('object_edit', {'class': 'Person', 'id': 1}) }}" class="nav-link">Edit Person</a> - </li> - <li class="nav-item"> - <a href="{{ path('object_edit', {'class': 'UserRequest', 'id': 1}) }}" class="nav-link">Edit UserRequest</a> - </li> - <li class="nav-item"> - <a href="{{ path('configuration_edit') }}" class="nav-link">Edit Configuration</a> - </li> - </ul> - <form class="actions d-flex"> - {% block actions %}{% endblock %} - </form> + <!-- nav --> + <nav class="navbar navbar-expand-lg fixed-top bg-body-tertiary"> + <div class="container-fluid"> + <a class="navbar-brand" href="#"><img class="app_icon" src="{{ asset_image('DI/flask-solid.svg') }}" width="24px"> Forms SDK</a> + <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> + <span class="navbar-toggler-icon"></span> + </button> + <div class="collapse navbar-collapse" id="navbarSupportedContent"> + <ul class="navbar-nav me-auto mb-2 mb-lg-0"> + <li class="nav-item"> + <a class="nav-link active" aria-current="page" href="{{ path('home') }}">Home</a> + </li> + <li class="nav-item dropdown"> + <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false"> + Edit Object + </a> + <ul class="dropdown-menu"> + <li><a class="dropdown-item" href="{{ path('object_edit', {'class': 'Organization', 'id': 1}) }}">Organization</a></li> + <li><a class="dropdown-item" href="{{ path('object_edit', {'class': 'Person', 'id': 1}) }}">Person</a></li> + <li><a class="dropdown-item" href="{{ path('object_edit', {'class': 'User', 'id': 1}) }}">User</a></li> + <li><a class="dropdown-item" href="{{ path('object_edit', {'class': 'UserRequest', 'id': 1}) }}">UserRequest</a></li> + </ul> + </li> + <li class="nav-item"> + <a href="{{ path('configuration_edit') }}" class="nav-link">Edit Configuration</a> + </li> + </ul> + <div> + <button id="dark_mode" type="button" class="btn" role="button" data-bs-toggle="button" aria-pressed="false"><i class="fa-solid fa-moon text-warning"></i></button> + </div> + <form class="actions d-flex"> + {% block actions %}{% endblock %} + </form> + </div> + </div> + </nav> + + <div class="m-3"> + + {# - BLOCK BODY - #} + {% block body %}{% endblock %} + + </div> + + <div class="toast-container position-fixed bottom-0 start-50 translate-middle-x p-3"> + + {# - BLOCK TOASTS - #} + {% block toasts %}{% endblock %} + + </div> + + <!-- Full screen modal --> + <div class="modal fade" id="object_modal" tabindex="-1" aria-labelledby="object_modal1" aria-hidden="true"> + <div class="modal-dialog modal-fullscreen"> + <div class="modal-content"> + <div class="modal-header"> + <h1 class="modal-title fs-4" id="exampleModalFullscreenLabel">Create object</h1> + <div> + <button type="button" class="btn btn-secondary" data-bs-dismiss="modal" aria-label="Close">Cancel</button> + <button type="button" class="btn btn-primary" data-bs-dismiss="modal" aria-label="Confirm">Confirm</button> + </div> + </div> + <div class="modal-body"> + </div> + </div> </div> </div> - </nav> - <div class="m-3"> - {% block body %}{% endblock %} - </div> - <div class="toast-container position-static"> - </div> -</body> + + + <script> + + // Toolkit + const oToolkit = new Toolkit(); + oToolkit.init(); + + // App initialization + const oApp = new App(); + oApp.init(); + + $(document).ready(function(e) { + + {# - BLOCK READY SCRIPTS - #} + {% block ready_scripts %}{% endblock %} + + }); + + </script> + + </body> + </html> diff --git a/templates/DI/object/object_single_attribute.html.twig b/templates/DI/form.html.twig similarity index 100% rename from templates/DI/object/object_single_attribute.html.twig rename to templates/DI/form.html.twig diff --git a/templates/DI/form/classic_theme.html.twig b/templates/DI/form/classic_theme.html.twig new file mode 100644 index 000000000..264217950 --- /dev/null +++ b/templates/DI/form/classic_theme.html.twig @@ -0,0 +1,165 @@ +{% use "bootstrap_5_layout.html.twig" %} + +{# LAYOUT #} + +{# column #} +{%- block column_widget -%} + + {{ form_widget(form, {'attr': {'class': 'combodo-column'}}) }} + {{ form_help(form) }} + {{ form_errors(form) }} + +{%- endblock column_widget -%} + +{# row #} +{%- block row_widget -%} + + {{ form_widget(form, {'attr': {'class': 'combodo-row'}}) }} + {{ form_help(form) }} + {{ form_errors(form) }} + +{%- endblock row_widget -%} + +{# fieldset #} +{%- block field_set_widget -%} + + {{ form_widget(form, {'attr': {'class': 'combodo-field-set'}}) }} + {{ form_help(form) }} + {{ form_errors(form) }} + +{%- endblock field_set_widget -%} + +{# ATTRIBUTE #} + +{# DocumentType #} +{%- block document_widget -%} + + <div class="d-flex align-items-center"> + <img src="{{ data }}" alt="" class="m-2"> + <div> + <div><span>Type:</span><span>{{ mime_type }}</span></div> + <div><span>Finename:</span><span>{{ filename }}</span></div> + </div> + </div> + + {{ form_widget(form, {'attr': {'class': 'combodo-document'}}) }} + {{ form_help(form) }} + {{ form_errors(form) }} + +{%- endblock document_widget -%} + +{# ExternalKeyType #} +{%- block external_key_widget -%} + + <div class="d-flex"> + + <div class="flex-grow-1"> + {{ form_widget(form) }} + </div> + + {% if allow_target_creation %} + <button type="button" class="btn btn-secondary ms-1"><i class="fa-solid fa-plus"></i></button> + {% endif %} + </div> + +{%- endblock external_key_widget -%} + +{# LinkSetType #} +{%- block link_set_widget -%} + + {% if is_indirect %} + <span class="badge bg-warning">Indirect</span> + {% endif %} + + {% if is_abstract %} + <span class="badge bg-danger">abstract</span> + {% endif %} + + {# container #} + <div class="link_set_widget_container"> + + {# table #} + <table class="table link_set_widget" > + + {# header #} + <thead> + <tr> + {% for l in labels %} + <th>{{ l }}</th> + {% endfor %} + <th></th> + </tr> + </thead> + + {# body #} + <tbody class="{{ form.vars.id }}" + data-index="{{ form.vars.value|length > 0 ? form.vars.value|length : 0 }}" + data-prototype="{{ form_widget(form.vars.prototype)|e('html_attr') }}"> + + {# no data row #} + <tr class="no_data" {% if form|length != 0 %} style="display: none"{% endif %}><td colspan="{{ labels|length+1 }}">Aucune donnée</td></tr> + + {# links #} + {% for child in form %} + {{ form_widget(child) }} + {% endfor %} + + </tbody> + + </table> + + {% set buttonDataAttributes = 'data-object-class="' ~ object_class ~ '" data-ext-key-to-me="' ~ ext_key_to_me ~ '"' %} + + {% if is_abstract %} + {# create item button #} + <div class="d-inline-block"> + <div class="dropdown"> + <button class="btn btn-secondary btn-sm dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false"> + Create + </button> + <ul class="dropdown-menu dropdown_scroll_300"> + {% for object_class in object_classes %} + <li><a class="dropdown-item create_item_link" href="#" {{ buttonDataAttributes|raw }}>{{ object_class }}</a></li> + {% endfor %} + </ul> + </div> + </div> + {% elseif is_indirect %} + {# add item button #} + <button type="button" class="add_item_link btn btn-secondary btn-sm" data-collection-holder-class="{{ form.vars.id }}">Add {{ target_class }}</button> + {% else %} + {# create item button #} + <button type="button" class="btn btn-secondary create_item_link btn-sm" {{ buttonDataAttributes|raw }}>Create {{ target_class }}</button> + {% endif %} + + </div> + + {{ form_help(form) }} + {{ form_errors(form) }} + +{%- endblock link_set_widget -%} + +{# COMPOUND #} + +{# Object #} +{%- block object_widget -%} + + {% if z_list == 'list' %} + <tr data-block="container"> + {% for child in form %} + <td data-block="container"> + {{ form_widget(child) }} + </td> + {% endfor %} + <td style="text-align: right;width: 40px;"> + <a class="btn btn-danger btn-remove-link"><i class="fa-solid fa-trash"></i></a> + </td> + </tr> + {% else %} + + {{ form_widget(form) }} + + {% endif %} + +{%- endblock object_widget -%} + diff --git a/templates/DI/form/external_key_widget.html.twig b/templates/DI/form/external_key_widget.html.twig deleted file mode 100644 index 94f04b86c..000000000 --- a/templates/DI/form/external_key_widget.html.twig +++ /dev/null @@ -1,16 +0,0 @@ -{% use "bootstrap_5_layout.html.twig" %} - -{%- block external_key_widget -%} - - <div class="d-flex"> - - <div class="flex-grow-1"> - {{ form_widget(form) }} - </div> - - {% if allow_target_creation %} - <button class="btn btn-secondary ms-2">+</button> - {% endif %} - </div> - -{%- endblock external_key_widget -%} \ No newline at end of file diff --git a/templates/DI/form/form_layout.html.twig b/templates/DI/form/form_layout.html.twig deleted file mode 100644 index 800958988..000000000 --- a/templates/DI/form/form_layout.html.twig +++ /dev/null @@ -1,134 +0,0 @@ -{# column #} -{%- block column_widget -%} - - {{ form_widget(form, {'attr': {'class': 'combodo-column'}}) }} - {{ form_help(form) }} - {{ form_errors(form) }} - -{%- endblock column_widget -%} - -{# row #} -{%- block row_widget -%} - - {{ form_widget(form, {'attr': {'class': 'combodo-row'}}) }} - {{ form_help(form) }} - {{ form_errors(form) }} - -{%- endblock row_widget -%} - -{# fieldset #} -{%- block field_set_widget -%} - - {{ form_widget(form, {'attr': {'class': 'combodo-field-set'}}) }} - {{ form_help(form) }} - {{ form_errors(form) }} - -{%- endblock field_set_widget -%} - -{# DocumentType #} -{%- block document_widget -%} - - <div class="d-flex align-items-center"> - <img src="{{ data }}" alt="" class="m-2"> - <div> - <div><span>Type:</span><span>{{ mime_type }}</span></div> - <div><span>Finename:</span><span>{{ filename }}</span></div> - </div> - </div> - - {{ form_widget(form, {'attr': {'class': 'combodo-document'}}) }} - {{ form_help(form) }} - {{ form_errors(form) }} - -{%- endblock document_widget -%} - - -{# fieldset #} -{%- block link_set_widget -%} - - <script> - - - $(document).ready(function(){ - document - .querySelectorAll('.add_item_link') - .forEach(btn => { - btn.addEventListener("click", addFormToCollection) - }); - - document - .querySelectorAll('.btn-remove-link') - .forEach(btn => { - btn.addEventListener("click", (e) => { - btn.closest('tr').remove() - }) - }); - - }); - - - - </script> - - - - <table class="table link_set_widget" > - <thead> - <tr> - {% for l in labels %} - <th>{{ l }}</th> - {% endfor %} - <th></th> - </tr> - </thead> - <tbody class="{{ form.vars.id }}" - data-index="{{ form.vars.value|length > 0 ? form.vars.value|length : 0 }}" - data-prototype="{{ form_widget(form.vars.prototype)|e('html_attr') }}"> - {% for child in form %} - <tr> - {% for child2 in child %} - <td> - {{ form_widget(child2) }} - </td> - {% endfor %} - <td style="text-align: right;"> - <a class="btn btn-danger btn-remove-link"><i class="fa-solid fa-trash"></i></a> - </td> - </tr> - {% else %} - <tr><td colspan="{{ labels|length+1 }}">Aucune donnée</td></tr> - {% endfor %} - </tbody> - </table> - - <button type="button" class="add_item_link btn btn-primary" data-collection-holder-class="{{ form.vars.id }}">Add</button> - - {{ form_help(form) }} - {{ form_errors(form) }} - -{%- endblock link_set_widget -%} - - - -{# Object #} -{%- block object_widget -%} - - {% if z_list == 'list' %} - <tr> - <input type="hidden" name="classe_a_instancier" id="classe_a_instancier"> - {% for child in form %} - <td> - {{ form_widget(child) }} - </td> - {% endfor %} - <td style="text-align: right;"> - <a class="btn btn-danger btn-remove-link"><i class="fa-solid fa-trash"></i></a> - </td> - </tr> - {% else %} - - {{ form_widget(form) }} - - {% endif %} - -{%- endblock object_widget -%} \ No newline at end of file diff --git a/templates/DI/home.html.twig b/templates/DI/home.html.twig index d4af01ca5..fd15ed8f0 100644 --- a/templates/DI/home.html.twig +++ b/templates/DI/home.html.twig @@ -1,7 +1,7 @@ {% extends "DI/base.html.twig" %} {% block title %} - Router / DI / Forms + Forms SDK {% endblock %} {% block body %} diff --git a/templates/DI/object/edit.html.twig b/templates/DI/object/edit.html.twig index 5e35d495e..842d799ae 100644 --- a/templates/DI/object/edit.html.twig +++ b/templates/DI/object/edit.html.twig @@ -4,35 +4,57 @@ Object Edition {% endblock %} +{% block head %} + + <script src="{{ asset_js('DI/widget/text_widget.js') }}"></script> + +{% endblock %} + {% block actions %} - <a href="{{ path('object_edit', {'class': class, 'id': id - 1}) }}" class="btn btn-light btn {% if id <= 1 %} disabled {% endif %}"><i class="fa-solid fa-arrow-left"></i></a> - <a href="{{ path('object_edit', {'class': class, 'id': id + 1}) }}" class="btn btn-light btn"><i class="fa-solid fa-arrow-right"></i></a> - <button type="submit" class="btn-primary btn" form="object_form">Save Object</button> + <a href="{{ path('object_edit', {'class': class, 'id': id - 1}) }}" class="btn btn-secondary btn {% if id <= 1 %} disabled {% endif %}"><i class="fa-solid fa-arrow-left"></i></a> + <a href="{{ path('object_edit', {'class': class, 'id': id + 1}) }}" class="btn btn-secondary btn"><i class="fa-solid fa-arrow-right"></i></a> + <button type="reset" class="btn-secondary btn" form="object_form">Reset</button> + <button type="submit" class="btn-primary btn" form="object_form">Save</button> +{% endblock %} + +{% block toasts %} + + {# database information toast #} + <div id="toast" role="alert" aria-live="assertive" aria-atomic="true" class="toast text-bg-primary" data-bs-autohide="true"> + <div class="toast-body"> + <h6><i class="fa-solid fa-database"></i> Database information</h6> + <div><b>Host:</b> {{ db_host }} <b>Database name:</b> {{ db_name }}</div> + </div> + </div> + {% endblock %} {% block body %} + {# inject form #} <div> - - {# database informations #} - <div class="alert alert-primary" role="alert"> - <b><i class="fa-solid fa-database"></i> Database information</b> - <div><u>Host:</u> {{ db_host }} <u>Database name:</u> {{ db_name }}</div> - </div> - - {# inject form #} - <div> - {{ form(form, {'attr': {'id' : 'object_form'}}) }} - </div> - + {{ form(form, {'attr': {'id' : 'object_form'}}) }} </div> - <script> +{% endblock %} - {# form handler #} - di = new DIForm('{{ reload_url }}'); - di.handleElement(document); +{% block ready_scripts %} - </script> + {# Widget #} + const oWidget = new Widget(); + oWidget.handleElement(document); + + {# Form #} + const oForm = new Form(oWidget); + oForm.handleElement(document); + + {# Collection #} + const oCollection = new Collection(oForm, '{{ path('object_form', {'class': 'object_class', 'id' : 0, 'name': 'form_name'}) }}'); + oCollection.handleElement(document); + + {# toast database information #} + const toastLiveExample = document.getElementById('toast') + const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastLiveExample) + toastBootstrap.show(); {% endblock %} \ No newline at end of file